diff --git a/.gitignore b/.gitignore index cff36cbde1..b52de3762d 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,7 @@ tower-backup-* env/* nohup.out reports + +# AWX python libs populated by requirements.txt +awx/lib/site-packages + diff --git a/Makefile b/Makefile index 73115fc033..862a83773f 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ RPM_NVR = $(NAME)-$(VERSION)-$(RELEASE)$(RPM_DIST) MOCK_BIN ?= mock MOCK_CFG ?= -.PHONY: clean rebase push requirements requirements_pypi requirements_jenkins \ +.PHONY: clean rebase push requirements requirements_dev requirements_jenkins requirements_post \ develop refresh adduser syncdb migrate dbchange dbshell runserver celeryd \ receiver test test_coverage coverage_html ui_analysis_report test_jenkins dev_build \ release_build release_clean sdist rpmtar mock-rpm mock-srpm rpm-sign \ @@ -137,51 +137,35 @@ rebase: push: git push origin master -# Install third-party requirements needed for development environment (using -# locally downloaded packages). -requirements: - @if [ "$(VIRTUAL_ENV)" ]; then \ - (cd requirements && pip install --no-index setuptools-12.0.5.tar.gz); \ - (cd requirements && pip install --no-index Django-1.6.7.tar.gz); \ - (cd requirements && pip install --no-index -r dev_local.txt); \ - $(PYTHON) fix_virtualenv_setuptools.py; \ - else \ - (cd requirements && sudo pip install --no-index -r dev_local.txt); \ - fi +requirements_post: + touch awx/lib/site-packages/oslo/__init__.py + touch awx/lib/site-packages/dogpile/__init__.py -# Install third-party requirements needed for development environment -# (downloading from PyPI if necessary). -requirements_pypi: +# Install third-party requirements needed for development environment. +requirements: + (pip install -r requirements/requirements.txt -t awx/lib/site-packages/); @if [ "$(VIRTUAL_ENV)" ]; then \ - pip install setuptools==12.0.5; \ - pip install Django\>=1.6.7,\<1.7; \ - pip install -r requirements/dev.txt; \ - $(PYTHON) fix_virtualenv_setuptools.py; \ - else \ - sudo pip install -r requirements/dev.txt; \ + $(PYTHON) fix_virtualenv_setuptools.py; \ fi + $(MAKE) requirements_post + +requirements_dev: + (cat requirements/requirements.txt requirements/requirements_dev.txt > /tmp/req_dev.txt); + (pip install -r /tmp/req_dev.txt -t awx/lib/site-packages/); + @if [ "$(VIRTUAL_ENV)" ]; then \ + $(PYTHON) fix_virtualenv_setuptools.py; \ + fi + $(MAKE) requirements_post # Install third-party requirements needed for running unittests in jenkins -# (using locally downloaded packages). -requirements_jenkins: +requirements_jenkins: requirements + (pip install -r requirements/requirements_jenkins.txt); @if [ "$(VIRTUAL_ENV)" ]; then \ - (cd requirements && pip install --no-index distribute-0.7.3.zip || true); \ - (cd requirements && pip install --no-index pip-1.5.4.tar.gz || true); \ - else \ - (cd requirements && sudo pip install --no-index distribute-0.7.3.zip || true); \ - (cd requirements && sudo pip install --no-index pip-1.5.4.tar.gz || true); \ - fi - $(MAKE) requirements - @if [ "$(VIRTUAL_ENV)" ]; then \ - (cd requirements && pip install -r jenkins.txt); \ - $(PYTHON) fix_virtualenv_setuptools.py; \ - else \ - (cd requirements && sudo pip install -r jenkins.txt); \ + $(PYTHON) fix_virtualenv_setuptools.py; \ fi npm install csslint jshint -# "Install" ansible-tower package in development mode. Creates link to working -# copy in site-packages and installs awx-manage command. +# "Install" ansible-tower package in development mode. develop: @if [ "$(VIRTUAL_ENV)" ]; then \ pip uninstall -y awx; \ @@ -191,6 +175,10 @@ develop: sudo $(PYTHON) setup.py develop; \ fi +version_file: + mkdir -p /var/lib/awx/ + python -c "import awx as awx; print awx.__version__" > /var/lib/awx/.tower_version + # Do any one-time init tasks. init: @if [ "$(VIRTUAL_ENV)" ]; then \ @@ -200,7 +188,7 @@ init: fi # Refresh development environment after pulling new code. -refresh: clean requirements develop migrate +refresh: clean requirements_dev version_file develop migrate # Create Django superuser. adduser: @@ -407,7 +395,7 @@ release_clean: dist/$(SDIST_TAR_FILE): BUILD="$(BUILD)" $(PYTHON) setup.py sdist -sdist: minjs dist/$(SDIST_TAR_FILE) +sdist: minjs requirements dist/$(SDIST_TAR_FILE) rpm-build: mkdir -p rpm-build diff --git a/awx/lib/site-packages/IPy.py b/awx/lib/site-packages/IPy.py deleted file mode 100644 index e05dbae47b..0000000000 --- a/awx/lib/site-packages/IPy.py +++ /dev/null @@ -1,1652 +0,0 @@ -""" -IPy - class and tools for handling of IPv4 and IPv6 addresses and networks. -See README file for learn how to use IPy. - -Further Information might be available at: -https://github.com/haypo/python-ipy -""" - -__version__ = '0.83' - -import bisect -import collections -import sys -import types - -# Definition of the Ranges for IPv4 IPs -# this should include www.iana.org/assignments/ipv4-address-space -# and www.iana.org/assignments/multicast-addresses -IPv4ranges = { - '0': 'PUBLIC', # fall back - '00000000': 'PRIVATE', # 0/8 - '00001010': 'PRIVATE', # 10/8 - '0110010001': 'CARRIER_GRADE_NAT', #100.64/10 - '01111111': 'LOOPBACK', # 127.0/8 - '1': 'PUBLIC', # fall back - '1010100111111110': 'PRIVATE', # 169.254/16 - '101011000001': 'PRIVATE', # 172.16/12 - '1100000010101000': 'PRIVATE', # 192.168/16 - '111': 'RESERVED', # 224/3 - } - -# Definition of the Ranges for IPv6 IPs -# http://www.iana.org/assignments/ipv6-address-space/ -# http://www.iana.org/assignments/ipv6-unicast-address-assignments/ -# http://www.iana.org/assignments/ipv6-multicast-addresses/ -IPv6ranges = { - '00000000' : 'RESERVED', # ::/8 - '0' * 96 : 'RESERVED', # ::/96 Formerly IPV4COMP [RFC4291] - '0' * 128 : 'UNSPECIFIED', # ::/128 - '0' * 127 + '1' : 'LOOPBACK', # ::1/128 - '0' * 80 + '1' * 16 : 'IPV4MAP', # ::ffff:0:0/96 - '00000000011001001111111110011011' + '0' * 64 : 'WKP46TRANS', # 0064:ff9b::/96 Well-Known-Prefix [RFC6052] - '00000001' : 'UNASSIGNED', # 0100::/8 - '0000001' : 'RESERVED', # 0200::/7 Formerly NSAP [RFC4048] - '0000010' : 'RESERVED', # 0400::/7 Formerly IPX [RFC3513] - '0000011' : 'RESERVED', # 0600::/7 - '00001' : 'RESERVED', # 0800::/5 - '0001' : 'RESERVED', # 1000::/4 - '001' : 'GLOBAL-UNICAST', # 2000::/3 [RFC4291] - '00100000000000010000000' : 'SPECIALPURPOSE', # 2001::/23 [RFC4773] - '00100000000000010000000000000000' : 'TEREDO', # 2001::/32 [RFC4380] - '00100000000000010000000000000010' + '0' * 16 : 'BMWG', # 2001:0002::/48 Benchmarking [RFC5180] - '0010000000000001000000000001' : 'ORCHID', # 2001:0010::/28 (Temp until 2014-03-21) [RFC4843] - '00100000000000010000001' : 'ALLOCATED APNIC', # 2001:0200::/23 - '00100000000000010000010' : 'ALLOCATED ARIN', # 2001:0400::/23 - '00100000000000010000011' : 'ALLOCATED RIPE NCC', # 2001:0600::/23 - '00100000000000010000100' : 'ALLOCATED RIPE NCC', # 2001:0800::/23 - '00100000000000010000101' : 'ALLOCATED RIPE NCC', # 2001:0a00::/23 - '00100000000000010000110' : 'ALLOCATED APNIC', # 2001:0c00::/23 - '00100000000000010000110110111000' : 'DOCUMENTATION', # 2001:0db8::/32 [RFC3849] - '00100000000000010000111' : 'ALLOCATED APNIC', # 2001:0e00::/23 - '00100000000000010001001' : 'ALLOCATED LACNIC', # 2001:1200::/23 - '00100000000000010001010' : 'ALLOCATED RIPE NCC', # 2001:1400::/23 - '00100000000000010001011' : 'ALLOCATED RIPE NCC', # 2001:1600::/23 - '00100000000000010001100' : 'ALLOCATED ARIN', # 2001:1800::/23 - '00100000000000010001101' : 'ALLOCATED RIPE NCC', # 2001:1a00::/23 - '0010000000000001000111' : 'ALLOCATED RIPE NCC', # 2001:1c00::/22 - '00100000000000010010' : 'ALLOCATED RIPE NCC', # 2001:2000::/20 - '001000000000000100110' : 'ALLOCATED RIPE NCC', # 2001:3000::/21 - '0010000000000001001110' : 'ALLOCATED RIPE NCC', # 2001:3800::/22 - '0010000000000001001111' : 'RESERVED', # 2001:3c00::/22 Possible future allocation to RIPE NCC - '00100000000000010100000' : 'ALLOCATED RIPE NCC', # 2001:4000::/23 - '00100000000000010100001' : 'ALLOCATED AFRINIC', # 2001:4200::/23 - '00100000000000010100010' : 'ALLOCATED APNIC', # 2001:4400::/23 - '00100000000000010100011' : 'ALLOCATED RIPE NCC', # 2001:4600::/23 - '00100000000000010100100' : 'ALLOCATED ARIN', # 2001:4800::/23 - '00100000000000010100101' : 'ALLOCATED RIPE NCC', # 2001:4a00::/23 - '00100000000000010100110' : 'ALLOCATED RIPE NCC', # 2001:4c00::/23 - '00100000000000010101' : 'ALLOCATED RIPE NCC', # 2001:5000::/20 - '0010000000000001100' : 'ALLOCATED APNIC', # 2001:8000::/19 - '00100000000000011010' : 'ALLOCATED APNIC', # 2001:a000::/20 - '00100000000000011011' : 'ALLOCATED APNIC', # 2001:b000::/20 - '0010000000000010' : '6TO4', # 2002::/16 "6to4" [RFC3056] - '001000000000001100' : 'ALLOCATED RIPE NCC', # 2003::/18 - '001001000000' : 'ALLOCATED APNIC', # 2400::/12 - '001001100000' : 'ALLOCATED ARIN', # 2600::/12 - '00100110000100000000000' : 'ALLOCATED ARIN', # 2610::/23 - '00100110001000000000000' : 'ALLOCATED ARIN', # 2620::/23 - '001010000000' : 'ALLOCATED LACNIC', # 2800::/12 - '001010100000' : 'ALLOCATED RIPE NCC', # 2a00::/12 - '001011000000' : 'ALLOCATED AFRINIC', # 2c00::/12 - '00101101' : 'RESERVED', # 2d00::/8 - '0010111' : 'RESERVED', # 2e00::/7 - '0011' : 'RESERVED', # 3000::/4 - '010' : 'RESERVED', # 4000::/3 - '011' : 'RESERVED', # 6000::/3 - '100' : 'RESERVED', # 8000::/3 - '101' : 'RESERVED', # a000::/3 - '110' : 'RESERVED', # c000::/3 - '1110' : 'RESERVED', # e000::/4 - '11110' : 'RESERVED', # f000::/5 - '111110' : 'RESERVED', # f800::/6 - '1111110' : 'ULA', # fc00::/7 [RFC4193] - '111111100' : 'RESERVED', # fe00::/9 - '1111111010' : 'LINKLOCAL', # fe80::/10 - '1111111011' : 'RESERVED', # fec0::/10 Formerly SITELOCAL [RFC4291] - '11111111' : 'MULTICAST', # ff00::/8 - '1111111100000001' : 'NODE-LOCAL MULTICAST', # ff01::/16 - '1111111100000010' : 'LINK-LOCAL MULTICAST', # ff02::/16 - '1111111100000100' : 'ADMIN-LOCAL MULTICAST', # ff04::/16 - '1111111100000101' : 'SITE-LOCAL MULTICAST', # ff05::/16 - '1111111100001000' : 'ORG-LOCAL MULTICAST', # ff08::/16 - '1111111100001110' : 'GLOBAL MULTICAST', # ff0e::/16 - '1111111100001111' : 'RESERVED MULTICAST', # ff0f::/16 - '111111110011' : 'PREFIX-BASED MULTICAST', # ff30::/12 [RFC3306] - '111111110111' : 'RP-EMBEDDED MULTICAST', # ff70::/12 [RFC3956] - } - -MAX_IPV4_ADDRESS = 0xffffffff -MAX_IPV6_ADDRESS = 0xffffffffffffffffffffffffffffffff -IPV6_TEST_MAP = 0xffffffffffffffffffffffff00000000 -IPV6_MAP_MASK = 0x00000000000000000000ffff00000000 - -if sys.version_info >= (3,): - INT_TYPES = (int,) - STR_TYPES = (str,) - xrange = range -else: - INT_TYPES = (int, long) - STR_TYPES = (str, unicode) - - -class IPint(object): - """Handling of IP addresses returning integers. - - Use class IP instead because some features are not implemented for - IPint.""" - - def __init__(self, data, ipversion=0, make_net=0): - """Create an instance of an IP object. - - Data can be a network specification or a single IP. IP - addresses can be specified in all forms understood by - parseAddress(). The size of a network can be specified as - - /prefixlen a.b.c.0/24 2001:658:22a:cafe::/64 - -lastIP a.b.c.0-a.b.c.255 2001:658:22a:cafe::-2001:658:22a:cafe:ffff:ffff:ffff:ffff - /decimal netmask a.b.c.d/255.255.255.0 not supported for IPv6 - - If no size specification is given a size of 1 address (/32 for - IPv4 and /128 for IPv6) is assumed. - - If make_net is True, an IP address will be transformed into the network - address by applying the specified netmask. - - >>> print(IP('127.0.0.0/8')) - 127.0.0.0/8 - >>> print(IP('127.0.0.0/255.0.0.0')) - 127.0.0.0/8 - >>> print(IP('127.0.0.0-127.255.255.255')) - 127.0.0.0/8 - >>> print(IP('127.0.0.1/255.0.0.0', make_net=True)) - 127.0.0.0/8 - - See module documentation for more examples. - """ - - # Print no Prefixlen for /32 and /128 - self.NoPrefixForSingleIp = 1 - - # Do we want prefix printed by default? see _printPrefix() - self.WantPrefixLen = None - - netbits = 0 - prefixlen = -1 - - # handling of non string values in constructor - if isinstance(data, INT_TYPES): - self.ip = int(data) - if ipversion == 0: - if self.ip <= MAX_IPV4_ADDRESS: - ipversion = 4 - else: - ipversion = 6 - if ipversion == 4: - if self.ip > MAX_IPV4_ADDRESS: - raise ValueError("IPv4 Address can't be larger than %x: %x" % (MAX_IPV4_ADDRESS, self.ip)) - prefixlen = 32 - elif ipversion == 6: - if self.ip > MAX_IPV6_ADDRESS: - raise ValueError("IPv6 Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, self.ip)) - prefixlen = 128 - else: - raise ValueError("only IPv4 and IPv6 supported") - self._ipversion = ipversion - self._prefixlen = prefixlen - # handle IP instance as an parameter - elif isinstance(data, IPint): - self._ipversion = data._ipversion - self._prefixlen = data._prefixlen - self.ip = data.ip - elif isinstance(data, STR_TYPES): - # TODO: refactor me! - # splitting of a string into IP and prefixlen et. al. - x = data.split('-') - if len(x) == 2: - # a.b.c.0-a.b.c.255 specification ? - (ip, last) = x - (self.ip, parsedVersion) = parseAddress(ip) - if parsedVersion != 4: - raise ValueError("first-last notation only allowed for IPv4") - (last, lastversion) = parseAddress(last) - if lastversion != 4: - raise ValueError("last address should be IPv4, too") - if last < self.ip: - raise ValueError("last address should be larger than first") - size = last - self.ip - netbits = _count1Bits(size) - # make sure the broadcast is the same as the last ip - # otherwise it will return /16 for something like: - # 192.168.0.0-192.168.191.255 - if IP('%s/%s' % (ip, 32-netbits)).broadcast().int() != last: - raise ValueError("the range %s is not on a network boundary." % data) - elif len(x) == 1: - x = data.split('/') - # if no prefix is given use defaults - if len(x) == 1: - ip = x[0] - prefixlen = -1 - elif len(x) > 2: - raise ValueError("only one '/' allowed in IP Address") - else: - (ip, prefixlen) = x - if prefixlen.find('.') != -1: - # check if the user might have used a netmask like - # a.b.c.d/255.255.255.0 - (netmask, vers) = parseAddress(prefixlen) - if vers != 4: - raise ValueError("netmask must be IPv4") - prefixlen = _netmaskToPrefixlen(netmask) - elif len(x) > 2: - raise ValueError("only one '-' allowed in IP Address") - else: - raise ValueError("can't parse") - - (self.ip, parsedVersion) = parseAddress(ip) - if ipversion == 0: - ipversion = parsedVersion - if prefixlen == -1: - bits = _ipVersionToLen(ipversion) - prefixlen = bits - netbits - self._ipversion = ipversion - self._prefixlen = int(prefixlen) - - if make_net: - self.ip = self.ip & _prefixlenToNetmask(self._prefixlen, self._ipversion) - - if not _checkNetaddrWorksWithPrefixlen(self.ip, - self._prefixlen, self._ipversion): - raise ValueError("%s has invalid prefix length (%s)" % (repr(self), self._prefixlen)) - else: - raise TypeError("Unsupported data type: %s" % type(data)) - - def int(self): - """Return the first / base / network addess as an (long) integer. - - The same as IP[0]. - - >>> "%X" % IP('10.0.0.0/8').int() - 'A000000' - """ - return self.ip - - def version(self): - """Return the IP version of this Object. - - >>> IP('10.0.0.0/8').version() - 4 - >>> IP('::1').version() - 6 - """ - return self._ipversion - - def prefixlen(self): - """Returns Network Prefixlen. - - >>> IP('10.0.0.0/8').prefixlen() - 8 - """ - return self._prefixlen - - def net(self): - """ - Return the base (first) address of a network as an (long) integer. - """ - return self.int() - - def broadcast(self): - """ - Return the broadcast (last) address of a network as an (long) integer. - - The same as IP[-1].""" - return self.int() + self.len() - 1 - - def _printPrefix(self, want): - """Prints Prefixlen/Netmask. - - Not really. In fact it is our universal Netmask/Prefixlen printer. - This is considered an internal function. - - want == 0 / None don't return anything 1.2.3.0 - want == 1 /prefix 1.2.3.0/24 - want == 2 /netmask 1.2.3.0/255.255.255.0 - want == 3 -lastip 1.2.3.0-1.2.3.255 - """ - - if (self._ipversion == 4 and self._prefixlen == 32) or \ - (self._ipversion == 6 and self._prefixlen == 128): - if self.NoPrefixForSingleIp: - want = 0 - if want == None: - want = self.WantPrefixLen - if want == None: - want = 1 - if want: - if want == 2: - # this should work with IP and IPint - netmask = self.netmask() - if not isinstance(netmask, INT_TYPES): - netmask = netmask.int() - return "/%s" % (intToIp(netmask, self._ipversion)) - elif want == 3: - return "-%s" % (intToIp(self.ip + self.len() - 1, self._ipversion)) - else: - # default - return "/%d" % (self._prefixlen) - else: - return '' - - # We have different flavours to convert to: - # strFullsize 127.0.0.1 2001:0658:022a:cafe:0200:c0ff:fe8d:08fa - # strNormal 127.0.0.1 2001:658:22a:cafe:200:c0ff:fe8d:08fa - # strCompressed 127.0.0.1 2001:658:22a:cafe::1 - # strHex 0x7F000001 0x20010658022ACAFE0200C0FFFE8D08FA - # strDec 2130706433 42540616829182469433547974687817795834 - - def strBin(self, wantprefixlen = None): - """Return a string representation as a binary value. - - >>> print(IP('127.0.0.1').strBin()) - 01111111000000000000000000000001 - >>> print(IP('2001:0658:022a:cafe:0200::1').strBin()) - 00100000000000010000011001011000000000100010101011001010111111100000001000000000000000000000000000000000000000000000000000000001 - """ - - bits = _ipVersionToLen(self._ipversion) - if self.WantPrefixLen == None and wantprefixlen == None: - wantprefixlen = 0 - ret = _intToBin(self.ip) - return '0' * (bits - len(ret)) + ret + self._printPrefix(wantprefixlen) - - def strCompressed(self, wantprefixlen = None): - """Return a string representation in compressed format using '::' Notation. - - >>> IP('127.0.0.1').strCompressed() - '127.0.0.1' - >>> IP('2001:0658:022a:cafe:0200::1').strCompressed() - '2001:658:22a:cafe:200::1' - >>> IP('ffff:ffff:ffff:ffff:ffff:f:f:fffc/127').strCompressed() - 'ffff:ffff:ffff:ffff:ffff:f:f:fffc/127' - """ - - if self.WantPrefixLen == None and wantprefixlen == None: - wantprefixlen = 1 - - if self._ipversion == 4: - return self.strFullsize(wantprefixlen) - else: - if self.ip >> 32 == 0xffff: - ipv4 = intToIp(self.ip & MAX_IPV4_ADDRESS, 4) - text = "::ffff:" + ipv4 + self._printPrefix(wantprefixlen) - return text - # find the longest sequence of '0' - hextets = [int(x, 16) for x in self.strFullsize(0).split(':')] - # every element of followingzeros will contain the number of zeros - # following the corresponding element of hextets - followingzeros = [0] * 8 - for i in xrange(len(hextets)): - followingzeros[i] = _countFollowingZeros(hextets[i:]) - # compressionpos is the position where we can start removing zeros - compressionpos = followingzeros.index(max(followingzeros)) - if max(followingzeros) > 1: - # genererate string with the longest number of zeros cut out - # now we need hextets as strings - hextets = [x for x in self.strNormal(0).split(':')] - while compressionpos < len(hextets) and hextets[compressionpos] == '0': - del(hextets[compressionpos]) - hextets.insert(compressionpos, '') - if compressionpos + 1 >= len(hextets): - hextets.append('') - if compressionpos == 0: - hextets = [''] + hextets - return ':'.join(hextets) + self._printPrefix(wantprefixlen) - else: - return self.strNormal(0) + self._printPrefix(wantprefixlen) - - def strNormal(self, wantprefixlen = None): - """Return a string representation in the usual format. - - >>> print(IP('127.0.0.1').strNormal()) - 127.0.0.1 - >>> print(IP('2001:0658:022a:cafe:0200::1').strNormal()) - 2001:658:22a:cafe:200:0:0:1 - """ - - if self.WantPrefixLen == None and wantprefixlen == None: - wantprefixlen = 1 - - if self._ipversion == 4: - ret = self.strFullsize(0) - elif self._ipversion == 6: - ret = ':'.join(["%x" % x for x in [int(x, 16) for x in self.strFullsize(0).split(':')]]) - else: - raise ValueError("only IPv4 and IPv6 supported") - - - - return ret + self._printPrefix(wantprefixlen) - - def strFullsize(self, wantprefixlen = None): - """Return a string representation in the non-mangled format. - - >>> print(IP('127.0.0.1').strFullsize()) - 127.0.0.1 - >>> print(IP('2001:0658:022a:cafe:0200::1').strFullsize()) - 2001:0658:022a:cafe:0200:0000:0000:0001 - """ - - if self.WantPrefixLen == None and wantprefixlen == None: - wantprefixlen = 1 - - return intToIp(self.ip, self._ipversion) + self._printPrefix(wantprefixlen) - - def strHex(self, wantprefixlen = None): - """Return a string representation in hex format in lower case. - - >>> print(IP('127.0.0.1').strHex()) - 0x7f000001 - >>> print(IP('2001:0658:022a:cafe:0200::1').strHex()) - 0x20010658022acafe0200000000000001 - """ - - if self.WantPrefixLen == None and wantprefixlen == None: - wantprefixlen = 0 - - x = '0x%x' % self.ip - return x + self._printPrefix(wantprefixlen) - - def strDec(self, wantprefixlen = None): - """Return a string representation in decimal format. - - >>> print(IP('127.0.0.1').strDec()) - 2130706433 - >>> print(IP('2001:0658:022a:cafe:0200::1').strDec()) - 42540616829182469433547762482097946625 - """ - - if self.WantPrefixLen == None and wantprefixlen == None: - wantprefixlen = 0 - - x = '%d' % self.ip - return x + self._printPrefix(wantprefixlen) - - def iptype(self): - """Return a description of the IP type ('PRIVATE', 'RESERVED', etc). - - >>> print(IP('127.0.0.1').iptype()) - PRIVATE - >>> print(IP('192.168.1.1').iptype()) - PRIVATE - >>> print(IP('195.185.1.2').iptype()) - PUBLIC - >>> print(IP('::1').iptype()) - LOOPBACK - >>> print(IP('2001:0658:022a:cafe:0200::1').iptype()) - ALLOCATED RIPE NCC - - The type information for IPv6 is out of sync with reality. - """ - - # this could be greatly improved - - if self._ipversion == 4: - iprange = IPv4ranges - elif self._ipversion == 6: - iprange = IPv6ranges - else: - raise ValueError("only IPv4 and IPv6 supported") - - bits = self.strBin() - for i in xrange(len(bits), 0, -1): - if bits[:i] in iprange: - return iprange[bits[:i]] - return "unknown" - - - def netmask(self): - """Return netmask as an integer. - - >>> "%X" % IP('195.185.0.0/16').netmask().int() - 'FFFF0000' - """ - - # TODO: unify with prefixlenToNetmask? - bits = _ipVersionToLen(self._ipversion) - locallen = bits - self._prefixlen - - return ((2 ** self._prefixlen) - 1) << locallen - - - def strNetmask(self): - """Return netmask as an string. Mostly useful for IPv6. - - >>> print(IP('195.185.0.0/16').strNetmask()) - 255.255.0.0 - >>> print(IP('2001:0658:022a:cafe::0/64').strNetmask()) - /64 - """ - - # TODO: unify with prefixlenToNetmask? - # Note: call to _ipVersionToLen() also validates version is 4 or 6 - bits = _ipVersionToLen(self._ipversion) - if self._ipversion == 4: - locallen = bits - self._prefixlen - return intToIp(((2 ** self._prefixlen) - 1) << locallen, 4) - elif self._ipversion == 6: - return "/%d" % self._prefixlen - - def len(self): - """Return the length of a subnet. - - >>> print(IP('195.185.1.0/28').len()) - 16 - >>> print(IP('195.185.1.0/24').len()) - 256 - """ - - bits = _ipVersionToLen(self._ipversion) - locallen = bits - self._prefixlen - return 2 ** locallen - - - def __nonzero__(self): - """All IPy objects should evaluate to true in boolean context. - Ordinarily they do, but if handling a default route expressed as - 0.0.0.0/0, the __len__() of the object becomes 0, which is used - as the boolean value of the object. - """ - return True - - - def __len__(self): - """ - Return the length of a subnet. - - Called to implement the built-in function len(). - It will break with large IPv6 Networks. - Use the object's len() instead. - """ - return self.len() - - def __add__(self, other): - """Emulate numeric objects through network aggregation""" - if self._ipversion != other._ipversion: - raise ValueError("Only networks with the same IP version can be added.") - if self._prefixlen != other._prefixlen: - raise ValueError("Only networks with the same prefixlen can be added.") - if self._prefixlen < 1: - raise ValueError("Networks with a prefixlen longer than /1 can't be added.") - if self > other: - # fixed by Skinny Puppy - return other.__add__(self) - if other.int() - self[-1].int() != 1: - raise ValueError("Only adjacent networks can be added together.") - ret = IP(self.int(), ipversion=self._ipversion) - ret._prefixlen = self.prefixlen() - 1 - if not _checkNetaddrWorksWithPrefixlen(ret.ip, ret._prefixlen, - ret._ipversion): - raise ValueError("The resulting %s has invalid prefix length (%s)" - % (repr(ret), ret._prefixlen)) - return ret - - def __sub__(self, other): - """Return the prefixes that are in this IP but not in the other""" - return _remove_subprefix(self, other) - - def __getitem__(self, key): - """Called to implement evaluation of self[key]. - - >>> ip=IP('127.0.0.0/30') - >>> for x in ip: - ... print(repr(x)) - ... - IP('127.0.0.0') - IP('127.0.0.1') - IP('127.0.0.2') - IP('127.0.0.3') - >>> ip[2] - IP('127.0.0.2') - >>> ip[-1] - IP('127.0.0.3') - """ - - if isinstance(key, slice): - return [self.ip + int(x) for x in xrange(*key.indices(len(self)))] - if not isinstance(key, INT_TYPES): - raise TypeError - if key < 0: - if abs(key) <= self.len(): - key = self.len() - abs(key) - else: - raise IndexError - else: - if key >= self.len(): - raise IndexError - - return self.ip + int(key) - - - - def __contains__(self, item): - """Called to implement membership test operators. - - Should return true if item is in self, false otherwise. Item - can be other IP-objects, strings or ints. - - >>> IP('195.185.1.1').strHex() - '0xc3b90101' - >>> 0xC3B90101 in IP('195.185.1.0/24') - True - >>> '127.0.0.1' in IP('127.0.0.0/24') - True - >>> IP('127.0.0.0/24') in IP('127.0.0.0/25') - False - """ - - if isinstance(item, IP): - if item._ipversion != self._ipversion: - return False - else: - item = IP(item) - if item.ip >= self.ip and item.ip < self.ip + self.len() - item.len() + 1: - return True - else: - return False - - - def overlaps(self, item): - """Check if two IP address ranges overlap. - - Returns 0 if the two ranges don't overlap, 1 if the given - range overlaps at the end and -1 if it does at the beginning. - - >>> IP('192.168.0.0/23').overlaps('192.168.1.0/24') - 1 - >>> IP('192.168.0.0/23').overlaps('192.168.1.255') - 1 - >>> IP('192.168.0.0/23').overlaps('192.168.2.0') - 0 - >>> IP('192.168.1.0/24').overlaps('192.168.0.0/23') - -1 - """ - - if not isinstance(item, IP): - item = IP(item) - if item.ip >= self.ip and item.ip < self.ip + self.len(): - return 1 - elif self.ip >= item.ip and self.ip < item.ip + item.len(): - return -1 - else: - return 0 - - - def __str__(self): - """Dispatch to the prefered String Representation. - - Used to implement str(IP).""" - - return self.strCompressed() - - - def __repr__(self): - """Print a representation of the Object. - - Used to implement repr(IP). Returns a string which evaluates - to an identical Object (without the wantprefixlen stuff - see - module docstring. - - >>> print(repr(IP('10.0.0.0/24'))) - IP('10.0.0.0/24') - """ - - return("IPint('%s')" % (self.strCompressed(1))) - - - def __cmp__(self, other): - """Called by comparison operations. - - Should return a negative integer if self < other, zero if self - == other, a positive integer if self > other. - - Order is first determined by the address family. IPv4 addresses - are always smaller than IPv6 addresses: - - >>> IP('10.0.0.0') < IP('2001:db8::') - 1 - - Then the first address is compared. Lower addresses are - always smaller: - - >>> IP('10.0.0.0') > IP('10.0.0.1') - 0 - >>> IP('10.0.0.0/24') > IP('10.0.0.1') - 0 - >>> IP('10.0.1.0') > IP('10.0.0.0/24') - 1 - >>> IP('10.0.1.0/24') > IP('10.0.0.0/24') - 1 - >>> IP('10.0.1.0/24') > IP('10.0.0.0') - 1 - - Then the prefix length is compared. Shorter prefixes are - considered smaller than longer prefixes: - - >>> IP('10.0.0.0/24') > IP('10.0.0.0') - 0 - >>> IP('10.0.0.0/24') > IP('10.0.0.0/25') - 0 - >>> IP('10.0.0.0/24') > IP('10.0.0.0/23') - 1 - - """ - if not isinstance(other, IPint): - raise TypeError - - # Lower version -> lower result - if self._ipversion != other._ipversion: - return self._ipversion < other._ipversion and -1 or 1 - - # Lower start address -> lower result - if self.ip != other.ip: - return self.ip < other.ip and -1 or 1 - - # Shorter prefix length -> lower result - if self._prefixlen != other._prefixlen: - return self._prefixlen < other._prefixlen and -1 or 1 - - # No differences found - return 0 - - def __eq__(self, other): - if not isinstance(other, IPint): - return False - return self.__cmp__(other) == 0 - - def __ne__(self, other): - return not self.__eq__(other) - - def __lt__(self, other): - return self.__cmp__(other) < 0 - - def __hash__(self): - """Called for the key object for dictionary operations, and by - the built-in function hash(). Should return a 32-bit integer - usable as a hash value for dictionary operations. The only - required property is that objects which compare equal have the - same hash value - - >>> IP('10.0.0.0/24').__hash__() - -167772185 - """ - - thehash = int(-1) - ip = self.ip - while ip > 0: - thehash = thehash ^ (ip & 0x7fffffff) - ip = ip >> 32 - thehash = thehash ^ self._prefixlen - return int(thehash) - - -class IP(IPint): - """Class for handling IP addresses and networks.""" - - def net(self): - """Return the base (first) address of a network as an IP object. - - The same as IP[0]. - - >>> IP('10.0.0.0/8').net() - IP('10.0.0.0') - """ - return IP(IPint.net(self), ipversion=self._ipversion) - - def broadcast(self): - """Return the broadcast (last) address of a network as an IP object. - - The same as IP[-1]. - - >>> IP('10.0.0.0/8').broadcast() - IP('10.255.255.255') - """ - return IP(IPint.broadcast(self)) - - def netmask(self): - """Return netmask as an IP object. - - >>> IP('10.0.0.0/8').netmask() - IP('255.0.0.0') - """ - return IP(IPint.netmask(self), ipversion=self._ipversion) - - def _getIPv4Map(self): - if self._ipversion != 6: - return None - if (self.ip >> 32) != 0xffff: - return None - ipv4 = self.ip & MAX_IPV4_ADDRESS - if self._prefixlen != 128: - ipv4 = '%s/%s' % (ipv4, 32-(128-self._prefixlen)) - return IP(ipv4, ipversion=4) - - def reverseNames(self): - """Return a list with values forming the reverse lookup. - - >>> IP('213.221.113.87/32').reverseNames() - ['87.113.221.213.in-addr.arpa.'] - >>> IP('213.221.112.224/30').reverseNames() - ['224.112.221.213.in-addr.arpa.', '225.112.221.213.in-addr.arpa.', '226.112.221.213.in-addr.arpa.', '227.112.221.213.in-addr.arpa.'] - >>> IP('127.0.0.0/24').reverseNames() - ['0.0.127.in-addr.arpa.'] - >>> IP('127.0.0.0/23').reverseNames() - ['0.0.127.in-addr.arpa.', '1.0.127.in-addr.arpa.'] - >>> IP('127.0.0.0/16').reverseNames() - ['0.127.in-addr.arpa.'] - >>> IP('127.0.0.0/15').reverseNames() - ['0.127.in-addr.arpa.', '1.127.in-addr.arpa.'] - >>> IP('128.0.0.0/8').reverseNames() - ['128.in-addr.arpa.'] - >>> IP('128.0.0.0/7').reverseNames() - ['128.in-addr.arpa.', '129.in-addr.arpa.'] - >>> IP('::1:2').reverseNames() - ['2.0.0.0.1.ip6.arpa.'] - """ - - if self._ipversion == 4: - ret = [] - # TODO: Refactor. Add support for IPint objects - if self.len() < 2**8: - for x in self: - ret.append(x.reverseName()) - elif self.len() < 2**16: - for i in xrange(0, self.len(), 2**8): - ret.append(self[i].reverseName()[2:]) - elif self.len() < 2**24: - for i in xrange(0, self.len(), 2**16): - ret.append(self[i].reverseName()[4:]) - else: - for i in xrange(0, self.len(), 2**24): - ret.append(self[i].reverseName()[6:]) - return ret - elif self._ipversion == 6: - ipv4 = self._getIPv4Map() - if ipv4 is not None: - return ipv4.reverseNames() - s = "%x" % self.ip - if self._prefixlen % 4 != 0: - raise NotImplementedError("can't create IPv6 reverse names at sub nibble level") - s = list(s) - s.reverse() - s = '.'.join(s) - first_nibble_index = int(32 - (self._prefixlen // 4)) * 2 - return ["%s.ip6.arpa." % s[first_nibble_index:]] - else: - raise ValueError("only IPv4 and IPv6 supported") - - def reverseName(self): - """Return the value for reverse lookup/PTR records as RFC 2317 look alike. - - RFC 2317 is an ugly hack which only works for sub-/24 e.g. not - for /23. Do not use it. Better set up a zone for every - address. See reverseName for a way to achieve that. - - >>> print(IP('195.185.1.1').reverseName()) - 1.1.185.195.in-addr.arpa. - >>> print(IP('195.185.1.0/28').reverseName()) - 0-15.1.185.195.in-addr.arpa. - >>> IP('::1:2').reverseName() - '2.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.' - >>> IP('ff02::/64').reverseName() - '0.0.0.0.0.0.0.0.0.0.0.0.2.0.f.f.ip6.arpa.' - """ - - if self._ipversion == 4: - s = self.strFullsize(0) - s = s.split('.') - s.reverse() - first_byte_index = int(4 - (self._prefixlen // 8)) - if self._prefixlen % 8 != 0: - nibblepart = "%s-%s" % (s[3-(self._prefixlen // 8)], intToIp(self.ip + self.len() - 1, 4).split('.')[-1]) - nibblepart += '.' - else: - nibblepart = "" - - s = '.'.join(s[first_byte_index:]) - return "%s%s.in-addr.arpa." % (nibblepart, s) - - elif self._ipversion == 6: - ipv4 = self._getIPv4Map() - if ipv4 is not None: - return ipv4.reverseName() - s = '%032x' % self.ip - if self._prefixlen % 4 != 0: - nibblepart = "%s-%x" % (s[self._prefixlen:], self.ip + self.len() - 1) - nibblepart += '.' - else: - nibblepart = "" - s = list(s) - s.reverse() - s = '.'.join(s) - first_nibble_index = int(32 - (self._prefixlen // 4)) * 2 - return "%s%s.ip6.arpa." % (nibblepart, s[first_nibble_index:]) - else: - raise ValueError("only IPv4 and IPv6 supported") - - def make_net(self, netmask): - """Transform a single IP address into a network specification by - applying the given netmask. - - Returns a new IP instance. - - >>> print(IP('127.0.0.1').make_net('255.0.0.0')) - 127.0.0.0/8 - """ - if '/' in str(netmask): - raise ValueError("invalid netmask (%s)" % netmask) - return IP('%s/%s' % (self, netmask), make_net=True) - - def __getitem__(self, key): - """Called to implement evaluation of self[key]. - - >>> ip=IP('127.0.0.0/30') - >>> for x in ip: - ... print(str(x)) - ... - 127.0.0.0 - 127.0.0.1 - 127.0.0.2 - 127.0.0.3 - >>> print(str(ip[2])) - 127.0.0.2 - >>> print(str(ip[-1])) - 127.0.0.3 - """ - if isinstance(key, slice): - return [IP(IPint.__getitem__(self, x), ipversion=self._ipversion) for x in xrange(*key.indices(len(self)))] - return IP(IPint.__getitem__(self, key), ipversion=self._ipversion) - - def __repr__(self): - """Print a representation of the Object. - - >>> IP('10.0.0.0/8') - IP('10.0.0.0/8') - """ - - return("IP('%s')" % (self.strCompressed(1))) - - def get_mac(self): - """ - Get the 802.3 MAC address from IPv6 RFC 2464 address, in lower case. - Return None if the address is an IPv4 or not a IPv6 RFC 2464 address. - - >>> IP('fe80::f66d:04ff:fe47:2fae').get_mac() - 'f4:6d:04:47:2f:ae' - """ - if self._ipversion != 6: - return None - if (self.ip & 0x20000ffff000000) != 0x20000fffe000000: - return None - return '%02x:%02x:%02x:%02x:%02x:%02x' % ( - (((self.ip >> 56) & 0xff) & 0xfd), - (self.ip >> 48) & 0xff, - (self.ip >> 40) & 0xff, - (self.ip >> 16) & 0xff, - (self.ip >> 8) & 0xff, - self.ip & 0xff, - ) - - def v46map(self): - """ - Returns the IPv6 mapped address of an IPv4 address, or the corresponding - IPv4 address if the IPv6 address is in the appropriate range. - Raises a ValueError if the IPv6 address is not translatable. See RFC 4291. - - >>> IP('192.168.1.1').v46map() - IP('::ffff:192.168.1.1') - >>> IP('::ffff:192.168.1.1').v46map() - IP('192.168.1.1') - """ - if self._ipversion == 4: - return IP(str(IPV6_MAP_MASK + self.ip) + - "/%s" % (self._prefixlen + 96)) - else: - if self.ip & IPV6_TEST_MAP == IPV6_MAP_MASK: - return IP(str(self.ip - IPV6_MAP_MASK) + - "/%s" % (self._prefixlen - 96)) - raise ValueError("%s cannot be converted to an IPv4 address." - % repr(self)) - -class IPSet(collections.MutableSet): - def __init__(self, iterable=[]): - # Make sure it's iterable, otherwise wrap - if not isinstance(iterable, collections.Iterable): - raise TypeError("'%s' object is not iterable" % type(iterable).__name__) - - # Make sure we only accept IP objects - for prefix in iterable: - if not isinstance(prefix, IP): - raise ValueError('Only IP objects can be added to an IPSet') - - # Store and optimize - self.prefixes = iterable[:] - self.optimize() - - def __contains__(self, ip): - valid_masks = self.prefixtable.keys() - if isinstance(ip, IP): - #Don't dig through more-specific ranges - ip_mask = ip._prefixlen - valid_masks = [x for x in valid_masks if x <= ip_mask] - for mask in sorted(valid_masks): - i = bisect.bisect(self.prefixtable[mask], ip) - # Because of sorting order, a match can only occur in the prefix - # that comes before the result of the search. - if i and ip in self.prefixtable[mask][i - 1]: - return True - - def __iter__(self): - for prefix in self.prefixes: - yield prefix - - def __len__(self): - return self.len() - - def __add__(self, other): - return IPSet(self.prefixes + other.prefixes) - - def __sub__(self, other): - new = IPSet(self.prefixes) - for prefix in other: - new.discard(prefix) - return new - - def __and__(self, other): - left = iter(self.prefixes) - right = iter(other.prefixes) - result = [] - try: - l = next(left) - r = next(right) - while True: - # iterate over prefixes in order, keeping the smaller of the - # two if they overlap - if l in r: - result.append(l) - l = next(left) - continue - elif r in l: - result.append(r) - r = next(right) - continue - if l < r: - l = next(left) - else: - r = next(right) - except StopIteration: - return IPSet(result) - - def __repr__(self): - return '%s([' % self.__class__.__name__ + ', '.join(map(repr, self.prefixes)) + '])' - - def len(self): - return sum(prefix.len() for prefix in self.prefixes) - - def add(self, value): - # Make sure it's iterable, otherwise wrap - if not isinstance(value, collections.Iterable): - value = [value] - - # Check type - for prefix in value: - if not isinstance(prefix, IP): - raise ValueError('Only IP objects can be added to an IPSet') - - # Append and optimize - self.prefixes.extend(value) - self.optimize() - - def discard(self, value): - # Make sure it's iterable, otherwise wrap - if not isinstance(value, collections.Iterable): - value = [value] - - # This is much faster than iterating over the addresses - if isinstance(value, IPSet): - value = value.prefixes - - # Remove - for del_prefix in value: - if not isinstance(del_prefix, IP): - raise ValueError('Only IP objects can be removed from an IPSet') - - # First check if this prefix contains anything in our list - found = False - d = 0 - for i in range(len(self.prefixes)): - if self.prefixes[i - d] in del_prefix: - self.prefixes.pop(i - d) - d = d + 1 - found = True - - if found: - # If the prefix was bigger than an existing prefix, then it's - # certainly not a subset of one, so skip the rest - continue - - # Maybe one of our prefixes contains this prefix - found = False - for i in range(len(self.prefixes)): - if del_prefix in self.prefixes[i]: - self.prefixes[i:i+1] = self.prefixes[i] - del_prefix - break - - self.optimize() - - def isdisjoint(self, other): - left = iter(self.prefixes) - right = iter(other.prefixes) - try: - l = next(left) - r = next(right) - while True: - if l in r or r in l: - return False - if l < r: - l = next(left) - else: - r = next(right) - except StopIteration: - return True - - def optimize(self): - # The algorithm below *depends* on the sort order - self.prefixes.sort() - - # First eliminate all values that are a subset of other values - addrlen = len(self.prefixes) - i = 0 - while i < addrlen: - # Everything that might be inside this prefix follows - # directly behind it - j = i+1 - while j < addrlen and self.prefixes[j] in self.prefixes[i]: - # Mark for deletion by overwriting with None - self.prefixes[j] = None - j += 1 - - # Continue where we left off - i = j - - # Try to merge as many prefixes as possible - run_again = True - while run_again: - # Filter None values. This happens when a subset is eliminated - # above, or when two prefixes are merged below - self.prefixes = [a for a in self.prefixes if a is not None] - - # We'll set run_again to True when we make changes that require - # re-evaluation of the whole list - run_again = False - - # We can merge two prefixes that have the same version, same - # prefix length and differ only on the last bit of the prefix - addrlen = len(self.prefixes) - i = 0 - while i < addrlen-1: - j = i + 1 - - try: - # The next line will throw an exception when merging - # is not possible - self.prefixes[i] += self.prefixes[j] - self.prefixes[j] = None - i = j + 1 - run_again = True - except ValueError: - # Can't be merged, see if position j can be merged - i = j - - # O(n) insertion now by prefix means faster searching on __contains__ - # when lots of ranges with the same length exist - self.prefixtable = {} - for address in self.prefixes: - try: - self.prefixtable[address._prefixlen].append(address) - except KeyError: - self.prefixtable[address._prefixlen] = [address] - -def _parseAddressIPv6(ipstr): - """ - Internal function used by parseAddress() to parse IPv6 address with ':'. - - >>> print(_parseAddressIPv6('::')) - 0 - >>> print(_parseAddressIPv6('::1')) - 1 - >>> print(_parseAddressIPv6('0:0:0:0:0:0:0:1')) - 1 - >>> print(_parseAddressIPv6('0:0:0::0:0:1')) - 1 - >>> print(_parseAddressIPv6('0:0:0:0:0:0:0:0')) - 0 - >>> print(_parseAddressIPv6('0:0:0::0:0:0')) - 0 - - >>> print(_parseAddressIPv6('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210')) - 338770000845734292534325025077361652240 - >>> print(_parseAddressIPv6('1080:0000:0000:0000:0008:0800:200C:417A')) - 21932261930451111902915077091070067066 - >>> print(_parseAddressIPv6('1080:0:0:0:8:800:200C:417A')) - 21932261930451111902915077091070067066 - >>> print(_parseAddressIPv6('1080:0::8:800:200C:417A')) - 21932261930451111902915077091070067066 - >>> print(_parseAddressIPv6('1080::8:800:200C:417A')) - 21932261930451111902915077091070067066 - >>> print(_parseAddressIPv6('FF01:0:0:0:0:0:0:43')) - 338958331222012082418099330867817087043 - >>> print(_parseAddressIPv6('FF01:0:0::0:0:43')) - 338958331222012082418099330867817087043 - >>> print(_parseAddressIPv6('FF01::43')) - 338958331222012082418099330867817087043 - >>> print(_parseAddressIPv6('0:0:0:0:0:0:13.1.68.3')) - 218186755 - >>> print(_parseAddressIPv6('::13.1.68.3')) - 218186755 - >>> print(_parseAddressIPv6('0:0:0:0:0:FFFF:129.144.52.38')) - 281472855454758 - >>> print(_parseAddressIPv6('::FFFF:129.144.52.38')) - 281472855454758 - >>> print(_parseAddressIPv6('1080:0:0:0:8:800:200C:417A')) - 21932261930451111902915077091070067066 - >>> print(_parseAddressIPv6('1080::8:800:200C:417A')) - 21932261930451111902915077091070067066 - >>> print(_parseAddressIPv6('::1:2:3:4:5:6')) - 1208962713947218704138246 - >>> print(_parseAddressIPv6('1:2:3:4:5:6::')) - 5192455318486707404433266432802816 - """ - - # Split string into a list, example: - # '1080:200C::417A' => ['1080', '200C', '417A'] and fill_pos=2 - # and fill_pos is the position of '::' in the list - items = [] - index = 0 - fill_pos = None - while index < len(ipstr): - text = ipstr[index:] - if text.startswith("::"): - if fill_pos is not None: - # Invalid IPv6, eg. '1::2::' - raise ValueError("%r: Invalid IPv6 address: more than one '::'" % ipstr) - fill_pos = len(items) - index += 2 - continue - pos = text.find(':') - if pos == 0: - # Invalid IPv6, eg. '1::2:' - raise ValueError("%r: Invalid IPv6 address" % ipstr) - if pos != -1: - items.append(text[:pos]) - if text[pos:pos+2] == "::": - index += pos - else: - index += pos+1 - - if index == len(ipstr): - # Invalid IPv6, eg. '1::2:' - raise ValueError("%r: Invalid IPv6 address" % ipstr) - else: - items.append(text) - break - - if items and '.' in items[-1]: - # IPv6 ending with IPv4 like '::ffff:192.168.0.1' - if (fill_pos is not None) and not (fill_pos <= len(items)-1): - # Invalid IPv6: 'ffff:192.168.0.1::' - raise ValueError("%r: Invalid IPv6 address: '::' after IPv4" % ipstr) - value = parseAddress(items[-1])[0] - items = items[:-1] + ["%04x" % (value >> 16), "%04x" % (value & 0xffff)] - - # Expand fill_pos to fill with '0' - # ['1','2'] with fill_pos=1 => ['1', '0', '0', '0', '0', '0', '0', '2'] - if fill_pos is not None: - diff = 8 - len(items) - if diff <= 0: - raise ValueError("%r: Invalid IPv6 address: '::' is not needed" % ipstr) - items = items[:fill_pos] + ['0']*diff + items[fill_pos:] - - # Here we have a list of 8 strings - if len(items) != 8: - # Invalid IPv6, eg. '1:2:3' - raise ValueError("%r: Invalid IPv6 address: should have 8 hextets" % ipstr) - - # Convert strings to long integer - value = 0 - index = 0 - for item in items: - try: - item = int(item, 16) - error = not(0 <= item <= 0xffff) - except ValueError: - error = True - if error: - raise ValueError("%r: Invalid IPv6 address: invalid hexlet %r" % (ipstr, item)) - value = (value << 16) + item - index += 1 - return value - -def parseAddress(ipstr): - """ - Parse a string and return the corresponding IP address (as integer) - and a guess of the IP version. - - Following address formats are recognized: - - >>> def testParseAddress(address): - ... ip, version = parseAddress(address) - ... print(("%s (IPv%s)" % (ip, version))) - ... - >>> testParseAddress('0x0123456789abcdef') # IPv4 if <= 0xffffffff else IPv6 - 81985529216486895 (IPv6) - >>> testParseAddress('123.123.123.123') # IPv4 - 2071690107 (IPv4) - >>> testParseAddress('123.123') # 0-padded IPv4 - 2071658496 (IPv4) - >>> testParseAddress('127') - 2130706432 (IPv4) - >>> testParseAddress('255') - 4278190080 (IPv4) - >>> testParseAddress('256') - 256 (IPv4) - >>> testParseAddress('108000000000000000080800200C417A') - 21932261930451111902915077091070067066 (IPv6) - >>> testParseAddress('0x108000000000000000080800200C417A') - 21932261930451111902915077091070067066 (IPv6) - >>> testParseAddress('1080:0000:0000:0000:0008:0800:200C:417A') - 21932261930451111902915077091070067066 (IPv6) - >>> testParseAddress('1080:0:0:0:8:800:200C:417A') - 21932261930451111902915077091070067066 (IPv6) - >>> testParseAddress('1080:0::8:800:200C:417A') - 21932261930451111902915077091070067066 (IPv6) - >>> testParseAddress('::1') - 1 (IPv6) - >>> testParseAddress('::') - 0 (IPv6) - >>> testParseAddress('0:0:0:0:0:FFFF:129.144.52.38') - 281472855454758 (IPv6) - >>> testParseAddress('::13.1.68.3') - 218186755 (IPv6) - >>> testParseAddress('::FFFF:129.144.52.38') - 281472855454758 (IPv6) - """ - - try: - hexval = int(ipstr, 16) - except ValueError: - hexval = None - try: - intval = int(ipstr, 10) - except ValueError: - intval = None - - if ipstr.startswith('0x') and hexval is not None: - if hexval > MAX_IPV6_ADDRESS: - raise ValueError("IP Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, hexval)) - if hexval <= MAX_IPV4_ADDRESS: - return (hexval, 4) - else: - return (hexval, 6) - - if ipstr.find(':') != -1: - return (_parseAddressIPv6(ipstr), 6) - - elif len(ipstr) == 32 and hexval is not None: - # assume IPv6 in pure hexadecimal notation - return (hexval, 6) - - elif ipstr.find('.') != -1 or (intval is not None and intval < 256): - # assume IPv4 ('127' gets interpreted as '127.0.0.0') - bytes = ipstr.split('.') - if len(bytes) > 4: - raise ValueError("IPv4 Address with more than 4 bytes") - bytes += ['0'] * (4 - len(bytes)) - bytes = [int(x) for x in bytes] - for x in bytes: - if x > 255 or x < 0: - raise ValueError("%r: single byte must be 0 <= byte < 256" % (ipstr)) - return ((bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3], 4) - - elif intval is not None: - # we try to interprete it as a decimal digit - - # this ony works for numbers > 255 ... others - # will be interpreted as IPv4 first byte - if intval > MAX_IPV6_ADDRESS: - raise ValueError("IP Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, intval)) - if intval <= MAX_IPV4_ADDRESS: - return (intval, 4) - else: - return (intval, 6) - - raise ValueError("IP Address format was invalid: %s" % ipstr) - - -def intToIp(ip, version): - """Transform an integer string into an IP address.""" - - # just to be sure and hoping for Python 2.2 - ip = int(ip) - - if ip < 0: - raise ValueError("IPs can't be negative: %d" % (ip)) - - ret = '' - if version == 4: - if ip > MAX_IPV4_ADDRESS: - raise ValueError("IPv4 Address can't be larger than %x: %x" % (MAX_IPV4_ADDRESS, ip)) - for l in xrange(4): - ret = str(ip & 0xff) + '.' + ret - ip = ip >> 8 - ret = ret[:-1] - elif version == 6: - if ip > MAX_IPV6_ADDRESS: - raise ValueError("IPv6 Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, ip)) - l = "%032x" % ip - for x in xrange(1, 33): - ret = l[-x] + ret - if x % 4 == 0: - ret = ':' + ret - ret = ret[1:] - else: - raise ValueError("only IPv4 and IPv6 supported") - - return ret - -def _ipVersionToLen(version): - """Return number of bits in address for a certain IP version. - - >>> _ipVersionToLen(4) - 32 - >>> _ipVersionToLen(6) - 128 - >>> _ipVersionToLen(5) - Traceback (most recent call last): - File "", line 1, in ? - File "IPy.py", line 1076, in _ipVersionToLen - raise ValueError("only IPv4 and IPv6 supported") - ValueError: only IPv4 and IPv6 supported - """ - - if version == 4: - return 32 - elif version == 6: - return 128 - else: - raise ValueError("only IPv4 and IPv6 supported") - - -def _countFollowingZeros(l): - """Return number of elements containing 0 at the beginning of the list.""" - if len(l) == 0: - return 0 - elif l[0] != 0: - return 0 - else: - return 1 + _countFollowingZeros(l[1:]) - - -_BitTable = {'0': '0000', '1': '0001', '2': '0010', '3': '0011', - '4': '0100', '5': '0101', '6': '0110', '7': '0111', - '8': '1000', '9': '1001', 'a': '1010', 'b': '1011', - 'c': '1100', 'd': '1101', 'e': '1110', 'f': '1111'} - -def _intToBin(val): - """Return the binary representation of an integer as string.""" - - if val < 0: - raise ValueError("Only positive values allowed") - s = "%x" % val - ret = '' - for x in s: - ret += _BitTable[x] - # remove leading zeros - while ret[0] == '0' and len(ret) > 1: - ret = ret[1:] - return ret - -def _count1Bits(num): - """Find the highest bit set to 1 in an integer.""" - ret = 0 - while num > 0: - num = num >> 1 - ret += 1 - return ret - -def _count0Bits(num): - """Find the highest bit set to 0 in an integer.""" - - # this could be so easy if _count1Bits(~int(num)) would work as excepted - num = int(num) - if num < 0: - raise ValueError("Only positive Numbers please: %s" % (num)) - ret = 0 - while num > 0: - if num & 1 == 1: - break - num = num >> 1 - ret += 1 - return ret - - -def _checkPrefix(ip, prefixlen, version): - """Check the validity of a prefix - - Checks if the variant part of a prefix only has 0s, and the length is - correct. - - >>> _checkPrefix(0x7f000000, 24, 4) - 1 - >>> _checkPrefix(0x7f000001, 24, 4) - 0 - >>> repr(_checkPrefix(0x7f000001, -1, 4)) - 'None' - >>> repr(_checkPrefix(0x7f000001, 33, 4)) - 'None' - """ - - # TODO: unify this v4/v6/invalid code in a function - bits = _ipVersionToLen(version) - - if prefixlen < 0 or prefixlen > bits: - return None - - if ip == 0: - zbits = bits + 1 - else: - zbits = _count0Bits(ip) - if zbits < bits - prefixlen: - return 0 - else: - return 1 - - -def _checkNetmask(netmask, masklen): - """Checks if a netmask is expressable as a prefixlen.""" - - num = int(netmask) - bits = masklen - - # remove zero bits at the end - while (num & 1) == 0 and bits != 0: - num = num >> 1 - bits -= 1 - if bits == 0: - break - # now check if the rest consists only of ones - while bits > 0: - if (num & 1) == 0: - raise ValueError("Netmask 0x%x can't be expressed as an prefix." % netmask) - num = num >> 1 - bits -= 1 - - -def _checkNetaddrWorksWithPrefixlen(net, prefixlen, version): - """Check if a base addess of a network is compatible with a prefixlen""" - try: - return (net & _prefixlenToNetmask(prefixlen, version) == net) - except ValueError: - return False - - -def _netmaskToPrefixlen(netmask): - """Convert an Integer representing a netmask to a prefixlen. - - E.g. 0xffffff00 (255.255.255.0) returns 24 - """ - - netlen = _count0Bits(netmask) - masklen = _count1Bits(netmask) - _checkNetmask(netmask, masklen) - return masklen - netlen - - -def _prefixlenToNetmask(prefixlen, version): - """Return a mask of n bits as a long integer. - - From 'IP address conversion functions with the builtin socket module' - by Alex Martelli - http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66517 - """ - if prefixlen == 0: - return 0 - elif prefixlen < 0: - raise ValueError("Prefixlen must be > 0") - return ((2<', 'eval', - dont_inherit=True) - -_cache = weakref.WeakValueDictionary() - -def compile(marker): - """Return compiled marker as a function accepting an environment dict.""" - try: - return _cache[marker] - except KeyError: - pass - if not marker.strip(): - def marker_fn(environment=None, override=None): - """""" - return True - else: - compiled_marker = compile_marker(parse_marker(marker)) - def marker_fn(environment=None, override=None): - """override updates environment""" - if override is None: - override = {} - if environment is None: - environment = default_environment() - environment.update(override) - return eval(compiled_marker, environment) - marker_fn.__doc__ = marker - _cache[marker] = marker_fn - return _cache[marker] - -def interpret(marker, environment=None): - return compile(marker)(environment) diff --git a/awx/lib/site-packages/amqp/__init__.py b/awx/lib/site-packages/amqp/__init__.py deleted file mode 100644 index 3bd57c9a9e..0000000000 --- a/awx/lib/site-packages/amqp/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -"""Low-level AMQP client for Python (fork of amqplib)""" -# Copyright (C) 2007-2008 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -VERSION = (1, 4, 5) -__version__ = '.'.join(map(str, VERSION[0:3])) + ''.join(VERSION[3:]) -__author__ = 'Barry Pederson' -__maintainer__ = 'Ask Solem' -__contact__ = 'pyamqp@celeryproject.org' -__homepage__ = 'http://github.com/celery/py-amqp' -__docformat__ = 'restructuredtext' - -# -eof meta- - -# -# Pull in the public items from the various sub-modules -# -from .basic_message import Message # noqa -from .channel import Channel # noqa -from .connection import Connection # noqa -from .exceptions import ( # noqa - AMQPError, - ConnectionError, - RecoverableConnectionError, - IrrecoverableConnectionError, - ChannelError, - RecoverableChannelError, - IrrecoverableChannelError, - ConsumerCancelled, - ContentTooLarge, - NoConsumers, - ConnectionForced, - InvalidPath, - AccessRefused, - NotFound, - ResourceLocked, - PreconditionFailed, - FrameError, - FrameSyntaxError, - InvalidCommand, - ChannelNotOpen, - UnexpectedFrame, - ResourceError, - NotAllowed, - AMQPNotImplementedError, - InternalError, - error_for_code, - __all__ as _all_exceptions, -) -from .utils import promise # noqa - -__all__ = [ - 'Connection', - 'Channel', - 'Message', -] + _all_exceptions diff --git a/awx/lib/site-packages/amqp/abstract_channel.py b/awx/lib/site-packages/amqp/abstract_channel.py deleted file mode 100644 index 28cfe136e5..0000000000 --- a/awx/lib/site-packages/amqp/abstract_channel.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Code common to Connection and Channel objects.""" -# Copyright (C) 2007-2008 Barry Pederson ) -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -from .exceptions import AMQPNotImplementedError, RecoverableConnectionError -from .serialization import AMQPWriter - -__all__ = ['AbstractChannel'] - - -class AbstractChannel(object): - """Superclass for both the Connection, which is treated - as channel 0, and other user-created Channel objects. - - The subclasses must have a _METHOD_MAP class property, mapping - between AMQP method signatures and Python methods. - - """ - def __init__(self, connection, channel_id): - self.connection = connection - self.channel_id = channel_id - connection.channels[channel_id] = self - self.method_queue = [] # Higher level queue for methods - self.auto_decode = False - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - def _send_method(self, method_sig, args=bytes(), content=None): - """Send a method for our channel.""" - conn = self.connection - if conn is None: - raise RecoverableConnectionError('connection already closed') - - if isinstance(args, AMQPWriter): - args = args.getvalue() - - conn.method_writer.write_method( - self.channel_id, method_sig, args, content, - ) - - def close(self): - """Close this Channel or Connection""" - raise NotImplementedError('Must be overriden in subclass') - - def wait(self, allowed_methods=None): - """Wait for a method that matches our allowed_methods parameter (the - default value of None means match any method), and dispatch to it.""" - method_sig, args, content = self.connection._wait_method( - self.channel_id, allowed_methods) - - return self.dispatch_method(method_sig, args, content) - - def dispatch_method(self, method_sig, args, content): - if content and \ - self.auto_decode and \ - hasattr(content, 'content_encoding'): - try: - content.body = content.body.decode(content.content_encoding) - except Exception: - pass - - try: - amqp_method = self._METHOD_MAP[method_sig] - except KeyError: - raise AMQPNotImplementedError( - 'Unknown AMQP method {0!r}'.format(method_sig)) - - if content is None: - return amqp_method(self, args) - else: - return amqp_method(self, args, content) - - #: Placeholder, the concrete implementations will have to - #: supply their own versions of _METHOD_MAP - _METHOD_MAP = {} diff --git a/awx/lib/site-packages/amqp/basic_message.py b/awx/lib/site-packages/amqp/basic_message.py deleted file mode 100644 index 192ede90b2..0000000000 --- a/awx/lib/site-packages/amqp/basic_message.py +++ /dev/null @@ -1,124 +0,0 @@ -"""Messages for AMQP""" -# Copyright (C) 2007-2008 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -from .serialization import GenericContent - -__all__ = ['Message'] - - -class Message(GenericContent): - """A Message for use with the Channnel.basic_* methods.""" - - #: Instances of this class have these attributes, which - #: are passed back and forth as message properties between - #: client and server - PROPERTIES = [ - ('content_type', 'shortstr'), - ('content_encoding', 'shortstr'), - ('application_headers', 'table'), - ('delivery_mode', 'octet'), - ('priority', 'octet'), - ('correlation_id', 'shortstr'), - ('reply_to', 'shortstr'), - ('expiration', 'shortstr'), - ('message_id', 'shortstr'), - ('timestamp', 'timestamp'), - ('type', 'shortstr'), - ('user_id', 'shortstr'), - ('app_id', 'shortstr'), - ('cluster_id', 'shortstr') - ] - - def __init__(self, body='', children=None, channel=None, **properties): - """Expected arg types - - body: string - children: (not supported) - - Keyword properties may include: - - content_type: shortstr - MIME content type - - content_encoding: shortstr - MIME content encoding - - application_headers: table - Message header field table, a dict with string keys, - and string | int | Decimal | datetime | dict values. - - delivery_mode: octet - Non-persistent (1) or persistent (2) - - priority: octet - The message priority, 0 to 9 - - correlation_id: shortstr - The application correlation identifier - - reply_to: shortstr - The destination to reply to - - expiration: shortstr - Message expiration specification - - message_id: shortstr - The application message identifier - - timestamp: datetime.datetime - The message timestamp - - type: shortstr - The message type name - - user_id: shortstr - The creating user id - - app_id: shortstr - The creating application id - - cluster_id: shortstr - Intra-cluster routing identifier - - Unicode bodies are encoded according to the 'content_encoding' - argument. If that's None, it's set to 'UTF-8' automatically. - - example:: - - msg = Message('hello world', - content_type='text/plain', - application_headers={'foo': 7}) - - """ - super(Message, self).__init__(**properties) - self.body = body - self.channel = channel - - def __eq__(self, other): - """Check if the properties and bodies of this Message and another - Message are the same. - - Received messages may contain a 'delivery_info' attribute, - which isn't compared. - - """ - try: - return (super(Message, self).__eq__(other) and - self.body == other.body) - except AttributeError: - return NotImplemented diff --git a/awx/lib/site-packages/amqp/channel.py b/awx/lib/site-packages/amqp/channel.py deleted file mode 100644 index 05eb09a206..0000000000 --- a/awx/lib/site-packages/amqp/channel.py +++ /dev/null @@ -1,2537 +0,0 @@ -"""AMQP Channels""" -# Copyright (C) 2007-2008 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -import logging - -from collections import defaultdict -from warnings import warn - -from .abstract_channel import AbstractChannel -from .exceptions import ChannelError, ConsumerCancelled, error_for_code -from .five import Queue -from .protocol import basic_return_t, queue_declare_ok_t -from .serialization import AMQPWriter - -__all__ = ['Channel'] - -AMQP_LOGGER = logging.getLogger('amqp') - -EXCHANGE_AUTODELETE_DEPRECATED = """\ -The auto_delete flag for exchanges has been deprecated and will be removed -from py-amqp v1.5.0.\ -""" - - -class VDeprecationWarning(DeprecationWarning): - pass - - -class Channel(AbstractChannel): - """Work with channels - - The channel class provides methods for a client to establish a - virtual connection - a channel - to a server and for both peers to - operate the virtual connection thereafter. - - GRAMMAR:: - - channel = open-channel *use-channel close-channel - open-channel = C:OPEN S:OPEN-OK - use-channel = C:FLOW S:FLOW-OK - / S:FLOW C:FLOW-OK - / functional-class - close-channel = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK - - """ - - def __init__(self, connection, channel_id=None, auto_decode=True): - """Create a channel bound to a connection and using the specified - numeric channel_id, and open on the server. - - The 'auto_decode' parameter (defaults to True), indicates - whether the library should attempt to decode the body - of Messages to a Unicode string if there's a 'content_encoding' - property for the message. If there's no 'content_encoding' - property, or the decode raises an Exception, the message body - is left as plain bytes. - - """ - if channel_id: - connection._claim_channel_id(channel_id) - else: - channel_id = connection._get_free_channel_id() - - AMQP_LOGGER.debug('using channel_id: %d', channel_id) - - super(Channel, self).__init__(connection, channel_id) - - self.is_open = False - self.active = True # Flow control - self.returned_messages = Queue() - self.callbacks = {} - self.cancel_callbacks = {} - self.auto_decode = auto_decode - self.events = defaultdict(set) - self.no_ack_consumers = set() - - # set first time basic_publish_confirm is called - # and publisher confirms are enabled for this channel. - self._confirm_selected = False - if self.connection.confirm_publish: - self.basic_publish = self.basic_publish_confirm - - self._x_open() - - def _do_close(self): - """Tear down this object, after we've agreed to close - with the server.""" - AMQP_LOGGER.debug('Closed channel #%d', self.channel_id) - self.is_open = False - channel_id, self.channel_id = self.channel_id, None - connection, self.connection = self.connection, None - if connection: - connection.channels.pop(channel_id, None) - connection._avail_channel_ids.append(channel_id) - self.callbacks.clear() - self.cancel_callbacks.clear() - self.events.clear() - self.no_ack_consumers.clear() - - def _do_revive(self): - self.is_open = False - self._x_open() - - def close(self, reply_code=0, reply_text='', method_sig=(0, 0)): - """Request a channel close - - This method indicates that the sender wants to close the - channel. This may be due to internal conditions (e.g. a forced - shut-down) or due to an error handling a specific method, i.e. - an exception. When a close is due to an exception, the sender - provides the class and method id of the method which caused - the exception. - - RULE: - - After sending this method any received method except - Channel.Close-OK MUST be discarded. - - RULE: - - The peer sending this method MAY use a counter or timeout - to detect failure of the other peer to respond correctly - with Channel.Close-OK.. - - PARAMETERS: - reply_code: short - - The reply code. The AMQ reply codes are defined in AMQ - RFC 011. - - reply_text: shortstr - - The localised reply text. This text can be logged as an - aid to resolving issues. - - class_id: short - - failing method class - - When the close is provoked by a method exception, this - is the class of the method. - - method_id: short - - failing method ID - - When the close is provoked by a method exception, this - is the ID of the method. - - """ - try: - if not self.is_open or self.connection is None: - return - - args = AMQPWriter() - args.write_short(reply_code) - args.write_shortstr(reply_text) - args.write_short(method_sig[0]) # class_id - args.write_short(method_sig[1]) # method_id - self._send_method((20, 40), args) - return self.wait(allowed_methods=[ - (20, 40), # Channel.close - (20, 41), # Channel.close_ok - ]) - finally: - self.connection = None - - def _close(self, args): - """Request a channel close - - This method indicates that the sender wants to close the - channel. This may be due to internal conditions (e.g. a forced - shut-down) or due to an error handling a specific method, i.e. - an exception. When a close is due to an exception, the sender - provides the class and method id of the method which caused - the exception. - - RULE: - - After sending this method any received method except - Channel.Close-OK MUST be discarded. - - RULE: - - The peer sending this method MAY use a counter or timeout - to detect failure of the other peer to respond correctly - with Channel.Close-OK.. - - PARAMETERS: - reply_code: short - - The reply code. The AMQ reply codes are defined in AMQ - RFC 011. - - reply_text: shortstr - - The localised reply text. This text can be logged as an - aid to resolving issues. - - class_id: short - - failing method class - - When the close is provoked by a method exception, this - is the class of the method. - - method_id: short - - failing method ID - - When the close is provoked by a method exception, this - is the ID of the method. - - """ - - reply_code = args.read_short() - reply_text = args.read_shortstr() - class_id = args.read_short() - method_id = args.read_short() - - self._send_method((20, 41)) - self._do_revive() - - raise error_for_code( - reply_code, reply_text, (class_id, method_id), ChannelError, - ) - - def _close_ok(self, args): - """Confirm a channel close - - This method confirms a Channel.Close method and tells the - recipient that it is safe to release resources for the channel - and close the socket. - - RULE: - - A peer that detects a socket closure without having - received a Channel.Close-Ok handshake method SHOULD log - the error. - - """ - self._do_close() - - def flow(self, active): - """Enable/disable flow from peer - - This method asks the peer to pause or restart the flow of - content data. This is a simple flow-control mechanism that a - peer can use to avoid oveflowing its queues or otherwise - finding itself receiving more messages than it can process. - Note that this method is not intended for window control. The - peer that receives a request to stop sending content should - finish sending the current content, if any, and then wait - until it receives a Flow restart method. - - RULE: - - When a new channel is opened, it is active. Some - applications assume that channels are inactive until - started. To emulate this behaviour a client MAY open the - channel, then pause it. - - RULE: - - When sending content data in multiple frames, a peer - SHOULD monitor the channel for incoming methods and - respond to a Channel.Flow as rapidly as possible. - - RULE: - - A peer MAY use the Channel.Flow method to throttle - incoming content data for internal reasons, for example, - when exchangeing data over a slower connection. - - RULE: - - The peer that requests a Channel.Flow method MAY - disconnect and/or ban a peer that does not respect the - request. - - PARAMETERS: - active: boolean - - start/stop content frames - - If True, the peer starts sending content frames. If - False, the peer stops sending content frames. - - """ - args = AMQPWriter() - args.write_bit(active) - self._send_method((20, 20), args) - return self.wait(allowed_methods=[ - (20, 21), # Channel.flow_ok - ]) - - def _flow(self, args): - """Enable/disable flow from peer - - This method asks the peer to pause or restart the flow of - content data. This is a simple flow-control mechanism that a - peer can use to avoid oveflowing its queues or otherwise - finding itself receiving more messages than it can process. - Note that this method is not intended for window control. The - peer that receives a request to stop sending content should - finish sending the current content, if any, and then wait - until it receives a Flow restart method. - - RULE: - - When a new channel is opened, it is active. Some - applications assume that channels are inactive until - started. To emulate this behaviour a client MAY open the - channel, then pause it. - - RULE: - - When sending content data in multiple frames, a peer - SHOULD monitor the channel for incoming methods and - respond to a Channel.Flow as rapidly as possible. - - RULE: - - A peer MAY use the Channel.Flow method to throttle - incoming content data for internal reasons, for example, - when exchangeing data over a slower connection. - - RULE: - - The peer that requests a Channel.Flow method MAY - disconnect and/or ban a peer that does not respect the - request. - - PARAMETERS: - active: boolean - - start/stop content frames - - If True, the peer starts sending content frames. If - False, the peer stops sending content frames. - - """ - self.active = args.read_bit() - self._x_flow_ok(self.active) - - def _x_flow_ok(self, active): - """Confirm a flow method - - Confirms to the peer that a flow command was received and - processed. - - PARAMETERS: - active: boolean - - current flow setting - - Confirms the setting of the processed flow method: - True means the peer will start sending or continue - to send content frames; False means it will not. - - """ - args = AMQPWriter() - args.write_bit(active) - self._send_method((20, 21), args) - - def _flow_ok(self, args): - """Confirm a flow method - - Confirms to the peer that a flow command was received and - processed. - - PARAMETERS: - active: boolean - - current flow setting - - Confirms the setting of the processed flow method: - True means the peer will start sending or continue - to send content frames; False means it will not. - - """ - return args.read_bit() - - def _x_open(self): - """Open a channel for use - - This method opens a virtual connection (a channel). - - RULE: - - This method MUST NOT be called when the channel is already - open. - - PARAMETERS: - out_of_band: shortstr (DEPRECATED) - - out-of-band settings - - Configures out-of-band transfers on this channel. The - syntax and meaning of this field will be formally - defined at a later date. - - """ - if self.is_open: - return - - args = AMQPWriter() - args.write_shortstr('') # out_of_band: deprecated - self._send_method((20, 10), args) - return self.wait(allowed_methods=[ - (20, 11), # Channel.open_ok - ]) - - def _open_ok(self, args): - """Signal that the channel is ready - - This method signals to the client that the channel is ready - for use. - - """ - self.is_open = True - AMQP_LOGGER.debug('Channel open') - - ############# - # - # Exchange - # - # - # work with exchanges - # - # Exchanges match and distribute messages across queues. - # Exchanges can be configured in the server or created at runtime. - # - # GRAMMAR:: - # - # exchange = C:DECLARE S:DECLARE-OK - # / C:DELETE S:DELETE-OK - # - # RULE: - # - # The server MUST implement the direct and fanout exchange - # types, and predeclare the corresponding exchanges named - # amq.direct and amq.fanout in each virtual host. The server - # MUST also predeclare a direct exchange to act as the default - # exchange for content Publish methods and for default queue - # bindings. - # - # RULE: - # - # The server SHOULD implement the topic exchange type, and - # predeclare the corresponding exchange named amq.topic in - # each virtual host. - # - # RULE: - # - # The server MAY implement the system exchange type, and - # predeclare the corresponding exchanges named amq.system in - # each virtual host. If the client attempts to bind a queue to - # the system exchange, the server MUST raise a connection - # exception with reply code 507 (not allowed). - # - - def exchange_declare(self, exchange, type, passive=False, durable=False, - auto_delete=True, nowait=False, arguments=None): - """Declare exchange, create if needed - - This method creates an exchange if it does not already exist, - and if the exchange exists, verifies that it is of the correct - and expected class. - - RULE: - - The server SHOULD support a minimum of 16 exchanges per - virtual host and ideally, impose no limit except as - defined by available resources. - - PARAMETERS: - exchange: shortstr - - RULE: - - Exchange names starting with "amq." are reserved - for predeclared and standardised exchanges. If - the client attempts to create an exchange starting - with "amq.", the server MUST raise a channel - exception with reply code 403 (access refused). - - type: shortstr - - exchange type - - Each exchange belongs to one of a set of exchange - types implemented by the server. The exchange types - define the functionality of the exchange - i.e. how - messages are routed through it. It is not valid or - meaningful to attempt to change the type of an - existing exchange. - - RULE: - - If the exchange already exists with a different - type, the server MUST raise a connection exception - with a reply code 507 (not allowed). - - RULE: - - If the server does not support the requested - exchange type it MUST raise a connection exception - with a reply code 503 (command invalid). - - passive: boolean - - do not create exchange - - If set, the server will not create the exchange. The - client can use this to check whether an exchange - exists without modifying the server state. - - RULE: - - If set, and the exchange does not already exist, - the server MUST raise a channel exception with - reply code 404 (not found). - - durable: boolean - - request a durable exchange - - If set when creating a new exchange, the exchange will - be marked as durable. Durable exchanges remain active - when a server restarts. Non-durable exchanges - (transient exchanges) are purged if/when a server - restarts. - - RULE: - - The server MUST support both durable and transient - exchanges. - - RULE: - - The server MUST ignore the durable field if the - exchange already exists. - - auto_delete: boolean - - auto-delete when unused - - If set, the exchange is deleted when all queues have - finished using it. - - RULE: - - The server SHOULD allow for a reasonable delay - between the point when it determines that an - exchange is not being used (or no longer used), - and the point when it deletes the exchange. At - the least it must allow a client to create an - exchange and then bind a queue to it, with a small - but non-zero delay between these two actions. - - RULE: - - The server MUST ignore the auto-delete field if - the exchange already exists. - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - arguments: table - - arguments for declaration - - A set of arguments for the declaration. The syntax and - semantics of these arguments depends on the server - implementation. This field is ignored if passive is - True. - - """ - arguments = {} if arguments is None else arguments - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(exchange) - args.write_shortstr(type) - args.write_bit(passive) - args.write_bit(durable) - args.write_bit(auto_delete) - args.write_bit(False) # internal: deprecated - args.write_bit(nowait) - args.write_table(arguments) - self._send_method((40, 10), args) - - if auto_delete: - warn(VDeprecationWarning(EXCHANGE_AUTODELETE_DEPRECATED)) - - if not nowait: - return self.wait(allowed_methods=[ - (40, 11), # Channel.exchange_declare_ok - ]) - - def _exchange_declare_ok(self, args): - """Confirms an exchange declaration - - This method confirms a Declare method and confirms the name of - the exchange, essential for automatically-named exchanges. - - """ - pass - - def exchange_delete(self, exchange, if_unused=False, nowait=False): - """Delete an exchange - - This method deletes an exchange. When an exchange is deleted - all queue bindings on the exchange are cancelled. - - PARAMETERS: - exchange: shortstr - - RULE: - - The exchange MUST exist. Attempting to delete a - non-existing exchange causes a channel exception. - - if_unused: boolean - - delete only if unused - - If set, the server will only delete the exchange if it - has no queue bindings. If the exchange has queue - bindings the server does not delete it but raises a - channel exception instead. - - RULE: - - If set, the server SHOULD delete the exchange but - only if it has no queue bindings. - - RULE: - - If set, the server SHOULD raise a channel - exception if the exchange is in use. - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - """ - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(exchange) - args.write_bit(if_unused) - args.write_bit(nowait) - self._send_method((40, 20), args) - - if not nowait: - return self.wait(allowed_methods=[ - (40, 21), # Channel.exchange_delete_ok - ]) - - def _exchange_delete_ok(self, args): - """Confirm deletion of an exchange - - This method confirms the deletion of an exchange. - - """ - pass - - def exchange_bind(self, destination, source='', routing_key='', - nowait=False, arguments=None): - """This method binds an exchange to an exchange. - - RULE: - - A server MUST allow and ignore duplicate bindings - that - is, two or more bind methods for a specific exchanges, - with identical arguments - without treating these as an - error. - - RULE: - - A server MUST allow cycles of exchange bindings to be - created including allowing an exchange to be bound to - itself. - - RULE: - - A server MUST not deliver the same message more than once - to a destination exchange, even if the topology of - exchanges and bindings results in multiple (even infinite) - routes to that exchange. - - PARAMETERS: - reserved-1: short - - destination: shortstr - - Specifies the name of the destination exchange to - bind. - - RULE: - - A client MUST NOT be allowed to bind a non- - existent destination exchange. - - RULE: - - The server MUST accept a blank exchange name to - mean the default exchange. - - source: shortstr - - Specifies the name of the source exchange to bind. - - RULE: - - A client MUST NOT be allowed to bind a non- - existent source exchange. - - RULE: - - The server MUST accept a blank exchange name to - mean the default exchange. - - routing-key: shortstr - - Specifies the routing key for the binding. The routing - key is used for routing messages depending on the - exchange configuration. Not all exchanges use a - routing key - refer to the specific exchange - documentation. - - no-wait: bit - - arguments: table - - A set of arguments for the binding. The syntax and - semantics of these arguments depends on the exchange - class. - - """ - arguments = {} if arguments is None else arguments - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(destination) - args.write_shortstr(source) - args.write_shortstr(routing_key) - args.write_bit(nowait) - args.write_table(arguments) - self._send_method((40, 30), args) - - if not nowait: - return self.wait(allowed_methods=[ - (40, 31), # Channel.exchange_bind_ok - ]) - - def exchange_unbind(self, destination, source='', routing_key='', - nowait=False, arguments=None): - """This method unbinds an exchange from an exchange. - - RULE: - - If a unbind fails, the server MUST raise a connection - exception. - - PARAMETERS: - reserved-1: short - - destination: shortstr - - Specifies the name of the destination exchange to - unbind. - - RULE: - - The client MUST NOT attempt to unbind an exchange - that does not exist from an exchange. - - RULE: - - The server MUST accept a blank exchange name to - mean the default exchange. - - source: shortstr - - Specifies the name of the source exchange to unbind. - - RULE: - - The client MUST NOT attempt to unbind an exchange - from an exchange that does not exist. - - RULE: - - The server MUST accept a blank exchange name to - mean the default exchange. - - routing-key: shortstr - - Specifies the routing key of the binding to unbind. - - no-wait: bit - - arguments: table - - Specifies the arguments of the binding to unbind. - - """ - arguments = {} if arguments is None else arguments - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(destination) - args.write_shortstr(source) - args.write_shortstr(routing_key) - args.write_bit(nowait) - args.write_table(arguments) - self._send_method((40, 40), args) - - if not nowait: - return self.wait(allowed_methods=[ - (40, 51), # Channel.exchange_unbind_ok - ]) - - def _exchange_bind_ok(self, args): - """Confirm bind successful - - This method confirms that the bind was successful. - - """ - pass - - def _exchange_unbind_ok(self, args): - """Confirm unbind successful - - This method confirms that the unbind was successful. - - """ - pass - - ############# - # - # Queue - # - # - # work with queues - # - # Queues store and forward messages. Queues can be configured in - # the server or created at runtime. Queues must be attached to at - # least one exchange in order to receive messages from publishers. - # - # GRAMMAR:: - # - # queue = C:DECLARE S:DECLARE-OK - # / C:BIND S:BIND-OK - # / C:PURGE S:PURGE-OK - # / C:DELETE S:DELETE-OK - # - # RULE: - # - # A server MUST allow any content class to be sent to any - # queue, in any mix, and queue and delivery these content - # classes independently. Note that all methods that fetch - # content off queues are specific to a given content class. - # - - def queue_bind(self, queue, exchange='', routing_key='', - nowait=False, arguments=None): - """Bind queue to an exchange - - This method binds a queue to an exchange. Until a queue is - bound it will not receive any messages. In a classic - messaging model, store-and-forward queues are bound to a dest - exchange and subscription queues are bound to a dest_wild - exchange. - - RULE: - - A server MUST allow ignore duplicate bindings - that is, - two or more bind methods for a specific queue, with - identical arguments - without treating these as an error. - - RULE: - - If a bind fails, the server MUST raise a connection - exception. - - RULE: - - The server MUST NOT allow a durable queue to bind to a - transient exchange. If the client attempts this the server - MUST raise a channel exception. - - RULE: - - Bindings for durable queues are automatically durable and - the server SHOULD restore such bindings after a server - restart. - - RULE: - - The server SHOULD support at least 4 bindings per queue, - and ideally, impose no limit except as defined by - available resources. - - PARAMETERS: - queue: shortstr - - Specifies the name of the queue to bind. If the queue - name is empty, refers to the current queue for the - channel, which is the last declared queue. - - RULE: - - If the client did not previously declare a queue, - and the queue name in this method is empty, the - server MUST raise a connection exception with - reply code 530 (not allowed). - - RULE: - - If the queue does not exist the server MUST raise - a channel exception with reply code 404 (not - found). - - exchange: shortstr - - The name of the exchange to bind to. - - RULE: - - If the exchange does not exist the server MUST - raise a channel exception with reply code 404 (not - found). - - routing_key: shortstr - - message routing key - - Specifies the routing key for the binding. The - routing key is used for routing messages depending on - the exchange configuration. Not all exchanges use a - routing key - refer to the specific exchange - documentation. If the routing key is empty and the - queue name is empty, the routing key will be the - current queue for the channel, which is the last - declared queue. - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - arguments: table - - arguments for binding - - A set of arguments for the binding. The syntax and - semantics of these arguments depends on the exchange - class. - """ - arguments = {} if arguments is None else arguments - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(queue) - args.write_shortstr(exchange) - args.write_shortstr(routing_key) - args.write_bit(nowait) - args.write_table(arguments) - self._send_method((50, 20), args) - - if not nowait: - return self.wait(allowed_methods=[ - (50, 21), # Channel.queue_bind_ok - ]) - - def _queue_bind_ok(self, args): - """Confirm bind successful - - This method confirms that the bind was successful. - - """ - pass - - def queue_unbind(self, queue, exchange, routing_key='', - nowait=False, arguments=None): - """Unbind a queue from an exchange - - This method unbinds a queue from an exchange. - - RULE: - - If a unbind fails, the server MUST raise a connection exception. - - PARAMETERS: - queue: shortstr - - Specifies the name of the queue to unbind. - - RULE: - - The client MUST either specify a queue name or have - previously declared a queue on the same channel - - RULE: - - The client MUST NOT attempt to unbind a queue that - does not exist. - - exchange: shortstr - - The name of the exchange to unbind from. - - RULE: - - The client MUST NOT attempt to unbind a queue from an - exchange that does not exist. - - RULE: - - The server MUST accept a blank exchange name to mean - the default exchange. - - routing_key: shortstr - - routing key of binding - - Specifies the routing key of the binding to unbind. - - arguments: table - - arguments of binding - - Specifies the arguments of the binding to unbind. - - """ - arguments = {} if arguments is None else arguments - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(queue) - args.write_shortstr(exchange) - args.write_shortstr(routing_key) - #args.write_bit(nowait) - args.write_table(arguments) - self._send_method((50, 50), args) - - if not nowait: - return self.wait(allowed_methods=[ - (50, 51), # Channel.queue_unbind_ok - ]) - - def _queue_unbind_ok(self, args): - """Confirm unbind successful - - This method confirms that the unbind was successful. - - """ - pass - - def queue_declare(self, queue='', passive=False, durable=False, - exclusive=False, auto_delete=True, nowait=False, - arguments=None): - """Declare queue, create if needed - - This method creates or checks a queue. When creating a new - queue the client can specify various properties that control - the durability of the queue and its contents, and the level of - sharing for the queue. - - RULE: - - The server MUST create a default binding for a newly- - created queue to the default exchange, which is an - exchange of type 'direct'. - - RULE: - - The server SHOULD support a minimum of 256 queues per - virtual host and ideally, impose no limit except as - defined by available resources. - - PARAMETERS: - queue: shortstr - - RULE: - - The queue name MAY be empty, in which case the - server MUST create a new queue with a unique - generated name and return this to the client in - the Declare-Ok method. - - RULE: - - Queue names starting with "amq." are reserved for - predeclared and standardised server queues. If - the queue name starts with "amq." and the passive - option is False, the server MUST raise a connection - exception with reply code 403 (access refused). - - passive: boolean - - do not create queue - - If set, the server will not create the queue. The - client can use this to check whether a queue exists - without modifying the server state. - - RULE: - - If set, and the queue does not already exist, the - server MUST respond with a reply code 404 (not - found) and raise a channel exception. - - durable: boolean - - request a durable queue - - If set when creating a new queue, the queue will be - marked as durable. Durable queues remain active when - a server restarts. Non-durable queues (transient - queues) are purged if/when a server restarts. Note - that durable queues do not necessarily hold persistent - messages, although it does not make sense to send - persistent messages to a transient queue. - - RULE: - - The server MUST recreate the durable queue after a - restart. - - RULE: - - The server MUST support both durable and transient - queues. - - RULE: - - The server MUST ignore the durable field if the - queue already exists. - - exclusive: boolean - - request an exclusive queue - - Exclusive queues may only be consumed from by the - current connection. Setting the 'exclusive' flag - always implies 'auto-delete'. - - RULE: - - The server MUST support both exclusive (private) - and non-exclusive (shared) queues. - - RULE: - - The server MUST raise a channel exception if - 'exclusive' is specified and the queue already - exists and is owned by a different connection. - - auto_delete: boolean - - auto-delete queue when unused - - If set, the queue is deleted when all consumers have - finished using it. Last consumer can be cancelled - either explicitly or because its channel is closed. If - there was no consumer ever on the queue, it won't be - deleted. - - RULE: - - The server SHOULD allow for a reasonable delay - between the point when it determines that a queue - is not being used (or no longer used), and the - point when it deletes the queue. At the least it - must allow a client to create a queue and then - create a consumer to read from it, with a small - but non-zero delay between these two actions. The - server should equally allow for clients that may - be disconnected prematurely, and wish to re- - consume from the same queue without losing - messages. We would recommend a configurable - timeout, with a suitable default value being one - minute. - - RULE: - - The server MUST ignore the auto-delete field if - the queue already exists. - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - arguments: table - - arguments for declaration - - A set of arguments for the declaration. The syntax and - semantics of these arguments depends on the server - implementation. This field is ignored if passive is - True. - - Returns a tuple containing 3 items: - the name of the queue (essential for automatically-named queues) - message count - consumer count - - """ - arguments = {} if arguments is None else arguments - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(queue) - args.write_bit(passive) - args.write_bit(durable) - args.write_bit(exclusive) - args.write_bit(auto_delete) - args.write_bit(nowait) - args.write_table(arguments) - self._send_method((50, 10), args) - - if not nowait: - return self.wait(allowed_methods=[ - (50, 11), # Channel.queue_declare_ok - ]) - - def _queue_declare_ok(self, args): - """Confirms a queue definition - - This method confirms a Declare method and confirms the name of - the queue, essential for automatically-named queues. - - PARAMETERS: - queue: shortstr - - Reports the name of the queue. If the server generated - a queue name, this field contains that name. - - message_count: long - - number of messages in queue - - Reports the number of messages in the queue, which - will be zero for newly-created queues. - - consumer_count: long - - number of consumers - - Reports the number of active consumers for the queue. - Note that consumers can suspend activity - (Channel.Flow) in which case they do not appear in - this count. - - """ - return queue_declare_ok_t( - args.read_shortstr(), - args.read_long(), - args.read_long(), - ) - - def queue_delete(self, queue='', - if_unused=False, if_empty=False, nowait=False): - """Delete a queue - - This method deletes a queue. When a queue is deleted any - pending messages are sent to a dead-letter queue if this is - defined in the server configuration, and all consumers on the - queue are cancelled. - - RULE: - - The server SHOULD use a dead-letter queue to hold messages - that were pending on a deleted queue, and MAY provide - facilities for a system administrator to move these - messages back to an active queue. - - PARAMETERS: - queue: shortstr - - Specifies the name of the queue to delete. If the - queue name is empty, refers to the current queue for - the channel, which is the last declared queue. - - RULE: - - If the client did not previously declare a queue, - and the queue name in this method is empty, the - server MUST raise a connection exception with - reply code 530 (not allowed). - - RULE: - - The queue must exist. Attempting to delete a non- - existing queue causes a channel exception. - - if_unused: boolean - - delete only if unused - - If set, the server will only delete the queue if it - has no consumers. If the queue has consumers the - server does does not delete it but raises a channel - exception instead. - - RULE: - - The server MUST respect the if-unused flag when - deleting a queue. - - if_empty: boolean - - delete only if empty - - If set, the server will only delete the queue if it - has no messages. If the queue is not empty the server - raises a channel exception. - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - """ - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(queue) - args.write_bit(if_unused) - args.write_bit(if_empty) - args.write_bit(nowait) - self._send_method((50, 40), args) - - if not nowait: - return self.wait(allowed_methods=[ - (50, 41), # Channel.queue_delete_ok - ]) - - def _queue_delete_ok(self, args): - """Confirm deletion of a queue - - This method confirms the deletion of a queue. - - PARAMETERS: - message_count: long - - number of messages purged - - Reports the number of messages purged. - - """ - return args.read_long() - - def queue_purge(self, queue='', nowait=False): - """Purge a queue - - This method removes all messages from a queue. It does not - cancel consumers. Purged messages are deleted without any - formal "undo" mechanism. - - RULE: - - A call to purge MUST result in an empty queue. - - RULE: - - On transacted channels the server MUST not purge messages - that have already been sent to a client but not yet - acknowledged. - - RULE: - - The server MAY implement a purge queue or log that allows - system administrators to recover accidentally-purged - messages. The server SHOULD NOT keep purged messages in - the same storage spaces as the live messages since the - volumes of purged messages may get very large. - - PARAMETERS: - queue: shortstr - - Specifies the name of the queue to purge. If the - queue name is empty, refers to the current queue for - the channel, which is the last declared queue. - - RULE: - - If the client did not previously declare a queue, - and the queue name in this method is empty, the - server MUST raise a connection exception with - reply code 530 (not allowed). - - RULE: - - The queue must exist. Attempting to purge a non- - existing queue causes a channel exception. - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - if nowait is False, returns a message_count - - """ - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(queue) - args.write_bit(nowait) - self._send_method((50, 30), args) - - if not nowait: - return self.wait(allowed_methods=[ - (50, 31), # Channel.queue_purge_ok - ]) - - def _queue_purge_ok(self, args): - """Confirms a queue purge - - This method confirms the purge of a queue. - - PARAMETERS: - message_count: long - - number of messages purged - - Reports the number of messages purged. - - """ - return args.read_long() - - ############# - # - # Basic - # - # - # work with basic content - # - # The Basic class provides methods that support an industry- - # standard messaging model. - # - # GRAMMAR:: - # - # basic = C:QOS S:QOS-OK - # / C:CONSUME S:CONSUME-OK - # / C:CANCEL S:CANCEL-OK - # / C:PUBLISH content - # / S:RETURN content - # / S:DELIVER content - # / C:GET ( S:GET-OK content / S:GET-EMPTY ) - # / C:ACK - # / C:REJECT - # - # RULE: - # - # The server SHOULD respect the persistent property of basic - # messages and SHOULD make a best-effort to hold persistent - # basic messages on a reliable storage mechanism. - # - # RULE: - # - # The server MUST NOT discard a persistent basic message in - # case of a queue overflow. The server MAY use the - # Channel.Flow method to slow or stop a basic message - # publisher when necessary. - # - # RULE: - # - # The server MAY overflow non-persistent basic messages to - # persistent storage and MAY discard or dead-letter non- - # persistent basic messages on a priority basis if the queue - # size exceeds some configured limit. - # - # RULE: - # - # The server MUST implement at least 2 priority levels for - # basic messages, where priorities 0-4 and 5-9 are treated as - # two distinct levels. The server MAY implement up to 10 - # priority levels. - # - # RULE: - # - # The server MUST deliver messages of the same priority in - # order irrespective of their individual persistence. - # - # RULE: - # - # The server MUST support both automatic and explicit - # acknowledgements on Basic content. - # - - def basic_ack(self, delivery_tag, multiple=False): - """Acknowledge one or more messages - - This method acknowledges one or more messages delivered via - the Deliver or Get-Ok methods. The client can ask to confirm - a single message or a set of messages up to and including a - specific message. - - PARAMETERS: - delivery_tag: longlong - - server-assigned delivery tag - - The server-assigned and channel-specific delivery tag - - RULE: - - The delivery tag is valid only within the channel - from which the message was received. I.e. a client - MUST NOT receive a message on one channel and then - acknowledge it on another. - - RULE: - - The server MUST NOT use a zero value for delivery - tags. Zero is reserved for client use, meaning "all - messages so far received". - - multiple: boolean - - acknowledge multiple messages - - If set to True, the delivery tag is treated as "up to - and including", so that the client can acknowledge - multiple messages with a single method. If set to - False, the delivery tag refers to a single message. - If the multiple field is True, and the delivery tag - is zero, tells the server to acknowledge all - outstanding mesages. - - RULE: - - The server MUST validate that a non-zero delivery- - tag refers to an delivered message, and raise a - channel exception if this is not the case. - - """ - args = AMQPWriter() - args.write_longlong(delivery_tag) - args.write_bit(multiple) - self._send_method((60, 80), args) - - def basic_cancel(self, consumer_tag, nowait=False): - """End a queue consumer - - This method cancels a consumer. This does not affect already - delivered messages, but it does mean the server will not send - any more messages for that consumer. The client may receive - an abitrary number of messages in between sending the cancel - method and receiving the cancel-ok reply. - - RULE: - - If the queue no longer exists when the client sends a - cancel command, or the consumer has been cancelled for - other reasons, this command has no effect. - - PARAMETERS: - consumer_tag: shortstr - - consumer tag - - Identifier for the consumer, valid within the current - connection. - - RULE: - - The consumer tag is valid only within the channel - from which the consumer was created. I.e. a client - MUST NOT create a consumer in one channel and then - use it in another. - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - """ - if self.connection is not None: - self.no_ack_consumers.discard(consumer_tag) - args = AMQPWriter() - args.write_shortstr(consumer_tag) - args.write_bit(nowait) - self._send_method((60, 30), args) - return self.wait(allowed_methods=[ - (60, 31), # Channel.basic_cancel_ok - ]) - - def _basic_cancel_notify(self, args): - """Consumer cancelled by server. - - Most likely the queue was deleted. - - """ - consumer_tag = args.read_shortstr() - callback = self._on_cancel(consumer_tag) - if callback: - callback(consumer_tag) - else: - raise ConsumerCancelled(consumer_tag, (60, 30)) - - def _basic_cancel_ok(self, args): - """Confirm a cancelled consumer - - This method confirms that the cancellation was completed. - - PARAMETERS: - consumer_tag: shortstr - - consumer tag - - Identifier for the consumer, valid within the current - connection. - - RULE: - - The consumer tag is valid only within the channel - from which the consumer was created. I.e. a client - MUST NOT create a consumer in one channel and then - use it in another. - - """ - consumer_tag = args.read_shortstr() - self._on_cancel(consumer_tag) - - def _on_cancel(self, consumer_tag): - self.callbacks.pop(consumer_tag, None) - return self.cancel_callbacks.pop(consumer_tag, None) - - def basic_consume(self, queue='', consumer_tag='', no_local=False, - no_ack=False, exclusive=False, nowait=False, - callback=None, arguments=None, on_cancel=None): - """Start a queue consumer - - This method asks the server to start a "consumer", which is a - transient request for messages from a specific queue. - Consumers last as long as the channel they were created on, or - until the client cancels them. - - RULE: - - The server SHOULD support at least 16 consumers per queue, - unless the queue was declared as private, and ideally, - impose no limit except as defined by available resources. - - PARAMETERS: - queue: shortstr - - Specifies the name of the queue to consume from. If - the queue name is null, refers to the current queue - for the channel, which is the last declared queue. - - RULE: - - If the client did not previously declare a queue, - and the queue name in this method is empty, the - server MUST raise a connection exception with - reply code 530 (not allowed). - - consumer_tag: shortstr - - Specifies the identifier for the consumer. The - consumer tag is local to a connection, so two clients - can use the same consumer tags. If this field is empty - the server will generate a unique tag. - - RULE: - - The tag MUST NOT refer to an existing consumer. If - the client attempts to create two consumers with - the same non-empty tag the server MUST raise a - connection exception with reply code 530 (not - allowed). - - no_local: boolean - - do not deliver own messages - - If the no-local field is set the server will not send - messages to the client that published them. - - no_ack: boolean - - no acknowledgement needed - - If this field is set the server does not expect - acknowledgments for messages. That is, when a message - is delivered to the client the server automatically and - silently acknowledges it on behalf of the client. This - functionality increases performance but at the cost of - reliability. Messages can get lost if a client dies - before it can deliver them to the application. - - exclusive: boolean - - request exclusive access - - Request exclusive consumer access, meaning only this - consumer can access the queue. - - RULE: - - If the server cannot grant exclusive access to the - queue when asked, - because there are other - consumers active - it MUST raise a channel - exception with return code 403 (access refused). - - nowait: boolean - - do not send a reply method - - If set, the server will not respond to the method. The - client should not wait for a reply method. If the - server could not complete the method it will raise a - channel or connection exception. - - callback: Python callable - - function/method called with each delivered message - - For each message delivered by the broker, the - callable will be called with a Message object - as the single argument. If no callable is specified, - messages are quietly discarded, no_ack should probably - be set to True in that case. - - """ - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(queue) - args.write_shortstr(consumer_tag) - args.write_bit(no_local) - args.write_bit(no_ack) - args.write_bit(exclusive) - args.write_bit(nowait) - args.write_table(arguments or {}) - self._send_method((60, 20), args) - - if not nowait: - consumer_tag = self.wait(allowed_methods=[ - (60, 21), # Channel.basic_consume_ok - ]) - - self.callbacks[consumer_tag] = callback - - if on_cancel: - self.cancel_callbacks[consumer_tag] = on_cancel - if no_ack: - self.no_ack_consumers.add(consumer_tag) - - return consumer_tag - - def _basic_consume_ok(self, args): - """Confirm a new consumer - - The server provides the client with a consumer tag, which is - used by the client for methods called on the consumer at a - later stage. - - PARAMETERS: - consumer_tag: shortstr - - Holds the consumer tag specified by the client or - provided by the server. - - """ - return args.read_shortstr() - - def _basic_deliver(self, args, msg): - """Notify the client of a consumer message - - This method delivers a message to the client, via a consumer. - In the asynchronous message delivery model, the client starts - a consumer using the Consume method, then the server responds - with Deliver methods as and when messages arrive for that - consumer. - - RULE: - - The server SHOULD track the number of times a message has - been delivered to clients and when a message is - redelivered a certain number of times - e.g. 5 times - - without being acknowledged, the server SHOULD consider the - message to be unprocessable (possibly causing client - applications to abort), and move the message to a dead - letter queue. - - PARAMETERS: - consumer_tag: shortstr - - consumer tag - - Identifier for the consumer, valid within the current - connection. - - RULE: - - The consumer tag is valid only within the channel - from which the consumer was created. I.e. a client - MUST NOT create a consumer in one channel and then - use it in another. - - delivery_tag: longlong - - server-assigned delivery tag - - The server-assigned and channel-specific delivery tag - - RULE: - - The delivery tag is valid only within the channel - from which the message was received. I.e. a client - MUST NOT receive a message on one channel and then - acknowledge it on another. - - RULE: - - The server MUST NOT use a zero value for delivery - tags. Zero is reserved for client use, meaning "all - messages so far received". - - redelivered: boolean - - message is being redelivered - - This indicates that the message has been previously - delivered to this or another client. - - exchange: shortstr - - Specifies the name of the exchange that the message - was originally published to. - - routing_key: shortstr - - Message routing key - - Specifies the routing key name specified when the - message was published. - - """ - consumer_tag = args.read_shortstr() - delivery_tag = args.read_longlong() - redelivered = args.read_bit() - exchange = args.read_shortstr() - routing_key = args.read_shortstr() - - msg.channel = self - msg.delivery_info = { - 'consumer_tag': consumer_tag, - 'delivery_tag': delivery_tag, - 'redelivered': redelivered, - 'exchange': exchange, - 'routing_key': routing_key, - } - - try: - fun = self.callbacks[consumer_tag] - except KeyError: - pass - else: - fun(msg) - - def basic_get(self, queue='', no_ack=False): - """Direct access to a queue - - This method provides a direct access to the messages in a - queue using a synchronous dialogue that is designed for - specific types of application where synchronous functionality - is more important than performance. - - PARAMETERS: - queue: shortstr - - Specifies the name of the queue to consume from. If - the queue name is null, refers to the current queue - for the channel, which is the last declared queue. - - RULE: - - If the client did not previously declare a queue, - and the queue name in this method is empty, the - server MUST raise a connection exception with - reply code 530 (not allowed). - - no_ack: boolean - - no acknowledgement needed - - If this field is set the server does not expect - acknowledgments for messages. That is, when a message - is delivered to the client the server automatically and - silently acknowledges it on behalf of the client. This - functionality increases performance but at the cost of - reliability. Messages can get lost if a client dies - before it can deliver them to the application. - - Non-blocking, returns a message object, or None. - - """ - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(queue) - args.write_bit(no_ack) - self._send_method((60, 70), args) - return self.wait(allowed_methods=[ - (60, 71), # Channel.basic_get_ok - (60, 72), # Channel.basic_get_empty - ]) - - def _basic_get_empty(self, args): - """Indicate no messages available - - This method tells the client that the queue has no messages - available for the client. - - PARAMETERS: - cluster_id: shortstr - - Cluster id - - For use by cluster applications, should not be used by - client applications. - - """ - cluster_id = args.read_shortstr() # noqa - - def _basic_get_ok(self, args, msg): - """Provide client with a message - - This method delivers a message to the client following a get - method. A message delivered by 'get-ok' must be acknowledged - unless the no-ack option was set in the get method. - - PARAMETERS: - delivery_tag: longlong - - server-assigned delivery tag - - The server-assigned and channel-specific delivery tag - - RULE: - - The delivery tag is valid only within the channel - from which the message was received. I.e. a client - MUST NOT receive a message on one channel and then - acknowledge it on another. - - RULE: - - The server MUST NOT use a zero value for delivery - tags. Zero is reserved for client use, meaning "all - messages so far received". - - redelivered: boolean - - message is being redelivered - - This indicates that the message has been previously - delivered to this or another client. - - exchange: shortstr - - Specifies the name of the exchange that the message - was originally published to. If empty, the message - was published to the default exchange. - - routing_key: shortstr - - Message routing key - - Specifies the routing key name specified when the - message was published. - - message_count: long - - number of messages pending - - This field reports the number of messages pending on - the queue, excluding the message being delivered. - Note that this figure is indicative, not reliable, and - can change arbitrarily as messages are added to the - queue and removed by other clients. - - """ - delivery_tag = args.read_longlong() - redelivered = args.read_bit() - exchange = args.read_shortstr() - routing_key = args.read_shortstr() - message_count = args.read_long() - - msg.channel = self - msg.delivery_info = { - 'delivery_tag': delivery_tag, - 'redelivered': redelivered, - 'exchange': exchange, - 'routing_key': routing_key, - 'message_count': message_count - } - return msg - - def _basic_publish(self, msg, exchange='', routing_key='', - mandatory=False, immediate=False): - """Publish a message - - This method publishes a message to a specific exchange. The - message will be routed to queues as defined by the exchange - configuration and distributed to any active consumers when the - transaction, if any, is committed. - - PARAMETERS: - exchange: shortstr - - Specifies the name of the exchange to publish to. The - exchange name can be empty, meaning the default - exchange. If the exchange name is specified, and that - exchange does not exist, the server will raise a - channel exception. - - RULE: - - The server MUST accept a blank exchange name to - mean the default exchange. - - RULE: - - The exchange MAY refuse basic content in which - case it MUST raise a channel exception with reply - code 540 (not implemented). - - routing_key: shortstr - - Message routing key - - Specifies the routing key for the message. The - routing key is used for routing messages depending on - the exchange configuration. - - mandatory: boolean - - indicate mandatory routing - - This flag tells the server how to react if the message - cannot be routed to a queue. If this flag is True, the - server will return an unroutable message with a Return - method. If this flag is False, the server silently - drops the message. - - RULE: - - The server SHOULD implement the mandatory flag. - - immediate: boolean - - request immediate delivery - - This flag tells the server how to react if the message - cannot be routed to a queue consumer immediately. If - this flag is set, the server will return an - undeliverable message with a Return method. If this - flag is zero, the server will queue the message, but - with no guarantee that it will ever be consumed. - - RULE: - - The server SHOULD implement the immediate flag. - - """ - args = AMQPWriter() - args.write_short(0) - args.write_shortstr(exchange) - args.write_shortstr(routing_key) - args.write_bit(mandatory) - args.write_bit(immediate) - - self._send_method((60, 40), args, msg) - basic_publish = _basic_publish - - def basic_publish_confirm(self, *args, **kwargs): - if not self._confirm_selected: - self._confirm_selected = True - self.confirm_select() - ret = self._basic_publish(*args, **kwargs) - self.wait([(60, 80)]) - return ret - - def basic_qos(self, prefetch_size, prefetch_count, a_global): - """Specify quality of service - - This method requests a specific quality of service. The QoS - can be specified for the current channel or for all channels - on the connection. The particular properties and semantics of - a qos method always depend on the content class semantics. - Though the qos method could in principle apply to both peers, - it is currently meaningful only for the server. - - PARAMETERS: - prefetch_size: long - - prefetch window in octets - - The client can request that messages be sent in - advance so that when the client finishes processing a - message, the following message is already held - locally, rather than needing to be sent down the - channel. Prefetching gives a performance improvement. - This field specifies the prefetch window size in - octets. The server will send a message in advance if - it is equal to or smaller in size than the available - prefetch size (and also falls into other prefetch - limits). May be set to zero, meaning "no specific - limit", although other prefetch limits may still - apply. The prefetch-size is ignored if the no-ack - option is set. - - RULE: - - The server MUST ignore this setting when the - client is not processing any messages - i.e. the - prefetch size does not limit the transfer of - single messages to a client, only the sending in - advance of more messages while the client still - has one or more unacknowledged messages. - - prefetch_count: short - - prefetch window in messages - - Specifies a prefetch window in terms of whole - messages. This field may be used in combination with - the prefetch-size field; a message will only be sent - in advance if both prefetch windows (and those at the - channel and connection level) allow it. The prefetch- - count is ignored if the no-ack option is set. - - RULE: - - The server MAY send less data in advance than - allowed by the client's specified prefetch windows - but it MUST NOT send more. - - a_global: boolean - - apply to entire connection - - By default the QoS settings apply to the current - channel only. If this field is set, they are applied - to the entire connection. - - """ - args = AMQPWriter() - args.write_long(prefetch_size) - args.write_short(prefetch_count) - args.write_bit(a_global) - self._send_method((60, 10), args) - return self.wait(allowed_methods=[ - (60, 11), # Channel.basic_qos_ok - ]) - - def _basic_qos_ok(self, args): - """Confirm the requested qos - - This method tells the client that the requested QoS levels - could be handled by the server. The requested QoS applies to - all active consumers until a new QoS is defined. - - """ - pass - - def basic_recover(self, requeue=False): - """Redeliver unacknowledged messages - - This method asks the broker to redeliver all unacknowledged - messages on a specified channel. Zero or more messages may be - redelivered. This method is only allowed on non-transacted - channels. - - RULE: - - The server MUST set the redelivered flag on all messages - that are resent. - - RULE: - - The server MUST raise a channel exception if this is - called on a transacted channel. - - PARAMETERS: - requeue: boolean - - requeue the message - - If this field is False, the message will be redelivered - to the original recipient. If this field is True, the - server will attempt to requeue the message, - potentially then delivering it to an alternative - subscriber. - - """ - args = AMQPWriter() - args.write_bit(requeue) - self._send_method((60, 110), args) - - def basic_recover_async(self, requeue=False): - args = AMQPWriter() - args.write_bit(requeue) - self._send_method((60, 100), args) - - def _basic_recover_ok(self, args): - """In 0-9-1 the deprecated recover solicits a response.""" - pass - - def basic_reject(self, delivery_tag, requeue): - """Reject an incoming message - - This method allows a client to reject a message. It can be - used to interrupt and cancel large incoming messages, or - return untreatable messages to their original queue. - - RULE: - - The server SHOULD be capable of accepting and process the - Reject method while sending message content with a Deliver - or Get-Ok method. I.e. the server should read and process - incoming methods while sending output frames. To cancel a - partially-send content, the server sends a content body - frame of size 1 (i.e. with no data except the frame-end - octet). - - RULE: - - The server SHOULD interpret this method as meaning that - the client is unable to process the message at this time. - - RULE: - - A client MUST NOT use this method as a means of selecting - messages to process. A rejected message MAY be discarded - or dead-lettered, not necessarily passed to another - client. - - PARAMETERS: - delivery_tag: longlong - - server-assigned delivery tag - - The server-assigned and channel-specific delivery tag - - RULE: - - The delivery tag is valid only within the channel - from which the message was received. I.e. a client - MUST NOT receive a message on one channel and then - acknowledge it on another. - - RULE: - - The server MUST NOT use a zero value for delivery - tags. Zero is reserved for client use, meaning "all - messages so far received". - - requeue: boolean - - requeue the message - - If this field is False, the message will be discarded. - If this field is True, the server will attempt to - requeue the message. - - RULE: - - The server MUST NOT deliver the message to the - same client within the context of the current - channel. The recommended strategy is to attempt - to deliver the message to an alternative consumer, - and if that is not possible, to move the message - to a dead-letter queue. The server MAY use more - sophisticated tracking to hold the message on the - queue and redeliver it to the same client at a - later stage. - - """ - args = AMQPWriter() - args.write_longlong(delivery_tag) - args.write_bit(requeue) - self._send_method((60, 90), args) - - def _basic_return(self, args, msg): - """Return a failed message - - This method returns an undeliverable message that was - published with the "immediate" flag set, or an unroutable - message published with the "mandatory" flag set. The reply - code and text provide information about the reason that the - message was undeliverable. - - PARAMETERS: - reply_code: short - - The reply code. The AMQ reply codes are defined in AMQ - RFC 011. - - reply_text: shortstr - - The localised reply text. This text can be logged as an - aid to resolving issues. - - exchange: shortstr - - Specifies the name of the exchange that the message - was originally published to. - - routing_key: shortstr - - Message routing key - - Specifies the routing key name specified when the - message was published. - - """ - self.returned_messages.put(basic_return_t( - args.read_short(), - args.read_shortstr(), - args.read_shortstr(), - args.read_shortstr(), - msg, - )) - - ############# - # - # Tx - # - # - # work with standard transactions - # - # Standard transactions provide so-called "1.5 phase commit". We - # can ensure that work is never lost, but there is a chance of - # confirmations being lost, so that messages may be resent. - # Applications that use standard transactions must be able to - # detect and ignore duplicate messages. - # - # GRAMMAR:: - # - # tx = C:SELECT S:SELECT-OK - # / C:COMMIT S:COMMIT-OK - # / C:ROLLBACK S:ROLLBACK-OK - # - # RULE: - # - # An client using standard transactions SHOULD be able to - # track all messages received within a reasonable period, and - # thus detect and reject duplicates of the same message. It - # SHOULD NOT pass these to the application layer. - # - # - - def tx_commit(self): - """Commit the current transaction - - This method commits all messages published and acknowledged in - the current transaction. A new transaction starts immediately - after a commit. - - """ - self._send_method((90, 20)) - return self.wait(allowed_methods=[ - (90, 21), # Channel.tx_commit_ok - ]) - - def _tx_commit_ok(self, args): - """Confirm a successful commit - - This method confirms to the client that the commit succeeded. - Note that if a commit fails, the server raises a channel - exception. - - """ - pass - - def tx_rollback(self): - """Abandon the current transaction - - This method abandons all messages published and acknowledged - in the current transaction. A new transaction starts - immediately after a rollback. - - """ - self._send_method((90, 30)) - return self.wait(allowed_methods=[ - (90, 31), # Channel.tx_rollback_ok - ]) - - def _tx_rollback_ok(self, args): - """Confirm a successful rollback - - This method confirms to the client that the rollback - succeeded. Note that if an rollback fails, the server raises a - channel exception. - - """ - pass - - def tx_select(self): - """Select standard transaction mode - - This method sets the channel to use standard transactions. - The client must use this method at least once on a channel - before using the Commit or Rollback methods. - - """ - self._send_method((90, 10)) - return self.wait(allowed_methods=[ - (90, 11), # Channel.tx_select_ok - ]) - - def _tx_select_ok(self, args): - """Confirm transaction mode - - This method confirms to the client that the channel was - successfully set to use standard transactions. - - """ - pass - - def confirm_select(self, nowait=False): - """Enables publisher confirms for this channel (an RabbitMQ - extension). - - Can now be used if the channel is in transactional mode. - - :param nowait: - If set, the server will not respond to the method. - The client should not wait for a reply method. If the - server could not complete the method it will raise a channel - or connection exception. - - """ - args = AMQPWriter() - args.write_bit(nowait) - - self._send_method((85, 10), args) - if not nowait: - self.wait(allowed_methods=[ - (85, 11), # Confirm.select_ok - ]) - - def _confirm_select_ok(self, args): - """With this method the broker confirms to the client that - the channel is now using publisher confirms.""" - pass - - def _basic_ack_recv(self, args): - delivery_tag = args.read_longlong() - multiple = args.read_bit() - for callback in self.events['basic_ack']: - callback(delivery_tag, multiple) - - _METHOD_MAP = { - (20, 11): _open_ok, - (20, 20): _flow, - (20, 21): _flow_ok, - (20, 40): _close, - (20, 41): _close_ok, - (40, 11): _exchange_declare_ok, - (40, 21): _exchange_delete_ok, - (40, 31): _exchange_bind_ok, - (40, 51): _exchange_unbind_ok, - (50, 11): _queue_declare_ok, - (50, 21): _queue_bind_ok, - (50, 31): _queue_purge_ok, - (50, 41): _queue_delete_ok, - (50, 51): _queue_unbind_ok, - (60, 11): _basic_qos_ok, - (60, 21): _basic_consume_ok, - (60, 30): _basic_cancel_notify, - (60, 31): _basic_cancel_ok, - (60, 50): _basic_return, - (60, 60): _basic_deliver, - (60, 71): _basic_get_ok, - (60, 72): _basic_get_empty, - (60, 80): _basic_ack_recv, - (60, 111): _basic_recover_ok, - (85, 11): _confirm_select_ok, - (90, 11): _tx_select_ok, - (90, 21): _tx_commit_ok, - (90, 31): _tx_rollback_ok, - } - - _IMMEDIATE_METHODS = [ - (60, 50), # basic_return - ] diff --git a/awx/lib/site-packages/amqp/connection.py b/awx/lib/site-packages/amqp/connection.py deleted file mode 100644 index c93d91fedc..0000000000 --- a/awx/lib/site-packages/amqp/connection.py +++ /dev/null @@ -1,1004 +0,0 @@ -"""AMQP Connections""" -# Copyright (C) 2007-2008 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -import logging -import socket - -from array import array -try: - from ssl import SSLError -except ImportError: - class SSLError(Exception): # noqa - pass - -from . import __version__ -from .abstract_channel import AbstractChannel -from .channel import Channel -from .exceptions import ( - AMQPNotImplementedError, ChannelError, ResourceError, - ConnectionForced, ConnectionError, error_for_code, - RecoverableConnectionError, RecoverableChannelError, -) -from .five import items, range, values, monotonic -from .method_framing import MethodReader, MethodWriter -from .serialization import AMQPWriter -from .transport import create_transport - -HAS_MSG_PEEK = hasattr(socket, 'MSG_PEEK') - -START_DEBUG_FMT = """ -Start from server, version: %d.%d, properties: %s, mechanisms: %s, locales: %s -""".strip() - -__all__ = ['Connection'] - -# -# Client property info that gets sent to the server on connection startup -# -LIBRARY_PROPERTIES = { - 'product': 'py-amqp', - 'product_version': __version__, - 'capabilities': {}, -} - -AMQP_LOGGER = logging.getLogger('amqp') - - -class Connection(AbstractChannel): - """The connection class provides methods for a client to establish a - network connection to a server, and for both peers to operate the - connection thereafter. - - GRAMMAR:: - - connection = open-connection *use-connection close-connection - open-connection = C:protocol-header - S:START C:START-OK - *challenge - S:TUNE C:TUNE-OK - C:OPEN S:OPEN-OK - challenge = S:SECURE C:SECURE-OK - use-connection = *channel - close-connection = C:CLOSE S:CLOSE-OK - / S:CLOSE C:CLOSE-OK - - """ - Channel = Channel - - #: Final heartbeat interval value (in float seconds) after negotiation - heartbeat = None - - #: Original heartbeat interval value proposed by client. - client_heartbeat = None - - #: Original heartbeat interval proposed by server. - server_heartbeat = None - - #: Time of last heartbeat sent (in monotonic time, if available). - last_heartbeat_sent = 0 - - #: Time of last heartbeat received (in monotonic time, if available). - last_heartbeat_received = 0 - - #: Number of bytes sent to socket at the last heartbeat check. - prev_sent = None - - #: Number of bytes received from socket at the last heartbeat check. - prev_recv = None - - def __init__(self, host='localhost', userid='guest', password='guest', - login_method='AMQPLAIN', login_response=None, - virtual_host='/', locale='en_US', client_properties=None, - ssl=False, connect_timeout=None, channel_max=None, - frame_max=None, heartbeat=0, on_blocked=None, - on_unblocked=None, confirm_publish=False, **kwargs): - """Create a connection to the specified host, which should be - a 'host[:port]', such as 'localhost', or '1.2.3.4:5672' - (defaults to 'localhost', if a port is not specified then - 5672 is used) - - If login_response is not specified, one is built up for you from - userid and password if they are present. - - The 'ssl' parameter may be simply True/False, or for Python >= 2.6 - a dictionary of options to pass to ssl.wrap_socket() such as - requiring certain certificates. - - """ - channel_max = channel_max or 65535 - frame_max = frame_max or 131072 - if (login_response is None) \ - and (userid is not None) \ - and (password is not None): - login_response = AMQPWriter() - login_response.write_table({'LOGIN': userid, 'PASSWORD': password}) - login_response = login_response.getvalue()[4:] # Skip the length - # at the beginning - - d = dict(LIBRARY_PROPERTIES, **client_properties or {}) - self._method_override = {(60, 50): self._dispatch_basic_return} - - self.channels = {} - # The connection object itself is treated as channel 0 - super(Connection, self).__init__(self, 0) - - self.transport = None - - # Properties set in the Tune method - self.channel_max = channel_max - self.frame_max = frame_max - self.client_heartbeat = heartbeat - - self.confirm_publish = confirm_publish - - # Callbacks - self.on_blocked = on_blocked - self.on_unblocked = on_unblocked - - self._avail_channel_ids = array('H', range(self.channel_max, 0, -1)) - - # Properties set in the Start method - self.version_major = 0 - self.version_minor = 0 - self.server_properties = {} - self.mechanisms = [] - self.locales = [] - - # Let the transport.py module setup the actual - # socket connection to the broker. - # - self.transport = create_transport(host, connect_timeout, ssl) - - self.method_reader = MethodReader(self.transport) - self.method_writer = MethodWriter(self.transport, self.frame_max) - - self.wait(allowed_methods=[ - (10, 10), # start - ]) - - self._x_start_ok(d, login_method, login_response, locale) - - self._wait_tune_ok = True - while self._wait_tune_ok: - self.wait(allowed_methods=[ - (10, 20), # secure - (10, 30), # tune - ]) - - return self._x_open(virtual_host) - - @property - def connected(self): - return self.transport and self.transport.connected - - def _do_close(self): - try: - self.transport.close() - - temp_list = [x for x in values(self.channels) if x is not self] - for ch in temp_list: - ch._do_close() - except socket.error: - pass # connection already closed on the other end - finally: - self.transport = self.connection = self.channels = None - - def _get_free_channel_id(self): - try: - return self._avail_channel_ids.pop() - except IndexError: - raise ResourceError( - 'No free channel ids, current={0}, channel_max={1}'.format( - len(self.channels), self.channel_max), (20, 10)) - - def _claim_channel_id(self, channel_id): - try: - return self._avail_channel_ids.remove(channel_id) - except ValueError: - raise ConnectionError( - 'Channel %r already open' % (channel_id, )) - - def _wait_method(self, channel_id, allowed_methods): - """Wait for a method from the server destined for - a particular channel.""" - # - # Check the channel's deferred methods - # - method_queue = self.channels[channel_id].method_queue - - for queued_method in method_queue: - method_sig = queued_method[0] - if (allowed_methods is None) \ - or (method_sig in allowed_methods) \ - or (method_sig == (20, 40)): - method_queue.remove(queued_method) - return queued_method - - # - # Nothing queued, need to wait for a method from the peer - # - while 1: - channel, method_sig, args, content = \ - self.method_reader.read_method() - - if channel == channel_id and ( - allowed_methods is None or - method_sig in allowed_methods or - method_sig == (20, 40)): - return method_sig, args, content - - # - # Certain methods like basic_return should be dispatched - # immediately rather than being queued, even if they're not - # one of the 'allowed_methods' we're looking for. - # - if channel and method_sig in self.Channel._IMMEDIATE_METHODS: - self.channels[channel].dispatch_method( - method_sig, args, content, - ) - continue - - # - # Not the channel and/or method we were looking for. Queue - # this method for later - # - self.channels[channel].method_queue.append( - (method_sig, args, content), - ) - - # - # If we just queued up a method for channel 0 (the Connection - # itself) it's probably a close method in reaction to some - # error, so deal with it right away. - # - if not channel: - self.wait() - - def channel(self, channel_id=None): - """Fetch a Channel object identified by the numeric channel_id, or - create that object if it doesn't already exist.""" - try: - return self.channels[channel_id] - except KeyError: - return self.Channel(self, channel_id) - - def is_alive(self): - if HAS_MSG_PEEK: - sock = self.sock - prev = sock.gettimeout() - sock.settimeout(0.0001) - try: - sock.recv(1, socket.MSG_PEEK) - except socket.timeout: - pass - except socket.error: - return False - finally: - sock.settimeout(prev) - return True - - def drain_events(self, timeout=None): - """Wait for an event on a channel.""" - chanmap = self.channels - chanid, method_sig, args, content = self._wait_multiple( - chanmap, None, timeout=timeout, - ) - - channel = chanmap[chanid] - - if (content and - channel.auto_decode and - hasattr(content, 'content_encoding')): - try: - content.body = content.body.decode(content.content_encoding) - except Exception: - pass - - amqp_method = (self._method_override.get(method_sig) or - channel._METHOD_MAP.get(method_sig, None)) - - if amqp_method is None: - raise AMQPNotImplementedError( - 'Unknown AMQP method {0!r}'.format(method_sig)) - - if content is None: - return amqp_method(channel, args) - else: - return amqp_method(channel, args, content) - - def read_timeout(self, timeout=None): - if timeout is None: - return self.method_reader.read_method() - sock = self.sock - prev = sock.gettimeout() - if prev != timeout: - sock.settimeout(timeout) - try: - try: - return self.method_reader.read_method() - except SSLError as exc: - # http://bugs.python.org/issue10272 - if 'timed out' in str(exc): - raise socket.timeout() - # Non-blocking SSL sockets can throw SSLError - if 'The operation did not complete' in str(exc): - raise socket.timeout() - raise - finally: - if prev != timeout: - sock.settimeout(prev) - - def _wait_multiple(self, channels, allowed_methods, timeout=None): - for channel_id, channel in items(channels): - method_queue = channel.method_queue - for queued_method in method_queue: - method_sig = queued_method[0] - if (allowed_methods is None or - method_sig in allowed_methods or - method_sig == (20, 40)): - method_queue.remove(queued_method) - method_sig, args, content = queued_method - return channel_id, method_sig, args, content - - # Nothing queued, need to wait for a method from the peer - read_timeout = self.read_timeout - wait = self.wait - while 1: - channel, method_sig, args, content = read_timeout(timeout) - - if channel in channels and ( - allowed_methods is None or - method_sig in allowed_methods or - method_sig == (20, 40)): - return channel, method_sig, args, content - - # Not the channel and/or method we were looking for. Queue - # this method for later - channels[channel].method_queue.append((method_sig, args, content)) - - # - # If we just queued up a method for channel 0 (the Connection - # itself) it's probably a close method in reaction to some - # error, so deal with it right away. - # - if channel == 0: - wait() - - def _dispatch_basic_return(self, channel, args, msg): - reply_code = args.read_short() - reply_text = args.read_shortstr() - exchange = args.read_shortstr() - routing_key = args.read_shortstr() - - exc = error_for_code(reply_code, reply_text, (50, 60), ChannelError) - handlers = channel.events.get('basic_return') - if not handlers: - raise exc - for callback in handlers: - callback(exc, exchange, routing_key, msg) - - def close(self, reply_code=0, reply_text='', method_sig=(0, 0)): - """Request a connection close - - This method indicates that the sender wants to close the - connection. This may be due to internal conditions (e.g. a - forced shut-down) or due to an error handling a specific - method, i.e. an exception. When a close is due to an - exception, the sender provides the class and method id of the - method which caused the exception. - - RULE: - - After sending this method any received method except the - Close-OK method MUST be discarded. - - RULE: - - The peer sending this method MAY use a counter or timeout - to detect failure of the other peer to respond correctly - with the Close-OK method. - - RULE: - - When a server receives the Close method from a client it - MUST delete all server-side resources associated with the - client's context. A client CANNOT reconnect to a context - after sending or receiving a Close method. - - PARAMETERS: - reply_code: short - - The reply code. The AMQ reply codes are defined in AMQ - RFC 011. - - reply_text: shortstr - - The localised reply text. This text can be logged as an - aid to resolving issues. - - class_id: short - - failing method class - - When the close is provoked by a method exception, this - is the class of the method. - - method_id: short - - failing method ID - - When the close is provoked by a method exception, this - is the ID of the method. - - """ - if self.transport is None: - # already closed - return - - args = AMQPWriter() - args.write_short(reply_code) - args.write_shortstr(reply_text) - args.write_short(method_sig[0]) # class_id - args.write_short(method_sig[1]) # method_id - self._send_method((10, 50), args) - return self.wait(allowed_methods=[ - (10, 50), # Connection.close - (10, 51), # Connection.close_ok - ]) - - def _close(self, args): - """Request a connection close - - This method indicates that the sender wants to close the - connection. This may be due to internal conditions (e.g. a - forced shut-down) or due to an error handling a specific - method, i.e. an exception. When a close is due to an - exception, the sender provides the class and method id of the - method which caused the exception. - - RULE: - - After sending this method any received method except the - Close-OK method MUST be discarded. - - RULE: - - The peer sending this method MAY use a counter or timeout - to detect failure of the other peer to respond correctly - with the Close-OK method. - - RULE: - - When a server receives the Close method from a client it - MUST delete all server-side resources associated with the - client's context. A client CANNOT reconnect to a context - after sending or receiving a Close method. - - PARAMETERS: - reply_code: short - - The reply code. The AMQ reply codes are defined in AMQ - RFC 011. - - reply_text: shortstr - - The localised reply text. This text can be logged as an - aid to resolving issues. - - class_id: short - - failing method class - - When the close is provoked by a method exception, this - is the class of the method. - - method_id: short - - failing method ID - - When the close is provoked by a method exception, this - is the ID of the method. - - """ - reply_code = args.read_short() - reply_text = args.read_shortstr() - class_id = args.read_short() - method_id = args.read_short() - - self._x_close_ok() - - raise error_for_code(reply_code, reply_text, - (class_id, method_id), ConnectionError) - - def _blocked(self, args): - """RabbitMQ Extension.""" - reason = args.read_shortstr() - if self.on_blocked: - return self.on_blocked(reason) - - def _unblocked(self, *args): - if self.on_unblocked: - return self.on_unblocked() - - def _x_close_ok(self): - """Confirm a connection close - - This method confirms a Connection.Close method and tells the - recipient that it is safe to release resources for the - connection and close the socket. - - RULE: - - A peer that detects a socket closure without having - received a Close-Ok handshake method SHOULD log the error. - - """ - self._send_method((10, 51)) - self._do_close() - - def _close_ok(self, args): - """Confirm a connection close - - This method confirms a Connection.Close method and tells the - recipient that it is safe to release resources for the - connection and close the socket. - - RULE: - - A peer that detects a socket closure without having - received a Close-Ok handshake method SHOULD log the error. - - """ - self._do_close() - - def _x_open(self, virtual_host, capabilities=''): - """Open connection to virtual host - - This method opens a connection to a virtual host, which is a - collection of resources, and acts to separate multiple - application domains within a server. - - RULE: - - The client MUST open the context before doing any work on - the connection. - - PARAMETERS: - virtual_host: shortstr - - virtual host name - - The name of the virtual host to work with. - - RULE: - - If the server supports multiple virtual hosts, it - MUST enforce a full separation of exchanges, - queues, and all associated entities per virtual - host. An application, connected to a specific - virtual host, MUST NOT be able to access resources - of another virtual host. - - RULE: - - The server SHOULD verify that the client has - permission to access the specified virtual host. - - RULE: - - The server MAY configure arbitrary limits per - virtual host, such as the number of each type of - entity that may be used, per connection and/or in - total. - - capabilities: shortstr - - required capabilities - - The client may specify a number of capability names, - delimited by spaces. The server can use this string - to how to process the client's connection request. - - """ - args = AMQPWriter() - args.write_shortstr(virtual_host) - args.write_shortstr(capabilities) - args.write_bit(False) - self._send_method((10, 40), args) - return self.wait(allowed_methods=[ - (10, 41), # Connection.open_ok - ]) - - def _open_ok(self, args): - """Signal that the connection is ready - - This method signals to the client that the connection is ready - for use. - - PARAMETERS: - known_hosts: shortstr (deprecated) - - """ - AMQP_LOGGER.debug('Open OK!') - - def _secure(self, args): - """Security mechanism challenge - - The SASL protocol works by exchanging challenges and responses - until both peers have received sufficient information to - authenticate each other. This method challenges the client to - provide more information. - - PARAMETERS: - challenge: longstr - - security challenge data - - Challenge information, a block of opaque binary data - passed to the security mechanism. - - """ - challenge = args.read_longstr() # noqa - - def _x_secure_ok(self, response): - """Security mechanism response - - This method attempts to authenticate, passing a block of SASL - data for the security mechanism at the server side. - - PARAMETERS: - response: longstr - - security response data - - A block of opaque data passed to the security - mechanism. The contents of this data are defined by - the SASL security mechanism. - - """ - args = AMQPWriter() - args.write_longstr(response) - self._send_method((10, 21), args) - - def _start(self, args): - """Start connection negotiation - - This method starts the connection negotiation process by - telling the client the protocol version that the server - proposes, along with a list of security mechanisms which the - client can use for authentication. - - RULE: - - If the client cannot handle the protocol version suggested - by the server it MUST close the socket connection. - - RULE: - - The server MUST provide a protocol version that is lower - than or equal to that requested by the client in the - protocol header. If the server cannot support the - specified protocol it MUST NOT send this method, but MUST - close the socket connection. - - PARAMETERS: - version_major: octet - - protocol major version - - The protocol major version that the server agrees to - use, which cannot be higher than the client's major - version. - - version_minor: octet - - protocol major version - - The protocol minor version that the server agrees to - use, which cannot be higher than the client's minor - version. - - server_properties: table - - server properties - - mechanisms: longstr - - available security mechanisms - - A list of the security mechanisms that the server - supports, delimited by spaces. Currently ASL supports - these mechanisms: PLAIN. - - locales: longstr - - available message locales - - A list of the message locales that the server - supports, delimited by spaces. The locale defines the - language in which the server will send reply texts. - - RULE: - - All servers MUST support at least the en_US - locale. - - """ - self.version_major = args.read_octet() - self.version_minor = args.read_octet() - self.server_properties = args.read_table() - self.mechanisms = args.read_longstr().split(' ') - self.locales = args.read_longstr().split(' ') - - AMQP_LOGGER.debug( - START_DEBUG_FMT, - self.version_major, self.version_minor, - self.server_properties, self.mechanisms, self.locales, - ) - - def _x_start_ok(self, client_properties, mechanism, response, locale): - """Select security mechanism and locale - - This method selects a SASL security mechanism. ASL uses SASL - (RFC2222) to negotiate authentication and encryption. - - PARAMETERS: - client_properties: table - - client properties - - mechanism: shortstr - - selected security mechanism - - A single security mechanisms selected by the client, - which must be one of those specified by the server. - - RULE: - - The client SHOULD authenticate using the highest- - level security profile it can handle from the list - provided by the server. - - RULE: - - The mechanism field MUST contain one of the - security mechanisms proposed by the server in the - Start method. If it doesn't, the server MUST close - the socket. - - response: longstr - - security response data - - A block of opaque data passed to the security - mechanism. The contents of this data are defined by - the SASL security mechanism. For the PLAIN security - mechanism this is defined as a field table holding two - fields, LOGIN and PASSWORD. - - locale: shortstr - - selected message locale - - A single message local selected by the client, which - must be one of those specified by the server. - - """ - if self.server_capabilities.get('consumer_cancel_notify'): - if 'capabilities' not in client_properties: - client_properties['capabilities'] = {} - client_properties['capabilities']['consumer_cancel_notify'] = True - if self.server_capabilities.get('connection.blocked'): - if 'capabilities' not in client_properties: - client_properties['capabilities'] = {} - client_properties['capabilities']['connection.blocked'] = True - args = AMQPWriter() - args.write_table(client_properties) - args.write_shortstr(mechanism) - args.write_longstr(response) - args.write_shortstr(locale) - self._send_method((10, 11), args) - - def _tune(self, args): - """Propose connection tuning parameters - - This method proposes a set of connection configuration values - to the client. The client can accept and/or adjust these. - - PARAMETERS: - channel_max: short - - proposed maximum channels - - The maximum total number of channels that the server - allows per connection. Zero means that the server does - not impose a fixed limit, but the number of allowed - channels may be limited by available server resources. - - frame_max: long - - proposed maximum frame size - - The largest frame size that the server proposes for - the connection. The client can negotiate a lower - value. Zero means that the server does not impose any - specific limit but may reject very large frames if it - cannot allocate resources for them. - - RULE: - - Until the frame-max has been negotiated, both - peers MUST accept frames of up to 4096 octets - large. The minimum non-zero value for the frame- - max field is 4096. - - heartbeat: short - - desired heartbeat delay - - The delay, in seconds, of the connection heartbeat - that the server wants. Zero means the server does not - want a heartbeat. - - """ - client_heartbeat = self.client_heartbeat or 0 - self.channel_max = args.read_short() or self.channel_max - self.frame_max = args.read_long() or self.frame_max - self.method_writer.frame_max = self.frame_max - self.server_heartbeat = args.read_short() or 0 - - # negotiate the heartbeat interval to the smaller of the - # specified values - if self.server_heartbeat == 0 or client_heartbeat == 0: - self.heartbeat = max(self.server_heartbeat, client_heartbeat) - else: - self.heartbeat = min(self.server_heartbeat, client_heartbeat) - - # Ignore server heartbeat if client_heartbeat is disabled - if not self.client_heartbeat: - self.heartbeat = 0 - - self._x_tune_ok(self.channel_max, self.frame_max, self.heartbeat) - - def send_heartbeat(self): - self.transport.write_frame(8, 0, bytes()) - - def heartbeat_tick(self, rate=2): - """Send heartbeat packets, if necessary, and fail if none have been - received recently. This should be called frequently, on the order of - once per second. - - :keyword rate: Ignored - """ - if not self.heartbeat: - return - - # treat actual data exchange in either direction as a heartbeat - sent_now = self.method_writer.bytes_sent - recv_now = self.method_reader.bytes_recv - if self.prev_sent is None or self.prev_sent != sent_now: - self.last_heartbeat_sent = monotonic() - if self.prev_recv is None or self.prev_recv != recv_now: - self.last_heartbeat_received = monotonic() - self.prev_sent, self.prev_recv = sent_now, recv_now - - # send a heartbeat if it's time to do so - if monotonic() > self.last_heartbeat_sent + self.heartbeat: - self.send_heartbeat() - self.last_heartbeat_sent = monotonic() - - # if we've missed two intervals' heartbeats, fail; this gives the - # server enough time to send heartbeats a little late - if (self.last_heartbeat_received and - self.last_heartbeat_received + 2 * - self.heartbeat < monotonic()): - raise ConnectionForced('Too many heartbeats missed') - - def _x_tune_ok(self, channel_max, frame_max, heartbeat): - """Negotiate connection tuning parameters - - This method sends the client's connection tuning parameters to - the server. Certain fields are negotiated, others provide - capability information. - - PARAMETERS: - channel_max: short - - negotiated maximum channels - - The maximum total number of channels that the client - will use per connection. May not be higher than the - value specified by the server. - - RULE: - - The server MAY ignore the channel-max value or MAY - use it for tuning its resource allocation. - - frame_max: long - - negotiated maximum frame size - - The largest frame size that the client and server will - use for the connection. Zero means that the client - does not impose any specific limit but may reject very - large frames if it cannot allocate resources for them. - Note that the frame-max limit applies principally to - content frames, where large contents can be broken - into frames of arbitrary size. - - RULE: - - Until the frame-max has been negotiated, both - peers must accept frames of up to 4096 octets - large. The minimum non-zero value for the frame- - max field is 4096. - - heartbeat: short - - desired heartbeat delay - - The delay, in seconds, of the connection heartbeat - that the client wants. Zero means the client does not - want a heartbeat. - - """ - args = AMQPWriter() - args.write_short(channel_max) - args.write_long(frame_max) - args.write_short(heartbeat or 0) - self._send_method((10, 31), args) - self._wait_tune_ok = False - - @property - def sock(self): - return self.transport.sock - - @property - def server_capabilities(self): - return self.server_properties.get('capabilities') or {} - - _METHOD_MAP = { - (10, 10): _start, - (10, 20): _secure, - (10, 30): _tune, - (10, 41): _open_ok, - (10, 50): _close, - (10, 51): _close_ok, - (10, 60): _blocked, - (10, 61): _unblocked, - } - - _IMMEDIATE_METHODS = [] - connection_errors = ( - ConnectionError, - socket.error, - IOError, - OSError, - ) - channel_errors = (ChannelError, ) - recoverable_connection_errors = ( - RecoverableConnectionError, - socket.error, - IOError, - OSError, - ) - recoverable_channel_errors = ( - RecoverableChannelError, - ) diff --git a/awx/lib/site-packages/amqp/exceptions.py b/awx/lib/site-packages/amqp/exceptions.py deleted file mode 100644 index e3e144a509..0000000000 --- a/awx/lib/site-packages/amqp/exceptions.py +++ /dev/null @@ -1,258 +0,0 @@ -"""Exceptions used by amqp""" -# Copyright (C) 2007-2008 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -from struct import pack, unpack - -__all__ = [ - 'AMQPError', - 'ConnectionError', 'ChannelError', - 'RecoverableConnectionError', 'IrrecoverableConnectionError', - 'RecoverableChannelError', 'IrrecoverableChannelError', - 'ConsumerCancelled', 'ContentTooLarge', 'NoConsumers', - 'ConnectionForced', 'InvalidPath', 'AccessRefused', 'NotFound', - 'ResourceLocked', 'PreconditionFailed', 'FrameError', 'FrameSyntaxError', - 'InvalidCommand', 'ChannelNotOpen', 'UnexpectedFrame', 'ResourceError', - 'NotAllowed', 'AMQPNotImplementedError', 'InternalError', -] - - -class AMQPError(Exception): - code = 0 - - def __init__(self, reply_text=None, method_sig=None, - method_name=None, reply_code=None): - self.message = reply_text - self.reply_code = reply_code or self.code - self.reply_text = reply_text - self.method_sig = method_sig - self.method_name = method_name or '' - if method_sig and not self.method_name: - self.method_name = METHOD_NAME_MAP.get(method_sig, '') - Exception.__init__(self, reply_code, - reply_text, method_sig, self.method_name) - - def __str__(self): - if self.method: - return '{0.method}: ({0.reply_code}) {0.reply_text}'.format(self) - return self.reply_text or '' - - @property - def method(self): - return self.method_name or self.method_sig - - -class ConnectionError(AMQPError): - pass - - -class ChannelError(AMQPError): - pass - - -class RecoverableChannelError(ChannelError): - pass - - -class IrrecoverableChannelError(ChannelError): - pass - - -class RecoverableConnectionError(ConnectionError): - pass - - -class IrrecoverableConnectionError(ConnectionError): - pass - - -class Blocked(RecoverableConnectionError): - pass - - -class ConsumerCancelled(RecoverableConnectionError): - pass - - -class ContentTooLarge(RecoverableChannelError): - code = 311 - - -class NoConsumers(RecoverableChannelError): - code = 313 - - -class ConnectionForced(RecoverableConnectionError): - code = 320 - - -class InvalidPath(IrrecoverableConnectionError): - code = 402 - - -class AccessRefused(IrrecoverableChannelError): - code = 403 - - -class NotFound(IrrecoverableChannelError): - code = 404 - - -class ResourceLocked(RecoverableChannelError): - code = 405 - - -class PreconditionFailed(IrrecoverableChannelError): - code = 406 - - -class FrameError(IrrecoverableConnectionError): - code = 501 - - -class FrameSyntaxError(IrrecoverableConnectionError): - code = 502 - - -class InvalidCommand(IrrecoverableConnectionError): - code = 503 - - -class ChannelNotOpen(IrrecoverableConnectionError): - code = 504 - - -class UnexpectedFrame(IrrecoverableConnectionError): - code = 505 - - -class ResourceError(RecoverableConnectionError): - code = 506 - - -class NotAllowed(IrrecoverableConnectionError): - code = 530 - - -class AMQPNotImplementedError(IrrecoverableConnectionError): - code = 540 - - -class InternalError(IrrecoverableConnectionError): - code = 541 - - -ERROR_MAP = { - 311: ContentTooLarge, - 313: NoConsumers, - 320: ConnectionForced, - 402: InvalidPath, - 403: AccessRefused, - 404: NotFound, - 405: ResourceLocked, - 406: PreconditionFailed, - 501: FrameError, - 502: FrameSyntaxError, - 503: InvalidCommand, - 504: ChannelNotOpen, - 505: UnexpectedFrame, - 506: ResourceError, - 530: NotAllowed, - 540: AMQPNotImplementedError, - 541: InternalError, -} - - -def error_for_code(code, text, method, default): - try: - return ERROR_MAP[code](text, method, reply_code=code) - except KeyError: - return default(text, method, reply_code=code) - - -def raise_for_code(code, text, method, default): - raise error_for_code(code, text, method, default) - - -METHOD_NAME_MAP = { - (10, 10): 'Connection.start', - (10, 11): 'Connection.start_ok', - (10, 20): 'Connection.secure', - (10, 21): 'Connection.secure_ok', - (10, 30): 'Connection.tune', - (10, 31): 'Connection.tune_ok', - (10, 40): 'Connection.open', - (10, 41): 'Connection.open_ok', - (10, 50): 'Connection.close', - (10, 51): 'Connection.close_ok', - (20, 10): 'Channel.open', - (20, 11): 'Channel.open_ok', - (20, 20): 'Channel.flow', - (20, 21): 'Channel.flow_ok', - (20, 40): 'Channel.close', - (20, 41): 'Channel.close_ok', - (30, 10): 'Access.request', - (30, 11): 'Access.request_ok', - (40, 10): 'Exchange.declare', - (40, 11): 'Exchange.declare_ok', - (40, 20): 'Exchange.delete', - (40, 21): 'Exchange.delete_ok', - (40, 30): 'Exchange.bind', - (40, 31): 'Exchange.bind_ok', - (40, 40): 'Exchange.unbind', - (40, 41): 'Exchange.unbind_ok', - (50, 10): 'Queue.declare', - (50, 11): 'Queue.declare_ok', - (50, 20): 'Queue.bind', - (50, 21): 'Queue.bind_ok', - (50, 30): 'Queue.purge', - (50, 31): 'Queue.purge_ok', - (50, 40): 'Queue.delete', - (50, 41): 'Queue.delete_ok', - (50, 50): 'Queue.unbind', - (50, 51): 'Queue.unbind_ok', - (60, 10): 'Basic.qos', - (60, 11): 'Basic.qos_ok', - (60, 20): 'Basic.consume', - (60, 21): 'Basic.consume_ok', - (60, 30): 'Basic.cancel', - (60, 31): 'Basic.cancel_ok', - (60, 40): 'Basic.publish', - (60, 50): 'Basic.return', - (60, 60): 'Basic.deliver', - (60, 70): 'Basic.get', - (60, 71): 'Basic.get_ok', - (60, 72): 'Basic.get_empty', - (60, 80): 'Basic.ack', - (60, 90): 'Basic.reject', - (60, 100): 'Basic.recover_async', - (60, 110): 'Basic.recover', - (60, 111): 'Basic.recover_ok', - (60, 120): 'Basic.nack', - (90, 10): 'Tx.select', - (90, 11): 'Tx.select_ok', - (90, 20): 'Tx.commit', - (90, 21): 'Tx.commit_ok', - (90, 30): 'Tx.rollback', - (90, 31): 'Tx.rollback_ok', - (85, 10): 'Confirm.select', - (85, 11): 'Confirm.select_ok', -} - - -for _method_id, _method_name in list(METHOD_NAME_MAP.items()): - METHOD_NAME_MAP[unpack('>I', pack('>HH', *_method_id))[0]] = _method_name diff --git a/awx/lib/site-packages/amqp/five.py b/awx/lib/site-packages/amqp/five.py deleted file mode 100644 index 5157df59a5..0000000000 --- a/awx/lib/site-packages/amqp/five.py +++ /dev/null @@ -1,188 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.five - ~~~~~~~~~~~ - - Compatibility implementations of features - only available in newer Python versions. - - -""" -from __future__ import absolute_import - -############## py3k ######################################################### -import sys -PY3 = sys.version_info[0] == 3 - -try: - reload = reload # noqa -except NameError: # pragma: no cover - from imp import reload # noqa - -try: - from UserList import UserList # noqa -except ImportError: # pragma: no cover - from collections import UserList # noqa - -try: - from UserDict import UserDict # noqa -except ImportError: # pragma: no cover - from collections import UserDict # noqa - - -if PY3: - import builtins - - from queue import Queue, Empty - from itertools import zip_longest - from io import StringIO, BytesIO - - map = map - string = str - string_t = str - long_t = int - text_t = str - range = range - int_types = (int, ) - - open_fqdn = 'builtins.open' - - def items(d): - return d.items() - - def keys(d): - return d.keys() - - def values(d): - return d.values() - - def nextfun(it): - return it.__next__ - - exec_ = getattr(builtins, 'exec') - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - class WhateverIO(StringIO): - - def write(self, data): - if isinstance(data, bytes): - data = data.encode() - StringIO.write(self, data) - -else: - import __builtin__ as builtins # noqa - from Queue import Queue, Empty # noqa - from itertools import imap as map, izip_longest as zip_longest # noqa - from StringIO import StringIO # noqa - string = unicode # noqa - string_t = basestring # noqa - text_t = unicode - long_t = long # noqa - range = xrange - int_types = (int, long) - - open_fqdn = '__builtin__.open' - - def items(d): # noqa - return d.iteritems() - - def keys(d): # noqa - return d.iterkeys() - - def values(d): # noqa - return d.itervalues() - - def nextfun(it): # noqa - return it.next - - def exec_(code, globs=None, locs=None): - """Execute code in a namespace.""" - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - - exec_("""def reraise(tp, value, tb=None): raise tp, value, tb""") - - BytesIO = WhateverIO = StringIO # noqa - - -def with_metaclass(Type, skip_attrs=set(['__dict__', '__weakref__'])): - """Class decorator to set metaclass. - - Works with both Python 3 and Python 3 and it does not add - an extra class in the lookup order like ``six.with_metaclass`` does - (that is -- it copies the original class instead of using inheritance). - - """ - - def _clone_with_metaclass(Class): - attrs = dict((key, value) for key, value in items(vars(Class)) - if key not in skip_attrs) - return Type(Class.__name__, Class.__bases__, attrs) - - return _clone_with_metaclass - -############## time.monotonic ################################################ - -if sys.version_info < (3, 3): - - import platform - SYSTEM = platform.system() - - if SYSTEM == 'Darwin': - import ctypes - from ctypes.util import find_library - libSystem = ctypes.CDLL('libSystem.dylib') - CoreServices = ctypes.CDLL(find_library('CoreServices'), - use_errno=True) - mach_absolute_time = libSystem.mach_absolute_time - mach_absolute_time.restype = ctypes.c_uint64 - absolute_to_nanoseconds = CoreServices.AbsoluteToNanoseconds - absolute_to_nanoseconds.restype = ctypes.c_uint64 - absolute_to_nanoseconds.argtypes = [ctypes.c_uint64] - - def _monotonic(): - return absolute_to_nanoseconds(mach_absolute_time()) * 1e-9 - - elif SYSTEM == 'Linux': - # from stackoverflow: - # questions/1205722/how-do-i-get-monotonic-time-durations-in-python - import ctypes - import os - - CLOCK_MONOTONIC = 1 # see - - class timespec(ctypes.Structure): - _fields_ = [ - ('tv_sec', ctypes.c_long), - ('tv_nsec', ctypes.c_long), - ] - - librt = ctypes.CDLL('librt.so.1', use_errno=True) - clock_gettime = librt.clock_gettime - clock_gettime.argtypes = [ - ctypes.c_int, ctypes.POINTER(timespec), - ] - - def _monotonic(): # noqa - t = timespec() - if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0: - errno_ = ctypes.get_errno() - raise OSError(errno_, os.strerror(errno_)) - return t.tv_sec + t.tv_nsec * 1e-9 - else: - from time import time as _monotonic -try: - from time import monotonic -except ImportError: - monotonic = _monotonic # noqa diff --git a/awx/lib/site-packages/amqp/method_framing.py b/awx/lib/site-packages/amqp/method_framing.py deleted file mode 100644 index b454524727..0000000000 --- a/awx/lib/site-packages/amqp/method_framing.py +++ /dev/null @@ -1,231 +0,0 @@ -"""Convert between frames and higher-level AMQP methods""" -# Copyright (C) 2007-2008 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -from collections import defaultdict, deque -from struct import pack, unpack - -from .basic_message import Message -from .exceptions import AMQPError, UnexpectedFrame -from .five import range, string -from .serialization import AMQPReader - -__all__ = ['MethodReader'] - -# -# MethodReader needs to know which methods are supposed -# to be followed by content headers and bodies. -# -_CONTENT_METHODS = [ - (60, 50), # Basic.return - (60, 60), # Basic.deliver - (60, 71), # Basic.get_ok -] - - -class _PartialMessage(object): - """Helper class to build up a multi-frame method.""" - - def __init__(self, method_sig, args, channel): - self.method_sig = method_sig - self.args = args - self.msg = Message() - self.body_parts = [] - self.body_received = 0 - self.body_size = None - self.complete = False - - def add_header(self, payload): - class_id, weight, self.body_size = unpack('>HHQ', payload[:12]) - self.msg._load_properties(payload[12:]) - self.complete = (self.body_size == 0) - - def add_payload(self, payload): - parts = self.body_parts - self.body_received += len(payload) - if self.body_received == self.body_size: - if parts: - parts.append(payload) - self.msg.body = bytes().join(parts) - else: - self.msg.body = payload - self.complete = True - else: - parts.append(payload) - - -class MethodReader(object): - """Helper class to receive frames from the broker, combine them if - necessary with content-headers and content-bodies into complete methods. - - Normally a method is represented as a tuple containing - (channel, method_sig, args, content). - - In the case of a framing error, an :exc:`ConnectionError` is placed - in the queue. - - In the case of unexpected frames, a tuple made up of - ``(channel, ChannelError)`` is placed in the queue. - - """ - - def __init__(self, source): - self.source = source - self.queue = deque() - self.running = False - self.partial_messages = {} - self.heartbeats = 0 - # For each channel, which type is expected next - self.expected_types = defaultdict(lambda: 1) - # not an actual byte count, just incremented whenever we receive - self.bytes_recv = 0 - self._quick_put = self.queue.append - self._quick_get = self.queue.popleft - - def _next_method(self): - """Read the next method from the source, once one complete method has - been assembled it is placed in the internal queue.""" - queue = self.queue - put = self._quick_put - read_frame = self.source.read_frame - while not queue: - try: - frame_type, channel, payload = read_frame() - except Exception as exc: - # - # Connection was closed? Framing Error? - # - put(exc) - break - - self.bytes_recv += 1 - - if frame_type not in (self.expected_types[channel], 8): - put(( - channel, - UnexpectedFrame( - 'Received frame {0} while expecting type: {1}'.format( - frame_type, self.expected_types[channel])))) - elif frame_type == 1: - self._process_method_frame(channel, payload) - elif frame_type == 2: - self._process_content_header(channel, payload) - elif frame_type == 3: - self._process_content_body(channel, payload) - elif frame_type == 8: - self._process_heartbeat(channel, payload) - - def _process_heartbeat(self, channel, payload): - self.heartbeats += 1 - - def _process_method_frame(self, channel, payload): - """Process Method frames""" - method_sig = unpack('>HH', payload[:4]) - args = AMQPReader(payload[4:]) - - if method_sig in _CONTENT_METHODS: - # - # Save what we've got so far and wait for the content-header - # - self.partial_messages[channel] = _PartialMessage( - method_sig, args, channel, - ) - self.expected_types[channel] = 2 - else: - self._quick_put((channel, method_sig, args, None)) - - def _process_content_header(self, channel, payload): - """Process Content Header frames""" - partial = self.partial_messages[channel] - partial.add_header(payload) - - if partial.complete: - # - # a bodyless message, we're done - # - self._quick_put((channel, partial.method_sig, - partial.args, partial.msg)) - self.partial_messages.pop(channel, None) - self.expected_types[channel] = 1 - else: - # - # wait for the content-body - # - self.expected_types[channel] = 3 - - def _process_content_body(self, channel, payload): - """Process Content Body frames""" - partial = self.partial_messages[channel] - partial.add_payload(payload) - if partial.complete: - # - # Stick the message in the queue and go back to - # waiting for method frames - # - self._quick_put((channel, partial.method_sig, - partial.args, partial.msg)) - self.partial_messages.pop(channel, None) - self.expected_types[channel] = 1 - - def read_method(self): - """Read a method from the peer.""" - self._next_method() - m = self._quick_get() - if isinstance(m, Exception): - raise m - if isinstance(m, tuple) and isinstance(m[1], AMQPError): - raise m[1] - return m - - -class MethodWriter(object): - """Convert AMQP methods into AMQP frames and send them out - to the peer.""" - - def __init__(self, dest, frame_max): - self.dest = dest - self.frame_max = frame_max - self.bytes_sent = 0 - - def write_method(self, channel, method_sig, args, content=None): - write_frame = self.dest.write_frame - payload = pack('>HH', method_sig[0], method_sig[1]) + args - - if content: - # do this early, so we can raise an exception if there's a - # problem with the content properties, before sending the - # first frame - body = content.body - if isinstance(body, string): - coding = content.properties.get('content_encoding', None) - if coding is None: - coding = content.properties['content_encoding'] = 'UTF-8' - - body = body.encode(coding) - properties = content._serialize_properties() - - write_frame(1, channel, payload) - - if content: - payload = pack('>HHQ', method_sig[0], 0, len(body)) + properties - - write_frame(2, channel, payload) - - chunk_size = self.frame_max - 8 - for i in range(0, len(body), chunk_size): - write_frame(3, channel, body[i:i + chunk_size]) - self.bytes_sent += 1 diff --git a/awx/lib/site-packages/amqp/protocol.py b/awx/lib/site-packages/amqp/protocol.py deleted file mode 100644 index 0856eb4e13..0000000000 --- a/awx/lib/site-packages/amqp/protocol.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import absolute_import - -from collections import namedtuple - - -queue_declare_ok_t = namedtuple( - 'queue_declare_ok_t', ('queue', 'message_count', 'consumer_count'), -) - -basic_return_t = namedtuple( - 'basic_return_t', - ('reply_code', 'reply_text', 'exchange', 'routing_key', 'message'), -) diff --git a/awx/lib/site-packages/amqp/serialization.py b/awx/lib/site-packages/amqp/serialization.py deleted file mode 100644 index 4ad1b06905..0000000000 --- a/awx/lib/site-packages/amqp/serialization.py +++ /dev/null @@ -1,510 +0,0 @@ -""" -Convert between bytestreams and higher-level AMQP types. - -2007-11-05 Barry Pederson - -""" -# Copyright (C) 2007 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -import sys - -from datetime import datetime -from decimal import Decimal -from io import BytesIO -from struct import pack, unpack -from time import mktime - -from .exceptions import FrameSyntaxError -from .five import int_types, long_t, string, string_t, items - -IS_PY3K = sys.version_info[0] >= 3 - -if IS_PY3K: - def byte(n): - return bytes([n]) -else: - byte = chr - - -ILLEGAL_TABLE_TYPE_WITH_KEY = """\ -Table type {0!r} for key {1!r} not handled by amqp. [value: {2!r}] -""" - -ILLEGAL_TABLE_TYPE = """\ - Table type {0!r} not handled by amqp. [value: {1!r}] -""" - - -class AMQPReader(object): - """Read higher-level AMQP types from a bytestream.""" - def __init__(self, source): - """Source should be either a file-like object with a read() method, or - a plain (non-unicode) string.""" - if isinstance(source, bytes): - self.input = BytesIO(source) - elif hasattr(source, 'read'): - self.input = source - else: - raise ValueError( - 'AMQPReader needs a file-like object or plain string') - - self.bitcount = self.bits = 0 - - def close(self): - self.input.close() - - def read(self, n): - """Read n bytes.""" - self.bitcount = self.bits = 0 - return self.input.read(n) - - def read_bit(self): - """Read a single boolean value.""" - if not self.bitcount: - self.bits = ord(self.input.read(1)) - self.bitcount = 8 - result = (self.bits & 1) == 1 - self.bits >>= 1 - self.bitcount -= 1 - return result - - def read_octet(self): - """Read one byte, return as an integer""" - self.bitcount = self.bits = 0 - return unpack('B', self.input.read(1))[0] - - def read_short(self): - """Read an unsigned 16-bit integer""" - self.bitcount = self.bits = 0 - return unpack('>H', self.input.read(2))[0] - - def read_long(self): - """Read an unsigned 32-bit integer""" - self.bitcount = self.bits = 0 - return unpack('>I', self.input.read(4))[0] - - def read_longlong(self): - """Read an unsigned 64-bit integer""" - self.bitcount = self.bits = 0 - return unpack('>Q', self.input.read(8))[0] - - def read_float(self): - """Read float value.""" - self.bitcount = self.bits = 0 - return unpack('>d', self.input.read(8))[0] - - def read_shortstr(self): - """Read a short string that's stored in up to 255 bytes. - - The encoding isn't specified in the AMQP spec, so - assume it's utf-8 - - """ - self.bitcount = self.bits = 0 - slen = unpack('B', self.input.read(1))[0] - return self.input.read(slen).decode('utf-8') - - def read_longstr(self): - """Read a string that's up to 2**32 bytes. - - The encoding isn't specified in the AMQP spec, so - assume it's utf-8 - - """ - self.bitcount = self.bits = 0 - slen = unpack('>I', self.input.read(4))[0] - return self.input.read(slen).decode('utf-8') - - def read_table(self): - """Read an AMQP table, and return as a Python dictionary.""" - self.bitcount = self.bits = 0 - tlen = unpack('>I', self.input.read(4))[0] - table_data = AMQPReader(self.input.read(tlen)) - result = {} - while table_data.input.tell() < tlen: - name = table_data.read_shortstr() - val = table_data.read_item() - result[name] = val - return result - - def read_item(self): - ftype = ord(self.input.read(1)) - - # 'S': long string - if ftype == 83: - val = self.read_longstr() - # 's': short string - elif ftype == 115: - val = self.read_shortstr() - # 'b': short-short int - elif ftype == 98: - val, = unpack('>B', self.input.read(1)) - # 'B': short-short unsigned int - elif ftype == 66: - val, = unpack('>b', self.input.read(1)) - # 'U': short int - elif ftype == 85: - val, = unpack('>h', self.input.read(2)) - # 'u': short unsigned int - elif ftype == 117: - val, = unpack('>H', self.input.read(2)) - # 'I': long int - elif ftype == 73: - val, = unpack('>i', self.input.read(4)) - # 'i': long unsigned int - elif ftype == 105: # 'l' - val, = unpack('>I', self.input.read(4)) - # 'L': long long int - elif ftype == 76: - val, = unpack('>q', self.input.read(8)) - # 'l': long long unsigned int - elif ftype == 108: - val, = unpack('>Q', self.input.read(8)) - # 'f': float - elif ftype == 102: - val, = unpack('>f', self.input.read(4)) - # 'd': double - elif ftype == 100: - val = self.read_float() - # 'D': decimal - elif ftype == 68: - d = self.read_octet() - n, = unpack('>i', self.input.read(4)) - val = Decimal(n) / Decimal(10 ** d) - # 'F': table - elif ftype == 70: - val = self.read_table() # recurse - # 'A': array - elif ftype == 65: - val = self.read_array() - # 't' (bool) - elif ftype == 116: - val = self.read_bit() - # 'T': timestamp - elif ftype == 84: - val = self.read_timestamp() - # 'V': void - elif ftype == 86: - val = None - else: - raise FrameSyntaxError( - 'Unknown value in table: {0!r} ({1!r})'.format( - ftype, type(ftype))) - return val - - def read_array(self): - array_length = unpack('>I', self.input.read(4))[0] - array_data = AMQPReader(self.input.read(array_length)) - result = [] - while array_data.input.tell() < array_length: - val = array_data.read_item() - result.append(val) - return result - - def read_timestamp(self): - """Read and AMQP timestamp, which is a 64-bit integer representing - seconds since the Unix epoch in 1-second resolution. - - Return as a Python datetime.datetime object, - expressed as localtime. - - """ - return datetime.fromtimestamp(self.read_longlong()) - - -class AMQPWriter(object): - """Convert higher-level AMQP types to bytestreams.""" - - def __init__(self, dest=None): - """dest may be a file-type object (with a write() method). If None - then a BytesIO is created, and the contents can be accessed with - this class's getvalue() method.""" - self.out = BytesIO() if dest is None else dest - self.bits = [] - self.bitcount = 0 - - def _flushbits(self): - if self.bits: - out = self.out - for b in self.bits: - out.write(pack('B', b)) - self.bits = [] - self.bitcount = 0 - - def close(self): - """Pass through if possible to any file-like destinations.""" - try: - self.out.close() - except AttributeError: - pass - - def flush(self): - """Pass through if possible to any file-like destinations.""" - try: - self.out.flush() - except AttributeError: - pass - - def getvalue(self): - """Get what's been encoded so far if we're working with a BytesIO.""" - self._flushbits() - return self.out.getvalue() - - def write(self, s): - """Write a plain Python string with no special encoding in Python 2.x, - or bytes in Python 3.x""" - self._flushbits() - self.out.write(s) - - def write_bit(self, b): - """Write a boolean value.""" - b = 1 if b else 0 - shift = self.bitcount % 8 - if shift == 0: - self.bits.append(0) - self.bits[-1] |= (b << shift) - self.bitcount += 1 - - def write_octet(self, n): - """Write an integer as an unsigned 8-bit value.""" - if n < 0 or n > 255: - raise FrameSyntaxError( - 'Octet {0!r} out of range 0..255'.format(n)) - self._flushbits() - self.out.write(pack('B', n)) - - def write_short(self, n): - """Write an integer as an unsigned 16-bit value.""" - if n < 0 or n > 65535: - raise FrameSyntaxError( - 'Octet {0!r} out of range 0..65535'.format(n)) - self._flushbits() - self.out.write(pack('>H', int(n))) - - def write_long(self, n): - """Write an integer as an unsigned2 32-bit value.""" - if n < 0 or n >= 4294967296: - raise FrameSyntaxError( - 'Octet {0!r} out of range 0..2**31-1'.format(n)) - self._flushbits() - self.out.write(pack('>I', n)) - - def write_longlong(self, n): - """Write an integer as an unsigned 64-bit value.""" - if n < 0 or n >= 18446744073709551616: - raise FrameSyntaxError( - 'Octet {0!r} out of range 0..2**64-1'.format(n)) - self._flushbits() - self.out.write(pack('>Q', n)) - - def write_shortstr(self, s): - """Write a string up to 255 bytes long (after any encoding). - - If passed a unicode string, encode with UTF-8. - - """ - self._flushbits() - if isinstance(s, string): - s = s.encode('utf-8') - if len(s) > 255: - raise FrameSyntaxError( - 'Shortstring overflow ({0} > 255)'.format(len(s))) - self.write_octet(len(s)) - self.out.write(s) - - def write_longstr(self, s): - """Write a string up to 2**32 bytes long after encoding. - - If passed a unicode string, encode as UTF-8. - - """ - self._flushbits() - if isinstance(s, string): - s = s.encode('utf-8') - self.write_long(len(s)) - self.out.write(s) - - def write_table(self, d): - """Write out a Python dictionary made of up string keys, and values - that are strings, signed integers, Decimal, datetime.datetime, or - sub-dictionaries following the same constraints.""" - self._flushbits() - table_data = AMQPWriter() - for k, v in items(d): - table_data.write_shortstr(k) - table_data.write_item(v, k) - table_data = table_data.getvalue() - self.write_long(len(table_data)) - self.out.write(table_data) - - def write_item(self, v, k=None): - if isinstance(v, (string_t, bytes)): - if isinstance(v, string): - v = v.encode('utf-8') - self.write(b'S') - self.write_longstr(v) - elif isinstance(v, bool): - self.write(pack('>cB', b't', int(v))) - elif isinstance(v, float): - self.write(pack('>cd', b'd', v)) - elif isinstance(v, int_types): - self.write(pack('>ci', b'I', v)) - elif isinstance(v, Decimal): - self.write(b'D') - sign, digits, exponent = v.as_tuple() - v = 0 - for d in digits: - v = (v * 10) + d - if sign: - v = -v - self.write_octet(-exponent) - self.write(pack('>i', v)) - elif isinstance(v, datetime): - self.write(b'T') - self.write_timestamp(v) - ## FIXME: timezone ? - elif isinstance(v, dict): - self.write(b'F') - self.write_table(v) - elif isinstance(v, (list, tuple)): - self.write(b'A') - self.write_array(v) - elif v is None: - self.write(b'V') - else: - err = (ILLEGAL_TABLE_TYPE_WITH_KEY.format(type(v), k, v) if k - else ILLEGAL_TABLE_TYPE.format(type(v), v)) - raise FrameSyntaxError(err) - - def write_array(self, a): - array_data = AMQPWriter() - for v in a: - array_data.write_item(v) - array_data = array_data.getvalue() - self.write_long(len(array_data)) - self.out.write(array_data) - - def write_timestamp(self, v): - """Write out a Python datetime.datetime object as a 64-bit integer - representing seconds since the Unix epoch.""" - self.out.write(pack('>q', long_t(mktime(v.timetuple())))) - - -class GenericContent(object): - """Abstract base class for AMQP content. - - Subclasses should override the PROPERTIES attribute. - - """ - PROPERTIES = [('dummy', 'shortstr')] - - def __init__(self, **props): - """Save the properties appropriate to this AMQP content type - in a 'properties' dictionary.""" - d = {} - for propname, _ in self.PROPERTIES: - if propname in props: - d[propname] = props[propname] - # FIXME: should we ignore unknown properties? - - self.properties = d - - def __eq__(self, other): - """Check if this object has the same properties as another - content object.""" - try: - return self.properties == other.properties - except AttributeError: - return NotImplemented - - def __getattr__(self, name): - """Look for additional properties in the 'properties' - dictionary, and if present - the 'delivery_info' - dictionary.""" - if name == '__setstate__': - # Allows pickling/unpickling to work - raise AttributeError('__setstate__') - - if name in self.properties: - return self.properties[name] - - if 'delivery_info' in self.__dict__ \ - and name in self.delivery_info: - return self.delivery_info[name] - - raise AttributeError(name) - - def _load_properties(self, raw_bytes): - """Given the raw bytes containing the property-flags and property-list - from a content-frame-header, parse and insert into a dictionary - stored in this object as an attribute named 'properties'.""" - r = AMQPReader(raw_bytes) - - # - # Read 16-bit shorts until we get one with a low bit set to zero - # - flags = [] - while 1: - flag_bits = r.read_short() - flags.append(flag_bits) - if flag_bits & 1 == 0: - break - - shift = 0 - d = {} - for key, proptype in self.PROPERTIES: - if shift == 0: - if not flags: - break - flag_bits, flags = flags[0], flags[1:] - shift = 15 - if flag_bits & (1 << shift): - d[key] = getattr(r, 'read_' + proptype)() - shift -= 1 - - self.properties = d - - def _serialize_properties(self): - """serialize the 'properties' attribute (a dictionary) into - the raw bytes making up a set of property flags and a - property list, suitable for putting into a content frame header.""" - shift = 15 - flag_bits = 0 - flags = [] - raw_bytes = AMQPWriter() - for key, proptype in self.PROPERTIES: - val = self.properties.get(key, None) - if val is not None: - if shift == 0: - flags.append(flag_bits) - flag_bits = 0 - shift = 15 - - flag_bits |= (1 << shift) - if proptype != 'bit': - getattr(raw_bytes, 'write_' + proptype)(val) - - shift -= 1 - - flags.append(flag_bits) - result = AMQPWriter() - for flag_bits in flags: - result.write_short(flag_bits) - result.write(raw_bytes.getvalue()) - - return result.getvalue() diff --git a/awx/lib/site-packages/amqp/transport.py b/awx/lib/site-packages/amqp/transport.py deleted file mode 100644 index eac3dbcca5..0000000000 --- a/awx/lib/site-packages/amqp/transport.py +++ /dev/null @@ -1,294 +0,0 @@ -# Copyright (C) 2009 Barry Pederson -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -from __future__ import absolute_import - -import errno -import re -import socket -import ssl - -# Jython does not have this attribute -try: - from socket import SOL_TCP -except ImportError: # pragma: no cover - from socket import IPPROTO_TCP as SOL_TCP # noqa - -try: - from ssl import SSLError -except ImportError: - class SSLError(Exception): # noqa - pass - -from struct import pack, unpack - -from .exceptions import UnexpectedFrame -from .utils import get_errno, set_cloexec - -_UNAVAIL = errno.EAGAIN, errno.EINTR, errno.ENOENT - -AMQP_PORT = 5672 - -EMPTY_BUFFER = bytes() - -# Yes, Advanced Message Queuing Protocol Protocol is redundant -AMQP_PROTOCOL_HEADER = 'AMQP\x01\x01\x00\x09'.encode('latin_1') - -# Match things like: [fe80::1]:5432, from RFC 2732 -IPV6_LITERAL = re.compile(r'\[([\.0-9a-f:]+)\](?::(\d+))?') - - -class _AbstractTransport(object): - """Common superclass for TCP and SSL transports""" - connected = False - - def __init__(self, host, connect_timeout): - self.connected = True - msg = None - port = AMQP_PORT - - m = IPV6_LITERAL.match(host) - if m: - host = m.group(1) - if m.group(2): - port = int(m.group(2)) - else: - if ':' in host: - host, port = host.rsplit(':', 1) - port = int(port) - - self.sock = None - last_err = None - for res in socket.getaddrinfo(host, port, 0, - socket.SOCK_STREAM, SOL_TCP): - af, socktype, proto, canonname, sa = res - try: - self.sock = socket.socket(af, socktype, proto) - try: - set_cloexec(self.sock, True) - except NotImplementedError: - pass - self.sock.settimeout(connect_timeout) - self.sock.connect(sa) - except socket.error as exc: - msg = exc - self.sock.close() - self.sock = None - last_err = msg - continue - break - - if not self.sock: - # Didn't connect, return the most recent error message - raise socket.error(last_err) - - try: - self.sock.settimeout(None) - self.sock.setsockopt(SOL_TCP, socket.TCP_NODELAY, 1) - self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) - - self._setup_transport() - - self._write(AMQP_PROTOCOL_HEADER) - except (OSError, IOError, socket.error) as exc: - if get_errno(exc) not in _UNAVAIL: - self.connected = False - raise - - def __del__(self): - try: - # socket module may have been collected by gc - # if this is called by a thread at shutdown. - if socket is not None: - try: - self.close() - except socket.error: - pass - finally: - self.sock = None - - def _read(self, n, initial=False): - """Read exactly n bytes from the peer""" - raise NotImplementedError('Must be overriden in subclass') - - def _setup_transport(self): - """Do any additional initialization of the class (used - by the subclasses).""" - pass - - def _shutdown_transport(self): - """Do any preliminary work in shutting down the connection.""" - pass - - def _write(self, s): - """Completely write a string to the peer.""" - raise NotImplementedError('Must be overriden in subclass') - - def close(self): - if self.sock is not None: - self._shutdown_transport() - # Call shutdown first to make sure that pending messages - # reach the AMQP broker if the program exits after - # calling this method. - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() - self.sock = None - self.connected = False - - def read_frame(self, unpack=unpack): - read = self._read - try: - frame_type, channel, size = unpack('>BHI', read(7, True)) - payload = read(size) - ch = ord(read(1)) - except socket.timeout: - raise - except (OSError, IOError, socket.error) as exc: - # Don't disconnect for ssl read time outs - # http://bugs.python.org/issue10272 - if isinstance(exc, SSLError) and 'timed out' in str(exc): - raise socket.timeout() - if get_errno(exc) not in _UNAVAIL: - self.connected = False - raise - if ch == 206: # '\xce' - return frame_type, channel, payload - else: - raise UnexpectedFrame( - 'Received 0x{0:02x} while expecting 0xce'.format(ch)) - - def write_frame(self, frame_type, channel, payload): - size = len(payload) - try: - self._write(pack( - '>BHI%dsB' % size, - frame_type, channel, size, payload, 0xce, - )) - except socket.timeout: - raise - except (OSError, IOError, socket.error) as exc: - if get_errno(exc) not in _UNAVAIL: - self.connected = False - raise - - -class SSLTransport(_AbstractTransport): - """Transport that works over SSL""" - - def __init__(self, host, connect_timeout, ssl): - if isinstance(ssl, dict): - self.sslopts = ssl - self._read_buffer = EMPTY_BUFFER - super(SSLTransport, self).__init__(host, connect_timeout) - - def _setup_transport(self): - """Wrap the socket in an SSL object.""" - if hasattr(self, 'sslopts'): - self.sock = ssl.wrap_socket(self.sock, **self.sslopts) - else: - self.sock = ssl.wrap_socket(self.sock) - self.sock.do_handshake() - self._quick_recv = self.sock.read - - def _shutdown_transport(self): - """Unwrap a Python 2.6 SSL socket, so we can call shutdown()""" - if self.sock is not None: - try: - unwrap = self.sock.unwrap - except AttributeError: - return - self.sock = unwrap() - - def _read(self, n, initial=False, - _errnos=(errno.ENOENT, errno.EAGAIN, errno.EINTR)): - # According to SSL_read(3), it can at most return 16kb of data. - # Thus, we use an internal read buffer like TCPTransport._read - # to get the exact number of bytes wanted. - recv = self._quick_recv - rbuf = self._read_buffer - try: - while len(rbuf) < n: - try: - s = recv(n - len(rbuf)) # see note above - except socket.error as exc: - # ssl.sock.read may cause ENOENT if the - # operation couldn't be performed (Issue celery#1414). - if not initial and exc.errno in _errnos: - continue - raise - if not s: - raise IOError('Socket closed') - rbuf += s - except: - self._read_buffer = rbuf - raise - result, self._read_buffer = rbuf[:n], rbuf[n:] - return result - - def _write(self, s): - """Write a string out to the SSL socket fully.""" - try: - write = self.sock.write - except AttributeError: - # Works around a bug in python socket library - raise IOError('Socket closed') - else: - while s: - n = write(s) - if not n: - raise IOError('Socket closed') - s = s[n:] - - -class TCPTransport(_AbstractTransport): - """Transport that deals directly with TCP socket.""" - - def _setup_transport(self): - """Setup to _write() directly to the socket, and - do our own buffered reads.""" - self._write = self.sock.sendall - self._read_buffer = EMPTY_BUFFER - self._quick_recv = self.sock.recv - - def _read(self, n, initial=False, _errnos=(errno.EAGAIN, errno.EINTR)): - """Read exactly n bytes from the socket""" - recv = self._quick_recv - rbuf = self._read_buffer - try: - while len(rbuf) < n: - try: - s = recv(n - len(rbuf)) - except socket.error as exc: - if not initial and exc.errno in _errnos: - continue - raise - if not s: - raise IOError('Socket closed') - rbuf += s - except: - self._read_buffer = rbuf - raise - - result, self._read_buffer = rbuf[:n], rbuf[n:] - return result - - -def create_transport(host, connect_timeout, ssl=False): - """Given a few parameters from the Connection constructor, - select and create a subclass of _AbstractTransport.""" - if ssl: - return SSLTransport(host, connect_timeout, ssl) - else: - return TCPTransport(host, connect_timeout) diff --git a/awx/lib/site-packages/amqp/utils.py b/awx/lib/site-packages/amqp/utils.py deleted file mode 100644 index 900d2aace4..0000000000 --- a/awx/lib/site-packages/amqp/utils.py +++ /dev/null @@ -1,102 +0,0 @@ -from __future__ import absolute_import - -import sys - -try: - import fcntl -except ImportError: - fcntl = None # noqa - - -class promise(object): - if not hasattr(sys, 'pypy_version_info'): - __slots__ = tuple( - 'fun args kwargs value ready failed ' - ' on_success on_error calls'.split() - ) - - def __init__(self, fun, args=(), kwargs=(), - on_success=None, on_error=None): - self.fun = fun - self.args = args - self.kwargs = kwargs - self.ready = False - self.failed = False - self.on_success = on_success - self.on_error = on_error - self.value = None - self.calls = 0 - - def __repr__(self): - return '<$: {0.fun.__name__}(*{0.args!r}, **{0.kwargs!r})'.format( - self, - ) - - def __call__(self, *args, **kwargs): - try: - self.value = self.fun( - *self.args + args if self.args else args, - **dict(self.kwargs, **kwargs) if self.kwargs else kwargs - ) - except Exception as exc: - self.set_error_state(exc) - else: - if self.on_success: - self.on_success(self.value) - finally: - self.ready = True - self.calls += 1 - - def then(self, callback=None, on_error=None): - self.on_success = callback - self.on_error = on_error - return callback - - def set_error_state(self, exc): - self.failed = True - if self.on_error is None: - raise - self.on_error(exc) - - def throw(self, exc): - try: - raise exc - except exc.__class__ as with_cause: - self.set_error_state(with_cause) - - -def noop(): - return promise(lambda *a, **k: None) - - -try: - from os import set_cloexec # Python 3.4? -except ImportError: - def set_cloexec(fd, cloexec): # noqa - try: - FD_CLOEXEC = fcntl.FD_CLOEXEC - except AttributeError: - raise NotImplementedError( - 'close-on-exec flag not supported on this platform', - ) - flags = fcntl.fcntl(fd, fcntl.F_GETFD) - if cloexec: - flags |= FD_CLOEXEC - else: - flags &= ~FD_CLOEXEC - return fcntl.fcntl(fd, fcntl.F_SETFD, flags) - - -def get_errno(exc): - """:exc:`socket.error` and :exc:`IOError` first got - the ``.errno`` attribute in Py2.7""" - try: - return exc.errno - except AttributeError: - try: - # e.args = (errno, reason) - if isinstance(exc.args, tuple) and len(exc.args) == 2: - return exc.args[0] - except AttributeError: - pass - return 0 diff --git a/awx/lib/site-packages/ansiconv.py b/awx/lib/site-packages/ansiconv.py deleted file mode 100644 index d0a66df5cd..0000000000 --- a/awx/lib/site-packages/ansiconv.py +++ /dev/null @@ -1,128 +0,0 @@ -""" -Converts ANSI coded text and converts it to either plain text -or to HTML. -""" -import re - -supported_sgr_codes = [1, 3, 4, 9, 30, 31, 32, 33, 34, 35, 36, 37, 40, 41, 42, - 43, 44, 45, 46, 47] - - -def to_plain(ansi): - """Takes the given string and strips all ANSI codes out. - - :param ansi: The string to strip - :return: The stripped string - """ - return re.sub(r'\x1B\[[0-9;]*[ABCDEFGHJKSTfmnsulh]', '', ansi) - - -def to_html(ansi, replace_newline=False): - """Converts the given ANSI string to HTML - - If `replace_newline` is set to True, then all newlines will be - replaced with
. - - :param ansi: The ANSI text. - :param replace_newline: Whether to replace newlines with HTML. - :return: The resulting HTML string. - """ - blocks = ansi.split('\x1B') - parsed_blocks = [] - for block in blocks: - command, text = _block_to_html(block) - - # The command "A" means move the cursor up, so we emulate that here. - if command == 'A' and len(parsed_blocks) > 0: - parsed_blocks.pop() - while len(parsed_blocks) > 0 and '\n' not in parsed_blocks[-1]: - parsed_blocks.pop() - - parsed_blocks.append(text) - - text = ''.join(parsed_blocks) - - if replace_newline: - text = text.replace('\n', '
\n') - - return text - - -def base_css(dark=True): - """Some base CSS with all of the default ANSI styles/colors. - - :param dark: Whether background should be dark or light. - :return: A string of CSS - """ - return "\n".join([ - css_rule('.ansi_fore', color=('#000000', '#FFFFFF')[dark]), - css_rule('.ansi_back', background_color=('#FFFFFF', '#000000')[dark]), - css_rule('.ansi1', font_weight='bold'), - css_rule('.ansi3', font_weight='italic'), - css_rule('.ansi4', text_decoration='underline'), - css_rule('.ansi9', text_decoration='line-through'), - css_rule('.ansi30', color="#000000"), - css_rule('.ansi31', color="#FF0000"), - css_rule('.ansi32', color="#00FF00"), - css_rule('.ansi33', color="#FFFF00"), - css_rule('.ansi34', color="#0000FF"), - css_rule('.ansi35', color="#FF00FF"), - css_rule('.ansi36', color="#00FFFF"), - css_rule('.ansi37', color="#FFFFFF"), - css_rule('.ansi40', background_color="#000000"), - css_rule('.ansi41', background_color="#FF0000"), - css_rule('.ansi42', background_color="#00FF00"), - css_rule('.ansi43', background_color="#FFFF00"), - css_rule('.ansi44', background_color="#0000FF"), - css_rule('.ansi45', background_color="#FF00FF"), - css_rule('.ansi46', background_color="#00FFFF"), - css_rule('.ansi47', background_color="#FFFFFF") - ]) - - -def css_rule(class_name, **properties): - """Creates a CSS rule string. - - The named parameters are used as the css properties. Underscores - are converted to hyphens. - - :param class_name: The CSS class name - :param properties: The properties sent as named params. - :return: The CSS string - """ - prop_str = lambda name, val: name.replace('_', '-') + ': ' + val - return '{0} {{ {1}; }}'.format( - class_name, - '; '.join([prop_str(prop, properties[prop]) for prop in properties]) - ) - - -def _block_to_html(text): - """Converts the given block of ANSI coded text to HTML. - - The text is only given back as HTML if the ANSI code is at the - beginning of the string (e.g. "[0;33mFoobar") - - :param text: The text block to convert. - :return: The text as HTML - """ - match = re.match(r'^\[(?P\d+(?:;\d+)*)?(?P[Am])', text) - if match is None: - return None, text - - command = match.group('command') - text = text[match.end():] - - if match.group('code') is None: - return command, text - - classes = [] - for code in match.group('code').split(';'): - if int(code) in supported_sgr_codes: - classes.append('ansi{0}'.format(code)) - - if classes: - text = u'{1}'.format(' '.join(classes), text) - - return command, text - diff --git a/awx/lib/site-packages/anyjson/__init__.py b/awx/lib/site-packages/anyjson/__init__.py deleted file mode 100644 index 1f671be163..0000000000 --- a/awx/lib/site-packages/anyjson/__init__.py +++ /dev/null @@ -1,142 +0,0 @@ -"""Wraps the best available JSON implementation available in a common -interface""" - -import sys - -VERSION = (0, 3, 3) -__version__ = ".".join(map(str, VERSION[0:3])) + "".join(VERSION[3:]) -__author__ = "Rune Halvorsen" -__contact__ = "runefh@gmail.com" -__homepage__ = "http://bitbucket.org/runeh/anyjson/" -__docformat__ = "restructuredtext" - -# -eof meta- - -#: The json implementation object. This is probably not useful to you, -#: except to get the name of the implementation in use. The name is -#: available through ``implementation.name``. -implementation = None - -# json.loads does not support buffer() objects, -# so we load() and StringIO instead, and it won't copy. -if sys.version_info[0] == 3: - from io import StringIO -else: - try: - from cStringIO import StringIO # noqa - except ImportError: - from StringIO import StringIO # noqa - -#: List of known json modules, and the names of their loads/dumps -#: methods, as well as the exceptions they throw. Exception can be either -#: an exception class or a string. -_modules = [("yajl", "dumps", TypeError, "loads", ValueError, "load"), - ("jsonlib2", "write", "WriteError", "read", "ReadError", None), - ("jsonlib", "write", "WriteError", "read", "ReadError", None), - ("simplejson", "dumps", TypeError, "loads", ValueError, "load"), - ("json", "dumps", TypeError, "loads", ValueError, "load"), - ("django.utils.simplejson", "dumps", TypeError, "loads", ValueError, "load"), - ("cjson", "encode", "EncodeError", "decode", "DecodeError", None) - ] - -_fields = ("modname", "encoder", "encerror", - "decoder", "decerror", "filedecoder") - - -class _JsonImplementation(object): - """Incapsulates a JSON implementation""" - - def __init__(self, modspec): - modinfo = dict(zip(_fields, modspec)) - - if modinfo["modname"] == "cjson": - import warnings - warnings.warn("cjson is deprecated! See http://pypi.python.org/pypi/python-cjson/1.0.5", DeprecationWarning) - - # No try block. We want importerror to end up at caller - module = self._attempt_load(modinfo["modname"]) - - self.implementation = modinfo["modname"] - self._encode = getattr(module, modinfo["encoder"]) - self._decode = getattr(module, modinfo["decoder"]) - fdec = modinfo["filedecoder"] - self._filedecode = fdec and getattr(module, fdec) - self._encode_error = modinfo["encerror"] - self._decode_error = modinfo["decerror"] - - if isinstance(modinfo["encerror"], basestring): - self._encode_error = getattr(module, modinfo["encerror"]) - if isinstance(modinfo["decerror"], basestring): - self._decode_error = getattr(module, modinfo["decerror"]) - - self.name = modinfo["modname"] - - def __repr__(self): - return "<_JsonImplementation instance using %s>" % self.name - - def _attempt_load(self, modname): - """Attempt to load module name modname, returning it on success, - throwing ImportError if module couldn't be imported""" - __import__(modname) - return sys.modules[modname] - - def dumps(self, data): - """Serialize the datastructure to json. Returns a string. Raises - TypeError if the object could not be serialized.""" - try: - return self._encode(data) - except self._encode_error, exc: - raise TypeError, TypeError(*exc.args), sys.exc_info()[2] - serialize = dumps - - def loads(self, s): - """deserialize the string to python data types. Raises - ValueError if the string could not be parsed.""" - # uses StringIO to support buffer objects. - try: - if self._filedecode and not isinstance(s, basestring): - return self._filedecode(StringIO(s)) - return self._decode(s) - except self._decode_error, exc: - raise ValueError, ValueError(*exc.args), sys.exc_info()[2] - deserialize = loads - - -def force_implementation(modname): - """Forces anyjson to use a specific json module if it's available""" - global implementation - for name, spec in [(e[0], e) for e in _modules]: - if name == modname: - implementation = _JsonImplementation(spec) - return - raise ImportError("No module named: %s" % modname) - - -if __name__ == "__main__": - # If run as a script, we do nothing but print an error message. - # We do NOT try to load a compatible module because that may throw an - # exception, which renders the package uninstallable with easy_install - # (It trys to execfile the script when installing, to make sure it works) - print "Running anyjson as a stand alone script is not supported" - sys.exit(1) -else: - for modspec in _modules: - try: - implementation = _JsonImplementation(modspec) - break - except ImportError: - pass - else: - raise ImportError("No supported JSON module found") - - - def loads(value): - """Serialize the object to JSON.""" - return implementation.loads(value) - deserialize = loads # compat - - - def dumps(value): - """Deserialize JSON-encoded object to a Python object.""" - return implementation.dumps(value) - serialize = dumps diff --git a/awx/lib/site-packages/argparse.py b/awx/lib/site-packages/argparse.py deleted file mode 100644 index 32d948c03c..0000000000 --- a/awx/lib/site-packages/argparse.py +++ /dev/null @@ -1,2362 +0,0 @@ -# Author: Steven J. Bethard . - -"""Command-line parsing library - -This module is an optparse-inspired command-line parsing library that: - - - handles both optional and positional arguments - - produces highly informative usage messages - - supports parsers that dispatch to sub-parsers - -The following is a simple usage example that sums integers from the -command-line and writes the result to a file:: - - parser = argparse.ArgumentParser( - description='sum the integers at the command line') - parser.add_argument( - 'integers', metavar='int', nargs='+', type=int, - help='an integer to be summed') - parser.add_argument( - '--log', default=sys.stdout, type=argparse.FileType('w'), - help='the file where the sum should be written') - args = parser.parse_args() - args.log.write('%s' % sum(args.integers)) - args.log.close() - -The module contains the following public classes: - - - ArgumentParser -- The main entry point for command-line parsing. As the - example above shows, the add_argument() method is used to populate - the parser with actions for optional and positional arguments. Then - the parse_args() method is invoked to convert the args at the - command-line into an object with attributes. - - - ArgumentError -- The exception raised by ArgumentParser objects when - there are errors with the parser's actions. Errors raised while - parsing the command-line are caught by ArgumentParser and emitted - as command-line messages. - - - FileType -- A factory for defining types of files to be created. As the - example above shows, instances of FileType are typically passed as - the type= argument of add_argument() calls. - - - Action -- The base class for parser actions. Typically actions are - selected by passing strings like 'store_true' or 'append_const' to - the action= argument of add_argument(). However, for greater - customization of ArgumentParser actions, subclasses of Action may - be defined and passed as the action= argument. - - - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter, - ArgumentDefaultsHelpFormatter -- Formatter classes which - may be passed as the formatter_class= argument to the - ArgumentParser constructor. HelpFormatter is the default, - RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser - not to change the formatting for help text, and - ArgumentDefaultsHelpFormatter adds information about argument defaults - to the help. - -All other classes in this module are considered implementation details. -(Also note that HelpFormatter and RawDescriptionHelpFormatter are only -considered public as object names -- the API of the formatter objects is -still considered an implementation detail.) -""" - -__version__ = '1.2.1' -__all__ = [ - 'ArgumentParser', - 'ArgumentError', - 'ArgumentTypeError', - 'FileType', - 'HelpFormatter', - 'ArgumentDefaultsHelpFormatter', - 'RawDescriptionHelpFormatter', - 'RawTextHelpFormatter', - 'Namespace', - 'Action', - 'ONE_OR_MORE', - 'OPTIONAL', - 'PARSER', - 'REMAINDER', - 'SUPPRESS', - 'ZERO_OR_MORE', -] - - -import copy as _copy -import os as _os -import re as _re -import sys as _sys -import textwrap as _textwrap - -from gettext import gettext as _ - -try: - set -except NameError: - # for python < 2.4 compatibility (sets module is there since 2.3): - from sets import Set as set - -try: - basestring -except NameError: - basestring = str - -try: - sorted -except NameError: - # for python < 2.4 compatibility: - def sorted(iterable, reverse=False): - result = list(iterable) - result.sort() - if reverse: - result.reverse() - return result - - -def _callable(obj): - return hasattr(obj, '__call__') or hasattr(obj, '__bases__') - - -SUPPRESS = '==SUPPRESS==' - -OPTIONAL = '?' -ZERO_OR_MORE = '*' -ONE_OR_MORE = '+' -PARSER = 'A...' -REMAINDER = '...' -_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args' - -# ============================= -# Utility functions and classes -# ============================= - -class _AttributeHolder(object): - """Abstract base class that provides __repr__. - - The __repr__ method returns a string in the format:: - ClassName(attr=name, attr=name, ...) - The attributes are determined either by a class-level attribute, - '_kwarg_names', or by inspecting the instance __dict__. - """ - - def __repr__(self): - type_name = type(self).__name__ - arg_strings = [] - for arg in self._get_args(): - arg_strings.append(repr(arg)) - for name, value in self._get_kwargs(): - arg_strings.append('%s=%r' % (name, value)) - return '%s(%s)' % (type_name, ', '.join(arg_strings)) - - def _get_kwargs(self): - return sorted(self.__dict__.items()) - - def _get_args(self): - return [] - - -def _ensure_value(namespace, name, value): - if getattr(namespace, name, None) is None: - setattr(namespace, name, value) - return getattr(namespace, name) - - -# =============== -# Formatting Help -# =============== - -class HelpFormatter(object): - """Formatter for generating usage messages and argument help strings. - - Only the name of this class is considered a public API. All the methods - provided by the class are considered an implementation detail. - """ - - def __init__(self, - prog, - indent_increment=2, - max_help_position=24, - width=None): - - # default setting for width - if width is None: - try: - width = int(_os.environ['COLUMNS']) - except (KeyError, ValueError): - width = 80 - width -= 2 - - self._prog = prog - self._indent_increment = indent_increment - self._max_help_position = max_help_position - self._width = width - - self._current_indent = 0 - self._level = 0 - self._action_max_length = 0 - - self._root_section = self._Section(self, None) - self._current_section = self._root_section - - self._whitespace_matcher = _re.compile(r'\s+') - self._long_break_matcher = _re.compile(r'\n\n\n+') - - # =============================== - # Section and indentation methods - # =============================== - def _indent(self): - self._current_indent += self._indent_increment - self._level += 1 - - def _dedent(self): - self._current_indent -= self._indent_increment - assert self._current_indent >= 0, 'Indent decreased below 0.' - self._level -= 1 - - class _Section(object): - - def __init__(self, formatter, parent, heading=None): - self.formatter = formatter - self.parent = parent - self.heading = heading - self.items = [] - - def format_help(self): - # format the indented section - if self.parent is not None: - self.formatter._indent() - join = self.formatter._join_parts - for func, args in self.items: - func(*args) - item_help = join([func(*args) for func, args in self.items]) - if self.parent is not None: - self.formatter._dedent() - - # return nothing if the section was empty - if not item_help: - return '' - - # add the heading if the section was non-empty - if self.heading is not SUPPRESS and self.heading is not None: - current_indent = self.formatter._current_indent - heading = '%*s%s:\n' % (current_indent, '', self.heading) - else: - heading = '' - - # join the section-initial newline, the heading and the help - return join(['\n', heading, item_help, '\n']) - - def _add_item(self, func, args): - self._current_section.items.append((func, args)) - - # ======================== - # Message building methods - # ======================== - def start_section(self, heading): - self._indent() - section = self._Section(self, self._current_section, heading) - self._add_item(section.format_help, []) - self._current_section = section - - def end_section(self): - self._current_section = self._current_section.parent - self._dedent() - - def add_text(self, text): - if text is not SUPPRESS and text is not None: - self._add_item(self._format_text, [text]) - - def add_usage(self, usage, actions, groups, prefix=None): - if usage is not SUPPRESS: - args = usage, actions, groups, prefix - self._add_item(self._format_usage, args) - - def add_argument(self, action): - if action.help is not SUPPRESS: - - # find all invocations - get_invocation = self._format_action_invocation - invocations = [get_invocation(action)] - for subaction in self._iter_indented_subactions(action): - invocations.append(get_invocation(subaction)) - - # update the maximum item length - invocation_length = max([len(s) for s in invocations]) - action_length = invocation_length + self._current_indent - self._action_max_length = max(self._action_max_length, - action_length) - - # add the item to the list - self._add_item(self._format_action, [action]) - - def add_arguments(self, actions): - for action in actions: - self.add_argument(action) - - # ======================= - # Help-formatting methods - # ======================= - def format_help(self): - help = self._root_section.format_help() - if help: - help = self._long_break_matcher.sub('\n\n', help) - help = help.strip('\n') + '\n' - return help - - def _join_parts(self, part_strings): - return ''.join([part - for part in part_strings - if part and part is not SUPPRESS]) - - def _format_usage(self, usage, actions, groups, prefix): - if prefix is None: - prefix = _('usage: ') - - # if usage is specified, use that - if usage is not None: - usage = usage % dict(prog=self._prog) - - # if no optionals or positionals are available, usage is just prog - elif usage is None and not actions: - usage = '%(prog)s' % dict(prog=self._prog) - - # if optionals and positionals are available, calculate usage - elif usage is None: - prog = '%(prog)s' % dict(prog=self._prog) - - # split optionals from positionals - optionals = [] - positionals = [] - for action in actions: - if action.option_strings: - optionals.append(action) - else: - positionals.append(action) - - # build full usage string - format = self._format_actions_usage - action_usage = format(optionals + positionals, groups) - usage = ' '.join([s for s in [prog, action_usage] if s]) - - # wrap the usage parts if it's too long - text_width = self._width - self._current_indent - if len(prefix) + len(usage) > text_width: - - # break usage into wrappable parts - part_regexp = r'\(.*?\)+|\[.*?\]+|\S+' - opt_usage = format(optionals, groups) - pos_usage = format(positionals, groups) - opt_parts = _re.findall(part_regexp, opt_usage) - pos_parts = _re.findall(part_regexp, pos_usage) - assert ' '.join(opt_parts) == opt_usage - assert ' '.join(pos_parts) == pos_usage - - # helper for wrapping lines - def get_lines(parts, indent, prefix=None): - lines = [] - line = [] - if prefix is not None: - line_len = len(prefix) - 1 - else: - line_len = len(indent) - 1 - for part in parts: - if line_len + 1 + len(part) > text_width: - lines.append(indent + ' '.join(line)) - line = [] - line_len = len(indent) - 1 - line.append(part) - line_len += len(part) + 1 - if line: - lines.append(indent + ' '.join(line)) - if prefix is not None: - lines[0] = lines[0][len(indent):] - return lines - - # if prog is short, follow it with optionals or positionals - if len(prefix) + len(prog) <= 0.75 * text_width: - indent = ' ' * (len(prefix) + len(prog) + 1) - if opt_parts: - lines = get_lines([prog] + opt_parts, indent, prefix) - lines.extend(get_lines(pos_parts, indent)) - elif pos_parts: - lines = get_lines([prog] + pos_parts, indent, prefix) - else: - lines = [prog] - - # if prog is long, put it on its own line - else: - indent = ' ' * len(prefix) - parts = opt_parts + pos_parts - lines = get_lines(parts, indent) - if len(lines) > 1: - lines = [] - lines.extend(get_lines(opt_parts, indent)) - lines.extend(get_lines(pos_parts, indent)) - lines = [prog] + lines - - # join lines into usage - usage = '\n'.join(lines) - - # prefix with 'usage:' - return '%s%s\n\n' % (prefix, usage) - - def _format_actions_usage(self, actions, groups): - # find group indices and identify actions in groups - group_actions = set() - inserts = {} - for group in groups: - try: - start = actions.index(group._group_actions[0]) - except ValueError: - continue - else: - end = start + len(group._group_actions) - if actions[start:end] == group._group_actions: - for action in group._group_actions: - group_actions.add(action) - if not group.required: - if start in inserts: - inserts[start] += ' [' - else: - inserts[start] = '[' - inserts[end] = ']' - else: - if start in inserts: - inserts[start] += ' (' - else: - inserts[start] = '(' - inserts[end] = ')' - for i in range(start + 1, end): - inserts[i] = '|' - - # collect all actions format strings - parts = [] - for i, action in enumerate(actions): - - # suppressed arguments are marked with None - # remove | separators for suppressed arguments - if action.help is SUPPRESS: - parts.append(None) - if inserts.get(i) == '|': - inserts.pop(i) - elif inserts.get(i + 1) == '|': - inserts.pop(i + 1) - - # produce all arg strings - elif not action.option_strings: - part = self._format_args(action, action.dest) - - # if it's in a group, strip the outer [] - if action in group_actions: - if part[0] == '[' and part[-1] == ']': - part = part[1:-1] - - # add the action string to the list - parts.append(part) - - # produce the first way to invoke the option in brackets - else: - option_string = action.option_strings[0] - - # if the Optional doesn't take a value, format is: - # -s or --long - if action.nargs == 0: - part = '%s' % option_string - - # if the Optional takes a value, format is: - # -s ARGS or --long ARGS - else: - default = action.dest.upper() - args_string = self._format_args(action, default) - part = '%s %s' % (option_string, args_string) - - # make it look optional if it's not required or in a group - if not action.required and action not in group_actions: - part = '[%s]' % part - - # add the action string to the list - parts.append(part) - - # insert things at the necessary indices - for i in sorted(inserts, reverse=True): - parts[i:i] = [inserts[i]] - - # join all the action items with spaces - text = ' '.join([item for item in parts if item is not None]) - - # clean up separators for mutually exclusive groups - open = r'[\[(]' - close = r'[\])]' - text = _re.sub(r'(%s) ' % open, r'\1', text) - text = _re.sub(r' (%s)' % close, r'\1', text) - text = _re.sub(r'%s *%s' % (open, close), r'', text) - text = _re.sub(r'\(([^|]*)\)', r'\1', text) - text = text.strip() - - # return the text - return text - - def _format_text(self, text): - if '%(prog)' in text: - text = text % dict(prog=self._prog) - text_width = self._width - self._current_indent - indent = ' ' * self._current_indent - return self._fill_text(text, text_width, indent) + '\n\n' - - def _format_action(self, action): - # determine the required width and the entry label - help_position = min(self._action_max_length + 2, - self._max_help_position) - help_width = self._width - help_position - action_width = help_position - self._current_indent - 2 - action_header = self._format_action_invocation(action) - - # ho nelp; start on same line and add a final newline - if not action.help: - tup = self._current_indent, '', action_header - action_header = '%*s%s\n' % tup - - # short action name; start on the same line and pad two spaces - elif len(action_header) <= action_width: - tup = self._current_indent, '', action_width, action_header - action_header = '%*s%-*s ' % tup - indent_first = 0 - - # long action name; start on the next line - else: - tup = self._current_indent, '', action_header - action_header = '%*s%s\n' % tup - indent_first = help_position - - # collect the pieces of the action help - parts = [action_header] - - # if there was help for the action, add lines of help text - if action.help: - help_text = self._expand_help(action) - help_lines = self._split_lines(help_text, help_width) - parts.append('%*s%s\n' % (indent_first, '', help_lines[0])) - for line in help_lines[1:]: - parts.append('%*s%s\n' % (help_position, '', line)) - - # or add a newline if the description doesn't end with one - elif not action_header.endswith('\n'): - parts.append('\n') - - # if there are any sub-actions, add their help as well - for subaction in self._iter_indented_subactions(action): - parts.append(self._format_action(subaction)) - - # return a single string - return self._join_parts(parts) - - def _format_action_invocation(self, action): - if not action.option_strings: - metavar, = self._metavar_formatter(action, action.dest)(1) - return metavar - - else: - parts = [] - - # if the Optional doesn't take a value, format is: - # -s, --long - if action.nargs == 0: - parts.extend(action.option_strings) - - # if the Optional takes a value, format is: - # -s ARGS, --long ARGS - else: - default = action.dest.upper() - args_string = self._format_args(action, default) - for option_string in action.option_strings: - parts.append('%s %s' % (option_string, args_string)) - - return ', '.join(parts) - - def _metavar_formatter(self, action, default_metavar): - if action.metavar is not None: - result = action.metavar - elif action.choices is not None: - choice_strs = [str(choice) for choice in action.choices] - result = '{%s}' % ','.join(choice_strs) - else: - result = default_metavar - - def format(tuple_size): - if isinstance(result, tuple): - return result - else: - return (result, ) * tuple_size - return format - - def _format_args(self, action, default_metavar): - get_metavar = self._metavar_formatter(action, default_metavar) - if action.nargs is None: - result = '%s' % get_metavar(1) - elif action.nargs == OPTIONAL: - result = '[%s]' % get_metavar(1) - elif action.nargs == ZERO_OR_MORE: - result = '[%s [%s ...]]' % get_metavar(2) - elif action.nargs == ONE_OR_MORE: - result = '%s [%s ...]' % get_metavar(2) - elif action.nargs == REMAINDER: - result = '...' - elif action.nargs == PARSER: - result = '%s ...' % get_metavar(1) - else: - formats = ['%s' for _ in range(action.nargs)] - result = ' '.join(formats) % get_metavar(action.nargs) - return result - - def _expand_help(self, action): - params = dict(vars(action), prog=self._prog) - for name in list(params): - if params[name] is SUPPRESS: - del params[name] - for name in list(params): - if hasattr(params[name], '__name__'): - params[name] = params[name].__name__ - if params.get('choices') is not None: - choices_str = ', '.join([str(c) for c in params['choices']]) - params['choices'] = choices_str - return self._get_help_string(action) % params - - def _iter_indented_subactions(self, action): - try: - get_subactions = action._get_subactions - except AttributeError: - pass - else: - self._indent() - for subaction in get_subactions(): - yield subaction - self._dedent() - - def _split_lines(self, text, width): - text = self._whitespace_matcher.sub(' ', text).strip() - return _textwrap.wrap(text, width) - - def _fill_text(self, text, width, indent): - text = self._whitespace_matcher.sub(' ', text).strip() - return _textwrap.fill(text, width, initial_indent=indent, - subsequent_indent=indent) - - def _get_help_string(self, action): - return action.help - - -class RawDescriptionHelpFormatter(HelpFormatter): - """Help message formatter which retains any formatting in descriptions. - - Only the name of this class is considered a public API. All the methods - provided by the class are considered an implementation detail. - """ - - def _fill_text(self, text, width, indent): - return ''.join([indent + line for line in text.splitlines(True)]) - - -class RawTextHelpFormatter(RawDescriptionHelpFormatter): - """Help message formatter which retains formatting of all help text. - - Only the name of this class is considered a public API. All the methods - provided by the class are considered an implementation detail. - """ - - def _split_lines(self, text, width): - return text.splitlines() - - -class ArgumentDefaultsHelpFormatter(HelpFormatter): - """Help message formatter which adds default values to argument help. - - Only the name of this class is considered a public API. All the methods - provided by the class are considered an implementation detail. - """ - - def _get_help_string(self, action): - help = action.help - if '%(default)' not in action.help: - if action.default is not SUPPRESS: - defaulting_nargs = [OPTIONAL, ZERO_OR_MORE] - if action.option_strings or action.nargs in defaulting_nargs: - help += ' (default: %(default)s)' - return help - - -# ===================== -# Options and Arguments -# ===================== - -def _get_action_name(argument): - if argument is None: - return None - elif argument.option_strings: - return '/'.join(argument.option_strings) - elif argument.metavar not in (None, SUPPRESS): - return argument.metavar - elif argument.dest not in (None, SUPPRESS): - return argument.dest - else: - return None - - -class ArgumentError(Exception): - """An error from creating or using an argument (optional or positional). - - The string value of this exception is the message, augmented with - information about the argument that caused it. - """ - - def __init__(self, argument, message): - self.argument_name = _get_action_name(argument) - self.message = message - - def __str__(self): - if self.argument_name is None: - format = '%(message)s' - else: - format = 'argument %(argument_name)s: %(message)s' - return format % dict(message=self.message, - argument_name=self.argument_name) - - -class ArgumentTypeError(Exception): - """An error from trying to convert a command line string to a type.""" - pass - - -# ============== -# Action classes -# ============== - -class Action(_AttributeHolder): - """Information about how to convert command line strings to Python objects. - - Action objects are used by an ArgumentParser to represent the information - needed to parse a single argument from one or more strings from the - command line. The keyword arguments to the Action constructor are also - all attributes of Action instances. - - Keyword Arguments: - - - option_strings -- A list of command-line option strings which - should be associated with this action. - - - dest -- The name of the attribute to hold the created object(s) - - - nargs -- The number of command-line arguments that should be - consumed. By default, one argument will be consumed and a single - value will be produced. Other values include: - - N (an integer) consumes N arguments (and produces a list) - - '?' consumes zero or one arguments - - '*' consumes zero or more arguments (and produces a list) - - '+' consumes one or more arguments (and produces a list) - Note that the difference between the default and nargs=1 is that - with the default, a single value will be produced, while with - nargs=1, a list containing a single value will be produced. - - - const -- The value to be produced if the option is specified and the - option uses an action that takes no values. - - - default -- The value to be produced if the option is not specified. - - - type -- The type which the command-line arguments should be converted - to, should be one of 'string', 'int', 'float', 'complex' or a - callable object that accepts a single string argument. If None, - 'string' is assumed. - - - choices -- A container of values that should be allowed. If not None, - after a command-line argument has been converted to the appropriate - type, an exception will be raised if it is not a member of this - collection. - - - required -- True if the action must always be specified at the - command line. This is only meaningful for optional command-line - arguments. - - - help -- The help string describing the argument. - - - metavar -- The name to be used for the option's argument with the - help string. If None, the 'dest' value will be used as the name. - """ - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=None, - choices=None, - required=False, - help=None, - metavar=None): - self.option_strings = option_strings - self.dest = dest - self.nargs = nargs - self.const = const - self.default = default - self.type = type - self.choices = choices - self.required = required - self.help = help - self.metavar = metavar - - def _get_kwargs(self): - names = [ - 'option_strings', - 'dest', - 'nargs', - 'const', - 'default', - 'type', - 'choices', - 'help', - 'metavar', - ] - return [(name, getattr(self, name)) for name in names] - - def __call__(self, parser, namespace, values, option_string=None): - raise NotImplementedError(_('.__call__() not defined')) - - -class _StoreAction(Action): - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=None, - choices=None, - required=False, - help=None, - metavar=None): - if nargs == 0: - raise ValueError('nargs for store actions must be > 0; if you ' - 'have nothing to store, actions such as store ' - 'true or store const may be more appropriate') - if const is not None and nargs != OPTIONAL: - raise ValueError('nargs must be %r to supply const' % OPTIONAL) - super(_StoreAction, self).__init__( - option_strings=option_strings, - dest=dest, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - setattr(namespace, self.dest, values) - - -class _StoreConstAction(Action): - - def __init__(self, - option_strings, - dest, - const, - default=None, - required=False, - help=None, - metavar=None): - super(_StoreConstAction, self).__init__( - option_strings=option_strings, - dest=dest, - nargs=0, - const=const, - default=default, - required=required, - help=help) - - def __call__(self, parser, namespace, values, option_string=None): - setattr(namespace, self.dest, self.const) - - -class _StoreTrueAction(_StoreConstAction): - - def __init__(self, - option_strings, - dest, - default=False, - required=False, - help=None): - super(_StoreTrueAction, self).__init__( - option_strings=option_strings, - dest=dest, - const=True, - default=default, - required=required, - help=help) - - -class _StoreFalseAction(_StoreConstAction): - - def __init__(self, - option_strings, - dest, - default=True, - required=False, - help=None): - super(_StoreFalseAction, self).__init__( - option_strings=option_strings, - dest=dest, - const=False, - default=default, - required=required, - help=help) - - -class _AppendAction(Action): - - def __init__(self, - option_strings, - dest, - nargs=None, - const=None, - default=None, - type=None, - choices=None, - required=False, - help=None, - metavar=None): - if nargs == 0: - raise ValueError('nargs for append actions must be > 0; if arg ' - 'strings are not supplying the value to append, ' - 'the append const action may be more appropriate') - if const is not None and nargs != OPTIONAL: - raise ValueError('nargs must be %r to supply const' % OPTIONAL) - super(_AppendAction, self).__init__( - option_strings=option_strings, - dest=dest, - nargs=nargs, - const=const, - default=default, - type=type, - choices=choices, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - items = _copy.copy(_ensure_value(namespace, self.dest, [])) - items.append(values) - setattr(namespace, self.dest, items) - - -class _AppendConstAction(Action): - - def __init__(self, - option_strings, - dest, - const, - default=None, - required=False, - help=None, - metavar=None): - super(_AppendConstAction, self).__init__( - option_strings=option_strings, - dest=dest, - nargs=0, - const=const, - default=default, - required=required, - help=help, - metavar=metavar) - - def __call__(self, parser, namespace, values, option_string=None): - items = _copy.copy(_ensure_value(namespace, self.dest, [])) - items.append(self.const) - setattr(namespace, self.dest, items) - - -class _CountAction(Action): - - def __init__(self, - option_strings, - dest, - default=None, - required=False, - help=None): - super(_CountAction, self).__init__( - option_strings=option_strings, - dest=dest, - nargs=0, - default=default, - required=required, - help=help) - - def __call__(self, parser, namespace, values, option_string=None): - new_count = _ensure_value(namespace, self.dest, 0) + 1 - setattr(namespace, self.dest, new_count) - - -class _HelpAction(Action): - - def __init__(self, - option_strings, - dest=SUPPRESS, - default=SUPPRESS, - help=None): - super(_HelpAction, self).__init__( - option_strings=option_strings, - dest=dest, - default=default, - nargs=0, - help=help) - - def __call__(self, parser, namespace, values, option_string=None): - parser.print_help() - parser.exit() - - -class _VersionAction(Action): - - def __init__(self, - option_strings, - version=None, - dest=SUPPRESS, - default=SUPPRESS, - help="show program's version number and exit"): - super(_VersionAction, self).__init__( - option_strings=option_strings, - dest=dest, - default=default, - nargs=0, - help=help) - self.version = version - - def __call__(self, parser, namespace, values, option_string=None): - version = self.version - if version is None: - version = parser.version - formatter = parser._get_formatter() - formatter.add_text(version) - parser.exit(message=formatter.format_help()) - - -class _SubParsersAction(Action): - - class _ChoicesPseudoAction(Action): - - def __init__(self, name, help): - sup = super(_SubParsersAction._ChoicesPseudoAction, self) - sup.__init__(option_strings=[], dest=name, help=help) - - def __init__(self, - option_strings, - prog, - parser_class, - dest=SUPPRESS, - help=None, - metavar=None): - - self._prog_prefix = prog - self._parser_class = parser_class - self._name_parser_map = {} - self._choices_actions = [] - - super(_SubParsersAction, self).__init__( - option_strings=option_strings, - dest=dest, - nargs=PARSER, - choices=self._name_parser_map, - help=help, - metavar=metavar) - - def add_parser(self, name, **kwargs): - # set prog from the existing prefix - if kwargs.get('prog') is None: - kwargs['prog'] = '%s %s' % (self._prog_prefix, name) - - # create a pseudo-action to hold the choice help - if 'help' in kwargs: - help = kwargs.pop('help') - choice_action = self._ChoicesPseudoAction(name, help) - self._choices_actions.append(choice_action) - - # create the parser and add it to the map - parser = self._parser_class(**kwargs) - self._name_parser_map[name] = parser - return parser - - def _get_subactions(self): - return self._choices_actions - - def __call__(self, parser, namespace, values, option_string=None): - parser_name = values[0] - arg_strings = values[1:] - - # set the parser name if requested - if self.dest is not SUPPRESS: - setattr(namespace, self.dest, parser_name) - - # select the parser - try: - parser = self._name_parser_map[parser_name] - except KeyError: - tup = parser_name, ', '.join(self._name_parser_map) - msg = _('unknown parser %r (choices: %s)' % tup) - raise ArgumentError(self, msg) - - # parse all the remaining options into the namespace - # store any unrecognized options on the object, so that the top - # level parser can decide what to do with them - namespace, arg_strings = parser.parse_known_args(arg_strings, namespace) - if arg_strings: - vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, []) - getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings) - - -# ============== -# Type classes -# ============== - -class FileType(object): - """Factory for creating file object types - - Instances of FileType are typically passed as type= arguments to the - ArgumentParser add_argument() method. - - Keyword Arguments: - - mode -- A string indicating how the file is to be opened. Accepts the - same values as the builtin open() function. - - bufsize -- The file's desired buffer size. Accepts the same values as - the builtin open() function. - """ - - def __init__(self, mode='r', bufsize=None): - self._mode = mode - self._bufsize = bufsize - - def __call__(self, string): - # the special argument "-" means sys.std{in,out} - if string == '-': - if 'r' in self._mode: - return _sys.stdin - elif 'w' in self._mode: - return _sys.stdout - else: - msg = _('argument "-" with mode %r' % self._mode) - raise ValueError(msg) - - # all other arguments are used as file names - if self._bufsize: - return open(string, self._mode, self._bufsize) - else: - return open(string, self._mode) - - def __repr__(self): - args = [self._mode, self._bufsize] - args_str = ', '.join([repr(arg) for arg in args if arg is not None]) - return '%s(%s)' % (type(self).__name__, args_str) - -# =========================== -# Optional and Positional Parsing -# =========================== - -class Namespace(_AttributeHolder): - """Simple object for storing attributes. - - Implements equality by attribute names and values, and provides a simple - string representation. - """ - - def __init__(self, **kwargs): - for name in kwargs: - setattr(self, name, kwargs[name]) - - __hash__ = None - - def __eq__(self, other): - return vars(self) == vars(other) - - def __ne__(self, other): - return not (self == other) - - def __contains__(self, key): - return key in self.__dict__ - - -class _ActionsContainer(object): - - def __init__(self, - description, - prefix_chars, - argument_default, - conflict_handler): - super(_ActionsContainer, self).__init__() - - self.description = description - self.argument_default = argument_default - self.prefix_chars = prefix_chars - self.conflict_handler = conflict_handler - - # set up registries - self._registries = {} - - # register actions - self.register('action', None, _StoreAction) - self.register('action', 'store', _StoreAction) - self.register('action', 'store_const', _StoreConstAction) - self.register('action', 'store_true', _StoreTrueAction) - self.register('action', 'store_false', _StoreFalseAction) - self.register('action', 'append', _AppendAction) - self.register('action', 'append_const', _AppendConstAction) - self.register('action', 'count', _CountAction) - self.register('action', 'help', _HelpAction) - self.register('action', 'version', _VersionAction) - self.register('action', 'parsers', _SubParsersAction) - - # raise an exception if the conflict handler is invalid - self._get_handler() - - # action storage - self._actions = [] - self._option_string_actions = {} - - # groups - self._action_groups = [] - self._mutually_exclusive_groups = [] - - # defaults storage - self._defaults = {} - - # determines whether an "option" looks like a negative number - self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$') - - # whether or not there are any optionals that look like negative - # numbers -- uses a list so it can be shared and edited - self._has_negative_number_optionals = [] - - # ==================== - # Registration methods - # ==================== - def register(self, registry_name, value, object): - registry = self._registries.setdefault(registry_name, {}) - registry[value] = object - - def _registry_get(self, registry_name, value, default=None): - return self._registries[registry_name].get(value, default) - - # ================================== - # Namespace default accessor methods - # ================================== - def set_defaults(self, **kwargs): - self._defaults.update(kwargs) - - # if these defaults match any existing arguments, replace - # the previous default on the object with the new one - for action in self._actions: - if action.dest in kwargs: - action.default = kwargs[action.dest] - - def get_default(self, dest): - for action in self._actions: - if action.dest == dest and action.default is not None: - return action.default - return self._defaults.get(dest, None) - - - # ======================= - # Adding argument actions - # ======================= - def add_argument(self, *args, **kwargs): - """ - add_argument(dest, ..., name=value, ...) - add_argument(option_string, option_string, ..., name=value, ...) - """ - - # if no positional args are supplied or only one is supplied and - # it doesn't look like an option string, parse a positional - # argument - chars = self.prefix_chars - if not args or len(args) == 1 and args[0][0] not in chars: - if args and 'dest' in kwargs: - raise ValueError('dest supplied twice for positional argument') - kwargs = self._get_positional_kwargs(*args, **kwargs) - - # otherwise, we're adding an optional argument - else: - kwargs = self._get_optional_kwargs(*args, **kwargs) - - # if no default was supplied, use the parser-level default - if 'default' not in kwargs: - dest = kwargs['dest'] - if dest in self._defaults: - kwargs['default'] = self._defaults[dest] - elif self.argument_default is not None: - kwargs['default'] = self.argument_default - - # create the action object, and add it to the parser - action_class = self._pop_action_class(kwargs) - if not _callable(action_class): - raise ValueError('unknown action "%s"' % action_class) - action = action_class(**kwargs) - - # raise an error if the action type is not callable - type_func = self._registry_get('type', action.type, action.type) - if not _callable(type_func): - raise ValueError('%r is not callable' % type_func) - - return self._add_action(action) - - def add_argument_group(self, *args, **kwargs): - group = _ArgumentGroup(self, *args, **kwargs) - self._action_groups.append(group) - return group - - def add_mutually_exclusive_group(self, **kwargs): - group = _MutuallyExclusiveGroup(self, **kwargs) - self._mutually_exclusive_groups.append(group) - return group - - def _add_action(self, action): - # resolve any conflicts - self._check_conflict(action) - - # add to actions list - self._actions.append(action) - action.container = self - - # index the action by any option strings it has - for option_string in action.option_strings: - self._option_string_actions[option_string] = action - - # set the flag if any option strings look like negative numbers - for option_string in action.option_strings: - if self._negative_number_matcher.match(option_string): - if not self._has_negative_number_optionals: - self._has_negative_number_optionals.append(True) - - # return the created action - return action - - def _remove_action(self, action): - self._actions.remove(action) - - def _add_container_actions(self, container): - # collect groups by titles - title_group_map = {} - for group in self._action_groups: - if group.title in title_group_map: - msg = _('cannot merge actions - two groups are named %r') - raise ValueError(msg % (group.title)) - title_group_map[group.title] = group - - # map each action to its group - group_map = {} - for group in container._action_groups: - - # if a group with the title exists, use that, otherwise - # create a new group matching the container's group - if group.title not in title_group_map: - title_group_map[group.title] = self.add_argument_group( - title=group.title, - description=group.description, - conflict_handler=group.conflict_handler) - - # map the actions to their new group - for action in group._group_actions: - group_map[action] = title_group_map[group.title] - - # add container's mutually exclusive groups - # NOTE: if add_mutually_exclusive_group ever gains title= and - # description= then this code will need to be expanded as above - for group in container._mutually_exclusive_groups: - mutex_group = self.add_mutually_exclusive_group( - required=group.required) - - # map the actions to their new mutex group - for action in group._group_actions: - group_map[action] = mutex_group - - # add all actions to this container or their group - for action in container._actions: - group_map.get(action, self)._add_action(action) - - def _get_positional_kwargs(self, dest, **kwargs): - # make sure required is not specified - if 'required' in kwargs: - msg = _("'required' is an invalid argument for positionals") - raise TypeError(msg) - - # mark positional arguments as required if at least one is - # always required - if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]: - kwargs['required'] = True - if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs: - kwargs['required'] = True - - # return the keyword arguments with no option strings - return dict(kwargs, dest=dest, option_strings=[]) - - def _get_optional_kwargs(self, *args, **kwargs): - # determine short and long option strings - option_strings = [] - long_option_strings = [] - for option_string in args: - # error on strings that don't start with an appropriate prefix - if not option_string[0] in self.prefix_chars: - msg = _('invalid option string %r: ' - 'must start with a character %r') - tup = option_string, self.prefix_chars - raise ValueError(msg % tup) - - # strings starting with two prefix characters are long options - option_strings.append(option_string) - if option_string[0] in self.prefix_chars: - if len(option_string) > 1: - if option_string[1] in self.prefix_chars: - long_option_strings.append(option_string) - - # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x' - dest = kwargs.pop('dest', None) - if dest is None: - if long_option_strings: - dest_option_string = long_option_strings[0] - else: - dest_option_string = option_strings[0] - dest = dest_option_string.lstrip(self.prefix_chars) - if not dest: - msg = _('dest= is required for options like %r') - raise ValueError(msg % option_string) - dest = dest.replace('-', '_') - - # return the updated keyword arguments - return dict(kwargs, dest=dest, option_strings=option_strings) - - def _pop_action_class(self, kwargs, default=None): - action = kwargs.pop('action', default) - return self._registry_get('action', action, action) - - def _get_handler(self): - # determine function from conflict handler string - handler_func_name = '_handle_conflict_%s' % self.conflict_handler - try: - return getattr(self, handler_func_name) - except AttributeError: - msg = _('invalid conflict_resolution value: %r') - raise ValueError(msg % self.conflict_handler) - - def _check_conflict(self, action): - - # find all options that conflict with this option - confl_optionals = [] - for option_string in action.option_strings: - if option_string in self._option_string_actions: - confl_optional = self._option_string_actions[option_string] - confl_optionals.append((option_string, confl_optional)) - - # resolve any conflicts - if confl_optionals: - conflict_handler = self._get_handler() - conflict_handler(action, confl_optionals) - - def _handle_conflict_error(self, action, conflicting_actions): - message = _('conflicting option string(s): %s') - conflict_string = ', '.join([option_string - for option_string, action - in conflicting_actions]) - raise ArgumentError(action, message % conflict_string) - - def _handle_conflict_resolve(self, action, conflicting_actions): - - # remove all conflicting options - for option_string, action in conflicting_actions: - - # remove the conflicting option - action.option_strings.remove(option_string) - self._option_string_actions.pop(option_string, None) - - # if the option now has no option string, remove it from the - # container holding it - if not action.option_strings: - action.container._remove_action(action) - - -class _ArgumentGroup(_ActionsContainer): - - def __init__(self, container, title=None, description=None, **kwargs): - # add any missing keyword arguments by checking the container - update = kwargs.setdefault - update('conflict_handler', container.conflict_handler) - update('prefix_chars', container.prefix_chars) - update('argument_default', container.argument_default) - super_init = super(_ArgumentGroup, self).__init__ - super_init(description=description, **kwargs) - - # group attributes - self.title = title - self._group_actions = [] - - # share most attributes with the container - self._registries = container._registries - self._actions = container._actions - self._option_string_actions = container._option_string_actions - self._defaults = container._defaults - self._has_negative_number_optionals = \ - container._has_negative_number_optionals - - def _add_action(self, action): - action = super(_ArgumentGroup, self)._add_action(action) - self._group_actions.append(action) - return action - - def _remove_action(self, action): - super(_ArgumentGroup, self)._remove_action(action) - self._group_actions.remove(action) - - -class _MutuallyExclusiveGroup(_ArgumentGroup): - - def __init__(self, container, required=False): - super(_MutuallyExclusiveGroup, self).__init__(container) - self.required = required - self._container = container - - def _add_action(self, action): - if action.required: - msg = _('mutually exclusive arguments must be optional') - raise ValueError(msg) - action = self._container._add_action(action) - self._group_actions.append(action) - return action - - def _remove_action(self, action): - self._container._remove_action(action) - self._group_actions.remove(action) - - -class ArgumentParser(_AttributeHolder, _ActionsContainer): - """Object for parsing command line strings into Python objects. - - Keyword Arguments: - - prog -- The name of the program (default: sys.argv[0]) - - usage -- A usage message (default: auto-generated from arguments) - - description -- A description of what the program does - - epilog -- Text following the argument descriptions - - parents -- Parsers whose arguments should be copied into this one - - formatter_class -- HelpFormatter class for printing help messages - - prefix_chars -- Characters that prefix optional arguments - - fromfile_prefix_chars -- Characters that prefix files containing - additional arguments - - argument_default -- The default value for all arguments - - conflict_handler -- String indicating how to handle conflicts - - add_help -- Add a -h/-help option - """ - - def __init__(self, - prog=None, - usage=None, - description=None, - epilog=None, - version=None, - parents=[], - formatter_class=HelpFormatter, - prefix_chars='-', - fromfile_prefix_chars=None, - argument_default=None, - conflict_handler='error', - add_help=True): - - if version is not None: - import warnings - warnings.warn( - """The "version" argument to ArgumentParser is deprecated. """ - """Please use """ - """"add_argument(..., action='version', version="N", ...)" """ - """instead""", DeprecationWarning) - - superinit = super(ArgumentParser, self).__init__ - superinit(description=description, - prefix_chars=prefix_chars, - argument_default=argument_default, - conflict_handler=conflict_handler) - - # default setting for prog - if prog is None: - prog = _os.path.basename(_sys.argv[0]) - - self.prog = prog - self.usage = usage - self.epilog = epilog - self.version = version - self.formatter_class = formatter_class - self.fromfile_prefix_chars = fromfile_prefix_chars - self.add_help = add_help - - add_group = self.add_argument_group - self._positionals = add_group(_('positional arguments')) - self._optionals = add_group(_('optional arguments')) - self._subparsers = None - - # register types - def identity(string): - return string - self.register('type', None, identity) - - # add help and version arguments if necessary - # (using explicit default to override global argument_default) - if '-' in prefix_chars: - default_prefix = '-' - else: - default_prefix = prefix_chars[0] - if self.add_help: - self.add_argument( - default_prefix+'h', default_prefix*2+'help', - action='help', default=SUPPRESS, - help=_('show this help message and exit')) - if self.version: - self.add_argument( - default_prefix+'v', default_prefix*2+'version', - action='version', default=SUPPRESS, - version=self.version, - help=_("show program's version number and exit")) - - # add parent arguments and defaults - for parent in parents: - self._add_container_actions(parent) - try: - defaults = parent._defaults - except AttributeError: - pass - else: - self._defaults.update(defaults) - - # ======================= - # Pretty __repr__ methods - # ======================= - def _get_kwargs(self): - names = [ - 'prog', - 'usage', - 'description', - 'version', - 'formatter_class', - 'conflict_handler', - 'add_help', - ] - return [(name, getattr(self, name)) for name in names] - - # ================================== - # Optional/Positional adding methods - # ================================== - def add_subparsers(self, **kwargs): - if self._subparsers is not None: - self.error(_('cannot have multiple subparser arguments')) - - # add the parser class to the arguments if it's not present - kwargs.setdefault('parser_class', type(self)) - - if 'title' in kwargs or 'description' in kwargs: - title = _(kwargs.pop('title', 'subcommands')) - description = _(kwargs.pop('description', None)) - self._subparsers = self.add_argument_group(title, description) - else: - self._subparsers = self._positionals - - # prog defaults to the usage message of this parser, skipping - # optional arguments and with no "usage:" prefix - if kwargs.get('prog') is None: - formatter = self._get_formatter() - positionals = self._get_positional_actions() - groups = self._mutually_exclusive_groups - formatter.add_usage(self.usage, positionals, groups, '') - kwargs['prog'] = formatter.format_help().strip() - - # create the parsers action and add it to the positionals list - parsers_class = self._pop_action_class(kwargs, 'parsers') - action = parsers_class(option_strings=[], **kwargs) - self._subparsers._add_action(action) - - # return the created parsers action - return action - - def _add_action(self, action): - if action.option_strings: - self._optionals._add_action(action) - else: - self._positionals._add_action(action) - return action - - def _get_optional_actions(self): - return [action - for action in self._actions - if action.option_strings] - - def _get_positional_actions(self): - return [action - for action in self._actions - if not action.option_strings] - - # ===================================== - # Command line argument parsing methods - # ===================================== - def parse_args(self, args=None, namespace=None): - args, argv = self.parse_known_args(args, namespace) - if argv: - msg = _('unrecognized arguments: %s') - self.error(msg % ' '.join(argv)) - return args - - def parse_known_args(self, args=None, namespace=None): - # args default to the system args - if args is None: - args = _sys.argv[1:] - - # default Namespace built from parser defaults - if namespace is None: - namespace = Namespace() - - # add any action defaults that aren't present - for action in self._actions: - if action.dest is not SUPPRESS: - if not hasattr(namespace, action.dest): - if action.default is not SUPPRESS: - default = action.default - if isinstance(action.default, basestring): - default = self._get_value(action, default) - setattr(namespace, action.dest, default) - - # add any parser defaults that aren't present - for dest in self._defaults: - if not hasattr(namespace, dest): - setattr(namespace, dest, self._defaults[dest]) - - # parse the arguments and exit if there are any errors - try: - namespace, args = self._parse_known_args(args, namespace) - if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR): - args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) - delattr(namespace, _UNRECOGNIZED_ARGS_ATTR) - return namespace, args - except ArgumentError: - err = _sys.exc_info()[1] - self.error(str(err)) - - def _parse_known_args(self, arg_strings, namespace): - # replace arg strings that are file references - if self.fromfile_prefix_chars is not None: - arg_strings = self._read_args_from_files(arg_strings) - - # map all mutually exclusive arguments to the other arguments - # they can't occur with - action_conflicts = {} - for mutex_group in self._mutually_exclusive_groups: - group_actions = mutex_group._group_actions - for i, mutex_action in enumerate(mutex_group._group_actions): - conflicts = action_conflicts.setdefault(mutex_action, []) - conflicts.extend(group_actions[:i]) - conflicts.extend(group_actions[i + 1:]) - - # find all option indices, and determine the arg_string_pattern - # which has an 'O' if there is an option at an index, - # an 'A' if there is an argument, or a '-' if there is a '--' - option_string_indices = {} - arg_string_pattern_parts = [] - arg_strings_iter = iter(arg_strings) - for i, arg_string in enumerate(arg_strings_iter): - - # all args after -- are non-options - if arg_string == '--': - arg_string_pattern_parts.append('-') - for arg_string in arg_strings_iter: - arg_string_pattern_parts.append('A') - - # otherwise, add the arg to the arg strings - # and note the index if it was an option - else: - option_tuple = self._parse_optional(arg_string) - if option_tuple is None: - pattern = 'A' - else: - option_string_indices[i] = option_tuple - pattern = 'O' - arg_string_pattern_parts.append(pattern) - - # join the pieces together to form the pattern - arg_strings_pattern = ''.join(arg_string_pattern_parts) - - # converts arg strings to the appropriate and then takes the action - seen_actions = set() - seen_non_default_actions = set() - - def take_action(action, argument_strings, option_string=None): - seen_actions.add(action) - argument_values = self._get_values(action, argument_strings) - - # error if this argument is not allowed with other previously - # seen arguments, assuming that actions that use the default - # value don't really count as "present" - if argument_values is not action.default: - seen_non_default_actions.add(action) - for conflict_action in action_conflicts.get(action, []): - if conflict_action in seen_non_default_actions: - msg = _('not allowed with argument %s') - action_name = _get_action_name(conflict_action) - raise ArgumentError(action, msg % action_name) - - # take the action if we didn't receive a SUPPRESS value - # (e.g. from a default) - if argument_values is not SUPPRESS: - action(self, namespace, argument_values, option_string) - - # function to convert arg_strings into an optional action - def consume_optional(start_index): - - # get the optional identified at this index - option_tuple = option_string_indices[start_index] - action, option_string, explicit_arg = option_tuple - - # identify additional optionals in the same arg string - # (e.g. -xyz is the same as -x -y -z if no args are required) - match_argument = self._match_argument - action_tuples = [] - while True: - - # if we found no optional action, skip it - if action is None: - extras.append(arg_strings[start_index]) - return start_index + 1 - - # if there is an explicit argument, try to match the - # optional's string arguments to only this - if explicit_arg is not None: - arg_count = match_argument(action, 'A') - - # if the action is a single-dash option and takes no - # arguments, try to parse more single-dash options out - # of the tail of the option string - chars = self.prefix_chars - if arg_count == 0 and option_string[1] not in chars: - action_tuples.append((action, [], option_string)) - char = option_string[0] - option_string = char + explicit_arg[0] - new_explicit_arg = explicit_arg[1:] or None - optionals_map = self._option_string_actions - if option_string in optionals_map: - action = optionals_map[option_string] - explicit_arg = new_explicit_arg - else: - msg = _('ignored explicit argument %r') - raise ArgumentError(action, msg % explicit_arg) - - # if the action expect exactly one argument, we've - # successfully matched the option; exit the loop - elif arg_count == 1: - stop = start_index + 1 - args = [explicit_arg] - action_tuples.append((action, args, option_string)) - break - - # error if a double-dash option did not use the - # explicit argument - else: - msg = _('ignored explicit argument %r') - raise ArgumentError(action, msg % explicit_arg) - - # if there is no explicit argument, try to match the - # optional's string arguments with the following strings - # if successful, exit the loop - else: - start = start_index + 1 - selected_patterns = arg_strings_pattern[start:] - arg_count = match_argument(action, selected_patterns) - stop = start + arg_count - args = arg_strings[start:stop] - action_tuples.append((action, args, option_string)) - break - - # add the Optional to the list and return the index at which - # the Optional's string args stopped - assert action_tuples - for action, args, option_string in action_tuples: - take_action(action, args, option_string) - return stop - - # the list of Positionals left to be parsed; this is modified - # by consume_positionals() - positionals = self._get_positional_actions() - - # function to convert arg_strings into positional actions - def consume_positionals(start_index): - # match as many Positionals as possible - match_partial = self._match_arguments_partial - selected_pattern = arg_strings_pattern[start_index:] - arg_counts = match_partial(positionals, selected_pattern) - - # slice off the appropriate arg strings for each Positional - # and add the Positional and its args to the list - for action, arg_count in zip(positionals, arg_counts): - args = arg_strings[start_index: start_index + arg_count] - start_index += arg_count - take_action(action, args) - - # slice off the Positionals that we just parsed and return the - # index at which the Positionals' string args stopped - positionals[:] = positionals[len(arg_counts):] - return start_index - - # consume Positionals and Optionals alternately, until we have - # passed the last option string - extras = [] - start_index = 0 - if option_string_indices: - max_option_string_index = max(option_string_indices) - else: - max_option_string_index = -1 - while start_index <= max_option_string_index: - - # consume any Positionals preceding the next option - next_option_string_index = min([ - index - for index in option_string_indices - if index >= start_index]) - if start_index != next_option_string_index: - positionals_end_index = consume_positionals(start_index) - - # only try to parse the next optional if we didn't consume - # the option string during the positionals parsing - if positionals_end_index > start_index: - start_index = positionals_end_index - continue - else: - start_index = positionals_end_index - - # if we consumed all the positionals we could and we're not - # at the index of an option string, there were extra arguments - if start_index not in option_string_indices: - strings = arg_strings[start_index:next_option_string_index] - extras.extend(strings) - start_index = next_option_string_index - - # consume the next optional and any arguments for it - start_index = consume_optional(start_index) - - # consume any positionals following the last Optional - stop_index = consume_positionals(start_index) - - # if we didn't consume all the argument strings, there were extras - extras.extend(arg_strings[stop_index:]) - - # if we didn't use all the Positional objects, there were too few - # arg strings supplied. - if positionals: - self.error(_('too few arguments')) - - # make sure all required actions were present - for action in self._actions: - if action.required: - if action not in seen_actions: - name = _get_action_name(action) - self.error(_('argument %s is required') % name) - - # make sure all required groups had one option present - for group in self._mutually_exclusive_groups: - if group.required: - for action in group._group_actions: - if action in seen_non_default_actions: - break - - # if no actions were used, report the error - else: - names = [_get_action_name(action) - for action in group._group_actions - if action.help is not SUPPRESS] - msg = _('one of the arguments %s is required') - self.error(msg % ' '.join(names)) - - # return the updated namespace and the extra arguments - return namespace, extras - - def _read_args_from_files(self, arg_strings): - # expand arguments referencing files - new_arg_strings = [] - for arg_string in arg_strings: - - # for regular arguments, just add them back into the list - if arg_string[0] not in self.fromfile_prefix_chars: - new_arg_strings.append(arg_string) - - # replace arguments referencing files with the file content - else: - try: - args_file = open(arg_string[1:]) - try: - arg_strings = [] - for arg_line in args_file.read().splitlines(): - for arg in self.convert_arg_line_to_args(arg_line): - arg_strings.append(arg) - arg_strings = self._read_args_from_files(arg_strings) - new_arg_strings.extend(arg_strings) - finally: - args_file.close() - except IOError: - err = _sys.exc_info()[1] - self.error(str(err)) - - # return the modified argument list - return new_arg_strings - - def convert_arg_line_to_args(self, arg_line): - return [arg_line] - - def _match_argument(self, action, arg_strings_pattern): - # match the pattern for this action to the arg strings - nargs_pattern = self._get_nargs_pattern(action) - match = _re.match(nargs_pattern, arg_strings_pattern) - - # raise an exception if we weren't able to find a match - if match is None: - nargs_errors = { - None: _('expected one argument'), - OPTIONAL: _('expected at most one argument'), - ONE_OR_MORE: _('expected at least one argument'), - } - default = _('expected %s argument(s)') % action.nargs - msg = nargs_errors.get(action.nargs, default) - raise ArgumentError(action, msg) - - # return the number of arguments matched - return len(match.group(1)) - - def _match_arguments_partial(self, actions, arg_strings_pattern): - # progressively shorten the actions list by slicing off the - # final actions until we find a match - result = [] - for i in range(len(actions), 0, -1): - actions_slice = actions[:i] - pattern = ''.join([self._get_nargs_pattern(action) - for action in actions_slice]) - match = _re.match(pattern, arg_strings_pattern) - if match is not None: - result.extend([len(string) for string in match.groups()]) - break - - # return the list of arg string counts - return result - - def _parse_optional(self, arg_string): - # if it's an empty string, it was meant to be a positional - if not arg_string: - return None - - # if it doesn't start with a prefix, it was meant to be positional - if not arg_string[0] in self.prefix_chars: - return None - - # if the option string is present in the parser, return the action - if arg_string in self._option_string_actions: - action = self._option_string_actions[arg_string] - return action, arg_string, None - - # if it's just a single character, it was meant to be positional - if len(arg_string) == 1: - return None - - # if the option string before the "=" is present, return the action - if '=' in arg_string: - option_string, explicit_arg = arg_string.split('=', 1) - if option_string in self._option_string_actions: - action = self._option_string_actions[option_string] - return action, option_string, explicit_arg - - # search through all possible prefixes of the option string - # and all actions in the parser for possible interpretations - option_tuples = self._get_option_tuples(arg_string) - - # if multiple actions match, the option string was ambiguous - if len(option_tuples) > 1: - options = ', '.join([option_string - for action, option_string, explicit_arg in option_tuples]) - tup = arg_string, options - self.error(_('ambiguous option: %s could match %s') % tup) - - # if exactly one action matched, this segmentation is good, - # so return the parsed action - elif len(option_tuples) == 1: - option_tuple, = option_tuples - return option_tuple - - # if it was not found as an option, but it looks like a negative - # number, it was meant to be positional - # unless there are negative-number-like options - if self._negative_number_matcher.match(arg_string): - if not self._has_negative_number_optionals: - return None - - # if it contains a space, it was meant to be a positional - if ' ' in arg_string: - return None - - # it was meant to be an optional but there is no such option - # in this parser (though it might be a valid option in a subparser) - return None, arg_string, None - - def _get_option_tuples(self, option_string): - result = [] - - # option strings starting with two prefix characters are only - # split at the '=' - chars = self.prefix_chars - if option_string[0] in chars and option_string[1] in chars: - if '=' in option_string: - option_prefix, explicit_arg = option_string.split('=', 1) - else: - option_prefix = option_string - explicit_arg = None - for option_string in self._option_string_actions: - if option_string.startswith(option_prefix): - action = self._option_string_actions[option_string] - tup = action, option_string, explicit_arg - result.append(tup) - - # single character options can be concatenated with their arguments - # but multiple character options always have to have their argument - # separate - elif option_string[0] in chars and option_string[1] not in chars: - option_prefix = option_string - explicit_arg = None - short_option_prefix = option_string[:2] - short_explicit_arg = option_string[2:] - - for option_string in self._option_string_actions: - if option_string == short_option_prefix: - action = self._option_string_actions[option_string] - tup = action, option_string, short_explicit_arg - result.append(tup) - elif option_string.startswith(option_prefix): - action = self._option_string_actions[option_string] - tup = action, option_string, explicit_arg - result.append(tup) - - # shouldn't ever get here - else: - self.error(_('unexpected option string: %s') % option_string) - - # return the collected option tuples - return result - - def _get_nargs_pattern(self, action): - # in all examples below, we have to allow for '--' args - # which are represented as '-' in the pattern - nargs = action.nargs - - # the default (None) is assumed to be a single argument - if nargs is None: - nargs_pattern = '(-*A-*)' - - # allow zero or one arguments - elif nargs == OPTIONAL: - nargs_pattern = '(-*A?-*)' - - # allow zero or more arguments - elif nargs == ZERO_OR_MORE: - nargs_pattern = '(-*[A-]*)' - - # allow one or more arguments - elif nargs == ONE_OR_MORE: - nargs_pattern = '(-*A[A-]*)' - - # allow any number of options or arguments - elif nargs == REMAINDER: - nargs_pattern = '([-AO]*)' - - # allow one argument followed by any number of options or arguments - elif nargs == PARSER: - nargs_pattern = '(-*A[-AO]*)' - - # all others should be integers - else: - nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs) - - # if this is an optional action, -- is not allowed - if action.option_strings: - nargs_pattern = nargs_pattern.replace('-*', '') - nargs_pattern = nargs_pattern.replace('-', '') - - # return the pattern - return nargs_pattern - - # ======================== - # Value conversion methods - # ======================== - def _get_values(self, action, arg_strings): - # for everything but PARSER args, strip out '--' - if action.nargs not in [PARSER, REMAINDER]: - arg_strings = [s for s in arg_strings if s != '--'] - - # optional argument produces a default when not present - if not arg_strings and action.nargs == OPTIONAL: - if action.option_strings: - value = action.const - else: - value = action.default - if isinstance(value, basestring): - value = self._get_value(action, value) - self._check_value(action, value) - - # when nargs='*' on a positional, if there were no command-line - # args, use the default if it is anything other than None - elif (not arg_strings and action.nargs == ZERO_OR_MORE and - not action.option_strings): - if action.default is not None: - value = action.default - else: - value = arg_strings - self._check_value(action, value) - - # single argument or optional argument produces a single value - elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]: - arg_string, = arg_strings - value = self._get_value(action, arg_string) - self._check_value(action, value) - - # REMAINDER arguments convert all values, checking none - elif action.nargs == REMAINDER: - value = [self._get_value(action, v) for v in arg_strings] - - # PARSER arguments convert all values, but check only the first - elif action.nargs == PARSER: - value = [self._get_value(action, v) for v in arg_strings] - self._check_value(action, value[0]) - - # all other types of nargs produce a list - else: - value = [self._get_value(action, v) for v in arg_strings] - for v in value: - self._check_value(action, v) - - # return the converted value - return value - - def _get_value(self, action, arg_string): - type_func = self._registry_get('type', action.type, action.type) - if not _callable(type_func): - msg = _('%r is not callable') - raise ArgumentError(action, msg % type_func) - - # convert the value to the appropriate type - try: - result = type_func(arg_string) - - # ArgumentTypeErrors indicate errors - except ArgumentTypeError: - name = getattr(action.type, '__name__', repr(action.type)) - msg = str(_sys.exc_info()[1]) - raise ArgumentError(action, msg) - - # TypeErrors or ValueErrors also indicate errors - except (TypeError, ValueError): - name = getattr(action.type, '__name__', repr(action.type)) - msg = _('invalid %s value: %r') - raise ArgumentError(action, msg % (name, arg_string)) - - # return the converted value - return result - - def _check_value(self, action, value): - # converted value must be one of the choices (if specified) - if action.choices is not None and value not in action.choices: - tup = value, ', '.join(map(repr, action.choices)) - msg = _('invalid choice: %r (choose from %s)') % tup - raise ArgumentError(action, msg) - - # ======================= - # Help-formatting methods - # ======================= - def format_usage(self): - formatter = self._get_formatter() - formatter.add_usage(self.usage, self._actions, - self._mutually_exclusive_groups) - return formatter.format_help() - - def format_help(self): - formatter = self._get_formatter() - - # usage - formatter.add_usage(self.usage, self._actions, - self._mutually_exclusive_groups) - - # description - formatter.add_text(self.description) - - # positionals, optionals and user-defined groups - for action_group in self._action_groups: - formatter.start_section(action_group.title) - formatter.add_text(action_group.description) - formatter.add_arguments(action_group._group_actions) - formatter.end_section() - - # epilog - formatter.add_text(self.epilog) - - # determine help from format above - return formatter.format_help() - - def format_version(self): - import warnings - warnings.warn( - 'The format_version method is deprecated -- the "version" ' - 'argument to ArgumentParser is no longer supported.', - DeprecationWarning) - formatter = self._get_formatter() - formatter.add_text(self.version) - return formatter.format_help() - - def _get_formatter(self): - return self.formatter_class(prog=self.prog) - - # ===================== - # Help-printing methods - # ===================== - def print_usage(self, file=None): - if file is None: - file = _sys.stdout - self._print_message(self.format_usage(), file) - - def print_help(self, file=None): - if file is None: - file = _sys.stdout - self._print_message(self.format_help(), file) - - def print_version(self, file=None): - import warnings - warnings.warn( - 'The print_version method is deprecated -- the "version" ' - 'argument to ArgumentParser is no longer supported.', - DeprecationWarning) - self._print_message(self.format_version(), file) - - def _print_message(self, message, file=None): - if message: - if file is None: - file = _sys.stderr - file.write(message) - - # =============== - # Exiting methods - # =============== - def exit(self, status=0, message=None): - if message: - self._print_message(message, _sys.stderr) - _sys.exit(status) - - def error(self, message): - """error(message: string) - - Prints a usage message incorporating the message to stderr and - exits. - - If you override this in a subclass, it should not return -- it - should either exit or raise an exception. - """ - self.print_usage(_sys.stderr) - self.exit(2, _('%s: error: %s\n') % (self.prog, message)) diff --git a/awx/lib/site-packages/azure/__init__.py b/awx/lib/site-packages/azure/__init__.py deleted file mode 100644 index 0e9250de04..0000000000 --- a/awx/lib/site-packages/azure/__init__.py +++ /dev/null @@ -1,999 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import ast -import base64 -import hashlib -import hmac -import sys -import types -import warnings -if sys.version_info < (3,): - from urllib2 import quote as url_quote - from urllib2 import unquote as url_unquote - _strtype = basestring -else: - from urllib.parse import quote as url_quote - from urllib.parse import unquote as url_unquote - _strtype = str - -from datetime import datetime -from xml.dom import minidom -from xml.sax.saxutils import escape as xml_escape - -#-------------------------------------------------------------------------- -# constants - -__author__ = 'Microsoft Corp. ' -__version__ = '0.9.0' - -# Live ServiceClient URLs -BLOB_SERVICE_HOST_BASE = '.blob.core.windows.net' -QUEUE_SERVICE_HOST_BASE = '.queue.core.windows.net' -TABLE_SERVICE_HOST_BASE = '.table.core.windows.net' -SERVICE_BUS_HOST_BASE = '.servicebus.windows.net' -MANAGEMENT_HOST = 'management.core.windows.net' - -# Development ServiceClient URLs -DEV_BLOB_HOST = '127.0.0.1:10000' -DEV_QUEUE_HOST = '127.0.0.1:10001' -DEV_TABLE_HOST = '127.0.0.1:10002' - -# Default credentials for Development Storage Service -DEV_ACCOUNT_NAME = 'devstoreaccount1' -DEV_ACCOUNT_KEY = 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==' - -# All of our error messages -_ERROR_CANNOT_FIND_PARTITION_KEY = 'Cannot find partition key in request.' -_ERROR_CANNOT_FIND_ROW_KEY = 'Cannot find row key in request.' -_ERROR_INCORRECT_TABLE_IN_BATCH = \ - 'Table should be the same in a batch operations' -_ERROR_INCORRECT_PARTITION_KEY_IN_BATCH = \ - 'Partition Key should be the same in a batch operations' -_ERROR_DUPLICATE_ROW_KEY_IN_BATCH = \ - 'Row Keys should not be the same in a batch operations' -_ERROR_BATCH_COMMIT_FAIL = 'Batch Commit Fail' -_ERROR_MESSAGE_NOT_PEEK_LOCKED_ON_DELETE = \ - 'Message is not peek locked and cannot be deleted.' -_ERROR_MESSAGE_NOT_PEEK_LOCKED_ON_UNLOCK = \ - 'Message is not peek locked and cannot be unlocked.' -_ERROR_QUEUE_NOT_FOUND = 'Queue was not found' -_ERROR_TOPIC_NOT_FOUND = 'Topic was not found' -_ERROR_CONFLICT = 'Conflict ({0})' -_ERROR_NOT_FOUND = 'Not found ({0})' -_ERROR_UNKNOWN = 'Unknown error ({0})' -_ERROR_SERVICEBUS_MISSING_INFO = \ - 'You need to provide servicebus namespace, access key and Issuer' -_ERROR_STORAGE_MISSING_INFO = \ - 'You need to provide both account name and access key' -_ERROR_ACCESS_POLICY = \ - 'share_access_policy must be either SignedIdentifier or AccessPolicy ' + \ - 'instance' -_WARNING_VALUE_SHOULD_BE_BYTES = \ - 'Warning: {0} must be bytes data type. It will be converted ' + \ - 'automatically, with utf-8 text encoding.' -_ERROR_VALUE_SHOULD_BE_BYTES = '{0} should be of type bytes.' -_ERROR_VALUE_NONE = '{0} should not be None.' -_ERROR_VALUE_NEGATIVE = '{0} should not be negative.' -_ERROR_CANNOT_SERIALIZE_VALUE_TO_ENTITY = \ - 'Cannot serialize the specified value ({0}) to an entity. Please use ' + \ - 'an EntityProperty (which can specify custom types), int, str, bool, ' + \ - 'or datetime.' -_ERROR_PAGE_BLOB_SIZE_ALIGNMENT = \ - 'Invalid page blob size: {0}. ' + \ - 'The size must be aligned to a 512-byte boundary.' - -_USER_AGENT_STRING = 'pyazure/' + __version__ - -METADATA_NS = 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata' - - -class WindowsAzureData(object): - - ''' This is the base of data class. - It is only used to check whether it is instance or not. ''' - pass - -class WindowsAzureError(Exception): - - ''' WindowsAzure Exception base class. ''' - - def __init__(self, message): - super(WindowsAzureError, self).__init__(message) - - -class WindowsAzureConflictError(WindowsAzureError): - - '''Indicates that the resource could not be created because it already - exists''' - - def __init__(self, message): - super(WindowsAzureConflictError, self).__init__(message) - - -class WindowsAzureMissingResourceError(WindowsAzureError): - - '''Indicates that a request for a request for a resource (queue, table, - container, etc...) failed because the specified resource does not exist''' - - def __init__(self, message): - super(WindowsAzureMissingResourceError, self).__init__(message) - - -class WindowsAzureBatchOperationError(WindowsAzureError): - - '''Indicates that a batch operation failed''' - - def __init__(self, message, code): - super(WindowsAzureBatchOperationError, self).__init__(message) - self.code = code - - -class Feed(object): - pass - - -class _Base64String(str): - pass - - -class HeaderDict(dict): - - def __getitem__(self, index): - return super(HeaderDict, self).__getitem__(index.lower()) - - -def _encode_base64(data): - if isinstance(data, _unicode_type): - data = data.encode('utf-8') - encoded = base64.b64encode(data) - return encoded.decode('utf-8') - - -def _decode_base64_to_bytes(data): - if isinstance(data, _unicode_type): - data = data.encode('utf-8') - return base64.b64decode(data) - - -def _decode_base64_to_text(data): - decoded_bytes = _decode_base64_to_bytes(data) - return decoded_bytes.decode('utf-8') - - -def _get_readable_id(id_name, id_prefix_to_skip): - """simplified an id to be more friendly for us people""" - # id_name is in the form 'https://namespace.host.suffix/name' - # where name may contain a forward slash! - pos = id_name.find('//') - if pos != -1: - pos += 2 - if id_prefix_to_skip: - pos = id_name.find(id_prefix_to_skip, pos) - if pos != -1: - pos += len(id_prefix_to_skip) - pos = id_name.find('/', pos) - if pos != -1: - return id_name[pos + 1:] - return id_name - - -def _get_entry_properties_from_node(entry, include_id, id_prefix_to_skip=None, use_title_as_id=False): - ''' get properties from entry xml ''' - properties = {} - - etag = entry.getAttributeNS(METADATA_NS, 'etag') - if etag: - properties['etag'] = etag - for updated in _get_child_nodes(entry, 'updated'): - properties['updated'] = updated.firstChild.nodeValue - for name in _get_children_from_path(entry, 'author', 'name'): - if name.firstChild is not None: - properties['author'] = name.firstChild.nodeValue - - if include_id: - if use_title_as_id: - for title in _get_child_nodes(entry, 'title'): - properties['name'] = title.firstChild.nodeValue - else: - for id in _get_child_nodes(entry, 'id'): - properties['name'] = _get_readable_id( - id.firstChild.nodeValue, id_prefix_to_skip) - - return properties - - -def _get_entry_properties(xmlstr, include_id, id_prefix_to_skip=None): - ''' get properties from entry xml ''' - xmldoc = minidom.parseString(xmlstr) - properties = {} - - for entry in _get_child_nodes(xmldoc, 'entry'): - properties.update(_get_entry_properties_from_node(entry, include_id, id_prefix_to_skip)) - - return properties - - -def _get_first_child_node_value(parent_node, node_name): - xml_attrs = _get_child_nodes(parent_node, node_name) - if xml_attrs: - xml_attr = xml_attrs[0] - if xml_attr.firstChild: - value = xml_attr.firstChild.nodeValue - return value - - -def _get_child_nodes(node, tagName): - return [childNode for childNode in node.getElementsByTagName(tagName) - if childNode.parentNode == node] - - -def _get_children_from_path(node, *path): - '''descends through a hierarchy of nodes returning the list of children - at the inner most level. Only returns children who share a common parent, - not cousins.''' - cur = node - for index, child in enumerate(path): - if isinstance(child, _strtype): - next = _get_child_nodes(cur, child) - else: - next = _get_child_nodesNS(cur, *child) - if index == len(path) - 1: - return next - elif not next: - break - - cur = next[0] - return [] - - -def _get_child_nodesNS(node, ns, tagName): - return [childNode for childNode in node.getElementsByTagNameNS(ns, tagName) - if childNode.parentNode == node] - - -def _create_entry(entry_body): - ''' Adds common part of entry to a given entry body and return the whole - xml. ''' - updated_str = datetime.utcnow().isoformat() - if datetime.utcnow().utcoffset() is None: - updated_str += '+00:00' - - entry_start = ''' - -<updated>{updated}</updated><author><name /></author><id /> -<content type="application/xml"> - {body}</content></entry>''' - return entry_start.format(updated=updated_str, body=entry_body) - - -def _to_datetime(strtime): - return datetime.strptime(strtime, "%Y-%m-%dT%H:%M:%S.%f") - -_KNOWN_SERIALIZATION_XFORMS = { - 'include_apis': 'IncludeAPIs', - 'message_id': 'MessageId', - 'content_md5': 'Content-MD5', - 'last_modified': 'Last-Modified', - 'cache_control': 'Cache-Control', - 'account_admin_live_email_id': 'AccountAdminLiveEmailId', - 'service_admin_live_email_id': 'ServiceAdminLiveEmailId', - 'subscription_id': 'SubscriptionID', - 'fqdn': 'FQDN', - 'private_id': 'PrivateID', - 'os_virtual_hard_disk': 'OSVirtualHardDisk', - 'logical_disk_size_in_gb': 'LogicalDiskSizeInGB', - 'logical_size_in_gb': 'LogicalSizeInGB', - 'os': 'OS', - 'persistent_vm_downtime_info': 'PersistentVMDowntimeInfo', - 'copy_id': 'CopyId', - 'os_state': 'OSState', - 'vm_image': 'VMImage', - 'vm_images': 'VMImages', - 'os_disk_configuration': 'OSDiskConfiguration', - 'public_ips': 'PublicIPs', - 'public_ip': 'PublicIP', - 'supported_os': 'SupportedOS', - 'reserved_ip': 'ReservedIP', - 'reserved_ips': 'ReservedIPs', - 'aad_tenant_id': 'AADTenantID', - 'start_ip_address': 'StartIPAddress', - 'end_ip_address': 'EndIPAddress', - } - - -def _get_serialization_name(element_name): - """converts a Python name into a serializable name""" - known = _KNOWN_SERIALIZATION_XFORMS.get(element_name) - if known is not None: - return known - - if element_name.startswith('x_ms_'): - return element_name.replace('_', '-') - if element_name.endswith('_id'): - element_name = element_name.replace('_id', 'ID') - for name in ['content_', 'last_modified', 'if_', 'cache_control']: - if element_name.startswith(name): - element_name = element_name.replace('_', '-_') - - return ''.join(name.capitalize() for name in element_name.split('_')) - -if sys.version_info < (3,): - _unicode_type = unicode - - def _str(value): - if isinstance(value, unicode): - return value.encode('utf-8') - - return str(value) -else: - _str = str - _unicode_type = str - - -def _str_or_none(value): - if value is None: - return None - - return _str(value) - - -def _int_or_none(value): - if value is None: - return None - - return str(int(value)) - - -def _bool_or_none(value): - if value is None: - return None - - if isinstance(value, bool): - if value: - return 'true' - else: - return 'false' - - return str(value) - - -def _convert_class_to_xml(source, xml_prefix=True): - if source is None: - return '' - - xmlstr = '' - if xml_prefix: - xmlstr = '<?xml version="1.0" encoding="utf-8"?>' - - if isinstance(source, list): - for value in source: - xmlstr += _convert_class_to_xml(value, False) - elif isinstance(source, WindowsAzureData): - class_name = source.__class__.__name__ - xmlstr += '<' + class_name + '>' - for name, value in vars(source).items(): - if value is not None: - if isinstance(value, list) or \ - isinstance(value, WindowsAzureData): - xmlstr += _convert_class_to_xml(value, False) - else: - xmlstr += ('<' + _get_serialization_name(name) + '>' + - xml_escape(str(value)) + '</' + - _get_serialization_name(name) + '>') - xmlstr += '</' + class_name + '>' - return xmlstr - - -def _find_namespaces_from_child(parent, child, namespaces): - """Recursively searches from the parent to the child, - gathering all the applicable namespaces along the way""" - for cur_child in parent.childNodes: - if cur_child is child: - return True - if _find_namespaces_from_child(cur_child, child, namespaces): - # we are the parent node - for key in cur_child.attributes.keys(): - if key.startswith('xmlns:') or key == 'xmlns': - namespaces[key] = cur_child.attributes[key] - break - return False - - -def _find_namespaces(parent, child): - res = {} - for key in parent.documentElement.attributes.keys(): - if key.startswith('xmlns:') or key == 'xmlns': - res[key] = parent.documentElement.attributes[key] - _find_namespaces_from_child(parent, child, res) - return res - - -def _clone_node_with_namespaces(node_to_clone, original_doc): - clone = node_to_clone.cloneNode(True) - - for key, value in _find_namespaces(original_doc, node_to_clone).items(): - clone.attributes[key] = value - - return clone - - -def _convert_response_to_feeds(response, convert_func): - if response is None: - return None - - feeds = _list_of(Feed) - - x_ms_continuation = HeaderDict() - for name, value in response.headers: - if 'x-ms-continuation' in name: - x_ms_continuation[name[len('x-ms-continuation') + 1:]] = value - if x_ms_continuation: - setattr(feeds, 'x_ms_continuation', x_ms_continuation) - - xmldoc = minidom.parseString(response.body) - xml_entries = _get_children_from_path(xmldoc, 'feed', 'entry') - if not xml_entries: - # in some cases, response contains only entry but no feed - xml_entries = _get_children_from_path(xmldoc, 'entry') - for xml_entry in xml_entries: - new_node = _clone_node_with_namespaces(xml_entry, xmldoc) - feeds.append(convert_func(new_node.toxml('utf-8'))) - - return feeds - - -def _convert_xml_to_windows_azure_object(xmlstr, azure_type, include_id=True, use_title_as_id=True): - xmldoc = minidom.parseString(xmlstr) - return_obj = azure_type() - xml_name = azure_type._xml_name if hasattr(azure_type, '_xml_name') else azure_type.__name__ - - # Only one entry here - for xml_entry in _get_children_from_path(xmldoc, - 'entry'): - for node in _get_children_from_path(xml_entry, - 'content', - xml_name): - _fill_data_to_return_object(node, return_obj) - for name, value in _get_entry_properties_from_node(xml_entry, - include_id=include_id, - use_title_as_id=use_title_as_id).items(): - setattr(return_obj, name, value) - return return_obj - - -def _validate_type_bytes(param_name, param): - if not isinstance(param, bytes): - raise TypeError(_ERROR_VALUE_SHOULD_BE_BYTES.format(param_name)) - - -def _validate_not_none(param_name, param): - if param is None: - raise TypeError(_ERROR_VALUE_NONE.format(param_name)) - - -def _fill_list_of(xmldoc, element_type, xml_element_name): - xmlelements = _get_child_nodes(xmldoc, xml_element_name) - return [_parse_response_body_from_xml_node(xmlelement, element_type) \ - for xmlelement in xmlelements] - - -def _fill_scalar_list_of(xmldoc, element_type, parent_xml_element_name, - xml_element_name): - '''Converts an xml fragment into a list of scalar types. The parent xml - element contains a flat list of xml elements which are converted into the - specified scalar type and added to the list. - Example: - xmldoc= -<Endpoints> - <Endpoint>http://{storage-service-name}.blob.core.windows.net/</Endpoint> - <Endpoint>http://{storage-service-name}.queue.core.windows.net/</Endpoint> - <Endpoint>http://{storage-service-name}.table.core.windows.net/</Endpoint> -</Endpoints> - element_type=str - parent_xml_element_name='Endpoints' - xml_element_name='Endpoint' - ''' - xmlelements = _get_child_nodes(xmldoc, parent_xml_element_name) - if xmlelements: - xmlelements = _get_child_nodes(xmlelements[0], xml_element_name) - return [_get_node_value(xmlelement, element_type) \ - for xmlelement in xmlelements] - - -def _fill_dict(xmldoc, element_name): - xmlelements = _get_child_nodes(xmldoc, element_name) - if xmlelements: - return_obj = {} - for child in xmlelements[0].childNodes: - if child.firstChild: - return_obj[child.nodeName] = child.firstChild.nodeValue - return return_obj - - -def _fill_dict_of(xmldoc, parent_xml_element_name, pair_xml_element_name, - key_xml_element_name, value_xml_element_name): - '''Converts an xml fragment into a dictionary. The parent xml element - contains a list of xml elements where each element has a child element for - the key, and another for the value. - Example: - xmldoc= -<ExtendedProperties> - <ExtendedProperty> - <Name>Ext1</Name> - <Value>Val1</Value> - </ExtendedProperty> - <ExtendedProperty> - <Name>Ext2</Name> - <Value>Val2</Value> - </ExtendedProperty> -</ExtendedProperties> - element_type=str - parent_xml_element_name='ExtendedProperties' - pair_xml_element_name='ExtendedProperty' - key_xml_element_name='Name' - value_xml_element_name='Value' - ''' - return_obj = {} - - xmlelements = _get_child_nodes(xmldoc, parent_xml_element_name) - if xmlelements: - xmlelements = _get_child_nodes(xmlelements[0], pair_xml_element_name) - for pair in xmlelements: - keys = _get_child_nodes(pair, key_xml_element_name) - values = _get_child_nodes(pair, value_xml_element_name) - if keys and values: - key = keys[0].firstChild.nodeValue - value = values[0].firstChild.nodeValue - return_obj[key] = value - - return return_obj - - -def _fill_instance_child(xmldoc, element_name, return_type): - '''Converts a child of the current dom element to the specified type. - ''' - xmlelements = _get_child_nodes( - xmldoc, _get_serialization_name(element_name)) - - if not xmlelements: - return None - - return_obj = return_type() - _fill_data_to_return_object(xmlelements[0], return_obj) - - return return_obj - - -def _fill_instance_element(element, return_type): - """Converts a DOM element into the specified object""" - return _parse_response_body_from_xml_node(element, return_type) - - -def _fill_data_minidom(xmldoc, element_name, data_member): - xmlelements = _get_child_nodes( - xmldoc, _get_serialization_name(element_name)) - - if not xmlelements or not xmlelements[0].childNodes: - return None - - value = xmlelements[0].firstChild.nodeValue - - if data_member is None: - return value - elif isinstance(data_member, datetime): - return _to_datetime(value) - elif type(data_member) is bool: - return value.lower() != 'false' - else: - return type(data_member)(value) - - -def _get_node_value(xmlelement, data_type): - value = xmlelement.firstChild.nodeValue - if data_type is datetime: - return _to_datetime(value) - elif data_type is bool: - return value.lower() != 'false' - else: - return data_type(value) - - -def _get_request_body_bytes_only(param_name, param_value): - '''Validates the request body passed in and converts it to bytes - if our policy allows it.''' - if param_value is None: - return b'' - - if isinstance(param_value, bytes): - return param_value - - # Previous versions of the SDK allowed data types other than bytes to be - # passed in, and they would be auto-converted to bytes. We preserve this - # behavior when running under 2.7, but issue a warning. - # Python 3 support is new, so we reject anything that's not bytes. - if sys.version_info < (3,): - warnings.warn(_WARNING_VALUE_SHOULD_BE_BYTES.format(param_name)) - return _get_request_body(param_value) - - raise TypeError(_ERROR_VALUE_SHOULD_BE_BYTES.format(param_name)) - - -def _get_request_body(request_body): - '''Converts an object into a request body. If it's None - we'll return an empty string, if it's one of our objects it'll - convert it to XML and return it. Otherwise we just use the object - directly''' - if request_body is None: - return b'' - - if isinstance(request_body, WindowsAzureData): - request_body = _convert_class_to_xml(request_body) - - if isinstance(request_body, bytes): - return request_body - - if isinstance(request_body, _unicode_type): - return request_body.encode('utf-8') - - request_body = str(request_body) - if isinstance(request_body, _unicode_type): - return request_body.encode('utf-8') - - return request_body - - -def _parse_enum_results_list(response, return_type, resp_type, item_type): - """resp_body is the XML we received -resp_type is a string, such as Containers, -return_type is the type we're constructing, such as ContainerEnumResults -item_type is the type object of the item to be created, such as Container - -This function then returns a ContainerEnumResults object with the -containers member populated with the results. -""" - - # parsing something like: - # <EnumerationResults ... > - # <Queues> - # <Queue> - # <Something /> - # <SomethingElse /> - # </Queue> - # </Queues> - # </EnumerationResults> - respbody = response.body - return_obj = return_type() - doc = minidom.parseString(respbody) - - items = [] - for enum_results in _get_child_nodes(doc, 'EnumerationResults'): - # path is something like Queues, Queue - for child in _get_children_from_path(enum_results, - resp_type, - resp_type[:-1]): - items.append(_fill_instance_element(child, item_type)) - - for name, value in vars(return_obj).items(): - # queues, Queues, this is the list its self which we populated - # above - if name == resp_type.lower(): - # the list its self. - continue - value = _fill_data_minidom(enum_results, name, value) - if value is not None: - setattr(return_obj, name, value) - - setattr(return_obj, resp_type.lower(), items) - return return_obj - - -def _parse_simple_list(response, type, item_type, list_name): - respbody = response.body - res = type() - res_items = [] - doc = minidom.parseString(respbody) - type_name = type.__name__ - item_name = item_type.__name__ - for item in _get_children_from_path(doc, type_name, item_name): - res_items.append(_fill_instance_element(item, item_type)) - - setattr(res, list_name, res_items) - return res - - -def _parse_response(response, return_type): - ''' - Parse the HTTPResponse's body and fill all the data into a class of - return_type. - ''' - return _parse_response_body_from_xml_text(response.body, return_type) - -def _parse_service_resources_response(response, return_type): - ''' - Parse the HTTPResponse's body and fill all the data into a class of - return_type. - ''' - return _parse_response_body_from_service_resources_xml_text(response.body, return_type) - - -def _fill_data_to_return_object(node, return_obj): - members = dict(vars(return_obj)) - for name, value in members.items(): - if isinstance(value, _list_of): - setattr(return_obj, - name, - _fill_list_of(node, - value.list_type, - value.xml_element_name)) - elif isinstance(value, _scalar_list_of): - setattr(return_obj, - name, - _fill_scalar_list_of(node, - value.list_type, - _get_serialization_name(name), - value.xml_element_name)) - elif isinstance(value, _dict_of): - setattr(return_obj, - name, - _fill_dict_of(node, - _get_serialization_name(name), - value.pair_xml_element_name, - value.key_xml_element_name, - value.value_xml_element_name)) - elif isinstance(value, _xml_attribute): - real_value = None - if node.hasAttribute(value.xml_element_name): - real_value = node.getAttribute(value.xml_element_name) - if real_value is not None: - setattr(return_obj, name, real_value) - elif isinstance(value, WindowsAzureData): - setattr(return_obj, - name, - _fill_instance_child(node, name, value.__class__)) - elif isinstance(value, dict): - setattr(return_obj, - name, - _fill_dict(node, _get_serialization_name(name))) - elif isinstance(value, _Base64String): - value = _fill_data_minidom(node, name, '') - if value is not None: - value = _decode_base64_to_text(value) - # always set the attribute, so we don't end up returning an object - # with type _Base64String - setattr(return_obj, name, value) - else: - value = _fill_data_minidom(node, name, value) - if value is not None: - setattr(return_obj, name, value) - - -def _parse_response_body_from_xml_node(node, return_type): - ''' - parse the xml and fill all the data into a class of return_type - ''' - return_obj = return_type() - _fill_data_to_return_object(node, return_obj) - - return return_obj - - -def _parse_response_body_from_xml_text(respbody, return_type): - ''' - parse the xml and fill all the data into a class of return_type - ''' - doc = minidom.parseString(respbody) - return_obj = return_type() - xml_name = return_type._xml_name if hasattr(return_type, '_xml_name') else return_type.__name__ - for node in _get_child_nodes(doc, xml_name): - _fill_data_to_return_object(node, return_obj) - - return return_obj - -def _parse_response_body_from_service_resources_xml_text(respbody, return_type): - ''' - parse the xml and fill all the data into a class of return_type - ''' - doc = minidom.parseString(respbody) - return_obj = _list_of(return_type) - for node in _get_children_from_path(doc, "ServiceResources", "ServiceResource"): - local_obj = return_type() - _fill_data_to_return_object(node, local_obj) - return_obj.append(local_obj) - - return return_obj - -class _dict_of(dict): - - """a dict which carries with it the xml element names for key,val. - Used for deserializaion and construction of the lists""" - - def __init__(self, pair_xml_element_name, key_xml_element_name, - value_xml_element_name): - self.pair_xml_element_name = pair_xml_element_name - self.key_xml_element_name = key_xml_element_name - self.value_xml_element_name = value_xml_element_name - super(_dict_of, self).__init__() - - -class _list_of(list): - - """a list which carries with it the type that's expected to go in it. - Used for deserializaion and construction of the lists""" - - def __init__(self, list_type, xml_element_name=None): - self.list_type = list_type - if xml_element_name is None: - self.xml_element_name = list_type.__name__ - else: - self.xml_element_name = xml_element_name - super(_list_of, self).__init__() - - -class _scalar_list_of(list): - - """a list of scalar types which carries with it the type that's - expected to go in it along with its xml element name. - Used for deserializaion and construction of the lists""" - - def __init__(self, list_type, xml_element_name): - self.list_type = list_type - self.xml_element_name = xml_element_name - super(_scalar_list_of, self).__init__() - -class _xml_attribute: - - """a accessor to XML attributes - expected to go in it along with its xml element name. - Used for deserialization and construction""" - - def __init__(self, xml_element_name): - self.xml_element_name = xml_element_name - - -def _update_request_uri_query_local_storage(request, use_local_storage): - ''' create correct uri and query for the request ''' - uri, query = _update_request_uri_query(request) - if use_local_storage: - return '/' + DEV_ACCOUNT_NAME + uri, query - return uri, query - - -def _update_request_uri_query(request): - '''pulls the query string out of the URI and moves it into - the query portion of the request object. If there are already - query parameters on the request the parameters in the URI will - appear after the existing parameters''' - - if '?' in request.path: - request.path, _, query_string = request.path.partition('?') - if query_string: - query_params = query_string.split('&') - for query in query_params: - if '=' in query: - name, _, value = query.partition('=') - request.query.append((name, value)) - - request.path = url_quote(request.path, '/()$=\',') - - # add encoded queries to request.path. - if request.query: - request.path += '?' - for name, value in request.query: - if value is not None: - request.path += name + '=' + url_quote(value, '/()$=\',') + '&' - request.path = request.path[:-1] - - return request.path, request.query - - -def _dont_fail_on_exist(error): - ''' don't throw exception if the resource exists. - This is called by create_* APIs with fail_on_exist=False''' - if isinstance(error, WindowsAzureConflictError): - return False - else: - raise error - - -def _dont_fail_not_exist(error): - ''' don't throw exception if the resource doesn't exist. - This is called by create_* APIs with fail_on_exist=False''' - if isinstance(error, WindowsAzureMissingResourceError): - return False - else: - raise error - - -def _general_error_handler(http_error): - ''' Simple error handler for azure.''' - if http_error.status == 409: - raise WindowsAzureConflictError( - _ERROR_CONFLICT.format(str(http_error))) - elif http_error.status == 404: - raise WindowsAzureMissingResourceError( - _ERROR_NOT_FOUND.format(str(http_error))) - else: - if http_error.respbody is not None: - raise WindowsAzureError( - _ERROR_UNKNOWN.format(str(http_error)) + '\n' + \ - http_error.respbody.decode('utf-8')) - else: - raise WindowsAzureError(_ERROR_UNKNOWN.format(str(http_error))) - - -def _parse_response_for_dict(response): - ''' Extracts name-values from response header. Filter out the standard - http headers.''' - - if response is None: - return None - http_headers = ['server', 'date', 'location', 'host', - 'via', 'proxy-connection', 'connection'] - return_dict = HeaderDict() - if response.headers: - for name, value in response.headers: - if not name.lower() in http_headers: - return_dict[name] = value - - return return_dict - - -def _parse_response_for_dict_prefix(response, prefixes): - ''' Extracts name-values for names starting with prefix from response - header. Filter out the standard http headers.''' - - if response is None: - return None - return_dict = {} - orig_dict = _parse_response_for_dict(response) - if orig_dict: - for name, value in orig_dict.items(): - for prefix_value in prefixes: - if name.lower().startswith(prefix_value.lower()): - return_dict[name] = value - break - return return_dict - else: - return None - - -def _parse_response_for_dict_filter(response, filter): - ''' Extracts name-values for names in filter from response header. Filter - out the standard http headers.''' - if response is None: - return None - return_dict = {} - orig_dict = _parse_response_for_dict(response) - if orig_dict: - for name, value in orig_dict.items(): - if name.lower() in filter: - return_dict[name] = value - return return_dict - else: - return None - - -def _sign_string(key, string_to_sign, key_is_base64=True): - if key_is_base64: - key = _decode_base64_to_bytes(key) - else: - if isinstance(key, _unicode_type): - key = key.encode('utf-8') - if isinstance(string_to_sign, _unicode_type): - string_to_sign = string_to_sign.encode('utf-8') - signed_hmac_sha256 = hmac.HMAC(key, string_to_sign, hashlib.sha256) - digest = signed_hmac_sha256.digest() - encoded_digest = _encode_base64(digest) - return encoded_digest diff --git a/awx/lib/site-packages/azure/azure.pyproj b/awx/lib/site-packages/azure/azure.pyproj deleted file mode 100644 index bb79dc0229..0000000000 --- a/awx/lib/site-packages/azure/azure.pyproj +++ /dev/null @@ -1,81 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <SchemaVersion>2.0</SchemaVersion> - <ProjectGuid>{25b2c65a-0553-4452-8907-8b5b17544e68}</ProjectGuid> - <ProjectHome> - </ProjectHome> - <StartupFile>storage\blobservice.py</StartupFile> - <SearchPath>..</SearchPath> - <WorkingDirectory>.</WorkingDirectory> - <OutputPath>.</OutputPath> - <Name>azure</Name> - <RootNamespace>azure</RootNamespace> - <IsWindowsApplication>False</IsWindowsApplication> - <LaunchProvider>Standard Python launcher</LaunchProvider> - <CommandLineArguments /> - <InterpreterPath /> - <InterpreterArguments /> - <InterpreterId>{2af0f10d-7135-4994-9156-5d01c9c11b7e}</InterpreterId> - <InterpreterVersion>2.7</InterpreterVersion> - <SccProjectName>SAK</SccProjectName> - <SccProvider>SAK</SccProvider> - <SccAuxPath>SAK</SccAuxPath> - <SccLocalPath>SAK</SccLocalPath> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> - <DebugSymbols>true</DebugSymbols> - <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> - <DebugSymbols>true</DebugSymbols> - <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging> - </PropertyGroup> - <ItemGroup> - <Compile Include="http\batchclient.py" /> - <Compile Include="http\httpclient.py" /> - <Compile Include="http\requestsclient.py" /> - <Compile Include="http\winhttp.py" /> - <Compile Include="http\__init__.py" /> - <Compile Include="servicemanagement\schedulermanagementservice.py" /> - <Compile Include="servicemanagement\servicebusmanagementservice.py" /> - <Compile Include="servicemanagement\servicemanagementclient.py" /> - <Compile Include="servicemanagement\servicemanagementservice.py" /> - <Compile Include="servicemanagement\sqldatabasemanagementservice.py" /> - <Compile Include="servicemanagement\websitemanagementservice.py" /> - <Compile Include="servicemanagement\__init__.py" /> - <Compile Include="servicebus\servicebusservice.py" /> - <Compile Include="storage\blobservice.py" /> - <Compile Include="storage\queueservice.py" /> - <Compile Include="storage\cloudstorageaccount.py" /> - <Compile Include="storage\tableservice.py" /> - <Compile Include="storage\sharedaccesssignature.py" /> - <Compile Include="__init__.py" /> - <Compile Include="servicebus\__init__.py" /> - <Compile Include="storage\storageclient.py" /> - <Compile Include="storage\__init__.py" /> - </ItemGroup> - <ItemGroup> - <Folder Include="http" /> - <Folder Include="servicemanagement" /> - <Folder Include="servicebus" /> - <Folder Include="storage" /> - </ItemGroup> - <ItemGroup> - <InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\2.6" /> - <InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\2.7" /> - <InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\3.3" /> - <InterpreterReference Include="{2af0f10d-7135-4994-9156-5d01c9c11b7e}\3.4" /> - <InterpreterReference Include="{9a7a9026-48c1-4688-9d5d-e5699d47d074}\2.7" /> - <InterpreterReference Include="{9a7a9026-48c1-4688-9d5d-e5699d47d074}\3.3" /> - <InterpreterReference Include="{9a7a9026-48c1-4688-9d5d-e5699d47d074}\3.4" /> - </ItemGroup> - <PropertyGroup> - <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> - <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> - <PtvsTargetsFile>$(VSToolsPath)\Python Tools\Microsoft.PythonTools.targets</PtvsTargetsFile> - </PropertyGroup> - <Import Condition="Exists($(PtvsTargetsFile))" Project="$(PtvsTargetsFile)" /> - <Import Condition="!Exists($(PtvsTargetsFile))" Project="$(MSBuildToolsPath)\Microsoft.Common.targets" /> -</Project> \ No newline at end of file diff --git a/awx/lib/site-packages/azure/http/__init__.py b/awx/lib/site-packages/azure/http/__init__.py deleted file mode 100644 index 680d5b5ad5..0000000000 --- a/awx/lib/site-packages/azure/http/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- - -HTTP_RESPONSE_NO_CONTENT = 204 - - -class HTTPError(Exception): - - ''' HTTP Exception when response status code >= 300 ''' - - def __init__(self, status, message, respheader, respbody): - '''Creates a new HTTPError with the specified status, message, - response headers and body''' - self.status = status - self.respheader = respheader - self.respbody = respbody - Exception.__init__(self, message) - - -class HTTPResponse(object): - - """Represents a response from an HTTP request. An HTTPResponse has the - following attributes: - - status: the status code of the response - message: the message - headers: the returned headers, as a list of (name, value) pairs - body: the body of the response - """ - - def __init__(self, status, message, headers, body): - self.status = status - self.message = message - self.headers = headers - self.body = body - - -class HTTPRequest(object): - - '''Represents an HTTP Request. An HTTP Request consists of the following - attributes: - - host: the host name to connect to - method: the method to use to connect (string such as GET, POST, PUT, etc.) - path: the uri fragment - query: query parameters specified as a list of (name, value) pairs - headers: header values specified as (name, value) pairs - body: the body of the request. - protocol_override: - specify to use this protocol instead of the global one stored in - _HTTPClient. - ''' - - def __init__(self): - self.host = '' - self.method = '' - self.path = '' - self.query = [] # list of (name, value) - self.headers = [] # list of (header name, header value) - self.body = '' - self.protocol_override = None diff --git a/awx/lib/site-packages/azure/http/batchclient.py b/awx/lib/site-packages/azure/http/batchclient.py deleted file mode 100644 index 9bd3223e15..0000000000 --- a/awx/lib/site-packages/azure/http/batchclient.py +++ /dev/null @@ -1,339 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import sys -import uuid - -from azure import ( - _update_request_uri_query, - WindowsAzureError, - WindowsAzureBatchOperationError, - _get_children_from_path, - url_unquote, - _ERROR_CANNOT_FIND_PARTITION_KEY, - _ERROR_CANNOT_FIND_ROW_KEY, - _ERROR_INCORRECT_TABLE_IN_BATCH, - _ERROR_INCORRECT_PARTITION_KEY_IN_BATCH, - _ERROR_DUPLICATE_ROW_KEY_IN_BATCH, - _ERROR_BATCH_COMMIT_FAIL, - ) -from azure.http import HTTPError, HTTPRequest, HTTPResponse -from azure.http.httpclient import _HTTPClient -from azure.storage import ( - _update_storage_table_header, - METADATA_NS, - _sign_storage_table_request, - ) -from xml.dom import minidom - -_DATASERVICES_NS = 'http://schemas.microsoft.com/ado/2007/08/dataservices' - -if sys.version_info < (3,): - def _new_boundary(): - return str(uuid.uuid1()) -else: - def _new_boundary(): - return str(uuid.uuid1()).encode('utf-8') - - -class _BatchClient(_HTTPClient): - - ''' - This is the class that is used for batch operation for storage table - service. It only supports one changeset. - ''' - - def __init__(self, service_instance, account_key, account_name, - protocol='http'): - _HTTPClient.__init__(self, service_instance, account_name=account_name, - account_key=account_key, protocol=protocol) - self.is_batch = False - self.batch_requests = [] - self.batch_table = '' - self.batch_partition_key = '' - self.batch_row_keys = [] - - def get_request_table(self, request): - ''' - Extracts table name from request.uri. The request.uri has either - "/mytable(...)" or "/mytable" format. - - request: the request to insert, update or delete entity - ''' - if '(' in request.path: - pos = request.path.find('(') - return request.path[1:pos] - else: - return request.path[1:] - - def get_request_partition_key(self, request): - ''' - Extracts PartitionKey from request.body if it is a POST request or from - request.path if it is not a POST request. Only insert operation request - is a POST request and the PartitionKey is in the request body. - - request: the request to insert, update or delete entity - ''' - if request.method == 'POST': - doc = minidom.parseString(request.body) - part_key = _get_children_from_path( - doc, 'entry', 'content', (METADATA_NS, 'properties'), - (_DATASERVICES_NS, 'PartitionKey')) - if not part_key: - raise WindowsAzureError(_ERROR_CANNOT_FIND_PARTITION_KEY) - return part_key[0].firstChild.nodeValue - else: - uri = url_unquote(request.path) - pos1 = uri.find('PartitionKey=\'') - pos2 = uri.find('\',', pos1) - if pos1 == -1 or pos2 == -1: - raise WindowsAzureError(_ERROR_CANNOT_FIND_PARTITION_KEY) - return uri[pos1 + len('PartitionKey=\''):pos2] - - def get_request_row_key(self, request): - ''' - Extracts RowKey from request.body if it is a POST request or from - request.path if it is not a POST request. Only insert operation request - is a POST request and the Rowkey is in the request body. - - request: the request to insert, update or delete entity - ''' - if request.method == 'POST': - doc = minidom.parseString(request.body) - row_key = _get_children_from_path( - doc, 'entry', 'content', (METADATA_NS, 'properties'), - (_DATASERVICES_NS, 'RowKey')) - if not row_key: - raise WindowsAzureError(_ERROR_CANNOT_FIND_ROW_KEY) - return row_key[0].firstChild.nodeValue - else: - uri = url_unquote(request.path) - pos1 = uri.find('RowKey=\'') - pos2 = uri.find('\')', pos1) - if pos1 == -1 or pos2 == -1: - raise WindowsAzureError(_ERROR_CANNOT_FIND_ROW_KEY) - row_key = uri[pos1 + len('RowKey=\''):pos2] - return row_key - - def validate_request_table(self, request): - ''' - Validates that all requests have the same table name. Set the table - name if it is the first request for the batch operation. - - request: the request to insert, update or delete entity - ''' - if self.batch_table: - if self.get_request_table(request) != self.batch_table: - raise WindowsAzureError(_ERROR_INCORRECT_TABLE_IN_BATCH) - else: - self.batch_table = self.get_request_table(request) - - def validate_request_partition_key(self, request): - ''' - Validates that all requests have the same PartitiionKey. Set the - PartitionKey if it is the first request for the batch operation. - - request: the request to insert, update or delete entity - ''' - if self.batch_partition_key: - if self.get_request_partition_key(request) != \ - self.batch_partition_key: - raise WindowsAzureError(_ERROR_INCORRECT_PARTITION_KEY_IN_BATCH) - else: - self.batch_partition_key = self.get_request_partition_key(request) - - def validate_request_row_key(self, request): - ''' - Validates that all requests have the different RowKey and adds RowKey - to existing RowKey list. - - request: the request to insert, update or delete entity - ''' - if self.batch_row_keys: - if self.get_request_row_key(request) in self.batch_row_keys: - raise WindowsAzureError(_ERROR_DUPLICATE_ROW_KEY_IN_BATCH) - else: - self.batch_row_keys.append(self.get_request_row_key(request)) - - def begin_batch(self): - ''' - Starts the batch operation. Intializes the batch variables - - is_batch: batch operation flag. - batch_table: the table name of the batch operation - batch_partition_key: the PartitionKey of the batch requests. - batch_row_keys: the RowKey list of adding requests. - batch_requests: the list of the requests. - ''' - self.is_batch = True - self.batch_table = '' - self.batch_partition_key = '' - self.batch_row_keys = [] - self.batch_requests = [] - - def insert_request_to_batch(self, request): - ''' - Adds request to batch operation. - - request: the request to insert, update or delete entity - ''' - self.validate_request_table(request) - self.validate_request_partition_key(request) - self.validate_request_row_key(request) - self.batch_requests.append(request) - - def commit_batch(self): - ''' Resets batch flag and commits the batch requests. ''' - if self.is_batch: - self.is_batch = False - self.commit_batch_requests() - - def commit_batch_requests(self): - ''' Commits the batch requests. ''' - - batch_boundary = b'batch_' + _new_boundary() - changeset_boundary = b'changeset_' + _new_boundary() - - # Commits batch only the requests list is not empty. - if self.batch_requests: - request = HTTPRequest() - request.method = 'POST' - request.host = self.batch_requests[0].host - request.path = '/$batch' - request.headers = [ - ('Content-Type', 'multipart/mixed; boundary=' + \ - batch_boundary.decode('utf-8')), - ('Accept', 'application/atom+xml,application/xml'), - ('Accept-Charset', 'UTF-8')] - - request.body = b'--' + batch_boundary + b'\n' - request.body += b'Content-Type: multipart/mixed; boundary=' - request.body += changeset_boundary + b'\n\n' - - content_id = 1 - - # Adds each request body to the POST data. - for batch_request in self.batch_requests: - request.body += b'--' + changeset_boundary + b'\n' - request.body += b'Content-Type: application/http\n' - request.body += b'Content-Transfer-Encoding: binary\n\n' - request.body += batch_request.method.encode('utf-8') - request.body += b' http://' - request.body += batch_request.host.encode('utf-8') - request.body += batch_request.path.encode('utf-8') - request.body += b' HTTP/1.1\n' - request.body += b'Content-ID: ' - request.body += str(content_id).encode('utf-8') + b'\n' - content_id += 1 - - # Add different headers for different type requests. - if not batch_request.method == 'DELETE': - request.body += \ - b'Content-Type: application/atom+xml;type=entry\n' - for name, value in batch_request.headers: - if name == 'If-Match': - request.body += name.encode('utf-8') + b': ' - request.body += value.encode('utf-8') + b'\n' - break - request.body += b'Content-Length: ' - request.body += str(len(batch_request.body)).encode('utf-8') - request.body += b'\n\n' - request.body += batch_request.body + b'\n' - else: - for name, value in batch_request.headers: - # If-Match should be already included in - # batch_request.headers, but in case it is missing, - # just add it. - if name == 'If-Match': - request.body += name.encode('utf-8') + b': ' - request.body += value.encode('utf-8') + b'\n\n' - break - else: - request.body += b'If-Match: *\n\n' - - request.body += b'--' + changeset_boundary + b'--' + b'\n' - request.body += b'--' + batch_boundary + b'--' - - request.path, request.query = _update_request_uri_query(request) - request.headers = _update_storage_table_header(request) - auth = _sign_storage_table_request(request, - self.account_name, - self.account_key) - request.headers.append(('Authorization', auth)) - - # Submit the whole request as batch request. - response = self.perform_request(request) - if response.status >= 300: - raise HTTPError(response.status, - _ERROR_BATCH_COMMIT_FAIL, - self.respheader, - response.body) - - # http://www.odata.org/documentation/odata-version-2-0/batch-processing/ - # The body of a ChangeSet response is either a response for all the - # successfully processed change request within the ChangeSet, - # formatted exactly as it would have appeared outside of a batch, - # or a single response indicating a failure of the entire ChangeSet. - responses = self._parse_batch_response(response.body) - if responses and responses[0].status >= 300: - self._report_batch_error(responses[0]) - - def cancel_batch(self): - ''' Resets the batch flag. ''' - self.is_batch = False - - def _parse_batch_response(self, body): - parts = body.split(b'--changesetresponse_') - - responses = [] - for part in parts: - httpLocation = part.find(b'HTTP/') - if httpLocation > 0: - response = self._parse_batch_response_part(part[httpLocation:]) - responses.append(response) - - return responses - - def _parse_batch_response_part(self, part): - lines = part.splitlines(); - - # First line is the HTTP status/reason - status, _, reason = lines[0].partition(b' ')[2].partition(b' ') - - # Followed by headers and body - headers = [] - body = b'' - isBody = False - for line in lines[1:]: - if line == b'' and not isBody: - isBody = True - elif isBody: - body += line - else: - headerName, _, headerVal = line.partition(b':') - headers.append((headerName.lower(), headerVal)) - - return HTTPResponse(int(status), reason.strip(), headers, body) - - def _report_batch_error(self, response): - xml = response.body.decode('utf-8') - doc = minidom.parseString(xml) - - n = _get_children_from_path(doc, (METADATA_NS, 'error'), 'code') - code = n[0].firstChild.nodeValue if n and n[0].firstChild else '' - - n = _get_children_from_path(doc, (METADATA_NS, 'error'), 'message') - message = n[0].firstChild.nodeValue if n and n[0].firstChild else xml - - raise WindowsAzureBatchOperationError(message, code) diff --git a/awx/lib/site-packages/azure/http/httpclient.py b/awx/lib/site-packages/azure/http/httpclient.py deleted file mode 100644 index 1bdeb73102..0000000000 --- a/awx/lib/site-packages/azure/http/httpclient.py +++ /dev/null @@ -1,251 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import base64 -import os -import sys - -if sys.version_info < (3,): - from httplib import ( - HTTPSConnection, - HTTPConnection, - HTTP_PORT, - HTTPS_PORT, - ) - from urlparse import urlparse -else: - from http.client import ( - HTTPSConnection, - HTTPConnection, - HTTP_PORT, - HTTPS_PORT, - ) - from urllib.parse import urlparse - -from azure.http import HTTPError, HTTPResponse -from azure import _USER_AGENT_STRING, _update_request_uri_query - -DEBUG_REQUESTS = False -DEBUG_RESPONSES = False - -class _HTTPClient(object): - - ''' - Takes the request and sends it to cloud service and returns the response. - ''' - - def __init__(self, service_instance, cert_file=None, account_name=None, - account_key=None, protocol='https', request_session=None): - ''' - service_instance: service client instance. - cert_file: - certificate file name/location. This is only used in hosted - service management. - account_name: the storage account. - account_key: - the storage account access key. - request_session: - session object created with requests library (or compatible). - ''' - self.service_instance = service_instance - self.status = None - self.respheader = None - self.message = None - self.cert_file = cert_file - self.account_name = account_name - self.account_key = account_key - self.protocol = protocol - self.proxy_host = None - self.proxy_port = None - self.proxy_user = None - self.proxy_password = None - self.request_session = request_session - if request_session: - self.use_httplib = True - else: - self.use_httplib = self.should_use_httplib() - - def should_use_httplib(self): - if sys.platform.lower().startswith('win') and self.cert_file: - # On Windows, auto-detect between Windows Store Certificate - # (winhttp) and OpenSSL .pem certificate file (httplib). - # - # We used to only support certificates installed in the Windows - # Certificate Store. - # cert_file example: CURRENT_USER\my\CertificateName - # - # We now support using an OpenSSL .pem certificate file, - # for a consistent experience across all platforms. - # cert_file example: account\certificate.pem - # - # When using OpenSSL .pem certificate file on Windows, make sure - # you are on CPython 2.7.4 or later. - - # If it's not an existing file on disk, then treat it as a path in - # the Windows Certificate Store, which means we can't use httplib. - if not os.path.isfile(self.cert_file): - return False - - return True - - def set_proxy(self, host, port, user, password): - ''' - Sets the proxy server host and port for the HTTP CONNECT Tunnelling. - - host: Address of the proxy. Ex: '192.168.0.100' - port: Port of the proxy. Ex: 6000 - user: User for proxy authorization. - password: Password for proxy authorization. - ''' - self.proxy_host = host - self.proxy_port = port - self.proxy_user = user - self.proxy_password = password - - def get_uri(self, request): - ''' Return the target uri for the request.''' - protocol = request.protocol_override \ - if request.protocol_override else self.protocol - port = HTTP_PORT if protocol == 'http' else HTTPS_PORT - return protocol + '://' + request.host + ':' + str(port) + request.path - - def get_connection(self, request): - ''' Create connection for the request. ''' - protocol = request.protocol_override \ - if request.protocol_override else self.protocol - target_host = request.host - target_port = HTTP_PORT if protocol == 'http' else HTTPS_PORT - - if self.request_session: - import azure.http.requestsclient - connection = azure.http.requestsclient._RequestsConnection( - target_host, protocol, self.request_session) - #TODO: proxy stuff - elif not self.use_httplib: - import azure.http.winhttp - connection = azure.http.winhttp._HTTPConnection( - target_host, cert_file=self.cert_file, protocol=protocol) - proxy_host = self.proxy_host - proxy_port = self.proxy_port - else: - if ':' in target_host: - target_host, _, target_port = target_host.rpartition(':') - if self.proxy_host: - proxy_host = target_host - proxy_port = target_port - host = self.proxy_host - port = self.proxy_port - else: - host = target_host - port = target_port - - if protocol == 'http': - connection = HTTPConnection(host, int(port)) - else: - connection = HTTPSConnection( - host, int(port), cert_file=self.cert_file) - - if self.proxy_host: - headers = None - if self.proxy_user and self.proxy_password: - auth = base64.encodestring( - "{0}:{1}".format(self.proxy_user, self.proxy_password)) - headers = {'Proxy-Authorization': 'Basic {0}'.format(auth)} - connection.set_tunnel(proxy_host, int(proxy_port), headers) - - return connection - - def send_request_headers(self, connection, request_headers): - if self.use_httplib: - if self.proxy_host: - for i in connection._buffer: - if i.startswith("Host: "): - connection._buffer.remove(i) - connection.putheader( - 'Host', "{0}:{1}".format(connection._tunnel_host, - connection._tunnel_port)) - - for name, value in request_headers: - if value: - connection.putheader(name, value) - - connection.putheader('User-Agent', _USER_AGENT_STRING) - connection.endheaders() - - def send_request_body(self, connection, request_body): - if request_body: - assert isinstance(request_body, bytes) - connection.send(request_body) - elif (not isinstance(connection, HTTPSConnection) and - not isinstance(connection, HTTPConnection)): - connection.send(None) - - def perform_request(self, request): - ''' Sends request to cloud service server and return the response. ''' - connection = self.get_connection(request) - try: - connection.putrequest(request.method, request.path) - - if not self.use_httplib: - if self.proxy_host and self.proxy_user: - connection.set_proxy_credentials( - self.proxy_user, self.proxy_password) - - self.send_request_headers(connection, request.headers) - self.send_request_body(connection, request.body) - - if DEBUG_REQUESTS and request.body: - print('request:') - try: - print(request.body) - except: - pass - - resp = connection.getresponse() - self.status = int(resp.status) - self.message = resp.reason - self.respheader = headers = resp.getheaders() - - # for consistency across platforms, make header names lowercase - for i, value in enumerate(headers): - headers[i] = (value[0].lower(), value[1]) - - respbody = None - if resp.length is None: - respbody = resp.read() - elif resp.length > 0: - respbody = resp.read(resp.length) - - if DEBUG_RESPONSES and respbody: - print('response:') - try: - print(respbody) - except: - pass - - response = HTTPResponse( - int(resp.status), resp.reason, headers, respbody) - if self.status == 307: - new_url = urlparse(dict(headers)['location']) - request.host = new_url.hostname - request.path = new_url.path - request.path, request.query = _update_request_uri_query(request) - return self.perform_request(request) - if self.status >= 300: - raise HTTPError(self.status, self.message, - self.respheader, respbody) - - return response - finally: - connection.close() diff --git a/awx/lib/site-packages/azure/http/requestsclient.py b/awx/lib/site-packages/azure/http/requestsclient.py deleted file mode 100644 index 02b524214c..0000000000 --- a/awx/lib/site-packages/azure/http/requestsclient.py +++ /dev/null @@ -1,74 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- - -class _Response(object): - - ''' Response class corresponding to the response returned from httplib - HTTPConnection. ''' - - def __init__(self, response): - self.status = response.status_code - self.reason = response.reason - self.respbody = response.content - self.length = len(response.content) - self.headers = [] - for key, name in response.headers.items(): - self.headers.append((key.lower(), name)) - - def getheaders(self): - '''Returns response headers.''' - return self.headers - - def read(self, _length): - '''Returns response body. ''' - return self.respbody[:_length] - - -class _RequestsConnection(object): - - def __init__(self, host, protocol, session): - self.host = host - self.protocol = protocol - self.session = session - self.headers = {} - self.method = None - self.body = None - self.response = None - self.uri = None - - def close(self): - pass - - def set_tunnel(self, host, port=None, headers=None): - pass - - def set_proxy_credentials(self, user, password): - pass - - def putrequest(self, method, uri): - self.method = method - self.uri = self.protocol + '://' + self.host + uri - - def putheader(self, name, value): - self.headers[name] = value - - def endheaders(self): - pass - - def send(self, request_body): - self.response = self.session.request(self.method, self.uri, data=request_body, headers=self.headers) - - def getresponse(self): - return _Response(self.response) diff --git a/awx/lib/site-packages/azure/http/winhttp.py b/awx/lib/site-packages/azure/http/winhttp.py deleted file mode 100644 index 055bf778e0..0000000000 --- a/awx/lib/site-packages/azure/http/winhttp.py +++ /dev/null @@ -1,471 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from ctypes import ( - c_void_p, - c_long, - c_ulong, - c_longlong, - c_ulonglong, - c_short, - c_ushort, - c_wchar_p, - c_byte, - byref, - Structure, - Union, - POINTER, - WINFUNCTYPE, - HRESULT, - oledll, - WinDLL, - ) -import ctypes -import sys - -if sys.version_info >= (3,): - def unicode(text): - return text - -#------------------------------------------------------------------------------ -# Constants that are used in COM operations -VT_EMPTY = 0 -VT_NULL = 1 -VT_I2 = 2 -VT_I4 = 3 -VT_BSTR = 8 -VT_BOOL = 11 -VT_I1 = 16 -VT_UI1 = 17 -VT_UI2 = 18 -VT_UI4 = 19 -VT_I8 = 20 -VT_UI8 = 21 -VT_ARRAY = 8192 - -HTTPREQUEST_PROXYSETTING_PROXY = 2 -HTTPREQUEST_SETCREDENTIALS_FOR_PROXY = 1 - -HTTPREQUEST_PROXY_SETTING = c_long -HTTPREQUEST_SETCREDENTIALS_FLAGS = c_long -#------------------------------------------------------------------------------ -# Com related APIs that are used. -_ole32 = oledll.ole32 -_oleaut32 = WinDLL('oleaut32') -_CLSIDFromString = _ole32.CLSIDFromString -_CoInitialize = _ole32.CoInitialize -_CoInitialize.argtypes = [c_void_p] - -_CoCreateInstance = _ole32.CoCreateInstance - -_SysAllocString = _oleaut32.SysAllocString -_SysAllocString.restype = c_void_p -_SysAllocString.argtypes = [c_wchar_p] - -_SysFreeString = _oleaut32.SysFreeString -_SysFreeString.argtypes = [c_void_p] - -# SAFEARRAY* -# SafeArrayCreateVector(_In_ VARTYPE vt,_In_ LONG lLbound,_In_ ULONG -# cElements); -_SafeArrayCreateVector = _oleaut32.SafeArrayCreateVector -_SafeArrayCreateVector.restype = c_void_p -_SafeArrayCreateVector.argtypes = [c_ushort, c_long, c_ulong] - -# HRESULT -# SafeArrayAccessData(_In_ SAFEARRAY *psa, _Out_ void **ppvData); -_SafeArrayAccessData = _oleaut32.SafeArrayAccessData -_SafeArrayAccessData.argtypes = [c_void_p, POINTER(c_void_p)] - -# HRESULT -# SafeArrayUnaccessData(_In_ SAFEARRAY *psa); -_SafeArrayUnaccessData = _oleaut32.SafeArrayUnaccessData -_SafeArrayUnaccessData.argtypes = [c_void_p] - -# HRESULT -# SafeArrayGetUBound(_In_ SAFEARRAY *psa, _In_ UINT nDim, _Out_ LONG -# *plUbound); -_SafeArrayGetUBound = _oleaut32.SafeArrayGetUBound -_SafeArrayGetUBound.argtypes = [c_void_p, c_ulong, POINTER(c_long)] - - -#------------------------------------------------------------------------------ - -class BSTR(c_wchar_p): - - ''' BSTR class in python. ''' - - def __init__(self, value): - super(BSTR, self).__init__(_SysAllocString(value)) - - def __del__(self): - _SysFreeString(self) - - -class VARIANT(Structure): - - ''' - VARIANT structure in python. Does not match the definition in - MSDN exactly & it is only mapping the used fields. Field names are also - slighty different. - ''' - - class _tagData(Union): - - class _tagRecord(Structure): - _fields_ = [('pvoid', c_void_p), ('precord', c_void_p)] - - _fields_ = [('llval', c_longlong), - ('ullval', c_ulonglong), - ('lval', c_long), - ('ulval', c_ulong), - ('ival', c_short), - ('boolval', c_ushort), - ('bstrval', BSTR), - ('parray', c_void_p), - ('record', _tagRecord)] - - _fields_ = [('vt', c_ushort), - ('wReserved1', c_ushort), - ('wReserved2', c_ushort), - ('wReserved3', c_ushort), - ('vdata', _tagData)] - - @staticmethod - def create_empty(): - variant = VARIANT() - variant.vt = VT_EMPTY - variant.vdata.llval = 0 - return variant - - @staticmethod - def create_safearray_from_str(text): - variant = VARIANT() - variant.vt = VT_ARRAY | VT_UI1 - - length = len(text) - variant.vdata.parray = _SafeArrayCreateVector(VT_UI1, 0, length) - pvdata = c_void_p() - _SafeArrayAccessData(variant.vdata.parray, byref(pvdata)) - ctypes.memmove(pvdata, text, length) - _SafeArrayUnaccessData(variant.vdata.parray) - - return variant - - @staticmethod - def create_bstr_from_str(text): - variant = VARIANT() - variant.vt = VT_BSTR - variant.vdata.bstrval = BSTR(text) - return variant - - @staticmethod - def create_bool_false(): - variant = VARIANT() - variant.vt = VT_BOOL - variant.vdata.boolval = 0 - return variant - - def is_safearray_of_bytes(self): - return self.vt == VT_ARRAY | VT_UI1 - - def str_from_safearray(self): - assert self.vt == VT_ARRAY | VT_UI1 - pvdata = c_void_p() - count = c_long() - _SafeArrayGetUBound(self.vdata.parray, 1, byref(count)) - count = c_long(count.value + 1) - _SafeArrayAccessData(self.vdata.parray, byref(pvdata)) - text = ctypes.string_at(pvdata, count) - _SafeArrayUnaccessData(self.vdata.parray) - return text - - def __del__(self): - _VariantClear(self) - -# HRESULT VariantClear(_Inout_ VARIANTARG *pvarg); -_VariantClear = _oleaut32.VariantClear -_VariantClear.argtypes = [POINTER(VARIANT)] - - -class GUID(Structure): - - ''' GUID structure in python. ''' - - _fields_ = [("data1", c_ulong), - ("data2", c_ushort), - ("data3", c_ushort), - ("data4", c_byte * 8)] - - def __init__(self, name=None): - if name is not None: - _CLSIDFromString(unicode(name), byref(self)) - - -class _WinHttpRequest(c_void_p): - - ''' - Maps the Com API to Python class functions. Not all methods in - IWinHttpWebRequest are mapped - only the methods we use. - ''' - _AddRef = WINFUNCTYPE(c_long) \ - (1, 'AddRef') - _Release = WINFUNCTYPE(c_long) \ - (2, 'Release') - _SetProxy = WINFUNCTYPE(HRESULT, - HTTPREQUEST_PROXY_SETTING, - VARIANT, - VARIANT) \ - (7, 'SetProxy') - _SetCredentials = WINFUNCTYPE(HRESULT, - BSTR, - BSTR, - HTTPREQUEST_SETCREDENTIALS_FLAGS) \ - (8, 'SetCredentials') - _Open = WINFUNCTYPE(HRESULT, BSTR, BSTR, VARIANT) \ - (9, 'Open') - _SetRequestHeader = WINFUNCTYPE(HRESULT, BSTR, BSTR) \ - (10, 'SetRequestHeader') - _GetResponseHeader = WINFUNCTYPE(HRESULT, BSTR, POINTER(c_void_p)) \ - (11, 'GetResponseHeader') - _GetAllResponseHeaders = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \ - (12, 'GetAllResponseHeaders') - _Send = WINFUNCTYPE(HRESULT, VARIANT) \ - (13, 'Send') - _Status = WINFUNCTYPE(HRESULT, POINTER(c_long)) \ - (14, 'Status') - _StatusText = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \ - (15, 'StatusText') - _ResponseText = WINFUNCTYPE(HRESULT, POINTER(c_void_p)) \ - (16, 'ResponseText') - _ResponseBody = WINFUNCTYPE(HRESULT, POINTER(VARIANT)) \ - (17, 'ResponseBody') - _ResponseStream = WINFUNCTYPE(HRESULT, POINTER(VARIANT)) \ - (18, 'ResponseStream') - _WaitForResponse = WINFUNCTYPE(HRESULT, VARIANT, POINTER(c_ushort)) \ - (21, 'WaitForResponse') - _Abort = WINFUNCTYPE(HRESULT) \ - (22, 'Abort') - _SetTimeouts = WINFUNCTYPE(HRESULT, c_long, c_long, c_long, c_long) \ - (23, 'SetTimeouts') - _SetClientCertificate = WINFUNCTYPE(HRESULT, BSTR) \ - (24, 'SetClientCertificate') - - def open(self, method, url): - ''' - Opens the request. - - method: the request VERB 'GET', 'POST', etc. - url: the url to connect - ''' - _WinHttpRequest._SetTimeouts(self, 0, 65000, 65000, 65000) - - flag = VARIANT.create_bool_false() - _method = BSTR(method) - _url = BSTR(url) - _WinHttpRequest._Open(self, _method, _url, flag) - - def set_request_header(self, name, value): - ''' Sets the request header. ''' - - _name = BSTR(name) - _value = BSTR(value) - _WinHttpRequest._SetRequestHeader(self, _name, _value) - - def get_all_response_headers(self): - ''' Gets back all response headers. ''' - - bstr_headers = c_void_p() - _WinHttpRequest._GetAllResponseHeaders(self, byref(bstr_headers)) - bstr_headers = ctypes.cast(bstr_headers, c_wchar_p) - headers = bstr_headers.value - _SysFreeString(bstr_headers) - return headers - - def send(self, request=None): - ''' Sends the request body. ''' - - # Sends VT_EMPTY if it is GET, HEAD request. - if request is None: - var_empty = VARIANT.create_empty() - _WinHttpRequest._Send(self, var_empty) - else: # Sends request body as SAFEArray. - _request = VARIANT.create_safearray_from_str(request) - _WinHttpRequest._Send(self, _request) - - def status(self): - ''' Gets status of response. ''' - - status = c_long() - _WinHttpRequest._Status(self, byref(status)) - return int(status.value) - - def status_text(self): - ''' Gets status text of response. ''' - - bstr_status_text = c_void_p() - _WinHttpRequest._StatusText(self, byref(bstr_status_text)) - bstr_status_text = ctypes.cast(bstr_status_text, c_wchar_p) - status_text = bstr_status_text.value - _SysFreeString(bstr_status_text) - return status_text - - def response_body(self): - ''' - Gets response body as a SAFEARRAY and converts the SAFEARRAY to str. - If it is an xml file, it always contains 3 characters before <?xml, - so we remove them. - ''' - var_respbody = VARIANT() - _WinHttpRequest._ResponseBody(self, byref(var_respbody)) - if var_respbody.is_safearray_of_bytes(): - respbody = var_respbody.str_from_safearray() - if respbody[3:].startswith(b'<?xml') and\ - respbody.startswith(b'\xef\xbb\xbf'): - respbody = respbody[3:] - return respbody - else: - return '' - - def set_client_certificate(self, certificate): - '''Sets client certificate for the request. ''' - _certificate = BSTR(certificate) - _WinHttpRequest._SetClientCertificate(self, _certificate) - - def set_tunnel(self, host, port): - ''' Sets up the host and the port for the HTTP CONNECT Tunnelling.''' - url = host - if port: - url = url + u':' + port - - var_host = VARIANT.create_bstr_from_str(url) - var_empty = VARIANT.create_empty() - - _WinHttpRequest._SetProxy( - self, HTTPREQUEST_PROXYSETTING_PROXY, var_host, var_empty) - - def set_proxy_credentials(self, user, password): - _WinHttpRequest._SetCredentials( - self, BSTR(user), BSTR(password), - HTTPREQUEST_SETCREDENTIALS_FOR_PROXY) - - def __del__(self): - if self.value is not None: - _WinHttpRequest._Release(self) - - -class _Response(object): - - ''' Response class corresponding to the response returned from httplib - HTTPConnection. ''' - - def __init__(self, _status, _status_text, _length, _headers, _respbody): - self.status = _status - self.reason = _status_text - self.length = _length - self.headers = _headers - self.respbody = _respbody - - def getheaders(self): - '''Returns response headers.''' - return self.headers - - def read(self, _length): - '''Returns resonse body. ''' - return self.respbody[:_length] - - -class _HTTPConnection(object): - - ''' Class corresponding to httplib HTTPConnection class. ''' - - def __init__(self, host, cert_file=None, key_file=None, protocol='http'): - ''' initialize the IWinHttpWebRequest Com Object.''' - self.host = unicode(host) - self.cert_file = cert_file - self._httprequest = _WinHttpRequest() - self.protocol = protocol - clsid = GUID('{2087C2F4-2CEF-4953-A8AB-66779B670495}') - iid = GUID('{016FE2EC-B2C8-45F8-B23B-39E53A75396B}') - _CoInitialize(None) - _CoCreateInstance(byref(clsid), 0, 1, byref(iid), - byref(self._httprequest)) - - def close(self): - pass - - def set_tunnel(self, host, port=None, headers=None): - ''' Sets up the host and the port for the HTTP CONNECT Tunnelling. ''' - self._httprequest.set_tunnel(unicode(host), unicode(str(port))) - - def set_proxy_credentials(self, user, password): - self._httprequest.set_proxy_credentials( - unicode(user), unicode(password)) - - def putrequest(self, method, uri): - ''' Connects to host and sends the request. ''' - - protocol = unicode(self.protocol + '://') - url = protocol + self.host + unicode(uri) - self._httprequest.open(unicode(method), url) - - # sets certificate for the connection if cert_file is set. - if self.cert_file is not None: - self._httprequest.set_client_certificate(unicode(self.cert_file)) - - def putheader(self, name, value): - ''' Sends the headers of request. ''' - if sys.version_info < (3,): - name = str(name).decode('utf-8') - value = str(value).decode('utf-8') - self._httprequest.set_request_header(name, value) - - def endheaders(self): - ''' No operation. Exists only to provide the same interface of httplib - HTTPConnection.''' - pass - - def send(self, request_body): - ''' Sends request body. ''' - if not request_body: - self._httprequest.send() - else: - self._httprequest.send(request_body) - - def getresponse(self): - ''' Gets the response and generates the _Response object''' - status = self._httprequest.status() - status_text = self._httprequest.status_text() - - resp_headers = self._httprequest.get_all_response_headers() - fixed_headers = [] - for resp_header in resp_headers.split('\n'): - if (resp_header.startswith('\t') or\ - resp_header.startswith(' ')) and fixed_headers: - # append to previous header - fixed_headers[-1] += resp_header - else: - fixed_headers.append(resp_header) - - headers = [] - for resp_header in fixed_headers: - if ':' in resp_header: - pos = resp_header.find(':') - headers.append( - (resp_header[:pos].lower(), resp_header[pos + 1:].strip())) - - body = self._httprequest.response_body() - length = len(body) - - return _Response(status, status_text, length, headers, body) diff --git a/awx/lib/site-packages/azure/servicebus/__init__.py b/awx/lib/site-packages/azure/servicebus/__init__.py deleted file mode 100644 index ba098f8123..0000000000 --- a/awx/lib/site-packages/azure/servicebus/__init__.py +++ /dev/null @@ -1,852 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import ast -import json -import sys - -from datetime import datetime -from xml.dom import minidom -from azure import ( - WindowsAzureData, - WindowsAzureError, - xml_escape, - _create_entry, - _general_error_handler, - _get_entry_properties, - _get_child_nodes, - _get_children_from_path, - _get_first_child_node_value, - _ERROR_MESSAGE_NOT_PEEK_LOCKED_ON_DELETE, - _ERROR_MESSAGE_NOT_PEEK_LOCKED_ON_UNLOCK, - _ERROR_QUEUE_NOT_FOUND, - _ERROR_TOPIC_NOT_FOUND, - ) -from azure.http import HTTPError - -# default rule name for subscription -DEFAULT_RULE_NAME = '$Default' - -#----------------------------------------------------------------------------- -# Constants for Azure app environment settings. -AZURE_SERVICEBUS_NAMESPACE = 'AZURE_SERVICEBUS_NAMESPACE' -AZURE_SERVICEBUS_ACCESS_KEY = 'AZURE_SERVICEBUS_ACCESS_KEY' -AZURE_SERVICEBUS_ISSUER = 'AZURE_SERVICEBUS_ISSUER' - -# namespace used for converting rules to objects -XML_SCHEMA_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance' - - -class Queue(WindowsAzureData): - - ''' Queue class corresponding to Queue Description: - http://msdn.microsoft.com/en-us/library/windowsazure/hh780773''' - - def __init__(self, lock_duration=None, max_size_in_megabytes=None, - requires_duplicate_detection=None, requires_session=None, - default_message_time_to_live=None, - dead_lettering_on_message_expiration=None, - duplicate_detection_history_time_window=None, - max_delivery_count=None, enable_batched_operations=None, - size_in_bytes=None, message_count=None): - - self.lock_duration = lock_duration - self.max_size_in_megabytes = max_size_in_megabytes - self.requires_duplicate_detection = requires_duplicate_detection - self.requires_session = requires_session - self.default_message_time_to_live = default_message_time_to_live - self.dead_lettering_on_message_expiration = \ - dead_lettering_on_message_expiration - self.duplicate_detection_history_time_window = \ - duplicate_detection_history_time_window - self.max_delivery_count = max_delivery_count - self.enable_batched_operations = enable_batched_operations - self.size_in_bytes = size_in_bytes - self.message_count = message_count - - -class Topic(WindowsAzureData): - - ''' Topic class corresponding to Topic Description: - http://msdn.microsoft.com/en-us/library/windowsazure/hh780749. ''' - - def __init__(self, default_message_time_to_live=None, - max_size_in_megabytes=None, requires_duplicate_detection=None, - duplicate_detection_history_time_window=None, - enable_batched_operations=None, size_in_bytes=None): - - self.default_message_time_to_live = default_message_time_to_live - self.max_size_in_megabytes = max_size_in_megabytes - self.requires_duplicate_detection = requires_duplicate_detection - self.duplicate_detection_history_time_window = \ - duplicate_detection_history_time_window - self.enable_batched_operations = enable_batched_operations - self.size_in_bytes = size_in_bytes - - @property - def max_size_in_mega_bytes(self): - import warnings - warnings.warn( - 'This attribute has been changed to max_size_in_megabytes.') - return self.max_size_in_megabytes - - @max_size_in_mega_bytes.setter - def max_size_in_mega_bytes(self, value): - self.max_size_in_megabytes = value - - -class Subscription(WindowsAzureData): - - ''' Subscription class corresponding to Subscription Description: - http://msdn.microsoft.com/en-us/library/windowsazure/hh780763. ''' - - def __init__(self, lock_duration=None, requires_session=None, - default_message_time_to_live=None, - dead_lettering_on_message_expiration=None, - dead_lettering_on_filter_evaluation_exceptions=None, - enable_batched_operations=None, max_delivery_count=None, - message_count=None): - - self.lock_duration = lock_duration - self.requires_session = requires_session - self.default_message_time_to_live = default_message_time_to_live - self.dead_lettering_on_message_expiration = \ - dead_lettering_on_message_expiration - self.dead_lettering_on_filter_evaluation_exceptions = \ - dead_lettering_on_filter_evaluation_exceptions - self.enable_batched_operations = enable_batched_operations - self.max_delivery_count = max_delivery_count - self.message_count = message_count - - -class Rule(WindowsAzureData): - - ''' Rule class corresponding to Rule Description: - http://msdn.microsoft.com/en-us/library/windowsazure/hh780753. ''' - - def __init__(self, filter_type=None, filter_expression=None, - action_type=None, action_expression=None): - self.filter_type = filter_type - self.filter_expression = filter_expression - self.action_type = action_type - self.action_expression = action_type - - -class Message(WindowsAzureData): - - ''' Message class that used in send message/get mesage apis. ''' - - def __init__(self, body=None, service_bus_service=None, location=None, - custom_properties=None, - type='application/atom+xml;type=entry;charset=utf-8', - broker_properties=None): - self.body = body - self.location = location - self.broker_properties = broker_properties - self.custom_properties = custom_properties - self.type = type - self.service_bus_service = service_bus_service - self._topic_name = None - self._subscription_name = None - self._queue_name = None - - if not service_bus_service: - return - - # if location is set, then extracts the queue name for queue message and - # extracts the topic and subscriptions name if it is topic message. - if location: - if '/subscriptions/' in location: - pos = location.find(service_bus_service.host_base.lower())+1 - pos1 = location.find('/subscriptions/') - self._topic_name = location[pos+len(service_bus_service.host_base):pos1] - pos = pos1 + len('/subscriptions/') - pos1 = location.find('/', pos) - self._subscription_name = location[pos:pos1] - elif '/messages/' in location: - pos = location.find(service_bus_service.host_base.lower())+1 - pos1 = location.find('/messages/') - self._queue_name = location[pos+len(service_bus_service.host_base):pos1] - - def delete(self): - ''' Deletes itself if find queue name or topic name and subscription - name. ''' - if self._queue_name: - self.service_bus_service.delete_queue_message( - self._queue_name, - self.broker_properties['SequenceNumber'], - self.broker_properties['LockToken']) - elif self._topic_name and self._subscription_name: - self.service_bus_service.delete_subscription_message( - self._topic_name, - self._subscription_name, - self.broker_properties['SequenceNumber'], - self.broker_properties['LockToken']) - else: - raise WindowsAzureError(_ERROR_MESSAGE_NOT_PEEK_LOCKED_ON_DELETE) - - def unlock(self): - ''' Unlocks itself if find queue name or topic name and subscription - name. ''' - if self._queue_name: - self.service_bus_service.unlock_queue_message( - self._queue_name, - self.broker_properties['SequenceNumber'], - self.broker_properties['LockToken']) - elif self._topic_name and self._subscription_name: - self.service_bus_service.unlock_subscription_message( - self._topic_name, - self._subscription_name, - self.broker_properties['SequenceNumber'], - self.broker_properties['LockToken']) - else: - raise WindowsAzureError(_ERROR_MESSAGE_NOT_PEEK_LOCKED_ON_UNLOCK) - - def add_headers(self, request): - ''' add addtional headers to request for message request.''' - - # Adds custom properties - if self.custom_properties: - for name, value in self.custom_properties.items(): - if sys.version_info < (3,) and isinstance(value, unicode): - request.headers.append( - (name, '"' + value.encode('utf-8') + '"')) - elif isinstance(value, str): - request.headers.append((name, '"' + str(value) + '"')) - elif isinstance(value, datetime): - request.headers.append( - (name, '"' + value.strftime('%a, %d %b %Y %H:%M:%S GMT') + '"')) - else: - request.headers.append((name, str(value).lower())) - - # Adds content-type - request.headers.append(('Content-Type', self.type)) - - # Adds BrokerProperties - if self.broker_properties: - request.headers.append( - ('BrokerProperties', str(self.broker_properties))) - - return request.headers - - -def _create_message(response, service_instance): - ''' Create message from response. - - response: response from service bus cloud server. - service_instance: the service bus client. - ''' - respbody = response.body - custom_properties = {} - broker_properties = None - message_type = None - message_location = None - - # gets all information from respheaders. - for name, value in response.headers: - if name.lower() == 'brokerproperties': - broker_properties = json.loads(value) - elif name.lower() == 'content-type': - message_type = value - elif name.lower() == 'location': - message_location = value - elif name.lower() not in ['content-type', - 'brokerproperties', - 'transfer-encoding', - 'server', - 'location', - 'date']: - if '"' in value: - value = value[1:-1] - try: - custom_properties[name] = datetime.strptime( - value, '%a, %d %b %Y %H:%M:%S GMT') - except ValueError: - custom_properties[name] = value - else: # only int, float or boolean - if value.lower() == 'true': - custom_properties[name] = True - elif value.lower() == 'false': - custom_properties[name] = False - # int('3.1') doesn't work so need to get float('3.14') first - elif str(int(float(value))) == value: - custom_properties[name] = int(value) - else: - custom_properties[name] = float(value) - - if message_type == None: - message = Message( - respbody, service_instance, message_location, custom_properties, - 'application/atom+xml;type=entry;charset=utf-8', broker_properties) - else: - message = Message(respbody, service_instance, message_location, - custom_properties, message_type, broker_properties) - return message - -# convert functions - - -def _convert_response_to_rule(response): - return _convert_xml_to_rule(response.body) - - -def _convert_xml_to_rule(xmlstr): - ''' Converts response xml to rule object. - - The format of xml for rule: -<entry xmlns='http://www.w3.org/2005/Atom'> -<content type='application/xml'> -<RuleDescription - xmlns:i="http://www.w3.org/2001/XMLSchema-instance" - xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"> - <Filter i:type="SqlFilterExpression"> - <SqlExpression>MyProperty='XYZ'</SqlExpression> - </Filter> - <Action i:type="SqlFilterAction"> - <SqlExpression>set MyProperty2 = 'ABC'</SqlExpression> - </Action> -</RuleDescription> -</content> -</entry> - ''' - xmldoc = minidom.parseString(xmlstr) - rule = Rule() - - for rule_desc in _get_children_from_path(xmldoc, - 'entry', - 'content', - 'RuleDescription'): - for xml_filter in _get_child_nodes(rule_desc, 'Filter'): - filter_type = xml_filter.getAttributeNS( - XML_SCHEMA_NAMESPACE, 'type') - setattr(rule, 'filter_type', str(filter_type)) - if xml_filter.childNodes: - - for expr in _get_child_nodes(xml_filter, 'SqlExpression'): - setattr(rule, 'filter_expression', - expr.firstChild.nodeValue) - - for xml_action in _get_child_nodes(rule_desc, 'Action'): - action_type = xml_action.getAttributeNS( - XML_SCHEMA_NAMESPACE, 'type') - setattr(rule, 'action_type', str(action_type)) - if xml_action.childNodes: - action_expression = xml_action.childNodes[0].firstChild - if action_expression: - setattr(rule, 'action_expression', - action_expression.nodeValue) - - # extract id, updated and name value from feed entry and set them of rule. - for name, value in _get_entry_properties(xmlstr, True, '/rules').items(): - setattr(rule, name, value) - - return rule - - -def _convert_response_to_queue(response): - return _convert_xml_to_queue(response.body) - - -def _parse_bool(value): - if value.lower() == 'true': - return True - return False - - -def _convert_xml_to_queue(xmlstr): - ''' Converts xml response to queue object. - - The format of xml response for queue: -<QueueDescription - xmlns=\"http://schemas.microsoft.com/netservices/2010/10/servicebus/connect\"> - <MaxSizeInBytes>10000</MaxSizeInBytes> - <DefaultMessageTimeToLive>PT5M</DefaultMessageTimeToLive> - <LockDuration>PT2M</LockDuration> - <RequiresGroupedReceives>False</RequiresGroupedReceives> - <SupportsDuplicateDetection>False</SupportsDuplicateDetection> - ... -</QueueDescription> - - ''' - xmldoc = minidom.parseString(xmlstr) - queue = Queue() - - invalid_queue = True - # get node for each attribute in Queue class, if nothing found then the - # response is not valid xml for Queue. - for desc in _get_children_from_path(xmldoc, - 'entry', - 'content', - 'QueueDescription'): - node_value = _get_first_child_node_value(desc, 'LockDuration') - if node_value is not None: - queue.lock_duration = node_value - invalid_queue = False - - node_value = _get_first_child_node_value(desc, 'MaxSizeInMegabytes') - if node_value is not None: - queue.max_size_in_megabytes = int(node_value) - invalid_queue = False - - node_value = _get_first_child_node_value( - desc, 'RequiresDuplicateDetection') - if node_value is not None: - queue.requires_duplicate_detection = _parse_bool(node_value) - invalid_queue = False - - node_value = _get_first_child_node_value(desc, 'RequiresSession') - if node_value is not None: - queue.requires_session = _parse_bool(node_value) - invalid_queue = False - - node_value = _get_first_child_node_value( - desc, 'DefaultMessageTimeToLive') - if node_value is not None: - queue.default_message_time_to_live = node_value - invalid_queue = False - - node_value = _get_first_child_node_value( - desc, 'DeadLetteringOnMessageExpiration') - if node_value is not None: - queue.dead_lettering_on_message_expiration = _parse_bool(node_value) - invalid_queue = False - - node_value = _get_first_child_node_value( - desc, 'DuplicateDetectionHistoryTimeWindow') - if node_value is not None: - queue.duplicate_detection_history_time_window = node_value - invalid_queue = False - - node_value = _get_first_child_node_value( - desc, 'EnableBatchedOperations') - if node_value is not None: - queue.enable_batched_operations = _parse_bool(node_value) - invalid_queue = False - - node_value = _get_first_child_node_value(desc, 'MaxDeliveryCount') - if node_value is not None: - queue.max_delivery_count = int(node_value) - invalid_queue = False - - node_value = _get_first_child_node_value(desc, 'MessageCount') - if node_value is not None: - queue.message_count = int(node_value) - invalid_queue = False - - node_value = _get_first_child_node_value(desc, 'SizeInBytes') - if node_value is not None: - queue.size_in_bytes = int(node_value) - invalid_queue = False - - if invalid_queue: - raise WindowsAzureError(_ERROR_QUEUE_NOT_FOUND) - - # extract id, updated and name value from feed entry and set them of queue. - for name, value in _get_entry_properties(xmlstr, True).items(): - setattr(queue, name, value) - - return queue - - -def _convert_response_to_topic(response): - return _convert_xml_to_topic(response.body) - - -def _convert_xml_to_topic(xmlstr): - '''Converts xml response to topic - - The xml format for topic: -<entry xmlns='http://www.w3.org/2005/Atom'> - <content type='application/xml'> - <TopicDescription - xmlns:i="http://www.w3.org/2001/XMLSchema-instance" - xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"> - <DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive> - <MaxSizeInMegabytes>1024</MaxSizeInMegabytes> - <RequiresDuplicateDetection>false</RequiresDuplicateDetection> - <DuplicateDetectionHistoryTimeWindow>P7D</DuplicateDetectionHistoryTimeWindow> - <DeadLetteringOnFilterEvaluationExceptions>true</DeadLetteringOnFilterEvaluationExceptions> - </TopicDescription> - </content> -</entry> - ''' - xmldoc = minidom.parseString(xmlstr) - topic = Topic() - - invalid_topic = True - - # get node for each attribute in Topic class, if nothing found then the - # response is not valid xml for Topic. - for desc in _get_children_from_path(xmldoc, - 'entry', - 'content', - 'TopicDescription'): - invalid_topic = True - node_value = _get_first_child_node_value( - desc, 'DefaultMessageTimeToLive') - if node_value is not None: - topic.default_message_time_to_live = node_value - invalid_topic = False - node_value = _get_first_child_node_value(desc, 'MaxSizeInMegabytes') - if node_value is not None: - topic.max_size_in_megabytes = int(node_value) - invalid_topic = False - node_value = _get_first_child_node_value( - desc, 'RequiresDuplicateDetection') - if node_value is not None: - topic.requires_duplicate_detection = _parse_bool(node_value) - invalid_topic = False - node_value = _get_first_child_node_value( - desc, 'DuplicateDetectionHistoryTimeWindow') - if node_value is not None: - topic.duplicate_detection_history_time_window = node_value - invalid_topic = False - node_value = _get_first_child_node_value( - desc, 'EnableBatchedOperations') - if node_value is not None: - topic.enable_batched_operations = _parse_bool(node_value) - invalid_topic = False - node_value = _get_first_child_node_value(desc, 'SizeInBytes') - if node_value is not None: - topic.size_in_bytes = int(node_value) - invalid_topic = False - - if invalid_topic: - raise WindowsAzureError(_ERROR_TOPIC_NOT_FOUND) - - # extract id, updated and name value from feed entry and set them of topic. - for name, value in _get_entry_properties(xmlstr, True).items(): - setattr(topic, name, value) - return topic - - -def _convert_response_to_subscription(response): - return _convert_xml_to_subscription(response.body) - - -def _convert_xml_to_subscription(xmlstr): - '''Converts xml response to subscription - - The xml format for subscription: -<entry xmlns='http://www.w3.org/2005/Atom'> - <content type='application/xml'> - <SubscriptionDescription - xmlns:i="http://www.w3.org/2001/XMLSchema-instance" - xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"> - <LockDuration>PT5M</LockDuration> - <RequiresSession>false</RequiresSession> - <DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive> - <DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration> - <DeadLetteringOnFilterEvaluationExceptions>true</DeadLetteringOnFilterEvaluationExceptions> - </SubscriptionDescription> - </content> -</entry> - ''' - xmldoc = minidom.parseString(xmlstr) - subscription = Subscription() - - for desc in _get_children_from_path(xmldoc, - 'entry', - 'content', - 'SubscriptionDescription'): - node_value = _get_first_child_node_value(desc, 'LockDuration') - if node_value is not None: - subscription.lock_duration = node_value - - node_value = _get_first_child_node_value( - desc, 'RequiresSession') - if node_value is not None: - subscription.requires_session = _parse_bool(node_value) - - node_value = _get_first_child_node_value( - desc, 'DefaultMessageTimeToLive') - if node_value is not None: - subscription.default_message_time_to_live = node_value - - node_value = _get_first_child_node_value( - desc, 'DeadLetteringOnFilterEvaluationExceptions') - if node_value is not None: - subscription.dead_lettering_on_filter_evaluation_exceptions = \ - _parse_bool(node_value) - - node_value = _get_first_child_node_value( - desc, 'DeadLetteringOnMessageExpiration') - if node_value is not None: - subscription.dead_lettering_on_message_expiration = \ - _parse_bool(node_value) - - node_value = _get_first_child_node_value( - desc, 'EnableBatchedOperations') - if node_value is not None: - subscription.enable_batched_operations = _parse_bool(node_value) - - node_value = _get_first_child_node_value( - desc, 'MaxDeliveryCount') - if node_value is not None: - subscription.max_delivery_count = int(node_value) - - node_value = _get_first_child_node_value( - desc, 'MessageCount') - if node_value is not None: - subscription.message_count = int(node_value) - - for name, value in _get_entry_properties(xmlstr, - True, - '/subscriptions').items(): - setattr(subscription, name, value) - - return subscription - - -def _convert_subscription_to_xml(subscription): - ''' - Converts a subscription object to xml to send. The order of each field of - subscription in xml is very important so we can't simple call - convert_class_to_xml. - - subscription: the subsciption object to be converted. - ''' - - subscription_body = '<SubscriptionDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">' - if subscription: - if subscription.lock_duration is not None: - subscription_body += ''.join( - ['<LockDuration>', - str(subscription.lock_duration), - '</LockDuration>']) - - if subscription.requires_session is not None: - subscription_body += ''.join( - ['<RequiresSession>', - str(subscription.requires_session).lower(), - '</RequiresSession>']) - - if subscription.default_message_time_to_live is not None: - subscription_body += ''.join( - ['<DefaultMessageTimeToLive>', - str(subscription.default_message_time_to_live), - '</DefaultMessageTimeToLive>']) - - if subscription.dead_lettering_on_message_expiration is not None: - subscription_body += ''.join( - ['<DeadLetteringOnMessageExpiration>', - str(subscription.dead_lettering_on_message_expiration).lower(), - '</DeadLetteringOnMessageExpiration>']) - - if subscription.dead_lettering_on_filter_evaluation_exceptions is not None: - subscription_body += ''.join( - ['<DeadLetteringOnFilterEvaluationExceptions>', - str(subscription.dead_lettering_on_filter_evaluation_exceptions).lower(), - '</DeadLetteringOnFilterEvaluationExceptions>']) - - if subscription.enable_batched_operations is not None: - subscription_body += ''.join( - ['<EnableBatchedOperations>', - str(subscription.enable_batched_operations).lower(), - '</EnableBatchedOperations>']) - - if subscription.max_delivery_count is not None: - subscription_body += ''.join( - ['<MaxDeliveryCount>', - str(subscription.max_delivery_count), - '</MaxDeliveryCount>']) - - if subscription.message_count is not None: - subscription_body += ''.join( - ['<MessageCount>', - str(subscription.message_count), - '</MessageCount>']) - - subscription_body += '</SubscriptionDescription>' - return _create_entry(subscription_body) - - -def _convert_rule_to_xml(rule): - ''' - Converts a rule object to xml to send. The order of each field of rule - in xml is very important so we cann't simple call convert_class_to_xml. - - rule: the rule object to be converted. - ''' - rule_body = '<RuleDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">' - if rule: - if rule.filter_type: - rule_body += ''.join( - ['<Filter i:type="', - xml_escape(rule.filter_type), - '">']) - if rule.filter_type == 'CorrelationFilter': - rule_body += ''.join( - ['<CorrelationId>', - xml_escape(rule.filter_expression), - '</CorrelationId>']) - else: - rule_body += ''.join( - ['<SqlExpression>', - xml_escape(rule.filter_expression), - '</SqlExpression>']) - rule_body += '<CompatibilityLevel>20</CompatibilityLevel>' - rule_body += '</Filter>' - if rule.action_type: - rule_body += ''.join( - ['<Action i:type="', - xml_escape(rule.action_type), - '">']) - if rule.action_type == 'SqlRuleAction': - rule_body += ''.join( - ['<SqlExpression>', - xml_escape(rule.action_expression), - '</SqlExpression>']) - rule_body += '<CompatibilityLevel>20</CompatibilityLevel>' - rule_body += '</Action>' - rule_body += '</RuleDescription>' - - return _create_entry(rule_body) - - -def _convert_topic_to_xml(topic): - ''' - Converts a topic object to xml to send. The order of each field of topic - in xml is very important so we cann't simple call convert_class_to_xml. - - topic: the topic object to be converted. - ''' - - topic_body = '<TopicDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">' - if topic: - if topic.default_message_time_to_live is not None: - topic_body += ''.join( - ['<DefaultMessageTimeToLive>', - str(topic.default_message_time_to_live), - '</DefaultMessageTimeToLive>']) - - if topic.max_size_in_megabytes is not None: - topic_body += ''.join( - ['<MaxSizeInMegabytes>', - str(topic.max_size_in_megabytes), - '</MaxSizeInMegabytes>']) - - if topic.requires_duplicate_detection is not None: - topic_body += ''.join( - ['<RequiresDuplicateDetection>', - str(topic.requires_duplicate_detection).lower(), - '</RequiresDuplicateDetection>']) - - if topic.duplicate_detection_history_time_window is not None: - topic_body += ''.join( - ['<DuplicateDetectionHistoryTimeWindow>', - str(topic.duplicate_detection_history_time_window), - '</DuplicateDetectionHistoryTimeWindow>']) - - if topic.enable_batched_operations is not None: - topic_body += ''.join( - ['<EnableBatchedOperations>', - str(topic.enable_batched_operations).lower(), - '</EnableBatchedOperations>']) - - if topic.size_in_bytes is not None: - topic_body += ''.join( - ['<SizeInBytes>', - str(topic.size_in_bytes), - '</SizeInBytes>']) - - topic_body += '</TopicDescription>' - - return _create_entry(topic_body) - - -def _convert_queue_to_xml(queue): - ''' - Converts a queue object to xml to send. The order of each field of queue - in xml is very important so we cann't simple call convert_class_to_xml. - - queue: the queue object to be converted. - ''' - queue_body = '<QueueDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">' - if queue: - if queue.lock_duration: - queue_body += ''.join( - ['<LockDuration>', - str(queue.lock_duration), - '</LockDuration>']) - - if queue.max_size_in_megabytes is not None: - queue_body += ''.join( - ['<MaxSizeInMegabytes>', - str(queue.max_size_in_megabytes), - '</MaxSizeInMegabytes>']) - - if queue.requires_duplicate_detection is not None: - queue_body += ''.join( - ['<RequiresDuplicateDetection>', - str(queue.requires_duplicate_detection).lower(), - '</RequiresDuplicateDetection>']) - - if queue.requires_session is not None: - queue_body += ''.join( - ['<RequiresSession>', - str(queue.requires_session).lower(), - '</RequiresSession>']) - - if queue.default_message_time_to_live is not None: - queue_body += ''.join( - ['<DefaultMessageTimeToLive>', - str(queue.default_message_time_to_live), - '</DefaultMessageTimeToLive>']) - - if queue.dead_lettering_on_message_expiration is not None: - queue_body += ''.join( - ['<DeadLetteringOnMessageExpiration>', - str(queue.dead_lettering_on_message_expiration).lower(), - '</DeadLetteringOnMessageExpiration>']) - - if queue.duplicate_detection_history_time_window is not None: - queue_body += ''.join( - ['<DuplicateDetectionHistoryTimeWindow>', - str(queue.duplicate_detection_history_time_window), - '</DuplicateDetectionHistoryTimeWindow>']) - - if queue.max_delivery_count is not None: - queue_body += ''.join( - ['<MaxDeliveryCount>', - str(queue.max_delivery_count), - '</MaxDeliveryCount>']) - - if queue.enable_batched_operations is not None: - queue_body += ''.join( - ['<EnableBatchedOperations>', - str(queue.enable_batched_operations).lower(), - '</EnableBatchedOperations>']) - - if queue.size_in_bytes is not None: - queue_body += ''.join( - ['<SizeInBytes>', - str(queue.size_in_bytes), - '</SizeInBytes>']) - - if queue.message_count is not None: - queue_body += ''.join( - ['<MessageCount>', - str(queue.message_count), - '</MessageCount>']) - - queue_body += '</QueueDescription>' - return _create_entry(queue_body) - - -def _service_bus_error_handler(http_error): - ''' Simple error handler for service bus service. ''' - return _general_error_handler(http_error) - -from azure.servicebus.servicebusservice import ServiceBusService diff --git a/awx/lib/site-packages/azure/servicebus/servicebusservice.py b/awx/lib/site-packages/azure/servicebus/servicebusservice.py deleted file mode 100644 index dcd5fd6ed3..0000000000 --- a/awx/lib/site-packages/azure/servicebus/servicebusservice.py +++ /dev/null @@ -1,1011 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import datetime -import os -import time - -from azure import ( - WindowsAzureError, - SERVICE_BUS_HOST_BASE, - _convert_response_to_feeds, - _dont_fail_not_exist, - _dont_fail_on_exist, - _encode_base64, - _get_request_body, - _get_request_body_bytes_only, - _int_or_none, - _sign_string, - _str, - _unicode_type, - _update_request_uri_query, - url_quote, - url_unquote, - _validate_not_none, - ) -from azure.http import ( - HTTPError, - HTTPRequest, - ) -from azure.http.httpclient import _HTTPClient -from azure.servicebus import ( - AZURE_SERVICEBUS_NAMESPACE, - AZURE_SERVICEBUS_ACCESS_KEY, - AZURE_SERVICEBUS_ISSUER, - _convert_topic_to_xml, - _convert_response_to_topic, - _convert_queue_to_xml, - _convert_response_to_queue, - _convert_subscription_to_xml, - _convert_response_to_subscription, - _convert_rule_to_xml, - _convert_response_to_rule, - _convert_xml_to_queue, - _convert_xml_to_topic, - _convert_xml_to_subscription, - _convert_xml_to_rule, - _create_message, - _service_bus_error_handler, - ) - - -class ServiceBusService(object): - - def __init__(self, service_namespace=None, account_key=None, issuer=None, - x_ms_version='2011-06-01', host_base=SERVICE_BUS_HOST_BASE, - shared_access_key_name=None, shared_access_key_value=None, - authentication=None): - ''' - Initializes the service bus service for a namespace with the specified - authentication settings (SAS or ACS). - - service_namespace: - Service bus namespace, required for all operations. If None, - the value is set to the AZURE_SERVICEBUS_NAMESPACE env variable. - account_key: - ACS authentication account key. If None, the value is set to the - AZURE_SERVICEBUS_ACCESS_KEY env variable. - Note that if both SAS and ACS settings are specified, SAS is used. - issuer: - ACS authentication issuer. If None, the value is set to the - AZURE_SERVICEBUS_ISSUER env variable. - Note that if both SAS and ACS settings are specified, SAS is used. - x_ms_version: Unused. Kept for backwards compatibility. - host_base: - Optional. Live host base url. Defaults to Azure url. Override this - for on-premise. - shared_access_key_name: - SAS authentication key name. - Note that if both SAS and ACS settings are specified, SAS is used. - shared_access_key_value: - SAS authentication key value. - Note that if both SAS and ACS settings are specified, SAS is used. - authentication: - Instance of authentication class. If this is specified, then - ACS and SAS parameters are ignored. - ''' - self.requestid = None - self.service_namespace = service_namespace - self.host_base = host_base - - if not self.service_namespace: - self.service_namespace = os.environ.get(AZURE_SERVICEBUS_NAMESPACE) - - if not self.service_namespace: - raise WindowsAzureError('You need to provide servicebus namespace') - - if authentication: - self.authentication = authentication - else: - if not account_key: - account_key = os.environ.get(AZURE_SERVICEBUS_ACCESS_KEY) - if not issuer: - issuer = os.environ.get(AZURE_SERVICEBUS_ISSUER) - - if shared_access_key_name and shared_access_key_value: - self.authentication = ServiceBusSASAuthentication( - shared_access_key_name, - shared_access_key_value) - elif account_key and issuer: - self.authentication = ServiceBusWrapTokenAuthentication( - account_key, - issuer) - else: - raise WindowsAzureError( - 'You need to provide servicebus access key and Issuer OR shared access key and value') - - self._httpclient = _HTTPClient(service_instance=self) - self._filter = self._httpclient.perform_request - - # Backwards compatibility: - # account_key and issuer used to be stored on the service class, they are - # now stored on the authentication class. - @property - def account_key(self): - return self.authentication.account_key - - @account_key.setter - def account_key(self, value): - self.authentication.account_key = value - - @property - def issuer(self): - return self.authentication.issuer - - @issuer.setter - def issuer(self, value): - self.authentication.issuer = value - - def with_filter(self, filter): - ''' - Returns a new service which will process requests with the specified - filter. Filtering operations can include logging, automatic retrying, - etc... The filter is a lambda which receives the HTTPRequest and - another lambda. The filter can perform any pre-processing on the - request, pass it off to the next lambda, and then perform any - post-processing on the response. - ''' - res = ServiceBusService( - service_namespace=self.service_namespace, - authentication=self.authentication) - - old_filter = self._filter - - def new_filter(request): - return filter(request, old_filter) - - res._filter = new_filter - return res - - def set_proxy(self, host, port, user=None, password=None): - ''' - Sets the proxy server host and port for the HTTP CONNECT Tunnelling. - - host: Address of the proxy. Ex: '192.168.0.100' - port: Port of the proxy. Ex: 6000 - user: User for proxy authorization. - password: Password for proxy authorization. - ''' - self._httpclient.set_proxy(host, port, user, password) - - def create_queue(self, queue_name, queue=None, fail_on_exist=False): - ''' - Creates a new queue. Once created, this queue's resource manifest is - immutable. - - queue_name: Name of the queue to create. - queue: Queue object to create. - fail_on_exist: - Specify whether to throw an exception when the queue exists. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '' - request.body = _get_request_body(_convert_queue_to_xml(queue)) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_on_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_on_exist(ex) - return False - else: - self._perform_request(request) - return True - - def delete_queue(self, queue_name, fail_not_exist=False): - ''' - Deletes an existing queue. This operation will also remove all - associated state including messages in the queue. - - queue_name: Name of the queue to delete. - fail_not_exist: - Specify whether to throw an exception if the queue doesn't exist. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_not_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_not_exist(ex) - return False - else: - self._perform_request(request) - return True - - def get_queue(self, queue_name): - ''' - Retrieves an existing queue. - - queue_name: Name of the queue. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_queue(response) - - def list_queues(self): - ''' - Enumerates the queues in the service namespace. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/$Resources/Queues' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_feeds(response, _convert_xml_to_queue) - - def create_topic(self, topic_name, topic=None, fail_on_exist=False): - ''' - Creates a new topic. Once created, this topic resource manifest is - immutable. - - topic_name: Name of the topic to create. - topic: Topic object to create. - fail_on_exist: - Specify whether to throw an exception when the topic exists. - ''' - _validate_not_none('topic_name', topic_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '' - request.body = _get_request_body(_convert_topic_to_xml(topic)) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_on_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_on_exist(ex) - return False - else: - self._perform_request(request) - return True - - def delete_topic(self, topic_name, fail_not_exist=False): - ''' - Deletes an existing topic. This operation will also remove all - associated state including associated subscriptions. - - topic_name: Name of the topic to delete. - fail_not_exist: - Specify whether throw exception when topic doesn't exist. - ''' - _validate_not_none('topic_name', topic_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_not_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_not_exist(ex) - return False - else: - self._perform_request(request) - return True - - def get_topic(self, topic_name): - ''' - Retrieves the description for the specified topic. - - topic_name: Name of the topic. - ''' - _validate_not_none('topic_name', topic_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_topic(response) - - def list_topics(self): - ''' - Retrieves the topics in the service namespace. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/$Resources/Topics' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_feeds(response, _convert_xml_to_topic) - - def create_rule(self, topic_name, subscription_name, rule_name, rule=None, - fail_on_exist=False): - ''' - Creates a new rule. Once created, this rule's resource manifest is - immutable. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - rule_name: Name of the rule. - fail_on_exist: - Specify whether to throw an exception when the rule exists. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - _validate_not_none('rule_name', rule_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '/subscriptions/' + \ - _str(subscription_name) + \ - '/rules/' + _str(rule_name) + '' - request.body = _get_request_body(_convert_rule_to_xml(rule)) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_on_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_on_exist(ex) - return False - else: - self._perform_request(request) - return True - - def delete_rule(self, topic_name, subscription_name, rule_name, - fail_not_exist=False): - ''' - Deletes an existing rule. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - rule_name: - Name of the rule to delete. DEFAULT_RULE_NAME=$Default. - Use DEFAULT_RULE_NAME to delete default rule for the subscription. - fail_not_exist: - Specify whether throw exception when rule doesn't exist. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - _validate_not_none('rule_name', rule_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '/subscriptions/' + \ - _str(subscription_name) + \ - '/rules/' + _str(rule_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_not_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_not_exist(ex) - return False - else: - self._perform_request(request) - return True - - def get_rule(self, topic_name, subscription_name, rule_name): - ''' - Retrieves the description for the specified rule. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - rule_name: Name of the rule. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - _validate_not_none('rule_name', rule_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '/subscriptions/' + \ - _str(subscription_name) + \ - '/rules/' + _str(rule_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_rule(response) - - def list_rules(self, topic_name, subscription_name): - ''' - Retrieves the rules that exist under the specified subscription. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(topic_name) + '/subscriptions/' + \ - _str(subscription_name) + '/rules/' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_feeds(response, _convert_xml_to_rule) - - def create_subscription(self, topic_name, subscription_name, - subscription=None, fail_on_exist=False): - ''' - Creates a new subscription. Once created, this subscription resource - manifest is immutable. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - fail_on_exist: - Specify whether throw exception when subscription exists. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(topic_name) + '/subscriptions/' + _str(subscription_name) + '' - request.body = _get_request_body( - _convert_subscription_to_xml(subscription)) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_on_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_on_exist(ex) - return False - else: - self._perform_request(request) - return True - - def delete_subscription(self, topic_name, subscription_name, - fail_not_exist=False): - ''' - Deletes an existing subscription. - - topic_name: Name of the topic. - subscription_name: Name of the subscription to delete. - fail_not_exist: - Specify whether to throw an exception when the subscription - doesn't exist. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + \ - _str(topic_name) + '/subscriptions/' + _str(subscription_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - if not fail_not_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_not_exist(ex) - return False - else: - self._perform_request(request) - return True - - def get_subscription(self, topic_name, subscription_name): - ''' - Gets an existing subscription. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(topic_name) + '/subscriptions/' + _str(subscription_name) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_subscription(response) - - def list_subscriptions(self, topic_name): - ''' - Retrieves the subscriptions in the specified topic. - - topic_name: Name of the topic. - ''' - _validate_not_none('topic_name', topic_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '/subscriptions/' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _convert_response_to_feeds(response, - _convert_xml_to_subscription) - - def send_topic_message(self, topic_name, message=None): - ''' - Enqueues a message into the specified topic. The limit to the number - of messages which may be present in the topic is governed by the - message size in MaxTopicSizeInBytes. If this message causes the topic - to exceed its quota, a quota exceeded error is returned and the - message will be rejected. - - topic_name: Name of the topic. - message: Message object containing message body and properties. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('message', message) - request = HTTPRequest() - request.method = 'POST' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + '/messages' - request.headers = message.add_headers(request) - request.body = _get_request_body_bytes_only( - 'message.body', message.body) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - self._perform_request(request) - - def peek_lock_subscription_message(self, topic_name, subscription_name, - timeout='60'): - ''' - This operation is used to atomically retrieve and lock a message for - processing. The message is guaranteed not to be delivered to other - receivers during the lock duration period specified in buffer - description. Once the lock expires, the message will be available to - other receivers (on the same subscription only) during the lock - duration period specified in the topic description. Once the lock - expires, the message will be available to other receivers. In order to - complete processing of the message, the receiver should issue a delete - command with the lock ID received from this operation. To abandon - processing of the message and unlock it for other receivers, an Unlock - Message command should be issued, or the lock duration period can - expire. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - request = HTTPRequest() - request.method = 'POST' - request.host = self._get_host() - request.path = '/' + \ - _str(topic_name) + '/subscriptions/' + \ - _str(subscription_name) + '/messages/head' - request.query = [('timeout', _int_or_none(timeout))] - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _create_message(response, self) - - def unlock_subscription_message(self, topic_name, subscription_name, - sequence_number, lock_token): - ''' - Unlock a message for processing by other receivers on a given - subscription. This operation deletes the lock object, causing the - message to be unlocked. A message must have first been locked by a - receiver before this operation is called. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - sequence_number: - The sequence number of the message to be unlocked as returned in - BrokerProperties['SequenceNumber'] by the Peek Message operation. - lock_token: - The ID of the lock as returned by the Peek Message operation in - BrokerProperties['LockToken'] - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - _validate_not_none('sequence_number', sequence_number) - _validate_not_none('lock_token', lock_token) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + \ - '/subscriptions/' + str(subscription_name) + \ - '/messages/' + _str(sequence_number) + \ - '/' + _str(lock_token) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - self._perform_request(request) - - def read_delete_subscription_message(self, topic_name, subscription_name, - timeout='60'): - ''' - Read and delete a message from a subscription as an atomic operation. - This operation should be used when a best-effort guarantee is - sufficient for an application; that is, using this operation it is - possible for messages to be lost if processing fails. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + \ - '/subscriptions/' + _str(subscription_name) + \ - '/messages/head' - request.query = [('timeout', _int_or_none(timeout))] - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _create_message(response, self) - - def delete_subscription_message(self, topic_name, subscription_name, - sequence_number, lock_token): - ''' - Completes processing on a locked message and delete it from the - subscription. This operation should only be called after processing a - previously locked message is successful to maintain At-Least-Once - delivery assurances. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - sequence_number: - The sequence number of the message to be deleted as returned in - BrokerProperties['SequenceNumber'] by the Peek Message operation. - lock_token: - The ID of the lock as returned by the Peek Message operation in - BrokerProperties['LockToken'] - ''' - _validate_not_none('topic_name', topic_name) - _validate_not_none('subscription_name', subscription_name) - _validate_not_none('sequence_number', sequence_number) - _validate_not_none('lock_token', lock_token) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(topic_name) + \ - '/subscriptions/' + _str(subscription_name) + \ - '/messages/' + _str(sequence_number) + \ - '/' + _str(lock_token) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - self._perform_request(request) - - def send_queue_message(self, queue_name, message=None): - ''' - Sends a message into the specified queue. The limit to the number of - messages which may be present in the topic is governed by the message - size the MaxTopicSizeInMegaBytes. If this message will cause the queue - to exceed its quota, a quota exceeded error is returned and the - message will be rejected. - - queue_name: Name of the queue. - message: Message object containing message body and properties. - ''' - _validate_not_none('queue_name', queue_name) - _validate_not_none('message', message) - request = HTTPRequest() - request.method = 'POST' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '/messages' - request.headers = message.add_headers(request) - request.body = _get_request_body_bytes_only('message.body', - message.body) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - self._perform_request(request) - - def peek_lock_queue_message(self, queue_name, timeout='60'): - ''' - Automically retrieves and locks a message from a queue for processing. - The message is guaranteed not to be delivered to other receivers (on - the same subscription only) during the lock duration period specified - in the queue description. Once the lock expires, the message will be - available to other receivers. In order to complete processing of the - message, the receiver should issue a delete command with the lock ID - received from this operation. To abandon processing of the message and - unlock it for other receivers, an Unlock Message command should be - issued, or the lock duration period can expire. - - queue_name: Name of the queue. - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'POST' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '/messages/head' - request.query = [('timeout', _int_or_none(timeout))] - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _create_message(response, self) - - def unlock_queue_message(self, queue_name, sequence_number, lock_token): - ''' - Unlocks a message for processing by other receivers on a given - subscription. This operation deletes the lock object, causing the - message to be unlocked. A message must have first been locked by a - receiver before this operation is called. - - queue_name: Name of the queue. - sequence_number: - The sequence number of the message to be unlocked as returned in - BrokerProperties['SequenceNumber'] by the Peek Message operation. - lock_token: - The ID of the lock as returned by the Peek Message operation in - BrokerProperties['LockToken'] - ''' - _validate_not_none('queue_name', queue_name) - _validate_not_none('sequence_number', sequence_number) - _validate_not_none('lock_token', lock_token) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + \ - '/messages/' + _str(sequence_number) + \ - '/' + _str(lock_token) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - self._perform_request(request) - - def read_delete_queue_message(self, queue_name, timeout='60'): - ''' - Reads and deletes a message from a queue as an atomic operation. This - operation should be used when a best-effort guarantee is sufficient - for an application; that is, using this operation it is possible for - messages to be lost if processing fails. - - queue_name: Name of the queue. - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '/messages/head' - request.query = [('timeout', _int_or_none(timeout))] - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - response = self._perform_request(request) - - return _create_message(response, self) - - def delete_queue_message(self, queue_name, sequence_number, lock_token): - ''' - Completes processing on a locked message and delete it from the queue. - This operation should only be called after processing a previously - locked message is successful to maintain At-Least-Once delivery - assurances. - - queue_name: Name of the queue. - sequence_number: - The sequence number of the message to be deleted as returned in - BrokerProperties['SequenceNumber'] by the Peek Message operation. - lock_token: - The ID of the lock as returned by the Peek Message operation in - BrokerProperties['LockToken'] - ''' - _validate_not_none('queue_name', queue_name) - _validate_not_none('sequence_number', sequence_number) - _validate_not_none('lock_token', lock_token) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + \ - '/messages/' + _str(sequence_number) + \ - '/' + _str(lock_token) + '' - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_service_bus_header(request) - self._perform_request(request) - - def receive_queue_message(self, queue_name, peek_lock=True, timeout=60): - ''' - Receive a message from a queue for processing. - - queue_name: Name of the queue. - peek_lock: - Optional. True to retrieve and lock the message. False to read and - delete the message. Default is True (lock). - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - if peek_lock: - return self.peek_lock_queue_message(queue_name, timeout) - else: - return self.read_delete_queue_message(queue_name, timeout) - - def receive_subscription_message(self, topic_name, subscription_name, - peek_lock=True, timeout=60): - ''' - Receive a message from a subscription for processing. - - topic_name: Name of the topic. - subscription_name: Name of the subscription. - peek_lock: - Optional. True to retrieve and lock the message. False to read and - delete the message. Default is True (lock). - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - if peek_lock: - return self.peek_lock_subscription_message(topic_name, - subscription_name, - timeout) - else: - return self.read_delete_subscription_message(topic_name, - subscription_name, - timeout) - - def _get_host(self): - return self.service_namespace + self.host_base - - def _perform_request(self, request): - try: - resp = self._filter(request) - except HTTPError as ex: - return _service_bus_error_handler(ex) - - return resp - - def _update_service_bus_header(self, request): - ''' Add additional headers for service bus. ''' - - if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']: - request.headers.append(('Content-Length', str(len(request.body)))) - - # if it is not GET or HEAD request, must set content-type. - if not request.method in ['GET', 'HEAD']: - for name, _ in request.headers: - if 'content-type' == name.lower(): - break - else: - request.headers.append( - ('Content-Type', - 'application/atom+xml;type=entry;charset=utf-8')) - - # Adds authorization header for authentication. - self.authentication.sign_request(request, self._httpclient) - - return request.headers - - -# Token cache for Authentication -# Shared by the different instances of ServiceBusWrapTokenAuthentication -_tokens = {} - - -class ServiceBusWrapTokenAuthentication: - def __init__(self, account_key, issuer): - self.account_key = account_key - self.issuer = issuer - - def sign_request(self, request, httpclient): - request.headers.append( - ('Authorization', self._get_authorization(request, httpclient))) - - def _get_authorization(self, request, httpclient): - ''' return the signed string with token. ''' - return 'WRAP access_token="' + \ - self._get_token(request.host, request.path, httpclient) + '"' - - def _token_is_expired(self, token): - ''' Check if token expires or not. ''' - time_pos_begin = token.find('ExpiresOn=') + len('ExpiresOn=') - time_pos_end = token.find('&', time_pos_begin) - token_expire_time = int(token[time_pos_begin:time_pos_end]) - time_now = time.mktime(time.localtime()) - - # Adding 30 seconds so the token wouldn't be expired when we send the - # token to server. - return (token_expire_time - time_now) < 30 - - def _get_token(self, host, path, httpclient): - ''' - Returns token for the request. - - host: the service bus service request. - path: the service bus service request. - ''' - wrap_scope = 'http://' + host + path + self.issuer + self.account_key - - # Check whether has unexpired cache, return cached token if it is still - # usable. - if wrap_scope in _tokens: - token = _tokens[wrap_scope] - if not self._token_is_expired(token): - return token - - # get token from accessconstrol server - request = HTTPRequest() - request.protocol_override = 'https' - request.host = host.replace('.servicebus.', '-sb.accesscontrol.') - request.method = 'POST' - request.path = '/WRAPv0.9' - request.body = ('wrap_name=' + url_quote(self.issuer) + - '&wrap_password=' + url_quote(self.account_key) + - '&wrap_scope=' + - url_quote('http://' + host + path)).encode('utf-8') - request.headers.append(('Content-Length', str(len(request.body)))) - resp = httpclient.perform_request(request) - - token = resp.body.decode('utf-8') - token = url_unquote(token[token.find('=') + 1:token.rfind('&')]) - _tokens[wrap_scope] = token - - return token - - -class ServiceBusSASAuthentication: - def __init__(self, key_name, key_value): - self.key_name = key_name - self.key_value = key_value - - def sign_request(self, request, httpclient): - request.headers.append( - ('Authorization', self._get_authorization(request, httpclient))) - - def _get_authorization(self, request, httpclient): - uri = httpclient.get_uri(request) - uri = url_quote(uri, '').lower() - expiry = str(self._get_expiry()) - - to_sign = uri + '\n' + expiry - signature = url_quote(_sign_string(self.key_value, to_sign, False), '') - - auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}' - auth = auth_format.format(signature, expiry, self.key_name, uri) - - return auth - - def _get_expiry(self): - '''Returns the UTC datetime, in seconds since Epoch, when this signed - request expires (5 minutes from now).''' - return int(round(time.time() + 300)) diff --git a/awx/lib/site-packages/azure/servicemanagement/__init__.py b/awx/lib/site-packages/azure/servicemanagement/__init__.py deleted file mode 100644 index b452a828bf..0000000000 --- a/awx/lib/site-packages/azure/servicemanagement/__init__.py +++ /dev/null @@ -1,3004 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from xml.dom import minidom -from azure import ( - WindowsAzureData, - _Base64String, - _create_entry, - _dict_of, - _encode_base64, - _general_error_handler, - _get_children_from_path, - _get_first_child_node_value, - _list_of, - _scalar_list_of, - _str, - _xml_attribute, - _get_entry_properties_from_node, - _get_child_nodes, - _get_serialization_name, - ) - -#----------------------------------------------------------------------------- -# Constants for Azure app environment settings. -AZURE_MANAGEMENT_CERTFILE = 'AZURE_MANAGEMENT_CERTFILE' -AZURE_MANAGEMENT_SUBSCRIPTIONID = 'AZURE_MANAGEMENT_SUBSCRIPTIONID' - -# x-ms-version for service management. -X_MS_VERSION = '2014-06-01' - -#----------------------------------------------------------------------------- -# Data classes - - -class StorageServices(WindowsAzureData): - - def __init__(self): - self.storage_services = _list_of(StorageService) - - def __iter__(self): - return iter(self.storage_services) - - def __len__(self): - return len(self.storage_services) - - def __getitem__(self, index): - return self.storage_services[index] - - -class StorageService(WindowsAzureData): - - def __init__(self): - self.url = '' - self.service_name = '' - self.storage_service_properties = StorageAccountProperties() - self.storage_service_keys = StorageServiceKeys() - self.extended_properties = _dict_of( - 'ExtendedProperty', 'Name', 'Value') - self.capabilities = _scalar_list_of(str, 'Capability') - - -class StorageAccountProperties(WindowsAzureData): - - def __init__(self): - self.description = u'' - self.affinity_group = u'' - self.location = u'' - self.label = _Base64String() - self.status = u'' - self.endpoints = _scalar_list_of(str, 'Endpoint') - self.geo_replication_enabled = False - self.geo_primary_region = u'' - self.status_of_primary = u'' - self.geo_secondary_region = u'' - self.status_of_secondary = u'' - self.last_geo_failover_time = u'' - self.creation_time = u'' - self.account_type = u'' - - -class StorageServiceKeys(WindowsAzureData): - - def __init__(self): - self.primary = u'' - self.secondary = u'' - - -class Locations(WindowsAzureData): - - def __init__(self): - self.locations = _list_of(Location) - - def __iter__(self): - return iter(self.locations) - - def __len__(self): - return len(self.locations) - - def __getitem__(self, index): - return self.locations[index] - - -class Location(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.display_name = u'' - self.available_services = _scalar_list_of(str, 'AvailableService') - self.compute_capabilities = ComputeCapabilities() - - -class ComputeCapabilities(WindowsAzureData): - - def __init__(self): - self.web_worker_role_sizes = _scalar_list_of(str, 'RoleSize') - self.virtual_machines_role_sizes = _scalar_list_of(str, 'RoleSize') - - -class AffinityGroup(WindowsAzureData): - - def __init__(self): - self.name = '' - self.label = _Base64String() - self.description = u'' - self.location = u'' - self.hosted_services = HostedServices() - self.storage_services = StorageServices() - self.capabilities = _scalar_list_of(str, 'Capability') - - -class AffinityGroups(WindowsAzureData): - - def __init__(self): - self.affinity_groups = _list_of(AffinityGroup) - - def __iter__(self): - return iter(self.affinity_groups) - - def __len__(self): - return len(self.affinity_groups) - - def __getitem__(self, index): - return self.affinity_groups[index] - - -class HostedServices(WindowsAzureData): - - def __init__(self): - self.hosted_services = _list_of(HostedService) - - def __iter__(self): - return iter(self.hosted_services) - - def __len__(self): - return len(self.hosted_services) - - def __getitem__(self, index): - return self.hosted_services[index] - - -class HostedService(WindowsAzureData): - - def __init__(self): - self.url = u'' - self.service_name = u'' - self.hosted_service_properties = HostedServiceProperties() - self.deployments = Deployments() - - -class HostedServiceProperties(WindowsAzureData): - - def __init__(self): - self.description = u'' - self.location = u'' - self.affinity_group = u'' - self.label = _Base64String() - self.status = u'' - self.date_created = u'' - self.date_last_modified = u'' - self.extended_properties = _dict_of( - 'ExtendedProperty', 'Name', 'Value') - - -class VirtualNetworkSites(WindowsAzureData): - - def __init__(self): - self.virtual_network_sites = _list_of(VirtualNetworkSite) - - def __iter__(self): - return iter(self.virtual_network_sites) - - def __len__(self): - return len(self.virtual_network_sites) - - def __getitem__(self, index): - return self.virtual_network_sites[index] - - -class VirtualNetworkSite(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.id = u'' - self.affinity_group = u'' - self.subnets = Subnets() - - -class Subnets(WindowsAzureData): - - def __init__(self): - self.subnets = _list_of(Subnet) - - def __iter__(self): - return iter(self.subnets) - - def __len__(self): - return len(self.subnets) - - def __getitem__(self, index): - return self.subnets[index] - - -class Subnet(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.address_prefix = u'' - - - -class Deployments(WindowsAzureData): - - def __init__(self): - self.deployments = _list_of(Deployment) - - def __iter__(self): - return iter(self.deployments) - - def __len__(self): - return len(self.deployments) - - def __getitem__(self, index): - return self.deployments[index] - - -class Deployment(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.deployment_slot = u'' - self.private_id = u'' - self.status = u'' - self.label = _Base64String() - self.url = u'' - self.configuration = _Base64String() - self.role_instance_list = RoleInstanceList() - self.upgrade_status = UpgradeStatus() - self.upgrade_domain_count = u'' - self.role_list = RoleList() - self.sdk_version = u'' - self.input_endpoint_list = InputEndpoints() - self.locked = False - self.rollback_allowed = False - self.persistent_vm_downtime_info = PersistentVMDowntimeInfo() - self.created_time = u'' - self.virtual_network_name = u'' - self.last_modified_time = u'' - self.extended_properties = _dict_of( - 'ExtendedProperty', 'Name', 'Value') - - -class RoleInstanceList(WindowsAzureData): - - def __init__(self): - self.role_instances = _list_of(RoleInstance) - - def __iter__(self): - return iter(self.role_instances) - - def __len__(self): - return len(self.role_instances) - - def __getitem__(self, index): - return self.role_instances[index] - - -class RoleInstance(WindowsAzureData): - - def __init__(self): - self.role_name = u'' - self.instance_name = u'' - self.instance_status = u'' - self.instance_upgrade_domain = 0 - self.instance_fault_domain = 0 - self.instance_size = u'' - self.instance_state_details = u'' - self.instance_error_code = u'' - self.ip_address = u'' - self.instance_endpoints = InstanceEndpoints() - self.power_state = u'' - self.fqdn = u'' - self.host_name = u'' - self.public_ips = PublicIPs() - -class InstanceEndpoints(WindowsAzureData): - - def __init__(self): - self.instance_endpoints = _list_of(InstanceEndpoint) - - def __iter__(self): - return iter(self.instance_endpoints) - - def __len__(self): - return len(self.instance_endpoints) - - def __getitem__(self, index): - return self.instance_endpoints[index] - - -class InstanceEndpoint(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.vip = u'' - self.public_port = u'' - self.local_port = u'' - self.protocol = u'' - - -class UpgradeStatus(WindowsAzureData): - - def __init__(self): - self.upgrade_type = u'' - self.current_upgrade_domain_state = u'' - self.current_upgrade_domain = u'' - - -class InputEndpoints(WindowsAzureData): - - def __init__(self): - self.input_endpoints = _list_of(InputEndpoint) - - def __iter__(self): - return iter(self.input_endpoints) - - def __len__(self): - return len(self.input_endpoints) - - def __getitem__(self, index): - return self.input_endpoints[index] - - -class InputEndpoint(WindowsAzureData): - - def __init__(self): - self.role_name = u'' - self.vip = u'' - self.port = u'' - - -class RoleList(WindowsAzureData): - - def __init__(self): - self.roles = _list_of(Role) - - def __iter__(self): - return iter(self.roles) - - def __len__(self): - return len(self.roles) - - def __getitem__(self, index): - return self.roles[index] - - -class Role(WindowsAzureData): - - def __init__(self): - self.role_name = u'' - self.role_type = u'' - self.os_version = u'' - self.configuration_sets = ConfigurationSets() - self.availability_set_name = u'' - self.data_virtual_hard_disks = DataVirtualHardDisks() - self.os_virtual_hard_disk = OSVirtualHardDisk() - self.role_size = u'' - self.default_win_rm_certificate_thumbprint = u'' - - -class CaptureRoleAsVMImage: - - def __init__(self, os_state=None, vm_image_name=None, vm_image_label=None, - description=None, language=None, image_family=None, - recommended_vm_size=None): - self.os_state = os_state - self.vm_image_name = vm_image_name - self.vm_image_label = vm_image_label - self.description = description - self.language = language - self.image_family = image_family - self.recommended_vm_size = recommended_vm_size - - -class OSDiskConfiguration(WindowsAzureData): - - def __init__(self): - self.name = None - self.host_caching = None - self.os_state = None - self.os = None - self.media_link = None - self.logical_disk_size_in_gb = -1 - - -class DataDiskConfigurations(WindowsAzureData): - - def __init__(self): - self.data_disk_configurations = _list_of(DataDiskConfiguration) - - def __iter__(self): - return iter(self.data_disk_configurations) - - def __len__(self): - return len(self.data_disk_configurations) - - def __getitem__(self, index): - return self.data_disk_configurations[index] - - -class DataDiskConfiguration(WindowsAzureData): - - def __init__(self): - self.name = None - self.host_caching = None - self.lun = -1 - self.media_link = None - self.logical_disk_size_in_gb = -1 - - -class VMImages(WindowsAzureData): - - def __init__(self): - self.vm_images = _list_of(VMImage) - - def __iter__(self): - return iter(self.vm_images) - - def __len__(self): - return len(self.vm_images) - - def __getitem__(self, index): - return self.vm_images[index] - - -class VMImage(WindowsAzureData): - - def __init__(self, name=None, label=None, description=None): - self.name = name - self.label = label - self.category = None # read-only - self.description = description - self.os_disk_configuration = OSDiskConfiguration() - self.data_disk_configurations = DataDiskConfigurations() - self.service_name = None # read-only - self.deployment_name = None # read-only - self.role_name = None # read-only - self.location = None # read-only - self.affinity_group = None # read-only - self.created_time = None # read-only - self.modified_time = None # read-only - self.language = None - self.image_family = None - self.recommended_vm_size = None - self.is_premium = False # read-only - self.eula = None - self.icon_uri = None - self.small_icon_uri = None - self.privacy_uri = None - self.publisher_name = None # read-only - self.published_date = None - self.show_in_gui = False - self.pricing_detail_link = None # read-only - - -class ResourceExtensions(WindowsAzureData): - - def __init__(self): - self.resource_extensions = _list_of(ResourceExtension) - - def __iter__(self): - return iter(self.resource_extensions) - - def __len__(self): - return len(self.resource_extensions) - - def __getitem__(self, index): - return self.resource_extensions[index] - - -class ResourceExtension(WindowsAzureData): - - def __init__(self): - self.publisher = u'' - self.name = u'' - self.version = u'' - self.label = u'' - self.description = u'' - self.public_configuration_schema = u'' - self.private_configuration_schema = u'' - self.sample_config = u'' - self.replication_completed = False - self.eula = u'' - self.privacy_uri = u'' - self.homepage_uri = u'' - self.is_json_extension = False - self.is_internal_extension = False - self.disallow_major_version_upgrade = False - self.company_name = u'' - self.supported_os = u'' - self.published_date = u'' - - -class ResourceExtensionParameterValues(WindowsAzureData): - - def __init__(self): - self.resource_extension_parameter_values = _list_of(ResourceExtensionParameterValue) - - def __iter__(self): - return iter(self.resource_extension_parameter_values) - - def __len__(self): - return len(self.resource_extension_parameter_values) - - def __getitem__(self, index): - return self.resource_extension_parameter_values[index] - - -class ResourceExtensionParameterValue(WindowsAzureData): - - def __init__(self): - self.key = u'' - self.value = u'' - self.type = u'' - - -class ResourceExtensionReferences(WindowsAzureData): - - def __init__(self): - self.resource_extension_references = _list_of(ResourceExtensionReference) - - def __iter__(self): - return iter(self.resource_extension_references) - - def __len__(self): - return len(self.resource_extension_references) - - def __getitem__(self, index): - return self.resource_extension_references[index] - - -class ResourceExtensionReference(WindowsAzureData): - - def __init__(self, reference_name=u'', publisher=u'', name=u'', version=u''): - self.reference_name = reference_name - self.publisher = publisher - self.name = name - self.version = version - self.resource_extension_parameter_values = ResourceExtensionParameterValues() - self.state = u'' - self.certificates = Certificates() - - -class AdditionalUnattendContent(WindowsAzureData): - - def __init__(self): - self.passes = Passes() - - -class Passes(WindowsAzureData): - - def __init__(self): - self.passes = _list_of(UnattendPass) - - def __iter__(self): - return iter(self.passes) - - def __len__(self): - return len(self.passes) - - def __getitem__(self, index): - return self.passes[index] - - -class UnattendPass(WindowsAzureData): - - def __init__(self): - self.pass_name = u'' - self.components = Components() - - -class Components(WindowsAzureData): - - def __init__(self): - self.components = _list_of(UnattendComponent) - - def __iter__(self): - return iter(self.components) - - def __len__(self): - return len(self.components) - - def __getitem__(self, index): - return self.components[index] - - -class UnattendComponent(WindowsAzureData): - - def __init__(self): - self.component_name = u'' - self.component_settings = ComponentSettings() - - -class ComponentSettings(WindowsAzureData): - - def __init__(self): - self.component_settings = _list_of(ComponentSetting) - - def __iter__(self): - return iter(self.component_settings) - - def __len__(self): - return len(self.component_settings) - - def __getitem__(self, index): - return self.component_settings[index] - - -class ComponentSetting(WindowsAzureData): - - def __init__(self): - self.setting_name = u'' - self.content = u'' - - -class DnsServer(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.address = u'' - - -class ReservedIPs(WindowsAzureData): - - def __init__(self): - self.reserved_ips = _list_of(ReservedIP) - - def __iter__(self): - return iter(self.reserved_ips) - - def __len__(self): - return len(self.reserved_ips) - - def __getitem__(self, index): - return self.reserved_ips[index] - - -class ReservedIP(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.address = u'' - self.id = u'' - self.label = u'' - self.state = u'' - self.in_use = False - self.service_name = u'' - self.deployment_name = u'' - self.location = u'' - - -class PersistentVMDowntimeInfo(WindowsAzureData): - - def __init__(self): - self.start_time = u'' - self.end_time = u'' - self.status = u'' - - -class Certificates(WindowsAzureData): - - def __init__(self): - self.certificates = _list_of(Certificate) - - def __iter__(self): - return iter(self.certificates) - - def __len__(self): - return len(self.certificates) - - def __getitem__(self, index): - return self.certificates[index] - - -class Certificate(WindowsAzureData): - - def __init__(self): - self.certificate_url = u'' - self.thumbprint = u'' - self.thumbprint_algorithm = u'' - self.data = u'' - - -class OperationError(WindowsAzureData): - - def __init__(self): - self.code = u'' - self.message = u'' - - -class Operation(WindowsAzureData): - - def __init__(self): - self.id = u'' - self.status = u'' - self.http_status_code = u'' - self.error = OperationError() - - -class OperatingSystem(WindowsAzureData): - - def __init__(self): - self.version = u'' - self.label = _Base64String() - self.is_default = True - self.is_active = True - self.family = 0 - self.family_label = _Base64String() - - -class OperatingSystems(WindowsAzureData): - - def __init__(self): - self.operating_systems = _list_of(OperatingSystem) - - def __iter__(self): - return iter(self.operating_systems) - - def __len__(self): - return len(self.operating_systems) - - def __getitem__(self, index): - return self.operating_systems[index] - - -class OperatingSystemFamily(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.label = _Base64String() - self.operating_systems = OperatingSystems() - - -class OperatingSystemFamilies(WindowsAzureData): - - def __init__(self): - self.operating_system_families = _list_of(OperatingSystemFamily) - - def __iter__(self): - return iter(self.operating_system_families) - - def __len__(self): - return len(self.operating_system_families) - - def __getitem__(self, index): - return self.operating_system_families[index] - - -class Subscriptions(WindowsAzureData): - - def __init__(self): - self.subscriptions = _list_of(Subscription) - - def __iter__(self): - return iter(self.subscriptions) - - def __len__(self): - return len(self.subscriptions) - - def __getitem__(self, index): - return self.subscriptions[index] - - -class Subscription(WindowsAzureData): - - def __init__(self): - self.subscription_id = u'' - self.subscription_name = u'' - self.subscription_status = u'' - self.account_admin_live_email_id = u'' - self.service_admin_live_email_id = u'' - self.max_core_count = 0 - self.max_storage_accounts = 0 - self.max_hosted_services = 0 - self.current_core_count = 0 - self.current_hosted_services = 0 - self.current_storage_accounts = 0 - self.max_virtual_network_sites = 0 - self.current_virtual_network_sites = 0 - self.max_local_network_sites = 0 - self.max_dns_servers = 0 - self.aad_tenant_id = u'' - self.created_time = u'' - - -class AvailabilityResponse(WindowsAzureData): - - def __init__(self): - self.result = False - self.reason = False - - -class SubscriptionCertificates(WindowsAzureData): - - def __init__(self): - self.subscription_certificates = _list_of(SubscriptionCertificate) - - def __iter__(self): - return iter(self.subscription_certificates) - - def __len__(self): - return len(self.subscription_certificates) - - def __getitem__(self, index): - return self.subscription_certificates[index] - - -class SubscriptionCertificate(WindowsAzureData): - - def __init__(self): - self.subscription_certificate_public_key = u'' - self.subscription_certificate_thumbprint = u'' - self.subscription_certificate_data = u'' - self.created = u'' - - -class RoleSizes(WindowsAzureData): - - def __init__(self): - self.role_sizes = _list_of(RoleSize) - - def __iter__(self): - return iter(self.role_sizes) - - def __len__(self): - return len(self.role_sizes) - - def __getitem__(self, index): - return self.role_sizes[index] - - -class RoleSize(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.label = u'' - self.cores = 0 - self.memory_in_mb = 0 - self.supported_by_web_worker_roles = False - self.supported_by_virtual_machines = False - self.max_data_disk_count = 0 - self.web_worker_resource_disk_size_in_mb = 0 - self.virtual_machine_resource_disk_size_in_mb = 0 - - -class Images(WindowsAzureData): - - def __init__(self): - self.images = _list_of(OSImage) - - def __iter__(self): - return iter(self.images) - - def __len__(self): - return len(self.images) - - def __getitem__(self, index): - return self.images[index] - - -class OSImage(WindowsAzureData): - - def __init__(self): - self.affinity_group = u'' - self.category = u'' - self.location = u'' - self.logical_size_in_gb = 0 - self.label = u'' - self.media_link = u'' - self.name = u'' - self.os = u'' - self.eula = u'' - self.description = u'' - self.image_family = u'' - self.show_in_gui = True - self.published_date = u'' - self.is_premium = True - self.icon_uri = u'' - self.privacy_uri = u'' - self.recommended_vm_size = u'' - self.publisher_name = u'' - self.pricing_detail_link = u'' - self.small_icon_uri = u'' - self.os_state = u'' - self.language = u'' - - -class Disks(WindowsAzureData): - - def __init__(self): - self.disks = _list_of(Disk) - - def __iter__(self): - return iter(self.disks) - - def __len__(self): - return len(self.disks) - - def __getitem__(self, index): - return self.disks[index] - - -class Disk(WindowsAzureData): - - def __init__(self): - self.affinity_group = u'' - self.attached_to = AttachedTo() - self.has_operating_system = u'' - self.is_corrupted = u'' - self.location = u'' - self.logical_disk_size_in_gb = 0 - self.label = u'' - self.media_link = u'' - self.name = u'' - self.os = u'' - self.source_image_name = u'' - - -class AttachedTo(WindowsAzureData): - - def __init__(self): - self.hosted_service_name = u'' - self.deployment_name = u'' - self.role_name = u'' - - -class PersistentVMRole(WindowsAzureData): - - def __init__(self): - self.role_name = u'' - self.role_type = u'' - self.os_version = u'' # undocumented - self.configuration_sets = ConfigurationSets() - self.availability_set_name = u'' - self.data_virtual_hard_disks = DataVirtualHardDisks() - self.os_virtual_hard_disk = OSVirtualHardDisk() - self.role_size = u'' - self.default_win_rm_certificate_thumbprint = u'' - - -class ConfigurationSets(WindowsAzureData): - - def __init__(self): - self.configuration_sets = _list_of(ConfigurationSet) - - def __iter__(self): - return iter(self.configuration_sets) - - def __len__(self): - return len(self.configuration_sets) - - def __getitem__(self, index): - return self.configuration_sets[index] - - -class PublicIPs(WindowsAzureData): - - def __init__(self): - self.public_ips = _list_of(PublicIP) - - def __iter__(self): - return iter(self.public_ips) - - def __len__(self): - return len(self.public_ips) - - def __getitem__(self, index): - return self.public_ips[index] - - -class PublicIP(WindowsAzureData): - - def __init__(self, name=u''): - self.name = name - self.idle_timeout_in_minutes = 4 - self.address = None - -class ConfigurationSet(WindowsAzureData): - - def __init__(self): - self.configuration_set_type = u'NetworkConfiguration' - self.role_type = u'' - self.input_endpoints = ConfigurationSetInputEndpoints() - self.subnet_names = _scalar_list_of(str, 'SubnetName') - self.public_ips = PublicIPs() - - -class ConfigurationSetInputEndpoints(WindowsAzureData): - - def __init__(self): - self.input_endpoints = _list_of( - ConfigurationSetInputEndpoint, 'InputEndpoint') - - def __iter__(self): - return iter(self.input_endpoints) - - def __len__(self): - return len(self.input_endpoints) - - def __getitem__(self, index): - return self.input_endpoints[index] - - -class ConfigurationSetInputEndpoint(WindowsAzureData): - - ''' - Initializes a network configuration input endpoint. - - name: Specifies the name for the external endpoint. - protocol: - Specifies the protocol to use to inspect the virtual machine - availability status. Possible values are: HTTP, TCP. - port: Specifies the external port to use for the endpoint. - local_port: - Specifies the internal port on which the virtual machine is listening - to serve the endpoint. - load_balanced_endpoint_set_name: - Specifies a name for a set of load-balanced endpoints. Specifying this - element for a given endpoint adds it to the set. If you are setting an - endpoint to use to connect to the virtual machine via the Remote - Desktop, do not set this property. - enable_direct_server_return: - Specifies whether direct server return load balancing is enabled. - ''' - - def __init__(self, name=u'', protocol=u'', port=u'', local_port=u'', - load_balanced_endpoint_set_name=u'', - enable_direct_server_return=False): - self.enable_direct_server_return = enable_direct_server_return - self.load_balanced_endpoint_set_name = load_balanced_endpoint_set_name - self.local_port = local_port - self.name = name - self.port = port - self.load_balancer_probe = LoadBalancerProbe() - self.protocol = protocol - - -class WindowsConfigurationSet(WindowsAzureData): - - def __init__(self, computer_name=None, admin_password=None, - reset_password_on_first_logon=None, - enable_automatic_updates=None, time_zone=None, - admin_username=None, custom_data=None): - self.configuration_set_type = u'WindowsProvisioningConfiguration' - self.computer_name = computer_name - self.admin_password = admin_password - self.admin_username = admin_username - self.reset_password_on_first_logon = reset_password_on_first_logon - self.enable_automatic_updates = enable_automatic_updates - self.time_zone = time_zone - self.domain_join = DomainJoin() - self.stored_certificate_settings = StoredCertificateSettings() - self.win_rm = WinRM() - self.custom_data = custom_data - self.additional_unattend_content = AdditionalUnattendContent() - - -class DomainJoin(WindowsAzureData): - - def __init__(self): - self.credentials = Credentials() - self.join_domain = u'' - self.machine_object_ou = u'' - - -class Credentials(WindowsAzureData): - - def __init__(self): - self.domain = u'' - self.username = u'' - self.password = u'' - - -class StoredCertificateSettings(WindowsAzureData): - - def __init__(self): - self.stored_certificate_settings = _list_of(CertificateSetting) - - def __iter__(self): - return iter(self.stored_certificate_settings) - - def __len__(self): - return len(self.stored_certificate_settings) - - def __getitem__(self, index): - return self.stored_certificate_settings[index] - - -class CertificateSetting(WindowsAzureData): - - ''' - Initializes a certificate setting. - - thumbprint: - Specifies the thumbprint of the certificate to be provisioned. The - thumbprint must specify an existing service certificate. - store_name: - Specifies the name of the certificate store from which retrieve - certificate. - store_location: - Specifies the target certificate store location on the virtual machine. - The only supported value is LocalMachine. - ''' - - def __init__(self, thumbprint=u'', store_name=u'', store_location=u''): - self.thumbprint = thumbprint - self.store_name = store_name - self.store_location = store_location - - -class WinRM(WindowsAzureData): - - ''' - Contains configuration settings for the Windows Remote Management service on - the Virtual Machine. - ''' - - def __init__(self): - self.listeners = Listeners() - - -class Listeners(WindowsAzureData): - - def __init__(self): - self.listeners = _list_of(Listener) - - def __iter__(self): - return iter(self.listeners) - - def __len__(self): - return len(self.listeners) - - def __getitem__(self, index): - return self.listeners[index] - - -class Listener(WindowsAzureData): - - ''' - Specifies the protocol and certificate information for the listener. - - protocol: - Specifies the protocol of listener. Possible values are: Http, Https. - The value is case sensitive. - certificate_thumbprint: - Optional. Specifies the certificate thumbprint for the secure - connection. If this value is not specified, a self-signed certificate is - generated and used for the Virtual Machine. - ''' - - def __init__(self, protocol=u'', certificate_thumbprint=u''): - self.protocol = protocol - self.certificate_thumbprint = certificate_thumbprint - - -class LinuxConfigurationSet(WindowsAzureData): - - def __init__(self, host_name=None, user_name=None, user_password=None, - disable_ssh_password_authentication=None, custom_data=None): - self.configuration_set_type = u'LinuxProvisioningConfiguration' - self.host_name = host_name - self.user_name = user_name - self.user_password = user_password - self.disable_ssh_password_authentication =\ - disable_ssh_password_authentication - self.ssh = SSH() - self.custom_data = custom_data - - -class SSH(WindowsAzureData): - - def __init__(self): - self.public_keys = PublicKeys() - self.key_pairs = KeyPairs() - - -class PublicKeys(WindowsAzureData): - - def __init__(self): - self.public_keys = _list_of(PublicKey) - - def __iter__(self): - return iter(self.public_keys) - - def __len__(self): - return len(self.public_keys) - - def __getitem__(self, index): - return self.public_keys[index] - - -class PublicKey(WindowsAzureData): - - def __init__(self, fingerprint=u'', path=u''): - self.fingerprint = fingerprint - self.path = path - - -class KeyPairs(WindowsAzureData): - - def __init__(self): - self.key_pairs = _list_of(KeyPair) - - def __iter__(self): - return iter(self.key_pairs) - - def __len__(self): - return len(self.key_pairs) - - def __getitem__(self, index): - return self.key_pairs[index] - - -class KeyPair(WindowsAzureData): - - def __init__(self, fingerprint=u'', path=u''): - self.fingerprint = fingerprint - self.path = path - - -class LoadBalancerProbe(WindowsAzureData): - - def __init__(self): - self.path = u'' - self.port = u'' - self.protocol = u'' - - -class DataVirtualHardDisks(WindowsAzureData): - - def __init__(self): - self.data_virtual_hard_disks = _list_of(DataVirtualHardDisk) - - def __iter__(self): - return iter(self.data_virtual_hard_disks) - - def __len__(self): - return len(self.data_virtual_hard_disks) - - def __getitem__(self, index): - return self.data_virtual_hard_disks[index] - - -class DataVirtualHardDisk(WindowsAzureData): - - def __init__(self): - self.host_caching = None - self.disk_label = u'' - self.disk_name = u'' - self.lun = 0 - self.logical_disk_size_in_gb = 0 - self.media_link = u'' - - -class OSVirtualHardDisk(WindowsAzureData): - - def __init__(self, source_image_name=None, media_link=None, - host_caching=None, disk_label=None, disk_name=None, - os=None, remote_source_image_link=None): - self.source_image_name = source_image_name - self.media_link = media_link - self.host_caching = host_caching - self.disk_label = disk_label - self.disk_name = disk_name - self.os = os - self.remote_source_image_link = remote_source_image_link - -class AsynchronousOperationResult(WindowsAzureData): - - def __init__(self, request_id=None): - self.request_id = request_id - - -class ServiceBusRegion(WindowsAzureData): - - def __init__(self): - self.code = u'' - self.fullname = u'' - - -class ServiceBusNamespace(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.region = u'' - self.default_key = u'' - self.status = u'' - self.created_at = u'' - self.acs_management_endpoint = u'' - self.servicebus_endpoint = u'' - self.connection_string = u'' - self.subscription_id = u'' - self.enabled = False - - -class MetricProperties(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.primary_aggregation = u'' - self.unit = u'' - self.display_name = u'' - - -class MetricValues(WindowsAzureData): - - def __init__(self): - self.timestamp = u'' - self.min = 0 - self.max = 0 - self.average = 0 - self.total = 0 - - -class MetricRollups(WindowsAzureData): - - def __init__(self): - self.time_grain = u'' - self.retention = u'' - - -class WebSpaces(WindowsAzureData): - - def __init__(self): - self.web_space = _list_of(WebSpace) - - def __iter__(self): - return iter(self.web_space) - - def __len__(self): - return len(self.web_space) - - def __getitem__(self, index): - return self.web_space[index] - - -class WebSpace(WindowsAzureData): - - def __init__(self): - self.availability_state = u'' - self.geo_location = u'' - self.geo_region = u'' - self.name = u'' - self.plan = u'' - self.status = u'' - self.subscription = u'' - - -class Sites(WindowsAzureData): - - def __init__(self): - self.site = _list_of(Site) - - def __iter__(self): - return iter(self.site) - - def __len__(self): - return len(self.site) - - def __getitem__(self, index): - return self.site[index] - - -class Site(WindowsAzureData): - - def __init__(self): - self.admin_enabled = False - self.availability_state = '' - self.compute_mode = '' - self.enabled = False - self.enabled_host_names = _scalar_list_of(str, 'a:string') - self.host_name_ssl_states = HostNameSslStates() - self.host_names = _scalar_list_of(str, 'a:string') - self.last_modified_time_utc = '' - self.name = '' - self.repository_site_name = '' - self.self_link = '' - self.server_farm = '' - self.site_mode = '' - self.state = '' - self.storage_recovery_default_state = '' - self.usage_state = '' - self.web_space = '' - - -class HostNameSslStates(WindowsAzureData): - - def __init__(self): - self.host_name_ssl_state = _list_of(HostNameSslState) - - def __iter__(self): - return iter(self.host_name_ssl_state) - - def __len__(self): - return len(self.host_name_ssl_state) - - def __getitem__(self, index): - return self.host_name_ssl_state[index] - - -class HostNameSslState(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.ssl_state = u'' - - -class PublishData(WindowsAzureData): - _xml_name = 'publishData' - - def __init__(self): - self.publish_profiles = _list_of(PublishProfile, 'publishProfile') - -class PublishProfile(WindowsAzureData): - - def __init__(self): - self.profile_name = _xml_attribute('profileName') - self.publish_method = _xml_attribute('publishMethod') - self.publish_url = _xml_attribute('publishUrl') - self.msdeploysite = _xml_attribute('msdeploySite') - self.user_name = _xml_attribute('userName') - self.user_pwd = _xml_attribute('userPWD') - self.destination_app_url = _xml_attribute('destinationAppUrl') - self.sql_server_db_connection_string = _xml_attribute('SQLServerDBConnectionString') - self.my_sqldb_connection_string = _xml_attribute('mySQLDBConnectionString') - self.hosting_provider_forum_link = _xml_attribute('hostingProviderForumLink') - self.control_panel_link = _xml_attribute('controlPanelLink') - -class QueueDescription(WindowsAzureData): - - def __init__(self): - self.lock_duration = u'' - self.max_size_in_megabytes = 0 - self.requires_duplicate_detection = False - self.requires_session = False - self.default_message_time_to_live = u'' - self.dead_lettering_on_message_expiration = False - self.duplicate_detection_history_time_window = u'' - self.max_delivery_count = 0 - self.enable_batched_operations = False - self.size_in_bytes = 0 - self.message_count = 0 - self.is_anonymous_accessible = False - self.authorization_rules = AuthorizationRules() - self.status = u'' - self.created_at = u'' - self.updated_at = u'' - self.accessed_at = u'' - self.support_ordering = False - self.auto_delete_on_idle = u'' - self.count_details = CountDetails() - self.entity_availability_status = u'' - -class TopicDescription(WindowsAzureData): - - def __init__(self): - self.default_message_time_to_live = u'' - self.max_size_in_megabytes = 0 - self.requires_duplicate_detection = False - self.duplicate_detection_history_time_window = u'' - self.enable_batched_operations = False - self.size_in_bytes = 0 - self.filtering_messages_before_publishing = False - self.is_anonymous_accessible = False - self.authorization_rules = AuthorizationRules() - self.status = u'' - self.created_at = u'' - self.updated_at = u'' - self.accessed_at = u'' - self.support_ordering = False - self.count_details = CountDetails() - self.subscription_count = 0 - -class CountDetails(WindowsAzureData): - - def __init__(self): - self.active_message_count = 0 - self.dead_letter_message_count = 0 - self.scheduled_message_count = 0 - self.transfer_message_count = 0 - self.transfer_dead_letter_message_count = 0 - -class NotificationHubDescription(WindowsAzureData): - - def __init__(self): - self.registration_ttl = u'' - self.authorization_rules = AuthorizationRules() - -class AuthorizationRules(WindowsAzureData): - - def __init__(self): - self.authorization_rule = _list_of(AuthorizationRule) - - def __iter__(self): - return iter(self.authorization_rule) - - def __len__(self): - return len(self.authorization_rule) - - def __getitem__(self, index): - return self.authorization_rule[index] - -class AuthorizationRule(WindowsAzureData): - - def __init__(self): - self.claim_type = u'' - self.claim_value = u'' - self.rights = _scalar_list_of(str, 'AccessRights') - self.created_time = u'' - self.modified_time = u'' - self.key_name = u'' - self.primary_key = u'' - self.secondary_keu = u'' - -class RelayDescription(WindowsAzureData): - - def __init__(self): - self.path = u'' - self.listener_type = u'' - self.listener_count = 0 - self.created_at = u'' - self.updated_at = u'' - - -class MetricResponses(WindowsAzureData): - - def __init__(self): - self.metric_response = _list_of(MetricResponse) - - def __iter__(self): - return iter(self.metric_response) - - def __len__(self): - return len(self.metric_response) - - def __getitem__(self, index): - return self.metric_response[index] - - -class MetricResponse(WindowsAzureData): - - def __init__(self): - self.code = u'' - self.data = Data() - self.message = u'' - - -class Data(WindowsAzureData): - - def __init__(self): - self.display_name = u'' - self.end_time = u'' - self.name = u'' - self.primary_aggregation_type = u'' - self.start_time = u'' - self.time_grain = u'' - self.unit = u'' - self.values = Values() - - -class Values(WindowsAzureData): - - def __init__(self): - self.metric_sample = _list_of(MetricSample) - - def __iter__(self): - return iter(self.metric_sample) - - def __len__(self): - return len(self.metric_sample) - - def __getitem__(self, index): - return self.metric_sample[index] - - -class MetricSample(WindowsAzureData): - - def __init__(self): - self.count = 0 - self.time_created = u'' - self.total = 0 - - -class MetricDefinitions(WindowsAzureData): - - def __init__(self): - self.metric_definition = _list_of(MetricDefinition) - - def __iter__(self): - return iter(self.metric_definition) - - def __len__(self): - return len(self.metric_definition) - - def __getitem__(self, index): - return self.metric_definition[index] - - -class MetricDefinition(WindowsAzureData): - - def __init__(self): - self.display_name = u'' - self.metric_availabilities = MetricAvailabilities() - self.name = u'' - self.primary_aggregation_type = u'' - self.unit = u'' - - -class MetricAvailabilities(WindowsAzureData): - - def __init__(self): - self.metric_availability = _list_of(MetricAvailability, 'MetricAvailabilily') - - def __iter__(self): - return iter(self.metric_availability) - - def __len__(self): - return len(self.metric_availability) - - def __getitem__(self, index): - return self.metric_availability[index] - - -class MetricAvailability(WindowsAzureData): - - def __init__(self): - self.retention = u'' - self.time_grain = u'' - - -class Servers(WindowsAzureData): - - def __init__(self): - self.server = _list_of(Server) - - def __iter__(self): - return iter(self.server) - - def __len__(self): - return len(self.server) - - def __getitem__(self, index): - return self.server[index] - - -class Server(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.administrator_login = u'' - self.location = u'' - self.geo_paired_region = u'' - self.fully_qualified_domain_name = u'' - self.version = u'' - - -class ServerQuota(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.type = u'' - self.state = u'' - self.self_link = u'' - self.parent_link = u'' - self.value = 0 - - -class EventLog(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.type = u'' - self.state = u'' - self.self_link = u'' - self.parent_link = u'' - self.database_name = u'' - self.name = u'' - self.start_time_utc = u'' - self.interval_size_in_minutes = 0 - self.event_category = u'' - self.event_type = u'' - self.event_subtype = 0 - self.event_subtype_description = u'' - self.number_of_events = 0 - self.severity = 0 - self.description = u'' - self.additional_data = u'' - - -class CreateServerResponse(WindowsAzureData): - - def __init__(self): - self.server_name = u'' - - -class Database(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.type = u'' - self.state = u'' - self.self_link = u'' - self.parent_link = u'' - self.id = 0 - self.edition = u'' - self.collation_name = u'' - self.creation_date = u'' - self.is_federation_root = False - self.is_system_object = False - self.max_size_bytes = 0 - - -class FirewallRule(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.type = u'' - self.state = u'' - self.self_link = u'' - self.parent_link = u'' - self.start_ip_address = u'' - self.end_ip_address = u'' - - -class ServiceObjective(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.type = u'' - self.state = u'' - self.self_link = u'' - self.parent_link = u'' - self.id = u'' - self.is_default = False - self.is_system = False - self.description = u'' - self.enabled = False - - -class CloudServices(WindowsAzureData): - - def __init__(self): - self.cloud_service = _list_of(CloudService) - - def __iter__(self): - return iter(self.cloud_service) - - def __len__(self): - return len(self.cloud_service) - - def __getitem__(self, index): - return self.cloud_service[index] - - -class CloudService(WindowsAzureData): - - def __init__(self): - self.name = u'' - self.label = u'' - self.description = u'' - self.geo_region = u'' - self.resources = Resources() - - -class Resources(WindowsAzureData): - - def __init__(self): - self.resource = _list_of(Resource) - - def __iter__(self): - return iter(self.resource) - - def __len__(self): - return len(self.resource) - - def __getitem__(self, index): - return self.resource[index] - - -class Resource(WindowsAzureData): - - def __init__(self): - self.resource_provider_namespace = u'' - self.type = u'' - self.name = u'' - self.schema_version = u'' - self.e_tag = u'' - self.state = u'' - self.intrinsic_settings = IntrinsicSettings() - self.operation_status = OperationStatus() - - -class IntrinsicSettings(WindowsAzureData): - - def __init__(self): - self.plan = u'' - self.quota = Quota() - - -class Quota(WindowsAzureData): - - def __init__(self): - self.max_job_count = 0 - self.max_recurrence = MaxRecurrence() - - -class MaxRecurrence(WindowsAzureData): - - def __init__(self): - self.frequency = u'' - self.interval = 0 - - -class OperationStatus(WindowsAzureData): - - def __init__(self): - self.type = u'' - self.result = u'' - - -def parse_response_for_async_op(response): - ''' Extracts request id from response header. ''' - - if response is None: - return None - - result = AsynchronousOperationResult() - if response.headers: - for name, value in response.headers: - if name.lower() == 'x-ms-request-id': - result.request_id = value - - return result - - -def _management_error_handler(http_error): - ''' Simple error handler for management service. ''' - return _general_error_handler(http_error) - - -def _lower(text): - return text.lower() - - -def _data_to_xml(data): - '''Creates an xml fragment from the specified data. - data: Array of tuples, where first: xml element name - second: xml element text - third: conversion function - ''' - xml = '' - for element in data: - name = element[0] - val = element[1] - if len(element) > 2: - converter = element[2] - else: - converter = None - - if val is not None: - if converter is not None: - text = _str(converter(_str(val))) - else: - text = _str(val) - - xml += ''.join(['<', name, '>', text, '</', name, '>']) - return xml - - -class _XmlSerializer(object): - - @staticmethod - def create_storage_service_input_to_xml(service_name, description, label, - affinity_group, location, - account_type, - extended_properties): - xml = _XmlSerializer.data_to_xml( - [('ServiceName', service_name), - ('Description', description), - ('Label', label, _encode_base64), - ('AffinityGroup', affinity_group), - ('Location', location)]) - if extended_properties is not None: - xml += _XmlSerializer.extended_properties_dict_to_xml_fragment( - extended_properties) - xml += _XmlSerializer.data_to_xml([('AccountType', account_type)]) - return _XmlSerializer.doc_from_xml('CreateStorageServiceInput', xml) - - @staticmethod - def update_storage_service_input_to_xml(description, label, - account_type, - extended_properties): - xml = _XmlSerializer.data_to_xml( - [('Description', description), - ('Label', label, _encode_base64)]) - if extended_properties is not None: - xml += _XmlSerializer.extended_properties_dict_to_xml_fragment( - extended_properties) - xml += _XmlSerializer.data_to_xml([('AccountType', account_type)]) - return _XmlSerializer.doc_from_xml('UpdateStorageServiceInput', xml) - - @staticmethod - def regenerate_keys_to_xml(key_type): - return _XmlSerializer.doc_from_data('RegenerateKeys', - [('KeyType', key_type)]) - - @staticmethod - def update_hosted_service_to_xml(label, description, extended_properties): - return _XmlSerializer.doc_from_data('UpdateHostedService', - [('Label', label, _encode_base64), - ('Description', description)], - extended_properties) - - @staticmethod - def create_hosted_service_to_xml(service_name, label, description, - location, affinity_group, - extended_properties): - return _XmlSerializer.doc_from_data( - 'CreateHostedService', - [('ServiceName', service_name), - ('Label', label, _encode_base64), - ('Description', description), - ('Location', location), - ('AffinityGroup', affinity_group)], - extended_properties) - - @staticmethod - def create_deployment_to_xml(name, package_url, label, configuration, - start_deployment, treat_warnings_as_error, - extended_properties): - return _XmlSerializer.doc_from_data( - 'CreateDeployment', - [('Name', name), - ('PackageUrl', package_url), - ('Label', label, _encode_base64), - ('Configuration', configuration), - ('StartDeployment', - start_deployment, _lower), - ('TreatWarningsAsError', treat_warnings_as_error, _lower)], - extended_properties) - - @staticmethod - def swap_deployment_to_xml(production, source_deployment): - return _XmlSerializer.doc_from_data( - 'Swap', - [('Production', production), - ('SourceDeployment', source_deployment)]) - - @staticmethod - def update_deployment_status_to_xml(status): - return _XmlSerializer.doc_from_data( - 'UpdateDeploymentStatus', - [('Status', status)]) - - @staticmethod - def change_deployment_to_xml(configuration, treat_warnings_as_error, mode, - extended_properties): - return _XmlSerializer.doc_from_data( - 'ChangeConfiguration', - [('Configuration', configuration), - ('TreatWarningsAsError', treat_warnings_as_error, _lower), - ('Mode', mode)], - extended_properties) - - @staticmethod - def upgrade_deployment_to_xml(mode, package_url, configuration, label, - role_to_upgrade, force, extended_properties): - return _XmlSerializer.doc_from_data( - 'UpgradeDeployment', - [('Mode', mode), - ('PackageUrl', package_url), - ('Configuration', configuration), - ('Label', label, _encode_base64), - ('RoleToUpgrade', role_to_upgrade), - ('Force', force, _lower)], - extended_properties) - - @staticmethod - def rollback_upgrade_to_xml(mode, force): - return _XmlSerializer.doc_from_data( - 'RollbackUpdateOrUpgrade', - [('Mode', mode), - ('Force', force, _lower)]) - - @staticmethod - def walk_upgrade_domain_to_xml(upgrade_domain): - return _XmlSerializer.doc_from_data( - 'WalkUpgradeDomain', - [('UpgradeDomain', upgrade_domain)]) - - @staticmethod - def certificate_file_to_xml(data, certificate_format, password): - return _XmlSerializer.doc_from_data( - 'CertificateFile', - [('Data', data), - ('CertificateFormat', certificate_format), - ('Password', password)]) - - @staticmethod - def create_affinity_group_to_xml(name, label, description, location): - return _XmlSerializer.doc_from_data( - 'CreateAffinityGroup', - [('Name', name), - ('Label', label, _encode_base64), - ('Description', description), - ('Location', location)]) - - @staticmethod - def update_affinity_group_to_xml(label, description): - return _XmlSerializer.doc_from_data( - 'UpdateAffinityGroup', - [('Label', label, _encode_base64), - ('Description', description)]) - - @staticmethod - def subscription_certificate_to_xml(public_key, thumbprint, data): - return _XmlSerializer.doc_from_data( - 'SubscriptionCertificate', - [('SubscriptionCertificatePublicKey', public_key), - ('SubscriptionCertificateThumbprint', thumbprint), - ('SubscriptionCertificateData', data)]) - - @staticmethod - def os_image_to_xml(label, media_link, name, os): - return _XmlSerializer.doc_from_data( - 'OSImage', - [('Label', label), - ('MediaLink', media_link), - ('Name', name), - ('OS', os)]) - - @staticmethod - def data_virtual_hard_disk_to_xml(host_caching, disk_label, disk_name, lun, - logical_disk_size_in_gb, media_link, - source_media_link): - return _XmlSerializer.doc_from_data( - 'DataVirtualHardDisk', - [('HostCaching', host_caching), - ('DiskLabel', disk_label), - ('DiskName', disk_name), - ('Lun', lun), - ('LogicalDiskSizeInGB', logical_disk_size_in_gb), - ('MediaLink', media_link), - ('SourceMediaLink', source_media_link)]) - - @staticmethod - def disk_to_xml(has_operating_system, label, media_link, name, os): - return _XmlSerializer.doc_from_data( - 'Disk', - [('HasOperatingSystem', has_operating_system, _lower), - ('Label', label), - ('MediaLink', media_link), - ('Name', name), - ('OS', os)]) - - @staticmethod - def restart_role_operation_to_xml(): - return _XmlSerializer.doc_from_xml( - 'RestartRoleOperation', - '<OperationType>RestartRoleOperation</OperationType>') - - @staticmethod - def shutdown_role_operation_to_xml(post_shutdown_action): - xml = _XmlSerializer.data_to_xml( - [('OperationType', 'ShutdownRoleOperation'), - ('PostShutdownAction', post_shutdown_action)]) - return _XmlSerializer.doc_from_xml('ShutdownRoleOperation', xml) - - @staticmethod - def shutdown_roles_operation_to_xml(role_names, post_shutdown_action): - xml = _XmlSerializer.data_to_xml( - [('OperationType', 'ShutdownRolesOperation')]) - xml += '<Roles>' - for role_name in role_names: - xml += _XmlSerializer.data_to_xml([('Name', role_name)]) - xml += '</Roles>' - xml += _XmlSerializer.data_to_xml( - [('PostShutdownAction', post_shutdown_action)]) - return _XmlSerializer.doc_from_xml('ShutdownRolesOperation', xml) - - @staticmethod - def start_role_operation_to_xml(): - return _XmlSerializer.doc_from_xml( - 'StartRoleOperation', - '<OperationType>StartRoleOperation</OperationType>') - - @staticmethod - def start_roles_operation_to_xml(role_names): - xml = _XmlSerializer.data_to_xml( - [('OperationType', 'StartRolesOperation')]) - xml += '<Roles>' - for role_name in role_names: - xml += _XmlSerializer.data_to_xml([('Name', role_name)]) - xml += '</Roles>' - return _XmlSerializer.doc_from_xml('StartRolesOperation', xml) - - @staticmethod - def windows_configuration_to_xml(configuration): - xml = _XmlSerializer.data_to_xml( - [('ConfigurationSetType', configuration.configuration_set_type), - ('ComputerName', configuration.computer_name), - ('AdminPassword', configuration.admin_password), - ('ResetPasswordOnFirstLogon', - configuration.reset_password_on_first_logon, - _lower), - ('EnableAutomaticUpdates', - configuration.enable_automatic_updates, - _lower), - ('TimeZone', configuration.time_zone)]) - - if configuration.domain_join is not None: - xml += '<DomainJoin>' - xml += '<Credentials>' - xml += _XmlSerializer.data_to_xml( - [('Domain', configuration.domain_join.credentials.domain), - ('Username', configuration.domain_join.credentials.username), - ('Password', configuration.domain_join.credentials.password)]) - xml += '</Credentials>' - xml += _XmlSerializer.data_to_xml( - [('JoinDomain', configuration.domain_join.join_domain), - ('MachineObjectOU', - configuration.domain_join.machine_object_ou)]) - xml += '</DomainJoin>' - if configuration.stored_certificate_settings is not None: - xml += '<StoredCertificateSettings>' - for cert in configuration.stored_certificate_settings: - xml += '<CertificateSetting>' - xml += _XmlSerializer.data_to_xml( - [('StoreLocation', cert.store_location), - ('StoreName', cert.store_name), - ('Thumbprint', cert.thumbprint)]) - xml += '</CertificateSetting>' - xml += '</StoredCertificateSettings>' - if configuration.win_rm is not None: - xml += '<WinRM><Listeners>' - for listener in configuration.win_rm.listeners: - xml += '<Listener>' - xml += _XmlSerializer.data_to_xml( - [('Protocol', listener.protocol), - ('CertificateThumbprint', listener.certificate_thumbprint)]) - xml += '</Listener>' - xml += '</Listeners></WinRM>' - xml += _XmlSerializer.data_to_xml( - [('AdminUsername', configuration.admin_username), - ('CustomData', configuration.custom_data, _encode_base64)]) - if configuration.additional_unattend_content and configuration.additional_unattend_content.passes: - xml += '<AdditionalUnattendContent><Passes>' - for unattend_pass in configuration.additional_unattend_content.passes: - xml += _XmlSerializer.data_to_xml( - [('PassName', unattend_pass.pass_name)]) - if unattend_pass.components: - xml += '<Components>' - for comp in unattend_pass.components: - xml += '<UnattendComponent>' - xml += _XmlSerializer.data_to_xml( - [('ComponentName', comp.component_name)]) - if comp.component_settings: - xml += '<ComponentSettings>' - for setting in comp.component_settings: - xml += '<ComponentSetting>' - xml += _XmlSerializer.data_to_xml( - [('SettingName', setting.setting_name), - ('Content', setting.content)]) - xml += '</ComponentSetting>' - xml += '</ComponentSettings>' - xml += '</UnattendComponent>' - xml += '</Components>' - xml += '</Passes></AdditionalUnattendContent>' - - return xml - - @staticmethod - def linux_configuration_to_xml(configuration): - xml = _XmlSerializer.data_to_xml( - [('ConfigurationSetType', configuration.configuration_set_type), - ('HostName', configuration.host_name), - ('UserName', configuration.user_name), - ('UserPassword', configuration.user_password), - ('DisableSshPasswordAuthentication', - configuration.disable_ssh_password_authentication, - _lower)]) - - if configuration.ssh is not None: - xml += '<SSH>' - xml += '<PublicKeys>' - for key in configuration.ssh.public_keys: - xml += '<PublicKey>' - xml += _XmlSerializer.data_to_xml( - [('Fingerprint', key.fingerprint), - ('Path', key.path)]) - xml += '</PublicKey>' - xml += '</PublicKeys>' - xml += '<KeyPairs>' - for key in configuration.ssh.key_pairs: - xml += '<KeyPair>' - xml += _XmlSerializer.data_to_xml( - [('Fingerprint', key.fingerprint), - ('Path', key.path)]) - xml += '</KeyPair>' - xml += '</KeyPairs>' - xml += '</SSH>' - - xml += _XmlSerializer.data_to_xml( - [('CustomData', configuration.custom_data, _encode_base64)]) - - return xml - - @staticmethod - def network_configuration_to_xml(configuration): - xml = _XmlSerializer.data_to_xml( - [('ConfigurationSetType', configuration.configuration_set_type)]) - xml += '<InputEndpoints>' - for endpoint in configuration.input_endpoints: - xml += '<InputEndpoint>' - xml += _XmlSerializer.data_to_xml( - [('LoadBalancedEndpointSetName', - endpoint.load_balanced_endpoint_set_name), - ('LocalPort', endpoint.local_port), - ('Name', endpoint.name), - ('Port', endpoint.port)]) - - if endpoint.load_balancer_probe.path or\ - endpoint.load_balancer_probe.port or\ - endpoint.load_balancer_probe.protocol: - xml += '<LoadBalancerProbe>' - xml += _XmlSerializer.data_to_xml( - [('Path', endpoint.load_balancer_probe.path), - ('Port', endpoint.load_balancer_probe.port), - ('Protocol', endpoint.load_balancer_probe.protocol)]) - xml += '</LoadBalancerProbe>' - - xml += _XmlSerializer.data_to_xml( - [('Protocol', endpoint.protocol), - ('EnableDirectServerReturn', - endpoint.enable_direct_server_return, - _lower)]) - - xml += '</InputEndpoint>' - xml += '</InputEndpoints>' - xml += '<SubnetNames>' - for name in configuration.subnet_names: - xml += _XmlSerializer.data_to_xml([('SubnetName', name)]) - xml += '</SubnetNames>' - - if configuration.public_ips: - xml += '<PublicIPs>' - for public_ip in configuration.public_ips: - xml += '<PublicIP>' - xml += _XmlSerializer.data_to_xml( - [('Name', public_ip.name), - ('IdleTimeoutInMinutes', public_ip.idle_timeout_in_minutes)]) - xml += '</PublicIP>' - xml += '</PublicIPs>' - - return xml - - @staticmethod - def role_to_xml(availability_set_name, data_virtual_hard_disks, - network_configuration_set, os_virtual_hard_disk, role_name, - role_size, role_type, system_configuration_set, - resource_extension_references, - provision_guest_agent, vm_image_name, media_location): - xml = _XmlSerializer.data_to_xml([('RoleName', role_name), - ('RoleType', role_type)]) - - if system_configuration_set or network_configuration_set: - xml += '<ConfigurationSets>' - - if system_configuration_set is not None: - xml += '<ConfigurationSet>' - if isinstance(system_configuration_set, WindowsConfigurationSet): - xml += _XmlSerializer.windows_configuration_to_xml( - system_configuration_set) - elif isinstance(system_configuration_set, LinuxConfigurationSet): - xml += _XmlSerializer.linux_configuration_to_xml( - system_configuration_set) - xml += '</ConfigurationSet>' - - if network_configuration_set is not None: - xml += '<ConfigurationSet>' - xml += _XmlSerializer.network_configuration_to_xml( - network_configuration_set) - xml += '</ConfigurationSet>' - - xml += '</ConfigurationSets>' - - if resource_extension_references: - xml += '<ResourceExtensionReferences>' - for ext in resource_extension_references: - xml += '<ResourceExtensionReference>' - xml += _XmlSerializer.data_to_xml( - [('ReferenceName', ext.reference_name), - ('Publisher', ext.publisher), - ('Name', ext.name), - ('Version', ext.version)]) - if ext.resource_extension_parameter_values: - xml += '<ResourceExtensionParameterValues>' - for val in ext.resource_extension_parameter_values: - xml += '<ResourceExtensionParameterValue>' - xml += _XmlSerializer.data_to_xml( - [('Key', val.key), - ('Value', val.value), - ('Type', val.type)]) - xml += '</ResourceExtensionParameterValue>' - xml += '</ResourceExtensionParameterValues>' - xml += '</ResourceExtensionReference>' - xml += '</ResourceExtensionReferences>' - - xml += _XmlSerializer.data_to_xml( - [('VMImageName', vm_image_name), - ('MediaLocation', media_location), - ('AvailabilitySetName', availability_set_name)]) - - if data_virtual_hard_disks is not None: - xml += '<DataVirtualHardDisks>' - for hd in data_virtual_hard_disks: - xml += '<DataVirtualHardDisk>' - xml += _XmlSerializer.data_to_xml( - [('HostCaching', hd.host_caching), - ('DiskLabel', hd.disk_label), - ('DiskName', hd.disk_name), - ('Lun', hd.lun), - ('LogicalDiskSizeInGB', hd.logical_disk_size_in_gb), - ('MediaLink', hd.media_link)]) - xml += '</DataVirtualHardDisk>' - xml += '</DataVirtualHardDisks>' - - if os_virtual_hard_disk is not None: - xml += '<OSVirtualHardDisk>' - xml += _XmlSerializer.data_to_xml( - [('HostCaching', os_virtual_hard_disk.host_caching), - ('DiskLabel', os_virtual_hard_disk.disk_label), - ('DiskName', os_virtual_hard_disk.disk_name), - ('MediaLink', os_virtual_hard_disk.media_link), - ('SourceImageName', os_virtual_hard_disk.source_image_name), - ('OS', os_virtual_hard_disk.os), - ('RemoteSourceImageLink', os_virtual_hard_disk.remote_source_image_link)]) - xml += '</OSVirtualHardDisk>' - - xml += _XmlSerializer.data_to_xml( - [('RoleSize', role_size), - ('ProvisionGuestAgent', provision_guest_agent, _lower)]) - - return xml - - @staticmethod - def add_role_to_xml(role_name, system_configuration_set, - os_virtual_hard_disk, role_type, - network_configuration_set, availability_set_name, - data_virtual_hard_disks, role_size, - resource_extension_references, provision_guest_agent, - vm_image_name, media_location): - xml = _XmlSerializer.role_to_xml( - availability_set_name, - data_virtual_hard_disks, - network_configuration_set, - os_virtual_hard_disk, - role_name, - role_size, - role_type, - system_configuration_set, - resource_extension_references, - provision_guest_agent, - vm_image_name, - media_location) - return _XmlSerializer.doc_from_xml('PersistentVMRole', xml) - - @staticmethod - def update_role_to_xml(role_name, os_virtual_hard_disk, role_type, - network_configuration_set, availability_set_name, - data_virtual_hard_disks, role_size, - resource_extension_references, - provision_guest_agent): - xml = _XmlSerializer.role_to_xml( - availability_set_name, - data_virtual_hard_disks, - network_configuration_set, - os_virtual_hard_disk, - role_name, - role_size, - role_type, - None, - resource_extension_references, - provision_guest_agent, - None, - None) - return _XmlSerializer.doc_from_xml('PersistentVMRole', xml) - - @staticmethod - def capture_role_to_xml(post_capture_action, target_image_name, - target_image_label, provisioning_configuration): - xml = _XmlSerializer.data_to_xml( - [('OperationType', 'CaptureRoleOperation'), - ('PostCaptureAction', post_capture_action)]) - - if provisioning_configuration is not None: - xml += '<ProvisioningConfiguration>' - if isinstance(provisioning_configuration, WindowsConfigurationSet): - xml += _XmlSerializer.windows_configuration_to_xml( - provisioning_configuration) - elif isinstance(provisioning_configuration, LinuxConfigurationSet): - xml += _XmlSerializer.linux_configuration_to_xml( - provisioning_configuration) - xml += '</ProvisioningConfiguration>' - - xml += _XmlSerializer.data_to_xml( - [('TargetImageLabel', target_image_label), - ('TargetImageName', target_image_name)]) - - return _XmlSerializer.doc_from_xml('CaptureRoleOperation', xml) - - @staticmethod - def virtual_machine_deployment_to_xml(deployment_name, deployment_slot, - label, role_name, - system_configuration_set, - os_virtual_hard_disk, role_type, - network_configuration_set, - availability_set_name, - data_virtual_hard_disks, role_size, - virtual_network_name, - resource_extension_references, - provision_guest_agent, - vm_image_name, - media_location, - dns_servers, - reserved_ip_name): - xml = _XmlSerializer.data_to_xml([('Name', deployment_name), - ('DeploymentSlot', deployment_slot), - ('Label', label)]) - xml += '<RoleList>' - xml += '<Role>' - xml += _XmlSerializer.role_to_xml( - availability_set_name, - data_virtual_hard_disks, - network_configuration_set, - os_virtual_hard_disk, - role_name, - role_size, - role_type, - system_configuration_set, - resource_extension_references, - provision_guest_agent, - vm_image_name, - media_location) - xml += '</Role>' - xml += '</RoleList>' - - xml += _XmlSerializer.data_to_xml( - [('VirtualNetworkName', virtual_network_name)]) - - if dns_servers: - xml += '<Dns><DnsServers>' - for dns_server in dns_servers: - xml += '<DnsServer>' - xml += _XmlSerializer.data_to_xml( - [('Name', dns_server.name), - ('Address', dns_server.address)]) - xml += '</DnsServer>' - xml += '</DnsServers></Dns>' - - xml += _XmlSerializer.data_to_xml( - [('ReservedIPName', reserved_ip_name)]) - - return _XmlSerializer.doc_from_xml('Deployment', xml) - - @staticmethod - def capture_vm_image_to_xml(options): - return _XmlSerializer.doc_from_data( - 'CaptureRoleAsVMImageOperation ', - [('OperationType', 'CaptureRoleAsVMImageOperation'), - ('OSState', options.os_state), - ('VMImageName', options.vm_image_name), - ('VMImageLabel', options.vm_image_label), - ('Description', options.description), - ('Language', options.language), - ('ImageFamily', options.image_family), - ('RecommendedVMSize', options.recommended_vm_size)]) - - @staticmethod - def create_vm_image_to_xml(image): - xml = _XmlSerializer.data_to_xml( - [('Name', image.name), - ('Label', image.label), - ('Description', image.description)]) - - os_disk = image.os_disk_configuration - xml += '<OSDiskConfiguration>' - xml += _XmlSerializer.data_to_xml( - [('HostCaching', os_disk.host_caching), - ('OSState', os_disk.os_state), - ('OS', os_disk.os), - ('MediaLink', os_disk.media_link)]) - xml += '</OSDiskConfiguration>' - - if image.data_disk_configurations: - xml += '<DataDiskConfigurations>' - for data_disk in image.data_disk_configurations: - xml += '<DataDiskConfiguration>' - xml += _XmlSerializer.data_to_xml( - [('HostCaching', data_disk.host_caching), - ('Lun', data_disk.lun), - ('MediaLink', data_disk.media_link), - ('LogicalDiskSizeInGB', data_disk.logical_disk_size_in_gb)]) - xml += '</DataDiskConfiguration>' - xml += '</DataDiskConfigurations>' - - xml += _XmlSerializer.data_to_xml( - [('Language', image.language), - ('ImageFamily', image.image_family), - ('RecommendedVMSize', image.recommended_vm_size), - ('Eula', image.eula), - ('IconUri', image.icon_uri), - ('SmallIconUri', image.small_icon_uri), - ('PrivacyUri', image.privacy_uri), - ('PublishedDate', image.published_date), - ('ShowInGui', image.show_in_gui, _lower)]) - - return _XmlSerializer.doc_from_xml('VMImage', xml) - - @staticmethod - def update_vm_image_to_xml(image): - xml = _XmlSerializer.data_to_xml( - [('Label', image.label), - ('Description', image.description)]) - - os_disk = image.os_disk_configuration - xml += '<OSDiskConfiguration>' - xml += _XmlSerializer.data_to_xml( - [('HostCaching', os_disk.host_caching)]) - xml += '</OSDiskConfiguration>' - - xml += '<DataDiskConfigurations>' - for data_disk in image.data_disk_configurations: - xml += '<DataDiskConfiguration>' - xml += _XmlSerializer.data_to_xml( - [('Name', data_disk.name), - ('HostCaching', data_disk.host_caching), - ('Lun', data_disk.lun)]) - xml += '</DataDiskConfiguration>' - xml += '</DataDiskConfigurations>' - - xml += _XmlSerializer.data_to_xml( - [('Language', image.language), - ('ImageFamily', image.image_family), - ('RecommendedVMSize', image.recommended_vm_size), - ('Eula', image.eula), - ('IconUri', image.icon_uri), - ('SmallIconUri', image.small_icon_uri), - ('PrivacyUri', image.privacy_uri), - ('PublishedDate', image.published_date), - ('ShowInGui', image.show_in_gui, _lower)]) - - return _XmlSerializer.doc_from_xml('VMImage', xml) - - @staticmethod - def create_website_to_xml(webspace_name, website_name, geo_region, plan, - host_names, compute_mode, server_farm, site_mode): - xml = '<HostNames xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">' - for host_name in host_names: - xml += '<a:string>{0}</a:string>'.format(host_name) - xml += '</HostNames>' - xml += _XmlSerializer.data_to_xml( - [('Name', website_name), - ('ComputeMode', compute_mode), - ('ServerFarm', server_farm), - ('SiteMode', site_mode)]) - xml += '<WebSpaceToCreate>' - xml += _XmlSerializer.data_to_xml( - [('GeoRegion', geo_region), - ('Name', webspace_name), - ('Plan', plan)]) - xml += '</WebSpaceToCreate>' - return _XmlSerializer.doc_from_xml('Site', xml) - - @staticmethod - def create_reserved_ip_to_xml(name, label, location): - return _XmlSerializer.doc_from_data( - 'ReservedIP', - [('Name', name), - ('Label', label), - ('Location', location)]) - - @staticmethod - def dns_server_to_xml(name, address): - return _XmlSerializer.doc_from_data( - 'DnsServer', - [('Name', name), - ('Address', address)]) - - @staticmethod - def role_instances_to_xml(role_instances): - xml = '' - for name in role_instances: - xml += _XmlSerializer.data_to_xml([('Name', name)]) - return _XmlSerializer.doc_from_xml('RoleInstances ', xml) - - @staticmethod - def data_to_xml(data): - return _data_to_xml(data) - - @staticmethod - def doc_from_xml(document_element_name, inner_xml): - '''Wraps the specified xml in an xml root element with default azure - namespaces''' - xml = ''.join(['<', document_element_name, - ' xmlns:i="http://www.w3.org/2001/XMLSchema-instance"', - ' xmlns="http://schemas.microsoft.com/windowsazure">']) - xml += inner_xml - xml += ''.join(['</', document_element_name, '>']) - return xml - - @staticmethod - def doc_from_data(document_element_name, data, extended_properties=None): - xml = _XmlSerializer.data_to_xml(data) - if extended_properties is not None: - xml += _XmlSerializer.extended_properties_dict_to_xml_fragment( - extended_properties) - return _XmlSerializer.doc_from_xml(document_element_name, xml) - - @staticmethod - def extended_properties_dict_to_xml_fragment(extended_properties): - xml = '' - if extended_properties is not None and len(extended_properties) > 0: - xml += '<ExtendedProperties>' - for key, val in extended_properties.items(): - xml += ''.join(['<ExtendedProperty>', - '<Name>', - _str(key), - '</Name>', - '<Value>', - _str(val), - '</Value>', - '</ExtendedProperty>']) - xml += '</ExtendedProperties>' - return xml - - -class _SqlManagementXmlSerializer(object): - - @staticmethod - def create_server_to_xml(admin_login, admin_password, location): - return _SqlManagementXmlSerializer.doc_from_data( - 'Server', - [('AdministratorLogin', admin_login), - ('AdministratorLoginPassword', admin_password), - ('Location', location)], - 'http://schemas.microsoft.com/sqlazure/2010/12/') - - @staticmethod - def set_server_admin_password_to_xml(admin_password): - return _SqlManagementXmlSerializer.doc_from_xml( - 'AdministratorLoginPassword', admin_password, - 'http://schemas.microsoft.com/sqlazure/2010/12/') - - @staticmethod - def create_firewall_rule_to_xml(name, start_ip_address, end_ip_address): - return _SqlManagementXmlSerializer.doc_from_data( - 'ServiceResource', - [('Name', name), - ('StartIPAddress', start_ip_address), - ('EndIPAddress', end_ip_address)]) - - @staticmethod - def update_firewall_rule_to_xml(name, start_ip_address, end_ip_address): - return _SqlManagementXmlSerializer.doc_from_data( - 'ServiceResource', - [('Name', name), - ('StartIPAddress', start_ip_address), - ('EndIPAddress', end_ip_address)]) - - @staticmethod - def create_database_to_xml(name, service_objective_id, edition, collation_name, - max_size_bytes): - return _SqlManagementXmlSerializer.doc_from_data( - 'ServiceResource', - [('Name', name), - ('Edition', edition), - ('CollationName', collation_name), - ('MaxSizeBytes', max_size_bytes), - ('ServiceObjectiveId', service_objective_id)]) - - @staticmethod - def update_database_to_xml(name, service_objective_id, edition, - max_size_bytes): - return _SqlManagementXmlSerializer.doc_from_data( - 'ServiceResource', - [('Name', name), - ('Edition', edition), - ('MaxSizeBytes', max_size_bytes), - ('ServiceObjectiveId', service_objective_id)]) - - @staticmethod - def xml_to_create_server_response(xmlstr): - xmldoc = minidom.parseString(xmlstr) - element = xmldoc.documentElement - - response = CreateServerResponse() - response.server_name = element.firstChild.nodeValue - response.fully_qualified_domain_name = element.getAttribute('FullyQualifiedDomainName') - - return response - - @staticmethod - def data_to_xml(data): - return _data_to_xml(data) - - @staticmethod - def doc_from_xml(document_element_name, inner_xml, - xmlns='http://schemas.microsoft.com/windowsazure'): - '''Wraps the specified xml in an xml root element with default azure - namespaces''' - xml = ''.join(['<', document_element_name, - ' xmlns="{0}">'.format(xmlns)]) - xml += inner_xml - xml += ''.join(['</', document_element_name, '>']) - return xml - - @staticmethod - def doc_from_data(document_element_name, data, - xmlns='http://schemas.microsoft.com/windowsazure'): - xml = _SqlManagementXmlSerializer.data_to_xml(data) - return _SqlManagementXmlSerializer.doc_from_xml( - document_element_name, xml, xmlns) - - -def _parse_bool(value): - if value.lower() == 'true': - return True - return False - - -class _ServiceBusManagementXmlSerializer(object): - - @staticmethod - def namespace_to_xml(region): - '''Converts a service bus namespace description to xml - - The xml format: -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<entry xmlns="http://www.w3.org/2005/Atom"> - <content type="application/xml"> - <NamespaceDescription - xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"> - <Region>West US</Region> - </NamespaceDescription> - </content> -</entry> - ''' - body = '<NamespaceDescription xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">' - body += ''.join(['<Region>', region, '</Region>']) - body += '</NamespaceDescription>' - - return _create_entry(body) - - @staticmethod - def xml_to_namespace(xmlstr): - '''Converts xml response to service bus namespace - - The xml format for namespace: -<entry> -<id>uuid:00000000-0000-0000-0000-000000000000;id=0000000</id> -<title type="text">myunittests -2012-08-22T16:48:10Z - - - myunittests - West US - 0000000000000000000000000000000000000000000= - Active - 2012-08-22T16:48:10.217Z - https://myunittests-sb.accesscontrol.windows.net/ - https://myunittests.servicebus.windows.net/ - Endpoint=sb://myunittests.servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=0000000000000000000000000000000000000000000= - 00000000000000000000000000000000 - true - - - - ''' - xmldoc = minidom.parseString(xmlstr) - namespace = ServiceBusNamespace() - - mappings = ( - ('Name', 'name', None), - ('Region', 'region', None), - ('DefaultKey', 'default_key', None), - ('Status', 'status', None), - ('CreatedAt', 'created_at', None), - ('AcsManagementEndpoint', 'acs_management_endpoint', None), - ('ServiceBusEndpoint', 'servicebus_endpoint', None), - ('ConnectionString', 'connection_string', None), - ('SubscriptionId', 'subscription_id', None), - ('Enabled', 'enabled', _parse_bool), - ) - - for desc in _get_children_from_path(xmldoc, - 'entry', - 'content', - 'NamespaceDescription'): - for xml_name, field_name, conversion_func in mappings: - node_value = _get_first_child_node_value(desc, xml_name) - if node_value is not None: - if conversion_func is not None: - node_value = conversion_func(node_value) - setattr(namespace, field_name, node_value) - - return namespace - - @staticmethod - def xml_to_region(xmlstr): - '''Converts xml response to service bus region - - The xml format for region: - -uuid:157c311f-081f-4b4a-a0ba-a8f990ffd2a3;id=1756759 - -2013-04-10T18:25:29Z - - - East Asia - East Asia - - - - ''' - xmldoc = minidom.parseString(xmlstr) - region = ServiceBusRegion() - - for desc in _get_children_from_path(xmldoc, 'entry', 'content', - 'RegionCodeDescription'): - node_value = _get_first_child_node_value(desc, 'Code') - if node_value is not None: - region.code = node_value - node_value = _get_first_child_node_value(desc, 'FullName') - if node_value is not None: - region.fullname = node_value - - return region - - @staticmethod - def xml_to_namespace_availability(xmlstr): - '''Converts xml response to service bus namespace availability - - The xml format: - - - uuid:9fc7c652-1856-47ab-8d74-cd31502ea8e6;id=3683292 - - 2013-04-16T03:03:37Z - - - false - - - - ''' - xmldoc = minidom.parseString(xmlstr) - availability = AvailabilityResponse() - - for desc in _get_children_from_path(xmldoc, 'entry', 'content', - 'NamespaceAvailability'): - node_value = _get_first_child_node_value(desc, 'Result') - if node_value is not None: - availability.result = _parse_bool(node_value) - - return availability - - @staticmethod - def odata_converter(data, str_type): - ''' Convert odata type - http://www.odata.org/documentation/odata-version-2-0/overview#AbstractTypeSystem - To be completed - ''' - if not str_type: - return _str(data) - if str_type in ["Edm.Single", "Edm.Double"]: - return float(data) - elif "Edm.Int" in str_type: - return int(data) - else: - return _str(data) - - @staticmethod - def xml_to_metrics(xmlstr, object_type): - '''Converts xml response to service bus metrics objects - - The xml format for MetricProperties - - https://sbgm.windows.net/Metrics(\'listeners.active\') - - <updated>2014-10-09T11:56:50Z</updated> - <author> - <name/> - </author> - <content type="application/xml"> - <m:properties> - <d:Name>listeners.active</d:Name> - <d:PrimaryAggregation>Average</d:PrimaryAggregation> - <d:Unit>Count</d:Unit> - <d:DisplayName>Active listeners</d:DisplayName> - </m:properties> - </content> -</entry> - - The xml format for MetricValues - <entry> - <id>https://sbgm.windows.net/MetricValues(datetime\'2014-10-02T00:00:00Z\')</id> - <title/> - <updated>2014-10-09T18:38:28Z</updated> - <author> - <name/> - </author> - <content type="application/xml"> - <m:properties> - <d:Timestamp m:type="Edm.DateTime">2014-10-02T00:00:00Z</d:Timestamp> - <d:Min m:type="Edm.Int64">-118</d:Min> - <d:Max m:type="Edm.Int64">15</d:Max> - <d:Average m:type="Edm.Single">-78.44444</d:Average> - <d:Total m:type="Edm.Int64">0</d:Total> - </m:properties> - </content> - </entry> - ''' - - xmldoc = minidom.parseString(xmlstr) - return_obj = object_type() - - members = dict(vars(return_obj)) - - # Only one entry here - for xml_entry in _get_children_from_path(xmldoc, - 'entry'): - for node in _get_children_from_path(xml_entry, - 'content', - 'm:properties'): - for name in members: - xml_name = "d:" + _get_serialization_name(name) - children = _get_child_nodes(node, xml_name) - if not children: - continue - child = children[0] - node_type = child.getAttributeNS("http://schemas.microsoft.com/ado/2007/08/dataservices/metadata", 'type') - node_value = _ServiceBusManagementXmlSerializer.odata_converter(child.firstChild.nodeValue, node_type) - setattr(return_obj, name, node_value) - for name, value in _get_entry_properties_from_node(xml_entry, - include_id=True, - use_title_as_id=False).items(): - if name in members: - continue # Do not override if already members - setattr(return_obj, name, value) - return return_obj - -from azure.servicemanagement.servicemanagementservice import ( - ServiceManagementService) -from azure.servicemanagement.servicebusmanagementservice import ( - ServiceBusManagementService) -from azure.servicemanagement.websitemanagementservice import ( - WebsiteManagementService) diff --git a/awx/lib/site-packages/azure/servicemanagement/schedulermanagementservice.py b/awx/lib/site-packages/azure/servicemanagement/schedulermanagementservice.py deleted file mode 100644 index ee57b6f2ed..0000000000 --- a/awx/lib/site-packages/azure/servicemanagement/schedulermanagementservice.py +++ /dev/null @@ -1,70 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - MANAGEMENT_HOST, - _str - ) -from azure.servicemanagement import ( - CloudServices, - ) -from azure.servicemanagement.servicemanagementclient import ( - _ServiceManagementClient, - ) - -class SchedulerManagementService(_ServiceManagementClient): - ''' Note that this class is a preliminary work on Scheduler - management. Since it lack a lot a features, final version - can be slightly different from the current one. - ''' - - def __init__(self, subscription_id=None, cert_file=None, - host=MANAGEMENT_HOST, request_session=None): - ''' - Initializes the scheduler management service. - - subscription_id: Subscription to manage. - cert_file: - Path to .pem certificate file (httplib), or location of the - certificate in your Personal certificate store (winhttp) in the - CURRENT_USER\my\CertificateName format. - If a request_session is specified, then this is unused. - host: Live ServiceClient URL. Defaults to Azure public cloud. - request_session: - Session object to use for http requests. If this is specified, it - replaces the default use of httplib or winhttp. Also, the cert_file - parameter is unused when a session is passed in. - The session object handles authentication, and as such can support - multiple types of authentication: .pem certificate, oauth. - For example, you can pass in a Session instance from the requests - library. To use .pem certificate authentication with requests - library, set the path to the .pem file on the session.cert - attribute. - ''' - super(SchedulerManagementService, self).__init__( - subscription_id, cert_file, host, request_session) - - #--Operations for scheduler ---------------------------------------- - def list_cloud_services(self): - ''' - List the cloud services for scheduling defined on the account. - ''' - return self._perform_get(self._get_list_cloud_services_path(), - CloudServices) - - - #--Helper functions -------------------------------------------------- - def _get_list_cloud_services_path(self): - return self._get_path('cloudservices', None) - diff --git a/awx/lib/site-packages/azure/servicemanagement/servicebusmanagementservice.py b/awx/lib/site-packages/azure/servicemanagement/servicebusmanagementservice.py deleted file mode 100644 index 6008e171be..0000000000 --- a/awx/lib/site-packages/azure/servicemanagement/servicebusmanagementservice.py +++ /dev/null @@ -1,534 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - MANAGEMENT_HOST, - _convert_response_to_feeds, - _str, - _validate_not_none, - _convert_xml_to_windows_azure_object, -) -from azure.servicemanagement import ( - _ServiceBusManagementXmlSerializer, - QueueDescription, - TopicDescription, - NotificationHubDescription, - RelayDescription, - MetricProperties, - MetricValues, - MetricRollups, -) -from azure.servicemanagement.servicemanagementclient import ( - _ServiceManagementClient, -) - -from functools import partial - -X_MS_VERSION = '2012-03-01' - -class ServiceBusManagementService(_ServiceManagementClient): - - def __init__(self, subscription_id=None, cert_file=None, - host=MANAGEMENT_HOST, request_session=None): - ''' - Initializes the service bus management service. - - subscription_id: Subscription to manage. - cert_file: - Path to .pem certificate file (httplib), or location of the - certificate in your Personal certificate store (winhttp) in the - CURRENT_USER\my\CertificateName format. - If a request_session is specified, then this is unused. - host: Live ServiceClient URL. Defaults to Azure public cloud. - request_session: - Session object to use for http requests. If this is specified, it - replaces the default use of httplib or winhttp. Also, the cert_file - parameter is unused when a session is passed in. - The session object handles authentication, and as such can support - multiple types of authentication: .pem certificate, oauth. - For example, you can pass in a Session instance from the requests - library. To use .pem certificate authentication with requests - library, set the path to the .pem file on the session.cert - attribute. - ''' - super(ServiceBusManagementService, self).__init__( - subscription_id, cert_file, host, request_session) - self.x_ms_version = X_MS_VERSION - - # Operations for service bus ---------------------------------------- - def get_regions(self): - ''' - Get list of available service bus regions. - ''' - response = self._perform_get( - self._get_path('services/serviceBus/Regions/', None), - None) - - return _convert_response_to_feeds( - response, - _ServiceBusManagementXmlSerializer.xml_to_region) - - def list_namespaces(self): - ''' - List the service bus namespaces defined on the account. - ''' - response = self._perform_get( - self._get_path('services/serviceBus/Namespaces/', None), - None) - - return _convert_response_to_feeds( - response, - _ServiceBusManagementXmlSerializer.xml_to_namespace) - - def get_namespace(self, name): - ''' - Get details about a specific namespace. - - name: Name of the service bus namespace. - ''' - response = self._perform_get( - self._get_path('services/serviceBus/Namespaces', name), - None) - - return _ServiceBusManagementXmlSerializer.xml_to_namespace( - response.body) - - def create_namespace(self, name, region): - ''' - Create a new service bus namespace. - - name: Name of the service bus namespace to create. - region: Region to create the namespace in. - ''' - _validate_not_none('name', name) - - return self._perform_put( - self._get_path('services/serviceBus/Namespaces', name), - _ServiceBusManagementXmlSerializer.namespace_to_xml(region)) - - def delete_namespace(self, name): - ''' - Delete a service bus namespace. - - name: Name of the service bus namespace to delete. - ''' - _validate_not_none('name', name) - - return self._perform_delete( - self._get_path('services/serviceBus/Namespaces', name), - None) - - def check_namespace_availability(self, name): - ''' - Checks to see if the specified service bus namespace is available, or - if it has already been taken. - - name: Name of the service bus namespace to validate. - ''' - _validate_not_none('name', name) - - response = self._perform_get( - self._get_path('services/serviceBus/CheckNamespaceAvailability', - None) + '/?namespace=' + _str(name), None) - - return _ServiceBusManagementXmlSerializer.xml_to_namespace_availability( - response.body) - - def list_queues(self, name): - ''' - Enumerates the queues in the service namespace. - - name: Name of the service bus namespace. - ''' - _validate_not_none('name', name) - - response = self._perform_get( - self._get_list_queues_path(name), - None) - - return _convert_response_to_feeds(response, - partial(_convert_xml_to_windows_azure_object, - azure_type=QueueDescription)) - - def list_topics(self, name): - ''' - Retrieves the topics in the service namespace. - - name: Name of the service bus namespace. - ''' - response = self._perform_get( - self._get_list_topics_path(name), - None) - - return _convert_response_to_feeds(response, - partial(_convert_xml_to_windows_azure_object, - azure_type=TopicDescription)) - - def list_notification_hubs(self, name): - ''' - Retrieves the notification hubs in the service namespace. - - name: Name of the service bus namespace. - ''' - response = self._perform_get( - self._get_list_notification_hubs_path(name), - None) - - return _convert_response_to_feeds(response, - partial(_convert_xml_to_windows_azure_object, - azure_type=NotificationHubDescription)) - - def list_relays(self, name): - ''' - Retrieves the relays in the service namespace. - - name: Name of the service bus namespace. - ''' - response = self._perform_get( - self._get_list_relays_path(name), - None) - - return _convert_response_to_feeds(response, - partial(_convert_xml_to_windows_azure_object, - azure_type=RelayDescription)) - - def get_supported_metrics_queue(self, name, queue_name): - ''' - Retrieves the list of supported metrics for this namespace and queue - - name: Name of the service bus namespace. - queue_name: Name of the service bus queue in this namespace. - ''' - response = self._perform_get( - self._get_get_supported_metrics_queue_path(name, queue_name), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricProperties)) - - def get_supported_metrics_topic(self, name, topic_name): - ''' - Retrieves the list of supported metrics for this namespace and topic - - name: Name of the service bus namespace. - topic_name: Name of the service bus queue in this namespace. - ''' - response = self._perform_get( - self._get_get_supported_metrics_topic_path(name, topic_name), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricProperties)) - - def get_supported_metrics_notification_hub(self, name, hub_name): - ''' - Retrieves the list of supported metrics for this namespace and topic - - name: Name of the service bus namespace. - hub_name: Name of the service bus notification hub in this namespace. - ''' - response = self._perform_get( - self._get_get_supported_metrics_hub_path(name, hub_name), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricProperties)) - - def get_supported_metrics_relay(self, name, relay_name): - ''' - Retrieves the list of supported metrics for this namespace and relay - - name: Name of the service bus namespace. - relay_name: Name of the service bus relay in this namespace. - ''' - response = self._perform_get( - self._get_get_supported_metrics_relay_path(name, relay_name), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricProperties)) - - def get_metrics_data_queue(self, name, queue_name, metric, rollup, filter_expresssion): - ''' - Retrieves the list of supported metrics for this namespace and queue - - name: Name of the service bus namespace. - queue_name: Name of the service bus queue in this namespace. - metric: name of a supported metric - rollup: name of a supported rollup - filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'" - ''' - response = self._perform_get( - self._get_get_metrics_data_queue_path(name, queue_name, metric, rollup, filter_expresssion), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricValues)) - - def get_metrics_data_topic(self, name, topic_name, metric, rollup, filter_expresssion): - ''' - Retrieves the list of supported metrics for this namespace and topic - - name: Name of the service bus namespace. - topic_name: Name of the service bus queue in this namespace. - metric: name of a supported metric - rollup: name of a supported rollup - filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'" - ''' - response = self._perform_get( - self._get_get_metrics_data_topic_path(name, topic_name, metric, rollup, filter_expresssion), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricValues)) - - def get_metrics_data_notification_hub(self, name, hub_name, metric, rollup, filter_expresssion): - ''' - Retrieves the list of supported metrics for this namespace and topic - - name: Name of the service bus namespace. - hub_name: Name of the service bus notification hub in this namespace. - metric: name of a supported metric - rollup: name of a supported rollup - filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'" - ''' - response = self._perform_get( - self._get_get_metrics_data_hub_path(name, hub_name, metric, rollup, filter_expresssion), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricValues)) - - def get_metrics_data_relay(self, name, relay_name, metric, rollup, filter_expresssion): - ''' - Retrieves the list of supported metrics for this namespace and relay - - name: Name of the service bus namespace. - relay_name: Name of the service bus relay in this namespace. - metric: name of a supported metric - rollup: name of a supported rollup - filter_expression: filter, for instance "$filter=Timestamp gt datetime'2014-10-01T00:00:00Z'" - ''' - response = self._perform_get( - self._get_get_metrics_data_relay_path(name, relay_name, metric, rollup, filter_expresssion), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricValues)) - - def get_metrics_rollups_queue(self, name, queue_name, metric): - ''' - This operation gets rollup data for Service Bus metrics queue. - Rollup data includes the time granularity for the telemetry aggregation as well as - the retention settings for each time granularity. - - name: Name of the service bus namespace. - queue_name: Name of the service bus queue in this namespace. - metric: name of a supported metric - ''' - response = self._perform_get( - self._get_get_metrics_rollup_queue_path(name, queue_name, metric), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricRollups)) - - def get_metrics_rollups_topic(self, name, topic_name, metric): - ''' - This operation gets rollup data for Service Bus metrics topic. - Rollup data includes the time granularity for the telemetry aggregation as well as - the retention settings for each time granularity. - - name: Name of the service bus namespace. - topic_name: Name of the service bus queue in this namespace. - metric: name of a supported metric - ''' - response = self._perform_get( - self._get_get_metrics_rollup_topic_path(name, topic_name, metric), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricRollups)) - - def get_metrics_rollups_notification_hub(self, name, hub_name, metric): - ''' - This operation gets rollup data for Service Bus metrics notification hub. - Rollup data includes the time granularity for the telemetry aggregation as well as - the retention settings for each time granularity. - - name: Name of the service bus namespace. - hub_name: Name of the service bus notification hub in this namespace. - metric: name of a supported metric - ''' - response = self._perform_get( - self._get_get_metrics_rollup_hub_path(name, hub_name, metric), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricRollups)) - - def get_metrics_rollups_relay(self, name, relay_name, metric): - ''' - This operation gets rollup data for Service Bus metrics relay. - Rollup data includes the time granularity for the telemetry aggregation as well as - the retention settings for each time granularity. - - name: Name of the service bus namespace. - relay_name: Name of the service bus relay in this namespace. - metric: name of a supported metric - ''' - response = self._perform_get( - self._get_get_metrics_rollup_relay_path(name, relay_name, metric), - None) - - return _convert_response_to_feeds(response, - partial(_ServiceBusManagementXmlSerializer.xml_to_metrics, - object_type=MetricRollups)) - - - # Helper functions -------------------------------------------------- - def _get_list_queues_path(self, namespace_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/Queues' - - def _get_list_topics_path(self, namespace_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/Topics' - - def _get_list_notification_hubs_path(self, namespace_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/NotificationHubs' - - def _get_list_relays_path(self, namespace_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/Relays' - - def _get_get_supported_metrics_queue_path(self, namespace_name, queue_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/Queues/' + _str(queue_name) + '/Metrics' - - def _get_get_supported_metrics_topic_path(self, namespace_name, topic_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/Topics/' + _str(topic_name) + '/Metrics' - - def _get_get_supported_metrics_hub_path(self, namespace_name, hub_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/NotificationHubs/' + _str(hub_name) + '/Metrics' - - def _get_get_supported_metrics_relay_path(self, namespace_name, queue_name): - return self._get_path('services/serviceBus/Namespaces/', - namespace_name) + '/Relays/' + _str(queue_name) + '/Metrics' - - def _get_get_metrics_data_queue_path(self, namespace_name, queue_name, metric, rollup, filter_expr): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/Queues/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups/', - _str(rollup), - '/Values?', - filter_expr - ]) - - def _get_get_metrics_data_topic_path(self, namespace_name, queue_name, metric, rollup, filter_expr): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/Topics/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups/', - _str(rollup), - '/Values?', - filter_expr - ]) - - def _get_get_metrics_data_hub_path(self, namespace_name, queue_name, metric, rollup, filter_expr): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/NotificationHubs/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups/', - _str(rollup), - '/Values?', - filter_expr - ]) - - def _get_get_metrics_data_relay_path(self, namespace_name, queue_name, metric, rollup, filter_expr): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/Relays/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups/', - _str(rollup), - '/Values?', - filter_expr - ]) - - def _get_get_metrics_rollup_queue_path(self, namespace_name, queue_name, metric): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/Queues/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups', - ]) - - def _get_get_metrics_rollup_topic_path(self, namespace_name, queue_name, metric): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/Topics/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups', - ]) - - def _get_get_metrics_rollup_hub_path(self, namespace_name, queue_name, metric): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/NotificationHubs/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups', - ]) - - def _get_get_metrics_rollup_relay_path(self, namespace_name, queue_name, metric): - return "".join([ - self._get_path('services/serviceBus/Namespaces/', namespace_name), - '/Relays/', - _str(queue_name), - '/Metrics/', - _str(metric), - '/Rollups', - ]) diff --git a/awx/lib/site-packages/azure/servicemanagement/servicemanagementclient.py b/awx/lib/site-packages/azure/servicemanagement/servicemanagementclient.py deleted file mode 100644 index 808956e0bb..0000000000 --- a/awx/lib/site-packages/azure/servicemanagement/servicemanagementclient.py +++ /dev/null @@ -1,258 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import os - -from azure import ( - WindowsAzureError, - MANAGEMENT_HOST, - _get_request_body, - _parse_response, - _str, - _update_request_uri_query, - ) -from azure.http import ( - HTTPError, - HTTPRequest, - ) -from azure.http.httpclient import _HTTPClient -from azure.servicemanagement import ( - AZURE_MANAGEMENT_CERTFILE, - AZURE_MANAGEMENT_SUBSCRIPTIONID, - _management_error_handler, - parse_response_for_async_op, - X_MS_VERSION, - ) - - -class _ServiceManagementClient(object): - - def __init__(self, subscription_id=None, cert_file=None, - host=MANAGEMENT_HOST, request_session=None): - self.requestid = None - self.subscription_id = subscription_id - self.cert_file = cert_file - self.host = host - self.request_session = request_session - self.x_ms_version = X_MS_VERSION - self.content_type = 'application/atom+xml;type=entry;charset=utf-8' - - if not self.cert_file and not request_session: - if AZURE_MANAGEMENT_CERTFILE in os.environ: - self.cert_file = os.environ[AZURE_MANAGEMENT_CERTFILE] - - if not self.subscription_id: - if AZURE_MANAGEMENT_SUBSCRIPTIONID in os.environ: - self.subscription_id = os.environ[ - AZURE_MANAGEMENT_SUBSCRIPTIONID] - - if not self.request_session: - if not self.cert_file or not self.subscription_id: - raise WindowsAzureError( - 'You need to provide subscription id and certificate file') - - self._httpclient = _HTTPClient( - service_instance=self, cert_file=self.cert_file, - request_session=self.request_session) - self._filter = self._httpclient.perform_request - - def with_filter(self, filter): - '''Returns a new service which will process requests with the - specified filter. Filtering operations can include logging, automatic - retrying, etc... The filter is a lambda which receives the HTTPRequest - and another lambda. The filter can perform any pre-processing on the - request, pass it off to the next lambda, and then perform any - post-processing on the response.''' - res = type(self)(self.subscription_id, self.cert_file, self.host, - self.request_session) - old_filter = self._filter - - def new_filter(request): - return filter(request, old_filter) - - res._filter = new_filter - return res - - def set_proxy(self, host, port, user=None, password=None): - ''' - Sets the proxy server host and port for the HTTP CONNECT Tunnelling. - - host: Address of the proxy. Ex: '192.168.0.100' - port: Port of the proxy. Ex: 6000 - user: User for proxy authorization. - password: Password for proxy authorization. - ''' - self._httpclient.set_proxy(host, port, user, password) - - def perform_get(self, path, x_ms_version=None): - ''' - Performs a GET request and returns the response. - - path: - Path to the resource. - Ex: '/<subscription-id>/services/hostedservices/<service-name>' - x_ms_version: - If specified, this is used for the x-ms-version header. - Otherwise, self.x_ms_version is used. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self.host - request.path = path - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_management_header(request, x_ms_version) - response = self._perform_request(request) - - return response - - def perform_put(self, path, body, x_ms_version=None): - ''' - Performs a PUT request and returns the response. - - path: - Path to the resource. - Ex: '/<subscription-id>/services/hostedservices/<service-name>' - body: - Body for the PUT request. - x_ms_version: - If specified, this is used for the x-ms-version header. - Otherwise, self.x_ms_version is used. - ''' - request = HTTPRequest() - request.method = 'PUT' - request.host = self.host - request.path = path - request.body = _get_request_body(body) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_management_header(request, x_ms_version) - response = self._perform_request(request) - - return response - - def perform_post(self, path, body, x_ms_version=None): - ''' - Performs a POST request and returns the response. - - path: - Path to the resource. - Ex: '/<subscription-id>/services/hostedservices/<service-name>' - body: - Body for the POST request. - x_ms_version: - If specified, this is used for the x-ms-version header. - Otherwise, self.x_ms_version is used. - ''' - request = HTTPRequest() - request.method = 'POST' - request.host = self.host - request.path = path - request.body = _get_request_body(body) - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_management_header(request, x_ms_version) - response = self._perform_request(request) - - return response - - def perform_delete(self, path, x_ms_version=None): - ''' - Performs a DELETE request and returns the response. - - path: - Path to the resource. - Ex: '/<subscription-id>/services/hostedservices/<service-name>' - x_ms_version: - If specified, this is used for the x-ms-version header. - Otherwise, self.x_ms_version is used. - ''' - request = HTTPRequest() - request.method = 'DELETE' - request.host = self.host - request.path = path - request.path, request.query = _update_request_uri_query(request) - request.headers = self._update_management_header(request, x_ms_version) - response = self._perform_request(request) - - return response - - #--Helper functions -------------------------------------------------- - def _perform_request(self, request): - try: - resp = self._filter(request) - except HTTPError as ex: - return _management_error_handler(ex) - - return resp - - def _update_management_header(self, request, x_ms_version): - ''' Add additional headers for management. ''' - - if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']: - request.headers.append(('Content-Length', str(len(request.body)))) - - # append additional headers base on the service - request.headers.append(('x-ms-version', x_ms_version or self.x_ms_version)) - - # if it is not GET or HEAD request, must set content-type. - if not request.method in ['GET', 'HEAD']: - for name, _ in request.headers: - if 'content-type' == name.lower(): - break - else: - request.headers.append( - ('Content-Type', - self.content_type)) - - return request.headers - - def _perform_get(self, path, response_type, x_ms_version=None): - response = self.perform_get(path, x_ms_version) - - if response_type is not None: - return _parse_response(response, response_type) - - return response - - def _perform_put(self, path, body, async=False, x_ms_version=None): - response = self.perform_put(path, body, x_ms_version) - - if async: - return parse_response_for_async_op(response) - - return None - - def _perform_post(self, path, body, response_type=None, async=False, - x_ms_version=None): - response = self.perform_post(path, body, x_ms_version) - - if response_type is not None: - return _parse_response(response, response_type) - - if async: - return parse_response_for_async_op(response) - - return None - - def _perform_delete(self, path, async=False, x_ms_version=None): - response = self.perform_delete(path, x_ms_version) - - if async: - return parse_response_for_async_op(response) - - return None - - def _get_path(self, resource, name): - path = '/' + self.subscription_id + '/' + resource - if name is not None: - path += '/' + _str(name) - return path diff --git a/awx/lib/site-packages/azure/servicemanagement/servicemanagementservice.py b/awx/lib/site-packages/azure/servicemanagement/servicemanagementservice.py deleted file mode 100644 index 651ffdae53..0000000000 --- a/awx/lib/site-packages/azure/servicemanagement/servicemanagementservice.py +++ /dev/null @@ -1,2300 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - WindowsAzureError, - MANAGEMENT_HOST, - _str, - _validate_not_none, - ) -from azure.servicemanagement import ( - AffinityGroups, - AffinityGroup, - AvailabilityResponse, - Certificate, - Certificates, - DataVirtualHardDisk, - Deployment, - Disk, - Disks, - Locations, - Operation, - HostedService, - HostedServices, - Images, - OperatingSystems, - OperatingSystemFamilies, - OSImage, - PersistentVMRole, - ResourceExtensions, - ReservedIP, - ReservedIPs, - RoleSize, - RoleSizes, - StorageService, - StorageServices, - Subscription, - Subscriptions, - SubscriptionCertificate, - SubscriptionCertificates, - VirtualNetworkSites, - VMImages, - _XmlSerializer, - ) -from azure.servicemanagement.servicemanagementclient import ( - _ServiceManagementClient, - ) - -class ServiceManagementService(_ServiceManagementClient): - - def __init__(self, subscription_id=None, cert_file=None, - host=MANAGEMENT_HOST, request_session=None): - ''' - Initializes the management service. - - subscription_id: Subscription to manage. - cert_file: - Path to .pem certificate file (httplib), or location of the - certificate in your Personal certificate store (winhttp) in the - CURRENT_USER\my\CertificateName format. - If a request_session is specified, then this is unused. - host: Live ServiceClient URL. Defaults to Azure public cloud. - request_session: - Session object to use for http requests. If this is specified, it - replaces the default use of httplib or winhttp. Also, the cert_file - parameter is unused when a session is passed in. - The session object handles authentication, and as such can support - multiple types of authentication: .pem certificate, oauth. - For example, you can pass in a Session instance from the requests - library. To use .pem certificate authentication with requests - library, set the path to the .pem file on the session.cert - attribute. - ''' - super(ServiceManagementService, self).__init__( - subscription_id, cert_file, host, request_session) - - #--Operations for subscriptions -------------------------------------- - def list_role_sizes(self): - ''' - Lists the role sizes that are available under the specified - subscription. - ''' - return self._perform_get(self._get_role_sizes_path(), - RoleSizes) - - def list_subscriptions(self): - ''' - Returns a list of subscriptions that you can access. - - You must make sure that the request that is made to the management - service is secure using an Active Directory access token. - ''' - return self._perform_get(self._get_subscriptions_path(), - Subscriptions) - - #--Operations for storage accounts ----------------------------------- - def list_storage_accounts(self): - ''' - Lists the storage accounts available under the current subscription. - ''' - return self._perform_get(self._get_storage_service_path(), - StorageServices) - - def get_storage_account_properties(self, service_name): - ''' - Returns system properties for the specified storage account. - - service_name: Name of the storage service account. - ''' - _validate_not_none('service_name', service_name) - return self._perform_get(self._get_storage_service_path(service_name), - StorageService) - - def get_storage_account_keys(self, service_name): - ''' - Returns the primary and secondary access keys for the specified - storage account. - - service_name: Name of the storage service account. - ''' - _validate_not_none('service_name', service_name) - return self._perform_get( - self._get_storage_service_path(service_name) + '/keys', - StorageService) - - def regenerate_storage_account_keys(self, service_name, key_type): - ''' - Regenerates the primary or secondary access key for the specified - storage account. - - service_name: Name of the storage service account. - key_type: - Specifies which key to regenerate. Valid values are: - Primary, Secondary - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('key_type', key_type) - return self._perform_post( - self._get_storage_service_path( - service_name) + '/keys?action=regenerate', - _XmlSerializer.regenerate_keys_to_xml( - key_type), - StorageService) - - def create_storage_account(self, service_name, description, label, - affinity_group=None, location=None, - geo_replication_enabled=None, - extended_properties=None, - account_type='Standard_GRS'): - ''' - Creates a new storage account in Windows Azure. - - service_name: - A name for the storage account that is unique within Windows Azure. - Storage account names must be between 3 and 24 characters in length - and use numbers and lower-case letters only. - description: - A description for the storage account. The description may be up - to 1024 characters in length. - label: - A name for the storage account. The name may be up to 100 - characters in length. The name can be used to identify the storage - account for your tracking purposes. - affinity_group: - The name of an existing affinity group in the specified - subscription. You can specify either a location or affinity_group, - but not both. - location: - The location where the storage account is created. You can specify - either a location or affinity_group, but not both. - geo_replication_enabled: - Deprecated. Replaced by the account_type parameter. - extended_properties: - Dictionary containing name/value pairs of storage account - properties. You can have a maximum of 50 extended property - name/value pairs. The maximum length of the Name element is 64 - characters, only alphanumeric characters and underscores are valid - in the Name, and the name must start with a letter. The value has - a maximum length of 255 characters. - account_type: - Specifies whether the account supports locally-redundant storage, - geo-redundant storage, zone-redundant storage, or read access - geo-redundant storage. - Possible values are: - Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('description', description) - _validate_not_none('label', label) - if affinity_group is None and location is None: - raise WindowsAzureError( - 'location or affinity_group must be specified') - if affinity_group is not None and location is not None: - raise WindowsAzureError( - 'Only one of location or affinity_group needs to be specified') - if geo_replication_enabled == False: - account_type = 'Standard_LRS' - return self._perform_post( - self._get_storage_service_path(), - _XmlSerializer.create_storage_service_input_to_xml( - service_name, - description, - label, - affinity_group, - location, - account_type, - extended_properties), - async=True) - - def update_storage_account(self, service_name, description=None, - label=None, geo_replication_enabled=None, - extended_properties=None, - account_type='Standard_GRS'): - ''' - Updates the label, the description, and enables or disables the - geo-replication status for a storage account in Windows Azure. - - service_name: Name of the storage service account. - description: - A description for the storage account. The description may be up - to 1024 characters in length. - label: - A name for the storage account. The name may be up to 100 - characters in length. The name can be used to identify the storage - account for your tracking purposes. - geo_replication_enabled: - Deprecated. Replaced by the account_type parameter. - extended_properties: - Dictionary containing name/value pairs of storage account - properties. You can have a maximum of 50 extended property - name/value pairs. The maximum length of the Name element is 64 - characters, only alphanumeric characters and underscores are valid - in the Name, and the name must start with a letter. The value has - a maximum length of 255 characters. - account_type: - Specifies whether the account supports locally-redundant storage, - geo-redundant storage, zone-redundant storage, or read access - geo-redundant storage. - Possible values are: - Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS - ''' - _validate_not_none('service_name', service_name) - if geo_replication_enabled == False: - account_type = 'Standard_LRS' - return self._perform_put( - self._get_storage_service_path(service_name), - _XmlSerializer.update_storage_service_input_to_xml( - description, - label, - account_type, - extended_properties)) - - def delete_storage_account(self, service_name): - ''' - Deletes the specified storage account from Windows Azure. - - service_name: Name of the storage service account. - ''' - _validate_not_none('service_name', service_name) - return self._perform_delete( - self._get_storage_service_path(service_name)) - - def check_storage_account_name_availability(self, service_name): - ''' - Checks to see if the specified storage account name is available, or - if it has already been taken. - - service_name: Name of the storage service account. - ''' - _validate_not_none('service_name', service_name) - return self._perform_get( - self._get_storage_service_path() + - '/operations/isavailable/' + - _str(service_name) + '', - AvailabilityResponse) - - #--Operations for hosted services ------------------------------------ - def list_hosted_services(self): - ''' - Lists the hosted services available under the current subscription. - ''' - return self._perform_get(self._get_hosted_service_path(), - HostedServices) - - def get_hosted_service_properties(self, service_name, embed_detail=False): - ''' - Retrieves system properties for the specified hosted service. These - properties include the service name and service type; the name of the - affinity group to which the service belongs, or its location if it is - not part of an affinity group; and optionally, information on the - service's deployments. - - service_name: Name of the hosted service. - embed_detail: - When True, the management service returns properties for all - deployments of the service, as well as for the service itself. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('embed_detail', embed_detail) - return self._perform_get( - self._get_hosted_service_path(service_name) + - '?embed-detail=' + - _str(embed_detail).lower(), - HostedService) - - def create_hosted_service(self, service_name, label, description=None, - location=None, affinity_group=None, - extended_properties=None): - ''' - Creates a new hosted service in Windows Azure. - - service_name: - A name for the hosted service that is unique within Windows Azure. - This name is the DNS prefix name and can be used to access the - hosted service. - label: - A name for the hosted service. The name can be up to 100 characters - in length. The name can be used to identify the storage account for - your tracking purposes. - description: - A description for the hosted service. The description can be up to - 1024 characters in length. - location: - The location where the hosted service will be created. You can - specify either a location or affinity_group, but not both. - affinity_group: - The name of an existing affinity group associated with this - subscription. This name is a GUID and can be retrieved by examining - the name element of the response body returned by - list_affinity_groups. You can specify either a location or - affinity_group, but not both. - extended_properties: - Dictionary containing name/value pairs of storage account - properties. You can have a maximum of 50 extended property - name/value pairs. The maximum length of the Name element is 64 - characters, only alphanumeric characters and underscores are valid - in the Name, and the name must start with a letter. The value has - a maximum length of 255 characters. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('label', label) - if affinity_group is None and location is None: - raise WindowsAzureError( - 'location or affinity_group must be specified') - if affinity_group is not None and location is not None: - raise WindowsAzureError( - 'Only one of location or affinity_group needs to be specified') - return self._perform_post(self._get_hosted_service_path(), - _XmlSerializer.create_hosted_service_to_xml( - service_name, - label, - description, - location, - affinity_group, - extended_properties)) - - def update_hosted_service(self, service_name, label=None, description=None, - extended_properties=None): - ''' - Updates the label and/or the description for a hosted service in - Windows Azure. - - service_name: Name of the hosted service. - label: - A name for the hosted service. The name may be up to 100 characters - in length. You must specify a value for either Label or - Description, or for both. It is recommended that the label be - unique within the subscription. The name can be used - identify the hosted service for your tracking purposes. - description: - A description for the hosted service. The description may be up to - 1024 characters in length. You must specify a value for either - Label or Description, or for both. - extended_properties: - Dictionary containing name/value pairs of storage account - properties. You can have a maximum of 50 extended property - name/value pairs. The maximum length of the Name element is 64 - characters, only alphanumeric characters and underscores are valid - in the Name, and the name must start with a letter. The value has - a maximum length of 255 characters. - ''' - _validate_not_none('service_name', service_name) - return self._perform_put(self._get_hosted_service_path(service_name), - _XmlSerializer.update_hosted_service_to_xml( - label, - description, - extended_properties)) - - def delete_hosted_service(self, service_name): - ''' - Deletes the specified hosted service from Windows Azure. - - service_name: Name of the hosted service. - ''' - _validate_not_none('service_name', service_name) - return self._perform_delete(self._get_hosted_service_path(service_name)) - - def get_deployment_by_slot(self, service_name, deployment_slot): - ''' - Returns configuration information, status, and system properties for - a deployment. - - service_name: Name of the hosted service. - deployment_slot: - The environment to which the hosted service is deployed. Valid - values are: staging, production - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_slot', deployment_slot) - return self._perform_get( - self._get_deployment_path_using_slot( - service_name, deployment_slot), - Deployment) - - def get_deployment_by_name(self, service_name, deployment_name): - ''' - Returns configuration information, status, and system properties for a - deployment. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - return self._perform_get( - self._get_deployment_path_using_name( - service_name, deployment_name), - Deployment) - - def create_deployment(self, service_name, deployment_slot, name, - package_url, label, configuration, - start_deployment=False, - treat_warnings_as_error=False, - extended_properties=None): - ''' - Uploads a new service package and creates a new deployment on staging - or production. - - service_name: Name of the hosted service. - deployment_slot: - The environment to which the hosted service is deployed. Valid - values are: staging, production - name: - The name for the deployment. The deployment name must be unique - among other deployments for the hosted service. - package_url: - A URL that refers to the location of the service package in the - Blob service. The service package can be located either in a - storage account beneath the same subscription or a Shared Access - Signature (SAS) URI from any storage account. - label: - A name for the hosted service. The name can be up to 100 characters - in length. It is recommended that the label be unique within the - subscription. The name can be used to identify the hosted service - for your tracking purposes. - configuration: - The base-64 encoded service configuration file for the deployment. - start_deployment: - Indicates whether to start the deployment immediately after it is - created. If false, the service model is still deployed to the - virtual machines but the code is not run immediately. Instead, the - service is Suspended until you call Update Deployment Status and - set the status to Running, at which time the service will be - started. A deployed service still incurs charges, even if it is - suspended. - treat_warnings_as_error: - Indicates whether to treat package validation warnings as errors. - If set to true, the Created Deployment operation fails if there - are validation warnings on the service package. - extended_properties: - Dictionary containing name/value pairs of storage account - properties. You can have a maximum of 50 extended property - name/value pairs. The maximum length of the Name element is 64 - characters, only alphanumeric characters and underscores are valid - in the Name, and the name must start with a letter. The value has - a maximum length of 255 characters. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_slot', deployment_slot) - _validate_not_none('name', name) - _validate_not_none('package_url', package_url) - _validate_not_none('label', label) - _validate_not_none('configuration', configuration) - return self._perform_post( - self._get_deployment_path_using_slot( - service_name, deployment_slot), - _XmlSerializer.create_deployment_to_xml( - name, - package_url, - label, - configuration, - start_deployment, - treat_warnings_as_error, - extended_properties), - async=True) - - def delete_deployment(self, service_name, deployment_name): - ''' - Deletes the specified deployment. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - return self._perform_delete( - self._get_deployment_path_using_name( - service_name, deployment_name), - async=True) - - def swap_deployment(self, service_name, production, source_deployment): - ''' - Initiates a virtual IP swap between the staging and production - deployment environments for a service. If the service is currently - running in the staging environment, it will be swapped to the - production environment. If it is running in the production - environment, it will be swapped to staging. - - service_name: Name of the hosted service. - production: The name of the production deployment. - source_deployment: The name of the source deployment. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('production', production) - _validate_not_none('source_deployment', source_deployment) - return self._perform_post(self._get_hosted_service_path(service_name), - _XmlSerializer.swap_deployment_to_xml( - production, source_deployment), - async=True) - - def change_deployment_configuration(self, service_name, deployment_name, - configuration, - treat_warnings_as_error=False, - mode='Auto', extended_properties=None): - ''' - Initiates a change to the deployment configuration. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - configuration: - The base-64 encoded service configuration file for the deployment. - treat_warnings_as_error: - Indicates whether to treat package validation warnings as errors. - If set to true, the Created Deployment operation fails if there - are validation warnings on the service package. - mode: - If set to Manual, WalkUpgradeDomain must be called to apply the - update. If set to Auto, the Windows Azure platform will - automatically apply the update To each upgrade domain for the - service. Possible values are: Auto, Manual - extended_properties: - Dictionary containing name/value pairs of storage account - properties. You can have a maximum of 50 extended property - name/value pairs. The maximum length of the Name element is 64 - characters, only alphanumeric characters and underscores are valid - in the Name, and the name must start with a letter. The value has - a maximum length of 255 characters. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('configuration', configuration) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + '/?comp=config', - _XmlSerializer.change_deployment_to_xml( - configuration, - treat_warnings_as_error, - mode, - extended_properties), - async=True) - - def update_deployment_status(self, service_name, deployment_name, status): - ''' - Initiates a change in deployment status. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - status: - The change to initiate to the deployment status. Possible values - include: Running, Suspended - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('status', status) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + '/?comp=status', - _XmlSerializer.update_deployment_status_to_xml( - status), - async=True) - - def upgrade_deployment(self, service_name, deployment_name, mode, - package_url, configuration, label, force, - role_to_upgrade=None, extended_properties=None): - ''' - Initiates an upgrade. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - mode: - If set to Manual, WalkUpgradeDomain must be called to apply the - update. If set to Auto, the Windows Azure platform will - automatically apply the update To each upgrade domain for the - service. Possible values are: Auto, Manual - package_url: - A URL that refers to the location of the service package in the - Blob service. The service package can be located either in a - storage account beneath the same subscription or a Shared Access - Signature (SAS) URI from any storage account. - configuration: - The base-64 encoded service configuration file for the deployment. - label: - A name for the hosted service. The name can be up to 100 characters - in length. It is recommended that the label be unique within the - subscription. The name can be used to identify the hosted service - for your tracking purposes. - force: - Specifies whether the rollback should proceed even when it will - cause local data to be lost from some role instances. True if the - rollback should proceed; otherwise false if the rollback should - fail. - role_to_upgrade: The name of the specific role to upgrade. - extended_properties: - Dictionary containing name/value pairs of storage account - properties. You can have a maximum of 50 extended property - name/value pairs. The maximum length of the Name element is 64 - characters, only alphanumeric characters and underscores are valid - in the Name, and the name must start with a letter. The value has - a maximum length of 255 characters. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('mode', mode) - _validate_not_none('package_url', package_url) - _validate_not_none('configuration', configuration) - _validate_not_none('label', label) - _validate_not_none('force', force) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + '/?comp=upgrade', - _XmlSerializer.upgrade_deployment_to_xml( - mode, - package_url, - configuration, - label, - role_to_upgrade, - force, - extended_properties), - async=True) - - def walk_upgrade_domain(self, service_name, deployment_name, - upgrade_domain): - ''' - Specifies the next upgrade domain to be walked during manual in-place - upgrade or configuration change. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - upgrade_domain: - An integer value that identifies the upgrade domain to walk. - Upgrade domains are identified with a zero-based index: the first - upgrade domain has an ID of 0, the second has an ID of 1, and so on. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('upgrade_domain', upgrade_domain) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + '/?comp=walkupgradedomain', - _XmlSerializer.walk_upgrade_domain_to_xml( - upgrade_domain), - async=True) - - def rollback_update_or_upgrade(self, service_name, deployment_name, mode, - force): - ''' - Cancels an in progress configuration change (update) or upgrade and - returns the deployment to its state before the upgrade or - configuration change was started. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - mode: - Specifies whether the rollback should proceed automatically. - auto - The rollback proceeds without further user input. - manual - You must call the Walk Upgrade Domain operation to - apply the rollback to each upgrade domain. - force: - Specifies whether the rollback should proceed even when it will - cause local data to be lost from some role instances. True if the - rollback should proceed; otherwise false if the rollback should - fail. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('mode', mode) - _validate_not_none('force', force) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + '/?comp=rollback', - _XmlSerializer.rollback_upgrade_to_xml( - mode, force), - async=True) - - def reboot_role_instance(self, service_name, deployment_name, - role_instance_name): - ''' - Requests a reboot of a role instance that is running in a deployment. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - role_instance_name: The name of the role instance. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_instance_name', role_instance_name) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + \ - '/roleinstances/' + _str(role_instance_name) + \ - '?comp=reboot', - '', - async=True) - - def reimage_role_instance(self, service_name, deployment_name, - role_instance_name): - ''' - Requests a reimage of a role instance that is running in a deployment. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - role_instance_name: The name of the role instance. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_instance_name', role_instance_name) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + \ - '/roleinstances/' + _str(role_instance_name) + \ - '?comp=reimage', - '', - async=True) - - def rebuild_role_instance(self, service_name, deployment_name, - role_instance_name): - ''' - Reinstalls the operating system on instances of web roles or worker - roles and initializes the storage resources that are used by them. If - you do not want to initialize storage resources, you can use - reimage_role_instance. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - role_instance_name: The name of the role instance. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_instance_name', role_instance_name) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + \ - '/roleinstances/' + _str(role_instance_name) + \ - '?comp=rebuild&resources=allLocalDrives', - '', - async=True) - - def delete_role_instances(self, service_name, deployment_name, - role_instance_names): - ''' - Reinstalls the operating system on instances of web roles or worker - roles and initializes the storage resources that are used by them. If - you do not want to initialize storage resources, you can use - reimage_role_instance. - - service_name: Name of the hosted service. - deployment_name: The name of the deployment. - role_instance_names: List of role instance names. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_instance_names', role_instance_names) - return self._perform_post( - self._get_deployment_path_using_name( - service_name, deployment_name) + '/roleinstances/?comp=delete', - _XmlSerializer.role_instances_to_xml(role_instance_names), - async=True) - - def check_hosted_service_name_availability(self, service_name): - ''' - Checks to see if the specified hosted service name is available, or if - it has already been taken. - - service_name: Name of the hosted service. - ''' - _validate_not_none('service_name', service_name) - return self._perform_get( - '/' + self.subscription_id + - '/services/hostedservices/operations/isavailable/' + - _str(service_name) + '', - AvailabilityResponse) - - #--Operations for service certificates ------------------------------- - def list_service_certificates(self, service_name): - ''' - Lists all of the service certificates associated with the specified - hosted service. - - service_name: Name of the hosted service. - ''' - _validate_not_none('service_name', service_name) - return self._perform_get( - '/' + self.subscription_id + '/services/hostedservices/' + - _str(service_name) + '/certificates', - Certificates) - - def get_service_certificate(self, service_name, thumbalgorithm, thumbprint): - ''' - Returns the public data for the specified X.509 certificate associated - with a hosted service. - - service_name: Name of the hosted service. - thumbalgorithm: The algorithm for the certificate's thumbprint. - thumbprint: The hexadecimal representation of the thumbprint. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('thumbalgorithm', thumbalgorithm) - _validate_not_none('thumbprint', thumbprint) - return self._perform_get( - '/' + self.subscription_id + '/services/hostedservices/' + - _str(service_name) + '/certificates/' + - _str(thumbalgorithm) + '-' + _str(thumbprint) + '', - Certificate) - - def add_service_certificate(self, service_name, data, certificate_format, - password): - ''' - Adds a certificate to a hosted service. - - service_name: Name of the hosted service. - data: The base-64 encoded form of the pfx file. - certificate_format: - The service certificate format. The only supported value is pfx. - password: The certificate password. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('data', data) - _validate_not_none('certificate_format', certificate_format) - _validate_not_none('password', password) - return self._perform_post( - '/' + self.subscription_id + '/services/hostedservices/' + - _str(service_name) + '/certificates', - _XmlSerializer.certificate_file_to_xml( - data, certificate_format, password), - async=True) - - def delete_service_certificate(self, service_name, thumbalgorithm, - thumbprint): - ''' - Deletes a service certificate from the certificate store of a hosted - service. - - service_name: Name of the hosted service. - thumbalgorithm: The algorithm for the certificate's thumbprint. - thumbprint: The hexadecimal representation of the thumbprint. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('thumbalgorithm', thumbalgorithm) - _validate_not_none('thumbprint', thumbprint) - return self._perform_delete( - '/' + self.subscription_id + '/services/hostedservices/' + - _str(service_name) + '/certificates/' + - _str(thumbalgorithm) + '-' + _str(thumbprint), - async=True) - - #--Operations for management certificates ---------------------------- - def list_management_certificates(self): - ''' - The List Management Certificates operation lists and returns basic - information about all of the management certificates associated with - the specified subscription. Management certificates, which are also - known as subscription certificates, authenticate clients attempting to - connect to resources associated with your Windows Azure subscription. - ''' - return self._perform_get('/' + self.subscription_id + '/certificates', - SubscriptionCertificates) - - def get_management_certificate(self, thumbprint): - ''' - The Get Management Certificate operation retrieves information about - the management certificate with the specified thumbprint. Management - certificates, which are also known as subscription certificates, - authenticate clients attempting to connect to resources associated - with your Windows Azure subscription. - - thumbprint: The thumbprint value of the certificate. - ''' - _validate_not_none('thumbprint', thumbprint) - return self._perform_get( - '/' + self.subscription_id + '/certificates/' + _str(thumbprint), - SubscriptionCertificate) - - def add_management_certificate(self, public_key, thumbprint, data): - ''' - The Add Management Certificate operation adds a certificate to the - list of management certificates. Management certificates, which are - also known as subscription certificates, authenticate clients - attempting to connect to resources associated with your Windows Azure - subscription. - - public_key: - A base64 representation of the management certificate public key. - thumbprint: - The thumb print that uniquely identifies the management - certificate. - data: The certificate's raw data in base-64 encoded .cer format. - ''' - _validate_not_none('public_key', public_key) - _validate_not_none('thumbprint', thumbprint) - _validate_not_none('data', data) - return self._perform_post( - '/' + self.subscription_id + '/certificates', - _XmlSerializer.subscription_certificate_to_xml( - public_key, thumbprint, data)) - - def delete_management_certificate(self, thumbprint): - ''' - The Delete Management Certificate operation deletes a certificate from - the list of management certificates. Management certificates, which - are also known as subscription certificates, authenticate clients - attempting to connect to resources associated with your Windows Azure - subscription. - - thumbprint: - The thumb print that uniquely identifies the management - certificate. - ''' - _validate_not_none('thumbprint', thumbprint) - return self._perform_delete( - '/' + self.subscription_id + '/certificates/' + _str(thumbprint)) - - #--Operations for affinity groups ------------------------------------ - def list_affinity_groups(self): - ''' - Lists the affinity groups associated with the specified subscription. - ''' - return self._perform_get( - '/' + self.subscription_id + '/affinitygroups', - AffinityGroups) - - def get_affinity_group_properties(self, affinity_group_name): - ''' - Returns the system properties associated with the specified affinity - group. - - affinity_group_name: The name of the affinity group. - ''' - _validate_not_none('affinity_group_name', affinity_group_name) - return self._perform_get( - '/' + self.subscription_id + '/affinitygroups/' + - _str(affinity_group_name) + '', - AffinityGroup) - - def create_affinity_group(self, name, label, location, description=None): - ''' - Creates a new affinity group for the specified subscription. - - name: A name for the affinity group that is unique to the subscription. - label: - A name for the affinity group. The name can be up to 100 characters - in length. - location: - The data center location where the affinity group will be created. - To list available locations, use the list_location function. - description: - A description for the affinity group. The description can be up to - 1024 characters in length. - ''' - _validate_not_none('name', name) - _validate_not_none('label', label) - _validate_not_none('location', location) - return self._perform_post( - '/' + self.subscription_id + '/affinitygroups', - _XmlSerializer.create_affinity_group_to_xml(name, - label, - description, - location)) - - def update_affinity_group(self, affinity_group_name, label, - description=None): - ''' - Updates the label and/or the description for an affinity group for the - specified subscription. - - affinity_group_name: The name of the affinity group. - label: - A name for the affinity group. The name can be up to 100 characters - in length. - description: - A description for the affinity group. The description can be up to - 1024 characters in length. - ''' - _validate_not_none('affinity_group_name', affinity_group_name) - _validate_not_none('label', label) - return self._perform_put( - '/' + self.subscription_id + '/affinitygroups/' + - _str(affinity_group_name), - _XmlSerializer.update_affinity_group_to_xml(label, description)) - - def delete_affinity_group(self, affinity_group_name): - ''' - Deletes an affinity group in the specified subscription. - - affinity_group_name: The name of the affinity group. - ''' - _validate_not_none('affinity_group_name', affinity_group_name) - return self._perform_delete('/' + self.subscription_id + \ - '/affinitygroups/' + \ - _str(affinity_group_name)) - - #--Operations for locations ------------------------------------------ - def list_locations(self): - ''' - Lists all of the data center locations that are valid for your - subscription. - ''' - return self._perform_get('/' + self.subscription_id + '/locations', - Locations) - - #--Operations for tracking asynchronous requests --------------------- - def get_operation_status(self, request_id): - ''' - Returns the status of the specified operation. After calling an - asynchronous operation, you can call Get Operation Status to determine - whether the operation has succeeded, failed, or is still in progress. - - request_id: The request ID for the request you wish to track. - ''' - _validate_not_none('request_id', request_id) - return self._perform_get( - '/' + self.subscription_id + '/operations/' + _str(request_id), - Operation) - - #--Operations for retrieving operating system information ------------ - def list_operating_systems(self): - ''' - Lists the versions of the guest operating system that are currently - available in Windows Azure. - ''' - return self._perform_get( - '/' + self.subscription_id + '/operatingsystems', - OperatingSystems) - - def list_operating_system_families(self): - ''' - Lists the guest operating system families available in Windows Azure, - and also lists the operating system versions available for each family. - ''' - return self._perform_get( - '/' + self.subscription_id + '/operatingsystemfamilies', - OperatingSystemFamilies) - - #--Operations for retrieving subscription history -------------------- - def get_subscription(self): - ''' - Returns account and resource allocation information on the specified - subscription. - ''' - return self._perform_get('/' + self.subscription_id + '', - Subscription) - - #--Operations for reserved ip addresses ----------------------------- - def create_reserved_ip_address(self, name, label=None, location=None): - ''' - Reserves an IPv4 address for the specified subscription. - - name: - Required. Specifies the name for the reserved IP address. - label: - Optional. Specifies a label for the reserved IP address. The label - can be up to 100 characters long and can be used for your tracking - purposes. - location: - Required. Specifies the location of the reserved IP address. This - should be the same location that is assigned to the cloud service - containing the deployment that will use the reserved IP address. - To see the available locations, you can use list_locations. - ''' - _validate_not_none('name', name) - return self._perform_post( - self._get_reserved_ip_path(), - _XmlSerializer.create_reserved_ip_to_xml(name, label, location)) - - def delete_reserved_ip_address(self, name): - ''' - Deletes a reserved IP address from the specified subscription. - - name: Required. Name of the reserved IP address. - ''' - _validate_not_none('name', name) - return self._perform_delete(self._get_reserved_ip_path(name)) - - def get_reserved_ip_address(self, name): - ''' - Retrieves information about the specified reserved IP address. - - name: Required. Name of the reserved IP address. - ''' - _validate_not_none('name', name) - return self._perform_get(self._get_reserved_ip_path(name), ReservedIP) - - def list_reserved_ip_addresses(self): - ''' - Lists the IP addresses that have been reserved for the specified - subscription. - ''' - return self._perform_get(self._get_reserved_ip_path(), ReservedIPs) - - #--Operations for virtual machines ----------------------------------- - def get_role(self, service_name, deployment_name, role_name): - ''' - Retrieves the specified virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - return self._perform_get( - self._get_role_path(service_name, deployment_name, role_name), - PersistentVMRole) - - def create_virtual_machine_deployment(self, service_name, deployment_name, - deployment_slot, label, role_name, - system_config, os_virtual_hard_disk, - network_config=None, - availability_set_name=None, - data_virtual_hard_disks=None, - role_size=None, - role_type='PersistentVMRole', - virtual_network_name=None, - resource_extension_references=None, - provision_guest_agent=None, - vm_image_name=None, - media_location=None, - dns_servers=None, - reserved_ip_name=None): - ''' - Provisions a virtual machine based on the supplied configuration. - - service_name: Name of the hosted service. - deployment_name: - The name for the deployment. The deployment name must be unique - among other deployments for the hosted service. - deployment_slot: - The environment to which the hosted service is deployed. Valid - values are: staging, production - label: - Specifies an identifier for the deployment. The label can be up to - 100 characters long. The label can be used for tracking purposes. - role_name: The name of the role. - system_config: - Contains the metadata required to provision a virtual machine from - a Windows or Linux OS image. Use an instance of - WindowsConfigurationSet or LinuxConfigurationSet. - os_virtual_hard_disk: - Contains the parameters Windows Azure uses to create the operating - system disk for the virtual machine. If you are creating a Virtual - Machine by using a VM Image, this parameter is not used. - network_config: - Encapsulates the metadata required to create the virtual network - configuration for a virtual machine. If you do not include a - network configuration set you will not be able to access the VM - through VIPs over the internet. If your virtual machine belongs to - a virtual network you can not specify which subnet address space - it resides under. - availability_set_name: - Specifies the name of an availability set to which to add the - virtual machine. This value controls the virtual machine - allocation in the Windows Azure environment. Virtual machines - specified in the same availability set are allocated to different - nodes to maximize availability. - data_virtual_hard_disks: - Contains the parameters Windows Azure uses to create a data disk - for a virtual machine. - role_size: - The size of the virtual machine to allocate. The default value is - Small. Possible values are: ExtraSmall, Small, Medium, Large, - ExtraLarge. The specified value must be compatible with the disk - selected in the OSVirtualHardDisk values. - role_type: - The type of the role for the virtual machine. The only supported - value is PersistentVMRole. - virtual_network_name: - Specifies the name of an existing virtual network to which the - deployment will belong. - resource_extension_references: - Optional. Contains a collection of resource extensions that are to - be installed on the Virtual Machine. This element is used if - provision_guest_agent is set to True. - provision_guest_agent: - Optional. Indicates whether the VM Agent is installed on the - Virtual Machine. To run a resource extension in a Virtual Machine, - this service must be installed. - vm_image_name: - Optional. Specifies the name of the VM Image that is to be used to - create the Virtual Machine. If this is specified, the - system_config and network_config parameters are not used. - media_location: - Optional. Required if the Virtual Machine is being created from a - published VM Image. Specifies the location of the VHD file that is - created when VMImageName specifies a published VM Image. - dns_servers: - Optional. List of DNS servers (use DnsServer class) to associate - with the Virtual Machine. - reserved_ip_name: - Optional. Specifies the name of a reserved IP address that is to be - assigned to the deployment. You must run create_reserved_ip_address - before you can assign the address to the deployment using this - element. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('deployment_slot', deployment_slot) - _validate_not_none('label', label) - _validate_not_none('role_name', role_name) - return self._perform_post( - self._get_deployment_path_using_name(service_name), - _XmlSerializer.virtual_machine_deployment_to_xml( - deployment_name, - deployment_slot, - label, - role_name, - system_config, - os_virtual_hard_disk, - role_type, - network_config, - availability_set_name, - data_virtual_hard_disks, - role_size, - virtual_network_name, - resource_extension_references, - provision_guest_agent, - vm_image_name, - media_location, - dns_servers, - reserved_ip_name), - async=True) - - def add_role(self, service_name, deployment_name, role_name, system_config, - os_virtual_hard_disk, network_config=None, - availability_set_name=None, data_virtual_hard_disks=None, - role_size=None, role_type='PersistentVMRole', - resource_extension_references=None, - provision_guest_agent=None, vm_image_name=None, - media_location=None): - ''' - Adds a virtual machine to an existing deployment. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - system_config: - Contains the metadata required to provision a virtual machine from - a Windows or Linux OS image. Use an instance of - WindowsConfigurationSet or LinuxConfigurationSet. - os_virtual_hard_disk: - Contains the parameters Windows Azure uses to create the operating - system disk for the virtual machine. If you are creating a Virtual - Machine by using a VM Image, this parameter is not used. - network_config: - Encapsulates the metadata required to create the virtual network - configuration for a virtual machine. If you do not include a - network configuration set you will not be able to access the VM - through VIPs over the internet. If your virtual machine belongs to - a virtual network you can not specify which subnet address space - it resides under. - availability_set_name: - Specifies the name of an availability set to which to add the - virtual machine. This value controls the virtual machine allocation - in the Windows Azure environment. Virtual machines specified in the - same availability set are allocated to different nodes to maximize - availability. - data_virtual_hard_disks: - Contains the parameters Windows Azure uses to create a data disk - for a virtual machine. - role_size: - The size of the virtual machine to allocate. The default value is - Small. Possible values are: ExtraSmall, Small, Medium, Large, - ExtraLarge. The specified value must be compatible with the disk - selected in the OSVirtualHardDisk values. - role_type: - The type of the role for the virtual machine. The only supported - value is PersistentVMRole. - resource_extension_references: - Optional. Contains a collection of resource extensions that are to - be installed on the Virtual Machine. This element is used if - provision_guest_agent is set to True. - provision_guest_agent: - Optional. Indicates whether the VM Agent is installed on the - Virtual Machine. To run a resource extension in a Virtual Machine, - this service must be installed. - vm_image_name: - Optional. Specifies the name of the VM Image that is to be used to - create the Virtual Machine. If this is specified, the - system_config and network_config parameters are not used. - media_location: - Optional. Required if the Virtual Machine is being created from a - published VM Image. Specifies the location of the VHD file that is - created when VMImageName specifies a published VM Image. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - return self._perform_post( - self._get_role_path(service_name, deployment_name), - _XmlSerializer.add_role_to_xml( - role_name, - system_config, - os_virtual_hard_disk, - role_type, - network_config, - availability_set_name, - data_virtual_hard_disks, - role_size, - resource_extension_references, - provision_guest_agent, - vm_image_name, - media_location), - async=True) - - def update_role(self, service_name, deployment_name, role_name, - os_virtual_hard_disk=None, network_config=None, - availability_set_name=None, data_virtual_hard_disks=None, - role_size=None, role_type='PersistentVMRole', - resource_extension_references=None, - provision_guest_agent=None): - ''' - Updates the specified virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - os_virtual_hard_disk: - Contains the parameters Windows Azure uses to create the operating - system disk for the virtual machine. - network_config: - Encapsulates the metadata required to create the virtual network - configuration for a virtual machine. If you do not include a - network configuration set you will not be able to access the VM - through VIPs over the internet. If your virtual machine belongs to - a virtual network you can not specify which subnet address space - it resides under. - availability_set_name: - Specifies the name of an availability set to which to add the - virtual machine. This value controls the virtual machine allocation - in the Windows Azure environment. Virtual machines specified in the - same availability set are allocated to different nodes to maximize - availability. - data_virtual_hard_disks: - Contains the parameters Windows Azure uses to create a data disk - for a virtual machine. - role_size: - The size of the virtual machine to allocate. The default value is - Small. Possible values are: ExtraSmall, Small, Medium, Large, - ExtraLarge. The specified value must be compatible with the disk - selected in the OSVirtualHardDisk values. - role_type: - The type of the role for the virtual machine. The only supported - value is PersistentVMRole. - resource_extension_references: - Optional. Contains a collection of resource extensions that are to - be installed on the Virtual Machine. This element is used if - provision_guest_agent is set to True. - provision_guest_agent: - Optional. Indicates whether the VM Agent is installed on the - Virtual Machine. To run a resource extension in a Virtual Machine, - this service must be installed. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - return self._perform_put( - self._get_role_path(service_name, deployment_name, role_name), - _XmlSerializer.update_role_to_xml( - role_name, - os_virtual_hard_disk, - role_type, - network_config, - availability_set_name, - data_virtual_hard_disks, - role_size, - resource_extension_references, - provision_guest_agent), - async=True) - - def delete_role(self, service_name, deployment_name, role_name): - ''' - Deletes the specified virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - return self._perform_delete( - self._get_role_path(service_name, deployment_name, role_name), - async=True) - - def capture_role(self, service_name, deployment_name, role_name, - post_capture_action, target_image_name, - target_image_label, provisioning_configuration=None): - ''' - The Capture Role operation captures a virtual machine image to your - image gallery. From the captured image, you can create additional - customized virtual machines. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - post_capture_action: - Specifies the action after capture operation completes. Possible - values are: Delete, Reprovision. - target_image_name: - Specifies the image name of the captured virtual machine. - target_image_label: - Specifies the friendly name of the captured virtual machine. - provisioning_configuration: - Use an instance of WindowsConfigurationSet or LinuxConfigurationSet. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - _validate_not_none('post_capture_action', post_capture_action) - _validate_not_none('target_image_name', target_image_name) - _validate_not_none('target_image_label', target_image_label) - return self._perform_post( - self._get_role_instance_operations_path( - service_name, deployment_name, role_name), - _XmlSerializer.capture_role_to_xml( - post_capture_action, - target_image_name, - target_image_label, - provisioning_configuration), - async=True) - - def start_role(self, service_name, deployment_name, role_name): - ''' - Starts the specified virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - return self._perform_post( - self._get_role_instance_operations_path( - service_name, deployment_name, role_name), - _XmlSerializer.start_role_operation_to_xml(), - async=True) - - def start_roles(self, service_name, deployment_name, role_names): - ''' - Starts the specified virtual machines. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_names: The names of the roles, as an enumerable of strings. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_names', role_names) - return self._perform_post( - self._get_roles_operations_path(service_name, deployment_name), - _XmlSerializer.start_roles_operation_to_xml(role_names), - async=True) - - def restart_role(self, service_name, deployment_name, role_name): - ''' - Restarts the specified virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - return self._perform_post( - self._get_role_instance_operations_path( - service_name, deployment_name, role_name), - _XmlSerializer.restart_role_operation_to_xml( - ), - async=True) - - def shutdown_role(self, service_name, deployment_name, role_name, - post_shutdown_action='Stopped'): - ''' - Shuts down the specified virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - post_shutdown_action: - Specifies how the Virtual Machine should be shut down. Values are: - Stopped - Shuts down the Virtual Machine but retains the compute - resources. You will continue to be billed for the resources - that the stopped machine uses. - StoppedDeallocated - Shuts down the Virtual Machine and releases the compute - resources. You are not billed for the compute resources that - this Virtual Machine uses. If a static Virtual Network IP - address is assigned to the Virtual Machine, it is reserved. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - _validate_not_none('post_shutdown_action', post_shutdown_action) - return self._perform_post( - self._get_role_instance_operations_path( - service_name, deployment_name, role_name), - _XmlSerializer.shutdown_role_operation_to_xml(post_shutdown_action), - async=True) - - def shutdown_roles(self, service_name, deployment_name, role_names, - post_shutdown_action='Stopped'): - ''' - Shuts down the specified virtual machines. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_names: The names of the roles, as an enumerable of strings. - post_shutdown_action: - Specifies how the Virtual Machine should be shut down. Values are: - Stopped - Shuts down the Virtual Machine but retains the compute - resources. You will continue to be billed for the resources - that the stopped machine uses. - StoppedDeallocated - Shuts down the Virtual Machine and releases the compute - resources. You are not billed for the compute resources that - this Virtual Machine uses. If a static Virtual Network IP - address is assigned to the Virtual Machine, it is reserved. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_names', role_names) - _validate_not_none('post_shutdown_action', post_shutdown_action) - return self._perform_post( - self._get_roles_operations_path(service_name, deployment_name), - _XmlSerializer.shutdown_roles_operation_to_xml( - role_names, post_shutdown_action), - async=True) - - def add_dns_server(self, service_name, deployment_name, dns_server_name, address): - ''' - Adds a DNS server definition to an existing deployment. - - service_name: The name of the service. - deployment_name: The name of the deployment. - dns_server_name: Specifies the name of the DNS server. - address: Specifies the IP address of the DNS server. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('dns_server_name', dns_server_name) - _validate_not_none('address', address) - return self._perform_post( - self._get_dns_server_path(service_name, deployment_name), - _XmlSerializer.dns_server_to_xml(dns_server_name, address), - async=True) - - def update_dns_server(self, service_name, deployment_name, dns_server_name, address): - ''' - Updates the ip address of a DNS server. - - service_name: The name of the service. - deployment_name: The name of the deployment. - dns_server_name: Specifies the name of the DNS server. - address: Specifies the IP address of the DNS server. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('dns_server_name', dns_server_name) - _validate_not_none('address', address) - return self._perform_put( - self._get_dns_server_path(service_name, - deployment_name, - dns_server_name), - _XmlSerializer.dns_server_to_xml(dns_server_name, address), - async=True) - - def delete_dns_server(self, service_name, deployment_name, dns_server_name): - ''' - Deletes a DNS server from a deployment. - - service_name: The name of the service. - deployment_name: The name of the deployment. - dns_server_name: Name of the DNS server that you want to delete. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('dns_server_name', dns_server_name) - return self._perform_delete( - self._get_dns_server_path(service_name, - deployment_name, - dns_server_name), - async=True) - - def list_resource_extensions(self): - ''' - Lists the resource extensions that are available to add to a - Virtual Machine. - ''' - return self._perform_get(self._get_resource_extensions_path(), - ResourceExtensions) - - def list_resource_extension_versions(self, publisher_name, extension_name): - ''' - Lists the versions of a resource extension that are available to add - to a Virtual Machine. - - publisher_name: Name of the resource extension publisher. - extension_name: Name of the resource extension. - ''' - return self._perform_get(self._get_resource_extension_versions_path( - publisher_name, extension_name), - ResourceExtensions) - - #--Operations for virtual machine images ----------------------------- - def capture_vm_image(self, service_name, deployment_name, role_name, options): - ''' - Creates a copy of the operating system virtual hard disk (VHD) and all - of the data VHDs that are associated with the Virtual Machine, saves - the VHD copies in the same storage location as the original VHDs, and - registers the copies as a VM Image in the image repository that is - associated with the specified subscription. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - options: An instance of CaptureRoleAsVMImage class. - options.os_state: - Required. Specifies the state of the operating system in the image. - Possible values are: Generalized, Specialized - A Virtual Machine that is fully configured and running contains a - Specialized operating system. A Virtual Machine on which the - Sysprep command has been run with the generalize option contains a - Generalized operating system. If you capture an image from a - generalized Virtual Machine, the machine is deleted after the image - is captured. It is recommended that all Virtual Machines are shut - down before capturing an image. - options.vm_image_name: - Required. Specifies the name of the VM Image. - options.vm_image_name: - Required. Specifies the label of the VM Image. - options.description: - Optional. Specifies the description of the VM Image. - options.language: - Optional. Specifies the language of the VM Image. - options.image_family: - Optional. Specifies a value that can be used to group VM Images. - options.recommended_vm_size: - Optional. Specifies the size to use for the Virtual Machine that - is created from the VM Image. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - _validate_not_none('options', options) - _validate_not_none('options.os_state', options.os_state) - _validate_not_none('options.vm_image_name', options.vm_image_name) - _validate_not_none('options.vm_image_label', options.vm_image_label) - return self._perform_post( - self._get_capture_vm_image_path(service_name, deployment_name, role_name), - _XmlSerializer.capture_vm_image_to_xml(options), - async=True) - - def create_vm_image(self, vm_image): - ''' - Creates a VM Image in the image repository that is associated with the - specified subscription using a specified set of virtual hard disks. - - vm_image: An instance of VMImage class. - vm_image.name: Required. Specifies the name of the image. - vm_image.label: Required. Specifies an identifier for the image. - vm_image.description: Optional. Specifies the description of the image. - vm_image.os_disk_configuration: - Required. Specifies configuration information for the operating - system disk that is associated with the image. - vm_image.os_disk_configuration.host_caching: - Optional. Specifies the caching behavior of the operating system disk. - Possible values are: None, ReadOnly, ReadWrite - vm_image.os_disk_configuration.os_state: - Required. Specifies the state of the operating system in the image. - Possible values are: Generalized, Specialized - A Virtual Machine that is fully configured and running contains a - Specialized operating system. A Virtual Machine on which the - Sysprep command has been run with the generalize option contains a - Generalized operating system. - vm_image.os_disk_configuration.os: - Required. Specifies the operating system type of the image. - vm_image.os_disk_configuration.media_link: - Required. Specifies the location of the blob in Windows Azure - storage. The blob location belongs to a storage account in the - subscription specified by the <subscription-id> value in the - operation call. - vm_image.data_disk_configurations: - Optional. Specifies configuration information for the data disks - that are associated with the image. A VM Image might not have data - disks associated with it. - vm_image.data_disk_configurations[].host_caching: - Optional. Specifies the caching behavior of the data disk. - Possible values are: None, ReadOnly, ReadWrite - vm_image.data_disk_configurations[].lun: - Optional if the lun for the disk is 0. Specifies the Logical Unit - Number (LUN) for the data disk. - vm_image.data_disk_configurations[].media_link: - Required. Specifies the location of the blob in Windows Azure - storage. The blob location belongs to a storage account in the - subscription specified by the <subscription-id> value in the - operation call. - vm_image.data_disk_configurations[].logical_size_in_gb: - Required. Specifies the size, in GB, of the data disk. - vm_image.language: Optional. Specifies the language of the image. - vm_image.image_family: - Optional. Specifies a value that can be used to group VM Images. - vm_image.recommended_vm_size: - Optional. Specifies the size to use for the Virtual Machine that - is created from the VM Image. - vm_image.eula: - Optional. Specifies the End User License Agreement that is - associated with the image. The value for this element is a string, - but it is recommended that the value be a URL that points to a EULA. - vm_image.icon_uri: - Optional. Specifies the URI to the icon that is displayed for the - image in the Management Portal. - vm_image.small_icon_uri: - Optional. Specifies the URI to the small icon that is displayed for - the image in the Management Portal. - vm_image.privacy_uri: - Optional. Specifies the URI that points to a document that contains - the privacy policy related to the image. - vm_image.published_date: - Optional. Specifies the date when the image was added to the image - repository. - vm_image.show_in_gui: - Optional. Indicates whether the VM Images should be listed in the - portal. - ''' - _validate_not_none('vm_image', vm_image) - _validate_not_none('vm_image.name', vm_image.name) - _validate_not_none('vm_image.label', vm_image.label) - _validate_not_none('vm_image.os_disk_configuration.os_state', - vm_image.os_disk_configuration.os_state) - _validate_not_none('vm_image.os_disk_configuration.os', - vm_image.os_disk_configuration.os) - _validate_not_none('vm_image.os_disk_configuration.media_link', - vm_image.os_disk_configuration.media_link) - return self._perform_post( - self._get_vm_image_path(), - _XmlSerializer.create_vm_image_to_xml(vm_image), - async=True) - - def delete_vm_image(self, vm_image_name, delete_vhd=False): - ''' - Deletes the specified VM Image from the image repository that is - associated with the specified subscription. - - vm_image_name: The name of the image. - delete_vhd: Deletes the underlying vhd blob in Azure storage. - ''' - _validate_not_none('vm_image_name', vm_image_name) - path = self._get_vm_image_path(vm_image_name) - if delete_vhd: - path += '?comp=media' - return self._perform_delete(path, async=True) - - def list_vm_images(self, location=None, publisher=None, category=None): - ''' - Retrieves a list of the VM Images from the image repository that is - associated with the specified subscription. - ''' - path = self._get_vm_image_path() - query = '' - if location: - query += '&location=' + location - if publisher: - query += '&publisher=' + publisher - if category: - query += '&category=' + category - if query: - path = path + '?' + query.lstrip('&') - return self._perform_get(path, VMImages) - - def update_vm_image(self, vm_image_name, vm_image): - ''' - Updates a VM Image in the image repository that is associated with the - specified subscription. - - vm_image_name: Name of image to update. - vm_image: An instance of VMImage class. - vm_image.label: Optional. Specifies an identifier for the image. - vm_image.os_disk_configuration: - Required. Specifies configuration information for the operating - system disk that is associated with the image. - vm_image.os_disk_configuration.host_caching: - Optional. Specifies the caching behavior of the operating system disk. - Possible values are: None, ReadOnly, ReadWrite - vm_image.data_disk_configurations: - Optional. Specifies configuration information for the data disks - that are associated with the image. A VM Image might not have data - disks associated with it. - vm_image.data_disk_configurations[].name: - Required. Specifies the name of the data disk. - vm_image.data_disk_configurations[].host_caching: - Optional. Specifies the caching behavior of the data disk. - Possible values are: None, ReadOnly, ReadWrite - vm_image.data_disk_configurations[].lun: - Optional if the lun for the disk is 0. Specifies the Logical Unit - Number (LUN) for the data disk. - vm_image.description: Optional. Specifies the description of the image. - vm_image.language: Optional. Specifies the language of the image. - vm_image.image_family: - Optional. Specifies a value that can be used to group VM Images. - vm_image.recommended_vm_size: - Optional. Specifies the size to use for the Virtual Machine that - is created from the VM Image. - vm_image.eula: - Optional. Specifies the End User License Agreement that is - associated with the image. The value for this element is a string, - but it is recommended that the value be a URL that points to a EULA. - vm_image.icon_uri: - Optional. Specifies the URI to the icon that is displayed for the - image in the Management Portal. - vm_image.small_icon_uri: - Optional. Specifies the URI to the small icon that is displayed for - the image in the Management Portal. - vm_image.privacy_uri: - Optional. Specifies the URI that points to a document that contains - the privacy policy related to the image. - vm_image.published_date: - Optional. Specifies the date when the image was added to the image - repository. - vm_image.show_in_gui: - Optional. Indicates whether the VM Images should be listed in the - portal. - ''' - _validate_not_none('vm_image_name', vm_image_name) - _validate_not_none('vm_image', vm_image) - return self._perform_put(self._get_vm_image_path(vm_image_name), - _XmlSerializer.update_vm_image_to_xml(vm_image), - async=True) - - #--Operations for operating system images ---------------------------- - def list_os_images(self): - ''' - Retrieves a list of the OS images from the image repository. - ''' - return self._perform_get(self._get_image_path(), - Images) - - def get_os_image(self, image_name): - ''' - Retrieves an OS image from the image repository. - ''' - return self._perform_get(self._get_image_path(image_name), - OSImage) - - def add_os_image(self, label, media_link, name, os): - ''' - Adds an OS image that is currently stored in a storage account in your - subscription to the image repository. - - label: Specifies the friendly name of the image. - media_link: - Specifies the location of the blob in Windows Azure blob store - where the media for the image is located. The blob location must - belong to a storage account in the subscription specified by the - <subscription-id> value in the operation call. Example: - http://example.blob.core.windows.net/disks/mydisk.vhd - name: - Specifies a name for the OS image that Windows Azure uses to - identify the image when creating one or more virtual machines. - os: - The operating system type of the OS image. Possible values are: - Linux, Windows - ''' - _validate_not_none('label', label) - _validate_not_none('media_link', media_link) - _validate_not_none('name', name) - _validate_not_none('os', os) - return self._perform_post(self._get_image_path(), - _XmlSerializer.os_image_to_xml( - label, media_link, name, os), - async=True) - - def update_os_image(self, image_name, label, media_link, name, os): - ''' - Updates an OS image that in your image repository. - - image_name: The name of the image to update. - label: - Specifies the friendly name of the image to be updated. You cannot - use this operation to update images provided by the Windows Azure - platform. - media_link: - Specifies the location of the blob in Windows Azure blob store - where the media for the image is located. The blob location must - belong to a storage account in the subscription specified by the - <subscription-id> value in the operation call. Example: - http://example.blob.core.windows.net/disks/mydisk.vhd - name: - Specifies a name for the OS image that Windows Azure uses to - identify the image when creating one or more VM Roles. - os: - The operating system type of the OS image. Possible values are: - Linux, Windows - ''' - _validate_not_none('image_name', image_name) - _validate_not_none('label', label) - _validate_not_none('media_link', media_link) - _validate_not_none('name', name) - _validate_not_none('os', os) - return self._perform_put(self._get_image_path(image_name), - _XmlSerializer.os_image_to_xml( - label, media_link, name, os), - async=True) - - def delete_os_image(self, image_name, delete_vhd=False): - ''' - Deletes the specified OS image from your image repository. - - image_name: The name of the image. - delete_vhd: Deletes the underlying vhd blob in Azure storage. - ''' - _validate_not_none('image_name', image_name) - path = self._get_image_path(image_name) - if delete_vhd: - path += '?comp=media' - return self._perform_delete(path, async=True) - - #--Operations for virtual machine disks ------------------------------ - def get_data_disk(self, service_name, deployment_name, role_name, lun): - ''' - Retrieves the specified data disk from a virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - lun: The Logical Unit Number (LUN) for the disk. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - _validate_not_none('lun', lun) - return self._perform_get( - self._get_data_disk_path( - service_name, deployment_name, role_name, lun), - DataVirtualHardDisk) - - def add_data_disk(self, service_name, deployment_name, role_name, lun, - host_caching=None, media_link=None, disk_label=None, - disk_name=None, logical_disk_size_in_gb=None, - source_media_link=None): - ''' - Adds a data disk to a virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - lun: - Specifies the Logical Unit Number (LUN) for the disk. The LUN - specifies the slot in which the data drive appears when mounted - for usage by the virtual machine. Valid LUN values are 0 through 15. - host_caching: - Specifies the platform caching behavior of data disk blob for - read/write efficiency. The default vault is ReadOnly. Possible - values are: None, ReadOnly, ReadWrite - media_link: - Specifies the location of the blob in Windows Azure blob store - where the media for the disk is located. The blob location must - belong to the storage account in the subscription specified by the - <subscription-id> value in the operation call. Example: - http://example.blob.core.windows.net/disks/mydisk.vhd - disk_label: - Specifies the description of the data disk. When you attach a disk, - either by directly referencing a media using the MediaLink element - or specifying the target disk size, you can use the DiskLabel - element to customize the name property of the target data disk. - disk_name: - Specifies the name of the disk. Windows Azure uses the specified - disk to create the data disk for the machine and populates this - field with the disk name. - logical_disk_size_in_gb: - Specifies the size, in GB, of an empty disk to be attached to the - role. The disk can be created as part of disk attach or create VM - role call by specifying the value for this property. Windows Azure - creates the empty disk based on size preference and attaches the - newly created disk to the Role. - source_media_link: - Specifies the location of a blob in account storage which is - mounted as a data disk when the virtual machine is created. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - _validate_not_none('lun', lun) - return self._perform_post( - self._get_data_disk_path(service_name, deployment_name, role_name), - _XmlSerializer.data_virtual_hard_disk_to_xml( - host_caching, - disk_label, - disk_name, - lun, - logical_disk_size_in_gb, - media_link, - source_media_link), - async=True) - - def update_data_disk(self, service_name, deployment_name, role_name, lun, - host_caching=None, media_link=None, updated_lun=None, - disk_label=None, disk_name=None, - logical_disk_size_in_gb=None): - ''' - Updates the specified data disk attached to the specified virtual - machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - lun: - Specifies the Logical Unit Number (LUN) for the disk. The LUN - specifies the slot in which the data drive appears when mounted - for usage by the virtual machine. Valid LUN values are 0 through - 15. - host_caching: - Specifies the platform caching behavior of data disk blob for - read/write efficiency. The default vault is ReadOnly. Possible - values are: None, ReadOnly, ReadWrite - media_link: - Specifies the location of the blob in Windows Azure blob store - where the media for the disk is located. The blob location must - belong to the storage account in the subscription specified by - the <subscription-id> value in the operation call. Example: - http://example.blob.core.windows.net/disks/mydisk.vhd - updated_lun: - Specifies the Logical Unit Number (LUN) for the disk. The LUN - specifies the slot in which the data drive appears when mounted - for usage by the virtual machine. Valid LUN values are 0 through 15. - disk_label: - Specifies the description of the data disk. When you attach a disk, - either by directly referencing a media using the MediaLink element - or specifying the target disk size, you can use the DiskLabel - element to customize the name property of the target data disk. - disk_name: - Specifies the name of the disk. Windows Azure uses the specified - disk to create the data disk for the machine and populates this - field with the disk name. - logical_disk_size_in_gb: - Specifies the size, in GB, of an empty disk to be attached to the - role. The disk can be created as part of disk attach or create VM - role call by specifying the value for this property. Windows Azure - creates the empty disk based on size preference and attaches the - newly created disk to the Role. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - _validate_not_none('lun', lun) - return self._perform_put( - self._get_data_disk_path( - service_name, deployment_name, role_name, lun), - _XmlSerializer.data_virtual_hard_disk_to_xml( - host_caching, - disk_label, - disk_name, - updated_lun, - logical_disk_size_in_gb, - media_link, - None), - async=True) - - def delete_data_disk(self, service_name, deployment_name, role_name, lun, delete_vhd=False): - ''' - Removes the specified data disk from a virtual machine. - - service_name: The name of the service. - deployment_name: The name of the deployment. - role_name: The name of the role. - lun: The Logical Unit Number (LUN) for the disk. - delete_vhd: Deletes the underlying vhd blob in Azure storage. - ''' - _validate_not_none('service_name', service_name) - _validate_not_none('deployment_name', deployment_name) - _validate_not_none('role_name', role_name) - _validate_not_none('lun', lun) - path = self._get_data_disk_path(service_name, deployment_name, role_name, lun) - if delete_vhd: - path += '?comp=media' - return self._perform_delete(path, async=True) - - #--Operations for virtual machine disks ------------------------------ - def list_disks(self): - ''' - Retrieves a list of the disks in your image repository. - ''' - return self._perform_get(self._get_disk_path(), - Disks) - - def get_disk(self, disk_name): - ''' - Retrieves a disk from your image repository. - ''' - return self._perform_get(self._get_disk_path(disk_name), - Disk) - - def add_disk(self, has_operating_system, label, media_link, name, os): - ''' - Adds a disk to the user image repository. The disk can be an OS disk - or a data disk. - - has_operating_system: - Specifies whether the disk contains an operation system. Only a - disk with an operating system installed can be mounted as OS Drive. - label: Specifies the description of the disk. - media_link: - Specifies the location of the blob in Windows Azure blob store - where the media for the disk is located. The blob location must - belong to the storage account in the current subscription specified - by the <subscription-id> value in the operation call. Example: - http://example.blob.core.windows.net/disks/mydisk.vhd - name: - Specifies a name for the disk. Windows Azure uses the name to - identify the disk when creating virtual machines from the disk. - os: The OS type of the disk. Possible values are: Linux, Windows - ''' - _validate_not_none('has_operating_system', has_operating_system) - _validate_not_none('label', label) - _validate_not_none('media_link', media_link) - _validate_not_none('name', name) - _validate_not_none('os', os) - return self._perform_post(self._get_disk_path(), - _XmlSerializer.disk_to_xml( - has_operating_system, - label, - media_link, - name, - os)) - - def update_disk(self, disk_name, has_operating_system, label, media_link, - name, os): - ''' - Updates an existing disk in your image repository. - - disk_name: The name of the disk to update. - has_operating_system: - Specifies whether the disk contains an operation system. Only a - disk with an operating system installed can be mounted as OS Drive. - label: Specifies the description of the disk. - media_link: - Specifies the location of the blob in Windows Azure blob store - where the media for the disk is located. The blob location must - belong to the storage account in the current subscription specified - by the <subscription-id> value in the operation call. Example: - http://example.blob.core.windows.net/disks/mydisk.vhd - name: - Specifies a name for the disk. Windows Azure uses the name to - identify the disk when creating virtual machines from the disk. - os: The OS type of the disk. Possible values are: Linux, Windows - ''' - _validate_not_none('disk_name', disk_name) - _validate_not_none('has_operating_system', has_operating_system) - _validate_not_none('label', label) - _validate_not_none('media_link', media_link) - _validate_not_none('name', name) - _validate_not_none('os', os) - return self._perform_put(self._get_disk_path(disk_name), - _XmlSerializer.disk_to_xml( - has_operating_system, - label, - media_link, - name, - os)) - - def delete_disk(self, disk_name, delete_vhd=False): - ''' - Deletes the specified data or operating system disk from your image - repository. - - disk_name: The name of the disk to delete. - delete_vhd: Deletes the underlying vhd blob in Azure storage. - ''' - _validate_not_none('disk_name', disk_name) - path = self._get_disk_path(disk_name) - if delete_vhd: - path += '?comp=media' - return self._perform_delete(path) - - #--Operations for virtual networks ------------------------------ - def list_virtual_network_sites(self): - ''' - Retrieves a list of the virtual networks. - ''' - return self._perform_get(self._get_virtual_network_site_path(), VirtualNetworkSites) - - #--Helper functions -------------------------------------------------- - def _get_role_sizes_path(self): - return self._get_path('rolesizes', None) - - def _get_subscriptions_path(self): - return '/subscriptions' - - def _get_virtual_network_site_path(self): - return self._get_path('services/networking/virtualnetwork', None) - - def _get_storage_service_path(self, service_name=None): - return self._get_path('services/storageservices', service_name) - - def _get_hosted_service_path(self, service_name=None): - return self._get_path('services/hostedservices', service_name) - - def _get_deployment_path_using_slot(self, service_name, slot=None): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deploymentslots', slot) - - def _get_deployment_path_using_name(self, service_name, - deployment_name=None): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deployments', deployment_name) - - def _get_role_path(self, service_name, deployment_name, role_name=None): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deployments/' + deployment_name + - '/roles', role_name) - - def _get_role_instance_operations_path(self, service_name, deployment_name, - role_name=None): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deployments/' + deployment_name + - '/roleinstances', role_name) + '/Operations' - - def _get_roles_operations_path(self, service_name, deployment_name): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deployments/' + deployment_name + - '/roles/Operations', None) - - def _get_resource_extensions_path(self): - return self._get_path('services/resourceextensions', None) - - def _get_resource_extension_versions_path(self, publisher_name, extension_name): - return self._get_path('services/resourceextensions', - publisher_name + '/' + extension_name) - - def _get_dns_server_path(self, service_name, deployment_name, - dns_server_name=None): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deployments/' + deployment_name + - '/dnsservers', dns_server_name) - - def _get_capture_vm_image_path(self, service_name, deployment_name, role_name): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deployments/' + _str(deployment_name) + - '/roleinstances/' + _str(role_name) + '/Operations', - None) - - def _get_vm_image_path(self, image_name=None): - return self._get_path('services/vmimages', image_name) - - def _get_reserved_ip_path(self, name=None): - return self._get_path('services/networking/reservedips', name) - - def _get_data_disk_path(self, service_name, deployment_name, role_name, - lun=None): - return self._get_path('services/hostedservices/' + _str(service_name) + - '/deployments/' + _str(deployment_name) + - '/roles/' + _str(role_name) + '/DataDisks', lun) - - def _get_disk_path(self, disk_name=None): - return self._get_path('services/disks', disk_name) - - def _get_image_path(self, image_name=None): - return self._get_path('services/images', image_name) diff --git a/awx/lib/site-packages/azure/servicemanagement/sqldatabasemanagementservice.py b/awx/lib/site-packages/azure/servicemanagement/sqldatabasemanagementservice.py deleted file mode 100644 index 741b60f8b4..0000000000 --- a/awx/lib/site-packages/azure/servicemanagement/sqldatabasemanagementservice.py +++ /dev/null @@ -1,390 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - MANAGEMENT_HOST, - _parse_service_resources_response, - _validate_not_none, - ) -from azure.servicemanagement import ( - EventLog, - ServerQuota, - Servers, - ServiceObjective, - Database, - FirewallRule, - _SqlManagementXmlSerializer, - ) -from azure.servicemanagement.servicemanagementclient import ( - _ServiceManagementClient, - ) - -class SqlDatabaseManagementService(_ServiceManagementClient): - ''' Note that this class is a preliminary work on SQL Database - management. Since it lack a lot a features, final version - can be slightly different from the current one. - ''' - - def __init__(self, subscription_id=None, cert_file=None, - host=MANAGEMENT_HOST, request_session=None): - ''' - Initializes the sql database management service. - - subscription_id: Subscription to manage. - cert_file: - Path to .pem certificate file (httplib), or location of the - certificate in your Personal certificate store (winhttp) in the - CURRENT_USER\my\CertificateName format. - If a request_session is specified, then this is unused. - host: Live ServiceClient URL. Defaults to Azure public cloud. - request_session: - Session object to use for http requests. If this is specified, it - replaces the default use of httplib or winhttp. Also, the cert_file - parameter is unused when a session is passed in. - The session object handles authentication, and as such can support - multiple types of authentication: .pem certificate, oauth. - For example, you can pass in a Session instance from the requests - library. To use .pem certificate authentication with requests - library, set the path to the .pem file on the session.cert - attribute. - ''' - super(SqlDatabaseManagementService, self).__init__( - subscription_id, cert_file, host, request_session) - self.content_type = 'application/xml' - - #--Operations for sql servers ---------------------------------------- - def create_server(self, admin_login, admin_password, location): - ''' - Create a new Azure SQL Database server. - - admin_login: The administrator login name for the new server. - admin_password: The administrator login password for the new server. - location: The region to deploy the new server. - ''' - _validate_not_none('admin_login', admin_login) - _validate_not_none('admin_password', admin_password) - _validate_not_none('location', location) - response = self.perform_post( - self._get_servers_path(), - _SqlManagementXmlSerializer.create_server_to_xml( - admin_login, - admin_password, - location - ) - ) - - return _SqlManagementXmlSerializer.xml_to_create_server_response( - response.body) - - def set_server_admin_password(self, server_name, admin_password): - ''' - Reset the administrator password for a server. - - server_name: Name of the server to change the password. - admin_password: The new administrator password for the server. - ''' - _validate_not_none('server_name', server_name) - _validate_not_none('admin_password', admin_password) - return self._perform_post( - self._get_servers_path(server_name) + '?op=ResetPassword', - _SqlManagementXmlSerializer.set_server_admin_password_to_xml( - admin_password - ) - ) - - def delete_server(self, server_name): - ''' - Deletes an Azure SQL Database server (including all its databases). - - server_name: Name of the server you want to delete. - ''' - _validate_not_none('server_name', server_name) - return self._perform_delete( - self._get_servers_path(server_name)) - - def list_servers(self): - ''' - List the SQL servers defined on the account. - ''' - return self._perform_get(self._get_servers_path(), - Servers) - - def list_quotas(self, server_name): - ''' - Gets quotas for an Azure SQL Database Server. - - server_name: Name of the server. - ''' - _validate_not_none('server_name', server_name) - response = self._perform_get(self._get_quotas_path(server_name), - None) - return _parse_service_resources_response(response, ServerQuota) - - def get_server_event_logs(self, server_name, start_date, - interval_size_in_minutes, event_types=''): - ''' - Gets the event logs for an Azure SQL Database Server. - - server_name: Name of the server to retrieve the event logs from. - start_date: - The starting date and time of the events to retrieve in UTC format, - for example '2011-09-28 16:05:00'. - interval_size_in_minutes: - Size of the event logs to retrieve (in minutes). - Valid values are: 5, 60, or 1440. - event_types: - The event type of the log entries you want to retrieve. - Valid values are: - - connection_successful - - connection_failed - - connection_terminated - - deadlock - - throttling - - throttling_long_transaction - To return all event types pass in an empty string. - ''' - _validate_not_none('server_name', server_name) - _validate_not_none('start_date', start_date) - _validate_not_none('interval_size_in_minutes', interval_size_in_minutes) - _validate_not_none('event_types', event_types) - path = self._get_server_event_logs_path(server_name) + \ - '?startDate={0}&intervalSizeInMinutes={1}&eventTypes={2}'.format( - start_date, interval_size_in_minutes, event_types) - response = self._perform_get(path, None) - return _parse_service_resources_response(response, EventLog) - - #--Operations for firewall rules ------------------------------------------ - def create_firewall_rule(self, server_name, name, start_ip_address, - end_ip_address): - ''' - Creates an Azure SQL Database server firewall rule. - - server_name: Name of the server to set the firewall rule on. - name: The name of the new firewall rule. - start_ip_address: - The lowest IP address in the range of the server-level firewall - setting. IP addresses equal to or greater than this can attempt to - connect to the server. The lowest possible IP address is 0.0.0.0. - end_ip_address: - The highest IP address in the range of the server-level firewall - setting. IP addresses equal to or less than this can attempt to - connect to the server. The highest possible IP address is - 255.255.255.255. - ''' - _validate_not_none('server_name', server_name) - _validate_not_none('name', name) - _validate_not_none('start_ip_address', start_ip_address) - _validate_not_none('end_ip_address', end_ip_address) - return self._perform_post( - self._get_firewall_rules_path(server_name), - _SqlManagementXmlSerializer.create_firewall_rule_to_xml( - name, start_ip_address, end_ip_address - ) - ) - - def update_firewall_rule(self, server_name, name, start_ip_address, - end_ip_address): - ''' - Update a firewall rule for an Azure SQL Database server. - - server_name: Name of the server to set the firewall rule on. - name: The name of the firewall rule to update. - start_ip_address: - The lowest IP address in the range of the server-level firewall - setting. IP addresses equal to or greater than this can attempt to - connect to the server. The lowest possible IP address is 0.0.0.0. - end_ip_address: - The highest IP address in the range of the server-level firewall - setting. IP addresses equal to or less than this can attempt to - connect to the server. The highest possible IP address is - 255.255.255.255. - ''' - _validate_not_none('server_name', server_name) - _validate_not_none('name', name) - _validate_not_none('start_ip_address', start_ip_address) - _validate_not_none('end_ip_address', end_ip_address) - return self._perform_put( - self._get_firewall_rules_path(server_name, name), - _SqlManagementXmlSerializer.update_firewall_rule_to_xml( - name, start_ip_address, end_ip_address - ) - ) - - def delete_firewall_rule(self, server_name, name): - ''' - Deletes an Azure SQL Database server firewall rule. - - server_name: - Name of the server with the firewall rule you want to delete. - name: - Name of the firewall rule you want to delete. - ''' - _validate_not_none('server_name', server_name) - _validate_not_none('name', name) - return self._perform_delete( - self._get_firewall_rules_path(server_name, name)) - - def list_firewall_rules(self, server_name): - ''' - Retrieves the set of firewall rules for an Azure SQL Database Server. - - server_name: Name of the server. - ''' - _validate_not_none('server_name', server_name) - response = self._perform_get(self._get_firewall_rules_path(server_name), - None) - return _parse_service_resources_response(response, FirewallRule) - - def list_service_level_objectives(self, server_name): - ''' - Gets the service level objectives for an Azure SQL Database server. - - server_name: Name of the server. - ''' - _validate_not_none('server_name', server_name) - response = self._perform_get( - self._get_service_objectives_path(server_name), None) - return _parse_service_resources_response(response, ServiceObjective) - - #--Operations for sql databases ---------------------------------------- - def create_database(self, server_name, name, service_objective_id, - edition=None, collation_name=None, - max_size_bytes=None): - ''' - Creates a new Azure SQL Database. - - server_name: Name of the server to contain the new database. - name: - Required. The name for the new database. See Naming Requirements - in Azure SQL Database General Guidelines and Limitations and - Database Identifiers for more information. - service_objective_id: - Required. The GUID corresponding to the performance level for - Edition. See List Service Level Objectives for current values. - edition: - Optional. The Service Tier (Edition) for the new database. If - omitted, the default is Web. Valid values are Web, Business, - Basic, Standard, and Premium. See Azure SQL Database Service Tiers - (Editions) and Web and Business Edition Sunset FAQ for more - information. - collation_name: - Optional. The database collation. This can be any collation - supported by SQL. If omitted, the default collation is used. See - SQL Server Collation Support in Azure SQL Database General - Guidelines and Limitations for more information. - max_size_bytes: - Optional. Sets the maximum size, in bytes, for the database. This - value must be within the range of allowed values for Edition. If - omitted, the default value for the edition is used. See Azure SQL - Database Service Tiers (Editions) for current maximum databases - sizes. Convert MB or GB values to bytes. - 1 MB = 1048576 bytes. 1 GB = 1073741824 bytes. - ''' - _validate_not_none('server_name', server_name) - _validate_not_none('name', name) - _validate_not_none('service_objective_id', service_objective_id) - return self._perform_post( - self._get_databases_path(server_name), - _SqlManagementXmlSerializer.create_database_to_xml( - name, service_objective_id, edition, collation_name, - max_size_bytes - ) - ) - - def update_database(self, server_name, name, new_database_name=None, - service_objective_id=None, edition=None, - max_size_bytes=None): - ''' - Updates existing database details. - - server_name: Name of the server to contain the new database. - name: - Required. The name for the new database. See Naming Requirements - in Azure SQL Database General Guidelines and Limitations and - Database Identifiers for more information. - new_database_name: - Optional. The new name for the new database. - service_objective_id: - Optional. The new service level to apply to the database. For more - information about service levels, see Azure SQL Database Service - Tiers and Performance Levels. Use List Service Level Objectives to - get the correct ID for the desired service objective. - edition: - Optional. The new edition for the new database. - max_size_bytes: - Optional. The new size of the database in bytes. For information on - available sizes for each edition, see Azure SQL Database Service - Tiers (Editions). - ''' - _validate_not_none('server_name', server_name) - _validate_not_none('name', name) - return self._perform_put( - self._get_databases_path(server_name, name), - _SqlManagementXmlSerializer.update_database_to_xml( - new_database_name, service_objective_id, edition, - max_size_bytes - ) - ) - - def delete_database(self, server_name, name): - ''' - Deletes an Azure SQL Database. - - server_name: Name of the server where the database is located. - name: Name of the database to delete. - ''' - return self._perform_delete(self._get_databases_path(server_name, name)) - - def list_databases(self, name): - ''' - List the SQL databases defined on the specified server name - ''' - response = self._perform_get(self._get_list_databases_path(name), - None) - return _parse_service_resources_response(response, Database) - - - #--Helper functions -------------------------------------------------- - def _get_servers_path(self, server_name=None): - return self._get_path('services/sqlservers/servers', server_name) - - def _get_firewall_rules_path(self, server_name, name=None): - path = self._get_servers_path(server_name) + '/firewallrules' - if name: - path = path + '/' + name - return path - - def _get_databases_path(self, server_name, name=None): - path = self._get_servers_path(server_name) + '/databases' - if name: - path = path + '/' + name - return path - - def _get_server_event_logs_path(self, server_name): - return self._get_servers_path(server_name) + '/events' - - def _get_service_objectives_path(self, server_name): - return self._get_servers_path(server_name) + '/serviceobjectives' - - def _get_quotas_path(self, server_name, name=None): - path = self._get_servers_path(server_name) + '/serverquotas' - if name: - path = path + '/' + name - return path - - def _get_list_databases_path(self, name): - # *contentview=generic is mandatory* - return self._get_path('services/sqlservers/servers/', - name) + '/databases?contentview=generic' - diff --git a/awx/lib/site-packages/azure/servicemanagement/websitemanagementservice.py b/awx/lib/site-packages/azure/servicemanagement/websitemanagementservice.py deleted file mode 100644 index 3faf30562b..0000000000 --- a/awx/lib/site-packages/azure/servicemanagement/websitemanagementservice.py +++ /dev/null @@ -1,256 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - MANAGEMENT_HOST, - _str, - ) -from azure.servicemanagement import ( - WebSpaces, - WebSpace, - Sites, - Site, - MetricResponses, - MetricDefinitions, - PublishData, - _XmlSerializer, - ) -from azure.servicemanagement.servicemanagementclient import ( - _ServiceManagementClient, - ) - -class WebsiteManagementService(_ServiceManagementClient): - ''' Note that this class is a preliminary work on WebSite - management. Since it lack a lot a features, final version - can be slightly different from the current one. - ''' - - def __init__(self, subscription_id=None, cert_file=None, - host=MANAGEMENT_HOST, request_session=None): - ''' - Initializes the website management service. - - subscription_id: Subscription to manage. - cert_file: - Path to .pem certificate file (httplib), or location of the - certificate in your Personal certificate store (winhttp) in the - CURRENT_USER\my\CertificateName format. - If a request_session is specified, then this is unused. - host: Live ServiceClient URL. Defaults to Azure public cloud. - request_session: - Session object to use for http requests. If this is specified, it - replaces the default use of httplib or winhttp. Also, the cert_file - parameter is unused when a session is passed in. - The session object handles authentication, and as such can support - multiple types of authentication: .pem certificate, oauth. - For example, you can pass in a Session instance from the requests - library. To use .pem certificate authentication with requests - library, set the path to the .pem file on the session.cert - attribute. - ''' - super(WebsiteManagementService, self).__init__( - subscription_id, cert_file, host, request_session) - - #--Operations for web sites ---------------------------------------- - def list_webspaces(self): - ''' - List the webspaces defined on the account. - ''' - return self._perform_get(self._get_list_webspaces_path(), - WebSpaces) - - def get_webspace(self, webspace_name): - ''' - Get details of a specific webspace. - - webspace_name: The name of the webspace. - ''' - return self._perform_get(self._get_webspace_details_path(webspace_name), - WebSpace) - - def list_sites(self, webspace_name): - ''' - List the web sites defined on this webspace. - - webspace_name: The name of the webspace. - ''' - return self._perform_get(self._get_sites_path(webspace_name), - Sites) - - def get_site(self, webspace_name, website_name): - ''' - List the web sites defined on this webspace. - - webspace_name: The name of the webspace. - website_name: The name of the website. - ''' - return self._perform_get(self._get_sites_details_path(webspace_name, - website_name), - Site) - - def create_site(self, webspace_name, website_name, geo_region, host_names, - plan='VirtualDedicatedPlan', compute_mode='Shared', - server_farm=None, site_mode=None): - ''' - Create a website. - - webspace_name: The name of the webspace. - website_name: The name of the website. - geo_region: - The geographical region of the webspace that will be created. - host_names: - An array of fully qualified domain names for website. Only one - hostname can be specified in the azurewebsites.net domain. - The hostname should match the name of the website. Custom domains - can only be specified for Shared or Standard websites. - plan: - This value must be 'VirtualDedicatedPlan'. - compute_mode: - This value should be 'Shared' for the Free or Paid Shared - offerings, or 'Dedicated' for the Standard offering. The default - value is 'Shared'. If you set it to 'Dedicated', you must specify - a value for the server_farm parameter. - server_farm: - The name of the Server Farm associated with this website. This is - a required value for Standard mode. - site_mode: - Can be None, 'Limited' or 'Basic'. This value is 'Limited' for the - Free offering, and 'Basic' for the Paid Shared offering. Standard - mode does not use the site_mode parameter; it uses the compute_mode - parameter. - ''' - xml = _XmlSerializer.create_website_to_xml(webspace_name, website_name, geo_region, plan, host_names, compute_mode, server_farm, site_mode) - return self._perform_post( - self._get_sites_path(webspace_name), - xml, - Site) - - def delete_site(self, webspace_name, website_name, - delete_empty_server_farm=False, delete_metrics=False): - ''' - Delete a website. - - webspace_name: The name of the webspace. - website_name: The name of the website. - delete_empty_server_farm: - If the site being deleted is the last web site in a server farm, - you can delete the server farm by setting this to True. - delete_metrics: - To also delete the metrics for the site that you are deleting, you - can set this to True. - ''' - path = self._get_sites_details_path(webspace_name, website_name) - query = '' - if delete_empty_server_farm: - query += '&deleteEmptyServerFarm=true' - if delete_metrics: - query += '&deleteMetrics=true' - if query: - path = path + '?' + query.lstrip('&') - return self._perform_delete(path) - - def restart_site(self, webspace_name, website_name): - ''' - Restart a web site. - - webspace_name: The name of the webspace. - website_name: The name of the website. - ''' - return self._perform_post( - self._get_restart_path(webspace_name, website_name), - '') - - def get_historical_usage_metrics(self, webspace_name, website_name, - metrics = None, start_time=None, end_time=None, time_grain=None): - ''' - Get historical usage metrics. - - webspace_name: The name of the webspace. - website_name: The name of the website. - metrics: Optional. List of metrics name. Otherwise, all metrics returned. - start_time: Optional. An ISO8601 date. Otherwise, current hour is used. - end_time: Optional. An ISO8601 date. Otherwise, current time is used. - time_grain: Optional. A rollup name, as P1D. OTherwise, default rollup for the metrics is used. - More information and metrics name at: - http://msdn.microsoft.com/en-us/library/azure/dn166964.aspx - ''' - metrics = ('names='+','.join(metrics)) if metrics else '' - start_time = ('StartTime='+start_time) if start_time else '' - end_time = ('EndTime='+end_time) if end_time else '' - time_grain = ('TimeGrain='+time_grain) if time_grain else '' - parameters = ('&'.join(v for v in (metrics, start_time, end_time, time_grain) if v)) - parameters = '?'+parameters if parameters else '' - return self._perform_get(self._get_historical_usage_metrics_path(webspace_name, website_name) + parameters, - MetricResponses) - - def get_metric_definitions(self, webspace_name, website_name): - ''' - Get metric definitions of metrics available of this web site. - - webspace_name: The name of the webspace. - website_name: The name of the website. - ''' - return self._perform_get(self._get_metric_definitions_path(webspace_name, website_name), - MetricDefinitions) - - def get_publish_profile_xml(self, webspace_name, website_name): - ''' - Get a site's publish profile as a string - - webspace_name: The name of the webspace. - website_name: The name of the website. - ''' - return self._perform_get(self._get_publishxml_path(webspace_name, website_name), - None).body.decode("utf-8") - - def get_publish_profile(self, webspace_name, website_name): - ''' - Get a site's publish profile as an object - - webspace_name: The name of the webspace. - website_name: The name of the website. - ''' - return self._perform_get(self._get_publishxml_path(webspace_name, website_name), - PublishData) - - #--Helper functions -------------------------------------------------- - def _get_list_webspaces_path(self): - return self._get_path('services/webspaces', None) - - def _get_webspace_details_path(self, webspace_name): - return self._get_path('services/webspaces/', webspace_name) - - def _get_sites_path(self, webspace_name): - return self._get_path('services/webspaces/', - webspace_name) + '/sites' - - def _get_sites_details_path(self, webspace_name, website_name): - return self._get_path('services/webspaces/', - webspace_name) + '/sites/' + _str(website_name) - - def _get_restart_path(self, webspace_name, website_name): - return self._get_path('services/webspaces/', - webspace_name) + '/sites/' + _str(website_name) + '/restart/' - - def _get_historical_usage_metrics_path(self, webspace_name, website_name): - return self._get_path('services/webspaces/', - webspace_name) + '/sites/' + _str(website_name) + '/metrics/' - - def _get_metric_definitions_path(self, webspace_name, website_name): - return self._get_path('services/webspaces/', - webspace_name) + '/sites/' + _str(website_name) + '/metricdefinitions/' - - def _get_publishxml_path(self, webspace_name, website_name): - return self._get_path('services/webspaces/', - webspace_name) + '/sites/' + _str(website_name) + '/publishxml/' diff --git a/awx/lib/site-packages/azure/storage/__init__.py b/awx/lib/site-packages/azure/storage/__init__.py deleted file mode 100644 index 6089d3ff2a..0000000000 --- a/awx/lib/site-packages/azure/storage/__init__.py +++ /dev/null @@ -1,901 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import sys -import types - -from datetime import datetime -from dateutil import parser -from dateutil.tz import tzutc -from xml.dom import minidom -from azure import (WindowsAzureData, - WindowsAzureError, - METADATA_NS, - xml_escape, - _create_entry, - _decode_base64_to_text, - _decode_base64_to_bytes, - _encode_base64, - _fill_data_minidom, - _fill_instance_element, - _get_child_nodes, - _get_child_nodesNS, - _get_children_from_path, - _get_entry_properties, - _general_error_handler, - _list_of, - _parse_response_for_dict, - _sign_string, - _unicode_type, - _ERROR_CANNOT_SERIALIZE_VALUE_TO_ENTITY, - ) - -# x-ms-version for storage service. -X_MS_VERSION = '2012-02-12' - - -class EnumResultsBase(object): - - ''' base class for EnumResults. ''' - - def __init__(self): - self.prefix = u'' - self.marker = u'' - self.max_results = 0 - self.next_marker = u'' - - -class ContainerEnumResults(EnumResultsBase): - - ''' Blob Container list. ''' - - def __init__(self): - EnumResultsBase.__init__(self) - self.containers = _list_of(Container) - - def __iter__(self): - return iter(self.containers) - - def __len__(self): - return len(self.containers) - - def __getitem__(self, index): - return self.containers[index] - - -class Container(WindowsAzureData): - - ''' Blob container class. ''' - - def __init__(self): - self.name = u'' - self.url = u'' - self.properties = Properties() - self.metadata = {} - - -class Properties(WindowsAzureData): - - ''' Blob container's properties class. ''' - - def __init__(self): - self.last_modified = u'' - self.etag = u'' - - -class RetentionPolicy(WindowsAzureData): - - ''' RetentionPolicy in service properties. ''' - - def __init__(self): - self.enabled = False - self.__dict__['days'] = None - - def get_days(self): - # convert days to int value - return int(self.__dict__['days']) - - def set_days(self, value): - ''' set default days if days is set to empty. ''' - self.__dict__['days'] = value - - days = property(fget=get_days, fset=set_days) - - -class Logging(WindowsAzureData): - - ''' Logging class in service properties. ''' - - def __init__(self): - self.version = u'1.0' - self.delete = False - self.read = False - self.write = False - self.retention_policy = RetentionPolicy() - - -class Metrics(WindowsAzureData): - - ''' Metrics class in service properties. ''' - - def __init__(self): - self.version = u'1.0' - self.enabled = False - self.include_apis = None - self.retention_policy = RetentionPolicy() - - -class StorageServiceProperties(WindowsAzureData): - - ''' Storage Service Propeties class. ''' - - def __init__(self): - self.logging = Logging() - self.metrics = Metrics() - - -class AccessPolicy(WindowsAzureData): - - ''' Access Policy class in service properties. ''' - - def __init__(self, start=u'', expiry=u'', permission='u'): - self.start = start - self.expiry = expiry - self.permission = permission - - -class SignedIdentifier(WindowsAzureData): - - ''' Signed Identifier class for service properties. ''' - - def __init__(self): - self.id = u'' - self.access_policy = AccessPolicy() - - -class SignedIdentifiers(WindowsAzureData): - - ''' SignedIdentifier list. ''' - - def __init__(self): - self.signed_identifiers = _list_of(SignedIdentifier) - - def __iter__(self): - return iter(self.signed_identifiers) - - def __len__(self): - return len(self.signed_identifiers) - - def __getitem__(self, index): - return self.signed_identifiers[index] - - -class BlobEnumResults(EnumResultsBase): - - ''' Blob list.''' - - def __init__(self): - EnumResultsBase.__init__(self) - self.blobs = _list_of(Blob) - self.prefixes = _list_of(BlobPrefix) - self.delimiter = '' - - def __iter__(self): - return iter(self.blobs) - - def __len__(self): - return len(self.blobs) - - def __getitem__(self, index): - return self.blobs[index] - - -class BlobResult(bytes): - - def __new__(cls, blob, properties): - return bytes.__new__(cls, blob if blob else b'') - - def __init__(self, blob, properties): - self.properties = properties - - -class Blob(WindowsAzureData): - - ''' Blob class. ''' - - def __init__(self): - self.name = u'' - self.snapshot = u'' - self.url = u'' - self.properties = BlobProperties() - self.metadata = {} - - -class BlobProperties(WindowsAzureData): - - ''' Blob Properties ''' - - def __init__(self): - self.last_modified = u'' - self.etag = u'' - self.content_length = 0 - self.content_type = u'' - self.content_encoding = u'' - self.content_language = u'' - self.content_md5 = u'' - self.xms_blob_sequence_number = 0 - self.blob_type = u'' - self.lease_status = u'' - self.lease_state = u'' - self.lease_duration = u'' - self.copy_id = u'' - self.copy_source = u'' - self.copy_status = u'' - self.copy_progress = u'' - self.copy_completion_time = u'' - self.copy_status_description = u'' - - -class BlobPrefix(WindowsAzureData): - - ''' BlobPrefix in Blob. ''' - - def __init__(self): - self.name = '' - - -class BlobBlock(WindowsAzureData): - - ''' BlobBlock class ''' - - def __init__(self, id=None, size=None): - self.id = id - self.size = size - - -class BlobBlockList(WindowsAzureData): - - ''' BlobBlockList class ''' - - def __init__(self): - self.committed_blocks = [] - self.uncommitted_blocks = [] - - -class PageRange(WindowsAzureData): - - ''' Page Range for page blob. ''' - - def __init__(self): - self.start = 0 - self.end = 0 - - -class PageList(object): - - ''' Page list for page blob. ''' - - def __init__(self): - self.page_ranges = _list_of(PageRange) - - def __iter__(self): - return iter(self.page_ranges) - - def __len__(self): - return len(self.page_ranges) - - def __getitem__(self, index): - return self.page_ranges[index] - - -class QueueEnumResults(EnumResultsBase): - - ''' Queue list''' - - def __init__(self): - EnumResultsBase.__init__(self) - self.queues = _list_of(Queue) - - def __iter__(self): - return iter(self.queues) - - def __len__(self): - return len(self.queues) - - def __getitem__(self, index): - return self.queues[index] - - -class Queue(WindowsAzureData): - - ''' Queue class ''' - - def __init__(self): - self.name = u'' - self.url = u'' - self.metadata = {} - - -class QueueMessagesList(WindowsAzureData): - - ''' Queue message list. ''' - - def __init__(self): - self.queue_messages = _list_of(QueueMessage) - - def __iter__(self): - return iter(self.queue_messages) - - def __len__(self): - return len(self.queue_messages) - - def __getitem__(self, index): - return self.queue_messages[index] - - -class QueueMessage(WindowsAzureData): - - ''' Queue message class. ''' - - def __init__(self): - self.message_id = u'' - self.insertion_time = u'' - self.expiration_time = u'' - self.pop_receipt = u'' - self.time_next_visible = u'' - self.dequeue_count = u'' - self.message_text = u'' - - -class Entity(WindowsAzureData): - - ''' Entity class. The attributes of entity will be created dynamically. ''' - pass - - -class EntityProperty(WindowsAzureData): - - ''' Entity property. contains type and value. ''' - - def __init__(self, type=None, value=None): - self.type = type - self.value = value - - -class Table(WindowsAzureData): - - ''' Only for intellicens and telling user the return type. ''' - pass - - -def _parse_blob_enum_results_list(response): - respbody = response.body - return_obj = BlobEnumResults() - doc = minidom.parseString(respbody) - - for enum_results in _get_child_nodes(doc, 'EnumerationResults'): - for child in _get_children_from_path(enum_results, 'Blobs', 'Blob'): - return_obj.blobs.append(_fill_instance_element(child, Blob)) - - for child in _get_children_from_path(enum_results, - 'Blobs', - 'BlobPrefix'): - return_obj.prefixes.append( - _fill_instance_element(child, BlobPrefix)) - - for name, value in vars(return_obj).items(): - if name == 'blobs' or name == 'prefixes': - continue - value = _fill_data_minidom(enum_results, name, value) - if value is not None: - setattr(return_obj, name, value) - - return return_obj - - -def _update_storage_header(request): - ''' add additional headers for storage request. ''' - if request.body: - assert isinstance(request.body, bytes) - - # if it is PUT, POST, MERGE, DELETE, need to add content-length to header. - if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']: - request.headers.append(('Content-Length', str(len(request.body)))) - - # append addtional headers base on the service - request.headers.append(('x-ms-version', X_MS_VERSION)) - - # append x-ms-meta name, values to header - for name, value in request.headers: - if 'x-ms-meta-name-values' in name and value: - for meta_name, meta_value in value.items(): - request.headers.append(('x-ms-meta-' + meta_name, meta_value)) - request.headers.remove((name, value)) - break - return request - - -def _update_storage_blob_header(request, account_name, account_key): - ''' add additional headers for storage blob request. ''' - - request = _update_storage_header(request) - current_time = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') - request.headers.append(('x-ms-date', current_time)) - request.headers.append( - ('Content-Type', 'application/octet-stream Charset=UTF-8')) - request.headers.append(('Authorization', - _sign_storage_blob_request(request, - account_name, - account_key))) - - return request.headers - - -def _update_storage_queue_header(request, account_name, account_key): - ''' add additional headers for storage queue request. ''' - return _update_storage_blob_header(request, account_name, account_key) - - -def _update_storage_table_header(request): - ''' add additional headers for storage table request. ''' - - request = _update_storage_header(request) - for name, _ in request.headers: - if name.lower() == 'content-type': - break - else: - request.headers.append(('Content-Type', 'application/atom+xml')) - request.headers.append(('DataServiceVersion', '2.0;NetFx')) - request.headers.append(('MaxDataServiceVersion', '2.0;NetFx')) - current_time = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') - request.headers.append(('x-ms-date', current_time)) - request.headers.append(('Date', current_time)) - return request.headers - - -def _sign_storage_blob_request(request, account_name, account_key): - ''' - Returns the signed string for blob request which is used to set - Authorization header. This is also used to sign queue request. - ''' - - uri_path = request.path.split('?')[0] - - # method to sign - string_to_sign = request.method + '\n' - - # get headers to sign - headers_to_sign = [ - 'content-encoding', 'content-language', 'content-length', - 'content-md5', 'content-type', 'date', 'if-modified-since', - 'if-match', 'if-none-match', 'if-unmodified-since', 'range'] - - request_header_dict = dict((name.lower(), value) - for name, value in request.headers if value) - string_to_sign += '\n'.join(request_header_dict.get(x, '') - for x in headers_to_sign) + '\n' - - # get x-ms header to sign - x_ms_headers = [] - for name, value in request.headers: - if 'x-ms' in name: - x_ms_headers.append((name.lower(), value)) - x_ms_headers.sort() - for name, value in x_ms_headers: - if value: - string_to_sign += ''.join([name, ':', value, '\n']) - - # get account_name and uri path to sign - string_to_sign += '/' + account_name + uri_path - - # get query string to sign if it is not table service - query_to_sign = request.query - query_to_sign.sort() - - current_name = '' - for name, value in query_to_sign: - if value: - if current_name != name: - string_to_sign += '\n' + name + ':' + value - else: - string_to_sign += '\n' + ',' + value - - # sign the request - auth_string = 'SharedKey ' + account_name + ':' + \ - _sign_string(account_key, string_to_sign) - return auth_string - - -def _sign_storage_table_request(request, account_name, account_key): - uri_path = request.path.split('?')[0] - - string_to_sign = request.method + '\n' - headers_to_sign = ['content-md5', 'content-type', 'date'] - request_header_dict = dict((name.lower(), value) - for name, value in request.headers if value) - string_to_sign += '\n'.join(request_header_dict.get(x, '') - for x in headers_to_sign) + '\n' - - # get account_name and uri path to sign - string_to_sign += ''.join(['/', account_name, uri_path]) - - for name, value in request.query: - if name == 'comp' and uri_path == '/': - string_to_sign += '?comp=' + value - break - - # sign the request - auth_string = 'SharedKey ' + account_name + ':' + \ - _sign_string(account_key, string_to_sign) - return auth_string - - -def _to_python_bool(value): - if value.lower() == 'true': - return True - return False - - -def _to_entity_int(data): - int_max = (2 << 30) - 1 - if data > (int_max) or data < (int_max + 1) * (-1): - return 'Edm.Int64', str(data) - else: - return 'Edm.Int32', str(data) - - -def _to_entity_bool(value): - if value: - return 'Edm.Boolean', 'true' - return 'Edm.Boolean', 'false' - - -def _to_entity_datetime(value): - # Azure expects the date value passed in to be UTC. - # Azure will always return values as UTC. - # If a date is passed in without timezone info, it is assumed to be UTC. - if value.tzinfo: - value = value.astimezone(tzutc()) - return 'Edm.DateTime', value.strftime('%Y-%m-%dT%H:%M:%SZ') - - -def _to_entity_float(value): - return 'Edm.Double', str(value) - - -def _to_entity_property(value): - if value.type == 'Edm.Binary': - return value.type, _encode_base64(value.value) - - return value.type, str(value.value) - - -def _to_entity_none(value): - return None, None - - -def _to_entity_str(value): - return 'Edm.String', value - - -# Tables of conversions to and from entity types. We support specific -# datatypes, and beyond that the user can use an EntityProperty to get -# custom data type support. - -def _from_entity_binary(value): - return EntityProperty('Edm.Binary', _decode_base64_to_bytes(value)) - - -def _from_entity_int(value): - return int(value) - - -def _from_entity_datetime(value): - # Note that Azure always returns UTC datetime, and dateutil parser - # will set the tzinfo on the date it returns - return parser.parse(value) - -_ENTITY_TO_PYTHON_CONVERSIONS = { - 'Edm.Binary': _from_entity_binary, - 'Edm.Int32': _from_entity_int, - 'Edm.Int64': _from_entity_int, - 'Edm.Double': float, - 'Edm.Boolean': _to_python_bool, - 'Edm.DateTime': _from_entity_datetime, -} - -# Conversion from Python type to a function which returns a tuple of the -# type string and content string. -_PYTHON_TO_ENTITY_CONVERSIONS = { - int: _to_entity_int, - bool: _to_entity_bool, - datetime: _to_entity_datetime, - float: _to_entity_float, - EntityProperty: _to_entity_property, - str: _to_entity_str, -} - -if sys.version_info < (3,): - _PYTHON_TO_ENTITY_CONVERSIONS.update({ - long: _to_entity_int, - types.NoneType: _to_entity_none, - unicode: _to_entity_str, - }) - - -def _convert_entity_to_xml(source): - ''' Converts an entity object to xml to send. - - The entity format is: - <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom"> - <title /> - <updated>2008-09-18T23:46:19.3857256Z</updated> - <author> - <name /> - </author> - <id /> - <content type="application/xml"> - <m:properties> - <d:Address>Mountain View</d:Address> - <d:Age m:type="Edm.Int32">23</d:Age> - <d:AmountDue m:type="Edm.Double">200.23</d:AmountDue> - <d:BinaryData m:type="Edm.Binary" m:null="true" /> - <d:CustomerCode m:type="Edm.Guid">c9da6455-213d-42c9-9a79-3e9149a57833</d:CustomerCode> - <d:CustomerSince m:type="Edm.DateTime">2008-07-10T00:00:00</d:CustomerSince> - <d:IsActive m:type="Edm.Boolean">true</d:IsActive> - <d:NumOfOrders m:type="Edm.Int64">255</d:NumOfOrders> - <d:PartitionKey>mypartitionkey</d:PartitionKey> - <d:RowKey>myrowkey1</d:RowKey> - <d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp> - </m:properties> - </content> - </entry> - ''' - - # construct the entity body included in <m:properties> and </m:properties> - entity_body = '<m:properties xml:space="preserve">{properties}</m:properties>' - - if isinstance(source, WindowsAzureData): - source = vars(source) - - properties_str = '' - - # set properties type for types we know if value has no type info. - # if value has type info, then set the type to value.type - for name, value in source.items(): - mtype = '' - conv = _PYTHON_TO_ENTITY_CONVERSIONS.get(type(value)) - if conv is None and sys.version_info >= (3,) and value is None: - conv = _to_entity_none - if conv is None: - raise WindowsAzureError( - _ERROR_CANNOT_SERIALIZE_VALUE_TO_ENTITY.format( - type(value).__name__)) - - mtype, value = conv(value) - - # form the property node - properties_str += ''.join(['<d:', name]) - if value is None: - properties_str += ' m:null="true" />' - else: - if mtype: - properties_str += ''.join([' m:type="', mtype, '"']) - properties_str += ''.join(['>', - xml_escape(value), '</d:', name, '>']) - - if sys.version_info < (3,): - if isinstance(properties_str, unicode): - properties_str = properties_str.encode('utf-8') - - # generate the entity_body - entity_body = entity_body.format(properties=properties_str) - xmlstr = _create_entry(entity_body) - return xmlstr - - -def _convert_table_to_xml(table_name): - ''' - Create xml to send for a given table name. Since xml format for table is - the same as entity and the only difference is that table has only one - property 'TableName', so we just call _convert_entity_to_xml. - - table_name: the name of the table - ''' - return _convert_entity_to_xml({'TableName': table_name}) - - -def _convert_block_list_to_xml(block_id_list): - ''' - Convert a block list to xml to send. - - block_id_list: - a str list containing the block ids that are used in put_block_list. - Only get block from latest blocks. - ''' - if block_id_list is None: - return '' - xml = '<?xml version="1.0" encoding="utf-8"?><BlockList>' - for value in block_id_list: - xml += '<Latest>{0}</Latest>'.format(_encode_base64(value)) - - return xml + '</BlockList>' - - -def _create_blob_result(response): - blob_properties = _parse_response_for_dict(response) - return BlobResult(response.body, blob_properties) - - -def _convert_response_to_block_list(response): - ''' - Converts xml response to block list class. - ''' - blob_block_list = BlobBlockList() - - xmldoc = minidom.parseString(response.body) - for xml_block in _get_children_from_path(xmldoc, - 'BlockList', - 'CommittedBlocks', - 'Block'): - xml_block_id = _decode_base64_to_text( - _get_child_nodes(xml_block, 'Name')[0].firstChild.nodeValue) - xml_block_size = int( - _get_child_nodes(xml_block, 'Size')[0].firstChild.nodeValue) - blob_block_list.committed_blocks.append( - BlobBlock(xml_block_id, xml_block_size)) - - for xml_block in _get_children_from_path(xmldoc, - 'BlockList', - 'UncommittedBlocks', - 'Block'): - xml_block_id = _decode_base64_to_text( - _get_child_nodes(xml_block, 'Name')[0].firstChild.nodeValue) - xml_block_size = int( - _get_child_nodes(xml_block, 'Size')[0].firstChild.nodeValue) - blob_block_list.uncommitted_blocks.append( - BlobBlock(xml_block_id, xml_block_size)) - - return blob_block_list - - -def _remove_prefix(name): - colon = name.find(':') - if colon != -1: - return name[colon + 1:] - return name - - -def _convert_response_to_entity(response): - if response is None: - return response - return _convert_xml_to_entity(response.body) - - -def _convert_xml_to_entity(xmlstr): - ''' Convert xml response to entity. - - The format of entity: - <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom"> - <title /> - <updated>2008-09-18T23:46:19.3857256Z</updated> - <author> - <name /> - </author> - <id /> - <content type="application/xml"> - <m:properties> - <d:Address>Mountain View</d:Address> - <d:Age m:type="Edm.Int32">23</d:Age> - <d:AmountDue m:type="Edm.Double">200.23</d:AmountDue> - <d:BinaryData m:type="Edm.Binary" m:null="true" /> - <d:CustomerCode m:type="Edm.Guid">c9da6455-213d-42c9-9a79-3e9149a57833</d:CustomerCode> - <d:CustomerSince m:type="Edm.DateTime">2008-07-10T00:00:00</d:CustomerSince> - <d:IsActive m:type="Edm.Boolean">true</d:IsActive> - <d:NumOfOrders m:type="Edm.Int64">255</d:NumOfOrders> - <d:PartitionKey>mypartitionkey</d:PartitionKey> - <d:RowKey>myrowkey1</d:RowKey> - <d:Timestamp m:type="Edm.DateTime">0001-01-01T00:00:00</d:Timestamp> - </m:properties> - </content> - </entry> - ''' - xmldoc = minidom.parseString(xmlstr) - - xml_properties = None - for entry in _get_child_nodes(xmldoc, 'entry'): - for content in _get_child_nodes(entry, 'content'): - # TODO: Namespace - xml_properties = _get_child_nodesNS( - content, METADATA_NS, 'properties') - - if not xml_properties: - return None - - entity = Entity() - # extract each property node and get the type from attribute and node value - for xml_property in xml_properties[0].childNodes: - name = _remove_prefix(xml_property.nodeName) - - if xml_property.firstChild: - value = xml_property.firstChild.nodeValue - else: - value = '' - - isnull = xml_property.getAttributeNS(METADATA_NS, 'null') - mtype = xml_property.getAttributeNS(METADATA_NS, 'type') - - # if not isnull and no type info, then it is a string and we just - # need the str type to hold the property. - if not isnull and not mtype: - _set_entity_attr(entity, name, value) - elif isnull == 'true': - if mtype: - property = EntityProperty(mtype, None) - else: - property = EntityProperty('Edm.String', None) - else: # need an object to hold the property - conv = _ENTITY_TO_PYTHON_CONVERSIONS.get(mtype) - if conv is not None: - property = conv(value) - else: - property = EntityProperty(mtype, value) - _set_entity_attr(entity, name, property) - - # extract id, updated and name value from feed entry and set them of - # rule. - for name, value in _get_entry_properties(xmlstr, True).items(): - if name in ['etag']: - _set_entity_attr(entity, name, value) - - return entity - - -def _set_entity_attr(entity, name, value): - try: - setattr(entity, name, value) - except UnicodeEncodeError: - # Python 2 doesn't support unicode attribute names, so we'll - # add them and access them directly through the dictionary - entity.__dict__[name] = value - - -def _convert_xml_to_table(xmlstr): - ''' Converts the xml response to table class. - Simply call convert_xml_to_entity and extract the table name, and add - updated and author info - ''' - table = Table() - entity = _convert_xml_to_entity(xmlstr) - setattr(table, 'name', entity.TableName) - for name, value in _get_entry_properties(xmlstr, False).items(): - setattr(table, name, value) - return table - - -def _storage_error_handler(http_error): - ''' Simple error handler for storage service. ''' - return _general_error_handler(http_error) - -# make these available just from storage. -from azure.storage.blobservice import BlobService -from azure.storage.queueservice import QueueService -from azure.storage.tableservice import TableService -from azure.storage.cloudstorageaccount import CloudStorageAccount -from azure.storage.sharedaccesssignature import ( - SharedAccessSignature, - SharedAccessPolicy, - Permission, - WebResource, - ) diff --git a/awx/lib/site-packages/azure/storage/blobservice.py b/awx/lib/site-packages/azure/storage/blobservice.py deleted file mode 100644 index f6b060eccd..0000000000 --- a/awx/lib/site-packages/azure/storage/blobservice.py +++ /dev/null @@ -1,2178 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - WindowsAzureError, - BLOB_SERVICE_HOST_BASE, - DEV_BLOB_HOST, - _ERROR_VALUE_NEGATIVE, - _ERROR_PAGE_BLOB_SIZE_ALIGNMENT, - _convert_class_to_xml, - _dont_fail_not_exist, - _dont_fail_on_exist, - _encode_base64, - _get_request_body, - _get_request_body_bytes_only, - _int_or_none, - _parse_enum_results_list, - _parse_response, - _parse_response_for_dict, - _parse_response_for_dict_filter, - _parse_response_for_dict_prefix, - _parse_simple_list, - _str, - _str_or_none, - _update_request_uri_query_local_storage, - _validate_type_bytes, - _validate_not_none, - ) -from azure.http import HTTPRequest -from azure.storage import ( - Container, - ContainerEnumResults, - PageList, - PageRange, - SignedIdentifiers, - StorageServiceProperties, - _convert_block_list_to_xml, - _convert_response_to_block_list, - _create_blob_result, - _parse_blob_enum_results_list, - _update_storage_blob_header, - ) -from azure.storage.storageclient import _StorageClient -from os import path -import sys -if sys.version_info >= (3,): - from io import BytesIO -else: - from cStringIO import StringIO as BytesIO - -# Keep this value sync with _ERROR_PAGE_BLOB_SIZE_ALIGNMENT -_PAGE_SIZE = 512 - - -class BlobService(_StorageClient): - - ''' - This is the main class managing Blob resources. - ''' - - def __init__(self, account_name=None, account_key=None, protocol='https', - host_base=BLOB_SERVICE_HOST_BASE, dev_host=DEV_BLOB_HOST): - ''' - account_name: your storage account name, required for all operations. - account_key: your storage account key, required for all operations. - protocol: Optional. Protocol. Defaults to https. - host_base: - Optional. Live host base url. Defaults to Azure url. Override this - for on-premise. - dev_host: Optional. Dev host url. Defaults to localhost. - ''' - self._BLOB_MAX_DATA_SIZE = 64 * 1024 * 1024 - self._BLOB_MAX_CHUNK_DATA_SIZE = 4 * 1024 * 1024 - super(BlobService, self).__init__( - account_name, account_key, protocol, host_base, dev_host) - - def make_blob_url(self, container_name, blob_name, account_name=None, - protocol=None, host_base=None): - ''' - Creates the url to access a blob. - - container_name: Name of container. - blob_name: Name of blob. - account_name: - Name of the storage account. If not specified, uses the account - specified when BlobService was initialized. - protocol: - Protocol to use: 'http' or 'https'. If not specified, uses the - protocol specified when BlobService was initialized. - host_base: - Live host base url. If not specified, uses the host base specified - when BlobService was initialized. - ''' - - if not account_name: - account_name = self.account_name - if not protocol: - protocol = self.protocol - if not host_base: - host_base = self.host_base - - return '{0}://{1}{2}/{3}/{4}'.format(protocol, - account_name, - host_base, - container_name, - blob_name) - - def list_containers(self, prefix=None, marker=None, maxresults=None, - include=None): - ''' - The List Containers operation returns a list of the containers under - the specified account. - - prefix: - Optional. Filters the results to return only containers whose names - begin with the specified prefix. - marker: - Optional. A string value that identifies the portion of the list to - be returned with the next list operation. - maxresults: - Optional. Specifies the maximum number of containers to return. - include: - Optional. Include this parameter to specify that the container's - metadata be returned as part of the response body. set this - parameter to string 'metadata' to get container's metadata. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/?comp=list' - request.query = [ - ('prefix', _str_or_none(prefix)), - ('marker', _str_or_none(marker)), - ('maxresults', _int_or_none(maxresults)), - ('include', _str_or_none(include)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_enum_results_list(response, - ContainerEnumResults, - "Containers", - Container) - - def create_container(self, container_name, x_ms_meta_name_values=None, - x_ms_blob_public_access=None, fail_on_exist=False): - ''' - Creates a new container under the specified account. If the container - with the same name already exists, the operation fails. - - container_name: Name of container to create. - x_ms_meta_name_values: - Optional. A dict with name_value pairs to associate with the - container as metadata. Example:{'Category':'test'} - x_ms_blob_public_access: - Optional. Possible values include: container, blob - fail_on_exist: - specify whether to throw an exception when the container exists. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '?restype=container' - request.headers = [ - ('x-ms-meta-name-values', x_ms_meta_name_values), - ('x-ms-blob-public-access', _str_or_none(x_ms_blob_public_access)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - if not fail_on_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_on_exist(ex) - return False - else: - self._perform_request(request) - return True - - def get_container_properties(self, container_name, x_ms_lease_id=None): - ''' - Returns all user-defined metadata and system properties for the - specified container. - - container_name: Name of existing container. - x_ms_lease_id: - If specified, get_container_properties only succeeds if the - container's lease is active and matches this ID. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '?restype=container' - request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict(response) - - def get_container_metadata(self, container_name, x_ms_lease_id=None): - ''' - Returns all user-defined metadata for the specified container. The - metadata will be in returned dictionary['x-ms-meta-(name)']. - - container_name: Name of existing container. - x_ms_lease_id: - If specified, get_container_metadata only succeeds if the - container's lease is active and matches this ID. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '?restype=container&comp=metadata' - request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict_prefix(response, prefixes=['x-ms-meta']) - - def set_container_metadata(self, container_name, - x_ms_meta_name_values=None, x_ms_lease_id=None): - ''' - Sets one or more user-defined name-value pairs for the specified - container. - - container_name: Name of existing container. - x_ms_meta_name_values: - A dict containing name, value for metadata. - Example: {'category':'test'} - x_ms_lease_id: - If specified, set_container_metadata only succeeds if the - container's lease is active and matches this ID. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '?restype=container&comp=metadata' - request.headers = [ - ('x-ms-meta-name-values', x_ms_meta_name_values), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def get_container_acl(self, container_name, x_ms_lease_id=None): - ''' - Gets the permissions for the specified container. - - container_name: Name of existing container. - x_ms_lease_id: - If specified, get_container_acl only succeeds if the - container's lease is active and matches this ID. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '?restype=container&comp=acl' - request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response(response, SignedIdentifiers) - - def set_container_acl(self, container_name, signed_identifiers=None, - x_ms_blob_public_access=None, x_ms_lease_id=None): - ''' - Sets the permissions for the specified container. - - container_name: Name of existing container. - signed_identifiers: SignedIdentifers instance - x_ms_blob_public_access: - Optional. Possible values include: container, blob - x_ms_lease_id: - If specified, set_container_acl only succeeds if the - container's lease is active and matches this ID. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '?restype=container&comp=acl' - request.headers = [ - ('x-ms-blob-public-access', _str_or_none(x_ms_blob_public_access)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ] - request.body = _get_request_body( - _convert_class_to_xml(signed_identifiers)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def delete_container(self, container_name, fail_not_exist=False, - x_ms_lease_id=None): - ''' - Marks the specified container for deletion. - - container_name: Name of container to delete. - fail_not_exist: - Specify whether to throw an exception when the container doesn't - exist. - x_ms_lease_id: Required if the container has an active lease. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '?restype=container' - request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - if not fail_not_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_not_exist(ex) - return False - else: - self._perform_request(request) - return True - - def lease_container(self, container_name, x_ms_lease_action, - x_ms_lease_id=None, x_ms_lease_duration=60, - x_ms_lease_break_period=None, - x_ms_proposed_lease_id=None): - ''' - Establishes and manages a lock on a container for delete operations. - The lock duration can be 15 to 60 seconds, or can be infinite. - - container_name: Name of existing container. - x_ms_lease_action: - Required. Possible values: acquire|renew|release|break|change - x_ms_lease_id: Required if the container has an active lease. - x_ms_lease_duration: - Specifies the duration of the lease, in seconds, or negative one - (-1) for a lease that never expires. A non-infinite lease can be - between 15 and 60 seconds. A lease duration cannot be changed - using renew or change. For backwards compatibility, the default is - 60, and the value is only used on an acquire operation. - x_ms_lease_break_period: - Optional. For a break operation, this is the proposed duration of - seconds that the lease should continue before it is broken, between - 0 and 60 seconds. This break period is only used if it is shorter - than the time remaining on the lease. If longer, the time remaining - on the lease is used. A new lease will not be available before the - break period has expired, but the lease may be held for longer than - the break period. If this header does not appear with a break - operation, a fixed-duration lease breaks after the remaining lease - period elapses, and an infinite lease breaks immediately. - x_ms_proposed_lease_id: - Optional for acquire, required for change. Proposed lease ID, in a - GUID string format. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('x_ms_lease_action', x_ms_lease_action) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '?restype=container&comp=lease' - request.headers = [ - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-lease-action', _str_or_none(x_ms_lease_action)), - ('x-ms-lease-duration', - _str_or_none( - x_ms_lease_duration if x_ms_lease_action == 'acquire'\ - else None)), - ('x-ms-lease-break-period', _str_or_none(x_ms_lease_break_period)), - ('x-ms-proposed-lease-id', _str_or_none(x_ms_proposed_lease_id)), - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict_filter( - response, - filter=['x-ms-lease-id', 'x-ms-lease-time']) - - def list_blobs(self, container_name, prefix=None, marker=None, - maxresults=None, include=None, delimiter=None): - ''' - Returns the list of blobs under the specified container. - - container_name: Name of existing container. - prefix: - Optional. Filters the results to return only blobs whose names - begin with the specified prefix. - marker: - Optional. A string value that identifies the portion of the list - to be returned with the next list operation. The operation returns - a marker value within the response body if the list returned was - not complete. The marker value may then be used in a subsequent - call to request the next set of list items. The marker value is - opaque to the client. - maxresults: - Optional. Specifies the maximum number of blobs to return, - including all BlobPrefix elements. If the request does not specify - maxresults or specifies a value greater than 5,000, the server will - return up to 5,000 items. Setting maxresults to a value less than - or equal to zero results in error response code 400 (Bad Request). - include: - Optional. Specifies one or more datasets to include in the - response. To specify more than one of these options on the URI, - you must separate each option with a comma. Valid values are: - snapshots: - Specifies that snapshots should be included in the - enumeration. Snapshots are listed from oldest to newest in - the response. - metadata: - Specifies that blob metadata be returned in the response. - uncommittedblobs: - Specifies that blobs for which blocks have been uploaded, - but which have not been committed using Put Block List - (REST API), be included in the response. - copy: - Version 2012-02-12 and newer. Specifies that metadata - related to any current or previous Copy Blob operation - should be included in the response. - delimiter: - Optional. When the request includes this parameter, the operation - returns a BlobPrefix element in the response body that acts as a - placeholder for all blobs whose names begin with the same - substring up to the appearance of the delimiter character. The - delimiter may be a single character or a string. - ''' - _validate_not_none('container_name', container_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '?restype=container&comp=list' - request.query = [ - ('prefix', _str_or_none(prefix)), - ('delimiter', _str_or_none(delimiter)), - ('marker', _str_or_none(marker)), - ('maxresults', _int_or_none(maxresults)), - ('include', _str_or_none(include)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_blob_enum_results_list(response) - - def set_blob_service_properties(self, storage_service_properties, - timeout=None): - ''' - Sets the properties of a storage account's Blob service, including - Windows Azure Storage Analytics. You can also use this operation to - set the default request version for all incoming requests that do not - have a version specified. - - storage_service_properties: a StorageServiceProperties object. - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - _validate_not_none('storage_service_properties', - storage_service_properties) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/?restype=service&comp=properties' - request.query = [('timeout', _int_or_none(timeout))] - request.body = _get_request_body( - _convert_class_to_xml(storage_service_properties)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def get_blob_service_properties(self, timeout=None): - ''' - Gets the properties of a storage account's Blob service, including - Windows Azure Storage Analytics. - - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/?restype=service&comp=properties' - request.query = [('timeout', _int_or_none(timeout))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response(response, StorageServiceProperties) - - def get_blob_properties(self, container_name, blob_name, - x_ms_lease_id=None): - ''' - Returns all user-defined metadata, standard HTTP properties, and - system properties for the blob. - - container_name: Name of existing container. - blob_name: Name of existing blob. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'HEAD' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '/' + _str(blob_name) + '' - request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - - response = self._perform_request(request) - - return _parse_response_for_dict(response) - - def set_blob_properties(self, container_name, blob_name, - x_ms_blob_cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_md5=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_lease_id=None): - ''' - Sets system properties on the blob. - - container_name: Name of existing container. - blob_name: Name of existing blob. - x_ms_blob_cache_control: - Optional. Modifies the cache control string for the blob. - x_ms_blob_content_type: Optional. Sets the blob's content type. - x_ms_blob_content_md5: Optional. Sets the blob's MD5 hash. - x_ms_blob_content_encoding: Optional. Sets the blob's content encoding. - x_ms_blob_content_language: Optional. Sets the blob's content language. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=properties' - request.headers = [ - ('x-ms-blob-cache-control', _str_or_none(x_ms_blob_cache_control)), - ('x-ms-blob-content-type', _str_or_none(x_ms_blob_content_type)), - ('x-ms-blob-content-md5', _str_or_none(x_ms_blob_content_md5)), - ('x-ms-blob-content-encoding', - _str_or_none(x_ms_blob_content_encoding)), - ('x-ms-blob-content-language', - _str_or_none(x_ms_blob_content_language)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def put_blob(self, container_name, blob_name, blob, x_ms_blob_type, - content_encoding=None, content_language=None, - content_md5=None, cache_control=None, - x_ms_blob_content_type=None, x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, x_ms_meta_name_values=None, - x_ms_lease_id=None, x_ms_blob_content_length=None, - x_ms_blob_sequence_number=None): - ''' - Creates a new block blob or page blob, or updates the content of an - existing block blob. - - See put_block_blob_from_* and put_page_blob_from_* for high level - functions that handle the creation and upload of large blobs with - automatic chunking and progress notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - blob: - For BlockBlob: - Content of blob as bytes (size < 64MB). For larger size, you - must call put_block and put_block_list to set content of blob. - For PageBlob: - Use None and call put_page to set content of blob. - x_ms_blob_type: Required. Could be BlockBlob or PageBlob. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - x_ms_blob_content_length: - Required for page blobs. This header specifies the maximum size - for the page blob, up to 1 TB. The page blob size must be aligned - to a 512-byte boundary. - x_ms_blob_sequence_number: - Optional. Set for page blobs only. The sequence number is a - user-controlled value that you can use to track requests. The - value of the sequence number must be between 0 and 2^63 - 1. The - default value is 0. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('x_ms_blob_type', x_ms_blob_type) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '/' + _str(blob_name) + '' - request.headers = [ - ('x-ms-blob-type', _str_or_none(x_ms_blob_type)), - ('Content-Encoding', _str_or_none(content_encoding)), - ('Content-Language', _str_or_none(content_language)), - ('Content-MD5', _str_or_none(content_md5)), - ('Cache-Control', _str_or_none(cache_control)), - ('x-ms-blob-content-type', _str_or_none(x_ms_blob_content_type)), - ('x-ms-blob-content-encoding', - _str_or_none(x_ms_blob_content_encoding)), - ('x-ms-blob-content-language', - _str_or_none(x_ms_blob_content_language)), - ('x-ms-blob-content-md5', _str_or_none(x_ms_blob_content_md5)), - ('x-ms-blob-cache-control', _str_or_none(x_ms_blob_cache_control)), - ('x-ms-meta-name-values', x_ms_meta_name_values), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-blob-content-length', - _str_or_none(x_ms_blob_content_length)), - ('x-ms-blob-sequence-number', - _str_or_none(x_ms_blob_sequence_number)) - ] - request.body = _get_request_body_bytes_only('blob', blob) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def put_block_blob_from_path(self, container_name, blob_name, file_path, - content_encoding=None, content_language=None, - content_md5=None, cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, - x_ms_meta_name_values=None, - x_ms_lease_id=None, progress_callback=None): - ''' - Creates a new block blob from a file path, or updates the content of an - existing block blob, with automatic chunking and progress notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - file_path: Path of the file to upload as the blob content. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob, or None if the total size is unknown. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('file_path', file_path) - - count = path.getsize(file_path) - with open(file_path, 'rb') as stream: - self.put_block_blob_from_file(container_name, - blob_name, - stream, - count, - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id, - progress_callback) - - def put_block_blob_from_file(self, container_name, blob_name, stream, - count=None, content_encoding=None, - content_language=None, content_md5=None, - cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, - x_ms_meta_name_values=None, - x_ms_lease_id=None, progress_callback=None): - ''' - Creates a new block blob from a file/stream, or updates the content of - an existing block blob, with automatic chunking and progress - notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - stream: Opened file/stream to upload as the blob content. - count: - Number of bytes to read from the stream. This is optional, but - should be supplied for optimal performance. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob, or None if the total size is unknown. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('stream', stream) - - if count and count < self._BLOB_MAX_DATA_SIZE: - if progress_callback: - progress_callback(0, count) - - data = stream.read(count) - self.put_blob(container_name, - blob_name, - data, - 'BlockBlob', - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id) - - if progress_callback: - progress_callback(count, count) - else: - if progress_callback: - progress_callback(0, count) - - self.put_blob(container_name, - blob_name, - None, - 'BlockBlob', - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id) - - remain_bytes = count - block_ids = [] - block_index = 0 - index = 0 - while True: - request_count = self._BLOB_MAX_CHUNK_DATA_SIZE\ - if remain_bytes is None else min( - remain_bytes, - self._BLOB_MAX_CHUNK_DATA_SIZE) - data = stream.read(request_count) - if data: - length = len(data) - index += length - remain_bytes = remain_bytes - \ - length if remain_bytes else None - block_id = '{0:08d}'.format(block_index) - self.put_block(container_name, blob_name, - data, block_id, x_ms_lease_id=x_ms_lease_id) - block_ids.append(block_id) - block_index += 1 - if progress_callback: - progress_callback(index, count) - else: - break - - self.put_block_list(container_name, blob_name, block_ids, - content_md5, x_ms_blob_cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_meta_name_values, - x_ms_lease_id) - - def put_block_blob_from_bytes(self, container_name, blob_name, blob, - index=0, count=None, content_encoding=None, - content_language=None, content_md5=None, - cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, - x_ms_meta_name_values=None, - x_ms_lease_id=None, progress_callback=None): - ''' - Creates a new block blob from an array of bytes, or updates the content - of an existing block blob, with automatic chunking and progress - notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - blob: Content of blob as an array of bytes. - index: Start index in the array of bytes. - count: - Number of bytes to upload. Set to None or negative value to upload - all bytes starting from index. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob, or None if the total size is unknown. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('blob', blob) - _validate_not_none('index', index) - _validate_type_bytes('blob', blob) - - if index < 0: - raise TypeError(_ERROR_VALUE_NEGATIVE.format('index')) - - if count is None or count < 0: - count = len(blob) - index - - if count < self._BLOB_MAX_DATA_SIZE: - if progress_callback: - progress_callback(0, count) - - data = blob[index: index + count] - self.put_blob(container_name, - blob_name, - data, - 'BlockBlob', - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id) - - if progress_callback: - progress_callback(count, count) - else: - stream = BytesIO(blob) - stream.seek(index) - - self.put_block_blob_from_file(container_name, - blob_name, - stream, - count, - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id, - progress_callback) - - def put_block_blob_from_text(self, container_name, blob_name, text, - text_encoding='utf-8', - content_encoding=None, content_language=None, - content_md5=None, cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, - x_ms_meta_name_values=None, - x_ms_lease_id=None, progress_callback=None): - ''' - Creates a new block blob from str/unicode, or updates the content of an - existing block blob, with automatic chunking and progress notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - text: Text to upload to the blob. - text_encoding: Encoding to use to convert the text to bytes. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob, or None if the total size is unknown. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('text', text) - - if not isinstance(text, bytes): - _validate_not_none('text_encoding', text_encoding) - text = text.encode(text_encoding) - - self.put_block_blob_from_bytes(container_name, - blob_name, - text, - 0, - len(text), - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id, - progress_callback) - - def put_page_blob_from_path(self, container_name, blob_name, file_path, - content_encoding=None, content_language=None, - content_md5=None, cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, - x_ms_meta_name_values=None, - x_ms_lease_id=None, - x_ms_blob_sequence_number=None, - progress_callback=None): - ''' - Creates a new page blob from a file path, or updates the content of an - existing page blob, with automatic chunking and progress notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - file_path: Path of the file to upload as the blob content. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - x_ms_blob_sequence_number: - Optional. Set for page blobs only. The sequence number is a - user-controlled value that you can use to track requests. The - value of the sequence number must be between 0 and 2^63 - 1. The - default value is 0. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob, or None if the total size is unknown. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('file_path', file_path) - - count = path.getsize(file_path) - with open(file_path, 'rb') as stream: - self.put_page_blob_from_file(container_name, - blob_name, - stream, - count, - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id, - x_ms_blob_sequence_number, - progress_callback) - - def put_page_blob_from_file(self, container_name, blob_name, stream, count, - content_encoding=None, content_language=None, - content_md5=None, cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, - x_ms_meta_name_values=None, - x_ms_lease_id=None, - x_ms_blob_sequence_number=None, - progress_callback=None): - ''' - Creates a new page blob from a file/stream, or updates the content of an - existing page blob, with automatic chunking and progress notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - stream: Opened file/stream to upload as the blob content. - count: - Number of bytes to read from the stream. This is required, a page - blob cannot be created if the count is unknown. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - x_ms_blob_sequence_number: - Optional. Set for page blobs only. The sequence number is a - user-controlled value that you can use to track requests. The - value of the sequence number must be between 0 and 2^63 - 1. The - default value is 0. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob, or None if the total size is unknown. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('stream', stream) - _validate_not_none('count', count) - - if count < 0: - raise TypeError(_ERROR_VALUE_NEGATIVE.format('count')) - - if count % _PAGE_SIZE != 0: - raise TypeError(_ERROR_PAGE_BLOB_SIZE_ALIGNMENT.format(count)) - - if progress_callback: - progress_callback(0, count) - - self.put_blob(container_name, - blob_name, - b'', - 'PageBlob', - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id, - count, - x_ms_blob_sequence_number) - - remain_bytes = count - page_start = 0 - while True: - request_count = min(remain_bytes, self._BLOB_MAX_CHUNK_DATA_SIZE) - data = stream.read(request_count) - if data: - length = len(data) - remain_bytes = remain_bytes - length - page_end = page_start + length - 1 - self.put_page(container_name, - blob_name, - data, - 'bytes={0}-{1}'.format(page_start, page_end), - 'update', - x_ms_lease_id=x_ms_lease_id) - page_start = page_start + length - - if progress_callback: - progress_callback(page_start, count) - else: - break - - def put_page_blob_from_bytes(self, container_name, blob_name, blob, - index=0, count=None, content_encoding=None, - content_language=None, content_md5=None, - cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, - x_ms_blob_cache_control=None, - x_ms_meta_name_values=None, - x_ms_lease_id=None, - x_ms_blob_sequence_number=None, - progress_callback=None): - ''' - Creates a new page blob from an array of bytes, or updates the content - of an existing page blob, with automatic chunking and progress - notifications. - - container_name: Name of existing container. - blob_name: Name of blob to create or update. - blob: Content of blob as an array of bytes. - index: Start index in the array of bytes. - count: - Number of bytes to upload. Set to None or negative value to upload - all bytes starting from index. - content_encoding: - Optional. Specifies which content encodings have been applied to - the blob. This value is returned to the client when the Get Blob - (REST API) operation is performed on the blob resource. The client - can use this value when returned to decode the blob content. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - x_ms_blob_content_type: Optional. Set the blob's content type. - x_ms_blob_content_encoding: Optional. Set the blob's content encoding. - x_ms_blob_content_language: Optional. Set the blob's content language. - x_ms_blob_content_md5: Optional. Set the blob's MD5 hash. - x_ms_blob_cache_control: Optional. Sets the blob's cache control. - x_ms_meta_name_values: A dict containing name, value for metadata. - x_ms_lease_id: Required if the blob has an active lease. - x_ms_blob_sequence_number: - Optional. Set for page blobs only. The sequence number is a - user-controlled value that you can use to track requests. The - value of the sequence number must be between 0 and 2^63 - 1. The - default value is 0. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob, or None if the total size is unknown. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('blob', blob) - _validate_type_bytes('blob', blob) - - if index < 0: - raise TypeError(_ERROR_VALUE_NEGATIVE.format('index')) - - if count is None or count < 0: - count = len(blob) - index - - stream = BytesIO(blob) - stream.seek(index) - - self.put_page_blob_from_file(container_name, - blob_name, - stream, - count, - content_encoding, - content_language, - content_md5, - cache_control, - x_ms_blob_content_type, - x_ms_blob_content_encoding, - x_ms_blob_content_language, - x_ms_blob_content_md5, - x_ms_blob_cache_control, - x_ms_meta_name_values, - x_ms_lease_id, - x_ms_blob_sequence_number, - progress_callback) - - def get_blob(self, container_name, blob_name, snapshot=None, - x_ms_range=None, x_ms_lease_id=None, - x_ms_range_get_content_md5=None): - ''' - Reads or downloads a blob from the system, including its metadata and - properties. - - See get_blob_to_* for high level functions that handle the download - of large blobs with automatic chunking and progress notifications. - - container_name: Name of existing container. - blob_name: Name of existing blob. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve. - x_ms_range: - Optional. Return only the bytes of the blob in the specified range. - x_ms_lease_id: Required if the blob has an active lease. - x_ms_range_get_content_md5: - Optional. When this header is set to true and specified together - with the Range header, the service returns the MD5 hash for the - range, as long as the range is less than or equal to 4 MB in size. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '/' + _str(blob_name) + '' - request.headers = [ - ('x-ms-range', _str_or_none(x_ms_range)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-range-get-content-md5', - _str_or_none(x_ms_range_get_content_md5)) - ] - request.query = [('snapshot', _str_or_none(snapshot))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request, None) - - return _create_blob_result(response) - - def get_blob_to_path(self, container_name, blob_name, file_path, - open_mode='wb', snapshot=None, x_ms_lease_id=None, - progress_callback=None): - ''' - Downloads a blob to a file path, with automatic chunking and progress - notifications. - - container_name: Name of existing container. - blob_name: Name of existing blob. - file_path: Path of file to write to. - open_mode: Mode to use when opening the file. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('file_path', file_path) - _validate_not_none('open_mode', open_mode) - - with open(file_path, open_mode) as stream: - self.get_blob_to_file(container_name, - blob_name, - stream, - snapshot, - x_ms_lease_id, - progress_callback) - - def get_blob_to_file(self, container_name, blob_name, stream, - snapshot=None, x_ms_lease_id=None, - progress_callback=None): - ''' - Downloads a blob to a file/stream, with automatic chunking and progress - notifications. - - container_name: Name of existing container. - blob_name: Name of existing blob. - stream: Opened file/stream to write to. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('stream', stream) - - props = self.get_blob_properties(container_name, blob_name) - blob_size = int(props['content-length']) - - if blob_size < self._BLOB_MAX_DATA_SIZE: - if progress_callback: - progress_callback(0, blob_size) - - data = self.get_blob(container_name, - blob_name, - snapshot, - x_ms_lease_id=x_ms_lease_id) - - stream.write(data) - - if progress_callback: - progress_callback(blob_size, blob_size) - else: - if progress_callback: - progress_callback(0, blob_size) - - index = 0 - while index < blob_size: - chunk_range = 'bytes={0}-{1}'.format( - index, - index + self._BLOB_MAX_CHUNK_DATA_SIZE - 1) - data = self.get_blob( - container_name, blob_name, x_ms_range=chunk_range) - length = len(data) - index += length - if length > 0: - stream.write(data) - if progress_callback: - progress_callback(index, blob_size) - if length < self._BLOB_MAX_CHUNK_DATA_SIZE: - break - else: - break - - def get_blob_to_bytes(self, container_name, blob_name, snapshot=None, - x_ms_lease_id=None, progress_callback=None): - ''' - Downloads a blob as an array of bytes, with automatic chunking and - progress notifications. - - container_name: Name of existing container. - blob_name: Name of existing blob. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - - stream = BytesIO() - self.get_blob_to_file(container_name, - blob_name, - stream, - snapshot, - x_ms_lease_id, - progress_callback) - - return stream.getvalue() - - def get_blob_to_text(self, container_name, blob_name, text_encoding='utf-8', - snapshot=None, x_ms_lease_id=None, - progress_callback=None): - ''' - Downloads a blob as unicode text, with automatic chunking and progress - notifications. - - container_name: Name of existing container. - blob_name: Name of existing blob. - text_encoding: Encoding to use when decoding the blob data. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve. - x_ms_lease_id: Required if the blob has an active lease. - progress_callback: - Callback for progress with signature function(current, total) where - current is the number of bytes transfered so far, and total is the - size of the blob. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('text_encoding', text_encoding) - - result = self.get_blob_to_bytes(container_name, - blob_name, - snapshot, - x_ms_lease_id, - progress_callback) - - return result.decode(text_encoding) - - def get_blob_metadata(self, container_name, blob_name, snapshot=None, - x_ms_lease_id=None): - ''' - Returns all user-defined metadata for the specified blob or snapshot. - - container_name: Name of existing container. - blob_name: Name of existing blob. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=metadata' - request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))] - request.query = [('snapshot', _str_or_none(snapshot))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict_prefix(response, prefixes=['x-ms-meta']) - - def set_blob_metadata(self, container_name, blob_name, - x_ms_meta_name_values=None, x_ms_lease_id=None): - ''' - Sets user-defined metadata for the specified blob as one or more - name-value pairs. - - container_name: Name of existing container. - blob_name: Name of existing blob. - x_ms_meta_name_values: Dict containing name and value pairs. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=metadata' - request.headers = [ - ('x-ms-meta-name-values', x_ms_meta_name_values), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def lease_blob(self, container_name, blob_name, x_ms_lease_action, - x_ms_lease_id=None, x_ms_lease_duration=60, - x_ms_lease_break_period=None, x_ms_proposed_lease_id=None): - ''' - Establishes and manages a one-minute lock on a blob for write - operations. - - container_name: Name of existing container. - blob_name: Name of existing blob. - x_ms_lease_action: - Required. Possible values: acquire|renew|release|break|change - x_ms_lease_id: Required if the blob has an active lease. - x_ms_lease_duration: - Specifies the duration of the lease, in seconds, or negative one - (-1) for a lease that never expires. A non-infinite lease can be - between 15 and 60 seconds. A lease duration cannot be changed - using renew or change. For backwards compatibility, the default is - 60, and the value is only used on an acquire operation. - x_ms_lease_break_period: - Optional. For a break operation, this is the proposed duration of - seconds that the lease should continue before it is broken, between - 0 and 60 seconds. This break period is only used if it is shorter - than the time remaining on the lease. If longer, the time remaining - on the lease is used. A new lease will not be available before the - break period has expired, but the lease may be held for longer than - the break period. If this header does not appear with a break - operation, a fixed-duration lease breaks after the remaining lease - period elapses, and an infinite lease breaks immediately. - x_ms_proposed_lease_id: - Optional for acquire, required for change. Proposed lease ID, in a - GUID string format. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('x_ms_lease_action', x_ms_lease_action) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=lease' - request.headers = [ - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-lease-action', _str_or_none(x_ms_lease_action)), - ('x-ms-lease-duration', _str_or_none(x_ms_lease_duration\ - if x_ms_lease_action == 'acquire' else None)), - ('x-ms-lease-break-period', _str_or_none(x_ms_lease_break_period)), - ('x-ms-proposed-lease-id', _str_or_none(x_ms_proposed_lease_id)), - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict_filter( - response, - filter=['x-ms-lease-id', 'x-ms-lease-time']) - - def snapshot_blob(self, container_name, blob_name, - x_ms_meta_name_values=None, if_modified_since=None, - if_unmodified_since=None, if_match=None, - if_none_match=None, x_ms_lease_id=None): - ''' - Creates a read-only snapshot of a blob. - - container_name: Name of existing container. - blob_name: Name of existing blob. - x_ms_meta_name_values: Optional. Dict containing name and value pairs. - if_modified_since: Optional. Datetime string. - if_unmodified_since: DateTime string. - if_match: - Optional. snapshot the blob only if its ETag value matches the - value specified. - if_none_match: Optional. An ETag value - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=snapshot' - request.headers = [ - ('x-ms-meta-name-values', x_ms_meta_name_values), - ('If-Modified-Since', _str_or_none(if_modified_since)), - ('If-Unmodified-Since', _str_or_none(if_unmodified_since)), - ('If-Match', _str_or_none(if_match)), - ('If-None-Match', _str_or_none(if_none_match)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict_filter( - response, - filter=['x-ms-snapshot', 'etag', 'last-modified']) - - def copy_blob(self, container_name, blob_name, x_ms_copy_source, - x_ms_meta_name_values=None, - x_ms_source_if_modified_since=None, - x_ms_source_if_unmodified_since=None, - x_ms_source_if_match=None, x_ms_source_if_none_match=None, - if_modified_since=None, if_unmodified_since=None, - if_match=None, if_none_match=None, x_ms_lease_id=None, - x_ms_source_lease_id=None): - ''' - Copies a blob to a destination within the storage account. - - container_name: Name of existing container. - blob_name: Name of existing blob. - x_ms_copy_source: - URL up to 2 KB in length that specifies a blob. A source blob in - the same account can be private, but a blob in another account - must be public or accept credentials included in this URL, such as - a Shared Access Signature. Examples: - https://myaccount.blob.core.windows.net/mycontainer/myblob - https://myaccount.blob.core.windows.net/mycontainer/myblob?snapshot=<DateTime> - x_ms_meta_name_values: Optional. Dict containing name and value pairs. - x_ms_source_if_modified_since: - Optional. An ETag value. Specify this conditional header to copy - the source blob only if its ETag matches the value specified. - x_ms_source_if_unmodified_since: - Optional. An ETag value. Specify this conditional header to copy - the blob only if its ETag does not match the value specified. - x_ms_source_if_match: - Optional. A DateTime value. Specify this conditional header to - copy the blob only if the source blob has been modified since the - specified date/time. - x_ms_source_if_none_match: - Optional. An ETag value. Specify this conditional header to copy - the source blob only if its ETag matches the value specified. - if_modified_since: Optional. Datetime string. - if_unmodified_since: DateTime string. - if_match: - Optional. Snapshot the blob only if its ETag value matches the - value specified. - if_none_match: Optional. An ETag value - x_ms_lease_id: Required if the blob has an active lease. - x_ms_source_lease_id: - Optional. Specify this to perform the Copy Blob operation only if - the lease ID given matches the active lease ID of the source blob. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('x_ms_copy_source', x_ms_copy_source) - - if x_ms_copy_source.startswith('/'): - # Backwards compatibility for earlier versions of the SDK where - # the copy source can be in the following formats: - # - Blob in named container: - # /accountName/containerName/blobName - # - Snapshot in named container: - # /accountName/containerName/blobName?snapshot=<DateTime> - # - Blob in root container: - # /accountName/blobName - # - Snapshot in root container: - # /accountName/blobName?snapshot=<DateTime> - account, _, source =\ - x_ms_copy_source.partition('/')[2].partition('/') - x_ms_copy_source = self.protocol + '://' + \ - account + self.host_base + '/' + source - - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '/' + _str(blob_name) + '' - request.headers = [ - ('x-ms-copy-source', _str_or_none(x_ms_copy_source)), - ('x-ms-meta-name-values', x_ms_meta_name_values), - ('x-ms-source-if-modified-since', - _str_or_none(x_ms_source_if_modified_since)), - ('x-ms-source-if-unmodified-since', - _str_or_none(x_ms_source_if_unmodified_since)), - ('x-ms-source-if-match', _str_or_none(x_ms_source_if_match)), - ('x-ms-source-if-none-match', - _str_or_none(x_ms_source_if_none_match)), - ('If-Modified-Since', _str_or_none(if_modified_since)), - ('If-Unmodified-Since', _str_or_none(if_unmodified_since)), - ('If-Match', _str_or_none(if_match)), - ('If-None-Match', _str_or_none(if_none_match)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-source-lease-id', _str_or_none(x_ms_source_lease_id)) - ] - - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict(response) - - def abort_copy_blob(self, container_name, blob_name, x_ms_copy_id, - x_ms_lease_id=None): - ''' - Aborts a pending copy_blob operation, and leaves a destination blob - with zero length and full metadata. - - container_name: Name of destination container. - blob_name: Name of destination blob. - x_ms_copy_id: - Copy identifier provided in the x-ms-copy-id of the original - copy_blob operation. - x_ms_lease_id: - Required if the destination blob has an active infinite lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('x_ms_copy_id', x_ms_copy_id) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '/' + \ - _str(blob_name) + '?comp=copy©id=' + \ - _str(x_ms_copy_id) - request.headers = [ - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-copy-action', 'abort'), - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def delete_blob(self, container_name, blob_name, snapshot=None, - timeout=None, x_ms_lease_id=None, - x_ms_delete_snapshots=None): - ''' - Marks the specified blob or snapshot for deletion. The blob is later - deleted during garbage collection. - - To mark a specific snapshot for deletion provide the date/time of the - snapshot via the snapshot parameter. - - container_name: Name of existing container. - blob_name: Name of existing blob. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to delete. - timeout: - Optional. The timeout parameter is expressed in seconds. - The Blob service returns an error when the timeout interval elapses - while processing the request. - x_ms_lease_id: Required if the blob has an active lease. - x_ms_delete_snapshots: - Required if the blob has associated snapshots. Specify one of the - following two options: - include: Delete the base blob and all of its snapshots. - only: Delete only the blob's snapshots and not the blob itself. - This header should be specified only for a request against the base - blob resource. If this header is specified on a request to delete - an individual snapshot, the Blob service returns status code 400 - (Bad Request). If this header is not specified on the request and - the blob has associated snapshots, the Blob service returns status - code 409 (Conflict). - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(container_name) + '/' + _str(blob_name) + '' - request.headers = [ - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-delete-snapshots', _str_or_none(x_ms_delete_snapshots)) - ] - request.query = [ - ('snapshot', _str_or_none(snapshot)), - ('timeout', _int_or_none(timeout)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def put_block(self, container_name, blob_name, block, blockid, - content_md5=None, x_ms_lease_id=None): - ''' - Creates a new block to be committed as part of a blob. - - container_name: Name of existing container. - blob_name: Name of existing blob. - block: Content of the block. - blockid: - Required. A value that identifies the block. The string must be - less than or equal to 64 bytes in size. - content_md5: - Optional. An MD5 hash of the block content. This hash is used to - verify the integrity of the blob during transport. When this - header is specified, the storage service checks the hash that has - arrived with the one that was sent. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('block', block) - _validate_not_none('blockid', blockid) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=block' - request.headers = [ - ('Content-MD5', _str_or_none(content_md5)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)) - ] - request.query = [('blockid', _encode_base64(_str_or_none(blockid)))] - request.body = _get_request_body_bytes_only('block', block) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def put_block_list(self, container_name, blob_name, block_list, - content_md5=None, x_ms_blob_cache_control=None, - x_ms_blob_content_type=None, - x_ms_blob_content_encoding=None, - x_ms_blob_content_language=None, - x_ms_blob_content_md5=None, x_ms_meta_name_values=None, - x_ms_lease_id=None): - ''' - Writes a blob by specifying the list of block IDs that make up the - blob. In order to be written as part of a blob, a block must have been - successfully written to the server in a prior Put Block (REST API) - operation. - - container_name: Name of existing container. - blob_name: Name of existing blob. - block_list: A str list containing the block ids. - content_md5: - Optional. An MD5 hash of the block content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. - x_ms_blob_cache_control: - Optional. Sets the blob's cache control. If specified, this - property is stored with the blob and returned with a read request. - x_ms_blob_content_type: - Optional. Sets the blob's content type. If specified, this property - is stored with the blob and returned with a read request. - x_ms_blob_content_encoding: - Optional. Sets the blob's content encoding. If specified, this - property is stored with the blob and returned with a read request. - x_ms_blob_content_language: - Optional. Set the blob's content language. If specified, this - property is stored with the blob and returned with a read request. - x_ms_blob_content_md5: - Optional. An MD5 hash of the blob content. Note that this hash is - not validated, as the hashes for the individual blocks were - validated when each was uploaded. - x_ms_meta_name_values: Optional. Dict containing name and value pairs. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('block_list', block_list) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=blocklist' - request.headers = [ - ('Content-MD5', _str_or_none(content_md5)), - ('x-ms-blob-cache-control', _str_or_none(x_ms_blob_cache_control)), - ('x-ms-blob-content-type', _str_or_none(x_ms_blob_content_type)), - ('x-ms-blob-content-encoding', - _str_or_none(x_ms_blob_content_encoding)), - ('x-ms-blob-content-language', - _str_or_none(x_ms_blob_content_language)), - ('x-ms-blob-content-md5', _str_or_none(x_ms_blob_content_md5)), - ('x-ms-meta-name-values', x_ms_meta_name_values), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)) - ] - request.body = _get_request_body( - _convert_block_list_to_xml(block_list)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def get_block_list(self, container_name, blob_name, snapshot=None, - blocklisttype=None, x_ms_lease_id=None): - ''' - Retrieves the list of blocks that have been uploaded as part of a - block blob. - - container_name: Name of existing container. - blob_name: Name of existing blob. - snapshot: - Optional. Datetime to determine the time to retrieve the blocks. - blocklisttype: - Specifies whether to return the list of committed blocks, the list - of uncommitted blocks, or both lists together. Valid values are: - committed, uncommitted, or all. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=blocklist' - request.headers = [('x-ms-lease-id', _str_or_none(x_ms_lease_id))] - request.query = [ - ('snapshot', _str_or_none(snapshot)), - ('blocklisttype', _str_or_none(blocklisttype)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _convert_response_to_block_list(response) - - def put_page(self, container_name, blob_name, page, x_ms_range, - x_ms_page_write, timeout=None, content_md5=None, - x_ms_lease_id=None, x_ms_if_sequence_number_lte=None, - x_ms_if_sequence_number_lt=None, - x_ms_if_sequence_number_eq=None, - if_modified_since=None, if_unmodified_since=None, - if_match=None, if_none_match=None): - ''' - Writes a range of pages to a page blob. - - container_name: Name of existing container. - blob_name: Name of existing blob. - page: Content of the page. - x_ms_range: - Required. Specifies the range of bytes to be written as a page. - Both the start and end of the range must be specified. Must be in - format: bytes=startByte-endByte. Given that pages must be aligned - with 512-byte boundaries, the start offset must be a modulus of - 512 and the end offset must be a modulus of 512-1. Examples of - valid byte ranges are 0-511, 512-1023, etc. - x_ms_page_write: - Required. You may specify one of the following options: - update (lower case): - Writes the bytes specified by the request body into the - specified range. The Range and Content-Length headers must - match to perform the update. - clear (lower case): - Clears the specified range and releases the space used in - storage for that range. To clear a range, set the - Content-Length header to zero, and the Range header to a - value that indicates the range to clear, up to maximum - blob size. - timeout: the timeout parameter is expressed in seconds. - content_md5: - Optional. An MD5 hash of the page content. This hash is used to - verify the integrity of the page during transport. When this header - is specified, the storage service compares the hash of the content - that has arrived with the header value that was sent. If the two - hashes do not match, the operation will fail with error code 400 - (Bad Request). - x_ms_lease_id: Required if the blob has an active lease. - x_ms_if_sequence_number_lte: - Optional. If the blob's sequence number is less than or equal to - the specified value, the request proceeds; otherwise it fails. - x_ms_if_sequence_number_lt: - Optional. If the blob's sequence number is less than the specified - value, the request proceeds; otherwise it fails. - x_ms_if_sequence_number_eq: - Optional. If the blob's sequence number is equal to the specified - value, the request proceeds; otherwise it fails. - if_modified_since: - Optional. A DateTime value. Specify this conditional header to - write the page only if the blob has been modified since the - specified date/time. If the blob has not been modified, the Blob - service fails. - if_unmodified_since: - Optional. A DateTime value. Specify this conditional header to - write the page only if the blob has not been modified since the - specified date/time. If the blob has been modified, the Blob - service fails. - if_match: - Optional. An ETag value. Specify an ETag value for this conditional - header to write the page only if the blob's ETag value matches the - value specified. If the values do not match, the Blob service fails. - if_none_match: - Optional. An ETag value. Specify an ETag value for this conditional - header to write the page only if the blob's ETag value does not - match the value specified. If the values are identical, the Blob - service fails. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - _validate_not_none('page', page) - _validate_not_none('x_ms_range', x_ms_range) - _validate_not_none('x_ms_page_write', x_ms_page_write) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=page' - request.headers = [ - ('x-ms-range', _str_or_none(x_ms_range)), - ('Content-MD5', _str_or_none(content_md5)), - ('x-ms-page-write', _str_or_none(x_ms_page_write)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)), - ('x-ms-if-sequence-number-le', - _str_or_none(x_ms_if_sequence_number_lte)), - ('x-ms-if-sequence-number-lt', - _str_or_none(x_ms_if_sequence_number_lt)), - ('x-ms-if-sequence-number-eq', - _str_or_none(x_ms_if_sequence_number_eq)), - ('If-Modified-Since', _str_or_none(if_modified_since)), - ('If-Unmodified-Since', _str_or_none(if_unmodified_since)), - ('If-Match', _str_or_none(if_match)), - ('If-None-Match', _str_or_none(if_none_match)) - ] - request.query = [('timeout', _int_or_none(timeout))] - request.body = _get_request_body_bytes_only('page', page) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def get_page_ranges(self, container_name, blob_name, snapshot=None, - range=None, x_ms_range=None, x_ms_lease_id=None): - ''' - Retrieves the page ranges for a blob. - - container_name: Name of existing container. - blob_name: Name of existing blob. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve information - from. - range: - Optional. Specifies the range of bytes over which to list ranges, - inclusively. If omitted, then all ranges for the blob are returned. - x_ms_range: - Optional. Specifies the range of bytes to be written as a page. - Both the start and end of the range must be specified. Must be in - format: bytes=startByte-endByte. Given that pages must be aligned - with 512-byte boundaries, the start offset must be a modulus of - 512 and the end offset must be a modulus of 512-1. Examples of - valid byte ranges are 0-511, 512-1023, etc. - x_ms_lease_id: Required if the blob has an active lease. - ''' - _validate_not_none('container_name', container_name) - _validate_not_none('blob_name', blob_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + \ - _str(container_name) + '/' + _str(blob_name) + '?comp=pagelist' - request.headers = [ - ('Range', _str_or_none(range)), - ('x-ms-range', _str_or_none(x_ms_range)), - ('x-ms-lease-id', _str_or_none(x_ms_lease_id)) - ] - request.query = [('snapshot', _str_or_none(snapshot))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_blob_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_simple_list(response, PageList, PageRange, "page_ranges") diff --git a/awx/lib/site-packages/azure/storage/cloudstorageaccount.py b/awx/lib/site-packages/azure/storage/cloudstorageaccount.py deleted file mode 100644 index 4cca4c45b3..0000000000 --- a/awx/lib/site-packages/azure/storage/cloudstorageaccount.py +++ /dev/null @@ -1,39 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure.storage.blobservice import BlobService -from azure.storage.tableservice import TableService -from azure.storage.queueservice import QueueService - - -class CloudStorageAccount(object): - - """ - Provides a factory for creating the blob, queue, and table services - with a common account name and account key. Users can either use the - factory or can construct the appropriate service directly. - """ - - def __init__(self, account_name=None, account_key=None): - self.account_name = account_name - self.account_key = account_key - - def create_blob_service(self): - return BlobService(self.account_name, self.account_key) - - def create_table_service(self): - return TableService(self.account_name, self.account_key) - - def create_queue_service(self): - return QueueService(self.account_name, self.account_key) diff --git a/awx/lib/site-packages/azure/storage/queueservice.py b/awx/lib/site-packages/azure/storage/queueservice.py deleted file mode 100644 index bfcb47a2de..0000000000 --- a/awx/lib/site-packages/azure/storage/queueservice.py +++ /dev/null @@ -1,458 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - WindowsAzureConflictError, - WindowsAzureError, - DEV_QUEUE_HOST, - QUEUE_SERVICE_HOST_BASE, - xml_escape, - _convert_class_to_xml, - _dont_fail_not_exist, - _dont_fail_on_exist, - _get_request_body, - _int_or_none, - _parse_enum_results_list, - _parse_response, - _parse_response_for_dict_filter, - _parse_response_for_dict_prefix, - _str, - _str_or_none, - _update_request_uri_query_local_storage, - _validate_not_none, - _ERROR_CONFLICT, - ) -from azure.http import ( - HTTPRequest, - HTTP_RESPONSE_NO_CONTENT, - ) -from azure.storage import ( - Queue, - QueueEnumResults, - QueueMessagesList, - StorageServiceProperties, - _update_storage_queue_header, - ) -from azure.storage.storageclient import _StorageClient - - -class QueueService(_StorageClient): - - ''' - This is the main class managing queue resources. - ''' - - def __init__(self, account_name=None, account_key=None, protocol='https', - host_base=QUEUE_SERVICE_HOST_BASE, dev_host=DEV_QUEUE_HOST): - ''' - account_name: your storage account name, required for all operations. - account_key: your storage account key, required for all operations. - protocol: Optional. Protocol. Defaults to http. - host_base: - Optional. Live host base url. Defaults to Azure url. Override this - for on-premise. - dev_host: Optional. Dev host url. Defaults to localhost. - ''' - super(QueueService, self).__init__( - account_name, account_key, protocol, host_base, dev_host) - - def get_queue_service_properties(self, timeout=None): - ''' - Gets the properties of a storage account's Queue Service, including - Windows Azure Storage Analytics. - - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/?restype=service&comp=properties' - request.query = [('timeout', _int_or_none(timeout))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response(response, StorageServiceProperties) - - def list_queues(self, prefix=None, marker=None, maxresults=None, - include=None): - ''' - Lists all of the queues in a given storage account. - - prefix: - Filters the results to return only queues with names that begin - with the specified prefix. - marker: - A string value that identifies the portion of the list to be - returned with the next list operation. The operation returns a - NextMarker element within the response body if the list returned - was not complete. This value may then be used as a query parameter - in a subsequent call to request the next portion of the list of - queues. The marker value is opaque to the client. - maxresults: - Specifies the maximum number of queues to return. If maxresults is - not specified, the server will return up to 5,000 items. - include: - Optional. Include this parameter to specify that the container's - metadata be returned as part of the response body. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/?comp=list' - request.query = [ - ('prefix', _str_or_none(prefix)), - ('marker', _str_or_none(marker)), - ('maxresults', _int_or_none(maxresults)), - ('include', _str_or_none(include)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_enum_results_list( - response, QueueEnumResults, "Queues", Queue) - - def create_queue(self, queue_name, x_ms_meta_name_values=None, - fail_on_exist=False): - ''' - Creates a queue under the given account. - - queue_name: name of the queue. - x_ms_meta_name_values: - Optional. A dict containing name-value pairs to associate with the - queue as metadata. - fail_on_exist: Specify whether throw exception when queue exists. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '' - request.headers = [('x-ms-meta-name-values', x_ms_meta_name_values)] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - if not fail_on_exist: - try: - response = self._perform_request(request) - if response.status == HTTP_RESPONSE_NO_CONTENT: - return False - return True - except WindowsAzureError as ex: - _dont_fail_on_exist(ex) - return False - else: - response = self._perform_request(request) - if response.status == HTTP_RESPONSE_NO_CONTENT: - raise WindowsAzureConflictError( - _ERROR_CONFLICT.format(response.message)) - return True - - def delete_queue(self, queue_name, fail_not_exist=False): - ''' - Permanently deletes the specified queue. - - queue_name: Name of the queue. - fail_not_exist: - Specify whether throw exception when queue doesn't exist. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '' - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - if not fail_not_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_not_exist(ex) - return False - else: - self._perform_request(request) - return True - - def get_queue_metadata(self, queue_name): - ''' - Retrieves user-defined metadata and queue properties on the specified - queue. Metadata is associated with the queue as name-values pairs. - - queue_name: Name of the queue. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '?comp=metadata' - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict_prefix( - response, - prefixes=['x-ms-meta', 'x-ms-approximate-messages-count']) - - def set_queue_metadata(self, queue_name, x_ms_meta_name_values=None): - ''' - Sets user-defined metadata on the specified queue. Metadata is - associated with the queue as name-value pairs. - - queue_name: Name of the queue. - x_ms_meta_name_values: - Optional. A dict containing name-value pairs to associate with the - queue as metadata. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '?comp=metadata' - request.headers = [('x-ms-meta-name-values', x_ms_meta_name_values)] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def put_message(self, queue_name, message_text, visibilitytimeout=None, - messagettl=None): - ''' - Adds a new message to the back of the message queue. A visibility - timeout can also be specified to make the message invisible until the - visibility timeout expires. A message must be in a format that can be - included in an XML request with UTF-8 encoding. The encoded message can - be up to 64KB in size for versions 2011-08-18 and newer, or 8KB in size - for previous versions. - - queue_name: Name of the queue. - message_text: Message content. - visibilitytimeout: - Optional. If not specified, the default value is 0. Specifies the - new visibility timeout value, in seconds, relative to server time. - The new value must be larger than or equal to 0, and cannot be - larger than 7 days. The visibility timeout of a message cannot be - set to a value later than the expiry time. visibilitytimeout - should be set to a value smaller than the time-to-live value. - messagettl: - Optional. Specifies the time-to-live interval for the message, in - seconds. The maximum time-to-live allowed is 7 days. If this - parameter is omitted, the default time-to-live is 7 days. - ''' - _validate_not_none('queue_name', queue_name) - _validate_not_none('message_text', message_text) - request = HTTPRequest() - request.method = 'POST' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '/messages' - request.query = [ - ('visibilitytimeout', _str_or_none(visibilitytimeout)), - ('messagettl', _str_or_none(messagettl)) - ] - request.body = _get_request_body( - '<?xml version="1.0" encoding="utf-8"?> \ -<QueueMessage> \ - <MessageText>' + xml_escape(_str(message_text)) + '</MessageText> \ -</QueueMessage>') - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def get_messages(self, queue_name, numofmessages=None, - visibilitytimeout=None): - ''' - Retrieves one or more messages from the front of the queue. - - queue_name: Name of the queue. - numofmessages: - Optional. A nonzero integer value that specifies the number of - messages to retrieve from the queue, up to a maximum of 32. If - fewer are visible, the visible messages are returned. By default, - a single message is retrieved from the queue with this operation. - visibilitytimeout: - Specifies the new visibility timeout value, in seconds, relative - to server time. The new value must be larger than or equal to 1 - second, and cannot be larger than 7 days, or larger than 2 hours - on REST protocol versions prior to version 2011-08-18. The - visibility timeout of a message can be set to a value later than - the expiry time. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '/messages' - request.query = [ - ('numofmessages', _str_or_none(numofmessages)), - ('visibilitytimeout', _str_or_none(visibilitytimeout)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response(response, QueueMessagesList) - - def peek_messages(self, queue_name, numofmessages=None): - ''' - Retrieves one or more messages from the front of the queue, but does - not alter the visibility of the message. - - queue_name: Name of the queue. - numofmessages: - Optional. A nonzero integer value that specifies the number of - messages to peek from the queue, up to a maximum of 32. By default, - a single message is peeked from the queue with this operation. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '/messages?peekonly=true' - request.query = [('numofmessages', _str_or_none(numofmessages))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response(response, QueueMessagesList) - - def delete_message(self, queue_name, message_id, popreceipt): - ''' - Deletes the specified message. - - queue_name: Name of the queue. - message_id: Message to delete. - popreceipt: - Required. A valid pop receipt value returned from an earlier call - to the Get Messages or Update Message operation. - ''' - _validate_not_none('queue_name', queue_name) - _validate_not_none('message_id', message_id) - _validate_not_none('popreceipt', popreceipt) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + \ - _str(queue_name) + '/messages/' + _str(message_id) + '' - request.query = [('popreceipt', _str_or_none(popreceipt))] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def clear_messages(self, queue_name): - ''' - Deletes all messages from the specified queue. - - queue_name: Name of the queue. - ''' - _validate_not_none('queue_name', queue_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + _str(queue_name) + '/messages' - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - self._perform_request(request) - - def update_message(self, queue_name, message_id, message_text, popreceipt, - visibilitytimeout): - ''' - Updates the visibility timeout of a message. You can also use this - operation to update the contents of a message. - - queue_name: Name of the queue. - message_id: Message to update. - message_text: Content of message. - popreceipt: - Required. A valid pop receipt value returned from an earlier call - to the Get Messages or Update Message operation. - visibilitytimeout: - Required. Specifies the new visibility timeout value, in seconds, - relative to server time. The new value must be larger than or equal - to 0, and cannot be larger than 7 days. The visibility timeout of a - message cannot be set to a value later than the expiry time. A - message can be updated until it has been deleted or has expired. - ''' - _validate_not_none('queue_name', queue_name) - _validate_not_none('message_id', message_id) - _validate_not_none('message_text', message_text) - _validate_not_none('popreceipt', popreceipt) - _validate_not_none('visibilitytimeout', visibilitytimeout) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(queue_name) + '/messages/' + _str(message_id) + '' - request.query = [ - ('popreceipt', _str_or_none(popreceipt)), - ('visibilitytimeout', _str_or_none(visibilitytimeout)) - ] - request.body = _get_request_body( - '<?xml version="1.0" encoding="utf-8"?> \ -<QueueMessage> \ - <MessageText>' + xml_escape(_str(message_text)) + '</MessageText> \ -</QueueMessage>') - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - response = self._perform_request(request) - - return _parse_response_for_dict_filter( - response, - filter=['x-ms-popreceipt', 'x-ms-time-next-visible']) - - def set_queue_service_properties(self, storage_service_properties, - timeout=None): - ''' - Sets the properties of a storage account's Queue service, including - Windows Azure Storage Analytics. - - storage_service_properties: StorageServiceProperties object. - timeout: Optional. The timeout parameter is expressed in seconds. - ''' - _validate_not_none('storage_service_properties', - storage_service_properties) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/?restype=service&comp=properties' - request.query = [('timeout', _int_or_none(timeout))] - request.body = _get_request_body( - _convert_class_to_xml(storage_service_properties)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_queue_header( - request, self.account_name, self.account_key) - self._perform_request(request) diff --git a/awx/lib/site-packages/azure/storage/sharedaccesssignature.py b/awx/lib/site-packages/azure/storage/sharedaccesssignature.py deleted file mode 100644 index a9ec14cc70..0000000000 --- a/awx/lib/site-packages/azure/storage/sharedaccesssignature.py +++ /dev/null @@ -1,231 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import _sign_string, url_quote -from azure.storage import X_MS_VERSION - -#------------------------------------------------------------------------- -# Constants for the share access signature -SIGNED_VERSION = 'sv' -SIGNED_START = 'st' -SIGNED_EXPIRY = 'se' -SIGNED_RESOURCE = 'sr' -SIGNED_PERMISSION = 'sp' -SIGNED_IDENTIFIER = 'si' -SIGNED_SIGNATURE = 'sig' -SIGNED_VERSION = 'sv' -RESOURCE_BLOB = 'b' -RESOURCE_CONTAINER = 'c' -SIGNED_RESOURCE_TYPE = 'resource' -SHARED_ACCESS_PERMISSION = 'permission' - -#-------------------------------------------------------------------------- - - -class WebResource(object): - - ''' - Class that stands for the resource to get the share access signature - - path: the resource path. - properties: dict of name and values. Contains 2 item: resource type and - permission - request_url: the url of the webresource include all the queries. - ''' - - def __init__(self, path=None, request_url=None, properties=None): - self.path = path - self.properties = properties or {} - self.request_url = request_url - - -class Permission(object): - - ''' - Permission class. Contains the path and query_string for the path. - - path: the resource path - query_string: dict of name, values. Contains SIGNED_START, SIGNED_EXPIRY - SIGNED_RESOURCE, SIGNED_PERMISSION, SIGNED_IDENTIFIER, - SIGNED_SIGNATURE name values. - ''' - - def __init__(self, path=None, query_string=None): - self.path = path - self.query_string = query_string - - -class SharedAccessPolicy(object): - - ''' SharedAccessPolicy class. ''' - - def __init__(self, access_policy, signed_identifier=None): - self.id = signed_identifier - self.access_policy = access_policy - - -class SharedAccessSignature(object): - - ''' - The main class used to do the signing and generating the signature. - - account_name: - the storage account name used to generate shared access signature - account_key: the access key to genenerate share access signature - permission_set: the permission cache used to signed the request url. - ''' - - def __init__(self, account_name, account_key, permission_set=None): - self.account_name = account_name - self.account_key = account_key - self.permission_set = permission_set - - def generate_signed_query_string(self, path, resource_type, - shared_access_policy, - version=X_MS_VERSION): - ''' - Generates the query string for path, resource type and shared access - policy. - - path: the resource - resource_type: could be blob or container - shared_access_policy: shared access policy - version: - x-ms-version for storage service, or None to get a signed query - string compatible with pre 2012-02-12 clients, where the version - is not included in the query string. - ''' - - query_string = {} - if shared_access_policy.access_policy.start: - query_string[ - SIGNED_START] = shared_access_policy.access_policy.start - - if version: - query_string[SIGNED_VERSION] = version - query_string[SIGNED_EXPIRY] = shared_access_policy.access_policy.expiry - query_string[SIGNED_RESOURCE] = resource_type - query_string[ - SIGNED_PERMISSION] = shared_access_policy.access_policy.permission - - if shared_access_policy.id: - query_string[SIGNED_IDENTIFIER] = shared_access_policy.id - - query_string[SIGNED_SIGNATURE] = self._generate_signature( - path, shared_access_policy, version) - return query_string - - def sign_request(self, web_resource): - ''' sign request to generate request_url with sharedaccesssignature - info for web_resource.''' - - if self.permission_set: - for shared_access_signature in self.permission_set: - if self._permission_matches_request( - shared_access_signature, web_resource, - web_resource.properties[ - SIGNED_RESOURCE_TYPE], - web_resource.properties[SHARED_ACCESS_PERMISSION]): - if web_resource.request_url.find('?') == -1: - web_resource.request_url += '?' - else: - web_resource.request_url += '&' - - web_resource.request_url += self._convert_query_string( - shared_access_signature.query_string) - break - return web_resource - - def _convert_query_string(self, query_string): - ''' Converts query string to str. The order of name, values is very - important and can't be wrong.''' - - convert_str = '' - if SIGNED_START in query_string: - convert_str += SIGNED_START + '=' + \ - url_quote(query_string[SIGNED_START]) + '&' - convert_str += SIGNED_EXPIRY + '=' + \ - url_quote(query_string[SIGNED_EXPIRY]) + '&' - convert_str += SIGNED_PERMISSION + '=' + \ - query_string[SIGNED_PERMISSION] + '&' - convert_str += SIGNED_RESOURCE + '=' + \ - query_string[SIGNED_RESOURCE] + '&' - - if SIGNED_IDENTIFIER in query_string: - convert_str += SIGNED_IDENTIFIER + '=' + \ - query_string[SIGNED_IDENTIFIER] + '&' - if SIGNED_VERSION in query_string: - convert_str += SIGNED_VERSION + '=' + \ - query_string[SIGNED_VERSION] + '&' - convert_str += SIGNED_SIGNATURE + '=' + \ - url_quote(query_string[SIGNED_SIGNATURE]) + '&' - return convert_str - - def _generate_signature(self, path, shared_access_policy, version): - ''' Generates signature for a given path and shared access policy. ''' - - def get_value_to_append(value, no_new_line=False): - return_value = '' - if value: - return_value = value - if not no_new_line: - return_value += '\n' - return return_value - - if path[0] != '/': - path = '/' + path - - canonicalized_resource = '/' + self.account_name + path - - # Form the string to sign from shared_access_policy and canonicalized - # resource. The order of values is important. - string_to_sign = \ - (get_value_to_append(shared_access_policy.access_policy.permission) + - get_value_to_append(shared_access_policy.access_policy.start) + - get_value_to_append(shared_access_policy.access_policy.expiry) + - get_value_to_append(canonicalized_resource)) - - if version: - string_to_sign += get_value_to_append(shared_access_policy.id) - string_to_sign += get_value_to_append(version, True) - else: - string_to_sign += get_value_to_append(shared_access_policy.id, True) - - return self._sign(string_to_sign) - - def _permission_matches_request(self, shared_access_signature, - web_resource, resource_type, - required_permission): - ''' Check whether requested permission matches given - shared_access_signature, web_resource and resource type. ''' - - required_resource_type = resource_type - if required_resource_type == RESOURCE_BLOB: - required_resource_type += RESOURCE_CONTAINER - - for name, value in shared_access_signature.query_string.items(): - if name == SIGNED_RESOURCE and \ - required_resource_type.find(value) == -1: - return False - elif name == SIGNED_PERMISSION and \ - required_permission.find(value) == -1: - return False - - return web_resource.path.find(shared_access_signature.path) != -1 - - def _sign(self, string_to_sign): - ''' use HMAC-SHA256 to sign the string and convert it as base64 - encoded string. ''' - - return _sign_string(self.account_key, string_to_sign) diff --git a/awx/lib/site-packages/azure/storage/storageclient.py b/awx/lib/site-packages/azure/storage/storageclient.py deleted file mode 100644 index 9b0fd56c4b..0000000000 --- a/awx/lib/site-packages/azure/storage/storageclient.py +++ /dev/null @@ -1,152 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -import os -import sys - -from azure import ( - WindowsAzureError, - DEV_ACCOUNT_NAME, - DEV_ACCOUNT_KEY, - _ERROR_STORAGE_MISSING_INFO, - ) -from azure.http import HTTPError -from azure.http.httpclient import _HTTPClient -from azure.storage import _storage_error_handler - -#-------------------------------------------------------------------------- -# constants for azure app setting environment variables -AZURE_STORAGE_ACCOUNT = 'AZURE_STORAGE_ACCOUNT' -AZURE_STORAGE_ACCESS_KEY = 'AZURE_STORAGE_ACCESS_KEY' -EMULATED = 'EMULATED' - -#-------------------------------------------------------------------------- - - -class _StorageClient(object): - - ''' - This is the base class for BlobManager, TableManager and QueueManager. - ''' - - def __init__(self, account_name=None, account_key=None, protocol='https', - host_base='', dev_host=''): - ''' - account_name: your storage account name, required for all operations. - account_key: your storage account key, required for all operations. - protocol: Optional. Protocol. Defaults to http. - host_base: - Optional. Live host base url. Defaults to Azure url. Override this - for on-premise. - dev_host: Optional. Dev host url. Defaults to localhost. - ''' - self.account_name = account_name - self.account_key = account_key - self.requestid = None - self.protocol = protocol - self.host_base = host_base - self.dev_host = dev_host - - # the app is not run in azure emulator or use default development - # storage account and key if app is run in emulator. - self.use_local_storage = False - - # check whether it is run in emulator. - if EMULATED in os.environ: - self.is_emulated = os.environ[EMULATED].lower() != 'false' - else: - self.is_emulated = False - - # get account_name and account key. If they are not set when - # constructing, get the account and key from environment variables if - # the app is not run in azure emulator or use default development - # storage account and key if app is run in emulator. - if not self.account_name or not self.account_key: - if self.is_emulated: - self.account_name = DEV_ACCOUNT_NAME - self.account_key = DEV_ACCOUNT_KEY - self.protocol = 'http' - self.use_local_storage = True - else: - self.account_name = os.environ.get(AZURE_STORAGE_ACCOUNT) - self.account_key = os.environ.get(AZURE_STORAGE_ACCESS_KEY) - - if not self.account_name or not self.account_key: - raise WindowsAzureError(_ERROR_STORAGE_MISSING_INFO) - - self._httpclient = _HTTPClient( - service_instance=self, - account_key=self.account_key, - account_name=self.account_name, - protocol=self.protocol) - self._batchclient = None - self._filter = self._perform_request_worker - - def with_filter(self, filter): - ''' - Returns a new service which will process requests with the specified - filter. Filtering operations can include logging, automatic retrying, - etc... The filter is a lambda which receives the HTTPRequest and - another lambda. The filter can perform any pre-processing on the - request, pass it off to the next lambda, and then perform any - post-processing on the response. - ''' - res = type(self)(self.account_name, self.account_key, self.protocol) - old_filter = self._filter - - def new_filter(request): - return filter(request, old_filter) - - res._filter = new_filter - return res - - def set_proxy(self, host, port, user=None, password=None): - ''' - Sets the proxy server host and port for the HTTP CONNECT Tunnelling. - - host: Address of the proxy. Ex: '192.168.0.100' - port: Port of the proxy. Ex: 6000 - user: User for proxy authorization. - password: Password for proxy authorization. - ''' - self._httpclient.set_proxy(host, port, user, password) - - def _get_host(self): - if self.use_local_storage: - return self.dev_host - else: - return self.account_name + self.host_base - - def _perform_request_worker(self, request): - return self._httpclient.perform_request(request) - - def _perform_request(self, request, text_encoding='utf-8'): - ''' - Sends the request and return response. Catches HTTPError and hand it - to error handler - ''' - try: - if self._batchclient is not None: - return self._batchclient.insert_request_to_batch(request) - else: - resp = self._filter(request) - - if sys.version_info >= (3,) and isinstance(resp, bytes) and \ - text_encoding: - resp = resp.decode(text_encoding) - - except HTTPError as ex: - _storage_error_handler(ex) - - return resp diff --git a/awx/lib/site-packages/azure/storage/tableservice.py b/awx/lib/site-packages/azure/storage/tableservice.py deleted file mode 100644 index f25c48a5c8..0000000000 --- a/awx/lib/site-packages/azure/storage/tableservice.py +++ /dev/null @@ -1,491 +0,0 @@ -#------------------------------------------------------------------------- -# Copyright (c) Microsoft. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#-------------------------------------------------------------------------- -from azure import ( - WindowsAzureError, - TABLE_SERVICE_HOST_BASE, - DEV_TABLE_HOST, - _convert_class_to_xml, - _convert_response_to_feeds, - _dont_fail_not_exist, - _dont_fail_on_exist, - _get_request_body, - _int_or_none, - _parse_response, - _parse_response_for_dict, - _parse_response_for_dict_filter, - _str, - _str_or_none, - _update_request_uri_query_local_storage, - _validate_not_none, - ) -from azure.http import HTTPRequest -from azure.http.batchclient import _BatchClient -from azure.storage import ( - StorageServiceProperties, - _convert_entity_to_xml, - _convert_response_to_entity, - _convert_table_to_xml, - _convert_xml_to_entity, - _convert_xml_to_table, - _sign_storage_table_request, - _update_storage_table_header, - ) -from azure.storage.storageclient import _StorageClient - - -class TableService(_StorageClient): - - ''' - This is the main class managing Table resources. - ''' - - def __init__(self, account_name=None, account_key=None, protocol='https', - host_base=TABLE_SERVICE_HOST_BASE, dev_host=DEV_TABLE_HOST): - ''' - account_name: your storage account name, required for all operations. - account_key: your storage account key, required for all operations. - protocol: Optional. Protocol. Defaults to http. - host_base: - Optional. Live host base url. Defaults to Azure url. Override this - for on-premise. - dev_host: Optional. Dev host url. Defaults to localhost. - ''' - super(TableService, self).__init__( - account_name, account_key, protocol, host_base, dev_host) - - def begin_batch(self): - if self._batchclient is None: - self._batchclient = _BatchClient( - service_instance=self, - account_key=self.account_key, - account_name=self.account_name) - return self._batchclient.begin_batch() - - def commit_batch(self): - try: - ret = self._batchclient.commit_batch() - finally: - self._batchclient = None - return ret - - def cancel_batch(self): - self._batchclient = None - - def get_table_service_properties(self): - ''' - Gets the properties of a storage account's Table service, including - Windows Azure Storage Analytics. - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/?restype=service&comp=properties' - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _parse_response(response, StorageServiceProperties) - - def set_table_service_properties(self, storage_service_properties): - ''' - Sets the properties of a storage account's Table Service, including - Windows Azure Storage Analytics. - - storage_service_properties: StorageServiceProperties object. - ''' - _validate_not_none('storage_service_properties', - storage_service_properties) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/?restype=service&comp=properties' - request.body = _get_request_body( - _convert_class_to_xml(storage_service_properties)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _parse_response_for_dict(response) - - def query_tables(self, table_name=None, top=None, next_table_name=None): - ''' - Returns a list of tables under the specified account. - - table_name: Optional. The specific table to query. - top: Optional. Maximum number of tables to return. - next_table_name: - Optional. When top is used, the next table name is stored in - result.x_ms_continuation['NextTableName'] - ''' - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - if table_name is not None: - uri_part_table_name = "('" + table_name + "')" - else: - uri_part_table_name = "" - request.path = '/Tables' + uri_part_table_name + '' - request.query = [ - ('$top', _int_or_none(top)), - ('NextTableName', _str_or_none(next_table_name)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _convert_response_to_feeds(response, _convert_xml_to_table) - - def create_table(self, table, fail_on_exist=False): - ''' - Creates a new table in the storage account. - - table: - Name of the table to create. Table name may contain only - alphanumeric characters and cannot begin with a numeric character. - It is case-insensitive and must be from 3 to 63 characters long. - fail_on_exist: Specify whether throw exception when table exists. - ''' - _validate_not_none('table', table) - request = HTTPRequest() - request.method = 'POST' - request.host = self._get_host() - request.path = '/Tables' - request.body = _get_request_body(_convert_table_to_xml(table)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - if not fail_on_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_on_exist(ex) - return False - else: - self._perform_request(request) - return True - - def delete_table(self, table_name, fail_not_exist=False): - ''' - table_name: Name of the table to delete. - fail_not_exist: - Specify whether throw exception when table doesn't exist. - ''' - _validate_not_none('table_name', table_name) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/Tables(\'' + _str(table_name) + '\')' - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - if not fail_not_exist: - try: - self._perform_request(request) - return True - except WindowsAzureError as ex: - _dont_fail_not_exist(ex) - return False - else: - self._perform_request(request) - return True - - def get_entity(self, table_name, partition_key, row_key, select=''): - ''' - Get an entity in a table; includes the $select options. - - partition_key: PartitionKey of the entity. - row_key: RowKey of the entity. - select: Property names to select. - ''' - _validate_not_none('table_name', table_name) - _validate_not_none('partition_key', partition_key) - _validate_not_none('row_key', row_key) - _validate_not_none('select', select) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(table_name) + \ - '(PartitionKey=\'' + _str(partition_key) + \ - '\',RowKey=\'' + \ - _str(row_key) + '\')?$select=' + \ - _str(select) + '' - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _convert_response_to_entity(response) - - def query_entities(self, table_name, filter=None, select=None, top=None, - next_partition_key=None, next_row_key=None): - ''' - Get entities in a table; includes the $filter and $select options. - - table_name: Table to query. - filter: - Optional. Filter as described at - http://msdn.microsoft.com/en-us/library/windowsazure/dd894031.aspx - select: Optional. Property names to select from the entities. - top: Optional. Maximum number of entities to return. - next_partition_key: - Optional. When top is used, the next partition key is stored in - result.x_ms_continuation['NextPartitionKey'] - next_row_key: - Optional. When top is used, the next partition key is stored in - result.x_ms_continuation['NextRowKey'] - ''' - _validate_not_none('table_name', table_name) - request = HTTPRequest() - request.method = 'GET' - request.host = self._get_host() - request.path = '/' + _str(table_name) + '()' - request.query = [ - ('$filter', _str_or_none(filter)), - ('$select', _str_or_none(select)), - ('$top', _int_or_none(top)), - ('NextPartitionKey', _str_or_none(next_partition_key)), - ('NextRowKey', _str_or_none(next_row_key)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _convert_response_to_feeds(response, _convert_xml_to_entity) - - def insert_entity(self, table_name, entity, - content_type='application/atom+xml'): - ''' - Inserts a new entity into a table. - - table_name: Table name. - entity: - Required. The entity object to insert. Could be a dict format or - entity object. - content_type: Required. Must be set to application/atom+xml - ''' - _validate_not_none('table_name', table_name) - _validate_not_none('entity', entity) - _validate_not_none('content_type', content_type) - request = HTTPRequest() - request.method = 'POST' - request.host = self._get_host() - request.path = '/' + _str(table_name) + '' - request.headers = [('Content-Type', _str_or_none(content_type))] - request.body = _get_request_body(_convert_entity_to_xml(entity)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _convert_response_to_entity(response) - - def update_entity(self, table_name, partition_key, row_key, entity, - content_type='application/atom+xml', if_match='*'): - ''' - Updates an existing entity in a table. The Update Entity operation - replaces the entire entity and can be used to remove properties. - - table_name: Table name. - partition_key: PartitionKey of the entity. - row_key: RowKey of the entity. - entity: - Required. The entity object to insert. Could be a dict format or - entity object. - content_type: Required. Must be set to application/atom+xml - if_match: - Optional. Specifies the condition for which the merge should be - performed. To force an unconditional merge, set to the wildcard - character (*). - ''' - _validate_not_none('table_name', table_name) - _validate_not_none('partition_key', partition_key) - _validate_not_none('row_key', row_key) - _validate_not_none('entity', entity) - _validate_not_none('content_type', content_type) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(table_name) + '(PartitionKey=\'' + \ - _str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')' - request.headers = [ - ('Content-Type', _str_or_none(content_type)), - ('If-Match', _str_or_none(if_match)) - ] - request.body = _get_request_body(_convert_entity_to_xml(entity)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _parse_response_for_dict_filter(response, filter=['etag']) - - def merge_entity(self, table_name, partition_key, row_key, entity, - content_type='application/atom+xml', if_match='*'): - ''' - Updates an existing entity by updating the entity's properties. This - operation does not replace the existing entity as the Update Entity - operation does. - - table_name: Table name. - partition_key: PartitionKey of the entity. - row_key: RowKey of the entity. - entity: - Required. The entity object to insert. Can be a dict format or - entity object. - content_type: Required. Must be set to application/atom+xml - if_match: - Optional. Specifies the condition for which the merge should be - performed. To force an unconditional merge, set to the wildcard - character (*). - ''' - _validate_not_none('table_name', table_name) - _validate_not_none('partition_key', partition_key) - _validate_not_none('row_key', row_key) - _validate_not_none('entity', entity) - _validate_not_none('content_type', content_type) - request = HTTPRequest() - request.method = 'MERGE' - request.host = self._get_host() - request.path = '/' + \ - _str(table_name) + '(PartitionKey=\'' + \ - _str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')' - request.headers = [ - ('Content-Type', _str_or_none(content_type)), - ('If-Match', _str_or_none(if_match)) - ] - request.body = _get_request_body(_convert_entity_to_xml(entity)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _parse_response_for_dict_filter(response, filter=['etag']) - - def delete_entity(self, table_name, partition_key, row_key, - content_type='application/atom+xml', if_match='*'): - ''' - Deletes an existing entity in a table. - - table_name: Table name. - partition_key: PartitionKey of the entity. - row_key: RowKey of the entity. - content_type: Required. Must be set to application/atom+xml - if_match: - Optional. Specifies the condition for which the delete should be - performed. To force an unconditional delete, set to the wildcard - character (*). - ''' - _validate_not_none('table_name', table_name) - _validate_not_none('partition_key', partition_key) - _validate_not_none('row_key', row_key) - _validate_not_none('content_type', content_type) - _validate_not_none('if_match', if_match) - request = HTTPRequest() - request.method = 'DELETE' - request.host = self._get_host() - request.path = '/' + \ - _str(table_name) + '(PartitionKey=\'' + \ - _str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')' - request.headers = [ - ('Content-Type', _str_or_none(content_type)), - ('If-Match', _str_or_none(if_match)) - ] - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - self._perform_request(request) - - def insert_or_replace_entity(self, table_name, partition_key, row_key, - entity, content_type='application/atom+xml'): - ''' - Replaces an existing entity or inserts a new entity if it does not - exist in the table. Because this operation can insert or update an - entity, it is also known as an "upsert" operation. - - table_name: Table name. - partition_key: PartitionKey of the entity. - row_key: RowKey of the entity. - entity: - Required. The entity object to insert. Could be a dict format or - entity object. - content_type: Required. Must be set to application/atom+xml - ''' - _validate_not_none('table_name', table_name) - _validate_not_none('partition_key', partition_key) - _validate_not_none('row_key', row_key) - _validate_not_none('entity', entity) - _validate_not_none('content_type', content_type) - request = HTTPRequest() - request.method = 'PUT' - request.host = self._get_host() - request.path = '/' + \ - _str(table_name) + '(PartitionKey=\'' + \ - _str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')' - request.headers = [('Content-Type', _str_or_none(content_type))] - request.body = _get_request_body(_convert_entity_to_xml(entity)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _parse_response_for_dict_filter(response, filter=['etag']) - - def insert_or_merge_entity(self, table_name, partition_key, row_key, - entity, content_type='application/atom+xml'): - ''' - Merges an existing entity or inserts a new entity if it does not exist - in the table. Because this operation can insert or update an entity, - it is also known as an "upsert" operation. - - table_name: Table name. - partition_key: PartitionKey of the entity. - row_key: RowKey of the entity. - entity: - Required. The entity object to insert. Could be a dict format or - entity object. - content_type: Required. Must be set to application/atom+xml - ''' - _validate_not_none('table_name', table_name) - _validate_not_none('partition_key', partition_key) - _validate_not_none('row_key', row_key) - _validate_not_none('entity', entity) - _validate_not_none('content_type', content_type) - request = HTTPRequest() - request.method = 'MERGE' - request.host = self._get_host() - request.path = '/' + \ - _str(table_name) + '(PartitionKey=\'' + \ - _str(partition_key) + '\',RowKey=\'' + _str(row_key) + '\')' - request.headers = [('Content-Type', _str_or_none(content_type))] - request.body = _get_request_body(_convert_entity_to_xml(entity)) - request.path, request.query = _update_request_uri_query_local_storage( - request, self.use_local_storage) - request.headers = _update_storage_table_header(request) - response = self._perform_request(request) - - return _parse_response_for_dict_filter(response, filter=['etag']) - - def _perform_request_worker(self, request): - auth = _sign_storage_table_request(request, - self.account_name, - self.account_key) - request.headers.append(('Authorization', auth)) - return self._httpclient.perform_request(request) diff --git a/awx/lib/site-packages/babel/__init__.py b/awx/lib/site-packages/babel/__init__.py deleted file mode 100644 index dd9f17e04d..0000000000 --- a/awx/lib/site-packages/babel/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel - ~~~~~ - - Integrated collection of utilities that assist in internationalizing and - localizing applications. - - This package is basically composed of two major parts: - - * tools to build and work with ``gettext`` message catalogs - * a Python interface to the CLDR (Common Locale Data Repository), providing - access to various locale display names, localized number and date - formatting, etc. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -from babel.core import UnknownLocaleError, Locale, default_locale, \ - negotiate_locale, parse_locale, get_locale_identifier - - -__version__ = '1.3' diff --git a/awx/lib/site-packages/babel/_compat.py b/awx/lib/site-packages/babel/_compat.py deleted file mode 100644 index 86096daa61..0000000000 --- a/awx/lib/site-packages/babel/_compat.py +++ /dev/null @@ -1,51 +0,0 @@ -import sys - -PY2 = sys.version_info[0] == 2 - -_identity = lambda x: x - - -if not PY2: - text_type = str - string_types = (str,) - integer_types = (int, ) - unichr = chr - - text_to_native = lambda s, enc: s - - iterkeys = lambda d: iter(d.keys()) - itervalues = lambda d: iter(d.values()) - iteritems = lambda d: iter(d.items()) - - from io import StringIO, BytesIO - import pickle - - izip = zip - imap = map - range_type = range - - cmp = lambda a, b: (a > b) - (a < b) - -else: - text_type = unicode - string_types = (str, unicode) - integer_types = (int, long) - - text_to_native = lambda s, enc: s.encode(enc) - unichr = unichr - - iterkeys = lambda d: d.iterkeys() - itervalues = lambda d: d.itervalues() - iteritems = lambda d: d.iteritems() - - from cStringIO import StringIO as BytesIO - from StringIO import StringIO - import cPickle as pickle - - from itertools import izip, imap - range_type = xrange - - cmp = cmp - - -number_types = integer_types + (float,) diff --git a/awx/lib/site-packages/babel/core.py b/awx/lib/site-packages/babel/core.py deleted file mode 100644 index 6e6e6d6194..0000000000 --- a/awx/lib/site-packages/babel/core.py +++ /dev/null @@ -1,941 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.core - ~~~~~~~~~~ - - Core locale representation and locale data access. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import os - -from babel import localedata -from babel._compat import pickle, string_types - -__all__ = ['UnknownLocaleError', 'Locale', 'default_locale', 'negotiate_locale', - 'parse_locale'] - - -_global_data = None - - -def _raise_no_data_error(): - raise RuntimeError('The babel data files are not available. ' - 'This usually happens because you are using ' - 'a source checkout from Babel and you did ' - 'not build the data files. Just make sure ' - 'to run "python setup.py import_cldr" before ' - 'installing the library.') - - -def get_global(key): - """Return the dictionary for the given key in the global data. - - The global data is stored in the ``babel/global.dat`` file and contains - information independent of individual locales. - - >>> get_global('zone_aliases')['UTC'] - u'Etc/GMT' - >>> get_global('zone_territories')['Europe/Berlin'] - u'DE' - - .. versionadded:: 0.9 - - :param key: the data key - """ - global _global_data - if _global_data is None: - dirname = os.path.join(os.path.dirname(__file__)) - filename = os.path.join(dirname, 'global.dat') - if not os.path.isfile(filename): - _raise_no_data_error() - fileobj = open(filename, 'rb') - try: - _global_data = pickle.load(fileobj) - finally: - fileobj.close() - return _global_data.get(key, {}) - - -LOCALE_ALIASES = { - 'ar': 'ar_SY', 'bg': 'bg_BG', 'bs': 'bs_BA', 'ca': 'ca_ES', 'cs': 'cs_CZ', - 'da': 'da_DK', 'de': 'de_DE', 'el': 'el_GR', 'en': 'en_US', 'es': 'es_ES', - 'et': 'et_EE', 'fa': 'fa_IR', 'fi': 'fi_FI', 'fr': 'fr_FR', 'gl': 'gl_ES', - 'he': 'he_IL', 'hu': 'hu_HU', 'id': 'id_ID', 'is': 'is_IS', 'it': 'it_IT', - 'ja': 'ja_JP', 'km': 'km_KH', 'ko': 'ko_KR', 'lt': 'lt_LT', 'lv': 'lv_LV', - 'mk': 'mk_MK', 'nl': 'nl_NL', 'nn': 'nn_NO', 'no': 'nb_NO', 'pl': 'pl_PL', - 'pt': 'pt_PT', 'ro': 'ro_RO', 'ru': 'ru_RU', 'sk': 'sk_SK', 'sl': 'sl_SI', - 'sv': 'sv_SE', 'th': 'th_TH', 'tr': 'tr_TR', 'uk': 'uk_UA' -} - - -class UnknownLocaleError(Exception): - """Exception thrown when a locale is requested for which no locale data - is available. - """ - - def __init__(self, identifier): - """Create the exception. - - :param identifier: the identifier string of the unsupported locale - """ - Exception.__init__(self, 'unknown locale %r' % identifier) - - #: The identifier of the locale that could not be found. - self.identifier = identifier - - -class Locale(object): - """Representation of a specific locale. - - >>> locale = Locale('en', 'US') - >>> repr(locale) - "Locale('en', territory='US')" - >>> locale.display_name - u'English (United States)' - - A `Locale` object can also be instantiated from a raw locale string: - - >>> locale = Locale.parse('en-US', sep='-') - >>> repr(locale) - "Locale('en', territory='US')" - - `Locale` objects provide access to a collection of locale data, such as - territory and language names, number and date format patterns, and more: - - >>> locale.number_symbols['decimal'] - u'.' - - If a locale is requested for which no locale data is available, an - `UnknownLocaleError` is raised: - - >>> Locale.parse('en_DE') - Traceback (most recent call last): - ... - UnknownLocaleError: unknown locale 'en_DE' - - For more information see :rfc:`3066`. - """ - - def __init__(self, language, territory=None, script=None, variant=None): - """Initialize the locale object from the given identifier components. - - >>> locale = Locale('en', 'US') - >>> locale.language - 'en' - >>> locale.territory - 'US' - - :param language: the language code - :param territory: the territory (country or region) code - :param script: the script code - :param variant: the variant code - :raise `UnknownLocaleError`: if no locale data is available for the - requested locale - """ - #: the language code - self.language = language - #: the territory (country or region) code - self.territory = territory - #: the script code - self.script = script - #: the variant code - self.variant = variant - self.__data = None - - identifier = str(self) - if not localedata.exists(identifier): - raise UnknownLocaleError(identifier) - - @classmethod - def default(cls, category=None, aliases=LOCALE_ALIASES): - """Return the system default locale for the specified category. - - >>> for name in ['LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LC_MESSAGES']: - ... os.environ[name] = '' - >>> os.environ['LANG'] = 'fr_FR.UTF-8' - >>> Locale.default('LC_MESSAGES') - Locale('fr', territory='FR') - - The following fallbacks to the variable are always considered: - - - ``LANGUAGE`` - - ``LC_ALL`` - - ``LC_CTYPE`` - - ``LANG`` - - :param category: one of the ``LC_XXX`` environment variable names - :param aliases: a dictionary of aliases for locale identifiers - """ - # XXX: use likely subtag expansion here instead of the - # aliases dictionary. - locale_string = default_locale(category, aliases=aliases) - return cls.parse(locale_string) - - @classmethod - def negotiate(cls, preferred, available, sep='_', aliases=LOCALE_ALIASES): - """Find the best match between available and requested locale strings. - - >>> Locale.negotiate(['de_DE', 'en_US'], ['de_DE', 'de_AT']) - Locale('de', territory='DE') - >>> Locale.negotiate(['de_DE', 'en_US'], ['en', 'de']) - Locale('de') - >>> Locale.negotiate(['de_DE', 'de'], ['en_US']) - - You can specify the character used in the locale identifiers to separate - the differnet components. This separator is applied to both lists. Also, - case is ignored in the comparison: - - >>> Locale.negotiate(['de-DE', 'de'], ['en-us', 'de-de'], sep='-') - Locale('de', territory='DE') - - :param preferred: the list of locale identifers preferred by the user - :param available: the list of locale identifiers available - :param aliases: a dictionary of aliases for locale identifiers - """ - identifier = negotiate_locale(preferred, available, sep=sep, - aliases=aliases) - if identifier: - return Locale.parse(identifier, sep=sep) - - @classmethod - def parse(cls, identifier, sep='_', resolve_likely_subtags=True): - """Create a `Locale` instance for the given locale identifier. - - >>> l = Locale.parse('de-DE', sep='-') - >>> l.display_name - u'Deutsch (Deutschland)' - - If the `identifier` parameter is not a string, but actually a `Locale` - object, that object is returned: - - >>> Locale.parse(l) - Locale('de', territory='DE') - - This also can perform resolving of likely subtags which it does - by default. This is for instance useful to figure out the most - likely locale for a territory you can use ``'und'`` as the - language tag: - - >>> Locale.parse('und_AT') - Locale('de', territory='AT') - - :param identifier: the locale identifier string - :param sep: optional component separator - :param resolve_likely_subtags: if this is specified then a locale will - have its likely subtag resolved if the - locale otherwise does not exist. For - instance ``zh_TW`` by itself is not a - locale that exists but Babel can - automatically expand it to the full - form of ``zh_hant_TW``. Note that this - expansion is only taking place if no - locale exists otherwise. For instance - there is a locale ``en`` that can exist - by itself. - :raise `ValueError`: if the string does not appear to be a valid locale - identifier - :raise `UnknownLocaleError`: if no locale data is available for the - requested locale - """ - if identifier is None: - return None - elif isinstance(identifier, Locale): - return identifier - elif not isinstance(identifier, string_types): - raise TypeError('Unxpected value for identifier: %r' % (identifier,)) - - parts = parse_locale(identifier, sep=sep) - input_id = get_locale_identifier(parts) - - def _try_load(parts): - try: - return cls(*parts) - except UnknownLocaleError: - return None - - def _try_load_reducing(parts): - # Success on first hit, return it. - locale = _try_load(parts) - if locale is not None: - return locale - - # Now try without script and variant - locale = _try_load(parts[:2]) - if locale is not None: - return locale - - locale = _try_load(parts) - if locale is not None: - return locale - if not resolve_likely_subtags: - raise UnknownLocaleError(input_id) - - # From here onwards is some very bad likely subtag resolving. This - # whole logic is not entirely correct but good enough (tm) for the - # time being. This has been added so that zh_TW does not cause - # errors for people when they upgrade. Later we should properly - # implement ICU like fuzzy locale objects and provide a way to - # maximize and minimize locale tags. - - language, territory, script, variant = parts - language = get_global('language_aliases').get(language, language) - territory = get_global('territory_aliases').get(territory, territory) - script = get_global('script_aliases').get(script, script) - variant = get_global('variant_aliases').get(variant, variant) - - if territory == 'ZZ': - territory = None - if script == 'Zzzz': - script = None - - parts = language, territory, script, variant - - # First match: try the whole identifier - new_id = get_locale_identifier(parts) - likely_subtag = get_global('likely_subtags').get(new_id) - if likely_subtag is not None: - locale = _try_load_reducing(parse_locale(likely_subtag)) - if locale is not None: - return locale - - # If we did not find anything so far, try again with a - # simplified identifier that is just the language - likely_subtag = get_global('likely_subtags').get(language) - if likely_subtag is not None: - language2, _, script2, variant2 = parse_locale(likely_subtag) - locale = _try_load_reducing((language2, territory, script2, variant2)) - if locale is not None: - return locale - - raise UnknownLocaleError(input_id) - - def __eq__(self, other): - for key in ('language', 'territory', 'script', 'variant'): - if not hasattr(other, key): - return False - return (self.language == other.language) and \ - (self.territory == other.territory) and \ - (self.script == other.script) and \ - (self.variant == other.variant) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - parameters = [''] - for key in ('territory', 'script', 'variant'): - value = getattr(self, key) - if value is not None: - parameters.append('%s=%r' % (key, value)) - parameter_string = '%r' % self.language + ', '.join(parameters) - return 'Locale(%s)' % parameter_string - - def __str__(self): - return get_locale_identifier((self.language, self.territory, - self.script, self.variant)) - - @property - def _data(self): - if self.__data is None: - self.__data = localedata.LocaleDataDict(localedata.load(str(self))) - return self.__data - - def get_display_name(self, locale=None): - """Return the display name of the locale using the given locale. - - The display name will include the language, territory, script, and - variant, if those are specified. - - >>> Locale('zh', 'CN', script='Hans').get_display_name('en') - u'Chinese (Simplified, China)' - - :param locale: the locale to use - """ - if locale is None: - locale = self - locale = Locale.parse(locale) - retval = locale.languages.get(self.language) - if self.territory or self.script or self.variant: - details = [] - if self.script: - details.append(locale.scripts.get(self.script)) - if self.territory: - details.append(locale.territories.get(self.territory)) - if self.variant: - details.append(locale.variants.get(self.variant)) - details = filter(None, details) - if details: - retval += ' (%s)' % u', '.join(details) - return retval - - display_name = property(get_display_name, doc="""\ - The localized display name of the locale. - - >>> Locale('en').display_name - u'English' - >>> Locale('en', 'US').display_name - u'English (United States)' - >>> Locale('sv').display_name - u'svenska' - - :type: `unicode` - """) - - def get_language_name(self, locale=None): - """Return the language of this locale in the given locale. - - >>> Locale('zh', 'CN', script='Hans').get_language_name('de') - u'Chinesisch' - - .. versionadded:: 1.0 - - :param locale: the locale to use - """ - if locale is None: - locale = self - locale = Locale.parse(locale) - return locale.languages.get(self.language) - - language_name = property(get_language_name, doc="""\ - The localized language name of the locale. - - >>> Locale('en', 'US').language_name - u'English' - """) - - def get_territory_name(self, locale=None): - """Return the territory name in the given locale.""" - if locale is None: - locale = self - locale = Locale.parse(locale) - return locale.territories.get(self.territory) - - territory_name = property(get_territory_name, doc="""\ - The localized territory name of the locale if available. - - >>> Locale('de', 'DE').territory_name - u'Deutschland' - """) - - def get_script_name(self, locale=None): - """Return the script name in the given locale.""" - if locale is None: - locale = self - locale = Locale.parse(locale) - return locale.scripts.get(self.script) - - script_name = property(get_script_name, doc="""\ - The localized script name of the locale if available. - - >>> Locale('ms', 'SG', script='Latn').script_name - u'Latin' - """) - - @property - def english_name(self): - """The english display name of the locale. - - >>> Locale('de').english_name - u'German' - >>> Locale('de', 'DE').english_name - u'German (Germany)' - - :type: `unicode`""" - return self.get_display_name(Locale('en')) - - #{ General Locale Display Names - - @property - def languages(self): - """Mapping of language codes to translated language names. - - >>> Locale('de', 'DE').languages['ja'] - u'Japanisch' - - See `ISO 639 <http://www.loc.gov/standards/iso639-2/>`_ for - more information. - """ - return self._data['languages'] - - @property - def scripts(self): - """Mapping of script codes to translated script names. - - >>> Locale('en', 'US').scripts['Hira'] - u'Hiragana' - - See `ISO 15924 <http://www.evertype.com/standards/iso15924/>`_ - for more information. - """ - return self._data['scripts'] - - @property - def territories(self): - """Mapping of script codes to translated script names. - - >>> Locale('es', 'CO').territories['DE'] - u'Alemania' - - See `ISO 3166 <http://www.iso.org/iso/en/prods-services/iso3166ma/>`_ - for more information. - """ - return self._data['territories'] - - @property - def variants(self): - """Mapping of script codes to translated script names. - - >>> Locale('de', 'DE').variants['1901'] - u'Alte deutsche Rechtschreibung' - """ - return self._data['variants'] - - #{ Number Formatting - - @property - def currencies(self): - """Mapping of currency codes to translated currency names. This - only returns the generic form of the currency name, not the count - specific one. If an actual number is requested use the - :func:`babel.numbers.get_currency_name` function. - - >>> Locale('en').currencies['COP'] - u'Colombian Peso' - >>> Locale('de', 'DE').currencies['COP'] - u'Kolumbianischer Peso' - """ - return self._data['currency_names'] - - @property - def currency_symbols(self): - """Mapping of currency codes to symbols. - - >>> Locale('en', 'US').currency_symbols['USD'] - u'$' - >>> Locale('es', 'CO').currency_symbols['USD'] - u'US$' - """ - return self._data['currency_symbols'] - - @property - def number_symbols(self): - """Symbols used in number formatting. - - >>> Locale('fr', 'FR').number_symbols['decimal'] - u',' - """ - return self._data['number_symbols'] - - @property - def decimal_formats(self): - """Locale patterns for decimal number formatting. - - >>> Locale('en', 'US').decimal_formats[None] - <NumberPattern u'#,##0.###'> - """ - return self._data['decimal_formats'] - - @property - def currency_formats(self): - """Locale patterns for currency number formatting. - - >>> print Locale('en', 'US').currency_formats[None] - <NumberPattern u'\\xa4#,##0.00'> - """ - return self._data['currency_formats'] - - @property - def percent_formats(self): - """Locale patterns for percent number formatting. - - >>> Locale('en', 'US').percent_formats[None] - <NumberPattern u'#,##0%'> - """ - return self._data['percent_formats'] - - @property - def scientific_formats(self): - """Locale patterns for scientific number formatting. - - >>> Locale('en', 'US').scientific_formats[None] - <NumberPattern u'#E0'> - """ - return self._data['scientific_formats'] - - #{ Calendar Information and Date Formatting - - @property - def periods(self): - """Locale display names for day periods (AM/PM). - - >>> Locale('en', 'US').periods['am'] - u'AM' - """ - return self._data['periods'] - - @property - def days(self): - """Locale display names for weekdays. - - >>> Locale('de', 'DE').days['format']['wide'][3] - u'Donnerstag' - """ - return self._data['days'] - - @property - def months(self): - """Locale display names for months. - - >>> Locale('de', 'DE').months['format']['wide'][10] - u'Oktober' - """ - return self._data['months'] - - @property - def quarters(self): - """Locale display names for quarters. - - >>> Locale('de', 'DE').quarters['format']['wide'][1] - u'1. Quartal' - """ - return self._data['quarters'] - - @property - def eras(self): - """Locale display names for eras. - - >>> Locale('en', 'US').eras['wide'][1] - u'Anno Domini' - >>> Locale('en', 'US').eras['abbreviated'][0] - u'BC' - """ - return self._data['eras'] - - @property - def time_zones(self): - """Locale display names for time zones. - - >>> Locale('en', 'US').time_zones['Europe/London']['long']['daylight'] - u'British Summer Time' - >>> Locale('en', 'US').time_zones['America/St_Johns']['city'] - u'St. John\u2019s' - """ - return self._data['time_zones'] - - @property - def meta_zones(self): - """Locale display names for meta time zones. - - Meta time zones are basically groups of different Olson time zones that - have the same GMT offset and daylight savings time. - - >>> Locale('en', 'US').meta_zones['Europe_Central']['long']['daylight'] - u'Central European Summer Time' - - .. versionadded:: 0.9 - """ - return self._data['meta_zones'] - - @property - def zone_formats(self): - """Patterns related to the formatting of time zones. - - >>> Locale('en', 'US').zone_formats['fallback'] - u'%(1)s (%(0)s)' - >>> Locale('pt', 'BR').zone_formats['region'] - u'Hor\\xe1rio %s' - - .. versionadded:: 0.9 - """ - return self._data['zone_formats'] - - @property - def first_week_day(self): - """The first day of a week, with 0 being Monday. - - >>> Locale('de', 'DE').first_week_day - 0 - >>> Locale('en', 'US').first_week_day - 6 - """ - return self._data['week_data']['first_day'] - - @property - def weekend_start(self): - """The day the weekend starts, with 0 being Monday. - - >>> Locale('de', 'DE').weekend_start - 5 - """ - return self._data['week_data']['weekend_start'] - - @property - def weekend_end(self): - """The day the weekend ends, with 0 being Monday. - - >>> Locale('de', 'DE').weekend_end - 6 - """ - return self._data['week_data']['weekend_end'] - - @property - def min_week_days(self): - """The minimum number of days in a week so that the week is counted as - the first week of a year or month. - - >>> Locale('de', 'DE').min_week_days - 4 - """ - return self._data['week_data']['min_days'] - - @property - def date_formats(self): - """Locale patterns for date formatting. - - >>> Locale('en', 'US').date_formats['short'] - <DateTimePattern u'M/d/yy'> - >>> Locale('fr', 'FR').date_formats['long'] - <DateTimePattern u'd MMMM y'> - """ - return self._data['date_formats'] - - @property - def time_formats(self): - """Locale patterns for time formatting. - - >>> Locale('en', 'US').time_formats['short'] - <DateTimePattern u'h:mm a'> - >>> Locale('fr', 'FR').time_formats['long'] - <DateTimePattern u'HH:mm:ss z'> - """ - return self._data['time_formats'] - - @property - def datetime_formats(self): - """Locale patterns for datetime formatting. - - >>> Locale('en').datetime_formats['full'] - u"{1} 'at' {0}" - >>> Locale('th').datetime_formats['medium'] - u'{1}, {0}' - """ - return self._data['datetime_formats'] - - @property - def plural_form(self): - """Plural rules for the locale. - - >>> Locale('en').plural_form(1) - 'one' - >>> Locale('en').plural_form(0) - 'other' - >>> Locale('fr').plural_form(0) - 'one' - >>> Locale('ru').plural_form(100) - 'many' - """ - return self._data['plural_form'] - - -def default_locale(category=None, aliases=LOCALE_ALIASES): - """Returns the system default locale for a given category, based on - environment variables. - - >>> for name in ['LANGUAGE', 'LC_ALL', 'LC_CTYPE']: - ... os.environ[name] = '' - >>> os.environ['LANG'] = 'fr_FR.UTF-8' - >>> default_locale('LC_MESSAGES') - 'fr_FR' - - The "C" or "POSIX" pseudo-locales are treated as aliases for the - "en_US_POSIX" locale: - - >>> os.environ['LC_MESSAGES'] = 'POSIX' - >>> default_locale('LC_MESSAGES') - 'en_US_POSIX' - - The following fallbacks to the variable are always considered: - - - ``LANGUAGE`` - - ``LC_ALL`` - - ``LC_CTYPE`` - - ``LANG`` - - :param category: one of the ``LC_XXX`` environment variable names - :param aliases: a dictionary of aliases for locale identifiers - """ - varnames = (category, 'LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LANG') - for name in filter(None, varnames): - locale = os.getenv(name) - if locale: - if name == 'LANGUAGE' and ':' in locale: - # the LANGUAGE variable may contain a colon-separated list of - # language codes; we just pick the language on the list - locale = locale.split(':')[0] - if locale in ('C', 'POSIX'): - locale = 'en_US_POSIX' - elif aliases and locale in aliases: - locale = aliases[locale] - try: - return get_locale_identifier(parse_locale(locale)) - except ValueError: - pass - - -def negotiate_locale(preferred, available, sep='_', aliases=LOCALE_ALIASES): - """Find the best match between available and requested locale strings. - - >>> negotiate_locale(['de_DE', 'en_US'], ['de_DE', 'de_AT']) - 'de_DE' - >>> negotiate_locale(['de_DE', 'en_US'], ['en', 'de']) - 'de' - - Case is ignored by the algorithm, the result uses the case of the preferred - locale identifier: - - >>> negotiate_locale(['de_DE', 'en_US'], ['de_de', 'de_at']) - 'de_DE' - - >>> negotiate_locale(['de_DE', 'en_US'], ['de_de', 'de_at']) - 'de_DE' - - By default, some web browsers unfortunately do not include the territory - in the locale identifier for many locales, and some don't even allow the - user to easily add the territory. So while you may prefer using qualified - locale identifiers in your web-application, they would not normally match - the language-only locale sent by such browsers. To workaround that, this - function uses a default mapping of commonly used langauge-only locale - identifiers to identifiers including the territory: - - >>> negotiate_locale(['ja', 'en_US'], ['ja_JP', 'en_US']) - 'ja_JP' - - Some browsers even use an incorrect or outdated language code, such as "no" - for Norwegian, where the correct locale identifier would actually be "nb_NO" - (BokmÃ¥l) or "nn_NO" (Nynorsk). The aliases are intended to take care of - such cases, too: - - >>> negotiate_locale(['no', 'sv'], ['nb_NO', 'sv_SE']) - 'nb_NO' - - You can override this default mapping by passing a different `aliases` - dictionary to this function, or you can bypass the behavior althogher by - setting the `aliases` parameter to `None`. - - :param preferred: the list of locale strings preferred by the user - :param available: the list of locale strings available - :param sep: character that separates the different parts of the locale - strings - :param aliases: a dictionary of aliases for locale identifiers - """ - available = [a.lower() for a in available if a] - for locale in preferred: - ll = locale.lower() - if ll in available: - return locale - if aliases: - alias = aliases.get(ll) - if alias: - alias = alias.replace('_', sep) - if alias.lower() in available: - return alias - parts = locale.split(sep) - if len(parts) > 1 and parts[0].lower() in available: - return parts[0] - return None - - -def parse_locale(identifier, sep='_'): - """Parse a locale identifier into a tuple of the form ``(language, - territory, script, variant)``. - - >>> parse_locale('zh_CN') - ('zh', 'CN', None, None) - >>> parse_locale('zh_Hans_CN') - ('zh', 'CN', 'Hans', None) - - The default component separator is "_", but a different separator can be - specified using the `sep` parameter: - - >>> parse_locale('zh-CN', sep='-') - ('zh', 'CN', None, None) - - If the identifier cannot be parsed into a locale, a `ValueError` exception - is raised: - - >>> parse_locale('not_a_LOCALE_String') - Traceback (most recent call last): - ... - ValueError: 'not_a_LOCALE_String' is not a valid locale identifier - - Encoding information and locale modifiers are removed from the identifier: - - >>> parse_locale('it_IT@euro') - ('it', 'IT', None, None) - >>> parse_locale('en_US.UTF-8') - ('en', 'US', None, None) - >>> parse_locale('de_DE.iso885915@euro') - ('de', 'DE', None, None) - - See :rfc:`4646` for more information. - - :param identifier: the locale identifier string - :param sep: character that separates the different components of the locale - identifier - :raise `ValueError`: if the string does not appear to be a valid locale - identifier - """ - if '.' in identifier: - # this is probably the charset/encoding, which we don't care about - identifier = identifier.split('.', 1)[0] - if '@' in identifier: - # this is a locale modifier such as @euro, which we don't care about - # either - identifier = identifier.split('@', 1)[0] - - parts = identifier.split(sep) - lang = parts.pop(0).lower() - if not lang.isalpha(): - raise ValueError('expected only letters, got %r' % lang) - - script = territory = variant = None - if parts: - if len(parts[0]) == 4 and parts[0].isalpha(): - script = parts.pop(0).title() - - if parts: - if len(parts[0]) == 2 and parts[0].isalpha(): - territory = parts.pop(0).upper() - elif len(parts[0]) == 3 and parts[0].isdigit(): - territory = parts.pop(0) - - if parts: - if len(parts[0]) == 4 and parts[0][0].isdigit() or \ - len(parts[0]) >= 5 and parts[0][0].isalpha(): - variant = parts.pop() - - if parts: - raise ValueError('%r is not a valid locale identifier' % identifier) - - return lang, territory, script, variant - - -def get_locale_identifier(tup, sep='_'): - """The reverse of :func:`parse_locale`. It creates a locale identifier out - of a ``(language, territory, script, variant)`` tuple. Items can be set to - ``None`` and trailing ``None``\s can also be left out of the tuple. - - >>> get_locale_identifier(('de', 'DE', None, '1999')) - 'de_DE_1999' - - .. versionadded:: 1.0 - - :param tup: the tuple as returned by :func:`parse_locale`. - :param sep: the separator for the identifier. - """ - tup = tuple(tup[:4]) - lang, territory, script, variant = tup + (None,) * (4 - len(tup)) - return sep.join(filter(None, (lang, script, territory, variant))) diff --git a/awx/lib/site-packages/babel/dates.py b/awx/lib/site-packages/babel/dates.py deleted file mode 100644 index 72674e8aa4..0000000000 --- a/awx/lib/site-packages/babel/dates.py +++ /dev/null @@ -1,1181 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.dates - ~~~~~~~~~~~ - - Locale dependent formatting and parsing of dates and times. - - The default locale for the functions in this module is determined by the - following environment variables, in that order: - - * ``LC_TIME``, - * ``LC_ALL``, and - * ``LANG`` - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -from __future__ import division - -import re -import pytz as _pytz - -from datetime import date, datetime, time, timedelta -from bisect import bisect_right - -from babel.core import default_locale, get_global, Locale -from babel.util import UTC, LOCALTZ -from babel._compat import string_types, integer_types, number_types - - -LC_TIME = default_locale('LC_TIME') - -# Aliases for use in scopes where the modules are shadowed by local variables -date_ = date -datetime_ = datetime -time_ = time - - -def get_timezone(zone=None): - """Looks up a timezone by name and returns it. The timezone object - returned comes from ``pytz`` and corresponds to the `tzinfo` interface and - can be used with all of the functions of Babel that operate with dates. - - If a timezone is not known a :exc:`LookupError` is raised. If `zone` - is ``None`` a local zone object is returned. - - :param zone: the name of the timezone to look up. If a timezone object - itself is passed in, mit's returned unchanged. - """ - if zone is None: - return LOCALTZ - if not isinstance(zone, string_types): - return zone - try: - return _pytz.timezone(zone) - except _pytz.UnknownTimeZoneError: - raise LookupError('Unknown timezone %s' % zone) - - -def get_next_timezone_transition(zone=None, dt=None): - """Given a timezone it will return a :class:`TimezoneTransition` object - that holds the information about the next timezone transition that's going - to happen. For instance this can be used to detect when the next DST - change is going to happen and how it looks like. - - The transition is calculated relative to the given datetime object. The - next transition that follows the date is used. If a transition cannot - be found the return value will be `None`. - - Transition information can only be provided for timezones returned by - the :func:`get_timezone` function. - - :param zone: the timezone for which the transition should be looked up. - If not provided the local timezone is used. - :param dt: the date after which the next transition should be found. - If not given the current time is assumed. - """ - zone = get_timezone(zone) - if dt is None: - dt = datetime.utcnow() - else: - dt = dt.replace(tzinfo=None) - - if not hasattr(zone, '_utc_transition_times'): - raise TypeError('Given timezone does not have UTC transition ' - 'times. This can happen because the operating ' - 'system fallback local timezone is used or a ' - 'custom timezone object') - - try: - idx = max(0, bisect_right(zone._utc_transition_times, dt)) - old_trans = zone._transition_info[idx - 1] - new_trans = zone._transition_info[idx] - old_tz = zone._tzinfos[old_trans] - new_tz = zone._tzinfos[new_trans] - except (LookupError, ValueError): - return None - - return TimezoneTransition( - activates=zone._utc_transition_times[idx], - from_tzinfo=old_tz, - to_tzinfo=new_tz, - reference_date=dt - ) - - -class TimezoneTransition(object): - """A helper object that represents the return value from - :func:`get_next_timezone_transition`. - """ - - def __init__(self, activates, from_tzinfo, to_tzinfo, reference_date=None): - #: the time of the activation of the timezone transition in UTC. - self.activates = activates - #: the timezone from where the transition starts. - self.from_tzinfo = from_tzinfo - #: the timezone for after the transition. - self.to_tzinfo = to_tzinfo - #: the reference date that was provided. This is the `dt` parameter - #: to the :func:`get_next_timezone_transition`. - self.reference_date = reference_date - - @property - def from_tz(self): - """The name of the timezone before the transition.""" - return self.from_tzinfo._tzname - - @property - def to_tz(self): - """The name of the timezone after the transition.""" - return self.to_tzinfo._tzname - - @property - def from_offset(self): - """The UTC offset in seconds before the transition.""" - return int(self.from_tzinfo._utcoffset.total_seconds()) - - @property - def to_offset(self): - """The UTC offset in seconds after the transition.""" - return int(self.to_tzinfo._utcoffset.total_seconds()) - - def __repr__(self): - return '<TimezoneTransition %s -> %s (%s)>' % ( - self.from_tz, - self.to_tz, - self.activates, - ) - - -def get_period_names(locale=LC_TIME): - """Return the names for day periods (AM/PM) used by the locale. - - >>> get_period_names(locale='en_US')['am'] - u'AM' - - :param locale: the `Locale` object, or a locale string - """ - return Locale.parse(locale).periods - - -def get_day_names(width='wide', context='format', locale=LC_TIME): - """Return the day names used by the locale for the specified format. - - >>> get_day_names('wide', locale='en_US')[1] - u'Tuesday' - >>> get_day_names('abbreviated', locale='es')[1] - u'mar' - >>> get_day_names('narrow', context='stand-alone', locale='de_DE')[1] - u'D' - - :param width: the width to use, one of "wide", "abbreviated", or "narrow" - :param context: the context, either "format" or "stand-alone" - :param locale: the `Locale` object, or a locale string - """ - return Locale.parse(locale).days[context][width] - - -def get_month_names(width='wide', context='format', locale=LC_TIME): - """Return the month names used by the locale for the specified format. - - >>> get_month_names('wide', locale='en_US')[1] - u'January' - >>> get_month_names('abbreviated', locale='es')[1] - u'ene' - >>> get_month_names('narrow', context='stand-alone', locale='de_DE')[1] - u'J' - - :param width: the width to use, one of "wide", "abbreviated", or "narrow" - :param context: the context, either "format" or "stand-alone" - :param locale: the `Locale` object, or a locale string - """ - return Locale.parse(locale).months[context][width] - - -def get_quarter_names(width='wide', context='format', locale=LC_TIME): - """Return the quarter names used by the locale for the specified format. - - >>> get_quarter_names('wide', locale='en_US')[1] - u'1st quarter' - >>> get_quarter_names('abbreviated', locale='de_DE')[1] - u'Q1' - - :param width: the width to use, one of "wide", "abbreviated", or "narrow" - :param context: the context, either "format" or "stand-alone" - :param locale: the `Locale` object, or a locale string - """ - return Locale.parse(locale).quarters[context][width] - - -def get_era_names(width='wide', locale=LC_TIME): - """Return the era names used by the locale for the specified format. - - >>> get_era_names('wide', locale='en_US')[1] - u'Anno Domini' - >>> get_era_names('abbreviated', locale='de_DE')[1] - u'n. Chr.' - - :param width: the width to use, either "wide", "abbreviated", or "narrow" - :param locale: the `Locale` object, or a locale string - """ - return Locale.parse(locale).eras[width] - - -def get_date_format(format='medium', locale=LC_TIME): - """Return the date formatting patterns used by the locale for the specified - format. - - >>> get_date_format(locale='en_US') - <DateTimePattern u'MMM d, y'> - >>> get_date_format('full', locale='de_DE') - <DateTimePattern u'EEEE, d. MMMM y'> - - :param format: the format to use, one of "full", "long", "medium", or - "short" - :param locale: the `Locale` object, or a locale string - """ - return Locale.parse(locale).date_formats[format] - - -def get_datetime_format(format='medium', locale=LC_TIME): - """Return the datetime formatting patterns used by the locale for the - specified format. - - >>> get_datetime_format(locale='en_US') - u'{1}, {0}' - - :param format: the format to use, one of "full", "long", "medium", or - "short" - :param locale: the `Locale` object, or a locale string - """ - patterns = Locale.parse(locale).datetime_formats - if format not in patterns: - format = None - return patterns[format] - - -def get_time_format(format='medium', locale=LC_TIME): - """Return the time formatting patterns used by the locale for the specified - format. - - >>> get_time_format(locale='en_US') - <DateTimePattern u'h:mm:ss a'> - >>> get_time_format('full', locale='de_DE') - <DateTimePattern u'HH:mm:ss zzzz'> - - :param format: the format to use, one of "full", "long", "medium", or - "short" - :param locale: the `Locale` object, or a locale string - """ - return Locale.parse(locale).time_formats[format] - - -def get_timezone_gmt(datetime=None, width='long', locale=LC_TIME): - """Return the timezone associated with the given `datetime` object formatted - as string indicating the offset from GMT. - - >>> dt = datetime(2007, 4, 1, 15, 30) - >>> get_timezone_gmt(dt, locale='en') - u'GMT+00:00' - - >>> tz = get_timezone('America/Los_Angeles') - >>> dt = datetime(2007, 4, 1, 15, 30, tzinfo=tz) - >>> get_timezone_gmt(dt, locale='en') - u'GMT-08:00' - >>> get_timezone_gmt(dt, 'short', locale='en') - u'-0800' - - The long format depends on the locale, for example in France the acronym - UTC string is used instead of GMT: - - >>> get_timezone_gmt(dt, 'long', locale='fr_FR') - u'UTC-08:00' - - .. versionadded:: 0.9 - - :param datetime: the ``datetime`` object; if `None`, the current date and - time in UTC is used - :param width: either "long" or "short" - :param locale: the `Locale` object, or a locale string - """ - if datetime is None: - datetime = datetime_.utcnow() - elif isinstance(datetime, integer_types): - datetime = datetime_.utcfromtimestamp(datetime).time() - if datetime.tzinfo is None: - datetime = datetime.replace(tzinfo=UTC) - locale = Locale.parse(locale) - - offset = datetime.tzinfo.utcoffset(datetime) - seconds = offset.days * 24 * 60 * 60 + offset.seconds - hours, seconds = divmod(seconds, 3600) - if width == 'short': - pattern = u'%+03d%02d' - else: - pattern = locale.zone_formats['gmt'] % '%+03d:%02d' - return pattern % (hours, seconds // 60) - - -def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME): - """Return a representation of the given timezone using "location format". - - The result depends on both the local display name of the country and the - city associated with the time zone: - - >>> tz = get_timezone('America/St_Johns') - >>> get_timezone_location(tz, locale='de_DE') - u"Kanada (St. John's) Zeit" - >>> tz = get_timezone('America/Mexico_City') - >>> get_timezone_location(tz, locale='de_DE') - u'Mexiko (Mexiko-Stadt) Zeit' - - If the timezone is associated with a country that uses only a single - timezone, just the localized country name is returned: - - >>> tz = get_timezone('Europe/Berlin') - >>> get_timezone_name(tz, locale='de_DE') - u'Mitteleurop\\xe4ische Zeit' - - .. versionadded:: 0.9 - - :param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines - the timezone; if `None`, the current date and time in - UTC is assumed - :param locale: the `Locale` object, or a locale string - :return: the localized timezone name using location format - """ - if dt_or_tzinfo is None: - dt = datetime.now() - tzinfo = LOCALTZ - elif isinstance(dt_or_tzinfo, string_types): - dt = None - tzinfo = get_timezone(dt_or_tzinfo) - elif isinstance(dt_or_tzinfo, integer_types): - dt = None - tzinfo = UTC - elif isinstance(dt_or_tzinfo, (datetime, time)): - dt = dt_or_tzinfo - if dt.tzinfo is not None: - tzinfo = dt.tzinfo - else: - tzinfo = UTC - else: - dt = None - tzinfo = dt_or_tzinfo - locale = Locale.parse(locale) - - if hasattr(tzinfo, 'zone'): - zone = tzinfo.zone - else: - zone = tzinfo.tzname(dt or datetime.utcnow()) - - # Get the canonical time-zone code - zone = get_global('zone_aliases').get(zone, zone) - - info = locale.time_zones.get(zone, {}) - - # Otherwise, if there is only one timezone for the country, return the - # localized country name - region_format = locale.zone_formats['region'] - territory = get_global('zone_territories').get(zone) - if territory not in locale.territories: - territory = 'ZZ' # invalid/unknown - territory_name = locale.territories[territory] - if territory and len(get_global('territory_zones').get(territory, [])) == 1: - return region_format % (territory_name) - - # Otherwise, include the city in the output - fallback_format = locale.zone_formats['fallback'] - if 'city' in info: - city_name = info['city'] - else: - metazone = get_global('meta_zones').get(zone) - metazone_info = locale.meta_zones.get(metazone, {}) - if 'city' in metazone_info: - city_name = metazone_info['city'] - elif '/' in zone: - city_name = zone.split('/', 1)[1].replace('_', ' ') - else: - city_name = zone.replace('_', ' ') - - return region_format % (fallback_format % { - '0': city_name, - '1': territory_name - }) - - -def get_timezone_name(dt_or_tzinfo=None, width='long', uncommon=False, - locale=LC_TIME, zone_variant=None): - r"""Return the localized display name for the given timezone. The timezone - may be specified using a ``datetime`` or `tzinfo` object. - - >>> dt = time(15, 30, tzinfo=get_timezone('America/Los_Angeles')) - >>> get_timezone_name(dt, locale='en_US') - u'Pacific Standard Time' - >>> get_timezone_name(dt, width='short', locale='en_US') - u'PST' - - If this function gets passed only a `tzinfo` object and no concrete - `datetime`, the returned display name is indenpendent of daylight savings - time. This can be used for example for selecting timezones, or to set the - time of events that recur across DST changes: - - >>> tz = get_timezone('America/Los_Angeles') - >>> get_timezone_name(tz, locale='en_US') - u'Pacific Time' - >>> get_timezone_name(tz, 'short', locale='en_US') - u'PT' - - If no localized display name for the timezone is available, and the timezone - is associated with a country that uses only a single timezone, the name of - that country is returned, formatted according to the locale: - - >>> tz = get_timezone('Europe/Berlin') - >>> get_timezone_name(tz, locale='de_DE') - u'Mitteleurop\xe4ische Zeit' - >>> get_timezone_name(tz, locale='pt_BR') - u'Hor\xe1rio da Europa Central' - - On the other hand, if the country uses multiple timezones, the city is also - included in the representation: - - >>> tz = get_timezone('America/St_Johns') - >>> get_timezone_name(tz, locale='de_DE') - u'Neufundland-Zeit' - - Note that short format is currently not supported for all timezones and - all locales. This is partially because not every timezone has a short - code in every locale. In that case it currently falls back to the long - format. - - For more information see `LDML Appendix J: Time Zone Display Names - <http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_ - - .. versionadded:: 0.9 - - .. versionchanged:: 1.0 - Added `zone_variant` support. - - :param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines - the timezone; if a ``tzinfo`` object is used, the - resulting display name will be generic, i.e. - independent of daylight savings time; if `None`, the - current date in UTC is assumed - :param width: either "long" or "short" - :param uncommon: deprecated and ignored - :param zone_variant: defines the zone variation to return. By default the - variation is defined from the datetime object - passed in. If no datetime object is passed in, the - ``'generic'`` variation is assumed. The following - values are valid: ``'generic'``, ``'daylight'`` and - ``'standard'``. - :param locale: the `Locale` object, or a locale string - """ - if dt_or_tzinfo is None: - dt = datetime.now() - tzinfo = LOCALTZ - elif isinstance(dt_or_tzinfo, string_types): - dt = None - tzinfo = get_timezone(dt_or_tzinfo) - elif isinstance(dt_or_tzinfo, integer_types): - dt = None - tzinfo = UTC - elif isinstance(dt_or_tzinfo, (datetime, time)): - dt = dt_or_tzinfo - if dt.tzinfo is not None: - tzinfo = dt.tzinfo - else: - tzinfo = UTC - else: - dt = None - tzinfo = dt_or_tzinfo - locale = Locale.parse(locale) - - if hasattr(tzinfo, 'zone'): - zone = tzinfo.zone - else: - zone = tzinfo.tzname(dt) - - if zone_variant is None: - if dt is None: - zone_variant = 'generic' - else: - dst = tzinfo.dst(dt) - if dst: - zone_variant = 'daylight' - else: - zone_variant = 'standard' - else: - if zone_variant not in ('generic', 'standard', 'daylight'): - raise ValueError('Invalid zone variation') - - # Get the canonical time-zone code - zone = get_global('zone_aliases').get(zone, zone) - - info = locale.time_zones.get(zone, {}) - # Try explicitly translated zone names first - if width in info: - if zone_variant in info[width]: - return info[width][zone_variant] - - metazone = get_global('meta_zones').get(zone) - if metazone: - metazone_info = locale.meta_zones.get(metazone, {}) - if width in metazone_info: - if zone_variant in metazone_info[width]: - return metazone_info[width][zone_variant] - - # If we have a concrete datetime, we assume that the result can't be - # independent of daylight savings time, so we return the GMT offset - if dt is not None: - return get_timezone_gmt(dt, width=width, locale=locale) - - return get_timezone_location(dt_or_tzinfo, locale=locale) - - -def format_date(date=None, format='medium', locale=LC_TIME): - """Return a date formatted according to the given pattern. - - >>> d = date(2007, 04, 01) - >>> format_date(d, locale='en_US') - u'Apr 1, 2007' - >>> format_date(d, format='full', locale='de_DE') - u'Sonntag, 1. April 2007' - - If you don't want to use the locale default formats, you can specify a - custom date pattern: - - >>> format_date(d, "EEE, MMM d, ''yy", locale='en') - u"Sun, Apr 1, '07" - - :param date: the ``date`` or ``datetime`` object; if `None`, the current - date is used - :param format: one of "full", "long", "medium", or "short", or a custom - date/time pattern - :param locale: a `Locale` object or a locale identifier - """ - if date is None: - date = date_.today() - elif isinstance(date, datetime): - date = date.date() - - locale = Locale.parse(locale) - if format in ('full', 'long', 'medium', 'short'): - format = get_date_format(format, locale=locale) - pattern = parse_pattern(format) - return pattern.apply(date, locale) - - -def format_datetime(datetime=None, format='medium', tzinfo=None, - locale=LC_TIME): - r"""Return a date formatted according to the given pattern. - - >>> dt = datetime(2007, 04, 01, 15, 30) - >>> format_datetime(dt, locale='en_US') - u'Apr 1, 2007, 3:30:00 PM' - - For any pattern requiring the display of the time-zone, the third-party - ``pytz`` package is needed to explicitly specify the time-zone: - - >>> format_datetime(dt, 'full', tzinfo=get_timezone('Europe/Paris'), - ... locale='fr_FR') - u'dimanche 1 avril 2007 17:30:00 heure avanc\xe9e d\u2019Europe centrale' - >>> format_datetime(dt, "yyyy.MM.dd G 'at' HH:mm:ss zzz", - ... tzinfo=get_timezone('US/Eastern'), locale='en') - u'2007.04.01 AD at 11:30:00 EDT' - - :param datetime: the `datetime` object; if `None`, the current date and - time is used - :param format: one of "full", "long", "medium", or "short", or a custom - date/time pattern - :param tzinfo: the timezone to apply to the time for display - :param locale: a `Locale` object or a locale identifier - """ - if datetime is None: - datetime = datetime_.utcnow() - elif isinstance(datetime, number_types): - datetime = datetime_.utcfromtimestamp(datetime) - elif isinstance(datetime, time): - datetime = datetime_.combine(date.today(), datetime) - if datetime.tzinfo is None: - datetime = datetime.replace(tzinfo=UTC) - if tzinfo is not None: - datetime = datetime.astimezone(get_timezone(tzinfo)) - if hasattr(tzinfo, 'normalize'): # pytz - datetime = tzinfo.normalize(datetime) - - locale = Locale.parse(locale) - if format in ('full', 'long', 'medium', 'short'): - return get_datetime_format(format, locale=locale) \ - .replace("'", "") \ - .replace('{0}', format_time(datetime, format, tzinfo=None, - locale=locale)) \ - .replace('{1}', format_date(datetime, format, locale=locale)) - else: - return parse_pattern(format).apply(datetime, locale) - - -def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME): - r"""Return a time formatted according to the given pattern. - - >>> t = time(15, 30) - >>> format_time(t, locale='en_US') - u'3:30:00 PM' - >>> format_time(t, format='short', locale='de_DE') - u'15:30' - - If you don't want to use the locale default formats, you can specify a - custom time pattern: - - >>> format_time(t, "hh 'o''clock' a", locale='en') - u"03 o'clock PM" - - For any pattern requiring the display of the time-zone a - timezone has to be specified explicitly: - - >>> t = datetime(2007, 4, 1, 15, 30) - >>> tzinfo = get_timezone('Europe/Paris') - >>> t = tzinfo.localize(t) - >>> format_time(t, format='full', tzinfo=tzinfo, locale='fr_FR') - u'15:30:00 heure avanc\xe9e d\u2019Europe centrale' - >>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=get_timezone('US/Eastern'), - ... locale='en') - u"09 o'clock AM, Eastern Daylight Time" - - As that example shows, when this function gets passed a - ``datetime.datetime`` value, the actual time in the formatted string is - adjusted to the timezone specified by the `tzinfo` parameter. If the - ``datetime`` is "naive" (i.e. it has no associated timezone information), - it is assumed to be in UTC. - - These timezone calculations are **not** performed if the value is of type - ``datetime.time``, as without date information there's no way to determine - what a given time would translate to in a different timezone without - information about whether daylight savings time is in effect or not. This - means that time values are left as-is, and the value of the `tzinfo` - parameter is only used to display the timezone name if needed: - - >>> t = time(15, 30) - >>> format_time(t, format='full', tzinfo=get_timezone('Europe/Paris'), - ... locale='fr_FR') - u'15:30:00 heure normale de l\u2019Europe centrale' - >>> format_time(t, format='full', tzinfo=get_timezone('US/Eastern'), - ... locale='en_US') - u'3:30:00 PM Eastern Standard Time' - - :param time: the ``time`` or ``datetime`` object; if `None`, the current - time in UTC is used - :param format: one of "full", "long", "medium", or "short", or a custom - date/time pattern - :param tzinfo: the time-zone to apply to the time for display - :param locale: a `Locale` object or a locale identifier - """ - if time is None: - time = datetime.utcnow() - elif isinstance(time, number_types): - time = datetime.utcfromtimestamp(time) - if time.tzinfo is None: - time = time.replace(tzinfo=UTC) - if isinstance(time, datetime): - if tzinfo is not None: - time = time.astimezone(tzinfo) - if hasattr(tzinfo, 'normalize'): # pytz - time = tzinfo.normalize(time) - time = time.timetz() - elif tzinfo is not None: - time = time.replace(tzinfo=tzinfo) - - locale = Locale.parse(locale) - if format in ('full', 'long', 'medium', 'short'): - format = get_time_format(format, locale=locale) - return parse_pattern(format).apply(time, locale) - - -TIMEDELTA_UNITS = ( - ('year', 3600 * 24 * 365), - ('month', 3600 * 24 * 30), - ('week', 3600 * 24 * 7), - ('day', 3600 * 24), - ('hour', 3600), - ('minute', 60), - ('second', 1) -) - - -def format_timedelta(delta, granularity='second', threshold=.85, - add_direction=False, format='medium', - locale=LC_TIME): - """Return a time delta according to the rules of the given locale. - - >>> format_timedelta(timedelta(weeks=12), locale='en_US') - u'3 months' - >>> format_timedelta(timedelta(seconds=1), locale='es') - u'1 segundo' - - The granularity parameter can be provided to alter the lowest unit - presented, which defaults to a second. - - >>> format_timedelta(timedelta(hours=3), granularity='day', - ... locale='en_US') - u'1 day' - - The threshold parameter can be used to determine at which value the - presentation switches to the next higher unit. A higher threshold factor - means the presentation will switch later. For example: - - >>> format_timedelta(timedelta(hours=23), threshold=0.9, locale='en_US') - u'1 day' - >>> format_timedelta(timedelta(hours=23), threshold=1.1, locale='en_US') - u'23 hours' - - In addition directional information can be provided that informs - the user if the date is in the past or in the future: - - >>> format_timedelta(timedelta(hours=1), add_direction=True) - u'In 1 hour' - >>> format_timedelta(timedelta(hours=-1), add_direction=True) - u'1 hour ago' - - :param delta: a ``timedelta`` object representing the time difference to - format, or the delta in seconds as an `int` value - :param granularity: determines the smallest unit that should be displayed, - the value can be one of "year", "month", "week", "day", - "hour", "minute" or "second" - :param threshold: factor that determines at which point the presentation - switches to the next higher unit - :param add_direction: if this flag is set to `True` the return value will - include directional information. For instance a - positive timedelta will include the information about - it being in the future, a negative will be information - about the value being in the past. - :param format: the format (currently only "medium" and "short" are supported) - :param locale: a `Locale` object or a locale identifier - """ - if format not in ('short', 'medium'): - raise TypeError('Format can only be one of "short" or "medium"') - if isinstance(delta, timedelta): - seconds = int((delta.days * 86400) + delta.seconds) - else: - seconds = delta - locale = Locale.parse(locale) - - def _iter_choices(unit): - if add_direction: - if seconds >= 0: - yield unit + '-future' - else: - yield unit + '-past' - yield unit + ':' + format - yield unit - - for unit, secs_per_unit in TIMEDELTA_UNITS: - value = abs(seconds) / secs_per_unit - if value >= threshold or unit == granularity: - if unit == granularity and value > 0: - value = max(1, value) - value = int(round(value)) - plural_form = locale.plural_form(value) - pattern = None - for choice in _iter_choices(unit): - patterns = locale._data['unit_patterns'].get(choice) - if patterns is not None: - pattern = patterns[plural_form] - break - # This really should not happen - if pattern is None: - return u'' - return pattern.replace('{0}', str(value)) - - return u'' - - -def parse_date(string, locale=LC_TIME): - """Parse a date from a string. - - This function uses the date format for the locale as a hint to determine - the order in which the date fields appear in the string. - - >>> parse_date('4/1/04', locale='en_US') - datetime.date(2004, 4, 1) - >>> parse_date('01.04.2004', locale='de_DE') - datetime.date(2004, 4, 1) - - :param string: the string containing the date - :param locale: a `Locale` object or a locale identifier - """ - # TODO: try ISO format first? - format = get_date_format(locale=locale).pattern.lower() - year_idx = format.index('y') - month_idx = format.index('m') - if month_idx < 0: - month_idx = format.index('l') - day_idx = format.index('d') - - indexes = [(year_idx, 'Y'), (month_idx, 'M'), (day_idx, 'D')] - indexes.sort() - indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)]) - - # FIXME: this currently only supports numbers, but should also support month - # names, both in the requested locale, and english - - numbers = re.findall('(\d+)', string) - year = numbers[indexes['Y']] - if len(year) == 2: - year = 2000 + int(year) - else: - year = int(year) - month = int(numbers[indexes['M']]) - day = int(numbers[indexes['D']]) - if month > 12: - month, day = day, month - return date(year, month, day) - - -def parse_time(string, locale=LC_TIME): - """Parse a time from a string. - - This function uses the time format for the locale as a hint to determine - the order in which the time fields appear in the string. - - >>> parse_time('15:30:00', locale='en_US') - datetime.time(15, 30) - - :param string: the string containing the time - :param locale: a `Locale` object or a locale identifier - :return: the parsed time - :rtype: `time` - """ - # TODO: try ISO format first? - format = get_time_format(locale=locale).pattern.lower() - hour_idx = format.index('h') - if hour_idx < 0: - hour_idx = format.index('k') - min_idx = format.index('m') - sec_idx = format.index('s') - - indexes = [(hour_idx, 'H'), (min_idx, 'M'), (sec_idx, 'S')] - indexes.sort() - indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)]) - - # FIXME: support 12 hour clock, and 0-based hour specification - # and seconds should be optional, maybe minutes too - # oh, and time-zones, of course - - numbers = re.findall('(\d+)', string) - hour = int(numbers[indexes['H']]) - minute = int(numbers[indexes['M']]) - second = int(numbers[indexes['S']]) - return time(hour, minute, second) - - -class DateTimePattern(object): - - def __init__(self, pattern, format): - self.pattern = pattern - self.format = format - - def __repr__(self): - return '<%s %r>' % (type(self).__name__, self.pattern) - - def __unicode__(self): - return self.pattern - - def __mod__(self, other): - if type(other) is not DateTimeFormat: - return NotImplemented - return self.format % other - - def apply(self, datetime, locale): - return self % DateTimeFormat(datetime, locale) - - -class DateTimeFormat(object): - - def __init__(self, value, locale): - assert isinstance(value, (date, datetime, time)) - if isinstance(value, (datetime, time)) and value.tzinfo is None: - value = value.replace(tzinfo=UTC) - self.value = value - self.locale = Locale.parse(locale) - - def __getitem__(self, name): - char = name[0] - num = len(name) - if char == 'G': - return self.format_era(char, num) - elif char in ('y', 'Y', 'u'): - return self.format_year(char, num) - elif char in ('Q', 'q'): - return self.format_quarter(char, num) - elif char in ('M', 'L'): - return self.format_month(char, num) - elif char in ('w', 'W'): - return self.format_week(char, num) - elif char == 'd': - return self.format(self.value.day, num) - elif char == 'D': - return self.format_day_of_year(num) - elif char == 'F': - return self.format_day_of_week_in_month() - elif char in ('E', 'e', 'c'): - return self.format_weekday(char, num) - elif char == 'a': - return self.format_period(char) - elif char == 'h': - if self.value.hour % 12 == 0: - return self.format(12, num) - else: - return self.format(self.value.hour % 12, num) - elif char == 'H': - return self.format(self.value.hour, num) - elif char == 'K': - return self.format(self.value.hour % 12, num) - elif char == 'k': - if self.value.hour == 0: - return self.format(24, num) - else: - return self.format(self.value.hour, num) - elif char == 'm': - return self.format(self.value.minute, num) - elif char == 's': - return self.format(self.value.second, num) - elif char == 'S': - return self.format_frac_seconds(num) - elif char == 'A': - return self.format_milliseconds_in_day(num) - elif char in ('z', 'Z', 'v', 'V'): - return self.format_timezone(char, num) - else: - raise KeyError('Unsupported date/time field %r' % char) - - def format_era(self, char, num): - width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)] - era = int(self.value.year >= 0) - return get_era_names(width, self.locale)[era] - - def format_year(self, char, num): - value = self.value.year - if char.isupper(): - week = self.get_week_number(self.get_day_of_year()) - if week == 0: - value -= 1 - year = self.format(value, num) - if num == 2: - year = year[-2:] - return year - - def format_quarter(self, char, num): - quarter = (self.value.month - 1) // 3 + 1 - if num <= 2: - return ('%%0%dd' % num) % quarter - width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num] - context = {'Q': 'format', 'q': 'stand-alone'}[char] - return get_quarter_names(width, context, self.locale)[quarter] - - def format_month(self, char, num): - if num <= 2: - return ('%%0%dd' % num) % self.value.month - width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num] - context = {'M': 'format', 'L': 'stand-alone'}[char] - return get_month_names(width, context, self.locale)[self.value.month] - - def format_week(self, char, num): - if char.islower(): # week of year - day_of_year = self.get_day_of_year() - week = self.get_week_number(day_of_year) - if week == 0: - date = self.value - timedelta(days=day_of_year) - week = self.get_week_number(self.get_day_of_year(date), - date.weekday()) - return self.format(week, num) - else: # week of month - week = self.get_week_number(self.value.day) - if week == 0: - date = self.value - timedelta(days=self.value.day) - week = self.get_week_number(date.day, date.weekday()) - pass - return '%d' % week - - def format_weekday(self, char, num): - if num < 3: - if char.islower(): - value = 7 - self.locale.first_week_day + self.value.weekday() - return self.format(value % 7 + 1, num) - num = 3 - weekday = self.value.weekday() - width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num] - context = {3: 'format', 4: 'format', 5: 'stand-alone'}[num] - return get_day_names(width, context, self.locale)[weekday] - - def format_day_of_year(self, num): - return self.format(self.get_day_of_year(), num) - - def format_day_of_week_in_month(self): - return '%d' % ((self.value.day - 1) // 7 + 1) - - def format_period(self, char): - period = {0: 'am', 1: 'pm'}[int(self.value.hour >= 12)] - return get_period_names(locale=self.locale)[period] - - def format_frac_seconds(self, num): - value = str(self.value.microsecond) - return self.format(round(float('.%s' % value), num) * 10**num, num) - - def format_milliseconds_in_day(self, num): - msecs = self.value.microsecond // 1000 + self.value.second * 1000 + \ - self.value.minute * 60000 + self.value.hour * 3600000 - return self.format(msecs, num) - - def format_timezone(self, char, num): - width = {3: 'short', 4: 'long'}[max(3, num)] - if char == 'z': - return get_timezone_name(self.value, width, locale=self.locale) - elif char == 'Z': - return get_timezone_gmt(self.value, width, locale=self.locale) - elif char == 'v': - return get_timezone_name(self.value.tzinfo, width, - locale=self.locale) - elif char == 'V': - if num == 1: - return get_timezone_name(self.value.tzinfo, width, - uncommon=True, locale=self.locale) - return get_timezone_location(self.value.tzinfo, locale=self.locale) - - def format(self, value, length): - return ('%%0%dd' % length) % value - - def get_day_of_year(self, date=None): - if date is None: - date = self.value - return (date - date.replace(month=1, day=1)).days + 1 - - def get_week_number(self, day_of_period, day_of_week=None): - """Return the number of the week of a day within a period. This may be - the week number in a year or the week number in a month. - - Usually this will return a value equal to or greater than 1, but if the - first week of the period is so short that it actually counts as the last - week of the previous period, this function will return 0. - - >>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('de_DE')) - >>> format.get_week_number(6) - 1 - - >>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('en_US')) - >>> format.get_week_number(6) - 2 - - :param day_of_period: the number of the day in the period (usually - either the day of month or the day of year) - :param day_of_week: the week day; if ommitted, the week day of the - current date is assumed - """ - if day_of_week is None: - day_of_week = self.value.weekday() - first_day = (day_of_week - self.locale.first_week_day - - day_of_period + 1) % 7 - if first_day < 0: - first_day += 7 - week_number = (day_of_period + first_day - 1) // 7 - if 7 - first_day >= self.locale.min_week_days: - week_number += 1 - return week_number - - -PATTERN_CHARS = { - 'G': [1, 2, 3, 4, 5], # era - 'y': None, 'Y': None, 'u': None, # year - 'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter - 'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month - 'w': [1, 2], 'W': [1], # week - 'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day - 'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day - 'a': [1], # period - 'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour - 'm': [1, 2], # minute - 's': [1, 2], 'S': None, 'A': None, # second - 'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4], 'v': [1, 4], 'V': [1, 4] # zone -} - - -def parse_pattern(pattern): - """Parse date, time, and datetime format patterns. - - >>> parse_pattern("MMMMd").format - u'%(MMMM)s%(d)s' - >>> parse_pattern("MMM d, yyyy").format - u'%(MMM)s %(d)s, %(yyyy)s' - - Pattern can contain literal strings in single quotes: - - >>> parse_pattern("H:mm' Uhr 'z").format - u'%(H)s:%(mm)s Uhr %(z)s' - - An actual single quote can be used by using two adjacent single quote - characters: - - >>> parse_pattern("hh' o''clock'").format - u"%(hh)s o'clock" - - :param pattern: the formatting pattern to parse - """ - if type(pattern) is DateTimePattern: - return pattern - - result = [] - quotebuf = None - charbuf = [] - fieldchar = [''] - fieldnum = [0] - - def append_chars(): - result.append(''.join(charbuf).replace('%', '%%')) - del charbuf[:] - - def append_field(): - limit = PATTERN_CHARS[fieldchar[0]] - if limit and fieldnum[0] not in limit: - raise ValueError('Invalid length for field: %r' - % (fieldchar[0] * fieldnum[0])) - result.append('%%(%s)s' % (fieldchar[0] * fieldnum[0])) - fieldchar[0] = '' - fieldnum[0] = 0 - - for idx, char in enumerate(pattern.replace("''", '\0')): - if quotebuf is None: - if char == "'": # quote started - if fieldchar[0]: - append_field() - elif charbuf: - append_chars() - quotebuf = [] - elif char in PATTERN_CHARS: - if charbuf: - append_chars() - if char == fieldchar[0]: - fieldnum[0] += 1 - else: - if fieldchar[0]: - append_field() - fieldchar[0] = char - fieldnum[0] = 1 - else: - if fieldchar[0]: - append_field() - charbuf.append(char) - - elif quotebuf is not None: - if char == "'": # end of quote - charbuf.extend(quotebuf) - quotebuf = None - else: # inside quote - quotebuf.append(char) - - if fieldchar[0]: - append_field() - elif charbuf: - append_chars() - - return DateTimePattern(pattern, u''.join(result).replace('\0', "'")) diff --git a/awx/lib/site-packages/babel/global.dat b/awx/lib/site-packages/babel/global.dat deleted file mode 100644 index 82cbbae121..0000000000 Binary files a/awx/lib/site-packages/babel/global.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata.py b/awx/lib/site-packages/babel/localedata.py deleted file mode 100644 index 88883ac80e..0000000000 --- a/awx/lib/site-packages/babel/localedata.py +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.localedata - ~~~~~~~~~~~~~~~~ - - Low-level locale data access. - - :note: The `Locale` class, which uses this module under the hood, provides a - more convenient interface for accessing the locale data. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import os -import threading -from collections import MutableMapping - -from babel._compat import pickle - - -_cache = {} -_cache_lock = threading.RLock() -_dirname = os.path.join(os.path.dirname(__file__), 'localedata') - - -def exists(name): - """Check whether locale data is available for the given locale. Ther - return value is `True` if it exists, `False` otherwise. - - :param name: the locale identifier string - """ - if name in _cache: - return True - return os.path.exists(os.path.join(_dirname, '%s.dat' % name)) - - -def locale_identifiers(): - """Return a list of all locale identifiers for which locale data is - available. - - .. versionadded:: 0.8.1 - - :return: a list of locale identifiers (strings) - """ - return [stem for stem, extension in [ - os.path.splitext(filename) for filename in os.listdir(_dirname) - ] if extension == '.dat' and stem != 'root'] - - -def load(name, merge_inherited=True): - """Load the locale data for the given locale. - - The locale data is a dictionary that contains much of the data defined by - the Common Locale Data Repository (CLDR). This data is stored as a - collection of pickle files inside the ``babel`` package. - - >>> d = load('en_US') - >>> d['languages']['sv'] - u'Swedish' - - Note that the results are cached, and subsequent requests for the same - locale return the same dictionary: - - >>> d1 = load('en_US') - >>> d2 = load('en_US') - >>> d1 is d2 - True - - :param name: the locale identifier string (or "root") - :param merge_inherited: whether the inherited data should be merged into - the data of the requested locale - :raise `IOError`: if no locale data file is found for the given locale - identifer, or one of the locales it inherits from - """ - _cache_lock.acquire() - try: - data = _cache.get(name) - if not data: - # Load inherited data - if name == 'root' or not merge_inherited: - data = {} - else: - parts = name.split('_') - if len(parts) == 1: - parent = 'root' - else: - parent = '_'.join(parts[:-1]) - data = load(parent).copy() - filename = os.path.join(_dirname, '%s.dat' % name) - fileobj = open(filename, 'rb') - try: - if name != 'root' and merge_inherited: - merge(data, pickle.load(fileobj)) - else: - data = pickle.load(fileobj) - _cache[name] = data - finally: - fileobj.close() - return data - finally: - _cache_lock.release() - - -def merge(dict1, dict2): - """Merge the data from `dict2` into the `dict1` dictionary, making copies - of nested dictionaries. - - >>> d = {1: 'foo', 3: 'baz'} - >>> merge(d, {1: 'Foo', 2: 'Bar'}) - >>> items = d.items(); items.sort(); items - [(1, 'Foo'), (2, 'Bar'), (3, 'baz')] - - :param dict1: the dictionary to merge into - :param dict2: the dictionary containing the data that should be merged - """ - for key, val2 in dict2.items(): - if val2 is not None: - val1 = dict1.get(key) - if isinstance(val2, dict): - if val1 is None: - val1 = {} - if isinstance(val1, Alias): - val1 = (val1, val2) - elif isinstance(val1, tuple): - alias, others = val1 - others = others.copy() - merge(others, val2) - val1 = (alias, others) - else: - val1 = val1.copy() - merge(val1, val2) - else: - val1 = val2 - dict1[key] = val1 - - -class Alias(object): - """Representation of an alias in the locale data. - - An alias is a value that refers to some other part of the locale data, - as specified by the `keys`. - """ - - def __init__(self, keys): - self.keys = tuple(keys) - - def __repr__(self): - return '<%s %r>' % (type(self).__name__, self.keys) - - def resolve(self, data): - """Resolve the alias based on the given data. - - This is done recursively, so if one alias resolves to a second alias, - that second alias will also be resolved. - - :param data: the locale data - :type data: `dict` - """ - base = data - for key in self.keys: - data = data[key] - if isinstance(data, Alias): - data = data.resolve(base) - elif isinstance(data, tuple): - alias, others = data - data = alias.resolve(base) - return data - - -class LocaleDataDict(MutableMapping): - """Dictionary wrapper that automatically resolves aliases to the actual - values. - """ - - def __init__(self, data, base=None): - self._data = data - if base is None: - base = data - self.base = base - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, key): - orig = val = self._data[key] - if isinstance(val, Alias): # resolve an alias - val = val.resolve(self.base) - if isinstance(val, tuple): # Merge a partial dict with an alias - alias, others = val - val = alias.resolve(self.base).copy() - merge(val, others) - if type(val) is dict: # Return a nested alias-resolving dict - val = LocaleDataDict(val, base=self.base) - if val is not orig: - self._data[key] = val - return val - - def __setitem__(self, key, value): - self._data[key] = value - - def __delitem__(self, key): - del self._data[key] - - def copy(self): - return LocaleDataDict(self._data.copy(), base=self.base) diff --git a/awx/lib/site-packages/babel/localedata/aa.dat b/awx/lib/site-packages/babel/localedata/aa.dat deleted file mode 100644 index 7a5e498755..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/aa.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/aa_DJ.dat b/awx/lib/site-packages/babel/localedata/aa_DJ.dat deleted file mode 100644 index ceafe15576..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/aa_DJ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/aa_ER.dat b/awx/lib/site-packages/babel/localedata/aa_ER.dat deleted file mode 100644 index 61ff1648da..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/aa_ER.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/aa_ET.dat b/awx/lib/site-packages/babel/localedata/aa_ET.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/aa_ET.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/af.dat b/awx/lib/site-packages/babel/localedata/af.dat deleted file mode 100644 index b17f184ab8..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/af.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/af_NA.dat b/awx/lib/site-packages/babel/localedata/af_NA.dat deleted file mode 100644 index c915eedcd9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/af_NA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/af_ZA.dat b/awx/lib/site-packages/babel/localedata/af_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/af_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/agq.dat b/awx/lib/site-packages/babel/localedata/agq.dat deleted file mode 100644 index 0c57e93bef..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/agq.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/agq_CM.dat b/awx/lib/site-packages/babel/localedata/agq_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/agq_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ak.dat b/awx/lib/site-packages/babel/localedata/ak.dat deleted file mode 100644 index fa10f57beb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ak.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ak_GH.dat b/awx/lib/site-packages/babel/localedata/ak_GH.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ak_GH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/am.dat b/awx/lib/site-packages/babel/localedata/am.dat deleted file mode 100644 index 4bb060eb88..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/am.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/am_ET.dat b/awx/lib/site-packages/babel/localedata/am_ET.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/am_ET.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar.dat b/awx/lib/site-packages/babel/localedata/ar.dat deleted file mode 100644 index 79d92cc7bf..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_001.dat b/awx/lib/site-packages/babel/localedata/ar_001.dat deleted file mode 100644 index 5b852b0bba..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_001.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_AE.dat b/awx/lib/site-packages/babel/localedata/ar_AE.dat deleted file mode 100644 index 72b454249a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_AE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_BH.dat b/awx/lib/site-packages/babel/localedata/ar_BH.dat deleted file mode 100644 index 72b454249a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_BH.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_DJ.dat b/awx/lib/site-packages/babel/localedata/ar_DJ.dat deleted file mode 100644 index b0ee442122..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_DJ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_DZ.dat b/awx/lib/site-packages/babel/localedata/ar_DZ.dat deleted file mode 100644 index bf61a6fb7f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_DZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_EG.dat b/awx/lib/site-packages/babel/localedata/ar_EG.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_EG.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_EH.dat b/awx/lib/site-packages/babel/localedata/ar_EH.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_EH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_ER.dat b/awx/lib/site-packages/babel/localedata/ar_ER.dat deleted file mode 100644 index 61ff1648da..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_ER.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_IL.dat b/awx/lib/site-packages/babel/localedata/ar_IL.dat deleted file mode 100644 index 36bd112d1a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_IL.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_IQ.dat b/awx/lib/site-packages/babel/localedata/ar_IQ.dat deleted file mode 100644 index 882435e4e2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_IQ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_JO.dat b/awx/lib/site-packages/babel/localedata/ar_JO.dat deleted file mode 100644 index 563ecb417d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_JO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_KM.dat b/awx/lib/site-packages/babel/localedata/ar_KM.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_KM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_KW.dat b/awx/lib/site-packages/babel/localedata/ar_KW.dat deleted file mode 100644 index 72b454249a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_KW.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_LB.dat b/awx/lib/site-packages/babel/localedata/ar_LB.dat deleted file mode 100644 index 369f5368dd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_LB.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_LY.dat b/awx/lib/site-packages/babel/localedata/ar_LY.dat deleted file mode 100644 index dc63b518c8..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_LY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_MA.dat b/awx/lib/site-packages/babel/localedata/ar_MA.dat deleted file mode 100644 index 741e7913b5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_MA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_MR.dat b/awx/lib/site-packages/babel/localedata/ar_MR.dat deleted file mode 100644 index 6ea05710e0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_MR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_OM.dat b/awx/lib/site-packages/babel/localedata/ar_OM.dat deleted file mode 100644 index 150c7e3b45..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_OM.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_PS.dat b/awx/lib/site-packages/babel/localedata/ar_PS.dat deleted file mode 100644 index 889cfe8c9e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_PS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_QA.dat b/awx/lib/site-packages/babel/localedata/ar_QA.dat deleted file mode 100644 index c63c35df6b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_QA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_SA.dat b/awx/lib/site-packages/babel/localedata/ar_SA.dat deleted file mode 100644 index 052e74564a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_SA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_SD.dat b/awx/lib/site-packages/babel/localedata/ar_SD.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_SD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_SO.dat b/awx/lib/site-packages/babel/localedata/ar_SO.dat deleted file mode 100644 index 39a665033f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_SO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_SY.dat b/awx/lib/site-packages/babel/localedata/ar_SY.dat deleted file mode 100644 index 96f96b03be..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_SY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_TD.dat b/awx/lib/site-packages/babel/localedata/ar_TD.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/ar_TD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ar_TN.dat b/awx/lib/site-packages/babel/localedata/ar_TN.dat deleted file mode 100644 index 5144a9c7af..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_TN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ar_YE.dat b/awx/lib/site-packages/babel/localedata/ar_YE.dat deleted file mode 100644 index 052e74564a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ar_YE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/as.dat b/awx/lib/site-packages/babel/localedata/as.dat deleted file mode 100644 index ecf4a3fb33..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/as.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/as_IN.dat b/awx/lib/site-packages/babel/localedata/as_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/as_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/asa.dat b/awx/lib/site-packages/babel/localedata/asa.dat deleted file mode 100644 index 599f61930c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/asa.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/asa_TZ.dat b/awx/lib/site-packages/babel/localedata/asa_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/asa_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ast.dat b/awx/lib/site-packages/babel/localedata/ast.dat deleted file mode 100644 index b3544d0eb5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ast.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ast_ES.dat b/awx/lib/site-packages/babel/localedata/ast_ES.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ast_ES.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/az.dat b/awx/lib/site-packages/babel/localedata/az.dat deleted file mode 100644 index c31ec5935a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/az.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/az_Cyrl.dat b/awx/lib/site-packages/babel/localedata/az_Cyrl.dat deleted file mode 100644 index 1d74d11bb2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/az_Cyrl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/az_Cyrl_AZ.dat b/awx/lib/site-packages/babel/localedata/az_Cyrl_AZ.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/az_Cyrl_AZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/az_Latn.dat b/awx/lib/site-packages/babel/localedata/az_Latn.dat deleted file mode 100644 index 980ab6b6fc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/az_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/az_Latn_AZ.dat b/awx/lib/site-packages/babel/localedata/az_Latn_AZ.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/az_Latn_AZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bas.dat b/awx/lib/site-packages/babel/localedata/bas.dat deleted file mode 100644 index fe53dafc14..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bas.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bas_CM.dat b/awx/lib/site-packages/babel/localedata/bas_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bas_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/be.dat b/awx/lib/site-packages/babel/localedata/be.dat deleted file mode 100644 index 00270ce944..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/be.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/be_BY.dat b/awx/lib/site-packages/babel/localedata/be_BY.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/be_BY.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/bem.dat b/awx/lib/site-packages/babel/localedata/bem.dat deleted file mode 100644 index 65713a7cac..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bem.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bem_ZM.dat b/awx/lib/site-packages/babel/localedata/bem_ZM.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bem_ZM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bez.dat b/awx/lib/site-packages/babel/localedata/bez.dat deleted file mode 100644 index aa7bfc25b9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bez.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bez_TZ.dat b/awx/lib/site-packages/babel/localedata/bez_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bez_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bg.dat b/awx/lib/site-packages/babel/localedata/bg.dat deleted file mode 100644 index 35d4342907..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bg.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bg_BG.dat b/awx/lib/site-packages/babel/localedata/bg_BG.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bg_BG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bm.dat b/awx/lib/site-packages/babel/localedata/bm.dat deleted file mode 100644 index 9f5202cda9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bm.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bm_ML.dat b/awx/lib/site-packages/babel/localedata/bm_ML.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bm_ML.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bn.dat b/awx/lib/site-packages/babel/localedata/bn.dat deleted file mode 100644 index c5be3e5671..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bn_BD.dat b/awx/lib/site-packages/babel/localedata/bn_BD.dat deleted file mode 100644 index 281a7813c8..0000000000 --- a/awx/lib/site-packages/babel/localedata/bn_BD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/bn_IN.dat b/awx/lib/site-packages/babel/localedata/bn_IN.dat deleted file mode 100644 index 07613a585a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bn_IN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bo.dat b/awx/lib/site-packages/babel/localedata/bo.dat deleted file mode 100644 index bcfa2184a6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bo_CN.dat b/awx/lib/site-packages/babel/localedata/bo_CN.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/bo_CN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/bo_IN.dat b/awx/lib/site-packages/babel/localedata/bo_IN.dat deleted file mode 100644 index fbda3e34fc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bo_IN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/br.dat b/awx/lib/site-packages/babel/localedata/br.dat deleted file mode 100644 index 2c2bc2ccac..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/br.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/br_FR.dat b/awx/lib/site-packages/babel/localedata/br_FR.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/br_FR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/brx.dat b/awx/lib/site-packages/babel/localedata/brx.dat deleted file mode 100644 index aaa57e92df..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/brx.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/brx_IN.dat b/awx/lib/site-packages/babel/localedata/brx_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/brx_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/bs.dat b/awx/lib/site-packages/babel/localedata/bs.dat deleted file mode 100644 index 82abeed2a0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bs.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bs_Cyrl.dat b/awx/lib/site-packages/babel/localedata/bs_Cyrl.dat deleted file mode 100644 index f152d9de89..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bs_Cyrl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bs_Cyrl_BA.dat b/awx/lib/site-packages/babel/localedata/bs_Cyrl_BA.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bs_Cyrl_BA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bs_Latn.dat b/awx/lib/site-packages/babel/localedata/bs_Latn.dat deleted file mode 100644 index a882c5bcaf..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bs_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/bs_Latn_BA.dat b/awx/lib/site-packages/babel/localedata/bs_Latn_BA.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/bs_Latn_BA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/byn.dat b/awx/lib/site-packages/babel/localedata/byn.dat deleted file mode 100644 index 6cbcf5a446..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/byn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/byn_ER.dat b/awx/lib/site-packages/babel/localedata/byn_ER.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/byn_ER.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ca.dat b/awx/lib/site-packages/babel/localedata/ca.dat deleted file mode 100644 index 82aa8738ea..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ca.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ca_AD.dat b/awx/lib/site-packages/babel/localedata/ca_AD.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ca_AD.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ca_ES.dat b/awx/lib/site-packages/babel/localedata/ca_ES.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ca_ES.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/cgg.dat b/awx/lib/site-packages/babel/localedata/cgg.dat deleted file mode 100644 index 7550fa7592..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/cgg.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/cgg_UG.dat b/awx/lib/site-packages/babel/localedata/cgg_UG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/cgg_UG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/chr.dat b/awx/lib/site-packages/babel/localedata/chr.dat deleted file mode 100644 index 65dee5bbde..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/chr.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/chr_US.dat b/awx/lib/site-packages/babel/localedata/chr_US.dat deleted file mode 100644 index e1639abe76..0000000000 --- a/awx/lib/site-packages/babel/localedata/chr_US.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/cs.dat b/awx/lib/site-packages/babel/localedata/cs.dat deleted file mode 100644 index f85d6ade6b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/cs.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/cs_CZ.dat b/awx/lib/site-packages/babel/localedata/cs_CZ.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/cs_CZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/cy.dat b/awx/lib/site-packages/babel/localedata/cy.dat deleted file mode 100644 index c6ec58fe20..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/cy.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/cy_GB.dat b/awx/lib/site-packages/babel/localedata/cy_GB.dat deleted file mode 100644 index 401708ffe0..0000000000 --- a/awx/lib/site-packages/babel/localedata/cy_GB.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/da.dat b/awx/lib/site-packages/babel/localedata/da.dat deleted file mode 100644 index 47548dd0cc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/da.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/da_DK.dat b/awx/lib/site-packages/babel/localedata/da_DK.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/da_DK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dav.dat b/awx/lib/site-packages/babel/localedata/dav.dat deleted file mode 100644 index cc17bc0b8e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dav.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dav_KE.dat b/awx/lib/site-packages/babel/localedata/dav_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/dav_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/de.dat b/awx/lib/site-packages/babel/localedata/de.dat deleted file mode 100644 index ba55b5074d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/de.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/de_AT.dat b/awx/lib/site-packages/babel/localedata/de_AT.dat deleted file mode 100644 index bee43e3159..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/de_AT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/de_BE.dat b/awx/lib/site-packages/babel/localedata/de_BE.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/de_BE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/de_CH.dat b/awx/lib/site-packages/babel/localedata/de_CH.dat deleted file mode 100644 index a4d26be1dd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/de_CH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/de_DE.dat b/awx/lib/site-packages/babel/localedata/de_DE.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/de_DE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/de_LI.dat b/awx/lib/site-packages/babel/localedata/de_LI.dat deleted file mode 100644 index 2b92c9b00a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/de_LI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/de_LU.dat b/awx/lib/site-packages/babel/localedata/de_LU.dat deleted file mode 100644 index 8d080e12b2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/de_LU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dje.dat b/awx/lib/site-packages/babel/localedata/dje.dat deleted file mode 100644 index b3997c7552..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dje.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dje_NE.dat b/awx/lib/site-packages/babel/localedata/dje_NE.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dje_NE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dua.dat b/awx/lib/site-packages/babel/localedata/dua.dat deleted file mode 100644 index 2693dc173c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dua.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dua_CM.dat b/awx/lib/site-packages/babel/localedata/dua_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dua_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dyo.dat b/awx/lib/site-packages/babel/localedata/dyo.dat deleted file mode 100644 index 9bd62330c0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dyo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dyo_SN.dat b/awx/lib/site-packages/babel/localedata/dyo_SN.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dyo_SN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dz.dat b/awx/lib/site-packages/babel/localedata/dz.dat deleted file mode 100644 index 0ba26a88c5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/dz.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/dz_BT.dat b/awx/lib/site-packages/babel/localedata/dz_BT.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/dz_BT.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ebu.dat b/awx/lib/site-packages/babel/localedata/ebu.dat deleted file mode 100644 index 2ce0ac43ff..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ebu.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ebu_KE.dat b/awx/lib/site-packages/babel/localedata/ebu_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ebu_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ee.dat b/awx/lib/site-packages/babel/localedata/ee.dat deleted file mode 100644 index 28c274332f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ee.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ee_GH.dat b/awx/lib/site-packages/babel/localedata/ee_GH.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ee_GH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ee_TG.dat b/awx/lib/site-packages/babel/localedata/ee_TG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ee_TG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/el.dat b/awx/lib/site-packages/babel/localedata/el.dat deleted file mode 100644 index 9c10ce51b4..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/el.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/el_CY.dat b/awx/lib/site-packages/babel/localedata/el_CY.dat deleted file mode 100644 index 83f7d85433..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/el_CY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/el_GR.dat b/awx/lib/site-packages/babel/localedata/el_GR.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/el_GR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en.dat b/awx/lib/site-packages/babel/localedata/en.dat deleted file mode 100644 index cbe140ca9d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_150.dat b/awx/lib/site-packages/babel/localedata/en_150.dat deleted file mode 100644 index 23a79939be..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_150.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_AG.dat b/awx/lib/site-packages/babel/localedata/en_AG.dat deleted file mode 100644 index c6f15402ff..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_AG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_AS.dat b/awx/lib/site-packages/babel/localedata/en_AS.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_AS.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_AU.dat b/awx/lib/site-packages/babel/localedata/en_AU.dat deleted file mode 100644 index 14472b3627..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_AU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_BB.dat b/awx/lib/site-packages/babel/localedata/en_BB.dat deleted file mode 100644 index 40f7b9702e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_BB.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_BE.dat b/awx/lib/site-packages/babel/localedata/en_BE.dat deleted file mode 100644 index 89586c286e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_BE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_BM.dat b/awx/lib/site-packages/babel/localedata/en_BM.dat deleted file mode 100644 index cf27a79bb5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_BM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_BS.dat b/awx/lib/site-packages/babel/localedata/en_BS.dat deleted file mode 100644 index 9f24a114ec..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_BS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_BW.dat b/awx/lib/site-packages/babel/localedata/en_BW.dat deleted file mode 100644 index a27e49f681..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_BW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_BZ.dat b/awx/lib/site-packages/babel/localedata/en_BZ.dat deleted file mode 100644 index de2936c152..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_BZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_CA.dat b/awx/lib/site-packages/babel/localedata/en_CA.dat deleted file mode 100644 index f46ef18861..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_CA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_CM.dat b/awx/lib/site-packages/babel/localedata/en_CM.dat deleted file mode 100644 index ec06b5e903..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_DM.dat b/awx/lib/site-packages/babel/localedata/en_DM.dat deleted file mode 100644 index c6f15402ff..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_DM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_Dsrt.dat b/awx/lib/site-packages/babel/localedata/en_Dsrt.dat deleted file mode 100644 index c9b5e98def..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_Dsrt.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_Dsrt_US.dat b/awx/lib/site-packages/babel/localedata/en_Dsrt_US.dat deleted file mode 100644 index e1639abe76..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_Dsrt_US.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_FJ.dat b/awx/lib/site-packages/babel/localedata/en_FJ.dat deleted file mode 100644 index 33e22056a2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_FJ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_FM.dat b/awx/lib/site-packages/babel/localedata/en_FM.dat deleted file mode 100644 index b2c2947d53..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_FM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_GB.dat b/awx/lib/site-packages/babel/localedata/en_GB.dat deleted file mode 100644 index 2baebd09a9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_GB.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_GD.dat b/awx/lib/site-packages/babel/localedata/en_GD.dat deleted file mode 100644 index 049f10a163..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_GD.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_GG.dat b/awx/lib/site-packages/babel/localedata/en_GG.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_GG.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_GH.dat b/awx/lib/site-packages/babel/localedata/en_GH.dat deleted file mode 100644 index dceb36d48b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_GH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_GI.dat b/awx/lib/site-packages/babel/localedata/en_GI.dat deleted file mode 100644 index 33a2e60a00..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_GI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_GM.dat b/awx/lib/site-packages/babel/localedata/en_GM.dat deleted file mode 100644 index a7c4e45565..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_GM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_GU.dat b/awx/lib/site-packages/babel/localedata/en_GU.dat deleted file mode 100644 index b022c61444..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_GU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_GY.dat b/awx/lib/site-packages/babel/localedata/en_GY.dat deleted file mode 100644 index 19a886ca98..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_GY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_HK.dat b/awx/lib/site-packages/babel/localedata/en_HK.dat deleted file mode 100644 index a62e01372b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_HK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_IE.dat b/awx/lib/site-packages/babel/localedata/en_IE.dat deleted file mode 100644 index e4bd14ef84..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_IE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_IM.dat b/awx/lib/site-packages/babel/localedata/en_IM.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_IM.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_IN.dat b/awx/lib/site-packages/babel/localedata/en_IN.dat deleted file mode 100644 index cea4cae933..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_IN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_JE.dat b/awx/lib/site-packages/babel/localedata/en_JE.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_JE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_JM.dat b/awx/lib/site-packages/babel/localedata/en_JM.dat deleted file mode 100644 index e792cb936a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_JM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_KE.dat b/awx/lib/site-packages/babel/localedata/en_KE.dat deleted file mode 100644 index f1dc0e5d37..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_KE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_KI.dat b/awx/lib/site-packages/babel/localedata/en_KI.dat deleted file mode 100644 index b87da16d16..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_KI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_KN.dat b/awx/lib/site-packages/babel/localedata/en_KN.dat deleted file mode 100644 index 049f10a163..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_KN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_KY.dat b/awx/lib/site-packages/babel/localedata/en_KY.dat deleted file mode 100644 index a6415f498d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_KY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_LC.dat b/awx/lib/site-packages/babel/localedata/en_LC.dat deleted file mode 100644 index 049f10a163..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_LC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_LR.dat b/awx/lib/site-packages/babel/localedata/en_LR.dat deleted file mode 100644 index e92eac71bd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_LR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_LS.dat b/awx/lib/site-packages/babel/localedata/en_LS.dat deleted file mode 100644 index 76aab995ba..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_LS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_MG.dat b/awx/lib/site-packages/babel/localedata/en_MG.dat deleted file mode 100644 index 25efe8a01d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_MG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_MH.dat b/awx/lib/site-packages/babel/localedata/en_MH.dat deleted file mode 100644 index 2a51e5ab8d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_MH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_MP.dat b/awx/lib/site-packages/babel/localedata/en_MP.dat deleted file mode 100644 index b2c2947d53..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_MP.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_MT.dat b/awx/lib/site-packages/babel/localedata/en_MT.dat deleted file mode 100644 index d68588a1c7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_MT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_MU.dat b/awx/lib/site-packages/babel/localedata/en_MU.dat deleted file mode 100644 index 6434affc27..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_MU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_MW.dat b/awx/lib/site-packages/babel/localedata/en_MW.dat deleted file mode 100644 index 2b728133de..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_MW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_NA.dat b/awx/lib/site-packages/babel/localedata/en_NA.dat deleted file mode 100644 index ab7159fbac..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_NA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_NG.dat b/awx/lib/site-packages/babel/localedata/en_NG.dat deleted file mode 100644 index ca4464e6c1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_NG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_NZ.dat b/awx/lib/site-packages/babel/localedata/en_NZ.dat deleted file mode 100644 index 1e8d8df3d4..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_NZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_PG.dat b/awx/lib/site-packages/babel/localedata/en_PG.dat deleted file mode 100644 index 57dc8c5588..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_PG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_PH.dat b/awx/lib/site-packages/babel/localedata/en_PH.dat deleted file mode 100644 index edf7178fdb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_PH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_PK.dat b/awx/lib/site-packages/babel/localedata/en_PK.dat deleted file mode 100644 index 40744ea85f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_PK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_PR.dat b/awx/lib/site-packages/babel/localedata/en_PR.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_PR.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_PW.dat b/awx/lib/site-packages/babel/localedata/en_PW.dat deleted file mode 100644 index b2c2947d53..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_PW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_SB.dat b/awx/lib/site-packages/babel/localedata/en_SB.dat deleted file mode 100644 index eaab8887d3..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_SB.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_SC.dat b/awx/lib/site-packages/babel/localedata/en_SC.dat deleted file mode 100644 index 355ec817e0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_SC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_SG.dat b/awx/lib/site-packages/babel/localedata/en_SG.dat deleted file mode 100644 index d12d553c42..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_SG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_SL.dat b/awx/lib/site-packages/babel/localedata/en_SL.dat deleted file mode 100644 index a9b33f38f1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_SL.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_SS.dat b/awx/lib/site-packages/babel/localedata/en_SS.dat deleted file mode 100644 index 98b33925d6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_SS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_SZ.dat b/awx/lib/site-packages/babel/localedata/en_SZ.dat deleted file mode 100644 index 2bd0229dc5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_SZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_TC.dat b/awx/lib/site-packages/babel/localedata/en_TC.dat deleted file mode 100644 index 59cbead6d3..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_TC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_TO.dat b/awx/lib/site-packages/babel/localedata/en_TO.dat deleted file mode 100644 index 5f95a001b6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_TO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_TT.dat b/awx/lib/site-packages/babel/localedata/en_TT.dat deleted file mode 100644 index fa9a6ce137..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_TT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_TZ.dat b/awx/lib/site-packages/babel/localedata/en_TZ.dat deleted file mode 100644 index 26922be123..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_UG.dat b/awx/lib/site-packages/babel/localedata/en_UG.dat deleted file mode 100644 index c41cbbf007..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_UG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_UM.dat b/awx/lib/site-packages/babel/localedata/en_UM.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_UM.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_US.dat b/awx/lib/site-packages/babel/localedata/en_US.dat deleted file mode 100644 index e1639abe76..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_US.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_US_POSIX.dat b/awx/lib/site-packages/babel/localedata/en_US_POSIX.dat deleted file mode 100644 index 09cbe7ecb7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_US_POSIX.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_VC.dat b/awx/lib/site-packages/babel/localedata/en_VC.dat deleted file mode 100644 index 049f10a163..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_VC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_VG.dat b/awx/lib/site-packages/babel/localedata/en_VG.dat deleted file mode 100644 index 59cbead6d3..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_VG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_VI.dat b/awx/lib/site-packages/babel/localedata/en_VI.dat deleted file mode 100644 index e1639abe76..0000000000 --- a/awx/lib/site-packages/babel/localedata/en_VI.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/en_VU.dat b/awx/lib/site-packages/babel/localedata/en_VU.dat deleted file mode 100644 index bf18911127..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_VU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_WS.dat b/awx/lib/site-packages/babel/localedata/en_WS.dat deleted file mode 100644 index d9693cc4f3..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_WS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_ZA.dat b/awx/lib/site-packages/babel/localedata/en_ZA.dat deleted file mode 100644 index c66ff2ba78..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_ZA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_ZM.dat b/awx/lib/site-packages/babel/localedata/en_ZM.dat deleted file mode 100644 index 6faaea8510..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_ZM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/en_ZW.dat b/awx/lib/site-packages/babel/localedata/en_ZW.dat deleted file mode 100644 index 97fee5615f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/en_ZW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/eo.dat b/awx/lib/site-packages/babel/localedata/eo.dat deleted file mode 100644 index 452c849188..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/eo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es.dat b/awx/lib/site-packages/babel/localedata/es.dat deleted file mode 100644 index a48af1bc21..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_419.dat b/awx/lib/site-packages/babel/localedata/es_419.dat deleted file mode 100644 index b3a15f1bde..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_419.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_AR.dat b/awx/lib/site-packages/babel/localedata/es_AR.dat deleted file mode 100644 index 7b21f4fce5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_AR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_BO.dat b/awx/lib/site-packages/babel/localedata/es_BO.dat deleted file mode 100644 index 438c36005f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_BO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_CL.dat b/awx/lib/site-packages/babel/localedata/es_CL.dat deleted file mode 100644 index e11cc51d06..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_CL.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_CO.dat b/awx/lib/site-packages/babel/localedata/es_CO.dat deleted file mode 100644 index dd04333657..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_CO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_CR.dat b/awx/lib/site-packages/babel/localedata/es_CR.dat deleted file mode 100644 index f433899fee..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_CR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_CU.dat b/awx/lib/site-packages/babel/localedata/es_CU.dat deleted file mode 100644 index 7228820220..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_CU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_DO.dat b/awx/lib/site-packages/babel/localedata/es_DO.dat deleted file mode 100644 index 66bebe8429..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_DO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_EA.dat b/awx/lib/site-packages/babel/localedata/es_EA.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_EA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_EC.dat b/awx/lib/site-packages/babel/localedata/es_EC.dat deleted file mode 100644 index 83d1eaf041..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_EC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_ES.dat b/awx/lib/site-packages/babel/localedata/es_ES.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_ES.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_GQ.dat b/awx/lib/site-packages/babel/localedata/es_GQ.dat deleted file mode 100644 index 13b86e08be..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_GQ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_GT.dat b/awx/lib/site-packages/babel/localedata/es_GT.dat deleted file mode 100644 index 83f5f6a05c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_GT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_HN.dat b/awx/lib/site-packages/babel/localedata/es_HN.dat deleted file mode 100644 index 4aa9304d56..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_HN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_IC.dat b/awx/lib/site-packages/babel/localedata/es_IC.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_IC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_MX.dat b/awx/lib/site-packages/babel/localedata/es_MX.dat deleted file mode 100644 index ae1c2a346f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_MX.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_NI.dat b/awx/lib/site-packages/babel/localedata/es_NI.dat deleted file mode 100644 index 7dfe184861..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_NI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_PA.dat b/awx/lib/site-packages/babel/localedata/es_PA.dat deleted file mode 100644 index 1222b4600e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_PA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_PE.dat b/awx/lib/site-packages/babel/localedata/es_PE.dat deleted file mode 100644 index 4da742810d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_PE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_PH.dat b/awx/lib/site-packages/babel/localedata/es_PH.dat deleted file mode 100644 index f4663c6eed..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_PH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_PR.dat b/awx/lib/site-packages/babel/localedata/es_PR.dat deleted file mode 100644 index 8db3f313b6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_PR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_PY.dat b/awx/lib/site-packages/babel/localedata/es_PY.dat deleted file mode 100644 index 0a022b42d7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_PY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_SV.dat b/awx/lib/site-packages/babel/localedata/es_SV.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/es_SV.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/es_US.dat b/awx/lib/site-packages/babel/localedata/es_US.dat deleted file mode 100644 index e427ff3c61..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_US.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_UY.dat b/awx/lib/site-packages/babel/localedata/es_UY.dat deleted file mode 100644 index bfd9e03337..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_UY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/es_VE.dat b/awx/lib/site-packages/babel/localedata/es_VE.dat deleted file mode 100644 index 65b44e1b35..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/es_VE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/et.dat b/awx/lib/site-packages/babel/localedata/et.dat deleted file mode 100644 index a9d8bb9e1d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/et.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/et_EE.dat b/awx/lib/site-packages/babel/localedata/et_EE.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/et_EE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/eu.dat b/awx/lib/site-packages/babel/localedata/eu.dat deleted file mode 100644 index 6131e09633..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/eu.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/eu_ES.dat b/awx/lib/site-packages/babel/localedata/eu_ES.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/eu_ES.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ewo.dat b/awx/lib/site-packages/babel/localedata/ewo.dat deleted file mode 100644 index 24172c24f4..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ewo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ewo_CM.dat b/awx/lib/site-packages/babel/localedata/ewo_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ewo_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fa.dat b/awx/lib/site-packages/babel/localedata/fa.dat deleted file mode 100644 index e5d7d4a2d9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fa.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fa_AF.dat b/awx/lib/site-packages/babel/localedata/fa_AF.dat deleted file mode 100644 index b7592aa281..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fa_AF.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fa_IR.dat b/awx/lib/site-packages/babel/localedata/fa_IR.dat deleted file mode 100644 index 150c7e3b45..0000000000 --- a/awx/lib/site-packages/babel/localedata/fa_IR.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ff.dat b/awx/lib/site-packages/babel/localedata/ff.dat deleted file mode 100644 index 5b3aab1cb2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ff.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ff_SN.dat b/awx/lib/site-packages/babel/localedata/ff_SN.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ff_SN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fi.dat b/awx/lib/site-packages/babel/localedata/fi.dat deleted file mode 100644 index cd6383776b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fi.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fi_FI.dat b/awx/lib/site-packages/babel/localedata/fi_FI.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fi_FI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fil.dat b/awx/lib/site-packages/babel/localedata/fil.dat deleted file mode 100644 index 4e790acd18..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fil.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fil_PH.dat b/awx/lib/site-packages/babel/localedata/fil_PH.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/fil_PH.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fo.dat b/awx/lib/site-packages/babel/localedata/fo.dat deleted file mode 100644 index 53dad88146..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fo_FO.dat b/awx/lib/site-packages/babel/localedata/fo_FO.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fo_FO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr.dat b/awx/lib/site-packages/babel/localedata/fr.dat deleted file mode 100644 index 12624b7779..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_BE.dat b/awx/lib/site-packages/babel/localedata/fr_BE.dat deleted file mode 100644 index 873a78c0db..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_BE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_BF.dat b/awx/lib/site-packages/babel/localedata/fr_BF.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_BF.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_BI.dat b/awx/lib/site-packages/babel/localedata/fr_BI.dat deleted file mode 100644 index 0e37e69993..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_BI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_BJ.dat b/awx/lib/site-packages/babel/localedata/fr_BJ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_BJ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_BL.dat b/awx/lib/site-packages/babel/localedata/fr_BL.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_BL.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_CA.dat b/awx/lib/site-packages/babel/localedata/fr_CA.dat deleted file mode 100644 index 22e00e6a87..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_CA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_CD.dat b/awx/lib/site-packages/babel/localedata/fr_CD.dat deleted file mode 100644 index 54d87d994b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_CD.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_CF.dat b/awx/lib/site-packages/babel/localedata/fr_CF.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_CF.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_CG.dat b/awx/lib/site-packages/babel/localedata/fr_CG.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_CG.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_CH.dat b/awx/lib/site-packages/babel/localedata/fr_CH.dat deleted file mode 100644 index da2a9705bb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_CH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_CI.dat b/awx/lib/site-packages/babel/localedata/fr_CI.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_CI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_CM.dat b/awx/lib/site-packages/babel/localedata/fr_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_DJ.dat b/awx/lib/site-packages/babel/localedata/fr_DJ.dat deleted file mode 100644 index b0ee442122..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_DJ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_DZ.dat b/awx/lib/site-packages/babel/localedata/fr_DZ.dat deleted file mode 100644 index be317e2b95..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_DZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_FR.dat b/awx/lib/site-packages/babel/localedata/fr_FR.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_FR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_GA.dat b/awx/lib/site-packages/babel/localedata/fr_GA.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_GA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_GF.dat b/awx/lib/site-packages/babel/localedata/fr_GF.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_GF.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_GN.dat b/awx/lib/site-packages/babel/localedata/fr_GN.dat deleted file mode 100644 index 4207c303c0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_GN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_GP.dat b/awx/lib/site-packages/babel/localedata/fr_GP.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_GP.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_GQ.dat b/awx/lib/site-packages/babel/localedata/fr_GQ.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_GQ.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_HT.dat b/awx/lib/site-packages/babel/localedata/fr_HT.dat deleted file mode 100644 index b57f296d4f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_HT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_KM.dat b/awx/lib/site-packages/babel/localedata/fr_KM.dat deleted file mode 100644 index 6a215c9a74..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_KM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_LU.dat b/awx/lib/site-packages/babel/localedata/fr_LU.dat deleted file mode 100644 index 947f11cb5e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_LU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_MA.dat b/awx/lib/site-packages/babel/localedata/fr_MA.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_MA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_MC.dat b/awx/lib/site-packages/babel/localedata/fr_MC.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_MC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_MF.dat b/awx/lib/site-packages/babel/localedata/fr_MF.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_MF.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_MG.dat b/awx/lib/site-packages/babel/localedata/fr_MG.dat deleted file mode 100644 index 507d98791c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_MG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_ML.dat b/awx/lib/site-packages/babel/localedata/fr_ML.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_ML.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_MQ.dat b/awx/lib/site-packages/babel/localedata/fr_MQ.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_MQ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_MR.dat b/awx/lib/site-packages/babel/localedata/fr_MR.dat deleted file mode 100644 index e37ceddb21..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_MR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_MU.dat b/awx/lib/site-packages/babel/localedata/fr_MU.dat deleted file mode 100644 index 1dcad22d3f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_MU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_NC.dat b/awx/lib/site-packages/babel/localedata/fr_NC.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_NC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_NE.dat b/awx/lib/site-packages/babel/localedata/fr_NE.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_NE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_PF.dat b/awx/lib/site-packages/babel/localedata/fr_PF.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_PF.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_RE.dat b/awx/lib/site-packages/babel/localedata/fr_RE.dat deleted file mode 100644 index 9721f8c0fd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_RE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_RW.dat b/awx/lib/site-packages/babel/localedata/fr_RW.dat deleted file mode 100644 index a6a51af8b6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_RW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_SC.dat b/awx/lib/site-packages/babel/localedata/fr_SC.dat deleted file mode 100644 index 017b99b9a7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_SC.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_SN.dat b/awx/lib/site-packages/babel/localedata/fr_SN.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_SN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_SY.dat b/awx/lib/site-packages/babel/localedata/fr_SY.dat deleted file mode 100644 index d2dd10e5bb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_SY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_TD.dat b/awx/lib/site-packages/babel/localedata/fr_TD.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/fr_TD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/fr_TG.dat b/awx/lib/site-packages/babel/localedata/fr_TG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_TG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_TN.dat b/awx/lib/site-packages/babel/localedata/fr_TN.dat deleted file mode 100644 index 70cc066160..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_TN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_VU.dat b/awx/lib/site-packages/babel/localedata/fr_VU.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_VU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fr_YT.dat b/awx/lib/site-packages/babel/localedata/fr_YT.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fr_YT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fur.dat b/awx/lib/site-packages/babel/localedata/fur.dat deleted file mode 100644 index 92767739a7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fur.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/fur_IT.dat b/awx/lib/site-packages/babel/localedata/fur_IT.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/fur_IT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ga.dat b/awx/lib/site-packages/babel/localedata/ga.dat deleted file mode 100644 index e47984a399..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ga.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ga_IE.dat b/awx/lib/site-packages/babel/localedata/ga_IE.dat deleted file mode 100644 index 401708ffe0..0000000000 --- a/awx/lib/site-packages/babel/localedata/ga_IE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/gd.dat b/awx/lib/site-packages/babel/localedata/gd.dat deleted file mode 100644 index d8d4a0357e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/gd.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/gd_GB.dat b/awx/lib/site-packages/babel/localedata/gd_GB.dat deleted file mode 100644 index 401708ffe0..0000000000 --- a/awx/lib/site-packages/babel/localedata/gd_GB.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/gl.dat b/awx/lib/site-packages/babel/localedata/gl.dat deleted file mode 100644 index c9fcaabfbc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/gl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/gl_ES.dat b/awx/lib/site-packages/babel/localedata/gl_ES.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/gl_ES.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/gsw.dat b/awx/lib/site-packages/babel/localedata/gsw.dat deleted file mode 100644 index 061781160a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/gsw.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/gsw_CH.dat b/awx/lib/site-packages/babel/localedata/gsw_CH.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/gsw_CH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/gu.dat b/awx/lib/site-packages/babel/localedata/gu.dat deleted file mode 100644 index 19621ca20f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/gu.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/gu_IN.dat b/awx/lib/site-packages/babel/localedata/gu_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/gu_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/guz.dat b/awx/lib/site-packages/babel/localedata/guz.dat deleted file mode 100644 index d287c50cfe..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/guz.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/guz_KE.dat b/awx/lib/site-packages/babel/localedata/guz_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/guz_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/gv.dat b/awx/lib/site-packages/babel/localedata/gv.dat deleted file mode 100644 index 4d92358922..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/gv.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/gv_GB.dat b/awx/lib/site-packages/babel/localedata/gv_GB.dat deleted file mode 100644 index 401708ffe0..0000000000 --- a/awx/lib/site-packages/babel/localedata/gv_GB.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ha.dat b/awx/lib/site-packages/babel/localedata/ha.dat deleted file mode 100644 index d42e1f232b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ha.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ha_Latn.dat b/awx/lib/site-packages/babel/localedata/ha_Latn.dat deleted file mode 100644 index 27760a1c92..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ha_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ha_Latn_GH.dat b/awx/lib/site-packages/babel/localedata/ha_Latn_GH.dat deleted file mode 100644 index a6c4ac105f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ha_Latn_GH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ha_Latn_NE.dat b/awx/lib/site-packages/babel/localedata/ha_Latn_NE.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ha_Latn_NE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ha_Latn_NG.dat b/awx/lib/site-packages/babel/localedata/ha_Latn_NG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ha_Latn_NG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/haw.dat b/awx/lib/site-packages/babel/localedata/haw.dat deleted file mode 100644 index 74c46ef839..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/haw.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/haw_US.dat b/awx/lib/site-packages/babel/localedata/haw_US.dat deleted file mode 100644 index e1639abe76..0000000000 --- a/awx/lib/site-packages/babel/localedata/haw_US.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/he.dat b/awx/lib/site-packages/babel/localedata/he.dat deleted file mode 100644 index f085ae17bd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/he.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/he_IL.dat b/awx/lib/site-packages/babel/localedata/he_IL.dat deleted file mode 100644 index 36bd112d1a..0000000000 --- a/awx/lib/site-packages/babel/localedata/he_IL.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/hi.dat b/awx/lib/site-packages/babel/localedata/hi.dat deleted file mode 100644 index 26f01c7ee8..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hi.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/hi_IN.dat b/awx/lib/site-packages/babel/localedata/hi_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/hi_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/hr.dat b/awx/lib/site-packages/babel/localedata/hr.dat deleted file mode 100644 index c11d395194..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hr.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/hr_BA.dat b/awx/lib/site-packages/babel/localedata/hr_BA.dat deleted file mode 100644 index 7b23688527..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hr_BA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/hr_HR.dat b/awx/lib/site-packages/babel/localedata/hr_HR.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hr_HR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/hu.dat b/awx/lib/site-packages/babel/localedata/hu.dat deleted file mode 100644 index ddc9aae167..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hu.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/hu_HU.dat b/awx/lib/site-packages/babel/localedata/hu_HU.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hu_HU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/hy.dat b/awx/lib/site-packages/babel/localedata/hy.dat deleted file mode 100644 index 59fc3928e9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hy.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/hy_AM.dat b/awx/lib/site-packages/babel/localedata/hy_AM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/hy_AM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ia.dat b/awx/lib/site-packages/babel/localedata/ia.dat deleted file mode 100644 index d97e3257c2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ia.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ia_FR.dat b/awx/lib/site-packages/babel/localedata/ia_FR.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ia_FR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/id.dat b/awx/lib/site-packages/babel/localedata/id.dat deleted file mode 100644 index 1b8398a67d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/id.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/id_ID.dat b/awx/lib/site-packages/babel/localedata/id_ID.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/id_ID.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ig.dat b/awx/lib/site-packages/babel/localedata/ig.dat deleted file mode 100644 index c19bb598f7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ig.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ig_NG.dat b/awx/lib/site-packages/babel/localedata/ig_NG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ig_NG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ii.dat b/awx/lib/site-packages/babel/localedata/ii.dat deleted file mode 100644 index 1b6499e90c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ii.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ii_CN.dat b/awx/lib/site-packages/babel/localedata/ii_CN.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/ii_CN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/is.dat b/awx/lib/site-packages/babel/localedata/is.dat deleted file mode 100644 index f1996ea61d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/is.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/is_IS.dat b/awx/lib/site-packages/babel/localedata/is_IS.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/is_IS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/it.dat b/awx/lib/site-packages/babel/localedata/it.dat deleted file mode 100644 index b084d771c9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/it.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/it_CH.dat b/awx/lib/site-packages/babel/localedata/it_CH.dat deleted file mode 100644 index d37370cc80..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/it_CH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/it_IT.dat b/awx/lib/site-packages/babel/localedata/it_IT.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/it_IT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/it_SM.dat b/awx/lib/site-packages/babel/localedata/it_SM.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/it_SM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ja.dat b/awx/lib/site-packages/babel/localedata/ja.dat deleted file mode 100644 index 7351a74748..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ja.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ja_JP.dat b/awx/lib/site-packages/babel/localedata/ja_JP.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/ja_JP.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/jgo.dat b/awx/lib/site-packages/babel/localedata/jgo.dat deleted file mode 100644 index 616271b58e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/jgo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/jgo_CM.dat b/awx/lib/site-packages/babel/localedata/jgo_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/jgo_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/jmc.dat b/awx/lib/site-packages/babel/localedata/jmc.dat deleted file mode 100644 index ccc3b8369b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/jmc.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/jmc_TZ.dat b/awx/lib/site-packages/babel/localedata/jmc_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/jmc_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ka.dat b/awx/lib/site-packages/babel/localedata/ka.dat deleted file mode 100644 index 1979e8aaf1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ka.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ka_GE.dat b/awx/lib/site-packages/babel/localedata/ka_GE.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ka_GE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kab.dat b/awx/lib/site-packages/babel/localedata/kab.dat deleted file mode 100644 index 409ba3b0a9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kab.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kab_DZ.dat b/awx/lib/site-packages/babel/localedata/kab_DZ.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/kab_DZ.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/kam.dat b/awx/lib/site-packages/babel/localedata/kam.dat deleted file mode 100644 index 70c78d0556..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kam.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kam_KE.dat b/awx/lib/site-packages/babel/localedata/kam_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/kam_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/kde.dat b/awx/lib/site-packages/babel/localedata/kde.dat deleted file mode 100644 index 3468c0687d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kde.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kde_TZ.dat b/awx/lib/site-packages/babel/localedata/kde_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kde_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kea.dat b/awx/lib/site-packages/babel/localedata/kea.dat deleted file mode 100644 index 36e669e1e1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kea.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kea_CV.dat b/awx/lib/site-packages/babel/localedata/kea_CV.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kea_CV.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/khq.dat b/awx/lib/site-packages/babel/localedata/khq.dat deleted file mode 100644 index 4e900a7809..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/khq.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/khq_ML.dat b/awx/lib/site-packages/babel/localedata/khq_ML.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/khq_ML.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ki.dat b/awx/lib/site-packages/babel/localedata/ki.dat deleted file mode 100644 index d30ce01f50..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ki.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ki_KE.dat b/awx/lib/site-packages/babel/localedata/ki_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ki_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/kk.dat b/awx/lib/site-packages/babel/localedata/kk.dat deleted file mode 100644 index 3125ea545d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kk.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kk_Cyrl.dat b/awx/lib/site-packages/babel/localedata/kk_Cyrl.dat deleted file mode 100644 index 27760a1c92..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kk_Cyrl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kk_Cyrl_KZ.dat b/awx/lib/site-packages/babel/localedata/kk_Cyrl_KZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kk_Cyrl_KZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kkj.dat b/awx/lib/site-packages/babel/localedata/kkj.dat deleted file mode 100644 index bd2d7b08a2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kkj.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kkj_CM.dat b/awx/lib/site-packages/babel/localedata/kkj_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kkj_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kl.dat b/awx/lib/site-packages/babel/localedata/kl.dat deleted file mode 100644 index 5c13a69f58..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kl_GL.dat b/awx/lib/site-packages/babel/localedata/kl_GL.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/kl_GL.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/kln.dat b/awx/lib/site-packages/babel/localedata/kln.dat deleted file mode 100644 index a5cc035256..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kln.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kln_KE.dat b/awx/lib/site-packages/babel/localedata/kln_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/kln_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/km.dat b/awx/lib/site-packages/babel/localedata/km.dat deleted file mode 100644 index 4613359cfd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/km.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/km_KH.dat b/awx/lib/site-packages/babel/localedata/km_KH.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/km_KH.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/kn.dat b/awx/lib/site-packages/babel/localedata/kn.dat deleted file mode 100644 index c136cc5fed..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kn_IN.dat b/awx/lib/site-packages/babel/localedata/kn_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/kn_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ko.dat b/awx/lib/site-packages/babel/localedata/ko.dat deleted file mode 100644 index 5910e0d6d5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ko.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ko_KP.dat b/awx/lib/site-packages/babel/localedata/ko_KP.dat deleted file mode 100644 index 4b4537f74c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ko_KP.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ko_KR.dat b/awx/lib/site-packages/babel/localedata/ko_KR.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/ko_KR.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/kok.dat b/awx/lib/site-packages/babel/localedata/kok.dat deleted file mode 100644 index 012c2e20ea..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kok.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kok_IN.dat b/awx/lib/site-packages/babel/localedata/kok_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/kok_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ks.dat b/awx/lib/site-packages/babel/localedata/ks.dat deleted file mode 100644 index bd4a42723c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ks.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ks_Arab.dat b/awx/lib/site-packages/babel/localedata/ks_Arab.dat deleted file mode 100644 index 27760a1c92..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ks_Arab.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ks_Arab_IN.dat b/awx/lib/site-packages/babel/localedata/ks_Arab_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/ks_Arab_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ksb.dat b/awx/lib/site-packages/babel/localedata/ksb.dat deleted file mode 100644 index 4a1600561e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ksb.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ksb_TZ.dat b/awx/lib/site-packages/babel/localedata/ksb_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ksb_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ksf.dat b/awx/lib/site-packages/babel/localedata/ksf.dat deleted file mode 100644 index 11881d4407..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ksf.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ksf_CM.dat b/awx/lib/site-packages/babel/localedata/ksf_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ksf_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ksh.dat b/awx/lib/site-packages/babel/localedata/ksh.dat deleted file mode 100644 index 385e52e44a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ksh.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ksh_DE.dat b/awx/lib/site-packages/babel/localedata/ksh_DE.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ksh_DE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kw.dat b/awx/lib/site-packages/babel/localedata/kw.dat deleted file mode 100644 index 4056d0ad99..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/kw.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/kw_GB.dat b/awx/lib/site-packages/babel/localedata/kw_GB.dat deleted file mode 100644 index 401708ffe0..0000000000 --- a/awx/lib/site-packages/babel/localedata/kw_GB.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ky.dat b/awx/lib/site-packages/babel/localedata/ky.dat deleted file mode 100644 index cff43ec904..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ky.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ky_KG.dat b/awx/lib/site-packages/babel/localedata/ky_KG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ky_KG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lag.dat b/awx/lib/site-packages/babel/localedata/lag.dat deleted file mode 100644 index 922e70fb30..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lag.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lag_TZ.dat b/awx/lib/site-packages/babel/localedata/lag_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lag_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lg.dat b/awx/lib/site-packages/babel/localedata/lg.dat deleted file mode 100644 index dbbf1eba33..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lg.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lg_UG.dat b/awx/lib/site-packages/babel/localedata/lg_UG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lg_UG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ln.dat b/awx/lib/site-packages/babel/localedata/ln.dat deleted file mode 100644 index 320079bba8..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ln.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ln_AO.dat b/awx/lib/site-packages/babel/localedata/ln_AO.dat deleted file mode 100644 index dc23f4ecc1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ln_AO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ln_CD.dat b/awx/lib/site-packages/babel/localedata/ln_CD.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/ln_CD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ln_CF.dat b/awx/lib/site-packages/babel/localedata/ln_CF.dat deleted file mode 100644 index 4c19ce3b40..0000000000 --- a/awx/lib/site-packages/babel/localedata/ln_CF.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqML U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ln_CG.dat b/awx/lib/site-packages/babel/localedata/ln_CG.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/ln_CG.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/lo.dat b/awx/lib/site-packages/babel/localedata/lo.dat deleted file mode 100644 index 561bad36b2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lo_LA.dat b/awx/lib/site-packages/babel/localedata/lo_LA.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/lo_LA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/lt.dat b/awx/lib/site-packages/babel/localedata/lt.dat deleted file mode 100644 index c05b9188a8..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lt.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lt_LT.dat b/awx/lib/site-packages/babel/localedata/lt_LT.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lt_LT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lu.dat b/awx/lib/site-packages/babel/localedata/lu.dat deleted file mode 100644 index 5d49557305..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lu.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lu_CD.dat b/awx/lib/site-packages/babel/localedata/lu_CD.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/lu_CD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/luo.dat b/awx/lib/site-packages/babel/localedata/luo.dat deleted file mode 100644 index 326e796e29..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/luo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/luo_KE.dat b/awx/lib/site-packages/babel/localedata/luo_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/luo_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/luy.dat b/awx/lib/site-packages/babel/localedata/luy.dat deleted file mode 100644 index b9706a1feb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/luy.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/luy_KE.dat b/awx/lib/site-packages/babel/localedata/luy_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/luy_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/lv.dat b/awx/lib/site-packages/babel/localedata/lv.dat deleted file mode 100644 index a3f770d489..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lv.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/lv_LV.dat b/awx/lib/site-packages/babel/localedata/lv_LV.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/lv_LV.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mas.dat b/awx/lib/site-packages/babel/localedata/mas.dat deleted file mode 100644 index 6f17d0de79..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mas.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mas_KE.dat b/awx/lib/site-packages/babel/localedata/mas_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/mas_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/mas_TZ.dat b/awx/lib/site-packages/babel/localedata/mas_TZ.dat deleted file mode 100644 index 5e7539548b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mas_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mer.dat b/awx/lib/site-packages/babel/localedata/mer.dat deleted file mode 100644 index 265eac28a2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mer.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mer_KE.dat b/awx/lib/site-packages/babel/localedata/mer_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/mer_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/mfe.dat b/awx/lib/site-packages/babel/localedata/mfe.dat deleted file mode 100644 index e146820f92..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mfe.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mfe_MU.dat b/awx/lib/site-packages/babel/localedata/mfe_MU.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mfe_MU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mg.dat b/awx/lib/site-packages/babel/localedata/mg.dat deleted file mode 100644 index bbab19f030..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mg.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mg_MG.dat b/awx/lib/site-packages/babel/localedata/mg_MG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mg_MG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mgh.dat b/awx/lib/site-packages/babel/localedata/mgh.dat deleted file mode 100644 index 12987fc6df..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mgh.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mgh_MZ.dat b/awx/lib/site-packages/babel/localedata/mgh_MZ.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/mgh_MZ.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/mgo.dat b/awx/lib/site-packages/babel/localedata/mgo.dat deleted file mode 100644 index c90ac45f6d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mgo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mgo_CM.dat b/awx/lib/site-packages/babel/localedata/mgo_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mgo_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mk.dat b/awx/lib/site-packages/babel/localedata/mk.dat deleted file mode 100644 index 098b226262..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mk.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mk_MK.dat b/awx/lib/site-packages/babel/localedata/mk_MK.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mk_MK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ml.dat b/awx/lib/site-packages/babel/localedata/ml.dat deleted file mode 100644 index df293ad9b1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ml.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ml_IN.dat b/awx/lib/site-packages/babel/localedata/ml_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/ml_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/mn.dat b/awx/lib/site-packages/babel/localedata/mn.dat deleted file mode 100644 index 8b3efac675..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mn_Cyrl.dat b/awx/lib/site-packages/babel/localedata/mn_Cyrl.dat deleted file mode 100644 index 27760a1c92..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mn_Cyrl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mn_Cyrl_MN.dat b/awx/lib/site-packages/babel/localedata/mn_Cyrl_MN.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mn_Cyrl_MN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mr.dat b/awx/lib/site-packages/babel/localedata/mr.dat deleted file mode 100644 index 29dde4e7ea..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mr.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mr_IN.dat b/awx/lib/site-packages/babel/localedata/mr_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/mr_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ms.dat b/awx/lib/site-packages/babel/localedata/ms.dat deleted file mode 100644 index a6974ea4c4..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ms.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ms_Latn.dat b/awx/lib/site-packages/babel/localedata/ms_Latn.dat deleted file mode 100644 index 1ba8202e3a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ms_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ms_Latn_BN.dat b/awx/lib/site-packages/babel/localedata/ms_Latn_BN.dat deleted file mode 100644 index d76b0c96ce..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ms_Latn_BN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ms_Latn_MY.dat b/awx/lib/site-packages/babel/localedata/ms_Latn_MY.dat deleted file mode 100644 index 5080866361..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ms_Latn_MY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ms_Latn_SG.dat b/awx/lib/site-packages/babel/localedata/ms_Latn_SG.dat deleted file mode 100644 index 5120c3052f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ms_Latn_SG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mt.dat b/awx/lib/site-packages/babel/localedata/mt.dat deleted file mode 100644 index cbf2feb17d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mt.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mt_MT.dat b/awx/lib/site-packages/babel/localedata/mt_MT.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/mt_MT.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/mua.dat b/awx/lib/site-packages/babel/localedata/mua.dat deleted file mode 100644 index dd4881c8fa..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mua.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/mua_CM.dat b/awx/lib/site-packages/babel/localedata/mua_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/mua_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/my.dat b/awx/lib/site-packages/babel/localedata/my.dat deleted file mode 100644 index 6482e5ea0f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/my.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/my_MM.dat b/awx/lib/site-packages/babel/localedata/my_MM.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/my_MM.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/naq.dat b/awx/lib/site-packages/babel/localedata/naq.dat deleted file mode 100644 index 87fc01f852..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/naq.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/naq_NA.dat b/awx/lib/site-packages/babel/localedata/naq_NA.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/naq_NA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nb.dat b/awx/lib/site-packages/babel/localedata/nb.dat deleted file mode 100644 index aa34863b4e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nb.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nb_NO.dat b/awx/lib/site-packages/babel/localedata/nb_NO.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nb_NO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nd.dat b/awx/lib/site-packages/babel/localedata/nd.dat deleted file mode 100644 index 231008ec88..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nd.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nd_ZW.dat b/awx/lib/site-packages/babel/localedata/nd_ZW.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/nd_ZW.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ne.dat b/awx/lib/site-packages/babel/localedata/ne.dat deleted file mode 100644 index d078fcf401..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ne.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ne_IN.dat b/awx/lib/site-packages/babel/localedata/ne_IN.dat deleted file mode 100644 index 8044567a61..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ne_IN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ne_NP.dat b/awx/lib/site-packages/babel/localedata/ne_NP.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/ne_NP.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/nl.dat b/awx/lib/site-packages/babel/localedata/nl.dat deleted file mode 100644 index ace2ad6470..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nl_AW.dat b/awx/lib/site-packages/babel/localedata/nl_AW.dat deleted file mode 100644 index 6f68c997cd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nl_AW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nl_BE.dat b/awx/lib/site-packages/babel/localedata/nl_BE.dat deleted file mode 100644 index c722c78caa..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nl_BE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nl_CW.dat b/awx/lib/site-packages/babel/localedata/nl_CW.dat deleted file mode 100644 index 11b34d922f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nl_CW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nl_NL.dat b/awx/lib/site-packages/babel/localedata/nl_NL.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nl_NL.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nl_SR.dat b/awx/lib/site-packages/babel/localedata/nl_SR.dat deleted file mode 100644 index 91804fbfc9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nl_SR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nl_SX.dat b/awx/lib/site-packages/babel/localedata/nl_SX.dat deleted file mode 100644 index 11b34d922f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nl_SX.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nmg.dat b/awx/lib/site-packages/babel/localedata/nmg.dat deleted file mode 100644 index 41987a1ec7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nmg.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nmg_CM.dat b/awx/lib/site-packages/babel/localedata/nmg_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nmg_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nn.dat b/awx/lib/site-packages/babel/localedata/nn.dat deleted file mode 100644 index c810a884d0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nn_NO.dat b/awx/lib/site-packages/babel/localedata/nn_NO.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nn_NO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nnh.dat b/awx/lib/site-packages/babel/localedata/nnh.dat deleted file mode 100644 index 28dbf242e6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nnh.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nnh_CM.dat b/awx/lib/site-packages/babel/localedata/nnh_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nnh_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nr.dat b/awx/lib/site-packages/babel/localedata/nr.dat deleted file mode 100644 index 019afc0a40..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nr.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nr_ZA.dat b/awx/lib/site-packages/babel/localedata/nr_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/nr_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/nso.dat b/awx/lib/site-packages/babel/localedata/nso.dat deleted file mode 100644 index 0a37bd063b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nso.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nso_ZA.dat b/awx/lib/site-packages/babel/localedata/nso_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/nso_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/nus.dat b/awx/lib/site-packages/babel/localedata/nus.dat deleted file mode 100644 index 3ad9c0cc18..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nus.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nus_SD.dat b/awx/lib/site-packages/babel/localedata/nus_SD.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/nus_SD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/nyn.dat b/awx/lib/site-packages/babel/localedata/nyn.dat deleted file mode 100644 index f13b314bd2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nyn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/nyn_UG.dat b/awx/lib/site-packages/babel/localedata/nyn_UG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/nyn_UG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/om.dat b/awx/lib/site-packages/babel/localedata/om.dat deleted file mode 100644 index 53213cfe23..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/om.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/om_ET.dat b/awx/lib/site-packages/babel/localedata/om_ET.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/om_ET.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/om_KE.dat b/awx/lib/site-packages/babel/localedata/om_KE.dat deleted file mode 100644 index b126edd7f1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/om_KE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/or.dat b/awx/lib/site-packages/babel/localedata/or.dat deleted file mode 100644 index c01ab44228..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/or.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/or_IN.dat b/awx/lib/site-packages/babel/localedata/or_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/or_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/os.dat b/awx/lib/site-packages/babel/localedata/os.dat deleted file mode 100644 index 0a01ac8b1c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/os.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/os_GE.dat b/awx/lib/site-packages/babel/localedata/os_GE.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/os_GE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/os_RU.dat b/awx/lib/site-packages/babel/localedata/os_RU.dat deleted file mode 100644 index b1b0d843d5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/os_RU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pa.dat b/awx/lib/site-packages/babel/localedata/pa.dat deleted file mode 100644 index 100c377967..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pa.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pa_Arab.dat b/awx/lib/site-packages/babel/localedata/pa_Arab.dat deleted file mode 100644 index b32025cf66..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pa_Arab.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pa_Arab_PK.dat b/awx/lib/site-packages/babel/localedata/pa_Arab_PK.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/pa_Arab_PK.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/pa_Guru.dat b/awx/lib/site-packages/babel/localedata/pa_Guru.dat deleted file mode 100644 index 27760a1c92..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pa_Guru.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pa_Guru_IN.dat b/awx/lib/site-packages/babel/localedata/pa_Guru_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/pa_Guru_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/pl.dat b/awx/lib/site-packages/babel/localedata/pl.dat deleted file mode 100644 index 11abe814dc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pl_PL.dat b/awx/lib/site-packages/babel/localedata/pl_PL.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pl_PL.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ps.dat b/awx/lib/site-packages/babel/localedata/ps.dat deleted file mode 100644 index 6521e4b33f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ps.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ps_AF.dat b/awx/lib/site-packages/babel/localedata/ps_AF.dat deleted file mode 100644 index 150c7e3b45..0000000000 --- a/awx/lib/site-packages/babel/localedata/ps_AF.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/pt.dat b/awx/lib/site-packages/babel/localedata/pt.dat deleted file mode 100644 index bf22a14e06..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_AO.dat b/awx/lib/site-packages/babel/localedata/pt_AO.dat deleted file mode 100644 index cd4cd79d3d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_AO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_BR.dat b/awx/lib/site-packages/babel/localedata/pt_BR.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/pt_BR.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/pt_CV.dat b/awx/lib/site-packages/babel/localedata/pt_CV.dat deleted file mode 100644 index 98f10615f6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_CV.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_GW.dat b/awx/lib/site-packages/babel/localedata/pt_GW.dat deleted file mode 100644 index 98f10615f6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_GW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_MO.dat b/awx/lib/site-packages/babel/localedata/pt_MO.dat deleted file mode 100644 index d40c46f1fc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_MO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_MZ.dat b/awx/lib/site-packages/babel/localedata/pt_MZ.dat deleted file mode 100644 index bfd2551065..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_MZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_PT.dat b/awx/lib/site-packages/babel/localedata/pt_PT.dat deleted file mode 100644 index 203b692c8a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_PT.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_ST.dat b/awx/lib/site-packages/babel/localedata/pt_ST.dat deleted file mode 100644 index 30882bdedf..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_ST.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/pt_TL.dat b/awx/lib/site-packages/babel/localedata/pt_TL.dat deleted file mode 100644 index 6b5a0f9f72..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/pt_TL.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rm.dat b/awx/lib/site-packages/babel/localedata/rm.dat deleted file mode 100644 index c03c5aed97..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rm.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rm_CH.dat b/awx/lib/site-packages/babel/localedata/rm_CH.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rm_CH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rn.dat b/awx/lib/site-packages/babel/localedata/rn.dat deleted file mode 100644 index 50efb2e990..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rn_BI.dat b/awx/lib/site-packages/babel/localedata/rn_BI.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rn_BI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ro.dat b/awx/lib/site-packages/babel/localedata/ro.dat deleted file mode 100644 index 18ee70fa44..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ro.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ro_MD.dat b/awx/lib/site-packages/babel/localedata/ro_MD.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ro_MD.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ro_RO.dat b/awx/lib/site-packages/babel/localedata/ro_RO.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ro_RO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rof.dat b/awx/lib/site-packages/babel/localedata/rof.dat deleted file mode 100644 index 28f38de9cb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rof.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rof_TZ.dat b/awx/lib/site-packages/babel/localedata/rof_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rof_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/root.dat b/awx/lib/site-packages/babel/localedata/root.dat deleted file mode 100644 index 80ab0eb763..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/root.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ru.dat b/awx/lib/site-packages/babel/localedata/ru.dat deleted file mode 100644 index fc116df80c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ru.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ru_BY.dat b/awx/lib/site-packages/babel/localedata/ru_BY.dat deleted file mode 100644 index 640cb7967e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ru_BY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ru_KG.dat b/awx/lib/site-packages/babel/localedata/ru_KG.dat deleted file mode 100644 index 87f3389642..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ru_KG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ru_KZ.dat b/awx/lib/site-packages/babel/localedata/ru_KZ.dat deleted file mode 100644 index 62d0b24636..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ru_KZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ru_MD.dat b/awx/lib/site-packages/babel/localedata/ru_MD.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ru_MD.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ru_RU.dat b/awx/lib/site-packages/babel/localedata/ru_RU.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ru_RU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ru_UA.dat b/awx/lib/site-packages/babel/localedata/ru_UA.dat deleted file mode 100644 index c726ba8109..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ru_UA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rw.dat b/awx/lib/site-packages/babel/localedata/rw.dat deleted file mode 100644 index 0403c67b76..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rw.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rw_RW.dat b/awx/lib/site-packages/babel/localedata/rw_RW.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rw_RW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rwk.dat b/awx/lib/site-packages/babel/localedata/rwk.dat deleted file mode 100644 index d18d314480..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rwk.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/rwk_TZ.dat b/awx/lib/site-packages/babel/localedata/rwk_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/rwk_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sah.dat b/awx/lib/site-packages/babel/localedata/sah.dat deleted file mode 100644 index 38fb037c5b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sah.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sah_RU.dat b/awx/lib/site-packages/babel/localedata/sah_RU.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sah_RU.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/saq.dat b/awx/lib/site-packages/babel/localedata/saq.dat deleted file mode 100644 index 858cb6a020..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/saq.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/saq_KE.dat b/awx/lib/site-packages/babel/localedata/saq_KE.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/saq_KE.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/sbp.dat b/awx/lib/site-packages/babel/localedata/sbp.dat deleted file mode 100644 index 36f5081126..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sbp.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sbp_TZ.dat b/awx/lib/site-packages/babel/localedata/sbp_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sbp_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/se.dat b/awx/lib/site-packages/babel/localedata/se.dat deleted file mode 100644 index 4093ad3e75..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/se.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/se_FI.dat b/awx/lib/site-packages/babel/localedata/se_FI.dat deleted file mode 100644 index 561ae0fdb8..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/se_FI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/se_NO.dat b/awx/lib/site-packages/babel/localedata/se_NO.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/se_NO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/seh.dat b/awx/lib/site-packages/babel/localedata/seh.dat deleted file mode 100644 index 639220100f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/seh.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/seh_MZ.dat b/awx/lib/site-packages/babel/localedata/seh_MZ.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/seh_MZ.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ses.dat b/awx/lib/site-packages/babel/localedata/ses.dat deleted file mode 100644 index d537b3f856..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ses.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ses_ML.dat b/awx/lib/site-packages/babel/localedata/ses_ML.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ses_ML.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sg.dat b/awx/lib/site-packages/babel/localedata/sg.dat deleted file mode 100644 index f7e398c823..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sg.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sg_CF.dat b/awx/lib/site-packages/babel/localedata/sg_CF.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/sg_CF.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/shi.dat b/awx/lib/site-packages/babel/localedata/shi.dat deleted file mode 100644 index 8adbb59a88..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/shi.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/shi_Latn.dat b/awx/lib/site-packages/babel/localedata/shi_Latn.dat deleted file mode 100644 index 1cb6147cbc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/shi_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/shi_Latn_MA.dat b/awx/lib/site-packages/babel/localedata/shi_Latn_MA.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/shi_Latn_MA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/shi_Tfng.dat b/awx/lib/site-packages/babel/localedata/shi_Tfng.dat deleted file mode 100644 index 21966f5f74..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/shi_Tfng.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/shi_Tfng_MA.dat b/awx/lib/site-packages/babel/localedata/shi_Tfng_MA.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/shi_Tfng_MA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/si.dat b/awx/lib/site-packages/babel/localedata/si.dat deleted file mode 100644 index ecb30a7658..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/si.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/si_LK.dat b/awx/lib/site-packages/babel/localedata/si_LK.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/si_LK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sk.dat b/awx/lib/site-packages/babel/localedata/sk.dat deleted file mode 100644 index 59fa86d2d6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sk.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sk_SK.dat b/awx/lib/site-packages/babel/localedata/sk_SK.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sk_SK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sl.dat b/awx/lib/site-packages/babel/localedata/sl.dat deleted file mode 100644 index 7810cc351c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sl_SI.dat b/awx/lib/site-packages/babel/localedata/sl_SI.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sl_SI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sn.dat b/awx/lib/site-packages/babel/localedata/sn.dat deleted file mode 100644 index 29c97a36e1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sn_ZW.dat b/awx/lib/site-packages/babel/localedata/sn_ZW.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/sn_ZW.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/so.dat b/awx/lib/site-packages/babel/localedata/so.dat deleted file mode 100644 index 7844a44567..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/so.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/so_DJ.dat b/awx/lib/site-packages/babel/localedata/so_DJ.dat deleted file mode 100644 index b0ee442122..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/so_DJ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/so_ET.dat b/awx/lib/site-packages/babel/localedata/so_ET.dat deleted file mode 100644 index b432229662..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/so_ET.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/so_KE.dat b/awx/lib/site-packages/babel/localedata/so_KE.dat deleted file mode 100644 index b126edd7f1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/so_KE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/so_SO.dat b/awx/lib/site-packages/babel/localedata/so_SO.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/so_SO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sq.dat b/awx/lib/site-packages/babel/localedata/sq.dat deleted file mode 100644 index a03fcf0a3d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sq.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sq_AL.dat b/awx/lib/site-packages/babel/localedata/sq_AL.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sq_AL.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sq_MK.dat b/awx/lib/site-packages/babel/localedata/sq_MK.dat deleted file mode 100644 index 65bfa5c8c9..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sq_MK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sq_XK.dat b/awx/lib/site-packages/babel/localedata/sq_XK.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sq_XK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr.dat b/awx/lib/site-packages/babel/localedata/sr.dat deleted file mode 100644 index ef9cd2cc33..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Cyrl.dat b/awx/lib/site-packages/babel/localedata/sr_Cyrl.dat deleted file mode 100644 index a882c5bcaf..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Cyrl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Cyrl_BA.dat b/awx/lib/site-packages/babel/localedata/sr_Cyrl_BA.dat deleted file mode 100644 index 8d9fa9f5a3..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Cyrl_BA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Cyrl_ME.dat b/awx/lib/site-packages/babel/localedata/sr_Cyrl_ME.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Cyrl_ME.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Cyrl_RS.dat b/awx/lib/site-packages/babel/localedata/sr_Cyrl_RS.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Cyrl_RS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Cyrl_XK.dat b/awx/lib/site-packages/babel/localedata/sr_Cyrl_XK.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Cyrl_XK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Latn.dat b/awx/lib/site-packages/babel/localedata/sr_Latn.dat deleted file mode 100644 index 57b44f1ea7..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Latn_BA.dat b/awx/lib/site-packages/babel/localedata/sr_Latn_BA.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Latn_BA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Latn_ME.dat b/awx/lib/site-packages/babel/localedata/sr_Latn_ME.dat deleted file mode 100644 index b0f4d9b306..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Latn_ME.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Latn_RS.dat b/awx/lib/site-packages/babel/localedata/sr_Latn_RS.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Latn_RS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sr_Latn_XK.dat b/awx/lib/site-packages/babel/localedata/sr_Latn_XK.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sr_Latn_XK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ss.dat b/awx/lib/site-packages/babel/localedata/ss.dat deleted file mode 100644 index c7807243d0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ss.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ss_SZ.dat b/awx/lib/site-packages/babel/localedata/ss_SZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ss_SZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ss_ZA.dat b/awx/lib/site-packages/babel/localedata/ss_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ss_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ssy.dat b/awx/lib/site-packages/babel/localedata/ssy.dat deleted file mode 100644 index 926fd85d84..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ssy.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ssy_ER.dat b/awx/lib/site-packages/babel/localedata/ssy_ER.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ssy_ER.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/st.dat b/awx/lib/site-packages/babel/localedata/st.dat deleted file mode 100644 index d19795e3e2..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/st.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/st_LS.dat b/awx/lib/site-packages/babel/localedata/st_LS.dat deleted file mode 100644 index 348a167849..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/st_LS.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/st_ZA.dat b/awx/lib/site-packages/babel/localedata/st_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/st_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/sv.dat b/awx/lib/site-packages/babel/localedata/sv.dat deleted file mode 100644 index bce70f1513..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sv.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sv_AX.dat b/awx/lib/site-packages/babel/localedata/sv_AX.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sv_AX.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sv_FI.dat b/awx/lib/site-packages/babel/localedata/sv_FI.dat deleted file mode 100644 index f42189dcea..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sv_FI.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sv_SE.dat b/awx/lib/site-packages/babel/localedata/sv_SE.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sv_SE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sw.dat b/awx/lib/site-packages/babel/localedata/sw.dat deleted file mode 100644 index 6c525cad5e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sw.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sw_KE.dat b/awx/lib/site-packages/babel/localedata/sw_KE.dat deleted file mode 100644 index 3c922118c0..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sw_KE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sw_TZ.dat b/awx/lib/site-packages/babel/localedata/sw_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sw_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/sw_UG.dat b/awx/lib/site-packages/babel/localedata/sw_UG.dat deleted file mode 100644 index 3b68eaa1a1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/sw_UG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/swc.dat b/awx/lib/site-packages/babel/localedata/swc.dat deleted file mode 100644 index 247ea25727..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/swc.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/swc_CD.dat b/awx/lib/site-packages/babel/localedata/swc_CD.dat deleted file mode 100644 index a7cee6f283..0000000000 --- a/awx/lib/site-packages/babel/localedata/swc_CD.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}qUcurrency_namesq }q!U unit_patternsq"}q#u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ta.dat b/awx/lib/site-packages/babel/localedata/ta.dat deleted file mode 100644 index 9115227a99..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ta.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ta_IN.dat b/awx/lib/site-packages/babel/localedata/ta_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/ta_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ta_LK.dat b/awx/lib/site-packages/babel/localedata/ta_LK.dat deleted file mode 100644 index 482cab29ef..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ta_LK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ta_MY.dat b/awx/lib/site-packages/babel/localedata/ta_MY.dat deleted file mode 100644 index d3980d49fe..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ta_MY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ta_SG.dat b/awx/lib/site-packages/babel/localedata/ta_SG.dat deleted file mode 100644 index d2b3c0c963..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ta_SG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/te.dat b/awx/lib/site-packages/babel/localedata/te.dat deleted file mode 100644 index 82dde54f43..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/te.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/te_IN.dat b/awx/lib/site-packages/babel/localedata/te_IN.dat deleted file mode 100644 index 1564619c55..0000000000 --- a/awx/lib/site-packages/babel/localedata/te_IN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq }q!Ucurrency_namesq"}q#U unit_patternsq$}q%u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/teo.dat b/awx/lib/site-packages/babel/localedata/teo.dat deleted file mode 100644 index 15490c3aa6..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/teo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/teo_KE.dat b/awx/lib/site-packages/babel/localedata/teo_KE.dat deleted file mode 100644 index b126edd7f1..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/teo_KE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/teo_UG.dat b/awx/lib/site-packages/babel/localedata/teo_UG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/teo_UG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tg.dat b/awx/lib/site-packages/babel/localedata/tg.dat deleted file mode 100644 index 2ca7e3c87d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tg.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tg_Cyrl.dat b/awx/lib/site-packages/babel/localedata/tg_Cyrl.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tg_Cyrl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tg_Cyrl_TJ.dat b/awx/lib/site-packages/babel/localedata/tg_Cyrl_TJ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tg_Cyrl_TJ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/th.dat b/awx/lib/site-packages/babel/localedata/th.dat deleted file mode 100644 index e052aa592f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/th.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/th_TH.dat b/awx/lib/site-packages/babel/localedata/th_TH.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/th_TH.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/ti.dat b/awx/lib/site-packages/babel/localedata/ti.dat deleted file mode 100644 index b5ce842beb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ti.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ti_ER.dat b/awx/lib/site-packages/babel/localedata/ti_ER.dat deleted file mode 100644 index 1e2f1e3098..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ti_ER.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ti_ET.dat b/awx/lib/site-packages/babel/localedata/ti_ET.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ti_ET.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/tig.dat b/awx/lib/site-packages/babel/localedata/tig.dat deleted file mode 100644 index 8e82e8f613..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tig.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tig_ER.dat b/awx/lib/site-packages/babel/localedata/tig_ER.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tig_ER.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tn.dat b/awx/lib/site-packages/babel/localedata/tn.dat deleted file mode 100644 index d1a3042814..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tn_BW.dat b/awx/lib/site-packages/babel/localedata/tn_BW.dat deleted file mode 100644 index 325d2b09dd..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tn_BW.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tn_ZA.dat b/awx/lib/site-packages/babel/localedata/tn_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/tn_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/to.dat b/awx/lib/site-packages/babel/localedata/to.dat deleted file mode 100644 index 80c436141b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/to.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/to_TO.dat b/awx/lib/site-packages/babel/localedata/to_TO.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/to_TO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tr.dat b/awx/lib/site-packages/babel/localedata/tr.dat deleted file mode 100644 index 292d00717e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tr.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tr_CY.dat b/awx/lib/site-packages/babel/localedata/tr_CY.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tr_CY.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tr_TR.dat b/awx/lib/site-packages/babel/localedata/tr_TR.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tr_TR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ts.dat b/awx/lib/site-packages/babel/localedata/ts.dat deleted file mode 100644 index c24c9e40da..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ts.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ts_ZA.dat b/awx/lib/site-packages/babel/localedata/ts_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ts_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/twq.dat b/awx/lib/site-packages/babel/localedata/twq.dat deleted file mode 100644 index f9c3773a0a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/twq.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/twq_NE.dat b/awx/lib/site-packages/babel/localedata/twq_NE.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/twq_NE.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tzm.dat b/awx/lib/site-packages/babel/localedata/tzm.dat deleted file mode 100644 index 2543fb3902..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tzm.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tzm_Latn.dat b/awx/lib/site-packages/babel/localedata/tzm_Latn.dat deleted file mode 100644 index 500194c51b..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/tzm_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/tzm_Latn_MA.dat b/awx/lib/site-packages/babel/localedata/tzm_Latn_MA.dat deleted file mode 100644 index 01c29af978..0000000000 --- a/awx/lib/site-packages/babel/localedata/tzm_Latn_MA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/uk.dat b/awx/lib/site-packages/babel/localedata/uk.dat deleted file mode 100644 index 2ce73b767c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uk.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/uk_UA.dat b/awx/lib/site-packages/babel/localedata/uk_UA.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uk_UA.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ur.dat b/awx/lib/site-packages/babel/localedata/ur.dat deleted file mode 100644 index 325b54153f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ur.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ur_IN.dat b/awx/lib/site-packages/babel/localedata/ur_IN.dat deleted file mode 100644 index a8f52387cc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ur_IN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ur_PK.dat b/awx/lib/site-packages/babel/localedata/ur_PK.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/ur_PK.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/uz.dat b/awx/lib/site-packages/babel/localedata/uz.dat deleted file mode 100644 index 799049cf4c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uz.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/uz_Arab.dat b/awx/lib/site-packages/babel/localedata/uz_Arab.dat deleted file mode 100644 index 29426be7ae..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uz_Arab.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/uz_Arab_AF.dat b/awx/lib/site-packages/babel/localedata/uz_Arab_AF.dat deleted file mode 100644 index 150c7e3b45..0000000000 --- a/awx/lib/site-packages/babel/localedata/uz_Arab_AF.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (U weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}q Uvariantsq!}q"Ucurrency_namesq#}q$U unit_patternsq%}q&u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/uz_Cyrl.dat b/awx/lib/site-packages/babel/localedata/uz_Cyrl.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uz_Cyrl.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/uz_Cyrl_UZ.dat b/awx/lib/site-packages/babel/localedata/uz_Cyrl_UZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uz_Cyrl_UZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/uz_Latn.dat b/awx/lib/site-packages/babel/localedata/uz_Latn.dat deleted file mode 100644 index febdc7c34f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uz_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/uz_Latn_UZ.dat b/awx/lib/site-packages/babel/localedata/uz_Latn_UZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/uz_Latn_UZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vai.dat b/awx/lib/site-packages/babel/localedata/vai.dat deleted file mode 100644 index 8decb6febc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vai.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vai_Latn.dat b/awx/lib/site-packages/babel/localedata/vai_Latn.dat deleted file mode 100644 index 8b6be24045..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vai_Latn.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vai_Latn_LR.dat b/awx/lib/site-packages/babel/localedata/vai_Latn_LR.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vai_Latn_LR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vai_Vaii.dat b/awx/lib/site-packages/babel/localedata/vai_Vaii.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vai_Vaii.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vai_Vaii_LR.dat b/awx/lib/site-packages/babel/localedata/vai_Vaii_LR.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vai_Vaii_LR.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ve.dat b/awx/lib/site-packages/babel/localedata/ve.dat deleted file mode 100644 index a547fffa0a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/ve.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/ve_ZA.dat b/awx/lib/site-packages/babel/localedata/ve_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/ve_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/vi.dat b/awx/lib/site-packages/babel/localedata/vi.dat deleted file mode 100644 index 2c1eb2d9fc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vi.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vi_VN.dat b/awx/lib/site-packages/babel/localedata/vi_VN.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vi_VN.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vo.dat b/awx/lib/site-packages/babel/localedata/vo.dat deleted file mode 100644 index 979ea71ed5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vun.dat b/awx/lib/site-packages/babel/localedata/vun.dat deleted file mode 100644 index f023b1381a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vun.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/vun_TZ.dat b/awx/lib/site-packages/babel/localedata/vun_TZ.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/vun_TZ.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/wae.dat b/awx/lib/site-packages/babel/localedata/wae.dat deleted file mode 100644 index 98d0869e64..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/wae.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/wae_CH.dat b/awx/lib/site-packages/babel/localedata/wae_CH.dat deleted file mode 100644 index f981f10762..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/wae_CH.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/wal.dat b/awx/lib/site-packages/babel/localedata/wal.dat deleted file mode 100644 index 39a5a73b8d..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/wal.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/wal_ET.dat b/awx/lib/site-packages/babel/localedata/wal_ET.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/wal_ET.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/xh.dat b/awx/lib/site-packages/babel/localedata/xh.dat deleted file mode 100644 index 86f8bdc36f..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/xh.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/xh_ZA.dat b/awx/lib/site-packages/babel/localedata/xh_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/xh_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/xog.dat b/awx/lib/site-packages/babel/localedata/xog.dat deleted file mode 100644 index f660164e28..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/xog.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/xog_UG.dat b/awx/lib/site-packages/babel/localedata/xog_UG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/xog_UG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/yav.dat b/awx/lib/site-packages/babel/localedata/yav.dat deleted file mode 100644 index 43d7148f6a..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/yav.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/yav_CM.dat b/awx/lib/site-packages/babel/localedata/yav_CM.dat deleted file mode 100644 index 074603a416..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/yav_CM.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/yo.dat b/awx/lib/site-packages/babel/localedata/yo.dat deleted file mode 100644 index 46120718eb..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/yo.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/yo_NG.dat b/awx/lib/site-packages/babel/localedata/yo_NG.dat deleted file mode 100644 index 67b749dd3e..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/yo_NG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh.dat b/awx/lib/site-packages/babel/localedata/zh.dat deleted file mode 100644 index cb916a89ef..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hans.dat b/awx/lib/site-packages/babel/localedata/zh_Hans.dat deleted file mode 100644 index 980ab6b6fc..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh_Hans.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hans_CN.dat b/awx/lib/site-packages/babel/localedata/zh_Hans_CN.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/zh_Hans_CN.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/zh_Hans_HK.dat b/awx/lib/site-packages/babel/localedata/zh_Hans_HK.dat deleted file mode 100644 index 3d1a848434..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh_Hans_HK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hans_MO.dat b/awx/lib/site-packages/babel/localedata/zh_Hans_MO.dat deleted file mode 100644 index 7caa160409..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh_Hans_MO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hans_SG.dat b/awx/lib/site-packages/babel/localedata/zh_Hans_SG.dat deleted file mode 100644 index 7c57b7bf38..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh_Hans_SG.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hant.dat b/awx/lib/site-packages/babel/localedata/zh_Hant.dat deleted file mode 100644 index 6e093dd2b5..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh_Hant.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hant_HK.dat b/awx/lib/site-packages/babel/localedata/zh_Hant_HK.dat deleted file mode 100644 index f5a59a1eab..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh_Hant_HK.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hant_MO.dat b/awx/lib/site-packages/babel/localedata/zh_Hant_MO.dat deleted file mode 100644 index 7ce4ddc05c..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zh_Hant_MO.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zh_Hant_TW.dat b/awx/lib/site-packages/babel/localedata/zh_Hant_TW.dat deleted file mode 100644 index 81c8925439..0000000000 --- a/awx/lib/site-packages/babel/localedata/zh_Hant_TW.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q U first_dayqKsU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq}qUvariantsq}q Ucurrency_namesq!}q"U unit_patternsq#}q$u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localedata/zu.dat b/awx/lib/site-packages/babel/localedata/zu.dat deleted file mode 100644 index 99b984e830..0000000000 Binary files a/awx/lib/site-packages/babel/localedata/zu.dat and /dev/null differ diff --git a/awx/lib/site-packages/babel/localedata/zu_ZA.dat b/awx/lib/site-packages/babel/localedata/zu_ZA.dat deleted file mode 100644 index 356909133a..0000000000 --- a/awx/lib/site-packages/babel/localedata/zu_ZA.dat +++ /dev/null @@ -1,4 +0,0 @@ -€}q(Ucurrency_symbolsq}qUscientific_formatsq}qUpercent_formatsq}qUnumber_symbolsq}q Ucurrency_names_pluralq -}q U week_dataq }q (Umin_daysqKU weekend_startqKU first_dayqKU weekend_endqKuU zone_formatsq}qUcurrency_formatsq}qU_versionqM5 U languagesq}qU territoriesq}U -time_zonesq}qUscriptsq}qUdecimal_formatsq}qU -meta_zonesq }q!Uvariantsq"}q#Ucurrency_namesq$}q%U unit_patternsq&}q'u. \ No newline at end of file diff --git a/awx/lib/site-packages/babel/localtime/__init__.py b/awx/lib/site-packages/babel/localtime/__init__.py deleted file mode 100644 index cdb3e9b5d5..0000000000 --- a/awx/lib/site-packages/babel/localtime/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.localtime - ~~~~~~~~~~~~~~~ - - Babel specific fork of tzlocal to determine the local timezone - of the system. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import sys -import pytz -import time -from datetime import timedelta, datetime -from datetime import tzinfo -from threading import RLock - -if sys.platform == 'win32': - from babel.localtime._win32 import _get_localzone -else: - from babel.localtime._unix import _get_localzone - - -_cached_tz = None -_cache_lock = RLock() - -STDOFFSET = timedelta(seconds = -time.timezone) -if time.daylight: - DSTOFFSET = timedelta(seconds = -time.altzone) -else: - DSTOFFSET = STDOFFSET - -DSTDIFF = DSTOFFSET - STDOFFSET -ZERO = timedelta(0) - - -class _FallbackLocalTimezone(tzinfo): - - def utcoffset(self, dt): - if self._isdst(dt): - return DSTOFFSET - else: - return STDOFFSET - - def dst(self, dt): - if self._isdst(dt): - return DSTDIFF - else: - return ZERO - - def tzname(self, dt): - return time.tzname[self._isdst(dt)] - - def _isdst(self, dt): - tt = (dt.year, dt.month, dt.day, - dt.hour, dt.minute, dt.second, - dt.weekday(), 0, -1) - stamp = time.mktime(tt) - tt = time.localtime(stamp) - return tt.tm_isdst > 0 - - -def get_localzone(): - """Returns the current underlying local timezone object. - Generally this function does not need to be used, it's a - better idea to use the :data:`LOCALTZ` singleton instead. - """ - return _get_localzone() - - -try: - LOCALTZ = get_localzone() -except pytz.UnknownTimeZoneError: - LOCALTZ = _FallbackLocalTimezone() diff --git a/awx/lib/site-packages/babel/localtime/_unix.py b/awx/lib/site-packages/babel/localtime/_unix.py deleted file mode 100644 index b4a3b599f0..0000000000 --- a/awx/lib/site-packages/babel/localtime/_unix.py +++ /dev/null @@ -1,137 +0,0 @@ -from __future__ import with_statement -import os -import re -import sys -import pytz -import subprocess - -_systemconfig_tz = re.compile(r'^Time Zone: (.*)$(?m)') - - -def _tz_from_env(tzenv): - if tzenv[0] == ':': - tzenv = tzenv[1:] - - # TZ specifies a file - if os.path.exists(tzenv): - with open(tzenv, 'rb') as tzfile: - return pytz.tzfile.build_tzinfo('local', tzfile) - - # TZ specifies a zoneinfo zone. - try: - tz = pytz.timezone(tzenv) - # That worked, so we return this: - return tz - except pytz.UnknownTimeZoneError: - raise pytz.UnknownTimeZoneError( - "tzlocal() does not support non-zoneinfo timezones like %s. \n" - "Please use a timezone in the form of Continent/City") - -def _get_localzone(_root='/'): - """Tries to find the local timezone configuration. - This method prefers finding the timezone name and passing that to pytz, - over passing in the localtime file, as in the later case the zoneinfo - name is unknown. - The parameter _root makes the function look for files like /etc/localtime - beneath the _root directory. This is primarily used by the tests. - In normal usage you call the function without parameters. - """ - - tzenv = os.environ.get('TZ') - if tzenv: - return _tz_from_env(tzenv) - - # This is actually a pretty reliable way to test for the local time - # zone on operating systems like OS X. On OS X especially this is the - # only one that actually works. - try: - link_dst = os.readlink('/etc/localtime') - except OSError: - pass - else: - pos = link_dst.find('/zoneinfo/') - if pos >= 0: - zone_name = link_dst[pos + 10:] - try: - return pytz.timezone(zone_name) - except pytz.UnknownTimeZoneError: - pass - - # If we are on OS X now we are pretty sure that the rest of the - # code will fail and just fall through until it hits the reading - # of /etc/localtime and using it without name. At this point we - # can invoke systemconfig which internally invokes ICU. ICU itself - # does the same thing we do (readlink + compare file contents) but - # since it knows where the zone files are that should be a bit - # better than reimplementing the logic here. - if sys.platform == 'darwin': - c = subprocess.Popen(['systemsetup', '-gettimezone'], - stdout=subprocess.PIPE) - sys_result = c.communicate()[0] - c.wait() - tz_match = _systemconfig_tz.search(sys_result) - if tz_match is not None: - zone_name = tz_match.group(1) - try: - return pytz.timezone(zone_name) - except pytz.UnknownTimeZoneError: - pass - - # Now look for distribution specific configuration files - # that contain the timezone name. - tzpath = os.path.join(_root, 'etc/timezone') - if os.path.exists(tzpath): - with open(tzpath, 'rb') as tzfile: - data = tzfile.read() - - # Issue #3 in tzlocal was that /etc/timezone was a zoneinfo file. - # That's a misconfiguration, but we need to handle it gracefully: - if data[:5] != 'TZif2': - etctz = data.strip().decode() - # Get rid of host definitions and comments: - if ' ' in etctz: - etctz, dummy = etctz.split(' ', 1) - if '#' in etctz: - etctz, dummy = etctz.split('#', 1) - return pytz.timezone(etctz.replace(' ', '_')) - - # CentOS has a ZONE setting in /etc/sysconfig/clock, - # OpenSUSE has a TIMEZONE setting in /etc/sysconfig/clock and - # Gentoo has a TIMEZONE setting in /etc/conf.d/clock - # We look through these files for a timezone: - zone_re = re.compile('\s*ZONE\s*=\s*\"') - timezone_re = re.compile('\s*TIMEZONE\s*=\s*\"') - end_re = re.compile('\"') - - for filename in ('etc/sysconfig/clock', 'etc/conf.d/clock'): - tzpath = os.path.join(_root, filename) - if not os.path.exists(tzpath): - continue - with open(tzpath, 'rt') as tzfile: - data = tzfile.readlines() - - for line in data: - # Look for the ZONE= setting. - match = zone_re.match(line) - if match is None: - # No ZONE= setting. Look for the TIMEZONE= setting. - match = timezone_re.match(line) - if match is not None: - # Some setting existed - line = line[match.end():] - etctz = line[:end_re.search(line).start()] - - # We found a timezone - return pytz.timezone(etctz.replace(' ', '_')) - - # No explicit setting existed. Use localtime - for filename in ('etc/localtime', 'usr/local/etc/localtime'): - tzpath = os.path.join(_root, filename) - - if not os.path.exists(tzpath): - continue - - with open(tzpath, 'rb') as tzfile: - return pytz.tzfile.build_tzinfo('local', tzfile) - - raise pytz.UnknownTimeZoneError('Can not find any timezone configuration') diff --git a/awx/lib/site-packages/babel/localtime/_win32.py b/awx/lib/site-packages/babel/localtime/_win32.py deleted file mode 100644 index 1f6ecc7c0d..0000000000 --- a/awx/lib/site-packages/babel/localtime/_win32.py +++ /dev/null @@ -1,89 +0,0 @@ -try: - import _winreg as winreg -except ImportError: - try: - import winreg - except ImportError: - winreg = None - -from babel.core import get_global -import pytz - - -tz_names = get_global('windows_zone_mapping') - - -def valuestodict(key): - """Convert a registry key's values to a dictionary.""" - dict = {} - size = winreg.QueryInfoKey(key)[1] - for i in range(size): - data = winreg.EnumValue(key, i) - dict[data[0]] = data[1] - return dict - - -def get_localzone_name(): - # Windows is special. It has unique time zone names (in several - # meanings of the word) available, but unfortunately, they can be - # translated to the language of the operating system, so we need to - # do a backwards lookup, by going through all time zones and see which - # one matches. - handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - - TZLOCALKEYNAME = r'SYSTEM\CurrentControlSet\Control\TimeZoneInformation' - localtz = winreg.OpenKey(handle, TZLOCALKEYNAME) - keyvalues = valuestodict(localtz) - localtz.Close() - if 'TimeZoneKeyName' in keyvalues: - # Windows 7 (and Vista?) - - # For some reason this returns a string with loads of NUL bytes at - # least on some systems. I don't know if this is a bug somewhere, I - # just work around it. - tzkeyname = keyvalues['TimeZoneKeyName'].split('\x00', 1)[0] - else: - # Windows 2000 or XP - - # This is the localized name: - tzwin = keyvalues['StandardName'] - - # Open the list of timezones to look up the real name: - TZKEYNAME = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones' - tzkey = winreg.OpenKey(handle, TZKEYNAME) - - # Now, match this value to Time Zone information - tzkeyname = None - for i in range(winreg.QueryInfoKey(tzkey)[0]): - subkey = winreg.EnumKey(tzkey, i) - sub = winreg.OpenKey(tzkey, subkey) - data = valuestodict(sub) - sub.Close() - if data['Std'] == tzwin: - tzkeyname = subkey - break - - tzkey.Close() - handle.Close() - - if tzkeyname is None: - raise LookupError('Can not find Windows timezone configuration') - - timezone = tz_names.get(tzkeyname) - if timezone is None: - # Nope, that didn't work. Try adding 'Standard Time', - # it seems to work a lot of times: - timezone = tz_names.get(tzkeyname + ' Standard Time') - - # Return what we have. - if timezone is None: - raise pytz.UnknownTimeZoneError('Can not find timezone ' + tzkeyname) - - return timezone - - -def _get_localzone(): - if winreg is None: - raise pytz.UnknownTimeZoneError( - 'Runtime support not available') - return pytz.timezone(get_localzone_name()) diff --git a/awx/lib/site-packages/babel/messages/__init__.py b/awx/lib/site-packages/babel/messages/__init__.py deleted file mode 100644 index 1b63bae2ee..0000000000 --- a/awx/lib/site-packages/babel/messages/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages - ~~~~~~~~~~~~~~ - - Support for ``gettext`` message catalogs. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -from babel.messages.catalog import * diff --git a/awx/lib/site-packages/babel/messages/catalog.py b/awx/lib/site-packages/babel/messages/catalog.py deleted file mode 100644 index 501763b584..0000000000 --- a/awx/lib/site-packages/babel/messages/catalog.py +++ /dev/null @@ -1,831 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.catalog - ~~~~~~~~~~~~~~~~~~~~~~ - - Data structures for message catalogs. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import re -import time - -from cgi import parse_header -from datetime import datetime, time as time_ -from difflib import get_close_matches -from email import message_from_string -from copy import copy - -from babel import __version__ as VERSION -from babel.core import Locale -from babel.dates import format_datetime -from babel.messages.plurals import get_plural -from babel.util import odict, distinct, LOCALTZ, FixedOffsetTimezone -from babel._compat import string_types, number_types, PY2, cmp - -__all__ = ['Message', 'Catalog', 'TranslationError'] - - -PYTHON_FORMAT = re.compile(r'''(?x) - \% - (?:\(([\w]*)\))? - ( - [-#0\ +]?(?:\*|[\d]+)? - (?:\.(?:\*|[\d]+))? - [hlL]? - ) - ([diouxXeEfFgGcrs%]) -''') - - -class Message(object): - """Representation of a single message in a catalog.""" - - def __init__(self, id, string=u'', locations=(), flags=(), auto_comments=(), - user_comments=(), previous_id=(), lineno=None, context=None): - """Create the message object. - - :param id: the message ID, or a ``(singular, plural)`` tuple for - pluralizable messages - :param string: the translated message string, or a - ``(singular, plural)`` tuple for pluralizable messages - :param locations: a sequence of ``(filenname, lineno)`` tuples - :param flags: a set or sequence of flags - :param auto_comments: a sequence of automatic comments for the message - :param user_comments: a sequence of user comments for the message - :param previous_id: the previous message ID, or a ``(singular, plural)`` - tuple for pluralizable messages - :param lineno: the line number on which the msgid line was found in the - PO file, if any - :param context: the message context - """ - self.id = id #: The message ID - if not string and self.pluralizable: - string = (u'', u'') - self.string = string #: The message translation - self.locations = list(distinct(locations)) - self.flags = set(flags) - if id and self.python_format: - self.flags.add('python-format') - else: - self.flags.discard('python-format') - self.auto_comments = list(distinct(auto_comments)) - self.user_comments = list(distinct(user_comments)) - if isinstance(previous_id, string_types): - self.previous_id = [previous_id] - else: - self.previous_id = list(previous_id) - self.lineno = lineno - self.context = context - - def __repr__(self): - return '<%s %r (flags: %r)>' % (type(self).__name__, self.id, - list(self.flags)) - - def __cmp__(self, obj): - """Compare Messages, taking into account plural ids""" - def values_to_compare(): - if isinstance(obj, Message): - plural = self.pluralizable - obj_plural = obj.pluralizable - if plural and obj_plural: - return self.id[0], obj.id[0] - elif plural: - return self.id[0], obj.id - elif obj_plural: - return self.id, obj.id[0] - return self.id, obj.id - this, other = values_to_compare() - return cmp(this, other) - - def __gt__(self, other): - return self.__cmp__(other) > 0 - - def __lt__(self, other): - return self.__cmp__(other) < 0 - - def __ge__(self, other): - return self.__cmp__(other) >= 0 - - def __le__(self, other): - return self.__cmp__(other) <= 0 - - def __eq__(self, other): - return self.__cmp__(other) == 0 - - def __ne__(self, other): - return self.__cmp__(other) != 0 - - def clone(self): - return Message(*map(copy, (self.id, self.string, self.locations, - self.flags, self.auto_comments, - self.user_comments, self.previous_id, - self.lineno, self.context))) - - def check(self, catalog=None): - """Run various validation checks on the message. Some validations - are only performed if the catalog is provided. This method returns - a sequence of `TranslationError` objects. - - :rtype: ``iterator`` - :param catalog: A catalog instance that is passed to the checkers - :see: `Catalog.check` for a way to perform checks for all messages - in a catalog. - """ - from babel.messages.checkers import checkers - errors = [] - for checker in checkers: - try: - checker(catalog, self) - except TranslationError as e: - errors.append(e) - return errors - - @property - def fuzzy(self): - """Whether the translation is fuzzy. - - >>> Message('foo').fuzzy - False - >>> msg = Message('foo', 'foo', flags=['fuzzy']) - >>> msg.fuzzy - True - >>> msg - <Message 'foo' (flags: ['fuzzy'])> - - :type: `bool`""" - return 'fuzzy' in self.flags - - @property - def pluralizable(self): - """Whether the message is plurizable. - - >>> Message('foo').pluralizable - False - >>> Message(('foo', 'bar')).pluralizable - True - - :type: `bool`""" - return isinstance(self.id, (list, tuple)) - - @property - def python_format(self): - """Whether the message contains Python-style parameters. - - >>> Message('foo %(name)s bar').python_format - True - >>> Message(('foo %(name)s', 'foo %(name)s')).python_format - True - - :type: `bool`""" - ids = self.id - if not isinstance(ids, (list, tuple)): - ids = [ids] - return any(PYTHON_FORMAT.search(id) for id in ids) - - -class TranslationError(Exception): - """Exception thrown by translation checkers when invalid message - translations are encountered.""" - - -DEFAULT_HEADER = u"""\ -# Translations template for PROJECT. -# Copyright (C) YEAR ORGANIZATION -# This file is distributed under the same license as the PROJECT project. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -#""" - - -if PY2: - def _parse_header(header_string): - # message_from_string only works for str, not for unicode - headers = message_from_string(header_string.encode('utf8')) - decoded_headers = {} - for name, value in headers.items(): - name = name.decode('utf8') - value = value.decode('utf8') - decoded_headers[name] = value - return decoded_headers - -else: - _parse_header = message_from_string - - -class Catalog(object): - """Representation of a message catalog.""" - - def __init__(self, locale=None, domain=None, header_comment=DEFAULT_HEADER, - project=None, version=None, copyright_holder=None, - msgid_bugs_address=None, creation_date=None, - revision_date=None, last_translator=None, language_team=None, - charset=None, fuzzy=True): - """Initialize the catalog object. - - :param locale: the locale identifier or `Locale` object, or `None` - if the catalog is not bound to a locale (which basically - means it's a template) - :param domain: the message domain - :param header_comment: the header comment as string, or `None` for the - default header - :param project: the project's name - :param version: the project's version - :param copyright_holder: the copyright holder of the catalog - :param msgid_bugs_address: the email address or URL to submit bug - reports to - :param creation_date: the date the catalog was created - :param revision_date: the date the catalog was revised - :param last_translator: the name and email of the last translator - :param language_team: the name and email of the language team - :param charset: the encoding to use in the output (defaults to utf-8) - :param fuzzy: the fuzzy bit on the catalog header - """ - self.domain = domain #: The message domain - if locale: - locale = Locale.parse(locale) - self.locale = locale #: The locale or `None` - self._header_comment = header_comment - self._messages = odict() - - self.project = project or 'PROJECT' #: The project name - self.version = version or 'VERSION' #: The project version - self.copyright_holder = copyright_holder or 'ORGANIZATION' - self.msgid_bugs_address = msgid_bugs_address or 'EMAIL@ADDRESS' - - self.last_translator = last_translator or 'FULL NAME <EMAIL@ADDRESS>' - """Name and email address of the last translator.""" - self.language_team = language_team or 'LANGUAGE <LL@li.org>' - """Name and email address of the language team.""" - - self.charset = charset or 'utf-8' - - if creation_date is None: - creation_date = datetime.now(LOCALTZ) - elif isinstance(creation_date, datetime) and not creation_date.tzinfo: - creation_date = creation_date.replace(tzinfo=LOCALTZ) - self.creation_date = creation_date #: Creation date of the template - if revision_date is None: - revision_date = 'YEAR-MO-DA HO:MI+ZONE' - elif isinstance(revision_date, datetime) and not revision_date.tzinfo: - revision_date = revision_date.replace(tzinfo=LOCALTZ) - self.revision_date = revision_date #: Last revision date of the catalog - self.fuzzy = fuzzy #: Catalog header fuzzy bit (`True` or `False`) - - self.obsolete = odict() #: Dictionary of obsolete messages - self._num_plurals = None - self._plural_expr = None - - def _get_header_comment(self): - comment = self._header_comment - year = datetime.now(LOCALTZ).strftime('%Y') - if hasattr(self.revision_date, 'strftime'): - year = self.revision_date.strftime('%Y') - comment = comment.replace('PROJECT', self.project) \ - .replace('VERSION', self.version) \ - .replace('YEAR', year) \ - .replace('ORGANIZATION', self.copyright_holder) - if self.locale: - comment = comment.replace('Translations template', '%s translations' - % self.locale.english_name) - return comment - - def _set_header_comment(self, string): - self._header_comment = string - - header_comment = property(_get_header_comment, _set_header_comment, doc="""\ - The header comment for the catalog. - - >>> catalog = Catalog(project='Foobar', version='1.0', - ... copyright_holder='Foo Company') - >>> print catalog.header_comment #doctest: +ELLIPSIS - # Translations template for Foobar. - # Copyright (C) ... Foo Company - # This file is distributed under the same license as the Foobar project. - # FIRST AUTHOR <EMAIL@ADDRESS>, .... - # - - The header can also be set from a string. Any known upper-case variables - will be replaced when the header is retrieved again: - - >>> catalog = Catalog(project='Foobar', version='1.0', - ... copyright_holder='Foo Company') - >>> catalog.header_comment = '''\\ - ... # The POT for my really cool PROJECT project. - ... # Copyright (C) 1990-2003 ORGANIZATION - ... # This file is distributed under the same license as the PROJECT - ... # project. - ... #''' - >>> print catalog.header_comment - # The POT for my really cool Foobar project. - # Copyright (C) 1990-2003 Foo Company - # This file is distributed under the same license as the Foobar - # project. - # - - :type: `unicode` - """) - - def _get_mime_headers(self): - headers = [] - headers.append(('Project-Id-Version', - '%s %s' % (self.project, self.version))) - headers.append(('Report-Msgid-Bugs-To', self.msgid_bugs_address)) - headers.append(('POT-Creation-Date', - format_datetime(self.creation_date, 'yyyy-MM-dd HH:mmZ', - locale='en'))) - if isinstance(self.revision_date, (datetime, time_) + number_types): - headers.append(('PO-Revision-Date', - format_datetime(self.revision_date, - 'yyyy-MM-dd HH:mmZ', locale='en'))) - else: - headers.append(('PO-Revision-Date', self.revision_date)) - headers.append(('Last-Translator', self.last_translator)) - if (self.locale is not None) and ('LANGUAGE' in self.language_team): - headers.append(('Language-Team', - self.language_team.replace('LANGUAGE', - str(self.locale)))) - else: - headers.append(('Language-Team', self.language_team)) - if self.locale is not None: - headers.append(('Plural-Forms', self.plural_forms)) - headers.append(('MIME-Version', '1.0')) - headers.append(('Content-Type', - 'text/plain; charset=%s' % self.charset)) - headers.append(('Content-Transfer-Encoding', '8bit')) - headers.append(('Generated-By', 'Babel %s\n' % VERSION)) - return headers - - def _set_mime_headers(self, headers): - for name, value in headers: - name = name.lower() - if name == 'project-id-version': - parts = value.split(' ') - self.project = u' '.join(parts[:-1]) - self.version = parts[-1] - elif name == 'report-msgid-bugs-to': - self.msgid_bugs_address = value - elif name == 'last-translator': - self.last_translator = value - elif name == 'language-team': - self.language_team = value - elif name == 'content-type': - mimetype, params = parse_header(value) - if 'charset' in params: - self.charset = params['charset'].lower() - elif name == 'plural-forms': - _, params = parse_header(' ;' + value) - self._num_plurals = int(params.get('nplurals', 2)) - self._plural_expr = params.get('plural', '(n != 1)') - elif name == 'pot-creation-date': - # FIXME: this should use dates.parse_datetime as soon as that - # is ready - value, tzoffset, _ = re.split('([+-]\d{4})$', value, 1) - - tt = time.strptime(value, '%Y-%m-%d %H:%M') - ts = time.mktime(tt) - - # Separate the offset into a sign component, hours, and minutes - plus_minus_s, rest = tzoffset[0], tzoffset[1:] - hours_offset_s, mins_offset_s = rest[:2], rest[2:] - - # Make them all integers - plus_minus = int(plus_minus_s + '1') - hours_offset = int(hours_offset_s) - mins_offset = int(mins_offset_s) - - # Calculate net offset - net_mins_offset = hours_offset * 60 - net_mins_offset += mins_offset - net_mins_offset *= plus_minus - - # Create an offset object - tzoffset = FixedOffsetTimezone(net_mins_offset) - - # Store the offset in a datetime object - dt = datetime.fromtimestamp(ts) - self.creation_date = dt.replace(tzinfo=tzoffset) - elif name == 'po-revision-date': - # Keep the value if it's not the default one - if 'YEAR' not in value: - # FIXME: this should use dates.parse_datetime as soon as - # that is ready - value, tzoffset, _ = re.split('([+-]\d{4})$', value, 1) - tt = time.strptime(value, '%Y-%m-%d %H:%M') - ts = time.mktime(tt) - - # Separate the offset into a sign component, hours, and - # minutes - plus_minus_s, rest = tzoffset[0], tzoffset[1:] - hours_offset_s, mins_offset_s = rest[:2], rest[2:] - - # Make them all integers - plus_minus = int(plus_minus_s + '1') - hours_offset = int(hours_offset_s) - mins_offset = int(mins_offset_s) - - # Calculate net offset - net_mins_offset = hours_offset * 60 - net_mins_offset += mins_offset - net_mins_offset *= plus_minus - - # Create an offset object - tzoffset = FixedOffsetTimezone(net_mins_offset) - - # Store the offset in a datetime object - dt = datetime.fromtimestamp(ts) - self.revision_date = dt.replace(tzinfo=tzoffset) - - mime_headers = property(_get_mime_headers, _set_mime_headers, doc="""\ - The MIME headers of the catalog, used for the special ``msgid ""`` entry. - - The behavior of this property changes slightly depending on whether a locale - is set or not, the latter indicating that the catalog is actually a template - for actual translations. - - Here's an example of the output for such a catalog template: - - >>> from babel.dates import UTC - >>> created = datetime(1990, 4, 1, 15, 30, tzinfo=UTC) - >>> catalog = Catalog(project='Foobar', version='1.0', - ... creation_date=created) - >>> for name, value in catalog.mime_headers: - ... print '%s: %s' % (name, value) - Project-Id-Version: Foobar 1.0 - Report-Msgid-Bugs-To: EMAIL@ADDRESS - POT-Creation-Date: 1990-04-01 15:30+0000 - PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE - Last-Translator: FULL NAME <EMAIL@ADDRESS> - Language-Team: LANGUAGE <LL@li.org> - MIME-Version: 1.0 - Content-Type: text/plain; charset=utf-8 - Content-Transfer-Encoding: 8bit - Generated-By: Babel ... - - And here's an example of the output when the locale is set: - - >>> revised = datetime(1990, 8, 3, 12, 0, tzinfo=UTC) - >>> catalog = Catalog(locale='de_DE', project='Foobar', version='1.0', - ... creation_date=created, revision_date=revised, - ... last_translator='John Doe <jd@example.com>', - ... language_team='de_DE <de@example.com>') - >>> for name, value in catalog.mime_headers: - ... print '%s: %s' % (name, value) - Project-Id-Version: Foobar 1.0 - Report-Msgid-Bugs-To: EMAIL@ADDRESS - POT-Creation-Date: 1990-04-01 15:30+0000 - PO-Revision-Date: 1990-08-03 12:00+0000 - Last-Translator: John Doe <jd@example.com> - Language-Team: de_DE <de@example.com> - Plural-Forms: nplurals=2; plural=(n != 1) - MIME-Version: 1.0 - Content-Type: text/plain; charset=utf-8 - Content-Transfer-Encoding: 8bit - Generated-By: Babel ... - - :type: `list` - """) - - @property - def num_plurals(self): - """The number of plurals used by the catalog or locale. - - >>> Catalog(locale='en').num_plurals - 2 - >>> Catalog(locale='ga').num_plurals - 3 - - :type: `int`""" - if self._num_plurals is None: - num = 2 - if self.locale: - num = get_plural(self.locale)[0] - self._num_plurals = num - return self._num_plurals - - @property - def plural_expr(self): - """The plural expression used by the catalog or locale. - - >>> Catalog(locale='en').plural_expr - '(n != 1)' - >>> Catalog(locale='ga').plural_expr - '(n==1 ? 0 : n==2 ? 1 : 2)' - - :type: `string_types`""" - if self._plural_expr is None: - expr = '(n != 1)' - if self.locale: - expr = get_plural(self.locale)[1] - self._plural_expr = expr - return self._plural_expr - - @property - def plural_forms(self): - """Return the plural forms declaration for the locale. - - >>> Catalog(locale='en').plural_forms - 'nplurals=2; plural=(n != 1)' - >>> Catalog(locale='pt_BR').plural_forms - 'nplurals=2; plural=(n > 1)' - - :type: `str`""" - return 'nplurals=%s; plural=%s' % (self.num_plurals, self.plural_expr) - - def __contains__(self, id): - """Return whether the catalog has a message with the specified ID.""" - return self._key_for(id) in self._messages - - def __len__(self): - """The number of messages in the catalog. - - This does not include the special ``msgid ""`` entry.""" - return len(self._messages) - - def __iter__(self): - """Iterates through all the entries in the catalog, in the order they - were added, yielding a `Message` object for every entry. - - :rtype: ``iterator``""" - buf = [] - for name, value in self.mime_headers: - buf.append('%s: %s' % (name, value)) - flags = set() - if self.fuzzy: - flags |= set(['fuzzy']) - yield Message(u'', '\n'.join(buf), flags=flags) - for key in self._messages: - yield self._messages[key] - - def __repr__(self): - locale = '' - if self.locale: - locale = ' %s' % self.locale - return '<%s %r%s>' % (type(self).__name__, self.domain, locale) - - def __delitem__(self, id): - """Delete the message with the specified ID.""" - self.delete(id) - - def __getitem__(self, id): - """Return the message with the specified ID. - - :param id: the message ID - """ - return self.get(id) - - def __setitem__(self, id, message): - """Add or update the message with the specified ID. - - >>> catalog = Catalog() - >>> catalog[u'foo'] = Message(u'foo') - >>> catalog[u'foo'] - <Message u'foo' (flags: [])> - - If a message with that ID is already in the catalog, it is updated - to include the locations and flags of the new message. - - >>> catalog = Catalog() - >>> catalog[u'foo'] = Message(u'foo', locations=[('main.py', 1)]) - >>> catalog[u'foo'].locations - [('main.py', 1)] - >>> catalog[u'foo'] = Message(u'foo', locations=[('utils.py', 5)]) - >>> catalog[u'foo'].locations - [('main.py', 1), ('utils.py', 5)] - - :param id: the message ID - :param message: the `Message` object - """ - assert isinstance(message, Message), 'expected a Message object' - key = self._key_for(id, message.context) - current = self._messages.get(key) - if current: - if message.pluralizable and not current.pluralizable: - # The new message adds pluralization - current.id = message.id - current.string = message.string - current.locations = list(distinct(current.locations + - message.locations)) - current.auto_comments = list(distinct(current.auto_comments + - message.auto_comments)) - current.user_comments = list(distinct(current.user_comments + - message.user_comments)) - current.flags |= message.flags - message = current - elif id == '': - # special treatment for the header message - self.mime_headers = _parse_header(message.string).items() - self.header_comment = '\n'.join([('# %s' % c).rstrip() for c - in message.user_comments]) - self.fuzzy = message.fuzzy - else: - if isinstance(id, (list, tuple)): - assert isinstance(message.string, (list, tuple)), \ - 'Expected sequence but got %s' % type(message.string) - self._messages[key] = message - - def add(self, id, string=None, locations=(), flags=(), auto_comments=(), - user_comments=(), previous_id=(), lineno=None, context=None): - """Add or update the message with the specified ID. - - >>> catalog = Catalog() - >>> catalog.add(u'foo') - <Message ...> - >>> catalog[u'foo'] - <Message u'foo' (flags: [])> - - This method simply constructs a `Message` object with the given - arguments and invokes `__setitem__` with that object. - - :param id: the message ID, or a ``(singular, plural)`` tuple for - pluralizable messages - :param string: the translated message string, or a - ``(singular, plural)`` tuple for pluralizable messages - :param locations: a sequence of ``(filenname, lineno)`` tuples - :param flags: a set or sequence of flags - :param auto_comments: a sequence of automatic comments - :param user_comments: a sequence of user comments - :param previous_id: the previous message ID, or a ``(singular, plural)`` - tuple for pluralizable messages - :param lineno: the line number on which the msgid line was found in the - PO file, if any - :param context: the message context - """ - message = Message(id, string, list(locations), flags, auto_comments, - user_comments, previous_id, lineno=lineno, - context=context) - self[id] = message - return message - - def check(self): - """Run various validation checks on the translations in the catalog. - - For every message which fails validation, this method yield a - ``(message, errors)`` tuple, where ``message`` is the `Message` object - and ``errors`` is a sequence of `TranslationError` objects. - - :rtype: ``iterator`` - """ - for message in self._messages.values(): - errors = message.check(catalog=self) - if errors: - yield message, errors - - def get(self, id, context=None): - """Return the message with the specified ID and context. - - :param id: the message ID - :param context: the message context, or ``None`` for no context - """ - return self._messages.get(self._key_for(id, context)) - - def delete(self, id, context=None): - """Delete the message with the specified ID and context. - - :param id: the message ID - :param context: the message context, or ``None`` for no context - """ - key = self._key_for(id, context) - if key in self._messages: - del self._messages[key] - - def update(self, template, no_fuzzy_matching=False): - """Update the catalog based on the given template catalog. - - >>> from babel.messages import Catalog - >>> template = Catalog() - >>> template.add('green', locations=[('main.py', 99)]) - <Message ...> - >>> template.add('blue', locations=[('main.py', 100)]) - <Message ...> - >>> template.add(('salad', 'salads'), locations=[('util.py', 42)]) - <Message ...> - >>> catalog = Catalog(locale='de_DE') - >>> catalog.add('blue', u'blau', locations=[('main.py', 98)]) - <Message ...> - >>> catalog.add('head', u'Kopf', locations=[('util.py', 33)]) - <Message ...> - >>> catalog.add(('salad', 'salads'), (u'Salat', u'Salate'), - ... locations=[('util.py', 38)]) - <Message ...> - - >>> catalog.update(template) - >>> len(catalog) - 3 - - >>> msg1 = catalog['green'] - >>> msg1.string - >>> msg1.locations - [('main.py', 99)] - - >>> msg2 = catalog['blue'] - >>> msg2.string - u'blau' - >>> msg2.locations - [('main.py', 100)] - - >>> msg3 = catalog['salad'] - >>> msg3.string - (u'Salat', u'Salate') - >>> msg3.locations - [('util.py', 42)] - - Messages that are in the catalog but not in the template are removed - from the main collection, but can still be accessed via the `obsolete` - member: - - >>> 'head' in catalog - False - >>> catalog.obsolete.values() - [<Message 'head' (flags: [])>] - - :param template: the reference catalog, usually read from a POT file - :param no_fuzzy_matching: whether to use fuzzy matching of message IDs - """ - messages = self._messages - remaining = messages.copy() - self._messages = odict() - - # Prepare for fuzzy matching - fuzzy_candidates = [] - if not no_fuzzy_matching: - fuzzy_candidates = dict([ - (self._key_for(msgid), messages[msgid].context) - for msgid in messages if msgid and messages[msgid].string - ]) - fuzzy_matches = set() - - def _merge(message, oldkey, newkey): - message = message.clone() - fuzzy = False - if oldkey != newkey: - fuzzy = True - fuzzy_matches.add(oldkey) - oldmsg = messages.get(oldkey) - if isinstance(oldmsg.id, string_types): - message.previous_id = [oldmsg.id] - else: - message.previous_id = list(oldmsg.id) - else: - oldmsg = remaining.pop(oldkey, None) - message.string = oldmsg.string - if isinstance(message.id, (list, tuple)): - if not isinstance(message.string, (list, tuple)): - fuzzy = True - message.string = tuple( - [message.string] + ([u''] * (len(message.id) - 1)) - ) - elif len(message.string) != self.num_plurals: - fuzzy = True - message.string = tuple(message.string[:len(oldmsg.string)]) - elif isinstance(message.string, (list, tuple)): - fuzzy = True - message.string = message.string[0] - message.flags |= oldmsg.flags - if fuzzy: - message.flags |= set([u'fuzzy']) - self[message.id] = message - - for message in template: - if message.id: - key = self._key_for(message.id, message.context) - if key in messages: - _merge(message, key, key) - else: - if no_fuzzy_matching is False: - # do some fuzzy matching with difflib - if isinstance(key, tuple): - matchkey = key[0] # just the msgid, no context - else: - matchkey = key - matches = get_close_matches(matchkey.lower().strip(), - fuzzy_candidates.keys(), 1) - if matches: - newkey = matches[0] - newctxt = fuzzy_candidates[newkey] - if newctxt is not None: - newkey = newkey, newctxt - _merge(message, newkey, key) - continue - - self[message.id] = message - - for msgid in remaining: - if no_fuzzy_matching or msgid not in fuzzy_matches: - self.obsolete[msgid] = remaining[msgid] - # Make updated catalog's POT-Creation-Date equal to the template - # used to update the catalog - self.creation_date = template.creation_date - - def _key_for(self, id, context=None): - """The key for a message is just the singular ID even for pluralizable - messages, but is a ``(msgid, msgctxt)`` tuple for context-specific - messages. - """ - key = id - if isinstance(key, (list, tuple)): - key = id[0] - if context is not None: - key = (key, context) - return key diff --git a/awx/lib/site-packages/babel/messages/checkers.py b/awx/lib/site-packages/babel/messages/checkers.py deleted file mode 100644 index 24ecdcfedb..0000000000 --- a/awx/lib/site-packages/babel/messages/checkers.py +++ /dev/null @@ -1,173 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.checkers - ~~~~~~~~~~~~~~~~~~~~~~~ - - Various routines that help with validation of translations. - - :since: version 0.9 - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -from babel.messages.catalog import TranslationError, PYTHON_FORMAT -from babel._compat import string_types, izip - - -#: list of format chars that are compatible to each other -_string_format_compatibilities = [ - set(['i', 'd', 'u']), - set(['x', 'X']), - set(['f', 'F', 'g', 'G']) -] - - -def num_plurals(catalog, message): - """Verify the number of plurals in the translation.""" - if not message.pluralizable: - if not isinstance(message.string, string_types): - raise TranslationError("Found plural forms for non-pluralizable " - "message") - return - - # skip further tests if no catalog is provided. - elif catalog is None: - return - - msgstrs = message.string - if not isinstance(msgstrs, (list, tuple)): - msgstrs = (msgstrs,) - if len(msgstrs) != catalog.num_plurals: - raise TranslationError("Wrong number of plural forms (expected %d)" % - catalog.num_plurals) - - -def python_format(catalog, message): - """Verify the format string placeholders in the translation.""" - if 'python-format' not in message.flags: - return - msgids = message.id - if not isinstance(msgids, (list, tuple)): - msgids = (msgids,) - msgstrs = message.string - if not isinstance(msgstrs, (list, tuple)): - msgstrs = (msgstrs,) - - for msgid, msgstr in izip(msgids, msgstrs): - if msgstr: - _validate_format(msgid, msgstr) - - -def _validate_format(format, alternative): - """Test format string `alternative` against `format`. `format` can be the - msgid of a message and `alternative` one of the `msgstr`\s. The two - arguments are not interchangeable as `alternative` may contain less - placeholders if `format` uses named placeholders. - - The behavior of this function is undefined if the string does not use - string formattings. - - If the string formatting of `alternative` is compatible to `format` the - function returns `None`, otherwise a `TranslationError` is raised. - - Examples for compatible format strings: - - >>> _validate_format('Hello %s!', 'Hallo %s!') - >>> _validate_format('Hello %i!', 'Hallo %d!') - - Example for an incompatible format strings: - - >>> _validate_format('Hello %(name)s!', 'Hallo %s!') - Traceback (most recent call last): - ... - TranslationError: the format strings are of different kinds - - This function is used by the `python_format` checker. - - :param format: The original format string - :param alternative: The alternative format string that should be checked - against format - :raises TranslationError: on formatting errors - """ - - def _parse(string): - result = [] - for match in PYTHON_FORMAT.finditer(string): - name, format, typechar = match.groups() - if typechar == '%' and name is None: - continue - result.append((name, str(typechar))) - return result - - def _compatible(a, b): - if a == b: - return True - for set in _string_format_compatibilities: - if a in set and b in set: - return True - return False - - def _check_positional(results): - positional = None - for name, char in results: - if positional is None: - positional = name is None - else: - if (name is None) != positional: - raise TranslationError('format string mixes positional ' - 'and named placeholders') - return bool(positional) - - a, b = map(_parse, (format, alternative)) - - # now check if both strings are positional or named - a_positional, b_positional = map(_check_positional, (a, b)) - if a_positional and not b_positional and not b: - raise TranslationError('placeholders are incompatible') - elif a_positional != b_positional: - raise TranslationError('the format strings are of different kinds') - - # if we are operating on positional strings both must have the - # same number of format chars and those must be compatible - if a_positional: - if len(a) != len(b): - raise TranslationError('positional format placeholders are ' - 'unbalanced') - for idx, ((_, first), (_, second)) in enumerate(izip(a, b)): - if not _compatible(first, second): - raise TranslationError('incompatible format for placeholder ' - '%d: %r and %r are not compatible' % - (idx + 1, first, second)) - - # otherwise the second string must not have names the first one - # doesn't have and the types of those included must be compatible - else: - type_map = dict(a) - for name, typechar in b: - if name not in type_map: - raise TranslationError('unknown named placeholder %r' % name) - elif not _compatible(typechar, type_map[name]): - raise TranslationError('incompatible format for ' - 'placeholder %r: ' - '%r and %r are not compatible' % - (name, typechar, type_map[name])) - - -def _find_checkers(): - checkers = [] - try: - from pkg_resources import working_set - except ImportError: - pass - else: - for entry_point in working_set.iter_entry_points('babel.checkers'): - checkers.append(entry_point.load()) - if len(checkers) == 0: - # if pkg_resources is not available or no usable egg-info was found - # (see #230), just resort to hard-coded checkers - return [num_plurals, python_format] - return checkers - - -checkers = _find_checkers() diff --git a/awx/lib/site-packages/babel/messages/extract.py b/awx/lib/site-packages/babel/messages/extract.py deleted file mode 100644 index 2f8084af53..0000000000 --- a/awx/lib/site-packages/babel/messages/extract.py +++ /dev/null @@ -1,562 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.extract - ~~~~~~~~~~~~~~~~~~~~~~ - - Basic infrastructure for extracting localizable messages from source files. - - This module defines an extensible system for collecting localizable message - strings from a variety of sources. A native extractor for Python source - files is builtin, extractors for other sources can be added using very - simple plugins. - - The main entry points into the extraction functionality are the functions - `extract_from_dir` and `extract_from_file`. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import os -import sys -from tokenize import generate_tokens, COMMENT, NAME, OP, STRING - -from babel.util import parse_encoding, pathmatch, relpath -from babel._compat import PY2, text_type -from textwrap import dedent - - -GROUP_NAME = 'babel.extractors' - -DEFAULT_KEYWORDS = { - '_': None, - 'gettext': None, - 'ngettext': (1, 2), - 'ugettext': None, - 'ungettext': (1, 2), - 'dgettext': (2,), - 'dngettext': (2, 3), - 'N_': None, - 'pgettext': ((1, 'c'), 2) -} - -DEFAULT_MAPPING = [('**.py', 'python')] - -empty_msgid_warning = ( -'%s: warning: Empty msgid. It is reserved by GNU gettext: gettext("") ' -'returns the header entry with meta information, not the empty string.') - - -def _strip_comment_tags(comments, tags): - """Helper function for `extract` that strips comment tags from strings - in a list of comment lines. This functions operates in-place. - """ - def _strip(line): - for tag in tags: - if line.startswith(tag): - return line[len(tag):].strip() - return line - comments[:] = map(_strip, comments) - - -def extract_from_dir(dirname=None, method_map=DEFAULT_MAPPING, - options_map=None, keywords=DEFAULT_KEYWORDS, - comment_tags=(), callback=None, strip_comment_tags=False): - """Extract messages from any source files found in the given directory. - - This function generates tuples of the form ``(filename, lineno, message, - comments, context)``. - - Which extraction method is used per file is determined by the `method_map` - parameter, which maps extended glob patterns to extraction method names. - For example, the following is the default mapping: - - >>> method_map = [ - ... ('**.py', 'python') - ... ] - - This basically says that files with the filename extension ".py" at any - level inside the directory should be processed by the "python" extraction - method. Files that don't match any of the mapping patterns are ignored. See - the documentation of the `pathmatch` function for details on the pattern - syntax. - - The following extended mapping would also use the "genshi" extraction - method on any file in "templates" subdirectory: - - >>> method_map = [ - ... ('**/templates/**.*', 'genshi'), - ... ('**.py', 'python') - ... ] - - The dictionary provided by the optional `options_map` parameter augments - these mappings. It uses extended glob patterns as keys, and the values are - dictionaries mapping options names to option values (both strings). - - The glob patterns of the `options_map` do not necessarily need to be the - same as those used in the method mapping. For example, while all files in - the ``templates`` folders in an application may be Genshi applications, the - options for those files may differ based on extension: - - >>> options_map = { - ... '**/templates/**.txt': { - ... 'template_class': 'genshi.template:TextTemplate', - ... 'encoding': 'latin-1' - ... }, - ... '**/templates/**.html': { - ... 'include_attrs': '' - ... } - ... } - - :param dirname: the path to the directory to extract messages from. If - not given the current working directory is used. - :param method_map: a list of ``(pattern, method)`` tuples that maps of - extraction method names to extended glob patterns - :param options_map: a dictionary of additional options (optional) - :param keywords: a dictionary mapping keywords (i.e. names of functions - that should be recognized as translation functions) to - tuples that specify which of their arguments contain - localizable strings - :param comment_tags: a list of tags of translator comments to search for - and include in the results - :param callback: a function that is called for every file that message are - extracted from, just before the extraction itself is - performed; the function is passed the filename, the name - of the extraction method and and the options dictionary as - positional arguments, in that order - :param strip_comment_tags: a flag that if set to `True` causes all comment - tags to be removed from the collected comments. - :see: `pathmatch` - """ - if dirname is None: - dirname = os.getcwd() - if options_map is None: - options_map = {} - - absname = os.path.abspath(dirname) - for root, dirnames, filenames in os.walk(absname): - for subdir in dirnames: - if subdir.startswith('.') or subdir.startswith('_'): - dirnames.remove(subdir) - dirnames.sort() - filenames.sort() - for filename in filenames: - filename = relpath( - os.path.join(root, filename).replace(os.sep, '/'), - dirname - ) - for pattern, method in method_map: - if pathmatch(pattern, filename): - filepath = os.path.join(absname, filename) - options = {} - for opattern, odict in options_map.items(): - if pathmatch(opattern, filename): - options = odict - if callback: - callback(filename, method, options) - for lineno, message, comments, context in \ - extract_from_file(method, filepath, - keywords=keywords, - comment_tags=comment_tags, - options=options, - strip_comment_tags= - strip_comment_tags): - yield filename, lineno, message, comments, context - break - - -def extract_from_file(method, filename, keywords=DEFAULT_KEYWORDS, - comment_tags=(), options=None, strip_comment_tags=False): - """Extract messages from a specific file. - - This function returns a list of tuples of the form ``(lineno, funcname, - message)``. - - :param filename: the path to the file to extract messages from - :param method: a string specifying the extraction method (.e.g. "python") - :param keywords: a dictionary mapping keywords (i.e. names of functions - that should be recognized as translation functions) to - tuples that specify which of their arguments contain - localizable strings - :param comment_tags: a list of translator tags to search for and include - in the results - :param strip_comment_tags: a flag that if set to `True` causes all comment - tags to be removed from the collected comments. - :param options: a dictionary of additional options (optional) - """ - fileobj = open(filename, 'rb') - try: - return list(extract(method, fileobj, keywords, comment_tags, options, - strip_comment_tags)) - finally: - fileobj.close() - - -def extract(method, fileobj, keywords=DEFAULT_KEYWORDS, comment_tags=(), - options=None, strip_comment_tags=False): - """Extract messages from the given file-like object using the specified - extraction method. - - This function returns tuples of the form ``(lineno, message, comments)``. - - The implementation dispatches the actual extraction to plugins, based on the - value of the ``method`` parameter. - - >>> source = '''# foo module - ... def run(argv): - ... print _('Hello, world!') - ... ''' - - >>> from StringIO import StringIO - >>> for message in extract('python', StringIO(source)): - ... print message - (3, u'Hello, world!', [], None) - - :param method: a string specifying the extraction method (.e.g. "python"); - if this is a simple name, the extraction function will be - looked up by entry point; if it is an explicit reference - to a function (of the form ``package.module:funcname`` or - ``package.module.funcname``), the corresponding function - will be imported and used - :param fileobj: the file-like object the messages should be extracted from - :param keywords: a dictionary mapping keywords (i.e. names of functions - that should be recognized as translation functions) to - tuples that specify which of their arguments contain - localizable strings - :param comment_tags: a list of translator tags to search for and include - in the results - :param options: a dictionary of additional options (optional) - :param strip_comment_tags: a flag that if set to `True` causes all comment - tags to be removed from the collected comments. - :raise ValueError: if the extraction method is not registered - """ - func = None - if ':' in method or '.' in method: - if ':' not in method: - lastdot = method.rfind('.') - module, attrname = method[:lastdot], method[lastdot + 1:] - else: - module, attrname = method.split(':', 1) - func = getattr(__import__(module, {}, {}, [attrname]), attrname) - else: - try: - from pkg_resources import working_set - except ImportError: - pass - else: - for entry_point in working_set.iter_entry_points(GROUP_NAME, - method): - func = entry_point.load(require=True) - break - if func is None: - # if pkg_resources is not available or no usable egg-info was found - # (see #230), we resort to looking up the builtin extractors - # directly - builtin = { - 'ignore': extract_nothing, - 'python': extract_python, - 'javascript': extract_javascript - } - func = builtin.get(method) - if func is None: - raise ValueError('Unknown extraction method %r' % method) - - results = func(fileobj, keywords.keys(), comment_tags, - options=options or {}) - - for lineno, funcname, messages, comments in results: - if funcname: - spec = keywords[funcname] or (1,) - else: - spec = (1,) - if not isinstance(messages, (list, tuple)): - messages = [messages] - if not messages: - continue - - # Validate the messages against the keyword's specification - context = None - msgs = [] - invalid = False - # last_index is 1 based like the keyword spec - last_index = len(messages) - for index in spec: - if isinstance(index, tuple): - context = messages[index[0] - 1] - continue - if last_index < index: - # Not enough arguments - invalid = True - break - message = messages[index - 1] - if message is None: - invalid = True - break - msgs.append(message) - if invalid: - continue - - # keyword spec indexes are 1 based, therefore '-1' - if isinstance(spec[0], tuple): - # context-aware *gettext method - first_msg_index = spec[1] - 1 - else: - first_msg_index = spec[0] - 1 - if not messages[first_msg_index]: - # An empty string msgid isn't valid, emit a warning - where = '%s:%i' % (hasattr(fileobj, 'name') and \ - fileobj.name or '(unknown)', lineno) - sys.stderr.write((empty_msgid_warning % where) + '\n') - continue - - messages = tuple(msgs) - if len(messages) == 1: - messages = messages[0] - - if strip_comment_tags: - _strip_comment_tags(comments, comment_tags) - yield lineno, messages, comments, context - - -def extract_nothing(fileobj, keywords, comment_tags, options): - """Pseudo extractor that does not actually extract anything, but simply - returns an empty list. - """ - return [] - - -def extract_python(fileobj, keywords, comment_tags, options): - """Extract messages from Python source code. - - It returns an iterator yielding tuples in the following form ``(lineno, - funcname, message, comments)``. - - :param fileobj: the seekable, file-like object the messages should be - extracted from - :param keywords: a list of keywords (i.e. function names) that should be - recognized as translation functions - :param comment_tags: a list of translator tags to search for and include - in the results - :param options: a dictionary of additional options (optional) - :rtype: ``iterator`` - """ - funcname = lineno = message_lineno = None - call_stack = -1 - buf = [] - messages = [] - translator_comments = [] - in_def = in_translator_comments = False - comment_tag = None - - encoding = parse_encoding(fileobj) or options.get('encoding', 'iso-8859-1') - - if PY2: - next_line = fileobj.readline - else: - next_line = lambda: fileobj.readline().decode(encoding) - - tokens = generate_tokens(next_line) - for tok, value, (lineno, _), _, _ in tokens: - if call_stack == -1 and tok == NAME and value in ('def', 'class'): - in_def = True - elif tok == OP and value == '(': - if in_def: - # Avoid false positives for declarations such as: - # def gettext(arg='message'): - in_def = False - continue - if funcname: - message_lineno = lineno - call_stack += 1 - elif in_def and tok == OP and value == ':': - # End of a class definition without parens - in_def = False - continue - elif call_stack == -1 and tok == COMMENT: - # Strip the comment token from the line - if PY2: - value = value.decode(encoding) - value = value[1:].strip() - if in_translator_comments and \ - translator_comments[-1][0] == lineno - 1: - # We're already inside a translator comment, continue appending - translator_comments.append((lineno, value)) - continue - # If execution reaches this point, let's see if comment line - # starts with one of the comment tags - for comment_tag in comment_tags: - if value.startswith(comment_tag): - in_translator_comments = True - translator_comments.append((lineno, value)) - break - elif funcname and call_stack == 0: - if tok == OP and value == ')': - if buf: - messages.append(''.join(buf)) - del buf[:] - else: - messages.append(None) - - if len(messages) > 1: - messages = tuple(messages) - else: - messages = messages[0] - # Comments don't apply unless they immediately preceed the - # message - if translator_comments and \ - translator_comments[-1][0] < message_lineno - 1: - translator_comments = [] - - yield (message_lineno, funcname, messages, - [comment[1] for comment in translator_comments]) - - funcname = lineno = message_lineno = None - call_stack = -1 - messages = [] - translator_comments = [] - in_translator_comments = False - elif tok == STRING: - # Unwrap quotes in a safe manner, maintaining the string's - # encoding - # https://sourceforge.net/tracker/?func=detail&atid=355470& - # aid=617979&group_id=5470 - value = eval('# coding=%s\n%s' % (str(encoding), value), - {'__builtins__':{}}, {}) - if PY2 and not isinstance(value, text_type): - value = value.decode(encoding) - buf.append(value) - elif tok == OP and value == ',': - if buf: - messages.append(''.join(buf)) - del buf[:] - else: - messages.append(None) - if translator_comments: - # We have translator comments, and since we're on a - # comma(,) user is allowed to break into a new line - # Let's increase the last comment's lineno in order - # for the comment to still be a valid one - old_lineno, old_comment = translator_comments.pop() - translator_comments.append((old_lineno+1, old_comment)) - elif call_stack > 0 and tok == OP and value == ')': - call_stack -= 1 - elif funcname and call_stack == -1: - funcname = None - elif tok == NAME and value in keywords: - funcname = value - - -def extract_javascript(fileobj, keywords, comment_tags, options): - """Extract messages from JavaScript source code. - - :param fileobj: the seekable, file-like object the messages should be - extracted from - :param keywords: a list of keywords (i.e. function names) that should be - recognized as translation functions - :param comment_tags: a list of translator tags to search for and include - in the results - :param options: a dictionary of additional options (optional) - """ - from babel.messages.jslexer import tokenize, unquote_string - funcname = message_lineno = None - messages = [] - last_argument = None - translator_comments = [] - concatenate_next = False - encoding = options.get('encoding', 'utf-8') - last_token = None - call_stack = -1 - - for token in tokenize(fileobj.read().decode(encoding)): - if token.type == 'operator' and token.value == '(': - if funcname: - message_lineno = token.lineno - call_stack += 1 - - elif call_stack == -1 and token.type == 'linecomment': - value = token.value[2:].strip() - if translator_comments and \ - translator_comments[-1][0] == token.lineno - 1: - translator_comments.append((token.lineno, value)) - continue - - for comment_tag in comment_tags: - if value.startswith(comment_tag): - translator_comments.append((token.lineno, value.strip())) - break - - elif token.type == 'multilinecomment': - # only one multi-line comment may preceed a translation - translator_comments = [] - value = token.value[2:-2].strip() - for comment_tag in comment_tags: - if value.startswith(comment_tag): - lines = value.splitlines() - if lines: - lines[0] = lines[0].strip() - lines[1:] = dedent('\n'.join(lines[1:])).splitlines() - for offset, line in enumerate(lines): - translator_comments.append((token.lineno + offset, - line)) - break - - elif funcname and call_stack == 0: - if token.type == 'operator' and token.value == ')': - if last_argument is not None: - messages.append(last_argument) - if len(messages) > 1: - messages = tuple(messages) - elif messages: - messages = messages[0] - else: - messages = None - - # Comments don't apply unless they immediately precede the - # message - if translator_comments and \ - translator_comments[-1][0] < message_lineno - 1: - translator_comments = [] - - if messages is not None: - yield (message_lineno, funcname, messages, - [comment[1] for comment in translator_comments]) - - funcname = message_lineno = last_argument = None - concatenate_next = False - translator_comments = [] - messages = [] - call_stack = -1 - - elif token.type == 'string': - new_value = unquote_string(token.value) - if concatenate_next: - last_argument = (last_argument or '') + new_value - concatenate_next = False - else: - last_argument = new_value - - elif token.type == 'operator': - if token.value == ',': - if last_argument is not None: - messages.append(last_argument) - last_argument = None - else: - messages.append(None) - concatenate_next = False - elif token.value == '+': - concatenate_next = True - - elif call_stack > 0 and token.type == 'operator' \ - and token.value == ')': - call_stack -= 1 - - elif funcname and call_stack == -1: - funcname = None - - elif call_stack == -1 and token.type == 'name' and \ - token.value in keywords and \ - (last_token is None or last_token.type != 'name' or - last_token.value != 'function'): - funcname = token.value - - last_token = token diff --git a/awx/lib/site-packages/babel/messages/frontend.py b/awx/lib/site-packages/babel/messages/frontend.py deleted file mode 100644 index 144bc98a10..0000000000 --- a/awx/lib/site-packages/babel/messages/frontend.py +++ /dev/null @@ -1,1259 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.frontend - ~~~~~~~~~~~~~~~~~~~~~~~ - - Frontends for the message extraction functionality. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -try: - from ConfigParser import RawConfigParser -except ImportError: - from configparser import RawConfigParser -from datetime import datetime -from distutils import log -from distutils.cmd import Command -from distutils.errors import DistutilsOptionError, DistutilsSetupError -from locale import getpreferredencoding -import logging -from optparse import OptionParser -import os -import re -import shutil -import sys -import tempfile - -from babel import __version__ as VERSION -from babel import Locale, localedata -from babel.core import UnknownLocaleError -from babel.messages.catalog import Catalog -from babel.messages.extract import extract_from_dir, DEFAULT_KEYWORDS, \ - DEFAULT_MAPPING -from babel.messages.mofile import write_mo -from babel.messages.pofile import read_po, write_po -from babel.util import odict, LOCALTZ -from babel._compat import string_types, BytesIO, PY2 - - -class compile_catalog(Command): - """Catalog compilation command for use in ``setup.py`` scripts. - - If correctly installed, this command is available to Setuptools-using - setup scripts automatically. For projects using plain old ``distutils``, - the command needs to be registered explicitly in ``setup.py``:: - - from babel.messages.frontend import compile_catalog - - setup( - ... - cmdclass = {'compile_catalog': compile_catalog} - ) - - .. versionadded:: 0.9 - """ - - description = 'compile message catalogs to binary MO files' - user_options = [ - ('domain=', 'D', - "domain of PO file (default 'messages')"), - ('directory=', 'd', - 'path to base directory containing the catalogs'), - ('input-file=', 'i', - 'name of the input file'), - ('output-file=', 'o', - "name of the output file (default " - "'<output_dir>/<locale>/LC_MESSAGES/<domain>.po')"), - ('locale=', 'l', - 'locale of the catalog to compile'), - ('use-fuzzy', 'f', - 'also include fuzzy translations'), - ('statistics', None, - 'print statistics about translations') - ] - boolean_options = ['use-fuzzy', 'statistics'] - - def initialize_options(self): - self.domain = 'messages' - self.directory = None - self.input_file = None - self.output_file = None - self.locale = None - self.use_fuzzy = False - self.statistics = False - - def finalize_options(self): - if not self.input_file and not self.directory: - raise DistutilsOptionError('you must specify either the input file ' - 'or the base directory') - if not self.output_file and not self.directory: - raise DistutilsOptionError('you must specify either the input file ' - 'or the base directory') - - def run(self): - po_files = [] - mo_files = [] - - if not self.input_file: - if self.locale: - po_files.append((self.locale, - os.path.join(self.directory, self.locale, - 'LC_MESSAGES', - self.domain + '.po'))) - mo_files.append(os.path.join(self.directory, self.locale, - 'LC_MESSAGES', - self.domain + '.mo')) - else: - for locale in os.listdir(self.directory): - po_file = os.path.join(self.directory, locale, - 'LC_MESSAGES', self.domain + '.po') - if os.path.exists(po_file): - po_files.append((locale, po_file)) - mo_files.append(os.path.join(self.directory, locale, - 'LC_MESSAGES', - self.domain + '.mo')) - else: - po_files.append((self.locale, self.input_file)) - if self.output_file: - mo_files.append(self.output_file) - else: - mo_files.append(os.path.join(self.directory, self.locale, - 'LC_MESSAGES', - self.domain + '.mo')) - - if not po_files: - raise DistutilsOptionError('no message catalogs found') - - for idx, (locale, po_file) in enumerate(po_files): - mo_file = mo_files[idx] - infile = open(po_file, 'r') - try: - catalog = read_po(infile, locale) - finally: - infile.close() - - if self.statistics: - translated = 0 - for message in list(catalog)[1:]: - if message.string: - translated +=1 - percentage = 0 - if len(catalog): - percentage = translated * 100 // len(catalog) - log.info('%d of %d messages (%d%%) translated in %r', - translated, len(catalog), percentage, po_file) - - if catalog.fuzzy and not self.use_fuzzy: - log.warn('catalog %r is marked as fuzzy, skipping', po_file) - continue - - for message, errors in catalog.check(): - for error in errors: - log.error('error: %s:%d: %s', po_file, message.lineno, - error) - - log.info('compiling catalog %r to %r', po_file, mo_file) - - outfile = open(mo_file, 'wb') - try: - write_mo(outfile, catalog, use_fuzzy=self.use_fuzzy) - finally: - outfile.close() - - -class extract_messages(Command): - """Message extraction command for use in ``setup.py`` scripts. - - If correctly installed, this command is available to Setuptools-using - setup scripts automatically. For projects using plain old ``distutils``, - the command needs to be registered explicitly in ``setup.py``:: - - from babel.messages.frontend import extract_messages - - setup( - ... - cmdclass = {'extract_messages': extract_messages} - ) - """ - - description = 'extract localizable strings from the project code' - user_options = [ - ('charset=', None, - 'charset to use in the output file'), - ('keywords=', 'k', - 'space-separated list of keywords to look for in addition to the ' - 'defaults'), - ('no-default-keywords', None, - 'do not include the default keywords'), - ('mapping-file=', 'F', - 'path to the mapping configuration file'), - ('no-location', None, - 'do not include location comments with filename and line number'), - ('omit-header', None, - 'do not include msgid "" entry in header'), - ('output-file=', 'o', - 'name of the output file'), - ('width=', 'w', - 'set output line width (default 76)'), - ('no-wrap', None, - 'do not break long message lines, longer than the output line width, ' - 'into several lines'), - ('sort-output', None, - 'generate sorted output (default False)'), - ('sort-by-file', None, - 'sort output by file location (default False)'), - ('msgid-bugs-address=', None, - 'set report address for msgid'), - ('copyright-holder=', None, - 'set copyright holder in output'), - ('add-comments=', 'c', - 'place comment block with TAG (or those preceding keyword lines) in ' - 'output file. Separate multiple TAGs with commas(,)'), - ('strip-comments', None, - 'strip the comment TAGs from the comments.'), - ('input-dirs=', None, - 'directories that should be scanned for messages. Separate multiple ' - 'directories with commas(,)'), - ] - boolean_options = [ - 'no-default-keywords', 'no-location', 'omit-header', 'no-wrap', - 'sort-output', 'sort-by-file', 'strip-comments' - ] - - def initialize_options(self): - self.charset = 'utf-8' - self.keywords = '' - self._keywords = DEFAULT_KEYWORDS.copy() - self.no_default_keywords = False - self.mapping_file = None - self.no_location = False - self.omit_header = False - self.output_file = None - self.input_dirs = None - self.width = None - self.no_wrap = False - self.sort_output = False - self.sort_by_file = False - self.msgid_bugs_address = None - self.copyright_holder = None - self.add_comments = None - self._add_comments = [] - self.strip_comments = False - - def finalize_options(self): - if self.no_default_keywords and not self.keywords: - raise DistutilsOptionError('you must specify new keywords if you ' - 'disable the default ones') - if self.no_default_keywords: - self._keywords = {} - if self.keywords: - self._keywords.update(parse_keywords(self.keywords.split())) - - if not self.output_file: - raise DistutilsOptionError('no output file specified') - if self.no_wrap and self.width: - raise DistutilsOptionError("'--no-wrap' and '--width' are mutually " - "exclusive") - if not self.no_wrap and not self.width: - self.width = 76 - elif self.width is not None: - self.width = int(self.width) - - if self.sort_output and self.sort_by_file: - raise DistutilsOptionError("'--sort-output' and '--sort-by-file' " - "are mutually exclusive") - - if self.input_dirs: - self.input_dirs = re.split(',\s*', self.input_dirs) - else: - self.input_dirs = dict.fromkeys([k.split('.',1)[0] - for k in self.distribution.packages - ]).keys() - - if self.add_comments: - self._add_comments = self.add_comments.split(',') - - def run(self): - mappings = self._get_mappings() - outfile = open(self.output_file, 'wb') - try: - catalog = Catalog(project=self.distribution.get_name(), - version=self.distribution.get_version(), - msgid_bugs_address=self.msgid_bugs_address, - copyright_holder=self.copyright_holder, - charset=self.charset) - - for dirname, (method_map, options_map) in mappings.items(): - def callback(filename, method, options): - if method == 'ignore': - return - filepath = os.path.normpath(os.path.join(dirname, filename)) - optstr = '' - if options: - optstr = ' (%s)' % ', '.join(['%s="%s"' % (k, v) for - k, v in options.items()]) - log.info('extracting messages from %s%s', filepath, optstr) - - extracted = extract_from_dir(dirname, method_map, options_map, - keywords=self._keywords, - comment_tags=self._add_comments, - callback=callback, - strip_comment_tags= - self.strip_comments) - for filename, lineno, message, comments, context in extracted: - filepath = os.path.normpath(os.path.join(dirname, filename)) - catalog.add(message, None, [(filepath, lineno)], - auto_comments=comments, context=context) - - log.info('writing PO template file to %s' % self.output_file) - write_po(outfile, catalog, width=self.width, - no_location=self.no_location, - omit_header=self.omit_header, - sort_output=self.sort_output, - sort_by_file=self.sort_by_file) - finally: - outfile.close() - - def _get_mappings(self): - mappings = {} - - if self.mapping_file: - fileobj = open(self.mapping_file, 'U') - try: - method_map, options_map = parse_mapping(fileobj) - for dirname in self.input_dirs: - mappings[dirname] = method_map, options_map - finally: - fileobj.close() - - elif getattr(self.distribution, 'message_extractors', None): - message_extractors = self.distribution.message_extractors - for dirname, mapping in message_extractors.items(): - if isinstance(mapping, string_types): - method_map, options_map = parse_mapping(BytesIO(mapping)) - else: - method_map, options_map = [], {} - for pattern, method, options in mapping: - method_map.append((pattern, method)) - options_map[pattern] = options or {} - mappings[dirname] = method_map, options_map - - else: - for dirname in self.input_dirs: - mappings[dirname] = DEFAULT_MAPPING, {} - - return mappings - - -def check_message_extractors(dist, name, value): - """Validate the ``message_extractors`` keyword argument to ``setup()``. - - :param dist: the distutils/setuptools ``Distribution`` object - :param name: the name of the keyword argument (should always be - "message_extractors") - :param value: the value of the keyword argument - :raise `DistutilsSetupError`: if the value is not valid - """ - assert name == 'message_extractors' - if not isinstance(value, dict): - raise DistutilsSetupError('the value of the "message_extractors" ' - 'parameter must be a dictionary') - - -class init_catalog(Command): - """New catalog initialization command for use in ``setup.py`` scripts. - - If correctly installed, this command is available to Setuptools-using - setup scripts automatically. For projects using plain old ``distutils``, - the command needs to be registered explicitly in ``setup.py``:: - - from babel.messages.frontend import init_catalog - - setup( - ... - cmdclass = {'init_catalog': init_catalog} - ) - """ - - description = 'create a new catalog based on a POT file' - user_options = [ - ('domain=', 'D', - "domain of PO file (default 'messages')"), - ('input-file=', 'i', - 'name of the input file'), - ('output-dir=', 'd', - 'path to output directory'), - ('output-file=', 'o', - "name of the output file (default " - "'<output_dir>/<locale>/LC_MESSAGES/<domain>.po')"), - ('locale=', 'l', - 'locale for the new localized catalog'), - ('width=', 'w', - 'set output line width (default 76)'), - ('no-wrap', None, - 'do not break long message lines, longer than the output line width, ' - 'into several lines'), - ] - boolean_options = ['no-wrap'] - - def initialize_options(self): - self.output_dir = None - self.output_file = None - self.input_file = None - self.locale = None - self.domain = 'messages' - self.no_wrap = False - self.width = None - - def finalize_options(self): - if not self.input_file: - raise DistutilsOptionError('you must specify the input file') - - if not self.locale: - raise DistutilsOptionError('you must provide a locale for the ' - 'new catalog') - try: - self._locale = Locale.parse(self.locale) - except UnknownLocaleError as e: - raise DistutilsOptionError(e) - - if not self.output_file and not self.output_dir: - raise DistutilsOptionError('you must specify the output directory') - if not self.output_file: - self.output_file = os.path.join(self.output_dir, self.locale, - 'LC_MESSAGES', self.domain + '.po') - - if not os.path.exists(os.path.dirname(self.output_file)): - os.makedirs(os.path.dirname(self.output_file)) - if self.no_wrap and self.width: - raise DistutilsOptionError("'--no-wrap' and '--width' are mutually " - "exclusive") - if not self.no_wrap and not self.width: - self.width = 76 - elif self.width is not None: - self.width = int(self.width) - - def run(self): - log.info('creating catalog %r based on %r', self.output_file, - self.input_file) - - infile = open(self.input_file, 'r') - try: - # Although reading from the catalog template, read_po must be fed - # the locale in order to correctly calculate plurals - catalog = read_po(infile, locale=self.locale) - finally: - infile.close() - - catalog.locale = self._locale - catalog.revision_date = datetime.now(LOCALTZ) - catalog.fuzzy = False - - outfile = open(self.output_file, 'wb') - try: - write_po(outfile, catalog, width=self.width) - finally: - outfile.close() - - -class update_catalog(Command): - """Catalog merging command for use in ``setup.py`` scripts. - - If correctly installed, this command is available to Setuptools-using - setup scripts automatically. For projects using plain old ``distutils``, - the command needs to be registered explicitly in ``setup.py``:: - - from babel.messages.frontend import update_catalog - - setup( - ... - cmdclass = {'update_catalog': update_catalog} - ) - - .. versionadded:: 0.9 - """ - - description = 'update message catalogs from a POT file' - user_options = [ - ('domain=', 'D', - "domain of PO file (default 'messages')"), - ('input-file=', 'i', - 'name of the input file'), - ('output-dir=', 'd', - 'path to base directory containing the catalogs'), - ('output-file=', 'o', - "name of the output file (default " - "'<output_dir>/<locale>/LC_MESSAGES/<domain>.po')"), - ('locale=', 'l', - 'locale of the catalog to compile'), - ('width=', 'w', - 'set output line width (default 76)'), - ('no-wrap', None, - 'do not break long message lines, longer than the output line width, ' - 'into several lines'), - ('ignore-obsolete=', None, - 'whether to omit obsolete messages from the output'), - ('no-fuzzy-matching', 'N', - 'do not use fuzzy matching'), - ('previous', None, - 'keep previous msgids of translated messages') - ] - boolean_options = ['ignore_obsolete', 'no_fuzzy_matching', 'previous'] - - def initialize_options(self): - self.domain = 'messages' - self.input_file = None - self.output_dir = None - self.output_file = None - self.locale = None - self.width = None - self.no_wrap = False - self.ignore_obsolete = False - self.no_fuzzy_matching = False - self.previous = False - - def finalize_options(self): - if not self.input_file: - raise DistutilsOptionError('you must specify the input file') - if not self.output_file and not self.output_dir: - raise DistutilsOptionError('you must specify the output file or ' - 'directory') - if self.output_file and not self.locale: - raise DistutilsOptionError('you must specify the locale') - if self.no_wrap and self.width: - raise DistutilsOptionError("'--no-wrap' and '--width' are mutually " - "exclusive") - if not self.no_wrap and not self.width: - self.width = 76 - elif self.width is not None: - self.width = int(self.width) - if self.no_fuzzy_matching and self.previous: - self.previous = False - - def run(self): - po_files = [] - if not self.output_file: - if self.locale: - po_files.append((self.locale, - os.path.join(self.output_dir, self.locale, - 'LC_MESSAGES', - self.domain + '.po'))) - else: - for locale in os.listdir(self.output_dir): - po_file = os.path.join(self.output_dir, locale, - 'LC_MESSAGES', - self.domain + '.po') - if os.path.exists(po_file): - po_files.append((locale, po_file)) - else: - po_files.append((self.locale, self.output_file)) - - domain = self.domain - if not domain: - domain = os.path.splitext(os.path.basename(self.input_file))[0] - - infile = open(self.input_file, 'U') - try: - template = read_po(infile) - finally: - infile.close() - - if not po_files: - raise DistutilsOptionError('no message catalogs found') - - for locale, filename in po_files: - log.info('updating catalog %r based on %r', filename, - self.input_file) - infile = open(filename, 'U') - try: - catalog = read_po(infile, locale=locale, domain=domain) - finally: - infile.close() - - catalog.update(template, self.no_fuzzy_matching) - - tmpname = os.path.join(os.path.dirname(filename), - tempfile.gettempprefix() + - os.path.basename(filename)) - tmpfile = open(tmpname, 'w') - try: - try: - write_po(tmpfile, catalog, - ignore_obsolete=self.ignore_obsolete, - include_previous=self.previous, width=self.width) - finally: - tmpfile.close() - except: - os.remove(tmpname) - raise - - try: - os.rename(tmpname, filename) - except OSError: - # We're probably on Windows, which doesn't support atomic - # renames, at least not through Python - # If the error is in fact due to a permissions problem, that - # same error is going to be raised from one of the following - # operations - os.remove(filename) - shutil.copy(tmpname, filename) - os.remove(tmpname) - - -class CommandLineInterface(object): - """Command-line interface. - - This class provides a simple command-line interface to the message - extraction and PO file generation functionality. - """ - - usage = '%%prog %s [options] %s' - version = '%%prog %s' % VERSION - commands = { - 'compile': 'compile message catalogs to MO files', - 'extract': 'extract messages from source files and generate a POT file', - 'init': 'create new message catalogs from a POT file', - 'update': 'update existing message catalogs from a POT file' - } - - def run(self, argv=sys.argv): - """Main entry point of the command-line interface. - - :param argv: list of arguments passed on the command-line - """ - self.parser = OptionParser(usage=self.usage % ('command', '[args]'), - version=self.version) - self.parser.disable_interspersed_args() - self.parser.print_help = self._help - self.parser.add_option('--list-locales', dest='list_locales', - action='store_true', - help="print all known locales and exit") - self.parser.add_option('-v', '--verbose', action='store_const', - dest='loglevel', const=logging.DEBUG, - help='print as much as possible') - self.parser.add_option('-q', '--quiet', action='store_const', - dest='loglevel', const=logging.ERROR, - help='print as little as possible') - self.parser.set_defaults(list_locales=False, loglevel=logging.INFO) - - options, args = self.parser.parse_args(argv[1:]) - - self._configure_logging(options.loglevel) - if options.list_locales: - identifiers = localedata.locale_identifiers() - longest = max([len(identifier) for identifier in identifiers]) - identifiers.sort() - format = u'%%-%ds %%s' % (longest + 1) - for identifier in identifiers: - locale = Locale.parse(identifier) - output = format % (identifier, locale.english_name) - print(output.encode(sys.stdout.encoding or - getpreferredencoding() or - 'ascii', 'replace')) - return 0 - - if not args: - self.parser.error('no valid command or option passed. ' - 'Try the -h/--help option for more information.') - - cmdname = args[0] - if cmdname not in self.commands: - self.parser.error('unknown command "%s"' % cmdname) - - return getattr(self, cmdname)(args[1:]) - - def _configure_logging(self, loglevel): - self.log = logging.getLogger('babel') - self.log.setLevel(loglevel) - # Don't add a new handler for every instance initialization (#227), this - # would cause duplicated output when the CommandLineInterface as an - # normal Python class. - if self.log.handlers: - handler = self.log.handlers[0] - else: - handler = logging.StreamHandler() - self.log.addHandler(handler) - handler.setLevel(loglevel) - formatter = logging.Formatter('%(message)s') - handler.setFormatter(formatter) - - def _help(self): - print(self.parser.format_help()) - print("commands:") - longest = max([len(command) for command in self.commands]) - format = " %%-%ds %%s" % max(8, longest + 1) - commands = sorted(self.commands.items()) - for name, description in commands: - print(format % (name, description)) - - def compile(self, argv): - """Subcommand for compiling a message catalog to a MO file. - - :param argv: the command arguments - :since: version 0.9 - """ - parser = OptionParser(usage=self.usage % ('compile', ''), - description=self.commands['compile']) - parser.add_option('--domain', '-D', dest='domain', - help="domain of MO and PO files (default '%default')") - parser.add_option('--directory', '-d', dest='directory', - metavar='DIR', help='base directory of catalog files') - parser.add_option('--locale', '-l', dest='locale', metavar='LOCALE', - help='locale of the catalog') - parser.add_option('--input-file', '-i', dest='input_file', - metavar='FILE', help='name of the input file') - parser.add_option('--output-file', '-o', dest='output_file', - metavar='FILE', - help="name of the output file (default " - "'<output_dir>/<locale>/LC_MESSAGES/" - "<domain>.mo')") - parser.add_option('--use-fuzzy', '-f', dest='use_fuzzy', - action='store_true', - help='also include fuzzy translations (default ' - '%default)') - parser.add_option('--statistics', dest='statistics', - action='store_true', - help='print statistics about translations') - - parser.set_defaults(domain='messages', use_fuzzy=False, - compile_all=False, statistics=False) - options, args = parser.parse_args(argv) - - po_files = [] - mo_files = [] - if not options.input_file: - if not options.directory: - parser.error('you must specify either the input file or the ' - 'base directory') - if options.locale: - po_files.append((options.locale, - os.path.join(options.directory, - options.locale, 'LC_MESSAGES', - options.domain + '.po'))) - mo_files.append(os.path.join(options.directory, options.locale, - 'LC_MESSAGES', - options.domain + '.mo')) - else: - for locale in os.listdir(options.directory): - po_file = os.path.join(options.directory, locale, - 'LC_MESSAGES', options.domain + '.po') - if os.path.exists(po_file): - po_files.append((locale, po_file)) - mo_files.append(os.path.join(options.directory, locale, - 'LC_MESSAGES', - options.domain + '.mo')) - else: - po_files.append((options.locale, options.input_file)) - if options.output_file: - mo_files.append(options.output_file) - else: - if not options.directory: - parser.error('you must specify either the input file or ' - 'the base directory') - mo_files.append(os.path.join(options.directory, options.locale, - 'LC_MESSAGES', - options.domain + '.mo')) - if not po_files: - parser.error('no message catalogs found') - - for idx, (locale, po_file) in enumerate(po_files): - mo_file = mo_files[idx] - infile = open(po_file, 'r') - try: - catalog = read_po(infile, locale) - finally: - infile.close() - - if options.statistics: - translated = 0 - for message in list(catalog)[1:]: - if message.string: - translated +=1 - percentage = 0 - if len(catalog): - percentage = translated * 100 // len(catalog) - self.log.info("%d of %d messages (%d%%) translated in %r", - translated, len(catalog), percentage, po_file) - - if catalog.fuzzy and not options.use_fuzzy: - self.log.warning('catalog %r is marked as fuzzy, skipping', - po_file) - continue - - for message, errors in catalog.check(): - for error in errors: - self.log.error('error: %s:%d: %s', po_file, message.lineno, - error) - - self.log.info('compiling catalog %r to %r', po_file, mo_file) - - outfile = open(mo_file, 'wb') - try: - write_mo(outfile, catalog, use_fuzzy=options.use_fuzzy) - finally: - outfile.close() - - def extract(self, argv): - """Subcommand for extracting messages from source files and generating - a POT file. - - :param argv: the command arguments - """ - parser = OptionParser(usage=self.usage % ('extract', 'dir1 <dir2> ...'), - description=self.commands['extract']) - parser.add_option('--charset', dest='charset', - help='charset to use in the output (default ' - '"%default")') - parser.add_option('-k', '--keyword', dest='keywords', action='append', - help='keywords to look for in addition to the ' - 'defaults. You can specify multiple -k flags on ' - 'the command line.') - parser.add_option('--no-default-keywords', dest='no_default_keywords', - action='store_true', - help="do not include the default keywords") - parser.add_option('--mapping', '-F', dest='mapping_file', - help='path to the extraction mapping file') - parser.add_option('--no-location', dest='no_location', - action='store_true', - help='do not include location comments with filename ' - 'and line number') - parser.add_option('--omit-header', dest='omit_header', - action='store_true', - help='do not include msgid "" entry in header') - parser.add_option('-o', '--output', dest='output', - help='path to the output POT file') - parser.add_option('-w', '--width', dest='width', type='int', - help="set output line width (default 76)") - parser.add_option('--no-wrap', dest='no_wrap', action='store_true', - help='do not break long message lines, longer than ' - 'the output line width, into several lines') - parser.add_option('--sort-output', dest='sort_output', - action='store_true', - help='generate sorted output (default False)') - parser.add_option('--sort-by-file', dest='sort_by_file', - action='store_true', - help='sort output by file location (default False)') - parser.add_option('--msgid-bugs-address', dest='msgid_bugs_address', - metavar='EMAIL@ADDRESS', - help='set report address for msgid') - parser.add_option('--copyright-holder', dest='copyright_holder', - help='set copyright holder in output') - parser.add_option('--project', dest='project', - help='set project name in output') - parser.add_option('--version', dest='version', - help='set project version in output') - parser.add_option('--add-comments', '-c', dest='comment_tags', - metavar='TAG', action='append', - help='place comment block with TAG (or those ' - 'preceding keyword lines) in output file. One ' - 'TAG per argument call') - parser.add_option('--strip-comment-tags', '-s', - dest='strip_comment_tags', action='store_true', - help='Strip the comment tags from the comments.') - - parser.set_defaults(charset='utf-8', keywords=[], - no_default_keywords=False, no_location=False, - omit_header = False, width=None, no_wrap=False, - sort_output=False, sort_by_file=False, - comment_tags=[], strip_comment_tags=False) - options, args = parser.parse_args(argv) - if not args: - parser.error('incorrect number of arguments') - - keywords = DEFAULT_KEYWORDS.copy() - if options.no_default_keywords: - if not options.keywords: - parser.error('you must specify new keywords if you disable the ' - 'default ones') - keywords = {} - if options.keywords: - keywords.update(parse_keywords(options.keywords)) - - if options.mapping_file: - fileobj = open(options.mapping_file, 'U') - try: - method_map, options_map = parse_mapping(fileobj) - finally: - fileobj.close() - else: - method_map = DEFAULT_MAPPING - options_map = {} - - if options.width and options.no_wrap: - parser.error("'--no-wrap' and '--width' are mutually exclusive.") - elif not options.width and not options.no_wrap: - options.width = 76 - - if options.sort_output and options.sort_by_file: - parser.error("'--sort-output' and '--sort-by-file' are mutually " - "exclusive") - - catalog = Catalog(project=options.project, - version=options.version, - msgid_bugs_address=options.msgid_bugs_address, - copyright_holder=options.copyright_holder, - charset=options.charset) - - for dirname in args: - if not os.path.isdir(dirname): - parser.error('%r is not a directory' % dirname) - - def callback(filename, method, options): - if method == 'ignore': - return - filepath = os.path.normpath(os.path.join(dirname, filename)) - optstr = '' - if options: - optstr = ' (%s)' % ', '.join(['%s="%s"' % (k, v) for - k, v in options.items()]) - self.log.info('extracting messages from %s%s', filepath, - optstr) - - extracted = extract_from_dir(dirname, method_map, options_map, - keywords, options.comment_tags, - callback=callback, - strip_comment_tags= - options.strip_comment_tags) - for filename, lineno, message, comments, context in extracted: - filepath = os.path.normpath(os.path.join(dirname, filename)) - catalog.add(message, None, [(filepath, lineno)], - auto_comments=comments, context=context) - - catalog_charset = catalog.charset - if options.output not in (None, '-'): - self.log.info('writing PO template file to %s' % options.output) - outfile = open(options.output, 'wb') - close_output = True - else: - outfile = sys.stdout - - # This is a bit of a hack on Python 3. stdout is a text stream so - # we need to find the underlying file when we write the PO. In - # later versions of Babel we want the write_po function to accept - # text or binary streams and automatically adjust the encoding. - if not PY2 and hasattr(outfile, 'buffer'): - catalog.charset = outfile.encoding - outfile = outfile.buffer.raw - - close_output = False - - try: - write_po(outfile, catalog, width=options.width, - no_location=options.no_location, - omit_header=options.omit_header, - sort_output=options.sort_output, - sort_by_file=options.sort_by_file) - finally: - if close_output: - outfile.close() - catalog.charset = catalog_charset - - def init(self, argv): - """Subcommand for creating new message catalogs from a template. - - :param argv: the command arguments - """ - parser = OptionParser(usage=self.usage % ('init', ''), - description=self.commands['init']) - parser.add_option('--domain', '-D', dest='domain', - help="domain of PO file (default '%default')") - parser.add_option('--input-file', '-i', dest='input_file', - metavar='FILE', help='name of the input file') - parser.add_option('--output-dir', '-d', dest='output_dir', - metavar='DIR', help='path to output directory') - parser.add_option('--output-file', '-o', dest='output_file', - metavar='FILE', - help="name of the output file (default " - "'<output_dir>/<locale>/LC_MESSAGES/" - "<domain>.po')") - parser.add_option('--locale', '-l', dest='locale', metavar='LOCALE', - help='locale for the new localized catalog') - parser.add_option('-w', '--width', dest='width', type='int', - help="set output line width (default 76)") - parser.add_option('--no-wrap', dest='no_wrap', action='store_true', - help='do not break long message lines, longer than ' - 'the output line width, into several lines') - - parser.set_defaults(domain='messages') - options, args = parser.parse_args(argv) - - if not options.locale: - parser.error('you must provide a locale for the new catalog') - try: - locale = Locale.parse(options.locale) - except UnknownLocaleError as e: - parser.error(e) - - if not options.input_file: - parser.error('you must specify the input file') - - if not options.output_file and not options.output_dir: - parser.error('you must specify the output file or directory') - - if not options.output_file: - options.output_file = os.path.join(options.output_dir, - options.locale, 'LC_MESSAGES', - options.domain + '.po') - if not os.path.exists(os.path.dirname(options.output_file)): - os.makedirs(os.path.dirname(options.output_file)) - if options.width and options.no_wrap: - parser.error("'--no-wrap' and '--width' are mutually exclusive.") - elif not options.width and not options.no_wrap: - options.width = 76 - - infile = open(options.input_file, 'r') - try: - # Although reading from the catalog template, read_po must be fed - # the locale in order to correctly calculate plurals - catalog = read_po(infile, locale=options.locale) - finally: - infile.close() - - catalog.locale = locale - catalog.revision_date = datetime.now(LOCALTZ) - - self.log.info('creating catalog %r based on %r', options.output_file, - options.input_file) - - outfile = open(options.output_file, 'wb') - try: - write_po(outfile, catalog, width=options.width) - finally: - outfile.close() - - def update(self, argv): - """Subcommand for updating existing message catalogs from a template. - - :param argv: the command arguments - :since: version 0.9 - """ - parser = OptionParser(usage=self.usage % ('update', ''), - description=self.commands['update']) - parser.add_option('--domain', '-D', dest='domain', - help="domain of PO file (default '%default')") - parser.add_option('--input-file', '-i', dest='input_file', - metavar='FILE', help='name of the input file') - parser.add_option('--output-dir', '-d', dest='output_dir', - metavar='DIR', help='path to output directory') - parser.add_option('--output-file', '-o', dest='output_file', - metavar='FILE', - help="name of the output file (default " - "'<output_dir>/<locale>/LC_MESSAGES/" - "<domain>.po')") - parser.add_option('--locale', '-l', dest='locale', metavar='LOCALE', - help='locale of the translations catalog') - parser.add_option('-w', '--width', dest='width', type='int', - help="set output line width (default 76)") - parser.add_option('--no-wrap', dest='no_wrap', action = 'store_true', - help='do not break long message lines, longer than ' - 'the output line width, into several lines') - parser.add_option('--ignore-obsolete', dest='ignore_obsolete', - action='store_true', - help='do not include obsolete messages in the output ' - '(default %default)') - parser.add_option('--no-fuzzy-matching', '-N', dest='no_fuzzy_matching', - action='store_true', - help='do not use fuzzy matching (default %default)') - parser.add_option('--previous', dest='previous', action='store_true', - help='keep previous msgids of translated messages ' - '(default %default)') - - parser.set_defaults(domain='messages', ignore_obsolete=False, - no_fuzzy_matching=False, previous=False) - options, args = parser.parse_args(argv) - - if not options.input_file: - parser.error('you must specify the input file') - if not options.output_file and not options.output_dir: - parser.error('you must specify the output file or directory') - if options.output_file and not options.locale: - parser.error('you must specify the locale') - if options.no_fuzzy_matching and options.previous: - options.previous = False - - po_files = [] - if not options.output_file: - if options.locale: - po_files.append((options.locale, - os.path.join(options.output_dir, - options.locale, 'LC_MESSAGES', - options.domain + '.po'))) - else: - for locale in os.listdir(options.output_dir): - po_file = os.path.join(options.output_dir, locale, - 'LC_MESSAGES', - options.domain + '.po') - if os.path.exists(po_file): - po_files.append((locale, po_file)) - else: - po_files.append((options.locale, options.output_file)) - - domain = options.domain - if not domain: - domain = os.path.splitext(os.path.basename(options.input_file))[0] - - infile = open(options.input_file, 'U') - try: - template = read_po(infile) - finally: - infile.close() - - if not po_files: - parser.error('no message catalogs found') - - if options.width and options.no_wrap: - parser.error("'--no-wrap' and '--width' are mutually exclusive.") - elif not options.width and not options.no_wrap: - options.width = 76 - for locale, filename in po_files: - self.log.info('updating catalog %r based on %r', filename, - options.input_file) - infile = open(filename, 'U') - try: - catalog = read_po(infile, locale=locale, domain=domain) - finally: - infile.close() - - catalog.update(template, options.no_fuzzy_matching) - - tmpname = os.path.join(os.path.dirname(filename), - tempfile.gettempprefix() + - os.path.basename(filename)) - tmpfile = open(tmpname, 'w') - try: - try: - write_po(tmpfile, catalog, - ignore_obsolete=options.ignore_obsolete, - include_previous=options.previous, - width=options.width) - finally: - tmpfile.close() - except: - os.remove(tmpname) - raise - - try: - os.rename(tmpname, filename) - except OSError: - # We're probably on Windows, which doesn't support atomic - # renames, at least not through Python - # If the error is in fact due to a permissions problem, that - # same error is going to be raised from one of the following - # operations - os.remove(filename) - shutil.copy(tmpname, filename) - os.remove(tmpname) - - -def main(): - return CommandLineInterface().run(sys.argv) - - -def parse_mapping(fileobj, filename=None): - """Parse an extraction method mapping from a file-like object. - - >>> buf = BytesIO(b''' - ... [extractors] - ... custom = mypackage.module:myfunc - ... - ... # Python source files - ... [python: **.py] - ... - ... # Genshi templates - ... [genshi: **/templates/**.html] - ... include_attrs = - ... [genshi: **/templates/**.txt] - ... template_class = genshi.template:TextTemplate - ... encoding = latin-1 - ... - ... # Some custom extractor - ... [custom: **/custom/*.*] - ... ''') - - >>> method_map, options_map = parse_mapping(buf) - >>> len(method_map) - 4 - - >>> method_map[0] - ('**.py', 'python') - >>> options_map['**.py'] - {} - >>> method_map[1] - ('**/templates/**.html', 'genshi') - >>> options_map['**/templates/**.html']['include_attrs'] - '' - >>> method_map[2] - ('**/templates/**.txt', 'genshi') - >>> options_map['**/templates/**.txt']['template_class'] - 'genshi.template:TextTemplate' - >>> options_map['**/templates/**.txt']['encoding'] - 'latin-1' - - >>> method_map[3] - ('**/custom/*.*', 'mypackage.module:myfunc') - >>> options_map['**/custom/*.*'] - {} - - :param fileobj: a readable file-like object containing the configuration - text to parse - :see: `extract_from_directory` - """ - extractors = {} - method_map = [] - options_map = {} - - parser = RawConfigParser() - parser._sections = odict(parser._sections) # We need ordered sections - parser.readfp(fileobj, filename) - for section in parser.sections(): - if section == 'extractors': - extractors = dict(parser.items(section)) - else: - method, pattern = [part.strip() for part in section.split(':', 1)] - method_map.append((pattern, method)) - options_map[pattern] = dict(parser.items(section)) - - if extractors: - for idx, (pattern, method) in enumerate(method_map): - if method in extractors: - method = extractors[method] - method_map[idx] = (pattern, method) - - return (method_map, options_map) - - -def parse_keywords(strings=[]): - """Parse keywords specifications from the given list of strings. - - >>> kw = parse_keywords(['_', 'dgettext:2', 'dngettext:2,3', 'pgettext:1c,2']).items() - >>> kw.sort() - >>> for keyword, indices in kw: - ... print (keyword, indices) - ('_', None) - ('dgettext', (2,)) - ('dngettext', (2, 3)) - ('pgettext', ((1, 'c'), 2)) - """ - keywords = {} - for string in strings: - if ':' in string: - funcname, indices = string.split(':') - else: - funcname, indices = string, None - if funcname not in keywords: - if indices: - inds = [] - for x in indices.split(','): - if x[-1] == 'c': - inds.append((int(x[:-1]), 'c')) - else: - inds.append(int(x)) - indices = tuple(inds) - keywords[funcname] = indices - return keywords - - -if __name__ == '__main__': - main() diff --git a/awx/lib/site-packages/babel/messages/jslexer.py b/awx/lib/site-packages/babel/messages/jslexer.py deleted file mode 100644 index 22c6e1f9ce..0000000000 --- a/awx/lib/site-packages/babel/messages/jslexer.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.jslexer - ~~~~~~~~~~~~~~~~~~~~~~ - - A simple JavaScript 1.5 lexer which is used for the JavaScript - extractor. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -from operator import itemgetter -import re -from babel._compat import unichr - -operators = [ - '+', '-', '*', '%', '!=', '==', '<', '>', '<=', '>=', '=', - '+=', '-=', '*=', '%=', '<<', '>>', '>>>', '<<=', '>>=', - '>>>=', '&', '&=', '|', '|=', '&&', '||', '^', '^=', '(', ')', - '[', ']', '{', '}', '!', '--', '++', '~', ',', ';', '.', ':' -] -operators.sort(key=lambda a: -len(a)) - -escapes = {'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t'} - -rules = [ - (None, re.compile(r'\s+(?u)')), - (None, re.compile(r'<!--.*')), - ('linecomment', re.compile(r'//.*')), - ('multilinecomment', re.compile(r'/\*.*?\*/(?us)')), - ('name', re.compile(r'(\$+\w*|[^\W\d]\w*)(?u)')), - ('number', re.compile(r'''(?x)( - (?:0|[1-9]\d*) - (\.\d+)? - ([eE][-+]?\d+)? | - (0x[a-fA-F0-9]+) - )''')), - ('operator', re.compile(r'(%s)' % '|'.join(map(re.escape, operators)))), - ('string', re.compile(r'''(?xs)( - '(?:[^'\\]*(?:\\.[^'\\]*)*)' | - "(?:[^"\\]*(?:\\.[^"\\]*)*)" - )''')) -] - -division_re = re.compile(r'/=?') -regex_re = re.compile(r'/(?:[^/\\]*(?:\\.[^/\\]*)*)/[a-zA-Z]*(?s)') -line_re = re.compile(r'(\r\n|\n|\r)') -line_join_re = re.compile(r'\\' + line_re.pattern) -uni_escape_re = re.compile(r'[a-fA-F0-9]{1,4}') - - -class Token(tuple): - """Represents a token as returned by `tokenize`.""" - __slots__ = () - - def __new__(cls, type, value, lineno): - return tuple.__new__(cls, (type, value, lineno)) - - type = property(itemgetter(0)) - value = property(itemgetter(1)) - lineno = property(itemgetter(2)) - - -def indicates_division(token): - """A helper function that helps the tokenizer to decide if the current - token may be followed by a division operator. - """ - if token.type == 'operator': - return token.value in (')', ']', '}', '++', '--') - return token.type in ('name', 'number', 'string', 'regexp') - - -def unquote_string(string): - """Unquote a string with JavaScript rules. The string has to start with - string delimiters (``'`` or ``"``.) - """ - assert string and string[0] == string[-1] and string[0] in '"\'', \ - 'string provided is not properly delimited' - string = line_join_re.sub('\\1', string[1:-1]) - result = [] - add = result.append - pos = 0 - - while 1: - # scan for the next escape - escape_pos = string.find('\\', pos) - if escape_pos < 0: - break - add(string[pos:escape_pos]) - - # check which character is escaped - next_char = string[escape_pos + 1] - if next_char in escapes: - add(escapes[next_char]) - - # unicode escapes. trie to consume up to four characters of - # hexadecimal characters and try to interpret them as unicode - # character point. If there is no such character point, put - # all the consumed characters into the string. - elif next_char in 'uU': - escaped = uni_escape_re.match(string, escape_pos + 2) - if escaped is not None: - escaped_value = escaped.group() - if len(escaped_value) == 4: - try: - add(unichr(int(escaped_value, 16))) - except ValueError: - pass - else: - pos = escape_pos + 6 - continue - add(next_char + escaped_value) - pos = escaped.end() - continue - else: - add(next_char) - - # bogus escape. Just remove the backslash. - else: - add(next_char) - pos = escape_pos + 2 - - if pos < len(string): - add(string[pos:]) - - return u''.join(result) - - -def tokenize(source): - """Tokenize a JavaScript source. Returns a generator of tokens. - """ - may_divide = False - pos = 0 - lineno = 1 - end = len(source) - - while pos < end: - # handle regular rules first - for token_type, rule in rules: - match = rule.match(source, pos) - if match is not None: - break - # if we don't have a match we don't give up yet, but check for - # division operators or regular expression literals, based on - # the status of `may_divide` which is determined by the last - # processed non-whitespace token using `indicates_division`. - else: - if may_divide: - match = division_re.match(source, pos) - token_type = 'operator' - else: - match = regex_re.match(source, pos) - token_type = 'regexp' - if match is None: - # woops. invalid syntax. jump one char ahead and try again. - pos += 1 - continue - - token_value = match.group() - if token_type is not None: - token = Token(token_type, token_value, lineno) - may_divide = indicates_division(token) - yield token - lineno += len(line_re.findall(token_value)) - pos = match.end() diff --git a/awx/lib/site-packages/babel/messages/mofile.py b/awx/lib/site-packages/babel/messages/mofile.py deleted file mode 100644 index 5dd20aee03..0000000000 --- a/awx/lib/site-packages/babel/messages/mofile.py +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.mofile - ~~~~~~~~~~~~~~~~~~~~~ - - Writing of files in the ``gettext`` MO (machine object) format. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import array -import struct - -from babel.messages.catalog import Catalog, Message -from babel._compat import range_type - - -LE_MAGIC = 0x950412de -BE_MAGIC = 0xde120495 - - -def read_mo(fileobj): - """Read a binary MO file from the given file-like object and return a - corresponding `Catalog` object. - - :param fileobj: the file-like object to read the MO file from - - :note: The implementation of this function is heavily based on the - ``GNUTranslations._parse`` method of the ``gettext`` module in the - standard library. - """ - catalog = Catalog() - headers = {} - - filename = getattr(fileobj, 'name', '') - - buf = fileobj.read() - buflen = len(buf) - unpack = struct.unpack - - # Parse the .mo file header, which consists of 5 little endian 32 - # bit words. - magic = unpack('<I', buf[:4])[0] # Are we big endian or little endian? - if magic == LE_MAGIC: - version, msgcount, origidx, transidx = unpack('<4I', buf[4:20]) - ii = '<II' - elif magic == BE_MAGIC: - version, msgcount, origidx, transidx = unpack('>4I', buf[4:20]) - ii = '>II' - else: - raise IOError(0, 'Bad magic number', filename) - - # Now put all messages from the .mo file buffer into the catalog - # dictionary - for i in range_type(0, msgcount): - mlen, moff = unpack(ii, buf[origidx:origidx + 8]) - mend = moff + mlen - tlen, toff = unpack(ii, buf[transidx:transidx + 8]) - tend = toff + tlen - if mend < buflen and tend < buflen: - msg = buf[moff:mend] - tmsg = buf[toff:tend] - else: - raise IOError(0, 'File is corrupt', filename) - - # See if we're looking at GNU .mo conventions for metadata - if mlen == 0: - # Catalog description - lastkey = key = None - for item in tmsg.splitlines(): - item = item.strip() - if not item: - continue - if b':' in item: - key, value = item.split(b':', 1) - lastkey = key = key.strip().lower() - headers[key] = value.strip() - elif lastkey: - headers[lastkey] += b'\n' + item - - if b'\x04' in msg: # context - ctxt, msg = msg.split(b'\x04') - else: - ctxt = None - - if b'\x00' in msg: # plural forms - msg = msg.split(b'\x00') - tmsg = tmsg.split(b'\x00') - if catalog.charset: - msg = [x.decode(catalog.charset) for x in msg] - tmsg = [x.decode(catalog.charset) for x in tmsg] - else: - if catalog.charset: - msg = msg.decode(catalog.charset) - tmsg = tmsg.decode(catalog.charset) - catalog[msg] = Message(msg, tmsg, context=ctxt) - - # advance to next entry in the seek tables - origidx += 8 - transidx += 8 - - catalog.mime_headers = headers.items() - return catalog - - -def write_mo(fileobj, catalog, use_fuzzy=False): - """Write a catalog to the specified file-like object using the GNU MO file - format. - - >>> from babel.messages import Catalog - >>> from gettext import GNUTranslations - >>> from StringIO import StringIO - - >>> catalog = Catalog(locale='en_US') - >>> catalog.add('foo', 'Voh') - <Message ...> - >>> catalog.add((u'bar', u'baz'), (u'Bahr', u'Batz')) - <Message ...> - >>> catalog.add('fuz', 'Futz', flags=['fuzzy']) - <Message ...> - >>> catalog.add('Fizz', '') - <Message ...> - >>> catalog.add(('Fuzz', 'Fuzzes'), ('', '')) - <Message ...> - >>> buf = StringIO() - - >>> write_mo(buf, catalog) - >>> buf.seek(0) - >>> translations = GNUTranslations(fp=buf) - >>> translations.ugettext('foo') - u'Voh' - >>> translations.ungettext('bar', 'baz', 1) - u'Bahr' - >>> translations.ungettext('bar', 'baz', 2) - u'Batz' - >>> translations.ugettext('fuz') - u'fuz' - >>> translations.ugettext('Fizz') - u'Fizz' - >>> translations.ugettext('Fuzz') - u'Fuzz' - >>> translations.ugettext('Fuzzes') - u'Fuzzes' - - :param fileobj: the file-like object to write to - :param catalog: the `Catalog` instance - :param use_fuzzy: whether translations marked as "fuzzy" should be included - in the output - """ - messages = list(catalog) - if not use_fuzzy: - messages[1:] = [m for m in messages[1:] if not m.fuzzy] - messages.sort() - - ids = strs = b'' - offsets = [] - - for message in messages: - # For each string, we need size and file offset. Each string is NUL - # terminated; the NUL does not count into the size. - if message.pluralizable: - msgid = b'\x00'.join([ - msgid.encode(catalog.charset) for msgid in message.id - ]) - msgstrs = [] - for idx, string in enumerate(message.string): - if not string: - msgstrs.append(message.id[min(int(idx), 1)]) - else: - msgstrs.append(string) - msgstr = b'\x00'.join([ - msgstr.encode(catalog.charset) for msgstr in msgstrs - ]) - else: - msgid = message.id.encode(catalog.charset) - if not message.string: - msgstr = message.id.encode(catalog.charset) - else: - msgstr = message.string.encode(catalog.charset) - if message.context: - msgid = b'\x04'.join([message.context.encode(catalog.charset), - msgid]) - offsets.append((len(ids), len(msgid), len(strs), len(msgstr))) - ids += msgid + b'\x00' - strs += msgstr + b'\x00' - - # The header is 7 32-bit unsigned integers. We don't use hash tables, so - # the keys start right after the index tables. - keystart = 7 * 4 + 16 * len(messages) - valuestart = keystart + len(ids) - - # The string table first has the list of keys, then the list of values. - # Each entry has first the size of the string, then the file offset. - koffsets = [] - voffsets = [] - for o1, l1, o2, l2 in offsets: - koffsets += [l1, o1 + keystart] - voffsets += [l2, o2 + valuestart] - offsets = koffsets + voffsets - - fileobj.write(struct.pack('Iiiiiii', - LE_MAGIC, # magic - 0, # version - len(messages), # number of entries - 7 * 4, # start of key index - 7 * 4 + len(messages) * 8, # start of value index - 0, 0 # size and offset of hash table - ) + array.array("i", offsets).tostring() + ids + strs) diff --git a/awx/lib/site-packages/babel/messages/plurals.py b/awx/lib/site-packages/babel/messages/plurals.py deleted file mode 100644 index c00a211088..0000000000 --- a/awx/lib/site-packages/babel/messages/plurals.py +++ /dev/null @@ -1,254 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.plurals - ~~~~~~~~~~~~~~~~~~~~~~ - - Plural form definitions. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -from babel.core import default_locale, Locale -from operator import itemgetter - - -# XXX: remove this file, duplication with babel.plural - - -LC_CTYPE = default_locale('LC_CTYPE') - - -PLURALS = { - # Afar - # 'aa': (), - # Abkhazian - # 'ab': (), - # Avestan - # 'ae': (), - # Afrikaans - From Pootle's PO's - 'af': (2, '(n != 1)'), - # Akan - # 'ak': (), - # Amharic - # 'am': (), - # Aragonese - # 'an': (), - # Arabic - From Pootle's PO's - 'ar': (6, '(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n>=3 && n<=10 ? 3 : n>=11 && n<=99 ? 4 : 5)'), - # Assamese - # 'as': (), - # Avaric - # 'av': (), - # Aymara - # 'ay': (), - # Azerbaijani - # 'az': (), - # Bashkir - # 'ba': (), - # Belarusian - # 'be': (), - # Bulgarian - From Pootle's PO's - 'bg': (2, '(n != 1)'), - # Bihari - # 'bh': (), - # Bislama - # 'bi': (), - # Bambara - # 'bm': (), - # Bengali - From Pootle's PO's - 'bn': (2, '(n != 1)'), - # Tibetan - as discussed in private with Andrew West - 'bo': (1, '0'), - # Breton - # 'br': (), - # Bosnian - # 'bs': (), - # Catalan - From Pootle's PO's - 'ca': (2, '(n != 1)'), - # Chechen - # 'ce': (), - # Chamorro - # 'ch': (), - # Corsican - # 'co': (), - # Cree - # 'cr': (), - # Czech - 'cs': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Church Slavic - # 'cu': (), - # Chuvash - 'cv': (1, '0'), - # Welsh - 'cy': (5, '(n==1 ? 1 : n==2 ? 2 : n==3 ? 3 : n==6 ? 4 : 0)'), - # Danish - 'da': (2, '(n != 1)'), - # German - 'de': (2, '(n != 1)'), - # Divehi - # 'dv': (), - # Dzongkha - 'dz': (1, '0'), - # Greek - 'el': (2, '(n != 1)'), - # English - 'en': (2, '(n != 1)'), - # Esperanto - 'eo': (2, '(n != 1)'), - # Spanish - 'es': (2, '(n != 1)'), - # Estonian - 'et': (2, '(n != 1)'), - # Basque - From Pootle's PO's - 'eu': (2, '(n != 1)'), - # Persian - From Pootle's PO's - 'fa': (1, '0'), - # Finnish - 'fi': (2, '(n != 1)'), - # French - 'fr': (2, '(n > 1)'), - # Friulian - From Pootle's PO's - 'fur': (2, '(n > 1)'), - # Irish - 'ga': (3, '(n==1 ? 0 : n==2 ? 1 : 2)'), - # Galician - From Pootle's PO's - 'gl': (2, '(n != 1)'), - # Hausa - From Pootle's PO's - 'ha': (2, '(n != 1)'), - # Hebrew - 'he': (2, '(n != 1)'), - # Hindi - From Pootle's PO's - 'hi': (2, '(n != 1)'), - # Croatian - 'hr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Hungarian - 'hu': (1, '0'), - # Armenian - From Pootle's PO's - 'hy': (1, '0'), - # Icelandic - From Pootle's PO's - 'is': (2, '(n != 1)'), - # Italian - 'it': (2, '(n != 1)'), - # Japanese - 'ja': (1, '0'), - # Georgian - From Pootle's PO's - 'ka': (1, '0'), - # Kongo - From Pootle's PO's - 'kg': (2, '(n != 1)'), - # Khmer - From Pootle's PO's - 'km': (1, '0'), - # Korean - 'ko': (1, '0'), - # Kurdish - From Pootle's PO's - 'ku': (2, '(n != 1)'), - # Lao - Another member of the Tai language family, like Thai. - 'lo': (1, '0'), - # Lithuanian - 'lt': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Latvian - 'lv': (3, '(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)'), - # Maltese - From Pootle's PO's - 'mt': (4, '(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)'), - # Norwegian BokmÃ¥l - 'nb': (2, '(n != 1)'), - # Dutch - 'nl': (2, '(n != 1)'), - # Norwegian Nynorsk - 'nn': (2, '(n != 1)'), - # Norwegian - 'no': (2, '(n != 1)'), - # Punjabi - From Pootle's PO's - 'pa': (2, '(n != 1)'), - # Polish - 'pl': (3, '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Portuguese - 'pt': (2, '(n != 1)'), - # Brazilian - 'pt_BR': (2, '(n > 1)'), - # Romanian - From Pootle's PO's - 'ro': (3, '(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2)'), - # Russian - 'ru': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Slovak - 'sk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Slovenian - 'sl': (4, '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)'), - # Serbian - From Pootle's PO's - 'sr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Southern Sotho - From Pootle's PO's - 'st': (2, '(n != 1)'), - # Swedish - 'sv': (2, '(n != 1)'), - # Thai - 'th': (1, '0'), - # Turkish - 'tr': (1, '0'), - # Ukrainian - 'uk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'), - # Venda - From Pootle's PO's - 've': (2, '(n != 1)'), - # Vietnamese - From Pootle's PO's - 'vi': (1, '0'), - # Xhosa - From Pootle's PO's - 'xh': (2, '(n != 1)'), - # Chinese - From Pootle's PO's - 'zh_CN': (1, '0'), - 'zh_HK': (1, '0'), - 'zh_TW': (1, '0'), -} - - -DEFAULT_PLURAL = (2, '(n != 1)') - - -class _PluralTuple(tuple): - """A tuple with plural information.""" - - __slots__ = () - num_plurals = property(itemgetter(0), doc=""" - The number of plurals used by the locale.""") - plural_expr = property(itemgetter(1), doc=""" - The plural expression used by the locale.""") - plural_forms = property(lambda x: 'npurals=%s; plural=%s' % x, doc=""" - The plural expression used by the catalog or locale.""") - - def __str__(self): - return self.plural_forms - - -def get_plural(locale=LC_CTYPE): - """A tuple with the information catalogs need to perform proper - pluralization. The first item of the tuple is the number of plural - forms, the second the plural expression. - - >>> get_plural(locale='en') - (2, '(n != 1)') - >>> get_plural(locale='ga') - (3, '(n==1 ? 0 : n==2 ? 1 : 2)') - - The object returned is a special tuple with additional members: - - >>> tup = get_plural("ja") - >>> tup.num_plurals - 1 - >>> tup.plural_expr - '0' - >>> tup.plural_forms - 'npurals=1; plural=0' - - Converting the tuple into a string prints the plural forms for a - gettext catalog: - - >>> str(tup) - 'npurals=1; plural=0' - """ - locale = Locale.parse(locale) - try: - tup = PLURALS[str(locale)] - except KeyError: - try: - tup = PLURALS[locale.language] - except KeyError: - tup = DEFAULT_PLURAL - return _PluralTuple(tup) diff --git a/awx/lib/site-packages/babel/messages/pofile.py b/awx/lib/site-packages/babel/messages/pofile.py deleted file mode 100644 index 4aaf406f96..0000000000 --- a/awx/lib/site-packages/babel/messages/pofile.py +++ /dev/null @@ -1,474 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.messages.pofile - ~~~~~~~~~~~~~~~~~~~~~ - - Reading and writing of files in the ``gettext`` PO (portable object) - format. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import os -import re - -from babel.messages.catalog import Catalog, Message -from babel.util import wraptext -from babel._compat import text_type - - -def unescape(string): - r"""Reverse `escape` the given string. - - >>> print unescape('"Say:\\n \\"hello, world!\\"\\n"') - Say: - "hello, world!" - <BLANKLINE> - - :param string: the string to unescape - """ - def replace_escapes(match): - m = match.group(1) - if m == 'n': - return '\n' - elif m == 't': - return '\t' - elif m == 'r': - return '\r' - # m is \ or " - return m - return re.compile(r'\\([\\trn"])').sub(replace_escapes, string[1:-1]) - - -def denormalize(string): - r"""Reverse the normalization done by the `normalize` function. - - >>> print denormalize(r'''"" - ... "Say:\n" - ... " \"hello, world!\"\n"''') - Say: - "hello, world!" - <BLANKLINE> - - >>> print denormalize(r'''"" - ... "Say:\n" - ... " \"Lorem ipsum dolor sit " - ... "amet, consectetur adipisicing" - ... " elit, \"\n"''') - Say: - "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " - <BLANKLINE> - - :param string: the string to denormalize - """ - if '\n' in string: - escaped_lines = string.splitlines() - if string.startswith('""'): - escaped_lines = escaped_lines[1:] - lines = map(unescape, escaped_lines) - return ''.join(lines) - else: - return unescape(string) - - -def read_po(fileobj, locale=None, domain=None, ignore_obsolete=False, charset=None): - """Read messages from a ``gettext`` PO (portable object) file from the given - file-like object and return a `Catalog`. - - >>> from datetime import datetime - >>> from StringIO import StringIO - >>> buf = StringIO(''' - ... #: main.py:1 - ... #, fuzzy, python-format - ... msgid "foo %(name)s" - ... msgstr "quux %(name)s" - ... - ... # A user comment - ... #. An auto comment - ... #: main.py:3 - ... msgid "bar" - ... msgid_plural "baz" - ... msgstr[0] "bar" - ... msgstr[1] "baaz" - ... ''') - >>> catalog = read_po(buf) - >>> catalog.revision_date = datetime(2007, 04, 01) - - >>> for message in catalog: - ... if message.id: - ... print (message.id, message.string) - ... print ' ', (message.locations, message.flags) - ... print ' ', (message.user_comments, message.auto_comments) - (u'foo %(name)s', u'quux %(name)s') - ([(u'main.py', 1)], set([u'fuzzy', u'python-format'])) - ([], []) - ((u'bar', u'baz'), (u'bar', u'baaz')) - ([(u'main.py', 3)], set([])) - ([u'A user comment'], [u'An auto comment']) - - .. versionadded:: 1.0 - Added support for explicit charset argument. - - :param fileobj: the file-like object to read the PO file from - :param locale: the locale identifier or `Locale` object, or `None` - if the catalog is not bound to a locale (which basically - means it's a template) - :param domain: the message domain - :param ignore_obsolete: whether to ignore obsolete messages in the input - :param charset: the character set of the catalog. - """ - catalog = Catalog(locale=locale, domain=domain, charset=charset) - - counter = [0] - offset = [0] - messages = [] - translations = [] - locations = [] - flags = [] - user_comments = [] - auto_comments = [] - obsolete = [False] - context = [] - in_msgid = [False] - in_msgstr = [False] - in_msgctxt = [False] - - def _add_message(): - translations.sort() - if len(messages) > 1: - msgid = tuple([denormalize(m) for m in messages]) - else: - msgid = denormalize(messages[0]) - if isinstance(msgid, (list, tuple)): - string = [] - for idx in range(catalog.num_plurals): - try: - string.append(translations[idx]) - except IndexError: - string.append((idx, '')) - string = tuple([denormalize(t[1]) for t in string]) - else: - string = denormalize(translations[0][1]) - if context: - msgctxt = denormalize('\n'.join(context)) - else: - msgctxt = None - message = Message(msgid, string, list(locations), set(flags), - auto_comments, user_comments, lineno=offset[0] + 1, - context=msgctxt) - if obsolete[0]: - if not ignore_obsolete: - catalog.obsolete[msgid] = message - else: - catalog[msgid] = message - del messages[:]; del translations[:]; del context[:]; del locations[:]; - del flags[:]; del auto_comments[:]; del user_comments[:]; - obsolete[0] = False - counter[0] += 1 - - def _process_message_line(lineno, line): - if line.startswith('msgid_plural'): - in_msgid[0] = True - msg = line[12:].lstrip() - messages.append(msg) - elif line.startswith('msgid'): - in_msgid[0] = True - offset[0] = lineno - txt = line[5:].lstrip() - if messages: - _add_message() - messages.append(txt) - elif line.startswith('msgstr'): - in_msgid[0] = False - in_msgstr[0] = True - msg = line[6:].lstrip() - if msg.startswith('['): - idx, msg = msg[1:].split(']', 1) - translations.append([int(idx), msg.lstrip()]) - else: - translations.append([0, msg]) - elif line.startswith('msgctxt'): - if messages: - _add_message() - in_msgid[0] = in_msgstr[0] = False - context.append(line[7:].lstrip()) - elif line.startswith('"'): - if in_msgid[0]: - messages[-1] += u'\n' + line.rstrip() - elif in_msgstr[0]: - translations[-1][1] += u'\n' + line.rstrip() - elif in_msgctxt[0]: - context.append(line.rstrip()) - - for lineno, line in enumerate(fileobj.readlines()): - line = line.strip() - if not isinstance(line, text_type): - line = line.decode(catalog.charset) - if line.startswith('#'): - in_msgid[0] = in_msgstr[0] = False - if messages and translations: - _add_message() - if line[1:].startswith(':'): - for location in line[2:].lstrip().split(): - pos = location.rfind(':') - if pos >= 0: - try: - lineno = int(location[pos + 1:]) - except ValueError: - continue - locations.append((location[:pos], lineno)) - elif line[1:].startswith(','): - for flag in line[2:].lstrip().split(','): - flags.append(flag.strip()) - elif line[1:].startswith('~'): - obsolete[0] = True - _process_message_line(lineno, line[2:].lstrip()) - elif line[1:].startswith('.'): - # These are called auto-comments - comment = line[2:].strip() - if comment: # Just check that we're not adding empty comments - auto_comments.append(comment) - else: - # These are called user comments - user_comments.append(line[1:].strip()) - else: - _process_message_line(lineno, line) - - if messages: - _add_message() - - # No actual messages found, but there was some info in comments, from which - # we'll construct an empty header message - elif not counter[0] and (flags or user_comments or auto_comments): - messages.append(u'') - translations.append([0, u'']) - _add_message() - - return catalog - - -WORD_SEP = re.compile('(' - r'\s+|' # any whitespace - r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words - r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w)' # em-dash -')') - - -def escape(string): - r"""Escape the given string so that it can be included in double-quoted - strings in ``PO`` files. - - >>> escape('''Say: - ... "hello, world!" - ... ''') - '"Say:\\n \\"hello, world!\\"\\n"' - - :param string: the string to escape - """ - return '"%s"' % string.replace('\\', '\\\\') \ - .replace('\t', '\\t') \ - .replace('\r', '\\r') \ - .replace('\n', '\\n') \ - .replace('\"', '\\"') - - -def normalize(string, prefix='', width=76): - r"""Convert a string into a format that is appropriate for .po files. - - >>> print normalize('''Say: - ... "hello, world!" - ... ''', width=None) - "" - "Say:\n" - " \"hello, world!\"\n" - - >>> print normalize('''Say: - ... "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " - ... ''', width=32) - "" - "Say:\n" - " \"Lorem ipsum dolor sit " - "amet, consectetur adipisicing" - " elit, \"\n" - - :param string: the string to normalize - :param prefix: a string that should be prepended to every line - :param width: the maximum line width; use `None`, 0, or a negative number - to completely disable line wrapping - """ - if width and width > 0: - prefixlen = len(prefix) - lines = [] - for line in string.splitlines(True): - if len(escape(line)) + prefixlen > width: - chunks = WORD_SEP.split(line) - chunks.reverse() - while chunks: - buf = [] - size = 2 - while chunks: - l = len(escape(chunks[-1])) - 2 + prefixlen - if size + l < width: - buf.append(chunks.pop()) - size += l - else: - if not buf: - # handle long chunks by putting them on a - # separate line - buf.append(chunks.pop()) - break - lines.append(u''.join(buf)) - else: - lines.append(line) - else: - lines = string.splitlines(True) - - if len(lines) <= 1: - return escape(string) - - # Remove empty trailing line - if lines and not lines[-1]: - del lines[-1] - lines[-1] += '\n' - return u'""\n' + u'\n'.join([(prefix + escape(l)) for l in lines]) - - -def write_po(fileobj, catalog, width=76, no_location=False, omit_header=False, - sort_output=False, sort_by_file=False, ignore_obsolete=False, - include_previous=False): - r"""Write a ``gettext`` PO (portable object) template file for a given - message catalog to the provided file-like object. - - >>> catalog = Catalog() - >>> catalog.add(u'foo %(name)s', locations=[('main.py', 1)], - ... flags=('fuzzy',)) - <Message...> - >>> catalog.add((u'bar', u'baz'), locations=[('main.py', 3)]) - <Message...> - >>> from io import BytesIO - >>> buf = BytesIO() - >>> write_po(buf, catalog, omit_header=True) - >>> print buf.getvalue() - #: main.py:1 - #, fuzzy, python-format - msgid "foo %(name)s" - msgstr "" - <BLANKLINE> - #: main.py:3 - msgid "bar" - msgid_plural "baz" - msgstr[0] "" - msgstr[1] "" - <BLANKLINE> - <BLANKLINE> - - :param fileobj: the file-like object to write to - :param catalog: the `Catalog` instance - :param width: the maximum line width for the generated output; use `None`, - 0, or a negative number to completely disable line wrapping - :param no_location: do not emit a location comment for every message - :param omit_header: do not include the ``msgid ""`` entry at the top of the - output - :param sort_output: whether to sort the messages in the output by msgid - :param sort_by_file: whether to sort the messages in the output by their - locations - :param ignore_obsolete: whether to ignore obsolete messages and not include - them in the output; by default they are included as - comments - :param include_previous: include the old msgid as a comment when - updating the catalog - """ - def _normalize(key, prefix=''): - return normalize(key, prefix=prefix, width=width) - - def _write(text): - if isinstance(text, text_type): - text = text.encode(catalog.charset, 'backslashreplace') - fileobj.write(text) - - def _write_comment(comment, prefix=''): - # xgettext always wraps comments even if --no-wrap is passed; - # provide the same behaviour - if width and width > 0: - _width = width - else: - _width = 76 - for line in wraptext(comment, _width): - _write('#%s %s\n' % (prefix, line.strip())) - - def _write_message(message, prefix=''): - if isinstance(message.id, (list, tuple)): - if message.context: - _write('%smsgctxt %s\n' % (prefix, - _normalize(message.context, prefix))) - _write('%smsgid %s\n' % (prefix, _normalize(message.id[0], prefix))) - _write('%smsgid_plural %s\n' % ( - prefix, _normalize(message.id[1], prefix) - )) - - for idx in range(catalog.num_plurals): - try: - string = message.string[idx] - except IndexError: - string = '' - _write('%smsgstr[%d] %s\n' % ( - prefix, idx, _normalize(string, prefix) - )) - else: - if message.context: - _write('%smsgctxt %s\n' % (prefix, - _normalize(message.context, prefix))) - _write('%smsgid %s\n' % (prefix, _normalize(message.id, prefix))) - _write('%smsgstr %s\n' % ( - prefix, _normalize(message.string or '', prefix) - )) - - messages = list(catalog) - if sort_output: - messages.sort() - elif sort_by_file: - messages.sort(lambda x,y: cmp(x.locations, y.locations)) - - for message in messages: - if not message.id: # This is the header "message" - if omit_header: - continue - comment_header = catalog.header_comment - if width and width > 0: - lines = [] - for line in comment_header.splitlines(): - lines += wraptext(line, width=width, - subsequent_indent='# ') - comment_header = u'\n'.join(lines) - _write(comment_header + u'\n') - - for comment in message.user_comments: - _write_comment(comment) - for comment in message.auto_comments: - _write_comment(comment, prefix='.') - - if not no_location: - locs = u' '.join([u'%s:%d' % (filename.replace(os.sep, '/'), lineno) - for filename, lineno in message.locations]) - _write_comment(locs, prefix=':') - if message.flags: - _write('#%s\n' % ', '.join([''] + sorted(message.flags))) - - if message.previous_id and include_previous: - _write_comment('msgid %s' % _normalize(message.previous_id[0]), - prefix='|') - if len(message.previous_id) > 1: - _write_comment('msgid_plural %s' % _normalize( - message.previous_id[1] - ), prefix='|') - - _write_message(message) - _write('\n') - - if not ignore_obsolete: - for message in catalog.obsolete.values(): - for comment in message.user_comments: - _write_comment(comment) - _write_message(message, prefix='#~ ') - _write('\n') diff --git a/awx/lib/site-packages/babel/numbers.py b/awx/lib/site-packages/babel/numbers.py deleted file mode 100644 index 0f387190a7..0000000000 --- a/awx/lib/site-packages/babel/numbers.py +++ /dev/null @@ -1,626 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.numbers - ~~~~~~~~~~~~~ - - Locale dependent formatting and parsing of numeric data. - - The default locale for the functions in this module is determined by the - following environment variables, in that order: - - * ``LC_NUMERIC``, - * ``LC_ALL``, and - * ``LANG`` - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" -# TODO: -# Padding and rounding increments in pattern: -# - http://www.unicode.org/reports/tr35/ (Appendix G.6) -from decimal import Decimal, InvalidOperation -import math -import re - -from babel.core import default_locale, Locale -from babel._compat import range_type - - -LC_NUMERIC = default_locale('LC_NUMERIC') - - -def get_currency_name(currency, count=None, locale=LC_NUMERIC): - """Return the name used by the locale for the specified currency. - - >>> get_currency_name('USD', locale='en_US') - u'US Dollar' - - .. versionadded:: 0.9.4 - - :param currency: the currency code - :param count: the optional count. If provided the currency name - will be pluralized to that number if possible. - :param locale: the `Locale` object or locale identifier - """ - loc = Locale.parse(locale) - if count is not None: - plural_form = loc.plural_form(count) - plural_names = loc._data['currency_names_plural'] - if currency in plural_names: - return plural_names[currency][plural_form] - return loc.currencies.get(currency, currency) - - -def get_currency_symbol(currency, locale=LC_NUMERIC): - """Return the symbol used by the locale for the specified currency. - - >>> get_currency_symbol('USD', locale='en_US') - u'$' - - :param currency: the currency code - :param locale: the `Locale` object or locale identifier - """ - return Locale.parse(locale).currency_symbols.get(currency, currency) - - -def get_decimal_symbol(locale=LC_NUMERIC): - """Return the symbol used by the locale to separate decimal fractions. - - >>> get_decimal_symbol('en_US') - u'.' - - :param locale: the `Locale` object or locale identifier - """ - return Locale.parse(locale).number_symbols.get('decimal', u'.') - - -def get_plus_sign_symbol(locale=LC_NUMERIC): - """Return the plus sign symbol used by the current locale. - - >>> get_plus_sign_symbol('en_US') - u'+' - - :param locale: the `Locale` object or locale identifier - """ - return Locale.parse(locale).number_symbols.get('plusSign', u'+') - - -def get_minus_sign_symbol(locale=LC_NUMERIC): - """Return the plus sign symbol used by the current locale. - - >>> get_minus_sign_symbol('en_US') - u'-' - - :param locale: the `Locale` object or locale identifier - """ - return Locale.parse(locale).number_symbols.get('minusSign', u'-') - - -def get_exponential_symbol(locale=LC_NUMERIC): - """Return the symbol used by the locale to separate mantissa and exponent. - - >>> get_exponential_symbol('en_US') - u'E' - - :param locale: the `Locale` object or locale identifier - """ - return Locale.parse(locale).number_symbols.get('exponential', u'E') - - -def get_group_symbol(locale=LC_NUMERIC): - """Return the symbol used by the locale to separate groups of thousands. - - >>> get_group_symbol('en_US') - u',' - - :param locale: the `Locale` object or locale identifier - """ - return Locale.parse(locale).number_symbols.get('group', u',') - - -def format_number(number, locale=LC_NUMERIC): - u"""Return the given number formatted for a specific locale. - - >>> format_number(1099, locale='en_US') - u'1,099' - >>> format_number(1099, locale='de_DE') - u'1.099' - - - :param number: the number to format - :param locale: the `Locale` object or locale identifier - """ - # Do we really need this one? - return format_decimal(number, locale=locale) - - -def format_decimal(number, format=None, locale=LC_NUMERIC): - u"""Return the given decimal number formatted for a specific locale. - - >>> format_decimal(1.2345, locale='en_US') - u'1.234' - >>> format_decimal(1.2346, locale='en_US') - u'1.235' - >>> format_decimal(-1.2346, locale='en_US') - u'-1.235' - >>> format_decimal(1.2345, locale='sv_SE') - u'1,234' - >>> format_decimal(1.2345, locale='de') - u'1,234' - - The appropriate thousands grouping and the decimal separator are used for - each locale: - - >>> format_decimal(12345.5, locale='en_US') - u'12,345.5' - - :param number: the number to format - :param format: - :param locale: the `Locale` object or locale identifier - """ - locale = Locale.parse(locale) - if not format: - format = locale.decimal_formats.get(format) - pattern = parse_pattern(format) - return pattern.apply(number, locale) - - -def format_currency(number, currency, format=None, locale=LC_NUMERIC): - u"""Return formatted currency value. - - >>> format_currency(1099.98, 'USD', locale='en_US') - u'$1,099.98' - >>> format_currency(1099.98, 'USD', locale='es_CO') - u'1.099,98\\xa0US$' - >>> format_currency(1099.98, 'EUR', locale='de_DE') - u'1.099,98\\xa0\\u20ac' - - The pattern can also be specified explicitly. The currency is - placed with the '¤' sign. As the sign gets repeated the format - expands (¤ being the symbol, ¤¤ is the currency abbreviation and - ¤¤¤ is the full name of the currency): - - >>> format_currency(1099.98, 'EUR', u'\xa4\xa4 #,##0.00', locale='en_US') - u'EUR 1,099.98' - >>> format_currency(1099.98, 'EUR', u'#,##0.00 \xa4\xa4\xa4', locale='en_US') - u'1,099.98 euros' - - :param number: the number to format - :param currency: the currency code - :param locale: the `Locale` object or locale identifier - """ - locale = Locale.parse(locale) - if not format: - format = locale.currency_formats.get(format) - pattern = parse_pattern(format) - return pattern.apply(number, locale, currency=currency) - - -def format_percent(number, format=None, locale=LC_NUMERIC): - """Return formatted percent value for a specific locale. - - >>> format_percent(0.34, locale='en_US') - u'34%' - >>> format_percent(25.1234, locale='en_US') - u'2,512%' - >>> format_percent(25.1234, locale='sv_SE') - u'2\\xa0512\\xa0%' - - The format pattern can also be specified explicitly: - - >>> format_percent(25.1234, u'#,##0\u2030', locale='en_US') - u'25,123\u2030' - - :param number: the percent number to format - :param format: - :param locale: the `Locale` object or locale identifier - """ - locale = Locale.parse(locale) - if not format: - format = locale.percent_formats.get(format) - pattern = parse_pattern(format) - return pattern.apply(number, locale) - - -def format_scientific(number, format=None, locale=LC_NUMERIC): - """Return value formatted in scientific notation for a specific locale. - - >>> format_scientific(10000, locale='en_US') - u'1E4' - - The format pattern can also be specified explicitly: - - >>> format_scientific(1234567, u'##0E00', locale='en_US') - u'1.23E06' - - :param number: the number to format - :param format: - :param locale: the `Locale` object or locale identifier - """ - locale = Locale.parse(locale) - if not format: - format = locale.scientific_formats.get(format) - pattern = parse_pattern(format) - return pattern.apply(number, locale) - - -class NumberFormatError(ValueError): - """Exception raised when a string cannot be parsed into a number.""" - - -def parse_number(string, locale=LC_NUMERIC): - """Parse localized number string into an integer. - - >>> parse_number('1,099', locale='en_US') - 1099 - >>> parse_number('1.099', locale='de_DE') - 1099 - - When the given string cannot be parsed, an exception is raised: - - >>> parse_number('1.099,98', locale='de') - Traceback (most recent call last): - ... - NumberFormatError: '1.099,98' is not a valid number - - :param string: the string to parse - :param locale: the `Locale` object or locale identifier - :return: the parsed number - :raise `NumberFormatError`: if the string can not be converted to a number - """ - try: - return int(string.replace(get_group_symbol(locale), '')) - except ValueError: - raise NumberFormatError('%r is not a valid number' % string) - - -def parse_decimal(string, locale=LC_NUMERIC): - """Parse localized decimal string into a decimal. - - >>> parse_decimal('1,099.98', locale='en_US') - Decimal('1099.98') - >>> parse_decimal('1.099,98', locale='de') - Decimal('1099.98') - - When the given string cannot be parsed, an exception is raised: - - >>> parse_decimal('2,109,998', locale='de') - Traceback (most recent call last): - ... - NumberFormatError: '2,109,998' is not a valid decimal number - - :param string: the string to parse - :param locale: the `Locale` object or locale identifier - :raise NumberFormatError: if the string can not be converted to a - decimal number - """ - locale = Locale.parse(locale) - try: - return Decimal(string.replace(get_group_symbol(locale), '') - .replace(get_decimal_symbol(locale), '.')) - except InvalidOperation: - raise NumberFormatError('%r is not a valid decimal number' % string) - - -PREFIX_END = r'[^0-9@#.,]' -NUMBER_TOKEN = r'[0-9@#.\-,E+]' - -PREFIX_PATTERN = r"(?P<prefix>(?:'[^']*'|%s)*)" % PREFIX_END -NUMBER_PATTERN = r"(?P<number>%s+)" % NUMBER_TOKEN -SUFFIX_PATTERN = r"(?P<suffix>.*)" - -number_re = re.compile(r"%s%s%s" % (PREFIX_PATTERN, NUMBER_PATTERN, - SUFFIX_PATTERN)) - -def split_number(value): - """Convert a number into a (intasstring, fractionasstring) tuple""" - if isinstance(value, Decimal): - # NB can't just do text = str(value) as str repr of Decimal may be - # in scientific notation, e.g. for small numbers. - - sign, digits, exp = value.as_tuple() - # build list of digits in reverse order, then reverse+join - # as per http://docs.python.org/library/decimal.html#recipes - int_part = [] - frac_part = [] - - digits = list(map(str, digits)) - - # get figures after decimal point - for i in range(-exp): - # add digit if available, else 0 - if digits: - frac_part.append(digits.pop()) - else: - frac_part.append('0') - - # add in some zeroes... - for i in range(exp): - int_part.append('0') - - # and the rest - while digits: - int_part.append(digits.pop()) - - # if < 1, int_part must be set to '0' - if len(int_part) == 0: - int_part = '0', - - if sign: - int_part.append('-') - - return ''.join(reversed(int_part)), ''.join(reversed(frac_part)) - text = ('%.9f' % value).rstrip('0') - if '.' in text: - a, b = text.split('.', 1) - if b == '0': - b = '' - else: - a, b = text, '' - return a, b - - -def bankersround(value, ndigits=0): - """Round a number to a given precision. - - Works like round() except that the round-half-even (banker's rounding) - algorithm is used instead of round-half-up. - - >>> bankersround(5.5, 0) - 6.0 - >>> bankersround(6.5, 0) - 6.0 - >>> bankersround(-6.5, 0) - -6.0 - >>> bankersround(1234.0, -2) - 1200.0 - """ - sign = int(value < 0) and -1 or 1 - value = abs(value) - a, b = split_number(value) - digits = a + b - add = 0 - i = len(a) + ndigits - if i < 0 or i >= len(digits): - pass - elif digits[i] > '5': - add = 1 - elif digits[i] == '5' and digits[i-1] in '13579': - add = 1 - elif digits[i] == '5': # previous digit is even - # We round up unless all following digits are zero. - for j in range_type(i + 1, len(digits)): - if digits[j] != '0': - add = 1 - break - - scale = 10**ndigits - if isinstance(value, Decimal): - return Decimal(int(value * scale + add)) / scale * sign - else: - return float(int(value * scale + add)) / scale * sign - - -def parse_grouping(p): - """Parse primary and secondary digit grouping - - >>> parse_grouping('##') - (1000, 1000) - >>> parse_grouping('#,###') - (3, 3) - >>> parse_grouping('#,####,###') - (3, 4) - """ - width = len(p) - g1 = p.rfind(',') - if g1 == -1: - return 1000, 1000 - g1 = width - g1 - 1 - g2 = p[:-g1 - 1].rfind(',') - if g2 == -1: - return g1, g1 - g2 = width - g1 - g2 - 2 - return g1, g2 - - -def parse_pattern(pattern): - """Parse number format patterns""" - if isinstance(pattern, NumberPattern): - return pattern - - def _match_number(pattern): - rv = number_re.search(pattern) - if rv is None: - raise ValueError('Invalid number pattern %r' % pattern) - return rv.groups() - - # Do we have a negative subpattern? - if ';' in pattern: - pattern, neg_pattern = pattern.split(';', 1) - pos_prefix, number, pos_suffix = _match_number(pattern) - neg_prefix, _, neg_suffix = _match_number(neg_pattern) - else: - pos_prefix, number, pos_suffix = _match_number(pattern) - neg_prefix = '-' + pos_prefix - neg_suffix = pos_suffix - if 'E' in number: - number, exp = number.split('E', 1) - else: - exp = None - if '@' in number: - if '.' in number and '0' in number: - raise ValueError('Significant digit patterns can not contain ' - '"@" or "0"') - if '.' in number: - integer, fraction = number.rsplit('.', 1) - else: - integer = number - fraction = '' - - def parse_precision(p): - """Calculate the min and max allowed digits""" - min = max = 0 - for c in p: - if c in '@0': - min += 1 - max += 1 - elif c == '#': - max += 1 - elif c == ',': - continue - else: - break - return min, max - - int_prec = parse_precision(integer) - frac_prec = parse_precision(fraction) - if exp: - frac_prec = parse_precision(integer+fraction) - exp_plus = exp.startswith('+') - exp = exp.lstrip('+') - exp_prec = parse_precision(exp) - else: - exp_plus = None - exp_prec = None - grouping = parse_grouping(integer) - return NumberPattern(pattern, (pos_prefix, neg_prefix), - (pos_suffix, neg_suffix), grouping, - int_prec, frac_prec, - exp_prec, exp_plus) - - -class NumberPattern(object): - - def __init__(self, pattern, prefix, suffix, grouping, - int_prec, frac_prec, exp_prec, exp_plus): - self.pattern = pattern - self.prefix = prefix - self.suffix = suffix - self.grouping = grouping - self.int_prec = int_prec - self.frac_prec = frac_prec - self.exp_prec = exp_prec - self.exp_plus = exp_plus - if '%' in ''.join(self.prefix + self.suffix): - self.scale = 100 - elif u'‰' in ''.join(self.prefix + self.suffix): - self.scale = 1000 - else: - self.scale = 1 - - def __repr__(self): - return '<%s %r>' % (type(self).__name__, self.pattern) - - def apply(self, value, locale, currency=None): - if isinstance(value, float): - value = Decimal(str(value)) - value *= self.scale - is_negative = int(value < 0) - if self.exp_prec: # Scientific notation - value = abs(value) - if value: - exp = int(math.floor(math.log(value, 10))) - else: - exp = 0 - # Minimum number of integer digits - if self.int_prec[0] == self.int_prec[1]: - exp -= self.int_prec[0] - 1 - # Exponent grouping - elif self.int_prec[1]: - exp = int(exp / self.int_prec[1]) * self.int_prec[1] - if not isinstance(value, Decimal): - value = float(value) - if exp < 0: - value = value * 10**(-exp) - else: - value = value / 10**exp - exp_sign = '' - if exp < 0: - exp_sign = get_minus_sign_symbol(locale) - elif self.exp_plus: - exp_sign = get_plus_sign_symbol(locale) - exp = abs(exp) - number = u'%s%s%s%s' % \ - (self._format_sigdig(value, self.frac_prec[0], - self.frac_prec[1]), - get_exponential_symbol(locale), exp_sign, - self._format_int(str(exp), self.exp_prec[0], - self.exp_prec[1], locale)) - elif '@' in self.pattern: # Is it a siginificant digits pattern? - text = self._format_sigdig(abs(value), - self.int_prec[0], - self.int_prec[1]) - if '.' in text: - a, b = text.split('.') - a = self._format_int(a, 0, 1000, locale) - if b: - b = get_decimal_symbol(locale) + b - number = a + b - else: - number = self._format_int(text, 0, 1000, locale) - else: # A normal number pattern - a, b = split_number(bankersround(abs(value), - self.frac_prec[1])) - b = b or '0' - a = self._format_int(a, self.int_prec[0], - self.int_prec[1], locale) - b = self._format_frac(b, locale) - number = a + b - retval = u'%s%s%s' % (self.prefix[is_negative], number, - self.suffix[is_negative]) - if u'¤' in retval: - retval = retval.replace(u'¤¤¤', - get_currency_name(currency, value, locale)) - retval = retval.replace(u'¤¤', currency.upper()) - retval = retval.replace(u'¤', get_currency_symbol(currency, locale)) - return retval - - def _format_sigdig(self, value, min, max): - """Convert value to a string. - - The resulting string will contain between (min, max) number of - significant digits. - """ - a, b = split_number(value) - ndecimals = len(a) - if a == '0' and b != '': - ndecimals = 0 - while b.startswith('0'): - b = b[1:] - ndecimals -= 1 - a, b = split_number(bankersround(value, max - ndecimals)) - digits = len((a + b).lstrip('0')) - if not digits: - digits = 1 - # Figure out if we need to add any trailing '0':s - if len(a) >= max and a != '0': - return a - if digits < min: - b += ('0' * (min - digits)) - if b: - return '%s.%s' % (a, b) - return a - - def _format_int(self, value, min, max, locale): - width = len(value) - if width < min: - value = '0' * (min - width) + value - gsize = self.grouping[0] - ret = '' - symbol = get_group_symbol(locale) - while len(value) > gsize: - ret = symbol + value[-gsize:] + ret - value = value[:-gsize] - gsize = self.grouping[1] - return value + ret - - def _format_frac(self, value, locale): - min, max = self.frac_prec - if len(value) < min: - value += ('0' * (min - len(value))) - if max == 0 or (min == 0 and int(value) == 0): - return '' - width = len(value) - while len(value) > min and value[-1] == '0': - value = value[:-1] - return get_decimal_symbol(locale) + value diff --git a/awx/lib/site-packages/babel/plural.py b/awx/lib/site-packages/babel/plural.py deleted file mode 100644 index 144a0dc020..0000000000 --- a/awx/lib/site-packages/babel/plural.py +++ /dev/null @@ -1,489 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.numbers - ~~~~~~~~~~~~~ - - CLDR Plural support. See UTS #35. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import re - - -_plural_tags = ('zero', 'one', 'two', 'few', 'many', 'other') -_fallback_tag = 'other' - - -class PluralRule(object): - """Represents a set of language pluralization rules. The constructor - accepts a list of (tag, expr) tuples or a dict of CLDR rules. The - resulting object is callable and accepts one parameter with a positive or - negative number (both integer and float) for the number that indicates the - plural form for a string and returns the tag for the format: - - >>> rule = PluralRule({'one': 'n is 1'}) - >>> rule(1) - 'one' - >>> rule(2) - 'other' - - Currently the CLDR defines these tags: zero, one, two, few, many and - other where other is an implicit default. Rules should be mutually - exclusive; for a given numeric value, only one rule should apply (i.e. - the condition should only be true for one of the plural rule elements. - """ - - __slots__ = ('abstract', '_func') - - def __init__(self, rules): - """Initialize the rule instance. - - :param rules: a list of ``(tag, expr)``) tuples with the rules - conforming to UTS #35 or a dict with the tags as keys - and expressions as values. - :raise RuleError: if the expression is malformed - """ - if isinstance(rules, dict): - rules = rules.items() - found = set() - self.abstract = [] - for key, expr in sorted(list(rules)): - if key not in _plural_tags: - raise ValueError('unknown tag %r' % key) - elif key in found: - raise ValueError('tag %r defined twice' % key) - found.add(key) - self.abstract.append((key, _Parser(expr).ast)) - - def __repr__(self): - rules = self.rules - return '<%s %r>' % ( - type(self).__name__, - ', '.join(['%s: %s' % (tag, rules[tag]) for tag in _plural_tags - if tag in rules]) - ) - - @classmethod - def parse(cls, rules): - """Create a `PluralRule` instance for the given rules. If the rules - are a `PluralRule` object, that object is returned. - - :param rules: the rules as list or dict, or a `PluralRule` object - :raise RuleError: if the expression is malformed - """ - if isinstance(rules, cls): - return rules - return cls(rules) - - @property - def rules(self): - """The `PluralRule` as a dict of unicode plural rules. - - >>> rule = PluralRule({'one': 'n is 1'}) - >>> rule.rules - {'one': 'n is 1'} - """ - _compile = _UnicodeCompiler().compile - return dict([(tag, _compile(ast)) for tag, ast in self.abstract]) - - tags = property(lambda x: frozenset([i[0] for i in x.abstract]), doc=""" - A set of explicitly defined tags in this rule. The implicit default - ``'other'`` rules is not part of this set unless there is an explicit - rule for it.""") - - def __getstate__(self): - return self.abstract - - def __setstate__(self, abstract): - self.abstract = abstract - - def __call__(self, n): - if not hasattr(self, '_func'): - self._func = to_python(self) - return self._func(n) - - -def to_javascript(rule): - """Convert a list/dict of rules or a `PluralRule` object into a JavaScript - function. This function depends on no external library: - - >>> to_javascript({'one': 'n is 1'}) - "(function(n) { return (n == 1) ? 'one' : 'other'; })" - - Implementation detail: The function generated will probably evaluate - expressions involved into range operations multiple times. This has the - advantage that external helper functions are not required and is not a - big performance hit for these simple calculations. - - :param rule: the rules as list or dict, or a `PluralRule` object - :raise RuleError: if the expression is malformed - """ - to_js = _JavaScriptCompiler().compile - result = ['(function(n) { return '] - for tag, ast in PluralRule.parse(rule).abstract: - result.append('%s ? %r : ' % (to_js(ast), tag)) - result.append('%r; })' % _fallback_tag) - return ''.join(result) - - -def to_python(rule): - """Convert a list/dict of rules or a `PluralRule` object into a regular - Python function. This is useful in situations where you need a real - function and don't are about the actual rule object: - - >>> func = to_python({'one': 'n is 1', 'few': 'n in 2..4'}) - >>> func(1) - 'one' - >>> func(3) - 'few' - >>> func = to_python({'one': 'n in 1,11', 'few': 'n in 3..10,13..19'}) - >>> func(11) - 'one' - >>> func(15) - 'few' - - :param rule: the rules as list or dict, or a `PluralRule` object - :raise RuleError: if the expression is malformed - """ - namespace = { - 'IN': in_range_list, - 'WITHIN': within_range_list, - 'MOD': cldr_modulo - } - to_python = _PythonCompiler().compile - result = ['def evaluate(n):'] - for tag, ast in PluralRule.parse(rule).abstract: - # the str() call is to coerce the tag to the native string. It's - # a limited ascii restricted set of tags anyways so that is fine. - result.append(' if (%s): return %r' % (to_python(ast), str(tag))) - result.append(' return %r' % _fallback_tag) - code = compile('\n'.join(result), '<rule>', 'exec') - eval(code, namespace) - return namespace['evaluate'] - - -def to_gettext(rule): - """The plural rule as gettext expression. The gettext expression is - technically limited to integers and returns indices rather than tags. - - >>> to_gettext({'one': 'n is 1', 'two': 'n is 2'}) - 'nplurals=3; plural=((n == 1) ? 0 : (n == 2) ? 1 : 2)' - - :param rule: the rules as list or dict, or a `PluralRule` object - :raise RuleError: if the expression is malformed - """ - rule = PluralRule.parse(rule) - - used_tags = rule.tags | set([_fallback_tag]) - _compile = _GettextCompiler().compile - _get_index = [tag for tag in _plural_tags if tag in used_tags].index - - result = ['nplurals=%d; plural=(' % len(used_tags)] - for tag, ast in rule.abstract: - result.append('%s ? %d : ' % (_compile(ast), _get_index(tag))) - result.append('%d)' % _get_index(_fallback_tag)) - return ''.join(result) - - -def in_range_list(num, range_list): - """Integer range list test. This is the callback for the "in" operator - of the UTS #35 pluralization rule language: - - >>> in_range_list(1, [(1, 3)]) - True - >>> in_range_list(3, [(1, 3)]) - True - >>> in_range_list(3, [(1, 3), (5, 8)]) - True - >>> in_range_list(1.2, [(1, 4)]) - False - >>> in_range_list(10, [(1, 4)]) - False - >>> in_range_list(10, [(1, 4), (6, 8)]) - False - """ - return num == int(num) and within_range_list(num, range_list) - - -def within_range_list(num, range_list): - """Float range test. This is the callback for the "within" operator - of the UTS #35 pluralization rule language: - - >>> within_range_list(1, [(1, 3)]) - True - >>> within_range_list(1.0, [(1, 3)]) - True - >>> within_range_list(1.2, [(1, 4)]) - True - >>> within_range_list(8.8, [(1, 4), (7, 15)]) - True - >>> within_range_list(10, [(1, 4)]) - False - >>> within_range_list(10.5, [(1, 4), (20, 30)]) - False - """ - return any(num >= min_ and num <= max_ for min_, max_ in range_list) - - -def cldr_modulo(a, b): - """Javaish modulo. This modulo operator returns the value with the sign - of the dividend rather than the divisor like Python does: - - >>> cldr_modulo(-3, 5) - -3 - >>> cldr_modulo(-3, -5) - -3 - >>> cldr_modulo(3, 5) - 3 - """ - reverse = 0 - if a < 0: - a *= -1 - reverse = 1 - if b < 0: - b *= -1 - rv = a % b - if reverse: - rv *= -1 - return rv - - -class RuleError(Exception): - """Raised if a rule is malformed.""" - - -class _Parser(object): - """Internal parser. This class can translate a single rule into an abstract - tree of tuples. It implements the following grammar:: - - condition = and_condition ('or' and_condition)* - and_condition = relation ('and' relation)* - relation = is_relation | in_relation | within_relation | 'n' <EOL> - is_relation = expr 'is' ('not')? value - in_relation = expr ('not')? 'in' range_list - within_relation = expr ('not')? 'within' range_list - expr = 'n' ('mod' value)? - range_list = (range | value) (',' range_list)* - value = digit+ - digit = 0|1|2|3|4|5|6|7|8|9 - range = value'..'value - - - Whitespace can occur between or around any of the above tokens. - - Rules should be mutually exclusive; for a given numeric value, only one - rule should apply (i.e. the condition should only be true for one of - the plural rule elements). - - The in and within relations can take comma-separated lists, such as: - 'n in 3,5,7..15'. - - The translator parses the expression on instanciation into an attribute - called `ast`. - """ - - _rules = [ - (None, re.compile(r'\s+(?u)')), - ('word', re.compile(r'\b(and|or|is|(?:with)?in|not|mod|n)\b')), - ('value', re.compile(r'\d+')), - ('comma', re.compile(r',')), - ('ellipsis', re.compile(r'\.\.')) - ] - - def __init__(self, string): - string = string.lower() - result = [] - pos = 0 - end = len(string) - while pos < end: - for tok, rule in self._rules: - match = rule.match(string, pos) - if match is not None: - pos = match.end() - if tok: - result.append((tok, match.group())) - break - else: - raise RuleError('malformed CLDR pluralization rule. ' - 'Got unexpected %r' % string[pos]) - self.tokens = result[::-1] - - self.ast = self.condition() - if self.tokens: - raise RuleError('Expected end of rule, got %r' % - self.tokens[-1][1]) - - def test(self, type, value=None): - return self.tokens and self.tokens[-1][0] == type and \ - (value is None or self.tokens[-1][1] == value) - - def skip(self, type, value=None): - if self.test(type, value): - return self.tokens.pop() - - def expect(self, type, value=None, term=None): - token = self.skip(type, value) - if token is not None: - return token - if term is None: - term = repr(value is None and type or value) - if not self.tokens: - raise RuleError('expected %s but end of rule reached' % term) - raise RuleError('expected %s but got %r' % (term, self.tokens[-1][1])) - - def condition(self): - op = self.and_condition() - while self.skip('word', 'or'): - op = 'or', (op, self.and_condition()) - return op - - def and_condition(self): - op = self.relation() - while self.skip('word', 'and'): - op = 'and', (op, self.relation()) - return op - - def relation(self): - left = self.expr() - if self.skip('word', 'is'): - return self.skip('word', 'not') and 'isnot' or 'is', \ - (left, self.value()) - negated = self.skip('word', 'not') - method = 'in' - if self.skip('word', 'within'): - method = 'within' - else: - self.expect('word', 'in', term="'within' or 'in'") - rv = 'relation', (method, left, self.range_list()) - if negated: - rv = 'not', (rv,) - return rv - - def range_or_value(self): - left = self.value() - if self.skip('ellipsis'): - return((left, self.value())) - else: - return((left, left)) - - def range_list(self): - range_list = [self.range_or_value()] - while self.skip('comma'): - range_list.append(self.range_or_value()) - return 'range_list', range_list - - def expr(self): - self.expect('word', 'n') - if self.skip('word', 'mod'): - return 'mod', (('n', ()), self.value()) - return 'n', () - - def value(self): - return 'value', (int(self.expect('value')[1]),) - - -def _binary_compiler(tmpl): - """Compiler factory for the `_Compiler`.""" - return lambda self, l, r: tmpl % (self.compile(l), self.compile(r)) - - -def _unary_compiler(tmpl): - """Compiler factory for the `_Compiler`.""" - return lambda self, x: tmpl % self.compile(x) - - -class _Compiler(object): - """The compilers are able to transform the expressions into multiple - output formats. - """ - - def compile(self, arg): - op, args = arg - return getattr(self, 'compile_' + op)(*args) - - compile_n = lambda x: 'n' - compile_value = lambda x, v: str(v) - compile_and = _binary_compiler('(%s && %s)') - compile_or = _binary_compiler('(%s || %s)') - compile_not = _unary_compiler('(!%s)') - compile_mod = _binary_compiler('(%s %% %s)') - compile_is = _binary_compiler('(%s == %s)') - compile_isnot = _binary_compiler('(%s != %s)') - - def compile_relation(self, method, expr, range_list): - raise NotImplementedError() - - -class _PythonCompiler(_Compiler): - """Compiles an expression to Python.""" - - compile_and = _binary_compiler('(%s and %s)') - compile_or = _binary_compiler('(%s or %s)') - compile_not = _unary_compiler('(not %s)') - compile_mod = _binary_compiler('MOD(%s, %s)') - - def compile_relation(self, method, expr, range_list): - compile_range_list = '[%s]' % ','.join( - ['(%s, %s)' % tuple(map(self.compile, range_)) - for range_ in range_list[1]]) - return '%s(%s, %s)' % (method.upper(), self.compile(expr), - compile_range_list) - - -class _GettextCompiler(_Compiler): - """Compile into a gettext plural expression.""" - - def compile_relation(self, method, expr, range_list): - rv = [] - expr = self.compile(expr) - for item in range_list[1]: - if item[0] == item[1]: - rv.append('(%s == %s)' % ( - expr, - self.compile(item[0]) - )) - else: - min, max = map(self.compile, item) - rv.append('(%s >= %s && %s <= %s)' % ( - expr, - min, - expr, - max - )) - return '(%s)' % ' || '.join(rv) - - -class _JavaScriptCompiler(_GettextCompiler): - """Compiles the expression to plain of JavaScript.""" - - def compile_relation(self, method, expr, range_list): - code = _GettextCompiler.compile_relation( - self, method, expr, range_list) - if method == 'in': - expr = self.compile(expr) - code = '(parseInt(%s) == %s && %s)' % (expr, expr, code) - return code - - -class _UnicodeCompiler(_Compiler): - """Returns a unicode pluralization rule again.""" - - compile_is = _binary_compiler('%s is %s') - compile_isnot = _binary_compiler('%s is not %s') - compile_and = _binary_compiler('%s and %s') - compile_or = _binary_compiler('%s or %s') - compile_mod = _binary_compiler('%s mod %s') - - def compile_not(self, relation): - return self.compile_relation(negated=True, *relation[1]) - - def compile_relation(self, method, expr, range_list, negated=False): - ranges = [] - for item in range_list[1]: - if item[0] == item[1]: - ranges.append(self.compile(item[0])) - else: - ranges.append('%s..%s' % tuple(map(self.compile, item))) - return '%s%s %s %s' % ( - self.compile(expr), negated and ' not' or '', - method, ','.join(ranges) - ) diff --git a/awx/lib/site-packages/babel/support.py b/awx/lib/site-packages/babel/support.py deleted file mode 100644 index c720c747cd..0000000000 --- a/awx/lib/site-packages/babel/support.py +++ /dev/null @@ -1,592 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.support - ~~~~~~~~~~~~~ - - Several classes and functions that help with integrating and using Babel - in applications. - - .. note: the code in this module is not used by Babel itself - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import gettext -import locale - -from babel.core import Locale -from babel.dates import format_date, format_datetime, format_time, \ - format_timedelta -from babel.numbers import format_number, format_decimal, format_currency, \ - format_percent, format_scientific -from babel._compat import PY2, text_type, text_to_native - - -class Format(object): - """Wrapper class providing the various date and number formatting functions - bound to a specific locale and time-zone. - - >>> from babel.util import UTC - >>> from datetime import date - >>> fmt = Format('en_US', UTC) - >>> fmt.date(date(2007, 4, 1)) - u'Apr 1, 2007' - >>> fmt.decimal(1.2345) - u'1.234' - """ - - def __init__(self, locale, tzinfo=None): - """Initialize the formatter. - - :param locale: the locale identifier or `Locale` instance - :param tzinfo: the time-zone info (a `tzinfo` instance or `None`) - """ - self.locale = Locale.parse(locale) - self.tzinfo = tzinfo - - def date(self, date=None, format='medium'): - """Return a date formatted according to the given pattern. - - >>> from datetime import date - >>> fmt = Format('en_US') - >>> fmt.date(date(2007, 4, 1)) - u'Apr 1, 2007' - """ - return format_date(date, format, locale=self.locale) - - def datetime(self, datetime=None, format='medium'): - """Return a date and time formatted according to the given pattern. - - >>> from datetime import datetime - >>> from pytz import timezone - >>> fmt = Format('en_US', tzinfo=timezone('US/Eastern')) - >>> fmt.datetime(datetime(2007, 4, 1, 15, 30)) - u'Apr 1, 2007, 11:30:00 AM' - """ - return format_datetime(datetime, format, tzinfo=self.tzinfo, - locale=self.locale) - - def time(self, time=None, format='medium'): - """Return a time formatted according to the given pattern. - - >>> from datetime import datetime - >>> from pytz import timezone - >>> fmt = Format('en_US', tzinfo=timezone('US/Eastern')) - >>> fmt.time(datetime(2007, 4, 1, 15, 30)) - u'11:30:00 AM' - """ - return format_time(time, format, tzinfo=self.tzinfo, locale=self.locale) - - def timedelta(self, delta, granularity='second', threshold=.85, - format='medium', add_direction=False): - """Return a time delta according to the rules of the given locale. - - >>> from datetime import timedelta - >>> fmt = Format('en_US') - >>> fmt.timedelta(timedelta(weeks=11)) - u'3 months' - """ - return format_timedelta(delta, granularity=granularity, - threshold=threshold, - format=format, add_direction=add_direction, - locale=self.locale) - - def number(self, number): - """Return an integer number formatted for the locale. - - >>> fmt = Format('en_US') - >>> fmt.number(1099) - u'1,099' - """ - return format_number(number, locale=self.locale) - - def decimal(self, number, format=None): - """Return a decimal number formatted for the locale. - - >>> fmt = Format('en_US') - >>> fmt.decimal(1.2345) - u'1.234' - """ - return format_decimal(number, format, locale=self.locale) - - def currency(self, number, currency): - """Return a number in the given currency formatted for the locale. - """ - return format_currency(number, currency, locale=self.locale) - - def percent(self, number, format=None): - """Return a number formatted as percentage for the locale. - - >>> fmt = Format('en_US') - >>> fmt.percent(0.34) - u'34%' - """ - return format_percent(number, format, locale=self.locale) - - def scientific(self, number): - """Return a number formatted using scientific notation for the locale. - """ - return format_scientific(number, locale=self.locale) - - -class LazyProxy(object): - """Class for proxy objects that delegate to a specified function to evaluate - the actual object. - - >>> def greeting(name='world'): - ... return 'Hello, %s!' % name - >>> lazy_greeting = LazyProxy(greeting, name='Joe') - >>> print lazy_greeting - Hello, Joe! - >>> u' ' + lazy_greeting - u' Hello, Joe!' - >>> u'(%s)' % lazy_greeting - u'(Hello, Joe!)' - - This can be used, for example, to implement lazy translation functions that - delay the actual translation until the string is actually used. The - rationale for such behavior is that the locale of the user may not always - be available. In web applications, you only know the locale when processing - a request. - - The proxy implementation attempts to be as complete as possible, so that - the lazy objects should mostly work as expected, for example for sorting: - - >>> greetings = [ - ... LazyProxy(greeting, 'world'), - ... LazyProxy(greeting, 'Joe'), - ... LazyProxy(greeting, 'universe'), - ... ] - >>> greetings.sort() - >>> for greeting in greetings: - ... print greeting - Hello, Joe! - Hello, universe! - Hello, world! - """ - __slots__ = ['_func', '_args', '_kwargs', '_value', '_is_cache_enabled'] - - def __init__(self, func, *args, **kwargs): - is_cache_enabled = kwargs.pop('enable_cache', True) - # Avoid triggering our own __setattr__ implementation - object.__setattr__(self, '_func', func) - object.__setattr__(self, '_args', args) - object.__setattr__(self, '_kwargs', kwargs) - object.__setattr__(self, '_is_cache_enabled', is_cache_enabled) - object.__setattr__(self, '_value', None) - - @property - def value(self): - if self._value is None: - value = self._func(*self._args, **self._kwargs) - if not self._is_cache_enabled: - return value - object.__setattr__(self, '_value', value) - return self._value - - def __contains__(self, key): - return key in self.value - - def __nonzero__(self): - return bool(self.value) - - def __dir__(self): - return dir(self.value) - - def __iter__(self): - return iter(self.value) - - def __len__(self): - return len(self.value) - - def __str__(self): - return str(self.value) - - def __unicode__(self): - return unicode(self.value) - - def __add__(self, other): - return self.value + other - - def __radd__(self, other): - return other + self.value - - def __mod__(self, other): - return self.value % other - - def __rmod__(self, other): - return other % self.value - - def __mul__(self, other): - return self.value * other - - def __rmul__(self, other): - return other * self.value - - def __call__(self, *args, **kwargs): - return self.value(*args, **kwargs) - - def __lt__(self, other): - return self.value < other - - def __le__(self, other): - return self.value <= other - - def __eq__(self, other): - return self.value == other - - def __ne__(self, other): - return self.value != other - - def __gt__(self, other): - return self.value > other - - def __ge__(self, other): - return self.value >= other - - def __delattr__(self, name): - delattr(self.value, name) - - def __getattr__(self, name): - return getattr(self.value, name) - - def __setattr__(self, name, value): - setattr(self.value, name, value) - - def __delitem__(self, key): - del self.value[key] - - def __getitem__(self, key): - return self.value[key] - - def __setitem__(self, key, value): - self.value[key] = value - - -class NullTranslations(gettext.NullTranslations, object): - - DEFAULT_DOMAIN = None - - def __init__(self, fp=None): - """Initialize a simple translations class which is not backed by a - real catalog. Behaves similar to gettext.NullTranslations but also - offers Babel's on *gettext methods (e.g. 'dgettext()'). - - :param fp: a file-like object (ignored in this class) - """ - # These attributes are set by gettext.NullTranslations when a catalog - # is parsed (fp != None). Ensure that they are always present because - # some *gettext methods (including '.gettext()') rely on the attributes. - self._catalog = {} - self.plural = lambda n: int(n != 1) - super(NullTranslations, self).__init__(fp=fp) - self.files = filter(None, [getattr(fp, 'name', None)]) - self.domain = self.DEFAULT_DOMAIN - self._domains = {} - - def dgettext(self, domain, message): - """Like ``gettext()``, but look the message up in the specified - domain. - """ - return self._domains.get(domain, self).gettext(message) - - def ldgettext(self, domain, message): - """Like ``lgettext()``, but look the message up in the specified - domain. - """ - return self._domains.get(domain, self).lgettext(message) - - def udgettext(self, domain, message): - """Like ``ugettext()``, but look the message up in the specified - domain. - """ - return self._domains.get(domain, self).ugettext(message) - # backward compatibility with 0.9 - dugettext = udgettext - - def dngettext(self, domain, singular, plural, num): - """Like ``ngettext()``, but look the message up in the specified - domain. - """ - return self._domains.get(domain, self).ngettext(singular, plural, num) - - def ldngettext(self, domain, singular, plural, num): - """Like ``lngettext()``, but look the message up in the specified - domain. - """ - return self._domains.get(domain, self).lngettext(singular, plural, num) - - def udngettext(self, domain, singular, plural, num): - """Like ``ungettext()`` but look the message up in the specified - domain. - """ - return self._domains.get(domain, self).ungettext(singular, plural, num) - # backward compatibility with 0.9 - dungettext = udngettext - - # Most of the downwards code, until it get's included in stdlib, from: - # http://bugs.python.org/file10036/gettext-pgettext.patch - # - # The encoding of a msgctxt and a msgid in a .mo file is - # msgctxt + "\x04" + msgid (gettext version >= 0.15) - CONTEXT_ENCODING = '%s\x04%s' - - def pgettext(self, context, message): - """Look up the `context` and `message` id in the catalog and return the - corresponding message string, as an 8-bit string encoded with the - catalog's charset encoding, if known. If there is no entry in the - catalog for the `message` id and `context` , and a fallback has been - set, the look up is forwarded to the fallback's ``pgettext()`` - method. Otherwise, the `message` id is returned. - """ - ctxt_msg_id = self.CONTEXT_ENCODING % (context, message) - missing = object() - tmsg = self._catalog.get(ctxt_msg_id, missing) - if tmsg is missing: - if self._fallback: - return self._fallback.pgettext(context, message) - return message - # Encode the Unicode tmsg back to an 8-bit string, if possible - if self._output_charset: - return text_to_native(tmsg, self._output_charset) - elif self._charset: - return text_to_native(tmsg, self._charset) - return tmsg - - def lpgettext(self, context, message): - """Equivalent to ``pgettext()``, but the translation is returned in the - preferred system encoding, if no other encoding was explicitly set with - ``bind_textdomain_codeset()``. - """ - ctxt_msg_id = self.CONTEXT_ENCODING % (context, message) - missing = object() - tmsg = self._catalog.get(ctxt_msg_id, missing) - if tmsg is missing: - if self._fallback: - return self._fallback.lpgettext(context, message) - return message - if self._output_charset: - return tmsg.encode(self._output_charset) - return tmsg.encode(locale.getpreferredencoding()) - - def npgettext(self, context, singular, plural, num): - """Do a plural-forms lookup of a message id. `singular` is used as the - message id for purposes of lookup in the catalog, while `num` is used to - determine which plural form to use. The returned message string is an - 8-bit string encoded with the catalog's charset encoding, if known. - - If the message id for `context` is not found in the catalog, and a - fallback is specified, the request is forwarded to the fallback's - ``npgettext()`` method. Otherwise, when ``num`` is 1 ``singular`` is - returned, and ``plural`` is returned in all other cases. - """ - ctxt_msg_id = self.CONTEXT_ENCODING % (context, singular) - try: - tmsg = self._catalog[(ctxt_msg_id, self.plural(num))] - if self._output_charset: - return text_to_native(tmsg, self._output_charset) - elif self._charset: - return text_to_native(tmsg, self._charset) - return tmsg - except KeyError: - if self._fallback: - return self._fallback.npgettext(context, singular, plural, num) - if num == 1: - return singular - else: - return plural - - def lnpgettext(self, context, singular, plural, num): - """Equivalent to ``npgettext()``, but the translation is returned in the - preferred system encoding, if no other encoding was explicitly set with - ``bind_textdomain_codeset()``. - """ - ctxt_msg_id = self.CONTEXT_ENCODING % (context, singular) - try: - tmsg = self._catalog[(ctxt_msg_id, self.plural(num))] - if self._output_charset: - return tmsg.encode(self._output_charset) - return tmsg.encode(locale.getpreferredencoding()) - except KeyError: - if self._fallback: - return self._fallback.lnpgettext(context, singular, plural, num) - if num == 1: - return singular - else: - return plural - - def upgettext(self, context, message): - """Look up the `context` and `message` id in the catalog and return the - corresponding message string, as a Unicode string. If there is no entry - in the catalog for the `message` id and `context`, and a fallback has - been set, the look up is forwarded to the fallback's ``upgettext()`` - method. Otherwise, the `message` id is returned. - """ - ctxt_message_id = self.CONTEXT_ENCODING % (context, message) - missing = object() - tmsg = self._catalog.get(ctxt_message_id, missing) - if tmsg is missing: - if self._fallback: - return self._fallback.upgettext(context, message) - return text_type(message) - return tmsg - - def unpgettext(self, context, singular, plural, num): - """Do a plural-forms lookup of a message id. `singular` is used as the - message id for purposes of lookup in the catalog, while `num` is used to - determine which plural form to use. The returned message string is a - Unicode string. - - If the message id for `context` is not found in the catalog, and a - fallback is specified, the request is forwarded to the fallback's - ``unpgettext()`` method. Otherwise, when `num` is 1 `singular` is - returned, and `plural` is returned in all other cases. - """ - ctxt_message_id = self.CONTEXT_ENCODING % (context, singular) - try: - tmsg = self._catalog[(ctxt_message_id, self.plural(num))] - except KeyError: - if self._fallback: - return self._fallback.unpgettext(context, singular, plural, num) - if num == 1: - tmsg = text_type(singular) - else: - tmsg = text_type(plural) - return tmsg - - def dpgettext(self, domain, context, message): - """Like `pgettext()`, but look the message up in the specified - `domain`. - """ - return self._domains.get(domain, self).pgettext(context, message) - - def udpgettext(self, domain, context, message): - """Like `upgettext()`, but look the message up in the specified - `domain`. - """ - return self._domains.get(domain, self).upgettext(context, message) - # backward compatibility with 0.9 - dupgettext = udpgettext - - def ldpgettext(self, domain, context, message): - """Equivalent to ``dpgettext()``, but the translation is returned in the - preferred system encoding, if no other encoding was explicitly set with - ``bind_textdomain_codeset()``. - """ - return self._domains.get(domain, self).lpgettext(context, message) - - def dnpgettext(self, domain, context, singular, plural, num): - """Like ``npgettext``, but look the message up in the specified - `domain`. - """ - return self._domains.get(domain, self).npgettext(context, singular, - plural, num) - - def udnpgettext(self, domain, context, singular, plural, num): - """Like ``unpgettext``, but look the message up in the specified - `domain`. - """ - return self._domains.get(domain, self).unpgettext(context, singular, - plural, num) - # backward compatibility with 0.9 - dunpgettext = udnpgettext - - def ldnpgettext(self, domain, context, singular, plural, num): - """Equivalent to ``dnpgettext()``, but the translation is returned in - the preferred system encoding, if no other encoding was explicitly set - with ``bind_textdomain_codeset()``. - """ - return self._domains.get(domain, self).lnpgettext(context, singular, - plural, num) - - if not PY2: - ugettext = gettext.NullTranslations.gettext - ungettext = gettext.NullTranslations.ngettext - - -class Translations(NullTranslations, gettext.GNUTranslations): - """An extended translation catalog class.""" - - DEFAULT_DOMAIN = 'messages' - - def __init__(self, fp=None, domain=None): - """Initialize the translations catalog. - - :param fp: the file-like object the translation should be read from - :param domain: the message domain (default: 'messages') - """ - super(Translations, self).__init__(fp=fp) - self.domain = domain or self.DEFAULT_DOMAIN - - if not PY2: - ugettext = gettext.GNUTranslations.gettext - ungettext = gettext.GNUTranslations.ngettext - - @classmethod - def load(cls, dirname=None, locales=None, domain=None): - """Load translations from the given directory. - - :param dirname: the directory containing the ``MO`` files - :param locales: the list of locales in order of preference (items in - this list can be either `Locale` objects or locale - strings) - :param domain: the message domain (default: 'messages') - """ - if locales is not None: - if not isinstance(locales, (list, tuple)): - locales = [locales] - locales = [str(locale) for locale in locales] - if not domain: - domain = cls.DEFAULT_DOMAIN - filename = gettext.find(domain, dirname, locales) - if not filename: - return NullTranslations() - with open(filename, 'rb') as fp: - return cls(fp=fp, domain=domain) - - def __repr__(self): - return '<%s: "%s">' % (type(self).__name__, - self._info.get('project-id-version')) - - def add(self, translations, merge=True): - """Add the given translations to the catalog. - - If the domain of the translations is different than that of the - current catalog, they are added as a catalog that is only accessible - by the various ``d*gettext`` functions. - - :param translations: the `Translations` instance with the messages to - add - :param merge: whether translations for message domains that have - already been added should be merged with the existing - translations - """ - domain = getattr(translations, 'domain', self.DEFAULT_DOMAIN) - if merge and domain == self.domain: - return self.merge(translations) - - existing = self._domains.get(domain) - if merge and existing is not None: - existing.merge(translations) - else: - translations.add_fallback(self) - self._domains[domain] = translations - - return self - - def merge(self, translations): - """Merge the given translations into the catalog. - - Message translations in the specified catalog override any messages - with the same identifier in the existing catalog. - - :param translations: the `Translations` instance with the messages to - merge - """ - if isinstance(translations, gettext.GNUTranslations): - self._catalog.update(translations._catalog) - if isinstance(translations, Translations): - self.files.extend(translations.files) - - return self diff --git a/awx/lib/site-packages/babel/util.py b/awx/lib/site-packages/babel/util.py deleted file mode 100644 index f46ee2b707..0000000000 --- a/awx/lib/site-packages/babel/util.py +++ /dev/null @@ -1,289 +0,0 @@ -# -*- coding: utf-8 -*- -""" - babel.util - ~~~~~~~~~~ - - Various utility classes and functions. - - :copyright: (c) 2013 by the Babel Team. - :license: BSD, see LICENSE for more details. -""" - -import codecs -from datetime import timedelta, tzinfo -import os -import re -import textwrap -from babel._compat import izip, imap - -missing = object() - - -def distinct(iterable): - """Yield all items in an iterable collection that are distinct. - - Unlike when using sets for a similar effect, the original ordering of the - items in the collection is preserved by this function. - - >>> print list(distinct([1, 2, 1, 3, 4, 4])) - [1, 2, 3, 4] - >>> print list(distinct('foobar')) - ['f', 'o', 'b', 'a', 'r'] - - :param iterable: the iterable collection providing the data - """ - seen = set() - for item in iter(iterable): - if item not in seen: - yield item - seen.add(item) - -# Regexp to match python magic encoding line -PYTHON_MAGIC_COMMENT_re = re.compile( - br'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)', re.VERBOSE) -def parse_encoding(fp): - """Deduce the encoding of a source file from magic comment. - - It does this in the same way as the `Python interpreter`__ - - .. __: http://docs.python.org/ref/encodings.html - - The ``fp`` argument should be a seekable file object. - - (From Jeff Dairiki) - """ - pos = fp.tell() - fp.seek(0) - try: - line1 = fp.readline() - has_bom = line1.startswith(codecs.BOM_UTF8) - if has_bom: - line1 = line1[len(codecs.BOM_UTF8):] - - m = PYTHON_MAGIC_COMMENT_re.match(line1) - if not m: - try: - import parser - parser.suite(line1.decode('latin-1')) - except (ImportError, SyntaxError): - # Either it's a real syntax error, in which case the source is - # not valid python source, or line2 is a continuation of line1, - # in which case we don't want to scan line2 for a magic - # comment. - pass - else: - line2 = fp.readline() - m = PYTHON_MAGIC_COMMENT_re.match(line2) - - if has_bom: - if m: - raise SyntaxError( - "python refuses to compile code with both a UTF8 " - "byte-order-mark and a magic encoding comment") - return 'utf_8' - elif m: - return m.group(1).decode('latin-1') - else: - return None - finally: - fp.seek(pos) - -def pathmatch(pattern, filename): - """Extended pathname pattern matching. - - This function is similar to what is provided by the ``fnmatch`` module in - the Python standard library, but: - - * can match complete (relative or absolute) path names, and not just file - names, and - * also supports a convenience pattern ("**") to match files at any - directory level. - - Examples: - - >>> pathmatch('**.py', 'bar.py') - True - >>> pathmatch('**.py', 'foo/bar/baz.py') - True - >>> pathmatch('**.py', 'templates/index.html') - False - - >>> pathmatch('**/templates/*.html', 'templates/index.html') - True - >>> pathmatch('**/templates/*.html', 'templates/foo/bar.html') - False - - :param pattern: the glob pattern - :param filename: the path name of the file to match against - """ - symbols = { - '?': '[^/]', - '?/': '[^/]/', - '*': '[^/]+', - '*/': '[^/]+/', - '**/': '(?:.+/)*?', - '**': '(?:.+/)*?[^/]+', - } - buf = [] - for idx, part in enumerate(re.split('([?*]+/?)', pattern)): - if idx % 2: - buf.append(symbols[part]) - elif part: - buf.append(re.escape(part)) - match = re.match(''.join(buf) + '$', filename.replace(os.sep, '/')) - return match is not None - - -class TextWrapper(textwrap.TextWrapper): - wordsep_re = re.compile( - r'(\s+|' # any whitespace - r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))' # em-dash - ) - - -def wraptext(text, width=70, initial_indent='', subsequent_indent=''): - """Simple wrapper around the ``textwrap.wrap`` function in the standard - library. This version does not wrap lines on hyphens in words. - - :param text: the text to wrap - :param width: the maximum line width - :param initial_indent: string that will be prepended to the first line of - wrapped output - :param subsequent_indent: string that will be prepended to all lines save - the first of wrapped output - """ - wrapper = TextWrapper(width=width, initial_indent=initial_indent, - subsequent_indent=subsequent_indent, - break_long_words=False) - return wrapper.wrap(text) - - -class odict(dict): - """Ordered dict implementation. - - :see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 - """ - def __init__(self, data=None): - dict.__init__(self, data or {}) - self._keys = list(dict.keys(self)) - - def __delitem__(self, key): - dict.__delitem__(self, key) - self._keys.remove(key) - - def __setitem__(self, key, item): - dict.__setitem__(self, key, item) - if key not in self._keys: - self._keys.append(key) - - def __iter__(self): - return iter(self._keys) - iterkeys = __iter__ - - def clear(self): - dict.clear(self) - self._keys = [] - - def copy(self): - d = odict() - d.update(self) - return d - - def items(self): - return zip(self._keys, self.values()) - - def iteritems(self): - return izip(self._keys, self.itervalues()) - - def keys(self): - return self._keys[:] - - def pop(self, key, default=missing): - if default is missing: - return dict.pop(self, key) - elif key not in self: - return default - self._keys.remove(key) - return dict.pop(self, key, default) - - def popitem(self, key): - self._keys.remove(key) - return dict.popitem(key) - - def setdefault(self, key, failobj = None): - dict.setdefault(self, key, failobj) - if key not in self._keys: - self._keys.append(key) - - def update(self, dict): - for (key, val) in dict.items(): - self[key] = val - - def values(self): - return map(self.get, self._keys) - - def itervalues(self): - return imap(self.get, self._keys) - - -try: - relpath = os.path.relpath -except AttributeError: - def relpath(path, start='.'): - """Compute the relative path to one path from another. - - >>> relpath('foo/bar.txt', '').replace(os.sep, '/') - 'foo/bar.txt' - >>> relpath('foo/bar.txt', 'foo').replace(os.sep, '/') - 'bar.txt' - >>> relpath('foo/bar.txt', 'baz').replace(os.sep, '/') - '../foo/bar.txt' - """ - start_list = os.path.abspath(start).split(os.sep) - path_list = os.path.abspath(path).split(os.sep) - - # Work out how much of the filepath is shared by start and path. - i = len(os.path.commonprefix([start_list, path_list])) - - rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:] - return os.path.join(*rel_list) - - -class FixedOffsetTimezone(tzinfo): - """Fixed offset in minutes east from UTC.""" - - def __init__(self, offset, name=None): - self._offset = timedelta(minutes=offset) - if name is None: - name = 'Etc/GMT+%d' % offset - self.zone = name - - def __str__(self): - return self.zone - - def __repr__(self): - return '<FixedOffset "%s" %s>' % (self.zone, self._offset) - - def utcoffset(self, dt): - return self._offset - - def tzname(self, dt): - return self.zone - - def dst(self, dt): - return ZERO - - -import pytz as _pytz -from babel import localtime - -# Export the localtime functionality here because that's -# where it was in the past. -UTC = _pytz.utc -LOCALTZ = localtime.LOCALTZ -get_localzone = localtime.get_localzone - -STDOFFSET = localtime.STDOFFSET -DSTOFFSET = localtime.DSTOFFSET -DSTDIFF = localtime.DSTDIFF -ZERO = localtime.ZERO diff --git a/awx/lib/site-packages/billiard/__init__.py b/awx/lib/site-packages/billiard/__init__.py deleted file mode 100644 index 3a15224653..0000000000 --- a/awx/lib/site-packages/billiard/__init__.py +++ /dev/null @@ -1,327 +0,0 @@ -"""Python multiprocessing fork with improvements and bugfixes""" -# -# Package analogous to 'threading.py' but using processes -# -# multiprocessing/__init__.py -# -# This package is intended to duplicate the functionality (and much of -# the API) of threading.py but uses processes instead of threads. A -# subpackage 'multiprocessing.dummy' has the same API but is a simple -# wrapper for 'threading'. -# -# Try calling `multiprocessing.doc.main()` to read the html -# documentation in a webbrowser. -# -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# - -from __future__ import absolute_import - -VERSION = (3, 3, 0, 16) -__version__ = '.'.join(map(str, VERSION[0:4])) + "".join(VERSION[4:]) -__author__ = 'R Oudkerk / Python Software Foundation' -__author_email__ = 'python-dev@python.org' -__maintainer__ = 'Ask Solem', -__contact__ = "ask@celeryproject.org" -__homepage__ = "http://github.com/celery/billiard" -__docformat__ = "restructuredtext" - -# -eof meta- - -__all__ = [ - 'Process', 'current_process', 'active_children', 'freeze_support', - 'Manager', 'Pipe', 'cpu_count', 'log_to_stderr', 'get_logger', - 'allow_connection_pickling', 'BufferTooShort', 'TimeoutError', - 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition', - 'Event', 'Queue', 'JoinableQueue', 'Pool', 'Value', 'Array', - 'RawValue', 'RawArray', 'SUBDEBUG', 'SUBWARNING', 'set_executable', - 'forking_enable', 'forking_is_enabled' -] - -# -# Imports -# - -import os -import sys -import warnings - -from .exceptions import ( # noqa - ProcessError, - BufferTooShort, - TimeoutError, - AuthenticationError, - TimeLimitExceeded, - SoftTimeLimitExceeded, - WorkerLostError, -) -from .process import Process, current_process, active_children -from .util import SUBDEBUG, SUBWARNING - - -def ensure_multiprocessing(): - from ._ext import ensure_multiprocessing - return ensure_multiprocessing() - - -W_NO_EXECV = """\ -force_execv is not supported as the billiard C extension \ -is not installed\ -""" - -# -# Definitions not depending on native semaphores -# - - -def Manager(): - ''' - Returns a manager associated with a running server process - - The managers methods such as `Lock()`, `Condition()` and `Queue()` - can be used to create shared objects. - ''' - from .managers import SyncManager - m = SyncManager() - m.start() - return m - - -def Pipe(duplex=True, rnonblock=False, wnonblock=False): - ''' - Returns two connection object connected by a pipe - ''' - from billiard.connection import Pipe - return Pipe(duplex, rnonblock, wnonblock) - - -def cpu_count(): - ''' - Returns the number of CPUs in the system - ''' - if sys.platform == 'win32': - try: - num = int(os.environ['NUMBER_OF_PROCESSORS']) - except (ValueError, KeyError): - num = 0 - elif 'bsd' in sys.platform or sys.platform == 'darwin': - comm = '/sbin/sysctl -n hw.ncpu' - if sys.platform == 'darwin': - comm = '/usr' + comm - try: - with os.popen(comm) as p: - num = int(p.read()) - except ValueError: - num = 0 - else: - try: - num = os.sysconf('SC_NPROCESSORS_ONLN') - except (ValueError, OSError, AttributeError): - num = 0 - - if num >= 1: - return num - else: - raise NotImplementedError('cannot determine number of cpus') - - -def freeze_support(): - ''' - Check whether this is a fake forked process in a frozen executable. - If so then run code specified by commandline and exit. - ''' - if sys.platform == 'win32' and getattr(sys, 'frozen', False): - from .forking import freeze_support - freeze_support() - - -def get_logger(): - ''' - Return package logger -- if it does not already exist then it is created - ''' - from .util import get_logger - return get_logger() - - -def log_to_stderr(level=None): - ''' - Turn on logging and add a handler which prints to stderr - ''' - from .util import log_to_stderr - return log_to_stderr(level) - - -def allow_connection_pickling(): - ''' - Install support for sending connections and sockets between processes - ''' - from . import reduction # noqa - -# -# Definitions depending on native semaphores -# - - -def Lock(): - ''' - Returns a non-recursive lock object - ''' - from .synchronize import Lock - return Lock() - - -def RLock(): - ''' - Returns a recursive lock object - ''' - from .synchronize import RLock - return RLock() - - -def Condition(lock=None): - ''' - Returns a condition object - ''' - from .synchronize import Condition - return Condition(lock) - - -def Semaphore(value=1): - ''' - Returns a semaphore object - ''' - from .synchronize import Semaphore - return Semaphore(value) - - -def BoundedSemaphore(value=1): - ''' - Returns a bounded semaphore object - ''' - from .synchronize import BoundedSemaphore - return BoundedSemaphore(value) - - -def Event(): - ''' - Returns an event object - ''' - from .synchronize import Event - return Event() - - -def Queue(maxsize=0): - ''' - Returns a queue object - ''' - from .queues import Queue - return Queue(maxsize) - - -def JoinableQueue(maxsize=0): - ''' - Returns a queue object - ''' - from .queues import JoinableQueue - return JoinableQueue(maxsize) - - -def Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None, - timeout=None, soft_timeout=None, lost_worker_timeout=None, - max_restarts=None, max_restart_freq=1, on_process_up=None, - on_process_down=None, on_timeout_set=None, on_timeout_cancel=None, - threads=True, semaphore=None, putlocks=False, allow_restart=False): - ''' - Returns a process pool object - ''' - from .pool import Pool - return Pool(processes, initializer, initargs, maxtasksperchild, - timeout, soft_timeout, lost_worker_timeout, - max_restarts, max_restart_freq, on_process_up, - on_process_down, on_timeout_set, on_timeout_cancel, - threads, semaphore, putlocks, allow_restart) - - -def RawValue(typecode_or_type, *args): - ''' - Returns a shared object - ''' - from .sharedctypes import RawValue - return RawValue(typecode_or_type, *args) - - -def RawArray(typecode_or_type, size_or_initializer): - ''' - Returns a shared array - ''' - from .sharedctypes import RawArray - return RawArray(typecode_or_type, size_or_initializer) - - -def Value(typecode_or_type, *args, **kwds): - ''' - Returns a synchronized shared object - ''' - from .sharedctypes import Value - return Value(typecode_or_type, *args, **kwds) - - -def Array(typecode_or_type, size_or_initializer, **kwds): - ''' - Returns a synchronized shared array - ''' - from .sharedctypes import Array - return Array(typecode_or_type, size_or_initializer, **kwds) - -# -# -# - - -def set_executable(executable): - ''' - Sets the path to a python.exe or pythonw.exe binary used to run - child processes on Windows instead of sys.executable. - Useful for people embedding Python. - ''' - from .forking import set_executable - set_executable(executable) - - -def forking_is_enabled(): - ''' - Returns a boolean value indicating whether billiard is - currently set to create child processes by forking the current - python process rather than by starting a new instances of python. - - On Windows this always returns `False`. On Unix it returns `True` by - default. - ''' - from . import forking - return forking._forking_is_enabled - - -def forking_enable(value): - ''' - Enable/disable creation of child process by forking the current process. - - `value` should be a boolean value. If `value` is true then - forking is enabled. If `value` is false then forking is disabled. - On systems with `os.fork()` forking is enabled by default, and on - other systems it is always disabled. - ''' - if not value: - from ._ext import supports_exec - if supports_exec: - from . import forking - if value and not hasattr(os, 'fork'): - raise ValueError('os.fork() not found') - forking._forking_is_enabled = bool(value) - if not value: - os.environ["MULTIPROCESSING_FORKING_DISABLE"] = "1" - else: - warnings.warn(RuntimeWarning(W_NO_EXECV)) -if os.environ.get("MULTIPROCESSING_FORKING_DISABLE"): - forking_enable(False) diff --git a/awx/lib/site-packages/billiard/_ext.py b/awx/lib/site-packages/billiard/_ext.py deleted file mode 100644 index fb2c055891..0000000000 --- a/awx/lib/site-packages/billiard/_ext.py +++ /dev/null @@ -1,40 +0,0 @@ -from __future__ import absolute_import - -import sys - -supports_exec = True - -from .compat import _winapi as win32 # noqa - -if sys.platform.startswith("java"): - _billiard = None -else: - try: - import _billiard # noqa - except ImportError: - import _multiprocessing as _billiard # noqa - supports_exec = False - try: - Connection = _billiard.Connection - except AttributeError: # Py3 - from billiard.connection import Connection # noqa - - PipeConnection = getattr(_billiard, "PipeConnection", None) - - -def ensure_multiprocessing(): - if _billiard is None: - raise NotImplementedError("multiprocessing not supported") - - -def ensure_SemLock(): - try: - from _billiard import SemLock # noqa - except ImportError: - try: - from _multiprocessing import SemLock # noqa - except ImportError: - raise ImportError("""\ -This platform lacks a functioning sem_open implementation, therefore, -the required synchronization primitives needed will not function, -see issue 3770.""") diff --git a/awx/lib/site-packages/billiard/_win.py b/awx/lib/site-packages/billiard/_win.py deleted file mode 100644 index dc0262e83f..0000000000 --- a/awx/lib/site-packages/billiard/_win.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf-8 -*- -""" - billiard._win - ~~~~~~~~~~~~~ - - Windows utilities to terminate process groups. - -""" -from __future__ import absolute_import - -import os - -# psutil is painfully slow in win32. So to avoid adding big -# dependencies like pywin32 a ctypes based solution is preferred - -# Code based on the winappdbg project http://winappdbg.sourceforge.net/ -# (BSD License) -from ctypes import ( - byref, sizeof, windll, - Structure, WinError, POINTER, - c_size_t, c_char, c_void_p, -) -from ctypes.wintypes import DWORD, LONG - -ERROR_NO_MORE_FILES = 18 -INVALID_HANDLE_VALUE = c_void_p(-1).value - - -class PROCESSENTRY32(Structure): - _fields_ = [ - ('dwSize', DWORD), - ('cntUsage', DWORD), - ('th32ProcessID', DWORD), - ('th32DefaultHeapID', c_size_t), - ('th32ModuleID', DWORD), - ('cntThreads', DWORD), - ('th32ParentProcessID', DWORD), - ('pcPriClassBase', LONG), - ('dwFlags', DWORD), - ('szExeFile', c_char * 260), - ] -LPPROCESSENTRY32 = POINTER(PROCESSENTRY32) - - -def CreateToolhelp32Snapshot(dwFlags=2, th32ProcessID=0): - hSnapshot = windll.kernel32.CreateToolhelp32Snapshot(dwFlags, - th32ProcessID) - if hSnapshot == INVALID_HANDLE_VALUE: - raise WinError() - return hSnapshot - - -def Process32First(hSnapshot, pe=None): - return _Process32n(windll.kernel32.Process32First, hSnapshot, pe) - - -def Process32Next(hSnapshot, pe=None): - return _Process32n(windll.kernel32.Process32Next, hSnapshot, pe) - - -def _Process32n(fun, hSnapshot, pe=None): - if pe is None: - pe = PROCESSENTRY32() - pe.dwSize = sizeof(PROCESSENTRY32) - success = fun(hSnapshot, byref(pe)) - if not success: - if windll.kernel32.GetLastError() == ERROR_NO_MORE_FILES: - return - raise WinError() - return pe - - -def get_all_processes_pids(): - """Return a dictionary with all processes pids as keys and their - parents as value. Ignore processes with no parents. - """ - h = CreateToolhelp32Snapshot() - parents = {} - pe = Process32First(h) - while pe: - if pe.th32ParentProcessID: - parents[pe.th32ProcessID] = pe.th32ParentProcessID - pe = Process32Next(h, pe) - - return parents - - -def get_processtree_pids(pid, include_parent=True): - """Return a list with all the pids of a process tree""" - parents = get_all_processes_pids() - all_pids = list(parents.keys()) - pids = set([pid]) - while 1: - pids_new = pids.copy() - - for _pid in all_pids: - if parents[_pid] in pids: - pids_new.add(_pid) - - if pids_new == pids: - break - - pids = pids_new.copy() - - if not include_parent: - pids.remove(pid) - - return list(pids) - - -def kill_processtree(pid, signum): - """Kill a process and all its descendants""" - family_pids = get_processtree_pids(pid) - - for _pid in family_pids: - os.kill(_pid, signum) diff --git a/awx/lib/site-packages/billiard/common.py b/awx/lib/site-packages/billiard/common.py deleted file mode 100644 index 4b8ab82bfd..0000000000 --- a/awx/lib/site-packages/billiard/common.py +++ /dev/null @@ -1,134 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module contains utilities added by billiard, to keep -"non-core" functionality out of ``.util``.""" -from __future__ import absolute_import - -import os -import signal -import sys - -import pickle as pypickle -try: - import cPickle as cpickle -except ImportError: # pragma: no cover - cpickle = None # noqa - -from .exceptions import RestartFreqExceeded -from .five import monotonic - -if sys.version_info < (2, 6): # pragma: no cover - # cPickle does not use absolute_imports - pickle = pypickle - pickle_load = pypickle.load - pickle_loads = pypickle.loads -else: - pickle = cpickle or pypickle - pickle_load = pickle.load - pickle_loads = pickle.loads - -# cPickle.loads does not support buffer() objects, -# but we can just create a StringIO and use load. -if sys.version_info[0] == 3: - from io import BytesIO -else: - try: - from cStringIO import StringIO as BytesIO # noqa - except ImportError: - from StringIO import StringIO as BytesIO # noqa - -EX_SOFTWARE = 70 - -TERMSIGS_DEFAULT = ( - 'SIGHUP', - 'SIGQUIT', - 'SIGTERM', - 'SIGUSR1', - 'SIGUSR2' -) - -TERMSIGS_FULL = ( - 'SIGHUP', - 'SIGQUIT', - 'SIGTRAP', - 'SIGABRT', - 'SIGEMT', - 'SIGSYS', - 'SIGPIPE', - 'SIGALRM', - 'SIGTERM', - 'SIGXCPU', - 'SIGXFSZ', - 'SIGVTALRM', - 'SIGPROF', - 'SIGUSR1', - 'SIGUSR2', -) - -#: set by signal handlers just before calling exit. -#: if this is true after the sighandler returns it means that something -#: went wrong while terminating the process, and :func:`os._exit` -#: must be called ASAP. -_should_have_exited = [False] - - -def pickle_loads(s, load=pickle_load): - # used to support buffer objects - return load(BytesIO(s)) - - -def maybe_setsignal(signum, handler): - try: - signal.signal(signum, handler) - except (OSError, AttributeError, ValueError, RuntimeError): - pass - - -def _shutdown_cleanup(signum, frame): - # we will exit here so if the signal is received a second time - # we can be sure that something is very wrong and we may be in - # a crashing loop. - if _should_have_exited[0]: - os._exit(EX_SOFTWARE) - maybe_setsignal(signum, signal.SIG_DFL) - _should_have_exited[0] = True - sys.exit(-(256 - signum)) - - -def reset_signals(handler=_shutdown_cleanup, full=False): - for sig in TERMSIGS_FULL if full else TERMSIGS_DEFAULT: - try: - signum = getattr(signal, sig) - except AttributeError: - pass - else: - current = signal.getsignal(signum) - if current is not None and current != signal.SIG_IGN: - maybe_setsignal(signum, handler) - - -class restart_state(object): - RestartFreqExceeded = RestartFreqExceeded - - def __init__(self, maxR, maxT): - self.maxR, self.maxT = maxR, maxT - self.R, self.T = 0, None - - def step(self, now=None): - now = monotonic() if now is None else now - R = self.R - if self.T and now - self.T >= self.maxT: - # maxT passed, reset counter and time passed. - self.T, self.R = now, 0 - elif self.maxR and self.R >= self.maxR: - # verify that R has a value as the result handler - # resets this when a job is accepted. If a job is accepted - # the startup probably went fine (startup restart burst - # protection) - if self.R: # pragma: no cover - self.R = 0 # reset in case someone catches the error - raise self.RestartFreqExceeded("%r in %rs" % (R, self.maxT)) - # first run sets T - if self.T is None: - self.T = now - self.R += 1 diff --git a/awx/lib/site-packages/billiard/compat.py b/awx/lib/site-packages/billiard/compat.py deleted file mode 100644 index aac4b7c6fe..0000000000 --- a/awx/lib/site-packages/billiard/compat.py +++ /dev/null @@ -1,107 +0,0 @@ -from __future__ import absolute_import - -import errno -import os -import sys - -from .five import range - -if sys.platform == 'win32': - try: - import _winapi # noqa - except ImportError: # pragma: no cover - try: - from _billiard import win32 as _winapi # noqa - except (ImportError, AttributeError): - from _multiprocessing import win32 as _winapi # noqa -else: - _winapi = None # noqa - - -if sys.version_info > (2, 7, 5): - buf_t, is_new_buffer = memoryview, True # noqa -else: - buf_t, is_new_buffer = buffer, False # noqa - -if hasattr(os, 'write'): - __write__ = os.write - - if is_new_buffer: - - def send_offset(fd, buf, offset): - return __write__(fd, buf[offset:]) - - else: # Py<2.7.6 - - def send_offset(fd, buf, offset): # noqa - return __write__(fd, buf_t(buf, offset)) - -else: # non-posix platform - - def send_offset(fd, buf, offset): # noqa - raise NotImplementedError('send_offset') - - -if sys.version_info[0] == 3: - bytes = bytes -else: - _bytes = bytes - - # the 'bytes' alias in Python2 does not support an encoding argument. - - class bytes(_bytes): # noqa - - def __new__(cls, *args): - if len(args) > 1: - return _bytes(args[0]).encode(*args[1:]) - return _bytes(*args) - -try: - closerange = os.closerange -except AttributeError: - - def closerange(fd_low, fd_high): # noqa - for fd in reversed(range(fd_low, fd_high)): - try: - os.close(fd) - except OSError as exc: - if exc.errno != errno.EBADF: - raise - - -def get_errno(exc): - """:exc:`socket.error` and :exc:`IOError` first got - the ``.errno`` attribute in Py2.7""" - try: - return exc.errno - except AttributeError: - try: - # e.args = (errno, reason) - if isinstance(exc.args, tuple) and len(exc.args) == 2: - return exc.args[0] - except AttributeError: - pass - return 0 - - -if sys.platform == 'win32': - - def setblocking(handle, blocking): - raise NotImplementedError('setblocking not implemented on win32') - - def isblocking(handle): - raise NotImplementedError('isblocking not implemented on win32') - -else: - from os import O_NONBLOCK - from fcntl import fcntl, F_GETFL, F_SETFL - - def isblocking(handle): # noqa - return not (fcntl(handle, F_GETFL) & O_NONBLOCK) - - def setblocking(handle, blocking): # noqa - flags = fcntl(handle, F_GETFL, 0) - fcntl( - handle, F_SETFL, - flags & (~O_NONBLOCK) if blocking else flags | O_NONBLOCK, - ) diff --git a/awx/lib/site-packages/billiard/connection.py b/awx/lib/site-packages/billiard/connection.py deleted file mode 100644 index bd2e36eb14..0000000000 --- a/awx/lib/site-packages/billiard/connection.py +++ /dev/null @@ -1,27 +0,0 @@ -from __future__ import absolute_import - -import sys - -is_pypy = hasattr(sys, 'pypy_version_info') - -if sys.version_info[0] == 3: - from .py3 import connection -else: - from .py2 import connection # noqa - - -if is_pypy: - import _multiprocessing - from .compat import setblocking, send_offset - - class Connection(_multiprocessing.Connection): - - def send_offset(self, buf, offset): - return send_offset(self.fileno(), buf, offset) - - def setblocking(self, blocking): - setblocking(self.fileno(), blocking) - _multiprocessing.Connection = Connection - - -sys.modules[__name__] = connection diff --git a/awx/lib/site-packages/billiard/dummy/__init__.py b/awx/lib/site-packages/billiard/dummy/__init__.py deleted file mode 100644 index 369b6a81d0..0000000000 --- a/awx/lib/site-packages/billiard/dummy/__init__.py +++ /dev/null @@ -1,165 +0,0 @@ -# -# Support for the API of the multiprocessing package using threads -# -# multiprocessing/dummy/__init__.py -# -# Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -from __future__ import absolute_import - -__all__ = [ - 'Process', 'current_process', 'active_children', 'freeze_support', - 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition', - 'Event', 'Queue', 'Manager', 'Pipe', 'Pool', 'JoinableQueue' -] - -# -# Imports -# - -import threading -import sys -import weakref -import array - -from threading import Lock, RLock, Semaphore, BoundedSemaphore -from threading import Event - -from billiard.five import Queue - -from billiard.connection import Pipe - - -class DummyProcess(threading.Thread): - - def __init__(self, group=None, target=None, name=None, args=(), kwargs={}): - threading.Thread.__init__(self, group, target, name, args, kwargs) - self._pid = None - self._children = weakref.WeakKeyDictionary() - self._start_called = False - self._parent = current_process() - - def start(self): - assert self._parent is current_process() - self._start_called = True - self._parent._children[self] = None - threading.Thread.start(self) - - @property - def exitcode(self): - if self._start_called and not self.is_alive(): - return 0 - else: - return None - - -try: - _Condition = threading._Condition -except AttributeError: # Py3 - _Condition = threading.Condition # noqa - - -class Condition(_Condition): - if sys.version_info[0] == 3: - notify_all = _Condition.notifyAll - else: - notify_all = _Condition.notifyAll.__func__ - - -Process = DummyProcess -current_process = threading.currentThread -current_process()._children = weakref.WeakKeyDictionary() - - -def active_children(): - children = current_process()._children - for p in list(children): - if not p.is_alive(): - children.pop(p, None) - return list(children) - - -def freeze_support(): - pass - - -class Namespace(object): - - def __init__(self, **kwds): - self.__dict__.update(kwds) - - def __repr__(self): - items = list(self.__dict__.items()) - temp = [] - for name, value in items: - if not name.startswith('_'): - temp.append('%s=%r' % (name, value)) - temp.sort() - return 'Namespace(%s)' % str.join(', ', temp) - - -dict = dict -list = list - - -def Array(typecode, sequence, lock=True): - return array.array(typecode, sequence) - - -class Value(object): - - def __init__(self, typecode, value, lock=True): - self._typecode = typecode - self._value = value - - def _get(self): - return self._value - - def _set(self, value): - self._value = value - value = property(_get, _set) - - def __repr__(self): - return '<%r(%r, %r)>' % (type(self).__name__, - self._typecode, self._value) - - -def Manager(): - return sys.modules[__name__] - - -def shutdown(): - pass - - -def Pool(processes=None, initializer=None, initargs=()): - from billiard.pool import ThreadPool - return ThreadPool(processes, initializer, initargs) - -JoinableQueue = Queue diff --git a/awx/lib/site-packages/billiard/dummy/connection.py b/awx/lib/site-packages/billiard/dummy/connection.py deleted file mode 100644 index 46502ee31f..0000000000 --- a/awx/lib/site-packages/billiard/dummy/connection.py +++ /dev/null @@ -1,94 +0,0 @@ -# -# Analogue of `multiprocessing.connection` which uses queues instead of sockets -# -# multiprocessing/dummy/connection.py -# -# Copyright (c) 2006-2008, R Oudkerk -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of author nor the names of any contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -from __future__ import absolute_import - -__all__ = ['Client', 'Listener', 'Pipe'] - -from billiard.five import Queue - - -families = [None] - - -class Listener(object): - - def __init__(self, address=None, family=None, backlog=1): - self._backlog_queue = Queue(backlog) - - def accept(self): - return Connection(*self._backlog_queue.get()) - - def close(self): - self._backlog_queue = None - - address = property(lambda self: self._backlog_queue) - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - -def Client(address): - _in, _out = Queue(), Queue() - address.put((_out, _in)) - return Connection(_in, _out) - - -def Pipe(duplex=True): - a, b = Queue(), Queue() - return Connection(a, b), Connection(b, a) - - -class Connection(object): - - def __init__(self, _in, _out): - self._out = _out - self._in = _in - self.send = self.send_bytes = _out.put - self.recv = self.recv_bytes = _in.get - - def poll(self, timeout=0.0): - if self._in.qsize() > 0: - return True - if timeout <= 0.0: - return False - self._in.not_empty.acquire() - self._in.not_empty.wait(timeout) - self._in.not_empty.release() - return self._in.qsize() > 0 - - def close(self): - pass diff --git a/awx/lib/site-packages/billiard/einfo.py b/awx/lib/site-packages/billiard/einfo.py deleted file mode 100644 index e761620d66..0000000000 --- a/awx/lib/site-packages/billiard/einfo.py +++ /dev/null @@ -1,112 +0,0 @@ -from __future__ import absolute_import - -import sys -import traceback - - -class _Code(object): - - def __init__(self, code): - self.co_filename = code.co_filename - self.co_name = code.co_name - - -class _Frame(object): - Code = _Code - - def __init__(self, frame): - self.f_globals = { - "__file__": frame.f_globals.get("__file__", "__main__"), - "__name__": frame.f_globals.get("__name__"), - "__loader__": None, - } - self.f_locals = fl = {} - try: - fl["__traceback_hide__"] = frame.f_locals["__traceback_hide__"] - except KeyError: - pass - self.f_code = self.Code(frame.f_code) - self.f_lineno = frame.f_lineno - - -class _Object(object): - - def __init__(self, **kw): - [setattr(self, k, v) for k, v in kw.items()] - - -class _Truncated(object): - - def __init__(self): - self.tb_lineno = -1 - self.tb_frame = _Object( - f_globals={"__file__": "", - "__name__": "", - "__loader__": None}, - f_fileno=None, - f_code=_Object(co_filename="...", - co_name="[rest of traceback truncated]"), - ) - self.tb_next = None - - -class Traceback(object): - Frame = _Frame - - tb_frame = tb_lineno = tb_next = None - max_frames = sys.getrecursionlimit() // 8 - - def __init__(self, tb, max_frames=None, depth=0): - limit = self.max_frames = max_frames or self.max_frames - self.tb_frame = self.Frame(tb.tb_frame) - self.tb_lineno = tb.tb_lineno - if tb.tb_next is not None: - if depth <= limit: - self.tb_next = Traceback(tb.tb_next, limit, depth + 1) - else: - self.tb_next = _Truncated() - - -class ExceptionInfo(object): - """Exception wrapping an exception and its traceback. - - :param exc_info: The exception info tuple as returned by - :func:`sys.exc_info`. - - """ - - #: Exception type. - type = None - - #: Exception instance. - exception = None - - #: Pickleable traceback instance for use with :mod:`traceback` - tb = None - - #: String representation of the traceback. - traceback = None - - #: Set to true if this is an internal error. - internal = False - - def __init__(self, exc_info=None, internal=False): - self.type, self.exception, tb = exc_info or sys.exc_info() - try: - self.tb = Traceback(tb) - self.traceback = ''.join( - traceback.format_exception(self.type, self.exception, tb), - ) - self.internal = internal - finally: - del(tb) - - def __str__(self): - return self.traceback - - def __repr__(self): - return "<ExceptionInfo: %r>" % (self.exception, ) - - @property - def exc_info(self): - return self.type, self.exception, self.tb diff --git a/awx/lib/site-packages/billiard/exceptions.py b/awx/lib/site-packages/billiard/exceptions.py deleted file mode 100644 index df560833e5..0000000000 --- a/awx/lib/site-packages/billiard/exceptions.py +++ /dev/null @@ -1,54 +0,0 @@ -from __future__ import absolute_import - -try: - from multiprocessing import ( - ProcessError, - BufferTooShort, - TimeoutError, - AuthenticationError, - ) -except ImportError: - class ProcessError(Exception): # noqa - pass - - class BufferTooShort(Exception): # noqa - pass - - class TimeoutError(Exception): # noqa - pass - - class AuthenticationError(Exception): # noqa - pass - - -class TimeLimitExceeded(Exception): - """The time limit has been exceeded and the job has been terminated.""" - - def __str__(self): - return "TimeLimitExceeded%s" % (self.args, ) - - -class SoftTimeLimitExceeded(Exception): - """The soft time limit has been exceeded. This exception is raised - to give the task a chance to clean up.""" - - def __str__(self): - return "SoftTimeLimitExceeded%s" % (self.args, ) - - -class WorkerLostError(Exception): - """The worker processing a job has exited prematurely.""" - - -class Terminated(Exception): - """The worker processing a job has been terminated by user request.""" - - -class RestartFreqExceeded(Exception): - """Restarts too fast.""" - - -class CoroStop(Exception): - """Coroutine exit, as opposed to StopIteration which may - mean it should be restarted.""" - pass diff --git a/awx/lib/site-packages/billiard/five.py b/awx/lib/site-packages/billiard/five.py deleted file mode 100644 index 765b07ca13..0000000000 --- a/awx/lib/site-packages/billiard/five.py +++ /dev/null @@ -1,188 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.five - ~~~~~~~~~~~ - - Compatibility implementations of features - only available in newer Python versions. - - -""" -from __future__ import absolute_import - -############## py3k ######################################################### -import sys -PY3 = sys.version_info[0] == 3 - -try: - reload = reload # noqa -except NameError: # pragma: no cover - from imp import reload # noqa - -try: - from UserList import UserList # noqa -except ImportError: # pragma: no cover - from collections import UserList # noqa - -try: - from UserDict import UserDict # noqa -except ImportError: # pragma: no cover - from collections import UserDict # noqa - -############## time.monotonic ################################################ - -if sys.version_info < (3, 3): - - import platform - SYSTEM = platform.system() - - if SYSTEM == 'Darwin': - import ctypes - from ctypes.util import find_library - libSystem = ctypes.CDLL('libSystem.dylib') - CoreServices = ctypes.CDLL(find_library('CoreServices'), - use_errno=True) - mach_absolute_time = libSystem.mach_absolute_time - mach_absolute_time.restype = ctypes.c_uint64 - absolute_to_nanoseconds = CoreServices.AbsoluteToNanoseconds - absolute_to_nanoseconds.restype = ctypes.c_uint64 - absolute_to_nanoseconds.argtypes = [ctypes.c_uint64] - - def _monotonic(): - return absolute_to_nanoseconds(mach_absolute_time()) * 1e-9 - - elif SYSTEM == 'Linux': - # from stackoverflow: - # questions/1205722/how-do-i-get-monotonic-time-durations-in-python - import ctypes - import os - - CLOCK_MONOTONIC = 1 # see <linux/time.h> - - class timespec(ctypes.Structure): - _fields_ = [ - ('tv_sec', ctypes.c_long), - ('tv_nsec', ctypes.c_long), - ] - - librt = ctypes.CDLL('librt.so.1', use_errno=True) - clock_gettime = librt.clock_gettime - clock_gettime.argtypes = [ - ctypes.c_int, ctypes.POINTER(timespec), - ] - - def _monotonic(): # noqa - t = timespec() - if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0: - errno_ = ctypes.get_errno() - raise OSError(errno_, os.strerror(errno_)) - return t.tv_sec + t.tv_nsec * 1e-9 - else: - from time import time as _monotonic - -try: - from time import monotonic -except ImportError: - monotonic = _monotonic # noqa - -if PY3: - import builtins - - from queue import Queue, Empty, Full - from itertools import zip_longest - from io import StringIO, BytesIO - - map = map - string = str - string_t = str - long_t = int - text_t = str - range = range - int_types = (int, ) - - open_fqdn = 'builtins.open' - - def items(d): - return d.items() - - def keys(d): - return d.keys() - - def values(d): - return d.values() - - def nextfun(it): - return it.__next__ - - exec_ = getattr(builtins, 'exec') - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - class WhateverIO(StringIO): - - def write(self, data): - if isinstance(data, bytes): - data = data.encode() - StringIO.write(self, data) - -else: - import __builtin__ as builtins # noqa - from Queue import Queue, Empty, Full # noqa - from itertools import imap as map, izip_longest as zip_longest # noqa - from StringIO import StringIO # noqa - string = unicode # noqa - string_t = basestring # noqa - text_t = unicode - long_t = long # noqa - range = xrange - int_types = (int, long) - - open_fqdn = '__builtin__.open' - - def items(d): # noqa - return d.iteritems() - - def keys(d): # noqa - return d.iterkeys() - - def values(d): # noqa - return d.itervalues() - - def nextfun(it): # noqa - return it.next - - def exec_(code, globs=None, locs=None): - """Execute code in a namespace.""" - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - - exec_("""def reraise(tp, value, tb=None): raise tp, value, tb""") - - BytesIO = WhateverIO = StringIO # noqa - - -def with_metaclass(Type, skip_attrs=set(['__dict__', '__weakref__'])): - """Class decorator to set metaclass. - - Works with both Python 3 and Python 3 and it does not add - an extra class in the lookup order like ``six.with_metaclass`` does - (that is -- it copies the original class instead of using inheritance). - - """ - - def _clone_with_metaclass(Class): - attrs = dict((key, value) for key, value in items(vars(Class)) - if key not in skip_attrs) - return Type(Class.__name__, Class.__bases__, attrs) - - return _clone_with_metaclass diff --git a/awx/lib/site-packages/billiard/forking.py b/awx/lib/site-packages/billiard/forking.py deleted file mode 100644 index 57fc9795e4..0000000000 --- a/awx/lib/site-packages/billiard/forking.py +++ /dev/null @@ -1,580 +0,0 @@ -# -# Module for starting a process object using os.fork() or CreateProcess() -# -# multiprocessing/forking.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# - -from __future__ import absolute_import - -import os -import sys -import signal -import warnings - -from pickle import load, HIGHEST_PROTOCOL -from billiard import util -from billiard import process -from billiard.five import int_types -from .reduction import dump -from .compat import _winapi as win32 - -__all__ = ['Popen', 'assert_spawning', 'exit', - 'duplicate', 'close'] - -try: - WindowsError = WindowsError # noqa -except NameError: - class WindowsError(Exception): # noqa - pass - -W_OLD_DJANGO_LAYOUT = """\ -Will add directory %r to path! This is necessary to accommodate \ -pre-Django 1.4 layouts using setup_environ. -You can skip this warning by adding a DJANGO_SETTINGS_MODULE=settings \ -environment variable. -""" - -# -# Choose whether to do a fork or spawn (fork+exec) on Unix. -# This affects how some shared resources should be created. -# - -_forking_is_enabled = sys.platform != 'win32' - -# -# Check that the current thread is spawning a child process -# - - -def assert_spawning(self): - if not Popen.thread_is_spawning(): - raise RuntimeError( - '%s objects should only be shared between processes' - ' through inheritance' % type(self).__name__ - ) - - -# -# Unix -# - -if sys.platform != 'win32': - try: - import thread - except ImportError: - import _thread as thread # noqa - import select - - WINEXE = False - WINSERVICE = False - - exit = os._exit - duplicate = os.dup - close = os.close - _select = util._eintr_retry(select.select) - - # - # We define a Popen class similar to the one from subprocess, but - # whose constructor takes a process object as its argument. - # - - class Popen(object): - - _tls = thread._local() - - def __init__(self, process_obj): - # register reducers - from billiard import connection # noqa - _Django_old_layout_hack__save() - sys.stdout.flush() - sys.stderr.flush() - self.returncode = None - r, w = os.pipe() - self.sentinel = r - - if _forking_is_enabled: - self.pid = os.fork() - if self.pid == 0: - os.close(r) - if 'random' in sys.modules: - import random - random.seed() - code = process_obj._bootstrap() - os._exit(code) - else: - from_parent_fd, to_child_fd = os.pipe() - cmd = get_command_line() + [str(from_parent_fd)] - - self.pid = os.fork() - if self.pid == 0: - os.close(r) - os.close(to_child_fd) - os.execv(sys.executable, cmd) - - # send information to child - prep_data = get_preparation_data(process_obj._name) - os.close(from_parent_fd) - to_child = os.fdopen(to_child_fd, 'wb') - Popen._tls.process_handle = self.pid - try: - dump(prep_data, to_child, HIGHEST_PROTOCOL) - dump(process_obj, to_child, HIGHEST_PROTOCOL) - finally: - del(Popen._tls.process_handle) - to_child.close() - - # `w` will be closed when the child exits, at which point `r` - # will become ready for reading (using e.g. select()). - os.close(w) - util.Finalize(self, os.close, (r,)) - - def poll(self, flag=os.WNOHANG): - if self.returncode is None: - try: - pid, sts = os.waitpid(self.pid, flag) - except os.error: - # Child process not yet created. See #1731717 - # e.errno == errno.ECHILD == 10 - return None - if pid == self.pid: - if os.WIFSIGNALED(sts): - self.returncode = -os.WTERMSIG(sts) - else: - assert os.WIFEXITED(sts) - self.returncode = os.WEXITSTATUS(sts) - return self.returncode - - def wait(self, timeout=None): - if self.returncode is None: - if timeout is not None: - r = _select([self.sentinel], [], [], timeout)[0] - if not r: - return None - # This shouldn't block if select() returned successfully. - return self.poll(os.WNOHANG if timeout == 0.0 else 0) - return self.returncode - - def terminate(self): - if self.returncode is None: - try: - os.kill(self.pid, signal.SIGTERM) - except OSError: - if self.wait(timeout=0.1) is None: - raise - - @staticmethod - def thread_is_spawning(): - if _forking_is_enabled: - return False - else: - return getattr(Popen._tls, 'process_handle', None) is not None - - @staticmethod - def duplicate_for_child(handle): - return handle - -# -# Windows -# - -else: - try: - import thread - except ImportError: - import _thread as thread # noqa - import msvcrt - try: - import _subprocess - except ImportError: - import _winapi as _subprocess # noqa - - # - # - # - - TERMINATE = 0x10000 - WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False)) - WINSERVICE = sys.executable.lower().endswith("pythonservice.exe") - - exit = win32.ExitProcess - close = win32.CloseHandle - - # - # - # - - def duplicate(handle, target_process=None, inheritable=False): - if target_process is None: - target_process = _subprocess.GetCurrentProcess() - h = _subprocess.DuplicateHandle( - _subprocess.GetCurrentProcess(), handle, target_process, - 0, inheritable, _subprocess.DUPLICATE_SAME_ACCESS - ) - if sys.version_info[0] < 3 or ( - sys.version_info[0] == 3 and sys.version_info[1] < 3): - h = h.Detach() - return h - - # - # We define a Popen class similar to the one from subprocess, but - # whose constructor takes a process object as its argument. - # - - class Popen(object): - ''' - Start a subprocess to run the code of a process object - ''' - _tls = thread._local() - - def __init__(self, process_obj): - _Django_old_layout_hack__save() - # create pipe for communication with child - rfd, wfd = os.pipe() - - # get handle for read end of the pipe and make it inheritable - rhandle = duplicate(msvcrt.get_osfhandle(rfd), inheritable=True) - os.close(rfd) - - # start process - cmd = get_command_line() + [rhandle] - cmd = ' '.join('"%s"' % x for x in cmd) - hp, ht, pid, tid = _subprocess.CreateProcess( - _python_exe, cmd, None, None, 1, 0, None, None, None - ) - close(ht) if isinstance(ht, int_types) else ht.Close() - (close(rhandle) if isinstance(rhandle, int_types) - else rhandle.Close()) - - # set attributes of self - self.pid = pid - self.returncode = None - self._handle = hp - self.sentinel = int(hp) - - # send information to child - prep_data = get_preparation_data(process_obj._name) - to_child = os.fdopen(wfd, 'wb') - Popen._tls.process_handle = int(hp) - try: - dump(prep_data, to_child, HIGHEST_PROTOCOL) - dump(process_obj, to_child, HIGHEST_PROTOCOL) - finally: - del Popen._tls.process_handle - to_child.close() - - @staticmethod - def thread_is_spawning(): - return getattr(Popen._tls, 'process_handle', None) is not None - - @staticmethod - def duplicate_for_child(handle): - return duplicate(handle, Popen._tls.process_handle) - - def wait(self, timeout=None): - if self.returncode is None: - if timeout is None: - msecs = _subprocess.INFINITE - else: - msecs = max(0, int(timeout * 1000 + 0.5)) - - res = _subprocess.WaitForSingleObject(int(self._handle), msecs) - if res == _subprocess.WAIT_OBJECT_0: - code = _subprocess.GetExitCodeProcess(self._handle) - if code == TERMINATE: - code = -signal.SIGTERM - self.returncode = code - - return self.returncode - - def poll(self): - return self.wait(timeout=0) - - def terminate(self): - if self.returncode is None: - try: - _subprocess.TerminateProcess(int(self._handle), TERMINATE) - except WindowsError: - if self.wait(timeout=0.1) is None: - raise - - # - # - # - -if WINSERVICE: - _python_exe = os.path.join(sys.exec_prefix, 'python.exe') -else: - _python_exe = sys.executable - - -def set_executable(exe): - global _python_exe - _python_exe = exe - - -def is_forking(argv): - ''' - Return whether commandline indicates we are forking - ''' - if len(argv) >= 2 and argv[1] == '--billiard-fork': - assert len(argv) == 3 - os.environ["FORKED_BY_MULTIPROCESSING"] = "1" - return True - else: - return False - - -def freeze_support(): - ''' - Run code for process object if this in not the main process - ''' - if is_forking(sys.argv): - main() - sys.exit() - - -def get_command_line(): - ''' - Returns prefix of command line used for spawning a child process - ''' - if process.current_process()._identity == () and is_forking(sys.argv): - raise RuntimeError(''' - Attempt to start a new process before the current process - has finished its bootstrapping phase. - - This probably means that have forgotten to use the proper - idiom in the main module: - - if __name__ == '__main__': - freeze_support() - ... - - The "freeze_support()" line can be omitted if the program - is not going to be frozen to produce a Windows executable.''') - - if getattr(sys, 'frozen', False): - return [sys.executable, '--billiard-fork'] - else: - prog = 'from billiard.forking import main; main()' - return [_python_exe, '-c', prog, '--billiard-fork'] - - -def _Django_old_layout_hack__save(): - if 'DJANGO_PROJECT_DIR' not in os.environ: - try: - settings_name = os.environ['DJANGO_SETTINGS_MODULE'] - except KeyError: - return # not using Django. - - conf_settings = sys.modules.get('django.conf.settings') - configured = conf_settings and conf_settings.configured - try: - project_name, _ = settings_name.split('.', 1) - except ValueError: - return # not modified by setup_environ - - project = __import__(project_name) - try: - project_dir = os.path.normpath(_module_parent_dir(project)) - except AttributeError: - return # dynamically generated module (no __file__) - if configured: - warnings.warn(UserWarning( - W_OLD_DJANGO_LAYOUT % os.path.realpath(project_dir) - )) - os.environ['DJANGO_PROJECT_DIR'] = project_dir - - -def _Django_old_layout_hack__load(): - try: - sys.path.append(os.environ['DJANGO_PROJECT_DIR']) - except KeyError: - pass - - -def _module_parent_dir(mod): - dir, filename = os.path.split(_module_dir(mod)) - if dir == os.curdir or not dir: - dir = os.getcwd() - return dir - - -def _module_dir(mod): - if '__init__.py' in mod.__file__: - return os.path.dirname(mod.__file__) - return mod.__file__ - - -def main(): - ''' - Run code specifed by data received over pipe - ''' - global _forking_is_enabled - _Django_old_layout_hack__load() - - assert is_forking(sys.argv) - _forking_is_enabled = False - - handle = int(sys.argv[-1]) - if sys.platform == 'win32': - fd = msvcrt.open_osfhandle(handle, os.O_RDONLY) - else: - fd = handle - from_parent = os.fdopen(fd, 'rb') - - process.current_process()._inheriting = True - preparation_data = load(from_parent) - prepare(preparation_data) - # Huge hack to make logging before Process.run work. - try: - os.environ["MP_MAIN_FILE"] = sys.modules["__main__"].__file__ - except KeyError: - pass - except AttributeError: - pass - loglevel = os.environ.get("_MP_FORK_LOGLEVEL_") - logfile = os.environ.get("_MP_FORK_LOGFILE_") or None - format = os.environ.get("_MP_FORK_LOGFORMAT_") - if loglevel: - from billiard import util - import logging - logger = util.get_logger() - logger.setLevel(int(loglevel)) - if not logger.handlers: - logger._rudimentary_setup = True - logfile = logfile or sys.__stderr__ - if hasattr(logfile, "write"): - handler = logging.StreamHandler(logfile) - else: - handler = logging.FileHandler(logfile) - formatter = logging.Formatter( - format or util.DEFAULT_LOGGING_FORMAT, - ) - handler.setFormatter(formatter) - logger.addHandler(handler) - - self = load(from_parent) - process.current_process()._inheriting = False - - from_parent.close() - - exitcode = self._bootstrap() - exit(exitcode) - - -def get_preparation_data(name): - ''' - Return info about parent needed by child to unpickle process object - ''' - from billiard.util import _logger, _log_to_stderr - - d = dict( - name=name, - sys_path=sys.path, - sys_argv=sys.argv, - log_to_stderr=_log_to_stderr, - orig_dir=process.ORIGINAL_DIR, - authkey=process.current_process().authkey, - ) - - if _logger is not None: - d['log_level'] = _logger.getEffectiveLevel() - - if not WINEXE and not WINSERVICE: - main_path = getattr(sys.modules['__main__'], '__file__', None) - if not main_path and sys.argv[0] not in ('', '-c'): - main_path = sys.argv[0] - if main_path is not None: - if (not os.path.isabs(main_path) and - process.ORIGINAL_DIR is not None): - main_path = os.path.join(process.ORIGINAL_DIR, main_path) - d['main_path'] = os.path.normpath(main_path) - - return d - -# -# Prepare current process -# - -old_main_modules = [] - - -def prepare(data): - ''' - Try to get current process ready to unpickle process object - ''' - old_main_modules.append(sys.modules['__main__']) - - if 'name' in data: - process.current_process().name = data['name'] - - if 'authkey' in data: - process.current_process()._authkey = data['authkey'] - - if 'log_to_stderr' in data and data['log_to_stderr']: - util.log_to_stderr() - - if 'log_level' in data: - util.get_logger().setLevel(data['log_level']) - - if 'sys_path' in data: - sys.path = data['sys_path'] - - if 'sys_argv' in data: - sys.argv = data['sys_argv'] - - if 'dir' in data: - os.chdir(data['dir']) - - if 'orig_dir' in data: - process.ORIGINAL_DIR = data['orig_dir'] - - if 'main_path' in data: - main_path = data['main_path'] - main_name = os.path.splitext(os.path.basename(main_path))[0] - if main_name == '__init__': - main_name = os.path.basename(os.path.dirname(main_path)) - - if main_name == '__main__': - main_module = sys.modules['__main__'] - main_module.__file__ = main_path - elif main_name != 'ipython': - # Main modules not actually called __main__.py may - # contain additional code that should still be executed - import imp - - if main_path is None: - dirs = None - elif os.path.basename(main_path).startswith('__init__.py'): - dirs = [os.path.dirname(os.path.dirname(main_path))] - else: - dirs = [os.path.dirname(main_path)] - - assert main_name not in sys.modules, main_name - file, path_name, etc = imp.find_module(main_name, dirs) - try: - # We would like to do "imp.load_module('__main__', ...)" - # here. However, that would cause 'if __name__ == - # "__main__"' clauses to be executed. - main_module = imp.load_module( - '__parents_main__', file, path_name, etc - ) - finally: - if file: - file.close() - - sys.modules['__main__'] = main_module - main_module.__name__ = '__main__' - - # Try to make the potentially picklable objects in - # sys.modules['__main__'] realize they are in the main - # module -- somewhat ugly. - for obj in list(main_module.__dict__.values()): - try: - if obj.__module__ == '__parents_main__': - obj.__module__ = '__main__' - except Exception: - pass diff --git a/awx/lib/site-packages/billiard/heap.py b/awx/lib/site-packages/billiard/heap.py deleted file mode 100644 index 027a050559..0000000000 --- a/awx/lib/site-packages/billiard/heap.py +++ /dev/null @@ -1,255 +0,0 @@ -# -# Module which supports allocation of memory from an mmap -# -# multiprocessing/heap.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -import bisect -import mmap -import os -import sys -import threading -import itertools - -from ._ext import _billiard, win32 -from .util import Finalize, info, get_temp_dir -from .forking import assert_spawning -from .reduction import ForkingPickler - -__all__ = ['BufferWrapper'] - -try: - maxsize = sys.maxsize -except AttributeError: - maxsize = sys.maxint - -# -# Inheirtable class which wraps an mmap, and from which blocks can be allocated -# - -if sys.platform == 'win32': - - class Arena(object): - - _counter = itertools.count() - - def __init__(self, size): - self.size = size - self.name = 'pym-%d-%d' % (os.getpid(), next(Arena._counter)) - self.buffer = mmap.mmap(-1, self.size, tagname=self.name) - assert win32.GetLastError() == 0, 'tagname already in use' - self._state = (self.size, self.name) - - def __getstate__(self): - assert_spawning(self) - return self._state - - def __setstate__(self, state): - self.size, self.name = self._state = state - self.buffer = mmap.mmap(-1, self.size, tagname=self.name) - assert win32.GetLastError() == win32.ERROR_ALREADY_EXISTS - -else: - - class Arena(object): - - _counter = itertools.count() - - def __init__(self, size, fileno=-1): - from .forking import _forking_is_enabled - self.size = size - self.fileno = fileno - if fileno == -1 and not _forking_is_enabled: - name = os.path.join( - get_temp_dir(), - 'pym-%d-%d' % (os.getpid(), next(self._counter))) - self.fileno = os.open( - name, os.O_RDWR | os.O_CREAT | os.O_EXCL, 0o600) - os.unlink(name) - os.ftruncate(self.fileno, size) - self.buffer = mmap.mmap(self.fileno, self.size) - - def reduce_arena(a): - if a.fileno == -1: - raise ValueError('Arena is unpicklable because' - 'forking was enabled when it was created') - return Arena, (a.size, a.fileno) - - ForkingPickler.register(Arena, reduce_arena) - -# -# Class allowing allocation of chunks of memory from arenas -# - - -class Heap(object): - - _alignment = 8 - - def __init__(self, size=mmap.PAGESIZE): - self._lastpid = os.getpid() - self._lock = threading.Lock() - self._size = size - self._lengths = [] - self._len_to_seq = {} - self._start_to_block = {} - self._stop_to_block = {} - self._allocated_blocks = set() - self._arenas = [] - # list of pending blocks to free - see free() comment below - self._pending_free_blocks = [] - - @staticmethod - def _roundup(n, alignment): - # alignment must be a power of 2 - mask = alignment - 1 - return (n + mask) & ~mask - - def _malloc(self, size): - # returns a large enough block -- it might be much larger - i = bisect.bisect_left(self._lengths, size) - if i == len(self._lengths): - length = self._roundup(max(self._size, size), mmap.PAGESIZE) - self._size *= 2 - info('allocating a new mmap of length %d', length) - arena = Arena(length) - self._arenas.append(arena) - return (arena, 0, length) - else: - length = self._lengths[i] - seq = self._len_to_seq[length] - block = seq.pop() - if not seq: - del self._len_to_seq[length], self._lengths[i] - - (arena, start, stop) = block - del self._start_to_block[(arena, start)] - del self._stop_to_block[(arena, stop)] - return block - - def _free(self, block): - # free location and try to merge with neighbours - (arena, start, stop) = block - - try: - prev_block = self._stop_to_block[(arena, start)] - except KeyError: - pass - else: - start, _ = self._absorb(prev_block) - - try: - next_block = self._start_to_block[(arena, stop)] - except KeyError: - pass - else: - _, stop = self._absorb(next_block) - - block = (arena, start, stop) - length = stop - start - - try: - self._len_to_seq[length].append(block) - except KeyError: - self._len_to_seq[length] = [block] - bisect.insort(self._lengths, length) - - self._start_to_block[(arena, start)] = block - self._stop_to_block[(arena, stop)] = block - - def _absorb(self, block): - # deregister this block so it can be merged with a neighbour - (arena, start, stop) = block - del self._start_to_block[(arena, start)] - del self._stop_to_block[(arena, stop)] - - length = stop - start - seq = self._len_to_seq[length] - seq.remove(block) - if not seq: - del self._len_to_seq[length] - self._lengths.remove(length) - - return start, stop - - def _free_pending_blocks(self): - # Free all the blocks in the pending list - called with the lock held - while 1: - try: - block = self._pending_free_blocks.pop() - except IndexError: - break - self._allocated_blocks.remove(block) - self._free(block) - - def free(self, block): - # free a block returned by malloc() - # Since free() can be called asynchronously by the GC, it could happen - # that it's called while self._lock is held: in that case, - # self._lock.acquire() would deadlock (issue #12352). To avoid that, a - # trylock is used instead, and if the lock can't be acquired - # immediately, the block is added to a list of blocks to be freed - # synchronously sometimes later from malloc() or free(), by calling - # _free_pending_blocks() (appending and retrieving from a list is not - # strictly thread-safe but under cPython it's atomic thanks - # to the GIL). - assert os.getpid() == self._lastpid - if not self._lock.acquire(False): - # can't aquire the lock right now, add the block to the list of - # pending blocks to free - self._pending_free_blocks.append(block) - else: - # we hold the lock - try: - self._free_pending_blocks() - self._allocated_blocks.remove(block) - self._free(block) - finally: - self._lock.release() - - def malloc(self, size): - # return a block of right size (possibly rounded up) - assert 0 <= size < maxsize - if os.getpid() != self._lastpid: - self.__init__() # reinitialize after fork - self._lock.acquire() - self._free_pending_blocks() - try: - size = self._roundup(max(size, 1), self._alignment) - (arena, start, stop) = self._malloc(size) - new_stop = start + size - if new_stop < stop: - self._free((arena, new_stop, stop)) - block = (arena, start, new_stop) - self._allocated_blocks.add(block) - return block - finally: - self._lock.release() - -# -# Class representing a chunk of an mmap -- can be inherited -# - - -class BufferWrapper(object): - - _heap = Heap() - - def __init__(self, size): - assert 0 <= size < maxsize - block = BufferWrapper._heap.malloc(size) - self._state = (block, size) - Finalize(self, BufferWrapper._heap.free, args=(block,)) - - def get_address(self): - (arena, start, stop), size = self._state - address, length = _billiard.address_of_buffer(arena.buffer) - assert size <= length - return address + start - - def get_size(self): - return self._state[1] diff --git a/awx/lib/site-packages/billiard/managers.py b/awx/lib/site-packages/billiard/managers.py deleted file mode 100644 index 0a8117a741..0000000000 --- a/awx/lib/site-packages/billiard/managers.py +++ /dev/null @@ -1,1169 +0,0 @@ -# -# Module providing the `SyncManager` class for dealing -# with shared objects -# -# multiprocessing/managers.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -__all__ = ['BaseManager', 'SyncManager', 'BaseProxy', 'Token'] - -# -# Imports -# - -import sys -import threading -import array - -from traceback import format_exc - -from . import Process, current_process, active_children, Pool, util, connection -from .five import Queue, items, monotonic -from .process import AuthenticationString -from .forking import exit, Popen -from .reduction import ForkingPickler -from .util import Finalize, error, info - -# -# Register some things for pickling -# - - -def reduce_array(a): - return array.array, (a.typecode, a.tostring()) -ForkingPickler.register(array.array, reduce_array) - -view_types = [type(getattr({}, name)()) - for name in ('items', 'keys', 'values')] -if view_types[0] is not list: # only needed in Py3.0 - - def rebuild_as_list(obj): - return list, (list(obj), ) - for view_type in view_types: - ForkingPickler.register(view_type, rebuild_as_list) - try: - import copyreg - except ImportError: - pass - else: - copyreg.pickle(view_type, rebuild_as_list) - -# -# Type for identifying shared objects -# - - -class Token(object): - ''' - Type to uniquely indentify a shared object - ''' - __slots__ = ('typeid', 'address', 'id') - - def __init__(self, typeid, address, id): - (self.typeid, self.address, self.id) = (typeid, address, id) - - def __getstate__(self): - return (self.typeid, self.address, self.id) - - def __setstate__(self, state): - (self.typeid, self.address, self.id) = state - - def __repr__(self): - return 'Token(typeid=%r, address=%r, id=%r)' % \ - (self.typeid, self.address, self.id) - -# -# Function for communication with a manager's server process -# - - -def dispatch(c, id, methodname, args=(), kwds={}): - ''' - Send a message to manager using connection `c` and return response - ''' - c.send((id, methodname, args, kwds)) - kind, result = c.recv() - if kind == '#RETURN': - return result - raise convert_to_error(kind, result) - - -def convert_to_error(kind, result): - if kind == '#ERROR': - return result - elif kind == '#TRACEBACK': - assert type(result) is str - return RemoteError(result) - elif kind == '#UNSERIALIZABLE': - assert type(result) is str - return RemoteError('Unserializable message: %s\n' % result) - else: - return ValueError('Unrecognized message type') - - -class RemoteError(Exception): - - def __str__(self): - return ('\n' + '-' * 75 + '\n' + str(self.args[0]) + '-' * 75) - -# -# Functions for finding the method names of an object -# - - -def all_methods(obj): - ''' - Return a list of names of methods of `obj` - ''' - temp = [] - for name in dir(obj): - func = getattr(obj, name) - if callable(func): - temp.append(name) - return temp - - -def public_methods(obj): - ''' - Return a list of names of methods of `obj` which do not start with '_' - ''' - return [name for name in all_methods(obj) if name[0] != '_'] - -# -# Server which is run in a process controlled by a manager -# - - -class Server(object): - ''' - Server class which runs in a process controlled by a manager object - ''' - public = ['shutdown', 'create', 'accept_connection', 'get_methods', - 'debug_info', 'number_of_objects', 'dummy', 'incref', 'decref'] - - def __init__(self, registry, address, authkey, serializer): - assert isinstance(authkey, bytes) - self.registry = registry - self.authkey = AuthenticationString(authkey) - Listener, Client = listener_client[serializer] - - # do authentication later - self.listener = Listener(address=address, backlog=16) - self.address = self.listener.address - - self.id_to_obj = {'0': (None, ())} - self.id_to_refcount = {} - self.mutex = threading.RLock() - self.stop = 0 - - def serve_forever(self): - ''' - Run the server forever - ''' - current_process()._manager_server = self - try: - try: - while 1: - try: - c = self.listener.accept() - except (OSError, IOError): - continue - t = threading.Thread(target=self.handle_request, args=(c,)) - t.daemon = True - t.start() - except (KeyboardInterrupt, SystemExit): - pass - finally: - self.stop = 999 - self.listener.close() - - def handle_request(self, c): - ''' - Handle a new connection - ''' - funcname = result = request = None - try: - connection.deliver_challenge(c, self.authkey) - connection.answer_challenge(c, self.authkey) - request = c.recv() - ignore, funcname, args, kwds = request - assert funcname in self.public, '%r unrecognized' % funcname - func = getattr(self, funcname) - except Exception: - msg = ('#TRACEBACK', format_exc()) - else: - try: - result = func(c, *args, **kwds) - except Exception: - msg = ('#TRACEBACK', format_exc()) - else: - msg = ('#RETURN', result) - try: - c.send(msg) - except Exception as exc: - try: - c.send(('#TRACEBACK', format_exc())) - except Exception: - pass - info('Failure to send message: %r', msg) - info(' ... request was %r', request) - info(' ... exception was %r', exc) - - c.close() - - def serve_client(self, conn): - ''' - Handle requests from the proxies in a particular process/thread - ''' - util.debug('starting server thread to service %r', - threading.currentThread().name) - - recv = conn.recv - send = conn.send - id_to_obj = self.id_to_obj - - while not self.stop: - - try: - methodname = obj = None - request = recv() - ident, methodname, args, kwds = request - obj, exposed, gettypeid = id_to_obj[ident] - - if methodname not in exposed: - raise AttributeError( - 'method %r of %r object is not in exposed=%r' % ( - methodname, type(obj), exposed) - ) - - function = getattr(obj, methodname) - - try: - res = function(*args, **kwds) - except Exception as exc: - msg = ('#ERROR', exc) - else: - typeid = gettypeid and gettypeid.get(methodname, None) - if typeid: - rident, rexposed = self.create(conn, typeid, res) - token = Token(typeid, self.address, rident) - msg = ('#PROXY', (rexposed, token)) - else: - msg = ('#RETURN', res) - - except AttributeError: - if methodname is None: - msg = ('#TRACEBACK', format_exc()) - else: - try: - fallback_func = self.fallback_mapping[methodname] - result = fallback_func( - self, conn, ident, obj, *args, **kwds - ) - msg = ('#RETURN', result) - except Exception: - msg = ('#TRACEBACK', format_exc()) - - except EOFError: - util.debug('got EOF -- exiting thread serving %r', - threading.currentThread().name) - sys.exit(0) - - except Exception: - msg = ('#TRACEBACK', format_exc()) - - try: - try: - send(msg) - except Exception: - send(('#UNSERIALIZABLE', repr(msg))) - except Exception as exc: - info('exception in thread serving %r', - threading.currentThread().name) - info(' ... message was %r', msg) - info(' ... exception was %r', exc) - conn.close() - sys.exit(1) - - def fallback_getvalue(self, conn, ident, obj): - return obj - - def fallback_str(self, conn, ident, obj): - return str(obj) - - def fallback_repr(self, conn, ident, obj): - return repr(obj) - - fallback_mapping = { - '__str__': fallback_str, - '__repr__': fallback_repr, - '#GETVALUE': fallback_getvalue, - } - - def dummy(self, c): - pass - - def debug_info(self, c): - ''' - Return some info --- useful to spot problems with refcounting - ''' - with self.mutex: - result = [] - keys = list(self.id_to_obj.keys()) - keys.sort() - for ident in keys: - if ident != '0': - result.append(' %s: refcount=%s\n %s' % - (ident, self.id_to_refcount[ident], - str(self.id_to_obj[ident][0])[:75])) - return '\n'.join(result) - - def number_of_objects(self, c): - ''' - Number of shared objects - ''' - return len(self.id_to_obj) - 1 # don't count ident='0' - - def shutdown(self, c): - ''' - Shutdown this process - ''' - try: - try: - util.debug('manager received shutdown message') - c.send(('#RETURN', None)) - - if sys.stdout != sys.__stdout__: - util.debug('resetting stdout, stderr') - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - - util._run_finalizers(0) - - for p in active_children(): - util.debug('terminating a child process of manager') - p.terminate() - - for p in active_children(): - util.debug('terminating a child process of manager') - p.join() - - util._run_finalizers() - info('manager exiting with exitcode 0') - except: - if not error("Error while manager shutdown", exc_info=True): - import traceback - traceback.print_exc() - finally: - exit(0) - - def create(self, c, typeid, *args, **kwds): - ''' - Create a new shared object and return its id - ''' - with self.mutex: - callable, exposed, method_to_typeid, proxytype = \ - self.registry[typeid] - - if callable is None: - assert len(args) == 1 and not kwds - obj = args[0] - else: - obj = callable(*args, **kwds) - - if exposed is None: - exposed = public_methods(obj) - if method_to_typeid is not None: - assert type(method_to_typeid) is dict - exposed = list(exposed) + list(method_to_typeid) - - ident = '%x' % id(obj) # convert to string because xmlrpclib - # only has 32 bit signed integers - util.debug('%r callable returned object with id %r', typeid, ident) - - self.id_to_obj[ident] = (obj, set(exposed), method_to_typeid) - if ident not in self.id_to_refcount: - self.id_to_refcount[ident] = 0 - # increment the reference count immediately, to avoid - # this object being garbage collected before a Proxy - # object for it can be created. The caller of create() - # is responsible for doing a decref once the Proxy object - # has been created. - self.incref(c, ident) - return ident, tuple(exposed) - - def get_methods(self, c, token): - ''' - Return the methods of the shared object indicated by token - ''' - return tuple(self.id_to_obj[token.id][1]) - - def accept_connection(self, c, name): - ''' - Spawn a new thread to serve this connection - ''' - threading.currentThread().name = name - c.send(('#RETURN', None)) - self.serve_client(c) - - def incref(self, c, ident): - with self.mutex: - self.id_to_refcount[ident] += 1 - - def decref(self, c, ident): - with self.mutex: - assert self.id_to_refcount[ident] >= 1 - self.id_to_refcount[ident] -= 1 - if self.id_to_refcount[ident] == 0: - del self.id_to_obj[ident], self.id_to_refcount[ident] - util.debug('disposing of obj with id %r', ident) - -# -# Class to represent state of a manager -# - - -class State(object): - __slots__ = ['value'] - INITIAL = 0 - STARTED = 1 - SHUTDOWN = 2 - -# -# Mapping from serializer name to Listener and Client types -# - -listener_client = { - 'pickle': (connection.Listener, connection.Client), - 'xmlrpclib': (connection.XmlListener, connection.XmlClient), -} - -# -# Definition of BaseManager -# - - -class BaseManager(object): - ''' - Base class for managers - ''' - _registry = {} - _Server = Server - - def __init__(self, address=None, authkey=None, serializer='pickle'): - if authkey is None: - authkey = current_process().authkey - self._address = address # XXX not final address if eg ('', 0) - self._authkey = AuthenticationString(authkey) - self._state = State() - self._state.value = State.INITIAL - self._serializer = serializer - self._Listener, self._Client = listener_client[serializer] - - def __reduce__(self): - return (type(self).from_address, - (self._address, self._authkey, self._serializer)) - - def get_server(self): - ''' - Return server object with serve_forever() method and address attribute - ''' - assert self._state.value == State.INITIAL - return Server(self._registry, self._address, - self._authkey, self._serializer) - - def connect(self): - ''' - Connect manager object to the server process - ''' - Listener, Client = listener_client[self._serializer] - conn = Client(self._address, authkey=self._authkey) - dispatch(conn, None, 'dummy') - self._state.value = State.STARTED - - def start(self, initializer=None, initargs=()): - ''' - Spawn a server process for this manager object - ''' - assert self._state.value == State.INITIAL - - if initializer is not None and not callable(initializer): - raise TypeError('initializer must be a callable') - - # pipe over which we will retrieve address of server - reader, writer = connection.Pipe(duplex=False) - - # spawn process which runs a server - self._process = Process( - target=type(self)._run_server, - args=(self._registry, self._address, self._authkey, - self._serializer, writer, initializer, initargs), - ) - ident = ':'.join(str(i) for i in self._process._identity) - self._process.name = type(self).__name__ + '-' + ident - self._process.start() - - # get address of server - writer.close() - self._address = reader.recv() - reader.close() - - # register a finalizer - self._state.value = State.STARTED - self.shutdown = Finalize( - self, type(self)._finalize_manager, - args=(self._process, self._address, self._authkey, - self._state, self._Client), - exitpriority=0 - ) - - @classmethod - def _run_server(cls, registry, address, authkey, serializer, writer, - initializer=None, initargs=()): - ''' - Create a server, report its address and run it - ''' - if initializer is not None: - initializer(*initargs) - - # create server - server = cls._Server(registry, address, authkey, serializer) - - # inform parent process of the server's address - writer.send(server.address) - writer.close() - - # run the manager - info('manager serving at %r', server.address) - server.serve_forever() - - def _create(self, typeid, *args, **kwds): - ''' - Create a new shared object; return the token and exposed tuple - ''' - assert self._state.value == State.STARTED, 'server not yet started' - conn = self._Client(self._address, authkey=self._authkey) - try: - id, exposed = dispatch(conn, None, 'create', - (typeid,) + args, kwds) - finally: - conn.close() - return Token(typeid, self._address, id), exposed - - def join(self, timeout=None): - ''' - Join the manager process (if it has been spawned) - ''' - self._process.join(timeout) - - def _debug_info(self): - ''' - Return some info about the servers shared objects and connections - ''' - conn = self._Client(self._address, authkey=self._authkey) - try: - return dispatch(conn, None, 'debug_info') - finally: - conn.close() - - def _number_of_objects(self): - ''' - Return the number of shared objects - ''' - conn = self._Client(self._address, authkey=self._authkey) - try: - return dispatch(conn, None, 'number_of_objects') - finally: - conn.close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.shutdown() - - @staticmethod - def _finalize_manager(process, address, authkey, state, _Client): - ''' - Shutdown the manager process; will be registered as a finalizer - ''' - if process.is_alive(): - info('sending shutdown message to manager') - try: - conn = _Client(address, authkey=authkey) - try: - dispatch(conn, None, 'shutdown') - finally: - conn.close() - except Exception: - pass - - process.join(timeout=0.2) - if process.is_alive(): - info('manager still alive') - if hasattr(process, 'terminate'): - info('trying to `terminate()` manager process') - process.terminate() - process.join(timeout=0.1) - if process.is_alive(): - info('manager still alive after terminate') - - state.value = State.SHUTDOWN - try: - del BaseProxy._address_to_local[address] - except KeyError: - pass - - address = property(lambda self: self._address) - - @classmethod - def register(cls, typeid, callable=None, proxytype=None, exposed=None, - method_to_typeid=None, create_method=True): - ''' - Register a typeid with the manager type - ''' - if '_registry' not in cls.__dict__: - cls._registry = cls._registry.copy() - - if proxytype is None: - proxytype = AutoProxy - - exposed = exposed or getattr(proxytype, '_exposed_', None) - - method_to_typeid = ( - method_to_typeid or - getattr(proxytype, '_method_to_typeid_', None) - ) - - if method_to_typeid: - for key, value in items(method_to_typeid): - assert type(key) is str, '%r is not a string' % key - assert type(value) is str, '%r is not a string' % value - - cls._registry[typeid] = ( - callable, exposed, method_to_typeid, proxytype - ) - - if create_method: - def temp(self, *args, **kwds): - util.debug('requesting creation of a shared %r object', typeid) - token, exp = self._create(typeid, *args, **kwds) - proxy = proxytype( - token, self._serializer, manager=self, - authkey=self._authkey, exposed=exp - ) - conn = self._Client(token.address, authkey=self._authkey) - dispatch(conn, None, 'decref', (token.id,)) - return proxy - temp.__name__ = typeid - setattr(cls, typeid, temp) - -# -# Subclass of set which get cleared after a fork -# - - -class ProcessLocalSet(set): - - def __init__(self): - util.register_after_fork(self, lambda obj: obj.clear()) - - def __reduce__(self): - return type(self), () - -# -# Definition of BaseProxy -# - - -class BaseProxy(object): - ''' - A base for proxies of shared objects - ''' - _address_to_local = {} - _mutex = util.ForkAwareThreadLock() - - def __init__(self, token, serializer, manager=None, - authkey=None, exposed=None, incref=True): - BaseProxy._mutex.acquire() - try: - tls_idset = BaseProxy._address_to_local.get(token.address, None) - if tls_idset is None: - tls_idset = util.ForkAwareLocal(), ProcessLocalSet() - BaseProxy._address_to_local[token.address] = tls_idset - finally: - BaseProxy._mutex.release() - - # self._tls is used to record the connection used by this - # thread to communicate with the manager at token.address - self._tls = tls_idset[0] - - # self._idset is used to record the identities of all shared - # objects for which the current process owns references and - # which are in the manager at token.address - self._idset = tls_idset[1] - - self._token = token - self._id = self._token.id - self._manager = manager - self._serializer = serializer - self._Client = listener_client[serializer][1] - - if authkey is not None: - self._authkey = AuthenticationString(authkey) - elif self._manager is not None: - self._authkey = self._manager._authkey - else: - self._authkey = current_process().authkey - - if incref: - self._incref() - - util.register_after_fork(self, BaseProxy._after_fork) - - def _connect(self): - util.debug('making connection to manager') - name = current_process().name - if threading.currentThread().name != 'MainThread': - name += '|' + threading.currentThread().name - conn = self._Client(self._token.address, authkey=self._authkey) - dispatch(conn, None, 'accept_connection', (name,)) - self._tls.connection = conn - - def _callmethod(self, methodname, args=(), kwds={}): - ''' - Try to call a method of the referrent and return a copy of the result - ''' - try: - conn = self._tls.connection - except AttributeError: - util.debug('thread %r does not own a connection', - threading.currentThread().name) - self._connect() - conn = self._tls.connection - - conn.send((self._id, methodname, args, kwds)) - kind, result = conn.recv() - - if kind == '#RETURN': - return result - elif kind == '#PROXY': - exposed, token = result - proxytype = self._manager._registry[token.typeid][-1] - proxy = proxytype( - token, self._serializer, manager=self._manager, - authkey=self._authkey, exposed=exposed - ) - conn = self._Client(token.address, authkey=self._authkey) - dispatch(conn, None, 'decref', (token.id,)) - return proxy - raise convert_to_error(kind, result) - - def _getvalue(self): - ''' - Get a copy of the value of the referent - ''' - return self._callmethod('#GETVALUE') - - def _incref(self): - conn = self._Client(self._token.address, authkey=self._authkey) - dispatch(conn, None, 'incref', (self._id,)) - util.debug('INCREF %r', self._token.id) - - self._idset.add(self._id) - - state = self._manager and self._manager._state - - self._close = Finalize( - self, BaseProxy._decref, - args=(self._token, self._authkey, state, - self._tls, self._idset, self._Client), - exitpriority=10 - ) - - @staticmethod - def _decref(token, authkey, state, tls, idset, _Client): - idset.discard(token.id) - - # check whether manager is still alive - if state is None or state.value == State.STARTED: - # tell manager this process no longer cares about referent - try: - util.debug('DECREF %r', token.id) - conn = _Client(token.address, authkey=authkey) - dispatch(conn, None, 'decref', (token.id,)) - except Exception as exc: - util.debug('... decref failed %s', exc) - - else: - util.debug('DECREF %r -- manager already shutdown', token.id) - - # check whether we can close this thread's connection because - # the process owns no more references to objects for this manager - if not idset and hasattr(tls, 'connection'): - util.debug('thread %r has no more proxies so closing conn', - threading.currentThread().name) - tls.connection.close() - del tls.connection - - def _after_fork(self): - self._manager = None - try: - self._incref() - except Exception as exc: - # the proxy may just be for a manager which has shutdown - info('incref failed: %s', exc) - - def __reduce__(self): - kwds = {} - if Popen.thread_is_spawning(): - kwds['authkey'] = self._authkey - - if getattr(self, '_isauto', False): - kwds['exposed'] = self._exposed_ - return (RebuildProxy, - (AutoProxy, self._token, self._serializer, kwds)) - else: - return (RebuildProxy, - (type(self), self._token, self._serializer, kwds)) - - def __deepcopy__(self, memo): - return self._getvalue() - - def __repr__(self): - return '<%s object, typeid %r at %s>' % \ - (type(self).__name__, self._token.typeid, '0x%x' % id(self)) - - def __str__(self): - ''' - Return representation of the referent (or a fall-back if that fails) - ''' - try: - return self._callmethod('__repr__') - except Exception: - return repr(self)[:-1] + "; '__str__()' failed>" - -# -# Function used for unpickling -# - - -def RebuildProxy(func, token, serializer, kwds): - ''' - Function used for unpickling proxy objects. - - If possible the shared object is returned, or otherwise a proxy for it. - ''' - server = getattr(current_process(), '_manager_server', None) - - if server and server.address == token.address: - return server.id_to_obj[token.id][0] - else: - incref = ( - kwds.pop('incref', True) and - not getattr(current_process(), '_inheriting', False) - ) - return func(token, serializer, incref=incref, **kwds) - -# -# Functions to create proxies and proxy types -# - - -def MakeProxyType(name, exposed, _cache={}): - ''' - Return an proxy type whose methods are given by `exposed` - ''' - exposed = tuple(exposed) - try: - return _cache[(name, exposed)] - except KeyError: - pass - - dic = {} - - for meth in exposed: - exec('''def %s(self, *args, **kwds): - return self._callmethod(%r, args, kwds)''' % (meth, meth), dic) - - ProxyType = type(name, (BaseProxy,), dic) - ProxyType._exposed_ = exposed - _cache[(name, exposed)] = ProxyType - return ProxyType - - -def AutoProxy(token, serializer, manager=None, authkey=None, - exposed=None, incref=True): - ''' - Return an auto-proxy for `token` - ''' - _Client = listener_client[serializer][1] - - if exposed is None: - conn = _Client(token.address, authkey=authkey) - try: - exposed = dispatch(conn, None, 'get_methods', (token,)) - finally: - conn.close() - - if authkey is None and manager is not None: - authkey = manager._authkey - if authkey is None: - authkey = current_process().authkey - - ProxyType = MakeProxyType('AutoProxy[%s]' % token.typeid, exposed) - proxy = ProxyType(token, serializer, manager=manager, authkey=authkey, - incref=incref) - proxy._isauto = True - return proxy - -# -# Types/callables which we will register with SyncManager -# - - -class Namespace(object): - - def __init__(self, **kwds): - self.__dict__.update(kwds) - - def __repr__(self): - items = list(self.__dict__.items()) - temp = [] - for name, value in items: - if not name.startswith('_'): - temp.append('%s=%r' % (name, value)) - temp.sort() - return 'Namespace(%s)' % str.join(', ', temp) - - -class Value(object): - - def __init__(self, typecode, value, lock=True): - self._typecode = typecode - self._value = value - - def get(self): - return self._value - - def set(self, value): - self._value = value - - def __repr__(self): - return '%s(%r, %r)' % (type(self).__name__, - self._typecode, self._value) - value = property(get, set) - - -def Array(typecode, sequence, lock=True): - return array.array(typecode, sequence) - -# -# Proxy types used by SyncManager -# - - -class IteratorProxy(BaseProxy): - if sys.version_info[0] == 3: - _exposed = ('__next__', 'send', 'throw', 'close') - else: - _exposed_ = ('__next__', 'next', 'send', 'throw', 'close') - - def next(self, *args): - return self._callmethod('next', args) - - def __iter__(self): - return self - - def __next__(self, *args): - return self._callmethod('__next__', args) - - def send(self, *args): - return self._callmethod('send', args) - - def throw(self, *args): - return self._callmethod('throw', args) - - def close(self, *args): - return self._callmethod('close', args) - - -class AcquirerProxy(BaseProxy): - _exposed_ = ('acquire', 'release') - - def acquire(self, blocking=True): - return self._callmethod('acquire', (blocking,)) - - def release(self): - return self._callmethod('release') - - def __enter__(self): - return self._callmethod('acquire') - - def __exit__(self, exc_type, exc_val, exc_tb): - return self._callmethod('release') - - -class ConditionProxy(AcquirerProxy): - _exposed_ = ('acquire', 'release', 'wait', 'notify', 'notify_all') - - def wait(self, timeout=None): - return self._callmethod('wait', (timeout,)) - - def notify(self): - return self._callmethod('notify') - - def notify_all(self): - return self._callmethod('notify_all') - - def wait_for(self, predicate, timeout=None): - result = predicate() - if result: - return result - if timeout is not None: - endtime = monotonic() + timeout - else: - endtime = None - waittime = None - while not result: - if endtime is not None: - waittime = endtime - monotonic() - if waittime <= 0: - break - self.wait(waittime) - result = predicate() - return result - - -class EventProxy(BaseProxy): - _exposed_ = ('is_set', 'set', 'clear', 'wait') - - def is_set(self): - return self._callmethod('is_set') - - def set(self): - return self._callmethod('set') - - def clear(self): - return self._callmethod('clear') - - def wait(self, timeout=None): - return self._callmethod('wait', (timeout,)) - - -class NamespaceProxy(BaseProxy): - _exposed_ = ('__getattribute__', '__setattr__', '__delattr__') - - def __getattr__(self, key): - if key[0] == '_': - return object.__getattribute__(self, key) - callmethod = object.__getattribute__(self, '_callmethod') - return callmethod('__getattribute__', (key,)) - - def __setattr__(self, key, value): - if key[0] == '_': - return object.__setattr__(self, key, value) - callmethod = object.__getattribute__(self, '_callmethod') - return callmethod('__setattr__', (key, value)) - - def __delattr__(self, key): - if key[0] == '_': - return object.__delattr__(self, key) - callmethod = object.__getattribute__(self, '_callmethod') - return callmethod('__delattr__', (key,)) - - -class ValueProxy(BaseProxy): - _exposed_ = ('get', 'set') - - def get(self): - return self._callmethod('get') - - def set(self, value): - return self._callmethod('set', (value,)) - value = property(get, set) - - -BaseListProxy = MakeProxyType('BaseListProxy', ( - '__add__', '__contains__', '__delitem__', '__delslice__', - '__getitem__', '__getslice__', '__len__', '__mul__', - '__reversed__', '__rmul__', '__setitem__', '__setslice__', - 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', - 'reverse', 'sort', '__imul__', -)) # XXX __getslice__ and __setslice__ unneeded in Py3.0 - - -class ListProxy(BaseListProxy): - - def __iadd__(self, value): - self._callmethod('extend', (value,)) - return self - - def __imul__(self, value): - self._callmethod('__imul__', (value,)) - return self - - -DictProxy = MakeProxyType('DictProxy', ( - '__contains__', '__delitem__', '__getitem__', '__len__', - '__setitem__', 'clear', 'copy', 'get', 'has_key', 'items', - 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', -)) - - -ArrayProxy = MakeProxyType('ArrayProxy', ( - '__len__', '__getitem__', '__setitem__', '__getslice__', '__setslice__', -)) # XXX __getslice__ and __setslice__ unneeded in Py3.0 - - -PoolProxy = MakeProxyType('PoolProxy', ( - 'apply', 'apply_async', 'close', 'imap', 'imap_unordered', 'join', - 'map', 'map_async', 'starmap', 'starmap_async', 'terminate', -)) -PoolProxy._method_to_typeid_ = { - 'apply_async': 'AsyncResult', - 'map_async': 'AsyncResult', - 'starmap_async': 'AsyncResult', - 'imap': 'Iterator', - 'imap_unordered': 'Iterator', -} - -# -# Definition of SyncManager -# - - -class SyncManager(BaseManager): - ''' - Subclass of `BaseManager` which supports a number of shared object types. - - The types registered are those intended for the synchronization - of threads, plus `dict`, `list` and `Namespace`. - - The `billiard.Manager()` function creates started instances of - this class. - ''' - -SyncManager.register('Queue', Queue) -SyncManager.register('JoinableQueue', Queue) -SyncManager.register('Event', threading.Event, EventProxy) -SyncManager.register('Lock', threading.Lock, AcquirerProxy) -SyncManager.register('RLock', threading.RLock, AcquirerProxy) -SyncManager.register('Semaphore', threading.Semaphore, AcquirerProxy) -SyncManager.register('BoundedSemaphore', threading.BoundedSemaphore, - AcquirerProxy) -SyncManager.register('Condition', threading.Condition, ConditionProxy) -SyncManager.register('Pool', Pool, PoolProxy) -SyncManager.register('list', list, ListProxy) -SyncManager.register('dict', dict, DictProxy) -SyncManager.register('Value', Value, ValueProxy) -SyncManager.register('Array', Array, ArrayProxy) -SyncManager.register('Namespace', Namespace, NamespaceProxy) - -# types returned by methods of PoolProxy -SyncManager.register('Iterator', proxytype=IteratorProxy, create_method=False) -SyncManager.register('AsyncResult', create_method=False) diff --git a/awx/lib/site-packages/billiard/pool.py b/awx/lib/site-packages/billiard/pool.py deleted file mode 100644 index 468865c1b7..0000000000 --- a/awx/lib/site-packages/billiard/pool.py +++ /dev/null @@ -1,1944 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Module providing the `Pool` class for managing a process pool -# -# multiprocessing/pool.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -# -# Imports -# - -import errno -import itertools -import os -import platform -import signal -import sys -import threading -import time -import warnings - -from collections import deque -from functools import partial - -from . import Event, Process, cpu_count -from . import util -from .common import pickle_loads, reset_signals, restart_state -from .compat import get_errno, send_offset -from .einfo import ExceptionInfo -from .exceptions import ( - CoroStop, - RestartFreqExceeded, - SoftTimeLimitExceeded, - Terminated, - TimeLimitExceeded, - TimeoutError, - WorkerLostError, -) -from .five import Empty, Queue, range, values, reraise, monotonic -from .util import Finalize, debug - -PY3 = sys.version_info[0] == 3 - -if platform.system() == 'Windows': # pragma: no cover - # On Windows os.kill calls TerminateProcess which cannot be - # handled by # any process, so this is needed to terminate the task - # *and its children* (if any). - from ._win import kill_processtree as _kill # noqa -else: - from os import kill as _kill # noqa - - -try: - TIMEOUT_MAX = threading.TIMEOUT_MAX -except AttributeError: # pragma: no cover - TIMEOUT_MAX = 1e10 # noqa - - -if sys.version_info >= (3, 3): - _Semaphore = threading.Semaphore -else: - # Semaphore is a factory function pointing to _Semaphore - _Semaphore = threading._Semaphore # noqa - -SIGMAP = dict( - (getattr(signal, n), n) for n in dir(signal) if n.startswith('SIG') -) - -# -# Constants representing the state of a pool -# - -RUN = 0 -CLOSE = 1 -TERMINATE = 2 - -# -# Constants representing the state of a job -# - -ACK = 0 -READY = 1 -TASK = 2 -NACK = 3 -DEATH = 4 - -# -# Exit code constants -# -EX_OK = 0 -EX_FAILURE = 1 -EX_RECYCLE = 0x9B - - -# Signal used for soft time limits. -SIG_SOFT_TIMEOUT = getattr(signal, "SIGUSR1", None) - -# -# Miscellaneous -# - -LOST_WORKER_TIMEOUT = 10.0 -EX_OK = getattr(os, "EX_OK", 0) - -job_counter = itertools.count() - -Lock = threading.Lock - - -def _get_send_offset(connection): - try: - native = connection.send_offset - except AttributeError: - native = None - if native is None: - return partial(send_offset, connection.fileno()) - return native - - -def human_status(status): - if status < 0: - try: - return 'signal {0} ({1})'.format(-status, SIGMAP[-status]) - except KeyError: - return 'signal {0}'.format(-status) - return 'exitcode {0}'.format(status) - - -def mapstar(args): - return list(map(*args)) - - -def starmapstar(args): - return list(itertools.starmap(args[0], args[1])) - - -def error(msg, *args, **kwargs): - if util._logger: - util._logger.error(msg, *args, **kwargs) - - -def stop_if_not_current(thread, timeout=None): - if thread is not threading.currentThread(): - thread.stop(timeout) - - -class LaxBoundedSemaphore(_Semaphore): - """Semaphore that checks that # release is <= # acquires, - but ignores if # releases >= value.""" - - def __init__(self, value=1, verbose=None): - if PY3: - _Semaphore.__init__(self, value) - else: - _Semaphore.__init__(self, value, verbose) - self._initial_value = value - - def grow(self): - if PY3: - cond = self._cond - else: - cond = self._Semaphore__cond - with cond: - self._initial_value += 1 - self._Semaphore__value += 1 - cond.notify() - - def shrink(self): - self._initial_value -= 1 - self.acquire() - - if PY3: - - def release(self): - cond = self._cond - with cond: - if self._value < self._initial_value: - self._value += 1 - cond.notify_all() - - def clear(self): - while self._value < self._initial_value: - _Semaphore.release(self) - else: - - def release(self): # noqa - cond = self._Semaphore__cond - with cond: - if self._Semaphore__value < self._initial_value: - self._Semaphore__value += 1 - cond.notifyAll() - - def clear(self): # noqa - while self._Semaphore__value < self._initial_value: - _Semaphore.release(self) - -# -# Exceptions -# - - -class MaybeEncodingError(Exception): - """Wraps possible unpickleable errors, so they can be - safely sent through the socket.""" - - def __init__(self, exc, value): - self.exc = repr(exc) - self.value = repr(value) - super(MaybeEncodingError, self).__init__(self.exc, self.value) - - def __repr__(self): - return "<MaybeEncodingError: %s>" % str(self) - - def __str__(self): - return "Error sending result: '%r'. Reason: '%r'." % ( - self.value, self.exc) - - -class WorkersJoined(Exception): - """All workers have terminated.""" - - -def soft_timeout_sighandler(signum, frame): - raise SoftTimeLimitExceeded() - -# -# Code run by worker processes -# - - -class Worker(Process): - _controlled_termination = False - _job_terminated = False - - def __init__(self, inq, outq, synq=None, initializer=None, initargs=(), - maxtasks=None, sentinel=None, on_exit=None, - sigprotection=True): - assert maxtasks is None or (type(maxtasks) == int and maxtasks > 0) - self.initializer = initializer - self.initargs = initargs - self.maxtasks = maxtasks - self._shutdown = sentinel - self.on_exit = on_exit - self.sigprotection = sigprotection - self.inq, self.outq, self.synq = inq, outq, synq - self._make_shortcuts() - - super(Worker, self).__init__() - - def __reduce__(self): - return self.__class__, ( - self.inq, self.outq, self.synq, self.initializer, - self.initargs, self.maxtasks, self._shutdown, - ) - - def _make_shortcuts(self): - self.inqW_fd = self.inq._writer.fileno() # inqueue write fd - self.outqR_fd = self.outq._reader.fileno() # outqueue read fd - if self.synq: - self.synqR_fd = self.synq._reader.fileno() # synqueue read fd - self.synqW_fd = self.synq._writer.fileno() # synqueue write fd - self.send_syn_offset = _get_send_offset(self.synq._writer) - else: - self.synqR_fd = self.synqW_fd = self._send_syn_offset = None - self._quick_put = self.inq._writer.send - self._quick_get = self.outq._reader.recv - self.send_job_offset = _get_send_offset(self.inq._writer) - - def run(self): - _exit = sys.exit - _exitcode = [None] - - def exit(status=None): - _exitcode[0] = status - return _exit() - sys.exit = exit - - pid = os.getpid() - - self._make_child_methods() - self.after_fork() - self.on_loop_start(pid=pid) # callback on loop start - try: - sys.exit(self.workloop(pid=pid)) - except Exception as exc: - error('Pool process %r error: %r', self, exc, exc_info=1) - self._do_exit(pid, _exitcode[0], exc) - finally: - self._do_exit(pid, _exitcode[0], None) - - def _do_exit(self, pid, exitcode, exc=None): - if exitcode is None: - exitcode = EX_FAILURE if exc else EX_OK - - if self.on_exit is not None: - self.on_exit(pid, exitcode) - - if sys.platform != 'win32': - try: - self.outq.put((DEATH, (pid, exitcode))) - time.sleep(1) - finally: - os._exit(exitcode) - else: - os._exit(exitcode) - - def on_loop_start(self, pid): - pass - - def terminate_controlled(self): - self._controlled_termination = True - self.terminate() - - def prepare_result(self, result): - return result - - def workloop(self, debug=debug, now=monotonic, pid=None): - pid = pid or os.getpid() - put = self.outq.put - inqW_fd = self.inqW_fd - synqW_fd = self.synqW_fd - maxtasks = self.maxtasks - prepare_result = self.prepare_result - - wait_for_job = self.wait_for_job - _wait_for_syn = self.wait_for_syn - - def wait_for_syn(jid): - i = 0 - while 1: - if i > 60: - error('!!!WAIT FOR ACK TIMEOUT: job:%r fd:%r!!!', - jid, self.synq._reader.fileno(), exc_info=1) - req = _wait_for_syn() - if req: - type_, args = req - if type_ == NACK: - return False - assert type_ == ACK - return True - i += 1 - - completed = 0 - while maxtasks is None or (maxtasks and completed < maxtasks): - req = wait_for_job() - if req: - type_, args_ = req - assert type_ == TASK - job, i, fun, args, kwargs = args_ - put((ACK, (job, i, now(), pid, synqW_fd))) - if _wait_for_syn: - confirm = wait_for_syn(job) - if not confirm: - continue # received NACK - try: - result = (True, prepare_result(fun(*args, **kwargs))) - except Exception: - result = (False, ExceptionInfo()) - try: - put((READY, (job, i, result, inqW_fd))) - except Exception as exc: - _, _, tb = sys.exc_info() - try: - wrapped = MaybeEncodingError(exc, result[1]) - einfo = ExceptionInfo(( - MaybeEncodingError, wrapped, tb, - )) - put((READY, (job, i, (False, einfo), inqW_fd))) - finally: - del(tb) - completed += 1 - debug('worker exiting after %d tasks', completed) - if maxtasks: - return EX_RECYCLE if completed == maxtasks else EX_FAILURE - return EX_OK - - def after_fork(self): - if hasattr(self.inq, '_writer'): - self.inq._writer.close() - if hasattr(self.outq, '_reader'): - self.outq._reader.close() - - if self.initializer is not None: - self.initializer(*self.initargs) - - # Make sure all exiting signals call finally: blocks. - # This is important for the semaphore to be released. - reset_signals(full=self.sigprotection) - - # install signal handler for soft timeouts. - if SIG_SOFT_TIMEOUT is not None: - signal.signal(SIG_SOFT_TIMEOUT, soft_timeout_sighandler) - - try: - signal.signal(signal.SIGINT, signal.SIG_IGN) - except AttributeError: - pass - - def _make_recv_method(self, conn): - get = conn.get - - if hasattr(conn, '_reader'): - _poll = conn._reader.poll - if hasattr(conn, 'get_payload') and conn.get_payload: - get_payload = conn.get_payload - - def _recv(timeout, loads=pickle_loads): - return True, loads(get_payload()) - else: - def _recv(timeout): # noqa - if _poll(timeout): - return True, get() - return False, None - else: - def _recv(timeout): # noqa - try: - return True, get(timeout=timeout) - except Queue.Empty: - return False, None - return _recv - - def _make_child_methods(self, loads=pickle_loads): - self.wait_for_job = self._make_protected_receive(self.inq) - self.wait_for_syn = (self._make_protected_receive(self.synq) - if self.synq else None) - - def _make_protected_receive(self, conn): - _receive = self._make_recv_method(conn) - should_shutdown = self._shutdown.is_set if self._shutdown else None - - def receive(debug=debug): - if should_shutdown and should_shutdown(): - debug('worker got sentinel -- exiting') - raise SystemExit(EX_OK) - try: - ready, req = _receive(1.0) - if not ready: - return None - except (EOFError, IOError) as exc: - if get_errno(exc) == errno.EINTR: - return None # interrupted, maybe by gdb - debug('worker got %s -- exiting', type(exc).__name__) - raise SystemExit(EX_FAILURE) - if req is None: - debug('worker got sentinel -- exiting') - raise SystemExit(EX_FAILURE) - return req - - return receive - - -# -# Class representing a process pool -# - - -class PoolThread(threading.Thread): - - def __init__(self, *args, **kwargs): - threading.Thread.__init__(self) - self._state = RUN - self._was_started = False - self.daemon = True - - def run(self): - try: - return self.body() - except RestartFreqExceeded as exc: - error("Thread %r crashed: %r", type(self).__name__, exc, - exc_info=1) - _kill(os.getpid(), signal.SIGTERM) - sys.exit() - except Exception as exc: - error("Thread %r crashed: %r", type(self).__name__, exc, - exc_info=1) - os._exit(1) - - def start(self, *args, **kwargs): - self._was_started = True - super(PoolThread, self).start(*args, **kwargs) - - def on_stop_not_started(self): - pass - - def stop(self, timeout=None): - if self._was_started: - self.join(timeout) - return - self.on_stop_not_started() - - def terminate(self): - self._state = TERMINATE - - def close(self): - self._state = CLOSE - - -class Supervisor(PoolThread): - - def __init__(self, pool): - self.pool = pool - super(Supervisor, self).__init__() - - def body(self): - debug('worker handler starting') - - time.sleep(0.8) - - pool = self.pool - - try: - # do a burst at startup to verify that we can start - # our pool processes, and in that time we lower - # the max restart frequency. - prev_state = pool.restart_state - pool.restart_state = restart_state(10 * pool._processes, 1) - for _ in range(10): - if self._state == RUN and pool._state == RUN: - pool._maintain_pool() - time.sleep(0.1) - - # Keep maintaing workers until the cache gets drained, unless - # the pool is termianted - pool.restart_state = prev_state - while self._state == RUN and pool._state == RUN: - pool._maintain_pool() - time.sleep(0.8) - except RestartFreqExceeded: - pool.close() - pool.join() - raise - debug('worker handler exiting') - - -class TaskHandler(PoolThread): - - def __init__(self, taskqueue, put, outqueue, pool): - self.taskqueue = taskqueue - self.put = put - self.outqueue = outqueue - self.pool = pool - super(TaskHandler, self).__init__() - - def body(self): - taskqueue = self.taskqueue - put = self.put - - for taskseq, set_length in iter(taskqueue.get, None): - try: - i = -1 - for i, task in enumerate(taskseq): - if self._state: - debug('task handler found thread._state != RUN') - break - try: - put(task) - except IOError: - debug('could not put task on queue') - break - else: - if set_length: - debug('doing set_length()') - set_length(i + 1) - continue - break - except Exception as exc: - error('Task Handler ERROR: %r', exc, exc_info=1) - break - else: - debug('task handler got sentinel') - - self.tell_others() - - def tell_others(self): - outqueue = self.outqueue - put = self.put - pool = self.pool - - try: - # tell result handler to finish when cache is empty - debug('task handler sending sentinel to result handler') - outqueue.put(None) - - # tell workers there is no more work - debug('task handler sending sentinel to workers') - for p in pool: - put(None) - except IOError: - debug('task handler got IOError when sending sentinels') - - debug('task handler exiting') - - def on_stop_not_started(self): - self.tell_others() - - -class TimeoutHandler(PoolThread): - - def __init__(self, processes, cache, t_soft, t_hard): - self.processes = processes - self.cache = cache - self.t_soft = t_soft - self.t_hard = t_hard - self._it = None - super(TimeoutHandler, self).__init__() - - def _process_by_pid(self, pid): - return next(( - (proc, i) for i, proc in enumerate(self.processes) - if proc.pid == pid - ), (None, None)) - - def on_soft_timeout(self, job): - debug('soft time limit exceeded for %r', job) - process, _index = self._process_by_pid(job._worker_pid) - if not process: - return - - # Run timeout callback - if job._timeout_callback is not None: - job._timeout_callback(soft=True, timeout=job._soft_timeout) - - try: - _kill(job._worker_pid, SIG_SOFT_TIMEOUT) - except OSError as exc: - if get_errno(exc) != errno.ESRCH: - raise - - def on_hard_timeout(self, job): - if job.ready(): - return - debug('hard time limit exceeded for %r', job) - # Remove from cache and set return value to an exception - try: - raise TimeLimitExceeded(job._timeout) - except TimeLimitExceeded: - job._set(job._job, (False, ExceptionInfo())) - else: # pragma: no cover - pass - - # Remove from _pool - process, _index = self._process_by_pid(job._worker_pid) - - # Run timeout callback - if job._timeout_callback is not None: - job._timeout_callback(soft=False, timeout=job._timeout) - if process: - self._trywaitkill(process) - - def _trywaitkill(self, worker): - debug('timeout: sending TERM to %s', worker._name) - try: - worker.terminate() - except OSError: - pass - else: - if worker._popen.wait(timeout=0.1): - return - debug('timeout: TERM timed-out, now sending KILL to %s', worker._name) - try: - _kill(worker.pid, signal.SIGKILL) - except OSError: - pass - - def handle_timeouts(self): - cache = self.cache - t_hard, t_soft = self.t_hard, self.t_soft - dirty = set() - on_soft_timeout = self.on_soft_timeout - on_hard_timeout = self.on_hard_timeout - - def _timed_out(start, timeout): - if not start or not timeout: - return False - if monotonic() >= start + timeout: - return True - - # Inner-loop - while self._state == RUN: - - # Remove dirty items not in cache anymore - if dirty: - dirty = set(k for k in dirty if k in cache) - - for i, job in list(cache.items()): - ack_time = job._time_accepted - soft_timeout = job._soft_timeout - if soft_timeout is None: - soft_timeout = t_soft - hard_timeout = job._timeout - if hard_timeout is None: - hard_timeout = t_hard - if _timed_out(ack_time, hard_timeout): - on_hard_timeout(job) - elif i not in dirty and _timed_out(ack_time, soft_timeout): - on_soft_timeout(job) - dirty.add(i) - yield - - def body(self): - while self._state == RUN: - try: - for _ in self.handle_timeouts(): - time.sleep(1.0) # don't spin - except CoroStop: - break - debug('timeout handler exiting') - - def handle_event(self, *args): - if self._it is None: - self._it = self.handle_timeouts() - try: - next(self._it) - except StopIteration: - self._it = None - - -class ResultHandler(PoolThread): - - def __init__(self, outqueue, get, cache, poll, - join_exited_workers, putlock, restart_state, - check_timeouts, on_job_ready): - self.outqueue = outqueue - self.get = get - self.cache = cache - self.poll = poll - self.join_exited_workers = join_exited_workers - self.putlock = putlock - self.restart_state = restart_state - self._it = None - self._shutdown_complete = False - self.check_timeouts = check_timeouts - self.on_job_ready = on_job_ready - self._make_methods() - super(ResultHandler, self).__init__() - - def on_stop_not_started(self): - # used when pool started without result handler thread. - self.finish_at_shutdown(handle_timeouts=True) - - def _make_methods(self): - cache = self.cache - putlock = self.putlock - restart_state = self.restart_state - on_job_ready = self.on_job_ready - - def on_ack(job, i, time_accepted, pid, synqW_fd): - restart_state.R = 0 - try: - cache[job]._ack(i, time_accepted, pid, synqW_fd) - except (KeyError, AttributeError): - # Object gone or doesn't support _ack (e.g. IMAPIterator). - pass - - def on_ready(job, i, obj, inqW_fd): - if on_job_ready is not None: - on_job_ready(job, i, obj, inqW_fd) - try: - item = cache[job] - except KeyError: - return - if not item.ready(): - if putlock is not None: - putlock.release() - try: - item._set(i, obj) - except KeyError: - pass - - def on_death(pid, exitcode): - try: - os.kill(pid, signal.SIGTERM) - except OSError as exc: - if get_errno(exc) != errno.ESRCH: - raise - - state_handlers = self.state_handlers = { - ACK: on_ack, READY: on_ready, DEATH: on_death - } - - def on_state_change(task): - state, args = task - try: - state_handlers[state](*args) - except KeyError: - debug("Unknown job state: %s (args=%s)", state, args) - self.on_state_change = on_state_change - - def _process_result(self, timeout=1.0): - poll = self.poll - on_state_change = self.on_state_change - - while 1: - try: - ready, task = poll(timeout) - except (IOError, EOFError) as exc: - debug('result handler got %r -- exiting', exc) - raise CoroStop() - - if self._state: - assert self._state == TERMINATE - debug('result handler found thread._state=TERMINATE') - raise CoroStop() - - if ready: - if task is None: - debug('result handler got sentinel') - raise CoroStop() - on_state_change(task) - if timeout != 0: # blocking - break - else: - break - yield - - def handle_event(self, fileno=None, events=None): - if self._state == RUN: - if self._it is None: - self._it = self._process_result(0) # non-blocking - try: - next(self._it) - except (StopIteration, CoroStop): - self._it = None - - def body(self): - debug('result handler starting') - try: - while self._state == RUN: - try: - for _ in self._process_result(1.0): # blocking - pass - except CoroStop: - break - finally: - self.finish_at_shutdown() - - def finish_at_shutdown(self, handle_timeouts=False): - self._shutdown_complete = True - get = self.get - outqueue = self.outqueue - cache = self.cache - poll = self.poll - join_exited_workers = self.join_exited_workers - check_timeouts = self.check_timeouts - on_state_change = self.on_state_change - - time_terminate = None - while cache and self._state != TERMINATE: - if check_timeouts is not None: - check_timeouts() - try: - ready, task = poll(1.0) - except (IOError, EOFError) as exc: - debug('result handler got %r -- exiting', exc) - return - - if ready: - if task is None: - debug('result handler ignoring extra sentinel') - continue - - on_state_change(task) - try: - join_exited_workers(shutdown=True) - except WorkersJoined: - now = monotonic() - if not time_terminate: - time_terminate = now - else: - if now - time_terminate > 5.0: - debug('result handler exiting: timed out') - break - debug('result handler: all workers terminated, ' - 'timeout in %ss', - abs(min(now - time_terminate - 5.0, 0))) - - if hasattr(outqueue, '_reader'): - debug('ensuring that outqueue is not full') - # If we don't make room available in outqueue then - # attempts to add the sentinel (None) to outqueue may - # block. There is guaranteed to be no more than 2 sentinels. - try: - for i in range(10): - if not outqueue._reader.poll(): - break - get() - except (IOError, EOFError): - pass - - debug('result handler exiting: len(cache)=%s, thread._state=%s', - len(cache), self._state) - - -class Pool(object): - ''' - Class which supports an async version of applying functions to arguments. - ''' - Worker = Worker - Supervisor = Supervisor - TaskHandler = TaskHandler - TimeoutHandler = TimeoutHandler - ResultHandler = ResultHandler - SoftTimeLimitExceeded = SoftTimeLimitExceeded - - def __init__(self, processes=None, initializer=None, initargs=(), - maxtasksperchild=None, timeout=None, soft_timeout=None, - lost_worker_timeout=None, - max_restarts=None, max_restart_freq=1, - on_process_up=None, - on_process_down=None, - on_timeout_set=None, - on_timeout_cancel=None, - threads=True, - semaphore=None, - putlocks=False, - allow_restart=False, - synack=False, - on_process_exit=None, - **kwargs): - self.synack = synack - self._setup_queues() - self._taskqueue = Queue() - self._cache = {} - self._state = RUN - self.timeout = timeout - self.soft_timeout = soft_timeout - self._maxtasksperchild = maxtasksperchild - self._initializer = initializer - self._initargs = initargs - self._on_process_exit = on_process_exit - self.lost_worker_timeout = lost_worker_timeout or LOST_WORKER_TIMEOUT - self.on_process_up = on_process_up - self.on_process_down = on_process_down - self.on_timeout_set = on_timeout_set - self.on_timeout_cancel = on_timeout_cancel - self.threads = threads - self.readers = {} - self.allow_restart = allow_restart - - if soft_timeout and SIG_SOFT_TIMEOUT is None: - warnings.warn(UserWarning( - "Soft timeouts are not supported: " - "on this platform: It does not have the SIGUSR1 signal.", - )) - soft_timeout = None - - self._processes = self.cpu_count() if processes is None else processes - self.max_restarts = max_restarts or round(self._processes * 100) - self.restart_state = restart_state(max_restarts, max_restart_freq or 1) - - if initializer is not None and not callable(initializer): - raise TypeError('initializer must be a callable') - - if on_process_exit is not None and not callable(on_process_exit): - raise TypeError('on_process_exit must be callable') - - self._pool = [] - self._poolctrl = {} - self.putlocks = putlocks - self._putlock = semaphore or LaxBoundedSemaphore(self._processes) - for i in range(self._processes): - self._create_worker_process(i) - - self._worker_handler = self.Supervisor(self) - if threads: - self._worker_handler.start() - - self._task_handler = self.TaskHandler(self._taskqueue, - self._quick_put, - self._outqueue, - self._pool) - if threads: - self._task_handler.start() - - # Thread killing timedout jobs. - self._timeout_handler = self.TimeoutHandler( - self._pool, self._cache, - self.soft_timeout, self.timeout, - ) - self._timeout_handler_mutex = Lock() - self._timeout_handler_started = False - if self.timeout is not None or self.soft_timeout is not None: - self._start_timeout_handler() - - # If running without threads, we need to check for timeouts - # while waiting for unfinished work at shutdown. - self.check_timeouts = None - if not threads: - self.check_timeouts = self._timeout_handler.handle_event - - # Thread processing results in the outqueue. - self._result_handler = self.create_result_handler() - self.handle_result_event = self._result_handler.handle_event - - if threads: - self._result_handler.start() - - self._terminate = Finalize( - self, self._terminate_pool, - args=(self._taskqueue, self._inqueue, self._outqueue, - self._pool, self._worker_handler, self._task_handler, - self._result_handler, self._cache, - self._timeout_handler, - self._help_stuff_finish_args()), - exitpriority=15, - ) - - def create_result_handler(self, **extra_kwargs): - return self.ResultHandler( - self._outqueue, self._quick_get, self._cache, - self._poll_result, self._join_exited_workers, - self._putlock, self.restart_state, self.check_timeouts, - self.on_job_ready, **extra_kwargs - ) - - def on_job_ready(self, job, i, obj, inqW_fd): - pass - - def _help_stuff_finish_args(self): - return self._inqueue, self._task_handler, self._pool - - def cpu_count(self): - try: - return cpu_count() - except NotImplementedError: - return 1 - - def handle_result_event(self, *args): - return self._result_handler.handle_event(*args) - - def _process_register_queues(self, worker, queues): - pass - - def _process_by_pid(self, pid): - return next(( - (proc, i) for i, proc in enumerate(self._pool) - if proc.pid == pid - ), (None, None)) - - def get_process_queues(self): - return self._inqueue, self._outqueue, None - - def _create_worker_process(self, i): - sentinel = Event() if self.allow_restart else None - inq, outq, synq = self.get_process_queues() - w = self.Worker( - inq, outq, synq, self._initializer, self._initargs, - self._maxtasksperchild, sentinel, self._on_process_exit, - # Need to handle all signals if using the ipc semaphore, - # to make sure the semaphore is released. - sigprotection=self.threads, - ) - self._pool.append(w) - self._process_register_queues(w, (inq, outq, synq)) - w.name = w.name.replace('Process', 'PoolWorker') - w.daemon = True - w.index = i - w.start() - self._poolctrl[w.pid] = sentinel - if self.on_process_up: - self.on_process_up(w) - return w - - def process_flush_queues(self, worker): - pass - - def _join_exited_workers(self, shutdown=False): - """Cleanup after any worker processes which have exited due to - reaching their specified lifetime. Returns True if any workers were - cleaned up. - """ - now = None - # The worker may have published a result before being terminated, - # but we have no way to accurately tell if it did. So we wait for - # _lost_worker_timeout seconds before we mark the job with - # WorkerLostError. - for job in [job for job in list(self._cache.values()) - if not job.ready() and job._worker_lost]: - now = now or monotonic() - lost_time, lost_ret = job._worker_lost - if now - lost_time > job._lost_worker_timeout: - self.mark_as_worker_lost(job, lost_ret) - - if shutdown and not len(self._pool): - raise WorkersJoined() - - cleaned, exitcodes = {}, {} - for i in reversed(range(len(self._pool))): - worker = self._pool[i] - exitcode = worker.exitcode - popen = worker._popen - if popen is None or exitcode is not None: - # worker exited - debug('Supervisor: cleaning up worker %d', i) - if popen is not None: - worker.join() - debug('Supervisor: worked %d joined', i) - cleaned[worker.pid] = worker - exitcodes[worker.pid] = exitcode - if exitcode not in (EX_OK, EX_RECYCLE) and \ - not getattr(worker, '_controlled_termination', False): - error( - 'Process %r pid:%r exited with exitcode %r', - worker.name, worker.pid, exitcode, exc_info=0, - ) - self.process_flush_queues(worker) - del self._pool[i] - del self._poolctrl[worker.pid] - if cleaned: - all_pids = [w.pid for w in self._pool] - for job in list(self._cache.values()): - acked_by_gone = next( - (pid for pid in job.worker_pids() - if pid in cleaned or pid not in all_pids), - None - ) - # already accepted by process - if acked_by_gone: - self.on_job_process_down(job, acked_by_gone) - if not job.ready(): - exitcode = exitcodes.get(acked_by_gone) or 0 - proc = cleaned.get(acked_by_gone) - if proc and getattr(proc, '_job_terminated', False): - job._set_terminated(exitcode) - else: - self.on_job_process_lost( - job, acked_by_gone, exitcode, - ) - else: - # started writing to - write_to = job._write_to - # was scheduled to write to - sched_for = job._scheduled_for - - if write_to and not write_to._is_alive(): - self.on_job_process_down(job, write_to.pid) - elif sched_for and not sched_for._is_alive(): - self.on_job_process_down(job, sched_for.pid) - - for worker in values(cleaned): - if self.on_process_down: - if not shutdown: - self._process_cleanup_queues(worker) - self.on_process_down(worker) - return list(exitcodes.values()) - return [] - - def on_partial_read(self, job, worker): - pass - - def _process_cleanup_queues(self, worker): - pass - - def on_job_process_down(self, job, pid_gone): - pass - - def on_job_process_lost(self, job, pid, exitcode): - job._worker_lost = (monotonic(), exitcode) - - def mark_as_worker_lost(self, job, exitcode): - try: - raise WorkerLostError( - 'Worker exited prematurely: {0}.'.format( - human_status(exitcode)), - ) - except WorkerLostError: - job._set(None, (False, ExceptionInfo())) - else: # pragma: no cover - pass - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - return self.terminate() - - def on_grow(self, n): - pass - - def on_shrink(self, n): - pass - - def shrink(self, n=1): - for i, worker in enumerate(self._iterinactive()): - self._processes -= 1 - if self._putlock: - self._putlock.shrink() - worker.terminate_controlled() - self.on_shrink(1) - if i == n - 1: - return - raise ValueError("Can't shrink pool. All processes busy!") - - def grow(self, n=1): - for i in range(n): - self._processes += 1 - if self._putlock: - self._putlock.grow() - self.on_grow(n) - - def _iterinactive(self): - for worker in self._pool: - if not self._worker_active(worker): - yield worker - raise StopIteration() - - def _worker_active(self, worker): - for job in values(self._cache): - if worker.pid in job.worker_pids(): - return True - return False - - def _repopulate_pool(self, exitcodes): - """Bring the number of pool processes up to the specified number, - for use after reaping workers which have exited. - """ - for i in range(self._processes - len(self._pool)): - if self._state != RUN: - return - try: - if exitcodes and exitcodes[i] not in (EX_OK, EX_RECYCLE): - self.restart_state.step() - except IndexError: - self.restart_state.step() - self._create_worker_process(self._avail_index()) - debug('added worker') - - def _avail_index(self): - assert len(self._pool) < self._processes - indices = set(p.index for p in self._pool) - return next(i for i in range(self._processes) if i not in indices) - - def did_start_ok(self): - return not self._join_exited_workers() - - def _maintain_pool(self): - """"Clean up any exited workers and start replacements for them. - """ - joined = self._join_exited_workers() - self._repopulate_pool(joined) - for i in range(len(joined)): - if self._putlock is not None: - self._putlock.release() - - def maintain_pool(self): - if self._worker_handler._state == RUN and self._state == RUN: - try: - self._maintain_pool() - except RestartFreqExceeded: - self.close() - self.join() - raise - except OSError as exc: - if get_errno(exc) == errno.ENOMEM: - reraise(MemoryError, - MemoryError(str(exc)), - sys.exc_info()[2]) - raise - - def _setup_queues(self): - from billiard.queues import SimpleQueue - self._inqueue = SimpleQueue() - self._outqueue = SimpleQueue() - self._quick_put = self._inqueue._writer.send - self._quick_get = self._outqueue._reader.recv - - def _poll_result(timeout): - if self._outqueue._reader.poll(timeout): - return True, self._quick_get() - return False, None - self._poll_result = _poll_result - - def _start_timeout_handler(self): - # ensure more than one thread does not start the timeout handler - # thread at once. - if self.threads: - with self._timeout_handler_mutex: - if not self._timeout_handler_started: - self._timeout_handler_started = True - self._timeout_handler.start() - - def apply(self, func, args=(), kwds={}): - ''' - Equivalent of `func(*args, **kwargs)`. - ''' - if self._state == RUN: - return self.apply_async(func, args, kwds).get() - - def starmap(self, func, iterable, chunksize=None): - ''' - Like `map()` method but the elements of the `iterable` are expected to - be iterables as well and will be unpacked as arguments. Hence - `func` and (a, b) becomes func(a, b). - ''' - if self._state == RUN: - return self._map_async(func, iterable, - starmapstar, chunksize).get() - - def starmap_async(self, func, iterable, chunksize=None, - callback=None, error_callback=None): - ''' - Asynchronous version of `starmap()` method. - ''' - if self._state == RUN: - return self._map_async(func, iterable, starmapstar, chunksize, - callback, error_callback) - - def map(self, func, iterable, chunksize=None): - ''' - Apply `func` to each element in `iterable`, collecting the results - in a list that is returned. - ''' - if self._state == RUN: - return self.map_async(func, iterable, chunksize).get() - - def imap(self, func, iterable, chunksize=1, lost_worker_timeout=None): - ''' - Equivalent of `map()` -- can be MUCH slower than `Pool.map()`. - ''' - if self._state != RUN: - return - lost_worker_timeout = lost_worker_timeout or self.lost_worker_timeout - if chunksize == 1: - result = IMapIterator(self._cache, - lost_worker_timeout=lost_worker_timeout) - self._taskqueue.put(( - ((TASK, (result._job, i, func, (x,), {})) - for i, x in enumerate(iterable)), - result._set_length, - )) - return result - else: - assert chunksize > 1 - task_batches = Pool._get_tasks(func, iterable, chunksize) - result = IMapIterator(self._cache, - lost_worker_timeout=lost_worker_timeout) - self._taskqueue.put(( - ((TASK, (result._job, i, mapstar, (x,), {})) - for i, x in enumerate(task_batches)), - result._set_length, - )) - return (item for chunk in result for item in chunk) - - def imap_unordered(self, func, iterable, chunksize=1, - lost_worker_timeout=None): - ''' - Like `imap()` method but ordering of results is arbitrary. - ''' - if self._state != RUN: - return - lost_worker_timeout = lost_worker_timeout or self.lost_worker_timeout - if chunksize == 1: - result = IMapUnorderedIterator( - self._cache, lost_worker_timeout=lost_worker_timeout, - ) - self._taskqueue.put(( - ((TASK, (result._job, i, func, (x,), {})) - for i, x in enumerate(iterable)), - result._set_length, - )) - return result - else: - assert chunksize > 1 - task_batches = Pool._get_tasks(func, iterable, chunksize) - result = IMapUnorderedIterator( - self._cache, lost_worker_timeout=lost_worker_timeout, - ) - self._taskqueue.put(( - ((TASK, (result._job, i, mapstar, (x,), {})) - for i, x in enumerate(task_batches)), - result._set_length, - )) - return (item for chunk in result for item in chunk) - - def apply_async(self, func, args=(), kwds={}, - callback=None, error_callback=None, accept_callback=None, - timeout_callback=None, waitforslot=None, - soft_timeout=None, timeout=None, lost_worker_timeout=None, - callbacks_propagate=(), - correlation_id=None): - ''' - Asynchronous equivalent of `apply()` method. - - Callback is called when the functions return value is ready. - The accept callback is called when the job is accepted to be executed. - - Simplified the flow is like this: - - >>> def apply_async(func, args, kwds, callback, accept_callback): - ... if accept_callback: - ... accept_callback() - ... retval = func(*args, **kwds) - ... if callback: - ... callback(retval) - - ''' - if self._state != RUN: - return - soft_timeout = soft_timeout or self.soft_timeout - timeout = timeout or self.timeout - lost_worker_timeout = lost_worker_timeout or self.lost_worker_timeout - if soft_timeout and SIG_SOFT_TIMEOUT is None: - warnings.warn(UserWarning( - "Soft timeouts are not supported: " - "on this platform: It does not have the SIGUSR1 signal.", - )) - soft_timeout = None - if self._state == RUN: - waitforslot = self.putlocks if waitforslot is None else waitforslot - if waitforslot and self._putlock is not None: - self._putlock.acquire() - result = ApplyResult( - self._cache, callback, accept_callback, timeout_callback, - error_callback, soft_timeout, timeout, lost_worker_timeout, - on_timeout_set=self.on_timeout_set, - on_timeout_cancel=self.on_timeout_cancel, - callbacks_propagate=callbacks_propagate, - send_ack=self.send_ack if self.synack else None, - correlation_id=correlation_id, - ) - if timeout or soft_timeout: - # start the timeout handler thread when required. - self._start_timeout_handler() - if self.threads: - self._taskqueue.put(([(TASK, (result._job, None, - func, args, kwds))], None)) - else: - self._quick_put((TASK, (result._job, None, func, args, kwds))) - return result - - def send_ack(self, response, job, i, fd): - pass - - def terminate_job(self, pid, sig=None): - proc, _ = self._process_by_pid(pid) - if proc is not None: - try: - _kill(pid, sig or signal.SIGTERM) - except OSError as exc: - if get_errno(exc) != errno.ESRCH: - raise - else: - proc._controlled_termination = True - proc._job_terminated = True - - def map_async(self, func, iterable, chunksize=None, - callback=None, error_callback=None): - ''' - Asynchronous equivalent of `map()` method. - ''' - return self._map_async( - func, iterable, mapstar, chunksize, callback, error_callback, - ) - - def _map_async(self, func, iterable, mapper, chunksize=None, - callback=None, error_callback=None): - ''' - Helper function to implement map, starmap and their async counterparts. - ''' - if self._state != RUN: - return - if not hasattr(iterable, '__len__'): - iterable = list(iterable) - - if chunksize is None: - chunksize, extra = divmod(len(iterable), len(self._pool) * 4) - if extra: - chunksize += 1 - if len(iterable) == 0: - chunksize = 0 - - task_batches = Pool._get_tasks(func, iterable, chunksize) - result = MapResult(self._cache, chunksize, len(iterable), callback, - error_callback=error_callback) - self._taskqueue.put((((TASK, (result._job, i, mapper, (x,), {})) - for i, x in enumerate(task_batches)), None)) - return result - - @staticmethod - def _get_tasks(func, it, size): - it = iter(it) - while 1: - x = tuple(itertools.islice(it, size)) - if not x: - return - yield (func, x) - - def __reduce__(self): - raise NotImplementedError( - 'pool objects cannot be passed between processes or pickled', - ) - - def close(self): - debug('closing pool') - if self._state == RUN: - self._state = CLOSE - if self._putlock: - self._putlock.clear() - self._worker_handler.close() - self._taskqueue.put(None) - stop_if_not_current(self._worker_handler) - - def terminate(self): - debug('terminating pool') - self._state = TERMINATE - self._worker_handler.terminate() - self._terminate() - - @staticmethod - def _stop_task_handler(task_handler): - stop_if_not_current(task_handler) - - def join(self): - assert self._state in (CLOSE, TERMINATE) - debug('joining worker handler') - stop_if_not_current(self._worker_handler) - debug('joining task handler') - self._stop_task_handler(self._task_handler) - debug('joining result handler') - stop_if_not_current(self._result_handler) - debug('result handler joined') - for i, p in enumerate(self._pool): - debug('joining worker %s/%s (%r)', i+1, len(self._pool), p) - if p._popen is not None: # process started? - p.join() - debug('pool join complete') - - def restart(self): - for e in values(self._poolctrl): - e.set() - - @staticmethod - def _help_stuff_finish(inqueue, task_handler, _pool): - # task_handler may be blocked trying to put items on inqueue - debug('removing tasks from inqueue until task handler finished') - inqueue._rlock.acquire() - while task_handler.is_alive() and inqueue._reader.poll(): - inqueue._reader.recv() - time.sleep(0) - - @classmethod - def _set_result_sentinel(cls, outqueue, pool): - outqueue.put(None) - - @classmethod - def _terminate_pool(cls, taskqueue, inqueue, outqueue, pool, - worker_handler, task_handler, - result_handler, cache, timeout_handler, - help_stuff_finish_args): - - # this is guaranteed to only be called once - debug('finalizing pool') - - worker_handler.terminate() - - task_handler.terminate() - taskqueue.put(None) # sentinel - - debug('helping task handler/workers to finish') - cls._help_stuff_finish(*help_stuff_finish_args) - - result_handler.terminate() - cls._set_result_sentinel(outqueue, pool) - - if timeout_handler is not None: - timeout_handler.terminate() - - # Terminate workers which haven't already finished - if pool and hasattr(pool[0], 'terminate'): - debug('terminating workers') - for p in pool: - if p._is_alive(): - p.terminate() - - debug('joining task handler') - cls._stop_task_handler(task_handler) - - debug('joining result handler') - result_handler.stop() - - if timeout_handler is not None: - debug('joining timeout handler') - timeout_handler.stop(TIMEOUT_MAX) - - if pool and hasattr(pool[0], 'terminate'): - debug('joining pool workers') - for p in pool: - if p.is_alive(): - # worker has not yet exited - debug('cleaning up worker %d', p.pid) - if p._popen is not None: - p.join() - debug('pool workers joined') - - @property - def process_sentinels(self): - return [w._popen.sentinel for w in self._pool] - -# -# Class whose instances are returned by `Pool.apply_async()` -# - - -class ApplyResult(object): - _worker_lost = None - _write_to = None - _scheduled_for = None - - def __init__(self, cache, callback, accept_callback=None, - timeout_callback=None, error_callback=None, soft_timeout=None, - timeout=None, lost_worker_timeout=LOST_WORKER_TIMEOUT, - on_timeout_set=None, on_timeout_cancel=None, - callbacks_propagate=(), send_ack=None, - correlation_id=None): - self.correlation_id = correlation_id - self._mutex = Lock() - self._event = threading.Event() - self._job = next(job_counter) - self._cache = cache - self._callback = callback - self._accept_callback = accept_callback - self._error_callback = error_callback - self._timeout_callback = timeout_callback - self._timeout = timeout - self._terminated = None - self._soft_timeout = soft_timeout - self._lost_worker_timeout = lost_worker_timeout - self._on_timeout_set = on_timeout_set - self._on_timeout_cancel = on_timeout_cancel - self._callbacks_propagate = callbacks_propagate or () - self._send_ack = send_ack - - self._accepted = False - self._cancelled = False - self._worker_pid = None - self._time_accepted = None - cache[self._job] = self - - def __repr__(self): - return '<Result: {id} ack:{ack} ready:{ready}>'.format( - id=self._job, ack=self._accepted, ready=self.ready(), - ) - - def ready(self): - return self._event.isSet() - - def accepted(self): - return self._accepted - - def successful(self): - assert self.ready() - return self._success - - def _cancel(self): - """Only works if synack is used.""" - self._cancelled = True - - def discard(self): - self._cache.pop(self._job, None) - - def terminate(self, signum): - self._terminated = signum - - def _set_terminated(self, signum=None): - try: - raise Terminated(-(signum or 0)) - except Terminated: - self._set(None, (False, ExceptionInfo())) - - def worker_pids(self): - return [self._worker_pid] if self._worker_pid else [] - - def wait(self, timeout=None): - self._event.wait(timeout) - - def get(self, timeout=None): - self.wait(timeout) - if not self.ready(): - raise TimeoutError - if self._success: - return self._value - else: - raise self._value.exception - - def safe_apply_callback(self, fun, *args): - if fun: - try: - fun(*args) - except self._callbacks_propagate: - raise - except Exception as exc: - error('Pool callback raised exception: %r', exc, - exc_info=1) - - def _set(self, i, obj): - with self._mutex: - if self._on_timeout_cancel: - self._on_timeout_cancel(self) - self._success, self._value = obj - self._event.set() - if self._accepted: - # if not accepted yet, then the set message - # was received before the ack, which means - # the ack will remove the entry. - self._cache.pop(self._job, None) - - # apply callbacks last - if self._callback and self._success: - self.safe_apply_callback( - self._callback, self._value) - if (self._value is not None and - self._error_callback and not self._success): - self.safe_apply_callback( - self._error_callback, self._value) - - def _ack(self, i, time_accepted, pid, synqW_fd): - with self._mutex: - if self._cancelled and self._send_ack: - self._accepted = True - if synqW_fd: - return self._send_ack(NACK, pid, self._job, synqW_fd) - return - self._accepted = True - self._time_accepted = time_accepted - self._worker_pid = pid - if self.ready(): - # ack received after set() - self._cache.pop(self._job, None) - if self._on_timeout_set: - self._on_timeout_set(self, self._soft_timeout, self._timeout) - response = ACK - if self._accept_callback: - try: - self._accept_callback(pid, time_accepted) - except self._propagate_errors: - response = NACK - raise - except Exception: - response = NACK - # ignore other errors - finally: - if self._send_ack and synqW_fd: - return self._send_ack( - response, pid, self._job, synqW_fd - ) - if self._send_ack and synqW_fd: - self._send_ack(response, pid, self._job, synqW_fd) - -# -# Class whose instances are returned by `Pool.map_async()` -# - - -class MapResult(ApplyResult): - - def __init__(self, cache, chunksize, length, callback, error_callback): - ApplyResult.__init__( - self, cache, callback, error_callback=error_callback, - ) - self._success = True - self._length = length - self._value = [None] * length - self._accepted = [False] * length - self._worker_pid = [None] * length - self._time_accepted = [None] * length - self._chunksize = chunksize - if chunksize <= 0: - self._number_left = 0 - self._event.set() - del cache[self._job] - else: - self._number_left = length // chunksize + bool(length % chunksize) - - def _set(self, i, success_result): - success, result = success_result - if success: - self._value[i * self._chunksize:(i + 1) * self._chunksize] = result - self._number_left -= 1 - if self._number_left == 0: - if self._callback: - self._callback(self._value) - if self._accepted: - self._cache.pop(self._job, None) - self._event.set() - else: - self._success = False - self._value = result - if self._error_callback: - self._error_callback(self._value) - if self._accepted: - self._cache.pop(self._job, None) - self._event.set() - - def _ack(self, i, time_accepted, pid): - start = i * self._chunksize - stop = (i + 1) * self._chunksize - for j in range(start, stop): - self._accepted[j] = True - self._worker_pid[j] = pid - self._time_accepted[j] = time_accepted - if self.ready(): - self._cache.pop(self._job, None) - - def accepted(self): - return all(self._accepted) - - def worker_pids(self): - return [pid for pid in self._worker_pid if pid] - -# -# Class whose instances are returned by `Pool.imap()` -# - - -class IMapIterator(object): - _worker_lost = None - - def __init__(self, cache, lost_worker_timeout=LOST_WORKER_TIMEOUT): - self._cond = threading.Condition(threading.Lock()) - self._job = next(job_counter) - self._cache = cache - self._items = deque() - self._index = 0 - self._length = None - self._ready = False - self._unsorted = {} - self._worker_pids = [] - self._lost_worker_timeout = lost_worker_timeout - cache[self._job] = self - - def __iter__(self): - return self - - def next(self, timeout=None): - with self._cond: - try: - item = self._items.popleft() - except IndexError: - if self._index == self._length: - self._ready = True - raise StopIteration - self._cond.wait(timeout) - try: - item = self._items.popleft() - except IndexError: - if self._index == self._length: - self._ready = True - raise StopIteration - raise TimeoutError - - success, value = item - if success: - return value - raise Exception(value) - - __next__ = next # XXX - - def _set(self, i, obj): - with self._cond: - if self._index == i: - self._items.append(obj) - self._index += 1 - while self._index in self._unsorted: - obj = self._unsorted.pop(self._index) - self._items.append(obj) - self._index += 1 - self._cond.notify() - else: - self._unsorted[i] = obj - - if self._index == self._length: - self._ready = True - del self._cache[self._job] - - def _set_length(self, length): - with self._cond: - self._length = length - if self._index == self._length: - self._ready = True - self._cond.notify() - del self._cache[self._job] - - def _ack(self, i, time_accepted, pid): - self._worker_pids.append(pid) - - def ready(self): - return self._ready - - def worker_pids(self): - return self._worker_pids - -# -# Class whose instances are returned by `Pool.imap_unordered()` -# - - -class IMapUnorderedIterator(IMapIterator): - - def _set(self, i, obj): - with self._cond: - self._items.append(obj) - self._index += 1 - self._cond.notify() - if self._index == self._length: - self._ready = True - del self._cache[self._job] - -# -# -# - - -class ThreadPool(Pool): - - from billiard.dummy import Process as DummyProcess - Process = DummyProcess - - def __init__(self, processes=None, initializer=None, initargs=()): - Pool.__init__(self, processes, initializer, initargs) - - def _setup_queues(self): - self._inqueue = Queue() - self._outqueue = Queue() - self._quick_put = self._inqueue.put - self._quick_get = self._outqueue.get - - def _poll_result(timeout): - try: - return True, self._quick_get(timeout=timeout) - except Empty: - return False, None - self._poll_result = _poll_result - - @staticmethod - def _help_stuff_finish(inqueue, task_handler, pool): - # put sentinels at head of inqueue to make workers finish - with inqueue.not_empty: - inqueue.queue.clear() - inqueue.queue.extend([None] * len(pool)) - inqueue.not_empty.notify_all() diff --git a/awx/lib/site-packages/billiard/process.py b/awx/lib/site-packages/billiard/process.py deleted file mode 100644 index f3d01d13f2..0000000000 --- a/awx/lib/site-packages/billiard/process.py +++ /dev/null @@ -1,368 +0,0 @@ -# -# Module providing the `Process` class which emulates `threading.Thread` -# -# multiprocessing/process.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -__all__ = ['Process', 'current_process', 'active_children'] - -# -# Imports -# - -import os -import sys -import signal -import itertools -import binascii -import logging -import threading - -from multiprocessing import process as _mproc - -from .compat import bytes -try: - from _weakrefset import WeakSet -except ImportError: - WeakSet = None # noqa -from .five import items, string_t - -try: - ORIGINAL_DIR = os.path.abspath(os.getcwd()) -except OSError: - ORIGINAL_DIR = None - -# -# Public functions -# - - -def current_process(): - ''' - Return process object representing the current process - ''' - return _current_process - - -def _set_current_process(process): - global _current_process - _current_process = _mproc._current_process = process - - -def _cleanup(): - # check for processes which have finished - if _current_process is not None: - for p in list(_current_process._children): - if p._popen.poll() is not None: - _current_process._children.discard(p) - - -def _maybe_flush(f): - try: - f.flush() - except (AttributeError, EnvironmentError, NotImplementedError): - pass - - -def active_children(_cleanup=_cleanup): - ''' - Return list of process objects corresponding to live child processes - ''' - try: - _cleanup() - except TypeError: - # called after gc collect so _cleanup does not exist anymore - return [] - if _current_process is not None: - return list(_current_process._children) - return [] - - -class Process(object): - ''' - Process objects represent activity that is run in a separate process - - The class is analagous to `threading.Thread` - ''' - _Popen = None - - def __init__(self, group=None, target=None, name=None, - args=(), kwargs={}, daemon=None, **_kw): - assert group is None, 'group argument must be None for now' - count = next(_current_process._counter) - self._identity = _current_process._identity + (count,) - self._authkey = _current_process._authkey - if daemon is not None: - self._daemonic = daemon - else: - self._daemonic = _current_process._daemonic - self._tempdir = _current_process._tempdir - self._semprefix = _current_process._semprefix - self._unlinkfd = _current_process._unlinkfd - self._parent_pid = os.getpid() - self._popen = None - self._target = target - self._args = tuple(args) - self._kwargs = dict(kwargs) - self._name = ( - name or type(self).__name__ + '-' + - ':'.join(str(i) for i in self._identity) - ) - if _dangling is not None: - _dangling.add(self) - - def run(self): - ''' - Method to be run in sub-process; can be overridden in sub-class - ''' - if self._target: - self._target(*self._args, **self._kwargs) - - def start(self): - ''' - Start child process - ''' - assert self._popen is None, 'cannot start a process twice' - assert self._parent_pid == os.getpid(), \ - 'can only start a process object created by current process' - _cleanup() - if self._Popen is not None: - Popen = self._Popen - else: - from .forking import Popen - self._popen = Popen(self) - self._sentinel = self._popen.sentinel - _current_process._children.add(self) - - def terminate(self): - ''' - Terminate process; sends SIGTERM signal or uses TerminateProcess() - ''' - self._popen.terminate() - - def join(self, timeout=None): - ''' - Wait until child process terminates - ''' - assert self._parent_pid == os.getpid(), 'can only join a child process' - assert self._popen is not None, 'can only join a started process' - res = self._popen.wait(timeout) - if res is not None: - _current_process._children.discard(self) - - def is_alive(self): - ''' - Return whether process is alive - ''' - if self is _current_process: - return True - assert self._parent_pid == os.getpid(), 'can only test a child process' - if self._popen is None: - return False - self._popen.poll() - return self._popen.returncode is None - - def _is_alive(self): - if self._popen is None: - return False - return self._popen.poll() is None - - def _get_name(self): - return self._name - - def _set_name(self, value): - assert isinstance(name, string_t), 'name must be a string' - self._name = value - name = property(_get_name, _set_name) - - def _get_daemon(self): - return self._daemonic - - def _set_daemon(self, daemonic): - assert self._popen is None, 'process has already started' - self._daemonic = daemonic - daemon = property(_get_daemon, _set_daemon) - - def _get_authkey(self): - return self._authkey - - def _set_authkey(self, authkey): - self._authkey = AuthenticationString(authkey) - authkey = property(_get_authkey, _set_authkey) - - @property - def exitcode(self): - ''' - Return exit code of process or `None` if it has yet to stop - ''' - if self._popen is None: - return self._popen - return self._popen.poll() - - @property - def ident(self): - ''' - Return identifier (PID) of process or `None` if it has yet to start - ''' - if self is _current_process: - return os.getpid() - else: - return self._popen and self._popen.pid - - pid = ident - - @property - def sentinel(self): - ''' - Return a file descriptor (Unix) or handle (Windows) suitable for - waiting for process termination. - ''' - try: - return self._sentinel - except AttributeError: - raise ValueError("process not started") - - def __repr__(self): - if self is _current_process: - status = 'started' - elif self._parent_pid != os.getpid(): - status = 'unknown' - elif self._popen is None: - status = 'initial' - else: - if self._popen.poll() is not None: - status = self.exitcode - else: - status = 'started' - - if type(status) is int: - if status == 0: - status = 'stopped' - else: - status = 'stopped[%s]' % _exitcode_to_name.get(status, status) - - return '<%s(%s, %s%s)>' % (type(self).__name__, self._name, - status, self._daemonic and ' daemon' or '') - - ## - - def _bootstrap(self): - from . import util - global _current_process - - try: - self._children = set() - self._counter = itertools.count(1) - if sys.stdin is not None: - try: - sys.stdin.close() - sys.stdin = open(os.devnull) - except (OSError, ValueError): - pass - old_process = _current_process - _set_current_process(self) - - # Re-init logging system. - # Workaround for http://bugs.python.org/issue6721/#msg140215 - # Python logging module uses RLock() objects which are broken - # after fork. This can result in a deadlock (Celery Issue #496). - loggerDict = logging.Logger.manager.loggerDict - logger_names = list(loggerDict.keys()) - logger_names.append(None) # for root logger - for name in logger_names: - if not name or not isinstance(loggerDict[name], - logging.PlaceHolder): - for handler in logging.getLogger(name).handlers: - handler.createLock() - logging._lock = threading.RLock() - - try: - util._finalizer_registry.clear() - util._run_after_forkers() - finally: - # delay finalization of the old process object until after - # _run_after_forkers() is executed - del old_process - util.info('child process %s calling self.run()', self.pid) - try: - self.run() - exitcode = 0 - finally: - util._exit_function() - except SystemExit as exc: - if not exc.args: - exitcode = 1 - elif isinstance(exc.args[0], int): - exitcode = exc.args[0] - else: - sys.stderr.write(str(exc.args[0]) + '\n') - _maybe_flush(sys.stderr) - exitcode = 0 if isinstance(exc.args[0], str) else 1 - except: - exitcode = 1 - if not util.error('Process %s', self.name, exc_info=True): - import traceback - sys.stderr.write('Process %s:\n' % self.name) - traceback.print_exc() - finally: - util.info('process %s exiting with exitcode %d', - self.pid, exitcode) - _maybe_flush(sys.stdout) - _maybe_flush(sys.stderr) - return exitcode - -# -# We subclass bytes to avoid accidental transmission of auth keys over network -# - - -class AuthenticationString(bytes): - - def __reduce__(self): - from .forking import Popen - - if not Popen.thread_is_spawning(): - raise TypeError( - 'Pickling an AuthenticationString object is ' - 'disallowed for security reasons') - return AuthenticationString, (bytes(self),) - -# -# Create object representing the main process -# - - -class _MainProcess(Process): - - def __init__(self): - self._identity = () - self._daemonic = False - self._name = 'MainProcess' - self._parent_pid = None - self._popen = None - self._counter = itertools.count(1) - self._children = set() - self._authkey = AuthenticationString(os.urandom(32)) - self._tempdir = None - self._semprefix = 'mp-' + binascii.hexlify( - os.urandom(4)).decode('ascii') - self._unlinkfd = None - -_current_process = _MainProcess() -del _MainProcess - -# -# Give names to some return codes -# - -_exitcode_to_name = {} - -for name, signum in items(signal.__dict__): - if name[:3] == 'SIG' and '_' not in name: - _exitcode_to_name[-signum] = name - -_dangling = WeakSet() if WeakSet is not None else None diff --git a/awx/lib/site-packages/billiard/py2/__init__.py b/awx/lib/site-packages/billiard/py2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/billiard/py2/connection.py b/awx/lib/site-packages/billiard/py2/connection.py deleted file mode 100644 index d2b865e23e..0000000000 --- a/awx/lib/site-packages/billiard/py2/connection.py +++ /dev/null @@ -1,492 +0,0 @@ -# -# A higher level module for using sockets (or Windows named pipes) -# -# multiprocessing/connection.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# - -from __future__ import absolute_import - -__all__ = ['Client', 'Listener', 'Pipe'] - -import os -import sys -import socket -import errno -import time -import tempfile -import itertools - -from .. import AuthenticationError -from .. import reduction -from .._ext import _billiard, win32 -from ..compat import get_errno, setblocking, bytes as cbytes -from ..five import monotonic -from ..forking import duplicate, close -from ..reduction import ForkingPickler -from ..util import get_temp_dir, Finalize, sub_debug, debug - -try: - WindowsError = WindowsError # noqa -except NameError: - WindowsError = None # noqa - - -# global set later -xmlrpclib = None - -Connection = getattr(_billiard, 'Connection', None) -PipeConnection = getattr(_billiard, 'PipeConnection', None) - - -# -# -# - -BUFSIZE = 8192 -# A very generous timeout when it comes to local connections... -CONNECTION_TIMEOUT = 20. - -_mmap_counter = itertools.count() - -default_family = 'AF_INET' -families = ['AF_INET'] - -if hasattr(socket, 'AF_UNIX'): - default_family = 'AF_UNIX' - families += ['AF_UNIX'] - -if sys.platform == 'win32': - default_family = 'AF_PIPE' - families += ['AF_PIPE'] - - -def _init_timeout(timeout=CONNECTION_TIMEOUT): - return monotonic() + timeout - - -def _check_timeout(t): - return monotonic() > t - -# -# -# - - -def arbitrary_address(family): - ''' - Return an arbitrary free address for the given family - ''' - if family == 'AF_INET': - return ('localhost', 0) - elif family == 'AF_UNIX': - return tempfile.mktemp(prefix='listener-', dir=get_temp_dir()) - elif family == 'AF_PIPE': - return tempfile.mktemp(prefix=r'\\.\pipe\pyc-%d-%d-' % - (os.getpid(), next(_mmap_counter))) - else: - raise ValueError('unrecognized family') - - -def address_type(address): - ''' - Return the types of the address - - This can be 'AF_INET', 'AF_UNIX', or 'AF_PIPE' - ''' - if type(address) == tuple: - return 'AF_INET' - elif type(address) is str and address.startswith('\\\\'): - return 'AF_PIPE' - elif type(address) is str: - return 'AF_UNIX' - else: - raise ValueError('address type of %r unrecognized' % address) - -# -# Public functions -# - - -class Listener(object): - ''' - Returns a listener object. - - This is a wrapper for a bound socket which is 'listening' for - connections, or for a Windows named pipe. - ''' - def __init__(self, address=None, family=None, backlog=1, authkey=None): - family = (family or - (address and address_type(address)) or - default_family) - address = address or arbitrary_address(family) - - if family == 'AF_PIPE': - self._listener = PipeListener(address, backlog) - else: - self._listener = SocketListener(address, family, backlog) - - if authkey is not None and not isinstance(authkey, bytes): - raise TypeError('authkey should be a byte string') - - self._authkey = authkey - - def accept(self): - ''' - Accept a connection on the bound socket or named pipe of `self`. - - Returns a `Connection` object. - ''' - if self._listener is None: - raise IOError('listener is closed') - c = self._listener.accept() - if self._authkey: - deliver_challenge(c, self._authkey) - answer_challenge(c, self._authkey) - return c - - def close(self): - ''' - Close the bound socket or named pipe of `self`. - ''' - if self._listener is not None: - self._listener.close() - self._listener = None - - address = property(lambda self: self._listener._address) - last_accepted = property(lambda self: self._listener._last_accepted) - - def __enter__(self): - return self - - def __exit__(self, *exc_args): - self.close() - - -def Client(address, family=None, authkey=None): - ''' - Returns a connection to the address of a `Listener` - ''' - family = family or address_type(address) - if family == 'AF_PIPE': - c = PipeClient(address) - else: - c = SocketClient(address) - - if authkey is not None and not isinstance(authkey, bytes): - raise TypeError('authkey should be a byte string') - - if authkey is not None: - answer_challenge(c, authkey) - deliver_challenge(c, authkey) - - return c - - -if sys.platform != 'win32': - - def Pipe(duplex=True, rnonblock=False, wnonblock=False): - ''' - Returns pair of connection objects at either end of a pipe - ''' - if duplex: - s1, s2 = socket.socketpair() - s1.setblocking(not rnonblock) - s2.setblocking(not wnonblock) - c1 = Connection(os.dup(s1.fileno())) - c2 = Connection(os.dup(s2.fileno())) - s1.close() - s2.close() - else: - fd1, fd2 = os.pipe() - if rnonblock: - setblocking(fd1, 0) - if wnonblock: - setblocking(fd2, 0) - c1 = Connection(fd1, writable=False) - c2 = Connection(fd2, readable=False) - - return c1, c2 - -else: - - def Pipe(duplex=True, rnonblock=False, wnonblock=False): # noqa - ''' - Returns pair of connection objects at either end of a pipe - ''' - address = arbitrary_address('AF_PIPE') - if duplex: - openmode = win32.PIPE_ACCESS_DUPLEX - access = win32.GENERIC_READ | win32.GENERIC_WRITE - obsize, ibsize = BUFSIZE, BUFSIZE - else: - openmode = win32.PIPE_ACCESS_INBOUND - access = win32.GENERIC_WRITE - obsize, ibsize = 0, BUFSIZE - - h1 = win32.CreateNamedPipe( - address, openmode, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - 1, obsize, ibsize, win32.NMPWAIT_WAIT_FOREVER, win32.NULL - ) - h2 = win32.CreateFile( - address, access, 0, win32.NULL, win32.OPEN_EXISTING, 0, win32.NULL - ) - win32.SetNamedPipeHandleState( - h2, win32.PIPE_READMODE_MESSAGE, None, None - ) - - try: - win32.ConnectNamedPipe(h1, win32.NULL) - except WindowsError as exc: - if exc.args[0] != win32.ERROR_PIPE_CONNECTED: - raise - - c1 = PipeConnection(h1, writable=duplex) - c2 = PipeConnection(h2, readable=duplex) - - return c1, c2 - -# -# Definitions for connections based on sockets -# - - -class SocketListener(object): - ''' - Representation of a socket which is bound to an address and listening - ''' - def __init__(self, address, family, backlog=1): - self._socket = socket.socket(getattr(socket, family)) - try: - # SO_REUSEADDR has different semantics on Windows (Issue #2550). - if os.name == 'posix': - self._socket.setsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR, 1) - self._socket.bind(address) - self._socket.listen(backlog) - self._address = self._socket.getsockname() - except OSError: - self._socket.close() - raise - self._family = family - self._last_accepted = None - - if family == 'AF_UNIX': - self._unlink = Finalize( - self, os.unlink, args=(address,), exitpriority=0 - ) - else: - self._unlink = None - - def accept(self): - s, self._last_accepted = self._socket.accept() - fd = duplicate(s.fileno()) - conn = Connection(fd) - s.close() - return conn - - def close(self): - self._socket.close() - if self._unlink is not None: - self._unlink() - - -def SocketClient(address): - ''' - Return a connection object connected to the socket given by `address` - ''' - family = address_type(address) - s = socket.socket(getattr(socket, family)) - t = _init_timeout() - - while 1: - try: - s.connect(address) - except socket.error as exc: - if get_errno(exc) != errno.ECONNREFUSED or _check_timeout(t): - debug('failed to connect to address %s', address) - raise - time.sleep(0.01) - else: - break - else: - raise - - fd = duplicate(s.fileno()) - conn = Connection(fd) - s.close() - return conn - -# -# Definitions for connections based on named pipes -# - -if sys.platform == 'win32': - - class PipeListener(object): - ''' - Representation of a named pipe - ''' - def __init__(self, address, backlog=None): - self._address = address - handle = win32.CreateNamedPipe( - address, win32.PIPE_ACCESS_DUPLEX, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - win32.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, - win32.NMPWAIT_WAIT_FOREVER, win32.NULL - ) - self._handle_queue = [handle] - self._last_accepted = None - - sub_debug('listener created with address=%r', self._address) - - self.close = Finalize( - self, PipeListener._finalize_pipe_listener, - args=(self._handle_queue, self._address), exitpriority=0 - ) - - def accept(self): - newhandle = win32.CreateNamedPipe( - self._address, win32.PIPE_ACCESS_DUPLEX, - win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | - win32.PIPE_WAIT, - win32.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, - win32.NMPWAIT_WAIT_FOREVER, win32.NULL - ) - self._handle_queue.append(newhandle) - handle = self._handle_queue.pop(0) - try: - win32.ConnectNamedPipe(handle, win32.NULL) - except WindowsError as exc: - if exc.args[0] != win32.ERROR_PIPE_CONNECTED: - raise - return PipeConnection(handle) - - @staticmethod - def _finalize_pipe_listener(queue, address): - sub_debug('closing listener with address=%r', address) - for handle in queue: - close(handle) - - def PipeClient(address): - ''' - Return a connection object connected to the pipe given by `address` - ''' - t = _init_timeout() - while 1: - try: - win32.WaitNamedPipe(address, 1000) - h = win32.CreateFile( - address, win32.GENERIC_READ | win32.GENERIC_WRITE, - 0, win32.NULL, win32.OPEN_EXISTING, 0, win32.NULL, - ) - except WindowsError as exc: - if exc.args[0] not in ( - win32.ERROR_SEM_TIMEOUT, - win32.ERROR_PIPE_BUSY) or _check_timeout(t): - raise - else: - break - else: - raise - - win32.SetNamedPipeHandleState( - h, win32.PIPE_READMODE_MESSAGE, None, None - ) - return PipeConnection(h) - -# -# Authentication stuff -# - -MESSAGE_LENGTH = 20 - -CHALLENGE = cbytes('#CHALLENGE#', 'ascii') -WELCOME = cbytes('#WELCOME#', 'ascii') -FAILURE = cbytes('#FAILURE#', 'ascii') - - -def deliver_challenge(connection, authkey): - import hmac - assert isinstance(authkey, bytes) - message = os.urandom(MESSAGE_LENGTH) - connection.send_bytes(CHALLENGE + message) - digest = hmac.new(authkey, message).digest() - response = connection.recv_bytes(256) # reject large message - if response == digest: - connection.send_bytes(WELCOME) - else: - connection.send_bytes(FAILURE) - raise AuthenticationError('digest received was wrong') - - -def answer_challenge(connection, authkey): - import hmac - assert isinstance(authkey, bytes) - message = connection.recv_bytes(256) # reject large message - assert message[:len(CHALLENGE)] == CHALLENGE, 'message = %r' % message - message = message[len(CHALLENGE):] - digest = hmac.new(authkey, message).digest() - connection.send_bytes(digest) - response = connection.recv_bytes(256) # reject large message - if response != WELCOME: - raise AuthenticationError('digest sent was rejected') - -# -# Support for using xmlrpclib for serialization -# - - -class ConnectionWrapper(object): - def __init__(self, conn, dumps, loads): - self._conn = conn - self._dumps = dumps - self._loads = loads - for attr in ('fileno', 'close', 'poll', 'recv_bytes', 'send_bytes'): - obj = getattr(conn, attr) - setattr(self, attr, obj) - - def send(self, obj): - s = self._dumps(obj) - self._conn.send_bytes(s) - - def recv(self): - s = self._conn.recv_bytes() - return self._loads(s) - - -def _xml_dumps(obj): - return xmlrpclib.dumps((obj,), None, None, None, 1).encode('utf8') - - -def _xml_loads(s): - (obj,), method = xmlrpclib.loads(s.decode('utf8')) - return obj - - -class XmlListener(Listener): - def accept(self): - global xmlrpclib - import xmlrpclib # noqa - obj = Listener.accept(self) - return ConnectionWrapper(obj, _xml_dumps, _xml_loads) - - -def XmlClient(*args, **kwds): - global xmlrpclib - import xmlrpclib # noqa - return ConnectionWrapper(Client(*args, **kwds), _xml_dumps, _xml_loads) - - -if sys.platform == 'win32': - ForkingPickler.register(socket.socket, reduction.reduce_socket) - ForkingPickler.register(Connection, reduction.reduce_connection) - ForkingPickler.register(PipeConnection, reduction.reduce_pipe_connection) -else: - ForkingPickler.register(socket.socket, reduction.reduce_socket) - ForkingPickler.register(Connection, reduction.reduce_connection) diff --git a/awx/lib/site-packages/billiard/py2/reduction.py b/awx/lib/site-packages/billiard/py2/reduction.py deleted file mode 100644 index b6cde35c86..0000000000 --- a/awx/lib/site-packages/billiard/py2/reduction.py +++ /dev/null @@ -1,248 +0,0 @@ -# -# Module to allow connection and socket objects to be transferred -# between processes -# -# multiprocessing/reduction.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# - -from __future__ import absolute_import - -__all__ = [] - -import os -import sys -import socket -import threading - -from pickle import Pickler - -from .. import current_process -from .._ext import _billiard, win32 -from ..util import register_after_fork, debug, sub_debug - -is_win32 = sys.platform == 'win32' -is_pypy = hasattr(sys, 'pypy_version_info') -is_py3k = sys.version_info[0] == 3 - -if not(is_win32 or is_pypy or is_py3k or hasattr(_billiard, 'recvfd')): - raise ImportError('pickling of connections not supported') - -close = win32.CloseHandle if sys.platform == 'win32' else os.close - -# globals set later -_listener = None -_lock = None -_cache = set() - -# -# ForkingPickler -# - - -class ForkingPickler(Pickler): # noqa - dispatch = Pickler.dispatch.copy() - - @classmethod - def register(cls, type, reduce): - def dispatcher(self, obj): - rv = reduce(obj) - self.save_reduce(obj=obj, *rv) - cls.dispatch[type] = dispatcher - - -def _reduce_method(m): # noqa - if m.__self__ is None: - return getattr, (m.__self__.__class__, m.__func__.__name__) - else: - return getattr, (m.__self__, m.__func__.__name__) -ForkingPickler.register(type(ForkingPickler.save), _reduce_method) - - -def _reduce_method_descriptor(m): - return getattr, (m.__objclass__, m.__name__) -ForkingPickler.register(type(list.append), _reduce_method_descriptor) -ForkingPickler.register(type(int.__add__), _reduce_method_descriptor) - -try: - from functools import partial -except ImportError: - pass -else: - - def _reduce_partial(p): - return _rebuild_partial, (p.func, p.args, p.keywords or {}) - - def _rebuild_partial(func, args, keywords): - return partial(func, *args, **keywords) - ForkingPickler.register(partial, _reduce_partial) - - -def dump(obj, file, protocol=None): - ForkingPickler(file, protocol).dump(obj) - -# -# Platform specific definitions -# - -if sys.platform == 'win32': - # XXX Should this subprocess import be here? - import _subprocess # noqa - - def send_handle(conn, handle, destination_pid): - from ..forking import duplicate - process_handle = win32.OpenProcess( - win32.PROCESS_ALL_ACCESS, False, destination_pid - ) - try: - new_handle = duplicate(handle, process_handle) - conn.send(new_handle) - finally: - close(process_handle) - - def recv_handle(conn): - return conn.recv() - -else: - def send_handle(conn, handle, destination_pid): # noqa - _billiard.sendfd(conn.fileno(), handle) - - def recv_handle(conn): # noqa - return _billiard.recvfd(conn.fileno()) - -# -# Support for a per-process server thread which caches pickled handles -# - - -def _reset(obj): - global _lock, _listener, _cache - for h in _cache: - close(h) - _cache.clear() - _lock = threading.Lock() - _listener = None - -_reset(None) -register_after_fork(_reset, _reset) - - -def _get_listener(): - global _listener - - if _listener is None: - _lock.acquire() - try: - if _listener is None: - from ..connection import Listener - debug('starting listener and thread for sending handles') - _listener = Listener(authkey=current_process().authkey) - t = threading.Thread(target=_serve) - t.daemon = True - t.start() - finally: - _lock.release() - - return _listener - - -def _serve(): - from ..util import is_exiting, sub_warning - - while 1: - try: - conn = _listener.accept() - handle_wanted, destination_pid = conn.recv() - _cache.remove(handle_wanted) - send_handle(conn, handle_wanted, destination_pid) - close(handle_wanted) - conn.close() - except: - if not is_exiting(): - sub_warning('thread for sharing handles raised exception', - exc_info=True) - -# -# Functions to be used for pickling/unpickling objects with handles -# - - -def reduce_handle(handle): - from ..forking import Popen, duplicate - if Popen.thread_is_spawning(): - return (None, Popen.duplicate_for_child(handle), True) - dup_handle = duplicate(handle) - _cache.add(dup_handle) - sub_debug('reducing handle %d', handle) - return (_get_listener().address, dup_handle, False) - - -def rebuild_handle(pickled_data): - from ..connection import Client - address, handle, inherited = pickled_data - if inherited: - return handle - sub_debug('rebuilding handle %d', handle) - conn = Client(address, authkey=current_process().authkey) - conn.send((handle, os.getpid())) - new_handle = recv_handle(conn) - conn.close() - return new_handle - -# -# Register `_billiard.Connection` with `ForkingPickler` -# - - -def reduce_connection(conn): - rh = reduce_handle(conn.fileno()) - return rebuild_connection, (rh, conn.readable, conn.writable) - - -def rebuild_connection(reduced_handle, readable, writable): - handle = rebuild_handle(reduced_handle) - return _billiard.Connection( - handle, readable=readable, writable=writable - ) - -# Register `socket.socket` with `ForkingPickler` -# - - -def fromfd(fd, family, type_, proto=0): - s = socket.fromfd(fd, family, type_, proto) - if s.__class__ is not socket.socket: - s = socket.socket(_sock=s) - return s - - -def reduce_socket(s): - reduced_handle = reduce_handle(s.fileno()) - return rebuild_socket, (reduced_handle, s.family, s.type, s.proto) - - -def rebuild_socket(reduced_handle, family, type_, proto): - fd = rebuild_handle(reduced_handle) - _sock = fromfd(fd, family, type_, proto) - close(fd) - return _sock - -ForkingPickler.register(socket.socket, reduce_socket) - -# -# Register `_billiard.PipeConnection` with `ForkingPickler` -# - -if sys.platform == 'win32': - - def reduce_pipe_connection(conn): - rh = reduce_handle(conn.fileno()) - return rebuild_pipe_connection, (rh, conn.readable, conn.writable) - - def rebuild_pipe_connection(reduced_handle, readable, writable): - handle = rebuild_handle(reduced_handle) - return _billiard.PipeConnection( - handle, readable=readable, writable=writable - ) diff --git a/awx/lib/site-packages/billiard/queues.py b/awx/lib/site-packages/billiard/queues.py deleted file mode 100644 index c3d15ff6d7..0000000000 --- a/awx/lib/site-packages/billiard/queues.py +++ /dev/null @@ -1,372 +0,0 @@ -# -# Module implementing queues -# -# multiprocessing/queues.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -__all__ = ['Queue', 'SimpleQueue', 'JoinableQueue'] - -import sys -import os -import threading -import collections -import weakref -import errno - -from . import Pipe -from ._ext import _billiard -from .compat import get_errno -from .five import monotonic -from .synchronize import Lock, BoundedSemaphore, Semaphore, Condition -from .util import debug, error, info, Finalize, register_after_fork -from .five import Empty, Full -from .forking import assert_spawning - - -class Queue(object): - ''' - Queue type using a pipe, buffer and thread - ''' - def __init__(self, maxsize=0): - if maxsize <= 0: - maxsize = _billiard.SemLock.SEM_VALUE_MAX - self._maxsize = maxsize - self._reader, self._writer = Pipe(duplex=False) - self._rlock = Lock() - self._opid = os.getpid() - if sys.platform == 'win32': - self._wlock = None - else: - self._wlock = Lock() - self._sem = BoundedSemaphore(maxsize) - # For use by concurrent.futures - self._ignore_epipe = False - - self._after_fork() - - if sys.platform != 'win32': - register_after_fork(self, Queue._after_fork) - - def __getstate__(self): - assert_spawning(self) - return (self._ignore_epipe, self._maxsize, self._reader, self._writer, - self._rlock, self._wlock, self._sem, self._opid) - - def __setstate__(self, state): - (self._ignore_epipe, self._maxsize, self._reader, self._writer, - self._rlock, self._wlock, self._sem, self._opid) = state - self._after_fork() - - def _after_fork(self): - debug('Queue._after_fork()') - self._notempty = threading.Condition(threading.Lock()) - self._buffer = collections.deque() - self._thread = None - self._jointhread = None - self._joincancelled = False - self._closed = False - self._close = None - self._send = self._writer.send - self._recv = self._reader.recv - self._poll = self._reader.poll - - def put(self, obj, block=True, timeout=None): - assert not self._closed - if not self._sem.acquire(block, timeout): - raise Full - - with self._notempty: - if self._thread is None: - self._start_thread() - self._buffer.append(obj) - self._notempty.notify() - - def get(self, block=True, timeout=None): - if block and timeout is None: - with self._rlock: - res = self._recv() - self._sem.release() - return res - - else: - if block: - deadline = monotonic() + timeout - if not self._rlock.acquire(block, timeout): - raise Empty - try: - if block: - timeout = deadline - monotonic() - if timeout < 0 or not self._poll(timeout): - raise Empty - elif not self._poll(): - raise Empty - res = self._recv() - self._sem.release() - return res - finally: - self._rlock.release() - - def qsize(self): - # Raises NotImplementedError on Mac OSX because - # of broken sem_getvalue() - return self._maxsize - self._sem._semlock._get_value() - - def empty(self): - return not self._poll() - - def full(self): - return self._sem._semlock._is_zero() - - def get_nowait(self): - return self.get(False) - - def put_nowait(self, obj): - return self.put(obj, False) - - def close(self): - self._closed = True - self._reader.close() - if self._close: - self._close() - - def join_thread(self): - debug('Queue.join_thread()') - assert self._closed - if self._jointhread: - self._jointhread() - - def cancel_join_thread(self): - debug('Queue.cancel_join_thread()') - self._joincancelled = True - try: - self._jointhread.cancel() - except AttributeError: - pass - - def _start_thread(self): - debug('Queue._start_thread()') - - # Start thread which transfers data from buffer to pipe - self._buffer.clear() - self._thread = threading.Thread( - target=Queue._feed, - args=(self._buffer, self._notempty, self._send, - self._wlock, self._writer.close, self._ignore_epipe), - name='QueueFeederThread' - ) - self._thread.daemon = True - - debug('doing self._thread.start()') - self._thread.start() - debug('... done self._thread.start()') - - # On process exit we will wait for data to be flushed to pipe. - # - # However, if this process created the queue then all - # processes which use the queue will be descendants of this - # process. Therefore waiting for the queue to be flushed - # is pointless once all the child processes have been joined. - created_by_this_process = (self._opid == os.getpid()) - if not self._joincancelled and not created_by_this_process: - self._jointhread = Finalize( - self._thread, Queue._finalize_join, - [weakref.ref(self._thread)], - exitpriority=-5 - ) - - # Send sentinel to the thread queue object when garbage collected - self._close = Finalize( - self, Queue._finalize_close, - [self._buffer, self._notempty], - exitpriority=10 - ) - - @staticmethod - def _finalize_join(twr): - debug('joining queue thread') - thread = twr() - if thread is not None: - thread.join() - debug('... queue thread joined') - else: - debug('... queue thread already dead') - - @staticmethod - def _finalize_close(buffer, notempty): - debug('telling queue thread to quit') - with notempty: - buffer.append(_sentinel) - notempty.notify() - - @staticmethod - def _feed(buffer, notempty, send, writelock, close, ignore_epipe): - debug('starting thread to feed data to pipe') - from .util import is_exiting - - ncond = notempty - nwait = notempty.wait - bpopleft = buffer.popleft - sentinel = _sentinel - if sys.platform != 'win32': - wlock = writelock - else: - wlock = None - - try: - while 1: - with ncond: - if not buffer: - nwait() - try: - while 1: - obj = bpopleft() - if obj is sentinel: - debug('feeder thread got sentinel -- exiting') - close() - return - - if wlock is None: - send(obj) - else: - with wlock: - send(obj) - except IndexError: - pass - except Exception as exc: - if ignore_epipe and get_errno(exc) == errno.EPIPE: - return - # Since this runs in a daemon thread the resources it uses - # may be become unusable while the process is cleaning up. - # We ignore errors which happen after the process has - # started to cleanup. - try: - if is_exiting(): - info('error in queue thread: %r', exc, exc_info=True) - else: - if not error('error in queue thread: %r', exc, - exc_info=True): - import traceback - traceback.print_exc() - except Exception: - pass - -_sentinel = object() - - -class JoinableQueue(Queue): - ''' - A queue type which also supports join() and task_done() methods - - Note that if you do not call task_done() for each finished task then - eventually the counter's semaphore may overflow causing Bad Things - to happen. - ''' - - def __init__(self, maxsize=0): - Queue.__init__(self, maxsize) - self._unfinished_tasks = Semaphore(0) - self._cond = Condition() - - def __getstate__(self): - return Queue.__getstate__(self) + (self._cond, self._unfinished_tasks) - - def __setstate__(self, state): - Queue.__setstate__(self, state[:-2]) - self._cond, self._unfinished_tasks = state[-2:] - - def put(self, obj, block=True, timeout=None): - assert not self._closed - if not self._sem.acquire(block, timeout): - raise Full - - with self._notempty: - with self._cond: - if self._thread is None: - self._start_thread() - self._buffer.append(obj) - self._unfinished_tasks.release() - self._notempty.notify() - - def task_done(self): - with self._cond: - if not self._unfinished_tasks.acquire(False): - raise ValueError('task_done() called too many times') - if self._unfinished_tasks._semlock._is_zero(): - self._cond.notify_all() - - def join(self): - with self._cond: - if not self._unfinished_tasks._semlock._is_zero(): - self._cond.wait() - - -class _SimpleQueue(object): - ''' - Simplified Queue type -- really just a locked pipe - ''' - - def __init__(self, rnonblock=False, wnonblock=False): - self._reader, self._writer = Pipe( - duplex=False, rnonblock=rnonblock, wnonblock=wnonblock, - ) - self._poll = self._reader.poll - self._rlock = self._wlock = None - self._make_methods() - - def empty(self): - return not self._poll() - - def __getstate__(self): - assert_spawning(self) - return (self._reader, self._writer, self._rlock, self._wlock) - - def __setstate__(self, state): - (self._reader, self._writer, self._rlock, self._wlock) = state - self._make_methods() - - def _make_methods(self): - recv = self._reader.recv - try: - recv_payload = self._reader.recv_payload - except AttributeError: - recv_payload = self._reader.recv_bytes - rlock = self._rlock - - if rlock is not None: - def get(): - with rlock: - return recv() - self.get = get - - def get_payload(): - with rlock: - return recv_payload() - self.get_payload = get_payload - else: - self.get = recv - self.get_payload = recv_payload - - if self._wlock is None: - # writes to a message oriented win32 pipe are atomic - self.put = self._writer.send - else: - send = self._writer.send - wlock = self._wlock - - def put(obj): - with wlock: - return send(obj) - self.put = put - - -class SimpleQueue(_SimpleQueue): - - def __init__(self): - self._reader, self._writer = Pipe(duplex=False) - self._rlock = Lock() - self._wlock = Lock() if sys.platform != 'win32' else None - self._make_methods() diff --git a/awx/lib/site-packages/billiard/reduction.py b/awx/lib/site-packages/billiard/reduction.py deleted file mode 100644 index c334b3e90d..0000000000 --- a/awx/lib/site-packages/billiard/reduction.py +++ /dev/null @@ -1,10 +0,0 @@ -from __future__ import absolute_import - -import sys - -if sys.version_info[0] == 3: - from .py3 import reduction -else: - from .py2 import reduction # noqa - -sys.modules[__name__] = reduction diff --git a/awx/lib/site-packages/billiard/sharedctypes.py b/awx/lib/site-packages/billiard/sharedctypes.py deleted file mode 100644 index e336c80b13..0000000000 --- a/awx/lib/site-packages/billiard/sharedctypes.py +++ /dev/null @@ -1,248 +0,0 @@ -# -# Module which supports allocation of ctypes objects from shared memory -# -# multiprocessing/sharedctypes.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -import ctypes -import weakref - -from . import heap, RLock -from .five import int_types -from .forking import assert_spawning -from .reduction import ForkingPickler - -__all__ = ['RawValue', 'RawArray', 'Value', 'Array', 'copy', 'synchronized'] - -typecode_to_type = { - 'c': ctypes.c_char, 'u': ctypes.c_wchar, - 'b': ctypes.c_byte, 'B': ctypes.c_ubyte, - 'h': ctypes.c_short, 'H': ctypes.c_ushort, - 'i': ctypes.c_int, 'I': ctypes.c_uint, - 'l': ctypes.c_long, 'L': ctypes.c_ulong, - 'f': ctypes.c_float, 'd': ctypes.c_double -} - - -def _new_value(type_): - size = ctypes.sizeof(type_) - wrapper = heap.BufferWrapper(size) - return rebuild_ctype(type_, wrapper, None) - - -def RawValue(typecode_or_type, *args): - ''' - Returns a ctypes object allocated from shared memory - ''' - type_ = typecode_to_type.get(typecode_or_type, typecode_or_type) - obj = _new_value(type_) - ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj)) - obj.__init__(*args) - return obj - - -def RawArray(typecode_or_type, size_or_initializer): - ''' - Returns a ctypes array allocated from shared memory - ''' - type_ = typecode_to_type.get(typecode_or_type, typecode_or_type) - if isinstance(size_or_initializer, int_types): - type_ = type_ * size_or_initializer - obj = _new_value(type_) - ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj)) - return obj - else: - type_ = type_ * len(size_or_initializer) - result = _new_value(type_) - result.__init__(*size_or_initializer) - return result - - -def Value(typecode_or_type, *args, **kwds): - ''' - Return a synchronization wrapper for a Value - ''' - lock = kwds.pop('lock', None) - if kwds: - raise ValueError( - 'unrecognized keyword argument(s): %s' % list(kwds.keys())) - obj = RawValue(typecode_or_type, *args) - if lock is False: - return obj - if lock in (True, None): - lock = RLock() - if not hasattr(lock, 'acquire'): - raise AttributeError("'%r' has no method 'acquire'" % lock) - return synchronized(obj, lock) - - -def Array(typecode_or_type, size_or_initializer, **kwds): - ''' - Return a synchronization wrapper for a RawArray - ''' - lock = kwds.pop('lock', None) - if kwds: - raise ValueError( - 'unrecognized keyword argument(s): %s' % list(kwds.keys())) - obj = RawArray(typecode_or_type, size_or_initializer) - if lock is False: - return obj - if lock in (True, None): - lock = RLock() - if not hasattr(lock, 'acquire'): - raise AttributeError("'%r' has no method 'acquire'" % lock) - return synchronized(obj, lock) - - -def copy(obj): - new_obj = _new_value(type(obj)) - ctypes.pointer(new_obj)[0] = obj - return new_obj - - -def synchronized(obj, lock=None): - assert not isinstance(obj, SynchronizedBase), 'object already synchronized' - - if isinstance(obj, ctypes._SimpleCData): - return Synchronized(obj, lock) - elif isinstance(obj, ctypes.Array): - if obj._type_ is ctypes.c_char: - return SynchronizedString(obj, lock) - return SynchronizedArray(obj, lock) - else: - cls = type(obj) - try: - scls = class_cache[cls] - except KeyError: - names = [field[0] for field in cls._fields_] - d = dict((name, make_property(name)) for name in names) - classname = 'Synchronized' + cls.__name__ - scls = class_cache[cls] = type(classname, (SynchronizedBase,), d) - return scls(obj, lock) - -# -# Functions for pickling/unpickling -# - - -def reduce_ctype(obj): - assert_spawning(obj) - if isinstance(obj, ctypes.Array): - return rebuild_ctype, (obj._type_, obj._wrapper, obj._length_) - else: - return rebuild_ctype, (type(obj), obj._wrapper, None) - - -def rebuild_ctype(type_, wrapper, length): - if length is not None: - type_ = type_ * length - ForkingPickler.register(type_, reduce_ctype) - obj = type_.from_address(wrapper.get_address()) - obj._wrapper = wrapper - return obj - -# -# Function to create properties -# - - -def make_property(name): - try: - return prop_cache[name] - except KeyError: - d = {} - exec(template % ((name, ) * 7), d) - prop_cache[name] = d[name] - return d[name] - -template = ''' -def get%s(self): - self.acquire() - try: - return self._obj.%s - finally: - self.release() -def set%s(self, value): - self.acquire() - try: - self._obj.%s = value - finally: - self.release() -%s = property(get%s, set%s) -''' - -prop_cache = {} -class_cache = weakref.WeakKeyDictionary() - -# -# Synchronized wrappers -# - - -class SynchronizedBase(object): - - def __init__(self, obj, lock=None): - self._obj = obj - self._lock = lock or RLock() - self.acquire = self._lock.acquire - self.release = self._lock.release - - def __reduce__(self): - assert_spawning(self) - return synchronized, (self._obj, self._lock) - - def get_obj(self): - return self._obj - - def get_lock(self): - return self._lock - - def __repr__(self): - return '<%s wrapper for %s>' % (type(self).__name__, self._obj) - - -class Synchronized(SynchronizedBase): - value = make_property('value') - - -class SynchronizedArray(SynchronizedBase): - - def __len__(self): - return len(self._obj) - - def __getitem__(self, i): - self.acquire() - try: - return self._obj[i] - finally: - self.release() - - def __setitem__(self, i, value): - self.acquire() - try: - self._obj[i] = value - finally: - self.release() - - def __getslice__(self, start, stop): - self.acquire() - try: - return self._obj[start:stop] - finally: - self.release() - - def __setslice__(self, start, stop, values): - self.acquire() - try: - self._obj[start:stop] = values - finally: - self.release() - - -class SynchronizedString(SynchronizedArray): - value = make_property('value') - raw = make_property('raw') diff --git a/awx/lib/site-packages/billiard/synchronize.py b/awx/lib/site-packages/billiard/synchronize.py deleted file mode 100644 index 0583a17362..0000000000 --- a/awx/lib/site-packages/billiard/synchronize.py +++ /dev/null @@ -1,445 +0,0 @@ -# -# Module implementing synchronization primitives -# -# multiprocessing/synchronize.py -# -# Copyright (c) 2006-2008, R Oudkerk -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -__all__ = [ - 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Condition', 'Event', -] - -import itertools -import os -import signal -import sys -import threading - - -from ._ext import _billiard, ensure_SemLock -from .five import range, monotonic -from .process import current_process -from .util import Finalize, register_after_fork, debug -from .forking import assert_spawning, Popen -from .compat import bytes, closerange - -# Try to import the mp.synchronize module cleanly, if it fails -# raise ImportError for platforms lacking a working sem_open implementation. -# See issue 3770 -ensure_SemLock() - -# -# Constants -# - -RECURSIVE_MUTEX, SEMAPHORE = list(range(2)) -SEM_VALUE_MAX = _billiard.SemLock.SEM_VALUE_MAX - -try: - sem_unlink = _billiard.SemLock.sem_unlink -except AttributeError: - sem_unlink = None - -# -# Base class for semaphores and mutexes; wraps `_billiard.SemLock` -# - - -def _semname(sl): - try: - return sl.name - except AttributeError: - pass - - -class SemLock(object): - _counter = itertools.count() - - def __init__(self, kind, value, maxvalue): - from .forking import _forking_is_enabled - unlink_immediately = _forking_is_enabled or sys.platform == 'win32' - if sem_unlink: - sl = self._semlock = _billiard.SemLock( - kind, value, maxvalue, self._make_name(), unlink_immediately) - else: - sl = self._semlock = _billiard.SemLock(kind, value, maxvalue) - - debug('created semlock with handle %s', sl.handle) - self._make_methods() - - if sem_unlink: - - if sys.platform != 'win32': - def _after_fork(obj): - obj._semlock._after_fork() - register_after_fork(self, _after_fork) - - if _semname(self._semlock) is not None: - # We only get here if we are on Unix with forking - # disabled. When the object is garbage collected or the - # process shuts down we unlink the semaphore name - Finalize(self, sem_unlink, (self._semlock.name,), - exitpriority=0) - # In case of abnormal termination unlink semaphore name - _cleanup_semaphore_if_leaked(self._semlock.name) - - def _make_methods(self): - self.acquire = self._semlock.acquire - self.release = self._semlock.release - - def __enter__(self): - return self._semlock.__enter__() - - def __exit__(self, *args): - return self._semlock.__exit__(*args) - - def __getstate__(self): - assert_spawning(self) - sl = self._semlock - state = (Popen.duplicate_for_child(sl.handle), sl.kind, sl.maxvalue) - try: - state += (sl.name, ) - except AttributeError: - pass - return state - - def __setstate__(self, state): - self._semlock = _billiard.SemLock._rebuild(*state) - debug('recreated blocker with handle %r', state[0]) - self._make_methods() - - @staticmethod - def _make_name(): - return '/%s-%s-%s' % (current_process()._semprefix, - os.getpid(), next(SemLock._counter)) - - -class Semaphore(SemLock): - - def __init__(self, value=1): - SemLock.__init__(self, SEMAPHORE, value, SEM_VALUE_MAX) - - def get_value(self): - return self._semlock._get_value() - - def __repr__(self): - try: - value = self._semlock._get_value() - except Exception: - value = 'unknown' - return '<Semaphore(value=%s)>' % value - - -class BoundedSemaphore(Semaphore): - - def __init__(self, value=1): - SemLock.__init__(self, SEMAPHORE, value, value) - - def __repr__(self): - try: - value = self._semlock._get_value() - except Exception: - value = 'unknown' - return '<BoundedSemaphore(value=%s, maxvalue=%s)>' % \ - (value, self._semlock.maxvalue) - - -class Lock(SemLock): - ''' - Non-recursive lock. - ''' - - def __init__(self): - SemLock.__init__(self, SEMAPHORE, 1, 1) - - def __repr__(self): - try: - if self._semlock._is_mine(): - name = current_process().name - if threading.currentThread().name != 'MainThread': - name += '|' + threading.currentThread().name - elif self._semlock._get_value() == 1: - name = 'None' - elif self._semlock._count() > 0: - name = 'SomeOtherThread' - else: - name = 'SomeOtherProcess' - except Exception: - name = 'unknown' - return '<Lock(owner=%s)>' % name - - -class RLock(SemLock): - ''' - Recursive lock - ''' - - def __init__(self): - SemLock.__init__(self, RECURSIVE_MUTEX, 1, 1) - - def __repr__(self): - try: - if self._semlock._is_mine(): - name = current_process().name - if threading.currentThread().name != 'MainThread': - name += '|' + threading.currentThread().name - count = self._semlock._count() - elif self._semlock._get_value() == 1: - name, count = 'None', 0 - elif self._semlock._count() > 0: - name, count = 'SomeOtherThread', 'nonzero' - else: - name, count = 'SomeOtherProcess', 'nonzero' - except Exception: - name, count = 'unknown', 'unknown' - return '<RLock(%s, %s)>' % (name, count) - - -class Condition(object): - ''' - Condition variable - ''' - - def __init__(self, lock=None): - self._lock = lock or RLock() - self._sleeping_count = Semaphore(0) - self._woken_count = Semaphore(0) - self._wait_semaphore = Semaphore(0) - self._make_methods() - - def __getstate__(self): - assert_spawning(self) - return (self._lock, self._sleeping_count, - self._woken_count, self._wait_semaphore) - - def __setstate__(self, state): - (self._lock, self._sleeping_count, - self._woken_count, self._wait_semaphore) = state - self._make_methods() - - def __enter__(self): - return self._lock.__enter__() - - def __exit__(self, *args): - return self._lock.__exit__(*args) - - def _make_methods(self): - self.acquire = self._lock.acquire - self.release = self._lock.release - - def __repr__(self): - try: - num_waiters = (self._sleeping_count._semlock._get_value() - - self._woken_count._semlock._get_value()) - except Exception: - num_waiters = 'unkown' - return '<Condition(%s, %s)>' % (self._lock, num_waiters) - - def wait(self, timeout=None): - assert self._lock._semlock._is_mine(), \ - 'must acquire() condition before using wait()' - - # indicate that this thread is going to sleep - self._sleeping_count.release() - - # release lock - count = self._lock._semlock._count() - for i in range(count): - self._lock.release() - - try: - # wait for notification or timeout - ret = self._wait_semaphore.acquire(True, timeout) - finally: - # indicate that this thread has woken - self._woken_count.release() - - # reacquire lock - for i in range(count): - self._lock.acquire() - return ret - - def notify(self): - assert self._lock._semlock._is_mine(), 'lock is not owned' - assert not self._wait_semaphore.acquire(False) - - # to take account of timeouts since last notify() we subtract - # woken_count from sleeping_count and rezero woken_count - while self._woken_count.acquire(False): - res = self._sleeping_count.acquire(False) - assert res - - if self._sleeping_count.acquire(False): # try grabbing a sleeper - self._wait_semaphore.release() # wake up one sleeper - self._woken_count.acquire() # wait for sleeper to wake - - # rezero _wait_semaphore in case a timeout just happened - self._wait_semaphore.acquire(False) - - def notify_all(self): - assert self._lock._semlock._is_mine(), 'lock is not owned' - assert not self._wait_semaphore.acquire(False) - - # to take account of timeouts since last notify*() we subtract - # woken_count from sleeping_count and rezero woken_count - while self._woken_count.acquire(False): - res = self._sleeping_count.acquire(False) - assert res - - sleepers = 0 - while self._sleeping_count.acquire(False): - self._wait_semaphore.release() # wake up one sleeper - sleepers += 1 - - if sleepers: - for i in range(sleepers): - self._woken_count.acquire() # wait for a sleeper to wake - - # rezero wait_semaphore in case some timeouts just happened - while self._wait_semaphore.acquire(False): - pass - - def wait_for(self, predicate, timeout=None): - result = predicate() - if result: - return result - if timeout is not None: - endtime = monotonic() + timeout - else: - endtime = None - waittime = None - while not result: - if endtime is not None: - waittime = endtime - monotonic() - if waittime <= 0: - break - self.wait(waittime) - result = predicate() - return result - - -class Event(object): - - def __init__(self): - self._cond = Condition(Lock()) - self._flag = Semaphore(0) - - def is_set(self): - self._cond.acquire() - try: - if self._flag.acquire(False): - self._flag.release() - return True - return False - finally: - self._cond.release() - - def set(self): - self._cond.acquire() - try: - self._flag.acquire(False) - self._flag.release() - self._cond.notify_all() - finally: - self._cond.release() - - def clear(self): - self._cond.acquire() - try: - self._flag.acquire(False) - finally: - self._cond.release() - - def wait(self, timeout=None): - self._cond.acquire() - try: - if self._flag.acquire(False): - self._flag.release() - else: - self._cond.wait(timeout) - - if self._flag.acquire(False): - self._flag.release() - return True - return False - finally: - self._cond.release() - - -if sys.platform != 'win32': - # - # Protection against unlinked semaphores if the program ends abnormally - # and forking has been disabled. - # - - def _cleanup_semaphore_if_leaked(name): - name = name.encode('ascii') + bytes('\0', 'ascii') - if len(name) > 512: - # posix guarantees that writes to a pipe of less than PIPE_BUF - # bytes are atomic, and that PIPE_BUF >= 512 - raise ValueError('name too long') - fd = _get_unlinkfd() - bits = os.write(fd, name) - assert bits == len(name) - - def _get_unlinkfd(): - cp = current_process() - if cp._unlinkfd is None: - r, w = os.pipe() - pid = os.fork() - if pid == 0: - try: - from setproctitle import setproctitle - setproctitle("[sem_cleanup for %r]" % cp.pid) - except: - pass - - # Fork a process which will survive until all other processes - # which have a copy of the write end of the pipe have exited. - # The forked process just collects names of semaphores until - # EOF is indicated. Then it tries unlinking all the names it - # has collected. - _collect_names_then_unlink(r) - os._exit(0) - os.close(r) - cp._unlinkfd = w - return cp._unlinkfd - - def _collect_names_then_unlink(r): - # protect the process from ^C and "killall python" etc - signal.signal(signal.SIGINT, signal.SIG_IGN) - signal.signal(signal.SIGTERM, signal.SIG_IGN) - - # close all fds except r - try: - MAXFD = os.sysconf("SC_OPEN_MAX") - except: - MAXFD = 256 - closerange(0, r) - closerange(r + 1, MAXFD) - - # collect data written to pipe - data = [] - while 1: - try: - s = os.read(r, 512) - except: - # XXX IO lock might be held at fork, so don't try - # printing unexpected exception - see issue 6721 - pass - else: - if not s: - break - data.append(s) - - # attempt to unlink each collected name - for name in bytes('', 'ascii').join(data).split(bytes('\0', 'ascii')): - try: - sem_unlink(name.decode('ascii')) - except: - # XXX IO lock might be held at fork, so don't try - # printing unexpected exception - see issue 6721 - pass diff --git a/awx/lib/site-packages/billiard/tests/__init__.py b/awx/lib/site-packages/billiard/tests/__init__.py deleted file mode 100644 index a87fce1c5f..0000000000 --- a/awx/lib/site-packages/billiard/tests/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import absolute_import - -import atexit - - -def teardown(): - # Workaround for multiprocessing bug where logging - # is attempted after global already collected at shutdown. - cancelled = set() - try: - import multiprocessing.util - cancelled.add(multiprocessing.util._exit_function) - except (AttributeError, ImportError): - pass - - try: - atexit._exithandlers[:] = [ - e for e in atexit._exithandlers if e[0] not in cancelled - ] - except AttributeError: - pass diff --git a/awx/lib/site-packages/billiard/tests/compat.py b/awx/lib/site-packages/billiard/tests/compat.py deleted file mode 100644 index 30eb853b0d..0000000000 --- a/awx/lib/site-packages/billiard/tests/compat.py +++ /dev/null @@ -1,85 +0,0 @@ -from __future__ import absolute_import - -import sys - - -class WarningMessage(object): - - """Holds the result of a single showwarning() call.""" - - _WARNING_DETAILS = ('message', 'category', 'filename', 'lineno', 'file', - 'line') - - def __init__(self, message, category, filename, lineno, file=None, - line=None): - local_values = locals() - for attr in self._WARNING_DETAILS: - setattr(self, attr, local_values[attr]) - - self._category_name = category and category.__name__ or None - - def __str__(self): - return ('{message : %r, category : %r, filename : %r, lineno : %s, ' - 'line : %r}' % (self.message, self._category_name, - self.filename, self.lineno, self.line)) - - -class catch_warnings(object): - - """A context manager that copies and restores the warnings filter upon - exiting the context. - - The 'record' argument specifies whether warnings should be captured by a - custom implementation of warnings.showwarning() and be appended to a list - returned by the context manager. Otherwise None is returned by the context - manager. The objects appended to the list are arguments whose attributes - mirror the arguments to showwarning(). - - The 'module' argument is to specify an alternative module to the module - named 'warnings' and imported under that name. This argument is only - useful when testing the warnings module itself. - - """ - - def __init__(self, record=False, module=None): - """Specify whether to record warnings and if an alternative module - should be used other than sys.modules['warnings']. - - For compatibility with Python 3.0, please consider all arguments to be - keyword-only. - - """ - self._record = record - self._module = module is None and sys.modules['warnings'] or module - self._entered = False - - def __repr__(self): - args = [] - if self._record: - args.append('record=True') - if self._module is not sys.modules['warnings']: - args.append('module=%r' % self._module) - name = type(self).__name__ - return '%s(%s)' % (name, ', '.join(args)) - - def __enter__(self): - if self._entered: - raise RuntimeError('Cannot enter %r twice' % self) - self._entered = True - self._filters = self._module.filters - self._module.filters = self._filters[:] - self._showwarning = self._module.showwarning - if self._record: - log = [] - - def showwarning(*args, **kwargs): - log.append(WarningMessage(*args, **kwargs)) - - self._module.showwarning = showwarning - return log - - def __exit__(self, *exc_info): - if not self._entered: - raise RuntimeError('Cannot exit %r without entering first' % self) - self._module.filters = self._filters - self._module.showwarning = self._showwarning diff --git a/awx/lib/site-packages/billiard/tests/test_common.py b/awx/lib/site-packages/billiard/tests/test_common.py deleted file mode 100644 index 0eb3318911..0000000000 --- a/awx/lib/site-packages/billiard/tests/test_common.py +++ /dev/null @@ -1,98 +0,0 @@ -from __future__ import absolute_import - -import os -import signal - -from contextlib import contextmanager -from mock import call, patch, Mock -from time import time - -from billiard.common import ( - _shutdown_cleanup, - reset_signals, - restart_state, -) - -from .utils import Case - - -def signo(name): - return getattr(signal, name) - - -@contextmanager -def termsigs(default, full): - from billiard import common - prev_def, common.TERMSIGS_DEFAULT = common.TERMSIGS_DEFAULT, default - prev_full, common.TERMSIGS_FULL = common.TERMSIGS_FULL, full - try: - yield - finally: - common.TERMSIGS_DEFAULT, common.TERMSIGS_FULL = prev_def, prev_full - - -class test_reset_signals(Case): - - def test_shutdown_handler(self): - with patch('sys.exit') as exit: - _shutdown_cleanup(15, Mock()) - self.assertTrue(exit.called) - self.assertEqual(os.WTERMSIG(exit.call_args[0][0]), 15) - - def test_does_not_reset_ignored_signal(self, sigs=['SIGTERM']): - with self.assert_context(sigs, [], signal.SIG_IGN) as (_, SET): - self.assertFalse(SET.called) - - def test_does_not_reset_if_current_is_None(self, sigs=['SIGTERM']): - with self.assert_context(sigs, [], None) as (_, SET): - self.assertFalse(SET.called) - - def test_resets_for_SIG_DFL(self, sigs=['SIGTERM', 'SIGINT', 'SIGUSR1']): - with self.assert_context(sigs, [], signal.SIG_DFL) as (_, SET): - SET.assert_has_calls([ - call(signo(sig), _shutdown_cleanup) for sig in sigs - ]) - - def test_resets_for_obj(self, sigs=['SIGTERM', 'SIGINT', 'SIGUSR1']): - with self.assert_context(sigs, [], object()) as (_, SET): - SET.assert_has_calls([ - call(signo(sig), _shutdown_cleanup) for sig in sigs - ]) - - def test_handles_errors(self, sigs=['SIGTERM']): - for exc in (OSError(), AttributeError(), - ValueError(), RuntimeError()): - with self.assert_context(sigs, [], signal.SIG_DFL, exc) as (_, SET): - self.assertTrue(SET.called) - - @contextmanager - def assert_context(self, default, full, get_returns=None, set_effect=None): - with termsigs(default, full): - with patch('signal.getsignal') as GET: - with patch('signal.signal') as SET: - GET.return_value = get_returns - SET.side_effect = set_effect - reset_signals() - GET.assert_has_calls([ - call(signo(sig)) for sig in default - ]) - yield GET, SET - - -class test_restart_state(Case): - - def test_raises(self): - s = restart_state(100, 1) # max 100 restarts in 1 second. - s.R = 99 - s.step() - with self.assertRaises(s.RestartFreqExceeded): - s.step() - - def test_time_passed_resets_counter(self): - s = restart_state(100, 10) - s.R, s.T = 100, time() - with self.assertRaises(s.RestartFreqExceeded): - s.step() - s.R, s.T = 100, time() - s.step(time() + 20) - self.assertEqual(s.R, 1) diff --git a/awx/lib/site-packages/billiard/tests/test_package.py b/awx/lib/site-packages/billiard/tests/test_package.py deleted file mode 100644 index 79347187d6..0000000000 --- a/awx/lib/site-packages/billiard/tests/test_package.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import absolute_import - -import billiard - -from .utils import Case - - -class test_billiard(Case): - - def test_has_version(self): - self.assertTrue(billiard.__version__) - self.assertIsInstance(billiard.__version__, str) diff --git a/awx/lib/site-packages/billiard/tests/utils.py b/awx/lib/site-packages/billiard/tests/utils.py deleted file mode 100644 index 1ac881f2da..0000000000 --- a/awx/lib/site-packages/billiard/tests/utils.py +++ /dev/null @@ -1,145 +0,0 @@ -from __future__ import absolute_import - -import re -import sys -import warnings - -try: - import unittest # noqa - unittest.skip - from unittest.util import safe_repr, unorderable_list_difference -except AttributeError: - import unittest2 as unittest # noqa - from unittest2.util import safe_repr, unorderable_list_difference # noqa - -from billiard.five import string_t, items, values - -from .compat import catch_warnings - -# -- adds assertWarns from recent unittest2, not in Python 2.7. - - -class _AssertRaisesBaseContext(object): - - def __init__(self, expected, test_case, callable_obj=None, - expected_regex=None): - self.expected = expected - self.failureException = test_case.failureException - self.obj_name = None - if isinstance(expected_regex, string_t): - expected_regex = re.compile(expected_regex) - self.expected_regex = expected_regex - - -class _AssertWarnsContext(_AssertRaisesBaseContext): - """A context manager used to implement TestCase.assertWarns* methods.""" - - def __enter__(self): - # The __warningregistry__'s need to be in a pristine state for tests - # to work properly. - warnings.resetwarnings() - for v in values(sys.modules): - if getattr(v, '__warningregistry__', None): - v.__warningregistry__ = {} - self.warnings_manager = catch_warnings(record=True) - self.warnings = self.warnings_manager.__enter__() - warnings.simplefilter('always', self.expected) - return self - - def __exit__(self, exc_type, exc_value, tb): - self.warnings_manager.__exit__(exc_type, exc_value, tb) - if exc_type is not None: - # let unexpected exceptions pass through - return - try: - exc_name = self.expected.__name__ - except AttributeError: - exc_name = str(self.expected) - first_matching = None - for m in self.warnings: - w = m.message - if not isinstance(w, self.expected): - continue - if first_matching is None: - first_matching = w - if (self.expected_regex is not None and - not self.expected_regex.search(str(w))): - continue - # store warning for later retrieval - self.warning = w - self.filename = m.filename - self.lineno = m.lineno - return - # Now we simply try to choose a helpful failure message - if first_matching is not None: - raise self.failureException( - '%r does not match %r' % ( - self.expected_regex.pattern, str(first_matching))) - if self.obj_name: - raise self.failureException( - '%s not triggered by %s' % (exc_name, self.obj_name)) - else: - raise self.failureException('%s not triggered' % exc_name) - - -class Case(unittest.TestCase): - - def assertWarns(self, expected_warning): - return _AssertWarnsContext(expected_warning, self, None) - - def assertWarnsRegex(self, expected_warning, expected_regex): - return _AssertWarnsContext(expected_warning, self, - None, expected_regex) - - def assertDictContainsSubset(self, expected, actual, msg=None): - missing, mismatched = [], [] - - for key, value in items(expected): - if key not in actual: - missing.append(key) - elif value != actual[key]: - mismatched.append('%s, expected: %s, actual: %s' % ( - safe_repr(key), safe_repr(value), - safe_repr(actual[key]))) - - if not (missing or mismatched): - return - - standard_msg = '' - if missing: - standard_msg = 'Missing: %s' % ','.join(map(safe_repr, missing)) - - if mismatched: - if standard_msg: - standard_msg += '; ' - standard_msg += 'Mismatched values: %s' % ( - ','.join(mismatched)) - - self.fail(self._formatMessage(msg, standard_msg)) - - def assertItemsEqual(self, expected_seq, actual_seq, msg=None): - missing = unexpected = None - try: - expected = sorted(expected_seq) - actual = sorted(actual_seq) - except TypeError: - # Unsortable items (example: set(), complex(), ...) - expected = list(expected_seq) - actual = list(actual_seq) - missing, unexpected = unorderable_list_difference( - expected, actual) - else: - return self.assertSequenceEqual(expected, actual, msg=msg) - - errors = [] - if missing: - errors.append( - 'Expected, but missing:\n %s' % (safe_repr(missing), ), - ) - if unexpected: - errors.append( - 'Unexpected, but present:\n %s' % (safe_repr(unexpected), ), - ) - if errors: - standardMsg = '\n'.join(errors) - self.fail(self._formatMessage(msg, standardMsg)) diff --git a/awx/lib/site-packages/billiard/util.py b/awx/lib/site-packages/billiard/util.py deleted file mode 100644 index 8b5e4c3122..0000000000 --- a/awx/lib/site-packages/billiard/util.py +++ /dev/null @@ -1,152 +0,0 @@ -# -# Module providing various facilities to other parts of the package -# -# billiard/util.py -# -# Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt -# Licensed to PSF under a Contributor Agreement. -# -from __future__ import absolute_import - -import errno -import functools -import atexit - -from multiprocessing.util import ( # noqa - _afterfork_registry, - _afterfork_counter, - _exit_function, - _finalizer_registry, - _finalizer_counter, - Finalize, - ForkAwareLocal, - ForkAwareThreadLock, - get_temp_dir, - is_exiting, - register_after_fork, - _run_after_forkers, - _run_finalizers, -) - -from .compat import get_errno - -__all__ = [ - 'sub_debug', 'debug', 'info', 'sub_warning', 'get_logger', - 'log_to_stderr', 'get_temp_dir', 'register_after_fork', - 'is_exiting', 'Finalize', 'ForkAwareThreadLock', 'ForkAwareLocal', - 'SUBDEBUG', 'SUBWARNING', -] - -# -# Logging -# - -NOTSET = 0 -SUBDEBUG = 5 -DEBUG = 10 -INFO = 20 -SUBWARNING = 25 -ERROR = 40 - -LOGGER_NAME = 'multiprocessing' -DEFAULT_LOGGING_FORMAT = '[%(levelname)s/%(processName)s] %(message)s' - -_logger = None -_log_to_stderr = False - - -def sub_debug(msg, *args, **kwargs): - if _logger: - _logger.log(SUBDEBUG, msg, *args, **kwargs) - - -def debug(msg, *args, **kwargs): - if _logger: - _logger.log(DEBUG, msg, *args, **kwargs) - return True - return False - - -def info(msg, *args, **kwargs): - if _logger: - _logger.log(INFO, msg, *args, **kwargs) - return True - return False - - -def sub_warning(msg, *args, **kwargs): - if _logger: - _logger.log(SUBWARNING, msg, *args, **kwargs) - return True - return False - - -def error(msg, *args, **kwargs): - if _logger: - _logger.log(ERROR, msg, *args, **kwargs) - return True - return False - - -def get_logger(): - ''' - Returns logger used by multiprocessing - ''' - global _logger - import logging - - logging._acquireLock() - try: - if not _logger: - - _logger = logging.getLogger(LOGGER_NAME) - _logger.propagate = 0 - logging.addLevelName(SUBDEBUG, 'SUBDEBUG') - logging.addLevelName(SUBWARNING, 'SUBWARNING') - - # XXX multiprocessing should cleanup before logging - if hasattr(atexit, 'unregister'): - atexit.unregister(_exit_function) - atexit.register(_exit_function) - else: - atexit._exithandlers.remove((_exit_function, (), {})) - atexit._exithandlers.append((_exit_function, (), {})) - finally: - logging._releaseLock() - - return _logger - - -def log_to_stderr(level=None): - ''' - Turn on logging and add a handler which prints to stderr - ''' - global _log_to_stderr - import logging - - logger = get_logger() - formatter = logging.Formatter(DEFAULT_LOGGING_FORMAT) - handler = logging.StreamHandler() - handler.setFormatter(formatter) - logger.addHandler(handler) - - if level: - logger.setLevel(level) - _log_to_stderr = True - return _logger - - -def _eintr_retry(func): - ''' - Automatic retry after EINTR. - ''' - - @functools.wraps(func) - def wrapped(*args, **kwargs): - while 1: - try: - return func(*args, **kwargs) - except OSError as exc: - if get_errno(exc) != errno.EINTR: - raise - return wrapped diff --git a/awx/lib/site-packages/boto/__init__.py b/awx/lib/site-packages/boto/__init__.py deleted file mode 100644 index fe5fd7d4b2..0000000000 --- a/awx/lib/site-packages/boto/__init__.py +++ /dev/null @@ -1,1045 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010-2011, Eucalyptus Systems, Inc. -# Copyright (c) 2011, Nexenta Systems Inc. -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# Copyright (c) 2010, Google, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.pyami.config import Config, BotoConfigLocations -from boto.storage_uri import BucketStorageUri, FileStorageUri -import boto.plugin -import datetime -import os -import platform -import re -import sys -import logging -import logging.config - -from boto.compat import urlparse -from boto.exception import InvalidUriError - -__version__ = '2.34.0' -Version = __version__ # for backware compatibility - -# http://bugs.python.org/issue7980 -datetime.datetime.strptime('', '') - -UserAgent = 'Boto/%s Python/%s %s/%s' % ( - __version__, - platform.python_version(), - platform.system(), - platform.release() -) -config = Config() - -# Regex to disallow buckets violating charset or not [3..255] chars total. -BUCKET_NAME_RE = re.compile(r'^[a-zA-Z0-9][a-zA-Z0-9\._-]{1,253}[a-zA-Z0-9]$') -# Regex to disallow buckets with individual DNS labels longer than 63. -TOO_LONG_DNS_NAME_COMP = re.compile(r'[-_a-z0-9]{64}') -GENERATION_RE = re.compile(r'(?P<versionless_uri_str>.+)' - r'#(?P<generation>[0-9]+)$') -VERSION_RE = re.compile('(?P<versionless_uri_str>.+)#(?P<version_id>.+)$') -ENDPOINTS_PATH = os.path.join(os.path.dirname(__file__), 'endpoints.json') - - -def init_logging(): - for file in BotoConfigLocations: - try: - logging.config.fileConfig(os.path.expanduser(file)) - except: - pass - - -class NullHandler(logging.Handler): - def emit(self, record): - pass - -log = logging.getLogger('boto') -perflog = logging.getLogger('boto.perf') -log.addHandler(NullHandler()) -perflog.addHandler(NullHandler()) -init_logging() - -# convenience function to set logging to a particular file - - -def set_file_logger(name, filepath, level=logging.INFO, format_string=None): - global log - if not format_string: - format_string = "%(asctime)s %(name)s [%(levelname)s]:%(message)s" - logger = logging.getLogger(name) - logger.setLevel(level) - fh = logging.FileHandler(filepath) - fh.setLevel(level) - formatter = logging.Formatter(format_string) - fh.setFormatter(formatter) - logger.addHandler(fh) - log = logger - - -def set_stream_logger(name, level=logging.DEBUG, format_string=None): - global log - if not format_string: - format_string = "%(asctime)s %(name)s [%(levelname)s]:%(message)s" - logger = logging.getLogger(name) - logger.setLevel(level) - fh = logging.StreamHandler() - fh.setLevel(level) - formatter = logging.Formatter(format_string) - fh.setFormatter(formatter) - logger.addHandler(fh) - log = logger - - -def connect_sqs(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.sqs.connection.SQSConnection` - :return: A connection to Amazon's SQS - """ - from boto.sqs.connection import SQSConnection - return SQSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_s3(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.s3.connection.S3Connection` - :return: A connection to Amazon's S3 - """ - from boto.s3.connection import S3Connection - return S3Connection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_gs(gs_access_key_id=None, gs_secret_access_key=None, **kwargs): - """ - @type gs_access_key_id: string - @param gs_access_key_id: Your Google Cloud Storage Access Key ID - - @type gs_secret_access_key: string - @param gs_secret_access_key: Your Google Cloud Storage Secret Access Key - - @rtype: L{GSConnection<boto.gs.connection.GSConnection>} - @return: A connection to Google's Storage service - """ - from boto.gs.connection import GSConnection - return GSConnection(gs_access_key_id, gs_secret_access_key, **kwargs) - - -def connect_ec2(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ec2.connection.EC2Connection` - :return: A connection to Amazon's EC2 - """ - from boto.ec2.connection import EC2Connection - return EC2Connection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_elb(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ec2.elb.ELBConnection` - :return: A connection to Amazon's Load Balancing Service - """ - from boto.ec2.elb import ELBConnection - return ELBConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_autoscale(aws_access_key_id=None, aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ec2.autoscale.AutoScaleConnection` - :return: A connection to Amazon's Auto Scaling Service - - :type use_block_device_types bool - :param use_block_device_types: Specifies whether to return described Launch Configs with block device mappings containing - block device types, or a list of old style block device mappings (deprecated). This defaults to false for compatability - with the old incorrect style. - """ - from boto.ec2.autoscale import AutoScaleConnection - return AutoScaleConnection(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_cloudwatch(aws_access_key_id=None, aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ec2.cloudwatch.CloudWatchConnection` - :return: A connection to Amazon's EC2 Monitoring service - """ - from boto.ec2.cloudwatch import CloudWatchConnection - return CloudWatchConnection(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_sdb(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.sdb.connection.SDBConnection` - :return: A connection to Amazon's SDB - """ - from boto.sdb.connection import SDBConnection - return SDBConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_fps(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.fps.connection.FPSConnection` - :return: A connection to FPS - """ - from boto.fps.connection import FPSConnection - return FPSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_mturk(aws_access_key_id=None, aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.mturk.connection.MTurkConnection` - :return: A connection to MTurk - """ - from boto.mturk.connection import MTurkConnection - return MTurkConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_cloudfront(aws_access_key_id=None, aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.fps.connection.FPSConnection` - :return: A connection to FPS - """ - from boto.cloudfront import CloudFrontConnection - return CloudFrontConnection(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_vpc(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.vpc.VPCConnection` - :return: A connection to VPC - """ - from boto.vpc import VPCConnection - return VPCConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_rds(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.rds.RDSConnection` - :return: A connection to RDS - """ - from boto.rds import RDSConnection - return RDSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_rds2(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.rds2.layer1.RDSConnection` - :return: A connection to RDS - """ - from boto.rds2.layer1 import RDSConnection - return RDSConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def connect_emr(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.emr.EmrConnection` - :return: A connection to Elastic mapreduce - """ - from boto.emr import EmrConnection - return EmrConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_sns(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.sns.SNSConnection` - :return: A connection to Amazon's SNS - """ - from boto.sns import SNSConnection - return SNSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_iam(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.iam.IAMConnection` - :return: A connection to Amazon's IAM - """ - from boto.iam import IAMConnection - return IAMConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_route53(aws_access_key_id=None, aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.dns.Route53Connection` - :return: A connection to Amazon's Route53 DNS Service - """ - from boto.route53 import Route53Connection - return Route53Connection(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_cloudformation(aws_access_key_id=None, aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.cloudformation.CloudFormationConnection` - :return: A connection to Amazon's CloudFormation Service - """ - from boto.cloudformation import CloudFormationConnection - return CloudFormationConnection(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_euca(host=None, aws_access_key_id=None, aws_secret_access_key=None, - port=8773, path='/services/Eucalyptus', is_secure=False, - **kwargs): - """ - Connect to a Eucalyptus service. - - :type host: string - :param host: the host name or ip address of the Eucalyptus server - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ec2.connection.EC2Connection` - :return: A connection to Eucalyptus server - """ - from boto.ec2 import EC2Connection - from boto.ec2.regioninfo import RegionInfo - - # Check for values in boto config, if not supplied as args - if not aws_access_key_id: - aws_access_key_id = config.get('Credentials', - 'euca_access_key_id', - None) - if not aws_secret_access_key: - aws_secret_access_key = config.get('Credentials', - 'euca_secret_access_key', - None) - if not host: - host = config.get('Boto', 'eucalyptus_host', None) - - reg = RegionInfo(name='eucalyptus', endpoint=host) - return EC2Connection(aws_access_key_id, aws_secret_access_key, - region=reg, port=port, path=path, - is_secure=is_secure, **kwargs) - - -def connect_glacier(aws_access_key_id=None, aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.glacier.layer2.Layer2` - :return: A connection to Amazon's Glacier Service - """ - from boto.glacier.layer2 import Layer2 - return Layer2(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_ec2_endpoint(url, aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to an EC2 Api endpoint. Additional arguments are passed - through to connect_ec2. - - :type url: string - :param url: A url for the ec2 api endpoint to connect to - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ec2.connection.EC2Connection` - :return: A connection to Eucalyptus server - """ - from boto.ec2.regioninfo import RegionInfo - - purl = urlparse(url) - kwargs['port'] = purl.port - kwargs['host'] = purl.hostname - kwargs['path'] = purl.path - if not 'is_secure' in kwargs: - kwargs['is_secure'] = (purl.scheme == "https") - - kwargs['region'] = RegionInfo(name=purl.hostname, - endpoint=purl.hostname) - kwargs['aws_access_key_id'] = aws_access_key_id - kwargs['aws_secret_access_key'] = aws_secret_access_key - - return(connect_ec2(**kwargs)) - - -def connect_walrus(host=None, aws_access_key_id=None, - aws_secret_access_key=None, - port=8773, path='/services/Walrus', is_secure=False, - **kwargs): - """ - Connect to a Walrus service. - - :type host: string - :param host: the host name or ip address of the Walrus server - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.s3.connection.S3Connection` - :return: A connection to Walrus - """ - from boto.s3.connection import S3Connection - from boto.s3.connection import OrdinaryCallingFormat - - # Check for values in boto config, if not supplied as args - if not aws_access_key_id: - aws_access_key_id = config.get('Credentials', - 'euca_access_key_id', - None) - if not aws_secret_access_key: - aws_secret_access_key = config.get('Credentials', - 'euca_secret_access_key', - None) - if not host: - host = config.get('Boto', 'walrus_host', None) - - return S3Connection(aws_access_key_id, aws_secret_access_key, - host=host, port=port, path=path, - calling_format=OrdinaryCallingFormat(), - is_secure=is_secure, **kwargs) - - -def connect_ses(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ses.SESConnection` - :return: A connection to Amazon's SES - """ - from boto.ses import SESConnection - return SESConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_sts(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.sts.STSConnection` - :return: A connection to Amazon's STS - """ - from boto.sts import STSConnection - return STSConnection(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_ia(ia_access_key_id=None, ia_secret_access_key=None, - is_secure=False, **kwargs): - """ - Connect to the Internet Archive via their S3-like API. - - :type ia_access_key_id: string - :param ia_access_key_id: Your IA Access Key ID. This will also look - in your boto config file for an entry in the Credentials - section called "ia_access_key_id" - - :type ia_secret_access_key: string - :param ia_secret_access_key: Your IA Secret Access Key. This will also - look in your boto config file for an entry in the Credentials - section called "ia_secret_access_key" - - :rtype: :class:`boto.s3.connection.S3Connection` - :return: A connection to the Internet Archive - """ - from boto.s3.connection import S3Connection - from boto.s3.connection import OrdinaryCallingFormat - - access_key = config.get('Credentials', 'ia_access_key_id', - ia_access_key_id) - secret_key = config.get('Credentials', 'ia_secret_access_key', - ia_secret_access_key) - - return S3Connection(access_key, secret_key, - host='s3.us.archive.org', - calling_format=OrdinaryCallingFormat(), - is_secure=is_secure, **kwargs) - - -def connect_dynamodb(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.dynamodb.layer2.Layer2` - :return: A connection to the Layer2 interface for DynamoDB. - """ - from boto.dynamodb.layer2 import Layer2 - return Layer2(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_swf(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.swf.layer1.Layer1` - :return: A connection to the Layer1 interface for SWF. - """ - from boto.swf.layer1 import Layer1 - return Layer1(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_cloudsearch(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.cloudsearch.layer2.Layer2` - :return: A connection to Amazon's CloudSearch service - """ - from boto.cloudsearch.layer2 import Layer2 - return Layer2(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_cloudsearch2(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.cloudsearch2.layer2.Layer2` - :return: A connection to Amazon's CloudSearch2 service - """ - from boto.cloudsearch2.layer2 import Layer2 - return Layer2(aws_access_key_id, aws_secret_access_key, - **kwargs) - - -def connect_beanstalk(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.beanstalk.layer1.Layer1` - :return: A connection to Amazon's Elastic Beanstalk service - """ - from boto.beanstalk.layer1 import Layer1 - return Layer1(aws_access_key_id, aws_secret_access_key, **kwargs) - - -def connect_elastictranscoder(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ets.layer1.ElasticTranscoderConnection` - :return: A connection to Amazon's Elastic Transcoder service - """ - from boto.elastictranscoder.layer1 import ElasticTranscoderConnection - return ElasticTranscoderConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs) - - -def connect_opsworks(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - from boto.opsworks.layer1 import OpsWorksConnection - return OpsWorksConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs) - - -def connect_redshift(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.redshift.layer1.RedshiftConnection` - :return: A connection to Amazon's Redshift service - """ - from boto.redshift.layer1 import RedshiftConnection - return RedshiftConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def connect_support(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.support.layer1.SupportConnection` - :return: A connection to Amazon's Support service - """ - from boto.support.layer1 import SupportConnection - return SupportConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def connect_cloudtrail(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to AWS CloudTrail - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.cloudtrail.layer1.CloudtrailConnection` - :return: A connection to the AWS Cloudtrail service - """ - from boto.cloudtrail.layer1 import CloudTrailConnection - return CloudTrailConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def connect_directconnect(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to AWS DirectConnect - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.directconnect.layer1.DirectConnectConnection` - :return: A connection to the AWS DirectConnect service - """ - from boto.directconnect.layer1 import DirectConnectConnection - return DirectConnectConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - -def connect_kinesis(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to Amazon Kinesis - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - rtype: :class:`boto.kinesis.layer1.KinesisConnection` - :return: A connection to the Amazon Kinesis service - """ - from boto.kinesis.layer1 import KinesisConnection - return KinesisConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - -def connect_logs(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to Amazon CloudWatch Logs - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - rtype: :class:`boto.kinesis.layer1.CloudWatchLogsConnection` - :return: A connection to the Amazon CloudWatch Logs service - """ - from boto.logs.layer1 import CloudWatchLogsConnection - return CloudWatchLogsConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def connect_route53domains(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to Amazon Route 53 Domains - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - rtype: :class:`boto.route53.domains.layer1.Route53DomainsConnection` - :return: A connection to the Amazon Route 53 Domains service - """ - from boto.route53.domains.layer1 import Route53DomainsConnection - return Route53DomainsConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def connect_cognito_identity(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to Amazon Cognito Identity - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - rtype: :class:`boto.cognito.identity.layer1.CognitoIdentityConnection` - :return: A connection to the Amazon Cognito Identity service - """ - from boto.cognito.identity.layer1 import CognitoIdentityConnection - return CognitoIdentityConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def connect_cognito_sync(aws_access_key_id=None, - aws_secret_access_key=None, - **kwargs): - """ - Connect to Amazon Cognito Sync - - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - rtype: :class:`boto.cognito.sync.layer1.CognitoSyncConnection` - :return: A connection to the Amazon Cognito Sync service - """ - from boto.cognito.sync.layer1 import CognitoSyncConnection - return CognitoSyncConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - **kwargs - ) - - -def storage_uri(uri_str, default_scheme='file', debug=0, validate=True, - bucket_storage_uri_class=BucketStorageUri, - suppress_consec_slashes=True, is_latest=False): - """ - Instantiate a StorageUri from a URI string. - - :type uri_str: string - :param uri_str: URI naming bucket + optional object. - :type default_scheme: string - :param default_scheme: default scheme for scheme-less URIs. - :type debug: int - :param debug: debug level to pass in to boto connection (range 0..2). - :type validate: bool - :param validate: whether to check for bucket name validity. - :type bucket_storage_uri_class: BucketStorageUri interface. - :param bucket_storage_uri_class: Allows mocking for unit tests. - :param suppress_consec_slashes: If provided, controls whether - consecutive slashes will be suppressed in key paths. - :type is_latest: bool - :param is_latest: whether this versioned object represents the - current version. - - We allow validate to be disabled to allow caller - to implement bucket-level wildcarding (outside the boto library; - see gsutil). - - :rtype: :class:`boto.StorageUri` subclass - :return: StorageUri subclass for given URI. - - ``uri_str`` must be one of the following formats: - - * gs://bucket/name - * gs://bucket/name#ver - * s3://bucket/name - * gs://bucket - * s3://bucket - * filename (which could be a Unix path like /a/b/c or a Windows path like - C:\a\b\c) - - The last example uses the default scheme ('file', unless overridden). - """ - version_id = None - generation = None - - # Manually parse URI components instead of using urlparse because - # what we're calling URIs don't really fit the standard syntax for URIs - # (the latter includes an optional host/net location part). - end_scheme_idx = uri_str.find('://') - if end_scheme_idx == -1: - scheme = default_scheme.lower() - path = uri_str - else: - scheme = uri_str[0:end_scheme_idx].lower() - path = uri_str[end_scheme_idx + 3:] - - if scheme not in ['file', 's3', 'gs']: - raise InvalidUriError('Unrecognized scheme "%s"' % scheme) - if scheme == 'file': - # For file URIs we have no bucket name, and use the complete path - # (minus 'file://') as the object name. - is_stream = False - if path == '-': - is_stream = True - return FileStorageUri(path, debug, is_stream) - else: - path_parts = path.split('/', 1) - bucket_name = path_parts[0] - object_name = '' - # If validate enabled, ensure the bucket name is valid, to avoid - # possibly confusing other parts of the code. (For example if we didn't - # catch bucket names containing ':', when a user tried to connect to - # the server with that name they might get a confusing error about - # non-integer port numbers.) - if (validate and bucket_name and - (not BUCKET_NAME_RE.match(bucket_name) - or TOO_LONG_DNS_NAME_COMP.search(bucket_name))): - raise InvalidUriError('Invalid bucket name in URI "%s"' % uri_str) - if scheme == 'gs': - match = GENERATION_RE.search(path) - if match: - md = match.groupdict() - versionless_uri_str = md['versionless_uri_str'] - path_parts = versionless_uri_str.split('/', 1) - generation = int(md['generation']) - elif scheme == 's3': - match = VERSION_RE.search(path) - if match: - md = match.groupdict() - versionless_uri_str = md['versionless_uri_str'] - path_parts = versionless_uri_str.split('/', 1) - version_id = md['version_id'] - else: - raise InvalidUriError('Unrecognized scheme "%s"' % scheme) - if len(path_parts) > 1: - object_name = path_parts[1] - return bucket_storage_uri_class( - scheme, bucket_name, object_name, debug, - suppress_consec_slashes=suppress_consec_slashes, - version_id=version_id, generation=generation, is_latest=is_latest) - - -def storage_uri_for_key(key): - """Returns a StorageUri for the given key. - - :type key: :class:`boto.s3.key.Key` or subclass - :param key: URI naming bucket + optional object. - """ - if not isinstance(key, boto.s3.key.Key): - raise InvalidUriError('Requested key (%s) is not a subclass of ' - 'boto.s3.key.Key' % str(type(key))) - prov_name = key.bucket.connection.provider.get_provider_name() - uri_str = '%s://%s/%s' % (prov_name, key.bucket.name, key.name) - return storage_uri(uri_str) - -boto.plugin.load_plugins(config) diff --git a/awx/lib/site-packages/boto/auth.py b/awx/lib/site-packages/boto/auth.py deleted file mode 100644 index 3e9ded7903..0000000000 --- a/awx/lib/site-packages/boto/auth.py +++ /dev/null @@ -1,1027 +0,0 @@ -# Copyright 2010 Google Inc. -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -""" -Handles authentication required to AWS and GS -""" - -import base64 -import boto -import boto.auth_handler -import boto.exception -import boto.plugin -import boto.utils -import copy -import datetime -from email.utils import formatdate -import hmac -import os -import posixpath - -from boto.compat import urllib, encodebytes -from boto.auth_handler import AuthHandler -from boto.exception import BotoClientError - -try: - from hashlib import sha1 as sha - from hashlib import sha256 as sha256 -except ImportError: - import sha - sha256 = None - - -class HmacKeys(object): - """Key based Auth handler helper.""" - - def __init__(self, host, config, provider): - if provider.access_key is None or provider.secret_key is None: - raise boto.auth_handler.NotReadyToAuthenticate() - self.host = host - self.update_provider(provider) - - def update_provider(self, provider): - self._provider = provider - self._hmac = hmac.new(self._provider.secret_key.encode('utf-8'), - digestmod=sha) - if sha256: - self._hmac_256 = hmac.new(self._provider.secret_key.encode('utf-8'), - digestmod=sha256) - else: - self._hmac_256 = None - - def algorithm(self): - if self._hmac_256: - return 'HmacSHA256' - else: - return 'HmacSHA1' - - def _get_hmac(self): - if self._hmac_256: - digestmod = sha256 - else: - digestmod = sha - return hmac.new(self._provider.secret_key.encode('utf-8'), - digestmod=digestmod) - - def sign_string(self, string_to_sign): - new_hmac = self._get_hmac() - new_hmac.update(string_to_sign.encode('utf-8')) - return encodebytes(new_hmac.digest()).decode('utf-8').strip() - - def __getstate__(self): - pickled_dict = copy.copy(self.__dict__) - del pickled_dict['_hmac'] - del pickled_dict['_hmac_256'] - return pickled_dict - - def __setstate__(self, dct): - self.__dict__ = dct - self.update_provider(self._provider) - - -class AnonAuthHandler(AuthHandler, HmacKeys): - """ - Implements Anonymous requests. - """ - - capability = ['anon'] - - def __init__(self, host, config, provider): - super(AnonAuthHandler, self).__init__(host, config, provider) - - def add_auth(self, http_request, **kwargs): - pass - - -class HmacAuthV1Handler(AuthHandler, HmacKeys): - """ Implements the HMAC request signing used by S3 and GS.""" - - capability = ['hmac-v1', 's3'] - - def __init__(self, host, config, provider): - AuthHandler.__init__(self, host, config, provider) - HmacKeys.__init__(self, host, config, provider) - self._hmac_256 = None - - def update_provider(self, provider): - super(HmacAuthV1Handler, self).update_provider(provider) - self._hmac_256 = None - - def add_auth(self, http_request, **kwargs): - headers = http_request.headers - method = http_request.method - auth_path = http_request.auth_path - if 'Date' not in headers: - headers['Date'] = formatdate(usegmt=True) - - if self._provider.security_token: - key = self._provider.security_token_header - headers[key] = self._provider.security_token - string_to_sign = boto.utils.canonical_string(method, auth_path, - headers, None, - self._provider) - boto.log.debug('StringToSign:\n%s' % string_to_sign) - b64_hmac = self.sign_string(string_to_sign) - auth_hdr = self._provider.auth_header - auth = ("%s %s:%s" % (auth_hdr, self._provider.access_key, b64_hmac)) - boto.log.debug('Signature:\n%s' % auth) - headers['Authorization'] = auth - - -class HmacAuthV2Handler(AuthHandler, HmacKeys): - """ - Implements the simplified HMAC authorization used by CloudFront. - """ - capability = ['hmac-v2', 'cloudfront'] - - def __init__(self, host, config, provider): - AuthHandler.__init__(self, host, config, provider) - HmacKeys.__init__(self, host, config, provider) - self._hmac_256 = None - - def update_provider(self, provider): - super(HmacAuthV2Handler, self).update_provider(provider) - self._hmac_256 = None - - def add_auth(self, http_request, **kwargs): - headers = http_request.headers - if 'Date' not in headers: - headers['Date'] = formatdate(usegmt=True) - if self._provider.security_token: - key = self._provider.security_token_header - headers[key] = self._provider.security_token - - b64_hmac = self.sign_string(headers['Date']) - auth_hdr = self._provider.auth_header - headers['Authorization'] = ("%s %s:%s" % - (auth_hdr, - self._provider.access_key, b64_hmac)) - - -class HmacAuthV3Handler(AuthHandler, HmacKeys): - """Implements the new Version 3 HMAC authorization used by Route53.""" - - capability = ['hmac-v3', 'route53', 'ses'] - - def __init__(self, host, config, provider): - AuthHandler.__init__(self, host, config, provider) - HmacKeys.__init__(self, host, config, provider) - - def add_auth(self, http_request, **kwargs): - headers = http_request.headers - if 'Date' not in headers: - headers['Date'] = formatdate(usegmt=True) - - if self._provider.security_token: - key = self._provider.security_token_header - headers[key] = self._provider.security_token - - b64_hmac = self.sign_string(headers['Date']) - s = "AWS3-HTTPS AWSAccessKeyId=%s," % self._provider.access_key - s += "Algorithm=%s,Signature=%s" % (self.algorithm(), b64_hmac) - headers['X-Amzn-Authorization'] = s - - -class HmacAuthV3HTTPHandler(AuthHandler, HmacKeys): - """ - Implements the new Version 3 HMAC authorization used by DynamoDB. - """ - - capability = ['hmac-v3-http'] - - def __init__(self, host, config, provider): - AuthHandler.__init__(self, host, config, provider) - HmacKeys.__init__(self, host, config, provider) - - def headers_to_sign(self, http_request): - """ - Select the headers from the request that need to be included - in the StringToSign. - """ - headers_to_sign = {'Host': self.host} - for name, value in http_request.headers.items(): - lname = name.lower() - if lname.startswith('x-amz'): - headers_to_sign[name] = value - return headers_to_sign - - def canonical_headers(self, headers_to_sign): - """ - Return the headers that need to be included in the StringToSign - in their canonical form by converting all header keys to lower - case, sorting them in alphabetical order and then joining - them into a string, separated by newlines. - """ - l = sorted(['%s:%s' % (n.lower().strip(), - headers_to_sign[n].strip()) for n in headers_to_sign]) - return '\n'.join(l) - - def string_to_sign(self, http_request): - """ - Return the canonical StringToSign as well as a dict - containing the original version of all headers that - were included in the StringToSign. - """ - headers_to_sign = self.headers_to_sign(http_request) - canonical_headers = self.canonical_headers(headers_to_sign) - string_to_sign = '\n'.join([http_request.method, - http_request.auth_path, - '', - canonical_headers, - '', - http_request.body]) - return string_to_sign, headers_to_sign - - def add_auth(self, req, **kwargs): - """ - Add AWS3 authentication to a request. - - :type req: :class`boto.connection.HTTPRequest` - :param req: The HTTPRequest object. - """ - # This could be a retry. Make sure the previous - # authorization header is removed first. - if 'X-Amzn-Authorization' in req.headers: - del req.headers['X-Amzn-Authorization'] - req.headers['X-Amz-Date'] = formatdate(usegmt=True) - if self._provider.security_token: - req.headers['X-Amz-Security-Token'] = self._provider.security_token - string_to_sign, headers_to_sign = self.string_to_sign(req) - boto.log.debug('StringToSign:\n%s' % string_to_sign) - hash_value = sha256(string_to_sign.encode('utf-8')).digest() - b64_hmac = self.sign_string(hash_value) - s = "AWS3 AWSAccessKeyId=%s," % self._provider.access_key - s += "Algorithm=%s," % self.algorithm() - s += "SignedHeaders=%s," % ';'.join(headers_to_sign) - s += "Signature=%s" % b64_hmac - req.headers['X-Amzn-Authorization'] = s - - -class HmacAuthV4Handler(AuthHandler, HmacKeys): - """ - Implements the new Version 4 HMAC authorization. - """ - - capability = ['hmac-v4'] - - def __init__(self, host, config, provider, - service_name=None, region_name=None): - AuthHandler.__init__(self, host, config, provider) - HmacKeys.__init__(self, host, config, provider) - # You can set the service_name and region_name to override the - # values which would otherwise come from the endpoint, e.g. - # <service>.<region>.amazonaws.com. - self.service_name = service_name - self.region_name = region_name - - def _sign(self, key, msg, hex=False): - if not isinstance(key, bytes): - key = key.encode('utf-8') - - if hex: - sig = hmac.new(key, msg.encode('utf-8'), sha256).hexdigest() - else: - sig = hmac.new(key, msg.encode('utf-8'), sha256).digest() - return sig - - def headers_to_sign(self, http_request): - """ - Select the headers from the request that need to be included - in the StringToSign. - """ - host_header_value = self.host_header(self.host, http_request) - headers_to_sign = {'Host': host_header_value} - for name, value in http_request.headers.items(): - lname = name.lower() - if lname.startswith('x-amz'): - if isinstance(value, bytes): - value = value.decode('utf-8') - headers_to_sign[name] = value - return headers_to_sign - - def host_header(self, host, http_request): - port = http_request.port - secure = http_request.protocol == 'https' - if ((port == 80 and not secure) or (port == 443 and secure)): - return host - return '%s:%s' % (host, port) - - def query_string(self, http_request): - parameter_names = sorted(http_request.params.keys()) - pairs = [] - for pname in parameter_names: - pval = boto.utils.get_utf8_value(http_request.params[pname]) - pairs.append(urllib.parse.quote(pname, safe='') + '=' + - urllib.parse.quote(pval, safe='-_~')) - return '&'.join(pairs) - - def canonical_query_string(self, http_request): - # POST requests pass parameters in through the - # http_request.body field. - if http_request.method == 'POST': - return "" - l = [] - for param in sorted(http_request.params): - value = boto.utils.get_utf8_value(http_request.params[param]) - l.append('%s=%s' % (urllib.parse.quote(param, safe='-_.~'), - urllib.parse.quote(value, safe='-_.~'))) - return '&'.join(l) - - def canonical_headers(self, headers_to_sign): - """ - Return the headers that need to be included in the StringToSign - in their canonical form by converting all header keys to lower - case, sorting them in alphabetical order and then joining - them into a string, separated by newlines. - """ - canonical = [] - - for header in headers_to_sign: - c_name = header.lower().strip() - raw_value = headers_to_sign[header] - if '"' in raw_value: - c_value = raw_value.strip() - else: - c_value = ' '.join(raw_value.strip().split()) - canonical.append('%s:%s' % (c_name, c_value)) - return '\n'.join(sorted(canonical)) - - def signed_headers(self, headers_to_sign): - l = ['%s' % n.lower().strip() for n in headers_to_sign] - l = sorted(l) - return ';'.join(l) - - def canonical_uri(self, http_request): - path = http_request.auth_path - # Normalize the path - # in windows normpath('/') will be '\\' so we chane it back to '/' - normalized = posixpath.normpath(path).replace('\\', '/') - # Then urlencode whatever's left. - encoded = urllib.parse.quote(normalized) - if len(path) > 1 and path.endswith('/'): - encoded += '/' - return encoded - - def payload(self, http_request): - body = http_request.body - # If the body is a file like object, we can use - # boto.utils.compute_hash, which will avoid reading - # the entire body into memory. - if hasattr(body, 'seek') and hasattr(body, 'read'): - return boto.utils.compute_hash(body, hash_algorithm=sha256)[0] - elif not isinstance(body, bytes): - body = body.encode('utf-8') - return sha256(body).hexdigest() - - def canonical_request(self, http_request): - cr = [http_request.method.upper()] - cr.append(self.canonical_uri(http_request)) - cr.append(self.canonical_query_string(http_request)) - headers_to_sign = self.headers_to_sign(http_request) - cr.append(self.canonical_headers(headers_to_sign) + '\n') - cr.append(self.signed_headers(headers_to_sign)) - cr.append(self.payload(http_request)) - return '\n'.join(cr) - - def scope(self, http_request): - scope = [self._provider.access_key] - scope.append(http_request.timestamp) - scope.append(http_request.region_name) - scope.append(http_request.service_name) - scope.append('aws4_request') - return '/'.join(scope) - - def split_host_parts(self, host): - return host.split('.') - - def determine_region_name(self, host): - parts = self.split_host_parts(host) - if self.region_name is not None: - region_name = self.region_name - elif len(parts) > 1: - if parts[1] == 'us-gov': - region_name = 'us-gov-west-1' - else: - if len(parts) == 3: - region_name = 'us-east-1' - else: - region_name = parts[1] - else: - region_name = parts[0] - - return region_name - - def determine_service_name(self, host): - parts = self.split_host_parts(host) - if self.service_name is not None: - service_name = self.service_name - else: - service_name = parts[0] - return service_name - - def credential_scope(self, http_request): - scope = [] - http_request.timestamp = http_request.headers['X-Amz-Date'][0:8] - scope.append(http_request.timestamp) - # The service_name and region_name either come from: - # * The service_name/region_name attrs or (if these values are None) - # * parsed from the endpoint <service>.<region>.amazonaws.com. - region_name = self.determine_region_name(http_request.host) - service_name = self.determine_service_name(http_request.host) - http_request.service_name = service_name - http_request.region_name = region_name - - scope.append(http_request.region_name) - scope.append(http_request.service_name) - scope.append('aws4_request') - return '/'.join(scope) - - def string_to_sign(self, http_request, canonical_request): - """ - Return the canonical StringToSign as well as a dict - containing the original version of all headers that - were included in the StringToSign. - """ - sts = ['AWS4-HMAC-SHA256'] - sts.append(http_request.headers['X-Amz-Date']) - sts.append(self.credential_scope(http_request)) - sts.append(sha256(canonical_request.encode('utf-8')).hexdigest()) - return '\n'.join(sts) - - def signature(self, http_request, string_to_sign): - key = self._provider.secret_key - k_date = self._sign(('AWS4' + key).encode('utf-8'), - http_request.timestamp) - k_region = self._sign(k_date, http_request.region_name) - k_service = self._sign(k_region, http_request.service_name) - k_signing = self._sign(k_service, 'aws4_request') - return self._sign(k_signing, string_to_sign, hex=True) - - def add_auth(self, req, **kwargs): - """ - Add AWS4 authentication to a request. - - :type req: :class`boto.connection.HTTPRequest` - :param req: The HTTPRequest object. - """ - # This could be a retry. Make sure the previous - # authorization header is removed first. - if 'X-Amzn-Authorization' in req.headers: - del req.headers['X-Amzn-Authorization'] - now = datetime.datetime.utcnow() - req.headers['X-Amz-Date'] = now.strftime('%Y%m%dT%H%M%SZ') - if self._provider.security_token: - req.headers['X-Amz-Security-Token'] = self._provider.security_token - qs = self.query_string(req) - - qs_to_post = qs - - # We do not want to include any params that were mangled into - # the params if performing s3-sigv4 since it does not - # belong in the body of a post for some requests. Mangled - # refers to items in the query string URL being added to the - # http response params. However, these params get added to - # the body of the request, but the query string URL does not - # belong in the body of the request. ``unmangled_resp`` is the - # response that happened prior to the mangling. This ``unmangled_req`` - # kwarg will only appear for s3-sigv4. - if 'unmangled_req' in kwargs: - qs_to_post = self.query_string(kwargs['unmangled_req']) - - if qs_to_post and req.method == 'POST': - # Stash request parameters into post body - # before we generate the signature. - req.body = qs_to_post - req.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8' - req.headers['Content-Length'] = str(len(req.body)) - else: - # Safe to modify req.path here since - # the signature will use req.auth_path. - req.path = req.path.split('?')[0] - - if qs: - # Don't insert the '?' unless there's actually a query string - req.path = req.path + '?' + qs - canonical_request = self.canonical_request(req) - boto.log.debug('CanonicalRequest:\n%s' % canonical_request) - string_to_sign = self.string_to_sign(req, canonical_request) - boto.log.debug('StringToSign:\n%s' % string_to_sign) - signature = self.signature(req, string_to_sign) - boto.log.debug('Signature:\n%s' % signature) - headers_to_sign = self.headers_to_sign(req) - l = ['AWS4-HMAC-SHA256 Credential=%s' % self.scope(req)] - l.append('SignedHeaders=%s' % self.signed_headers(headers_to_sign)) - l.append('Signature=%s' % signature) - req.headers['Authorization'] = ','.join(l) - - -class S3HmacAuthV4Handler(HmacAuthV4Handler, AuthHandler): - """ - Implements a variant of Version 4 HMAC authorization specific to S3. - """ - capability = ['hmac-v4-s3'] - - def __init__(self, *args, **kwargs): - super(S3HmacAuthV4Handler, self).__init__(*args, **kwargs) - - if self.region_name: - self.region_name = self.clean_region_name(self.region_name) - - def clean_region_name(self, region_name): - if region_name.startswith('s3-'): - return region_name[3:] - - return region_name - - def canonical_uri(self, http_request): - # S3 does **NOT** do path normalization that SigV4 typically does. - # Urlencode the path, **NOT** ``auth_path`` (because vhosting). - path = urllib.parse.urlparse(http_request.path) - # Because some quoting may have already been applied, let's back it out. - unquoted = urllib.parse.unquote(path.path) - # Requote, this time addressing all characters. - encoded = urllib.parse.quote(unquoted) - return encoded - - def canonical_query_string(self, http_request): - # Note that we just do not return an empty string for - # POST request. Query strings in url are included in canonical - # query string. - l = [] - for param in sorted(http_request.params): - value = boto.utils.get_utf8_value(http_request.params[param]) - l.append('%s=%s' % (urllib.parse.quote(param, safe='-_.~'), - urllib.parse.quote(value, safe='-_.~'))) - return '&'.join(l) - - def host_header(self, host, http_request): - port = http_request.port - secure = http_request.protocol == 'https' - if ((port == 80 and not secure) or (port == 443 and secure)): - return http_request.host - return '%s:%s' % (http_request.host, port) - - def headers_to_sign(self, http_request): - """ - Select the headers from the request that need to be included - in the StringToSign. - """ - host_header_value = self.host_header(self.host, http_request) - headers_to_sign = {'Host': host_header_value} - for name, value in http_request.headers.items(): - lname = name.lower() - # Hooray for the only difference! The main SigV4 signer only does - # ``Host`` + ``x-amz-*``. But S3 wants pretty much everything - # signed, except for authorization itself. - if lname not in ['authorization']: - headers_to_sign[name] = value - return headers_to_sign - - def determine_region_name(self, host): - # S3's different format(s) of representing region/service from the - # rest of AWS makes this hurt too. - # - # Possible domain formats: - # - s3.amazonaws.com (Classic) - # - s3-us-west-2.amazonaws.com (Specific region) - # - bukkit.s3.amazonaws.com (Vhosted Classic) - # - bukkit.s3-ap-northeast-1.amazonaws.com (Vhosted specific region) - # - s3.cn-north-1.amazonaws.com.cn - (Beijing region) - # - bukkit.s3.cn-north-1.amazonaws.com.cn - (Vhosted Beijing region) - parts = self.split_host_parts(host) - - if self.region_name is not None: - region_name = self.region_name - else: - # Classic URLs - s3-us-west-2.amazonaws.com - if len(parts) == 3: - region_name = self.clean_region_name(parts[0]) - - # Special-case for Classic. - if region_name == 's3': - region_name = 'us-east-1' - else: - # Iterate over the parts in reverse order. - for offset, part in enumerate(reversed(parts)): - part = part.lower() - - # Look for the first thing starting with 's3'. - # Until there's a ``.s3`` TLD, we should be OK. :P - if part == 's3': - # If it's by itself, the region is the previous part. - region_name = parts[-offset] - - # Unless it's Vhosted classic - if region_name == 'amazonaws': - region_name = 'us-east-1' - - break - elif part.startswith('s3-'): - region_name = self.clean_region_name(part) - break - - return region_name - - def determine_service_name(self, host): - # Should this signing mechanism ever be used for anything else, this - # will fail. Consider utilizing the logic from the parent class should - # you find yourself here. - return 's3' - - def mangle_path_and_params(self, req): - """ - Returns a copy of the request object with fixed ``auth_path/params`` - attributes from the original. - """ - modified_req = copy.copy(req) - - # Unlike the most other services, in S3, ``req.params`` isn't the only - # source of query string parameters. - # Because of the ``query_args``, we may already have a query string - # **ON** the ``path/auth_path``. - # Rip them apart, so the ``auth_path/params`` can be signed - # appropriately. - parsed_path = urllib.parse.urlparse(modified_req.auth_path) - modified_req.auth_path = parsed_path.path - - if modified_req.params is None: - modified_req.params = {} - else: - # To keep the original request object untouched. We must make - # a copy of the params dictionary. Because the copy of the - # original request directly refers to the params dictionary - # of the original request. - copy_params = req.params.copy() - modified_req.params = copy_params - - raw_qs = parsed_path.query - existing_qs = urllib.parse.parse_qs( - raw_qs, - keep_blank_values=True - ) - - # ``parse_qs`` will return lists. Don't do that unless there's a real, - # live list provided. - for key, value in existing_qs.items(): - if isinstance(value, (list, tuple)): - if len(value) == 1: - existing_qs[key] = value[0] - - modified_req.params.update(existing_qs) - return modified_req - - def payload(self, http_request): - if http_request.headers.get('x-amz-content-sha256'): - return http_request.headers['x-amz-content-sha256'] - - return super(S3HmacAuthV4Handler, self).payload(http_request) - - def add_auth(self, req, **kwargs): - if 'x-amz-content-sha256' not in req.headers: - if '_sha256' in req.headers: - req.headers['x-amz-content-sha256'] = req.headers.pop('_sha256') - else: - req.headers['x-amz-content-sha256'] = self.payload(req) - updated_req = self.mangle_path_and_params(req) - return super(S3HmacAuthV4Handler, self).add_auth(updated_req, - unmangled_req=req, - **kwargs) - - def presign(self, req, expires, iso_date=None): - """ - Presign a request using SigV4 query params. Takes in an HTTP request - and an expiration time in seconds and returns a URL. - - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html - """ - if iso_date is None: - iso_date = datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%SZ') - - region = self.determine_region_name(req.host) - service = self.determine_service_name(req.host) - - params = { - 'X-Amz-Algorithm': 'AWS4-HMAC-SHA256', - 'X-Amz-Credential': '%s/%s/%s/%s/aws4_request' % ( - self._provider.access_key, - iso_date[:8], - region, - service - ), - 'X-Amz-Date': iso_date, - 'X-Amz-Expires': expires, - 'X-Amz-SignedHeaders': 'host' - } - - if self._provider.security_token: - params['X-Amz-Security-Token'] = self._provider.security_token - - headers_to_sign = self.headers_to_sign(req) - l = sorted(['%s' % n.lower().strip() for n in headers_to_sign]) - params['X-Amz-SignedHeaders'] = ';'.join(l) - - req.params.update(params) - - cr = self.canonical_request(req) - - # We need to replace the payload SHA with a constant - cr = '\n'.join(cr.split('\n')[:-1]) + '\nUNSIGNED-PAYLOAD' - - # Date header is expected for string_to_sign, but unused otherwise - req.headers['X-Amz-Date'] = iso_date - - sts = self.string_to_sign(req, cr) - signature = self.signature(req, sts) - - # Add signature to params now that we have it - req.params['X-Amz-Signature'] = signature - - return 'https://%s%s?%s' % (req.host, req.path, - urllib.parse.urlencode(req.params)) - - -class QueryAuthHandler(AuthHandler): - """ - Provides pure query construction (no actual signing). - - Mostly useful for STS' ``assume_role_with_web_identity``. - - Does **NOT** escape query string values! - """ - - capability = ['pure-query'] - - def _escape_value(self, value): - # Would normally be ``return urllib.parse.quote(value)``. - return value - - def _build_query_string(self, params): - keys = list(params.keys()) - keys.sort(key=lambda x: x.lower()) - pairs = [] - for key in keys: - val = boto.utils.get_utf8_value(params[key]) - pairs.append(key + '=' + self._escape_value(val.decode('utf-8'))) - return '&'.join(pairs) - - def add_auth(self, http_request, **kwargs): - headers = http_request.headers - qs = self._build_query_string( - http_request.params - ) - boto.log.debug('query_string: %s' % qs) - headers['Content-Type'] = 'application/json; charset=UTF-8' - http_request.body = '' - # if this is a retried request, the qs from the previous try will - # already be there, we need to get rid of that and rebuild it - http_request.path = http_request.path.split('?')[0] - http_request.path = http_request.path + '?' + qs - - -class QuerySignatureHelper(HmacKeys): - """ - Helper for Query signature based Auth handler. - - Concrete sub class need to implement _calc_sigature method. - """ - - def add_auth(self, http_request, **kwargs): - headers = http_request.headers - params = http_request.params - params['AWSAccessKeyId'] = self._provider.access_key - params['SignatureVersion'] = self.SignatureVersion - params['Timestamp'] = boto.utils.get_ts() - qs, signature = self._calc_signature( - http_request.params, http_request.method, - http_request.auth_path, http_request.host) - boto.log.debug('query_string: %s Signature: %s' % (qs, signature)) - if http_request.method == 'POST': - headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8' - http_request.body = qs + '&Signature=' + urllib.parse.quote_plus(signature) - http_request.headers['Content-Length'] = str(len(http_request.body)) - else: - http_request.body = '' - # if this is a retried request, the qs from the previous try will - # already be there, we need to get rid of that and rebuild it - http_request.path = http_request.path.split('?')[0] - http_request.path = (http_request.path + '?' + qs + - '&Signature=' + urllib.parse.quote_plus(signature)) - - -class QuerySignatureV0AuthHandler(QuerySignatureHelper, AuthHandler): - """Provides Signature V0 Signing""" - - SignatureVersion = 0 - capability = ['sign-v0'] - - def _calc_signature(self, params, *args): - boto.log.debug('using _calc_signature_0') - hmac = self._get_hmac() - s = params['Action'] + params['Timestamp'] - hmac.update(s.encode('utf-8')) - keys = params.keys() - keys.sort(cmp=lambda x, y: cmp(x.lower(), y.lower())) - pairs = [] - for key in keys: - val = boto.utils.get_utf8_value(params[key]) - pairs.append(key + '=' + urllib.parse.quote(val)) - qs = '&'.join(pairs) - return (qs, base64.b64encode(hmac.digest())) - - -class QuerySignatureV1AuthHandler(QuerySignatureHelper, AuthHandler): - """ - Provides Query Signature V1 Authentication. - """ - - SignatureVersion = 1 - capability = ['sign-v1', 'mturk'] - - def __init__(self, *args, **kw): - QuerySignatureHelper.__init__(self, *args, **kw) - AuthHandler.__init__(self, *args, **kw) - self._hmac_256 = None - - def _calc_signature(self, params, *args): - boto.log.debug('using _calc_signature_1') - hmac = self._get_hmac() - keys = params.keys() - keys.sort(cmp=lambda x, y: cmp(x.lower(), y.lower())) - pairs = [] - for key in keys: - hmac.update(key.encode('utf-8')) - val = boto.utils.get_utf8_value(params[key]) - hmac.update(val) - pairs.append(key + '=' + urllib.parse.quote(val)) - qs = '&'.join(pairs) - return (qs, base64.b64encode(hmac.digest())) - - -class QuerySignatureV2AuthHandler(QuerySignatureHelper, AuthHandler): - """Provides Query Signature V2 Authentication.""" - - SignatureVersion = 2 - capability = ['sign-v2', 'ec2', 'ec2', 'emr', 'fps', 'ecs', - 'sdb', 'iam', 'rds', 'sns', 'sqs', 'cloudformation'] - - def _calc_signature(self, params, verb, path, server_name): - boto.log.debug('using _calc_signature_2') - string_to_sign = '%s\n%s\n%s\n' % (verb, server_name.lower(), path) - hmac = self._get_hmac() - params['SignatureMethod'] = self.algorithm() - if self._provider.security_token: - params['SecurityToken'] = self._provider.security_token - keys = sorted(params.keys()) - pairs = [] - for key in keys: - val = boto.utils.get_utf8_value(params[key]) - pairs.append(urllib.parse.quote(key, safe='') + '=' + - urllib.parse.quote(val, safe='-_~')) - qs = '&'.join(pairs) - boto.log.debug('query string: %s' % qs) - string_to_sign += qs - boto.log.debug('string_to_sign: %s' % string_to_sign) - hmac.update(string_to_sign.encode('utf-8')) - b64 = base64.b64encode(hmac.digest()) - boto.log.debug('len(b64)=%d' % len(b64)) - boto.log.debug('base64 encoded digest: %s' % b64) - return (qs, b64) - - -class POSTPathQSV2AuthHandler(QuerySignatureV2AuthHandler, AuthHandler): - """ - Query Signature V2 Authentication relocating signed query - into the path and allowing POST requests with Content-Types. - """ - - capability = ['mws'] - - def add_auth(self, req, **kwargs): - req.params['AWSAccessKeyId'] = self._provider.access_key - req.params['SignatureVersion'] = self.SignatureVersion - req.params['Timestamp'] = boto.utils.get_ts() - qs, signature = self._calc_signature(req.params, req.method, - req.auth_path, req.host) - boto.log.debug('query_string: %s Signature: %s' % (qs, signature)) - if req.method == 'POST': - req.headers['Content-Length'] = str(len(req.body)) - req.headers['Content-Type'] = req.headers.get('Content-Type', - 'text/plain') - else: - req.body = '' - # if this is a retried req, the qs from the previous try will - # already be there, we need to get rid of that and rebuild it - req.path = req.path.split('?')[0] - req.path = (req.path + '?' + qs + - '&Signature=' + urllib.parse.quote_plus(signature)) - - -def get_auth_handler(host, config, provider, requested_capability=None): - """Finds an AuthHandler that is ready to authenticate. - - Lists through all the registered AuthHandlers to find one that is willing - to handle for the requested capabilities, config and provider. - - :type host: string - :param host: The name of the host - - :type config: - :param config: - - :type provider: - :param provider: - - Returns: - An implementation of AuthHandler. - - Raises: - boto.exception.NoAuthHandlerFound - """ - ready_handlers = [] - auth_handlers = boto.plugin.get_plugin(AuthHandler, requested_capability) - for handler in auth_handlers: - try: - ready_handlers.append(handler(host, config, provider)) - except boto.auth_handler.NotReadyToAuthenticate: - pass - - if not ready_handlers: - checked_handlers = auth_handlers - names = [handler.__name__ for handler in checked_handlers] - raise boto.exception.NoAuthHandlerFound( - 'No handler was ready to authenticate. %d handlers were checked.' - ' %s ' - 'Check your credentials' % (len(names), str(names))) - - # We select the last ready auth handler that was loaded, to allow users to - # customize how auth works in environments where there are shared boto - # config files (e.g., /etc/boto.cfg and ~/.boto): The more general, - # system-wide shared configs should be loaded first, and the user's - # customizations loaded last. That way, for example, the system-wide - # config might include a plugin_directory that includes a service account - # auth plugin shared by all users of a Google Compute Engine instance - # (allowing sharing of non-user data between various services), and the - # user could override this with a .boto config that includes user-specific - # credentials (for access to user data). - return ready_handlers[-1] - - -def detect_potential_sigv4(func): - def _wrapper(self): - if os.environ.get('EC2_USE_SIGV4', False): - return ['hmac-v4'] - - if boto.config.get('ec2', 'use-sigv4', False): - return ['hmac-v4'] - - if hasattr(self, 'region'): - # If you're making changes here, you should also check - # ``boto/iam/connection.py``, as several things there are also - # endpoint-related. - if getattr(self.region, 'endpoint', ''): - if '.cn-' in self.region.endpoint or \ - '.eu-central' in self.region.endpoint: - return ['hmac-v4'] - - return func(self) - return _wrapper - - -def detect_potential_s3sigv4(func): - def _wrapper(self): - if os.environ.get('S3_USE_SIGV4', False): - return ['hmac-v4-s3'] - - if boto.config.get('s3', 'use-sigv4', False): - return ['hmac-v4-s3'] - - if hasattr(self, 'host'): - # If you're making changes here, you should also check - # ``boto/iam/connection.py``, as several things there are also - # endpoint-related. - if '.cn-' in self.host or '.eu-central' in self.host: - return ['hmac-v4-s3'] - - return func(self) - return _wrapper diff --git a/awx/lib/site-packages/boto/auth_handler.py b/awx/lib/site-packages/boto/auth_handler.py deleted file mode 100644 index a8583f8aa3..0000000000 --- a/awx/lib/site-packages/boto/auth_handler.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Defines an interface which all Auth handlers need to implement. -""" - -from boto.plugin import Plugin - - -class NotReadyToAuthenticate(Exception): - pass - - -class AuthHandler(Plugin): - - capability = [] - - def __init__(self, host, config, provider): - """Constructs the handlers. - :type host: string - :param host: The host to which the request is being sent. - - :type config: boto.pyami.Config - :param config: Boto configuration. - - :type provider: boto.provider.Provider - :param provider: Provider details. - - Raises: - NotReadyToAuthenticate: if this handler is not willing to - authenticate for the given provider and config. - """ - pass - - def add_auth(self, http_request): - """Invoked to add authentication details to request. - - :type http_request: boto.connection.HTTPRequest - :param http_request: HTTP request that needs to be authenticated. - """ - pass diff --git a/awx/lib/site-packages/boto/beanstalk/__init__.py b/awx/lib/site-packages/boto/beanstalk/__init__.py deleted file mode 100644 index c3928bcd1b..0000000000 --- a/awx/lib/site-packages/boto/beanstalk/__init__.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the AWS Elastic Beanstalk service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - import boto.beanstalk.layer1 - return get_regions( - 'elasticbeanstalk', - connection_cls=boto.beanstalk.layer1.Layer1 - ) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/beanstalk/exception.py b/awx/lib/site-packages/boto/beanstalk/exception.py deleted file mode 100644 index 0fbd4ab9fa..0000000000 --- a/awx/lib/site-packages/boto/beanstalk/exception.py +++ /dev/null @@ -1,63 +0,0 @@ -import sys -from boto.compat import json -from boto.exception import BotoServerError - - -def simple(e): - code = e.code - - if code.endswith('Exception'): - code = code.rstrip('Exception') - - try: - # Dynamically get the error class. - simple_e = getattr(sys.modules[__name__], code)(e) - except AttributeError: - # Return original exception on failure. - return e - - return simple_e - - -class SimpleException(BotoServerError): - def __init__(self, e): - super(SimpleException, self).__init__(e.status, e.reason, e.body) - self.error_message = self.message - - def __repr__(self): - return self.__class__.__name__ + ': ' + self.error_message - def __str__(self): - return self.__class__.__name__ + ': ' + self.error_message - - -class ValidationError(SimpleException): pass - -# Common beanstalk exceptions. -class IncompleteSignature(SimpleException): pass -class InternalFailure(SimpleException): pass -class InvalidAction(SimpleException): pass -class InvalidClientTokenId(SimpleException): pass -class InvalidParameterCombination(SimpleException): pass -class InvalidParameterValue(SimpleException): pass -class InvalidQueryParameter(SimpleException): pass -class MalformedQueryString(SimpleException): pass -class MissingAction(SimpleException): pass -class MissingAuthenticationToken(SimpleException): pass -class MissingParameter(SimpleException): pass -class OptInRequired(SimpleException): pass -class RequestExpired(SimpleException): pass -class ServiceUnavailable(SimpleException): pass -class Throttling(SimpleException): pass - - -# Action specific exceptions. -class TooManyApplications(SimpleException): pass -class InsufficientPrivileges(SimpleException): pass -class S3LocationNotInServiceRegion(SimpleException): pass -class TooManyApplicationVersions(SimpleException): pass -class TooManyConfigurationTemplates(SimpleException): pass -class TooManyEnvironments(SimpleException): pass -class S3SubscriptionRequired(SimpleException): pass -class TooManyBuckets(SimpleException): pass -class OperationInProgress(SimpleException): pass -class SourceBundleDeletion(SimpleException): pass diff --git a/awx/lib/site-packages/boto/beanstalk/layer1.py b/awx/lib/site-packages/boto/beanstalk/layer1.py deleted file mode 100644 index e72ee23ec5..0000000000 --- a/awx/lib/site-packages/boto/beanstalk/layer1.py +++ /dev/null @@ -1,1201 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -import boto.jsonresponse -from boto.compat import json -from boto.regioninfo import RegionInfo -from boto.connection import AWSQueryConnection - - -class Layer1(AWSQueryConnection): - - APIVersion = '2010-12-01' - DefaultRegionName = 'us-east-1' - DefaultRegionEndpoint = 'elasticbeanstalk.us-east-1.amazonaws.com' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, - proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - api_version=None, security_token=None, profile_name=None): - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - super(Layer1, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token, profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def _encode_bool(self, v): - v = bool(v) - return {True: "true", False: "false"}[v] - - def _get_response(self, action, params, path='/', verb='GET'): - params['ContentType'] = 'JSON' - response = self.make_request(action, params, path, verb) - body = response.read().decode('utf-8') - boto.log.debug(body) - if response.status == 200: - return json.loads(body) - else: - raise self.ResponseError(response.status, response.reason, body) - - def check_dns_availability(self, cname_prefix): - """Checks if the specified CNAME is available. - - :type cname_prefix: string - :param cname_prefix: The prefix used when this CNAME is - reserved. - """ - params = {'CNAMEPrefix': cname_prefix} - return self._get_response('CheckDNSAvailability', params) - - def create_application(self, application_name, description=None): - """ - Creates an application that has one configuration template - named default and no application versions. - - :type application_name: string - :param application_name: The name of the application. - Constraint: This name must be unique within your account. If the - specified name already exists, the action returns an - InvalidParameterValue error. - - :type description: string - :param description: Describes the application. - - :raises: TooManyApplicationsException - """ - params = {'ApplicationName': application_name} - if description: - params['Description'] = description - return self._get_response('CreateApplication', params) - - def create_application_version(self, application_name, version_label, - description=None, s3_bucket=None, - s3_key=None, auto_create_application=None): - """Creates an application version for the specified application. - - :type application_name: string - :param application_name: The name of the application. If no - application is found with this name, and AutoCreateApplication is - false, returns an InvalidParameterValue error. - - :type version_label: string - :param version_label: A label identifying this version. Constraint: - Must be unique per application. If an application version already - exists with this label for the specified application, AWS Elastic - Beanstalk returns an InvalidParameterValue error. - - :type description: string - :param description: Describes this version. - - :type s3_bucket: string - :param s3_bucket: The Amazon S3 bucket where the data is located. - - :type s3_key: string - :param s3_key: The Amazon S3 key where the data is located. Both - s3_bucket and s3_key must be specified in order to use a specific - source bundle. If both of these values are not specified the - sample application will be used. - - :type auto_create_application: boolean - :param auto_create_application: Determines how the system behaves if - the specified application for this version does not already exist: - true: Automatically creates the specified application for this - version if it does not already exist. false: Returns an - InvalidParameterValue if the specified application for this version - does not already exist. Default: false Valid Values: true | false - - :raises: TooManyApplicationsException, - TooManyApplicationVersionsException, - InsufficientPrivilegesException, - S3LocationNotInServiceRegionException - - """ - params = {'ApplicationName': application_name, - 'VersionLabel': version_label} - if description: - params['Description'] = description - if s3_bucket and s3_key: - params['SourceBundle.S3Bucket'] = s3_bucket - params['SourceBundle.S3Key'] = s3_key - if auto_create_application: - params['AutoCreateApplication'] = self._encode_bool( - auto_create_application) - return self._get_response('CreateApplicationVersion', params) - - def create_configuration_template(self, application_name, template_name, - solution_stack_name=None, - source_configuration_application_name=None, - source_configuration_template_name=None, - environment_id=None, description=None, - option_settings=None): - """Creates a configuration template. - - Templates are associated with a specific application and are used to - deploy different versions of the application with the same - configuration settings. - - :type application_name: string - :param application_name: The name of the application to associate with - this configuration template. If no application is found with this - name, AWS Elastic Beanstalk returns an InvalidParameterValue error. - - :type template_name: string - :param template_name: The name of the configuration template. - Constraint: This name must be unique per application. Default: If - a configuration template already exists with this name, AWS Elastic - Beanstalk returns an InvalidParameterValue error. - - :type solution_stack_name: string - :param solution_stack_name: The name of the solution stack used by this - configuration. The solution stack specifies the operating system, - architecture, and application server for a configuration template. - It determines the set of configuration options as well as the - possible and default values. Use ListAvailableSolutionStacks to - obtain a list of available solution stacks. Default: If the - SolutionStackName is not specified and the source configuration - parameter is blank, AWS Elastic Beanstalk uses the default solution - stack. If not specified and the source configuration parameter is - specified, AWS Elastic Beanstalk uses the same solution stack as - the source configuration template. - - :type source_configuration_application_name: string - :param source_configuration_application_name: The name of the - application associated with the configuration. - - :type source_configuration_template_name: string - :param source_configuration_template_name: The name of the - configuration template. - - :type environment_id: string - :param environment_id: The ID of the environment used with this - configuration template. - - :type description: string - :param description: Describes this configuration. - - :type option_settings: list - :param option_settings: If specified, AWS Elastic Beanstalk sets the - specified configuration option to the requested value. The new - value overrides the value obtained from the solution stack or the - source configuration template. - - :raises: InsufficientPrivilegesException, - TooManyConfigurationTemplatesException - """ - params = {'ApplicationName': application_name, - 'TemplateName': template_name} - if solution_stack_name: - params['SolutionStackName'] = solution_stack_name - if source_configuration_application_name: - params['SourceConfiguration.ApplicationName'] = source_configuration_application_name - if source_configuration_template_name: - params['SourceConfiguration.TemplateName'] = source_configuration_template_name - if environment_id: - params['EnvironmentId'] = environment_id - if description: - params['Description'] = description - if option_settings: - self._build_list_params(params, option_settings, - 'OptionSettings.member', - ('Namespace', 'OptionName', 'Value')) - return self._get_response('CreateConfigurationTemplate', params) - - def create_environment(self, application_name, environment_name, - version_label=None, template_name=None, - solution_stack_name=None, cname_prefix=None, - description=None, option_settings=None, - options_to_remove=None, tier_name=None, - tier_type=None, tier_version='1.0'): - """Launches an environment for the application using a configuration. - - :type application_name: string - :param application_name: The name of the application that contains the - version to be deployed. If no application is found with this name, - CreateEnvironment returns an InvalidParameterValue error. - - :type environment_name: string - :param environment_name: A unique name for the deployment environment. - Used in the application URL. Constraint: Must be from 4 to 23 - characters in length. The name can contain only letters, numbers, - and hyphens. It cannot start or end with a hyphen. This name must - be unique in your account. If the specified name already exists, - AWS Elastic Beanstalk returns an InvalidParameterValue error. - Default: If the CNAME parameter is not specified, the environment - name becomes part of the CNAME, and therefore part of the visible - URL for your application. - - :type version_label: string - :param version_label: The name of the application version to deploy. If - the specified application has no associated application versions, - AWS Elastic Beanstalk UpdateEnvironment returns an - InvalidParameterValue error. Default: If not specified, AWS - Elastic Beanstalk attempts to launch the most recently created - application version. - - :type template_name: string - :param template_name: The name of the configuration template to - use in deployment. If no configuration template is found with this - name, AWS Elastic Beanstalk returns an InvalidParameterValue error. - Condition: You must specify either this parameter or a - SolutionStackName, but not both. If you specify both, AWS Elastic - Beanstalk returns an InvalidParameterCombination error. If you do - not specify either, AWS Elastic Beanstalk returns a - MissingRequiredParameter error. - - :type solution_stack_name: string - :param solution_stack_name: This is an alternative to specifying a - configuration name. If specified, AWS Elastic Beanstalk sets the - configuration values to the default values associated with the - specified solution stack. Condition: You must specify either this - or a TemplateName, but not both. If you specify both, AWS Elastic - Beanstalk returns an InvalidParameterCombination error. If you do - not specify either, AWS Elastic Beanstalk returns a - MissingRequiredParameter error. - - :type cname_prefix: string - :param cname_prefix: If specified, the environment attempts to use this - value as the prefix for the CNAME. If not specified, the - environment uses the environment name. - - :type description: string - :param description: Describes this environment. - - :type option_settings: list - :param option_settings: If specified, AWS Elastic Beanstalk sets the - specified configuration options to the requested value in the - configuration set for the new environment. These override the - values obtained from the solution stack or the configuration - template. Each element in the list is a tuple of (Namespace, - OptionName, Value), for example:: - - [('aws:autoscaling:launchconfiguration', - 'Ec2KeyName', 'mykeypair')] - - :type options_to_remove: list - :param options_to_remove: A list of custom user-defined configuration - options to remove from the configuration set for this new - environment. - - :type tier_name: string - :param tier_name: The name of the tier. Valid values are - "WebServer" and "Worker". Defaults to "WebServer". - The ``tier_name`` and a ``tier_type`` parameters are - related and the values provided must be valid. - The possible combinations are: - - * "WebServer" and "Standard" (the default) - * "Worker" and "SQS/HTTP" - - :type tier_type: string - :param tier_type: The type of the tier. Valid values are - "Standard" if ``tier_name`` is "WebServer" and "SQS/HTTP" - if ``tier_name`` is "Worker". Defaults to "Standard". - - :type tier_version: string - :type tier_version: The version of the tier. Valid values - currently are "1.0". Defaults to "1.0". - - :raises: TooManyEnvironmentsException, InsufficientPrivilegesException - - """ - params = {'ApplicationName': application_name, - 'EnvironmentName': environment_name} - if version_label: - params['VersionLabel'] = version_label - if template_name: - params['TemplateName'] = template_name - if solution_stack_name: - params['SolutionStackName'] = solution_stack_name - if cname_prefix: - params['CNAMEPrefix'] = cname_prefix - if description: - params['Description'] = description - if option_settings: - self._build_list_params(params, option_settings, - 'OptionSettings.member', - ('Namespace', 'OptionName', 'Value')) - if options_to_remove: - self.build_list_params(params, options_to_remove, - 'OptionsToRemove.member') - if tier_name and tier_type and tier_version: - params['Tier.Name'] = tier_name - params['Tier.Type'] = tier_type - params['Tier.Version'] = tier_version - return self._get_response('CreateEnvironment', params) - - def create_storage_location(self): - """ - Creates the Amazon S3 storage location for the account. This - location is used to store user log files. - - :raises: TooManyBucketsException, - S3SubscriptionRequiredException, - InsufficientPrivilegesException - - """ - return self._get_response('CreateStorageLocation', params={}) - - def delete_application(self, application_name, - terminate_env_by_force=None): - """ - Deletes the specified application along with all associated - versions and configurations. The application versions will not - be deleted from your Amazon S3 bucket. - - :type application_name: string - :param application_name: The name of the application to delete. - - :type terminate_env_by_force: boolean - :param terminate_env_by_force: When set to true, running - environments will be terminated before deleting the application. - - :raises: OperationInProgressException - - """ - params = {'ApplicationName': application_name} - if terminate_env_by_force: - params['TerminateEnvByForce'] = self._encode_bool( - terminate_env_by_force) - return self._get_response('DeleteApplication', params) - - def delete_application_version(self, application_name, version_label, - delete_source_bundle=None): - """Deletes the specified version from the specified application. - - :type application_name: string - :param application_name: The name of the application to delete - releases from. - - :type version_label: string - :param version_label: The label of the version to delete. - - :type delete_source_bundle: boolean - :param delete_source_bundle: Indicates whether to delete the - associated source bundle from Amazon S3. Valid Values: true | - false - - :raises: SourceBundleDeletionException, - InsufficientPrivilegesException, - OperationInProgressException, - S3LocationNotInServiceRegionException - """ - params = {'ApplicationName': application_name, - 'VersionLabel': version_label} - if delete_source_bundle: - params['DeleteSourceBundle'] = self._encode_bool( - delete_source_bundle) - return self._get_response('DeleteApplicationVersion', params) - - def delete_configuration_template(self, application_name, template_name): - """Deletes the specified configuration template. - - :type application_name: string - :param application_name: The name of the application to delete - the configuration template from. - - :type template_name: string - :param template_name: The name of the configuration template to - delete. - - :raises: OperationInProgressException - - """ - params = {'ApplicationName': application_name, - 'TemplateName': template_name} - return self._get_response('DeleteConfigurationTemplate', params) - - def delete_environment_configuration(self, application_name, - environment_name): - """ - Deletes the draft configuration associated with the running - environment. Updating a running environment with any - configuration changes creates a draft configuration set. You can - get the draft configuration using DescribeConfigurationSettings - while the update is in progress or if the update fails. The - DeploymentStatus for the draft configuration indicates whether - the deployment is in process or has failed. The draft - configuration remains in existence until it is deleted with this - action. - - :type application_name: string - :param application_name: The name of the application the - environment is associated with. - - :type environment_name: string - :param environment_name: The name of the environment to delete - the draft configuration from. - - """ - params = {'ApplicationName': application_name, - 'EnvironmentName': environment_name} - return self._get_response('DeleteEnvironmentConfiguration', params) - - def describe_application_versions(self, application_name=None, - version_labels=None): - """Returns descriptions for existing application versions. - - :type application_name: string - :param application_name: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to only include ones that are associated - with the specified application. - - :type version_labels: list - :param version_labels: If specified, restricts the returned - descriptions to only include ones that have the specified version - labels. - - """ - params = {} - if application_name: - params['ApplicationName'] = application_name - if version_labels: - self.build_list_params(params, version_labels, - 'VersionLabels.member') - return self._get_response('DescribeApplicationVersions', params) - - def describe_applications(self, application_names=None): - """Returns the descriptions of existing applications. - - :type application_names: list - :param application_names: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to only include those with the specified - names. - - """ - params = {} - if application_names: - self.build_list_params(params, application_names, - 'ApplicationNames.member') - return self._get_response('DescribeApplications', params) - - def describe_configuration_options(self, application_name=None, - template_name=None, - environment_name=None, - solution_stack_name=None, options=None): - """Describes configuration options used in a template or environment. - - Describes the configuration options that are used in a - particular configuration template or environment, or that a - specified solution stack defines. The description includes the - values the options, their default values, and an indication of - the required action on a running environment if an option value - is changed. - - :type application_name: string - :param application_name: The name of the application associated with - the configuration template or environment. Only needed if you want - to describe the configuration options associated with either the - configuration template or environment. - - :type template_name: string - :param template_name: The name of the configuration template whose - configuration options you want to describe. - - :type environment_name: string - :param environment_name: The name of the environment whose - configuration options you want to describe. - - :type solution_stack_name: string - :param solution_stack_name: The name of the solution stack whose - configuration options you want to describe. - - :type options: list - :param options: If specified, restricts the descriptions to only - the specified options. - """ - params = {} - if application_name: - params['ApplicationName'] = application_name - if template_name: - params['TemplateName'] = template_name - if environment_name: - params['EnvironmentName'] = environment_name - if solution_stack_name: - params['SolutionStackName'] = solution_stack_name - if options: - self.build_list_params(params, options, 'Options.member') - return self._get_response('DescribeConfigurationOptions', params) - - def describe_configuration_settings(self, application_name, - template_name=None, - environment_name=None): - """ - Returns a description of the settings for the specified - configuration set, that is, either a configuration template or - the configuration set associated with a running environment. - When describing the settings for the configuration set - associated with a running environment, it is possible to receive - two sets of setting descriptions. One is the deployed - configuration set, and the other is a draft configuration of an - environment that is either in the process of deployment or that - failed to deploy. - - :type application_name: string - :param application_name: The application for the environment or - configuration template. - - :type template_name: string - :param template_name: The name of the configuration template to - describe. Conditional: You must specify either this parameter or - an EnvironmentName, but not both. If you specify both, AWS Elastic - Beanstalk returns an InvalidParameterCombination error. If you do - not specify either, AWS Elastic Beanstalk returns a - MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the environment to describe. - Condition: You must specify either this or a TemplateName, but not - both. If you specify both, AWS Elastic Beanstalk returns an - InvalidParameterCombination error. If you do not specify either, - AWS Elastic Beanstalk returns MissingRequiredParameter error. - """ - params = {'ApplicationName': application_name} - if template_name: - params['TemplateName'] = template_name - if environment_name: - params['EnvironmentName'] = environment_name - return self._get_response('DescribeConfigurationSettings', params) - - def describe_environment_resources(self, environment_id=None, - environment_name=None): - """Returns AWS resources for this environment. - - :type environment_id: string - :param environment_id: The ID of the environment to retrieve AWS - resource usage data. Condition: You must specify either this or an - EnvironmentName, or both. If you do not specify either, AWS Elastic - Beanstalk returns MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the environment to retrieve - AWS resource usage data. Condition: You must specify either this - or an EnvironmentId, or both. If you do not specify either, AWS - Elastic Beanstalk returns MissingRequiredParameter error. - - :raises: InsufficientPrivilegesException - """ - params = {} - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - return self._get_response('DescribeEnvironmentResources', params) - - def describe_environments(self, application_name=None, version_label=None, - environment_ids=None, environment_names=None, - include_deleted=None, - included_deleted_back_to=None): - """Returns descriptions for existing environments. - - :type application_name: string - :param application_name: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to include only those that are associated - with this application. - - :type version_label: string - :param version_label: If specified, AWS Elastic Beanstalk restricts the - returned descriptions to include only those that are associated - with this application version. - - :type environment_ids: list - :param environment_ids: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to include only those that have the - specified IDs. - - :type environment_names: list - :param environment_names: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to include only those that have the - specified names. - - :type include_deleted: boolean - :param include_deleted: Indicates whether to include deleted - environments: true: Environments that have been deleted after - IncludedDeletedBackTo are displayed. false: Do not include deleted - environments. - - :type included_deleted_back_to: timestamp - :param included_deleted_back_to: If specified when IncludeDeleted is - set to true, then environments deleted after this date are - displayed. - """ - params = {} - if application_name: - params['ApplicationName'] = application_name - if version_label: - params['VersionLabel'] = version_label - if environment_ids: - self.build_list_params(params, environment_ids, - 'EnvironmentIds.member') - if environment_names: - self.build_list_params(params, environment_names, - 'EnvironmentNames.member') - if include_deleted: - params['IncludeDeleted'] = self._encode_bool(include_deleted) - if included_deleted_back_to: - params['IncludedDeletedBackTo'] = included_deleted_back_to - return self._get_response('DescribeEnvironments', params) - - def describe_events(self, application_name=None, version_label=None, - template_name=None, environment_id=None, - environment_name=None, request_id=None, severity=None, - start_time=None, end_time=None, max_records=None, - next_token=None): - """Returns event descriptions matching criteria up to the last 6 weeks. - - :type application_name: string - :param application_name: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to include only those associated with - this application. - - :type version_label: string - :param version_label: If specified, AWS Elastic Beanstalk restricts the - returned descriptions to those associated with this application - version. - - :type template_name: string - :param template_name: If specified, AWS Elastic Beanstalk restricts the - returned descriptions to those that are associated with this - environment configuration. - - :type environment_id: string - :param environment_id: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to those associated with this - environment. - - :type environment_name: string - :param environment_name: If specified, AWS Elastic Beanstalk restricts - the returned descriptions to those associated with this - environment. - - :type request_id: string - :param request_id: If specified, AWS Elastic Beanstalk restricts the - described events to include only those associated with this request - ID. - - :type severity: string - :param severity: If specified, limits the events returned from this - call to include only those with the specified severity or higher. - - :type start_time: timestamp - :param start_time: If specified, AWS Elastic Beanstalk restricts the - returned descriptions to those that occur on or after this time. - - :type end_time: timestamp - :param end_time: If specified, AWS Elastic Beanstalk restricts the - returned descriptions to those that occur up to, but not including, - the EndTime. - - :type max_records: integer - :param max_records: Specifies the maximum number of events that can be - returned, beginning with the most recent event. - - :type next_token: string - :param next_token: Pagination token. If specified, the events return - the next batch of results. - """ - params = {} - if application_name: - params['ApplicationName'] = application_name - if version_label: - params['VersionLabel'] = version_label - if template_name: - params['TemplateName'] = template_name - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - if request_id: - params['RequestId'] = request_id - if severity: - params['Severity'] = severity - if start_time: - params['StartTime'] = start_time - if end_time: - params['EndTime'] = end_time - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - return self._get_response('DescribeEvents', params) - - def list_available_solution_stacks(self): - """Returns a list of the available solution stack names.""" - return self._get_response('ListAvailableSolutionStacks', params={}) - - def rebuild_environment(self, environment_id=None, environment_name=None): - """ - Deletes and recreates all of the AWS resources (for example: - the Auto Scaling group, load balancer, etc.) for a specified - environment and forces a restart. - - :type environment_id: string - :param environment_id: The ID of the environment to rebuild. - Condition: You must specify either this or an EnvironmentName, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the environment to rebuild. - Condition: You must specify either this or an EnvironmentId, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - - :raises: InsufficientPrivilegesException - """ - params = {} - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - return self._get_response('RebuildEnvironment', params) - - def request_environment_info(self, info_type='tail', environment_id=None, - environment_name=None): - """ - Initiates a request to compile the specified type of - information of the deployed environment. Setting the InfoType - to tail compiles the last lines from the application server log - files of every Amazon EC2 instance in your environment. Use - RetrieveEnvironmentInfo to access the compiled information. - - :type info_type: string - :param info_type: The type of information to request. - - :type environment_id: string - :param environment_id: The ID of the environment of the - requested data. If no such environment is found, - RequestEnvironmentInfo returns an InvalidParameterValue error. - Condition: You must specify either this or an EnvironmentName, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the environment of the - requested data. If no such environment is found, - RequestEnvironmentInfo returns an InvalidParameterValue error. - Condition: You must specify either this or an EnvironmentId, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - """ - params = {'InfoType': info_type} - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - return self._get_response('RequestEnvironmentInfo', params) - - def restart_app_server(self, environment_id=None, environment_name=None): - """ - Causes the environment to restart the application container - server running on each Amazon EC2 instance. - - :type environment_id: string - :param environment_id: The ID of the environment to restart the server - for. Condition: You must specify either this or an - EnvironmentName, or both. If you do not specify either, AWS Elastic - Beanstalk returns MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the environment to restart the - server for. Condition: You must specify either this or an - EnvironmentId, or both. If you do not specify either, AWS Elastic - Beanstalk returns MissingRequiredParameter error. - """ - params = {} - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - return self._get_response('RestartAppServer', params) - - def retrieve_environment_info(self, info_type='tail', environment_id=None, - environment_name=None): - """ - Retrieves the compiled information from a RequestEnvironmentInfo - request. - - :type info_type: string - :param info_type: The type of information to retrieve. - - :type environment_id: string - :param environment_id: The ID of the data's environment. If no such - environment is found, returns an InvalidParameterValue error. - Condition: You must specify either this or an EnvironmentName, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the data's environment. If no such - environment is found, returns an InvalidParameterValue error. - Condition: You must specify either this or an EnvironmentId, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - """ - params = {'InfoType': info_type} - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - return self._get_response('RetrieveEnvironmentInfo', params) - - def swap_environment_cnames(self, source_environment_id=None, - source_environment_name=None, - destination_environment_id=None, - destination_environment_name=None): - """Swaps the CNAMEs of two environments. - - :type source_environment_id: string - :param source_environment_id: The ID of the source environment. - Condition: You must specify at least the SourceEnvironmentID or the - SourceEnvironmentName. You may also specify both. If you specify - the SourceEnvironmentId, you must specify the - DestinationEnvironmentId. - - :type source_environment_name: string - :param source_environment_name: The name of the source environment. - Condition: You must specify at least the SourceEnvironmentID or the - SourceEnvironmentName. You may also specify both. If you specify - the SourceEnvironmentName, you must specify the - DestinationEnvironmentName. - - :type destination_environment_id: string - :param destination_environment_id: The ID of the destination - environment. Condition: You must specify at least the - DestinationEnvironmentID or the DestinationEnvironmentName. You may - also specify both. You must specify the SourceEnvironmentId with - the DestinationEnvironmentId. - - :type destination_environment_name: string - :param destination_environment_name: The name of the destination - environment. Condition: You must specify at least the - DestinationEnvironmentID or the DestinationEnvironmentName. You may - also specify both. You must specify the SourceEnvironmentName with - the DestinationEnvironmentName. - """ - params = {} - if source_environment_id: - params['SourceEnvironmentId'] = source_environment_id - if source_environment_name: - params['SourceEnvironmentName'] = source_environment_name - if destination_environment_id: - params['DestinationEnvironmentId'] = destination_environment_id - if destination_environment_name: - params['DestinationEnvironmentName'] = destination_environment_name - return self._get_response('SwapEnvironmentCNAMEs', params) - - def terminate_environment(self, environment_id=None, environment_name=None, - terminate_resources=None): - """Terminates the specified environment. - - :type environment_id: string - :param environment_id: The ID of the environment to terminate. - Condition: You must specify either this or an EnvironmentName, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the environment to terminate. - Condition: You must specify either this or an EnvironmentId, or - both. If you do not specify either, AWS Elastic Beanstalk returns - MissingRequiredParameter error. - - :type terminate_resources: boolean - :param terminate_resources: Indicates whether the associated AWS - resources should shut down when the environment is terminated: - true: (default) The user AWS resources (for example, the Auto - Scaling group, LoadBalancer, etc.) are terminated along with the - environment. false: The environment is removed from the AWS - Elastic Beanstalk but the AWS resources continue to operate. For - more information, see the AWS Elastic Beanstalk User Guide. - Default: true Valid Values: true | false - - :raises: InsufficientPrivilegesException - """ - params = {} - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - if terminate_resources: - params['TerminateResources'] = self._encode_bool( - terminate_resources) - return self._get_response('TerminateEnvironment', params) - - def update_application(self, application_name, description=None): - """ - Updates the specified application to have the specified - properties. - - :type application_name: string - :param application_name: The name of the application to update. - If no such application is found, UpdateApplication returns an - InvalidParameterValue error. - - :type description: string - :param description: A new description for the application. Default: If - not specified, AWS Elastic Beanstalk does not update the - description. - """ - params = {'ApplicationName': application_name} - if description: - params['Description'] = description - return self._get_response('UpdateApplication', params) - - def update_application_version(self, application_name, version_label, - description=None): - """Updates the application version to have the properties. - - :type application_name: string - :param application_name: The name of the application associated with - this version. If no application is found with this name, - UpdateApplication returns an InvalidParameterValue error. - - :type version_label: string - :param version_label: The name of the version to update. If no - application version is found with this label, UpdateApplication - returns an InvalidParameterValue error. - - :type description: string - :param description: A new description for this release. - """ - params = {'ApplicationName': application_name, - 'VersionLabel': version_label} - if description: - params['Description'] = description - return self._get_response('UpdateApplicationVersion', params) - - def update_configuration_template(self, application_name, template_name, - description=None, option_settings=None, - options_to_remove=None): - """ - Updates the specified configuration template to have the - specified properties or configuration option values. - - :type application_name: string - :param application_name: The name of the application associated with - the configuration template to update. If no application is found - with this name, UpdateConfigurationTemplate returns an - InvalidParameterValue error. - - :type template_name: string - :param template_name: The name of the configuration template to update. - If no configuration template is found with this name, - UpdateConfigurationTemplate returns an InvalidParameterValue error. - - :type description: string - :param description: A new description for the configuration. - - :type option_settings: list - :param option_settings: A list of configuration option settings to - update with the new specified option value. - - :type options_to_remove: list - :param options_to_remove: A list of configuration options to remove - from the configuration set. Constraint: You can remove only - UserDefined configuration options. - - :raises: InsufficientPrivilegesException - """ - params = {'ApplicationName': application_name, - 'TemplateName': template_name} - if description: - params['Description'] = description - if option_settings: - self._build_list_params(params, option_settings, - 'OptionSettings.member', - ('Namespace', 'OptionName', 'Value')) - if options_to_remove: - self.build_list_params(params, options_to_remove, - 'OptionsToRemove.member') - return self._get_response('UpdateConfigurationTemplate', params) - - def update_environment(self, environment_id=None, environment_name=None, - version_label=None, template_name=None, - description=None, option_settings=None, - options_to_remove=None, tier_name=None, - tier_type=None, tier_version='1.0'): - """ - Updates the environment description, deploys a new application - version, updates the configuration settings to an entirely new - configuration template, or updates select configuration option - values in the running environment. Attempting to update both - the release and configuration is not allowed and AWS Elastic - Beanstalk returns an InvalidParameterCombination error. When - updating the configuration settings to a new template or - individual settings, a draft configuration is created and - DescribeConfigurationSettings for this environment returns two - setting descriptions with different DeploymentStatus values. - - :type environment_id: string - :param environment_id: The ID of the environment to update. If no - environment with this ID exists, AWS Elastic Beanstalk returns an - InvalidParameterValue error. Condition: You must specify either - this or an EnvironmentName, or both. If you do not specify either, - AWS Elastic Beanstalk returns MissingRequiredParameter error. - - :type environment_name: string - :param environment_name: The name of the environment to update. If no - environment with this name exists, AWS Elastic Beanstalk returns an - InvalidParameterValue error. Condition: You must specify either - this or an EnvironmentId, or both. If you do not specify either, - AWS Elastic Beanstalk returns MissingRequiredParameter error. - - :type version_label: string - :param version_label: If this parameter is specified, AWS Elastic - Beanstalk deploys the named application version to the environment. - If no such application version is found, returns an - InvalidParameterValue error. - - :type template_name: string - :param template_name: If this parameter is specified, AWS Elastic - Beanstalk deploys this configuration template to the environment. - If no such configuration template is found, AWS Elastic Beanstalk - returns an InvalidParameterValue error. - - :type description: string - :param description: If this parameter is specified, AWS Elastic - Beanstalk updates the description of this environment. - - :type option_settings: list - :param option_settings: If specified, AWS Elastic Beanstalk updates the - configuration set associated with the running environment and sets - the specified configuration options to the requested value. - - :type options_to_remove: list - :param options_to_remove: A list of custom user-defined configuration - options to remove from the configuration set for this environment. - - :type tier_name: string - :param tier_name: The name of the tier. Valid values are - "WebServer" and "Worker". Defaults to "WebServer". - The ``tier_name`` and a ``tier_type`` parameters are - related and the values provided must be valid. - The possible combinations are: - - * "WebServer" and "Standard" (the default) - * "Worker" and "SQS/HTTP" - - :type tier_type: string - :param tier_type: The type of the tier. Valid values are - "Standard" if ``tier_name`` is "WebServer" and "SQS/HTTP" - if ``tier_name`` is "Worker". Defaults to "Standard". - - :type tier_version: string - :type tier_version: The version of the tier. Valid values - currently are "1.0". Defaults to "1.0". - - :raises: InsufficientPrivilegesException - """ - params = {} - if environment_id: - params['EnvironmentId'] = environment_id - if environment_name: - params['EnvironmentName'] = environment_name - if version_label: - params['VersionLabel'] = version_label - if template_name: - params['TemplateName'] = template_name - if description: - params['Description'] = description - if option_settings: - self._build_list_params(params, option_settings, - 'OptionSettings.member', - ('Namespace', 'OptionName', 'Value')) - if options_to_remove: - self.build_list_params(params, options_to_remove, - 'OptionsToRemove.member') - if tier_name and tier_type and tier_version: - params['Tier.Name'] = tier_name - params['Tier.Type'] = tier_type - params['Tier.Version'] = tier_version - return self._get_response('UpdateEnvironment', params) - - def validate_configuration_settings(self, application_name, - option_settings, template_name=None, - environment_name=None): - """ - Takes a set of configuration settings and either a - configuration template or environment, and determines whether - those values are valid. This action returns a list of messages - indicating any errors or warnings associated with the selection - of option values. - - :type application_name: string - :param application_name: The name of the application that the - configuration template or environment belongs to. - - :type template_name: string - :param template_name: The name of the configuration template to - validate the settings against. Condition: You cannot specify both - this and an environment name. - - :type environment_name: string - :param environment_name: The name of the environment to validate the - settings against. Condition: You cannot specify both this and a - configuration template name. - - :type option_settings: list - :param option_settings: A list of the options and desired values to - evaluate. - - :raises: InsufficientPrivilegesException - """ - params = {'ApplicationName': application_name} - self._build_list_params(params, option_settings, - 'OptionSettings.member', - ('Namespace', 'OptionName', 'Value')) - if template_name: - params['TemplateName'] = template_name - if environment_name: - params['EnvironmentName'] = environment_name - return self._get_response('ValidateConfigurationSettings', params) - - def _build_list_params(self, params, user_values, prefix, tuple_names): - # For params such as the ConfigurationOptionSettings, - # they can specify a list of tuples where each tuple maps to a specific - # arg. For example: - # user_values = [('foo', 'bar', 'baz'] - # prefix=MyOption.member - # tuple_names=('One', 'Two', 'Three') - # would result in: - # MyOption.member.1.One = foo - # MyOption.member.1.Two = bar - # MyOption.member.1.Three = baz - for i, user_value in enumerate(user_values, 1): - current_prefix = '%s.%s' % (prefix, i) - for key, value in zip(tuple_names, user_value): - full_key = '%s.%s' % (current_prefix, key) - params[full_key] = value diff --git a/awx/lib/site-packages/boto/beanstalk/response.py b/awx/lib/site-packages/boto/beanstalk/response.py deleted file mode 100644 index 8128ba1fed..0000000000 --- a/awx/lib/site-packages/boto/beanstalk/response.py +++ /dev/null @@ -1,704 +0,0 @@ -"""Classify responses from layer1 and strict type values.""" -from datetime import datetime -from boto.compat import six - - -class BaseObject(object): - - def __repr__(self): - result = self.__class__.__name__ + '{ ' - counter = 0 - for key, value in six.iteritems(self.__dict__): - # first iteration no comma - counter += 1 - if counter > 1: - result += ', ' - result += key + ': ' - result += self._repr_by_type(value) - result += ' }' - return result - - def _repr_by_type(self, value): - # Everything is either a 'Response', 'list', or 'None/str/int/bool'. - result = '' - if isinstance(value, Response): - result += value.__repr__() - elif isinstance(value, list): - result += self._repr_list(value) - else: - result += str(value) - return result - - def _repr_list(self, array): - result = '[' - for value in array: - result += ' ' + self._repr_by_type(value) + ',' - # Check for trailing comma with a space. - if len(result) > 1: - result = result[:-1] + ' ' - result += ']' - return result - - -class Response(BaseObject): - def __init__(self, response): - super(Response, self).__init__() - - if response['ResponseMetadata']: - self.response_metadata = ResponseMetadata(response['ResponseMetadata']) - else: - self.response_metadata = None - - -class ResponseMetadata(BaseObject): - def __init__(self, response): - super(ResponseMetadata, self).__init__() - - self.request_id = str(response['RequestId']) - - -class ApplicationDescription(BaseObject): - def __init__(self, response): - super(ApplicationDescription, self).__init__() - - self.application_name = str(response['ApplicationName']) - self.configuration_templates = [] - if response['ConfigurationTemplates']: - for member in response['ConfigurationTemplates']: - configuration_template = str(member) - self.configuration_templates.append(configuration_template) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.description = str(response['Description']) - self.versions = [] - if response['Versions']: - for member in response['Versions']: - version = str(member) - self.versions.append(version) - - -class ApplicationVersionDescription(BaseObject): - def __init__(self, response): - super(ApplicationVersionDescription, self).__init__() - - self.application_name = str(response['ApplicationName']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.description = str(response['Description']) - if response['SourceBundle']: - self.source_bundle = S3Location(response['SourceBundle']) - else: - self.source_bundle = None - self.version_label = str(response['VersionLabel']) - - -class AutoScalingGroup(BaseObject): - def __init__(self, response): - super(AutoScalingGroup, self).__init__() - - self.name = str(response['Name']) - - -class ConfigurationOptionDescription(BaseObject): - def __init__(self, response): - super(ConfigurationOptionDescription, self).__init__() - - self.change_severity = str(response['ChangeSeverity']) - self.default_value = str(response['DefaultValue']) - self.max_length = int(response['MaxLength']) if response['MaxLength'] else None - self.max_value = int(response['MaxValue']) if response['MaxValue'] else None - self.min_value = int(response['MinValue']) if response['MinValue'] else None - self.name = str(response['Name']) - self.namespace = str(response['Namespace']) - if response['Regex']: - self.regex = OptionRestrictionRegex(response['Regex']) - else: - self.regex = None - self.user_defined = str(response['UserDefined']) - self.value_options = [] - if response['ValueOptions']: - for member in response['ValueOptions']: - value_option = str(member) - self.value_options.append(value_option) - self.value_type = str(response['ValueType']) - - -class ConfigurationOptionSetting(BaseObject): - def __init__(self, response): - super(ConfigurationOptionSetting, self).__init__() - - self.namespace = str(response['Namespace']) - self.option_name = str(response['OptionName']) - self.value = str(response['Value']) - - -class ConfigurationSettingsDescription(BaseObject): - def __init__(self, response): - super(ConfigurationSettingsDescription, self).__init__() - - self.application_name = str(response['ApplicationName']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.deployment_status = str(response['DeploymentStatus']) - self.description = str(response['Description']) - self.environment_name = str(response['EnvironmentName']) - self.option_settings = [] - if response['OptionSettings']: - for member in response['OptionSettings']: - option_setting = ConfigurationOptionSetting(member) - self.option_settings.append(option_setting) - self.solution_stack_name = str(response['SolutionStackName']) - self.template_name = str(response['TemplateName']) - - -class EnvironmentDescription(BaseObject): - def __init__(self, response): - super(EnvironmentDescription, self).__init__() - - self.application_name = str(response['ApplicationName']) - self.cname = str(response['CNAME']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.description = str(response['Description']) - self.endpoint_url = str(response['EndpointURL']) - self.environment_id = str(response['EnvironmentId']) - self.environment_name = str(response['EnvironmentName']) - self.health = str(response['Health']) - if response['Resources']: - self.resources = EnvironmentResourcesDescription(response['Resources']) - else: - self.resources = None - self.solution_stack_name = str(response['SolutionStackName']) - self.status = str(response['Status']) - self.template_name = str(response['TemplateName']) - self.version_label = str(response['VersionLabel']) - - -class EnvironmentInfoDescription(BaseObject): - def __init__(self, response): - super(EnvironmentInfoDescription, self).__init__() - - self.ec2_instance_id = str(response['Ec2InstanceId']) - self.info_type = str(response['InfoType']) - self.message = str(response['Message']) - self.sample_timestamp = datetime.fromtimestamp(response['SampleTimestamp']) - - -class EnvironmentResourceDescription(BaseObject): - def __init__(self, response): - super(EnvironmentResourceDescription, self).__init__() - - self.auto_scaling_groups = [] - if response['AutoScalingGroups']: - for member in response['AutoScalingGroups']: - auto_scaling_group = AutoScalingGroup(member) - self.auto_scaling_groups.append(auto_scaling_group) - self.environment_name = str(response['EnvironmentName']) - self.instances = [] - if response['Instances']: - for member in response['Instances']: - instance = Instance(member) - self.instances.append(instance) - self.launch_configurations = [] - if response['LaunchConfigurations']: - for member in response['LaunchConfigurations']: - launch_configuration = LaunchConfiguration(member) - self.launch_configurations.append(launch_configuration) - self.load_balancers = [] - if response['LoadBalancers']: - for member in response['LoadBalancers']: - load_balancer = LoadBalancer(member) - self.load_balancers.append(load_balancer) - self.triggers = [] - if response['Triggers']: - for member in response['Triggers']: - trigger = Trigger(member) - self.triggers.append(trigger) - - -class EnvironmentResourcesDescription(BaseObject): - def __init__(self, response): - super(EnvironmentResourcesDescription, self).__init__() - - if response['LoadBalancer']: - self.load_balancer = LoadBalancerDescription(response['LoadBalancer']) - else: - self.load_balancer = None - - -class EventDescription(BaseObject): - def __init__(self, response): - super(EventDescription, self).__init__() - - self.application_name = str(response['ApplicationName']) - self.environment_name = str(response['EnvironmentName']) - self.event_date = datetime.fromtimestamp(response['EventDate']) - self.message = str(response['Message']) - self.request_id = str(response['RequestId']) - self.severity = str(response['Severity']) - self.template_name = str(response['TemplateName']) - self.version_label = str(response['VersionLabel']) - - -class Instance(BaseObject): - def __init__(self, response): - super(Instance, self).__init__() - - self.id = str(response['Id']) - - -class LaunchConfiguration(BaseObject): - def __init__(self, response): - super(LaunchConfiguration, self).__init__() - - self.name = str(response['Name']) - - -class Listener(BaseObject): - def __init__(self, response): - super(Listener, self).__init__() - - self.port = int(response['Port']) if response['Port'] else None - self.protocol = str(response['Protocol']) - - -class LoadBalancer(BaseObject): - def __init__(self, response): - super(LoadBalancer, self).__init__() - - self.name = str(response['Name']) - - -class LoadBalancerDescription(BaseObject): - def __init__(self, response): - super(LoadBalancerDescription, self).__init__() - - self.domain = str(response['Domain']) - self.listeners = [] - if response['Listeners']: - for member in response['Listeners']: - listener = Listener(member) - self.listeners.append(listener) - self.load_balancer_name = str(response['LoadBalancerName']) - - -class OptionRestrictionRegex(BaseObject): - def __init__(self, response): - super(OptionRestrictionRegex, self).__init__() - - self.label = response['Label'] - self.pattern = response['Pattern'] - - -class SolutionStackDescription(BaseObject): - def __init__(self, response): - super(SolutionStackDescription, self).__init__() - - self.permitted_file_types = [] - if response['PermittedFileTypes']: - for member in response['PermittedFileTypes']: - permitted_file_type = str(member) - self.permitted_file_types.append(permitted_file_type) - self.solution_stack_name = str(response['SolutionStackName']) - - -class S3Location(BaseObject): - def __init__(self, response): - super(S3Location, self).__init__() - - self.s3_bucket = str(response['S3Bucket']) - self.s3_key = str(response['S3Key']) - - -class Trigger(BaseObject): - def __init__(self, response): - super(Trigger, self).__init__() - - self.name = str(response['Name']) - - -class ValidationMessage(BaseObject): - def __init__(self, response): - super(ValidationMessage, self).__init__() - - self.message = str(response['Message']) - self.namespace = str(response['Namespace']) - self.option_name = str(response['OptionName']) - self.severity = str(response['Severity']) - - -# These are the response objects layer2 uses, one for each layer1 api call. -class CheckDNSAvailabilityResponse(Response): - def __init__(self, response): - response = response['CheckDNSAvailabilityResponse'] - super(CheckDNSAvailabilityResponse, self).__init__(response) - - response = response['CheckDNSAvailabilityResult'] - self.fully_qualified_cname = str(response['FullyQualifiedCNAME']) - self.available = bool(response['Available']) - - -# Our naming convension produces this class name but api names it with more -# capitals. -class CheckDnsAvailabilityResponse(CheckDNSAvailabilityResponse): pass - - -class CreateApplicationResponse(Response): - def __init__(self, response): - response = response['CreateApplicationResponse'] - super(CreateApplicationResponse, self).__init__(response) - - response = response['CreateApplicationResult'] - if response['Application']: - self.application = ApplicationDescription(response['Application']) - else: - self.application = None - - -class CreateApplicationVersionResponse(Response): - def __init__(self, response): - response = response['CreateApplicationVersionResponse'] - super(CreateApplicationVersionResponse, self).__init__(response) - - response = response['CreateApplicationVersionResult'] - if response['ApplicationVersion']: - self.application_version = ApplicationVersionDescription(response['ApplicationVersion']) - else: - self.application_version = None - - -class CreateConfigurationTemplateResponse(Response): - def __init__(self, response): - response = response['CreateConfigurationTemplateResponse'] - super(CreateConfigurationTemplateResponse, self).__init__(response) - - response = response['CreateConfigurationTemplateResult'] - self.application_name = str(response['ApplicationName']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.deployment_status = str(response['DeploymentStatus']) - self.description = str(response['Description']) - self.environment_name = str(response['EnvironmentName']) - self.option_settings = [] - if response['OptionSettings']: - for member in response['OptionSettings']: - option_setting = ConfigurationOptionSetting(member) - self.option_settings.append(option_setting) - self.solution_stack_name = str(response['SolutionStackName']) - self.template_name = str(response['TemplateName']) - - -class CreateEnvironmentResponse(Response): - def __init__(self, response): - response = response['CreateEnvironmentResponse'] - super(CreateEnvironmentResponse, self).__init__(response) - - response = response['CreateEnvironmentResult'] - self.application_name = str(response['ApplicationName']) - self.cname = str(response['CNAME']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.description = str(response['Description']) - self.endpoint_url = str(response['EndpointURL']) - self.environment_id = str(response['EnvironmentId']) - self.environment_name = str(response['EnvironmentName']) - self.health = str(response['Health']) - if response['Resources']: - self.resources = EnvironmentResourcesDescription(response['Resources']) - else: - self.resources = None - self.solution_stack_name = str(response['SolutionStackName']) - self.status = str(response['Status']) - self.template_name = str(response['TemplateName']) - self.version_label = str(response['VersionLabel']) - - -class CreateStorageLocationResponse(Response): - def __init__(self, response): - response = response['CreateStorageLocationResponse'] - super(CreateStorageLocationResponse, self).__init__(response) - - response = response['CreateStorageLocationResult'] - self.s3_bucket = str(response['S3Bucket']) - - -class DeleteApplicationResponse(Response): - def __init__(self, response): - response = response['DeleteApplicationResponse'] - super(DeleteApplicationResponse, self).__init__(response) - - -class DeleteApplicationVersionResponse(Response): - def __init__(self, response): - response = response['DeleteApplicationVersionResponse'] - super(DeleteApplicationVersionResponse, self).__init__(response) - - -class DeleteConfigurationTemplateResponse(Response): - def __init__(self, response): - response = response['DeleteConfigurationTemplateResponse'] - super(DeleteConfigurationTemplateResponse, self).__init__(response) - - -class DeleteEnvironmentConfigurationResponse(Response): - def __init__(self, response): - response = response['DeleteEnvironmentConfigurationResponse'] - super(DeleteEnvironmentConfigurationResponse, self).__init__(response) - - -class DescribeApplicationVersionsResponse(Response): - def __init__(self, response): - response = response['DescribeApplicationVersionsResponse'] - super(DescribeApplicationVersionsResponse, self).__init__(response) - - response = response['DescribeApplicationVersionsResult'] - self.application_versions = [] - if response['ApplicationVersions']: - for member in response['ApplicationVersions']: - application_version = ApplicationVersionDescription(member) - self.application_versions.append(application_version) - - -class DescribeApplicationsResponse(Response): - def __init__(self, response): - response = response['DescribeApplicationsResponse'] - super(DescribeApplicationsResponse, self).__init__(response) - - response = response['DescribeApplicationsResult'] - self.applications = [] - if response['Applications']: - for member in response['Applications']: - application = ApplicationDescription(member) - self.applications.append(application) - - -class DescribeConfigurationOptionsResponse(Response): - def __init__(self, response): - response = response['DescribeConfigurationOptionsResponse'] - super(DescribeConfigurationOptionsResponse, self).__init__(response) - - response = response['DescribeConfigurationOptionsResult'] - self.options = [] - if response['Options']: - for member in response['Options']: - option = ConfigurationOptionDescription(member) - self.options.append(option) - self.solution_stack_name = str(response['SolutionStackName']) - - -class DescribeConfigurationSettingsResponse(Response): - def __init__(self, response): - response = response['DescribeConfigurationSettingsResponse'] - super(DescribeConfigurationSettingsResponse, self).__init__(response) - - response = response['DescribeConfigurationSettingsResult'] - self.configuration_settings = [] - if response['ConfigurationSettings']: - for member in response['ConfigurationSettings']: - configuration_setting = ConfigurationSettingsDescription(member) - self.configuration_settings.append(configuration_setting) - - -class DescribeEnvironmentResourcesResponse(Response): - def __init__(self, response): - response = response['DescribeEnvironmentResourcesResponse'] - super(DescribeEnvironmentResourcesResponse, self).__init__(response) - - response = response['DescribeEnvironmentResourcesResult'] - if response['EnvironmentResources']: - self.environment_resources = EnvironmentResourceDescription(response['EnvironmentResources']) - else: - self.environment_resources = None - - -class DescribeEnvironmentsResponse(Response): - def __init__(self, response): - response = response['DescribeEnvironmentsResponse'] - super(DescribeEnvironmentsResponse, self).__init__(response) - - response = response['DescribeEnvironmentsResult'] - self.environments = [] - if response['Environments']: - for member in response['Environments']: - environment = EnvironmentDescription(member) - self.environments.append(environment) - - -class DescribeEventsResponse(Response): - def __init__(self, response): - response = response['DescribeEventsResponse'] - super(DescribeEventsResponse, self).__init__(response) - - response = response['DescribeEventsResult'] - self.events = [] - if response['Events']: - for member in response['Events']: - event = EventDescription(member) - self.events.append(event) - self.next_tokent = str(response['NextToken']) - - -class ListAvailableSolutionStacksResponse(Response): - def __init__(self, response): - response = response['ListAvailableSolutionStacksResponse'] - super(ListAvailableSolutionStacksResponse, self).__init__(response) - - response = response['ListAvailableSolutionStacksResult'] - self.solution_stack_details = [] - if response['SolutionStackDetails']: - for member in response['SolutionStackDetails']: - solution_stack_detail = SolutionStackDescription(member) - self.solution_stack_details.append(solution_stack_detail) - self.solution_stacks = [] - if response['SolutionStacks']: - for member in response['SolutionStacks']: - solution_stack = str(member) - self.solution_stacks.append(solution_stack) - - -class RebuildEnvironmentResponse(Response): - def __init__(self, response): - response = response['RebuildEnvironmentResponse'] - super(RebuildEnvironmentResponse, self).__init__(response) - - -class RequestEnvironmentInfoResponse(Response): - def __init__(self, response): - response = response['RequestEnvironmentInfoResponse'] - super(RequestEnvironmentInfoResponse, self).__init__(response) - - -class RestartAppServerResponse(Response): - def __init__(self, response): - response = response['RestartAppServerResponse'] - super(RestartAppServerResponse, self).__init__(response) - - -class RetrieveEnvironmentInfoResponse(Response): - def __init__(self, response): - response = response['RetrieveEnvironmentInfoResponse'] - super(RetrieveEnvironmentInfoResponse, self).__init__(response) - - response = response['RetrieveEnvironmentInfoResult'] - self.environment_info = [] - if response['EnvironmentInfo']: - for member in response['EnvironmentInfo']: - environment_info = EnvironmentInfoDescription(member) - self.environment_info.append(environment_info) - - -class SwapEnvironmentCNAMEsResponse(Response): - def __init__(self, response): - response = response['SwapEnvironmentCNAMEsResponse'] - super(SwapEnvironmentCNAMEsResponse, self).__init__(response) - - -class SwapEnvironmentCnamesResponse(SwapEnvironmentCNAMEsResponse): pass - - -class TerminateEnvironmentResponse(Response): - def __init__(self, response): - response = response['TerminateEnvironmentResponse'] - super(TerminateEnvironmentResponse, self).__init__(response) - - response = response['TerminateEnvironmentResult'] - self.application_name = str(response['ApplicationName']) - self.cname = str(response['CNAME']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.description = str(response['Description']) - self.endpoint_url = str(response['EndpointURL']) - self.environment_id = str(response['EnvironmentId']) - self.environment_name = str(response['EnvironmentName']) - self.health = str(response['Health']) - if response['Resources']: - self.resources = EnvironmentResourcesDescription(response['Resources']) - else: - self.resources = None - self.solution_stack_name = str(response['SolutionStackName']) - self.status = str(response['Status']) - self.template_name = str(response['TemplateName']) - self.version_label = str(response['VersionLabel']) - - -class UpdateApplicationResponse(Response): - def __init__(self, response): - response = response['UpdateApplicationResponse'] - super(UpdateApplicationResponse, self).__init__(response) - - response = response['UpdateApplicationResult'] - if response['Application']: - self.application = ApplicationDescription(response['Application']) - else: - self.application = None - - -class UpdateApplicationVersionResponse(Response): - def __init__(self, response): - response = response['UpdateApplicationVersionResponse'] - super(UpdateApplicationVersionResponse, self).__init__(response) - - response = response['UpdateApplicationVersionResult'] - if response['ApplicationVersion']: - self.application_version = ApplicationVersionDescription(response['ApplicationVersion']) - else: - self.application_version = None - - -class UpdateConfigurationTemplateResponse(Response): - def __init__(self, response): - response = response['UpdateConfigurationTemplateResponse'] - super(UpdateConfigurationTemplateResponse, self).__init__(response) - - response = response['UpdateConfigurationTemplateResult'] - self.application_name = str(response['ApplicationName']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.deployment_status = str(response['DeploymentStatus']) - self.description = str(response['Description']) - self.environment_name = str(response['EnvironmentName']) - self.option_settings = [] - if response['OptionSettings']: - for member in response['OptionSettings']: - option_setting = ConfigurationOptionSetting(member) - self.option_settings.append(option_setting) - self.solution_stack_name = str(response['SolutionStackName']) - self.template_name = str(response['TemplateName']) - - -class UpdateEnvironmentResponse(Response): - def __init__(self, response): - response = response['UpdateEnvironmentResponse'] - super(UpdateEnvironmentResponse, self).__init__(response) - - response = response['UpdateEnvironmentResult'] - self.application_name = str(response['ApplicationName']) - self.cname = str(response['CNAME']) - self.date_created = datetime.fromtimestamp(response['DateCreated']) - self.date_updated = datetime.fromtimestamp(response['DateUpdated']) - self.description = str(response['Description']) - self.endpoint_url = str(response['EndpointURL']) - self.environment_id = str(response['EnvironmentId']) - self.environment_name = str(response['EnvironmentName']) - self.health = str(response['Health']) - if response['Resources']: - self.resources = EnvironmentResourcesDescription(response['Resources']) - else: - self.resources = None - self.solution_stack_name = str(response['SolutionStackName']) - self.status = str(response['Status']) - self.template_name = str(response['TemplateName']) - self.version_label = str(response['VersionLabel']) - - -class ValidateConfigurationSettingsResponse(Response): - def __init__(self, response): - response = response['ValidateConfigurationSettingsResponse'] - super(ValidateConfigurationSettingsResponse, self).__init__(response) - - response = response['ValidateConfigurationSettingsResult'] - self.messages = [] - if response['Messages']: - for member in response['Messages']: - message = ValidationMessage(member) - self.messages.append(message) diff --git a/awx/lib/site-packages/boto/beanstalk/wrapper.py b/awx/lib/site-packages/boto/beanstalk/wrapper.py deleted file mode 100644 index eea1124a9e..0000000000 --- a/awx/lib/site-packages/boto/beanstalk/wrapper.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Wraps layer1 api methods and converts layer1 dict responses to objects.""" -from boto.beanstalk.layer1 import Layer1 -import boto.beanstalk.response -from boto.exception import BotoServerError -import boto.beanstalk.exception as exception - - -def beanstalk_wrapper(func, name): - def _wrapped_low_level_api(*args, **kwargs): - try: - response = func(*args, **kwargs) - except BotoServerError as e: - raise exception.simple(e) - # Turn 'this_is_a_function_name' into 'ThisIsAFunctionNameResponse'. - cls_name = ''.join([part.capitalize() for part in name.split('_')]) + 'Response' - cls = getattr(boto.beanstalk.response, cls_name) - return cls(response) - return _wrapped_low_level_api - - -class Layer1Wrapper(object): - def __init__(self, *args, **kwargs): - self.api = Layer1(*args, **kwargs) - - def __getattr__(self, name): - try: - return beanstalk_wrapper(getattr(self.api, name), name) - except AttributeError: - raise AttributeError("%s has no attribute %r" % (self, name)) diff --git a/awx/lib/site-packages/boto/cacerts/__init__.py b/awx/lib/site-packages/boto/cacerts/__init__.py deleted file mode 100644 index 1b2dec79e7..0000000000 --- a/awx/lib/site-packages/boto/cacerts/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2010 Google Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# diff --git a/awx/lib/site-packages/boto/cacerts/cacerts.txt b/awx/lib/site-packages/boto/cacerts/cacerts.txt deleted file mode 100644 index 3cf3f26f97..0000000000 --- a/awx/lib/site-packages/boto/cacerts/cacerts.txt +++ /dev/null @@ -1,3869 +0,0 @@ -## -## boto/cacerts/cacerts.txt -- Bundle of CA Root Certificates -## -## Certificate data from Mozilla downloaded on: Wed Aug 20 03:12:04 2014 -## -## This is a bundle of X.509 certificates of public Certificate Authorities -## (CA). These were automatically extracted from Mozilla's root certificates -## file (certdata.txt). This file can be found in the mozilla source tree: -## http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt -## -## It contains the certificates in PEM format and therefore -## can be directly used with curl / libcurl / php_curl, or with -## an Apache+mod_ssl webserver for SSL client authentication. -## Just configure this file as the SSLCACertificateFile. -## -## Conversion done with mk-ca-bundle.pl verison 1.22. -## SHA1: bf2c15b3019e696660321d2227d942936dc50aa7 -## - - -GTE CyberTrust Global Root -========================== ------BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg -Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG -A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz -MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL -Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 -IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u -sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql -HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID -AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW -M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF -NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ ------END CERTIFICATE----- - -Thawte Server CA -================ ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs -dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE -AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j -b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV -BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u -c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG -A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 -ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl -/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 -1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR -MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J -GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ -GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- - -Thawte Premium Server CA -======================== ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs -dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE -AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl -ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT -AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU -VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 -aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ -cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 -aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh -Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ -qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm -SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf -8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t -UCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- - -Equifax Secure CA -================= ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE -ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 -MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT -B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB -nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR -fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW -8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG -A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE -CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG -A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS -spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB -Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 -zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB -BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 -70+sB3c4 ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority -======================================================= ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx -FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow -XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz -IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 -f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol -hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA -TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah -WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf -Tqj/ZA1k ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority - G2 -============================================================ ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz -dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT -MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz -dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO -FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 -lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB -MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT -1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD -Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 ------END CERTIFICATE----- - -GlobalSign Root CA -================== ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx -GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds -b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV -BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD -VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa -DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc -THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb -Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP -c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX -gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF -AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj -Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG -j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH -hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC -X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- - -GlobalSign Root CA - R2 -======================= ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv -YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh -bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT -aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln -bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 -ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp -s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN -S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL -TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C -ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i -YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN -BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp -9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu -01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 -9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- - -ValiCert Class 1 VA -=================== ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp -b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh -bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy -MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 -d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg -UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 -LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi -GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm -DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG -lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX -icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP -Orf1LXLI ------END CERTIFICATE----- - -ValiCert Class 2 VA -=================== ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp -b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh -bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw -MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 -d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg -UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 -LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC -CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf -ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ -SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV -UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8 -W9ViH0Pd ------END CERTIFICATE----- - -RSA Root Certificate 1 -====================== ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp -b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh -bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw -MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 -d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg -UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 -LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td -3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H -BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs -3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF -V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r -on+jjBXu ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy -dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 -EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc -cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw -EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj -055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA -ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f -j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 -xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa -t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- - -Verisign Class 4 Public Primary Certification Authority - G3 -============================================================ ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy -dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS -tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM -8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW -Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX -Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA -j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt -mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd -RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG -UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- - -Entrust.net Secure Server CA -============================ ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV -BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg -cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl -ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG -A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi -eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p -dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ -aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5 -gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw -ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw -CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l -dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw -NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow -HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA -BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN -Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9 -n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= ------END CERTIFICATE----- - -Entrust.net Premium 2048 Secure Server CA -========================================= ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u -ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp -bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV -BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx -NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 -d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl -MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u -ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL -Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr -hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW -nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi -VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ -KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy -T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT -J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e -nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= ------END CERTIFICATE----- - -Baltimore CyberTrust Root -========================= ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE -ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li -ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC -SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs -dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME -uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB -UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C -G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 -XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr -l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI -VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB -BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh -cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 -hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa -Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H -RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- - -Equifax Secure Global eBusiness CA -================================== ------BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp -bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx -HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds -b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV -PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN -qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn -hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j -BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs -MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN -I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY -NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV ------END CERTIFICATE----- - -Equifax Secure eBusiness CA 1 -============================= ------BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB -LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE -ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz -IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ -1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a -IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk -MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW -Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF -AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 -lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ -KpYrtWKmpj29f5JZzVoqgrI3eQ== ------END CERTIFICATE----- - -AddTrust Low-Value Services Root -================================ ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU -cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw -CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO -ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 -54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr -oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 -Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui -GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w -HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD -AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT -RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw -HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt -ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph -iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr -mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj -ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= ------END CERTIFICATE----- - -AddTrust External Root -====================== ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD -VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw -NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU -cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg -Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 -+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw -Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo -aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy -2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 -7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL -VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk -VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB -IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl -j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 -e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u -G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- - -AddTrust Public Services Root -============================= ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU -cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ -BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l -dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu -nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i -d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG -Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw -HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G -A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G -A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 -JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL -+YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 -Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H -EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= ------END CERTIFICATE----- - -AddTrust Qualified Certificates Root -==================================== ------BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU -cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx -CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ -IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx -64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 -KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o -L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR -wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU -MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE -BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y -azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG -GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze -RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB -iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= ------END CERTIFICATE----- - -Entrust Root Certification Authority -==================================== ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV -BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw -b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG -A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 -MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu -MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu -Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v -dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz -A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww -Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 -j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN -rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw -DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 -MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH -hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM -Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa -v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS -W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 -tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -RSA Security 2048 v3 -==================== ------BEGIN CERTIFICATE----- -MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK -ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy -MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb -BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 -Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb -WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH -KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP -+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E -FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY -v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj -0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj -VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 -nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA -pKnXwiJPZ9d37CAFYd4= ------END CERTIFICATE----- - -GeoTrust Global CA -================== ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw -MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j -LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo -BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet -8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc -T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU -vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk -DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q -zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 -d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 -mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p -XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm -Mw== ------END CERTIFICATE----- - -GeoTrust Global CA 2 -==================== ------BEGIN CERTIFICATE----- -MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN -R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw -MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j -LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ -NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k -LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA -Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b -HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH -K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 -srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh -ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL -OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC -x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF -H4z1Ir+rzoPz4iIprn2DQKi6bA== ------END CERTIFICATE----- - -GeoTrust Universal CA -===================== ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN -R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 -MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu -Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t -JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e -RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs -7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d -8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V -qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga -Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB -Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu -KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 -ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 -XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB -hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 -qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL -oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK -xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF -KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 -DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK -xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU -p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI -P/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- - -GeoTrust Universal CA 2 -======================= ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN -R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 -MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg -SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 -DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 -j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q -JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a -QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 -WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP -20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn -ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC -SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG -8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 -+/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E -BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ -4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ -mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq -A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg -Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP -pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d -FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp -gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm -X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- - -America Online Root Certification Authority 1 -============================================= ------BEGIN CERTIFICATE----- -MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG -A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg -T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG -v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z -DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh -sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP -8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T -AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z -o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf -GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF -VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft -3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g -Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds -sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 ------END CERTIFICATE----- - -America Online Root Certification Authority 2 -============================================= ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT -QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG -A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg -T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en -fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 -f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO -qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN -RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 -gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn -6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid -FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 -Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj -B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op -aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY -T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p -+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg -JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy -zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO -ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh -1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf -GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff -Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP -cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= ------END CERTIFICATE----- - -Visa eCommerce Root -=================== ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG -EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug -QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 -WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm -VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL -F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b -RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 -TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI -/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs -GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG -MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc -CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW -YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz -zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu -YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- - -Certum Root CA -============== ------BEGIN CERTIFICATE----- -MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK -ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla -Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u -by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x -wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL -kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ -89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K -Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P -NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq -hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ -GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg -GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ -0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS -qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== ------END CERTIFICATE----- - -Comodo AAA Services root -======================== ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw -MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl -c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV -BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG -C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs -i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW -Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH -Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK -Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f -BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl -cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz -LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm -7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z -8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C -12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- - -Comodo Secure Services root -=========================== ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw -MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu -Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi -BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP -9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc -rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC -oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V -p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E -FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w -gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj -YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm -aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm -4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL -DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw -pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H -RR3B7Hzs/Sk= ------END CERTIFICATE----- - -Comodo Trusted Services root -============================ ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw -MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h -bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw -IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 -3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y -/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 -juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS -ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud -DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp -ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl -cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw -uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA -BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l -R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O -9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- - -QuoVadis Root CA -================ ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE -ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz -MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp -cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD -EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk -J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL -F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL -YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen -AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w -PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y -ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 -MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj -YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs -ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW -Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu -BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw -FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 -tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo -fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul -LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x -gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi -5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi -5nrQNiOKSnQ2+Q== ------END CERTIFICATE----- - -QuoVadis Root CA 2 -================== ------BEGIN CERTIFICATE----- -MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT -EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx -ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 -XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk -lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB -lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy -lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt -66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn -wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh -D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy -BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie -J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud -DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU -a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT -ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv -Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 -UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm -VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK -+JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW -IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 -WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X -f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II -4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 -VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u ------END CERTIFICATE----- - -QuoVadis Root CA 3 -================== ------BEGIN CERTIFICATE----- -MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT -EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx -OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg -DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij -KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K -DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv -BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp -p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 -nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX -MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM -Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz -uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT -BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj -YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 -aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB -BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD -VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 -ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE -AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV -qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s -hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z -POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 -Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp -8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC -bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu -g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p -vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr -qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= ------END CERTIFICATE----- - -Security Communication Root CA -============================== ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw -8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM -DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX -5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd -DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 -JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw -DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g -0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a -mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ -s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ -6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi -FL39vmwLAw== ------END CERTIFICATE----- - -Sonera Class 2 Root CA -====================== ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG -U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw -NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh -IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 -/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT -dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG -f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P -tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH -nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT -XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt -0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI -cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph -Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx -EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH -llpwrN9M ------END CERTIFICATE----- - -Staat der Nederlanden Root CA -============================= ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE -ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g -Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w -HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh -bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt -vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P -jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca -C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth -vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 -22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV -HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v -dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN -BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR -EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw -MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y -nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- - -TDC Internet Root CA -==================== ------BEGIN CERTIFICATE----- -MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE -ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx -NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu -ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j -xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL -znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc -5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6 -otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI -AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM -VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM -MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC -AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe -UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G -CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m -gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ -2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb -O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU -Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l ------END CERTIFICATE----- - -UTN DATACorp SGC Root CA -======================== ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ -BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa -MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w -HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy -dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys -raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo -wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA -9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv -33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud -DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 -BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD -LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 -DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 -I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx -EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP -DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- - -UTN USERFirst Hardware Root CA -============================== ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd -BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx -OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 -eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz -ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI -wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd -tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 -i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf -Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw -gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF -lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF -UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF -BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW -XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 -lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn -iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 -nfhmqA== ------END CERTIFICATE----- - -Camerfirma Chambers of Commerce Root -==================================== ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe -QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i -ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx -NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp -cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn -MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC -AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU -xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH -NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW -DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV -d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud -EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v -cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P -AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh -bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD -VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz -aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi -fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD -L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN -UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n -ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 -erfutGWaIZDgqtCYvDi1czyL+Nw= ------END CERTIFICATE----- - -Camerfirma Global Chambersign Root -================================== ------BEGIN CERTIFICATE----- -MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe -QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i -ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx -NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt -YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg -MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw -ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J -1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O -by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl -6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c -8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ -BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j -aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B -Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj -aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y -ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh -bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA -PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y -gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ -PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 -IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes -t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== ------END CERTIFICATE----- - -NetLock Notary (Class A) Root -============================= ------BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI -EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 -dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j -ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX -DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH -EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD -VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz -cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM -D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ -z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC -/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 -tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 -4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG -A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC -Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv -bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn -LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 -ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz -IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh -IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu -b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh -bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg -Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp -bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 -ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP -ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB -CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr -KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM -8CgHrTwXZoi1/baI ------END CERTIFICATE----- - -NetLock Business (Class B) Root -=============================== ------BEGIN CERTIFICATE----- -MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT -CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV -BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg -VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD -VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv -bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg -VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB -iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S -o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr -1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV -HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ -RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh -dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0 -ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv -c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg -YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh -c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz -Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA -bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl -IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2 -YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj -cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM -43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR -stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI ------END CERTIFICATE----- - -NetLock Express (Class C) Root -============================== ------BEGIN CERTIFICATE----- -MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT -CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV -BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD -KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ -BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 -dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j -ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z -W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63 -euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw -DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN -RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn -YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB -IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i -aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0 -ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs -ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo -dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y -emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k -IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ -UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg -YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2 -xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW -gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A== ------END CERTIFICATE----- - -XRamp Global CA Root -==================== ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE -BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj -dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx -HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg -U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu -IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx -foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE -zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs -AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry -xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud -EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap -oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC -AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc -/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n -nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz -8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- - -Go Daddy Class 2 CA -=================== ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY -VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG -A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g -RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD -ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv -2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 -qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j -YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY -vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O -BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o -atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu -MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG -A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim -PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt -I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI -Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b -vZ8= ------END CERTIFICATE----- - -Starfield Class 2 CA -==================== ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc -U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo -MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG -A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG -SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY -bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ -JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm -epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN -F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF -MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f -hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo -bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g -QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs -afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM -PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD -KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 -QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- - -StartCom Certification Authority -================================ ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN -U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu -ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 -NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk -LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg -U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y -o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ -Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d -eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt -2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z -6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ -osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ -untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc -UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT -37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj -YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH -AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw -Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg -U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 -LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl -cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh -cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT -dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC -AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh -3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm -vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk -fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 -fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ -EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl -1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ -lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro -g14= ------END CERTIFICATE----- - -Taiwan GRCA -=========== ------BEGIN CERTIFICATE----- -MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG -EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X -DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv -dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN -w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 -BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O -1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO -htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov -J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 -Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t -B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB -O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 -lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV -HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 -09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ -TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj -Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 -Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU -D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz -DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk -Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk -7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ -CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy -+fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS ------END CERTIFICATE----- - -Swisscom Root CA 1 -================== ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG -EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy -dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4 -MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln -aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC -IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM -MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF -NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe -AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC -b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn -7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN -cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp -WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5 -haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY -MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw -HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j -BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9 -MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn -jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ -MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H -VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl -vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl -OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3 -1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq -nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy -x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW -NY6E0F/6MBr1mmz0DlP5OlvRHA== ------END CERTIFICATE----- - -DigiCert Assured ID Root CA -=========================== ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw -IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx -MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL -ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO -9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy -UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW -/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy -oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf -GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF -66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq -hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc -EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn -SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i -8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- - -DigiCert Global Root CA -======================= ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw -HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw -MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 -dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn -TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 -BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H -4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y -7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB -o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm -8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF -BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr -EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt -tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 -UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- - -DigiCert High Assurance EV Root CA -================================== ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw -KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw -MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ -MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu -Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t -Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS -OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 -MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ -NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe -h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB -Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY -JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ -V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp -myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK -mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K ------END CERTIFICATE----- - -Certplus Class 2 Primary CA -=========================== ------BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE -BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN -OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy -dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR -5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ -Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO -YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e -e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME -CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ -YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t -L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD -P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R -TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ -7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW -//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 -l7+ijrRU ------END CERTIFICATE----- - -DST Root CA X3 -============== ------BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK -ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X -DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 -cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT -rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 -UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy -xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d -utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ -MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug -dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE -GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw -RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS -fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- - -DST ACES CA X6 -============== ------BEGIN CERTIFICATE----- -MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG -EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT -MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha -MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE -CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI -DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa -pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow -GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy -MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu -Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy -dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU -CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 -5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t -Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq -nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs -vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 -oKfN5XozNmr6mis= ------END CERTIFICATE----- - -TURKTRUST Certificate Services Provider Root 1 -============================================== ------BEGIN CERTIFICATE----- -MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP -MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 -acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx -MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg -U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB -TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC -aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX -yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i -Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ -8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 -W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME -BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 -sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE -q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy -B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY -nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H ------END CERTIFICATE----- - -TURKTRUST Certificate Services Provider Root 2 -============================================== ------BEGIN CERTIFICATE----- -MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP -MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg -QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN -MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr -dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G -A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls -acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe -LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI -x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g -QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr -5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB -AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt -Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 -Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ -hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P -9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 -UrbnBEI= ------END CERTIFICATE----- - -SwissSign Gold CA - G2 -====================== ------BEGIN CERTIFICATE----- -MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw -EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN -MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp -c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq -t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C -jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg -vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF -ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR -AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend -jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO -peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR -7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi -GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 -OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov -L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm -5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr -44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf -Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m -Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp -mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk -vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf -KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br -NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj -viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ ------END CERTIFICATE----- - -SwissSign Silver CA - G2 -======================== ------BEGIN CERTIFICATE----- -MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT -BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X -DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 -aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG -9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 -N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm -+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH -6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu -MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h -qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 -FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs -ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc -celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X -CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB -tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 -cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P -4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F -kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L -3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx -/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa -DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP -e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu -WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ -DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub -DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u ------END CERTIFICATE----- - -GeoTrust Primary Certification Authority -======================================== ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx -CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ -cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN -b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 -nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge -RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt -tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI -hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K -Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN -NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa -Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG -1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- - -thawte Primary Root CA -====================== ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE -BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 -aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 -MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg -SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv -KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT -FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs -oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ -1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc -q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K -aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p -afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD -VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF -AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE -uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 -jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH -z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== ------END CERTIFICATE----- - -VeriSign Class 3 Public Primary Certification Authority - G5 -============================================================ ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE -BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO -ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk -IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln -biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh -dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz -j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD -Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ -Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r -fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ -BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv -Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG -SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ -X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE -KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC -Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE -ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- - -SecureTrust CA -============== ------BEGIN CERTIFICATE----- -MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG -EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy -dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe -BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX -OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t -DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH -GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b -01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH -ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj -aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ -KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu -SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf -mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ -nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR -3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= ------END CERTIFICATE----- - -Secure Global CA -================ ------BEGIN CERTIFICATE----- -MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG -EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH -bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg -MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg -Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx -YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ -bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g -8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV -HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi -0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud -EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn -oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA -MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ -OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn -CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 -3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc -f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW ------END CERTIFICATE----- - -COMODO Certification Authority -============================== ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE -BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG -A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb -MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD -T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH -+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww -xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV -4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA -1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI -rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k -b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC -AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP -OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc -IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN -+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== ------END CERTIFICATE----- - -Network Solutions Certificate Authority -======================================= ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG -EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr -IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx -MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx -jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT -aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT -crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc -/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB -AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv -bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA -A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q -4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ -GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD -ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- - -WellsSecure Public Root Certificate Authority -============================================= ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM -F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw -NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN -MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl -bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD -VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 -iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 -i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 -bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB -K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB -AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu -cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm -lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB -i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww -GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg -Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI -K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 -bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj -qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es -E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ -tylv2G0xffX8oRAHh84vWdw+WNs= ------END CERTIFICATE----- - -COMODO ECC Certification Authority -================================== ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC -R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE -ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix -GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR -Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X -4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni -wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG -FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA -U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- - -IGC/A -===== ------BEGIN CERTIFICATE----- -MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD -VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE -Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy -MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI -EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT -STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 -TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW -So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy -HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd -frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ -tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB -egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC -iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK -q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q -MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg -Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI -lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF -0mBWWg== ------END CERTIFICATE----- - -Security Communication EV RootCA1 -================================= ------BEGIN CERTIFICATE----- -MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc -U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh -dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE -BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl -Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO -/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX -WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z -ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 -bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK -9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG -SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm -iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG -Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW -mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW -T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 ------END CERTIFICATE----- - -OISTE WISeKey Global Root GA CA -=============================== ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE -BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG -A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH -bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD -VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw -IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 -IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 -Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg -Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD -d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ -/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R -LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ -KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm -MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 -+vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa -hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY -okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= ------END CERTIFICATE----- - -Microsec e-Szigno Root CA -========================= ------BEGIN CERTIFICATE----- -MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE -BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL -EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 -MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz -dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT -GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG -d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N -oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc -QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ -PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb -MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG -IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD -VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 -LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A -dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn -AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA -4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg -AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA -egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 -Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO -PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv -c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h -cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw -IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT -WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV -MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER -MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp -Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal -HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT -nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE -aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a -86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK -yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB -S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= ------END CERTIFICATE----- - -Certigna -======== ------BEGIN CERTIFICATE----- -MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw -EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 -MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI -Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q -XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH -GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p -ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg -DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf -Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ -tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ -BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J -SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA -hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ -ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu -PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY -1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw -WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== ------END CERTIFICATE----- - -AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. -====================================== ------BEGIN CERTIFICATE----- -MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT -AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg -LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w -HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+ -U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh -IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN -yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU -2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3 -4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP -2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm -8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf -HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa -Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK -5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b -czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g -ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF -BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug -cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf -AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX -EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v -/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3 -MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4 -3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk -eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f -/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h -RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU -Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ== ------END CERTIFICATE----- - -TC TrustCenter Class 2 CA II -============================ ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy -IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw -MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 -c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE -AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw -IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 -xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ -Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u -SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB -7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 -Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU -cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i -SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G -dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ -KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj -TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP -JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk -vQ== ------END CERTIFICATE----- - -TC TrustCenter Class 3 CA II -============================ ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy -IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw -MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 -c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE -AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W -yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo -6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ -uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk -2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB -7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 -Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU -cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i -SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE -O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 -yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 -IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal -092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc -5A== ------END CERTIFICATE----- - -TC TrustCenter Universal CA I -============================= ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC -REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy -IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN -MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg -VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw -JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC -qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv -xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw -ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O -gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j -BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG -1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy -vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 -ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a -7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- - -Deutsche Telekom Root CA 2 -========================== ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT -RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG -A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 -MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G -A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS -b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 -bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI -KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY -AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK -Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV -jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV -HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr -E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy -zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 -rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G -dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU -Cm26OWMohpLzGITY+9HPBVZkVw== ------END CERTIFICATE----- - -ComSign Secured CA -================== ------BEGIN CERTIFICATE----- -MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE -AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w -NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD -QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs -49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH -7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB -kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 -9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw -AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t -U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA -j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC -AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a -BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp -FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP -51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz -OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== ------END CERTIFICATE----- - -Cybertrust Global Root -====================== ------BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li -ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 -MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD -ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -+Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW -0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL -AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin -89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT -8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 -MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G -A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO -lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi -5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 -hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T -X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW -WL1WMRJOEcgh4LMRkWXbtKaIOM5V ------END CERTIFICATE----- - -ePKI Root Certification Authority -================================= ------BEGIN CERTIFICATE----- -MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG -EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg -Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx -MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq -MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs -IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi -lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv -qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX -12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O -WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ -ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao -lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ -vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi -Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi -MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH -ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 -1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq -KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV -xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP -NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r -GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE -xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx -gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy -sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD -BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= ------END CERTIFICATE----- - -T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 -============================================================================================================================= ------BEGIN CERTIFICATE----- -MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH -DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q -aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry -b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV -BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg -S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 -MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl -IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF -n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl -IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft -dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl -cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO -Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 -xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR -6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL -hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd -BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 -N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT -y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh -LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M -dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= ------END CERTIFICATE----- - -Buypass Class 2 CA 1 -==================== ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 -MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh -c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M -cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 -0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 -0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R -uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P -AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV -1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt -7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 -fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w -wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho ------END CERTIFICATE----- - -Buypass Class 3 CA 1 -==================== ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 -MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh -c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx -ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 -n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia -AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c -1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P -AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 -pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA -EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 -htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj -el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 ------END CERTIFICATE----- - -EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 -========================================================================== ------BEGIN CERTIFICATE----- -MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg -QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe -Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p -ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt -IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by -X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b -gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr -eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ -TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy -Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn -uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI -qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm -ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0 -Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB -/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW -Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t -FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm -zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k -XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT -bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU -RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK -1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt -2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ -Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9 -AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT ------END CERTIFICATE----- - -certSIGN ROOT CA -================ ------BEGIN CERTIFICATE----- -MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD -VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa -Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE -CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I -JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH -rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 -ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD -0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 -AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B -Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB -AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 -SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 -x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt -vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz -TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD ------END CERTIFICATE----- - -CNNIC ROOT -========== ------BEGIN CERTIFICATE----- -MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE -ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw -OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD -o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz -VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT -VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or -czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK -y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC -wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S -lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 -Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM -O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 -BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 -G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m -mxE= ------END CERTIFICATE----- - -ApplicationCA - Japanese Government -=================================== ------BEGIN CERTIFICATE----- -MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT -SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw -MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl -cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 -fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN -wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE -jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu -nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU -WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV -BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD -vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs -o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g -/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD -io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW -dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL -rosot4LKGAfmt1t06SAZf7IbiVQ= ------END CERTIFICATE----- - -GeoTrust Primary Certification Authority - G3 -============================================= ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz -NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo -YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT -LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j -K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE -c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C -IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu -dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr -2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 -cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE -Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s -t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt ------END CERTIFICATE----- - -thawte Primary Root CA - G2 -=========================== ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC -VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu -IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg -Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV -MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG -b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt -IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS -LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 -8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU -mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN -G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K -rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- - -thawte Primary Root CA - G3 -=========================== ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE -BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 -aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w -ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD -VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG -A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At -P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC -+BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY -7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW -vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ -KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK -A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC -8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm -er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- - -GeoTrust Primary Certification Authority - G2 -============================================= ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 -OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl -b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG -BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc -KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ -EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m -ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 -npaqBA+K ------END CERTIFICATE----- - -VeriSign Universal Root Certification Authority -=============================================== ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE -BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO -ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk -IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u -IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj -1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP -MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 -9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I -AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR -tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G -CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O -a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 -Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx -Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx -P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P -wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 -mJO37M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- - -VeriSign Class 3 Public Primary Certification Authority - G4 -============================================================ ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC -VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 -b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz -ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU -cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo -b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 -Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz -rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw -HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u -Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD -A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx -AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- - -NetLock Arany (Class Gold) Főtanúsítvány -============================================ ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G -A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 -dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB -cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx -MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO -ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 -c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu -0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw -/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk -H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw -fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 -neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW -qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta -YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna -NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu -dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- - -Staat der Nederlanden Root CA - G2 -================================== ------BEGIN CERTIFICATE----- -MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE -CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g -Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC -TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l -ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ -5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn -vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj -CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil -e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR -OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI -CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65 -48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi -trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737 -qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB -AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC -ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA -A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz -+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj -f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN -kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk -CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF -URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb -CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h -oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV -IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm -66+KAQ== ------END CERTIFICATE----- - -CA Disig -======== ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK -QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw -MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz -bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm -GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD -Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo -hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt -ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w -gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P -AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz -aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff -ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa -BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t -WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 -mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ -CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K -ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA -4Z7CRneC9VkGjCFMhwnN5ag= ------END CERTIFICATE----- - -Juur-SK -======= ------BEGIN CERTIFICATE----- -MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA -c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw -DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG -SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy -aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf -TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC -+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw -UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa -Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF -MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD -HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh -AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA -cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr -AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw -cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE -FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G -A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo -ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL -abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 -IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh -Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 -yyqcjg== ------END CERTIFICATE----- - -Hongkong Post Root CA 1 -======================= ------BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT -DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx -NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n -IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 -ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr -auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh -qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY -V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV -HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i -h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio -l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei -IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps -T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT -c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== ------END CERTIFICATE----- - -SecureSign RootCA11 -=================== ------BEGIN CERTIFICATE----- -MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi -SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS -b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw -KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 -cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL -TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO -wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq -g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP -O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA -bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX -t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh -OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r -bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ -Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 -y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 -lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= ------END CERTIFICATE----- - -ACEDICOM Root -============= ------BEGIN CERTIFICATE----- -MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD -T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4 -MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG -A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk -WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD -YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew -MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb -m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk -HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT -xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2 -3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9 -2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq -TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz -4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU -9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv -bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg -aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP -eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk -zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1 -ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI -KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq -nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE -I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp -MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o -tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA== ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority -======================================================= ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx -FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow -XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz -IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 -f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol -hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky -CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX -bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/ -D/xwzoiQ ------END CERTIFICATE----- - -Microsec e-Szigno Root CA 2009 -============================== ------BEGIN CERTIFICATE----- -MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER -MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv -c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o -dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE -BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt -U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA -fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG -0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA -pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm -1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC -AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf -QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE -FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o -lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX -I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 -tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 -yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi -LXpUq3DDfSJlgnCW ------END CERTIFICATE----- - -E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi -=================================================== ------BEGIN CERTIFICATE----- -MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG -EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz -ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 -MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 -cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u -aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY -8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y -jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI -JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk -9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD -AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG -SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d -F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq -D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 -Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq -fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX ------END CERTIFICATE----- - -GlobalSign Root CA - R3 -======================= ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv -YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh -bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT -aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln -bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt -iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ -0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 -rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl -OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 -xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 -lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 -EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E -bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 -YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r -kpeDMdmztcpHWD9f ------END CERTIFICATE----- - -Autoridad de Certificacion Firmaprofesional CIF A62634068 -========================================================= ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA -BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw -QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB -NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD -Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P -B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY -7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH -ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI -plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX -MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX -LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK -bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU -vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud -EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH -DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp -cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA -bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx -ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx -51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk -R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP -T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f -Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl -osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR -crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR -saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD -KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi -6Et8Vcad+qMUu2WFbm5PEn4KPJ2V ------END CERTIFICATE----- - -Izenpe.com -========== ------BEGIN CERTIFICATE----- -MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG -EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz -MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu -QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ -03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK -ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU -+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC -PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT -OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK -F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK -0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ -0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB -leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID -AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ -SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG -NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx -MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O -BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l -Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga -kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q -hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs -g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 -aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 -nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC -ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo -Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z -WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== ------END CERTIFICATE----- - -Chambers of Commerce Root - 2008 -================================ ------BEGIN CERTIFICATE----- -MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD -MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv -bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu -QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy -Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl -ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF -EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl -cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA -XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj -h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ -ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk -NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g -D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 -lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ -0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj -ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 -EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI -G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ -BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh -bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh -bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC -CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH -AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 -wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH -3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU -RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 -M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 -YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF -9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK -zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG -nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg -OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ ------END CERTIFICATE----- - -Global Chambersign Root - 2008 -============================== ------BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD -MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv -bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu -QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx -NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg -Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ -QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf -VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf -XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 -ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB -/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA -TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M -H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe -Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF -HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB -AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT -BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE -BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm -aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm -aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp -1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 -dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG -/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 -ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s -dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg -9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH -foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du -qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr -P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq -c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B ------END CERTIFICATE----- - -Go Daddy Root Certificate Authority - G2 -======================================== ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu -MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G -A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq -9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD -+qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd -fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl -NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 -BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac -vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r -5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV -N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 ------END CERTIFICATE----- - -Starfield Root Certificate Authority - G2 -========================================= ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s -b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 -eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw -DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg -VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB -dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv -W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs -bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk -N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf -ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU -JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol -TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx -4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw -F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ -c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -Starfield Services Root Certificate Authority - G2 -================================================== ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s -b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl -IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT -dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg -Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 -h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa -hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP -LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB -rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG -SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP -E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy -xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza -YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 ------END CERTIFICATE----- - -AffirmTrust Commercial -====================== ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw -MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly -bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb -DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV -C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 -BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww -MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV -HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG -hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi -qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv -0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh -sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -AffirmTrust Networking -====================== ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw -MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly -bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE -Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI -dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 -/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb -h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV -HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu -UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 -12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 -WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 -/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -AffirmTrust Premium -=================== ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy -OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy -dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn -BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV -5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs -+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd -GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R -p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI -S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 -6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 -/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo -+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv -MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC -6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S -L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK -+4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV -BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg -IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 -g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb -zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== ------END CERTIFICATE----- - -AffirmTrust Premium ECC -======================= ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV -BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx -MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U -cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ -N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW -BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK -BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X -57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM -eQ== ------END CERTIFICATE----- - -Certum Trusted Network CA -========================= ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK -ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy -MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU -ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC -l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J -J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 -fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 -cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB -Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw -DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj -jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 -mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj -Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- - -Certinomis - Autorité Racine -============================= ------BEGIN CERTIFICATE----- -MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK -Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg -LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG -A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw -JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa -wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly -Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw -2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N -jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q -c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC -lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb -xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g -530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna -4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ -KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x -WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva -R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 -nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B -CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv -JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE -qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b -WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE -wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ -vgt2Fl43N+bYdJeimUV5 ------END CERTIFICATE----- - -Root CA Generalitat Valenciana -============================== ------BEGIN CERTIFICATE----- -MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE -ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 -IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 -WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE -CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 -F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B -ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ -D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte -JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB -AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n -dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB -ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl -AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA -YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy -AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA -aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt -AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA -YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu -AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA -OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 -dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV -BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G -A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S -b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh -TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz -Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 -NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH -iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt -+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= ------END CERTIFICATE----- - -A-Trust-nQual-03 -================ ------BEGIN CERTIFICATE----- -MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE -Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy -a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R -dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw -RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 -ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 -c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA -zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n -yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE -SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 -iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V -cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV -eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 -ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr -sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd -JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS -mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 -ahq97BvIxYSazQ== ------END CERTIFICATE----- - -TWCA Root Certification Authority -================================= ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ -VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG -EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB -IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx -QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC -oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP -4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r -y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG -9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC -mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW -QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY -T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny -Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ------END CERTIFICATE----- - -Security Communication RootCA2 -============================== ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc -U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh -dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC -SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy -aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ -+T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R -3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV -spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K -EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 -QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB -CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj -u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk -3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q -tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 -mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ------END CERTIFICATE----- - -EC-ACC -====== ------BEGIN CERTIFICATE----- -MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE -BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w -ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD -VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE -CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT -BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 -MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt -SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl -Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh -cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK -w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT -ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 -HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a -E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw -0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD -VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 -Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l -dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ -lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa -Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe -l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 -E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D -5EI= ------END CERTIFICATE----- - -Hellenic Academic and Research Institutions RootCA 2011 -======================================================= ------BEGIN CERTIFICATE----- -MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT -O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y -aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z -IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT -AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z -IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo -IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI -1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa -71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u -8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH -3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ -MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 -MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu -b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt -XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 -TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD -/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N -7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 ------END CERTIFICATE----- - -Actalis Authentication Root CA -============================== ------BEGIN CERTIFICATE----- -MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM -BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE -AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky -MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz -IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 -IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ -wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa -by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 -zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f -YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 -oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l -EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 -hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 -EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 -jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY -iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt -ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI -WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 -JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx -K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ -Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC -4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo -2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz -lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem -OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 -vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== ------END CERTIFICATE----- - -Trustis FPS Root CA -=================== ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG -EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 -IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV -BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ -RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk -H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa -cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt -o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA -AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd -BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c -GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC -yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P -8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV -l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl -iB6XzCGcKQENZetX2fNXlrtIzYE= ------END CERTIFICATE----- - -StartCom Certification Authority -================================ ------BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN -U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu -ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 -NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk -LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg -U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y -o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ -Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d -eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt -2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z -6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ -osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ -untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc -UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT -37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ -Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 -dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu -c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv -bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 -aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t -L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG -cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 -fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm -N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN -Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T -tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX -e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA -2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs -HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib -D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= ------END CERTIFICATE----- - -StartCom Certification Authority G2 -=================================== ------BEGIN CERTIFICATE----- -MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN -U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE -ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O -o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG -4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi -Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul -Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs -O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H -vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L -nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS -FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa -z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ -KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K -2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk -J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ -JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG -/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc -nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld -blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc -l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm -7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm -obp573PYtlNXLfbQ4ddI ------END CERTIFICATE----- - -Buypass Class 2 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X -DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 -g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn -9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b -/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU -CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff -awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI -zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn -Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX -Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs -M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI -osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S -aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd -DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD -LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 -oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC -wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS -CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN -rJgWVqA= ------END CERTIFICATE----- - -Buypass Class 3 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X -DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH -sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR -5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh -7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ -ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH -2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV -/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ -RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA -Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq -j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G -uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG -Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 -ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 -KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz -6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug -UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe -eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi -Cp/HuZc= ------END CERTIFICATE----- - -T-TeleSec GlobalRoot Class 3 -============================ ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM -IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU -cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx -MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz -dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD -ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK -9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU -NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF -iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W -0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr -AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb -fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT -ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h -P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== ------END CERTIFICATE----- - -EE Certification Centre Root CA -=============================== ------BEGIN CERTIFICATE----- -MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG -EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy -dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw -MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB -UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy -ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM -TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 -rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw -93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN -P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ -MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF -BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj -xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM -lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u -uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU -3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM -dcGWxZ0= ------END CERTIFICATE----- - -TURKTRUST Certificate Services Provider Root 2007 -================================================= ------BEGIN CERTIFICATE----- -MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP -MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg -QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X -DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl -a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN -BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp -bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N -YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv -KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya -KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT -rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC -AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP -BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s -Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I -aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO -Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb -BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK -poRq0Tl9 ------END CERTIFICATE----- - -D-TRUST Root Class 3 CA 2 2009 -============================== ------BEGIN CERTIFICATE----- -MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe -Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE -LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD -ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA -BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv -KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z -p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC -AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ -4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y -eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw -MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G -PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw -OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm -2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV -dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph -X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= ------END CERTIFICATE----- - -D-TRUST Root Class 3 CA 2 EV 2009 -================================= ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw -OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw -OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS -egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh -zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T -7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 -sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 -11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv -cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v -ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El -MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp -b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh -c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ -PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX -ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA -NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv -w9y4AyHqnxbxLFS1 ------END CERTIFICATE----- - -PSCProcert -========== ------BEGIN CERTIFICATE----- -MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk -ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ -MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz -dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl -cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw -IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw -MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w -DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD -ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp -Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC -wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA -3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh -RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO -EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2 -0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH -0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU -td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw -Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp -r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/ -AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz -Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId -xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp -ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH -EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h -Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k -ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG -9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG -MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG -LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52 -ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy -YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v -Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o -dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq -T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN -g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q -uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1 -n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn -FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo -5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq -3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5 -poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y -eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km ------END CERTIFICATE----- - -China Internet Network Information Center EV Certificates Root -============================================================== ------BEGIN CERTIFICATE----- -MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV -BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D -aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg -Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG -A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM -PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl -cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y -jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV -98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H -klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23 -KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC -7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD -glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5 -0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM -7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws -ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0 -5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8= ------END CERTIFICATE----- - -Swisscom Root CA 2 -================== ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG -EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy -dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2 -MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln -aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC -IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM -LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo -ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ -wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH -Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a -SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS -NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab -mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY -Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3 -qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw -HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O -BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu -MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO -v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ -82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz -o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs -a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx -OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW -mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o -+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC -rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX -5OfNeOI5wSsSnqaeG8XmDtkx2Q== ------END CERTIFICATE----- - -Swisscom Root EV CA 2 -===================== ------BEGIN CERTIFICATE----- -MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE -BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl -cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN -MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT -HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg -Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz -o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy -Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti -GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li -qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH -Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG -alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa -m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox -bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi -xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED -MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB -bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL -j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU -wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7 -XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH -59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/ -23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq -J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA -HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi -uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW -l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc= ------END CERTIFICATE----- - -CA Disig Root R1 -================ ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw -EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp -ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx -EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp -c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy -3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8 -u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2 -m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk -CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa -YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6 -vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL -LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX -ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is -XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ -04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR -xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B -LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM -CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb -VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85 -YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS -ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix -lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N -UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ -a7+h89n07eLw4+1knj0vllJPgFOL ------END CERTIFICATE----- - -CA Disig Root R2 -================ ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw -EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp -ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx -EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp -c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC -w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia -xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 -A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S -GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV -g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa -5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE -koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A -Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i -Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u -Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV -sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je -dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 -1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx -mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 -utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 -sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg -UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV -7+ZtsH8tZ/3zbBt1RqPlShfppNcL ------END CERTIFICATE----- - -ACCVRAIZ1 -========= ------BEGIN CERTIFICATE----- -MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB -SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 -MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH -UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM -jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 -RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD -aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ -0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG -WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 -8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR -5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J -9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK -Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw -Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu -Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM -Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA -QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh -AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA -YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj -AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA -IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk -aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 -dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 -MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI -hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E -R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN -YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 -nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ -TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 -sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg -Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd -3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p -EfbRD0tVNEYqi4Y7 ------END CERTIFICATE----- - -TWCA Global Root CA -=================== ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT -CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD -QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK -EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg -Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C -nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV -r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR -Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV -tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W -KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 -sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p -yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn -kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI -zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC -AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g -cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M -8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg -/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg -lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP -A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m -i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 -EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 -zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= ------END CERTIFICATE----- - -TeliaSonera Root CA v1 -====================== ------BEGIN CERTIFICATE----- -MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE -CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 -MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW -VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ -6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA -3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k -B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn -Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH -oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 -F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ -oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 -gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc -TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB -AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW -DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm -zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx -0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW -pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV -G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc -c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT -JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 -qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 -Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems -WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= ------END CERTIFICATE----- - -E-Tugra Certification Authority -=============================== ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w -DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls -ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw -NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx -QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl -cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD -DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd -hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K -CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g -ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ -BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 -E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz -rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq -jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 -dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB -/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG -MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK -kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO -XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 -VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo -a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc -dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV -KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT -Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 -8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G -C7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- - -T-TeleSec GlobalRoot Class 2 -============================ ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM -IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU -cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx -MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz -dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD -ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ -SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F -vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 -2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV -WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy -YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 -r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf -vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR -3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== ------END CERTIFICATE----- - -Atos TrustedRoot 2011 -===================== ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU -cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 -MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG -A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV -hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr -54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ -DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 -HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR -z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R -l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ -bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h -k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh -TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 -61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G -3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ------END CERTIFICATE----- diff --git a/awx/lib/site-packages/boto/cloudformation/__init__.py b/awx/lib/site-packages/boto/cloudformation/__init__.py deleted file mode 100644 index d602dc39e8..0000000000 --- a/awx/lib/site-packages/boto/cloudformation/__init__.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2010-2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010-2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.cloudformation.connection import CloudFormationConnection -from boto.regioninfo import RegionInfo, get_regions, load_regions - -RegionData = load_regions().get('cloudformation') - - -def regions(): - """ - Get all available regions for the CloudFormation service. - - :rtype: list - :return: A list of :class:`boto.RegionInfo` instances - """ - return get_regions( - 'cloudformation', - connection_cls=CloudFormationConnection - ) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.cloudformation.CloudFormationConnection`. - - :param str region_name: The name of the region to connect to. - - :rtype: :class:`boto.cloudformation.CloudFormationConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/cloudformation/connection.py b/awx/lib/site-packages/boto/cloudformation/connection.py deleted file mode 100644 index 6c31ac53b3..0000000000 --- a/awx/lib/site-packages/boto/cloudformation/connection.py +++ /dev/null @@ -1,888 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -from boto.cloudformation.stack import Stack, StackSummary, StackEvent -from boto.cloudformation.stack import StackResource, StackResourceSummary -from boto.cloudformation.template import Template -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.compat import json - - -class CloudFormationConnection(AWSQueryConnection): - """ - AWS CloudFormation - AWS CloudFormation enables you to create and manage AWS - infrastructure deployments predictably and repeatedly. AWS - CloudFormation helps you leverage AWS products such as Amazon EC2, - EBS, Amazon SNS, ELB, and Auto Scaling to build highly-reliable, - highly scalable, cost effective applications without worrying - about creating and configuring the underlying AWS infrastructure. - - With AWS CloudFormation, you declare all of your resources and - dependencies in a template file. The template defines a collection - of resources as a single unit called a stack. AWS CloudFormation - creates and deletes all member resources of the stack together and - manages all dependencies between the resources for you. - - For more information about this product, go to the `CloudFormation - Product Page`_. - - Amazon CloudFormation makes use of other AWS products. If you need - additional technical information about a specific AWS product, you - can find the product's technical documentation at - `http://aws.amazon.com/documentation/`_. - """ - APIVersion = boto.config.get('Boto', 'cfn_version', '2010-05-15') - DefaultRegionName = boto.config.get('Boto', 'cfn_region_name', 'us-east-1') - DefaultRegionEndpoint = boto.config.get('Boto', 'cfn_region_endpoint', - 'cloudformation.us-east-1.amazonaws.com') - - valid_states = ( - 'CREATE_IN_PROGRESS', 'CREATE_FAILED', 'CREATE_COMPLETE', - 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_FAILED', 'ROLLBACK_COMPLETE', - 'DELETE_IN_PROGRESS', 'DELETE_FAILED', 'DELETE_COMPLETE', - 'UPDATE_IN_PROGRESS', 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS', - 'UPDATE_COMPLETE', 'UPDATE_ROLLBACK_IN_PROGRESS', - 'UPDATE_ROLLBACK_FAILED', - 'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS', - 'UPDATE_ROLLBACK_COMPLETE') - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - converter=None, security_token=None, validate_certs=True, - profile_name=None): - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint, CloudFormationConnection) - self.region = region - super(CloudFormationConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def encode_bool(self, v): - v = bool(v) - return {True: "true", False: "false"}[v] - - def _build_create_or_update_params(self, stack_name, template_body, - template_url, parameters, disable_rollback, timeout_in_minutes, - notification_arns, capabilities, on_failure, stack_policy_body, - stack_policy_url, tags, stack_policy_during_update_body=None, - stack_policy_during_update_url=None): - """ - Helper that creates JSON parameters needed by a Stack Create or - Stack Update call. - - :type stack_name: string - :param stack_name: - The name associated with the stack. The name must be unique within your - AWS account. - - Must contain only alphanumeric characters (case sensitive) and start - with an alpha character. Maximum length of the name is 255 - characters. - - :type template_body: string - :param template_body: Structure containing the template body. (For more - information, go to `Template Anatomy`_ in the AWS CloudFormation - User Guide.) - Conditional: You must pass `TemplateBody` or `TemplateURL`. If both are - passed, only `TemplateBody` is used. - - :type template_url: string - :param template_url: Location of file containing the template body. The - URL must point to a template (max size: 307,200 bytes) located in - an S3 bucket in the same region as the stack. For more information, - go to the `Template Anatomy`_ in the AWS CloudFormation User Guide. - Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are - passed, only `TemplateBody` is used. - - :type parameters: list - :param parameters: A list of key/value tuples that specify input - parameters for the stack. - - :type disable_rollback: boolean - :param disable_rollback: Set to `True` to disable rollback of the stack - if stack creation failed. You can specify either `DisableRollback` - or `OnFailure`, but not both. - Default: `False` - - :type timeout_in_minutes: integer - :param timeout_in_minutes: The amount of time that can pass before the - stack status becomes CREATE_FAILED; if `DisableRollback` is not set - or is set to `False`, the stack will be rolled back. - - :type notification_arns: list - :param notification_arns: The Simple Notification Service (SNS) topic - ARNs to publish stack related events. You can find your SNS topic - ARNs using the `SNS console`_ or your Command Line Interface (CLI). - - :type capabilities: list - :param capabilities: The list of capabilities that you want to allow in - the stack. If your template contains certain resources, you must - specify the CAPABILITY_IAM value for this parameter; otherwise, - this action returns an InsufficientCapabilities error. The - following resources require you to specify the capabilities - parameter: `AWS::CloudFormation::Stack`_, `AWS::IAM::AccessKey`_, - `AWS::IAM::Group`_, `AWS::IAM::InstanceProfile`_, - `AWS::IAM::Policy`_, `AWS::IAM::Role`_, `AWS::IAM::User`_, and - `AWS::IAM::UserToGroupAddition`_. - - :type on_failure: string - :param on_failure: Determines what action will be taken if stack - creation fails. This must be one of: DO_NOTHING, ROLLBACK, or - DELETE. You can specify either `OnFailure` or `DisableRollback`, - but not both. - Default: `ROLLBACK` - - :type stack_policy_body: string - :param stack_policy_body: Structure containing the stack policy body. - (For more information, go to ` Prevent Updates to Stack Resources`_ - in the AWS CloudFormation User Guide.) - If you pass `StackPolicyBody` and `StackPolicyURL`, only - `StackPolicyBody` is used. - - :type stack_policy_url: string - :param stack_policy_url: Location of a file containing the stack - policy. The URL must point to a policy (max size: 16KB) located in - an S3 bucket in the same region as the stack. If you pass - `StackPolicyBody` and `StackPolicyURL`, only `StackPolicyBody` is - used. - - :type tags: list - :param tags: A set of user-defined `Tags` to associate with this stack, - represented by key/value pairs. Tags defined for the stack are - propagated to EC2 resources that are created as part of the stack. - A maximum number of 10 tags can be specified. - - :type stack_policy_during_update_body: string - :param stack_policy_during_update_body: Structure containing the - temporary overriding stack policy body. If you pass - `StackPolicyDuringUpdateBody` and `StackPolicyDuringUpdateURL`, - only `StackPolicyDuringUpdateBody` is used. - If you want to update protected resources, specify a temporary - overriding stack policy during this update. If you do not specify a - stack policy, the current policy that associated with the stack - will be used. - - :type stack_policy_during_update_url: string - :param stack_policy_during_update_url: Location of a file containing - the temporary overriding stack policy. The URL must point to a - policy (max size: 16KB) located in an S3 bucket in the same region - as the stack. If you pass `StackPolicyDuringUpdateBody` and - `StackPolicyDuringUpdateURL`, only `StackPolicyDuringUpdateBody` is - used. - If you want to update protected resources, specify a temporary - overriding stack policy during this update. If you do not specify a - stack policy, the current policy that is associated with the stack - will be used. - - :rtype: dict - :return: JSON parameters represented as a Python dict. - """ - params = {'ContentType': "JSON", 'StackName': stack_name, - 'DisableRollback': self.encode_bool(disable_rollback)} - if template_body: - params['TemplateBody'] = template_body - if template_url: - params['TemplateURL'] = template_url - if template_body and template_url: - boto.log.warning("If both TemplateBody and TemplateURL are" - " specified, only TemplateBody will be honored by the API") - if parameters and len(parameters) > 0: - for i, (key, value) in enumerate(parameters): - params['Parameters.member.%d.ParameterKey' % (i + 1)] = key - params['Parameters.member.%d.ParameterValue' % (i + 1)] = value - if capabilities: - for i, value in enumerate(capabilities): - params['Capabilities.member.%d' % (i + 1)] = value - if tags: - for i, (key, value) in enumerate(tags.items()): - params['Tags.member.%d.Key' % (i + 1)] = key - params['Tags.member.%d.Value' % (i + 1)] = value - if notification_arns and len(notification_arns) > 0: - self.build_list_params(params, notification_arns, - "NotificationARNs.member") - if timeout_in_minutes: - params['TimeoutInMinutes'] = int(timeout_in_minutes) - if disable_rollback is not None: - params['DisableRollback'] = str( - disable_rollback).lower() - if on_failure is not None: - params['OnFailure'] = on_failure - if stack_policy_body is not None: - params['StackPolicyBody'] = stack_policy_body - if stack_policy_url is not None: - params['StackPolicyURL'] = stack_policy_url - if stack_policy_during_update_body is not None: - params['StackPolicyDuringUpdateBody'] = stack_policy_during_update_body - if stack_policy_during_update_url is not None: - params['StackPolicyDuringUpdateURL'] = stack_policy_during_update_url - return params - - def _do_request(self, call, params, path, method): - """ - Do a request via ``self.make_request`` and parse the JSON response. - - :type call: string - :param call: Call name, e.g. ``CreateStack`` - - :type params: dict - :param params: Dictionary of call parameters - - :type path: string - :param path: Server path - - :type method: string - :param method: HTTP method to use - - :rtype: dict - :return: Parsed JSON response data - """ - response = self.make_request(call, params, path, method) - body = response.read().decode('utf-8') - if response.status == 200: - body = json.loads(body) - return body - else: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise self.ResponseError(response.status, response.reason, body=body) - - def create_stack(self, stack_name, template_body=None, template_url=None, - parameters=None, notification_arns=None, disable_rollback=None, - timeout_in_minutes=None, capabilities=None, tags=None, - on_failure=None, stack_policy_body=None, stack_policy_url=None): - """ - Creates a stack as specified in the template. After the call - completes successfully, the stack creation starts. You can - check the status of the stack via the DescribeStacks API. - Currently, the limit for stacks is 20 stacks per account per - region. - - :type stack_name: string - :param stack_name: - The name associated with the stack. The name must be unique within your - AWS account. - - Must contain only alphanumeric characters (case sensitive) and start - with an alpha character. Maximum length of the name is 255 - characters. - - :type template_body: string - :param template_body: Structure containing the template body. (For more - information, go to `Template Anatomy`_ in the AWS CloudFormation - User Guide.) - Conditional: You must pass `TemplateBody` or `TemplateURL`. If both are - passed, only `TemplateBody` is used. - - :type template_url: string - :param template_url: Location of file containing the template body. The - URL must point to a template (max size: 307,200 bytes) located in - an S3 bucket in the same region as the stack. For more information, - go to the `Template Anatomy`_ in the AWS CloudFormation User Guide. - Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are - passed, only `TemplateBody` is used. - - :type parameters: list - :param parameters: A list of key/value tuples that specify input - parameters for the stack. - - :type disable_rollback: boolean - :param disable_rollback: Set to `True` to disable rollback of the stack - if stack creation failed. You can specify either `DisableRollback` - or `OnFailure`, but not both. - Default: `False` - - :type timeout_in_minutes: integer - :param timeout_in_minutes: The amount of time that can pass before the - stack status becomes CREATE_FAILED; if `DisableRollback` is not set - or is set to `False`, the stack will be rolled back. - - :type notification_arns: list - :param notification_arns: The Simple Notification Service (SNS) topic - ARNs to publish stack related events. You can find your SNS topic - ARNs using the `SNS console`_ or your Command Line Interface (CLI). - - :type capabilities: list - :param capabilities: The list of capabilities that you want to allow in - the stack. If your template contains certain resources, you must - specify the CAPABILITY_IAM value for this parameter; otherwise, - this action returns an InsufficientCapabilities error. The - following resources require you to specify the capabilities - parameter: `AWS::CloudFormation::Stack`_, `AWS::IAM::AccessKey`_, - `AWS::IAM::Group`_, `AWS::IAM::InstanceProfile`_, - `AWS::IAM::Policy`_, `AWS::IAM::Role`_, `AWS::IAM::User`_, and - `AWS::IAM::UserToGroupAddition`_. - - :type on_failure: string - :param on_failure: Determines what action will be taken if stack - creation fails. This must be one of: DO_NOTHING, ROLLBACK, or - DELETE. You can specify either `OnFailure` or `DisableRollback`, - but not both. - Default: `ROLLBACK` - - :type stack_policy_body: string - :param stack_policy_body: Structure containing the stack policy body. - (For more information, go to ` Prevent Updates to Stack Resources`_ - in the AWS CloudFormation User Guide.) - If you pass `StackPolicyBody` and `StackPolicyURL`, only - `StackPolicyBody` is used. - - :type stack_policy_url: string - :param stack_policy_url: Location of a file containing the stack - policy. The URL must point to a policy (max size: 16KB) located in - an S3 bucket in the same region as the stack. If you pass - `StackPolicyBody` and `StackPolicyURL`, only `StackPolicyBody` is - used. - - :type tags: dict - :param tags: A set of user-defined `Tags` to associate with this stack, - represented by key/value pairs. Tags defined for the stack are - propagated to EC2 resources that are created as part of the stack. - A maximum number of 10 tags can be specified. - """ - params = self._build_create_or_update_params(stack_name, template_body, - template_url, parameters, disable_rollback, timeout_in_minutes, - notification_arns, capabilities, on_failure, stack_policy_body, - stack_policy_url, tags) - body = self._do_request('CreateStack', params, '/', 'POST') - return body['CreateStackResponse']['CreateStackResult']['StackId'] - - def update_stack(self, stack_name, template_body=None, template_url=None, - parameters=None, notification_arns=None, disable_rollback=False, - timeout_in_minutes=None, capabilities=None, tags=None, - stack_policy_during_update_body=None, - stack_policy_during_update_url=None, - stack_policy_body=None, stack_policy_url=None): - """ - Updates a stack as specified in the template. After the call - completes successfully, the stack update starts. You can check - the status of the stack via the DescribeStacks action. - - - - **Note: **You cannot update `AWS::S3::Bucket`_ resources, for - example, to add or modify tags. - - - - To get a copy of the template for an existing stack, you can - use the GetTemplate action. - - Tags that were associated with this stack during creation time - will still be associated with the stack after an `UpdateStack` - operation. - - For more information about creating an update template, - updating a stack, and monitoring the progress of the update, - see `Updating a Stack`_. - - :type stack_name: string - :param stack_name: - The name or stack ID of the stack to update. - - Must contain only alphanumeric characters (case sensitive) and start - with an alpha character. Maximum length of the name is 255 - characters. - - :type template_body: string - :param template_body: Structure containing the template body. (For more - information, go to `Template Anatomy`_ in the AWS CloudFormation - User Guide.) - Conditional: You must pass `TemplateBody` or `TemplateURL`. If both are - passed, only `TemplateBody` is used. - - :type template_url: string - :param template_url: Location of file containing the template body. The - URL must point to a template located in an S3 bucket in the same - region as the stack. For more information, go to `Template - Anatomy`_ in the AWS CloudFormation User Guide. - Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are - passed, only `TemplateBody` is used. - - :type parameters: list - :param parameters: A list of key/value tuples that specify input - parameters for the stack. - - :type notification_arns: list - :param notification_arns: The Simple Notification Service (SNS) topic - ARNs to publish stack related events. You can find your SNS topic - ARNs using the `SNS console`_ or your Command Line Interface (CLI). - - :type disable_rollback: bool - :param disable_rollback: Indicates whether or not to rollback on - failure. - - :type timeout_in_minutes: integer - :param timeout_in_minutes: The amount of time that can pass before the - stack status becomes CREATE_FAILED; if `DisableRollback` is not set - or is set to `False`, the stack will be rolled back. - - :type capabilities: list - :param capabilities: The list of capabilities you want to allow in - the stack. Currently, the only valid capability is - 'CAPABILITY_IAM'. - - :type tags: dict - :param tags: A set of user-defined `Tags` to associate with this stack, - represented by key/value pairs. Tags defined for the stack are - propagated to EC2 resources that are created as part of the stack. - A maximum number of 10 tags can be specified. - - :type template_url: string - :param template_url: Location of file containing the template body. The - URL must point to a template located in an S3 bucket in the same - region as the stack. For more information, go to `Template - Anatomy`_ in the AWS CloudFormation User Guide. - Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are - passed, only `TemplateBody` is used. - - :type stack_policy_during_update_body: string - :param stack_policy_during_update_body: Structure containing the - temporary overriding stack policy body. If you pass - `StackPolicyDuringUpdateBody` and `StackPolicyDuringUpdateURL`, - only `StackPolicyDuringUpdateBody` is used. - If you want to update protected resources, specify a temporary - overriding stack policy during this update. If you do not specify a - stack policy, the current policy that associated with the stack - will be used. - - :type stack_policy_during_update_url: string - :param stack_policy_during_update_url: Location of a file containing - the temporary overriding stack policy. The URL must point to a - policy (max size: 16KB) located in an S3 bucket in the same region - as the stack. If you pass `StackPolicyDuringUpdateBody` and - `StackPolicyDuringUpdateURL`, only `StackPolicyDuringUpdateBody` is - used. - If you want to update protected resources, specify a temporary - overriding stack policy during this update. If you do not specify a - stack policy, the current policy that is associated with the stack - will be used. - - :rtype: string - :return: The unique Stack ID. - """ - params = self._build_create_or_update_params(stack_name, template_body, - template_url, parameters, disable_rollback, timeout_in_minutes, - notification_arns, capabilities, None, stack_policy_body, - stack_policy_url, tags, stack_policy_during_update_body, - stack_policy_during_update_url) - body = self._do_request('UpdateStack', params, '/', 'POST') - return body['UpdateStackResponse']['UpdateStackResult']['StackId'] - - def delete_stack(self, stack_name_or_id): - """ - Deletes a specified stack. Once the call completes - successfully, stack deletion starts. Deleted stacks do not - show up in the DescribeStacks API if the deletion has been - completed successfully. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated - with the stack. - - """ - params = {'ContentType': "JSON", 'StackName': stack_name_or_id} - return self._do_request('DeleteStack', params, '/', 'GET') - - def describe_stack_events(self, stack_name_or_id=None, next_token=None): - """ - Returns all stack related events for a specified stack. For - more information about a stack's event history, go to - `Stacks`_ in the AWS CloudFormation User Guide. - Events are returned, even if the stack never existed or has - been successfully deleted. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated - with the stack. - Default: There is no default value. - - :type next_token: string - :param next_token: String that identifies the start of the next list of - events, if there is one. - Default: There is no default value. - - """ - params = {} - if stack_name_or_id: - params['StackName'] = stack_name_or_id - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribeStackEvents', params, [('member', - StackEvent)]) - - def describe_stack_resource(self, stack_name_or_id, logical_resource_id): - """ - Returns a description of the specified resource in the - specified stack. - - For deleted stacks, DescribeStackResource returns resource - information for up to 90 days after the stack has been - deleted. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated - with the stack. - Default: There is no default value. - - :type logical_resource_id: string - :param logical_resource_id: The logical name of the resource as - specified in the template. - Default: There is no default value. - - """ - params = {'ContentType': "JSON", 'StackName': stack_name_or_id, - 'LogicalResourceId': logical_resource_id} - return self._do_request('DescribeStackResource', params, '/', 'GET') - - def describe_stack_resources(self, stack_name_or_id=None, - logical_resource_id=None, - physical_resource_id=None): - """ - Returns AWS resource descriptions for running and deleted - stacks. If `StackName` is specified, all the associated - resources that are part of the stack are returned. If - `PhysicalResourceId` is specified, the associated resources of - the stack that the resource belongs to are returned. - Only the first 100 resources will be returned. If your stack - has more resources than this, you should use - `ListStackResources` instead. - For deleted stacks, `DescribeStackResources` returns resource - information for up to 90 days after the stack has been - deleted. - - You must specify either `StackName` or `PhysicalResourceId`, - but not both. In addition, you can specify `LogicalResourceId` - to filter the returned result. For more information about - resources, the `LogicalResourceId` and `PhysicalResourceId`, - go to the `AWS CloudFormation User Guide`_. - A `ValidationError` is returned if you specify both - `StackName` and `PhysicalResourceId` in the same request. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated - with the stack. - Required: Conditional. If you do not specify `StackName`, you must - specify `PhysicalResourceId`. - - Default: There is no default value. - - :type logical_resource_id: string - :param logical_resource_id: The logical name of the resource as - specified in the template. - Default: There is no default value. - - :type physical_resource_id: string - :param physical_resource_id: The name or unique identifier that - corresponds to a physical instance ID of a resource supported by - AWS CloudFormation. - For example, for an Amazon Elastic Compute Cloud (EC2) instance, - `PhysicalResourceId` corresponds to the `InstanceId`. You can pass - the EC2 `InstanceId` to `DescribeStackResources` to find which - stack the instance belongs to and what other resources are part of - the stack. - - Required: Conditional. If you do not specify `PhysicalResourceId`, you - must specify `StackName`. - - Default: There is no default value. - - """ - params = {} - if stack_name_or_id: - params['StackName'] = stack_name_or_id - if logical_resource_id: - params['LogicalResourceId'] = logical_resource_id - if physical_resource_id: - params['PhysicalResourceId'] = physical_resource_id - return self.get_list('DescribeStackResources', params, - [('member', StackResource)]) - - def describe_stacks(self, stack_name_or_id=None, next_token=None): - """ - Returns the description for the specified stack; if no stack - name was specified, then it returns the description for all - the stacks created. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated - with the stack. - Default: There is no default value. - - :type next_token: string - :param next_token: String that identifies the start of the next list of - stacks, if there is one. - - """ - params = {} - if stack_name_or_id: - params['StackName'] = stack_name_or_id - if next_token is not None: - params['NextToken'] = next_token - return self.get_list('DescribeStacks', params, [('member', Stack)]) - - def get_template(self, stack_name_or_id): - """ - Returns the template body for a specified stack. You can get - the template for running or deleted stacks. - - For deleted stacks, GetTemplate returns the template for up to - 90 days after the stack has been deleted. - If the template does not exist, a `ValidationError` is - returned. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated - with the stack, which are not always interchangeable: - - + Running stacks: You can specify either the stack's name or its unique - stack ID. - + Deleted stacks: You must specify the unique stack ID. - - - Default: There is no default value. - - """ - params = {'ContentType': "JSON", 'StackName': stack_name_or_id} - return self._do_request('GetTemplate', params, '/', 'GET') - - def list_stack_resources(self, stack_name_or_id, next_token=None): - """ - Returns descriptions of all resources of the specified stack. - - For deleted stacks, ListStackResources returns resource - information for up to 90 days after the stack has been - deleted. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated - with the stack, which are not always interchangeable: - - + Running stacks: You can specify either the stack's name or its unique - stack ID. - + Deleted stacks: You must specify the unique stack ID. - - - Default: There is no default value. - - :type next_token: string - :param next_token: String that identifies the start of the next list of - stack resource summaries, if there is one. - Default: There is no default value. - - """ - params = {'StackName': stack_name_or_id} - if next_token: - params['NextToken'] = next_token - return self.get_list('ListStackResources', params, - [('member', StackResourceSummary)]) - - def list_stacks(self, stack_status_filters=None, next_token=None): - """ - Returns the summary information for stacks whose status - matches the specified StackStatusFilter. Summary information - for stacks that have been deleted is kept for 90 days after - the stack is deleted. If no StackStatusFilter is specified, - summary information for all stacks is returned (including - existing stacks and stacks that have been deleted). - - :type next_token: string - :param next_token: String that identifies the start of the next list of - stacks, if there is one. - Default: There is no default value. - - :type stack_status_filter: list - :param stack_status_filter: Stack status to use as a filter. Specify - one or more stack status codes to list only stacks with the - specified status codes. For a complete list of stack status codes, - see the `StackStatus` parameter of the Stack data type. - - """ - params = {} - if next_token: - params['NextToken'] = next_token - if stack_status_filters and len(stack_status_filters) > 0: - self.build_list_params(params, stack_status_filters, - "StackStatusFilter.member") - - return self.get_list('ListStacks', params, - [('member', StackSummary)]) - - def validate_template(self, template_body=None, template_url=None): - """ - Validates a specified template. - - :type template_body: string - :param template_body: String containing the template body. (For more - information, go to `Template Anatomy`_ in the AWS CloudFormation - User Guide.) - Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are - passed, only `TemplateBody` is used. - - :type template_url: string - :param template_url: Location of file containing the template body. The - URL must point to a template (max size: 307,200 bytes) located in - an S3 bucket in the same region as the stack. For more information, - go to `Template Anatomy`_ in the AWS CloudFormation User Guide. - Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are - passed, only `TemplateBody` is used. - - """ - params = {} - if template_body: - params['TemplateBody'] = template_body - if template_url: - params['TemplateURL'] = template_url - if template_body and template_url: - boto.log.warning("If both TemplateBody and TemplateURL are" - " specified, only TemplateBody will be honored by the API") - return self.get_object('ValidateTemplate', params, Template, - verb="POST") - - def cancel_update_stack(self, stack_name_or_id=None): - """ - Cancels an update on the specified stack. If the call - completes successfully, the stack will roll back the update - and revert to the previous stack configuration. - Only stacks that are in the UPDATE_IN_PROGRESS state can be - canceled. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or the unique identifier associated with - the stack. - - """ - params = {} - if stack_name_or_id: - params['StackName'] = stack_name_or_id - return self.get_status('CancelUpdateStack', params) - - def estimate_template_cost(self, template_body=None, template_url=None, - parameters=None): - """ - Returns the estimated monthly cost of a template. The return - value is an AWS Simple Monthly Calculator URL with a query - string that describes the resources required to run the - template. - - :type template_body: string - :param template_body: Structure containing the template body. (For more - information, go to `Template Anatomy`_ in the AWS CloudFormation - User Guide.) - Conditional: You must pass `TemplateBody` or `TemplateURL`. If both are - passed, only `TemplateBody` is used. - - :type template_url: string - :param template_url: Location of file containing the template body. The - URL must point to a template located in an S3 bucket in the same - region as the stack. For more information, go to `Template - Anatomy`_ in the AWS CloudFormation User Guide. - Conditional: You must pass `TemplateURL` or `TemplateBody`. If both are - passed, only `TemplateBody` is used. - - :type parameters: list - :param parameters: A list of key/value tuples that specify input - parameters for the template. - - :rtype: string - :returns: URL to pre-filled cost calculator - """ - params = {'ContentType': "JSON"} - if template_body is not None: - params['TemplateBody'] = template_body - if template_url is not None: - params['TemplateURL'] = template_url - if parameters and len(parameters) > 0: - for i, (key, value) in enumerate(parameters): - params['Parameters.member.%d.ParameterKey' % (i + 1)] = key - params['Parameters.member.%d.ParameterValue' % (i + 1)] = value - - response = self._do_request('EstimateTemplateCost', params, '/', 'POST') - return response['EstimateTemplateCostResponse']\ - ['EstimateTemplateCostResult']\ - ['Url'] - - def get_stack_policy(self, stack_name_or_id): - """ - Returns the stack policy for a specified stack. If a stack - doesn't have a policy, a null value is returned. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or stack ID that is associated with - the stack whose policy you want to get. - - :rtype: string - :return: The policy JSON document - """ - params = {'ContentType': "JSON", 'StackName': stack_name_or_id, } - response = self._do_request('GetStackPolicy', params, '/', 'POST') - return response['GetStackPolicyResponse']\ - ['GetStackPolicyResult']\ - ['StackPolicyBody'] - - def set_stack_policy(self, stack_name_or_id, stack_policy_body=None, - stack_policy_url=None): - """ - Sets a stack policy for a specified stack. - - :type stack_name_or_id: string - :param stack_name_or_id: The name or stack ID that you want to - associate a policy with. - - :type stack_policy_body: string - :param stack_policy_body: Structure containing the stack policy body. - (For more information, go to ` Prevent Updates to Stack Resources`_ - in the AWS CloudFormation User Guide.) - You must pass `StackPolicyBody` or `StackPolicyURL`. If both are - passed, only `StackPolicyBody` is used. - - :type stack_policy_url: string - :param stack_policy_url: Location of a file containing the stack - policy. The URL must point to a policy (max size: 16KB) located in - an S3 bucket in the same region as the stack. You must pass - `StackPolicyBody` or `StackPolicyURL`. If both are passed, only - `StackPolicyBody` is used. - - """ - params = {'ContentType': "JSON", 'StackName': stack_name_or_id, } - if stack_policy_body is not None: - params['StackPolicyBody'] = stack_policy_body - if stack_policy_url is not None: - params['StackPolicyURL'] = stack_policy_url - - response = self._do_request('SetStackPolicy', params, '/', 'POST') - return response['SetStackPolicyResponse']\ - ['SetStackPolicyResult'] diff --git a/awx/lib/site-packages/boto/cloudformation/stack.py b/awx/lib/site-packages/boto/cloudformation/stack.py deleted file mode 100644 index 5dac0dd7cf..0000000000 --- a/awx/lib/site-packages/boto/cloudformation/stack.py +++ /dev/null @@ -1,415 +0,0 @@ -from datetime import datetime - -from boto.resultset import ResultSet - - -class Stack(object): - def __init__(self, connection=None): - self.connection = connection - self.creation_time = None - self.description = None - self.disable_rollback = None - self.notification_arns = [] - self.outputs = [] - self.parameters = [] - self.capabilities = [] - self.tags = [] - self.stack_id = None - self.stack_status = None - self.stack_name = None - self.stack_name_reason = None - self.timeout_in_minutes = None - - def startElement(self, name, attrs, connection): - if name == "Parameters": - self.parameters = ResultSet([('member', Parameter)]) - return self.parameters - elif name == "Outputs": - self.outputs = ResultSet([('member', Output)]) - return self.outputs - elif name == "Capabilities": - self.capabilities = ResultSet([('member', Capability)]) - return self.capabilities - elif name == "Tags": - self.tags = Tag() - return self.tags - elif name == 'NotificationARNs': - self.notification_arns = ResultSet([('member', NotificationARN)]) - return self.notification_arns - else: - return None - - def endElement(self, name, value, connection): - if name == 'CreationTime': - try: - self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - except ValueError: - self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - elif name == "Description": - self.description = value - elif name == "DisableRollback": - if str(value).lower() == 'true': - self.disable_rollback = True - else: - self.disable_rollback = False - elif name == 'StackId': - self.stack_id = value - elif name == 'StackName': - self.stack_name = value - elif name == 'StackStatus': - self.stack_status = value - elif name == "StackStatusReason": - self.stack_status_reason = value - elif name == "TimeoutInMinutes": - self.timeout_in_minutes = int(value) - elif name == "member": - pass - else: - setattr(self, name, value) - - def delete(self): - return self.connection.delete_stack(stack_name_or_id=self.stack_id) - - def describe_events(self, next_token=None): - return self.connection.describe_stack_events( - stack_name_or_id=self.stack_id, - next_token=next_token - ) - - def describe_resource(self, logical_resource_id): - return self.connection.describe_stack_resource( - stack_name_or_id=self.stack_id, - logical_resource_id=logical_resource_id - ) - - def describe_resources(self, logical_resource_id=None, - physical_resource_id=None): - return self.connection.describe_stack_resources( - stack_name_or_id=self.stack_id, - logical_resource_id=logical_resource_id, - physical_resource_id=physical_resource_id - ) - - def list_resources(self, next_token=None): - return self.connection.list_stack_resources( - stack_name_or_id=self.stack_id, - next_token=next_token - ) - - def update(self): - rs = self.connection.describe_stacks(self.stack_id) - if len(rs) == 1 and rs[0].stack_id == self.stack_id: - self.__dict__.update(rs[0].__dict__) - else: - raise ValueError("%s is not a valid Stack ID or Name" % - self.stack_id) - - def get_template(self): - return self.connection.get_template(stack_name_or_id=self.stack_id) - - def get_policy(self): - """ - Returns the stack policy for this stack. If it has no policy - then, a null value is returned. - """ - return self.connection.get_stack_policy(self.stack_id) - - def set_policy(self, stack_policy_body=None, stack_policy_url=None): - """ - Sets a stack policy for this stack. - - :type stack_policy_body: string - :param stack_policy_body: Structure containing the stack policy body. - (For more information, go to ` Prevent Updates to Stack Resources`_ - in the AWS CloudFormation User Guide.) - You must pass `StackPolicyBody` or `StackPolicyURL`. If both are - passed, only `StackPolicyBody` is used. - - :type stack_policy_url: string - :param stack_policy_url: Location of a file containing the stack - policy. The URL must point to a policy (max size: 16KB) located in - an S3 bucket in the same region as the stack. You must pass - `StackPolicyBody` or `StackPolicyURL`. If both are passed, only - `StackPolicyBody` is used. - """ - return self.connection.set_stack_policy(self.stack_id, - stack_policy_body=stack_policy_body, - stack_policy_url=stack_policy_url) - - -class StackSummary(object): - def __init__(self, connection=None): - self.connection = connection - self.stack_id = None - self.stack_status = None - self.stack_name = None - self.creation_time = None - self.deletion_time = None - self.template_description = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'StackId': - self.stack_id = value - elif name == 'StackStatus': - self.stack_status = value - elif name == 'StackName': - self.stack_name = value - elif name == 'CreationTime': - try: - self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - except ValueError: - self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - elif name == "DeletionTime": - try: - self.deletion_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - except ValueError: - self.deletion_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - elif name == 'TemplateDescription': - self.template_description = value - elif name == "member": - pass - else: - setattr(self, name, value) - - -class Parameter(object): - def __init__(self, connection=None): - self.connection = None - self.key = None - self.value = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == "ParameterKey": - self.key = value - elif name == "ParameterValue": - self.value = value - else: - setattr(self, name, value) - - def __repr__(self): - return "Parameter:\"%s\"=\"%s\"" % (self.key, self.value) - - -class Output(object): - def __init__(self, connection=None): - self.connection = connection - self.description = None - self.key = None - self.value = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == "Description": - self.description = value - elif name == "OutputKey": - self.key = value - elif name == "OutputValue": - self.value = value - else: - setattr(self, name, value) - - def __repr__(self): - return "Output:\"%s\"=\"%s\"" % (self.key, self.value) - - -class Capability(object): - def __init__(self, connection=None): - self.connection = None - self.value = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - self.value = value - - def __repr__(self): - return "Capability:\"%s\"" % (self.value) - - -class Tag(dict): - - def __init__(self, connection=None): - dict.__init__(self) - self.connection = connection - self._current_key = None - self._current_value = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == "Key": - self._current_key = value - elif name == "Value": - self._current_value = value - else: - setattr(self, name, value) - - if self._current_key and self._current_value: - self[self._current_key] = self._current_value - self._current_key = None - self._current_value = None - - -class NotificationARN(object): - def __init__(self, connection=None): - self.connection = None - self.value = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - self.value = value - - def __repr__(self): - return "NotificationARN:\"%s\"" % (self.value) - - -class StackResource(object): - def __init__(self, connection=None): - self.connection = connection - self.description = None - self.logical_resource_id = None - self.physical_resource_id = None - self.resource_status = None - self.resource_status_reason = None - self.resource_type = None - self.stack_id = None - self.stack_name = None - self.timestamp = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == "Description": - self.description = value - elif name == "LogicalResourceId": - self.logical_resource_id = value - elif name == "PhysicalResourceId": - self.physical_resource_id = value - elif name == "ResourceStatus": - self.resource_status = value - elif name == "ResourceStatusReason": - self.resource_status_reason = value - elif name == "ResourceType": - self.resource_type = value - elif name == "StackId": - self.stack_id = value - elif name == "StackName": - self.stack_name = value - elif name == "Timestamp": - try: - self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - except ValueError: - self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - else: - setattr(self, name, value) - - def __repr__(self): - return "StackResource:%s (%s)" % (self.logical_resource_id, - self.resource_type) - - -class StackResourceSummary(object): - def __init__(self, connection=None): - self.connection = connection - self.last_updated_time = None - self.logical_resource_id = None - self.physical_resource_id = None - self.resource_status = None - self.resource_status_reason = None - self.resource_type = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == "LastUpdatedTime": - try: - self.last_updated_time = datetime.strptime( - value, - '%Y-%m-%dT%H:%M:%SZ' - ) - except ValueError: - self.last_updated_time = datetime.strptime( - value, - '%Y-%m-%dT%H:%M:%S.%fZ' - ) - elif name == "LogicalResourceId": - self.logical_resource_id = value - elif name == "PhysicalResourceId": - self.physical_resource_id = value - elif name == "ResourceStatus": - self.resource_status = value - elif name == "ResourceStatusReason": - self.resource_status_reason = value - elif name == "ResourceType": - self.resource_type = value - else: - setattr(self, name, value) - - def __repr__(self): - return "StackResourceSummary:%s (%s)" % (self.logical_resource_id, - self.resource_type) - - -class StackEvent(object): - valid_states = ("CREATE_IN_PROGRESS", "CREATE_FAILED", "CREATE_COMPLETE", - "DELETE_IN_PROGRESS", "DELETE_FAILED", "DELETE_COMPLETE") - def __init__(self, connection=None): - self.connection = connection - self.event_id = None - self.logical_resource_id = None - self.physical_resource_id = None - self.resource_properties = None - self.resource_status = None - self.resource_status_reason = None - self.resource_type = None - self.stack_id = None - self.stack_name = None - self.timestamp = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == "EventId": - self.event_id = value - elif name == "LogicalResourceId": - self.logical_resource_id = value - elif name == "PhysicalResourceId": - self.physical_resource_id = value - elif name == "ResourceProperties": - self.resource_properties = value - elif name == "ResourceStatus": - self.resource_status = value - elif name == "ResourceStatusReason": - self.resource_status_reason = value - elif name == "ResourceType": - self.resource_type = value - elif name == "StackId": - self.stack_id = value - elif name == "StackName": - self.stack_name = value - elif name == "Timestamp": - try: - self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - except ValueError: - self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - else: - setattr(self, name, value) - - def __repr__(self): - return "StackEvent %s %s %s" % (self.resource_type, - self.logical_resource_id, self.resource_status) diff --git a/awx/lib/site-packages/boto/cloudformation/template.py b/awx/lib/site-packages/boto/cloudformation/template.py deleted file mode 100644 index bab2148630..0000000000 --- a/awx/lib/site-packages/boto/cloudformation/template.py +++ /dev/null @@ -1,51 +0,0 @@ -from boto.resultset import ResultSet -from boto.cloudformation.stack import Capability - -class Template(object): - def __init__(self, connection=None): - self.connection = connection - self.description = None - self.template_parameters = None - self.capabilities_reason = None - self.capabilities = None - - def startElement(self, name, attrs, connection): - if name == "Parameters": - self.template_parameters = ResultSet([('member', TemplateParameter)]) - return self.template_parameters - elif name == "Capabilities": - self.capabilities = ResultSet([('member', Capability)]) - return self.capabilities - else: - return None - - def endElement(self, name, value, connection): - if name == "Description": - self.description = value - elif name == "CapabilitiesReason": - self.capabilities_reason = value - else: - setattr(self, name, value) - -class TemplateParameter(object): - def __init__(self, parent): - self.parent = parent - self.default_value = None - self.description = None - self.no_echo = None - self.parameter_key = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == "DefaultValue": - self.default_value = value - elif name == "Description": - self.description = value - elif name == "NoEcho": - self.no_echo = bool(value) - elif name == "ParameterKey": - self.parameter_key = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/cloudfront/__init__.py b/awx/lib/site-packages/boto/cloudfront/__init__.py deleted file mode 100644 index 1afefebbf3..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/__init__.py +++ /dev/null @@ -1,326 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import xml.sax -import time -import boto -from boto.connection import AWSAuthConnection -from boto import handler -from boto.cloudfront.distribution import Distribution, DistributionSummary, DistributionConfig -from boto.cloudfront.distribution import StreamingDistribution, StreamingDistributionSummary, StreamingDistributionConfig -from boto.cloudfront.identity import OriginAccessIdentity -from boto.cloudfront.identity import OriginAccessIdentitySummary -from boto.cloudfront.identity import OriginAccessIdentityConfig -from boto.cloudfront.invalidation import InvalidationBatch, InvalidationSummary, InvalidationListResultSet -from boto.resultset import ResultSet -from boto.cloudfront.exception import CloudFrontServerError - - -class CloudFrontConnection(AWSAuthConnection): - - DefaultHost = 'cloudfront.amazonaws.com' - Version = '2010-11-01' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - port=None, proxy=None, proxy_port=None, - host=DefaultHost, debug=0, security_token=None, - validate_certs=True, profile_name=None, https_connection_factory=None): - super(CloudFrontConnection, self).__init__(host, - aws_access_key_id, aws_secret_access_key, - True, port, proxy, proxy_port, debug=debug, - security_token=security_token, - validate_certs=validate_certs, - https_connection_factory=https_connection_factory, - profile_name=profile_name) - - def get_etag(self, response): - response_headers = response.msg - for key in response_headers.keys(): - if key.lower() == 'etag': - return response_headers[key] - return None - - def _required_auth_capability(self): - return ['cloudfront'] - - # Generics - - def _get_all_objects(self, resource, tags, result_set_class=None, - result_set_kwargs=None): - if not tags: - tags = [('DistributionSummary', DistributionSummary)] - response = self.make_request('GET', '/%s/%s' % (self.Version, - resource)) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise CloudFrontServerError(response.status, response.reason, body) - rs_class = result_set_class or ResultSet - rs_kwargs = result_set_kwargs or dict() - rs = rs_class(tags, **rs_kwargs) - h = handler.XmlHandler(rs, self) - xml.sax.parseString(body, h) - return rs - - def _get_info(self, id, resource, dist_class): - uri = '/%s/%s/%s' % (self.Version, resource, id) - response = self.make_request('GET', uri) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise CloudFrontServerError(response.status, response.reason, body) - d = dist_class(connection=self) - response_headers = response.msg - for key in response_headers.keys(): - if key.lower() == 'etag': - d.etag = response_headers[key] - h = handler.XmlHandler(d, self) - xml.sax.parseString(body, h) - return d - - def _get_config(self, id, resource, config_class): - uri = '/%s/%s/%s/config' % (self.Version, resource, id) - response = self.make_request('GET', uri) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise CloudFrontServerError(response.status, response.reason, body) - d = config_class(connection=self) - d.etag = self.get_etag(response) - h = handler.XmlHandler(d, self) - xml.sax.parseString(body, h) - return d - - def _set_config(self, distribution_id, etag, config): - if isinstance(config, StreamingDistributionConfig): - resource = 'streaming-distribution' - else: - resource = 'distribution' - uri = '/%s/%s/%s/config' % (self.Version, resource, distribution_id) - headers = {'If-Match': etag, 'Content-Type': 'text/xml'} - response = self.make_request('PUT', uri, headers, config.to_xml()) - body = response.read() - boto.log.debug(body) - if response.status != 200: - raise CloudFrontServerError(response.status, response.reason, body) - return self.get_etag(response) - - def _create_object(self, config, resource, dist_class): - response = self.make_request('POST', '/%s/%s' % (self.Version, - resource), - {'Content-Type': 'text/xml'}, - data=config.to_xml()) - body = response.read() - boto.log.debug(body) - if response.status == 201: - d = dist_class(connection=self) - h = handler.XmlHandler(d, self) - xml.sax.parseString(body, h) - d.etag = self.get_etag(response) - return d - else: - raise CloudFrontServerError(response.status, response.reason, body) - - def _delete_object(self, id, etag, resource): - uri = '/%s/%s/%s' % (self.Version, resource, id) - response = self.make_request('DELETE', uri, {'If-Match': etag}) - body = response.read() - boto.log.debug(body) - if response.status != 204: - raise CloudFrontServerError(response.status, response.reason, body) - - # Distributions - - def get_all_distributions(self): - tags = [('DistributionSummary', DistributionSummary)] - return self._get_all_objects('distribution', tags) - - def get_distribution_info(self, distribution_id): - return self._get_info(distribution_id, 'distribution', Distribution) - - def get_distribution_config(self, distribution_id): - return self._get_config(distribution_id, 'distribution', - DistributionConfig) - - def set_distribution_config(self, distribution_id, etag, config): - return self._set_config(distribution_id, etag, config) - - def create_distribution(self, origin, enabled, caller_reference='', - cnames=None, comment='', trusted_signers=None): - config = DistributionConfig(origin=origin, enabled=enabled, - caller_reference=caller_reference, - cnames=cnames, comment=comment, - trusted_signers=trusted_signers) - return self._create_object(config, 'distribution', Distribution) - - def delete_distribution(self, distribution_id, etag): - return self._delete_object(distribution_id, etag, 'distribution') - - # Streaming Distributions - - def get_all_streaming_distributions(self): - tags = [('StreamingDistributionSummary', StreamingDistributionSummary)] - return self._get_all_objects('streaming-distribution', tags) - - def get_streaming_distribution_info(self, distribution_id): - return self._get_info(distribution_id, 'streaming-distribution', - StreamingDistribution) - - def get_streaming_distribution_config(self, distribution_id): - return self._get_config(distribution_id, 'streaming-distribution', - StreamingDistributionConfig) - - def set_streaming_distribution_config(self, distribution_id, etag, config): - return self._set_config(distribution_id, etag, config) - - def create_streaming_distribution(self, origin, enabled, - caller_reference='', - cnames=None, comment='', - trusted_signers=None): - config = StreamingDistributionConfig(origin=origin, enabled=enabled, - caller_reference=caller_reference, - cnames=cnames, comment=comment, - trusted_signers=trusted_signers) - return self._create_object(config, 'streaming-distribution', - StreamingDistribution) - - def delete_streaming_distribution(self, distribution_id, etag): - return self._delete_object(distribution_id, etag, - 'streaming-distribution') - - # Origin Access Identity - - def get_all_origin_access_identity(self): - tags = [('CloudFrontOriginAccessIdentitySummary', - OriginAccessIdentitySummary)] - return self._get_all_objects('origin-access-identity/cloudfront', tags) - - def get_origin_access_identity_info(self, access_id): - return self._get_info(access_id, 'origin-access-identity/cloudfront', - OriginAccessIdentity) - - def get_origin_access_identity_config(self, access_id): - return self._get_config(access_id, - 'origin-access-identity/cloudfront', - OriginAccessIdentityConfig) - - def set_origin_access_identity_config(self, access_id, - etag, config): - return self._set_config(access_id, etag, config) - - def create_origin_access_identity(self, caller_reference='', comment=''): - config = OriginAccessIdentityConfig(caller_reference=caller_reference, - comment=comment) - return self._create_object(config, 'origin-access-identity/cloudfront', - OriginAccessIdentity) - - def delete_origin_access_identity(self, access_id, etag): - return self._delete_object(access_id, etag, - 'origin-access-identity/cloudfront') - - # Object Invalidation - - def create_invalidation_request(self, distribution_id, paths, - caller_reference=None): - """Creates a new invalidation request - :see: http://goo.gl/8vECq - """ - # We allow you to pass in either an array or - # an InvalidationBatch object - if not isinstance(paths, InvalidationBatch): - paths = InvalidationBatch(paths) - paths.connection = self - uri = '/%s/distribution/%s/invalidation' % (self.Version, - distribution_id) - response = self.make_request('POST', uri, - {'Content-Type': 'text/xml'}, - data=paths.to_xml()) - body = response.read() - if response.status == 201: - h = handler.XmlHandler(paths, self) - xml.sax.parseString(body, h) - return paths - else: - raise CloudFrontServerError(response.status, response.reason, body) - - def invalidation_request_status(self, distribution_id, - request_id, caller_reference=None): - uri = '/%s/distribution/%s/invalidation/%s' % (self.Version, - distribution_id, - request_id) - response = self.make_request('GET', uri, {'Content-Type': 'text/xml'}) - body = response.read() - if response.status == 200: - paths = InvalidationBatch([]) - h = handler.XmlHandler(paths, self) - xml.sax.parseString(body, h) - return paths - else: - raise CloudFrontServerError(response.status, response.reason, body) - - def get_invalidation_requests(self, distribution_id, marker=None, - max_items=None): - """ - Get all invalidation requests for a given CloudFront distribution. - This returns an instance of an InvalidationListResultSet that - automatically handles all of the result paging, etc. from CF - you just - need to keep iterating until there are no more results. - - :type distribution_id: string - :param distribution_id: The id of the CloudFront distribution - - :type marker: string - :param marker: Use this only when paginating results and only in - follow-up request after you've received a response where - the results are truncated. Set this to the value of the - Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results and only in a - follow-up request to indicate the maximum number of - invalidation requests you want in the response. You - will need to pass the next_marker property from the - previous InvalidationListResultSet response in the - follow-up request in order to get the next 'page' of - results. - - :rtype: :class:`boto.cloudfront.invalidation.InvalidationListResultSet` - :returns: An InvalidationListResultSet iterator that lists invalidation - requests for a given CloudFront distribution. Automatically - handles paging the results. - """ - uri = 'distribution/%s/invalidation' % distribution_id - params = dict() - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - if params: - uri += '?%s=%s' % params.popitem() - for k, v in params.items(): - uri += '&%s=%s' % (k, v) - tags=[('InvalidationSummary', InvalidationSummary)] - rs_class = InvalidationListResultSet - rs_kwargs = dict(connection=self, distribution_id=distribution_id, - max_items=max_items, marker=marker) - return self._get_all_objects(uri, tags, result_set_class=rs_class, - result_set_kwargs=rs_kwargs) diff --git a/awx/lib/site-packages/boto/cloudfront/distribution.py b/awx/lib/site-packages/boto/cloudfront/distribution.py deleted file mode 100644 index 7131c86c83..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/distribution.py +++ /dev/null @@ -1,757 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import uuid -import base64 -import time -from boto.compat import six, json -from boto.cloudfront.identity import OriginAccessIdentity -from boto.cloudfront.object import Object, StreamingObject -from boto.cloudfront.signers import ActiveTrustedSigners, TrustedSigners -from boto.cloudfront.logging import LoggingInfo -from boto.cloudfront.origin import S3Origin, CustomOrigin -from boto.s3.acl import ACL - -class DistributionConfig(object): - - def __init__(self, connection=None, origin=None, enabled=False, - caller_reference='', cnames=None, comment='', - trusted_signers=None, default_root_object=None, - logging=None): - """ - :param origin: Origin information to associate with the - distribution. If your distribution will use - an Amazon S3 origin, then this should be an - S3Origin object. If your distribution will use - a custom origin (non Amazon S3), then this - should be a CustomOrigin object. - :type origin: :class:`boto.cloudfront.origin.S3Origin` or - :class:`boto.cloudfront.origin.CustomOrigin` - - :param enabled: Whether the distribution is enabled to accept - end user requests for content. - :type enabled: bool - - :param caller_reference: A unique number that ensures the - request can't be replayed. If no - caller_reference is provided, boto - will generate a type 4 UUID for use - as the caller reference. - :type enabled: str - - :param cnames: A CNAME alias you want to associate with this - distribution. You can have up to 10 CNAME aliases - per distribution. - :type enabled: array of str - - :param comment: Any comments you want to include about the - distribution. - :type comment: str - - :param trusted_signers: Specifies any AWS accounts you want to - permit to create signed URLs for private - content. If you want the distribution to - use signed URLs, this should contain a - TrustedSigners object; if you want the - distribution to use basic URLs, leave - this None. - :type trusted_signers: :class`boto.cloudfront.signers.TrustedSigners` - - :param default_root_object: Designates a default root object. - Only include a DefaultRootObject value - if you are going to assign a default - root object for the distribution. - :type comment: str - - :param logging: Controls whether access logs are written for the - distribution. If you want to turn on access logs, - this should contain a LoggingInfo object; otherwise - it should contain None. - :type logging: :class`boto.cloudfront.logging.LoggingInfo` - - """ - self.connection = connection - self.origin = origin - self.enabled = enabled - if caller_reference: - self.caller_reference = caller_reference - else: - self.caller_reference = str(uuid.uuid4()) - self.cnames = [] - if cnames: - self.cnames = cnames - self.comment = comment - self.trusted_signers = trusted_signers - self.logging = logging - self.default_root_object = default_root_object - - def __repr__(self): - return "DistributionConfig:%s" % self.origin - - def to_xml(self): - s = '<?xml version="1.0" encoding="UTF-8"?>\n' - s += '<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-07-15/">\n' - if self.origin: - s += self.origin.to_xml() - s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference - for cname in self.cnames: - s += ' <CNAME>%s</CNAME>\n' % cname - if self.comment: - s += ' <Comment>%s</Comment>\n' % self.comment - s += ' <Enabled>' - if self.enabled: - s += 'true' - else: - s += 'false' - s += '</Enabled>\n' - if self.trusted_signers: - s += '<TrustedSigners>\n' - for signer in self.trusted_signers: - if signer == 'Self': - s += ' <Self></Self>\n' - else: - s += ' <AwsAccountNumber>%s</AwsAccountNumber>\n' % signer - s += '</TrustedSigners>\n' - if self.logging: - s += '<Logging>\n' - s += ' <Bucket>%s</Bucket>\n' % self.logging.bucket - s += ' <Prefix>%s</Prefix>\n' % self.logging.prefix - s += '</Logging>\n' - if self.default_root_object: - dro = self.default_root_object - s += '<DefaultRootObject>%s</DefaultRootObject>\n' % dro - s += '</DistributionConfig>\n' - return s - - def startElement(self, name, attrs, connection): - if name == 'TrustedSigners': - self.trusted_signers = TrustedSigners() - return self.trusted_signers - elif name == 'Logging': - self.logging = LoggingInfo() - return self.logging - elif name == 'S3Origin': - self.origin = S3Origin() - return self.origin - elif name == 'CustomOrigin': - self.origin = CustomOrigin() - return self.origin - else: - return None - - def endElement(self, name, value, connection): - if name == 'CNAME': - self.cnames.append(value) - elif name == 'Comment': - self.comment = value - elif name == 'Enabled': - if value.lower() == 'true': - self.enabled = True - else: - self.enabled = False - elif name == 'CallerReference': - self.caller_reference = value - elif name == 'DefaultRootObject': - self.default_root_object = value - else: - setattr(self, name, value) - -class StreamingDistributionConfig(DistributionConfig): - - def __init__(self, connection=None, origin='', enabled=False, - caller_reference='', cnames=None, comment='', - trusted_signers=None, logging=None): - super(StreamingDistributionConfig, self).__init__(connection=connection, - origin=origin, enabled=enabled, - caller_reference=caller_reference, - cnames=cnames, comment=comment, - trusted_signers=trusted_signers, - logging=logging) - def to_xml(self): - s = '<?xml version="1.0" encoding="UTF-8"?>\n' - s += '<StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-07-15/">\n' - if self.origin: - s += self.origin.to_xml() - s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference - for cname in self.cnames: - s += ' <CNAME>%s</CNAME>\n' % cname - if self.comment: - s += ' <Comment>%s</Comment>\n' % self.comment - s += ' <Enabled>' - if self.enabled: - s += 'true' - else: - s += 'false' - s += '</Enabled>\n' - if self.trusted_signers: - s += '<TrustedSigners>\n' - for signer in self.trusted_signers: - if signer == 'Self': - s += ' <Self/>\n' - else: - s += ' <AwsAccountNumber>%s</AwsAccountNumber>\n' % signer - s += '</TrustedSigners>\n' - if self.logging: - s += '<Logging>\n' - s += ' <Bucket>%s</Bucket>\n' % self.logging.bucket - s += ' <Prefix>%s</Prefix>\n' % self.logging.prefix - s += '</Logging>\n' - s += '</StreamingDistributionConfig>\n' - return s - -class DistributionSummary(object): - - def __init__(self, connection=None, domain_name='', id='', - last_modified_time=None, status='', origin=None, - cname='', comment='', enabled=False): - self.connection = connection - self.domain_name = domain_name - self.id = id - self.last_modified_time = last_modified_time - self.status = status - self.origin = origin - self.enabled = enabled - self.cnames = [] - if cname: - self.cnames.append(cname) - self.comment = comment - self.trusted_signers = None - self.etag = None - self.streaming = False - - def __repr__(self): - return "DistributionSummary:%s" % self.domain_name - - def startElement(self, name, attrs, connection): - if name == 'TrustedSigners': - self.trusted_signers = TrustedSigners() - return self.trusted_signers - elif name == 'S3Origin': - self.origin = S3Origin() - return self.origin - elif name == 'CustomOrigin': - self.origin = CustomOrigin() - return self.origin - return None - - def endElement(self, name, value, connection): - if name == 'Id': - self.id = value - elif name == 'Status': - self.status = value - elif name == 'LastModifiedTime': - self.last_modified_time = value - elif name == 'DomainName': - self.domain_name = value - elif name == 'Origin': - self.origin = value - elif name == 'CNAME': - self.cnames.append(value) - elif name == 'Comment': - self.comment = value - elif name == 'Enabled': - if value.lower() == 'true': - self.enabled = True - else: - self.enabled = False - elif name == 'StreamingDistributionSummary': - self.streaming = True - else: - setattr(self, name, value) - - def get_distribution(self): - return self.connection.get_distribution_info(self.id) - -class StreamingDistributionSummary(DistributionSummary): - - def get_distribution(self): - return self.connection.get_streaming_distribution_info(self.id) - -class Distribution(object): - - def __init__(self, connection=None, config=None, domain_name='', - id='', last_modified_time=None, status=''): - self.connection = connection - self.config = config - self.domain_name = domain_name - self.id = id - self.last_modified_time = last_modified_time - self.status = status - self.in_progress_invalidation_batches = 0 - self.active_signers = None - self.etag = None - self._bucket = None - self._object_class = Object - - def __repr__(self): - return "Distribution:%s" % self.domain_name - - def startElement(self, name, attrs, connection): - if name == 'DistributionConfig': - self.config = DistributionConfig() - return self.config - elif name == 'ActiveTrustedSigners': - self.active_signers = ActiveTrustedSigners() - return self.active_signers - else: - return None - - def endElement(self, name, value, connection): - if name == 'Id': - self.id = value - elif name == 'LastModifiedTime': - self.last_modified_time = value - elif name == 'Status': - self.status = value - elif name == 'InProgressInvalidationBatches': - self.in_progress_invalidation_batches = int(value) - elif name == 'DomainName': - self.domain_name = value - else: - setattr(self, name, value) - - def update(self, enabled=None, cnames=None, comment=None): - """ - Update the configuration of the Distribution. The only values - of the DistributionConfig that can be directly updated are: - - * CNAMES - * Comment - * Whether the Distribution is enabled or not - - Any changes to the ``trusted_signers`` or ``origin`` properties of - this distribution's current config object will also be included in - the update. Therefore, to set the origin access identity for this - distribution, set ``Distribution.config.origin.origin_access_identity`` - before calling this update method. - - :type enabled: bool - :param enabled: Whether the Distribution is active or not. - - :type cnames: list of str - :param cnames: The DNS CNAME's associated with this - Distribution. Maximum of 10 values. - - :type comment: str or unicode - :param comment: The comment associated with the Distribution. - - """ - new_config = DistributionConfig(self.connection, self.config.origin, - self.config.enabled, self.config.caller_reference, - self.config.cnames, self.config.comment, - self.config.trusted_signers, - self.config.default_root_object) - if enabled is not None: - new_config.enabled = enabled - if cnames is not None: - new_config.cnames = cnames - if comment is not None: - new_config.comment = comment - self.etag = self.connection.set_distribution_config(self.id, self.etag, new_config) - self.config = new_config - self._object_class = Object - - def enable(self): - """ - Activate the Distribution. A convenience wrapper around - the update method. - """ - self.update(enabled=True) - - def disable(self): - """ - Deactivate the Distribution. A convenience wrapper around - the update method. - """ - self.update(enabled=False) - - def delete(self): - """ - Delete this CloudFront Distribution. The content - associated with the Distribution is not deleted from - the underlying Origin bucket in S3. - """ - self.connection.delete_distribution(self.id, self.etag) - - def _get_bucket(self): - if isinstance(self.config.origin, S3Origin): - if not self._bucket: - bucket_dns_name = self.config.origin.dns_name - bucket_name = bucket_dns_name.replace('.s3.amazonaws.com', '') - from boto.s3.connection import S3Connection - s3 = S3Connection(self.connection.aws_access_key_id, - self.connection.aws_secret_access_key, - proxy=self.connection.proxy, - proxy_port=self.connection.proxy_port, - proxy_user=self.connection.proxy_user, - proxy_pass=self.connection.proxy_pass) - self._bucket = s3.get_bucket(bucket_name) - self._bucket.distribution = self - self._bucket.set_key_class(self._object_class) - return self._bucket - else: - raise NotImplementedError('Unable to get_objects on CustomOrigin') - - def get_objects(self): - """ - Return a list of all content objects in this distribution. - - :rtype: list of :class:`boto.cloudfront.object.Object` - :return: The content objects - """ - bucket = self._get_bucket() - objs = [] - for key in bucket: - objs.append(key) - return objs - - def set_permissions(self, object, replace=False): - """ - Sets the S3 ACL grants for the given object to the appropriate - value based on the type of Distribution. If the Distribution - is serving private content the ACL will be set to include the - Origin Access Identity associated with the Distribution. If - the Distribution is serving public content the content will - be set up with "public-read". - - :type object: :class:`boto.cloudfront.object.Object` - :param enabled: The Object whose ACL is being set - - :type replace: bool - :param replace: If False, the Origin Access Identity will be - appended to the existing ACL for the object. - If True, the ACL for the object will be - completely replaced with one that grants - READ permission to the Origin Access Identity. - - """ - if isinstance(self.config.origin, S3Origin): - if self.config.origin.origin_access_identity: - id = self.config.origin.origin_access_identity.split('/')[-1] - oai = self.connection.get_origin_access_identity_info(id) - policy = object.get_acl() - if replace: - policy.acl = ACL() - policy.acl.add_user_grant('READ', oai.s3_user_id) - object.set_acl(policy) - else: - object.set_canned_acl('public-read') - - def set_permissions_all(self, replace=False): - """ - Sets the S3 ACL grants for all objects in the Distribution - to the appropriate value based on the type of Distribution. - - :type replace: bool - :param replace: If False, the Origin Access Identity will be - appended to the existing ACL for the object. - If True, the ACL for the object will be - completely replaced with one that grants - READ permission to the Origin Access Identity. - - """ - bucket = self._get_bucket() - for key in bucket: - self.set_permissions(key, replace) - - def add_object(self, name, content, headers=None, replace=True): - """ - Adds a new content object to the Distribution. The content - for the object will be copied to a new Key in the S3 Bucket - and the permissions will be set appropriately for the type - of Distribution. - - :type name: str or unicode - :param name: The name or key of the new object. - - :type content: file-like object - :param content: A file-like object that contains the content - for the new object. - - :type headers: dict - :param headers: A dictionary containing additional headers - you would like associated with the new - object in S3. - - :rtype: :class:`boto.cloudfront.object.Object` - :return: The newly created object. - """ - if self.config.origin.origin_access_identity: - policy = 'private' - else: - policy = 'public-read' - bucket = self._get_bucket() - object = bucket.new_key(name) - object.set_contents_from_file(content, headers=headers, policy=policy) - if self.config.origin.origin_access_identity: - self.set_permissions(object, replace) - return object - - def create_signed_url(self, url, keypair_id, - expire_time=None, valid_after_time=None, - ip_address=None, policy_url=None, - private_key_file=None, private_key_string=None): - """ - Creates a signed CloudFront URL that is only valid within the specified - parameters. - - :type url: str - :param url: The URL of the protected object. - - :type keypair_id: str - :param keypair_id: The keypair ID of the Amazon KeyPair used to sign - theURL. This ID MUST correspond to the private key - specified with private_key_file or private_key_string. - - :type expire_time: int - :param expire_time: The expiry time of the URL. If provided, the URL - will expire after the time has passed. If not provided the URL will - never expire. Format is a unix epoch. - Use time.time() + duration_in_sec. - - :type valid_after_time: int - :param valid_after_time: If provided, the URL will not be valid until - after valid_after_time. Format is a unix epoch. - Use time.time() + secs_until_valid. - - :type ip_address: str - :param ip_address: If provided, only allows access from the specified - IP address. Use '192.168.0.10' for a single IP or - use '192.168.0.0/24' CIDR notation for a subnet. - - :type policy_url: str - :param policy_url: If provided, allows the signature to contain - wildcard globs in the URL. For example, you could - provide: 'http://example.com/media/\*' and the policy - and signature would allow access to all contents of - the media subdirectory. If not specified, only - allow access to the exact url provided in 'url'. - - :type private_key_file: str or file object. - :param private_key_file: If provided, contains the filename of the - private key file used for signing or an open - file object containing the private key - contents. Only one of private_key_file or - private_key_string can be provided. - - :type private_key_string: str - :param private_key_string: If provided, contains the private key string - used for signing. Only one of private_key_file or - private_key_string can be provided. - - :rtype: str - :return: The signed URL. - """ - # Get the required parameters - params = self._create_signing_params( - url=url, keypair_id=keypair_id, expire_time=expire_time, - valid_after_time=valid_after_time, ip_address=ip_address, - policy_url=policy_url, private_key_file=private_key_file, - private_key_string=private_key_string) - - #combine these into a full url - if "?" in url: - sep = "&" - else: - sep = "?" - signed_url_params = [] - for key in ["Expires", "Policy", "Signature", "Key-Pair-Id"]: - if key in params: - param = "%s=%s" % (key, params[key]) - signed_url_params.append(param) - signed_url = url + sep + "&".join(signed_url_params) - return signed_url - - def _create_signing_params(self, url, keypair_id, - expire_time=None, valid_after_time=None, - ip_address=None, policy_url=None, - private_key_file=None, private_key_string=None): - """ - Creates the required URL parameters for a signed URL. - """ - params = {} - # Check if we can use a canned policy - if expire_time and not valid_after_time and not ip_address and not policy_url: - # we manually construct this policy string to ensure formatting - # matches signature - policy = self._canned_policy(url, expire_time) - params["Expires"] = str(expire_time) - else: - # If no policy_url is specified, default to the full url. - if policy_url is None: - policy_url = url - # Can't use canned policy - policy = self._custom_policy(policy_url, expires=expire_time, - valid_after=valid_after_time, - ip_address=ip_address) - - encoded_policy = self._url_base64_encode(policy) - params["Policy"] = encoded_policy - #sign the policy - signature = self._sign_string(policy, private_key_file, private_key_string) - #now base64 encode the signature (URL safe as well) - encoded_signature = self._url_base64_encode(signature) - params["Signature"] = encoded_signature - params["Key-Pair-Id"] = keypair_id - return params - - @staticmethod - def _canned_policy(resource, expires): - """ - Creates a canned policy string. - """ - policy = ('{"Statement":[{"Resource":"%(resource)s",' - '"Condition":{"DateLessThan":{"AWS:EpochTime":' - '%(expires)s}}}]}' % locals()) - return policy - - @staticmethod - def _custom_policy(resource, expires=None, valid_after=None, ip_address=None): - """ - Creates a custom policy string based on the supplied parameters. - """ - condition = {} - # SEE: http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RestrictingAccessPrivateContent.html#CustomPolicy - # The 'DateLessThan' property is required. - if not expires: - # Defaults to ONE day - expires = int(time.time()) + 86400 - condition["DateLessThan"] = {"AWS:EpochTime": expires} - if valid_after: - condition["DateGreaterThan"] = {"AWS:EpochTime": valid_after} - if ip_address: - if '/' not in ip_address: - ip_address += "/32" - condition["IpAddress"] = {"AWS:SourceIp": ip_address} - policy = {"Statement": [{ - "Resource": resource, - "Condition": condition}]} - return json.dumps(policy, separators=(",", ":")) - - @staticmethod - def _sign_string(message, private_key_file=None, private_key_string=None): - """ - Signs a string for use with Amazon CloudFront. - Requires the rsa library be installed. - """ - try: - import rsa - except ImportError: - raise NotImplementedError("Boto depends on the python rsa " - "library to generate signed URLs for " - "CloudFront") - # Make sure only one of private_key_file and private_key_string is set - if private_key_file and private_key_string: - raise ValueError("Only specify the private_key_file or the private_key_string not both") - if not private_key_file and not private_key_string: - raise ValueError("You must specify one of private_key_file or private_key_string") - # If private_key_file is a file name, open it and read it - if private_key_string is None: - if isinstance(private_key_file, six.string_types): - with open(private_key_file, 'r') as file_handle: - private_key_string = file_handle.read() - # Otherwise, treat it like a file - else: - private_key_string = private_key_file.read() - - # Sign it! - private_key = rsa.PrivateKey.load_pkcs1(private_key_string) - signature = rsa.sign(str(message), private_key, 'SHA-1') - return signature - - @staticmethod - def _url_base64_encode(msg): - """ - Base64 encodes a string using the URL-safe characters specified by - Amazon. - """ - msg_base64 = base64.b64encode(msg) - msg_base64 = msg_base64.replace('+', '-') - msg_base64 = msg_base64.replace('=', '_') - msg_base64 = msg_base64.replace('/', '~') - return msg_base64 - -class StreamingDistribution(Distribution): - - def __init__(self, connection=None, config=None, domain_name='', - id='', last_modified_time=None, status=''): - super(StreamingDistribution, self).__init__(connection, config, - domain_name, id, last_modified_time, status) - self._object_class = StreamingObject - - def startElement(self, name, attrs, connection): - if name == 'StreamingDistributionConfig': - self.config = StreamingDistributionConfig() - return self.config - else: - return super(StreamingDistribution, self).startElement(name, attrs, - connection) - - def update(self, enabled=None, cnames=None, comment=None): - """ - Update the configuration of the StreamingDistribution. The only values - of the StreamingDistributionConfig that can be directly updated are: - - * CNAMES - * Comment - * Whether the Distribution is enabled or not - - Any changes to the ``trusted_signers`` or ``origin`` properties of - this distribution's current config object will also be included in - the update. Therefore, to set the origin access identity for this - distribution, set - ``StreamingDistribution.config.origin.origin_access_identity`` - before calling this update method. - - :type enabled: bool - :param enabled: Whether the StreamingDistribution is active or not. - - :type cnames: list of str - :param cnames: The DNS CNAME's associated with this - Distribution. Maximum of 10 values. - - :type comment: str or unicode - :param comment: The comment associated with the Distribution. - - """ - new_config = StreamingDistributionConfig(self.connection, - self.config.origin, - self.config.enabled, - self.config.caller_reference, - self.config.cnames, - self.config.comment, - self.config.trusted_signers) - if enabled is not None: - new_config.enabled = enabled - if cnames is not None: - new_config.cnames = cnames - if comment is not None: - new_config.comment = comment - self.etag = self.connection.set_streaming_distribution_config(self.id, - self.etag, - new_config) - self.config = new_config - self._object_class = StreamingObject - - def delete(self): - self.connection.delete_streaming_distribution(self.id, self.etag) - - diff --git a/awx/lib/site-packages/boto/cloudfront/exception.py b/awx/lib/site-packages/boto/cloudfront/exception.py deleted file mode 100644 index 768064210c..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/exception.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.exception import BotoServerError - -class CloudFrontServerError(BotoServerError): - - pass diff --git a/awx/lib/site-packages/boto/cloudfront/identity.py b/awx/lib/site-packages/boto/cloudfront/identity.py deleted file mode 100644 index de79c8ac76..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/identity.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import uuid - -class OriginAccessIdentity(object): - def __init__(self, connection=None, config=None, id='', - s3_user_id='', comment=''): - self.connection = connection - self.config = config - self.id = id - self.s3_user_id = s3_user_id - self.comment = comment - self.etag = None - - def startElement(self, name, attrs, connection): - if name == 'CloudFrontOriginAccessIdentityConfig': - self.config = OriginAccessIdentityConfig() - return self.config - else: - return None - - def endElement(self, name, value, connection): - if name == 'Id': - self.id = value - elif name == 'S3CanonicalUserId': - self.s3_user_id = value - elif name == 'Comment': - self.comment = value - else: - setattr(self, name, value) - - def update(self, comment=None): - new_config = OriginAccessIdentityConfig(self.connection, - self.config.caller_reference, - self.config.comment) - if comment is not None: - new_config.comment = comment - self.etag = self.connection.set_origin_identity_config(self.id, self.etag, new_config) - self.config = new_config - - def delete(self): - return self.connection.delete_origin_access_identity(self.id, self.etag) - - def uri(self): - return 'origin-access-identity/cloudfront/%s' % self.id - - -class OriginAccessIdentityConfig(object): - def __init__(self, connection=None, caller_reference='', comment=''): - self.connection = connection - if caller_reference: - self.caller_reference = caller_reference - else: - self.caller_reference = str(uuid.uuid4()) - self.comment = comment - - def to_xml(self): - s = '<?xml version="1.0" encoding="UTF-8"?>\n' - s += '<CloudFrontOriginAccessIdentityConfig xmlns="http://cloudfront.amazonaws.com/doc/2009-09-09/">\n' - s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference - if self.comment: - s += ' <Comment>%s</Comment>\n' % self.comment - s += '</CloudFrontOriginAccessIdentityConfig>\n' - return s - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Comment': - self.comment = value - elif name == 'CallerReference': - self.caller_reference = value - else: - setattr(self, name, value) - - -class OriginAccessIdentitySummary(object): - def __init__(self, connection=None, id='', - s3_user_id='', comment=''): - self.connection = connection - self.id = id - self.s3_user_id = s3_user_id - self.comment = comment - self.etag = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Id': - self.id = value - elif name == 'S3CanonicalUserId': - self.s3_user_id = value - elif name == 'Comment': - self.comment = value - else: - setattr(self, name, value) - - def get_origin_access_identity(self): - return self.connection.get_origin_access_identity_info(self.id) - diff --git a/awx/lib/site-packages/boto/cloudfront/invalidation.py b/awx/lib/site-packages/boto/cloudfront/invalidation.py deleted file mode 100644 index 58adf81fd3..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/invalidation.py +++ /dev/null @@ -1,216 +0,0 @@ -# Copyright (c) 2006-2010 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import uuid - -from boto.compat import urllib -from boto.resultset import ResultSet - - -class InvalidationBatch(object): - """A simple invalidation request. - :see: http://docs.amazonwebservices.com/AmazonCloudFront/2010-08-01/APIReference/index.html?InvalidationBatchDatatype.html - """ - - def __init__(self, paths=None, connection=None, distribution=None, caller_reference=''): - """Create a new invalidation request: - :paths: An array of paths to invalidate - """ - self.paths = paths or [] - self.distribution = distribution - self.caller_reference = caller_reference - if not self.caller_reference: - self.caller_reference = str(uuid.uuid4()) - - # If we passed in a distribution, - # then we use that as the connection object - if distribution: - self.connection = distribution - else: - self.connection = connection - - def __repr__(self): - return '<InvalidationBatch: %s>' % self.id - - def add(self, path): - """Add another path to this invalidation request""" - return self.paths.append(path) - - def remove(self, path): - """Remove a path from this invalidation request""" - return self.paths.remove(path) - - def __iter__(self): - return iter(self.paths) - - def __getitem__(self, i): - return self.paths[i] - - def __setitem__(self, k, v): - self.paths[k] = v - - def escape(self, p): - """Escape a path, make sure it begins with a slash and contains no invalid characters""" - if not p[0] == "/": - p = "/%s" % p - return urllib.parse.quote(p) - - def to_xml(self): - """Get this batch as XML""" - assert self.connection is not None - s = '<?xml version="1.0" encoding="UTF-8"?>\n' - s += '<InvalidationBatch xmlns="http://cloudfront.amazonaws.com/doc/%s/">\n' % self.connection.Version - for p in self.paths: - s += ' <Path>%s</Path>\n' % self.escape(p) - s += ' <CallerReference>%s</CallerReference>\n' % self.caller_reference - s += '</InvalidationBatch>\n' - return s - - def startElement(self, name, attrs, connection): - if name == "InvalidationBatch": - self.paths = [] - return None - - def endElement(self, name, value, connection): - if name == 'Path': - self.paths.append(value) - elif name == "Status": - self.status = value - elif name == "Id": - self.id = value - elif name == "CreateTime": - self.create_time = value - elif name == "CallerReference": - self.caller_reference = value - return None - - -class InvalidationListResultSet(object): - """ - A resultset for listing invalidations on a given CloudFront distribution. - Implements the iterator interface and transparently handles paging results - from CF so even if you have many thousands of invalidations on the - distribution you can iterate over all invalidations in a reasonably - efficient manner. - """ - def __init__(self, markers=None, connection=None, distribution_id=None, - invalidations=None, marker='', next_marker=None, - max_items=None, is_truncated=False): - self.markers = markers or [] - self.connection = connection - self.distribution_id = distribution_id - self.marker = marker - self.next_marker = next_marker - self.max_items = max_items - self.auto_paginate = max_items is None - self.is_truncated = is_truncated - self._inval_cache = invalidations or [] - - def __iter__(self): - """ - A generator function for listing invalidation requests for a given - CloudFront distribution. - """ - conn = self.connection - distribution_id = self.distribution_id - result_set = self - for inval in result_set._inval_cache: - yield inval - if not self.auto_paginate: - return - while result_set.is_truncated: - result_set = conn.get_invalidation_requests(distribution_id, - marker=result_set.next_marker, - max_items=result_set.max_items) - for i in result_set._inval_cache: - yield i - - def startElement(self, name, attrs, connection): - for root_elem, handler in self.markers: - if name == root_elem: - obj = handler(connection, distribution_id=self.distribution_id) - self._inval_cache.append(obj) - return obj - - def endElement(self, name, value, connection): - if name == 'IsTruncated': - self.is_truncated = self.to_boolean(value) - elif name == 'Marker': - self.marker = value - elif name == 'NextMarker': - self.next_marker = value - elif name == 'MaxItems': - self.max_items = int(value) - - def to_boolean(self, value, true_value='true'): - if value == true_value: - return True - else: - return False - -class InvalidationSummary(object): - """ - Represents InvalidationSummary complex type in CloudFront API that lists - the id and status of a given invalidation request. - """ - def __init__(self, connection=None, distribution_id=None, id='', - status=''): - self.connection = connection - self.distribution_id = distribution_id - self.id = id - self.status = status - - def __repr__(self): - return '<InvalidationSummary: %s>' % self.id - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Id': - self.id = value - elif name == 'Status': - self.status = value - - def get_distribution(self): - """ - Returns a Distribution object representing the parent CloudFront - distribution of the invalidation request listed in the - InvalidationSummary. - - :rtype: :class:`boto.cloudfront.distribution.Distribution` - :returns: A Distribution object representing the parent CloudFront - distribution of the invalidation request listed in the - InvalidationSummary - """ - return self.connection.get_distribution_info(self.distribution_id) - - def get_invalidation_request(self): - """ - Returns an InvalidationBatch object representing the invalidation - request referred to in the InvalidationSummary. - - :rtype: :class:`boto.cloudfront.invalidation.InvalidationBatch` - :returns: An InvalidationBatch object representing the invalidation - request referred to by the InvalidationSummary - """ - return self.connection.invalidation_request_status( - self.distribution_id, self.id) diff --git a/awx/lib/site-packages/boto/cloudfront/logging.py b/awx/lib/site-packages/boto/cloudfront/logging.py deleted file mode 100644 index 6c2f4fde2f..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/logging.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class LoggingInfo(object): - - def __init__(self, bucket='', prefix=''): - self.bucket = bucket - self.prefix = prefix - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Bucket': - self.bucket = value - elif name == 'Prefix': - self.prefix = value - else: - setattr(self, name, value) - diff --git a/awx/lib/site-packages/boto/cloudfront/object.py b/awx/lib/site-packages/boto/cloudfront/object.py deleted file mode 100644 index 24fc85064c..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/object.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.s3.key import Key - -class Object(Key): - - def __init__(self, bucket, name=None): - super(Object, self).__init__(bucket, name=name) - self.distribution = bucket.distribution - - def __repr__(self): - return '<Object: %s/%s>' % (self.distribution.config.origin, self.name) - - def url(self, scheme='http'): - url = '%s://' % scheme - url += self.distribution.domain_name - if scheme.lower().startswith('rtmp'): - url += '/cfx/st/' - else: - url += '/' - url += self.name - return url - -class StreamingObject(Object): - - def url(self, scheme='rtmp'): - return super(StreamingObject, self).url(scheme) - - diff --git a/awx/lib/site-packages/boto/cloudfront/origin.py b/awx/lib/site-packages/boto/cloudfront/origin.py deleted file mode 100644 index b88ec7e7f8..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/origin.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.cloudfront.identity import OriginAccessIdentity - -def get_oai_value(origin_access_identity): - if isinstance(origin_access_identity, OriginAccessIdentity): - return origin_access_identity.uri() - else: - return origin_access_identity - -class S3Origin(object): - """ - Origin information to associate with the distribution. - If your distribution will use an Amazon S3 origin, - then you use the S3Origin element. - """ - - def __init__(self, dns_name=None, origin_access_identity=None): - """ - :param dns_name: The DNS name of your Amazon S3 bucket to - associate with the distribution. - For example: mybucket.s3.amazonaws.com. - :type dns_name: str - - :param origin_access_identity: The CloudFront origin access - identity to associate with the - distribution. If you want the - distribution to serve private content, - include this element; if you want the - distribution to serve public content, - remove this element. - :type origin_access_identity: str - - """ - self.dns_name = dns_name - self.origin_access_identity = origin_access_identity - - def __repr__(self): - return '<S3Origin: %s>' % self.dns_name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'DNSName': - self.dns_name = value - elif name == 'OriginAccessIdentity': - self.origin_access_identity = value - else: - setattr(self, name, value) - - def to_xml(self): - s = ' <S3Origin>\n' - s += ' <DNSName>%s</DNSName>\n' % self.dns_name - if self.origin_access_identity: - val = get_oai_value(self.origin_access_identity) - s += ' <OriginAccessIdentity>%s</OriginAccessIdentity>\n' % val - s += ' </S3Origin>\n' - return s - -class CustomOrigin(object): - """ - Origin information to associate with the distribution. - If your distribution will use a non-Amazon S3 origin, - then you use the CustomOrigin element. - """ - - def __init__(self, dns_name=None, http_port=80, https_port=443, - origin_protocol_policy=None): - """ - :param dns_name: The DNS name of your Amazon S3 bucket to - associate with the distribution. - For example: mybucket.s3.amazonaws.com. - :type dns_name: str - - :param http_port: The HTTP port the custom origin listens on. - :type http_port: int - - :param https_port: The HTTPS port the custom origin listens on. - :type http_port: int - - :param origin_protocol_policy: The origin protocol policy to - apply to your origin. If you - specify http-only, CloudFront - will use HTTP only to access the origin. - If you specify match-viewer, CloudFront - will fetch from your origin using HTTP - or HTTPS, based on the protocol of the - viewer request. - :type origin_protocol_policy: str - - """ - self.dns_name = dns_name - self.http_port = http_port - self.https_port = https_port - self.origin_protocol_policy = origin_protocol_policy - - def __repr__(self): - return '<CustomOrigin: %s>' % self.dns_name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'DNSName': - self.dns_name = value - elif name == 'HTTPPort': - try: - self.http_port = int(value) - except ValueError: - self.http_port = value - elif name == 'HTTPSPort': - try: - self.https_port = int(value) - except ValueError: - self.https_port = value - elif name == 'OriginProtocolPolicy': - self.origin_protocol_policy = value - else: - setattr(self, name, value) - - def to_xml(self): - s = ' <CustomOrigin>\n' - s += ' <DNSName>%s</DNSName>\n' % self.dns_name - s += ' <HTTPPort>%d</HTTPPort>\n' % self.http_port - s += ' <HTTPSPort>%d</HTTPSPort>\n' % self.https_port - s += ' <OriginProtocolPolicy>%s</OriginProtocolPolicy>\n' % self.origin_protocol_policy - s += ' </CustomOrigin>\n' - return s - diff --git a/awx/lib/site-packages/boto/cloudfront/signers.py b/awx/lib/site-packages/boto/cloudfront/signers.py deleted file mode 100644 index dcc9fc9ea3..0000000000 --- a/awx/lib/site-packages/boto/cloudfront/signers.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class Signer(object): - def __init__(self): - self.id = None - self.key_pair_ids = [] - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Self': - self.id = 'Self' - elif name == 'AwsAccountNumber': - self.id = value - elif name == 'KeyPairId': - self.key_pair_ids.append(value) - - -class ActiveTrustedSigners(list): - def startElement(self, name, attrs, connection): - if name == 'Signer': - s = Signer() - self.append(s) - return s - - def endElement(self, name, value, connection): - pass - - -class TrustedSigners(list): - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Self': - self.append(name) - elif name == 'AwsAccountNumber': - self.append(value) - diff --git a/awx/lib/site-packages/boto/cloudsearch/__init__.py b/awx/lib/site-packages/boto/cloudsearch/__init__.py deleted file mode 100644 index 451a6bfab8..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon CloudSearch service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - import boto.cloudsearch.layer1 - return get_regions( - 'cloudsearch', - connection_cls=boto.cloudsearch.layer1.Layer1 - ) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/cloudsearch/document.py b/awx/lib/site-packages/boto/cloudsearch/document.py deleted file mode 100644 index 0a1d9db22c..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/document.py +++ /dev/null @@ -1,271 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto.exception -from boto.compat import json -import requests -import boto - -class SearchServiceException(Exception): - pass - - -class CommitMismatchError(Exception): - pass - -class EncodingError(Exception): - """ - Content sent for Cloud Search indexing was incorrectly encoded. - - This usually happens when a document is marked as unicode but non-unicode - characters are present. - """ - pass - -class ContentTooLongError(Exception): - """ - Content sent for Cloud Search indexing was too long - - This will usually happen when documents queued for indexing add up to more - than the limit allowed per upload batch (5MB) - - """ - pass - -class DocumentServiceConnection(object): - """ - A CloudSearch document service. - - The DocumentServiceConection is used to add, remove and update documents in - CloudSearch. Commands are uploaded to CloudSearch in SDF (Search Document Format). - - To generate an appropriate SDF, use :func:`add` to add or update documents, - as well as :func:`delete` to remove documents. - - Once the set of documents is ready to be index, use :func:`commit` to send the - commands to CloudSearch. - - If there are a lot of documents to index, it may be preferable to split the - generation of SDF data and the actual uploading into CloudSearch. Retrieve - the current SDF with :func:`get_sdf`. If this file is the uploaded into S3, - it can be retrieved back afterwards for upload into CloudSearch using - :func:`add_sdf_from_s3`. - - The SDF is not cleared after a :func:`commit`. If you wish to continue - using the DocumentServiceConnection for another batch upload of commands, - you will need to :func:`clear_sdf` first to stop the previous batch of - commands from being uploaded again. - - """ - - def __init__(self, domain=None, endpoint=None): - self.domain = domain - self.endpoint = endpoint - if not self.endpoint: - self.endpoint = domain.doc_service_endpoint - self.documents_batch = [] - self._sdf = None - - def add(self, _id, version, fields, lang='en'): - """ - Add a document to be processed by the DocumentService - - The document will not actually be added until :func:`commit` is called - - :type _id: string - :param _id: A unique ID used to refer to this document. - - :type version: int - :param version: Version of the document being indexed. If a file is - being reindexed, the version should be higher than the existing one - in CloudSearch. - - :type fields: dict - :param fields: A dictionary of key-value pairs to be uploaded . - - :type lang: string - :param lang: The language code the data is in. Only 'en' is currently - supported - """ - - d = {'type': 'add', 'id': _id, 'version': version, 'lang': lang, - 'fields': fields} - self.documents_batch.append(d) - - def delete(self, _id, version): - """ - Schedule a document to be removed from the CloudSearch service - - The document will not actually be scheduled for removal until :func:`commit` is called - - :type _id: string - :param _id: The unique ID of this document. - - :type version: int - :param version: Version of the document to remove. The delete will only - occur if this version number is higher than the version currently - in the index. - """ - - d = {'type': 'delete', 'id': _id, 'version': version} - self.documents_batch.append(d) - - def get_sdf(self): - """ - Generate the working set of documents in Search Data Format (SDF) - - :rtype: string - :returns: JSON-formatted string of the documents in SDF - """ - - return self._sdf if self._sdf else json.dumps(self.documents_batch) - - def clear_sdf(self): - """ - Clear the working documents from this DocumentServiceConnection - - This should be used after :func:`commit` if the connection will be reused - for another set of documents. - """ - - self._sdf = None - self.documents_batch = [] - - def add_sdf_from_s3(self, key_obj): - """ - Load an SDF from S3 - - Using this method will result in documents added through - :func:`add` and :func:`delete` being ignored. - - :type key_obj: :class:`boto.s3.key.Key` - :param key_obj: An S3 key which contains an SDF - """ - #@todo:: (lucas) would be nice if this could just take an s3://uri..." - - self._sdf = key_obj.get_contents_as_string() - - def commit(self): - """ - Actually send an SDF to CloudSearch for processing - - If an SDF file has been explicitly loaded it will be used. Otherwise, - documents added through :func:`add` and :func:`delete` will be used. - - :rtype: :class:`CommitResponse` - :returns: A summary of documents added and deleted - """ - - sdf = self.get_sdf() - - if ': null' in sdf: - boto.log.error('null value in sdf detected. This will probably raise ' - '500 error.') - index = sdf.index(': null') - boto.log.error(sdf[index - 100:index + 100]) - - url = "http://%s/2011-02-01/documents/batch" % (self.endpoint) - - # Keep-alive is automatic in a post-1.0 requests world. - session = requests.Session() - adapter = requests.adapters.HTTPAdapter( - pool_connections=20, - pool_maxsize=50, - max_retries=5 - ) - session.mount('http://', adapter) - session.mount('https://', adapter) - r = session.post(url, data=sdf, headers={'Content-Type': 'application/json'}) - - return CommitResponse(r, self, sdf) - - -class CommitResponse(object): - """Wrapper for response to Cloudsearch document batch commit. - - :type response: :class:`requests.models.Response` - :param response: Response from Cloudsearch /documents/batch API - - :type doc_service: :class:`boto.cloudsearch.document.DocumentServiceConnection` - :param doc_service: Object containing the documents posted and methods to - retry - - :raises: :class:`boto.exception.BotoServerError` - :raises: :class:`boto.cloudsearch.document.SearchServiceException` - :raises: :class:`boto.cloudsearch.document.EncodingError` - :raises: :class:`boto.cloudsearch.document.ContentTooLongError` - """ - def __init__(self, response, doc_service, sdf): - self.response = response - self.doc_service = doc_service - self.sdf = sdf - - _body = response.content.decode('utf-8') - - try: - self.content = json.loads(_body) - except: - boto.log.error('Error indexing documents.\nResponse Content:\n{0}\n\n' - 'SDF:\n{1}'.format(_body, self.sdf)) - raise boto.exception.BotoServerError(self.response.status_code, '', - body=_body) - - self.status = self.content['status'] - if self.status == 'error': - self.errors = [e.get('message') for e in self.content.get('errors', - [])] - for e in self.errors: - if "Illegal Unicode character" in e: - raise EncodingError("Illegal Unicode character in document") - elif e == "The Content-Length is too long": - raise ContentTooLongError("Content was too long") - if 'adds' not in self.content or 'deletes' not in self.content: - raise SearchServiceException("Error indexing documents" - " => %s" % self.content.get('message', '')) - else: - self.errors = [] - - self.adds = self.content['adds'] - self.deletes = self.content['deletes'] - self._check_num_ops('add', self.adds) - self._check_num_ops('delete', self.deletes) - - def _check_num_ops(self, type_, response_num): - """Raise exception if number of ops in response doesn't match commit - - :type type_: str - :param type_: Type of commit operation: 'add' or 'delete' - - :type response_num: int - :param response_num: Number of adds or deletes in the response. - - :raises: :class:`boto.cloudsearch.document.CommitMismatchError` - """ - commit_num = len([d for d in self.doc_service.documents_batch - if d['type'] == type_]) - - if response_num != commit_num: - raise CommitMismatchError( - 'Incorrect number of {0}s returned. Commit: {1} Response: {2}'\ - .format(type_, commit_num, response_num)) diff --git a/awx/lib/site-packages/boto/cloudsearch/domain.py b/awx/lib/site-packages/boto/cloudsearch/domain.py deleted file mode 100644 index 9800b17512..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/domain.py +++ /dev/null @@ -1,394 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.cloudsearch.optionstatus import OptionStatus -from boto.cloudsearch.optionstatus import IndexFieldStatus -from boto.cloudsearch.optionstatus import ServicePoliciesStatus -from boto.cloudsearch.optionstatus import RankExpressionStatus -from boto.cloudsearch.document import DocumentServiceConnection -from boto.cloudsearch.search import SearchConnection - -def handle_bool(value): - if value in [True, 'true', 'True', 'TRUE', 1]: - return True - return False - - -class Domain(object): - """ - A Cloudsearch domain. - - :ivar name: The name of the domain. - - :ivar id: The internally generated unique identifier for the domain. - - :ivar created: A boolean which is True if the domain is - created. It can take several minutes to initialize a domain - when CreateDomain is called. Newly created search domains are - returned with a False value for Created until domain creation - is complete - - :ivar deleted: A boolean which is True if the search domain has - been deleted. The system must clean up resources dedicated to - the search domain when delete is called. Newly deleted - search domains are returned from list_domains with a True - value for deleted for several minutes until resource cleanup - is complete. - - :ivar processing: True if processing is being done to activate the - current domain configuration. - - :ivar num_searchable_docs: The number of documents that have been - submittted to the domain and indexed. - - :ivar requires_index_document: True if index_documents needs to be - called to activate the current domain configuration. - - :ivar search_instance_count: The number of search instances that are - available to process search requests. - - :ivar search_instance_type: The instance type that is being used to - process search requests. - - :ivar search_partition_count: The number of partitions across which - the search index is spread. - """ - - def __init__(self, layer1, data): - self.layer1 = layer1 - self.update_from_data(data) - - def update_from_data(self, data): - self.created = data['created'] - self.deleted = data['deleted'] - self.processing = data['processing'] - self.requires_index_documents = data['requires_index_documents'] - self.domain_id = data['domain_id'] - self.domain_name = data['domain_name'] - self.num_searchable_docs = data['num_searchable_docs'] - self.search_instance_count = data['search_instance_count'] - self.search_instance_type = data.get('search_instance_type', None) - self.search_partition_count = data['search_partition_count'] - self._doc_service = data['doc_service'] - self._search_service = data['search_service'] - - @property - def doc_service_arn(self): - return self._doc_service['arn'] - - @property - def doc_service_endpoint(self): - return self._doc_service['endpoint'] - - @property - def search_service_arn(self): - return self._search_service['arn'] - - @property - def search_service_endpoint(self): - return self._search_service['endpoint'] - - @property - def created(self): - return self._created - - @created.setter - def created(self, value): - self._created = handle_bool(value) - - @property - def deleted(self): - return self._deleted - - @deleted.setter - def deleted(self, value): - self._deleted = handle_bool(value) - - @property - def processing(self): - return self._processing - - @processing.setter - def processing(self, value): - self._processing = handle_bool(value) - - @property - def requires_index_documents(self): - return self._requires_index_documents - - @requires_index_documents.setter - def requires_index_documents(self, value): - self._requires_index_documents = handle_bool(value) - - @property - def search_partition_count(self): - return self._search_partition_count - - @search_partition_count.setter - def search_partition_count(self, value): - self._search_partition_count = int(value) - - @property - def search_instance_count(self): - return self._search_instance_count - - @search_instance_count.setter - def search_instance_count(self, value): - self._search_instance_count = int(value) - - @property - def num_searchable_docs(self): - return self._num_searchable_docs - - @num_searchable_docs.setter - def num_searchable_docs(self, value): - self._num_searchable_docs = int(value) - - @property - def name(self): - return self.domain_name - - @property - def id(self): - return self.domain_id - - def delete(self): - """ - Delete this domain and all index data associated with it. - """ - return self.layer1.delete_domain(self.name) - - def get_stemming(self): - """ - Return a :class:`boto.cloudsearch.option.OptionStatus` object - representing the currently defined stemming options for - the domain. - """ - return OptionStatus(self, None, - self.layer1.describe_stemming_options, - self.layer1.update_stemming_options) - - def get_stopwords(self): - """ - Return a :class:`boto.cloudsearch.option.OptionStatus` object - representing the currently defined stopword options for - the domain. - """ - return OptionStatus(self, None, - self.layer1.describe_stopword_options, - self.layer1.update_stopword_options) - - def get_synonyms(self): - """ - Return a :class:`boto.cloudsearch.option.OptionStatus` object - representing the currently defined synonym options for - the domain. - """ - return OptionStatus(self, None, - self.layer1.describe_synonym_options, - self.layer1.update_synonym_options) - - def get_access_policies(self): - """ - Return a :class:`boto.cloudsearch.option.OptionStatus` object - representing the currently defined access policies for - the domain. - """ - return ServicePoliciesStatus(self, None, - self.layer1.describe_service_access_policies, - self.layer1.update_service_access_policies) - - def index_documents(self): - """ - Tells the search domain to start indexing its documents using - the latest text processing options and IndexFields. This - operation must be invoked to make options whose OptionStatus - has OptioState of RequiresIndexDocuments visible in search - results. - """ - self.layer1.index_documents(self.name) - - def get_index_fields(self, field_names=None): - """ - Return a list of index fields defined for this domain. - """ - data = self.layer1.describe_index_fields(self.name, field_names) - return [IndexFieldStatus(self, d) for d in data] - - def create_index_field(self, field_name, field_type, - default='', facet=False, result=False, searchable=False, - source_attributes=[]): - """ - Defines an ``IndexField``, either replacing an existing - definition or creating a new one. - - :type field_name: string - :param field_name: The name of a field in the search index. - - :type field_type: string - :param field_type: The type of field. Valid values are - uint | literal | text - - :type default: string or int - :param default: The default value for the field. If the - field is of type ``uint`` this should be an integer value. - Otherwise, it's a string. - - :type facet: bool - :param facet: A boolean to indicate whether facets - are enabled for this field or not. Does not apply to - fields of type ``uint``. - - :type results: bool - :param results: A boolean to indicate whether values - of this field can be returned in search results or - used in ranking. Does not apply to fields of type ``uint``. - - :type searchable: bool - :param searchable: A boolean to indicate whether search - is enabled for this field or not. Applies only to fields - of type ``literal``. - - :type source_attributes: list of dicts - :param source_attributes: An optional list of dicts that - provide information about attributes for this index field. - A maximum of 20 source attributes can be configured for - each index field. - - Each item in the list is a dict with the following keys: - - * data_copy - The value is a dict with the following keys: - * default - Optional default value if the source attribute - is not specified in a document. - * name - The name of the document source field to add - to this ``IndexField``. - * data_function - Identifies the transformation to apply - when copying data from a source attribute. - * data_map - The value is a dict with the following keys: - * cases - A dict that translates source field values - to custom values. - * default - An optional default value to use if the - source attribute is not specified in a document. - * name - the name of the document source field to add - to this ``IndexField`` - * data_trim_title - Trims common title words from a source - document attribute when populating an ``IndexField``. - This can be used to create an ``IndexField`` you can - use for sorting. The value is a dict with the following - fields: - * default - An optional default value. - * language - an IETF RFC 4646 language code. - * separator - The separator that follows the text to trim. - * name - The name of the document source field to add. - - :raises: BaseException, InternalException, LimitExceededException, - InvalidTypeException, ResourceNotFoundException - """ - data = self.layer1.define_index_field(self.name, field_name, - field_type, default=default, - facet=facet, result=result, - searchable=searchable, - source_attributes=source_attributes) - return IndexFieldStatus(self, data, - self.layer1.describe_index_fields) - - def get_rank_expressions(self, rank_names=None): - """ - Return a list of rank expressions defined for this domain. - """ - fn = self.layer1.describe_rank_expressions - data = fn(self.name, rank_names) - return [RankExpressionStatus(self, d, fn) for d in data] - - def create_rank_expression(self, name, expression): - """ - Create a new rank expression. - - :type rank_name: string - :param rank_name: The name of an expression computed for ranking - while processing a search request. - - :type rank_expression: string - :param rank_expression: The expression to evaluate for ranking - or thresholding while processing a search request. The - RankExpression syntax is based on JavaScript expressions - and supports: - - * Integer, floating point, hex and octal literals - * Shortcut evaluation of logical operators such that an - expression a || b evaluates to the value a if a is - true without evaluting b at all - * JavaScript order of precedence for operators - * Arithmetic operators: + - * / % - * Boolean operators (including the ternary operator) - * Bitwise operators - * Comparison operators - * Common mathematic functions: abs ceil erf exp floor - lgamma ln log2 log10 max min sqrt pow - * Trigonometric library functions: acosh acos asinh asin - atanh atan cosh cos sinh sin tanh tan - * Random generation of a number between 0 and 1: rand - * Current time in epoch: time - * The min max functions that operate on a variable argument list - - Intermediate results are calculated as double precision - floating point values. The final return value of a - RankExpression is automatically converted from floating - point to a 32-bit unsigned integer by rounding to the - nearest integer, with a natural floor of 0 and a ceiling - of max(uint32_t), 4294967295. Mathematical errors such as - dividing by 0 will fail during evaluation and return a - value of 0. - - The source data for a RankExpression can be the name of an - IndexField of type uint, another RankExpression or the - reserved name text_relevance. The text_relevance source is - defined to return an integer from 0 to 1000 (inclusive) to - indicate how relevant a document is to the search request, - taking into account repetition of search terms in the - document and proximity of search terms to each other in - each matching IndexField in the document. - - For more information about using rank expressions to - customize ranking, see the Amazon CloudSearch Developer - Guide. - - :raises: BaseException, InternalException, LimitExceededException, - InvalidTypeException, ResourceNotFoundException - """ - data = self.layer1.define_rank_expression(self.name, name, expression) - return RankExpressionStatus(self, data, - self.layer1.describe_rank_expressions) - - def get_document_service(self): - return DocumentServiceConnection(domain=self) - - def get_search_service(self): - return SearchConnection(domain=self) - - def __repr__(self): - return '<Domain: %s>' % self.domain_name - diff --git a/awx/lib/site-packages/boto/cloudsearch/layer1.py b/awx/lib/site-packages/boto/cloudsearch/layer1.py deleted file mode 100644 index 69132e39ce..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/layer1.py +++ /dev/null @@ -1,747 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -import boto.jsonresponse -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo - -#boto.set_stream_logger('cloudsearch') - - -def do_bool(val): - return 'true' if val in [True, 1, '1', 'true'] else 'false' - - -class Layer1(AWSQueryConnection): - - APIVersion = '2011-02-01' - DefaultRegionName = boto.config.get('Boto', 'cs_region_name', 'us-east-1') - DefaultRegionEndpoint = boto.config.get('Boto', 'cs_region_endpoint', - 'cloudsearch.us-east-1.amazonaws.com') - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, host=None, port=None, - proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - api_version=None, security_token=None, - validate_certs=True, profile_name=None): - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - AWSQueryConnection.__init__( - self, - host=self.region.endpoint, - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - is_secure=is_secure, - port=port, - proxy=proxy, - proxy_port=proxy_port, - proxy_user=proxy_user, - proxy_pass=proxy_pass, - debug=debug, - https_connection_factory=https_connection_factory, - path=path, - security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def get_response(self, doc_path, action, params, path='/', - parent=None, verb='GET', list_marker=None): - if not parent: - parent = self - response = self.make_request(action, params, path, verb) - body = response.read() - boto.log.debug(body) - if response.status == 200: - e = boto.jsonresponse.Element( - list_marker=list_marker if list_marker else 'Set', - pythonize_name=True) - h = boto.jsonresponse.XmlHandler(e, parent) - h.parse(body) - inner = e - for p in doc_path: - inner = inner.get(p) - if not inner: - return None if list_marker is None else [] - if isinstance(inner, list): - return inner - else: - return dict(**inner) - else: - raise self.ResponseError(response.status, response.reason, body) - - def create_domain(self, domain_name): - """ - Create a new search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException, LimitExceededException - """ - doc_path = ('create_domain_response', - 'create_domain_result', - 'domain_status') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'CreateDomain', - params, verb='POST') - - def define_index_field(self, domain_name, field_name, field_type, - default='', facet=False, result=False, - searchable=False, source_attributes=None): - """ - Defines an ``IndexField``, either replacing an existing - definition or creating a new one. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type field_name: string - :param field_name: The name of a field in the search index. - - :type field_type: string - :param field_type: The type of field. Valid values are - uint | literal | text - - :type default: string or int - :param default: The default value for the field. If the - field is of type ``uint`` this should be an integer value. - Otherwise, it's a string. - - :type facet: bool - :param facet: A boolean to indicate whether facets - are enabled for this field or not. Does not apply to - fields of type ``uint``. - - :type results: bool - :param results: A boolean to indicate whether values - of this field can be returned in search results or - used in ranking. Does not apply to fields of type ``uint``. - - :type searchable: bool - :param searchable: A boolean to indicate whether search - is enabled for this field or not. Applies only to fields - of type ``literal``. - - :type source_attributes: list of dicts - :param source_attributes: An optional list of dicts that - provide information about attributes for this index field. - A maximum of 20 source attributes can be configured for - each index field. - - Each item in the list is a dict with the following keys: - - * data_copy - The value is a dict with the following keys: - * default - Optional default value if the source attribute - is not specified in a document. - * name - The name of the document source field to add - to this ``IndexField``. - * data_function - Identifies the transformation to apply - when copying data from a source attribute. - * data_map - The value is a dict with the following keys: - * cases - A dict that translates source field values - to custom values. - * default - An optional default value to use if the - source attribute is not specified in a document. - * name - the name of the document source field to add - to this ``IndexField`` - * data_trim_title - Trims common title words from a source - document attribute when populating an ``IndexField``. - This can be used to create an ``IndexField`` you can - use for sorting. The value is a dict with the following - fields: - * default - An optional default value. - * language - an IETF RFC 4646 language code. - * separator - The separator that follows the text to trim. - * name - The name of the document source field to add. - - :raises: BaseException, InternalException, LimitExceededException, - InvalidTypeException, ResourceNotFoundException - """ - doc_path = ('define_index_field_response', - 'define_index_field_result', - 'index_field') - params = {'DomainName': domain_name, - 'IndexField.IndexFieldName': field_name, - 'IndexField.IndexFieldType': field_type} - if field_type == 'literal': - params['IndexField.LiteralOptions.DefaultValue'] = default - params['IndexField.LiteralOptions.FacetEnabled'] = do_bool(facet) - params['IndexField.LiteralOptions.ResultEnabled'] = do_bool(result) - params['IndexField.LiteralOptions.SearchEnabled'] = do_bool(searchable) - elif field_type == 'uint': - params['IndexField.UIntOptions.DefaultValue'] = default - elif field_type == 'text': - params['IndexField.TextOptions.DefaultValue'] = default - params['IndexField.TextOptions.FacetEnabled'] = do_bool(facet) - params['IndexField.TextOptions.ResultEnabled'] = do_bool(result) - - return self.get_response(doc_path, 'DefineIndexField', - params, verb='POST') - - def define_rank_expression(self, domain_name, rank_name, rank_expression): - """ - Defines a RankExpression, either replacing an existing - definition or creating a new one. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type rank_name: string - :param rank_name: The name of an expression computed for ranking - while processing a search request. - - :type rank_expression: string - :param rank_expression: The expression to evaluate for ranking - or thresholding while processing a search request. The - RankExpression syntax is based on JavaScript expressions - and supports: - - * Integer, floating point, hex and octal literals - * Shortcut evaluation of logical operators such that an - expression a || b evaluates to the value a if a is - true without evaluting b at all - * JavaScript order of precedence for operators - * Arithmetic operators: + - * / % - * Boolean operators (including the ternary operator) - * Bitwise operators - * Comparison operators - * Common mathematic functions: abs ceil erf exp floor - lgamma ln log2 log10 max min sqrt pow - * Trigonometric library functions: acosh acos asinh asin - atanh atan cosh cos sinh sin tanh tan - * Random generation of a number between 0 and 1: rand - * Current time in epoch: time - * The min max functions that operate on a variable argument list - - Intermediate results are calculated as double precision - floating point values. The final return value of a - RankExpression is automatically converted from floating - point to a 32-bit unsigned integer by rounding to the - nearest integer, with a natural floor of 0 and a ceiling - of max(uint32_t), 4294967295. Mathematical errors such as - dividing by 0 will fail during evaluation and return a - value of 0. - - The source data for a RankExpression can be the name of an - IndexField of type uint, another RankExpression or the - reserved name text_relevance. The text_relevance source is - defined to return an integer from 0 to 1000 (inclusive) to - indicate how relevant a document is to the search request, - taking into account repetition of search terms in the - document and proximity of search terms to each other in - each matching IndexField in the document. - - For more information about using rank expressions to - customize ranking, see the Amazon CloudSearch Developer - Guide. - - :raises: BaseException, InternalException, LimitExceededException, - InvalidTypeException, ResourceNotFoundException - """ - doc_path = ('define_rank_expression_response', - 'define_rank_expression_result', - 'rank_expression') - params = {'DomainName': domain_name, - 'RankExpression.RankExpression': rank_expression, - 'RankExpression.RankName': rank_name} - return self.get_response(doc_path, 'DefineRankExpression', - params, verb='POST') - - def delete_domain(self, domain_name): - """ - Delete a search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException - """ - doc_path = ('delete_domain_response', - 'delete_domain_result', - 'domain_status') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'DeleteDomain', - params, verb='POST') - - def delete_index_field(self, domain_name, field_name): - """ - Deletes an existing ``IndexField`` from the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type field_name: string - :param field_name: A string that represents the name of - an index field. Field names must begin with a letter and - can contain the following characters: a-z (lowercase), - 0-9, and _ (underscore). Uppercase letters and hyphens are - not allowed. The names "body", "docid", and - "text_relevance" are reserved and cannot be specified as - field or rank expression names. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('delete_index_field_response', - 'delete_index_field_result', - 'index_field') - params = {'DomainName': domain_name, - 'IndexFieldName': field_name} - return self.get_response(doc_path, 'DeleteIndexField', - params, verb='POST') - - def delete_rank_expression(self, domain_name, rank_name): - """ - Deletes an existing ``RankExpression`` from the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type rank_name: string - :param rank_name: Name of the ``RankExpression`` to delete. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('delete_rank_expression_response', - 'delete_rank_expression_result', - 'rank_expression') - params = {'DomainName': domain_name, 'RankName': rank_name} - return self.get_response(doc_path, 'DeleteRankExpression', - params, verb='POST') - - def describe_default_search_field(self, domain_name): - """ - Describes options defining the default search field used by - indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('describe_default_search_field_response', - 'describe_default_search_field_result', - 'default_search_field') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'DescribeDefaultSearchField', - params, verb='POST') - - def describe_domains(self, domain_names=None): - """ - Describes the domains (optionally limited to one or more - domains by name) owned by this account. - - :type domain_names: list - :param domain_names: Limits the response to the specified domains. - - :raises: BaseException, InternalException - """ - doc_path = ('describe_domains_response', - 'describe_domains_result', - 'domain_status_list') - params = {} - if domain_names: - for i, domain_name in enumerate(domain_names, 1): - params['DomainNames.member.%d' % i] = domain_name - return self.get_response(doc_path, 'DescribeDomains', - params, verb='POST', - list_marker='DomainStatusList') - - def describe_index_fields(self, domain_name, field_names=None): - """ - Describes index fields in the search domain, optionally - limited to a single ``IndexField``. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type field_names: list - :param field_names: Limits the response to the specified fields. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('describe_index_fields_response', - 'describe_index_fields_result', - 'index_fields') - params = {'DomainName': domain_name} - if field_names: - for i, field_name in enumerate(field_names, 1): - params['FieldNames.member.%d' % i] = field_name - return self.get_response(doc_path, 'DescribeIndexFields', - params, verb='POST', - list_marker='IndexFields') - - def describe_rank_expressions(self, domain_name, rank_names=None): - """ - Describes RankExpressions in the search domain, optionally - limited to a single expression. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type rank_names: list - :param rank_names: Limit response to the specified rank names. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('describe_rank_expressions_response', - 'describe_rank_expressions_result', - 'rank_expressions') - params = {'DomainName': domain_name} - if rank_names: - for i, rank_name in enumerate(rank_names, 1): - params['RankNames.member.%d' % i] = rank_name - return self.get_response(doc_path, 'DescribeRankExpressions', - params, verb='POST', - list_marker='RankExpressions') - - def describe_service_access_policies(self, domain_name): - """ - Describes the resource-based policies controlling access to - the services in this search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('describe_service_access_policies_response', - 'describe_service_access_policies_result', - 'access_policies') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'DescribeServiceAccessPolicies', - params, verb='POST') - - def describe_stemming_options(self, domain_name): - """ - Describes stemming options used by indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('describe_stemming_options_response', - 'describe_stemming_options_result', - 'stems') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'DescribeStemmingOptions', - params, verb='POST') - - def describe_stopword_options(self, domain_name): - """ - Describes stopword options used by indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('describe_stopword_options_response', - 'describe_stopword_options_result', - 'stopwords') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'DescribeStopwordOptions', - params, verb='POST') - - def describe_synonym_options(self, domain_name): - """ - Describes synonym options used by indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('describe_synonym_options_response', - 'describe_synonym_options_result', - 'synonyms') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'DescribeSynonymOptions', - params, verb='POST') - - def index_documents(self, domain_name): - """ - Tells the search domain to start scanning its documents using - the latest text processing options and ``IndexFields``. This - operation must be invoked to make visible in searches any - options whose <a>OptionStatus</a> has ``OptionState`` of - ``RequiresIndexDocuments``. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :raises: BaseException, InternalException, ResourceNotFoundException - """ - doc_path = ('index_documents_response', - 'index_documents_result', - 'field_names') - params = {'DomainName': domain_name} - return self.get_response(doc_path, 'IndexDocuments', params, - verb='POST', list_marker='FieldNames') - - def update_default_search_field(self, domain_name, default_search_field): - """ - Updates options defining the default search field used by - indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type default_search_field: string - :param default_search_field: The IndexField to use for search - requests issued with the q parameter. The default is an - empty string, which automatically searches all text - fields. - - :raises: BaseException, InternalException, InvalidTypeException, - ResourceNotFoundException - """ - doc_path = ('update_default_search_field_response', - 'update_default_search_field_result', - 'default_search_field') - params = {'DomainName': domain_name, - 'DefaultSearchField': default_search_field} - return self.get_response(doc_path, 'UpdateDefaultSearchField', - params, verb='POST') - - def update_service_access_policies(self, domain_name, access_policies): - """ - Updates the policies controlling access to the services in - this search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type access_policies: string - :param access_policies: An IAM access policy as described in - The Access Policy Language in Using AWS Identity and - Access Management. The maximum size of an access policy - document is 100KB. - - :raises: BaseException, InternalException, LimitExceededException, - ResourceNotFoundException, InvalidTypeException - """ - doc_path = ('update_service_access_policies_response', - 'update_service_access_policies_result', - 'access_policies') - params = {'AccessPolicies': access_policies, - 'DomainName': domain_name} - return self.get_response(doc_path, 'UpdateServiceAccessPolicies', - params, verb='POST') - - def update_stemming_options(self, domain_name, stems): - """ - Updates stemming options used by indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type stems: string - :param stems: Maps terms to their stems. The JSON object - has a single key called "stems" whose value is a - dict mapping terms to their stems. The maximum size - of a stemming document is 500KB. - Example: {"stems":{"people": "person", "walking":"walk"}} - - :raises: BaseException, InternalException, InvalidTypeException, - LimitExceededException, ResourceNotFoundException - """ - doc_path = ('update_stemming_options_response', - 'update_stemming_options_result', - 'stems') - params = {'DomainName': domain_name, - 'Stems': stems} - return self.get_response(doc_path, 'UpdateStemmingOptions', - params, verb='POST') - - def update_stopword_options(self, domain_name, stopwords): - """ - Updates stopword options used by indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type stopwords: string - :param stopwords: Lists stopwords in a JSON object. The object has a - single key called "stopwords" whose value is an array of strings. - The maximum size of a stopwords document is 10KB. Example: - {"stopwords": ["a", "an", "the", "of"]} - - :raises: BaseException, InternalException, InvalidTypeException, - LimitExceededException, ResourceNotFoundException - """ - doc_path = ('update_stopword_options_response', - 'update_stopword_options_result', - 'stopwords') - params = {'DomainName': domain_name, - 'Stopwords': stopwords} - return self.get_response(doc_path, 'UpdateStopwordOptions', - params, verb='POST') - - def update_synonym_options(self, domain_name, synonyms): - """ - Updates synonym options used by indexing for the search domain. - - :type domain_name: string - :param domain_name: A string that represents the name of a - domain. Domain names must be unique across the domains - owned by an account within an AWS region. Domain names - must start with a letter or number and can contain the - following characters: a-z (lowercase), 0-9, and - - (hyphen). Uppercase letters and underscores are not - allowed. - - :type synonyms: string - :param synonyms: Maps terms to their synonyms. The JSON object - has a single key "synonyms" whose value is a dict mapping terms - to their synonyms. Each synonym is a simple string or an - array of strings. The maximum size of a stopwords document - is 100KB. Example: - {"synonyms": {"cat": ["feline", "kitten"], "puppy": "dog"}} - - :raises: BaseException, InternalException, InvalidTypeException, - LimitExceededException, ResourceNotFoundException - """ - doc_path = ('update_synonym_options_response', - 'update_synonym_options_result', - 'synonyms') - params = {'DomainName': domain_name, - 'Synonyms': synonyms} - return self.get_response(doc_path, 'UpdateSynonymOptions', - params, verb='POST') diff --git a/awx/lib/site-packages/boto/cloudsearch/layer2.py b/awx/lib/site-packages/boto/cloudsearch/layer2.py deleted file mode 100644 index b565d4b5b9..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/layer2.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.cloudsearch.layer1 import Layer1 -from boto.cloudsearch.domain import Domain - - -class Layer2(object): - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - host=None, debug=0, session_token=None, region=None, - validate_certs=True): - self.layer1 = Layer1( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - is_secure=is_secure, - port=port, - proxy=proxy, - proxy_port=proxy_port, - host=host, - debug=debug, - security_token=session_token, - region=region, - validate_certs=validate_certs) - - def list_domains(self, domain_names=None): - """ - Return a list of :class:`boto.cloudsearch.domain.Domain` - objects for each domain defined in the current account. - """ - domain_data = self.layer1.describe_domains(domain_names) - return [Domain(self.layer1, data) for data in domain_data] - - def create_domain(self, domain_name): - """ - Create a new CloudSearch domain and return the corresponding - :class:`boto.cloudsearch.domain.Domain` object. - """ - data = self.layer1.create_domain(domain_name) - return Domain(self.layer1, data) - - def lookup(self, domain_name): - """ - Lookup a single domain - :param domain_name: The name of the domain to look up - :type domain_name: str - - :return: Domain object, or None if the domain isn't found - :rtype: :class:`boto.cloudsearch.domain.Domain` - """ - domains = self.list_domains(domain_names=[domain_name]) - if len(domains) > 0: - return domains[0] diff --git a/awx/lib/site-packages/boto/cloudsearch/optionstatus.py b/awx/lib/site-packages/boto/cloudsearch/optionstatus.py deleted file mode 100644 index dddda76f97..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/optionstatus.py +++ /dev/null @@ -1,248 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import time -from boto.compat import json - - -class OptionStatus(dict): - """ - Presents a combination of status field (defined below) which are - accessed as attributes and option values which are stored in the - native Python dictionary. In this class, the option values are - merged from a JSON object that is stored as the Option part of - the object. - - :ivar domain_name: The name of the domain this option is associated with. - :ivar create_date: A timestamp for when this option was created. - :ivar state: The state of processing a change to an option. - Possible values: - - * RequiresIndexDocuments: the option's latest value will not - be visible in searches until IndexDocuments has been called - and indexing is complete. - * Processing: the option's latest value is not yet visible in - all searches but is in the process of being activated. - * Active: the option's latest value is completely visible. - - :ivar update_date: A timestamp for when this option was updated. - :ivar update_version: A unique integer that indicates when this - option was last updated. - """ - - def __init__(self, domain, data=None, refresh_fn=None, save_fn=None): - self.domain = domain - self.refresh_fn = refresh_fn - self.save_fn = save_fn - self.refresh(data) - - def _update_status(self, status): - self.creation_date = status['creation_date'] - self.status = status['state'] - self.update_date = status['update_date'] - self.update_version = int(status['update_version']) - - def _update_options(self, options): - if options: - self.update(json.loads(options)) - - def refresh(self, data=None): - """ - Refresh the local state of the object. You can either pass - new state data in as the parameter ``data`` or, if that parameter - is omitted, the state data will be retrieved from CloudSearch. - """ - if not data: - if self.refresh_fn: - data = self.refresh_fn(self.domain.name) - if data: - self._update_status(data['status']) - self._update_options(data['options']) - - def to_json(self): - """ - Return the JSON representation of the options as a string. - """ - return json.dumps(self) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'CreationDate': - self.created = value - elif name == 'State': - self.state = value - elif name == 'UpdateDate': - self.updated = value - elif name == 'UpdateVersion': - self.update_version = int(value) - elif name == 'Options': - self.update_from_json_doc(value) - else: - setattr(self, name, value) - - def save(self): - """ - Write the current state of the local object back to the - CloudSearch service. - """ - if self.save_fn: - data = self.save_fn(self.domain.name, self.to_json()) - self.refresh(data) - - def wait_for_state(self, state): - """ - Performs polling of CloudSearch to wait for the ``state`` - of this object to change to the provided state. - """ - while self.state != state: - time.sleep(5) - self.refresh() - - -class IndexFieldStatus(OptionStatus): - - def _update_options(self, options): - self.update(options) - - def save(self): - pass - - -class RankExpressionStatus(IndexFieldStatus): - - pass - -class ServicePoliciesStatus(OptionStatus): - - def new_statement(self, arn, ip): - """ - Returns a new policy statement that will allow - access to the service described by ``arn`` by the - ip specified in ``ip``. - - :type arn: string - :param arn: The Amazon Resource Notation identifier for the - service you wish to provide access to. This would be - either the search service or the document service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - return { - "Effect":"Allow", - "Action":"*", # Docs say use GET, but denies unless * - "Resource": arn, - "Condition": { - "IpAddress": { - "aws:SourceIp": [ip] - } - } - } - - def _allow_ip(self, arn, ip): - if 'Statement' not in self: - s = self.new_statement(arn, ip) - self['Statement'] = [s] - self.save() - else: - add_statement = True - for statement in self['Statement']: - if statement['Resource'] == arn: - for condition_name in statement['Condition']: - if condition_name == 'IpAddress': - add_statement = False - condition = statement['Condition'][condition_name] - if ip not in condition['aws:SourceIp']: - condition['aws:SourceIp'].append(ip) - - if add_statement: - s = self.new_statement(arn, ip) - self['Statement'].append(s) - self.save() - - def allow_search_ip(self, ip): - """ - Add the provided ip address or CIDR block to the list of - allowable address for the search service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.search_service_arn - self._allow_ip(arn, ip) - - def allow_doc_ip(self, ip): - """ - Add the provided ip address or CIDR block to the list of - allowable address for the document service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.doc_service_arn - self._allow_ip(arn, ip) - - def _disallow_ip(self, arn, ip): - if 'Statement' not in self: - return - need_update = False - for statement in self['Statement']: - if statement['Resource'] == arn: - for condition_name in statement['Condition']: - if condition_name == 'IpAddress': - condition = statement['Condition'][condition_name] - if ip in condition['aws:SourceIp']: - condition['aws:SourceIp'].remove(ip) - need_update = True - if need_update: - self.save() - - def disallow_search_ip(self, ip): - """ - Remove the provided ip address or CIDR block from the list of - allowable address for the search service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.search_service_arn - self._disallow_ip(arn, ip) - - def disallow_doc_ip(self, ip): - """ - Remove the provided ip address or CIDR block from the list of - allowable address for the document service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.doc_service_arn - self._disallow_ip(arn, ip) diff --git a/awx/lib/site-packages/boto/cloudsearch/search.py b/awx/lib/site-packages/boto/cloudsearch/search.py deleted file mode 100644 index 70ea479bec..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/search.py +++ /dev/null @@ -1,377 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from math import ceil -from boto.compat import json, map, six -import requests - - -class SearchServiceException(Exception): - pass - - -class CommitMismatchError(Exception): - pass - - -class SearchResults(object): - def __init__(self, **attrs): - self.rid = attrs['info']['rid'] - # self.doc_coverage_pct = attrs['info']['doc-coverage-pct'] - self.cpu_time_ms = attrs['info']['cpu-time-ms'] - self.time_ms = attrs['info']['time-ms'] - self.hits = attrs['hits']['found'] - self.docs = attrs['hits']['hit'] - self.start = attrs['hits']['start'] - self.rank = attrs['rank'] - self.match_expression = attrs['match-expr'] - self.query = attrs['query'] - self.search_service = attrs['search_service'] - - self.facets = {} - if 'facets' in attrs: - for (facet, values) in attrs['facets'].items(): - if 'constraints' in values: - self.facets[facet] = dict((k, v) for (k, v) in map(lambda x: (x['value'], x['count']), values['constraints'])) - - self.num_pages_needed = ceil(self.hits / self.query.real_size) - - def __len__(self): - return len(self.docs) - - def __iter__(self): - return iter(self.docs) - - def next_page(self): - """Call Cloudsearch to get the next page of search results - - :rtype: :class:`boto.cloudsearch.search.SearchResults` - :return: the following page of search results - """ - if self.query.page <= self.num_pages_needed: - self.query.start += self.query.real_size - self.query.page += 1 - return self.search_service(self.query) - else: - raise StopIteration - - -class Query(object): - - RESULTS_PER_PAGE = 500 - - def __init__(self, q=None, bq=None, rank=None, - return_fields=None, size=10, - start=0, facet=None, facet_constraints=None, - facet_sort=None, facet_top_n=None, t=None): - - self.q = q - self.bq = bq - self.rank = rank or [] - self.return_fields = return_fields or [] - self.start = start - self.facet = facet or [] - self.facet_constraints = facet_constraints or {} - self.facet_sort = facet_sort or {} - self.facet_top_n = facet_top_n or {} - self.t = t or {} - self.page = 0 - self.update_size(size) - - def update_size(self, new_size): - self.size = new_size - self.real_size = Query.RESULTS_PER_PAGE if (self.size > - Query.RESULTS_PER_PAGE or self.size == 0) else self.size - - def to_params(self): - """Transform search parameters from instance properties to a dictionary - - :rtype: dict - :return: search parameters - """ - params = {'start': self.start, 'size': self.real_size} - - if self.q: - params['q'] = self.q - - if self.bq: - params['bq'] = self.bq - - if self.rank: - params['rank'] = ','.join(self.rank) - - if self.return_fields: - params['return-fields'] = ','.join(self.return_fields) - - if self.facet: - params['facet'] = ','.join(self.facet) - - if self.facet_constraints: - for k, v in six.iteritems(self.facet_constraints): - params['facet-%s-constraints' % k] = v - - if self.facet_sort: - for k, v in six.iteritems(self.facet_sort): - params['facet-%s-sort' % k] = v - - if self.facet_top_n: - for k, v in six.iteritems(self.facet_top_n): - params['facet-%s-top-n' % k] = v - - if self.t: - for k, v in six.iteritems(self.t): - params['t-%s' % k] = v - return params - - -class SearchConnection(object): - - def __init__(self, domain=None, endpoint=None): - self.domain = domain - self.endpoint = endpoint - if not endpoint: - self.endpoint = domain.search_service_endpoint - - def build_query(self, q=None, bq=None, rank=None, return_fields=None, - size=10, start=0, facet=None, facet_constraints=None, - facet_sort=None, facet_top_n=None, t=None): - return Query(q=q, bq=bq, rank=rank, return_fields=return_fields, - size=size, start=start, facet=facet, - facet_constraints=facet_constraints, - facet_sort=facet_sort, facet_top_n=facet_top_n, t=t) - - def search(self, q=None, bq=None, rank=None, return_fields=None, - size=10, start=0, facet=None, facet_constraints=None, - facet_sort=None, facet_top_n=None, t=None): - """ - Send a query to CloudSearch - - Each search query should use at least the q or bq argument to specify - the search parameter. The other options are used to specify the - criteria of the search. - - :type q: string - :param q: A string to search the default search fields for. - - :type bq: string - :param bq: A string to perform a Boolean search. This can be used to - create advanced searches. - - :type rank: List of strings - :param rank: A list of fields or rank expressions used to order the - search results. A field can be reversed by using the - operator. - ``['-year', 'author']`` - - :type return_fields: List of strings - :param return_fields: A list of fields which should be returned by the - search. If this field is not specified, only IDs will be returned. - ``['headline']`` - - :type size: int - :param size: Number of search results to specify - - :type start: int - :param start: Offset of the first search result to return (can be used - for paging) - - :type facet: list - :param facet: List of fields for which facets should be returned - ``['colour', 'size']`` - - :type facet_constraints: dict - :param facet_constraints: Use to limit facets to specific values - specified as comma-delimited strings in a Dictionary of facets - ``{'colour': "'blue','white','red'", 'size': "big"}`` - - :type facet_sort: dict - :param facet_sort: Rules used to specify the order in which facet - values should be returned. Allowed values are *alpha*, *count*, - *max*, *sum*. Use *alpha* to sort alphabetical, and *count* to sort - the facet by number of available result. - ``{'color': 'alpha', 'size': 'count'}`` - - :type facet_top_n: dict - :param facet_top_n: Dictionary of facets and number of facets to - return. - ``{'colour': 2}`` - - :type t: dict - :param t: Specify ranges for specific fields - ``{'year': '2000..2005'}`` - - :rtype: :class:`boto.cloudsearch.search.SearchResults` - :return: Returns the results of this search - - The following examples all assume we have indexed a set of documents - with fields: *author*, *date*, *headline* - - A simple search will look for documents whose default text search - fields will contain the search word exactly: - - >>> search(q='Tim') # Return documents with the word Tim in them (but not Timothy) - - A simple search with more keywords will return documents whose default - text search fields contain the search strings together or separately. - - >>> search(q='Tim apple') # Will match "tim" and "apple" - - More complex searches require the boolean search operator. - - Wildcard searches can be used to search for any words that start with - the search string. - - >>> search(bq="'Tim*'") # Return documents with words like Tim or Timothy) - - Search terms can also be combined. Allowed operators are "and", "or", - "not", "field", "optional", "token", "phrase", or "filter" - - >>> search(bq="(and 'Tim' (field author 'John Smith'))") - - Facets allow you to show classification information about the search - results. For example, you can retrieve the authors who have written - about Tim: - - >>> search(q='Tim', facet=['Author']) - - With facet_constraints, facet_top_n and facet_sort more complicated - constraints can be specified such as returning the top author out of - John Smith and Mark Smith who have a document with the word Tim in it. - - >>> search(q='Tim', - ... facet=['Author'], - ... facet_constraints={'author': "'John Smith','Mark Smith'"}, - ... facet=['author'], - ... facet_top_n={'author': 1}, - ... facet_sort={'author': 'count'}) - """ - - query = self.build_query(q=q, bq=bq, rank=rank, - return_fields=return_fields, - size=size, start=start, facet=facet, - facet_constraints=facet_constraints, - facet_sort=facet_sort, - facet_top_n=facet_top_n, t=t) - return self(query) - - def __call__(self, query): - """Make a call to CloudSearch - - :type query: :class:`boto.cloudsearch.search.Query` - :param query: A group of search criteria - - :rtype: :class:`boto.cloudsearch.search.SearchResults` - :return: search results - """ - url = "http://%s/2011-02-01/search" % (self.endpoint) - params = query.to_params() - - r = requests.get(url, params=params) - body = r.content.decode('utf-8') - try: - data = json.loads(body) - except ValueError as e: - if r.status_code == 403: - msg = '' - import re - g = re.search('<html><body><h1>403 Forbidden</h1>([^<]+)<', body) - try: - msg = ': %s' % (g.groups()[0].strip()) - except AttributeError: - pass - raise SearchServiceException('Authentication error from Amazon%s' % msg) - raise SearchServiceException("Got non-json response from Amazon. %s" % body, query) - - if 'messages' in data and 'error' in data: - for m in data['messages']: - if m['severity'] == 'fatal': - raise SearchServiceException("Error processing search %s " - "=> %s" % (params, m['message']), query) - elif 'error' in data: - raise SearchServiceException("Unknown error processing search %s" - % json.dumps(data), query) - - data['query'] = query - data['search_service'] = self - - return SearchResults(**data) - - def get_all_paged(self, query, per_page): - """Get a generator to iterate over all pages of search results - - :type query: :class:`boto.cloudsearch.search.Query` - :param query: A group of search criteria - - :type per_page: int - :param per_page: Number of docs in each :class:`boto.cloudsearch.search.SearchResults` object. - - :rtype: generator - :return: Generator containing :class:`boto.cloudsearch.search.SearchResults` - """ - query.update_size(per_page) - page = 0 - num_pages_needed = 0 - while page <= num_pages_needed: - results = self(query) - num_pages_needed = results.num_pages_needed - yield results - query.start += query.real_size - page += 1 - - def get_all_hits(self, query): - """Get a generator to iterate over all search results - - Transparently handles the results paging from Cloudsearch - search results so even if you have many thousands of results - you can iterate over all results in a reasonably efficient - manner. - - :type query: :class:`boto.cloudsearch.search.Query` - :param query: A group of search criteria - - :rtype: generator - :return: All docs matching query - """ - page = 0 - num_pages_needed = 0 - while page <= num_pages_needed: - results = self(query) - num_pages_needed = results.num_pages_needed - for doc in results: - yield doc - query.start += query.real_size - page += 1 - - def get_num_hits(self, query): - """Return the total number of hits for query - - :type query: :class:`boto.cloudsearch.search.Query` - :param query: a group of search criteria - - :rtype: int - :return: Total number of hits for query - """ - query.update_size(1) - return self(query).hits - - - diff --git a/awx/lib/site-packages/boto/cloudsearch/sourceattribute.py b/awx/lib/site-packages/boto/cloudsearch/sourceattribute.py deleted file mode 100644 index 2883314722..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch/sourceattribute.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 202 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class SourceAttribute(object): - """ - Provide information about attributes for an index field. - A maximum of 20 source attributes can be configured for - each index field. - - :ivar default: Optional default value if the source attribute - is not specified in a document. - - :ivar name: The name of the document source field to add - to this ``IndexField``. - - :ivar data_function: Identifies the transformation to apply - when copying data from a source attribute. - - :ivar data_map: The value is a dict with the following keys: - * cases - A dict that translates source field values - to custom values. - * default - An optional default value to use if the - source attribute is not specified in a document. - * name - the name of the document source field to add - to this ``IndexField`` - :ivar data_trim_title: Trims common title words from a source - document attribute when populating an ``IndexField``. - This can be used to create an ``IndexField`` you can - use for sorting. The value is a dict with the following - fields: - * default - An optional default value. - * language - an IETF RFC 4646 language code. - * separator - The separator that follows the text to trim. - * name - The name of the document source field to add. - """ - - ValidDataFunctions = ('Copy', 'TrimTitle', 'Map') - - def __init__(self): - self.data_copy = {} - self._data_function = self.ValidDataFunctions[0] - self.data_map = {} - self.data_trim_title = {} - - @property - def data_function(self): - return self._data_function - - @data_function.setter - def data_function(self, value): - if value not in self.ValidDataFunctions: - valid = '|'.join(self.ValidDataFunctions) - raise ValueError('data_function must be one of: %s' % valid) - self._data_function = value diff --git a/awx/lib/site-packages/boto/cloudsearch2/__init__.py b/awx/lib/site-packages/boto/cloudsearch2/__init__.py deleted file mode 100644 index d14c917935..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from boto.regioninfo import get_regions - - -def regions(): - """ - Get all available regions for the Amazon CloudSearch service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - import boto.cloudsearch2.layer1 - return get_regions( - 'cloudsearch', - connection_cls=boto.cloudsearch2.layer1.CloudSearchConnection - ) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/cloudsearch2/document.py b/awx/lib/site-packages/boto/cloudsearch2/document.py deleted file mode 100644 index 3b36f13337..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/document.py +++ /dev/null @@ -1,282 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto.exception -from boto.compat import json -import requests -import boto - - -class SearchServiceException(Exception): - pass - - -class CommitMismatchError(Exception): - # Let's do some extra work and let the user handle errors on his/her own. - - errors = None - - -class EncodingError(Exception): - """ - Content sent for Cloud Search indexing was incorrectly encoded. - - This usually happens when a document is marked as unicode but non-unicode - characters are present. - """ - pass - - -class ContentTooLongError(Exception): - """ - Content sent for Cloud Search indexing was too long - - This will usually happen when documents queued for indexing add up to more - than the limit allowed per upload batch (5MB) - - """ - pass - - -class DocumentServiceConnection(object): - """ - A CloudSearch document service. - - The DocumentServiceConection is used to add, remove and update documents in - CloudSearch. Commands are uploaded to CloudSearch in SDF (Search Document - Format). - - To generate an appropriate SDF, use :func:`add` to add or update documents, - as well as :func:`delete` to remove documents. - - Once the set of documents is ready to be index, use :func:`commit` to send - the commands to CloudSearch. - - If there are a lot of documents to index, it may be preferable to split the - generation of SDF data and the actual uploading into CloudSearch. Retrieve - the current SDF with :func:`get_sdf`. If this file is the uploaded into S3, - it can be retrieved back afterwards for upload into CloudSearch using - :func:`add_sdf_from_s3`. - - The SDF is not cleared after a :func:`commit`. If you wish to continue - using the DocumentServiceConnection for another batch upload of commands, - you will need to :func:`clear_sdf` first to stop the previous batch of - commands from being uploaded again. - - """ - - def __init__(self, domain=None, endpoint=None): - self.domain = domain - self.endpoint = endpoint - if not self.endpoint: - self.endpoint = domain.doc_service_endpoint - self.documents_batch = [] - self._sdf = None - - # Copy proxy settings from connection - if self.domain and self.domain.layer1 and self.domain.layer1.use_proxy: - self.proxy = {'http': self.domain.layer1.get_proxy_url_with_auth()} - else: - self.proxy = {} - - def add(self, _id, fields): - """ - Add a document to be processed by the DocumentService - - The document will not actually be added until :func:`commit` is called - - :type _id: string - :param _id: A unique ID used to refer to this document. - - :type fields: dict - :param fields: A dictionary of key-value pairs to be uploaded . - """ - - d = {'type': 'add', 'id': _id, 'fields': fields} - self.documents_batch.append(d) - - def delete(self, _id): - """ - Schedule a document to be removed from the CloudSearch service - - The document will not actually be scheduled for removal until - :func:`commit` is called - - :type _id: string - :param _id: The unique ID of this document. - """ - - d = {'type': 'delete', 'id': _id} - self.documents_batch.append(d) - - def get_sdf(self): - """ - Generate the working set of documents in Search Data Format (SDF) - - :rtype: string - :returns: JSON-formatted string of the documents in SDF - """ - - return self._sdf if self._sdf else json.dumps(self.documents_batch) - - def clear_sdf(self): - """ - Clear the working documents from this DocumentServiceConnection - - This should be used after :func:`commit` if the connection will be - reused for another set of documents. - """ - - self._sdf = None - self.documents_batch = [] - - def add_sdf_from_s3(self, key_obj): - """ - Load an SDF from S3 - - Using this method will result in documents added through - :func:`add` and :func:`delete` being ignored. - - :type key_obj: :class:`boto.s3.key.Key` - :param key_obj: An S3 key which contains an SDF - """ - #@todo:: (lucas) would be nice if this could just take an s3://uri..." - - self._sdf = key_obj.get_contents_as_string() - - def commit(self): - """ - Actually send an SDF to CloudSearch for processing - - If an SDF file has been explicitly loaded it will be used. Otherwise, - documents added through :func:`add` and :func:`delete` will be used. - - :rtype: :class:`CommitResponse` - :returns: A summary of documents added and deleted - """ - - sdf = self.get_sdf() - - if ': null' in sdf: - boto.log.error('null value in sdf detected. This will probably ' - 'raise 500 error.') - index = sdf.index(': null') - boto.log.error(sdf[index - 100:index + 100]) - - api_version = '2013-01-01' - if self.domain: - api_version = self.domain.layer1.APIVersion - url = "http://%s/%s/documents/batch" % (self.endpoint, api_version) - - # Keep-alive is automatic in a post-1.0 requests world. - session = requests.Session() - session.proxies = self.proxy - adapter = requests.adapters.HTTPAdapter( - pool_connections=20, - pool_maxsize=50, - max_retries=5 - ) - session.mount('http://', adapter) - session.mount('https://', adapter) - r = session.post(url, data=sdf, - headers={'Content-Type': 'application/json'}) - - return CommitResponse(r, self, sdf) - - -class CommitResponse(object): - """Wrapper for response to Cloudsearch document batch commit. - - :type response: :class:`requests.models.Response` - :param response: Response from Cloudsearch /documents/batch API - - :type doc_service: :class:`boto.cloudsearch2.document.DocumentServiceConnection` - :param doc_service: Object containing the documents posted and methods to - retry - - :raises: :class:`boto.exception.BotoServerError` - :raises: :class:`boto.cloudsearch2.document.SearchServiceException` - :raises: :class:`boto.cloudsearch2.document.EncodingError` - :raises: :class:`boto.cloudsearch2.document.ContentTooLongError` - """ - def __init__(self, response, doc_service, sdf): - self.response = response - self.doc_service = doc_service - self.sdf = sdf - - _body = response.content.decode('utf-8') - - try: - self.content = json.loads(_body) - except: - boto.log.error('Error indexing documents.\nResponse Content:\n{0}' - '\n\nSDF:\n{1}'.format(_body, self.sdf)) - raise boto.exception.BotoServerError(self.response.status_code, '', - body=_body) - - self.status = self.content['status'] - if self.status == 'error': - self.errors = [e.get('message') for e in self.content.get('errors', - [])] - for e in self.errors: - if "Illegal Unicode character" in e: - raise EncodingError("Illegal Unicode character in document") - elif e == "The Content-Length is too long": - raise ContentTooLongError("Content was too long") - else: - self.errors = [] - - self.adds = self.content['adds'] - self.deletes = self.content['deletes'] - self._check_num_ops('add', self.adds) - self._check_num_ops('delete', self.deletes) - - def _check_num_ops(self, type_, response_num): - """Raise exception if number of ops in response doesn't match commit - - :type type_: str - :param type_: Type of commit operation: 'add' or 'delete' - - :type response_num: int - :param response_num: Number of adds or deletes in the response. - - :raises: :class:`boto.cloudsearch2.document.CommitMismatchError` - """ - commit_num = len([d for d in self.doc_service.documents_batch - if d['type'] == type_]) - - if response_num != commit_num: - boto.log.debug(self.response.content) - # There will always be a commit mismatch error if there is any - # errors on cloudsearch. self.errors gets lost when this - # CommitMismatchError is raised. Whoever is using boto has no idea - # why their commit failed. They can't even notify the user of the - # cause by parsing the error messages from amazon. So let's - # attach the self.errors to the exceptions if we already spent - # time and effort collecting them out of the response. - exc = CommitMismatchError( - 'Incorrect number of {0}s returned. Commit: {1} Response: {2}' - .format(type_, commit_num, response_num) - ) - exc.errors = self.errors - raise exc diff --git a/awx/lib/site-packages/boto/cloudsearch2/domain.py b/awx/lib/site-packages/boto/cloudsearch2/domain.py deleted file mode 100644 index 956af216d8..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/domain.py +++ /dev/null @@ -1,542 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.cloudsearch2.optionstatus import IndexFieldStatus -from boto.cloudsearch2.optionstatus import ServicePoliciesStatus -from boto.cloudsearch2.optionstatus import ExpressionStatus -from boto.cloudsearch2.optionstatus import AvailabilityOptionsStatus -from boto.cloudsearch2.optionstatus import ScalingParametersStatus -from boto.cloudsearch2.document import DocumentServiceConnection -from boto.cloudsearch2.search import SearchConnection - - -def handle_bool(value): - if value in [True, 'true', 'True', 'TRUE', 1]: - return True - return False - - -class Domain(object): - """ - A Cloudsearch domain. - - :ivar name: The name of the domain. - - :ivar id: The internally generated unique identifier for the domain. - - :ivar created: A boolean which is True if the domain is - created. It can take several minutes to initialize a domain - when CreateDomain is called. Newly created search domains are - returned with a False value for Created until domain creation - is complete - - :ivar deleted: A boolean which is True if the search domain has - been deleted. The system must clean up resources dedicated to - the search domain when delete is called. Newly deleted - search domains are returned from list_domains with a True - value for deleted for several minutes until resource cleanup - is complete. - - :ivar processing: True if processing is being done to activate the - current domain configuration. - - :ivar num_searchable_docs: The number of documents that have been - submittted to the domain and indexed. - - :ivar requires_index_document: True if index_documents needs to be - called to activate the current domain configuration. - - :ivar search_instance_count: The number of search instances that are - available to process search requests. - - :ivar search_instance_type: The instance type that is being used to - process search requests. - - :ivar search_partition_count: The number of partitions across which - the search index is spread. - """ - - def __init__(self, layer1, data): - """ - Constructor - Create a domain object from a layer1 and data params - - :type layer1: :class:`boto.cloudsearch2.layer1.Layer1` object - :param layer1: A :class:`boto.cloudsearch2.layer1.Layer1` object - which is used to perform operations on the domain. - """ - self.layer1 = layer1 - self.update_from_data(data) - - def update_from_data(self, data): - self.created = data['Created'] - self.deleted = data['Deleted'] - self.processing = data['Processing'] - self.requires_index_documents = data['RequiresIndexDocuments'] - self.domain_id = data['DomainId'] - self.domain_name = data['DomainName'] - self.search_instance_count = data['SearchInstanceCount'] - self.search_instance_type = data.get('SearchInstanceType', None) - self.search_partition_count = data['SearchPartitionCount'] - self._doc_service = data['DocService'] - self._service_arn = data['ARN'] - self._search_service = data['SearchService'] - - @property - def service_arn(self): - return self._service_arn - - @property - def doc_service_endpoint(self): - return self._doc_service['Endpoint'] - - @property - def search_service_endpoint(self): - return self._search_service['Endpoint'] - - @property - def created(self): - return self._created - - @created.setter - def created(self, value): - self._created = handle_bool(value) - - @property - def deleted(self): - return self._deleted - - @deleted.setter - def deleted(self, value): - self._deleted = handle_bool(value) - - @property - def processing(self): - return self._processing - - @processing.setter - def processing(self, value): - self._processing = handle_bool(value) - - @property - def requires_index_documents(self): - return self._requires_index_documents - - @requires_index_documents.setter - def requires_index_documents(self, value): - self._requires_index_documents = handle_bool(value) - - @property - def search_partition_count(self): - return self._search_partition_count - - @search_partition_count.setter - def search_partition_count(self, value): - self._search_partition_count = int(value) - - @property - def search_instance_count(self): - return self._search_instance_count - - @search_instance_count.setter - def search_instance_count(self, value): - self._search_instance_count = int(value) - - @property - def name(self): - return self.domain_name - - @property - def id(self): - return self.domain_id - - def delete(self): - """ - Delete this domain and all index data associated with it. - """ - return self.layer1.delete_domain(self.name) - - def get_analysis_schemes(self): - """ - Return a list of Analysis Scheme objects. - """ - return self.layer1.describe_analysis_schemes(self.name) - - def get_availability_options(self): - """ - Return a :class:`boto.cloudsearch2.option.AvailabilityOptionsStatus` - object representing the currently defined availability options for - the domain. - :return: OptionsStatus object - :rtype: :class:`boto.cloudsearch2.option.AvailabilityOptionsStatus` - object - """ - return AvailabilityOptionsStatus( - self, refresh_fn=self.layer1.describe_availability_options, - refresh_key=['DescribeAvailabilityOptionsResponse', - 'DescribeAvailabilityOptionsResult', - 'AvailabilityOptions'], - save_fn=self.layer1.update_availability_options) - - def get_scaling_options(self): - """ - Return a :class:`boto.cloudsearch2.option.ScalingParametersStatus` - object representing the currently defined scaling options for the - domain. - :return: ScalingParametersStatus object - :rtype: :class:`boto.cloudsearch2.option.ScalingParametersStatus` - object - """ - return ScalingParametersStatus( - self, refresh_fn=self.layer1.describe_scaling_parameters, - refresh_key=['DescribeScalingParametersResponse', - 'DescribeScalingParametersResult', - 'ScalingParameters'], - save_fn=self.layer1.update_scaling_parameters) - - def get_access_policies(self): - """ - Return a :class:`boto.cloudsearch2.option.ServicePoliciesStatus` - object representing the currently defined access policies for the - domain. - :return: ServicePoliciesStatus object - :rtype: :class:`boto.cloudsearch2.option.ServicePoliciesStatus` object - """ - return ServicePoliciesStatus( - self, refresh_fn=self.layer1.describe_service_access_policies, - refresh_key=['DescribeServiceAccessPoliciesResponse', - 'DescribeServiceAccessPoliciesResult', - 'AccessPolicies'], - save_fn=self.layer1.update_service_access_policies) - - def index_documents(self): - """ - Tells the search domain to start indexing its documents using - the latest text processing options and IndexFields. This - operation must be invoked to make options whose OptionStatus - has OptionState of RequiresIndexDocuments visible in search - results. - """ - self.layer1.index_documents(self.name) - - def get_index_fields(self, field_names=None): - """ - Return a list of index fields defined for this domain. - :return: list of IndexFieldStatus objects - :rtype: list of :class:`boto.cloudsearch2.option.IndexFieldStatus` - object - """ - data = self.layer1.describe_index_fields(self.name, field_names) - - data = (data['DescribeIndexFieldsResponse'] - ['DescribeIndexFieldsResult'] - ['IndexFields']) - - return [IndexFieldStatus(self, d) for d in data] - - def create_index_field(self, field_name, field_type, - default='', facet=False, returnable=False, - searchable=False, sortable=False, - highlight=False, source_field=None, - analysis_scheme=None): - """ - Defines an ``IndexField``, either replacing an existing - definition or creating a new one. - - :type field_name: string - :param field_name: The name of a field in the search index. - - :type field_type: string - :param field_type: The type of field. Valid values are - int | double | literal | text | date | latlon | - int-array | double-array | literal-array | text-array | date-array - - :type default: string or int - :param default: The default value for the field. If the - field is of type ``int`` this should be an integer value. - Otherwise, it's a string. - - :type facet: bool - :param facet: A boolean to indicate whether facets - are enabled for this field or not. Does not apply to - fields of type ``int, int-array, text, text-array``. - - :type returnable: bool - :param returnable: A boolean to indicate whether values - of this field can be returned in search results or - used in ranking. - - :type searchable: bool - :param searchable: A boolean to indicate whether search - is enabled for this field or not. - - :type sortable: bool - :param sortable: A boolean to indicate whether sorting - is enabled for this field or not. Does not apply to - fields of array types. - - :type highlight: bool - :param highlight: A boolean to indicate whether highlighting - is enabled for this field or not. Does not apply to - fields of type ``double, int, date, latlon`` - - :type source_field: list of strings or string - :param source_field: For array types, this is the list of fields - to treat as the source. For singular types, pass a string only. - - :type analysis_scheme: string - :param analysis_scheme: The analysis scheme to use for this field. - Only applies to ``text | text-array`` field types - - :return: IndexFieldStatus objects - :rtype: :class:`boto.cloudsearch2.option.IndexFieldStatus` object - - :raises: BaseException, InternalException, LimitExceededException, - InvalidTypeException, ResourceNotFoundException - """ - index = { - 'IndexFieldName': field_name, - 'IndexFieldType': field_type - } - if field_type == 'literal': - index['LiteralOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable, - 'SortEnabled': sortable - } - if default: - index['LiteralOptions']['DefaultValue'] = default - if source_field: - index['LiteralOptions']['SourceField'] = source_field - elif field_type == 'literal-array': - index['LiteralArrayOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable - } - if default: - index['LiteralArrayOptions']['DefaultValue'] = default - if source_field: - index['LiteralArrayOptions']['SourceFields'] = \ - ','.join(source_field) - elif field_type == 'int': - index['IntOptions'] = { - 'DefaultValue': default, - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable, - 'SortEnabled': sortable - } - if default: - index['IntOptions']['DefaultValue'] = default - if source_field: - index['IntOptions']['SourceField'] = source_field - elif field_type == 'int-array': - index['IntArrayOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable - } - if default: - index['IntArrayOptions']['DefaultValue'] = default - if source_field: - index['IntArrayOptions']['SourceFields'] = \ - ','.join(source_field) - elif field_type == 'date': - index['DateOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable, - 'SortEnabled': sortable - } - if default: - index['DateOptions']['DefaultValue'] = default - if source_field: - index['DateOptions']['SourceField'] = source_field - elif field_type == 'date-array': - index['DateArrayOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable - } - if default: - index['DateArrayOptions']['DefaultValue'] = default - if source_field: - index['DateArrayOptions']['SourceFields'] = \ - ','.join(source_field) - elif field_type == 'double': - index['DoubleOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable, - 'SortEnabled': sortable - } - if default: - index['DoubleOptions']['DefaultValue'] = default - if source_field: - index['DoubleOptions']['SourceField'] = source_field - elif field_type == 'double-array': - index['DoubleArrayOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable - } - if default: - index['DoubleArrayOptions']['DefaultValue'] = default - if source_field: - index['DoubleArrayOptions']['SourceFields'] = \ - ','.join(source_field) - elif field_type == 'text': - index['TextOptions'] = { - 'ReturnEnabled': returnable, - 'HighlightEnabled': highlight, - 'SortEnabled': sortable - } - if default: - index['TextOptions']['DefaultValue'] = default - if source_field: - index['TextOptions']['SourceField'] = source_field - if analysis_scheme: - index['TextOptions']['AnalysisScheme'] = analysis_scheme - elif field_type == 'text-array': - index['TextArrayOptions'] = { - 'ReturnEnabled': returnable, - 'HighlightEnabled': highlight - } - if default: - index['TextArrayOptions']['DefaultValue'] = default - if source_field: - index['TextArrayOptions']['SourceFields'] = \ - ','.join(source_field) - if analysis_scheme: - index['TextArrayOptions']['AnalysisScheme'] = analysis_scheme - elif field_type == 'latlon': - index['LatLonOptions'] = { - 'FacetEnabled': facet, - 'ReturnEnabled': returnable, - 'SearchEnabled': searchable, - 'SortEnabled': sortable - } - if default: - index['LatLonOptions']['DefaultValue'] = default - if source_field: - index['LatLonOptions']['SourceField'] = source_field - - data = self.layer1.define_index_field(self.name, index) - - data = (data['DefineIndexFieldResponse'] - ['DefineIndexFieldResult'] - ['IndexField']) - - return IndexFieldStatus(self, data, - self.layer1.describe_index_fields) - - def get_expressions(self, names=None): - """ - Return a list of rank expressions defined for this domain. - :return: list of ExpressionStatus objects - :rtype: list of :class:`boto.cloudsearch2.option.ExpressionStatus` - object - """ - fn = self.layer1.describe_expressions - data = fn(self.name, names) - - data = (data['DescribeExpressionsResponse'] - ['DescribeExpressionsResult'] - ['Expressions']) - - return [ExpressionStatus(self, d, fn) for d in data] - - def create_expression(self, name, value): - """ - Create a new expression. - - :type name: string - :param name: The name of an expression for processing - during a search request. - - :type value: string - :param value: The expression to evaluate for ranking - or thresholding while processing a search request. The - Expression syntax is based on JavaScript expressions - and supports: - - * Single value, sort enabled numeric fields (int, double, date) - * Other expressions - * The _score variable, which references a document's relevance - score - * The _time variable, which references the current epoch time - * Integer, floating point, hex, and octal literals - * Arithmetic operators: + - * / % - * Bitwise operators: | & ^ ~ << >> >>> - * Boolean operators (including the ternary operator): && || ! ?: - * Comparison operators: < <= == >= > - * Mathematical functions: abs ceil exp floor ln log2 log10 logn - max min pow sqrt pow - * Trigonometric functions: acos acosh asin asinh atan atan2 atanh - cos cosh sin sinh tanh tan - * The haversin distance function - - Expressions always return an integer value from 0 to the maximum - 64-bit signed integer value (2^63 - 1). Intermediate results are - calculated as double-precision floating point values and the return - value is rounded to the nearest integer. If the expression is - invalid or evaluates to a negative value, it returns 0. If the - expression evaluates to a value greater than the maximum, it - returns the maximum value. - - The source data for an Expression can be the name of an - IndexField of type int or double, another Expression or the - reserved name _score. The _score source is - defined to return as a double from 0 to 10.0 (inclusive) to - indicate how relevant a document is to the search request, - taking into account repetition of search terms in the - document and proximity of search terms to each other in - each matching IndexField in the document. - - For more information about using rank expressions to - customize ranking, see the Amazon CloudSearch Developer - Guide. - - :return: ExpressionStatus object - :rtype: :class:`boto.cloudsearch2.option.ExpressionStatus` object - - :raises: BaseException, InternalException, LimitExceededException, - InvalidTypeException, ResourceNotFoundException - """ - data = self.layer1.define_expression(self.name, name, value) - - data = (data['DefineExpressionResponse'] - ['DefineExpressionResult'] - ['Expression']) - - return ExpressionStatus(self, data, - self.layer1.describe_expressions) - - def get_document_service(self): - return DocumentServiceConnection(domain=self) - - def get_search_service(self): - return SearchConnection(domain=self) - - def __repr__(self): - return '<Domain: %s>' % self.domain_name diff --git a/awx/lib/site-packages/boto/cloudsearch2/exceptions.py b/awx/lib/site-packages/boto/cloudsearch2/exceptions.py deleted file mode 100644 index c114113963..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/exceptions.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Exceptions that are specific to the cloudsearch2 module. -""" -from boto.exception import BotoServerError - - -class InvalidTypeException(BotoServerError): - """ - Raised when an invalid record type is passed to CloudSearch. - """ - pass - - -class LimitExceededException(BotoServerError): - """ - Raised when a limit has been exceeded. - """ - pass - - -class InternalException(BotoServerError): - """ - A generic server-side error. - """ - pass - - -class DisabledOperationException(BotoServerError): - """ - Raised when an operation has been disabled. - """ - pass - - -class ResourceNotFoundException(BotoServerError): - """ - Raised when a requested resource does not exist. - """ - pass - - -class BaseException(BotoServerError): - """ - A generic server-side error. - """ - pass diff --git a/awx/lib/site-packages/boto/cloudsearch2/layer1.py b/awx/lib/site-packages/boto/cloudsearch2/layer1.py deleted file mode 100644 index 0c41762ffb..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/layer1.py +++ /dev/null @@ -1,781 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.cloudsearch2 import exceptions - - -class CloudSearchConnection(AWSQueryConnection): - """ - Amazon CloudSearch Configuration Service - You use the Amazon CloudSearch configuration service to create, - configure, and manage search domains. Configuration service - requests are submitted using the AWS Query protocol. AWS Query - requests are HTTP or HTTPS requests submitted via HTTP GET or POST - with a query parameter named Action. - - The endpoint for configuration service requests is region- - specific: cloudsearch. region .amazonaws.com. For example, - cloudsearch.us-east-1.amazonaws.com. For a current list of - supported regions and endpoints, see `Regions and Endpoints`_. - """ - APIVersion = "2013-01-01" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "cloudsearch.us-east-1.amazonaws.com" - ResponseError = JSONResponseError - - _faults = { - "InvalidTypeException": exceptions.InvalidTypeException, - "LimitExceededException": exceptions.LimitExceededException, - "InternalException": exceptions.InternalException, - "DisabledOperationException": exceptions.DisabledOperationException, - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "BaseException": exceptions.BaseException, - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs or kwargs['host'] is None: - kwargs['host'] = region.endpoint - - super(CloudSearchConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def build_suggesters(self, domain_name): - """ - Indexes the search suggestions. - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - """ - params = {'DomainName': domain_name, } - return self._make_request( - action='BuildSuggesters', - verb='POST', - path='/', params=params) - - def create_domain(self, domain_name): - """ - Creates a new search domain. For more information, see - `Creating a Search Domain`_ in the Amazon CloudSearch - Developer Guide . - - :type domain_name: string - :param domain_name: A name for the domain you are creating. Allowed - characters are a-z (lower-case letters), 0-9, and hyphen (-). - Domain names must start with a letter or number and be at least 3 - and no more than 28 characters long. - - """ - params = {'DomainName': domain_name, } - return self._make_request( - action='CreateDomain', - verb='POST', - path='/', params=params) - - def define_analysis_scheme(self, domain_name, analysis_scheme): - """ - Configures an analysis scheme that can be applied to a `text` - or `text-array` field to define language-specific text - processing options. For more information, see `Configuring - Analysis Schemes`_ in the Amazon CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type analysis_scheme: dict - :param analysis_scheme: Configuration information for an analysis - scheme. Each analysis scheme has a unique name and specifies the - language of the text to be processed. The following options can be - configured for an analysis scheme: `Synonyms`, `Stopwords`, - `StemmingDictionary`, and `AlgorithmicStemming`. - - """ - params = {'DomainName': domain_name, } - self.build_complex_param(params, 'AnalysisScheme', - analysis_scheme) - return self._make_request( - action='DefineAnalysisScheme', - verb='POST', - path='/', params=params) - - def define_expression(self, domain_name, expression): - """ - Configures an `Expression` for the search domain. Used to - create new expressions and modify existing ones. If the - expression exists, the new configuration replaces the old one. - For more information, see `Configuring Expressions`_ in the - Amazon CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type expression: dict - :param expression: A named expression that can be evaluated at search - time. Can be used to sort the search results, define other - expressions, or return computed information in the search results. - - """ - params = {'DomainName': domain_name, } - self.build_complex_param(params, 'Expression', - expression) - return self._make_request( - action='DefineExpression', - verb='POST', - path='/', params=params) - - def define_index_field(self, domain_name, index_field): - """ - Configures an `IndexField` for the search domain. Used to - create new fields and modify existing ones. You must specify - the name of the domain you are configuring and an index field - configuration. The index field configuration specifies a - unique name, the index field type, and the options you want to - configure for the field. The options you can specify depend on - the `IndexFieldType`. If the field exists, the new - configuration replaces the old one. For more information, see - `Configuring Index Fields`_ in the Amazon CloudSearch - Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type index_field: dict - :param index_field: The index field and field options you want to - configure. - - """ - params = {'DomainName': domain_name, } - self.build_complex_param(params, 'IndexField', - index_field) - return self._make_request( - action='DefineIndexField', - verb='POST', - path='/', params=params) - - def define_suggester(self, domain_name, suggester): - """ - Configures a suggester for a domain. A suggester enables you - to display possible matches before users finish typing their - queries. When you configure a suggester, you must specify the - name of the text field you want to search for possible matches - and a unique name for the suggester. For more information, see - `Getting Search Suggestions`_ in the Amazon CloudSearch - Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type suggester: dict - :param suggester: Configuration information for a search suggester. - Each suggester has a unique name and specifies the text field you - want to use for suggestions. The following options can be - configured for a suggester: `FuzzyMatching`, `SortExpression`. - - """ - params = {'DomainName': domain_name, } - self.build_complex_param(params, 'Suggester', - suggester) - return self._make_request( - action='DefineSuggester', - verb='POST', - path='/', params=params) - - def delete_analysis_scheme(self, domain_name, analysis_scheme_name): - """ - Deletes an analysis scheme. For more information, see - `Configuring Analysis Schemes`_ in the Amazon CloudSearch - Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type analysis_scheme_name: string - :param analysis_scheme_name: The name of the analysis scheme you want - to delete. - - """ - params = { - 'DomainName': domain_name, - 'AnalysisSchemeName': analysis_scheme_name, - } - return self._make_request( - action='DeleteAnalysisScheme', - verb='POST', - path='/', params=params) - - def delete_domain(self, domain_name): - """ - Permanently deletes a search domain and all of its data. Once - a domain has been deleted, it cannot be recovered. For more - information, see `Deleting a Search Domain`_ in the Amazon - CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: The name of the domain you want to permanently - delete. - - """ - params = {'DomainName': domain_name, } - return self._make_request( - action='DeleteDomain', - verb='POST', - path='/', params=params) - - def delete_expression(self, domain_name, expression_name): - """ - Removes an `Expression` from the search domain. For more - information, see `Configuring Expressions`_ in the Amazon - CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type expression_name: string - :param expression_name: The name of the `Expression` to delete. - - """ - params = { - 'DomainName': domain_name, - 'ExpressionName': expression_name, - } - return self._make_request( - action='DeleteExpression', - verb='POST', - path='/', params=params) - - def delete_index_field(self, domain_name, index_field_name): - """ - Removes an `IndexField` from the search domain. For more - information, see `Configuring Index Fields`_ in the Amazon - CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type index_field_name: string - :param index_field_name: The name of the index field your want to - remove from the domain's indexing options. - - """ - params = { - 'DomainName': domain_name, - 'IndexFieldName': index_field_name, - } - return self._make_request( - action='DeleteIndexField', - verb='POST', - path='/', params=params) - - def delete_suggester(self, domain_name, suggester_name): - """ - Deletes a suggester. For more information, see `Getting Search - Suggestions`_ in the Amazon CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type suggester_name: string - :param suggester_name: Specifies the name of the suggester you want to - delete. - - """ - params = { - 'DomainName': domain_name, - 'SuggesterName': suggester_name, - } - return self._make_request( - action='DeleteSuggester', - verb='POST', - path='/', params=params) - - def describe_analysis_schemes(self, domain_name, - analysis_scheme_names=None, deployed=None): - """ - Gets the analysis schemes configured for a domain. An analysis - scheme defines language-specific text processing options for a - `text` field. Can be limited to specific analysis schemes by - name. By default, shows all analysis schemes and includes any - pending changes to the configuration. Set the `Deployed` - option to `True` to show the active configuration and exclude - pending changes. For more information, see `Configuring - Analysis Schemes`_ in the Amazon CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: The name of the domain you want to describe. - - :type analysis_scheme_names: list - :param analysis_scheme_names: The analysis schemes you want to - describe. - - :type deployed: boolean - :param deployed: Whether to display the deployed configuration ( - `True`) or include any pending changes ( `False`). Defaults to - `False`. - - """ - params = {'DomainName': domain_name, } - if analysis_scheme_names is not None: - self.build_list_params(params, - analysis_scheme_names, - 'AnalysisSchemeNames.member') - if deployed is not None: - params['Deployed'] = str( - deployed).lower() - return self._make_request( - action='DescribeAnalysisSchemes', - verb='POST', - path='/', params=params) - - def describe_availability_options(self, domain_name, deployed=None): - """ - Gets the availability options configured for a domain. By - default, shows the configuration with any pending changes. Set - the `Deployed` option to `True` to show the active - configuration and exclude pending changes. For more - information, see `Configuring Availability Options`_ in the - Amazon CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: The name of the domain you want to describe. - - :type deployed: boolean - :param deployed: Whether to display the deployed configuration ( - `True`) or include any pending changes ( `False`). Defaults to - `False`. - - """ - params = {'DomainName': domain_name, } - if deployed is not None: - params['Deployed'] = str( - deployed).lower() - return self._make_request( - action='DescribeAvailabilityOptions', - verb='POST', - path='/', params=params) - - def describe_domains(self, domain_names=None): - """ - Gets information about the search domains owned by this - account. Can be limited to specific domains. Shows all domains - by default. To get the number of searchable documents in a - domain, use the console or submit a `matchall` request to your - domain's search endpoint: - `q=matchall&q.parser=structured&size=0`. For more information, - see `Getting Information about a Search Domain`_ in the Amazon - CloudSearch Developer Guide . - - :type domain_names: list - :param domain_names: The names of the domains you want to include in - the response. - - """ - params = {} - if domain_names is not None: - self.build_list_params(params, - domain_names, - 'DomainNames.member') - return self._make_request( - action='DescribeDomains', - verb='POST', - path='/', params=params) - - def describe_expressions(self, domain_name, expression_names=None, - deployed=None): - """ - Gets the expressions configured for the search domain. Can be - limited to specific expressions by name. By default, shows all - expressions and includes any pending changes to the - configuration. Set the `Deployed` option to `True` to show the - active configuration and exclude pending changes. For more - information, see `Configuring Expressions`_ in the Amazon - CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: The name of the domain you want to describe. - - :type expression_names: list - :param expression_names: Limits the `DescribeExpressions` response to - the specified expressions. If not specified, all expressions are - shown. - - :type deployed: boolean - :param deployed: Whether to display the deployed configuration ( - `True`) or include any pending changes ( `False`). Defaults to - `False`. - - """ - params = {'DomainName': domain_name, } - if expression_names is not None: - self.build_list_params(params, - expression_names, - 'ExpressionNames.member') - if deployed is not None: - params['Deployed'] = str( - deployed).lower() - return self._make_request( - action='DescribeExpressions', - verb='POST', - path='/', params=params) - - def describe_index_fields(self, domain_name, field_names=None, - deployed=None): - """ - Gets information about the index fields configured for the - search domain. Can be limited to specific fields by name. By - default, shows all fields and includes any pending changes to - the configuration. Set the `Deployed` option to `True` to show - the active configuration and exclude pending changes. For more - information, see `Getting Domain Information`_ in the Amazon - CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: The name of the domain you want to describe. - - :type field_names: list - :param field_names: A list of the index fields you want to describe. If - not specified, information is returned for all configured index - fields. - - :type deployed: boolean - :param deployed: Whether to display the deployed configuration ( - `True`) or include any pending changes ( `False`). Defaults to - `False`. - - """ - params = {'DomainName': domain_name, } - if field_names is not None: - self.build_list_params(params, - field_names, - 'FieldNames.member') - if deployed is not None: - params['Deployed'] = str( - deployed).lower() - return self._make_request( - action='DescribeIndexFields', - verb='POST', - path='/', params=params) - - def describe_scaling_parameters(self, domain_name): - """ - Gets the scaling parameters configured for a domain. A - domain's scaling parameters specify the desired search - instance type and replication count. For more information, see - `Configuring Scaling Options`_ in the Amazon CloudSearch - Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - """ - params = {'DomainName': domain_name, } - return self._make_request( - action='DescribeScalingParameters', - verb='POST', - path='/', params=params) - - def describe_service_access_policies(self, domain_name, deployed=None): - """ - Gets information about the access policies that control access - to the domain's document and search endpoints. By default, - shows the configuration with any pending changes. Set the - `Deployed` option to `True` to show the active configuration - and exclude pending changes. For more information, see - `Configuring Access for a Search Domain`_ in the Amazon - CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: The name of the domain you want to describe. - - :type deployed: boolean - :param deployed: Whether to display the deployed configuration ( - `True`) or include any pending changes ( `False`). Defaults to - `False`. - - """ - params = {'DomainName': domain_name, } - if deployed is not None: - params['Deployed'] = str( - deployed).lower() - return self._make_request( - action='DescribeServiceAccessPolicies', - verb='POST', - path='/', params=params) - - def describe_suggesters(self, domain_name, suggester_names=None, - deployed=None): - """ - Gets the suggesters configured for a domain. A suggester - enables you to display possible matches before users finish - typing their queries. Can be limited to specific suggesters by - name. By default, shows all suggesters and includes any - pending changes to the configuration. Set the `Deployed` - option to `True` to show the active configuration and exclude - pending changes. For more information, see `Getting Search - Suggestions`_ in the Amazon CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: The name of the domain you want to describe. - - :type suggester_names: list - :param suggester_names: The suggesters you want to describe. - - :type deployed: boolean - :param deployed: Whether to display the deployed configuration ( - `True`) or include any pending changes ( `False`). Defaults to - `False`. - - """ - params = {'DomainName': domain_name, } - if suggester_names is not None: - self.build_list_params(params, - suggester_names, - 'SuggesterNames.member') - if deployed is not None: - params['Deployed'] = str( - deployed).lower() - return self._make_request( - action='DescribeSuggesters', - verb='POST', - path='/', params=params) - - def index_documents(self, domain_name): - """ - Tells the search domain to start indexing its documents using - the latest indexing options. This operation must be invoked to - activate options whose OptionStatus is - `RequiresIndexDocuments`. - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - """ - params = {'DomainName': domain_name, } - return self._make_request( - action='IndexDocuments', - verb='POST', - path='/', params=params) - - def list_domain_names(self): - """ - Lists all search domains owned by an account. - """ - params = {} - return self._make_request( - action='ListDomainNames', - verb='POST', - path='/', params=params) - - def update_availability_options(self, domain_name, multi_az): - """ - Configures the availability options for a domain. Enabling the - Multi-AZ option expands an Amazon CloudSearch domain to an - additional Availability Zone in the same Region to increase - fault tolerance in the event of a service disruption. Changes - to the Multi-AZ option can take about half an hour to become - active. For more information, see `Configuring Availability - Options`_ in the Amazon CloudSearch Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type multi_az: boolean - :param multi_az: You expand an existing search domain to a second - Availability Zone by setting the Multi-AZ option to true. - Similarly, you can turn off the Multi-AZ option to downgrade the - domain to a single Availability Zone by setting the Multi-AZ option - to `False`. - - """ - params = {'DomainName': domain_name, 'MultiAZ': multi_az, } - return self._make_request( - action='UpdateAvailabilityOptions', - verb='POST', - path='/', params=params) - - def update_scaling_parameters(self, domain_name, scaling_parameters): - """ - Configures scaling parameters for a domain. A domain's scaling - parameters specify the desired search instance type and - replication count. Amazon CloudSearch will still automatically - scale your domain based on the volume of data and traffic, but - not below the desired instance type and replication count. If - the Multi-AZ option is enabled, these values control the - resources used per Availability Zone. For more information, - see `Configuring Scaling Options`_ in the Amazon CloudSearch - Developer Guide . - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type scaling_parameters: dict - :param scaling_parameters: The desired instance type and desired number - of replicas of each index partition. - - """ - params = {'DomainName': domain_name, } - self.build_complex_param(params, 'ScalingParameters', - scaling_parameters) - return self._make_request( - action='UpdateScalingParameters', - verb='POST', - path='/', params=params) - - def update_service_access_policies(self, domain_name, access_policies): - """ - Configures the access rules that control access to the - domain's document and search endpoints. For more information, - see ` Configuring Access for an Amazon CloudSearch Domain`_. - - :type domain_name: string - :param domain_name: A string that represents the name of a domain. - Domain names are unique across the domains owned by an account - within an AWS region. Domain names start with a letter or number - and can contain the following characters: a-z (lowercase), 0-9, and - - (hyphen). - - :type access_policies: string - :param access_policies: The access rules you want to configure. These - rules replace any existing rules. - - """ - params = { - 'DomainName': domain_name, - 'AccessPolicies': access_policies, - } - return self._make_request( - action='UpdateServiceAccessPolicies', - verb='POST', - path='/', params=params) - - def build_complex_param(self, params, label, value): - """Serialize a structure. - - For example:: - - param_type = 'structure' - label = 'IndexField' - value = {'IndexFieldName': 'a', 'IntOptions': {'DefaultValue': 5}} - - would result in the params dict being updated with these params:: - - IndexField.IndexFieldName = a - IndexField.IntOptions.DefaultValue = 5 - - :type params: dict - :param params: The params dict. The complex list params - will be added to this dict. - - :type label: str - :param label: String label for param key - - :type value: any - :param value: The value to serialize - """ - for k, v in value.items(): - if isinstance(v, dict): - for k2, v2 in v.items(): - self.build_complex_param(params, label + '.' + k, v) - elif isinstance(v, bool): - params['%s.%s' % (label, k)] = v and 'true' or 'false' - else: - params['%s.%s' % (label, k)] = v - - def _make_request(self, action, verb, path, params): - params['ContentType'] = 'JSON' - response = self.make_request(action=action, verb='POST', - path='/', params=params) - body = response.read().decode('utf-8') - boto.log.debug(body) - if response.status == 200: - return json.loads(body) - else: - json_body = json.loads(body) - fault_name = json_body.get('Error', {}).get('Code', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/cloudsearch2/layer2.py b/awx/lib/site-packages/boto/cloudsearch2/layer2.py deleted file mode 100644 index c4840482a0..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/layer2.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.cloudsearch2.layer1 import CloudSearchConnection -from boto.cloudsearch2.domain import Domain -from boto.compat import six - - -class Layer2(object): - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - host=None, debug=0, session_token=None, region=None, - validate_certs=True): - - if isinstance(region, six.string_types): - import boto.cloudsearch2 - for region_info in boto.cloudsearch2.regions(): - if region_info.name == region: - region = region_info - break - - self.layer1 = CloudSearchConnection( - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - is_secure=is_secure, - port=port, - proxy=proxy, - proxy_port=proxy_port, - host=host, - debug=debug, - security_token=session_token, - region=region, - validate_certs=validate_certs) - - def list_domains(self, domain_names=None): - """ - Return a list of objects for each domain defined in the - current account. - :rtype: list of :class:`boto.cloudsearch2.domain.Domain` - """ - domain_data = self.layer1.describe_domains(domain_names) - - domain_data = (domain_data['DescribeDomainsResponse'] - ['DescribeDomainsResult'] - ['DomainStatusList']) - - return [Domain(self.layer1, data) for data in domain_data] - - def create_domain(self, domain_name): - """ - Create a new CloudSearch domain and return the corresponding object. - :return: Domain object, or None if the domain isn't found - :rtype: :class:`boto.cloudsearch2.domain.Domain` - """ - data = self.layer1.create_domain(domain_name) - return Domain(self.layer1, data['CreateDomainResponse'] - ['CreateDomainResult'] - ['DomainStatus']) - - def lookup(self, domain_name): - """ - Lookup a single domain - :param domain_name: The name of the domain to look up - :type domain_name: str - - :return: Domain object, or None if the domain isn't found - :rtype: :class:`boto.cloudsearch2.domain.Domain` - """ - domains = self.list_domains(domain_names=[domain_name]) - if len(domains) > 0: - return domains[0] diff --git a/awx/lib/site-packages/boto/cloudsearch2/optionstatus.py b/awx/lib/site-packages/boto/cloudsearch2/optionstatus.py deleted file mode 100644 index 0a45bea4f0..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/optionstatus.py +++ /dev/null @@ -1,233 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.compat import json - - -class OptionStatus(dict): - """ - Presents a combination of status field (defined below) which are - accessed as attributes and option values which are stored in the - native Python dictionary. In this class, the option values are - merged from a JSON object that is stored as the Option part of - the object. - - :ivar domain_name: The name of the domain this option is associated with. - :ivar create_date: A timestamp for when this option was created. - :ivar state: The state of processing a change to an option. - Possible values: - - * RequiresIndexDocuments: the option's latest value will not - be visible in searches until IndexDocuments has been called - and indexing is complete. - * Processing: the option's latest value is not yet visible in - all searches but is in the process of being activated. - * Active: the option's latest value is completely visible. - - :ivar update_date: A timestamp for when this option was updated. - :ivar update_version: A unique integer that indicates when this - option was last updated. - """ - - def __init__(self, domain, data=None, refresh_fn=None, refresh_key=None, - save_fn=None): - self.domain = domain - self.refresh_fn = refresh_fn - self.refresh_key = refresh_key - self.save_fn = save_fn - self.refresh(data) - - def _update_status(self, status): - self.creation_date = status['CreationDate'] - self.status = status['State'] - self.update_date = status['UpdateDate'] - self.update_version = int(status['UpdateVersion']) - - def _update_options(self, options): - if options: - self.update(options) - - def refresh(self, data=None): - """ - Refresh the local state of the object. You can either pass - new state data in as the parameter ``data`` or, if that parameter - is omitted, the state data will be retrieved from CloudSearch. - """ - if not data: - if self.refresh_fn: - data = self.refresh_fn(self.domain.name) - - if data and self.refresh_key: - # Attempt to pull out the right nested bag of data - for key in self.refresh_key: - data = data[key] - if data: - self._update_status(data['Status']) - self._update_options(data['Options']) - - def to_json(self): - """ - Return the JSON representation of the options as a string. - """ - return json.dumps(self) - - def save(self): - """ - Write the current state of the local object back to the - CloudSearch service. - """ - if self.save_fn: - data = self.save_fn(self.domain.name, self.to_json()) - self.refresh(data) - - -class IndexFieldStatus(OptionStatus): - def save(self): - pass - - -class AvailabilityOptionsStatus(OptionStatus): - def save(self): - pass - - -class ScalingParametersStatus(IndexFieldStatus): - pass - - -class ExpressionStatus(IndexFieldStatus): - pass - - -class ServicePoliciesStatus(OptionStatus): - - def new_statement(self, arn, ip): - """ - Returns a new policy statement that will allow - access to the service described by ``arn`` by the - ip specified in ``ip``. - - :type arn: string - :param arn: The Amazon Resource Notation identifier for the - service you wish to provide access to. This would be - either the search service or the document service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - return { - "Effect": "Allow", - "Action": "*", # Docs say use GET, but denies unless * - "Resource": arn, - "Condition": { - "IpAddress": { - "aws:SourceIp": [ip] - } - } - } - - def _allow_ip(self, arn, ip): - if 'Statement' not in self: - s = self.new_statement(arn, ip) - self['Statement'] = [s] - self.save() - else: - add_statement = True - for statement in self['Statement']: - if statement['Resource'] == arn: - for condition_name in statement['Condition']: - if condition_name == 'IpAddress': - add_statement = False - condition = statement['Condition'][condition_name] - if ip not in condition['aws:SourceIp']: - condition['aws:SourceIp'].append(ip) - - if add_statement: - s = self.new_statement(arn, ip) - self['Statement'].append(s) - self.save() - - def allow_search_ip(self, ip): - """ - Add the provided ip address or CIDR block to the list of - allowable address for the search service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.service_arn - self._allow_ip(arn, ip) - - def allow_doc_ip(self, ip): - """ - Add the provided ip address or CIDR block to the list of - allowable address for the document service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.service_arn - self._allow_ip(arn, ip) - - def _disallow_ip(self, arn, ip): - if 'Statement' not in self: - return - need_update = False - for statement in self['Statement']: - if statement['Resource'] == arn: - for condition_name in statement['Condition']: - if condition_name == 'IpAddress': - condition = statement['Condition'][condition_name] - if ip in condition['aws:SourceIp']: - condition['aws:SourceIp'].remove(ip) - need_update = True - if need_update: - self.save() - - def disallow_search_ip(self, ip): - """ - Remove the provided ip address or CIDR block from the list of - allowable address for the search service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.service_arn - self._disallow_ip(arn, ip) - - def disallow_doc_ip(self, ip): - """ - Remove the provided ip address or CIDR block from the list of - allowable address for the document service. - - :type ip: string - :param ip: An IP address or CIDR block you wish to grant access - to. - """ - arn = self.domain.service_arn - self._disallow_ip(arn, ip) diff --git a/awx/lib/site-packages/boto/cloudsearch2/search.py b/awx/lib/site-packages/boto/cloudsearch2/search.py deleted file mode 100644 index 634faf85e8..0000000000 --- a/awx/lib/site-packages/boto/cloudsearch2/search.py +++ /dev/null @@ -1,367 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from math import ceil -from boto.compat import json, map, six -import requests - -SIMPLE = 'simple' -STRUCTURED = 'structured' -LUCENE = 'lucene' -DISMAX = 'dismax' - - -class SearchServiceException(Exception): - pass - - -class SearchResults(object): - def __init__(self, **attrs): - self.rid = attrs['status']['rid'] - self.time_ms = attrs['status']['time-ms'] - self.hits = attrs['hits']['found'] - self.docs = attrs['hits']['hit'] - self.start = attrs['hits']['start'] - self.query = attrs['query'] - self.search_service = attrs['search_service'] - - self.facets = {} - if 'facets' in attrs: - for (facet, values) in attrs['facets'].items(): - if 'buckets' in values: - self.facets[facet] = dict((k, v) for (k, v) in map(lambda x: (x['value'], x['count']), values.get('buckets', []))) - - self.num_pages_needed = ceil(self.hits / self.query.real_size) - - def __len__(self): - return len(self.docs) - - def __iter__(self): - return iter(self.docs) - - def next_page(self): - """Call Cloudsearch to get the next page of search results - - :rtype: :class:`boto.cloudsearch2.search.SearchResults` - :return: the following page of search results - """ - if self.query.page <= self.num_pages_needed: - self.query.start += self.query.real_size - self.query.page += 1 - return self.search_service(self.query) - else: - raise StopIteration - - -class Query(object): - - RESULTS_PER_PAGE = 500 - - def __init__(self, q=None, parser=None, fq=None, expr=None, - return_fields=None, size=10, start=0, sort=None, - facet=None, highlight=None, partial=None, options=None): - - self.q = q - self.parser = parser - self.fq = fq - self.expr = expr or {} - self.sort = sort or [] - self.return_fields = return_fields or [] - self.start = start - self.facet = facet or {} - self.highlight = highlight or {} - self.partial = partial - self.options = options - self.page = 0 - self.update_size(size) - - def update_size(self, new_size): - self.size = new_size - self.real_size = Query.RESULTS_PER_PAGE if (self.size > - Query.RESULTS_PER_PAGE or self.size == 0) else self.size - - def to_params(self): - """Transform search parameters from instance properties to a dictionary - - :rtype: dict - :return: search parameters - """ - params = {'start': self.start, 'size': self.real_size} - - if self.q: - params['q'] = self.q - - if self.parser: - params['q.parser'] = self.parser - - if self.fq: - params['fq'] = self.fq - - if self.expr: - for k, v in six.iteritems(self.expr): - params['expr.%s' % k] = v - - if self.facet: - for k, v in six.iteritems(self.facet): - if not isinstance(v, six.string_types): - v = json.dumps(v) - params['facet.%s' % k] = v - - if self.highlight: - for k, v in six.iteritems(self.highlight): - params['highlight.%s' % k] = v - - if self.options: - params['q.options'] = self.options - - if self.return_fields: - params['return'] = ','.join(self.return_fields) - - if self.partial is not None: - params['partial'] = self.partial - - if self.sort: - params['sort'] = ','.join(self.sort) - - return params - - -class SearchConnection(object): - - def __init__(self, domain=None, endpoint=None): - self.domain = domain - self.endpoint = endpoint - self.session = requests.Session() - - # Copy proxy settings from connection - if self.domain and self.domain.layer1 and self.domain.layer1.use_proxy: - self.session.proxies['http'] = self.domain.layer1.get_proxy_url_with_auth() - - if not endpoint: - self.endpoint = domain.search_service_endpoint - - def build_query(self, q=None, parser=None, fq=None, rank=None, return_fields=None, - size=10, start=0, facet=None, highlight=None, sort=None, - partial=None, options=None): - return Query(q=q, parser=parser, fq=fq, expr=rank, return_fields=return_fields, - size=size, start=start, facet=facet, highlight=highlight, - sort=sort, partial=partial, options=options) - - def search(self, q=None, parser=None, fq=None, rank=None, return_fields=None, - size=10, start=0, facet=None, highlight=None, sort=None, partial=None, - options=None): - """ - Send a query to CloudSearch - - Each search query should use at least the q or bq argument to specify - the search parameter. The other options are used to specify the - criteria of the search. - - :type q: string - :param q: A string to search the default search fields for. - - :type parser: string - :param parser: The parser to use. 'simple', 'structured', 'lucene', 'dismax' - - :type fq: string - :param fq: The filter query to use. - - :type sort: List of strings - :param sort: A list of fields or rank expressions used to order the - search results. Order is handled by adding 'desc' or 'asc' after the field name. - ``['year desc', 'author asc']`` - - :type return_fields: List of strings - :param return_fields: A list of fields which should be returned by the - search. If this field is not specified, only IDs will be returned. - ``['headline']`` - - :type size: int - :param size: Number of search results to specify - - :type start: int - :param start: Offset of the first search result to return (can be used - for paging) - - :type facet: dict - :param facet: Dictionary of fields for which facets should be returned - The facet value is string of JSON options - ``{'year': '{sort:"bucket", size:3}', 'genres': '{buckets:["Action","Adventure","Sci-Fi"]}'}`` - - :type highlight: dict - :param highlight: Dictionary of fields for which highlights should be returned - The facet value is string of JSON options - ``{'genres': '{format:'text',max_phrases:2,pre_tag:'<b>',post_tag:'</b>'}'}`` - - :type partial: bool - :param partial: Should partial results from a partioned service be returned if - one or more index partitions are unreachable. - - :type options: str - :param options: Options for the query parser specified in *parser*. - Specified as a string in JSON format. - ``{fields: ['title^5', 'description']}`` - - :rtype: :class:`boto.cloudsearch2.search.SearchResults` - :return: Returns the results of this search - - The following examples all assume we have indexed a set of documents - with fields: *author*, *date*, *headline* - - A simple search will look for documents whose default text search - fields will contain the search word exactly: - - >>> search(q='Tim') # Return documents with the word Tim in them (but not Timothy) - - A simple search with more keywords will return documents whose default - text search fields contain the search strings together or separately. - - >>> search(q='Tim apple') # Will match "tim" and "apple" - - More complex searches require the boolean search operator. - - Wildcard searches can be used to search for any words that start with - the search string. - - >>> search(q="'Tim*'") # Return documents with words like Tim or Timothy) - - Search terms can also be combined. Allowed operators are "and", "or", - "not", "field", "optional", "token", "phrase", or "filter" - - >>> search(q="(and 'Tim' (field author 'John Smith'))", parser='structured') - - Facets allow you to show classification information about the search - results. For example, you can retrieve the authors who have written - about Tim with a max of 3 - - >>> search(q='Tim', facet={'Author': '{sort:"bucket", size:3}'}) - """ - - query = self.build_query(q=q, parser=parser, fq=fq, rank=rank, - return_fields=return_fields, - size=size, start=start, facet=facet, - highlight=highlight, sort=sort, - partial=partial, options=options) - return self(query) - - def __call__(self, query): - """Make a call to CloudSearch - - :type query: :class:`boto.cloudsearch2.search.Query` - :param query: A group of search criteria - - :rtype: :class:`boto.cloudsearch2.search.SearchResults` - :return: search results - """ - api_version = '2013-01-01' - if self.domain: - api_version = self.domain.layer1.APIVersion - url = "http://%s/%s/search" % (self.endpoint, api_version) - params = query.to_params() - - r = self.session.get(url, params=params) - _body = r.content.decode('utf-8') - try: - data = json.loads(_body) - except ValueError: - if r.status_code == 403: - msg = '' - import re - g = re.search('<html><body><h1>403 Forbidden</h1>([^<]+)<', _body) - try: - msg = ': %s' % (g.groups()[0].strip()) - except AttributeError: - pass - raise SearchServiceException('Authentication error from Amazon%s' % msg) - raise SearchServiceException("Got non-json response from Amazon. %s" % _body, query) - - if 'messages' in data and 'error' in data: - for m in data['messages']: - if m['severity'] == 'fatal': - raise SearchServiceException("Error processing search %s " - "=> %s" % (params, m['message']), query) - elif 'error' in data: - raise SearchServiceException("Unknown error processing search %s" - % json.dumps(data), query) - - data['query'] = query - data['search_service'] = self - - return SearchResults(**data) - - def get_all_paged(self, query, per_page): - """Get a generator to iterate over all pages of search results - - :type query: :class:`boto.cloudsearch2.search.Query` - :param query: A group of search criteria - - :type per_page: int - :param per_page: Number of docs in each :class:`boto.cloudsearch2.search.SearchResults` object. - - :rtype: generator - :return: Generator containing :class:`boto.cloudsearch2.search.SearchResults` - """ - query.update_size(per_page) - page = 0 - num_pages_needed = 0 - while page <= num_pages_needed: - results = self(query) - num_pages_needed = results.num_pages_needed - yield results - query.start += query.real_size - page += 1 - - def get_all_hits(self, query): - """Get a generator to iterate over all search results - - Transparently handles the results paging from Cloudsearch - search results so even if you have many thousands of results - you can iterate over all results in a reasonably efficient - manner. - - :type query: :class:`boto.cloudsearch2.search.Query` - :param query: A group of search criteria - - :rtype: generator - :return: All docs matching query - """ - page = 0 - num_pages_needed = 0 - while page <= num_pages_needed: - results = self(query) - num_pages_needed = results.num_pages_needed - for doc in results: - yield doc - query.start += query.real_size - page += 1 - - def get_num_hits(self, query): - """Return the total number of hits for query - - :type query: :class:`boto.cloudsearch2.search.Query` - :param query: a group of search criteria - - :rtype: int - :return: Total number of hits for query - """ - query.update_size(1) - return self(query).hits diff --git a/awx/lib/site-packages/boto/cloudtrail/__init__.py b/awx/lib/site-packages/boto/cloudtrail/__init__.py deleted file mode 100644 index 263caffa6d..0000000000 --- a/awx/lib/site-packages/boto/cloudtrail/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the AWS Cloudtrail service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.cloudtrail.layer1 import CloudTrailConnection - return get_regions('cloudtrail', connection_cls=CloudTrailConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/cloudtrail/exceptions.py b/awx/lib/site-packages/boto/cloudtrail/exceptions.py deleted file mode 100644 index ac4efbd22a..0000000000 --- a/awx/lib/site-packages/boto/cloudtrail/exceptions.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -Exceptions that are specific to the cloudtrail module. -""" -from boto.exception import BotoServerError - - -class InvalidSnsTopicNameException(BotoServerError): - """ - Raised when an invalid SNS topic name is passed to Cloudtrail. - """ - pass - - -class InvalidS3BucketNameException(BotoServerError): - """ - Raised when an invalid S3 bucket name is passed to Cloudtrail. - """ - pass - - -class TrailAlreadyExistsException(BotoServerError): - """ - Raised when the given trail name already exists. - """ - pass - - -class InsufficientSnsTopicPolicyException(BotoServerError): - """ - Raised when the SNS topic does not allow Cloudtrail to post - messages. - """ - pass - - -class InvalidTrailNameException(BotoServerError): - """ - Raised when the trail name is invalid. - """ - pass - - -class InternalErrorException(BotoServerError): - """ - Raised when there was an internal Cloudtrail error. - """ - pass - - -class TrailNotFoundException(BotoServerError): - """ - Raised when the given trail name is not found. - """ - pass - - -class S3BucketDoesNotExistException(BotoServerError): - """ - Raised when the given S3 bucket does not exist. - """ - pass - - -class TrailNotProvidedException(BotoServerError): - """ - Raised when no trail name was provided. - """ - pass - - -class InvalidS3PrefixException(BotoServerError): - """ - Raised when an invalid key prefix is given. - """ - pass - - -class MaximumNumberOfTrailsExceededException(BotoServerError): - """ - Raised when no more trails can be created. - """ - pass - - -class InsufficientS3BucketPolicyException(BotoServerError): - """ - Raised when the S3 bucket does not allow Cloudtrail to - write files into the prefix. - """ - pass diff --git a/awx/lib/site-packages/boto/cloudtrail/layer1.py b/awx/lib/site-packages/boto/cloudtrail/layer1.py deleted file mode 100644 index 960b00da11..0000000000 --- a/awx/lib/site-packages/boto/cloudtrail/layer1.py +++ /dev/null @@ -1,352 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.cloudtrail import exceptions -from boto.compat import json - - -class CloudTrailConnection(AWSQueryConnection): - """ - AWS Cloud Trail - This is the CloudTrail API Reference. It provides descriptions of - actions, data types, common parameters, and common errors for - CloudTrail. - - CloudTrail is a web service that records AWS API calls for your - AWS account and delivers log files to an Amazon S3 bucket. The - recorded information includes the identity of the user, the start - time of the AWS API call, the source IP address, the request - parameters, and the response elements returned by the service. - - As an alternative to using the API, you can use one of the AWS - SDKs, which consist of libraries and sample code for various - programming languages and platforms (Java, Ruby, .NET, iOS, - Android, etc.). The SDKs provide a convenient way to create - programmatic access to AWSCloudTrail. For example, the SDKs take - care of cryptographically signing requests, managing errors, and - retrying requests automatically. For information about the AWS - SDKs, including how to download and install them, see the `Tools - for Amazon Web Services page`_. - - See the CloudTrail User Guide for information about the data that - is included with each AWS API call listed in the log files. - """ - APIVersion = "2013-11-01" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "cloudtrail.us-east-1.amazonaws.com" - ServiceName = "CloudTrail" - TargetPrefix = "com.amazonaws.cloudtrail.v20131101.CloudTrail_20131101" - ResponseError = JSONResponseError - - _faults = { - "InvalidSnsTopicNameException": exceptions.InvalidSnsTopicNameException, - "InvalidS3BucketNameException": exceptions.InvalidS3BucketNameException, - "TrailAlreadyExistsException": exceptions.TrailAlreadyExistsException, - "InsufficientSnsTopicPolicyException": exceptions.InsufficientSnsTopicPolicyException, - "InvalidTrailNameException": exceptions.InvalidTrailNameException, - "TrailNotProvidedException": exceptions.TrailNotProvidedException, - "TrailNotFoundException": exceptions.TrailNotFoundException, - "S3BucketDoesNotExistException": exceptions.S3BucketDoesNotExistException, - "InvalidS3PrefixException": exceptions.InvalidS3PrefixException, - "MaximumNumberOfTrailsExceededException": exceptions.MaximumNumberOfTrailsExceededException, - "InsufficientS3BucketPolicyException": exceptions.InsufficientS3BucketPolicyException, - } - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs: - kwargs['host'] = region.endpoint - - super(CloudTrailConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def create_trail(self, name=None, s3_bucket_name=None, - s3_key_prefix=None, sns_topic_name=None, - include_global_service_events=None, trail=None): - """ - From the command line, use `create-subscription`. - - Creates a trail that specifies the settings for delivery of - log data to an Amazon S3 bucket. - - Support for passing Trail as a parameter ends as early as - February 25, 2014. The request and response examples in this - topic show the use of parameters as well as a Trail object. - Until Trail is removed, you can use either Trail or the - parameter list. - - :type name: string - :param name: Specifies the name of the trail. - - :type s3_bucket_name: string - :param s3_bucket_name: Specifies the name of the Amazon S3 bucket - designated for publishing log files. - - :type s3_key_prefix: string - :param s3_key_prefix: Specifies the Amazon S3 key prefix that precedes - the name of the bucket you have designated for log file delivery. - - :type sns_topic_name: string - :param sns_topic_name: Specifies the name of the Amazon SNS topic - defined for notification of log file delivery. - - :type include_global_service_events: boolean - :param include_global_service_events: Specifies whether the trail is - publishing events from global services such as IAM to the log - files. - - :type trail: dict - :param trail: Support for passing a Trail object in the CreateTrail or - UpdateTrail actions will end as early as February 15, 2014. Instead - of the Trail object and its members, use the parameters listed for - these actions. - - """ - params = {} - if name is not None: - params['Name'] = name - if s3_bucket_name is not None: - params['S3BucketName'] = s3_bucket_name - if s3_key_prefix is not None: - params['S3KeyPrefix'] = s3_key_prefix - if sns_topic_name is not None: - params['SnsTopicName'] = sns_topic_name - if include_global_service_events is not None: - params['IncludeGlobalServiceEvents'] = include_global_service_events - if trail is not None: - params['trail'] = trail - return self.make_request(action='CreateTrail', - body=json.dumps(params)) - - def delete_trail(self, name): - """ - Deletes a trail. - - :type name: string - :param name: The name of a trail to be deleted. - - """ - params = {'Name': name, } - return self.make_request(action='DeleteTrail', - body=json.dumps(params)) - - def describe_trails(self, trail_name_list=None): - """ - Retrieves the settings for some or all trails associated with - an account. - - :type trail_name_list: list - :param trail_name_list: The list of trails. - - """ - params = {} - if trail_name_list is not None: - params['trailNameList'] = trail_name_list - return self.make_request(action='DescribeTrails', - body=json.dumps(params)) - - def get_trail_status(self, name): - """ - Returns a JSON-formatted list of information about the - specified trail. Fields include information on delivery - errors, Amazon SNS and Amazon S3 errors, and start and stop - logging times for each trail. - - The CloudTrail API is currently undergoing revision. This - action currently returns both new fields and fields slated for - removal from the API. The following lists indicate the plans - for each field: - - **List of Members Planned for Ongoing Support** - - - + IsLogging - + LatestDeliveryTime - + LatestNotificationTime - + StartLoggingTime - + StopLoggingTime - + LatestNotificationError - + LatestDeliveryError - - - **List of Members Scheduled for Removal** - - - + **LatestDeliveryAttemptTime**: Use LatestDeliveryTime - instead. - + **LatestNotificationAttemptTime**: Use - LatestNotificationTime instead. - + **LatestDeliveryAttemptSucceeded**: No replacement. See the - note following this list. - + **LatestNotificationAttemptSucceeded**: No replacement. See - the note following this list. - + **TimeLoggingStarted**: Use StartLoggingTime instead. - + **TimeLoggingStopped**: Use StopLoggingtime instead. - - - No replacements have been created for - LatestDeliveryAttemptSucceeded and - LatestNotificationAttemptSucceeded . Use LatestDeliveryError - and LatestNotificationError to evaluate success or failure of - log delivery or notification. Empty values returned for these - fields indicate success. An error in LatestDeliveryError - generally indicates either a missing bucket or insufficient - permissions to write to the bucket. Similarly, an error in - LatestNotificationError indicates either a missing topic or - insufficient permissions. - - :type name: string - :param name: The name of the trail for which you are requesting the - current status. - - """ - params = {'Name': name, } - return self.make_request(action='GetTrailStatus', - body=json.dumps(params)) - - def start_logging(self, name): - """ - Starts the recording of AWS API calls and log file delivery - for a trail. - - :type name: string - :param name: The name of the trail for which CloudTrail logs AWS API - calls. - - """ - params = {'Name': name, } - return self.make_request(action='StartLogging', - body=json.dumps(params)) - - def stop_logging(self, name): - """ - Suspends the recording of AWS API calls and log file delivery - for the specified trail. Under most circumstances, there is no - need to use this action. You can update a trail without - stopping it first. This action is the only way to stop - recording. - - :type name: string - :param name: Communicates to CloudTrail the name of the trail for which - to stop logging AWS API calls. - - """ - params = {'Name': name, } - return self.make_request(action='StopLogging', - body=json.dumps(params)) - - def update_trail(self, name=None, s3_bucket_name=None, - s3_key_prefix=None, sns_topic_name=None, - include_global_service_events=None, trail=None): - """ - From the command line, use `update-subscription`. - - Updates the settings that specify delivery of log files. - Changes to a trail do not require stopping the CloudTrail - service. Use this action to designate an existing bucket for - log delivery. If the existing bucket has previously been a - target for CloudTrail log files, an IAM policy exists for the - bucket. - - Support for passing Trail as a parameter ends as early as - February 25, 2014. The request and response examples in this - topic show the use of parameters as well as a Trail object. - Until Trail is removed, you can use either Trail or the - parameter list. - - :type name: string - :param name: Specifies the name of the trail. - - :type s3_bucket_name: string - :param s3_bucket_name: Specifies the name of the Amazon S3 bucket - designated for publishing log files. - - :type s3_key_prefix: string - :param s3_key_prefix: Specifies the Amazon S3 key prefix that precedes - the name of the bucket you have designated for log file delivery. - - :type sns_topic_name: string - :param sns_topic_name: Specifies the name of the Amazon SNS topic - defined for notification of log file delivery. - - :type include_global_service_events: boolean - :param include_global_service_events: Specifies whether the trail is - publishing events from global services such as IAM to the log - files. - - :type trail: dict - :param trail: Support for passing a Trail object in the CreateTrail or - UpdateTrail actions will end as early as February 15, 2014. Instead - of the Trail object and its members, use the parameters listed for - these actions. - - """ - params = {} - if name is not None: - params['Name'] = name - if s3_bucket_name is not None: - params['S3BucketName'] = s3_bucket_name - if s3_key_prefix is not None: - params['S3KeyPrefix'] = s3_key_prefix - if sns_topic_name is not None: - params['SnsTopicName'] = sns_topic_name - if include_global_service_events is not None: - params['IncludeGlobalServiceEvents'] = include_global_service_events - if trail is not None: - params['trail'] = trail - return self.make_request(action='UpdateTrail', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/cognito/__init__.py b/awx/lib/site-packages/boto/cognito/__init__.py deleted file mode 100644 index 70cc23febf..0000000000 --- a/awx/lib/site-packages/boto/cognito/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# diff --git a/awx/lib/site-packages/boto/cognito/identity/__init__.py b/awx/lib/site-packages/boto/cognito/identity/__init__.py deleted file mode 100644 index e58b480b3f..0000000000 --- a/awx/lib/site-packages/boto/cognito/identity/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon Cognito Identity service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.cognito.identity.layer1 import CognitoIdentityConnection - return get_regions('cognito-identity', - connection_cls=CognitoIdentityConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/cognito/identity/exceptions.py b/awx/lib/site-packages/boto/cognito/identity/exceptions.py deleted file mode 100644 index 179089dfb2..0000000000 --- a/awx/lib/site-packages/boto/cognito/identity/exceptions.py +++ /dev/null @@ -1,40 +0,0 @@ -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import BotoServerError - - -class LimitExceededException(BotoServerError): - pass - - -class ResourceConflictException(BotoServerError): - pass - - -class TooManyRequestsException(BotoServerError): - pass - - -class InvalidParameterException(BotoServerError): - pass - - -class ResourceNotFoundException(BotoServerError): - pass - - -class InternalErrorException(BotoServerError): - pass - - -class NotAuthorizedException(BotoServerError): - pass diff --git a/awx/lib/site-packages/boto/cognito/identity/layer1.py b/awx/lib/site-packages/boto/cognito/identity/layer1.py deleted file mode 100644 index 0a9c8e4e59..0000000000 --- a/awx/lib/site-packages/boto/cognito/identity/layer1.py +++ /dev/null @@ -1,303 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.cognito.identity import exceptions - - -class CognitoIdentityConnection(AWSQueryConnection): - """ - Amazon Cognito - Amazon Cognito is a web service that facilitates the delivery of - scoped, temporary credentials to mobile devices or other untrusted - environments. Amazon Cognito uniquely identifies a device or user - and supplies the user with a consistent identity throughout the - lifetime of an application. - - Amazon Cognito lets users authenticate with third-party identity - providers (Facebook, Google, or Login with Amazon). As a - developer, you decide which identity providers to trust. You can - also choose to support unauthenticated access from your - application. Your users are provided with Cognito tokens that - uniquely identify their device and any information provided about - third-party logins. - """ - APIVersion = "2014-06-30" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "cognito-identity.us-east-1.amazonaws.com" - ServiceName = "CognitoIdentity" - TargetPrefix = "AWSCognitoIdentityService" - ResponseError = JSONResponseError - - _faults = { - "LimitExceededException": exceptions.LimitExceededException, - "ResourceConflictException": exceptions.ResourceConflictException, - "TooManyRequestsException": exceptions.TooManyRequestsException, - "InvalidParameterException": exceptions.InvalidParameterException, - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "InternalErrorException": exceptions.InternalErrorException, - "NotAuthorizedException": exceptions.NotAuthorizedException, - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs or kwargs['host'] is None: - kwargs['host'] = region.endpoint - - super(CognitoIdentityConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def create_identity_pool(self, identity_pool_name, - allow_unauthenticated_identities, - supported_login_providers=None): - """ - Creates a new identity pool. The identity pool is a store of - user identity information that is specific to your AWS - account. - - :type identity_pool_name: string - :param identity_pool_name: A string that you provide. - - :type allow_unauthenticated_identities: boolean - :param allow_unauthenticated_identities: TRUE if the identity pool - supports unauthenticated logins. - - :type supported_login_providers: map - :param supported_login_providers: Optional key:value pairs mapping - provider names to provider app IDs. - - """ - params = { - 'IdentityPoolName': identity_pool_name, - 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities, - } - if supported_login_providers is not None: - params['SupportedLoginProviders'] = supported_login_providers - return self.make_request(action='CreateIdentityPool', - body=json.dumps(params)) - - def delete_identity_pool(self, identity_pool_id): - """ - Deletes a user pool. Once a pool is deleted, users will not be - able to authenticate with the pool. - - :type identity_pool_id: string - :param identity_pool_id: An identity pool ID in the format REGION:GUID. - - """ - params = {'IdentityPoolId': identity_pool_id, } - return self.make_request(action='DeleteIdentityPool', - body=json.dumps(params)) - - def describe_identity_pool(self, identity_pool_id): - """ - Gets details about a particular identity pool, including the - pool name, ID description, creation date, and current number - of users. - - :type identity_pool_id: string - :param identity_pool_id: An identity pool ID in the format REGION:GUID. - - """ - params = {'IdentityPoolId': identity_pool_id, } - return self.make_request(action='DescribeIdentityPool', - body=json.dumps(params)) - - def get_id(self, account_id, identity_pool_id, logins=None): - """ - Generates (or retrieves) a Cognito ID. Supplying multiple - logins will create an implicit linked account. - - :type account_id: string - :param account_id: A standard AWS account ID (9+ digits). - - :type identity_pool_id: string - :param identity_pool_id: An identity pool ID in the format REGION:GUID. - - :type logins: map - :param logins: A set of optional name/value pairs that map provider - names to provider tokens. - - """ - params = { - 'AccountId': account_id, - 'IdentityPoolId': identity_pool_id, - } - if logins is not None: - params['Logins'] = logins - return self.make_request(action='GetId', - body=json.dumps(params)) - - def get_open_id_token(self, identity_id, logins=None): - """ - Gets an OpenID token, using a known Cognito ID. This known - Cognito ID is returned from GetId. You can optionally add - additional logins for the identity. Supplying multiple logins - creates an implicit link. - - :type identity_id: string - :param identity_id: A unique identifier in the format REGION:GUID. - - :type logins: map - :param logins: A set of optional name/value pairs that map provider - names to provider tokens. - - """ - params = {'IdentityId': identity_id, } - if logins is not None: - params['Logins'] = logins - return self.make_request(action='GetOpenIdToken', - body=json.dumps(params)) - - def list_identities(self, identity_pool_id, max_results, next_token=None): - """ - Lists the identities in a pool. - - :type identity_pool_id: string - :param identity_pool_id: An identity pool ID in the format REGION:GUID. - - :type max_results: integer - :param max_results: The maximum number of identities to return. - - :type next_token: string - :param next_token: A pagination token. - - """ - params = { - 'IdentityPoolId': identity_pool_id, - 'MaxResults': max_results, - } - if next_token is not None: - params['NextToken'] = next_token - return self.make_request(action='ListIdentities', - body=json.dumps(params)) - - def list_identity_pools(self, max_results, next_token=None): - """ - Lists all of the Cognito identity pools registered for your - account. - - :type max_results: integer - :param max_results: The maximum number of identities to return. - - :type next_token: string - :param next_token: A pagination token. - - """ - params = {'MaxResults': max_results, } - if next_token is not None: - params['NextToken'] = next_token - return self.make_request(action='ListIdentityPools', - body=json.dumps(params)) - - def unlink_identity(self, identity_id, logins, logins_to_remove): - """ - Unlinks a federated identity from an existing account. - Unlinked logins will be considered new identities next time - they are seen. Removing the last linked login will make this - identity inaccessible. - - :type identity_id: string - :param identity_id: A unique identifier in the format REGION:GUID. - - :type logins: map - :param logins: A set of optional name/value pairs that map provider - names to provider tokens. - - :type logins_to_remove: list - :param logins_to_remove: Provider names to unlink from this identity. - - """ - params = { - 'IdentityId': identity_id, - 'Logins': logins, - 'LoginsToRemove': logins_to_remove, - } - return self.make_request(action='UnlinkIdentity', - body=json.dumps(params)) - - def update_identity_pool(self, identity_pool_id, identity_pool_name, - allow_unauthenticated_identities, - supported_login_providers=None): - """ - Updates a user pool. - - :type identity_pool_id: string - :param identity_pool_id: An identity pool ID in the format REGION:GUID. - - :type identity_pool_name: string - :param identity_pool_name: A string that you provide. - - :type allow_unauthenticated_identities: boolean - :param allow_unauthenticated_identities: TRUE if the identity pool - supports unauthenticated logins. - - :type supported_login_providers: map - :param supported_login_providers: Optional key:value pairs mapping - provider names to provider app IDs. - - """ - params = { - 'IdentityPoolId': identity_pool_id, - 'IdentityPoolName': identity_pool_name, - 'AllowUnauthenticatedIdentities': allow_unauthenticated_identities, - } - if supported_login_providers is not None: - params['SupportedLoginProviders'] = supported_login_providers - return self.make_request(action='UpdateIdentityPool', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/cognito/sync/__init__.py b/awx/lib/site-packages/boto/cognito/sync/__init__.py deleted file mode 100644 index 3d48bd18ee..0000000000 --- a/awx/lib/site-packages/boto/cognito/sync/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon Cognito Sync service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.cognito.sync.layer1 import CognitoSyncConnection - return get_regions('cognito-sync', connection_cls=CognitoSyncConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/cognito/sync/exceptions.py b/awx/lib/site-packages/boto/cognito/sync/exceptions.py deleted file mode 100644 index d64fb27801..0000000000 --- a/awx/lib/site-packages/boto/cognito/sync/exceptions.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import BotoServerError - - -class LimitExceededException(BotoServerError): - pass - - -class ResourceConflictException(BotoServerError): - pass - - -class TooManyRequestsException(BotoServerError): - pass - - -class InvalidParameterException(BotoServerError): - pass - - -class ResourceNotFoundException(BotoServerError): - pass - - -class InternalErrorException(BotoServerError): - pass - - -class NotAuthorizedException(BotoServerError): - pass diff --git a/awx/lib/site-packages/boto/cognito/sync/layer1.py b/awx/lib/site-packages/boto/cognito/sync/layer1.py deleted file mode 100644 index 545af5ebfd..0000000000 --- a/awx/lib/site-packages/boto/cognito/sync/layer1.py +++ /dev/null @@ -1,307 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.compat import json -from boto.exception import JSONResponseError -from boto.connection import AWSAuthConnection -from boto.regioninfo import RegionInfo -from boto.cognito.sync import exceptions - - -class CognitoSyncConnection(AWSAuthConnection): - """ - Amazon Cognito Sync - Amazon Cognito Sync provides an AWS service and client library - that enable cross-device syncing of application-related user data. - High-level client libraries are available for both iOS and - Android. You can use these libraries to persist data locally so - that it's available even if the device is offline. Developer - credentials don't need to be stored on the mobile device to access - the service. You can use Amazon Cognito to obtain a normalized - user ID and credentials. User data is persisted in a dataset that - can store up to 1 MB of key-value pairs, and you can have up to 20 - datasets per user identity. - """ - APIVersion = "2014-06-30" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "cognito-sync.us-east-1.amazonaws.com" - ResponseError = JSONResponseError - - _faults = { - "LimitExceededException": exceptions.LimitExceededException, - "ResourceConflictException": exceptions.ResourceConflictException, - "TooManyRequestsException": exceptions.TooManyRequestsException, - "InvalidParameterException": exceptions.InvalidParameterException, - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "InternalErrorException": exceptions.InternalErrorException, - "NotAuthorizedException": exceptions.NotAuthorizedException, - } - - - def __init__(self, **kwargs): - region = kwargs.get('region') - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - else: - del kwargs['region'] - kwargs['host'] = region.endpoint - super(CognitoSyncConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def delete_dataset(self, identity_pool_id, identity_id, dataset_name): - """ - Deletes the specific dataset. The dataset will be deleted - permanently, and the action can't be undone. Datasets that - this dataset was merged with will no longer report the merge. - Any consequent operation on this dataset will result in a - ResourceNotFoundException. - - :type identity_pool_id: string - :param identity_pool_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type identity_id: string - :param identity_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type dataset_name: string - :param dataset_name: A string of up to 128 characters. Allowed - characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' - (dot). - - """ - uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format( - identity_pool_id, identity_id, dataset_name) - return self.make_request('DELETE', uri, expected_status=200) - - def describe_dataset(self, identity_pool_id, identity_id, dataset_name): - """ - Gets metadata about a dataset by identity and dataset name. - - :type identity_pool_id: string - :param identity_pool_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type identity_id: string - :param identity_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type dataset_name: string - :param dataset_name: A string of up to 128 characters. Allowed - characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' - (dot). - - """ - uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format( - identity_pool_id, identity_id, dataset_name) - return self.make_request('GET', uri, expected_status=200) - - def describe_identity_pool_usage(self, identity_pool_id): - """ - Gets usage details (for example, data storage) about a - particular identity pool. - - :type identity_pool_id: string - :param identity_pool_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - """ - uri = '/identitypools/{0}'.format(identity_pool_id) - return self.make_request('GET', uri, expected_status=200) - - def describe_identity_usage(self, identity_pool_id, identity_id): - """ - Gets usage information for an identity, including number of - datasets and data usage. - - :type identity_pool_id: string - :param identity_pool_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type identity_id: string - :param identity_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - """ - uri = '/identitypools/{0}/identities/{1}'.format( - identity_pool_id, identity_id) - return self.make_request('GET', uri, expected_status=200) - - def list_datasets(self, identity_pool_id, identity_id, next_token=None, - max_results=None): - """ - Lists datasets for an identity. - - :type identity_pool_id: string - :param identity_pool_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type identity_id: string - :param identity_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type next_token: string - :param next_token: A pagination token for obtaining the next page of - results. - - :type max_results: integer - :param max_results: The maximum number of results to be returned. - - """ - uri = '/identitypools/{0}/identities/{1}/datasets'.format( - identity_pool_id, identity_id) - params = {} - headers = {} - return self.make_request('GET', uri, expected_status=200, - data=json.dumps(params), headers=headers) - - def list_identity_pool_usage(self, next_token=None, max_results=None): - """ - Gets a list of identity pools registered with Cognito. - - :type next_token: string - :param next_token: A pagination token for obtaining the next page of - results. - - :type max_results: integer - :param max_results: The maximum number of results to be returned. - - """ - uri = '/identitypools' - params = {} - headers = {} - return self.make_request('GET', uri, expected_status=200, - data=json.dumps(params), headers=headers) - - def list_records(self, identity_pool_id, identity_id, dataset_name, - last_sync_count=None, next_token=None, max_results=None, - sync_session_token=None): - """ - Gets paginated records, optionally changed after a particular - sync count for a dataset and identity. - - :type identity_pool_id: string - :param identity_pool_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type identity_id: string - :param identity_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type dataset_name: string - :param dataset_name: A string of up to 128 characters. Allowed - characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' - (dot). - - :type last_sync_count: long - :param last_sync_count: The last server sync count for this record. - - :type next_token: string - :param next_token: A pagination token for obtaining the next page of - results. - - :type max_results: integer - :param max_results: The maximum number of results to be returned. - - :type sync_session_token: string - :param sync_session_token: A token containing a session ID, identity - ID, and expiration. - - """ - uri = '/identitypools/{0}/identities/{1}/datasets/{2}/records'.format( - identity_pool_id, identity_id, dataset_name) - params = {} - headers = {} - return self.make_request('GET', uri, expected_status=200, - data=json.dumps(params), headers=headers) - - def update_records(self, identity_pool_id, identity_id, dataset_name, - sync_session_token, record_patches=None, - client_context=None): - """ - Posts updates to records and add and delete records for a - dataset and user. - - :type identity_pool_id: string - :param identity_pool_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type identity_id: string - :param identity_id: A name-spaced GUID (for example, us- - east-1:23EC4050-6AEA-7089-A2DD-08002EXAMPLE) created by Amazon - Cognito. GUID generation is unique within a region. - - :type dataset_name: string - :param dataset_name: A string of up to 128 characters. Allowed - characters are a-z, A-Z, 0-9, '_' (underscore), '-' (dash), and '.' - (dot). - - :type record_patches: list - :param record_patches: - - :type sync_session_token: string - :param sync_session_token: The SyncSessionToken returned by a previous - call to ListRecords for this dataset and identity. - - :type client_context: string - :param client_context: - - """ - uri = '/identitypools/{0}/identities/{1}/datasets/{2}'.format( - identity_pool_id, identity_id, dataset_name) - params = {'SyncSessionToken': sync_session_token, } - headers = {} - if record_patches is not None: - params['RecordPatches'] = record_patches - if client_context is not None: - headers['x-amz-Client-Context'] = client_context - return self.make_request('POST', uri, expected_status=200, - data=json.dumps(params), headers=headers) - - def make_request(self, verb, resource, headers=None, data='', - expected_status=None, params=None): - if headers is None: - headers = {} - response = AWSAuthConnection.make_request( - self, verb, resource, headers=headers, data=data, params=params) - body = json.loads(response.read().decode('utf-8')) - if response.status == expected_status: - return body - else: - error_type = response.getheader('x-amzn-ErrorType').split(':')[0] - error_class = self._faults.get(error_type, self.ResponseError) - raise error_class(response.status, response.reason, body) diff --git a/awx/lib/site-packages/boto/compat.py b/awx/lib/site-packages/boto/compat.py deleted file mode 100644 index a7503f013b..0000000000 --- a/awx/lib/site-packages/boto/compat.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import os - -# This allows boto modules to say "from boto.compat import json". This is -# preferred so that all modules don't have to repeat this idiom. -try: - import simplejson as json -except ImportError: - import json - - -# Switch to use encodebytes, which deprecates encodestring in Python 3 -try: - from base64 import encodebytes -except ImportError: - from base64 import encodestring as encodebytes - - -# If running in Google App Engine there is no "user" and -# os.path.expanduser() will fail. Attempt to detect this case and use a -# no-op expanduser function in this case. -try: - os.path.expanduser('~') - expanduser = os.path.expanduser -except (AttributeError, ImportError): - # This is probably running on App Engine. - expanduser = (lambda x: x) - -from boto.vendored import six - -from boto.vendored.six import BytesIO, StringIO -from boto.vendored.six.moves import filter, http_client, map, _thread, \ - urllib, zip -from boto.vendored.six.moves.queue import Queue -from boto.vendored.six.moves.urllib.parse import parse_qs, quote, unquote, \ - urlparse, urlsplit -from boto.vendored.six.moves.urllib.request import urlopen - -if six.PY3: - # StandardError was removed, so use the base exception type instead - StandardError = Exception - long_type = int - from configparser import ConfigParser -else: - StandardError = StandardError - long_type = long - from ConfigParser import SafeConfigParser as ConfigParser diff --git a/awx/lib/site-packages/boto/connection.py b/awx/lib/site-packages/boto/connection.py deleted file mode 100644 index 40db69a782..0000000000 --- a/awx/lib/site-packages/boto/connection.py +++ /dev/null @@ -1,1223 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# Copyright (c) 2010 Google -# Copyright (c) 2008 rPath, Inc. -# Copyright (c) 2009 The Echo Nest Corporation -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# Copyright (c) 2011, Nexenta Systems Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# -# Parts of this code were copied or derived from sample code supplied by AWS. -# The following notice applies to that code. -# -# This software code is made available "AS IS" without warranties of any -# kind. You may copy, display, modify and redistribute the software -# code either by itself or as incorporated into your code; provided that -# you do not remove any proprietary notices. Your use of this software -# code is at your own risk and you waive any claim against Amazon -# Digital Services, Inc. or its affiliates with respect to your use of -# this software code. (c) 2006 Amazon Digital Services, Inc. or its -# affiliates. - -""" -Handles basic connections to AWS -""" -from datetime import datetime -import errno -import os -import random -import re -import socket -import sys -import time -import xml.sax -import copy - -from boto import auth -from boto import auth_handler -import boto -import boto.utils -import boto.handler -import boto.cacerts - -from boto import config, UserAgent -from boto.compat import six, http_client, urlparse, quote, encodebytes -from boto.exception import AWSConnectionError -from boto.exception import BotoClientError -from boto.exception import BotoServerError -from boto.exception import PleaseRetryException -from boto.provider import Provider -from boto.resultset import ResultSet - -HAVE_HTTPS_CONNECTION = False -try: - import ssl - from boto import https_connection - # Google App Engine runs on Python 2.5 so doesn't have ssl.SSLError. - if hasattr(ssl, 'SSLError'): - HAVE_HTTPS_CONNECTION = True -except ImportError: - pass - -try: - import threading -except ImportError: - import dummy_threading as threading - -ON_APP_ENGINE = all(key in os.environ for key in ( - 'USER_IS_ADMIN', 'CURRENT_VERSION_ID', 'APPLICATION_ID')) - -PORTS_BY_SECURITY = {True: 443, - False: 80} - -DEFAULT_CA_CERTS_FILE = os.path.join(os.path.dirname(os.path.abspath(boto.cacerts.__file__)), "cacerts.txt") - - -class HostConnectionPool(object): - - """ - A pool of connections for one remote (host,port,is_secure). - - When connections are added to the pool, they are put into a - pending queue. The _mexe method returns connections to the pool - before the response body has been read, so they connections aren't - ready to send another request yet. They stay in the pending queue - until they are ready for another request, at which point they are - returned to the pool of ready connections. - - The pool of ready connections is an ordered list of - (connection,time) pairs, where the time is the time the connection - was returned from _mexe. After a certain period of time, - connections are considered stale, and discarded rather than being - reused. This saves having to wait for the connection to time out - if AWS has decided to close it on the other end because of - inactivity. - - Thread Safety: - - This class is used only from ConnectionPool while it's mutex - is held. - """ - - def __init__(self): - self.queue = [] - - def size(self): - """ - Returns the number of connections in the pool for this host. - Some of the connections may still be in use, and may not be - ready to be returned by get(). - """ - return len(self.queue) - - def put(self, conn): - """ - Adds a connection to the pool, along with the time it was - added. - """ - self.queue.append((conn, time.time())) - - def get(self): - """ - Returns the next connection in this pool that is ready to be - reused. Returns None if there aren't any. - """ - # Discard ready connections that are too old. - self.clean() - - # Return the first connection that is ready, and remove it - # from the queue. Connections that aren't ready are returned - # to the end of the queue with an updated time, on the - # assumption that somebody is actively reading the response. - for _ in range(len(self.queue)): - (conn, _) = self.queue.pop(0) - if self._conn_ready(conn): - return conn - else: - self.put(conn) - return None - - def _conn_ready(self, conn): - """ - There is a nice state diagram at the top of http_client.py. It - indicates that once the response headers have been read (which - _mexe does before adding the connection to the pool), a - response is attached to the connection, and it stays there - until it's done reading. This isn't entirely true: even after - the client is done reading, the response may be closed, but - not removed from the connection yet. - - This is ugly, reading a private instance variable, but the - state we care about isn't available in any public methods. - """ - if ON_APP_ENGINE: - # Google AppEngine implementation of HTTPConnection doesn't contain - # _HTTPConnection__response attribute. Moreover, it's not possible - # to determine if given connection is ready. Reusing connections - # simply doesn't make sense with App Engine urlfetch service. - return False - else: - response = getattr(conn, '_HTTPConnection__response', None) - return (response is None) or response.isclosed() - - def clean(self): - """ - Get rid of stale connections. - """ - # Note that we do not close the connection here -- somebody - # may still be reading from it. - while len(self.queue) > 0 and self._pair_stale(self.queue[0]): - self.queue.pop(0) - - def _pair_stale(self, pair): - """ - Returns true of the (connection,time) pair is too old to be - used. - """ - (_conn, return_time) = pair - now = time.time() - return return_time + ConnectionPool.STALE_DURATION < now - - -class ConnectionPool(object): - - """ - A connection pool that expires connections after a fixed period of - time. This saves time spent waiting for a connection that AWS has - timed out on the other end. - - This class is thread-safe. - """ - - # - # The amout of time between calls to clean. - # - - CLEAN_INTERVAL = 5.0 - - # - # How long before a connection becomes "stale" and won't be reused - # again. The intention is that this time is less that the timeout - # period that AWS uses, so we'll never try to reuse a connection - # and find that AWS is timing it out. - # - # Experimentation in July 2011 shows that AWS starts timing things - # out after three minutes. The 60 seconds here is conservative so - # we should never hit that 3-minute timout. - # - - STALE_DURATION = 60.0 - - def __init__(self): - # Mapping from (host,port,is_secure) to HostConnectionPool. - # If a pool becomes empty, it is removed. - self.host_to_pool = {} - # The last time the pool was cleaned. - self.last_clean_time = 0.0 - self.mutex = threading.Lock() - ConnectionPool.STALE_DURATION = \ - config.getfloat('Boto', 'connection_stale_duration', - ConnectionPool.STALE_DURATION) - - def __getstate__(self): - pickled_dict = copy.copy(self.__dict__) - pickled_dict['host_to_pool'] = {} - del pickled_dict['mutex'] - return pickled_dict - - def __setstate__(self, dct): - self.__init__() - - def size(self): - """ - Returns the number of connections in the pool. - """ - return sum(pool.size() for pool in self.host_to_pool.values()) - - def get_http_connection(self, host, port, is_secure): - """ - Gets a connection from the pool for the named host. Returns - None if there is no connection that can be reused. It's the caller's - responsibility to call close() on the connection when it's no longer - needed. - """ - self.clean() - with self.mutex: - key = (host, port, is_secure) - if key not in self.host_to_pool: - return None - return self.host_to_pool[key].get() - - def put_http_connection(self, host, port, is_secure, conn): - """ - Adds a connection to the pool of connections that can be - reused for the named host. - """ - with self.mutex: - key = (host, port, is_secure) - if key not in self.host_to_pool: - self.host_to_pool[key] = HostConnectionPool() - self.host_to_pool[key].put(conn) - - def clean(self): - """ - Clean up the stale connections in all of the pools, and then - get rid of empty pools. Pools clean themselves every time a - connection is fetched; this cleaning takes care of pools that - aren't being used any more, so nothing is being gotten from - them. - """ - with self.mutex: - now = time.time() - if self.last_clean_time + self.CLEAN_INTERVAL < now: - to_remove = [] - for (host, pool) in self.host_to_pool.items(): - pool.clean() - if pool.size() == 0: - to_remove.append(host) - for host in to_remove: - del self.host_to_pool[host] - self.last_clean_time = now - - -class HTTPRequest(object): - - def __init__(self, method, protocol, host, port, path, auth_path, - params, headers, body): - """Represents an HTTP request. - - :type method: string - :param method: The HTTP method name, 'GET', 'POST', 'PUT' etc. - - :type protocol: string - :param protocol: The http protocol used, 'http' or 'https'. - - :type host: string - :param host: Host to which the request is addressed. eg. abc.com - - :type port: int - :param port: port on which the request is being sent. Zero means unset, - in which case default port will be chosen. - - :type path: string - :param path: URL path that is being accessed. - - :type auth_path: string - :param path: The part of the URL path used when creating the - authentication string. - - :type params: dict - :param params: HTTP url query parameters, with key as name of - the param, and value as value of param. - - :type headers: dict - :param headers: HTTP headers, with key as name of the header and value - as value of header. - - :type body: string - :param body: Body of the HTTP request. If not present, will be None or - empty string (''). - """ - self.method = method - self.protocol = protocol - self.host = host - self.port = port - self.path = path - if auth_path is None: - auth_path = path - self.auth_path = auth_path - self.params = params - # chunked Transfer-Encoding should act only on PUT request. - if headers and 'Transfer-Encoding' in headers and \ - headers['Transfer-Encoding'] == 'chunked' and \ - self.method != 'PUT': - self.headers = headers.copy() - del self.headers['Transfer-Encoding'] - else: - self.headers = headers - self.body = body - - def __str__(self): - return (('method:(%s) protocol:(%s) host(%s) port(%s) path(%s) ' - 'params(%s) headers(%s) body(%s)') % (self.method, - self.protocol, self.host, self.port, self.path, self.params, - self.headers, self.body)) - - def authorize(self, connection, **kwargs): - if not getattr(self, '_headers_quoted', False): - for key in self.headers: - val = self.headers[key] - if isinstance(val, six.text_type): - safe = '!"#$%&\'()*+,/:;<=>?@[\\]^`{|}~' - self.headers[key] = quote(val.encode('utf-8'), safe) - setattr(self, '_headers_quoted', True) - - self.headers['User-Agent'] = UserAgent - - connection._auth_handler.add_auth(self, **kwargs) - - # I'm not sure if this is still needed, now that add_auth is - # setting the content-length for POST requests. - if 'Content-Length' not in self.headers: - if 'Transfer-Encoding' not in self.headers or \ - self.headers['Transfer-Encoding'] != 'chunked': - self.headers['Content-Length'] = len(self.body) - - -class HTTPResponse(http_client.HTTPResponse): - - def __init__(self, *args, **kwargs): - http_client.HTTPResponse.__init__(self, *args, **kwargs) - self._cached_response = '' - - def read(self, amt=None): - """Read the response. - - This method does not have the same behavior as - http_client.HTTPResponse.read. Instead, if this method is called with - no ``amt`` arg, then the response body will be cached. Subsequent - calls to ``read()`` with no args **will return the cached response**. - - """ - if amt is None: - # The reason for doing this is that many places in boto call - # response.read() and except to get the response body that they - # can then process. To make sure this always works as they expect - # we're caching the response so that multiple calls to read() - # will return the full body. Note that this behavior only - # happens if the amt arg is not specified. - if not self._cached_response: - self._cached_response = http_client.HTTPResponse.read(self) - return self._cached_response - else: - return http_client.HTTPResponse.read(self, amt) - - -class AWSAuthConnection(object): - def __init__(self, host, aws_access_key_id=None, - aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, path='/', - provider='aws', security_token=None, - suppress_consec_slashes=True, - validate_certs=True, profile_name=None): - """ - :type host: str - :param host: The host to make the connection to - - :keyword str aws_access_key_id: Your AWS Access Key ID (provided by - Amazon). If none is specified, the value in your - ``AWS_ACCESS_KEY_ID`` environmental variable is used. - :keyword str aws_secret_access_key: Your AWS Secret Access Key - (provided by Amazon). If none is specified, the value in your - ``AWS_SECRET_ACCESS_KEY`` environmental variable is used. - :keyword str security_token: The security token associated with - temporary credentials issued by STS. Optional unless using - temporary credentials. If none is specified, the environment - variable ``AWS_SECURITY_TOKEN`` is used if defined. - - :type is_secure: boolean - :param is_secure: Whether the connection is over SSL - - :type https_connection_factory: list or tuple - :param https_connection_factory: A pair of an HTTP connection - factory and the exceptions to catch. The factory should have - a similar interface to L{http_client.HTTPSConnection}. - - :param str proxy: Address/hostname for a proxy server - - :type proxy_port: int - :param proxy_port: The port to use when connecting over a proxy - - :type proxy_user: str - :param proxy_user: The username to connect with on the proxy - - :type proxy_pass: str - :param proxy_pass: The password to use when connection over a proxy. - - :type port: int - :param port: The port to use to connect - - :type suppress_consec_slashes: bool - :param suppress_consec_slashes: If provided, controls whether - consecutive slashes will be suppressed in key paths. - - :type validate_certs: bool - :param validate_certs: Controls whether SSL certificates - will be validated or not. Defaults to True. - - :type profile_name: str - :param profile_name: Override usual Credentials section in config - file to use a named set of keys instead. - """ - self.suppress_consec_slashes = suppress_consec_slashes - self.num_retries = 6 - # Override passed-in is_secure setting if value was defined in config. - if config.has_option('Boto', 'is_secure'): - is_secure = config.getboolean('Boto', 'is_secure') - self.is_secure = is_secure - # Whether or not to validate server certificates. - # The default is now to validate certificates. This can be - # overridden in the boto config file are by passing an - # explicit validate_certs parameter to the class constructor. - self.https_validate_certificates = config.getbool( - 'Boto', 'https_validate_certificates', - validate_certs) - if self.https_validate_certificates and not HAVE_HTTPS_CONNECTION: - raise BotoClientError( - "SSL server certificate validation is enabled in boto " - "configuration, but Python dependencies required to " - "support this feature are not available. Certificate " - "validation is only supported when running under Python " - "2.6 or later.") - certs_file = config.get_value( - 'Boto', 'ca_certificates_file', DEFAULT_CA_CERTS_FILE) - if certs_file == 'system': - certs_file = None - self.ca_certificates_file = certs_file - if port: - self.port = port - else: - self.port = PORTS_BY_SECURITY[is_secure] - - self.handle_proxy(proxy, proxy_port, proxy_user, proxy_pass) - # define exceptions from http_client that we want to catch and retry - self.http_exceptions = (http_client.HTTPException, socket.error, - socket.gaierror, http_client.BadStatusLine) - # define subclasses of the above that are not retryable. - self.http_unretryable_exceptions = [] - if HAVE_HTTPS_CONNECTION: - self.http_unretryable_exceptions.append( - https_connection.InvalidCertificateException) - - # define values in socket exceptions we don't want to catch - self.socket_exception_values = (errno.EINTR,) - if https_connection_factory is not None: - self.https_connection_factory = https_connection_factory[0] - self.http_exceptions += https_connection_factory[1] - else: - self.https_connection_factory = None - if (is_secure): - self.protocol = 'https' - else: - self.protocol = 'http' - self.host = host - self.path = path - # if the value passed in for debug - if not isinstance(debug, six.integer_types): - debug = 0 - self.debug = config.getint('Boto', 'debug', debug) - self.host_header = None - - # Timeout used to tell http_client how long to wait for socket timeouts. - # Default is to leave timeout unchanged, which will in turn result in - # the socket's default global timeout being used. To specify a - # timeout, set http_socket_timeout in Boto config. Regardless, - # timeouts will only be applied if Python is 2.6 or greater. - self.http_connection_kwargs = {} - if (sys.version_info[0], sys.version_info[1]) >= (2, 6): - # If timeout isn't defined in boto config file, use 70 second - # default as recommended by - # http://docs.aws.amazon.com/amazonswf/latest/apireference/API_PollForActivityTask.html - self.http_connection_kwargs['timeout'] = config.getint( - 'Boto', 'http_socket_timeout', 70) - - if isinstance(provider, Provider): - # Allow overriding Provider - self.provider = provider - else: - self._provider_type = provider - self.provider = Provider(self._provider_type, - aws_access_key_id, - aws_secret_access_key, - security_token, - profile_name) - - # Allow config file to override default host, port, and host header. - if self.provider.host: - self.host = self.provider.host - if self.provider.port: - self.port = self.provider.port - if self.provider.host_header: - self.host_header = self.provider.host_header - - self._pool = ConnectionPool() - self._connection = (self.host, self.port, self.is_secure) - self._last_rs = None - self._auth_handler = auth.get_auth_handler( - host, config, self.provider, self._required_auth_capability()) - if getattr(self, 'AuthServiceName', None) is not None: - self.auth_service_name = self.AuthServiceName - self.request_hook = None - - def __repr__(self): - return '%s:%s' % (self.__class__.__name__, self.host) - - def _required_auth_capability(self): - return [] - - def _get_auth_service_name(self): - return getattr(self._auth_handler, 'service_name') - - # For Sigv4, the auth_service_name/auth_region_name properties allow - # the service_name/region_name to be explicitly set instead of being - # derived from the endpoint url. - def _set_auth_service_name(self, value): - self._auth_handler.service_name = value - auth_service_name = property(_get_auth_service_name, _set_auth_service_name) - - def _get_auth_region_name(self): - return getattr(self._auth_handler, 'region_name') - - def _set_auth_region_name(self, value): - self._auth_handler.region_name = value - auth_region_name = property(_get_auth_region_name, _set_auth_region_name) - - def connection(self): - return self.get_http_connection(*self._connection) - connection = property(connection) - - def aws_access_key_id(self): - return self.provider.access_key - aws_access_key_id = property(aws_access_key_id) - gs_access_key_id = aws_access_key_id - access_key = aws_access_key_id - - def aws_secret_access_key(self): - return self.provider.secret_key - aws_secret_access_key = property(aws_secret_access_key) - gs_secret_access_key = aws_secret_access_key - secret_key = aws_secret_access_key - - def profile_name(self): - return self.provider.profile_name - profile_name = property(profile_name) - - def get_path(self, path='/'): - # The default behavior is to suppress consecutive slashes for reasons - # discussed at - # https://groups.google.com/forum/#!topic/boto-dev/-ft0XPUy0y8 - # You can override that behavior with the suppress_consec_slashes param. - if not self.suppress_consec_slashes: - return self.path + re.sub('^(/*)/', "\\1", path) - pos = path.find('?') - if pos >= 0: - params = path[pos:] - path = path[:pos] - else: - params = None - if path[-1] == '/': - need_trailing = True - else: - need_trailing = False - path_elements = self.path.split('/') - path_elements.extend(path.split('/')) - path_elements = [p for p in path_elements if p] - path = '/' + '/'.join(path_elements) - if path[-1] != '/' and need_trailing: - path += '/' - if params: - path = path + params - return path - - def server_name(self, port=None): - if not port: - port = self.port - if port == 80: - signature_host = self.host - else: - # This unfortunate little hack can be attributed to - # a difference in the 2.6 version of http_client. In old - # versions, it would append ":443" to the hostname sent - # in the Host header and so we needed to make sure we - # did the same when calculating the V2 signature. In 2.6 - # (and higher!) - # it no longer does that. Hence, this kludge. - if ((ON_APP_ENGINE and sys.version[:3] == '2.5') or - sys.version[:3] in ('2.6', '2.7')) and port == 443: - signature_host = self.host - else: - signature_host = '%s:%d' % (self.host, port) - return signature_host - - def handle_proxy(self, proxy, proxy_port, proxy_user, proxy_pass): - self.proxy = proxy - self.proxy_port = proxy_port - self.proxy_user = proxy_user - self.proxy_pass = proxy_pass - if 'http_proxy' in os.environ and not self.proxy: - pattern = re.compile( - '(?:http://)?' - '(?:(?P<user>[\w\-\.]+):(?P<pass>.*)@)?' - '(?P<host>[\w\-\.]+)' - '(?::(?P<port>\d+))?' - ) - match = pattern.match(os.environ['http_proxy']) - if match: - self.proxy = match.group('host') - self.proxy_port = match.group('port') - self.proxy_user = match.group('user') - self.proxy_pass = match.group('pass') - else: - if not self.proxy: - self.proxy = config.get_value('Boto', 'proxy', None) - if not self.proxy_port: - self.proxy_port = config.get_value('Boto', 'proxy_port', None) - if not self.proxy_user: - self.proxy_user = config.get_value('Boto', 'proxy_user', None) - if not self.proxy_pass: - self.proxy_pass = config.get_value('Boto', 'proxy_pass', None) - - if not self.proxy_port and self.proxy: - print("http_proxy environment variable does not specify " - "a port, using default") - self.proxy_port = self.port - - self.no_proxy = os.environ.get('no_proxy', '') or os.environ.get('NO_PROXY', '') - self.use_proxy = (self.proxy is not None) - - def get_http_connection(self, host, port, is_secure): - conn = self._pool.get_http_connection(host, port, is_secure) - if conn is not None: - return conn - else: - return self.new_http_connection(host, port, is_secure) - - def skip_proxy(self, host): - if not self.no_proxy: - return False - - if self.no_proxy == "*": - return True - - hostonly = host - hostonly = host.split(':')[0] - - for name in self.no_proxy.split(','): - if name and (hostonly.endswith(name) or host.endswith(name)): - return True - - return False - - def new_http_connection(self, host, port, is_secure): - if host is None: - host = self.server_name() - - # Make sure the host is really just the host, not including - # the port number - host = host.split(':', 1)[0] - - http_connection_kwargs = self.http_connection_kwargs.copy() - - # Connection factories below expect a port keyword argument - http_connection_kwargs['port'] = port - - # Override host with proxy settings if needed - if self.use_proxy and not is_secure and \ - not self.skip_proxy(host): - host = self.proxy - http_connection_kwargs['port'] = int(self.proxy_port) - - if is_secure: - boto.log.debug( - 'establishing HTTPS connection: host=%s, kwargs=%s', - host, http_connection_kwargs) - if self.use_proxy and not self.skip_proxy(host): - connection = self.proxy_ssl(host, is_secure and 443 or 80) - elif self.https_connection_factory: - connection = self.https_connection_factory(host) - elif self.https_validate_certificates and HAVE_HTTPS_CONNECTION: - connection = https_connection.CertValidatingHTTPSConnection( - host, ca_certs=self.ca_certificates_file, - **http_connection_kwargs) - else: - connection = http_client.HTTPSConnection( - host, **http_connection_kwargs) - else: - boto.log.debug('establishing HTTP connection: kwargs=%s' % - http_connection_kwargs) - if self.https_connection_factory: - # even though the factory says https, this is too handy - # to not be able to allow overriding for http also. - connection = self.https_connection_factory( - host, **http_connection_kwargs) - else: - connection = http_client.HTTPConnection( - host, **http_connection_kwargs) - if self.debug > 1: - connection.set_debuglevel(self.debug) - # self.connection must be maintained for backwards-compatibility - # however, it must be dynamically pulled from the connection pool - # set a private variable which will enable that - if host.split(':')[0] == self.host and is_secure == self.is_secure: - self._connection = (host, port, is_secure) - # Set the response class of the http connection to use our custom - # class. - connection.response_class = HTTPResponse - return connection - - def put_http_connection(self, host, port, is_secure, connection): - self._pool.put_http_connection(host, port, is_secure, connection) - - def proxy_ssl(self, host=None, port=None): - if host and port: - host = '%s:%d' % (host, port) - else: - host = '%s:%d' % (self.host, self.port) - # Seems properly to use timeout for connect too - timeout = self.http_connection_kwargs.get("timeout") - if timeout is not None: - sock = socket.create_connection((self.proxy, - int(self.proxy_port)), timeout) - else: - sock = socket.create_connection((self.proxy, int(self.proxy_port))) - boto.log.debug("Proxy connection: CONNECT %s HTTP/1.0\r\n", host) - sock.sendall("CONNECT %s HTTP/1.0\r\n" % host) - sock.sendall("User-Agent: %s\r\n" % UserAgent) - if self.proxy_user and self.proxy_pass: - for k, v in self.get_proxy_auth_header().items(): - sock.sendall("%s: %s\r\n" % (k, v)) - # See discussion about this config option at - # https://groups.google.com/forum/?fromgroups#!topic/boto-dev/teenFvOq2Cc - if config.getbool('Boto', 'send_crlf_after_proxy_auth_headers', False): - sock.sendall("\r\n") - else: - sock.sendall("\r\n") - resp = http_client.HTTPResponse(sock, strict=True, debuglevel=self.debug) - resp.begin() - - if resp.status != 200: - # Fake a socket error, use a code that make it obvious it hasn't - # been generated by the socket library - raise socket.error(-71, - "Error talking to HTTP proxy %s:%s: %s (%s)" % - (self.proxy, self.proxy_port, - resp.status, resp.reason)) - - # We can safely close the response, it duped the original socket - resp.close() - - h = http_client.HTTPConnection(host) - - if self.https_validate_certificates and HAVE_HTTPS_CONNECTION: - msg = "wrapping ssl socket for proxied connection; " - if self.ca_certificates_file: - msg += "CA certificate file=%s" % self.ca_certificates_file - else: - msg += "using system provided SSL certs" - boto.log.debug(msg) - key_file = self.http_connection_kwargs.get('key_file', None) - cert_file = self.http_connection_kwargs.get('cert_file', None) - sslSock = ssl.wrap_socket(sock, keyfile=key_file, - certfile=cert_file, - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=self.ca_certificates_file) - cert = sslSock.getpeercert() - hostname = self.host.split(':', 0)[0] - if not https_connection.ValidateCertificateHostname(cert, hostname): - raise https_connection.InvalidCertificateException( - hostname, cert, 'hostname mismatch') - else: - # Fallback for old Python without ssl.wrap_socket - if hasattr(http_client, 'ssl'): - sslSock = http_client.ssl.SSLSocket(sock) - else: - sslSock = socket.ssl(sock, None, None) - sslSock = http_client.FakeSocket(sock, sslSock) - - # This is a bit unclean - h.sock = sslSock - return h - - def prefix_proxy_to_path(self, path, host=None): - path = self.protocol + '://' + (host or self.server_name()) + path - return path - - def get_proxy_auth_header(self): - auth = encodebytes(self.proxy_user + ':' + self.proxy_pass) - return {'Proxy-Authorization': 'Basic %s' % auth} - - # For passing proxy information to other connection libraries, e.g. cloudsearch2 - def get_proxy_url_with_auth(self): - if not self.use_proxy: - return None - - if self.proxy_user or self.proxy_pass: - if self.proxy_pass: - login_info = '%s:%s@' % (self.proxy_user, self.proxy_pass) - else: - login_info = '%s@' % self.proxy_user - else: - login_info = '' - - return 'http://%s%s:%s' % (login_info, self.proxy, str(self.proxy_port or self.port)) - - def set_host_header(self, request): - try: - request.headers['Host'] = \ - self._auth_handler.host_header(self.host, request) - except AttributeError: - request.headers['Host'] = self.host.split(':', 1)[0] - - def set_request_hook(self, hook): - self.request_hook = hook - - def _mexe(self, request, sender=None, override_num_retries=None, - retry_handler=None): - """ - mexe - Multi-execute inside a loop, retrying multiple times to handle - transient Internet errors by simply trying again. - Also handles redirects. - - This code was inspired by the S3Utils classes posted to the boto-users - Google group by Larry Bates. Thanks! - - """ - boto.log.debug('Method: %s' % request.method) - boto.log.debug('Path: %s' % request.path) - boto.log.debug('Data: %s' % request.body) - boto.log.debug('Headers: %s' % request.headers) - boto.log.debug('Host: %s' % request.host) - boto.log.debug('Port: %s' % request.port) - boto.log.debug('Params: %s' % request.params) - response = None - body = None - e = None - if override_num_retries is None: - num_retries = config.getint('Boto', 'num_retries', self.num_retries) - else: - num_retries = override_num_retries - i = 0 - connection = self.get_http_connection(request.host, request.port, - self.is_secure) - - # Convert body to bytes if needed - if not isinstance(request.body, bytes) and hasattr(request.body, - 'encode'): - request.body = request.body.encode('utf-8') - - while i <= num_retries: - # Use binary exponential backoff to desynchronize client requests. - next_sleep = min(random.random() * (2 ** i), - boto.config.get('Boto', 'max_retry_delay', 60)) - try: - # we now re-sign each request before it is retried - boto.log.debug('Token: %s' % self.provider.security_token) - request.authorize(connection=self) - # Only force header for non-s3 connections, because s3 uses - # an older signing method + bucket resource URLs that include - # the port info. All others should be now be up to date and - # not include the port. - if 's3' not in self._required_auth_capability(): - if not getattr(self, 'anon', False): - self.set_host_header(request) - boto.log.debug('Final headers: %s' % request.headers) - request.start_time = datetime.now() - if callable(sender): - response = sender(connection, request.method, request.path, - request.body, request.headers) - else: - connection.request(request.method, request.path, - request.body, request.headers) - response = connection.getresponse() - boto.log.debug('Response headers: %s' % response.getheaders()) - location = response.getheader('location') - # -- gross hack -- - # http_client gets confused with chunked responses to HEAD requests - # so I have to fake it out - if request.method == 'HEAD' and getattr(response, - 'chunked', False): - response.chunked = 0 - if callable(retry_handler): - status = retry_handler(response, i, next_sleep) - if status: - msg, i, next_sleep = status - if msg: - boto.log.debug(msg) - time.sleep(next_sleep) - continue - if response.status in [500, 502, 503, 504]: - msg = 'Received %d response. ' % response.status - msg += 'Retrying in %3.1f seconds' % next_sleep - boto.log.debug(msg) - body = response.read() - if isinstance(body, bytes): - body = body.decode('utf-8') - elif response.status < 300 or response.status >= 400 or \ - not location: - # don't return connection to the pool if response contains - # Connection:close header, because the connection has been - # closed and default reconnect behavior may do something - # different than new_http_connection. Also, it's probably - # less efficient to try to reuse a closed connection. - conn_header_value = response.getheader('connection') - if conn_header_value == 'close': - connection.close() - else: - self.put_http_connection(request.host, request.port, - self.is_secure, connection) - if self.request_hook is not None: - self.request_hook.handle_request_data(request, response) - return response - else: - scheme, request.host, request.path, \ - params, query, fragment = urlparse(location) - if query: - request.path += '?' + query - # urlparse can return both host and port in netloc, so if - # that's the case we need to split them up properly - if ':' in request.host: - request.host, request.port = request.host.split(':', 1) - msg = 'Redirecting: %s' % scheme + '://' - msg += request.host + request.path - boto.log.debug(msg) - connection = self.get_http_connection(request.host, - request.port, - scheme == 'https') - response = None - continue - except PleaseRetryException as e: - boto.log.debug('encountered a retry exception: %s' % e) - connection = self.new_http_connection(request.host, request.port, - self.is_secure) - response = e.response - except self.http_exceptions as e: - for unretryable in self.http_unretryable_exceptions: - if isinstance(e, unretryable): - boto.log.debug( - 'encountered unretryable %s exception, re-raising' % - e.__class__.__name__) - raise - boto.log.debug('encountered %s exception, reconnecting' % - e.__class__.__name__) - connection = self.new_http_connection(request.host, request.port, - self.is_secure) - time.sleep(next_sleep) - i += 1 - # If we made it here, it's because we have exhausted our retries - # and stil haven't succeeded. So, if we have a response object, - # use it to raise an exception. - # Otherwise, raise the exception that must have already happened. - if self.request_hook is not None: - self.request_hook.handle_request_data(request, response, error=True) - if response: - raise BotoServerError(response.status, response.reason, body) - elif e: - raise - else: - msg = 'Please report this exception as a Boto Issue!' - raise BotoClientError(msg) - - def build_base_http_request(self, method, path, auth_path, - params=None, headers=None, data='', host=None): - path = self.get_path(path) - if auth_path is not None: - auth_path = self.get_path(auth_path) - if params is None: - params = {} - else: - params = params.copy() - if headers is None: - headers = {} - else: - headers = headers.copy() - if self.host_header and not boto.utils.find_matching_headers('host', headers): - headers['host'] = self.host_header - host = host or self.host - if self.use_proxy: - if not auth_path: - auth_path = path - path = self.prefix_proxy_to_path(path, host) - if self.proxy_user and self.proxy_pass and not self.is_secure: - # If is_secure, we don't have to set the proxy authentication - # header here, we did that in the CONNECT to the proxy. - headers.update(self.get_proxy_auth_header()) - return HTTPRequest(method, self.protocol, host, self.port, - path, auth_path, params, headers, data) - - def make_request(self, method, path, headers=None, data='', host=None, - auth_path=None, sender=None, override_num_retries=None, - params=None, retry_handler=None): - """Makes a request to the server, with stock multiple-retry logic.""" - if params is None: - params = {} - http_request = self.build_base_http_request(method, path, auth_path, - params, headers, data, host) - return self._mexe(http_request, sender, override_num_retries, - retry_handler=retry_handler) - - def close(self): - """(Optional) Close any open HTTP connections. This is non-destructive, - and making a new request will open a connection again.""" - - boto.log.debug('closing all HTTP connections') - self._connection = None # compat field - - -class AWSQueryConnection(AWSAuthConnection): - - APIVersion = '' - ResponseError = BotoServerError - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, host=None, debug=0, - https_connection_factory=None, path='/', security_token=None, - validate_certs=True, profile_name=None): - super(AWSQueryConnection, self).__init__( - host, aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, - proxy_port, proxy_user, proxy_pass, - debug, https_connection_factory, path, - security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return [] - - def get_utf8_value(self, value): - return boto.utils.get_utf8_value(value) - - def make_request(self, action, params=None, path='/', verb='GET'): - http_request = self.build_base_http_request(verb, path, None, - params, {}, '', - self.host) - if action: - http_request.params['Action'] = action - if self.APIVersion: - http_request.params['Version'] = self.APIVersion - return self._mexe(http_request) - - def build_list_params(self, params, items, label): - if isinstance(items, six.string_types): - items = [items] - for i in range(1, len(items) + 1): - params['%s.%d' % (label, i)] = items[i - 1] - - def build_complex_list_params(self, params, items, label, names): - """Serialize a list of structures. - - For example:: - - items = [('foo', 'bar', 'baz'), ('foo2', 'bar2', 'baz2')] - label = 'ParamName.member' - names = ('One', 'Two', 'Three') - self.build_complex_list_params(params, items, label, names) - - would result in the params dict being updated with these params:: - - ParamName.member.1.One = foo - ParamName.member.1.Two = bar - ParamName.member.1.Three = baz - - ParamName.member.2.One = foo2 - ParamName.member.2.Two = bar2 - ParamName.member.2.Three = baz2 - - :type params: dict - :param params: The params dict. The complex list params - will be added to this dict. - - :type items: list of tuples - :param items: The list to serialize. - - :type label: string - :param label: The prefix to apply to the parameter. - - :type names: tuple of strings - :param names: The names associated with each tuple element. - - """ - for i, item in enumerate(items, 1): - current_prefix = '%s.%s' % (label, i) - for key, value in zip(names, item): - full_key = '%s.%s' % (current_prefix, key) - params[full_key] = value - - # generics - - def get_list(self, action, params, markers, path='/', - parent=None, verb='GET'): - if not parent: - parent = self - response = self.make_request(action, params, path, verb) - body = response.read() - boto.log.debug(body) - if not body: - boto.log.error('Null body %s' % body) - raise self.ResponseError(response.status, response.reason, body) - elif response.status == 200: - rs = ResultSet(markers) - h = boto.handler.XmlHandler(rs, parent) - if isinstance(body, six.text_type): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return rs - else: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise self.ResponseError(response.status, response.reason, body) - - def get_object(self, action, params, cls, path='/', - parent=None, verb='GET'): - if not parent: - parent = self - response = self.make_request(action, params, path, verb) - body = response.read() - boto.log.debug(body) - if not body: - boto.log.error('Null body %s' % body) - raise self.ResponseError(response.status, response.reason, body) - elif response.status == 200: - obj = cls(parent) - h = boto.handler.XmlHandler(obj, parent) - if isinstance(body, six.text_type): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return obj - else: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise self.ResponseError(response.status, response.reason, body) - - def get_status(self, action, params, path='/', parent=None, verb='GET'): - if not parent: - parent = self - response = self.make_request(action, params, path, verb) - body = response.read() - boto.log.debug(body) - if not body: - boto.log.error('Null body %s' % body) - raise self.ResponseError(response.status, response.reason, body) - elif response.status == 200: - rs = ResultSet() - h = boto.handler.XmlHandler(rs, parent) - xml.sax.parseString(body, h) - return rs.status - else: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise self.ResponseError(response.status, response.reason, body) diff --git a/awx/lib/site-packages/boto/contrib/__init__.py b/awx/lib/site-packages/boto/contrib/__init__.py deleted file mode 100644 index a7e571e236..0000000000 --- a/awx/lib/site-packages/boto/contrib/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# diff --git a/awx/lib/site-packages/boto/contrib/ymlmessage.py b/awx/lib/site-packages/boto/contrib/ymlmessage.py deleted file mode 100644 index ae6aea488e..0000000000 --- a/awx/lib/site-packages/boto/contrib/ymlmessage.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2006,2007 Chris Moyer -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -This module was contributed by Chris Moyer. It provides a subclass of the -SQS Message class that supports YAML as the body of the message. - -This module requires the yaml module. -""" -from boto.sqs.message import Message -import yaml - - -class YAMLMessage(Message): - """ - The YAMLMessage class provides a YAML compatible message. Encoding and - decoding are handled automaticaly. - - Access this message data like such: - - m.data = [ 1, 2, 3] - m.data[0] # Returns 1 - - This depends on the PyYAML package - """ - - def __init__(self, queue=None, body='', xml_attrs=None): - self.data = None - super(YAMLMessage, self).__init__(queue, body) - - def set_body(self, body): - self.data = yaml.load(body) - - def get_body(self): - return yaml.dump(self.data) diff --git a/awx/lib/site-packages/boto/datapipeline/__init__.py b/awx/lib/site-packages/boto/datapipeline/__init__.py deleted file mode 100644 index 1f61ea67e9..0000000000 --- a/awx/lib/site-packages/boto/datapipeline/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import get_regions - - -def regions(): - """ - Get all available regions for the AWS Datapipeline service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.datapipeline.layer1 import DataPipelineConnection - return get_regions('datapipeline', connection_cls=DataPipelineConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/datapipeline/exceptions.py b/awx/lib/site-packages/boto/datapipeline/exceptions.py deleted file mode 100644 index c2761e25c1..0000000000 --- a/awx/lib/site-packages/boto/datapipeline/exceptions.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import JSONResponseError - - -class PipelineDeletedException(JSONResponseError): - pass - - -class InvalidRequestException(JSONResponseError): - pass - - -class TaskNotFoundException(JSONResponseError): - pass - - -class PipelineNotFoundException(JSONResponseError): - pass - - -class InternalServiceError(JSONResponseError): - pass diff --git a/awx/lib/site-packages/boto/datapipeline/layer1.py b/awx/lib/site-packages/boto/datapipeline/layer1.py deleted file mode 100644 index 028fd9d2e3..0000000000 --- a/awx/lib/site-packages/boto/datapipeline/layer1.py +++ /dev/null @@ -1,639 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.datapipeline import exceptions - - -class DataPipelineConnection(AWSQueryConnection): - """ - This is the AWS Data Pipeline API Reference . This guide provides - descriptions and samples of the AWS Data Pipeline API. - - AWS Data Pipeline is a web service that configures and manages a - data-driven workflow called a pipeline. AWS Data Pipeline handles - the details of scheduling and ensuring that data dependencies are - met so your application can focus on processing the data. - - The AWS Data Pipeline API implements two main sets of - functionality. The first set of actions configure the pipeline in - the web service. You call these actions to create a pipeline and - define data sources, schedules, dependencies, and the transforms - to be performed on the data. - - The second set of actions are used by a task runner application - that calls the AWS Data Pipeline API to receive the next task - ready for processing. The logic for performing the task, such as - querying the data, running data analysis, or converting the data - from one format to another, is contained within the task runner. - The task runner performs the task assigned to it by the web - service, reporting progress to the web service as it does so. When - the task is done, the task runner reports the final success or - failure of the task to the web service. - - AWS Data Pipeline provides an open-source implementation of a task - runner called AWS Data Pipeline Task Runner. AWS Data Pipeline - Task Runner provides logic for common data management scenarios, - such as performing database queries and running data analysis - using Amazon Elastic MapReduce (Amazon EMR). You can use AWS Data - Pipeline Task Runner as your task runner, or you can write your - own task runner to provide custom data management. - - The AWS Data Pipeline API uses the Signature Version 4 protocol - for signing requests. For more information about how to sign a - request with this protocol, see `Signature Version 4 Signing - Process`_. In the code examples in this reference, the Signature - Version 4 Request parameters are represented as AuthParams. - """ - APIVersion = "2012-10-29" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "datapipeline.us-east-1.amazonaws.com" - ServiceName = "DataPipeline" - TargetPrefix = "DataPipeline" - ResponseError = JSONResponseError - - _faults = { - "PipelineDeletedException": exceptions.PipelineDeletedException, - "InvalidRequestException": exceptions.InvalidRequestException, - "TaskNotFoundException": exceptions.TaskNotFoundException, - "PipelineNotFoundException": exceptions.PipelineNotFoundException, - "InternalServiceError": exceptions.InternalServiceError, - } - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - kwargs['host'] = region.endpoint - super(DataPipelineConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def activate_pipeline(self, pipeline_id): - """ - Validates a pipeline and initiates processing. If the pipeline - does not pass validation, activation fails. - - Call this action to start processing pipeline tasks of a - pipeline you've created using the CreatePipeline and - PutPipelineDefinition actions. A pipeline cannot be modified - after it has been successfully activated. - - :type pipeline_id: string - :param pipeline_id: The identifier of the pipeline to activate. - - """ - params = {'pipelineId': pipeline_id, } - return self.make_request(action='ActivatePipeline', - body=json.dumps(params)) - - def create_pipeline(self, name, unique_id, description=None): - """ - Creates a new empty pipeline. When this action succeeds, you - can then use the PutPipelineDefinition action to populate the - pipeline. - - :type name: string - :param name: The name of the new pipeline. You can use the same name - for multiple pipelines associated with your AWS account, because - AWS Data Pipeline assigns each new pipeline a unique pipeline - identifier. - - :type unique_id: string - :param unique_id: A unique identifier that you specify. This identifier - is not the same as the pipeline identifier assigned by AWS Data - Pipeline. You are responsible for defining the format and ensuring - the uniqueness of this identifier. You use this parameter to ensure - idempotency during repeated calls to CreatePipeline. For example, - if the first call to CreatePipeline does not return a clear - success, you can pass in the same unique identifier and pipeline - name combination on a subsequent call to CreatePipeline. - CreatePipeline ensures that if a pipeline already exists with the - same name and unique identifier, a new pipeline will not be - created. Instead, you'll receive the pipeline identifier from the - previous attempt. The uniqueness of the name and unique identifier - combination is scoped to the AWS account or IAM user credentials. - - :type description: string - :param description: The description of the new pipeline. - - """ - params = {'name': name, 'uniqueId': unique_id, } - if description is not None: - params['description'] = description - return self.make_request(action='CreatePipeline', - body=json.dumps(params)) - - def delete_pipeline(self, pipeline_id): - """ - Permanently deletes a pipeline, its pipeline definition and - its run history. You cannot query or restore a deleted - pipeline. AWS Data Pipeline will attempt to cancel instances - associated with the pipeline that are currently being - processed by task runners. Deleting a pipeline cannot be - undone. - - To temporarily pause a pipeline instead of deleting it, call - SetStatus with the status set to Pause on individual - components. Components that are paused by SetStatus can be - resumed. - - :type pipeline_id: string - :param pipeline_id: The identifier of the pipeline to be deleted. - - """ - params = {'pipelineId': pipeline_id, } - return self.make_request(action='DeletePipeline', - body=json.dumps(params)) - - def describe_objects(self, object_ids, pipeline_id, marker=None, - evaluate_expressions=None): - """ - Returns the object definitions for a set of objects associated - with the pipeline. Object definitions are composed of a set of - fields that define the properties of the object. - - :type pipeline_id: string - :param pipeline_id: Identifier of the pipeline that contains the object - definitions. - - :type object_ids: list - :param object_ids: Identifiers of the pipeline objects that contain the - definitions to be described. You can pass as many as 25 identifiers - in a single call to DescribeObjects. - - :type evaluate_expressions: boolean - :param evaluate_expressions: Indicates whether any expressions in the - object should be evaluated when the object descriptions are - returned. - - :type marker: string - :param marker: The starting point for the results to be returned. The - first time you call DescribeObjects, this value should be empty. As - long as the action returns `HasMoreResults` as `True`, you can call - DescribeObjects again and pass the marker value from the response - to retrieve the next set of results. - - """ - params = { - 'pipelineId': pipeline_id, - 'objectIds': object_ids, - } - if evaluate_expressions is not None: - params['evaluateExpressions'] = evaluate_expressions - if marker is not None: - params['marker'] = marker - return self.make_request(action='DescribeObjects', - body=json.dumps(params)) - - def describe_pipelines(self, pipeline_ids): - """ - Retrieve metadata about one or more pipelines. The information - retrieved includes the name of the pipeline, the pipeline - identifier, its current state, and the user account that owns - the pipeline. Using account credentials, you can retrieve - metadata about pipelines that you or your IAM users have - created. If you are using an IAM user account, you can - retrieve metadata about only those pipelines you have read - permission for. - - To retrieve the full pipeline definition instead of metadata - about the pipeline, call the GetPipelineDefinition action. - - :type pipeline_ids: list - :param pipeline_ids: Identifiers of the pipelines to describe. You can - pass as many as 25 identifiers in a single call to - DescribePipelines. You can obtain pipeline identifiers by calling - ListPipelines. - - """ - params = {'pipelineIds': pipeline_ids, } - return self.make_request(action='DescribePipelines', - body=json.dumps(params)) - - def evaluate_expression(self, pipeline_id, expression, object_id): - """ - Evaluates a string in the context of a specified object. A - task runner can use this action to evaluate SQL queries stored - in Amazon S3. - - :type pipeline_id: string - :param pipeline_id: The identifier of the pipeline. - - :type object_id: string - :param object_id: The identifier of the object. - - :type expression: string - :param expression: The expression to evaluate. - - """ - params = { - 'pipelineId': pipeline_id, - 'objectId': object_id, - 'expression': expression, - } - return self.make_request(action='EvaluateExpression', - body=json.dumps(params)) - - def get_pipeline_definition(self, pipeline_id, version=None): - """ - Returns the definition of the specified pipeline. You can call - GetPipelineDefinition to retrieve the pipeline definition you - provided using PutPipelineDefinition. - - :type pipeline_id: string - :param pipeline_id: The identifier of the pipeline. - - :type version: string - :param version: The version of the pipeline definition to retrieve. - This parameter accepts the values `latest` (default) and `active`. - Where `latest` indicates the last definition saved to the pipeline - and `active` indicates the last definition of the pipeline that was - activated. - - """ - params = {'pipelineId': pipeline_id, } - if version is not None: - params['version'] = version - return self.make_request(action='GetPipelineDefinition', - body=json.dumps(params)) - - def list_pipelines(self, marker=None): - """ - Returns a list of pipeline identifiers for all active - pipelines. Identifiers are returned only for pipelines you - have permission to access. - - :type marker: string - :param marker: The starting point for the results to be returned. The - first time you call ListPipelines, this value should be empty. As - long as the action returns `HasMoreResults` as `True`, you can call - ListPipelines again and pass the marker value from the response to - retrieve the next set of results. - - """ - params = {} - if marker is not None: - params['marker'] = marker - return self.make_request(action='ListPipelines', - body=json.dumps(params)) - - def poll_for_task(self, worker_group, hostname=None, - instance_identity=None): - """ - Task runners call this action to receive a task to perform - from AWS Data Pipeline. The task runner specifies which tasks - it can perform by setting a value for the workerGroup - parameter of the PollForTask call. The task returned by - PollForTask may come from any of the pipelines that match the - workerGroup value passed in by the task runner and that was - launched using the IAM user credentials specified by the task - runner. - - If tasks are ready in the work queue, PollForTask returns a - response immediately. If no tasks are available in the queue, - PollForTask uses long-polling and holds on to a poll - connection for up to a 90 seconds during which time the first - newly scheduled task is handed to the task runner. To - accomodate this, set the socket timeout in your task runner to - 90 seconds. The task runner should not call PollForTask again - on the same `workerGroup` until it receives a response, and - this may take up to 90 seconds. - - :type worker_group: string - :param worker_group: Indicates the type of task the task runner is - configured to accept and process. The worker group is set as a - field on objects in the pipeline when they are created. You can - only specify a single value for `workerGroup` in the call to - PollForTask. There are no wildcard values permitted in - `workerGroup`, the string must be an exact, case-sensitive, match. - - :type hostname: string - :param hostname: The public DNS name of the calling task runner. - - :type instance_identity: dict - :param instance_identity: Identity information for the Amazon EC2 - instance that is hosting the task runner. You can get this value by - calling the URI, `http://169.254.169.254/latest/meta-data/instance- - id`, from the EC2 instance. For more information, go to `Instance - Metadata`_ in the Amazon Elastic Compute Cloud User Guide. Passing - in this value proves that your task runner is running on an EC2 - instance, and ensures the proper AWS Data Pipeline service charges - are applied to your pipeline. - - """ - params = {'workerGroup': worker_group, } - if hostname is not None: - params['hostname'] = hostname - if instance_identity is not None: - params['instanceIdentity'] = instance_identity - return self.make_request(action='PollForTask', - body=json.dumps(params)) - - def put_pipeline_definition(self, pipeline_objects, pipeline_id): - """ - Adds tasks, schedules, and preconditions that control the - behavior of the pipeline. You can use PutPipelineDefinition to - populate a new pipeline or to update an existing pipeline that - has not yet been activated. - - PutPipelineDefinition also validates the configuration as it - adds it to the pipeline. Changes to the pipeline are saved - unless one of the following three validation errors exists in - the pipeline. - - #. An object is missing a name or identifier field. - #. A string or reference field is empty. - #. The number of objects in the pipeline exceeds the maximum - allowed objects. - - - - Pipeline object definitions are passed to the - PutPipelineDefinition action and returned by the - GetPipelineDefinition action. - - :type pipeline_id: string - :param pipeline_id: The identifier of the pipeline to be configured. - - :type pipeline_objects: list - :param pipeline_objects: The objects that define the pipeline. These - will overwrite the existing pipeline definition. - - """ - params = { - 'pipelineId': pipeline_id, - 'pipelineObjects': pipeline_objects, - } - return self.make_request(action='PutPipelineDefinition', - body=json.dumps(params)) - - def query_objects(self, pipeline_id, sphere, marker=None, query=None, - limit=None): - """ - Queries a pipeline for the names of objects that match a - specified set of conditions. - - The objects returned by QueryObjects are paginated and then - filtered by the value you set for query. This means the action - may return an empty result set with a value set for marker. If - `HasMoreResults` is set to `True`, you should continue to call - QueryObjects, passing in the returned value for marker, until - `HasMoreResults` returns `False`. - - :type pipeline_id: string - :param pipeline_id: Identifier of the pipeline to be queried for object - names. - - :type query: dict - :param query: Query that defines the objects to be returned. The Query - object can contain a maximum of ten selectors. The conditions in - the query are limited to top-level String fields in the object. - These filters can be applied to components, instances, and - attempts. - - :type sphere: string - :param sphere: Specifies whether the query applies to components or - instances. Allowable values: `COMPONENT`, `INSTANCE`, `ATTEMPT`. - - :type marker: string - :param marker: The starting point for the results to be returned. The - first time you call QueryObjects, this value should be empty. As - long as the action returns `HasMoreResults` as `True`, you can call - QueryObjects again and pass the marker value from the response to - retrieve the next set of results. - - :type limit: integer - :param limit: Specifies the maximum number of object names that - QueryObjects will return in a single call. The default value is - 100. - - """ - params = {'pipelineId': pipeline_id, 'sphere': sphere, } - if query is not None: - params['query'] = query - if marker is not None: - params['marker'] = marker - if limit is not None: - params['limit'] = limit - return self.make_request(action='QueryObjects', - body=json.dumps(params)) - - def report_task_progress(self, task_id): - """ - Updates the AWS Data Pipeline service on the progress of the - calling task runner. When the task runner is assigned a task, - it should call ReportTaskProgress to acknowledge that it has - the task within 2 minutes. If the web service does not recieve - this acknowledgement within the 2 minute window, it will - assign the task in a subsequent PollForTask call. After this - initial acknowledgement, the task runner only needs to report - progress every 15 minutes to maintain its ownership of the - task. You can change this reporting time from 15 minutes by - specifying a `reportProgressTimeout` field in your pipeline. - If a task runner does not report its status after 5 minutes, - AWS Data Pipeline will assume that the task runner is unable - to process the task and will reassign the task in a subsequent - response to PollForTask. task runners should call - ReportTaskProgress every 60 seconds. - - :type task_id: string - :param task_id: Identifier of the task assigned to the task runner. - This value is provided in the TaskObject that the service returns - with the response for the PollForTask action. - - """ - params = {'taskId': task_id, } - return self.make_request(action='ReportTaskProgress', - body=json.dumps(params)) - - def report_task_runner_heartbeat(self, taskrunner_id, worker_group=None, - hostname=None): - """ - Task runners call ReportTaskRunnerHeartbeat every 15 minutes - to indicate that they are operational. In the case of AWS Data - Pipeline Task Runner launched on a resource managed by AWS - Data Pipeline, the web service can use this call to detect - when the task runner application has failed and restart a new - instance. - - :type taskrunner_id: string - :param taskrunner_id: The identifier of the task runner. This value - should be unique across your AWS account. In the case of AWS Data - Pipeline Task Runner launched on a resource managed by AWS Data - Pipeline, the web service provides a unique identifier when it - launches the application. If you have written a custom task runner, - you should assign a unique identifier for the task runner. - - :type worker_group: string - :param worker_group: Indicates the type of task the task runner is - configured to accept and process. The worker group is set as a - field on objects in the pipeline when they are created. You can - only specify a single value for `workerGroup` in the call to - ReportTaskRunnerHeartbeat. There are no wildcard values permitted - in `workerGroup`, the string must be an exact, case-sensitive, - match. - - :type hostname: string - :param hostname: The public DNS name of the calling task runner. - - """ - params = {'taskrunnerId': taskrunner_id, } - if worker_group is not None: - params['workerGroup'] = worker_group - if hostname is not None: - params['hostname'] = hostname - return self.make_request(action='ReportTaskRunnerHeartbeat', - body=json.dumps(params)) - - def set_status(self, object_ids, status, pipeline_id): - """ - Requests that the status of an array of physical or logical - pipeline objects be updated in the pipeline. This update may - not occur immediately, but is eventually consistent. The - status that can be set depends on the type of object. - - :type pipeline_id: string - :param pipeline_id: Identifies the pipeline that contains the objects. - - :type object_ids: list - :param object_ids: Identifies an array of objects. The corresponding - objects can be either physical or components, but not a mix of both - types. - - :type status: string - :param status: Specifies the status to be set on all the objects in - `objectIds`. For components, this can be either `PAUSE` or - `RESUME`. For instances, this can be either `CANCEL`, `RERUN`, or - `MARK_FINISHED`. - - """ - params = { - 'pipelineId': pipeline_id, - 'objectIds': object_ids, - 'status': status, - } - return self.make_request(action='SetStatus', - body=json.dumps(params)) - - def set_task_status(self, task_id, task_status, error_id=None, - error_message=None, error_stack_trace=None): - """ - Notifies AWS Data Pipeline that a task is completed and - provides information about the final status. The task runner - calls this action regardless of whether the task was - sucessful. The task runner does not need to call SetTaskStatus - for tasks that are canceled by the web service during a call - to ReportTaskProgress. - - :type task_id: string - :param task_id: Identifies the task assigned to the task runner. This - value is set in the TaskObject that is returned by the PollForTask - action. - - :type task_status: string - :param task_status: If `FINISHED`, the task successfully completed. If - `FAILED` the task ended unsuccessfully. The `FALSE` value is used - by preconditions. - - :type error_id: string - :param error_id: If an error occurred during the task, this value - specifies an id value that represents the error. This value is set - on the physical attempt object. It is used to display error - information to the user. It should not start with string "Service_" - which is reserved by the system. - - :type error_message: string - :param error_message: If an error occurred during the task, this value - specifies a text description of the error. This value is set on the - physical attempt object. It is used to display error information to - the user. The web service does not parse this value. - - :type error_stack_trace: string - :param error_stack_trace: If an error occurred during the task, this - value specifies the stack trace associated with the error. This - value is set on the physical attempt object. It is used to display - error information to the user. The web service does not parse this - value. - - """ - params = {'taskId': task_id, 'taskStatus': task_status, } - if error_id is not None: - params['errorId'] = error_id - if error_message is not None: - params['errorMessage'] = error_message - if error_stack_trace is not None: - params['errorStackTrace'] = error_stack_trace - return self.make_request(action='SetTaskStatus', - body=json.dumps(params)) - - def validate_pipeline_definition(self, pipeline_objects, pipeline_id): - """ - Tests the pipeline definition with a set of validation checks - to ensure that it is well formed and can run without error. - - :type pipeline_id: string - :param pipeline_id: Identifies the pipeline whose definition is to be - validated. - - :type pipeline_objects: list - :param pipeline_objects: A list of objects that define the pipeline - changes to validate against the pipeline. - - """ - params = { - 'pipelineId': pipeline_id, - 'pipelineObjects': pipeline_objects, - } - return self.make_request(action='ValidatePipelineDefinition', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/directconnect/__init__.py b/awx/lib/site-packages/boto/directconnect/__init__.py deleted file mode 100644 index 2603177d62..0000000000 --- a/awx/lib/site-packages/boto/directconnect/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the AWS DirectConnect service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.directconnect.layer1 import DirectConnectConnection - return get_regions('directconnect', connection_cls=DirectConnectConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/directconnect/exceptions.py b/awx/lib/site-packages/boto/directconnect/exceptions.py deleted file mode 100644 index 88168d302c..0000000000 --- a/awx/lib/site-packages/boto/directconnect/exceptions.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - -class DirectConnectClientException(Exception): - pass - - -class DirectConnectServerException(Exception): - pass diff --git a/awx/lib/site-packages/boto/directconnect/layer1.py b/awx/lib/site-packages/boto/directconnect/layer1.py deleted file mode 100644 index a332b31bdd..0000000000 --- a/awx/lib/site-packages/boto/directconnect/layer1.py +++ /dev/null @@ -1,627 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.directconnect import exceptions -from boto.compat import json - - -class DirectConnectConnection(AWSQueryConnection): - """ - AWS Direct Connect makes it easy to establish a dedicated network - connection from your premises to Amazon Web Services (AWS). Using - AWS Direct Connect, you can establish private connectivity between - AWS and your data center, office, or colocation environment, which - in many cases can reduce your network costs, increase bandwidth - throughput, and provide a more consistent network experience than - Internet-based connections. - - The AWS Direct Connect API Reference provides descriptions, - syntax, and usage examples for each of the actions and data types - for AWS Direct Connect. Use the following links to get started - using the AWS Direct Connect API Reference : - - - + `Actions`_: An alphabetical list of all AWS Direct Connect - actions. - + `Data Types`_: An alphabetical list of all AWS Direct Connect - data types. - + `Common Query Parameters`_: Parameters that all Query actions - can use. - + `Common Errors`_: Client and server errors that all actions can - return. - """ - APIVersion = "2012-10-25" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "directconnect.us-east-1.amazonaws.com" - ServiceName = "DirectConnect" - TargetPrefix = "OvertureService" - ResponseError = JSONResponseError - - _faults = { - "DirectConnectClientException": exceptions.DirectConnectClientException, - "DirectConnectServerException": exceptions.DirectConnectServerException, - } - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs: - kwargs['host'] = region.endpoint - - super(DirectConnectConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def allocate_connection_on_interconnect(self, bandwidth, connection_name, - owner_account, interconnect_id, - vlan): - """ - Creates a hosted connection on an interconnect. - - Allocates a VLAN number and a specified amount of bandwidth - for use by a hosted connection on the given interconnect. - - :type bandwidth: string - :param bandwidth: Bandwidth of the connection. - Example: " 500Mbps " - - Default: None - - :type connection_name: string - :param connection_name: Name of the provisioned connection. - Example: " 500M Connection to AWS " - - Default: None - - :type owner_account: string - :param owner_account: Numeric account Id of the customer for whom the - connection will be provisioned. - Example: 123443215678 - - Default: None - - :type interconnect_id: string - :param interconnect_id: ID of the interconnect on which the connection - will be provisioned. - Example: dxcon-456abc78 - - Default: None - - :type vlan: integer - :param vlan: The dedicated VLAN provisioned to the connection. - Example: 101 - - Default: None - - """ - params = { - 'bandwidth': bandwidth, - 'connectionName': connection_name, - 'ownerAccount': owner_account, - 'interconnectId': interconnect_id, - 'vlan': vlan, - } - return self.make_request(action='AllocateConnectionOnInterconnect', - body=json.dumps(params)) - - def allocate_private_virtual_interface(self, connection_id, - owner_account, - new_private_virtual_interface_allocation): - """ - Provisions a private virtual interface to be owned by a - different customer. - - The owner of a connection calls this function to provision a - private virtual interface which will be owned by another AWS - customer. - - Virtual interfaces created using this function must be - confirmed by the virtual interface owner by calling - ConfirmPrivateVirtualInterface. Until this step has been - completed, the virtual interface will be in 'Confirming' - state, and will not be available for handling traffic. - - :type connection_id: string - :param connection_id: The connection ID on which the private virtual - interface is provisioned. - Default: None - - :type owner_account: string - :param owner_account: The AWS account that will own the new private - virtual interface. - Default: None - - :type new_private_virtual_interface_allocation: dict - :param new_private_virtual_interface_allocation: Detailed information - for the private virtual interface to be provisioned. - Default: None - - """ - params = { - 'connectionId': connection_id, - 'ownerAccount': owner_account, - 'newPrivateVirtualInterfaceAllocation': new_private_virtual_interface_allocation, - } - return self.make_request(action='AllocatePrivateVirtualInterface', - body=json.dumps(params)) - - def allocate_public_virtual_interface(self, connection_id, owner_account, - new_public_virtual_interface_allocation): - """ - Provisions a public virtual interface to be owned by a - different customer. - - The owner of a connection calls this function to provision a - public virtual interface which will be owned by another AWS - customer. - - Virtual interfaces created using this function must be - confirmed by the virtual interface owner by calling - ConfirmPublicVirtualInterface. Until this step has been - completed, the virtual interface will be in 'Confirming' - state, and will not be available for handling traffic. - - :type connection_id: string - :param connection_id: The connection ID on which the public virtual - interface is provisioned. - Default: None - - :type owner_account: string - :param owner_account: The AWS account that will own the new public - virtual interface. - Default: None - - :type new_public_virtual_interface_allocation: dict - :param new_public_virtual_interface_allocation: Detailed information - for the public virtual interface to be provisioned. - Default: None - - """ - params = { - 'connectionId': connection_id, - 'ownerAccount': owner_account, - 'newPublicVirtualInterfaceAllocation': new_public_virtual_interface_allocation, - } - return self.make_request(action='AllocatePublicVirtualInterface', - body=json.dumps(params)) - - def confirm_connection(self, connection_id): - """ - Confirm the creation of a hosted connection on an - interconnect. - - Upon creation, the hosted connection is initially in the - 'Ordering' state, and will remain in this state until the - owner calls ConfirmConnection to confirm creation of the - hosted connection. - - :type connection_id: string - :param connection_id: ID of the connection. - Example: dxcon-fg5678gh - - Default: None - - """ - params = {'connectionId': connection_id, } - return self.make_request(action='ConfirmConnection', - body=json.dumps(params)) - - def confirm_private_virtual_interface(self, virtual_interface_id, - virtual_gateway_id): - """ - Accept ownership of a private virtual interface created by - another customer. - - After the virtual interface owner calls this function, the - virtual interface will be created and attached to the given - virtual private gateway, and will be available for handling - traffic. - - :type virtual_interface_id: string - :param virtual_interface_id: ID of the virtual interface. - Example: dxvif-123dfg56 - - Default: None - - :type virtual_gateway_id: string - :param virtual_gateway_id: ID of the virtual private gateway that will - be attached to the virtual interface. - A virtual private gateway can be managed via the Amazon Virtual Private - Cloud (VPC) console or the `EC2 CreateVpnGateway`_ action. - - Default: None - - """ - params = { - 'virtualInterfaceId': virtual_interface_id, - 'virtualGatewayId': virtual_gateway_id, - } - return self.make_request(action='ConfirmPrivateVirtualInterface', - body=json.dumps(params)) - - def confirm_public_virtual_interface(self, virtual_interface_id): - """ - Accept ownership of a public virtual interface created by - another customer. - - After the virtual interface owner calls this function, the - specified virtual interface will be created and made available - for handling traffic. - - :type virtual_interface_id: string - :param virtual_interface_id: ID of the virtual interface. - Example: dxvif-123dfg56 - - Default: None - - """ - params = {'virtualInterfaceId': virtual_interface_id, } - return self.make_request(action='ConfirmPublicVirtualInterface', - body=json.dumps(params)) - - def create_connection(self, location, bandwidth, connection_name): - """ - Creates a new connection between the customer network and a - specific AWS Direct Connect location. - - A connection links your internal network to an AWS Direct - Connect location over a standard 1 gigabit or 10 gigabit - Ethernet fiber-optic cable. One end of the cable is connected - to your router, the other to an AWS Direct Connect router. An - AWS Direct Connect location provides access to Amazon Web - Services in the region it is associated with. You can - establish connections with AWS Direct Connect locations in - multiple regions, but a connection in one region does not - provide connectivity to other regions. - - :type location: string - :param location: Where the connection is located. - Example: EqSV5 - - Default: None - - :type bandwidth: string - :param bandwidth: Bandwidth of the connection. - Example: 1Gbps - - Default: None - - :type connection_name: string - :param connection_name: The name of the connection. - Example: " My Connection to AWS " - - Default: None - - """ - params = { - 'location': location, - 'bandwidth': bandwidth, - 'connectionName': connection_name, - } - return self.make_request(action='CreateConnection', - body=json.dumps(params)) - - def create_interconnect(self, interconnect_name, bandwidth, location): - """ - Creates a new interconnect between a AWS Direct Connect - partner's network and a specific AWS Direct Connect location. - - An interconnect is a connection which is capable of hosting - other connections. The AWS Direct Connect partner can use an - interconnect to provide sub-1Gbps AWS Direct Connect service - to tier 2 customers who do not have their own connections. - Like a standard connection, an interconnect links the AWS - Direct Connect partner's network to an AWS Direct Connect - location over a standard 1 Gbps or 10 Gbps Ethernet fiber- - optic cable. One end is connected to the partner's router, the - other to an AWS Direct Connect router. - - For each end customer, the AWS Direct Connect partner - provisions a connection on their interconnect by calling - AllocateConnectionOnInterconnect. The end customer can then - connect to AWS resources by creating a virtual interface on - their connection, using the VLAN assigned to them by the AWS - Direct Connect partner. - - :type interconnect_name: string - :param interconnect_name: The name of the interconnect. - Example: " 1G Interconnect to AWS " - - Default: None - - :type bandwidth: string - :param bandwidth: The port bandwidth - Example: 1Gbps - - Default: None - - Available values: 1Gbps,10Gbps - - :type location: string - :param location: Where the interconnect is located - Example: EqSV5 - - Default: None - - """ - params = { - 'interconnectName': interconnect_name, - 'bandwidth': bandwidth, - 'location': location, - } - return self.make_request(action='CreateInterconnect', - body=json.dumps(params)) - - def create_private_virtual_interface(self, connection_id, - new_private_virtual_interface): - """ - Creates a new private virtual interface. A virtual interface - is the VLAN that transports AWS Direct Connect traffic. A - private virtual interface supports sending traffic to a single - virtual private cloud (VPC). - - :type connection_id: string - :param connection_id: ID of the connection. - Example: dxcon-fg5678gh - - Default: None - - :type new_private_virtual_interface: dict - :param new_private_virtual_interface: Detailed information for the - private virtual interface to be created. - Default: None - - """ - params = { - 'connectionId': connection_id, - 'newPrivateVirtualInterface': new_private_virtual_interface, - } - return self.make_request(action='CreatePrivateVirtualInterface', - body=json.dumps(params)) - - def create_public_virtual_interface(self, connection_id, - new_public_virtual_interface): - """ - Creates a new public virtual interface. A virtual interface is - the VLAN that transports AWS Direct Connect traffic. A public - virtual interface supports sending traffic to public services - of AWS such as Amazon Simple Storage Service (Amazon S3). - - :type connection_id: string - :param connection_id: ID of the connection. - Example: dxcon-fg5678gh - - Default: None - - :type new_public_virtual_interface: dict - :param new_public_virtual_interface: Detailed information for the - public virtual interface to be created. - Default: None - - """ - params = { - 'connectionId': connection_id, - 'newPublicVirtualInterface': new_public_virtual_interface, - } - return self.make_request(action='CreatePublicVirtualInterface', - body=json.dumps(params)) - - def delete_connection(self, connection_id): - """ - Deletes the connection. - - Deleting a connection only stops the AWS Direct Connect port - hour and data transfer charges. You need to cancel separately - with the providers any services or charges for cross-connects - or network circuits that connect you to the AWS Direct Connect - location. - - :type connection_id: string - :param connection_id: ID of the connection. - Example: dxcon-fg5678gh - - Default: None - - """ - params = {'connectionId': connection_id, } - return self.make_request(action='DeleteConnection', - body=json.dumps(params)) - - def delete_interconnect(self, interconnect_id): - """ - Deletes the specified interconnect. - - :type interconnect_id: string - :param interconnect_id: The ID of the interconnect. - Example: dxcon-abc123 - - """ - params = {'interconnectId': interconnect_id, } - return self.make_request(action='DeleteInterconnect', - body=json.dumps(params)) - - def delete_virtual_interface(self, virtual_interface_id): - """ - Deletes a virtual interface. - - :type virtual_interface_id: string - :param virtual_interface_id: ID of the virtual interface. - Example: dxvif-123dfg56 - - Default: None - - """ - params = {'virtualInterfaceId': virtual_interface_id, } - return self.make_request(action='DeleteVirtualInterface', - body=json.dumps(params)) - - def describe_connections(self, connection_id=None): - """ - Displays all connections in this region. - - If a connection ID is provided, the call returns only that - particular connection. - - :type connection_id: string - :param connection_id: ID of the connection. - Example: dxcon-fg5678gh - - Default: None - - """ - params = {} - if connection_id is not None: - params['connectionId'] = connection_id - return self.make_request(action='DescribeConnections', - body=json.dumps(params)) - - def describe_connections_on_interconnect(self, interconnect_id): - """ - Return a list of connections that have been provisioned on the - given interconnect. - - :type interconnect_id: string - :param interconnect_id: ID of the interconnect on which a list of - connection is provisioned. - Example: dxcon-abc123 - - Default: None - - """ - params = {'interconnectId': interconnect_id, } - return self.make_request(action='DescribeConnectionsOnInterconnect', - body=json.dumps(params)) - - def describe_interconnects(self, interconnect_id=None): - """ - Returns a list of interconnects owned by the AWS account. - - If an interconnect ID is provided, it will only return this - particular interconnect. - - :type interconnect_id: string - :param interconnect_id: The ID of the interconnect. - Example: dxcon-abc123 - - """ - params = {} - if interconnect_id is not None: - params['interconnectId'] = interconnect_id - return self.make_request(action='DescribeInterconnects', - body=json.dumps(params)) - - def describe_locations(self): - """ - Returns the list of AWS Direct Connect locations in the - current AWS region. These are the locations that may be - selected when calling CreateConnection or CreateInterconnect. - """ - params = {} - return self.make_request(action='DescribeLocations', - body=json.dumps(params)) - - def describe_virtual_gateways(self): - """ - Returns a list of virtual private gateways owned by the AWS - account. - - You can create one or more AWS Direct Connect private virtual - interfaces linking to a virtual private gateway. A virtual - private gateway can be managed via Amazon Virtual Private - Cloud (VPC) console or the `EC2 CreateVpnGateway`_ action. - """ - params = {} - return self.make_request(action='DescribeVirtualGateways', - body=json.dumps(params)) - - def describe_virtual_interfaces(self, connection_id=None, - virtual_interface_id=None): - """ - Displays all virtual interfaces for an AWS account. Virtual - interfaces deleted fewer than 15 minutes before - DescribeVirtualInterfaces is called are also returned. If a - connection ID is included then only virtual interfaces - associated with this connection will be returned. If a virtual - interface ID is included then only a single virtual interface - will be returned. - - A virtual interface (VLAN) transmits the traffic between the - AWS Direct Connect location and the customer. - - If a connection ID is provided, only virtual interfaces - provisioned on the specified connection will be returned. If a - virtual interface ID is provided, only this particular virtual - interface will be returned. - - :type connection_id: string - :param connection_id: ID of the connection. - Example: dxcon-fg5678gh - - Default: None - - :type virtual_interface_id: string - :param virtual_interface_id: ID of the virtual interface. - Example: dxvif-123dfg56 - - Default: None - - """ - params = {} - if connection_id is not None: - params['connectionId'] = connection_id - if virtual_interface_id is not None: - params['virtualInterfaceId'] = virtual_interface_id - return self.make_request(action='DescribeVirtualInterfaces', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/dynamodb/__init__.py b/awx/lib/site-packages/boto/dynamodb/__init__.py deleted file mode 100644 index 8d548167d8..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon DynamoDB service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - import boto.dynamodb.layer2 - return get_regions('dynamodb', connection_cls=boto.dynamodb.layer2.Layer2) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/dynamodb/batch.py b/awx/lib/site-packages/boto/dynamodb/batch.py deleted file mode 100644 index f30b8425c6..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/batch.py +++ /dev/null @@ -1,261 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.compat import six - - -class Batch(object): - """ - Used to construct a BatchGet request. - - :ivar table: The Table object from which the item is retrieved. - - :ivar keys: A list of scalar or tuple values. Each element in the - list represents one Item to retrieve. If the schema for the - table has both a HashKey and a RangeKey, each element in the - list should be a tuple consisting of (hash_key, range_key). If - the schema for the table contains only a HashKey, each element - in the list should be a scalar value of the appropriate type - for the table schema. NOTE: The maximum number of items that - can be retrieved for a single operation is 100. Also, the - number of items retrieved is constrained by a 1 MB size limit. - - :ivar attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :ivar consistent_read: Specify whether or not to use a - consistent read. Defaults to False. - - """ - - def __init__(self, table, keys, attributes_to_get=None, - consistent_read=False): - self.table = table - self.keys = keys - self.attributes_to_get = attributes_to_get - self.consistent_read = consistent_read - - def to_dict(self): - """ - Convert the Batch object into the format required for Layer1. - """ - batch_dict = {} - key_list = [] - for key in self.keys: - if isinstance(key, tuple): - hash_key, range_key = key - else: - hash_key = key - range_key = None - k = self.table.layer2.build_key_from_values(self.table.schema, - hash_key, range_key) - key_list.append(k) - batch_dict['Keys'] = key_list - if self.attributes_to_get: - batch_dict['AttributesToGet'] = self.attributes_to_get - if self.consistent_read: - batch_dict['ConsistentRead'] = True - else: - batch_dict['ConsistentRead'] = False - return batch_dict - - -class BatchWrite(object): - """ - Used to construct a BatchWrite request. Each BatchWrite object - represents a collection of PutItem and DeleteItem requests for - a single Table. - - :ivar table: The Table object from which the item is retrieved. - - :ivar puts: A list of :class:`boto.dynamodb.item.Item` objects - that you want to write to DynamoDB. - - :ivar deletes: A list of scalar or tuple values. Each element in the - list represents one Item to delete. If the schema for the - table has both a HashKey and a RangeKey, each element in the - list should be a tuple consisting of (hash_key, range_key). If - the schema for the table contains only a HashKey, each element - in the list should be a scalar value of the appropriate type - for the table schema. - """ - - def __init__(self, table, puts=None, deletes=None): - self.table = table - self.puts = puts or [] - self.deletes = deletes or [] - - def to_dict(self): - """ - Convert the Batch object into the format required for Layer1. - """ - op_list = [] - for item in self.puts: - d = {'Item': self.table.layer2.dynamize_item(item)} - d = {'PutRequest': d} - op_list.append(d) - for key in self.deletes: - if isinstance(key, tuple): - hash_key, range_key = key - else: - hash_key = key - range_key = None - k = self.table.layer2.build_key_from_values(self.table.schema, - hash_key, range_key) - d = {'Key': k} - op_list.append({'DeleteRequest': d}) - return (self.table.name, op_list) - - -class BatchList(list): - """ - A subclass of a list object that contains a collection of - :class:`boto.dynamodb.batch.Batch` objects. - """ - - def __init__(self, layer2): - list.__init__(self) - self.unprocessed = None - self.layer2 = layer2 - - def add_batch(self, table, keys, attributes_to_get=None, - consistent_read=False): - """ - Add a Batch to this BatchList. - - :type table: :class:`boto.dynamodb.table.Table` - :param table: The Table object in which the items are contained. - - :type keys: list - :param keys: A list of scalar or tuple values. Each element in the - list represents one Item to retrieve. If the schema for the - table has both a HashKey and a RangeKey, each element in the - list should be a tuple consisting of (hash_key, range_key). If - the schema for the table contains only a HashKey, each element - in the list should be a scalar value of the appropriate type - for the table schema. NOTE: The maximum number of items that - can be retrieved for a single operation is 100. Also, the - number of items retrieved is constrained by a 1 MB size limit. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - """ - self.append(Batch(table, keys, attributes_to_get, consistent_read)) - - def resubmit(self): - """ - Resubmit the batch to get the next result set. The request object is - rebuild from scratch meaning that all batch added between ``submit`` - and ``resubmit`` will be lost. - - Note: This method is experimental and subject to changes in future releases - """ - del self[:] - - if not self.unprocessed: - return None - - for table_name, table_req in six.iteritems(self.unprocessed): - table_keys = table_req['Keys'] - table = self.layer2.get_table(table_name) - - keys = [] - for key in table_keys: - h = key['HashKeyElement'] - r = None - if 'RangeKeyElement' in key: - r = key['RangeKeyElement'] - keys.append((h, r)) - - attributes_to_get = None - if 'AttributesToGet' in table_req: - attributes_to_get = table_req['AttributesToGet'] - - self.add_batch(table, keys, attributes_to_get=attributes_to_get) - - return self.submit() - - def submit(self): - res = self.layer2.batch_get_item(self) - if 'UnprocessedKeys' in res: - self.unprocessed = res['UnprocessedKeys'] - return res - - def to_dict(self): - """ - Convert a BatchList object into format required for Layer1. - """ - d = {} - for batch in self: - b = batch.to_dict() - if b['Keys']: - d[batch.table.name] = b - return d - - -class BatchWriteList(list): - """ - A subclass of a list object that contains a collection of - :class:`boto.dynamodb.batch.BatchWrite` objects. - """ - - def __init__(self, layer2): - list.__init__(self) - self.layer2 = layer2 - - def add_batch(self, table, puts=None, deletes=None): - """ - Add a BatchWrite to this BatchWriteList. - - :type table: :class:`boto.dynamodb.table.Table` - :param table: The Table object in which the items are contained. - - :type puts: list of :class:`boto.dynamodb.item.Item` objects - :param puts: A list of items that you want to write to DynamoDB. - - :type deletes: A list - :param deletes: A list of scalar or tuple values. Each element - in the list represents one Item to delete. If the schema - for the table has both a HashKey and a RangeKey, each - element in the list should be a tuple consisting of - (hash_key, range_key). If the schema for the table - contains only a HashKey, each element in the list should - be a scalar value of the appropriate type for the table - schema. - """ - self.append(BatchWrite(table, puts, deletes)) - - def submit(self): - return self.layer2.batch_write_item(self) - - def to_dict(self): - """ - Convert a BatchWriteList object into format required for Layer1. - """ - d = {} - for batch in self: - table_name, batch_dict = batch.to_dict() - d[table_name] = batch_dict - return d diff --git a/awx/lib/site-packages/boto/dynamodb/condition.py b/awx/lib/site-packages/boto/dynamodb/condition.py deleted file mode 100644 index f5db538c29..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/condition.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.dynamodb.types import dynamize_value - - -class Condition(object): - """ - Base class for conditions. Doesn't do a darn thing but allows - is to test if something is a Condition instance or not. - """ - - def __eq__(self, other): - if isinstance(other, Condition): - return self.to_dict() == other.to_dict() - -class ConditionNoArgs(Condition): - """ - Abstract class for Conditions that require no arguments, such - as NULL or NOT_NULL. - """ - - def __repr__(self): - return '%s' % self.__class__.__name__ - - def to_dict(self): - return {'ComparisonOperator': self.__class__.__name__} - - -class ConditionOneArg(Condition): - """ - Abstract class for Conditions that require a single argument - such as EQ or NE. - """ - - def __init__(self, v1): - self.v1 = v1 - - def __repr__(self): - return '%s:%s' % (self.__class__.__name__, self.v1) - - def to_dict(self): - return {'AttributeValueList': [dynamize_value(self.v1)], - 'ComparisonOperator': self.__class__.__name__} - - -class ConditionTwoArgs(Condition): - """ - Abstract class for Conditions that require two arguments. - The only example of this currently is BETWEEN. - """ - - def __init__(self, v1, v2): - self.v1 = v1 - self.v2 = v2 - - def __repr__(self): - return '%s(%s, %s)' % (self.__class__.__name__, self.v1, self.v2) - - def to_dict(self): - values = (self.v1, self.v2) - return {'AttributeValueList': [dynamize_value(v) for v in values], - 'ComparisonOperator': self.__class__.__name__} - - -class ConditionSeveralArgs(Condition): - """ - Abstract class for conditions that require several argument (ex: IN). - """ - - def __init__(self, values): - self.values = values - - def __repr__(self): - return '{0}({1})'.format(self.__class__.__name__, - ', '.join(self.values)) - - def to_dict(self): - return {'AttributeValueList': [dynamize_value(v) for v in self.values], - 'ComparisonOperator': self.__class__.__name__} - - -class EQ(ConditionOneArg): - - pass - - -class NE(ConditionOneArg): - - pass - - -class LE(ConditionOneArg): - - pass - - -class LT(ConditionOneArg): - - pass - - -class GE(ConditionOneArg): - - pass - - -class GT(ConditionOneArg): - - pass - - -class NULL(ConditionNoArgs): - - pass - - -class NOT_NULL(ConditionNoArgs): - - pass - - -class CONTAINS(ConditionOneArg): - - pass - - -class NOT_CONTAINS(ConditionOneArg): - - pass - - -class BEGINS_WITH(ConditionOneArg): - - pass - - -class IN(ConditionSeveralArgs): - - pass - - -class BEGINS_WITH(ConditionOneArg): - - pass - - -class BETWEEN(ConditionTwoArgs): - - pass diff --git a/awx/lib/site-packages/boto/dynamodb/exceptions.py b/awx/lib/site-packages/boto/dynamodb/exceptions.py deleted file mode 100644 index 12be2d72b5..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/exceptions.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -Exceptions that are specific to the dynamodb module. -""" -from boto.exception import BotoServerError, BotoClientError -from boto.exception import DynamoDBResponseError - - -class DynamoDBExpiredTokenError(BotoServerError): - """ - Raised when a DynamoDB security token expires. This is generally boto's - (or the user's) notice to renew their DynamoDB security tokens. - """ - pass - - -class DynamoDBKeyNotFoundError(BotoClientError): - """ - Raised when attempting to retrieve or interact with an item whose key - can't be found. - """ - pass - - -class DynamoDBItemError(BotoClientError): - """ - Raised when invalid parameters are passed when creating a - new Item in DynamoDB. - """ - pass - - -class DynamoDBNumberError(BotoClientError): - """ - Raised in the event of incompatible numeric type casting. - """ - pass - - -class DynamoDBConditionalCheckFailedError(DynamoDBResponseError): - """ - Raised when a ConditionalCheckFailedException response is received. - This happens when a conditional check, expressed via the expected_value - paramenter, fails. - """ - pass - - -class DynamoDBValidationError(DynamoDBResponseError): - """ - Raised when a ValidationException response is received. This happens - when one or more required parameter values are missing, or if the item - has exceeded the 64Kb size limit. - """ - pass - - -class DynamoDBThroughputExceededError(DynamoDBResponseError): - """ - Raised when the provisioned throughput has been exceeded. - Normally, when provisioned throughput is exceeded the operation - is retried. If the retries are exhausted then this exception - will be raised. - """ - pass diff --git a/awx/lib/site-packages/boto/dynamodb/item.py b/awx/lib/site-packages/boto/dynamodb/item.py deleted file mode 100644 index a47f22bf0e..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/item.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.dynamodb.exceptions import DynamoDBItemError - - -class Item(dict): - """ - An item in Amazon DynamoDB. - - :ivar hash_key: The HashKey of this item. - :ivar range_key: The RangeKey of this item or None if no RangeKey - is defined. - :ivar hash_key_name: The name of the HashKey associated with this item. - :ivar range_key_name: The name of the RangeKey associated with this item. - :ivar table: The Table this item belongs to. - """ - - def __init__(self, table, hash_key=None, range_key=None, attrs=None): - self.table = table - self._updates = None - self._hash_key_name = self.table.schema.hash_key_name - self._range_key_name = self.table.schema.range_key_name - if attrs is None: - attrs = {} - if hash_key is None: - hash_key = attrs.get(self._hash_key_name, None) - self[self._hash_key_name] = hash_key - if self._range_key_name: - if range_key is None: - range_key = attrs.get(self._range_key_name, None) - self[self._range_key_name] = range_key - self._updates = {} - for key, value in attrs.items(): - if key != self._hash_key_name and key != self._range_key_name: - self[key] = value - self.consumed_units = 0 - - @property - def hash_key(self): - return self[self._hash_key_name] - - @property - def range_key(self): - return self.get(self._range_key_name) - - @property - def hash_key_name(self): - return self._hash_key_name - - @property - def range_key_name(self): - return self._range_key_name - - def add_attribute(self, attr_name, attr_value): - """ - Queue the addition of an attribute to an item in DynamoDB. - This will eventually result in an UpdateItem request being issued - with an update action of ADD when the save method is called. - - :type attr_name: str - :param attr_name: Name of the attribute you want to alter. - - :type attr_value: int|long|float|set - :param attr_value: Value which is to be added to the attribute. - """ - self._updates[attr_name] = ("ADD", attr_value) - - def delete_attribute(self, attr_name, attr_value=None): - """ - Queue the deletion of an attribute from an item in DynamoDB. - This call will result in a UpdateItem request being issued - with update action of DELETE when the save method is called. - - :type attr_name: str - :param attr_name: Name of the attribute you want to alter. - - :type attr_value: set - :param attr_value: A set of values to be removed from the attribute. - This parameter is optional. If None, the whole attribute is - removed from the item. - """ - self._updates[attr_name] = ("DELETE", attr_value) - - def put_attribute(self, attr_name, attr_value): - """ - Queue the putting of an attribute to an item in DynamoDB. - This call will result in an UpdateItem request being issued - with the update action of PUT when the save method is called. - - :type attr_name: str - :param attr_name: Name of the attribute you want to alter. - - :type attr_value: int|long|float|str|set - :param attr_value: New value of the attribute. - """ - self._updates[attr_name] = ("PUT", attr_value) - - def save(self, expected_value=None, return_values=None): - """ - Commits pending updates to Amazon DynamoDB. - - :type expected_value: dict - :param expected_value: A dictionary of name/value pairs that - you expect. This dictionary should have name/value pairs - where the name is the name of the attribute and the value is - either the value you are expecting or False if you expect - the attribute not to exist. - - :type return_values: str - :param return_values: Controls the return of attribute name/value pairs - before they were updated. Possible values are: None, 'ALL_OLD', - 'UPDATED_OLD', 'ALL_NEW' or 'UPDATED_NEW'. If 'ALL_OLD' is - specified and the item is overwritten, the content of the old item - is returned. If 'ALL_NEW' is specified, then all the attributes of - the new version of the item are returned. If 'UPDATED_NEW' is - specified, the new versions of only the updated attributes are - returned. - """ - return self.table.layer2.update_item(self, expected_value, - return_values) - - def delete(self, expected_value=None, return_values=None): - """ - Delete the item from DynamoDB. - - :type expected_value: dict - :param expected_value: A dictionary of name/value pairs that - you expect. This dictionary should have name/value pairs - where the name is the name of the attribute and the value - is either the value you are expecting or False if you expect - the attribute not to exist. - - :type return_values: str - :param return_values: Controls the return of attribute - name-value pairs before then were changed. Possible - values are: None or 'ALL_OLD'. If 'ALL_OLD' is - specified and the item is overwritten, the content - of the old item is returned. - """ - return self.table.layer2.delete_item(self, expected_value, - return_values) - - def put(self, expected_value=None, return_values=None): - """ - Store a new item or completely replace an existing item - in Amazon DynamoDB. - - :type expected_value: dict - :param expected_value: A dictionary of name/value pairs that - you expect. This dictionary should have name/value pairs - where the name is the name of the attribute and the value - is either the value you are expecting or False if you expect - the attribute not to exist. - - :type return_values: str - :param return_values: Controls the return of attribute - name-value pairs before then were changed. Possible - values are: None or 'ALL_OLD'. If 'ALL_OLD' is - specified and the item is overwritten, the content - of the old item is returned. - """ - return self.table.layer2.put_item(self, expected_value, return_values) - - def __setitem__(self, key, value): - """Overrwrite the setter to instead update the _updates - method so this can act like a normal dict""" - if self._updates is not None: - self.put_attribute(key, value) - dict.__setitem__(self, key, value) - - def __delitem__(self, key): - """Remove this key from the items""" - if self._updates is not None: - self.delete_attribute(key) - dict.__delitem__(self, key) - - # Allow this item to still be pickled - def __getstate__(self): - return self.__dict__ - def __setstate__(self, d): - self.__dict__.update(d) diff --git a/awx/lib/site-packages/boto/dynamodb/layer1.py b/awx/lib/site-packages/boto/dynamodb/layer1.py deleted file mode 100644 index 0984f71ab4..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/layer1.py +++ /dev/null @@ -1,577 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import time -from binascii import crc32 - -import boto -from boto.connection import AWSAuthConnection -from boto.exception import DynamoDBResponseError -from boto.provider import Provider -from boto.dynamodb import exceptions as dynamodb_exceptions -from boto.compat import json - - -class Layer1(AWSAuthConnection): - """ - This is the lowest-level interface to DynamoDB. Methods at this - layer map directly to API requests and parameters to the methods - are either simple, scalar values or they are the Python equivalent - of the JSON input as defined in the DynamoDB Developer's Guide. - All responses are direct decoding of the JSON response bodies to - Python data structures via the json or simplejson modules. - - :ivar throughput_exceeded_events: An integer variable that - keeps a running total of the number of ThroughputExceeded - responses this connection has received from Amazon DynamoDB. - """ - - DefaultRegionName = 'us-east-1' - """The default region name for DynamoDB API.""" - - ServiceName = 'DynamoDB' - """The name of the Service""" - - Version = '20111205' - """DynamoDB API version.""" - - ThruputError = "ProvisionedThroughputExceededException" - """The error response returned when provisioned throughput is exceeded""" - - SessionExpiredError = 'com.amazon.coral.service#ExpiredTokenException' - """The error response returned when session token has expired""" - - ConditionalCheckFailedError = 'ConditionalCheckFailedException' - """The error response returned when a conditional check fails""" - - ValidationError = 'ValidationException' - """The error response returned when an item is invalid in some way""" - - ResponseError = DynamoDBResponseError - - NumberRetries = 10 - """The number of times an error is retried.""" - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - debug=0, security_token=None, region=None, - validate_certs=True, validate_checksums=True, profile_name=None): - if not region: - region_name = boto.config.get('DynamoDB', 'region', - self.DefaultRegionName) - for reg in boto.dynamodb.regions(): - if reg.name == region_name: - region = reg - break - - self.region = region - super(Layer1, self).__init__(self.region.endpoint, - aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - debug=debug, security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - self.throughput_exceeded_events = 0 - self._validate_checksums = boto.config.getbool( - 'DynamoDB', 'validate_checksums', validate_checksums) - - def _get_session_token(self): - self.provider = Provider(self._provider_type) - self._auth_handler.update_provider(self.provider) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def make_request(self, action, body='', object_hook=None): - """ - :raises: ``DynamoDBExpiredTokenError`` if the security token expires. - """ - headers = {'X-Amz-Target': '%s_%s.%s' % (self.ServiceName, - self.Version, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.0', - 'Content-Length': str(len(body))} - http_request = self.build_base_http_request('POST', '/', '/', - {}, headers, body, None) - start = time.time() - response = self._mexe(http_request, sender=None, - override_num_retries=self.NumberRetries, - retry_handler=self._retry_handler) - elapsed = (time.time() - start) * 1000 - request_id = response.getheader('x-amzn-RequestId') - boto.log.debug('RequestId: %s' % request_id) - boto.perflog.debug('%s: id=%s time=%sms', - headers['X-Amz-Target'], request_id, int(elapsed)) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - return json.loads(response_body, object_hook=object_hook) - - def _retry_handler(self, response, i, next_sleep): - status = None - if response.status == 400: - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - data = json.loads(response_body) - if self.ThruputError in data.get('__type'): - self.throughput_exceeded_events += 1 - msg = "%s, retry attempt %s" % (self.ThruputError, i) - next_sleep = self._exponential_time(i) - i += 1 - status = (msg, i, next_sleep) - if i == self.NumberRetries: - # If this was our last retry attempt, raise - # a specific error saying that the throughput - # was exceeded. - raise dynamodb_exceptions.DynamoDBThroughputExceededError( - response.status, response.reason, data) - elif self.SessionExpiredError in data.get('__type'): - msg = 'Renewing Session Token' - self._get_session_token() - status = (msg, i + self.num_retries - 1, 0) - elif self.ConditionalCheckFailedError in data.get('__type'): - raise dynamodb_exceptions.DynamoDBConditionalCheckFailedError( - response.status, response.reason, data) - elif self.ValidationError in data.get('__type'): - raise dynamodb_exceptions.DynamoDBValidationError( - response.status, response.reason, data) - else: - raise self.ResponseError(response.status, response.reason, - data) - expected_crc32 = response.getheader('x-amz-crc32') - if self._validate_checksums and expected_crc32 is not None: - boto.log.debug('Validating crc32 checksum for body: %s', - response.read().decode('utf-8')) - actual_crc32 = crc32(response.read()) & 0xffffffff - expected_crc32 = int(expected_crc32) - if actual_crc32 != expected_crc32: - msg = ("The calculated checksum %s did not match the expected " - "checksum %s" % (actual_crc32, expected_crc32)) - status = (msg, i + 1, self._exponential_time(i)) - return status - - def _exponential_time(self, i): - if i == 0: - next_sleep = 0 - else: - next_sleep = min(0.05 * (2 ** i), - boto.config.get('Boto', 'max_retry_delay', 60)) - return next_sleep - - def list_tables(self, limit=None, start_table=None): - """ - Returns a dictionary of results. The dictionary contains - a **TableNames** key whose value is a list of the table names. - The dictionary could also contain a **LastEvaluatedTableName** - key whose value would be the last table name returned if - the complete list of table names was not returned. This - value would then be passed as the ``start_table`` parameter on - a subsequent call to this method. - - :type limit: int - :param limit: The maximum number of tables to return. - - :type start_table: str - :param start_table: The name of the table that starts the - list. If you ran a previous list_tables and not - all results were returned, the response dict would - include a LastEvaluatedTableName attribute. Use - that value here to continue the listing. - """ - data = {} - if limit: - data['Limit'] = limit - if start_table: - data['ExclusiveStartTableName'] = start_table - json_input = json.dumps(data) - return self.make_request('ListTables', json_input) - - def describe_table(self, table_name): - """ - Returns information about the table including current - state of the table, primary key schema and when the - table was created. - - :type table_name: str - :param table_name: The name of the table to describe. - """ - data = {'TableName': table_name} - json_input = json.dumps(data) - return self.make_request('DescribeTable', json_input) - - def create_table(self, table_name, schema, provisioned_throughput): - """ - Add a new table to your account. The table name must be unique - among those associated with the account issuing the request. - This request triggers an asynchronous workflow to begin creating - the table. When the workflow is complete, the state of the - table will be ACTIVE. - - :type table_name: str - :param table_name: The name of the table to create. - - :type schema: dict - :param schema: A Python version of the KeySchema data structure - as defined by DynamoDB - - :type provisioned_throughput: dict - :param provisioned_throughput: A Python version of the - ProvisionedThroughput data structure defined by - DynamoDB. - """ - data = {'TableName': table_name, - 'KeySchema': schema, - 'ProvisionedThroughput': provisioned_throughput} - json_input = json.dumps(data) - response_dict = self.make_request('CreateTable', json_input) - return response_dict - - def update_table(self, table_name, provisioned_throughput): - """ - Updates the provisioned throughput for a given table. - - :type table_name: str - :param table_name: The name of the table to update. - - :type provisioned_throughput: dict - :param provisioned_throughput: A Python version of the - ProvisionedThroughput data structure defined by - DynamoDB. - """ - data = {'TableName': table_name, - 'ProvisionedThroughput': provisioned_throughput} - json_input = json.dumps(data) - return self.make_request('UpdateTable', json_input) - - def delete_table(self, table_name): - """ - Deletes the table and all of it's data. After this request - the table will be in the DELETING state until DynamoDB - completes the delete operation. - - :type table_name: str - :param table_name: The name of the table to delete. - """ - data = {'TableName': table_name} - json_input = json.dumps(data) - return self.make_request('DeleteTable', json_input) - - def get_item(self, table_name, key, attributes_to_get=None, - consistent_read=False, object_hook=None): - """ - Return a set of attributes for an item that matches - the supplied key. - - :type table_name: str - :param table_name: The name of the table containing the item. - - :type key: dict - :param key: A Python version of the Key data structure - defined by DynamoDB. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type consistent_read: bool - :param consistent_read: If True, a consistent read - request is issued. Otherwise, an eventually consistent - request is issued. - """ - data = {'TableName': table_name, - 'Key': key} - if attributes_to_get: - data['AttributesToGet'] = attributes_to_get - if consistent_read: - data['ConsistentRead'] = True - json_input = json.dumps(data) - response = self.make_request('GetItem', json_input, - object_hook=object_hook) - if 'Item' not in response: - raise dynamodb_exceptions.DynamoDBKeyNotFoundError( - "Key does not exist." - ) - return response - - def batch_get_item(self, request_items, object_hook=None): - """ - Return a set of attributes for a multiple items in - multiple tables using their primary keys. - - :type request_items: dict - :param request_items: A Python version of the RequestItems - data structure defined by DynamoDB. - """ - # If the list is empty, return empty response - if not request_items: - return {} - data = {'RequestItems': request_items} - json_input = json.dumps(data) - return self.make_request('BatchGetItem', json_input, - object_hook=object_hook) - - def batch_write_item(self, request_items, object_hook=None): - """ - This operation enables you to put or delete several items - across multiple tables in a single API call. - - :type request_items: dict - :param request_items: A Python version of the RequestItems - data structure defined by DynamoDB. - """ - data = {'RequestItems': request_items} - json_input = json.dumps(data) - return self.make_request('BatchWriteItem', json_input, - object_hook=object_hook) - - def put_item(self, table_name, item, - expected=None, return_values=None, - object_hook=None): - """ - Create a new item or replace an old item with a new - item (including all attributes). If an item already - exists in the specified table with the same primary - key, the new item will completely replace the old item. - You can perform a conditional put by specifying an - expected rule. - - :type table_name: str - :param table_name: The name of the table in which to put the item. - - :type item: dict - :param item: A Python version of the Item data structure - defined by DynamoDB. - - :type expected: dict - :param expected: A Python version of the Expected - data structure defined by DynamoDB. - - :type return_values: str - :param return_values: Controls the return of attribute - name-value pairs before then were changed. Possible - values are: None or 'ALL_OLD'. If 'ALL_OLD' is - specified and the item is overwritten, the content - of the old item is returned. - """ - data = {'TableName': table_name, - 'Item': item} - if expected: - data['Expected'] = expected - if return_values: - data['ReturnValues'] = return_values - json_input = json.dumps(data) - return self.make_request('PutItem', json_input, - object_hook=object_hook) - - def update_item(self, table_name, key, attribute_updates, - expected=None, return_values=None, - object_hook=None): - """ - Edits an existing item's attributes. You can perform a conditional - update (insert a new attribute name-value pair if it doesn't exist, - or replace an existing name-value pair if it has certain expected - attribute values). - - :type table_name: str - :param table_name: The name of the table. - - :type key: dict - :param key: A Python version of the Key data structure - defined by DynamoDB which identifies the item to be updated. - - :type attribute_updates: dict - :param attribute_updates: A Python version of the AttributeUpdates - data structure defined by DynamoDB. - - :type expected: dict - :param expected: A Python version of the Expected - data structure defined by DynamoDB. - - :type return_values: str - :param return_values: Controls the return of attribute - name-value pairs before then were changed. Possible - values are: None or 'ALL_OLD'. If 'ALL_OLD' is - specified and the item is overwritten, the content - of the old item is returned. - """ - data = {'TableName': table_name, - 'Key': key, - 'AttributeUpdates': attribute_updates} - if expected: - data['Expected'] = expected - if return_values: - data['ReturnValues'] = return_values - json_input = json.dumps(data) - return self.make_request('UpdateItem', json_input, - object_hook=object_hook) - - def delete_item(self, table_name, key, - expected=None, return_values=None, - object_hook=None): - """ - Delete an item and all of it's attributes by primary key. - You can perform a conditional delete by specifying an - expected rule. - - :type table_name: str - :param table_name: The name of the table containing the item. - - :type key: dict - :param key: A Python version of the Key data structure - defined by DynamoDB. - - :type expected: dict - :param expected: A Python version of the Expected - data structure defined by DynamoDB. - - :type return_values: str - :param return_values: Controls the return of attribute - name-value pairs before then were changed. Possible - values are: None or 'ALL_OLD'. If 'ALL_OLD' is - specified and the item is overwritten, the content - of the old item is returned. - """ - data = {'TableName': table_name, - 'Key': key} - if expected: - data['Expected'] = expected - if return_values: - data['ReturnValues'] = return_values - json_input = json.dumps(data) - return self.make_request('DeleteItem', json_input, - object_hook=object_hook) - - def query(self, table_name, hash_key_value, range_key_conditions=None, - attributes_to_get=None, limit=None, consistent_read=False, - scan_index_forward=True, exclusive_start_key=None, - object_hook=None, count=False): - """ - Perform a query of DynamoDB. This version is currently punting - and expecting you to provide a full and correct JSON body - which is passed as is to DynamoDB. - - :type table_name: str - :param table_name: The name of the table to query. - - :type hash_key_value: dict - :param key: A DynamoDB-style HashKeyValue. - - :type range_key_conditions: dict - :param range_key_conditions: A Python version of the - RangeKeyConditions data structure. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type limit: int - :param limit: The maximum number of items to return. - - :type count: bool - :param count: If True, Amazon DynamoDB returns a total - number of items for the Query operation, even if the - operation has no matching items for the assigned filter. - - :type consistent_read: bool - :param consistent_read: If True, a consistent read - request is issued. Otherwise, an eventually consistent - request is issued. - - :type scan_index_forward: bool - :param scan_index_forward: Specified forward or backward - traversal of the index. Default is forward (True). - - :type exclusive_start_key: list or tuple - :param exclusive_start_key: Primary key of the item from - which to continue an earlier query. This would be - provided as the LastEvaluatedKey in that query. - """ - data = {'TableName': table_name, - 'HashKeyValue': hash_key_value} - if range_key_conditions: - data['RangeKeyCondition'] = range_key_conditions - if attributes_to_get: - data['AttributesToGet'] = attributes_to_get - if limit: - data['Limit'] = limit - if count: - data['Count'] = True - if consistent_read: - data['ConsistentRead'] = True - if scan_index_forward: - data['ScanIndexForward'] = True - else: - data['ScanIndexForward'] = False - if exclusive_start_key: - data['ExclusiveStartKey'] = exclusive_start_key - json_input = json.dumps(data) - return self.make_request('Query', json_input, - object_hook=object_hook) - - def scan(self, table_name, scan_filter=None, - attributes_to_get=None, limit=None, - exclusive_start_key=None, object_hook=None, count=False): - """ - Perform a scan of DynamoDB. This version is currently punting - and expecting you to provide a full and correct JSON body - which is passed as is to DynamoDB. - - :type table_name: str - :param table_name: The name of the table to scan. - - :type scan_filter: dict - :param scan_filter: A Python version of the - ScanFilter data structure. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type limit: int - :param limit: The maximum number of items to evaluate. - - :type count: bool - :param count: If True, Amazon DynamoDB returns a total - number of items for the Scan operation, even if the - operation has no matching items for the assigned filter. - - :type exclusive_start_key: list or tuple - :param exclusive_start_key: Primary key of the item from - which to continue an earlier query. This would be - provided as the LastEvaluatedKey in that query. - """ - data = {'TableName': table_name} - if scan_filter: - data['ScanFilter'] = scan_filter - if attributes_to_get: - data['AttributesToGet'] = attributes_to_get - if limit: - data['Limit'] = limit - if count: - data['Count'] = True - if exclusive_start_key: - data['ExclusiveStartKey'] = exclusive_start_key - json_input = json.dumps(data) - return self.make_request('Scan', json_input, object_hook=object_hook) diff --git a/awx/lib/site-packages/boto/dynamodb/layer2.py b/awx/lib/site-packages/boto/dynamodb/layer2.py deleted file mode 100644 index fa0e545f7d..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/layer2.py +++ /dev/null @@ -1,806 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.dynamodb.layer1 import Layer1 -from boto.dynamodb.table import Table -from boto.dynamodb.schema import Schema -from boto.dynamodb.item import Item -from boto.dynamodb.batch import BatchList, BatchWriteList -from boto.dynamodb.types import get_dynamodb_type, Dynamizer, \ - LossyFloatDynamizer - - -class TableGenerator(object): - """ - This is an object that wraps up the table_generator function. - The only real reason to have this is that we want to be able - to accumulate and return the ConsumedCapacityUnits element that - is part of each response. - - :ivar last_evaluated_key: A sequence representing the key(s) - of the item last evaluated, or None if no additional - results are available. - - :ivar remaining: The remaining quantity of results requested. - - :ivar table: The table to which the call was made. - """ - - def __init__(self, table, callable, remaining, item_class, kwargs): - self.table = table - self.callable = callable - self.remaining = -1 if remaining is None else remaining - self.item_class = item_class - self.kwargs = kwargs - self._consumed_units = 0.0 - self.last_evaluated_key = None - self._count = 0 - self._scanned_count = 0 - self._response = None - - @property - def count(self): - """ - The total number of items retrieved thus far. This value changes with - iteration and even when issuing a call with count=True, it is necessary - to complete the iteration to assert an accurate count value. - """ - self.response - return self._count - - @property - def scanned_count(self): - """ - As above, but representing the total number of items scanned by - DynamoDB, without regard to any filters. - """ - self.response - return self._scanned_count - - @property - def consumed_units(self): - """ - Returns a float representing the ConsumedCapacityUnits accumulated. - """ - self.response - return self._consumed_units - - @property - def response(self): - """ - The current response to the call from DynamoDB. - """ - return self.next_response() if self._response is None else self._response - - def next_response(self): - """ - Issue a call and return the result. You can invoke this method - while iterating over the TableGenerator in order to skip to the - next "page" of results. - """ - # preserve any existing limit in case the user alters self.remaining - limit = self.kwargs.get('limit') - if (self.remaining > 0 and (limit is None or limit > self.remaining)): - self.kwargs['limit'] = self.remaining - self._response = self.callable(**self.kwargs) - self.kwargs['limit'] = limit - self._consumed_units += self._response.get('ConsumedCapacityUnits', 0.0) - self._count += self._response.get('Count', 0) - self._scanned_count += self._response.get('ScannedCount', 0) - # at the expense of a possibly gratuitous dynamize, ensure that - # early generator termination won't result in bad LEK values - if 'LastEvaluatedKey' in self._response: - lek = self._response['LastEvaluatedKey'] - esk = self.table.layer2.dynamize_last_evaluated_key(lek) - self.kwargs['exclusive_start_key'] = esk - lektuple = (lek['HashKeyElement'],) - if 'RangeKeyElement' in lek: - lektuple += (lek['RangeKeyElement'],) - self.last_evaluated_key = lektuple - else: - self.last_evaluated_key = None - return self._response - - def __iter__(self): - while self.remaining != 0: - response = self.response - for item in response.get('Items', []): - self.remaining -= 1 - yield self.item_class(self.table, attrs=item) - if self.remaining == 0: - break - if response is not self._response: - break - else: - if self.last_evaluated_key is not None: - self.next_response() - continue - break - if response is not self._response: - continue - break - - -class Layer2(object): - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - debug=0, security_token=None, region=None, - validate_certs=True, dynamizer=LossyFloatDynamizer, - profile_name=None): - self.layer1 = Layer1(aws_access_key_id, aws_secret_access_key, - is_secure, port, proxy, proxy_port, - debug, security_token, region, - validate_certs=validate_certs, - profile_name=profile_name) - self.dynamizer = dynamizer() - - def use_decimals(self): - """ - Use the ``decimal.Decimal`` type for encoding/decoding numeric types. - - By default, ints/floats are used to represent numeric types - ('N', 'NS') received from DynamoDB. Using the ``Decimal`` - type is recommended to prevent loss of precision. - - """ - # Eventually this should be made the default dynamizer. - self.dynamizer = Dynamizer() - - def dynamize_attribute_updates(self, pending_updates): - """ - Convert a set of pending item updates into the structure - required by Layer1. - """ - d = {} - for attr_name in pending_updates: - action, value = pending_updates[attr_name] - if value is None: - # DELETE without an attribute value - d[attr_name] = {"Action": action} - else: - d[attr_name] = {"Action": action, - "Value": self.dynamizer.encode(value)} - return d - - def dynamize_item(self, item): - d = {} - for attr_name in item: - d[attr_name] = self.dynamizer.encode(item[attr_name]) - return d - - def dynamize_range_key_condition(self, range_key_condition): - """ - Convert a layer2 range_key_condition parameter into the - structure required by Layer1. - """ - return range_key_condition.to_dict() - - def dynamize_scan_filter(self, scan_filter): - """ - Convert a layer2 scan_filter parameter into the - structure required by Layer1. - """ - d = None - if scan_filter: - d = {} - for attr_name in scan_filter: - condition = scan_filter[attr_name] - d[attr_name] = condition.to_dict() - return d - - def dynamize_expected_value(self, expected_value): - """ - Convert an expected_value parameter into the data structure - required for Layer1. - """ - d = None - if expected_value: - d = {} - for attr_name in expected_value: - attr_value = expected_value[attr_name] - if attr_value is True: - attr_value = {'Exists': True} - elif attr_value is False: - attr_value = {'Exists': False} - else: - val = self.dynamizer.encode(expected_value[attr_name]) - attr_value = {'Value': val} - d[attr_name] = attr_value - return d - - def dynamize_last_evaluated_key(self, last_evaluated_key): - """ - Convert a last_evaluated_key parameter into the data structure - required for Layer1. - """ - d = None - if last_evaluated_key: - hash_key = last_evaluated_key['HashKeyElement'] - d = {'HashKeyElement': self.dynamizer.encode(hash_key)} - if 'RangeKeyElement' in last_evaluated_key: - range_key = last_evaluated_key['RangeKeyElement'] - d['RangeKeyElement'] = self.dynamizer.encode(range_key) - return d - - def build_key_from_values(self, schema, hash_key, range_key=None): - """ - Build a Key structure to be used for accessing items - in Amazon DynamoDB. This method takes the supplied hash_key - and optional range_key and validates them against the - schema. If there is a mismatch, a TypeError is raised. - Otherwise, a Python dict version of a Amazon DynamoDB Key - data structure is returned. - - :type hash_key: int|float|str|unicode|Binary - :param hash_key: The hash key of the item you are looking for. - The type of the hash key should match the type defined in - the schema. - - :type range_key: int|float|str|unicode|Binary - :param range_key: The range key of the item your are looking for. - This should be supplied only if the schema requires a - range key. The type of the range key should match the - type defined in the schema. - """ - dynamodb_key = {} - dynamodb_value = self.dynamizer.encode(hash_key) - if list(dynamodb_value.keys())[0] != schema.hash_key_type: - msg = 'Hashkey must be of type: %s' % schema.hash_key_type - raise TypeError(msg) - dynamodb_key['HashKeyElement'] = dynamodb_value - if range_key is not None: - dynamodb_value = self.dynamizer.encode(range_key) - if list(dynamodb_value.keys())[0] != schema.range_key_type: - msg = 'RangeKey must be of type: %s' % schema.range_key_type - raise TypeError(msg) - dynamodb_key['RangeKeyElement'] = dynamodb_value - return dynamodb_key - - def new_batch_list(self): - """ - Return a new, empty :class:`boto.dynamodb.batch.BatchList` - object. - """ - return BatchList(self) - - def new_batch_write_list(self): - """ - Return a new, empty :class:`boto.dynamodb.batch.BatchWriteList` - object. - """ - return BatchWriteList(self) - - def list_tables(self, limit=None): - """ - Return a list of the names of all tables associated with the - current account and region. - - :type limit: int - :param limit: The maximum number of tables to return. - """ - tables = [] - start_table = None - while not limit or len(tables) < limit: - this_round_limit = None - if limit: - this_round_limit = limit - len(tables) - this_round_limit = min(this_round_limit, 100) - result = self.layer1.list_tables(limit=this_round_limit, start_table=start_table) - tables.extend(result.get('TableNames', [])) - start_table = result.get('LastEvaluatedTableName', None) - if not start_table: - break - return tables - - def describe_table(self, name): - """ - Retrieve information about an existing table. - - :type name: str - :param name: The name of the desired table. - - """ - return self.layer1.describe_table(name) - - def table_from_schema(self, name, schema): - """ - Create a Table object from a schema. - - This method will create a Table object without - making any API calls. If you know the name and schema - of the table, you can use this method instead of - ``get_table``. - - Example usage:: - - table = layer2.table_from_schema( - 'tablename', - Schema.create(hash_key=('foo', 'N'))) - - :type name: str - :param name: The name of the table. - - :type schema: :class:`boto.dynamodb.schema.Schema` - :param schema: The schema associated with the table. - - :rtype: :class:`boto.dynamodb.table.Table` - :return: A Table object representing the table. - - """ - return Table.create_from_schema(self, name, schema) - - def get_table(self, name): - """ - Retrieve the Table object for an existing table. - - :type name: str - :param name: The name of the desired table. - - :rtype: :class:`boto.dynamodb.table.Table` - :return: A Table object representing the table. - """ - response = self.layer1.describe_table(name) - return Table(self, response) - - lookup = get_table - - def create_table(self, name, schema, read_units, write_units): - """ - Create a new Amazon DynamoDB table. - - :type name: str - :param name: The name of the desired table. - - :type schema: :class:`boto.dynamodb.schema.Schema` - :param schema: The Schema object that defines the schema used - by this table. - - :type read_units: int - :param read_units: The value for ReadCapacityUnits. - - :type write_units: int - :param write_units: The value for WriteCapacityUnits. - - :rtype: :class:`boto.dynamodb.table.Table` - :return: A Table object representing the new Amazon DynamoDB table. - """ - response = self.layer1.create_table(name, schema.dict, - {'ReadCapacityUnits': read_units, - 'WriteCapacityUnits': write_units}) - return Table(self, response) - - def update_throughput(self, table, read_units, write_units): - """ - Update the ProvisionedThroughput for the Amazon DynamoDB Table. - - :type table: :class:`boto.dynamodb.table.Table` - :param table: The Table object whose throughput is being updated. - - :type read_units: int - :param read_units: The new value for ReadCapacityUnits. - - :type write_units: int - :param write_units: The new value for WriteCapacityUnits. - """ - response = self.layer1.update_table(table.name, - {'ReadCapacityUnits': read_units, - 'WriteCapacityUnits': write_units}) - table.update_from_response(response) - - def delete_table(self, table): - """ - Delete this table and all items in it. After calling this - the Table objects status attribute will be set to 'DELETING'. - - :type table: :class:`boto.dynamodb.table.Table` - :param table: The Table object that is being deleted. - """ - response = self.layer1.delete_table(table.name) - table.update_from_response(response) - - def create_schema(self, hash_key_name, hash_key_proto_value, - range_key_name=None, range_key_proto_value=None): - """ - Create a Schema object used when creating a Table. - - :type hash_key_name: str - :param hash_key_name: The name of the HashKey for the schema. - - :type hash_key_proto_value: int|long|float|str|unicode|Binary - :param hash_key_proto_value: A sample or prototype of the type - of value you want to use for the HashKey. Alternatively, - you can also just pass in the Python type (e.g. int, float, etc.). - - :type range_key_name: str - :param range_key_name: The name of the RangeKey for the schema. - This parameter is optional. - - :type range_key_proto_value: int|long|float|str|unicode|Binary - :param range_key_proto_value: A sample or prototype of the type - of value you want to use for the RangeKey. Alternatively, - you can also pass in the Python type (e.g. int, float, etc.) - This parameter is optional. - """ - hash_key = (hash_key_name, get_dynamodb_type(hash_key_proto_value)) - if range_key_name and range_key_proto_value is not None: - range_key = (range_key_name, - get_dynamodb_type(range_key_proto_value)) - else: - range_key = None - return Schema.create(hash_key, range_key) - - def get_item(self, table, hash_key, range_key=None, - attributes_to_get=None, consistent_read=False, - item_class=Item): - """ - Retrieve an existing item from the table. - - :type table: :class:`boto.dynamodb.table.Table` - :param table: The Table object from which the item is retrieved. - - :type hash_key: int|long|float|str|unicode|Binary - :param hash_key: The HashKey of the requested item. The - type of the value must match the type defined in the - schema for the table. - - :type range_key: int|long|float|str|unicode|Binary - :param range_key: The optional RangeKey of the requested item. - The type of the value must match the type defined in the - schema for the table. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type consistent_read: bool - :param consistent_read: If True, a consistent read - request is issued. Otherwise, an eventually consistent - request is issued. - - :type item_class: Class - :param item_class: Allows you to override the class used - to generate the items. This should be a subclass of - :class:`boto.dynamodb.item.Item` - """ - key = self.build_key_from_values(table.schema, hash_key, range_key) - response = self.layer1.get_item(table.name, key, - attributes_to_get, consistent_read, - object_hook=self.dynamizer.decode) - item = item_class(table, hash_key, range_key, response['Item']) - if 'ConsumedCapacityUnits' in response: - item.consumed_units = response['ConsumedCapacityUnits'] - return item - - def batch_get_item(self, batch_list): - """ - Return a set of attributes for a multiple items in - multiple tables using their primary keys. - - :type batch_list: :class:`boto.dynamodb.batch.BatchList` - :param batch_list: A BatchList object which consists of a - list of :class:`boto.dynamoddb.batch.Batch` objects. - Each Batch object contains the information about one - batch of objects that you wish to retrieve in this - request. - """ - request_items = batch_list.to_dict() - return self.layer1.batch_get_item(request_items, - object_hook=self.dynamizer.decode) - - def batch_write_item(self, batch_list): - """ - Performs multiple Puts and Deletes in one batch. - - :type batch_list: :class:`boto.dynamodb.batch.BatchWriteList` - :param batch_list: A BatchWriteList object which consists of a - list of :class:`boto.dynamoddb.batch.BatchWrite` objects. - Each Batch object contains the information about one - batch of objects that you wish to put or delete. - """ - request_items = batch_list.to_dict() - return self.layer1.batch_write_item(request_items, - object_hook=self.dynamizer.decode) - - def put_item(self, item, expected_value=None, return_values=None): - """ - Store a new item or completely replace an existing item - in Amazon DynamoDB. - - :type item: :class:`boto.dynamodb.item.Item` - :param item: The Item to write to Amazon DynamoDB. - - :type expected_value: dict - :param expected_value: A dictionary of name/value pairs that you expect. - This dictionary should have name/value pairs where the name - is the name of the attribute and the value is either the value - you are expecting or False if you expect the attribute not to - exist. - - :type return_values: str - :param return_values: Controls the return of attribute - name-value pairs before then were changed. Possible - values are: None or 'ALL_OLD'. If 'ALL_OLD' is - specified and the item is overwritten, the content - of the old item is returned. - """ - expected_value = self.dynamize_expected_value(expected_value) - response = self.layer1.put_item(item.table.name, - self.dynamize_item(item), - expected_value, return_values, - object_hook=self.dynamizer.decode) - if 'ConsumedCapacityUnits' in response: - item.consumed_units = response['ConsumedCapacityUnits'] - return response - - def update_item(self, item, expected_value=None, return_values=None): - """ - Commit pending item updates to Amazon DynamoDB. - - :type item: :class:`boto.dynamodb.item.Item` - :param item: The Item to update in Amazon DynamoDB. It is expected - that you would have called the add_attribute, put_attribute - and/or delete_attribute methods on this Item prior to calling - this method. Those queued changes are what will be updated. - - :type expected_value: dict - :param expected_value: A dictionary of name/value pairs that you - expect. This dictionary should have name/value pairs where the - name is the name of the attribute and the value is either the - value you are expecting or False if you expect the attribute - not to exist. - - :type return_values: str - :param return_values: Controls the return of attribute name/value pairs - before they were updated. Possible values are: None, 'ALL_OLD', - 'UPDATED_OLD', 'ALL_NEW' or 'UPDATED_NEW'. If 'ALL_OLD' is - specified and the item is overwritten, the content of the old item - is returned. If 'ALL_NEW' is specified, then all the attributes of - the new version of the item are returned. If 'UPDATED_NEW' is - specified, the new versions of only the updated attributes are - returned. - - """ - expected_value = self.dynamize_expected_value(expected_value) - key = self.build_key_from_values(item.table.schema, - item.hash_key, item.range_key) - attr_updates = self.dynamize_attribute_updates(item._updates) - - response = self.layer1.update_item(item.table.name, key, - attr_updates, - expected_value, return_values, - object_hook=self.dynamizer.decode) - item._updates.clear() - if 'ConsumedCapacityUnits' in response: - item.consumed_units = response['ConsumedCapacityUnits'] - return response - - def delete_item(self, item, expected_value=None, return_values=None): - """ - Delete the item from Amazon DynamoDB. - - :type item: :class:`boto.dynamodb.item.Item` - :param item: The Item to delete from Amazon DynamoDB. - - :type expected_value: dict - :param expected_value: A dictionary of name/value pairs that you expect. - This dictionary should have name/value pairs where the name - is the name of the attribute and the value is either the value - you are expecting or False if you expect the attribute not to - exist. - - :type return_values: str - :param return_values: Controls the return of attribute - name-value pairs before then were changed. Possible - values are: None or 'ALL_OLD'. If 'ALL_OLD' is - specified and the item is overwritten, the content - of the old item is returned. - """ - expected_value = self.dynamize_expected_value(expected_value) - key = self.build_key_from_values(item.table.schema, - item.hash_key, item.range_key) - return self.layer1.delete_item(item.table.name, key, - expected=expected_value, - return_values=return_values, - object_hook=self.dynamizer.decode) - - def query(self, table, hash_key, range_key_condition=None, - attributes_to_get=None, request_limit=None, - max_results=None, consistent_read=False, - scan_index_forward=True, exclusive_start_key=None, - item_class=Item, count=False): - """ - Perform a query on the table. - - :type table: :class:`boto.dynamodb.table.Table` - :param table: The Table object that is being queried. - - :type hash_key: int|long|float|str|unicode|Binary - :param hash_key: The HashKey of the requested item. The - type of the value must match the type defined in the - schema for the table. - - :type range_key_condition: :class:`boto.dynamodb.condition.Condition` - :param range_key_condition: A Condition object. - Condition object can be one of the following types: - - EQ|LE|LT|GE|GT|BEGINS_WITH|BETWEEN - - The only condition which expects or will accept two - values is 'BETWEEN', otherwise a single value should - be passed to the Condition constructor. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type request_limit: int - :param request_limit: The maximum number of items to retrieve - from Amazon DynamoDB on each request. You may want to set - a specific request_limit based on the provisioned throughput - of your table. The default behavior is to retrieve as many - results as possible per request. - - :type max_results: int - :param max_results: The maximum number of results that will - be retrieved from Amazon DynamoDB in total. For example, - if you only wanted to see the first 100 results from the - query, regardless of how many were actually available, you - could set max_results to 100 and the generator returned - from the query method will only yeild 100 results max. - - :type consistent_read: bool - :param consistent_read: If True, a consistent read - request is issued. Otherwise, an eventually consistent - request is issued. - - :type scan_index_forward: bool - :param scan_index_forward: Specified forward or backward - traversal of the index. Default is forward (True). - - :type count: bool - :param count: If True, Amazon DynamoDB returns a total - number of items for the Query operation, even if the - operation has no matching items for the assigned filter. - If count is True, the actual items are not returned and - the count is accessible as the ``count`` attribute of - the returned object. - - :type exclusive_start_key: list or tuple - :param exclusive_start_key: Primary key of the item from - which to continue an earlier query. This would be - provided as the LastEvaluatedKey in that query. - - :type item_class: Class - :param item_class: Allows you to override the class used - to generate the items. This should be a subclass of - :class:`boto.dynamodb.item.Item` - - :rtype: :class:`boto.dynamodb.layer2.TableGenerator` - """ - if range_key_condition: - rkc = self.dynamize_range_key_condition(range_key_condition) - else: - rkc = None - if exclusive_start_key: - esk = self.build_key_from_values(table.schema, - *exclusive_start_key) - else: - esk = None - kwargs = {'table_name': table.name, - 'hash_key_value': self.dynamizer.encode(hash_key), - 'range_key_conditions': rkc, - 'attributes_to_get': attributes_to_get, - 'limit': request_limit, - 'count': count, - 'consistent_read': consistent_read, - 'scan_index_forward': scan_index_forward, - 'exclusive_start_key': esk, - 'object_hook': self.dynamizer.decode} - return TableGenerator(table, self.layer1.query, - max_results, item_class, kwargs) - - def scan(self, table, scan_filter=None, - attributes_to_get=None, request_limit=None, max_results=None, - exclusive_start_key=None, item_class=Item, count=False): - """ - Perform a scan of DynamoDB. - - :type table: :class:`boto.dynamodb.table.Table` - :param table: The Table object that is being scanned. - - :type scan_filter: A dict - :param scan_filter: A dictionary where the key is the - attribute name and the value is a - :class:`boto.dynamodb.condition.Condition` object. - Valid Condition objects include: - - * EQ - equal (1) - * NE - not equal (1) - * LE - less than or equal (1) - * LT - less than (1) - * GE - greater than or equal (1) - * GT - greater than (1) - * NOT_NULL - attribute exists (0, use None) - * NULL - attribute does not exist (0, use None) - * CONTAINS - substring or value in list (1) - * NOT_CONTAINS - absence of substring or value in list (1) - * BEGINS_WITH - substring prefix (1) - * IN - exact match in list (N) - * BETWEEN - >= first value, <= second value (2) - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type request_limit: int - :param request_limit: The maximum number of items to retrieve - from Amazon DynamoDB on each request. You may want to set - a specific request_limit based on the provisioned throughput - of your table. The default behavior is to retrieve as many - results as possible per request. - - :type max_results: int - :param max_results: The maximum number of results that will - be retrieved from Amazon DynamoDB in total. For example, - if you only wanted to see the first 100 results from the - query, regardless of how many were actually available, you - could set max_results to 100 and the generator returned - from the query method will only yeild 100 results max. - - :type count: bool - :param count: If True, Amazon DynamoDB returns a total - number of items for the Scan operation, even if the - operation has no matching items for the assigned filter. - If count is True, the actual items are not returned and - the count is accessible as the ``count`` attribute of - the returned object. - - :type exclusive_start_key: list or tuple - :param exclusive_start_key: Primary key of the item from - which to continue an earlier query. This would be - provided as the LastEvaluatedKey in that query. - - :type item_class: Class - :param item_class: Allows you to override the class used - to generate the items. This should be a subclass of - :class:`boto.dynamodb.item.Item` - - :rtype: :class:`boto.dynamodb.layer2.TableGenerator` - """ - if exclusive_start_key: - esk = self.build_key_from_values(table.schema, - *exclusive_start_key) - else: - esk = None - kwargs = {'table_name': table.name, - 'scan_filter': self.dynamize_scan_filter(scan_filter), - 'attributes_to_get': attributes_to_get, - 'limit': request_limit, - 'count': count, - 'exclusive_start_key': esk, - 'object_hook': self.dynamizer.decode} - return TableGenerator(table, self.layer1.scan, - max_results, item_class, kwargs) diff --git a/awx/lib/site-packages/boto/dynamodb/schema.py b/awx/lib/site-packages/boto/dynamodb/schema.py deleted file mode 100644 index 4a697a827d..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/schema.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - -class Schema(object): - """ - Represents a DynamoDB schema. - - :ivar hash_key_name: The name of the hash key of the schema. - :ivar hash_key_type: The DynamoDB type specification for the - hash key of the schema. - :ivar range_key_name: The name of the range key of the schema - or None if no range key is defined. - :ivar range_key_type: The DynamoDB type specification for the - range key of the schema or None if no range key is defined. - :ivar dict: The underlying Python dictionary that needs to be - passed to Layer1 methods. - """ - - def __init__(self, schema_dict): - self._dict = schema_dict - - def __repr__(self): - if self.range_key_name: - s = 'Schema(%s:%s)' % (self.hash_key_name, self.range_key_name) - else: - s = 'Schema(%s)' % self.hash_key_name - return s - - @classmethod - def create(cls, hash_key, range_key=None): - """Convenience method to create a schema object. - - Example usage:: - - schema = Schema.create(hash_key=('foo', 'N')) - schema2 = Schema.create(hash_key=('foo', 'N'), - range_key=('bar', 'S')) - - :type hash_key: tuple - :param hash_key: A tuple of (hash_key_name, hash_key_type) - - :type range_key: tuple - :param hash_key: A tuple of (range_key_name, range_key_type) - - """ - reconstructed = { - 'HashKeyElement': { - 'AttributeName': hash_key[0], - 'AttributeType': hash_key[1], - } - } - if range_key is not None: - reconstructed['RangeKeyElement'] = { - 'AttributeName': range_key[0], - 'AttributeType': range_key[1], - } - instance = cls(None) - instance._dict = reconstructed - return instance - - @property - def dict(self): - return self._dict - - @property - def hash_key_name(self): - return self._dict['HashKeyElement']['AttributeName'] - - @property - def hash_key_type(self): - return self._dict['HashKeyElement']['AttributeType'] - - @property - def range_key_name(self): - name = None - if 'RangeKeyElement' in self._dict: - name = self._dict['RangeKeyElement']['AttributeName'] - return name - - @property - def range_key_type(self): - type = None - if 'RangeKeyElement' in self._dict: - type = self._dict['RangeKeyElement']['AttributeType'] - return type - - def __eq__(self, other): - return (self.hash_key_name == other.hash_key_name and - self.hash_key_type == other.hash_key_type and - self.range_key_name == other.range_key_name and - self.range_key_type == other.range_key_type) diff --git a/awx/lib/site-packages/boto/dynamodb/table.py b/awx/lib/site-packages/boto/dynamodb/table.py deleted file mode 100644 index 152b95d908..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/table.py +++ /dev/null @@ -1,546 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.dynamodb.batch import BatchList -from boto.dynamodb.schema import Schema -from boto.dynamodb.item import Item -from boto.dynamodb import exceptions as dynamodb_exceptions -import time - - -class TableBatchGenerator(object): - """ - A low-level generator used to page through results from - batch_get_item operations. - - :ivar consumed_units: An integer that holds the number of - ConsumedCapacityUnits accumulated thus far for this - generator. - """ - - def __init__(self, table, keys, attributes_to_get=None, - consistent_read=False): - self.table = table - self.keys = keys - self.consumed_units = 0 - self.attributes_to_get = attributes_to_get - self.consistent_read = consistent_read - - def _queue_unprocessed(self, res): - if u'UnprocessedKeys' not in res: - return - if self.table.name not in res[u'UnprocessedKeys']: - return - - keys = res[u'UnprocessedKeys'][self.table.name][u'Keys'] - - for key in keys: - h = key[u'HashKeyElement'] - r = key[u'RangeKeyElement'] if u'RangeKeyElement' in key else None - self.keys.append((h, r)) - - def __iter__(self): - while self.keys: - # Build the next batch - batch = BatchList(self.table.layer2) - batch.add_batch(self.table, self.keys[:100], - self.attributes_to_get) - res = batch.submit() - - # parse the results - if self.table.name not in res[u'Responses']: - continue - self.consumed_units += res[u'Responses'][self.table.name][u'ConsumedCapacityUnits'] - for elem in res[u'Responses'][self.table.name][u'Items']: - yield elem - - # re-queue un processed keys - self.keys = self.keys[100:] - self._queue_unprocessed(res) - - -class Table(object): - """ - An Amazon DynamoDB table. - - :ivar name: The name of the table. - :ivar create_time: The date and time that the table was created. - :ivar status: The current status of the table. One of: - 'ACTIVE', 'UPDATING', 'DELETING'. - :ivar schema: A :class:`boto.dynamodb.schema.Schema` object representing - the schema defined for the table. - :ivar item_count: The number of items in the table. This value is - set only when the Table object is created or refreshed and - may not reflect the actual count. - :ivar size_bytes: Total size of the specified table, in bytes. - Amazon DynamoDB updates this value approximately every six hours. - Recent changes might not be reflected in this value. - :ivar read_units: The ReadCapacityUnits of the tables - Provisioned Throughput. - :ivar write_units: The WriteCapacityUnits of the tables - Provisioned Throughput. - :ivar schema: The Schema object associated with the table. - """ - - def __init__(self, layer2, response): - """ - - :type layer2: :class:`boto.dynamodb.layer2.Layer2` - :param layer2: A `Layer2` api object. - - :type response: dict - :param response: The output of - `boto.dynamodb.layer1.Layer1.describe_table`. - - """ - self.layer2 = layer2 - self._dict = {} - self.update_from_response(response) - - @classmethod - def create_from_schema(cls, layer2, name, schema): - """Create a Table object. - - If you know the name and schema of your table, you can - create a ``Table`` object without having to make any - API calls (normally an API call is made to retrieve - the schema of a table). - - Example usage:: - - table = Table.create_from_schema( - boto.connect_dynamodb(), - 'tablename', - Schema.create(hash_key=('keyname', 'N'))) - - :type layer2: :class:`boto.dynamodb.layer2.Layer2` - :param layer2: A ``Layer2`` api object. - - :type name: str - :param name: The name of the table. - - :type schema: :class:`boto.dynamodb.schema.Schema` - :param schema: The schema associated with the table. - - :rtype: :class:`boto.dynamodb.table.Table` - :return: A Table object representing the table. - - """ - table = cls(layer2, {'Table': {'TableName': name}}) - table._schema = schema - return table - - def __repr__(self): - return 'Table(%s)' % self.name - - @property - def name(self): - return self._dict['TableName'] - - @property - def create_time(self): - return self._dict.get('CreationDateTime', None) - - @property - def status(self): - return self._dict.get('TableStatus', None) - - @property - def item_count(self): - return self._dict.get('ItemCount', 0) - - @property - def size_bytes(self): - return self._dict.get('TableSizeBytes', 0) - - @property - def schema(self): - return self._schema - - @property - def read_units(self): - try: - return self._dict['ProvisionedThroughput']['ReadCapacityUnits'] - except KeyError: - return None - - @property - def write_units(self): - try: - return self._dict['ProvisionedThroughput']['WriteCapacityUnits'] - except KeyError: - return None - - def update_from_response(self, response): - """ - Update the state of the Table object based on the response - data received from Amazon DynamoDB. - """ - # 'Table' is from a describe_table call. - if 'Table' in response: - self._dict.update(response['Table']) - # 'TableDescription' is from a create_table call. - elif 'TableDescription' in response: - self._dict.update(response['TableDescription']) - if 'KeySchema' in self._dict: - self._schema = Schema(self._dict['KeySchema']) - - def refresh(self, wait_for_active=False, retry_seconds=5): - """ - Refresh all of the fields of the Table object by calling - the underlying DescribeTable request. - - :type wait_for_active: bool - :param wait_for_active: If True, this command will not return - until the table status, as returned from Amazon DynamoDB, is - 'ACTIVE'. - - :type retry_seconds: int - :param retry_seconds: If wait_for_active is True, this - parameter controls the number of seconds of delay between - calls to update_table in Amazon DynamoDB. Default is 5 seconds. - """ - done = False - while not done: - response = self.layer2.describe_table(self.name) - self.update_from_response(response) - if wait_for_active: - if self.status == 'ACTIVE': - done = True - else: - time.sleep(retry_seconds) - else: - done = True - - def update_throughput(self, read_units, write_units): - """ - Update the ProvisionedThroughput for the Amazon DynamoDB Table. - - :type read_units: int - :param read_units: The new value for ReadCapacityUnits. - - :type write_units: int - :param write_units: The new value for WriteCapacityUnits. - """ - self.layer2.update_throughput(self, read_units, write_units) - - def delete(self): - """ - Delete this table and all items in it. After calling this - the Table objects status attribute will be set to 'DELETING'. - """ - self.layer2.delete_table(self) - - def get_item(self, hash_key, range_key=None, - attributes_to_get=None, consistent_read=False, - item_class=Item): - """ - Retrieve an existing item from the table. - - :type hash_key: int|long|float|str|unicode|Binary - :param hash_key: The HashKey of the requested item. The - type of the value must match the type defined in the - schema for the table. - - :type range_key: int|long|float|str|unicode|Binary - :param range_key: The optional RangeKey of the requested item. - The type of the value must match the type defined in the - schema for the table. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type consistent_read: bool - :param consistent_read: If True, a consistent read - request is issued. Otherwise, an eventually consistent - request is issued. - - :type item_class: Class - :param item_class: Allows you to override the class used - to generate the items. This should be a subclass of - :class:`boto.dynamodb.item.Item` - """ - return self.layer2.get_item(self, hash_key, range_key, - attributes_to_get, consistent_read, - item_class) - lookup = get_item - - def has_item(self, hash_key, range_key=None, consistent_read=False): - """ - Checks the table to see if the Item with the specified ``hash_key`` - exists. This may save a tiny bit of time/bandwidth over a - straight :py:meth:`get_item` if you have no intention to touch - the data that is returned, since this method specifically tells - Amazon not to return anything but the Item's key. - - :type hash_key: int|long|float|str|unicode|Binary - :param hash_key: The HashKey of the requested item. The - type of the value must match the type defined in the - schema for the table. - - :type range_key: int|long|float|str|unicode|Binary - :param range_key: The optional RangeKey of the requested item. - The type of the value must match the type defined in the - schema for the table. - - :type consistent_read: bool - :param consistent_read: If True, a consistent read - request is issued. Otherwise, an eventually consistent - request is issued. - - :rtype: bool - :returns: ``True`` if the Item exists, ``False`` if not. - """ - try: - # Attempt to get the key. If it can't be found, it'll raise - # an exception. - self.get_item(hash_key, range_key=range_key, - # This minimizes the size of the response body. - attributes_to_get=[hash_key], - consistent_read=consistent_read) - except dynamodb_exceptions.DynamoDBKeyNotFoundError: - # Key doesn't exist. - return False - return True - - def new_item(self, hash_key=None, range_key=None, attrs=None, - item_class=Item): - """ - Return an new, unsaved Item which can later be PUT to - Amazon DynamoDB. - - This method has explicit (but optional) parameters for - the hash_key and range_key values of the item. You can use - these explicit parameters when calling the method, such as:: - - >>> my_item = my_table.new_item(hash_key='a', range_key=1, - attrs={'key1': 'val1', 'key2': 'val2'}) - >>> my_item - {u'bar': 1, u'foo': 'a', 'key1': 'val1', 'key2': 'val2'} - - Or, if you prefer, you can simply put the hash_key and range_key - in the attrs dictionary itself, like this:: - - >>> attrs = {'foo': 'a', 'bar': 1, 'key1': 'val1', 'key2': 'val2'} - >>> my_item = my_table.new_item(attrs=attrs) - >>> my_item - {u'bar': 1, u'foo': 'a', 'key1': 'val1', 'key2': 'val2'} - - The effect is the same. - - .. note: - The explicit parameters take priority over the values in - the attrs dict. So, if you have a hash_key or range_key - in the attrs dict and you also supply either or both using - the explicit parameters, the values in the attrs will be - ignored. - - :type hash_key: int|long|float|str|unicode|Binary - :param hash_key: The HashKey of the new item. The - type of the value must match the type defined in the - schema for the table. - - :type range_key: int|long|float|str|unicode|Binary - :param range_key: The optional RangeKey of the new item. - The type of the value must match the type defined in the - schema for the table. - - :type attrs: dict - :param attrs: A dictionary of key value pairs used to - populate the new item. - - :type item_class: Class - :param item_class: Allows you to override the class used - to generate the items. This should be a subclass of - :class:`boto.dynamodb.item.Item` - """ - return item_class(self, hash_key, range_key, attrs) - - def query(self, hash_key, *args, **kw): - """ - Perform a query on the table. - - :type hash_key: int|long|float|str|unicode|Binary - :param hash_key: The HashKey of the requested item. The - type of the value must match the type defined in the - schema for the table. - - :type range_key_condition: :class:`boto.dynamodb.condition.Condition` - :param range_key_condition: A Condition object. - Condition object can be one of the following types: - - EQ|LE|LT|GE|GT|BEGINS_WITH|BETWEEN - - The only condition which expects or will accept two - values is 'BETWEEN', otherwise a single value should - be passed to the Condition constructor. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type request_limit: int - :param request_limit: The maximum number of items to retrieve - from Amazon DynamoDB on each request. You may want to set - a specific request_limit based on the provisioned throughput - of your table. The default behavior is to retrieve as many - results as possible per request. - - :type max_results: int - :param max_results: The maximum number of results that will - be retrieved from Amazon DynamoDB in total. For example, - if you only wanted to see the first 100 results from the - query, regardless of how many were actually available, you - could set max_results to 100 and the generator returned - from the query method will only yeild 100 results max. - - :type consistent_read: bool - :param consistent_read: If True, a consistent read - request is issued. Otherwise, an eventually consistent - request is issued. - - :type scan_index_forward: bool - :param scan_index_forward: Specified forward or backward - traversal of the index. Default is forward (True). - - :type exclusive_start_key: list or tuple - :param exclusive_start_key: Primary key of the item from - which to continue an earlier query. This would be - provided as the LastEvaluatedKey in that query. - - :type count: bool - :param count: If True, Amazon DynamoDB returns a total - number of items for the Query operation, even if the - operation has no matching items for the assigned filter. - If count is True, the actual items are not returned and - the count is accessible as the ``count`` attribute of - the returned object. - - - :type item_class: Class - :param item_class: Allows you to override the class used - to generate the items. This should be a subclass of - :class:`boto.dynamodb.item.Item` - """ - return self.layer2.query(self, hash_key, *args, **kw) - - def scan(self, *args, **kw): - """ - Scan through this table, this is a very long - and expensive operation, and should be avoided if - at all possible. - - :type scan_filter: A dict - :param scan_filter: A dictionary where the key is the - attribute name and the value is a - :class:`boto.dynamodb.condition.Condition` object. - Valid Condition objects include: - - * EQ - equal (1) - * NE - not equal (1) - * LE - less than or equal (1) - * LT - less than (1) - * GE - greater than or equal (1) - * GT - greater than (1) - * NOT_NULL - attribute exists (0, use None) - * NULL - attribute does not exist (0, use None) - * CONTAINS - substring or value in list (1) - * NOT_CONTAINS - absence of substring or value in list (1) - * BEGINS_WITH - substring prefix (1) - * IN - exact match in list (N) - * BETWEEN - >= first value, <= second value (2) - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :type request_limit: int - :param request_limit: The maximum number of items to retrieve - from Amazon DynamoDB on each request. You may want to set - a specific request_limit based on the provisioned throughput - of your table. The default behavior is to retrieve as many - results as possible per request. - - :type max_results: int - :param max_results: The maximum number of results that will - be retrieved from Amazon DynamoDB in total. For example, - if you only wanted to see the first 100 results from the - query, regardless of how many were actually available, you - could set max_results to 100 and the generator returned - from the query method will only yeild 100 results max. - - :type count: bool - :param count: If True, Amazon DynamoDB returns a total - number of items for the Scan operation, even if the - operation has no matching items for the assigned filter. - If count is True, the actual items are not returned and - the count is accessible as the ``count`` attribute of - the returned object. - - :type exclusive_start_key: list or tuple - :param exclusive_start_key: Primary key of the item from - which to continue an earlier query. This would be - provided as the LastEvaluatedKey in that query. - - :type item_class: Class - :param item_class: Allows you to override the class used - to generate the items. This should be a subclass of - :class:`boto.dynamodb.item.Item` - - :return: A TableGenerator (generator) object which will iterate - over all results - :rtype: :class:`boto.dynamodb.layer2.TableGenerator` - """ - return self.layer2.scan(self, *args, **kw) - - def batch_get_item(self, keys, attributes_to_get=None): - """ - Return a set of attributes for a multiple items from a single table - using their primary keys. This abstraction removes the 100 Items per - batch limitations as well as the "UnprocessedKeys" logic. - - :type keys: list - :param keys: A list of scalar or tuple values. Each element in the - list represents one Item to retrieve. If the schema for the - table has both a HashKey and a RangeKey, each element in the - list should be a tuple consisting of (hash_key, range_key). If - the schema for the table contains only a HashKey, each element - in the list should be a scalar value of the appropriate type - for the table schema. NOTE: The maximum number of items that - can be retrieved for a single operation is 100. Also, the - number of items retrieved is constrained by a 1 MB size limit. - - :type attributes_to_get: list - :param attributes_to_get: A list of attribute names. - If supplied, only the specified attribute names will - be returned. Otherwise, all attributes will be returned. - - :return: A TableBatchGenerator (generator) object which will - iterate over all results - :rtype: :class:`boto.dynamodb.table.TableBatchGenerator` - """ - return TableBatchGenerator(self, keys, attributes_to_get) diff --git a/awx/lib/site-packages/boto/dynamodb/types.py b/awx/lib/site-packages/boto/dynamodb/types.py deleted file mode 100644 index 2049c219cc..0000000000 --- a/awx/lib/site-packages/boto/dynamodb/types.py +++ /dev/null @@ -1,363 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -""" -Some utility functions to deal with mapping Amazon DynamoDB types to -Python types and vice-versa. -""" -import base64 -from decimal import (Decimal, DecimalException, Context, - Clamped, Overflow, Inexact, Underflow, Rounded) -from boto.dynamodb.exceptions import DynamoDBNumberError -from boto.compat import filter, map, six, long_type - - -DYNAMODB_CONTEXT = Context( - Emin=-128, Emax=126, rounding=None, prec=38, - traps=[Clamped, Overflow, Inexact, Rounded, Underflow]) - - -# python2.6 cannot convert floats directly to -# Decimals. This is taken from: -# http://docs.python.org/release/2.6.7/library/decimal.html#decimal-faq -def float_to_decimal(f): - n, d = f.as_integer_ratio() - numerator, denominator = Decimal(n), Decimal(d) - ctx = DYNAMODB_CONTEXT - result = ctx.divide(numerator, denominator) - while ctx.flags[Inexact]: - ctx.flags[Inexact] = False - ctx.prec *= 2 - result = ctx.divide(numerator, denominator) - return result - - -def is_num(n): - types = (int, long_type, float, bool, Decimal) - return isinstance(n, types) or n in types - - -if six.PY2: - def is_str(n): - return (isinstance(n, basestring) or - isinstance(n, type) and issubclass(n, basestring)) - - def is_binary(n): - return isinstance(n, Binary) - -else: # PY3 - def is_str(n): - return (isinstance(n, str) or - isinstance(n, type) and issubclass(n, str)) - - def is_binary(n): - return isinstance(n, bytes) # Binary is subclass of bytes. - - -def serialize_num(val): - """Cast a number to a string and perform - validation to ensure no loss of precision. - """ - if isinstance(val, bool): - return str(int(val)) - return str(val) - - -def convert_num(s): - if '.' in s: - n = float(s) - else: - n = int(s) - return n - - -def convert_binary(n): - return Binary(base64.b64decode(n)) - - -def get_dynamodb_type(val): - """ - Take a scalar Python value and return a string representing - the corresponding Amazon DynamoDB type. If the value passed in is - not a supported type, raise a TypeError. - """ - dynamodb_type = None - if is_num(val): - dynamodb_type = 'N' - elif is_str(val): - dynamodb_type = 'S' - elif isinstance(val, (set, frozenset)): - if False not in map(is_num, val): - dynamodb_type = 'NS' - elif False not in map(is_str, val): - dynamodb_type = 'SS' - elif False not in map(is_binary, val): - dynamodb_type = 'BS' - elif is_binary(val): - dynamodb_type = 'B' - if dynamodb_type is None: - msg = 'Unsupported type "%s" for value "%s"' % (type(val), val) - raise TypeError(msg) - return dynamodb_type - - -def dynamize_value(val): - """ - Take a scalar Python value and return a dict consisting - of the Amazon DynamoDB type specification and the value that - needs to be sent to Amazon DynamoDB. If the type of the value - is not supported, raise a TypeError - """ - dynamodb_type = get_dynamodb_type(val) - if dynamodb_type == 'N': - val = {dynamodb_type: serialize_num(val)} - elif dynamodb_type == 'S': - val = {dynamodb_type: val} - elif dynamodb_type == 'NS': - val = {dynamodb_type: list(map(serialize_num, val))} - elif dynamodb_type == 'SS': - val = {dynamodb_type: [n for n in val]} - elif dynamodb_type == 'B': - if isinstance(val, bytes): - val = Binary(val) - val = {dynamodb_type: val.encode()} - elif dynamodb_type == 'BS': - val = {dynamodb_type: [n.encode() for n in val]} - return val - - -if six.PY2: - class Binary(object): - def __init__(self, value): - if not isinstance(value, (bytes, six.text_type)): - raise TypeError('Value must be a string of binary data!') - if not isinstance(value, bytes): - value = value.encode("utf-8") - - self.value = value - - def encode(self): - return base64.b64encode(self.value).decode('utf-8') - - def __eq__(self, other): - if isinstance(other, Binary): - return self.value == other.value - else: - return self.value == other - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return 'Binary(%r)' % self.value - - def __str__(self): - return self.value - - def __hash__(self): - return hash(self.value) -else: - class Binary(bytes): - def encode(self): - return base64.b64encode(self).decode('utf-8') - - @property - def value(self): - # This matches the public API of the Python 2 version, - # but just returns itself since it is already a bytes - # instance. - return bytes(self) - - def __repr__(self): - return 'Binary(%r)' % self.value - - -def item_object_hook(dct): - """ - A custom object hook for use when decoding JSON item bodys. - This hook will transform Amazon DynamoDB JSON responses to something - that maps directly to native Python types. - """ - if len(dct.keys()) > 1: - return dct - if 'S' in dct: - return dct['S'] - if 'N' in dct: - return convert_num(dct['N']) - if 'SS' in dct: - return set(dct['SS']) - if 'NS' in dct: - return set(map(convert_num, dct['NS'])) - if 'B' in dct: - return convert_binary(dct['B']) - if 'BS' in dct: - return set(map(convert_binary, dct['BS'])) - return dct - - -class Dynamizer(object): - """Control serialization/deserialization of types. - - This class controls the encoding of python types to the - format that is expected by the DynamoDB API, as well as - taking DynamoDB types and constructing the appropriate - python types. - - If you want to customize this process, you can subclass - this class and override the encoding/decoding of - specific types. For example:: - - 'foo' (Python type) - | - v - encode('foo') - | - v - _encode_s('foo') - | - v - {'S': 'foo'} (Encoding sent to/received from DynamoDB) - | - V - decode({'S': 'foo'}) - | - v - _decode_s({'S': 'foo'}) - | - v - 'foo' (Python type) - - """ - def _get_dynamodb_type(self, attr): - return get_dynamodb_type(attr) - - def encode(self, attr): - """ - Encodes a python type to the format expected - by DynamoDB. - - """ - dynamodb_type = self._get_dynamodb_type(attr) - try: - encoder = getattr(self, '_encode_%s' % dynamodb_type.lower()) - except AttributeError: - raise ValueError("Unable to encode dynamodb type: %s" % - dynamodb_type) - return {dynamodb_type: encoder(attr)} - - def _encode_n(self, attr): - try: - if isinstance(attr, float) and not hasattr(Decimal, 'from_float'): - # python2.6 does not support creating Decimals directly - # from floats so we have to do this ourself. - n = str(float_to_decimal(attr)) - else: - n = str(DYNAMODB_CONTEXT.create_decimal(attr)) - if list(filter(lambda x: x in n, ('Infinity', 'NaN'))): - raise TypeError('Infinity and NaN not supported') - return n - except (TypeError, DecimalException) as e: - msg = '{0} numeric for `{1}`\n{2}'.format( - e.__class__.__name__, attr, str(e) or '') - raise DynamoDBNumberError(msg) - - def _encode_s(self, attr): - if isinstance(attr, bytes): - attr = attr.decode('utf-8') - elif not isinstance(attr, six.text_type): - attr = str(attr) - return attr - - def _encode_ns(self, attr): - return list(map(self._encode_n, attr)) - - def _encode_ss(self, attr): - return [self._encode_s(n) for n in attr] - - def _encode_b(self, attr): - if isinstance(attr, bytes): - attr = Binary(attr) - return attr.encode() - - def _encode_bs(self, attr): - return [self._encode_b(n) for n in attr] - - def decode(self, attr): - """ - Takes the format returned by DynamoDB and constructs - the appropriate python type. - - """ - if len(attr) > 1 or not attr: - return attr - dynamodb_type = list(attr.keys())[0] - if dynamodb_type.lower() == dynamodb_type: - # It's not an actual type, just a single character attr that - # overlaps with the DDB types. Return it. - return attr - try: - decoder = getattr(self, '_decode_%s' % dynamodb_type.lower()) - except AttributeError: - return attr - return decoder(attr[dynamodb_type]) - - def _decode_n(self, attr): - return DYNAMODB_CONTEXT.create_decimal(attr) - - def _decode_s(self, attr): - return attr - - def _decode_ns(self, attr): - return set(map(self._decode_n, attr)) - - def _decode_ss(self, attr): - return set(map(self._decode_s, attr)) - - def _decode_b(self, attr): - return convert_binary(attr) - - def _decode_bs(self, attr): - return set(map(self._decode_b, attr)) - - -class LossyFloatDynamizer(Dynamizer): - """Use float/int instead of Decimal for numeric types. - - This class is provided for backwards compatibility. Instead of - using Decimals for the 'N', 'NS' types it uses ints/floats. - - This class is deprecated and its usage is not encouraged, - as doing so may result in loss of precision. Use the - `Dynamizer` class instead. - - """ - def _encode_n(self, attr): - return serialize_num(attr) - - def _encode_ns(self, attr): - return [str(i) for i in attr] - - def _decode_n(self, attr): - return convert_num(attr) - - def _decode_ns(self, attr): - return set(map(self._decode_n, attr)) diff --git a/awx/lib/site-packages/boto/dynamodb2/__init__.py b/awx/lib/site-packages/boto/dynamodb2/__init__.py deleted file mode 100644 index aa07e5cce4..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon DynamoDB service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.dynamodb2.layer1 import DynamoDBConnection - return get_regions('dynamodb', connection_cls=DynamoDBConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/dynamodb2/exceptions.py b/awx/lib/site-packages/boto/dynamodb2/exceptions.py deleted file mode 100644 index 3a677e09df..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/exceptions.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import JSONResponseError - - -class ProvisionedThroughputExceededException(JSONResponseError): - pass - - -class LimitExceededException(JSONResponseError): - pass - - -class ConditionalCheckFailedException(JSONResponseError): - pass - - -class ResourceInUseException(JSONResponseError): - pass - - -class ResourceNotFoundException(JSONResponseError): - pass - - -class InternalServerError(JSONResponseError): - pass - - -class ValidationException(JSONResponseError): - pass - - -class ItemCollectionSizeLimitExceededException(JSONResponseError): - pass - - -class DynamoDBError(Exception): - pass - - -class UnknownSchemaFieldError(DynamoDBError): - pass - - -class UnknownIndexFieldError(DynamoDBError): - pass - - -class UnknownFilterTypeError(DynamoDBError): - pass - - -class QueryError(DynamoDBError): - pass - - -class ItemNotFound(DynamoDBError): - pass diff --git a/awx/lib/site-packages/boto/dynamodb2/fields.py b/awx/lib/site-packages/boto/dynamodb2/fields.py deleted file mode 100644 index 4443969e4e..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/fields.py +++ /dev/null @@ -1,337 +0,0 @@ -from boto.dynamodb2.types import STRING - - -class BaseSchemaField(object): - """ - An abstract class for defining schema fields. - - Contains most of the core functionality for the field. Subclasses must - define an ``attr_type`` to pass to DynamoDB. - """ - attr_type = None - - def __init__(self, name, data_type=STRING): - """ - Creates a Python schema field, to represent the data to pass to - DynamoDB. - - Requires a ``name`` parameter, which should be a string name of the - field. - - Optionally accepts a ``data_type`` parameter, which should be a - constant from ``boto.dynamodb2.types``. (Default: ``STRING``) - """ - self.name = name - self.data_type = data_type - - def definition(self): - """ - Returns the attribute definition structure DynamoDB expects. - - Example:: - - >>> field.definition() - { - 'AttributeName': 'username', - 'AttributeType': 'S', - } - - """ - return { - 'AttributeName': self.name, - 'AttributeType': self.data_type, - } - - def schema(self): - """ - Returns the schema structure DynamoDB expects. - - Example:: - - >>> field.schema() - { - 'AttributeName': 'username', - 'KeyType': 'HASH', - } - - """ - return { - 'AttributeName': self.name, - 'KeyType': self.attr_type, - } - - -class HashKey(BaseSchemaField): - """ - An field representing a hash key. - - Example:: - - >>> from boto.dynamodb2.types import NUMBER - >>> HashKey('username') - >>> HashKey('date_joined', data_type=NUMBER) - - """ - attr_type = 'HASH' - - -class RangeKey(BaseSchemaField): - """ - An field representing a range key. - - Example:: - - >>> from boto.dynamodb2.types import NUMBER - >>> HashKey('username') - >>> HashKey('date_joined', data_type=NUMBER) - - """ - attr_type = 'RANGE' - - -class BaseIndexField(object): - """ - An abstract class for defining schema indexes. - - Contains most of the core functionality for the index. Subclasses must - define a ``projection_type`` to pass to DynamoDB. - """ - def __init__(self, name, parts): - self.name = name - self.parts = parts - - def definition(self): - """ - Returns the attribute definition structure DynamoDB expects. - - Example:: - - >>> index.definition() - { - 'AttributeName': 'username', - 'AttributeType': 'S', - } - - """ - definition = [] - - for part in self.parts: - definition.append({ - 'AttributeName': part.name, - 'AttributeType': part.data_type, - }) - - return definition - - def schema(self): - """ - Returns the schema structure DynamoDB expects. - - Example:: - - >>> index.schema() - { - 'IndexName': 'LastNameIndex', - 'KeySchema': [ - { - 'AttributeName': 'username', - 'KeyType': 'HASH', - }, - ], - 'Projection': { - 'ProjectionType': 'KEYS_ONLY', - } - } - - """ - key_schema = [] - - for part in self.parts: - key_schema.append(part.schema()) - - return { - 'IndexName': self.name, - 'KeySchema': key_schema, - 'Projection': { - 'ProjectionType': self.projection_type, - } - } - - -class AllIndex(BaseIndexField): - """ - An index signifying all fields should be in the index. - - Example:: - - >>> AllIndex('MostRecentlyJoined', parts=[ - ... HashKey('username'), - ... RangeKey('date_joined') - ... ]) - - """ - projection_type = 'ALL' - - -class KeysOnlyIndex(BaseIndexField): - """ - An index signifying only key fields should be in the index. - - Example:: - - >>> KeysOnlyIndex('MostRecentlyJoined', parts=[ - ... HashKey('username'), - ... RangeKey('date_joined') - ... ]) - - """ - projection_type = 'KEYS_ONLY' - - -class IncludeIndex(BaseIndexField): - """ - An index signifying only certain fields should be in the index. - - Example:: - - >>> IncludeIndex('GenderIndex', parts=[ - ... HashKey('username'), - ... RangeKey('date_joined') - ... ], includes=['gender']) - - """ - projection_type = 'INCLUDE' - - def __init__(self, *args, **kwargs): - self.includes_fields = kwargs.pop('includes', []) - super(IncludeIndex, self).__init__(*args, **kwargs) - - def schema(self): - schema_data = super(IncludeIndex, self).schema() - schema_data['Projection']['NonKeyAttributes'] = self.includes_fields - return schema_data - - -class GlobalBaseIndexField(BaseIndexField): - """ - An abstract class for defining global indexes. - - Contains most of the core functionality for the index. Subclasses must - define a ``projection_type`` to pass to DynamoDB. - """ - throughput = { - 'read': 5, - 'write': 5, - } - - def __init__(self, *args, **kwargs): - throughput = kwargs.pop('throughput', None) - - if throughput is not None: - self.throughput = throughput - - super(GlobalBaseIndexField, self).__init__(*args, **kwargs) - - def schema(self): - """ - Returns the schema structure DynamoDB expects. - - Example:: - - >>> index.schema() - { - 'IndexName': 'LastNameIndex', - 'KeySchema': [ - { - 'AttributeName': 'username', - 'KeyType': 'HASH', - }, - ], - 'Projection': { - 'ProjectionType': 'KEYS_ONLY', - }, - 'ProvisionedThroughput': { - 'ReadCapacityUnits': 5, - 'WriteCapacityUnits': 5 - } - } - - """ - schema_data = super(GlobalBaseIndexField, self).schema() - schema_data['ProvisionedThroughput'] = { - 'ReadCapacityUnits': int(self.throughput['read']), - 'WriteCapacityUnits': int(self.throughput['write']), - } - return schema_data - - -class GlobalAllIndex(GlobalBaseIndexField): - """ - An index signifying all fields should be in the index. - - Example:: - - >>> GlobalAllIndex('MostRecentlyJoined', parts=[ - ... HashKey('username'), - ... RangeKey('date_joined') - ... ], - ... throughput={ - ... 'read': 2, - ... 'write': 1, - ... }) - - """ - projection_type = 'ALL' - - -class GlobalKeysOnlyIndex(GlobalBaseIndexField): - """ - An index signifying only key fields should be in the index. - - Example:: - - >>> GlobalKeysOnlyIndex('MostRecentlyJoined', parts=[ - ... HashKey('username'), - ... RangeKey('date_joined') - ... ], - ... throughput={ - ... 'read': 2, - ... 'write': 1, - ... }) - - """ - projection_type = 'KEYS_ONLY' - - -class GlobalIncludeIndex(GlobalBaseIndexField, IncludeIndex): - """ - An index signifying only certain fields should be in the index. - - Example:: - - >>> GlobalIncludeIndex('GenderIndex', parts=[ - ... HashKey('username'), - ... RangeKey('date_joined') - ... ], - ... includes=['gender'], - ... throughput={ - ... 'read': 2, - ... 'write': 1, - ... }) - - """ - projection_type = 'INCLUDE' - - def __init__(self, *args, **kwargs): - throughput = kwargs.pop('throughput', None) - IncludeIndex.__init__(self, *args, **kwargs) - if throughput: - kwargs['throughput'] = throughput - GlobalBaseIndexField.__init__(self, *args, **kwargs) - - def schema(self): - # Pick up the includes. - schema_data = IncludeIndex.schema(self) - # Also the throughput. - schema_data.update(GlobalBaseIndexField.schema(self)) - return schema_data diff --git a/awx/lib/site-packages/boto/dynamodb2/items.py b/awx/lib/site-packages/boto/dynamodb2/items.py deleted file mode 100644 index 463feee793..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/items.py +++ /dev/null @@ -1,472 +0,0 @@ -from copy import deepcopy - -from boto.dynamodb2.types import Dynamizer - - -class NEWVALUE(object): - # A marker for new data added. - pass - - -class Item(object): - """ - An object representing the item data within a DynamoDB table. - - An item is largely schema-free, meaning it can contain any data. The only - limitation is that it must have data for the fields in the ``Table``'s - schema. - - This object presents a dictionary-like interface for accessing/storing - data. It also tries to intelligently track how data has changed throughout - the life of the instance, to be as efficient as possible about updates. - - Empty items, or items that have no data, are considered falsey. - - """ - def __init__(self, table, data=None, loaded=False): - """ - Constructs an (unsaved) ``Item`` instance. - - To persist the data in DynamoDB, you'll need to call the ``Item.save`` - (or ``Item.partial_save``) on the instance. - - Requires a ``table`` parameter, which should be a ``Table`` instance. - This is required, as DynamoDB's API is focus around all operations - being table-level. It's also for persisting schema around many objects. - - Optionally accepts a ``data`` parameter, which should be a dictionary - of the fields & values of the item. - - Optionally accepts a ``loaded`` parameter, which should be a boolean. - ``True`` if it was preexisting data loaded from DynamoDB, ``False`` if - it's new data from the user. Default is ``False``. - - Example:: - - >>> users = Table('users') - >>> user = Item(users, data={ - ... 'username': 'johndoe', - ... 'first_name': 'John', - ... 'date_joined': 1248o61592, - ... }) - - # Change existing data. - >>> user['first_name'] = 'Johann' - # Add more data. - >>> user['last_name'] = 'Doe' - # Delete data. - >>> del user['date_joined'] - - # Iterate over all the data. - >>> for field, val in user.items(): - ... print "%s: %s" % (field, val) - username: johndoe - first_name: John - date_joined: 1248o61592 - - """ - self.table = table - self._loaded = loaded - self._orig_data = {} - self._data = data - self._dynamizer = Dynamizer() - - if self._data is None: - self._data = {} - - if self._loaded: - self._orig_data = deepcopy(self._data) - - def __getitem__(self, key): - return self._data.get(key, None) - - def __setitem__(self, key, value): - self._data[key] = value - - def __delitem__(self, key): - if not key in self._data: - return - - del self._data[key] - - def keys(self): - return self._data.keys() - - def values(self): - return self._data.values() - - def items(self): - return self._data.items() - - def get(self, key, default=None): - return self._data.get(key, default) - - def __iter__(self): - for key in self._data: - yield self._data[key] - - def __contains__(self, key): - return key in self._data - - def __bool__(self): - return bool(self._data) - - __nonzero__ = __bool__ - - def _determine_alterations(self): - """ - Checks the ``-orig_data`` against the ``_data`` to determine what - changes to the data are present. - - Returns a dictionary containing the keys ``adds``, ``changes`` & - ``deletes``, containing the updated data. - """ - alterations = { - 'adds': {}, - 'changes': {}, - 'deletes': [], - } - - orig_keys = set(self._orig_data.keys()) - data_keys = set(self._data.keys()) - - # Run through keys we know are in both for changes. - for key in orig_keys.intersection(data_keys): - if self._data[key] != self._orig_data[key]: - if self._is_storable(self._data[key]): - alterations['changes'][key] = self._data[key] - else: - alterations['deletes'].append(key) - - # Run through additions. - for key in data_keys.difference(orig_keys): - if self._is_storable(self._data[key]): - alterations['adds'][key] = self._data[key] - - # Run through deletions. - for key in orig_keys.difference(data_keys): - alterations['deletes'].append(key) - - return alterations - - def needs_save(self, data=None): - """ - Returns whether or not the data has changed on the ``Item``. - - Optionally accepts a ``data`` argument, which accepts the output from - ``self._determine_alterations()`` if you've already called it. Typically - unnecessary to do. Default is ``None``. - - Example: - - >>> user.needs_save() - False - >>> user['first_name'] = 'Johann' - >>> user.needs_save() - True - - """ - if data is None: - data = self._determine_alterations() - - needs_save = False - - for kind in ['adds', 'changes', 'deletes']: - if len(data[kind]): - needs_save = True - break - - return needs_save - - def mark_clean(self): - """ - Marks an ``Item`` instance as no longer needing to be saved. - - Example: - - >>> user.needs_save() - False - >>> user['first_name'] = 'Johann' - >>> user.needs_save() - True - >>> user.mark_clean() - >>> user.needs_save() - False - - """ - self._orig_data = deepcopy(self._data) - - def mark_dirty(self): - """ - DEPRECATED: Marks an ``Item`` instance as needing to be saved. - - This method is no longer necessary, as the state tracking on ``Item`` - has been improved to automatically detect proper state. - """ - return - - def load(self, data): - """ - This is only useful when being handed raw data from DynamoDB directly. - If you have a Python datastructure already, use the ``__init__`` or - manually set the data instead. - - Largely internal, unless you know what you're doing or are trying to - mix the low-level & high-level APIs. - """ - self._data = {} - - for field_name, field_value in data.get('Item', {}).items(): - self[field_name] = self._dynamizer.decode(field_value) - - self._loaded = True - self._orig_data = deepcopy(self._data) - - def get_keys(self): - """ - Returns a Python-style dict of the keys/values. - - Largely internal. - """ - key_fields = self.table.get_key_fields() - key_data = {} - - for key in key_fields: - key_data[key] = self[key] - - return key_data - - def get_raw_keys(self): - """ - Returns a DynamoDB-style dict of the keys/values. - - Largely internal. - """ - raw_key_data = {} - - for key, value in self.get_keys().items(): - raw_key_data[key] = self._dynamizer.encode(value) - - return raw_key_data - - def build_expects(self, fields=None): - """ - Builds up a list of expecations to hand off to DynamoDB on save. - - Largely internal. - """ - expects = {} - - if fields is None: - fields = list(self._data.keys()) + list(self._orig_data.keys()) - - # Only uniques. - fields = set(fields) - - for key in fields: - expects[key] = { - 'Exists': True, - } - value = None - - # Check for invalid keys. - if not key in self._orig_data and not key in self._data: - raise ValueError("Unknown key %s provided." % key) - - # States: - # * New field (only in _data) - # * Unchanged field (in both _data & _orig_data, same data) - # * Modified field (in both _data & _orig_data, different data) - # * Deleted field (only in _orig_data) - orig_value = self._orig_data.get(key, NEWVALUE) - current_value = self._data.get(key, NEWVALUE) - - if orig_value == current_value: - # Existing field unchanged. - value = current_value - else: - if key in self._data: - if not key in self._orig_data: - # New field. - expects[key]['Exists'] = False - else: - # Existing field modified. - value = orig_value - else: - # Existing field deleted. - value = orig_value - - if value is not None: - expects[key]['Value'] = self._dynamizer.encode(value) - - return expects - - def _is_storable(self, value): - # We need to prevent ``None``, empty string & empty set from - # heading to DDB, but allow false-y values like 0 & False make it. - if not value: - if not value in (0, 0.0, False): - return False - - return True - - def prepare_full(self): - """ - Runs through all fields & encodes them to be handed off to DynamoDB - as part of an ``save`` (``put_item``) call. - - Largely internal. - """ - # This doesn't save on it's own. Rather, we prepare the datastructure - # and hand-off to the table to handle creation/update. - final_data = {} - - for key, value in self._data.items(): - if not self._is_storable(value): - continue - - final_data[key] = self._dynamizer.encode(value) - - return final_data - - def prepare_partial(self): - """ - Runs through **ONLY** the changed/deleted fields & encodes them to be - handed off to DynamoDB as part of an ``partial_save`` (``update_item``) - call. - - Largely internal. - """ - # This doesn't save on it's own. Rather, we prepare the datastructure - # and hand-off to the table to handle creation/update. - final_data = {} - fields = set() - alterations = self._determine_alterations() - - for key, value in alterations['adds'].items(): - final_data[key] = { - 'Action': 'PUT', - 'Value': self._dynamizer.encode(self._data[key]) - } - fields.add(key) - - for key, value in alterations['changes'].items(): - final_data[key] = { - 'Action': 'PUT', - 'Value': self._dynamizer.encode(self._data[key]) - } - fields.add(key) - - for key in alterations['deletes']: - final_data[key] = { - 'Action': 'DELETE', - } - fields.add(key) - - return final_data, fields - - def partial_save(self): - """ - Saves only the changed data to DynamoDB. - - Extremely useful for high-volume/high-write data sets, this allows - you to update only a handful of fields rather than having to push - entire items. This prevents many accidental overwrite situations as - well as saves on the amount of data to transfer over the wire. - - Returns ``True`` on success, ``False`` if no save was performed or - the write failed. - - Example:: - - >>> user['last_name'] = 'Doh!' - # Only the last name field will be sent to DynamoDB. - >>> user.partial_save() - - """ - key = self.get_keys() - # Build a new dict of only the data we're changing. - final_data, fields = self.prepare_partial() - - if not final_data: - return False - - # Remove the key(s) from the ``final_data`` if present. - # They should only be present if this is a new item, in which - # case we shouldn't be sending as part of the data to update. - for fieldname, value in key.items(): - if fieldname in final_data: - del final_data[fieldname] - - try: - # It's likely also in ``fields``, so remove it there too. - fields.remove(fieldname) - except KeyError: - pass - - # Build expectations of only the fields we're planning to update. - expects = self.build_expects(fields=fields) - returned = self.table._update_item(key, final_data, expects=expects) - # Mark the object as clean. - self.mark_clean() - return returned - - def save(self, overwrite=False): - """ - Saves all data to DynamoDB. - - By default, this attempts to ensure that none of the underlying - data has changed. If any fields have changed in between when the - ``Item`` was constructed & when it is saved, this call will fail so - as not to cause any data loss. - - If you're sure possibly overwriting data is acceptable, you can pass - an ``overwrite=True``. If that's not acceptable, you may be able to use - ``Item.partial_save`` to only write the changed field data. - - Optionally accepts an ``overwrite`` parameter, which should be a - boolean. If you provide ``True``, the item will be forcibly overwritten - within DynamoDB, even if another process changed the data in the - meantime. (Default: ``False``) - - Returns ``True`` on success, ``False`` if no save was performed. - - Example:: - - >>> user['last_name'] = 'Doh!' - # All data on the Item is sent to DynamoDB. - >>> user.save() - - # If it fails, you can overwrite. - >>> user.save(overwrite=True) - - """ - if not self.needs_save() and not overwrite: - return False - - final_data = self.prepare_full() - expects = None - - if overwrite is False: - # Build expectations about *all* of the data. - expects = self.build_expects() - - returned = self.table._put_item(final_data, expects=expects) - # Mark the object as clean. - self.mark_clean() - return returned - - def delete(self): - """ - Deletes the item's data to DynamoDB. - - Returns ``True`` on success. - - Example:: - - # Buh-bye now. - >>> user.delete() - - """ - key_data = self.get_keys() - return self.table.delete_item(**key_data) diff --git a/awx/lib/site-packages/boto/dynamodb2/layer1.py b/awx/lib/site-packages/boto/dynamodb2/layer1.py deleted file mode 100644 index fd98d2f953..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/layer1.py +++ /dev/null @@ -1,2793 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from binascii import crc32 - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.dynamodb2 import exceptions - - -class DynamoDBConnection(AWSQueryConnection): - """ - Amazon DynamoDB **Overview** - This is the Amazon DynamoDB API Reference. This guide provides - descriptions and samples of the low-level DynamoDB API. For - information about DynamoDB application development, go to the - `Amazon DynamoDB Developer Guide`_. - - Instead of making the requests to the low-level DynamoDB API - directly from your application, we recommend that you use the AWS - Software Development Kits (SDKs). The easy-to-use libraries in the - AWS SDKs make it unnecessary to call the low-level DynamoDB API - directly from your application. The libraries take care of request - authentication, serialization, and connection management. For more - information, go to `Using the AWS SDKs with DynamoDB`_ in the - Amazon DynamoDB Developer Guide . - - If you decide to code against the low-level DynamoDB API directly, - you will need to write the necessary code to authenticate your - requests. For more information on signing your requests, go to - `Using the DynamoDB API`_ in the Amazon DynamoDB Developer Guide . - - The following are short descriptions of each low-level API action, - organized by function. - - **Managing Tables** - - - - + CreateTable - Creates a table with user-specified provisioned - throughput settings. You must designate one attribute as the hash - primary key for the table; you can optionally designate a second - attribute as the range primary key. DynamoDB creates indexes on - these key attributes for fast data access. Optionally, you can - create one or more secondary indexes, which provide fast data - access using non-key attributes. - + DescribeTable - Returns metadata for a table, such as table - size, status, and index information. - + UpdateTable - Modifies the provisioned throughput settings for a - table. Optionally, you can modify the provisioned throughput - settings for global secondary indexes on the table. - + ListTables - Returns a list of all tables associated with the - current AWS account and endpoint. - + DeleteTable - Deletes a table and all of its indexes. - - - - For conceptual information about managing tables, go to `Working - with Tables`_ in the Amazon DynamoDB Developer Guide . - - **Reading Data** - - - - + GetItem - Returns a set of attributes for the item that has a - given primary key. By default, GetItem performs an eventually - consistent read; however, applications can specify a strongly - consistent read instead. - + BatchGetItem - Performs multiple GetItem requests for data items - using their primary keys, from one table or multiple tables. The - response from BatchGetItem has a size limit of 16 MB and returns a - maximum of 100 items. Both eventually consistent and strongly - consistent reads can be used. - + Query - Returns one or more items from a table or a secondary - index. You must provide a specific hash key value. You can narrow - the scope of the query using comparison operators against a range - key value, or on the index key. Query supports either eventual or - strong consistency. A single response has a size limit of 1 MB. - + Scan - Reads every item in a table; the result set is eventually - consistent. You can limit the number of items returned by - filtering the data attributes, using conditional expressions. Scan - can be used to enable ad-hoc querying of a table against non-key - attributes; however, since this is a full table scan without using - an index, Scan should not be used for any application query use - case that requires predictable performance. - - - - For conceptual information about reading data, go to `Working with - Items`_ and `Query and Scan Operations`_ in the Amazon DynamoDB - Developer Guide . - - **Modifying Data** - - - - + PutItem - Creates a new item, or replaces an existing item with - a new item (including all the attributes). By default, if an item - in the table already exists with the same primary key, the new - item completely replaces the existing item. You can use - conditional operators to replace an item only if its attribute - values match certain conditions, or to insert a new item only if - that item doesn't already exist. - + UpdateItem - Modifies the attributes of an existing item. You - can also use conditional operators to perform an update only if - the item's attribute values match certain conditions. - + DeleteItem - Deletes an item in a table by primary key. You can - use conditional operators to perform a delete an item only if the - item's attribute values match certain conditions. - + BatchWriteItem - Performs multiple PutItem and DeleteItem - requests across multiple tables in a single request. A failure of - any request(s) in the batch will not cause the entire - BatchWriteItem operation to fail. Supports batches of up to 25 - items to put or delete, with a maximum total request size of 16 - MB. - - - - For conceptual information about modifying data, go to `Working - with Items`_ and `Query and Scan Operations`_ in the Amazon - DynamoDB Developer Guide . - """ - APIVersion = "2012-08-10" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "dynamodb.us-east-1.amazonaws.com" - ServiceName = "DynamoDB" - TargetPrefix = "DynamoDB_20120810" - ResponseError = JSONResponseError - - _faults = { - "ProvisionedThroughputExceededException": exceptions.ProvisionedThroughputExceededException, - "LimitExceededException": exceptions.LimitExceededException, - "ConditionalCheckFailedException": exceptions.ConditionalCheckFailedException, - "ResourceInUseException": exceptions.ResourceInUseException, - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "InternalServerError": exceptions.InternalServerError, - "ItemCollectionSizeLimitExceededException": exceptions.ItemCollectionSizeLimitExceededException, - } - - NumberRetries = 10 - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - validate_checksums = kwargs.pop('validate_checksums', True) - if not region: - region_name = boto.config.get('DynamoDB', 'region', - self.DefaultRegionName) - for reg in boto.dynamodb2.regions(): - if reg.name == region_name: - region = reg - break - - # Only set host if it isn't manually overwritten - if 'host' not in kwargs: - kwargs['host'] = region.endpoint - - super(DynamoDBConnection, self).__init__(**kwargs) - self.region = region - self._validate_checksums = boto.config.getbool( - 'DynamoDB', 'validate_checksums', validate_checksums) - self.throughput_exceeded_events = 0 - - def _required_auth_capability(self): - return ['hmac-v4'] - - def batch_get_item(self, request_items, return_consumed_capacity=None): - """ - The BatchGetItem operation returns the attributes of one or - more items from one or more tables. You identify requested - items by primary key. - - A single operation can retrieve up to 16 MB of data, which can - contain as many as 100 items. BatchGetItem will return a - partial result if the response size limit is exceeded, the - table's provisioned throughput is exceeded, or an internal - processing failure occurs. If a partial result is returned, - the operation returns a value for UnprocessedKeys . You can - use this value to retry the operation starting with the next - item to get. - - For example, if you ask to retrieve 100 items, but each - individual item is 300 KB in size, the system returns 52 items - (so as not to exceed the 16 MB limit). It also returns an - appropriate UnprocessedKeys value so you can get the next page - of results. If desired, your application can include its own - logic to assemble the pages of results into one data set. - - If none of the items can be processed due to insufficient - provisioned throughput on all of the tables in the request, - then BatchGetItem will return a - ProvisionedThroughputExceededException . If at least one of - the items is successfully processed, then BatchGetItem - completes successfully, while returning the keys of the unread - items in UnprocessedKeys . - - If DynamoDB returns any unprocessed items, you should retry - the batch operation on those items. However, we strongly - recommend that you use an exponential backoff algorithm . If - you retry the batch operation immediately, the underlying read - or write requests can still fail due to throttling on the - individual tables. If you delay the batch operation using - exponential backoff, the individual requests in the batch are - much more likely to succeed. - - For more information, go to `Batch Operations and Error - Handling`_ in the Amazon DynamoDB Developer Guide . - - By default, BatchGetItem performs eventually consistent reads - on every table in the request. If you want strongly consistent - reads instead, you can set ConsistentRead to `True` for any or - all tables. - - In order to minimize response latency, BatchGetItem retrieves - items in parallel. - - When designing your application, keep in mind that DynamoDB - does not return attributes in any particular order. To help - parse the response by item, include the primary key values for - the items in your request in the AttributesToGet parameter. - - If a requested item does not exist, it is not returned in the - result. Requests for nonexistent items consume the minimum - read capacity units according to the type of read. For more - information, see `Capacity Units Calculations`_ in the Amazon - DynamoDB Developer Guide . - - :type request_items: map - :param request_items: - A map of one or more table names and, for each table, the corresponding - primary keys for the items to retrieve. Each table name can be - invoked only once. - - Each element in the map consists of the following: - - - + Keys - An array of primary key attribute values that define specific - items in the table. For each primary key, you must provide all of - the key attributes. For example, with a hash type primary key, you - only need to specify the hash attribute. For a hash-and-range type - primary key, you must specify both the hash attribute and the range - attribute. - + AttributesToGet - One or more attributes to be retrieved from the - table. By default, all attributes are returned. If a specified - attribute is not found, it does not appear in the result. Note that - AttributesToGet has no effect on provisioned throughput - consumption. DynamoDB determines capacity units consumed based on - item size, not on the amount of data that is returned to an - application. - + ConsistentRead - If `True`, a strongly consistent read is used; if - `False` (the default), an eventually consistent read is used. - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - """ - params = {'RequestItems': request_items, } - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - return self.make_request(action='BatchGetItem', - body=json.dumps(params)) - - def batch_write_item(self, request_items, return_consumed_capacity=None, - return_item_collection_metrics=None): - """ - The BatchWriteItem operation puts or deletes multiple items in - one or more tables. A single call to BatchWriteItem can write - up to 16 MB of data, which can comprise as many as 25 put or - delete requests. Individual items to be written can be as - large as 400 KB. - - The individual PutItem and DeleteItem operations specified in - BatchWriteItem are atomic; however BatchWriteItem as a whole - is not. If any requested operations fail because the table's - provisioned throughput is exceeded or an internal processing - failure occurs, the failed operations are returned in the - UnprocessedItems response parameter. You can investigate and - optionally resend the requests. Typically, you would call - BatchWriteItem in a loop. Each iteration would check for - unprocessed items and submit a new BatchWriteItem request with - those unprocessed items until all items have been processed. - - Note that if none of the items can be processed due to - insufficient provisioned throughput on all of the tables in - the request, then BatchWriteItem will return a - ProvisionedThroughputExceededException . - - If DynamoDB returns any unprocessed items, you should retry - the batch operation on those items. However, we strongly - recommend that you use an exponential backoff algorithm . If - you retry the batch operation immediately, the underlying read - or write requests can still fail due to throttling on the - individual tables. If you delay the batch operation using - exponential backoff, the individual requests in the batch are - much more likely to succeed. - - For more information, go to `Batch Operations and Error - Handling`_ in the Amazon DynamoDB Developer Guide . - - With BatchWriteItem , you can efficiently write or delete - large amounts of data, such as from Amazon Elastic MapReduce - (EMR), or copy data from another database into DynamoDB. In - order to improve performance with these large-scale - operations, BatchWriteItem does not behave in the same way as - individual PutItem and DeleteItem calls would For example, you - cannot specify conditions on individual put and delete - requests, and BatchWriteItem does not return deleted items in - the response. - - If you use a programming language that supports concurrency, - such as Java, you can use threads to write items in parallel. - Your application must include the necessary logic to manage - the threads. With languages that don't support threading, such - as PHP, you must update or delete the specified items one at a - time. In both situations, BatchWriteItem provides an - alternative where the API performs the specified put and - delete operations in parallel, giving you the power of the - thread pool approach without having to introduce complexity - into your application. - - Parallel processing reduces latency, but each specified put - and delete request consumes the same number of write capacity - units whether it is processed in parallel or not. Delete - operations on nonexistent items consume one write capacity - unit. - - If one or more of the following is true, DynamoDB rejects the - entire batch write operation: - - - + One or more tables specified in the BatchWriteItem request - does not exist. - + Primary key attributes specified on an item in the request - do not match those in the corresponding table's primary key - schema. - + You try to perform multiple operations on the same item in - the same BatchWriteItem request. For example, you cannot put - and delete the same item in the same BatchWriteItem request. - + There are more than 25 requests in the batch. - + Any individual item in a batch exceeds 400 KB. - + The total request size exceeds 16 MB. - - :type request_items: map - :param request_items: - A map of one or more table names and, for each table, a list of - operations to be performed ( DeleteRequest or PutRequest ). Each - element in the map consists of the following: - - - + DeleteRequest - Perform a DeleteItem operation on the specified item. - The item to be deleted is identified by a Key subelement: - - + Key - A map of primary key attribute values that uniquely identify - the ! item. Each entry in this map consists of an attribute name - and an attribute value. For each primary key, you must provide all - of the key attributes. For example, with a hash type primary key, - you only need to specify the hash attribute. For a hash-and-range - type primary key, you must specify both the hash attribute and the - range attribute. - - + PutRequest - Perform a PutItem operation on the specified item. The - item to be put is identified by an Item subelement: - - + Item - A map of attributes and their values. Each entry in this map - consists of an attribute name and an attribute value. Attribute - values must not be null; string and binary type attributes must - have lengths greater than zero; and set type attributes must not be - empty. Requests that contain empty values will be rejected with a - ValidationException exception. If you specify any attributes that - are part of an index key, then the data types for those attributes - must match those of the schema in the table's attribute definition. - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - :type return_item_collection_metrics: string - :param return_item_collection_metrics: A value that if set to `SIZE`, - the response includes statistics about item collections, if any, - that were modified during the operation are returned in the - response. If set to `NONE` (the default), no statistics are - returned. - - """ - params = {'RequestItems': request_items, } - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - if return_item_collection_metrics is not None: - params['ReturnItemCollectionMetrics'] = return_item_collection_metrics - return self.make_request(action='BatchWriteItem', - body=json.dumps(params)) - - def create_table(self, attribute_definitions, table_name, key_schema, - provisioned_throughput, local_secondary_indexes=None, - global_secondary_indexes=None): - """ - The CreateTable operation adds a new table to your account. In - an AWS account, table names must be unique within each region. - That is, you can have two tables with same name if you create - the tables in different regions. - - CreateTable is an asynchronous operation. Upon receiving a - CreateTable request, DynamoDB immediately returns a response - with a TableStatus of `CREATING`. After the table is created, - DynamoDB sets the TableStatus to `ACTIVE`. You can perform - read and write operations only on an `ACTIVE` table. - - If you want to create multiple tables with secondary indexes - on them, you must create them sequentially. Only one table - with secondary indexes can be in the `CREATING` state at any - given time. - - You can use the DescribeTable API to check the table status. - - :type attribute_definitions: list - :param attribute_definitions: An array of attributes that describe the - key schema for the table and indexes. - - :type table_name: string - :param table_name: The name of the table to create. - - :type key_schema: list - :param key_schema: Specifies the attributes that make up the primary - key for a table or an index. The attributes in KeySchema must also - be defined in the AttributeDefinitions array. For more information, - see `Data Model`_ in the Amazon DynamoDB Developer Guide . - Each KeySchemaElement in the array is composed of: - - - + AttributeName - The name of this key attribute. - + KeyType - Determines whether the key attribute is `HASH` or `RANGE`. - - - For a primary key that consists of a hash attribute, you must specify - exactly one element with a KeyType of `HASH`. - - For a primary key that consists of hash and range attributes, you must - specify exactly two elements, in this order: The first element must - have a KeyType of `HASH`, and the second element must have a - KeyType of `RANGE`. - - For more information, see `Specifying the Primary Key`_ in the Amazon - DynamoDB Developer Guide . - - :type local_secondary_indexes: list - :param local_secondary_indexes: - One or more local secondary indexes (the maximum is five) to be created - on the table. Each index is scoped to a given hash key value. There - is a 10 GB size limit per hash key; otherwise, the size of a local - secondary index is unconstrained. - - Each local secondary index in the array includes the following: - - - + IndexName - The name of the local secondary index. Must be unique - only for this table. - + KeySchema - Specifies the key schema for the local secondary index. - The key schema must begin with the same hash key attribute as the - table. - + Projection - Specifies attributes that are copied (projected) from - the table into the index. These are in addition to the primary key - attributes and index key attributes, which are automatically - projected. Each attribute specification is composed of: - - + ProjectionType - One of the following: - - + `KEYS_ONLY` - Only the index and primary keys are projected into the - index. - + `INCLUDE` - Only the specified table attributes are projected into - the index. The list of projected attributes are in NonKeyAttributes - . - + `ALL` - All of the table attributes are projected into the index. - - + NonKeyAttributes - A list of one or more non-key attribute names that - are projected into the secondary index. The total count of - attributes specified in NonKeyAttributes , summed across all of the - secondary indexes, must not exceed 20. If you project the same - attribute into two different indexes, this counts as two distinct - attributes when determining the total. - - :type global_secondary_indexes: list - :param global_secondary_indexes: - One or more global secondary indexes (the maximum is five) to be - created on the table. Each global secondary index in the array - includes the following: - - - + IndexName - The name of the global secondary index. Must be unique - only for this table. - + KeySchema - Specifies the key schema for the global secondary index. - + Projection - Specifies attributes that are copied (projected) from - the table into the index. These are in addition to the primary key - attributes and index key attributes, which are automatically - projected. Each attribute specification is composed of: - - + ProjectionType - One of the following: - - + `KEYS_ONLY` - Only the index and primary keys are projected into the - index. - + `INCLUDE` - Only the specified table attributes are projected into - the index. The list of projected attributes are in NonKeyAttributes - . - + `ALL` - All of the table attributes are projected into the index. - - + NonKeyAttributes - A list of one or more non-key attribute names that - are projected into the secondary index. The total count of - attributes specified in NonKeyAttributes , summed across all of the - secondary indexes, must not exceed 20. If you project the same - attribute into two different indexes, this counts as two distinct - attributes when determining the total. - - + ProvisionedThroughput - The provisioned throughput settings for the - global secondary index, consisting of read and write capacity - units. - - :type provisioned_throughput: dict - :param provisioned_throughput: Represents the provisioned throughput - settings for a specified table or index. The settings can be - modified using the UpdateTable operation. - For current minimum and maximum provisioned throughput values, see - `Limits`_ in the Amazon DynamoDB Developer Guide . - - """ - params = { - 'AttributeDefinitions': attribute_definitions, - 'TableName': table_name, - 'KeySchema': key_schema, - 'ProvisionedThroughput': provisioned_throughput, - } - if local_secondary_indexes is not None: - params['LocalSecondaryIndexes'] = local_secondary_indexes - if global_secondary_indexes is not None: - params['GlobalSecondaryIndexes'] = global_secondary_indexes - return self.make_request(action='CreateTable', - body=json.dumps(params)) - - def delete_item(self, table_name, key, expected=None, - conditional_operator=None, return_values=None, - return_consumed_capacity=None, - return_item_collection_metrics=None, - condition_expression=None, - expression_attribute_names=None, - expression_attribute_values=None): - """ - Deletes a single item in a table by primary key. You can - perform a conditional delete operation that deletes the item - if it exists, or if it has an expected attribute value. - - In addition to deleting an item, you can also return the - item's attribute values in the same operation, using the - ReturnValues parameter. - - Unless you specify conditions, the DeleteItem is an idempotent - operation; running it multiple times on the same item or - attribute does not result in an error response. - - Conditional deletes are useful for deleting items only if - specific conditions are met. If those conditions are met, - DynamoDB performs the delete. Otherwise, the item is not - deleted. - - :type table_name: string - :param table_name: The name of the table from which to delete the item. - - :type key: map - :param key: A map of attribute names to AttributeValue objects, - representing the primary key of the item to delete. - For the primary key, you must provide all of the attributes. For - example, with a hash type primary key, you only need to specify the - hash attribute. For a hash-and-range type primary key, you must - specify both the hash attribute and the range attribute. - - :type expected: map - :param expected: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use Expected and ConditionExpression at the same - time, DynamoDB will return a ValidationException exception. - - This parameter does not support lists or maps. - - A map of attribute/condition pairs. Expected provides a conditional - block for the DeleteItem operation. - - Each element of Expected consists of an attribute name, a comparison - operator, and one or more values. DynamoDB compares the attribute - with the value(s) you supplied, using the comparison operator. For - each Expected element, the result of the evaluation is either true - or false. - - If you specify more than one element in the Expected map, then by - default all of the conditions must evaluate to true. In other - words, the conditions are ANDed together. (You can use the - ConditionalOperator parameter to OR the conditions instead. If you - do this, then at least one of the conditions must evaluate to true, - rather than all of them.) - - If the Expected map evaluates to true, then the conditional operation - succeeds; otherwise, it fails. - - Expected contains the following: - - - + AttributeValueList - One or more values to evaluate against the - supplied attribute. The number of values in the list depends on the - ComparisonOperator being used. For type Number, value comparisons - are numeric. String value comparisons for greater than, equals, or - less than are based on ASCII character code values. For example, - `a` is greater than `A`, and `aa` is greater than `B`. For a list - of code values, see - `http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters`_. - For type Binary, DynamoDB treats each byte of the binary data as - unsigned when it compares binary values, for example when - evaluating query expressions. - + ComparisonOperator - A comparator for evaluating attributes in the - AttributeValueList . When performing the comparison, DynamoDB uses - strongly consistent reads. The following comparison operators are - available: `EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | - CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN` The following - are descriptions of each comparison operator. - - + `EQ` : Equal. `EQ` is supported for all datatypes, including lists - and maps. AttributeValueList can contain only one AttributeValue - element of type String, Number, Binary, String Set, Number Set, or - Binary Set. If an item contains an AttributeValue element of a - different type than the one specified in the request, the value - does not match. For example, `{"S":"6"}` does not equal - `{"N":"6"}`. Also, `{"N":"6"}` does not equal `{"NS":["6", "2", - "1"]}`. > <li> - + `NE` : Not equal. `NE` is supported for all datatypes, including - lists and maps. AttributeValueList can contain only one - AttributeValue of type String, Number, Binary, String Set, Number - Set, or Binary Set. If an item contains an AttributeValue of a - different type than the one specified in the request, the value - does not match. For example, `{"S":"6"}` does not equal - `{"N":"6"}`. Also, `{"N":"6"}` does not equal `{"NS":["6", "2", - "1"]}`. > <li> - + `LE` : Less than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `LT` : Less than. AttributeValueList can contain only one - AttributeValue of type String, Number, or Binary (not a set type). - If an item contains an AttributeValue element of a different type - than the one specified in the request, the value does not match. - For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GE` : Greater than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GT` : Greater than. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `NOT_NULL` : The attribute exists. `NOT_NULL` is supported for all - datatypes, including lists and maps. - + `NULL` : The attribute does not exist. `NULL` is supported for all - datatypes, including lists and maps. - + `CONTAINS` : Checks for a subsequence, or value in a set. - AttributeValueList can contain only one AttributeValue element of - type String, Number, or Binary (not a set type). If the target - attribute of the comparison is of type String, then the operator - checks for a substring match. If the target attribute of the - comparison is of type Binary, then the operator looks for a - subsequence of the target that matches the input. If the target - attribute of the comparison is a set (" `SS`", " `NS`", or " - `BS`"), then the operator evaluates to true if it finds an exact - match with any member of the set. CONTAINS is supported for lists: - When evaluating " `a CONTAINS b`", " `a`" can be a list; however, " - `b`" cannot be a set, a map, or a list. - + `NOT_CONTAINS` : Checks for absence of a subsequence, or absence of a - value in a set. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If the target attribute of the comparison is a String, then - the operator checks for the absence of a substring match. If the - target attribute of the comparison is Binary, then the operator - checks for the absence of a subsequence of the target that matches - the input. If the target attribute of the comparison is a set (" - `SS`", " `NS`", or " `BS`"), then the operator evaluates to true if - it does not find an exact match with any member of the set. - NOT_CONTAINS is supported for lists: When evaluating " `a NOT - CONTAINS b`", " `a`" can be a list; however, " `b`" cannot be a - set, a map, or a list. - + `BEGINS_WITH` : Checks for a prefix. AttributeValueList can contain - only one AttributeValue of type String or Binary (not a Number or a - set type). The target attribute of the comparison must be of type - String or Binary (not a Number or a set type). > <li> - + `IN` : Checks for matching elements within two sets. - AttributeValueList can contain one or more AttributeValue elements - of type String, Number, or Binary (not a set type). These - attributes are compared against an existing set type attribute of - an item. If any elements of the input set are present in the item - attribute, the expression evaluates to true. - + `BETWEEN` : Greater than or equal to the first value, and less than - or equal to the second value. AttributeValueList must contain two - AttributeValue elements of the same type, either String, Number, or - Binary (not a set type). A target attribute matches if the target - value is greater than, or equal to, the first element and less - than, or equal to, the second element. If an item contains an - AttributeValue element of a different type than the one specified - in the request, the value does not match. For example, `{"S":"6"}` - does not compare to `{"N":"6"}`. Also, `{"N":"6"}` does not compare - to `{"NS":["6", "2", "1"]}` - - - - For usage examples of AttributeValueList and ComparisonOperator , see - `Legacy Conditional Parameters`_ in the Amazon DynamoDB Developer - Guide . - - For backward compatibility with previous DynamoDB releases, the - following parameters can be used instead of AttributeValueList and - ComparisonOperator : - - - + Value - A value for DynamoDB to compare with an attribute. - + Exists - A Boolean value that causes DynamoDB to evaluate the value - before attempting the conditional operation: - - + If Exists is `True`, DynamoDB will check to see if that attribute - value already exists in the table. If it is found, then the - condition evaluates to true; otherwise the condition evaluate to - false. - + If Exists is `False`, DynamoDB assumes that the attribute value does - not exist in the table. If in fact the value does not exist, then - the assumption is valid and the condition evaluates to true. If the - value is found, despite the assumption that it does not exist, the - condition evaluates to false. - - - - The Value and Exists parameters are incompatible with - AttributeValueList and ComparisonOperator . Note that if you use - both sets of parameters at once, DynamoDB will return a - ValidationException exception. - - :type conditional_operator: string - :param conditional_operator: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use ConditionalOperator and ConditionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter does not support lists or maps. - - A logical operator to apply to the conditions in the Expected map: - - - + `AND` - If all of the conditions evaluate to true, then the entire - map evaluates to true. - + `OR` - If at least one of the conditions evaluate to true, then the - entire map evaluates to true. - - - If you omit ConditionalOperator , then `AND` is the default. - - The operation will succeed only if the entire map evaluates to true. - - :type return_values: string - :param return_values: - Use ReturnValues if you want to get the item attributes as they - appeared before they were deleted. For DeleteItem , the valid - values are: - - - + `NONE` - If ReturnValues is not specified, or if its value is `NONE`, - then nothing is returned. (This setting is the default for - ReturnValues .) - + `ALL_OLD` - The content of the old item is returned. - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - :type return_item_collection_metrics: string - :param return_item_collection_metrics: A value that if set to `SIZE`, - the response includes statistics about item collections, if any, - that were modified during the operation are returned in the - response. If set to `NONE` (the default), no statistics are - returned. - - :type condition_expression: string - :param condition_expression: - A condition that must be satisfied in order for a conditional - DeleteItem to succeed. - - An expression can contain any of the following: - - - + Boolean functions: `ATTRIBUTE_EXIST | CONTAINS | BEGINS_WITH` - + Comparison operators: ` = | <> | < | > | <= - | >= | BETWEEN | IN` - + Logical operators: `NOT | AND | OR` - - :type expression_attribute_names: map - :param expression_attribute_names: - One or more substitution tokens for simplifying complex expressions. - The following are some use cases for an ExpressionAttributeNames - value: - - - + To shorten an attribute name that is very long or unwieldy in an - expression. - + To create a placeholder for repeating occurrences of an attribute - name in an expression. - + To prevent special characters in an attribute name from being - misinterpreted in an expression. - - - Use the **#** character in an expression to dereference an attribute - name. For example, consider the following expression: - - - + `order.customerInfo.LastName = "Smith" OR order.customerInfo.LastName - = "Jones"` - - - Now suppose that you specified the following for - ExpressionAttributeNames : - - - + `{"n":"order.customerInfo.LastName"}` - - - The expression can now be simplified as follows: - - - + `#n = "Smith" OR #n = "Jones"` - - :type expression_attribute_values: map - :param expression_attribute_values: - One or more values that can be substituted in an expression. - - Use the **:** character in an expression to dereference an attribute - value. For example, consider the following expression: - - - + `ProductStatus IN ("Available","Backordered","Discontinued")` - - - Now suppose that you specified the following for - ExpressionAttributeValues : - - - + `{ "a":{"S":"Available"}, "b":{"S":"Backordered"}, - "d":{"S":"Discontinued"} }` - - - The expression can now be simplified as follows: - - - + `ProductStatus IN (:a,:b,:c)` - - """ - params = {'TableName': table_name, 'Key': key, } - if expected is not None: - params['Expected'] = expected - if conditional_operator is not None: - params['ConditionalOperator'] = conditional_operator - if return_values is not None: - params['ReturnValues'] = return_values - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - if return_item_collection_metrics is not None: - params['ReturnItemCollectionMetrics'] = return_item_collection_metrics - if condition_expression is not None: - params['ConditionExpression'] = condition_expression - if expression_attribute_names is not None: - params['ExpressionAttributeNames'] = expression_attribute_names - if expression_attribute_values is not None: - params['ExpressionAttributeValues'] = expression_attribute_values - return self.make_request(action='DeleteItem', - body=json.dumps(params)) - - def delete_table(self, table_name): - """ - The DeleteTable operation deletes a table and all of its - items. After a DeleteTable request, the specified table is in - the `DELETING` state until DynamoDB completes the deletion. If - the table is in the `ACTIVE` state, you can delete it. If a - table is in `CREATING` or `UPDATING` states, then DynamoDB - returns a ResourceInUseException . If the specified table does - not exist, DynamoDB returns a ResourceNotFoundException . If - table is already in the `DELETING` state, no error is - returned. - - When you delete a table, any indexes on that table are also - deleted. - - Use the DescribeTable API to check the status of the table. - - :type table_name: string - :param table_name: The name of the table to delete. - - """ - params = {'TableName': table_name, } - return self.make_request(action='DeleteTable', - body=json.dumps(params)) - - def describe_table(self, table_name): - """ - Returns information about the table, including the current - status of the table, when it was created, the primary key - schema, and any indexes on the table. - - :type table_name: string - :param table_name: The name of the table to describe. - - """ - params = {'TableName': table_name, } - return self.make_request(action='DescribeTable', - body=json.dumps(params)) - - def get_item(self, table_name, key, attributes_to_get=None, - consistent_read=None, return_consumed_capacity=None, - projection_expression=None, expression_attribute_names=None): - """ - The GetItem operation returns a set of attributes for the item - with the given primary key. If there is no matching item, - GetItem does not return any data. - - GetItem provides an eventually consistent read by default. If - your application requires a strongly consistent read, set - ConsistentRead to `True`. Although a strongly consistent read - might take more time than an eventually consistent read, it - always returns the last updated value. - - :type table_name: string - :param table_name: The name of the table containing the requested item. - - :type key: map - :param key: A map of attribute names to AttributeValue objects, - representing the primary key of the item to retrieve. - For the primary key, you must provide all of the attributes. For - example, with a hash type primary key, you only need to specify the - hash attribute. For a hash-and-range type primary key, you must - specify both the hash attribute and the range attribute. - - :type attributes_to_get: list - :param attributes_to_get: - There is a newer parameter available. Use ProjectionExpression instead. - Note that if you use AttributesToGet and ProjectionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter allows you to retrieve lists or maps; however, it cannot - retrieve individual list or map elements. - - The names of one or more attributes to retrieve. If no attribute names - are specified, then all attributes will be returned. If any of the - requested attributes are not found, they will not appear in the - result. - - Note that AttributesToGet has no effect on provisioned throughput - consumption. DynamoDB determines capacity units consumed based on - item size, not on the amount of data that is returned to an - application. - - :type consistent_read: boolean - :param consistent_read: A value that if set to `True`, then the - operation uses strongly consistent reads; otherwise, eventually - consistent reads are used. - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - :type projection_expression: string - :param projection_expression: One or more attributes to retrieve from - the table. These attributes can include scalars, sets, or elements - of a JSON document. The attributes in the expression must be - separated by commas. - If no attribute names are specified, then all attributes will be - returned. If any of the requested attributes are not found, they - will not appear in the result. - - :type expression_attribute_names: map - :param expression_attribute_names: - One or more substitution tokens for simplifying complex expressions. - The following are some use cases for an ExpressionAttributeNames - value: - - - + To shorten an attribute name that is very long or unwieldy in an - expression. - + To create a placeholder for repeating occurrences of an attribute - name in an expression. - + To prevent special characters in an attribute name from being - misinterpreted in an expression. - - - Use the **#** character in an expression to dereference an attribute - name. For example, consider the following expression: - - - + `order.customerInfo.LastName = "Smith" OR order.customerInfo.LastName - = "Jones"` - - - Now suppose that you specified the following for - ExpressionAttributeNames : - - - + `{"n":"order.customerInfo.LastName"}` - - - The expression can now be simplified as follows: - - - + `#n = "Smith" OR #n = "Jones"` - - """ - params = {'TableName': table_name, 'Key': key, } - if attributes_to_get is not None: - params['AttributesToGet'] = attributes_to_get - if consistent_read is not None: - params['ConsistentRead'] = consistent_read - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - if projection_expression is not None: - params['ProjectionExpression'] = projection_expression - if expression_attribute_names is not None: - params['ExpressionAttributeNames'] = expression_attribute_names - return self.make_request(action='GetItem', - body=json.dumps(params)) - - def list_tables(self, exclusive_start_table_name=None, limit=None): - """ - Returns an array of table names associated with the current - account and endpoint. The output from ListTables is paginated, - with each page returning a maximum of 100 table names. - - :type exclusive_start_table_name: string - :param exclusive_start_table_name: The first table name that this - operation will evaluate. Use the value that was returned for - LastEvaluatedTableName in a previous operation, so that you can - obtain the next page of results. - - :type limit: integer - :param limit: A maximum number of table names to return. If this - parameter is not specified, the limit is 100. - - """ - params = {} - if exclusive_start_table_name is not None: - params['ExclusiveStartTableName'] = exclusive_start_table_name - if limit is not None: - params['Limit'] = limit - return self.make_request(action='ListTables', - body=json.dumps(params)) - - def put_item(self, table_name, item, expected=None, return_values=None, - return_consumed_capacity=None, - return_item_collection_metrics=None, - conditional_operator=None, condition_expression=None, - expression_attribute_names=None, - expression_attribute_values=None): - """ - Creates a new item, or replaces an old item with a new item. - If an item that has the same primary key as the new item - already exists in the specified table, the new item completely - replaces the existing item. You can perform a conditional put - operation (add a new item if one with the specified primary - key doesn't exist), or replace an existing item if it has - certain attribute values. - - In addition to putting an item, you can also return the item's - attribute values in the same operation, using the ReturnValues - parameter. - - When you add an item, the primary key attribute(s) are the - only required attributes. Attribute values cannot be null. - String and Binary type attributes must have lengths greater - than zero. Set type attributes cannot be empty. Requests with - empty values will be rejected with a ValidationException - exception. - - You can request that PutItem return either a copy of the - original item (before the update) or a copy of the updated - item (after the update). For more information, see the - ReturnValues description below. - - For more information about using this API, see `Working with - Items`_ in the Amazon DynamoDB Developer Guide . - - :type table_name: string - :param table_name: The name of the table to contain the item. - - :type item: map - :param item: A map of attribute name/value pairs, one for each - attribute. Only the primary key attributes are required; you can - optionally provide other attribute name-value pairs for the item. - You must provide all of the attributes for the primary key. For - example, with a hash type primary key, you only need to specify the - hash attribute. For a hash-and-range type primary key, you must - specify both the hash attribute and the range attribute. - - If you specify any attributes that are part of an index key, then the - data types for those attributes must match those of the schema in - the table's attribute definition. - - For more information about primary keys, see `Primary Key`_ in the - Amazon DynamoDB Developer Guide . - - Each element in the Item map is an AttributeValue object. - - :type expected: map - :param expected: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use Expected and ConditionExpression at the same - time, DynamoDB will return a ValidationException exception. - - This parameter does not support lists or maps. - - A map of attribute/condition pairs. Expected provides a conditional - block for the PutItem operation. - - Each element of Expected consists of an attribute name, a comparison - operator, and one or more values. DynamoDB compares the attribute - with the value(s) you supplied, using the comparison operator. For - each Expected element, the result of the evaluation is either true - or false. - - If you specify more than one element in the Expected map, then by - default all of the conditions must evaluate to true. In other - words, the conditions are ANDed together. (You can use the - ConditionalOperator parameter to OR the conditions instead. If you - do this, then at least one of the conditions must evaluate to true, - rather than all of them.) - - If the Expected map evaluates to true, then the conditional operation - succeeds; otherwise, it fails. - - Expected contains the following: - - - + AttributeValueList - One or more values to evaluate against the - supplied attribute. The number of values in the list depends on the - ComparisonOperator being used. For type Number, value comparisons - are numeric. String value comparisons for greater than, equals, or - less than are based on ASCII character code values. For example, - `a` is greater than `A`, and `aa` is greater than `B`. For a list - of code values, see - `http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters`_. - For type Binary, DynamoDB treats each byte of the binary data as - unsigned when it compares binary values, for example when - evaluating query expressions. - + ComparisonOperator - A comparator for evaluating attributes in the - AttributeValueList . When performing the comparison, DynamoDB uses - strongly consistent reads. The following comparison operators are - available: `EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | - CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN` The following - are descriptions of each comparison operator. - - + `EQ` : Equal. `EQ` is supported for all datatypes, including lists - and maps. AttributeValueList can contain only one AttributeValue - element of type String, Number, Binary, String Set, Number Set, or - Binary Set. If an item contains an AttributeValue element of a - different type than the one specified in the request, the value - does not match. For example, `{"S":"6"}` does not equal - `{"N":"6"}`. Also, `{"N":"6"}` does not equal `{"NS":["6", "2", - "1"]}`. > <li> - + `NE` : Not equal. `NE` is supported for all datatypes, including - lists and maps. AttributeValueList can contain only one - AttributeValue of type String, Number, Binary, String Set, Number - Set, or Binary Set. If an item contains an AttributeValue of a - different type than the one specified in the request, the value - does not match. For example, `{"S":"6"}` does not equal - `{"N":"6"}`. Also, `{"N":"6"}` does not equal `{"NS":["6", "2", - "1"]}`. > <li> - + `LE` : Less than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `LT` : Less than. AttributeValueList can contain only one - AttributeValue of type String, Number, or Binary (not a set type). - If an item contains an AttributeValue element of a different type - than the one specified in the request, the value does not match. - For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GE` : Greater than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GT` : Greater than. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `NOT_NULL` : The attribute exists. `NOT_NULL` is supported for all - datatypes, including lists and maps. - + `NULL` : The attribute does not exist. `NULL` is supported for all - datatypes, including lists and maps. - + `CONTAINS` : Checks for a subsequence, or value in a set. - AttributeValueList can contain only one AttributeValue element of - type String, Number, or Binary (not a set type). If the target - attribute of the comparison is of type String, then the operator - checks for a substring match. If the target attribute of the - comparison is of type Binary, then the operator looks for a - subsequence of the target that matches the input. If the target - attribute of the comparison is a set (" `SS`", " `NS`", or " - `BS`"), then the operator evaluates to true if it finds an exact - match with any member of the set. CONTAINS is supported for lists: - When evaluating " `a CONTAINS b`", " `a`" can be a list; however, " - `b`" cannot be a set, a map, or a list. - + `NOT_CONTAINS` : Checks for absence of a subsequence, or absence of a - value in a set. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If the target attribute of the comparison is a String, then - the operator checks for the absence of a substring match. If the - target attribute of the comparison is Binary, then the operator - checks for the absence of a subsequence of the target that matches - the input. If the target attribute of the comparison is a set (" - `SS`", " `NS`", or " `BS`"), then the operator evaluates to true if - it does not find an exact match with any member of the set. - NOT_CONTAINS is supported for lists: When evaluating " `a NOT - CONTAINS b`", " `a`" can be a list; however, " `b`" cannot be a - set, a map, or a list. - + `BEGINS_WITH` : Checks for a prefix. AttributeValueList can contain - only one AttributeValue of type String or Binary (not a Number or a - set type). The target attribute of the comparison must be of type - String or Binary (not a Number or a set type). > <li> - + `IN` : Checks for matching elements within two sets. - AttributeValueList can contain one or more AttributeValue elements - of type String, Number, or Binary (not a set type). These - attributes are compared against an existing set type attribute of - an item. If any elements of the input set are present in the item - attribute, the expression evaluates to true. - + `BETWEEN` : Greater than or equal to the first value, and less than - or equal to the second value. AttributeValueList must contain two - AttributeValue elements of the same type, either String, Number, or - Binary (not a set type). A target attribute matches if the target - value is greater than, or equal to, the first element and less - than, or equal to, the second element. If an item contains an - AttributeValue element of a different type than the one specified - in the request, the value does not match. For example, `{"S":"6"}` - does not compare to `{"N":"6"}`. Also, `{"N":"6"}` does not compare - to `{"NS":["6", "2", "1"]}` - - - - For usage examples of AttributeValueList and ComparisonOperator , see - `Legacy Conditional Parameters`_ in the Amazon DynamoDB Developer - Guide . - - For backward compatibility with previous DynamoDB releases, the - following parameters can be used instead of AttributeValueList and - ComparisonOperator : - - - + Value - A value for DynamoDB to compare with an attribute. - + Exists - A Boolean value that causes DynamoDB to evaluate the value - before attempting the conditional operation: - - + If Exists is `True`, DynamoDB will check to see if that attribute - value already exists in the table. If it is found, then the - condition evaluates to true; otherwise the condition evaluate to - false. - + If Exists is `False`, DynamoDB assumes that the attribute value does - not exist in the table. If in fact the value does not exist, then - the assumption is valid and the condition evaluates to true. If the - value is found, despite the assumption that it does not exist, the - condition evaluates to false. - - - - The Value and Exists parameters are incompatible with - AttributeValueList and ComparisonOperator . Note that if you use - both sets of parameters at once, DynamoDB will return a - ValidationException exception. - - :type return_values: string - :param return_values: - Use ReturnValues if you want to get the item attributes as they - appeared before they were updated with the PutItem request. For - PutItem , the valid values are: - - - + `NONE` - If ReturnValues is not specified, or if its value is `NONE`, - then nothing is returned. (This setting is the default for - ReturnValues .) - + `ALL_OLD` - If PutItem overwrote an attribute name-value pair, then - the content of the old item is returned. - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - :type return_item_collection_metrics: string - :param return_item_collection_metrics: A value that if set to `SIZE`, - the response includes statistics about item collections, if any, - that were modified during the operation are returned in the - response. If set to `NONE` (the default), no statistics are - returned. - - :type conditional_operator: string - :param conditional_operator: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use ConditionalOperator and ConditionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter does not support lists or maps. - - A logical operator to apply to the conditions in the Expected map: - - - + `AND` - If all of the conditions evaluate to true, then the entire - map evaluates to true. - + `OR` - If at least one of the conditions evaluate to true, then the - entire map evaluates to true. - - - If you omit ConditionalOperator , then `AND` is the default. - - The operation will succeed only if the entire map evaluates to true. - - :type condition_expression: string - :param condition_expression: - A condition that must be satisfied in order for a conditional PutItem - operation to succeed. - - An expression can contain any of the following: - - - + Boolean functions: `ATTRIBUTE_EXIST | CONTAINS | BEGINS_WITH` - + Comparison operators: ` = | <> | < | > | <= - | >= | BETWEEN | IN` - + Logical operators: `NOT | AND | OR` - - :type expression_attribute_names: map - :param expression_attribute_names: - One or more substitution tokens for simplifying complex expressions. - The following are some use cases for an ExpressionAttributeNames - value: - - - + To shorten an attribute name that is very long or unwieldy in an - expression. - + To create a placeholder for repeating occurrences of an attribute - name in an expression. - + To prevent special characters in an attribute name from being - misinterpreted in an expression. - - - Use the **#** character in an expression to dereference an attribute - name. For example, consider the following expression: - - - + `order.customerInfo.LastName = "Smith" OR order.customerInfo.LastName - = "Jones"` - - - Now suppose that you specified the following for - ExpressionAttributeNames : - - - + `{"n":"order.customerInfo.LastName"}` - - - The expression can now be simplified as follows: - - - + `#n = "Smith" OR #n = "Jones"` - - :type expression_attribute_values: map - :param expression_attribute_values: - One or more values that can be substituted in an expression. - - Use the **:** character in an expression to dereference an attribute - value. For example, consider the following expression: - - - + `ProductStatus IN ("Available","Backordered","Discontinued")` - - - Now suppose that you specified the following for - ExpressionAttributeValues : - - - + `{ "a":{"S":"Available"}, "b":{"S":"Backordered"}, - "d":{"S":"Discontinued"} }` - - - The expression can now be simplified as follows: - - - + `ProductStatus IN (:a,:b,:c)` - - """ - params = {'TableName': table_name, 'Item': item, } - if expected is not None: - params['Expected'] = expected - if return_values is not None: - params['ReturnValues'] = return_values - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - if return_item_collection_metrics is not None: - params['ReturnItemCollectionMetrics'] = return_item_collection_metrics - if conditional_operator is not None: - params['ConditionalOperator'] = conditional_operator - if condition_expression is not None: - params['ConditionExpression'] = condition_expression - if expression_attribute_names is not None: - params['ExpressionAttributeNames'] = expression_attribute_names - if expression_attribute_values is not None: - params['ExpressionAttributeValues'] = expression_attribute_values - return self.make_request(action='PutItem', - body=json.dumps(params)) - - def query(self, table_name, key_conditions, index_name=None, select=None, - attributes_to_get=None, limit=None, consistent_read=None, - query_filter=None, conditional_operator=None, - scan_index_forward=None, exclusive_start_key=None, - return_consumed_capacity=None, projection_expression=None, - filter_expression=None, expression_attribute_names=None, - expression_attribute_values=None): - """ - A Query operation directly accesses items from a table using - the table primary key, or from an index using the index key. - You must provide a specific hash key value. You can narrow the - scope of the query by using comparison operators on the range - key value, or on the index key. You can use the - ScanIndexForward parameter to get results in forward or - reverse order, by range key or by index key. - - Queries that do not return results consume the minimum number - of read capacity units for that type of read operation. - - If the total number of items meeting the query criteria - exceeds the result set size limit of 1 MB, the query stops and - results are returned to the user with LastEvaluatedKey to - continue the query in a subsequent operation. Unlike a Scan - operation, a Query operation never returns both an empty - result set and a LastEvaluatedKey . The LastEvaluatedKey is - only provided if the results exceed 1 MB, or if you have used - Limit . - - You can query a table, a local secondary index, or a global - secondary index. For a query on a table or on a local - secondary index, you can set ConsistentRead to true and obtain - a strongly consistent result. Global secondary indexes support - eventually consistent reads only, so do not specify - ConsistentRead when querying a global secondary index. - - :type table_name: string - :param table_name: The name of the table containing the requested - items. - - :type index_name: string - :param index_name: The name of an index to query. This index can be any - local secondary index or global secondary index on the table. - - :type select: string - :param select: The attributes to be returned in the result. You can - retrieve all item attributes, specific item attributes, the count - of matching items, or in the case of an index, some or all of the - attributes projected into the index. - - + `ALL_ATTRIBUTES` - Returns all of the item attributes from the - specified table or index. If you query a local secondary index, - then for each matching item in the index DynamoDB will fetch the - entire item from the parent table. If the index is configured to - project all item attributes, then all of the data can be obtained - from the local secondary index, and no fetching is required. - + `ALL_PROJECTED_ATTRIBUTES` - Allowed only when querying an index. - Retrieves all attributes that have been projected into the index. - If the index is configured to project all attributes, this return - value is equivalent to specifying `ALL_ATTRIBUTES`. - + `COUNT` - Returns the number of matching items, rather than the - matching items themselves. - + `SPECIFIC_ATTRIBUTES` - Returns only the attributes listed in - AttributesToGet . This return value is equivalent to specifying - AttributesToGet without specifying any value for Select . If you - query a local secondary index and request only attributes that are - projected into that index, the operation will read only the index - and not the table. If any of the requested attributes are not - projected into the local secondary index, DynamoDB will fetch each - of these attributes from the parent table. This extra fetching - incurs additional throughput cost and latency. If you query a - global secondary index, you can only request attributes that are - projected into the index. Global secondary index queries cannot - fetch attributes from the parent table. - - - If neither Select nor AttributesToGet are specified, DynamoDB defaults - to `ALL_ATTRIBUTES` when accessing a table, and - `ALL_PROJECTED_ATTRIBUTES` when accessing an index. You cannot use - both Select and AttributesToGet together in a single request, - unless the value for Select is `SPECIFIC_ATTRIBUTES`. (This usage - is equivalent to specifying AttributesToGet without any value for - Select .) - - :type attributes_to_get: list - :param attributes_to_get: - There is a newer parameter available. Use ProjectionExpression instead. - Note that if you use AttributesToGet and ProjectionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter allows you to retrieve lists or maps; however, it cannot - retrieve individual list or map elements. - - The names of one or more attributes to retrieve. If no attribute names - are specified, then all attributes will be returned. If any of the - requested attributes are not found, they will not appear in the - result. - - Note that AttributesToGet has no effect on provisioned throughput - consumption. DynamoDB determines capacity units consumed based on - item size, not on the amount of data that is returned to an - application. - - You cannot use both AttributesToGet and Select together in a Query - request, unless the value for Select is `SPECIFIC_ATTRIBUTES`. - (This usage is equivalent to specifying AttributesToGet without any - value for Select .) - - If you query a local secondary index and request only attributes that - are projected into that index, the operation will read only the - index and not the table. If any of the requested attributes are not - projected into the local secondary index, DynamoDB will fetch each - of these attributes from the parent table. This extra fetching - incurs additional throughput cost and latency. - - If you query a global secondary index, you can only request attributes - that are projected into the index. Global secondary index queries - cannot fetch attributes from the parent table. - - :type limit: integer - :param limit: The maximum number of items to evaluate (not necessarily - the number of matching items). If DynamoDB processes the number of - items up to the limit while processing the results, it stops the - operation and returns the matching values up to that point, and a - key in LastEvaluatedKey to apply in a subsequent operation, so that - you can pick up where you left off. Also, if the processed data set - size exceeds 1 MB before DynamoDB reaches this limit, it stops the - operation and returns the matching values up to the limit, and a - key in LastEvaluatedKey to apply in a subsequent operation to - continue the operation. For more information, see `Query and Scan`_ - in the Amazon DynamoDB Developer Guide . - - :type consistent_read: boolean - :param consistent_read: A value that if set to `True`, then the - operation uses strongly consistent reads; otherwise, eventually - consistent reads are used. - Strongly consistent reads are not supported on global secondary - indexes. If you query a global secondary index with ConsistentRead - set to `True`, you will receive an error message. - - :type key_conditions: map - :param key_conditions: The selection criteria for the query. For a - query on a table, you can have conditions only on the table primary - key attributes. You must specify the hash key attribute name and - value as an `EQ` condition. You can optionally specify a second - condition, referring to the range key attribute. - For a query on an index, you can have conditions only on the index key - attributes. You must specify the index hash attribute name and - value as an EQ condition. You can optionally specify a second - condition, referring to the index key range attribute. - - Each KeyConditions element consists of an attribute name to compare, - along with the following: - - - + AttributeValueList - One or more values to evaluate against the - supplied attribute. The number of values in the list depends on the - ComparisonOperator being used. For type Number, value comparisons - are numeric. String value comparisons for greater than, equals, or - less than are based on ASCII character code values. For example, - `a` is greater than `A`, and `aa` is greater than `B`. For a list - of code values, see - `http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters`_. - For Binary, DynamoDB treats each byte of the binary data as - unsigned when it compares binary values, for example when - evaluating query expressions. - + ComparisonOperator - A comparator for evaluating attributes, for - example, equals, greater than, less than, and so on. For - KeyConditions , only the following comparison operators are - supported: `EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN` The - following are descriptions of these comparison operators. - - + `EQ` : Equal. AttributeValueList can contain only one AttributeValue - of type String, Number, or Binary (not a set type). If an item - contains an AttributeValue element of a different type than the one - specified in the request, the value does not match. For example, - `{"S":"6"}` does not equal `{"N":"6"}`. Also, `{"N":"6"}` does not - equal `{"NS":["6", "2", "1"]}`. - + `LE` : Less than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `LT` : Less than. AttributeValueList can contain only one - AttributeValue of type String, Number, or Binary (not a set type). - If an item contains an AttributeValue element of a different type - than the one specified in the request, the value does not match. - For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GE` : Greater than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GT` : Greater than. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `BEGINS_WITH` : Checks for a prefix. AttributeValueList can contain - only one AttributeValue of type String or Binary (not a Number or a - set type). The target attribute of the comparison must be of type - String or Binary (not a Number or a set type). > <li> - + `BETWEEN` : Greater than or equal to the first value, and less than - or equal to the second value. AttributeValueList must contain two - AttributeValue elements of the same type, either String, Number, or - Binary (not a set type). A target attribute matches if the target - value is greater than, or equal to, the first element and less - than, or equal to, the second element. If an item contains an - AttributeValue element of a different type than the one specified - in the request, the value does not match. For example, `{"S":"6"}` - does not compare to `{"N":"6"}`. Also, `{"N":"6"}` does not compare - to `{"NS":["6", "2", "1"]}` - - - - For usage examples of AttributeValueList and ComparisonOperator , see - `Legacy Conditional Parameters`_ in the Amazon DynamoDB Developer - Guide . - - :type query_filter: map - :param query_filter: - There is a newer parameter available. Use FilterExpression instead. - Note that if you use QueryFilter and FilterExpression at the same - time, DynamoDB will return a ValidationException exception. - - This parameter does not support lists or maps. - - A condition that evaluates the query results and returns only the - desired values. - - If you specify more than one condition in the QueryFilter map, then by - default all of the conditions must evaluate to true. In other - words, the conditions are ANDed together. (You can use the - ConditionalOperator parameter to OR the conditions instead. If you - do this, then at least one of the conditions must evaluate to true, - rather than all of them.) - - Each QueryFilter element consists of an attribute name to compare, - along with the following: - - - + AttributeValueList - One or more values to evaluate against the - supplied attribute. The number of values in the list depends on the - operator specified in ComparisonOperator . For type Number, value - comparisons are numeric. String value comparisons for greater than, - equals, or less than are based on ASCII character code values. For - example, `a` is greater than `A`, and `aa` is greater than `B`. For - a list of code values, see - `http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters`_. - For type Binary, DynamoDB treats each byte of the binary data as - unsigned when it compares binary values, for example when - evaluating query expressions. For information on specifying data - types in JSON, see `JSON Data Format`_ in the Amazon DynamoDB - Developer Guide . - + ComparisonOperator - A comparator for evaluating attributes. For - example, equals, greater than, less than, etc. The following - comparison operators are available: `EQ | NE | LE | LT | GE | GT | - NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | - BETWEEN` For complete descriptions of all comparison operators, see - `API_Condition.html`_. - - :type conditional_operator: string - :param conditional_operator: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use ConditionalOperator and ConditionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter does not support lists or maps. - - A logical operator to apply to the conditions in the QueryFilter map: - - - + `AND` - If all of the conditions evaluate to true, then the entire - map evaluates to true. - + `OR` - If at least one of the conditions evaluate to true, then the - entire map evaluates to true. - - - If you omit ConditionalOperator , then `AND` is the default. - - The operation will succeed only if the entire map evaluates to true. - - :type scan_index_forward: boolean - :param scan_index_forward: A value that specifies ascending (true) or - descending (false) traversal of the index. DynamoDB returns results - reflecting the requested order determined by the range key. If the - data type is Number, the results are returned in numeric order. For - type String, the results are returned in order of ASCII character - code values. For type Binary, DynamoDB treats each byte of the - binary data as unsigned when it compares binary values. - If ScanIndexForward is not specified, the results are returned in - ascending order. - - :type exclusive_start_key: map - :param exclusive_start_key: The primary key of the first item that this - operation will evaluate. Use the value that was returned for - LastEvaluatedKey in the previous operation. - The data type for ExclusiveStartKey must be String, Number or Binary. - No set data types are allowed. - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - :type projection_expression: string - :param projection_expression: One or more attributes to retrieve from - the table. These attributes can include scalars, sets, or elements - of a JSON document. The attributes in the expression must be - separated by commas. - If no attribute names are specified, then all attributes will be - returned. If any of the requested attributes are not found, they - will not appear in the result. - - :type filter_expression: string - :param filter_expression: A condition that evaluates the query results - and returns only the desired values. - The condition you specify is applied to the items queried; any items - that do not match the expression are not returned. - - :type expression_attribute_names: map - :param expression_attribute_names: - One or more substitution tokens for simplifying complex expressions. - The following are some use cases for an ExpressionAttributeNames - value: - - - + To shorten an attribute name that is very long or unwieldy in an - expression. - + To create a placeholder for repeating occurrences of an attribute - name in an expression. - + To prevent special characters in an attribute name from being - misinterpreted in an expression. - - - Use the **#** character in an expression to dereference an attribute - name. For example, consider the following expression: - - - + `order.customerInfo.LastName = "Smith" OR order.customerInfo.LastName - = "Jones"` - - - Now suppose that you specified the following for - ExpressionAttributeNames : - - - + `{"n":"order.customerInfo.LastName"}` - - - The expression can now be simplified as follows: - - - + `#n = "Smith" OR #n = "Jones"` - - :type expression_attribute_values: map - :param expression_attribute_values: - One or more values that can be substituted in an expression. - - Use the **:** character in an expression to dereference an attribute - value. For example, consider the following expression: - - - + `ProductStatus IN ("Available","Backordered","Discontinued")` - - - Now suppose that you specified the following for - ExpressionAttributeValues : - - - + `{ "a":{"S":"Available"}, "b":{"S":"Backordered"}, - "d":{"S":"Discontinued"} }` - - - The expression can now be simplified as follows: - - - + `ProductStatus IN (:a,:b,:c)` - - """ - params = { - 'TableName': table_name, - 'KeyConditions': key_conditions, - } - if index_name is not None: - params['IndexName'] = index_name - if select is not None: - params['Select'] = select - if attributes_to_get is not None: - params['AttributesToGet'] = attributes_to_get - if limit is not None: - params['Limit'] = limit - if consistent_read is not None: - params['ConsistentRead'] = consistent_read - if query_filter is not None: - params['QueryFilter'] = query_filter - if conditional_operator is not None: - params['ConditionalOperator'] = conditional_operator - if scan_index_forward is not None: - params['ScanIndexForward'] = scan_index_forward - if exclusive_start_key is not None: - params['ExclusiveStartKey'] = exclusive_start_key - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - if projection_expression is not None: - params['ProjectionExpression'] = projection_expression - if filter_expression is not None: - params['FilterExpression'] = filter_expression - if expression_attribute_names is not None: - params['ExpressionAttributeNames'] = expression_attribute_names - if expression_attribute_values is not None: - params['ExpressionAttributeValues'] = expression_attribute_values - return self.make_request(action='Query', - body=json.dumps(params)) - - def scan(self, table_name, attributes_to_get=None, limit=None, - select=None, scan_filter=None, conditional_operator=None, - exclusive_start_key=None, return_consumed_capacity=None, - total_segments=None, segment=None, projection_expression=None, - filter_expression=None, expression_attribute_names=None, - expression_attribute_values=None): - """ - The Scan operation returns one or more items and item - attributes by accessing every item in the table. To have - DynamoDB return fewer items, you can provide a ScanFilter - operation. - - If the total number of scanned items exceeds the maximum data - set size limit of 1 MB, the scan stops and results are - returned to the user as a LastEvaluatedKey value to continue - the scan in a subsequent operation. The results also include - the number of items exceeding the limit. A scan can result in - no table data meeting the filter criteria. - - The result set is eventually consistent. - - By default, Scan operations proceed sequentially; however, for - faster performance on large tables, applications can request a - parallel Scan operation by specifying the Segment and - TotalSegments parameters. For more information, see `Parallel - Scan`_ in the Amazon DynamoDB Developer Guide . - - :type table_name: string - :param table_name: The name of the table containing the requested - items. - - :type attributes_to_get: list - :param attributes_to_get: - There is a newer parameter available. Use ProjectionExpression instead. - Note that if you use AttributesToGet and ProjectionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter allows you to retrieve lists or maps; however, it cannot - retrieve individual list or map elements. - - The names of one or more attributes to retrieve. If no attribute names - are specified, then all attributes will be returned. If any of the - requested attributes are not found, they will not appear in the - result. - - Note that AttributesToGet has no effect on provisioned throughput - consumption. DynamoDB determines capacity units consumed based on - item size, not on the amount of data that is returned to an - application. - - :type limit: integer - :param limit: The maximum number of items to evaluate (not necessarily - the number of matching items). If DynamoDB processes the number of - items up to the limit while processing the results, it stops the - operation and returns the matching values up to that point, and a - key in LastEvaluatedKey to apply in a subsequent operation, so that - you can pick up where you left off. Also, if the processed data set - size exceeds 1 MB before DynamoDB reaches this limit, it stops the - operation and returns the matching values up to the limit, and a - key in LastEvaluatedKey to apply in a subsequent operation to - continue the operation. For more information, see `Query and Scan`_ - in the Amazon DynamoDB Developer Guide . - - :type select: string - :param select: The attributes to be returned in the result. You can - retrieve all item attributes, specific item attributes, or the - count of matching items. - - + `ALL_ATTRIBUTES` - Returns all of the item attributes. - + `COUNT` - Returns the number of matching items, rather than the - matching items themselves. - + `SPECIFIC_ATTRIBUTES` - Returns only the attributes listed in - AttributesToGet . This return value is equivalent to specifying - AttributesToGet without specifying any value for Select . - - - If neither Select nor AttributesToGet are specified, DynamoDB defaults - to `ALL_ATTRIBUTES`. You cannot use both AttributesToGet and Select - together in a single request, unless the value for Select is - `SPECIFIC_ATTRIBUTES`. (This usage is equivalent to specifying - AttributesToGet without any value for Select .) - - :type scan_filter: map - :param scan_filter: - There is a newer parameter available. Use FilterExpression instead. - Note that if you use ScanFilter and FilterExpression at the same - time, DynamoDB will return a ValidationException exception. - - This parameter does not support lists or maps. - - A condition that evaluates the scan results and returns only the - desired values. - - If you specify more than one condition in the ScanFilter map, then by - default all of the conditions must evaluate to true. In other - words, the conditions are ANDed together. (You can use the - ConditionalOperator parameter to OR the conditions instead. If you - do this, then at least one of the conditions must evaluate to true, - rather than all of them.) - - Each ScanFilter element consists of an attribute name to compare, along - with the following: - - - + AttributeValueList - One or more values to evaluate against the - supplied attribute. The number of values in the list depends on the - operator specified in ComparisonOperator . For type Number, value - comparisons are numeric. String value comparisons for greater than, - equals, or less than are based on ASCII character code values. For - example, `a` is greater than `A`, and `aa` is greater than `B`. For - a list of code values, see - `http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters`_. - For Binary, DynamoDB treats each byte of the binary data as - unsigned when it compares binary values, for example when - evaluating query expressions. For information on specifying data - types in JSON, see `JSON Data Format`_ in the Amazon DynamoDB - Developer Guide . - + ComparisonOperator - A comparator for evaluating attributes. For - example, equals, greater than, less than, etc. The following - comparison operators are available: `EQ | NE | LE | LT | GE | GT | - NOT_NULL | NULL | CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | - BETWEEN` For complete descriptions of all comparison operators, see - `Condition`_. - - :type conditional_operator: string - :param conditional_operator: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use ConditionalOperator and ConditionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter does not support lists or maps. - - A logical operator to apply to the conditions in the ScanFilter map: - - - + `AND` - If all of the conditions evaluate to true, then the entire - map evaluates to true. - + `OR` - If at least one of the conditions evaluate to true, then the - entire map evaluates to true. - - - If you omit ConditionalOperator , then `AND` is the default. - - The operation will succeed only if the entire map evaluates to true. - - :type exclusive_start_key: map - :param exclusive_start_key: The primary key of the first item that this - operation will evaluate. Use the value that was returned for - LastEvaluatedKey in the previous operation. - The data type for ExclusiveStartKey must be String, Number or Binary. - No set data types are allowed. - - In a parallel scan, a Scan request that includes ExclusiveStartKey must - specify the same segment whose previous Scan returned the - corresponding value of LastEvaluatedKey . - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - :type total_segments: integer - :param total_segments: For a parallel Scan request, TotalSegments - represents the total number of segments into which the Scan - operation will be divided. The value of TotalSegments corresponds - to the number of application workers that will perform the parallel - scan. For example, if you want to scan a table using four - application threads, specify a TotalSegments value of 4. - The value for TotalSegments must be greater than or equal to 1, and - less than or equal to 1000000. If you specify a TotalSegments value - of 1, the Scan operation will be sequential rather than parallel. - - If you specify TotalSegments , you must also specify Segment . - - :type segment: integer - :param segment: For a parallel Scan request, Segment identifies an - individual segment to be scanned by an application worker. - Segment IDs are zero-based, so the first segment is always 0. For - example, if you want to scan a table using four application - threads, the first thread specifies a Segment value of 0, the - second thread specifies 1, and so on. - - The value of LastEvaluatedKey returned from a parallel Scan request - must be used as ExclusiveStartKey with the same segment ID in a - subsequent Scan operation. - - The value for Segment must be greater than or equal to 0, and less than - the value provided for TotalSegments . - - If you specify Segment , you must also specify TotalSegments . - - :type projection_expression: string - :param projection_expression: One or more attributes to retrieve from - the table. These attributes can include scalars, sets, or elements - of a JSON document. The attributes in the expression must be - separated by commas. - If no attribute names are specified, then all attributes will be - returned. If any of the requested attributes are not found, they - will not appear in the result. - - :type filter_expression: string - :param filter_expression: A condition that evaluates the scan results - and returns only the desired values. - The condition you specify is applied to the items scanned; any items - that do not match the expression are not returned. - - :type expression_attribute_names: map - :param expression_attribute_names: - One or more substitution tokens for simplifying complex expressions. - The following are some use cases for an ExpressionAttributeNames - value: - - - + To shorten an attribute name that is very long or unwieldy in an - expression. - + To create a placeholder for repeating occurrences of an attribute - name in an expression. - + To prevent special characters in an attribute name from being - misinterpreted in an expression. - - - Use the **#** character in an expression to dereference an attribute - name. For example, consider the following expression: - - - + `order.customerInfo.LastName = "Smith" OR order.customerInfo.LastName - = "Jones"` - - - Now suppose that you specified the following for - ExpressionAttributeNames : - - - + `{"n":"order.customerInfo.LastName"}` - - - The expression can now be simplified as follows: - - - + `#n = "Smith" OR #n = "Jones"` - - :type expression_attribute_values: map - :param expression_attribute_values: - One or more values that can be substituted in an expression. - - Use the **:** character in an expression to dereference an attribute - value. For example, consider the following expression: - - - + `ProductStatus IN ("Available","Backordered","Discontinued")` - - - Now suppose that you specified the following for - ExpressionAttributeValues : - - - + `{ "a":{"S":"Available"}, "b":{"S":"Backordered"}, - "d":{"S":"Discontinued"} }` - - - The expression can now be simplified as follows: - - - + `ProductStatus IN (:a,:b,:c)` - - """ - params = {'TableName': table_name, } - if attributes_to_get is not None: - params['AttributesToGet'] = attributes_to_get - if limit is not None: - params['Limit'] = limit - if select is not None: - params['Select'] = select - if scan_filter is not None: - params['ScanFilter'] = scan_filter - if conditional_operator is not None: - params['ConditionalOperator'] = conditional_operator - if exclusive_start_key is not None: - params['ExclusiveStartKey'] = exclusive_start_key - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - if total_segments is not None: - params['TotalSegments'] = total_segments - if segment is not None: - params['Segment'] = segment - if projection_expression is not None: - params['ProjectionExpression'] = projection_expression - if filter_expression is not None: - params['FilterExpression'] = filter_expression - if expression_attribute_names is not None: - params['ExpressionAttributeNames'] = expression_attribute_names - if expression_attribute_values is not None: - params['ExpressionAttributeValues'] = expression_attribute_values - return self.make_request(action='Scan', - body=json.dumps(params)) - - def update_item(self, table_name, key, attribute_updates=None, - expected=None, conditional_operator=None, - return_values=None, return_consumed_capacity=None, - return_item_collection_metrics=None, - update_expression=None, condition_expression=None, - expression_attribute_names=None, - expression_attribute_values=None): - """ - Edits an existing item's attributes, or adds a new item to the - table if it does not already exist. You can put, delete, or - add attribute values. You can also perform a conditional - update (insert a new attribute name-value pair if it doesn't - exist, or replace an existing name-value pair if it has - certain expected attribute values). - - You can also return the item's attribute values in the same - UpdateItem operation using the ReturnValues parameter. - - :type table_name: string - :param table_name: The name of the table containing the item to update. - - :type key: map - :param key: The primary key of the item to be updated. Each element - consists of an attribute name and a value for that attribute. - For the primary key, you must provide all of the attributes. For - example, with a hash type primary key, you only need to specify the - hash attribute. For a hash-and-range type primary key, you must - specify both the hash attribute and the range attribute. - - :type attribute_updates: map - :param attribute_updates: - There is a newer parameter available. Use UpdateExpression instead. - Note that if you use AttributeUpdates and UpdateExpression at the - same time, DynamoDB will return a ValidationException exception. - - This parameter can be used for modifying top-level attributes; however, - it does not support individual list or map elements. - - The names of attributes to be modified, the action to perform on each, - and the new value for each. If you are updating an attribute that - is an index key attribute for any indexes on that table, the - attribute type must match the index key type defined in the - AttributesDefinition of the table description. You can use - UpdateItem to update any nonkey attributes. - - Attribute values cannot be null. String and Binary type attributes must - have lengths greater than zero. Set type attributes must not be - empty. Requests with empty values will be rejected with a - ValidationException exception. - - Each AttributeUpdates element consists of an attribute name to modify, - along with the following: - - - + Value - The new value, if applicable, for this attribute. - + Action - A value that specifies how to perform the update. This - action is only valid for an existing attribute whose data type is - Number or is a set; do not use `ADD` for other data types. If an - item with the specified primary key is found in the table, the - following values perform the following actions: - - + `PUT` - Adds the specified attribute to the item. If the attribute - already exists, it is replaced by the new value. - + `DELETE` - Removes the attribute and its value, if no value is - specified for `DELETE`. The data type of the specified value must - match the existing value's data type. If a set of values is - specified, then those values are subtracted from the old set. For - example, if the attribute value was the set `[a,b,c]` and the - `DELETE` action specifies `[a,c]`, then the final attribute value - is `[b]`. Specifying an empty set is an error. - + `ADD` - Adds the specified value to the item, if the attribute does - not already exist. If the attribute does exist, then the behavior - of `ADD` depends on the data type of the attribute: - - + If the existing attribute is a number, and if Value is also a number, - then Value is mathematically added to the existing attribute. If - Value is a negative number, then it is subtracted from the existing - attribute. - + If the existing data type is a set, and if Value is also a set, then - Value is appended to the existing set. For example, if the - attribute value is the set `[1,2]`, and the `ADD` action specified - `[3]`, then the final attribute value is `[1,2,3]`. An error occurs - if an `ADD` action is specified for a set attribute and the - attribute type specified does not match the existing set type. Both - sets must have the same primitive data type. For example, if the - existing data type is a set of strings, Value must also be a set of - strings. - - If no item with the specified key is found in the table, the following - values perform the following actions: - - + `PUT` - Causes DynamoDB to create a new item with the specified - primary key, and then adds the attribute. - + `DELETE` - Causes nothing to happen; there is no attribute to delete. - + `ADD` - Causes DynamoDB to creat an item with the supplied primary - key and number (or set of numbers) for the attribute value. The - only data types allowed are Number and Number Set. - - - - If you specify any attributes that are part of an index key, then the - data types for those attributes must match those of the schema in - the table's attribute definition. - - :type expected: map - :param expected: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use Expected and ConditionExpression at the same - time, DynamoDB will return a ValidationException exception. - - This parameter does not support lists or maps. - - A map of attribute/condition pairs. Expected provides a conditional - block for the UpdateItem operation. - - Each element of Expected consists of an attribute name, a comparison - operator, and one or more values. DynamoDB compares the attribute - with the value(s) you supplied, using the comparison operator. For - each Expected element, the result of the evaluation is either true - or false. - - If you specify more than one element in the Expected map, then by - default all of the conditions must evaluate to true. In other - words, the conditions are ANDed together. (You can use the - ConditionalOperator parameter to OR the conditions instead. If you - do this, then at least one of the conditions must evaluate to true, - rather than all of them.) - - If the Expected map evaluates to true, then the conditional operation - succeeds; otherwise, it fails. - - Expected contains the following: - - - + AttributeValueList - One or more values to evaluate against the - supplied attribute. The number of values in the list depends on the - ComparisonOperator being used. For type Number, value comparisons - are numeric. String value comparisons for greater than, equals, or - less than are based on ASCII character code values. For example, - `a` is greater than `A`, and `aa` is greater than `B`. For a list - of code values, see - `http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters`_. - For type Binary, DynamoDB treats each byte of the binary data as - unsigned when it compares binary values, for example when - evaluating query expressions. - + ComparisonOperator - A comparator for evaluating attributes in the - AttributeValueList . When performing the comparison, DynamoDB uses - strongly consistent reads. The following comparison operators are - available: `EQ | NE | LE | LT | GE | GT | NOT_NULL | NULL | - CONTAINS | NOT_CONTAINS | BEGINS_WITH | IN | BETWEEN` The following - are descriptions of each comparison operator. - - + `EQ` : Equal. `EQ` is supported for all datatypes, including lists - and maps. AttributeValueList can contain only one AttributeValue - element of type String, Number, Binary, String Set, Number Set, or - Binary Set. If an item contains an AttributeValue element of a - different type than the one specified in the request, the value - does not match. For example, `{"S":"6"}` does not equal - `{"N":"6"}`. Also, `{"N":"6"}` does not equal `{"NS":["6", "2", - "1"]}`. > <li> - + `NE` : Not equal. `NE` is supported for all datatypes, including - lists and maps. AttributeValueList can contain only one - AttributeValue of type String, Number, Binary, String Set, Number - Set, or Binary Set. If an item contains an AttributeValue of a - different type than the one specified in the request, the value - does not match. For example, `{"S":"6"}` does not equal - `{"N":"6"}`. Also, `{"N":"6"}` does not equal `{"NS":["6", "2", - "1"]}`. > <li> - + `LE` : Less than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `LT` : Less than. AttributeValueList can contain only one - AttributeValue of type String, Number, or Binary (not a set type). - If an item contains an AttributeValue element of a different type - than the one specified in the request, the value does not match. - For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GE` : Greater than or equal. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `GT` : Greater than. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If an item contains an AttributeValue element of a different - type than the one specified in the request, the value does not - match. For example, `{"S":"6"}` does not equal `{"N":"6"}`. Also, - `{"N":"6"}` does not compare to `{"NS":["6", "2", "1"]}`. > <li> - + `NOT_NULL` : The attribute exists. `NOT_NULL` is supported for all - datatypes, including lists and maps. - + `NULL` : The attribute does not exist. `NULL` is supported for all - datatypes, including lists and maps. - + `CONTAINS` : Checks for a subsequence, or value in a set. - AttributeValueList can contain only one AttributeValue element of - type String, Number, or Binary (not a set type). If the target - attribute of the comparison is of type String, then the operator - checks for a substring match. If the target attribute of the - comparison is of type Binary, then the operator looks for a - subsequence of the target that matches the input. If the target - attribute of the comparison is a set (" `SS`", " `NS`", or " - `BS`"), then the operator evaluates to true if it finds an exact - match with any member of the set. CONTAINS is supported for lists: - When evaluating " `a CONTAINS b`", " `a`" can be a list; however, " - `b`" cannot be a set, a map, or a list. - + `NOT_CONTAINS` : Checks for absence of a subsequence, or absence of a - value in a set. AttributeValueList can contain only one - AttributeValue element of type String, Number, or Binary (not a set - type). If the target attribute of the comparison is a String, then - the operator checks for the absence of a substring match. If the - target attribute of the comparison is Binary, then the operator - checks for the absence of a subsequence of the target that matches - the input. If the target attribute of the comparison is a set (" - `SS`", " `NS`", or " `BS`"), then the operator evaluates to true if - it does not find an exact match with any member of the set. - NOT_CONTAINS is supported for lists: When evaluating " `a NOT - CONTAINS b`", " `a`" can be a list; however, " `b`" cannot be a - set, a map, or a list. - + `BEGINS_WITH` : Checks for a prefix. AttributeValueList can contain - only one AttributeValue of type String or Binary (not a Number or a - set type). The target attribute of the comparison must be of type - String or Binary (not a Number or a set type). > <li> - + `IN` : Checks for matching elements within two sets. - AttributeValueList can contain one or more AttributeValue elements - of type String, Number, or Binary (not a set type). These - attributes are compared against an existing set type attribute of - an item. If any elements of the input set are present in the item - attribute, the expression evaluates to true. - + `BETWEEN` : Greater than or equal to the first value, and less than - or equal to the second value. AttributeValueList must contain two - AttributeValue elements of the same type, either String, Number, or - Binary (not a set type). A target attribute matches if the target - value is greater than, or equal to, the first element and less - than, or equal to, the second element. If an item contains an - AttributeValue element of a different type than the one specified - in the request, the value does not match. For example, `{"S":"6"}` - does not compare to `{"N":"6"}`. Also, `{"N":"6"}` does not compare - to `{"NS":["6", "2", "1"]}` - - - - For usage examples of AttributeValueList and ComparisonOperator , see - `Legacy Conditional Parameters`_ in the Amazon DynamoDB Developer - Guide . - - For backward compatibility with previous DynamoDB releases, the - following parameters can be used instead of AttributeValueList and - ComparisonOperator : - - - + Value - A value for DynamoDB to compare with an attribute. - + Exists - A Boolean value that causes DynamoDB to evaluate the value - before attempting the conditional operation: - - + If Exists is `True`, DynamoDB will check to see if that attribute - value already exists in the table. If it is found, then the - condition evaluates to true; otherwise the condition evaluate to - false. - + If Exists is `False`, DynamoDB assumes that the attribute value does - not exist in the table. If in fact the value does not exist, then - the assumption is valid and the condition evaluates to true. If the - value is found, despite the assumption that it does not exist, the - condition evaluates to false. - - - - The Value and Exists parameters are incompatible with - AttributeValueList and ComparisonOperator . Note that if you use - both sets of parameters at once, DynamoDB will return a - ValidationException exception. - - :type conditional_operator: string - :param conditional_operator: - There is a newer parameter available. Use ConditionExpression instead. - Note that if you use ConditionalOperator and ConditionExpression at - the same time, DynamoDB will return a ValidationException - exception. - - This parameter does not support lists or maps. - - A logical operator to apply to the conditions in the Expected map: - - - + `AND` - If all of the conditions evaluate to true, then the entire - map evaluates to true. - + `OR` - If at least one of the conditions evaluate to true, then the - entire map evaluates to true. - - - If you omit ConditionalOperator , then `AND` is the default. - - The operation will succeed only if the entire map evaluates to true. - - :type return_values: string - :param return_values: - Use ReturnValues if you want to get the item attributes as they - appeared either before or after they were updated. For UpdateItem , - the valid values are: - - - + `NONE` - If ReturnValues is not specified, or if its value is `NONE`, - then nothing is returned. (This setting is the default for - ReturnValues .) - + `ALL_OLD` - If UpdateItem overwrote an attribute name-value pair, - then the content of the old item is returned. - + `UPDATED_OLD` - The old versions of only the updated attributes are - returned. - + `ALL_NEW` - All of the attributes of the new version of the item are - returned. - + `UPDATED_NEW` - The new versions of only the updated attributes are - returned. - - :type return_consumed_capacity: string - :param return_consumed_capacity: A value that if set to `TOTAL`, the - response includes ConsumedCapacity data for tables and indexes. If - set to `INDEXES`, the response includes ConsumedCapacity for - indexes. If set to `NONE` (the default), ConsumedCapacity is not - included in the response. - - :type return_item_collection_metrics: string - :param return_item_collection_metrics: A value that if set to `SIZE`, - the response includes statistics about item collections, if any, - that were modified during the operation are returned in the - response. If set to `NONE` (the default), no statistics are - returned. - - :type update_expression: string - :param update_expression: - An expression that defines one or more attributes to be updated, the - action to be performed on them, and new value(s) for them. - - The following action values are available for UpdateExpression . - - - + `SET` - Adds one or more attributes and values to an item. If any of - these attribute already exist, they are replaced by the new values. - You can also use `SET` to add or subtract from an attribute that is - of type Number. `SET` supports the following functions: - - + `if_not_exists (path, operand)` - if the item does not contain an - attribute at the specified path, then `if_not_exists` evaluates to - operand; otherwise, it evaluates to path. You can use this function - to avoid overwriting an attribute that may already be present in - the item. - + `list_append (operand, operand)` - evaluates to a list with a new - element added to it. You can append the new element to the start or - the end of the list by reversing the order of the operands. - These function names are case-sensitive. - + `REMOVE` - Removes one or more attributes from an item. - + `ADD` - Adds the specified value to the item, if the attribute does - not already exist. If the attribute does exist, then the behavior - of `ADD` depends on the data type of the attribute: - - + If the existing attribute is a number, and if Value is also a number, - then Value is mathematically added to the existing attribute. If - Value is a negative number, then it is subtracted from the existing - attribute. - + If the existing data type is a set and if Value is also a set, then - Value is added to the existing set. For example, if the attribute - value is the set `[1,2]`, and the `ADD` action specified `[3]`, - then the final attribute value is `[1,2,3]`. An error occurs if an - `ADD` action is specified for a set attribute and the attribute - type specified does not match the existing set type. Both sets must - have the same primitive data type. For example, if the existing - data type is a set of strings, the Value must also be a set of - strings. - The `ADD` action only supports Number and set data types. In addition, - `ADD` can only be used on top-level attributes, not nested - attributes. - + `DELETE` - Deletes an element from a set. If a set of values is - specified, then those values are subtracted from the old set. For - example, if the attribute value was the set `[a,b,c]` and the - `DELETE` action specifies `[a,c]`, then the final attribute value - is `[b]`. Specifying an empty set is an error. The `DELETE` action - only supports Number and set data types. In addition, `DELETE` can - only be used on top-level attributes, not nested attributes. - - - You can have many actions in a single expression, such as the - following: `SET a=:value1, b=:value2 DELETE :value3, :value4, - :value5` - - An expression can contain any of the following: - - - + Boolean functions: `ATTRIBUTE_EXIST | CONTAINS | BEGINS_WITH` - + Comparison operators: ` = | <> | < | > | <= - | >= | BETWEEN | IN` - + Logical operators: `NOT | AND | OR` - - :type condition_expression: string - :param condition_expression: - A condition that must be satisfied in order for a conditional update to - succeed. - - An expression can contain any of the following: - - - + Boolean functions: `ATTRIBUTE_EXIST | CONTAINS | BEGINS_WITH` - + Comparison operators: ` = | <> | < | > | <= - | >= | BETWEEN | IN` - + Logical operators: `NOT | AND | OR` - - :type expression_attribute_names: map - :param expression_attribute_names: - One or more substitution tokens for simplifying complex expressions. - The following are some use cases for an ExpressionAttributeNames - value: - - - + To shorten an attribute name that is very long or unwieldy in an - expression. - + To create a placeholder for repeating occurrences of an attribute - name in an expression. - + To prevent special characters in an attribute name from being - misinterpreted in an expression. - - - Use the **#** character in an expression to dereference an attribute - name. For example, consider the following expression: - - - + `order.customerInfo.LastName = "Smith" OR order.customerInfo.LastName - = "Jones"` - - - Now suppose that you specified the following for - ExpressionAttributeNames : - - - + `{"n":"order.customerInfo.LastName"}` - - - The expression can now be simplified as follows: - - - + `#n = "Smith" OR #n = "Jones"` - - :type expression_attribute_values: map - :param expression_attribute_values: - One or more values that can be substituted in an expression. - - Use the **:** character in an expression to dereference an attribute - value. For example, consider the following expression: - - - + `ProductStatus IN ("Available","Backordered","Discontinued")` - - - Now suppose that you specified the following for - ExpressionAttributeValues : - - - + `{ "a":{"S":"Available"}, "b":{"S":"Backordered"}, - "d":{"S":"Discontinued"} }` - - - The expression can now be simplified as follows: - - - + `ProductStatus IN (:a,:b,:c)` - - """ - params = {'TableName': table_name, 'Key': key, } - if attribute_updates is not None: - params['AttributeUpdates'] = attribute_updates - if expected is not None: - params['Expected'] = expected - if conditional_operator is not None: - params['ConditionalOperator'] = conditional_operator - if return_values is not None: - params['ReturnValues'] = return_values - if return_consumed_capacity is not None: - params['ReturnConsumedCapacity'] = return_consumed_capacity - if return_item_collection_metrics is not None: - params['ReturnItemCollectionMetrics'] = return_item_collection_metrics - if update_expression is not None: - params['UpdateExpression'] = update_expression - if condition_expression is not None: - params['ConditionExpression'] = condition_expression - if expression_attribute_names is not None: - params['ExpressionAttributeNames'] = expression_attribute_names - if expression_attribute_values is not None: - params['ExpressionAttributeValues'] = expression_attribute_values - return self.make_request(action='UpdateItem', - body=json.dumps(params)) - - def update_table(self, table_name, provisioned_throughput=None, - global_secondary_index_updates=None): - """ - Updates the provisioned throughput for the given table. - Setting the throughput for a table helps you manage - performance and is part of the provisioned throughput feature - of DynamoDB. - - The provisioned throughput values can be upgraded or - downgraded based on the maximums and minimums listed in the - `Limits`_ section in the Amazon DynamoDB Developer Guide . - - The table must be in the `ACTIVE` state for this operation to - succeed. UpdateTable is an asynchronous operation; while - executing the operation, the table is in the `UPDATING` state. - While the table is in the `UPDATING` state, the table still - has the provisioned throughput from before the call. The new - provisioned throughput setting is in effect only when the - table returns to the `ACTIVE` state after the UpdateTable - operation. - - You cannot add, modify or delete indexes using UpdateTable . - Indexes can only be defined at table creation time. - - :type table_name: string - :param table_name: The name of the table to be updated. - - :type provisioned_throughput: dict - :param provisioned_throughput: Represents the provisioned throughput - settings for a specified table or index. The settings can be - modified using the UpdateTable operation. - For current minimum and maximum provisioned throughput values, see - `Limits`_ in the Amazon DynamoDB Developer Guide . - - :type global_secondary_index_updates: list - :param global_secondary_index_updates: An array of one or more global - secondary indexes on the table, together with provisioned - throughput settings for each index. - - """ - params = {'TableName': table_name, } - if provisioned_throughput is not None: - params['ProvisionedThroughput'] = provisioned_throughput - if global_secondary_index_updates is not None: - params['GlobalSecondaryIndexUpdates'] = global_secondary_index_updates - return self.make_request(action='UpdateTable', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.host, - 'Content-Type': 'application/x-amz-json-1.0', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body, host=self.host) - response = self._mexe(http_request, sender=None, - override_num_retries=self.NumberRetries, - retry_handler=self._retry_handler) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) - - def _retry_handler(self, response, i, next_sleep): - status = None - boto.log.debug("Saw HTTP status: %s" % response.status) - if response.status == 400: - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - data = json.loads(response_body) - if 'ProvisionedThroughputExceededException' in data.get('__type'): - self.throughput_exceeded_events += 1 - msg = "%s, retry attempt %s" % ( - 'ProvisionedThroughputExceededException', - i - ) - next_sleep = self._truncated_exponential_time(i) - i += 1 - status = (msg, i, next_sleep) - if i == self.NumberRetries: - # If this was our last retry attempt, raise - # a specific error saying that the throughput - # was exceeded. - raise exceptions.ProvisionedThroughputExceededException( - response.status, response.reason, data) - elif 'ConditionalCheckFailedException' in data.get('__type'): - raise exceptions.ConditionalCheckFailedException( - response.status, response.reason, data) - elif 'ValidationException' in data.get('__type'): - raise exceptions.ValidationException( - response.status, response.reason, data) - else: - raise self.ResponseError(response.status, response.reason, - data) - expected_crc32 = response.getheader('x-amz-crc32') - if self._validate_checksums and expected_crc32 is not None: - boto.log.debug('Validating crc32 checksum for body: %s', - response.read()) - actual_crc32 = crc32(response.read()) & 0xffffffff - expected_crc32 = int(expected_crc32) - if actual_crc32 != expected_crc32: - msg = ("The calculated checksum %s did not match the expected " - "checksum %s" % (actual_crc32, expected_crc32)) - status = (msg, i + 1, self._truncated_exponential_time(i)) - return status - - def _truncated_exponential_time(self, i): - if i == 0: - next_sleep = 0 - else: - next_sleep = min(0.05 * (2 ** i), - boto.config.get('Boto', 'max_retry_delay', 60)) - return next_sleep diff --git a/awx/lib/site-packages/boto/dynamodb2/results.py b/awx/lib/site-packages/boto/dynamodb2/results.py deleted file mode 100644 index 3d80ecf317..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/results.py +++ /dev/null @@ -1,202 +0,0 @@ -class ResultSet(object): - """ - A class used to lazily handle page-to-page navigation through a set of - results. - - It presents a transparent iterator interface, so that all the user has - to do is use it in a typical ``for`` loop (or list comprehension, etc.) - to fetch results, even if they weren't present in the current page of - results. - - This is used by the ``Table.query`` & ``Table.scan`` methods. - - Example:: - - >>> users = Table('users') - >>> results = ResultSet() - >>> results.to_call(users.query, username__gte='johndoe') - # Now iterate. When it runs out of results, it'll fetch the next page. - >>> for res in results: - ... print res['username'] - - """ - def __init__(self, max_page_size=None): - super(ResultSet, self).__init__() - self.the_callable = None - self.call_args = [] - self.call_kwargs = {} - self._results = [] - self._offset = -1 - self._results_left = True - self._last_key_seen = None - self._fetches = 0 - self._max_page_size = max_page_size - self._limit = None - - @property - def first_key(self): - return 'exclusive_start_key' - - def _reset(self): - """ - Resets the internal state of the ``ResultSet``. - - This prevents results from being cached long-term & consuming - excess memory. - - Largely internal. - """ - self._results = [] - self._offset = 0 - - def __iter__(self): - return self - - def __next__(self): - self._offset += 1 - - if self._offset >= len(self._results): - if self._results_left is False: - raise StopIteration() - - self.fetch_more() - - # It's possible that previous call to ``fetch_more`` may not return - # anything useful but there may be more results. Loop until we get - # something back, making sure we guard for no results left. - while not len(self._results) and self._results_left: - self.fetch_more() - - if self._offset < len(self._results): - if self._limit is not None: - self._limit -= 1 - - if self._limit < 0: - raise StopIteration() - - return self._results[self._offset] - else: - raise StopIteration() - - next = __next__ - - def to_call(self, the_callable, *args, **kwargs): - """ - Sets up the callable & any arguments to run it with. - - This is stored for subsequent calls so that those queries can be - run without requiring user intervention. - - Example:: - - # Just an example callable. - >>> def squares_to(y): - ... for x in range(1, y): - ... yield x**2 - >>> rs = ResultSet() - # Set up what to call & arguments. - >>> rs.to_call(squares_to, y=3) - - """ - if not callable(the_callable): - raise ValueError( - 'You must supply an object or function to be called.' - ) - - # We pop the ``limit``, if present, to track how many we should return - # to the user. This isn't the same as the ``limit`` that the low-level - # DDB api calls use (which limit page size, not the overall result set). - self._limit = kwargs.pop('limit', None) - - if self._limit is not None and self._limit < 0: - self._limit = None - - self.the_callable = the_callable - self.call_args = args - self.call_kwargs = kwargs - - def fetch_more(self): - """ - When the iterator runs out of results, this method is run to re-execute - the callable (& arguments) to fetch the next page. - - Largely internal. - """ - self._reset() - - args = self.call_args[:] - kwargs = self.call_kwargs.copy() - - if self._last_key_seen is not None: - kwargs[self.first_key] = self._last_key_seen - - # If the page size is greater than limit set them - # to the same value - if self._limit and self._max_page_size and self._max_page_size > self._limit: - self._max_page_size = self._limit - - # Put in the max page size. - if self._max_page_size is not None: - kwargs['limit'] = self._max_page_size - elif self._limit is not None: - # If max_page_size is not set and limit is available - # use it as the page size - kwargs['limit'] = self._limit - - results = self.the_callable(*args, **kwargs) - self._fetches += 1 - new_results = results.get('results', []) - self._last_key_seen = results.get('last_key', None) - - if len(new_results): - self._results.extend(results['results']) - - # Check the limit, if it's present. - if self._limit is not None and self._limit >= 0: - limit = self._limit - limit -= len(results['results']) - # If we've exceeded the limit, we don't have any more - # results to look for. - if limit <= 0: - self._results_left = False - - if self._last_key_seen is None: - self._results_left = False - - -class BatchGetResultSet(ResultSet): - def __init__(self, *args, **kwargs): - self._keys_left = kwargs.pop('keys', []) - self._max_batch_get = kwargs.pop('max_batch_get', 100) - super(BatchGetResultSet, self).__init__(*args, **kwargs) - - def fetch_more(self): - self._reset() - - args = self.call_args[:] - kwargs = self.call_kwargs.copy() - - # Slice off the max we can fetch. - kwargs['keys'] = self._keys_left[:self._max_batch_get] - self._keys_left = self._keys_left[self._max_batch_get:] - - results = self.the_callable(*args, **kwargs) - - if not len(results.get('results', [])): - self._results_left = False - return - - self._results.extend(results['results']) - - for offset, key_data in enumerate(results.get('unprocessed_keys', [])): - # We've got an unprocessed key. Reinsert it into the list. - # DynamoDB only returns valid keys, so there should be no risk of - # missing keys ever making it here. - self._keys_left.insert(offset, key_data) - - if len(self._keys_left) <= 0: - self._results_left = False - - # Decrease the limit, if it's present. - if self.call_kwargs.get('limit'): - self.call_kwargs['limit'] -= len(results['results']) diff --git a/awx/lib/site-packages/boto/dynamodb2/table.py b/awx/lib/site-packages/boto/dynamodb2/table.py deleted file mode 100644 index 052758f7c3..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/table.py +++ /dev/null @@ -1,1507 +0,0 @@ -import boto -from boto.dynamodb2 import exceptions -from boto.dynamodb2.fields import (HashKey, RangeKey, - AllIndex, KeysOnlyIndex, IncludeIndex, - GlobalAllIndex, GlobalKeysOnlyIndex, - GlobalIncludeIndex) -from boto.dynamodb2.items import Item -from boto.dynamodb2.layer1 import DynamoDBConnection -from boto.dynamodb2.results import ResultSet, BatchGetResultSet -from boto.dynamodb2.types import (Dynamizer, FILTER_OPERATORS, QUERY_OPERATORS, - STRING) -from boto.exception import JSONResponseError - - -class Table(object): - """ - Interacts & models the behavior of a DynamoDB table. - - The ``Table`` object represents a set (or rough categorization) of - records within DynamoDB. The important part is that all records within the - table, while largely-schema-free, share the same schema & are essentially - namespaced for use in your application. For example, you might have a - ``users`` table or a ``forums`` table. - """ - max_batch_get = 100 - - def __init__(self, table_name, schema=None, throughput=None, indexes=None, - global_indexes=None, connection=None): - """ - Sets up a new in-memory ``Table``. - - This is useful if the table already exists within DynamoDB & you simply - want to use it for additional interactions. The only required parameter - is the ``table_name``. However, under the hood, the object will call - ``describe_table`` to determine the schema/indexes/throughput. You - can avoid this extra call by passing in ``schema`` & ``indexes``. - - **IMPORTANT** - If you're creating a new ``Table`` for the first time, - you should use the ``Table.create`` method instead, as it will - persist the table structure to DynamoDB. - - Requires a ``table_name`` parameter, which should be a simple string - of the name of the table. - - Optionally accepts a ``schema`` parameter, which should be a list of - ``BaseSchemaField`` subclasses representing the desired schema. - - Optionally accepts a ``throughput`` parameter, which should be a - dictionary. If provided, it should specify a ``read`` & ``write`` key, - both of which should have an integer value associated with them. - - Optionally accepts a ``indexes`` parameter, which should be a list of - ``BaseIndexField`` subclasses representing the desired indexes. - - Optionally accepts a ``global_indexes`` parameter, which should be a - list of ``GlobalBaseIndexField`` subclasses representing the desired - indexes. - - Optionally accepts a ``connection`` parameter, which should be a - ``DynamoDBConnection`` instance (or subclass). This is primarily useful - for specifying alternate connection parameters. - - Example:: - - # The simple, it-already-exists case. - >>> conn = Table('users') - - # The full, minimum-extra-calls case. - >>> from boto import dynamodb2 - >>> users = Table('users', schema=[ - ... HashKey('username'), - ... RangeKey('date_joined', data_type=NUMBER) - ... ], throughput={ - ... 'read':20, - ... 'write': 10, - ... }, indexes=[ - ... KeysOnlyIndex('MostRecentlyJoined', parts=[ - ... HashKey('username') - ... RangeKey('date_joined') - ... ]), - ... ], global_indexes=[ - ... GlobalAllIndex('UsersByZipcode', parts=[ - ... HashKey('zipcode'), - ... RangeKey('username'), - ... ], - ... throughput={ - ... 'read':10, - ... 'write":10, - ... }), - ... ], connection=dynamodb2.connect_to_region('us-west-2', - ... aws_access_key_id='key', - ... aws_secret_access_key='key', - ... )) - - """ - self.table_name = table_name - self.connection = connection - self.throughput = { - 'read': 5, - 'write': 5, - } - self.schema = schema - self.indexes = indexes - self.global_indexes = global_indexes - - if self.connection is None: - self.connection = DynamoDBConnection() - - if throughput is not None: - self.throughput = throughput - - self._dynamizer = Dynamizer() - - @classmethod - def create(cls, table_name, schema, throughput=None, indexes=None, - global_indexes=None, connection=None): - """ - Creates a new table in DynamoDB & returns an in-memory ``Table`` object. - - This will setup a brand new table within DynamoDB. The ``table_name`` - must be unique for your AWS account. The ``schema`` is also required - to define the key structure of the table. - - **IMPORTANT** - You should consider the usage pattern of your table - up-front, as the schema & indexes can **NOT** be modified once the - table is created, requiring the creation of a new table & migrating - the data should you wish to revise it. - - **IMPORTANT** - If the table already exists in DynamoDB, additional - calls to this method will result in an error. If you just need - a ``Table`` object to interact with the existing table, you should - just initialize a new ``Table`` object, which requires only the - ``table_name``. - - Requires a ``table_name`` parameter, which should be a simple string - of the name of the table. - - Requires a ``schema`` parameter, which should be a list of - ``BaseSchemaField`` subclasses representing the desired schema. - - Optionally accepts a ``throughput`` parameter, which should be a - dictionary. If provided, it should specify a ``read`` & ``write`` key, - both of which should have an integer value associated with them. - - Optionally accepts a ``indexes`` parameter, which should be a list of - ``BaseIndexField`` subclasses representing the desired indexes. - - Optionally accepts a ``global_indexes`` parameter, which should be a - list of ``GlobalBaseIndexField`` subclasses representing the desired - indexes. - - Optionally accepts a ``connection`` parameter, which should be a - ``DynamoDBConnection`` instance (or subclass). This is primarily useful - for specifying alternate connection parameters. - - Example:: - - >>> users = Table.create('users', schema=[ - ... HashKey('username'), - ... RangeKey('date_joined', data_type=NUMBER) - ... ], throughput={ - ... 'read':20, - ... 'write': 10, - ... }, indexes=[ - ... KeysOnlyIndex('MostRecentlyJoined', parts=[ - ... RangeKey('date_joined') - ... ]), global_indexes=[ - ... GlobalAllIndex('UsersByZipcode', parts=[ - ... HashKey('zipcode'), - ... RangeKey('username'), - ... ], - ... throughput={ - ... 'read':10, - ... 'write':10, - ... }), - ... ]) - - """ - table = cls(table_name=table_name, connection=connection) - table.schema = schema - - if throughput is not None: - table.throughput = throughput - - if indexes is not None: - table.indexes = indexes - - if global_indexes is not None: - table.global_indexes = global_indexes - - # Prep the schema. - raw_schema = [] - attr_defs = [] - seen_attrs = set() - - for field in table.schema: - raw_schema.append(field.schema()) - # Build the attributes off what we know. - seen_attrs.add(field.name) - attr_defs.append(field.definition()) - - raw_throughput = { - 'ReadCapacityUnits': int(table.throughput['read']), - 'WriteCapacityUnits': int(table.throughput['write']), - } - kwargs = {} - - kwarg_map = { - 'indexes': 'local_secondary_indexes', - 'global_indexes': 'global_secondary_indexes', - } - for index_attr in ('indexes', 'global_indexes'): - table_indexes = getattr(table, index_attr) - if table_indexes: - raw_indexes = [] - for index_field in table_indexes: - raw_indexes.append(index_field.schema()) - # Make sure all attributes specified in the indexes are - # added to the definition - for field in index_field.parts: - if field.name not in seen_attrs: - seen_attrs.add(field.name) - attr_defs.append(field.definition()) - - kwargs[kwarg_map[index_attr]] = raw_indexes - - table.connection.create_table( - table_name=table.table_name, - attribute_definitions=attr_defs, - key_schema=raw_schema, - provisioned_throughput=raw_throughput, - **kwargs - ) - return table - - def _introspect_schema(self, raw_schema, raw_attributes=None): - """ - Given a raw schema structure back from a DynamoDB response, parse - out & build the high-level Python objects that represent them. - """ - schema = [] - sane_attributes = {} - - if raw_attributes: - for field in raw_attributes: - sane_attributes[field['AttributeName']] = field['AttributeType'] - - for field in raw_schema: - data_type = sane_attributes.get(field['AttributeName'], STRING) - - if field['KeyType'] == 'HASH': - schema.append( - HashKey(field['AttributeName'], data_type=data_type) - ) - elif field['KeyType'] == 'RANGE': - schema.append( - RangeKey(field['AttributeName'], data_type=data_type) - ) - else: - raise exceptions.UnknownSchemaFieldError( - "%s was seen, but is unknown. Please report this at " - "https://github.com/boto/boto/issues." % field['KeyType'] - ) - - return schema - - def _introspect_indexes(self, raw_indexes): - """ - Given a raw index structure back from a DynamoDB response, parse - out & build the high-level Python objects that represent them. - """ - indexes = [] - - for field in raw_indexes: - index_klass = AllIndex - kwargs = { - 'parts': [] - } - - if field['Projection']['ProjectionType'] == 'ALL': - index_klass = AllIndex - elif field['Projection']['ProjectionType'] == 'KEYS_ONLY': - index_klass = KeysOnlyIndex - elif field['Projection']['ProjectionType'] == 'INCLUDE': - index_klass = IncludeIndex - kwargs['includes'] = field['Projection']['NonKeyAttributes'] - else: - raise exceptions.UnknownIndexFieldError( - "%s was seen, but is unknown. Please report this at " - "https://github.com/boto/boto/issues." % \ - field['Projection']['ProjectionType'] - ) - - name = field['IndexName'] - kwargs['parts'] = self._introspect_schema(field['KeySchema'], None) - indexes.append(index_klass(name, **kwargs)) - - return indexes - - def describe(self): - """ - Describes the current structure of the table in DynamoDB. - - This information will be used to update the ``schema``, ``indexes`` - and ``throughput`` information on the ``Table``. Some calls, such as - those involving creating keys or querying, will require this - information to be populated. - - It also returns the full raw datastructure from DynamoDB, in the - event you'd like to parse out additional information (such as the - ``ItemCount`` or usage information). - - Example:: - - >>> users.describe() - { - # Lots of keys here... - } - >>> len(users.schema) - 2 - - """ - result = self.connection.describe_table(self.table_name) - - # Blindly update throughput, since what's on DynamoDB's end is likely - # more correct. - raw_throughput = result['Table']['ProvisionedThroughput'] - self.throughput['read'] = int(raw_throughput['ReadCapacityUnits']) - self.throughput['write'] = int(raw_throughput['WriteCapacityUnits']) - - if not self.schema: - # Since we have the data, build the schema. - raw_schema = result['Table'].get('KeySchema', []) - raw_attributes = result['Table'].get('AttributeDefinitions', []) - self.schema = self._introspect_schema(raw_schema, raw_attributes) - - if not self.indexes: - # Build the index information as well. - raw_indexes = result['Table'].get('LocalSecondaryIndexes', []) - self.indexes = self._introspect_indexes(raw_indexes) - - # This is leaky. - return result - - def update(self, throughput, global_indexes=None): - """ - Updates table attributes in DynamoDB. - - Currently, the only thing you can modify about a table after it has - been created is the throughput. - - Requires a ``throughput`` parameter, which should be a - dictionary. If provided, it should specify a ``read`` & ``write`` key, - both of which should have an integer value associated with them. - - Returns ``True`` on success. - - Example:: - - # For a read-heavier application... - >>> users.update(throughput={ - ... 'read': 20, - ... 'write': 10, - ... }) - True - - # To also update the global index(es) throughput. - >>> users.update(throughput={ - ... 'read': 20, - ... 'write': 10, - ... }, - ... global_secondary_indexes={ - ... 'TheIndexNameHere': { - ... 'read': 15, - ... 'write': 5, - ... } - ... }) - True - - """ - self.throughput = throughput - data = { - 'ReadCapacityUnits': int(self.throughput['read']), - 'WriteCapacityUnits': int(self.throughput['write']), - } - gsi_data = None - - if global_indexes: - gsi_data = [] - - for gsi_name, gsi_throughput in global_indexes.items(): - gsi_data.append({ - "Update": { - "IndexName": gsi_name, - "ProvisionedThroughput": { - "ReadCapacityUnits": int(gsi_throughput['read']), - "WriteCapacityUnits": int(gsi_throughput['write']), - }, - }, - }) - - self.connection.update_table( - self.table_name, - provisioned_throughput=data, - global_secondary_index_updates=gsi_data - ) - return True - - def delete(self): - """ - Deletes a table in DynamoDB. - - **IMPORTANT** - Be careful when using this method, there is no undo. - - Returns ``True`` on success. - - Example:: - - >>> users.delete() - True - - """ - self.connection.delete_table(self.table_name) - return True - - def _encode_keys(self, keys): - """ - Given a flat Python dictionary of keys/values, converts it into the - nested dictionary DynamoDB expects. - - Converts:: - - { - 'username': 'john', - 'tags': [1, 2, 5], - } - - ...to...:: - - { - 'username': {'S': 'john'}, - 'tags': {'NS': ['1', '2', '5']}, - } - - """ - raw_key = {} - - for key, value in keys.items(): - raw_key[key] = self._dynamizer.encode(value) - - return raw_key - - def get_item(self, consistent=False, attributes=None, **kwargs): - """ - Fetches an item (record) from a table in DynamoDB. - - To specify the key of the item you'd like to get, you can specify the - key attributes as kwargs. - - Optionally accepts a ``consistent`` parameter, which should be a - boolean. If you provide ``True``, it will perform - a consistent (but more expensive) read from DynamoDB. - (Default: ``False``) - - Optionally accepts an ``attributes`` parameter, which should be a - list of fieldname to fetch. (Default: ``None``, which means all fields - should be fetched) - - Returns an ``Item`` instance containing all the data for that record. - - Raises an ``ItemNotFound`` exception if the item is not found. - - Example:: - - # A simple hash key. - >>> john = users.get_item(username='johndoe') - >>> john['first_name'] - 'John' - - # A complex hash+range key. - >>> john = users.get_item(username='johndoe', last_name='Doe') - >>> john['first_name'] - 'John' - - # A consistent read (assuming the data might have just changed). - >>> john = users.get_item(username='johndoe', consistent=True) - >>> john['first_name'] - 'Johann' - - # With a key that is an invalid variable name in Python. - # Also, assumes a different schema than previous examples. - >>> john = users.get_item(**{ - ... 'date-joined': 127549192, - ... }) - >>> john['first_name'] - 'John' - - """ - raw_key = self._encode_keys(kwargs) - item_data = self.connection.get_item( - self.table_name, - raw_key, - attributes_to_get=attributes, - consistent_read=consistent - ) - if 'Item' not in item_data: - raise exceptions.ItemNotFound("Item %s couldn't be found." % kwargs) - item = Item(self) - item.load(item_data) - return item - - def has_item(self, **kwargs): - """ - Return whether an item (record) exists within a table in DynamoDB. - - To specify the key of the item you'd like to get, you can specify the - key attributes as kwargs. - - Optionally accepts a ``consistent`` parameter, which should be a - boolean. If you provide ``True``, it will perform - a consistent (but more expensive) read from DynamoDB. - (Default: ``False``) - - Optionally accepts an ``attributes`` parameter, which should be a - list of fieldnames to fetch. (Default: ``None``, which means all fields - should be fetched) - - Returns ``True`` if an ``Item`` is present, ``False`` if not. - - Example:: - - # Simple, just hash-key schema. - >>> users.has_item(username='johndoe') - True - - # Complex schema, item not present. - >>> users.has_item( - ... username='johndoe', - ... date_joined='2014-01-07' - ... ) - False - - """ - try: - self.get_item(**kwargs) - except (JSONResponseError, exceptions.ItemNotFound): - return False - - return True - - def lookup(self, *args, **kwargs): - """ - Look up an entry in DynamoDB. This is mostly backwards compatible - with boto.dynamodb. Unlike get_item, it takes hash_key and range_key first, - although you may still specify keyword arguments instead. - - Also unlike the get_item command, if the returned item has no keys - (i.e., it does not exist in DynamoDB), a None result is returned, instead - of an empty key object. - - Example:: - >>> user = users.lookup(username) - >>> user = users.lookup(username, consistent=True) - >>> app = apps.lookup('my_customer_id', 'my_app_id') - - """ - if not self.schema: - self.describe() - for x, arg in enumerate(args): - kwargs[self.schema[x].name] = arg - ret = self.get_item(**kwargs) - if not ret.keys(): - return None - return ret - - def new_item(self, *args): - """ - Returns a new, blank item - - This is mostly for consistency with boto.dynamodb - """ - if not self.schema: - self.describe() - data = {} - for x, arg in enumerate(args): - data[self.schema[x].name] = arg - return Item(self, data=data) - - def put_item(self, data, overwrite=False): - """ - Saves an entire item to DynamoDB. - - By default, if any part of the ``Item``'s original data doesn't match - what's currently in DynamoDB, this request will fail. This prevents - other processes from updating the data in between when you read the - item & when your request to update the item's data is processed, which - would typically result in some data loss. - - Requires a ``data`` parameter, which should be a dictionary of the data - you'd like to store in DynamoDB. - - Optionally accepts an ``overwrite`` parameter, which should be a - boolean. If you provide ``True``, this will tell DynamoDB to blindly - overwrite whatever data is present, if any. - - Returns ``True`` on success. - - Example:: - - >>> users.put_item(data={ - ... 'username': 'jane', - ... 'first_name': 'Jane', - ... 'last_name': 'Doe', - ... 'date_joined': 126478915, - ... }) - True - - """ - item = Item(self, data=data) - return item.save(overwrite=overwrite) - - def _put_item(self, item_data, expects=None): - """ - The internal variant of ``put_item`` (full data). This is used by the - ``Item`` objects, since that operation is represented at the - table-level by the API, but conceptually maps better to telling an - individual ``Item`` to save itself. - """ - kwargs = {} - - if expects is not None: - kwargs['expected'] = expects - - self.connection.put_item(self.table_name, item_data, **kwargs) - return True - - def _update_item(self, key, item_data, expects=None): - """ - The internal variant of ``put_item`` (partial data). This is used by the - ``Item`` objects, since that operation is represented at the - table-level by the API, but conceptually maps better to telling an - individual ``Item`` to save itself. - """ - raw_key = self._encode_keys(key) - kwargs = {} - - if expects is not None: - kwargs['expected'] = expects - - self.connection.update_item(self.table_name, raw_key, item_data, **kwargs) - return True - - def delete_item(self, expected=None, conditional_operator=None, **kwargs): - """ - Deletes a single item. You can perform a conditional delete operation - that deletes the item if it exists, or if it has an expected attribute - value. - - Conditional deletes are useful for only deleting items if specific - conditions are met. If those conditions are met, DynamoDB performs - the delete. Otherwise, the item is not deleted. - - To specify the expected attribute values of the item, you can pass a - dictionary of conditions to ``expected``. Each condition should follow - the pattern ``<attributename>__<comparison_operator>=<value_to_expect>``. - - **IMPORTANT** - Be careful when using this method, there is no undo. - - To specify the key of the item you'd like to get, you can specify the - key attributes as kwargs. - - Optionally accepts an ``expected`` parameter which is a dictionary of - expected attribute value conditions. - - Optionally accepts a ``conditional_operator`` which applies to the - expected attribute value conditions: - - + `AND` - If all of the conditions evaluate to true (default) - + `OR` - True if at least one condition evaluates to true - - Returns ``True`` on success, ``False`` on failed conditional delete. - - Example:: - - # A simple hash key. - >>> users.delete_item(username='johndoe') - True - - # A complex hash+range key. - >>> users.delete_item(username='jane', last_name='Doe') - True - - # With a key that is an invalid variable name in Python. - # Also, assumes a different schema than previous examples. - >>> users.delete_item(**{ - ... 'date-joined': 127549192, - ... }) - True - - # Conditional delete - >>> users.delete_item(username='johndoe', - ... expected={'balance__eq': 0}) - True - """ - expected = self._build_filters(expected, using=FILTER_OPERATORS) - raw_key = self._encode_keys(kwargs) - - try: - self.connection.delete_item(self.table_name, raw_key, - expected=expected, - conditional_operator=conditional_operator) - except exceptions.ConditionalCheckFailedException: - return False - - return True - - def get_key_fields(self): - """ - Returns the fields necessary to make a key for a table. - - If the ``Table`` does not already have a populated ``schema``, - this will request it via a ``Table.describe`` call. - - Returns a list of fieldnames (strings). - - Example:: - - # A simple hash key. - >>> users.get_key_fields() - ['username'] - - # A complex hash+range key. - >>> users.get_key_fields() - ['username', 'last_name'] - - """ - if not self.schema: - # We don't know the structure of the table. Get a description to - # populate the schema. - self.describe() - - return [field.name for field in self.schema] - - def batch_write(self): - """ - Allows the batching of writes to DynamoDB. - - Since each write/delete call to DynamoDB has a cost associated with it, - when loading lots of data, it makes sense to batch them, creating as - few calls as possible. - - This returns a context manager that will transparently handle creating - these batches. The object you get back lightly-resembles a ``Table`` - object, sharing just the ``put_item`` & ``delete_item`` methods - (which are all that DynamoDB can batch in terms of writing data). - - DynamoDB's maximum batch size is 25 items per request. If you attempt - to put/delete more than that, the context manager will batch as many - as it can up to that number, then flush them to DynamoDB & continue - batching as more calls come in. - - Example:: - - # Assuming a table with one record... - >>> with users.batch_write() as batch: - ... batch.put_item(data={ - ... 'username': 'johndoe', - ... 'first_name': 'John', - ... 'last_name': 'Doe', - ... 'owner': 1, - ... }) - ... # Nothing across the wire yet. - ... batch.delete_item(username='bob') - ... # Still no requests sent. - ... batch.put_item(data={ - ... 'username': 'jane', - ... 'first_name': 'Jane', - ... 'last_name': 'Doe', - ... 'date_joined': 127436192, - ... }) - ... # Nothing yet, but once we leave the context, the - ... # put/deletes will be sent. - - """ - # PHENOMENAL COSMIC DOCS!!! itty-bitty code. - return BatchTable(self) - - def _build_filters(self, filter_kwargs, using=QUERY_OPERATORS): - """ - An internal method for taking query/scan-style ``**kwargs`` & turning - them into the raw structure DynamoDB expects for filtering. - """ - if filter_kwargs is None: - return - - filters = {} - - for field_and_op, value in filter_kwargs.items(): - field_bits = field_and_op.split('__') - fieldname = '__'.join(field_bits[:-1]) - - try: - op = using[field_bits[-1]] - except KeyError: - raise exceptions.UnknownFilterTypeError( - "Operator '%s' from '%s' is not recognized." % ( - field_bits[-1], - field_and_op - ) - ) - - lookup = { - 'AttributeValueList': [], - 'ComparisonOperator': op, - } - - # Special-case the ``NULL/NOT_NULL`` case. - if field_bits[-1] == 'null': - del lookup['AttributeValueList'] - - if value is False: - lookup['ComparisonOperator'] = 'NOT_NULL' - else: - lookup['ComparisonOperator'] = 'NULL' - # Special-case the ``BETWEEN`` case. - elif field_bits[-1] == 'between': - if len(value) == 2 and isinstance(value, (list, tuple)): - lookup['AttributeValueList'].append( - self._dynamizer.encode(value[0]) - ) - lookup['AttributeValueList'].append( - self._dynamizer.encode(value[1]) - ) - # Special-case the ``IN`` case - elif field_bits[-1] == 'in': - for val in value: - lookup['AttributeValueList'].append(self._dynamizer.encode(val)) - else: - # Fix up the value for encoding, because it was built to only work - # with ``set``s. - if isinstance(value, (list, tuple)): - value = set(value) - lookup['AttributeValueList'].append( - self._dynamizer.encode(value) - ) - - # Finally, insert it into the filters. - filters[fieldname] = lookup - - return filters - - def query(self, limit=None, index=None, reverse=False, consistent=False, - attributes=None, max_page_size=None, **filter_kwargs): - """ - **WARNING:** This method is provided **strictly** for - backward-compatibility. It returns results in an incorrect order. - - If you are writing new code, please use ``Table.query_2``. - """ - reverse = not reverse - return self.query_2(limit=limit, index=index, reverse=reverse, - consistent=consistent, attributes=attributes, - max_page_size=max_page_size, **filter_kwargs) - - def query_2(self, limit=None, index=None, reverse=False, - consistent=False, attributes=None, max_page_size=None, - query_filter=None, conditional_operator=None, - **filter_kwargs): - """ - Queries for a set of matching items in a DynamoDB table. - - Queries can be performed against a hash key, a hash+range key or - against any data stored in your local secondary indexes. Query filters - can be used to filter on arbitrary fields. - - **Note** - You can not query against arbitrary fields within the data - stored in DynamoDB unless you specify ``query_filter`` values. - - To specify the filters of the items you'd like to get, you can specify - the filters as kwargs. Each filter kwarg should follow the pattern - ``<fieldname>__<filter_operation>=<value_to_look_for>``. Query filters - are specified in the same way. - - Optionally accepts a ``limit`` parameter, which should be an integer - count of the total number of items to return. (Default: ``None`` - - all results) - - Optionally accepts an ``index`` parameter, which should be a string of - name of the local secondary index you want to query against. - (Default: ``None``) - - Optionally accepts a ``reverse`` parameter, which will present the - results in reverse order. (Default: ``False`` - normal order) - - Optionally accepts a ``consistent`` parameter, which should be a - boolean. If you provide ``True``, it will force a consistent read of - the data (more expensive). (Default: ``False`` - use eventually - consistent reads) - - Optionally accepts a ``attributes`` parameter, which should be a - tuple. If you provide any attributes only these will be fetched - from DynamoDB. This uses the ``AttributesToGet`` and set's - ``Select`` to ``SPECIFIC_ATTRIBUTES`` API. - - Optionally accepts a ``max_page_size`` parameter, which should be an - integer count of the maximum number of items to retrieve - **per-request**. This is useful in making faster requests & prevent - the scan from drowning out other queries. (Default: ``None`` - - fetch as many as DynamoDB will return) - - Optionally accepts a ``query_filter`` which is a dictionary of filter - conditions against any arbitrary field in the returned data. - - Optionally accepts a ``conditional_operator`` which applies to the - query filter conditions: - - + `AND` - True if all filter conditions evaluate to true (default) - + `OR` - True if at least one filter condition evaluates to true - - Returns a ``ResultSet``, which transparently handles the pagination of - results you get back. - - Example:: - - # Look for last names equal to "Doe". - >>> results = users.query(last_name__eq='Doe') - >>> for res in results: - ... print res['first_name'] - 'John' - 'Jane' - - # Look for last names beginning with "D", in reverse order, limit 3. - >>> results = users.query( - ... last_name__beginswith='D', - ... reverse=True, - ... limit=3 - ... ) - >>> for res in results: - ... print res['first_name'] - 'Alice' - 'Jane' - 'John' - - # Use an LSI & a consistent read. - >>> results = users.query( - ... date_joined__gte=1236451000, - ... owner__eq=1, - ... index='DateJoinedIndex', - ... consistent=True - ... ) - >>> for res in results: - ... print res['first_name'] - 'Alice' - 'Bob' - 'John' - 'Fred' - - # Filter by non-indexed field(s) - >>> results = users.query( - ... last_name__eq='Doe', - ... reverse=True, - ... query_filter={ - ... 'first_name__beginswith': 'A' - ... } - ... ) - >>> for res in results: - ... print res['first_name'] + ' ' + res['last_name'] - 'Alice Doe' - - """ - if self.schema: - if len(self.schema) == 1: - if len(filter_kwargs) <= 1: - if not self.global_indexes or not len(self.global_indexes): - # If the schema only has one field, there's <= 1 filter - # param & no Global Secondary Indexes, this is user - # error. Bail early. - raise exceptions.QueryError( - "You must specify more than one key to filter on." - ) - - if attributes is not None: - select = 'SPECIFIC_ATTRIBUTES' - else: - select = None - - results = ResultSet( - max_page_size=max_page_size - ) - kwargs = filter_kwargs.copy() - kwargs.update({ - 'limit': limit, - 'index': index, - 'reverse': reverse, - 'consistent': consistent, - 'select': select, - 'attributes_to_get': attributes, - 'query_filter': query_filter, - 'conditional_operator': conditional_operator, - }) - results.to_call(self._query, **kwargs) - return results - - def query_count(self, index=None, consistent=False, conditional_operator=None, - query_filter=None, scan_index_forward=True, limit=None, - **filter_kwargs): - """ - Queries the exact count of matching items in a DynamoDB table. - - Queries can be performed against a hash key, a hash+range key or - against any data stored in your local secondary indexes. Query filters - can be used to filter on arbitrary fields. - - To specify the filters of the items you'd like to get, you can specify - the filters as kwargs. Each filter kwarg should follow the pattern - ``<fieldname>__<filter_operation>=<value_to_look_for>``. Query filters - are specified in the same way. - - Optionally accepts an ``index`` parameter, which should be a string of - name of the local secondary index you want to query against. - (Default: ``None``) - - Optionally accepts a ``consistent`` parameter, which should be a - boolean. If you provide ``True``, it will force a consistent read of - the data (more expensive). (Default: ``False`` - use eventually - consistent reads) - - Optionally accepts a ``query_filter`` which is a dictionary of filter - conditions against any arbitrary field in the returned data. - - Optionally accepts a ``conditional_operator`` which applies to the - query filter conditions: - - + `AND` - True if all filter conditions evaluate to true (default) - + `OR` - True if at least one filter condition evaluates to true - - Returns an integer which represents the exact amount of matched - items. - - :type scan_index_forward: boolean - :param scan_index_forward: Specifies ascending (true) or descending - (false) traversal of the index. DynamoDB returns results reflecting - the requested order determined by the range key. If the data type - is Number, the results are returned in numeric order. For String, - the results are returned in order of ASCII character code values. - For Binary, DynamoDB treats each byte of the binary data as - unsigned when it compares binary values. - - If ScanIndexForward is not specified, the results are returned in - ascending order. - - :type limit: integer - :param limit: The maximum number of items to evaluate (not necessarily - the number of matching items). - - Example:: - - # Look for last names equal to "Doe". - >>> users.query_count(last_name__eq='Doe') - 5 - - # Use an LSI & a consistent read. - >>> users.query_count( - ... date_joined__gte=1236451000, - ... owner__eq=1, - ... index='DateJoinedIndex', - ... consistent=True - ... ) - 2 - - """ - key_conditions = self._build_filters( - filter_kwargs, - using=QUERY_OPERATORS - ) - - built_query_filter = self._build_filters( - query_filter, - using=FILTER_OPERATORS - ) - - raw_results = self.connection.query( - self.table_name, - index_name=index, - consistent_read=consistent, - select='COUNT', - key_conditions=key_conditions, - query_filter=built_query_filter, - conditional_operator=conditional_operator, - limit=limit, - scan_index_forward=scan_index_forward, - ) - return int(raw_results.get('Count', 0)) - - def _query(self, limit=None, index=None, reverse=False, consistent=False, - exclusive_start_key=None, select=None, attributes_to_get=None, - query_filter=None, conditional_operator=None, **filter_kwargs): - """ - The internal method that performs the actual queries. Used extensively - by ``ResultSet`` to perform each (paginated) request. - """ - kwargs = { - 'limit': limit, - 'index_name': index, - 'consistent_read': consistent, - 'select': select, - 'attributes_to_get': attributes_to_get, - 'conditional_operator': conditional_operator, - } - - if reverse: - kwargs['scan_index_forward'] = False - - if exclusive_start_key: - kwargs['exclusive_start_key'] = {} - - for key, value in exclusive_start_key.items(): - kwargs['exclusive_start_key'][key] = \ - self._dynamizer.encode(value) - - # Convert the filters into something we can actually use. - kwargs['key_conditions'] = self._build_filters( - filter_kwargs, - using=QUERY_OPERATORS - ) - - kwargs['query_filter'] = self._build_filters( - query_filter, - using=FILTER_OPERATORS - ) - - raw_results = self.connection.query( - self.table_name, - **kwargs - ) - results = [] - last_key = None - - for raw_item in raw_results.get('Items', []): - item = Item(self) - item.load({ - 'Item': raw_item, - }) - results.append(item) - - if raw_results.get('LastEvaluatedKey', None): - last_key = {} - - for key, value in raw_results['LastEvaluatedKey'].items(): - last_key[key] = self._dynamizer.decode(value) - - return { - 'results': results, - 'last_key': last_key, - } - - def scan(self, limit=None, segment=None, total_segments=None, - max_page_size=None, attributes=None, conditional_operator=None, - **filter_kwargs): - """ - Scans across all items within a DynamoDB table. - - Scans can be performed against a hash key or a hash+range key. You can - additionally filter the results after the table has been read but - before the response is returned by using query filters. - - To specify the filters of the items you'd like to get, you can specify - the filters as kwargs. Each filter kwarg should follow the pattern - ``<fieldname>__<filter_operation>=<value_to_look_for>``. - - Optionally accepts a ``limit`` parameter, which should be an integer - count of the total number of items to return. (Default: ``None`` - - all results) - - Optionally accepts a ``segment`` parameter, which should be an integer - of the segment to retrieve on. Please see the documentation about - Parallel Scans (Default: ``None`` - no segments) - - Optionally accepts a ``total_segments`` parameter, which should be an - integer count of number of segments to divide the table into. - Please see the documentation about Parallel Scans (Default: ``None`` - - no segments) - - Optionally accepts a ``max_page_size`` parameter, which should be an - integer count of the maximum number of items to retrieve - **per-request**. This is useful in making faster requests & prevent - the scan from drowning out other queries. (Default: ``None`` - - fetch as many as DynamoDB will return) - - Optionally accepts an ``attributes`` parameter, which should be a - tuple. If you provide any attributes only these will be fetched - from DynamoDB. This uses the ``AttributesToGet`` and set's - ``Select`` to ``SPECIFIC_ATTRIBUTES`` API. - - Returns a ``ResultSet``, which transparently handles the pagination of - results you get back. - - Example:: - - # All results. - >>> everything = users.scan() - - # Look for last names beginning with "D". - >>> results = users.scan(last_name__beginswith='D') - >>> for res in results: - ... print res['first_name'] - 'Alice' - 'John' - 'Jane' - - # Use an ``IN`` filter & limit. - >>> results = users.scan( - ... age__in=[25, 26, 27, 28, 29], - ... limit=1 - ... ) - >>> for res in results: - ... print res['first_name'] - 'Alice' - - """ - results = ResultSet( - max_page_size=max_page_size - ) - kwargs = filter_kwargs.copy() - kwargs.update({ - 'limit': limit, - 'segment': segment, - 'total_segments': total_segments, - 'attributes': attributes, - 'conditional_operator': conditional_operator, - }) - results.to_call(self._scan, **kwargs) - return results - - def _scan(self, limit=None, exclusive_start_key=None, segment=None, - total_segments=None, attributes=None, conditional_operator=None, - **filter_kwargs): - """ - The internal method that performs the actual scan. Used extensively - by ``ResultSet`` to perform each (paginated) request. - """ - kwargs = { - 'limit': limit, - 'segment': segment, - 'total_segments': total_segments, - 'attributes_to_get': attributes, - 'conditional_operator': conditional_operator, - } - - if exclusive_start_key: - kwargs['exclusive_start_key'] = {} - - for key, value in exclusive_start_key.items(): - kwargs['exclusive_start_key'][key] = \ - self._dynamizer.encode(value) - - # Convert the filters into something we can actually use. - kwargs['scan_filter'] = self._build_filters( - filter_kwargs, - using=FILTER_OPERATORS - ) - - raw_results = self.connection.scan( - self.table_name, - **kwargs - ) - results = [] - last_key = None - - for raw_item in raw_results.get('Items', []): - item = Item(self) - item.load({ - 'Item': raw_item, - }) - results.append(item) - - if raw_results.get('LastEvaluatedKey', None): - last_key = {} - - for key, value in raw_results['LastEvaluatedKey'].items(): - last_key[key] = self._dynamizer.decode(value) - - return { - 'results': results, - 'last_key': last_key, - } - - def batch_get(self, keys, consistent=False, attributes=None): - """ - Fetches many specific items in batch from a table. - - Requires a ``keys`` parameter, which should be a list of dictionaries. - Each dictionary should consist of the keys values to specify. - - Optionally accepts a ``consistent`` parameter, which should be a - boolean. If you provide ``True``, a strongly consistent read will be - used. (Default: False) - - Optionally accepts an ``attributes`` parameter, which should be a - tuple. If you provide any attributes only these will be fetched - from DynamoDB. - - Returns a ``ResultSet``, which transparently handles the pagination of - results you get back. - - Example:: - - >>> results = users.batch_get(keys=[ - ... { - ... 'username': 'johndoe', - ... }, - ... { - ... 'username': 'jane', - ... }, - ... { - ... 'username': 'fred', - ... }, - ... ]) - >>> for res in results: - ... print res['first_name'] - 'John' - 'Jane' - 'Fred' - - """ - # We pass the keys to the constructor instead, so it can maintain it's - # own internal state as to what keys have been processed. - results = BatchGetResultSet(keys=keys, max_batch_get=self.max_batch_get) - results.to_call(self._batch_get, consistent=consistent, attributes=attributes) - return results - - def _batch_get(self, keys, consistent=False, attributes=None): - """ - The internal method that performs the actual batch get. Used extensively - by ``BatchGetResultSet`` to perform each (paginated) request. - """ - items = { - self.table_name: { - 'Keys': [], - }, - } - - if consistent: - items[self.table_name]['ConsistentRead'] = True - - if attributes is not None: - items[self.table_name]['AttributesToGet'] = attributes - - for key_data in keys: - raw_key = {} - - for key, value in key_data.items(): - raw_key[key] = self._dynamizer.encode(value) - - items[self.table_name]['Keys'].append(raw_key) - - raw_results = self.connection.batch_get_item(request_items=items) - results = [] - unprocessed_keys = [] - - for raw_item in raw_results['Responses'].get(self.table_name, []): - item = Item(self) - item.load({ - 'Item': raw_item, - }) - results.append(item) - - raw_unproccessed = raw_results.get('UnprocessedKeys', {}) - - for raw_key in raw_unproccessed.get('Keys', []): - py_key = {} - - for key, value in raw_key.items(): - py_key[key] = self._dynamizer.decode(value) - - unprocessed_keys.append(py_key) - - return { - 'results': results, - # NEVER return a ``last_key``. Just in-case any part of - # ``ResultSet`` peeks through, since much of the - # original underlying implementation is based on this key. - 'last_key': None, - 'unprocessed_keys': unprocessed_keys, - } - - def count(self): - """ - Returns a (very) eventually consistent count of the number of items - in a table. - - Lag time is about 6 hours, so don't expect a high degree of accuracy. - - Example:: - - >>> users.count() - 6 - - """ - info = self.describe() - return info['Table'].get('ItemCount', 0) - - -class BatchTable(object): - """ - Used by ``Table`` as the context manager for batch writes. - - You likely don't want to try to use this object directly. - """ - def __init__(self, table): - self.table = table - self._to_put = [] - self._to_delete = [] - self._unprocessed = [] - - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - if self._to_put or self._to_delete: - # Flush anything that's left. - self.flush() - - if self._unprocessed: - # Finally, handle anything that wasn't processed. - self.resend_unprocessed() - - def put_item(self, data, overwrite=False): - self._to_put.append(data) - - if self.should_flush(): - self.flush() - - def delete_item(self, **kwargs): - self._to_delete.append(kwargs) - - if self.should_flush(): - self.flush() - - def should_flush(self): - if len(self._to_put) + len(self._to_delete) == 25: - return True - - return False - - def flush(self): - batch_data = { - self.table.table_name: [ - # We'll insert data here shortly. - ], - } - - for put in self._to_put: - item = Item(self.table, data=put) - batch_data[self.table.table_name].append({ - 'PutRequest': { - 'Item': item.prepare_full(), - } - }) - - for delete in self._to_delete: - batch_data[self.table.table_name].append({ - 'DeleteRequest': { - 'Key': self.table._encode_keys(delete), - } - }) - - resp = self.table.connection.batch_write_item(batch_data) - self.handle_unprocessed(resp) - - self._to_put = [] - self._to_delete = [] - return True - - def handle_unprocessed(self, resp): - if len(resp.get('UnprocessedItems', [])): - table_name = self.table.table_name - unprocessed = resp['UnprocessedItems'].get(table_name, []) - - # Some items have not been processed. Stow them for now & - # re-attempt processing on ``__exit__``. - msg = "%s items were unprocessed. Storing for later." - boto.log.info(msg % len(unprocessed)) - self._unprocessed.extend(unprocessed) - - def resend_unprocessed(self): - # If there are unprocessed records (for instance, the user was over - # their throughput limitations), iterate over them & send until they're - # all there. - boto.log.info( - "Re-sending %s unprocessed items." % len(self._unprocessed) - ) - - while len(self._unprocessed): - # Again, do 25 at a time. - to_resend = self._unprocessed[:25] - # Remove them from the list. - self._unprocessed = self._unprocessed[25:] - batch_data = { - self.table.table_name: to_resend - } - boto.log.info("Sending %s items" % len(to_resend)) - resp = self.table.connection.batch_write_item(batch_data) - self.handle_unprocessed(resp) - boto.log.info( - "%s unprocessed items left" % len(self._unprocessed) - ) diff --git a/awx/lib/site-packages/boto/dynamodb2/types.py b/awx/lib/site-packages/boto/dynamodb2/types.py deleted file mode 100644 index fc67aa012c..0000000000 --- a/awx/lib/site-packages/boto/dynamodb2/types.py +++ /dev/null @@ -1,40 +0,0 @@ -# Shadow the DynamoDB v1 bits. -# This way, no end user should have to cross-import between versions & we -# reserve the namespace to extend v2 if it's ever needed. -from boto.dynamodb.types import Dynamizer - - -# Some constants for our use. -STRING = 'S' -NUMBER = 'N' -BINARY = 'B' -STRING_SET = 'SS' -NUMBER_SET = 'NS' -BINARY_SET = 'BS' - -QUERY_OPERATORS = { - 'eq': 'EQ', - 'lte': 'LE', - 'lt': 'LT', - 'gte': 'GE', - 'gt': 'GT', - 'beginswith': 'BEGINS_WITH', - 'between': 'BETWEEN', -} - -FILTER_OPERATORS = { - 'eq': 'EQ', - 'ne': 'NE', - 'lte': 'LE', - 'lt': 'LT', - 'gte': 'GE', - 'gt': 'GT', - # FIXME: Is this necessary? i.e. ``whatever__null=False`` - 'nnull': 'NOT_NULL', - 'null': 'NULL', - 'contains': 'CONTAINS', - 'ncontains': 'NOT_CONTAINS', - 'beginswith': 'BEGINS_WITH', - 'in': 'IN', - 'between': 'BETWEEN', -} diff --git a/awx/lib/site-packages/boto/ec2/__init__.py b/awx/lib/site-packages/boto/ec2/__init__.py deleted file mode 100644 index c3976da19f..0000000000 --- a/awx/lib/site-packages/boto/ec2/__init__.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2006-2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -""" -This module provides an interface to the Elastic Compute Cloud (EC2) -service from AWS. -""" -from boto.ec2.connection import EC2Connection -from boto.regioninfo import RegionInfo, get_regions, load_regions - - -RegionData = load_regions().get('ec2', {}) - - -def regions(**kw_params): - """ - Get all available regions for the EC2 service. - You may pass any of the arguments accepted by the EC2Connection - object's constructor as keyword arguments and they will be - passed along to the EC2Connection object. - - :rtype: list - :return: A list of :class:`boto.ec2.regioninfo.RegionInfo` - """ - return get_regions('ec2', connection_cls=EC2Connection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.ec2.connection.EC2Connection`. - Any additional parameters after the region_name are passed on to - the connect method of the region object. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.ec2.connection.EC2Connection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - if 'region' in kw_params and isinstance(kw_params['region'], RegionInfo)\ - and region_name == kw_params['region'].name: - return EC2Connection(**kw_params) - - for region in regions(**kw_params): - if region.name == region_name: - return region.connect(**kw_params) - - return None - - -def get_region(region_name, **kw_params): - """ - Find and return a :class:`boto.ec2.regioninfo.RegionInfo` object - given a region name. - - :type: str - :param: The name of the region. - - :rtype: :class:`boto.ec2.regioninfo.RegionInfo` - :return: The RegionInfo object for the given region or None if - an invalid region name is provided. - """ - for region in regions(**kw_params): - if region.name == region_name: - return region - return None diff --git a/awx/lib/site-packages/boto/ec2/address.py b/awx/lib/site-packages/boto/ec2/address.py deleted file mode 100644 index 807406f78b..0000000000 --- a/awx/lib/site-packages/boto/ec2/address.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -from boto.ec2.ec2object import EC2Object - - -class Address(EC2Object): - """ - Represents an EC2 Elastic IP Address - - :ivar public_ip: The Elastic IP address. - :ivar instance_id: The instance the address is associated with (if any). - :ivar domain: Indicates whether the address is a EC2 address or a VPC address (standard|vpc). - :ivar allocation_id: The allocation ID for the address (VPC addresses only). - :ivar association_id: The association ID for the address (VPC addresses only). - :ivar network_interface_id: The network interface (if any) that the address is associated with (VPC addresses only). - :ivar network_interface_owner_id: The owner IID (VPC addresses only). - :ivar private_ip_address: The private IP address associated with the Elastic IP address (VPC addresses only). - """ - - def __init__(self, connection=None, public_ip=None, instance_id=None): - super(Address, self).__init__(connection) - self.connection = connection - self.public_ip = public_ip - self.instance_id = instance_id - self.domain = None - self.allocation_id = None - self.association_id = None - self.network_interface_id = None - self.network_interface_owner_id = None - self.private_ip_address = None - - def __repr__(self): - return 'Address:%s' % self.public_ip - - def endElement(self, name, value, connection): - if name == 'publicIp': - self.public_ip = value - elif name == 'instanceId': - self.instance_id = value - elif name == 'domain': - self.domain = value - elif name == 'allocationId': - self.allocation_id = value - elif name == 'associationId': - self.association_id = value - elif name == 'networkInterfaceId': - self.network_interface_id = value - elif name == 'networkInterfaceOwnerId': - self.network_interface_owner_id = value - elif name == 'privateIpAddress': - self.private_ip_address = value - else: - setattr(self, name, value) - - def release(self, dry_run=False): - """ - Free up this Elastic IP address. - :see: :meth:`boto.ec2.connection.EC2Connection.release_address` - """ - if self.allocation_id: - return self.connection.release_address( - allocation_id=self.allocation_id, - dry_run=dry_run) - else: - return self.connection.release_address( - public_ip=self.public_ip, - dry_run=dry_run - ) - - delete = release - - def associate(self, instance_id=None, network_interface_id=None, private_ip_address=None, allow_reassociation=False, dry_run=False): - """ - Associate this Elastic IP address with a currently running instance. - :see: :meth:`boto.ec2.connection.EC2Connection.associate_address` - """ - if self.allocation_id: - return self.connection.associate_address( - instance_id=instance_id, - public_ip=self.public_ip, - allocation_id=self.allocation_id, - network_interface_id=network_interface_id, - private_ip_address=private_ip_address, - allow_reassociation=allow_reassociation, - dry_run=dry_run - ) - return self.connection.associate_address( - instance_id=instance_id, - public_ip=self.public_ip, - network_interface_id=network_interface_id, - private_ip_address=private_ip_address, - allow_reassociation=allow_reassociation, - dry_run=dry_run - ) - - def disassociate(self, dry_run=False): - """ - Disassociate this Elastic IP address from a currently running instance. - :see: :meth:`boto.ec2.connection.EC2Connection.disassociate_address` - """ - if self.association_id: - return self.connection.disassociate_address( - association_id=self.association_id, - dry_run=dry_run - ) - else: - return self.connection.disassociate_address( - public_ip=self.public_ip, - dry_run=dry_run - ) diff --git a/awx/lib/site-packages/boto/ec2/attributes.py b/awx/lib/site-packages/boto/ec2/attributes.py deleted file mode 100644 index d76e5c5428..0000000000 --- a/awx/lib/site-packages/boto/ec2/attributes.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class AccountAttribute(object): - def __init__(self, connection=None): - self.connection = connection - self.attribute_name = None - self.attribute_values = None - - def startElement(self, name, attrs, connection): - if name == 'attributeValueSet': - self.attribute_values = AttributeValues() - return self.attribute_values - - def endElement(self, name, value, connection): - if name == 'attributeName': - self.attribute_name = value - - -class AttributeValues(list): - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'attributeValue': - self.append(value) - - -class VPCAttribute(object): - def __init__(self, connection=None): - self.connection = connection - self.vpc_id = None - self.enable_dns_hostnames = None - self.enable_dns_support = None - self._current_attr = None - - def startElement(self, name, attrs, connection): - if name in ('enableDnsHostnames', 'enableDnsSupport'): - self._current_attr = name - - def endElement(self, name, value, connection): - if name == 'vpcId': - self.vpc_id = value - elif name == 'value': - if value == 'true': - value = True - else: - value = False - if self._current_attr == 'enableDnsHostnames': - self.enable_dns_hostnames = value - elif self._current_attr == 'enableDnsSupport': - self.enable_dns_support = value diff --git a/awx/lib/site-packages/boto/ec2/autoscale/__init__.py b/awx/lib/site-packages/boto/ec2/autoscale/__init__.py deleted file mode 100644 index 5a58748d41..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/__init__.py +++ /dev/null @@ -1,866 +0,0 @@ -# Copyright (c) 2009-2011 Reza Lotun http://reza.lotun.name/ -# Copyright (c) 2011 Jann Kleen -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -This module provides an interface to the Elastic Compute Cloud (EC2) -Auto Scaling service. -""" - -import base64 - -import boto -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo, get_regions, load_regions -from boto.ec2.autoscale.request import Request -from boto.ec2.autoscale.launchconfig import LaunchConfiguration -from boto.ec2.autoscale.group import AutoScalingGroup -from boto.ec2.autoscale.group import ProcessType -from boto.ec2.autoscale.activity import Activity -from boto.ec2.autoscale.policy import AdjustmentType -from boto.ec2.autoscale.policy import MetricCollectionTypes -from boto.ec2.autoscale.policy import ScalingPolicy -from boto.ec2.autoscale.policy import TerminationPolicies -from boto.ec2.autoscale.instance import Instance -from boto.ec2.autoscale.scheduled import ScheduledUpdateGroupAction -from boto.ec2.autoscale.tag import Tag -from boto.ec2.autoscale.limits import AccountLimits -from boto.compat import six - -RegionData = load_regions().get('autoscaling', {}) - - -def regions(): - """ - Get all available regions for the Auto Scaling service. - - :rtype: list - :return: A list of :class:`boto.RegionInfo` instances - """ - return get_regions('autoscaling', connection_cls=AutoScaleConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.ec2.autoscale.AutoScaleConnection`. - - :param str region_name: The name of the region to connect to. - - :rtype: :class:`boto.ec2.AutoScaleConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None - - -class AutoScaleConnection(AWSQueryConnection): - APIVersion = boto.config.get('Boto', 'autoscale_version', '2011-01-01') - DefaultRegionEndpoint = boto.config.get('Boto', 'autoscale_endpoint', - 'autoscaling.us-east-1.amazonaws.com') - DefaultRegionName = boto.config.get('Boto', 'autoscale_region_name', - 'us-east-1') - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, profile_name=None, - use_block_device_types=False): - """ - Init method to create a new connection to the AutoScaling service. - - B{Note:} The host argument is overridden by the host specified in the - boto configuration file. - - - """ - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint, - AutoScaleConnection) - self.region = region - self.use_block_device_types = use_block_device_types - super(AutoScaleConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path=path, - security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def build_list_params(self, params, items, label): - """ - Items is a list of dictionaries or strings:: - - [ - { - 'Protocol' : 'HTTP', - 'LoadBalancerPort' : '80', - 'InstancePort' : '80' - }, - .. - ] etc. - - or:: - - ['us-east-1b',...] - """ - # different from EC2 list params - for i in range(1, len(items) + 1): - if isinstance(items[i - 1], dict): - for k, v in six.iteritems(items[i - 1]): - if isinstance(v, dict): - for kk, vv in six.iteritems(v): - params['%s.member.%d.%s.%s' % (label, i, k, kk)] = vv - else: - params['%s.member.%d.%s' % (label, i, k)] = v - elif isinstance(items[i - 1], six.string_types): - params['%s.member.%d' % (label, i)] = items[i - 1] - - def _update_group(self, op, as_group): - params = {'AutoScalingGroupName': as_group.name, - 'LaunchConfigurationName': as_group.launch_config_name, - 'MinSize': as_group.min_size, - 'MaxSize': as_group.max_size} - # get availability zone information (required param) - zones = as_group.availability_zones - self.build_list_params(params, zones, 'AvailabilityZones') - if as_group.desired_capacity is not None: - params['DesiredCapacity'] = as_group.desired_capacity - if as_group.vpc_zone_identifier: - params['VPCZoneIdentifier'] = as_group.vpc_zone_identifier - if as_group.health_check_period: - params['HealthCheckGracePeriod'] = as_group.health_check_period - if as_group.health_check_type: - params['HealthCheckType'] = as_group.health_check_type - if as_group.default_cooldown: - params['DefaultCooldown'] = as_group.default_cooldown - if as_group.placement_group: - params['PlacementGroup'] = as_group.placement_group - if as_group.instance_id: - params['InstanceId'] = as_group.instance_id - if as_group.termination_policies: - self.build_list_params(params, as_group.termination_policies, - 'TerminationPolicies') - if op.startswith('Create'): - # you can only associate load balancers with an autoscale - # group at creation time - if as_group.load_balancers: - self.build_list_params(params, as_group.load_balancers, - 'LoadBalancerNames') - if as_group.tags: - for i, tag in enumerate(as_group.tags): - tag.build_params(params, i + 1) - return self.get_object(op, params, Request) - - def attach_instances(self, name, instance_ids): - """ - Attach instances to an autoscaling group. - """ - params = { - 'AutoScalingGroupName': name, - } - self.build_list_params(params, instance_ids, 'InstanceIds') - return self.get_status('AttachInstances', params) - - def create_auto_scaling_group(self, as_group): - """ - Create auto scaling group. - """ - return self._update_group('CreateAutoScalingGroup', as_group) - - def delete_auto_scaling_group(self, name, force_delete=False): - """ - Deletes the specified auto scaling group if the group has no instances - and no scaling activities in progress. - """ - if(force_delete): - params = {'AutoScalingGroupName': name, 'ForceDelete': 'true'} - else: - params = {'AutoScalingGroupName': name} - return self.get_object('DeleteAutoScalingGroup', params, Request) - - def create_launch_configuration(self, launch_config): - """ - Creates a new Launch Configuration. - - :type launch_config: :class:`boto.ec2.autoscale.launchconfig.LaunchConfiguration` - :param launch_config: LaunchConfiguration object. - """ - params = {'ImageId': launch_config.image_id, - 'LaunchConfigurationName': launch_config.name, - 'InstanceType': launch_config.instance_type} - if launch_config.key_name: - params['KeyName'] = launch_config.key_name - if launch_config.user_data: - user_data = launch_config.user_data - if isinstance(user_data, six.text_type): - user_data = user_data.encode('utf-8') - params['UserData'] = base64.b64encode(user_data).decode('utf-8') - if launch_config.kernel_id: - params['KernelId'] = launch_config.kernel_id - if launch_config.ramdisk_id: - params['RamdiskId'] = launch_config.ramdisk_id - if launch_config.block_device_mappings: - [x.autoscale_build_list_params(params) for x in launch_config.block_device_mappings] - if launch_config.security_groups: - self.build_list_params(params, launch_config.security_groups, - 'SecurityGroups') - if launch_config.instance_monitoring: - params['InstanceMonitoring.Enabled'] = 'true' - else: - params['InstanceMonitoring.Enabled'] = 'false' - if launch_config.spot_price is not None: - params['SpotPrice'] = str(launch_config.spot_price) - if launch_config.instance_profile_name is not None: - params['IamInstanceProfile'] = launch_config.instance_profile_name - if launch_config.ebs_optimized: - params['EbsOptimized'] = 'true' - else: - params['EbsOptimized'] = 'false' - if launch_config.associate_public_ip_address is True: - params['AssociatePublicIpAddress'] = 'true' - elif launch_config.associate_public_ip_address is False: - params['AssociatePublicIpAddress'] = 'false' - if launch_config.volume_type: - params['VolumeType'] = launch_config.volume_type - if launch_config.delete_on_termination: - params['DeleteOnTermination'] = 'true' - else: - params['DeleteOnTermination'] = 'false' - if launch_config.iops: - params['Iops'] = launch_config.iops - return self.get_object('CreateLaunchConfiguration', params, - Request, verb='POST') - - def get_account_limits(self): - """ - Returns the limits for the Auto Scaling resources currently granted for - your AWS account. - """ - params = {} - return self.get_object('DescribeAccountLimits', params, AccountLimits) - - def create_scaling_policy(self, scaling_policy): - """ - Creates a new Scaling Policy. - - :type scaling_policy: :class:`boto.ec2.autoscale.policy.ScalingPolicy` - :param scaling_policy: ScalingPolicy object. - """ - params = {'AdjustmentType': scaling_policy.adjustment_type, - 'AutoScalingGroupName': scaling_policy.as_name, - 'PolicyName': scaling_policy.name, - 'ScalingAdjustment': scaling_policy.scaling_adjustment} - - if scaling_policy.adjustment_type == "PercentChangeInCapacity" and \ - scaling_policy.min_adjustment_step is not None: - params['MinAdjustmentStep'] = scaling_policy.min_adjustment_step - - if scaling_policy.cooldown is not None: - params['Cooldown'] = scaling_policy.cooldown - - return self.get_object('PutScalingPolicy', params, Request) - - def delete_launch_configuration(self, launch_config_name): - """ - Deletes the specified LaunchConfiguration. - - The specified launch configuration must not be attached to an Auto - Scaling group. Once this call completes, the launch configuration is no - longer available for use. - """ - params = {'LaunchConfigurationName': launch_config_name} - return self.get_object('DeleteLaunchConfiguration', params, Request) - - def get_all_groups(self, names=None, max_records=None, next_token=None): - """ - Returns a full description of each Auto Scaling group in the given - list. This includes all Amazon EC2 instances that are members of the - group. If a list of names is not provided, the service returns the full - details of all Auto Scaling groups. - - This action supports pagination by returning a token if there are more - pages to retrieve. To get the next page, call this action again with - the returned token as the NextToken parameter. - - :type names: list - :param names: List of group names which should be searched for. - - :type max_records: int - :param max_records: Maximum amount of groups to return. - - :rtype: list - :returns: List of :class:`boto.ec2.autoscale.group.AutoScalingGroup` - instances. - """ - params = {} - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - if names: - self.build_list_params(params, names, 'AutoScalingGroupNames') - return self.get_list('DescribeAutoScalingGroups', params, - [('member', AutoScalingGroup)]) - - def get_all_launch_configurations(self, **kwargs): - """ - Returns a full description of the launch configurations given the - specified names. - - If no names are specified, then the full details of all launch - configurations are returned. - - :type names: list - :param names: List of configuration names which should be searched for. - - :type max_records: int - :param max_records: Maximum amount of configurations to return. - - :type next_token: str - :param next_token: If you have more results than can be returned - at once, pass in this parameter to page through all results. - - :rtype: list - :returns: List of - :class:`boto.ec2.autoscale.launchconfig.LaunchConfiguration` - instances. - """ - params = {} - max_records = kwargs.get('max_records', None) - names = kwargs.get('names', None) - if max_records is not None: - params['MaxRecords'] = max_records - if names: - self.build_list_params(params, names, 'LaunchConfigurationNames') - next_token = kwargs.get('next_token') - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribeLaunchConfigurations', params, - [('member', LaunchConfiguration)]) - - def get_all_activities(self, autoscale_group, activity_ids=None, - max_records=None, next_token=None): - """ - Get all activities for the given autoscaling group. - - This action supports pagination by returning a token if there are more - pages to retrieve. To get the next page, call this action again with - the returned token as the NextToken parameter - - :type autoscale_group: str or - :class:`boto.ec2.autoscale.group.AutoScalingGroup` object - :param autoscale_group: The auto scaling group to get activities on. - - :type max_records: int - :param max_records: Maximum amount of activities to return. - - :rtype: list - :returns: List of - :class:`boto.ec2.autoscale.activity.Activity` instances. - """ - name = autoscale_group - if isinstance(autoscale_group, AutoScalingGroup): - name = autoscale_group.name - params = {'AutoScalingGroupName': name} - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - if activity_ids: - self.build_list_params(params, activity_ids, 'ActivityIds') - return self.get_list('DescribeScalingActivities', - params, [('member', Activity)]) - - def get_termination_policies(self): - """Gets all valid termination policies. - - These values can then be used as the termination_policies arg - when creating and updating autoscale groups. - """ - return self.get_object('DescribeTerminationPolicyTypes', - {}, TerminationPolicies) - - def delete_scheduled_action(self, scheduled_action_name, - autoscale_group=None): - """ - Deletes a previously scheduled action. - - :type scheduled_action_name: str - :param scheduled_action_name: The name of the action you want - to delete. - - :type autoscale_group: str - :param autoscale_group: The name of the autoscale group. - """ - params = {'ScheduledActionName': scheduled_action_name} - if autoscale_group: - params['AutoScalingGroupName'] = autoscale_group - return self.get_status('DeleteScheduledAction', params) - - def terminate_instance(self, instance_id, decrement_capacity=True): - """ - Terminates the specified instance. The desired group size can - also be adjusted, if desired. - - :type instance_id: str - :param instance_id: The ID of the instance to be terminated. - - :type decrement_capability: bool - :param decrement_capacity: Whether to decrement the size of the - autoscaling group or not. - """ - params = {'InstanceId': instance_id} - if decrement_capacity: - params['ShouldDecrementDesiredCapacity'] = 'true' - else: - params['ShouldDecrementDesiredCapacity'] = 'false' - return self.get_object('TerminateInstanceInAutoScalingGroup', params, - Activity) - - def delete_policy(self, policy_name, autoscale_group=None): - """ - Delete a policy. - - :type policy_name: str - :param policy_name: The name or ARN of the policy to delete. - - :type autoscale_group: str - :param autoscale_group: The name of the autoscale group. - """ - params = {'PolicyName': policy_name} - if autoscale_group: - params['AutoScalingGroupName'] = autoscale_group - return self.get_status('DeletePolicy', params) - - def get_all_adjustment_types(self): - return self.get_list('DescribeAdjustmentTypes', {}, - [('member', AdjustmentType)]) - - def get_all_autoscaling_instances(self, instance_ids=None, - max_records=None, next_token=None): - """ - Returns a description of each Auto Scaling instance in the instance_ids - list. If a list is not provided, the service returns the full details - of all instances up to a maximum of fifty. - - This action supports pagination by returning a token if there are more - pages to retrieve. To get the next page, call this action again with - the returned token as the NextToken parameter. - - :type instance_ids: list - :param instance_ids: List of Autoscaling Instance IDs which should be - searched for. - - :type max_records: int - :param max_records: Maximum number of results to return. - - :rtype: list - :returns: List of - :class:`boto.ec2.autoscale.instance.Instance` objects. - """ - params = {} - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceIds') - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribeAutoScalingInstances', - params, [('member', Instance)]) - - def get_all_metric_collection_types(self): - """ - Returns a list of metrics and a corresponding list of granularities - for each metric. - """ - return self.get_object('DescribeMetricCollectionTypes', - {}, MetricCollectionTypes) - - def get_all_policies(self, as_group=None, policy_names=None, - max_records=None, next_token=None): - """ - Returns descriptions of what each policy does. This action supports - pagination. If the response includes a token, there are more records - available. To get the additional records, repeat the request with the - response token as the NextToken parameter. - - If no group name or list of policy names are provided, all - available policies are returned. - - :type as_group: str - :param as_group: The name of the - :class:`boto.ec2.autoscale.group.AutoScalingGroup` to filter for. - - :type policy_names: list - :param policy_names: List of policy names which should be searched for. - - :type max_records: int - :param max_records: Maximum amount of groups to return. - - :type next_token: str - :param next_token: If you have more results than can be returned - at once, pass in this parameter to page through all results. - """ - params = {} - if as_group: - params['AutoScalingGroupName'] = as_group - if policy_names: - self.build_list_params(params, policy_names, 'PolicyNames') - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribePolicies', params, - [('member', ScalingPolicy)]) - - def get_all_scaling_process_types(self): - """ - Returns scaling process types for use in the ResumeProcesses and - SuspendProcesses actions. - """ - return self.get_list('DescribeScalingProcessTypes', {}, - [('member', ProcessType)]) - - def suspend_processes(self, as_group, scaling_processes=None): - """ - Suspends Auto Scaling processes for an Auto Scaling group. - - :type as_group: string - :param as_group: The auto scaling group to suspend processes on. - - :type scaling_processes: list - :param scaling_processes: Processes you want to suspend. If omitted, - all processes will be suspended. - """ - params = {'AutoScalingGroupName': as_group} - if scaling_processes: - self.build_list_params(params, scaling_processes, - 'ScalingProcesses') - return self.get_status('SuspendProcesses', params) - - def resume_processes(self, as_group, scaling_processes=None): - """ - Resumes Auto Scaling processes for an Auto Scaling group. - - :type as_group: string - :param as_group: The auto scaling group to resume processes on. - - :type scaling_processes: list - :param scaling_processes: Processes you want to resume. If omitted, all - processes will be resumed. - """ - params = {'AutoScalingGroupName': as_group} - - if scaling_processes: - self.build_list_params(params, scaling_processes, - 'ScalingProcesses') - return self.get_status('ResumeProcesses', params) - - def create_scheduled_group_action(self, as_group, name, time=None, - desired_capacity=None, - min_size=None, max_size=None, - start_time=None, end_time=None, - recurrence=None): - """ - Creates a scheduled scaling action for a Auto Scaling group. If you - leave a parameter unspecified, the corresponding value remains - unchanged in the affected Auto Scaling group. - - :type as_group: string - :param as_group: The auto scaling group to get activities on. - - :type name: string - :param name: Scheduled action name. - - :type time: datetime.datetime - :param time: The time for this action to start. (Depracated) - - :type desired_capacity: int - :param desired_capacity: The number of EC2 instances that should - be running in this group. - - :type min_size: int - :param min_size: The minimum size for the new auto scaling group. - - :type max_size: int - :param max_size: The minimum size for the new auto scaling group. - - :type start_time: datetime.datetime - :param start_time: The time for this action to start. When StartTime and EndTime are specified with Recurrence, they form the boundaries of when the recurring action will start and stop. - - :type end_time: datetime.datetime - :param end_time: The time for this action to end. When StartTime and EndTime are specified with Recurrence, they form the boundaries of when the recurring action will start and stop. - - :type recurrence: string - :param recurrence: The time when recurring future actions will start. Start time is specified by the user following the Unix cron syntax format. EXAMPLE: '0 10 * * *' - """ - params = {'AutoScalingGroupName': as_group, - 'ScheduledActionName': name} - if start_time is not None: - params['StartTime'] = start_time.isoformat() - if end_time is not None: - params['EndTime'] = end_time.isoformat() - if recurrence is not None: - params['Recurrence'] = recurrence - if time: - params['Time'] = time.isoformat() - if desired_capacity is not None: - params['DesiredCapacity'] = desired_capacity - if min_size is not None: - params['MinSize'] = min_size - if max_size is not None: - params['MaxSize'] = max_size - return self.get_status('PutScheduledUpdateGroupAction', params) - - def get_all_scheduled_actions(self, as_group=None, start_time=None, - end_time=None, scheduled_actions=None, - max_records=None, next_token=None): - params = {} - if as_group: - params['AutoScalingGroupName'] = as_group - if scheduled_actions: - self.build_list_params(params, scheduled_actions, - 'ScheduledActionNames') - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribeScheduledActions', params, - [('member', ScheduledUpdateGroupAction)]) - - def disable_metrics_collection(self, as_group, metrics=None): - """ - Disables monitoring of group metrics for the Auto Scaling group - specified in AutoScalingGroupName. You can specify the list of affected - metrics with the Metrics parameter. - """ - params = {'AutoScalingGroupName': as_group} - - if metrics: - self.build_list_params(params, metrics, 'Metrics') - return self.get_status('DisableMetricsCollection', params) - - def enable_metrics_collection(self, as_group, granularity, metrics=None): - """ - Enables monitoring of group metrics for the Auto Scaling group - specified in AutoScalingGroupName. You can specify the list of enabled - metrics with the Metrics parameter. - - Auto scaling metrics collection can be turned on only if the - InstanceMonitoring.Enabled flag, in the Auto Scaling group's launch - configuration, is set to true. - - :type autoscale_group: string - :param autoscale_group: The auto scaling group to get activities on. - - :type granularity: string - :param granularity: The granularity to associate with the metrics to - collect. Currently, the only legal granularity is "1Minute". - - :type metrics: string list - :param metrics: The list of metrics to collect. If no metrics are - specified, all metrics are enabled. - """ - params = {'AutoScalingGroupName': as_group, - 'Granularity': granularity} - if metrics: - self.build_list_params(params, metrics, 'Metrics') - return self.get_status('EnableMetricsCollection', params) - - def execute_policy(self, policy_name, as_group=None, honor_cooldown=None): - params = {'PolicyName': policy_name} - if as_group: - params['AutoScalingGroupName'] = as_group - if honor_cooldown: - params['HonorCooldown'] = honor_cooldown - return self.get_status('ExecutePolicy', params) - - def put_notification_configuration(self, autoscale_group, topic, notification_types): - """ - Configures an Auto Scaling group to send notifications when - specified events take place. - - :type autoscale_group: str or - :class:`boto.ec2.autoscale.group.AutoScalingGroup` object - :param autoscale_group: The Auto Scaling group to put notification - configuration on. - - :type topic: str - :param topic: The Amazon Resource Name (ARN) of the Amazon Simple - Notification Service (SNS) topic. - - :type notification_types: list - :param notification_types: The type of events that will trigger - the notification. Valid types are: - 'autoscaling:EC2_INSTANCE_LAUNCH', - 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR', - 'autoscaling:EC2_INSTANCE_TERMINATE', - 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR', - 'autoscaling:TEST_NOTIFICATION' - """ - - name = autoscale_group - if isinstance(autoscale_group, AutoScalingGroup): - name = autoscale_group.name - - params = {'AutoScalingGroupName': name, - 'TopicARN': topic} - self.build_list_params(params, notification_types, 'NotificationTypes') - return self.get_status('PutNotificationConfiguration', params) - - def delete_notification_configuration(self, autoscale_group, topic): - """ - Deletes notifications created by put_notification_configuration. - - :type autoscale_group: str or - :class:`boto.ec2.autoscale.group.AutoScalingGroup` object - :param autoscale_group: The Auto Scaling group to put notification - configuration on. - - :type topic: str - :param topic: The Amazon Resource Name (ARN) of the Amazon Simple - Notification Service (SNS) topic. - """ - - name = autoscale_group - if isinstance(autoscale_group, AutoScalingGroup): - name = autoscale_group.name - - params = {'AutoScalingGroupName': name, - 'TopicARN': topic} - - return self.get_status('DeleteNotificationConfiguration', params) - - def set_instance_health(self, instance_id, health_status, - should_respect_grace_period=True): - """ - Explicitly set the health status of an instance. - - :type instance_id: str - :param instance_id: The identifier of the EC2 instance. - - :type health_status: str - :param health_status: The health status of the instance. - "Healthy" means that the instance is healthy and should remain - in service. "Unhealthy" means that the instance is unhealthy. - Auto Scaling should terminate and replace it. - - :type should_respect_grace_period: bool - :param should_respect_grace_period: If True, this call should - respect the grace period associated with the group. - """ - params = {'InstanceId': instance_id, - 'HealthStatus': health_status} - if should_respect_grace_period: - params['ShouldRespectGracePeriod'] = 'true' - else: - params['ShouldRespectGracePeriod'] = 'false' - return self.get_status('SetInstanceHealth', params) - - def set_desired_capacity(self, group_name, desired_capacity, honor_cooldown=False): - """ - Adjusts the desired size of the AutoScalingGroup by initiating scaling - activities. When reducing the size of the group, it is not possible to define - which Amazon EC2 instances will be terminated. This applies to any Auto Scaling - decisions that might result in terminating instances. - - :type group_name: string - :param group_name: name of the auto scaling group - - :type desired_capacity: integer - :param desired_capacity: new capacity setting for auto scaling group - - :type honor_cooldown: boolean - :param honor_cooldown: by default, overrides any cooldown period - """ - params = {'AutoScalingGroupName': group_name, - 'DesiredCapacity': desired_capacity} - if honor_cooldown: - params['HonorCooldown'] = 'true' - - return self.get_status('SetDesiredCapacity', params) - - # Tag methods - - def get_all_tags(self, filters=None, max_records=None, next_token=None): - """ - Lists the Auto Scaling group tags. - - This action supports pagination by returning a token if there - are more pages to retrieve. To get the next page, call this - action again with the returned token as the NextToken - parameter. - - :type filters: dict - :param filters: The value of the filter type used to identify - the tags to be returned. NOT IMPLEMENTED YET. - - :type max_records: int - :param max_records: Maximum number of tags to return. - - :rtype: list - :returns: List of :class:`boto.ec2.autoscale.tag.Tag` - instances. - """ - params = {} - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribeTags', params, - [('member', Tag)]) - - def create_or_update_tags(self, tags): - """ - Creates new tags or updates existing tags for an Auto Scaling group. - - :type tags: List of :class:`boto.ec2.autoscale.tag.Tag` - :param tags: The new or updated tags. - """ - params = {} - for i, tag in enumerate(tags): - tag.build_params(params, i + 1) - return self.get_status('CreateOrUpdateTags', params, verb='POST') - - def delete_tags(self, tags): - """ - Deletes existing tags for an Auto Scaling group. - - :type tags: List of :class:`boto.ec2.autoscale.tag.Tag` - :param tags: The new or updated tags. - """ - params = {} - for i, tag in enumerate(tags): - tag.build_params(params, i + 1) - return self.get_status('DeleteTags', params, verb='POST') diff --git a/awx/lib/site-packages/boto/ec2/autoscale/activity.py b/awx/lib/site-packages/boto/ec2/autoscale/activity.py deleted file mode 100644 index bfe32f436d..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/activity.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (c) 2009-2011 Reza Lotun http://reza.lotun.name/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from datetime import datetime - - -class Activity(object): - def __init__(self, connection=None): - self.connection = connection - self.start_time = None - self.end_time = None - self.activity_id = None - self.progress = None - self.status_code = None - self.cause = None - self.description = None - self.status_message = None - self.group_name = None - - def __repr__(self): - return 'Activity<%s>: For group:%s, progress:%s, cause:%s' % (self.activity_id, - self.group_name, - self.status_message, - self.cause) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'ActivityId': - self.activity_id = value - elif name == 'AutoScalingGroupName': - self.group_name = value - elif name == 'StartTime': - try: - self.start_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - except ValueError: - self.start_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - elif name == 'EndTime': - try: - self.end_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - except ValueError: - self.end_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - elif name == 'Progress': - self.progress = value - elif name == 'Cause': - self.cause = value - elif name == 'Description': - self.description = value - elif name == 'StatusMessage': - self.status_message = value - elif name == 'StatusCode': - self.status_code = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/group.py b/awx/lib/site-packages/boto/ec2/autoscale/group.py deleted file mode 100644 index c3c041275d..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/group.py +++ /dev/null @@ -1,361 +0,0 @@ -# Copyright (c) 2009-2011 Reza Lotun http://reza.lotun.name/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.ec2.elb.listelement import ListElement -from boto.resultset import ResultSet -from boto.ec2.autoscale.launchconfig import LaunchConfiguration -from boto.ec2.autoscale.request import Request -from boto.ec2.autoscale.instance import Instance -from boto.ec2.autoscale.tag import Tag - - -class ProcessType(object): - def __init__(self, connection=None): - self.connection = connection - self.process_name = None - - def __repr__(self): - return 'ProcessType(%s)' % self.process_name - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'ProcessName': - self.process_name = value - - -class SuspendedProcess(object): - def __init__(self, connection=None): - self.connection = connection - self.process_name = None - self.reason = None - - def __repr__(self): - return 'SuspendedProcess(%s, %s)' % (self.process_name, self.reason) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'ProcessName': - self.process_name = value - elif name == 'SuspensionReason': - self.reason = value - - -class EnabledMetric(object): - def __init__(self, connection=None, metric=None, granularity=None): - self.connection = connection - self.metric = metric - self.granularity = granularity - - def __repr__(self): - return 'EnabledMetric(%s, %s)' % (self.metric, self.granularity) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Granularity': - self.granularity = value - elif name == 'Metric': - self.metric = value - - -class TerminationPolicies(list): - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'member': - self.append(value) - - -class AutoScalingGroup(object): - def __init__(self, connection=None, name=None, - launch_config=None, availability_zones=None, - load_balancers=None, default_cooldown=None, - health_check_type=None, health_check_period=None, - placement_group=None, vpc_zone_identifier=None, - desired_capacity=None, min_size=None, max_size=None, - tags=None, termination_policies=None, instance_id=None, - **kwargs): - """ - Creates a new AutoScalingGroup with the specified name. - - You must not have already used up your entire quota of - AutoScalingGroups in order for this call to be successful. Once the - creation request is completed, the AutoScalingGroup is ready to be - used in other calls. - - :type name: str - :param name: Name of autoscaling group (required). - - :type availability_zones: list - :param availability_zones: List of availability zones (required). - - :type default_cooldown: int - :param default_cooldown: Number of seconds after a Scaling Activity - completes before any further scaling activities can start. - - :type desired_capacity: int - :param desired_capacity: The desired capacity for the group. - - :type health_check_period: str - :param health_check_period: Length of time in seconds after a new - EC2 instance comes into service that Auto Scaling starts - checking its health. - - :type health_check_type: str - :param health_check_type: The service you want the health status from, - Amazon EC2 or Elastic Load Balancer. - - :type launch_config: str or LaunchConfiguration - :param launch_config: Name of launch configuration (required). - - :type load_balancers: list - :param load_balancers: List of load balancers. - - :type max_size: int - :param max_size: Maximum size of group (required). - - :type min_size: int - :param min_size: Minimum size of group (required). - - :type placement_group: str - :param placement_group: Physical location of your cluster placement - group created in Amazon EC2. - - :type vpc_zone_identifier: str or list - :param vpc_zone_identifier: A comma-separated string or python list of - the subnet identifiers of the Virtual Private Cloud. - - :type tags: list - :param tags: List of :class:`boto.ec2.autoscale.tag.Tag`s - - :type termination_policies: list - :param termination_policies: A list of termination policies. Valid values - are: "OldestInstance", "NewestInstance", "OldestLaunchConfiguration", - "ClosestToNextInstanceHour", "Default". If no value is specified, - the "Default" value is used. - - :type instance_id: str - :param instance_id: The ID of the Amazon EC2 instance you want to use - to create the Auto Scaling group. - - :rtype: :class:`boto.ec2.autoscale.group.AutoScalingGroup` - :return: An autoscale group. - """ - self.name = name or kwargs.get('group_name') # backwards compat - self.connection = connection - self.min_size = int(min_size) if min_size is not None else None - self.max_size = int(max_size) if max_size is not None else None - self.created_time = None - # backwards compatibility - default_cooldown = default_cooldown or kwargs.get('cooldown') - if default_cooldown is not None: - default_cooldown = int(default_cooldown) - self.default_cooldown = default_cooldown - self.launch_config_name = launch_config - if launch_config and isinstance(launch_config, LaunchConfiguration): - self.launch_config_name = launch_config.name - self.desired_capacity = desired_capacity - lbs = load_balancers or [] - self.load_balancers = ListElement(lbs) - zones = availability_zones or [] - self.availability_zones = ListElement(zones) - self.health_check_period = health_check_period - self.health_check_type = health_check_type - self.placement_group = placement_group - self.autoscaling_group_arn = None - if type(vpc_zone_identifier) is list: - vpc_zone_identifier = ','.join(vpc_zone_identifier) - self.vpc_zone_identifier = vpc_zone_identifier - self.instances = None - self.tags = tags or None - termination_policies = termination_policies or [] - self.termination_policies = ListElement(termination_policies) - self.instance_id = instance_id - - # backwards compatible access to 'cooldown' param - def _get_cooldown(self): - return self.default_cooldown - - def _set_cooldown(self, val): - self.default_cooldown = val - - cooldown = property(_get_cooldown, _set_cooldown) - - def __repr__(self): - return 'AutoScaleGroup<%s>' % self.name - - def startElement(self, name, attrs, connection): - if name == 'Instances': - self.instances = ResultSet([('member', Instance)]) - return self.instances - elif name == 'LoadBalancerNames': - return self.load_balancers - elif name == 'AvailabilityZones': - return self.availability_zones - elif name == 'EnabledMetrics': - self.enabled_metrics = ResultSet([('member', EnabledMetric)]) - return self.enabled_metrics - elif name == 'SuspendedProcesses': - self.suspended_processes = ResultSet([('member', SuspendedProcess)]) - return self.suspended_processes - elif name == 'Tags': - self.tags = ResultSet([('member', Tag)]) - return self.tags - elif name == 'TerminationPolicies': - return self.termination_policies - else: - return - - def endElement(self, name, value, connection): - if name == 'MinSize': - self.min_size = int(value) - elif name == 'AutoScalingGroupARN': - self.autoscaling_group_arn = value - elif name == 'CreatedTime': - self.created_time = value - elif name == 'DefaultCooldown': - self.default_cooldown = int(value) - elif name == 'LaunchConfigurationName': - self.launch_config_name = value - elif name == 'DesiredCapacity': - self.desired_capacity = int(value) - elif name == 'MaxSize': - self.max_size = int(value) - elif name == 'AutoScalingGroupName': - self.name = value - elif name == 'PlacementGroup': - self.placement_group = value - elif name == 'HealthCheckGracePeriod': - try: - self.health_check_period = int(value) - except ValueError: - self.health_check_period = None - elif name == 'HealthCheckType': - self.health_check_type = value - elif name == 'VPCZoneIdentifier': - self.vpc_zone_identifier = value - elif name == 'InstanceId': - self.instance_id = value - else: - setattr(self, name, value) - - def set_capacity(self, capacity): - """ - Set the desired capacity for the group. - """ - params = {'AutoScalingGroupName': self.name, - 'DesiredCapacity': capacity} - req = self.connection.get_object('SetDesiredCapacity', params, - Request) - self.connection.last_request = req - return req - - def update(self): - """ - Sync local changes with AutoScaling group. - """ - return self.connection._update_group('UpdateAutoScalingGroup', self) - - def shutdown_instances(self): - """ - Convenience method which shuts down all instances associated with - this group. - """ - self.min_size = 0 - self.max_size = 0 - self.desired_capacity = 0 - self.update() - - def delete(self, force_delete=False): - """ - Delete this auto-scaling group if no instances attached or no - scaling activities in progress. - """ - return self.connection.delete_auto_scaling_group(self.name, - force_delete) - - def get_activities(self, activity_ids=None, max_records=50): - """ - Get all activies for this group. - """ - return self.connection.get_all_activities(self, activity_ids, - max_records) - - def put_notification_configuration(self, topic, notification_types): - """ - Configures an Auto Scaling group to send notifications when - specified events take place. Valid notification types are: - 'autoscaling:EC2_INSTANCE_LAUNCH', - 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR', - 'autoscaling:EC2_INSTANCE_TERMINATE', - 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR', - 'autoscaling:TEST_NOTIFICATION' - """ - return self.connection.put_notification_configuration(self, - topic, - notification_types) - - def delete_notification_configuration(self, topic): - """ - Deletes notifications created by put_notification_configuration. - """ - return self.connection.delete_notification_configuration(self, topic) - - def suspend_processes(self, scaling_processes=None): - """ - Suspends Auto Scaling processes for an Auto Scaling group. - """ - return self.connection.suspend_processes(self.name, scaling_processes) - - def resume_processes(self, scaling_processes=None): - """ - Resumes Auto Scaling processes for an Auto Scaling group. - """ - return self.connection.resume_processes(self.name, scaling_processes) - - -class AutoScalingGroupMetric(object): - def __init__(self, connection=None): - - self.connection = connection - self.metric = None - self.granularity = None - - def __repr__(self): - return 'AutoScalingGroupMetric:%s' % self.metric - - def startElement(self, name, attrs, connection): - return - - def endElement(self, name, value, connection): - if name == 'Metric': - self.metric = value - elif name == 'Granularity': - self.granularity = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/instance.py b/awx/lib/site-packages/boto/ec2/autoscale/instance.py deleted file mode 100644 index 6095c17be5..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/instance.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2009 Reza Lotun http://reza.lotun.name/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class Instance(object): - def __init__(self, connection=None): - self.connection = connection - self.instance_id = None - self.health_status = None - self.launch_config_name = None - self.lifecycle_state = None - self.availability_zone = None - self.group_name = None - - def __repr__(self): - r = 'Instance<id:%s, state:%s, health:%s' % (self.instance_id, - self.lifecycle_state, - self.health_status) - if self.group_name: - r += ' group:%s' % self.group_name - r += '>' - return r - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'InstanceId': - self.instance_id = value - elif name == 'HealthStatus': - self.health_status = value - elif name == 'LaunchConfigurationName': - self.launch_config_name = value - elif name == 'LifecycleState': - self.lifecycle_state = value - elif name == 'AvailabilityZone': - self.availability_zone = value - elif name == 'AutoScalingGroupName': - self.group_name = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/launchconfig.py b/awx/lib/site-packages/boto/ec2/autoscale/launchconfig.py deleted file mode 100644 index 889cee21bf..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/launchconfig.py +++ /dev/null @@ -1,252 +0,0 @@ -# Copyright (c) 2009 Reza Lotun http://reza.lotun.name/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.ec2.elb.listelement import ListElement -# Namespacing issue with deprecated local class -from boto.ec2.blockdevicemapping import BlockDeviceMapping as BDM -from boto.resultset import ResultSet -import boto.utils -import base64 - - -# this should use the corresponding object from boto.ec2 -# Currently in use by deprecated local BlockDeviceMapping class -class Ebs(object): - def __init__(self, connection=None, snapshot_id=None, volume_size=None): - self.connection = connection - self.snapshot_id = snapshot_id - self.volume_size = volume_size - - def __repr__(self): - return 'Ebs(%s, %s)' % (self.snapshot_id, self.volume_size) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'SnapshotId': - self.snapshot_id = value - elif name == 'VolumeSize': - self.volume_size = value - - -class InstanceMonitoring(object): - def __init__(self, connection=None, enabled='false'): - self.connection = connection - self.enabled = enabled - - def __repr__(self): - return 'InstanceMonitoring(%s)' % self.enabled - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Enabled': - self.enabled = value - - -# this should use the BlockDeviceMapping from boto.ec2.blockdevicemapping -# Currently in use by deprecated code for backwards compatability -# Removing this class can also remove the Ebs class in this same file -class BlockDeviceMapping(object): - def __init__(self, connection=None, device_name=None, virtual_name=None, - ebs=None, no_device=None): - self.connection = connection - self.device_name = device_name - self.virtual_name = virtual_name - self.ebs = ebs - self.no_device = no_device - - def __repr__(self): - return 'BlockDeviceMapping(%s, %s)' % (self.device_name, - self.virtual_name) - - def startElement(self, name, attrs, connection): - if name == 'Ebs': - self.ebs = Ebs(self) - return self.ebs - - def endElement(self, name, value, connection): - if name == 'DeviceName': - self.device_name = value - elif name == 'VirtualName': - self.virtual_name = value - elif name == 'NoDevice': - self.no_device = bool(value) - - -class LaunchConfiguration(object): - def __init__(self, connection=None, name=None, image_id=None, - key_name=None, security_groups=None, user_data=None, - instance_type='m1.small', kernel_id=None, - ramdisk_id=None, block_device_mappings=None, - instance_monitoring=False, spot_price=None, - instance_profile_name=None, ebs_optimized=False, - associate_public_ip_address=None, volume_type=None, - delete_on_termination=True, iops=None, use_block_device_types=False): - """ - A launch configuration. - - :type name: str - :param name: Name of the launch configuration to create. - - :type image_id: str - :param image_id: Unique ID of the Amazon Machine Image (AMI) which was - assigned during registration. - - :type key_name: str - :param key_name: The name of the EC2 key pair. - - :type security_groups: list - :param security_groups: Names or security group id's of the security - groups with which to associate the EC2 instances or VPC instances, - respectively. - - :type user_data: str - :param user_data: The user data available to launched EC2 instances. - - :type instance_type: str - :param instance_type: The instance type - - :type kernel_id: str - :param kernel_id: Kernel id for instance - - :type ramdisk_id: str - :param ramdisk_id: RAM disk id for instance - - :type block_device_mappings: list - :param block_device_mappings: Specifies how block devices are exposed - for instances - - :type instance_monitoring: bool - :param instance_monitoring: Whether instances in group are launched - with detailed monitoring. - - :type spot_price: float - :param spot_price: The spot price you are bidding. Only applies - if you are building an autoscaling group with spot instances. - - :type instance_profile_name: string - :param instance_profile_name: The name or the Amazon Resource - Name (ARN) of the instance profile associated with the IAM - role for the instance. - - :type ebs_optimized: bool - :param ebs_optimized: Specifies whether the instance is optimized - for EBS I/O (true) or not (false). - - - :type associate_public_ip_address: bool - :param associate_public_ip_address: Used for Auto Scaling groups that launch instances into an Amazon Virtual Private Cloud. - Specifies whether to assign a public IP address to each instance launched in a Amazon VPC. - """ - self.connection = connection - self.name = name - self.instance_type = instance_type - self.block_device_mappings = block_device_mappings - self.key_name = key_name - sec_groups = security_groups or [] - self.security_groups = ListElement(sec_groups) - self.image_id = image_id - self.ramdisk_id = ramdisk_id - self.created_time = None - self.kernel_id = kernel_id - self.user_data = user_data - self.created_time = None - self.instance_monitoring = instance_monitoring - self.spot_price = spot_price - self.instance_profile_name = instance_profile_name - self.launch_configuration_arn = None - self.ebs_optimized = ebs_optimized - self.associate_public_ip_address = associate_public_ip_address - self.volume_type = volume_type - self.delete_on_termination = delete_on_termination - self.iops = iops - self.use_block_device_types = use_block_device_types - - if connection is not None: - self.use_block_device_types = connection.use_block_device_types - - def __repr__(self): - return 'LaunchConfiguration:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'SecurityGroups': - return self.security_groups - elif name == 'BlockDeviceMappings': - if self.use_block_device_types: - self.block_device_mappings = BDM() - else: - self.block_device_mappings = ResultSet([('member', BlockDeviceMapping)]) - return self.block_device_mappings - elif name == 'InstanceMonitoring': - self.instance_monitoring = InstanceMonitoring(self) - return self.instance_monitoring - - def endElement(self, name, value, connection): - if name == 'InstanceType': - self.instance_type = value - elif name == 'LaunchConfigurationName': - self.name = value - elif name == 'KeyName': - self.key_name = value - elif name == 'ImageId': - self.image_id = value - elif name == 'CreatedTime': - self.created_time = boto.utils.parse_ts(value) - elif name == 'KernelId': - self.kernel_id = value - elif name == 'RamdiskId': - self.ramdisk_id = value - elif name == 'UserData': - try: - self.user_data = base64.b64decode(value) - except TypeError: - self.user_data = value - elif name == 'LaunchConfigurationARN': - self.launch_configuration_arn = value - elif name == 'InstanceMonitoring': - self.instance_monitoring = value - elif name == 'SpotPrice': - self.spot_price = float(value) - elif name == 'IamInstanceProfile': - self.instance_profile_name = value - elif name == 'EbsOptimized': - self.ebs_optimized = True if value.lower() == 'true' else False - elif name == 'AssociatePublicIpAddress': - self.associate_public_ip_address = True if value.lower() == 'true' else False - elif name == 'VolumeType': - self.volume_type = value - elif name == 'DeleteOnTermination': - if value.lower() == 'true': - self.delete_on_termination = True - else: - self.delete_on_termination = False - elif name == 'Iops': - self.iops = int(value) - else: - setattr(self, name, value) - - def delete(self): - """ Delete this launch configuration. """ - return self.connection.delete_launch_configuration(self.name) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/limits.py b/awx/lib/site-packages/boto/ec2/autoscale/limits.py deleted file mode 100644 index 89ece672e9..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/limits.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class AccountLimits(object): - def __init__(self, connection=None): - self.connection = connection - self.max_autoscaling_groups = None - self.max_launch_configurations = None - - def __repr__(self): - return 'AccountLimits: [%s, %s]' % (self.max_autoscaling_groups, - self.max_launch_configurations) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'RequestId': - self.request_id = value - elif name == 'MaxNumberOfAutoScalingGroups': - self.max_autoscaling_groups = int(value) - elif name == 'MaxNumberOfLaunchConfigurations': - self.max_launch_configurations = int(value) - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/policy.py b/awx/lib/site-packages/boto/ec2/autoscale/policy.py deleted file mode 100644 index 191ac496fd..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/policy.py +++ /dev/null @@ -1,181 +0,0 @@ -# Copyright (c) 2009-2010 Reza Lotun http://reza.lotun.name/ -# Copyright (c) 2011 Jann Kleen -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.resultset import ResultSet -from boto.ec2.elb.listelement import ListElement - - -class Alarm(object): - def __init__(self, connection=None): - self.connection = connection - self.name = None - self.alarm_arn = None - - def __repr__(self): - return 'Alarm:%s' % self.name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'AlarmName': - self.name = value - elif name == 'AlarmARN': - self.alarm_arn = value - else: - setattr(self, name, value) - - -class AdjustmentType(object): - def __init__(self, connection=None): - self.connection = connection - self.adjustment_type = None - - def __repr__(self): - return 'AdjustmentType:%s' % self.adjustment_type - - def startElement(self, name, attrs, connection): - return - - def endElement(self, name, value, connection): - if name == 'AdjustmentType': - self.adjustment_type = value - return - - -class MetricCollectionTypes(object): - class BaseType(object): - arg = '' - - def __init__(self, connection): - self.connection = connection - self.val = None - - def __repr__(self): - return '%s:%s' % (self.arg, self.val) - - def startElement(self, name, attrs, connection): - return - - def endElement(self, name, value, connection): - if name == self.arg: - self.val = value - - class Metric(BaseType): - arg = 'Metric' - - class Granularity(BaseType): - arg = 'Granularity' - - def __init__(self, connection=None): - self.connection = connection - self.metrics = [] - self.granularities = [] - - def __repr__(self): - return 'MetricCollectionTypes:<%s, %s>' % (self.metrics, self.granularities) - - def startElement(self, name, attrs, connection): - if name == 'Granularities': - self.granularities = ResultSet([('member', self.Granularity)]) - return self.granularities - elif name == 'Metrics': - self.metrics = ResultSet([('member', self.Metric)]) - return self.metrics - - def endElement(self, name, value, connection): - return - - -class ScalingPolicy(object): - def __init__(self, connection=None, **kwargs): - """ - Scaling Policy - - :type name: str - :param name: Name of scaling policy. - - :type adjustment_type: str - :param adjustment_type: Specifies the type of adjustment. Valid values are `ChangeInCapacity`, `ExactCapacity` and `PercentChangeInCapacity`. - - :type as_name: str or int - :param as_name: Name or ARN of the Auto Scaling Group. - - :type scaling_adjustment: int - :param scaling_adjustment: Value of adjustment (type specified in `adjustment_type`). - - :type min_adjustment_step: int - :param min_adjustment_step: Value of min adjustment step required to - apply the scaling policy (only make sense when use `PercentChangeInCapacity` as adjustment_type.). - - :type cooldown: int - :param cooldown: Time (in seconds) before Alarm related Scaling Activities can start after the previous Scaling Activity ends. - - """ - self.name = kwargs.get('name', None) - self.adjustment_type = kwargs.get('adjustment_type', None) - self.as_name = kwargs.get('as_name', None) - self.scaling_adjustment = kwargs.get('scaling_adjustment', None) - self.cooldown = kwargs.get('cooldown', None) - self.connection = connection - self.min_adjustment_step = kwargs.get('min_adjustment_step', None) - - def __repr__(self): - return 'ScalingPolicy(%s group:%s adjustment:%s)' % (self.name, - self.as_name, - self.adjustment_type) - - def startElement(self, name, attrs, connection): - if name == 'Alarms': - self.alarms = ResultSet([('member', Alarm)]) - return self.alarms - - def endElement(self, name, value, connection): - if name == 'PolicyName': - self.name = value - elif name == 'AutoScalingGroupName': - self.as_name = value - elif name == 'PolicyARN': - self.policy_arn = value - elif name == 'ScalingAdjustment': - self.scaling_adjustment = int(value) - elif name == 'Cooldown': - self.cooldown = int(value) - elif name == 'AdjustmentType': - self.adjustment_type = value - elif name == 'MinAdjustmentStep': - self.min_adjustment_step = int(value) - - def delete(self): - return self.connection.delete_policy(self.name, self.as_name) - - -class TerminationPolicies(list): - def __init__(self, connection=None, **kwargs): - pass - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'member': - self.append(value) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/request.py b/awx/lib/site-packages/boto/ec2/autoscale/request.py deleted file mode 100644 index b17b534fed..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/request.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2009 Reza Lotun http://reza.lotun.name/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class Request(object): - def __init__(self, connection=None): - self.connection = connection - self.request_id = '' - - def __repr__(self): - return 'Request:%s' % self.request_id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'RequestId': - self.request_id = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/scheduled.py b/awx/lib/site-packages/boto/ec2/autoscale/scheduled.py deleted file mode 100644 index 8d2eda407d..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/scheduled.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2009-2010 Reza Lotun http://reza.lotun.name/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -from datetime import datetime - - -class ScheduledUpdateGroupAction(object): - def __init__(self, connection=None): - self.connection = connection - self.name = None - self.action_arn = None - self.as_group = None - self.time = None - self.start_time = None - self.end_time = None - self.recurrence = None - self.desired_capacity = None - self.max_size = None - self.min_size = None - - def __repr__(self): - return 'ScheduledUpdateGroupAction:%s' % self.name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'DesiredCapacity': - self.desired_capacity = value - elif name == 'ScheduledActionName': - self.name = value - elif name == 'AutoScalingGroupName': - self.as_group = value - elif name == 'MaxSize': - self.max_size = int(value) - elif name == 'MinSize': - self.min_size = int(value) - elif name == 'ScheduledActionARN': - self.action_arn = value - elif name == 'Recurrence': - self.recurrence = value - elif name == 'Time': - try: - self.time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - except ValueError: - self.time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - elif name == 'StartTime': - try: - self.start_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - except ValueError: - self.start_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - elif name == 'EndTime': - try: - self.end_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') - except ValueError: - self.end_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/autoscale/tag.py b/awx/lib/site-packages/boto/ec2/autoscale/tag.py deleted file mode 100644 index a783edf096..0000000000 --- a/awx/lib/site-packages/boto/ec2/autoscale/tag.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class Tag(object): - """ - A name/value tag on an AutoScalingGroup resource. - - :ivar key: The key of the tag. - :ivar value: The value of the tag. - :ivar propagate_at_launch: Boolean value which specifies whether the - new tag will be applied to instances launched after the tag is created. - :ivar resource_id: The name of the autoscaling group. - :ivar resource_type: The only supported resource type at this time - is "auto-scaling-group". - """ - - def __init__(self, connection=None, key=None, value=None, - propagate_at_launch=False, resource_id=None, - resource_type='auto-scaling-group'): - self.connection = connection - self.key = key - self.value = value - self.propagate_at_launch = propagate_at_launch - self.resource_id = resource_id - self.resource_type = resource_type - - def __repr__(self): - return 'Tag(%s=%s)' % (self.key, self.value) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Key': - self.key = value - elif name == 'Value': - self.value = value - elif name == 'PropagateAtLaunch': - if value.lower() == 'true': - self.propagate_at_launch = True - else: - self.propagate_at_launch = False - elif name == 'ResourceId': - self.resource_id = value - elif name == 'ResourceType': - self.resource_type = value - - def build_params(self, params, i): - """ - Populates a dictionary with the name/value pairs necessary - to identify this Tag in a request. - """ - prefix = 'Tags.member.%d.' % i - params[prefix + 'ResourceId'] = self.resource_id - params[prefix + 'ResourceType'] = self.resource_type - params[prefix + 'Key'] = self.key - params[prefix + 'Value'] = self.value - if self.propagate_at_launch: - params[prefix + 'PropagateAtLaunch'] = 'true' - else: - params[prefix + 'PropagateAtLaunch'] = 'false' - - def delete(self): - return self.connection.delete_tags([self]) diff --git a/awx/lib/site-packages/boto/ec2/blockdevicemapping.py b/awx/lib/site-packages/boto/ec2/blockdevicemapping.py deleted file mode 100644 index 2f4e1faf4b..0000000000 --- a/awx/lib/site-packages/boto/ec2/blockdevicemapping.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright (c) 2009-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - -class BlockDeviceType(object): - """ - Represents parameters for a block device. - """ - - def __init__(self, - connection=None, - ephemeral_name=None, - no_device=False, - volume_id=None, - snapshot_id=None, - status=None, - attach_time=None, - delete_on_termination=False, - size=None, - volume_type=None, - iops=None, - encrypted=None): - self.connection = connection - self.ephemeral_name = ephemeral_name - self.no_device = no_device - self.volume_id = volume_id - self.snapshot_id = snapshot_id - self.status = status - self.attach_time = attach_time - self.delete_on_termination = delete_on_termination - self.size = size - self.volume_type = volume_type - self.iops = iops - self.encrypted = encrypted - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - lname = name.lower() - if name == 'volumeId': - self.volume_id = value - elif lname == 'virtualname': - self.ephemeral_name = value - elif lname == 'nodevice': - self.no_device = (value == 'true') - elif lname == 'snapshotid': - self.snapshot_id = value - elif lname == 'volumesize': - self.size = int(value) - elif lname == 'status': - self.status = value - elif lname == 'attachtime': - self.attach_time = value - elif lname == 'deleteontermination': - self.delete_on_termination = (value == 'true') - elif lname == 'volumetype': - self.volume_type = value - elif lname == 'iops': - self.iops = int(value) - elif lname == 'encrypted': - self.encrypted = (value == 'true') - else: - setattr(self, name, value) - -# for backwards compatibility -EBSBlockDeviceType = BlockDeviceType - - -class BlockDeviceMapping(dict): - """ - Represents a collection of BlockDeviceTypes when creating ec2 instances. - - Example: - dev_sda1 = BlockDeviceType() - dev_sda1.size = 100 # change root volume to 100GB instead of default - bdm = BlockDeviceMapping() - bdm['/dev/sda1'] = dev_sda1 - reservation = image.run(..., block_device_map=bdm, ...) - """ - - def __init__(self, connection=None): - """ - :type connection: :class:`boto.ec2.EC2Connection` - :param connection: Optional connection. - """ - dict.__init__(self) - self.connection = connection - self.current_name = None - self.current_value = None - - def startElement(self, name, attrs, connection): - lname = name.lower() - if lname in ['ebs', 'virtualname']: - self.current_value = BlockDeviceType(self) - return self.current_value - - def endElement(self, name, value, connection): - lname = name.lower() - if lname in ['device', 'devicename']: - self.current_name = value - elif lname in ['item', 'member']: - self[self.current_name] = self.current_value - - def ec2_build_list_params(self, params, prefix=''): - pre = '%sBlockDeviceMapping' % prefix - return self._build_list_params(params, prefix=pre) - - def autoscale_build_list_params(self, params, prefix=''): - pre = '%sBlockDeviceMappings.member' % prefix - return self._build_list_params(params, prefix=pre) - - def _build_list_params(self, params, prefix=''): - i = 1 - for dev_name in self: - pre = '%s.%d' % (prefix, i) - params['%s.DeviceName' % pre] = dev_name - block_dev = self[dev_name] - if block_dev.ephemeral_name: - params['%s.VirtualName' % pre] = block_dev.ephemeral_name - else: - if block_dev.no_device: - params['%s.NoDevice' % pre] = '' - else: - if block_dev.snapshot_id: - params['%s.Ebs.SnapshotId' % pre] = block_dev.snapshot_id - if block_dev.size: - params['%s.Ebs.VolumeSize' % pre] = block_dev.size - if block_dev.delete_on_termination: - params['%s.Ebs.DeleteOnTermination' % pre] = 'true' - else: - params['%s.Ebs.DeleteOnTermination' % pre] = 'false' - if block_dev.volume_type: - params['%s.Ebs.VolumeType' % pre] = block_dev.volume_type - if block_dev.iops is not None: - params['%s.Ebs.Iops' % pre] = block_dev.iops - # The encrypted flag (even if False) cannot be specified for the root EBS - # volume. - if block_dev.encrypted is not None: - if block_dev.encrypted: - params['%s.Ebs.Encrypted' % pre] = 'true' - else: - params['%s.Ebs.Encrypted' % pre] = 'false' - - i += 1 diff --git a/awx/lib/site-packages/boto/ec2/bundleinstance.py b/awx/lib/site-packages/boto/ec2/bundleinstance.py deleted file mode 100644 index e241da9adf..0000000000 --- a/awx/lib/site-packages/boto/ec2/bundleinstance.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Bundle Task -""" - -from boto.ec2.ec2object import EC2Object - - -class BundleInstanceTask(EC2Object): - - def __init__(self, connection=None): - super(BundleInstanceTask, self).__init__(connection) - self.id = None - self.instance_id = None - self.progress = None - self.start_time = None - self.state = None - self.bucket = None - self.prefix = None - self.upload_policy = None - self.upload_policy_signature = None - self.update_time = None - self.code = None - self.message = None - - def __repr__(self): - return 'BundleInstanceTask:%s' % self.id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'bundleId': - self.id = value - elif name == 'instanceId': - self.instance_id = value - elif name == 'progress': - self.progress = value - elif name == 'startTime': - self.start_time = value - elif name == 'state': - self.state = value - elif name == 'bucket': - self.bucket = value - elif name == 'prefix': - self.prefix = value - elif name == 'uploadPolicy': - self.upload_policy = value - elif name == 'uploadPolicySignature': - self.upload_policy_signature = value - elif name == 'updateTime': - self.update_time = value - elif name == 'code': - self.code = value - elif name == 'message': - self.message = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/buyreservation.py b/awx/lib/site-packages/boto/ec2/buyreservation.py deleted file mode 100644 index 786d0fed28..0000000000 --- a/awx/lib/site-packages/boto/ec2/buyreservation.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import boto.ec2 -from boto.sdb.db.property import StringProperty, IntegerProperty -from boto.manage import propget -from boto.compat import six - -InstanceTypes = ['m1.small', 'm1.large', 'm1.xlarge', - 'c1.medium', 'c1.xlarge', 'm2.xlarge', - 'm2.2xlarge', 'm2.4xlarge', 'cc1.4xlarge', - 't1.micro'] - - -class BuyReservation(object): - - def get_region(self, params): - if not params.get('region', None): - prop = StringProperty(name='region', verbose_name='EC2 Region', - choices=boto.ec2.regions) - params['region'] = propget.get(prop, choices=boto.ec2.regions) - - def get_instance_type(self, params): - if not params.get('instance_type', None): - prop = StringProperty(name='instance_type', verbose_name='Instance Type', - choices=InstanceTypes) - params['instance_type'] = propget.get(prop) - - def get_quantity(self, params): - if not params.get('quantity', None): - prop = IntegerProperty(name='quantity', verbose_name='Number of Instances') - params['quantity'] = propget.get(prop) - - def get_zone(self, params): - if not params.get('zone', None): - prop = StringProperty(name='zone', verbose_name='EC2 Availability Zone', - choices=self.ec2.get_all_zones) - params['zone'] = propget.get(prop) - - def get(self, params): - self.get_region(params) - self.ec2 = params['region'].connect() - self.get_instance_type(params) - self.get_zone(params) - self.get_quantity(params) - -if __name__ == "__main__": - obj = BuyReservation() - params = {} - obj.get(params) - offerings = obj.ec2.get_all_reserved_instances_offerings(instance_type=params['instance_type'], - availability_zone=params['zone'].name) - print('\nThe following Reserved Instances Offerings are available:\n') - for offering in offerings: - offering.describe() - prop = StringProperty(name='offering', verbose_name='Offering', - choices=offerings) - offering = propget.get(prop) - print('\nYou have chosen this offering:') - offering.describe() - unit_price = float(offering.fixed_price) - total_price = unit_price * params['quantity'] - print('!!! You are about to purchase %d of these offerings for a total of $%.2f !!!' % (params['quantity'], total_price)) - answer = six.moves.input('Are you sure you want to do this? If so, enter YES: ') - if answer.strip().lower() == 'yes': - offering.purchase(params['quantity']) - else: - print('Purchase cancelled') diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/__init__.py b/awx/lib/site-packages/boto/ec2/cloudwatch/__init__.py deleted file mode 100644 index 9b150b4e8f..0000000000 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/__init__.py +++ /dev/null @@ -1,593 +0,0 @@ -# Copyright (c) 2006-2011 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -""" -This module provides an interface to the Elastic Compute Cloud (EC2) -CloudWatch service from AWS. -""" -from boto.compat import json, map, six, zip -from boto.connection import AWSQueryConnection -from boto.ec2.cloudwatch.metric import Metric -from boto.ec2.cloudwatch.alarm import MetricAlarm, MetricAlarms, AlarmHistoryItem -from boto.ec2.cloudwatch.datapoint import Datapoint -from boto.regioninfo import RegionInfo, get_regions, load_regions -import boto - -RegionData = load_regions().get('cloudwatch', {}) - - -def regions(): - """ - Get all available regions for the CloudWatch service. - - :rtype: list - :return: A list of :class:`boto.RegionInfo` instances - """ - return get_regions('cloudwatch', connection_cls=CloudWatchConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.ec2.cloudwatch.CloudWatchConnection`. - - :param str region_name: The name of the region to connect to. - - :rtype: :class:`boto.ec2.CloudWatchConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None - - -class CloudWatchConnection(AWSQueryConnection): - - APIVersion = boto.config.get('Boto', 'cloudwatch_version', '2010-08-01') - DefaultRegionName = boto.config.get('Boto', 'cloudwatch_region_name', - 'us-east-1') - DefaultRegionEndpoint = boto.config.get('Boto', - 'cloudwatch_region_endpoint', - 'monitoring.us-east-1.amazonaws.com') - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, profile_name=None): - """ - Init method to create a new connection to EC2 Monitoring Service. - - B{Note:} The host argument is overridden by the host specified in the - boto configuration file. - """ - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - - # Ugly hack to get around both a bug in Python and a - # misconfigured SSL cert for the eu-west-1 endpoint - if self.region.name == 'eu-west-1': - validate_certs = False - - super(CloudWatchConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def build_dimension_param(self, dimension, params): - prefix = 'Dimensions.member' - i = 0 - for dim_name in dimension: - dim_value = dimension[dim_name] - if dim_value: - if isinstance(dim_value, six.string_types): - dim_value = [dim_value] - for value in dim_value: - params['%s.%d.Name' % (prefix, i + 1)] = dim_name - params['%s.%d.Value' % (prefix, i + 1)] = value - i += 1 - else: - params['%s.%d.Name' % (prefix, i + 1)] = dim_name - i += 1 - - def build_list_params(self, params, items, label): - if isinstance(items, six.string_types): - items = [items] - for index, item in enumerate(items): - i = index + 1 - if isinstance(item, dict): - for k, v in six.iteritems(item): - params[label % (i, 'Name')] = k - if v is not None: - params[label % (i, 'Value')] = v - else: - params[label % i] = item - - def build_put_params(self, params, name, value=None, timestamp=None, - unit=None, dimensions=None, statistics=None): - args = (name, value, unit, dimensions, statistics, timestamp) - length = max(map(lambda a: len(a) if isinstance(a, list) else 1, args)) - - def aslist(a): - if isinstance(a, list): - if len(a) != length: - raise Exception('Must specify equal number of elements; expected %d.' % length) - return a - return [a] * length - - for index, (n, v, u, d, s, t) in enumerate(zip(*map(aslist, args))): - metric_data = {'MetricName': n} - - if timestamp: - metric_data['Timestamp'] = t.isoformat() - - if unit: - metric_data['Unit'] = u - - if dimensions: - self.build_dimension_param(d, metric_data) - - if statistics: - metric_data['StatisticValues.Maximum'] = s['maximum'] - metric_data['StatisticValues.Minimum'] = s['minimum'] - metric_data['StatisticValues.SampleCount'] = s['samplecount'] - metric_data['StatisticValues.Sum'] = s['sum'] - if value is not None: - msg = 'You supplied a value and statistics for a ' + \ - 'metric.Posting statistics and not value.' - boto.log.warn(msg) - elif value is not None: - metric_data['Value'] = v - else: - raise Exception('Must specify a value or statistics to put.') - - for key, val in six.iteritems(metric_data): - params['MetricData.member.%d.%s' % (index + 1, key)] = val - - def get_metric_statistics(self, period, start_time, end_time, metric_name, - namespace, statistics, dimensions=None, - unit=None): - """ - Get time-series data for one or more statistics of a given metric. - - :type period: integer - :param period: The granularity, in seconds, of the returned datapoints. - Period must be at least 60 seconds and must be a multiple - of 60. The default value is 60. - - :type start_time: datetime - :param start_time: The time stamp to use for determining the - first datapoint to return. The value specified is - inclusive; results include datapoints with the time stamp - specified. - - :type end_time: datetime - :param end_time: The time stamp to use for determining the - last datapoint to return. The value specified is - exclusive; results will include datapoints up to the time - stamp specified. - - :type metric_name: string - :param metric_name: The metric name. - - :type namespace: string - :param namespace: The metric's namespace. - - :type statistics: list - :param statistics: A list of statistics names Valid values: - Average | Sum | SampleCount | Maximum | Minimum - - :type dimensions: dict - :param dimensions: A dictionary of dimension key/values where - the key is the dimension name and the value - is either a scalar value or an iterator - of values to be associated with that - dimension. - - :type unit: string - :param unit: The unit for the metric. Value values are: - Seconds | Microseconds | Milliseconds | Bytes | Kilobytes | - Megabytes | Gigabytes | Terabytes | Bits | Kilobits | - Megabits | Gigabits | Terabits | Percent | Count | - Bytes/Second | Kilobytes/Second | Megabytes/Second | - Gigabytes/Second | Terabytes/Second | Bits/Second | - Kilobits/Second | Megabits/Second | Gigabits/Second | - Terabits/Second | Count/Second | None - - :rtype: list - """ - params = {'Period': period, - 'MetricName': metric_name, - 'Namespace': namespace, - 'StartTime': start_time.isoformat(), - 'EndTime': end_time.isoformat()} - self.build_list_params(params, statistics, 'Statistics.member.%d') - if dimensions: - self.build_dimension_param(dimensions, params) - if unit: - params['Unit'] = unit - return self.get_list('GetMetricStatistics', params, - [('member', Datapoint)]) - - def list_metrics(self, next_token=None, dimensions=None, - metric_name=None, namespace=None): - """ - Returns a list of the valid metrics for which there is recorded - data available. - - :type next_token: str - :param next_token: A maximum of 500 metrics will be returned - at one time. If more results are available, the ResultSet - returned will contain a non-Null next_token attribute. - Passing that token as a parameter to list_metrics will - retrieve the next page of metrics. - - :type dimensions: dict - :param dimensions: A dictionary containing name/value - pairs that will be used to filter the results. The key in - the dictionary is the name of a Dimension. The value in - the dictionary is either a scalar value of that Dimension - name that you want to filter on or None if you want all - metrics with that Dimension name. To be included in the - result a metric must contain all specified dimensions, - although the metric may contain additional dimensions beyond - the requested metrics. The Dimension names, and values must - be strings between 1 and 250 characters long. A maximum of - 10 dimensions are allowed. - - :type metric_name: str - :param metric_name: The name of the Metric to filter against. If None, - all Metric names will be returned. - - :type namespace: str - :param namespace: A Metric namespace to filter against (e.g. AWS/EC2). - If None, Metrics from all namespaces will be returned. - """ - params = {} - if next_token: - params['NextToken'] = next_token - if dimensions: - self.build_dimension_param(dimensions, params) - if metric_name: - params['MetricName'] = metric_name - if namespace: - params['Namespace'] = namespace - - return self.get_list('ListMetrics', params, [('member', Metric)]) - - def put_metric_data(self, namespace, name, value=None, timestamp=None, - unit=None, dimensions=None, statistics=None): - """ - Publishes metric data points to Amazon CloudWatch. Amazon Cloudwatch - associates the data points with the specified metric. If the specified - metric does not exist, Amazon CloudWatch creates the metric. If a list - is specified for some, but not all, of the arguments, the remaining - arguments are repeated a corresponding number of times. - - :type namespace: str - :param namespace: The namespace of the metric. - - :type name: str or list - :param name: The name of the metric. - - :type value: float or list - :param value: The value for the metric. - - :type timestamp: datetime or list - :param timestamp: The time stamp used for the metric. If not specified, - the default value is set to the time the metric data was received. - - :type unit: string or list - :param unit: The unit of the metric. Valid Values: Seconds | - Microseconds | Milliseconds | Bytes | Kilobytes | - Megabytes | Gigabytes | Terabytes | Bits | Kilobits | - Megabits | Gigabits | Terabits | Percent | Count | - Bytes/Second | Kilobytes/Second | Megabytes/Second | - Gigabytes/Second | Terabytes/Second | Bits/Second | - Kilobits/Second | Megabits/Second | Gigabits/Second | - Terabits/Second | Count/Second | None - - :type dimensions: dict - :param dimensions: Add extra name value pairs to associate - with the metric, i.e.: - {'name1': value1, 'name2': (value2, value3)} - - :type statistics: dict or list - :param statistics: Use a statistic set instead of a value, for example:: - - {'maximum': 30, 'minimum': 1, 'samplecount': 100, 'sum': 10000} - """ - params = {'Namespace': namespace} - self.build_put_params(params, name, value=value, timestamp=timestamp, - unit=unit, dimensions=dimensions, statistics=statistics) - - return self.get_status('PutMetricData', params, verb="POST") - - def describe_alarms(self, action_prefix=None, alarm_name_prefix=None, - alarm_names=None, max_records=None, state_value=None, - next_token=None): - """ - Retrieves alarms with the specified names. If no name is specified, all - alarms for the user are returned. Alarms can be retrieved by using only - a prefix for the alarm name, the alarm state, or a prefix for any - action. - - :type action_prefix: string - :param action_name: The action name prefix. - - :type alarm_name_prefix: string - :param alarm_name_prefix: The alarm name prefix. AlarmNames cannot - be specified if this parameter is specified. - - :type alarm_names: list - :param alarm_names: A list of alarm names to retrieve information for. - - :type max_records: int - :param max_records: The maximum number of alarm descriptions - to retrieve. - - :type state_value: string - :param state_value: The state value to be used in matching alarms. - - :type next_token: string - :param next_token: The token returned by a previous call to - indicate that there is more data. - - :rtype list - """ - params = {} - if action_prefix: - params['ActionPrefix'] = action_prefix - if alarm_name_prefix: - params['AlarmNamePrefix'] = alarm_name_prefix - elif alarm_names: - self.build_list_params(params, alarm_names, 'AlarmNames.member.%s') - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - if state_value: - params['StateValue'] = state_value - - result = self.get_list('DescribeAlarms', params, - [('MetricAlarms', MetricAlarms)]) - ret = result[0] - ret.next_token = result.next_token - return ret - - def describe_alarm_history(self, alarm_name=None, - start_date=None, end_date=None, - max_records=None, history_item_type=None, - next_token=None): - """ - Retrieves history for the specified alarm. Filter alarms by date range - or item type. If an alarm name is not specified, Amazon CloudWatch - returns histories for all of the owner's alarms. - - Amazon CloudWatch retains the history of deleted alarms for a period of - six weeks. If an alarm has been deleted, its history can still be - queried. - - :type alarm_name: string - :param alarm_name: The name of the alarm. - - :type start_date: datetime - :param start_date: The starting date to retrieve alarm history. - - :type end_date: datetime - :param end_date: The starting date to retrieve alarm history. - - :type history_item_type: string - :param history_item_type: The type of alarm histories to retreive - (ConfigurationUpdate | StateUpdate | Action) - - :type max_records: int - :param max_records: The maximum number of alarm descriptions - to retrieve. - - :type next_token: string - :param next_token: The token returned by a previous call to indicate - that there is more data. - - :rtype list - """ - params = {} - if alarm_name: - params['AlarmName'] = alarm_name - if start_date: - params['StartDate'] = start_date.isoformat() - if end_date: - params['EndDate'] = end_date.isoformat() - if history_item_type: - params['HistoryItemType'] = history_item_type - if max_records: - params['MaxRecords'] = max_records - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribeAlarmHistory', params, - [('member', AlarmHistoryItem)]) - - def describe_alarms_for_metric(self, metric_name, namespace, period=None, - statistic=None, dimensions=None, unit=None): - """ - Retrieves all alarms for a single metric. Specify a statistic, period, - or unit to filter the set of alarms further. - - :type metric_name: string - :param metric_name: The name of the metric - - :type namespace: string - :param namespace: The namespace of the metric. - - :type period: int - :param period: The period in seconds over which the statistic - is applied. - - :type statistic: string - :param statistic: The statistic for the metric. - - :param dimension_filters: A dictionary containing name/value - pairs that will be used to filter the results. The key in - the dictionary is the name of a Dimension. The value in - the dictionary is either a scalar value of that Dimension - name that you want to filter on, a list of values to - filter on or None if you want all metrics with that - Dimension name. - - :type unit: string - - :rtype list - """ - params = {'MetricName': metric_name, - 'Namespace': namespace} - if period: - params['Period'] = period - if statistic: - params['Statistic'] = statistic - if dimensions: - self.build_dimension_param(dimensions, params) - if unit: - params['Unit'] = unit - return self.get_list('DescribeAlarmsForMetric', params, - [('member', MetricAlarm)]) - - def put_metric_alarm(self, alarm): - """ - Creates or updates an alarm and associates it with the specified Amazon - CloudWatch metric. Optionally, this operation can associate one or more - Amazon Simple Notification Service resources with the alarm. - - When this operation creates an alarm, the alarm state is immediately - set to INSUFFICIENT_DATA. The alarm is evaluated and its StateValue is - set appropriately. Any actions associated with the StateValue is then - executed. - - When updating an existing alarm, its StateValue is left unchanged. - - :type alarm: boto.ec2.cloudwatch.alarm.MetricAlarm - :param alarm: MetricAlarm object. - """ - params = { - 'AlarmName': alarm.name, - 'MetricName': alarm.metric, - 'Namespace': alarm.namespace, - 'Statistic': alarm.statistic, - 'ComparisonOperator': alarm.comparison, - 'Threshold': alarm.threshold, - 'EvaluationPeriods': alarm.evaluation_periods, - 'Period': alarm.period, - } - if alarm.actions_enabled is not None: - params['ActionsEnabled'] = alarm.actions_enabled - if alarm.alarm_actions: - self.build_list_params(params, alarm.alarm_actions, - 'AlarmActions.member.%s') - if alarm.description: - params['AlarmDescription'] = alarm.description - if alarm.dimensions: - self.build_dimension_param(alarm.dimensions, params) - if alarm.insufficient_data_actions: - self.build_list_params(params, alarm.insufficient_data_actions, - 'InsufficientDataActions.member.%s') - if alarm.ok_actions: - self.build_list_params(params, alarm.ok_actions, - 'OKActions.member.%s') - if alarm.unit: - params['Unit'] = alarm.unit - alarm.connection = self - return self.get_status('PutMetricAlarm', params) - create_alarm = put_metric_alarm - update_alarm = put_metric_alarm - - def delete_alarms(self, alarms): - """ - Deletes all specified alarms. In the event of an error, no - alarms are deleted. - - :type alarms: list - :param alarms: List of alarm names. - """ - params = {} - self.build_list_params(params, alarms, 'AlarmNames.member.%s') - return self.get_status('DeleteAlarms', params) - - def set_alarm_state(self, alarm_name, state_reason, state_value, - state_reason_data=None): - """ - Temporarily sets the state of an alarm. When the updated StateValue - differs from the previous value, the action configured for the - appropriate state is invoked. This is not a permanent change. The next - periodic alarm check (in about a minute) will set the alarm to its - actual state. - - :type alarm_name: string - :param alarm_name: Descriptive name for alarm. - - :type state_reason: string - :param state_reason: Human readable reason. - - :type state_value: string - :param state_value: OK | ALARM | INSUFFICIENT_DATA - - :type state_reason_data: string - :param state_reason_data: Reason string (will be jsonified). - """ - params = {'AlarmName': alarm_name, - 'StateReason': state_reason, - 'StateValue': state_value} - if state_reason_data: - params['StateReasonData'] = json.dumps(state_reason_data) - - return self.get_status('SetAlarmState', params) - - def enable_alarm_actions(self, alarm_names): - """ - Enables actions for the specified alarms. - - :type alarms: list - :param alarms: List of alarm names. - """ - params = {} - self.build_list_params(params, alarm_names, 'AlarmNames.member.%s') - return self.get_status('EnableAlarmActions', params) - - def disable_alarm_actions(self, alarm_names): - """ - Disables actions for the specified alarms. - - :type alarms: list - :param alarms: List of alarm names. - """ - params = {} - self.build_list_params(params, alarm_names, 'AlarmNames.member.%s') - return self.get_status('DisableAlarmActions', params) diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/alarm.py b/awx/lib/site-packages/boto/ec2/cloudwatch/alarm.py deleted file mode 100644 index ac6de3d2f6..0000000000 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/alarm.py +++ /dev/null @@ -1,323 +0,0 @@ -# Copyright (c) 2010 Reza Lotun http://reza.lotun.name -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from datetime import datetime -from boto.ec2.cloudwatch.listelement import ListElement -from boto.ec2.cloudwatch.dimension import Dimension -from boto.compat import json -from boto.compat import six - - -class MetricAlarms(list): - def __init__(self, connection=None): - """ - Parses a list of MetricAlarms. - """ - list.__init__(self) - self.connection = connection - - def startElement(self, name, attrs, connection): - if name == 'member': - metric_alarm = MetricAlarm(connection) - self.append(metric_alarm) - return metric_alarm - - def endElement(self, name, value, connection): - pass - - -class MetricAlarm(object): - - OK = 'OK' - ALARM = 'ALARM' - INSUFFICIENT_DATA = 'INSUFFICIENT_DATA' - - _cmp_map = { - '>=': 'GreaterThanOrEqualToThreshold', - '>': 'GreaterThanThreshold', - '<': 'LessThanThreshold', - '<=': 'LessThanOrEqualToThreshold', - } - _rev_cmp_map = dict((v, k) for (k, v) in six.iteritems(_cmp_map)) - - def __init__(self, connection=None, name=None, metric=None, - namespace=None, statistic=None, comparison=None, - threshold=None, period=None, evaluation_periods=None, - unit=None, description='', dimensions=None, - alarm_actions=None, insufficient_data_actions=None, - ok_actions=None): - """ - Creates a new Alarm. - - :type name: str - :param name: Name of alarm. - - :type metric: str - :param metric: Name of alarm's associated metric. - - :type namespace: str - :param namespace: The namespace for the alarm's metric. - - :type statistic: str - :param statistic: The statistic to apply to the alarm's associated - metric. - Valid values: SampleCount|Average|Sum|Minimum|Maximum - - :type comparison: str - :param comparison: Comparison used to compare statistic with threshold. - Valid values: >= | > | < | <= - - :type threshold: float - :param threshold: The value against which the specified statistic - is compared. - - :type period: int - :param period: The period in seconds over which teh specified - statistic is applied. - - :type evaluation_periods: int - :param evaluation_periods: The number of periods over which data is - compared to the specified threshold. - - :type unit: str - :param unit: Allowed Values are: - Seconds|Microseconds|Milliseconds, - Bytes|Kilobytes|Megabytes|Gigabytes|Terabytes, - Bits|Kilobits|Megabits|Gigabits|Terabits, - Percent|Count| - Bytes/Second|Kilobytes/Second|Megabytes/Second| - Gigabytes/Second|Terabytes/Second, - Bits/Second|Kilobits/Second|Megabits/Second, - Gigabits/Second|Terabits/Second|Count/Second|None - - :type description: str - :param description: Description of MetricAlarm - - :type dimensions: dict - :param dimensions: A dictionary of dimension key/values where - the key is the dimension name and the value - is either a scalar value or an iterator - of values to be associated with that - dimension. - Example: { - 'InstanceId': ['i-0123456', 'i-0123457'], - 'LoadBalancerName': 'test-lb' - } - - :type alarm_actions: list of strs - :param alarm_actions: A list of the ARNs of the actions to take in - ALARM state - - :type insufficient_data_actions: list of strs - :param insufficient_data_actions: A list of the ARNs of the actions to - take in INSUFFICIENT_DATA state - - :type ok_actions: list of strs - :param ok_actions: A list of the ARNs of the actions to take in OK state - """ - self.name = name - self.connection = connection - self.metric = metric - self.namespace = namespace - self.statistic = statistic - if threshold is not None: - self.threshold = float(threshold) - else: - self.threshold = None - self.comparison = self._cmp_map.get(comparison) - if period is not None: - self.period = int(period) - else: - self.period = None - if evaluation_periods is not None: - self.evaluation_periods = int(evaluation_periods) - else: - self.evaluation_periods = None - self.actions_enabled = None - self.alarm_arn = None - self.last_updated = None - self.description = description - self.dimensions = dimensions - self.state_reason = None - self.state_value = None - self.unit = unit - self.alarm_actions = alarm_actions - self.insufficient_data_actions = insufficient_data_actions - self.ok_actions = ok_actions - - def __repr__(self): - return 'MetricAlarm:%s[%s(%s) %s %s]' % (self.name, self.metric, - self.statistic, - self.comparison, - self.threshold) - - def startElement(self, name, attrs, connection): - if name == 'AlarmActions': - self.alarm_actions = ListElement() - return self.alarm_actions - elif name == 'InsufficientDataActions': - self.insufficient_data_actions = ListElement() - return self.insufficient_data_actions - elif name == 'OKActions': - self.ok_actions = ListElement() - return self.ok_actions - elif name == 'Dimensions': - self.dimensions = Dimension() - return self.dimensions - else: - pass - - def endElement(self, name, value, connection): - if name == 'ActionsEnabled': - self.actions_enabled = value - elif name == 'AlarmArn': - self.alarm_arn = value - elif name == 'AlarmConfigurationUpdatedTimestamp': - self.last_updated = value - elif name == 'AlarmDescription': - self.description = value - elif name == 'AlarmName': - self.name = value - elif name == 'ComparisonOperator': - setattr(self, 'comparison', self._rev_cmp_map[value]) - elif name == 'EvaluationPeriods': - self.evaluation_periods = int(value) - elif name == 'MetricName': - self.metric = value - elif name == 'Namespace': - self.namespace = value - elif name == 'Period': - self.period = int(value) - elif name == 'StateReason': - self.state_reason = value - elif name == 'StateValue': - self.state_value = value - elif name == 'Statistic': - self.statistic = value - elif name == 'Threshold': - self.threshold = float(value) - elif name == 'Unit': - self.unit = value - else: - setattr(self, name, value) - - def set_state(self, value, reason, data=None): - """ Temporarily sets the state of an alarm. - - :type value: str - :param value: OK | ALARM | INSUFFICIENT_DATA - - :type reason: str - :param reason: Reason alarm set (human readable). - - :type data: str - :param data: Reason data (will be jsonified). - """ - return self.connection.set_alarm_state(self.name, reason, value, data) - - def update(self): - return self.connection.update_alarm(self) - - def enable_actions(self): - return self.connection.enable_alarm_actions([self.name]) - - def disable_actions(self): - return self.connection.disable_alarm_actions([self.name]) - - def describe_history(self, start_date=None, end_date=None, max_records=None, - history_item_type=None, next_token=None): - return self.connection.describe_alarm_history(self.name, start_date, - end_date, max_records, - history_item_type, - next_token) - - def add_alarm_action(self, action_arn=None): - """ - Adds an alarm action, represented as an SNS topic, to this alarm. - What do do when alarm is triggered. - - :type action_arn: str - :param action_arn: SNS topics to which notification should be - sent if the alarm goes to state ALARM. - """ - if not action_arn: - return # Raise exception instead? - self.actions_enabled = 'true' - self.alarm_actions.append(action_arn) - - def add_insufficient_data_action(self, action_arn=None): - """ - Adds an insufficient_data action, represented as an SNS topic, to - this alarm. What to do when the insufficient_data state is reached. - - :type action_arn: str - :param action_arn: SNS topics to which notification should be - sent if the alarm goes to state INSUFFICIENT_DATA. - """ - if not action_arn: - return - self.actions_enabled = 'true' - self.insufficient_data_actions.append(action_arn) - - def add_ok_action(self, action_arn=None): - """ - Adds an ok action, represented as an SNS topic, to this alarm. What - to do when the ok state is reached. - - :type action_arn: str - :param action_arn: SNS topics to which notification should be - sent if the alarm goes to state INSUFFICIENT_DATA. - """ - if not action_arn: - return - self.actions_enabled = 'true' - self.ok_actions.append(action_arn) - - def delete(self): - self.connection.delete_alarms([self.name]) - - -class AlarmHistoryItem(object): - def __init__(self, connection=None): - self.connection = connection - - def __repr__(self): - return 'AlarmHistory:%s[%s at %s]' % (self.name, self.summary, self.timestamp) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'AlarmName': - self.name = value - elif name == 'HistoryData': - self.data = json.loads(value) - elif name == 'HistoryItemType': - self.tem_type = value - elif name == 'HistorySummary': - self.summary = value - elif name == 'Timestamp': - try: - self.timestamp = datetime.strptime(value, - '%Y-%m-%dT%H:%M:%S.%fZ') - except ValueError: - self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/datapoint.py b/awx/lib/site-packages/boto/ec2/cloudwatch/datapoint.py deleted file mode 100644 index 94955acd56..0000000000 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/datapoint.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from datetime import datetime - - -class Datapoint(dict): - - def __init__(self, connection=None): - dict.__init__(self) - self.connection = connection - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name in ['Average', 'Maximum', 'Minimum', 'Sum', 'SampleCount']: - self[name] = float(value) - elif name == 'Timestamp': - self[name] = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ') - elif name != 'member': - self[name] = value diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/dimension.py b/awx/lib/site-packages/boto/ec2/cloudwatch/dimension.py deleted file mode 100644 index 9ff4fb1160..0000000000 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/dimension.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - -class Dimension(dict): - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Name': - self._name = value - elif name == 'Value': - if self._name in self: - self[self._name].append(value) - else: - self[self._name] = [value] - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/listelement.py b/awx/lib/site-packages/boto/ec2/cloudwatch/listelement.py deleted file mode 100644 index 6a2904181b..0000000000 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/listelement.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class ListElement(list): - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'member': - self.append(value) diff --git a/awx/lib/site-packages/boto/ec2/cloudwatch/metric.py b/awx/lib/site-packages/boto/ec2/cloudwatch/metric.py deleted file mode 100644 index f92f282a65..0000000000 --- a/awx/lib/site-packages/boto/ec2/cloudwatch/metric.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.ec2.cloudwatch.alarm import MetricAlarm -from boto.ec2.cloudwatch.dimension import Dimension - - -class Metric(object): - - Statistics = ['Minimum', 'Maximum', 'Sum', 'Average', 'SampleCount'] - Units = ['Seconds', 'Microseconds', 'Milliseconds', 'Bytes', 'Kilobytes', - 'Megabytes', 'Gigabytes', 'Terabytes', 'Bits', 'Kilobits', - 'Megabits', 'Gigabits', 'Terabits', 'Percent', 'Count', - 'Bytes/Second', 'Kilobytes/Second', 'Megabytes/Second', - 'Gigabytes/Second', 'Terabytes/Second', 'Bits/Second', - 'Kilobits/Second', 'Megabits/Second', 'Gigabits/Second', - 'Terabits/Second', 'Count/Second', None] - - def __init__(self, connection=None): - self.connection = connection - self.name = None - self.namespace = None - self.dimensions = None - - def __repr__(self): - return 'Metric:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'Dimensions': - self.dimensions = Dimension() - return self.dimensions - - def endElement(self, name, value, connection): - if name == 'MetricName': - self.name = value - elif name == 'Namespace': - self.namespace = value - else: - setattr(self, name, value) - - def query(self, start_time, end_time, statistics, unit=None, period=60): - """ - :type start_time: datetime - :param start_time: The time stamp to use for determining the - first datapoint to return. The value specified is - inclusive; results include datapoints with the time stamp - specified. - - :type end_time: datetime - :param end_time: The time stamp to use for determining the - last datapoint to return. The value specified is - exclusive; results will include datapoints up to the time - stamp specified. - - :type statistics: list - :param statistics: A list of statistics names Valid values: - Average | Sum | SampleCount | Maximum | Minimum - - :type unit: string - :param unit: The unit for the metric. Value values are: - Seconds | Microseconds | Milliseconds | Bytes | Kilobytes | - Megabytes | Gigabytes | Terabytes | Bits | Kilobits | - Megabits | Gigabits | Terabits | Percent | Count | - Bytes/Second | Kilobytes/Second | Megabytes/Second | - Gigabytes/Second | Terabytes/Second | Bits/Second | - Kilobits/Second | Megabits/Second | Gigabits/Second | - Terabits/Second | Count/Second | None - - :type period: integer - :param period: The granularity, in seconds, of the returned datapoints. - Period must be at least 60 seconds and must be a multiple - of 60. The default value is 60. - - """ - if not isinstance(statistics, list): - statistics = [statistics] - return self.connection.get_metric_statistics(period, - start_time, - end_time, - self.name, - self.namespace, - statistics, - self.dimensions, - unit) - - def create_alarm(self, name, comparison, threshold, - period, evaluation_periods, - statistic, enabled=True, description=None, - dimensions=None, alarm_actions=None, ok_actions=None, - insufficient_data_actions=None, unit=None): - """ - Creates or updates an alarm and associates it with this metric. - Optionally, this operation can associate one or more - Amazon Simple Notification Service resources with the alarm. - - When this operation creates an alarm, the alarm state is immediately - set to INSUFFICIENT_DATA. The alarm is evaluated and its StateValue is - set appropriately. Any actions associated with the StateValue is then - executed. - - When updating an existing alarm, its StateValue is left unchanged. - - :type alarm: boto.ec2.cloudwatch.alarm.MetricAlarm - :param alarm: MetricAlarm object. - """ - if not dimensions: - dimensions = self.dimensions - alarm = MetricAlarm(self.connection, name, self.name, - self.namespace, statistic, comparison, - threshold, period, evaluation_periods, - unit, description, dimensions, - alarm_actions, insufficient_data_actions, - ok_actions) - if self.connection.put_metric_alarm(alarm): - return alarm - - def describe_alarms(self, period=None, statistic=None, - dimensions=None, unit=None): - """ - Retrieves all alarms for this metric. Specify a statistic, period, - or unit to filter the set of alarms further. - - :type period: int - :param period: The period in seconds over which the statistic - is applied. - - :type statistic: string - :param statistic: The statistic for the metric. - - :param dimension_filters: A dictionary containing name/value - pairs that will be used to filter the results. The key in - the dictionary is the name of a Dimension. The value in - the dictionary is either a scalar value of that Dimension - name that you want to filter on, a list of values to - filter on or None if you want all metrics with that - Dimension name. - - :type unit: string - - :rtype list - """ - return self.connection.describe_alarms_for_metric(self.name, - self.namespace, - period, - statistic, - dimensions, - unit) diff --git a/awx/lib/site-packages/boto/ec2/connection.py b/awx/lib/site-packages/boto/ec2/connection.py deleted file mode 100644 index f301ae5d31..0000000000 --- a/awx/lib/site-packages/boto/ec2/connection.py +++ /dev/null @@ -1,4461 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a connection to the EC2 service. -""" - -import base64 -import warnings -from datetime import datetime -from datetime import timedelta - -import boto -from boto.auth import detect_potential_sigv4 -from boto.connection import AWSQueryConnection -from boto.resultset import ResultSet -from boto.ec2.image import Image, ImageAttribute, CopyImage -from boto.ec2.instance import Reservation, Instance -from boto.ec2.instance import ConsoleOutput, InstanceAttribute -from boto.ec2.keypair import KeyPair -from boto.ec2.address import Address -from boto.ec2.volume import Volume, VolumeAttribute -from boto.ec2.snapshot import Snapshot -from boto.ec2.snapshot import SnapshotAttribute -from boto.ec2.zone import Zone -from boto.ec2.securitygroup import SecurityGroup -from boto.ec2.regioninfo import RegionInfo -from boto.ec2.instanceinfo import InstanceInfo -from boto.ec2.reservedinstance import ReservedInstancesOffering -from boto.ec2.reservedinstance import ReservedInstance -from boto.ec2.reservedinstance import ReservedInstanceListing -from boto.ec2.reservedinstance import ReservedInstancesConfiguration -from boto.ec2.reservedinstance import ModifyReservedInstancesResult -from boto.ec2.reservedinstance import ReservedInstancesModification -from boto.ec2.spotinstancerequest import SpotInstanceRequest -from boto.ec2.spotpricehistory import SpotPriceHistory -from boto.ec2.spotdatafeedsubscription import SpotDatafeedSubscription -from boto.ec2.bundleinstance import BundleInstanceTask -from boto.ec2.placementgroup import PlacementGroup -from boto.ec2.tag import Tag -from boto.ec2.instancetype import InstanceType -from boto.ec2.instancestatus import InstanceStatusSet -from boto.ec2.volumestatus import VolumeStatusSet -from boto.ec2.networkinterface import NetworkInterface -from boto.ec2.attributes import AccountAttribute, VPCAttribute -from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType -from boto.exception import EC2ResponseError -from boto.compat import six - -#boto.set_stream_logger('ec2') - - -class EC2Connection(AWSQueryConnection): - - APIVersion = boto.config.get('Boto', 'ec2_version', '2014-05-01') - DefaultRegionName = boto.config.get('Boto', 'ec2_region_name', 'us-east-1') - DefaultRegionEndpoint = boto.config.get('Boto', 'ec2_region_endpoint', - 'ec2.us-east-1.amazonaws.com') - ResponseError = EC2ResponseError - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, host=None, port=None, - proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - api_version=None, security_token=None, - validate_certs=True, profile_name=None): - """ - Init method to create a new connection to EC2. - """ - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - super(EC2Connection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token, - validate_certs=validate_certs, - profile_name=profile_name) - if api_version: - self.APIVersion = api_version - - @detect_potential_sigv4 - def _required_auth_capability(self): - return ['ec2'] - - def get_params(self): - """ - Returns a dictionary containing the value of all of the keyword - arguments passed when constructing this connection. - """ - param_names = ['aws_access_key_id', 'aws_secret_access_key', - 'is_secure', 'port', 'proxy', 'proxy_port', - 'proxy_user', 'proxy_pass', - 'debug', 'https_connection_factory'] - params = {} - for name in param_names: - params[name] = getattr(self, name) - return params - - def build_filter_params(self, params, filters): - if not isinstance(filters, dict): - filters = dict(filters) - - i = 1 - for name in filters: - aws_name = name - if not aws_name.startswith('tag:'): - aws_name = name.replace('_', '-') - params['Filter.%d.Name' % i] = aws_name - value = filters[name] - if not isinstance(value, list): - value = [value] - j = 1 - for v in value: - params['Filter.%d.Value.%d' % (i, j)] = v - j += 1 - i += 1 - - # Image methods - - def get_all_images(self, image_ids=None, owners=None, - executable_by=None, filters=None, dry_run=False): - """ - Retrieve all the EC2 images available on your account. - - :type image_ids: list - :param image_ids: A list of strings with the image IDs wanted - - :type owners: list - :param owners: A list of owner IDs, the special strings 'self', - 'amazon', and 'aws-marketplace', may be used to describe - images owned by you, Amazon or AWS Marketplace - respectively - - :type executable_by: list - :param executable_by: Returns AMIs for which the specified - user ID has explicit launch permissions - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.image.Image` - """ - params = {} - if image_ids: - self.build_list_params(params, image_ids, 'ImageId') - if owners: - self.build_list_params(params, owners, 'Owner') - if executable_by: - self.build_list_params(params, executable_by, 'ExecutableBy') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeImages', params, - [('item', Image)], verb='POST') - - def get_all_kernels(self, kernel_ids=None, owners=None, dry_run=False): - """ - Retrieve all the EC2 kernels available on your account. - Constructs a filter to allow the processing to happen server side. - - :type kernel_ids: list - :param kernel_ids: A list of strings with the image IDs wanted - - :type owners: list - :param owners: A list of owner IDs - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.image.Image` - """ - params = {} - if kernel_ids: - self.build_list_params(params, kernel_ids, 'ImageId') - if owners: - self.build_list_params(params, owners, 'Owner') - filter = {'image-type': 'kernel'} - self.build_filter_params(params, filter) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeImages', params, - [('item', Image)], verb='POST') - - def get_all_ramdisks(self, ramdisk_ids=None, owners=None, dry_run=False): - """ - Retrieve all the EC2 ramdisks available on your account. - Constructs a filter to allow the processing to happen server side. - - :type ramdisk_ids: list - :param ramdisk_ids: A list of strings with the image IDs wanted - - :type owners: list - :param owners: A list of owner IDs - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.image.Image` - """ - params = {} - if ramdisk_ids: - self.build_list_params(params, ramdisk_ids, 'ImageId') - if owners: - self.build_list_params(params, owners, 'Owner') - filter = {'image-type': 'ramdisk'} - self.build_filter_params(params, filter) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeImages', params, - [('item', Image)], verb='POST') - - def get_image(self, image_id, dry_run=False): - """ - Shortcut method to retrieve a specific image (AMI). - - :type image_id: string - :param image_id: the ID of the Image to retrieve - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.image.Image` - :return: The EC2 Image specified or None if the image is not found - """ - try: - return self.get_all_images(image_ids=[image_id], dry_run=dry_run)[0] - except IndexError: # None of those images available - return None - - def register_image(self, name=None, description=None, image_location=None, - architecture=None, kernel_id=None, ramdisk_id=None, - root_device_name=None, block_device_map=None, - dry_run=False, virtualization_type=None, - sriov_net_support=None, - snapshot_id=None, - delete_root_volume_on_termination=False): - """ - Register an image. - - :type name: string - :param name: The name of the AMI. Valid only for EBS-based images. - - :type description: string - :param description: The description of the AMI. - - :type image_location: string - :param image_location: Full path to your AMI manifest in - Amazon S3 storage. Only used for S3-based AMI's. - - :type architecture: string - :param architecture: The architecture of the AMI. Valid choices are: - * i386 - * x86_64 - - :type kernel_id: string - :param kernel_id: The ID of the kernel with which to launch - the instances - - :type root_device_name: string - :param root_device_name: The root device name (e.g. /dev/sdh) - - :type block_device_map: :class:`boto.ec2.blockdevicemapping.BlockDeviceMapping` - :param block_device_map: A BlockDeviceMapping data structure - describing the EBS volumes associated with the Image. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :type virtualization_type: string - :param virtualization_type: The virutalization_type of the image. - Valid choices are: - * paravirtual - * hvm - - :type sriov_net_support: string - :param sriov_net_support: Advanced networking support. - Valid choices are: - * simple - - :type snapshot_id: string - :param snapshot_id: A snapshot ID for the snapshot to be used - as root device for the image. Mutually exclusive with - block_device_map, requires root_device_name - - :type delete_root_volume_on_termination: bool - :param delete_root_volume_on_termination: Whether to delete the root - volume of the image after instance termination. Only applies when - creating image from snapshot_id. Defaults to False. Note that - leaving volumes behind after instance termination is not free. - - :rtype: string - :return: The new image id - """ - params = {} - if name: - params['Name'] = name - if description: - params['Description'] = description - if architecture: - params['Architecture'] = architecture - if kernel_id: - params['KernelId'] = kernel_id - if ramdisk_id: - params['RamdiskId'] = ramdisk_id - if image_location: - params['ImageLocation'] = image_location - if root_device_name: - params['RootDeviceName'] = root_device_name - if snapshot_id: - root_vol = BlockDeviceType(snapshot_id=snapshot_id, - delete_on_termination=delete_root_volume_on_termination) - block_device_map = BlockDeviceMapping() - block_device_map[root_device_name] = root_vol - if block_device_map: - block_device_map.ec2_build_list_params(params) - if dry_run: - params['DryRun'] = 'true' - if virtualization_type: - params['VirtualizationType'] = virtualization_type - if sriov_net_support: - params['SriovNetSupport'] = sriov_net_support - - rs = self.get_object('RegisterImage', params, ResultSet, verb='POST') - image_id = getattr(rs, 'imageId', None) - return image_id - - def deregister_image(self, image_id, delete_snapshot=False, dry_run=False): - """ - Unregister an AMI. - - :type image_id: string - :param image_id: the ID of the Image to unregister - - :type delete_snapshot: bool - :param delete_snapshot: Set to True if we should delete the - snapshot associated with an EBS volume mounted at /dev/sda1 - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - snapshot_id = None - if delete_snapshot: - image = self.get_image(image_id) - for key in image.block_device_mapping: - if key == "/dev/sda1": - snapshot_id = image.block_device_mapping[key].snapshot_id - break - params = { - 'ImageId': image_id, - } - if dry_run: - params['DryRun'] = 'true' - result = self.get_status('DeregisterImage', - params, verb='POST') - if result and snapshot_id: - return result and self.delete_snapshot(snapshot_id) - return result - - def create_image(self, instance_id, name, - description=None, no_reboot=False, - block_device_mapping=None, dry_run=False): - """ - Will create an AMI from the instance in the running or stopped - state. - - :type instance_id: string - :param instance_id: the ID of the instance to image. - - :type name: string - :param name: The name of the new image - - :type description: string - :param description: An optional human-readable string describing - the contents and purpose of the AMI. - - :type no_reboot: bool - :param no_reboot: An optional flag indicating that the - bundling process should not attempt to shutdown the - instance before bundling. If this flag is True, the - responsibility of maintaining file system integrity is - left to the owner of the instance. - - :type block_device_mapping: :class:`boto.ec2.blockdevicemapping.BlockDeviceMapping` - :param block_device_mapping: A BlockDeviceMapping data structure - describing the EBS volumes associated with the Image. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: string - :return: The new image id - """ - params = {'InstanceId': instance_id, - 'Name': name} - if description: - params['Description'] = description - if no_reboot: - params['NoReboot'] = 'true' - if block_device_mapping: - block_device_mapping.ec2_build_list_params(params) - if dry_run: - params['DryRun'] = 'true' - img = self.get_object('CreateImage', params, Image, verb='POST') - return img.id - - # ImageAttribute methods - - def get_image_attribute(self, image_id, attribute='launchPermission', - dry_run=False): - """ - Gets an attribute from an image. - - :type image_id: string - :param image_id: The Amazon image id for which you want info about - - :type attribute: string - :param attribute: The attribute you need information about. - Valid choices are: - * launchPermission - * productCodes - * blockDeviceMapping - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.image.ImageAttribute` - :return: An ImageAttribute object representing the value of the - attribute requested - """ - params = {'ImageId': image_id, - 'Attribute': attribute} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('DescribeImageAttribute', params, - ImageAttribute, verb='POST') - - def modify_image_attribute(self, image_id, attribute='launchPermission', - operation='add', user_ids=None, groups=None, - product_codes=None, dry_run=False): - """ - Changes an attribute of an image. - - :type image_id: string - :param image_id: The image id you wish to change - - :type attribute: string - :param attribute: The attribute you wish to change - - :type operation: string - :param operation: Either add or remove (this is required for changing - launchPermissions) - - :type user_ids: list - :param user_ids: The Amazon IDs of users to add/remove attributes - - :type groups: list - :param groups: The groups to add/remove attributes - - :type product_codes: list - :param product_codes: Amazon DevPay product code. Currently only one - product code can be associated with an AMI. Once - set, the product code cannot be changed or reset. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'ImageId': image_id, - 'Attribute': attribute, - 'OperationType': operation} - if user_ids: - self.build_list_params(params, user_ids, 'UserId') - if groups: - self.build_list_params(params, groups, 'UserGroup') - if product_codes: - self.build_list_params(params, product_codes, 'ProductCode') - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ModifyImageAttribute', params, verb='POST') - - def reset_image_attribute(self, image_id, attribute='launchPermission', - dry_run=False): - """ - Resets an attribute of an AMI to its default value. - - :type image_id: string - :param image_id: ID of the AMI for which an attribute will be described - - :type attribute: string - :param attribute: The attribute to reset - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: Whether the operation succeeded or not - """ - params = {'ImageId': image_id, - 'Attribute': attribute} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ResetImageAttribute', params, verb='POST') - - # Instance methods - - def get_all_instances(self, instance_ids=None, filters=None, dry_run=False, - max_results=None): - """ - Retrieve all the instance reservations associated with your account. - - .. note:: - This method's current behavior is deprecated in favor of - :meth:`get_all_reservations`. A future major release will change - :meth:`get_all_instances` to return a list of - :class:`boto.ec2.instance.Instance` objects as its name suggests. - To obtain that behavior today, use :meth:`get_only_instances`. - - :type instance_ids: list - :param instance_ids: A list of strings of instance IDs - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :type max_results: int - :param max_results: The maximum number of paginated instance - items per response. - - :rtype: list - :return: A list of :class:`boto.ec2.instance.Reservation` - - """ - warnings.warn(('The current get_all_instances implementation will be ' - 'replaced with get_all_reservations.'), - PendingDeprecationWarning) - return self.get_all_reservations(instance_ids=instance_ids, - filters=filters, dry_run=dry_run, - max_results=max_results) - - def get_only_instances(self, instance_ids=None, filters=None, - dry_run=False, max_results=None): - # A future release should rename this method to get_all_instances - # and make get_only_instances an alias for that. - """ - Retrieve all the instances associated with your account. - - :type instance_ids: list - :param instance_ids: A list of strings of instance IDs - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :type max_results: int - :param max_results: The maximum number of paginated instance - items per response. - - :rtype: list - :return: A list of :class:`boto.ec2.instance.Instance` - """ - next_token = None - retval = [] - while True: - reservations = self.get_all_reservations(instance_ids=instance_ids, - filters=filters, - dry_run=dry_run, - max_results=max_results, - next_token=next_token) - retval.extend([instance for reservation in reservations for - instance in reservation.instances]) - next_token = reservations.next_token - if not next_token: - break - - return retval - - def get_all_reservations(self, instance_ids=None, filters=None, - dry_run=False, max_results=None, next_token=None): - """ - Retrieve all the instance reservations associated with your account. - - :type instance_ids: list - :param instance_ids: A list of strings of instance IDs - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :type max_results: int - :param max_results: The maximum number of paginated instance - items per response. - - :type next_token: str - :param next_token: A string specifying the next paginated set - of results to return. - - :rtype: list - :return: A list of :class:`boto.ec2.instance.Reservation` - """ - params = {} - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceId') - if filters: - if 'group-id' in filters: - gid = filters.get('group-id') - if not gid.startswith('sg-') or len(gid) != 11: - warnings.warn( - "The group-id filter now requires a security group " - "identifier (sg-*) instead of a group name. To filter " - "by group name use the 'group-name' filter instead.", - UserWarning) - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - if max_results is not None: - params['MaxResults'] = max_results - if next_token: - params['NextToken'] = next_token - return self.get_list('DescribeInstances', params, - [('item', Reservation)], verb='POST') - - def get_all_instance_status(self, instance_ids=None, - max_results=None, next_token=None, - filters=None, dry_run=False, - include_all_instances=False): - """ - Retrieve all the instances in your account scheduled for maintenance. - - :type instance_ids: list - :param instance_ids: A list of strings of instance IDs - - :type max_results: int - :param max_results: The maximum number of paginated instance - items per response. - - :type next_token: str - :param next_token: A string specifying the next paginated set - of results to return. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :type include_all_instances: bool - :param include_all_instances: Set to True if all - instances should be returned. (Only running - instances are included by default.) - - :rtype: list - :return: A list of instances that have maintenance scheduled. - """ - params = {} - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceId') - if max_results: - params['MaxResults'] = max_results - if next_token: - params['NextToken'] = next_token - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - if include_all_instances: - params['IncludeAllInstances'] = 'true' - return self.get_object('DescribeInstanceStatus', params, - InstanceStatusSet, verb='POST') - - def run_instances(self, image_id, min_count=1, max_count=1, - key_name=None, security_groups=None, - user_data=None, addressing_type=None, - instance_type='m1.small', placement=None, - kernel_id=None, ramdisk_id=None, - monitoring_enabled=False, subnet_id=None, - block_device_map=None, - disable_api_termination=False, - instance_initiated_shutdown_behavior=None, - private_ip_address=None, - placement_group=None, client_token=None, - security_group_ids=None, - additional_info=None, instance_profile_name=None, - instance_profile_arn=None, tenancy=None, - ebs_optimized=False, network_interfaces=None, - dry_run=False): - """ - Runs an image on EC2. - - :type image_id: string - :param image_id: The ID of the image to run. - - :type min_count: int - :param min_count: The minimum number of instances to launch. - - :type max_count: int - :param max_count: The maximum number of instances to launch. - - :type key_name: string - :param key_name: The name of the key pair with which to - launch instances. - - :type security_groups: list of strings - :param security_groups: The names of the EC2 classic security groups - with which to associate instances - - :type user_data: string - :param user_data: The Base64-encoded MIME user data to be made - available to the instance(s) in this reservation. - - :type instance_type: string - :param instance_type: The type of instance to run: - - * t1.micro - * m1.small - * m1.medium - * m1.large - * m1.xlarge - * m3.medium - * m3.large - * m3.xlarge - * m3.2xlarge - * c1.medium - * c1.xlarge - * m2.xlarge - * m2.2xlarge - * m2.4xlarge - * cr1.8xlarge - * hi1.4xlarge - * hs1.8xlarge - * cc1.4xlarge - * cg1.4xlarge - * cc2.8xlarge - * g2.2xlarge - * c3.large - * c3.xlarge - * c3.2xlarge - * c3.4xlarge - * c3.8xlarge - * i2.xlarge - * i2.2xlarge - * i2.4xlarge - * i2.8xlarge - * t2.micro - * t2.small - * t2.medium - - :type placement: string - :param placement: The Availability Zone to launch the instance into. - - :type kernel_id: string - :param kernel_id: The ID of the kernel with which to launch the - instances. - - :type ramdisk_id: string - :param ramdisk_id: The ID of the RAM disk with which to launch the - instances. - - :type monitoring_enabled: bool - :param monitoring_enabled: Enable detailed CloudWatch monitoring on - the instance. - - :type subnet_id: string - :param subnet_id: The subnet ID within which to launch the instances - for VPC. - - :type private_ip_address: string - :param private_ip_address: If you're using VPC, you can - optionally use this parameter to assign the instance a - specific available IP address from the subnet (e.g., - 10.0.0.25). - - :type block_device_map: :class:`boto.ec2.blockdevicemapping.BlockDeviceMapping` - :param block_device_map: A BlockDeviceMapping data structure - describing the EBS volumes associated with the Image. - - :type disable_api_termination: bool - :param disable_api_termination: If True, the instances will be locked - and will not be able to be terminated via the API. - - :type instance_initiated_shutdown_behavior: string - :param instance_initiated_shutdown_behavior: Specifies whether the - instance stops or terminates on instance-initiated shutdown. - Valid values are: - - * stop - * terminate - - :type placement_group: string - :param placement_group: If specified, this is the name of the placement - group in which the instance(s) will be launched. - - :type client_token: string - :param client_token: Unique, case-sensitive identifier you provide - to ensure idempotency of the request. Maximum 64 ASCII characters. - - :type security_group_ids: list of strings - :param security_group_ids: The ID of the VPC security groups with - which to associate instances. - - :type additional_info: string - :param additional_info: Specifies additional information to make - available to the instance(s). - - :type tenancy: string - :param tenancy: The tenancy of the instance you want to - launch. An instance with a tenancy of 'dedicated' runs on - single-tenant hardware and can only be launched into a - VPC. Valid values are:"default" or "dedicated". - NOTE: To use dedicated tenancy you MUST specify a VPC - subnet-ID as well. - - :type instance_profile_arn: string - :param instance_profile_arn: The Amazon resource name (ARN) of - the IAM Instance Profile (IIP) to associate with the instances. - - :type instance_profile_name: string - :param instance_profile_name: The name of - the IAM Instance Profile (IIP) to associate with the instances. - - :type ebs_optimized: bool - :param ebs_optimized: Whether the instance is optimized for - EBS I/O. This optimization provides dedicated throughput - to Amazon EBS and an optimized configuration stack to - provide optimal EBS I/O performance. This optimization - isn't available with all instance types. - - :type network_interfaces: :class:`boto.ec2.networkinterface.NetworkInterfaceCollection` - :param network_interfaces: A NetworkInterfaceCollection data - structure containing the ENI specifications for the instance. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: Reservation - :return: The :class:`boto.ec2.instance.Reservation` associated with - the request for machines - """ - params = {'ImageId': image_id, - 'MinCount': min_count, - 'MaxCount': max_count} - if key_name: - params['KeyName'] = key_name - if security_group_ids: - l = [] - for group in security_group_ids: - if isinstance(group, SecurityGroup): - l.append(group.id) - else: - l.append(group) - self.build_list_params(params, l, 'SecurityGroupId') - if security_groups: - l = [] - for group in security_groups: - if isinstance(group, SecurityGroup): - l.append(group.name) - else: - l.append(group) - self.build_list_params(params, l, 'SecurityGroup') - if user_data: - if isinstance(user_data, six.text_type): - user_data = user_data.encode('utf-8') - params['UserData'] = base64.b64encode(user_data).decode('utf-8') - if addressing_type: - params['AddressingType'] = addressing_type - if instance_type: - params['InstanceType'] = instance_type - if placement: - params['Placement.AvailabilityZone'] = placement - if placement_group: - params['Placement.GroupName'] = placement_group - if tenancy: - params['Placement.Tenancy'] = tenancy - if kernel_id: - params['KernelId'] = kernel_id - if ramdisk_id: - params['RamdiskId'] = ramdisk_id - if monitoring_enabled: - params['Monitoring.Enabled'] = 'true' - if subnet_id: - params['SubnetId'] = subnet_id - if private_ip_address: - params['PrivateIpAddress'] = private_ip_address - if block_device_map: - block_device_map.ec2_build_list_params(params) - if disable_api_termination: - params['DisableApiTermination'] = 'true' - if instance_initiated_shutdown_behavior: - val = instance_initiated_shutdown_behavior - params['InstanceInitiatedShutdownBehavior'] = val - if client_token: - params['ClientToken'] = client_token - if additional_info: - params['AdditionalInfo'] = additional_info - if instance_profile_name: - params['IamInstanceProfile.Name'] = instance_profile_name - if instance_profile_arn: - params['IamInstanceProfile.Arn'] = instance_profile_arn - if ebs_optimized: - params['EbsOptimized'] = 'true' - if network_interfaces: - network_interfaces.build_list_params(params) - if dry_run: - params['DryRun'] = 'true' - return self.get_object('RunInstances', params, Reservation, - verb='POST') - - def terminate_instances(self, instance_ids=None, dry_run=False): - """ - Terminate the instances specified - - :type instance_ids: list - :param instance_ids: A list of strings of the Instance IDs to terminate - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of the instances terminated - """ - params = {} - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceId') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('TerminateInstances', params, - [('item', Instance)], verb='POST') - - def stop_instances(self, instance_ids=None, force=False, dry_run=False): - """ - Stop the instances specified - - :type instance_ids: list - :param instance_ids: A list of strings of the Instance IDs to stop - - :type force: bool - :param force: Forces the instance to stop - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of the instances stopped - """ - params = {} - if force: - params['Force'] = 'true' - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceId') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('StopInstances', params, - [('item', Instance)], verb='POST') - - def start_instances(self, instance_ids=None, dry_run=False): - """ - Start the instances specified - - :type instance_ids: list - :param instance_ids: A list of strings of the Instance IDs to start - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of the instances started - """ - params = {} - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceId') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('StartInstances', params, - [('item', Instance)], verb='POST') - - def get_console_output(self, instance_id, dry_run=False): - """ - Retrieves the console output for the specified instance. - - :type instance_id: string - :param instance_id: The instance ID of a running instance on the cloud. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.instance.ConsoleOutput` - :return: The console output as a ConsoleOutput object - """ - params = {} - self.build_list_params(params, [instance_id], 'InstanceId') - if dry_run: - params['DryRun'] = 'true' - return self.get_object('GetConsoleOutput', params, - ConsoleOutput, verb='POST') - - def reboot_instances(self, instance_ids=None, dry_run=False): - """ - Reboot the specified instances. - - :type instance_ids: list - :param instance_ids: The instances to terminate and reboot - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {} - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceId') - if dry_run: - params['DryRun'] = 'true' - return self.get_status('RebootInstances', params) - - def confirm_product_instance(self, product_code, instance_id, - dry_run=False): - """ - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'ProductCode': product_code, - 'InstanceId': instance_id} - if dry_run: - params['DryRun'] = 'true' - rs = self.get_object('ConfirmProductInstance', params, - ResultSet, verb='POST') - return (rs.status, rs.ownerId) - - # InstanceAttribute methods - - def get_instance_attribute(self, instance_id, attribute, dry_run=False): - """ - Gets an attribute from an instance. - - :type instance_id: string - :param instance_id: The Amazon id of the instance - - :type attribute: string - :param attribute: The attribute you need information about - Valid choices are: - - * instanceType - * kernel - * ramdisk - * userData - * disableApiTermination - * instanceInitiatedShutdownBehavior - * rootDeviceName - * blockDeviceMapping - * productCodes - * sourceDestCheck - * groupSet - * ebsOptimized - * sriovNetSupport - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.image.InstanceAttribute` - :return: An InstanceAttribute object representing the value of the - attribute requested - """ - params = {'InstanceId': instance_id} - if attribute: - params['Attribute'] = attribute - if dry_run: - params['DryRun'] = 'true' - return self.get_object('DescribeInstanceAttribute', params, - InstanceAttribute, verb='POST') - - def modify_network_interface_attribute(self, interface_id, attr, value, - attachment_id=None, dry_run=False): - """ - Changes an attribute of a network interface. - - :type interface_id: string - :param interface_id: The interface id. Looks like 'eni-xxxxxxxx' - - :type attr: string - :param attr: The attribute you wish to change. - - Learn more at http://docs.aws.amazon.com/AWSEC2/latest/API\ - Reference/ApiReference-query-ModifyNetworkInterfaceAttribute.html - - * description - Textual description of interface - * groupSet - List of security group ids or group objects - * sourceDestCheck - Boolean - * deleteOnTermination - Boolean. Must also specify attachment_id - - :type value: string - :param value: The new value for the attribute - - :rtype: bool - :return: Whether the operation succeeded or not - - :type attachment_id: string - :param attachment_id: If you're modifying DeleteOnTermination you must - specify the attachment_id. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - bool_reqs = ( - 'deleteontermination', - 'sourcedestcheck', - ) - if attr.lower() in bool_reqs: - if isinstance(value, bool): - if value: - value = 'true' - else: - value = 'false' - elif value not in ['true', 'false']: - raise ValueError('%s must be a boolean, "true", or "false"!' - % attr) - - params = {'NetworkInterfaceId': interface_id} - - # groupSet is handled differently from other arguments - if attr.lower() == 'groupset': - for idx, sg in enumerate(value): - if isinstance(sg, SecurityGroup): - sg = sg.id - params['SecurityGroupId.%s' % (idx + 1)] = sg - elif attr.lower() == 'description': - params['Description.Value'] = value - elif attr.lower() == 'sourcedestcheck': - params['SourceDestCheck.Value'] = value - elif attr.lower() == 'deleteontermination': - params['Attachment.DeleteOnTermination'] = value - if not attachment_id: - raise ValueError('You must also specify an attachment_id') - params['Attachment.AttachmentId'] = attachment_id - else: - raise ValueError('Unknown attribute "%s"' % (attr,)) - - if dry_run: - params['DryRun'] = 'true' - return self.get_status( - 'ModifyNetworkInterfaceAttribute', params, verb='POST') - - def modify_instance_attribute(self, instance_id, attribute, value, - dry_run=False): - """ - Changes an attribute of an instance - - :type instance_id: string - :param instance_id: The instance id you wish to change - - :type attribute: string - :param attribute: The attribute you wish to change. - - * instanceType - A valid instance type (m1.small) - * kernel - Kernel ID (None) - * ramdisk - Ramdisk ID (None) - * userData - Base64 encoded String (None) - * disableApiTermination - Boolean (true) - * instanceInitiatedShutdownBehavior - stop|terminate - * blockDeviceMapping - List of strings - ie: ['/dev/sda=false'] - * sourceDestCheck - Boolean (true) - * groupSet - Set of Security Groups or IDs - * ebsOptimized - Boolean (false) - * sriovNetSupport - String - ie: 'simple' - - :type value: string - :param value: The new value for the attribute - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: Whether the operation succeeded or not - """ - # Allow a bool to be passed in for value of disableApiTermination - bool_reqs = ('disableapitermination', - 'sourcedestcheck', - 'ebsoptimized') - if attribute.lower() in bool_reqs: - if isinstance(value, bool): - if value: - value = 'true' - else: - value = 'false' - - params = {'InstanceId': instance_id} - - # groupSet is handled differently from other arguments - if attribute.lower() == 'groupset': - for idx, sg in enumerate(value): - if isinstance(sg, SecurityGroup): - sg = sg.id - params['GroupId.%s' % (idx + 1)] = sg - elif attribute.lower() == 'blockdevicemapping': - for idx, kv in enumerate(value): - dev_name, _, flag = kv.partition('=') - pre = 'BlockDeviceMapping.%d' % (idx + 1) - params['%s.DeviceName' % pre] = dev_name - params['%s.Ebs.DeleteOnTermination' % pre] = flag or 'true' - else: - # for backwards compatibility handle lowercase first letter - attribute = attribute[0].upper() + attribute[1:] - params['%s.Value' % attribute] = value - - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ModifyInstanceAttribute', params, verb='POST') - - def reset_instance_attribute(self, instance_id, attribute, dry_run=False): - """ - Resets an attribute of an instance to its default value. - - :type instance_id: string - :param instance_id: ID of the instance - - :type attribute: string - :param attribute: The attribute to reset. Valid values are: - kernel|ramdisk - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: Whether the operation succeeded or not - """ - params = {'InstanceId': instance_id, - 'Attribute': attribute} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ResetInstanceAttribute', params, verb='POST') - - # Spot Instances - - def get_all_spot_instance_requests(self, request_ids=None, - filters=None, dry_run=False): - """ - Retrieve all the spot instances requests associated with your account. - - :type request_ids: list - :param request_ids: A list of strings of spot instance request IDs - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of - :class:`boto.ec2.spotinstancerequest.SpotInstanceRequest` - """ - params = {} - if request_ids: - self.build_list_params(params, request_ids, 'SpotInstanceRequestId') - if filters: - if 'launch.group-id' in filters: - lgid = filters.get('launch.group-id') - if not lgid.startswith('sg-') or len(lgid) != 11: - warnings.warn( - "The 'launch.group-id' filter now requires a security " - "group id (sg-*) and no longer supports filtering by " - "group name. Please update your filters accordingly.", - UserWarning) - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeSpotInstanceRequests', params, - [('item', SpotInstanceRequest)], verb='POST') - - def get_spot_price_history(self, start_time=None, end_time=None, - instance_type=None, product_description=None, - availability_zone=None, dry_run=False, - max_results=None, next_token=None, - filters=None): - """ - Retrieve the recent history of spot instances pricing. - - :type start_time: str - :param start_time: An indication of how far back to provide price - changes for. An ISO8601 DateTime string. - - :type end_time: str - :param end_time: An indication of how far forward to provide price - changes for. An ISO8601 DateTime string. - - :type instance_type: str - :param instance_type: Filter responses to a particular instance type. - - :type product_description: str - :param product_description: Filter responses to a particular platform. - Valid values are currently: - - * Linux/UNIX - * SUSE Linux - * Windows - * Linux/UNIX (Amazon VPC) - * SUSE Linux (Amazon VPC) - * Windows (Amazon VPC) - - :type availability_zone: str - :param availability_zone: The availability zone for which prices - should be returned. If not specified, data for all - availability zones will be returned. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :type max_results: int - :param max_results: The maximum number of paginated items - per response. - - :type next_token: str - :param next_token: The next set of rows to return. This should - be the value of the ``next_token`` attribute from a previous - call to ``get_spot_price_history``. - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :rtype: list - :return: A list tuples containing price and timestamp. - """ - params = {} - if start_time: - params['StartTime'] = start_time - if end_time: - params['EndTime'] = end_time - if instance_type: - params['InstanceType'] = instance_type - if product_description: - params['ProductDescription'] = product_description - if availability_zone: - params['AvailabilityZone'] = availability_zone - if dry_run: - params['DryRun'] = 'true' - if max_results is not None: - params['MaxResults'] = max_results - if next_token: - params['NextToken'] = next_token - if filters: - self.build_filter_params(params, filters) - return self.get_list('DescribeSpotPriceHistory', params, - [('item', SpotPriceHistory)], verb='POST') - - def request_spot_instances(self, price, image_id, count=1, type='one-time', - valid_from=None, valid_until=None, - launch_group=None, availability_zone_group=None, - key_name=None, security_groups=None, - user_data=None, addressing_type=None, - instance_type='m1.small', placement=None, - kernel_id=None, ramdisk_id=None, - monitoring_enabled=False, subnet_id=None, - placement_group=None, - block_device_map=None, - instance_profile_arn=None, - instance_profile_name=None, - security_group_ids=None, - ebs_optimized=False, - network_interfaces=None, dry_run=False): - """ - Request instances on the spot market at a particular price. - - :type price: str - :param price: The maximum price of your bid - - :type image_id: string - :param image_id: The ID of the image to run - - :type count: int - :param count: The of instances to requested - - :type type: str - :param type: Type of request. Can be 'one-time' or 'persistent'. - Default is one-time. - - :type valid_from: str - :param valid_from: Start date of the request. An ISO8601 time string. - - :type valid_until: str - :param valid_until: End date of the request. An ISO8601 time string. - - :type launch_group: str - :param launch_group: If supplied, all requests will be fulfilled - as a group. - - :type availability_zone_group: str - :param availability_zone_group: If supplied, all requests will be - fulfilled within a single availability zone. - - :type key_name: string - :param key_name: The name of the key pair with which to - launch instances - - :type security_groups: list of strings - :param security_groups: The names of the security groups with which to - associate instances - - :type user_data: string - :param user_data: The user data passed to the launched instances - - :type instance_type: string - :param instance_type: The type of instance to run: - - * t1.micro - * m1.small - * m1.medium - * m1.large - * m1.xlarge - * m3.medium - * m3.large - * m3.xlarge - * m3.2xlarge - * c1.medium - * c1.xlarge - * m2.xlarge - * m2.2xlarge - * m2.4xlarge - * cr1.8xlarge - * hi1.4xlarge - * hs1.8xlarge - * cc1.4xlarge - * cg1.4xlarge - * cc2.8xlarge - * g2.2xlarge - * c3.large - * c3.xlarge - * c3.2xlarge - * c3.4xlarge - * c3.8xlarge - * i2.xlarge - * i2.2xlarge - * i2.4xlarge - * i2.8xlarge - * t2.micro - * t2.small - * t2.medium - - :type placement: string - :param placement: The availability zone in which to launch - the instances - - :type kernel_id: string - :param kernel_id: The ID of the kernel with which to launch the - instances - - :type ramdisk_id: string - :param ramdisk_id: The ID of the RAM disk with which to launch the - instances - - :type monitoring_enabled: bool - :param monitoring_enabled: Enable detailed CloudWatch monitoring on - the instance. - - :type subnet_id: string - :param subnet_id: The subnet ID within which to launch the instances - for VPC. - - :type placement_group: string - :param placement_group: If specified, this is the name of the placement - group in which the instance(s) will be launched. - - :type block_device_map: :class:`boto.ec2.blockdevicemapping.BlockDeviceMapping` - :param block_device_map: A BlockDeviceMapping data structure - describing the EBS volumes associated with the Image. - - :type security_group_ids: list of strings - :param security_group_ids: The ID of the VPC security groups with - which to associate instances. - - :type instance_profile_arn: string - :param instance_profile_arn: The Amazon resource name (ARN) of - the IAM Instance Profile (IIP) to associate with the instances. - - :type instance_profile_name: string - :param instance_profile_name: The name of - the IAM Instance Profile (IIP) to associate with the instances. - - :type ebs_optimized: bool - :param ebs_optimized: Whether the instance is optimized for - EBS I/O. This optimization provides dedicated throughput - to Amazon EBS and an optimized configuration stack to - provide optimal EBS I/O performance. This optimization - isn't available with all instance types. - - :type network_interfaces: list - :param network_interfaces: A list of - :class:`boto.ec2.networkinterface.NetworkInterfaceSpecification` - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: Reservation - :return: The :class:`boto.ec2.spotinstancerequest.SpotInstanceRequest` - associated with the request for machines - """ - ls = 'LaunchSpecification' - params = {'%s.ImageId' % ls: image_id, - 'Type': type, - 'SpotPrice': price} - if count: - params['InstanceCount'] = count - if valid_from: - params['ValidFrom'] = valid_from - if valid_until: - params['ValidUntil'] = valid_until - if launch_group: - params['LaunchGroup'] = launch_group - if availability_zone_group: - params['AvailabilityZoneGroup'] = availability_zone_group - if key_name: - params['%s.KeyName' % ls] = key_name - if security_group_ids: - l = [] - for group in security_group_ids: - if isinstance(group, SecurityGroup): - l.append(group.id) - else: - l.append(group) - self.build_list_params(params, l, - '%s.SecurityGroupId' % ls) - if security_groups: - l = [] - for group in security_groups: - if isinstance(group, SecurityGroup): - l.append(group.name) - else: - l.append(group) - self.build_list_params(params, l, '%s.SecurityGroup' % ls) - if user_data: - params['%s.UserData' % ls] = base64.b64encode(user_data) - if addressing_type: - params['%s.AddressingType' % ls] = addressing_type - if instance_type: - params['%s.InstanceType' % ls] = instance_type - if placement: - params['%s.Placement.AvailabilityZone' % ls] = placement - if kernel_id: - params['%s.KernelId' % ls] = kernel_id - if ramdisk_id: - params['%s.RamdiskId' % ls] = ramdisk_id - if monitoring_enabled: - params['%s.Monitoring.Enabled' % ls] = 'true' - if subnet_id: - params['%s.SubnetId' % ls] = subnet_id - if placement_group: - params['%s.Placement.GroupName' % ls] = placement_group - if block_device_map: - block_device_map.ec2_build_list_params(params, '%s.' % ls) - if instance_profile_name: - params['%s.IamInstanceProfile.Name' % ls] = instance_profile_name - if instance_profile_arn: - params['%s.IamInstanceProfile.Arn' % ls] = instance_profile_arn - if ebs_optimized: - params['%s.EbsOptimized' % ls] = 'true' - if network_interfaces: - network_interfaces.build_list_params(params, prefix=ls + '.') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('RequestSpotInstances', params, - [('item', SpotInstanceRequest)], - verb='POST') - - def cancel_spot_instance_requests(self, request_ids, dry_run=False): - """ - Cancel the specified Spot Instance Requests. - - :type request_ids: list - :param request_ids: A list of strings of the Request IDs to terminate - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of the instances terminated - """ - params = {} - if request_ids: - self.build_list_params(params, request_ids, 'SpotInstanceRequestId') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('CancelSpotInstanceRequests', params, - [('item', SpotInstanceRequest)], verb='POST') - - def get_spot_datafeed_subscription(self, dry_run=False): - """ - Return the current spot instance data feed subscription - associated with this account, if any. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.spotdatafeedsubscription.SpotDatafeedSubscription` - :return: The datafeed subscription object or None - """ - params = {} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('DescribeSpotDatafeedSubscription', - params, SpotDatafeedSubscription, verb='POST') - - def create_spot_datafeed_subscription(self, bucket, prefix, dry_run=False): - """ - Create a spot instance datafeed subscription for this account. - - :type bucket: str or unicode - :param bucket: The name of the bucket where spot instance data - will be written. The account issuing this request - must have FULL_CONTROL access to the bucket - specified in the request. - - :type prefix: str or unicode - :param prefix: An optional prefix that will be pre-pended to all - data files written to the bucket. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.spotdatafeedsubscription.SpotDatafeedSubscription` - :return: The datafeed subscription object or None - """ - params = {'Bucket': bucket} - if prefix: - params['Prefix'] = prefix - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateSpotDatafeedSubscription', - params, SpotDatafeedSubscription, verb='POST') - - def delete_spot_datafeed_subscription(self, dry_run=False): - """ - Delete the current spot instance data feed subscription - associated with this account - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteSpotDatafeedSubscription', - params, verb='POST') - - # Zone methods - - def get_all_zones(self, zones=None, filters=None, dry_run=False): - """ - Get all Availability Zones associated with the current region. - - :type zones: list - :param zones: Optional list of zones. If this list is present, - only the Zones associated with these zone names - will be returned. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list of :class:`boto.ec2.zone.Zone` - :return: The requested Zone objects - """ - params = {} - if zones: - self.build_list_params(params, zones, 'ZoneName') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeAvailabilityZones', params, - [('item', Zone)], verb='POST') - - # Address methods - - def get_all_addresses(self, addresses=None, filters=None, - allocation_ids=None, dry_run=False): - """ - Get all EIP's associated with the current credentials. - - :type addresses: list - :param addresses: Optional list of addresses. If this list is present, - only the Addresses associated with these addresses - will be returned. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type allocation_ids: list - :param allocation_ids: Optional list of allocation IDs. If this list is - present, only the Addresses associated with the given - allocation IDs will be returned. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list of :class:`boto.ec2.address.Address` - :return: The requested Address objects - """ - params = {} - if addresses: - self.build_list_params(params, addresses, 'PublicIp') - if allocation_ids: - self.build_list_params(params, allocation_ids, 'AllocationId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeAddresses', params, [('item', Address)], verb='POST') - - def allocate_address(self, domain=None, dry_run=False): - """ - Allocate a new Elastic IP address and associate it with your account. - - :type domain: string - :param domain: Optional string. If domain is set to "vpc" the address - will be allocated to VPC . Will return address object with - allocation_id. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.address.Address` - :return: The newly allocated Address - """ - params = {} - - if domain is not None: - params['Domain'] = domain - - if dry_run: - params['DryRun'] = 'true' - - return self.get_object('AllocateAddress', params, Address, verb='POST') - - def assign_private_ip_addresses(self, network_interface_id=None, - private_ip_addresses=None, - secondary_private_ip_address_count=None, - allow_reassignment=False, dry_run=False): - """ - Assigns one or more secondary private IP addresses to a network - interface in Amazon VPC. - - :type network_interface_id: string - :param network_interface_id: The network interface to which the IP - address will be assigned. - - :type private_ip_addresses: list - :param private_ip_addresses: Assigns the specified IP addresses as - secondary IP addresses to the network interface. - - :type secondary_private_ip_address_count: int - :param secondary_private_ip_address_count: The number of secondary IP - addresses to assign to the network interface. You cannot specify - this parameter when also specifying private_ip_addresses. - - :type allow_reassignment: bool - :param allow_reassignment: Specifies whether to allow an IP address - that is already assigned to another network interface or instance - to be reassigned to the specified network interface. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {} - - if network_interface_id is not None: - params['NetworkInterfaceId'] = network_interface_id - - if private_ip_addresses is not None: - self.build_list_params(params, private_ip_addresses, - 'PrivateIpAddress') - elif secondary_private_ip_address_count is not None: - params['SecondaryPrivateIpAddressCount'] = \ - secondary_private_ip_address_count - - if allow_reassignment: - params['AllowReassignment'] = 'true' - - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('AssignPrivateIpAddresses', params, verb='POST') - - def _associate_address(self, status, instance_id=None, public_ip=None, - allocation_id=None, network_interface_id=None, - private_ip_address=None, allow_reassociation=False, - dry_run=False): - params = {} - if instance_id is not None: - params['InstanceId'] = instance_id - elif network_interface_id is not None: - params['NetworkInterfaceId'] = network_interface_id - - # Allocation id trumps public ip in order to associate with VPCs - if allocation_id is not None: - params['AllocationId'] = allocation_id - elif public_ip is not None: - params['PublicIp'] = public_ip - - if private_ip_address is not None: - params['PrivateIpAddress'] = private_ip_address - - if allow_reassociation: - params['AllowReassociation'] = 'true' - - if dry_run: - params['DryRun'] = 'true' - - if status: - return self.get_status('AssociateAddress', params, verb='POST') - else: - return self.get_object('AssociateAddress', params, Address, - verb='POST') - - def associate_address(self, instance_id=None, public_ip=None, - allocation_id=None, network_interface_id=None, - private_ip_address=None, allow_reassociation=False, - dry_run=False): - """ - Associate an Elastic IP address with a currently running instance. - This requires one of ``public_ip`` or ``allocation_id`` depending - on if you're associating a VPC address or a plain EC2 address. - - When using an Allocation ID, make sure to pass ``None`` for ``public_ip`` - as EC2 expects a single parameter and if ``public_ip`` is passed boto - will preference that instead of ``allocation_id``. - - :type instance_id: string - :param instance_id: The ID of the instance - - :type public_ip: string - :param public_ip: The public IP address for EC2 based allocations. - - :type allocation_id: string - :param allocation_id: The allocation ID for a VPC-based elastic IP. - - :type network_interface_id: string - :param network_interface_id: The network interface ID to which - elastic IP is to be assigned to - - :type private_ip_address: string - :param private_ip_address: The primary or secondary private IP address - to associate with the Elastic IP address. - - :type allow_reassociation: bool - :param allow_reassociation: Specify this option to allow an Elastic IP - address that is already associated with another network interface - or instance to be re-associated with the specified instance or - interface. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - return self._associate_address(True, instance_id=instance_id, - public_ip=public_ip, allocation_id=allocation_id, - network_interface_id=network_interface_id, - private_ip_address=private_ip_address, - allow_reassociation=allow_reassociation, dry_run=dry_run) - - def associate_address_object(self, instance_id=None, public_ip=None, - allocation_id=None, network_interface_id=None, - private_ip_address=None, allow_reassociation=False, - dry_run=False): - """ - Associate an Elastic IP address with a currently running instance. - This requires one of ``public_ip`` or ``allocation_id`` depending - on if you're associating a VPC address or a plain EC2 address. - - When using an Allocation ID, make sure to pass ``None`` for ``public_ip`` - as EC2 expects a single parameter and if ``public_ip`` is passed boto - will preference that instead of ``allocation_id``. - - :type instance_id: string - :param instance_id: The ID of the instance - - :type public_ip: string - :param public_ip: The public IP address for EC2 based allocations. - - :type allocation_id: string - :param allocation_id: The allocation ID for a VPC-based elastic IP. - - :type network_interface_id: string - :param network_interface_id: The network interface ID to which - elastic IP is to be assigned to - - :type private_ip_address: string - :param private_ip_address: The primary or secondary private IP address - to associate with the Elastic IP address. - - :type allow_reassociation: bool - :param allow_reassociation: Specify this option to allow an Elastic IP - address that is already associated with another network interface - or instance to be re-associated with the specified instance or - interface. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: class:`boto.ec2.address.Address` - :return: The associated address instance - """ - return self._associate_address(False, instance_id=instance_id, - public_ip=public_ip, allocation_id=allocation_id, - network_interface_id=network_interface_id, - private_ip_address=private_ip_address, - allow_reassociation=allow_reassociation, dry_run=dry_run) - - def disassociate_address(self, public_ip=None, association_id=None, - dry_run=False): - """ - Disassociate an Elastic IP address from a currently running instance. - - :type public_ip: string - :param public_ip: The public IP address for EC2 elastic IPs. - - :type association_id: string - :param association_id: The association ID for a VPC based elastic ip. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {} - - # If there is an association id it trumps public ip - # in order to successfully dissassociate with a VPC elastic ip - if association_id is not None: - params['AssociationId'] = association_id - elif public_ip is not None: - params['PublicIp'] = public_ip - - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('DisassociateAddress', params, verb='POST') - - def release_address(self, public_ip=None, allocation_id=None, - dry_run=False): - """ - Free up an Elastic IP address. Pass a public IP address to - release an EC2 Elastic IP address and an AllocationId to - release a VPC Elastic IP address. You should only pass - one value. - - This requires one of ``public_ip`` or ``allocation_id`` depending - on if you're associating a VPC address or a plain EC2 address. - - When using an Allocation ID, make sure to pass ``None`` for ``public_ip`` - as EC2 expects a single parameter and if ``public_ip`` is passed boto - will preference that instead of ``allocation_id``. - - :type public_ip: string - :param public_ip: The public IP address for EC2 elastic IPs. - - :type allocation_id: string - :param allocation_id: The Allocation ID for VPC elastic IPs. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {} - - if public_ip is not None: - params['PublicIp'] = public_ip - elif allocation_id is not None: - params['AllocationId'] = allocation_id - - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('ReleaseAddress', params, verb='POST') - - def unassign_private_ip_addresses(self, network_interface_id=None, - private_ip_addresses=None, dry_run=False): - """ - Unassigns one or more secondary private IP addresses from a network - interface in Amazon VPC. - - :type network_interface_id: string - :param network_interface_id: The network interface from which the - secondary private IP address will be unassigned. - - :type private_ip_addresses: list - :param private_ip_addresses: Specifies the secondary private IP - addresses that you want to unassign from the network interface. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {} - - if network_interface_id is not None: - params['NetworkInterfaceId'] = network_interface_id - - if private_ip_addresses is not None: - self.build_list_params(params, private_ip_addresses, - 'PrivateIpAddress') - - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('UnassignPrivateIpAddresses', params, - verb='POST') - - # Volume methods - - def get_all_volumes(self, volume_ids=None, filters=None, dry_run=False): - """ - Get all Volumes associated with the current credentials. - - :type volume_ids: list - :param volume_ids: Optional list of volume ids. If this list - is present, only the volumes associated with - these volume ids will be returned. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list of :class:`boto.ec2.volume.Volume` - :return: The requested Volume objects - """ - params = {} - if volume_ids: - self.build_list_params(params, volume_ids, 'VolumeId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeVolumes', params, - [('item', Volume)], verb='POST') - - def get_all_volume_status(self, volume_ids=None, - max_results=None, next_token=None, - filters=None, dry_run=False): - """ - Retrieve the status of one or more volumes. - - :type volume_ids: list - :param volume_ids: A list of strings of volume IDs - - :type max_results: int - :param max_results: The maximum number of paginated instance - items per response. - - :type next_token: str - :param next_token: A string specifying the next paginated set - of results to return. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of volume status. - """ - params = {} - if volume_ids: - self.build_list_params(params, volume_ids, 'VolumeId') - if max_results: - params['MaxResults'] = max_results - if next_token: - params['NextToken'] = next_token - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_object('DescribeVolumeStatus', params, - VolumeStatusSet, verb='POST') - - def enable_volume_io(self, volume_id, dry_run=False): - """ - Enables I/O operations for a volume that had I/O operations - disabled because the data on the volume was potentially inconsistent. - - :type volume_id: str - :param volume_id: The ID of the volume. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'VolumeId': volume_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('EnableVolumeIO', params, verb='POST') - - def get_volume_attribute(self, volume_id, - attribute='autoEnableIO', dry_run=False): - """ - Describes attribute of the volume. - - :type volume_id: str - :param volume_id: The ID of the volume. - - :type attribute: str - :param attribute: The requested attribute. Valid values are: - - * autoEnableIO - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list of :class:`boto.ec2.volume.VolumeAttribute` - :return: The requested Volume attribute - """ - params = {'VolumeId': volume_id, 'Attribute': attribute} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('DescribeVolumeAttribute', params, - VolumeAttribute, verb='POST') - - def modify_volume_attribute(self, volume_id, attribute, new_value, - dry_run=False): - """ - Changes an attribute of an Volume. - - :type volume_id: string - :param volume_id: The volume id you wish to change - - :type attribute: string - :param attribute: The attribute you wish to change. Valid values are: - AutoEnableIO. - - :type new_value: string - :param new_value: The new value of the attribute. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'VolumeId': volume_id} - if attribute == 'AutoEnableIO': - params['AutoEnableIO.Value'] = new_value - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ModifyVolumeAttribute', params, verb='POST') - - def create_volume(self, size, zone, snapshot=None, volume_type=None, - iops=None, encrypted=False, dry_run=False): - """ - Create a new EBS Volume. - - :type size: int - :param size: The size of the new volume, in GiB - - :type zone: string or :class:`boto.ec2.zone.Zone` - :param zone: The availability zone in which the Volume will be created. - - :type snapshot: string or :class:`boto.ec2.snapshot.Snapshot` - :param snapshot: The snapshot from which the new Volume will be - created. - - :type volume_type: string - :param volume_type: The type of the volume. (optional). Valid - values are: standard | io1 | gp2. - - :type iops: int - :param iops: The provisioned IOPS you want to associate with - this volume. (optional) - - :type encrypted: bool - :param encrypted: Specifies whether the volume should be encrypted. - (optional) - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - if isinstance(zone, Zone): - zone = zone.name - params = {'AvailabilityZone': zone} - if size: - params['Size'] = size - if snapshot: - if isinstance(snapshot, Snapshot): - snapshot = snapshot.id - params['SnapshotId'] = snapshot - if volume_type: - params['VolumeType'] = volume_type - if iops: - params['Iops'] = str(iops) - if encrypted: - params['Encrypted'] = 'true' - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateVolume', params, Volume, verb='POST') - - def delete_volume(self, volume_id, dry_run=False): - """ - Delete an EBS volume. - - :type volume_id: str - :param volume_id: The ID of the volume to be delete. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'VolumeId': volume_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteVolume', params, verb='POST') - - def attach_volume(self, volume_id, instance_id, device, dry_run=False): - """ - Attach an EBS volume to an EC2 instance. - - :type volume_id: str - :param volume_id: The ID of the EBS volume to be attached. - - :type instance_id: str - :param instance_id: The ID of the EC2 instance to which it will - be attached. - - :type device: str - :param device: The device on the instance through which the - volume will be exposted (e.g. /dev/sdh) - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'InstanceId': instance_id, - 'VolumeId': volume_id, - 'Device': device} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('AttachVolume', params, verb='POST') - - def detach_volume(self, volume_id, instance_id=None, - device=None, force=False, dry_run=False): - """ - Detach an EBS volume from an EC2 instance. - - :type volume_id: str - :param volume_id: The ID of the EBS volume to be attached. - - :type instance_id: str - :param instance_id: The ID of the EC2 instance from which it will - be detached. - - :type device: str - :param device: The device on the instance through which the - volume is exposted (e.g. /dev/sdh) - - :type force: bool - :param force: Forces detachment if the previous detachment - attempt did not occur cleanly. This option can lead to - data loss or a corrupted file system. Use this option only - as a last resort to detach a volume from a failed - instance. The instance will not have an opportunity to - flush file system caches nor file system meta data. If you - use this option, you must perform file system check and - repair procedures. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'VolumeId': volume_id} - if instance_id: - params['InstanceId'] = instance_id - if device: - params['Device'] = device - if force: - params['Force'] = 'true' - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DetachVolume', params, verb='POST') - - # Snapshot methods - - def get_all_snapshots(self, snapshot_ids=None, - owner=None, restorable_by=None, - filters=None, dry_run=False): - """ - Get all EBS Snapshots associated with the current credentials. - - :type snapshot_ids: list - :param snapshot_ids: Optional list of snapshot ids. If this list is - present, only the Snapshots associated with - these snapshot ids will be returned. - - :type owner: str or list - :param owner: If present, only the snapshots owned by the specified user(s) - will be returned. Valid values are: - - * self - * amazon - * AWS Account ID - - :type restorable_by: str or list - :param restorable_by: If present, only the snapshots that are restorable - by the specified account id(s) will be returned. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list of :class:`boto.ec2.snapshot.Snapshot` - :return: The requested Snapshot objects - """ - params = {} - if snapshot_ids: - self.build_list_params(params, snapshot_ids, 'SnapshotId') - - if owner: - self.build_list_params(params, owner, 'Owner') - if restorable_by: - self.build_list_params(params, restorable_by, 'RestorableBy') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeSnapshots', params, - [('item', Snapshot)], verb='POST') - - def create_snapshot(self, volume_id, description=None, dry_run=False): - """ - Create a snapshot of an existing EBS Volume. - - :type volume_id: str - :param volume_id: The ID of the volume to be snapshot'ed - - :type description: str - :param description: A description of the snapshot. - Limited to 255 characters. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.snapshot.Snapshot` - :return: The created Snapshot object - """ - params = {'VolumeId': volume_id} - if description: - params['Description'] = description[0:255] - if dry_run: - params['DryRun'] = 'true' - snapshot = self.get_object('CreateSnapshot', params, - Snapshot, verb='POST') - volume = self.get_all_volumes([volume_id], dry_run=dry_run)[0] - volume_name = volume.tags.get('Name') - if volume_name: - snapshot.add_tag('Name', volume_name) - return snapshot - - def delete_snapshot(self, snapshot_id, dry_run=False): - """ - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'SnapshotId': snapshot_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteSnapshot', params, verb='POST') - - def copy_snapshot(self, source_region, source_snapshot_id, - description=None, dry_run=False): - """ - Copies a point-in-time snapshot of an Amazon Elastic Block Store - (Amazon EBS) volume and stores it in Amazon Simple Storage Service - (Amazon S3). You can copy the snapshot within the same region or from - one region to another. You can use the snapshot to create new Amazon - EBS volumes or Amazon Machine Images (AMIs). - - - :type source_region: str - :param source_region: The ID of the AWS region that contains the - snapshot to be copied (e.g 'us-east-1', 'us-west-2', etc.). - - :type source_snapshot_id: str - :param source_snapshot_id: The ID of the Amazon EBS snapshot to copy - - :type description: str - :param description: A description of the new Amazon EBS snapshot. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: str - :return: The snapshot ID - - """ - params = { - 'SourceRegion': source_region, - 'SourceSnapshotId': source_snapshot_id, - } - if description is not None: - params['Description'] = description - if dry_run: - params['DryRun'] = 'true' - snapshot = self.get_object('CopySnapshot', params, Snapshot, - verb='POST') - return snapshot.id - - def trim_snapshots(self, hourly_backups=8, daily_backups=7, - weekly_backups=4, monthly_backups=True): - """ - Trim excess snapshots, based on when they were taken. More current - snapshots are retained, with the number retained decreasing as you - move back in time. - - If ebs volumes have a 'Name' tag with a value, their snapshots - will be assigned the same tag when they are created. The values - of the 'Name' tags for snapshots are used by this function to - group snapshots taken from the same volume (or from a series - of like-named volumes over time) for trimming. - - For every group of like-named snapshots, this function retains - the newest and oldest snapshots, as well as, by default, the - first snapshots taken in each of the last eight hours, the first - snapshots taken in each of the last seven days, the first snapshots - taken in the last 4 weeks (counting Midnight Sunday morning as - the start of the week), and the first snapshot from the first - day of each month forever. - - :type hourly_backups: int - :param hourly_backups: How many recent hourly backups should be saved. - - :type daily_backups: int - :param daily_backups: How many recent daily backups should be saved. - - :type weekly_backups: int - :param weekly_backups: How many recent weekly backups should be saved. - - :type monthly_backups: int - :param monthly_backups: How many monthly backups should be saved. Use True for no limit. - """ - - # This function first builds up an ordered list of target times - # that snapshots should be saved for (last 8 hours, last 7 days, etc.). - # Then a map of snapshots is constructed, with the keys being - # the snapshot / volume names and the values being arrays of - # chronologically sorted snapshots. - # Finally, for each array in the map, we go through the snapshot - # array and the target time array in an interleaved fashion, - # deleting snapshots whose start_times don't immediately follow a - # target time (we delete a snapshot if there's another snapshot - # that was made closer to the preceding target time). - - now = datetime.utcnow() - last_hour = datetime(now.year, now.month, now.day, now.hour) - last_midnight = datetime(now.year, now.month, now.day) - last_sunday = datetime(now.year, now.month, now.day) - timedelta(days=(now.weekday() + 1) % 7) - start_of_month = datetime(now.year, now.month, 1) - - target_backup_times = [] - - # there are no snapshots older than 1/1/2007 - oldest_snapshot_date = datetime(2007, 1, 1) - - for hour in range(0, hourly_backups): - target_backup_times.append(last_hour - timedelta(hours=hour)) - - for day in range(0, daily_backups): - target_backup_times.append(last_midnight - timedelta(days=day)) - - for week in range(0, weekly_backups): - target_backup_times.append(last_sunday - timedelta(weeks=week)) - - one_day = timedelta(days=1) - monthly_snapshots_added = 0 - while (start_of_month > oldest_snapshot_date and - (monthly_backups is True or - monthly_snapshots_added < monthly_backups)): - # append the start of the month to the list of - # snapshot dates to save: - target_backup_times.append(start_of_month) - monthly_snapshots_added += 1 - # there's no timedelta setting for one month, so instead: - # decrement the day by one, so we go to the final day of - # the previous month... - start_of_month -= one_day - # ... and then go to the first day of that previous month: - start_of_month = datetime(start_of_month.year, - start_of_month.month, 1) - - temp = [] - - for t in target_backup_times: - if temp.__contains__(t) == False: - temp.append(t) - - # sort to make the oldest dates first, and make sure the month start - # and last four week's start are in the proper order - target_backup_times = sorted(temp) - - # get all the snapshots, sort them by date and time, and - # organize them into one array for each volume: - all_snapshots = self.get_all_snapshots(owner = 'self') - all_snapshots.sort(cmp = lambda x, y: cmp(x.start_time, y.start_time)) - snaps_for_each_volume = {} - for snap in all_snapshots: - # the snapshot name and the volume name are the same. - # The snapshot name is set from the volume - # name at the time the snapshot is taken - volume_name = snap.tags.get('Name') - if volume_name: - # only examine snapshots that have a volume name - snaps_for_volume = snaps_for_each_volume.get(volume_name) - if not snaps_for_volume: - snaps_for_volume = [] - snaps_for_each_volume[volume_name] = snaps_for_volume - snaps_for_volume.append(snap) - - # Do a running comparison of snapshot dates to desired time - #periods, keeping the oldest snapshot in each - # time period and deleting the rest: - for volume_name in snaps_for_each_volume: - snaps = snaps_for_each_volume[volume_name] - snaps = snaps[:-1] # never delete the newest snapshot - time_period_number = 0 - snap_found_for_this_time_period = False - for snap in snaps: - check_this_snap = True - while check_this_snap and time_period_number < target_backup_times.__len__(): - snap_date = datetime.strptime(snap.start_time, - '%Y-%m-%dT%H:%M:%S.000Z') - if snap_date < target_backup_times[time_period_number]: - # the snap date is before the cutoff date. - # Figure out if it's the first snap in this - # date range and act accordingly (since both - #date the date ranges and the snapshots - # are sorted chronologically, we know this - #snapshot isn't in an earlier date range): - if snap_found_for_this_time_period == True: - if not snap.tags.get('preserve_snapshot'): - # as long as the snapshot wasn't marked - # with the 'preserve_snapshot' tag, delete it: - try: - self.delete_snapshot(snap.id) - boto.log.info('Trimmed snapshot %s (%s)' % (snap.tags['Name'], snap.start_time)) - except EC2ResponseError: - boto.log.error('Attempt to trim snapshot %s (%s) failed. Possible result of a race condition with trimming on another server?' % (snap.tags['Name'], snap.start_time)) - # go on and look at the next snapshot, - #leaving the time period alone - else: - # this was the first snapshot found for this - #time period. Leave it alone and look at the - # next snapshot: - snap_found_for_this_time_period = True - check_this_snap = False - else: - # the snap is after the cutoff date. Check it - # against the next cutoff date - time_period_number += 1 - snap_found_for_this_time_period = False - - def get_snapshot_attribute(self, snapshot_id, - attribute='createVolumePermission', - dry_run=False): - """ - Get information about an attribute of a snapshot. Only one attribute - can be specified per call. - - :type snapshot_id: str - :param snapshot_id: The ID of the snapshot. - - :type attribute: str - :param attribute: The requested attribute. Valid values are: - - * createVolumePermission - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list of :class:`boto.ec2.snapshotattribute.SnapshotAttribute` - :return: The requested Snapshot attribute - """ - params = {'Attribute': attribute} - if snapshot_id: - params['SnapshotId'] = snapshot_id - if dry_run: - params['DryRun'] = 'true' - return self.get_object('DescribeSnapshotAttribute', params, - SnapshotAttribute, verb='POST') - - def modify_snapshot_attribute(self, snapshot_id, - attribute='createVolumePermission', - operation='add', user_ids=None, groups=None, - dry_run=False): - """ - Changes an attribute of an image. - - :type snapshot_id: string - :param snapshot_id: The snapshot id you wish to change - - :type attribute: string - :param attribute: The attribute you wish to change. Valid values are: - createVolumePermission - - :type operation: string - :param operation: Either add or remove (this is required for changing - snapshot ermissions) - - :type user_ids: list - :param user_ids: The Amazon IDs of users to add/remove attributes - - :type groups: list - :param groups: The groups to add/remove attributes. The only valid - value at this time is 'all'. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'SnapshotId': snapshot_id, - 'Attribute': attribute, - 'OperationType': operation} - if user_ids: - self.build_list_params(params, user_ids, 'UserId') - if groups: - self.build_list_params(params, groups, 'UserGroup') - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ModifySnapshotAttribute', params, verb='POST') - - def reset_snapshot_attribute(self, snapshot_id, - attribute='createVolumePermission', - dry_run=False): - """ - Resets an attribute of a snapshot to its default value. - - :type snapshot_id: string - :param snapshot_id: ID of the snapshot - - :type attribute: string - :param attribute: The attribute to reset - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: Whether the operation succeeded or not - """ - params = {'SnapshotId': snapshot_id, - 'Attribute': attribute} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ResetSnapshotAttribute', params, verb='POST') - - # Keypair methods - - def get_all_key_pairs(self, keynames=None, filters=None, dry_run=False): - """ - Get all key pairs associated with your account. - - :type keynames: list - :param keynames: A list of the names of keypairs to retrieve. - If not provided, all key pairs will be returned. - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.keypair.KeyPair` - """ - params = {} - if keynames: - self.build_list_params(params, keynames, 'KeyName') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeKeyPairs', params, - [('item', KeyPair)], verb='POST') - - def get_key_pair(self, keyname, dry_run=False): - """ - Convenience method to retrieve a specific keypair (KeyPair). - - :type keyname: string - :param keyname: The name of the keypair to retrieve - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.keypair.KeyPair` - :return: The KeyPair specified or None if it is not found - """ - try: - return self.get_all_key_pairs( - keynames=[keyname], - dry_run=dry_run - )[0] - except self.ResponseError as e: - if e.code == 'InvalidKeyPair.NotFound': - return None - else: - raise - - def create_key_pair(self, key_name, dry_run=False): - """ - Create a new key pair for your account. - This will create the key pair within the region you - are currently connected to. - - :type key_name: string - :param key_name: The name of the new keypair - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.keypair.KeyPair` - :return: The newly created :class:`boto.ec2.keypair.KeyPair`. - The material attribute of the new KeyPair object - will contain the the unencrypted PEM encoded RSA private key. - """ - params = {'KeyName': key_name} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateKeyPair', params, KeyPair, verb='POST') - - def delete_key_pair(self, key_name, dry_run=False): - """ - Delete a key pair from your account. - - :type key_name: string - :param key_name: The name of the keypair to delete - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'KeyName': key_name} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteKeyPair', params, verb='POST') - - def import_key_pair(self, key_name, public_key_material, dry_run=False): - """ - imports the public key from an RSA key pair that you created - with a third-party tool. - - Supported formats: - - * OpenSSH public key format (e.g., the format - in ~/.ssh/authorized_keys) - - * Base64 encoded DER format - - * SSH public key file format as specified in RFC4716 - - DSA keys are not supported. Make sure your key generator is - set up to create RSA keys. - - Supported lengths: 1024, 2048, and 4096. - - :type key_name: string - :param key_name: The name of the new keypair - - :type public_key_material: string - :param public_key_material: The public key. You must base64 encode - the public key material before sending - it to AWS. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.keypair.KeyPair` - :return: A :class:`boto.ec2.keypair.KeyPair` object representing - the newly imported key pair. This object will contain only - the key name and the fingerprint. - """ - public_key_material = base64.b64encode(public_key_material) - params = {'KeyName': key_name, - 'PublicKeyMaterial': public_key_material} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('ImportKeyPair', params, KeyPair, verb='POST') - - # SecurityGroup methods - - def get_all_security_groups(self, groupnames=None, group_ids=None, - filters=None, dry_run=False): - """ - Get all security groups associated with your account in a region. - - :type groupnames: list - :param groupnames: A list of the names of security groups to retrieve. - If not provided, all security groups will be - returned. - - :type group_ids: list - :param group_ids: A list of IDs of security groups to retrieve for - security groups within a VPC. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.securitygroup.SecurityGroup` - """ - params = {} - if groupnames is not None: - self.build_list_params(params, groupnames, 'GroupName') - if group_ids is not None: - self.build_list_params(params, group_ids, 'GroupId') - if filters is not None: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeSecurityGroups', params, - [('item', SecurityGroup)], verb='POST') - - def create_security_group(self, name, description, vpc_id=None, - dry_run=False): - """ - Create a new security group for your account. - This will create the security group within the region you - are currently connected to. - - :type name: string - :param name: The name of the new security group - - :type description: string - :param description: The description of the new security group - - :type vpc_id: string - :param vpc_id: The ID of the VPC to create the security group in, - if any. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.securitygroup.SecurityGroup` - :return: The newly created :class:`boto.ec2.securitygroup.SecurityGroup`. - """ - params = {'GroupName': name, - 'GroupDescription': description} - - if vpc_id is not None: - params['VpcId'] = vpc_id - - if dry_run: - params['DryRun'] = 'true' - - group = self.get_object('CreateSecurityGroup', params, - SecurityGroup, verb='POST') - group.name = name - group.description = description - if vpc_id is not None: - group.vpc_id = vpc_id - return group - - def delete_security_group(self, name=None, group_id=None, dry_run=False): - """ - Delete a security group from your account. - - :type name: string - :param name: The name of the security group to delete. - - :type group_id: string - :param group_id: The ID of the security group to delete within - a VPC. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful. - """ - params = {} - - if name is not None: - params['GroupName'] = name - elif group_id is not None: - params['GroupId'] = group_id - - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('DeleteSecurityGroup', params, verb='POST') - - def authorize_security_group_deprecated(self, group_name, - src_security_group_name=None, - src_security_group_owner_id=None, - ip_protocol=None, - from_port=None, to_port=None, - cidr_ip=None, dry_run=False): - """ - NOTE: This method uses the old-style request parameters - that did not allow a port to be specified when - authorizing a group. - - :type group_name: string - :param group_name: The name of the security group you are adding - the rule to. - - :type src_security_group_name: string - :param src_security_group_name: The name of the security group you are - granting access to. - - :type src_security_group_owner_id: string - :param src_security_group_owner_id: The ID of the owner of the security - group you are granting access to. - - :type ip_protocol: string - :param ip_protocol: Either tcp | udp | icmp - - :type from_port: int - :param from_port: The beginning port number you are enabling - - :type to_port: int - :param to_port: The ending port number you are enabling - - :type to_port: string - :param to_port: The CIDR block you are providing access to. - See http://goo.gl/Yj5QC - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful. - """ - params = {'GroupName': group_name} - if src_security_group_name: - params['SourceSecurityGroupName'] = src_security_group_name - if src_security_group_owner_id: - params['SourceSecurityGroupOwnerId'] = src_security_group_owner_id - if ip_protocol: - params['IpProtocol'] = ip_protocol - if from_port: - params['FromPort'] = from_port - if to_port: - params['ToPort'] = to_port - if cidr_ip: - params['CidrIp'] = cidr_ip - if dry_run: - params['DryRun'] = 'true' - return self.get_status('AuthorizeSecurityGroupIngress', params) - - def authorize_security_group(self, group_name=None, - src_security_group_name=None, - src_security_group_owner_id=None, - ip_protocol=None, - from_port=None, to_port=None, - cidr_ip=None, group_id=None, - src_security_group_group_id=None, - dry_run=False): - """ - Add a new rule to an existing security group. - You need to pass in either src_security_group_name and - src_security_group_owner_id OR ip_protocol, from_port, to_port, - and cidr_ip. In other words, either you are authorizing another - group or you are authorizing some ip-based rule. - - :type group_name: string - :param group_name: The name of the security group you are adding - the rule to. - - :type src_security_group_name: string - :param src_security_group_name: The name of the security group you are - granting access to. - - :type src_security_group_owner_id: string - :param src_security_group_owner_id: The ID of the owner of the security - group you are granting access to. - - :type ip_protocol: string - :param ip_protocol: Either tcp | udp | icmp - - :type from_port: int - :param from_port: The beginning port number you are enabling - - :type to_port: int - :param to_port: The ending port number you are enabling - - :type cidr_ip: string or list of strings - :param cidr_ip: The CIDR block you are providing access to. - See http://goo.gl/Yj5QC - - :type group_id: string - :param group_id: ID of the EC2 or VPC security group to - modify. This is required for VPC security groups and can - be used instead of group_name for EC2 security groups. - - :type src_security_group_group_id: string - :param src_security_group_group_id: The ID of the security - group you are granting access to. Can be used instead of - src_security_group_name - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful. - """ - if src_security_group_name: - if from_port is None and to_port is None and ip_protocol is None: - return self.authorize_security_group_deprecated( - group_name, src_security_group_name, - src_security_group_owner_id) - - params = {} - - if group_name: - params['GroupName'] = group_name - if group_id: - params['GroupId'] = group_id - if src_security_group_name: - param_name = 'IpPermissions.1.Groups.1.GroupName' - params[param_name] = src_security_group_name - if src_security_group_owner_id: - param_name = 'IpPermissions.1.Groups.1.UserId' - params[param_name] = src_security_group_owner_id - if src_security_group_group_id: - param_name = 'IpPermissions.1.Groups.1.GroupId' - params[param_name] = src_security_group_group_id - if ip_protocol: - params['IpPermissions.1.IpProtocol'] = ip_protocol - if from_port is not None: - params['IpPermissions.1.FromPort'] = from_port - if to_port is not None: - params['IpPermissions.1.ToPort'] = to_port - if cidr_ip: - if not isinstance(cidr_ip, list): - cidr_ip = [cidr_ip] - for i, single_cidr_ip in enumerate(cidr_ip): - params['IpPermissions.1.IpRanges.%d.CidrIp' % (i + 1)] = \ - single_cidr_ip - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('AuthorizeSecurityGroupIngress', - params, verb='POST') - - def authorize_security_group_egress(self, - group_id, - ip_protocol, - from_port=None, - to_port=None, - src_group_id=None, - cidr_ip=None, - dry_run=False): - """ - The action adds one or more egress rules to a VPC security - group. Specifically, this action permits instances in a - security group to send traffic to one or more destination - CIDR IP address ranges, or to one or more destination - security groups in the same VPC. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = { - 'GroupId': group_id, - 'IpPermissions.1.IpProtocol': ip_protocol - } - - if from_port is not None: - params['IpPermissions.1.FromPort'] = from_port - if to_port is not None: - params['IpPermissions.1.ToPort'] = to_port - if src_group_id is not None: - params['IpPermissions.1.Groups.1.GroupId'] = src_group_id - if cidr_ip is not None: - params['IpPermissions.1.IpRanges.1.CidrIp'] = cidr_ip - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('AuthorizeSecurityGroupEgress', - params, verb='POST') - - def revoke_security_group_deprecated(self, group_name, - src_security_group_name=None, - src_security_group_owner_id=None, - ip_protocol=None, - from_port=None, to_port=None, - cidr_ip=None, dry_run=False): - """ - NOTE: This method uses the old-style request parameters - that did not allow a port to be specified when - authorizing a group. - - Remove an existing rule from an existing security group. - You need to pass in either src_security_group_name and - src_security_group_owner_id OR ip_protocol, from_port, to_port, - and cidr_ip. In other words, either you are revoking another - group or you are revoking some ip-based rule. - - :type group_name: string - :param group_name: The name of the security group you are removing - the rule from. - - :type src_security_group_name: string - :param src_security_group_name: The name of the security group you are - revoking access to. - - :type src_security_group_owner_id: string - :param src_security_group_owner_id: The ID of the owner of the security - group you are revoking access to. - - :type ip_protocol: string - :param ip_protocol: Either tcp | udp | icmp - - :type from_port: int - :param from_port: The beginning port number you are disabling - - :type to_port: int - :param to_port: The ending port number you are disabling - - :type to_port: string - :param to_port: The CIDR block you are revoking access to. - http://goo.gl/Yj5QC - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful. - """ - params = {'GroupName': group_name} - if src_security_group_name: - params['SourceSecurityGroupName'] = src_security_group_name - if src_security_group_owner_id: - params['SourceSecurityGroupOwnerId'] = src_security_group_owner_id - if ip_protocol: - params['IpProtocol'] = ip_protocol - if from_port: - params['FromPort'] = from_port - if to_port: - params['ToPort'] = to_port - if cidr_ip: - params['CidrIp'] = cidr_ip - if dry_run: - params['DryRun'] = 'true' - return self.get_status('RevokeSecurityGroupIngress', params) - - def revoke_security_group(self, group_name=None, - src_security_group_name=None, - src_security_group_owner_id=None, - ip_protocol=None, from_port=None, to_port=None, - cidr_ip=None, group_id=None, - src_security_group_group_id=None, dry_run=False): - """ - Remove an existing rule from an existing security group. - You need to pass in either src_security_group_name and - src_security_group_owner_id OR ip_protocol, from_port, to_port, - and cidr_ip. In other words, either you are revoking another - group or you are revoking some ip-based rule. - - :type group_name: string - :param group_name: The name of the security group you are removing - the rule from. - - :type src_security_group_name: string - :param src_security_group_name: The name of the security group you are - revoking access to. - - :type src_security_group_owner_id: string - :param src_security_group_owner_id: The ID of the owner of the security - group you are revoking access to. - - :type ip_protocol: string - :param ip_protocol: Either tcp | udp | icmp - - :type from_port: int - :param from_port: The beginning port number you are disabling - - :type to_port: int - :param to_port: The ending port number you are disabling - - :type cidr_ip: string - :param cidr_ip: The CIDR block you are revoking access to. - See http://goo.gl/Yj5QC - - :type group_id: string - :param group_id: ID of the EC2 or VPC security group to - modify. This is required for VPC security groups and can - be used instead of group_name for EC2 security groups. - - :type src_security_group_group_id: string - :param src_security_group_group_id: The ID of the security group - for which you are revoking access. Can be used instead - of src_security_group_name - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful. - """ - if src_security_group_name: - if from_port is None and to_port is None and ip_protocol is None: - return self.revoke_security_group_deprecated( - group_name, src_security_group_name, - src_security_group_owner_id) - params = {} - if group_name is not None: - params['GroupName'] = group_name - if group_id is not None: - params['GroupId'] = group_id - if src_security_group_name: - param_name = 'IpPermissions.1.Groups.1.GroupName' - params[param_name] = src_security_group_name - if src_security_group_group_id: - param_name = 'IpPermissions.1.Groups.1.GroupId' - params[param_name] = src_security_group_group_id - if src_security_group_owner_id: - param_name = 'IpPermissions.1.Groups.1.UserId' - params[param_name] = src_security_group_owner_id - if ip_protocol: - params['IpPermissions.1.IpProtocol'] = ip_protocol - if from_port is not None: - params['IpPermissions.1.FromPort'] = from_port - if to_port is not None: - params['IpPermissions.1.ToPort'] = to_port - if cidr_ip: - params['IpPermissions.1.IpRanges.1.CidrIp'] = cidr_ip - if dry_run: - params['DryRun'] = 'true' - return self.get_status('RevokeSecurityGroupIngress', - params, verb='POST') - - def revoke_security_group_egress(self, - group_id, - ip_protocol, - from_port=None, - to_port=None, - src_group_id=None, - cidr_ip=None, dry_run=False): - """ - Remove an existing egress rule from an existing VPC security - group. You need to pass in an ip_protocol, from_port and - to_port range only if the protocol you are using is - port-based. You also need to pass in either a src_group_id or - cidr_ip. - - :type group_name: string - :param group_id: The name of the security group you are removing - the rule from. - - :type ip_protocol: string - :param ip_protocol: Either tcp | udp | icmp | -1 - - :type from_port: int - :param from_port: The beginning port number you are disabling - - :type to_port: int - :param to_port: The ending port number you are disabling - - :type src_group_id: src_group_id - :param src_group_id: The source security group you are - revoking access to. - - :type cidr_ip: string - :param cidr_ip: The CIDR block you are revoking access to. - See http://goo.gl/Yj5QC - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful. - """ - - params = {} - if group_id: - params['GroupId'] = group_id - if ip_protocol: - params['IpPermissions.1.IpProtocol'] = ip_protocol - if from_port is not None: - params['IpPermissions.1.FromPort'] = from_port - if to_port is not None: - params['IpPermissions.1.ToPort'] = to_port - if src_group_id is not None: - params['IpPermissions.1.Groups.1.GroupId'] = src_group_id - if cidr_ip: - params['IpPermissions.1.IpRanges.1.CidrIp'] = cidr_ip - if dry_run: - params['DryRun'] = 'true' - return self.get_status('RevokeSecurityGroupEgress', - params, verb='POST') - - # - # Regions - # - - def get_all_regions(self, region_names=None, filters=None, dry_run=False): - """ - Get all available regions for the EC2 service. - - :type region_names: list of str - :param region_names: Names of regions to limit output - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.regioninfo.RegionInfo` - """ - params = {} - if region_names: - self.build_list_params(params, region_names, 'RegionName') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - regions = self.get_list('DescribeRegions', params, - [('item', RegionInfo)], verb='POST') - for region in regions: - region.connection_cls = EC2Connection - return regions - - # - # Reservation methods - # - - def get_all_reserved_instances_offerings(self, - reserved_instances_offering_ids=None, - instance_type=None, - availability_zone=None, - product_description=None, - filters=None, - instance_tenancy=None, - offering_type=None, - include_marketplace=None, - min_duration=None, - max_duration=None, - max_instance_count=None, - next_token=None, - max_results=None, - dry_run=False): - """ - Describes Reserved Instance offerings that are available for purchase. - - :type reserved_instances_offering_ids: list - :param reserved_instances_id: One or more Reserved Instances - offering IDs. - - :type instance_type: str - :param instance_type: Displays Reserved Instances of the specified - instance type. - - :type availability_zone: str - :param availability_zone: Displays Reserved Instances within the - specified Availability Zone. - - :type product_description: str - :param product_description: Displays Reserved Instances with the - specified product description. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type instance_tenancy: string - :param instance_tenancy: The tenancy of the Reserved Instance offering. - A Reserved Instance with tenancy of dedicated will run on - single-tenant hardware and can only be launched within a VPC. - - :type offering_type: string - :param offering_type: The Reserved Instance offering type. Valid - Values: `"Heavy Utilization" | "Medium Utilization" | "Light - Utilization"` - - :type include_marketplace: bool - :param include_marketplace: Include Marketplace offerings in the - response. - - :type min_duration: int :param min_duration: Minimum duration (in - seconds) to filter when searching for offerings. - - :type max_duration: int - :param max_duration: Maximum duration (in seconds) to filter when - searching for offerings. - - :type max_instance_count: int - :param max_instance_count: Maximum number of instances to filter when - searching for offerings. - - :type next_token: string - :param next_token: Token to use when requesting the next paginated set - of offerings. - - :type max_results: int - :param max_results: Maximum number of offerings to return per call. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of - :class:`boto.ec2.reservedinstance.ReservedInstancesOffering`. - - """ - params = {} - if reserved_instances_offering_ids is not None: - self.build_list_params(params, reserved_instances_offering_ids, - 'ReservedInstancesOfferingId') - if instance_type: - params['InstanceType'] = instance_type - if availability_zone: - params['AvailabilityZone'] = availability_zone - if product_description: - params['ProductDescription'] = product_description - if filters: - self.build_filter_params(params, filters) - if instance_tenancy is not None: - params['InstanceTenancy'] = instance_tenancy - if offering_type is not None: - params['OfferingType'] = offering_type - if include_marketplace is not None: - if include_marketplace: - params['IncludeMarketplace'] = 'true' - else: - params['IncludeMarketplace'] = 'false' - if min_duration is not None: - params['MinDuration'] = str(min_duration) - if max_duration is not None: - params['MaxDuration'] = str(max_duration) - if max_instance_count is not None: - params['MaxInstanceCount'] = str(max_instance_count) - if next_token is not None: - params['NextToken'] = next_token - if max_results is not None: - params['MaxResults'] = str(max_results) - if dry_run: - params['DryRun'] = 'true' - - return self.get_list('DescribeReservedInstancesOfferings', - params, [('item', ReservedInstancesOffering)], - verb='POST') - - def get_all_reserved_instances(self, reserved_instances_id=None, - filters=None, dry_run=False): - """ - Describes one or more of the Reserved Instances that you purchased. - - :type reserved_instance_ids: list - :param reserved_instance_ids: A list of the reserved instance ids that - will be returned. If not provided, all reserved instances - will be returned. - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.reservedinstance.ReservedInstance` - """ - params = {} - if reserved_instances_id: - self.build_list_params(params, reserved_instances_id, - 'ReservedInstancesId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeReservedInstances', - params, [('item', ReservedInstance)], verb='POST') - - def purchase_reserved_instance_offering(self, - reserved_instances_offering_id, - instance_count=1, limit_price=None, - dry_run=False): - """ - Purchase a Reserved Instance for use with your account. - ** CAUTION ** - This request can result in large amounts of money being charged to your - AWS account. Use with caution! - - :type reserved_instances_offering_id: string - :param reserved_instances_offering_id: The offering ID of the Reserved - Instance to purchase - - :type instance_count: int - :param instance_count: The number of Reserved Instances to purchase. - Default value is 1. - - :type limit_price: tuple - :param instance_count: Limit the price on the total order. - Must be a tuple of (amount, currency_code), for example: - (100.0, 'USD'). - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.reservedinstance.ReservedInstance` - :return: The newly created Reserved Instance - """ - params = { - 'ReservedInstancesOfferingId': reserved_instances_offering_id, - 'InstanceCount': instance_count} - if limit_price is not None: - params['LimitPrice.Amount'] = str(limit_price[0]) - params['LimitPrice.CurrencyCode'] = str(limit_price[1]) - if dry_run: - params['DryRun'] = 'true' - return self.get_object('PurchaseReservedInstancesOffering', params, - ReservedInstance, verb='POST') - - def create_reserved_instances_listing(self, reserved_instances_id, - instance_count, price_schedules, - client_token, dry_run=False): - """Creates a new listing for Reserved Instances. - - Creates a new listing for Amazon EC2 Reserved Instances that will be - sold in the Reserved Instance Marketplace. You can submit one Reserved - Instance listing at a time. - - The Reserved Instance Marketplace matches sellers who want to resell - Reserved Instance capacity that they no longer need with buyers who - want to purchase additional capacity. Reserved Instances bought and - sold through the Reserved Instance Marketplace work like any other - Reserved Instances. - - If you want to sell your Reserved Instances, you must first register as - a Seller in the Reserved Instance Marketplace. After completing the - registration process, you can create a Reserved Instance Marketplace - listing of some or all of your Reserved Instances, and specify the - upfront price you want to receive for them. Your Reserved Instance - listings then become available for purchase. - - :type reserved_instances_id: string - :param reserved_instances_id: The ID of the Reserved Instance that - will be listed. - - :type instance_count: int - :param instance_count: The number of instances that are a part of a - Reserved Instance account that will be listed in the Reserved - Instance Marketplace. This number should be less than or equal to - the instance count associated with the Reserved Instance ID - specified in this call. - - :type price_schedules: List of tuples - :param price_schedules: A list specifying the price of the Reserved - Instance for each month remaining in the Reserved Instance term. - Each tuple contains two elements, the price and the term. For - example, for an instance that 11 months remaining in its term, - we can have a price schedule with an upfront price of $2.50. - At 8 months remaining we can drop the price down to $2.00. - This would be expressed as:: - - price_schedules=[('2.50', 11), ('2.00', 8)] - - :type client_token: string - :param client_token: Unique, case-sensitive identifier you provide - to ensure idempotency of the request. Maximum 64 ASCII characters. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of - :class:`boto.ec2.reservedinstance.ReservedInstanceListing` - - """ - params = { - 'ReservedInstancesId': reserved_instances_id, - 'InstanceCount': str(instance_count), - 'ClientToken': client_token, - } - for i, schedule in enumerate(price_schedules): - price, term = schedule - params['PriceSchedules.%s.Price' % i] = str(price) - params['PriceSchedules.%s.Term' % i] = str(term) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('CreateReservedInstancesListing', - params, [('item', ReservedInstanceListing)], verb='POST') - - def cancel_reserved_instances_listing(self, - reserved_instances_listing_ids=None, - dry_run=False): - """Cancels the specified Reserved Instance listing. - - :type reserved_instances_listing_ids: List of strings - :param reserved_instances_listing_ids: The ID of the - Reserved Instance listing to be cancelled. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of - :class:`boto.ec2.reservedinstance.ReservedInstanceListing` - - """ - params = {} - if reserved_instances_listing_ids is not None: - self.build_list_params(params, reserved_instances_listing_ids, - 'ReservedInstancesListingId') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('CancelReservedInstancesListing', - params, [('item', ReservedInstanceListing)], verb='POST') - - def build_configurations_param_list(self, params, target_configurations): - for offset, tc in enumerate(target_configurations): - prefix = 'ReservedInstancesConfigurationSetItemType.%d.' % offset - if tc.availability_zone is not None: - params[prefix + 'AvailabilityZone'] = tc.availability_zone - if tc.platform is not None: - params[prefix + 'Platform'] = tc.platform - if tc.instance_count is not None: - params[prefix + 'InstanceCount'] = tc.instance_count - - def modify_reserved_instances(self, client_token, reserved_instance_ids, - target_configurations): - """ - Modifies the specified Reserved Instances. - - :type client_token: string - :param client_token: A unique, case-sensitive, token you provide to - ensure idempotency of your modification request. - - :type reserved_instance_ids: List of strings - :param reserved_instance_ids: The IDs of the Reserved Instances to - modify. - - :type target_configurations: List of :class:`boto.ec2.reservedinstance.ReservedInstancesConfiguration` - :param target_configurations: The configuration settings for the - modified Reserved Instances. - - :rtype: string - :return: The unique ID for the submitted modification request. - """ - params = { - 'ClientToken': client_token, - } - if reserved_instance_ids is not None: - self.build_list_params(params, reserved_instance_ids, - 'ReservedInstancesId') - if target_configurations is not None: - self.build_configurations_param_list(params, target_configurations) - mrir = self.get_object( - 'ModifyReservedInstances', - params, - ModifyReservedInstancesResult, - verb='POST' - ) - return mrir.modification_id - - def describe_reserved_instances_modifications(self, - reserved_instances_modification_ids=None, next_token=None, - filters=None): - """ - A request to describe the modifications made to Reserved Instances in - your account. - - :type reserved_instances_modification_ids: list - :param reserved_instances_modification_ids: An optional list of - Reserved Instances modification IDs to describe. - - :type next_token: str - :param next_token: A string specifying the next paginated set - of results to return. - - :type filters: dict - :param filters: Optional filters that can be used to limit the - results returned. Filters are provided in the form of a - dictionary consisting of filter names as the key and - filter values as the value. The set of allowable filter - names/values is dependent on the request being performed. - Check the EC2 API guide for details. - - :rtype: list - :return: A list of :class:`boto.ec2.reservedinstance.ReservedInstance` - """ - params = {} - if reserved_instances_modification_ids: - self.build_list_params(params, reserved_instances_modification_ids, - 'ReservedInstancesModificationId') - if next_token: - params['NextToken'] = next_token - if filters: - self.build_filter_params(params, filters) - return self.get_list('DescribeReservedInstancesModifications', - params, [('item', ReservedInstancesModification)], - verb='POST') - - # - # Monitoring - # - - def monitor_instances(self, instance_ids, dry_run=False): - """ - Enable detailed CloudWatch monitoring for the supplied instances. - - :type instance_id: list of strings - :param instance_id: The instance ids - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo` - """ - params = {} - self.build_list_params(params, instance_ids, 'InstanceId') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('MonitorInstances', params, - [('item', InstanceInfo)], verb='POST') - - def monitor_instance(self, instance_id, dry_run=False): - """ - Deprecated Version, maintained for backward compatibility. - Enable detailed CloudWatch monitoring for the supplied instance. - - :type instance_id: string - :param instance_id: The instance id - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo` - """ - return self.monitor_instances([instance_id], dry_run=dry_run) - - def unmonitor_instances(self, instance_ids, dry_run=False): - """ - Disable CloudWatch monitoring for the supplied instance. - - :type instance_id: list of string - :param instance_id: The instance id - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo` - """ - params = {} - self.build_list_params(params, instance_ids, 'InstanceId') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('UnmonitorInstances', params, - [('item', InstanceInfo)], verb='POST') - - def unmonitor_instance(self, instance_id, dry_run=False): - """ - Deprecated Version, maintained for backward compatibility. - Disable detailed CloudWatch monitoring for the supplied instance. - - :type instance_id: string - :param instance_id: The instance id - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.instanceinfo.InstanceInfo` - """ - return self.unmonitor_instances([instance_id], dry_run=dry_run) - - # - # Bundle Windows Instances - # - - def bundle_instance(self, instance_id, - s3_bucket, - s3_prefix, - s3_upload_policy, dry_run=False): - """ - Bundle Windows instance. - - :type instance_id: string - :param instance_id: The instance id - - :type s3_bucket: string - :param s3_bucket: The bucket in which the AMI should be stored. - - :type s3_prefix: string - :param s3_prefix: The beginning of the file name for the AMI. - - :type s3_upload_policy: string - :param s3_upload_policy: Base64 encoded policy that specifies condition - and permissions for Amazon EC2 to upload the - user's image into Amazon S3. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - - params = {'InstanceId': instance_id, - 'Storage.S3.Bucket': s3_bucket, - 'Storage.S3.Prefix': s3_prefix, - 'Storage.S3.UploadPolicy': s3_upload_policy} - s3auth = boto.auth.get_auth_handler(None, boto.config, - self.provider, ['s3']) - params['Storage.S3.AWSAccessKeyId'] = self.aws_access_key_id - signature = s3auth.sign_string(s3_upload_policy) - params['Storage.S3.UploadPolicySignature'] = signature - if dry_run: - params['DryRun'] = 'true' - return self.get_object('BundleInstance', params, - BundleInstanceTask, verb='POST') - - def get_all_bundle_tasks(self, bundle_ids=None, filters=None, - dry_run=False): - """ - Retrieve current bundling tasks. If no bundle id is specified, all - tasks are retrieved. - - :type bundle_ids: list - :param bundle_ids: A list of strings containing identifiers for - previously created bundling tasks. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {} - if bundle_ids: - self.build_list_params(params, bundle_ids, 'BundleId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeBundleTasks', params, - [('item', BundleInstanceTask)], verb='POST') - - def cancel_bundle_task(self, bundle_id, dry_run=False): - """ - Cancel a previously submitted bundle task - - :type bundle_id: string - :param bundle_id: The identifier of the bundle task to cancel. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'BundleId': bundle_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CancelBundleTask', params, - BundleInstanceTask, verb='POST') - - def get_password_data(self, instance_id, dry_run=False): - """ - Get encrypted administrator password for a Windows instance. - - :type instance_id: string - :param instance_id: The identifier of the instance to retrieve the - password for. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'InstanceId': instance_id} - if dry_run: - params['DryRun'] = 'true' - rs = self.get_object('GetPasswordData', params, ResultSet, verb='POST') - return rs.passwordData - - # - # Cluster Placement Groups - # - - def get_all_placement_groups(self, groupnames=None, filters=None, - dry_run=False): - """ - Get all placement groups associated with your account in a region. - - :type groupnames: list - :param groupnames: A list of the names of placement groups to retrieve. - If not provided, all placement groups will be - returned. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.placementgroup.PlacementGroup` - """ - params = {} - if groupnames: - self.build_list_params(params, groupnames, 'GroupName') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribePlacementGroups', params, - [('item', PlacementGroup)], verb='POST') - - def create_placement_group(self, name, strategy='cluster', dry_run=False): - """ - Create a new placement group for your account. - This will create the placement group within the region you - are currently connected to. - - :type name: string - :param name: The name of the new placement group - - :type strategy: string - :param strategy: The placement strategy of the new placement group. - Currently, the only acceptable value is "cluster". - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'GroupName': name, 'Strategy': strategy} - if dry_run: - params['DryRun'] = 'true' - group = self.get_status('CreatePlacementGroup', params, verb='POST') - return group - - def delete_placement_group(self, name, dry_run=False): - """ - Delete a placement group from your account. - - :type key_name: string - :param key_name: The name of the keypair to delete - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'GroupName': name} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeletePlacementGroup', params, verb='POST') - - # Tag methods - - def build_tag_param_list(self, params, tags): - keys = sorted(tags.keys()) - i = 1 - for key in keys: - value = tags[key] - params['Tag.%d.Key' % i] = key - if value is not None: - params['Tag.%d.Value' % i] = value - i += 1 - - def get_all_tags(self, filters=None, dry_run=False, max_results=None): - """ - Retrieve all the metadata tags associated with your account. - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :type max_results: int - :param max_results: The maximum number of paginated instance - items per response. - - :rtype: list - :return: A list of :class:`boto.ec2.tag.Tag` objects - """ - params = {} - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - if max_results is not None: - params['MaxResults'] = max_results - return self.get_list('DescribeTags', params, - [('item', Tag)], verb='POST') - - def create_tags(self, resource_ids, tags, dry_run=False): - """ - Create new metadata tags for the specified resource ids. - - :type resource_ids: list - :param resource_ids: List of strings - - :type tags: dict - :param tags: A dictionary containing the name/value pairs. - If you want to create only a tag name, the - value for that tag should be the empty string - (e.g. ''). - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {} - self.build_list_params(params, resource_ids, 'ResourceId') - self.build_tag_param_list(params, tags) - if dry_run: - params['DryRun'] = 'true' - return self.get_status('CreateTags', params, verb='POST') - - def delete_tags(self, resource_ids, tags, dry_run=False): - """ - Delete metadata tags for the specified resource ids. - - :type resource_ids: list - :param resource_ids: List of strings - - :type tags: dict or list - :param tags: Either a dictionary containing name/value pairs - or a list containing just tag names. - If you pass in a dictionary, the values must - match the actual tag values or the tag will - not be deleted. If you pass in a value of None - for the tag value, all tags with that name will - be deleted. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - if isinstance(tags, list): - tags = {}.fromkeys(tags, None) - params = {} - self.build_list_params(params, resource_ids, 'ResourceId') - self.build_tag_param_list(params, tags) - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteTags', params, verb='POST') - - # Network Interface methods - - def get_all_network_interfaces(self, network_interface_ids=None, filters=None, dry_run=False): - """ - Retrieve all of the Elastic Network Interfaces (ENI's) - associated with your account. - - :type network_interface_ids: list - :param network_interface_ids: a list of strings representing ENI IDs - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.ec2.networkinterface.NetworkInterface` - """ - params = {} - if network_interface_ids: - self.build_list_params(params, network_interface_ids, 'NetworkInterfaceId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeNetworkInterfaces', params, - [('item', NetworkInterface)], verb='POST') - - def create_network_interface(self, subnet_id, private_ip_address=None, - description=None, groups=None, dry_run=False): - """ - Creates a network interface in the specified subnet. - - :type subnet_id: str - :param subnet_id: The ID of the subnet to associate with the - network interface. - - :type private_ip_address: str - :param private_ip_address: The private IP address of the - network interface. If not supplied, one will be chosen - for you. - - :type description: str - :param description: The description of the network interface. - - :type groups: list - :param groups: Lists the groups for use by the network interface. - This can be either a list of group ID's or a list of - :class:`boto.ec2.securitygroup.SecurityGroup` objects. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: :class:`boto.ec2.networkinterface.NetworkInterface` - :return: The newly created network interface. - """ - params = {'SubnetId': subnet_id} - if private_ip_address: - params['PrivateIpAddress'] = private_ip_address - if description: - params['Description'] = description - if groups: - ids = [] - for group in groups: - if isinstance(group, SecurityGroup): - ids.append(group.id) - else: - ids.append(group) - self.build_list_params(params, ids, 'SecurityGroupId') - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateNetworkInterface', params, - NetworkInterface, verb='POST') - - def attach_network_interface(self, network_interface_id, - instance_id, device_index, dry_run=False): - """ - Attaches a network interface to an instance. - - :type network_interface_id: str - :param network_interface_id: The ID of the network interface to attach. - - :type instance_id: str - :param instance_id: The ID of the instance that will be attached - to the network interface. - - :type device_index: int - :param device_index: The index of the device for the network - interface attachment on the instance. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'NetworkInterfaceId': network_interface_id, - 'InstanceId': instance_id, - 'DeviceIndex': device_index} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('AttachNetworkInterface', params, verb='POST') - - def detach_network_interface(self, attachment_id, force=False, - dry_run=False): - """ - Detaches a network interface from an instance. - - :type attachment_id: str - :param attachment_id: The ID of the attachment. - - :type force: bool - :param force: Set to true to force a detachment. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'AttachmentId': attachment_id} - if force: - params['Force'] = 'true' - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DetachNetworkInterface', params, verb='POST') - - def delete_network_interface(self, network_interface_id, dry_run=False): - """ - Delete the specified network interface. - - :type network_interface_id: str - :param network_interface_id: The ID of the network interface to delete. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'NetworkInterfaceId': network_interface_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteNetworkInterface', params, verb='POST') - - def get_all_instance_types(self): - """ - Get all instance_types available on this cloud (eucalyptus specific) - - :rtype: list of :class:`boto.ec2.instancetype.InstanceType` - :return: The requested InstanceType objects - """ - params = {} - return self.get_list('DescribeInstanceTypes', params, [('item', InstanceType)], verb='POST') - - def copy_image(self, source_region, source_image_id, name=None, - description=None, client_token=None, dry_run=False): - """ - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - :rtype: :class:`boto.ec2.image.CopyImage` - :return: Object containing the image_id of the copied image. - """ - params = { - 'SourceRegion': source_region, - 'SourceImageId': source_image_id, - } - if name is not None: - params['Name'] = name - if description is not None: - params['Description'] = description - if client_token is not None: - params['ClientToken'] = client_token - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CopyImage', params, CopyImage, - verb='POST') - - def describe_account_attributes(self, attribute_names=None, dry_run=False): - """ - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {} - if attribute_names is not None: - self.build_list_params(params, attribute_names, 'AttributeName') - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeAccountAttributes', params, - [('item', AccountAttribute)], verb='POST') - - def describe_vpc_attribute(self, vpc_id, attribute=None, dry_run=False): - """ - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = { - 'VpcId': vpc_id - } - if attribute is not None: - params['Attribute'] = attribute - if dry_run: - params['DryRun'] = 'true' - return self.get_object('DescribeVpcAttribute', params, - VPCAttribute, verb='POST') - - def modify_vpc_attribute(self, vpc_id, enable_dns_support=None, - enable_dns_hostnames=None, dry_run=False): - """ - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = { - 'VpcId': vpc_id - } - if enable_dns_support is not None: - params['EnableDnsSupport.Value'] = ( - 'true' if enable_dns_support else 'false') - if enable_dns_hostnames is not None: - params['EnableDnsHostnames.Value'] = ( - 'true' if enable_dns_hostnames else 'false') - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ModifyVpcAttribute', params, verb='POST') diff --git a/awx/lib/site-packages/boto/ec2/ec2object.py b/awx/lib/site-packages/boto/ec2/ec2object.py deleted file mode 100644 index fa50a9fcc7..0000000000 --- a/awx/lib/site-packages/boto/ec2/ec2object.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Object -""" -from boto.ec2.tag import TagSet - - -class EC2Object(object): - - def __init__(self, connection=None): - self.connection = connection - if self.connection and hasattr(self.connection, 'region'): - self.region = connection.region - else: - self.region = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - -class TaggedEC2Object(EC2Object): - """ - Any EC2 resource that can be tagged should be represented - by a Python object that subclasses this class. This class - has the mechanism in place to handle the tagSet element in - the Describe* responses. If tags are found, it will create - a TagSet object and allow it to parse and collect the tags - into a dict that is stored in the "tags" attribute of the - object. - """ - - def __init__(self, connection=None): - super(TaggedEC2Object, self).__init__(connection) - self.tags = TagSet() - - def startElement(self, name, attrs, connection): - if name == 'tagSet': - return self.tags - else: - return None - - def add_tag(self, key, value='', dry_run=False): - """ - Add a tag to this object. Tags are stored by AWS and can be used - to organize and filter resources. Adding a tag involves a round-trip - to the EC2 service. - - :type key: str - :param key: The key or name of the tag being stored. - - :type value: str - :param value: An optional value that can be stored with the tag. - If you want only the tag name and no value, the - value should be the empty string. - """ - self.add_tags({key: value}, dry_run) - - def add_tags(self, tags, dry_run=False): - """ - Add tags to this object. Tags are stored by AWS and can be used - to organize and filter resources. Adding tags involves a round-trip - to the EC2 service. - - :type tags: dict - :param tags: A dictionary of key-value pairs for the tags being stored. - If for some tags you want only the name and no value, the - corresponding value for that tag name should be an empty - string. - """ - status = self.connection.create_tags( - [self.id], - tags, - dry_run=dry_run - ) - if self.tags is None: - self.tags = TagSet() - self.tags.update(tags) - - def remove_tag(self, key, value=None, dry_run=False): - """ - Remove a tag from this object. Removing a tag involves a round-trip - to the EC2 service. - - :type key: str - :param key: The key or name of the tag being stored. - - :type value: str - :param value: An optional value that can be stored with the tag. - If a value is provided, it must match the value currently - stored in EC2. If not, the tag will not be removed. If - a value of None is provided, the tag will be - unconditionally deleted. - NOTE: There is an important distinction between a value - of '' and a value of None. - """ - self.remove_tags({key: value}, dry_run) - - def remove_tags(self, tags, dry_run=False): - """ - Removes tags from this object. Removing tags involves a round-trip - to the EC2 service. - - :type tags: dict - :param tags: A dictionary of key-value pairs for the tags being removed. - For each key, the provided value must match the value - currently stored in EC2. If not, that particular tag will - not be removed. However, if a value of None is provided, - the tag will be unconditionally deleted. - NOTE: There is an important distinction between a value of - '' and a value of None. - """ - status = self.connection.delete_tags( - [self.id], - tags, - dry_run=dry_run - ) - for key, value in tags.items(): - if key in self.tags: - if value is None or value == self.tags[key]: - del self.tags[key] diff --git a/awx/lib/site-packages/boto/ec2/elb/__init__.py b/awx/lib/site-packages/boto/ec2/elb/__init__.py deleted file mode 100644 index 6123909c6c..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/__init__.py +++ /dev/null @@ -1,758 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -""" -This module provides an interface to the Elastic Compute Cloud (EC2) -load balancing service from AWS. -""" -from boto.connection import AWSQueryConnection -from boto.ec2.instanceinfo import InstanceInfo -from boto.ec2.elb.loadbalancer import LoadBalancer, LoadBalancerZones -from boto.ec2.elb.instancestate import InstanceState -from boto.ec2.elb.healthcheck import HealthCheck -from boto.regioninfo import RegionInfo, get_regions, load_regions -import boto -from boto.compat import six - -RegionData = load_regions().get('elasticloadbalancing', {}) - - -def regions(): - """ - Get all available regions for the ELB service. - - :rtype: list - :return: A list of :class:`boto.RegionInfo` instances - """ - return get_regions('elasticloadbalancing', connection_cls=ELBConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.ec2.elb.ELBConnection`. - - :param str region_name: The name of the region to connect to. - - :rtype: :class:`boto.ec2.ELBConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None - - -class ELBConnection(AWSQueryConnection): - - APIVersion = boto.config.get('Boto', 'elb_version', '2012-06-01') - DefaultRegionName = boto.config.get('Boto', 'elb_region_name', 'us-east-1') - DefaultRegionEndpoint = boto.config.get( - 'Boto', 'elb_region_endpoint', - 'elasticloadbalancing.us-east-1.amazonaws.com') - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, profile_name=None): - """ - Init method to create a new connection to EC2 Load Balancing Service. - - .. note:: The region argument is overridden by the region specified in - the boto configuration file. - """ - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - super(ELBConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['ec2'] - - def build_list_params(self, params, items, label): - if isinstance(items, six.string_types): - items = [items] - for index, item in enumerate(items): - params[label % (index + 1)] = item - - def get_all_load_balancers(self, load_balancer_names=None, marker=None): - """ - Retrieve all load balancers associated with your account. - - :type load_balancer_names: list - :keyword load_balancer_names: An optional list of load balancer names. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :rtype: :py:class:`boto.resultset.ResultSet` - :return: A ResultSet containing instances of - :class:`boto.ec2.elb.loadbalancer.LoadBalancer` - """ - params = {} - if load_balancer_names: - self.build_list_params(params, load_balancer_names, - 'LoadBalancerNames.member.%d') - - if marker: - params['Marker'] = marker - - return self.get_list('DescribeLoadBalancers', params, - [('member', LoadBalancer)]) - - def create_load_balancer(self, name, zones, listeners=None, subnets=None, - security_groups=None, scheme='internet-facing', - complex_listeners=None): - """ - Create a new load balancer for your account. By default the load - balancer will be created in EC2. To create a load balancer inside a - VPC, parameter zones must be set to None and subnets must not be None. - The load balancer will be automatically created under the VPC that - contains the subnet(s) specified. - - :type name: string - :param name: The mnemonic name associated with the new load balancer - - :type zones: List of strings - :param zones: The names of the availability zone(s) to add. - - :type listeners: List of tuples - :param listeners: Each tuple contains three or four values, - (LoadBalancerPortNumber, InstancePortNumber, Protocol, - [SSLCertificateId]) where LoadBalancerPortNumber and - InstancePortNumber are integer values between 1 and 65535, - Protocol is a string containing either 'TCP', 'SSL', HTTP', or - 'HTTPS'; SSLCertificateID is the ARN of a AWS IAM - certificate, and must be specified when doing HTTPS. - - :type subnets: list of strings - :param subnets: A list of subnet IDs in your VPC to attach to - your LoadBalancer. - - :type security_groups: list of strings - :param security_groups: The security groups assigned to your - LoadBalancer within your VPC. - - :type scheme: string - :param scheme: The type of a LoadBalancer. By default, Elastic - Load Balancing creates an internet-facing LoadBalancer with - a publicly resolvable DNS name, which resolves to public IP - addresses. - - Specify the value internal for this option to create an - internal LoadBalancer with a DNS name that resolves to - private IP addresses. - - This option is only available for LoadBalancers attached - to an Amazon VPC. - - :type complex_listeners: List of tuples - :param complex_listeners: Each tuple contains four or five values, - (LoadBalancerPortNumber, InstancePortNumber, Protocol, - InstanceProtocol, SSLCertificateId). - - Where: - - LoadBalancerPortNumber and InstancePortNumber are integer - values between 1 and 65535 - - Protocol and InstanceProtocol is a string containing - either 'TCP', - 'SSL', 'HTTP', or 'HTTPS' - - SSLCertificateId is the ARN of an SSL certificate loaded into - AWS IAM - - :rtype: :class:`boto.ec2.elb.loadbalancer.LoadBalancer` - :return: The newly created - :class:`boto.ec2.elb.loadbalancer.LoadBalancer` - """ - if not listeners and not complex_listeners: - # Must specify one of the two options - return None - - params = {'LoadBalancerName': name, - 'Scheme': scheme} - - # Handle legacy listeners - if listeners: - for index, listener in enumerate(listeners): - i = index + 1 - protocol = listener[2].upper() - params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0] - params['Listeners.member.%d.InstancePort' % i] = listener[1] - params['Listeners.member.%d.Protocol' % i] = listener[2] - if protocol == 'HTTPS' or protocol == 'SSL': - params['Listeners.member.%d.SSLCertificateId' % i] = listener[3] - - # Handle the full listeners - if complex_listeners: - for index, listener in enumerate(complex_listeners): - i = index + 1 - protocol = listener[2].upper() - InstanceProtocol = listener[3].upper() - params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0] - params['Listeners.member.%d.InstancePort' % i] = listener[1] - params['Listeners.member.%d.Protocol' % i] = listener[2] - params['Listeners.member.%d.InstanceProtocol' % i] = listener[3] - if protocol == 'HTTPS' or protocol == 'SSL': - params['Listeners.member.%d.SSLCertificateId' % i] = listener[4] - - if zones: - self.build_list_params(params, zones, 'AvailabilityZones.member.%d') - - if subnets: - self.build_list_params(params, subnets, 'Subnets.member.%d') - - if security_groups: - self.build_list_params(params, security_groups, - 'SecurityGroups.member.%d') - - load_balancer = self.get_object('CreateLoadBalancer', - params, LoadBalancer) - load_balancer.name = name - load_balancer.listeners = listeners - load_balancer.availability_zones = zones - load_balancer.subnets = subnets - load_balancer.security_groups = security_groups - return load_balancer - - def create_load_balancer_listeners(self, name, listeners=None, - complex_listeners=None): - """ - Creates a Listener (or group of listeners) for an existing - Load Balancer - - :type name: string - :param name: The name of the load balancer to create the listeners for - - :type listeners: List of tuples - :param listeners: Each tuple contains three or four values, - (LoadBalancerPortNumber, InstancePortNumber, Protocol, - [SSLCertificateId]) where LoadBalancerPortNumber and - InstancePortNumber are integer values between 1 and 65535, - Protocol is a string containing either 'TCP', 'SSL', HTTP', or - 'HTTPS'; SSLCertificateID is the ARN of a AWS IAM - certificate, and must be specified when doing HTTPS. - - :type complex_listeners: List of tuples - :param complex_listeners: Each tuple contains four or five values, - (LoadBalancerPortNumber, InstancePortNumber, Protocol, - InstanceProtocol, SSLCertificateId). - - Where: - - LoadBalancerPortNumber and InstancePortNumber are integer - values between 1 and 65535 - - Protocol and InstanceProtocol is a string containing - either 'TCP', - 'SSL', 'HTTP', or 'HTTPS' - - SSLCertificateId is the ARN of an SSL certificate loaded into - AWS IAM - - :return: The status of the request - """ - if not listeners and not complex_listeners: - # Must specify one of the two options - return None - - params = {'LoadBalancerName': name} - - # Handle the simple listeners - if listeners: - for index, listener in enumerate(listeners): - i = index + 1 - protocol = listener[2].upper() - params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0] - params['Listeners.member.%d.InstancePort' % i] = listener[1] - params['Listeners.member.%d.Protocol' % i] = listener[2] - if protocol == 'HTTPS' or protocol == 'SSL': - params['Listeners.member.%d.SSLCertificateId' % i] = listener[3] - - # Handle the full listeners - if complex_listeners: - for index, listener in enumerate(complex_listeners): - i = index + 1 - protocol = listener[2].upper() - InstanceProtocol = listener[3].upper() - params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0] - params['Listeners.member.%d.InstancePort' % i] = listener[1] - params['Listeners.member.%d.Protocol' % i] = listener[2] - params['Listeners.member.%d.InstanceProtocol' % i] = listener[3] - if protocol == 'HTTPS' or protocol == 'SSL': - params['Listeners.member.%d.SSLCertificateId' % i] = listener[4] - - return self.get_status('CreateLoadBalancerListeners', params) - - def delete_load_balancer(self, name): - """ - Delete a Load Balancer from your account. - - :type name: string - :param name: The name of the Load Balancer to delete - """ - params = {'LoadBalancerName': name} - return self.get_status('DeleteLoadBalancer', params) - - def delete_load_balancer_listeners(self, name, ports): - """ - Deletes a load balancer listener (or group of listeners) - - :type name: string - :param name: The name of the load balancer to create the listeners for - - :type ports: List int - :param ports: Each int represents the port on the ELB to be removed - - :return: The status of the request - """ - params = {'LoadBalancerName': name} - for index, port in enumerate(ports): - params['LoadBalancerPorts.member.%d' % (index + 1)] = port - return self.get_status('DeleteLoadBalancerListeners', params) - - def enable_availability_zones(self, load_balancer_name, zones_to_add): - """ - Add availability zones to an existing Load Balancer - All zones must be in the same region as the Load Balancer - Adding zones that are already registered with the Load Balancer - has no effect. - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :type zones: List of strings - :param zones: The name of the zone(s) to add. - - :rtype: List of strings - :return: An updated list of zones for this Load Balancer. - - """ - params = {'LoadBalancerName': load_balancer_name} - self.build_list_params(params, zones_to_add, - 'AvailabilityZones.member.%d') - obj = self.get_object('EnableAvailabilityZonesForLoadBalancer', - params, LoadBalancerZones) - return obj.zones - - def disable_availability_zones(self, load_balancer_name, zones_to_remove): - """ - Remove availability zones from an existing Load Balancer. - All zones must be in the same region as the Load Balancer. - Removing zones that are not registered with the Load Balancer - has no effect. - You cannot remove all zones from an Load Balancer. - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :type zones: List of strings - :param zones: The name of the zone(s) to remove. - - :rtype: List of strings - :return: An updated list of zones for this Load Balancer. - - """ - params = {'LoadBalancerName': load_balancer_name} - self.build_list_params(params, zones_to_remove, - 'AvailabilityZones.member.%d') - obj = self.get_object('DisableAvailabilityZonesForLoadBalancer', - params, LoadBalancerZones) - return obj.zones - - def modify_lb_attribute(self, load_balancer_name, attribute, value): - """Changes an attribute of a Load Balancer - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :type attribute: string - :param attribute: The attribute you wish to change. - - * crossZoneLoadBalancing - Boolean (true) - * connectingSettings - :py:class:`ConnectionSettingAttribute` instance - * accessLog - :py:class:`AccessLogAttribute` instance - * connectionDraining - :py:class:`ConnectionDrainingAttribute` instance - - :type value: string - :param value: The new value for the attribute - - :rtype: bool - :return: Whether the operation succeeded or not - """ - - bool_reqs = ('crosszoneloadbalancing',) - if attribute.lower() in bool_reqs: - if isinstance(value, bool): - if value: - value = 'true' - else: - value = 'false' - - params = {'LoadBalancerName': load_balancer_name} - if attribute.lower() == 'crosszoneloadbalancing': - params['LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled' - ] = value - elif attribute.lower() == 'accesslog': - params['LoadBalancerAttributes.AccessLog.Enabled'] = \ - value.enabled and 'true' or 'false' - params['LoadBalancerAttributes.AccessLog.S3BucketName'] = \ - value.s3_bucket_name - params['LoadBalancerAttributes.AccessLog.S3BucketPrefix'] = \ - value.s3_bucket_prefix - params['LoadBalancerAttributes.AccessLog.EmitInterval'] = \ - value.emit_interval - elif attribute.lower() == 'connectiondraining': - params['LoadBalancerAttributes.ConnectionDraining.Enabled'] = \ - value.enabled and 'true' or 'false' - params['LoadBalancerAttributes.ConnectionDraining.Timeout'] = \ - value.timeout - elif attribute.lower() == 'connectingsettings': - params['LoadBalancerAttributes.ConnectionSettings.IdleTimeout'] = \ - value.idle_timeout - else: - raise ValueError('InvalidAttribute', attribute) - return self.get_status('ModifyLoadBalancerAttributes', params, - verb='GET') - - def get_all_lb_attributes(self, load_balancer_name): - """Gets all Attributes of a Load Balancer - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :rtype: boto.ec2.elb.attribute.LbAttributes - :return: The attribute object of the ELB. - """ - from boto.ec2.elb.attributes import LbAttributes - params = {'LoadBalancerName': load_balancer_name} - return self.get_object('DescribeLoadBalancerAttributes', - params, LbAttributes) - - def get_lb_attribute(self, load_balancer_name, attribute): - """Gets an attribute of a Load Balancer - - This will make an EC2 call for each method call. - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :type attribute: string - :param attribute: The attribute you wish to see. - - * accessLog - :py:class:`AccessLogAttribute` instance - * crossZoneLoadBalancing - Boolean - * connectingSettings - :py:class:`ConnectionSettingAttribute` instance - * connectionDraining - :py:class:`ConnectionDrainingAttribute` - instance - - :rtype: Attribute dependent - :return: The new value for the attribute - """ - attributes = self.get_all_lb_attributes(load_balancer_name) - if attribute.lower() == 'accesslog': - return attributes.access_log - if attribute.lower() == 'crosszoneloadbalancing': - return attributes.cross_zone_load_balancing.enabled - if attribute.lower() == 'connectiondraining': - return attributes.connection_draining - if attribute.lower() == 'connectingsettings': - return attributes.connecting_settings - return None - - def register_instances(self, load_balancer_name, instances): - """ - Add new Instances to an existing Load Balancer. - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :type instances: List of strings - :param instances: The instance ID's of the EC2 instances to add. - - :rtype: List of strings - :return: An updated list of instances for this Load Balancer. - - """ - params = {'LoadBalancerName': load_balancer_name} - self.build_list_params(params, instances, - 'Instances.member.%d.InstanceId') - return self.get_list('RegisterInstancesWithLoadBalancer', - params, [('member', InstanceInfo)]) - - def deregister_instances(self, load_balancer_name, instances): - """ - Remove Instances from an existing Load Balancer. - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :type instances: List of strings - :param instances: The instance ID's of the EC2 instances to remove. - - :rtype: List of strings - :return: An updated list of instances for this Load Balancer. - - """ - params = {'LoadBalancerName': load_balancer_name} - self.build_list_params(params, instances, - 'Instances.member.%d.InstanceId') - return self.get_list('DeregisterInstancesFromLoadBalancer', - params, [('member', InstanceInfo)]) - - def describe_instance_health(self, load_balancer_name, instances=None): - """ - Get current state of all Instances registered to an Load Balancer. - - :type load_balancer_name: string - :param load_balancer_name: The name of the Load Balancer - - :type instances: List of strings - :param instances: The instance ID's of the EC2 instances - to return status for. If not provided, - the state of all instances will be returned. - - :rtype: List of :class:`boto.ec2.elb.instancestate.InstanceState` - :return: list of state info for instances in this Load Balancer. - - """ - params = {'LoadBalancerName': load_balancer_name} - if instances: - self.build_list_params(params, instances, - 'Instances.member.%d.InstanceId') - return self.get_list('DescribeInstanceHealth', params, - [('member', InstanceState)]) - - def configure_health_check(self, name, health_check): - """ - Define a health check for the EndPoints. - - :type name: string - :param name: The mnemonic name associated with the load balancer - - :type health_check: :class:`boto.ec2.elb.healthcheck.HealthCheck` - :param health_check: A HealthCheck object populated with the desired - values. - - :rtype: :class:`boto.ec2.elb.healthcheck.HealthCheck` - :return: The updated :class:`boto.ec2.elb.healthcheck.HealthCheck` - """ - params = {'LoadBalancerName': name, - 'HealthCheck.Timeout': health_check.timeout, - 'HealthCheck.Target': health_check.target, - 'HealthCheck.Interval': health_check.interval, - 'HealthCheck.UnhealthyThreshold': health_check.unhealthy_threshold, - 'HealthCheck.HealthyThreshold': health_check.healthy_threshold} - return self.get_object('ConfigureHealthCheck', params, HealthCheck) - - def set_lb_listener_SSL_certificate(self, lb_name, lb_port, - ssl_certificate_id): - """ - Sets the certificate that terminates the specified listener's SSL - connections. The specified certificate replaces any prior certificate - that was used on the same LoadBalancer and port. - """ - params = {'LoadBalancerName': lb_name, - 'LoadBalancerPort': lb_port, - 'SSLCertificateId': ssl_certificate_id} - return self.get_status('SetLoadBalancerListenerSSLCertificate', params) - - def create_app_cookie_stickiness_policy(self, name, lb_name, policy_name): - """ - Generates a stickiness policy with sticky session lifetimes that follow - that of an application-generated cookie. This policy can only be - associated with HTTP listeners. - - This policy is similar to the policy created by - CreateLBCookieStickinessPolicy, except that the lifetime of the special - Elastic Load Balancing cookie follows the lifetime of the - application-generated cookie specified in the policy configuration. The - load balancer only inserts a new stickiness cookie when the application - response includes a new application cookie. - - If the application cookie is explicitly removed or expires, the session - stops being sticky until a new application cookie is issued. - """ - params = {'CookieName': name, - 'LoadBalancerName': lb_name, - 'PolicyName': policy_name} - return self.get_status('CreateAppCookieStickinessPolicy', params) - - def create_lb_cookie_stickiness_policy(self, cookie_expiration_period, - lb_name, policy_name): - """ - Generates a stickiness policy with sticky session lifetimes controlled - by the lifetime of the browser (user-agent) or a specified expiration - period. This policy can only be associated only with HTTP listeners. - - When a load balancer implements this policy, the load balancer uses a - special cookie to track the backend server instance for each request. - When the load balancer receives a request, it first checks to see if - this cookie is present in the request. If so, the load balancer sends - the request to the application server specified in the cookie. If not, - the load balancer sends the request to a server that is chosen based on - the existing load balancing algorithm. - - A cookie is inserted into the response for binding subsequent requests - from the same user to that server. The validity of the cookie is based - on the cookie expiration time, which is specified in the policy - configuration. - - None may be passed for cookie_expiration_period. - """ - params = {'LoadBalancerName': lb_name, - 'PolicyName': policy_name} - if cookie_expiration_period is not None: - params['CookieExpirationPeriod'] = cookie_expiration_period - return self.get_status('CreateLBCookieStickinessPolicy', params) - - def create_lb_policy(self, lb_name, policy_name, policy_type, - policy_attributes): - """ - Creates a new policy that contains the necessary attributes - depending on the policy type. Policies are settings that are - saved for your load balancer and that can be applied to the - front-end listener, or the back-end application server. - - """ - params = {'LoadBalancerName': lb_name, - 'PolicyName': policy_name, - 'PolicyTypeName': policy_type} - for index, (name, value) in enumerate(six.iteritems(policy_attributes), 1): - params['PolicyAttributes.member.%d.AttributeName' % index] = name - params['PolicyAttributes.member.%d.AttributeValue' % index] = value - else: - params['PolicyAttributes'] = '' - return self.get_status('CreateLoadBalancerPolicy', params) - - def delete_lb_policy(self, lb_name, policy_name): - """ - Deletes a policy from the LoadBalancer. The specified policy must not - be enabled for any listeners. - """ - params = {'LoadBalancerName': lb_name, - 'PolicyName': policy_name} - return self.get_status('DeleteLoadBalancerPolicy', params) - - def set_lb_policies_of_listener(self, lb_name, lb_port, policies): - """ - Associates, updates, or disables a policy with a listener on the load - balancer. Currently only zero (0) or one (1) policy can be associated - with a listener. - """ - params = {'LoadBalancerName': lb_name, - 'LoadBalancerPort': lb_port} - if len(policies): - self.build_list_params(params, policies, 'PolicyNames.member.%d') - else: - params['PolicyNames'] = '' - return self.get_status('SetLoadBalancerPoliciesOfListener', params) - - def set_lb_policies_of_backend_server(self, lb_name, instance_port, - policies): - """ - Replaces the current set of policies associated with a port on which - the back-end server is listening with a new set of policies. - """ - params = {'LoadBalancerName': lb_name, - 'InstancePort': instance_port} - if policies: - self.build_list_params(params, policies, 'PolicyNames.member.%d') - else: - params['PolicyNames'] = '' - return self.get_status('SetLoadBalancerPoliciesForBackendServer', - params) - - def apply_security_groups_to_lb(self, name, security_groups): - """ - Applies security groups to the load balancer. - Applying security groups that are already registered with the - Load Balancer has no effect. - - :type name: string - :param name: The name of the Load Balancer - - :type security_groups: List of strings - :param security_groups: The name of the security group(s) to add. - - :rtype: List of strings - :return: An updated list of security groups for this Load Balancer. - - """ - params = {'LoadBalancerName': name} - self.build_list_params(params, security_groups, - 'SecurityGroups.member.%d') - return self.get_list('ApplySecurityGroupsToLoadBalancer', - params, None) - - def attach_lb_to_subnets(self, name, subnets): - """ - Attaches load balancer to one or more subnets. - Attaching subnets that are already registered with the - Load Balancer has no effect. - - :type name: string - :param name: The name of the Load Balancer - - :type subnets: List of strings - :param subnets: The name of the subnet(s) to add. - - :rtype: List of strings - :return: An updated list of subnets for this Load Balancer. - - """ - params = {'LoadBalancerName': name} - self.build_list_params(params, subnets, - 'Subnets.member.%d') - return self.get_list('AttachLoadBalancerToSubnets', - params, None) - - def detach_lb_from_subnets(self, name, subnets): - """ - Detaches load balancer from one or more subnets. - - :type name: string - :param name: The name of the Load Balancer - - :type subnets: List of strings - :param subnets: The name of the subnet(s) to detach. - - :rtype: List of strings - :return: An updated list of subnets for this Load Balancer. - - """ - params = {'LoadBalancerName': name} - self.build_list_params(params, subnets, - 'Subnets.member.%d') - return self.get_list('DetachLoadBalancerFromSubnets', - params, None) diff --git a/awx/lib/site-packages/boto/ec2/elb/attributes.py b/awx/lib/site-packages/boto/ec2/elb/attributes.py deleted file mode 100644 index 605e5d54a7..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/attributes.py +++ /dev/null @@ -1,154 +0,0 @@ -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# Created by Chris Huegle for TellApart, Inc. - -class ConnectionSettingAttribute(object): - """ - Represents the ConnectionSetting segment of ELB Attributes. - """ - def __init__(self, connection=None): - self.idle_timeout = None - - def __repr__(self): - return 'ConnectionSettingAttribute(%s)' % ( - self.idle_timeout) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'IdleTimeout': - self.idle_timeout = int(value) - -class CrossZoneLoadBalancingAttribute(object): - """ - Represents the CrossZoneLoadBalancing segement of ELB Attributes. - """ - def __init__(self, connection=None): - self.enabled = None - - def __repr__(self): - return 'CrossZoneLoadBalancingAttribute(%s)' % ( - self.enabled) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Enabled': - if value.lower() == 'true': - self.enabled = True - else: - self.enabled = False - - -class AccessLogAttribute(object): - """ - Represents the AccessLog segment of ELB attributes. - """ - def __init__(self, connection=None): - self.enabled = None - self.s3_bucket_name = None - self.s3_bucket_prefix = None - self.emit_interval = None - - def __repr__(self): - return 'AccessLog(%s, %s, %s, %s)' % ( - self.enabled, - self.s3_bucket_name, - self.s3_bucket_prefix, - self.emit_interval - ) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Enabled': - if value.lower() == 'true': - self.enabled = True - else: - self.enabled = False - elif name == 'S3BucketName': - self.s3_bucket_name = value - elif name == 'S3BucketPrefix': - self.s3_bucket_prefix = value - elif name == 'EmitInterval': - self.emit_interval = int(value) - - -class ConnectionDrainingAttribute(object): - """ - Represents the ConnectionDraining segment of ELB attributes. - """ - def __init__(self, connection=None): - self.enabled = None - self.timeout = None - - def __repr__(self): - return 'ConnectionDraining(%s, %s)' % ( - self.enabled, - self.timeout - ) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Enabled': - if value.lower() == 'true': - self.enabled = True - else: - self.enabled = False - elif name == 'Timeout': - self.timeout = int(value) - - -class LbAttributes(object): - """ - Represents the Attributes of an Elastic Load Balancer. - """ - def __init__(self, connection=None): - self.connection = connection - self.cross_zone_load_balancing = CrossZoneLoadBalancingAttribute( - self.connection) - self.access_log = AccessLogAttribute(self.connection) - self.connection_draining = ConnectionDrainingAttribute(self.connection) - self.connecting_settings = ConnectionSettingAttribute(self.connection) - - def __repr__(self): - return 'LbAttributes(%s, %s, %s, %s)' % ( - repr(self.cross_zone_load_balancing), - repr(self.access_log), - repr(self.connection_draining), - repr(self.connecting_settings)) - - def startElement(self, name, attrs, connection): - if name == 'CrossZoneLoadBalancing': - return self.cross_zone_load_balancing - if name == 'AccessLog': - return self.access_log - if name == 'ConnectionDraining': - return self.connection_draining - if name == 'ConnectionSettings': - return self.connecting_settings - - def endElement(self, name, value, connection): - pass diff --git a/awx/lib/site-packages/boto/ec2/elb/healthcheck.py b/awx/lib/site-packages/boto/ec2/elb/healthcheck.py deleted file mode 100644 index 040f962300..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/healthcheck.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class HealthCheck(object): - """ - Represents an EC2 Access Point Health Check. See - :ref:`elb-configuring-a-health-check` for a walkthrough on configuring - load balancer health checks. - """ - def __init__(self, access_point=None, interval=30, target=None, - healthy_threshold=3, timeout=5, unhealthy_threshold=5): - """ - :ivar str access_point: The name of the load balancer this - health check is associated with. - :ivar int interval: Specifies how many seconds there are between - health checks. - :ivar str target: Determines what to check on an instance. See the - Amazon HealthCheck_ documentation for possible Target values. - - .. _HealthCheck: http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_HealthCheck.html - """ - self.access_point = access_point - self.interval = interval - self.target = target - self.healthy_threshold = healthy_threshold - self.timeout = timeout - self.unhealthy_threshold = unhealthy_threshold - - def __repr__(self): - return 'HealthCheck:%s' % self.target - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Interval': - self.interval = int(value) - elif name == 'Target': - self.target = value - elif name == 'HealthyThreshold': - self.healthy_threshold = int(value) - elif name == 'Timeout': - self.timeout = int(value) - elif name == 'UnhealthyThreshold': - self.unhealthy_threshold = int(value) - else: - setattr(self, name, value) - - def update(self): - """ - In the case where you have accessed an existing health check on a - load balancer, this method applies this instance's health check - values to the load balancer it is attached to. - - .. note:: This method will not do anything if the :py:attr:`access_point` - attribute isn't set, as is the case with a newly instantiated - HealthCheck instance. - """ - if not self.access_point: - return - - new_hc = self.connection.configure_health_check(self.access_point, - self) - self.interval = new_hc.interval - self.target = new_hc.target - self.healthy_threshold = new_hc.healthy_threshold - self.unhealthy_threshold = new_hc.unhealthy_threshold - self.timeout = new_hc.timeout diff --git a/awx/lib/site-packages/boto/ec2/elb/instancestate.py b/awx/lib/site-packages/boto/ec2/elb/instancestate.py deleted file mode 100644 index dd61c123ce..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/instancestate.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class InstanceState(object): - """ - Represents the state of an EC2 Load Balancer Instance - """ - - def __init__(self, load_balancer=None, description=None, - state=None, instance_id=None, reason_code=None): - """ - :ivar boto.ec2.elb.loadbalancer.LoadBalancer load_balancer: The - load balancer this instance is registered to. - :ivar str description: A description of the instance. - :ivar str instance_id: The EC2 instance ID. - :ivar str reason_code: Provides information about the cause of - an OutOfService instance. Specifically, it indicates whether the - cause is Elastic Load Balancing or the instance behind the - LoadBalancer. - :ivar str state: Specifies the current state of the instance. - """ - self.load_balancer = load_balancer - self.description = description - self.state = state - self.instance_id = instance_id - self.reason_code = reason_code - - def __repr__(self): - return 'InstanceState:(%s,%s)' % (self.instance_id, self.state) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Description': - self.description = value - elif name == 'State': - self.state = value - elif name == 'InstanceId': - self.instance_id = value - elif name == 'ReasonCode': - self.reason_code = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/elb/listelement.py b/awx/lib/site-packages/boto/ec2/elb/listelement.py deleted file mode 100644 index 0fe3a1e8eb..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/listelement.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class ListElement(list): - """ - A :py:class:`list` subclass that has some additional methods - for interacting with Amazon's XML API. - """ - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'member': - self.append(value) diff --git a/awx/lib/site-packages/boto/ec2/elb/listener.py b/awx/lib/site-packages/boto/ec2/elb/listener.py deleted file mode 100644 index ed33b131a6..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/listener.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.ec2.elb.listelement import ListElement - - -class Listener(object): - """ - Represents an EC2 Load Balancer Listener tuple - """ - - def __init__(self, load_balancer=None, load_balancer_port=0, - instance_port=0, protocol='', ssl_certificate_id=None, instance_protocol=None): - self.load_balancer = load_balancer - self.load_balancer_port = load_balancer_port - self.instance_port = instance_port - self.protocol = protocol - self.instance_protocol = instance_protocol - self.ssl_certificate_id = ssl_certificate_id - self.policy_names = ListElement() - - def __repr__(self): - r = "(%d, %d, '%s'" % (self.load_balancer_port, self.instance_port, self.protocol) - if self.instance_protocol: - r += ", '%s'" % self.instance_protocol - if self.ssl_certificate_id: - r += ', %s' % (self.ssl_certificate_id) - r += ')' - return r - - def startElement(self, name, attrs, connection): - if name == 'PolicyNames': - return self.policy_names - return None - - def endElement(self, name, value, connection): - if name == 'LoadBalancerPort': - self.load_balancer_port = int(value) - elif name == 'InstancePort': - self.instance_port = int(value) - elif name == 'InstanceProtocol': - self.instance_protocol = value - elif name == 'Protocol': - self.protocol = value - elif name == 'SSLCertificateId': - self.ssl_certificate_id = value - else: - setattr(self, name, value) - - def get_tuple(self): - return self.load_balancer_port, self.instance_port, self.protocol - - def get_complex_tuple(self): - return self.load_balancer_port, self.instance_port, self.protocol, self.instance_protocol - - def __getitem__(self, key): - if key == 0: - return self.load_balancer_port - if key == 1: - return self.instance_port - if key == 2: - return self.protocol - if key == 3: - return self.instance_protocol - if key == 4: - return self.ssl_certificate_id - raise KeyError diff --git a/awx/lib/site-packages/boto/ec2/elb/loadbalancer.py b/awx/lib/site-packages/boto/ec2/elb/loadbalancer.py deleted file mode 100644 index 3a065cf3a9..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/loadbalancer.py +++ /dev/null @@ -1,419 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.ec2.elb.healthcheck import HealthCheck -from boto.ec2.elb.listener import Listener -from boto.ec2.elb.listelement import ListElement -from boto.ec2.elb.policies import Policies, OtherPolicy -from boto.ec2.elb.securitygroup import SecurityGroup -from boto.ec2.instanceinfo import InstanceInfo -from boto.resultset import ResultSet -from boto.compat import six - - -class Backend(object): - """Backend server description""" - - def __init__(self, connection=None): - self.connection = connection - self.instance_port = None - self.policies = None - - def __repr__(self): - return 'Backend(%r:%r)' % (self.instance_port, self.policies) - - def startElement(self, name, attrs, connection): - if name == 'PolicyNames': - self.policies = ResultSet([('member', OtherPolicy)]) - return self.policies - - def endElement(self, name, value, connection): - if name == 'InstancePort': - self.instance_port = int(value) - return - - -class LoadBalancerZones(object): - """ - Used to collect the zones for a Load Balancer when enable_zones - or disable_zones are called. - """ - def __init__(self, connection=None): - self.connection = connection - self.zones = ListElement() - - def startElement(self, name, attrs, connection): - if name == 'AvailabilityZones': - return self.zones - - def endElement(self, name, value, connection): - pass - - -class LoadBalancer(object): - """ - Represents an EC2 Load Balancer. - """ - - def __init__(self, connection=None, name=None, endpoints=None): - """ - :ivar boto.ec2.elb.ELBConnection connection: The connection this load - balancer was instance was instantiated from. - :ivar list listeners: A list of tuples in the form of - ``(<Inbound port>, <Outbound port>, <Protocol>)`` - :ivar boto.ec2.elb.healthcheck.HealthCheck health_check: The health - check policy for this load balancer. - :ivar boto.ec2.elb.policies.Policies policies: Cookie stickiness and - other policies. - :ivar str name: The name of the Load Balancer. - :ivar str dns_name: The external DNS name for the balancer. - :ivar str created_time: A date+time string showing when the - load balancer was created. - :ivar list instances: A list of :py:class:`boto.ec2.instanceinfo.InstanceInfo` - instances, representing the EC2 instances this load balancer is - distributing requests to. - :ivar list availability_zones: The availability zones this balancer - covers. - :ivar str canonical_hosted_zone_name: Current CNAME for the balancer. - :ivar str canonical_hosted_zone_name_id: The Route 53 hosted zone - ID of this balancer. Needed when creating an Alias record in a - Route 53 hosted zone. - :ivar boto.ec2.elb.securitygroup.SecurityGroup source_security_group: - The security group that you can use as part of your inbound rules - for your load balancer back-end instances to disallow traffic - from sources other than your load balancer. - :ivar list subnets: A list of subnets this balancer is on. - :ivar list security_groups: A list of additional security groups that - have been applied. - :ivar str vpc_id: The ID of the VPC that this ELB resides within. - :ivar list backends: A list of :py:class:`boto.ec2.elb.loadbalancer.Backend - back-end server descriptions. - """ - self.connection = connection - self.name = name - self.listeners = None - self.health_check = None - self.policies = None - self.dns_name = None - self.created_time = None - self.instances = None - self.availability_zones = ListElement() - self.canonical_hosted_zone_name = None - self.canonical_hosted_zone_name_id = None - self.source_security_group = None - self.subnets = ListElement() - self.security_groups = ListElement() - self.vpc_id = None - self.scheme = None - self.backends = None - self._attributes = None - - def __repr__(self): - return 'LoadBalancer:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'HealthCheck': - self.health_check = HealthCheck(self) - return self.health_check - elif name == 'ListenerDescriptions': - self.listeners = ResultSet([('member', Listener)]) - return self.listeners - elif name == 'AvailabilityZones': - return self.availability_zones - elif name == 'Instances': - self.instances = ResultSet([('member', InstanceInfo)]) - return self.instances - elif name == 'Policies': - self.policies = Policies(self) - return self.policies - elif name == 'SourceSecurityGroup': - self.source_security_group = SecurityGroup() - return self.source_security_group - elif name == 'Subnets': - return self.subnets - elif name == 'SecurityGroups': - return self.security_groups - elif name == 'VPCId': - pass - elif name == "BackendServerDescriptions": - self.backends = ResultSet([('member', Backend)]) - return self.backends - else: - return None - - def endElement(self, name, value, connection): - if name == 'LoadBalancerName': - self.name = value - elif name == 'DNSName': - self.dns_name = value - elif name == 'CreatedTime': - self.created_time = value - elif name == 'InstanceId': - self.instances.append(value) - elif name == 'CanonicalHostedZoneName': - self.canonical_hosted_zone_name = value - elif name == 'CanonicalHostedZoneNameID': - self.canonical_hosted_zone_name_id = value - elif name == 'VPCId': - self.vpc_id = value - elif name == 'Scheme': - self.scheme = value - else: - setattr(self, name, value) - - def enable_zones(self, zones): - """ - Enable availability zones to this Access Point. - All zones must be in the same region as the Access Point. - - :type zones: string or List of strings - :param zones: The name of the zone(s) to add. - - """ - if isinstance(zones, six.string_types): - zones = [zones] - new_zones = self.connection.enable_availability_zones(self.name, zones) - self.availability_zones = new_zones - - def disable_zones(self, zones): - """ - Disable availability zones from this Access Point. - - :type zones: string or List of strings - :param zones: The name of the zone(s) to add. - - """ - if isinstance(zones, six.string_types): - zones = [zones] - new_zones = self.connection.disable_availability_zones( - self.name, zones) - self.availability_zones = new_zones - - def get_attributes(self, force=False): - """ - Gets the LbAttributes. The Attributes will be cached. - - :type force: bool - :param force: Ignore cache value and reload. - - :rtype: boto.ec2.elb.attributes.LbAttributes - :return: The LbAttribues object - """ - if not self._attributes or force: - self._attributes = self.connection.get_all_lb_attributes(self.name) - return self._attributes - - def is_cross_zone_load_balancing(self, force=False): - """ - Identifies if the ELB is current configured to do CrossZone Balancing. - - :type force: bool - :param force: Ignore cache value and reload. - - :rtype: bool - :return: True if balancing is enabled, False if not. - """ - return self.get_attributes(force).cross_zone_load_balancing.enabled - - def enable_cross_zone_load_balancing(self): - """ - Turns on CrossZone Load Balancing for this ELB. - - :rtype: bool - :return: True if successful, False if not. - """ - success = self.connection.modify_lb_attribute( - self.name, 'crossZoneLoadBalancing', True) - if success and self._attributes: - self._attributes.cross_zone_load_balancing.enabled = True - return success - - def disable_cross_zone_load_balancing(self): - """ - Turns off CrossZone Load Balancing for this ELB. - - :rtype: bool - :return: True if successful, False if not. - """ - success = self.connection.modify_lb_attribute( - self.name, 'crossZoneLoadBalancing', False) - if success and self._attributes: - self._attributes.cross_zone_load_balancing.enabled = False - return success - - def register_instances(self, instances): - """ - Adds instances to this load balancer. All instances must be in the same - region as the load balancer. Adding endpoints that are already - registered with the load balancer has no effect. - - :param list instances: List of instance IDs (strings) that you'd like - to add to this load balancer. - - """ - if isinstance(instances, six.string_types): - instances = [instances] - new_instances = self.connection.register_instances(self.name, - instances) - self.instances = new_instances - - def deregister_instances(self, instances): - """ - Remove instances from this load balancer. Removing instances that are - not registered with the load balancer has no effect. - - :param list instances: List of instance IDs (strings) that you'd like - to remove from this load balancer. - - """ - if isinstance(instances, six.string_types): - instances = [instances] - new_instances = self.connection.deregister_instances(self.name, - instances) - self.instances = new_instances - - def delete(self): - """ - Delete this load balancer. - """ - return self.connection.delete_load_balancer(self.name) - - def configure_health_check(self, health_check): - """ - Configures the health check behavior for the instances behind this - load balancer. See :ref:`elb-configuring-a-health-check` for a - walkthrough. - - :param boto.ec2.elb.healthcheck.HealthCheck health_check: A - HealthCheck instance that tells the load balancer how to check - its instances for health. - """ - return self.connection.configure_health_check(self.name, health_check) - - def get_instance_health(self, instances=None): - """ - Returns a list of :py:class:`boto.ec2.elb.instancestate.InstanceState` - objects, which show the health of the instances attached to this - load balancer. - - :rtype: list - :returns: A list of - :py:class:`InstanceState <boto.ec2.elb.instancestate.InstanceState>` - instances, representing the instances - attached to this load balancer. - """ - return self.connection.describe_instance_health(self.name, instances) - - def create_listeners(self, listeners): - return self.connection.create_load_balancer_listeners(self.name, - listeners) - - def create_listener(self, inPort, outPort=None, proto="tcp"): - if outPort is None: - outPort = inPort - return self.create_listeners([(inPort, outPort, proto)]) - - def delete_listeners(self, listeners): - return self.connection.delete_load_balancer_listeners(self.name, - listeners) - - def delete_listener(self, inPort): - return self.delete_listeners([inPort]) - - def delete_policy(self, policy_name): - """ - Deletes a policy from the LoadBalancer. The specified policy must not - be enabled for any listeners. - """ - return self.connection.delete_lb_policy(self.name, policy_name) - - def set_policies_of_listener(self, lb_port, policies): - return self.connection.set_lb_policies_of_listener(self.name, - lb_port, - policies) - - def set_policies_of_backend_server(self, instance_port, policies): - return self.connection.set_lb_policies_of_backend_server( - self.name, instance_port, policies) - - def create_cookie_stickiness_policy(self, cookie_expiration_period, - policy_name): - return self.connection.create_lb_cookie_stickiness_policy( - cookie_expiration_period, self.name, policy_name) - - def create_app_cookie_stickiness_policy(self, name, policy_name): - return self.connection.create_app_cookie_stickiness_policy(name, - self.name, - policy_name) - - def set_listener_SSL_certificate(self, lb_port, ssl_certificate_id): - return self.connection.set_lb_listener_SSL_certificate( - self.name, lb_port, ssl_certificate_id) - - def create_lb_policy(self, policy_name, policy_type, policy_attribute): - return self.connection.create_lb_policy( - self.name, policy_name, policy_type, policy_attribute) - - def attach_subnets(self, subnets): - """ - Attaches load balancer to one or more subnets. - Attaching subnets that are already registered with the - Load Balancer has no effect. - - :type subnets: string or List of strings - :param subnets: The name of the subnet(s) to add. - - """ - if isinstance(subnets, six.string_types): - subnets = [subnets] - new_subnets = self.connection.attach_lb_to_subnets(self.name, subnets) - self.subnets = new_subnets - - def detach_subnets(self, subnets): - """ - Detaches load balancer from one or more subnets. - - :type subnets: string or List of strings - :param subnets: The name of the subnet(s) to detach. - - """ - if isinstance(subnets, six.string_types): - subnets = [subnets] - new_subnets = self.connection.detach_lb_from_subnets( - self.name, subnets) - self.subnets = new_subnets - - def apply_security_groups(self, security_groups): - """ - Applies security groups to the load balancer. - Applying security groups that are already registered with the - Load Balancer has no effect. - - :type security_groups: string or List of strings - :param security_groups: The name of the security group(s) to add. - - """ - if isinstance(security_groups, six.string_types): - security_groups = [security_groups] - new_sgs = self.connection.apply_security_groups_to_lb( - self.name, security_groups) - self.security_groups = new_sgs diff --git a/awx/lib/site-packages/boto/ec2/elb/policies.py b/awx/lib/site-packages/boto/ec2/elb/policies.py deleted file mode 100644 index 50fac0aff9..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/policies.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright (c) 2010 Reza Lotun http://reza.lotun.name -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.resultset import ResultSet - - -class AppCookieStickinessPolicy(object): - def __init__(self, connection=None): - self.cookie_name = None - self.policy_name = None - - def __repr__(self): - return 'AppCookieStickiness(%s, %s)' % (self.policy_name, - self.cookie_name) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'CookieName': - self.cookie_name = value - elif name == 'PolicyName': - self.policy_name = value - - -class LBCookieStickinessPolicy(object): - def __init__(self, connection=None): - self.policy_name = None - self.cookie_expiration_period = None - - def __repr__(self): - return 'LBCookieStickiness(%s, %s)' % (self.policy_name, - self.cookie_expiration_period) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'CookieExpirationPeriod': - self.cookie_expiration_period = value - elif name == 'PolicyName': - self.policy_name = value - - -class OtherPolicy(object): - def __init__(self, connection=None): - self.policy_name = None - - def __repr__(self): - return 'OtherPolicy(%s)' % (self.policy_name) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - self.policy_name = value - - -class Policies(object): - """ - ELB Policies - """ - def __init__(self, connection=None): - self.connection = connection - self.app_cookie_stickiness_policies = None - self.lb_cookie_stickiness_policies = None - self.other_policies = None - - def __repr__(self): - app = 'AppCookieStickiness%s' % self.app_cookie_stickiness_policies - lb = 'LBCookieStickiness%s' % self.lb_cookie_stickiness_policies - other = 'Other%s' % self.other_policies - return 'Policies(%s,%s,%s)' % (app, lb, other) - - def startElement(self, name, attrs, connection): - if name == 'AppCookieStickinessPolicies': - rs = ResultSet([('member', AppCookieStickinessPolicy)]) - self.app_cookie_stickiness_policies = rs - return rs - elif name == 'LBCookieStickinessPolicies': - rs = ResultSet([('member', LBCookieStickinessPolicy)]) - self.lb_cookie_stickiness_policies = rs - return rs - elif name == 'OtherPolicies': - rs = ResultSet([('member', OtherPolicy)]) - self.other_policies = rs - return rs - - def endElement(self, name, value, connection): - return diff --git a/awx/lib/site-packages/boto/ec2/elb/securitygroup.py b/awx/lib/site-packages/boto/ec2/elb/securitygroup.py deleted file mode 100644 index 65f981f8e2..0000000000 --- a/awx/lib/site-packages/boto/ec2/elb/securitygroup.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2010 Reza Lotun http://reza.lotun.name -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class SecurityGroup(object): - def __init__(self, connection=None): - self.name = None - self.owner_alias = None - - def __repr__(self): - return 'SecurityGroup(%s, %s)' % (self.name, self.owner_alias) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'GroupName': - self.name = value - elif name == 'OwnerAlias': - self.owner_alias = value diff --git a/awx/lib/site-packages/boto/ec2/group.py b/awx/lib/site-packages/boto/ec2/group.py deleted file mode 100644 index 99d7873421..0000000000 --- a/awx/lib/site-packages/boto/ec2/group.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class Group(object): - def __init__(self, parent=None): - self.id = None - self.name = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'groupId': - self.id = value - elif name == 'groupName': - self.name = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/image.py b/awx/lib/site-packages/boto/ec2/image.py deleted file mode 100644 index 612404f07d..0000000000 --- a/awx/lib/site-packages/boto/ec2/image.py +++ /dev/null @@ -1,440 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.ec2.ec2object import EC2Object, TaggedEC2Object -from boto.ec2.blockdevicemapping import BlockDeviceMapping - - -class ProductCodes(list): - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'productCode': - self.append(value) - - -class BillingProducts(list): - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'billingProduct': - self.append(value) - - -class Image(TaggedEC2Object): - """ - Represents an EC2 Image - """ - - def __init__(self, connection=None): - super(Image, self).__init__(connection) - self.id = None - self.location = None - self.state = None - self.ownerId = None # for backwards compatibility - self.owner_id = None - self.owner_alias = None - self.is_public = False - self.architecture = None - self.platform = None - self.type = None - self.kernel_id = None - self.ramdisk_id = None - self.name = None - self.description = None - self.product_codes = ProductCodes() - self.billing_products = BillingProducts() - self.block_device_mapping = None - self.root_device_type = None - self.root_device_name = None - self.virtualization_type = None - self.hypervisor = None - self.instance_lifecycle = None - self.sriov_net_support = None - - def __repr__(self): - return 'Image:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(Image, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'blockDeviceMapping': - self.block_device_mapping = BlockDeviceMapping() - return self.block_device_mapping - elif name == 'productCodes': - return self.product_codes - elif name == 'billingProducts': - return self.billing_products - else: - return None - - def endElement(self, name, value, connection): - if name == 'imageId': - self.id = value - elif name == 'imageLocation': - self.location = value - elif name == 'imageState': - self.state = value - elif name == 'imageOwnerId': - self.ownerId = value # for backwards compatibility - self.owner_id = value - elif name == 'isPublic': - if value == 'false': - self.is_public = False - elif value == 'true': - self.is_public = True - else: - raise Exception( - 'Unexpected value of isPublic %s for image %s' % ( - value, - self.id - ) - ) - elif name == 'architecture': - self.architecture = value - elif name == 'imageType': - self.type = value - elif name == 'kernelId': - self.kernel_id = value - elif name == 'ramdiskId': - self.ramdisk_id = value - elif name == 'imageOwnerAlias': - self.owner_alias = value - elif name == 'platform': - self.platform = value - elif name == 'name': - self.name = value - elif name == 'description': - self.description = value - elif name == 'rootDeviceType': - self.root_device_type = value - elif name == 'rootDeviceName': - self.root_device_name = value - elif name == 'virtualizationType': - self.virtualization_type = value - elif name == 'hypervisor': - self.hypervisor = value - elif name == 'instanceLifecycle': - self.instance_lifecycle = value - elif name == 'sriovNetSupport': - self.sriov_net_support = value - else: - setattr(self, name, value) - - def _update(self, updated): - self.__dict__.update(updated.__dict__) - - def update(self, validate=False, dry_run=False): - """ - Update the image's state information by making a call to fetch - the current image attributes from the service. - - :type validate: bool - :param validate: By default, if EC2 returns no data about the - image the update method returns quietly. If - the validate param is True, however, it will - raise a ValueError exception if no data is - returned from EC2. - """ - rs = self.connection.get_all_images([self.id], dry_run=dry_run) - if len(rs) > 0: - img = rs[0] - if img.id == self.id: - self._update(img) - elif validate: - raise ValueError('%s is not a valid Image ID' % self.id) - return self.state - - def run(self, min_count=1, max_count=1, key_name=None, - security_groups=None, user_data=None, - addressing_type=None, instance_type='m1.small', placement=None, - kernel_id=None, ramdisk_id=None, - monitoring_enabled=False, subnet_id=None, - block_device_map=None, - disable_api_termination=False, - instance_initiated_shutdown_behavior=None, - private_ip_address=None, - placement_group=None, security_group_ids=None, - additional_info=None, instance_profile_name=None, - instance_profile_arn=None, tenancy=None, dry_run=False): - - """ - Runs this instance. - - :type min_count: int - :param min_count: The minimum number of instances to start - - :type max_count: int - :param max_count: The maximum number of instances to start - - :type key_name: string - :param key_name: The name of the key pair with which to - launch instances. - - :type security_groups: list of strings - :param security_groups: The names of the security groups with which to - associate instances. - - :type user_data: string - :param user_data: The Base64-encoded MIME user data to be made - available to the instance(s) in this reservation. - - :type instance_type: string - :param instance_type: The type of instance to run: - - * t1.micro - * m1.small - * m1.medium - * m1.large - * m1.xlarge - * m3.medium - * m3.large - * m3.xlarge - * m3.2xlarge - * c1.medium - * c1.xlarge - * m2.xlarge - * m2.2xlarge - * m2.4xlarge - * cr1.8xlarge - * hi1.4xlarge - * hs1.8xlarge - * cc1.4xlarge - * cg1.4xlarge - * cc2.8xlarge - * g2.2xlarge - * c3.large - * c3.xlarge - * c3.2xlarge - * c3.4xlarge - * c3.8xlarge - * i2.xlarge - * i2.2xlarge - * i2.4xlarge - * i2.8xlarge - * t2.micro - * t2.small - * t2.medium - - :type placement: string - :param placement: The Availability Zone to launch the instance into. - - :type kernel_id: string - :param kernel_id: The ID of the kernel with which to launch the - instances. - - :type ramdisk_id: string - :param ramdisk_id: The ID of the RAM disk with which to launch the - instances. - - :type monitoring_enabled: bool - :param monitoring_enabled: Enable CloudWatch monitoring on - the instance. - - :type subnet_id: string - :param subnet_id: The subnet ID within which to launch the instances - for VPC. - - :type private_ip_address: string - :param private_ip_address: If you're using VPC, you can - optionally use this parameter to assign the instance a - specific available IP address from the subnet (e.g., - 10.0.0.25). - - :type block_device_map: :class:`boto.ec2.blockdevicemapping.BlockDeviceMapping` - :param block_device_map: A BlockDeviceMapping data structure - describing the EBS volumes associated with the Image. - - :type disable_api_termination: bool - :param disable_api_termination: If True, the instances will be locked - and will not be able to be terminated via the API. - - :type instance_initiated_shutdown_behavior: string - :param instance_initiated_shutdown_behavior: Specifies whether the - instance stops or terminates on instance-initiated shutdown. - Valid values are: - - * stop - * terminate - - :type placement_group: string - :param placement_group: If specified, this is the name of the placement - group in which the instance(s) will be launched. - - :type additional_info: string - :param additional_info: Specifies additional information to make - available to the instance(s). - - :type security_group_ids: list of strings - :param security_group_ids: The ID of the VPC security groups with - which to associate instances. - - :type instance_profile_name: string - :param instance_profile_name: The name of - the IAM Instance Profile (IIP) to associate with the instances. - - :type instance_profile_arn: string - :param instance_profile_arn: The Amazon resource name (ARN) of - the IAM Instance Profile (IIP) to associate with the instances. - - :type tenancy: string - :param tenancy: The tenancy of the instance you want to - launch. An instance with a tenancy of 'dedicated' runs on - single-tenant hardware and can only be launched into a - VPC. Valid values are:"default" or "dedicated". - NOTE: To use dedicated tenancy you MUST specify a VPC - subnet-ID as well. - - :rtype: Reservation - :return: The :class:`boto.ec2.instance.Reservation` associated with - the request for machines - - """ - - return self.connection.run_instances(self.id, min_count, max_count, - key_name, security_groups, - user_data, addressing_type, - instance_type, placement, - kernel_id, ramdisk_id, - monitoring_enabled, subnet_id, - block_device_map, disable_api_termination, - instance_initiated_shutdown_behavior, - private_ip_address, placement_group, - security_group_ids=security_group_ids, - additional_info=additional_info, - instance_profile_name=instance_profile_name, - instance_profile_arn=instance_profile_arn, - tenancy=tenancy, dry_run=dry_run) - - def deregister(self, delete_snapshot=False, dry_run=False): - return self.connection.deregister_image( - self.id, - delete_snapshot, - dry_run=dry_run - ) - - def get_launch_permissions(self, dry_run=False): - img_attrs = self.connection.get_image_attribute( - self.id, - 'launchPermission', - dry_run=dry_run - ) - return img_attrs.attrs - - def set_launch_permissions(self, user_ids=None, group_names=None, - dry_run=False): - return self.connection.modify_image_attribute(self.id, - 'launchPermission', - 'add', - user_ids, - group_names, - dry_run=dry_run) - - def remove_launch_permissions(self, user_ids=None, group_names=None, - dry_run=False): - return self.connection.modify_image_attribute(self.id, - 'launchPermission', - 'remove', - user_ids, - group_names, - dry_run=dry_run) - - def reset_launch_attributes(self, dry_run=False): - return self.connection.reset_image_attribute( - self.id, - 'launchPermission', - dry_run=dry_run - ) - - def get_kernel(self, dry_run=False): - img_attrs = self.connection.get_image_attribute( - self.id, - 'kernel', - dry_run=dry_run - ) - return img_attrs.kernel - - def get_ramdisk(self, dry_run=False): - img_attrs = self.connection.get_image_attribute( - self.id, - 'ramdisk', - dry_run=dry_run - ) - return img_attrs.ramdisk - - -class ImageAttribute(object): - def __init__(self, parent=None): - self.name = None - self.kernel = None - self.ramdisk = None - self.attrs = {} - - def startElement(self, name, attrs, connection): - if name == 'blockDeviceMapping': - self.attrs['block_device_mapping'] = BlockDeviceMapping() - return self.attrs['block_device_mapping'] - else: - return None - - def endElement(self, name, value, connection): - if name == 'launchPermission': - self.name = 'launch_permission' - elif name == 'group': - if 'groups' in self.attrs: - self.attrs['groups'].append(value) - else: - self.attrs['groups'] = [value] - elif name == 'userId': - if 'user_ids' in self.attrs: - self.attrs['user_ids'].append(value) - else: - self.attrs['user_ids'] = [value] - elif name == 'productCode': - if 'product_codes' in self.attrs: - self.attrs['product_codes'].append(value) - else: - self.attrs['product_codes'] = [value] - elif name == 'imageId': - self.image_id = value - elif name == 'kernel': - self.kernel = value - elif name == 'ramdisk': - self.ramdisk = value - else: - setattr(self, name, value) - - -class CopyImage(object): - def __init__(self, parent=None): - self._parent = parent - self.image_id = None - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'imageId': - self.image_id = value diff --git a/awx/lib/site-packages/boto/ec2/instance.py b/awx/lib/site-packages/boto/ec2/instance.py deleted file mode 100644 index eb7c9ec615..0000000000 --- a/awx/lib/site-packages/boto/ec2/instance.py +++ /dev/null @@ -1,678 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Instance -""" -import boto -from boto.ec2.ec2object import EC2Object, TaggedEC2Object -from boto.resultset import ResultSet -from boto.ec2.address import Address -from boto.ec2.blockdevicemapping import BlockDeviceMapping -from boto.ec2.image import ProductCodes -from boto.ec2.networkinterface import NetworkInterface -from boto.ec2.group import Group -import base64 - - -class InstanceState(object): - """ - The state of the instance. - - :ivar code: The low byte represents the state. The high byte is an - opaque internal value and should be ignored. Valid values: - - * 0 (pending) - * 16 (running) - * 32 (shutting-down) - * 48 (terminated) - * 64 (stopping) - * 80 (stopped) - - :ivar name: The name of the state of the instance. Valid values: - - * "pending" - * "running" - * "shutting-down" - * "terminated" - * "stopping" - * "stopped" - """ - def __init__(self, code=0, name=None): - self.code = code - self.name = name - - def __repr__(self): - return '%s(%d)' % (self.name, self.code) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'code': - self.code = int(value) - elif name == 'name': - self.name = value - else: - setattr(self, name, value) - - -class InstancePlacement(object): - """ - The location where the instance launched. - - :ivar zone: The Availability Zone of the instance. - :ivar group_name: The name of the placement group the instance is - in (for cluster compute instances). - :ivar tenancy: The tenancy of the instance (if the instance is - running within a VPC). An instance with a tenancy of dedicated - runs on single-tenant hardware. - """ - def __init__(self, zone=None, group_name=None, tenancy=None): - self.zone = zone - self.group_name = group_name - self.tenancy = tenancy - - def __repr__(self): - return self.zone - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'availabilityZone': - self.zone = value - elif name == 'groupName': - self.group_name = value - elif name == 'tenancy': - self.tenancy = value - else: - setattr(self, name, value) - - -class Reservation(EC2Object): - """ - Represents a Reservation response object. - - :ivar id: The unique ID of the Reservation. - :ivar owner_id: The unique ID of the owner of the Reservation. - :ivar groups: A list of Group objects representing the security - groups associated with launched instances. - :ivar instances: A list of Instance objects launched in this - Reservation. - """ - def __init__(self, connection=None): - super(Reservation, self).__init__(connection) - self.id = None - self.owner_id = None - self.groups = [] - self.instances = [] - - def __repr__(self): - return 'Reservation:%s' % self.id - - def startElement(self, name, attrs, connection): - if name == 'instancesSet': - self.instances = ResultSet([('item', Instance)]) - return self.instances - elif name == 'groupSet': - self.groups = ResultSet([('item', Group)]) - return self.groups - else: - return None - - def endElement(self, name, value, connection): - if name == 'reservationId': - self.id = value - elif name == 'ownerId': - self.owner_id = value - else: - setattr(self, name, value) - - def stop_all(self, dry_run=False): - for instance in self.instances: - instance.stop(dry_run=dry_run) - - -class Instance(TaggedEC2Object): - """ - Represents an instance. - - :ivar id: The unique ID of the Instance. - :ivar groups: A list of Group objects representing the security - groups associated with the instance. - :ivar public_dns_name: The public dns name of the instance. - :ivar private_dns_name: The private dns name of the instance. - :ivar state: The string representation of the instance's current state. - :ivar state_code: An integer representation of the instance's - current state. - :ivar previous_state: The string representation of the instance's - previous state. - :ivar previous_state_code: An integer representation of the - instance's current state. - :ivar key_name: The name of the SSH key associated with the instance. - :ivar instance_type: The type of instance (e.g. m1.small). - :ivar launch_time: The time the instance was launched. - :ivar image_id: The ID of the AMI used to launch this instance. - :ivar placement: The availability zone in which the instance is running. - :ivar placement_group: The name of the placement group the instance - is in (for cluster compute instances). - :ivar placement_tenancy: The tenancy of the instance, if the instance - is running within a VPC. An instance with a tenancy of dedicated - runs on a single-tenant hardware. - :ivar kernel: The kernel associated with the instance. - :ivar ramdisk: The ramdisk associated with the instance. - :ivar architecture: The architecture of the image (i386|x86_64). - :ivar hypervisor: The hypervisor used. - :ivar virtualization_type: The type of virtualization used. - :ivar product_codes: A list of product codes associated with this instance. - :ivar ami_launch_index: This instances position within it's launch group. - :ivar monitored: A boolean indicating whether monitoring is enabled or not. - :ivar monitoring_state: A string value that contains the actual value - of the monitoring element returned by EC2. - :ivar spot_instance_request_id: The ID of the spot instance request - if this is a spot instance. - :ivar subnet_id: The VPC Subnet ID, if running in VPC. - :ivar vpc_id: The VPC ID, if running in VPC. - :ivar private_ip_address: The private IP address of the instance. - :ivar ip_address: The public IP address of the instance. - :ivar platform: Platform of the instance (e.g. Windows) - :ivar root_device_name: The name of the root device. - :ivar root_device_type: The root device type (ebs|instance-store). - :ivar block_device_mapping: The Block Device Mapping for the instance. - :ivar state_reason: The reason for the most recent state transition. - :ivar groups: List of security Groups associated with the instance. - :ivar interfaces: List of Elastic Network Interfaces associated with - this instance. - :ivar ebs_optimized: Whether instance is using optimized EBS volumes - or not. - :ivar instance_profile: A Python dict containing the instance - profile id and arn associated with this instance. - """ - - def __init__(self, connection=None): - super(Instance, self).__init__(connection) - self.id = None - self.dns_name = None - self.public_dns_name = None - self.private_dns_name = None - self.key_name = None - self.instance_type = None - self.launch_time = None - self.image_id = None - self.kernel = None - self.ramdisk = None - self.product_codes = ProductCodes() - self.ami_launch_index = None - self.monitored = False - self.monitoring_state = None - self.spot_instance_request_id = None - self.subnet_id = None - self.vpc_id = None - self.private_ip_address = None - self.ip_address = None - self.requester_id = None - self._in_monitoring_element = False - self.persistent = False - self.root_device_name = None - self.root_device_type = None - self.block_device_mapping = None - self.state_reason = None - self.group_name = None - self.client_token = None - self.eventsSet = None - self.groups = [] - self.platform = None - self.interfaces = [] - self.hypervisor = None - self.virtualization_type = None - self.architecture = None - self.instance_profile = None - self._previous_state = None - self._state = InstanceState() - self._placement = InstancePlacement() - - def __repr__(self): - return 'Instance:%s' % self.id - - @property - def state(self): - return self._state.name - - @property - def state_code(self): - return self._state.code - - @property - def previous_state(self): - if self._previous_state: - return self._previous_state.name - return None - - @property - def previous_state_code(self): - if self._previous_state: - return self._previous_state.code - return 0 - - @property - def placement(self): - return self._placement.zone - - @property - def placement_group(self): - return self._placement.group_name - - @property - def placement_tenancy(self): - return self._placement.tenancy - - def startElement(self, name, attrs, connection): - retval = super(Instance, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'monitoring': - self._in_monitoring_element = True - elif name == 'blockDeviceMapping': - self.block_device_mapping = BlockDeviceMapping() - return self.block_device_mapping - elif name == 'productCodes': - return self.product_codes - elif name == 'stateReason': - self.state_reason = SubParse('stateReason') - return self.state_reason - elif name == 'groupSet': - self.groups = ResultSet([('item', Group)]) - return self.groups - elif name == "eventsSet": - self.eventsSet = SubParse('eventsSet') - return self.eventsSet - elif name == 'networkInterfaceSet': - self.interfaces = ResultSet([('item', NetworkInterface)]) - return self.interfaces - elif name == 'iamInstanceProfile': - self.instance_profile = SubParse('iamInstanceProfile') - return self.instance_profile - elif name == 'currentState': - return self._state - elif name == 'previousState': - self._previous_state = InstanceState() - return self._previous_state - elif name == 'instanceState': - return self._state - elif name == 'placement': - return self._placement - return None - - def endElement(self, name, value, connection): - if name == 'instanceId': - self.id = value - elif name == 'imageId': - self.image_id = value - elif name == 'dnsName' or name == 'publicDnsName': - self.dns_name = value # backwards compatibility - self.public_dns_name = value - elif name == 'privateDnsName': - self.private_dns_name = value - elif name == 'keyName': - self.key_name = value - elif name == 'amiLaunchIndex': - self.ami_launch_index = value - elif name == 'previousState': - self.previous_state = value - elif name == 'instanceType': - self.instance_type = value - elif name == 'rootDeviceName': - self.root_device_name = value - elif name == 'rootDeviceType': - self.root_device_type = value - elif name == 'launchTime': - self.launch_time = value - elif name == 'platform': - self.platform = value - elif name == 'kernelId': - self.kernel = value - elif name == 'ramdiskId': - self.ramdisk = value - elif name == 'state': - if self._in_monitoring_element: - self.monitoring_state = value - if value == 'enabled': - self.monitored = True - self._in_monitoring_element = False - elif name == 'spotInstanceRequestId': - self.spot_instance_request_id = value - elif name == 'subnetId': - self.subnet_id = value - elif name == 'vpcId': - self.vpc_id = value - elif name == 'privateIpAddress': - self.private_ip_address = value - elif name == 'ipAddress': - self.ip_address = value - elif name == 'requesterId': - self.requester_id = value - elif name == 'persistent': - if value == 'true': - self.persistent = True - else: - self.persistent = False - elif name == 'groupName': - if self._in_monitoring_element: - self.group_name = value - elif name == 'clientToken': - self.client_token = value - elif name == "eventsSet": - self.events = value - elif name == 'hypervisor': - self.hypervisor = value - elif name == 'virtualizationType': - self.virtualization_type = value - elif name == 'architecture': - self.architecture = value - elif name == 'ebsOptimized': - self.ebs_optimized = (value == 'true') - else: - setattr(self, name, value) - - def _update(self, updated): - self.__dict__.update(updated.__dict__) - - def update(self, validate=False, dry_run=False): - """ - Update the instance's state information by making a call to fetch - the current instance attributes from the service. - - :type validate: bool - :param validate: By default, if EC2 returns no data about the - instance the update method returns quietly. If - the validate param is True, however, it will - raise a ValueError exception if no data is - returned from EC2. - """ - rs = self.connection.get_all_reservations([self.id], dry_run=dry_run) - if len(rs) > 0: - r = rs[0] - for i in r.instances: - if i.id == self.id: - self._update(i) - elif validate: - raise ValueError('%s is not a valid Instance ID' % self.id) - return self.state - - def terminate(self, dry_run=False): - """ - Terminate the instance - """ - rs = self.connection.terminate_instances([self.id], dry_run=dry_run) - if len(rs) > 0: - self._update(rs[0]) - - def stop(self, force=False, dry_run=False): - """ - Stop the instance - - :type force: bool - :param force: Forces the instance to stop - - :rtype: list - :return: A list of the instances stopped - """ - rs = self.connection.stop_instances([self.id], force, dry_run=dry_run) - if len(rs) > 0: - self._update(rs[0]) - - def start(self, dry_run=False): - """ - Start the instance. - """ - rs = self.connection.start_instances([self.id], dry_run=dry_run) - if len(rs) > 0: - self._update(rs[0]) - - def reboot(self, dry_run=False): - return self.connection.reboot_instances([self.id], dry_run=dry_run) - - def get_console_output(self, dry_run=False): - """ - Retrieves the console output for the instance. - - :rtype: :class:`boto.ec2.instance.ConsoleOutput` - :return: The console output as a ConsoleOutput object - """ - return self.connection.get_console_output(self.id, dry_run=dry_run) - - def confirm_product(self, product_code, dry_run=False): - return self.connection.confirm_product_instance( - self.id, - product_code, - dry_run=dry_run - ) - - def use_ip(self, ip_address, dry_run=False): - """ - Associates an Elastic IP to the instance. - - :type ip_address: Either an instance of - :class:`boto.ec2.address.Address` or a string. - :param ip_address: The IP address to associate - with the instance. - - :rtype: bool - :return: True if successful - """ - - if isinstance(ip_address, Address): - ip_address = ip_address.public_ip - return self.connection.associate_address( - self.id, - ip_address, - dry_run=dry_run - ) - - def monitor(self, dry_run=False): - return self.connection.monitor_instance(self.id, dry_run=dry_run) - - def unmonitor(self, dry_run=False): - return self.connection.unmonitor_instance(self.id, dry_run=dry_run) - - def get_attribute(self, attribute, dry_run=False): - """ - Gets an attribute from this instance. - - :type attribute: string - :param attribute: The attribute you need information about - Valid choices are: - - * instanceType - * kernel - * ramdisk - * userData - * disableApiTermination - * instanceInitiatedShutdownBehavior - * rootDeviceName - * blockDeviceMapping - * productCodes - * sourceDestCheck - * groupSet - * ebsOptimized - - :rtype: :class:`boto.ec2.image.InstanceAttribute` - :return: An InstanceAttribute object representing the value of the - attribute requested - """ - return self.connection.get_instance_attribute( - self.id, - attribute, - dry_run=dry_run - ) - - def modify_attribute(self, attribute, value, dry_run=False): - """ - Changes an attribute of this instance - - :type attribute: string - :param attribute: The attribute you wish to change. - - * instanceType - A valid instance type (m1.small) - * kernel - Kernel ID (None) - * ramdisk - Ramdisk ID (None) - * userData - Base64 encoded String (None) - * disableApiTermination - Boolean (true) - * instanceInitiatedShutdownBehavior - stop|terminate - * sourceDestCheck - Boolean (true) - * groupSet - Set of Security Groups or IDs - * ebsOptimized - Boolean (false) - - :type value: string - :param value: The new value for the attribute - - :rtype: bool - :return: Whether the operation succeeded or not - """ - return self.connection.modify_instance_attribute( - self.id, - attribute, - value, - dry_run=dry_run - ) - - def reset_attribute(self, attribute, dry_run=False): - """ - Resets an attribute of this instance to its default value. - - :type attribute: string - :param attribute: The attribute to reset. Valid values are: - kernel|ramdisk - - :rtype: bool - :return: Whether the operation succeeded or not - """ - return self.connection.reset_instance_attribute( - self.id, - attribute, - dry_run=dry_run - ) - - def create_image(self, name, description=None, no_reboot=False, - dry_run=False): - """ - Will create an AMI from the instance in the running or stopped - state. - - :type name: string - :param name: The name of the new image - - :type description: string - :param description: An optional human-readable string describing - the contents and purpose of the AMI. - - :type no_reboot: bool - :param no_reboot: An optional flag indicating that the bundling process - should not attempt to shutdown the instance before - bundling. If this flag is True, the responsibility - of maintaining file system integrity is left to the - owner of the instance. - - :rtype: string - :return: The new image id - """ - return self.connection.create_image( - self.id, - name, - description, - no_reboot, - dry_run=dry_run - ) - - -class ConsoleOutput(object): - def __init__(self, parent=None): - self.parent = parent - self.instance_id = None - self.timestamp = None - self.output = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'instanceId': - self.instance_id = value - elif name == 'timestamp': - self.timestamp = value - elif name == 'output': - self.output = base64.b64decode(value) - else: - setattr(self, name, value) - - -class InstanceAttribute(dict): - ValidValues = ['instanceType', 'kernel', 'ramdisk', 'userData', - 'disableApiTermination', - 'instanceInitiatedShutdownBehavior', - 'rootDeviceName', 'blockDeviceMapping', 'sourceDestCheck', - 'groupSet'] - - def __init__(self, parent=None): - dict.__init__(self) - self.instance_id = None - self.request_id = None - self._current_value = None - - def startElement(self, name, attrs, connection): - if name == 'blockDeviceMapping': - self[name] = BlockDeviceMapping() - return self[name] - elif name == 'groupSet': - self[name] = ResultSet([('item', Group)]) - return self[name] - else: - return None - - def endElement(self, name, value, connection): - if name == 'instanceId': - self.instance_id = value - elif name == 'requestId': - self.request_id = value - elif name == 'value': - if value == 'true': - value = True - elif value == 'false': - value = False - self._current_value = value - elif name in self.ValidValues: - self[name] = self._current_value - - -class SubParse(dict): - def __init__(self, section, parent=None): - dict.__init__(self) - self.section = section - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name != self.section: - self[name] = value diff --git a/awx/lib/site-packages/boto/ec2/instanceinfo.py b/awx/lib/site-packages/boto/ec2/instanceinfo.py deleted file mode 100644 index afa8b9cba0..0000000000 --- a/awx/lib/site-packages/boto/ec2/instanceinfo.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2006-2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class InstanceInfo(object): - """ - Represents an EC2 Instance status response from CloudWatch - """ - - def __init__(self, connection=None, id=None, state=None): - """ - :ivar str id: The instance's EC2 ID. - :ivar str state: Specifies the current status of the instance. - """ - self.connection = connection - self.id = id - self.state = state - - def __repr__(self): - return 'InstanceInfo:%s' % self.id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'instanceId' or name == 'InstanceId': - self.id = value - elif name == 'state': - self.state = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/instancestatus.py b/awx/lib/site-packages/boto/ec2/instancestatus.py deleted file mode 100644 index b09b55ee80..0000000000 --- a/awx/lib/site-packages/boto/ec2/instancestatus.py +++ /dev/null @@ -1,212 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class Details(dict): - """ - A dict object that contains name/value pairs which provide - more detailed information about the status of the system - or the instance. - """ - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'name': - self._name = value - elif name == 'status': - self[self._name] = value - else: - setattr(self, name, value) - - -class Event(object): - """ - A status event for an instance. - - :ivar code: A string indicating the event type. - :ivar description: A string describing the reason for the event. - :ivar not_before: A datestring describing the earliest time for - the event. - :ivar not_after: A datestring describing the latest time for - the event. - """ - - def __init__(self, code=None, description=None, - not_before=None, not_after=None): - self.code = code - self.description = description - self.not_before = not_before - self.not_after = not_after - - def __repr__(self): - return 'Event:%s' % self.code - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'code': - self.code = value - elif name == 'description': - self.description = value - elif name == 'notBefore': - self.not_before = value - elif name == 'notAfter': - self.not_after = value - else: - setattr(self, name, value) - - -class Status(object): - """ - A generic Status object used for system status and instance status. - - :ivar status: A string indicating overall status. - :ivar details: A dict containing name-value pairs which provide - more details about the current status. - """ - - def __init__(self, status=None, details=None): - self.status = status - if not details: - details = Details() - self.details = details - - def __repr__(self): - return 'Status:%s' % self.status - - def startElement(self, name, attrs, connection): - if name == 'details': - return self.details - return None - - def endElement(self, name, value, connection): - if name == 'status': - self.status = value - else: - setattr(self, name, value) - - -class EventSet(list): - - def startElement(self, name, attrs, connection): - if name == 'item': - event = Event() - self.append(event) - return event - else: - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - -class InstanceStatus(object): - """ - Represents an EC2 Instance status as reported by - DescribeInstanceStatus request. - - :ivar id: The instance identifier. - :ivar zone: The availability zone of the instance. - :ivar events: A list of events relevant to the instance. - :ivar state_code: An integer representing the current state - of the instance. - :ivar state_name: A string describing the current state - of the instance. - :ivar system_status: A Status object that reports impaired - functionality that stems from issues related to the systems - that support an instance, such as such as hardware failures - and network connectivity problems. - :ivar instance_status: A Status object that reports impaired - functionality that arises from problems internal to the instance. - """ - - def __init__(self, id=None, zone=None, events=None, - state_code=None, state_name=None): - self.id = id - self.zone = zone - self.events = events - self.state_code = state_code - self.state_name = state_name - self.system_status = Status() - self.instance_status = Status() - - def __repr__(self): - return 'InstanceStatus:%s' % self.id - - def startElement(self, name, attrs, connection): - if name == 'eventsSet': - self.events = EventSet() - return self.events - elif name == 'systemStatus': - return self.system_status - elif name == 'instanceStatus': - return self.instance_status - else: - return None - - def endElement(self, name, value, connection): - if name == 'instanceId': - self.id = value - elif name == 'availabilityZone': - self.zone = value - elif name == 'code': - self.state_code = int(value) - elif name == 'name': - self.state_name = value - else: - setattr(self, name, value) - - -class InstanceStatusSet(list): - """ - A list object that contains the results of a call to - DescribeInstanceStatus request. Each element of the - list will be an InstanceStatus object. - - :ivar next_token: If the response was truncated by - the EC2 service, the next_token attribute of the - object will contain the string that needs to be - passed in to the next request to retrieve the next - set of results. - """ - - def __init__(self, connection=None): - list.__init__(self) - self.connection = connection - self.next_token = None - - def startElement(self, name, attrs, connection): - if name == 'item': - status = InstanceStatus() - self.append(status) - return status - else: - return None - - def endElement(self, name, value, connection): - if name == 'nextToken': - self.next_token = value - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/instancetype.py b/awx/lib/site-packages/boto/ec2/instancetype.py deleted file mode 100644 index 6197a3363b..0000000000 --- a/awx/lib/site-packages/boto/ec2/instancetype.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -from boto.ec2.ec2object import EC2Object - - -class InstanceType(EC2Object): - """ - Represents an EC2 VM Type - - :ivar name: The name of the vm type - :ivar cores: The number of cpu cores for this vm type - :ivar memory: The amount of memory in megabytes for this vm type - :ivar disk: The amount of disk space in gigabytes for this vm type - """ - - def __init__(self, connection=None, name=None, cores=None, - memory=None, disk=None): - super(InstanceType, self).__init__(connection) - self.connection = connection - self.name = name - self.cores = cores - self.memory = memory - self.disk = disk - - def __repr__(self): - return 'InstanceType:%s-%s,%s,%s' % (self.name, self.cores, - self.memory, self.disk) - - def endElement(self, name, value, connection): - if name == 'name': - self.name = value - elif name == 'cpu': - self.cores = value - elif name == 'disk': - self.disk = value - elif name == 'memory': - self.memory = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/keypair.py b/awx/lib/site-packages/boto/ec2/keypair.py deleted file mode 100644 index 623fb409f8..0000000000 --- a/awx/lib/site-packages/boto/ec2/keypair.py +++ /dev/null @@ -1,111 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Keypair -""" - -import os -from boto.ec2.ec2object import EC2Object -from boto.exception import BotoClientError - - -class KeyPair(EC2Object): - - def __init__(self, connection=None): - super(KeyPair, self).__init__(connection) - self.name = None - self.fingerprint = None - self.material = None - - def __repr__(self): - return 'KeyPair:%s' % self.name - - def endElement(self, name, value, connection): - if name == 'keyName': - self.name = value - elif name == 'keyFingerprint': - self.fingerprint = value - elif name == 'keyMaterial': - self.material = value - else: - setattr(self, name, value) - - def delete(self, dry_run=False): - """ - Delete the KeyPair. - - :rtype: bool - :return: True if successful, otherwise False. - """ - return self.connection.delete_key_pair(self.name, dry_run=dry_run) - - def save(self, directory_path): - """ - Save the material (the unencrypted PEM encoded RSA private key) - of a newly created KeyPair to a local file. - - :type directory_path: string - :param directory_path: The fully qualified path to the directory - in which the keypair will be saved. The - keypair file will be named using the name - of the keypair as the base name and .pem - for the file extension. If a file of that - name already exists in the directory, an - exception will be raised and the old file - will not be overwritten. - - :rtype: bool - :return: True if successful. - """ - if self.material: - directory_path = os.path.expanduser(directory_path) - file_path = os.path.join(directory_path, '%s.pem' % self.name) - if os.path.exists(file_path): - raise BotoClientError('%s already exists, it will not be overwritten' % file_path) - fp = open(file_path, 'wb') - fp.write(self.material) - fp.close() - os.chmod(file_path, 0o600) - return True - else: - raise BotoClientError('KeyPair contains no material') - - def copy_to_region(self, region, dry_run=False): - """ - Create a new key pair of the same new in another region. - Note that the new key pair will use a different ssh - cert than the this key pair. After doing the copy, - you will need to save the material associated with the - new key pair (use the save method) to a local file. - - :type region: :class:`boto.ec2.regioninfo.RegionInfo` - :param region: The region to which this security group will be copied. - - :rtype: :class:`boto.ec2.keypair.KeyPair` - :return: The new key pair - """ - if region.name == self.region: - raise BotoClientError('Unable to copy to the same Region') - conn_params = self.connection.get_params() - rconn = region.connect(**conn_params) - kp = rconn.create_key_pair(self.name, dry_run=dry_run) - return kp diff --git a/awx/lib/site-packages/boto/ec2/launchspecification.py b/awx/lib/site-packages/boto/ec2/launchspecification.py deleted file mode 100644 index f145ac4799..0000000000 --- a/awx/lib/site-packages/boto/ec2/launchspecification.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a launch specification for Spot instances. -""" - -from boto.ec2.ec2object import EC2Object -from boto.resultset import ResultSet -from boto.ec2.blockdevicemapping import BlockDeviceMapping -from boto.ec2.group import Group -from boto.ec2.instance import SubParse - - -class GroupList(list): - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'groupId': - self.append(value) - - -class LaunchSpecification(EC2Object): - - def __init__(self, connection=None): - super(LaunchSpecification, self).__init__(connection) - self.key_name = None - self.instance_type = None - self.image_id = None - self.groups = [] - self.placement = None - self.kernel = None - self.ramdisk = None - self.monitored = False - self.subnet_id = None - self._in_monitoring_element = False - self.block_device_mapping = None - self.instance_profile = None - self.ebs_optimized = False - - def __repr__(self): - return 'LaunchSpecification(%s)' % self.image_id - - def startElement(self, name, attrs, connection): - if name == 'groupSet': - self.groups = ResultSet([('item', Group)]) - return self.groups - elif name == 'monitoring': - self._in_monitoring_element = True - elif name == 'blockDeviceMapping': - self.block_device_mapping = BlockDeviceMapping() - return self.block_device_mapping - elif name == 'iamInstanceProfile': - self.instance_profile = SubParse('iamInstanceProfile') - return self.instance_profile - else: - return None - - def endElement(self, name, value, connection): - if name == 'imageId': - self.image_id = value - elif name == 'keyName': - self.key_name = value - elif name == 'instanceType': - self.instance_type = value - elif name == 'availabilityZone': - self.placement = value - elif name == 'placement': - pass - elif name == 'kernelId': - self.kernel = value - elif name == 'ramdiskId': - self.ramdisk = value - elif name == 'subnetId': - self.subnet_id = value - elif name == 'state': - if self._in_monitoring_element: - if value == 'enabled': - self.monitored = True - self._in_monitoring_element = False - elif name == 'ebsOptimized': - self.ebs_optimized = (value == 'true') - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/networkinterface.py b/awx/lib/site-packages/boto/ec2/networkinterface.py deleted file mode 100644 index 9bbeb7715e..0000000000 --- a/awx/lib/site-packages/boto/ec2/networkinterface.py +++ /dev/null @@ -1,351 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Elastic Network Interface -""" -from boto.exception import BotoClientError -from boto.ec2.ec2object import TaggedEC2Object -from boto.resultset import ResultSet -from boto.ec2.group import Group - - -class Attachment(object): - """ - :ivar id: The ID of the attachment. - :ivar instance_id: The ID of the instance. - :ivar device_index: The index of this device. - :ivar status: The status of the device. - :ivar attach_time: The time the device was attached. - :ivar delete_on_termination: Whether the device will be deleted - when the instance is terminated. - """ - - def __init__(self): - self.id = None - self.instance_id = None - self.instance_owner_id = None - self.device_index = 0 - self.status = None - self.attach_time = None - self.delete_on_termination = False - - def __repr__(self): - return 'Attachment:%s' % self.id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'attachmentId': - self.id = value - elif name == 'instanceId': - self.instance_id = value - elif name == 'deviceIndex': - self.device_index = int(value) - elif name == 'instanceOwnerId': - self.instance_owner_id = value - elif name == 'status': - self.status = value - elif name == 'attachTime': - self.attach_time = value - elif name == 'deleteOnTermination': - if value.lower() == 'true': - self.delete_on_termination = True - else: - self.delete_on_termination = False - else: - setattr(self, name, value) - - -class NetworkInterface(TaggedEC2Object): - """ - An Elastic Network Interface. - - :ivar id: The ID of the ENI. - :ivar subnet_id: The ID of the VPC subnet. - :ivar vpc_id: The ID of the VPC. - :ivar description: The description. - :ivar owner_id: The ID of the owner of the ENI. - :ivar requester_managed: - :ivar status: The interface's status (available|in-use). - :ivar mac_address: The MAC address of the interface. - :ivar private_ip_address: The IP address of the interface within - the subnet. - :ivar source_dest_check: Flag to indicate whether to validate - network traffic to or from this network interface. - :ivar groups: List of security groups associated with the interface. - :ivar attachment: The attachment object. - :ivar private_ip_addresses: A list of PrivateIPAddress objects. - """ - - def __init__(self, connection=None): - super(NetworkInterface, self).__init__(connection) - self.id = None - self.subnet_id = None - self.vpc_id = None - self.availability_zone = None - self.description = None - self.owner_id = None - self.requester_managed = False - self.status = None - self.mac_address = None - self.private_ip_address = None - self.source_dest_check = None - self.groups = [] - self.attachment = None - self.private_ip_addresses = [] - - def __repr__(self): - return 'NetworkInterface:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(NetworkInterface, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'groupSet': - self.groups = ResultSet([('item', Group)]) - return self.groups - elif name == 'attachment': - self.attachment = Attachment() - return self.attachment - elif name == 'privateIpAddressesSet': - self.private_ip_addresses = ResultSet([('item', PrivateIPAddress)]) - return self.private_ip_addresses - else: - return None - - def endElement(self, name, value, connection): - if name == 'networkInterfaceId': - self.id = value - elif name == 'subnetId': - self.subnet_id = value - elif name == 'vpcId': - self.vpc_id = value - elif name == 'availabilityZone': - self.availability_zone = value - elif name == 'description': - self.description = value - elif name == 'ownerId': - self.owner_id = value - elif name == 'requesterManaged': - if value.lower() == 'true': - self.requester_managed = True - else: - self.requester_managed = False - elif name == 'status': - self.status = value - elif name == 'macAddress': - self.mac_address = value - elif name == 'privateIpAddress': - self.private_ip_address = value - elif name == 'sourceDestCheck': - if value.lower() == 'true': - self.source_dest_check = True - else: - self.source_dest_check = False - else: - setattr(self, name, value) - - def _update(self, updated): - self.__dict__.update(updated.__dict__) - - def update(self, validate=False, dry_run=False): - """ - Update the data associated with this ENI by querying EC2. - - :type validate: bool - :param validate: By default, if EC2 returns no data about the - ENI the update method returns quietly. If - the validate param is True, however, it will - raise a ValueError exception if no data is - returned from EC2. - """ - rs = self.connection.get_all_network_interfaces( - [self.id], - dry_run=dry_run - ) - if len(rs) > 0: - self._update(rs[0]) - elif validate: - raise ValueError('%s is not a valid ENI ID' % self.id) - return self.status - - def attach(self, instance_id, device_index, dry_run=False): - """ - Attach this ENI to an EC2 instance. - - :type instance_id: str - :param instance_id: The ID of the EC2 instance to which it will - be attached. - - :type device_index: int - :param device_index: The interface nunber, N, on the instance (eg. ethN) - - :rtype: bool - :return: True if successful - """ - return self.connection.attach_network_interface( - self.id, - instance_id, - device_index, - dry_run=dry_run - ) - - def detach(self, force=False, dry_run=False): - """ - Detach this ENI from an EC2 instance. - - :type force: bool - :param force: Forces detachment if the previous detachment - attempt did not occur cleanly. - - :rtype: bool - :return: True if successful - """ - attachment_id = getattr(self.attachment, 'id', None) - - return self.connection.detach_network_interface( - attachment_id, - force, - dry_run=dry_run - ) - - def delete(self, dry_run=False): - return self.connection.delete_network_interface( - self.id, - dry_run=dry_run - ) - - -class PrivateIPAddress(object): - def __init__(self, connection=None, private_ip_address=None, - primary=None): - self.connection = connection - self.private_ip_address = private_ip_address - self.primary = primary - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'privateIpAddress': - self.private_ip_address = value - elif name == 'primary': - self.primary = True if value.lower() == 'true' else False - - def __repr__(self): - return "PrivateIPAddress(%s, primary=%s)" % (self.private_ip_address, - self.primary) - - -class NetworkInterfaceCollection(list): - def __init__(self, *interfaces): - self.extend(interfaces) - - def build_list_params(self, params, prefix=''): - for i, spec in enumerate(self): - full_prefix = '%sNetworkInterface.%s.' % (prefix, i) - if spec.network_interface_id is not None: - params[full_prefix + 'NetworkInterfaceId'] = \ - str(spec.network_interface_id) - if spec.device_index is not None: - params[full_prefix + 'DeviceIndex'] = \ - str(spec.device_index) - else: - params[full_prefix + 'DeviceIndex'] = 0 - if spec.subnet_id is not None: - params[full_prefix + 'SubnetId'] = str(spec.subnet_id) - if spec.description is not None: - params[full_prefix + 'Description'] = str(spec.description) - if spec.delete_on_termination is not None: - params[full_prefix + 'DeleteOnTermination'] = \ - 'true' if spec.delete_on_termination else 'false' - if spec.secondary_private_ip_address_count is not None: - params[full_prefix + 'SecondaryPrivateIpAddressCount'] = \ - str(spec.secondary_private_ip_address_count) - if spec.private_ip_address is not None: - params[full_prefix + 'PrivateIpAddress'] = \ - str(spec.private_ip_address) - if spec.groups is not None: - for j, group_id in enumerate(spec.groups): - query_param_key = '%sSecurityGroupId.%s' % (full_prefix, j) - params[query_param_key] = str(group_id) - if spec.private_ip_addresses is not None: - for k, ip_addr in enumerate(spec.private_ip_addresses): - query_param_key_prefix = ( - '%sPrivateIpAddresses.%s' % (full_prefix, k)) - params[query_param_key_prefix + '.PrivateIpAddress'] = \ - str(ip_addr.private_ip_address) - if ip_addr.primary is not None: - params[query_param_key_prefix + '.Primary'] = \ - 'true' if ip_addr.primary else 'false' - - # Associating Public IPs have special logic around them: - # - # * Only assignable on an device_index of ``0`` - # * Only on one interface - # * Only if there are no other interfaces being created - # * Only if it's a new interface (which we can't really guard - # against) - # - # More details on http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html - if spec.associate_public_ip_address is not None: - if not params[full_prefix + 'DeviceIndex'] in (0, '0'): - raise BotoClientError( - "Only the interface with device index of 0 can " + \ - "be provided when using " + \ - "'associate_public_ip_address'." - ) - - if len(self) > 1: - raise BotoClientError( - "Only one interface can be provided when using " + \ - "'associate_public_ip_address'." - ) - - key = full_prefix + 'AssociatePublicIpAddress' - - if spec.associate_public_ip_address: - params[key] = 'true' - else: - params[key] = 'false' - - -class NetworkInterfaceSpecification(object): - def __init__(self, network_interface_id=None, device_index=None, - subnet_id=None, description=None, private_ip_address=None, - groups=None, delete_on_termination=None, - private_ip_addresses=None, - secondary_private_ip_address_count=None, - associate_public_ip_address=None): - self.network_interface_id = network_interface_id - self.device_index = device_index - self.subnet_id = subnet_id - self.description = description - self.private_ip_address = private_ip_address - self.groups = groups - self.delete_on_termination = delete_on_termination - self.private_ip_addresses = private_ip_addresses - self.secondary_private_ip_address_count = \ - secondary_private_ip_address_count - self.associate_public_ip_address = associate_public_ip_address diff --git a/awx/lib/site-packages/boto/ec2/placementgroup.py b/awx/lib/site-packages/boto/ec2/placementgroup.py deleted file mode 100644 index 0c2596616d..0000000000 --- a/awx/lib/site-packages/boto/ec2/placementgroup.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -""" -Represents an EC2 Placement Group -""" -from boto.ec2.ec2object import EC2Object -from boto.exception import BotoClientError - - -class PlacementGroup(EC2Object): - - def __init__(self, connection=None, name=None, strategy=None, state=None): - super(PlacementGroup, self).__init__(connection) - self.name = name - self.strategy = strategy - self.state = state - - def __repr__(self): - return 'PlacementGroup:%s' % self.name - - def endElement(self, name, value, connection): - if name == 'groupName': - self.name = value - elif name == 'strategy': - self.strategy = value - elif name == 'state': - self.state = value - else: - setattr(self, name, value) - - def delete(self, dry_run=False): - return self.connection.delete_placement_group( - self.name, - dry_run=dry_run - ) diff --git a/awx/lib/site-packages/boto/ec2/regioninfo.py b/awx/lib/site-packages/boto/ec2/regioninfo.py deleted file mode 100644 index 21a56fb927..0000000000 --- a/awx/lib/site-packages/boto/ec2/regioninfo.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.regioninfo import RegionInfo - - -class EC2RegionInfo(RegionInfo): - """ - Represents an EC2 Region - """ - - def __init__(self, connection=None, name=None, endpoint=None, - connection_cls=None): - from boto.ec2.connection import EC2Connection - super(EC2RegionInfo, self).__init__(connection, name, endpoint, - EC2Connection) diff --git a/awx/lib/site-packages/boto/ec2/reservedinstance.py b/awx/lib/site-packages/boto/ec2/reservedinstance.py deleted file mode 100644 index 02d152765d..0000000000 --- a/awx/lib/site-packages/boto/ec2/reservedinstance.py +++ /dev/null @@ -1,349 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from boto.resultset import ResultSet -from boto.ec2.ec2object import EC2Object -from boto.utils import parse_ts - - -class ReservedInstancesOffering(EC2Object): - - def __init__(self, connection=None, id=None, instance_type=None, - availability_zone=None, duration=None, fixed_price=None, - usage_price=None, description=None, instance_tenancy=None, - currency_code=None, offering_type=None, - recurring_charges=None, pricing_details=None): - super(ReservedInstancesOffering, self).__init__(connection) - self.id = id - self.instance_type = instance_type - self.availability_zone = availability_zone - self.duration = duration - self.fixed_price = fixed_price - self.usage_price = usage_price - self.description = description - self.instance_tenancy = instance_tenancy - self.currency_code = currency_code - self.offering_type = offering_type - self.recurring_charges = recurring_charges - self.pricing_details = pricing_details - - def __repr__(self): - return 'ReservedInstanceOffering:%s' % self.id - - def startElement(self, name, attrs, connection): - if name == 'recurringCharges': - self.recurring_charges = ResultSet([('item', RecurringCharge)]) - return self.recurring_charges - elif name == 'pricingDetailsSet': - self.pricing_details = ResultSet([('item', PricingDetail)]) - return self.pricing_details - return None - - def endElement(self, name, value, connection): - if name == 'reservedInstancesOfferingId': - self.id = value - elif name == 'instanceType': - self.instance_type = value - elif name == 'availabilityZone': - self.availability_zone = value - elif name == 'duration': - self.duration = int(value) - elif name == 'fixedPrice': - self.fixed_price = value - elif name == 'usagePrice': - self.usage_price = value - elif name == 'productDescription': - self.description = value - elif name == 'instanceTenancy': - self.instance_tenancy = value - elif name == 'currencyCode': - self.currency_code = value - elif name == 'offeringType': - self.offering_type = value - elif name == 'marketplace': - self.marketplace = True if value == 'true' else False - - def describe(self): - print('ID=%s' % self.id) - print('\tInstance Type=%s' % self.instance_type) - print('\tZone=%s' % self.availability_zone) - print('\tDuration=%s' % self.duration) - print('\tFixed Price=%s' % self.fixed_price) - print('\tUsage Price=%s' % self.usage_price) - print('\tDescription=%s' % self.description) - - def purchase(self, instance_count=1, dry_run=False): - return self.connection.purchase_reserved_instance_offering( - self.id, - instance_count, - dry_run=dry_run - ) - - -class RecurringCharge(object): - def __init__(self, connection=None, frequency=None, amount=None): - self.frequency = frequency - self.amount = amount - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - -class PricingDetail(object): - def __init__(self, connection=None, price=None, count=None): - self.price = price - self.count = count - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - -class ReservedInstance(ReservedInstancesOffering): - - def __init__(self, connection=None, id=None, instance_type=None, - availability_zone=None, duration=None, fixed_price=None, - usage_price=None, description=None, - instance_count=None, state=None): - super(ReservedInstance, self).__init__(connection, id, instance_type, - availability_zone, duration, - fixed_price, usage_price, - description) - self.instance_count = instance_count - self.state = state - self.start = None - - def __repr__(self): - return 'ReservedInstance:%s' % self.id - - def endElement(self, name, value, connection): - if name == 'reservedInstancesId': - self.id = value - if name == 'instanceCount': - self.instance_count = int(value) - elif name == 'state': - self.state = value - elif name == 'start': - self.start = value - else: - super(ReservedInstance, self).endElement(name, value, connection) - - -class ReservedInstanceListing(EC2Object): - def __init__(self, connection=None, listing_id=None, id=None, - create_date=None, update_date=None, - status=None, status_message=None, client_token=None): - self.connection = connection - self.listing_id = listing_id - self.id = id - self.create_date = create_date - self.update_date = update_date - self.status = status - self.status_message = status_message - self.client_token = client_token - - def startElement(self, name, attrs, connection): - if name == 'instanceCounts': - self.instance_counts = ResultSet([('item', InstanceCount)]) - return self.instance_counts - elif name == 'priceSchedules': - self.price_schedules = ResultSet([('item', PriceSchedule)]) - return self.price_schedules - return None - - def endElement(self, name, value, connection): - if name == 'reservedInstancesListingId': - self.listing_id = value - elif name == 'reservedInstancesId': - self.id = value - elif name == 'createDate': - self.create_date = value - elif name == 'updateDate': - self.update_date = value - elif name == 'status': - self.status = value - elif name == 'statusMessage': - self.status_message = value - else: - setattr(self, name, value) - - -class InstanceCount(object): - def __init__(self, connection=None, state=None, instance_count=None): - self.state = state - self.instance_count = instance_count - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'state': - self.state = value - elif name == 'instanceCount': - self.instance_count = int(value) - else: - setattr(self, name, value) - - -class PriceSchedule(object): - def __init__(self, connection=None, term=None, price=None, - currency_code=None, active=None): - self.connection = connection - self.term = term - self.price = price - self.currency_code = currency_code - self.active = active - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'term': - self.term = int(value) - elif name == 'price': - self.price = value - elif name == 'currencyCode': - self.currency_code = value - elif name == 'active': - self.active = True if value == 'true' else False - else: - setattr(self, name, value) - - -class ReservedInstancesConfiguration(object): - def __init__(self, connection=None, availability_zone=None, platform=None, - instance_count=None, instance_type=None): - self.connection = connection - self.availability_zone = availability_zone - self.platform = platform - self.instance_count = instance_count - self.instance_type = instance_type - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'availabilityZone': - self.availability_zone = value - elif name == 'platform': - self.platform = value - elif name == 'instanceCount': - self.instance_count = int(value) - elif name == 'instanceType': - self.instance_type = value - else: - setattr(self, name, value) - - -class ModifyReservedInstancesResult(object): - def __init__(self, connection=None, modification_id=None): - self.connection = connection - self.modification_id = modification_id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'reservedInstancesModificationId': - self.modification_id = value - else: - setattr(self, name, value) - - -class ModificationResult(object): - def __init__(self, connection=None, modification_id=None, - availability_zone=None, platform=None, instance_count=None, - instance_type=None): - self.connection = connection - self.modification_id = modification_id - self.availability_zone = availability_zone - self.platform = platform - self.instance_count = instance_count - self.instance_type = instance_type - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'reservedInstancesModificationId': - self.modification_id = value - elif name == 'availabilityZone': - self.availability_zone = value - elif name == 'platform': - self.platform = value - elif name == 'instanceCount': - self.instance_count = int(value) - elif name == 'instanceType': - self.instance_type = value - else: - setattr(self, name, value) - - -class ReservedInstancesModification(object): - def __init__(self, connection=None, modification_id=None, - reserved_instances=None, modification_results=None, - create_date=None, update_date=None, effective_date=None, - status=None, status_message=None, client_token=None): - self.connection = connection - self.modification_id = modification_id - self.reserved_instances = reserved_instances - self.modification_results = modification_results - self.create_date = create_date - self.update_date = update_date - self.effective_date = effective_date - self.status = status - self.status_message = status_message - self.client_token = client_token - - def startElement(self, name, attrs, connection): - if name == 'reservedInstancesSet': - self.reserved_instances = ResultSet([ - ('item', ReservedInstance) - ]) - return self.reserved_instances - elif name == 'modificationResultSet': - self.modification_results = ResultSet([ - ('item', ModificationResult) - ]) - return self.modification_results - return None - - def endElement(self, name, value, connection): - if name == 'reservedInstancesModificationId': - self.modification_id = value - elif name == 'createDate': - self.create_date = parse_ts(value) - elif name == 'updateDate': - self.update_date = parse_ts(value) - elif name == 'effectiveDate': - self.effective_date = parse_ts(value) - elif name == 'status': - self.status = value - elif name == 'statusMessage': - self.status_message = value - elif name == 'clientToken': - self.client_token = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/securitygroup.py b/awx/lib/site-packages/boto/ec2/securitygroup.py deleted file mode 100644 index dec49cb278..0000000000 --- a/awx/lib/site-packages/boto/ec2/securitygroup.py +++ /dev/null @@ -1,392 +0,0 @@ -# Copyright (c) 2006-2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Security Group -""" -from boto.ec2.ec2object import TaggedEC2Object -from boto.exception import BotoClientError - - -class SecurityGroup(TaggedEC2Object): - - def __init__(self, connection=None, owner_id=None, - name=None, description=None, id=None): - super(SecurityGroup, self).__init__(connection) - self.id = id - self.owner_id = owner_id - self.name = name - self.description = description - self.vpc_id = None - self.rules = IPPermissionsList() - self.rules_egress = IPPermissionsList() - - def __repr__(self): - return 'SecurityGroup:%s' % self.name - - def startElement(self, name, attrs, connection): - retval = super(SecurityGroup, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'ipPermissions': - return self.rules - elif name == 'ipPermissionsEgress': - return self.rules_egress - else: - return None - - def endElement(self, name, value, connection): - if name == 'ownerId': - self.owner_id = value - elif name == 'groupId': - self.id = value - elif name == 'groupName': - self.name = value - elif name == 'vpcId': - self.vpc_id = value - elif name == 'groupDescription': - self.description = value - elif name == 'ipRanges': - pass - elif name == 'return': - if value == 'false': - self.status = False - elif value == 'true': - self.status = True - else: - raise Exception( - 'Unexpected value of status %s for group %s' % ( - value, - self.name - ) - ) - else: - setattr(self, name, value) - - def delete(self, dry_run=False): - if self.vpc_id: - return self.connection.delete_security_group( - group_id=self.id, - dry_run=dry_run - ) - else: - return self.connection.delete_security_group( - self.name, - dry_run=dry_run - ) - - def add_rule(self, ip_protocol, from_port, to_port, - src_group_name, src_group_owner_id, cidr_ip, - src_group_group_id, dry_run=False): - """ - Add a rule to the SecurityGroup object. Note that this method - only changes the local version of the object. No information - is sent to EC2. - """ - rule = IPPermissions(self) - rule.ip_protocol = ip_protocol - rule.from_port = from_port - rule.to_port = to_port - self.rules.append(rule) - rule.add_grant( - src_group_name, - src_group_owner_id, - cidr_ip, - src_group_group_id, - dry_run=dry_run - ) - - def remove_rule(self, ip_protocol, from_port, to_port, - src_group_name, src_group_owner_id, cidr_ip, - src_group_group_id, dry_run=False): - """ - Remove a rule to the SecurityGroup object. Note that this method - only changes the local version of the object. No information - is sent to EC2. - """ - if not self.rules: - raise ValueError("The security group has no rules") - - target_rule = None - for rule in self.rules: - if rule.ip_protocol == ip_protocol: - if rule.from_port == from_port: - if rule.to_port == to_port: - target_rule = rule - target_grant = None - for grant in rule.grants: - if grant.name == src_group_name or grant.group_id == src_group_group_id: - if grant.owner_id == src_group_owner_id: - if grant.cidr_ip == cidr_ip: - target_grant = grant - if target_grant: - rule.grants.remove(target_grant) - if len(rule.grants) == 0: - self.rules.remove(target_rule) - - def authorize(self, ip_protocol=None, from_port=None, to_port=None, - cidr_ip=None, src_group=None, dry_run=False): - """ - Add a new rule to this security group. - You need to pass in either src_group_name - OR ip_protocol, from_port, to_port, - and cidr_ip. In other words, either you are authorizing another - group or you are authorizing some ip-based rule. - - :type ip_protocol: string - :param ip_protocol: Either tcp | udp | icmp - - :type from_port: int - :param from_port: The beginning port number you are enabling - - :type to_port: int - :param to_port: The ending port number you are enabling - - :type cidr_ip: string or list of strings - :param cidr_ip: The CIDR block you are providing access to. - See http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing - - :type src_group: :class:`boto.ec2.securitygroup.SecurityGroup` or - :class:`boto.ec2.securitygroup.GroupOrCIDR` - :param src_group: The Security Group you are granting access to. - - :rtype: bool - :return: True if successful. - """ - group_name = None - if not self.vpc_id: - group_name = self.name - group_id = None - if self.vpc_id: - group_id = self.id - src_group_name = None - src_group_owner_id = None - src_group_group_id = None - if src_group: - cidr_ip = None - src_group_owner_id = src_group.owner_id - if not self.vpc_id: - src_group_name = src_group.name - else: - if hasattr(src_group, 'group_id'): - src_group_group_id = src_group.group_id - else: - src_group_group_id = src_group.id - status = self.connection.authorize_security_group(group_name, - src_group_name, - src_group_owner_id, - ip_protocol, - from_port, - to_port, - cidr_ip, - group_id, - src_group_group_id, - dry_run=dry_run) - if status: - if not isinstance(cidr_ip, list): - cidr_ip = [cidr_ip] - for single_cidr_ip in cidr_ip: - self.add_rule(ip_protocol, from_port, to_port, src_group_name, - src_group_owner_id, single_cidr_ip, - src_group_group_id, dry_run=dry_run) - return status - - def revoke(self, ip_protocol=None, from_port=None, to_port=None, - cidr_ip=None, src_group=None, dry_run=False): - group_name = None - if not self.vpc_id: - group_name = self.name - group_id = None - if self.vpc_id: - group_id = self.id - src_group_name = None - src_group_owner_id = None - src_group_group_id = None - if src_group: - cidr_ip = None - src_group_owner_id = src_group.owner_id - if not self.vpc_id: - src_group_name = src_group.name - else: - if hasattr(src_group, 'group_id'): - src_group_group_id = src_group.group_id - else: - src_group_group_id = src_group.id - status = self.connection.revoke_security_group(group_name, - src_group_name, - src_group_owner_id, - ip_protocol, - from_port, - to_port, - cidr_ip, - group_id, - src_group_group_id, - dry_run=dry_run) - if status: - self.remove_rule(ip_protocol, from_port, to_port, src_group_name, - src_group_owner_id, cidr_ip, src_group_group_id, - dry_run=dry_run) - return status - - def copy_to_region(self, region, name=None, dry_run=False): - """ - Create a copy of this security group in another region. - Note that the new security group will be a separate entity - and will not stay in sync automatically after the copy - operation. - - :type region: :class:`boto.ec2.regioninfo.RegionInfo` - :param region: The region to which this security group will be copied. - - :type name: string - :param name: The name of the copy. If not supplied, the copy - will have the same name as this security group. - - :rtype: :class:`boto.ec2.securitygroup.SecurityGroup` - :return: The new security group. - """ - if region.name == self.region: - raise BotoClientError('Unable to copy to the same Region') - conn_params = self.connection.get_params() - rconn = region.connect(**conn_params) - sg = rconn.create_security_group( - name or self.name, - self.description, - dry_run=dry_run - ) - source_groups = [] - for rule in self.rules: - for grant in rule.grants: - grant_nom = grant.name or grant.group_id - if grant_nom: - if grant_nom not in source_groups: - source_groups.append(grant_nom) - sg.authorize(None, None, None, None, grant, - dry_run=dry_run) - else: - sg.authorize(rule.ip_protocol, rule.from_port, rule.to_port, - grant.cidr_ip, dry_run=dry_run) - return sg - - def instances(self, dry_run=False): - """ - Find all of the current instances that are running within this - security group. - - :rtype: list of :class:`boto.ec2.instance.Instance` - :return: A list of Instance objects - """ - rs = [] - if self.vpc_id: - rs.extend(self.connection.get_all_reservations( - filters={'instance.group-id': self.id}, - dry_run=dry_run - )) - else: - rs.extend(self.connection.get_all_reservations( - filters={'group-id': self.id}, - dry_run=dry_run - )) - instances = [i for r in rs for i in r.instances] - return instances - - -class IPPermissionsList(list): - - def startElement(self, name, attrs, connection): - if name == 'item': - self.append(IPPermissions(self)) - return self[-1] - return None - - def endElement(self, name, value, connection): - pass - - -class IPPermissions(object): - - def __init__(self, parent=None): - self.parent = parent - self.ip_protocol = None - self.from_port = None - self.to_port = None - self.grants = [] - - def __repr__(self): - return 'IPPermissions:%s(%s-%s)' % (self.ip_protocol, - self.from_port, self.to_port) - - def startElement(self, name, attrs, connection): - if name == 'item': - self.grants.append(GroupOrCIDR(self)) - return self.grants[-1] - return None - - def endElement(self, name, value, connection): - if name == 'ipProtocol': - self.ip_protocol = value - elif name == 'fromPort': - self.from_port = value - elif name == 'toPort': - self.to_port = value - else: - setattr(self, name, value) - - def add_grant(self, name=None, owner_id=None, cidr_ip=None, group_id=None, - dry_run=False): - grant = GroupOrCIDR(self) - grant.owner_id = owner_id - grant.group_id = group_id - grant.name = name - grant.cidr_ip = cidr_ip - self.grants.append(grant) - return grant - - -class GroupOrCIDR(object): - - def __init__(self, parent=None): - self.owner_id = None - self.group_id = None - self.name = None - self.cidr_ip = None - - def __repr__(self): - if self.cidr_ip: - return '%s' % self.cidr_ip - else: - return '%s-%s' % (self.name or self.group_id, self.owner_id) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'userId': - self.owner_id = value - elif name == 'groupId': - self.group_id = value - elif name == 'groupName': - self.name = value - if name == 'cidrIp': - self.cidr_ip = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/snapshot.py b/awx/lib/site-packages/boto/ec2/snapshot.py deleted file mode 100644 index 8a84cdee47..0000000000 --- a/awx/lib/site-packages/boto/ec2/snapshot.py +++ /dev/null @@ -1,187 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Elastic Block Store Snapshot -""" -from boto.ec2.ec2object import TaggedEC2Object -from boto.ec2.zone import Zone - - -class Snapshot(TaggedEC2Object): - AttrName = 'createVolumePermission' - - def __init__(self, connection=None): - super(Snapshot, self).__init__(connection) - self.id = None - self.volume_id = None - self.status = None - self.progress = None - self.start_time = None - self.owner_id = None - self.owner_alias = None - self.volume_size = None - self.description = None - self.encrypted = None - - def __repr__(self): - return 'Snapshot:%s' % self.id - - def endElement(self, name, value, connection): - if name == 'snapshotId': - self.id = value - elif name == 'volumeId': - self.volume_id = value - elif name == 'status': - self.status = value - elif name == 'startTime': - self.start_time = value - elif name == 'ownerId': - self.owner_id = value - elif name == 'ownerAlias': - self.owner_alias = value - elif name == 'volumeSize': - try: - self.volume_size = int(value) - except: - self.volume_size = value - elif name == 'description': - self.description = value - elif name == 'encrypted': - self.encrypted = (value.lower() == 'true') - else: - setattr(self, name, value) - - def _update(self, updated): - self.progress = updated.progress - self.status = updated.status - - def update(self, validate=False, dry_run=False): - """ - Update the data associated with this snapshot by querying EC2. - - :type validate: bool - :param validate: By default, if EC2 returns no data about the - snapshot the update method returns quietly. If - the validate param is True, however, it will - raise a ValueError exception if no data is - returned from EC2. - """ - rs = self.connection.get_all_snapshots([self.id], dry_run=dry_run) - if len(rs) > 0: - self._update(rs[0]) - elif validate: - raise ValueError('%s is not a valid Snapshot ID' % self.id) - return self.progress - - def delete(self, dry_run=False): - return self.connection.delete_snapshot(self.id, dry_run=dry_run) - - def get_permissions(self, dry_run=False): - attrs = self.connection.get_snapshot_attribute( - self.id, - self.AttrName, - dry_run=dry_run - ) - return attrs.attrs - - def share(self, user_ids=None, groups=None, dry_run=False): - return self.connection.modify_snapshot_attribute(self.id, - self.AttrName, - 'add', - user_ids, - groups, - dry_run=dry_run) - - def unshare(self, user_ids=None, groups=None, dry_run=False): - return self.connection.modify_snapshot_attribute(self.id, - self.AttrName, - 'remove', - user_ids, - groups, - dry_run=dry_run) - - def reset_permissions(self, dry_run=False): - return self.connection.reset_snapshot_attribute( - self.id, - self.AttrName, - dry_run=dry_run - ) - - def create_volume(self, zone, size=None, volume_type=None, iops=None, - dry_run=False): - """ - Create a new EBS Volume from this Snapshot - - :type zone: string or :class:`boto.ec2.zone.Zone` - :param zone: The availability zone in which the Volume will be created. - - :type size: int - :param size: The size of the new volume, in GiB. (optional). Defaults to - the size of the snapshot. - - :type volume_type: string - :param volume_type: The type of the volume. (optional). Valid - values are: standard | io1. - - :type iops: int - :param iops: The provisioned IOPs you want to associate with - this volume. (optional) - """ - if isinstance(zone, Zone): - zone = zone.name - return self.connection.create_volume( - size, - zone, - self.id, - volume_type, - iops, - self.encrypted, - dry_run=dry_run - ) - - -class SnapshotAttribute(object): - def __init__(self, parent=None): - self.snapshot_id = None - self.attrs = {} - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'createVolumePermission': - self.name = 'create_volume_permission' - elif name == 'group': - if 'groups' in self.attrs: - self.attrs['groups'].append(value) - else: - self.attrs['groups'] = [value] - elif name == 'userId': - if 'user_ids' in self.attrs: - self.attrs['user_ids'].append(value) - else: - self.attrs['user_ids'] = [value] - elif name == 'snapshotId': - self.snapshot_id = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/spotdatafeedsubscription.py b/awx/lib/site-packages/boto/ec2/spotdatafeedsubscription.py deleted file mode 100644 index d0e0be8d3c..0000000000 --- a/awx/lib/site-packages/boto/ec2/spotdatafeedsubscription.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Spot Instance Datafeed Subscription -""" -from boto.ec2.ec2object import EC2Object -from boto.ec2.spotinstancerequest import SpotInstanceStateFault - - -class SpotDatafeedSubscription(EC2Object): - - def __init__(self, connection=None, owner_id=None, - bucket=None, prefix=None, state=None, fault=None): - super(SpotDatafeedSubscription, self).__init__(connection) - self.owner_id = owner_id - self.bucket = bucket - self.prefix = prefix - self.state = state - self.fault = fault - - def __repr__(self): - return 'SpotDatafeedSubscription:%s' % self.bucket - - def startElement(self, name, attrs, connection): - if name == 'fault': - self.fault = SpotInstanceStateFault() - return self.fault - else: - return None - - def endElement(self, name, value, connection): - if name == 'ownerId': - self.owner_id = value - elif name == 'bucket': - self.bucket = value - elif name == 'prefix': - self.prefix = value - elif name == 'state': - self.state = value - else: - setattr(self, name, value) - - def delete(self, dry_run=False): - return self.connection.delete_spot_datafeed_subscription( - dry_run=dry_run - ) diff --git a/awx/lib/site-packages/boto/ec2/spotinstancerequest.py b/awx/lib/site-packages/boto/ec2/spotinstancerequest.py deleted file mode 100644 index da087fefdb..0000000000 --- a/awx/lib/site-packages/boto/ec2/spotinstancerequest.py +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Spot Instance Request -""" - -from boto.ec2.ec2object import TaggedEC2Object -from boto.ec2.launchspecification import LaunchSpecification - - -class SpotInstanceStateFault(object): - """ - The fault codes for the Spot Instance request, if any. - - :ivar code: The reason code for the Spot Instance state change. - :ivar message: The message for the Spot Instance state change. - """ - - def __init__(self, code=None, message=None): - self.code = code - self.message = message - - def __repr__(self): - return '(%s, %s)' % (self.code, self.message) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'code': - self.code = value - elif name == 'message': - self.message = value - setattr(self, name, value) - - -class SpotInstanceStatus(object): - """ - Contains the status of a Spot Instance Request. - - :ivar code: Status code of the request. - :ivar message: The description for the status code for the Spot request. - :ivar update_time: Time the status was stated. - """ - - def __init__(self, code=None, update_time=None, message=None): - self.code = code - self.update_time = update_time - self.message = message - - def __repr__(self): - return '<Status: %s>' % self.code - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'code': - self.code = value - elif name == 'message': - self.message = value - elif name == 'updateTime': - self.update_time = value - - -class SpotInstanceRequest(TaggedEC2Object): - """ - - :ivar id: The ID of the Spot Instance Request. - :ivar price: The maximum hourly price for any Spot Instance launched to - fulfill the request. - :ivar type: The Spot Instance request type. - :ivar state: The state of the Spot Instance request. - :ivar fault: The fault codes for the Spot Instance request, if any. - :ivar valid_from: The start date of the request. If this is a one-time - request, the request becomes active at this date and time and remains - active until all instances launch, the request expires, or the request is - canceled. If the request is persistent, the request becomes active at this - date and time and remains active until it expires or is canceled. - :ivar valid_until: The end date of the request. If this is a one-time - request, the request remains active until all instances launch, the request - is canceled, or this date is reached. If the request is persistent, it - remains active until it is canceled or this date is reached. - :ivar launch_group: The instance launch group. Launch groups are Spot - Instances that launch together and terminate together. - :ivar launched_availability_zone: foo - :ivar product_description: The Availability Zone in which the bid is - launched. - :ivar availability_zone_group: The Availability Zone group. If you specify - the same Availability Zone group for all Spot Instance requests, all Spot - Instances are launched in the same Availability Zone. - :ivar create_time: The time stamp when the Spot Instance request was - created. - :ivar launch_specification: Additional information for launching instances. - :ivar instance_id: The instance ID, if an instance has been launched to - fulfill the Spot Instance request. - :ivar status: The status code and status message describing the Spot - Instance request. - - """ - - def __init__(self, connection=None): - super(SpotInstanceRequest, self).__init__(connection) - self.id = None - self.price = None - self.type = None - self.state = None - self.fault = None - self.valid_from = None - self.valid_until = None - self.launch_group = None - self.launched_availability_zone = None - self.product_description = None - self.availability_zone_group = None - self.create_time = None - self.launch_specification = None - self.instance_id = None - self.status = None - - def __repr__(self): - return 'SpotInstanceRequest:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(SpotInstanceRequest, self).startElement(name, attrs, - connection) - if retval is not None: - return retval - if name == 'launchSpecification': - self.launch_specification = LaunchSpecification(connection) - return self.launch_specification - elif name == 'fault': - self.fault = SpotInstanceStateFault() - return self.fault - elif name == 'status': - self.status = SpotInstanceStatus() - return self.status - else: - return None - - def endElement(self, name, value, connection): - if name == 'spotInstanceRequestId': - self.id = value - elif name == 'spotPrice': - self.price = float(value) - elif name == 'type': - self.type = value - elif name == 'state': - self.state = value - elif name == 'validFrom': - self.valid_from = value - elif name == 'validUntil': - self.valid_until = value - elif name == 'launchGroup': - self.launch_group = value - elif name == 'availabilityZoneGroup': - self.availability_zone_group = value - elif name == 'launchedAvailabilityZone': - self.launched_availability_zone = value - elif name == 'instanceId': - self.instance_id = value - elif name == 'createTime': - self.create_time = value - elif name == 'productDescription': - self.product_description = value - else: - setattr(self, name, value) - - def cancel(self, dry_run=False): - self.connection.cancel_spot_instance_requests( - [self.id], - dry_run=dry_run - ) diff --git a/awx/lib/site-packages/boto/ec2/spotpricehistory.py b/awx/lib/site-packages/boto/ec2/spotpricehistory.py deleted file mode 100644 index ac125de683..0000000000 --- a/awx/lib/site-packages/boto/ec2/spotpricehistory.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Spot Instance Request -""" - -from boto.ec2.ec2object import EC2Object - - -class SpotPriceHistory(EC2Object): - - def __init__(self, connection=None): - super(SpotPriceHistory, self).__init__(connection) - self.price = 0.0 - self.instance_type = None - self.product_description = None - self.timestamp = None - self.availability_zone = None - - def __repr__(self): - return 'SpotPriceHistory(%s):%2f' % (self.instance_type, self.price) - - def endElement(self, name, value, connection): - if name == 'instanceType': - self.instance_type = value - elif name == 'spotPrice': - self.price = float(value) - elif name == 'productDescription': - self.product_description = value - elif name == 'timestamp': - self.timestamp = value - elif name == 'availabilityZone': - self.availability_zone = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/tag.py b/awx/lib/site-packages/boto/ec2/tag.py deleted file mode 100644 index deb2c78800..0000000000 --- a/awx/lib/site-packages/boto/ec2/tag.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class TagSet(dict): - """ - A TagSet is used to collect the tags associated with a particular - EC2 resource. Not all resources can be tagged but for those that - can, this dict object will be used to collect those values. See - :class:`boto.ec2.ec2object.TaggedEC2Object` for more details. - """ - - def __init__(self, connection=None): - self.connection = connection - self._current_key = None - self._current_value = None - - def startElement(self, name, attrs, connection): - if name == 'item': - self._current_key = None - self._current_value = None - return None - - def endElement(self, name, value, connection): - if name == 'key': - self._current_key = value - elif name == 'value': - self._current_value = value - elif name == 'item': - self[self._current_key] = self._current_value - - -class Tag(object): - """ - A Tag is used when creating or listing all tags related to - an AWS account. It records not only the key and value but - also the ID of the resource to which the tag is attached - as well as the type of the resource. - """ - - def __init__(self, connection=None, res_id=None, res_type=None, - name=None, value=None): - self.connection = connection - self.res_id = res_id - self.res_type = res_type - self.name = name - self.value = value - - def __repr__(self): - return 'Tag:%s' % self.name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'resourceId': - self.res_id = value - elif name == 'resourceType': - self.res_type = value - elif name == 'key': - self.name = value - elif name == 'value': - self.value = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/volume.py b/awx/lib/site-packages/boto/ec2/volume.py deleted file mode 100644 index c40062b37c..0000000000 --- a/awx/lib/site-packages/boto/ec2/volume.py +++ /dev/null @@ -1,315 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Elastic Block Storage Volume -""" -from boto.resultset import ResultSet -from boto.ec2.tag import Tag -from boto.ec2.ec2object import TaggedEC2Object - - -class Volume(TaggedEC2Object): - """ - Represents an EBS volume. - - :ivar id: The unique ID of the volume. - :ivar create_time: The timestamp of when the volume was created. - :ivar status: The status of the volume. - :ivar size: The size (in GB) of the volume. - :ivar snapshot_id: The ID of the snapshot this volume was created - from, if applicable. - :ivar attach_data: An AttachmentSet object. - :ivar zone: The availability zone this volume is in. - :ivar type: The type of volume (standard or consistent-iops) - :ivar iops: If this volume is of type consistent-iops, this is - the number of IOPS provisioned (10-300). - :ivar encrypted: True if this volume is encrypted. - """ - - def __init__(self, connection=None): - super(Volume, self).__init__(connection) - self.id = None - self.create_time = None - self.status = None - self.size = None - self.snapshot_id = None - self.attach_data = None - self.zone = None - self.type = None - self.iops = None - self.encrypted = None - - def __repr__(self): - return 'Volume:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(Volume, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'attachmentSet': - self.attach_data = AttachmentSet() - return self.attach_data - elif name == 'tagSet': - self.tags = ResultSet([('item', Tag)]) - return self.tags - else: - return None - - def endElement(self, name, value, connection): - if name == 'volumeId': - self.id = value - elif name == 'createTime': - self.create_time = value - elif name == 'status': - if value != '': - self.status = value - elif name == 'size': - self.size = int(value) - elif name == 'snapshotId': - self.snapshot_id = value - elif name == 'availabilityZone': - self.zone = value - elif name == 'volumeType': - self.type = value - elif name == 'iops': - self.iops = int(value) - elif name == 'encrypted': - self.encrypted = (value.lower() == 'true') - else: - setattr(self, name, value) - - def _update(self, updated): - self.__dict__.update(updated.__dict__) - - def update(self, validate=False, dry_run=False): - """ - Update the data associated with this volume by querying EC2. - - :type validate: bool - :param validate: By default, if EC2 returns no data about the - volume the update method returns quietly. If - the validate param is True, however, it will - raise a ValueError exception if no data is - returned from EC2. - """ - # Check the resultset since Eucalyptus ignores the volumeId param - unfiltered_rs = self.connection.get_all_volumes( - [self.id], - dry_run=dry_run - ) - rs = [x for x in unfiltered_rs if x.id == self.id] - if len(rs) > 0: - self._update(rs[0]) - elif validate: - raise ValueError('%s is not a valid Volume ID' % self.id) - return self.status - - def delete(self, dry_run=False): - """ - Delete this EBS volume. - - :rtype: bool - :return: True if successful - """ - return self.connection.delete_volume(self.id, dry_run=dry_run) - - def attach(self, instance_id, device, dry_run=False): - """ - Attach this EBS volume to an EC2 instance. - - :type instance_id: str - :param instance_id: The ID of the EC2 instance to which it will - be attached. - - :type device: str - :param device: The device on the instance through which the - volume will be exposed (e.g. /dev/sdh) - - :rtype: bool - :return: True if successful - """ - return self.connection.attach_volume( - self.id, - instance_id, - device, - dry_run=dry_run - ) - - def detach(self, force=False, dry_run=False): - """ - Detach this EBS volume from an EC2 instance. - - :type force: bool - :param force: Forces detachment if the previous detachment - attempt did not occur cleanly. This option can lead to - data loss or a corrupted file system. Use this option only - as a last resort to detach a volume from a failed - instance. The instance will not have an opportunity to - flush file system caches nor file system meta data. If you - use this option, you must perform file system check and - repair procedures. - - :rtype: bool - :return: True if successful - """ - instance_id = None - if self.attach_data: - instance_id = self.attach_data.instance_id - device = None - if self.attach_data: - device = self.attach_data.device - return self.connection.detach_volume( - self.id, - instance_id, - device, - force, - dry_run=dry_run - ) - - def create_snapshot(self, description=None, dry_run=False): - """ - Create a snapshot of this EBS Volume. - - :type description: str - :param description: A description of the snapshot. - Limited to 256 characters. - - :rtype: :class:`boto.ec2.snapshot.Snapshot` - :return: The created Snapshot object - """ - return self.connection.create_snapshot( - self.id, - description, - dry_run=dry_run - ) - - def volume_state(self): - """ - Returns the state of the volume. Same value as the status attribute. - """ - return self.status - - def attachment_state(self): - """ - Get the attachment state. - """ - state = None - if self.attach_data: - state = self.attach_data.status - return state - - def snapshots(self, owner=None, restorable_by=None, dry_run=False): - """ - Get all snapshots related to this volume. Note that this requires - that all available snapshots for the account be retrieved from EC2 - first and then the list is filtered client-side to contain only - those for this volume. - - :type owner: str - :param owner: If present, only the snapshots owned by the - specified user will be returned. Valid values are: - - * self - * amazon - * AWS Account ID - - :type restorable_by: str - :param restorable_by: If present, only the snapshots that - are restorable by the specified account id will be returned. - - :rtype: list of L{boto.ec2.snapshot.Snapshot} - :return: The requested Snapshot objects - - """ - rs = self.connection.get_all_snapshots( - owner=owner, - restorable_by=restorable_by, - dry_run=dry_run - ) - mine = [] - for snap in rs: - if snap.volume_id == self.id: - mine.append(snap) - return mine - - -class AttachmentSet(object): - """ - Represents an EBS attachmentset. - - :ivar id: The unique ID of the volume. - :ivar instance_id: The unique ID of the attached instance - :ivar status: The status of the attachment - :ivar attach_time: Attached since - :ivar device: The device the instance has mapped - """ - def __init__(self): - self.id = None - self.instance_id = None - self.status = None - self.attach_time = None - self.device = None - - def __repr__(self): - return 'AttachmentSet:%s' % self.id - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'volumeId': - self.id = value - elif name == 'instanceId': - self.instance_id = value - elif name == 'status': - self.status = value - elif name == 'attachTime': - self.attach_time = value - elif name == 'device': - self.device = value - else: - setattr(self, name, value) - - -class VolumeAttribute(object): - def __init__(self, parent=None): - self.id = None - self._key_name = None - self.attrs = {} - - def startElement(self, name, attrs, connection): - if name == 'autoEnableIO': - self._key_name = name - return None - - def endElement(self, name, value, connection): - if name == 'value': - if value.lower() == 'true': - self.attrs[self._key_name] = True - else: - self.attrs[self._key_name] = False - elif name == 'volumeId': - self.id = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/volumestatus.py b/awx/lib/site-packages/boto/ec2/volumestatus.py deleted file mode 100644 index 78de2bb04f..0000000000 --- a/awx/lib/site-packages/boto/ec2/volumestatus.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.ec2.instancestatus import Status, Details - - -class Event(object): - """ - A status event for an instance. - - :ivar type: The type of the event. - :ivar id: The ID of the event. - :ivar description: A string describing the reason for the event. - :ivar not_before: A datestring describing the earliest time for - the event. - :ivar not_after: A datestring describing the latest time for - the event. - """ - - def __init__(self, type=None, id=None, description=None, - not_before=None, not_after=None): - self.type = type - self.id = id - self.description = description - self.not_before = not_before - self.not_after = not_after - - def __repr__(self): - return 'Event:%s' % self.type - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'eventType': - self.type = value - elif name == 'eventId': - self.id = value - elif name == 'description': - self.description = value - elif name == 'notBefore': - self.not_before = value - elif name == 'notAfter': - self.not_after = value - else: - setattr(self, name, value) - - -class EventSet(list): - - def startElement(self, name, attrs, connection): - if name == 'item': - event = Event() - self.append(event) - return event - else: - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - -class Action(object): - """ - An action for an instance. - - :ivar code: The code for the type of the action. - :ivar id: The ID of the event. - :ivar type: The type of the event. - :ivar description: A description of the action. - """ - - def __init__(self, code=None, id=None, description=None, type=None): - self.code = code - self.id = id - self.type = type - self.description = description - - def __repr__(self): - return 'Action:%s' % self.code - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'eventType': - self.type = value - elif name == 'eventId': - self.id = value - elif name == 'description': - self.description = value - elif name == 'code': - self.code = value - else: - setattr(self, name, value) - - -class ActionSet(list): - - def startElement(self, name, attrs, connection): - if name == 'item': - action = Action() - self.append(action) - return action - else: - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - -class VolumeStatus(object): - """ - Represents an EC2 Volume status as reported by - DescribeVolumeStatus request. - - :ivar id: The volume identifier. - :ivar zone: The availability zone of the volume - :ivar volume_status: A Status object that reports impaired - functionality that arises from problems internal to the instance. - :ivar events: A list of events relevant to the instance. - :ivar actions: A list of events relevant to the instance. - """ - - def __init__(self, id=None, zone=None): - self.id = id - self.zone = zone - self.volume_status = Status() - self.events = None - self.actions = None - - def __repr__(self): - return 'VolumeStatus:%s' % self.id - - def startElement(self, name, attrs, connection): - if name == 'eventsSet': - self.events = EventSet() - return self.events - elif name == 'actionsSet': - self.actions = ActionSet() - return self.actions - elif name == 'volumeStatus': - return self.volume_status - else: - return None - - def endElement(self, name, value, connection): - if name == 'volumeId': - self.id = value - elif name == 'availabilityZone': - self.zone = value - else: - setattr(self, name, value) - - -class VolumeStatusSet(list): - """ - A list object that contains the results of a call to - DescribeVolumeStatus request. Each element of the - list will be an VolumeStatus object. - - :ivar next_token: If the response was truncated by - the EC2 service, the next_token attribute of the - object will contain the string that needs to be - passed in to the next request to retrieve the next - set of results. - """ - - def __init__(self, connection=None): - list.__init__(self) - self.connection = connection - self.next_token = None - - def startElement(self, name, attrs, connection): - if name == 'item': - status = VolumeStatus() - self.append(status) - return status - else: - return None - - def endElement(self, name, value, connection): - if name == 'NextToken': - self.next_token = value - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ec2/zone.py b/awx/lib/site-packages/boto/ec2/zone.py deleted file mode 100644 index 85ed10224b..0000000000 --- a/awx/lib/site-packages/boto/ec2/zone.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2006-2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an EC2 Availability Zone -""" -from boto.ec2.ec2object import EC2Object - - -class MessageSet(list): - """ - A list object that contains messages associated with - an availability zone. - """ - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'message': - self.append(value) - else: - setattr(self, name, value) - - -class Zone(EC2Object): - """ - Represents an Availability Zone. - - :ivar name: The name of the zone. - :ivar state: The current state of the zone. - :ivar region_name: The name of the region the zone is associated with. - :ivar messages: A list of messages related to the zone. - """ - - def __init__(self, connection=None): - super(Zone, self).__init__(connection) - self.name = None - self.state = None - self.region_name = None - self.messages = None - - def __repr__(self): - return 'Zone:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'messageSet': - self.messages = MessageSet() - return self.messages - return None - - def endElement(self, name, value, connection): - if name == 'zoneName': - self.name = value - elif name == 'zoneState': - self.state = value - elif name == 'regionName': - self.region_name = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/ecs/__init__.py b/awx/lib/site-packages/boto/ecs/__init__.py deleted file mode 100644 index 46db50650e..0000000000 --- a/awx/lib/site-packages/boto/ecs/__init__.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (c) 2010 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -from boto.connection import AWSQueryConnection, AWSAuthConnection -from boto.exception import BotoServerError -import time -import urllib -import xml.sax -from boto.ecs.item import ItemSet -from boto import handler - -class ECSConnection(AWSQueryConnection): - """ - ECommerce Connection - - For more information on how to use this module see: - - http://blog.coredumped.org/2010/09/search-for-books-on-amazon-using-boto.html - """ - - APIVersion = '2010-11-01' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, host='ecs.amazonaws.com', - debug=0, https_connection_factory=None, path='/', - security_token=None, profile_name=None): - super(ECSConnection, self).__init__(aws_access_key_id, aws_secret_access_key, - is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, - host, debug, https_connection_factory, path, - security_token=security_token, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['ecs'] - - def get_response(self, action, params, page=0, itemSet=None): - """ - Utility method to handle calls to ECS and parsing of responses. - """ - params['Service'] = "AWSECommerceService" - params['Operation'] = action - if page: - params['ItemPage'] = page - response = self.make_request(None, params, "/onca/xml") - body = response.read().decode('utf-8') - boto.log.debug(body) - - if response.status != 200: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise BotoServerError(response.status, response.reason, body) - - if itemSet is None: - rs = ItemSet(self, action, params, page) - else: - rs = itemSet - h = handler.XmlHandler(rs, self) - xml.sax.parseString(body.encode('utf-8'), h) - if not rs.is_valid: - raise BotoServerError(response.status, '{Code}: {Message}'.format(**rs.errors[0])) - return rs - - # - # Group methods - # - - def item_search(self, search_index, **params): - """ - Returns items that satisfy the search criteria, including one or more search - indices. - - For a full list of search terms, - :see: http://docs.amazonwebservices.com/AWSECommerceService/2010-09-01/DG/index.html?ItemSearch.html - """ - params['SearchIndex'] = search_index - return self.get_response('ItemSearch', params) - - def item_lookup(self, **params): - """ - Returns items that satisfy the lookup query. - - For a full list of parameters, see: - http://s3.amazonaws.com/awsdocs/Associates/2011-08-01/prod-adv-api-dg-2011-08-01.pdf - """ - return self.get_response('ItemLookup', params) \ No newline at end of file diff --git a/awx/lib/site-packages/boto/ecs/item.py b/awx/lib/site-packages/boto/ecs/item.py deleted file mode 100644 index 79177a31d4..0000000000 --- a/awx/lib/site-packages/boto/ecs/item.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (c) 2010 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -import xml.sax -import cgi -from boto.compat import six, StringIO - -class ResponseGroup(xml.sax.ContentHandler): - """A Generic "Response Group", which can - be anything from the entire list of Items to - specific response elements within an item""" - - def __init__(self, connection=None, nodename=None): - """Initialize this Item""" - self._connection = connection - self._nodename = nodename - self._nodepath = [] - self._curobj = None - self._xml = StringIO() - - def __repr__(self): - return '<%s: %s>' % (self.__class__.__name__, self.__dict__) - - # - # Attribute Functions - # - def get(self, name): - return self.__dict__.get(name) - - def set(self, name, value): - self.__dict__[name] = value - - def to_xml(self): - return "<%s>%s</%s>" % (self._nodename, self._xml.getvalue(), self._nodename) - - # - # XML Parser functions - # - def startElement(self, name, attrs, connection): - self._xml.write("<%s>" % name) - self._nodepath.append(name) - if len(self._nodepath) == 1: - obj = ResponseGroup(self._connection) - self.set(name, obj) - self._curobj = obj - elif self._curobj: - self._curobj.startElement(name, attrs, connection) - return None - - def endElement(self, name, value, connection): - self._xml.write("%s</%s>" % (cgi.escape(value).replace("&amp;", "&"), name)) - if len(self._nodepath) == 0: - return - obj = None - curval = self.get(name) - if len(self._nodepath) == 1: - if value or not curval: - self.set(name, value) - if self._curobj: - self._curobj = None - #elif len(self._nodepath) == 2: - #self._curobj = None - elif self._curobj: - self._curobj.endElement(name, value, connection) - self._nodepath.pop() - return None - - -class Item(ResponseGroup): - """A single Item""" - - def __init__(self, connection=None): - """Initialize this Item""" - ResponseGroup.__init__(self, connection, "Item") - -class ItemSet(ResponseGroup): - """A special ResponseGroup that has built-in paging, and - only creates new Items on the "Item" tag""" - - def __init__(self, connection, action, params, page=0): - ResponseGroup.__init__(self, connection, "Items") - self.objs = [] - self.iter = None - self.page = page - self.action = action - self.params = params - self.curItem = None - self.total_results = 0 - self.total_pages = 0 - self.is_valid = False - self.errors = [] - - def startElement(self, name, attrs, connection): - if name == "Item": - self.curItem = Item(self._connection) - elif self.curItem is not None: - self.curItem.startElement(name, attrs, connection) - return None - - def endElement(self, name, value, connection): - if name == 'TotalResults': - self.total_results = value - elif name == 'TotalPages': - self.total_pages = value - elif name == 'IsValid': - if value == 'True': - self.is_valid = True - elif name == 'Code': - self.errors.append({'Code': value, 'Message': None}) - elif name == 'Message': - self.errors[-1]['Message'] = value - elif name == 'Item': - self.objs.append(self.curItem) - self._xml.write(self.curItem.to_xml()) - self.curItem = None - elif self.curItem is not None: - self.curItem.endElement(name, value, connection) - return None - - def __next__(self): - """Special paging functionality""" - if self.iter is None: - self.iter = iter(self.objs) - try: - return next(self.iter) - except StopIteration: - self.iter = None - self.objs = [] - if int(self.page) < int(self.total_pages): - self.page += 1 - self._connection.get_response(self.action, self.params, self.page, self) - return next(self) - else: - raise - - next = __next__ - - def __iter__(self): - return self - - def to_xml(self): - """Override to first fetch everything""" - for item in self: - pass - return ResponseGroup.to_xml(self) diff --git a/awx/lib/site-packages/boto/elasticache/__init__.py b/awx/lib/site-packages/boto/elasticache/__init__.py deleted file mode 100644 index 73d28c9f96..0000000000 --- a/awx/lib/site-packages/boto/elasticache/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the AWS ElastiCache service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.elasticache.layer1 import ElastiCacheConnection - return get_regions('elasticache', connection_cls=ElastiCacheConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/elasticache/layer1.py b/awx/lib/site-packages/boto/elasticache/layer1.py deleted file mode 100644 index 62bdefd187..0000000000 --- a/awx/lib/site-packages/boto/elasticache/layer1.py +++ /dev/null @@ -1,1664 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo - - -class ElastiCacheConnection(AWSQueryConnection): - """ - Amazon ElastiCache - Amazon ElastiCache is a web service that makes it easier to set - up, operate, and scale a distributed cache in the cloud. - - With ElastiCache, customers gain all of the benefits of a high- - performance, in-memory cache with far less of the administrative - burden of launching and managing a distributed cache. The service - makes set-up, scaling, and cluster failure handling much simpler - than in a self-managed cache deployment. - - In addition, through integration with Amazon CloudWatch, customers - get enhanced visibility into the key performance statistics - associated with their cache and can receive alarms if a part of - their cache runs hot. - """ - APIVersion = "2013-06-15" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "elasticache.us-east-1.amazonaws.com" - - def __init__(self, **kwargs): - region = kwargs.get('region') - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - else: - del kwargs['region'] - kwargs['host'] = region.endpoint - super(ElastiCacheConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def authorize_cache_security_group_ingress(self, - cache_security_group_name, - ec2_security_group_name, - ec2_security_group_owner_id): - """ - The AuthorizeCacheSecurityGroupIngress operation allows - network ingress to a cache security group. Applications using - ElastiCache must be running on Amazon EC2, and Amazon EC2 - security groups are used as the authorization mechanism. - You cannot authorize ingress from an Amazon EC2 security group - in one Region to an ElastiCache cluster in another Region. - - :type cache_security_group_name: string - :param cache_security_group_name: The cache security group which will - allow network ingress. - - :type ec2_security_group_name: string - :param ec2_security_group_name: The Amazon EC2 security group to be - authorized for ingress to the cache security group. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: The AWS account number of the - Amazon EC2 security group owner. Note that this is not the same - thing as an AWS access key ID - you must provide a valid AWS - account number for this parameter. - - """ - params = { - 'CacheSecurityGroupName': cache_security_group_name, - 'EC2SecurityGroupName': ec2_security_group_name, - 'EC2SecurityGroupOwnerId': ec2_security_group_owner_id, - } - return self._make_request( - action='AuthorizeCacheSecurityGroupIngress', - verb='POST', - path='/', params=params) - - def create_cache_cluster(self, cache_cluster_id, num_cache_nodes=None, - cache_node_type=None, engine=None, - replication_group_id=None, engine_version=None, - cache_parameter_group_name=None, - cache_subnet_group_name=None, - cache_security_group_names=None, - security_group_ids=None, snapshot_arns=None, - preferred_availability_zone=None, - preferred_maintenance_window=None, port=None, - notification_topic_arn=None, - auto_minor_version_upgrade=None): - """ - The CreateCacheCluster operation creates a new cache cluster. - All nodes in the cache cluster run the same protocol-compliant - cache engine software - either Memcached or Redis. - - :type cache_cluster_id: string - :param cache_cluster_id: - The cache cluster identifier. This parameter is stored as a lowercase - string. - - Constraints: - - - + Must contain from 1 to 20 alphanumeric characters or hyphens. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - :type replication_group_id: string - :param replication_group_id: The replication group to which this cache - cluster should belong. If this parameter is specified, the cache - cluster will be added to the specified replication group as a read - replica; otherwise, the cache cluster will be a standalone primary - that is not part of any replication group. - - :type num_cache_nodes: integer - :param num_cache_nodes: The initial number of cache nodes that the - cache cluster will have. - For a Memcached cluster, valid values are between 1 and 20. If you need - to exceed this limit, please fill out the ElastiCache Limit - Increase Request form at ``_ . - - For Redis, only single-node cache clusters are supported at this time, - so the value for this parameter must be 1. - - :type cache_node_type: string - :param cache_node_type: The compute and memory capacity of the nodes in - the cache cluster. - Valid values for Memcached: - - `cache.t1.micro` | `cache.m1.small` | `cache.m1.medium` | - `cache.m1.large` | `cache.m1.xlarge` | `cache.m3.xlarge` | - `cache.m3.2xlarge` | `cache.m2.xlarge` | `cache.m2.2xlarge` | - `cache.m2.4xlarge` | `cache.c1.xlarge` - - Valid values for Redis: - - `cache.t1.micro` | `cache.m1.small` | `cache.m1.medium` | - `cache.m1.large` | `cache.m1.xlarge` | `cache.m2.xlarge` | - `cache.m2.2xlarge` | `cache.m2.4xlarge` | `cache.c1.xlarge` - - For a complete listing of cache node types and specifications, see `. - - :type engine: string - :param engine: The name of the cache engine to be used for this cache - cluster. - Valid values for this parameter are: - - `memcached` | `redis` - - :type engine_version: string - :param engine_version: The version number of the cache engine to be - used for this cluster. To view the supported cache engine versions, - use the DescribeCacheEngineVersions operation. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: The name of the cache parameter - group to associate with this cache cluster. If this argument is - omitted, the default cache parameter group for the specified engine - will be used. - - :type cache_subnet_group_name: string - :param cache_subnet_group_name: The name of the cache subnet group to - be used for the cache cluster. - Use this parameter only when you are creating a cluster in an Amazon - Virtual Private Cloud (VPC). - - :type cache_security_group_names: list - :param cache_security_group_names: A list of cache security group names - to associate with this cache cluster. - Use this parameter only when you are creating a cluster outside of an - Amazon Virtual Private Cloud (VPC). - - :type security_group_ids: list - :param security_group_ids: One or more VPC security groups associated - with the cache cluster. - Use this parameter only when you are creating a cluster in an Amazon - Virtual Private Cloud (VPC). - - :type snapshot_arns: list - :param snapshot_arns: A single-element string list containing an Amazon - Resource Name (ARN) that uniquely identifies a Redis RDB snapshot - file stored in Amazon S3. The snapshot file will be used to - populate the Redis cache in the new cache cluster. The Amazon S3 - object name in the ARN cannot contain any commas. - Here is an example of an Amazon S3 ARN: - `arn:aws:s3:::my_bucket/snapshot1.rdb` - - **Note:** This parameter is only valid if the `Engine` parameter is - `redis`. - - :type preferred_availability_zone: string - :param preferred_availability_zone: The EC2 Availability Zone in which - the cache cluster will be created. - All cache nodes belonging to a cache cluster are placed in the - preferred availability zone. - - Default: System chosen availability zone. - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which system maintenance can occur. - Example: `sun:05:00-sun:09:00` - - :type port: integer - :param port: The port number on which each of the cache nodes will - accept connections. - - :type notification_topic_arn: string - :param notification_topic_arn: - The Amazon Resource Name (ARN) of the Amazon Simple Notification - Service (SNS) topic to which notifications will be sent. - - The Amazon SNS topic owner must be the same as the cache cluster owner. - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: Determines whether minor engine - upgrades will be applied automatically to the cache cluster during - the maintenance window. A value of `True` allows these upgrades to - occur; `False` disables automatic upgrades. - Default: `True` - - """ - params = { - 'CacheClusterId': cache_cluster_id, - } - if num_cache_nodes is not None: - params['NumCacheNodes'] = num_cache_nodes - if cache_node_type is not None: - params['CacheNodeType'] = cache_node_type - if engine is not None: - params['Engine'] = engine - if replication_group_id is not None: - params['ReplicationGroupId'] = replication_group_id - if engine_version is not None: - params['EngineVersion'] = engine_version - if cache_parameter_group_name is not None: - params['CacheParameterGroupName'] = cache_parameter_group_name - if cache_subnet_group_name is not None: - params['CacheSubnetGroupName'] = cache_subnet_group_name - if cache_security_group_names is not None: - self.build_list_params(params, - cache_security_group_names, - 'CacheSecurityGroupNames.member') - if security_group_ids is not None: - self.build_list_params(params, - security_group_ids, - 'SecurityGroupIds.member') - if snapshot_arns is not None: - self.build_list_params(params, - snapshot_arns, - 'SnapshotArns.member') - if preferred_availability_zone is not None: - params['PreferredAvailabilityZone'] = preferred_availability_zone - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if port is not None: - params['Port'] = port - if notification_topic_arn is not None: - params['NotificationTopicArn'] = notification_topic_arn - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - return self._make_request( - action='CreateCacheCluster', - verb='POST', - path='/', params=params) - - def create_cache_parameter_group(self, cache_parameter_group_name, - cache_parameter_group_family, - description): - """ - The CreateCacheParameterGroup operation creates a new cache - parameter group. A cache parameter group is a collection of - parameters that you apply to all of the nodes in a cache - cluster. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: A user-specified name for the cache - parameter group. - - :type cache_parameter_group_family: string - :param cache_parameter_group_family: The name of the cache parameter - group family the cache parameter group can be used with. - Valid values are: `memcached1.4` | `redis2.6` - - :type description: string - :param description: A user-specified description for the cache - parameter group. - - """ - params = { - 'CacheParameterGroupName': cache_parameter_group_name, - 'CacheParameterGroupFamily': cache_parameter_group_family, - 'Description': description, - } - return self._make_request( - action='CreateCacheParameterGroup', - verb='POST', - path='/', params=params) - - def create_cache_security_group(self, cache_security_group_name, - description): - """ - The CreateCacheSecurityGroup operation creates a new cache - security group. Use a cache security group to control access - to one or more cache clusters. - - Cache security groups are only used when you are creating a - cluster outside of an Amazon Virtual Private Cloud (VPC). If - you are creating a cluster inside of a VPC, use a cache subnet - group instead. For more information, see - CreateCacheSubnetGroup . - - :type cache_security_group_name: string - :param cache_security_group_name: A name for the cache security group. - This value is stored as a lowercase string. - Constraints: Must contain no more than 255 alphanumeric characters. - Must not be the word "Default". - - Example: `mysecuritygroup` - - :type description: string - :param description: A description for the cache security group. - - """ - params = { - 'CacheSecurityGroupName': cache_security_group_name, - 'Description': description, - } - return self._make_request( - action='CreateCacheSecurityGroup', - verb='POST', - path='/', params=params) - - def create_cache_subnet_group(self, cache_subnet_group_name, - cache_subnet_group_description, subnet_ids): - """ - The CreateCacheSubnetGroup operation creates a new cache - subnet group. - - Use this parameter only when you are creating a cluster in an - Amazon Virtual Private Cloud (VPC). - - :type cache_subnet_group_name: string - :param cache_subnet_group_name: A name for the cache subnet group. This - value is stored as a lowercase string. - Constraints: Must contain no more than 255 alphanumeric characters or - hyphens. - - Example: `mysubnetgroup` - - :type cache_subnet_group_description: string - :param cache_subnet_group_description: A description for the cache - subnet group. - - :type subnet_ids: list - :param subnet_ids: A list of VPC subnet IDs for the cache subnet group. - - """ - params = { - 'CacheSubnetGroupName': cache_subnet_group_name, - 'CacheSubnetGroupDescription': cache_subnet_group_description, - } - self.build_list_params(params, - subnet_ids, - 'SubnetIds.member') - return self._make_request( - action='CreateCacheSubnetGroup', - verb='POST', - path='/', params=params) - - def create_replication_group(self, replication_group_id, - primary_cluster_id, - replication_group_description): - """ - The CreateReplicationGroup operation creates a replication - group. A replication group is a collection of cache clusters, - where one of the clusters is a read/write primary and the - other clusters are read-only replicas. Writes to the primary - are automatically propagated to the replicas. - - When you create a replication group, you must specify an - existing cache cluster that is in the primary role. When the - replication group has been successfully created, you can add - one or more read replica replicas to it, up to a total of five - read replicas. - - :type replication_group_id: string - :param replication_group_id: - The replication group identifier. This parameter is stored as a - lowercase string. - - Constraints: - - - + Must contain from 1 to 20 alphanumeric characters or hyphens. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - :type primary_cluster_id: string - :param primary_cluster_id: The identifier of the cache cluster that - will serve as the primary for this replication group. This cache - cluster must already exist and have a status of available . - - :type replication_group_description: string - :param replication_group_description: A user-specified description for - the replication group. - - """ - params = { - 'ReplicationGroupId': replication_group_id, - 'PrimaryClusterId': primary_cluster_id, - 'ReplicationGroupDescription': replication_group_description, - } - return self._make_request( - action='CreateReplicationGroup', - verb='POST', - path='/', params=params) - - def delete_cache_cluster(self, cache_cluster_id): - """ - The DeleteCacheCluster operation deletes a previously - provisioned cache cluster. DeleteCacheCluster deletes all - associated cache nodes, node endpoints and the cache cluster - itself. When you receive a successful response from this - operation, Amazon ElastiCache immediately begins deleting the - cache cluster; you cannot cancel or revert this operation. - - :type cache_cluster_id: string - :param cache_cluster_id: The cache cluster identifier for the cluster - to be deleted. This parameter is not case sensitive. - - """ - params = {'CacheClusterId': cache_cluster_id, } - return self._make_request( - action='DeleteCacheCluster', - verb='POST', - path='/', params=params) - - def delete_cache_parameter_group(self, cache_parameter_group_name): - """ - The DeleteCacheParameterGroup operation deletes the specified - cache parameter group. You cannot delete a cache parameter - group if it is associated with any cache clusters. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: - The name of the cache parameter group to delete. - - The specified cache security group must not be associated with any - cache clusters. - - """ - params = { - 'CacheParameterGroupName': cache_parameter_group_name, - } - return self._make_request( - action='DeleteCacheParameterGroup', - verb='POST', - path='/', params=params) - - def delete_cache_security_group(self, cache_security_group_name): - """ - The DeleteCacheSecurityGroup operation deletes a cache - security group. - You cannot delete a cache security group if it is associated - with any cache clusters. - - :type cache_security_group_name: string - :param cache_security_group_name: - The name of the cache security group to delete. - - You cannot delete the default security group. - - """ - params = { - 'CacheSecurityGroupName': cache_security_group_name, - } - return self._make_request( - action='DeleteCacheSecurityGroup', - verb='POST', - path='/', params=params) - - def delete_cache_subnet_group(self, cache_subnet_group_name): - """ - The DeleteCacheSubnetGroup operation deletes a cache subnet - group. - You cannot delete a cache subnet group if it is associated - with any cache clusters. - - :type cache_subnet_group_name: string - :param cache_subnet_group_name: The name of the cache subnet group to - delete. - Constraints: Must contain no more than 255 alphanumeric characters or - hyphens. - - """ - params = {'CacheSubnetGroupName': cache_subnet_group_name, } - return self._make_request( - action='DeleteCacheSubnetGroup', - verb='POST', - path='/', params=params) - - def delete_replication_group(self, replication_group_id): - """ - The DeleteReplicationGroup operation deletes an existing - replication group. DeleteReplicationGroup deletes the primary - cache cluster and all of the read replicas in the replication - group. When you receive a successful response from this - operation, Amazon ElastiCache immediately begins deleting the - entire replication group; you cannot cancel or revert this - operation. - - :type replication_group_id: string - :param replication_group_id: The identifier for the replication group - to be deleted. This parameter is not case sensitive. - - """ - params = {'ReplicationGroupId': replication_group_id, } - return self._make_request( - action='DeleteReplicationGroup', - verb='POST', - path='/', params=params) - - def describe_cache_clusters(self, cache_cluster_id=None, - max_records=None, marker=None, - show_cache_node_info=None): - """ - The DescribeCacheClusters operation returns information about - all provisioned cache clusters if no cache cluster identifier - is specified, or about a specific cache cluster if a cache - cluster identifier is supplied. - - By default, abbreviated information about the cache - clusters(s) will be returned. You can use the optional - ShowDetails flag to retrieve detailed information about the - cache nodes associated with the cache clusters. These details - include the DNS address and port for the cache node endpoint. - - If the cluster is in the CREATING state, only cluster level - information will be displayed until all of the nodes are - successfully provisioned. - - If the cluster is in the DELETING state, only cluster level - information will be displayed. - - If cache nodes are currently being added to the cache cluster, - node endpoint information and creation time for the additional - nodes will not be displayed until they are completely - provisioned. When the cache cluster state is available , the - cluster is ready for use. - - If cache nodes are currently being removed from the cache - cluster, no endpoint information for the removed nodes is - displayed. - - :type cache_cluster_id: string - :param cache_cluster_id: The user-supplied cluster identifier. If this - parameter is specified, only information about that specific cache - cluster is returned. This parameter isn't case sensitive. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - :type show_cache_node_info: boolean - :param show_cache_node_info: An optional flag that can be included in - the DescribeCacheCluster request to retrieve information about the - individual cache nodes. - - """ - params = {} - if cache_cluster_id is not None: - params['CacheClusterId'] = cache_cluster_id - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - if show_cache_node_info is not None: - params['ShowCacheNodeInfo'] = str( - show_cache_node_info).lower() - return self._make_request( - action='DescribeCacheClusters', - verb='POST', - path='/', params=params) - - def describe_cache_engine_versions(self, engine=None, - engine_version=None, - cache_parameter_group_family=None, - max_records=None, marker=None, - default_only=None): - """ - The DescribeCacheEngineVersions operation returns a list of - the available cache engines and their versions. - - :type engine: string - :param engine: The cache engine to return. Valid values: `memcached` | - `redis` - - :type engine_version: string - :param engine_version: The cache engine version to return. - Example: `1.4.14` - - :type cache_parameter_group_family: string - :param cache_parameter_group_family: - The name of a specific cache parameter group family to return details - for. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - :type default_only: boolean - :param default_only: If true , specifies that only the default version - of the specified engine or engine and major version combination is - to be returned. - - """ - params = {} - if engine is not None: - params['Engine'] = engine - if engine_version is not None: - params['EngineVersion'] = engine_version - if cache_parameter_group_family is not None: - params['CacheParameterGroupFamily'] = cache_parameter_group_family - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - if default_only is not None: - params['DefaultOnly'] = str( - default_only).lower() - return self._make_request( - action='DescribeCacheEngineVersions', - verb='POST', - path='/', params=params) - - def describe_cache_parameter_groups(self, - cache_parameter_group_name=None, - max_records=None, marker=None): - """ - The DescribeCacheParameterGroups operation returns a list of - cache parameter group descriptions. If a cache parameter group - name is specified, the list will contain only the descriptions - for that group. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: The name of a specific cache - parameter group to return details for. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = {} - if cache_parameter_group_name is not None: - params['CacheParameterGroupName'] = cache_parameter_group_name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeCacheParameterGroups', - verb='POST', - path='/', params=params) - - def describe_cache_parameters(self, cache_parameter_group_name, - source=None, max_records=None, marker=None): - """ - The DescribeCacheParameters operation returns the detailed - parameter list for a particular cache parameter group. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: The name of a specific cache - parameter group to return details for. - - :type source: string - :param source: The parameter types to return. - Valid values: `user` | `system` | `engine-default` - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = { - 'CacheParameterGroupName': cache_parameter_group_name, - } - if source is not None: - params['Source'] = source - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeCacheParameters', - verb='POST', - path='/', params=params) - - def describe_cache_security_groups(self, cache_security_group_name=None, - max_records=None, marker=None): - """ - The DescribeCacheSecurityGroups operation returns a list of - cache security group descriptions. If a cache security group - name is specified, the list will contain only the description - of that group. - - :type cache_security_group_name: string - :param cache_security_group_name: The name of the cache security group - to return details for. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = {} - if cache_security_group_name is not None: - params['CacheSecurityGroupName'] = cache_security_group_name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeCacheSecurityGroups', - verb='POST', - path='/', params=params) - - def describe_cache_subnet_groups(self, cache_subnet_group_name=None, - max_records=None, marker=None): - """ - The DescribeCacheSubnetGroups operation returns a list of - cache subnet group descriptions. If a subnet group name is - specified, the list will contain only the description of that - group. - - :type cache_subnet_group_name: string - :param cache_subnet_group_name: The name of the cache subnet group to - return details for. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = {} - if cache_subnet_group_name is not None: - params['CacheSubnetGroupName'] = cache_subnet_group_name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeCacheSubnetGroups', - verb='POST', - path='/', params=params) - - def describe_engine_default_parameters(self, - cache_parameter_group_family, - max_records=None, marker=None): - """ - The DescribeEngineDefaultParameters operation returns the - default engine and system parameter information for the - specified cache engine. - - :type cache_parameter_group_family: string - :param cache_parameter_group_family: The name of the cache parameter - group family. Valid values are: `memcached1.4` | `redis2.6` - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = { - 'CacheParameterGroupFamily': cache_parameter_group_family, - } - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeEngineDefaultParameters', - verb='POST', - path='/', params=params) - - def describe_events(self, source_identifier=None, source_type=None, - start_time=None, end_time=None, duration=None, - max_records=None, marker=None): - """ - The DescribeEvents operation returns events related to cache - clusters, cache security groups, and cache parameter groups. - You can obtain events specific to a particular cache cluster, - cache security group, or cache parameter group by providing - the name as a parameter. - - By default, only the events occurring within the last hour are - returned; however, you can retrieve up to 14 days' worth of - events if necessary. - - :type source_identifier: string - :param source_identifier: The identifier of the event source for which - events will be returned. If not specified, then all sources are - included in the response. - - :type source_type: string - :param source_type: The event source to retrieve events for. If no - value is specified, all events are returned. - Valid values are: `cache-cluster` | `cache-parameter-group` | `cache- - security-group` | `cache-subnet-group` - - :type start_time: timestamp - :param start_time: The beginning of the time interval to retrieve - events for, specified in ISO 8601 format. - - :type end_time: timestamp - :param end_time: The end of the time interval for which to retrieve - events, specified in ISO 8601 format. - - :type duration: integer - :param duration: The number of minutes' worth of events to retrieve. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = {} - if source_identifier is not None: - params['SourceIdentifier'] = source_identifier - if source_type is not None: - params['SourceType'] = source_type - if start_time is not None: - params['StartTime'] = start_time - if end_time is not None: - params['EndTime'] = end_time - if duration is not None: - params['Duration'] = duration - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeEvents', - verb='POST', - path='/', params=params) - - def describe_replication_groups(self, replication_group_id=None, - max_records=None, marker=None): - """ - The DescribeReplicationGroups operation returns information - about a particular replication group. If no identifier is - specified, DescribeReplicationGroups returns information about - all replication groups. - - :type replication_group_id: string - :param replication_group_id: The identifier for the replication group - to be described. This parameter is not case sensitive. - If you do not specify this parameter, information about all replication - groups is returned. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = {} - if replication_group_id is not None: - params['ReplicationGroupId'] = replication_group_id - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeReplicationGroups', - verb='POST', - path='/', params=params) - - def describe_reserved_cache_nodes(self, reserved_cache_node_id=None, - reserved_cache_nodes_offering_id=None, - cache_node_type=None, duration=None, - product_description=None, - offering_type=None, max_records=None, - marker=None): - """ - The DescribeReservedCacheNodes operation returns information - about reserved cache nodes for this account, or about a - specified reserved cache node. - - :type reserved_cache_node_id: string - :param reserved_cache_node_id: The reserved cache node identifier - filter value. Use this parameter to show only the reservation that - matches the specified reservation ID. - - :type reserved_cache_nodes_offering_id: string - :param reserved_cache_nodes_offering_id: The offering identifier filter - value. Use this parameter to show only purchased reservations - matching the specified offering identifier. - - :type cache_node_type: string - :param cache_node_type: The cache node type filter value. Use this - parameter to show only those reservations matching the specified - cache node type. - - :type duration: string - :param duration: The duration filter value, specified in years or - seconds. Use this parameter to show only reservations for this - duration. - Valid Values: `1 | 3 | 31536000 | 94608000` - - :type product_description: string - :param product_description: The product description filter value. Use - this parameter to show only those reservations matching the - specified product description. - - :type offering_type: string - :param offering_type: The offering type filter value. Use this - parameter to show only the available offerings matching the - specified offering type. - Valid values: `"Light Utilization" | "Medium Utilization" | "Heavy - Utilization" ` - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = {} - if reserved_cache_node_id is not None: - params['ReservedCacheNodeId'] = reserved_cache_node_id - if reserved_cache_nodes_offering_id is not None: - params['ReservedCacheNodesOfferingId'] = reserved_cache_nodes_offering_id - if cache_node_type is not None: - params['CacheNodeType'] = cache_node_type - if duration is not None: - params['Duration'] = duration - if product_description is not None: - params['ProductDescription'] = product_description - if offering_type is not None: - params['OfferingType'] = offering_type - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeReservedCacheNodes', - verb='POST', - path='/', params=params) - - def describe_reserved_cache_nodes_offerings(self, - reserved_cache_nodes_offering_id=None, - cache_node_type=None, - duration=None, - product_description=None, - offering_type=None, - max_records=None, - marker=None): - """ - The DescribeReservedCacheNodesOfferings operation lists - available reserved cache node offerings. - - :type reserved_cache_nodes_offering_id: string - :param reserved_cache_nodes_offering_id: The offering identifier filter - value. Use this parameter to show only the available offering that - matches the specified reservation identifier. - Example: `438012d3-4052-4cc7-b2e3-8d3372e0e706` - - :type cache_node_type: string - :param cache_node_type: The cache node type filter value. Use this - parameter to show only the available offerings matching the - specified cache node type. - - :type duration: string - :param duration: Duration filter value, specified in years or seconds. - Use this parameter to show only reservations for a given duration. - Valid Values: `1 | 3 | 31536000 | 94608000` - - :type product_description: string - :param product_description: The product description filter value. Use - this parameter to show only the available offerings matching the - specified product description. - - :type offering_type: string - :param offering_type: The offering type filter value. Use this - parameter to show only the available offerings matching the - specified offering type. - Valid Values: `"Light Utilization" | "Medium Utilization" | "Heavy - Utilization" ` - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a marker is included in the response so that the remaining - results can be retrieved. - Default: 100 - - Constraints: minimum 20; maximum 100. - - :type marker: string - :param marker: An optional marker returned from a prior request. Use - this marker for pagination of results from this operation. If this - parameter is specified, the response includes only records beyond - the marker, up to the value specified by MaxRecords . - - """ - params = {} - if reserved_cache_nodes_offering_id is not None: - params['ReservedCacheNodesOfferingId'] = reserved_cache_nodes_offering_id - if cache_node_type is not None: - params['CacheNodeType'] = cache_node_type - if duration is not None: - params['Duration'] = duration - if product_description is not None: - params['ProductDescription'] = product_description - if offering_type is not None: - params['OfferingType'] = offering_type - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeReservedCacheNodesOfferings', - verb='POST', - path='/', params=params) - - def modify_cache_cluster(self, cache_cluster_id, num_cache_nodes=None, - cache_node_ids_to_remove=None, - cache_security_group_names=None, - security_group_ids=None, - preferred_maintenance_window=None, - notification_topic_arn=None, - cache_parameter_group_name=None, - notification_topic_status=None, - apply_immediately=None, engine_version=None, - auto_minor_version_upgrade=None): - """ - The ModifyCacheCluster operation modifies the settings for a - cache cluster. You can use this operation to change one or - more cluster configuration parameters by specifying the - parameters and the new values. - - :type cache_cluster_id: string - :param cache_cluster_id: The cache cluster identifier. This value is - stored as a lowercase string. - - :type num_cache_nodes: integer - :param num_cache_nodes: The number of cache nodes that the cache - cluster should have. If the value for NumCacheNodes is greater than - the existing number of cache nodes, then more nodes will be added. - If the value is less than the existing number of cache nodes, then - cache nodes will be removed. - If you are removing cache nodes, you must use the CacheNodeIdsToRemove - parameter to provide the IDs of the specific cache nodes to be - removed. - - :type cache_node_ids_to_remove: list - :param cache_node_ids_to_remove: A list of cache node IDs to be - removed. A node ID is a numeric identifier (0001, 0002, etc.). This - parameter is only valid when NumCacheNodes is less than the - existing number of cache nodes. The number of cache node IDs - supplied in this parameter must match the difference between the - existing number of cache nodes in the cluster and the value of - NumCacheNodes in the request. - - :type cache_security_group_names: list - :param cache_security_group_names: A list of cache security group names - to authorize on this cache cluster. This change is asynchronously - applied as soon as possible. - This parameter can be used only with clusters that are created outside - of an Amazon Virtual Private Cloud (VPC). - - Constraints: Must contain no more than 255 alphanumeric characters. - Must not be "Default". - - :type security_group_ids: list - :param security_group_ids: Specifies the VPC Security Groups associated - with the cache cluster. - This parameter can be used only with clusters that are created in an - Amazon Virtual Private Cloud (VPC). - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which system maintenance can occur. Note that system - maintenance may result in an outage. This change is made - immediately. If you are moving this window to the current time, - there must be at least 120 minutes between the current time and end - of the window to ensure that pending changes are applied. - - :type notification_topic_arn: string - :param notification_topic_arn: - The Amazon Resource Name (ARN) of the SNS topic to which notifications - will be sent. - - The SNS topic owner must be same as the cache cluster owner. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: The name of the cache parameter - group to apply to this cache cluster. This change is asynchronously - applied as soon as possible for parameters when the - ApplyImmediately parameter is specified as true for this request. - - :type notification_topic_status: string - :param notification_topic_status: The status of the Amazon SNS - notification topic. Notifications are sent only if the status is - active . - Valid values: `active` | `inactive` - - :type apply_immediately: boolean - :param apply_immediately: If `True`, this parameter causes the - modifications in this request and any pending modifications to be - applied, asynchronously and as soon as possible, regardless of the - PreferredMaintenanceWindow setting for the cache cluster. - If `False`, then changes to the cache cluster are applied on the next - maintenance reboot, or the next failure reboot, whichever occurs - first. - - Valid values: `True` | `False` - - Default: `False` - - :type engine_version: string - :param engine_version: The upgraded version of the cache engine to be - run on the cache cluster nodes. - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: If `True`, then minor engine - upgrades will be applied automatically to the cache cluster during - the maintenance window. - Valid values: `True` | `False` - - Default: `True` - - """ - params = {'CacheClusterId': cache_cluster_id, } - if num_cache_nodes is not None: - params['NumCacheNodes'] = num_cache_nodes - if cache_node_ids_to_remove is not None: - self.build_list_params(params, - cache_node_ids_to_remove, - 'CacheNodeIdsToRemove.member') - if cache_security_group_names is not None: - self.build_list_params(params, - cache_security_group_names, - 'CacheSecurityGroupNames.member') - if security_group_ids is not None: - self.build_list_params(params, - security_group_ids, - 'SecurityGroupIds.member') - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if notification_topic_arn is not None: - params['NotificationTopicArn'] = notification_topic_arn - if cache_parameter_group_name is not None: - params['CacheParameterGroupName'] = cache_parameter_group_name - if notification_topic_status is not None: - params['NotificationTopicStatus'] = notification_topic_status - if apply_immediately is not None: - params['ApplyImmediately'] = str( - apply_immediately).lower() - if engine_version is not None: - params['EngineVersion'] = engine_version - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - return self._make_request( - action='ModifyCacheCluster', - verb='POST', - path='/', params=params) - - def modify_cache_parameter_group(self, cache_parameter_group_name, - parameter_name_values): - """ - The ModifyCacheParameterGroup operation modifies the - parameters of a cache parameter group. You can modify up to 20 - parameters in a single request by submitting a list parameter - name and value pairs. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: The name of the cache parameter - group to modify. - - :type parameter_name_values: list - :param parameter_name_values: An array of parameter names and values - for the parameter update. You must supply at least one parameter - name and value; subsequent arguments are optional. A maximum of 20 - parameters may be modified per request. - - """ - params = { - 'CacheParameterGroupName': cache_parameter_group_name, - } - self.build_complex_list_params( - params, parameter_name_values, - 'ParameterNameValues.member', - ('ParameterName', 'ParameterValue')) - return self._make_request( - action='ModifyCacheParameterGroup', - verb='POST', - path='/', params=params) - - def modify_cache_subnet_group(self, cache_subnet_group_name, - cache_subnet_group_description=None, - subnet_ids=None): - """ - The ModifyCacheSubnetGroup operation modifies an existing - cache subnet group. - - :type cache_subnet_group_name: string - :param cache_subnet_group_name: The name for the cache subnet group. - This value is stored as a lowercase string. - Constraints: Must contain no more than 255 alphanumeric characters or - hyphens. - - Example: `mysubnetgroup` - - :type cache_subnet_group_description: string - :param cache_subnet_group_description: A description for the cache - subnet group. - - :type subnet_ids: list - :param subnet_ids: The EC2 subnet IDs for the cache subnet group. - - """ - params = {'CacheSubnetGroupName': cache_subnet_group_name, } - if cache_subnet_group_description is not None: - params['CacheSubnetGroupDescription'] = cache_subnet_group_description - if subnet_ids is not None: - self.build_list_params(params, - subnet_ids, - 'SubnetIds.member') - return self._make_request( - action='ModifyCacheSubnetGroup', - verb='POST', - path='/', params=params) - - def modify_replication_group(self, replication_group_id, - replication_group_description=None, - cache_security_group_names=None, - security_group_ids=None, - preferred_maintenance_window=None, - notification_topic_arn=None, - cache_parameter_group_name=None, - notification_topic_status=None, - apply_immediately=None, engine_version=None, - auto_minor_version_upgrade=None, - primary_cluster_id=None): - """ - The ModifyReplicationGroup operation modifies the settings for - a replication group. - - :type replication_group_id: string - :param replication_group_id: The identifier of the replication group to - modify. - - :type replication_group_description: string - :param replication_group_description: A description for the replication - group. Maximum length is 255 characters. - - :type cache_security_group_names: list - :param cache_security_group_names: A list of cache security group names - to authorize for the clusters in this replication group. This - change is asynchronously applied as soon as possible. - This parameter can be used only with replication groups containing - cache clusters running outside of an Amazon Virtual Private Cloud - (VPC). - - Constraints: Must contain no more than 255 alphanumeric characters. - Must not be "Default". - - :type security_group_ids: list - :param security_group_ids: Specifies the VPC Security Groups associated - with the cache clusters in the replication group. - This parameter can be used only with replication groups containing - cache clusters running in an Amazon Virtual Private Cloud (VPC). - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which replication group system maintenance can occur. Note - that system maintenance may result in an outage. This change is - made immediately. If you are moving this window to the current - time, there must be at least 120 minutes between the current time - and end of the window to ensure that pending changes are applied. - - :type notification_topic_arn: string - :param notification_topic_arn: - The Amazon Resource Name (ARN) of the SNS topic to which notifications - will be sent. - - The SNS topic owner must be same as the replication group owner. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: The name of the cache parameter - group to apply to all of the cache nodes in this replication group. - This change is asynchronously applied as soon as possible for - parameters when the ApplyImmediately parameter is specified as true - for this request. - - :type notification_topic_status: string - :param notification_topic_status: The status of the Amazon SNS - notification topic for the replication group. Notifications are - sent only if the status is active . - Valid values: `active` | `inactive` - - :type apply_immediately: boolean - :param apply_immediately: If `True`, this parameter causes the - modifications in this request and any pending modifications to be - applied, asynchronously and as soon as possible, regardless of the - PreferredMaintenanceWindow setting for the replication group. - If `False`, then changes to the nodes in the replication group are - applied on the next maintenance reboot, or the next failure reboot, - whichever occurs first. - - Valid values: `True` | `False` - - Default: `False` - - :type engine_version: string - :param engine_version: The upgraded version of the cache engine to be - run on the nodes in the replication group.. - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: Determines whether minor engine - upgrades will be applied automatically to all of the cache nodes in - the replication group during the maintenance window. A value of - `True` allows these upgrades to occur; `False` disables automatic - upgrades. - - :type primary_cluster_id: string - :param primary_cluster_id: If this parameter is specified, ElastiCache - will promote each of the nodes in the specified cache cluster to - the primary role. The nodes of all other clusters in the - replication group will be read replicas. - - """ - params = {'ReplicationGroupId': replication_group_id, } - if replication_group_description is not None: - params['ReplicationGroupDescription'] = replication_group_description - if cache_security_group_names is not None: - self.build_list_params(params, - cache_security_group_names, - 'CacheSecurityGroupNames.member') - if security_group_ids is not None: - self.build_list_params(params, - security_group_ids, - 'SecurityGroupIds.member') - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if notification_topic_arn is not None: - params['NotificationTopicArn'] = notification_topic_arn - if cache_parameter_group_name is not None: - params['CacheParameterGroupName'] = cache_parameter_group_name - if notification_topic_status is not None: - params['NotificationTopicStatus'] = notification_topic_status - if apply_immediately is not None: - params['ApplyImmediately'] = str( - apply_immediately).lower() - if engine_version is not None: - params['EngineVersion'] = engine_version - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - if primary_cluster_id is not None: - params['PrimaryClusterId'] = primary_cluster_id - return self._make_request( - action='ModifyReplicationGroup', - verb='POST', - path='/', params=params) - - def purchase_reserved_cache_nodes_offering(self, - reserved_cache_nodes_offering_id, - reserved_cache_node_id=None, - cache_node_count=None): - """ - The PurchaseReservedCacheNodesOffering operation allows you to - purchase a reserved cache node offering. - - :type reserved_cache_nodes_offering_id: string - :param reserved_cache_nodes_offering_id: The ID of the reserved cache - node offering to purchase. - Example: 438012d3-4052-4cc7-b2e3-8d3372e0e706 - - :type reserved_cache_node_id: string - :param reserved_cache_node_id: A customer-specified identifier to track - this reservation. - Example: myreservationID - - :type cache_node_count: integer - :param cache_node_count: The number of cache node instances to reserve. - Default: `1` - - """ - params = { - 'ReservedCacheNodesOfferingId': reserved_cache_nodes_offering_id, - } - if reserved_cache_node_id is not None: - params['ReservedCacheNodeId'] = reserved_cache_node_id - if cache_node_count is not None: - params['CacheNodeCount'] = cache_node_count - return self._make_request( - action='PurchaseReservedCacheNodesOffering', - verb='POST', - path='/', params=params) - - def reboot_cache_cluster(self, cache_cluster_id, - cache_node_ids_to_reboot): - """ - The RebootCacheCluster operation reboots some, or all, of the - cache cluster nodes within a provisioned cache cluster. This - API will apply any modified cache parameter groups to the - cache cluster. The reboot action takes place as soon as - possible, and results in a momentary outage to the cache - cluster. During the reboot, the cache cluster status is set to - REBOOTING. - - The reboot causes the contents of the cache (for each cache - cluster node being rebooted) to be lost. - - When the reboot is complete, a cache cluster event is created. - - :type cache_cluster_id: string - :param cache_cluster_id: The cache cluster identifier. This parameter - is stored as a lowercase string. - - :type cache_node_ids_to_reboot: list - :param cache_node_ids_to_reboot: A list of cache cluster node IDs to - reboot. A node ID is a numeric identifier (0001, 0002, etc.). To - reboot an entire cache cluster, specify all of the cache cluster - node IDs. - - """ - params = {'CacheClusterId': cache_cluster_id, } - self.build_list_params(params, - cache_node_ids_to_reboot, - 'CacheNodeIdsToReboot.member') - return self._make_request( - action='RebootCacheCluster', - verb='POST', - path='/', params=params) - - def reset_cache_parameter_group(self, cache_parameter_group_name, - parameter_name_values, - reset_all_parameters=None): - """ - The ResetCacheParameterGroup operation modifies the parameters - of a cache parameter group to the engine or system default - value. You can reset specific parameters by submitting a list - of parameter names. To reset the entire cache parameter group, - specify the ResetAllParameters and CacheParameterGroupName - parameters. - - :type cache_parameter_group_name: string - :param cache_parameter_group_name: The name of the cache parameter - group to reset. - - :type reset_all_parameters: boolean - :param reset_all_parameters: If true , all parameters in the cache - parameter group will be reset to default values. If false , no such - action occurs. - Valid values: `True` | `False` - - :type parameter_name_values: list - :param parameter_name_values: An array of parameter names to be reset. - If you are not resetting the entire cache parameter group, you must - specify at least one parameter name. - - """ - params = { - 'CacheParameterGroupName': cache_parameter_group_name, - } - self.build_complex_list_params( - params, parameter_name_values, - 'ParameterNameValues.member', - ('ParameterName', 'ParameterValue')) - if reset_all_parameters is not None: - params['ResetAllParameters'] = str( - reset_all_parameters).lower() - return self._make_request( - action='ResetCacheParameterGroup', - verb='POST', - path='/', params=params) - - def revoke_cache_security_group_ingress(self, cache_security_group_name, - ec2_security_group_name, - ec2_security_group_owner_id): - """ - The RevokeCacheSecurityGroupIngress operation revokes ingress - from a cache security group. Use this operation to disallow - access from an Amazon EC2 security group that had been - previously authorized. - - :type cache_security_group_name: string - :param cache_security_group_name: The name of the cache security group - to revoke ingress from. - - :type ec2_security_group_name: string - :param ec2_security_group_name: The name of the Amazon EC2 security - group to revoke access from. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: The AWS account number of the - Amazon EC2 security group owner. Note that this is not the same - thing as an AWS access key ID - you must provide a valid AWS - account number for this parameter. - - """ - params = { - 'CacheSecurityGroupName': cache_security_group_name, - 'EC2SecurityGroupName': ec2_security_group_name, - 'EC2SecurityGroupOwnerId': ec2_security_group_owner_id, - } - return self._make_request( - action='RevokeCacheSecurityGroupIngress', - verb='POST', - path='/', params=params) - - def _make_request(self, action, verb, path, params): - params['ContentType'] = 'JSON' - response = self.make_request(action=action, verb='POST', - path='/', params=params) - body = response.read().decode('utf-8') - boto.log.debug(body) - if response.status == 200: - return json.loads(body) - else: - raise self.ResponseError(response.status, response.reason, body) diff --git a/awx/lib/site-packages/boto/elastictranscoder/__init__.py b/awx/lib/site-packages/boto/elastictranscoder/__init__.py deleted file mode 100644 index afb23e56c8..0000000000 --- a/awx/lib/site-packages/boto/elastictranscoder/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the AWS Elastic Transcoder service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.elastictranscoder.layer1 import ElasticTranscoderConnection - return get_regions( - 'elastictranscoder', - connection_cls=ElasticTranscoderConnection - ) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None - diff --git a/awx/lib/site-packages/boto/elastictranscoder/exceptions.py b/awx/lib/site-packages/boto/elastictranscoder/exceptions.py deleted file mode 100644 index 94b399f537..0000000000 --- a/awx/lib/site-packages/boto/elastictranscoder/exceptions.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import JSONResponseError - - -class LimitExceededException(JSONResponseError): - pass - - -class ResourceInUseException(JSONResponseError): - pass - - -class AccessDeniedException(JSONResponseError): - pass - - -class ResourceNotFoundException(JSONResponseError): - pass - - -class InternalServiceException(JSONResponseError): - pass - - -class ValidationException(JSONResponseError): - pass - - -class IncompatibleVersionException(JSONResponseError): - pass diff --git a/awx/lib/site-packages/boto/elastictranscoder/layer1.py b/awx/lib/site-packages/boto/elastictranscoder/layer1.py deleted file mode 100644 index 0f4dc9c74c..0000000000 --- a/awx/lib/site-packages/boto/elastictranscoder/layer1.py +++ /dev/null @@ -1,932 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.compat import json -from boto.exception import JSONResponseError -from boto.connection import AWSAuthConnection -from boto.regioninfo import RegionInfo -from boto.elastictranscoder import exceptions - - -class ElasticTranscoderConnection(AWSAuthConnection): - """ - AWS Elastic Transcoder Service - The AWS Elastic Transcoder Service. - """ - APIVersion = "2012-09-25" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "elastictranscoder.us-east-1.amazonaws.com" - ResponseError = JSONResponseError - - _faults = { - "IncompatibleVersionException": exceptions.IncompatibleVersionException, - "LimitExceededException": exceptions.LimitExceededException, - "ResourceInUseException": exceptions.ResourceInUseException, - "AccessDeniedException": exceptions.AccessDeniedException, - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "InternalServiceException": exceptions.InternalServiceException, - "ValidationException": exceptions.ValidationException, - } - - - def __init__(self, **kwargs): - region = kwargs.get('region') - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - else: - del kwargs['region'] - kwargs['host'] = region.endpoint - super(ElasticTranscoderConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def cancel_job(self, id=None): - """ - The CancelJob operation cancels an unfinished job. - You can only cancel a job that has a status of `Submitted`. To - prevent a pipeline from starting to process a job while you're - getting the job identifier, use UpdatePipelineStatus to - temporarily pause the pipeline. - - :type id: string - :param id: The identifier of the job that you want to cancel. - To get a list of the jobs (including their `jobId`) that have a status - of `Submitted`, use the ListJobsByStatus API action. - - """ - uri = '/2012-09-25/jobs/{0}'.format(id) - return self.make_request('DELETE', uri, expected_status=202) - - def create_job(self, pipeline_id=None, input_name=None, output=None, - outputs=None, output_key_prefix=None, playlists=None): - """ - When you create a job, Elastic Transcoder returns JSON data - that includes the values that you specified plus information - about the job that is created. - - If you have specified more than one output for your jobs (for - example, one output for the Kindle Fire and another output for - the Apple iPhone 4s), you currently must use the Elastic - Transcoder API to list the jobs (as opposed to the AWS - Console). - - :type pipeline_id: string - :param pipeline_id: The `Id` of the pipeline that you want Elastic - Transcoder to use for transcoding. The pipeline determines several - settings, including the Amazon S3 bucket from which Elastic - Transcoder gets the files to transcode and the bucket into which - Elastic Transcoder puts the transcoded files. - - :type input_name: dict - :param input_name: A section of the request body that provides - information about the file that is being transcoded. - - :type output: dict - :param output: The `CreateJobOutput` structure. - - :type outputs: list - :param outputs: A section of the request body that provides information - about the transcoded (target) files. We recommend that you use the - `Outputs` syntax instead of the `Output` syntax. - - :type output_key_prefix: string - :param output_key_prefix: The value, if any, that you want Elastic - Transcoder to prepend to the names of all files that this job - creates, including output files, thumbnails, and playlists. - - :type playlists: list - :param playlists: If you specify a preset in `PresetId` for which the - value of `Container` is ts (MPEG-TS), Playlists contains - information about the master playlists that you want Elastic - Transcoder to create. - We recommend that you create only one master playlist. The maximum - number of master playlists in a job is 30. - - """ - uri = '/2012-09-25/jobs' - params = {} - if pipeline_id is not None: - params['PipelineId'] = pipeline_id - if input_name is not None: - params['Input'] = input_name - if output is not None: - params['Output'] = output - if outputs is not None: - params['Outputs'] = outputs - if output_key_prefix is not None: - params['OutputKeyPrefix'] = output_key_prefix - if playlists is not None: - params['Playlists'] = playlists - return self.make_request('POST', uri, expected_status=201, - data=json.dumps(params)) - - def create_pipeline(self, name=None, input_bucket=None, - output_bucket=None, role=None, notifications=None, - content_config=None, thumbnail_config=None): - """ - The CreatePipeline operation creates a pipeline with settings - that you specify. - - :type name: string - :param name: The name of the pipeline. We recommend that the name be - unique within the AWS account, but uniqueness is not enforced. - Constraints: Maximum 40 characters. - - :type input_bucket: string - :param input_bucket: The Amazon S3 bucket in which you saved the media - files that you want to transcode. - - :type output_bucket: string - :param output_bucket: The Amazon S3 bucket in which you want Elastic - Transcoder to save the transcoded files. (Use this, or use - ContentConfig:Bucket plus ThumbnailConfig:Bucket.) - Specify this value when all of the following are true: - - + You want to save transcoded files, thumbnails (if any), and playlists - (if any) together in one bucket. - + You do not want to specify the users or groups who have access to the - transcoded files, thumbnails, and playlists. - + You do not want to specify the permissions that Elastic Transcoder - grants to the files. When Elastic Transcoder saves files in - `OutputBucket`, it grants full control over the files only to the - AWS account that owns the role that is specified by `Role`. - + You want to associate the transcoded files and thumbnails with the - Amazon S3 Standard storage class. - - - - If you want to save transcoded files and playlists in one bucket and - thumbnails in another bucket, specify which users can access the - transcoded files or the permissions the users have, or change the - Amazon S3 storage class, omit `OutputBucket` and specify values for - `ContentConfig` and `ThumbnailConfig` instead. - - :type role: string - :param role: The IAM Amazon Resource Name (ARN) for the role that you - want Elastic Transcoder to use to create the pipeline. - - :type notifications: dict - :param notifications: - The Amazon Simple Notification Service (Amazon SNS) topic that you want - to notify to report job status. - To receive notifications, you must also subscribe to the new topic in - the Amazon SNS console. - - + **Progressing**: The topic ARN for the Amazon Simple Notification - Service (Amazon SNS) topic that you want to notify when Elastic - Transcoder has started to process a job in this pipeline. This is - the ARN that Amazon SNS returned when you created the topic. For - more information, see Create a Topic in the Amazon Simple - Notification Service Developer Guide. - + **Completed**: The topic ARN for the Amazon SNS topic that you want - to notify when Elastic Transcoder has finished processing a job in - this pipeline. This is the ARN that Amazon SNS returned when you - created the topic. - + **Warning**: The topic ARN for the Amazon SNS topic that you want to - notify when Elastic Transcoder encounters a warning condition while - processing a job in this pipeline. This is the ARN that Amazon SNS - returned when you created the topic. - + **Error**: The topic ARN for the Amazon SNS topic that you want to - notify when Elastic Transcoder encounters an error condition while - processing a job in this pipeline. This is the ARN that Amazon SNS - returned when you created the topic. - - :type content_config: dict - :param content_config: - The optional `ContentConfig` object specifies information about the - Amazon S3 bucket in which you want Elastic Transcoder to save - transcoded files and playlists: which bucket to use, which users - you want to have access to the files, the type of access you want - users to have, and the storage class that you want to assign to the - files. - - If you specify values for `ContentConfig`, you must also specify values - for `ThumbnailConfig`. - - If you specify values for `ContentConfig` and `ThumbnailConfig`, omit - the `OutputBucket` object. - - - + **Bucket**: The Amazon S3 bucket in which you want Elastic Transcoder - to save transcoded files and playlists. - + **Permissions** (Optional): The Permissions object specifies which - users you want to have access to transcoded files and the type of - access you want them to have. You can grant permissions to a - maximum of 30 users and/or predefined Amazon S3 groups. - + **Grantee Type**: Specify the type of value that appears in the - `Grantee` object: - - + **Canonical**: The value in the `Grantee` object is either the - canonical user ID for an AWS account or an origin access identity - for an Amazon CloudFront distribution. For more information about - canonical user IDs, see Access Control List (ACL) Overview in the - Amazon Simple Storage Service Developer Guide. For more information - about using CloudFront origin access identities to require that - users use CloudFront URLs instead of Amazon S3 URLs, see Using an - Origin Access Identity to Restrict Access to Your Amazon S3 - Content. A canonical user ID is not the same as an AWS account - number. - + **Email**: The value in the `Grantee` object is the registered email - address of an AWS account. - + **Group**: The value in the `Grantee` object is one of the following - predefined Amazon S3 groups: `AllUsers`, `AuthenticatedUsers`, or - `LogDelivery`. - - + **Grantee**: The AWS user or group that you want to have access to - transcoded files and playlists. To identify the user or group, you - can specify the canonical user ID for an AWS account, an origin - access identity for a CloudFront distribution, the registered email - address of an AWS account, or a predefined Amazon S3 group - + **Access**: The permission that you want to give to the AWS user that - you specified in `Grantee`. Permissions are granted on the files - that Elastic Transcoder adds to the bucket, including playlists and - video files. Valid values include: - - + `READ`: The grantee can read the objects and metadata for objects - that Elastic Transcoder adds to the Amazon S3 bucket. - + `READ_ACP`: The grantee can read the object ACL for objects that - Elastic Transcoder adds to the Amazon S3 bucket. - + `WRITE_ACP`: The grantee can write the ACL for the objects that - Elastic Transcoder adds to the Amazon S3 bucket. - + `FULL_CONTROL`: The grantee has `READ`, `READ_ACP`, and `WRITE_ACP` - permissions for the objects that Elastic Transcoder adds to the - Amazon S3 bucket. - - + **StorageClass**: The Amazon S3 storage class, `Standard` or - `ReducedRedundancy`, that you want Elastic Transcoder to assign to - the video files and playlists that it stores in your Amazon S3 - bucket. - - :type thumbnail_config: dict - :param thumbnail_config: - The `ThumbnailConfig` object specifies several values, including the - Amazon S3 bucket in which you want Elastic Transcoder to save - thumbnail files, which users you want to have access to the files, - the type of access you want users to have, and the storage class - that you want to assign to the files. - - If you specify values for `ContentConfig`, you must also specify values - for `ThumbnailConfig` even if you don't want to create thumbnails. - - If you specify values for `ContentConfig` and `ThumbnailConfig`, omit - the `OutputBucket` object. - - - + **Bucket**: The Amazon S3 bucket in which you want Elastic Transcoder - to save thumbnail files. - + **Permissions** (Optional): The `Permissions` object specifies which - users and/or predefined Amazon S3 groups you want to have access to - thumbnail files, and the type of access you want them to have. You - can grant permissions to a maximum of 30 users and/or predefined - Amazon S3 groups. - + **GranteeType**: Specify the type of value that appears in the - Grantee object: - - + **Canonical**: The value in the `Grantee` object is either the - canonical user ID for an AWS account or an origin access identity - for an Amazon CloudFront distribution. A canonical user ID is not - the same as an AWS account number. - + **Email**: The value in the `Grantee` object is the registered email - address of an AWS account. - + **Group**: The value in the `Grantee` object is one of the following - predefined Amazon S3 groups: `AllUsers`, `AuthenticatedUsers`, or - `LogDelivery`. - - + **Grantee**: The AWS user or group that you want to have access to - thumbnail files. To identify the user or group, you can specify the - canonical user ID for an AWS account, an origin access identity for - a CloudFront distribution, the registered email address of an AWS - account, or a predefined Amazon S3 group. - + **Access**: The permission that you want to give to the AWS user that - you specified in `Grantee`. Permissions are granted on the - thumbnail files that Elastic Transcoder adds to the bucket. Valid - values include: - - + `READ`: The grantee can read the thumbnails and metadata for objects - that Elastic Transcoder adds to the Amazon S3 bucket. - + `READ_ACP`: The grantee can read the object ACL for thumbnails that - Elastic Transcoder adds to the Amazon S3 bucket. - + `WRITE_ACP`: The grantee can write the ACL for the thumbnails that - Elastic Transcoder adds to the Amazon S3 bucket. - + `FULL_CONTROL`: The grantee has `READ`, `READ_ACP`, and `WRITE_ACP` - permissions for the thumbnails that Elastic Transcoder adds to the - Amazon S3 bucket. - - + **StorageClass**: The Amazon S3 storage class, `Standard` or - `ReducedRedundancy`, that you want Elastic Transcoder to assign to - the thumbnails that it stores in your Amazon S3 bucket. - - """ - uri = '/2012-09-25/pipelines' - params = {} - if name is not None: - params['Name'] = name - if input_bucket is not None: - params['InputBucket'] = input_bucket - if output_bucket is not None: - params['OutputBucket'] = output_bucket - if role is not None: - params['Role'] = role - if notifications is not None: - params['Notifications'] = notifications - if content_config is not None: - params['ContentConfig'] = content_config - if thumbnail_config is not None: - params['ThumbnailConfig'] = thumbnail_config - return self.make_request('POST', uri, expected_status=201, - data=json.dumps(params)) - - def create_preset(self, name=None, description=None, container=None, - video=None, audio=None, thumbnails=None): - """ - The CreatePreset operation creates a preset with settings that - you specify. - Elastic Transcoder checks the CreatePreset settings to ensure - that they meet Elastic Transcoder requirements and to - determine whether they comply with H.264 standards. If your - settings are not valid for Elastic Transcoder, Elastic - Transcoder returns an HTTP 400 response ( - `ValidationException`) and does not create the preset. If the - settings are valid for Elastic Transcoder but aren't strictly - compliant with the H.264 standard, Elastic Transcoder creates - the preset and returns a warning message in the response. This - helps you determine whether your settings comply with the - H.264 standard while giving you greater flexibility with - respect to the video that Elastic Transcoder produces. - Elastic Transcoder uses the H.264 video-compression format. - For more information, see the International Telecommunication - Union publication Recommendation ITU-T H.264: Advanced video - coding for generic audiovisual services . - - :type name: string - :param name: The name of the preset. We recommend that the name be - unique within the AWS account, but uniqueness is not enforced. - - :type description: string - :param description: A description of the preset. - - :type container: string - :param container: The container type for the output file. Valid values - include `mp3`, `mp4`, `ogg`, `ts`, and `webm`. - - :type video: dict - :param video: A section of the request body that specifies the video - parameters. - - :type audio: dict - :param audio: A section of the request body that specifies the audio - parameters. - - :type thumbnails: dict - :param thumbnails: A section of the request body that specifies the - thumbnail parameters, if any. - - """ - uri = '/2012-09-25/presets' - params = {} - if name is not None: - params['Name'] = name - if description is not None: - params['Description'] = description - if container is not None: - params['Container'] = container - if video is not None: - params['Video'] = video - if audio is not None: - params['Audio'] = audio - if thumbnails is not None: - params['Thumbnails'] = thumbnails - return self.make_request('POST', uri, expected_status=201, - data=json.dumps(params)) - - def delete_pipeline(self, id=None): - """ - The DeletePipeline operation removes a pipeline. - - You can only delete a pipeline that has never been used or - that is not currently in use (doesn't contain any active - jobs). If the pipeline is currently in use, `DeletePipeline` - returns an error. - - :type id: string - :param id: The identifier of the pipeline that you want to delete. - - """ - uri = '/2012-09-25/pipelines/{0}'.format(id) - return self.make_request('DELETE', uri, expected_status=202) - - def delete_preset(self, id=None): - """ - The DeletePreset operation removes a preset that you've added - in an AWS region. - - You can't delete the default presets that are included with - Elastic Transcoder. - - :type id: string - :param id: The identifier of the preset for which you want to get - detailed information. - - """ - uri = '/2012-09-25/presets/{0}'.format(id) - return self.make_request('DELETE', uri, expected_status=202) - - def list_jobs_by_pipeline(self, pipeline_id=None, ascending=None, - page_token=None): - """ - The ListJobsByPipeline operation gets a list of the jobs - currently in a pipeline. - - Elastic Transcoder returns all of the jobs currently in the - specified pipeline. The response body contains one element for - each job that satisfies the search criteria. - - :type pipeline_id: string - :param pipeline_id: The ID of the pipeline for which you want to get - job information. - - :type ascending: string - :param ascending: To list jobs in chronological order by the date and - time that they were submitted, enter `True`. To list jobs in - reverse chronological order, enter `False`. - - :type page_token: string - :param page_token: When Elastic Transcoder returns more than one page - of results, use `pageToken` in subsequent `GET` requests to get - each successive page of results. - - """ - uri = '/2012-09-25/jobsByPipeline/{0}'.format(pipeline_id) - params = {} - if pipeline_id is not None: - params['PipelineId'] = pipeline_id - if ascending is not None: - params['Ascending'] = ascending - if page_token is not None: - params['PageToken'] = page_token - return self.make_request('GET', uri, expected_status=200, - params=params) - - def list_jobs_by_status(self, status=None, ascending=None, - page_token=None): - """ - The ListJobsByStatus operation gets a list of jobs that have a - specified status. The response body contains one element for - each job that satisfies the search criteria. - - :type status: string - :param status: To get information about all of the jobs associated with - the current AWS account that have a given status, specify the - following status: `Submitted`, `Progressing`, `Complete`, - `Canceled`, or `Error`. - - :type ascending: string - :param ascending: To list jobs in chronological order by the date and - time that they were submitted, enter `True`. To list jobs in - reverse chronological order, enter `False`. - - :type page_token: string - :param page_token: When Elastic Transcoder returns more than one page - of results, use `pageToken` in subsequent `GET` requests to get - each successive page of results. - - """ - uri = '/2012-09-25/jobsByStatus/{0}'.format(status) - params = {} - if status is not None: - params['Status'] = status - if ascending is not None: - params['Ascending'] = ascending - if page_token is not None: - params['PageToken'] = page_token - return self.make_request('GET', uri, expected_status=200, - params=params) - - def list_pipelines(self, ascending=None, page_token=None): - """ - The ListPipelines operation gets a list of the pipelines - associated with the current AWS account. - - :type ascending: string - :param ascending: To list pipelines in chronological order by the date - and time that they were created, enter `True`. To list pipelines in - reverse chronological order, enter `False`. - - :type page_token: string - :param page_token: When Elastic Transcoder returns more than one page - of results, use `pageToken` in subsequent `GET` requests to get - each successive page of results. - - """ - uri = '/2012-09-25/pipelines'.format() - params = {} - if ascending is not None: - params['Ascending'] = ascending - if page_token is not None: - params['PageToken'] = page_token - return self.make_request('GET', uri, expected_status=200, - params=params) - - def list_presets(self, ascending=None, page_token=None): - """ - The ListPresets operation gets a list of the default presets - included with Elastic Transcoder and the presets that you've - added in an AWS region. - - :type ascending: string - :param ascending: To list presets in chronological order by the date - and time that they were created, enter `True`. To list presets in - reverse chronological order, enter `False`. - - :type page_token: string - :param page_token: When Elastic Transcoder returns more than one page - of results, use `pageToken` in subsequent `GET` requests to get - each successive page of results. - - """ - uri = '/2012-09-25/presets'.format() - params = {} - if ascending is not None: - params['Ascending'] = ascending - if page_token is not None: - params['PageToken'] = page_token - return self.make_request('GET', uri, expected_status=200, - params=params) - - def read_job(self, id=None): - """ - The ReadJob operation returns detailed information about a - job. - - :type id: string - :param id: The identifier of the job for which you want to get detailed - information. - - """ - uri = '/2012-09-25/jobs/{0}'.format(id) - return self.make_request('GET', uri, expected_status=200) - - def read_pipeline(self, id=None): - """ - The ReadPipeline operation gets detailed information about a - pipeline. - - :type id: string - :param id: The identifier of the pipeline to read. - - """ - uri = '/2012-09-25/pipelines/{0}'.format(id) - return self.make_request('GET', uri, expected_status=200) - - def read_preset(self, id=None): - """ - The ReadPreset operation gets detailed information about a - preset. - - :type id: string - :param id: The identifier of the preset for which you want to get - detailed information. - - """ - uri = '/2012-09-25/presets/{0}'.format(id) - return self.make_request('GET', uri, expected_status=200) - - def test_role(self, role=None, input_bucket=None, output_bucket=None, - topics=None): - """ - The TestRole operation tests the IAM role used to create the - pipeline. - - The `TestRole` action lets you determine whether the IAM role - you are using has sufficient permissions to let Elastic - Transcoder perform tasks associated with the transcoding - process. The action attempts to assume the specified IAM role, - checks read access to the input and output buckets, and tries - to send a test notification to Amazon SNS topics that you - specify. - - :type role: string - :param role: The IAM Amazon Resource Name (ARN) for the role that you - want Elastic Transcoder to test. - - :type input_bucket: string - :param input_bucket: The Amazon S3 bucket that contains media files to - be transcoded. The action attempts to read from this bucket. - - :type output_bucket: string - :param output_bucket: The Amazon S3 bucket that Elastic Transcoder will - write transcoded media files to. The action attempts to read from - this bucket. - - :type topics: list - :param topics: The ARNs of one or more Amazon Simple Notification - Service (Amazon SNS) topics that you want the action to send a test - notification to. - - """ - uri = '/2012-09-25/roleTests' - params = {} - if role is not None: - params['Role'] = role - if input_bucket is not None: - params['InputBucket'] = input_bucket - if output_bucket is not None: - params['OutputBucket'] = output_bucket - if topics is not None: - params['Topics'] = topics - return self.make_request('POST', uri, expected_status=200, - data=json.dumps(params)) - - def update_pipeline(self, id, name=None, input_bucket=None, role=None, - notifications=None, content_config=None, - thumbnail_config=None): - """ - Use the `UpdatePipeline` operation to update settings for a - pipeline. When you change pipeline settings, your changes take - effect immediately. Jobs that you have already submitted and - that Elastic Transcoder has not started to process are - affected in addition to jobs that you submit after you change - settings. - - :type id: string - :param id: The ID of the pipeline that you want to update. - - :type name: string - :param name: The name of the pipeline. We recommend that the name be - unique within the AWS account, but uniqueness is not enforced. - Constraints: Maximum 40 characters - - :type input_bucket: string - :param input_bucket: The Amazon S3 bucket in which you saved the media - files that you want to transcode and the graphics that you want to - use as watermarks. - - :type role: string - :param role: The IAM Amazon Resource Name (ARN) for the role that you - want Elastic Transcoder to use to transcode jobs for this pipeline. - - :type notifications: dict - :param notifications: - The Amazon Simple Notification Service (Amazon SNS) topic or topics to - notify in order to report job status. - To receive notifications, you must also subscribe to the new topic in - the Amazon SNS console. - - :type content_config: dict - :param content_config: - The optional `ContentConfig` object specifies information about the - Amazon S3 bucket in which you want Elastic Transcoder to save - transcoded files and playlists: which bucket to use, which users - you want to have access to the files, the type of access you want - users to have, and the storage class that you want to assign to the - files. - - If you specify values for `ContentConfig`, you must also specify values - for `ThumbnailConfig`. - - If you specify values for `ContentConfig` and `ThumbnailConfig`, omit - the `OutputBucket` object. - - - + **Bucket**: The Amazon S3 bucket in which you want Elastic Transcoder - to save transcoded files and playlists. - + **Permissions** (Optional): The Permissions object specifies which - users you want to have access to transcoded files and the type of - access you want them to have. You can grant permissions to a - maximum of 30 users and/or predefined Amazon S3 groups. - + **Grantee Type**: Specify the type of value that appears in the - `Grantee` object: - - + **Canonical**: The value in the `Grantee` object is either the - canonical user ID for an AWS account or an origin access identity - for an Amazon CloudFront distribution. For more information about - canonical user IDs, see Access Control List (ACL) Overview in the - Amazon Simple Storage Service Developer Guide. For more information - about using CloudFront origin access identities to require that - users use CloudFront URLs instead of Amazon S3 URLs, see Using an - Origin Access Identity to Restrict Access to Your Amazon S3 - Content. A canonical user ID is not the same as an AWS account - number. - + **Email**: The value in the `Grantee` object is the registered email - address of an AWS account. - + **Group**: The value in the `Grantee` object is one of the following - predefined Amazon S3 groups: `AllUsers`, `AuthenticatedUsers`, or - `LogDelivery`. - - + **Grantee**: The AWS user or group that you want to have access to - transcoded files and playlists. To identify the user or group, you - can specify the canonical user ID for an AWS account, an origin - access identity for a CloudFront distribution, the registered email - address of an AWS account, or a predefined Amazon S3 group - + **Access**: The permission that you want to give to the AWS user that - you specified in `Grantee`. Permissions are granted on the files - that Elastic Transcoder adds to the bucket, including playlists and - video files. Valid values include: - - + `READ`: The grantee can read the objects and metadata for objects - that Elastic Transcoder adds to the Amazon S3 bucket. - + `READ_ACP`: The grantee can read the object ACL for objects that - Elastic Transcoder adds to the Amazon S3 bucket. - + `WRITE_ACP`: The grantee can write the ACL for the objects that - Elastic Transcoder adds to the Amazon S3 bucket. - + `FULL_CONTROL`: The grantee has `READ`, `READ_ACP`, and `WRITE_ACP` - permissions for the objects that Elastic Transcoder adds to the - Amazon S3 bucket. - - + **StorageClass**: The Amazon S3 storage class, `Standard` or - `ReducedRedundancy`, that you want Elastic Transcoder to assign to - the video files and playlists that it stores in your Amazon S3 - bucket. - - :type thumbnail_config: dict - :param thumbnail_config: - The `ThumbnailConfig` object specifies several values, including the - Amazon S3 bucket in which you want Elastic Transcoder to save - thumbnail files, which users you want to have access to the files, - the type of access you want users to have, and the storage class - that you want to assign to the files. - - If you specify values for `ContentConfig`, you must also specify values - for `ThumbnailConfig` even if you don't want to create thumbnails. - - If you specify values for `ContentConfig` and `ThumbnailConfig`, omit - the `OutputBucket` object. - - - + **Bucket**: The Amazon S3 bucket in which you want Elastic Transcoder - to save thumbnail files. - + **Permissions** (Optional): The `Permissions` object specifies which - users and/or predefined Amazon S3 groups you want to have access to - thumbnail files, and the type of access you want them to have. You - can grant permissions to a maximum of 30 users and/or predefined - Amazon S3 groups. - + **GranteeType**: Specify the type of value that appears in the - Grantee object: - - + **Canonical**: The value in the `Grantee` object is either the - canonical user ID for an AWS account or an origin access identity - for an Amazon CloudFront distribution. A canonical user ID is not - the same as an AWS account number. - + **Email**: The value in the `Grantee` object is the registered email - address of an AWS account. - + **Group**: The value in the `Grantee` object is one of the following - predefined Amazon S3 groups: `AllUsers`, `AuthenticatedUsers`, or - `LogDelivery`. - - + **Grantee**: The AWS user or group that you want to have access to - thumbnail files. To identify the user or group, you can specify the - canonical user ID for an AWS account, an origin access identity for - a CloudFront distribution, the registered email address of an AWS - account, or a predefined Amazon S3 group. - + **Access**: The permission that you want to give to the AWS user that - you specified in `Grantee`. Permissions are granted on the - thumbnail files that Elastic Transcoder adds to the bucket. Valid - values include: - - + `READ`: The grantee can read the thumbnails and metadata for objects - that Elastic Transcoder adds to the Amazon S3 bucket. - + `READ_ACP`: The grantee can read the object ACL for thumbnails that - Elastic Transcoder adds to the Amazon S3 bucket. - + `WRITE_ACP`: The grantee can write the ACL for the thumbnails that - Elastic Transcoder adds to the Amazon S3 bucket. - + `FULL_CONTROL`: The grantee has `READ`, `READ_ACP`, and `WRITE_ACP` - permissions for the thumbnails that Elastic Transcoder adds to the - Amazon S3 bucket. - - + **StorageClass**: The Amazon S3 storage class, `Standard` or - `ReducedRedundancy`, that you want Elastic Transcoder to assign to - the thumbnails that it stores in your Amazon S3 bucket. - - """ - uri = '/2012-09-25/pipelines/{0}'.format(id) - params = {} - if name is not None: - params['Name'] = name - if input_bucket is not None: - params['InputBucket'] = input_bucket - if role is not None: - params['Role'] = role - if notifications is not None: - params['Notifications'] = notifications - if content_config is not None: - params['ContentConfig'] = content_config - if thumbnail_config is not None: - params['ThumbnailConfig'] = thumbnail_config - return self.make_request('PUT', uri, expected_status=200, - data=json.dumps(params)) - - def update_pipeline_notifications(self, id=None, notifications=None): - """ - With the UpdatePipelineNotifications operation, you can update - Amazon Simple Notification Service (Amazon SNS) notifications - for a pipeline. - - When you update notifications for a pipeline, Elastic - Transcoder returns the values that you specified in the - request. - - :type id: string - :param id: The identifier of the pipeline for which you want to change - notification settings. - - :type notifications: dict - :param notifications: - The topic ARN for the Amazon Simple Notification Service (Amazon SNS) - topic that you want to notify to report job status. - To receive notifications, you must also subscribe to the new topic in - the Amazon SNS console. - - + **Progressing**: The topic ARN for the Amazon Simple Notification - Service (Amazon SNS) topic that you want to notify when Elastic - Transcoder has started to process jobs that are added to this - pipeline. This is the ARN that Amazon SNS returned when you created - the topic. - + **Completed**: The topic ARN for the Amazon SNS topic that you want - to notify when Elastic Transcoder has finished processing a job. - This is the ARN that Amazon SNS returned when you created the - topic. - + **Warning**: The topic ARN for the Amazon SNS topic that you want to - notify when Elastic Transcoder encounters a warning condition. This - is the ARN that Amazon SNS returned when you created the topic. - + **Error**: The topic ARN for the Amazon SNS topic that you want to - notify when Elastic Transcoder encounters an error condition. This - is the ARN that Amazon SNS returned when you created the topic. - - """ - uri = '/2012-09-25/pipelines/{0}/notifications'.format(id) - params = {} - if id is not None: - params['Id'] = id - if notifications is not None: - params['Notifications'] = notifications - return self.make_request('POST', uri, expected_status=200, - data=json.dumps(params)) - - def update_pipeline_status(self, id=None, status=None): - """ - The UpdatePipelineStatus operation pauses or reactivates a - pipeline, so that the pipeline stops or restarts the - processing of jobs. - - Changing the pipeline status is useful if you want to cancel - one or more jobs. You can't cancel jobs after Elastic - Transcoder has started processing them; if you pause the - pipeline to which you submitted the jobs, you have more time - to get the job IDs for the jobs that you want to cancel, and - to send a CancelJob request. - - :type id: string - :param id: The identifier of the pipeline to update. - - :type status: string - :param status: - The desired status of the pipeline: - - - + `Active`: The pipeline is processing jobs. - + `Paused`: The pipeline is not currently processing jobs. - - """ - uri = '/2012-09-25/pipelines/{0}/status'.format(id) - params = {} - if id is not None: - params['Id'] = id - if status is not None: - params['Status'] = status - return self.make_request('POST', uri, expected_status=200, - data=json.dumps(params)) - - def make_request(self, verb, resource, headers=None, data='', - expected_status=None, params=None): - if headers is None: - headers = {} - response = super(ElasticTranscoderConnection, self).make_request( - verb, resource, headers=headers, data=data, params=params) - body = json.loads(response.read().decode('utf-8')) - if response.status == expected_status: - return body - else: - error_type = response.getheader('x-amzn-ErrorType').split(':')[0] - error_class = self._faults.get(error_type, self.ResponseError) - raise error_class(response.status, response.reason, body) diff --git a/awx/lib/site-packages/boto/emr/__init__.py b/awx/lib/site-packages/boto/emr/__init__.py deleted file mode 100644 index 5f3181d289..0000000000 --- a/awx/lib/site-packages/boto/emr/__init__.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2010 Spotify AB -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -This module provies an interface to the Elastic MapReduce (EMR) -service from AWS. -""" -from boto.emr.connection import EmrConnection -from boto.emr.step import Step, StreamingStep, JarStep -from boto.emr.bootstrap_action import BootstrapAction -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon Elastic MapReduce service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - return get_regions('elasticmapreduce', connection_cls=EmrConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/emr/bootstrap_action.py b/awx/lib/site-packages/boto/emr/bootstrap_action.py deleted file mode 100644 index 5a01fd21cc..0000000000 --- a/awx/lib/site-packages/boto/emr/bootstrap_action.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2010 Spotify AB -# Copyright (c) 2010 Yelp -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.compat import six - -class BootstrapAction(object): - def __init__(self, name, path, bootstrap_action_args): - self.name = name - self.path = path - - if isinstance(bootstrap_action_args, six.string_types): - bootstrap_action_args = [bootstrap_action_args] - - self.bootstrap_action_args = bootstrap_action_args - - def args(self): - args = [] - - if self.bootstrap_action_args: - args.extend(self.bootstrap_action_args) - - return args - - def __repr__(self): - return '%s.%s(name=%r, path=%r, bootstrap_action_args=%r)' % ( - self.__class__.__module__, self.__class__.__name__, - self.name, self.path, self.bootstrap_action_args) diff --git a/awx/lib/site-packages/boto/emr/connection.py b/awx/lib/site-packages/boto/emr/connection.py deleted file mode 100644 index d15852ea25..0000000000 --- a/awx/lib/site-packages/boto/emr/connection.py +++ /dev/null @@ -1,754 +0,0 @@ -# Copyright (c) 2010 Spotify AB -# Copyright (c) 2010-2011 Yelp -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a connection to the EMR service -""" -import types - -import boto -import boto.utils -from boto.ec2.regioninfo import RegionInfo -from boto.emr.emrobject import AddInstanceGroupsResponse, BootstrapActionList, \ - Cluster, ClusterSummaryList, HadoopStep, \ - InstanceGroupList, InstanceList, JobFlow, \ - JobFlowStepList, \ - ModifyInstanceGroupsResponse, \ - RunJobFlowResponse, StepSummaryList -from boto.emr.step import JarStep -from boto.connection import AWSQueryConnection -from boto.exception import EmrResponseError -from boto.compat import six - - -class EmrConnection(AWSQueryConnection): - - APIVersion = boto.config.get('Boto', 'emr_version', '2009-03-31') - DefaultRegionName = boto.config.get('Boto', 'emr_region_name', 'us-east-1') - DefaultRegionEndpoint = boto.config.get('Boto', 'emr_region_endpoint', - 'elasticmapreduce.us-east-1.amazonaws.com') - ResponseError = EmrResponseError - - # Constants for AWS Console debugging - DebuggingJar = 's3n://us-east-1.elasticmapreduce/libs/script-runner/script-runner.jar' - DebuggingArgs = 's3n://us-east-1.elasticmapreduce/libs/state-pusher/0.1/fetch' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, profile_name=None): - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - super(EmrConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token, - validate_certs=validate_certs, - profile_name=profile_name) - # Many of the EMR hostnames are of the form: - # <region>.<service_name>.amazonaws.com - # rather than the more common: - # <service_name>.<region>.amazonaws.com - # so we need to explicitly set the region_name and service_name - # for the SigV4 signing. - self.auth_region_name = self.region.name - self.auth_service_name = 'elasticmapreduce' - - def _required_auth_capability(self): - return ['hmac-v4'] - - def describe_cluster(self, cluster_id): - """ - Describes an Elastic MapReduce cluster - - :type cluster_id: str - :param cluster_id: The cluster id of interest - """ - params = { - 'ClusterId': cluster_id - } - return self.get_object('DescribeCluster', params, Cluster) - - def describe_jobflow(self, jobflow_id): - """ - Describes a single Elastic MapReduce job flow - - :type jobflow_id: str - :param jobflow_id: The job flow id of interest - """ - jobflows = self.describe_jobflows(jobflow_ids=[jobflow_id]) - if jobflows: - return jobflows[0] - - def describe_jobflows(self, states=None, jobflow_ids=None, - created_after=None, created_before=None): - """ - Retrieve all the Elastic MapReduce job flows on your account - - :type states: list - :param states: A list of strings with job flow states wanted - - :type jobflow_ids: list - :param jobflow_ids: A list of job flow IDs - :type created_after: datetime - :param created_after: Bound on job flow creation time - - :type created_before: datetime - :param created_before: Bound on job flow creation time - """ - params = {} - - if states: - self.build_list_params(params, states, 'JobFlowStates.member') - if jobflow_ids: - self.build_list_params(params, jobflow_ids, 'JobFlowIds.member') - if created_after: - params['CreatedAfter'] = created_after.strftime( - boto.utils.ISO8601) - if created_before: - params['CreatedBefore'] = created_before.strftime( - boto.utils.ISO8601) - - return self.get_list('DescribeJobFlows', params, [('member', JobFlow)]) - - def describe_step(self, cluster_id, step_id): - """ - Describe an Elastic MapReduce step - - :type cluster_id: str - :param cluster_id: The cluster id of interest - :type step_id: str - :param step_id: The step id of interest - """ - params = { - 'ClusterId': cluster_id, - 'StepId': step_id - } - - return self.get_object('DescribeStep', params, HadoopStep) - - def list_bootstrap_actions(self, cluster_id, marker=None): - """ - Get a list of bootstrap actions for an Elastic MapReduce cluster - - :type cluster_id: str - :param cluster_id: The cluster id of interest - :type marker: str - :param marker: Pagination marker - """ - params = { - 'ClusterId': cluster_id - } - - if marker: - params['Marker'] = marker - - return self.get_object('ListBootstrapActions', params, BootstrapActionList) - - def list_clusters(self, created_after=None, created_before=None, - cluster_states=None, marker=None): - """ - List Elastic MapReduce clusters with optional filtering - - :type created_after: datetime - :param created_after: Bound on cluster creation time - :type created_before: datetime - :param created_before: Bound on cluster creation time - :type cluster_states: list - :param cluster_states: Bound on cluster states - :type marker: str - :param marker: Pagination marker - """ - params = {} - if created_after: - params['CreatedAfter'] = created_after.strftime( - boto.utils.ISO8601) - if created_before: - params['CreatedBefore'] = created_before.strftime( - boto.utils.ISO8601) - if marker: - params['Marker'] = marker - - if cluster_states: - self.build_list_params(params, cluster_states, 'ClusterStates.member') - - return self.get_object('ListClusters', params, ClusterSummaryList) - - def list_instance_groups(self, cluster_id, marker=None): - """ - List EC2 instance groups in a cluster - - :type cluster_id: str - :param cluster_id: The cluster id of interest - :type marker: str - :param marker: Pagination marker - """ - params = { - 'ClusterId': cluster_id - } - - if marker: - params['Marker'] = marker - - return self.get_object('ListInstanceGroups', params, InstanceGroupList) - - def list_instances(self, cluster_id, instance_group_id=None, - instance_group_types=None, marker=None): - """ - List EC2 instances in a cluster - - :type cluster_id: str - :param cluster_id: The cluster id of interest - :type instance_group_id: str - :param instance_group_id: The EC2 instance group id of interest - :type instance_group_types: list - :param instance_group_types: Filter by EC2 instance group type - :type marker: str - :param marker: Pagination marker - """ - params = { - 'ClusterId': cluster_id - } - - if instance_group_id: - params['InstanceGroupId'] = instance_group_id - if marker: - params['Marker'] = marker - - if instance_group_types: - self.build_list_params(params, instance_group_types, - 'InstanceGroupTypeList.member') - - return self.get_object('ListInstances', params, InstanceList) - - def list_steps(self, cluster_id, step_states=None, marker=None): - """ - List cluster steps - - :type cluster_id: str - :param cluster_id: The cluster id of interest - :type step_states: list - :param step_states: Filter by step states - :type marker: str - :param marker: Pagination marker - """ - params = { - 'ClusterId': cluster_id - } - - if marker: - params['Marker'] = marker - - if step_states: - self.build_list_params(params, step_states, 'StepStateList.member') - - return self.get_object('ListSteps', params, StepSummaryList) - - def add_tags(self, resource_id, tags): - """ - Create new metadata tags for the specified resource id. - - :type resource_id: str - :param resource_id: The cluster id - - :type tags: dict - :param tags: A dictionary containing the name/value pairs. - If you want to create only a tag name, the - value for that tag should be the empty string - (e.g. '') or None. - """ - assert isinstance(resource_id, six.string_types) - params = { - 'ResourceId': resource_id, - } - params.update(self._build_tag_list(tags)) - return self.get_status('AddTags', params, verb='POST') - - def remove_tags(self, resource_id, tags): - """ - Remove metadata tags for the specified resource id. - - :type resource_id: str - :param resource_id: The cluster id - - :type tags: list - :param tags: A list of tag names to remove. - """ - params = { - 'ResourceId': resource_id, - } - params.update(self._build_string_list('TagKeys', tags)) - return self.get_status('RemoveTags', params, verb='POST') - - def terminate_jobflow(self, jobflow_id): - """ - Terminate an Elastic MapReduce job flow - - :type jobflow_id: str - :param jobflow_id: A jobflow id - """ - self.terminate_jobflows([jobflow_id]) - - def terminate_jobflows(self, jobflow_ids): - """ - Terminate an Elastic MapReduce job flow - - :type jobflow_ids: list - :param jobflow_ids: A list of job flow IDs - """ - params = {} - self.build_list_params(params, jobflow_ids, 'JobFlowIds.member') - return self.get_status('TerminateJobFlows', params, verb='POST') - - def add_jobflow_steps(self, jobflow_id, steps): - """ - Adds steps to a jobflow - - :type jobflow_id: str - :param jobflow_id: The job flow id - :type steps: list(boto.emr.Step) - :param steps: A list of steps to add to the job - """ - if not isinstance(steps, list): - steps = [steps] - params = {} - params['JobFlowId'] = jobflow_id - - # Step args - step_args = [self._build_step_args(step) for step in steps] - params.update(self._build_step_list(step_args)) - - return self.get_object( - 'AddJobFlowSteps', params, JobFlowStepList, verb='POST') - - def add_instance_groups(self, jobflow_id, instance_groups): - """ - Adds instance groups to a running cluster. - - :type jobflow_id: str - :param jobflow_id: The id of the jobflow which will take the - new instance groups - - :type instance_groups: list(boto.emr.InstanceGroup) - :param instance_groups: A list of instance groups to add to the job - """ - if not isinstance(instance_groups, list): - instance_groups = [instance_groups] - params = {} - params['JobFlowId'] = jobflow_id - params.update(self._build_instance_group_list_args(instance_groups)) - - return self.get_object('AddInstanceGroups', params, - AddInstanceGroupsResponse, verb='POST') - - def modify_instance_groups(self, instance_group_ids, new_sizes): - """ - Modify the number of nodes and configuration settings in an - instance group. - - :type instance_group_ids: list(str) - :param instance_group_ids: A list of the ID's of the instance - groups to be modified - - :type new_sizes: list(int) - :param new_sizes: A list of the new sizes for each instance group - """ - if not isinstance(instance_group_ids, list): - instance_group_ids = [instance_group_ids] - if not isinstance(new_sizes, list): - new_sizes = [new_sizes] - - instance_groups = zip(instance_group_ids, new_sizes) - - params = {} - for k, ig in enumerate(instance_groups): - # could be wrong - the example amazon gives uses - # InstanceRequestCount, while the api documentation - # says InstanceCount - params['InstanceGroups.member.%d.InstanceGroupId' % (k+1) ] = ig[0] - params['InstanceGroups.member.%d.InstanceCount' % (k+1) ] = ig[1] - - return self.get_object('ModifyInstanceGroups', params, - ModifyInstanceGroupsResponse, verb='POST') - - def run_jobflow(self, name, log_uri=None, ec2_keyname=None, - availability_zone=None, - master_instance_type='m1.small', - slave_instance_type='m1.small', num_instances=1, - action_on_failure='TERMINATE_JOB_FLOW', keep_alive=False, - enable_debugging=False, - hadoop_version=None, - steps=[], - bootstrap_actions=[], - instance_groups=None, - additional_info=None, - ami_version=None, - api_params=None, - visible_to_all_users=None, - job_flow_role=None, - service_role=None): - """ - Runs a job flow - :type name: str - :param name: Name of the job flow - - :type log_uri: str - :param log_uri: URI of the S3 bucket to place logs - - :type ec2_keyname: str - :param ec2_keyname: EC2 key used for the instances - - :type availability_zone: str - :param availability_zone: EC2 availability zone of the cluster - - :type master_instance_type: str - :param master_instance_type: EC2 instance type of the master - - :type slave_instance_type: str - :param slave_instance_type: EC2 instance type of the slave nodes - - :type num_instances: int - :param num_instances: Number of instances in the Hadoop cluster - - :type action_on_failure: str - :param action_on_failure: Action to take if a step terminates - - :type keep_alive: bool - :param keep_alive: Denotes whether the cluster should stay - alive upon completion - - :type enable_debugging: bool - :param enable_debugging: Denotes whether AWS console debugging - should be enabled. - - :type hadoop_version: str - :param hadoop_version: Version of Hadoop to use. This no longer - defaults to '0.20' and now uses the AMI default. - - :type steps: list(boto.emr.Step) - :param steps: List of steps to add with the job - - :type bootstrap_actions: list(boto.emr.BootstrapAction) - :param bootstrap_actions: List of bootstrap actions that run - before Hadoop starts. - - :type instance_groups: list(boto.emr.InstanceGroup) - :param instance_groups: Optional list of instance groups to - use when creating this job. - NB: When provided, this argument supersedes num_instances - and master/slave_instance_type. - - :type ami_version: str - :param ami_version: Amazon Machine Image (AMI) version to use - for instances. Values accepted by EMR are '1.0', '2.0', and - 'latest'; EMR currently defaults to '1.0' if you don't set - 'ami_version'. - - :type additional_info: JSON str - :param additional_info: A JSON string for selecting additional features - - :type api_params: dict - :param api_params: a dictionary of additional parameters to pass - directly to the EMR API (so you don't have to upgrade boto to - use new EMR features). You can also delete an API parameter - by setting it to None. - - :type visible_to_all_users: bool - :param visible_to_all_users: Whether the job flow is visible to all IAM - users of the AWS account associated with the job flow. If this - value is set to ``True``, all IAM users of that AWS - account can view and (if they have the proper policy permissions - set) manage the job flow. If it is set to ``False``, only - the IAM user that created the job flow can view and manage - it. - - :type job_flow_role: str - :param job_flow_role: An IAM role for the job flow. The EC2 - instances of the job flow assume this role. The default role is - ``EMRJobflowDefault``. In order to use the default role, - you must have already created it using the CLI. - - :type service_role: str - :param service_role: The IAM role that will be assumed by the Amazon - EMR service to access AWS resources on your behalf. - - :rtype: str - :return: The jobflow id - """ - params = {} - if action_on_failure: - params['ActionOnFailure'] = action_on_failure - if log_uri: - params['LogUri'] = log_uri - params['Name'] = name - - # Common instance args - common_params = self._build_instance_common_args(ec2_keyname, - availability_zone, - keep_alive, - hadoop_version) - params.update(common_params) - - # NB: according to the AWS API's error message, we must - # "configure instances either using instance count, master and - # slave instance type or instance groups but not both." - # - # Thus we switch here on the truthiness of instance_groups. - if not instance_groups: - # Instance args (the common case) - instance_params = self._build_instance_count_and_type_args( - master_instance_type, - slave_instance_type, - num_instances) - params.update(instance_params) - else: - # Instance group args (for spot instances or a heterogenous cluster) - list_args = self._build_instance_group_list_args(instance_groups) - instance_params = dict( - ('Instances.%s' % k, v) for k, v in six.iteritems(list_args) - ) - params.update(instance_params) - - # Debugging step from EMR API docs - if enable_debugging: - debugging_step = JarStep(name='Setup Hadoop Debugging', - action_on_failure='TERMINATE_JOB_FLOW', - main_class=None, - jar=self.DebuggingJar, - step_args=self.DebuggingArgs) - steps.insert(0, debugging_step) - - # Step args - if steps: - step_args = [self._build_step_args(step) for step in steps] - params.update(self._build_step_list(step_args)) - - if bootstrap_actions: - bootstrap_action_args = [self._build_bootstrap_action_args(bootstrap_action) for bootstrap_action in bootstrap_actions] - params.update(self._build_bootstrap_action_list(bootstrap_action_args)) - - if ami_version: - params['AmiVersion'] = ami_version - - if additional_info is not None: - params['AdditionalInfo'] = additional_info - - if api_params: - for key, value in six.iteritems(api_params): - if value is None: - params.pop(key, None) - else: - params[key] = value - - if visible_to_all_users is not None: - if visible_to_all_users: - params['VisibleToAllUsers'] = 'true' - else: - params['VisibleToAllUsers'] = 'false' - - if job_flow_role is not None: - params['JobFlowRole'] = job_flow_role - - if service_role is not None: - params['ServiceRole'] = service_role - - response = self.get_object( - 'RunJobFlow', params, RunJobFlowResponse, verb='POST') - return response.jobflowid - - def set_termination_protection(self, jobflow_id, - termination_protection_status): - """ - Set termination protection on specified Elastic MapReduce job flows - - :type jobflow_ids: list or str - :param jobflow_ids: A list of job flow IDs - - :type termination_protection_status: bool - :param termination_protection_status: Termination protection status - """ - assert termination_protection_status in (True, False) - - params = {} - params['TerminationProtected'] = (termination_protection_status and "true") or "false" - self.build_list_params(params, [jobflow_id], 'JobFlowIds.member') - - return self.get_status('SetTerminationProtection', params, verb='POST') - - def set_visible_to_all_users(self, jobflow_id, visibility): - """ - Set whether specified Elastic Map Reduce job flows are visible to all IAM users - - :type jobflow_ids: list or str - :param jobflow_ids: A list of job flow IDs - - :type visibility: bool - :param visibility: Visibility - """ - assert visibility in (True, False) - - params = {} - params['VisibleToAllUsers'] = (visibility and "true") or "false" - self.build_list_params(params, [jobflow_id], 'JobFlowIds.member') - - return self.get_status('SetVisibleToAllUsers', params, verb='POST') - - def _build_bootstrap_action_args(self, bootstrap_action): - bootstrap_action_params = {} - bootstrap_action_params['ScriptBootstrapAction.Path'] = bootstrap_action.path - - try: - bootstrap_action_params['Name'] = bootstrap_action.name - except AttributeError: - pass - - args = bootstrap_action.args() - if args: - self.build_list_params(bootstrap_action_params, args, 'ScriptBootstrapAction.Args.member') - - return bootstrap_action_params - - def _build_step_args(self, step): - step_params = {} - step_params['ActionOnFailure'] = step.action_on_failure - step_params['HadoopJarStep.Jar'] = step.jar() - - main_class = step.main_class() - if main_class: - step_params['HadoopJarStep.MainClass'] = main_class - - args = step.args() - if args: - self.build_list_params(step_params, args, 'HadoopJarStep.Args.member') - - step_params['Name'] = step.name - return step_params - - def _build_bootstrap_action_list(self, bootstrap_actions): - if not isinstance(bootstrap_actions, list): - bootstrap_actions = [bootstrap_actions] - - params = {} - for i, bootstrap_action in enumerate(bootstrap_actions): - for key, value in six.iteritems(bootstrap_action): - params['BootstrapActions.member.%s.%s' % (i + 1, key)] = value - return params - - def _build_step_list(self, steps): - if not isinstance(steps, list): - steps = [steps] - - params = {} - for i, step in enumerate(steps): - for key, value in six.iteritems(step): - params['Steps.member.%s.%s' % (i+1, key)] = value - return params - - def _build_string_list(self, field, items): - if not isinstance(items, list): - items = [items] - - params = {} - for i, item in enumerate(items): - params['%s.member.%s' % (field, i + 1)] = item - return params - - def _build_tag_list(self, tags): - assert isinstance(tags, dict) - - params = {} - for i, key_value in enumerate(sorted(six.iteritems(tags)), start=1): - key, value = key_value - current_prefix = 'Tags.member.%s' % i - params['%s.Key' % current_prefix] = key - if value: - params['%s.Value' % current_prefix] = value - return params - - def _build_instance_common_args(self, ec2_keyname, availability_zone, - keep_alive, hadoop_version): - """ - Takes a number of parameters used when starting a jobflow (as - specified in run_jobflow() above). Returns a comparable dict for - use in making a RunJobFlow request. - """ - params = { - 'Instances.KeepJobFlowAliveWhenNoSteps': str(keep_alive).lower(), - } - - if hadoop_version: - params['Instances.HadoopVersion'] = hadoop_version - if ec2_keyname: - params['Instances.Ec2KeyName'] = ec2_keyname - if availability_zone: - params['Instances.Placement.AvailabilityZone'] = availability_zone - - return params - - def _build_instance_count_and_type_args(self, master_instance_type, - slave_instance_type, num_instances): - """ - Takes a master instance type (string), a slave instance type - (string), and a number of instances. Returns a comparable dict - for use in making a RunJobFlow request. - """ - params = {'Instances.MasterInstanceType': master_instance_type, - 'Instances.SlaveInstanceType': slave_instance_type, - 'Instances.InstanceCount': num_instances} - return params - - def _build_instance_group_args(self, instance_group): - """ - Takes an InstanceGroup; returns a dict that, when its keys are - properly prefixed, can be used for describing InstanceGroups in - RunJobFlow or AddInstanceGroups requests. - """ - params = {'InstanceCount': instance_group.num_instances, - 'InstanceRole': instance_group.role, - 'InstanceType': instance_group.type, - 'Name': instance_group.name, - 'Market': instance_group.market} - if instance_group.market == 'SPOT': - params['BidPrice'] = instance_group.bidprice - return params - - def _build_instance_group_list_args(self, instance_groups): - """ - Takes a list of InstanceGroups, or a single InstanceGroup. Returns - a comparable dict for use in making a RunJobFlow or AddInstanceGroups - request. - """ - if not isinstance(instance_groups, list): - instance_groups = [instance_groups] - - params = {} - for i, instance_group in enumerate(instance_groups): - ig_dict = self._build_instance_group_args(instance_group) - for key, value in six.iteritems(ig_dict): - params['InstanceGroups.member.%d.%s' % (i+1, key)] = value - return params diff --git a/awx/lib/site-packages/boto/emr/emrobject.py b/awx/lib/site-packages/boto/emr/emrobject.py deleted file mode 100644 index f605834c72..0000000000 --- a/awx/lib/site-packages/boto/emr/emrobject.py +++ /dev/null @@ -1,481 +0,0 @@ -# Copyright (c) 2010 Spotify AB -# Copyright (c) 2010 Jeremy Thurgood <firxen+boto@gmail.com> -# Copyright (c) 2010-2011 Yelp -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -This module contains EMR response objects -""" - -from boto.resultset import ResultSet - - -class EmrObject(object): - Fields = set() - - def __init__(self, connection=None): - self.connection = connection - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name in self.Fields: - setattr(self, name.lower(), value) - - -class RunJobFlowResponse(EmrObject): - Fields = set(['JobFlowId']) - -class AddInstanceGroupsResponse(EmrObject): - Fields = set(['InstanceGroupIds', 'JobFlowId']) - -class ModifyInstanceGroupsResponse(EmrObject): - Fields = set(['RequestId']) - - -class Arg(EmrObject): - def __init__(self, connection=None): - self.value = None - - def endElement(self, name, value, connection): - self.value = value - - -class StepId(Arg): - pass - - -class JobFlowStepList(EmrObject): - def __ini__(self, connection=None): - self.connection = connection - self.stepids = None - - def startElement(self, name, attrs, connection): - if name == 'StepIds': - self.stepids = ResultSet([('member', StepId)]) - return self.stepids - else: - return None - - -class BootstrapAction(EmrObject): - Fields = set([ - 'Args', - 'Name', - 'Path', - 'ScriptPath', - ]) - - def startElement(self, name, attrs, connection): - if name == 'Args': - self.args = ResultSet([('member', Arg)]) - return self.args - - -class KeyValue(EmrObject): - Fields = set([ - 'Key', - 'Value', - ]) - - -class Step(EmrObject): - Fields = set([ - 'ActionOnFailure', - 'CreationDateTime', - 'EndDateTime', - 'Jar', - 'LastStateChangeReason', - 'MainClass', - 'Name', - 'StartDateTime', - 'State', - ]) - - def __init__(self, connection=None): - self.connection = connection - self.args = None - - def startElement(self, name, attrs, connection): - if name == 'Args': - self.args = ResultSet([('member', Arg)]) - return self.args - if name == 'Properties': - self.properties = ResultSet([('member', KeyValue)]) - return self.properties - - -class InstanceGroup(EmrObject): - Fields = set([ - 'BidPrice', - 'CreationDateTime', - 'EndDateTime', - 'InstanceGroupId', - 'InstanceRequestCount', - 'InstanceRole', - 'InstanceRunningCount', - 'InstanceType', - 'LastStateChangeReason', - 'LaunchGroup', - 'Market', - 'Name', - 'ReadyDateTime', - 'StartDateTime', - 'State', - ]) - - -class JobFlow(EmrObject): - Fields = set([ - 'AmiVersion', - 'AvailabilityZone', - 'CreationDateTime', - 'Ec2KeyName', - 'EndDateTime', - 'HadoopVersion', - 'Id', - 'InstanceCount', - 'JobFlowId', - 'KeepJobFlowAliveWhenNoSteps', - 'LastStateChangeReason', - 'LogUri', - 'MasterInstanceId', - 'MasterInstanceType', - 'MasterPublicDnsName', - 'Name', - 'NormalizedInstanceHours', - 'ReadyDateTime', - 'RequestId', - 'SlaveInstanceType', - 'StartDateTime', - 'State', - 'TerminationProtected', - 'Type', - 'Value', - 'VisibleToAllUsers', - ]) - - def __init__(self, connection=None): - self.connection = connection - self.steps = None - self.instancegroups = None - self.bootstrapactions = None - - def startElement(self, name, attrs, connection): - if name == 'Steps': - self.steps = ResultSet([('member', Step)]) - return self.steps - elif name == 'InstanceGroups': - self.instancegroups = ResultSet([('member', InstanceGroup)]) - return self.instancegroups - elif name == 'BootstrapActions': - self.bootstrapactions = ResultSet([('member', BootstrapAction)]) - return self.bootstrapactions - else: - return None - - -class ClusterTimeline(EmrObject): - Fields = set([ - 'CreationDateTime', - 'ReadyDateTime', - 'EndDateTime' - ]) - - -class ClusterStatus(EmrObject): - Fields = set([ - 'State', - 'StateChangeReason', - 'Timeline' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.timeline = None - - def startElement(self, name, attrs, connection): - if name == 'Timeline': - self.timeline = ClusterTimeline() - return self.timeline - else: - return None - - -class Ec2InstanceAttributes(EmrObject): - Fields = set([ - 'Ec2KeyName', - 'Ec2SubnetId', - 'Ec2AvailabilityZone', - 'IamInstanceProfile' - ]) - - -class Application(EmrObject): - Fields = set([ - 'Name', - 'Version', - 'Args', - 'AdditionalInfo' - ]) - - -class Cluster(EmrObject): - Fields = set([ - 'Id', - 'Name', - 'LogUri', - 'RequestedAmiVersion', - 'RunningAmiVersion', - 'AutoTerminate', - 'TerminationProtected', - 'VisibleToAllUsers' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.status = None - self.ec2instanceattributes = None - self.applications = None - self.tags = None - - def startElement(self, name, attrs, connection): - if name == 'Status': - self.status = ClusterStatus() - return self.status - elif name == 'Ec2InstanceAttributes': - self.ec2instanceattributes = Ec2InstanceAttributes() - return self.ec2instanceattributes - elif name == 'Applications': - self.applications = ResultSet([('member', Application)]) - return self.applications - elif name == 'Tags': - self.tags = ResultSet([('member', KeyValue)]) - return self.tags - else: - return None - - -class ClusterSummary(Cluster): - Fields = set([ - 'Id', - 'Name' - ]) - - -class ClusterSummaryList(EmrObject): - Fields = set([ - 'Marker' - ]) - - def __init__(self, connection): - self.connection = connection - self.clusters = None - - def startElement(self, name, attrs, connection): - if name == 'Clusters': - self.clusters = ResultSet([('member', ClusterSummary)]) - return self.clusters - else: - return None - - -class StepConfig(EmrObject): - Fields = set([ - 'Jar', - 'MainClass' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.properties = None - self.args = None - - def startElement(self, name, attrs, connection): - if name == 'Properties': - self.properties = ResultSet([('member', KeyValue)]) - return self.properties - elif name == 'Args': - self.args = ResultSet([('member', Arg)]) - return self.args - else: - return None - - -class HadoopStep(EmrObject): - Fields = set([ - 'Id', - 'Name', - 'ActionOnFailure' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.config = None - self.status = None - - def startElement(self, name, attrs, connection): - if name == 'Config': - self.config = StepConfig() - return self.config - elif name == 'Status': - self.status = ClusterStatus() - return self.status - else: - return None - - - -class InstanceGroupInfo(EmrObject): - Fields = set([ - 'Id', - 'Name', - 'Market', - 'InstanceGroupType', - 'BidPrice', - 'InstanceType', - 'RequestedInstanceCount', - 'RunningInstanceCount' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.status = None - - def startElement(self, name, attrs, connection): - if name == 'Status': - self.status = ClusterStatus() - return self.status - else: - return None - - -class InstanceGroupList(EmrObject): - Fields = set([ - 'Marker' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.instancegroups = None - - def startElement(self, name, attrs, connection): - if name == 'InstanceGroups': - self.instancegroups = ResultSet([('member', InstanceGroupInfo)]) - return self.instancegroups - else: - return None - - -class InstanceInfo(EmrObject): - Fields = set([ - 'Id', - 'Ec2InstanceId', - 'PublicDnsName', - 'PublicIpAddress', - 'PrivateDnsName', - 'PrivateIpAddress' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.status = None - - def startElement(self, name, attrs, connection): - if name == 'Status': - self.status = ClusterStatus() - return self.status - else: - return None - - -class InstanceList(EmrObject): - Fields = set([ - 'Marker' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.instances = None - - def startElement(self, name, attrs, connection): - if name == 'Instances': - self.instances = ResultSet([('member', InstanceInfo)]) - return self.instances - else: - return None - - -class StepSummary(EmrObject): - Fields = set([ - 'Id', - 'Name' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.status = None - self.config = None - - def startElement(self, name, attrs, connection): - if name == 'Status': - self.status = ClusterStatus() - return self.status - elif name == 'Config': - self.config = StepConfig() - return self.config - else: - return None - - -class StepSummaryList(EmrObject): - Fields = set([ - 'Marker' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.steps = None - - def startElement(self, name, attrs, connection): - if name == 'Steps': - self.steps = ResultSet([('member', StepSummary)]) - return self.steps - else: - return None - - -class BootstrapActionList(EmrObject): - Fields = set([ - 'Marker' - ]) - - def __init__(self, connection=None): - self.connection = connection - self.actions = None - - def startElement(self, name, attrs, connection): - if name == 'BootstrapActions': - self.actions = ResultSet([('member', BootstrapAction)]) - return self.actions - else: - return None diff --git a/awx/lib/site-packages/boto/emr/instance_group.py b/awx/lib/site-packages/boto/emr/instance_group.py deleted file mode 100644 index 6ab63c5d5a..0000000000 --- a/awx/lib/site-packages/boto/emr/instance_group.py +++ /dev/null @@ -1,43 +0,0 @@ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class InstanceGroup(object): - def __init__(self, num_instances, role, type, market, name, bidprice=None): - self.num_instances = num_instances - self.role = role - self.type = type - self.market = market - self.name = name - if market == 'SPOT': - if not bidprice: - raise ValueError('bidprice must be specified if market == SPOT') - self.bidprice = str(bidprice) - - def __repr__(self): - if self.market == 'SPOT': - return '%s.%s(name=%r, num_instances=%r, role=%r, type=%r, market = %r, bidprice = %r)' % ( - self.__class__.__module__, self.__class__.__name__, - self.name, self.num_instances, self.role, self.type, self.market, - self.bidprice) - else: - return '%s.%s(name=%r, num_instances=%r, role=%r, type=%r, market = %r)' % ( - self.__class__.__module__, self.__class__.__name__, - self.name, self.num_instances, self.role, self.type, self.market) diff --git a/awx/lib/site-packages/boto/emr/step.py b/awx/lib/site-packages/boto/emr/step.py deleted file mode 100644 index de6835fb4e..0000000000 --- a/awx/lib/site-packages/boto/emr/step.py +++ /dev/null @@ -1,283 +0,0 @@ -# Copyright (c) 2010 Spotify AB -# Copyright (c) 2010-2011 Yelp -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.compat import six - - -class Step(object): - """ - Jobflow Step base class - """ - def jar(self): - """ - :rtype: str - :return: URI to the jar - """ - raise NotImplemented() - - def args(self): - """ - :rtype: list(str) - :return: List of arguments for the step - """ - raise NotImplemented() - - def main_class(self): - """ - :rtype: str - :return: The main class name - """ - raise NotImplemented() - - -class JarStep(Step): - """ - Custom jar step - """ - def __init__(self, name, jar, main_class=None, - action_on_failure='TERMINATE_JOB_FLOW', step_args=None): - """ - A elastic mapreduce step that executes a jar - - :type name: str - :param name: The name of the step - :type jar: str - :param jar: S3 URI to the Jar file - :type main_class: str - :param main_class: The class to execute in the jar - :type action_on_failure: str - :param action_on_failure: An action, defined in the EMR docs to - take on failure. - :type step_args: list(str) - :param step_args: A list of arguments to pass to the step - """ - self.name = name - self._jar = jar - self._main_class = main_class - self.action_on_failure = action_on_failure - - if isinstance(step_args, six.string_types): - step_args = [step_args] - - self.step_args = step_args - - def jar(self): - return self._jar - - def args(self): - args = [] - - if self.step_args: - args.extend(self.step_args) - - return args - - def main_class(self): - return self._main_class - - -class StreamingStep(Step): - """ - Hadoop streaming step - """ - def __init__(self, name, mapper, reducer=None, combiner=None, - action_on_failure='TERMINATE_JOB_FLOW', - cache_files=None, cache_archives=None, - step_args=None, input=None, output=None, - jar='/home/hadoop/contrib/streaming/hadoop-streaming.jar'): - """ - A hadoop streaming elastic mapreduce step - - :type name: str - :param name: The name of the step - :type mapper: str - :param mapper: The mapper URI - :type reducer: str - :param reducer: The reducer URI - :type combiner: str - :param combiner: The combiner URI. Only works for Hadoop 0.20 - and later! - :type action_on_failure: str - :param action_on_failure: An action, defined in the EMR docs to - take on failure. - :type cache_files: list(str) - :param cache_files: A list of cache files to be bundled with the job - :type cache_archives: list(str) - :param cache_archives: A list of jar archives to be bundled with - the job - :type step_args: list(str) - :param step_args: A list of arguments to pass to the step - :type input: str or a list of str - :param input: The input uri - :type output: str - :param output: The output uri - :type jar: str - :param jar: The hadoop streaming jar. This can be either a local - path on the master node, or an s3:// URI. - """ - self.name = name - self.mapper = mapper - self.reducer = reducer - self.combiner = combiner - self.action_on_failure = action_on_failure - self.cache_files = cache_files - self.cache_archives = cache_archives - self.input = input - self.output = output - self._jar = jar - - if isinstance(step_args, six.string_types): - step_args = [step_args] - - self.step_args = step_args - - def jar(self): - return self._jar - - def main_class(self): - return None - - def args(self): - args = [] - - # put extra args BEFORE -mapper and -reducer so that e.g. -libjar - # will work - if self.step_args: - args.extend(self.step_args) - - args.extend(['-mapper', self.mapper]) - - if self.combiner: - args.extend(['-combiner', self.combiner]) - - if self.reducer: - args.extend(['-reducer', self.reducer]) - else: - args.extend(['-jobconf', 'mapred.reduce.tasks=0']) - - if self.input: - if isinstance(self.input, list): - for input in self.input: - args.extend(('-input', input)) - else: - args.extend(('-input', self.input)) - if self.output: - args.extend(('-output', self.output)) - - if self.cache_files: - for cache_file in self.cache_files: - args.extend(('-cacheFile', cache_file)) - - if self.cache_archives: - for cache_archive in self.cache_archives: - args.extend(('-cacheArchive', cache_archive)) - - return args - - def __repr__(self): - return '%s.%s(name=%r, mapper=%r, reducer=%r, action_on_failure=%r, cache_files=%r, cache_archives=%r, step_args=%r, input=%r, output=%r, jar=%r)' % ( - self.__class__.__module__, self.__class__.__name__, - self.name, self.mapper, self.reducer, self.action_on_failure, - self.cache_files, self.cache_archives, self.step_args, - self.input, self.output, self._jar) - - -class ScriptRunnerStep(JarStep): - - ScriptRunnerJar = 's3n://us-east-1.elasticmapreduce/libs/script-runner/script-runner.jar' - - def __init__(self, name, **kw): - super(ScriptRunnerStep, self).__init__(name, self.ScriptRunnerJar, **kw) - - -class PigBase(ScriptRunnerStep): - - BaseArgs = ['s3n://us-east-1.elasticmapreduce/libs/pig/pig-script', - '--base-path', 's3n://us-east-1.elasticmapreduce/libs/pig/'] - - -class InstallPigStep(PigBase): - """ - Install pig on emr step - """ - - InstallPigName = 'Install Pig' - - def __init__(self, pig_versions='latest'): - step_args = [] - step_args.extend(self.BaseArgs) - step_args.extend(['--install-pig']) - step_args.extend(['--pig-versions', pig_versions]) - super(InstallPigStep, self).__init__(self.InstallPigName, step_args=step_args) - - -class PigStep(PigBase): - """ - Pig script step - """ - - def __init__(self, name, pig_file, pig_versions='latest', pig_args=[]): - step_args = [] - step_args.extend(self.BaseArgs) - step_args.extend(['--pig-versions', pig_versions]) - step_args.extend(['--run-pig-script', '--args', '-f', pig_file]) - step_args.extend(pig_args) - super(PigStep, self).__init__(name, step_args=step_args) - - -class HiveBase(ScriptRunnerStep): - - BaseArgs = ['s3n://us-east-1.elasticmapreduce/libs/hive/hive-script', - '--base-path', 's3n://us-east-1.elasticmapreduce/libs/hive/'] - - -class InstallHiveStep(HiveBase): - """ - Install Hive on EMR step - """ - InstallHiveName = 'Install Hive' - - def __init__(self, hive_versions='latest', hive_site=None): - step_args = [] - step_args.extend(self.BaseArgs) - step_args.extend(['--install-hive']) - step_args.extend(['--hive-versions', hive_versions]) - if hive_site is not None: - step_args.extend(['--hive-site=%s' % hive_site]) - super(InstallHiveStep, self).__init__(self.InstallHiveName, - step_args=step_args) - - -class HiveStep(HiveBase): - """ - Hive script step - """ - - def __init__(self, name, hive_file, hive_versions='latest', - hive_args=None): - step_args = [] - step_args.extend(self.BaseArgs) - step_args.extend(['--hive-versions', hive_versions]) - step_args.extend(['--run-hive-script', '--args', '-f', hive_file]) - if hive_args is not None: - step_args.extend(hive_args) - super(HiveStep, self).__init__(name, step_args=step_args) diff --git a/awx/lib/site-packages/boto/endpoints.json b/awx/lib/site-packages/boto/endpoints.json deleted file mode 100644 index 1467314203..0000000000 --- a/awx/lib/site-packages/boto/endpoints.json +++ /dev/null @@ -1,365 +0,0 @@ -{ - "autoscaling": { - "ap-northeast-1": "autoscaling.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "autoscaling.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "autoscaling.ap-southeast-2.amazonaws.com", - "cn-north-1": "autoscaling.cn-north-1.amazonaws.com.cn", - "eu-west-1": "autoscaling.eu-west-1.amazonaws.com", - "sa-east-1": "autoscaling.sa-east-1.amazonaws.com", - "us-east-1": "autoscaling.us-east-1.amazonaws.com", - "us-gov-west-1": "autoscaling.us-gov-west-1.amazonaws.com", - "us-west-1": "autoscaling.us-west-1.amazonaws.com", - "us-west-2": "autoscaling.us-west-2.amazonaws.com", - "eu-central-1": "autoscaling.eu-central-1.amazonaws.com" - }, - "cloudformation": { - "ap-northeast-1": "cloudformation.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "cloudformation.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "cloudformation.ap-southeast-2.amazonaws.com", - "cn-north-1": "cloudformation.cn-north-1.amazonaws.com.cn", - "eu-west-1": "cloudformation.eu-west-1.amazonaws.com", - "sa-east-1": "cloudformation.sa-east-1.amazonaws.com", - "us-east-1": "cloudformation.us-east-1.amazonaws.com", - "us-gov-west-1": "cloudformation.us-gov-west-1.amazonaws.com", - "us-west-1": "cloudformation.us-west-1.amazonaws.com", - "us-west-2": "cloudformation.us-west-2.amazonaws.com", - "eu-central-1": "cloudformation.eu-central-1.amazonaws.com" - }, - "cloudfront": { - "ap-northeast-1": "cloudfront.amazonaws.com", - "ap-southeast-1": "cloudfront.amazonaws.com", - "ap-southeast-2": "cloudfront.amazonaws.com", - "eu-west-1": "cloudfront.amazonaws.com", - "sa-east-1": "cloudfront.amazonaws.com", - "us-east-1": "cloudfront.amazonaws.com", - "us-west-1": "cloudfront.amazonaws.com", - "us-west-2": "cloudfront.amazonaws.com", - "eu-central-1": "cloudfront.amazonaws.com" - }, - "cloudsearch": { - "ap-southeast-1": "cloudsearch.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "cloudsearch.ap-southeast-2.amazonaws.com", - "ap-northeast-1": "cloudsearch.ap-northeast-1.amazonaws.com", - "sa-east-1": "cloudsearch.sa-east-1.amazonaws.com", - "eu-west-1": "cloudsearch.eu-west-1.amazonaws.com", - "us-east-1": "cloudsearch.us-east-1.amazonaws.com", - "us-west-1": "cloudsearch.us-west-1.amazonaws.com", - "us-west-2": "cloudsearch.us-west-2.amazonaws.com", - "eu-central-1": "cloudsearch.eu-central-1.amazonaws.com" - }, - "cloudtrail": { - "ap-northeast-1": "cloudtrail.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "cloudtrail.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "cloudtrail.ap-southeast-2.amazonaws.com", - "eu-west-1": "cloudtrail.eu-west-1.amazonaws.com", - "sa-east-1": "cloudtrail.sa-east-1.amazonaws.com", - "us-east-1": "cloudtrail.us-east-1.amazonaws.com", - "us-west-1": "cloudtrail.us-west-1.amazonaws.com", - "us-west-2": "cloudtrail.us-west-2.amazonaws.com", - "eu-central-1": "cloudtrail.eu-central-1.amazonaws.com" - }, - "cloudwatch": { - "ap-northeast-1": "monitoring.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "monitoring.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "monitoring.ap-southeast-2.amazonaws.com", - "cn-north-1": "monitoring.cn-north-1.amazonaws.com.cn", - "eu-west-1": "monitoring.eu-west-1.amazonaws.com", - "sa-east-1": "monitoring.sa-east-1.amazonaws.com", - "us-east-1": "monitoring.us-east-1.amazonaws.com", - "us-gov-west-1": "monitoring.us-gov-west-1.amazonaws.com", - "us-west-1": "monitoring.us-west-1.amazonaws.com", - "us-west-2": "monitoring.us-west-2.amazonaws.com", - "eu-central-1": "monitoring.eu-central-1.amazonaws.com" - }, - "cognito-identity": { - "us-east-1": "cognito-identity.us-east-1.amazonaws.com" - }, - "cognito-sync": { - "us-east-1": "cognito-sync.us-east-1.amazonaws.com" - }, - "datapipeline": { - "us-east-1": "datapipeline.us-east-1.amazonaws.com", - "us-west-2": "datapipeline.us-west-2.amazonaws.com", - "eu-west-1": "datapipeline.eu-west-1.amazonaws.com", - "ap-southeast-2": "datapipeline.ap-southeast-2.amazonaws.com", - "ap-northeast-1": "datapipeline.ap-northeast-1.amazonaws.com", - "eu-central-1": "datapipeline.eu-central-1.amazonaws.com" - }, - "directconnect": { - "ap-northeast-1": "directconnect.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "directconnect.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "directconnect.ap-southeast-2.amazonaws.com", - "eu-west-1": "directconnect.eu-west-1.amazonaws.com", - "sa-east-1": "directconnect.sa-east-1.amazonaws.com", - "us-east-1": "directconnect.us-east-1.amazonaws.com", - "us-west-1": "directconnect.us-west-1.amazonaws.com", - "us-west-2": "directconnect.us-west-2.amazonaws.com", - "eu-central-1": "directconnect.eu-central-1.amazonaws.com" - }, - "dynamodb": { - "ap-northeast-1": "dynamodb.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "dynamodb.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "dynamodb.ap-southeast-2.amazonaws.com", - "cn-north-1": "dynamodb.cn-north-1.amazonaws.com.cn", - "eu-west-1": "dynamodb.eu-west-1.amazonaws.com", - "sa-east-1": "dynamodb.sa-east-1.amazonaws.com", - "us-east-1": "dynamodb.us-east-1.amazonaws.com", - "us-gov-west-1": "dynamodb.us-gov-west-1.amazonaws.com", - "us-west-1": "dynamodb.us-west-1.amazonaws.com", - "us-west-2": "dynamodb.us-west-2.amazonaws.com", - "eu-central-1": "dynamodb.eu-central-1.amazonaws.com" - }, - "ec2": { - "ap-northeast-1": "ec2.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "ec2.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "ec2.ap-southeast-2.amazonaws.com", - "cn-north-1": "ec2.cn-north-1.amazonaws.com.cn", - "eu-west-1": "ec2.eu-west-1.amazonaws.com", - "sa-east-1": "ec2.sa-east-1.amazonaws.com", - "us-east-1": "ec2.us-east-1.amazonaws.com", - "us-gov-west-1": "ec2.us-gov-west-1.amazonaws.com", - "us-west-1": "ec2.us-west-1.amazonaws.com", - "us-west-2": "ec2.us-west-2.amazonaws.com", - "eu-central-1": "ec2.eu-central-1.amazonaws.com" - }, - "elasticache": { - "ap-northeast-1": "elasticache.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "elasticache.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "elasticache.ap-southeast-2.amazonaws.com", - "cn-north-1": "elasticache.cn-north-1.amazonaws.com.cn", - "eu-west-1": "elasticache.eu-west-1.amazonaws.com", - "sa-east-1": "elasticache.sa-east-1.amazonaws.com", - "us-east-1": "elasticache.us-east-1.amazonaws.com", - "us-west-1": "elasticache.us-west-1.amazonaws.com", - "us-west-2": "elasticache.us-west-2.amazonaws.com", - "eu-central-1": "elasticache.eu-central-1.amazonaws.com" - }, - "elasticbeanstalk": { - "ap-northeast-1": "elasticbeanstalk.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "elasticbeanstalk.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "elasticbeanstalk.ap-southeast-2.amazonaws.com", - "eu-west-1": "elasticbeanstalk.eu-west-1.amazonaws.com", - "sa-east-1": "elasticbeanstalk.sa-east-1.amazonaws.com", - "us-east-1": "elasticbeanstalk.us-east-1.amazonaws.com", - "us-west-1": "elasticbeanstalk.us-west-1.amazonaws.com", - "us-west-2": "elasticbeanstalk.us-west-2.amazonaws.com", - "eu-central-1": "elasticbeanstalk.eu-central-1.amazonaws.com" - }, - "elasticloadbalancing": { - "ap-northeast-1": "elasticloadbalancing.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "elasticloadbalancing.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "elasticloadbalancing.ap-southeast-2.amazonaws.com", - "cn-north-1": "elasticloadbalancing.cn-north-1.amazonaws.com.cn", - "eu-west-1": "elasticloadbalancing.eu-west-1.amazonaws.com", - "sa-east-1": "elasticloadbalancing.sa-east-1.amazonaws.com", - "us-east-1": "elasticloadbalancing.us-east-1.amazonaws.com", - "us-gov-west-1": "elasticloadbalancing.us-gov-west-1.amazonaws.com", - "us-west-1": "elasticloadbalancing.us-west-1.amazonaws.com", - "us-west-2": "elasticloadbalancing.us-west-2.amazonaws.com", - "eu-central-1": "elasticloadbalancing.eu-central-1.amazonaws.com" - }, - "elasticmapreduce": { - "ap-northeast-1": "ap-northeast-1.elasticmapreduce.amazonaws.com", - "ap-southeast-1": "ap-southeast-1.elasticmapreduce.amazonaws.com", - "ap-southeast-2": "ap-southeast-2.elasticmapreduce.amazonaws.com", - "cn-north-1": "elasticmapreduce.cn-north-1.amazonaws.com.cn", - "eu-west-1": "elasticmapreduce.eu-west-1.amazonaws.com", - "sa-east-1": "sa-east-1.elasticmapreduce.amazonaws.com", - "us-east-1": "elasticmapreduce.us-east-1.amazonaws.com", - "us-gov-west-1": "us-gov-west-1.elasticmapreduce.amazonaws.com", - "us-west-1": "us-west-1.elasticmapreduce.amazonaws.com", - "us-west-2": "us-west-2.elasticmapreduce.amazonaws.com", - "eu-central-1": "eu-central-1.elasticmapreduce.amazonaws.com" - }, - "elastictranscoder": { - "ap-northeast-1": "elastictranscoder.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "elastictranscoder.ap-southeast-1.amazonaws.com", - "eu-west-1": "elastictranscoder.eu-west-1.amazonaws.com", - "us-east-1": "elastictranscoder.us-east-1.amazonaws.com", - "us-west-1": "elastictranscoder.us-west-1.amazonaws.com", - "us-west-2": "elastictranscoder.us-west-2.amazonaws.com", - "eu-central-1": "elastictranscoder.eu-central-1.amazonaws.com" - }, - "glacier": { - "ap-northeast-1": "glacier.ap-northeast-1.amazonaws.com", - "ap-southeast-2": "glacier.ap-southeast-2.amazonaws.com", - "cn-north-1": "glacier.cn-north-1.amazonaws.com.cn", - "eu-west-1": "glacier.eu-west-1.amazonaws.com", - "us-east-1": "glacier.us-east-1.amazonaws.com", - "us-west-1": "glacier.us-west-1.amazonaws.com", - "us-west-2": "glacier.us-west-2.amazonaws.com", - "eu-central-1": "glacier.eu-central-1.amazonaws.com" - }, - "iam": { - "ap-northeast-1": "iam.amazonaws.com", - "ap-southeast-1": "iam.amazonaws.com", - "ap-southeast-2": "iam.amazonaws.com", - "cn-north-1": "iam.cn-north-1.amazonaws.com.cn", - "eu-west-1": "iam.amazonaws.com", - "sa-east-1": "iam.amazonaws.com", - "us-east-1": "iam.amazonaws.com", - "us-gov-west-1": "iam.us-gov.amazonaws.com", - "us-west-1": "iam.amazonaws.com", - "us-west-2": "iam.amazonaws.com" - }, - "importexport": { - "ap-northeast-1": "importexport.amazonaws.com", - "ap-southeast-1": "importexport.amazonaws.com", - "ap-southeast-2": "importexport.amazonaws.com", - "eu-west-1": "importexport.amazonaws.com", - "sa-east-1": "importexport.amazonaws.com", - "us-east-1": "importexport.amazonaws.com", - "us-west-1": "importexport.amazonaws.com", - "us-west-2": "importexport.amazonaws.com" - }, - "kinesis": { - "us-east-1": "kinesis.us-east-1.amazonaws.com", - "us-west-2": "kinesis.us-west-2.amazonaws.com", - "eu-west-1": "kinesis.eu-west-1.amazonaws.com", - "ap-southeast-1": "kinesis.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "kinesis.ap-southeast-2.amazonaws.com", - "ap-northeast-1": "kinesis.ap-northeast-1.amazonaws.com", - "eu-central-1": "kinesis.eu-central-1.amazonaws.com" - }, - "logs": { - "us-east-1": "logs.us-east-1.amazonaws.com", - "us-west-2": "logs.us-west-2.amazonaws.com", - "eu-west-1": "logs.eu-west-1.amazonaws.com", - "eu-central-1": "logs.eu-central-1.amazonaws.com" - }, - "opsworks": { - "us-east-1": "opsworks.us-east-1.amazonaws.com", - "eu-central-1": "opsworks.eu-central-1.amazonaws.com" - }, - "rds": { - "ap-northeast-1": "rds.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "rds.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "rds.ap-southeast-2.amazonaws.com", - "cn-north-1": "rds.cn-north-1.amazonaws.com.cn", - "eu-west-1": "rds.eu-west-1.amazonaws.com", - "sa-east-1": "rds.sa-east-1.amazonaws.com", - "us-east-1": "rds.amazonaws.com", - "us-gov-west-1": "rds.us-gov-west-1.amazonaws.com", - "us-west-1": "rds.us-west-1.amazonaws.com", - "us-west-2": "rds.us-west-2.amazonaws.com", - "eu-central-1": "rds.eu-central-1.amazonaws.com" - }, - "redshift": { - "ap-northeast-1": "redshift.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "redshift.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "redshift.ap-southeast-2.amazonaws.com", - "eu-west-1": "redshift.eu-west-1.amazonaws.com", - "us-east-1": "redshift.us-east-1.amazonaws.com", - "us-west-2": "redshift.us-west-2.amazonaws.com", - "eu-central-1": "redshift.eu-central-1.amazonaws.com" - }, - "route53": { - "ap-northeast-1": "route53.amazonaws.com", - "ap-southeast-1": "route53.amazonaws.com", - "ap-southeast-2": "route53.amazonaws.com", - "eu-west-1": "route53.amazonaws.com", - "sa-east-1": "route53.amazonaws.com", - "us-east-1": "route53.amazonaws.com", - "us-west-1": "route53.amazonaws.com", - "us-west-2": "route53.amazonaws.com" - }, - "route53domains": { - "us-east-1": "route53domains.us-east-1.amazonaws.com" - }, - "s3": { - "ap-northeast-1": "s3-ap-northeast-1.amazonaws.com", - "ap-southeast-1": "s3-ap-southeast-1.amazonaws.com", - "ap-southeast-2": "s3-ap-southeast-2.amazonaws.com", - "cn-north-1": "s3.cn-north-1.amazonaws.com.cn", - "eu-west-1": "s3-eu-west-1.amazonaws.com", - "sa-east-1": "s3-sa-east-1.amazonaws.com", - "us-east-1": "s3.amazonaws.com", - "us-gov-west-1": "s3-us-gov-west-1.amazonaws.com", - "us-west-1": "s3-us-west-1.amazonaws.com", - "us-west-2": "s3-us-west-2.amazonaws.com", - "eu-central-1": "s3.eu-central-1.amazonaws.com" - }, - "sdb": { - "ap-northeast-1": "sdb.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "sdb.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "sdb.ap-southeast-2.amazonaws.com", - "eu-west-1": "sdb.eu-west-1.amazonaws.com", - "sa-east-1": "sdb.sa-east-1.amazonaws.com", - "us-east-1": "sdb.amazonaws.com", - "us-west-1": "sdb.us-west-1.amazonaws.com", - "us-west-2": "sdb.us-west-2.amazonaws.com", - "eu-central-1": "sdb.eu-central-1.amazonaws.com" - }, - "ses": { - "eu-west-1": "email.eu-west-1.amazonaws.com", - "us-east-1": "email.us-east-1.amazonaws.com", - "us-west-2": "email.us-west-2.amazonaws.com", - "eu-central-1": "email.eu-central-1.amazonaws.com" - }, - "sns": { - "ap-northeast-1": "sns.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "sns.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "sns.ap-southeast-2.amazonaws.com", - "cn-north-1": "sns.cn-north-1.amazonaws.com.cn", - "eu-west-1": "sns.eu-west-1.amazonaws.com", - "sa-east-1": "sns.sa-east-1.amazonaws.com", - "us-east-1": "sns.us-east-1.amazonaws.com", - "us-gov-west-1": "sns.us-gov-west-1.amazonaws.com", - "us-west-1": "sns.us-west-1.amazonaws.com", - "us-west-2": "sns.us-west-2.amazonaws.com", - "eu-central-1": "sns.eu-central-1.amazonaws.com" - }, - "sqs": { - "ap-northeast-1": "ap-northeast-1.queue.amazonaws.com", - "ap-southeast-1": "ap-southeast-1.queue.amazonaws.com", - "ap-southeast-2": "ap-southeast-2.queue.amazonaws.com", - "cn-north-1": "sqs.cn-north-1.amazonaws.com.cn", - "eu-west-1": "eu-west-1.queue.amazonaws.com", - "sa-east-1": "sa-east-1.queue.amazonaws.com", - "us-east-1": "queue.amazonaws.com", - "us-gov-west-1": "us-gov-west-1.queue.amazonaws.com", - "us-west-1": "us-west-1.queue.amazonaws.com", - "us-west-2": "us-west-2.queue.amazonaws.com", - "eu-central-1": "eu-central-1.queue.amazonaws.com" - }, - "storagegateway": { - "ap-northeast-1": "storagegateway.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "storagegateway.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "storagegateway.ap-southeast-2.amazonaws.com", - "eu-west-1": "storagegateway.eu-west-1.amazonaws.com", - "sa-east-1": "storagegateway.sa-east-1.amazonaws.com", - "us-east-1": "storagegateway.us-east-1.amazonaws.com", - "us-west-1": "storagegateway.us-west-1.amazonaws.com", - "us-west-2": "storagegateway.us-west-2.amazonaws.com", - "eu-central-1": "storagegateway.eu-central-1.amazonaws.com" - }, - "sts": { - "ap-northeast-1": "sts.amazonaws.com", - "ap-southeast-1": "sts.amazonaws.com", - "ap-southeast-2": "sts.amazonaws.com", - "cn-north-1": "sts.cn-north-1.amazonaws.com.cn", - "eu-west-1": "sts.amazonaws.com", - "sa-east-1": "sts.amazonaws.com", - "us-east-1": "sts.amazonaws.com", - "us-gov-west-1": "sts.us-gov-west-1.amazonaws.com", - "us-west-1": "sts.amazonaws.com", - "us-west-2": "sts.amazonaws.com" - }, - "support": { - "us-east-1": "support.us-east-1.amazonaws.com", - "eu-central-1": "support.eu-central-1.amazonaws.com" - }, - "swf": { - "ap-northeast-1": "swf.ap-northeast-1.amazonaws.com", - "ap-southeast-1": "swf.ap-southeast-1.amazonaws.com", - "ap-southeast-2": "swf.ap-southeast-2.amazonaws.com", - "cn-north-1": "swf.cn-north-1.amazonaws.com.cn", - "eu-west-1": "swf.eu-west-1.amazonaws.com", - "sa-east-1": "swf.sa-east-1.amazonaws.com", - "us-east-1": "swf.us-east-1.amazonaws.com", - "us-gov-west-1": "swf.us-gov-west-1.amazonaws.com", - "us-west-1": "swf.us-west-1.amazonaws.com", - "us-west-2": "swf.us-west-2.amazonaws.com", - "eu-central-1": "swf.eu-central-1.amazonaws.com" - } -} diff --git a/awx/lib/site-packages/boto/exception.py b/awx/lib/site-packages/boto/exception.py deleted file mode 100644 index 36c226fa84..0000000000 --- a/awx/lib/site-packages/boto/exception.py +++ /dev/null @@ -1,573 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Exception classes - Subclassing allows you to check for specific errors -""" -import base64 -import xml.sax - -import boto - -from boto import handler -from boto.compat import json, StandardError -from boto.resultset import ResultSet - - -class BotoClientError(StandardError): - """ - General Boto Client error (error accessing AWS) - """ - def __init__(self, reason, *args): - super(BotoClientError, self).__init__(reason, *args) - self.reason = reason - - def __repr__(self): - return 'BotoClientError: %s' % self.reason - - def __str__(self): - return 'BotoClientError: %s' % self.reason - - -class SDBPersistenceError(StandardError): - pass - - -class StoragePermissionsError(BotoClientError): - """ - Permissions error when accessing a bucket or key on a storage service. - """ - pass - - -class S3PermissionsError(StoragePermissionsError): - """ - Permissions error when accessing a bucket or key on S3. - """ - pass - - -class GSPermissionsError(StoragePermissionsError): - """ - Permissions error when accessing a bucket or key on GS. - """ - pass - - -class BotoServerError(StandardError): - def __init__(self, status, reason, body=None, *args): - super(BotoServerError, self).__init__(status, reason, body, *args) - self.status = status - self.reason = reason - self.body = body or '' - self.request_id = None - self.error_code = None - self._error_message = None - self.message = '' - self.box_usage = None - - if isinstance(self.body, bytes): - try: - self.body = self.body.decode('utf-8') - except UnicodeDecodeError: - boto.log.debug('Unable to decode body from bytes!') - - # Attempt to parse the error response. If body isn't present, - # then just ignore the error response. - if self.body: - # Check if it looks like a ``dict``. - if hasattr(self.body, 'items'): - # It's not a string, so trying to parse it will fail. - # But since it's data, we can work with that. - self.request_id = self.body.get('RequestId', None) - - if 'Error' in self.body: - # XML-style - error = self.body.get('Error', {}) - self.error_code = error.get('Code', None) - self.message = error.get('Message', None) - else: - # JSON-style. - self.message = self.body.get('message', None) - else: - try: - h = handler.XmlHandlerWrapper(self, self) - h.parseString(self.body) - except (TypeError, xml.sax.SAXParseException): - # What if it's JSON? Let's try that. - try: - parsed = json.loads(self.body) - - if 'RequestId' in parsed: - self.request_id = parsed['RequestId'] - if 'Error' in parsed: - if 'Code' in parsed['Error']: - self.error_code = parsed['Error']['Code'] - if 'Message' in parsed['Error']: - self.message = parsed['Error']['Message'] - - except (TypeError, ValueError): - # Remove unparsable message body so we don't include garbage - # in exception. But first, save self.body in self.error_message - # because occasionally we get error messages from Eucalyptus - # that are just text strings that we want to preserve. - self.message = self.body - self.body = None - - def __getattr__(self, name): - if name == 'error_message': - return self.message - if name == 'code': - return self.error_code - raise AttributeError - - def __setattr__(self, name, value): - if name == 'error_message': - self.message = value - else: - super(BotoServerError, self).__setattr__(name, value) - - def __repr__(self): - return '%s: %s %s\n%s' % (self.__class__.__name__, - self.status, self.reason, self.body) - - def __str__(self): - return '%s: %s %s\n%s' % (self.__class__.__name__, - self.status, self.reason, self.body) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name in ('RequestId', 'RequestID'): - self.request_id = value - elif name == 'Code': - self.error_code = value - elif name == 'Message': - self.message = value - elif name == 'BoxUsage': - self.box_usage = value - return None - - def _cleanupParsedProperties(self): - self.request_id = None - self.error_code = None - self.message = None - self.box_usage = None - - -class ConsoleOutput(object): - def __init__(self, parent=None): - self.parent = parent - self.instance_id = None - self.timestamp = None - self.comment = None - self.output = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'instanceId': - self.instance_id = value - elif name == 'output': - self.output = base64.b64decode(value) - else: - setattr(self, name, value) - - -class StorageCreateError(BotoServerError): - """ - Error creating a bucket or key on a storage service. - """ - def __init__(self, status, reason, body=None): - self.bucket = None - super(StorageCreateError, self).__init__(status, reason, body) - - def endElement(self, name, value, connection): - if name == 'BucketName': - self.bucket = value - else: - return super(StorageCreateError, self).endElement(name, value, connection) - - -class S3CreateError(StorageCreateError): - """ - Error creating a bucket or key on S3. - """ - pass - - -class GSCreateError(StorageCreateError): - """ - Error creating a bucket or key on GS. - """ - pass - - -class StorageCopyError(BotoServerError): - """ - Error copying a key on a storage service. - """ - pass - - -class S3CopyError(StorageCopyError): - """ - Error copying a key on S3. - """ - pass - - -class GSCopyError(StorageCopyError): - """ - Error copying a key on GS. - """ - pass - - -class SQSError(BotoServerError): - """ - General Error on Simple Queue Service. - """ - def __init__(self, status, reason, body=None): - self.detail = None - self.type = None - super(SQSError, self).__init__(status, reason, body) - - def startElement(self, name, attrs, connection): - return super(SQSError, self).startElement(name, attrs, connection) - - def endElement(self, name, value, connection): - if name == 'Detail': - self.detail = value - elif name == 'Type': - self.type = value - else: - return super(SQSError, self).endElement(name, value, connection) - - def _cleanupParsedProperties(self): - super(SQSError, self)._cleanupParsedProperties() - for p in ('detail', 'type'): - setattr(self, p, None) - - -class SQSDecodeError(BotoClientError): - """ - Error when decoding an SQS message. - """ - def __init__(self, reason, message): - super(SQSDecodeError, self).__init__(reason, message) - self.message = message - - def __repr__(self): - return 'SQSDecodeError: %s' % self.reason - - def __str__(self): - return 'SQSDecodeError: %s' % self.reason - - -class StorageResponseError(BotoServerError): - """ - Error in response from a storage service. - """ - def __init__(self, status, reason, body=None): - self.resource = None - super(StorageResponseError, self).__init__(status, reason, body) - - def startElement(self, name, attrs, connection): - return super(StorageResponseError, self).startElement( - name, attrs, connection) - - def endElement(self, name, value, connection): - if name == 'Resource': - self.resource = value - else: - return super(StorageResponseError, self).endElement( - name, value, connection) - - def _cleanupParsedProperties(self): - super(StorageResponseError, self)._cleanupParsedProperties() - for p in ('resource'): - setattr(self, p, None) - - -class S3ResponseError(StorageResponseError): - """ - Error in response from S3. - """ - pass - - -class GSResponseError(StorageResponseError): - """ - Error in response from GS. - """ - pass - - -class EC2ResponseError(BotoServerError): - """ - Error in response from EC2. - """ - def __init__(self, status, reason, body=None): - self.errors = None - self._errorResultSet = [] - super(EC2ResponseError, self).__init__(status, reason, body) - self.errors = [ - (e.error_code, e.error_message) for e in self._errorResultSet] - if len(self.errors): - self.error_code, self.error_message = self.errors[0] - - def startElement(self, name, attrs, connection): - if name == 'Errors': - self._errorResultSet = ResultSet([('Error', _EC2Error)]) - return self._errorResultSet - else: - return None - - def endElement(self, name, value, connection): - if name == 'RequestID': - self.request_id = value - else: - return None # don't call subclass here - - def _cleanupParsedProperties(self): - super(EC2ResponseError, self)._cleanupParsedProperties() - self._errorResultSet = [] - for p in ('errors'): - setattr(self, p, None) - - -class JSONResponseError(BotoServerError): - """ - This exception expects the fully parsed and decoded JSON response - body to be passed as the body parameter. - - :ivar status: The HTTP status code. - :ivar reason: The HTTP reason message. - :ivar body: The Python dict that represents the decoded JSON - response body. - :ivar error_message: The full description of the AWS error encountered. - :ivar error_code: A short string that identifies the AWS error - (e.g. ConditionalCheckFailedException) - """ - def __init__(self, status, reason, body=None, *args): - self.status = status - self.reason = reason - self.body = body - if self.body: - self.error_message = self.body.get('message', None) - self.error_code = self.body.get('__type', None) - if self.error_code: - self.error_code = self.error_code.split('#')[-1] - - -class DynamoDBResponseError(JSONResponseError): - pass - - -class SWFResponseError(JSONResponseError): - pass - - -class EmrResponseError(BotoServerError): - """ - Error in response from EMR - """ - pass - - -class _EC2Error(object): - def __init__(self, connection=None): - self.connection = connection - self.error_code = None - self.error_message = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Code': - self.error_code = value - elif name == 'Message': - self.error_message = value - else: - return None - - -class SDBResponseError(BotoServerError): - """ - Error in responses from SDB. - """ - pass - - -class AWSConnectionError(BotoClientError): - """ - General error connecting to Amazon Web Services. - """ - pass - - -class StorageDataError(BotoClientError): - """ - Error receiving data from a storage service. - """ - pass - - -class S3DataError(StorageDataError): - """ - Error receiving data from S3. - """ - pass - - -class GSDataError(StorageDataError): - """ - Error receiving data from GS. - """ - pass - - -class InvalidUriError(Exception): - """Exception raised when URI is invalid.""" - - def __init__(self, message): - super(InvalidUriError, self).__init__(message) - self.message = message - - -class InvalidAclError(Exception): - """Exception raised when ACL XML is invalid.""" - - def __init__(self, message): - super(InvalidAclError, self).__init__(message) - self.message = message - - -class InvalidCorsError(Exception): - """Exception raised when CORS XML is invalid.""" - - def __init__(self, message): - super(InvalidCorsError, self).__init__(message) - self.message = message - - -class NoAuthHandlerFound(Exception): - """Is raised when no auth handlers were found ready to authenticate.""" - pass - - -class InvalidLifecycleConfigError(Exception): - """Exception raised when GCS lifecycle configuration XML is invalid.""" - - def __init__(self, message): - super(InvalidLifecycleConfigError, self).__init__(message) - self.message = message - - -# Enum class for resumable upload failure disposition. -class ResumableTransferDisposition(object): - # START_OVER means an attempt to resume an existing transfer failed, - # and a new resumable upload should be attempted (without delay). - START_OVER = 'START_OVER' - - # WAIT_BEFORE_RETRY means the resumable transfer failed but that it can - # be retried after a time delay within the current process. - WAIT_BEFORE_RETRY = 'WAIT_BEFORE_RETRY' - - # ABORT_CUR_PROCESS means the resumable transfer failed and that - # delaying/retrying within the current process will not help. If - # resumable transfer included a state tracker file the upload can be - # retried again later, in another process (e.g., a later run of gsutil). - ABORT_CUR_PROCESS = 'ABORT_CUR_PROCESS' - - # ABORT means the resumable transfer failed in a way that it does not - # make sense to continue in the current process, and further that the - # current tracker ID should not be preserved (in a tracker file if one - # was specified at resumable upload start time). If the user tries again - # later (e.g., a separate run of gsutil) it will get a new resumable - # upload ID. - ABORT = 'ABORT' - - -class ResumableUploadException(Exception): - """ - Exception raised for various resumable upload problems. - - self.disposition is of type ResumableTransferDisposition. - """ - - def __init__(self, message, disposition): - super(ResumableUploadException, self).__init__(message, disposition) - self.message = message - self.disposition = disposition - - def __repr__(self): - return 'ResumableUploadException("%s", %s)' % ( - self.message, self.disposition) - - -class ResumableDownloadException(Exception): - """ - Exception raised for various resumable download problems. - - self.disposition is of type ResumableTransferDisposition. - """ - - def __init__(self, message, disposition): - super(ResumableDownloadException, self).__init__(message, disposition) - self.message = message - self.disposition = disposition - - def __repr__(self): - return 'ResumableDownloadException("%s", %s)' % ( - self.message, self.disposition) - - -class TooManyRecordsException(Exception): - """ - Exception raised when a search of Route53 records returns more - records than requested. - """ - - def __init__(self, message): - super(TooManyRecordsException, self).__init__(message) - self.message = message - - -class PleaseRetryException(Exception): - """ - Indicates a request should be retried. - """ - def __init__(self, message, response=None): - self.message = message - self.response = response - - def __repr__(self): - return 'PleaseRetryException("%s", %s)' % ( - self.message, - self.response - ) diff --git a/awx/lib/site-packages/boto/file/README b/awx/lib/site-packages/boto/file/README deleted file mode 100644 index af824554e1..0000000000 --- a/awx/lib/site-packages/boto/file/README +++ /dev/null @@ -1,49 +0,0 @@ -Handling of file:// URIs: - -This directory contains code to map basic boto connection, bucket, and key -operations onto files in the local filesystem, in support of file:// -URI operations. - -Bucket storage operations cannot be mapped completely onto a file system -because of the different naming semantics in these types of systems: the -former have a flat name space of objects within each named bucket; the -latter have a hierarchical name space of files, and nothing corresponding to -the notion of a bucket. The mapping we selected was guided by the desire -to achieve meaningful semantics for a useful subset of operations that can -be implemented polymorphically across both types of systems. We considered -several possibilities for mapping path names to bucket + object name: - -1) bucket = the file system root or local directory (for absolute vs -relative file:// URIs, respectively) and object = remainder of path. -We discarded this choice because the get_all_keys() method doesn't make -sense under this approach: Enumerating all files under the root or current -directory could include more than the caller intended. For example, -StorageUri("file:///usr/bin/X11/vim").get_all_keys() would enumerate all -files in the file system. - -2) bucket is treated mostly as an anonymous placeholder, with the object -name holding the URI path (minus the "file://" part). Two sub-options, -for object enumeration (the get_all_keys() call): - a) disallow get_all_keys(). This isn't great, as then the caller must - know the URI type before deciding whether to make this call. - b) return the single key for which this "bucket" was defined. - Note that this option means the app cannot use this API for listing - contents of the file system. While that makes the API less generally - useful, it avoids the potentially dangerous/unintended consequences - noted in option (1) above. - -We selected 2b, resulting in a class hierarchy where StorageUri is an abstract -class, with FileStorageUri and BucketStorageUri subclasses. - -Some additional notes: - -BucketStorageUri and FileStorageUri each implement these methods: - - clone_replace_name() creates a same-type URI with a - different object name - which is useful for various enumeration cases - (e.g., implementing wildcarding in a command line utility). - - names_container() determines if the given URI names a container for - multiple objects/files - i.e., a bucket or directory. - - names_singleton() determines if the given URI names an individual object - or file. - - is_file_uri() and is_cloud_uri() determine if the given URI is a - FileStorageUri or BucketStorageUri, respectively diff --git a/awx/lib/site-packages/boto/file/__init__.py b/awx/lib/site-packages/boto/file/__init__.py deleted file mode 100644 index 837a164f47..0000000000 --- a/awx/lib/site-packages/boto/file/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto - -from boto.file.connection import FileConnection as Connection -from boto.file.key import Key -from boto.file.bucket import Bucket - -__all__ = ['Connection', 'Key', 'Bucket'] diff --git a/awx/lib/site-packages/boto/file/bucket.py b/awx/lib/site-packages/boto/file/bucket.py deleted file mode 100644 index d49755eaae..0000000000 --- a/awx/lib/site-packages/boto/file/bucket.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2010 Google Inc. -# Copyright (c) 2011, Nexenta Systems Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# File representation of bucket, for use with "file://" URIs. - -import os -from boto.file.key import Key -from boto.file.simpleresultset import SimpleResultSet -from boto.s3.bucketlistresultset import BucketListResultSet - -class Bucket(object): - def __init__(self, name, contained_key): - """Instantiate an anonymous file-based Bucket around a single key. - """ - self.name = name - self.contained_key = contained_key - - def __iter__(self): - return iter(BucketListResultSet(self)) - - def __str__(self): - return 'anonymous bucket for file://' + self.contained_key - - def delete_key(self, key_name, headers=None, - version_id=None, mfa_token=None): - """ - Deletes a key from the bucket. - - :type key_name: string - :param key_name: The key name to delete - - :type version_id: string - :param version_id: Unused in this subclass. - - :type mfa_token: tuple or list of strings - :param mfa_token: Unused in this subclass. - """ - os.remove(key_name) - - def get_all_keys(self, headers=None, **params): - """ - This method returns the single key around which this anonymous Bucket - was instantiated. - - :rtype: SimpleResultSet - :return: The result from file system listing the keys requested - - """ - key = Key(self.name, self.contained_key) - return SimpleResultSet([key]) - - def get_key(self, key_name, headers=None, version_id=None, - key_type=Key.KEY_REGULAR_FILE): - """ - Check to see if a particular key exists within the bucket. - Returns: An instance of a Key object or None - - :type key_name: string - :param key_name: The name of the key to retrieve - - :type version_id: string - :param version_id: Unused in this subclass. - - :type stream_type: integer - :param stream_type: Type of the Key - Regular File or input/output Stream - - :rtype: :class:`boto.file.key.Key` - :returns: A Key object from this bucket. - """ - if key_name == '-': - return Key(self.name, '-', key_type=Key.KEY_STREAM_READABLE) - else: - fp = open(key_name, 'rb') - return Key(self.name, key_name, fp) - - def new_key(self, key_name=None, key_type=Key.KEY_REGULAR_FILE): - """ - Creates a new key - - :type key_name: string - :param key_name: The name of the key to create - - :rtype: :class:`boto.file.key.Key` - :returns: An instance of the newly created key object - """ - if key_name == '-': - return Key(self.name, '-', key_type=Key.KEY_STREAM_WRITABLE) - else: - dir_name = os.path.dirname(key_name) - if dir_name and not os.path.exists(dir_name): - os.makedirs(dir_name) - fp = open(key_name, 'wb') - return Key(self.name, key_name, fp) diff --git a/awx/lib/site-packages/boto/file/connection.py b/awx/lib/site-packages/boto/file/connection.py deleted file mode 100644 index 2507e2db0b..0000000000 --- a/awx/lib/site-packages/boto/file/connection.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# File representation of connection, for use with "file://" URIs. - -from boto.file.bucket import Bucket - -class FileConnection(object): - - def __init__(self, file_storage_uri): - # FileConnections are per-file storage URI. - self.file_storage_uri = file_storage_uri - - def get_bucket(self, bucket_name, validate=True, headers=None): - return Bucket(bucket_name, self.file_storage_uri.object_name) diff --git a/awx/lib/site-packages/boto/file/key.py b/awx/lib/site-packages/boto/file/key.py deleted file mode 100644 index 3ec345d464..0000000000 --- a/awx/lib/site-packages/boto/file/key.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright 2010 Google Inc. -# Copyright (c) 2011, Nexenta Systems Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# File representation of key, for use with "file://" URIs. - -import os, shutil -import sys - -from boto.compat import StringIO - -class Key(object): - - KEY_STREAM_READABLE = 0x01 - KEY_STREAM_WRITABLE = 0x02 - KEY_STREAM = (KEY_STREAM_READABLE | KEY_STREAM_WRITABLE) - KEY_REGULAR_FILE = 0x00 - - def __init__(self, bucket, name, fp=None, key_type=KEY_REGULAR_FILE): - self.bucket = bucket - self.full_path = name - if name == '-': - self.name = None - self.size = None - else: - self.name = name - self.size = os.stat(name).st_size - self.key_type = key_type - if key_type == self.KEY_STREAM_READABLE: - self.fp = sys.stdin - self.full_path = '<STDIN>' - elif key_type == self.KEY_STREAM_WRITABLE: - self.fp = sys.stdout - self.full_path = '<STDOUT>' - else: - self.fp = fp - - def __str__(self): - return 'file://' + self.full_path - - def get_file(self, fp, headers=None, cb=None, num_cb=10, torrent=False): - """ - Retrieves a file from a Key - - :type fp: file - :param fp: File pointer to put the data into - - :type headers: string - :param: ignored in this subclass. - - :type cb: function - :param cb: ignored in this subclass. - - :type cb: int - :param num_cb: ignored in this subclass. - """ - if self.key_type & self.KEY_STREAM_WRITABLE: - raise BotoClientError('Stream is not readable') - elif self.key_type & self.KEY_STREAM_READABLE: - key_file = self.fp - else: - key_file = open(self.full_path, 'rb') - try: - shutil.copyfileobj(key_file, fp) - finally: - key_file.close() - - def set_contents_from_file(self, fp, headers=None, replace=True, cb=None, - num_cb=10, policy=None, md5=None): - """ - Store an object in a file using the name of the Key object as the - key in file URI and the contents of the file pointed to by 'fp' as the - contents. - - :type fp: file - :param fp: the file whose contents to upload - - :type headers: dict - :param headers: ignored in this subclass. - - :type replace: bool - :param replace: If this parameter is False, the method - will first check to see if an object exists in the - bucket with the same key. If it does, it won't - overwrite it. The default value is True which will - overwrite the object. - - :type cb: function - :param cb: ignored in this subclass. - - :type cb: int - :param num_cb: ignored in this subclass. - - :type policy: :class:`boto.s3.acl.CannedACLStrings` - :param policy: ignored in this subclass. - - :type md5: A tuple containing the hexdigest version of the MD5 checksum - of the file as the first element and the Base64-encoded - version of the plain checksum as the second element. - This is the same format returned by the compute_md5 method. - :param md5: ignored in this subclass. - """ - if self.key_type & self.KEY_STREAM_READABLE: - raise BotoClientError('Stream is not writable') - elif self.key_type & self.KEY_STREAM_WRITABLE: - key_file = self.fp - else: - if not replace and os.path.exists(self.full_path): - return - key_file = open(self.full_path, 'wb') - try: - shutil.copyfileobj(fp, key_file) - finally: - key_file.close() - - def get_contents_to_file(self, fp, headers=None, cb=None, num_cb=None, - torrent=False, version_id=None, - res_download_handler=None, response_headers=None): - """ - Copy contents from the current file to the file pointed to by 'fp'. - - :type fp: File-like object - :param fp: - - :type headers: dict - :param headers: Unused in this subclass. - - :type cb: function - :param cb: Unused in this subclass. - - :type cb: int - :param num_cb: Unused in this subclass. - - :type torrent: bool - :param torrent: Unused in this subclass. - - :type res_upload_handler: ResumableDownloadHandler - :param res_download_handler: Unused in this subclass. - - :type response_headers: dict - :param response_headers: Unused in this subclass. - """ - shutil.copyfileobj(self.fp, fp) - - def get_contents_as_string(self, headers=None, cb=None, num_cb=10, - torrent=False): - """ - Retrieve file data from the Key, and return contents as a string. - - :type headers: dict - :param headers: ignored in this subclass. - - :type cb: function - :param cb: ignored in this subclass. - - :type cb: int - :param num_cb: ignored in this subclass. - - :type cb: int - :param num_cb: ignored in this subclass. - - :type torrent: bool - :param torrent: ignored in this subclass. - - :rtype: string - :returns: The contents of the file as a string - """ - - fp = StringIO() - self.get_contents_to_file(fp) - return fp.getvalue() - - def is_stream(self): - return (self.key_type & self.KEY_STREAM) - - def close(self): - """ - Closes fp associated with underlying file. - Caller should call this method when done with this class, to avoid - using up OS resources (e.g., when iterating over a large number - of files). - """ - self.fp.close() diff --git a/awx/lib/site-packages/boto/file/simpleresultset.py b/awx/lib/site-packages/boto/file/simpleresultset.py deleted file mode 100644 index 5f94dc1165..0000000000 --- a/awx/lib/site-packages/boto/file/simpleresultset.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class SimpleResultSet(list): - """ - ResultSet facade built from a simple list, rather than via XML parsing. - """ - - def __init__(self, input_list): - for x in input_list: - self.append(x) - self.is_truncated = False diff --git a/awx/lib/site-packages/boto/fps/__init__.py b/awx/lib/site-packages/boto/fps/__init__.py deleted file mode 100644 index d69b7f08a4..0000000000 --- a/awx/lib/site-packages/boto/fps/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2008, Chris Moyer http://coredumped.org -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# diff --git a/awx/lib/site-packages/boto/fps/connection.py b/awx/lib/site-packages/boto/fps/connection.py deleted file mode 100644 index 6dc90a248e..0000000000 --- a/awx/lib/site-packages/boto/fps/connection.py +++ /dev/null @@ -1,395 +0,0 @@ -# Copyright (c) 2012 Andy Davidoff http://www.disruptek.com/ -# Copyright (c) 2010 Jason R. Coombs http://www.jaraco.com/ -# Copyright (c) 2008 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import urllib -import uuid -from boto.connection import AWSQueryConnection -from boto.fps.exception import ResponseErrorFactory -from boto.fps.response import ResponseFactory -import boto.fps.response - -__all__ = ['FPSConnection'] - -decorated_attrs = ('action', 'response') - - -def add_attrs_from(func, to): - for attr in decorated_attrs: - setattr(to, attr, getattr(func, attr, None)) - return to - - -def complex_amounts(*fields): - def decorator(func): - def wrapper(self, *args, **kw): - for field in filter(kw.has_key, fields): - amount = kw.pop(field) - kw[field + '.Value'] = getattr(amount, 'Value', str(amount)) - kw[field + '.CurrencyCode'] = getattr(amount, 'CurrencyCode', - self.currencycode) - return func(self, *args, **kw) - wrapper.__doc__ = "{0}\nComplex Amounts: {1}".format(func.__doc__, - ', '.join(fields)) - return add_attrs_from(func, to=wrapper) - return decorator - - -def requires(*groups): - - def decorator(func): - - def wrapper(*args, **kw): - hasgroup = lambda x: len(x) == len(filter(kw.has_key, x)) - if 1 != len(filter(hasgroup, groups)): - message = ' OR '.join(['+'.join(g) for g in groups]) - message = "{0} requires {1} argument(s)" \ - "".format(getattr(func, 'action', 'Method'), message) - raise KeyError(message) - return func(*args, **kw) - message = ' OR '.join(['+'.join(g) for g in groups]) - wrapper.__doc__ = "{0}\nRequired: {1}".format(func.__doc__, - message) - return add_attrs_from(func, to=wrapper) - return decorator - - -def needs_caller_reference(func): - - def wrapper(*args, **kw): - kw.setdefault('CallerReference', uuid.uuid4()) - return func(*args, **kw) - wrapper.__doc__ = "{0}\nUses CallerReference, defaults " \ - "to uuid.uuid4()".format(func.__doc__) - return add_attrs_from(func, to=wrapper) - - -def api_action(*api): - - def decorator(func): - action = ''.join(api or map(str.capitalize, func.__name__.split('_'))) - response = ResponseFactory(action) - if hasattr(boto.fps.response, action + 'Response'): - response = getattr(boto.fps.response, action + 'Response') - - def wrapper(self, *args, **kw): - return func(self, action, response, *args, **kw) - wrapper.action, wrapper.response = action, response - wrapper.__doc__ = "FPS {0} API call\n{1}".format(action, - func.__doc__) - return wrapper - return decorator - - -class FPSConnection(AWSQueryConnection): - - APIVersion = '2010-08-28' - ResponseError = ResponseErrorFactory - currencycode = 'USD' - - def __init__(self, *args, **kw): - self.currencycode = kw.pop('CurrencyCode', self.currencycode) - kw.setdefault('host', 'fps.sandbox.amazonaws.com') - super(FPSConnection, self).__init__(*args, **kw) - - def _required_auth_capability(self): - return ['fps'] - - @needs_caller_reference - @complex_amounts('SettlementAmount') - @requires(['CreditInstrumentId', 'SettlementAmount.Value', - 'SenderTokenId', 'SettlementAmount.CurrencyCode']) - @api_action() - def settle_debt(self, action, response, **kw): - """ - Allows a caller to initiate a transaction that atomically transfers - money from a sender's payment instrument to the recipient, while - decreasing corresponding debt balance. - """ - return self.get_object(action, kw, response) - - @requires(['TransactionId']) - @api_action() - def get_transaction_status(self, action, response, **kw): - """ - Gets the latest status of a transaction. - """ - return self.get_object(action, kw, response) - - @requires(['StartDate']) - @api_action() - def get_account_activity(self, action, response, **kw): - """ - Returns transactions for a given date range. - """ - return self.get_object(action, kw, response) - - @requires(['TransactionId']) - @api_action() - def get_transaction(self, action, response, **kw): - """ - Returns all details of a transaction. - """ - return self.get_object(action, kw, response) - - @api_action() - def get_outstanding_debt_balance(self, action, response): - """ - Returns the total outstanding balance for all the credit instruments - for the given creditor account. - """ - return self.get_object(action, {}, response) - - @requires(['PrepaidInstrumentId']) - @api_action() - def get_prepaid_balance(self, action, response, **kw): - """ - Returns the balance available on the given prepaid instrument. - """ - return self.get_object(action, kw, response) - - @api_action() - def get_total_prepaid_liability(self, action, response): - """ - Returns the total liability held by the given account corresponding to - all the prepaid instruments owned by the account. - """ - return self.get_object(action, {}, response) - - @api_action() - def get_account_balance(self, action, response): - """ - Returns the account balance for an account in real time. - """ - return self.get_object(action, {}, response) - - @needs_caller_reference - @requires(['PaymentInstruction', 'TokenType']) - @api_action() - def install_payment_instruction(self, action, response, **kw): - """ - Installs a payment instruction for caller. - """ - return self.get_object(action, kw, response) - - @needs_caller_reference - @requires(['returnURL', 'pipelineName']) - def cbui_url(self, **kw): - """ - Generate a signed URL for the Co-Branded service API given arguments as - payload. - """ - sandbox = 'sandbox' in self.host and 'payments-sandbox' or 'payments' - endpoint = 'authorize.{0}.amazon.com'.format(sandbox) - base = '/cobranded-ui/actions/start' - - validpipelines = ('SingleUse', 'MultiUse', 'Recurring', 'Recipient', - 'SetupPrepaid', 'SetupPostpaid', 'EditToken') - assert kw['pipelineName'] in validpipelines, "Invalid pipelineName" - kw.update({ - 'signatureMethod': 'HmacSHA256', - 'signatureVersion': '2', - }) - kw.setdefault('callerKey', self.aws_access_key_id) - - safestr = lambda x: x is not None and str(x) or '' - safequote = lambda x: urllib.quote(safestr(x), safe='~') - payload = sorted([(k, safequote(v)) for k, v in kw.items()]) - - encoded = lambda p: '&'.join([k + '=' + v for k, v in p]) - canonical = '\n'.join(['GET', endpoint, base, encoded(payload)]) - signature = self._auth_handler.sign_string(canonical) - payload += [('signature', safequote(signature))] - payload.sort() - - return 'https://{0}{1}?{2}'.format(endpoint, base, encoded(payload)) - - @needs_caller_reference - @complex_amounts('TransactionAmount') - @requires(['SenderTokenId', 'TransactionAmount.Value', - 'TransactionAmount.CurrencyCode']) - @api_action() - def reserve(self, action, response, **kw): - """ - Reserve API is part of the Reserve and Settle API conjunction that - serve the purpose of a pay where the authorization and settlement have - a timing difference. - """ - return self.get_object(action, kw, response) - - @needs_caller_reference - @complex_amounts('TransactionAmount') - @requires(['SenderTokenId', 'TransactionAmount.Value', - 'TransactionAmount.CurrencyCode']) - @api_action() - def pay(self, action, response, **kw): - """ - Allows calling applications to move money from a sender to a recipient. - """ - return self.get_object(action, kw, response) - - @requires(['TransactionId']) - @api_action() - def cancel(self, action, response, **kw): - """ - Cancels an ongoing transaction and puts it in cancelled state. - """ - return self.get_object(action, kw, response) - - @complex_amounts('TransactionAmount') - @requires(['ReserveTransactionId', 'TransactionAmount.Value', - 'TransactionAmount.CurrencyCode']) - @api_action() - def settle(self, action, response, **kw): - """ - The Settle API is used in conjunction with the Reserve API and is used - to settle previously reserved transaction. - """ - return self.get_object(action, kw, response) - - @complex_amounts('RefundAmount') - @requires(['TransactionId', 'RefundAmount.Value', - 'CallerReference', 'RefundAmount.CurrencyCode']) - @api_action() - def refund(self, action, response, **kw): - """ - Refunds a previously completed transaction. - """ - return self.get_object(action, kw, response) - - @requires(['RecipientTokenId']) - @api_action() - def get_recipient_verification_status(self, action, response, **kw): - """ - Returns the recipient status. - """ - return self.get_object(action, kw, response) - - @requires(['CallerReference'], ['TokenId']) - @api_action() - def get_token_by_caller(self, action, response, **kw): - """ - Returns the details of a particular token installed by this calling - application using the subway co-branded UI. - """ - return self.get_object(action, kw, response) - - @requires(['UrlEndPoint', 'HttpParameters']) - @api_action() - def verify_signature(self, action, response, **kw): - """ - Verify the signature that FPS sent in IPN or callback urls. - """ - return self.get_object(action, kw, response) - - @api_action() - def get_tokens(self, action, response, **kw): - """ - Returns a list of tokens installed on the given account. - """ - return self.get_object(action, kw, response) - - @requires(['TokenId']) - @api_action() - def get_token_usage(self, action, response, **kw): - """ - Returns the usage of a token. - """ - return self.get_object(action, kw, response) - - @requires(['TokenId']) - @api_action() - def cancel_token(self, action, response, **kw): - """ - Cancels any token installed by the calling application on its own - account. - """ - return self.get_object(action, kw, response) - - @needs_caller_reference - @complex_amounts('FundingAmount') - @requires(['PrepaidInstrumentId', 'FundingAmount.Value', - 'SenderTokenId', 'FundingAmount.CurrencyCode']) - @api_action() - def fund_prepaid(self, action, response, **kw): - """ - Funds the prepaid balance on the given prepaid instrument. - """ - return self.get_object(action, kw, response) - - @requires(['CreditInstrumentId']) - @api_action() - def get_debt_balance(self, action, response, **kw): - """ - Returns the balance corresponding to the given credit instrument. - """ - return self.get_object(action, kw, response) - - @needs_caller_reference - @complex_amounts('AdjustmentAmount') - @requires(['CreditInstrumentId', 'AdjustmentAmount.Value', - 'AdjustmentAmount.CurrencyCode']) - @api_action() - def write_off_debt(self, action, response, **kw): - """ - Allows a creditor to write off the debt balance accumulated partially - or fully at any time. - """ - return self.get_object(action, kw, response) - - @requires(['SubscriptionId']) - @api_action() - def get_transactions_for_subscription(self, action, response, **kw): - """ - Returns the transactions for a given subscriptionID. - """ - return self.get_object(action, kw, response) - - @requires(['SubscriptionId']) - @api_action() - def get_subscription_details(self, action, response, **kw): - """ - Returns the details of Subscription for a given subscriptionID. - """ - return self.get_object(action, kw, response) - - @needs_caller_reference - @complex_amounts('RefundAmount') - @requires(['SubscriptionId']) - @api_action() - def cancel_subscription_and_refund(self, action, response, **kw): - """ - Cancels a subscription. - """ - message = "If you specify a RefundAmount, " \ - "you must specify CallerReference." - assert not 'RefundAmount.Value' in kw \ - or 'CallerReference' in kw, message - return self.get_object(action, kw, response) - - @requires(['TokenId']) - @api_action() - def get_payment_instruction(self, action, response, **kw): - """ - Gets the payment instruction of a token. - """ - return self.get_object(action, kw, response) diff --git a/awx/lib/site-packages/boto/fps/exception.py b/awx/lib/site-packages/boto/fps/exception.py deleted file mode 100644 index bebb86b787..0000000000 --- a/awx/lib/site-packages/boto/fps/exception.py +++ /dev/null @@ -1,344 +0,0 @@ -from boto.exception import BotoServerError - - -class ResponseErrorFactory(BotoServerError): - - def __new__(cls, *args, **kw): - error = BotoServerError(*args, **kw) - newclass = globals().get(error.error_code, ResponseError) - obj = newclass.__new__(newclass, *args, **kw) - obj.__dict__.update(error.__dict__) - return obj - - -class ResponseError(BotoServerError): - """Undefined response error. - """ - retry = False - - def __repr__(self): - return '{0}({1}, {2},\n\t{3})'.format(self.__class__.__name__, - self.status, self.reason, - self.error_message) - - def __str__(self): - return 'FPS Response Error: {0.status} {0.__class__.__name__} {1}\n' \ - '{2}\n' \ - '{0.error_message}'.format(self, - self.retry and '(Retriable)' or '', - self.__doc__.strip()) - - -class RetriableResponseError(ResponseError): - retry = True - - -class AccessFailure(RetriableResponseError): - """Account cannot be accessed. - """ - - -class AccountClosed(RetriableResponseError): - """Account is not active. - """ - - -class AccountLimitsExceeded(RetriableResponseError): - """The spending or receiving limit on the account is exceeded. - """ - - -class AmountOutOfRange(ResponseError): - """The transaction amount is more than the allowed range. - """ - - -class AuthFailure(RetriableResponseError): - """AWS was not able to validate the provided access credentials. - """ - - -class ConcurrentModification(RetriableResponseError): - """A retriable error can happen when two processes try to modify the - same data at the same time. - """ - - -class DuplicateRequest(ResponseError): - """A different request associated with this caller reference already - exists. - """ - - -class InactiveInstrument(ResponseError): - """Payment instrument is inactive. - """ - - -class IncompatibleTokens(ResponseError): - """The transaction could not be completed because the tokens have - incompatible payment instructions. - """ - - -class InstrumentAccessDenied(ResponseError): - """The external calling application is not the recipient for this - postpaid or prepaid instrument. - """ - - -class InstrumentExpired(ResponseError): - """The prepaid or the postpaid instrument has expired. - """ - - -class InsufficientBalance(RetriableResponseError): - """The sender, caller, or recipient's account balance has - insufficient funds to complete the transaction. - """ - - -class InternalError(RetriableResponseError): - """A retriable error that happens due to some transient problem in - the system. - """ - - -class InvalidAccountState(RetriableResponseError): - """The account is either suspended or closed. - """ - - -class InvalidAccountState_Caller(RetriableResponseError): - """The developer account cannot participate in the transaction. - """ - - -class InvalidAccountState_Recipient(RetriableResponseError): - """Recipient account cannot participate in the transaction. - """ - - -class InvalidAccountState_Sender(RetriableResponseError): - """Sender account cannot participate in the transaction. - """ - - -class InvalidCallerReference(ResponseError): - """The Caller Reference does not have a token associated with it. - """ - - -class InvalidClientTokenId(ResponseError): - """The AWS Access Key Id you provided does not exist in our records. - """ - - -class InvalidDateRange(ResponseError): - """The end date specified is before the start date or the start date - is in the future. - """ - - -class InvalidParams(ResponseError): - """One or more parameters in the request is invalid. - """ - - -class InvalidPaymentInstrument(ResponseError): - """The payment method used in the transaction is invalid. - """ - - -class InvalidPaymentMethod(ResponseError): - """Specify correct payment method. - """ - - -class InvalidRecipientForCCTransaction(ResponseError): - """This account cannot receive credit card payments. - """ - - -class InvalidSenderRoleForAccountType(ResponseError): - """This token cannot be used for this operation. - """ - - -class InvalidTokenId(ResponseError): - """You did not install the token that you are trying to cancel. - """ - - -class InvalidTokenId_Recipient(ResponseError): - """The recipient token specified is either invalid or canceled. - """ - - -class InvalidTokenId_Sender(ResponseError): - """The sender token specified is either invalid or canceled or the - token is not active. - """ - - -class InvalidTokenType(ResponseError): - """An invalid operation was performed on the token, for example, - getting the token usage information on a single use token. - """ - - -class InvalidTransactionId(ResponseError): - """The specified transaction could not be found or the caller did not - execute the transaction or this is not a Pay or Reserve call. - """ - - -class InvalidTransactionState(ResponseError): - """The transaction is not complete, or it has temporarily failed. - """ - - -class NotMarketplaceApp(RetriableResponseError): - """This is not an marketplace application or the caller does not - match either the sender or the recipient. - """ - - -class OriginalTransactionFailed(ResponseError): - """The original transaction has failed. - """ - - -class OriginalTransactionIncomplete(RetriableResponseError): - """The original transaction is still in progress. - """ - - -class PaymentInstrumentNotCC(ResponseError): - """The payment method specified in the transaction is not a credit - card. You can only use a credit card for this transaction. - """ - - -class PaymentMethodNotDefined(ResponseError): - """Payment method is not defined in the transaction. - """ - - -class PrepaidFundingLimitExceeded(RetriableResponseError): - """An attempt has been made to fund the prepaid instrument - at a level greater than its recharge limit. - """ - - -class RefundAmountExceeded(ResponseError): - """The refund amount is more than the refundable amount. - """ - - -class SameSenderAndRecipient(ResponseError): - """The sender and receiver are identical, which is not allowed. - """ - - -class SameTokenIdUsedMultipleTimes(ResponseError): - """This token is already used in earlier transactions. - """ - - -class SenderNotOriginalRecipient(ResponseError): - """The sender in the refund transaction is not - the recipient of the original transaction. - """ - - -class SettleAmountGreaterThanDebt(ResponseError): - """The amount being settled or written off is - greater than the current debt. - """ - - -class SettleAmountGreaterThanReserveAmount(ResponseError): - """The amount being settled is greater than the reserved amount. - """ - - -class SignatureDoesNotMatch(ResponseError): - """The request signature calculated by Amazon does not match the - signature you provided. - """ - - -class TokenAccessDenied(ResponseError): - """Permission to cancel the token is denied. - """ - - -class TokenNotActive(ResponseError): - """The token is canceled. - """ - - -class TokenNotActive_Recipient(ResponseError): - """The recipient token is canceled. - """ - - -class TokenNotActive_Sender(ResponseError): - """The sender token is canceled. - """ - - -class TokenUsageError(ResponseError): - """The token usage limit is exceeded. - """ - - -class TransactionDenied(ResponseError): - """The transaction is not allowed. - """ - - -class TransactionFullyRefundedAlready(ResponseError): - """The transaction has already been completely refunded. - """ - - -class TransactionTypeNotRefundable(ResponseError): - """You cannot refund this transaction. - """ - - -class UnverifiedAccount_Recipient(ResponseError): - """The recipient's account must have a verified bank account or a - credit card before this transaction can be initiated. - """ - - -class UnverifiedAccount_Sender(ResponseError): - """The sender's account must have a verified U.S. credit card or - a verified U.S bank account before this transaction can be - initiated. - """ - - -class UnverifiedBankAccount(ResponseError): - """A verified bank account should be used for this transaction. - """ - - -class UnverifiedEmailAddress_Caller(ResponseError): - """The caller account must have a verified email address. - """ - - -class UnverifiedEmailAddress_Recipient(ResponseError): - """The recipient account must have a verified - email address for receiving payments. - """ - - -class UnverifiedEmailAddress_Sender(ResponseError): - """The sender account must have a verified - email address for this payment. - """ diff --git a/awx/lib/site-packages/boto/fps/response.py b/awx/lib/site-packages/boto/fps/response.py deleted file mode 100644 index c0a9e2837f..0000000000 --- a/awx/lib/site-packages/boto/fps/response.py +++ /dev/null @@ -1,207 +0,0 @@ -# Copyright (c) 2012 Andy Davidoff http://www.disruptek.com/ -# Copyright (c) 2010 Jason R. Coombs http://www.jaraco.com/ -# Copyright (c) 2008 Chris Moyer http://coredumped.org/ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from decimal import Decimal -from boto.compat import filter, map - - -def ResponseFactory(action): - class FPSResponse(Response): - _action = action - _Result = globals().get(action + 'Result', ResponseElement) - - # due to nodes receiving their closing tags - def endElement(self, name, value, connection): - if name != action + 'Response': - super(FPSResponse, self).endElement(name, value, connection) - return FPSResponse - - -class ResponseElement(object): - def __init__(self, connection=None, name=None): - if connection is not None: - self._connection = connection - self._name = name or self.__class__.__name__ - - @property - def connection(self): - return self._connection - - def __repr__(self): - render = lambda pair: '{!s}: {!r}'.format(*pair) - do_show = lambda pair: not pair[0].startswith('_') - attrs = filter(do_show, self.__dict__.items()) - return '{0}({1})'.format(self.__class__.__name__, - ', '.join(map(render, attrs))) - - def startElement(self, name, attrs, connection): - return None - - # due to nodes receiving their closing tags - def endElement(self, name, value, connection): - if name != self._name: - setattr(self, name, value) - - -class Response(ResponseElement): - _action = 'Undefined' - - def startElement(self, name, attrs, connection): - if name == 'ResponseMetadata': - setattr(self, name, ResponseElement(name=name)) - elif name == self._action + 'Result': - setattr(self, name, self._Result(name=name)) - else: - return super(Response, self).startElement(name, attrs, connection) - return getattr(self, name) - - -class ComplexAmount(ResponseElement): - def __repr__(self): - return '{0} {1}'.format(self.CurrencyCode, self.Value) - - def __float__(self): - return float(self.Value) - - def __str__(self): - return str(self.Value) - - def startElement(self, name, attrs, connection): - if name not in ('CurrencyCode', 'Value'): - message = 'Unrecognized tag {0} in ComplexAmount'.format(name) - raise AssertionError(message) - return super(ComplexAmount, self).startElement(name, attrs, connection) - - def endElement(self, name, value, connection): - if name == 'Value': - value = Decimal(value) - super(ComplexAmount, self).endElement(name, value, connection) - - -class AmountCollection(ResponseElement): - def startElement(self, name, attrs, connection): - setattr(self, name, ComplexAmount(name=name)) - return getattr(self, name) - - -class AccountBalance(AmountCollection): - def startElement(self, name, attrs, connection): - if name == 'AvailableBalances': - setattr(self, name, AmountCollection(name=name)) - return getattr(self, name) - return super(AccountBalance, self).startElement(name, attrs, connection) - - -class GetAccountBalanceResult(ResponseElement): - def startElement(self, name, attrs, connection): - if name == 'AccountBalance': - setattr(self, name, AccountBalance(name=name)) - return getattr(self, name) - return super(GetAccountBalanceResult, self).startElement(name, attrs, - connection) - - -class GetTotalPrepaidLiabilityResult(ResponseElement): - def startElement(self, name, attrs, connection): - if name == 'OutstandingPrepaidLiability': - setattr(self, name, AmountCollection(name=name)) - return getattr(self, name) - return super(GetTotalPrepaidLiabilityResult, self).startElement(name, - attrs, connection) - - -class GetPrepaidBalanceResult(ResponseElement): - def startElement(self, name, attrs, connection): - if name == 'PrepaidBalance': - setattr(self, name, AmountCollection(name=name)) - return getattr(self, name) - return super(GetPrepaidBalanceResult, self).startElement(name, attrs, - connection) - - -class GetOutstandingDebtBalanceResult(ResponseElement): - def startElement(self, name, attrs, connection): - if name == 'OutstandingDebt': - setattr(self, name, AmountCollection(name=name)) - return getattr(self, name) - return super(GetOutstandingDebtBalanceResult, self).startElement(name, - attrs, connection) - - -class TransactionPart(ResponseElement): - def startElement(self, name, attrs, connection): - if name == 'FeesPaid': - setattr(self, name, ComplexAmount(name=name)) - return getattr(self, name) - return super(TransactionPart, self).startElement(name, attrs, - connection) - - -class Transaction(ResponseElement): - def __init__(self, *args, **kw): - self.TransactionPart = [] - super(Transaction, self).__init__(*args, **kw) - - def startElement(self, name, attrs, connection): - if name == 'TransactionPart': - getattr(self, name).append(TransactionPart(name=name)) - return getattr(self, name)[-1] - if name in ('TransactionAmount', 'FPSFees', 'Balance'): - setattr(self, name, ComplexAmount(name=name)) - return getattr(self, name) - return super(Transaction, self).startElement(name, attrs, connection) - - -class GetAccountActivityResult(ResponseElement): - def __init__(self, *args, **kw): - self.Transaction = [] - super(GetAccountActivityResult, self).__init__(*args, **kw) - - def startElement(self, name, attrs, connection): - if name == 'Transaction': - getattr(self, name).append(Transaction(name=name)) - return getattr(self, name)[-1] - return super(GetAccountActivityResult, self).startElement(name, attrs, - connection) - - -class GetTransactionResult(ResponseElement): - def startElement(self, name, attrs, connection): - if name == 'Transaction': - setattr(self, name, Transaction(name=name)) - return getattr(self, name) - return super(GetTransactionResult, self).startElement(name, attrs, - connection) - - -class GetTokensResult(ResponseElement): - def __init__(self, *args, **kw): - self.Token = [] - super(GetTokensResult, self).__init__(*args, **kw) - - def startElement(self, name, attrs, connection): - if name == 'Token': - getattr(self, name).append(ResponseElement(name=name)) - return getattr(self, name)[-1] - return super(GetTokensResult, self).startElement(name, attrs, - connection) diff --git a/awx/lib/site-packages/boto/glacier/__init__.py b/awx/lib/site-packages/boto/glacier/__init__.py deleted file mode 100644 index 713740b429..0000000000 --- a/awx/lib/site-packages/boto/glacier/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon Glacier service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.glacier.layer2 import Layer2 - return get_regions('glacier', connection_cls=Layer2) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/glacier/concurrent.py b/awx/lib/site-packages/boto/glacier/concurrent.py deleted file mode 100644 index a4f3a224a0..0000000000 --- a/awx/lib/site-packages/boto/glacier/concurrent.py +++ /dev/null @@ -1,425 +0,0 @@ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import os -import math -import threading -import hashlib -import time -import logging -from boto.compat import Queue -import binascii - -from boto.glacier.utils import DEFAULT_PART_SIZE, minimum_part_size, \ - chunk_hashes, tree_hash, bytes_to_hex -from boto.glacier.exceptions import UploadArchiveError, \ - DownloadArchiveError, \ - TreeHashDoesNotMatchError - - -_END_SENTINEL = object() -log = logging.getLogger('boto.glacier.concurrent') - - -class ConcurrentTransferer(object): - def __init__(self, part_size=DEFAULT_PART_SIZE, num_threads=10): - self._part_size = part_size - self._num_threads = num_threads - self._threads = [] - - def _calculate_required_part_size(self, total_size): - min_part_size_required = minimum_part_size(total_size) - if self._part_size >= min_part_size_required: - part_size = self._part_size - else: - part_size = min_part_size_required - log.debug("The part size specified (%s) is smaller than " - "the minimum required part size. Using a part " - "size of: %s", self._part_size, part_size) - total_parts = int(math.ceil(total_size / float(part_size))) - return total_parts, part_size - - def _shutdown_threads(self): - log.debug("Shutting down threads.") - for thread in self._threads: - thread.should_continue = False - for thread in self._threads: - thread.join() - log.debug("Threads have exited.") - - def _add_work_items_to_queue(self, total_parts, worker_queue, part_size): - log.debug("Adding work items to queue.") - for i in range(total_parts): - worker_queue.put((i, part_size)) - for i in range(self._num_threads): - worker_queue.put(_END_SENTINEL) - - -class ConcurrentUploader(ConcurrentTransferer): - """Concurrently upload an archive to glacier. - - This class uses a thread pool to concurrently upload an archive - to glacier using the multipart upload API. - - The threadpool is completely managed by this class and is - transparent to the users of this class. - - """ - def __init__(self, api, vault_name, part_size=DEFAULT_PART_SIZE, - num_threads=10): - """ - :type api: :class:`boto.glacier.layer1.Layer1` - :param api: A layer1 glacier object. - - :type vault_name: str - :param vault_name: The name of the vault. - - :type part_size: int - :param part_size: The size, in bytes, of the chunks to use when uploading - the archive parts. The part size must be a megabyte multiplied by - a power of two. - - :type num_threads: int - :param num_threads: The number of threads to spawn for the thread pool. - The number of threads will control how much parts are being - concurrently uploaded. - - """ - super(ConcurrentUploader, self).__init__(part_size, num_threads) - self._api = api - self._vault_name = vault_name - - def upload(self, filename, description=None): - """Concurrently create an archive. - - The part_size value specified when the class was constructed - will be used *unless* it is smaller than the minimum required - part size needed for the size of the given file. In that case, - the part size used will be the minimum part size required - to properly upload the given file. - - :type file: str - :param file: The filename to upload - - :type description: str - :param description: The description of the archive. - - :rtype: str - :return: The archive id of the newly created archive. - - """ - total_size = os.stat(filename).st_size - total_parts, part_size = self._calculate_required_part_size(total_size) - hash_chunks = [None] * total_parts - worker_queue = Queue() - result_queue = Queue() - response = self._api.initiate_multipart_upload(self._vault_name, - part_size, - description) - upload_id = response['UploadId'] - # The basic idea is to add the chunks (the offsets not the actual - # contents) to a work queue, start up a thread pool, let the crank - # through the items in the work queue, and then place their results - # in a result queue which we use to complete the multipart upload. - self._add_work_items_to_queue(total_parts, worker_queue, part_size) - self._start_upload_threads(result_queue, upload_id, - worker_queue, filename) - try: - self._wait_for_upload_threads(hash_chunks, result_queue, - total_parts) - except UploadArchiveError as e: - log.debug("An error occurred while uploading an archive, " - "aborting multipart upload.") - self._api.abort_multipart_upload(self._vault_name, upload_id) - raise e - log.debug("Completing upload.") - response = self._api.complete_multipart_upload( - self._vault_name, upload_id, bytes_to_hex(tree_hash(hash_chunks)), - total_size) - log.debug("Upload finished.") - return response['ArchiveId'] - - def _wait_for_upload_threads(self, hash_chunks, result_queue, total_parts): - for _ in range(total_parts): - result = result_queue.get() - if isinstance(result, Exception): - log.debug("An error was found in the result queue, terminating " - "threads: %s", result) - self._shutdown_threads() - raise UploadArchiveError("An error occurred while uploading " - "an archive: %s" % result) - # Each unit of work returns the tree hash for the given part - # number, which we use at the end to compute the tree hash of - # the entire archive. - part_number, tree_sha256 = result - hash_chunks[part_number] = tree_sha256 - self._shutdown_threads() - - def _start_upload_threads(self, result_queue, upload_id, worker_queue, - filename): - log.debug("Starting threads.") - for _ in range(self._num_threads): - thread = UploadWorkerThread(self._api, self._vault_name, filename, - upload_id, worker_queue, result_queue) - time.sleep(0.2) - thread.start() - self._threads.append(thread) - - -class TransferThread(threading.Thread): - def __init__(self, worker_queue, result_queue): - super(TransferThread, self).__init__() - self._worker_queue = worker_queue - self._result_queue = result_queue - # This value can be set externally by other objects - # to indicate that the thread should be shut down. - self.should_continue = True - - def run(self): - while self.should_continue: - try: - work = self._worker_queue.get(timeout=1) - except Empty: - continue - if work is _END_SENTINEL: - self._cleanup() - return - result = self._process_chunk(work) - self._result_queue.put(result) - self._cleanup() - - def _process_chunk(self, work): - pass - - def _cleanup(self): - pass - - -class UploadWorkerThread(TransferThread): - def __init__(self, api, vault_name, filename, upload_id, - worker_queue, result_queue, num_retries=5, - time_between_retries=5, - retry_exceptions=Exception): - super(UploadWorkerThread, self).__init__(worker_queue, result_queue) - self._api = api - self._vault_name = vault_name - self._filename = filename - self._fileobj = open(filename, 'rb') - self._upload_id = upload_id - self._num_retries = num_retries - self._time_between_retries = time_between_retries - self._retry_exceptions = retry_exceptions - - def _process_chunk(self, work): - result = None - for i in range(self._num_retries + 1): - try: - result = self._upload_chunk(work) - break - except self._retry_exceptions as e: - log.error("Exception caught uploading part number %s for " - "vault %s, attempt: (%s / %s), filename: %s, " - "exception: %s, msg: %s", - work[0], self._vault_name, i + 1, self._num_retries + 1, - self._filename, e.__class__, e) - time.sleep(self._time_between_retries) - result = e - return result - - def _upload_chunk(self, work): - part_number, part_size = work - start_byte = part_number * part_size - self._fileobj.seek(start_byte) - contents = self._fileobj.read(part_size) - linear_hash = hashlib.sha256(contents).hexdigest() - tree_hash_bytes = tree_hash(chunk_hashes(contents)) - byte_range = (start_byte, start_byte + len(contents) - 1) - log.debug("Uploading chunk %s of size %s", part_number, part_size) - response = self._api.upload_part(self._vault_name, self._upload_id, - linear_hash, - bytes_to_hex(tree_hash_bytes), - byte_range, contents) - # Reading the response allows the connection to be reused. - response.read() - return (part_number, tree_hash_bytes) - - def _cleanup(self): - self._fileobj.close() - - -class ConcurrentDownloader(ConcurrentTransferer): - """ - Concurrently download an archive from glacier. - - This class uses a thread pool to concurrently download an archive - from glacier. - - The threadpool is completely managed by this class and is - transparent to the users of this class. - - """ - def __init__(self, job, part_size=DEFAULT_PART_SIZE, - num_threads=10): - """ - :param job: A layer2 job object for archive retrieval object. - - :param part_size: The size, in bytes, of the chunks to use when uploading - the archive parts. The part size must be a megabyte multiplied by - a power of two. - - """ - super(ConcurrentDownloader, self).__init__(part_size, num_threads) - self._job = job - - def download(self, filename): - """ - Concurrently download an archive. - - :param filename: The filename to download the archive to - :type filename: str - - """ - total_size = self._job.archive_size - total_parts, part_size = self._calculate_required_part_size(total_size) - worker_queue = Queue() - result_queue = Queue() - self._add_work_items_to_queue(total_parts, worker_queue, part_size) - self._start_download_threads(result_queue, worker_queue) - try: - self._wait_for_download_threads(filename, result_queue, total_parts) - except DownloadArchiveError as e: - log.debug("An error occurred while downloading an archive: %s", e) - raise e - log.debug("Download completed.") - - def _wait_for_download_threads(self, filename, result_queue, total_parts): - """ - Waits until the result_queue is filled with all the downloaded parts - This indicates that all part downloads have completed - - Saves downloaded parts into filename - - :param filename: - :param result_queue: - :param total_parts: - """ - hash_chunks = [None] * total_parts - with open(filename, "wb") as f: - for _ in range(total_parts): - result = result_queue.get() - if isinstance(result, Exception): - log.debug("An error was found in the result queue, " - "terminating threads: %s", result) - self._shutdown_threads() - raise DownloadArchiveError( - "An error occurred while uploading " - "an archive: %s" % result) - part_number, part_size, actual_hash, data = result - hash_chunks[part_number] = actual_hash - start_byte = part_number * part_size - f.seek(start_byte) - f.write(data) - f.flush() - final_hash = bytes_to_hex(tree_hash(hash_chunks)) - log.debug("Verifying final tree hash of archive, expecting: %s, " - "actual: %s", self._job.sha256_treehash, final_hash) - if self._job.sha256_treehash != final_hash: - self._shutdown_threads() - raise TreeHashDoesNotMatchError( - "Tree hash for entire archive does not match, " - "expected: %s, got: %s" % (self._job.sha256_treehash, - final_hash)) - self._shutdown_threads() - - def _start_download_threads(self, result_queue, worker_queue): - log.debug("Starting threads.") - for _ in range(self._num_threads): - thread = DownloadWorkerThread(self._job, worker_queue, result_queue) - time.sleep(0.2) - thread.start() - self._threads.append(thread) - - -class DownloadWorkerThread(TransferThread): - def __init__(self, job, - worker_queue, result_queue, - num_retries=5, - time_between_retries=5, - retry_exceptions=Exception): - """ - Individual download thread that will download parts of the file from Glacier. Parts - to download stored in work queue. - - Parts download to a temp dir with each part a separate file - - :param job: Glacier job object - :param work_queue: A queue of tuples which include the part_number and - part_size - :param result_queue: A priority queue of tuples which include the - part_number and the path to the temp file that holds that - part's data. - - """ - super(DownloadWorkerThread, self).__init__(worker_queue, result_queue) - self._job = job - self._num_retries = num_retries - self._time_between_retries = time_between_retries - self._retry_exceptions = retry_exceptions - - def _process_chunk(self, work): - """ - Attempt to download a part of the archive from Glacier - Store the result in the result_queue - - :param work: - """ - result = None - for _ in range(self._num_retries): - try: - result = self._download_chunk(work) - break - except self._retry_exceptions as e: - log.error("Exception caught downloading part number %s for " - "job %s", work[0], self._job,) - time.sleep(self._time_between_retries) - result = e - return result - - def _download_chunk(self, work): - """ - Downloads a chunk of archive from Glacier. Saves the data to a temp file - Returns the part number and temp file location - - :param work: - """ - part_number, part_size = work - start_byte = part_number * part_size - byte_range = (start_byte, start_byte + part_size - 1) - log.debug("Downloading chunk %s of size %s", part_number, part_size) - response = self._job.get_output(byte_range) - data = response.read() - actual_hash = bytes_to_hex(tree_hash(chunk_hashes(data))) - if response['TreeHash'] != actual_hash: - raise TreeHashDoesNotMatchError( - "Tree hash for part number %s does not match, " - "expected: %s, got: %s" % (part_number, response['TreeHash'], - actual_hash)) - return (part_number, part_size, binascii.unhexlify(actual_hash), data) diff --git a/awx/lib/site-packages/boto/glacier/exceptions.py b/awx/lib/site-packages/boto/glacier/exceptions.py deleted file mode 100644 index c8bce1fe9b..0000000000 --- a/awx/lib/site-packages/boto/glacier/exceptions.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.compat import json - - -class UnexpectedHTTPResponseError(Exception): - def __init__(self, expected_responses, response): - self.status = response.status - self.body = response.read() - self.code = None - try: - body = json.loads(self.body) - self.code = body["code"] - msg = 'Expected %s, got ' % expected_responses - msg += '(%d, code=%s, message=%s)' % (response.status, - self.code, - body["message"]) - except Exception: - msg = 'Expected %s, got (%d, %s)' % (expected_responses, - response.status, - self.body) - super(UnexpectedHTTPResponseError, self).__init__(msg) - - -class ArchiveError(Exception): - pass - - -class UploadArchiveError(ArchiveError): - pass - - -class DownloadArchiveError(ArchiveError): - pass - - -class TreeHashDoesNotMatchError(ArchiveError): - pass diff --git a/awx/lib/site-packages/boto/glacier/job.py b/awx/lib/site-packages/boto/glacier/job.py deleted file mode 100644 index 33e66a196c..0000000000 --- a/awx/lib/site-packages/boto/glacier/job.py +++ /dev/null @@ -1,177 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import math -import socket - -from boto.glacier.exceptions import TreeHashDoesNotMatchError, \ - DownloadArchiveError -from boto.glacier.utils import tree_hash_from_str - - -class Job(object): - - DefaultPartSize = 4 * 1024 * 1024 - - ResponseDataElements = (('Action', 'action', None), - ('ArchiveId', 'archive_id', None), - ('ArchiveSizeInBytes', 'archive_size', 0), - ('Completed', 'completed', False), - ('CompletionDate', 'completion_date', None), - ('CreationDate', 'creation_date', None), - ('InventorySizeInBytes', 'inventory_size', 0), - ('JobDescription', 'description', None), - ('JobId', 'id', None), - ('SHA256TreeHash', 'sha256_treehash', None), - ('SNSTopic', 'sns_topic', None), - ('StatusCode', 'status_code', None), - ('StatusMessage', 'status_message', None), - ('VaultARN', 'arn', None)) - - def __init__(self, vault, response_data=None): - self.vault = vault - if response_data: - for response_name, attr_name, default in self.ResponseDataElements: - setattr(self, attr_name, response_data[response_name]) - else: - for response_name, attr_name, default in self.ResponseDataElements: - setattr(self, attr_name, default) - - def __repr__(self): - return 'Job(%s)' % self.arn - - def get_output(self, byte_range=None, validate_checksum=False): - """ - This operation downloads the output of the job. Depending on - the job type you specified when you initiated the job, the - output will be either the content of an archive or a vault - inventory. - - You can download all the job output or download a portion of - the output by specifying a byte range. In the case of an - archive retrieval job, depending on the byte range you - specify, Amazon Glacier returns the checksum for the portion - of the data. You can compute the checksum on the client and - verify that the values match to ensure the portion you - downloaded is the correct data. - - :type byte_range: tuple - :param range: A tuple of integer specifying the slice (in bytes) - of the archive you want to receive - - :type validate_checksum: bool - :param validate_checksum: Specify whether or not to validate - the associate tree hash. If the response does not contain - a TreeHash, then no checksum will be verified. - - """ - response = self.vault.layer1.get_job_output(self.vault.name, - self.id, - byte_range) - if validate_checksum and 'TreeHash' in response: - data = response.read() - actual_tree_hash = tree_hash_from_str(data) - if response['TreeHash'] != actual_tree_hash: - raise TreeHashDoesNotMatchError( - "The calculated tree hash %s does not match the " - "expected tree hash %s for the byte range %s" % ( - actual_tree_hash, response['TreeHash'], byte_range)) - return response - - def _calc_num_chunks(self, chunk_size): - return int(math.ceil(self.archive_size / float(chunk_size))) - - def download_to_file(self, filename, chunk_size=DefaultPartSize, - verify_hashes=True, retry_exceptions=(socket.error,)): - """Download an archive to a file by name. - - :type filename: str - :param filename: The name of the file where the archive - contents will be saved. - - :type chunk_size: int - :param chunk_size: The chunk size to use when downloading - the archive. - - :type verify_hashes: bool - :param verify_hashes: Indicates whether or not to verify - the tree hashes for each downloaded chunk. - - """ - num_chunks = self._calc_num_chunks(chunk_size) - with open(filename, 'wb') as output_file: - self._download_to_fileob(output_file, num_chunks, chunk_size, - verify_hashes, retry_exceptions) - - def download_to_fileobj(self, output_file, chunk_size=DefaultPartSize, - verify_hashes=True, - retry_exceptions=(socket.error,)): - """Download an archive to a file object. - - :type output_file: file - :param output_file: The file object where the archive - contents will be saved. - - :type chunk_size: int - :param chunk_size: The chunk size to use when downloading - the archive. - - :type verify_hashes: bool - :param verify_hashes: Indicates whether or not to verify - the tree hashes for each downloaded chunk. - - """ - num_chunks = self._calc_num_chunks(chunk_size) - self._download_to_fileob(output_file, num_chunks, chunk_size, - verify_hashes, retry_exceptions) - - def _download_to_fileob(self, fileobj, num_chunks, chunk_size, verify_hashes, - retry_exceptions): - for i in range(num_chunks): - byte_range = ((i * chunk_size), ((i + 1) * chunk_size) - 1) - data, expected_tree_hash = self._download_byte_range( - byte_range, retry_exceptions) - if verify_hashes: - actual_tree_hash = tree_hash_from_str(data) - if expected_tree_hash != actual_tree_hash: - raise TreeHashDoesNotMatchError( - "The calculated tree hash %s does not match the " - "expected tree hash %s for the byte range %s" % ( - actual_tree_hash, expected_tree_hash, byte_range)) - fileobj.write(data) - - def _download_byte_range(self, byte_range, retry_exceptions): - # You can occasionally get socket.errors when downloading - # chunks from Glacier, so each chunk can be retried up - # to 5 times. - for _ in range(5): - try: - response = self.get_output(byte_range) - data = response.read() - expected_tree_hash = response['TreeHash'] - return data, expected_tree_hash - except retry_exceptions as e: - continue - else: - raise DownloadArchiveError("There was an error downloading" - "byte range %s: %s" % (byte_range, - e)) diff --git a/awx/lib/site-packages/boto/glacier/layer1.py b/awx/lib/site-packages/boto/glacier/layer1.py deleted file mode 100644 index 39136cf03f..0000000000 --- a/awx/lib/site-packages/boto/glacier/layer1.py +++ /dev/null @@ -1,1279 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import os - -import boto.glacier -from boto.compat import json -from boto.connection import AWSAuthConnection -from boto.glacier.exceptions import UnexpectedHTTPResponseError -from boto.glacier.response import GlacierResponse -from boto.glacier.utils import ResettingFileSender - - -class Layer1(AWSAuthConnection): - """ - Amazon Glacier is a storage solution for "cold data." - - Amazon Glacier is an extremely low-cost storage service that - provides secure, durable and easy-to-use storage for data backup - and archival. With Amazon Glacier, customers can store their data - cost effectively for months, years, or decades. Amazon Glacier - also enables customers to offload the administrative burdens of - operating and scaling storage to AWS, so they don't have to worry - about capacity planning, hardware provisioning, data replication, - hardware failure and recovery, or time-consuming hardware - migrations. - - Amazon Glacier is a great storage choice when low storage cost is - paramount, your data is rarely retrieved, and retrieval latency of - several hours is acceptable. If your application requires fast or - frequent access to your data, consider using Amazon S3. For more - information, go to `Amazon Simple Storage Service (Amazon S3)`_. - - You can store any kind of data in any format. There is no maximum - limit on the total amount of data you can store in Amazon Glacier. - - If you are a first-time user of Amazon Glacier, we recommend that - you begin by reading the following sections in the Amazon Glacier - Developer Guide : - - - + `What is Amazon Glacier`_ - This section of the Developer Guide - describes the underlying data model, the operations it supports, - and the AWS SDKs that you can use to interact with the service. - + `Getting Started with Amazon Glacier`_ - The Getting Started - section walks you through the process of creating a vault, - uploading archives, creating jobs to download archives, retrieving - the job output, and deleting archives. - """ - Version = '2012-06-01' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - account_id='-', is_secure=True, port=None, - proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, path='/', - provider='aws', security_token=None, - suppress_consec_slashes=True, - region=None, region_name='us-east-1', - profile_name=None): - - if not region: - for reg in boto.glacier.regions(): - if reg.name == region_name: - region = reg - break - - self.region = region - self.account_id = account_id - super(Layer1, self).__init__(region.endpoint, - aws_access_key_id, aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, debug, - https_connection_factory, - path, provider, security_token, - suppress_consec_slashes, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def make_request(self, verb, resource, headers=None, - data='', ok_responses=(200,), params=None, - sender=None, response_headers=None): - if headers is None: - headers = {} - headers['x-amz-glacier-version'] = self.Version - uri = '/%s/%s' % (self.account_id, resource) - response = super(Layer1, self).make_request(verb, uri, - params=params, - headers=headers, - sender=sender, - data=data) - if response.status in ok_responses: - return GlacierResponse(response, response_headers) - else: - # create glacier-specific exceptions - raise UnexpectedHTTPResponseError(ok_responses, response) - - # Vaults - - def list_vaults(self, limit=None, marker=None): - """ - This operation lists all vaults owned by the calling user's - account. The list returned in the response is ASCII-sorted by - vault name. - - By default, this operation returns up to 1,000 items. If there - are more vaults to list, the response `marker` field contains - the vault Amazon Resource Name (ARN) at which to continue the - list with a new List Vaults request; otherwise, the `marker` - field is `null`. To return a list of vaults that begins at a - specific vault, set the `marker` request parameter to the - vault ARN you obtained from a previous List Vaults request. - You can also limit the number of vaults returned in the - response by specifying the `limit` parameter in the request. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Retrieving Vault Metadata in Amazon Glacier`_ and `List - Vaults `_ in the Amazon Glacier Developer Guide . - - :type marker: string - :param marker: A string used for pagination. The marker specifies the - vault ARN after which the listing of vaults should begin. - - :type limit: string - :param limit: The maximum number of items returned in the response. If - you don't specify a value, the List Vaults operation returns up to - 1,000 items. - """ - params = {} - if limit: - params['limit'] = limit - if marker: - params['marker'] = marker - return self.make_request('GET', 'vaults', params=params) - - def describe_vault(self, vault_name): - """ - This operation returns information about a vault, including - the vault's Amazon Resource Name (ARN), the date the vault was - created, the number of archives it contains, and the total - size of all the archives in the vault. The number of archives - and their total size are as of the last inventory generation. - This means that if you add or remove an archive from a vault, - and then immediately use Describe Vault, the change in - contents will not be immediately reflected. If you want to - retrieve the latest inventory of the vault, use InitiateJob. - Amazon Glacier generates vault inventories approximately - daily. For more information, see `Downloading a Vault - Inventory in Amazon Glacier`_. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Retrieving Vault Metadata in Amazon Glacier`_ and `Describe - Vault `_ in the Amazon Glacier Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - """ - uri = 'vaults/%s' % vault_name - return self.make_request('GET', uri) - - def create_vault(self, vault_name): - """ - This operation creates a new vault with the specified name. - The name of the vault must be unique within a region for an - AWS account. You can create up to 1,000 vaults per account. If - you need to create more vaults, contact Amazon Glacier. - - You must use the following guidelines when naming a vault. - - - - + Names can be between 1 and 255 characters long. - + Allowed characters are a-z, A-Z, 0-9, '_' (underscore), '-' - (hyphen), and '.' (period). - - - - This operation is idempotent. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Creating a Vault in Amazon Glacier`_ and `Create Vault `_ in - the Amazon Glacier Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - """ - uri = 'vaults/%s' % vault_name - return self.make_request('PUT', uri, ok_responses=(201,), - response_headers=[('Location', 'Location')]) - - def delete_vault(self, vault_name): - """ - This operation deletes a vault. Amazon Glacier will delete a - vault only if there are no archives in the vault as of the - last inventory and there have been no writes to the vault - since the last inventory. If either of these conditions is not - satisfied, the vault deletion fails (that is, the vault is not - removed) and Amazon Glacier returns an error. You can use - DescribeVault to return the number of archives in a vault, and - you can use `Initiate a Job (POST jobs)`_ to initiate a new - inventory retrieval for a vault. The inventory contains the - archive IDs you use to delete archives using `Delete Archive - (DELETE archive)`_. - - This operation is idempotent. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Deleting a Vault in Amazon Glacier`_ and `Delete Vault `_ in - the Amazon Glacier Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - """ - uri = 'vaults/%s' % vault_name - return self.make_request('DELETE', uri, ok_responses=(204,)) - - def get_vault_notifications(self, vault_name): - """ - This operation retrieves the `notification-configuration` - subresource of the specified vault. - - For information about setting a notification configuration on - a vault, see SetVaultNotifications. If a notification - configuration for a vault is not set, the operation returns a - `404 Not Found` error. For more information about vault - notifications, see `Configuring Vault Notifications in Amazon - Glacier`_. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Configuring Vault Notifications in Amazon Glacier`_ and `Get - Vault Notification Configuration `_ in the Amazon Glacier - Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - """ - uri = 'vaults/%s/notification-configuration' % vault_name - return self.make_request('GET', uri) - - def set_vault_notifications(self, vault_name, notification_config): - """ - This operation configures notifications that will be sent when - specific events happen to a vault. By default, you don't get - any notifications. - - To configure vault notifications, send a PUT request to the - `notification-configuration` subresource of the vault. The - request should include a JSON document that provides an Amazon - SNS topic and specific events for which you want Amazon - Glacier to send notifications to the topic. - - Amazon SNS topics must grant permission to the vault to be - allowed to publish notifications to the topic. You can - configure a vault to publish a notification for the following - vault events: - - - + **ArchiveRetrievalCompleted** This event occurs when a job - that was initiated for an archive retrieval is completed - (InitiateJob). The status of the completed job can be - "Succeeded" or "Failed". The notification sent to the SNS - topic is the same output as returned from DescribeJob. - + **InventoryRetrievalCompleted** This event occurs when a job - that was initiated for an inventory retrieval is completed - (InitiateJob). The status of the completed job can be - "Succeeded" or "Failed". The notification sent to the SNS - topic is the same output as returned from DescribeJob. - - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Configuring Vault Notifications in Amazon Glacier`_ and `Set - Vault Notification Configuration `_ in the Amazon Glacier - Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - - :type vault_notification_config: dict - :param vault_notification_config: Provides options for specifying - notification configuration. - - The format of the dictionary is: - - {'SNSTopic': 'mytopic', - 'Events': [event1,...]} - """ - uri = 'vaults/%s/notification-configuration' % vault_name - json_config = json.dumps(notification_config) - return self.make_request('PUT', uri, data=json_config, - ok_responses=(204,)) - - def delete_vault_notifications(self, vault_name): - """ - This operation deletes the notification configuration set for - a vault. The operation is eventually consistent;that is, it - might take some time for Amazon Glacier to completely disable - the notifications and you might still receive some - notifications for a short time after you send the delete - request. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Configuring Vault Notifications in Amazon Glacier`_ and - `Delete Vault Notification Configuration `_ in the Amazon - Glacier Developer Guide. - - :type vault_name: string - :param vault_name: The name of the vault. - """ - uri = 'vaults/%s/notification-configuration' % vault_name - return self.make_request('DELETE', uri, ok_responses=(204,)) - - # Jobs - - def list_jobs(self, vault_name, completed=None, status_code=None, - limit=None, marker=None): - """ - This operation lists jobs for a vault, including jobs that are - in-progress and jobs that have recently finished. - - - Amazon Glacier retains recently completed jobs for a period - before deleting them; however, it eventually removes completed - jobs. The output of completed jobs can be retrieved. Retaining - completed jobs for a period of time after they have completed - enables you to get a job output in the event you miss the job - completion notification or your first attempt to download it - fails. For example, suppose you start an archive retrieval job - to download an archive. After the job completes, you start to - download the archive but encounter a network error. In this - scenario, you can retry and download the archive while the job - exists. - - - To retrieve an archive or retrieve a vault inventory from - Amazon Glacier, you first initiate a job, and after the job - completes, you download the data. For an archive retrieval, - the output is the archive data, and for an inventory - retrieval, it is the inventory list. The List Job operation - returns a list of these jobs sorted by job initiation time. - - This List Jobs operation supports pagination. By default, this - operation returns up to 1,000 jobs in the response. You should - always check the response for a `marker` at which to continue - the list; if there are no more items the `marker` is `null`. - To return a list of jobs that begins at a specific job, set - the `marker` request parameter to the value you obtained from - a previous List Jobs request. You can also limit the number of - jobs returned in the response by specifying the `limit` - parameter in the request. - - Additionally, you can filter the jobs list returned by - specifying an optional `statuscode` (InProgress, Succeeded, or - Failed) and `completed` (true, false) parameter. The - `statuscode` allows you to specify that only jobs that match a - specified status are returned. The `completed` parameter - allows you to specify that only jobs in a specific completion - state are returned. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For the underlying REST API, go to `List Jobs `_ - - :type vault_name: string - :param vault_name: The name of the vault. - - :type limit: string - :param limit: Specifies that the response be limited to the specified - number of items or fewer. If not specified, the List Jobs operation - returns up to 1,000 jobs. - - :type marker: string - :param marker: An opaque string used for pagination. This value - specifies the job at which the listing of jobs should begin. Get - the marker value from a previous List Jobs response. You need only - include the marker if you are continuing the pagination of results - started in a previous List Jobs request. - - :type statuscode: string - :param statuscode: Specifies the type of job status to return. You can - specify the following values: "InProgress", "Succeeded", or - "Failed". - - :type completed: string - :param completed: Specifies the state of the jobs to return. You can - specify `True` or `False`. - - """ - params = {} - if limit: - params['limit'] = limit - if marker: - params['marker'] = marker - if status_code: - params['statuscode'] = status_code - if completed is not None: - params['completed'] = 'true' if completed else 'false' - uri = 'vaults/%s/jobs' % vault_name - return self.make_request('GET', uri, params=params) - - def describe_job(self, vault_name, job_id): - """ - This operation returns information about a job you previously - initiated, including the job initiation date, the user who - initiated the job, the job status code/message and the Amazon - SNS topic to notify after Amazon Glacier completes the job. - For more information about initiating a job, see InitiateJob. - - - This operation enables you to check the status of your job. - However, it is strongly recommended that you set up an Amazon - SNS topic and specify it in your initiate job request so that - Amazon Glacier can notify the topic after it completes the - job. - - - A job ID will not expire for at least 24 hours after Amazon - Glacier completes the job. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For information about the underlying REST API, go to `Working - with Archives in Amazon Glacier`_ in the Amazon Glacier - Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - - :type job_id: string - :param job_id: The ID of the job to describe. - """ - uri = 'vaults/%s/jobs/%s' % (vault_name, job_id) - return self.make_request('GET', uri, ok_responses=(200,)) - - def initiate_job(self, vault_name, job_data): - """ - This operation initiates a job of the specified type. In this - release, you can initiate a job to retrieve either an archive - or a vault inventory (a list of archives in a vault). - - Retrieving data from Amazon Glacier is a two-step process: - - - #. Initiate a retrieval job. - #. After the job completes, download the bytes. - - - The retrieval request is executed asynchronously. When you - initiate a retrieval job, Amazon Glacier creates a job and - returns a job ID in the response. When Amazon Glacier - completes the job, you can get the job output (archive or - inventory data). For information about getting job output, see - GetJobOutput operation. - - The job must complete before you can get its output. To - determine when a job is complete, you have the following - options: - - - + **Use Amazon SNS Notification** You can specify an Amazon - Simple Notification Service (Amazon SNS) topic to which Amazon - Glacier can post a notification after the job is completed. - You can specify an SNS topic per job request. The notification - is sent only after Amazon Glacier completes the job. In - addition to specifying an SNS topic per job request, you can - configure vault notifications for a vault so that job - notifications are always sent. For more information, see - SetVaultNotifications. - + **Get job details** You can make a DescribeJob request to - obtain job status information while a job is in progress. - However, it is more efficient to use an Amazon SNS - notification to determine when a job is complete. - - - - The information you get via notification is same that you get - by calling DescribeJob. - - - If for a specific event, you add both the notification - configuration on the vault and also specify an SNS topic in - your initiate job request, Amazon Glacier sends both - notifications. For more information, see - SetVaultNotifications. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - **About the Vault Inventory** - - Amazon Glacier prepares an inventory for each vault - periodically, every 24 hours. When you initiate a job for a - vault inventory, Amazon Glacier returns the last inventory for - the vault. The inventory data you get might be up to a day or - two days old. Also, the initiate inventory job might take some - time to complete before you can download the vault inventory. - So you do not want to retrieve a vault inventory for each - vault operation. However, in some scenarios, you might find - the vault inventory useful. For example, when you upload an - archive, you can provide an archive description but not an - archive name. Amazon Glacier provides you a unique archive ID, - an opaque string of characters. So, you might maintain your - own database that maps archive names to their corresponding - Amazon Glacier assigned archive IDs. You might find the vault - inventory useful in the event you need to reconcile - information in your database with the actual vault inventory. - - **About Ranged Archive Retrieval** - - You can initiate an archive retrieval for the whole archive or - a range of the archive. In the case of ranged archive - retrieval, you specify a byte range to return or the whole - archive. The range specified must be megabyte (MB) aligned, - that is the range start value must be divisible by 1 MB and - range end value plus 1 must be divisible by 1 MB or equal the - end of the archive. If the ranged archive retrieval is not - megabyte aligned, this operation returns a 400 response. - Furthermore, to ensure you get checksum values for data you - download using Get Job Output API, the range must be tree hash - aligned. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and the underlying REST API, go to - `Initiate a Job`_ and `Downloading a Vault Inventory`_ - - :type account_id: string - :param account_id: The `AccountId` is the AWS Account ID. You can - specify either the AWS Account ID or optionally a '-', in which - case Amazon Glacier uses the AWS Account ID associated with the - credentials used to sign the request. If you specify your Account - ID, do not include hyphens in it. - - :type vault_name: string - :param vault_name: The name of the vault. - - :type job_parameters: dict - :param job_parameters: Provides options for specifying job information. - The dictionary can contain the following attributes: - - * ArchiveId - The ID of the archive you want to retrieve. - This field is required only if the Type is set to - archive-retrieval. - * Description - The optional description for the job. - * Format - When initiating a job to retrieve a vault - inventory, you can optionally add this parameter to - specify the output format. Valid values are: CSV|JSON. - * SNSTopic - The Amazon SNS topic ARN where Amazon Glacier - sends a notification when the job is completed and the - output is ready for you to download. - * Type - The job type. Valid values are: - archive-retrieval|inventory-retrieval - * RetrievalByteRange - Optionally specify the range of - bytes to retrieve. - * InventoryRetrievalParameters: Optional job parameters - * Format - The output format, like "JSON" - * StartDate - ISO8601 starting date string - * EndDate - ISO8601 ending date string - * Limit - Maximum number of entries - * Marker - A unique string used for pagination - - """ - uri = 'vaults/%s/jobs' % vault_name - response_headers = [('x-amz-job-id', u'JobId'), - ('Location', u'Location')] - json_job_data = json.dumps(job_data) - return self.make_request('POST', uri, data=json_job_data, - ok_responses=(202,), - response_headers=response_headers) - - def get_job_output(self, vault_name, job_id, byte_range=None): - """ - This operation downloads the output of the job you initiated - using InitiateJob. Depending on the job type you specified - when you initiated the job, the output will be either the - content of an archive or a vault inventory. - - A job ID will not expire for at least 24 hours after Amazon - Glacier completes the job. That is, you can download the job - output within the 24 hours period after Amazon Glacier - completes the job. - - If the job output is large, then you can use the `Range` - request header to retrieve a portion of the output. This - allows you to download the entire output in smaller chunks of - bytes. For example, suppose you have 1 GB of job output you - want to download and you decide to download 128 MB chunks of - data at a time, which is a total of eight Get Job Output - requests. You use the following process to download the job - output: - - - #. Download a 128 MB chunk of output by specifying the - appropriate byte range using the `Range` header. - #. Along with the data, the response includes a checksum of - the payload. You compute the checksum of the payload on the - client and compare it with the checksum you received in the - response to ensure you received all the expected data. - #. Repeat steps 1 and 2 for all the eight 128 MB chunks of - output data, each time specifying the appropriate byte range. - #. After downloading all the parts of the job output, you have - a list of eight checksum values. Compute the tree hash of - these values to find the checksum of the entire output. Using - the Describe Job API, obtain job information of the job that - provided you the output. The response includes the checksum of - the entire archive stored in Amazon Glacier. You compare this - value with the checksum you computed to ensure you have - downloaded the entire archive content with no errors. - - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and the underlying REST API, go to - `Downloading a Vault Inventory`_, `Downloading an Archive`_, - and `Get Job Output `_ - - :type account_id: string - :param account_id: The `AccountId` is the AWS Account ID. You can - specify either the AWS Account ID or optionally a '-', in which - case Amazon Glacier uses the AWS Account ID associated with the - credentials used to sign the request. If you specify your Account - ID, do not include hyphens in it. - - :type vault_name: string - :param vault_name: The name of the vault. - - :type job_id: string - :param job_id: The job ID whose data is downloaded. - - :type byte_range: string - :param byte_range: The range of bytes to retrieve from the output. For - example, if you want to download the first 1,048,576 bytes, specify - "Range: bytes=0-1048575". By default, this operation downloads the - entire output. - """ - response_headers = [('x-amz-sha256-tree-hash', u'TreeHash'), - ('Content-Range', u'ContentRange'), - ('Content-Type', u'ContentType')] - headers = None - if byte_range: - headers = {'Range': 'bytes=%d-%d' % byte_range} - uri = 'vaults/%s/jobs/%s/output' % (vault_name, job_id) - response = self.make_request('GET', uri, headers=headers, - ok_responses=(200, 206), - response_headers=response_headers) - return response - - # Archives - - def upload_archive(self, vault_name, archive, - linear_hash, tree_hash, description=None): - """ - This operation adds an archive to a vault. This is a - synchronous operation, and for a successful upload, your data - is durably persisted. Amazon Glacier returns the archive ID in - the `x-amz-archive-id` header of the response. - - You must use the archive ID to access your data in Amazon - Glacier. After you upload an archive, you should save the - archive ID returned so that you can retrieve or delete the - archive later. Besides saving the archive ID, you can also - index it and give it a friendly name to allow for better - searching. You can also use the optional archive description - field to specify how the archive is referred to in an external - index of archives, such as you might create in Amazon - DynamoDB. You can also get the vault inventory to obtain a - list of archive IDs in a vault. For more information, see - InitiateJob. - - You must provide a SHA256 tree hash of the data you are - uploading. For information about computing a SHA256 tree hash, - see `Computing Checksums`_. - - You can optionally specify an archive description of up to - 1,024 printable ASCII characters. You can get the archive - description when you either retrieve the archive or get the - vault inventory. For more information, see InitiateJob. Amazon - Glacier does not interpret the description in any way. An - archive description does not need to be unique. You cannot use - the description to retrieve or sort the archive list. - - Archives are immutable. After you upload an archive, you - cannot edit the archive or its description. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Uploading an Archive in Amazon Glacier`_ and `Upload - Archive`_ in the Amazon Glacier Developer Guide . - - :type vault_name: str - :param vault_name: The name of the vault - - :type archive: bytes - :param archive: The data to upload. - - :type linear_hash: str - :param linear_hash: The SHA256 checksum (a linear hash) of the - payload. - - :type tree_hash: str - :param tree_hash: The user-computed SHA256 tree hash of the - payload. For more information on computing the - tree hash, see http://goo.gl/u7chF. - - :type description: str - :param description: The optional description of the archive you - are uploading. - """ - response_headers = [('x-amz-archive-id', u'ArchiveId'), - ('Location', u'Location'), - ('x-amz-sha256-tree-hash', u'TreeHash')] - uri = 'vaults/%s/archives' % vault_name - try: - content_length = str(len(archive)) - except (TypeError, AttributeError): - # If a file like object is provided, try to retrieve - # the file size via fstat. - content_length = str(os.fstat(archive.fileno()).st_size) - headers = {'x-amz-content-sha256': linear_hash, - 'x-amz-sha256-tree-hash': tree_hash, - 'Content-Length': content_length} - if description: - headers['x-amz-archive-description'] = description - if self._is_file_like(archive): - sender = ResettingFileSender(archive) - else: - sender = None - return self.make_request('POST', uri, headers=headers, - sender=sender, - data=archive, ok_responses=(201,), - response_headers=response_headers) - - def _is_file_like(self, archive): - return hasattr(archive, 'seek') and hasattr(archive, 'tell') - - def delete_archive(self, vault_name, archive_id): - """ - This operation deletes an archive from a vault. Subsequent - requests to initiate a retrieval of this archive will fail. - Archive retrievals that are in progress for this archive ID - may or may not succeed according to the following scenarios: - - - + If the archive retrieval job is actively preparing the data - for download when Amazon Glacier receives the delete archive - request, the archival retrieval operation might fail. - + If the archive retrieval job has successfully prepared the - archive for download when Amazon Glacier receives the delete - archive request, you will be able to download the output. - - - This operation is idempotent. Attempting to delete an already- - deleted archive does not result in an error. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Deleting an Archive in Amazon Glacier`_ and `Delete Archive`_ - in the Amazon Glacier Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - - :type archive_id: string - :param archive_id: The ID of the archive to delete. - """ - uri = 'vaults/%s/archives/%s' % (vault_name, archive_id) - return self.make_request('DELETE', uri, ok_responses=(204,)) - - # Multipart - - def initiate_multipart_upload(self, vault_name, part_size, - description=None): - """ - This operation initiates a multipart upload. Amazon Glacier - creates a multipart upload resource and returns its ID in the - response. The multipart upload ID is used in subsequent - requests to upload parts of an archive (see - UploadMultipartPart). - - When you initiate a multipart upload, you specify the part - size in number of bytes. The part size must be a megabyte - (1024 KB) multiplied by a power of 2-for example, 1048576 (1 - MB), 2097152 (2 MB), 4194304 (4 MB), 8388608 (8 MB), and so - on. The minimum allowable part size is 1 MB, and the maximum - is 4 GB. - - Every part you upload to this resource (see - UploadMultipartPart), except the last one, must have the same - size. The last one can be the same size or smaller. For - example, suppose you want to upload a 16.2 MB file. If you - initiate the multipart upload with a part size of 4 MB, you - will upload four parts of 4 MB each and one part of 0.2 MB. - - - You don't need to know the size of the archive when you start - a multipart upload because Amazon Glacier does not require you - to specify the overall archive size. - - - After you complete the multipart upload, Amazon Glacier - removes the multipart upload resource referenced by the ID. - Amazon Glacier also removes the multipart upload resource if - you cancel the multipart upload or it may be removed if there - is no activity for a period of 24 hours. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Uploading Large Archives in Parts (Multipart Upload)`_ and - `Initiate Multipart Upload`_ in the Amazon Glacier Developer - Guide . - - The part size must be a megabyte (1024 KB) multiplied by a power of - 2, for example, 1048576 (1 MB), 2097152 (2 MB), 4194304 (4 MB), - 8388608 (8 MB), and so on. The minimum allowable part size is 1 MB, - and the maximum is 4 GB (4096 MB). - - :type vault_name: str - :param vault_name: The name of the vault. - - :type description: str - :param description: The archive description that you are uploading in - parts. - - :type part_size: int - :param part_size: The size of each part except the last, in bytes. The - last part can be smaller than this part size. - """ - response_headers = [('x-amz-multipart-upload-id', u'UploadId'), - ('Location', u'Location')] - headers = {'x-amz-part-size': str(part_size)} - if description: - headers['x-amz-archive-description'] = description - uri = 'vaults/%s/multipart-uploads' % vault_name - response = self.make_request('POST', uri, headers=headers, - ok_responses=(201,), - response_headers=response_headers) - return response - - def complete_multipart_upload(self, vault_name, upload_id, - sha256_treehash, archive_size): - """ - You call this operation to inform Amazon Glacier that all the - archive parts have been uploaded and that Amazon Glacier can - now assemble the archive from the uploaded parts. After - assembling and saving the archive to the vault, Amazon Glacier - returns the URI path of the newly created archive resource. - Using the URI path, you can then access the archive. After you - upload an archive, you should save the archive ID returned to - retrieve the archive at a later point. You can also get the - vault inventory to obtain a list of archive IDs in a vault. - For more information, see InitiateJob. - - In the request, you must include the computed SHA256 tree hash - of the entire archive you have uploaded. For information about - computing a SHA256 tree hash, see `Computing Checksums`_. On - the server side, Amazon Glacier also constructs the SHA256 - tree hash of the assembled archive. If the values match, - Amazon Glacier saves the archive to the vault; otherwise, it - returns an error, and the operation fails. The ListParts - operation returns a list of parts uploaded for a specific - multipart upload. It includes checksum information for each - uploaded part that can be used to debug a bad checksum issue. - - Additionally, Amazon Glacier also checks for any missing - content ranges when assembling the archive, if missing content - ranges are found, Amazon Glacier returns an error and the - operation fails. - - Complete Multipart Upload is an idempotent operation. After - your first successful complete multipart upload, if you call - the operation again within a short period, the operation will - succeed and return the same archive ID. This is useful in the - event you experience a network issue that causes an aborted - connection or receive a 500 server error, in which case you - can repeat your Complete Multipart Upload request and get the - same archive ID without creating duplicate archives. Note, - however, that after the multipart upload completes, you cannot - call the List Parts operation and the multipart upload will - not appear in List Multipart Uploads response, even if - idempotent complete is possible. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Uploading Large Archives in Parts (Multipart Upload)`_ and - `Complete Multipart Upload`_ in the Amazon Glacier Developer - Guide . - - :type checksum: string - :param checksum: The SHA256 tree hash of the entire archive. It is the - tree hash of SHA256 tree hash of the individual parts. If the value - you specify in the request does not match the SHA256 tree hash of - the final assembled archive as computed by Amazon Glacier, Amazon - Glacier returns an error and the request fails. - - :type vault_name: str - :param vault_name: The name of the vault. - - :type upload_id: str - :param upload_id: The upload ID of the multipart upload. - - :type sha256_treehash: str - :param sha256_treehash: The SHA256 tree hash of the entire archive. - It is the tree hash of SHA256 tree hash of the individual parts. - If the value you specify in the request does not match the SHA256 - tree hash of the final assembled archive as computed by Amazon - Glacier, Amazon Glacier returns an error and the request fails. - - :type archive_size: int - :param archive_size: The total size, in bytes, of the entire - archive. This value should be the sum of all the sizes of - the individual parts that you uploaded. - """ - response_headers = [('x-amz-archive-id', u'ArchiveId'), - ('Location', u'Location')] - headers = {'x-amz-sha256-tree-hash': sha256_treehash, - 'x-amz-archive-size': str(archive_size)} - uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id) - response = self.make_request('POST', uri, headers=headers, - ok_responses=(201,), - response_headers=response_headers) - return response - - def abort_multipart_upload(self, vault_name, upload_id): - """ - This operation aborts a multipart upload identified by the - upload ID. - - After the Abort Multipart Upload request succeeds, you cannot - upload any more parts to the multipart upload or complete the - multipart upload. Aborting a completed upload fails. However, - aborting an already-aborted upload will succeed, for a short - time. For more information about uploading a part and - completing a multipart upload, see UploadMultipartPart and - CompleteMultipartUpload. - - This operation is idempotent. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Working with Archives in Amazon Glacier`_ and `Abort - Multipart Upload`_ in the Amazon Glacier Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - - :type upload_id: string - :param upload_id: The upload ID of the multipart upload to delete. - """ - uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id) - return self.make_request('DELETE', uri, ok_responses=(204,)) - - def list_multipart_uploads(self, vault_name, limit=None, marker=None): - """ - This operation lists in-progress multipart uploads for the - specified vault. An in-progress multipart upload is a - multipart upload that has been initiated by an - InitiateMultipartUpload request, but has not yet been - completed or aborted. The list returned in the List Multipart - Upload response has no guaranteed order. - - The List Multipart Uploads operation supports pagination. By - default, this operation returns up to 1,000 multipart uploads - in the response. You should always check the response for a - `marker` at which to continue the list; if there are no more - items the `marker` is `null`. To return a list of multipart - uploads that begins at a specific upload, set the `marker` - request parameter to the value you obtained from a previous - List Multipart Upload request. You can also limit the number - of uploads returned in the response by specifying the `limit` - parameter in the request. - - Note the difference between this operation and listing parts - (ListParts). The List Multipart Uploads operation lists all - multipart uploads for a vault and does not require a multipart - upload ID. The List Parts operation requires a multipart - upload ID since parts are associated with a single upload. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and the underlying REST API, go to - `Working with Archives in Amazon Glacier`_ and `List Multipart - Uploads `_ in the Amazon Glacier Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - - :type limit: string - :param limit: Specifies the maximum number of uploads returned in the - response body. If this value is not specified, the List Uploads - operation returns up to 1,000 uploads. - - :type marker: string - :param marker: An opaque string used for pagination. This value - specifies the upload at which the listing of uploads should begin. - Get the marker value from a previous List Uploads response. You - need only include the marker if you are continuing the pagination - of results started in a previous List Uploads request. - """ - params = {} - if limit: - params['limit'] = limit - if marker: - params['marker'] = marker - uri = 'vaults/%s/multipart-uploads' % vault_name - return self.make_request('GET', uri, params=params) - - def list_parts(self, vault_name, upload_id, limit=None, marker=None): - """ - This operation lists the parts of an archive that have been - uploaded in a specific multipart upload. You can make this - request at any time during an in-progress multipart upload - before you complete the upload (see CompleteMultipartUpload. - List Parts returns an error for completed uploads. The list - returned in the List Parts response is sorted by part range. - - The List Parts operation supports pagination. By default, this - operation returns up to 1,000 uploaded parts in the response. - You should always check the response for a `marker` at which - to continue the list; if there are no more items the `marker` - is `null`. To return a list of parts that begins at a specific - part, set the `marker` request parameter to the value you - obtained from a previous List Parts request. You can also - limit the number of parts returned in the response by - specifying the `limit` parameter in the request. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and the underlying REST API, go to - `Working with Archives in Amazon Glacier`_ and `List Parts`_ - in the Amazon Glacier Developer Guide . - - :type vault_name: string - :param vault_name: The name of the vault. - - :type upload_id: string - :param upload_id: The upload ID of the multipart upload. - - :type marker: string - :param marker: An opaque string used for pagination. This value - specifies the part at which the listing of parts should begin. Get - the marker value from the response of a previous List Parts - response. You need only include the marker if you are continuing - the pagination of results started in a previous List Parts request. - - :type limit: string - :param limit: Specifies the maximum number of parts returned in the - response body. If this value is not specified, the List Parts - operation returns up to 1,000 uploads. - """ - params = {} - if limit: - params['limit'] = limit - if marker: - params['marker'] = marker - uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id) - return self.make_request('GET', uri, params=params) - - def upload_part(self, vault_name, upload_id, linear_hash, - tree_hash, byte_range, part_data): - """ - This operation uploads a part of an archive. You can upload - archive parts in any order. You can also upload them in - parallel. You can upload up to 10,000 parts for a multipart - upload. - - Amazon Glacier rejects your upload part request if any of the - following conditions is true: - - - + **SHA256 tree hash does not match**To ensure that part data - is not corrupted in transmission, you compute a SHA256 tree - hash of the part and include it in your request. Upon - receiving the part data, Amazon Glacier also computes a SHA256 - tree hash. If these hash values don't match, the operation - fails. For information about computing a SHA256 tree hash, see - `Computing Checksums`_. - + **Part size does not match**The size of each part except the - last must match the size specified in the corresponding - InitiateMultipartUpload request. The size of the last part - must be the same size as, or smaller than, the specified size. - If you upload a part whose size is smaller than the part size - you specified in your initiate multipart upload request and - that part is not the last part, then the upload part request - will succeed. However, the subsequent Complete Multipart - Upload request will fail. - + **Range does not align**The byte range value in the request - does not align with the part size specified in the - corresponding initiate request. For example, if you specify a - part size of 4194304 bytes (4 MB), then 0 to 4194303 bytes (4 - MB - 1) and 4194304 (4 MB) to 8388607 (8 MB - 1) are valid - part ranges. However, if you set a range value of 2 MB to 6 - MB, the range does not align with the part size and the upload - will fail. - - - This operation is idempotent. If you upload the same part - multiple times, the data included in the most recent request - overwrites the previously uploaded data. - - An AWS account has full permission to perform all operations - (actions). However, AWS Identity and Access Management (IAM) - users don't have any permissions by default. You must grant - them explicit permission to perform specific actions. For more - information, see `Access Control Using AWS Identity and Access - Management (IAM)`_. - - For conceptual information and underlying REST API, go to - `Uploading Large Archives in Parts (Multipart Upload)`_ and - `Upload Part `_ in the Amazon Glacier Developer Guide . - - :type vault_name: str - :param vault_name: The name of the vault. - - :type linear_hash: str - :param linear_hash: The SHA256 checksum (a linear hash) of the - payload. - - :type tree_hash: str - :param tree_hash: The user-computed SHA256 tree hash of the - payload. For more information on computing the - tree hash, see http://goo.gl/u7chF. - - :type upload_id: str - :param upload_id: The unique ID associated with this upload - operation. - - :type byte_range: tuple of ints - :param byte_range: Identifies the range of bytes in the assembled - archive that will be uploaded in this part. Amazon Glacier uses - this information to assemble the archive in the proper sequence. - The format of this header follows RFC 2616. An example header is - Content-Range:bytes 0-4194303/*. - - :type part_data: bytes - :param part_data: The data to be uploaded for the part - """ - headers = {'x-amz-content-sha256': linear_hash, - 'x-amz-sha256-tree-hash': tree_hash, - 'Content-Range': 'bytes %d-%d/*' % byte_range} - response_headers = [('x-amz-sha256-tree-hash', u'TreeHash')] - uri = 'vaults/%s/multipart-uploads/%s' % (vault_name, upload_id) - return self.make_request('PUT', uri, headers=headers, - data=part_data, ok_responses=(204,), - response_headers=response_headers) diff --git a/awx/lib/site-packages/boto/glacier/layer2.py b/awx/lib/site-packages/boto/glacier/layer2.py deleted file mode 100644 index abc36199bb..0000000000 --- a/awx/lib/site-packages/boto/glacier/layer2.py +++ /dev/null @@ -1,101 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.glacier.layer1 import Layer1 -from boto.glacier.vault import Vault - - -class Layer2(object): - """ - Provides a more pythonic and friendly interface to Glacier based on Layer1 - """ - - def __init__(self, *args, **kwargs): - # Accept a passed in layer1, mainly to allow easier testing - if "layer1" in kwargs: - self.layer1 = kwargs["layer1"] - else: - self.layer1 = Layer1(*args, **kwargs) - - def create_vault(self, name): - """Creates a vault. - - :type name: str - :param name: The name of the vault - - :rtype: :class:`boto.glacier.vault.Vault` - :return: A Vault object representing the vault. - """ - self.layer1.create_vault(name) - return self.get_vault(name) - - def delete_vault(self, name): - """Delete a vault. - - This operation deletes a vault. Amazon Glacier will delete a - vault only if there are no archives in the vault as per the - last inventory and there have been no writes to the vault - since the last inventory. If either of these conditions is not - satisfied, the vault deletion fails (that is, the vault is not - removed) and Amazon Glacier returns an error. - - This operation is idempotent, you can send the same request - multiple times and it has no further effect after the first - time Amazon Glacier delete the specified vault. - - :type vault_name: str - :param vault_name: The name of the vault to delete. - """ - return self.layer1.delete_vault(name) - - def get_vault(self, name): - """ - Get an object representing a named vault from Glacier. This - operation does not check if the vault actually exists. - - :type name: str - :param name: The name of the vault - - :rtype: :class:`boto.glacier.vault.Vault` - :return: A Vault object representing the vault. - """ - response_data = self.layer1.describe_vault(name) - return Vault(self.layer1, response_data) - - def list_vaults(self): - """ - Return a list of all vaults associated with the account ID. - - :rtype: List of :class:`boto.glacier.vault.Vault` - :return: A list of Vault objects. - """ - vaults = [] - marker = None - while True: - response_data = self.layer1.list_vaults(marker=marker, limit=1000) - vaults.extend([Vault(self.layer1, rd) for rd in response_data['VaultList']]) - marker = response_data.get('Marker') - if not marker: - break - - return vaults diff --git a/awx/lib/site-packages/boto/glacier/response.py b/awx/lib/site-packages/boto/glacier/response.py deleted file mode 100644 index a67ec61d5f..0000000000 --- a/awx/lib/site-packages/boto/glacier/response.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.compat import json - - -class GlacierResponse(dict): - """ - Represents a response from Glacier layer1. It acts as a dictionary - containing the combined keys received via JSON in the body (if - supplied) and headers. - """ - def __init__(self, http_response, response_headers): - self.http_response = http_response - self.status = http_response.status - self[u'RequestId'] = http_response.getheader('x-amzn-requestid') - if response_headers: - for header_name, item_name in response_headers: - self[item_name] = http_response.getheader(header_name) - if http_response.getheader('Content-Type') == 'application/json': - body = json.loads(http_response.read().decode('utf-8')) - self.update(body) - size = http_response.getheader('Content-Length', None) - if size is not None: - self.size = size - - def read(self, amt=None): - "Reads and returns the response body, or up to the next amt bytes." - return self.http_response.read(amt) diff --git a/awx/lib/site-packages/boto/glacier/utils.py b/awx/lib/site-packages/boto/glacier/utils.py deleted file mode 100644 index 98847e3f16..0000000000 --- a/awx/lib/site-packages/boto/glacier/utils.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import hashlib -import math -import binascii - -from boto.compat import six - - -_MEGABYTE = 1024 * 1024 -DEFAULT_PART_SIZE = 4 * _MEGABYTE -MAXIMUM_NUMBER_OF_PARTS = 10000 - - -def minimum_part_size(size_in_bytes, default_part_size=DEFAULT_PART_SIZE): - """Calculate the minimum part size needed for a multipart upload. - - Glacier allows a maximum of 10,000 parts per upload. It also - states that the maximum archive size is 10,000 * 4 GB, which means - the part size can range from 1MB to 4GB (provided it is one 1MB - multiplied by a power of 2). - - This function will compute what the minimum part size must be in - order to upload a file of size ``size_in_bytes``. - - It will first check if ``default_part_size`` is sufficient for - a part size given the ``size_in_bytes``. If this is not the case, - then the smallest part size than can accomodate a file of size - ``size_in_bytes`` will be returned. - - If the file size is greater than the maximum allowed archive - size of 10,000 * 4GB, a ``ValueError`` will be raised. - - """ - # The default part size (4 MB) will be too small for a very large - # archive, as there is a limit of 10,000 parts in a multipart upload. - # This puts the maximum allowed archive size with the default part size - # at 40,000 MB. We need to do a sanity check on the part size, and find - # one that works if the default is too small. - part_size = _MEGABYTE - if (default_part_size * MAXIMUM_NUMBER_OF_PARTS) < size_in_bytes: - if size_in_bytes > (4096 * _MEGABYTE * 10000): - raise ValueError("File size too large: %s" % size_in_bytes) - min_part_size = size_in_bytes / 10000 - power = 3 - while part_size < min_part_size: - part_size = math.ldexp(_MEGABYTE, power) - power += 1 - part_size = int(part_size) - else: - part_size = default_part_size - return part_size - - -def chunk_hashes(bytestring, chunk_size=_MEGABYTE): - chunk_count = int(math.ceil(len(bytestring) / float(chunk_size))) - hashes = [] - for i in range(chunk_count): - start = i * chunk_size - end = (i + 1) * chunk_size - hashes.append(hashlib.sha256(bytestring[start:end]).digest()) - if not hashes: - return [hashlib.sha256(b'').digest()] - return hashes - - -def tree_hash(fo): - """ - Given a hash of each 1MB chunk (from chunk_hashes) this will hash - together adjacent hashes until it ends up with one big one. So a - tree of hashes. - """ - hashes = [] - hashes.extend(fo) - while len(hashes) > 1: - new_hashes = [] - while True: - if len(hashes) > 1: - first = hashes.pop(0) - second = hashes.pop(0) - new_hashes.append(hashlib.sha256(first + second).digest()) - elif len(hashes) == 1: - only = hashes.pop(0) - new_hashes.append(only) - else: - break - hashes.extend(new_hashes) - return hashes[0] - - -def compute_hashes_from_fileobj(fileobj, chunk_size=1024 * 1024): - """Compute the linear and tree hash from a fileobj. - - This function will compute the linear/tree hash of a fileobj - in a single pass through the fileobj. - - :param fileobj: A file like object. - - :param chunk_size: The size of the chunks to use for the tree - hash. This is also the buffer size used to read from - `fileobj`. - - :rtype: tuple - :return: A tuple of (linear_hash, tree_hash). Both hashes - are returned in hex. - - """ - # Python 3+, not binary - if six.PY3 and hasattr(fileobj, 'mode') and 'b' not in fileobj.mode: - raise ValueError('File-like object must be opened in binary mode!') - - linear_hash = hashlib.sha256() - chunks = [] - chunk = fileobj.read(chunk_size) - while chunk: - # It's possible to get a file-like object that has no mode (checked - # above) and returns something other than bytes (e.g. str). So here - # we try to catch that and encode to bytes. - if not isinstance(chunk, bytes): - chunk = chunk.encode(getattr(fileobj, 'encoding', '') or 'utf-8') - linear_hash.update(chunk) - chunks.append(hashlib.sha256(chunk).digest()) - chunk = fileobj.read(chunk_size) - if not chunks: - chunks = [hashlib.sha256(b'').digest()] - return linear_hash.hexdigest(), bytes_to_hex(tree_hash(chunks)) - - -def bytes_to_hex(str_as_bytes): - return binascii.hexlify(str_as_bytes) - - -def tree_hash_from_str(str_as_bytes): - """ - - :type str_as_bytes: str - :param str_as_bytes: The string for which to compute the tree hash. - - :rtype: str - :return: The computed tree hash, returned as hex. - - """ - return bytes_to_hex(tree_hash(chunk_hashes(str_as_bytes))) - - -class ResettingFileSender(object): - def __init__(self, archive): - self._archive = archive - self._starting_offset = archive.tell() - - def __call__(self, connection, method, path, body, headers): - try: - connection.request(method, path, self._archive, headers) - return connection.getresponse() - finally: - self._archive.seek(self._starting_offset) diff --git a/awx/lib/site-packages/boto/glacier/vault.py b/awx/lib/site-packages/boto/glacier/vault.py deleted file mode 100644 index 45d276cadb..0000000000 --- a/awx/lib/site-packages/boto/glacier/vault.py +++ /dev/null @@ -1,450 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# Copyright (c) 2012 Robie Basak <robie@justgohome.co.uk> -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import codecs -from boto.glacier.exceptions import UploadArchiveError -from boto.glacier.job import Job -from boto.glacier.writer import compute_hashes_from_fileobj, \ - resume_file_upload, Writer -from boto.glacier.concurrent import ConcurrentUploader -from boto.glacier.utils import minimum_part_size, DEFAULT_PART_SIZE -import os.path - - -_MEGABYTE = 1024 * 1024 -_GIGABYTE = 1024 * _MEGABYTE - -MAXIMUM_ARCHIVE_SIZE = 10000 * 4 * _GIGABYTE -MAXIMUM_NUMBER_OF_PARTS = 10000 - - -class Vault(object): - - DefaultPartSize = DEFAULT_PART_SIZE - SingleOperationThreshold = 100 * _MEGABYTE - - ResponseDataElements = (('VaultName', 'name', None), - ('VaultARN', 'arn', None), - ('CreationDate', 'creation_date', None), - ('LastInventoryDate', 'last_inventory_date', None), - ('SizeInBytes', 'size', 0), - ('NumberOfArchives', 'number_of_archives', 0)) - - def __init__(self, layer1, response_data=None): - self.layer1 = layer1 - if response_data: - for response_name, attr_name, default in self.ResponseDataElements: - value = response_data[response_name] - setattr(self, attr_name, value) - else: - for response_name, attr_name, default in self.ResponseDataElements: - setattr(self, attr_name, default) - - def __repr__(self): - return 'Vault("%s")' % self.arn - - def delete(self): - """ - Delete's this vault. WARNING! - """ - self.layer1.delete_vault(self.name) - - def upload_archive(self, filename, description=None): - """ - Adds an archive to a vault. For archives greater than 100MB the - multipart upload will be used. - - :type file: str - :param file: A filename to upload - - :type description: str - :param description: An optional description for the archive. - - :rtype: str - :return: The archive id of the newly created archive - """ - if os.path.getsize(filename) > self.SingleOperationThreshold: - return self.create_archive_from_file(filename, description=description) - return self._upload_archive_single_operation(filename, description) - - def _upload_archive_single_operation(self, filename, description): - """ - Adds an archive to a vault in a single operation. It's recommended for - archives less than 100MB - - :type file: str - :param file: A filename to upload - - :type description: str - :param description: A description for the archive. - - :rtype: str - :return: The archive id of the newly created archive - """ - with open(filename, 'rb') as fileobj: - linear_hash, tree_hash = compute_hashes_from_fileobj(fileobj) - fileobj.seek(0) - response = self.layer1.upload_archive(self.name, fileobj, - linear_hash, tree_hash, - description) - return response['ArchiveId'] - - def create_archive_writer(self, part_size=DefaultPartSize, - description=None): - """ - Create a new archive and begin a multi-part upload to it. - Returns a file-like object to which the data for the archive - can be written. Once all the data is written the file-like - object should be closed, you can then call the get_archive_id - method on it to get the ID of the created archive. - - :type part_size: int - :param part_size: The part size for the multipart upload. - - :type description: str - :param description: An optional description for the archive. - - :rtype: :class:`boto.glacier.writer.Writer` - :return: A Writer object that to which the archive data - should be written. - """ - response = self.layer1.initiate_multipart_upload(self.name, - part_size, - description) - return Writer(self, response['UploadId'], part_size=part_size) - - def create_archive_from_file(self, filename=None, file_obj=None, - description=None, upload_id_callback=None): - """ - Create a new archive and upload the data from the given file - or file-like object. - - :type filename: str - :param filename: A filename to upload - - :type file_obj: file - :param file_obj: A file-like object to upload - - :type description: str - :param description: An optional description for the archive. - - :type upload_id_callback: function - :param upload_id_callback: if set, call with the upload_id as the - only parameter when it becomes known, to enable future calls - to resume_archive_from_file in case resume is needed. - - :rtype: str - :return: The archive id of the newly created archive - """ - part_size = self.DefaultPartSize - if not file_obj: - file_size = os.path.getsize(filename) - try: - part_size = minimum_part_size(file_size, part_size) - except ValueError: - raise UploadArchiveError("File size of %s bytes exceeds " - "40,000 GB archive limit of Glacier.") - file_obj = open(filename, "rb") - writer = self.create_archive_writer( - description=description, - part_size=part_size) - if upload_id_callback: - upload_id_callback(writer.upload_id) - while True: - data = file_obj.read(part_size) - if not data: - break - writer.write(data) - writer.close() - return writer.get_archive_id() - - @staticmethod - def _range_string_to_part_index(range_string, part_size): - start, inside_end = [int(value) for value in range_string.split('-')] - end = inside_end + 1 - length = end - start - if length == part_size + 1: - # Off-by-one bug in Amazon's Glacier implementation, - # see: https://forums.aws.amazon.com/thread.jspa?threadID=106866 - # Workaround: since part_size is too big by one byte, adjust it - end -= 1 - inside_end -= 1 - length -= 1 - assert not (start % part_size), ( - "upload part start byte is not on a part boundary") - assert (length <= part_size), "upload part is bigger than part size" - return start // part_size - - def resume_archive_from_file(self, upload_id, filename=None, - file_obj=None): - """Resume upload of a file already part-uploaded to Glacier. - - The resumption of an upload where the part-uploaded section is empty - is a valid degenerate case that this function can handle. - - One and only one of filename or file_obj must be specified. - - :type upload_id: str - :param upload_id: existing Glacier upload id of upload being resumed. - - :type filename: str - :param filename: file to open for resume - - :type fobj: file - :param fobj: file-like object containing local data to resume. This - must read from the start of the entire upload, not just from the - point being resumed. Use fobj.seek(0) to achieve this if necessary. - - :rtype: str - :return: The archive id of the newly created archive - - """ - part_list_response = self.list_all_parts(upload_id) - part_size = part_list_response['PartSizeInBytes'] - - part_hash_map = {} - for part_desc in part_list_response['Parts']: - part_index = self._range_string_to_part_index( - part_desc['RangeInBytes'], part_size) - part_tree_hash = codecs.decode(part_desc['SHA256TreeHash'], 'hex_codec') - part_hash_map[part_index] = part_tree_hash - - if not file_obj: - file_obj = open(filename, "rb") - - return resume_file_upload( - self, upload_id, part_size, file_obj, part_hash_map) - - def concurrent_create_archive_from_file(self, filename, description, - **kwargs): - """ - Create a new archive from a file and upload the given - file. - - This is a convenience method around the - :class:`boto.glacier.concurrent.ConcurrentUploader` - class. This method will perform a multipart upload - and upload the parts of the file concurrently. - - :type filename: str - :param filename: A filename to upload - - :param kwargs: Additional kwargs to pass through to - :py:class:`boto.glacier.concurrent.ConcurrentUploader`. - You can pass any argument besides the ``api`` and - ``vault_name`` param (these arguments are already - passed to the ``ConcurrentUploader`` for you). - - :raises: `boto.glacier.exception.UploadArchiveError` is an error - occurs during the upload process. - - :rtype: str - :return: The archive id of the newly created archive - - """ - uploader = ConcurrentUploader(self.layer1, self.name, **kwargs) - archive_id = uploader.upload(filename, description) - return archive_id - - def retrieve_archive(self, archive_id, sns_topic=None, - description=None): - """ - Initiate a archive retrieval job to download the data from an - archive. You will need to wait for the notification from - Amazon (via SNS) before you can actually download the data, - this takes around 4 hours. - - :type archive_id: str - :param archive_id: The id of the archive - - :type description: str - :param description: An optional description for the job. - - :type sns_topic: str - :param sns_topic: The Amazon SNS topic ARN where Amazon Glacier - sends notification when the job is completed and the output - is ready for you to download. - - :rtype: :class:`boto.glacier.job.Job` - :return: A Job object representing the retrieval job. - """ - job_data = {'Type': 'archive-retrieval', - 'ArchiveId': archive_id} - if sns_topic is not None: - job_data['SNSTopic'] = sns_topic - if description is not None: - job_data['Description'] = description - - response = self.layer1.initiate_job(self.name, job_data) - return self.get_job(response['JobId']) - - def retrieve_inventory(self, sns_topic=None, - description=None, byte_range=None, - start_date=None, end_date=None, - limit=None): - """ - Initiate a inventory retrieval job to list the items in the - vault. You will need to wait for the notification from - Amazon (via SNS) before you can actually download the data, - this takes around 4 hours. - - :type description: str - :param description: An optional description for the job. - - :type sns_topic: str - :param sns_topic: The Amazon SNS topic ARN where Amazon Glacier - sends notification when the job is completed and the output - is ready for you to download. - - :type byte_range: str - :param byte_range: Range of bytes to retrieve. - - :type start_date: DateTime - :param start_date: Beginning of the date range to query. - - :type end_date: DateTime - :param end_date: End of the date range to query. - - :type limit: int - :param limit: Limits the number of results returned. - - :rtype: str - :return: The ID of the job - """ - job_data = {'Type': 'inventory-retrieval'} - if sns_topic is not None: - job_data['SNSTopic'] = sns_topic - if description is not None: - job_data['Description'] = description - if byte_range is not None: - job_data['RetrievalByteRange'] = byte_range - if start_date is not None or end_date is not None or limit is not None: - rparams = {} - - if start_date is not None: - rparams['StartDate'] = start_date.strftime('%Y-%m-%dT%H:%M:%S%Z') - if end_date is not None: - rparams['EndDate'] = end_date.strftime('%Y-%m-%dT%H:%M:%S%Z') - if limit is not None: - rparams['Limit'] = limit - - job_data['InventoryRetrievalParameters'] = rparams - - response = self.layer1.initiate_job(self.name, job_data) - return response['JobId'] - - def retrieve_inventory_job(self, **kwargs): - """ - Identical to ``retrieve_inventory``, but returns a ``Job`` instance - instead of just the job ID. - - :type description: str - :param description: An optional description for the job. - - :type sns_topic: str - :param sns_topic: The Amazon SNS topic ARN where Amazon Glacier - sends notification when the job is completed and the output - is ready for you to download. - - :type byte_range: str - :param byte_range: Range of bytes to retrieve. - - :type start_date: DateTime - :param start_date: Beginning of the date range to query. - - :type end_date: DateTime - :param end_date: End of the date range to query. - - :type limit: int - :param limit: Limits the number of results returned. - - :rtype: :class:`boto.glacier.job.Job` - :return: A Job object representing the retrieval job. - """ - job_id = self.retrieve_inventory(**kwargs) - return self.get_job(job_id) - - def delete_archive(self, archive_id): - """ - This operation deletes an archive from the vault. - - :type archive_id: str - :param archive_id: The ID for the archive to be deleted. - """ - return self.layer1.delete_archive(self.name, archive_id) - - def get_job(self, job_id): - """ - Get an object representing a job in progress. - - :type job_id: str - :param job_id: The ID of the job - - :rtype: :class:`boto.glacier.job.Job` - :return: A Job object representing the job. - """ - response_data = self.layer1.describe_job(self.name, job_id) - return Job(self, response_data) - - def list_jobs(self, completed=None, status_code=None): - """ - Return a list of Job objects related to this vault. - - :type completed: boolean - :param completed: Specifies the state of the jobs to return. - If a value of True is passed, only completed jobs will - be returned. If a value of False is passed, only - uncompleted jobs will be returned. If no value is - passed, all jobs will be returned. - - :type status_code: string - :param status_code: Specifies the type of job status to return. - Valid values are: InProgress|Succeeded|Failed. If not - specified, jobs with all status codes are returned. - - :rtype: list of :class:`boto.glacier.job.Job` - :return: A list of Job objects related to this vault. - """ - response_data = self.layer1.list_jobs(self.name, completed, - status_code) - return [Job(self, jd) for jd in response_data['JobList']] - - def list_all_parts(self, upload_id): - """Automatically make and combine multiple calls to list_parts. - - Call list_parts as necessary, combining the results in case multiple - calls were required to get data on all available parts. - - """ - result = self.layer1.list_parts(self.name, upload_id) - marker = result['Marker'] - while marker: - additional_result = self.layer1.list_parts( - self.name, upload_id, marker=marker) - result['Parts'].extend(additional_result['Parts']) - marker = additional_result['Marker'] - # The marker makes no sense in an unpaginated result, and clearing it - # makes testing easier. This also has the nice property that the result - # is a normal (but expanded) response. - result['Marker'] = None - return result diff --git a/awx/lib/site-packages/boto/glacier/writer.py b/awx/lib/site-packages/boto/glacier/writer.py deleted file mode 100644 index fa3161ab3c..0000000000 --- a/awx/lib/site-packages/boto/glacier/writer.py +++ /dev/null @@ -1,262 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# Copyright (c) 2012 Robie Basak <robie@justgohome.co.uk> -# Tree hash implementation from Aaron Brady bradya@gmail.com -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import hashlib - -from boto.glacier.utils import chunk_hashes, tree_hash, bytes_to_hex -# This import is provided for backwards compatibility. This function is -# now in boto.glacier.utils, but any existing code can still import -# this directly from this module. -from boto.glacier.utils import compute_hashes_from_fileobj - - -_ONE_MEGABYTE = 1024 * 1024 - - -class _Partitioner(object): - """Convert variable-size writes into part-sized writes - - Call write(data) with variable sized data as needed to write all data. Call - flush() after all data is written. - - This instance will call send_fn(part_data) as needed in part_size pieces, - except for the final part which may be shorter than part_size. Make sure to - call flush() to ensure that a short final part results in a final send_fn - call. - - """ - def __init__(self, part_size, send_fn): - self.part_size = part_size - self.send_fn = send_fn - self._buffer = [] - self._buffer_size = 0 - - def write(self, data): - if data == b'': - return - self._buffer.append(data) - self._buffer_size += len(data) - while self._buffer_size > self.part_size: - self._send_part() - - def _send_part(self): - data = b''.join(self._buffer) - # Put back any data remaining over the part size into the - # buffer - if len(data) > self.part_size: - self._buffer = [data[self.part_size:]] - self._buffer_size = len(self._buffer[0]) - else: - self._buffer = [] - self._buffer_size = 0 - # The part we will send - part = data[:self.part_size] - self.send_fn(part) - - def flush(self): - if self._buffer_size > 0: - self._send_part() - - -class _Uploader(object): - """Upload to a Glacier upload_id. - - Call upload_part for each part (in any order) and then close to complete - the upload. - - """ - def __init__(self, vault, upload_id, part_size, chunk_size=_ONE_MEGABYTE): - self.vault = vault - self.upload_id = upload_id - self.part_size = part_size - self.chunk_size = chunk_size - self.archive_id = None - - self._uploaded_size = 0 - self._tree_hashes = [] - - self.closed = False - - def _insert_tree_hash(self, index, raw_tree_hash): - list_length = len(self._tree_hashes) - if index >= list_length: - self._tree_hashes.extend([None] * (list_length - index + 1)) - self._tree_hashes[index] = raw_tree_hash - - def upload_part(self, part_index, part_data): - """Upload a part to Glacier. - - :param part_index: part number where 0 is the first part - :param part_data: data to upload corresponding to this part - - """ - if self.closed: - raise ValueError("I/O operation on closed file") - # Create a request and sign it - part_tree_hash = tree_hash(chunk_hashes(part_data, self.chunk_size)) - self._insert_tree_hash(part_index, part_tree_hash) - - hex_tree_hash = bytes_to_hex(part_tree_hash) - linear_hash = hashlib.sha256(part_data).hexdigest() - start = self.part_size * part_index - content_range = (start, - (start + len(part_data)) - 1) - response = self.vault.layer1.upload_part(self.vault.name, - self.upload_id, - linear_hash, - hex_tree_hash, - content_range, part_data) - response.read() - self._uploaded_size += len(part_data) - - def skip_part(self, part_index, part_tree_hash, part_length): - """Skip uploading of a part. - - The final close call needs to calculate the tree hash and total size - of all uploaded data, so this is the mechanism for resume - functionality to provide it without actually uploading the data again. - - :param part_index: part number where 0 is the first part - :param part_tree_hash: binary tree_hash of part being skipped - :param part_length: length of part being skipped - - """ - if self.closed: - raise ValueError("I/O operation on closed file") - self._insert_tree_hash(part_index, part_tree_hash) - self._uploaded_size += part_length - - def close(self): - if self.closed: - return - if None in self._tree_hashes: - raise RuntimeError("Some parts were not uploaded.") - # Complete the multiplart glacier upload - hex_tree_hash = bytes_to_hex(tree_hash(self._tree_hashes)) - response = self.vault.layer1.complete_multipart_upload( - self.vault.name, self.upload_id, hex_tree_hash, - self._uploaded_size) - self.archive_id = response['ArchiveId'] - self.closed = True - - -def generate_parts_from_fobj(fobj, part_size): - data = fobj.read(part_size) - while data: - yield data.encode('utf-8') - data = fobj.read(part_size) - - -def resume_file_upload(vault, upload_id, part_size, fobj, part_hash_map, - chunk_size=_ONE_MEGABYTE): - """Resume upload of a file already part-uploaded to Glacier. - - The resumption of an upload where the part-uploaded section is empty is a - valid degenerate case that this function can handle. In this case, - part_hash_map should be an empty dict. - - :param vault: boto.glacier.vault.Vault object. - :param upload_id: existing Glacier upload id of upload being resumed. - :param part_size: part size of existing upload. - :param fobj: file object containing local data to resume. This must read - from the start of the entire upload, not just from the point being - resumed. Use fobj.seek(0) to achieve this if necessary. - :param part_hash_map: {part_index: part_tree_hash, ...} of data already - uploaded. Each supplied part_tree_hash will be verified and the part - re-uploaded if there is a mismatch. - :param chunk_size: chunk size of tree hash calculation. This must be - 1 MiB for Amazon. - - """ - uploader = _Uploader(vault, upload_id, part_size, chunk_size) - for part_index, part_data in enumerate( - generate_parts_from_fobj(fobj, part_size)): - part_tree_hash = tree_hash(chunk_hashes(part_data, chunk_size)) - if (part_index not in part_hash_map or - part_hash_map[part_index] != part_tree_hash): - uploader.upload_part(part_index, part_data) - else: - uploader.skip_part(part_index, part_tree_hash, len(part_data)) - uploader.close() - return uploader.archive_id - - -class Writer(object): - """ - Presents a file-like object for writing to a Amazon Glacier - Archive. The data is written using the multi-part upload API. - """ - def __init__(self, vault, upload_id, part_size, chunk_size=_ONE_MEGABYTE): - self.uploader = _Uploader(vault, upload_id, part_size, chunk_size) - self.partitioner = _Partitioner(part_size, self._upload_part) - self.closed = False - self.next_part_index = 0 - - def write(self, data): - if self.closed: - raise ValueError("I/O operation on closed file") - self.partitioner.write(data) - - def _upload_part(self, part_data): - self.uploader.upload_part(self.next_part_index, part_data) - self.next_part_index += 1 - - def close(self): - if self.closed: - return - self.partitioner.flush() - self.uploader.close() - self.closed = True - - def get_archive_id(self): - self.close() - return self.uploader.archive_id - - @property - def current_tree_hash(self): - """ - Returns the current tree hash for the data that's been written - **so far**. - - Only once the writing is complete is the final tree hash returned. - """ - return tree_hash(self.uploader._tree_hashes) - - @property - def current_uploaded_size(self): - """ - Returns the current uploaded size for the data that's been written - **so far**. - - Only once the writing is complete is the final uploaded size returned. - """ - return self.uploader._uploaded_size - - @property - def upload_id(self): - return self.uploader.upload_id - - @property - def vault(self): - return self.uploader.vault diff --git a/awx/lib/site-packages/boto/gs/__init__.py b/awx/lib/site-packages/boto/gs/__init__.py deleted file mode 100644 index bf4c0b942b..0000000000 --- a/awx/lib/site-packages/boto/gs/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - diff --git a/awx/lib/site-packages/boto/gs/acl.py b/awx/lib/site-packages/boto/gs/acl.py deleted file mode 100644 index 57bdce1cbc..0000000000 --- a/awx/lib/site-packages/boto/gs/acl.py +++ /dev/null @@ -1,308 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.gs.user import User -from boto.exception import InvalidAclError - -ACCESS_CONTROL_LIST = 'AccessControlList' -ALL_AUTHENTICATED_USERS = 'AllAuthenticatedUsers' -ALL_USERS = 'AllUsers' -DISPLAY_NAME = 'DisplayName' -DOMAIN = 'Domain' -EMAIL_ADDRESS = 'EmailAddress' -ENTRY = 'Entry' -ENTRIES = 'Entries' -GROUP_BY_DOMAIN = 'GroupByDomain' -GROUP_BY_EMAIL = 'GroupByEmail' -GROUP_BY_ID = 'GroupById' -ID = 'ID' -NAME = 'Name' -OWNER = 'Owner' -PERMISSION = 'Permission' -SCOPE = 'Scope' -TYPE = 'type' -USER_BY_EMAIL = 'UserByEmail' -USER_BY_ID = 'UserById' - - -CannedACLStrings = ['private', 'public-read', 'project-private', - 'public-read-write', 'authenticated-read', - 'bucket-owner-read', 'bucket-owner-full-control'] -"""A list of Google Cloud Storage predefined (canned) ACL strings.""" - -SupportedPermissions = ['READ', 'WRITE', 'FULL_CONTROL'] -"""A list of supported ACL permissions.""" - - -class ACL(object): - - def __init__(self, parent=None): - self.parent = parent - self.entries = Entries(self) - - @property - def acl(self): - return self - - def __repr__(self): - # Owner is optional in GS ACLs. - if hasattr(self, 'owner'): - entries_repr = ['Owner:%s' % self.owner.__repr__()] - else: - entries_repr = [''] - acl_entries = self.entries - if acl_entries: - for e in acl_entries.entry_list: - entries_repr.append(e.__repr__()) - return '<%s>' % ', '.join(entries_repr) - - # Method with same signature as boto.s3.acl.ACL.add_email_grant(), to allow - # polymorphic treatment at application layer. - def add_email_grant(self, permission, email_address): - entry = Entry(type=USER_BY_EMAIL, email_address=email_address, - permission=permission) - self.entries.entry_list.append(entry) - - # Method with same signature as boto.s3.acl.ACL.add_user_grant(), to allow - # polymorphic treatment at application layer. - def add_user_grant(self, permission, user_id): - entry = Entry(permission=permission, type=USER_BY_ID, id=user_id) - self.entries.entry_list.append(entry) - - def add_group_email_grant(self, permission, email_address): - entry = Entry(type=GROUP_BY_EMAIL, email_address=email_address, - permission=permission) - self.entries.entry_list.append(entry) - - def add_group_grant(self, permission, group_id): - entry = Entry(type=GROUP_BY_ID, id=group_id, permission=permission) - self.entries.entry_list.append(entry) - - def startElement(self, name, attrs, connection): - if name.lower() == OWNER.lower(): - self.owner = User(self) - return self.owner - elif name.lower() == ENTRIES.lower(): - self.entries = Entries(self) - return self.entries - else: - return None - - def endElement(self, name, value, connection): - if name.lower() == OWNER.lower(): - pass - elif name.lower() == ENTRIES.lower(): - pass - else: - setattr(self, name, value) - - def to_xml(self): - s = '<%s>' % ACCESS_CONTROL_LIST - # Owner is optional in GS ACLs. - if hasattr(self, 'owner'): - s += self.owner.to_xml() - acl_entries = self.entries - if acl_entries: - s += acl_entries.to_xml() - s += '</%s>' % ACCESS_CONTROL_LIST - return s - - -class Entries(object): - - def __init__(self, parent=None): - self.parent = parent - # Entries is the class that represents the same-named XML - # element. entry_list is the list within this class that holds the data. - self.entry_list = [] - - def __repr__(self): - entries_repr = [] - for e in self.entry_list: - entries_repr.append(e.__repr__()) - return '<Entries: %s>' % ', '.join(entries_repr) - - def startElement(self, name, attrs, connection): - if name.lower() == ENTRY.lower(): - entry = Entry(self) - self.entry_list.append(entry) - return entry - else: - return None - - def endElement(self, name, value, connection): - if name.lower() == ENTRY.lower(): - pass - else: - setattr(self, name, value) - - def to_xml(self): - if not self.entry_list: - return '' - s = '<%s>' % ENTRIES - for entry in self.entry_list: - s += entry.to_xml() - s += '</%s>' % ENTRIES - return s - - -# Class that represents a single (Scope, Permission) entry in an ACL. -class Entry(object): - - def __init__(self, scope=None, type=None, id=None, name=None, - email_address=None, domain=None, permission=None): - if not scope: - scope = Scope(self, type, id, name, email_address, domain) - self.scope = scope - self.permission = permission - - def __repr__(self): - return '<%s: %s>' % (self.scope.__repr__(), self.permission.__repr__()) - - def startElement(self, name, attrs, connection): - if name.lower() == SCOPE.lower(): - # The following if statement used to look like this: - # if not TYPE in attrs: - # which caused problems because older versions of the - # AttributesImpl class in the xml.sax library neglected to include - # a __contains__() method (which Python calls to implement the - # 'in' operator). So when you use the in operator, like the if - # statement above, Python invokes the __getiter__() method with - # index 0, which raises an exception. More recent versions of - # xml.sax include the __contains__() method, rendering the in - # operator functional. The work-around here is to formulate the - # if statement as below, which is the legal way to query - # AttributesImpl for containment (and is also how the added - # __contains__() method works). At one time gsutil disallowed - # xmlplus-based parsers, until this more specific problem was - # determined. - if TYPE not in attrs: - raise InvalidAclError('Missing "%s" in "%s" part of ACL' % - (TYPE, SCOPE)) - self.scope = Scope(self, attrs[TYPE]) - return self.scope - elif name.lower() == PERMISSION.lower(): - pass - else: - return None - - def endElement(self, name, value, connection): - if name.lower() == SCOPE.lower(): - pass - elif name.lower() == PERMISSION.lower(): - value = value.strip() - if not value in SupportedPermissions: - raise InvalidAclError('Invalid Permission "%s"' % value) - self.permission = value - else: - setattr(self, name, value) - - def to_xml(self): - s = '<%s>' % ENTRY - s += self.scope.to_xml() - s += '<%s>%s</%s>' % (PERMISSION, self.permission, PERMISSION) - s += '</%s>' % ENTRY - return s - - -class Scope(object): - - # Map from Scope type.lower() to lower-cased list of allowed sub-elems. - ALLOWED_SCOPE_TYPE_SUB_ELEMS = { - ALL_AUTHENTICATED_USERS.lower() : [], - ALL_USERS.lower() : [], - GROUP_BY_DOMAIN.lower() : [DOMAIN.lower()], - GROUP_BY_EMAIL.lower() : [ - DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()], - GROUP_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()], - USER_BY_EMAIL.lower() : [ - DISPLAY_NAME.lower(), EMAIL_ADDRESS.lower(), NAME.lower()], - USER_BY_ID.lower() : [DISPLAY_NAME.lower(), ID.lower(), NAME.lower()] - } - - def __init__(self, parent, type=None, id=None, name=None, - email_address=None, domain=None): - self.parent = parent - self.type = type - self.name = name - self.id = id - self.domain = domain - self.email_address = email_address - if self.type.lower() not in self.ALLOWED_SCOPE_TYPE_SUB_ELEMS: - raise InvalidAclError('Invalid %s %s "%s" ' % - (SCOPE, TYPE, self.type)) - - def __repr__(self): - named_entity = None - if self.id: - named_entity = self.id - elif self.email_address: - named_entity = self.email_address - elif self.domain: - named_entity = self.domain - if named_entity: - return '<%s: %s>' % (self.type, named_entity) - else: - return '<%s>' % self.type - - def startElement(self, name, attrs, connection): - if (not name.lower() in - self.ALLOWED_SCOPE_TYPE_SUB_ELEMS[self.type.lower()]): - raise InvalidAclError('Element "%s" not allowed in %s %s "%s" ' % - (name, SCOPE, TYPE, self.type)) - return None - - def endElement(self, name, value, connection): - value = value.strip() - if name.lower() == DOMAIN.lower(): - self.domain = value - elif name.lower() == EMAIL_ADDRESS.lower(): - self.email_address = value - elif name.lower() == ID.lower(): - self.id = value - elif name.lower() == NAME.lower(): - self.name = value - else: - setattr(self, name, value) - - def to_xml(self): - s = '<%s type="%s">' % (SCOPE, self.type) - if (self.type.lower() == ALL_AUTHENTICATED_USERS.lower() - or self.type.lower() == ALL_USERS.lower()): - pass - elif self.type.lower() == GROUP_BY_DOMAIN.lower(): - s += '<%s>%s</%s>' % (DOMAIN, self.domain, DOMAIN) - elif (self.type.lower() == GROUP_BY_EMAIL.lower() - or self.type.lower() == USER_BY_EMAIL.lower()): - s += '<%s>%s</%s>' % (EMAIL_ADDRESS, self.email_address, - EMAIL_ADDRESS) - if self.name: - s += '<%s>%s</%s>' % (NAME, self.name, NAME) - elif (self.type.lower() == GROUP_BY_ID.lower() - or self.type.lower() == USER_BY_ID.lower()): - s += '<%s>%s</%s>' % (ID, self.id, ID) - if self.name: - s += '<%s>%s</%s>' % (NAME, self.name, NAME) - else: - raise InvalidAclError('Invalid scope type "%s" ', self.type) - - s += '</%s>' % SCOPE - return s diff --git a/awx/lib/site-packages/boto/gs/bucket.py b/awx/lib/site-packages/boto/gs/bucket.py deleted file mode 100644 index 37636fb876..0000000000 --- a/awx/lib/site-packages/boto/gs/bucket.py +++ /dev/null @@ -1,989 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import re -import urllib -import xml.sax - -import boto -from boto import handler -from boto.resultset import ResultSet -from boto.exception import GSResponseError -from boto.exception import InvalidAclError -from boto.gs.acl import ACL, CannedACLStrings -from boto.gs.acl import SupportedPermissions as GSPermissions -from boto.gs.bucketlistresultset import VersionedBucketListResultSet -from boto.gs.cors import Cors -from boto.gs.lifecycle import LifecycleConfig -from boto.gs.key import Key as GSKey -from boto.s3.acl import Policy -from boto.s3.bucket import Bucket as S3Bucket -from boto.utils import get_utf8_value -from boto.compat import six - -# constants for http query args -DEF_OBJ_ACL = 'defaultObjectAcl' -STANDARD_ACL = 'acl' -CORS_ARG = 'cors' -LIFECYCLE_ARG = 'lifecycle' -ERROR_DETAILS_REGEX = re.compile(r'<Details>(?P<details>.*)</Details>') - -class Bucket(S3Bucket): - """Represents a Google Cloud Storage bucket.""" - - VersioningBody = ('<?xml version="1.0" encoding="UTF-8"?>\n' - '<VersioningConfiguration><Status>%s</Status>' - '</VersioningConfiguration>') - WebsiteBody = ('<?xml version="1.0" encoding="UTF-8"?>\n' - '<WebsiteConfiguration>%s%s</WebsiteConfiguration>') - WebsiteMainPageFragment = '<MainPageSuffix>%s</MainPageSuffix>' - WebsiteErrorFragment = '<NotFoundPage>%s</NotFoundPage>' - - def __init__(self, connection=None, name=None, key_class=GSKey): - super(Bucket, self).__init__(connection, name, key_class) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Name': - self.name = value - elif name == 'CreationDate': - self.creation_date = value - else: - setattr(self, name, value) - - def get_key(self, key_name, headers=None, version_id=None, - response_headers=None, generation=None): - """Returns a Key instance for an object in this bucket. - - Note that this method uses a HEAD request to check for the existence of - the key. - - :type key_name: string - :param key_name: The name of the key to retrieve - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/06N3b for details. - - :type version_id: string - :param version_id: Unused in this subclass. - - :type generation: int - :param generation: A specific generation number to fetch the key at. If - not specified, the latest generation is fetched. - - :rtype: :class:`boto.gs.key.Key` - :returns: A Key object from this bucket. - """ - query_args_l = [] - if generation: - query_args_l.append('generation=%s' % generation) - if response_headers: - for rk, rv in six.iteritems(response_headers): - query_args_l.append('%s=%s' % (rk, urllib.quote(rv))) - try: - key, resp = self._get_key_internal(key_name, headers, - query_args_l=query_args_l) - except GSResponseError as e: - if e.status == 403 and 'Forbidden' in e.reason: - # If we failed getting an object, let the user know which object - # failed rather than just returning a generic 403. - e.reason = ("Access denied to 'gs://%s/%s'." % - (self.name, key_name)) - raise - return key - - def copy_key(self, new_key_name, src_bucket_name, src_key_name, - metadata=None, src_version_id=None, storage_class='STANDARD', - preserve_acl=False, encrypt_key=False, headers=None, - query_args=None, src_generation=None): - """Create a new key in the bucket by copying an existing key. - - :type new_key_name: string - :param new_key_name: The name of the new key - - :type src_bucket_name: string - :param src_bucket_name: The name of the source bucket - - :type src_key_name: string - :param src_key_name: The name of the source key - - :type src_generation: int - :param src_generation: The generation number of the source key to copy. - If not specified, the latest generation is copied. - - :type metadata: dict - :param metadata: Metadata to be associated with new key. If - metadata is supplied, it will replace the metadata of the - source key being copied. If no metadata is supplied, the - source key's metadata will be copied to the new key. - - :type version_id: string - :param version_id: Unused in this subclass. - - :type storage_class: string - :param storage_class: The storage class of the new key. By - default, the new key will use the standard storage class. - Possible values are: STANDARD | DURABLE_REDUCED_AVAILABILITY - - :type preserve_acl: bool - :param preserve_acl: If True, the ACL from the source key will - be copied to the destination key. If False, the - destination key will have the default ACL. Note that - preserving the ACL in the new key object will require two - additional API calls to GCS, one to retrieve the current - ACL and one to set that ACL on the new object. If you - don't care about the ACL (or if you have a default ACL set - on the bucket), a value of False will be significantly more - efficient. - - :type encrypt_key: bool - :param encrypt_key: Included for compatibility with S3. This argument is - ignored. - - :type headers: dict - :param headers: A dictionary of header name/value pairs. - - :type query_args: string - :param query_args: A string of additional querystring arguments - to append to the request - - :rtype: :class:`boto.gs.key.Key` - :returns: An instance of the newly created key object - """ - if src_generation: - headers = headers or {} - headers['x-goog-copy-source-generation'] = str(src_generation) - return super(Bucket, self).copy_key( - new_key_name, src_bucket_name, src_key_name, metadata=metadata, - storage_class=storage_class, preserve_acl=preserve_acl, - encrypt_key=encrypt_key, headers=headers, query_args=query_args) - - def list_versions(self, prefix='', delimiter='', marker='', - generation_marker='', headers=None): - """ - List versioned objects within a bucket. This returns an - instance of an VersionedBucketListResultSet that automatically - handles all of the result paging, etc. from GCS. You just need - to keep iterating until there are no more results. Called - with no arguments, this will return an iterator object across - all keys within the bucket. - - :type prefix: string - :param prefix: allows you to limit the listing to a particular - prefix. For example, if you call the method with - prefix='/foo/' then the iterator will only cycle through - the keys that begin with the string '/foo/'. - - :type delimiter: string - :param delimiter: can be used in conjunction with the prefix - to allow you to organize and browse your keys - hierarchically. See: - https://developers.google.com/storage/docs/reference-headers#delimiter - for more details. - - :type marker: string - :param marker: The "marker" of where you are in the result set - - :type generation_marker: string - :param generation_marker: The "generation marker" of where you are in - the result set. - - :type headers: dict - :param headers: A dictionary of header name/value pairs. - - :rtype: - :class:`boto.gs.bucketlistresultset.VersionedBucketListResultSet` - :return: an instance of a BucketListResultSet that handles paging, etc. - """ - return VersionedBucketListResultSet(self, prefix, delimiter, - marker, generation_marker, - headers) - - def validate_get_all_versions_params(self, params): - """ - See documentation in boto/s3/bucket.py. - """ - self.validate_kwarg_names(params, - ['version_id_marker', 'delimiter', 'marker', - 'generation_marker', 'prefix', 'max_keys']) - - def delete_key(self, key_name, headers=None, version_id=None, - mfa_token=None, generation=None): - """ - Deletes a key from the bucket. - - :type key_name: string - :param key_name: The key name to delete - - :type headers: dict - :param headers: A dictionary of header name/value pairs. - - :type version_id: string - :param version_id: Unused in this subclass. - - :type mfa_token: tuple or list of strings - :param mfa_token: Unused in this subclass. - - :type generation: int - :param generation: The generation number of the key to delete. If not - specified, the latest generation number will be deleted. - - :rtype: :class:`boto.gs.key.Key` - :returns: A key object holding information on what was - deleted. - """ - query_args_l = [] - if generation: - query_args_l.append('generation=%s' % generation) - self._delete_key_internal(key_name, headers=headers, - version_id=version_id, mfa_token=mfa_token, - query_args_l=query_args_l) - - def set_acl(self, acl_or_str, key_name='', headers=None, version_id=None, - generation=None, if_generation=None, if_metageneration=None): - """Sets or changes a bucket's or key's ACL. - - :type acl_or_str: string or :class:`boto.gs.acl.ACL` - :param acl_or_str: A canned ACL string (see - :data:`~.gs.acl.CannedACLStrings`) or an ACL object. - - :type key_name: string - :param key_name: A key name within the bucket to set the ACL for. If not - specified, the ACL for the bucket will be set. - - :type headers: dict - :param headers: Additional headers to set during the request. - - :type version_id: string - :param version_id: Unused in this subclass. - - :type generation: int - :param generation: If specified, sets the ACL for a specific generation - of a versioned object. If not specified, the current version is - modified. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the acl - will only be updated if its current generation number is this value. - - :type if_metageneration: int - :param if_metageneration: (optional) If set to a metageneration number, - the acl will only be updated if its current metageneration number is - this value. - """ - if isinstance(acl_or_str, Policy): - raise InvalidAclError('Attempt to set S3 Policy on GS ACL') - elif isinstance(acl_or_str, ACL): - self.set_xml_acl(acl_or_str.to_xml(), key_name, headers=headers, - generation=generation, - if_generation=if_generation, - if_metageneration=if_metageneration) - else: - self.set_canned_acl(acl_or_str, key_name, headers=headers, - generation=generation, - if_generation=if_generation, - if_metageneration=if_metageneration) - - def set_def_acl(self, acl_or_str, headers=None): - """Sets or changes a bucket's default ACL. - - :type acl_or_str: string or :class:`boto.gs.acl.ACL` - :param acl_or_str: A canned ACL string (see - :data:`~.gs.acl.CannedACLStrings`) or an ACL object. - - :type headers: dict - :param headers: Additional headers to set during the request. - """ - if isinstance(acl_or_str, Policy): - raise InvalidAclError('Attempt to set S3 Policy on GS ACL') - elif isinstance(acl_or_str, ACL): - self.set_def_xml_acl(acl_or_str.to_xml(), headers=headers) - else: - self.set_def_canned_acl(acl_or_str, headers=headers) - - def _get_xml_acl_helper(self, key_name, headers, query_args): - """Provides common functionality for get_xml_acl and _get_acl_helper.""" - response = self.connection.make_request('GET', self.name, key_name, - query_args=query_args, - headers=headers) - body = response.read() - if response.status != 200: - if response.status == 403: - match = ERROR_DETAILS_REGEX.search(body) - details = match.group('details') if match else None - if details: - details = (('<Details>%s. Note that Full Control access' - ' is required to access ACLs.</Details>') % - details) - body = re.sub(ERROR_DETAILS_REGEX, details, body) - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - return body - - def _get_acl_helper(self, key_name, headers, query_args): - """Provides common functionality for get_acl and get_def_acl.""" - body = self._get_xml_acl_helper(key_name, headers, query_args) - acl = ACL(self) - h = handler.XmlHandler(acl, self) - xml.sax.parseString(body, h) - return acl - - def get_acl(self, key_name='', headers=None, version_id=None, - generation=None): - """Returns the ACL of the bucket or an object in the bucket. - - :param str key_name: The name of the object to get the ACL for. If not - specified, the ACL for the bucket will be returned. - - :param dict headers: Additional headers to set during the request. - - :type version_id: string - :param version_id: Unused in this subclass. - - :param int generation: If specified, gets the ACL for a specific - generation of a versioned object. If not specified, the current - version is returned. This parameter is only valid when retrieving - the ACL of an object, not a bucket. - - :rtype: :class:`.gs.acl.ACL` - """ - query_args = STANDARD_ACL - if generation: - query_args += '&generation=%s' % generation - return self._get_acl_helper(key_name, headers, query_args) - - def get_xml_acl(self, key_name='', headers=None, version_id=None, - generation=None): - """Returns the ACL string of the bucket or an object in the bucket. - - :param str key_name: The name of the object to get the ACL for. If not - specified, the ACL for the bucket will be returned. - - :param dict headers: Additional headers to set during the request. - - :type version_id: string - :param version_id: Unused in this subclass. - - :param int generation: If specified, gets the ACL for a specific - generation of a versioned object. If not specified, the current - version is returned. This parameter is only valid when retrieving - the ACL of an object, not a bucket. - - :rtype: str - """ - query_args = STANDARD_ACL - if generation: - query_args += '&generation=%s' % generation - return self._get_xml_acl_helper(key_name, headers, query_args) - - def get_def_acl(self, headers=None): - """Returns the bucket's default ACL. - - :param dict headers: Additional headers to set during the request. - - :rtype: :class:`.gs.acl.ACL` - """ - return self._get_acl_helper('', headers, DEF_OBJ_ACL) - - def _set_acl_helper(self, acl_or_str, key_name, headers, query_args, - generation, if_generation, if_metageneration, - canned=False): - """Provides common functionality for set_acl, set_xml_acl, - set_canned_acl, set_def_acl, set_def_xml_acl, and - set_def_canned_acl().""" - - headers = headers or {} - data = '' - if canned: - headers[self.connection.provider.acl_header] = acl_or_str - else: - data = acl_or_str - - if generation: - query_args += '&generation=%s' % generation - - if if_metageneration is not None and if_generation is None: - raise ValueError("Received if_metageneration argument with no " - "if_generation argument. A metageneration has no " - "meaning without a content generation.") - if not key_name and (if_generation or if_metageneration): - raise ValueError("Received if_generation or if_metageneration " - "parameter while setting the ACL of a bucket.") - if if_generation is not None: - headers['x-goog-if-generation-match'] = str(if_generation) - if if_metageneration is not None: - headers['x-goog-if-metageneration-match'] = str(if_metageneration) - - response = self.connection.make_request( - 'PUT', get_utf8_value(self.name), get_utf8_value(key_name), - data=get_utf8_value(data), headers=headers, query_args=query_args) - body = response.read() - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_xml_acl(self, acl_str, key_name='', headers=None, version_id=None, - query_args='acl', generation=None, if_generation=None, - if_metageneration=None): - """Sets a bucket's or objects's ACL to an XML string. - - :type acl_str: string - :param acl_str: A string containing the ACL XML. - - :type key_name: string - :param key_name: A key name within the bucket to set the ACL for. If not - specified, the ACL for the bucket will be set. - - :type headers: dict - :param headers: Additional headers to set during the request. - - :type version_id: string - :param version_id: Unused in this subclass. - - :type query_args: str - :param query_args: The query parameters to pass with the request. - - :type generation: int - :param generation: If specified, sets the ACL for a specific generation - of a versioned object. If not specified, the current version is - modified. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the acl - will only be updated if its current generation number is this value. - - :type if_metageneration: int - :param if_metageneration: (optional) If set to a metageneration number, - the acl will only be updated if its current metageneration number is - this value. - """ - return self._set_acl_helper(acl_str, key_name=key_name, headers=headers, - query_args=query_args, - generation=generation, - if_generation=if_generation, - if_metageneration=if_metageneration) - - def set_canned_acl(self, acl_str, key_name='', headers=None, - version_id=None, generation=None, if_generation=None, - if_metageneration=None): - """Sets a bucket's or objects's ACL using a predefined (canned) value. - - :type acl_str: string - :param acl_str: A canned ACL string. See - :data:`~.gs.acl.CannedACLStrings`. - - :type key_name: string - :param key_name: A key name within the bucket to set the ACL for. If not - specified, the ACL for the bucket will be set. - - :type headers: dict - :param headers: Additional headers to set during the request. - - :type version_id: string - :param version_id: Unused in this subclass. - - :type generation: int - :param generation: If specified, sets the ACL for a specific generation - of a versioned object. If not specified, the current version is - modified. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the acl - will only be updated if its current generation number is this value. - - :type if_metageneration: int - :param if_metageneration: (optional) If set to a metageneration number, - the acl will only be updated if its current metageneration number is - this value. - """ - if acl_str not in CannedACLStrings: - raise ValueError("Provided canned ACL string (%s) is not valid." - % acl_str) - query_args = STANDARD_ACL - return self._set_acl_helper(acl_str, key_name, headers, query_args, - generation, if_generation, - if_metageneration, canned=True) - - def set_def_canned_acl(self, acl_str, headers=None): - """Sets a bucket's default ACL using a predefined (canned) value. - - :type acl_str: string - :param acl_str: A canned ACL string. See - :data:`~.gs.acl.CannedACLStrings`. - - :type headers: dict - :param headers: Additional headers to set during the request. - """ - if acl_str not in CannedACLStrings: - raise ValueError("Provided canned ACL string (%s) is not valid." - % acl_str) - query_args = DEF_OBJ_ACL - return self._set_acl_helper(acl_str, '', headers, query_args, - generation=None, if_generation=None, - if_metageneration=None, canned=True) - - def set_def_xml_acl(self, acl_str, headers=None): - """Sets a bucket's default ACL to an XML string. - - :type acl_str: string - :param acl_str: A string containing the ACL XML. - - :type headers: dict - :param headers: Additional headers to set during the request. - """ - return self.set_xml_acl(acl_str, '', headers, - query_args=DEF_OBJ_ACL) - - def get_cors(self, headers=None): - """Returns a bucket's CORS XML document. - - :param dict headers: Additional headers to send with the request. - :rtype: :class:`~.cors.Cors` - """ - response = self.connection.make_request('GET', self.name, - query_args=CORS_ARG, - headers=headers) - body = response.read() - if response.status == 200: - # Success - parse XML and return Cors object. - cors = Cors() - h = handler.XmlHandler(cors, self) - xml.sax.parseString(body, h) - return cors - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_cors(self, cors, headers=None): - """Sets a bucket's CORS XML document. - - :param str cors: A string containing the CORS XML. - :param dict headers: Additional headers to send with the request. - """ - response = self.connection.make_request( - 'PUT', get_utf8_value(self.name), data=get_utf8_value(cors), - query_args=CORS_ARG, headers=headers) - body = response.read() - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_storage_class(self): - """ - Returns the StorageClass for the bucket. - - :rtype: str - :return: The StorageClass for the bucket. - """ - response = self.connection.make_request('GET', self.name, - query_args='storageClass') - body = response.read() - if response.status == 200: - rs = ResultSet(self) - h = handler.XmlHandler(rs, self) - xml.sax.parseString(body, h) - return rs.StorageClass - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - - # Method with same signature as boto.s3.bucket.Bucket.add_email_grant(), - # to allow polymorphic treatment at application layer. - def add_email_grant(self, permission, email_address, - recursive=False, headers=None): - """ - Convenience method that provides a quick way to add an email grant - to a bucket. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL - and then PUT's the new ACL back to GCS. - - :type permission: string - :param permission: The permission being granted. Should be one of: - (READ, WRITE, FULL_CONTROL). - - :type email_address: string - :param email_address: The email address associated with the GS - account your are granting the permission to. - - :type recursive: bool - :param recursive: A boolean value to controls whether the call - will apply the grant to all keys within the bucket - or not. The default value is False. By passing a - True value, the call will iterate through all keys - in the bucket and apply the same grant to each key. - CAUTION: If you have a lot of keys, this could take - a long time! - """ - if permission not in GSPermissions: - raise self.connection.provider.storage_permissions_error( - 'Unknown Permission: %s' % permission) - acl = self.get_acl(headers=headers) - acl.add_email_grant(permission, email_address) - self.set_acl(acl, headers=headers) - if recursive: - for key in self: - key.add_email_grant(permission, email_address, headers=headers) - - # Method with same signature as boto.s3.bucket.Bucket.add_user_grant(), - # to allow polymorphic treatment at application layer. - def add_user_grant(self, permission, user_id, recursive=False, - headers=None): - """ - Convenience method that provides a quick way to add a canonical user - grant to a bucket. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL and - then PUTs the new ACL back to GCS. - - :type permission: string - :param permission: The permission being granted. Should be one of: - (READ|WRITE|FULL_CONTROL) - - :type user_id: string - :param user_id: The canonical user id associated with the GS account - you are granting the permission to. - - :type recursive: bool - :param recursive: A boolean value to controls whether the call - will apply the grant to all keys within the bucket - or not. The default value is False. By passing a - True value, the call will iterate through all keys - in the bucket and apply the same grant to each key. - CAUTION: If you have a lot of keys, this could take - a long time! - """ - if permission not in GSPermissions: - raise self.connection.provider.storage_permissions_error( - 'Unknown Permission: %s' % permission) - acl = self.get_acl(headers=headers) - acl.add_user_grant(permission, user_id) - self.set_acl(acl, headers=headers) - if recursive: - for key in self: - key.add_user_grant(permission, user_id, headers=headers) - - def add_group_email_grant(self, permission, email_address, recursive=False, - headers=None): - """ - Convenience method that provides a quick way to add an email group - grant to a bucket. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL and - then PUT's the new ACL back to GCS. - - :type permission: string - :param permission: The permission being granted. Should be one of: - READ|WRITE|FULL_CONTROL - See http://code.google.com/apis/storage/docs/developer-guide.html#authorization - for more details on permissions. - - :type email_address: string - :param email_address: The email address associated with the Google - Group to which you are granting the permission. - - :type recursive: bool - :param recursive: A boolean value to controls whether the call - will apply the grant to all keys within the bucket - or not. The default value is False. By passing a - True value, the call will iterate through all keys - in the bucket and apply the same grant to each key. - CAUTION: If you have a lot of keys, this could take - a long time! - """ - if permission not in GSPermissions: - raise self.connection.provider.storage_permissions_error( - 'Unknown Permission: %s' % permission) - acl = self.get_acl(headers=headers) - acl.add_group_email_grant(permission, email_address) - self.set_acl(acl, headers=headers) - if recursive: - for key in self: - key.add_group_email_grant(permission, email_address, - headers=headers) - - # Method with same input signature as boto.s3.bucket.Bucket.list_grants() - # (but returning different object type), to allow polymorphic treatment - # at application layer. - def list_grants(self, headers=None): - """Returns the ACL entries applied to this bucket. - - :param dict headers: Additional headers to send with the request. - :rtype: list containing :class:`~.gs.acl.Entry` objects. - """ - acl = self.get_acl(headers=headers) - return acl.entries - - def disable_logging(self, headers=None): - """Disable logging on this bucket. - - :param dict headers: Additional headers to send with the request. - """ - xml_str = '<?xml version="1.0" encoding="UTF-8"?><Logging/>' - self.set_subresource('logging', xml_str, headers=headers) - - def enable_logging(self, target_bucket, target_prefix=None, headers=None): - """Enable logging on a bucket. - - :type target_bucket: bucket or string - :param target_bucket: The bucket to log to. - - :type target_prefix: string - :param target_prefix: The prefix which should be prepended to the - generated log files written to the target_bucket. - - :param dict headers: Additional headers to send with the request. - """ - if isinstance(target_bucket, Bucket): - target_bucket = target_bucket.name - xml_str = '<?xml version="1.0" encoding="UTF-8"?><Logging>' - xml_str = (xml_str + '<LogBucket>%s</LogBucket>' % target_bucket) - if target_prefix: - xml_str = (xml_str + - '<LogObjectPrefix>%s</LogObjectPrefix>' % target_prefix) - xml_str = xml_str + '</Logging>' - - self.set_subresource('logging', xml_str, headers=headers) - - def get_logging_config_with_xml(self, headers=None): - """Returns the current status of logging configuration on the bucket as - unparsed XML. - - :param dict headers: Additional headers to send with the request. - - :rtype: 2-Tuple - :returns: 2-tuple containing: - - 1) A dictionary containing the parsed XML response from GCS. The - overall structure is: - - * Logging - - * LogObjectPrefix: Prefix that is prepended to log objects. - * LogBucket: Target bucket for log objects. - - 2) Unparsed XML describing the bucket's logging configuration. - """ - response = self.connection.make_request('GET', self.name, - query_args='logging', - headers=headers) - body = response.read() - boto.log.debug(body) - - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e, body - - def get_logging_config(self, headers=None): - """Returns the current status of logging configuration on the bucket. - - :param dict headers: Additional headers to send with the request. - - :rtype: dict - :returns: A dictionary containing the parsed XML response from GCS. The - overall structure is: - - * Logging - - * LogObjectPrefix: Prefix that is prepended to log objects. - * LogBucket: Target bucket for log objects. - """ - return self.get_logging_config_with_xml(headers)[0] - - def configure_website(self, main_page_suffix=None, error_key=None, - headers=None): - """Configure this bucket to act as a website - - :type main_page_suffix: str - :param main_page_suffix: Suffix that is appended to a request that is - for a "directory" on the website endpoint (e.g. if the suffix is - index.html and you make a request to samplebucket/images/ the data - that is returned will be for the object with the key name - images/index.html). The suffix must not be empty and must not - include a slash character. This parameter is optional and the - property is disabled if excluded. - - :type error_key: str - :param error_key: The object key name to use when a 400 error occurs. - This parameter is optional and the property is disabled if excluded. - - :param dict headers: Additional headers to send with the request. - """ - if main_page_suffix: - main_page_frag = self.WebsiteMainPageFragment % main_page_suffix - else: - main_page_frag = '' - - if error_key: - error_frag = self.WebsiteErrorFragment % error_key - else: - error_frag = '' - - body = self.WebsiteBody % (main_page_frag, error_frag) - response = self.connection.make_request( - 'PUT', get_utf8_value(self.name), data=get_utf8_value(body), - query_args='websiteConfig', headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_website_configuration(self, headers=None): - """Returns the current status of website configuration on the bucket. - - :param dict headers: Additional headers to send with the request. - - :rtype: dict - :returns: A dictionary containing the parsed XML response from GCS. The - overall structure is: - - * WebsiteConfiguration - - * MainPageSuffix: suffix that is appended to request that - is for a "directory" on the website endpoint. - * NotFoundPage: name of an object to serve when site visitors - encounter a 404. - """ - return self.get_website_configuration_with_xml(headers)[0] - - def get_website_configuration_with_xml(self, headers=None): - """Returns the current status of website configuration on the bucket as - unparsed XML. - - :param dict headers: Additional headers to send with the request. - - :rtype: 2-Tuple - :returns: 2-tuple containing: - - 1) A dictionary containing the parsed XML response from GCS. The - overall structure is: - - * WebsiteConfiguration - - * MainPageSuffix: suffix that is appended to request that is for - a "directory" on the website endpoint. - * NotFoundPage: name of an object to serve when site visitors - encounter a 404 - - 2) Unparsed XML describing the bucket's website configuration. - """ - response = self.connection.make_request('GET', self.name, - query_args='websiteConfig', headers=headers) - body = response.read() - boto.log.debug(body) - - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e, body - - def delete_website_configuration(self, headers=None): - """Remove the website configuration from this bucket. - - :param dict headers: Additional headers to send with the request. - """ - self.configure_website(headers=headers) - - def get_versioning_status(self, headers=None): - """Returns the current status of versioning configuration on the bucket. - - :rtype: bool - """ - response = self.connection.make_request('GET', self.name, - query_args='versioning', - headers=headers) - body = response.read() - boto.log.debug(body) - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - resp_json = boto.jsonresponse.Element() - boto.jsonresponse.XmlHandler(resp_json, None).parse(body) - resp_json = resp_json['VersioningConfiguration'] - return ('Status' in resp_json) and (resp_json['Status'] == 'Enabled') - - def configure_versioning(self, enabled, headers=None): - """Configure versioning for this bucket. - - :param bool enabled: If set to True, enables versioning on this bucket. - If set to False, disables versioning. - - :param dict headers: Additional headers to send with the request. - """ - if enabled == True: - req_body = self.VersioningBody % ('Enabled') - else: - req_body = self.VersioningBody % ('Suspended') - self.set_subresource('versioning', req_body, headers=headers) - - def get_lifecycle_config(self, headers=None): - """ - Returns the current lifecycle configuration on the bucket. - - :rtype: :class:`boto.gs.lifecycle.LifecycleConfig` - :returns: A LifecycleConfig object that describes all current - lifecycle rules in effect for the bucket. - """ - response = self.connection.make_request('GET', self.name, - query_args=LIFECYCLE_ARG, headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 200: - lifecycle_config = LifecycleConfig() - h = handler.XmlHandler(lifecycle_config, self) - xml.sax.parseString(body, h) - return lifecycle_config - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def configure_lifecycle(self, lifecycle_config, headers=None): - """ - Configure lifecycle for this bucket. - - :type lifecycle_config: :class:`boto.gs.lifecycle.LifecycleConfig` - :param lifecycle_config: The lifecycle configuration you want - to configure for this bucket. - """ - xml = lifecycle_config.to_xml() - response = self.connection.make_request( - 'PUT', get_utf8_value(self.name), data=get_utf8_value(xml), - query_args=LIFECYCLE_ARG, headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) diff --git a/awx/lib/site-packages/boto/gs/bucketlistresultset.py b/awx/lib/site-packages/boto/gs/bucketlistresultset.py deleted file mode 100644 index db634cfd45..0000000000 --- a/awx/lib/site-packages/boto/gs/bucketlistresultset.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2012 Google Inc. -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -def versioned_bucket_lister(bucket, prefix='', delimiter='', - marker='', generation_marker='', headers=None): - """ - A generator function for listing versioned objects. - """ - more_results = True - k = None - while more_results: - rs = bucket.get_all_versions(prefix=prefix, marker=marker, - generation_marker=generation_marker, - delimiter=delimiter, headers=headers, - max_keys=999) - for k in rs: - yield k - marker = rs.next_marker - generation_marker = rs.next_generation_marker - more_results= rs.is_truncated - -class VersionedBucketListResultSet(object): - """ - A resultset for listing versions within a bucket. Uses the bucket_lister - generator function and implements the iterator interface. This - transparently handles the results paging from GCS so even if you have - many thousands of keys within the bucket you can iterate over all - keys in a reasonably efficient manner. - """ - - def __init__(self, bucket=None, prefix='', delimiter='', marker='', - generation_marker='', headers=None): - self.bucket = bucket - self.prefix = prefix - self.delimiter = delimiter - self.marker = marker - self.generation_marker = generation_marker - self.headers = headers - - def __iter__(self): - return versioned_bucket_lister(self.bucket, prefix=self.prefix, - delimiter=self.delimiter, - marker=self.marker, - generation_marker=self.generation_marker, - headers=self.headers) diff --git a/awx/lib/site-packages/boto/gs/connection.py b/awx/lib/site-packages/boto/gs/connection.py deleted file mode 100644 index 9a2e4a2bbb..0000000000 --- a/awx/lib/site-packages/boto/gs/connection.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.gs.bucket import Bucket -from boto.s3.connection import S3Connection -from boto.s3.connection import SubdomainCallingFormat -from boto.s3.connection import check_lowercase_bucketname -from boto.utils import get_utf8_value - -class Location(object): - DEFAULT = 'US' - EU = 'EU' - -class GSConnection(S3Connection): - - DefaultHost = 'storage.googleapis.com' - QueryString = 'Signature=%s&Expires=%d&GoogleAccessId=%s' - - def __init__(self, gs_access_key_id=None, gs_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, - host=DefaultHost, debug=0, https_connection_factory=None, - calling_format=SubdomainCallingFormat(), path='/', - suppress_consec_slashes=True): - super(GSConnection, self).__init__(gs_access_key_id, gs_secret_access_key, - is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, - host, debug, https_connection_factory, calling_format, path, - "google", Bucket, - suppress_consec_slashes=suppress_consec_slashes) - - def create_bucket(self, bucket_name, headers=None, - location=Location.DEFAULT, policy=None, - storage_class='STANDARD'): - """ - Creates a new bucket. By default it's located in the USA. You can - pass Location.EU to create bucket in the EU. You can also pass - a LocationConstraint for where the bucket should be located, and - a StorageClass describing how the data should be stored. - - :type bucket_name: string - :param bucket_name: The name of the new bucket. - - :type headers: dict - :param headers: Additional headers to pass along with the request to GCS. - - :type location: :class:`boto.gs.connection.Location` - :param location: The location of the new bucket. - - :type policy: :class:`boto.gs.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the new key - in GCS. - - :type storage_class: string - :param storage_class: Either 'STANDARD' or 'DURABLE_REDUCED_AVAILABILITY'. - - """ - check_lowercase_bucketname(bucket_name) - - if policy: - if headers: - headers[self.provider.acl_header] = policy - else: - headers = {self.provider.acl_header : policy} - if not location: - location = Location.DEFAULT - location_elem = ('<LocationConstraint>%s</LocationConstraint>' - % location) - if storage_class: - storage_class_elem = ('<StorageClass>%s</StorageClass>' - % storage_class) - else: - storage_class_elem = '' - data = ('<CreateBucketConfiguration>%s%s</CreateBucketConfiguration>' - % (location_elem, storage_class_elem)) - response = self.make_request( - 'PUT', get_utf8_value(bucket_name), headers=headers, - data=get_utf8_value(data)) - body = response.read() - if response.status == 409: - raise self.provider.storage_create_error( - response.status, response.reason, body) - if response.status == 200: - return self.bucket_class(self, bucket_name) - else: - raise self.provider.storage_response_error( - response.status, response.reason, body) - - def get_bucket(self, bucket_name, validate=True, headers=None): - """ - Retrieves a bucket by name. - - If the bucket does not exist, an ``S3ResponseError`` will be raised. If - you are unsure if the bucket exists or not, you can use the - ``S3Connection.lookup`` method, which will either return a valid bucket - or ``None``. - - :type bucket_name: string - :param bucket_name: The name of the bucket - - :type headers: dict - :param headers: Additional headers to pass along with the request to - AWS. - - :type validate: boolean - :param validate: If ``True``, it will try to fetch all keys within the - given bucket. (Default: ``True``) - """ - bucket = self.bucket_class(self, bucket_name) - if validate: - bucket.get_all_keys(headers, maxkeys=0) - return bucket diff --git a/awx/lib/site-packages/boto/gs/cors.py b/awx/lib/site-packages/boto/gs/cors.py deleted file mode 100644 index 1c5cfd0c7b..0000000000 --- a/awx/lib/site-packages/boto/gs/cors.py +++ /dev/null @@ -1,169 +0,0 @@ -# Copyright 2012 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import types -from boto.gs.user import User -from boto.exception import InvalidCorsError -from xml.sax import handler - -# Relevant tags for the CORS XML document. -CORS_CONFIG = 'CorsConfig' -CORS = 'Cors' -ORIGINS = 'Origins' -ORIGIN = 'Origin' -METHODS = 'Methods' -METHOD = 'Method' -HEADERS = 'ResponseHeaders' -HEADER = 'ResponseHeader' -MAXAGESEC = 'MaxAgeSec' - -class Cors(handler.ContentHandler): - """Encapsulates the CORS configuration XML document""" - def __init__(self): - # List of CORS elements found within a CorsConfig element. - self.cors = [] - # List of collections (e.g. Methods, ResponseHeaders, Origins) - # found within a CORS element. We use a list of lists here - # instead of a dictionary because the collections need to be - # preserved in the order in which they appear in the input XML - # document (and Python dictionary keys are inherently unordered). - # The elements on this list are two element tuples of the form - # (collection name, [list of collection contents]). - self.collections = [] - # Lists of elements within a collection. Again a list is needed to - # preserve ordering but also because the same element may appear - # multiple times within a collection. - self.elements = [] - # Dictionary mapping supported collection names to element types - # which may be contained within each. - self.legal_collections = { - ORIGINS : [ORIGIN], - METHODS : [METHOD], - HEADERS : [HEADER], - MAXAGESEC: [] - } - # List of supported element types within any collection, used for - # checking validadity of a parsed element name. - self.legal_elements = [ORIGIN, METHOD, HEADER] - - self.parse_level = 0 - self.collection = None - self.element = None - - def validateParseLevel(self, tag, level): - """Verify parse level for a given tag.""" - if self.parse_level != level: - raise InvalidCorsError('Invalid tag %s at parse level %d: ' % - (tag, self.parse_level)) - - def startElement(self, name, attrs, connection): - """SAX XML logic for parsing new element found.""" - if name == CORS_CONFIG: - self.validateParseLevel(name, 0) - self.parse_level += 1; - elif name == CORS: - self.validateParseLevel(name, 1) - self.parse_level += 1; - elif name in self.legal_collections: - self.validateParseLevel(name, 2) - self.parse_level += 1; - self.collection = name - elif name in self.legal_elements: - self.validateParseLevel(name, 3) - # Make sure this tag is found inside a collection tag. - if self.collection is None: - raise InvalidCorsError('Tag %s found outside collection' % name) - # Make sure this tag is allowed for the current collection tag. - if name not in self.legal_collections[self.collection]: - raise InvalidCorsError('Tag %s not allowed in %s collection' % - (name, self.collection)) - self.element = name - else: - raise InvalidCorsError('Unsupported tag ' + name) - - def endElement(self, name, value, connection): - """SAX XML logic for parsing new element found.""" - if name == CORS_CONFIG: - self.validateParseLevel(name, 1) - self.parse_level -= 1; - elif name == CORS: - self.validateParseLevel(name, 2) - self.parse_level -= 1; - # Terminating a CORS element, save any collections we found - # and re-initialize collections list. - self.cors.append(self.collections) - self.collections = [] - elif name in self.legal_collections: - self.validateParseLevel(name, 3) - if name != self.collection: - raise InvalidCorsError('Mismatched start and end tags (%s/%s)' % - (self.collection, name)) - self.parse_level -= 1; - if not self.legal_collections[name]: - # If this collection doesn't contain any sub-elements, store - # a tuple of name and this tag's element value. - self.collections.append((name, value.strip())) - else: - # Otherwise, we're terminating a collection of sub-elements, - # so store a tuple of name and list of contained elements. - self.collections.append((name, self.elements)) - self.elements = [] - self.collection = None - elif name in self.legal_elements: - self.validateParseLevel(name, 3) - # Make sure this tag is found inside a collection tag. - if self.collection is None: - raise InvalidCorsError('Tag %s found outside collection' % name) - # Make sure this end tag is allowed for the current collection tag. - if name not in self.legal_collections[self.collection]: - raise InvalidCorsError('Tag %s not allowed in %s collection' % - (name, self.collection)) - if name != self.element: - raise InvalidCorsError('Mismatched start and end tags (%s/%s)' % - (self.element, name)) - # Terminating an element tag, add it to the list of elements - # for the current collection. - self.elements.append((name, value.strip())) - self.element = None - else: - raise InvalidCorsError('Unsupported end tag ' + name) - - def to_xml(self): - """Convert CORS object into XML string representation.""" - s = '<' + CORS_CONFIG + '>' - for collections in self.cors: - s += '<' + CORS + '>' - for (collection, elements_or_value) in collections: - assert collection is not None - s += '<' + collection + '>' - # If collection elements has type string, append atomic value, - # otherwise, append sequence of values in named tags. - if isinstance(elements_or_value, str): - s += elements_or_value - else: - for (name, value) in elements_or_value: - assert name is not None - assert value is not None - s += '<' + name + '>' + value + '</' + name + '>' - s += '</' + collection + '>' - s += '</' + CORS + '>' - s += '</' + CORS_CONFIG + '>' - return s diff --git a/awx/lib/site-packages/boto/gs/key.py b/awx/lib/site-packages/boto/gs/key.py deleted file mode 100644 index c4fcf01f09..0000000000 --- a/awx/lib/site-packages/boto/gs/key.py +++ /dev/null @@ -1,946 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import base64 -import binascii -import os -import re - -from boto.compat import StringIO -from boto.exception import BotoClientError -from boto.s3.key import Key as S3Key -from boto.s3.keyfile import KeyFile -from boto.utils import compute_hash -from boto.utils import get_utf8_value - -class Key(S3Key): - """ - Represents a key (object) in a GS bucket. - - :ivar bucket: The parent :class:`boto.gs.bucket.Bucket`. - :ivar name: The name of this Key object. - :ivar metadata: A dictionary containing user metadata that you - wish to store with the object or that has been retrieved from - an existing object. - :ivar cache_control: The value of the `Cache-Control` HTTP header. - :ivar content_type: The value of the `Content-Type` HTTP header. - :ivar content_encoding: The value of the `Content-Encoding` HTTP header. - :ivar content_disposition: The value of the `Content-Disposition` HTTP - header. - :ivar content_language: The value of the `Content-Language` HTTP header. - :ivar etag: The `etag` associated with this object. - :ivar last_modified: The string timestamp representing the last - time this object was modified in GS. - :ivar owner: The ID of the owner of this object. - :ivar storage_class: The storage class of the object. Currently, one of: - STANDARD | DURABLE_REDUCED_AVAILABILITY. - :ivar md5: The MD5 hash of the contents of the object. - :ivar size: The size, in bytes, of the object. - :ivar generation: The generation number of the object. - :ivar metageneration: The generation number of the object metadata. - :ivar encrypted: Whether the object is encrypted while at rest on - the server. - :ivar cloud_hashes: Dictionary of checksums as supplied by the storage - provider. - """ - - def __init__(self, bucket=None, name=None, generation=None): - super(Key, self).__init__(bucket=bucket, name=name) - self.generation = generation - self.meta_generation = None - self.cloud_hashes = {} - self.component_count = None - - def __repr__(self): - if self.generation and self.metageneration: - ver_str = '#%s.%s' % (self.generation, self.metageneration) - else: - ver_str = '' - if self.bucket: - return '<Key: %s,%s%s>' % (self.bucket.name, self.name, ver_str) - else: - return '<Key: None,%s%s>' % (self.name, ver_str) - - def endElement(self, name, value, connection): - if name == 'Key': - self.name = value - elif name == 'ETag': - self.etag = value - elif name == 'IsLatest': - if value == 'true': - self.is_latest = True - else: - self.is_latest = False - elif name == 'LastModified': - self.last_modified = value - elif name == 'Size': - self.size = int(value) - elif name == 'StorageClass': - self.storage_class = value - elif name == 'Owner': - pass - elif name == 'VersionId': - self.version_id = value - elif name == 'Generation': - self.generation = value - elif name == 'MetaGeneration': - self.metageneration = value - else: - setattr(self, name, value) - - def handle_version_headers(self, resp, force=False): - self.metageneration = resp.getheader('x-goog-metageneration', None) - self.generation = resp.getheader('x-goog-generation', None) - - def handle_restore_headers(self, response): - return - - def handle_addl_headers(self, headers): - for key, value in headers: - if key == 'x-goog-hash': - for hash_pair in value.split(','): - alg, b64_digest = hash_pair.strip().split('=', 1) - self.cloud_hashes[alg] = binascii.a2b_base64(b64_digest) - elif key == 'x-goog-component-count': - self.component_count = int(value) - elif key == 'x-goog-generation': - self.generation = value - # Use x-goog-stored-content-encoding and - # x-goog-stored-content-length to indicate original content length - # and encoding, which are transcoding-invariant (so are preferable - # over using content-encoding and size headers). - elif key == 'x-goog-stored-content-encoding': - self.content_encoding = value - elif key == 'x-goog-stored-content-length': - self.size = int(value) - - def open_read(self, headers=None, query_args='', - override_num_retries=None, response_headers=None): - """ - Open this key for reading - - :type headers: dict - :param headers: Headers to pass in the web request - - :type query_args: string - :param query_args: Arguments to pass in the query string - (ie, 'torrent') - - :type override_num_retries: int - :param override_num_retries: If not None will override configured - num_retries parameter for underlying GET. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - """ - # For GCS we need to include the object generation in the query args. - # The rest of the processing is handled in the parent class. - if self.generation: - if query_args: - query_args += '&' - query_args += 'generation=%s' % self.generation - super(Key, self).open_read(headers=headers, query_args=query_args, - override_num_retries=override_num_retries, - response_headers=response_headers) - - def get_file(self, fp, headers=None, cb=None, num_cb=10, - torrent=False, version_id=None, override_num_retries=None, - response_headers=None, hash_algs=None): - query_args = None - if self.generation: - query_args = ['generation=%s' % self.generation] - self._get_file_internal(fp, headers=headers, cb=cb, num_cb=num_cb, - override_num_retries=override_num_retries, - response_headers=response_headers, - hash_algs=hash_algs, - query_args=query_args) - - def get_contents_to_file(self, fp, headers=None, - cb=None, num_cb=10, - torrent=False, - version_id=None, - res_download_handler=None, - response_headers=None, - hash_algs=None): - """ - Retrieve an object from GCS using the name of the Key object as the - key in GCS. Write the contents of the object to the file pointed - to by 'fp'. - - :type fp: File -like object - :param fp: - - :type headers: dict - :param headers: additional HTTP headers that will be sent with - the GET request. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to GCS and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type torrent: bool - :param torrent: If True, returns the contents of a torrent - file as a string. - - :type res_upload_handler: ResumableDownloadHandler - :param res_download_handler: If provided, this handler will - perform the download. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/sMkcC for details. - """ - if self.bucket is not None: - if res_download_handler: - res_download_handler.get_file(self, fp, headers, cb, num_cb, - torrent=torrent, - version_id=version_id, - hash_algs=hash_algs) - else: - self.get_file(fp, headers, cb, num_cb, torrent=torrent, - version_id=version_id, - response_headers=response_headers, - hash_algs=hash_algs) - - def compute_hash(self, fp, algorithm, size=None): - """ - :type fp: file - :param fp: File pointer to the file to hash. The file - pointer will be reset to the same position before the - method returns. - - :type algorithm: zero-argument constructor for hash objects that - implements update() and digest() (e.g. hashlib.md5) - - :type size: int - :param size: (optional) The Maximum number of bytes to read - from the file pointer (fp). This is useful when uploading - a file in multiple parts where the file is being split - in place into different parts. Less bytes may be available. - """ - hex_digest, b64_digest, data_size = compute_hash( - fp, size=size, hash_algorithm=algorithm) - # The internal implementation of compute_hash() needs to return the - # data size, but we don't want to return that value to the external - # caller because it changes the class interface (i.e. it might - # break some code), so we consume the third tuple value here and - # return the remainder of the tuple to the caller, thereby preserving - # the existing interface. - self.size = data_size - return (hex_digest, b64_digest) - - def send_file(self, fp, headers=None, cb=None, num_cb=10, - query_args=None, chunked_transfer=False, size=None, - hash_algs=None): - """ - Upload a file to GCS. - - :type fp: file - :param fp: The file pointer to upload. The file pointer must - point point at the offset from which you wish to upload. - ie. if uploading the full file, it should point at the - start of the file. Normally when a file is opened for - reading, the fp will point at the first byte. See the - bytes parameter below for more info. - - :type headers: dict - :param headers: The headers to pass along with the PUT request - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file - transfer. Providing a negative integer will cause your - callback to be called with each buffer read. - - :type query_args: string - :param query_args: Arguments to pass in the query string. - - :type chunked_transfer: boolean - :param chunked_transfer: (optional) If true, we use chunked - Transfer-Encoding. - - :type size: int - :param size: (optional) The Maximum number of bytes to read - from the file pointer (fp). This is useful when uploading - a file in multiple parts where you are splitting the file - up into different ranges to be uploaded. If not specified, - the default behaviour is to read all bytes from the file - pointer. Less bytes may be available. - - :type hash_algs: dictionary - :param hash_algs: (optional) Dictionary of hash algorithms and - corresponding hashing class that implements update() and digest(). - Defaults to {'md5': hashlib.md5}. - """ - self._send_file_internal(fp, headers=headers, cb=cb, num_cb=num_cb, - query_args=query_args, - chunked_transfer=chunked_transfer, size=size, - hash_algs=hash_algs) - - def delete(self, headers=None): - return self.bucket.delete_key(self.name, version_id=self.version_id, - generation=self.generation, - headers=headers) - - def add_email_grant(self, permission, email_address): - """ - Convenience method that provides a quick way to add an email grant to a - key. This method retrieves the current ACL, creates a new grant based on - the parameters passed in, adds that grant to the ACL and then PUT's the - new ACL back to GS. - - :type permission: string - :param permission: The permission being granted. Should be one of: - READ|FULL_CONTROL - See http://code.google.com/apis/storage/docs/developer-guide.html#authorization - for more details on permissions. - - :type email_address: string - :param email_address: The email address associated with the Google - account to which you are granting the permission. - """ - acl = self.get_acl() - acl.add_email_grant(permission, email_address) - self.set_acl(acl) - - def add_user_grant(self, permission, user_id): - """ - Convenience method that provides a quick way to add a canonical user - grant to a key. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL and - then PUT's the new ACL back to GS. - - :type permission: string - :param permission: The permission being granted. Should be one of: - READ|FULL_CONTROL - See http://code.google.com/apis/storage/docs/developer-guide.html#authorization - for more details on permissions. - - :type user_id: string - :param user_id: The canonical user id associated with the GS account to - which you are granting the permission. - """ - acl = self.get_acl() - acl.add_user_grant(permission, user_id) - self.set_acl(acl) - - def add_group_email_grant(self, permission, email_address, headers=None): - """ - Convenience method that provides a quick way to add an email group - grant to a key. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL and - then PUT's the new ACL back to GS. - - :type permission: string - :param permission: The permission being granted. Should be one of: - READ|FULL_CONTROL - See http://code.google.com/apis/storage/docs/developer-guide.html#authorization - for more details on permissions. - - :type email_address: string - :param email_address: The email address associated with the Google - Group to which you are granting the permission. - """ - acl = self.get_acl(headers=headers) - acl.add_group_email_grant(permission, email_address) - self.set_acl(acl, headers=headers) - - def add_group_grant(self, permission, group_id): - """ - Convenience method that provides a quick way to add a canonical group - grant to a key. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL and - then PUT's the new ACL back to GS. - - :type permission: string - :param permission: The permission being granted. Should be one of: - READ|FULL_CONTROL - See http://code.google.com/apis/storage/docs/developer-guide.html#authorization - for more details on permissions. - - :type group_id: string - :param group_id: The canonical group id associated with the Google - Groups account you are granting the permission to. - """ - acl = self.get_acl() - acl.add_group_grant(permission, group_id) - self.set_acl(acl) - - def set_contents_from_file(self, fp, headers=None, replace=True, - cb=None, num_cb=10, policy=None, md5=None, - res_upload_handler=None, size=None, rewind=False, - if_generation=None): - """ - Store an object in GS using the name of the Key object as the - key in GS and the contents of the file pointed to by 'fp' as the - contents. - - :type fp: file - :param fp: The file whose contents are to be uploaded. - - :type headers: dict - :param headers: (optional) Additional HTTP headers to be sent with the - PUT request. - - :type replace: bool - :param replace: (optional) If this parameter is False, the method will - first check to see if an object exists in the bucket with the same - key. If it does, it won't overwrite it. The default value is True - which will overwrite the object. - - :type cb: function - :param cb: (optional) Callback function that will be called to report - progress on the upload. The callback should accept two integer - parameters, the first representing the number of bytes that have - been successfully transmitted to GS and the second representing the - total number of bytes that need to be transmitted. - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the cb - parameter, this parameter determines the granularity of the callback - by defining the maximum number of times the callback will be called - during the file transfer. - - :type policy: :class:`boto.gs.acl.CannedACLStrings` - :param policy: (optional) A canned ACL policy that will be applied to - the new key in GS. - - :type md5: tuple - :param md5: (optional) A tuple containing the hexdigest version of the - MD5 checksum of the file as the first element and the - Base64-encoded version of the plain checksum as the second element. - This is the same format returned by the compute_md5 method. - - If you need to compute the MD5 for any reason prior to upload, it's - silly to have to do it twice so this param, if present, will be - used as the MD5 values of the file. Otherwise, the checksum will be - computed. - - :type res_upload_handler: :py:class:`boto.gs.resumable_upload_handler.ResumableUploadHandler` - :param res_upload_handler: (optional) If provided, this handler will - perform the upload. - - :type size: int - :param size: (optional) The Maximum number of bytes to read from the - file pointer (fp). This is useful when uploading a file in multiple - parts where you are splitting the file up into different ranges to - be uploaded. If not specified, the default behaviour is to read all - bytes from the file pointer. Less bytes may be available. - - Notes: - - 1. The "size" parameter currently cannot be used when a - resumable upload handler is given but is still useful for - uploading part of a file as implemented by the parent class. - 2. At present Google Cloud Storage does not support multipart - uploads. - - :type rewind: bool - :param rewind: (optional) If True, the file pointer (fp) will be - rewound to the start before any bytes are read from it. The default - behaviour is False which reads from the current position of the - file pointer (fp). - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the - object will only be written to if its current generation number is - this value. If set to the value 0, the object will only be written - if it doesn't already exist. - - :rtype: int - :return: The number of bytes written to the key. - - TODO: At some point we should refactor the Bucket and Key classes, - to move functionality common to all providers into a parent class, - and provider-specific functionality into subclasses (rather than - just overriding/sharing code the way it currently works). - """ - provider = self.bucket.connection.provider - if res_upload_handler and size: - # could use size instead of file_length if provided but... - raise BotoClientError( - '"size" param not supported for resumable uploads.') - headers = headers or {} - if policy: - headers[provider.acl_header] = policy - - if rewind: - # caller requests reading from beginning of fp. - fp.seek(0, os.SEEK_SET) - else: - # The following seek/tell/seek logic is intended - # to detect applications using the older interface to - # set_contents_from_file(), which automatically rewound the - # file each time the Key was reused. This changed with commit - # 14ee2d03f4665fe20d19a85286f78d39d924237e, to support uploads - # split into multiple parts and uploaded in parallel, and at - # the time of that commit this check was added because otherwise - # older programs would get a success status and upload an empty - # object. Unfortuantely, it's very inefficient for fp's implemented - # by KeyFile (used, for example, by gsutil when copying between - # providers). So, we skip the check for the KeyFile case. - # TODO: At some point consider removing this seek/tell/seek - # logic, after enough time has passed that it's unlikely any - # programs remain that assume the older auto-rewind interface. - if not isinstance(fp, KeyFile): - spos = fp.tell() - fp.seek(0, os.SEEK_END) - if fp.tell() == spos: - fp.seek(0, os.SEEK_SET) - if fp.tell() != spos: - # Raise an exception as this is likely a programming - # error whereby there is data before the fp but nothing - # after it. - fp.seek(spos) - raise AttributeError('fp is at EOF. Use rewind option ' - 'or seek() to data start.') - # seek back to the correct position. - fp.seek(spos) - - if hasattr(fp, 'name'): - self.path = fp.name - if self.bucket is not None: - if isinstance(fp, KeyFile): - # Avoid EOF seek for KeyFile case as it's very inefficient. - key = fp.getkey() - size = key.size - fp.tell() - self.size = size - # At present both GCS and S3 use MD5 for the etag for - # non-multipart-uploaded objects. If the etag is 32 hex - # chars use it as an MD5, to avoid having to read the file - # twice while transferring. - if (re.match('^"[a-fA-F0-9]{32}"$', key.etag)): - etag = key.etag.strip('"') - md5 = (etag, base64.b64encode(binascii.unhexlify(etag))) - if size: - self.size = size - else: - # If md5 is provided, still need to size so - # calculate based on bytes to end of content - spos = fp.tell() - fp.seek(0, os.SEEK_END) - self.size = fp.tell() - spos - fp.seek(spos) - size = self.size - - if md5 is None: - md5 = self.compute_md5(fp, size) - self.md5 = md5[0] - self.base64md5 = md5[1] - - if self.name is None: - self.name = self.md5 - - if not replace: - if self.bucket.lookup(self.name): - return - - if if_generation is not None: - headers['x-goog-if-generation-match'] = str(if_generation) - - if res_upload_handler: - res_upload_handler.send_file(self, fp, headers, cb, num_cb) - else: - # Not a resumable transfer so use basic send_file mechanism. - self.send_file(fp, headers, cb, num_cb, size=size) - - def set_contents_from_filename(self, filename, headers=None, replace=True, - cb=None, num_cb=10, policy=None, md5=None, - reduced_redundancy=None, - res_upload_handler=None, - if_generation=None): - """ - Store an object in GS using the name of the Key object as the - key in GS and the contents of the file named by 'filename'. - See set_contents_from_file method for details about the - parameters. - - :type filename: string - :param filename: The name of the file that you want to put onto GS. - - :type headers: dict - :param headers: (optional) Additional headers to pass along with the - request to GS. - - :type replace: bool - :param replace: (optional) If True, replaces the contents of the file - if it already exists. - - :type cb: function - :param cb: (optional) Callback function that will be called to report - progress on the upload. The callback should accept two integer - parameters, the first representing the number of bytes that have - been successfully transmitted to GS and the second representing the - total number of bytes that need to be transmitted. - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the cb - parameter this parameter determines the granularity of the callback - by defining the maximum number of times the callback will be called - during the file transfer. - - :type policy: :py:attribute:`boto.gs.acl.CannedACLStrings` - :param policy: (optional) A canned ACL policy that will be applied to - the new key in GS. - - :type md5: tuple - :param md5: (optional) A tuple containing the hexdigest version of the - MD5 checksum of the file as the first element and the - Base64-encoded version of the plain checksum as the second element. - This is the same format returned by the compute_md5 method. - - If you need to compute the MD5 for any reason prior to upload, it's - silly to have to do it twice so this param, if present, will be - used as the MD5 values of the file. Otherwise, the checksum will be - computed. - - :type res_upload_handler: :py:class:`boto.gs.resumable_upload_handler.ResumableUploadHandler` - :param res_upload_handler: (optional) If provided, this handler will - perform the upload. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the - object will only be written to if its current generation number is - this value. If set to the value 0, the object will only be written - if it doesn't already exist. - """ - # Clear out any previously computed hashes, since we are setting the - # content. - self.local_hashes = {} - - with open(filename, 'rb') as fp: - self.set_contents_from_file(fp, headers, replace, cb, num_cb, - policy, md5, res_upload_handler, - if_generation=if_generation) - - def set_contents_from_string(self, s, headers=None, replace=True, - cb=None, num_cb=10, policy=None, md5=None, - if_generation=None): - """ - Store an object in GCS using the name of the Key object as the - key in GCS and the string 's' as the contents. - See set_contents_from_file method for details about the - parameters. - - :type headers: dict - :param headers: Additional headers to pass along with the - request to AWS. - - :type replace: bool - :param replace: If True, replaces the contents of the file if - it already exists. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept - two integer parameters, the first representing the - number of bytes that have been successfully - transmitted to GCS and the second representing the - size of the to be transmitted object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with - the cb parameter this parameter determines the - granularity of the callback by defining - the maximum number of times the callback will - be called during the file transfer. - - :type policy: :class:`boto.gs.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the - new key in GCS. - - :type md5: A tuple containing the hexdigest version of the MD5 - checksum of the file as the first element and the - Base64-encoded version of the plain checksum as the - second element. This is the same format returned by - the compute_md5 method. - :param md5: If you need to compute the MD5 for any reason prior - to upload, it's silly to have to do it twice so this - param, if present, will be used as the MD5 values - of the file. Otherwise, the checksum will be computed. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the - object will only be written to if its current generation number is - this value. If set to the value 0, the object will only be written - if it doesn't already exist. - """ - - # Clear out any previously computed md5 hashes, since we are setting the content. - self.md5 = None - self.base64md5 = None - - fp = StringIO(get_utf8_value(s)) - r = self.set_contents_from_file(fp, headers, replace, cb, num_cb, - policy, md5, - if_generation=if_generation) - fp.close() - return r - - def set_contents_from_stream(self, *args, **kwargs): - """ - Store an object using the name of the Key object as the key in - cloud and the contents of the data stream pointed to by 'fp' as - the contents. - - The stream object is not seekable and total size is not known. - This has the implication that we can't specify the - Content-Size and Content-MD5 in the header. So for huge - uploads, the delay in calculating MD5 is avoided but with a - penalty of inability to verify the integrity of the uploaded - data. - - :type fp: file - :param fp: the file whose contents are to be uploaded - - :type headers: dict - :param headers: additional HTTP headers to be sent with the - PUT request. - - :type replace: bool - :param replace: If this parameter is False, the method will first check - to see if an object exists in the bucket with the same key. If it - does, it won't overwrite it. The default value is True which will - overwrite the object. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two integer - parameters, the first representing the number of bytes that have - been successfully transmitted to GS and the second representing the - total number of bytes that need to be transmitted. - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter, this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type policy: :class:`boto.gs.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the new key - in GS. - - :type size: int - :param size: (optional) The Maximum number of bytes to read from - the file pointer (fp). This is useful when uploading a - file in multiple parts where you are splitting the file up - into different ranges to be uploaded. If not specified, - the default behaviour is to read all bytes from the file - pointer. Less bytes may be available. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the - object will only be written to if its current generation number is - this value. If set to the value 0, the object will only be written - if it doesn't already exist. - """ - if_generation = kwargs.pop('if_generation', None) - if if_generation is not None: - headers = kwargs.get('headers', {}) - headers['x-goog-if-generation-match'] = str(if_generation) - kwargs['headers'] = headers - super(Key, self).set_contents_from_stream(*args, **kwargs) - - def set_acl(self, acl_or_str, headers=None, generation=None, - if_generation=None, if_metageneration=None): - """Sets the ACL for this object. - - :type acl_or_str: string or :class:`boto.gs.acl.ACL` - :param acl_or_str: A canned ACL string (see - :data:`~.gs.acl.CannedACLStrings`) or an ACL object. - - :type headers: dict - :param headers: Additional headers to set during the request. - - :type generation: int - :param generation: If specified, sets the ACL for a specific generation - of a versioned object. If not specified, the current version is - modified. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the acl - will only be updated if its current generation number is this value. - - :type if_metageneration: int - :param if_metageneration: (optional) If set to a metageneration number, - the acl will only be updated if its current metageneration number is - this value. - """ - if self.bucket is not None: - self.bucket.set_acl(acl_or_str, self.name, headers=headers, - generation=generation, - if_generation=if_generation, - if_metageneration=if_metageneration) - - def get_acl(self, headers=None, generation=None): - """Returns the ACL of this object. - - :param dict headers: Additional headers to set during the request. - - :param int generation: If specified, gets the ACL for a specific - generation of a versioned object. If not specified, the current - version is returned. - - :rtype: :class:`.gs.acl.ACL` - """ - if self.bucket is not None: - return self.bucket.get_acl(self.name, headers=headers, - generation=generation) - - def get_xml_acl(self, headers=None, generation=None): - """Returns the ACL string of this object. - - :param dict headers: Additional headers to set during the request. - - :param int generation: If specified, gets the ACL for a specific - generation of a versioned object. If not specified, the current - version is returned. - - :rtype: str - """ - if self.bucket is not None: - return self.bucket.get_xml_acl(self.name, headers=headers, - generation=generation) - - def set_xml_acl(self, acl_str, headers=None, generation=None, - if_generation=None, if_metageneration=None): - """Sets this objects's ACL to an XML string. - - :type acl_str: string - :param acl_str: A string containing the ACL XML. - - :type headers: dict - :param headers: Additional headers to set during the request. - - :type generation: int - :param generation: If specified, sets the ACL for a specific generation - of a versioned object. If not specified, the current version is - modified. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the acl - will only be updated if its current generation number is this value. - - :type if_metageneration: int - :param if_metageneration: (optional) If set to a metageneration number, - the acl will only be updated if its current metageneration number is - this value. - """ - if self.bucket is not None: - return self.bucket.set_xml_acl(acl_str, self.name, headers=headers, - generation=generation, - if_generation=if_generation, - if_metageneration=if_metageneration) - - def set_canned_acl(self, acl_str, headers=None, generation=None, - if_generation=None, if_metageneration=None): - """Sets this objects's ACL using a predefined (canned) value. - - :type acl_str: string - :param acl_str: A canned ACL string. See - :data:`~.gs.acl.CannedACLStrings`. - - :type headers: dict - :param headers: Additional headers to set during the request. - - :type generation: int - :param generation: If specified, sets the ACL for a specific generation - of a versioned object. If not specified, the current version is - modified. - - :type if_generation: int - :param if_generation: (optional) If set to a generation number, the acl - will only be updated if its current generation number is this value. - - :type if_metageneration: int - :param if_metageneration: (optional) If set to a metageneration number, - the acl will only be updated if its current metageneration number is - this value. - """ - if self.bucket is not None: - return self.bucket.set_canned_acl( - acl_str, - self.name, - headers=headers, - generation=generation, - if_generation=if_generation, - if_metageneration=if_metageneration - ) - - def compose(self, components, content_type=None, headers=None): - """Create a new object from a sequence of existing objects. - - The content of the object representing this Key will be the - concatenation of the given object sequence. For more detail, visit - - https://developers.google.com/storage/docs/composite-objects - - :type components list of Keys - :param components List of gs.Keys representing the component objects - - :type content_type (optional) string - :param content_type Content type for the new composite object. - """ - compose_req = [] - for key in components: - if key.bucket.name != self.bucket.name: - raise BotoClientError( - 'GCS does not support inter-bucket composing') - - generation_tag = '' - if key.generation: - generation_tag = ('<Generation>%s</Generation>' - % str(key.generation)) - compose_req.append('<Component><Name>%s</Name>%s</Component>' % - (key.name, generation_tag)) - compose_req_xml = ('<ComposeRequest>%s</ComposeRequest>' % - ''.join(compose_req)) - headers = headers or {} - if content_type: - headers['Content-Type'] = content_type - resp = self.bucket.connection.make_request( - 'PUT', get_utf8_value(self.bucket.name), get_utf8_value(self.name), - headers=headers, query_args='compose', - data=get_utf8_value(compose_req_xml)) - if resp.status < 200 or resp.status > 299: - raise self.bucket.connection.provider.storage_response_error( - resp.status, resp.reason, resp.read()) - - # Return the generation so that the result URI can be built with this - # for automatic parallel uploads. - return resp.getheader('x-goog-generation') diff --git a/awx/lib/site-packages/boto/gs/lifecycle.py b/awx/lib/site-packages/boto/gs/lifecycle.py deleted file mode 100644 index 65f7d65d4e..0000000000 --- a/awx/lib/site-packages/boto/gs/lifecycle.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright 2013 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.exception import InvalidLifecycleConfigError - -# Relevant tags for the lifecycle configuration XML document. -LIFECYCLE_CONFIG = 'LifecycleConfiguration' -RULE = 'Rule' -ACTION = 'Action' -DELETE = 'Delete' -CONDITION = 'Condition' -AGE = 'Age' -CREATED_BEFORE = 'CreatedBefore' -NUM_NEWER_VERSIONS = 'NumberOfNewerVersions' -IS_LIVE = 'IsLive' - -# List of all action elements. -LEGAL_ACTIONS = [DELETE] -# List of all action parameter elements. -LEGAL_ACTION_PARAMS = [] -# List of all condition elements. -LEGAL_CONDITIONS = [AGE, CREATED_BEFORE, NUM_NEWER_VERSIONS, IS_LIVE] -# Dictionary mapping actions to supported action parameters for each action. -LEGAL_ACTION_ACTION_PARAMS = { - DELETE: [], -} - -class Rule(object): - """ - A lifecycle rule for a bucket. - - :ivar action: Action to be taken. - - :ivar action_params: A dictionary of action specific parameters. Each item - in the dictionary represents the name and value of an action parameter. - - :ivar conditions: A dictionary of conditions that specify when the action - should be taken. Each item in the dictionary represents the name and value - of a condition. - """ - - def __init__(self, action=None, action_params=None, conditions=None): - self.action = action - self.action_params = action_params or {} - self.conditions = conditions or {} - - # Name of the current enclosing tag (used to validate the schema). - self.current_tag = RULE - - def validateStartTag(self, tag, parent): - """Verify parent of the start tag.""" - if self.current_tag != parent: - raise InvalidLifecycleConfigError( - 'Invalid tag %s found inside %s tag' % (tag, self.current_tag)) - - def validateEndTag(self, tag): - """Verify end tag against the start tag.""" - if tag != self.current_tag: - raise InvalidLifecycleConfigError( - 'Mismatched start and end tags (%s/%s)' % - (self.current_tag, tag)) - - def startElement(self, name, attrs, connection): - if name == ACTION: - self.validateStartTag(name, RULE) - elif name in LEGAL_ACTIONS: - self.validateStartTag(name, ACTION) - # Verify there is only one action tag in the rule. - if self.action is not None: - raise InvalidLifecycleConfigError( - 'Only one action tag is allowed in each rule') - self.action = name - elif name in LEGAL_ACTION_PARAMS: - # Make sure this tag is found in an action tag. - if self.current_tag not in LEGAL_ACTIONS: - raise InvalidLifecycleConfigError( - 'Tag %s found outside of action' % name) - # Make sure this tag is allowed for the current action tag. - if name not in LEGAL_ACTION_ACTION_PARAMS[self.action]: - raise InvalidLifecycleConfigError( - 'Tag %s not allowed in action %s' % (name, self.action)) - elif name == CONDITION: - self.validateStartTag(name, RULE) - elif name in LEGAL_CONDITIONS: - self.validateStartTag(name, CONDITION) - # Verify there is no duplicate conditions. - if name in self.conditions: - raise InvalidLifecycleConfigError( - 'Found duplicate conditions %s' % name) - else: - raise InvalidLifecycleConfigError('Unsupported tag ' + name) - self.current_tag = name - - def endElement(self, name, value, connection): - self.validateEndTag(name) - if name == RULE: - # We have to validate the rule after it is fully populated because - # the action and condition elements could be in any order. - self.validate() - elif name == ACTION: - self.current_tag = RULE - elif name in LEGAL_ACTIONS: - self.current_tag = ACTION - elif name in LEGAL_ACTION_PARAMS: - self.current_tag = self.action - # Add the action parameter name and value to the dictionary. - self.action_params[name] = value.strip() - elif name == CONDITION: - self.current_tag = RULE - elif name in LEGAL_CONDITIONS: - self.current_tag = CONDITION - # Add the condition name and value to the dictionary. - self.conditions[name] = value.strip() - else: - raise InvalidLifecycleConfigError('Unsupported end tag ' + name) - - def validate(self): - """Validate the rule.""" - if not self.action: - raise InvalidLifecycleConfigError( - 'No action was specified in the rule') - if not self.conditions: - raise InvalidLifecycleConfigError( - 'No condition was specified for action %s' % self.action) - - def to_xml(self): - """Convert the rule into XML string representation.""" - s = '<' + RULE + '>' - s += '<' + ACTION + '>' - if self.action_params: - s += '<' + self.action + '>' - for param in LEGAL_ACTION_PARAMS: - if param in self.action_params: - s += ('<' + param + '>' + self.action_params[param] + '</' - + param + '>') - s += '</' + self.action + '>' - else: - s += '<' + self.action + '/>' - s += '</' + ACTION + '>' - s += '<' + CONDITION + '>' - for condition in LEGAL_CONDITIONS: - if condition in self.conditions: - s += ('<' + condition + '>' + self.conditions[condition] + '</' - + condition + '>') - s += '</' + CONDITION + '>' - s += '</' + RULE + '>' - return s - -class LifecycleConfig(list): - """ - A container of rules associated with a lifecycle configuration. - """ - - def __init__(self): - # Track if root tag has been seen. - self.has_root_tag = False - - def startElement(self, name, attrs, connection): - if name == LIFECYCLE_CONFIG: - if self.has_root_tag: - raise InvalidLifecycleConfigError( - 'Only one root tag is allowed in the XML') - self.has_root_tag = True - elif name == RULE: - if not self.has_root_tag: - raise InvalidLifecycleConfigError('Invalid root tag ' + name) - rule = Rule() - self.append(rule) - return rule - else: - raise InvalidLifecycleConfigError('Unsupported tag ' + name) - - def endElement(self, name, value, connection): - if name == LIFECYCLE_CONFIG: - pass - else: - raise InvalidLifecycleConfigError('Unsupported end tag ' + name) - - def to_xml(self): - """Convert LifecycleConfig object into XML string representation.""" - s = '<?xml version="1.0" encoding="UTF-8"?>' - s += '<' + LIFECYCLE_CONFIG + '>' - for rule in self: - s += rule.to_xml() - s += '</' + LIFECYCLE_CONFIG + '>' - return s - - def add_rule(self, action, action_params, conditions): - """ - Add a rule to this Lifecycle configuration. This only adds the rule to - the local copy. To install the new rule(s) on the bucket, you need to - pass this Lifecycle config object to the configure_lifecycle method of - the Bucket object. - - :type action: str - :param action: Action to be taken. - - :type action_params: dict - :param action_params: A dictionary of action specific parameters. Each - item in the dictionary represents the name and value of an action - parameter. - - :type conditions: dict - :param conditions: A dictionary of conditions that specify when the - action should be taken. Each item in the dictionary represents the name - and value of a condition. - """ - rule = Rule(action, action_params, conditions) - self.append(rule) diff --git a/awx/lib/site-packages/boto/gs/resumable_upload_handler.py b/awx/lib/site-packages/boto/gs/resumable_upload_handler.py deleted file mode 100644 index d74434693d..0000000000 --- a/awx/lib/site-packages/boto/gs/resumable_upload_handler.py +++ /dev/null @@ -1,679 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import errno -import httplib -import os -import random -import re -import socket -import time -import urlparse -from hashlib import md5 -from boto import config, UserAgent -from boto.connection import AWSAuthConnection -from boto.exception import InvalidUriError -from boto.exception import ResumableTransferDisposition -from boto.exception import ResumableUploadException -from boto.s3.keyfile import KeyFile - -""" -Handler for Google Cloud Storage resumable uploads. See -http://code.google.com/apis/storage/docs/developer-guide.html#resumable -for details. - -Resumable uploads will retry failed uploads, resuming at the byte -count completed by the last upload attempt. If too many retries happen with -no progress (per configurable num_retries param), the upload will be -aborted in the current process. - -The caller can optionally specify a tracker_file_name param in the -ResumableUploadHandler constructor. If you do this, that file will -save the state needed to allow retrying later, in a separate process -(e.g., in a later run of gsutil). -""" - - -class ResumableUploadHandler(object): - - BUFFER_SIZE = 8192 - RETRYABLE_EXCEPTIONS = (httplib.HTTPException, IOError, socket.error, - socket.gaierror) - - # (start, end) response indicating server has nothing (upload protocol uses - # inclusive numbering). - SERVER_HAS_NOTHING = (0, -1) - - def __init__(self, tracker_file_name=None, num_retries=None): - """ - Constructor. Instantiate once for each uploaded file. - - :type tracker_file_name: string - :param tracker_file_name: optional file name to save tracker URI. - If supplied and the current process fails the upload, it can be - retried in a new process. If called with an existing file containing - a valid tracker URI, we'll resume the upload from this URI; else - we'll start a new resumable upload (and write the URI to this - tracker file). - - :type num_retries: int - :param num_retries: the number of times we'll re-try a resumable upload - making no progress. (Count resets every time we get progress, so - upload can span many more than this number of retries.) - """ - self.tracker_file_name = tracker_file_name - self.num_retries = num_retries - self.server_has_bytes = 0 # Byte count at last server check. - self.tracker_uri = None - if tracker_file_name: - self._load_tracker_uri_from_file() - # Save upload_start_point in instance state so caller can find how - # much was transferred by this ResumableUploadHandler (across retries). - self.upload_start_point = None - - def _load_tracker_uri_from_file(self): - f = None - try: - f = open(self.tracker_file_name, 'r') - uri = f.readline().strip() - self._set_tracker_uri(uri) - except IOError as e: - # Ignore non-existent file (happens first time an upload - # is attempted on a file), but warn user for other errors. - if e.errno != errno.ENOENT: - # Will restart because self.tracker_uri is None. - print('Couldn\'t read URI tracker file (%s): %s. Restarting ' - 'upload from scratch.' % - (self.tracker_file_name, e.strerror)) - except InvalidUriError as e: - # Warn user, but proceed (will restart because - # self.tracker_uri is None). - print('Invalid tracker URI (%s) found in URI tracker file ' - '(%s). Restarting upload from scratch.' % - (uri, self.tracker_file_name)) - finally: - if f: - f.close() - - def _save_tracker_uri_to_file(self): - """ - Saves URI to tracker file if one was passed to constructor. - """ - if not self.tracker_file_name: - return - f = None - try: - with os.fdopen(os.open(self.tracker_file_name, - os.O_WRONLY | os.O_CREAT, 0o600), 'w') as f: - f.write(self.tracker_uri) - except IOError as e: - raise ResumableUploadException( - 'Couldn\'t write URI tracker file (%s): %s.\nThis can happen' - 'if you\'re using an incorrectly configured upload tool\n' - '(e.g., gsutil configured to save tracker files to an ' - 'unwritable directory)' % - (self.tracker_file_name, e.strerror), - ResumableTransferDisposition.ABORT) - - def _set_tracker_uri(self, uri): - """ - Called when we start a new resumable upload or get a new tracker - URI for the upload. Saves URI and resets upload state. - - Raises InvalidUriError if URI is syntactically invalid. - """ - parse_result = urlparse.urlparse(uri) - if (parse_result.scheme.lower() not in ['http', 'https'] or - not parse_result.netloc): - raise InvalidUriError('Invalid tracker URI (%s)' % uri) - self.tracker_uri = uri - self.tracker_uri_host = parse_result.netloc - self.tracker_uri_path = '%s?%s' % ( - parse_result.path, parse_result.query) - self.server_has_bytes = 0 - - def get_tracker_uri(self): - """ - Returns upload tracker URI, or None if the upload has not yet started. - """ - return self.tracker_uri - - def get_upload_id(self): - """ - Returns the upload ID for the resumable upload, or None if the upload - has not yet started. - """ - # We extract the upload_id from the tracker uri. We could retrieve the - # upload_id from the headers in the response but this only works for - # the case where we get the tracker uri from the service. In the case - # where we get the tracker from the tracking file we need to do this - # logic anyway. - delim = '?upload_id=' - if self.tracker_uri and delim in self.tracker_uri: - return self.tracker_uri[self.tracker_uri.index(delim) + len(delim):] - else: - return None - - def _remove_tracker_file(self): - if (self.tracker_file_name and - os.path.exists(self.tracker_file_name)): - os.unlink(self.tracker_file_name) - - def _build_content_range_header(self, range_spec='*', length_spec='*'): - return 'bytes %s/%s' % (range_spec, length_spec) - - def _query_server_state(self, conn, file_length): - """ - Queries server to find out state of given upload. - - Note that this method really just makes special case use of the - fact that the upload server always returns the current start/end - state whenever a PUT doesn't complete. - - Returns HTTP response from sending request. - - Raises ResumableUploadException if problem querying server. - """ - # Send an empty PUT so that server replies with this resumable - # transfer's state. - put_headers = {} - put_headers['Content-Range'] = ( - self._build_content_range_header('*', file_length)) - put_headers['Content-Length'] = '0' - return AWSAuthConnection.make_request(conn, 'PUT', - path=self.tracker_uri_path, - auth_path=self.tracker_uri_path, - headers=put_headers, - host=self.tracker_uri_host) - - def _query_server_pos(self, conn, file_length): - """ - Queries server to find out what bytes it currently has. - - Returns (server_start, server_end), where the values are inclusive. - For example, (0, 2) would mean that the server has bytes 0, 1, *and* 2. - - Raises ResumableUploadException if problem querying server. - """ - resp = self._query_server_state(conn, file_length) - if resp.status == 200: - # To handle the boundary condition where the server has the complete - # file, we return (server_start, file_length-1). That way the - # calling code can always simply read up through server_end. (If we - # didn't handle this boundary condition here, the caller would have - # to check whether server_end == file_length and read one fewer byte - # in that case.) - return (0, file_length - 1) # Completed upload. - if resp.status != 308: - # This means the server didn't have any state for the given - # upload ID, which can happen (for example) if the caller saved - # the tracker URI to a file and then tried to restart the transfer - # after that upload ID has gone stale. In that case we need to - # start a new transfer (and the caller will then save the new - # tracker URI to the tracker file). - raise ResumableUploadException( - 'Got non-308 response (%s) from server state query' % - resp.status, ResumableTransferDisposition.START_OVER) - got_valid_response = False - range_spec = resp.getheader('range') - if range_spec: - # Parse 'bytes=<from>-<to>' range_spec. - m = re.search('bytes=(\d+)-(\d+)', range_spec) - if m: - server_start = long(m.group(1)) - server_end = long(m.group(2)) - got_valid_response = True - else: - # No Range header, which means the server does not yet have - # any bytes. Note that the Range header uses inclusive 'from' - # and 'to' values. Since Range 0-0 would mean that the server - # has byte 0, omitting the Range header is used to indicate that - # the server doesn't have any bytes. - return self.SERVER_HAS_NOTHING - if not got_valid_response: - raise ResumableUploadException( - 'Couldn\'t parse upload server state query response (%s)' % - str(resp.getheaders()), ResumableTransferDisposition.START_OVER) - if conn.debug >= 1: - print('Server has: Range: %d - %d.' % (server_start, server_end)) - return (server_start, server_end) - - def _start_new_resumable_upload(self, key, headers=None): - """ - Starts a new resumable upload. - - Raises ResumableUploadException if any errors occur. - """ - conn = key.bucket.connection - if conn.debug >= 1: - print('Starting new resumable upload.') - self.server_has_bytes = 0 - - # Start a new resumable upload by sending a POST request with an - # empty body and the "X-Goog-Resumable: start" header. Include any - # caller-provided headers (e.g., Content-Type) EXCEPT Content-Length - # (and raise an exception if they tried to pass one, since it's - # a semantic error to specify it at this point, and if we were to - # include one now it would cause the server to expect that many - # bytes; the POST doesn't include the actual file bytes We set - # the Content-Length in the subsequent PUT, based on the uploaded - # file size. - post_headers = {} - for k in headers: - if k.lower() == 'content-length': - raise ResumableUploadException( - 'Attempt to specify Content-Length header (disallowed)', - ResumableTransferDisposition.ABORT) - post_headers[k] = headers[k] - post_headers[conn.provider.resumable_upload_header] = 'start' - - resp = conn.make_request( - 'POST', key.bucket.name, key.name, post_headers) - # Get tracker URI from response 'Location' header. - body = resp.read() - - # Check for various status conditions. - if resp.status in [500, 503]: - # Retry status 500 and 503 errors after a delay. - raise ResumableUploadException( - 'Got status %d from attempt to start resumable upload. ' - 'Will wait/retry' % resp.status, - ResumableTransferDisposition.WAIT_BEFORE_RETRY) - elif resp.status != 200 and resp.status != 201: - raise ResumableUploadException( - 'Got status %d from attempt to start resumable upload. ' - 'Aborting' % resp.status, - ResumableTransferDisposition.ABORT) - - # Else we got 200 or 201 response code, indicating the resumable - # upload was created. - tracker_uri = resp.getheader('Location') - if not tracker_uri: - raise ResumableUploadException( - 'No resumable tracker URI found in resumable initiation ' - 'POST response (%s)' % body, - ResumableTransferDisposition.WAIT_BEFORE_RETRY) - self._set_tracker_uri(tracker_uri) - self._save_tracker_uri_to_file() - - def _upload_file_bytes(self, conn, http_conn, fp, file_length, - total_bytes_uploaded, cb, num_cb, headers): - """ - Makes one attempt to upload file bytes, using an existing resumable - upload connection. - - Returns (etag, generation, metageneration) from server upon success. - - Raises ResumableUploadException if any problems occur. - """ - buf = fp.read(self.BUFFER_SIZE) - if cb: - # The cb_count represents the number of full buffers to send between - # cb executions. - if num_cb > 2: - cb_count = file_length / self.BUFFER_SIZE / (num_cb-2) - elif num_cb < 0: - cb_count = -1 - else: - cb_count = 0 - i = 0 - cb(total_bytes_uploaded, file_length) - - # Build resumable upload headers for the transfer. Don't send a - # Content-Range header if the file is 0 bytes long, because the - # resumable upload protocol uses an *inclusive* end-range (so, sending - # 'bytes 0-0/1' would actually mean you're sending a 1-byte file). - if not headers: - put_headers = {} - else: - put_headers = headers.copy() - if file_length: - if total_bytes_uploaded == file_length: - range_header = self._build_content_range_header( - '*', file_length) - else: - range_header = self._build_content_range_header( - '%d-%d' % (total_bytes_uploaded, file_length - 1), - file_length) - put_headers['Content-Range'] = range_header - # Set Content-Length to the total bytes we'll send with this PUT. - put_headers['Content-Length'] = str(file_length - total_bytes_uploaded) - http_request = AWSAuthConnection.build_base_http_request( - conn, 'PUT', path=self.tracker_uri_path, auth_path=None, - headers=put_headers, host=self.tracker_uri_host) - http_conn.putrequest('PUT', http_request.path) - for k in put_headers: - http_conn.putheader(k, put_headers[k]) - http_conn.endheaders() - - # Turn off debug on http connection so upload content isn't included - # in debug stream. - http_conn.set_debuglevel(0) - while buf: - http_conn.send(buf) - for alg in self.digesters: - self.digesters[alg].update(buf) - total_bytes_uploaded += len(buf) - if cb: - i += 1 - if i == cb_count or cb_count == -1: - cb(total_bytes_uploaded, file_length) - i = 0 - buf = fp.read(self.BUFFER_SIZE) - http_conn.set_debuglevel(conn.debug) - if cb: - cb(total_bytes_uploaded, file_length) - if total_bytes_uploaded != file_length: - # Abort (and delete the tracker file) so if the user retries - # they'll start a new resumable upload rather than potentially - # attempting to pick back up later where we left off. - raise ResumableUploadException( - 'File changed during upload: EOF at %d bytes of %d byte file.' % - (total_bytes_uploaded, file_length), - ResumableTransferDisposition.ABORT) - resp = http_conn.getresponse() - # Restore http connection debug level. - http_conn.set_debuglevel(conn.debug) - - if resp.status == 200: - # Success. - return (resp.getheader('etag'), - resp.getheader('x-goog-generation'), - resp.getheader('x-goog-metageneration')) - # Retry timeout (408) and status 500 and 503 errors after a delay. - elif resp.status in [408, 500, 503]: - disposition = ResumableTransferDisposition.WAIT_BEFORE_RETRY - else: - # Catch all for any other error codes. - disposition = ResumableTransferDisposition.ABORT - raise ResumableUploadException('Got response code %d while attempting ' - 'upload (%s)' % - (resp.status, resp.reason), disposition) - - def _attempt_resumable_upload(self, key, fp, file_length, headers, cb, - num_cb): - """ - Attempts a resumable upload. - - Returns (etag, generation, metageneration) from server upon success. - - Raises ResumableUploadException if any problems occur. - """ - (server_start, server_end) = self.SERVER_HAS_NOTHING - conn = key.bucket.connection - if self.tracker_uri: - # Try to resume existing resumable upload. - try: - (server_start, server_end) = ( - self._query_server_pos(conn, file_length)) - self.server_has_bytes = server_start - - if server_end: - # If the server already has some of the content, we need to - # update the digesters with the bytes that have already been - # uploaded to ensure we get a complete hash in the end. - print('Catching up hash digest(s) for resumed upload') - fp.seek(0) - # Read local file's bytes through position server has. For - # example, if server has (0, 3) we want to read 3-0+1=4 bytes. - bytes_to_go = server_end + 1 - while bytes_to_go: - chunk = fp.read(min(key.BufferSize, bytes_to_go)) - if not chunk: - raise ResumableUploadException( - 'Hit end of file during resumable upload hash ' - 'catchup. This should not happen under\n' - 'normal circumstances, as it indicates the ' - 'server has more bytes of this transfer\nthan' - ' the current file size. Restarting upload.', - ResumableTransferDisposition.START_OVER) - for alg in self.digesters: - self.digesters[alg].update(chunk) - bytes_to_go -= len(chunk) - - if conn.debug >= 1: - print('Resuming transfer.') - except ResumableUploadException as e: - if conn.debug >= 1: - print('Unable to resume transfer (%s).' % e.message) - self._start_new_resumable_upload(key, headers) - else: - self._start_new_resumable_upload(key, headers) - - # upload_start_point allows the code that instantiated the - # ResumableUploadHandler to find out the point from which it started - # uploading (e.g., so it can correctly compute throughput). - if self.upload_start_point is None: - self.upload_start_point = server_end - - total_bytes_uploaded = server_end + 1 - # Corner case: Don't attempt to seek if we've already uploaded the - # entire file, because if the file is a stream (e.g., the KeyFile - # wrapper around input key when copying between providers), attempting - # to seek to the end of file would result in an InvalidRange error. - if file_length < total_bytes_uploaded: - fp.seek(total_bytes_uploaded) - conn = key.bucket.connection - - # Get a new HTTP connection (vs conn.get_http_connection(), which reuses - # pool connections) because httplib requires a new HTTP connection per - # transaction. (Without this, calling http_conn.getresponse() would get - # "ResponseNotReady".) - http_conn = conn.new_http_connection(self.tracker_uri_host, conn.port, - conn.is_secure) - http_conn.set_debuglevel(conn.debug) - - # Make sure to close http_conn at end so if a local file read - # failure occurs partway through server will terminate current upload - # and can report that progress on next attempt. - try: - return self._upload_file_bytes(conn, http_conn, fp, file_length, - total_bytes_uploaded, cb, num_cb, - headers) - except (ResumableUploadException, socket.error): - resp = self._query_server_state(conn, file_length) - if resp.status == 400: - raise ResumableUploadException('Got 400 response from server ' - 'state query after failed resumable upload attempt. This ' - 'can happen for various reasons, including specifying an ' - 'invalid request (e.g., an invalid canned ACL) or if the ' - 'file size changed between upload attempts', - ResumableTransferDisposition.ABORT) - else: - raise - finally: - http_conn.close() - - def _check_final_md5(self, key, etag): - """ - Checks that etag from server agrees with md5 computed before upload. - This is important, since the upload could have spanned a number of - hours and multiple processes (e.g., gsutil runs), and the user could - change some of the file and not realize they have inconsistent data. - """ - if key.bucket.connection.debug >= 1: - print('Checking md5 against etag.') - if key.md5 != etag.strip('"\''): - # Call key.open_read() before attempting to delete the - # (incorrect-content) key, so we perform that request on a - # different HTTP connection. This is neededb because httplib - # will return a "Response not ready" error if you try to perform - # a second transaction on the connection. - key.open_read() - key.close() - key.delete() - raise ResumableUploadException( - 'File changed during upload: md5 signature doesn\'t match etag ' - '(incorrect uploaded object deleted)', - ResumableTransferDisposition.ABORT) - - def handle_resumable_upload_exception(self, e, debug): - if (e.disposition == ResumableTransferDisposition.ABORT_CUR_PROCESS): - if debug >= 1: - print('Caught non-retryable ResumableUploadException (%s); ' - 'aborting but retaining tracker file' % e.message) - raise - elif (e.disposition == ResumableTransferDisposition.ABORT): - if debug >= 1: - print('Caught non-retryable ResumableUploadException (%s); ' - 'aborting and removing tracker file' % e.message) - self._remove_tracker_file() - raise - else: - if debug >= 1: - print('Caught ResumableUploadException (%s) - will retry' % - e.message) - - def track_progress_less_iterations(self, server_had_bytes_before_attempt, - roll_back_md5=True, debug=0): - # At this point we had a re-tryable failure; see if made progress. - if self.server_has_bytes > server_had_bytes_before_attempt: - self.progress_less_iterations = 0 # If progress, reset counter. - else: - self.progress_less_iterations += 1 - if roll_back_md5: - # Rollback any potential hash updates, as we did not - # make any progress in this iteration. - self.digesters = self.digesters_before_attempt - - if self.progress_less_iterations > self.num_retries: - # Don't retry any longer in the current process. - raise ResumableUploadException( - 'Too many resumable upload attempts failed without ' - 'progress. You might try this upload again later', - ResumableTransferDisposition.ABORT_CUR_PROCESS) - - # Use binary exponential backoff to desynchronize client requests. - sleep_time_secs = random.random() * (2**self.progress_less_iterations) - if debug >= 1: - print('Got retryable failure (%d progress-less in a row).\n' - 'Sleeping %3.1f seconds before re-trying' % - (self.progress_less_iterations, sleep_time_secs)) - time.sleep(sleep_time_secs) - - def send_file(self, key, fp, headers, cb=None, num_cb=10, hash_algs=None): - """ - Upload a file to a key into a bucket on GS, using GS resumable upload - protocol. - - :type key: :class:`boto.s3.key.Key` or subclass - :param key: The Key object to which data is to be uploaded - - :type fp: file-like object - :param fp: The file pointer to upload - - :type headers: dict - :param headers: The headers to pass along with the PUT request - - :type cb: function - :param cb: a callback function that will be called to report progress on - the upload. The callback should accept two integer parameters, the - first representing the number of bytes that have been successfully - transmitted to GS, and the second representing the total number of - bytes that need to be transmitted. - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the cb - parameter, this parameter determines the granularity of the callback - by defining the maximum number of times the callback will be called - during the file transfer. Providing a negative integer will cause - your callback to be called with each buffer read. - - :type hash_algs: dictionary - :param hash_algs: (optional) Dictionary mapping hash algorithm - descriptions to corresponding state-ful hashing objects that - implement update(), digest(), and copy() (e.g. hashlib.md5()). - Defaults to {'md5': md5()}. - - Raises ResumableUploadException if a problem occurs during the transfer. - """ - - if not headers: - headers = {} - # If Content-Type header is present and set to None, remove it. - # This is gsutil's way of asking boto to refrain from auto-generating - # that header. - CT = 'Content-Type' - if CT in headers and headers[CT] is None: - del headers[CT] - - headers['User-Agent'] = UserAgent - - # Determine file size different ways for case where fp is actually a - # wrapper around a Key vs an actual file. - if isinstance(fp, KeyFile): - file_length = fp.getkey().size - else: - fp.seek(0, os.SEEK_END) - file_length = fp.tell() - fp.seek(0) - debug = key.bucket.connection.debug - - # Compute the MD5 checksum on the fly. - if hash_algs is None: - hash_algs = {'md5': md5} - self.digesters = dict( - (alg, hash_algs[alg]()) for alg in hash_algs or {}) - - # Use num-retries from constructor if one was provided; else check - # for a value specified in the boto config file; else default to 5. - if self.num_retries is None: - self.num_retries = config.getint('Boto', 'num_retries', 6) - self.progress_less_iterations = 0 - - while True: # Retry as long as we're making progress. - server_had_bytes_before_attempt = self.server_has_bytes - self.digesters_before_attempt = dict( - (alg, self.digesters[alg].copy()) - for alg in self.digesters) - try: - # Save generation and metageneration in class state so caller - # can find these values, for use in preconditions of future - # operations on the uploaded object. - (etag, self.generation, self.metageneration) = ( - self._attempt_resumable_upload(key, fp, file_length, - headers, cb, num_cb)) - - # Get the final digests for the uploaded content. - for alg in self.digesters: - key.local_hashes[alg] = self.digesters[alg].digest() - - # Upload succceded, so remove the tracker file (if have one). - self._remove_tracker_file() - self._check_final_md5(key, etag) - key.generation = self.generation - if debug >= 1: - print('Resumable upload complete.') - return - except self.RETRYABLE_EXCEPTIONS as e: - if debug >= 1: - print('Caught exception (%s)' % e.__repr__()) - if isinstance(e, IOError) and e.errno == errno.EPIPE: - # Broken pipe error causes httplib to immediately - # close the socket (http://bugs.python.org/issue5542), - # so we need to close the connection before we resume - # the upload (which will cause a new connection to be - # opened the next time an HTTP request is sent). - key.bucket.connection.connection.close() - except ResumableUploadException as e: - self.handle_resumable_upload_exception(e, debug) - - self.track_progress_less_iterations(server_had_bytes_before_attempt, - True, debug) diff --git a/awx/lib/site-packages/boto/gs/user.py b/awx/lib/site-packages/boto/gs/user.py deleted file mode 100644 index c3072952f9..0000000000 --- a/awx/lib/site-packages/boto/gs/user.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class User(object): - def __init__(self, parent=None, id='', name=''): - if parent: - parent.owner = self - self.type = None - self.id = id - self.name = name - - def __repr__(self): - return self.id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Name': - self.name = value - elif name == 'ID': - self.id = value - else: - setattr(self, name, value) - - def to_xml(self, element_name='Owner'): - if self.type: - s = '<%s type="%s">' % (element_name, self.type) - else: - s = '<%s>' % element_name - s += '<ID>%s</ID>' % self.id - if self.name: - s += '<Name>%s</Name>' % self.name - s += '</%s>' % element_name - return s diff --git a/awx/lib/site-packages/boto/handler.py b/awx/lib/site-packages/boto/handler.py deleted file mode 100644 index 3b5f073275..0000000000 --- a/awx/lib/site-packages/boto/handler.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import xml.sax - -from boto.compat import StringIO - - -class XmlHandler(xml.sax.ContentHandler): - - def __init__(self, root_node, connection): - self.connection = connection - self.nodes = [('root', root_node)] - self.current_text = '' - - def startElement(self, name, attrs): - self.current_text = '' - new_node = self.nodes[-1][1].startElement(name, attrs, self.connection) - if new_node is not None: - self.nodes.append((name, new_node)) - - def endElement(self, name): - self.nodes[-1][1].endElement(name, self.current_text, self.connection) - if self.nodes[-1][0] == name: - if hasattr(self.nodes[-1][1], 'endNode'): - self.nodes[-1][1].endNode(self.connection) - self.nodes.pop() - self.current_text = '' - - def characters(self, content): - self.current_text += content - - -class XmlHandlerWrapper(object): - def __init__(self, root_node, connection): - self.handler = XmlHandler(root_node, connection) - self.parser = xml.sax.make_parser() - self.parser.setContentHandler(self.handler) - self.parser.setFeature(xml.sax.handler.feature_external_ges, 0) - - def parseString(self, content): - return self.parser.parse(StringIO(content)) diff --git a/awx/lib/site-packages/boto/https_connection.py b/awx/lib/site-packages/boto/https_connection.py deleted file mode 100644 index ddc31a1522..0000000000 --- a/awx/lib/site-packages/boto/https_connection.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright 2007,2011 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This file is derived from -# http://googleappengine.googlecode.com/svn-history/r136/trunk/python/google/appengine/tools/https_wrapper.py - - -"""Extensions to allow HTTPS requests with SSL certificate validation.""" - -import re -import socket -import ssl - -import boto - -from boto.compat import six, http_client - - -class InvalidCertificateException(http_client.HTTPException): - """Raised when a certificate is provided with an invalid hostname.""" - - def __init__(self, host, cert, reason): - """Constructor. - - Args: - host: The hostname the connection was made to. - cert: The SSL certificate (as a dictionary) the host returned. - """ - http_client.HTTPException.__init__(self) - self.host = host - self.cert = cert - self.reason = reason - - def __str__(self): - return ('Host %s returned an invalid certificate (%s): %s' % - (self.host, self.reason, self.cert)) - - -def GetValidHostsForCert(cert): - """Returns a list of valid host globs for an SSL certificate. - - Args: - cert: A dictionary representing an SSL certificate. - Returns: - list: A list of valid host globs. - """ - if 'subjectAltName' in cert: - return [x[1] for x in cert['subjectAltName'] if x[0].lower() == 'dns'] - else: - return [x[0][1] for x in cert['subject'] - if x[0][0].lower() == 'commonname'] - - -def ValidateCertificateHostname(cert, hostname): - """Validates that a given hostname is valid for an SSL certificate. - - Args: - cert: A dictionary representing an SSL certificate. - hostname: The hostname to test. - Returns: - bool: Whether or not the hostname is valid for this certificate. - """ - hosts = GetValidHostsForCert(cert) - boto.log.debug( - "validating server certificate: hostname=%s, certificate hosts=%s", - hostname, hosts) - for host in hosts: - host_re = host.replace('.', '\.').replace('*', '[^.]*') - if re.search('^%s$' % (host_re,), hostname, re.I): - return True - return False - - -class CertValidatingHTTPSConnection(http_client.HTTPConnection): - """An HTTPConnection that connects over SSL and validates certificates.""" - - default_port = http_client.HTTPS_PORT - - def __init__(self, host, port=default_port, key_file=None, cert_file=None, - ca_certs=None, strict=None, **kwargs): - """Constructor. - - Args: - host: The hostname. Can be in 'host:port' form. - port: The port. Defaults to 443. - key_file: A file containing the client's private key - cert_file: A file containing the client's certificates - ca_certs: A file contianing a set of concatenated certificate authority - certs for validating the server against. - strict: When true, causes BadStatusLine to be raised if the status line - can't be parsed as a valid HTTP/1.0 or 1.1 status line. - """ - if six.PY2: - # Python 3.2 and newer have deprecated and removed the strict - # parameter. Since the params are supported as keyword arguments - # we conditionally add it here. - kwargs['strict'] = strict - - http_client.HTTPConnection.__init__(self, host=host, port=port, **kwargs) - self.key_file = key_file - self.cert_file = cert_file - self.ca_certs = ca_certs - - def connect(self): - "Connect to a host on a given (SSL) port." - if hasattr(self, "timeout"): - sock = socket.create_connection((self.host, self.port), self.timeout) - else: - sock = socket.create_connection((self.host, self.port)) - msg = "wrapping ssl socket; " - if self.ca_certs: - msg += "CA certificate file=%s" % self.ca_certs - else: - msg += "using system provided SSL certs" - boto.log.debug(msg) - self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, - certfile=self.cert_file, - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=self.ca_certs) - cert = self.sock.getpeercert() - hostname = self.host.split(':', 0)[0] - if not ValidateCertificateHostname(cert, hostname): - raise InvalidCertificateException(hostname, - cert, - 'remote hostname "%s" does not match ' - 'certificate' % hostname) diff --git a/awx/lib/site-packages/boto/iam/__init__.py b/awx/lib/site-packages/boto/iam/__init__.py deleted file mode 100644 index 3df44f2953..0000000000 --- a/awx/lib/site-packages/boto/iam/__init__.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2010-2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010-2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# this is here for backward compatibility -# originally, the IAMConnection class was defined here -from boto.iam.connection import IAMConnection -from boto.regioninfo import RegionInfo, get_regions - - -class IAMRegionInfo(RegionInfo): - - def connect(self, **kw_params): - """ - Connect to this Region's endpoint. Returns an connection - object pointing to the endpoint associated with this region. - You may pass any of the arguments accepted by the connection - class's constructor as keyword arguments and they will be - passed along to the connection object. - - :rtype: Connection object - :return: The connection to this regions endpoint - """ - if self.connection_cls: - return self.connection_cls(host=self.endpoint, **kw_params) - - -def regions(): - """ - Get all available regions for the IAM service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` instances - """ - regions = get_regions( - 'iam', - region_cls=IAMRegionInfo, - connection_cls=IAMConnection - ) - - # For historical reasons, we had a "universal" endpoint as well. - regions.append( - IAMRegionInfo( - name='universal', - endpoint='iam.amazonaws.com', - connection_cls=IAMConnection - ) - ) - - return regions - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.iam.connection.IAMConnection`. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.iam.connection.IAMConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/iam/connection.py b/awx/lib/site-packages/boto/iam/connection.py deleted file mode 100644 index 8590971dac..0000000000 --- a/awx/lib/site-packages/boto/iam/connection.py +++ /dev/null @@ -1,1546 +0,0 @@ -# Copyright (c) 2010-2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010-2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import boto -import boto.jsonresponse -from boto.compat import json, six -from boto.resultset import ResultSet -from boto.iam.summarymap import SummaryMap -from boto.connection import AWSQueryConnection - -DEFAULT_POLICY_DOCUMENTS = { - 'default': { - 'Statement': [ - { - 'Principal': { - 'Service': ['ec2.amazonaws.com'] - }, - 'Effect': 'Allow', - 'Action': ['sts:AssumeRole'] - } - ] - }, - 'amazonaws.com.cn': { - 'Statement': [ - { - 'Principal': { - 'Service': ['ec2.amazonaws.com.cn'] - }, - 'Effect': 'Allow', - 'Action': ['sts:AssumeRole'] - } - ] - }, -} -# For backward-compatibility, we'll preserve this here. -ASSUME_ROLE_POLICY_DOCUMENT = json.dumps(DEFAULT_POLICY_DOCUMENTS['default']) - - -class IAMConnection(AWSQueryConnection): - - APIVersion = '2010-05-08' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, host='iam.amazonaws.com', - debug=0, https_connection_factory=None, path='/', - security_token=None, validate_certs=True, profile_name=None): - super(IAMConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, - proxy_port, proxy_user, proxy_pass, - host, debug, https_connection_factory, - path, security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - def get_response(self, action, params, path='/', parent=None, - verb='POST', list_marker='Set'): - """ - Utility method to handle calls to IAM and parsing of responses. - """ - if not parent: - parent = self - response = self.make_request(action, params, path, verb) - body = response.read() - boto.log.debug(body) - if response.status == 200: - if body: - e = boto.jsonresponse.Element(list_marker=list_marker, - pythonize_name=True) - h = boto.jsonresponse.XmlHandler(e, parent) - h.parse(body) - return e - else: - # Support empty responses, e.g. deleting a SAML provider - # according to the official documentation. - return {} - else: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise self.ResponseError(response.status, response.reason, body) - - # - # Group methods - # - - def get_all_groups(self, path_prefix='/', marker=None, max_items=None): - """ - List the groups that have the specified path prefix. - - :type path_prefix: string - :param path_prefix: If provided, only groups whose paths match - the provided prefix will be returned. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - """ - params = {} - if path_prefix: - params['PathPrefix'] = path_prefix - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListGroups', params, - list_marker='Groups') - - def get_group(self, group_name, marker=None, max_items=None): - """ - Return a list of users that are in the specified group. - - :type group_name: string - :param group_name: The name of the group whose information should - be returned. - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - """ - params = {'GroupName': group_name} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('GetGroup', params, list_marker='Users') - - def create_group(self, group_name, path='/'): - """ - Create a group. - - :type group_name: string - :param group_name: The name of the new group - - :type path: string - :param path: The path to the group (Optional). Defaults to /. - - """ - params = {'GroupName': group_name, - 'Path': path} - return self.get_response('CreateGroup', params) - - def delete_group(self, group_name): - """ - Delete a group. The group must not contain any Users or - have any attached policies - - :type group_name: string - :param group_name: The name of the group to delete. - - """ - params = {'GroupName': group_name} - return self.get_response('DeleteGroup', params) - - def update_group(self, group_name, new_group_name=None, new_path=None): - """ - Updates name and/or path of the specified group. - - :type group_name: string - :param group_name: The name of the new group - - :type new_group_name: string - :param new_group_name: If provided, the name of the group will be - changed to this name. - - :type new_path: string - :param new_path: If provided, the path of the group will be - changed to this path. - - """ - params = {'GroupName': group_name} - if new_group_name: - params['NewGroupName'] = new_group_name - if new_path: - params['NewPath'] = new_path - return self.get_response('UpdateGroup', params) - - def add_user_to_group(self, group_name, user_name): - """ - Add a user to a group - - :type group_name: string - :param group_name: The name of the group - - :type user_name: string - :param user_name: The to be added to the group. - - """ - params = {'GroupName': group_name, - 'UserName': user_name} - return self.get_response('AddUserToGroup', params) - - def remove_user_from_group(self, group_name, user_name): - """ - Remove a user from a group. - - :type group_name: string - :param group_name: The name of the group - - :type user_name: string - :param user_name: The user to remove from the group. - - """ - params = {'GroupName': group_name, - 'UserName': user_name} - return self.get_response('RemoveUserFromGroup', params) - - def put_group_policy(self, group_name, policy_name, policy_json): - """ - Adds or updates the specified policy document for the specified group. - - :type group_name: string - :param group_name: The name of the group the policy is associated with. - - :type policy_name: string - :param policy_name: The policy document to get. - - :type policy_json: string - :param policy_json: The policy document. - - """ - params = {'GroupName': group_name, - 'PolicyName': policy_name, - 'PolicyDocument': policy_json} - return self.get_response('PutGroupPolicy', params, verb='POST') - - def get_all_group_policies(self, group_name, marker=None, max_items=None): - """ - List the names of the policies associated with the specified group. - - :type group_name: string - :param group_name: The name of the group the policy is associated with. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - """ - params = {'GroupName': group_name} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListGroupPolicies', params, - list_marker='PolicyNames') - - def get_group_policy(self, group_name, policy_name): - """ - Retrieves the specified policy document for the specified group. - - :type group_name: string - :param group_name: The name of the group the policy is associated with. - - :type policy_name: string - :param policy_name: The policy document to get. - - """ - params = {'GroupName': group_name, - 'PolicyName': policy_name} - return self.get_response('GetGroupPolicy', params, verb='POST') - - def delete_group_policy(self, group_name, policy_name): - """ - Deletes the specified policy document for the specified group. - - :type group_name: string - :param group_name: The name of the group the policy is associated with. - - :type policy_name: string - :param policy_name: The policy document to delete. - - """ - params = {'GroupName': group_name, - 'PolicyName': policy_name} - return self.get_response('DeleteGroupPolicy', params, verb='POST') - - def get_all_users(self, path_prefix='/', marker=None, max_items=None): - """ - List the users that have the specified path prefix. - - :type path_prefix: string - :param path_prefix: If provided, only users whose paths match - the provided prefix will be returned. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - """ - params = {'PathPrefix': path_prefix} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListUsers', params, list_marker='Users') - - # - # User methods - # - - def create_user(self, user_name, path='/'): - """ - Create a user. - - :type user_name: string - :param user_name: The name of the new user - - :type path: string - :param path: The path in which the user will be created. - Defaults to /. - - """ - params = {'UserName': user_name, - 'Path': path} - return self.get_response('CreateUser', params) - - def delete_user(self, user_name): - """ - Delete a user including the user's path, GUID and ARN. - - If the user_name is not specified, the user_name is determined - implicitly based on the AWS Access Key ID used to sign the request. - - :type user_name: string - :param user_name: The name of the user to delete. - - """ - params = {'UserName': user_name} - return self.get_response('DeleteUser', params) - - def get_user(self, user_name=None): - """ - Retrieve information about the specified user. - - If the user_name is not specified, the user_name is determined - implicitly based on the AWS Access Key ID used to sign the request. - - :type user_name: string - :param user_name: The name of the user to retrieve. - If not specified, defaults to user making request. - """ - params = {} - if user_name: - params['UserName'] = user_name - return self.get_response('GetUser', params) - - def update_user(self, user_name, new_user_name=None, new_path=None): - """ - Updates name and/or path of the specified user. - - :type user_name: string - :param user_name: The name of the user - - :type new_user_name: string - :param new_user_name: If provided, the username of the user will be - changed to this username. - - :type new_path: string - :param new_path: If provided, the path of the user will be - changed to this path. - - """ - params = {'UserName': user_name} - if new_user_name: - params['NewUserName'] = new_user_name - if new_path: - params['NewPath'] = new_path - return self.get_response('UpdateUser', params) - - def get_all_user_policies(self, user_name, marker=None, max_items=None): - """ - List the names of the policies associated with the specified user. - - :type user_name: string - :param user_name: The name of the user the policy is associated with. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - """ - params = {'UserName': user_name} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListUserPolicies', params, - list_marker='PolicyNames') - - def put_user_policy(self, user_name, policy_name, policy_json): - """ - Adds or updates the specified policy document for the specified user. - - :type user_name: string - :param user_name: The name of the user the policy is associated with. - - :type policy_name: string - :param policy_name: The policy document to get. - - :type policy_json: string - :param policy_json: The policy document. - - """ - params = {'UserName': user_name, - 'PolicyName': policy_name, - 'PolicyDocument': policy_json} - return self.get_response('PutUserPolicy', params, verb='POST') - - def get_user_policy(self, user_name, policy_name): - """ - Retrieves the specified policy document for the specified user. - - :type user_name: string - :param user_name: The name of the user the policy is associated with. - - :type policy_name: string - :param policy_name: The policy document to get. - - """ - params = {'UserName': user_name, - 'PolicyName': policy_name} - return self.get_response('GetUserPolicy', params, verb='POST') - - def delete_user_policy(self, user_name, policy_name): - """ - Deletes the specified policy document for the specified user. - - :type user_name: string - :param user_name: The name of the user the policy is associated with. - - :type policy_name: string - :param policy_name: The policy document to delete. - - """ - params = {'UserName': user_name, - 'PolicyName': policy_name} - return self.get_response('DeleteUserPolicy', params, verb='POST') - - def get_groups_for_user(self, user_name, marker=None, max_items=None): - """ - List the groups that a specified user belongs to. - - :type user_name: string - :param user_name: The name of the user to list groups for. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - """ - params = {'UserName': user_name} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListGroupsForUser', params, - list_marker='Groups') - - # - # Access Keys - # - - def get_all_access_keys(self, user_name, marker=None, max_items=None): - """ - Get all access keys associated with an account. - - :type user_name: string - :param user_name: The username of the user - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - """ - params = {'UserName': user_name} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListAccessKeys', params, - list_marker='AccessKeyMetadata') - - def create_access_key(self, user_name=None): - """ - Create a new AWS Secret Access Key and corresponding AWS Access Key ID - for the specified user. The default status for new keys is Active - - If the user_name is not specified, the user_name is determined - implicitly based on the AWS Access Key ID used to sign the request. - - :type user_name: string - :param user_name: The username of the user - - """ - params = {'UserName': user_name} - return self.get_response('CreateAccessKey', params) - - def update_access_key(self, access_key_id, status, user_name=None): - """ - Changes the status of the specified access key from Active to Inactive - or vice versa. This action can be used to disable a user's key as - part of a key rotation workflow. - - If the user_name is not specified, the user_name is determined - implicitly based on the AWS Access Key ID used to sign the request. - - :type access_key_id: string - :param access_key_id: The ID of the access key. - - :type status: string - :param status: Either Active or Inactive. - - :type user_name: string - :param user_name: The username of user (optional). - - """ - params = {'AccessKeyId': access_key_id, - 'Status': status} - if user_name: - params['UserName'] = user_name - return self.get_response('UpdateAccessKey', params) - - def delete_access_key(self, access_key_id, user_name=None): - """ - Delete an access key associated with a user. - - If the user_name is not specified, it is determined implicitly based - on the AWS Access Key ID used to sign the request. - - :type access_key_id: string - :param access_key_id: The ID of the access key to be deleted. - - :type user_name: string - :param user_name: The username of the user - - """ - params = {'AccessKeyId': access_key_id} - if user_name: - params['UserName'] = user_name - return self.get_response('DeleteAccessKey', params) - - # - # Signing Certificates - # - - def get_all_signing_certs(self, marker=None, max_items=None, - user_name=None): - """ - Get all signing certificates associated with an account. - - If the user_name is not specified, it is determined implicitly based - on the AWS Access Key ID used to sign the request. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - - :type user_name: string - :param user_name: The username of the user - - """ - params = {} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - if user_name: - params['UserName'] = user_name - return self.get_response('ListSigningCertificates', - params, list_marker='Certificates') - - def update_signing_cert(self, cert_id, status, user_name=None): - """ - Change the status of the specified signing certificate from - Active to Inactive or vice versa. - - If the user_name is not specified, it is determined implicitly based - on the AWS Access Key ID used to sign the request. - - :type cert_id: string - :param cert_id: The ID of the signing certificate - - :type status: string - :param status: Either Active or Inactive. - - :type user_name: string - :param user_name: The username of the user - """ - params = {'CertificateId': cert_id, - 'Status': status} - if user_name: - params['UserName'] = user_name - return self.get_response('UpdateSigningCertificate', params) - - def upload_signing_cert(self, cert_body, user_name=None): - """ - Uploads an X.509 signing certificate and associates it with - the specified user. - - If the user_name is not specified, it is determined implicitly based - on the AWS Access Key ID used to sign the request. - - :type cert_body: string - :param cert_body: The body of the signing certificate. - - :type user_name: string - :param user_name: The username of the user - - """ - params = {'CertificateBody': cert_body} - if user_name: - params['UserName'] = user_name - return self.get_response('UploadSigningCertificate', params, - verb='POST') - - def delete_signing_cert(self, cert_id, user_name=None): - """ - Delete a signing certificate associated with a user. - - If the user_name is not specified, it is determined implicitly based - on the AWS Access Key ID used to sign the request. - - :type user_name: string - :param user_name: The username of the user - - :type cert_id: string - :param cert_id: The ID of the certificate. - - """ - params = {'CertificateId': cert_id} - if user_name: - params['UserName'] = user_name - return self.get_response('DeleteSigningCertificate', params) - - # - # Server Certificates - # - - def list_server_certs(self, path_prefix='/', - marker=None, max_items=None): - """ - Lists the server certificates that have the specified path prefix. - If none exist, the action returns an empty list. - - :type path_prefix: string - :param path_prefix: If provided, only certificates whose paths match - the provided prefix will be returned. - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - - """ - params = {} - if path_prefix: - params['PathPrefix'] = path_prefix - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListServerCertificates', - params, - list_marker='ServerCertificateMetadataList') - - # Preserves backwards compatibility. - # TODO: Look into deprecating this eventually? - get_all_server_certs = list_server_certs - - def update_server_cert(self, cert_name, new_cert_name=None, - new_path=None): - """ - Updates the name and/or the path of the specified server certificate. - - :type cert_name: string - :param cert_name: The name of the server certificate that you want - to update. - - :type new_cert_name: string - :param new_cert_name: The new name for the server certificate. - Include this only if you are updating the - server certificate's name. - - :type new_path: string - :param new_path: If provided, the path of the certificate will be - changed to this path. - """ - params = {'ServerCertificateName': cert_name} - if new_cert_name: - params['NewServerCertificateName'] = new_cert_name - if new_path: - params['NewPath'] = new_path - return self.get_response('UpdateServerCertificate', params) - - def upload_server_cert(self, cert_name, cert_body, private_key, - cert_chain=None, path=None): - """ - Uploads a server certificate entity for the AWS Account. - The server certificate entity includes a public key certificate, - a private key, and an optional certificate chain, which should - all be PEM-encoded. - - :type cert_name: string - :param cert_name: The name for the server certificate. Do not - include the path in this value. - - :type cert_body: string - :param cert_body: The contents of the public key certificate - in PEM-encoded format. - - :type private_key: string - :param private_key: The contents of the private key in - PEM-encoded format. - - :type cert_chain: string - :param cert_chain: The contents of the certificate chain. This - is typically a concatenation of the PEM-encoded - public key certificates of the chain. - - :type path: string - :param path: The path for the server certificate. - """ - params = {'ServerCertificateName': cert_name, - 'CertificateBody': cert_body, - 'PrivateKey': private_key} - if cert_chain: - params['CertificateChain'] = cert_chain - if path: - params['Path'] = path - return self.get_response('UploadServerCertificate', params, - verb='POST') - - def get_server_certificate(self, cert_name): - """ - Retrieves information about the specified server certificate. - - :type cert_name: string - :param cert_name: The name of the server certificate you want - to retrieve information about. - - """ - params = {'ServerCertificateName': cert_name} - return self.get_response('GetServerCertificate', params) - - def delete_server_cert(self, cert_name): - """ - Delete the specified server certificate. - - :type cert_name: string - :param cert_name: The name of the server certificate you want - to delete. - - """ - params = {'ServerCertificateName': cert_name} - return self.get_response('DeleteServerCertificate', params) - - # - # MFA Devices - # - - def get_all_mfa_devices(self, user_name, marker=None, max_items=None): - """ - Get all MFA devices associated with an account. - - :type user_name: string - :param user_name: The username of the user - - :type marker: string - :param marker: Use this only when paginating results and only - in follow-up request after you've received a response - where the results are truncated. Set this to the value of - the Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this only when paginating results to indicate - the maximum number of groups you want in the response. - - """ - params = {'UserName': user_name} - if marker: - params['Marker'] = marker - if max_items: - params['MaxItems'] = max_items - return self.get_response('ListMFADevices', - params, list_marker='MFADevices') - - def enable_mfa_device(self, user_name, serial_number, - auth_code_1, auth_code_2): - """ - Enables the specified MFA device and associates it with the - specified user. - - :type user_name: string - :param user_name: The username of the user - - :type serial_number: string - :param serial_number: The serial number which uniquely identifies - the MFA device. - - :type auth_code_1: string - :param auth_code_1: An authentication code emitted by the device. - - :type auth_code_2: string - :param auth_code_2: A subsequent authentication code emitted - by the device. - - """ - params = {'UserName': user_name, - 'SerialNumber': serial_number, - 'AuthenticationCode1': auth_code_1, - 'AuthenticationCode2': auth_code_2} - return self.get_response('EnableMFADevice', params) - - def deactivate_mfa_device(self, user_name, serial_number): - """ - Deactivates the specified MFA device and removes it from - association with the user. - - :type user_name: string - :param user_name: The username of the user - - :type serial_number: string - :param serial_number: The serial number which uniquely identifies - the MFA device. - - """ - params = {'UserName': user_name, - 'SerialNumber': serial_number} - return self.get_response('DeactivateMFADevice', params) - - def resync_mfa_device(self, user_name, serial_number, - auth_code_1, auth_code_2): - """ - Syncronizes the specified MFA device with the AWS servers. - - :type user_name: string - :param user_name: The username of the user - - :type serial_number: string - :param serial_number: The serial number which uniquely identifies - the MFA device. - - :type auth_code_1: string - :param auth_code_1: An authentication code emitted by the device. - - :type auth_code_2: string - :param auth_code_2: A subsequent authentication code emitted - by the device. - - """ - params = {'UserName': user_name, - 'SerialNumber': serial_number, - 'AuthenticationCode1': auth_code_1, - 'AuthenticationCode2': auth_code_2} - return self.get_response('ResyncMFADevice', params) - - # - # Login Profiles - # - - def get_login_profiles(self, user_name): - """ - Retrieves the login profile for the specified user. - - :type user_name: string - :param user_name: The username of the user - - """ - params = {'UserName': user_name} - return self.get_response('GetLoginProfile', params) - - def create_login_profile(self, user_name, password): - """ - Creates a login profile for the specified user, give the user the - ability to access AWS services and the AWS Management Console. - - :type user_name: string - :param user_name: The name of the user - - :type password: string - :param password: The new password for the user - - """ - params = {'UserName': user_name, - 'Password': password} - return self.get_response('CreateLoginProfile', params) - - def delete_login_profile(self, user_name): - """ - Deletes the login profile associated with the specified user. - - :type user_name: string - :param user_name: The name of the user to delete. - - """ - params = {'UserName': user_name} - return self.get_response('DeleteLoginProfile', params) - - def update_login_profile(self, user_name, password): - """ - Resets the password associated with the user's login profile. - - :type user_name: string - :param user_name: The name of the user - - :type password: string - :param password: The new password for the user - - """ - params = {'UserName': user_name, - 'Password': password} - return self.get_response('UpdateLoginProfile', params) - - def create_account_alias(self, alias): - """ - Creates a new alias for the AWS account. - - For more information on account id aliases, please see - http://goo.gl/ToB7G - - :type alias: string - :param alias: The alias to attach to the account. - """ - params = {'AccountAlias': alias} - return self.get_response('CreateAccountAlias', params) - - def delete_account_alias(self, alias): - """ - Deletes an alias for the AWS account. - - For more information on account id aliases, please see - http://goo.gl/ToB7G - - :type alias: string - :param alias: The alias to remove from the account. - """ - params = {'AccountAlias': alias} - return self.get_response('DeleteAccountAlias', params) - - def get_account_alias(self): - """ - Get the alias for the current account. - - This is referred to in the docs as list_account_aliases, - but it seems you can only have one account alias currently. - - For more information on account id aliases, please see - http://goo.gl/ToB7G - """ - return self.get_response('ListAccountAliases', {}, - list_marker='AccountAliases') - - def get_signin_url(self, service='ec2'): - """ - Get the URL where IAM users can use their login profile to sign in - to this account's console. - - :type service: string - :param service: Default service to go to in the console. - """ - alias = self.get_account_alias() - - if not alias: - raise Exception('No alias associated with this account. Please use iam.create_account_alias() first.') - - resp = alias.get('list_account_aliases_response', {}) - result = resp.get('list_account_aliases_result', {}) - aliases = result.get('account_aliases', []) - - if not len(aliases): - raise Exception('No alias associated with this account. Please use iam.create_account_alias() first.') - - # We'll just use the first one we find. - alias = aliases[0] - - if self.host == 'iam.us-gov.amazonaws.com': - return "https://%s.signin.amazonaws-us-gov.com/console/%s" % ( - alias, - service - ) - elif self.host.endswith('amazonaws.com.cn'): - return "https://%s.signin.amazonaws.cn/console/%s" % ( - alias, - service - ) - else: - return "https://%s.signin.aws.amazon.com/console/%s" % ( - alias, - service - ) - - def get_account_summary(self): - """ - Get the alias for the current account. - - This is referred to in the docs as list_account_aliases, - but it seems you can only have one account alias currently. - - For more information on account id aliases, please see - http://goo.gl/ToB7G - """ - return self.get_object('GetAccountSummary', {}, SummaryMap) - - # - # IAM Roles - # - - def add_role_to_instance_profile(self, instance_profile_name, role_name): - """ - Adds the specified role to the specified instance profile. - - :type instance_profile_name: string - :param instance_profile_name: Name of the instance profile to update. - - :type role_name: string - :param role_name: Name of the role to add. - """ - return self.get_response('AddRoleToInstanceProfile', - {'InstanceProfileName': instance_profile_name, - 'RoleName': role_name}) - - def create_instance_profile(self, instance_profile_name, path=None): - """ - Creates a new instance profile. - - :type instance_profile_name: string - :param instance_profile_name: Name of the instance profile to create. - - :type path: string - :param path: The path to the instance profile. - """ - params = {'InstanceProfileName': instance_profile_name} - if path is not None: - params['Path'] = path - return self.get_response('CreateInstanceProfile', params) - - def _build_policy(self, assume_role_policy_document=None): - if assume_role_policy_document is not None: - if isinstance(assume_role_policy_document, six.string_types): - # Historically, they had to pass a string. If it's a string, - # assume the user has already handled it. - return assume_role_policy_document - else: - - for tld, policy in DEFAULT_POLICY_DOCUMENTS.items(): - if tld is 'default': - # Skip the default. We'll fall back to it if we don't find - # anything. - continue - - if self.host and self.host.endswith(tld): - assume_role_policy_document = policy - break - - if not assume_role_policy_document: - assume_role_policy_document = DEFAULT_POLICY_DOCUMENTS['default'] - - # Dump the policy (either user-supplied ``dict`` or one of the defaults) - return json.dumps(assume_role_policy_document) - - def create_role(self, role_name, assume_role_policy_document=None, path=None): - """ - Creates a new role for your AWS account. - - The policy grants permission to an EC2 instance to assume the role. - The policy is URL-encoded according to RFC 3986. Currently, only EC2 - instances can assume roles. - - :type role_name: string - :param role_name: Name of the role to create. - - :type assume_role_policy_document: ``string`` or ``dict`` - :param assume_role_policy_document: The policy that grants an entity - permission to assume the role. - - :type path: string - :param path: The path to the role. - """ - params = { - 'RoleName': role_name, - 'AssumeRolePolicyDocument': self._build_policy( - assume_role_policy_document - ), - } - if path is not None: - params['Path'] = path - return self.get_response('CreateRole', params) - - def delete_instance_profile(self, instance_profile_name): - """ - Deletes the specified instance profile. The instance profile must not - have an associated role. - - :type instance_profile_name: string - :param instance_profile_name: Name of the instance profile to delete. - """ - return self.get_response( - 'DeleteInstanceProfile', - {'InstanceProfileName': instance_profile_name}) - - def delete_role(self, role_name): - """ - Deletes the specified role. The role must not have any policies - attached. - - :type role_name: string - :param role_name: Name of the role to delete. - """ - return self.get_response('DeleteRole', {'RoleName': role_name}) - - def delete_role_policy(self, role_name, policy_name): - """ - Deletes the specified policy associated with the specified role. - - :type role_name: string - :param role_name: Name of the role associated with the policy. - - :type policy_name: string - :param policy_name: Name of the policy to delete. - """ - return self.get_response( - 'DeleteRolePolicy', - {'RoleName': role_name, 'PolicyName': policy_name}) - - def get_instance_profile(self, instance_profile_name): - """ - Retrieves information about the specified instance profile, including - the instance profile's path, GUID, ARN, and role. - - :type instance_profile_name: string - :param instance_profile_name: Name of the instance profile to get - information about. - """ - return self.get_response('GetInstanceProfile', - {'InstanceProfileName': instance_profile_name}) - - def get_role(self, role_name): - """ - Retrieves information about the specified role, including the role's - path, GUID, ARN, and the policy granting permission to EC2 to assume - the role. - - :type role_name: string - :param role_name: Name of the role associated with the policy. - """ - return self.get_response('GetRole', {'RoleName': role_name}) - - def get_role_policy(self, role_name, policy_name): - """ - Retrieves the specified policy document for the specified role. - - :type role_name: string - :param role_name: Name of the role associated with the policy. - - :type policy_name: string - :param policy_name: Name of the policy to get. - """ - return self.get_response('GetRolePolicy', - {'RoleName': role_name, - 'PolicyName': policy_name}) - - def list_instance_profiles(self, path_prefix=None, marker=None, - max_items=None): - """ - Lists the instance profiles that have the specified path prefix. If - there are none, the action returns an empty list. - - :type path_prefix: string - :param path_prefix: The path prefix for filtering the results. For - example: /application_abc/component_xyz/, which would get all - instance profiles whose path starts with - /application_abc/component_xyz/. - - :type marker: string - :param marker: Use this parameter only when paginating results, and - only in a subsequent request after you've received a response - where the results are truncated. Set it to the value of the - Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this parameter only when paginating results to - indicate the maximum number of user names you want in the response. - """ - params = {} - if path_prefix is not None: - params['PathPrefix'] = path_prefix - if marker is not None: - params['Marker'] = marker - if max_items is not None: - params['MaxItems'] = max_items - - return self.get_response('ListInstanceProfiles', params, - list_marker='InstanceProfiles') - - def list_instance_profiles_for_role(self, role_name, marker=None, - max_items=None): - """ - Lists the instance profiles that have the specified associated role. If - there are none, the action returns an empty list. - - :type role_name: string - :param role_name: The name of the role to list instance profiles for. - - :type marker: string - :param marker: Use this parameter only when paginating results, and - only in a subsequent request after you've received a response - where the results are truncated. Set it to the value of the - Marker element in the response you just received. - - :type max_items: int - :param max_items: Use this parameter only when paginating results to - indicate the maximum number of user names you want in the response. - """ - params = {'RoleName': role_name} - if marker is not None: - params['Marker'] = marker - if max_items is not None: - params['MaxItems'] = max_items - return self.get_response('ListInstanceProfilesForRole', params, - list_marker='InstanceProfiles') - - def list_role_policies(self, role_name, marker=None, max_items=None): - """ - Lists the names of the policies associated with the specified role. If - there are none, the action returns an empty list. - - :type role_name: string - :param role_name: The name of the role to list policies for. - - :type marker: string - :param marker: Use this parameter only when paginating results, and - only in a subsequent request after you've received a response - where the results are truncated. Set it to the value of the - marker element in the response you just received. - - :type max_items: int - :param max_items: Use this parameter only when paginating results to - indicate the maximum number of user names you want in the response. - """ - params = {'RoleName': role_name} - if marker is not None: - params['Marker'] = marker - if max_items is not None: - params['MaxItems'] = max_items - return self.get_response('ListRolePolicies', params, - list_marker='PolicyNames') - - def list_roles(self, path_prefix=None, marker=None, max_items=None): - """ - Lists the roles that have the specified path prefix. If there are none, - the action returns an empty list. - - :type path_prefix: string - :param path_prefix: The path prefix for filtering the results. - - :type marker: string - :param marker: Use this parameter only when paginating results, and - only in a subsequent request after you've received a response - where the results are truncated. Set it to the value of the - marker element in the response you just received. - - :type max_items: int - :param max_items: Use this parameter only when paginating results to - indicate the maximum number of user names you want in the response. - """ - params = {} - if path_prefix is not None: - params['PathPrefix'] = path_prefix - if marker is not None: - params['Marker'] = marker - if max_items is not None: - params['MaxItems'] = max_items - return self.get_response('ListRoles', params, list_marker='Roles') - - def put_role_policy(self, role_name, policy_name, policy_document): - """ - Adds (or updates) a policy document associated with the specified role. - - :type role_name: string - :param role_name: Name of the role to associate the policy with. - - :type policy_name: string - :param policy_name: Name of the policy document. - - :type policy_document: string - :param policy_document: The policy document. - """ - return self.get_response('PutRolePolicy', - {'RoleName': role_name, - 'PolicyName': policy_name, - 'PolicyDocument': policy_document}) - - def remove_role_from_instance_profile(self, instance_profile_name, - role_name): - """ - Removes the specified role from the specified instance profile. - - :type instance_profile_name: string - :param instance_profile_name: Name of the instance profile to update. - - :type role_name: string - :param role_name: Name of the role to remove. - """ - return self.get_response('RemoveRoleFromInstanceProfile', - {'InstanceProfileName': instance_profile_name, - 'RoleName': role_name}) - - def update_assume_role_policy(self, role_name, policy_document): - """ - Updates the policy that grants an entity permission to assume a role. - Currently, only an Amazon EC2 instance can assume a role. - - :type role_name: string - :param role_name: Name of the role to update. - - :type policy_document: string - :param policy_document: The policy that grants an entity permission to - assume the role. - """ - return self.get_response('UpdateAssumeRolePolicy', - {'RoleName': role_name, - 'PolicyDocument': policy_document}) - - def create_saml_provider(self, saml_metadata_document, name): - """ - Creates an IAM entity to describe an identity provider (IdP) - that supports SAML 2.0. - - The SAML provider that you create with this operation can be - used as a principal in a role's trust policy to establish a - trust relationship between AWS and a SAML identity provider. - You can create an IAM role that supports Web-based single - sign-on (SSO) to the AWS Management Console or one that - supports API access to AWS. - - When you create the SAML provider, you upload an a SAML - metadata document that you get from your IdP and that includes - the issuer's name, expiration information, and keys that can - be used to validate the SAML authentication response - (assertions) that are received from the IdP. You must generate - the metadata document using the identity management software - that is used as your organization's IdP. - This operation requires `Signature Version 4`_. - For more information, see `Giving Console Access Using SAML`_ - and `Creating Temporary Security Credentials for SAML - Federation`_ in the Using Temporary Credentials guide. - - :type saml_metadata_document: string - :param saml_metadata_document: An XML document generated by an identity - provider (IdP) that supports SAML 2.0. The document includes the - issuer's name, expiration information, and keys that can be used to - validate the SAML authentication response (assertions) that are - received from the IdP. You must generate the metadata document - using the identity management software that is used as your - organization's IdP. - For more information, see `Creating Temporary Security Credentials for - SAML Federation`_ in the Using Temporary Security Credentials - guide. - - :type name: string - :param name: The name of the provider to create. - - """ - params = { - 'SAMLMetadataDocument': saml_metadata_document, - 'Name': name, - } - return self.get_response('CreateSAMLProvider', params) - - def list_saml_providers(self): - """ - Lists the SAML providers in the account. - This operation requires `Signature Version 4`_. - """ - return self.get_response('ListSAMLProviders', {}, list_marker='SAMLProviderList') - - def get_saml_provider(self, saml_provider_arn): - """ - Returns the SAML provider metadocument that was uploaded when - the provider was created or updated. - This operation requires `Signature Version 4`_. - - :type saml_provider_arn: string - :param saml_provider_arn: The Amazon Resource Name (ARN) of the SAML - provider to get information about. - - """ - params = {'SAMLProviderArn': saml_provider_arn} - return self.get_response('GetSAMLProvider', params) - - def update_saml_provider(self, saml_provider_arn, saml_metadata_document): - """ - Updates the metadata document for an existing SAML provider. - This operation requires `Signature Version 4`_. - - :type saml_provider_arn: string - :param saml_provider_arn: The Amazon Resource Name (ARN) of the SAML - provider to update. - - :type saml_metadata_document: string - :param saml_metadata_document: An XML document generated by an identity - provider (IdP) that supports SAML 2.0. The document includes the - issuer's name, expiration information, and keys that can be used to - validate the SAML authentication response (assertions) that are - received from the IdP. You must generate the metadata document - using the identity management software that is used as your - organization's IdP. - - """ - params = { - 'SAMLMetadataDocument': saml_metadata_document, - 'SAMLProviderArn': saml_provider_arn, - } - return self.get_response('UpdateSAMLProvider', params) - - def delete_saml_provider(self, saml_provider_arn): - """ - Deletes a SAML provider. - - Deleting the provider does not update any roles that reference - the SAML provider as a principal in their trust policies. Any - attempt to assume a role that references a SAML provider that - has been deleted will fail. - This operation requires `Signature Version 4`_. - - :type saml_provider_arn: string - :param saml_provider_arn: The Amazon Resource Name (ARN) of the SAML - provider to delete. - - """ - params = {'SAMLProviderArn': saml_provider_arn} - return self.get_response('DeleteSAMLProvider', params) - - # - # IAM Reports - # - - def generate_credential_report(self): - """ - Generates a credential report for an account - - A new credential report can only be generated every 4 hours. If one - hasn't been generated in the last 4 hours then get_credential_report - will error when called - """ - params = {} - return self.get_response('GenerateCredentialReport', params) - - def get_credential_report(self): - """ - Retrieves a credential report for an account - - A report must have been generated in the last 4 hours to succeed. - The report is returned as a base64 encoded blob within the response. - """ - params = {} - return self.get_response('GetCredentialReport', params) - - def create_virtual_mfa_device(self, path, device_name): - """ - Creates a new virtual MFA device for the AWS account. - - After creating the virtual MFA, use enable-mfa-device to - attach the MFA device to an IAM user. - - :type path: string - :param path: The path for the virtual MFA device. - - :type device_name: string - :param device_name: The name of the virtual MFA device. - Used with path to uniquely identify a virtual MFA device. - - """ - params = { - 'Path': path, - 'VirtualMFADeviceName': device_name - } - return self.get_response('CreateVirtualMFADevice', params) diff --git a/awx/lib/site-packages/boto/iam/summarymap.py b/awx/lib/site-packages/boto/iam/summarymap.py deleted file mode 100644 index b7976bb7e1..0000000000 --- a/awx/lib/site-packages/boto/iam/summarymap.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class SummaryMap(dict): - - def __init__(self, parent=None): - self.parent = parent - dict.__init__(self) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'key': - self._name = value - elif name == 'value': - try: - self[self._name] = int(value) - except ValueError: - self[self._name] = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/jsonresponse.py b/awx/lib/site-packages/boto/jsonresponse.py deleted file mode 100644 index f872b42990..0000000000 --- a/awx/lib/site-packages/boto/jsonresponse.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import xml.sax -from boto import utils - - -class XmlHandler(xml.sax.ContentHandler): - - def __init__(self, root_node, connection): - self.connection = connection - self.nodes = [('root', root_node)] - self.current_text = '' - - def startElement(self, name, attrs): - self.current_text = '' - t = self.nodes[-1][1].startElement(name, attrs, self.connection) - if t is not None: - if isinstance(t, tuple): - self.nodes.append(t) - else: - self.nodes.append((name, t)) - - def endElement(self, name): - self.nodes[-1][1].endElement(name, self.current_text, self.connection) - if self.nodes[-1][0] == name: - self.nodes.pop() - self.current_text = '' - - def characters(self, content): - self.current_text += content - - def parse(self, s): - if not isinstance(s, bytes): - s = s.encode('utf-8') - xml.sax.parseString(s, self) - - -class Element(dict): - - def __init__(self, connection=None, element_name=None, - stack=None, parent=None, list_marker=('Set',), - item_marker=('member', 'item'), - pythonize_name=False): - dict.__init__(self) - self.connection = connection - self.element_name = element_name - self.list_marker = utils.mklist(list_marker) - self.item_marker = utils.mklist(item_marker) - if stack is None: - self.stack = [] - else: - self.stack = stack - self.pythonize_name = pythonize_name - self.parent = parent - - def __getattr__(self, key): - if key in self: - return self[key] - for k in self: - e = self[k] - if isinstance(e, Element): - try: - return getattr(e, key) - except AttributeError: - pass - raise AttributeError - - def get_name(self, name): - if self.pythonize_name: - name = utils.pythonize_name(name) - return name - - def startElement(self, name, attrs, connection): - self.stack.append(name) - for lm in self.list_marker: - if name.endswith(lm): - l = ListElement(self.connection, name, self.list_marker, - self.item_marker, self.pythonize_name) - self[self.get_name(name)] = l - return l - if len(self.stack) > 0: - element_name = self.stack[-1] - e = Element(self.connection, element_name, self.stack, self, - self.list_marker, self.item_marker, - self.pythonize_name) - self[self.get_name(element_name)] = e - return (element_name, e) - else: - return None - - def endElement(self, name, value, connection): - if len(self.stack) > 0: - self.stack.pop() - value = value.strip() - if value: - if isinstance(self.parent, Element): - self.parent[self.get_name(name)] = value - elif isinstance(self.parent, ListElement): - self.parent.append(value) - - -class ListElement(list): - - def __init__(self, connection=None, element_name=None, - list_marker=['Set'], item_marker=('member', 'item'), - pythonize_name=False): - list.__init__(self) - self.connection = connection - self.element_name = element_name - self.list_marker = list_marker - self.item_marker = item_marker - self.pythonize_name = pythonize_name - - def get_name(self, name): - if self.pythonize_name: - name = utils.pythonize_name(name) - return name - - def startElement(self, name, attrs, connection): - for lm in self.list_marker: - if name.endswith(lm): - l = ListElement(self.connection, name, - self.list_marker, self.item_marker, - self.pythonize_name) - setattr(self, self.get_name(name), l) - return l - if name in self.item_marker: - e = Element(self.connection, name, parent=self, - list_marker=self.list_marker, - item_marker=self.item_marker, - pythonize_name=self.pythonize_name) - self.append(e) - return e - else: - return None - - def endElement(self, name, value, connection): - if name == self.element_name: - if len(self) > 0: - empty = [] - for e in self: - if isinstance(e, Element): - if len(e) == 0: - empty.append(e) - for e in empty: - self.remove(e) - else: - setattr(self, self.get_name(name), value) diff --git a/awx/lib/site-packages/boto/kinesis/__init__.py b/awx/lib/site-packages/boto/kinesis/__init__.py deleted file mode 100644 index 5fc33c742a..0000000000 --- a/awx/lib/site-packages/boto/kinesis/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon Kinesis service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.kinesis.layer1 import KinesisConnection - return get_regions('kinesis', connection_cls=KinesisConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/kinesis/exceptions.py b/awx/lib/site-packages/boto/kinesis/exceptions.py deleted file mode 100644 index 708f46369a..0000000000 --- a/awx/lib/site-packages/boto/kinesis/exceptions.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import BotoServerError - - -class ProvisionedThroughputExceededException(BotoServerError): - pass - - -class LimitExceededException(BotoServerError): - pass - - -class ExpiredIteratorException(BotoServerError): - pass - - -class ResourceInUseException(BotoServerError): - pass - - -class ResourceNotFoundException(BotoServerError): - pass - - -class InvalidArgumentException(BotoServerError): - pass - - -class SubscriptionRequiredException(BotoServerError): - pass diff --git a/awx/lib/site-packages/boto/kinesis/layer1.py b/awx/lib/site-packages/boto/kinesis/layer1.py deleted file mode 100644 index d514b06485..0000000000 --- a/awx/lib/site-packages/boto/kinesis/layer1.py +++ /dev/null @@ -1,708 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import base64 -import boto - -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.kinesis import exceptions -from boto.compat import json - - -class KinesisConnection(AWSQueryConnection): - """ - Amazon Kinesis Service API Reference - Amazon Kinesis is a managed service that scales elastically for - real time processing of streaming big data. - """ - APIVersion = "2013-12-02" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "kinesis.us-east-1.amazonaws.com" - ServiceName = "Kinesis" - TargetPrefix = "Kinesis_20131202" - ResponseError = JSONResponseError - - _faults = { - "ProvisionedThroughputExceededException": exceptions.ProvisionedThroughputExceededException, - "LimitExceededException": exceptions.LimitExceededException, - "ExpiredIteratorException": exceptions.ExpiredIteratorException, - "ResourceInUseException": exceptions.ResourceInUseException, - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "InvalidArgumentException": exceptions.InvalidArgumentException, - "SubscriptionRequiredException": exceptions.SubscriptionRequiredException - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - if 'host' not in kwargs: - kwargs['host'] = region.endpoint - super(KinesisConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def create_stream(self, stream_name, shard_count): - """ - This operation adds a new Amazon Kinesis stream to your AWS - account. A stream captures and transports data records that - are continuously emitted from different data sources or - producers . Scale-out within an Amazon Kinesis stream is - explicitly supported by means of shards, which are uniquely - identified groups of data records in an Amazon Kinesis stream. - - You specify and control the number of shards that a stream is - composed of. Each shard can support up to 5 read transactions - per second up to a maximum total of 2 MB of data read per - second. Each shard can support up to 1000 write transactions - per second up to a maximum total of 1 MB data written per - second. You can add shards to a stream if the amount of data - input increases and you can remove shards if the amount of - data input decreases. - - The stream name identifies the stream. The name is scoped to - the AWS account used by the application. It is also scoped by - region. That is, two streams in two different accounts can - have the same name, and two streams in the same account, but - in two different regions, can have the same name. - - `CreateStream` is an asynchronous operation. Upon receiving a - `CreateStream` request, Amazon Kinesis immediately returns and - sets the stream status to CREATING. After the stream is - created, Amazon Kinesis sets the stream status to ACTIVE. You - should perform read and write operations only on an ACTIVE - stream. - - You receive a `LimitExceededException` when making a - `CreateStream` request if you try to do one of the following: - - - + Have more than five streams in the CREATING state at any - point in time. - + Create more shards than are authorized for your account. - - - **Note:** The default limit for an AWS account is two shards - per stream. If you need to create a stream with more than two - shards, contact AWS Support to increase the limit on your - account. - - You can use the `DescribeStream` operation to check the stream - status, which is returned in `StreamStatus`. - - `CreateStream` has a limit of 5 transactions per second per - account. - - :type stream_name: string - :param stream_name: A name to identify the stream. The stream name is - scoped to the AWS account used by the application that creates the - stream. It is also scoped by region. That is, two streams in two - different AWS accounts can have the same name, and two streams in - the same AWS account, but in two different regions, can have the - same name. - - :type shard_count: integer - :param shard_count: The number of shards that the stream will use. The - throughput of the stream is a function of the number of shards; - more shards are required for greater provisioned throughput. - **Note:** The default limit for an AWS account is two shards per - stream. If you need to create a stream with more than two shards, - contact AWS Support to increase the limit on your account. - - """ - params = { - 'StreamName': stream_name, - 'ShardCount': shard_count, - } - return self.make_request(action='CreateStream', - body=json.dumps(params)) - - def delete_stream(self, stream_name): - """ - This operation deletes a stream and all of its shards and - data. You must shut down any applications that are operating - on the stream before you delete the stream. If an application - attempts to operate on a deleted stream, it will receive the - exception `ResourceNotFoundException`. - - If the stream is in the ACTIVE state, you can delete it. After - a `DeleteStream` request, the specified stream is in the - DELETING state until Amazon Kinesis completes the deletion. - - **Note:** Amazon Kinesis might continue to accept data read - and write operations, such as PutRecord and GetRecords, on a - stream in the DELETING state until the stream deletion is - complete. - - When you delete a stream, any shards in that stream are also - deleted. - - You can use the DescribeStream operation to check the state of - the stream, which is returned in `StreamStatus`. - - `DeleteStream` has a limit of 5 transactions per second per - account. - - :type stream_name: string - :param stream_name: The name of the stream to delete. - - """ - params = {'StreamName': stream_name, } - return self.make_request(action='DeleteStream', - body=json.dumps(params)) - - def describe_stream(self, stream_name, limit=None, - exclusive_start_shard_id=None): - """ - This operation returns the following information about the - stream: the current status of the stream, the stream Amazon - Resource Name (ARN), and an array of shard objects that - comprise the stream. For each shard object there is - information about the hash key and sequence number ranges that - the shard spans, and the IDs of any earlier shards that played - in a role in a MergeShards or SplitShard operation that - created the shard. A sequence number is the identifier - associated with every record ingested in the Amazon Kinesis - stream. The sequence number is assigned by the Amazon Kinesis - service when a record is put into the stream. - - You can limit the number of returned shards using the `Limit` - parameter. The number of shards in a stream may be too large - to return from a single call to `DescribeStream`. You can - detect this by using the `HasMoreShards` flag in the returned - output. `HasMoreShards` is set to `True` when there is more - data available. - - If there are more shards available, you can request more - shards by using the shard ID of the last shard returned by the - `DescribeStream` request, in the `ExclusiveStartShardId` - parameter in a subsequent request to `DescribeStream`. - `DescribeStream` is a paginated operation. - - `DescribeStream` has a limit of 10 transactions per second per - account. - - :type stream_name: string - :param stream_name: The name of the stream to describe. - - :type limit: integer - :param limit: The maximum number of shards to return. - - :type exclusive_start_shard_id: string - :param exclusive_start_shard_id: The shard ID of the shard to start - with for the stream description. - - """ - params = {'StreamName': stream_name, } - if limit is not None: - params['Limit'] = limit - if exclusive_start_shard_id is not None: - params['ExclusiveStartShardId'] = exclusive_start_shard_id - return self.make_request(action='DescribeStream', - body=json.dumps(params)) - - def get_records(self, shard_iterator, limit=None, b64_decode=True): - """ - This operation returns one or more data records from a shard. - A `GetRecords` operation request can retrieve up to 10 MB of - data. - - You specify a shard iterator for the shard that you want to - read data from in the `ShardIterator` parameter. The shard - iterator specifies the position in the shard from which you - want to start reading data records sequentially. A shard - iterator specifies this position using the sequence number of - a data record in the shard. For more information about the - shard iterator, see GetShardIterator. - - `GetRecords` may return a partial result if the response size - limit is exceeded. You will get an error, but not a partial - result if the shard's provisioned throughput is exceeded, the - shard iterator has expired, or an internal processing failure - has occurred. Clients can request a smaller amount of data by - specifying a maximum number of returned records using the - `Limit` parameter. The `Limit` parameter can be set to an - integer value of up to 10,000. If you set the value to an - integer greater than 10,000, you will receive - `InvalidArgumentException`. - - A new shard iterator is returned by every `GetRecords` request - in `NextShardIterator`, which you use in the `ShardIterator` - parameter of the next `GetRecords` request. When you - repeatedly read from an Amazon Kinesis stream use a - GetShardIterator request to get the first shard iterator to - use in your first `GetRecords` request and then use the shard - iterator returned in `NextShardIterator` for subsequent reads. - - `GetRecords` can return `null` for the `NextShardIterator` to - reflect that the shard has been closed and that the requested - shard iterator would never have returned more data. - - If no items can be processed because of insufficient - provisioned throughput on the shard involved in the request, - `GetRecords` throws `ProvisionedThroughputExceededException`. - - :type shard_iterator: string - :param shard_iterator: The position in the shard from which you want to - start sequentially reading data records. - - :type limit: integer - :param limit: The maximum number of records to return, which can be set - to a value of up to 10,000. - - :type b64_decode: boolean - :param b64_decode: Decode the Base64-encoded ``Data`` field of records. - - """ - params = {'ShardIterator': shard_iterator, } - if limit is not None: - params['Limit'] = limit - - response = self.make_request(action='GetRecords', - body=json.dumps(params)) - - # Base64 decode the data - if b64_decode: - for record in response.get('Records', []): - record['Data'] = base64.b64decode( - record['Data'].encode('utf-8')).decode('utf-8') - - return response - - def get_shard_iterator(self, stream_name, shard_id, shard_iterator_type, - starting_sequence_number=None): - """ - This operation returns a shard iterator in `ShardIterator`. - The shard iterator specifies the position in the shard from - which you want to start reading data records sequentially. A - shard iterator specifies this position using the sequence - number of a data record in a shard. A sequence number is the - identifier associated with every record ingested in the Amazon - Kinesis stream. The sequence number is assigned by the Amazon - Kinesis service when a record is put into the stream. - - You must specify the shard iterator type in the - `GetShardIterator` request. For example, you can set the - `ShardIteratorType` parameter to read exactly from the - position denoted by a specific sequence number by using the - AT_SEQUENCE_NUMBER shard iterator type, or right after the - sequence number by using the AFTER_SEQUENCE_NUMBER shard - iterator type, using sequence numbers returned by earlier - PutRecord, GetRecords or DescribeStream requests. You can - specify the shard iterator type TRIM_HORIZON in the request to - cause `ShardIterator` to point to the last untrimmed record in - the shard in the system, which is the oldest data record in - the shard. Or you can point to just after the most recent - record in the shard, by using the shard iterator type LATEST, - so that you always read the most recent data in the shard. - - **Note:** Each shard iterator expires five minutes after it is - returned to the requester. - - When you repeatedly read from an Amazon Kinesis stream use a - GetShardIterator request to get the first shard iterator to to - use in your first `GetRecords` request and then use the shard - iterator returned by the `GetRecords` request in - `NextShardIterator` for subsequent reads. A new shard iterator - is returned by every `GetRecords` request in - `NextShardIterator`, which you use in the `ShardIterator` - parameter of the next `GetRecords` request. - - If a `GetShardIterator` request is made too often, you will - receive a `ProvisionedThroughputExceededException`. For more - information about throughput limits, see the `Amazon Kinesis - Developer Guide`_. - - `GetShardIterator` can return `null` for its `ShardIterator` - to indicate that the shard has been closed and that the - requested iterator will return no more data. A shard can be - closed by a SplitShard or MergeShards operation. - - `GetShardIterator` has a limit of 5 transactions per second - per account per shard. - - :type stream_name: string - :param stream_name: The name of the stream. - - :type shard_id: string - :param shard_id: The shard ID of the shard to get the iterator for. - - :type shard_iterator_type: string - :param shard_iterator_type: - Determines how the shard iterator is used to start reading data records - from the shard. - - The following are the valid shard iterator types: - - - + AT_SEQUENCE_NUMBER - Start reading exactly from the position denoted - by a specific sequence number. - + AFTER_SEQUENCE_NUMBER - Start reading right after the position - denoted by a specific sequence number. - + TRIM_HORIZON - Start reading at the last untrimmed record in the - shard in the system, which is the oldest data record in the shard. - + LATEST - Start reading just after the most recent record in the - shard, so that you always read the most recent data in the shard. - - :type starting_sequence_number: string - :param starting_sequence_number: The sequence number of the data record - in the shard from which to start reading from. - - """ - params = { - 'StreamName': stream_name, - 'ShardId': shard_id, - 'ShardIteratorType': shard_iterator_type, - } - if starting_sequence_number is not None: - params['StartingSequenceNumber'] = starting_sequence_number - return self.make_request(action='GetShardIterator', - body=json.dumps(params)) - - def list_streams(self, limit=None, exclusive_start_stream_name=None): - """ - This operation returns an array of the names of all the - streams that are associated with the AWS account making the - `ListStreams` request. A given AWS account can have many - streams active at one time. - - The number of streams may be too large to return from a single - call to `ListStreams`. You can limit the number of returned - streams using the `Limit` parameter. If you do not specify a - value for the `Limit` parameter, Amazon Kinesis uses the - default limit, which is currently 10. - - You can detect if there are more streams available to list by - using the `HasMoreStreams` flag from the returned output. If - there are more streams available, you can request more streams - by using the name of the last stream returned by the - `ListStreams` request in the `ExclusiveStartStreamName` - parameter in a subsequent request to `ListStreams`. The group - of stream names returned by the subsequent request is then - added to the list. You can continue this process until all the - stream names have been collected in the list. - - `ListStreams` has a limit of 5 transactions per second per - account. - - :type limit: integer - :param limit: The maximum number of streams to list. - - :type exclusive_start_stream_name: string - :param exclusive_start_stream_name: The name of the stream to start the - list with. - - """ - params = {} - if limit is not None: - params['Limit'] = limit - if exclusive_start_stream_name is not None: - params['ExclusiveStartStreamName'] = exclusive_start_stream_name - return self.make_request(action='ListStreams', - body=json.dumps(params)) - - def merge_shards(self, stream_name, shard_to_merge, - adjacent_shard_to_merge): - """ - This operation merges two adjacent shards in a stream and - combines them into a single shard to reduce the stream's - capacity to ingest and transport data. Two shards are - considered adjacent if the union of the hash key ranges for - the two shards form a contiguous set with no gaps. For - example, if you have two shards, one with a hash key range of - 276...381 and the other with a hash key range of 382...454, - then you could merge these two shards into a single shard that - would have a hash key range of 276...454. After the merge, the - single child shard receives data for all hash key values - covered by the two parent shards. - - `MergeShards` is called when there is a need to reduce the - overall capacity of a stream because of excess capacity that - is not being used. The operation requires that you specify the - shard to be merged and the adjacent shard for a given stream. - For more information about merging shards, see the `Amazon - Kinesis Developer Guide`_. - - If the stream is in the ACTIVE state, you can call - `MergeShards`. If a stream is in CREATING or UPDATING or - DELETING states, then Amazon Kinesis returns a - `ResourceInUseException`. If the specified stream does not - exist, Amazon Kinesis returns a `ResourceNotFoundException`. - - You can use the DescribeStream operation to check the state of - the stream, which is returned in `StreamStatus`. - - `MergeShards` is an asynchronous operation. Upon receiving a - `MergeShards` request, Amazon Kinesis immediately returns a - response and sets the `StreamStatus` to UPDATING. After the - operation is completed, Amazon Kinesis sets the `StreamStatus` - to ACTIVE. Read and write operations continue to work while - the stream is in the UPDATING state. - - You use the DescribeStream operation to determine the shard - IDs that are specified in the `MergeShards` request. - - If you try to operate on too many streams in parallel using - CreateStream, DeleteStream, `MergeShards` or SplitShard, you - will receive a `LimitExceededException`. - - `MergeShards` has limit of 5 transactions per second per - account. - - :type stream_name: string - :param stream_name: The name of the stream for the merge. - - :type shard_to_merge: string - :param shard_to_merge: The shard ID of the shard to combine with the - adjacent shard for the merge. - - :type adjacent_shard_to_merge: string - :param adjacent_shard_to_merge: The shard ID of the adjacent shard for - the merge. - - """ - params = { - 'StreamName': stream_name, - 'ShardToMerge': shard_to_merge, - 'AdjacentShardToMerge': adjacent_shard_to_merge, - } - return self.make_request(action='MergeShards', - body=json.dumps(params)) - - def put_record(self, stream_name, data, partition_key, - explicit_hash_key=None, - sequence_number_for_ordering=None, - exclusive_minimum_sequence_number=None, - b64_encode=True): - """ - This operation puts a data record into an Amazon Kinesis - stream from a producer. This operation must be called to send - data from the producer into the Amazon Kinesis stream for - real-time ingestion and subsequent processing. The `PutRecord` - operation requires the name of the stream that captures, - stores, and transports the data; a partition key; and the data - blob itself. The data blob could be a segment from a log file, - geographic/location data, website clickstream data, or any - other data type. - - The partition key is used to distribute data across shards. - Amazon Kinesis segregates the data records that belong to a - data stream into multiple shards, using the partition key - associated with each data record to determine which shard a - given data record belongs to. - - Partition keys are Unicode strings, with a maximum length - limit of 256 bytes. An MD5 hash function is used to map - partition keys to 128-bit integer values and to map associated - data records to shards using the hash key ranges of the - shards. You can override hashing the partition key to - determine the shard by explicitly specifying a hash value - using the `ExplicitHashKey` parameter. For more information, - see the `Amazon Kinesis Developer Guide`_. - - `PutRecord` returns the shard ID of where the data record was - placed and the sequence number that was assigned to the data - record. - - Sequence numbers generally increase over time. To guarantee - strictly increasing ordering, use the - `SequenceNumberForOrdering` parameter. For more information, - see the `Amazon Kinesis Developer Guide`_. - - If a `PutRecord` request cannot be processed because of - insufficient provisioned throughput on the shard involved in - the request, `PutRecord` throws - `ProvisionedThroughputExceededException`. - - Data records are accessible for only 24 hours from the time - that they are added to an Amazon Kinesis stream. - - :type stream_name: string - :param stream_name: The name of the stream to put the data record into. - - :type data: blob - :param data: The data blob to put into the record, which is - Base64-encoded when the blob is serialized. - The maximum size of the data blob (the payload after - Base64-decoding) is 50 kilobytes (KB) - Set `b64_encode` to disable automatic Base64 encoding. - - :type partition_key: string - :param partition_key: Determines which shard in the stream the data - record is assigned to. Partition keys are Unicode strings with a - maximum length limit of 256 bytes. Amazon Kinesis uses the - partition key as input to a hash function that maps the partition - key and associated data to a specific shard. Specifically, an MD5 - hash function is used to map partition keys to 128-bit integer - values and to map associated data records to shards. As a result of - this hashing mechanism, all data records with the same partition - key will map to the same shard within the stream. - - :type explicit_hash_key: string - :param explicit_hash_key: The hash value used to explicitly determine - the shard the data record is assigned to by overriding the - partition key hash. - - :type sequence_number_for_ordering: string - :param sequence_number_for_ordering: Guarantees strictly increasing - sequence numbers, for puts from the same client and to the same - partition key. Usage: set the `SequenceNumberForOrdering` of record - n to the sequence number of record n-1 (as returned in the - PutRecordResult when putting record n-1 ). If this parameter is not - set, records will be coarsely ordered based on arrival time. - - :type b64_encode: boolean - :param b64_encode: Whether to Base64 encode `data`. Can be set to - ``False`` if `data` is already encoded to prevent double encoding. - - """ - params = { - 'StreamName': stream_name, - 'Data': data, - 'PartitionKey': partition_key, - } - if explicit_hash_key is not None: - params['ExplicitHashKey'] = explicit_hash_key - if sequence_number_for_ordering is not None: - params['SequenceNumberForOrdering'] = sequence_number_for_ordering - if b64_encode: - params['Data'] = base64.b64encode( - params['Data'].encode('utf-8')).decode('utf-8') - return self.make_request(action='PutRecord', - body=json.dumps(params)) - - def split_shard(self, stream_name, shard_to_split, new_starting_hash_key): - """ - This operation splits a shard into two new shards in the - stream, to increase the stream's capacity to ingest and - transport data. `SplitShard` is called when there is a need to - increase the overall capacity of stream because of an expected - increase in the volume of data records being ingested. - - `SplitShard` can also be used when a given shard appears to be - approaching its maximum utilization, for example, when the set - of producers sending data into the specific shard are suddenly - sending more than previously anticipated. You can also call - the `SplitShard` operation to increase stream capacity, so - that more Amazon Kinesis applications can simultaneously read - data from the stream for real-time processing. - - The `SplitShard` operation requires that you specify the shard - to be split and the new hash key, which is the position in the - shard where the shard gets split in two. In many cases, the - new hash key might simply be the average of the beginning and - ending hash key, but it can be any hash key value in the range - being mapped into the shard. For more information about - splitting shards, see the `Amazon Kinesis Developer Guide`_. - - You can use the DescribeStream operation to determine the - shard ID and hash key values for the `ShardToSplit` and - `NewStartingHashKey` parameters that are specified in the - `SplitShard` request. - - `SplitShard` is an asynchronous operation. Upon receiving a - `SplitShard` request, Amazon Kinesis immediately returns a - response and sets the stream status to UPDATING. After the - operation is completed, Amazon Kinesis sets the stream status - to ACTIVE. Read and write operations continue to work while - the stream is in the UPDATING state. - - You can use `DescribeStream` to check the status of the - stream, which is returned in `StreamStatus`. If the stream is - in the ACTIVE state, you can call `SplitShard`. If a stream is - in CREATING or UPDATING or DELETING states, then Amazon - Kinesis returns a `ResourceInUseException`. - - If the specified stream does not exist, Amazon Kinesis returns - a `ResourceNotFoundException`. If you try to create more - shards than are authorized for your account, you receive a - `LimitExceededException`. - - **Note:** The default limit for an AWS account is two shards - per stream. If you need to create a stream with more than two - shards, contact AWS Support to increase the limit on your - account. - - If you try to operate on too many streams in parallel using - CreateStream, DeleteStream, MergeShards or SplitShard, you - will receive a `LimitExceededException`. - - `SplitShard` has limit of 5 transactions per second per - account. - - :type stream_name: string - :param stream_name: The name of the stream for the shard split. - - :type shard_to_split: string - :param shard_to_split: The shard ID of the shard to split. - - :type new_starting_hash_key: string - :param new_starting_hash_key: A hash key value for the starting hash - key of one of the child shards created by the split. The hash key - range for a given shard constitutes a set of ordered contiguous - positive integers. The value for `NewStartingHashKey` must be in - the range of hash keys being mapped into the shard. The - `NewStartingHashKey` hash key value and all higher hash key values - in hash key range are distributed to one of the child shards. All - the lower hash key values in the range are distributed to the other - child shard. - - """ - params = { - 'StreamName': stream_name, - 'ShardToSplit': shard_to_split, - 'NewStartingHashKey': new_starting_hash_key, - } - return self.make_request(action='SplitShard', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response.getheaders()) - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) - diff --git a/awx/lib/site-packages/boto/logs/__init__.py b/awx/lib/site-packages/boto/logs/__init__.py deleted file mode 100644 index 2ea075d1ea..0000000000 --- a/awx/lib/site-packages/boto/logs/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import get_regions - - -def regions(): - """ - Get all available regions for the CloudWatch Logs service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.logs.layer1 import CloudWatchLogsConnection - return get_regions('logs', connection_cls=CloudWatchLogsConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/logs/exceptions.py b/awx/lib/site-packages/boto/logs/exceptions.py deleted file mode 100644 index 49c01fa91c..0000000000 --- a/awx/lib/site-packages/boto/logs/exceptions.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2012 Thomas Parslow http://almostobsolete.net/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import BotoServerError - - -class LimitExceededException(BotoServerError): - pass - - -class DataAlreadyAcceptedException(BotoServerError): - pass - - -class ResourceInUseException(BotoServerError): - pass - - -class ServiceUnavailableException(BotoServerError): - pass - - -class InvalidParameterException(BotoServerError): - pass - - -class ResourceNotFoundException(BotoServerError): - pass - - -class ResourceAlreadyExistsException(BotoServerError): - pass - - -class OperationAbortedException(BotoServerError): - pass - - -class InvalidSequenceTokenException(BotoServerError): - pass diff --git a/awx/lib/site-packages/boto/logs/layer1.py b/awx/lib/site-packages/boto/logs/layer1.py deleted file mode 100644 index 26f7aff7cd..0000000000 --- a/awx/lib/site-packages/boto/logs/layer1.py +++ /dev/null @@ -1,576 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.logs import exceptions -from boto.compat import json - - -class CloudWatchLogsConnection(AWSQueryConnection): - """ - Amazon CloudWatch Logs Service API Reference - This is the Amazon CloudWatch Logs API Reference . Amazon - CloudWatch Logs is a managed service for real time monitoring and - archival of application logs. This guide provides detailed - information about Amazon CloudWatch Logs actions, data types, - parameters, and errors. For detailed information about Amazon - CloudWatch Logs features and their associated API calls, go to the - `Amazon CloudWatch Logs Developer Guide`_. - - Use the following links to get started using the Amazon CloudWatch - API Reference : - - - + `Actions`_: An alphabetical list of all Amazon CloudWatch Logs - actions. - + `Data Types`_: An alphabetical list of all Amazon CloudWatch - Logs data types. - + `Common Parameters`_: Parameters that all Query actions can use. - + `Common Errors`_: Client and server errors that all actions can - return. - + `Regions and Endpoints`_: Itemized regions and endpoints for all - AWS products. - - - In addition to using the Amazon CloudWatch Logs API, you can also - use the following SDKs and third-party libraries to access Amazon - CloudWatch Logs programmatically. - - - + `AWS SDK for Java Documentation`_ - + `AWS SDK for .NET Documentation`_ - + `AWS SDK for PHP Documentation`_ - + `AWS SDK for Ruby Documentation`_ - - - Developers in the AWS developer community also provide their own - libraries, which you can find at the following AWS developer - centers: - - - + `AWS Java Developer Center`_ - + `AWS PHP Developer Center`_ - + `AWS Python Developer Center`_ - + `AWS Ruby Developer Center`_ - + `AWS Windows and .NET Developer Center`_ - """ - APIVersion = "2014-03-28" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "logs.us-east-1.amazonaws.com" - ServiceName = "CloudWatchLogs" - TargetPrefix = "Logs_20140328" - ResponseError = JSONResponseError - - _faults = { - "LimitExceededException": exceptions.LimitExceededException, - "DataAlreadyAcceptedException": exceptions.DataAlreadyAcceptedException, - "ResourceInUseException": exceptions.ResourceInUseException, - "ServiceUnavailableException": exceptions.ServiceUnavailableException, - "InvalidParameterException": exceptions.InvalidParameterException, - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "ResourceAlreadyExistsException": exceptions.ResourceAlreadyExistsException, - "OperationAbortedException": exceptions.OperationAbortedException, - "InvalidSequenceTokenException": exceptions.InvalidSequenceTokenException, - } - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs or kwargs['host'] is None: - kwargs['host'] = region.endpoint - - super(CloudWatchLogsConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def create_log_group(self, log_group_name): - """ - Creates a new log group with the specified name. The name of - the log group must be unique within a region for an AWS - account. You can create up to 100 log groups per account. - - You must use the following guidelines when naming a log group: - - + Log group names can be between 1 and 512 characters long. - + Allowed characters are az, AZ, 09, '_' (underscore), '-' - (hyphen), '/' (forward slash), and '.' (period). - - - - Log groups are created with a default retention of 14 days. - The retention attribute allow you to configure the number of - days you want to retain log events in the specified log group. - See the `SetRetention` operation on how to modify the - retention of your log groups. - - :type log_group_name: string - :param log_group_name: - - """ - params = {'logGroupName': log_group_name, } - return self.make_request(action='CreateLogGroup', - body=json.dumps(params)) - - def create_log_stream(self, log_group_name, log_stream_name): - """ - Creates a new log stream in the specified log group. The name - of the log stream must be unique within the log group. There - is no limit on the number of log streams that can exist in a - log group. - - You must use the following guidelines when naming a log - stream: - - + Log stream names can be between 1 and 512 characters long. - + The ':' colon character is not allowed. - - :type log_group_name: string - :param log_group_name: - - :type log_stream_name: string - :param log_stream_name: - - """ - params = { - 'logGroupName': log_group_name, - 'logStreamName': log_stream_name, - } - return self.make_request(action='CreateLogStream', - body=json.dumps(params)) - - def delete_log_group(self, log_group_name): - """ - Deletes the log group with the specified name. Amazon - CloudWatch Logs will delete a log group only if there are no - log streams and no metric filters associated with the log - group. If this condition is not satisfied, the request will - fail and the log group will not be deleted. - - :type log_group_name: string - :param log_group_name: - - """ - params = {'logGroupName': log_group_name, } - return self.make_request(action='DeleteLogGroup', - body=json.dumps(params)) - - def delete_log_stream(self, log_group_name, log_stream_name): - """ - Deletes a log stream and permanently deletes all the archived - log events associated with it. - - :type log_group_name: string - :param log_group_name: - - :type log_stream_name: string - :param log_stream_name: - - """ - params = { - 'logGroupName': log_group_name, - 'logStreamName': log_stream_name, - } - return self.make_request(action='DeleteLogStream', - body=json.dumps(params)) - - def delete_metric_filter(self, log_group_name, filter_name): - """ - Deletes a metric filter associated with the specified log - group. - - :type log_group_name: string - :param log_group_name: - - :type filter_name: string - :param filter_name: The name of the metric filter. - - """ - params = { - 'logGroupName': log_group_name, - 'filterName': filter_name, - } - return self.make_request(action='DeleteMetricFilter', - body=json.dumps(params)) - - def delete_retention_policy(self, log_group_name): - """ - - - :type log_group_name: string - :param log_group_name: - - """ - params = {'logGroupName': log_group_name, } - return self.make_request(action='DeleteRetentionPolicy', - body=json.dumps(params)) - - def describe_log_groups(self, log_group_name_prefix=None, - next_token=None, limit=None): - """ - Returns all the log groups that are associated with the AWS - account making the request. The list returned in the response - is ASCII-sorted by log group name. - - By default, this operation returns up to 50 log groups. If - there are more log groups to list, the response would contain - a `nextToken` value in the response body. You can also limit - the number of log groups returned in the response by - specifying the `limit` parameter in the request. - - :type log_group_name_prefix: string - :param log_group_name_prefix: - - :type next_token: string - :param next_token: A string token used for pagination that points to - the next page of results. It must be a value obtained from the - response of the previous `DescribeLogGroups` request. - - :type limit: integer - :param limit: The maximum number of items returned in the response. If - you don't specify a value, the request would return up to 50 items. - - """ - params = {} - if log_group_name_prefix is not None: - params['logGroupNamePrefix'] = log_group_name_prefix - if next_token is not None: - params['nextToken'] = next_token - if limit is not None: - params['limit'] = limit - return self.make_request(action='DescribeLogGroups', - body=json.dumps(params)) - - def describe_log_streams(self, log_group_name, - log_stream_name_prefix=None, next_token=None, - limit=None): - """ - Returns all the log streams that are associated with the - specified log group. The list returned in the response is - ASCII-sorted by log stream name. - - By default, this operation returns up to 50 log streams. If - there are more log streams to list, the response would contain - a `nextToken` value in the response body. You can also limit - the number of log streams returned in the response by - specifying the `limit` parameter in the request. - - :type log_group_name: string - :param log_group_name: - - :type log_stream_name_prefix: string - :param log_stream_name_prefix: - - :type next_token: string - :param next_token: A string token used for pagination that points to - the next page of results. It must be a value obtained from the - response of the previous `DescribeLogStreams` request. - - :type limit: integer - :param limit: The maximum number of items returned in the response. If - you don't specify a value, the request would return up to 50 items. - - """ - params = {'logGroupName': log_group_name, } - if log_stream_name_prefix is not None: - params['logStreamNamePrefix'] = log_stream_name_prefix - if next_token is not None: - params['nextToken'] = next_token - if limit is not None: - params['limit'] = limit - return self.make_request(action='DescribeLogStreams', - body=json.dumps(params)) - - def describe_metric_filters(self, log_group_name, - filter_name_prefix=None, next_token=None, - limit=None): - """ - Returns all the metrics filters associated with the specified - log group. The list returned in the response is ASCII-sorted - by filter name. - - By default, this operation returns up to 50 metric filters. If - there are more metric filters to list, the response would - contain a `nextToken` value in the response body. You can also - limit the number of metric filters returned in the response by - specifying the `limit` parameter in the request. - - :type log_group_name: string - :param log_group_name: - - :type filter_name_prefix: string - :param filter_name_prefix: The name of the metric filter. - - :type next_token: string - :param next_token: A string token used for pagination that points to - the next page of results. It must be a value obtained from the - response of the previous `DescribeMetricFilters` request. - - :type limit: integer - :param limit: The maximum number of items returned in the response. If - you don't specify a value, the request would return up to 50 items. - - """ - params = {'logGroupName': log_group_name, } - if filter_name_prefix is not None: - params['filterNamePrefix'] = filter_name_prefix - if next_token is not None: - params['nextToken'] = next_token - if limit is not None: - params['limit'] = limit - return self.make_request(action='DescribeMetricFilters', - body=json.dumps(params)) - - def get_log_events(self, log_group_name, log_stream_name, - start_time=None, end_time=None, next_token=None, - limit=None, start_from_head=None): - """ - Retrieves log events from the specified log stream. You can - provide an optional time range to filter the results on the - event `timestamp`. - - By default, this operation returns as much log events as can - fit in a response size of 1MB, up to 10,000 log events. The - response will always include a `nextForwardToken` and a - `nextBackwardToken` in the response body. You can use any of - these tokens in subsequent `GetLogEvents` requests to paginate - through events in either forward or backward direction. You - can also limit the number of log events returned in the - response by specifying the `limit` parameter in the request. - - :type log_group_name: string - :param log_group_name: - - :type log_stream_name: string - :param log_stream_name: - - :type start_time: long - :param start_time: A point in time expressed as the number milliseconds - since Jan 1, 1970 00:00:00 UTC. - - :type end_time: long - :param end_time: A point in time expressed as the number milliseconds - since Jan 1, 1970 00:00:00 UTC. - - :type next_token: string - :param next_token: A string token used for pagination that points to - the next page of results. It must be a value obtained from the - `nextForwardToken` or `nextBackwardToken` fields in the response of - the previous `GetLogEvents` request. - - :type limit: integer - :param limit: The maximum number of log events returned in the - response. If you don't specify a value, the request would return as - much log events as can fit in a response size of 1MB, up to 10,000 - log events. - - :type start_from_head: boolean - :param start_from_head: - - """ - params = { - 'logGroupName': log_group_name, - 'logStreamName': log_stream_name, - } - if start_time is not None: - params['startTime'] = start_time - if end_time is not None: - params['endTime'] = end_time - if next_token is not None: - params['nextToken'] = next_token - if limit is not None: - params['limit'] = limit - if start_from_head is not None: - params['startFromHead'] = start_from_head - return self.make_request(action='GetLogEvents', - body=json.dumps(params)) - - def put_log_events(self, log_group_name, log_stream_name, log_events, - sequence_token=None): - """ - Uploads a batch of log events to the specified log stream. - - Every PutLogEvents request must include the `sequenceToken` - obtained from the response of the previous request. An upload - in a newly created log stream does not require a - `sequenceToken`. - - The batch of events must satisfy the following constraints: - - + The maximum batch size is 32,768 bytes, and this size is - calculated as the sum of all event messages in UTF-8, plus 26 - bytes for each log event. - + None of the log events in the batch can be more than 2 hours - in the future. - + None of the log events in the batch can be older than 14 - days or the retention period of the log group. - + The log events in the batch must be in chronological ordered - by their `timestamp`. - + The maximum number of log events in a batch is 1,000. - - :type log_group_name: string - :param log_group_name: - - :type log_stream_name: string - :param log_stream_name: - - :type log_events: list - :param log_events: A list of events belonging to a log stream. - - :type sequence_token: string - :param sequence_token: A string token that must be obtained from the - response of the previous `PutLogEvents` request. - - """ - params = { - 'logGroupName': log_group_name, - 'logStreamName': log_stream_name, - 'logEvents': log_events, - } - if sequence_token is not None: - params['sequenceToken'] = sequence_token - return self.make_request(action='PutLogEvents', - body=json.dumps(params)) - - def put_metric_filter(self, log_group_name, filter_name, filter_pattern, - metric_transformations): - """ - Creates or updates a metric filter and associates it with the - specified log group. Metric filters allow you to configure - rules to extract metric data from log events ingested through - `PutLogEvents` requests. - - :type log_group_name: string - :param log_group_name: - - :type filter_name: string - :param filter_name: The name of the metric filter. - - :type filter_pattern: string - :param filter_pattern: - - :type metric_transformations: list - :param metric_transformations: - - """ - params = { - 'logGroupName': log_group_name, - 'filterName': filter_name, - 'filterPattern': filter_pattern, - 'metricTransformations': metric_transformations, - } - return self.make_request(action='PutMetricFilter', - body=json.dumps(params)) - - def put_retention_policy(self, log_group_name, retention_in_days): - """ - - - :type log_group_name: string - :param log_group_name: - - :type retention_in_days: integer - :param retention_in_days: Specifies the number of days you want to - retain log events in the specified log group. Possible values are: - 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 547, 730. - - """ - params = { - 'logGroupName': log_group_name, - 'retentionInDays': retention_in_days, - } - return self.make_request(action='PutRetentionPolicy', - body=json.dumps(params)) - - def set_retention(self, log_group_name, retention_in_days): - """ - Sets the retention of the specified log group. Log groups are - created with a default retention of 14 days. The retention - attribute allow you to configure the number of days you want - to retain log events in the specified log group. - - :type log_group_name: string - :param log_group_name: - - :type retention_in_days: integer - :param retention_in_days: Specifies the number of days you want to - retain log events in the specified log group. Possible values are: - 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 547, 730. - - """ - params = { - 'logGroupName': log_group_name, - 'retentionInDays': retention_in_days, - } - return self.make_request(action='SetRetention', - body=json.dumps(params)) - - def test_metric_filter(self, filter_pattern, log_event_messages): - """ - Tests the filter pattern of a metric filter against a sample - of log event messages. You can use this operation to validate - the correctness of a metric filter pattern. - - :type filter_pattern: string - :param filter_pattern: - - :type log_event_messages: list - :param log_event_messages: - - """ - params = { - 'filterPattern': filter_pattern, - 'logEventMessages': log_event_messages, - } - return self.make_request(action='TestMetricFilter', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/manage/__init__.py b/awx/lib/site-packages/boto/manage/__init__.py deleted file mode 100644 index 49d029ba2c..0000000000 --- a/awx/lib/site-packages/boto/manage/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - diff --git a/awx/lib/site-packages/boto/manage/cmdshell.py b/awx/lib/site-packages/boto/manage/cmdshell.py deleted file mode 100644 index f53227763a..0000000000 --- a/awx/lib/site-packages/boto/manage/cmdshell.py +++ /dev/null @@ -1,407 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -""" -The cmdshell module uses the paramiko package to create SSH connections -to the servers that are represented by instance objects. The module has -functions for running commands, managing files, and opening interactive -shell sessions over those connections. -""" -from boto.mashups.interactive import interactive_shell -import boto -import os -import time -import shutil -import paramiko -import socket -import subprocess - -from boto.compat import StringIO - -class SSHClient(object): - """ - This class creates a paramiko.SSHClient() object that represents - a session with an SSH server. You can use the SSHClient object to send - commands to the remote host and manipulate files on the remote host. - - :ivar server: A Server object or FakeServer object. - :ivar host_key_file: The path to the user's .ssh key files. - :ivar uname: The username for the SSH connection. Default = 'root'. - :ivar timeout: The optional timeout variable for the TCP connection. - :ivar ssh_pwd: An optional password to use for authentication or for - unlocking the private key. - """ - def __init__(self, server, - host_key_file='~/.ssh/known_hosts', - uname='root', timeout=None, ssh_pwd=None): - self.server = server - self.host_key_file = host_key_file - self.uname = uname - self._timeout = timeout - self._pkey = paramiko.RSAKey.from_private_key_file(server.ssh_key_file, - password=ssh_pwd) - self._ssh_client = paramiko.SSHClient() - self._ssh_client.load_system_host_keys() - self._ssh_client.load_host_keys(os.path.expanduser(host_key_file)) - self._ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - self.connect() - - def connect(self, num_retries=5): - """ - Connect to an SSH server and authenticate with it. - - :type num_retries: int - :param num_retries: The maximum number of connection attempts. - """ - retry = 0 - while retry < num_retries: - try: - self._ssh_client.connect(self.server.hostname, - username=self.uname, - pkey=self._pkey, - timeout=self._timeout) - return - except socket.error as xxx_todo_changeme: - (value, message) = xxx_todo_changeme.args - if value in (51, 61, 111): - print('SSH Connection refused, will retry in 5 seconds') - time.sleep(5) - retry += 1 - else: - raise - except paramiko.BadHostKeyException: - print("%s has an entry in ~/.ssh/known_hosts and it doesn't match" % self.server.hostname) - print('Edit that file to remove the entry and then hit return to try again') - raw_input('Hit Enter when ready') - retry += 1 - except EOFError: - print('Unexpected Error from SSH Connection, retry in 5 seconds') - time.sleep(5) - retry += 1 - print('Could not establish SSH connection') - - def open_sftp(self): - """ - Open an SFTP session on the SSH server. - - :rtype: :class:`paramiko.sftp_client.SFTPClient` - :return: An SFTP client object. - """ - return self._ssh_client.open_sftp() - - def get_file(self, src, dst): - """ - Open an SFTP session on the remote host, and copy a file from - the remote host to the specified path on the local host. - - :type src: string - :param src: The path to the target file on the remote host. - - :type dst: string - :param dst: The path on your local host where you want to - store the file. - """ - sftp_client = self.open_sftp() - sftp_client.get(src, dst) - - def put_file(self, src, dst): - """ - Open an SFTP session on the remote host, and copy a file from - the local host to the specified path on the remote host. - - :type src: string - :param src: The path to the target file on your local host. - - :type dst: string - :param dst: The path on the remote host where you want to store - the file. - """ - sftp_client = self.open_sftp() - sftp_client.put(src, dst) - - def open(self, filename, mode='r', bufsize=-1): - """ - Open an SFTP session to the remote host, and open a file on - that host. - - :type filename: string - :param filename: The path to the file on the remote host. - - :type mode: string - :param mode: The file interaction mode. - - :type bufsize: integer - :param bufsize: The file buffer size. - - :rtype: :class:`paramiko.sftp_file.SFTPFile` - :return: A paramiko proxy object for a file on the remote server. - """ - sftp_client = self.open_sftp() - return sftp_client.open(filename, mode, bufsize) - - def listdir(self, path): - """ - List all of the files and subdirectories at the specified path - on the remote host. - - :type path: string - :param path: The base path from which to obtain the list. - - :rtype: list - :return: A list of files and subdirectories at the specified path. - """ - sftp_client = self.open_sftp() - return sftp_client.listdir(path) - - def isdir(self, path): - """ - Check the specified path on the remote host to determine if - it is a directory. - - :type path: string - :param path: The path to the directory that you want to check. - - :rtype: integer - :return: If the path is a directory, the function returns 1. - If the path is a file or an invalid path, the function - returns 0. - """ - status = self.run('[ -d %s ] || echo "FALSE"' % path) - if status[1].startswith('FALSE'): - return 0 - return 1 - - def exists(self, path): - """ - Check the remote host for the specified path, or a file - at the specified path. This function returns 1 if the - path or the file exist on the remote host, and returns 0 if - the path or the file does not exist on the remote host. - - :type path: string - :param path: The path to the directory or file that you want to check. - - :rtype: integer - :return: If the path or the file exist, the function returns 1. - If the path or the file do not exist on the remote host, - the function returns 0. - """ - - status = self.run('[ -a %s ] || echo "FALSE"' % path) - if status[1].startswith('FALSE'): - return 0 - return 1 - - def shell(self): - """ - Start an interactive shell session with the remote host. - """ - channel = self._ssh_client.invoke_shell() - interactive_shell(channel) - - def run(self, command): - """ - Run a command on the remote host. - - :type command: string - :param command: The command that you want to send to the remote host. - - :rtype: tuple - :return: This function returns a tuple that contains an integer status, - the stdout from the command, and the stderr from the command. - - """ - boto.log.debug('running:%s on %s' % (command, self.server.instance_id)) - status = 0 - try: - t = self._ssh_client.exec_command(command) - except paramiko.SSHException: - status = 1 - std_out = t[1].read() - std_err = t[2].read() - t[0].close() - t[1].close() - t[2].close() - boto.log.debug('stdout: %s' % std_out) - boto.log.debug('stderr: %s' % std_err) - return (status, std_out, std_err) - - def run_pty(self, command): - """ - Request a pseudo-terminal from a server, and execute a command on that - server. - - :type command: string - :param command: The command that you want to run on the remote host. - - :rtype: :class:`paramiko.channel.Channel` - :return: An open channel object. - """ - boto.log.debug('running:%s on %s' % (command, self.server.instance_id)) - channel = self._ssh_client.get_transport().open_session() - channel.get_pty() - channel.exec_command(command) - return channel - - def close(self): - """ - Close an SSH session and any open channels that are tied to it. - """ - transport = self._ssh_client.get_transport() - transport.close() - self.server.reset_cmdshell() - -class LocalClient(object): - """ - :ivar server: A Server object or FakeServer object. - :ivar host_key_file: The path to the user's .ssh key files. - :ivar uname: The username for the SSH connection. Default = 'root'. - """ - def __init__(self, server, host_key_file=None, uname='root'): - self.server = server - self.host_key_file = host_key_file - self.uname = uname - - def get_file(self, src, dst): - """ - Copy a file from one directory to another. - """ - shutil.copyfile(src, dst) - - def put_file(self, src, dst): - """ - Copy a file from one directory to another. - """ - shutil.copyfile(src, dst) - - def listdir(self, path): - """ - List all of the files and subdirectories at the specified path. - - :rtype: list - :return: Return a list containing the names of the entries - in the directory given by path. - """ - return os.listdir(path) - - def isdir(self, path): - """ - Check the specified path to determine if it is a directory. - - :rtype: boolean - :return: Returns True if the path is an existing directory. - """ - return os.path.isdir(path) - - def exists(self, path): - """ - Check for the specified path, or check a file at the specified path. - - :rtype: boolean - :return: If the path or the file exist, the function returns True. - """ - return os.path.exists(path) - - def shell(self): - raise NotImplementedError('shell not supported with LocalClient') - - def run(self): - """ - Open a subprocess and run a command on the local host. - - :rtype: tuple - :return: This function returns a tuple that contains an integer status - and a string with the combined stdout and stderr output. - """ - boto.log.info('running:%s' % self.command) - log_fp = StringIO() - process = subprocess.Popen(self.command, shell=True, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - while process.poll() is None: - time.sleep(1) - t = process.communicate() - log_fp.write(t[0]) - log_fp.write(t[1]) - boto.log.info(log_fp.getvalue()) - boto.log.info('output: %s' % log_fp.getvalue()) - return (process.returncode, log_fp.getvalue()) - - def close(self): - pass - -class FakeServer(object): - """ - This object has a subset of the variables that are normally in a - :class:`boto.manage.server.Server` object. You can use this FakeServer - object to create a :class:`boto.manage.SSHClient` object if you - don't have a real Server object. - - :ivar instance: A boto Instance object. - :ivar ssh_key_file: The path to the SSH key file. - """ - def __init__(self, instance, ssh_key_file): - self.instance = instance - self.ssh_key_file = ssh_key_file - self.hostname = instance.dns_name - self.instance_id = self.instance.id - -def start(server): - """ - Connect to the specified server. - - :return: If the server is local, the function returns a - :class:`boto.manage.cmdshell.LocalClient` object. - If the server is remote, the function returns a - :class:`boto.manage.cmdshell.SSHClient` object. - """ - instance_id = boto.config.get('Instance', 'instance-id', None) - if instance_id == server.instance_id: - return LocalClient(server) - else: - return SSHClient(server) - -def sshclient_from_instance(instance, ssh_key_file, - host_key_file='~/.ssh/known_hosts', - user_name='root', ssh_pwd=None): - """ - Create and return an SSHClient object given an - instance object. - - :type instance: :class`boto.ec2.instance.Instance` object - :param instance: The instance object. - - :type ssh_key_file: string - :param ssh_key_file: A path to the private key file that is - used to log into the instance. - - :type host_key_file: string - :param host_key_file: A path to the known_hosts file used - by the SSH client. - Defaults to ~/.ssh/known_hosts - :type user_name: string - :param user_name: The username to use when logging into - the instance. Defaults to root. - - :type ssh_pwd: string - :param ssh_pwd: The passphrase, if any, associated with - private key. - """ - s = FakeServer(instance, ssh_key_file) - return SSHClient(s, host_key_file, user_name, ssh_pwd) diff --git a/awx/lib/site-packages/boto/manage/propget.py b/awx/lib/site-packages/boto/manage/propget.py deleted file mode 100644 index d034127d8b..0000000000 --- a/awx/lib/site-packages/boto/manage/propget.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -def get(prop, choices=None): - prompt = prop.verbose_name - if not prompt: - prompt = prop.name - if choices: - if callable(choices): - choices = choices() - else: - choices = prop.get_choices() - valid = False - while not valid: - if choices: - min = 1 - max = len(choices) - for i in range(min, max+1): - value = choices[i-1] - if isinstance(value, tuple): - value = value[0] - print('[%d] %s' % (i, value)) - value = raw_input('%s [%d-%d]: ' % (prompt, min, max)) - try: - int_value = int(value) - value = choices[int_value-1] - if isinstance(value, tuple): - value = value[1] - valid = True - except ValueError: - print('%s is not a valid choice' % value) - except IndexError: - print('%s is not within the range[%d-%d]' % (min, max)) - else: - value = raw_input('%s: ' % prompt) - try: - value = prop.validate(value) - if prop.empty(value) and prop.required: - print('A value is required') - else: - valid = True - except: - print('Invalid value: %s' % value) - return value - diff --git a/awx/lib/site-packages/boto/manage/server.py b/awx/lib/site-packages/boto/manage/server.py deleted file mode 100644 index d9224ab8a8..0000000000 --- a/awx/lib/site-packages/boto/manage/server.py +++ /dev/null @@ -1,556 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -""" -High-level abstraction of an EC2 server -""" - -import boto.ec2 -from boto.mashups.iobject import IObject -from boto.pyami.config import BotoConfigPath, Config -from boto.sdb.db.model import Model -from boto.sdb.db.property import StringProperty, IntegerProperty, BooleanProperty, CalculatedProperty -from boto.manage import propget -from boto.ec2.zone import Zone -from boto.ec2.keypair import KeyPair -import os, time -from contextlib import closing -from boto.exception import EC2ResponseError -from boto.compat import six, StringIO - -InstanceTypes = ['m1.small', 'm1.large', 'm1.xlarge', - 'c1.medium', 'c1.xlarge', - 'm2.2xlarge', 'm2.4xlarge'] - -class Bundler(object): - - def __init__(self, server, uname='root'): - from boto.manage.cmdshell import SSHClient - self.server = server - self.uname = uname - self.ssh_client = SSHClient(server, uname=uname) - - def copy_x509(self, key_file, cert_file): - print('\tcopying cert and pk over to /mnt directory on server') - self.ssh_client.open_sftp() - path, name = os.path.split(key_file) - self.remote_key_file = '/mnt/%s' % name - self.ssh_client.put_file(key_file, self.remote_key_file) - path, name = os.path.split(cert_file) - self.remote_cert_file = '/mnt/%s' % name - self.ssh_client.put_file(cert_file, self.remote_cert_file) - print('...complete!') - - def bundle_image(self, prefix, size, ssh_key): - command = "" - if self.uname != 'root': - command = "sudo " - command += 'ec2-bundle-vol ' - command += '-c %s -k %s ' % (self.remote_cert_file, self.remote_key_file) - command += '-u %s ' % self.server._reservation.owner_id - command += '-p %s ' % prefix - command += '-s %d ' % size - command += '-d /mnt ' - if self.server.instance_type == 'm1.small' or self.server.instance_type == 'c1.medium': - command += '-r i386' - else: - command += '-r x86_64' - return command - - def upload_bundle(self, bucket, prefix, ssh_key): - command = "" - if self.uname != 'root': - command = "sudo " - command += 'ec2-upload-bundle ' - command += '-m /mnt/%s.manifest.xml ' % prefix - command += '-b %s ' % bucket - command += '-a %s ' % self.server.ec2.aws_access_key_id - command += '-s %s ' % self.server.ec2.aws_secret_access_key - return command - - def bundle(self, bucket=None, prefix=None, key_file=None, cert_file=None, - size=None, ssh_key=None, fp=None, clear_history=True): - iobject = IObject() - if not bucket: - bucket = iobject.get_string('Name of S3 bucket') - if not prefix: - prefix = iobject.get_string('Prefix for AMI file') - if not key_file: - key_file = iobject.get_filename('Path to RSA private key file') - if not cert_file: - cert_file = iobject.get_filename('Path to RSA public cert file') - if not size: - size = iobject.get_int('Size (in MB) of bundled image') - if not ssh_key: - ssh_key = self.server.get_ssh_key_file() - self.copy_x509(key_file, cert_file) - if not fp: - fp = StringIO() - fp.write('sudo mv %s /mnt/boto.cfg; ' % BotoConfigPath) - fp.write('mv ~/.ssh/authorized_keys /mnt/authorized_keys; ') - if clear_history: - fp.write('history -c; ') - fp.write(self.bundle_image(prefix, size, ssh_key)) - fp.write('; ') - fp.write(self.upload_bundle(bucket, prefix, ssh_key)) - fp.write('; ') - fp.write('sudo mv /mnt/boto.cfg %s; ' % BotoConfigPath) - fp.write('mv /mnt/authorized_keys ~/.ssh/authorized_keys') - command = fp.getvalue() - print('running the following command on the remote server:') - print(command) - t = self.ssh_client.run(command) - print('\t%s' % t[0]) - print('\t%s' % t[1]) - print('...complete!') - print('registering image...') - self.image_id = self.server.ec2.register_image(name=prefix, image_location='%s/%s.manifest.xml' % (bucket, prefix)) - return self.image_id - -class CommandLineGetter(object): - - def get_ami_list(self): - my_amis = [] - for ami in self.ec2.get_all_images(): - # hack alert, need a better way to do this! - if ami.location.find('pyami') >= 0: - my_amis.append((ami.location, ami)) - return my_amis - - def get_region(self, params): - region = params.get('region', None) - if isinstance(region, basestring): - region = boto.ec2.get_region(region) - params['region'] = region - if not region: - prop = self.cls.find_property('region_name') - params['region'] = propget.get(prop, choices=boto.ec2.regions) - self.ec2 = params['region'].connect() - - def get_name(self, params): - if not params.get('name', None): - prop = self.cls.find_property('name') - params['name'] = propget.get(prop) - - def get_description(self, params): - if not params.get('description', None): - prop = self.cls.find_property('description') - params['description'] = propget.get(prop) - - def get_instance_type(self, params): - if not params.get('instance_type', None): - prop = StringProperty(name='instance_type', verbose_name='Instance Type', - choices=InstanceTypes) - params['instance_type'] = propget.get(prop) - - def get_quantity(self, params): - if not params.get('quantity', None): - prop = IntegerProperty(name='quantity', verbose_name='Number of Instances') - params['quantity'] = propget.get(prop) - - def get_zone(self, params): - if not params.get('zone', None): - prop = StringProperty(name='zone', verbose_name='EC2 Availability Zone', - choices=self.ec2.get_all_zones) - params['zone'] = propget.get(prop) - - def get_ami_id(self, params): - valid = False - while not valid: - ami = params.get('ami', None) - if not ami: - prop = StringProperty(name='ami', verbose_name='AMI') - ami = propget.get(prop) - try: - rs = self.ec2.get_all_images([ami]) - if len(rs) == 1: - valid = True - params['ami'] = rs[0] - except EC2ResponseError: - pass - - def get_group(self, params): - group = params.get('group', None) - if isinstance(group, basestring): - group_list = self.ec2.get_all_security_groups() - for g in group_list: - if g.name == group: - group = g - params['group'] = g - if not group: - prop = StringProperty(name='group', verbose_name='EC2 Security Group', - choices=self.ec2.get_all_security_groups) - params['group'] = propget.get(prop) - - def get_key(self, params): - keypair = params.get('keypair', None) - if isinstance(keypair, basestring): - key_list = self.ec2.get_all_key_pairs() - for k in key_list: - if k.name == keypair: - keypair = k.name - params['keypair'] = k.name - if not keypair: - prop = StringProperty(name='keypair', verbose_name='EC2 KeyPair', - choices=self.ec2.get_all_key_pairs) - params['keypair'] = propget.get(prop).name - - def get(self, cls, params): - self.cls = cls - self.get_region(params) - self.ec2 = params['region'].connect() - self.get_name(params) - self.get_description(params) - self.get_instance_type(params) - self.get_zone(params) - self.get_quantity(params) - self.get_ami_id(params) - self.get_group(params) - self.get_key(params) - -class Server(Model): - - # - # The properties of this object consists of real properties for data that - # is not already stored in EC2 somewhere (e.g. name, description) plus - # calculated properties for all of the properties that are already in - # EC2 (e.g. hostname, security groups, etc.) - # - name = StringProperty(unique=True, verbose_name="Name") - description = StringProperty(verbose_name="Description") - region_name = StringProperty(verbose_name="EC2 Region Name") - instance_id = StringProperty(verbose_name="EC2 Instance ID") - elastic_ip = StringProperty(verbose_name="EC2 Elastic IP Address") - production = BooleanProperty(verbose_name="Is This Server Production", default=False) - ami_id = CalculatedProperty(verbose_name="AMI ID", calculated_type=str, use_method=True) - zone = CalculatedProperty(verbose_name="Availability Zone Name", calculated_type=str, use_method=True) - hostname = CalculatedProperty(verbose_name="Public DNS Name", calculated_type=str, use_method=True) - private_hostname = CalculatedProperty(verbose_name="Private DNS Name", calculated_type=str, use_method=True) - groups = CalculatedProperty(verbose_name="Security Groups", calculated_type=list, use_method=True) - security_group = CalculatedProperty(verbose_name="Primary Security Group Name", calculated_type=str, use_method=True) - key_name = CalculatedProperty(verbose_name="Key Name", calculated_type=str, use_method=True) - instance_type = CalculatedProperty(verbose_name="Instance Type", calculated_type=str, use_method=True) - status = CalculatedProperty(verbose_name="Current Status", calculated_type=str, use_method=True) - launch_time = CalculatedProperty(verbose_name="Server Launch Time", calculated_type=str, use_method=True) - console_output = CalculatedProperty(verbose_name="Console Output", calculated_type=open, use_method=True) - - packages = [] - plugins = [] - - @classmethod - def add_credentials(cls, cfg, aws_access_key_id, aws_secret_access_key): - if not cfg.has_section('Credentials'): - cfg.add_section('Credentials') - cfg.set('Credentials', 'aws_access_key_id', aws_access_key_id) - cfg.set('Credentials', 'aws_secret_access_key', aws_secret_access_key) - if not cfg.has_section('DB_Server'): - cfg.add_section('DB_Server') - cfg.set('DB_Server', 'db_type', 'SimpleDB') - cfg.set('DB_Server', 'db_name', cls._manager.domain.name) - - @classmethod - def create(cls, config_file=None, logical_volume = None, cfg = None, **params): - """ - Create a new instance based on the specified configuration file or the specified - configuration and the passed in parameters. - - If the config_file argument is not None, the configuration is read from there. - Otherwise, the cfg argument is used. - - The config file may include other config files with a #import reference. The included - config files must reside in the same directory as the specified file. - - The logical_volume argument, if supplied, will be used to get the current physical - volume ID and use that as an override of the value specified in the config file. This - may be useful for debugging purposes when you want to debug with a production config - file but a test Volume. - - The dictionary argument may be used to override any EC2 configuration values in the - config file. - """ - if config_file: - cfg = Config(path=config_file) - if cfg.has_section('EC2'): - # include any EC2 configuration values that aren't specified in params: - for option in cfg.options('EC2'): - if option not in params: - params[option] = cfg.get('EC2', option) - getter = CommandLineGetter() - getter.get(cls, params) - region = params.get('region') - ec2 = region.connect() - cls.add_credentials(cfg, ec2.aws_access_key_id, ec2.aws_secret_access_key) - ami = params.get('ami') - kp = params.get('keypair') - group = params.get('group') - zone = params.get('zone') - # deal with possibly passed in logical volume: - if logical_volume != None: - cfg.set('EBS', 'logical_volume_name', logical_volume.name) - cfg_fp = StringIO() - cfg.write(cfg_fp) - # deal with the possibility that zone and/or keypair are strings read from the config file: - if isinstance(zone, Zone): - zone = zone.name - if isinstance(kp, KeyPair): - kp = kp.name - reservation = ami.run(min_count=1, - max_count=params.get('quantity', 1), - key_name=kp, - security_groups=[group], - instance_type=params.get('instance_type'), - placement = zone, - user_data = cfg_fp.getvalue()) - l = [] - i = 0 - elastic_ip = params.get('elastic_ip') - instances = reservation.instances - if elastic_ip is not None and instances.__len__() > 0: - instance = instances[0] - print('Waiting for instance to start so we can set its elastic IP address...') - # Sometimes we get a message from ec2 that says that the instance does not exist. - # Hopefully the following delay will giv eec2 enough time to get to a stable state: - time.sleep(5) - while instance.update() != 'running': - time.sleep(1) - instance.use_ip(elastic_ip) - print('set the elastic IP of the first instance to %s' % elastic_ip) - for instance in instances: - s = cls() - s.ec2 = ec2 - s.name = params.get('name') + '' if i==0 else str(i) - s.description = params.get('description') - s.region_name = region.name - s.instance_id = instance.id - if elastic_ip and i == 0: - s.elastic_ip = elastic_ip - s.put() - l.append(s) - i += 1 - return l - - @classmethod - def create_from_instance_id(cls, instance_id, name, description=''): - regions = boto.ec2.regions() - for region in regions: - ec2 = region.connect() - try: - rs = ec2.get_all_reservations([instance_id]) - except: - rs = [] - if len(rs) == 1: - s = cls() - s.ec2 = ec2 - s.name = name - s.description = description - s.region_name = region.name - s.instance_id = instance_id - s._reservation = rs[0] - for instance in s._reservation.instances: - if instance.id == instance_id: - s._instance = instance - s.put() - return s - return None - - @classmethod - def create_from_current_instances(cls): - servers = [] - regions = boto.ec2.regions() - for region in regions: - ec2 = region.connect() - rs = ec2.get_all_reservations() - for reservation in rs: - for instance in reservation.instances: - try: - next(Server.find(instance_id=instance.id)) - boto.log.info('Server for %s already exists' % instance.id) - except StopIteration: - s = cls() - s.ec2 = ec2 - s.name = instance.id - s.region_name = region.name - s.instance_id = instance.id - s._reservation = reservation - s.put() - servers.append(s) - return servers - - def __init__(self, id=None, **kw): - super(Server, self).__init__(id, **kw) - self.ssh_key_file = None - self.ec2 = None - self._cmdshell = None - self._reservation = None - self._instance = None - self._setup_ec2() - - def _setup_ec2(self): - if self.ec2 and self._instance and self._reservation: - return - if self.id: - if self.region_name: - for region in boto.ec2.regions(): - if region.name == self.region_name: - self.ec2 = region.connect() - if self.instance_id and not self._instance: - try: - rs = self.ec2.get_all_reservations([self.instance_id]) - if len(rs) >= 1: - for instance in rs[0].instances: - if instance.id == self.instance_id: - self._reservation = rs[0] - self._instance = instance - except EC2ResponseError: - pass - - def _status(self): - status = '' - if self._instance: - self._instance.update() - status = self._instance.state - return status - - def _hostname(self): - hostname = '' - if self._instance: - hostname = self._instance.public_dns_name - return hostname - - def _private_hostname(self): - hostname = '' - if self._instance: - hostname = self._instance.private_dns_name - return hostname - - def _instance_type(self): - it = '' - if self._instance: - it = self._instance.instance_type - return it - - def _launch_time(self): - lt = '' - if self._instance: - lt = self._instance.launch_time - return lt - - def _console_output(self): - co = '' - if self._instance: - co = self._instance.get_console_output() - return co - - def _groups(self): - gn = [] - if self._reservation: - gn = self._reservation.groups - return gn - - def _security_group(self): - groups = self._groups() - if len(groups) >= 1: - return groups[0].id - return "" - - def _zone(self): - zone = None - if self._instance: - zone = self._instance.placement - return zone - - def _key_name(self): - kn = None - if self._instance: - kn = self._instance.key_name - return kn - - def put(self): - super(Server, self).put() - self._setup_ec2() - - def delete(self): - if self.production: - raise ValueError("Can't delete a production server") - #self.stop() - super(Server, self).delete() - - def stop(self): - if self.production: - raise ValueError("Can't delete a production server") - if self._instance: - self._instance.stop() - - def terminate(self): - if self.production: - raise ValueError("Can't delete a production server") - if self._instance: - self._instance.terminate() - - def reboot(self): - if self._instance: - self._instance.reboot() - - def wait(self): - while self.status != 'running': - time.sleep(5) - - def get_ssh_key_file(self): - if not self.ssh_key_file: - ssh_dir = os.path.expanduser('~/.ssh') - if os.path.isdir(ssh_dir): - ssh_file = os.path.join(ssh_dir, '%s.pem' % self.key_name) - if os.path.isfile(ssh_file): - self.ssh_key_file = ssh_file - if not self.ssh_key_file: - iobject = IObject() - self.ssh_key_file = iobject.get_filename('Path to OpenSSH Key file') - return self.ssh_key_file - - def get_cmdshell(self): - if not self._cmdshell: - from boto.manage import cmdshell - self.get_ssh_key_file() - self._cmdshell = cmdshell.start(self) - return self._cmdshell - - def reset_cmdshell(self): - self._cmdshell = None - - def run(self, command): - with closing(self.get_cmdshell()) as cmd: - status = cmd.run(command) - return status - - def get_bundler(self, uname='root'): - self.get_ssh_key_file() - return Bundler(self, uname) - - def get_ssh_client(self, uname='root', ssh_pwd=None): - from boto.manage.cmdshell import SSHClient - self.get_ssh_key_file() - return SSHClient(self, uname=uname, ssh_pwd=ssh_pwd) - - def install(self, pkg): - return self.run('apt-get -y install %s' % pkg) - - - diff --git a/awx/lib/site-packages/boto/manage/task.py b/awx/lib/site-packages/boto/manage/task.py deleted file mode 100644 index c6663b9f0e..0000000000 --- a/awx/lib/site-packages/boto/manage/task.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.sdb.db.property import StringProperty, DateTimeProperty, IntegerProperty -from boto.sdb.db.model import Model -import datetime, subprocess, time -from boto.compat import StringIO - -def check_hour(val): - if val == '*': - return - if int(val) < 0 or int(val) > 23: - raise ValueError - -class Task(Model): - - """ - A scheduled, repeating task that can be executed by any participating servers. - The scheduling is similar to cron jobs. Each task has an hour attribute. - The allowable values for hour are [0-23|*]. - - To keep the operation reasonably efficient and not cause excessive polling, - the minimum granularity of a Task is hourly. Some examples: - - hour='*' - the task would be executed each hour - hour='3' - the task would be executed at 3AM GMT each day. - - """ - name = StringProperty() - hour = StringProperty(required=True, validator=check_hour, default='*') - command = StringProperty(required=True) - last_executed = DateTimeProperty() - last_status = IntegerProperty() - last_output = StringProperty() - message_id = StringProperty() - - @classmethod - def start_all(cls, queue_name): - for task in cls.all(): - task.start(queue_name) - - def __init__(self, id=None, **kw): - super(Task, self).__init__(id, **kw) - self.hourly = self.hour == '*' - self.daily = self.hour != '*' - self.now = datetime.datetime.utcnow() - - def check(self): - """ - Determine how long until the next scheduled time for a Task. - Returns the number of seconds until the next scheduled time or zero - if the task needs to be run immediately. - If it's an hourly task and it's never been run, run it now. - If it's a daily task and it's never been run and the hour is right, run it now. - """ - boto.log.info('checking Task[%s]-now=%s, last=%s' % (self.name, self.now, self.last_executed)) - - if self.hourly and not self.last_executed: - return 0 - - if self.daily and not self.last_executed: - if int(self.hour) == self.now.hour: - return 0 - else: - return max( (int(self.hour)-self.now.hour), (self.now.hour-int(self.hour)) )*60*60 - - delta = self.now - self.last_executed - if self.hourly: - if delta.seconds >= 60*60: - return 0 - else: - return 60*60 - delta.seconds - else: - if int(self.hour) == self.now.hour: - if delta.days >= 1: - return 0 - else: - return 82800 # 23 hours, just to be safe - else: - return max( (int(self.hour)-self.now.hour), (self.now.hour-int(self.hour)) )*60*60 - - def _run(self, msg, vtimeout): - boto.log.info('Task[%s] - running:%s' % (self.name, self.command)) - log_fp = StringIO() - process = subprocess.Popen(self.command, shell=True, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - nsecs = 5 - current_timeout = vtimeout - while process.poll() is None: - boto.log.info('nsecs=%s, timeout=%s' % (nsecs, current_timeout)) - if nsecs >= current_timeout: - current_timeout += vtimeout - boto.log.info('Task[%s] - setting timeout to %d seconds' % (self.name, current_timeout)) - if msg: - msg.change_visibility(current_timeout) - time.sleep(5) - nsecs += 5 - t = process.communicate() - log_fp.write(t[0]) - log_fp.write(t[1]) - boto.log.info('Task[%s] - output: %s' % (self.name, log_fp.getvalue())) - self.last_executed = self.now - self.last_status = process.returncode - self.last_output = log_fp.getvalue()[0:1023] - - def run(self, msg, vtimeout=60): - delay = self.check() - boto.log.info('Task[%s] - delay=%s seconds' % (self.name, delay)) - if delay == 0: - self._run(msg, vtimeout) - queue = msg.queue - new_msg = queue.new_message(self.id) - new_msg = queue.write(new_msg) - self.message_id = new_msg.id - self.put() - boto.log.info('Task[%s] - new message id=%s' % (self.name, new_msg.id)) - msg.delete() - boto.log.info('Task[%s] - deleted message %s' % (self.name, msg.id)) - else: - boto.log.info('new_vtimeout: %d' % delay) - msg.change_visibility(delay) - - def start(self, queue_name): - boto.log.info('Task[%s] - starting with queue: %s' % (self.name, queue_name)) - queue = boto.lookup('sqs', queue_name) - msg = queue.new_message(self.id) - msg = queue.write(msg) - self.message_id = msg.id - self.put() - boto.log.info('Task[%s] - start successful' % self.name) - -class TaskPoller(object): - - def __init__(self, queue_name): - self.sqs = boto.connect_sqs() - self.queue = self.sqs.lookup(queue_name) - - def poll(self, wait=60, vtimeout=60): - while True: - m = self.queue.read(vtimeout) - if m: - task = Task.get_by_id(m.get_body()) - if task: - if not task.message_id or m.id == task.message_id: - boto.log.info('Task[%s] - read message %s' % (task.name, m.id)) - task.run(m, vtimeout) - else: - boto.log.info('Task[%s] - found extraneous message, ignoring' % task.name) - else: - time.sleep(wait) - - - - - - diff --git a/awx/lib/site-packages/boto/manage/test_manage.py b/awx/lib/site-packages/boto/manage/test_manage.py deleted file mode 100644 index a8c188c319..0000000000 --- a/awx/lib/site-packages/boto/manage/test_manage.py +++ /dev/null @@ -1,34 +0,0 @@ -from boto.manage.server import Server -from boto.manage.volume import Volume -import time - -print('--> Creating New Volume') -volume = Volume.create() -print(volume) - -print('--> Creating New Server') -server_list = Server.create() -server = server_list[0] -print(server) - -print('----> Waiting for Server to start up') -while server.status != 'running': - print('*') - time.sleep(10) -print('----> Server is running') - -print('--> Run "df -k" on Server') -status = server.run('df -k') -print(status[1]) - -print('--> Now run volume.make_ready to make the volume ready to use on server') -volume.make_ready(server) - -print('--> Run "df -k" on Server') -status = server.run('df -k') -print(status[1]) - -print('--> Do an "ls -al" on the new filesystem') -status = server.run('ls -al %s' % volume.mount_point) -print(status[1]) - diff --git a/awx/lib/site-packages/boto/manage/volume.py b/awx/lib/site-packages/boto/manage/volume.py deleted file mode 100644 index 410414c7b3..0000000000 --- a/awx/lib/site-packages/boto/manage/volume.py +++ /dev/null @@ -1,420 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from __future__ import print_function - -from boto.sdb.db.model import Model -from boto.sdb.db.property import StringProperty, IntegerProperty, ListProperty, ReferenceProperty, CalculatedProperty -from boto.manage.server import Server -from boto.manage import propget -import boto.utils -import boto.ec2 -import time -import traceback -from contextlib import closing -import datetime - - -class CommandLineGetter(object): - - def get_region(self, params): - if not params.get('region', None): - prop = self.cls.find_property('region_name') - params['region'] = propget.get(prop, choices=boto.ec2.regions) - - def get_zone(self, params): - if not params.get('zone', None): - prop = StringProperty(name='zone', verbose_name='EC2 Availability Zone', - choices=self.ec2.get_all_zones) - params['zone'] = propget.get(prop) - - def get_name(self, params): - if not params.get('name', None): - prop = self.cls.find_property('name') - params['name'] = propget.get(prop) - - def get_size(self, params): - if not params.get('size', None): - prop = IntegerProperty(name='size', verbose_name='Size (GB)') - params['size'] = propget.get(prop) - - def get_mount_point(self, params): - if not params.get('mount_point', None): - prop = self.cls.find_property('mount_point') - params['mount_point'] = propget.get(prop) - - def get_device(self, params): - if not params.get('device', None): - prop = self.cls.find_property('device') - params['device'] = propget.get(prop) - - def get(self, cls, params): - self.cls = cls - self.get_region(params) - self.ec2 = params['region'].connect() - self.get_zone(params) - self.get_name(params) - self.get_size(params) - self.get_mount_point(params) - self.get_device(params) - -class Volume(Model): - - name = StringProperty(required=True, unique=True, verbose_name='Name') - region_name = StringProperty(required=True, verbose_name='EC2 Region') - zone_name = StringProperty(required=True, verbose_name='EC2 Zone') - mount_point = StringProperty(verbose_name='Mount Point') - device = StringProperty(verbose_name="Device Name", default='/dev/sdp') - volume_id = StringProperty(required=True) - past_volume_ids = ListProperty(item_type=str) - server = ReferenceProperty(Server, collection_name='volumes', - verbose_name='Server Attached To') - volume_state = CalculatedProperty(verbose_name="Volume State", - calculated_type=str, use_method=True) - attachment_state = CalculatedProperty(verbose_name="Attachment State", - calculated_type=str, use_method=True) - size = CalculatedProperty(verbose_name="Size (GB)", - calculated_type=int, use_method=True) - - @classmethod - def create(cls, **params): - getter = CommandLineGetter() - getter.get(cls, params) - region = params.get('region') - ec2 = region.connect() - zone = params.get('zone') - size = params.get('size') - ebs_volume = ec2.create_volume(size, zone.name) - v = cls() - v.ec2 = ec2 - v.volume_id = ebs_volume.id - v.name = params.get('name') - v.mount_point = params.get('mount_point') - v.device = params.get('device') - v.region_name = region.name - v.zone_name = zone.name - v.put() - return v - - @classmethod - def create_from_volume_id(cls, region_name, volume_id, name): - vol = None - ec2 = boto.ec2.connect_to_region(region_name) - rs = ec2.get_all_volumes([volume_id]) - if len(rs) == 1: - v = rs[0] - vol = cls() - vol.volume_id = v.id - vol.name = name - vol.region_name = v.region.name - vol.zone_name = v.zone - vol.put() - return vol - - def create_from_latest_snapshot(self, name, size=None): - snapshot = self.get_snapshots()[-1] - return self.create_from_snapshot(name, snapshot, size) - - def create_from_snapshot(self, name, snapshot, size=None): - if size < self.size: - size = self.size - ec2 = self.get_ec2_connection() - if self.zone_name is None or self.zone_name == '': - # deal with the migration case where the zone is not set in the logical volume: - current_volume = ec2.get_all_volumes([self.volume_id])[0] - self.zone_name = current_volume.zone - ebs_volume = ec2.create_volume(size, self.zone_name, snapshot) - v = Volume() - v.ec2 = self.ec2 - v.volume_id = ebs_volume.id - v.name = name - v.mount_point = self.mount_point - v.device = self.device - v.region_name = self.region_name - v.zone_name = self.zone_name - v.put() - return v - - def get_ec2_connection(self): - if self.server: - return self.server.ec2 - if not hasattr(self, 'ec2') or self.ec2 is None: - self.ec2 = boto.ec2.connect_to_region(self.region_name) - return self.ec2 - - def _volume_state(self): - ec2 = self.get_ec2_connection() - rs = ec2.get_all_volumes([self.volume_id]) - return rs[0].volume_state() - - def _attachment_state(self): - ec2 = self.get_ec2_connection() - rs = ec2.get_all_volumes([self.volume_id]) - return rs[0].attachment_state() - - def _size(self): - if not hasattr(self, '__size'): - ec2 = self.get_ec2_connection() - rs = ec2.get_all_volumes([self.volume_id]) - self.__size = rs[0].size - return self.__size - - def install_xfs(self): - if self.server: - self.server.install('xfsprogs xfsdump') - - def get_snapshots(self): - """ - Returns a list of all completed snapshots for this volume ID. - """ - ec2 = self.get_ec2_connection() - rs = ec2.get_all_snapshots() - all_vols = [self.volume_id] + self.past_volume_ids - snaps = [] - for snapshot in rs: - if snapshot.volume_id in all_vols: - if snapshot.progress == '100%': - snapshot.date = boto.utils.parse_ts(snapshot.start_time) - snapshot.keep = True - snaps.append(snapshot) - snaps.sort(cmp=lambda x, y: cmp(x.date, y.date)) - return snaps - - def attach(self, server=None): - if self.attachment_state == 'attached': - print('already attached') - return None - if server: - self.server = server - self.put() - ec2 = self.get_ec2_connection() - ec2.attach_volume(self.volume_id, self.server.instance_id, self.device) - - def detach(self, force=False): - state = self.attachment_state - if state == 'available' or state is None or state == 'detaching': - print('already detached') - return None - ec2 = self.get_ec2_connection() - ec2.detach_volume(self.volume_id, self.server.instance_id, self.device, force) - self.server = None - self.put() - - def checkfs(self, use_cmd=None): - if self.server is None: - raise ValueError('server attribute must be set to run this command') - # detemine state of file system on volume, only works if attached - if use_cmd: - cmd = use_cmd - else: - cmd = self.server.get_cmdshell() - status = cmd.run('xfs_check %s' % self.device) - if not use_cmd: - cmd.close() - if status[1].startswith('bad superblock magic number 0'): - return False - return True - - def wait(self): - if self.server is None: - raise ValueError('server attribute must be set to run this command') - with closing(self.server.get_cmdshell()) as cmd: - # wait for the volume device to appear - cmd = self.server.get_cmdshell() - while not cmd.exists(self.device): - boto.log.info('%s still does not exist, waiting 10 seconds' % self.device) - time.sleep(10) - - def format(self): - if self.server is None: - raise ValueError('server attribute must be set to run this command') - status = None - with closing(self.server.get_cmdshell()) as cmd: - if not self.checkfs(cmd): - boto.log.info('make_fs...') - status = cmd.run('mkfs -t xfs %s' % self.device) - return status - - def mount(self): - if self.server is None: - raise ValueError('server attribute must be set to run this command') - boto.log.info('handle_mount_point') - with closing(self.server.get_cmdshell()) as cmd: - cmd = self.server.get_cmdshell() - if not cmd.isdir(self.mount_point): - boto.log.info('making directory') - # mount directory doesn't exist so create it - cmd.run("mkdir %s" % self.mount_point) - else: - boto.log.info('directory exists already') - status = cmd.run('mount -l') - lines = status[1].split('\n') - for line in lines: - t = line.split() - if t and t[2] == self.mount_point: - # something is already mounted at the mount point - # unmount that and mount it as /tmp - if t[0] != self.device: - cmd.run('umount %s' % self.mount_point) - cmd.run('mount %s /tmp' % t[0]) - cmd.run('chmod 777 /tmp') - break - # Mount up our new EBS volume onto mount_point - cmd.run("mount %s %s" % (self.device, self.mount_point)) - cmd.run('xfs_growfs %s' % self.mount_point) - - def make_ready(self, server): - self.server = server - self.put() - self.install_xfs() - self.attach() - self.wait() - self.format() - self.mount() - - def freeze(self): - if self.server: - return self.server.run("/usr/sbin/xfs_freeze -f %s" % self.mount_point) - - def unfreeze(self): - if self.server: - return self.server.run("/usr/sbin/xfs_freeze -u %s" % self.mount_point) - - def snapshot(self): - # if this volume is attached to a server - # we need to freeze the XFS file system - try: - self.freeze() - if self.server is None: - snapshot = self.get_ec2_connection().create_snapshot(self.volume_id) - else: - snapshot = self.server.ec2.create_snapshot(self.volume_id) - boto.log.info('Snapshot of Volume %s created: %s' % (self.name, snapshot)) - except Exception: - boto.log.info('Snapshot error') - boto.log.info(traceback.format_exc()) - finally: - status = self.unfreeze() - return status - - def get_snapshot_range(self, snaps, start_date=None, end_date=None): - l = [] - for snap in snaps: - if start_date and end_date: - if snap.date >= start_date and snap.date <= end_date: - l.append(snap) - elif start_date: - if snap.date >= start_date: - l.append(snap) - elif end_date: - if snap.date <= end_date: - l.append(snap) - else: - l.append(snap) - return l - - def trim_snapshots(self, delete=False): - """ - Trim the number of snapshots for this volume. This method always - keeps the oldest snapshot. It then uses the parameters passed in - to determine how many others should be kept. - - The algorithm is to keep all snapshots from the current day. Then - it will keep the first snapshot of the day for the previous seven days. - Then, it will keep the first snapshot of the week for the previous - four weeks. After than, it will keep the first snapshot of the month - for as many months as there are. - - """ - snaps = self.get_snapshots() - # Always keep the oldest and the newest - if len(snaps) <= 2: - return snaps - snaps = snaps[1:-1] - now = datetime.datetime.now(snaps[0].date.tzinfo) - midnight = datetime.datetime(year=now.year, month=now.month, - day=now.day, tzinfo=now.tzinfo) - # Keep the first snapshot from each day of the previous week - one_week = datetime.timedelta(days=7, seconds=60*60) - print(midnight-one_week, midnight) - previous_week = self.get_snapshot_range(snaps, midnight-one_week, midnight) - print(previous_week) - if not previous_week: - return snaps - current_day = None - for snap in previous_week: - if current_day and current_day == snap.date.day: - snap.keep = False - else: - current_day = snap.date.day - # Get ourselves onto the next full week boundary - if previous_week: - week_boundary = previous_week[0].date - if week_boundary.weekday() != 0: - delta = datetime.timedelta(days=week_boundary.weekday()) - week_boundary = week_boundary - delta - # Keep one within this partial week - partial_week = self.get_snapshot_range(snaps, week_boundary, previous_week[0].date) - if len(partial_week) > 1: - for snap in partial_week[1:]: - snap.keep = False - # Keep the first snapshot of each week for the previous 4 weeks - for i in range(0, 4): - weeks_worth = self.get_snapshot_range(snaps, week_boundary-one_week, week_boundary) - if len(weeks_worth) > 1: - for snap in weeks_worth[1:]: - snap.keep = False - week_boundary = week_boundary - one_week - # Now look through all remaining snaps and keep one per month - remainder = self.get_snapshot_range(snaps, end_date=week_boundary) - current_month = None - for snap in remainder: - if current_month and current_month == snap.date.month: - snap.keep = False - else: - current_month = snap.date.month - if delete: - for snap in snaps: - if not snap.keep: - boto.log.info('Deleting %s(%s) for %s' % (snap, snap.date, self.name)) - snap.delete() - return snaps - - def grow(self, size): - pass - - def copy(self, snapshot): - pass - - def get_snapshot_from_date(self, date): - pass - - def delete(self, delete_ebs_volume=False): - if delete_ebs_volume: - self.detach() - ec2 = self.get_ec2_connection() - ec2.delete_volume(self.volume_id) - super(Volume, self).delete() - - def archive(self): - # snapshot volume, trim snaps, delete volume-id - pass - - diff --git a/awx/lib/site-packages/boto/mashups/__init__.py b/awx/lib/site-packages/boto/mashups/__init__.py deleted file mode 100644 index 449bd162a8..0000000000 --- a/awx/lib/site-packages/boto/mashups/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - diff --git a/awx/lib/site-packages/boto/mashups/interactive.py b/awx/lib/site-packages/boto/mashups/interactive.py deleted file mode 100644 index 1eb9db47d5..0000000000 --- a/awx/lib/site-packages/boto/mashups/interactive.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2003-2007 Robey Pointer <robey@lag.net> -# -# This file is part of paramiko. -# -# Paramiko is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free -# Software Foundation; either version 2.1 of the License, or (at your option) -# any later version. -# -# Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Paramiko; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -from __future__ import print_function - -import socket -import sys - -# windows does not have termios... -try: - import termios - import tty - has_termios = True -except ImportError: - has_termios = False - - -def interactive_shell(chan): - if has_termios: - posix_shell(chan) - else: - windows_shell(chan) - - -def posix_shell(chan): - import select - - oldtty = termios.tcgetattr(sys.stdin) - try: - tty.setraw(sys.stdin.fileno()) - tty.setcbreak(sys.stdin.fileno()) - chan.settimeout(0.0) - - while True: - r, w, e = select.select([chan, sys.stdin], [], []) - if chan in r: - try: - x = chan.recv(1024) - if len(x) == 0: - print('\r\n*** EOF\r\n', end=' ') - break - sys.stdout.write(x) - sys.stdout.flush() - except socket.timeout: - pass - if sys.stdin in r: - x = sys.stdin.read(1) - if len(x) == 0: - break - chan.send(x) - - finally: - termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) - - -# thanks to Mike Looijmans for this code -def windows_shell(chan): - import threading - - sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") - - def writeall(sock): - while True: - data = sock.recv(256) - if not data: - sys.stdout.write('\r\n*** EOF ***\r\n\r\n') - sys.stdout.flush() - break - sys.stdout.write(data) - sys.stdout.flush() - - writer = threading.Thread(target=writeall, args=(chan,)) - writer.start() - - try: - while True: - d = sys.stdin.read(1) - if not d: - break - chan.send(d) - except EOFError: - # user hit ^Z or F6 - pass diff --git a/awx/lib/site-packages/boto/mashups/iobject.py b/awx/lib/site-packages/boto/mashups/iobject.py deleted file mode 100644 index f6ae98a34a..0000000000 --- a/awx/lib/site-packages/boto/mashups/iobject.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import os - -def int_val_fn(v): - try: - int(v) - return True - except: - return False - -class IObject(object): - - def choose_from_list(self, item_list, search_str='', - prompt='Enter Selection'): - if not item_list: - print('No Choices Available') - return - choice = None - while not choice: - n = 1 - choices = [] - for item in item_list: - if isinstance(item, basestring): - print('[%d] %s' % (n, item)) - choices.append(item) - n += 1 - else: - obj, id, desc = item - if desc: - if desc.find(search_str) >= 0: - print('[%d] %s - %s' % (n, id, desc)) - choices.append(obj) - n += 1 - else: - if id.find(search_str) >= 0: - print('[%d] %s' % (n, id)) - choices.append(obj) - n += 1 - if choices: - val = raw_input('%s[1-%d]: ' % (prompt, len(choices))) - if val.startswith('/'): - search_str = val[1:] - else: - try: - int_val = int(val) - if int_val == 0: - return None - choice = choices[int_val-1] - except ValueError: - print('%s is not a valid choice' % val) - except IndexError: - print('%s is not within the range[1-%d]' % (val, - len(choices))) - else: - print("No objects matched your pattern") - search_str = '' - return choice - - def get_string(self, prompt, validation_fn=None): - okay = False - while not okay: - val = raw_input('%s: ' % prompt) - if validation_fn: - okay = validation_fn(val) - if not okay: - print('Invalid value: %s' % val) - else: - okay = True - return val - - def get_filename(self, prompt): - okay = False - val = '' - while not okay: - val = raw_input('%s: %s' % (prompt, val)) - val = os.path.expanduser(val) - if os.path.isfile(val): - okay = True - elif os.path.isdir(val): - path = val - val = self.choose_from_list(os.listdir(path)) - if val: - val = os.path.join(path, val) - okay = True - else: - val = '' - else: - print('Invalid value: %s' % val) - val = '' - return val - - def get_int(self, prompt): - s = self.get_string(prompt, int_val_fn) - return int(s) - diff --git a/awx/lib/site-packages/boto/mashups/order.py b/awx/lib/site-packages/boto/mashups/order.py deleted file mode 100644 index 4aaec307bd..0000000000 --- a/awx/lib/site-packages/boto/mashups/order.py +++ /dev/null @@ -1,211 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -""" -High-level abstraction of an EC2 order for servers -""" - -import boto -import boto.ec2 -from boto.mashups.server import Server, ServerSet -from boto.mashups.iobject import IObject -from boto.pyami.config import Config -from boto.sdb.persist import get_domain, set_domain -import time -from boto.compat import StringIO - -InstanceTypes = ['m1.small', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge'] - -class Item(IObject): - - def __init__(self): - self.region = None - self.name = None - self.instance_type = None - self.quantity = 0 - self.zone = None - self.ami = None - self.groups = [] - self.key = None - self.ec2 = None - self.config = None - - def set_userdata(self, key, value): - self.userdata[key] = value - - def get_userdata(self, key): - return self.userdata[key] - - def set_region(self, region=None): - if region: - self.region = region - else: - l = [(r, r.name, r.endpoint) for r in boto.ec2.regions()] - self.region = self.choose_from_list(l, prompt='Choose Region') - - def set_name(self, name=None): - if name: - self.name = name - else: - self.name = self.get_string('Name') - - def set_instance_type(self, instance_type=None): - if instance_type: - self.instance_type = instance_type - else: - self.instance_type = self.choose_from_list(InstanceTypes, 'Instance Type') - - def set_quantity(self, n=0): - if n > 0: - self.quantity = n - else: - self.quantity = self.get_int('Quantity') - - def set_zone(self, zone=None): - if zone: - self.zone = zone - else: - l = [(z, z.name, z.state) for z in self.ec2.get_all_zones()] - self.zone = self.choose_from_list(l, prompt='Choose Availability Zone') - - def set_ami(self, ami=None): - if ami: - self.ami = ami - else: - l = [(a, a.id, a.location) for a in self.ec2.get_all_images()] - self.ami = self.choose_from_list(l, prompt='Choose AMI') - - def add_group(self, group=None): - if group: - self.groups.append(group) - else: - l = [(s, s.name, s.description) for s in self.ec2.get_all_security_groups()] - self.groups.append(self.choose_from_list(l, prompt='Choose Security Group')) - - def set_key(self, key=None): - if key: - self.key = key - else: - l = [(k, k.name, '') for k in self.ec2.get_all_key_pairs()] - self.key = self.choose_from_list(l, prompt='Choose Keypair') - - def update_config(self): - if not self.config.has_section('Credentials'): - self.config.add_section('Credentials') - self.config.set('Credentials', 'aws_access_key_id', self.ec2.aws_access_key_id) - self.config.set('Credentials', 'aws_secret_access_key', self.ec2.aws_secret_access_key) - if not self.config.has_section('Pyami'): - self.config.add_section('Pyami') - sdb_domain = get_domain() - if sdb_domain: - self.config.set('Pyami', 'server_sdb_domain', sdb_domain) - self.config.set('Pyami', 'server_sdb_name', self.name) - - def set_config(self, config_path=None): - if not config_path: - config_path = self.get_filename('Specify Config file') - self.config = Config(path=config_path) - - def get_userdata_string(self): - s = StringIO() - self.config.write(s) - return s.getvalue() - - def enter(self, **params): - self.region = params.get('region', self.region) - if not self.region: - self.set_region() - self.ec2 = self.region.connect() - self.name = params.get('name', self.name) - if not self.name: - self.set_name() - self.instance_type = params.get('instance_type', self.instance_type) - if not self.instance_type: - self.set_instance_type() - self.zone = params.get('zone', self.zone) - if not self.zone: - self.set_zone() - self.quantity = params.get('quantity', self.quantity) - if not self.quantity: - self.set_quantity() - self.ami = params.get('ami', self.ami) - if not self.ami: - self.set_ami() - self.groups = params.get('groups', self.groups) - if not self.groups: - self.add_group() - self.key = params.get('key', self.key) - if not self.key: - self.set_key() - self.config = params.get('config', self.config) - if not self.config: - self.set_config() - self.update_config() - -class Order(IObject): - - def __init__(self): - self.items = [] - self.reservation = None - - def add_item(self, **params): - item = Item() - item.enter(**params) - self.items.append(item) - - def display(self): - print('This Order consists of the following items') - print() - print('QTY\tNAME\tTYPE\nAMI\t\tGroups\t\t\tKeyPair') - for item in self.items: - print('%s\t%s\t%s\t%s\t%s\t%s' % (item.quantity, item.name, item.instance_type, - item.ami.id, item.groups, item.key.name)) - - def place(self, block=True): - if get_domain() is None: - print('SDB Persistence Domain not set') - domain_name = self.get_string('Specify SDB Domain') - set_domain(domain_name) - s = ServerSet() - for item in self.items: - r = item.ami.run(min_count=1, max_count=item.quantity, - key_name=item.key.name, user_data=item.get_userdata_string(), - security_groups=item.groups, instance_type=item.instance_type, - placement=item.zone.name) - if block: - states = [i.state for i in r.instances] - if states.count('running') != len(states): - print(states) - time.sleep(15) - states = [i.update() for i in r.instances] - for i in r.instances: - server = Server() - server.name = item.name - server.instance_id = i.id - server.reservation = r - server.save() - s.append(server) - if len(s) == 1: - return s[0] - else: - return s - - - diff --git a/awx/lib/site-packages/boto/mashups/server.py b/awx/lib/site-packages/boto/mashups/server.py deleted file mode 100644 index 7045e7f4da..0000000000 --- a/awx/lib/site-packages/boto/mashups/server.py +++ /dev/null @@ -1,395 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -""" -High-level abstraction of an EC2 server -""" - -import boto -import boto.utils -from boto.compat import StringIO -from boto.mashups.iobject import IObject -from boto.pyami.config import Config, BotoConfigPath -from boto.mashups.interactive import interactive_shell -from boto.sdb.db.model import Model -from boto.sdb.db.property import StringProperty -import os - - -class ServerSet(list): - - def __getattr__(self, name): - results = [] - is_callable = False - for server in self: - try: - val = getattr(server, name) - if callable(val): - is_callable = True - results.append(val) - except: - results.append(None) - if is_callable: - self.map_list = results - return self.map - return results - - def map(self, *args): - results = [] - for fn in self.map_list: - results.append(fn(*args)) - return results - -class Server(Model): - - @property - def ec2(self): - if self._ec2 is None: - self._ec2 = boto.connect_ec2() - return self._ec2 - - @classmethod - def Inventory(cls): - """ - Returns a list of Server instances, one for each Server object - persisted in the db - """ - l = ServerSet() - rs = cls.find() - for server in rs: - l.append(server) - return l - - @classmethod - def Register(cls, name, instance_id, description=''): - s = cls() - s.name = name - s.instance_id = instance_id - s.description = description - s.save() - return s - - def __init__(self, id=None, **kw): - super(Server, self).__init__(id, **kw) - self._reservation = None - self._instance = None - self._ssh_client = None - self._pkey = None - self._config = None - self._ec2 = None - - name = StringProperty(unique=True, verbose_name="Name") - instance_id = StringProperty(verbose_name="Instance ID") - config_uri = StringProperty() - ami_id = StringProperty(verbose_name="AMI ID") - zone = StringProperty(verbose_name="Availability Zone") - security_group = StringProperty(verbose_name="Security Group", default="default") - key_name = StringProperty(verbose_name="Key Name") - elastic_ip = StringProperty(verbose_name="Elastic IP") - instance_type = StringProperty(verbose_name="Instance Type") - description = StringProperty(verbose_name="Description") - log = StringProperty() - - def setReadOnly(self, value): - raise AttributeError - - def getInstance(self): - if not self._instance: - if self.instance_id: - try: - rs = self.ec2.get_all_reservations([self.instance_id]) - except: - return None - if len(rs) > 0: - self._reservation = rs[0] - self._instance = self._reservation.instances[0] - return self._instance - - instance = property(getInstance, setReadOnly, None, 'The Instance for the server') - - def getAMI(self): - if self.instance: - return self.instance.image_id - - ami = property(getAMI, setReadOnly, None, 'The AMI for the server') - - def getStatus(self): - if self.instance: - self.instance.update() - return self.instance.state - - status = property(getStatus, setReadOnly, None, - 'The status of the server') - - def getHostname(self): - if self.instance: - return self.instance.public_dns_name - - hostname = property(getHostname, setReadOnly, None, - 'The public DNS name of the server') - - def getPrivateHostname(self): - if self.instance: - return self.instance.private_dns_name - - private_hostname = property(getPrivateHostname, setReadOnly, None, - 'The private DNS name of the server') - - def getLaunchTime(self): - if self.instance: - return self.instance.launch_time - - launch_time = property(getLaunchTime, setReadOnly, None, - 'The time the Server was started') - - def getConsoleOutput(self): - if self.instance: - return self.instance.get_console_output() - - console_output = property(getConsoleOutput, setReadOnly, None, - 'Retrieve the console output for server') - - def getGroups(self): - if self._reservation: - return self._reservation.groups - else: - return None - - groups = property(getGroups, setReadOnly, None, - 'The Security Groups controlling access to this server') - - def getConfig(self): - if not self._config: - remote_file = BotoConfigPath - local_file = '%s.ini' % self.instance.id - self.get_file(remote_file, local_file) - self._config = Config(local_file) - return self._config - - def setConfig(self, config): - local_file = '%s.ini' % self.instance.id - fp = open(local_file) - config.write(fp) - fp.close() - self.put_file(local_file, BotoConfigPath) - self._config = config - - config = property(getConfig, setConfig, None, - 'The instance data for this server') - - def set_config(self, config): - """ - Set SDB based config - """ - self._config = config - self._config.dump_to_sdb("botoConfigs", self.id) - - def load_config(self): - self._config = Config(do_load=False) - self._config.load_from_sdb("botoConfigs", self.id) - - def stop(self): - if self.instance: - self.instance.stop() - - def start(self): - self.stop() - ec2 = boto.connect_ec2() - ami = ec2.get_all_images(image_ids = [str(self.ami_id)])[0] - groups = ec2.get_all_security_groups(groupnames=[str(self.security_group)]) - if not self._config: - self.load_config() - if not self._config.has_section("Credentials"): - self._config.add_section("Credentials") - self._config.set("Credentials", "aws_access_key_id", ec2.aws_access_key_id) - self._config.set("Credentials", "aws_secret_access_key", ec2.aws_secret_access_key) - - if not self._config.has_section("Pyami"): - self._config.add_section("Pyami") - - if self._manager.domain: - self._config.set('Pyami', 'server_sdb_domain', self._manager.domain.name) - self._config.set("Pyami", 'server_sdb_name', self.name) - - cfg = StringIO() - self._config.write(cfg) - cfg = cfg.getvalue() - r = ami.run(min_count=1, - max_count=1, - key_name=self.key_name, - security_groups = groups, - instance_type = self.instance_type, - placement = self.zone, - user_data = cfg) - i = r.instances[0] - self.instance_id = i.id - self.put() - if self.elastic_ip: - ec2.associate_address(self.instance_id, self.elastic_ip) - - def reboot(self): - if self.instance: - self.instance.reboot() - - def get_ssh_client(self, key_file=None, host_key_file='~/.ssh/known_hosts', - uname='root'): - import paramiko - if not self.instance: - print('No instance yet!') - return - if not self._ssh_client: - if not key_file: - iobject = IObject() - key_file = iobject.get_filename('Path to OpenSSH Key file') - self._pkey = paramiko.RSAKey.from_private_key_file(key_file) - self._ssh_client = paramiko.SSHClient() - self._ssh_client.load_system_host_keys() - self._ssh_client.load_host_keys(os.path.expanduser(host_key_file)) - self._ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - self._ssh_client.connect(self.instance.public_dns_name, - username=uname, pkey=self._pkey) - return self._ssh_client - - def get_file(self, remotepath, localpath): - ssh_client = self.get_ssh_client() - sftp_client = ssh_client.open_sftp() - sftp_client.get(remotepath, localpath) - - def put_file(self, localpath, remotepath): - ssh_client = self.get_ssh_client() - sftp_client = ssh_client.open_sftp() - sftp_client.put(localpath, remotepath) - - def listdir(self, remotepath): - ssh_client = self.get_ssh_client() - sftp_client = ssh_client.open_sftp() - return sftp_client.listdir(remotepath) - - def shell(self, key_file=None): - ssh_client = self.get_ssh_client(key_file) - channel = ssh_client.invoke_shell() - interactive_shell(channel) - - def bundle_image(self, prefix, key_file, cert_file, size): - print('bundling image...') - print('\tcopying cert and pk over to /mnt directory on server') - ssh_client = self.get_ssh_client() - sftp_client = ssh_client.open_sftp() - path, name = os.path.split(key_file) - remote_key_file = '/mnt/%s' % name - self.put_file(key_file, remote_key_file) - path, name = os.path.split(cert_file) - remote_cert_file = '/mnt/%s' % name - self.put_file(cert_file, remote_cert_file) - print('\tdeleting %s' % BotoConfigPath) - # delete the metadata.ini file if it exists - try: - sftp_client.remove(BotoConfigPath) - except: - pass - command = 'sudo ec2-bundle-vol ' - command += '-c %s -k %s ' % (remote_cert_file, remote_key_file) - command += '-u %s ' % self._reservation.owner_id - command += '-p %s ' % prefix - command += '-s %d ' % size - command += '-d /mnt ' - if self.instance.instance_type == 'm1.small' or self.instance_type == 'c1.medium': - command += '-r i386' - else: - command += '-r x86_64' - print('\t%s' % command) - t = ssh_client.exec_command(command) - response = t[1].read() - print('\t%s' % response) - print('\t%s' % t[2].read()) - print('...complete!') - - def upload_bundle(self, bucket, prefix): - print('uploading bundle...') - command = 'ec2-upload-bundle ' - command += '-m /mnt/%s.manifest.xml ' % prefix - command += '-b %s ' % bucket - command += '-a %s ' % self.ec2.aws_access_key_id - command += '-s %s ' % self.ec2.aws_secret_access_key - print('\t%s' % command) - ssh_client = self.get_ssh_client() - t = ssh_client.exec_command(command) - response = t[1].read() - print('\t%s' % response) - print('\t%s' % t[2].read()) - print('...complete!') - - def create_image(self, bucket=None, prefix=None, key_file=None, cert_file=None, size=None): - iobject = IObject() - if not bucket: - bucket = iobject.get_string('Name of S3 bucket') - if not prefix: - prefix = iobject.get_string('Prefix for AMI file') - if not key_file: - key_file = iobject.get_filename('Path to RSA private key file') - if not cert_file: - cert_file = iobject.get_filename('Path to RSA public cert file') - if not size: - size = iobject.get_int('Size (in MB) of bundled image') - self.bundle_image(prefix, key_file, cert_file, size) - self.upload_bundle(bucket, prefix) - print('registering image...') - self.image_id = self.ec2.register_image('%s/%s.manifest.xml' % (bucket, prefix)) - return self.image_id - - def attach_volume(self, volume, device="/dev/sdp"): - """ - Attach an EBS volume to this server - - :param volume: EBS Volume to attach - :type volume: boto.ec2.volume.Volume - - :param device: Device to attach to (default to /dev/sdp) - :type device: string - """ - if hasattr(volume, "id"): - volume_id = volume.id - else: - volume_id = volume - return self.ec2.attach_volume(volume_id=volume_id, instance_id=self.instance_id, device=device) - - def detach_volume(self, volume): - """ - Detach an EBS volume from this server - - :param volume: EBS Volume to detach - :type volume: boto.ec2.volume.Volume - """ - if hasattr(volume, "id"): - volume_id = volume.id - else: - volume_id = volume - return self.ec2.detach_volume(volume_id=volume_id, instance_id=self.instance_id) - - def install_package(self, package_name): - print('installing %s...' % package_name) - command = 'yum -y install %s' % package_name - print('\t%s' % command) - ssh_client = self.get_ssh_client() - t = ssh_client.exec_command(command) - response = t[1].read() - print('\t%s' % response) - print('\t%s' % t[2].read()) - print('...complete!') diff --git a/awx/lib/site-packages/boto/mturk/__init__.py b/awx/lib/site-packages/boto/mturk/__init__.py deleted file mode 100644 index 449bd162a8..0000000000 --- a/awx/lib/site-packages/boto/mturk/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - diff --git a/awx/lib/site-packages/boto/mturk/connection.py b/awx/lib/site-packages/boto/mturk/connection.py deleted file mode 100644 index 4f2a23faf1..0000000000 --- a/awx/lib/site-packages/boto/mturk/connection.py +++ /dev/null @@ -1,1052 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import xml.sax -import datetime -import itertools - -from boto import handler -from boto import config -from boto.mturk.price import Price -import boto.mturk.notification -from boto.connection import AWSQueryConnection -from boto.exception import EC2ResponseError -from boto.resultset import ResultSet -from boto.mturk.question import QuestionForm, ExternalQuestion, HTMLQuestion - - -class MTurkRequestError(EC2ResponseError): - "Error for MTurk Requests" - # todo: subclass from an abstract parent of EC2ResponseError - - -class MTurkConnection(AWSQueryConnection): - - APIVersion = '2012-03-25' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, - host=None, debug=0, - https_connection_factory=None, security_token=None, - profile_name=None): - if not host: - if config.has_option('MTurk', 'sandbox') and config.get('MTurk', 'sandbox') == 'True': - host = 'mechanicalturk.sandbox.amazonaws.com' - else: - host = 'mechanicalturk.amazonaws.com' - self.debug = debug - - super(MTurkConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, host, debug, - https_connection_factory, - security_token=security_token, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['mturk'] - - def get_account_balance(self): - """ - """ - params = {} - return self._process_request('GetAccountBalance', params, - [('AvailableBalance', Price), - ('OnHoldBalance', Price)]) - - def register_hit_type(self, title, description, reward, duration, - keywords=None, approval_delay=None, qual_req=None): - """ - Register a new HIT Type - title, description are strings - reward is a Price object - duration can be a timedelta, or an object castable to an int - """ - params = dict( - Title=title, - Description=description, - AssignmentDurationInSeconds=self.duration_as_seconds(duration), - ) - params.update(MTurkConnection.get_price_as_price(reward).get_as_params('Reward')) - - if keywords: - params['Keywords'] = self.get_keywords_as_string(keywords) - - if approval_delay is not None: - d = self.duration_as_seconds(approval_delay) - params['AutoApprovalDelayInSeconds'] = d - - if qual_req is not None: - params.update(qual_req.get_as_params()) - - return self._process_request('RegisterHITType', params, - [('HITTypeId', HITTypeId)]) - - def set_email_notification(self, hit_type, email, event_types=None): - """ - Performs a SetHITTypeNotification operation to set email - notification for a specified HIT type - """ - return self._set_notification(hit_type, 'Email', email, - 'SetHITTypeNotification', event_types) - - def set_rest_notification(self, hit_type, url, event_types=None): - """ - Performs a SetHITTypeNotification operation to set REST notification - for a specified HIT type - """ - return self._set_notification(hit_type, 'REST', url, - 'SetHITTypeNotification', event_types) - - def set_sqs_notification(self, hit_type, queue_url, event_types=None): - """ - Performs a SetHITTypeNotification operation so set SQS notification - for a specified HIT type. Queue URL is of form: - https://queue.amazonaws.com/<CUSTOMER_ID>/<QUEUE_NAME> and can be - found when looking at the details for a Queue in the AWS Console - """ - return self._set_notification(hit_type, "SQS", queue_url, - 'SetHITTypeNotification', event_types) - - def send_test_event_notification(self, hit_type, url, - event_types=None, - test_event_type='Ping'): - """ - Performs a SendTestEventNotification operation with REST notification - for a specified HIT type - """ - return self._set_notification(hit_type, 'REST', url, - 'SendTestEventNotification', - event_types, test_event_type) - - def _set_notification(self, hit_type, transport, - destination, request_type, - event_types=None, test_event_type=None): - """ - Common operation to set notification or send a test event - notification for a specified HIT type - """ - params = {'HITTypeId': hit_type} - - # from the Developer Guide: - # The 'Active' parameter is optional. If omitted, the active status of - # the HIT type's notification specification is unchanged. All HIT types - # begin with their notification specifications in the "inactive" status. - notification_params = {'Destination': destination, - 'Transport': transport, - 'Version': boto.mturk.notification.NotificationMessage.NOTIFICATION_VERSION, - 'Active': True, - } - - # add specific event types if required - if event_types: - self.build_list_params(notification_params, event_types, - 'EventType') - - # Set up dict of 'Notification.1.Transport' etc. values - notification_rest_params = {} - num = 1 - for key in notification_params: - notification_rest_params['Notification.%d.%s' % (num, key)] = notification_params[key] - - # Update main params dict - params.update(notification_rest_params) - - # If test notification, specify the notification type to be tested - if test_event_type: - params.update({'TestEventType': test_event_type}) - - # Execute operation - return self._process_request(request_type, params) - - def create_hit(self, hit_type=None, question=None, hit_layout=None, - lifetime=datetime.timedelta(days=7), - max_assignments=1, - title=None, description=None, keywords=None, - reward=None, duration=datetime.timedelta(days=7), - approval_delay=None, annotation=None, - questions=None, qualifications=None, - layout_params=None, response_groups=None): - """ - Creates a new HIT. - Returns a ResultSet - See: http://docs.amazonwebservices.com/AWSMechTurk/2012-03-25/AWSMturkAPI/ApiReference_CreateHITOperation.html - """ - - # Handle basic required arguments and set up params dict - params = {'LifetimeInSeconds': - self.duration_as_seconds(lifetime), - 'MaxAssignments': max_assignments, - } - - # handle single or multiple questions or layouts - neither = question is None and questions is None - if hit_layout is None: - both = question is not None and questions is not None - if neither or both: - raise ValueError("Must specify question (single Question instance) or questions (list or QuestionForm instance), but not both") - if question: - questions = [question] - question_param = QuestionForm(questions) - if isinstance(question, QuestionForm): - question_param = question - elif isinstance(question, ExternalQuestion): - question_param = question - elif isinstance(question, HTMLQuestion): - question_param = question - params['Question'] = question_param.get_as_xml() - else: - if not neither: - raise ValueError("Must not specify question (single Question instance) or questions (list or QuestionForm instance) when specifying hit_layout") - params['HITLayoutId'] = hit_layout - if layout_params: - params.update(layout_params.get_as_params()) - - # if hit type specified then add it - # else add the additional required parameters - if hit_type: - params['HITTypeId'] = hit_type - else: - # Handle keywords - final_keywords = MTurkConnection.get_keywords_as_string(keywords) - - # Handle price argument - final_price = MTurkConnection.get_price_as_price(reward) - - final_duration = self.duration_as_seconds(duration) - - additional_params = dict( - Title=title, - Description=description, - Keywords=final_keywords, - AssignmentDurationInSeconds=final_duration, - ) - additional_params.update(final_price.get_as_params('Reward')) - - if approval_delay is not None: - d = self.duration_as_seconds(approval_delay) - additional_params['AutoApprovalDelayInSeconds'] = d - - # add these params to the others - params.update(additional_params) - - # add the annotation if specified - if annotation is not None: - params['RequesterAnnotation'] = annotation - - # Add the Qualifications if specified - if qualifications is not None: - params.update(qualifications.get_as_params()) - - # Handle optional response groups argument - if response_groups: - self.build_list_params(params, response_groups, 'ResponseGroup') - - # Submit - return self._process_request('CreateHIT', params, [('HIT', HIT)]) - - def change_hit_type_of_hit(self, hit_id, hit_type): - """ - Change the HIT type of an existing HIT. Note that the reward associated - with the new HIT type must match the reward of the current HIT type in - order for the operation to be valid. - - :type hit_id: str - :type hit_type: str - """ - params = {'HITId': hit_id, - 'HITTypeId': hit_type} - - return self._process_request('ChangeHITTypeOfHIT', params) - - def get_reviewable_hits(self, hit_type=None, status='Reviewable', - sort_by='Expiration', sort_direction='Ascending', - page_size=10, page_number=1): - """ - Retrieve the HITs that have a status of Reviewable, or HITs that - have a status of Reviewing, and that belong to the Requester - calling the operation. - """ - params = {'Status': status, - 'SortProperty': sort_by, - 'SortDirection': sort_direction, - 'PageSize': page_size, - 'PageNumber': page_number} - - # Handle optional hit_type argument - if hit_type is not None: - params.update({'HITTypeId': hit_type}) - - return self._process_request('GetReviewableHITs', params, - [('HIT', HIT)]) - - @staticmethod - def _get_pages(page_size, total_records): - """ - Given a page size (records per page) and a total number of - records, return the page numbers to be retrieved. - """ - pages = total_records / page_size + bool(total_records % page_size) - return list(range(1, pages + 1)) - - def get_all_hits(self): - """ - Return all of a Requester's HITs - - Despite what search_hits says, it does not return all hits, but - instead returns a page of hits. This method will pull the hits - from the server 100 at a time, but will yield the results - iteratively, so subsequent requests are made on demand. - """ - page_size = 100 - search_rs = self.search_hits(page_size=page_size) - total_records = int(search_rs.TotalNumResults) - get_page_hits = lambda page: self.search_hits(page_size=page_size, page_number=page) - page_nums = self._get_pages(page_size, total_records) - hit_sets = itertools.imap(get_page_hits, page_nums) - return itertools.chain.from_iterable(hit_sets) - - def search_hits(self, sort_by='CreationTime', sort_direction='Ascending', - page_size=10, page_number=1, response_groups=None): - """ - Return a page of a Requester's HITs, on behalf of the Requester. - The operation returns HITs of any status, except for HITs that - have been disposed with the DisposeHIT operation. - Note: - The SearchHITs operation does not accept any search parameters - that filter the results. - """ - params = {'SortProperty': sort_by, - 'SortDirection': sort_direction, - 'PageSize': page_size, - 'PageNumber': page_number} - # Handle optional response groups argument - if response_groups: - self.build_list_params(params, response_groups, 'ResponseGroup') - - return self._process_request('SearchHITs', params, [('HIT', HIT)]) - - def get_assignment(self, assignment_id, response_groups=None): - """ - Retrieves an assignment using the assignment's ID. Requesters can only - retrieve their own assignments, and only assignments whose related HIT - has not been disposed. - - The returned ResultSet will have the following attributes: - - Request - This element is present only if the Request ResponseGroup - is specified. - Assignment - The assignment. The response includes one Assignment object. - HIT - The HIT associated with this assignment. The response - includes one HIT object. - - """ - - params = {'AssignmentId': assignment_id} - - # Handle optional response groups argument - if response_groups: - self.build_list_params(params, response_groups, 'ResponseGroup') - - return self._process_request('GetAssignment', params, - [('Assignment', Assignment), - ('HIT', HIT)]) - - def get_assignments(self, hit_id, status=None, - sort_by='SubmitTime', sort_direction='Ascending', - page_size=10, page_number=1, response_groups=None): - """ - Retrieves completed assignments for a HIT. - Use this operation to retrieve the results for a HIT. - - The returned ResultSet will have the following attributes: - - NumResults - The number of assignments on the page in the filtered results - list, equivalent to the number of assignments being returned - by this call. - A non-negative integer, as a string. - PageNumber - The number of the page in the filtered results list being - returned. - A positive integer, as a string. - TotalNumResults - The total number of HITs in the filtered results list based - on this call. - A non-negative integer, as a string. - - The ResultSet will contain zero or more Assignment objects - - """ - params = {'HITId': hit_id, - 'SortProperty': sort_by, - 'SortDirection': sort_direction, - 'PageSize': page_size, - 'PageNumber': page_number} - - if status is not None: - params['AssignmentStatus'] = status - - # Handle optional response groups argument - if response_groups: - self.build_list_params(params, response_groups, 'ResponseGroup') - - return self._process_request('GetAssignmentsForHIT', params, - [('Assignment', Assignment)]) - - def approve_assignment(self, assignment_id, feedback=None): - """ - """ - params = {'AssignmentId': assignment_id} - if feedback: - params['RequesterFeedback'] = feedback - return self._process_request('ApproveAssignment', params) - - def reject_assignment(self, assignment_id, feedback=None): - """ - """ - params = {'AssignmentId': assignment_id} - if feedback: - params['RequesterFeedback'] = feedback - return self._process_request('RejectAssignment', params) - - def approve_rejected_assignment(self, assignment_id, feedback=None): - """ - """ - params = {'AssignmentId': assignment_id} - if feedback: - params['RequesterFeedback'] = feedback - return self._process_request('ApproveRejectedAssignment', params) - - def get_file_upload_url(self, assignment_id, question_identifier): - """ - Generates and returns a temporary URL to an uploaded file. The - temporary URL is used to retrieve the file as an answer to a - FileUploadAnswer question, it is valid for 60 seconds. - - Will have a FileUploadURL attribute as per the API Reference. - """ - - params = {'AssignmentId': assignment_id, - 'QuestionIdentifier': question_identifier} - - return self._process_request('GetFileUploadURL', params, - [('FileUploadURL', FileUploadURL)]) - - def get_hit(self, hit_id, response_groups=None): - """ - """ - params = {'HITId': hit_id} - # Handle optional response groups argument - if response_groups: - self.build_list_params(params, response_groups, 'ResponseGroup') - - return self._process_request('GetHIT', params, [('HIT', HIT)]) - - def set_reviewing(self, hit_id, revert=None): - """ - Update a HIT with a status of Reviewable to have a status of Reviewing, - or reverts a Reviewing HIT back to the Reviewable status. - - Only HITs with a status of Reviewable can be updated with a status of - Reviewing. Similarly, only Reviewing HITs can be reverted back to a - status of Reviewable. - """ - params = {'HITId': hit_id} - if revert: - params['Revert'] = revert - return self._process_request('SetHITAsReviewing', params) - - def disable_hit(self, hit_id, response_groups=None): - """ - Remove a HIT from the Mechanical Turk marketplace, approves all - submitted assignments that have not already been approved or rejected, - and disposes of the HIT and all assignment data. - - Assignments for the HIT that have already been submitted, but not yet - approved or rejected, will be automatically approved. Assignments in - progress at the time of the call to DisableHIT will be approved once - the assignments are submitted. You will be charged for approval of - these assignments. DisableHIT completely disposes of the HIT and - all submitted assignment data. Assignment results data cannot be - retrieved for a HIT that has been disposed. - - It is not possible to re-enable a HIT once it has been disabled. - To make the work from a disabled HIT available again, create a new HIT. - """ - params = {'HITId': hit_id} - # Handle optional response groups argument - if response_groups: - self.build_list_params(params, response_groups, 'ResponseGroup') - - return self._process_request('DisableHIT', params) - - def dispose_hit(self, hit_id): - """ - Dispose of a HIT that is no longer needed. - - Only HITs in the "reviewable" state, with all submitted - assignments approved or rejected, can be disposed. A Requester - can call GetReviewableHITs to determine which HITs are - reviewable, then call GetAssignmentsForHIT to retrieve the - assignments. Disposing of a HIT removes the HIT from the - results of a call to GetReviewableHITs. """ - params = {'HITId': hit_id} - return self._process_request('DisposeHIT', params) - - def expire_hit(self, hit_id): - - """ - Expire a HIT that is no longer needed. - - The effect is identical to the HIT expiring on its own. The - HIT no longer appears on the Mechanical Turk web site, and no - new Workers are allowed to accept the HIT. Workers who have - accepted the HIT prior to expiration are allowed to complete - it or return it, or allow the assignment duration to elapse - (abandon the HIT). Once all remaining assignments have been - submitted, the expired HIT becomes"reviewable", and will be - returned by a call to GetReviewableHITs. - """ - params = {'HITId': hit_id} - return self._process_request('ForceExpireHIT', params) - - def extend_hit(self, hit_id, assignments_increment=None, - expiration_increment=None): - """ - Increase the maximum number of assignments, or extend the - expiration date, of an existing HIT. - - NOTE: If a HIT has a status of Reviewable and the HIT is - extended to make it Available, the HIT will not be returned by - GetReviewableHITs, and its submitted assignments will not be - returned by GetAssignmentsForHIT, until the HIT is Reviewable - again. Assignment auto-approval will still happen on its - original schedule, even if the HIT has been extended. Be sure - to retrieve and approve (or reject) submitted assignments - before extending the HIT, if so desired. - """ - # must provide assignment *or* expiration increment - if (assignments_increment is None and expiration_increment is None) or \ - (assignments_increment is not None and expiration_increment is not None): - raise ValueError("Must specify either assignments_increment or expiration_increment, but not both") - - params = {'HITId': hit_id} - if assignments_increment: - params['MaxAssignmentsIncrement'] = assignments_increment - if expiration_increment: - params['ExpirationIncrementInSeconds'] = expiration_increment - - return self._process_request('ExtendHIT', params) - - def get_help(self, about, help_type='Operation'): - """ - Return information about the Mechanical Turk Service - operations and response group NOTE - this is basically useless - as it just returns the URL of the documentation - - help_type: either 'Operation' or 'ResponseGroup' - """ - params = {'About': about, 'HelpType': help_type} - return self._process_request('Help', params) - - def grant_bonus(self, worker_id, assignment_id, bonus_price, reason): - """ - Issues a payment of money from your account to a Worker. To - be eligible for a bonus, the Worker must have submitted - results for one of your HITs, and have had those results - approved or rejected. This payment happens separately from the - reward you pay to the Worker when you approve the Worker's - assignment. The Bonus must be passed in as an instance of the - Price object. - """ - params = bonus_price.get_as_params('BonusAmount', 1) - params['WorkerId'] = worker_id - params['AssignmentId'] = assignment_id - params['Reason'] = reason - - return self._process_request('GrantBonus', params) - - def block_worker(self, worker_id, reason): - """ - Block a worker from working on my tasks. - """ - params = {'WorkerId': worker_id, 'Reason': reason} - - return self._process_request('BlockWorker', params) - - def unblock_worker(self, worker_id, reason): - """ - Unblock a worker from working on my tasks. - """ - params = {'WorkerId': worker_id, 'Reason': reason} - - return self._process_request('UnblockWorker', params) - - def notify_workers(self, worker_ids, subject, message_text): - """ - Send a text message to workers. - """ - params = {'Subject': subject, - 'MessageText': message_text} - self.build_list_params(params, worker_ids, 'WorkerId') - - return self._process_request('NotifyWorkers', params) - - def create_qualification_type(self, - name, - description, - status, - keywords=None, - retry_delay=None, - test=None, - answer_key=None, - answer_key_xml=None, - test_duration=None, - auto_granted=False, - auto_granted_value=1): - """ - Create a new Qualification Type. - - name: This will be visible to workers and must be unique for a - given requester. - - description: description shown to workers. Max 2000 characters. - - status: 'Active' or 'Inactive' - - keywords: list of keyword strings or comma separated string. - Max length of 1000 characters when concatenated with commas. - - retry_delay: number of seconds after requesting a - qualification the worker must wait before they can ask again. - If not specified, workers can only request this qualification - once. - - test: a QuestionForm - - answer_key: an XML string of your answer key, for automatically - scored qualification tests. - (Consider implementing an AnswerKey class for this to support.) - - test_duration: the number of seconds a worker has to complete the test. - - auto_granted: if True, requests for the Qualification are granted - immediately. Can't coexist with a test. - - auto_granted_value: auto_granted qualifications are given this value. - - """ - - params = {'Name': name, - 'Description': description, - 'QualificationTypeStatus': status, - } - if retry_delay is not None: - params['RetryDelayInSeconds'] = retry_delay - - if test is not None: - assert(isinstance(test, QuestionForm)) - assert(test_duration is not None) - params['Test'] = test.get_as_xml() - - if test_duration is not None: - params['TestDurationInSeconds'] = test_duration - - if answer_key is not None: - if isinstance(answer_key, basestring): - params['AnswerKey'] = answer_key # xml - else: - raise TypeError - # Eventually someone will write an AnswerKey class. - - if auto_granted: - assert(test is None) - params['AutoGranted'] = True - params['AutoGrantedValue'] = auto_granted_value - - if keywords: - params['Keywords'] = self.get_keywords_as_string(keywords) - - return self._process_request('CreateQualificationType', params, - [('QualificationType', - QualificationType)]) - - def get_qualification_type(self, qualification_type_id): - params = {'QualificationTypeId': qualification_type_id } - return self._process_request('GetQualificationType', params, - [('QualificationType', QualificationType)]) - - def get_all_qualifications_for_qual_type(self, qualification_type_id): - page_size = 100 - search_qual = self.get_qualifications_for_qualification_type(qualification_type_id) - total_records = int(search_qual.TotalNumResults) - get_page_quals = lambda page: self.get_qualifications_for_qualification_type(qualification_type_id = qualification_type_id, page_size=page_size, page_number = page) - page_nums = self._get_pages(page_size, total_records) - qual_sets = itertools.imap(get_page_quals, page_nums) - return itertools.chain.from_iterable(qual_sets) - - def get_qualifications_for_qualification_type(self, qualification_type_id, page_size=100, page_number = 1): - params = {'QualificationTypeId': qualification_type_id, - 'PageSize': page_size, - 'PageNumber': page_number} - return self._process_request('GetQualificationsForQualificationType', params, - [('Qualification', Qualification)]) - - def update_qualification_type(self, qualification_type_id, - description=None, - status=None, - retry_delay=None, - test=None, - answer_key=None, - test_duration=None, - auto_granted=None, - auto_granted_value=None): - - params = {'QualificationTypeId': qualification_type_id} - - if description is not None: - params['Description'] = description - - if status is not None: - params['QualificationTypeStatus'] = status - - if retry_delay is not None: - params['RetryDelayInSeconds'] = retry_delay - - if test is not None: - assert(isinstance(test, QuestionForm)) - params['Test'] = test.get_as_xml() - - if test_duration is not None: - params['TestDurationInSeconds'] = test_duration - - if answer_key is not None: - if isinstance(answer_key, basestring): - params['AnswerKey'] = answer_key # xml - else: - raise TypeError - # Eventually someone will write an AnswerKey class. - - if auto_granted is not None: - params['AutoGranted'] = auto_granted - - if auto_granted_value is not None: - params['AutoGrantedValue'] = auto_granted_value - - return self._process_request('UpdateQualificationType', params, - [('QualificationType', QualificationType)]) - - def dispose_qualification_type(self, qualification_type_id): - """TODO: Document.""" - params = {'QualificationTypeId': qualification_type_id} - return self._process_request('DisposeQualificationType', params) - - def search_qualification_types(self, query=None, sort_by='Name', - sort_direction='Ascending', page_size=10, - page_number=1, must_be_requestable=True, - must_be_owned_by_caller=True): - """TODO: Document.""" - params = {'Query': query, - 'SortProperty': sort_by, - 'SortDirection': sort_direction, - 'PageSize': page_size, - 'PageNumber': page_number, - 'MustBeRequestable': must_be_requestable, - 'MustBeOwnedByCaller': must_be_owned_by_caller} - return self._process_request('SearchQualificationTypes', params, - [('QualificationType', QualificationType)]) - - def get_qualification_requests(self, qualification_type_id, - sort_by='Expiration', - sort_direction='Ascending', page_size=10, - page_number=1): - """TODO: Document.""" - params = {'QualificationTypeId': qualification_type_id, - 'SortProperty': sort_by, - 'SortDirection': sort_direction, - 'PageSize': page_size, - 'PageNumber': page_number} - return self._process_request('GetQualificationRequests', params, - [('QualificationRequest', QualificationRequest)]) - - def grant_qualification(self, qualification_request_id, integer_value=1): - """TODO: Document.""" - params = {'QualificationRequestId': qualification_request_id, - 'IntegerValue': integer_value} - return self._process_request('GrantQualification', params) - - def revoke_qualification(self, subject_id, qualification_type_id, - reason=None): - """TODO: Document.""" - params = {'SubjectId': subject_id, - 'QualificationTypeId': qualification_type_id, - 'Reason': reason} - return self._process_request('RevokeQualification', params) - - def assign_qualification(self, qualification_type_id, worker_id, - value=1, send_notification=True): - params = {'QualificationTypeId': qualification_type_id, - 'WorkerId' : worker_id, - 'IntegerValue' : value, - 'SendNotification' : send_notification} - return self._process_request('AssignQualification', params) - - def get_qualification_score(self, qualification_type_id, worker_id): - """TODO: Document.""" - params = {'QualificationTypeId' : qualification_type_id, - 'SubjectId' : worker_id} - return self._process_request('GetQualificationScore', params, - [('Qualification', Qualification)]) - - def update_qualification_score(self, qualification_type_id, worker_id, - value): - """TODO: Document.""" - params = {'QualificationTypeId' : qualification_type_id, - 'SubjectId' : worker_id, - 'IntegerValue' : value} - return self._process_request('UpdateQualificationScore', params) - - def _process_request(self, request_type, params, marker_elems=None): - """ - Helper to process the xml response from AWS - """ - params['Operation'] = request_type - response = self.make_request(None, params, verb='POST') - return self._process_response(response, marker_elems) - - def _process_response(self, response, marker_elems=None): - """ - Helper to process the xml response from AWS - """ - body = response.read() - if self.debug == 2: - print(body) - if '<Errors>' not in body: - rs = ResultSet(marker_elems) - h = handler.XmlHandler(rs, self) - xml.sax.parseString(body, h) - return rs - else: - raise MTurkRequestError(response.status, response.reason, body) - - @staticmethod - def get_keywords_as_string(keywords): - """ - Returns a comma+space-separated string of keywords from either - a list or a string - """ - if isinstance(keywords, list): - keywords = ', '.join(keywords) - if isinstance(keywords, str): - final_keywords = keywords - elif isinstance(keywords, unicode): - final_keywords = keywords.encode('utf-8') - elif keywords is None: - final_keywords = "" - else: - raise TypeError("keywords argument must be a string or a list of strings; got a %s" % type(keywords)) - return final_keywords - - @staticmethod - def get_price_as_price(reward): - """ - Returns a Price data structure from either a float or a Price - """ - if isinstance(reward, Price): - final_price = reward - else: - final_price = Price(reward) - return final_price - - @staticmethod - def duration_as_seconds(duration): - if isinstance(duration, datetime.timedelta): - duration = duration.days * 86400 + duration.seconds - try: - duration = int(duration) - except TypeError: - raise TypeError("Duration must be a timedelta or int-castable, got %s" % type(duration)) - return duration - - -class BaseAutoResultElement(object): - """ - Base class to automatically add attributes when parsing XML - """ - def __init__(self, connection): - pass - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - -class HIT(BaseAutoResultElement): - """ - Class to extract a HIT structure from a response (used in ResultSet) - - Will have attributes named as per the Developer Guide, - e.g. HITId, HITTypeId, CreationTime - """ - - # property helper to determine if HIT has expired - def _has_expired(self): - """ Has this HIT expired yet? """ - expired = False - if hasattr(self, 'Expiration'): - now = datetime.datetime.utcnow() - expiration = datetime.datetime.strptime(self.Expiration, '%Y-%m-%dT%H:%M:%SZ') - expired = (now >= expiration) - else: - raise ValueError("ERROR: Request for expired property, but no Expiration in HIT!") - return expired - - # are we there yet? - expired = property(_has_expired) - - -class FileUploadURL(BaseAutoResultElement): - """ - Class to extract an FileUploadURL structure from a response - """ - - pass - - -class HITTypeId(BaseAutoResultElement): - """ - Class to extract an HITTypeId structure from a response - """ - - pass - - -class Qualification(BaseAutoResultElement): - """ - Class to extract an Qualification structure from a response (used in - ResultSet) - - Will have attributes named as per the Developer Guide such as - QualificationTypeId, IntegerValue. Does not seem to contain GrantTime. - """ - - pass - - -class QualificationType(BaseAutoResultElement): - """ - Class to extract an QualificationType structure from a response (used in - ResultSet) - - Will have attributes named as per the Developer Guide, - e.g. QualificationTypeId, CreationTime, Name, etc - """ - - pass - - -class QualificationRequest(BaseAutoResultElement): - """ - Class to extract an QualificationRequest structure from a response (used in - ResultSet) - - Will have attributes named as per the Developer Guide, - e.g. QualificationRequestId, QualificationTypeId, SubjectId, etc - """ - - def __init__(self, connection): - super(QualificationRequest, self).__init__(connection) - self.answers = [] - - def endElement(self, name, value, connection): - # the answer consists of embedded XML, so it needs to be parsed independantly - if name == 'Answer': - answer_rs = ResultSet([('Answer', QuestionFormAnswer)]) - h = handler.XmlHandler(answer_rs, connection) - value = connection.get_utf8_value(value) - xml.sax.parseString(value, h) - self.answers.append(answer_rs) - else: - super(QualificationRequest, self).endElement(name, value, connection) - - -class Assignment(BaseAutoResultElement): - """ - Class to extract an Assignment structure from a response (used in - ResultSet) - - Will have attributes named as per the Developer Guide, - e.g. AssignmentId, WorkerId, HITId, Answer, etc - """ - - def __init__(self, connection): - super(Assignment, self).__init__(connection) - self.answers = [] - - def endElement(self, name, value, connection): - # the answer consists of embedded XML, so it needs to be parsed independantly - if name == 'Answer': - answer_rs = ResultSet([('Answer', QuestionFormAnswer)]) - h = handler.XmlHandler(answer_rs, connection) - value = connection.get_utf8_value(value) - xml.sax.parseString(value, h) - self.answers.append(answer_rs) - else: - super(Assignment, self).endElement(name, value, connection) - - -class QuestionFormAnswer(BaseAutoResultElement): - """ - Class to extract Answers from inside the embedded XML - QuestionFormAnswers element inside the Answer element which is - part of the Assignment and QualificationRequest structures - - A QuestionFormAnswers element contains an Answer element for each - question in the HIT or Qualification test for which the Worker - provided an answer. Each Answer contains a QuestionIdentifier - element whose value corresponds to the QuestionIdentifier of a - Question in the QuestionForm. See the QuestionForm data structure - for more information about questions and answer specifications. - - If the question expects a free-text answer, the Answer element - contains a FreeText element. This element contains the Worker's - answer - - *NOTE* - currently really only supports free-text and selection answers - """ - - def __init__(self, connection): - super(QuestionFormAnswer, self).__init__(connection) - self.fields = [] - self.qid = None - - def endElement(self, name, value, connection): - if name == 'QuestionIdentifier': - self.qid = value - elif name in ['FreeText', 'SelectionIdentifier', 'OtherSelectionText'] and self.qid: - self.fields.append(value) diff --git a/awx/lib/site-packages/boto/mturk/layoutparam.py b/awx/lib/site-packages/boto/mturk/layoutparam.py deleted file mode 100644 index de7989554e..0000000000 --- a/awx/lib/site-packages/boto/mturk/layoutparam.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2008 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class LayoutParameters(object): - - def __init__(self, layoutParameters=None): - if layoutParameters is None: - layoutParameters = [] - self.layoutParameters = layoutParameters - - def add(self, req): - self.layoutParameters.append(req) - - def get_as_params(self): - params = {} - assert(len(self.layoutParameters) <= 25) - for n, layoutParameter in enumerate(self.layoutParameters): - kv = layoutParameter.get_as_params() - for key in kv: - params['HITLayoutParameter.%s.%s' % ((n+1), key) ] = kv[key] - return params - -class LayoutParameter(object): - """ - Representation of a single HIT layout parameter - """ - - def __init__(self, name, value): - self.name = name - self.value = value - - def get_as_params(self): - params = { - "Name": self.name, - "Value": self.value, - } - return params diff --git a/awx/lib/site-packages/boto/mturk/notification.py b/awx/lib/site-packages/boto/mturk/notification.py deleted file mode 100644 index 118daaab95..0000000000 --- a/awx/lib/site-packages/boto/mturk/notification.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Provides NotificationMessage and Event classes, with utility methods, for -implementations of the Mechanical Turk Notification API. -""" - -import hmac -try: - from hashlib import sha1 as sha -except ImportError: - import sha -import base64 -import re - -class NotificationMessage(object): - - NOTIFICATION_WSDL = "http://mechanicalturk.amazonaws.com/AWSMechanicalTurk/2006-05-05/AWSMechanicalTurkRequesterNotification.wsdl" - NOTIFICATION_VERSION = '2006-05-05' - - SERVICE_NAME = "AWSMechanicalTurkRequesterNotification" - OPERATION_NAME = "Notify" - - EVENT_PATTERN = r"Event\.(?P<n>\d+)\.(?P<param>\w+)" - EVENT_RE = re.compile(EVENT_PATTERN) - - def __init__(self, d): - """ - Constructor; expects parameter d to be a dict of string parameters from a REST transport notification message - """ - self.signature = d['Signature'] # vH6ZbE0NhkF/hfNyxz2OgmzXYKs= - self.timestamp = d['Timestamp'] # 2006-05-23T23:22:30Z - self.version = d['Version'] # 2006-05-05 - assert d['method'] == NotificationMessage.OPERATION_NAME, "Method should be '%s'" % NotificationMessage.OPERATION_NAME - - # Build Events - self.events = [] - events_dict = {} - if 'Event' in d: - # TurboGears surprised me by 'doing the right thing' and making { 'Event': { '1': { 'EventType': ... } } } etc. - events_dict = d['Event'] - else: - for k in d: - v = d[k] - if k.startswith('Event.'): - ed = NotificationMessage.EVENT_RE.search(k).groupdict() - n = int(ed['n']) - param = str(ed['param']) - if n not in events_dict: - events_dict[n] = {} - events_dict[n][param] = v - for n in events_dict: - self.events.append(Event(events_dict[n])) - - def verify(self, secret_key): - """ - Verifies the authenticity of a notification message. - - TODO: This is doing a form of authentication and - this functionality should really be merged - with the pluggable authentication mechanism - at some point. - """ - verification_input = NotificationMessage.SERVICE_NAME - verification_input += NotificationMessage.OPERATION_NAME - verification_input += self.timestamp - h = hmac.new(key=secret_key, digestmod=sha) - h.update(verification_input) - signature_calc = base64.b64encode(h.digest()) - return self.signature == signature_calc - -class Event(object): - def __init__(self, d): - self.event_type = d['EventType'] - self.event_time_str = d['EventTime'] - self.hit_type = d['HITTypeId'] - self.hit_id = d['HITId'] - if 'AssignmentId' in d: # Not present in all event types - self.assignment_id = d['AssignmentId'] - - #TODO: build self.event_time datetime from string self.event_time_str - - def __repr__(self): - return "<boto.mturk.notification.Event: %s for HIT # %s>" % (self.event_type, self.hit_id) diff --git a/awx/lib/site-packages/boto/mturk/price.py b/awx/lib/site-packages/boto/mturk/price.py deleted file mode 100644 index 8e194e422e..0000000000 --- a/awx/lib/site-packages/boto/mturk/price.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class Price(object): - - def __init__(self, amount=0.0, currency_code='USD'): - self.amount = amount - self.currency_code = currency_code - self.formatted_price = '' - - def __repr__(self): - if self.formatted_price: - return self.formatted_price - else: - return str(self.amount) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Amount': - self.amount = float(value) - elif name == 'CurrencyCode': - self.currency_code = value - elif name == 'FormattedPrice': - self.formatted_price = value - - def get_as_params(self, label, ord=1): - return {'%s.%d.Amount'%(label, ord) : str(self.amount), - '%s.%d.CurrencyCode'%(label, ord) : self.currency_code} diff --git a/awx/lib/site-packages/boto/mturk/qualification.py b/awx/lib/site-packages/boto/mturk/qualification.py deleted file mode 100644 index 4fc230f9df..0000000000 --- a/awx/lib/site-packages/boto/mturk/qualification.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright (c) 2008 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class Qualifications(object): - - def __init__(self, requirements=None): - if requirements is None: - requirements = [] - self.requirements = requirements - - def add(self, req): - self.requirements.append(req) - - def get_as_params(self): - params = {} - assert(len(self.requirements) <= 10) - for n, req in enumerate(self.requirements): - reqparams = req.get_as_params() - for rp in reqparams: - params['QualificationRequirement.%s.%s' % ((n+1), rp) ] = reqparams[rp] - return params - - -class Requirement(object): - """ - Representation of a single requirement - """ - - def __init__(self, qualification_type_id, comparator, integer_value=None, required_to_preview=False): - self.qualification_type_id = qualification_type_id - self.comparator = comparator - self.integer_value = integer_value - self.required_to_preview = required_to_preview - - def get_as_params(self): - params = { - "QualificationTypeId": self.qualification_type_id, - "Comparator": self.comparator, - } - if self.comparator != 'Exists' and self.integer_value is not None: - params['IntegerValue'] = self.integer_value - if self.required_to_preview: - params['RequiredToPreview'] = "true" - return params - -class PercentAssignmentsSubmittedRequirement(Requirement): - """ - The percentage of assignments the Worker has submitted, over all assignments the Worker has accepted. The value is an integer between 0 and 100. - """ - - def __init__(self, comparator, integer_value, required_to_preview=False): - super(PercentAssignmentsSubmittedRequirement, self).__init__(qualification_type_id="00000000000000000000", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) - -class PercentAssignmentsAbandonedRequirement(Requirement): - """ - The percentage of assignments the Worker has abandoned (allowed the deadline to elapse), over all assignments the Worker has accepted. The value is an integer between 0 and 100. - """ - - def __init__(self, comparator, integer_value, required_to_preview=False): - super(PercentAssignmentsAbandonedRequirement, self).__init__(qualification_type_id="00000000000000000070", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) - -class PercentAssignmentsReturnedRequirement(Requirement): - """ - The percentage of assignments the Worker has returned, over all assignments the Worker has accepted. The value is an integer between 0 and 100. - """ - - def __init__(self, comparator, integer_value, required_to_preview=False): - super(PercentAssignmentsReturnedRequirement, self).__init__(qualification_type_id="000000000000000000E0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) - -class PercentAssignmentsApprovedRequirement(Requirement): - """ - The percentage of assignments the Worker has submitted that were subsequently approved by the Requester, over all assignments the Worker has submitted. The value is an integer between 0 and 100. - """ - - def __init__(self, comparator, integer_value, required_to_preview=False): - super(PercentAssignmentsApprovedRequirement, self).__init__(qualification_type_id="000000000000000000L0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) - -class PercentAssignmentsRejectedRequirement(Requirement): - """ - The percentage of assignments the Worker has submitted that were subsequently rejected by the Requester, over all assignments the Worker has submitted. The value is an integer between 0 and 100. - """ - - def __init__(self, comparator, integer_value, required_to_preview=False): - super(PercentAssignmentsRejectedRequirement, self).__init__(qualification_type_id="000000000000000000S0", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) - -class NumberHitsApprovedRequirement(Requirement): - """ - Specifies the total number of HITs submitted by a Worker that have been approved. The value is an integer greater than or equal to 0. - """ - - def __init__(self, comparator, integer_value, required_to_preview=False): - super(NumberHitsApprovedRequirement, self).__init__(qualification_type_id="00000000000000000040", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) - -class LocaleRequirement(Requirement): - """ - A Qualification requirement based on the Worker's location. The Worker's location is specified by the Worker to Mechanical Turk when the Worker creates his account. - """ - - def __init__(self, comparator, locale, required_to_preview=False): - super(LocaleRequirement, self).__init__(qualification_type_id="00000000000000000071", comparator=comparator, integer_value=None, required_to_preview=required_to_preview) - self.locale = locale - - def get_as_params(self): - params = { - "QualificationTypeId": self.qualification_type_id, - "Comparator": self.comparator, - 'LocaleValue.Country': self.locale, - } - if self.required_to_preview: - params['RequiredToPreview'] = "true" - return params - -class AdultRequirement(Requirement): - """ - Requires workers to acknowledge that they are over 18 and that they agree to work on potentially offensive content. The value type is boolean, 1 (required), 0 (not required, the default). - """ - - def __init__(self, comparator, integer_value, required_to_preview=False): - super(AdultRequirement, self).__init__(qualification_type_id="00000000000000000060", comparator=comparator, integer_value=integer_value, required_to_preview=required_to_preview) diff --git a/awx/lib/site-packages/boto/mturk/question.py b/awx/lib/site-packages/boto/mturk/question.py deleted file mode 100644 index 293b0782ed..0000000000 --- a/awx/lib/site-packages/boto/mturk/question.py +++ /dev/null @@ -1,455 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import xml.sax.saxutils - -class Question(object): - template = "<Question>%(items)s</Question>" - - def __init__(self, identifier, content, answer_spec, - is_required=False, display_name=None): - # copy all of the parameters into object attributes - self.__dict__.update(vars()) - del self.self - - def get_as_params(self, label='Question'): - return {label: self.get_as_xml()} - - def get_as_xml(self): - items = [ - SimpleField('QuestionIdentifier', self.identifier), - SimpleField('IsRequired', str(self.is_required).lower()), - self.content, - self.answer_spec, - ] - if self.display_name is not None: - items.insert(1, SimpleField('DisplayName', self.display_name)) - items = ''.join(item.get_as_xml() for item in items) - return self.template % vars() - -try: - from lxml import etree - - class ValidatingXML(object): - - def validate(self): - import urllib2 - schema_src_file = urllib2.urlopen(self.schema_url) - schema_doc = etree.parse(schema_src_file) - schema = etree.XMLSchema(schema_doc) - doc = etree.fromstring(self.get_as_xml()) - schema.assertValid(doc) -except ImportError: - class ValidatingXML(object): - - def validate(self): - pass - - -class ExternalQuestion(ValidatingXML): - """ - An object for constructing an External Question. - """ - schema_url = "http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2006-07-14/ExternalQuestion.xsd" - template = '<ExternalQuestion xmlns="%(schema_url)s"><ExternalURL>%%(external_url)s</ExternalURL><FrameHeight>%%(frame_height)s</FrameHeight></ExternalQuestion>' % vars() - - def __init__(self, external_url, frame_height): - self.external_url = xml.sax.saxutils.escape( external_url ) - self.frame_height = frame_height - - def get_as_params(self, label='ExternalQuestion'): - return {label: self.get_as_xml()} - - def get_as_xml(self): - return self.template % vars(self) - - -class XMLTemplate(object): - def get_as_xml(self): - return self.template % vars(self) - - -class SimpleField(XMLTemplate): - """ - A Simple name/value pair that can be easily rendered as XML. - - >>> SimpleField('Text', 'A text string').get_as_xml() - '<Text>A text string</Text>' - """ - template = '<%(field)s>%(value)s</%(field)s>' - - def __init__(self, field, value): - self.field = field - self.value = value - - -class Binary(XMLTemplate): - template = """<Binary><MimeType><Type>%(type)s</Type><SubType>%(subtype)s</SubType></MimeType><DataURL>%(url)s</DataURL><AltText>%(alt_text)s</AltText></Binary>""" - - def __init__(self, type, subtype, url, alt_text): - self.__dict__.update(vars()) - del self.self - - -class List(list): - """A bulleted list suitable for OrderedContent or Overview content""" - def get_as_xml(self): - items = ''.join('<ListItem>%s</ListItem>' % item for item in self) - return '<List>%s</List>' % items - - -class Application(object): - template = "<Application><%(class_)s>%(content)s</%(class_)s></Application>" - parameter_template = "<Name>%(name)s</Name><Value>%(value)s</Value>" - - def __init__(self, width, height, **parameters): - self.width = width - self.height = height - self.parameters = parameters - - def get_inner_content(self, content): - content.append_field('Width', self.width) - content.append_field('Height', self.height) - for name, value in self.parameters.items(): - value = self.parameter_template % vars() - content.append_field('ApplicationParameter', value) - - def get_as_xml(self): - content = OrderedContent() - self.get_inner_content(content) - content = content.get_as_xml() - class_ = self.__class__.__name__ - return self.template % vars() - - -class HTMLQuestion(ValidatingXML): - schema_url = 'http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2011-11-11/HTMLQuestion.xsd' - template = '<HTMLQuestion xmlns=\"%(schema_url)s\"><HTMLContent><![CDATA[<!DOCTYPE html>%%(html_form)s]]></HTMLContent><FrameHeight>%%(frame_height)s</FrameHeight></HTMLQuestion>' % vars() - - def __init__(self, html_form, frame_height): - self.html_form = html_form - self.frame_height = frame_height - - def get_as_params(self, label="HTMLQuestion"): - return {label: self.get_as_xml()} - - def get_as_xml(self): - return self.template % vars(self) - - -class JavaApplet(Application): - def __init__(self, path, filename, *args, **kwargs): - self.path = path - self.filename = filename - super(JavaApplet, self).__init__(*args, **kwargs) - - def get_inner_content(self, content): - content = OrderedContent() - content.append_field('AppletPath', self.path) - content.append_field('AppletFilename', self.filename) - super(JavaApplet, self).get_inner_content(content) - - -class Flash(Application): - def __init__(self, url, *args, **kwargs): - self.url = url - super(Flash, self).__init__(*args, **kwargs) - - def get_inner_content(self, content): - content = OrderedContent() - content.append_field('FlashMovieURL', self.url) - super(Flash, self).get_inner_content(content) - - -class FormattedContent(XMLTemplate): - schema_url = 'http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2006-07-14/FormattedContentXHTMLSubset.xsd' - template = '<FormattedContent><![CDATA[%(content)s]]></FormattedContent>' - - def __init__(self, content): - self.content = content - - -class OrderedContent(list): - - def append_field(self, field, value): - self.append(SimpleField(field, value)) - - def get_as_xml(self): - return ''.join(item.get_as_xml() for item in self) - - -class Overview(OrderedContent): - template = '<Overview>%(content)s</Overview>' - - def get_as_params(self, label='Overview'): - return {label: self.get_as_xml()} - - def get_as_xml(self): - content = super(Overview, self).get_as_xml() - return self.template % vars() - - -class QuestionForm(ValidatingXML, list): - """ - From the AMT API docs: - - The top-most element of the QuestionForm data structure is a - QuestionForm element. This element contains optional Overview - elements and one or more Question elements. There can be any - number of these two element types listed in any order. The - following example structure has an Overview element and a - Question element followed by a second Overview element and - Question element--all within the same QuestionForm. - - :: - - <QuestionForm xmlns="[the QuestionForm schema URL]"> - <Overview> - [...] - </Overview> - <Question> - [...] - </Question> - <Overview> - [...] - </Overview> - <Question> - [...] - </Question> - [...] - </QuestionForm> - - QuestionForm is implemented as a list, so to construct a - QuestionForm, simply append Questions and Overviews (with at least - one Question). - """ - schema_url = "http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2005-10-01/QuestionForm.xsd" - xml_template = """<QuestionForm xmlns="%(schema_url)s">%%(items)s</QuestionForm>""" % vars() - - def is_valid(self): - return ( - any(isinstance(item, Question) for item in self) - and - all(isinstance(item, (Question, Overview)) for item in self) - ) - - def get_as_xml(self): - assert self.is_valid(), "QuestionForm contains invalid elements" - items = ''.join(item.get_as_xml() for item in self) - return self.xml_template % vars() - - -class QuestionContent(OrderedContent): - template = '<QuestionContent>%(content)s</QuestionContent>' - - def get_as_xml(self): - content = super(QuestionContent, self).get_as_xml() - return self.template % vars() - - -class AnswerSpecification(object): - template = '<AnswerSpecification>%(spec)s</AnswerSpecification>' - - def __init__(self, spec): - self.spec = spec - - def get_as_xml(self): - spec = self.spec.get_as_xml() - return self.template % vars() - - -class Constraints(OrderedContent): - template = '<Constraints>%(content)s</Constraints>' - - def get_as_xml(self): - content = super(Constraints, self).get_as_xml() - return self.template % vars() - - -class Constraint(object): - def get_attributes(self): - pairs = zip(self.attribute_names, self.attribute_values) - attrs = ' '.join( - '%s="%d"' % (name, value) - for (name, value) in pairs - if value is not None - ) - return attrs - - def get_as_xml(self): - attrs = self.get_attributes() - return self.template % vars() - - -class NumericConstraint(Constraint): - attribute_names = 'minValue', 'maxValue' - template = '<IsNumeric %(attrs)s />' - - def __init__(self, min_value=None, max_value=None): - self.attribute_values = min_value, max_value - - -class LengthConstraint(Constraint): - attribute_names = 'minLength', 'maxLength' - template = '<Length %(attrs)s />' - - def __init__(self, min_length=None, max_length=None): - self.attribute_values = min_length, max_length - - -class RegExConstraint(Constraint): - attribute_names = 'regex', 'errorText', 'flags' - template = '<AnswerFormatRegex %(attrs)s />' - - def __init__(self, pattern, error_text=None, flags=None): - self.attribute_values = pattern, error_text, flags - - def get_attributes(self): - pairs = zip(self.attribute_names, self.attribute_values) - attrs = ' '.join( - '%s="%s"' % (name, value) - for (name, value) in pairs - if value is not None - ) - return attrs - - -class NumberOfLinesSuggestion(object): - template = '<NumberOfLinesSuggestion>%(num_lines)s</NumberOfLinesSuggestion>' - - def __init__(self, num_lines=1): - self.num_lines = num_lines - - def get_as_xml(self): - num_lines = self.num_lines - return self.template % vars() - - -class FreeTextAnswer(object): - template = '<FreeTextAnswer>%(items)s</FreeTextAnswer>' - - def __init__(self, default=None, constraints=None, num_lines=None): - self.default = default - if constraints is None: - self.constraints = Constraints() - else: - self.constraints = Constraints(constraints) - self.num_lines = num_lines - - def get_as_xml(self): - items = [self.constraints] - if self.default: - items.append(SimpleField('DefaultText', self.default)) - if self.num_lines: - items.append(NumberOfLinesSuggestion(self.num_lines)) - items = ''.join(item.get_as_xml() for item in items) - return self.template % vars() - - -class FileUploadAnswer(object): - template = """<FileUploadAnswer><MaxFileSizeInBytes>%(max_bytes)d</MaxFileSizeInBytes><MinFileSizeInBytes>%(min_bytes)d</MinFileSizeInBytes></FileUploadAnswer>""" - - def __init__(self, min_bytes, max_bytes): - assert 0 <= min_bytes <= max_bytes <= 2 * 10 ** 9 - self.min_bytes = min_bytes - self.max_bytes = max_bytes - - def get_as_xml(self): - return self.template % vars(self) - - -class SelectionAnswer(object): - """ - A class to generate SelectionAnswer XML data structures. - Does not yet implement Binary selection options. - """ - SELECTIONANSWER_XML_TEMPLATE = """<SelectionAnswer>%s%s<Selections>%s</Selections></SelectionAnswer>""" # % (count_xml, style_xml, selections_xml) - SELECTION_XML_TEMPLATE = """<Selection><SelectionIdentifier>%s</SelectionIdentifier>%s</Selection>""" # (identifier, value_xml) - SELECTION_VALUE_XML_TEMPLATE = """<%s>%s</%s>""" # (type, value, type) - STYLE_XML_TEMPLATE = """<StyleSuggestion>%s</StyleSuggestion>""" # (style) - MIN_SELECTION_COUNT_XML_TEMPLATE = """<MinSelectionCount>%s</MinSelectionCount>""" # count - MAX_SELECTION_COUNT_XML_TEMPLATE = """<MaxSelectionCount>%s</MaxSelectionCount>""" # count - ACCEPTED_STYLES = ['radiobutton', 'dropdown', 'checkbox', 'list', 'combobox', 'multichooser'] - OTHER_SELECTION_ELEMENT_NAME = 'OtherSelection' - - def __init__(self, min=1, max=1, style=None, selections=None, type='text', other=False): - - if style is not None: - if style in SelectionAnswer.ACCEPTED_STYLES: - self.style_suggestion = style - else: - raise ValueError("style '%s' not recognized; should be one of %s" % (style, ', '.join(SelectionAnswer.ACCEPTED_STYLES))) - else: - self.style_suggestion = None - - if selections is None: - raise ValueError("SelectionAnswer.__init__(): selections must be a non-empty list of (content, identifier) tuples") - else: - self.selections = selections - - self.min_selections = min - self.max_selections = max - - assert len(selections) >= self.min_selections, "# of selections is less than minimum of %d" % self.min_selections - #assert len(selections) <= self.max_selections, "# of selections exceeds maximum of %d" % self.max_selections - - self.type = type - - self.other = other - - def get_as_xml(self): - if self.type == 'text': - TYPE_TAG = "Text" - elif self.type == 'binary': - TYPE_TAG = "Binary" - else: - raise ValueError("illegal type: %s; must be either 'text' or 'binary'" % str(self.type)) - - # build list of <Selection> elements - selections_xml = "" - for tpl in self.selections: - value_xml = SelectionAnswer.SELECTION_VALUE_XML_TEMPLATE % (TYPE_TAG, tpl[0], TYPE_TAG) - selection_xml = SelectionAnswer.SELECTION_XML_TEMPLATE % (tpl[1], value_xml) - selections_xml += selection_xml - - if self.other: - # add OtherSelection element as xml if available - if hasattr(self.other, 'get_as_xml'): - assert isinstance(self.other, FreeTextAnswer), 'OtherSelection can only be a FreeTextAnswer' - selections_xml += self.other.get_as_xml().replace('FreeTextAnswer', 'OtherSelection') - else: - selections_xml += "<OtherSelection />" - - if self.style_suggestion is not None: - style_xml = SelectionAnswer.STYLE_XML_TEMPLATE % self.style_suggestion - else: - style_xml = "" - - if self.style_suggestion != 'radiobutton': - count_xml = SelectionAnswer.MIN_SELECTION_COUNT_XML_TEMPLATE %self.min_selections - count_xml += SelectionAnswer.MAX_SELECTION_COUNT_XML_TEMPLATE %self.max_selections - else: - count_xml = "" - - ret = SelectionAnswer.SELECTIONANSWER_XML_TEMPLATE % (count_xml, style_xml, selections_xml) - - # return XML - return ret diff --git a/awx/lib/site-packages/boto/mws/__init__.py b/awx/lib/site-packages/boto/mws/__init__.py deleted file mode 100644 index d69b7f08a4..0000000000 --- a/awx/lib/site-packages/boto/mws/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2008, Chris Moyer http://coredumped.org -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# diff --git a/awx/lib/site-packages/boto/mws/connection.py b/awx/lib/site-packages/boto/mws/connection.py deleted file mode 100644 index b372ffb455..0000000000 --- a/awx/lib/site-packages/boto/mws/connection.py +++ /dev/null @@ -1,1168 +0,0 @@ -# Copyright (c) 2012-2014 Andy Davidoff http://www.disruptek.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import xml.sax -import hashlib -import string -import collections -from boto.connection import AWSQueryConnection -from boto.exception import BotoServerError -import boto.mws.exception -import boto.mws.response -from boto.handler import XmlHandler -from boto.compat import filter, map, six, encodebytes - -__all__ = ['MWSConnection'] - -api_version_path = { - 'Feeds': ('2009-01-01', 'Merchant', '/'), - 'Reports': ('2009-01-01', 'Merchant', '/'), - 'Orders': ('2013-09-01', 'SellerId', '/Orders/2013-09-01'), - 'Products': ('2011-10-01', 'SellerId', '/Products/2011-10-01'), - 'Sellers': ('2011-07-01', 'SellerId', '/Sellers/2011-07-01'), - 'Inbound': ('2010-10-01', 'SellerId', - '/FulfillmentInboundShipment/2010-10-01'), - 'Outbound': ('2010-10-01', 'SellerId', - '/FulfillmentOutboundShipment/2010-10-01'), - 'Inventory': ('2010-10-01', 'SellerId', - '/FulfillmentInventory/2010-10-01'), - 'Recommendations': ('2013-04-01', 'SellerId', - '/Recommendations/2013-04-01'), - 'CustomerInfo': ('2014-03-01', 'SellerId', - '/CustomerInformation/2014-03-01'), - 'CartInfo': ('2014-03-01', 'SellerId', - '/CartInformation/2014-03-01'), - 'Subscriptions': ('2013-07-01', 'SellerId', - '/Subscriptions/2013-07-01'), - 'OffAmazonPayments': ('2013-01-01', 'SellerId', - '/OffAmazonPayments/2013-01-01'), -} -content_md5 = lambda c: encodebytes(hashlib.md5(c).digest()).strip() -decorated_attrs = ('action', 'response', 'section', - 'quota', 'restore', 'version') -api_call_map = {} - - -def add_attrs_from(func, to): - for attr in decorated_attrs: - setattr(to, attr, getattr(func, attr, None)) - to.__wrapped__ = func - return to - - -def structured_lists(*fields): - - def decorator(func): - - def wrapper(self, *args, **kw): - for key, acc in [f.split('.') for f in fields]: - if key in kw: - newkey = key + '.' + acc + (acc and '.' or '') - for i in range(len(kw[key])): - kw[newkey + str(i + 1)] = kw[key][i] - kw.pop(key) - return func(self, *args, **kw) - wrapper.__doc__ = "{0}\nLists: {1}".format(func.__doc__, - ', '.join(fields)) - return add_attrs_from(func, to=wrapper) - return decorator - - -def http_body(field): - - def decorator(func): - - def wrapper(*args, **kw): - if any([f not in kw for f in (field, 'content_type')]): - message = "{0} requires {1} and content_type arguments for " \ - "building HTTP body".format(func.action, field) - raise KeyError(message) - kw['body'] = kw.pop(field) - kw['headers'] = { - 'Content-Type': kw.pop('content_type'), - 'Content-MD5': content_md5(kw['body']), - } - return func(*args, **kw) - wrapper.__doc__ = "{0}\nRequired HTTP Body: " \ - "{1}".format(func.__doc__, field) - return add_attrs_from(func, to=wrapper) - return decorator - - -def destructure_object(value, into, prefix, members=False): - if isinstance(value, boto.mws.response.ResponseElement): - destructure_object(value.__dict__, into, prefix, members=members) - elif isinstance(value, collections.Mapping): - for name in value: - if name.startswith('_'): - continue - destructure_object(value[name], into, prefix + '.' + name, - members=members) - elif isinstance(value, six.string_types): - into[prefix] = value - elif isinstance(value, collections.Iterable): - for index, element in enumerate(value): - suffix = (members and '.member.' or '.') + str(index + 1) - destructure_object(element, into, prefix + suffix, - members=members) - elif isinstance(value, bool): - into[prefix] = str(value).lower() - else: - into[prefix] = value - - -def structured_objects(*fields, **kwargs): - - def decorator(func): - - def wrapper(*args, **kw): - members = kwargs.get('members', False) - for field in filter(lambda i: i in kw, fields): - destructure_object(kw.pop(field), kw, field, members=members) - return func(*args, **kw) - wrapper.__doc__ = "{0}\nElement|Iter|Map: {1}\n" \ - "(ResponseElement or anything iterable/dict-like)" \ - .format(func.__doc__, ', '.join(fields)) - return add_attrs_from(func, to=wrapper) - return decorator - - -def requires(*groups): - - def decorator(func): - - def requires(*args, **kw): - hasgroup = lambda group: all(key in kw for key in group) - if 1 != len(list(filter(hasgroup, groups))): - message = ' OR '.join(['+'.join(g) for g in groups]) - message = "{0} requires {1} argument(s)" \ - "".format(func.action, message) - raise KeyError(message) - return func(*args, **kw) - message = ' OR '.join(['+'.join(g) for g in groups]) - requires.__doc__ = "{0}\nRequired: {1}".format(func.__doc__, - message) - return add_attrs_from(func, to=requires) - return decorator - - -def exclusive(*groups): - - def decorator(func): - - def wrapper(*args, **kw): - hasgroup = lambda group: all(key in kw for key in group) - if len(list(filter(hasgroup, groups))) not in (0, 1): - message = ' OR '.join(['+'.join(g) for g in groups]) - message = "{0} requires either {1}" \ - "".format(func.action, message) - raise KeyError(message) - return func(*args, **kw) - message = ' OR '.join(['+'.join(g) for g in groups]) - wrapper.__doc__ = "{0}\nEither: {1}".format(func.__doc__, - message) - return add_attrs_from(func, to=wrapper) - return decorator - - -def dependent(field, *groups): - - def decorator(func): - - def wrapper(*args, **kw): - hasgroup = lambda group: all(key in kw for key in group) - if field in kw and not any(hasgroup(g) for g in groups): - message = ' OR '.join(['+'.join(g) for g in groups]) - message = "{0} argument {1} requires {2}" \ - "".format(func.action, field, message) - raise KeyError(message) - return func(*args, **kw) - message = ' OR '.join(['+'.join(g) for g in groups]) - wrapper.__doc__ = "{0}\n{1} requires: {2}".format(func.__doc__, - field, - message) - return add_attrs_from(func, to=wrapper) - return decorator - - -def requires_some_of(*fields): - - def decorator(func): - - def requires(*args, **kw): - if not any(i in kw for i in fields): - message = "{0} requires at least one of {1} argument(s)" \ - "".format(func.action, ', '.join(fields)) - raise KeyError(message) - return func(*args, **kw) - requires.__doc__ = "{0}\nSome Required: {1}".format(func.__doc__, - ', '.join(fields)) - return add_attrs_from(func, to=requires) - return decorator - - -def boolean_arguments(*fields): - - def decorator(func): - - def wrapper(*args, **kw): - for field in [f for f in fields if isinstance(kw.get(f), bool)]: - kw[field] = str(kw[field]).lower() - return func(*args, **kw) - wrapper.__doc__ = "{0}\nBooleans: {1}".format(func.__doc__, - ', '.join(fields)) - return add_attrs_from(func, to=wrapper) - return decorator - - -def api_action(section, quota, restore, *api): - - def decorator(func, quota=int(quota), restore=float(restore)): - version, accesskey, path = api_version_path[section] - action = ''.join(api or map(str.capitalize, func.__name__.split('_'))) - - def wrapper(self, *args, **kw): - kw.setdefault(accesskey, getattr(self, accesskey, None)) - if kw[accesskey] is None: - message = "{0} requires {1} argument. Set the " \ - "MWSConnection.{2} attribute?" \ - "".format(action, accesskey, accesskey) - raise KeyError(message) - kw['Action'] = action - kw['Version'] = version - response = self._response_factory(action, connection=self) - request = dict(path=path, quota=quota, restore=restore) - return func(self, request, response, *args, **kw) - for attr in decorated_attrs: - setattr(wrapper, attr, locals().get(attr)) - wrapper.__doc__ = "MWS {0}/{1} API call; quota={2} restore={3:.2f}\n" \ - "{4}".format(action, version, quota, restore, - func.__doc__) - api_call_map[action] = func.__name__ - return wrapper - return decorator - - -class MWSConnection(AWSQueryConnection): - - ResponseFactory = boto.mws.response.ResponseFactory - ResponseErrorFactory = boto.mws.exception.ResponseErrorFactory - - def __init__(self, *args, **kw): - kw.setdefault('host', 'mws.amazonservices.com') - self._sandboxed = kw.pop('sandbox', False) - self.Merchant = kw.pop('Merchant', None) or kw.get('SellerId') - self.SellerId = kw.pop('SellerId', None) or self.Merchant - kw = self._setup_factories(kw.pop('factory_scopes', []), **kw) - super(MWSConnection, self).__init__(*args, **kw) - - def _setup_factories(self, extrascopes, **kw): - for factory, (scope, Default) in { - 'response_factory': - (boto.mws.response, self.ResponseFactory), - 'response_error_factory': - (boto.mws.exception, self.ResponseErrorFactory), - }.items(): - if factory in kw: - setattr(self, '_' + factory, kw.pop(factory)) - else: - scopes = extrascopes + [scope] - setattr(self, '_' + factory, Default(scopes=scopes)) - return kw - - def _sandboxify(self, path): - if not self._sandboxed: - return path - splat = path.split('/') - splat[-2] += '_Sandbox' - return splat.join('/') - - def _required_auth_capability(self): - return ['mws'] - - def _post_request(self, request, params, parser, body='', headers=None): - """Make a POST request, optionally with a content body, - and return the response, optionally as raw text. - """ - headers = headers or {} - path = self._sandboxify(request['path']) - request = self.build_base_http_request('POST', path, None, data=body, - params=params, headers=headers, - host=self.host) - try: - response = self._mexe(request, override_num_retries=None) - except BotoServerError as bs: - raise self._response_error_factory(bs.status, bs.reason, bs.body) - body = response.read() - boto.log.debug(body) - if not body: - boto.log.error('Null body %s' % body) - raise self._response_error_factory(response.status, - response.reason, body) - if response.status != 200: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise self._response_error_factory(response.status, - response.reason, body) - digest = response.getheader('Content-MD5') - if digest is not None: - assert content_md5(body) == digest - contenttype = response.getheader('Content-Type') - return self._parse_response(parser, contenttype, body) - - def _parse_response(self, parser, contenttype, body): - if not contenttype.startswith('text/xml'): - return body - handler = XmlHandler(parser, self) - xml.sax.parseString(body, handler) - return parser - - def method_for(self, name): - """Return the MWS API method referred to in the argument. - The named method can be in CamelCase or underlined_lower_case. - This is the complement to MWSConnection.any_call.action - """ - action = '_' in name and string.capwords(name, '_') or name - if action in api_call_map: - return getattr(self, api_call_map[action]) - return None - - def iter_call(self, call, *args, **kw): - """Pass a call name as the first argument and a generator - is returned for the initial response and any continuation - call responses made using the NextToken. - """ - method = self.method_for(call) - assert method, 'No call named "{0}"'.format(call) - return self.iter_response(method(*args, **kw)) - - def iter_response(self, response): - """Pass a call's response as the initial argument and a - generator is returned for the initial response and any - continuation call responses made using the NextToken. - """ - yield response - more = self.method_for(response._action + 'ByNextToken') - while more and response._result.HasNext == 'true': - response = more(NextToken=response._result.NextToken) - yield response - - @requires(['FeedType']) - @boolean_arguments('PurgeAndReplace') - @http_body('FeedContent') - @structured_lists('MarketplaceIdList.Id') - @api_action('Feeds', 15, 120) - def submit_feed(self, request, response, headers=None, body='', **kw): - """Uploads a feed for processing by Amazon MWS. - """ - headers = headers or {} - return self._post_request(request, kw, response, body=body, - headers=headers) - - @structured_lists('FeedSubmissionIdList.Id', 'FeedTypeList.Type', - 'FeedProcessingStatusList.Status') - @api_action('Feeds', 10, 45) - def get_feed_submission_list(self, request, response, **kw): - """Returns a list of all feed submissions submitted in the - previous 90 days. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Feeds', 0, 0) - def get_feed_submission_list_by_next_token(self, request, response, **kw): - """Returns a list of feed submissions using the NextToken parameter. - """ - return self._post_request(request, kw, response) - - @structured_lists('FeedTypeList.Type', 'FeedProcessingStatusList.Status') - @api_action('Feeds', 10, 45) - def get_feed_submission_count(self, request, response, **kw): - """Returns a count of the feeds submitted in the previous 90 days. - """ - return self._post_request(request, kw, response) - - @structured_lists('FeedSubmissionIdList.Id', 'FeedTypeList.Type') - @api_action('Feeds', 10, 45) - def cancel_feed_submissions(self, request, response, **kw): - """Cancels one or more feed submissions and returns a - count of the feed submissions that were canceled. - """ - return self._post_request(request, kw, response) - - @requires(['FeedSubmissionId']) - @api_action('Feeds', 15, 60) - def get_feed_submission_result(self, request, response, **kw): - """Returns the feed processing report. - """ - return self._post_request(request, kw, response) - - def get_service_status(self, **kw): - """Instruct the user on how to get service status. - """ - sections = ', '.join(map(str.lower, api_version_path.keys())) - message = "Use {0}.get_(section)_service_status(), " \ - "where (section) is one of the following: " \ - "{1}".format(self.__class__.__name__, sections) - raise AttributeError(message) - - @requires(['ReportType']) - @structured_lists('MarketplaceIdList.Id') - @boolean_arguments('ReportOptions=ShowSalesChannel') - @api_action('Reports', 15, 60) - def request_report(self, request, response, **kw): - """Creates a report request and submits the request to Amazon MWS. - """ - return self._post_request(request, kw, response) - - @structured_lists('ReportRequestIdList.Id', 'ReportTypeList.Type', - 'ReportProcessingStatusList.Status') - @api_action('Reports', 10, 45) - def get_report_request_list(self, request, response, **kw): - """Returns a list of report requests that you can use to get the - ReportRequestId for a report. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Reports', 0, 0) - def get_report_request_list_by_next_token(self, request, response, **kw): - """Returns a list of report requests using the NextToken, - which was supplied by a previous request to either - GetReportRequestListByNextToken or GetReportRequestList, where - the value of HasNext was true in that previous request. - """ - return self._post_request(request, kw, response) - - @structured_lists('ReportTypeList.Type', - 'ReportProcessingStatusList.Status') - @api_action('Reports', 10, 45) - def get_report_request_count(self, request, response, **kw): - """Returns a count of report requests that have been submitted - to Amazon MWS for processing. - """ - return self._post_request(request, kw, response) - - @api_action('Reports', 10, 45) - def cancel_report_requests(self, request, response, **kw): - """Cancel one or more report requests, returning the count of the - canceled report requests and the report request information. - """ - return self._post_request(request, kw, response) - - @boolean_arguments('Acknowledged') - @structured_lists('ReportRequestIdList.Id', 'ReportTypeList.Type') - @api_action('Reports', 10, 60) - def get_report_list(self, request, response, **kw): - """Returns a list of reports that were created in the previous - 90 days that match the query parameters. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Reports', 0, 0) - def get_report_list_by_next_token(self, request, response, **kw): - """Returns a list of reports using the NextToken, which - was supplied by a previous request to either - GetReportListByNextToken or GetReportList, where the - value of HasNext was true in the previous call. - """ - return self._post_request(request, kw, response) - - @boolean_arguments('Acknowledged') - @structured_lists('ReportTypeList.Type') - @api_action('Reports', 10, 45) - def get_report_count(self, request, response, **kw): - """Returns a count of the reports, created in the previous 90 days, - with a status of _DONE_ and that are available for download. - """ - return self._post_request(request, kw, response) - - @requires(['ReportId']) - @api_action('Reports', 15, 60) - def get_report(self, request, response, **kw): - """Returns the contents of a report. - """ - return self._post_request(request, kw, response) - - @requires(['ReportType', 'Schedule']) - @api_action('Reports', 10, 45) - def manage_report_schedule(self, request, response, **kw): - """Creates, updates, or deletes a report request schedule for - a specified report type. - """ - return self._post_request(request, kw, response) - - @structured_lists('ReportTypeList.Type') - @api_action('Reports', 10, 45) - def get_report_schedule_list(self, request, response, **kw): - """Returns a list of order report requests that are scheduled - to be submitted to Amazon MWS for processing. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Reports', 0, 0) - def get_report_schedule_list_by_next_token(self, request, response, **kw): - """Returns a list of report requests using the NextToken, - which was supplied by a previous request to either - GetReportScheduleListByNextToken or GetReportScheduleList, - where the value of HasNext was true in that previous request. - """ - return self._post_request(request, kw, response) - - @structured_lists('ReportTypeList.Type') - @api_action('Reports', 10, 45) - def get_report_schedule_count(self, request, response, **kw): - """Returns a count of order report requests that are scheduled - to be submitted to Amazon MWS. - """ - return self._post_request(request, kw, response) - - @requires(['ReportIdList']) - @boolean_arguments('Acknowledged') - @structured_lists('ReportIdList.Id') - @api_action('Reports', 10, 45) - def update_report_acknowledgements(self, request, response, **kw): - """Updates the acknowledged status of one or more reports. - """ - return self._post_request(request, kw, response) - - @requires(['ShipFromAddress', 'InboundShipmentPlanRequestItems']) - @structured_objects('ShipFromAddress', 'InboundShipmentPlanRequestItems') - @api_action('Inbound', 30, 0.5) - def create_inbound_shipment_plan(self, request, response, **kw): - """Returns the information required to create an inbound shipment. - """ - return self._post_request(request, kw, response) - - @requires(['ShipmentId', 'InboundShipmentHeader', 'InboundShipmentItems']) - @structured_objects('InboundShipmentHeader', 'InboundShipmentItems') - @api_action('Inbound', 30, 0.5) - def create_inbound_shipment(self, request, response, **kw): - """Creates an inbound shipment. - """ - return self._post_request(request, kw, response) - - @requires(['ShipmentId']) - @structured_objects('InboundShipmentHeader', 'InboundShipmentItems') - @api_action('Inbound', 30, 0.5) - def update_inbound_shipment(self, request, response, **kw): - """Updates an existing inbound shipment. Amazon documentation - is ambiguous as to whether the InboundShipmentHeader and - InboundShipmentItems arguments are required. - """ - return self._post_request(request, kw, response) - - @requires_some_of('ShipmentIdList', 'ShipmentStatusList') - @structured_lists('ShipmentIdList.Id', 'ShipmentStatusList.Status') - @api_action('Inbound', 30, 0.5) - def list_inbound_shipments(self, request, response, **kw): - """Returns a list of inbound shipments based on criteria that - you specify. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Inbound', 30, 0.5) - def list_inbound_shipments_by_next_token(self, request, response, **kw): - """Returns the next page of inbound shipments using the NextToken - parameter. - """ - return self._post_request(request, kw, response) - - @requires(['ShipmentId'], ['LastUpdatedAfter', 'LastUpdatedBefore']) - @api_action('Inbound', 30, 0.5) - def list_inbound_shipment_items(self, request, response, **kw): - """Returns a list of items in a specified inbound shipment, or a - list of items that were updated within a specified time frame. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Inbound', 30, 0.5) - def list_inbound_shipment_items_by_next_token(self, request, response, **kw): - """Returns the next page of inbound shipment items using the - NextToken parameter. - """ - return self._post_request(request, kw, response) - - @api_action('Inbound', 2, 300, 'GetServiceStatus') - def get_inbound_service_status(self, request, response, **kw): - """Returns the operational status of the Fulfillment Inbound - Shipment API section. - """ - return self._post_request(request, kw, response) - - @requires(['SellerSkus'], ['QueryStartDateTime']) - @structured_lists('SellerSkus.member') - @api_action('Inventory', 30, 0.5) - def list_inventory_supply(self, request, response, **kw): - """Returns information about the availability of a seller's - inventory. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Inventory', 30, 0.5) - def list_inventory_supply_by_next_token(self, request, response, **kw): - """Returns the next page of information about the availability - of a seller's inventory using the NextToken parameter. - """ - return self._post_request(request, kw, response) - - @api_action('Inventory', 2, 300, 'GetServiceStatus') - def get_inventory_service_status(self, request, response, **kw): - """Returns the operational status of the Fulfillment Inventory - API section. - """ - return self._post_request(request, kw, response) - - @requires(['PackageNumber']) - @api_action('Outbound', 30, 0.5) - def get_package_tracking_details(self, request, response, **kw): - """Returns delivery tracking information for a package in - an outbound shipment for a Multi-Channel Fulfillment order. - """ - return self._post_request(request, kw, response) - - @requires(['Address', 'Items']) - @structured_objects('Address', 'Items') - @api_action('Outbound', 30, 0.5) - def get_fulfillment_preview(self, request, response, **kw): - """Returns a list of fulfillment order previews based on items - and shipping speed categories that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['SellerFulfillmentOrderId', 'DisplayableOrderId', - 'ShippingSpeedCategory', 'DisplayableOrderDateTime', - 'DestinationAddress', 'DisplayableOrderComment', - 'Items']) - @structured_objects('DestinationAddress', 'Items') - @api_action('Outbound', 30, 0.5) - def create_fulfillment_order(self, request, response, **kw): - """Requests that Amazon ship items from the seller's inventory - to a destination address. - """ - return self._post_request(request, kw, response) - - @requires(['SellerFulfillmentOrderId']) - @api_action('Outbound', 30, 0.5) - def get_fulfillment_order(self, request, response, **kw): - """Returns a fulfillment order based on a specified - SellerFulfillmentOrderId. - """ - return self._post_request(request, kw, response) - - @api_action('Outbound', 30, 0.5) - def list_all_fulfillment_orders(self, request, response, **kw): - """Returns a list of fulfillment orders fulfilled after (or - at) a specified date or by fulfillment method. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Outbound', 30, 0.5) - def list_all_fulfillment_orders_by_next_token(self, request, response, **kw): - """Returns the next page of inbound shipment items using the - NextToken parameter. - """ - return self._post_request(request, kw, response) - - @requires(['SellerFulfillmentOrderId']) - @api_action('Outbound', 30, 0.5) - def cancel_fulfillment_order(self, request, response, **kw): - """Requests that Amazon stop attempting to fulfill an existing - fulfillment order. - """ - return self._post_request(request, kw, response) - - @api_action('Outbound', 2, 300, 'GetServiceStatus') - def get_outbound_service_status(self, request, response, **kw): - """Returns the operational status of the Fulfillment Outbound - API section. - """ - return self._post_request(request, kw, response) - - @requires(['CreatedAfter'], ['LastUpdatedAfter']) - @requires(['MarketplaceId']) - @exclusive(['CreatedAfter'], ['LastUpdatedAfter']) - @dependent('CreatedBefore', ['CreatedAfter']) - @exclusive(['LastUpdatedAfter'], ['BuyerEmail'], ['SellerOrderId']) - @dependent('LastUpdatedBefore', ['LastUpdatedAfter']) - @exclusive(['CreatedAfter'], ['LastUpdatedBefore']) - @structured_objects('OrderTotal', 'ShippingAddress', - 'PaymentExecutionDetail') - @structured_lists('MarketplaceId.Id', 'OrderStatus.Status', - 'FulfillmentChannel.Channel', 'PaymentMethod.') - @api_action('Orders', 6, 60) - def list_orders(self, request, response, **kw): - """Returns a list of orders created or updated during a time - frame that you specify. - """ - toggle = set(('FulfillmentChannel.Channel.1', - 'OrderStatus.Status.1', 'PaymentMethod.1', - 'LastUpdatedAfter', 'LastUpdatedBefore')) - for do, dont in { - 'BuyerEmail': toggle.union(['SellerOrderId']), - 'SellerOrderId': toggle.union(['BuyerEmail']), - }.items(): - if do in kw and any(i in dont for i in kw): - message = "Don't include {0} when specifying " \ - "{1}".format(' or '.join(dont), do) - raise AssertionError(message) - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Orders', 6, 60) - def list_orders_by_next_token(self, request, response, **kw): - """Returns the next page of orders using the NextToken value - that was returned by your previous request to either - ListOrders or ListOrdersByNextToken. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderId']) - @structured_lists('AmazonOrderId.Id') - @api_action('Orders', 6, 60) - def get_order(self, request, response, **kw): - """Returns an order for each AmazonOrderId that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderId']) - @api_action('Orders', 30, 2) - def list_order_items(self, request, response, **kw): - """Returns order item information for an AmazonOrderId that - you specify. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Orders', 30, 2) - def list_order_items_by_next_token(self, request, response, **kw): - """Returns the next page of order items using the NextToken - value that was returned by your previous request to either - ListOrderItems or ListOrderItemsByNextToken. - """ - return self._post_request(request, kw, response) - - @api_action('Orders', 2, 300, 'GetServiceStatus') - def get_orders_service_status(self, request, response, **kw): - """Returns the operational status of the Orders API section. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'Query']) - @api_action('Products', 20, 20) - def list_matching_products(self, request, response, **kw): - """Returns a list of products and their attributes, ordered - by relevancy, based on a search query that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'ASINList']) - @structured_lists('ASINList.ASIN') - @api_action('Products', 20, 20) - def get_matching_product(self, request, response, **kw): - """Returns a list of products and their attributes, based on - a list of ASIN values that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'IdType', 'IdList']) - @structured_lists('IdList.Id') - @api_action('Products', 20, 20) - def get_matching_product_for_id(self, request, response, **kw): - """Returns a list of products and their attributes, based on - a list of Product IDs that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'SellerSKUList']) - @structured_lists('SellerSKUList.SellerSKU') - @api_action('Products', 20, 10, 'GetCompetitivePricingForSKU') - def get_competitive_pricing_for_sku(self, request, response, **kw): - """Returns the current competitive pricing of a product, - based on the SellerSKUs and MarketplaceId that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'ASINList']) - @structured_lists('ASINList.ASIN') - @api_action('Products', 20, 10, 'GetCompetitivePricingForASIN') - def get_competitive_pricing_for_asin(self, request, response, **kw): - """Returns the current competitive pricing of a product, - based on the ASINs and MarketplaceId that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'SellerSKUList']) - @structured_lists('SellerSKUList.SellerSKU') - @api_action('Products', 20, 5, 'GetLowestOfferListingsForSKU') - def get_lowest_offer_listings_for_sku(self, request, response, **kw): - """Returns the lowest price offer listings for a specific - product by item condition and SellerSKUs. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'ASINList']) - @structured_lists('ASINList.ASIN') - @api_action('Products', 20, 5, 'GetLowestOfferListingsForASIN') - def get_lowest_offer_listings_for_asin(self, request, response, **kw): - """Returns the lowest price offer listings for a specific - product by item condition and ASINs. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'SellerSKU']) - @api_action('Products', 20, 20, 'GetProductCategoriesForSKU') - def get_product_categories_for_sku(self, request, response, **kw): - """Returns the product categories that a SellerSKU belongs to. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'ASIN']) - @api_action('Products', 20, 20, 'GetProductCategoriesForASIN') - def get_product_categories_for_asin(self, request, response, **kw): - """Returns the product categories that an ASIN belongs to. - """ - return self._post_request(request, kw, response) - - @api_action('Products', 2, 300, 'GetServiceStatus') - def get_products_service_status(self, request, response, **kw): - """Returns the operational status of the Products API section. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'SellerSKUList']) - @structured_lists('SellerSKUList.SellerSKU') - @api_action('Products', 20, 10, 'GetMyPriceForSKU') - def get_my_price_for_sku(self, request, response, **kw): - """Returns pricing information for your own offer listings, based on SellerSKU. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'ASINList']) - @structured_lists('ASINList.ASIN') - @api_action('Products', 20, 10, 'GetMyPriceForASIN') - def get_my_price_for_asin(self, request, response, **kw): - """Returns pricing information for your own offer listings, based on ASIN. - """ - return self._post_request(request, kw, response) - - @api_action('Sellers', 15, 60) - def list_marketplace_participations(self, request, response, **kw): - """Returns a list of marketplaces that the seller submitting - the request can sell in, and a list of participations that - include seller-specific information in that marketplace. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Sellers', 15, 60) - def list_marketplace_participations_by_next_token(self, request, response, - **kw): - """Returns the next page of marketplaces and participations - using the NextToken value that was returned by your - previous request to either ListMarketplaceParticipations - or ListMarketplaceParticipationsByNextToken. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId']) - @api_action('Recommendations', 5, 2) - def get_last_updated_time_for_recommendations(self, request, response, - **kw): - """Checks whether there are active recommendations for each category - for the given marketplace, and if there are, returns the time when - recommendations were last updated for each category. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId']) - @structured_lists('CategoryQueryList.CategoryQuery') - @api_action('Recommendations', 5, 2) - def list_recommendations(self, request, response, **kw): - """Returns your active recommendations for a specific category or for - all categories for a specific marketplace. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('Recommendations', 5, 2) - def list_recommendations_by_next_token(self, request, response, **kw): - """Returns the next page of recommendations using the NextToken - parameter. - """ - return self._post_request(request, kw, response) - - @api_action('Recommendations', 2, 300, 'GetServiceStatus') - def get_recommendations_service_status(self, request, response, **kw): - """Returns the operational status of the Recommendations API section. - """ - return self._post_request(request, kw, response) - - @api_action('CustomerInfo', 15, 12) - def list_customers(self, request, response, **kw): - """Returns a list of customer accounts based on search criteria that - you specify. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('CustomerInfo', 50, 3) - def list_customers_by_next_token(self, request, response, **kw): - """Returns the next page of customers using the NextToken parameter. - """ - return self._post_request(request, kw, response) - - @requires(['CustomerIdList']) - @structured_lists('CustomerIdList.CustomerId') - @api_action('CustomerInfo', 15, 12) - def get_customers_for_customer_id(self, request, response, **kw): - """Returns a list of customer accounts based on search criteria that - you specify. - """ - return self._post_request(request, kw, response) - - @api_action('CustomerInfo', 2, 300, 'GetServiceStatus') - def get_customerinfo_service_status(self, request, response, **kw): - """Returns the operational status of the Customer Information API - section. - """ - return self._post_request(request, kw, response) - - @requires(['DateRangeStart']) - @api_action('CartInfo', 15, 12) - def list_carts(self, request, response, **kw): - """Returns a list of shopping carts in your Webstore that were last - updated during the time range that you specify. - """ - return self._post_request(request, kw, response) - - @requires(['NextToken']) - @api_action('CartInfo', 50, 3) - def list_carts_by_next_token(self, request, response, **kw): - """Returns the next page of shopping carts using the NextToken - parameter. - """ - return self._post_request(request, kw, response) - - @requires(['CartIdList']) - @structured_lists('CartIdList.CartId') - @api_action('CartInfo', 15, 12) - def get_carts(self, request, response, **kw): - """Returns shopping carts based on the CartId values that you specify. - """ - return self._post_request(request, kw, response) - - @api_action('CartInfo', 2, 300, 'GetServiceStatus') - def get_cartinfo_service_status(self, request, response, **kw): - """Returns the operational status of the Cart Information API section. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'Destination']) - @structured_objects('Destination', members=True) - @api_action('Subscriptions', 25, 0.5) - def register_destination(self, request, response, **kw): - """Specifies a new destination where you want to receive notifications. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'Destination']) - @structured_objects('Destination', members=True) - @api_action('Subscriptions', 25, 0.5) - def deregister_destination(self, request, response, **kw): - """Removes an existing destination from the list of registered - destinations. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId']) - @api_action('Subscriptions', 25, 0.5) - def list_registered_destinations(self, request, response, **kw): - """Lists all current destinations that you have registered. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'Destination']) - @structured_objects('Destination', members=True) - @api_action('Subscriptions', 25, 0.5) - def send_test_notification_to_destination(self, request, response, **kw): - """Sends a test notification to an existing destination. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'Subscription']) - @structured_objects('Subscription', members=True) - @api_action('Subscriptions', 25, 0.5) - def create_subscription(self, request, response, **kw): - """Creates a new subscription for the specified notification type - and destination. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'NotificationType', 'Destination']) - @structured_objects('Destination', members=True) - @api_action('Subscriptions', 25, 0.5) - def get_subscription(self, request, response, **kw): - """Gets the subscription for the specified notification type and - destination. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'NotificationType', 'Destination']) - @structured_objects('Destination', members=True) - @api_action('Subscriptions', 25, 0.5) - def delete_subscription(self, request, response, **kw): - """Deletes the subscription for the specified notification type and - destination. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId']) - @api_action('Subscriptions', 25, 0.5) - def list_subscriptions(self, request, response, **kw): - """Returns a list of all your current subscriptions. - """ - return self._post_request(request, kw, response) - - @requires(['MarketplaceId', 'Subscription']) - @structured_objects('Subscription', members=True) - @api_action('Subscriptions', 25, 0.5) - def update_subscription(self, request, response, **kw): - """Updates the subscription for the specified notification type and - destination. - """ - return self._post_request(request, kw, response) - - @api_action('Subscriptions', 2, 300, 'GetServiceStatus') - def get_subscriptions_service_status(self, request, response, **kw): - """Returns the operational status of the Subscriptions API section. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderReferenceId', 'OrderReferenceAttributes']) - @structured_objects('OrderReferenceAttributes') - @api_action('OffAmazonPayments', 10, 1) - def set_order_reference_details(self, request, response, **kw): - """Sets order reference details such as the order total and a - description for the order. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderReferenceId']) - @api_action('OffAmazonPayments', 20, 2) - def get_order_reference_details(self, request, response, **kw): - """Returns details about the Order Reference object and its current - state. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderReferenceId']) - @api_action('OffAmazonPayments', 10, 1) - def confirm_order_reference(self, request, response, **kw): - """Confirms that the order reference is free of constraints and all - required information has been set on the order reference. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderReferenceId']) - @api_action('OffAmazonPayments', 10, 1) - def cancel_order_reference(self, request, response, **kw): - """Cancel an order reference; all authorizations associated with - this order reference are also closed. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderReferenceId']) - @api_action('OffAmazonPayments', 10, 1) - def close_order_reference(self, request, response, **kw): - """Confirms that an order reference has been fulfilled (fully - or partially) and that you do not expect to create any new - authorizations on this order reference. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonOrderReferenceId', 'AuthorizationReferenceId', - 'AuthorizationAmount']) - @structured_objects('AuthorizationAmount') - @api_action('OffAmazonPayments', 10, 1) - def authorize(self, request, response, **kw): - """Reserves a specified amount against the payment method(s) stored in - the order reference. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonAuthorizationId']) - @api_action('OffAmazonPayments', 20, 2) - def get_authorization_details(self, request, response, **kw): - """Returns the status of a particular authorization and the total - amount captured on the authorization. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonAuthorizationId', 'CaptureReferenceId', 'CaptureAmount']) - @structured_objects('CaptureAmount') - @api_action('OffAmazonPayments', 10, 1) - def capture(self, request, response, **kw): - """Captures funds from an authorized payment instrument. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonCaptureId']) - @api_action('OffAmazonPayments', 20, 2) - def get_capture_details(self, request, response, **kw): - """Returns the status of a particular capture and the total amount - refunded on the capture. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonAuthorizationId']) - @api_action('OffAmazonPayments', 10, 1) - def close_authorization(self, request, response, **kw): - """Closes an authorization. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonCaptureId', 'RefundReferenceId', 'RefundAmount']) - @structured_objects('RefundAmount') - @api_action('OffAmazonPayments', 10, 1) - def refund(self, request, response, **kw): - """Refunds a previously captured amount. - """ - return self._post_request(request, kw, response) - - @requires(['AmazonRefundId']) - @api_action('OffAmazonPayments', 20, 2) - def get_refund_details(self, request, response, **kw): - """Returns the status of a particular refund. - """ - return self._post_request(request, kw, response) - - @api_action('OffAmazonPayments', 2, 300, 'GetServiceStatus') - def get_offamazonpayments_service_status(self, request, response, **kw): - """Returns the operational status of the Off-Amazon Payments API - section. - """ - return self._post_request(request, kw, response) diff --git a/awx/lib/site-packages/boto/mws/exception.py b/awx/lib/site-packages/boto/mws/exception.py deleted file mode 100644 index fba8a5d5d2..0000000000 --- a/awx/lib/site-packages/boto/mws/exception.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (c) 2012-2014 Andy Davidoff http://www.disruptek.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from boto.exception import BotoServerError -from boto.mws.response import ResponseFactory - - -class ResponseErrorFactory(ResponseFactory): - - def __call__(self, status, reason, body=None): - server = BotoServerError(status, reason, body=body) - supplied = self.find_element(server.error_code, '', ResponseError) - print(supplied.__name__) - return supplied(status, reason, body=body) - - -class ResponseError(BotoServerError): - """ - Undefined response error. - """ - retry = False - - def __repr__(self): - return '{0.__name__}({1.reason}: "{1.message}")' \ - .format(self.__class__, self) - - def __str__(self): - doc = self.__doc__ and self.__doc__.strip() + "\n" or '' - return '{1.__name__}: {0.reason} {2}\n{3}' \ - '{0.message}'.format(self, self.__class__, - self.retry and '(Retriable)' or '', doc) - - -class RetriableResponseError(ResponseError): - retry = True - - -class InvalidParameterValue(ResponseError): - """ - One or more parameter values in the request is invalid. - """ - - -class InvalidParameter(ResponseError): - """ - One or more parameters in the request is invalid. - """ - - -class InvalidAddress(ResponseError): - """ - Invalid address. - """ diff --git a/awx/lib/site-packages/boto/mws/response.py b/awx/lib/site-packages/boto/mws/response.py deleted file mode 100644 index 7e2e23c07e..0000000000 --- a/awx/lib/site-packages/boto/mws/response.py +++ /dev/null @@ -1,787 +0,0 @@ -# Copyright (c) 2012-2014 Andy Davidoff http://www.disruptek.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, dis- tribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the fol- lowing conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- ITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -from decimal import Decimal -from boto.compat import filter, map - - -class ComplexType(dict): - _value = 'Value' - - def __repr__(self): - return '{0}{1}'.format(getattr(self, self._value, None), self.copy()) - - def __str__(self): - return str(getattr(self, self._value, '')) - - -class DeclarativeType(object): - def __init__(self, _hint=None, **kw): - self._value = None - if _hint is not None: - self._hint = _hint - return - - class JITResponse(ResponseElement): - pass - self._hint = JITResponse - self._hint.__name__ = 'JIT_{0}/{1}'.format(self.__class__.__name__, - hex(id(self._hint))[2:]) - for name, value in kw.items(): - setattr(self._hint, name, value) - - def __repr__(self): - parent = getattr(self, '_parent', None) - return '<{0}_{1}/{2}_{3}>'.format(self.__class__.__name__, - parent and parent._name or '?', - getattr(self, '_name', '?'), - hex(id(self.__class__))) - - def setup(self, parent, name, *args, **kw): - self._parent = parent - self._name = name - self._clone = self.__class__(_hint=self._hint) - self._clone._parent = parent - self._clone._name = name - setattr(self._parent, self._name, self._clone) - - def start(self, *args, **kw): - raise NotImplementedError - - def end(self, *args, **kw): - raise NotImplementedError - - def teardown(self, *args, **kw): - setattr(self._parent, self._name, self._value) - - -class Element(DeclarativeType): - def start(self, *args, **kw): - self._value = self._hint(parent=self._parent, **kw) - return self._value - - def end(self, *args, **kw): - pass - - -class SimpleList(DeclarativeType): - def __init__(self, *args, **kw): - super(SimpleList, self).__init__(*args, **kw) - self._value = [] - - def start(self, *args, **kw): - return None - - def end(self, name, value, *args, **kw): - self._value.append(value) - - -class ElementList(SimpleList): - def start(self, *args, **kw): - value = self._hint(parent=self._parent, **kw) - self._value.append(value) - return value - - def end(self, *args, **kw): - pass - - -class MemberList(Element): - def __init__(self, _member=None, _hint=None, *args, **kw): - message = 'Invalid `member` specification in {0}'.format(self.__class__.__name__) - assert 'member' not in kw, message - if _member is None: - if _hint is None: - super(MemberList, self).__init__(*args, member=ElementList(**kw)) - else: - super(MemberList, self).__init__(_hint=_hint) - else: - if _hint is None: - if issubclass(_member, DeclarativeType): - member = _member(**kw) - else: - member = ElementList(_member, **kw) - super(MemberList, self).__init__(*args, member=member) - else: - message = 'Nonsensical {0} hint {1!r}'.format(self.__class__.__name__, - _hint) - raise AssertionError(message) - - def teardown(self, *args, **kw): - if self._value is None: - self._value = [] - else: - if isinstance(self._value.member, DeclarativeType): - self._value.member = [] - self._value = self._value.member - super(MemberList, self).teardown(*args, **kw) - - -class ResponseFactory(object): - def __init__(self, scopes=None): - self.scopes = [] if scopes is None else scopes - - def element_factory(self, name, parent): - class DynamicElement(parent): - _name = name - setattr(DynamicElement, '__name__', str(name)) - return DynamicElement - - def search_scopes(self, key): - for scope in self.scopes: - if hasattr(scope, key): - return getattr(scope, key) - if hasattr(scope, '__getitem__'): - if key in scope: - return scope[key] - - def find_element(self, action, suffix, parent): - element = self.search_scopes(action + suffix) - if element is not None: - return element - if action.endswith('ByNextToken'): - element = self.search_scopes(action[:-len('ByNextToken')] + suffix) - if element is not None: - return self.element_factory(action + suffix, element) - return self.element_factory(action + suffix, parent) - - def __call__(self, action, connection=None): - response = self.find_element(action, 'Response', Response) - if not hasattr(response, action + 'Result'): - result = self.find_element(action, 'Result', ResponseElement) - setattr(response, action + 'Result', Element(result)) - return response(connection=connection) - - -def strip_namespace(func): - def wrapper(self, name, *args, **kw): - if self._namespace is not None: - if name.startswith(self._namespace + ':'): - name = name[len(self._namespace + ':'):] - return func(self, name, *args, **kw) - return wrapper - - -class ResponseElement(dict): - _override = {} - _name = None - _namespace = None - - def __init__(self, connection=None, name=None, parent=None, attrs=None): - if parent is not None and self._namespace is None: - self._namespace = parent._namespace - if connection is not None: - self._connection = connection - self._name = name or self._name or self.__class__.__name__ - self._declared('setup', attrs=attrs) - dict.__init__(self, attrs and attrs.copy() or {}) - - def _declared(self, op, **kw): - def inherit(obj): - result = {} - for cls in getattr(obj, '__bases__', ()): - result.update(inherit(cls)) - result.update(obj.__dict__) - return result - - scope = inherit(self.__class__) - scope.update(self.__dict__) - declared = lambda attr: isinstance(attr[1], DeclarativeType) - for name, node in filter(declared, scope.items()): - getattr(node, op)(self, name, parentname=self._name, **kw) - - @property - def connection(self): - return self._connection - - def __repr__(self): - render = lambda pair: '{0!s}: {1!r}'.format(*pair) - do_show = lambda pair: not pair[0].startswith('_') - attrs = filter(do_show, self.__dict__.items()) - name = self.__class__.__name__ - if name.startswith('JIT_'): - name = '^{0}^'.format(self._name or '') - return '{0}{1!r}({2})'.format( - name, self.copy(), ', '.join(map(render, attrs))) - - def _type_for(self, name, attrs): - return self._override.get(name, globals().get(name, ResponseElement)) - - @strip_namespace - def startElement(self, name, attrs, connection): - attribute = getattr(self, name, None) - if isinstance(attribute, DeclarativeType): - return attribute.start(name=name, attrs=attrs, - connection=connection) - elif attrs.getLength(): - setattr(self, name, ComplexType(attrs.copy())) - else: - return None - - @strip_namespace - def endElement(self, name, value, connection): - attribute = getattr(self, name, None) - if name == self._name: - self._declared('teardown') - elif isinstance(attribute, DeclarativeType): - attribute.end(name=name, value=value, connection=connection) - elif isinstance(attribute, ComplexType): - setattr(attribute, attribute._value, value) - else: - setattr(self, name, value) - - -class Response(ResponseElement): - ResponseMetadata = Element() - - @strip_namespace - def startElement(self, name, attrs, connection): - if name == self._name: - self.update(attrs) - else: - return super(Response, self).startElement(name, attrs, connection) - - @property - def _result(self): - return getattr(self, self._action + 'Result', None) - - @property - def _action(self): - return (self._name or self.__class__.__name__)[:-len('Response')] - - -class ResponseResultList(Response): - _ResultClass = ResponseElement - - def __init__(self, *args, **kw): - setattr(self, self._action + 'Result', ElementList(self._ResultClass)) - super(ResponseResultList, self).__init__(*args, **kw) - - -class FeedSubmissionInfo(ResponseElement): - pass - - -class SubmitFeedResult(ResponseElement): - FeedSubmissionInfo = Element(FeedSubmissionInfo) - - -class GetFeedSubmissionListResult(ResponseElement): - FeedSubmissionInfo = ElementList(FeedSubmissionInfo) - - -class GetFeedSubmissionCountResult(ResponseElement): - pass - - -class CancelFeedSubmissionsResult(GetFeedSubmissionListResult): - pass - - -class GetServiceStatusResult(ResponseElement): - Messages = Element(Messages=ElementList()) - - -class ReportRequestInfo(ResponseElement): - pass - - -class RequestReportResult(ResponseElement): - ReportRequestInfo = Element() - - -class GetReportRequestListResult(RequestReportResult): - ReportRequestInfo = ElementList() - - -class CancelReportRequestsResult(RequestReportResult): - pass - - -class GetReportListResult(ResponseElement): - ReportInfo = ElementList() - - -class ManageReportScheduleResult(ResponseElement): - ReportSchedule = Element() - - -class GetReportScheduleListResult(ManageReportScheduleResult): - pass - - -class UpdateReportAcknowledgementsResult(GetReportListResult): - pass - - -class CreateInboundShipmentPlanResult(ResponseElement): - InboundShipmentPlans = MemberList(ShipToAddress=Element(), - Items=MemberList()) - - -class ListInboundShipmentsResult(ResponseElement): - ShipmentData = MemberList(ShipFromAddress=Element()) - - -class ListInboundShipmentItemsResult(ResponseElement): - ItemData = MemberList() - - -class ListInventorySupplyResult(ResponseElement): - InventorySupplyList = MemberList( - EarliestAvailability=Element(), - SupplyDetail=MemberList( - EarliestAvailableToPick=Element(), - LatestAvailableToPick=Element(), - ) - ) - - -class ComplexAmount(ResponseElement): - _amount = 'Value' - - def __repr__(self): - return '{0} {1}'.format(self.CurrencyCode, getattr(self, self._amount)) - - def __float__(self): - return float(getattr(self, self._amount)) - - def __str__(self): - return str(getattr(self, self._amount)) - - @strip_namespace - def startElement(self, name, attrs, connection): - if name not in ('CurrencyCode', self._amount): - message = 'Unrecognized tag {0} in ComplexAmount'.format(name) - raise AssertionError(message) - return super(ComplexAmount, self).startElement(name, attrs, connection) - - @strip_namespace - def endElement(self, name, value, connection): - if name == self._amount: - value = Decimal(value) - super(ComplexAmount, self).endElement(name, value, connection) - - -class ComplexMoney(ComplexAmount): - _amount = 'Amount' - - -class ComplexWeight(ResponseElement): - def __repr__(self): - return '{0} {1}'.format(self.Value, self.Unit) - - def __float__(self): - return float(self.Value) - - def __str__(self): - return str(self.Value) - - @strip_namespace - def startElement(self, name, attrs, connection): - if name not in ('Unit', 'Value'): - message = 'Unrecognized tag {0} in ComplexWeight'.format(name) - raise AssertionError(message) - return super(ComplexWeight, self).startElement(name, attrs, connection) - - @strip_namespace - def endElement(self, name, value, connection): - if name == 'Value': - value = Decimal(value) - super(ComplexWeight, self).endElement(name, value, connection) - - -class Dimension(ComplexType): - _value = 'Value' - - -class ComplexDimensions(ResponseElement): - _dimensions = ('Height', 'Length', 'Width', 'Weight') - - def __repr__(self): - values = [getattr(self, key, None) for key in self._dimensions] - values = filter(None, values) - return 'x'.join(map('{0.Value:0.2f}{0[Units]}'.format, values)) - - @strip_namespace - def startElement(self, name, attrs, connection): - if name not in self._dimensions: - message = 'Unrecognized tag {0} in ComplexDimensions'.format(name) - raise AssertionError(message) - setattr(self, name, Dimension(attrs.copy())) - - @strip_namespace - def endElement(self, name, value, connection): - if name in self._dimensions: - value = Decimal(value or '0') - ResponseElement.endElement(self, name, value, connection) - - -class FulfillmentPreviewItem(ResponseElement): - EstimatedShippingWeight = Element(ComplexWeight) - - -class FulfillmentPreview(ResponseElement): - EstimatedShippingWeight = Element(ComplexWeight) - EstimatedFees = MemberList(Amount=Element(ComplexAmount)) - UnfulfillablePreviewItems = MemberList(FulfillmentPreviewItem) - FulfillmentPreviewShipments = MemberList( - FulfillmentPreviewItems=MemberList(FulfillmentPreviewItem), - ) - - -class GetFulfillmentPreviewResult(ResponseElement): - FulfillmentPreviews = MemberList(FulfillmentPreview) - - -class FulfillmentOrder(ResponseElement): - DestinationAddress = Element() - NotificationEmailList = MemberList(SimpleList) - - -class GetFulfillmentOrderResult(ResponseElement): - FulfillmentOrder = Element(FulfillmentOrder) - FulfillmentShipment = MemberList( - FulfillmentShipmentItem=MemberList(), - FulfillmentShipmentPackage=MemberList(), - ) - FulfillmentOrderItem = MemberList() - - -class ListAllFulfillmentOrdersResult(ResponseElement): - FulfillmentOrders = MemberList(FulfillmentOrder) - - -class GetPackageTrackingDetailsResult(ResponseElement): - ShipToAddress = Element() - TrackingEvents = MemberList(EventAddress=Element()) - - -class Image(ResponseElement): - pass - - -class AttributeSet(ResponseElement): - ItemDimensions = Element(ComplexDimensions) - ListPrice = Element(ComplexMoney) - PackageDimensions = Element(ComplexDimensions) - SmallImage = Element(Image) - - -class ItemAttributes(AttributeSet): - Languages = Element(Language=ElementList()) - - def __init__(self, *args, **kw): - names = ('Actor', 'Artist', 'Author', 'Creator', 'Director', - 'Feature', 'Format', 'GemType', 'MaterialType', - 'MediaType', 'OperatingSystem', 'Platform') - for name in names: - setattr(self, name, SimpleList()) - super(ItemAttributes, self).__init__(*args, **kw) - - -class VariationRelationship(ResponseElement): - Identifiers = Element(MarketplaceASIN=Element(), - SKUIdentifier=Element()) - GemType = SimpleList() - MaterialType = SimpleList() - OperatingSystem = SimpleList() - - -class Price(ResponseElement): - LandedPrice = Element(ComplexMoney) - ListingPrice = Element(ComplexMoney) - Shipping = Element(ComplexMoney) - - -class CompetitivePrice(ResponseElement): - Price = Element(Price) - - -class CompetitivePriceList(ResponseElement): - CompetitivePrice = ElementList(CompetitivePrice) - - -class CompetitivePricing(ResponseElement): - CompetitivePrices = Element(CompetitivePriceList) - NumberOfOfferListings = SimpleList() - TradeInValue = Element(ComplexMoney) - - -class SalesRank(ResponseElement): - pass - - -class LowestOfferListing(ResponseElement): - Qualifiers = Element(ShippingTime=Element()) - Price = Element(Price) - - -class Offer(ResponseElement): - BuyingPrice = Element(Price) - RegularPrice = Element(ComplexMoney) - - -class Product(ResponseElement): - _namespace = 'ns2' - Identifiers = Element(MarketplaceASIN=Element(), - SKUIdentifier=Element()) - AttributeSets = Element( - ItemAttributes=ElementList(ItemAttributes), - ) - Relationships = Element( - VariationParent=ElementList(VariationRelationship), - ) - CompetitivePricing = ElementList(CompetitivePricing) - SalesRankings = Element( - SalesRank=ElementList(SalesRank), - ) - LowestOfferListings = Element( - LowestOfferListing=ElementList(LowestOfferListing), - ) - Offers = Element( - Offer=ElementList(Offer), - ) - - -class ListMatchingProductsResult(ResponseElement): - Products = Element(Product=ElementList(Product)) - - -class ProductsBulkOperationResult(ResponseElement): - Product = Element(Product) - Error = Element() - - -class ProductsBulkOperationResponse(ResponseResultList): - _ResultClass = ProductsBulkOperationResult - - -class GetMatchingProductResponse(ProductsBulkOperationResponse): - pass - - -class GetMatchingProductForIdResult(ListMatchingProductsResult): - pass - - -class GetMatchingProductForIdResponse(ResponseResultList): - _ResultClass = GetMatchingProductForIdResult - - -class GetCompetitivePricingForSKUResponse(ProductsBulkOperationResponse): - pass - - -class GetCompetitivePricingForASINResponse(ProductsBulkOperationResponse): - pass - - -class GetLowestOfferListingsForSKUResponse(ProductsBulkOperationResponse): - pass - - -class GetLowestOfferListingsForASINResponse(ProductsBulkOperationResponse): - pass - - -class GetMyPriceForSKUResponse(ProductsBulkOperationResponse): - pass - - -class GetMyPriceForASINResponse(ProductsBulkOperationResponse): - pass - - -class ProductCategory(ResponseElement): - - def __init__(self, *args, **kw): - setattr(self, 'Parent', Element(ProductCategory)) - super(ProductCategory, self).__init__(*args, **kw) - - -class GetProductCategoriesResult(ResponseElement): - Self = ElementList(ProductCategory) - - -class GetProductCategoriesForSKUResult(GetProductCategoriesResult): - pass - - -class GetProductCategoriesForASINResult(GetProductCategoriesResult): - pass - - -class Order(ResponseElement): - OrderTotal = Element(ComplexMoney) - ShippingAddress = Element() - PaymentExecutionDetail = Element( - PaymentExecutionDetailItem=ElementList( - PaymentExecutionDetailItem=Element( - Payment=Element(ComplexMoney) - ) - ) - ) - - -class ListOrdersResult(ResponseElement): - Orders = Element(Order=ElementList(Order)) - - -class GetOrderResult(ListOrdersResult): - pass - - -class OrderItem(ResponseElement): - ItemPrice = Element(ComplexMoney) - ShippingPrice = Element(ComplexMoney) - GiftWrapPrice = Element(ComplexMoney) - ItemTax = Element(ComplexMoney) - ShippingTax = Element(ComplexMoney) - GiftWrapTax = Element(ComplexMoney) - ShippingDiscount = Element(ComplexMoney) - PromotionDiscount = Element(ComplexMoney) - PromotionIds = SimpleList() - CODFee = Element(ComplexMoney) - CODFeeDiscount = Element(ComplexMoney) - - -class ListOrderItemsResult(ResponseElement): - OrderItems = Element(OrderItem=ElementList(OrderItem)) - - -class ListMarketplaceParticipationsResult(ResponseElement): - ListParticipations = Element(Participation=ElementList()) - ListMarketplaces = Element(Marketplace=ElementList()) - - -class ListRecommendationsResult(ResponseElement): - ListingQualityRecommendations = MemberList(ItemIdentifier=Element()) - - -class Customer(ResponseElement): - PrimaryContactInfo = Element() - ShippingAddressList = Element(ShippingAddress=ElementList()) - AssociatedMarketplaces = Element(MarketplaceDomain=ElementList()) - - -class ListCustomersResult(ResponseElement): - CustomerList = Element(Customer=ElementList(Customer)) - - -class GetCustomersForCustomerIdResult(ListCustomersResult): - pass - - -class CartItem(ResponseElement): - CurrentPrice = Element(ComplexMoney) - SalePrice = Element(ComplexMoney) - - -class Cart(ResponseElement): - ActiveCartItemList = Element(CartItem=ElementList(CartItem)) - SavedCartItemList = Element(CartItem=ElementList(CartItem)) - - -class ListCartsResult(ResponseElement): - CartList = Element(Cart=ElementList(Cart)) - - -class GetCartsResult(ListCartsResult): - pass - - -class Destination(ResponseElement): - AttributeList = MemberList() - - -class ListRegisteredDestinationsResult(ResponseElement): - DestinationList = MemberList(Destination) - - -class Subscription(ResponseElement): - Destination = Element(Destination) - - -class GetSubscriptionResult(ResponseElement): - Subscription = Element(Subscription) - - -class ListSubscriptionsResult(ResponseElement): - SubscriptionList = MemberList(Subscription) - - -class OrderReferenceDetails(ResponseElement): - Buyer = Element() - OrderTotal = Element(ComplexMoney) - Destination = Element(PhysicalDestination=Element()) - SellerOrderAttributes = Element() - OrderReferenceStatus = Element() - Constraints = ElementList() - - -class SetOrderReferenceDetailsResult(ResponseElement): - OrderReferenceDetails = Element(OrderReferenceDetails) - - -class GetOrderReferenceDetailsResult(SetOrderReferenceDetailsResult): - pass - - -class AuthorizationDetails(ResponseElement): - AuthorizationAmount = Element(ComplexMoney) - CapturedAmount = Element(ComplexMoney) - AuthorizationFee = Element(ComplexMoney) - AuthorizationStatus = Element() - - -class AuthorizeResult(ResponseElement): - AuthorizationDetails = Element(AuthorizationDetails) - - -class GetAuthorizationDetailsResult(AuthorizeResult): - pass - - -class CaptureDetails(ResponseElement): - CaptureAmount = Element(ComplexMoney) - RefundedAmount = Element(ComplexMoney) - CaptureFee = Element(ComplexMoney) - CaptureStatus = Element() - - -class CaptureResult(ResponseElement): - CaptureDetails = Element(CaptureDetails) - - -class GetCaptureDetailsResult(CaptureResult): - pass - - -class RefundDetails(ResponseElement): - RefundAmount = Element(ComplexMoney) - FeeRefunded = Element(ComplexMoney) - RefundStatus = Element() - - -class RefundResult(ResponseElement): - RefundDetails = Element(RefundDetails) - - -class GetRefundDetails(RefundResult): - pass diff --git a/awx/lib/site-packages/boto/opsworks/__init__.py b/awx/lib/site-packages/boto/opsworks/__init__.py deleted file mode 100644 index 1ff5c0f6cf..0000000000 --- a/awx/lib/site-packages/boto/opsworks/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon OpsWorks service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.opsworks.layer1 import OpsWorksConnection - return get_regions('opsworks', connection_cls=OpsWorksConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/opsworks/exceptions.py b/awx/lib/site-packages/boto/opsworks/exceptions.py deleted file mode 100644 index da23e48521..0000000000 --- a/awx/lib/site-packages/boto/opsworks/exceptions.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import JSONResponseError - - -class ResourceNotFoundException(JSONResponseError): - pass - - -class ValidationException(JSONResponseError): - pass diff --git a/awx/lib/site-packages/boto/opsworks/layer1.py b/awx/lib/site-packages/boto/opsworks/layer1.py deleted file mode 100644 index 6610f32a2f..0000000000 --- a/awx/lib/site-packages/boto/opsworks/layer1.py +++ /dev/null @@ -1,2796 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.opsworks import exceptions - - -class OpsWorksConnection(AWSQueryConnection): - """ - AWS OpsWorks - Welcome to the AWS OpsWorks API Reference . This guide provides - descriptions, syntax, and usage examples about AWS OpsWorks - actions and data types, including common parameters and error - codes. - - AWS OpsWorks is an application management service that provides an - integrated experience for overseeing the complete application - lifecycle. For information about this product, go to the `AWS - OpsWorks`_ details page. - - **SDKs and CLI** - - The most common way to use the AWS OpsWorks API is by using the - AWS Command Line Interface (CLI) or by using one of the AWS SDKs - to implement applications in your preferred language. For more - information, see: - - - + `AWS CLI`_ - + `AWS SDK for Java`_ - + `AWS SDK for .NET`_ - + `AWS SDK for PHP 2`_ - + `AWS SDK for Ruby`_ - + `AWS SDK for Node.js`_ - + `AWS SDK for Python(Boto)`_ - - - **Endpoints** - - AWS OpsWorks supports only one endpoint, opsworks.us- - east-1.amazonaws.com (HTTPS), so you must connect to that - endpoint. You can then use the API to direct AWS OpsWorks to - create stacks in any AWS Region. - - **Chef Version** - - When you call CreateStack, CloneStack, or UpdateStack we recommend - you use the `ConfigurationManager` parameter to specify the Chef - version, 0.9, 11.4, or 11.10. The default value is currently 11.4. - For more information, see `Chef Versions`_. - """ - APIVersion = "2013-02-18" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "opsworks.us-east-1.amazonaws.com" - ServiceName = "OpsWorks" - TargetPrefix = "OpsWorks_20130218" - ResponseError = JSONResponseError - - _faults = { - "ResourceNotFoundException": exceptions.ResourceNotFoundException, - "ValidationException": exceptions.ValidationException, - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs or kwargs['host'] is None: - kwargs['host'] = region.endpoint - - super(OpsWorksConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def assign_volume(self, volume_id, instance_id=None): - """ - Assigns one of the stack's registered Amazon EBS volumes to a - specified instance. The volume must first be registered with - the stack by calling RegisterVolume. For more information, see - `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type volume_id: string - :param volume_id: The volume ID. - - :type instance_id: string - :param instance_id: The instance ID. - - """ - params = {'VolumeId': volume_id, } - if instance_id is not None: - params['InstanceId'] = instance_id - return self.make_request(action='AssignVolume', - body=json.dumps(params)) - - def associate_elastic_ip(self, elastic_ip, instance_id=None): - """ - Associates one of the stack's registered Elastic IP addresses - with a specified instance. The address must first be - registered with the stack by calling RegisterElasticIp. For - more information, see `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type elastic_ip: string - :param elastic_ip: The Elastic IP address. - - :type instance_id: string - :param instance_id: The instance ID. - - """ - params = {'ElasticIp': elastic_ip, } - if instance_id is not None: - params['InstanceId'] = instance_id - return self.make_request(action='AssociateElasticIp', - body=json.dumps(params)) - - def attach_elastic_load_balancer(self, elastic_load_balancer_name, - layer_id): - """ - Attaches an Elastic Load Balancing load balancer to a - specified layer. For more information, see `Elastic Load - Balancing`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type elastic_load_balancer_name: string - :param elastic_load_balancer_name: The Elastic Load Balancing - instance's name. - - :type layer_id: string - :param layer_id: The ID of the layer that the Elastic Load Balancing - instance is to be attached to. - - """ - params = { - 'ElasticLoadBalancerName': elastic_load_balancer_name, - 'LayerId': layer_id, - } - return self.make_request(action='AttachElasticLoadBalancer', - body=json.dumps(params)) - - def clone_stack(self, source_stack_id, service_role_arn, name=None, - region=None, vpc_id=None, attributes=None, - default_instance_profile_arn=None, default_os=None, - hostname_theme=None, default_availability_zone=None, - default_subnet_id=None, custom_json=None, - configuration_manager=None, chef_configuration=None, - use_custom_cookbooks=None, - use_opsworks_security_groups=None, - custom_cookbooks_source=None, default_ssh_key_name=None, - clone_permissions=None, clone_app_ids=None, - default_root_device_type=None): - """ - Creates a clone of a specified stack. For more information, - see `Clone a Stack`_. - - **Required Permissions**: To use this action, an IAM user must - have an attached policy that explicitly grants permissions. - For more information on user permissions, see `Managing User - Permissions`_. - - :type source_stack_id: string - :param source_stack_id: The source stack ID. - - :type name: string - :param name: The cloned stack name. - - :type region: string - :param region: The cloned stack AWS region, such as "us-east-1". For - more information about AWS regions, see `Regions and Endpoints`_. - - :type vpc_id: string - :param vpc_id: The ID of the VPC that the cloned stack is to be - launched into. It must be in the specified region. All instances - will be launched into this VPC, and you cannot change the ID later. - - + If your account supports EC2 Classic, the default value is no VPC. - + If your account does not support EC2 Classic, the default value is - the default VPC for the specified region. - - - If the VPC ID corresponds to a default VPC and you have specified - either the `DefaultAvailabilityZone` or the `DefaultSubnetId` - parameter only, AWS OpsWorks infers the value of the other - parameter. If you specify neither parameter, AWS OpsWorks sets - these parameters to the first valid Availability Zone for the - specified region and the corresponding default VPC subnet ID, - respectively. - - If you specify a nondefault VPC ID, note the following: - - - + It must belong to a VPC in your account that is in the specified - region. - + You must specify a value for `DefaultSubnetId`. - - - For more information on how to use AWS OpsWorks with a VPC, see - `Running a Stack in a VPC`_. For more information on default VPC - and EC2 Classic, see `Supported Platforms`_. - - :type attributes: map - :param attributes: A list of stack attributes and values as key/value - pairs to be added to the cloned stack. - - :type service_role_arn: string - :param service_role_arn: The stack AWS Identity and Access Management - (IAM) role, which allows AWS OpsWorks to work with AWS resources on - your behalf. You must set this parameter to the Amazon Resource - Name (ARN) for an existing IAM role. If you create a stack by using - the AWS OpsWorks console, it creates the role for you. You can - obtain an existing stack's IAM ARN programmatically by calling - DescribePermissions. For more information about IAM ARNs, see - `Using Identifiers`_. - - :type default_instance_profile_arn: string - :param default_instance_profile_arn: The ARN of an IAM profile that is - the default profile for all of the stack's EC2 instances. For more - information about IAM ARNs, see `Using Identifiers`_. - - :type default_os: string - :param default_os: The cloned stack's default operating system, which - must be set to `Amazon Linux` or `Ubuntu 12.04 LTS`. The default - option is `Amazon Linux`. - - :type hostname_theme: string - :param hostname_theme: The stack's host name theme, with spaces are - replaced by underscores. The theme is used to generate host names - for the stack's instances. By default, `HostnameTheme` is set to - `Layer_Dependent`, which creates host names by appending integers - to the layer's short name. The other themes are: - - + `Baked_Goods` - + `Clouds` - + `European_Cities` - + `Fruits` - + `Greek_Deities` - + `Legendary_Creatures_from_Japan` - + `Planets_and_Moons` - + `Roman_Deities` - + `Scottish_Islands` - + `US_Cities` - + `Wild_Cats` - - - To obtain a generated host name, call `GetHostNameSuggestion`, which - returns a host name based on the current theme. - - :type default_availability_zone: string - :param default_availability_zone: The cloned stack's default - Availability Zone, which must be in the specified region. For more - information, see `Regions and Endpoints`_. If you also specify a - value for `DefaultSubnetId`, the subnet must be in the same zone. - For more information, see the `VpcId` parameter description. - - :type default_subnet_id: string - :param default_subnet_id: The stack's default subnet ID. All instances - will be launched into this subnet unless you specify otherwise when - you create the instance. If you also specify a value for - `DefaultAvailabilityZone`, the subnet must be in the same zone. For - information on default values and when this parameter is required, - see the `VpcId` parameter description. - - :type custom_json: string - :param custom_json: A string that contains user-defined, custom JSON. - It is used to override the corresponding default stack - configuration JSON values. The string should be in the following - format and must escape characters such as '"'.: - `"{\"key1\": \"value1\", \"key2\": \"value2\",...}"` - - For more information on custom JSON, see `Use Custom JSON to Modify the - Stack Configuration JSON`_ - - :type configuration_manager: dict - :param configuration_manager: The configuration manager. When you clone - a stack we recommend that you use the configuration manager to - specify the Chef version, 0.9, 11.4, or 11.10. The default value is - currently 11.4. - - :type chef_configuration: dict - :param chef_configuration: A `ChefConfiguration` object that specifies - whether to enable Berkshelf and the Berkshelf version on Chef 11.10 - stacks. For more information, see `Create a New Stack`_. - - :type use_custom_cookbooks: boolean - :param use_custom_cookbooks: Whether to use custom cookbooks. - - :type use_opsworks_security_groups: boolean - :param use_opsworks_security_groups: Whether to associate the AWS - OpsWorks built-in security groups with the stack's layers. - AWS OpsWorks provides a standard set of built-in security groups, one - for each layer, which are associated with layers by default. With - `UseOpsworksSecurityGroups` you can instead provide your own custom - security groups. `UseOpsworksSecurityGroups` has the following - settings: - - - + True - AWS OpsWorks automatically associates the appropriate built-in - security group with each layer (default setting). You can associate - additional security groups with a layer after you create it but you - cannot delete the built-in security group. - + False - AWS OpsWorks does not associate built-in security groups with - layers. You must create appropriate EC2 security groups and - associate a security group with each layer that you create. - However, you can still manually associate a built-in security group - with a layer on creation; custom security groups are required only - for those layers that need custom settings. - - - For more information, see `Create a New Stack`_. - - :type custom_cookbooks_source: dict - :param custom_cookbooks_source: Contains the information required to - retrieve an app or cookbook from a repository. For more - information, see `Creating Apps`_ or `Custom Recipes and - Cookbooks`_. - - :type default_ssh_key_name: string - :param default_ssh_key_name: A default SSH key for the stack instances. - You can override this value when you create or update an instance. - - :type clone_permissions: boolean - :param clone_permissions: Whether to clone the source stack's - permissions. - - :type clone_app_ids: list - :param clone_app_ids: A list of source stack app IDs to be included in - the cloned stack. - - :type default_root_device_type: string - :param default_root_device_type: The default root device type. This - value is used by default for all instances in the cloned stack, but - you can override it when you create an instance. For more - information, see `Storage for the Root Device`_. - - """ - params = { - 'SourceStackId': source_stack_id, - 'ServiceRoleArn': service_role_arn, - } - if name is not None: - params['Name'] = name - if region is not None: - params['Region'] = region - if vpc_id is not None: - params['VpcId'] = vpc_id - if attributes is not None: - params['Attributes'] = attributes - if default_instance_profile_arn is not None: - params['DefaultInstanceProfileArn'] = default_instance_profile_arn - if default_os is not None: - params['DefaultOs'] = default_os - if hostname_theme is not None: - params['HostnameTheme'] = hostname_theme - if default_availability_zone is not None: - params['DefaultAvailabilityZone'] = default_availability_zone - if default_subnet_id is not None: - params['DefaultSubnetId'] = default_subnet_id - if custom_json is not None: - params['CustomJson'] = custom_json - if configuration_manager is not None: - params['ConfigurationManager'] = configuration_manager - if chef_configuration is not None: - params['ChefConfiguration'] = chef_configuration - if use_custom_cookbooks is not None: - params['UseCustomCookbooks'] = use_custom_cookbooks - if use_opsworks_security_groups is not None: - params['UseOpsworksSecurityGroups'] = use_opsworks_security_groups - if custom_cookbooks_source is not None: - params['CustomCookbooksSource'] = custom_cookbooks_source - if default_ssh_key_name is not None: - params['DefaultSshKeyName'] = default_ssh_key_name - if clone_permissions is not None: - params['ClonePermissions'] = clone_permissions - if clone_app_ids is not None: - params['CloneAppIds'] = clone_app_ids - if default_root_device_type is not None: - params['DefaultRootDeviceType'] = default_root_device_type - return self.make_request(action='CloneStack', - body=json.dumps(params)) - - def create_app(self, stack_id, name, type, shortname=None, - description=None, data_sources=None, app_source=None, - domains=None, enable_ssl=None, ssl_configuration=None, - attributes=None): - """ - Creates an app for a specified stack. For more information, - see `Creating Apps`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - :type shortname: string - :param shortname: The app's short name. - - :type name: string - :param name: The app name. - - :type description: string - :param description: A description of the app. - - :type data_sources: list - :param data_sources: The app's data source. - - :type type: string - :param type: The app type. Each supported type is associated with a - particular layer. For example, PHP applications are associated with - a PHP layer. AWS OpsWorks deploys an application to those instances - that are members of the corresponding layer. - - :type app_source: dict - :param app_source: A `Source` object that specifies the app repository. - - :type domains: list - :param domains: The app virtual host settings, with multiple domains - separated by commas. For example: `'www.example.com, example.com'` - - :type enable_ssl: boolean - :param enable_ssl: Whether to enable SSL for the app. - - :type ssl_configuration: dict - :param ssl_configuration: An `SslConfiguration` object with the SSL - configuration. - - :type attributes: map - :param attributes: One or more user-defined key/value pairs to be added - to the stack attributes. - - """ - params = {'StackId': stack_id, 'Name': name, 'Type': type, } - if shortname is not None: - params['Shortname'] = shortname - if description is not None: - params['Description'] = description - if data_sources is not None: - params['DataSources'] = data_sources - if app_source is not None: - params['AppSource'] = app_source - if domains is not None: - params['Domains'] = domains - if enable_ssl is not None: - params['EnableSsl'] = enable_ssl - if ssl_configuration is not None: - params['SslConfiguration'] = ssl_configuration - if attributes is not None: - params['Attributes'] = attributes - return self.make_request(action='CreateApp', - body=json.dumps(params)) - - def create_deployment(self, stack_id, command, app_id=None, - instance_ids=None, comment=None, custom_json=None): - """ - Deploys a stack or app. - - - + App deployment generates a `deploy` event, which runs the - associated recipes and passes them a JSON stack configuration - object that includes information about the app. - + Stack deployment runs the `deploy` recipes but does not - raise an event. - - - For more information, see `Deploying Apps`_ and `Run Stack - Commands`_. - - **Required Permissions**: To use this action, an IAM user must - have a Deploy or Manage permissions level for the stack, or an - attached policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - :type app_id: string - :param app_id: The app ID. This parameter is required for app - deployments, but not for other deployment commands. - - :type instance_ids: list - :param instance_ids: The instance IDs for the deployment targets. - - :type command: dict - :param command: A `DeploymentCommand` object that specifies the - deployment command and any associated arguments. - - :type comment: string - :param comment: A user-defined comment. - - :type custom_json: string - :param custom_json: A string that contains user-defined, custom JSON. - It is used to override the corresponding default stack - configuration JSON values. The string should be in the following - format and must escape characters such as '"'.: - `"{\"key1\": \"value1\", \"key2\": \"value2\",...}"` - - For more information on custom JSON, see `Use Custom JSON to Modify the - Stack Configuration JSON`_. - - """ - params = {'StackId': stack_id, 'Command': command, } - if app_id is not None: - params['AppId'] = app_id - if instance_ids is not None: - params['InstanceIds'] = instance_ids - if comment is not None: - params['Comment'] = comment - if custom_json is not None: - params['CustomJson'] = custom_json - return self.make_request(action='CreateDeployment', - body=json.dumps(params)) - - def create_instance(self, stack_id, layer_ids, instance_type, - auto_scaling_type=None, hostname=None, os=None, - ami_id=None, ssh_key_name=None, - availability_zone=None, virtualization_type=None, - subnet_id=None, architecture=None, - root_device_type=None, install_updates_on_boot=None, - ebs_optimized=None): - """ - Creates an instance in a specified stack. For more - information, see `Adding an Instance to a Layer`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - :type layer_ids: list - :param layer_ids: An array that contains the instance layer IDs. - - :type instance_type: string - :param instance_type: The instance type. AWS OpsWorks supports all - instance types except Cluster Compute, Cluster GPU, and High Memory - Cluster. For more information, see `Instance Families and Types`_. - The parameter values that you use to specify the various types are - in the API Name column of the Available Instance Types table. - - :type auto_scaling_type: string - :param auto_scaling_type: - The instance auto scaling type, which has three possible values: - - - + **AlwaysRunning**: A 24/7 instance, which is not affected by auto - scaling. - + **TimeBasedAutoScaling**: A time-based auto scaling instance, which - is started and stopped based on a specified schedule. To specify - the schedule, call SetTimeBasedAutoScaling. - + **LoadBasedAutoScaling**: A load-based auto scaling instance, which - is started and stopped based on load metrics. To use load-based - auto scaling, you must enable it for the instance layer and - configure the thresholds by calling SetLoadBasedAutoScaling. - - :type hostname: string - :param hostname: The instance host name. - - :type os: string - :param os: The instance operating system, which must be set to one of - the following. - - + Standard operating systems: `Amazon Linux` or `Ubuntu 12.04 LTS` - + Custom AMIs: `Custom` - - - The default option is `Amazon Linux`. If you set this parameter to - `Custom`, you must use the CreateInstance action's AmiId parameter - to specify the custom AMI that you want to use. For more - information on the standard operating systems, see `Operating - Systems`_For more information on how to use custom AMIs with - OpsWorks, see `Using Custom AMIs`_. - - :type ami_id: string - :param ami_id: A custom AMI ID to be used to create the instance. The - AMI should be based on one of the standard AWS OpsWorks APIs: - Amazon Linux or Ubuntu 12.04 LTS. For more information, see - `Instances`_ - - :type ssh_key_name: string - :param ssh_key_name: The instance SSH key name. - - :type availability_zone: string - :param availability_zone: The instance Availability Zone. For more - information, see `Regions and Endpoints`_. - - :type virtualization_type: string - :param virtualization_type: The instance's virtualization type, - `paravirtual` or `hvm`. - - :type subnet_id: string - :param subnet_id: The ID of the instance's subnet. If the stack is - running in a VPC, you can use this parameter to override the - stack's default subnet ID value and direct AWS OpsWorks to launch - the instance in a different subnet. - - :type architecture: string - :param architecture: The instance architecture. The default option is - `x86_64`. Instance types do not necessarily support both - architectures. For a list of the architectures that are supported - by the different instance types, see `Instance Families and - Types`_. - - :type root_device_type: string - :param root_device_type: The instance root device type. For more - information, see `Storage for the Root Device`_. - - :type install_updates_on_boot: boolean - :param install_updates_on_boot: Whether to install operating system and - package updates when the instance boots. The default value is - `True`. To control when updates are installed, set this value to - `False`. You must then update your instances manually by using - CreateDeployment to run the `update_dependencies` stack command or - manually running `yum` (Amazon Linux) or `apt-get` (Ubuntu) on the - instances. - - :type ebs_optimized: boolean - :param ebs_optimized: Whether to create an Amazon EBS-optimized - instance. - - """ - params = { - 'StackId': stack_id, - 'LayerIds': layer_ids, - 'InstanceType': instance_type, - } - if auto_scaling_type is not None: - params['AutoScalingType'] = auto_scaling_type - if hostname is not None: - params['Hostname'] = hostname - if os is not None: - params['Os'] = os - if ami_id is not None: - params['AmiId'] = ami_id - if ssh_key_name is not None: - params['SshKeyName'] = ssh_key_name - if availability_zone is not None: - params['AvailabilityZone'] = availability_zone - if virtualization_type is not None: - params['VirtualizationType'] = virtualization_type - if subnet_id is not None: - params['SubnetId'] = subnet_id - if architecture is not None: - params['Architecture'] = architecture - if root_device_type is not None: - params['RootDeviceType'] = root_device_type - if install_updates_on_boot is not None: - params['InstallUpdatesOnBoot'] = install_updates_on_boot - if ebs_optimized is not None: - params['EbsOptimized'] = ebs_optimized - return self.make_request(action='CreateInstance', - body=json.dumps(params)) - - def create_layer(self, stack_id, type, name, shortname, attributes=None, - custom_instance_profile_arn=None, - custom_security_group_ids=None, packages=None, - volume_configurations=None, enable_auto_healing=None, - auto_assign_elastic_ips=None, - auto_assign_public_ips=None, custom_recipes=None, - install_updates_on_boot=None, - use_ebs_optimized_instances=None): - """ - Creates a layer. For more information, see `How to Create a - Layer`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The layer stack ID. - - :type type: string - :param type: - The layer type. A stack cannot have more than one built-in layer of the - same type. It can have any number of custom layers. This parameter - must be set to one of the following: - - - + custom: A custom layer - + db-master: A MySQL layer - + java-app: A Java App Server layer - + rails-app: A Rails App Server layer - + lb: An HAProxy layer - + memcached: A Memcached layer - + monitoring-master: A Ganglia layer - + nodejs-app: A Node.js App Server layer - + php-app: A PHP App Server layer - + web: A Static Web Server layer - - :type name: string - :param name: The layer name, which is used by the console. - - :type shortname: string - :param shortname: The layer short name, which is used internally by AWS - OpsWorks and by Chef recipes. The short name is also used as the - name for the directory where your app files are installed. It can - have a maximum of 200 characters, which are limited to the - alphanumeric characters, '-', '_', and '.'. - - :type attributes: map - :param attributes: One or more user-defined key/value pairs to be added - to the stack attributes. - - :type custom_instance_profile_arn: string - :param custom_instance_profile_arn: The ARN of an IAM profile that to - be used for the layer's EC2 instances. For more information about - IAM ARNs, see `Using Identifiers`_. - - :type custom_security_group_ids: list - :param custom_security_group_ids: An array containing the layer custom - security group IDs. - - :type packages: list - :param packages: An array of `Package` objects that describe the layer - packages. - - :type volume_configurations: list - :param volume_configurations: A `VolumeConfigurations` object that - describes the layer's Amazon EBS volumes. - - :type enable_auto_healing: boolean - :param enable_auto_healing: Whether to disable auto healing for the - layer. - - :type auto_assign_elastic_ips: boolean - :param auto_assign_elastic_ips: Whether to automatically assign an - `Elastic IP address`_ to the layer's instances. For more - information, see `How to Edit a Layer`_. - - :type auto_assign_public_ips: boolean - :param auto_assign_public_ips: For stacks that are running in a VPC, - whether to automatically assign a public IP address to the layer's - instances. For more information, see `How to Edit a Layer`_. - - :type custom_recipes: dict - :param custom_recipes: A `LayerCustomRecipes` object that specifies the - layer custom recipes. - - :type install_updates_on_boot: boolean - :param install_updates_on_boot: Whether to install operating system and - package updates when the instance boots. The default value is - `True`. To control when updates are installed, set this value to - `False`. You must then update your instances manually by using - CreateDeployment to run the `update_dependencies` stack command or - manually running `yum` (Amazon Linux) or `apt-get` (Ubuntu) on the - instances. - - :type use_ebs_optimized_instances: boolean - :param use_ebs_optimized_instances: Whether to use Amazon EBS-optimized - instances. - - """ - params = { - 'StackId': stack_id, - 'Type': type, - 'Name': name, - 'Shortname': shortname, - } - if attributes is not None: - params['Attributes'] = attributes - if custom_instance_profile_arn is not None: - params['CustomInstanceProfileArn'] = custom_instance_profile_arn - if custom_security_group_ids is not None: - params['CustomSecurityGroupIds'] = custom_security_group_ids - if packages is not None: - params['Packages'] = packages - if volume_configurations is not None: - params['VolumeConfigurations'] = volume_configurations - if enable_auto_healing is not None: - params['EnableAutoHealing'] = enable_auto_healing - if auto_assign_elastic_ips is not None: - params['AutoAssignElasticIps'] = auto_assign_elastic_ips - if auto_assign_public_ips is not None: - params['AutoAssignPublicIps'] = auto_assign_public_ips - if custom_recipes is not None: - params['CustomRecipes'] = custom_recipes - if install_updates_on_boot is not None: - params['InstallUpdatesOnBoot'] = install_updates_on_boot - if use_ebs_optimized_instances is not None: - params['UseEbsOptimizedInstances'] = use_ebs_optimized_instances - return self.make_request(action='CreateLayer', - body=json.dumps(params)) - - def create_stack(self, name, region, service_role_arn, - default_instance_profile_arn, vpc_id=None, - attributes=None, default_os=None, hostname_theme=None, - default_availability_zone=None, default_subnet_id=None, - custom_json=None, configuration_manager=None, - chef_configuration=None, use_custom_cookbooks=None, - use_opsworks_security_groups=None, - custom_cookbooks_source=None, default_ssh_key_name=None, - default_root_device_type=None): - """ - Creates a new stack. For more information, see `Create a New - Stack`_. - - **Required Permissions**: To use this action, an IAM user must - have an attached policy that explicitly grants permissions. - For more information on user permissions, see `Managing User - Permissions`_. - - :type name: string - :param name: The stack name. - - :type region: string - :param region: The stack AWS region, such as "us-east-1". For more - information about Amazon regions, see `Regions and Endpoints`_. - - :type vpc_id: string - :param vpc_id: The ID of the VPC that the stack is to be launched into. - It must be in the specified region. All instances will be launched - into this VPC, and you cannot change the ID later. - - + If your account supports EC2 Classic, the default value is no VPC. - + If your account does not support EC2 Classic, the default value is - the default VPC for the specified region. - - - If the VPC ID corresponds to a default VPC and you have specified - either the `DefaultAvailabilityZone` or the `DefaultSubnetId` - parameter only, AWS OpsWorks infers the value of the other - parameter. If you specify neither parameter, AWS OpsWorks sets - these parameters to the first valid Availability Zone for the - specified region and the corresponding default VPC subnet ID, - respectively. - - If you specify a nondefault VPC ID, note the following: - - - + It must belong to a VPC in your account that is in the specified - region. - + You must specify a value for `DefaultSubnetId`. - - - For more information on how to use AWS OpsWorks with a VPC, see - `Running a Stack in a VPC`_. For more information on default VPC - and EC2 Classic, see `Supported Platforms`_. - - :type attributes: map - :param attributes: One or more user-defined key/value pairs to be added - to the stack attributes. - - :type service_role_arn: string - :param service_role_arn: The stack AWS Identity and Access Management - (IAM) role, which allows AWS OpsWorks to work with AWS resources on - your behalf. You must set this parameter to the Amazon Resource - Name (ARN) for an existing IAM role. For more information about IAM - ARNs, see `Using Identifiers`_. - - :type default_instance_profile_arn: string - :param default_instance_profile_arn: The ARN of an IAM profile that is - the default profile for all of the stack's EC2 instances. For more - information about IAM ARNs, see `Using Identifiers`_. - - :type default_os: string - :param default_os: The stack's default operating system, which must be - set to `Amazon Linux` or `Ubuntu 12.04 LTS`. The default option is - `Amazon Linux`. - - :type hostname_theme: string - :param hostname_theme: The stack's host name theme, with spaces are - replaced by underscores. The theme is used to generate host names - for the stack's instances. By default, `HostnameTheme` is set to - `Layer_Dependent`, which creates host names by appending integers - to the layer's short name. The other themes are: - - + `Baked_Goods` - + `Clouds` - + `European_Cities` - + `Fruits` - + `Greek_Deities` - + `Legendary_Creatures_from_Japan` - + `Planets_and_Moons` - + `Roman_Deities` - + `Scottish_Islands` - + `US_Cities` - + `Wild_Cats` - - - To obtain a generated host name, call `GetHostNameSuggestion`, which - returns a host name based on the current theme. - - :type default_availability_zone: string - :param default_availability_zone: The stack's default Availability - Zone, which must be in the specified region. For more information, - see `Regions and Endpoints`_. If you also specify a value for - `DefaultSubnetId`, the subnet must be in the same zone. For more - information, see the `VpcId` parameter description. - - :type default_subnet_id: string - :param default_subnet_id: The stack's default subnet ID. All instances - will be launched into this subnet unless you specify otherwise when - you create the instance. If you also specify a value for - `DefaultAvailabilityZone`, the subnet must be in that zone. For - information on default values and when this parameter is required, - see the `VpcId` parameter description. - - :type custom_json: string - :param custom_json: A string that contains user-defined, custom JSON. - It is used to override the corresponding default stack - configuration JSON values. The string should be in the following - format and must escape characters such as '"'.: - `"{\"key1\": \"value1\", \"key2\": \"value2\",...}"` - - For more information on custom JSON, see `Use Custom JSON to Modify the - Stack Configuration JSON`_. - - :type configuration_manager: dict - :param configuration_manager: The configuration manager. When you clone - a stack we recommend that you use the configuration manager to - specify the Chef version, 0.9, 11.4, or 11.10. The default value is - currently 11.4. - - :type chef_configuration: dict - :param chef_configuration: A `ChefConfiguration` object that specifies - whether to enable Berkshelf and the Berkshelf version on Chef 11.10 - stacks. For more information, see `Create a New Stack`_. - - :type use_custom_cookbooks: boolean - :param use_custom_cookbooks: Whether the stack uses custom cookbooks. - - :type use_opsworks_security_groups: boolean - :param use_opsworks_security_groups: Whether to associate the AWS - OpsWorks built-in security groups with the stack's layers. - AWS OpsWorks provides a standard set of built-in security groups, one - for each layer, which are associated with layers by default. With - `UseOpsworksSecurityGroups` you can instead provide your own custom - security groups. `UseOpsworksSecurityGroups` has the following - settings: - - - + True - AWS OpsWorks automatically associates the appropriate built-in - security group with each layer (default setting). You can associate - additional security groups with a layer after you create it but you - cannot delete the built-in security group. - + False - AWS OpsWorks does not associate built-in security groups with - layers. You must create appropriate EC2 security groups and - associate a security group with each layer that you create. - However, you can still manually associate a built-in security group - with a layer on creation; custom security groups are required only - for those layers that need custom settings. - - - For more information, see `Create a New Stack`_. - - :type custom_cookbooks_source: dict - :param custom_cookbooks_source: Contains the information required to - retrieve an app or cookbook from a repository. For more - information, see `Creating Apps`_ or `Custom Recipes and - Cookbooks`_. - - :type default_ssh_key_name: string - :param default_ssh_key_name: A default SSH key for the stack instances. - You can override this value when you create or update an instance. - - :type default_root_device_type: string - :param default_root_device_type: The default root device type. This - value is used by default for all instances in the stack, but you - can override it when you create an instance. The default option is - `instance-store`. For more information, see `Storage for the Root - Device`_. - - """ - params = { - 'Name': name, - 'Region': region, - 'ServiceRoleArn': service_role_arn, - 'DefaultInstanceProfileArn': default_instance_profile_arn, - } - if vpc_id is not None: - params['VpcId'] = vpc_id - if attributes is not None: - params['Attributes'] = attributes - if default_os is not None: - params['DefaultOs'] = default_os - if hostname_theme is not None: - params['HostnameTheme'] = hostname_theme - if default_availability_zone is not None: - params['DefaultAvailabilityZone'] = default_availability_zone - if default_subnet_id is not None: - params['DefaultSubnetId'] = default_subnet_id - if custom_json is not None: - params['CustomJson'] = custom_json - if configuration_manager is not None: - params['ConfigurationManager'] = configuration_manager - if chef_configuration is not None: - params['ChefConfiguration'] = chef_configuration - if use_custom_cookbooks is not None: - params['UseCustomCookbooks'] = use_custom_cookbooks - if use_opsworks_security_groups is not None: - params['UseOpsworksSecurityGroups'] = use_opsworks_security_groups - if custom_cookbooks_source is not None: - params['CustomCookbooksSource'] = custom_cookbooks_source - if default_ssh_key_name is not None: - params['DefaultSshKeyName'] = default_ssh_key_name - if default_root_device_type is not None: - params['DefaultRootDeviceType'] = default_root_device_type - return self.make_request(action='CreateStack', - body=json.dumps(params)) - - def create_user_profile(self, iam_user_arn, ssh_username=None, - ssh_public_key=None, allow_self_management=None): - """ - Creates a new user profile. - - **Required Permissions**: To use this action, an IAM user must - have an attached policy that explicitly grants permissions. - For more information on user permissions, see `Managing User - Permissions`_. - - :type iam_user_arn: string - :param iam_user_arn: The user's IAM ARN. - - :type ssh_username: string - :param ssh_username: The user's SSH user name. The allowable characters - are [a-z], [A-Z], [0-9], '-', and '_'. If the specified name - includes other punctuation marks, AWS OpsWorks removes them. For - example, `my.name` will be changed to `myname`. If you do not - specify an SSH user name, AWS OpsWorks generates one from the IAM - user name. - - :type ssh_public_key: string - :param ssh_public_key: The user's public SSH key. - - :type allow_self_management: boolean - :param allow_self_management: Whether users can specify their own SSH - public key through the My Settings page. For more information, see - `Setting an IAM User's Public SSH Key`_. - - """ - params = {'IamUserArn': iam_user_arn, } - if ssh_username is not None: - params['SshUsername'] = ssh_username - if ssh_public_key is not None: - params['SshPublicKey'] = ssh_public_key - if allow_self_management is not None: - params['AllowSelfManagement'] = allow_self_management - return self.make_request(action='CreateUserProfile', - body=json.dumps(params)) - - def delete_app(self, app_id): - """ - Deletes a specified app. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type app_id: string - :param app_id: The app ID. - - """ - params = {'AppId': app_id, } - return self.make_request(action='DeleteApp', - body=json.dumps(params)) - - def delete_instance(self, instance_id, delete_elastic_ip=None, - delete_volumes=None): - """ - Deletes a specified instance. You must stop an instance before - you can delete it. For more information, see `Deleting - Instances`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. - - :type delete_elastic_ip: boolean - :param delete_elastic_ip: Whether to delete the instance Elastic IP - address. - - :type delete_volumes: boolean - :param delete_volumes: Whether to delete the instance's Amazon EBS - volumes. - - """ - params = {'InstanceId': instance_id, } - if delete_elastic_ip is not None: - params['DeleteElasticIp'] = delete_elastic_ip - if delete_volumes is not None: - params['DeleteVolumes'] = delete_volumes - return self.make_request(action='DeleteInstance', - body=json.dumps(params)) - - def delete_layer(self, layer_id): - """ - Deletes a specified layer. You must first stop and then delete - all associated instances. For more information, see `How to - Delete a Layer`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type layer_id: string - :param layer_id: The layer ID. - - """ - params = {'LayerId': layer_id, } - return self.make_request(action='DeleteLayer', - body=json.dumps(params)) - - def delete_stack(self, stack_id): - """ - Deletes a specified stack. You must first delete all - instances, layers, and apps. For more information, see `Shut - Down a Stack`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - """ - params = {'StackId': stack_id, } - return self.make_request(action='DeleteStack', - body=json.dumps(params)) - - def delete_user_profile(self, iam_user_arn): - """ - Deletes a user profile. - - **Required Permissions**: To use this action, an IAM user must - have an attached policy that explicitly grants permissions. - For more information on user permissions, see `Managing User - Permissions`_. - - :type iam_user_arn: string - :param iam_user_arn: The user's IAM ARN. - - """ - params = {'IamUserArn': iam_user_arn, } - return self.make_request(action='DeleteUserProfile', - body=json.dumps(params)) - - def deregister_elastic_ip(self, elastic_ip): - """ - Deregisters a specified Elastic IP address. The address can - then be registered by another stack. For more information, see - `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type elastic_ip: string - :param elastic_ip: The Elastic IP address. - - """ - params = {'ElasticIp': elastic_ip, } - return self.make_request(action='DeregisterElasticIp', - body=json.dumps(params)) - - def deregister_rds_db_instance(self, rds_db_instance_arn): - """ - Deregisters an Amazon RDS instance. - - :type rds_db_instance_arn: string - :param rds_db_instance_arn: The Amazon RDS instance's ARN. - - """ - params = {'RdsDbInstanceArn': rds_db_instance_arn, } - return self.make_request(action='DeregisterRdsDbInstance', - body=json.dumps(params)) - - def deregister_volume(self, volume_id): - """ - Deregisters an Amazon EBS volume. The volume can then be - registered by another stack. For more information, see - `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type volume_id: string - :param volume_id: The volume ID. - - """ - params = {'VolumeId': volume_id, } - return self.make_request(action='DeregisterVolume', - body=json.dumps(params)) - - def describe_apps(self, stack_id=None, app_ids=None): - """ - Requests a description of a specified set of apps. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_id: string - :param stack_id: The app stack ID. If you use this parameter, - `DescribeApps` returns a description of the apps in the specified - stack. - - :type app_ids: list - :param app_ids: An array of app IDs for the apps to be described. If - you use this parameter, `DescribeApps` returns a description of the - specified apps. Otherwise, it returns a description of every app. - - """ - params = {} - if stack_id is not None: - params['StackId'] = stack_id - if app_ids is not None: - params['AppIds'] = app_ids - return self.make_request(action='DescribeApps', - body=json.dumps(params)) - - def describe_commands(self, deployment_id=None, instance_id=None, - command_ids=None): - """ - Describes the results of specified commands. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type deployment_id: string - :param deployment_id: The deployment ID. If you include this parameter, - `DescribeCommands` returns a description of the commands associated - with the specified deployment. - - :type instance_id: string - :param instance_id: The instance ID. If you include this parameter, - `DescribeCommands` returns a description of the commands associated - with the specified instance. - - :type command_ids: list - :param command_ids: An array of command IDs. If you include this - parameter, `DescribeCommands` returns a description of the - specified commands. Otherwise, it returns a description of every - command. - - """ - params = {} - if deployment_id is not None: - params['DeploymentId'] = deployment_id - if instance_id is not None: - params['InstanceId'] = instance_id - if command_ids is not None: - params['CommandIds'] = command_ids - return self.make_request(action='DescribeCommands', - body=json.dumps(params)) - - def describe_deployments(self, stack_id=None, app_id=None, - deployment_ids=None): - """ - Requests a description of a specified set of deployments. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. If you include this parameter, - `DescribeDeployments` returns a description of the commands - associated with the specified stack. - - :type app_id: string - :param app_id: The app ID. If you include this parameter, - `DescribeDeployments` returns a description of the commands - associated with the specified app. - - :type deployment_ids: list - :param deployment_ids: An array of deployment IDs to be described. If - you include this parameter, `DescribeDeployments` returns a - description of the specified deployments. Otherwise, it returns a - description of every deployment. - - """ - params = {} - if stack_id is not None: - params['StackId'] = stack_id - if app_id is not None: - params['AppId'] = app_id - if deployment_ids is not None: - params['DeploymentIds'] = deployment_ids - return self.make_request(action='DescribeDeployments', - body=json.dumps(params)) - - def describe_elastic_ips(self, instance_id=None, stack_id=None, ips=None): - """ - Describes `Elastic IP addresses`_. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. If you include this parameter, - `DescribeElasticIps` returns a description of the Elastic IP - addresses associated with the specified instance. - - :type stack_id: string - :param stack_id: A stack ID. If you include this parameter, - `DescribeElasticIps` returns a description of the Elastic IP - addresses that are registered with the specified stack. - - :type ips: list - :param ips: An array of Elastic IP addresses to be described. If you - include this parameter, `DescribeElasticIps` returns a description - of the specified Elastic IP addresses. Otherwise, it returns a - description of every Elastic IP address. - - """ - params = {} - if instance_id is not None: - params['InstanceId'] = instance_id - if stack_id is not None: - params['StackId'] = stack_id - if ips is not None: - params['Ips'] = ips - return self.make_request(action='DescribeElasticIps', - body=json.dumps(params)) - - def describe_elastic_load_balancers(self, stack_id=None, layer_ids=None): - """ - Describes a stack's Elastic Load Balancing instances. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_id: string - :param stack_id: A stack ID. The action describes the stack's Elastic - Load Balancing instances. - - :type layer_ids: list - :param layer_ids: A list of layer IDs. The action describes the Elastic - Load Balancing instances for the specified layers. - - """ - params = {} - if stack_id is not None: - params['StackId'] = stack_id - if layer_ids is not None: - params['LayerIds'] = layer_ids - return self.make_request(action='DescribeElasticLoadBalancers', - body=json.dumps(params)) - - def describe_instances(self, stack_id=None, layer_id=None, - instance_ids=None): - """ - Requests a description of a set of instances. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_id: string - :param stack_id: A stack ID. If you use this parameter, - `DescribeInstances` returns descriptions of the instances - associated with the specified stack. - - :type layer_id: string - :param layer_id: A layer ID. If you use this parameter, - `DescribeInstances` returns descriptions of the instances - associated with the specified layer. - - :type instance_ids: list - :param instance_ids: An array of instance IDs to be described. If you - use this parameter, `DescribeInstances` returns a description of - the specified instances. Otherwise, it returns a description of - every instance. - - """ - params = {} - if stack_id is not None: - params['StackId'] = stack_id - if layer_id is not None: - params['LayerId'] = layer_id - if instance_ids is not None: - params['InstanceIds'] = instance_ids - return self.make_request(action='DescribeInstances', - body=json.dumps(params)) - - def describe_layers(self, stack_id=None, layer_ids=None): - """ - Requests a description of one or more layers in a specified - stack. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - :type layer_ids: list - :param layer_ids: An array of layer IDs that specify the layers to be - described. If you omit this parameter, `DescribeLayers` returns a - description of every layer in the specified stack. - - """ - params = {} - if stack_id is not None: - params['StackId'] = stack_id - if layer_ids is not None: - params['LayerIds'] = layer_ids - return self.make_request(action='DescribeLayers', - body=json.dumps(params)) - - def describe_load_based_auto_scaling(self, layer_ids): - """ - Describes load-based auto scaling configurations for specified - layers. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type layer_ids: list - :param layer_ids: An array of layer IDs. - - """ - params = {'LayerIds': layer_ids, } - return self.make_request(action='DescribeLoadBasedAutoScaling', - body=json.dumps(params)) - - def describe_my_user_profile(self): - """ - Describes a user's SSH information. - - **Required Permissions**: To use this action, an IAM user must - have self-management enabled or an attached policy that - explicitly grants permissions. For more information on user - permissions, see `Managing User Permissions`_. - - - """ - params = {} - return self.make_request(action='DescribeMyUserProfile', - body=json.dumps(params)) - - def describe_permissions(self, iam_user_arn=None, stack_id=None): - """ - Describes the permissions for a specified stack. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type iam_user_arn: string - :param iam_user_arn: The user's IAM ARN. For more information about IAM - ARNs, see `Using Identifiers`_. - - :type stack_id: string - :param stack_id: The stack ID. - - """ - params = {} - if iam_user_arn is not None: - params['IamUserArn'] = iam_user_arn - if stack_id is not None: - params['StackId'] = stack_id - return self.make_request(action='DescribePermissions', - body=json.dumps(params)) - - def describe_raid_arrays(self, instance_id=None, raid_array_ids=None): - """ - Describe an instance's RAID arrays. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. If you use this parameter, - `DescribeRaidArrays` returns descriptions of the RAID arrays - associated with the specified instance. - - :type raid_array_ids: list - :param raid_array_ids: An array of RAID array IDs. If you use this - parameter, `DescribeRaidArrays` returns descriptions of the - specified arrays. Otherwise, it returns a description of every - array. - - """ - params = {} - if instance_id is not None: - params['InstanceId'] = instance_id - if raid_array_ids is not None: - params['RaidArrayIds'] = raid_array_ids - return self.make_request(action='DescribeRaidArrays', - body=json.dumps(params)) - - def describe_rds_db_instances(self, stack_id, rds_db_instance_arns=None): - """ - Describes Amazon RDS instances. - - :type stack_id: string - :param stack_id: The stack ID that the instances are registered with. - The operation returns descriptions of all registered Amazon RDS - instances. - - :type rds_db_instance_arns: list - :param rds_db_instance_arns: An array containing the ARNs of the - instances to be described. - - """ - params = {'StackId': stack_id, } - if rds_db_instance_arns is not None: - params['RdsDbInstanceArns'] = rds_db_instance_arns - return self.make_request(action='DescribeRdsDbInstances', - body=json.dumps(params)) - - def describe_service_errors(self, stack_id=None, instance_id=None, - service_error_ids=None): - """ - Describes AWS OpsWorks service errors. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. If you use this parameter, - `DescribeServiceErrors` returns descriptions of the errors - associated with the specified stack. - - :type instance_id: string - :param instance_id: The instance ID. If you use this parameter, - `DescribeServiceErrors` returns descriptions of the errors - associated with the specified instance. - - :type service_error_ids: list - :param service_error_ids: An array of service error IDs. If you use - this parameter, `DescribeServiceErrors` returns descriptions of the - specified errors. Otherwise, it returns a description of every - error. - - """ - params = {} - if stack_id is not None: - params['StackId'] = stack_id - if instance_id is not None: - params['InstanceId'] = instance_id - if service_error_ids is not None: - params['ServiceErrorIds'] = service_error_ids - return self.make_request(action='DescribeServiceErrors', - body=json.dumps(params)) - - def describe_stack_summary(self, stack_id): - """ - Describes the number of layers and apps in a specified stack, - and the number of instances in each state, such as - `running_setup` or `online`. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - """ - params = {'StackId': stack_id, } - return self.make_request(action='DescribeStackSummary', - body=json.dumps(params)) - - def describe_stacks(self, stack_ids=None): - """ - Requests a description of one or more stacks. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type stack_ids: list - :param stack_ids: An array of stack IDs that specify the stacks to be - described. If you omit this parameter, `DescribeStacks` returns a - description of every stack. - - """ - params = {} - if stack_ids is not None: - params['StackIds'] = stack_ids - return self.make_request(action='DescribeStacks', - body=json.dumps(params)) - - def describe_time_based_auto_scaling(self, instance_ids): - """ - Describes time-based auto scaling configurations for specified - instances. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type instance_ids: list - :param instance_ids: An array of instance IDs. - - """ - params = {'InstanceIds': instance_ids, } - return self.make_request(action='DescribeTimeBasedAutoScaling', - body=json.dumps(params)) - - def describe_user_profiles(self, iam_user_arns=None): - """ - Describe specified users. - - **Required Permissions**: To use this action, an IAM user must - have an attached policy that explicitly grants permissions. - For more information on user permissions, see `Managing User - Permissions`_. - - :type iam_user_arns: list - :param iam_user_arns: An array of IAM user ARNs that identify the users - to be described. - - """ - params = {} - if iam_user_arns is not None: - params['IamUserArns'] = iam_user_arns - return self.make_request(action='DescribeUserProfiles', - body=json.dumps(params)) - - def describe_volumes(self, instance_id=None, stack_id=None, - raid_array_id=None, volume_ids=None): - """ - Describes an instance's Amazon EBS volumes. - - You must specify at least one of the parameters. - - **Required Permissions**: To use this action, an IAM user must - have a Show, Deploy, or Manage permissions level for the - stack, or an attached policy that explicitly grants - permissions. For more information on user permissions, see - `Managing User Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. If you use this parameter, - `DescribeVolumes` returns descriptions of the volumes associated - with the specified instance. - - :type stack_id: string - :param stack_id: A stack ID. The action describes the stack's - registered Amazon EBS volumes. - - :type raid_array_id: string - :param raid_array_id: The RAID array ID. If you use this parameter, - `DescribeVolumes` returns descriptions of the volumes associated - with the specified RAID array. - - :type volume_ids: list - :param volume_ids: Am array of volume IDs. If you use this parameter, - `DescribeVolumes` returns descriptions of the specified volumes. - Otherwise, it returns a description of every volume. - - """ - params = {} - if instance_id is not None: - params['InstanceId'] = instance_id - if stack_id is not None: - params['StackId'] = stack_id - if raid_array_id is not None: - params['RaidArrayId'] = raid_array_id - if volume_ids is not None: - params['VolumeIds'] = volume_ids - return self.make_request(action='DescribeVolumes', - body=json.dumps(params)) - - def detach_elastic_load_balancer(self, elastic_load_balancer_name, - layer_id): - """ - Detaches a specified Elastic Load Balancing instance from its - layer. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type elastic_load_balancer_name: string - :param elastic_load_balancer_name: The Elastic Load Balancing - instance's name. - - :type layer_id: string - :param layer_id: The ID of the layer that the Elastic Load Balancing - instance is attached to. - - """ - params = { - 'ElasticLoadBalancerName': elastic_load_balancer_name, - 'LayerId': layer_id, - } - return self.make_request(action='DetachElasticLoadBalancer', - body=json.dumps(params)) - - def disassociate_elastic_ip(self, elastic_ip): - """ - Disassociates an Elastic IP address from its instance. The - address remains registered with the stack. For more - information, see `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type elastic_ip: string - :param elastic_ip: The Elastic IP address. - - """ - params = {'ElasticIp': elastic_ip, } - return self.make_request(action='DisassociateElasticIp', - body=json.dumps(params)) - - def get_hostname_suggestion(self, layer_id): - """ - Gets a generated host name for the specified layer, based on - the current host name theme. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type layer_id: string - :param layer_id: The layer ID. - - """ - params = {'LayerId': layer_id, } - return self.make_request(action='GetHostnameSuggestion', - body=json.dumps(params)) - - def reboot_instance(self, instance_id): - """ - Reboots a specified instance. For more information, see - `Starting, Stopping, and Rebooting Instances`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. - - """ - params = {'InstanceId': instance_id, } - return self.make_request(action='RebootInstance', - body=json.dumps(params)) - - def register_elastic_ip(self, elastic_ip, stack_id): - """ - Registers an Elastic IP address with a specified stack. An - address can be registered with only one stack at a time. If - the address is already registered, you must first deregister - it by calling DeregisterElasticIp. For more information, see - `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type elastic_ip: string - :param elastic_ip: The Elastic IP address. - - :type stack_id: string - :param stack_id: The stack ID. - - """ - params = {'ElasticIp': elastic_ip, 'StackId': stack_id, } - return self.make_request(action='RegisterElasticIp', - body=json.dumps(params)) - - def register_rds_db_instance(self, stack_id, rds_db_instance_arn, - db_user, db_password): - """ - Registers an Amazon RDS instance with a stack. - - :type stack_id: string - :param stack_id: The stack ID. - - :type rds_db_instance_arn: string - :param rds_db_instance_arn: The Amazon RDS instance's ARN. - - :type db_user: string - :param db_user: The database's master user name. - - :type db_password: string - :param db_password: The database password. - - """ - params = { - 'StackId': stack_id, - 'RdsDbInstanceArn': rds_db_instance_arn, - 'DbUser': db_user, - 'DbPassword': db_password, - } - return self.make_request(action='RegisterRdsDbInstance', - body=json.dumps(params)) - - def register_volume(self, stack_id, ec_2_volume_id=None): - """ - Registers an Amazon EBS volume with a specified stack. A - volume can be registered with only one stack at a time. If the - volume is already registered, you must first deregister it by - calling DeregisterVolume. For more information, see `Resource - Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type ec_2_volume_id: string - :param ec_2_volume_id: The Amazon EBS volume ID. - - :type stack_id: string - :param stack_id: The stack ID. - - """ - params = {'StackId': stack_id, } - if ec_2_volume_id is not None: - params['Ec2VolumeId'] = ec_2_volume_id - return self.make_request(action='RegisterVolume', - body=json.dumps(params)) - - def set_load_based_auto_scaling(self, layer_id, enable=None, - up_scaling=None, down_scaling=None): - """ - Specify the load-based auto scaling configuration for a - specified layer. For more information, see `Managing Load with - Time-based and Load-based Instances`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type layer_id: string - :param layer_id: The layer ID. - - :type enable: boolean - :param enable: Enables load-based auto scaling for the layer. - - :type up_scaling: dict - :param up_scaling: An `AutoScalingThresholds` object with the upscaling - threshold configuration. If the load exceeds these thresholds for a - specified amount of time, AWS OpsWorks starts a specified number of - instances. - - :type down_scaling: dict - :param down_scaling: An `AutoScalingThresholds` object with the - downscaling threshold configuration. If the load falls below these - thresholds for a specified amount of time, AWS OpsWorks stops a - specified number of instances. - - """ - params = {'LayerId': layer_id, } - if enable is not None: - params['Enable'] = enable - if up_scaling is not None: - params['UpScaling'] = up_scaling - if down_scaling is not None: - params['DownScaling'] = down_scaling - return self.make_request(action='SetLoadBasedAutoScaling', - body=json.dumps(params)) - - def set_permission(self, stack_id, iam_user_arn, allow_ssh=None, - allow_sudo=None, level=None): - """ - Specifies a user's permissions. For more information, see - `Security and Permissions`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - :type iam_user_arn: string - :param iam_user_arn: The user's IAM ARN. - - :type allow_ssh: boolean - :param allow_ssh: The user is allowed to use SSH to communicate with - the instance. - - :type allow_sudo: boolean - :param allow_sudo: The user is allowed to use **sudo** to elevate - privileges. - - :type level: string - :param level: The user's permission level, which must be set to one of - the following strings. You cannot set your own permissions level. - - + `deny` - + `show` - + `deploy` - + `manage` - + `iam_only` - - - For more information on the permissions associated with these levels, - see `Managing User Permissions`_ - - """ - params = {'StackId': stack_id, 'IamUserArn': iam_user_arn, } - if allow_ssh is not None: - params['AllowSsh'] = allow_ssh - if allow_sudo is not None: - params['AllowSudo'] = allow_sudo - if level is not None: - params['Level'] = level - return self.make_request(action='SetPermission', - body=json.dumps(params)) - - def set_time_based_auto_scaling(self, instance_id, - auto_scaling_schedule=None): - """ - Specify the time-based auto scaling configuration for a - specified instance. For more information, see `Managing Load - with Time-based and Load-based Instances`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. - - :type auto_scaling_schedule: dict - :param auto_scaling_schedule: An `AutoScalingSchedule` with the - instance schedule. - - """ - params = {'InstanceId': instance_id, } - if auto_scaling_schedule is not None: - params['AutoScalingSchedule'] = auto_scaling_schedule - return self.make_request(action='SetTimeBasedAutoScaling', - body=json.dumps(params)) - - def start_instance(self, instance_id): - """ - Starts a specified instance. For more information, see - `Starting, Stopping, and Rebooting Instances`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. - - """ - params = {'InstanceId': instance_id, } - return self.make_request(action='StartInstance', - body=json.dumps(params)) - - def start_stack(self, stack_id): - """ - Starts a stack's instances. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - """ - params = {'StackId': stack_id, } - return self.make_request(action='StartStack', - body=json.dumps(params)) - - def stop_instance(self, instance_id): - """ - Stops a specified instance. When you stop a standard instance, - the data disappears and must be reinstalled when you restart - the instance. You can stop an Amazon EBS-backed instance - without losing data. For more information, see `Starting, - Stopping, and Rebooting Instances`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. - - """ - params = {'InstanceId': instance_id, } - return self.make_request(action='StopInstance', - body=json.dumps(params)) - - def stop_stack(self, stack_id): - """ - Stops a specified stack. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - """ - params = {'StackId': stack_id, } - return self.make_request(action='StopStack', - body=json.dumps(params)) - - def unassign_volume(self, volume_id): - """ - Unassigns an assigned Amazon EBS volume. The volume remains - registered with the stack. For more information, see `Resource - Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type volume_id: string - :param volume_id: The volume ID. - - """ - params = {'VolumeId': volume_id, } - return self.make_request(action='UnassignVolume', - body=json.dumps(params)) - - def update_app(self, app_id, name=None, description=None, - data_sources=None, type=None, app_source=None, - domains=None, enable_ssl=None, ssl_configuration=None, - attributes=None): - """ - Updates a specified app. - - **Required Permissions**: To use this action, an IAM user must - have a Deploy or Manage permissions level for the stack, or an - attached policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type app_id: string - :param app_id: The app ID. - - :type name: string - :param name: The app name. - - :type description: string - :param description: A description of the app. - - :type data_sources: list - :param data_sources: The app's data sources. - - :type type: string - :param type: The app type. - - :type app_source: dict - :param app_source: A `Source` object that specifies the app repository. - - :type domains: list - :param domains: The app's virtual host settings, with multiple domains - separated by commas. For example: `'www.example.com, example.com'` - - :type enable_ssl: boolean - :param enable_ssl: Whether SSL is enabled for the app. - - :type ssl_configuration: dict - :param ssl_configuration: An `SslConfiguration` object with the SSL - configuration. - - :type attributes: map - :param attributes: One or more user-defined key/value pairs to be added - to the stack attributes. - - """ - params = {'AppId': app_id, } - if name is not None: - params['Name'] = name - if description is not None: - params['Description'] = description - if data_sources is not None: - params['DataSources'] = data_sources - if type is not None: - params['Type'] = type - if app_source is not None: - params['AppSource'] = app_source - if domains is not None: - params['Domains'] = domains - if enable_ssl is not None: - params['EnableSsl'] = enable_ssl - if ssl_configuration is not None: - params['SslConfiguration'] = ssl_configuration - if attributes is not None: - params['Attributes'] = attributes - return self.make_request(action='UpdateApp', - body=json.dumps(params)) - - def update_elastic_ip(self, elastic_ip, name=None): - """ - Updates a registered Elastic IP address's name. For more - information, see `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type elastic_ip: string - :param elastic_ip: The address. - - :type name: string - :param name: The new name. - - """ - params = {'ElasticIp': elastic_ip, } - if name is not None: - params['Name'] = name - return self.make_request(action='UpdateElasticIp', - body=json.dumps(params)) - - def update_instance(self, instance_id, layer_ids=None, - instance_type=None, auto_scaling_type=None, - hostname=None, os=None, ami_id=None, - ssh_key_name=None, architecture=None, - install_updates_on_boot=None, ebs_optimized=None): - """ - Updates a specified instance. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type instance_id: string - :param instance_id: The instance ID. - - :type layer_ids: list - :param layer_ids: The instance's layer IDs. - - :type instance_type: string - :param instance_type: The instance type. AWS OpsWorks supports all - instance types except Cluster Compute, Cluster GPU, and High Memory - Cluster. For more information, see `Instance Families and Types`_. - The parameter values that you use to specify the various types are - in the API Name column of the Available Instance Types table. - - :type auto_scaling_type: string - :param auto_scaling_type: - The instance's auto scaling type, which has three possible values: - - - + **AlwaysRunning**: A 24/7 instance, which is not affected by auto - scaling. - + **TimeBasedAutoScaling**: A time-based auto scaling instance, which - is started and stopped based on a specified schedule. - + **LoadBasedAutoScaling**: A load-based auto scaling instance, which - is started and stopped based on load metrics. - - :type hostname: string - :param hostname: The instance host name. - - :type os: string - :param os: The instance operating system, which must be set to one of - the following. - - + Standard operating systems: `Amazon Linux` or `Ubuntu 12.04 LTS` - + Custom AMIs: `Custom` - - - The default option is `Amazon Linux`. If you set this parameter to - `Custom`, you must use the CreateInstance action's AmiId parameter - to specify the custom AMI that you want to use. For more - information on the standard operating systems, see `Operating - Systems`_For more information on how to use custom AMIs with - OpsWorks, see `Using Custom AMIs`_. - - :type ami_id: string - :param ami_id: A custom AMI ID to be used to create the instance. The - AMI should be based on one of the standard AWS OpsWorks APIs: - Amazon Linux or Ubuntu 12.04 LTS. For more information, see - `Instances`_ - - :type ssh_key_name: string - :param ssh_key_name: The instance SSH key name. - - :type architecture: string - :param architecture: The instance architecture. Instance types do not - necessarily support both architectures. For a list of the - architectures that are supported by the different instance types, - see `Instance Families and Types`_. - - :type install_updates_on_boot: boolean - :param install_updates_on_boot: Whether to install operating system and - package updates when the instance boots. The default value is - `True`. To control when updates are installed, set this value to - `False`. You must then update your instances manually by using - CreateDeployment to run the `update_dependencies` stack command or - manually running `yum` (Amazon Linux) or `apt-get` (Ubuntu) on the - instances. - - :type ebs_optimized: boolean - :param ebs_optimized: Whether this is an Amazon EBS-optimized instance. - - """ - params = {'InstanceId': instance_id, } - if layer_ids is not None: - params['LayerIds'] = layer_ids - if instance_type is not None: - params['InstanceType'] = instance_type - if auto_scaling_type is not None: - params['AutoScalingType'] = auto_scaling_type - if hostname is not None: - params['Hostname'] = hostname - if os is not None: - params['Os'] = os - if ami_id is not None: - params['AmiId'] = ami_id - if ssh_key_name is not None: - params['SshKeyName'] = ssh_key_name - if architecture is not None: - params['Architecture'] = architecture - if install_updates_on_boot is not None: - params['InstallUpdatesOnBoot'] = install_updates_on_boot - if ebs_optimized is not None: - params['EbsOptimized'] = ebs_optimized - return self.make_request(action='UpdateInstance', - body=json.dumps(params)) - - def update_layer(self, layer_id, name=None, shortname=None, - attributes=None, custom_instance_profile_arn=None, - custom_security_group_ids=None, packages=None, - volume_configurations=None, enable_auto_healing=None, - auto_assign_elastic_ips=None, - auto_assign_public_ips=None, custom_recipes=None, - install_updates_on_boot=None, - use_ebs_optimized_instances=None): - """ - Updates a specified layer. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type layer_id: string - :param layer_id: The layer ID. - - :type name: string - :param name: The layer name, which is used by the console. - - :type shortname: string - :param shortname: The layer short name, which is used internally by AWS - OpsWorksand by Chef. The short name is also used as the name for - the directory where your app files are installed. It can have a - maximum of 200 characters and must be in the following format: - /\A[a-z0-9\-\_\.]+\Z/. - - :type attributes: map - :param attributes: One or more user-defined key/value pairs to be added - to the stack attributes. - - :type custom_instance_profile_arn: string - :param custom_instance_profile_arn: The ARN of an IAM profile to be - used for all of the layer's EC2 instances. For more information - about IAM ARNs, see `Using Identifiers`_. - - :type custom_security_group_ids: list - :param custom_security_group_ids: An array containing the layer's - custom security group IDs. - - :type packages: list - :param packages: An array of `Package` objects that describe the - layer's packages. - - :type volume_configurations: list - :param volume_configurations: A `VolumeConfigurations` object that - describes the layer's Amazon EBS volumes. - - :type enable_auto_healing: boolean - :param enable_auto_healing: Whether to disable auto healing for the - layer. - - :type auto_assign_elastic_ips: boolean - :param auto_assign_elastic_ips: Whether to automatically assign an - `Elastic IP address`_ to the layer's instances. For more - information, see `How to Edit a Layer`_. - - :type auto_assign_public_ips: boolean - :param auto_assign_public_ips: For stacks that are running in a VPC, - whether to automatically assign a public IP address to the layer's - instances. For more information, see `How to Edit a Layer`_. - - :type custom_recipes: dict - :param custom_recipes: A `LayerCustomRecipes` object that specifies the - layer's custom recipes. - - :type install_updates_on_boot: boolean - :param install_updates_on_boot: Whether to install operating system and - package updates when the instance boots. The default value is - `True`. To control when updates are installed, set this value to - `False`. You must then update your instances manually by using - CreateDeployment to run the `update_dependencies` stack command or - manually running `yum` (Amazon Linux) or `apt-get` (Ubuntu) on the - instances. - - :type use_ebs_optimized_instances: boolean - :param use_ebs_optimized_instances: Whether to use Amazon EBS-optimized - instances. - - """ - params = {'LayerId': layer_id, } - if name is not None: - params['Name'] = name - if shortname is not None: - params['Shortname'] = shortname - if attributes is not None: - params['Attributes'] = attributes - if custom_instance_profile_arn is not None: - params['CustomInstanceProfileArn'] = custom_instance_profile_arn - if custom_security_group_ids is not None: - params['CustomSecurityGroupIds'] = custom_security_group_ids - if packages is not None: - params['Packages'] = packages - if volume_configurations is not None: - params['VolumeConfigurations'] = volume_configurations - if enable_auto_healing is not None: - params['EnableAutoHealing'] = enable_auto_healing - if auto_assign_elastic_ips is not None: - params['AutoAssignElasticIps'] = auto_assign_elastic_ips - if auto_assign_public_ips is not None: - params['AutoAssignPublicIps'] = auto_assign_public_ips - if custom_recipes is not None: - params['CustomRecipes'] = custom_recipes - if install_updates_on_boot is not None: - params['InstallUpdatesOnBoot'] = install_updates_on_boot - if use_ebs_optimized_instances is not None: - params['UseEbsOptimizedInstances'] = use_ebs_optimized_instances - return self.make_request(action='UpdateLayer', - body=json.dumps(params)) - - def update_my_user_profile(self, ssh_public_key=None): - """ - Updates a user's SSH public key. - - **Required Permissions**: To use this action, an IAM user must - have self-management enabled or an attached policy that - explicitly grants permissions. For more information on user - permissions, see `Managing User Permissions`_. - - :type ssh_public_key: string - :param ssh_public_key: The user's SSH public key. - - """ - params = {} - if ssh_public_key is not None: - params['SshPublicKey'] = ssh_public_key - return self.make_request(action='UpdateMyUserProfile', - body=json.dumps(params)) - - def update_rds_db_instance(self, rds_db_instance_arn, db_user=None, - db_password=None): - """ - Updates an Amazon RDS instance. - - :type rds_db_instance_arn: string - :param rds_db_instance_arn: The Amazon RDS instance's ARN. - - :type db_user: string - :param db_user: The master user name. - - :type db_password: string - :param db_password: The database password. - - """ - params = {'RdsDbInstanceArn': rds_db_instance_arn, } - if db_user is not None: - params['DbUser'] = db_user - if db_password is not None: - params['DbPassword'] = db_password - return self.make_request(action='UpdateRdsDbInstance', - body=json.dumps(params)) - - def update_stack(self, stack_id, name=None, attributes=None, - service_role_arn=None, - default_instance_profile_arn=None, default_os=None, - hostname_theme=None, default_availability_zone=None, - default_subnet_id=None, custom_json=None, - configuration_manager=None, chef_configuration=None, - use_custom_cookbooks=None, custom_cookbooks_source=None, - default_ssh_key_name=None, - default_root_device_type=None, - use_opsworks_security_groups=None): - """ - Updates a specified stack. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type stack_id: string - :param stack_id: The stack ID. - - :type name: string - :param name: The stack's new name. - - :type attributes: map - :param attributes: One or more user-defined key/value pairs to be added - to the stack attributes. - - :type service_role_arn: string - :param service_role_arn: The stack AWS Identity and Access Management - (IAM) role, which allows AWS OpsWorks to work with AWS resources on - your behalf. You must set this parameter to the Amazon Resource - Name (ARN) for an existing IAM role. For more information about IAM - ARNs, see `Using Identifiers`_. - - :type default_instance_profile_arn: string - :param default_instance_profile_arn: The ARN of an IAM profile that is - the default profile for all of the stack's EC2 instances. For more - information about IAM ARNs, see `Using Identifiers`_. - - :type default_os: string - :param default_os: The stack's default operating system, which must be - set to `Amazon Linux` or `Ubuntu 12.04 LTS`. The default option is - `Amazon Linux`. - - :type hostname_theme: string - :param hostname_theme: The stack's new host name theme, with spaces are - replaced by underscores. The theme is used to generate host names - for the stack's instances. By default, `HostnameTheme` is set to - `Layer_Dependent`, which creates host names by appending integers - to the layer's short name. The other themes are: - - + `Baked_Goods` - + `Clouds` - + `European_Cities` - + `Fruits` - + `Greek_Deities` - + `Legendary_Creatures_from_Japan` - + `Planets_and_Moons` - + `Roman_Deities` - + `Scottish_Islands` - + `US_Cities` - + `Wild_Cats` - - - To obtain a generated host name, call `GetHostNameSuggestion`, which - returns a host name based on the current theme. - - :type default_availability_zone: string - :param default_availability_zone: The stack's default Availability - Zone, which must be in the specified region. For more information, - see `Regions and Endpoints`_. If you also specify a value for - `DefaultSubnetId`, the subnet must be in the same zone. For more - information, see CreateStack. - - :type default_subnet_id: string - :param default_subnet_id: The stack's default subnet ID. All instances - will be launched into this subnet unless you specify otherwise when - you create the instance. If you also specify a value for - `DefaultAvailabilityZone`, the subnet must be in that zone. For - more information, see CreateStack. - - :type custom_json: string - :param custom_json: A string that contains user-defined, custom JSON. - It is used to override the corresponding default stack - configuration JSON values. The string should be in the following - format and must escape characters such as '"'.: - `"{\"key1\": \"value1\", \"key2\": \"value2\",...}"` - - For more information on custom JSON, see `Use Custom JSON to Modify the - Stack Configuration JSON`_. - - :type configuration_manager: dict - :param configuration_manager: The configuration manager. When you clone - a stack we recommend that you use the configuration manager to - specify the Chef version, 0.9, 11.4, or 11.10. The default value is - currently 11.4. - - :type chef_configuration: dict - :param chef_configuration: A `ChefConfiguration` object that specifies - whether to enable Berkshelf and the Berkshelf version on Chef 11.10 - stacks. For more information, see `Create a New Stack`_. - - :type use_custom_cookbooks: boolean - :param use_custom_cookbooks: Whether the stack uses custom cookbooks. - - :type custom_cookbooks_source: dict - :param custom_cookbooks_source: Contains the information required to - retrieve an app or cookbook from a repository. For more - information, see `Creating Apps`_ or `Custom Recipes and - Cookbooks`_. - - :type default_ssh_key_name: string - :param default_ssh_key_name: A default SSH key for the stack instances. - You can override this value when you create or update an instance. - - :type default_root_device_type: string - :param default_root_device_type: The default root device type. This - value is used by default for all instances in the stack, but you - can override it when you create an instance. For more information, - see `Storage for the Root Device`_. - - :type use_opsworks_security_groups: boolean - :param use_opsworks_security_groups: Whether to associate the AWS - OpsWorks built-in security groups with the stack's layers. - AWS OpsWorks provides a standard set of built-in security groups, one - for each layer, which are associated with layers by default. - `UseOpsworksSecurityGroups` allows you to instead provide your own - custom security groups. `UseOpsworksSecurityGroups` has the - following settings: - - - + True - AWS OpsWorks automatically associates the appropriate built-in - security group with each layer (default setting). You can associate - additional security groups with a layer after you create it but you - cannot delete the built-in security group. - + False - AWS OpsWorks does not associate built-in security groups with - layers. You must create appropriate EC2 security groups and - associate a security group with each layer that you create. - However, you can still manually associate a built-in security group - with a layer on creation; custom security groups are required only - for those layers that need custom settings. - - - For more information, see `Create a New Stack`_. - - """ - params = {'StackId': stack_id, } - if name is not None: - params['Name'] = name - if attributes is not None: - params['Attributes'] = attributes - if service_role_arn is not None: - params['ServiceRoleArn'] = service_role_arn - if default_instance_profile_arn is not None: - params['DefaultInstanceProfileArn'] = default_instance_profile_arn - if default_os is not None: - params['DefaultOs'] = default_os - if hostname_theme is not None: - params['HostnameTheme'] = hostname_theme - if default_availability_zone is not None: - params['DefaultAvailabilityZone'] = default_availability_zone - if default_subnet_id is not None: - params['DefaultSubnetId'] = default_subnet_id - if custom_json is not None: - params['CustomJson'] = custom_json - if configuration_manager is not None: - params['ConfigurationManager'] = configuration_manager - if chef_configuration is not None: - params['ChefConfiguration'] = chef_configuration - if use_custom_cookbooks is not None: - params['UseCustomCookbooks'] = use_custom_cookbooks - if custom_cookbooks_source is not None: - params['CustomCookbooksSource'] = custom_cookbooks_source - if default_ssh_key_name is not None: - params['DefaultSshKeyName'] = default_ssh_key_name - if default_root_device_type is not None: - params['DefaultRootDeviceType'] = default_root_device_type - if use_opsworks_security_groups is not None: - params['UseOpsworksSecurityGroups'] = use_opsworks_security_groups - return self.make_request(action='UpdateStack', - body=json.dumps(params)) - - def update_user_profile(self, iam_user_arn, ssh_username=None, - ssh_public_key=None, allow_self_management=None): - """ - Updates a specified user profile. - - **Required Permissions**: To use this action, an IAM user must - have an attached policy that explicitly grants permissions. - For more information on user permissions, see `Managing User - Permissions`_. - - :type iam_user_arn: string - :param iam_user_arn: The user IAM ARN. - - :type ssh_username: string - :param ssh_username: The user's SSH user name. The allowable characters - are [a-z], [A-Z], [0-9], '-', and '_'. If the specified name - includes other punctuation marks, AWS OpsWorks removes them. For - example, `my.name` will be changed to `myname`. If you do not - specify an SSH user name, AWS OpsWorks generates one from the IAM - user name. - - :type ssh_public_key: string - :param ssh_public_key: The user's new SSH public key. - - :type allow_self_management: boolean - :param allow_self_management: Whether users can specify their own SSH - public key through the My Settings page. For more information, see - `Managing User Permissions`_. - - """ - params = {'IamUserArn': iam_user_arn, } - if ssh_username is not None: - params['SshUsername'] = ssh_username - if ssh_public_key is not None: - params['SshPublicKey'] = ssh_public_key - if allow_self_management is not None: - params['AllowSelfManagement'] = allow_self_management - return self.make_request(action='UpdateUserProfile', - body=json.dumps(params)) - - def update_volume(self, volume_id, name=None, mount_point=None): - """ - Updates an Amazon EBS volume's name or mount point. For more - information, see `Resource Management`_. - - **Required Permissions**: To use this action, an IAM user must - have a Manage permissions level for the stack, or an attached - policy that explicitly grants permissions. For more - information on user permissions, see `Managing User - Permissions`_. - - :type volume_id: string - :param volume_id: The volume ID. - - :type name: string - :param name: The new name. - - :type mount_point: string - :param mount_point: The new mount point. - - """ - params = {'VolumeId': volume_id, } - if name is not None: - params['Name'] = name - if mount_point is not None: - params['MountPoint'] = mount_point - return self.make_request(action='UpdateVolume', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/plugin.py b/awx/lib/site-packages/boto/plugin.py deleted file mode 100644 index 2c2931c9df..0000000000 --- a/awx/lib/site-packages/boto/plugin.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -""" -Implements plugin related api. - -To define a new plugin just subclass Plugin, like this. - -class AuthPlugin(Plugin): - pass - -Then start creating subclasses of your new plugin. - -class MyFancyAuth(AuthPlugin): - capability = ['sign', 'vmac'] - -The actual interface is duck typed. -""" - -import glob -import imp -import os.path - - -class Plugin(object): - """Base class for all plugins.""" - - capability = [] - - @classmethod - def is_capable(cls, requested_capability): - """Returns true if the requested capability is supported by this plugin - """ - for c in requested_capability: - if c not in cls.capability: - return False - return True - - -def get_plugin(cls, requested_capability=None): - if not requested_capability: - requested_capability = [] - result = [] - for handler in cls.__subclasses__(): - if handler.is_capable(requested_capability): - result.append(handler) - return result - - -def _import_module(filename): - (path, name) = os.path.split(filename) - (name, ext) = os.path.splitext(name) - - (file, filename, data) = imp.find_module(name, [path]) - try: - return imp.load_module(name, file, filename, data) - finally: - if file: - file.close() - -_plugin_loaded = False - - -def load_plugins(config): - global _plugin_loaded - if _plugin_loaded: - return - _plugin_loaded = True - - if not config.has_option('Plugin', 'plugin_directory'): - return - directory = config.get('Plugin', 'plugin_directory') - for file in glob.glob(os.path.join(directory, '*.py')): - _import_module(file) diff --git a/awx/lib/site-packages/boto/provider.py b/awx/lib/site-packages/boto/provider.py deleted file mode 100644 index 0da2f78a5c..0000000000 --- a/awx/lib/site-packages/boto/provider.py +++ /dev/null @@ -1,451 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright 2010 Google Inc. -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# Copyright (c) 2011, Nexenta Systems Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -""" -This class encapsulates the provider-specific header differences. -""" - -import os -from boto.compat import six -from datetime import datetime - -import boto -from boto import config -from boto.compat import expanduser -from boto.pyami.config import Config -from boto.gs.acl import ACL -from boto.gs.acl import CannedACLStrings as CannedGSACLStrings -from boto.s3.acl import CannedACLStrings as CannedS3ACLStrings -from boto.s3.acl import Policy - - -HEADER_PREFIX_KEY = 'header_prefix' -METADATA_PREFIX_KEY = 'metadata_prefix' - -AWS_HEADER_PREFIX = 'x-amz-' -GOOG_HEADER_PREFIX = 'x-goog-' - -ACL_HEADER_KEY = 'acl-header' -AUTH_HEADER_KEY = 'auth-header' -COPY_SOURCE_HEADER_KEY = 'copy-source-header' -COPY_SOURCE_VERSION_ID_HEADER_KEY = 'copy-source-version-id-header' -COPY_SOURCE_RANGE_HEADER_KEY = 'copy-source-range-header' -DELETE_MARKER_HEADER_KEY = 'delete-marker-header' -DATE_HEADER_KEY = 'date-header' -METADATA_DIRECTIVE_HEADER_KEY = 'metadata-directive-header' -RESUMABLE_UPLOAD_HEADER_KEY = 'resumable-upload-header' -SECURITY_TOKEN_HEADER_KEY = 'security-token-header' -STORAGE_CLASS_HEADER_KEY = 'storage-class' -MFA_HEADER_KEY = 'mfa-header' -SERVER_SIDE_ENCRYPTION_KEY = 'server-side-encryption-header' -VERSION_ID_HEADER_KEY = 'version-id-header' -RESTORE_HEADER_KEY = 'restore-header' - -STORAGE_COPY_ERROR = 'StorageCopyError' -STORAGE_CREATE_ERROR = 'StorageCreateError' -STORAGE_DATA_ERROR = 'StorageDataError' -STORAGE_PERMISSIONS_ERROR = 'StoragePermissionsError' -STORAGE_RESPONSE_ERROR = 'StorageResponseError' - - -class ProfileNotFoundError(ValueError): - pass - - -class Provider(object): - - CredentialMap = { - 'aws': ('aws_access_key_id', 'aws_secret_access_key', - 'aws_security_token', 'aws_profile'), - 'google': ('gs_access_key_id', 'gs_secret_access_key', - None, None), - } - - AclClassMap = { - 'aws': Policy, - 'google': ACL - } - - CannedAclsMap = { - 'aws': CannedS3ACLStrings, - 'google': CannedGSACLStrings - } - - HostKeyMap = { - 'aws': 's3', - 'google': 'gs' - } - - ChunkedTransferSupport = { - 'aws': False, - 'google': True - } - - MetadataServiceSupport = { - 'aws': True, - 'google': False - } - - # If you update this map please make sure to put "None" for the - # right-hand-side for any headers that don't apply to a provider, rather - # than simply leaving that header out (which would cause KeyErrors). - HeaderInfoMap = { - 'aws': { - HEADER_PREFIX_KEY: AWS_HEADER_PREFIX, - METADATA_PREFIX_KEY: AWS_HEADER_PREFIX + 'meta-', - ACL_HEADER_KEY: AWS_HEADER_PREFIX + 'acl', - AUTH_HEADER_KEY: 'AWS', - COPY_SOURCE_HEADER_KEY: AWS_HEADER_PREFIX + 'copy-source', - COPY_SOURCE_VERSION_ID_HEADER_KEY: AWS_HEADER_PREFIX + - 'copy-source-version-id', - COPY_SOURCE_RANGE_HEADER_KEY: AWS_HEADER_PREFIX + - 'copy-source-range', - DATE_HEADER_KEY: AWS_HEADER_PREFIX + 'date', - DELETE_MARKER_HEADER_KEY: AWS_HEADER_PREFIX + 'delete-marker', - METADATA_DIRECTIVE_HEADER_KEY: AWS_HEADER_PREFIX + - 'metadata-directive', - RESUMABLE_UPLOAD_HEADER_KEY: None, - SECURITY_TOKEN_HEADER_KEY: AWS_HEADER_PREFIX + 'security-token', - SERVER_SIDE_ENCRYPTION_KEY: AWS_HEADER_PREFIX + - 'server-side-encryption', - VERSION_ID_HEADER_KEY: AWS_HEADER_PREFIX + 'version-id', - STORAGE_CLASS_HEADER_KEY: AWS_HEADER_PREFIX + 'storage-class', - MFA_HEADER_KEY: AWS_HEADER_PREFIX + 'mfa', - RESTORE_HEADER_KEY: AWS_HEADER_PREFIX + 'restore', - }, - 'google': { - HEADER_PREFIX_KEY: GOOG_HEADER_PREFIX, - METADATA_PREFIX_KEY: GOOG_HEADER_PREFIX + 'meta-', - ACL_HEADER_KEY: GOOG_HEADER_PREFIX + 'acl', - AUTH_HEADER_KEY: 'GOOG1', - COPY_SOURCE_HEADER_KEY: GOOG_HEADER_PREFIX + 'copy-source', - COPY_SOURCE_VERSION_ID_HEADER_KEY: GOOG_HEADER_PREFIX + - 'copy-source-version-id', - COPY_SOURCE_RANGE_HEADER_KEY: None, - DATE_HEADER_KEY: GOOG_HEADER_PREFIX + 'date', - DELETE_MARKER_HEADER_KEY: GOOG_HEADER_PREFIX + 'delete-marker', - METADATA_DIRECTIVE_HEADER_KEY: GOOG_HEADER_PREFIX + - 'metadata-directive', - RESUMABLE_UPLOAD_HEADER_KEY: GOOG_HEADER_PREFIX + 'resumable', - SECURITY_TOKEN_HEADER_KEY: GOOG_HEADER_PREFIX + 'security-token', - SERVER_SIDE_ENCRYPTION_KEY: None, - # Note that this version header is not to be confused with - # the Google Cloud Storage 'x-goog-api-version' header. - VERSION_ID_HEADER_KEY: GOOG_HEADER_PREFIX + 'version-id', - STORAGE_CLASS_HEADER_KEY: None, - MFA_HEADER_KEY: None, - RESTORE_HEADER_KEY: None, - } - } - - ErrorMap = { - 'aws': { - STORAGE_COPY_ERROR: boto.exception.S3CopyError, - STORAGE_CREATE_ERROR: boto.exception.S3CreateError, - STORAGE_DATA_ERROR: boto.exception.S3DataError, - STORAGE_PERMISSIONS_ERROR: boto.exception.S3PermissionsError, - STORAGE_RESPONSE_ERROR: boto.exception.S3ResponseError, - }, - 'google': { - STORAGE_COPY_ERROR: boto.exception.GSCopyError, - STORAGE_CREATE_ERROR: boto.exception.GSCreateError, - STORAGE_DATA_ERROR: boto.exception.GSDataError, - STORAGE_PERMISSIONS_ERROR: boto.exception.GSPermissionsError, - STORAGE_RESPONSE_ERROR: boto.exception.GSResponseError, - } - } - - def __init__(self, name, access_key=None, secret_key=None, - security_token=None, profile_name=None): - self.host = None - self.port = None - self.host_header = None - self.access_key = access_key - self.secret_key = secret_key - self.security_token = security_token - self.profile_name = profile_name - self.name = name - self.acl_class = self.AclClassMap[self.name] - self.canned_acls = self.CannedAclsMap[self.name] - self._credential_expiry_time = None - - # Load shared credentials file if it exists - shared_path = os.path.join(expanduser('~'), '.' + name, 'credentials') - self.shared_credentials = Config(do_load=False) - if os.path.isfile(shared_path): - self.shared_credentials.load_from_path(shared_path) - - self.get_credentials(access_key, secret_key, security_token, profile_name) - self.configure_headers() - self.configure_errors() - - # Allow config file to override default host and port. - host_opt_name = '%s_host' % self.HostKeyMap[self.name] - if config.has_option('Credentials', host_opt_name): - self.host = config.get('Credentials', host_opt_name) - port_opt_name = '%s_port' % self.HostKeyMap[self.name] - if config.has_option('Credentials', port_opt_name): - self.port = config.getint('Credentials', port_opt_name) - host_header_opt_name = '%s_host_header' % self.HostKeyMap[self.name] - if config.has_option('Credentials', host_header_opt_name): - self.host_header = config.get('Credentials', host_header_opt_name) - - def get_access_key(self): - if self._credentials_need_refresh(): - self._populate_keys_from_metadata_server() - return self._access_key - - def set_access_key(self, value): - self._access_key = value - - access_key = property(get_access_key, set_access_key) - - def get_secret_key(self): - if self._credentials_need_refresh(): - self._populate_keys_from_metadata_server() - return self._secret_key - - def set_secret_key(self, value): - self._secret_key = value - - secret_key = property(get_secret_key, set_secret_key) - - def get_security_token(self): - if self._credentials_need_refresh(): - self._populate_keys_from_metadata_server() - return self._security_token - - def set_security_token(self, value): - self._security_token = value - - security_token = property(get_security_token, set_security_token) - - def _credentials_need_refresh(self): - if self._credential_expiry_time is None: - return False - else: - # The credentials should be refreshed if they're going to expire - # in less than 5 minutes. - delta = self._credential_expiry_time - datetime.utcnow() - # python2.6 does not have timedelta.total_seconds() so we have - # to calculate this ourselves. This is straight from the - # datetime docs. - seconds_left = ( - (delta.microseconds + (delta.seconds + delta.days * 24 * 3600) - * 10 ** 6) / 10 ** 6) - if seconds_left < (5 * 60): - boto.log.debug("Credentials need to be refreshed.") - return True - else: - return False - - def get_credentials(self, access_key=None, secret_key=None, - security_token=None, profile_name=None): - access_key_name, secret_key_name, security_token_name, \ - profile_name_name = self.CredentialMap[self.name] - - # Load profile from shared environment variable if it was not - # already passed in and the environment variable exists - if profile_name is None and profile_name_name is not None and \ - profile_name_name.upper() in os.environ: - profile_name = os.environ[profile_name_name.upper()] - - shared = self.shared_credentials - - if access_key is not None: - self.access_key = access_key - boto.log.debug("Using access key provided by client.") - elif access_key_name.upper() in os.environ: - self.access_key = os.environ[access_key_name.upper()] - boto.log.debug("Using access key found in environment variable.") - elif profile_name is not None: - if shared.has_option(profile_name, access_key_name): - self.access_key = shared.get(profile_name, access_key_name) - boto.log.debug("Using access key found in shared credential " - "file for profile %s." % profile_name) - elif config.has_option("profile %s" % profile_name, - access_key_name): - self.access_key = config.get("profile %s" % profile_name, - access_key_name) - boto.log.debug("Using access key found in config file: " - "profile %s." % profile_name) - else: - raise ProfileNotFoundError('Profile "%s" not found!' % - profile_name) - elif shared.has_option('default', access_key_name): - self.access_key = shared.get('default', access_key_name) - boto.log.debug("Using access key found in shared credential file.") - elif config.has_option('Credentials', access_key_name): - self.access_key = config.get('Credentials', access_key_name) - boto.log.debug("Using access key found in config file.") - - if secret_key is not None: - self.secret_key = secret_key - boto.log.debug("Using secret key provided by client.") - elif secret_key_name.upper() in os.environ: - self.secret_key = os.environ[secret_key_name.upper()] - boto.log.debug("Using secret key found in environment variable.") - elif profile_name is not None: - if shared.has_option(profile_name, secret_key_name): - self.secret_key = shared.get(profile_name, secret_key_name) - boto.log.debug("Using secret key found in shared credential " - "file for profile %s." % profile_name) - elif config.has_option("profile %s" % profile_name, secret_key_name): - self.secret_key = config.get("profile %s" % profile_name, - secret_key_name) - boto.log.debug("Using secret key found in config file: " - "profile %s." % profile_name) - else: - raise ProfileNotFoundError('Profile "%s" not found!' % - profile_name) - elif shared.has_option('default', secret_key_name): - self.secret_key = shared.get('default', secret_key_name) - boto.log.debug("Using secret key found in shared credential file.") - elif config.has_option('Credentials', secret_key_name): - self.secret_key = config.get('Credentials', secret_key_name) - boto.log.debug("Using secret key found in config file.") - elif config.has_option('Credentials', 'keyring'): - keyring_name = config.get('Credentials', 'keyring') - try: - import keyring - except ImportError: - boto.log.error("The keyring module could not be imported. " - "For keyring support, install the keyring " - "module.") - raise - self.secret_key = keyring.get_password( - keyring_name, self.access_key) - boto.log.debug("Using secret key found in keyring.") - - if security_token is not None: - self.security_token = security_token - boto.log.debug("Using security token provided by client.") - elif ((security_token_name is not None) and - (access_key is None) and (secret_key is None)): - # Only provide a token from the environment/config if the - # caller did not specify a key and secret. Otherwise an - # environment/config token could be paired with a - # different set of credentials provided by the caller - if security_token_name.upper() in os.environ: - self.security_token = os.environ[security_token_name.upper()] - boto.log.debug("Using security token found in environment" - " variable.") - elif shared.has_option(profile_name or 'default', - security_token_name): - self.security_token = shared.get(profile_name or 'default', - security_token_name) - boto.log.debug("Using security token found in shared " - "credential file.") - elif profile_name is not None: - if config.has_option("profile %s" % profile_name, - security_token_name): - boto.log.debug("config has option") - self.security_token = config.get("profile %s" % profile_name, - security_token_name) - boto.log.debug("Using security token found in config file: " - "profile %s." % profile_name) - elif config.has_option('Credentials', security_token_name): - self.security_token = config.get('Credentials', - security_token_name) - boto.log.debug("Using security token found in config file.") - - if ((self._access_key is None or self._secret_key is None) and - self.MetadataServiceSupport[self.name]): - self._populate_keys_from_metadata_server() - self._secret_key = self._convert_key_to_str(self._secret_key) - - def _populate_keys_from_metadata_server(self): - # get_instance_metadata is imported here because of a circular - # dependency. - boto.log.debug("Retrieving credentials from metadata server.") - from boto.utils import get_instance_metadata - timeout = config.getfloat('Boto', 'metadata_service_timeout', 1.0) - attempts = config.getint('Boto', 'metadata_service_num_attempts', 1) - # The num_retries arg is actually the total number of attempts made, - # so the config options is named *_num_attempts to make this more - # clear to users. - metadata = get_instance_metadata( - timeout=timeout, num_retries=attempts, - data='meta-data/iam/security-credentials/') - if metadata: - # I'm assuming there's only one role on the instance profile. - security = list(metadata.values())[0] - self._access_key = security['AccessKeyId'] - self._secret_key = self._convert_key_to_str(security['SecretAccessKey']) - self._security_token = security['Token'] - expires_at = security['Expiration'] - self._credential_expiry_time = datetime.strptime( - expires_at, "%Y-%m-%dT%H:%M:%SZ") - boto.log.debug("Retrieved credentials will expire in %s at: %s", - self._credential_expiry_time - datetime.now(), expires_at) - - def _convert_key_to_str(self, key): - if isinstance(key, six.text_type): - # the secret key must be bytes and not unicode to work - # properly with hmac.new (see http://bugs.python.org/issue5285) - return str(key) - return key - - def configure_headers(self): - header_info_map = self.HeaderInfoMap[self.name] - self.metadata_prefix = header_info_map[METADATA_PREFIX_KEY] - self.header_prefix = header_info_map[HEADER_PREFIX_KEY] - self.acl_header = header_info_map[ACL_HEADER_KEY] - self.auth_header = header_info_map[AUTH_HEADER_KEY] - self.copy_source_header = header_info_map[COPY_SOURCE_HEADER_KEY] - self.copy_source_version_id = header_info_map[ - COPY_SOURCE_VERSION_ID_HEADER_KEY] - self.copy_source_range_header = header_info_map[ - COPY_SOURCE_RANGE_HEADER_KEY] - self.date_header = header_info_map[DATE_HEADER_KEY] - self.delete_marker = header_info_map[DELETE_MARKER_HEADER_KEY] - self.metadata_directive_header = ( - header_info_map[METADATA_DIRECTIVE_HEADER_KEY]) - self.security_token_header = header_info_map[SECURITY_TOKEN_HEADER_KEY] - self.resumable_upload_header = ( - header_info_map[RESUMABLE_UPLOAD_HEADER_KEY]) - self.server_side_encryption_header = header_info_map[SERVER_SIDE_ENCRYPTION_KEY] - self.storage_class_header = header_info_map[STORAGE_CLASS_HEADER_KEY] - self.version_id = header_info_map[VERSION_ID_HEADER_KEY] - self.mfa_header = header_info_map[MFA_HEADER_KEY] - self.restore_header = header_info_map[RESTORE_HEADER_KEY] - - def configure_errors(self): - error_map = self.ErrorMap[self.name] - self.storage_copy_error = error_map[STORAGE_COPY_ERROR] - self.storage_create_error = error_map[STORAGE_CREATE_ERROR] - self.storage_data_error = error_map[STORAGE_DATA_ERROR] - self.storage_permissions_error = error_map[STORAGE_PERMISSIONS_ERROR] - self.storage_response_error = error_map[STORAGE_RESPONSE_ERROR] - - def get_provider_name(self): - return self.HostKeyMap[self.name] - - def supports_chunked_transfer(self): - return self.ChunkedTransferSupport[self.name] - - -# Static utility method for getting default Provider. -def get_default(): - return Provider('aws') diff --git a/awx/lib/site-packages/boto/pyami/__init__.py b/awx/lib/site-packages/boto/pyami/__init__.py deleted file mode 100644 index 303dbb66c9..0000000000 --- a/awx/lib/site-packages/boto/pyami/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - diff --git a/awx/lib/site-packages/boto/pyami/bootstrap.py b/awx/lib/site-packages/boto/pyami/bootstrap.py deleted file mode 100644 index 82c2822edd..0000000000 --- a/awx/lib/site-packages/boto/pyami/bootstrap.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import os -import boto -from boto.utils import get_instance_metadata, get_instance_userdata -from boto.pyami.config import Config, BotoConfigPath -from boto.pyami.scriptbase import ScriptBase -import time - -class Bootstrap(ScriptBase): - """ - The Bootstrap class is instantiated and run as part of the PyAMI - instance initialization process. The methods in this class will - be run from the rc.local script of the instance and will be run - as the root user. - - The main purpose of this class is to make sure the boto distribution - on the instance is the one required. - """ - - def __init__(self): - self.working_dir = '/mnt/pyami' - self.write_metadata() - super(Bootstrap, self).__init__() - - def write_metadata(self): - fp = open(os.path.expanduser(BotoConfigPath), 'w') - fp.write('[Instance]\n') - inst_data = get_instance_metadata() - for key in inst_data: - fp.write('%s = %s\n' % (key, inst_data[key])) - user_data = get_instance_userdata() - fp.write('\n%s\n' % user_data) - fp.write('[Pyami]\n') - fp.write('working_dir = %s\n' % self.working_dir) - fp.close() - # This file has the AWS credentials, should we lock it down? - # os.chmod(BotoConfigPath, stat.S_IREAD | stat.S_IWRITE) - # now that we have written the file, read it into a pyami Config object - boto.config = Config() - boto.init_logging() - - def create_working_dir(self): - boto.log.info('Working directory: %s' % self.working_dir) - if not os.path.exists(self.working_dir): - os.mkdir(self.working_dir) - - def load_boto(self): - update = boto.config.get('Boto', 'boto_update', 'svn:HEAD') - if update.startswith('svn'): - if update.find(':') >= 0: - method, version = update.split(':') - version = '-r%s' % version - else: - version = '-rHEAD' - location = boto.config.get('Boto', 'boto_location', '/usr/local/boto') - self.run('svn update %s %s' % (version, location)) - elif update.startswith('git'): - location = boto.config.get('Boto', 'boto_location', '/usr/share/python-support/python-boto/boto') - num_remaining_attempts = 10 - while num_remaining_attempts > 0: - num_remaining_attempts -= 1 - try: - self.run('git pull', cwd=location) - num_remaining_attempts = 0 - except Exception as e: - boto.log.info('git pull attempt failed with the following exception. Trying again in a bit. %s', e) - time.sleep(2) - if update.find(':') >= 0: - method, version = update.split(':') - else: - version = 'master' - self.run('git checkout %s' % version, cwd=location) - else: - # first remove the symlink needed when running from subversion - self.run('rm /usr/local/lib/python2.5/site-packages/boto') - self.run('easy_install %s' % update) - - def fetch_s3_file(self, s3_file): - try: - from boto.utils import fetch_file - f = fetch_file(s3_file) - path = os.path.join(self.working_dir, s3_file.split("/")[-1]) - open(path, "w").write(f.read()) - except: - boto.log.exception('Problem Retrieving file: %s' % s3_file) - path = None - return path - - def load_packages(self): - package_str = boto.config.get('Pyami', 'packages') - if package_str: - packages = package_str.split(',') - for package in packages: - package = package.strip() - if package.startswith('s3:'): - package = self.fetch_s3_file(package) - if package: - # if the "package" is really a .py file, it doesn't have to - # be installed, just being in the working dir is enough - if not package.endswith('.py'): - self.run('easy_install -Z %s' % package, exit_on_error=False) - - def main(self): - self.create_working_dir() - self.load_boto() - self.load_packages() - self.notify('Bootstrap Completed for %s' % boto.config.get_instance('instance-id')) - -if __name__ == "__main__": - # because bootstrap starts before any logging configuration can be loaded from - # the boto config files, we will manually enable logging to /var/log/boto.log - boto.set_file_logger('bootstrap', '/var/log/boto.log') - bs = Bootstrap() - bs.main() diff --git a/awx/lib/site-packages/boto/pyami/config.py b/awx/lib/site-packages/boto/pyami/config.py deleted file mode 100644 index 37445f85c3..0000000000 --- a/awx/lib/site-packages/boto/pyami/config.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import os -import re -import warnings - -import boto - -from boto.compat import expanduser, ConfigParser, StringIO - - -# By default we use two locations for the boto configurations, -# /etc/boto.cfg and ~/.boto (which works on Windows and Unix). -BotoConfigPath = '/etc/boto.cfg' -BotoConfigLocations = [BotoConfigPath] -UserConfigPath = os.path.join(expanduser('~'), '.boto') -BotoConfigLocations.append(UserConfigPath) - -# If there's a BOTO_CONFIG variable set, we load ONLY -# that variable -if 'BOTO_CONFIG' in os.environ: - BotoConfigLocations = [expanduser(os.environ['BOTO_CONFIG'])] - -# If there's a BOTO_PATH variable set, we use anything there -# as the current configuration locations, split with colons -elif 'BOTO_PATH' in os.environ: - BotoConfigLocations = [] - for path in os.environ['BOTO_PATH'].split(":"): - BotoConfigLocations.append(expanduser(path)) - - -class Config(ConfigParser): - - def __init__(self, path=None, fp=None, do_load=True): - # We don't use ``super`` here, because ``ConfigParser`` still uses - # old-style classes. - ConfigParser.__init__(self, {'working_dir': '/mnt/pyami', - 'debug': '0'}) - if do_load: - if path: - self.load_from_path(path) - elif fp: - self.readfp(fp) - else: - self.read(BotoConfigLocations) - if "AWS_CREDENTIAL_FILE" in os.environ: - full_path = expanduser(os.environ['AWS_CREDENTIAL_FILE']) - try: - self.load_credential_file(full_path) - except IOError: - warnings.warn('Unable to load AWS_CREDENTIAL_FILE (%s)' % full_path) - - def load_credential_file(self, path): - """Load a credential file as is setup like the Java utilities""" - c_data = StringIO() - c_data.write("[Credentials]\n") - for line in open(path, "r").readlines(): - c_data.write(line.replace("AWSAccessKeyId", "aws_access_key_id").replace("AWSSecretKey", "aws_secret_access_key")) - c_data.seek(0) - self.readfp(c_data) - - def load_from_path(self, path): - file = open(path) - for line in file.readlines(): - match = re.match("^#import[\s\t]*([^\s^\t]*)[\s\t]*$", line) - if match: - extended_file = match.group(1) - (dir, file) = os.path.split(path) - self.load_from_path(os.path.join(dir, extended_file)) - self.read(path) - - def save_option(self, path, section, option, value): - """ - Write the specified Section.Option to the config file specified by path. - Replace any previous value. If the path doesn't exist, create it. - Also add the option the the in-memory config. - """ - config = ConfigParser() - config.read(path) - if not config.has_section(section): - config.add_section(section) - config.set(section, option, value) - fp = open(path, 'w') - config.write(fp) - fp.close() - if not self.has_section(section): - self.add_section(section) - self.set(section, option, value) - - def save_user_option(self, section, option, value): - self.save_option(UserConfigPath, section, option, value) - - def save_system_option(self, section, option, value): - self.save_option(BotoConfigPath, section, option, value) - - def get_instance(self, name, default=None): - try: - val = self.get('Instance', name) - except: - val = default - return val - - def get_user(self, name, default=None): - try: - val = self.get('User', name) - except: - val = default - return val - - def getint_user(self, name, default=0): - try: - val = self.getint('User', name) - except: - val = default - return val - - def get_value(self, section, name, default=None): - return self.get(section, name, default) - - def get(self, section, name, default=None): - try: - val = ConfigParser.get(self, section, name) - except: - val = default - return val - - def getint(self, section, name, default=0): - try: - val = ConfigParser.getint(self, section, name) - except: - val = int(default) - return val - - def getfloat(self, section, name, default=0.0): - try: - val = ConfigParser.getfloat(self, section, name) - except: - val = float(default) - return val - - def getbool(self, section, name, default=False): - if self.has_option(section, name): - val = self.get(section, name) - if val.lower() == 'true': - val = True - else: - val = False - else: - val = default - return val - - def setbool(self, section, name, value): - if value: - self.set(section, name, 'true') - else: - self.set(section, name, 'false') - - def dump(self): - s = StringIO() - self.write(s) - print(s.getvalue()) - - def dump_safe(self, fp=None): - if not fp: - fp = StringIO() - for section in self.sections(): - fp.write('[%s]\n' % section) - for option in self.options(section): - if option == 'aws_secret_access_key': - fp.write('%s = xxxxxxxxxxxxxxxxxx\n' % option) - else: - fp.write('%s = %s\n' % (option, self.get(section, option))) - - def dump_to_sdb(self, domain_name, item_name): - from boto.compat import json - sdb = boto.connect_sdb() - domain = sdb.lookup(domain_name) - if not domain: - domain = sdb.create_domain(domain_name) - item = domain.new_item(item_name) - item.active = False - for section in self.sections(): - d = {} - for option in self.options(section): - d[option] = self.get(section, option) - item[section] = json.dumps(d) - item.save() - - def load_from_sdb(self, domain_name, item_name): - from boto.compat import json - sdb = boto.connect_sdb() - domain = sdb.lookup(domain_name) - item = domain.get_item(item_name) - for section in item.keys(): - if not self.has_section(section): - self.add_section(section) - d = json.loads(item[section]) - for attr_name in d.keys(): - attr_value = d[attr_name] - if attr_value is None: - attr_value = 'None' - if isinstance(attr_value, bool): - self.setbool(section, attr_name, attr_value) - else: - self.set(section, attr_name, attr_value) diff --git a/awx/lib/site-packages/boto/pyami/copybot.cfg b/awx/lib/site-packages/boto/pyami/copybot.cfg deleted file mode 100644 index cbfdc5ad19..0000000000 --- a/awx/lib/site-packages/boto/pyami/copybot.cfg +++ /dev/null @@ -1,60 +0,0 @@ -# -# Your AWS Credentials -# -[Credentials] -aws_access_key_id = <AWS Access Key Here> -aws_secret_access_key = <AWS Secret Key Here> - -# -# If you want to use a separate set of credentials when writing -# to the destination bucket, put them here -#dest_aws_access_key_id = <AWS Access Key Here> -#dest_aws_secret_access_key = <AWS Secret Key Here> - -# -# Fill out this section if you want emails from CopyBot -# when it starts and stops -# -[Notification] -#smtp_host = <your smtp host> -#smtp_user = <your smtp username, if necessary> -#smtp_pass = <your smtp password, if necessary> -#smtp_from = <email address for From: field> -#smtp_to = <email address for To: field> - -# -# If you leave this section as is, it will automatically -# update boto from subversion upon start up. -# If you don't want that to happen, comment this out -# -[Boto] -boto_location = /usr/local/boto -boto_update = svn:HEAD - -# -# This tells the Pyami code in boto what scripts -# to run during startup -# -[Pyami] -scripts = boto.pyami.copybot.CopyBot - -# -# Source bucket and Destination Bucket, obviously. -# If the Destination bucket does not exist, it will -# attempt to create it. -# If exit_on_completion is false, the instance -# will keep running after the copy operation is -# complete which might be handy for debugging. -# If copy_acls is false, the ACL's will not be -# copied with the objects to the new bucket. -# If replace_dst is false, copybot will not -# will only store the source file in the dest if -# that file does not already exist. If it's true -# it will replace it even if it does exist. -# -[CopyBot] -src_bucket = <your source bucket name> -dst_bucket = <your destination bucket name> -exit_on_completion = true -copy_acls = true -replace_dst = true diff --git a/awx/lib/site-packages/boto/pyami/copybot.py b/awx/lib/site-packages/boto/pyami/copybot.py deleted file mode 100644 index 09a6d444c5..0000000000 --- a/awx/lib/site-packages/boto/pyami/copybot.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import boto -from boto.pyami.scriptbase import ScriptBase -import os, StringIO - -class CopyBot(ScriptBase): - - def __init__(self): - super(CopyBot, self).__init__() - self.wdir = boto.config.get('Pyami', 'working_dir') - self.log_file = '%s.log' % self.instance_id - self.log_path = os.path.join(self.wdir, self.log_file) - boto.set_file_logger(self.name, self.log_path) - self.src_name = boto.config.get(self.name, 'src_bucket') - self.dst_name = boto.config.get(self.name, 'dst_bucket') - self.replace = boto.config.getbool(self.name, 'replace_dst', True) - s3 = boto.connect_s3() - self.src = s3.lookup(self.src_name) - if not self.src: - boto.log.error('Source bucket does not exist: %s' % self.src_name) - dest_access_key = boto.config.get(self.name, 'dest_aws_access_key_id', None) - if dest_access_key: - dest_secret_key = boto.config.get(self.name, 'dest_aws_secret_access_key', None) - s3 = boto.connect(dest_access_key, dest_secret_key) - self.dst = s3.lookup(self.dst_name) - if not self.dst: - self.dst = s3.create_bucket(self.dst_name) - - def copy_bucket_acl(self): - if boto.config.get(self.name, 'copy_acls', True): - acl = self.src.get_xml_acl() - self.dst.set_xml_acl(acl) - - def copy_key_acl(self, src, dst): - if boto.config.get(self.name, 'copy_acls', True): - acl = src.get_xml_acl() - dst.set_xml_acl(acl) - - def copy_keys(self): - boto.log.info('src=%s' % self.src.name) - boto.log.info('dst=%s' % self.dst.name) - try: - for key in self.src: - if not self.replace: - exists = self.dst.lookup(key.name) - if exists: - boto.log.info('key=%s already exists in %s, skipping' % (key.name, self.dst.name)) - continue - boto.log.info('copying %d bytes from key=%s' % (key.size, key.name)) - prefix, base = os.path.split(key.name) - path = os.path.join(self.wdir, base) - key.get_contents_to_filename(path) - new_key = self.dst.new_key(key.name) - new_key.set_contents_from_filename(path) - self.copy_key_acl(key, new_key) - os.unlink(path) - except: - boto.log.exception('Error copying key: %s' % key.name) - - def copy_log(self): - key = self.dst.new_key(self.log_file) - key.set_contents_from_filename(self.log_path) - - def main(self): - fp = StringIO.StringIO() - boto.config.dump_safe(fp) - self.notify('%s (%s) Starting' % (self.name, self.instance_id), fp.getvalue()) - if self.src and self.dst: - self.copy_keys() - if self.dst: - self.copy_log() - self.notify('%s (%s) Stopping' % (self.name, self.instance_id), - 'Copy Operation Complete') - if boto.config.getbool(self.name, 'exit_on_completion', True): - ec2 = boto.connect_ec2() - ec2.terminate_instances([self.instance_id]) diff --git a/awx/lib/site-packages/boto/pyami/helloworld.py b/awx/lib/site-packages/boto/pyami/helloworld.py deleted file mode 100644 index b9b53b60c5..0000000000 --- a/awx/lib/site-packages/boto/pyami/helloworld.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.pyami.scriptbase import ScriptBase - -class HelloWorld(ScriptBase): - - def main(self): - self.log('Hello World!!!') diff --git a/awx/lib/site-packages/boto/pyami/installers/__init__.py b/awx/lib/site-packages/boto/pyami/installers/__init__.py deleted file mode 100644 index 44abd0d24a..0000000000 --- a/awx/lib/site-packages/boto/pyami/installers/__init__.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.pyami.scriptbase import ScriptBase - - -class Installer(ScriptBase): - """ - Abstract base class for installers - """ - - def add_cron(self, name, minute, hour, mday, month, wday, who, command, env=None): - """ - Add an entry to the system crontab. - """ - raise NotImplementedError - - def add_init_script(self, file): - """ - Add this file to the init.d directory - """ - - def add_env(self, key, value): - """ - Add an environemnt variable - """ - raise NotImplementedError - - def stop(self, service_name): - """ - Stop a service. - """ - raise NotImplementedError - - def start(self, service_name): - """ - Start a service. - """ - raise NotImplementedError - - def install(self): - """ - Do whatever is necessary to "install" the package. - """ - raise NotImplementedError diff --git a/awx/lib/site-packages/boto/pyami/installers/ubuntu/__init__.py b/awx/lib/site-packages/boto/pyami/installers/ubuntu/__init__.py deleted file mode 100644 index 60ee658e34..0000000000 --- a/awx/lib/site-packages/boto/pyami/installers/ubuntu/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - diff --git a/awx/lib/site-packages/boto/pyami/installers/ubuntu/apache.py b/awx/lib/site-packages/boto/pyami/installers/ubuntu/apache.py deleted file mode 100644 index febc2dfa25..0000000000 --- a/awx/lib/site-packages/boto/pyami/installers/ubuntu/apache.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2008 Chris Moyer http://coredumped.org -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.pyami.installers.ubuntu.installer import Installer - -class Apache(Installer): - """ - Install apache2, mod_python, and libapache2-svn - """ - - def install(self): - self.run("apt-get update") - self.run('apt-get -y install apache2', notify=True, exit_on_error=True) - self.run('apt-get -y install libapache2-mod-python', notify=True, exit_on_error=True) - self.run('a2enmod rewrite', notify=True, exit_on_error=True) - self.run('a2enmod ssl', notify=True, exit_on_error=True) - self.run('a2enmod proxy', notify=True, exit_on_error=True) - self.run('a2enmod proxy_ajp', notify=True, exit_on_error=True) - - # Hard reboot the apache2 server to enable these module - self.stop("apache2") - self.start("apache2") - - def main(self): - self.install() diff --git a/awx/lib/site-packages/boto/pyami/installers/ubuntu/ebs.py b/awx/lib/site-packages/boto/pyami/installers/ubuntu/ebs.py deleted file mode 100644 index 54a479859d..0000000000 --- a/awx/lib/site-packages/boto/pyami/installers/ubuntu/ebs.py +++ /dev/null @@ -1,238 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -""" -Automated installer to attach, format and mount an EBS volume. -This installer assumes that you want the volume formatted as -an XFS file system. To drive this installer, you need the -following section in the boto config passed to the new instance. -You also need to install dateutil by listing python-dateutil -in the list of packages to be installed in the Pyami seciont -of your boto config file. - -If there is already a device mounted at the specified mount point, -the installer assumes that it is the ephemeral drive and unmounts -it, remounts it as /tmp and chmods it to 777. - -Config file section:: - - [EBS] - volume_id = <the id of the EBS volume, should look like vol-xxxxxxxx> - logical_volume_name = <the name of the logical volume that contaings - a reference to the physical volume to be mounted. If this parameter - is supplied, it overrides the volume_id setting.> - device = <the linux device the EBS volume should be mounted on> - mount_point = <directory to mount device, defaults to /ebs> - -""" -import boto -from boto.manage.volume import Volume -from boto.exception import EC2ResponseError -import os, time -from boto.pyami.installers.ubuntu.installer import Installer -from string import Template - -BackupScriptTemplate = """#!/usr/bin/env python -# Backup EBS volume -import boto -from boto.pyami.scriptbase import ScriptBase -import traceback - -class Backup(ScriptBase): - - def main(self): - try: - ec2 = boto.connect_ec2() - self.run("/usr/sbin/xfs_freeze -f ${mount_point}", exit_on_error = True) - snapshot = ec2.create_snapshot('${volume_id}') - boto.log.info("Snapshot created: %s " % snapshot) - except Exception, e: - self.notify(subject="${instance_id} Backup Failed", body=traceback.format_exc()) - boto.log.info("Snapshot created: ${volume_id}") - except Exception, e: - self.notify(subject="${instance_id} Backup Failed", body=traceback.format_exc()) - finally: - self.run("/usr/sbin/xfs_freeze -u ${mount_point}") - -if __name__ == "__main__": - b = Backup() - b.main() -""" - -BackupCleanupScript= """#!/usr/bin/env python -import boto -from boto.manage.volume import Volume - -# Cleans Backups of EBS volumes - -for v in Volume.all(): - v.trim_snapshots(True) -""" - -TagBasedBackupCleanupScript= """#!/usr/bin/env python -import boto - -# Cleans Backups of EBS volumes - -ec2 = boto.connect_ec2() -ec2.trim_snapshots() -""" - -class EBSInstaller(Installer): - """ - Set up the EBS stuff - """ - - def __init__(self, config_file=None): - super(EBSInstaller, self).__init__(config_file) - self.instance_id = boto.config.get('Instance', 'instance-id') - self.device = boto.config.get('EBS', 'device', '/dev/sdp') - self.volume_id = boto.config.get('EBS', 'volume_id') - self.logical_volume_name = boto.config.get('EBS', 'logical_volume_name') - self.mount_point = boto.config.get('EBS', 'mount_point', '/ebs') - - def attach(self): - ec2 = boto.connect_ec2() - if self.logical_volume_name: - # if a logical volume was specified, override the specified volume_id - # (if there was one) with the current AWS volume for the logical volume: - logical_volume = next(Volume.find(name=self.logical_volume_name)) - self.volume_id = logical_volume._volume_id - volume = ec2.get_all_volumes([self.volume_id])[0] - # wait for the volume to be available. The volume may still be being created - # from a snapshot. - while volume.update() != 'available': - boto.log.info('Volume %s not yet available. Current status = %s.' % (volume.id, volume.status)) - time.sleep(5) - instance = ec2.get_only_instances([self.instance_id])[0] - attempt_attach = True - while attempt_attach: - try: - ec2.attach_volume(self.volume_id, self.instance_id, self.device) - attempt_attach = False - except EC2ResponseError as e: - if e.error_code != 'IncorrectState': - # if there's an EC2ResonseError with the code set to IncorrectState, delay a bit for ec2 - # to realize the instance is running, then try again. Otherwise, raise the error: - boto.log.info('Attempt to attach the EBS volume %s to this instance (%s) returned %s. Trying again in a bit.' % (self.volume_id, self.instance_id, e.errors)) - time.sleep(2) - else: - raise e - boto.log.info('Attached volume %s to instance %s as device %s' % (self.volume_id, self.instance_id, self.device)) - # now wait for the volume device to appear - while not os.path.exists(self.device): - boto.log.info('%s still does not exist, waiting 2 seconds' % self.device) - time.sleep(2) - - def make_fs(self): - boto.log.info('make_fs...') - has_fs = self.run('fsck %s' % self.device) - if has_fs != 0: - self.run('mkfs -t xfs %s' % self.device) - - def create_backup_script(self): - t = Template(BackupScriptTemplate) - s = t.substitute(volume_id=self.volume_id, instance_id=self.instance_id, - mount_point=self.mount_point) - fp = open('/usr/local/bin/ebs_backup', 'w') - fp.write(s) - fp.close() - self.run('chmod +x /usr/local/bin/ebs_backup') - - def create_backup_cleanup_script(self, use_tag_based_cleanup=False): - fp = open('/usr/local/bin/ebs_backup_cleanup', 'w') - if use_tag_based_cleanup: - fp.write(TagBasedBackupCleanupScript) - else: - fp.write(BackupCleanupScript) - fp.close() - self.run('chmod +x /usr/local/bin/ebs_backup_cleanup') - - def handle_mount_point(self): - boto.log.info('handle_mount_point') - if not os.path.isdir(self.mount_point): - boto.log.info('making directory') - # mount directory doesn't exist so create it - self.run("mkdir %s" % self.mount_point) - else: - boto.log.info('directory exists already') - self.run('mount -l') - lines = self.last_command.output.split('\n') - for line in lines: - t = line.split() - if t and t[2] == self.mount_point: - # something is already mounted at the mount point - # unmount that and mount it as /tmp - if t[0] != self.device: - self.run('umount %s' % self.mount_point) - self.run('mount %s /tmp' % t[0]) - break - self.run('chmod 777 /tmp') - # Mount up our new EBS volume onto mount_point - self.run("mount %s %s" % (self.device, self.mount_point)) - self.run('xfs_growfs %s' % self.mount_point) - - def update_fstab(self): - f = open("/etc/fstab", "a") - f.write('%s\t%s\txfs\tdefaults 0 0\n' % (self.device, self.mount_point)) - f.close() - - def install(self): - # First, find and attach the volume - self.attach() - - # Install the xfs tools - self.run('apt-get -y install xfsprogs xfsdump') - - # Check to see if the filesystem was created or not - self.make_fs() - - # create the /ebs directory for mounting - self.handle_mount_point() - - # create the backup script - self.create_backup_script() - - # Set up the backup script - minute = boto.config.get('EBS', 'backup_cron_minute', '0') - hour = boto.config.get('EBS', 'backup_cron_hour', '4,16') - self.add_cron("ebs_backup", "/usr/local/bin/ebs_backup", minute=minute, hour=hour) - - # Set up the backup cleanup script - minute = boto.config.get('EBS', 'backup_cleanup_cron_minute') - hour = boto.config.get('EBS', 'backup_cleanup_cron_hour') - if (minute is not None) and (hour is not None): - # Snapshot clean up can either be done via the manage module, or via the new tag based - # snapshot code, if the snapshots have been tagged with the name of the associated - # volume. Check for the presence of the new configuration flag, and use the appropriate - # cleanup method / script: - use_tag_based_cleanup = boto.config.has_option('EBS', 'use_tag_based_snapshot_cleanup') - self.create_backup_cleanup_script(use_tag_based_cleanup) - self.add_cron("ebs_backup_cleanup", "/usr/local/bin/ebs_backup_cleanup", minute=minute, hour=hour) - - # Set up the fstab - self.update_fstab() - - def main(self): - if not os.path.exists(self.device): - self.install() - else: - boto.log.info("Device %s is already attached, skipping EBS Installer" % self.device) diff --git a/awx/lib/site-packages/boto/pyami/installers/ubuntu/installer.py b/awx/lib/site-packages/boto/pyami/installers/ubuntu/installer.py deleted file mode 100644 index 5a2abd908b..0000000000 --- a/awx/lib/site-packages/boto/pyami/installers/ubuntu/installer.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import boto.pyami.installers -import os -import os.path -import stat -import boto -import random -from pwd import getpwnam - -class Installer(boto.pyami.installers.Installer): - """ - Base Installer class for Ubuntu-based AMI's - """ - def add_cron(self, name, command, minute="*", hour="*", mday="*", month="*", wday="*", who="root", env=None): - """ - Write a file to /etc/cron.d to schedule a command - env is a dict containing environment variables you want to set in the file - name will be used as the name of the file - """ - if minute == 'random': - minute = str(random.randrange(60)) - if hour == 'random': - hour = str(random.randrange(24)) - fp = open('/etc/cron.d/%s' % name, "w") - if env: - for key, value in env.items(): - fp.write('%s=%s\n' % (key, value)) - fp.write('%s %s %s %s %s %s %s\n' % (minute, hour, mday, month, wday, who, command)) - fp.close() - - def add_init_script(self, file, name): - """ - Add this file to the init.d directory - """ - f_path = os.path.join("/etc/init.d", name) - f = open(f_path, "w") - f.write(file) - f.close() - os.chmod(f_path, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC) - self.run("/usr/sbin/update-rc.d %s defaults" % name) - - def add_env(self, key, value): - """ - Add an environemnt variable - For Ubuntu, the best place is /etc/environment. Values placed here do - not need to be exported. - """ - boto.log.info('Adding env variable: %s=%s' % (key, value)) - if not os.path.exists("/etc/environment.orig"): - self.run('cp /etc/environment /etc/environment.orig', notify=False, exit_on_error=False) - fp = open('/etc/environment', 'a') - fp.write('\n%s="%s"' % (key, value)) - fp.close() - os.environ[key] = value - - def stop(self, service_name): - self.run('/etc/init.d/%s stop' % service_name) - - def start(self, service_name): - self.run('/etc/init.d/%s start' % service_name) - - def create_user(self, user): - """ - Create a user on the local system - """ - self.run("useradd -m %s" % user) - usr = getpwnam(user) - return usr - - def install(self): - """ - This is the only method you need to override - """ - raise NotImplementedError diff --git a/awx/lib/site-packages/boto/pyami/installers/ubuntu/mysql.py b/awx/lib/site-packages/boto/pyami/installers/ubuntu/mysql.py deleted file mode 100644 index 5b0792ba9d..0000000000 --- a/awx/lib/site-packages/boto/pyami/installers/ubuntu/mysql.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -""" -This installer will install mysql-server on an Ubuntu machine. -In addition to the normal installation done by apt-get, it will -also configure the new MySQL server to store it's data files in -a different location. By default, this is /mnt but that can be -configured in the [MySQL] section of the boto config file passed -to the instance. -""" -from boto.pyami.installers.ubuntu.installer import Installer -import os -import boto -from boto.utils import ShellCommand -from boto.compat import ConfigParser -import time - -ConfigSection = """ -[MySQL] -root_password = <will be used as MySQL root password, default none> -data_dir = <new data dir for MySQL, default is /mnt> -""" - -class MySQL(Installer): - - def install(self): - self.run('apt-get update') - self.run('apt-get -y install mysql-server', notify=True, exit_on_error=True) - -# def set_root_password(self, password=None): -# if not password: -# password = boto.config.get('MySQL', 'root_password') -# if password: -# self.run('mysqladmin -u root password %s' % password) -# return password - - def change_data_dir(self, password=None): - data_dir = boto.config.get('MySQL', 'data_dir', '/mnt') - fresh_install = False - is_mysql_running_command = ShellCommand('mysqladmin ping') # exit status 0 if mysql is running - is_mysql_running_command.run() - if is_mysql_running_command.getStatus() == 0: - # mysql is running. This is the state apt-get will leave it in. If it isn't running, - # that means mysql was already installed on the AMI and there's no need to stop it, - # saving 40 seconds on instance startup. - time.sleep(10) #trying to stop mysql immediately after installing it fails - # We need to wait until mysql creates the root account before we kill it - # or bad things will happen - i = 0 - while self.run("echo 'quit' | mysql -u root") != 0 and i < 5: - time.sleep(5) - i = i + 1 - self.run('/etc/init.d/mysql stop') - self.run("pkill -9 mysql") - - mysql_path = os.path.join(data_dir, 'mysql') - if not os.path.exists(mysql_path): - self.run('mkdir %s' % mysql_path) - fresh_install = True - self.run('chown -R mysql:mysql %s' % mysql_path) - fp = open('/etc/mysql/conf.d/use_mnt.cnf', 'w') - fp.write('# created by pyami\n') - fp.write('# use the %s volume for data\n' % data_dir) - fp.write('[mysqld]\n') - fp.write('datadir = %s\n' % mysql_path) - fp.write('log_bin = %s\n' % os.path.join(mysql_path, 'mysql-bin.log')) - fp.close() - if fresh_install: - self.run('cp -pr /var/lib/mysql/* %s/' % mysql_path) - self.start('mysql') - else: - #get the password ubuntu expects to use: - config_parser = ConfigParser() - config_parser.read('/etc/mysql/debian.cnf') - password = config_parser.get('client', 'password') - # start the mysql deamon, then mysql with the required grant statement piped into it: - self.start('mysql') - time.sleep(10) #time for mysql to start - grant_command = "echo \"GRANT ALL PRIVILEGES ON *.* TO 'debian-sys-maint'@'localhost' IDENTIFIED BY '%s' WITH GRANT OPTION;\" | mysql" % password - while self.run(grant_command) != 0: - time.sleep(5) - # leave mysqld running - - def main(self): - self.install() - # change_data_dir runs 'mysql -u root' which assumes there is no mysql password, i - # and changing that is too ugly to be worth it: - #self.set_root_password() - self.change_data_dir() diff --git a/awx/lib/site-packages/boto/pyami/installers/ubuntu/trac.py b/awx/lib/site-packages/boto/pyami/installers/ubuntu/trac.py deleted file mode 100644 index 8c51c8f720..0000000000 --- a/awx/lib/site-packages/boto/pyami/installers/ubuntu/trac.py +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright (c) 2008 Chris Moyer http://coredumped.org -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.pyami.installers.ubuntu.installer import Installer -import boto -import os - -class Trac(Installer): - """ - Install Trac and DAV-SVN - Sets up a Vhost pointing to [Trac]->home - Using the config parameter [Trac]->hostname - Sets up a trac environment for every directory found under [Trac]->data_dir - - [Trac] - name = My Foo Server - hostname = trac.foo.com - home = /mnt/sites/trac - data_dir = /mnt/trac - svn_dir = /mnt/subversion - server_admin = root@foo.com - sdb_auth_domain = users - # Optional - SSLCertificateFile = /mnt/ssl/foo.crt - SSLCertificateKeyFile = /mnt/ssl/foo.key - SSLCertificateChainFile = /mnt/ssl/FooCA.crt - - """ - - def install(self): - self.run('apt-get -y install trac', notify=True, exit_on_error=True) - self.run('apt-get -y install libapache2-svn', notify=True, exit_on_error=True) - self.run("a2enmod ssl") - self.run("a2enmod mod_python") - self.run("a2enmod dav_svn") - self.run("a2enmod rewrite") - # Make sure that boto.log is writable by everyone so that subversion post-commit hooks can - # write to it. - self.run("touch /var/log/boto.log") - self.run("chmod a+w /var/log/boto.log") - - def setup_vhost(self): - domain = boto.config.get("Trac", "hostname").strip() - if domain: - domain_info = domain.split('.') - cnf = open("/etc/apache2/sites-available/%s" % domain_info[0], "w") - cnf.write("NameVirtualHost *:80\n") - if boto.config.get("Trac", "SSLCertificateFile"): - cnf.write("NameVirtualHost *:443\n\n") - cnf.write("<VirtualHost *:80>\n") - cnf.write("\tServerAdmin %s\n" % boto.config.get("Trac", "server_admin").strip()) - cnf.write("\tServerName %s\n" % domain) - cnf.write("\tRewriteEngine On\n") - cnf.write("\tRewriteRule ^(.*)$ https://%s$1\n" % domain) - cnf.write("</VirtualHost>\n\n") - - cnf.write("<VirtualHost *:443>\n") - else: - cnf.write("<VirtualHost *:80>\n") - - cnf.write("\tServerAdmin %s\n" % boto.config.get("Trac", "server_admin").strip()) - cnf.write("\tServerName %s\n" % domain) - cnf.write("\tDocumentRoot %s\n" % boto.config.get("Trac", "home").strip()) - - cnf.write("\t<Directory %s>\n" % boto.config.get("Trac", "home").strip()) - cnf.write("\t\tOptions FollowSymLinks Indexes MultiViews\n") - cnf.write("\t\tAllowOverride All\n") - cnf.write("\t\tOrder allow,deny\n") - cnf.write("\t\tallow from all\n") - cnf.write("\t</Directory>\n") - - cnf.write("\t<Location />\n") - cnf.write("\t\tAuthType Basic\n") - cnf.write("\t\tAuthName \"%s\"\n" % boto.config.get("Trac", "name")) - cnf.write("\t\tRequire valid-user\n") - cnf.write("\t\tAuthUserFile /mnt/apache/passwd/passwords\n") - cnf.write("\t</Location>\n") - - data_dir = boto.config.get("Trac", "data_dir") - for env in os.listdir(data_dir): - if(env[0] != "."): - cnf.write("\t<Location /trac/%s>\n" % env) - cnf.write("\t\tSetHandler mod_python\n") - cnf.write("\t\tPythonInterpreter main_interpreter\n") - cnf.write("\t\tPythonHandler trac.web.modpython_frontend\n") - cnf.write("\t\tPythonOption TracEnv %s/%s\n" % (data_dir, env)) - cnf.write("\t\tPythonOption TracUriRoot /trac/%s\n" % env) - cnf.write("\t</Location>\n") - - svn_dir = boto.config.get("Trac", "svn_dir") - for env in os.listdir(svn_dir): - if(env[0] != "."): - cnf.write("\t<Location /svn/%s>\n" % env) - cnf.write("\t\tDAV svn\n") - cnf.write("\t\tSVNPath %s/%s\n" % (svn_dir, env)) - cnf.write("\t</Location>\n") - - cnf.write("\tErrorLog /var/log/apache2/error.log\n") - cnf.write("\tLogLevel warn\n") - cnf.write("\tCustomLog /var/log/apache2/access.log combined\n") - cnf.write("\tServerSignature On\n") - SSLCertificateFile = boto.config.get("Trac", "SSLCertificateFile") - if SSLCertificateFile: - cnf.write("\tSSLEngine On\n") - cnf.write("\tSSLCertificateFile %s\n" % SSLCertificateFile) - - SSLCertificateKeyFile = boto.config.get("Trac", "SSLCertificateKeyFile") - if SSLCertificateKeyFile: - cnf.write("\tSSLCertificateKeyFile %s\n" % SSLCertificateKeyFile) - - SSLCertificateChainFile = boto.config.get("Trac", "SSLCertificateChainFile") - if SSLCertificateChainFile: - cnf.write("\tSSLCertificateChainFile %s\n" % SSLCertificateChainFile) - cnf.write("</VirtualHost>\n") - cnf.close() - self.run("a2ensite %s" % domain_info[0]) - self.run("/etc/init.d/apache2 force-reload") - - def main(self): - self.install() - self.setup_vhost() diff --git a/awx/lib/site-packages/boto/pyami/launch_ami.py b/awx/lib/site-packages/boto/pyami/launch_ami.py deleted file mode 100644 index 9037217b61..0000000000 --- a/awx/lib/site-packages/boto/pyami/launch_ami.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import getopt -import sys -import imp -import time -import boto - -usage_string = """ -SYNOPSIS - launch_ami.py -a ami_id [-b script_bucket] [-s script_name] - [-m module] [-c class_name] [-r] - [-g group] [-k key_name] [-n num_instances] - [-w] [extra_data] - Where: - ami_id - the id of the AMI you wish to launch - module - The name of the Python module containing the class you - want to run when the instance is started. If you use this - option the Python module must already be stored on the - instance in a location that is on the Python path. - script_file - The name of a local Python module that you would like - to have copied to S3 and then run on the instance - when it is started. The specified module must be - import'able (i.e. in your local Python path). It - will then be copied to the specified bucket in S3 - (see the -b option). Once the new instance(s) - start up the script will be copied from S3 and then - run locally on the instance. - class_name - The name of the class to be instantiated within the - module or script file specified. - script_bucket - the name of the bucket in which the script will be - stored - group - the name of the security group the instance will run in - key_name - the name of the keypair to use when launching the AMI - num_instances - how many instances of the AMI to launch (default 1) - input_queue_name - Name of SQS to read input messages from - output_queue_name - Name of SQS to write output messages to - extra_data - additional name-value pairs that will be passed as - userdata to the newly launched instance. These should - be of the form "name=value" - The -r option reloads the Python module to S3 without launching - another instance. This can be useful during debugging to allow - you to test a new version of your script without shutting down - your instance and starting up another one. - The -w option tells the script to run synchronously, meaning to - wait until the instance is actually up and running. It then prints - the IP address and internal and external DNS names before exiting. -""" - -def usage(): - print(usage_string) - sys.exit() - -def main(): - try: - opts, args = getopt.getopt(sys.argv[1:], 'a:b:c:g:hi:k:m:n:o:rs:w', - ['ami', 'bucket', 'class', 'group', 'help', - 'inputqueue', 'keypair', 'module', - 'numinstances', 'outputqueue', - 'reload', 'script_name', 'wait']) - except: - usage() - params = {'module_name': None, - 'script_name': None, - 'class_name': None, - 'script_bucket': None, - 'group': 'default', - 'keypair': None, - 'ami': None, - 'num_instances': 1, - 'input_queue_name': None, - 'output_queue_name': None} - reload = None - wait = None - for o, a in opts: - if o in ('-a', '--ami'): - params['ami'] = a - if o in ('-b', '--bucket'): - params['script_bucket'] = a - if o in ('-c', '--class'): - params['class_name'] = a - if o in ('-g', '--group'): - params['group'] = a - if o in ('-h', '--help'): - usage() - if o in ('-i', '--inputqueue'): - params['input_queue_name'] = a - if o in ('-k', '--keypair'): - params['keypair'] = a - if o in ('-m', '--module'): - params['module_name'] = a - if o in ('-n', '--num_instances'): - params['num_instances'] = int(a) - if o in ('-o', '--outputqueue'): - params['output_queue_name'] = a - if o in ('-r', '--reload'): - reload = True - if o in ('-s', '--script'): - params['script_name'] = a - if o in ('-w', '--wait'): - wait = True - - # check required fields - required = ['ami'] - for pname in required: - if not params.get(pname, None): - print('%s is required' % pname) - usage() - if params['script_name']: - # first copy the desired module file to S3 bucket - if reload: - print('Reloading module %s to S3' % params['script_name']) - else: - print('Copying module %s to S3' % params['script_name']) - l = imp.find_module(params['script_name']) - c = boto.connect_s3() - bucket = c.get_bucket(params['script_bucket']) - key = bucket.new_key(params['script_name'] + '.py') - key.set_contents_from_file(l[0]) - params['script_md5'] = key.md5 - # we have everything we need, now build userdata string - l = [] - for k, v in params.items(): - if v: - l.append('%s=%s' % (k, v)) - c = boto.connect_ec2() - l.append('aws_access_key_id=%s' % c.aws_access_key_id) - l.append('aws_secret_access_key=%s' % c.aws_secret_access_key) - for kv in args: - l.append(kv) - s = '|'.join(l) - if not reload: - rs = c.get_all_images([params['ami']]) - img = rs[0] - r = img.run(user_data=s, key_name=params['keypair'], - security_groups=[params['group']], - max_count=params.get('num_instances', 1)) - print('AMI: %s - %s (Started)' % (params['ami'], img.location)) - print('Reservation %s contains the following instances:' % r.id) - for i in r.instances: - print('\t%s' % i.id) - if wait: - running = False - while not running: - time.sleep(30) - [i.update() for i in r.instances] - status = [i.state for i in r.instances] - print(status) - if status.count('running') == len(r.instances): - running = True - for i in r.instances: - print('Instance: %s' % i.ami_launch_index) - print('Public DNS Name: %s' % i.public_dns_name) - print('Private DNS Name: %s' % i.private_dns_name) - -if __name__ == "__main__": - main() diff --git a/awx/lib/site-packages/boto/pyami/scriptbase.py b/awx/lib/site-packages/boto/pyami/scriptbase.py deleted file mode 100644 index d99a2b46e0..0000000000 --- a/awx/lib/site-packages/boto/pyami/scriptbase.py +++ /dev/null @@ -1,43 +0,0 @@ -import os -import sys -from boto.utils import ShellCommand, get_ts -import boto -import boto.utils - -class ScriptBase(object): - - def __init__(self, config_file=None): - self.instance_id = boto.config.get('Instance', 'instance-id', 'default') - self.name = self.__class__.__name__ - self.ts = get_ts() - if config_file: - boto.config.read(config_file) - - def notify(self, subject, body=''): - boto.utils.notify(subject, body) - - def mkdir(self, path): - if not os.path.isdir(path): - try: - os.mkdir(path) - except: - boto.log.error('Error creating directory: %s' % path) - - def umount(self, path): - if os.path.ismount(path): - self.run('umount %s' % path) - - def run(self, command, notify=True, exit_on_error=False, cwd=None): - self.last_command = ShellCommand(command, cwd=cwd) - if self.last_command.status != 0: - boto.log.error('Error running command: "%s". Output: "%s"' % (command, self.last_command.output)) - if notify: - self.notify('Error encountered', - 'Error running the following command:\n\t%s\n\nCommand output:\n\t%s' % \ - (command, self.last_command.output)) - if exit_on_error: - sys.exit(-1) - return self.last_command.status - - def main(self): - pass diff --git a/awx/lib/site-packages/boto/pyami/startup.py b/awx/lib/site-packages/boto/pyami/startup.py deleted file mode 100644 index 4bd9dadd89..0000000000 --- a/awx/lib/site-packages/boto/pyami/startup.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -import sys -import boto -from boto.utils import find_class -from boto import config -from boto.pyami.scriptbase import ScriptBase - - -class Startup(ScriptBase): - - def run_scripts(self): - scripts = config.get('Pyami', 'scripts') - if scripts: - for script in scripts.split(','): - script = script.strip(" ") - try: - pos = script.rfind('.') - if pos > 0: - mod_name = script[0:pos] - cls_name = script[pos + 1:] - cls = find_class(mod_name, cls_name) - boto.log.info('Running Script: %s' % script) - s = cls() - s.main() - else: - boto.log.warning('Trouble parsing script: %s' % script) - except Exception as e: - boto.log.exception('Problem Running Script: %s. Startup process halting.' % script) - raise e - - def main(self): - self.run_scripts() - self.notify('Startup Completed for %s' % config.get('Instance', 'instance-id')) - -if __name__ == "__main__": - if not config.has_section('loggers'): - boto.set_file_logger('startup', '/var/log/boto.log') - sys.path.append(config.get('Pyami', 'working_dir')) - su = Startup() - su.main() diff --git a/awx/lib/site-packages/boto/rds/__init__.py b/awx/lib/site-packages/boto/rds/__init__.py deleted file mode 100644 index 8e8afa81d4..0000000000 --- a/awx/lib/site-packages/boto/rds/__init__.py +++ /dev/null @@ -1,1623 +0,0 @@ -# Copyright (c) 2009-2012 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import urllib -from boto.connection import AWSQueryConnection -from boto.rds.dbinstance import DBInstance -from boto.rds.dbsecuritygroup import DBSecurityGroup -from boto.rds.optiongroup import OptionGroup, OptionGroupOption -from boto.rds.parametergroup import ParameterGroup -from boto.rds.dbsnapshot import DBSnapshot -from boto.rds.event import Event -from boto.rds.regioninfo import RDSRegionInfo -from boto.rds.dbsubnetgroup import DBSubnetGroup -from boto.rds.vpcsecuritygroupmembership import VPCSecurityGroupMembership -from boto.regioninfo import get_regions -from boto.rds.logfile import LogFile, LogFileObject - - -def regions(): - """ - Get all available regions for the RDS service. - - :rtype: list - :return: A list of :class:`boto.rds.regioninfo.RDSRegionInfo` - """ - return get_regions( - 'rds', - region_cls=RDSRegionInfo, - connection_cls=RDSConnection - ) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.rds.RDSConnection`. - Any additional parameters after the region_name are passed on to - the connect method of the region object. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.rds.RDSConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None - -#boto.set_stream_logger('rds') - - -class RDSConnection(AWSQueryConnection): - - DefaultRegionName = 'us-east-1' - DefaultRegionEndpoint = 'rds.amazonaws.com' - APIVersion = '2013-05-15' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, - profile_name=None): - if not region: - region = RDSRegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - super(RDSConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - # DB Instance methods - - def get_all_dbinstances(self, instance_id=None, max_records=None, - marker=None): - """ - Retrieve all the DBInstances in your account. - - :type instance_id: str - :param instance_id: DB Instance identifier. If supplied, only - information this instance will be returned. - Otherwise, info about all DB Instances will - be returned. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of :class:`boto.rds.dbinstance.DBInstance` - """ - params = {} - if instance_id: - params['DBInstanceIdentifier'] = instance_id - if max_records: - params['MaxRecords'] = max_records - if marker: - params['Marker'] = marker - return self.get_list('DescribeDBInstances', params, - [('DBInstance', DBInstance)]) - - def create_dbinstance(self, - id, - allocated_storage, - instance_class, - master_username, - master_password, - port=3306, - engine='MySQL5.1', - db_name=None, - param_group=None, - security_groups=None, - availability_zone=None, - preferred_maintenance_window=None, - backup_retention_period=None, - preferred_backup_window=None, - multi_az=False, - engine_version=None, - auto_minor_version_upgrade=True, - character_set_name = None, - db_subnet_group_name = None, - license_model = None, - option_group_name = None, - iops=None, - vpc_security_groups=None, - ): - # API version: 2013-09-09 - # Parameter notes: - # ================= - # id should be db_instance_identifier according to API docs but has been left - # id for backwards compatibility - # - # security_groups should be db_security_groups according to API docs but has been left - # security_groups for backwards compatibility - # - # master_password should be master_user_password according to API docs but has been left - # master_password for backwards compatibility - # - # instance_class should be db_instance_class according to API docs but has been left - # instance_class for backwards compatibility - """ - Create a new DBInstance. - - :type id: str - :param id: Unique identifier for the new instance. - Must contain 1-63 alphanumeric characters. - First character must be a letter. - May not end with a hyphen or contain two consecutive hyphens - - :type allocated_storage: int - :param allocated_storage: Initially allocated storage size, in GBs. - Valid values are depending on the engine value. - - * MySQL = 5--3072 - * oracle-se1 = 10--3072 - * oracle-se = 10--3072 - * oracle-ee = 10--3072 - * sqlserver-ee = 200--1024 - * sqlserver-se = 200--1024 - * sqlserver-ex = 30--1024 - * sqlserver-web = 30--1024 - * postgres = 5--3072 - - :type instance_class: str - :param instance_class: The compute and memory capacity of - the DBInstance. Valid values are: - - * db.t1.micro - * db.m1.small - * db.m1.medium - * db.m1.large - * db.m1.xlarge - * db.m2.xlarge - * db.m2.2xlarge - * db.m2.4xlarge - - :type engine: str - :param engine: Name of database engine. Defaults to MySQL but can be; - - * MySQL - * oracle-se1 - * oracle-se - * oracle-ee - * sqlserver-ee - * sqlserver-se - * sqlserver-ex - * sqlserver-web - * postgres - - :type master_username: str - :param master_username: Name of master user for the DBInstance. - - * MySQL must be; - - 1--16 alphanumeric characters - - first character must be a letter - - cannot be a reserved MySQL word - - * Oracle must be: - - 1--30 alphanumeric characters - - first character must be a letter - - cannot be a reserved Oracle word - - * SQL Server must be: - - 1--128 alphanumeric characters - - first character must be a letter - - cannot be a reserver SQL Server word - - :type master_password: str - :param master_password: Password of master user for the DBInstance. - - * MySQL must be 8--41 alphanumeric characters - - * Oracle must be 8--30 alphanumeric characters - - * SQL Server must be 8--128 alphanumeric characters. - - :type port: int - :param port: Port number on which database accepts connections. - Valid values [1115-65535]. - - * MySQL defaults to 3306 - - * Oracle defaults to 1521 - - * SQL Server defaults to 1433 and _cannot_ be 1434, 3389, - 47001, 49152, and 49152 through 49156. - - * PostgreSQL defaults to 5432 - - :type db_name: str - :param db_name: * MySQL: - Name of a database to create when the DBInstance - is created. Default is to create no databases. - - Must contain 1--64 alphanumeric characters and cannot - be a reserved MySQL word. - - * Oracle: - The Oracle System ID (SID) of the created DB instances. - Default is ORCL. Cannot be longer than 8 characters. - - * SQL Server: - Not applicable and must be None. - - * PostgreSQL: - Name of a database to create when the DBInstance - is created. Default is to create no databases. - - Must contain 1--63 alphanumeric characters. Must - begin with a letter or an underscore. Subsequent - characters can be letters, underscores, or digits (0-9) - and cannot be a reserved PostgreSQL word. - - :type param_group: str or ParameterGroup object - :param param_group: Name of DBParameterGroup or ParameterGroup instance - to associate with this DBInstance. If no groups are - specified no parameter groups will be used. - - :type security_groups: list of str or list of DBSecurityGroup objects - :param security_groups: List of names of DBSecurityGroup to - authorize on this DBInstance. - - :type availability_zone: str - :param availability_zone: Name of the availability zone to place - DBInstance into. - - :type preferred_maintenance_window: str - :param preferred_maintenance_window: The weekly time range (in UTC) - during which maintenance can occur. - Default is Sun:05:00-Sun:09:00 - - :type backup_retention_period: int - :param backup_retention_period: The number of days for which automated - backups are retained. Setting this to - zero disables automated backups. - - :type preferred_backup_window: str - :param preferred_backup_window: The daily time range during which - automated backups are created (if - enabled). Must be in h24:mi-hh24:mi - format (UTC). - - :type multi_az: bool - :param multi_az: If True, specifies the DB Instance will be - deployed in multiple availability zones. - - For Microsoft SQL Server, must be set to false. You cannot set - the AvailabilityZone parameter if the MultiAZ parameter is - set to true. - - :type engine_version: str - :param engine_version: The version number of the database engine to use. - - * MySQL format example: 5.1.42 - - * Oracle format example: 11.2.0.2.v2 - - * SQL Server format example: 10.50.2789.0.v1 - - * PostgreSQL format example: 9.3 - - :type auto_minor_version_upgrade: bool - :param auto_minor_version_upgrade: Indicates that minor engine - upgrades will be applied - automatically to the Read Replica - during the maintenance window. - Default is True. - :type character_set_name: str - :param character_set_name: For supported engines, indicates that the DB Instance - should be associated with the specified CharacterSet. - - :type db_subnet_group_name: str - :param db_subnet_group_name: A DB Subnet Group to associate with this DB Instance. - If there is no DB Subnet Group, then it is a non-VPC DB - instance. - - :type license_model: str - :param license_model: License model information for this DB Instance. - - Valid values are; - - license-included - - bring-your-own-license - - general-public-license - - All license types are not supported on all engines. - - :type option_group_name: str - :param option_group_name: Indicates that the DB Instance should be associated - with the specified option group. - - :type iops: int - :param iops: The amount of IOPS (input/output operations per second) to Provisioned - for the DB Instance. Can be modified at a later date. - - Must scale linearly. For every 1000 IOPS provision, you must allocated - 100 GB of storage space. This scales up to 1 TB / 10 000 IOPS for MySQL - and Oracle. MSSQL is limited to 700 GB / 7 000 IOPS. - - If you specify a value, it must be at least 1000 IOPS and you must - allocate 100 GB of storage. - - :type vpc_security_groups: list of str or a VPCSecurityGroupMembership object - :param vpc_security_groups: List of VPC security group ids or a list of - VPCSecurityGroupMembership objects this DBInstance should be a member of - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The new db instance. - """ - # boto argument alignment with AWS API parameter names: - # ===================================================== - # arg => AWS parameter - # allocated_storage => AllocatedStorage - # auto_minor_version_update => AutoMinorVersionUpgrade - # availability_zone => AvailabilityZone - # backup_retention_period => BackupRetentionPeriod - # character_set_name => CharacterSetName - # db_instance_class => DBInstanceClass - # db_instance_identifier => DBInstanceIdentifier - # db_name => DBName - # db_parameter_group_name => DBParameterGroupName - # db_security_groups => DBSecurityGroups.member.N - # db_subnet_group_name => DBSubnetGroupName - # engine => Engine - # engine_version => EngineVersion - # license_model => LicenseModel - # master_username => MasterUsername - # master_user_password => MasterUserPassword - # multi_az => MultiAZ - # option_group_name => OptionGroupName - # port => Port - # preferred_backup_window => PreferredBackupWindow - # preferred_maintenance_window => PreferredMaintenanceWindow - # vpc_security_groups => VpcSecurityGroupIds.member.N - params = { - 'AllocatedStorage': allocated_storage, - 'AutoMinorVersionUpgrade': str(auto_minor_version_upgrade).lower() if auto_minor_version_upgrade else None, - 'AvailabilityZone': availability_zone, - 'BackupRetentionPeriod': backup_retention_period, - 'CharacterSetName': character_set_name, - 'DBInstanceClass': instance_class, - 'DBInstanceIdentifier': id, - 'DBName': db_name, - 'DBParameterGroupName': (param_group.name - if isinstance(param_group, ParameterGroup) - else param_group), - 'DBSubnetGroupName': db_subnet_group_name, - 'Engine': engine, - 'EngineVersion': engine_version, - 'Iops': iops, - 'LicenseModel': license_model, - 'MasterUsername': master_username, - 'MasterUserPassword': master_password, - 'MultiAZ': str(multi_az).lower() if multi_az else None, - 'OptionGroupName': option_group_name, - 'Port': port, - 'PreferredBackupWindow': preferred_backup_window, - 'PreferredMaintenanceWindow': preferred_maintenance_window, - } - if security_groups: - l = [] - for group in security_groups: - if isinstance(group, DBSecurityGroup): - l.append(group.name) - else: - l.append(group) - self.build_list_params(params, l, 'DBSecurityGroups.member') - - if vpc_security_groups: - l = [] - for vpc_grp in vpc_security_groups: - if isinstance(vpc_grp, VPCSecurityGroupMembership): - l.append(vpc_grp.vpc_group) - else: - l.append(vpc_grp) - self.build_list_params(params, l, 'VpcSecurityGroupIds.member') - - # Remove any params set to None - for k, v in params.items(): - if v is None: del(params[k]) - - return self.get_object('CreateDBInstance', params, DBInstance) - - def create_dbinstance_read_replica(self, id, source_id, - instance_class=None, - port=3306, - availability_zone=None, - auto_minor_version_upgrade=None): - """ - Create a new DBInstance Read Replica. - - :type id: str - :param id: Unique identifier for the new instance. - Must contain 1-63 alphanumeric characters. - First character must be a letter. - May not end with a hyphen or contain two consecutive hyphens - - :type source_id: str - :param source_id: Unique identifier for the DB Instance for which this - DB Instance will act as a Read Replica. - - :type instance_class: str - :param instance_class: The compute and memory capacity of the - DBInstance. Default is to inherit from - the source DB Instance. - - Valid values are: - - * db.m1.small - * db.m1.large - * db.m1.xlarge - * db.m2.xlarge - * db.m2.2xlarge - * db.m2.4xlarge - - :type port: int - :param port: Port number on which database accepts connections. - Default is to inherit from source DB Instance. - Valid values [1115-65535]. Defaults to 3306. - - :type availability_zone: str - :param availability_zone: Name of the availability zone to place - DBInstance into. - - :type auto_minor_version_upgrade: bool - :param auto_minor_version_upgrade: Indicates that minor engine - upgrades will be applied - automatically to the Read Replica - during the maintenance window. - Default is to inherit this value - from the source DB Instance. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The new db instance. - """ - params = {'DBInstanceIdentifier': id, - 'SourceDBInstanceIdentifier': source_id} - if instance_class: - params['DBInstanceClass'] = instance_class - if port: - params['Port'] = port - if availability_zone: - params['AvailabilityZone'] = availability_zone - if auto_minor_version_upgrade is not None: - if auto_minor_version_upgrade is True: - params['AutoMinorVersionUpgrade'] = 'true' - else: - params['AutoMinorVersionUpgrade'] = 'false' - - return self.get_object('CreateDBInstanceReadReplica', - params, DBInstance) - - - def promote_read_replica(self, id, - backup_retention_period=None, - preferred_backup_window=None): - """ - Promote a Read Replica to a standalone DB Instance. - - :type id: str - :param id: Unique identifier for the new instance. - Must contain 1-63 alphanumeric characters. - First character must be a letter. - May not end with a hyphen or contain two consecutive hyphens - - :type backup_retention_period: int - :param backup_retention_period: The number of days for which automated - backups are retained. Setting this to - zero disables automated backups. - - :type preferred_backup_window: str - :param preferred_backup_window: The daily time range during which - automated backups are created (if - enabled). Must be in h24:mi-hh24:mi - format (UTC). - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The new db instance. - """ - params = {'DBInstanceIdentifier': id} - if backup_retention_period is not None: - params['BackupRetentionPeriod'] = backup_retention_period - if preferred_backup_window: - params['PreferredBackupWindow'] = preferred_backup_window - - return self.get_object('PromoteReadReplica', params, DBInstance) - - - def modify_dbinstance(self, id, param_group=None, security_groups=None, - preferred_maintenance_window=None, - master_password=None, allocated_storage=None, - instance_class=None, - backup_retention_period=None, - preferred_backup_window=None, - multi_az=False, - apply_immediately=False, - iops=None, - vpc_security_groups=None, - new_instance_id=None, - ): - """ - Modify an existing DBInstance. - - :type id: str - :param id: Unique identifier for the new instance. - - :type param_group: str or ParameterGroup object - :param param_group: Name of DBParameterGroup or ParameterGroup instance - to associate with this DBInstance. If no groups are - specified no parameter groups will be used. - - :type security_groups: list of str or list of DBSecurityGroup objects - :param security_groups: List of names of DBSecurityGroup to authorize on - this DBInstance. - - :type preferred_maintenance_window: str - :param preferred_maintenance_window: The weekly time range (in UTC) - during which maintenance can - occur. - Default is Sun:05:00-Sun:09:00 - - :type master_password: str - :param master_password: Password of master user for the DBInstance. - Must be 4-15 alphanumeric characters. - - :type allocated_storage: int - :param allocated_storage: The new allocated storage size, in GBs. - Valid values are [5-1024] - - :type instance_class: str - :param instance_class: The compute and memory capacity of the - DBInstance. Changes will be applied at - next maintenance window unless - apply_immediately is True. - - Valid values are: - - * db.m1.small - * db.m1.large - * db.m1.xlarge - * db.m2.xlarge - * db.m2.2xlarge - * db.m2.4xlarge - - :type apply_immediately: bool - :param apply_immediately: If true, the modifications will be applied - as soon as possible rather than waiting for - the next preferred maintenance window. - - :type backup_retention_period: int - :param backup_retention_period: The number of days for which automated - backups are retained. Setting this to - zero disables automated backups. - - :type preferred_backup_window: str - :param preferred_backup_window: The daily time range during which - automated backups are created (if - enabled). Must be in h24:mi-hh24:mi - format (UTC). - - :type multi_az: bool - :param multi_az: If True, specifies the DB Instance will be - deployed in multiple availability zones. - - :type iops: int - :param iops: The amount of IOPS (input/output operations per second) to Provisioned - for the DB Instance. Can be modified at a later date. - - Must scale linearly. For every 1000 IOPS provision, you must allocated - 100 GB of storage space. This scales up to 1 TB / 10 000 IOPS for MySQL - and Oracle. MSSQL is limited to 700 GB / 7 000 IOPS. - - If you specify a value, it must be at least 1000 IOPS and you must - allocate 100 GB of storage. - - :type vpc_security_groups: list of str or a VPCSecurityGroupMembership object - :param vpc_security_groups: List of VPC security group ids or a - VPCSecurityGroupMembership object this DBInstance should be a member of - - :type new_instance_id: str - :param new_instance_id: New name to rename the DBInstance to. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The modified db instance. - """ - params = {'DBInstanceIdentifier': id} - if param_group: - params['DBParameterGroupName'] = (param_group.name - if isinstance(param_group, ParameterGroup) - else param_group) - if security_groups: - l = [] - for group in security_groups: - if isinstance(group, DBSecurityGroup): - l.append(group.name) - else: - l.append(group) - self.build_list_params(params, l, 'DBSecurityGroups.member') - if vpc_security_groups: - l = [] - for vpc_grp in vpc_security_groups: - if isinstance(vpc_grp, VPCSecurityGroupMembership): - l.append(vpc_grp.vpc_group) - else: - l.append(vpc_grp) - self.build_list_params(params, l, 'VpcSecurityGroupIds.member') - if preferred_maintenance_window: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if master_password: - params['MasterUserPassword'] = master_password - if allocated_storage: - params['AllocatedStorage'] = allocated_storage - if instance_class: - params['DBInstanceClass'] = instance_class - if backup_retention_period is not None: - params['BackupRetentionPeriod'] = backup_retention_period - if preferred_backup_window: - params['PreferredBackupWindow'] = preferred_backup_window - if multi_az: - params['MultiAZ'] = 'true' - if apply_immediately: - params['ApplyImmediately'] = 'true' - if iops: - params['Iops'] = iops - if new_instance_id: - params['NewDBInstanceIdentifier'] = new_instance_id - - return self.get_object('ModifyDBInstance', params, DBInstance) - - def delete_dbinstance(self, id, skip_final_snapshot=False, - final_snapshot_id=''): - """ - Delete an existing DBInstance. - - :type id: str - :param id: Unique identifier for the new instance. - - :type skip_final_snapshot: bool - :param skip_final_snapshot: This parameter determines whether a final - db snapshot is created before the instance - is deleted. If True, no snapshot - is created. If False, a snapshot - is created before deleting the instance. - - :type final_snapshot_id: str - :param final_snapshot_id: If a final snapshot is requested, this - is the identifier used for that snapshot. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The deleted db instance. - """ - params = {'DBInstanceIdentifier': id} - if skip_final_snapshot: - params['SkipFinalSnapshot'] = 'true' - else: - params['SkipFinalSnapshot'] = 'false' - params['FinalDBSnapshotIdentifier'] = final_snapshot_id - return self.get_object('DeleteDBInstance', params, DBInstance) - - def reboot_dbinstance(self, id): - """ - Reboot DBInstance. - - :type id: str - :param id: Unique identifier of the instance. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The rebooting db instance. - """ - params = {'DBInstanceIdentifier': id} - return self.get_object('RebootDBInstance', params, DBInstance) - - # DBParameterGroup methods - - def get_all_dbparameter_groups(self, groupname=None, max_records=None, - marker=None): - """ - Get all parameter groups associated with your account in a region. - - :type groupname: str - :param groupname: The name of the DBParameter group to retrieve. - If not provided, all DBParameter groups will be returned. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of :class:`boto.ec2.parametergroup.ParameterGroup` - """ - params = {} - if groupname: - params['DBParameterGroupName'] = groupname - if max_records: - params['MaxRecords'] = max_records - if marker: - params['Marker'] = marker - return self.get_list('DescribeDBParameterGroups', params, - [('DBParameterGroup', ParameterGroup)]) - - def get_all_dbparameters(self, groupname, source=None, - max_records=None, marker=None): - """ - Get all parameters associated with a ParameterGroup - - :type groupname: str - :param groupname: The name of the DBParameter group to retrieve. - - :type source: str - :param source: Specifies which parameters to return. - If not specified, all parameters will be returned. - Valid values are: user|system|engine-default - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: :class:`boto.ec2.parametergroup.ParameterGroup` - :return: The ParameterGroup - """ - params = {'DBParameterGroupName': groupname} - if source: - params['Source'] = source - if max_records: - params['MaxRecords'] = max_records - if marker: - params['Marker'] = marker - pg = self.get_object('DescribeDBParameters', params, ParameterGroup) - pg.name = groupname - return pg - - def create_parameter_group(self, name, engine='MySQL5.1', description=''): - """ - Create a new dbparameter group for your account. - - :type name: string - :param name: The name of the new dbparameter group - - :type engine: str - :param engine: Name of database engine. - - :type description: string - :param description: The description of the new dbparameter group - - :rtype: :class:`boto.rds.parametergroup.ParameterGroup` - :return: The newly created ParameterGroup - """ - params = {'DBParameterGroupName': name, - 'DBParameterGroupFamily': engine, - 'Description': description} - return self.get_object('CreateDBParameterGroup', params, ParameterGroup) - - def modify_parameter_group(self, name, parameters=None): - """ - Modify a ParameterGroup for your account. - - :type name: string - :param name: The name of the new ParameterGroup - - :type parameters: list of :class:`boto.rds.parametergroup.Parameter` - :param parameters: The new parameters - - :rtype: :class:`boto.rds.parametergroup.ParameterGroup` - :return: The newly created ParameterGroup - """ - params = {'DBParameterGroupName': name} - for i in range(0, len(parameters)): - parameter = parameters[i] - parameter.merge(params, i+1) - return self.get_list('ModifyDBParameterGroup', params, - ParameterGroup, verb='POST') - - def reset_parameter_group(self, name, reset_all_params=False, - parameters=None): - """ - Resets some or all of the parameters of a ParameterGroup to the - default value - - :type key_name: string - :param key_name: The name of the ParameterGroup to reset - - :type parameters: list of :class:`boto.rds.parametergroup.Parameter` - :param parameters: The parameters to reset. If not supplied, - all parameters will be reset. - """ - params = {'DBParameterGroupName': name} - if reset_all_params: - params['ResetAllParameters'] = 'true' - else: - params['ResetAllParameters'] = 'false' - for i in range(0, len(parameters)): - parameter = parameters[i] - parameter.merge(params, i+1) - return self.get_status('ResetDBParameterGroup', params) - - def delete_parameter_group(self, name): - """ - Delete a ParameterGroup from your account. - - :type key_name: string - :param key_name: The name of the ParameterGroup to delete - """ - params = {'DBParameterGroupName': name} - return self.get_status('DeleteDBParameterGroup', params) - - # DBSecurityGroup methods - - def get_all_dbsecurity_groups(self, groupname=None, max_records=None, - marker=None): - """ - Get all security groups associated with your account in a region. - - :type groupnames: list - :param groupnames: A list of the names of security groups to retrieve. - If not provided, all security groups will - be returned. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of :class:`boto.rds.dbsecuritygroup.DBSecurityGroup` - """ - params = {} - if groupname: - params['DBSecurityGroupName'] = groupname - if max_records: - params['MaxRecords'] = max_records - if marker: - params['Marker'] = marker - return self.get_list('DescribeDBSecurityGroups', params, - [('DBSecurityGroup', DBSecurityGroup)]) - - def create_dbsecurity_group(self, name, description=None): - """ - Create a new security group for your account. - This will create the security group within the region you - are currently connected to. - - :type name: string - :param name: The name of the new security group - - :type description: string - :param description: The description of the new security group - - :rtype: :class:`boto.rds.dbsecuritygroup.DBSecurityGroup` - :return: The newly created DBSecurityGroup - """ - params = {'DBSecurityGroupName': name} - if description: - params['DBSecurityGroupDescription'] = description - group = self.get_object('CreateDBSecurityGroup', params, - DBSecurityGroup) - group.name = name - group.description = description - return group - - def delete_dbsecurity_group(self, name): - """ - Delete a DBSecurityGroup from your account. - - :type key_name: string - :param key_name: The name of the DBSecurityGroup to delete - """ - params = {'DBSecurityGroupName': name} - return self.get_status('DeleteDBSecurityGroup', params) - - def authorize_dbsecurity_group(self, group_name, cidr_ip=None, - ec2_security_group_name=None, - ec2_security_group_owner_id=None): - """ - Add a new rule to an existing security group. - You need to pass in either src_security_group_name and - src_security_group_owner_id OR a CIDR block but not both. - - :type group_name: string - :param group_name: The name of the security group you are adding - the rule to. - - :type ec2_security_group_name: string - :param ec2_security_group_name: The name of the EC2 security group - you are granting access to. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: The ID of the owner of the EC2 - security group you are granting - access to. - - :type cidr_ip: string - :param cidr_ip: The CIDR block you are providing access to. - See http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing - - :rtype: bool - :return: True if successful. - """ - params = {'DBSecurityGroupName': group_name} - if ec2_security_group_name: - params['EC2SecurityGroupName'] = ec2_security_group_name - if ec2_security_group_owner_id: - params['EC2SecurityGroupOwnerId'] = ec2_security_group_owner_id - if cidr_ip: - params['CIDRIP'] = urllib.quote(cidr_ip) - return self.get_object('AuthorizeDBSecurityGroupIngress', params, - DBSecurityGroup) - - def revoke_dbsecurity_group(self, group_name, ec2_security_group_name=None, - ec2_security_group_owner_id=None, cidr_ip=None): - """ - Remove an existing rule from an existing security group. - You need to pass in either ec2_security_group_name and - ec2_security_group_owner_id OR a CIDR block. - - :type group_name: string - :param group_name: The name of the security group you are removing - the rule from. - - :type ec2_security_group_name: string - :param ec2_security_group_name: The name of the EC2 security group - from which you are removing access. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: The ID of the owner of the EC2 - security from which you are - removing access. - - :type cidr_ip: string - :param cidr_ip: The CIDR block from which you are removing access. - See http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing - - :rtype: bool - :return: True if successful. - """ - params = {'DBSecurityGroupName': group_name} - if ec2_security_group_name: - params['EC2SecurityGroupName'] = ec2_security_group_name - if ec2_security_group_owner_id: - params['EC2SecurityGroupOwnerId'] = ec2_security_group_owner_id - if cidr_ip: - params['CIDRIP'] = cidr_ip - return self.get_object('RevokeDBSecurityGroupIngress', params, - DBSecurityGroup) - - # For backwards compatibility. This method was improperly named - # in previous versions. I have renamed it to match the others. - revoke_security_group = revoke_dbsecurity_group - - # DBSnapshot methods - - def get_all_dbsnapshots(self, snapshot_id=None, instance_id=None, - max_records=None, marker=None): - """ - Get information about DB Snapshots. - - :type snapshot_id: str - :param snapshot_id: The unique identifier of an RDS snapshot. - If not provided, all RDS snapshots will be returned. - - :type instance_id: str - :param instance_id: The identifier of a DBInstance. If provided, - only the DBSnapshots related to that instance will - be returned. - If not provided, all RDS snapshots will be returned. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of :class:`boto.rds.dbsnapshot.DBSnapshot` - """ - params = {} - if snapshot_id: - params['DBSnapshotIdentifier'] = snapshot_id - if instance_id: - params['DBInstanceIdentifier'] = instance_id - if max_records: - params['MaxRecords'] = max_records - if marker: - params['Marker'] = marker - return self.get_list('DescribeDBSnapshots', params, - [('DBSnapshot', DBSnapshot)]) - - def get_all_logs(self, dbinstance_id, max_records=None, marker=None, file_size=None, filename_contains=None, file_last_written=None): - """ - Get all log files - - :type instance_id: str - :param instance_id: The identifier of a DBInstance. - - :type max_records: int - :param max_records: Number of log file names to return. - - :type marker: str - :param marker: The marker provided by a previous request. - - :file_size: int - :param file_size: Filter results to files large than this size in bytes. - - :filename_contains: str - :param filename_contains: Filter results to files with filename containing this string - - :file_last_written: int - :param file_last_written: Filter results to files written after this time (POSIX timestamp) - - :rtype: list - :return: A list of :class:`boto.rds.logfile.LogFile` - """ - params = {'DBInstanceIdentifier': dbinstance_id} - - if file_size: - params['FileSize'] = file_size - - if filename_contains: - params['FilenameContains'] = filename_contains - - if file_last_written: - params['FileLastWritten'] = file_last_written - - if marker: - params['Marker'] = marker - - if max_records: - params['MaxRecords'] = max_records - - return self.get_list('DescribeDBLogFiles', params, - [('DescribeDBLogFilesDetails',LogFile)]) - - def get_log_file(self, dbinstance_id, log_file_name, marker=None, number_of_lines=None, max_records=None): - """ - Download a log file from RDS - - :type instance_id: str - :param instance_id: The identifier of a DBInstance. - - :type log_file_name: str - :param log_file_name: The name of the log file to retrieve - - :type marker: str - :param marker: A marker returned from a previous call to this method, or 0 to indicate the start of file. If - no marker is specified, this will fetch log lines from the end of file instead. - - :type number_of_lines: int - :param marker: The maximium number of lines to be returned. - """ - - params = { - 'DBInstanceIdentifier': dbinstance_id, - 'LogFileName': log_file_name, - } - - if marker: - params['Marker'] = marker - - if number_of_lines: - params['NumberOfLines'] = number_of_lines - - if max_records: - params['MaxRecords'] = max_records - - logfile = self.get_object('DownloadDBLogFilePortion', params, LogFileObject) - - if logfile: - logfile.log_filename = log_file_name - logfile.dbinstance_id = dbinstance_id - - return logfile - - def create_dbsnapshot(self, snapshot_id, dbinstance_id): - """ - Create a new DB snapshot. - - :type snapshot_id: string - :param snapshot_id: The identifier for the DBSnapshot - - :type dbinstance_id: string - :param dbinstance_id: The source identifier for the RDS instance from - which the snapshot is created. - - :rtype: :class:`boto.rds.dbsnapshot.DBSnapshot` - :return: The newly created DBSnapshot - """ - params = {'DBSnapshotIdentifier': snapshot_id, - 'DBInstanceIdentifier': dbinstance_id} - return self.get_object('CreateDBSnapshot', params, DBSnapshot) - - def copy_dbsnapshot(self, source_snapshot_id, target_snapshot_id): - """ - Copies the specified DBSnapshot. - - :type source_snapshot_id: string - :param source_snapshot_id: The identifier for the source DB snapshot. - - :type target_snapshot_id: string - :param target_snapshot_id: The identifier for the copied snapshot. - - :rtype: :class:`boto.rds.dbsnapshot.DBSnapshot` - :return: The newly created DBSnapshot. - """ - params = {'SourceDBSnapshotIdentifier': source_snapshot_id, - 'TargetDBSnapshotIdentifier': target_snapshot_id} - return self.get_object('CopyDBSnapshot', params, DBSnapshot) - - def delete_dbsnapshot(self, identifier): - """ - Delete a DBSnapshot - - :type identifier: string - :param identifier: The identifier of the DBSnapshot to delete - """ - params = {'DBSnapshotIdentifier': identifier} - return self.get_object('DeleteDBSnapshot', params, DBSnapshot) - - def restore_dbinstance_from_dbsnapshot(self, identifier, instance_id, - instance_class, port=None, - availability_zone=None, - multi_az=None, - auto_minor_version_upgrade=None, - db_subnet_group_name=None): - """ - Create a new DBInstance from a DB snapshot. - - :type identifier: string - :param identifier: The identifier for the DBSnapshot - - :type instance_id: string - :param instance_id: The source identifier for the RDS instance from - which the snapshot is created. - - :type instance_class: str - :param instance_class: The compute and memory capacity of the - DBInstance. Valid values are: - db.m1.small | db.m1.large | db.m1.xlarge | - db.m2.2xlarge | db.m2.4xlarge - - :type port: int - :param port: Port number on which database accepts connections. - Valid values [1115-65535]. Defaults to 3306. - - :type availability_zone: str - :param availability_zone: Name of the availability zone to place - DBInstance into. - - :type multi_az: bool - :param multi_az: If True, specifies the DB Instance will be - deployed in multiple availability zones. - Default is the API default. - - :type auto_minor_version_upgrade: bool - :param auto_minor_version_upgrade: Indicates that minor engine - upgrades will be applied - automatically to the Read Replica - during the maintenance window. - Default is the API default. - - :type db_subnet_group_name: str - :param db_subnet_group_name: A DB Subnet Group to associate with this DB Instance. - If there is no DB Subnet Group, then it is a non-VPC DB - instance. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The newly created DBInstance - """ - params = {'DBSnapshotIdentifier': identifier, - 'DBInstanceIdentifier': instance_id, - 'DBInstanceClass': instance_class} - if port: - params['Port'] = port - if availability_zone: - params['AvailabilityZone'] = availability_zone - if multi_az is not None: - params['MultiAZ'] = str(multi_az).lower() - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str(auto_minor_version_upgrade).lower() - if db_subnet_group_name is not None: - params['DBSubnetGroupName'] = db_subnet_group_name - return self.get_object('RestoreDBInstanceFromDBSnapshot', - params, DBInstance) - - def restore_dbinstance_from_point_in_time(self, source_instance_id, - target_instance_id, - use_latest=False, - restore_time=None, - dbinstance_class=None, - port=None, - availability_zone=None, - db_subnet_group_name=None): - - """ - Create a new DBInstance from a point in time. - - :type source_instance_id: string - :param source_instance_id: The identifier for the source DBInstance. - - :type target_instance_id: string - :param target_instance_id: The identifier of the new DBInstance. - - :type use_latest: bool - :param use_latest: If True, the latest snapshot availabile will - be used. - - :type restore_time: datetime - :param restore_time: The date and time to restore from. Only - used if use_latest is False. - - :type instance_class: str - :param instance_class: The compute and memory capacity of the - DBInstance. Valid values are: - db.m1.small | db.m1.large | db.m1.xlarge | - db.m2.2xlarge | db.m2.4xlarge - - :type port: int - :param port: Port number on which database accepts connections. - Valid values [1115-65535]. Defaults to 3306. - - :type availability_zone: str - :param availability_zone: Name of the availability zone to place - DBInstance into. - - :type db_subnet_group_name: str - :param db_subnet_group_name: A DB Subnet Group to associate with this DB Instance. - If there is no DB Subnet Group, then it is a non-VPC DB - instance. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The newly created DBInstance - """ - params = {'SourceDBInstanceIdentifier': source_instance_id, - 'TargetDBInstanceIdentifier': target_instance_id} - if use_latest: - params['UseLatestRestorableTime'] = 'true' - elif restore_time: - params['RestoreTime'] = restore_time.isoformat() - if dbinstance_class: - params['DBInstanceClass'] = dbinstance_class - if port: - params['Port'] = port - if availability_zone: - params['AvailabilityZone'] = availability_zone - if db_subnet_group_name is not None: - params['DBSubnetGroupName'] = db_subnet_group_name - return self.get_object('RestoreDBInstanceToPointInTime', - params, DBInstance) - - # Events - - def get_all_events(self, source_identifier=None, source_type=None, - start_time=None, end_time=None, - max_records=None, marker=None): - """ - Get information about events related to your DBInstances, - DBSecurityGroups and DBParameterGroups. - - :type source_identifier: str - :param source_identifier: If supplied, the events returned will be - limited to those that apply to the identified - source. The value of this parameter depends - on the value of source_type. If neither - parameter is specified, all events in the time - span will be returned. - - :type source_type: str - :param source_type: Specifies how the source_identifier should - be interpreted. Valid values are: - b-instance | db-security-group | - db-parameter-group | db-snapshot - - :type start_time: datetime - :param start_time: The beginning of the time interval for events. - If not supplied, all available events will - be returned. - - :type end_time: datetime - :param end_time: The ending of the time interval for events. - If not supplied, all available events will - be returned. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of class:`boto.rds.event.Event` - """ - params = {} - if source_identifier and source_type: - params['SourceIdentifier'] = source_identifier - params['SourceType'] = source_type - if start_time: - params['StartTime'] = start_time.isoformat() - if end_time: - params['EndTime'] = end_time.isoformat() - if max_records: - params['MaxRecords'] = max_records - if marker: - params['Marker'] = marker - return self.get_list('DescribeEvents', params, [('Event', Event)]) - - def create_db_subnet_group(self, name, desc, subnet_ids): - """ - Create a new Database Subnet Group. - - :type name: string - :param name: The identifier for the db_subnet_group - - :type desc: string - :param desc: A description of the db_subnet_group - - :type subnet_ids: list - :param subnets: A list of the subnet identifiers to include in the - db_subnet_group - - :rtype: :class:`boto.rds.dbsubnetgroup.DBSubnetGroup - :return: the created db_subnet_group - """ - - params = {'DBSubnetGroupName': name, - 'DBSubnetGroupDescription': desc} - self.build_list_params(params, subnet_ids, 'SubnetIds.member') - - return self.get_object('CreateDBSubnetGroup', params, DBSubnetGroup) - - def delete_db_subnet_group(self, name): - """ - Delete a Database Subnet Group. - - :type name: string - :param name: The identifier of the db_subnet_group to delete - - :rtype: :class:`boto.rds.dbsubnetgroup.DBSubnetGroup` - :return: The deleted db_subnet_group. - """ - - params = {'DBSubnetGroupName': name} - - return self.get_object('DeleteDBSubnetGroup', params, DBSubnetGroup) - - - def get_all_db_subnet_groups(self, name=None, max_records=None, marker=None): - """ - Retrieve all the DBSubnetGroups in your account. - - :type name: str - :param name: DBSubnetGroup name If supplied, only information about - this DBSubnetGroup will be returned. Otherwise, info - about all DBSubnetGroups will be returned. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a Token will be - returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of :class:`boto.rds.dbsubnetgroup.DBSubnetGroup` - """ - params = dict() - if name is not None: - params['DBSubnetGroupName'] = name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - - return self.get_list('DescribeDBSubnetGroups', params, [('DBSubnetGroup',DBSubnetGroup)]) - - def modify_db_subnet_group(self, name, description=None, subnet_ids=None): - """ - Modify a parameter group for your account. - - :type name: string - :param name: The name of the new parameter group - - :type parameters: list of :class:`boto.rds.parametergroup.Parameter` - :param parameters: The new parameters - - :rtype: :class:`boto.rds.parametergroup.ParameterGroup` - :return: The newly created ParameterGroup - """ - params = {'DBSubnetGroupName': name} - if description is not None: - params['DBSubnetGroupDescription'] = description - if subnet_ids is not None: - self.build_list_params(params, subnet_ids, 'SubnetIds.member') - - return self.get_object('ModifyDBSubnetGroup', params, DBSubnetGroup) - - def create_option_group(self, name, engine_name, major_engine_version, - description=None): - """ - Create a new option group for your account. - This will create the option group within the region you - are currently connected to. - - :type name: string - :param name: The name of the new option group - - :type engine_name: string - :param engine_name: Specifies the name of the engine that this option - group should be associated with. - - :type major_engine_version: string - :param major_engine_version: Specifies the major version of the engine - that this option group should be - associated with. - - :type description: string - :param description: The description of the new option group - - :rtype: :class:`boto.rds.optiongroup.OptionGroup` - :return: The newly created OptionGroup - """ - params = { - 'OptionGroupName': name, - 'EngineName': engine_name, - 'MajorEngineVersion': major_engine_version, - 'OptionGroupDescription': description, - } - group = self.get_object('CreateOptionGroup', params, OptionGroup) - group.name = name - group.engine_name = engine_name - group.major_engine_version = major_engine_version - group.description = description - return group - - def delete_option_group(self, name): - """ - Delete an OptionGroup from your account. - - :type key_name: string - :param key_name: The name of the OptionGroup to delete - """ - params = {'OptionGroupName': name} - return self.get_status('DeleteOptionGroup', params) - - def describe_option_groups(self, name=None, engine_name=None, - major_engine_version=None, max_records=100, - marker=None): - """ - Describes the available option groups. - - :type name: str - :param name: The name of the option group to describe. Cannot be - supplied together with engine_name or major_engine_version. - - :type engine_name: str - :param engine_name: Filters the list of option groups to only include - groups associated with a specific database engine. - - :type major_engine_version: datetime - :param major_engine_version: Filters the list of option groups to only - include groups associated with a specific - database engine version. If specified, then - engine_name must also be specified. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of class:`boto.rds.optiongroup.OptionGroup` - """ - params = {} - if name: - params['OptionGroupName'] = name - elif engine_name and major_engine_version: - params['EngineName'] = engine_name - params['MajorEngineVersion'] = major_engine_version - if max_records: - params['MaxRecords'] = int(max_records) - if marker: - params['Marker'] = marker - return self.get_list('DescribeOptionGroups', params, [ - ('OptionGroup', OptionGroup) - ]) - - def describe_option_group_options(self, engine_name=None, - major_engine_version=None, max_records=100, - marker=None): - """ - Describes the available option group options. - - :type engine_name: str - :param engine_name: Filters the list of option groups to only include - groups associated with a specific database engine. - - :type major_engine_version: datetime - :param major_engine_version: Filters the list of option groups to only - include groups associated with a specific - database engine version. If specified, then - engine_name must also be specified. - - :type max_records: int - :param max_records: The maximum number of records to be returned. - If more results are available, a MoreToken will - be returned in the response that can be used to - retrieve additional records. Default is 100. - - :type marker: str - :param marker: The marker provided by a previous request. - - :rtype: list - :return: A list of class:`boto.rds.optiongroup.Option` - """ - params = {} - if engine_name and major_engine_version: - params['EngineName'] = engine_name - params['MajorEngineVersion'] = major_engine_version - if max_records: - params['MaxRecords'] = int(max_records) - if marker: - params['Marker'] = marker - return self.get_list('DescribeOptionGroupOptions', params, [ - ('OptionGroupOptions', OptionGroupOption) - ]) diff --git a/awx/lib/site-packages/boto/rds/dbinstance.py b/awx/lib/site-packages/boto/rds/dbinstance.py deleted file mode 100644 index 6a6385103d..0000000000 --- a/awx/lib/site-packages/boto/rds/dbinstance.py +++ /dev/null @@ -1,416 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.rds.dbsecuritygroup import DBSecurityGroup -from boto.rds.parametergroup import ParameterGroup -from boto.rds.statusinfo import StatusInfo -from boto.rds.dbsubnetgroup import DBSubnetGroup -from boto.rds.vpcsecuritygroupmembership import VPCSecurityGroupMembership -from boto.resultset import ResultSet - - -class DBInstance(object): - """ - Represents a RDS DBInstance - - Properties reference available from the AWS documentation at - http://goo.gl/sC2Kn - - :ivar connection: connection - :ivar id: The name and identifier of the DBInstance - :ivar create_time: The date and time of creation - :ivar engine: The database engine being used - :ivar status: The status of the database in a string. e.g. "available" - :ivar allocated_storage: The size of the disk in gigabytes (int). - :ivar auto_minor_version_upgrade: Indicates that minor version patches - are applied automatically. - :ivar endpoint: A tuple that describes the hostname and port of - the instance. This is only available when the database is - in status "available". - :ivar instance_class: Contains the name of the compute and memory - capacity class of the DB Instance. - :ivar master_username: The username that is set as master username - at creation time. - :ivar parameter_groups: Provides the list of DB Parameter Groups - applied to this DB Instance. - :ivar security_groups: Provides List of DB Security Group elements - containing only DBSecurityGroup.Name and DBSecurityGroup.Status - subelements. - :ivar availability_zone: Specifies the name of the Availability Zone - the DB Instance is located in. - :ivar backup_retention_period: Specifies the number of days for - which automatic DB Snapshots are retained. - :ivar preferred_backup_window: Specifies the daily time range during - which automated backups are created if automated backups are - enabled, as determined by the backup_retention_period. - :ivar preferred_maintenance_window: Specifies the weekly time - range (in UTC) during which system maintenance can occur. (string) - :ivar latest_restorable_time: Specifies the latest time to which - a database can be restored with point-in-time restore. (string) - :ivar multi_az: Boolean that specifies if the DB Instance is a - Multi-AZ deployment. - :ivar iops: The current number of provisioned IOPS for the DB Instance. - Can be None if this is a standard instance. - :ivar vpc_security_groups: List of VPC Security Group Membership elements - containing only VpcSecurityGroupMembership.VpcSecurityGroupId and - VpcSecurityGroupMembership.Status subelements. - :ivar pending_modified_values: Specifies that changes to the - DB Instance are pending. This element is only included when changes - are pending. Specific changes are identified by subelements. - :ivar read_replica_dbinstance_identifiers: List of read replicas - associated with this DB instance. - :ivar status_infos: The status of a Read Replica. If the instance is not a - for a read replica, this will be blank. - :ivar character_set_name: If present, specifies the name of the character - set that this instance is associated with. - :ivar subnet_group: Specifies information on the subnet group associated - with the DB instance, including the name, description, and subnets - in the subnet group. - :ivar engine_version: Indicates the database engine version. - :ivar license_model: License model information for this DB instance. - """ - - def __init__(self, connection=None, id=None): - self.connection = connection - self.id = id - self.create_time = None - self.engine = None - self.status = None - self.allocated_storage = None - self.auto_minor_version_upgrade = None - self.endpoint = None - self.instance_class = None - self.master_username = None - self.parameter_groups = [] - self.security_groups = [] - self.read_replica_dbinstance_identifiers = [] - self.availability_zone = None - self.backup_retention_period = None - self.preferred_backup_window = None - self.preferred_maintenance_window = None - self.latest_restorable_time = None - self.multi_az = False - self.iops = None - self.vpc_security_groups = None - self.pending_modified_values = None - self._in_endpoint = False - self._port = None - self._address = None - self.status_infos = None - self.character_set_name = None - self.subnet_group = None - self.engine_version = None - self.license_model = None - - def __repr__(self): - return 'DBInstance:%s' % self.id - - def startElement(self, name, attrs, connection): - if name == 'Endpoint': - self._in_endpoint = True - elif name == 'DBParameterGroups': - self.parameter_groups = ResultSet([('DBParameterGroup', - ParameterGroup)]) - return self.parameter_groups - elif name == 'DBSecurityGroups': - self.security_groups = ResultSet([('DBSecurityGroup', - DBSecurityGroup)]) - return self.security_groups - elif name == 'VpcSecurityGroups': - self.vpc_security_groups = ResultSet([('VpcSecurityGroupMembership', - VPCSecurityGroupMembership)]) - return self.vpc_security_groups - elif name == 'PendingModifiedValues': - self.pending_modified_values = PendingModifiedValues() - return self.pending_modified_values - elif name == 'ReadReplicaDBInstanceIdentifiers': - self.read_replica_dbinstance_identifiers = \ - ReadReplicaDBInstanceIdentifiers() - return self.read_replica_dbinstance_identifiers - elif name == 'StatusInfos': - self.status_infos = ResultSet([ - ('DBInstanceStatusInfo', StatusInfo) - ]) - return self.status_infos - elif name == 'DBSubnetGroup': - self.subnet_group = DBSubnetGroup() - return self.subnet_group - return None - - def endElement(self, name, value, connection): - if name == 'DBInstanceIdentifier': - self.id = value - elif name == 'DBInstanceStatus': - self.status = value - elif name == 'InstanceCreateTime': - self.create_time = value - elif name == 'Engine': - self.engine = value - elif name == 'DBInstanceStatus': - self.status = value - elif name == 'AllocatedStorage': - self.allocated_storage = int(value) - elif name == 'AutoMinorVersionUpgrade': - self.auto_minor_version_upgrade = value.lower() == 'true' - elif name == 'DBInstanceClass': - self.instance_class = value - elif name == 'MasterUsername': - self.master_username = value - elif name == 'Port': - if self._in_endpoint: - self._port = int(value) - elif name == 'Address': - if self._in_endpoint: - self._address = value - elif name == 'Endpoint': - self.endpoint = (self._address, self._port) - self._in_endpoint = False - elif name == 'AvailabilityZone': - self.availability_zone = value - elif name == 'BackupRetentionPeriod': - self.backup_retention_period = int(value) - elif name == 'LatestRestorableTime': - self.latest_restorable_time = value - elif name == 'PreferredMaintenanceWindow': - self.preferred_maintenance_window = value - elif name == 'PreferredBackupWindow': - self.preferred_backup_window = value - elif name == 'MultiAZ': - if value.lower() == 'true': - self.multi_az = True - elif name == 'Iops': - self.iops = int(value) - elif name == 'CharacterSetName': - self.character_set_name = value - elif name == 'EngineVersion': - self.engine_version = value - elif name == 'LicenseModel': - self.license_model = value - else: - setattr(self, name, value) - - @property - def security_group(self): - """ - Provide backward compatibility for previous security_group - attribute. - """ - if len(self.security_groups) > 0: - return self.security_groups[-1] - else: - return None - - @property - def parameter_group(self): - """ - Provide backward compatibility for previous parameter_group - attribute. - """ - if len(self.parameter_groups) > 0: - return self.parameter_groups[-1] - else: - return None - - def snapshot(self, snapshot_id): - """ - Create a new DB snapshot of this DBInstance. - - :type identifier: string - :param identifier: The identifier for the DBSnapshot - - :rtype: :class:`boto.rds.dbsnapshot.DBSnapshot` - :return: The newly created DBSnapshot - """ - return self.connection.create_dbsnapshot(snapshot_id, self.id) - - def reboot(self): - """ - Reboot this DBInstance - - :rtype: :class:`boto.rds.dbsnapshot.DBSnapshot` - :return: The newly created DBSnapshot - """ - return self.connection.reboot_dbinstance(self.id) - - def update(self, validate=False): - """ - Update the DB instance's status information by making a call to fetch - the current instance attributes from the service. - - :type validate: bool - :param validate: By default, if EC2 returns no data about the - instance the update method returns quietly. If the - validate param is True, however, it will raise a - ValueError exception if no data is returned from EC2. - """ - rs = self.connection.get_all_dbinstances(self.id) - if len(rs) > 0: - for i in rs: - if i.id == self.id: - self.__dict__.update(i.__dict__) - elif validate: - raise ValueError('%s is not a valid Instance ID' % self.id) - return self.status - - def stop(self, skip_final_snapshot=False, final_snapshot_id=''): - """ - Delete this DBInstance. - - :type skip_final_snapshot: bool - :param skip_final_snapshot: This parameter determines whether - a final db snapshot is created before the instance is - deleted. If True, no snapshot is created. If False, a - snapshot is created before deleting the instance. - - :type final_snapshot_id: str - :param final_snapshot_id: If a final snapshot is requested, this - is the identifier used for that snapshot. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The deleted db instance. - """ - return self.connection.delete_dbinstance(self.id, - skip_final_snapshot, - final_snapshot_id) - - def modify(self, param_group=None, security_groups=None, - preferred_maintenance_window=None, - master_password=None, allocated_storage=None, - instance_class=None, - backup_retention_period=None, - preferred_backup_window=None, - multi_az=False, - iops=None, - vpc_security_groups=None, - apply_immediately=False, - new_instance_id=None): - """ - Modify this DBInstance. - - :type param_group: str - :param param_group: Name of DBParameterGroup to associate with - this DBInstance. - - :type security_groups: list of str or list of DBSecurityGroup objects - :param security_groups: List of names of DBSecurityGroup to - authorize on this DBInstance. - - :type preferred_maintenance_window: str - :param preferred_maintenance_window: The weekly time range (in - UTC) during which maintenance can occur. Default is - Sun:05:00-Sun:09:00 - - :type master_password: str - :param master_password: Password of master user for the DBInstance. - Must be 4-15 alphanumeric characters. - - :type allocated_storage: int - :param allocated_storage: The new allocated storage size, in GBs. - Valid values are [5-1024] - - :type instance_class: str - :param instance_class: The compute and memory capacity of the - DBInstance. Changes will be applied at next maintenance - window unless apply_immediately is True. - - Valid values are: - - * db.m1.small - * db.m1.large - * db.m1.xlarge - * db.m2.xlarge - * db.m2.2xlarge - * db.m2.4xlarge - - :type apply_immediately: bool - :param apply_immediately: If true, the modifications will be - applied as soon as possible rather than waiting for the - next preferred maintenance window. - - :type new_instance_id: str - :param new_instance_id: The new DB instance identifier. - - :type backup_retention_period: int - :param backup_retention_period: The number of days for which - automated backups are retained. Setting this to zero - disables automated backups. - - :type preferred_backup_window: str - :param preferred_backup_window: The daily time range during - which automated backups are created (if enabled). Must be - in h24:mi-hh24:mi format (UTC). - - :type multi_az: bool - :param multi_az: If True, specifies the DB Instance will be - deployed in multiple availability zones. - - :type iops: int - :param iops: The amount of IOPS (input/output operations per - second) to Provisioned for the DB Instance. Can be - modified at a later date. - - Must scale linearly. For every 1000 IOPS provision, you - must allocated 100 GB of storage space. This scales up to - 1 TB / 10 000 IOPS for MySQL and Oracle. MSSQL is limited - to 700 GB / 7 000 IOPS. - - If you specify a value, it must be at least 1000 IOPS and - you must allocate 100 GB of storage. - - :type vpc_security_groups: list - :param vpc_security_groups: List of VPCSecurityGroupMembership - that this DBInstance is a memberof. - - :rtype: :class:`boto.rds.dbinstance.DBInstance` - :return: The modified db instance. - """ - return self.connection.modify_dbinstance(self.id, - param_group, - security_groups, - preferred_maintenance_window, - master_password, - allocated_storage, - instance_class, - backup_retention_period, - preferred_backup_window, - multi_az, - apply_immediately, - iops, - vpc_security_groups, - new_instance_id) - - -class PendingModifiedValues(dict): - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name != 'PendingModifiedValues': - self[name] = value - - -class ReadReplicaDBInstanceIdentifiers(list): - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'ReadReplicaDBInstanceIdentifier': - self.append(value) diff --git a/awx/lib/site-packages/boto/rds/dbsecuritygroup.py b/awx/lib/site-packages/boto/rds/dbsecuritygroup.py deleted file mode 100644 index 378360667d..0000000000 --- a/awx/lib/site-packages/boto/rds/dbsecuritygroup.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright (c) 2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an DBSecurityGroup -""" -from boto.ec2.securitygroup import SecurityGroup - -class DBSecurityGroup(object): - """ - Represents an RDS database security group - - Properties reference available from the AWS documentation at - http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_DeleteDBSecurityGroup.html - - :ivar Status: The current status of the security group. Possible values are - [ active, ? ]. Reference documentation lacks specifics of possibilities - :ivar connection: :py:class:`boto.rds.RDSConnection` associated with the current object - :ivar description: The description of the security group - :ivar ec2_groups: List of :py:class:`EC2 Security Group - <boto.ec2.securitygroup.SecurityGroup>` objects that this security - group PERMITS - :ivar ip_ranges: List of :py:class:`boto.rds.dbsecuritygroup.IPRange` - objects (containing CIDR addresses) that this security group PERMITS - :ivar name: Name of the security group - :ivar owner_id: ID of the owner of the security group. Can be 'None' - """ - def __init__(self, connection=None, owner_id=None, - name=None, description=None): - self.connection = connection - self.owner_id = owner_id - self.name = name - self.description = description - self.ec2_groups = [] - self.ip_ranges = [] - - def __repr__(self): - return 'DBSecurityGroup:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'IPRange': - cidr = IPRange(self) - self.ip_ranges.append(cidr) - return cidr - elif name == 'EC2SecurityGroup': - ec2_grp = EC2SecurityGroup(self) - self.ec2_groups.append(ec2_grp) - return ec2_grp - else: - return None - - def endElement(self, name, value, connection): - if name == 'OwnerId': - self.owner_id = value - elif name == 'DBSecurityGroupName': - self.name = value - elif name == 'DBSecurityGroupDescription': - self.description = value - elif name == 'IPRanges': - pass - else: - setattr(self, name, value) - - def delete(self): - return self.connection.delete_dbsecurity_group(self.name) - - def authorize(self, cidr_ip=None, ec2_group=None): - """ - Add a new rule to this DBSecurity group. - You need to pass in either a CIDR block to authorize or - and EC2 SecurityGroup. - - :type cidr_ip: string - :param cidr_ip: A valid CIDR IP range to authorize - - :type ec2_group: :class:`boto.ec2.securitygroup.SecurityGroup` - :param ec2_group: An EC2 security group to authorize - - :rtype: bool - :return: True if successful. - """ - if isinstance(ec2_group, SecurityGroup): - group_name = ec2_group.name - group_owner_id = ec2_group.owner_id - else: - group_name = None - group_owner_id = None - return self.connection.authorize_dbsecurity_group(self.name, - cidr_ip, - group_name, - group_owner_id) - - def revoke(self, cidr_ip=None, ec2_group=None): - """ - Revoke access to a CIDR range or EC2 SecurityGroup. - You need to pass in either a CIDR block or - an EC2 SecurityGroup from which to revoke access. - - :type cidr_ip: string - :param cidr_ip: A valid CIDR IP range to revoke - - :type ec2_group: :class:`boto.ec2.securitygroup.SecurityGroup` - :param ec2_group: An EC2 security group to revoke - - :rtype: bool - :return: True if successful. - """ - if isinstance(ec2_group, SecurityGroup): - group_name = ec2_group.name - group_owner_id = ec2_group.owner_id - return self.connection.revoke_dbsecurity_group( - self.name, - ec2_security_group_name=group_name, - ec2_security_group_owner_id=group_owner_id) - - # Revoking by CIDR IP range - return self.connection.revoke_dbsecurity_group( - self.name, cidr_ip=cidr_ip) - -class IPRange(object): - """ - Describes a CIDR address range for use in a DBSecurityGroup - - :ivar cidr_ip: IP Address range - """ - - def __init__(self, parent=None): - self.parent = parent - self.cidr_ip = None - self.status = None - - def __repr__(self): - return 'IPRange:%s' % self.cidr_ip - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'CIDRIP': - self.cidr_ip = value - elif name == 'Status': - self.status = value - else: - setattr(self, name, value) - -class EC2SecurityGroup(object): - """ - Describes an EC2 security group for use in a DBSecurityGroup - """ - - def __init__(self, parent=None): - self.parent = parent - self.name = None - self.owner_id = None - - def __repr__(self): - return 'EC2SecurityGroup:%s' % self.name - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'EC2SecurityGroupName': - self.name = value - elif name == 'EC2SecurityGroupOwnerId': - self.owner_id = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/rds/dbsnapshot.py b/awx/lib/site-packages/boto/rds/dbsnapshot.py deleted file mode 100644 index 16d8125be7..0000000000 --- a/awx/lib/site-packages/boto/rds/dbsnapshot.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class DBSnapshot(object): - """ - Represents a RDS DB Snapshot - - Properties reference available from the AWS documentation at http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_DBSnapshot.html - - :ivar engine_version: Specifies the version of the database engine - :ivar license_model: License model information for the restored DB instance - :ivar allocated_storage: Specifies the allocated storage size in gigabytes (GB) - :ivar availability_zone: Specifies the name of the Availability Zone the DB Instance was located in at the time of the DB Snapshot - :ivar connection: boto.rds.RDSConnection associated with the current object - :ivar engine: Specifies the name of the database engine - :ivar id: Specifies the identifier for the DB Snapshot (DBSnapshotIdentifier) - :ivar instance_create_time: Specifies the time (UTC) when the snapshot was taken - :ivar instance_id: Specifies the the DBInstanceIdentifier of the DB Instance this DB Snapshot was created from (DBInstanceIdentifier) - :ivar master_username: Provides the master username for the DB Instance - :ivar port: Specifies the port that the database engine was listening on at the time of the snapshot - :ivar snapshot_create_time: Provides the time (UTC) when the snapshot was taken - :ivar status: Specifies the status of this DB Snapshot. Possible values are [ available, backing-up, creating, deleted, deleting, failed, modifying, rebooting, resetting-master-credentials ] - :ivar iops: Specifies the Provisioned IOPS (I/O operations per second) value of the DB instance at the time of the snapshot. - :ivar option_group_name: Provides the option group name for the DB snapshot. - :ivar percent_progress: The percentage of the estimated data that has been transferred. - :ivar snapshot_type: Provides the type of the DB snapshot. - :ivar source_region: The region that the DB snapshot was created in or copied from. - :ivar vpc_id: Provides the Vpc Id associated with the DB snapshot. - """ - - def __init__(self, connection=None, id=None): - self.connection = connection - self.id = id - self.engine = None - self.engine_version = None - self.snapshot_create_time = None - self.instance_create_time = None - self.port = None - self.status = None - self.availability_zone = None - self.master_username = None - self.allocated_storage = None - self.instance_id = None - self.availability_zone = None - self.license_model = None - self.iops = None - self.option_group_name = None - self.percent_progress = None - self.snapshot_type = None - self.source_region = None - self.vpc_id = None - - def __repr__(self): - return 'DBSnapshot:%s' % self.id - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Engine': - self.engine = value - elif name == 'EngineVersion': - self.engine_version = value - elif name == 'InstanceCreateTime': - self.instance_create_time = value - elif name == 'SnapshotCreateTime': - self.snapshot_create_time = value - elif name == 'DBInstanceIdentifier': - self.instance_id = value - elif name == 'DBSnapshotIdentifier': - self.id = value - elif name == 'Port': - self.port = int(value) - elif name == 'Status': - self.status = value - elif name == 'AvailabilityZone': - self.availability_zone = value - elif name == 'MasterUsername': - self.master_username = value - elif name == 'AllocatedStorage': - self.allocated_storage = int(value) - elif name == 'SnapshotTime': - self.time = value - elif name == 'LicenseModel': - self.license_model = value - elif name == 'Iops': - self.iops = int(value) - elif name == 'OptionGroupName': - self.option_group_name = value - elif name == 'PercentProgress': - self.percent_progress = int(value) - elif name == 'SnapshotType': - self.snapshot_type = value - elif name == 'SourceRegion': - self.source_region = value - elif name == 'VpcId': - self.vpc_id = value - else: - setattr(self, name, value) - - def update(self, validate=False): - """ - Update the DB snapshot's status information by making a call to fetch - the current snapshot attributes from the service. - - :type validate: bool - :param validate: By default, if EC2 returns no data about the - instance the update method returns quietly. If - the validate param is True, however, it will - raise a ValueError exception if no data is - returned from EC2. - """ - rs = self.connection.get_all_dbsnapshots(self.id) - if len(rs) > 0: - for i in rs: - if i.id == self.id: - self.__dict__.update(i.__dict__) - elif validate: - raise ValueError('%s is not a valid Snapshot ID' % self.id) - return self.status diff --git a/awx/lib/site-packages/boto/rds/dbsubnetgroup.py b/awx/lib/site-packages/boto/rds/dbsubnetgroup.py deleted file mode 100644 index 4f6bde8924..0000000000 --- a/awx/lib/site-packages/boto/rds/dbsubnetgroup.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2013 Franc Carter - franc.carter@gmail.com -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an DBSubnetGroup -""" - -class DBSubnetGroup(object): - """ - Represents an RDS database subnet group - - Properties reference available from the AWS documentation at http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_DeleteDBSubnetGroup.html - - :ivar status: The current status of the subnet group. Possibile values are [ active, ? ]. Reference documentation lacks specifics of possibilities - :ivar connection: boto.rds.RDSConnection associated with the current object - :ivar description: The description of the subnet group - :ivar subnet_ids: List of subnet identifiers in the group - :ivar name: Name of the subnet group - :ivar vpc_id: The ID of the VPC the subnets are inside - """ - def __init__(self, connection=None, name=None, description=None, subnet_ids=None): - self.connection = connection - self.name = name - self.description = description - if subnet_ids is not None: - self.subnet_ids = subnet_ids - else: - self.subnet_ids = [] - self.vpc_id = None - self.status = None - - def __repr__(self): - return 'DBSubnetGroup:%s' % self.name - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'SubnetIdentifier': - self.subnet_ids.append(value) - elif name == 'DBSubnetGroupName': - self.name = value - elif name == 'DBSubnetGroupDescription': - self.description = value - elif name == 'VpcId': - self.vpc_id = value - elif name == 'SubnetGroupStatus': - self.status = value - else: - setattr(self, name, value) - diff --git a/awx/lib/site-packages/boto/rds/event.py b/awx/lib/site-packages/boto/rds/event.py deleted file mode 100644 index a91f8f08a5..0000000000 --- a/awx/lib/site-packages/boto/rds/event.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class Event(object): - - def __init__(self, connection=None): - self.connection = connection - self.message = None - self.source_identifier = None - self.source_type = None - self.engine = None - self.date = None - - def __repr__(self): - return '"%s"' % self.message - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'SourceIdentifier': - self.source_identifier = value - elif name == 'SourceType': - self.source_type = value - elif name == 'Message': - self.message = value - elif name == 'Date': - self.date = value - else: - setattr(self, name, value) - diff --git a/awx/lib/site-packages/boto/rds/logfile.py b/awx/lib/site-packages/boto/rds/logfile.py deleted file mode 100644 index dd80a6ff82..0000000000 --- a/awx/lib/site-packages/boto/rds/logfile.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2014 Jumping Qu http://newrice.blogspot.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class LogFile(object): - - def __init__(self, connection=None): - self.connection = connection - self.size = None - self.log_filename = None - self.last_written = None - - def __repr__(self): - #return '(%s, %s, %s)' % (self.logfilename, self.size, self.lastwritten) - return '%s' % (self.log_filename) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'LastWritten': - self.last_written = value - elif name == 'LogFileName': - self.log_filename = value - elif name == 'Size': - self.size = value - else: - setattr(self, name, value) - - -class LogFileObject(object): - def __init__(self, connection=None): - self.connection = connection - self.log_filename = None - - def __repr__(self): - return "LogFileObject: %s/%s" % (self.dbinstance_id, self.log_filename) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'LogFileData': - self.data = value - elif name == 'AdditionalDataPending': - self.additional_data_pending = value - elif name == 'Marker': - self.marker = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/rds/optiongroup.py b/awx/lib/site-packages/boto/rds/optiongroup.py deleted file mode 100644 index 8968b6cad6..0000000000 --- a/awx/lib/site-packages/boto/rds/optiongroup.py +++ /dev/null @@ -1,404 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an OptionGroup -""" - -from boto.rds.dbsecuritygroup import DBSecurityGroup -from boto.resultset import ResultSet - - -class OptionGroup(object): - """ - Represents an RDS option group - - Properties reference available from the AWS documentation at - http://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_OptionGroup.html - - :ivar connection: :py:class:`boto.rds.RDSConnection` associated with the - current object - :ivar name: Name of the option group - :ivar description: The description of the option group - :ivar engine_name: The name of the database engine to use - :ivar major_engine_version: The major version number of the engine to use - :ivar allow_both_vpc_and_nonvpc: Indicates whether this option group can be - applied to both VPC and non-VPC instances. - The value ``True`` indicates the option - group can be applied to both VPC and - non-VPC instances. - :ivar vpc_id: If AllowsVpcAndNonVpcInstanceMemberships is 'false', this - field is blank. If AllowsVpcAndNonVpcInstanceMemberships is - ``True`` and this field is blank, then this option group can - be applied to both VPC and non-VPC instances. If this field - contains a value, then this option group can only be applied - to instances that are in the VPC indicated by this field. - :ivar options: The list of :py:class:`boto.rds.optiongroup.Option` objects - associated with the group - """ - def __init__(self, connection=None, name=None, engine_name=None, - major_engine_version=None, description=None, - allow_both_vpc_and_nonvpc=False, vpc_id=None): - self.name = name - self.engine_name = engine_name - self.major_engine_version = major_engine_version - self.description = description - self.allow_both_vpc_and_nonvpc = allow_both_vpc_and_nonvpc - self.vpc_id = vpc_id - self.options = [] - - def __repr__(self): - return 'OptionGroup:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'Options': - self.options = ResultSet([ - ('Options', Option) - ]) - else: - return None - - def endElement(self, name, value, connection): - if name == 'OptionGroupName': - self.name = value - elif name == 'EngineName': - self.engine_name = value - elif name == 'MajorEngineVersion': - self.major_engine_version = value - elif name == 'OptionGroupDescription': - self.description = value - elif name == 'AllowsVpcAndNonVpcInstanceMemberships': - if value.lower() == 'true': - self.allow_both_vpc_and_nonvpc = True - else: - self.allow_both_vpc_and_nonvpc = False - elif name == 'VpcId': - self.vpc_id = value - else: - setattr(self, name, value) - - def delete(self): - return self.connection.delete_option_group(self.name) - - -class Option(object): - """ - Describes a Option for use in an OptionGroup - - :ivar name: The name of the option - :ivar description: The description of the option. - :ivar permanent: Indicate if this option is permanent. - :ivar persistent: Indicate if this option is persistent. - :ivar port: If required, the port configured for this option to use. - :ivar settings: The option settings for this option. - :ivar db_security_groups: If the option requires access to a port, then - this DB Security Group allows access to the port. - :ivar vpc_security_groups: If the option requires access to a port, then - this VPC Security Group allows access to the - port. - """ - def __init__(self, name=None, description=None, permanent=False, - persistent=False, port=None, settings=None, - db_security_groups=None, vpc_security_groups=None): - self.name = name - self.description = description - self.permanent = permanent - self.persistent = persistent - self.port = port - self.settings = settings - self.db_security_groups = db_security_groups - self.vpc_security_groups = vpc_security_groups - - if self.settings is None: - self.settings = [] - - if self.db_security_groups is None: - self.db_security_groups = [] - - if self.vpc_security_groups is None: - self.vpc_security_groups = [] - - def __repr__(self): - return 'Option:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'OptionSettings': - self.settings = ResultSet([ - ('OptionSettings', OptionSetting) - ]) - elif name == 'DBSecurityGroupMemberships': - self.db_security_groups = ResultSet([ - ('DBSecurityGroupMemberships', DBSecurityGroup) - ]) - elif name == 'VpcSecurityGroupMemberships': - self.vpc_security_groups = ResultSet([ - ('VpcSecurityGroupMemberships', VpcSecurityGroup) - ]) - else: - return None - - def endElement(self, name, value, connection): - if name == 'OptionName': - self.name = value - elif name == 'OptionDescription': - self.description = value - elif name == 'Permanent': - if value.lower() == 'true': - self.permenant = True - else: - self.permenant = False - elif name == 'Persistent': - if value.lower() == 'true': - self.persistent = True - else: - self.persistent = False - elif name == 'Port': - self.port = int(value) - else: - setattr(self, name, value) - - -class OptionSetting(object): - """ - Describes a OptionSetting for use in an Option - - :ivar name: The name of the option that has settings that you can set. - :ivar description: The description of the option setting. - :ivar value: The current value of the option setting. - :ivar default_value: The default value of the option setting. - :ivar allowed_values: The allowed values of the option setting. - :ivar data_type: The data type of the option setting. - :ivar apply_type: The DB engine specific parameter type. - :ivar is_modifiable: A Boolean value that, when true, indicates the option - setting can be modified from the default. - :ivar is_collection: Indicates if the option setting is part of a - collection. - """ - - def __init__(self, name=None, description=None, value=None, - default_value=False, allowed_values=None, data_type=None, - apply_type=None, is_modifiable=False, is_collection=False): - self.name = name - self.description = description - self.value = value - self.default_value = default_value - self.allowed_values = allowed_values - self.data_type = data_type - self.apply_type = apply_type - self.is_modifiable = is_modifiable - self.is_collection = is_collection - - def __repr__(self): - return 'OptionSetting:%s' % self.name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Name': - self.name = value - elif name == 'Description': - self.description = value - elif name == 'Value': - self.value = value - elif name == 'DefaultValue': - self.default_value = value - elif name == 'AllowedValues': - self.allowed_values = value - elif name == 'DataType': - self.data_type = value - elif name == 'ApplyType': - self.apply_type = value - elif name == 'IsModifiable': - if value.lower() == 'true': - self.is_modifiable = True - else: - self.is_modifiable = False - elif name == 'IsCollection': - if value.lower() == 'true': - self.is_collection = True - else: - self.is_collection = False - else: - setattr(self, name, value) - - -class VpcSecurityGroup(object): - """ - Describes a VPC security group for use in a OptionGroup - """ - def __init__(self, vpc_id=None, status=None): - self.vpc_id = vpc_id - self.status = status - - def __repr__(self): - return 'VpcSecurityGroup:%s' % self.vpc_id - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'VpcSecurityGroupId': - self.vpc_id = value - elif name == 'Status': - self.status = value - else: - setattr(self, name, value) - - -class OptionGroupOption(object): - """ - Describes a OptionGroupOption for use in an OptionGroup - - :ivar name: The name of the option - :ivar description: The description of the option. - :ivar engine_name: Engine name that this option can be applied to. - :ivar major_engine_version: Indicates the major engine version that the - option is available for. - :ivar min_minor_engine_version: The minimum required engine version for the - option to be applied. - :ivar permanent: Indicate if this option is permanent. - :ivar persistent: Indicate if this option is persistent. - :ivar port_required: Specifies whether the option requires a port. - :ivar default_port: If the option requires a port, specifies the default - port for the option. - :ivar settings: The option settings for this option. - :ivar depends_on: List of all options that are prerequisites for this - option. - """ - def __init__(self, name=None, description=None, engine_name=None, - major_engine_version=None, min_minor_engine_version=None, - permanent=False, persistent=False, port_required=False, - default_port=None, settings=None, depends_on=None): - self.name = name - self.description = description - self.engine_name = engine_name - self.major_engine_version = major_engine_version - self.min_minor_engine_version = min_minor_engine_version - self.permanent = permanent - self.persistent = persistent - self.port_required = port_required - self.default_port = default_port - self.settings = settings - self.depends_on = depends_on - - if self.settings is None: - self.settings = [] - - if self.depends_on is None: - self.depends_on = [] - - def __repr__(self): - return 'OptionGroupOption:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'OptionGroupOptionSettings': - self.settings = ResultSet([ - ('OptionGroupOptionSettings', OptionGroupOptionSetting) - ]) - elif name == 'OptionsDependedOn': - self.depends_on = [] - else: - return None - - def endElement(self, name, value, connection): - if name == 'Name': - self.name = value - elif name == 'Description': - self.description = value - elif name == 'EngineName': - self.engine_name = value - elif name == 'MajorEngineVersion': - self.major_engine_version = value - elif name == 'MinimumRequiredMinorEngineVersion': - self.min_minor_engine_version = value - elif name == 'Permanent': - if value.lower() == 'true': - self.permenant = True - else: - self.permenant = False - elif name == 'Persistent': - if value.lower() == 'true': - self.persistent = True - else: - self.persistent = False - elif name == 'PortRequired': - if value.lower() == 'true': - self.port_required = True - else: - self.port_required = False - elif name == 'DefaultPort': - self.default_port = int(value) - else: - setattr(self, name, value) - - -class OptionGroupOptionSetting(object): - """ - Describes a OptionGroupOptionSetting for use in an OptionGroupOption. - - :ivar name: The name of the option that has settings that you can set. - :ivar description: The description of the option setting. - :ivar value: The current value of the option setting. - :ivar default_value: The default value of the option setting. - :ivar allowed_values: The allowed values of the option setting. - :ivar data_type: The data type of the option setting. - :ivar apply_type: The DB engine specific parameter type. - :ivar is_modifiable: A Boolean value that, when true, indicates the option - setting can be modified from the default. - :ivar is_collection: Indicates if the option setting is part of a - collection. - """ - - def __init__(self, name=None, description=None, default_value=False, - allowed_values=None, apply_type=None, is_modifiable=False): - self.name = name - self.description = description - self.default_value = default_value - self.allowed_values = allowed_values - self.apply_type = apply_type - self.is_modifiable = is_modifiable - - def __repr__(self): - return 'OptionGroupOptionSetting:%s' % self.name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'SettingName': - self.name = value - elif name == 'SettingDescription': - self.description = value - elif name == 'DefaultValue': - self.default_value = value - elif name == 'AllowedValues': - self.allowed_values = value - elif name == 'ApplyType': - self.apply_type = value - elif name == 'IsModifiable': - if value.lower() == 'true': - self.is_modifiable = True - else: - self.is_modifiable = False - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/rds/parametergroup.py b/awx/lib/site-packages/boto/rds/parametergroup.py deleted file mode 100644 index ade3b807e7..0000000000 --- a/awx/lib/site-packages/boto/rds/parametergroup.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class ParameterGroup(dict): - - def __init__(self, connection=None): - dict.__init__(self) - self.connection = connection - self.name = None - self.description = None - self.engine = None - self._current_param = None - - def __repr__(self): - return 'ParameterGroup:%s' % self.name - - def startElement(self, name, attrs, connection): - if name == 'Parameter': - if self._current_param: - self[self._current_param.name] = self._current_param - self._current_param = Parameter(self) - return self._current_param - - def endElement(self, name, value, connection): - if name == 'DBParameterGroupName': - self.name = value - elif name == 'Description': - self.description = value - elif name == 'Engine': - self.engine = value - else: - setattr(self, name, value) - - def modifiable(self): - mod = [] - for key in self: - p = self[key] - if p.is_modifiable: - mod.append(p) - return mod - - def get_params(self): - pg = self.connection.get_all_dbparameters(self.name) - self.update(pg) - - def add_param(self, name, value, apply_method): - param = Parameter() - param.name = name - param.value = value - param.apply_method = apply_method - self.params.append(param) - -class Parameter(object): - """ - Represents a RDS Parameter - """ - - ValidTypes = {'integer' : int, - 'string' : str, - 'boolean' : bool} - ValidSources = ['user', 'system', 'engine-default'] - ValidApplyTypes = ['static', 'dynamic'] - ValidApplyMethods = ['immediate', 'pending-reboot'] - - def __init__(self, group=None, name=None): - self.group = group - self.name = name - self._value = None - self.type = 'string' - self.source = None - self.is_modifiable = True - self.description = None - self.apply_method = None - self.allowed_values = None - - def __repr__(self): - return 'Parameter:%s' % self.name - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'ParameterName': - self.name = value - elif name == 'ParameterValue': - self._value = value - elif name == 'DataType': - if value in self.ValidTypes: - self.type = value - elif name == 'Source': - if value in self.ValidSources: - self.source = value - elif name == 'IsModifiable': - if value.lower() == 'true': - self.is_modifiable = True - else: - self.is_modifiable = False - elif name == 'Description': - self.description = value - elif name == 'ApplyType': - if value in self.ValidApplyTypes: - self.apply_type = value - elif name == 'AllowedValues': - self.allowed_values = value - else: - setattr(self, name, value) - - def merge(self, d, i): - prefix = 'Parameters.member.%d.' % i - if self.name: - d[prefix+'ParameterName'] = self.name - if self._value is not None: - d[prefix+'ParameterValue'] = self._value - if self.apply_type: - d[prefix+'ApplyMethod'] = self.apply_method - - def _set_string_value(self, value): - if not isinstance(value, basestring): - raise ValueError('value must be of type str') - if self.allowed_values: - choices = self.allowed_values.split(',') - if value not in choices: - raise ValueError('value must be in %s' % self.allowed_values) - self._value = value - - def _set_integer_value(self, value): - if isinstance(value, basestring): - value = int(value) - if isinstance(value, int) or isinstance(value, long): - if self.allowed_values: - min, max = self.allowed_values.split('-') - if value < int(min) or value > int(max): - raise ValueError('range is %s' % self.allowed_values) - self._value = value - else: - raise ValueError('value must be integer') - - def _set_boolean_value(self, value): - if isinstance(value, bool): - self._value = value - elif isinstance(value, basestring): - if value.lower() == 'true': - self._value = True - else: - self._value = False - else: - raise ValueError('value must be boolean') - - def set_value(self, value): - if self.type == 'string': - self._set_string_value(value) - elif self.type == 'integer': - self._set_integer_value(value) - elif self.type == 'boolean': - self._set_boolean_value(value) - else: - raise TypeError('unknown type (%s)' % self.type) - - def get_value(self): - if self._value is None: - return self._value - if self.type == 'string': - return self._value - elif self.type == 'integer': - if not isinstance(self._value, int) and not isinstance(self._value, long): - self._set_integer_value(self._value) - return self._value - elif self.type == 'boolean': - if not isinstance(self._value, bool): - self._set_boolean_value(self._value) - return self._value - else: - raise TypeError('unknown type (%s)' % self.type) - - value = property(get_value, set_value, 'The value of the parameter') - - def apply(self, immediate=False): - if immediate: - self.apply_method = 'immediate' - else: - self.apply_method = 'pending-reboot' - self.group.connection.modify_parameter_group(self.group.name, [self]) - diff --git a/awx/lib/site-packages/boto/rds/regioninfo.py b/awx/lib/site-packages/boto/rds/regioninfo.py deleted file mode 100644 index 5019aca90f..0000000000 --- a/awx/lib/site-packages/boto/rds/regioninfo.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo - -class RDSRegionInfo(RegionInfo): - - def __init__(self, connection=None, name=None, endpoint=None, - connection_cls=None): - from boto.rds import RDSConnection - super(RDSRegionInfo, self).__init__(connection, name, endpoint, - RDSConnection) diff --git a/awx/lib/site-packages/boto/rds/statusinfo.py b/awx/lib/site-packages/boto/rds/statusinfo.py deleted file mode 100644 index d4ff9b08de..0000000000 --- a/awx/lib/site-packages/boto/rds/statusinfo.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -class StatusInfo(object): - """ - Describes a status message. - """ - - def __init__(self, status_type=None, normal=None, status=None, message=None): - self.status_type = status_type - self.normal = normal - self.status = status - self.message = message - - def __repr__(self): - return 'StatusInfo:%s' % self.message - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'StatusType': - self.status_type = value - elif name == 'Normal': - if value.lower() == 'true': - self.normal = True - else: - self.normal = False - elif name == 'Status': - self.status = value - elif name == 'Message': - self.message = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/rds/vpcsecuritygroupmembership.py b/awx/lib/site-packages/boto/rds/vpcsecuritygroupmembership.py deleted file mode 100644 index e0092e9c2f..0000000000 --- a/awx/lib/site-packages/boto/rds/vpcsecuritygroupmembership.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2013 Anthony Tonns http://www.corsis.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a VPCSecurityGroupMembership -""" - - -class VPCSecurityGroupMembership(object): - """ - Represents VPC Security Group that this RDS database is a member of - - Properties reference available from the AWS documentation at - http://docs.aws.amazon.com/AmazonRDS/latest/APIReference/\ - API_VpcSecurityGroupMembership.html - - Example:: - pri = "sg-abcdefgh" - sec = "sg-hgfedcba" - - # Create with list of str - db = c.create_dbinstance(... vpc_security_groups=[pri], ... ) - - # Modify with list of str - db.modify(... vpc_security_groups=[pri,sec], ... ) - - # Create with objects - memberships = [] - membership = VPCSecurityGroupMembership() - membership.vpc_group = pri - memberships.append(membership) - - db = c.create_dbinstance(... vpc_security_groups=memberships, ... ) - - # Modify with objects - memberships = d.vpc_security_groups - membership = VPCSecurityGroupMembership() - membership.vpc_group = sec - memberships.append(membership) - - db.modify(... vpc_security_groups=memberships, ... ) - - :ivar connection: :py:class:`boto.rds.RDSConnection` associated with the - current object - :ivar vpc_group: This id of the VPC security group - :ivar status: Status of the VPC security group membership - <boto.ec2.securitygroup.SecurityGroup>` objects that this RDS Instance - is a member of - """ - def __init__(self, connection=None, status=None, vpc_group=None): - self.connection = connection - self.status = status - self.vpc_group = vpc_group - - def __repr__(self): - return 'VPCSecurityGroupMembership:%s' % self.vpc_group - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'VpcSecurityGroupId': - self.vpc_group = value - elif name == 'Status': - self.status = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/rds2/__init__.py b/awx/lib/site-packages/boto/rds2/__init__.py deleted file mode 100644 index 023a0baa95..0000000000 --- a/awx/lib/site-packages/boto/rds2/__init__.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import get_regions - - -def regions(): - """ - Get all available regions for the RDS service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.rds2.layer1 import RDSConnection - return get_regions('rds', connection_cls=RDSConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.rds2.layer1.RDSConnection`. - Any additional parameters after the region_name are passed on to - the connect method of the region object. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.rds2.layer1.RDSConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/rds2/exceptions.py b/awx/lib/site-packages/boto/rds2/exceptions.py deleted file mode 100644 index be610b0171..0000000000 --- a/awx/lib/site-packages/boto/rds2/exceptions.py +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import JSONResponseError - - -class InvalidSubnet(JSONResponseError): - pass - - -class DBParameterGroupQuotaExceeded(JSONResponseError): - pass - - -class DBSubnetGroupAlreadyExists(JSONResponseError): - pass - - -class DBSubnetGroupQuotaExceeded(JSONResponseError): - pass - - -class InstanceQuotaExceeded(JSONResponseError): - pass - - -class InvalidRestore(JSONResponseError): - pass - - -class InvalidDBParameterGroupState(JSONResponseError): - pass - - -class AuthorizationQuotaExceeded(JSONResponseError): - pass - - -class DBSecurityGroupAlreadyExists(JSONResponseError): - pass - - -class InsufficientDBInstanceCapacity(JSONResponseError): - pass - - -class ReservedDBInstanceQuotaExceeded(JSONResponseError): - pass - - -class DBSecurityGroupNotFound(JSONResponseError): - pass - - -class DBInstanceAlreadyExists(JSONResponseError): - pass - - -class ReservedDBInstanceNotFound(JSONResponseError): - pass - - -class DBSubnetGroupDoesNotCoverEnoughAZs(JSONResponseError): - pass - - -class InvalidDBSecurityGroupState(JSONResponseError): - pass - - -class InvalidVPCNetworkState(JSONResponseError): - pass - - -class ReservedDBInstancesOfferingNotFound(JSONResponseError): - pass - - -class SNSTopicArnNotFound(JSONResponseError): - pass - - -class SNSNoAuthorization(JSONResponseError): - pass - - -class SnapshotQuotaExceeded(JSONResponseError): - pass - - -class OptionGroupQuotaExceeded(JSONResponseError): - pass - - -class DBParameterGroupNotFound(JSONResponseError): - pass - - -class SNSInvalidTopic(JSONResponseError): - pass - - -class InvalidDBSubnetGroupState(JSONResponseError): - pass - - -class DBSubnetGroupNotFound(JSONResponseError): - pass - - -class InvalidOptionGroupState(JSONResponseError): - pass - - -class SourceNotFound(JSONResponseError): - pass - - -class SubscriptionCategoryNotFound(JSONResponseError): - pass - - -class EventSubscriptionQuotaExceeded(JSONResponseError): - pass - - -class DBSecurityGroupNotSupported(JSONResponseError): - pass - - -class InvalidEventSubscriptionState(JSONResponseError): - pass - - -class InvalidDBSubnetState(JSONResponseError): - pass - - -class InvalidDBSnapshotState(JSONResponseError): - pass - - -class SubscriptionAlreadyExist(JSONResponseError): - pass - - -class DBSecurityGroupQuotaExceeded(JSONResponseError): - pass - - -class ProvisionedIopsNotAvailableInAZ(JSONResponseError): - pass - - -class AuthorizationNotFound(JSONResponseError): - pass - - -class OptionGroupAlreadyExists(JSONResponseError): - pass - - -class SubscriptionNotFound(JSONResponseError): - pass - - -class DBUpgradeDependencyFailure(JSONResponseError): - pass - - -class PointInTimeRestoreNotEnabled(JSONResponseError): - pass - - -class AuthorizationAlreadyExists(JSONResponseError): - pass - - -class DBSubnetQuotaExceeded(JSONResponseError): - pass - - -class OptionGroupNotFound(JSONResponseError): - pass - - -class DBParameterGroupAlreadyExists(JSONResponseError): - pass - - -class DBInstanceNotFound(JSONResponseError): - pass - - -class ReservedDBInstanceAlreadyExists(JSONResponseError): - pass - - -class InvalidDBInstanceState(JSONResponseError): - pass - - -class DBSnapshotNotFound(JSONResponseError): - pass - - -class DBSnapshotAlreadyExists(JSONResponseError): - pass - - -class StorageQuotaExceeded(JSONResponseError): - pass - - -class SubnetAlreadyInUse(JSONResponseError): - pass diff --git a/awx/lib/site-packages/boto/rds2/layer1.py b/awx/lib/site-packages/boto/rds2/layer1.py deleted file mode 100644 index 5615f1107d..0000000000 --- a/awx/lib/site-packages/boto/rds2/layer1.py +++ /dev/null @@ -1,3770 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.rds2 import exceptions -from boto.compat import json - - -class RDSConnection(AWSQueryConnection): - """ - Amazon Relational Database Service - Amazon Relational Database Service (Amazon RDS) is a web service - that makes it easier to set up, operate, and scale a relational - database in the cloud. It provides cost-efficient, resizable - capacity for an industry-standard relational database and manages - common database administration tasks, freeing up developers to - focus on what makes their applications and businesses unique. - - Amazon RDS gives you access to the capabilities of a familiar - MySQL or Oracle database server. This means the code, - applications, and tools you already use today with your existing - MySQL or Oracle databases work with Amazon RDS without - modification. Amazon RDS automatically backs up your database and - maintains the database software that powers your DB instance. - Amazon RDS is flexible: you can scale your database instance's - compute resources and storage capacity to meet your application's - demand. As with all Amazon Web Services, there are no up-front - investments, and you pay only for the resources you use. - - This is the Amazon RDS API Reference . It contains a comprehensive - description of all Amazon RDS Query APIs and data types. Note that - this API is asynchronous and some actions may require polling to - determine when an action has been applied. See the parameter - description to determine if a change is applied immediately or on - the next instance reboot or during the maintenance window. For - more information on Amazon RDS concepts and usage scenarios, go to - the `Amazon RDS User Guide`_. - """ - APIVersion = "2013-09-09" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "rds.us-east-1.amazonaws.com" - ResponseError = JSONResponseError - - _faults = { - "InvalidSubnet": exceptions.InvalidSubnet, - "DBParameterGroupQuotaExceeded": exceptions.DBParameterGroupQuotaExceeded, - "DBSubnetGroupAlreadyExists": exceptions.DBSubnetGroupAlreadyExists, - "DBSubnetGroupQuotaExceeded": exceptions.DBSubnetGroupQuotaExceeded, - "InstanceQuotaExceeded": exceptions.InstanceQuotaExceeded, - "InvalidRestore": exceptions.InvalidRestore, - "InvalidDBParameterGroupState": exceptions.InvalidDBParameterGroupState, - "AuthorizationQuotaExceeded": exceptions.AuthorizationQuotaExceeded, - "DBSecurityGroupAlreadyExists": exceptions.DBSecurityGroupAlreadyExists, - "InsufficientDBInstanceCapacity": exceptions.InsufficientDBInstanceCapacity, - "ReservedDBInstanceQuotaExceeded": exceptions.ReservedDBInstanceQuotaExceeded, - "DBSecurityGroupNotFound": exceptions.DBSecurityGroupNotFound, - "DBInstanceAlreadyExists": exceptions.DBInstanceAlreadyExists, - "ReservedDBInstanceNotFound": exceptions.ReservedDBInstanceNotFound, - "DBSubnetGroupDoesNotCoverEnoughAZs": exceptions.DBSubnetGroupDoesNotCoverEnoughAZs, - "InvalidDBSecurityGroupState": exceptions.InvalidDBSecurityGroupState, - "InvalidVPCNetworkState": exceptions.InvalidVPCNetworkState, - "ReservedDBInstancesOfferingNotFound": exceptions.ReservedDBInstancesOfferingNotFound, - "SNSTopicArnNotFound": exceptions.SNSTopicArnNotFound, - "SNSNoAuthorization": exceptions.SNSNoAuthorization, - "SnapshotQuotaExceeded": exceptions.SnapshotQuotaExceeded, - "OptionGroupQuotaExceeded": exceptions.OptionGroupQuotaExceeded, - "DBParameterGroupNotFound": exceptions.DBParameterGroupNotFound, - "SNSInvalidTopic": exceptions.SNSInvalidTopic, - "InvalidDBSubnetGroupState": exceptions.InvalidDBSubnetGroupState, - "DBSubnetGroupNotFound": exceptions.DBSubnetGroupNotFound, - "InvalidOptionGroupState": exceptions.InvalidOptionGroupState, - "SourceNotFound": exceptions.SourceNotFound, - "SubscriptionCategoryNotFound": exceptions.SubscriptionCategoryNotFound, - "EventSubscriptionQuotaExceeded": exceptions.EventSubscriptionQuotaExceeded, - "DBSecurityGroupNotSupported": exceptions.DBSecurityGroupNotSupported, - "InvalidEventSubscriptionState": exceptions.InvalidEventSubscriptionState, - "InvalidDBSubnetState": exceptions.InvalidDBSubnetState, - "InvalidDBSnapshotState": exceptions.InvalidDBSnapshotState, - "SubscriptionAlreadyExist": exceptions.SubscriptionAlreadyExist, - "DBSecurityGroupQuotaExceeded": exceptions.DBSecurityGroupQuotaExceeded, - "ProvisionedIopsNotAvailableInAZ": exceptions.ProvisionedIopsNotAvailableInAZ, - "AuthorizationNotFound": exceptions.AuthorizationNotFound, - "OptionGroupAlreadyExists": exceptions.OptionGroupAlreadyExists, - "SubscriptionNotFound": exceptions.SubscriptionNotFound, - "DBUpgradeDependencyFailure": exceptions.DBUpgradeDependencyFailure, - "PointInTimeRestoreNotEnabled": exceptions.PointInTimeRestoreNotEnabled, - "AuthorizationAlreadyExists": exceptions.AuthorizationAlreadyExists, - "DBSubnetQuotaExceeded": exceptions.DBSubnetQuotaExceeded, - "OptionGroupNotFound": exceptions.OptionGroupNotFound, - "DBParameterGroupAlreadyExists": exceptions.DBParameterGroupAlreadyExists, - "DBInstanceNotFound": exceptions.DBInstanceNotFound, - "ReservedDBInstanceAlreadyExists": exceptions.ReservedDBInstanceAlreadyExists, - "InvalidDBInstanceState": exceptions.InvalidDBInstanceState, - "DBSnapshotNotFound": exceptions.DBSnapshotNotFound, - "DBSnapshotAlreadyExists": exceptions.DBSnapshotAlreadyExists, - "StorageQuotaExceeded": exceptions.StorageQuotaExceeded, - "SubnetAlreadyInUse": exceptions.SubnetAlreadyInUse, - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs: - kwargs['host'] = region.endpoint - - super(RDSConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def add_source_identifier_to_subscription(self, subscription_name, - source_identifier): - """ - Adds a source identifier to an existing RDS event notification - subscription. - - :type subscription_name: string - :param subscription_name: The name of the RDS event notification - subscription you want to add a source identifier to. - - :type source_identifier: string - :param source_identifier: - The identifier of the event source to be added. An identifier must - begin with a letter and must contain only ASCII letters, digits, - and hyphens; it cannot end with a hyphen or contain two consecutive - hyphens. - - Constraints: - - - + If the source type is a DB instance, then a `DBInstanceIdentifier` - must be supplied. - + If the source type is a DB security group, a `DBSecurityGroupName` - must be supplied. - + If the source type is a DB parameter group, a `DBParameterGroupName` - must be supplied. - + If the source type is a DB snapshot, a `DBSnapshotIdentifier` must be - supplied. - - """ - params = { - 'SubscriptionName': subscription_name, - 'SourceIdentifier': source_identifier, - } - return self._make_request( - action='AddSourceIdentifierToSubscription', - verb='POST', - path='/', params=params) - - def add_tags_to_resource(self, resource_name, tags): - """ - Adds metadata tags to an Amazon RDS resource. These tags can - also be used with cost allocation reporting to track cost - associated with Amazon RDS resources, or used in Condition - statement in IAM policy for Amazon RDS. - - For an overview on tagging Amazon RDS resources, see `Tagging - Amazon RDS Resources`_. - - :type resource_name: string - :param resource_name: The Amazon RDS resource the tags will be added - to. This value is an Amazon Resource Name (ARN). For information - about creating an ARN, see ` Constructing an RDS Amazon Resource - Name (ARN)`_. - - :type tags: list - :param tags: The tags to be assigned to the Amazon RDS resource. - - """ - params = {'ResourceName': resource_name, } - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='AddTagsToResource', - verb='POST', - path='/', params=params) - - def authorize_db_security_group_ingress(self, db_security_group_name, - cidrip=None, - ec2_security_group_name=None, - ec2_security_group_id=None, - ec2_security_group_owner_id=None): - """ - Enables ingress to a DBSecurityGroup using one of two forms of - authorization. First, EC2 or VPC security groups can be added - to the DBSecurityGroup if the application using the database - is running on EC2 or VPC instances. Second, IP ranges are - available if the application accessing your database is - running on the Internet. Required parameters for this API are - one of CIDR range, EC2SecurityGroupId for VPC, or - (EC2SecurityGroupOwnerId and either EC2SecurityGroupName or - EC2SecurityGroupId for non-VPC). - You cannot authorize ingress from an EC2 security group in one - Region to an Amazon RDS DB instance in another. You cannot - authorize ingress from a VPC security group in one VPC to an - Amazon RDS DB instance in another. - For an overview of CIDR ranges, go to the `Wikipedia - Tutorial`_. - - :type db_security_group_name: string - :param db_security_group_name: The name of the DB security group to add - authorization to. - - :type cidrip: string - :param cidrip: The IP range to authorize. - - :type ec2_security_group_name: string - :param ec2_security_group_name: Name of the EC2 security group to - authorize. For VPC DB security groups, `EC2SecurityGroupId` must be - provided. Otherwise, EC2SecurityGroupOwnerId and either - `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided. - - :type ec2_security_group_id: string - :param ec2_security_group_id: Id of the EC2 security group to - authorize. For VPC DB security groups, `EC2SecurityGroupId` must be - provided. Otherwise, EC2SecurityGroupOwnerId and either - `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: AWS Account Number of the owner of - the EC2 security group specified in the EC2SecurityGroupName - parameter. The AWS Access Key ID is not an acceptable value. For - VPC DB security groups, `EC2SecurityGroupId` must be provided. - Otherwise, EC2SecurityGroupOwnerId and either - `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided. - - """ - params = {'DBSecurityGroupName': db_security_group_name, } - if cidrip is not None: - params['CIDRIP'] = cidrip - if ec2_security_group_name is not None: - params['EC2SecurityGroupName'] = ec2_security_group_name - if ec2_security_group_id is not None: - params['EC2SecurityGroupId'] = ec2_security_group_id - if ec2_security_group_owner_id is not None: - params['EC2SecurityGroupOwnerId'] = ec2_security_group_owner_id - return self._make_request( - action='AuthorizeDBSecurityGroupIngress', - verb='POST', - path='/', params=params) - - def copy_db_snapshot(self, source_db_snapshot_identifier, - target_db_snapshot_identifier, tags=None): - """ - Copies the specified DBSnapshot. The source DBSnapshot must be - in the "available" state. - - :type source_db_snapshot_identifier: string - :param source_db_snapshot_identifier: The identifier for the source DB - snapshot. - Constraints: - - - + Must be the identifier for a valid system snapshot in the "available" - state. - - - Example: `rds:mydb-2012-04-02-00-01` - - :type target_db_snapshot_identifier: string - :param target_db_snapshot_identifier: The identifier for the copied - snapshot. - Constraints: - - - + Cannot be null, empty, or blank - + Must contain from 1 to 255 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - - Example: `my-db-snapshot` - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'SourceDBSnapshotIdentifier': source_db_snapshot_identifier, - 'TargetDBSnapshotIdentifier': target_db_snapshot_identifier, - } - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CopyDBSnapshot', - verb='POST', - path='/', params=params) - - def create_db_instance(self, db_instance_identifier, allocated_storage, - db_instance_class, engine, master_username, - master_user_password, db_name=None, - db_security_groups=None, - vpc_security_group_ids=None, - availability_zone=None, db_subnet_group_name=None, - preferred_maintenance_window=None, - db_parameter_group_name=None, - backup_retention_period=None, - preferred_backup_window=None, port=None, - multi_az=None, engine_version=None, - auto_minor_version_upgrade=None, - license_model=None, iops=None, - option_group_name=None, character_set_name=None, - publicly_accessible=None, tags=None): - """ - Creates a new DB instance. - - :type db_name: string - :param db_name: The meaning of this parameter differs according to the - database engine you use. - **MySQL** - - The name of the database to create when the DB instance is created. If - this parameter is not specified, no database is created in the DB - instance. - - Constraints: - - - + Must contain 1 to 64 alphanumeric characters - + Cannot be a word reserved by the specified database engine - - - Type: String - - **Oracle** - - The Oracle System ID (SID) of the created DB instance. - - Default: `ORCL` - - Constraints: - - - + Cannot be longer than 8 characters - - - **SQL Server** - - Not applicable. Must be null. - - :type db_instance_identifier: string - :param db_instance_identifier: The DB instance identifier. This - parameter is stored as a lowercase string. - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens (1 to 15 - for SQL Server). - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - - Example: `mydbinstance` - - :type allocated_storage: integer - :param allocated_storage: The amount of storage (in gigabytes) to be - initially allocated for the database instance. - **MySQL** - - Constraints: Must be an integer from 5 to 1024. - - Type: Integer - - **Oracle** - - Constraints: Must be an integer from 10 to 1024. - - **SQL Server** - - Constraints: Must be an integer from 200 to 1024 (Standard Edition and - Enterprise Edition) or from 30 to 1024 (Express Edition and Web - Edition) - - :type db_instance_class: string - :param db_instance_class: The compute and memory capacity of the DB - instance. - Valid Values: `db.t1.micro | db.m1.small | db.m1.medium | db.m1.large | - db.m1.xlarge | db.m2.xlarge |db.m2.2xlarge | db.m2.4xlarge` - - :type engine: string - :param engine: The name of the database engine to be used for this - instance. - Valid Values: `MySQL` | `oracle-se1` | `oracle-se` | `oracle-ee` | - `sqlserver-ee` | `sqlserver-se` | `sqlserver-ex` | `sqlserver-web` - - :type master_username: string - :param master_username: - The name of master user for the client DB instance. - - **MySQL** - - Constraints: - - - + Must be 1 to 16 alphanumeric characters. - + First character must be a letter. - + Cannot be a reserved word for the chosen database engine. - - - Type: String - - **Oracle** - - Constraints: - - - + Must be 1 to 30 alphanumeric characters. - + First character must be a letter. - + Cannot be a reserved word for the chosen database engine. - - - **SQL Server** - - Constraints: - - - + Must be 1 to 128 alphanumeric characters. - + First character must be a letter. - + Cannot be a reserved word for the chosen database engine. - - :type master_user_password: string - :param master_user_password: The password for the master database user. - Can be any printable ASCII character except "/", '"', or "@". - Type: String - - **MySQL** - - Constraints: Must contain from 8 to 41 characters. - - **Oracle** - - Constraints: Must contain from 8 to 30 characters. - - **SQL Server** - - Constraints: Must contain from 8 to 128 characters. - - :type db_security_groups: list - :param db_security_groups: A list of DB security groups to associate - with this DB instance. - Default: The default DB security group for the database engine. - - :type vpc_security_group_ids: list - :param vpc_security_group_ids: A list of EC2 VPC security groups to - associate with this DB instance. - Default: The default EC2 VPC security group for the DB subnet group's - VPC. - - :type availability_zone: string - :param availability_zone: The EC2 Availability Zone that the database - instance will be created in. - Default: A random, system-chosen Availability Zone in the endpoint's - region. - - Example: `us-east-1d` - - Constraint: The AvailabilityZone parameter cannot be specified if the - MultiAZ parameter is set to `True`. The specified Availability Zone - must be in the same region as the current endpoint. - - :type db_subnet_group_name: string - :param db_subnet_group_name: A DB subnet group to associate with this - DB instance. - If there is no DB subnet group, then it is a non-VPC DB instance. - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which system maintenance can occur. - Format: `ddd:hh24:mi-ddd:hh24:mi` - - Default: A 30-minute window selected at random from an 8-hour block of - time per region, occurring on a random day of the week. To see the - time blocks available, see ` Adjusting the Preferred Maintenance - Window`_ in the Amazon RDS User Guide. - - Valid Days: Mon, Tue, Wed, Thu, Fri, Sat, Sun - - Constraints: Minimum 30-minute window. - - :type db_parameter_group_name: string - :param db_parameter_group_name: - The name of the DB parameter group to associate with this DB instance. - If this argument is omitted, the default DBParameterGroup for the - specified engine will be used. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type backup_retention_period: integer - :param backup_retention_period: - The number of days for which automated backups are retained. Setting - this parameter to a positive number enables backups. Setting this - parameter to 0 disables automated backups. - - Default: 1 - - Constraints: - - - + Must be a value from 0 to 8 - + Cannot be set to 0 if the DB instance is a master instance with read - replicas - - :type preferred_backup_window: string - :param preferred_backup_window: The daily time range during which - automated backups are created if automated backups are enabled, - using the `BackupRetentionPeriod` parameter. - Default: A 30-minute window selected at random from an 8-hour block of - time per region. See the Amazon RDS User Guide for the time blocks - for each region from which the default backup windows are assigned. - - Constraints: Must be in the format `hh24:mi-hh24:mi`. Times should be - Universal Time Coordinated (UTC). Must not conflict with the - preferred maintenance window. Must be at least 30 minutes. - - :type port: integer - :param port: The port number on which the database accepts connections. - **MySQL** - - Default: `3306` - - Valid Values: `1150-65535` - - Type: Integer - - **Oracle** - - Default: `1521` - - Valid Values: `1150-65535` - - **SQL Server** - - Default: `1433` - - Valid Values: `1150-65535` except for `1434` and `3389`. - - :type multi_az: boolean - :param multi_az: Specifies if the DB instance is a Multi-AZ deployment. - You cannot set the AvailabilityZone parameter if the MultiAZ - parameter is set to true. - - :type engine_version: string - :param engine_version: The version number of the database engine to - use. - **MySQL** - - Example: `5.1.42` - - Type: String - - **Oracle** - - Example: `11.2.0.2.v2` - - Type: String - - **SQL Server** - - Example: `10.50.2789.0.v1` - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: Indicates that minor engine upgrades - will be applied automatically to the DB instance during the - maintenance window. - Default: `True` - - :type license_model: string - :param license_model: License model information for this DB instance. - Valid values: `license-included` | `bring-your-own-license` | `general- - public-license` - - :type iops: integer - :param iops: The amount of Provisioned IOPS (input/output operations - per second) to be initially allocated for the DB instance. - Constraints: Must be an integer greater than 1000. - - :type option_group_name: string - :param option_group_name: Indicates that the DB instance should be - associated with the specified option group. - Permanent options, such as the TDE option for Oracle Advanced Security - TDE, cannot be removed from an option group, and that option group - cannot be removed from a DB instance once it is associated with a - DB instance - - :type character_set_name: string - :param character_set_name: For supported engines, indicates that the DB - instance should be associated with the specified CharacterSet. - - :type publicly_accessible: boolean - :param publicly_accessible: Specifies the accessibility options for the - DB instance. A value of true specifies an Internet-facing instance - with a publicly resolvable DNS name, which resolves to a public IP - address. A value of false specifies an internal instance with a DNS - name that resolves to a private IP address. - Default: The default behavior varies depending on whether a VPC has - been requested or not. The following list shows the default - behavior in each case. - - - + **Default VPC:**true - + **VPC:**false - - - If no DB subnet group has been specified as part of the request and the - PubliclyAccessible value has not been set, the DB instance will be - publicly accessible. If a specific DB subnet group has been - specified as part of the request and the PubliclyAccessible value - has not been set, the DB instance will be private. - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'DBInstanceIdentifier': db_instance_identifier, - 'AllocatedStorage': allocated_storage, - 'DBInstanceClass': db_instance_class, - 'Engine': engine, - 'MasterUsername': master_username, - 'MasterUserPassword': master_user_password, - } - if db_name is not None: - params['DBName'] = db_name - if db_security_groups is not None: - self.build_list_params(params, - db_security_groups, - 'DBSecurityGroups.member') - if vpc_security_group_ids is not None: - self.build_list_params(params, - vpc_security_group_ids, - 'VpcSecurityGroupIds.member') - if availability_zone is not None: - params['AvailabilityZone'] = availability_zone - if db_subnet_group_name is not None: - params['DBSubnetGroupName'] = db_subnet_group_name - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if db_parameter_group_name is not None: - params['DBParameterGroupName'] = db_parameter_group_name - if backup_retention_period is not None: - params['BackupRetentionPeriod'] = backup_retention_period - if preferred_backup_window is not None: - params['PreferredBackupWindow'] = preferred_backup_window - if port is not None: - params['Port'] = port - if multi_az is not None: - params['MultiAZ'] = str( - multi_az).lower() - if engine_version is not None: - params['EngineVersion'] = engine_version - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - if license_model is not None: - params['LicenseModel'] = license_model - if iops is not None: - params['Iops'] = iops - if option_group_name is not None: - params['OptionGroupName'] = option_group_name - if character_set_name is not None: - params['CharacterSetName'] = character_set_name - if publicly_accessible is not None: - params['PubliclyAccessible'] = str( - publicly_accessible).lower() - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateDBInstance', - verb='POST', - path='/', params=params) - - def create_db_instance_read_replica(self, db_instance_identifier, - source_db_instance_identifier, - db_instance_class=None, - availability_zone=None, port=None, - auto_minor_version_upgrade=None, - iops=None, option_group_name=None, - publicly_accessible=None, tags=None): - """ - Creates a DB instance that acts as a read replica of a source - DB instance. - - All read replica DB instances are created as Single-AZ - deployments with backups disabled. All other DB instance - attributes (including DB security groups and DB parameter - groups) are inherited from the source DB instance, except as - specified below. - - The source DB instance must have backup retention enabled. - - :type db_instance_identifier: string - :param db_instance_identifier: The DB instance identifier of the read - replica. This is the unique key that identifies a DB instance. This - parameter is stored as a lowercase string. - - :type source_db_instance_identifier: string - :param source_db_instance_identifier: The identifier of the DB instance - that will act as the source for the read replica. Each DB instance - can have up to five read replicas. - Constraints: Must be the identifier of an existing DB instance that is - not already a read replica DB instance. - - :type db_instance_class: string - :param db_instance_class: The compute and memory capacity of the read - replica. - Valid Values: `db.m1.small | db.m1.medium | db.m1.large | db.m1.xlarge - | db.m2.xlarge |db.m2.2xlarge | db.m2.4xlarge` - - Default: Inherits from the source DB instance. - - :type availability_zone: string - :param availability_zone: The Amazon EC2 Availability Zone that the - read replica will be created in. - Default: A random, system-chosen Availability Zone in the endpoint's - region. - - Example: `us-east-1d` - - :type port: integer - :param port: The port number that the DB instance uses for connections. - Default: Inherits from the source DB instance - - Valid Values: `1150-65535` - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: Indicates that minor engine upgrades - will be applied automatically to the read replica during the - maintenance window. - Default: Inherits from the source DB instance - - :type iops: integer - :param iops: The amount of Provisioned IOPS (input/output operations - per second) to be initially allocated for the DB instance. - - :type option_group_name: string - :param option_group_name: The option group the DB instance will be - associated with. If omitted, the default option group for the - engine specified will be used. - - :type publicly_accessible: boolean - :param publicly_accessible: Specifies the accessibility options for the - DB instance. A value of true specifies an Internet-facing instance - with a publicly resolvable DNS name, which resolves to a public IP - address. A value of false specifies an internal instance with a DNS - name that resolves to a private IP address. - Default: The default behavior varies depending on whether a VPC has - been requested or not. The following list shows the default - behavior in each case. - - - + **Default VPC:**true - + **VPC:**false - - - If no DB subnet group has been specified as part of the request and the - PubliclyAccessible value has not been set, the DB instance will be - publicly accessible. If a specific DB subnet group has been - specified as part of the request and the PubliclyAccessible value - has not been set, the DB instance will be private. - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'DBInstanceIdentifier': db_instance_identifier, - 'SourceDBInstanceIdentifier': source_db_instance_identifier, - } - if db_instance_class is not None: - params['DBInstanceClass'] = db_instance_class - if availability_zone is not None: - params['AvailabilityZone'] = availability_zone - if port is not None: - params['Port'] = port - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - if iops is not None: - params['Iops'] = iops - if option_group_name is not None: - params['OptionGroupName'] = option_group_name - if publicly_accessible is not None: - params['PubliclyAccessible'] = str( - publicly_accessible).lower() - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateDBInstanceReadReplica', - verb='POST', - path='/', params=params) - - def create_db_parameter_group(self, db_parameter_group_name, - db_parameter_group_family, description, - tags=None): - """ - Creates a new DB parameter group. - - A DB parameter group is initially created with the default - parameters for the database engine used by the DB instance. To - provide custom values for any of the parameters, you must - modify the group after creating it using - ModifyDBParameterGroup . Once you've created a DB parameter - group, you need to associate it with your DB instance using - ModifyDBInstance . When you associate a new DB parameter group - with a running DB instance, you need to reboot the DB Instance - for the new DB parameter group and associated settings to take - effect. - - :type db_parameter_group_name: string - :param db_parameter_group_name: - The name of the DB parameter group. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - - This value is stored as a lower-case string. - - :type db_parameter_group_family: string - :param db_parameter_group_family: The DB parameter group family name. A - DB parameter group can be associated with one and only one DB - parameter group family, and can be applied only to a DB instance - running a database engine and engine version compatible with that - DB parameter group family. - - :type description: string - :param description: The description for the DB parameter group. - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'DBParameterGroupName': db_parameter_group_name, - 'DBParameterGroupFamily': db_parameter_group_family, - 'Description': description, - } - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateDBParameterGroup', - verb='POST', - path='/', params=params) - - def create_db_security_group(self, db_security_group_name, - db_security_group_description, tags=None): - """ - Creates a new DB security group. DB security groups control - access to a DB instance. - - :type db_security_group_name: string - :param db_security_group_name: The name for the DB security group. This - value is stored as a lowercase string. - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - + Must not be "Default" - + May not contain spaces - - - Example: `mysecuritygroup` - - :type db_security_group_description: string - :param db_security_group_description: The description for the DB - security group. - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'DBSecurityGroupName': db_security_group_name, - 'DBSecurityGroupDescription': db_security_group_description, - } - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateDBSecurityGroup', - verb='POST', - path='/', params=params) - - def create_db_snapshot(self, db_snapshot_identifier, - db_instance_identifier, tags=None): - """ - Creates a DBSnapshot. The source DBInstance must be in - "available" state. - - :type db_snapshot_identifier: string - :param db_snapshot_identifier: The identifier for the DB snapshot. - Constraints: - - - + Cannot be null, empty, or blank - + Must contain from 1 to 255 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - - Example: `my-snapshot-id` - - :type db_instance_identifier: string - :param db_instance_identifier: - The DB instance identifier. This is the unique key that identifies a DB - instance. This parameter isn't case sensitive. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'DBSnapshotIdentifier': db_snapshot_identifier, - 'DBInstanceIdentifier': db_instance_identifier, - } - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateDBSnapshot', - verb='POST', - path='/', params=params) - - def create_db_subnet_group(self, db_subnet_group_name, - db_subnet_group_description, subnet_ids, - tags=None): - """ - Creates a new DB subnet group. DB subnet groups must contain - at least one subnet in at least two AZs in the region. - - :type db_subnet_group_name: string - :param db_subnet_group_name: The name for the DB subnet group. This - value is stored as a lowercase string. - Constraints: Must contain no more than 255 alphanumeric characters or - hyphens. Must not be "Default". - - Example: `mySubnetgroup` - - :type db_subnet_group_description: string - :param db_subnet_group_description: The description for the DB subnet - group. - - :type subnet_ids: list - :param subnet_ids: The EC2 Subnet IDs for the DB subnet group. - - :type tags: list - :param tags: A list of tags into tuples. - - """ - params = { - 'DBSubnetGroupName': db_subnet_group_name, - 'DBSubnetGroupDescription': db_subnet_group_description, - } - self.build_list_params(params, - subnet_ids, - 'SubnetIds.member') - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateDBSubnetGroup', - verb='POST', - path='/', params=params) - - def create_event_subscription(self, subscription_name, sns_topic_arn, - source_type=None, event_categories=None, - source_ids=None, enabled=None, tags=None): - """ - Creates an RDS event notification subscription. This action - requires a topic ARN (Amazon Resource Name) created by either - the RDS console, the SNS console, or the SNS API. To obtain an - ARN with SNS, you must create a topic in Amazon SNS and - subscribe to the topic. The ARN is displayed in the SNS - console. - - You can specify the type of source (SourceType) you want to be - notified of, provide a list of RDS sources (SourceIds) that - triggers the events, and provide a list of event categories - (EventCategories) for events you want to be notified of. For - example, you can specify SourceType = db-instance, SourceIds = - mydbinstance1, mydbinstance2 and EventCategories = - Availability, Backup. - - If you specify both the SourceType and SourceIds, such as - SourceType = db-instance and SourceIdentifier = myDBInstance1, - you will be notified of all the db-instance events for the - specified source. If you specify a SourceType but do not - specify a SourceIdentifier, you will receive notice of the - events for that source type for all your RDS sources. If you - do not specify either the SourceType nor the SourceIdentifier, - you will be notified of events generated from all RDS sources - belonging to your customer account. - - :type subscription_name: string - :param subscription_name: The name of the subscription. - Constraints: The name must be less than 255 characters. - - :type sns_topic_arn: string - :param sns_topic_arn: The Amazon Resource Name (ARN) of the SNS topic - created for event notification. The ARN is created by Amazon SNS - when you create a topic and subscribe to it. - - :type source_type: string - :param source_type: The type of source that will be generating the - events. For example, if you want to be notified of events generated - by a DB instance, you would set this parameter to db-instance. if - this value is not specified, all events are returned. - Valid values: db-instance | db-parameter-group | db-security-group | - db-snapshot - - :type event_categories: list - :param event_categories: A list of event categories for a SourceType - that you want to subscribe to. You can see a list of the categories - for a given SourceType in the `Events`_ topic in the Amazon RDS - User Guide or by using the **DescribeEventCategories** action. - - :type source_ids: list - :param source_ids: - The list of identifiers of the event sources for which events will be - returned. If not specified, then all sources are included in the - response. An identifier must begin with a letter and must contain - only ASCII letters, digits, and hyphens; it cannot end with a - hyphen or contain two consecutive hyphens. - - Constraints: - - - + If SourceIds are supplied, SourceType must also be provided. - + If the source type is a DB instance, then a `DBInstanceIdentifier` - must be supplied. - + If the source type is a DB security group, a `DBSecurityGroupName` - must be supplied. - + If the source type is a DB parameter group, a `DBParameterGroupName` - must be supplied. - + If the source type is a DB snapshot, a `DBSnapshotIdentifier` must be - supplied. - - :type enabled: boolean - :param enabled: A Boolean value; set to **true** to activate the - subscription, set to **false** to create the subscription but not - active it. - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'SubscriptionName': subscription_name, - 'SnsTopicArn': sns_topic_arn, - } - if source_type is not None: - params['SourceType'] = source_type - if event_categories is not None: - self.build_list_params(params, - event_categories, - 'EventCategories.member') - if source_ids is not None: - self.build_list_params(params, - source_ids, - 'SourceIds.member') - if enabled is not None: - params['Enabled'] = str( - enabled).lower() - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateEventSubscription', - verb='POST', - path='/', params=params) - - def create_option_group(self, option_group_name, engine_name, - major_engine_version, option_group_description, - tags=None): - """ - Creates a new option group. You can create up to 20 option - groups. - - :type option_group_name: string - :param option_group_name: Specifies the name of the option group to be - created. - Constraints: - - - + Must be 1 to 255 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - - Example: `myoptiongroup` - - :type engine_name: string - :param engine_name: Specifies the name of the engine that this option - group should be associated with. - - :type major_engine_version: string - :param major_engine_version: Specifies the major version of the engine - that this option group should be associated with. - - :type option_group_description: string - :param option_group_description: The description of the option group. - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'OptionGroupName': option_group_name, - 'EngineName': engine_name, - 'MajorEngineVersion': major_engine_version, - 'OptionGroupDescription': option_group_description, - } - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='CreateOptionGroup', - verb='POST', - path='/', params=params) - - def delete_db_instance(self, db_instance_identifier, - skip_final_snapshot=None, - final_db_snapshot_identifier=None): - """ - The DeleteDBInstance action deletes a previously provisioned - DB instance. A successful response from the web service - indicates the request was received correctly. When you delete - a DB instance, all automated backups for that instance are - deleted and cannot be recovered. Manual DB snapshots of the DB - instance to be deleted are not deleted. - - If a final DB snapshot is requested the status of the RDS - instance will be "deleting" until the DB snapshot is created. - The API action `DescribeDBInstance` is used to monitor the - status of this operation. The action cannot be canceled or - reverted once submitted. - - :type db_instance_identifier: string - :param db_instance_identifier: - The DB instance identifier for the DB instance to be deleted. This - parameter isn't case sensitive. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type skip_final_snapshot: boolean - :param skip_final_snapshot: Determines whether a final DB snapshot is - created before the DB instance is deleted. If `True` is specified, - no DBSnapshot is created. If false is specified, a DB snapshot is - created before the DB instance is deleted. - The FinalDBSnapshotIdentifier parameter must be specified if - SkipFinalSnapshot is `False`. - - Default: `False` - - :type final_db_snapshot_identifier: string - :param final_db_snapshot_identifier: - The DBSnapshotIdentifier of the new DBSnapshot created when - SkipFinalSnapshot is set to `False`. - - Specifying this parameter and also setting the SkipFinalShapshot - parameter to true results in an error. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - """ - params = {'DBInstanceIdentifier': db_instance_identifier, } - if skip_final_snapshot is not None: - params['SkipFinalSnapshot'] = str( - skip_final_snapshot).lower() - if final_db_snapshot_identifier is not None: - params['FinalDBSnapshotIdentifier'] = final_db_snapshot_identifier - return self._make_request( - action='DeleteDBInstance', - verb='POST', - path='/', params=params) - - def delete_db_parameter_group(self, db_parameter_group_name): - """ - Deletes a specified DBParameterGroup. The DBParameterGroup - cannot be associated with any RDS instances to be deleted. - The specified DB parameter group cannot be associated with any - DB instances. - - :type db_parameter_group_name: string - :param db_parameter_group_name: - The name of the DB parameter group. - - Constraints: - - - + Must be the name of an existing DB parameter group - + You cannot delete a default DB parameter group - + Cannot be associated with any DB instances - - """ - params = {'DBParameterGroupName': db_parameter_group_name, } - return self._make_request( - action='DeleteDBParameterGroup', - verb='POST', - path='/', params=params) - - def delete_db_security_group(self, db_security_group_name): - """ - Deletes a DB security group. - The specified DB security group must not be associated with - any DB instances. - - :type db_security_group_name: string - :param db_security_group_name: - The name of the DB security group to delete. - - You cannot delete the default DB security group. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - + Must not be "Default" - + May not contain spaces - - """ - params = {'DBSecurityGroupName': db_security_group_name, } - return self._make_request( - action='DeleteDBSecurityGroup', - verb='POST', - path='/', params=params) - - def delete_db_snapshot(self, db_snapshot_identifier): - """ - Deletes a DBSnapshot. - The DBSnapshot must be in the `available` state to be deleted. - - :type db_snapshot_identifier: string - :param db_snapshot_identifier: The DBSnapshot identifier. - Constraints: Must be the name of an existing DB snapshot in the - `available` state. - - """ - params = {'DBSnapshotIdentifier': db_snapshot_identifier, } - return self._make_request( - action='DeleteDBSnapshot', - verb='POST', - path='/', params=params) - - def delete_db_subnet_group(self, db_subnet_group_name): - """ - Deletes a DB subnet group. - The specified database subnet group must not be associated - with any DB instances. - - :type db_subnet_group_name: string - :param db_subnet_group_name: - The name of the database subnet group to delete. - - You cannot delete the default subnet group. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - """ - params = {'DBSubnetGroupName': db_subnet_group_name, } - return self._make_request( - action='DeleteDBSubnetGroup', - verb='POST', - path='/', params=params) - - def delete_event_subscription(self, subscription_name): - """ - Deletes an RDS event notification subscription. - - :type subscription_name: string - :param subscription_name: The name of the RDS event notification - subscription you want to delete. - - """ - params = {'SubscriptionName': subscription_name, } - return self._make_request( - action='DeleteEventSubscription', - verb='POST', - path='/', params=params) - - def delete_option_group(self, option_group_name): - """ - Deletes an existing option group. - - :type option_group_name: string - :param option_group_name: - The name of the option group to be deleted. - - You cannot delete default option groups. - - """ - params = {'OptionGroupName': option_group_name, } - return self._make_request( - action='DeleteOptionGroup', - verb='POST', - path='/', params=params) - - def describe_db_engine_versions(self, engine=None, engine_version=None, - db_parameter_group_family=None, - max_records=None, marker=None, - default_only=None, - list_supported_character_sets=None): - """ - Returns a list of the available DB engines. - - :type engine: string - :param engine: The database engine to return. - - :type engine_version: string - :param engine_version: The database engine version to return. - Example: `5.1.49` - - :type db_parameter_group_family: string - :param db_parameter_group_family: - The name of a specific DB parameter group family to return details for. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more than the `MaxRecords` value is available, a - pagination token called a marker is included in the response so - that the following results can be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - request. If this parameter is specified, the response includes only - records beyond the marker, up to the value specified by - `MaxRecords`. - - :type default_only: boolean - :param default_only: Indicates that only the default version of the - specified engine or engine and major version combination is - returned. - - :type list_supported_character_sets: boolean - :param list_supported_character_sets: If this parameter is specified, - and if the requested engine supports the CharacterSetName parameter - for CreateDBInstance, the response includes a list of supported - character sets for each engine version. - - """ - params = {} - if engine is not None: - params['Engine'] = engine - if engine_version is not None: - params['EngineVersion'] = engine_version - if db_parameter_group_family is not None: - params['DBParameterGroupFamily'] = db_parameter_group_family - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - if default_only is not None: - params['DefaultOnly'] = str( - default_only).lower() - if list_supported_character_sets is not None: - params['ListSupportedCharacterSets'] = str( - list_supported_character_sets).lower() - return self._make_request( - action='DescribeDBEngineVersions', - verb='POST', - path='/', params=params) - - def describe_db_instances(self, db_instance_identifier=None, - filters=None, max_records=None, marker=None): - """ - Returns information about provisioned RDS instances. This API - supports pagination. - - :type db_instance_identifier: string - :param db_instance_identifier: - The user-supplied instance identifier. If this parameter is specified, - information from only the specific DB instance is returned. This - parameter isn't case sensitive. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type filters: list - :param filters: - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - DescribeDBInstances request. If this parameter is specified, the - response includes only records beyond the marker, up to the value - specified by `MaxRecords` . - - """ - params = {} - if db_instance_identifier is not None: - params['DBInstanceIdentifier'] = db_instance_identifier - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDBInstances', - verb='POST', - path='/', params=params) - - def describe_db_log_files(self, db_instance_identifier, - filename_contains=None, file_last_written=None, - file_size=None, max_records=None, marker=None): - """ - Returns a list of DB log files for the DB instance. - - :type db_instance_identifier: string - :param db_instance_identifier: - The customer-assigned name of the DB instance that contains the log - files you want to list. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type filename_contains: string - :param filename_contains: Filters the available log files for log file - names that contain the specified string. - - :type file_last_written: long - :param file_last_written: Filters the available log files for files - written since the specified date, in POSIX timestamp format. - - :type file_size: long - :param file_size: Filters the available log files for files larger than - the specified size. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified MaxRecords - value, a pagination token called a marker is included in the - response so that the remaining results can be retrieved. - - :type marker: string - :param marker: The pagination token provided in the previous request. - If this parameter is specified the response includes only records - beyond the marker, up to MaxRecords. - - """ - params = {'DBInstanceIdentifier': db_instance_identifier, } - if filename_contains is not None: - params['FilenameContains'] = filename_contains - if file_last_written is not None: - params['FileLastWritten'] = file_last_written - if file_size is not None: - params['FileSize'] = file_size - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDBLogFiles', - verb='POST', - path='/', params=params) - - def describe_db_parameter_groups(self, db_parameter_group_name=None, - filters=None, max_records=None, - marker=None): - """ - Returns a list of `DBParameterGroup` descriptions. If a - `DBParameterGroupName` is specified, the list will contain - only the description of the specified DB parameter group. - - :type db_parameter_group_name: string - :param db_parameter_group_name: - The name of a specific DB parameter group to return details for. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type filters: list - :param filters: - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - `DescribeDBParameterGroups` request. If this parameter is - specified, the response includes only records beyond the marker, up - to the value specified by `MaxRecords`. - - """ - params = {} - if db_parameter_group_name is not None: - params['DBParameterGroupName'] = db_parameter_group_name - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDBParameterGroups', - verb='POST', - path='/', params=params) - - def describe_db_parameters(self, db_parameter_group_name, source=None, - max_records=None, marker=None): - """ - Returns the detailed parameter list for a particular DB - parameter group. - - :type db_parameter_group_name: string - :param db_parameter_group_name: - The name of a specific DB parameter group to return details for. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type source: string - :param source: The parameter types to return. - Default: All parameter types returned - - Valid Values: `user | system | engine-default` - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - `DescribeDBParameters` request. If this parameter is specified, the - response includes only records beyond the marker, up to the value - specified by `MaxRecords`. - - """ - params = {'DBParameterGroupName': db_parameter_group_name, } - if source is not None: - params['Source'] = source - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDBParameters', - verb='POST', - path='/', params=params) - - def describe_db_security_groups(self, db_security_group_name=None, - filters=None, max_records=None, - marker=None): - """ - Returns a list of `DBSecurityGroup` descriptions. If a - `DBSecurityGroupName` is specified, the list will contain only - the descriptions of the specified DB security group. - - :type db_security_group_name: string - :param db_security_group_name: The name of the DB security group to - return details for. - - :type filters: list - :param filters: - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - DescribeDBSecurityGroups request. If this parameter is specified, - the response includes only records beyond the marker, up to the - value specified by `MaxRecords`. - - """ - params = {} - if db_security_group_name is not None: - params['DBSecurityGroupName'] = db_security_group_name - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDBSecurityGroups', - verb='POST', - path='/', params=params) - - def describe_db_snapshots(self, db_instance_identifier=None, - db_snapshot_identifier=None, - snapshot_type=None, filters=None, - max_records=None, marker=None): - """ - Returns information about DB snapshots. This API supports - pagination. - - :type db_instance_identifier: string - :param db_instance_identifier: - A DB instance identifier to retrieve the list of DB snapshots for. - Cannot be used in conjunction with `DBSnapshotIdentifier`. This - parameter is not case sensitive. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type db_snapshot_identifier: string - :param db_snapshot_identifier: - A specific DB snapshot identifier to describe. Cannot be used in - conjunction with `DBInstanceIdentifier`. This value is stored as a - lowercase string. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - + If this is the identifier of an automated snapshot, the - `SnapshotType` parameter must also be specified. - - :type snapshot_type: string - :param snapshot_type: The type of snapshots that will be returned. - Values can be "automated" or "manual." If not specified, the - returned results will include all snapshots types. - - :type filters: list - :param filters: - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - `DescribeDBSnapshots` request. If this parameter is specified, the - response includes only records beyond the marker, up to the value - specified by `MaxRecords`. - - """ - params = {} - if db_instance_identifier is not None: - params['DBInstanceIdentifier'] = db_instance_identifier - if db_snapshot_identifier is not None: - params['DBSnapshotIdentifier'] = db_snapshot_identifier - if snapshot_type is not None: - params['SnapshotType'] = snapshot_type - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDBSnapshots', - verb='POST', - path='/', params=params) - - def describe_db_subnet_groups(self, db_subnet_group_name=None, - filters=None, max_records=None, - marker=None): - """ - Returns a list of DBSubnetGroup descriptions. If a - DBSubnetGroupName is specified, the list will contain only the - descriptions of the specified DBSubnetGroup. - - For an overview of CIDR ranges, go to the `Wikipedia - Tutorial`_. - - :type db_subnet_group_name: string - :param db_subnet_group_name: The name of the DB subnet group to return - details for. - - :type filters: list - :param filters: - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - DescribeDBSubnetGroups request. If this parameter is specified, the - response includes only records beyond the marker, up to the value - specified by `MaxRecords`. - - """ - params = {} - if db_subnet_group_name is not None: - params['DBSubnetGroupName'] = db_subnet_group_name - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDBSubnetGroups', - verb='POST', - path='/', params=params) - - def describe_engine_default_parameters(self, db_parameter_group_family, - max_records=None, marker=None): - """ - Returns the default engine and system parameter information - for the specified database engine. - - :type db_parameter_group_family: string - :param db_parameter_group_family: The name of the DB parameter group - family. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - `DescribeEngineDefaultParameters` request. If this parameter is - specified, the response includes only records beyond the marker, up - to the value specified by `MaxRecords`. - - """ - params = { - 'DBParameterGroupFamily': db_parameter_group_family, - } - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeEngineDefaultParameters', - verb='POST', - path='/', params=params) - - def describe_event_categories(self, source_type=None): - """ - Displays a list of categories for all event source types, or, - if specified, for a specified source type. You can see a list - of the event categories and source types in the ` Events`_ - topic in the Amazon RDS User Guide. - - :type source_type: string - :param source_type: The type of source that will be generating the - events. - Valid values: db-instance | db-parameter-group | db-security-group | - db-snapshot - - """ - params = {} - if source_type is not None: - params['SourceType'] = source_type - return self._make_request( - action='DescribeEventCategories', - verb='POST', - path='/', params=params) - - def describe_event_subscriptions(self, subscription_name=None, - filters=None, max_records=None, - marker=None): - """ - Lists all the subscription descriptions for a customer - account. The description for a subscription includes - SubscriptionName, SNSTopicARN, CustomerID, SourceType, - SourceID, CreationTime, and Status. - - If you specify a SubscriptionName, lists the description for - that subscription. - - :type subscription_name: string - :param subscription_name: The name of the RDS event notification - subscription you want to describe. - - :type filters: list - :param filters: - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results can be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - DescribeOrderableDBInstanceOptions request. If this parameter is - specified, the response includes only records beyond the marker, up - to the value specified by `MaxRecords` . - - """ - params = {} - if subscription_name is not None: - params['SubscriptionName'] = subscription_name - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeEventSubscriptions', - verb='POST', - path='/', params=params) - - def describe_events(self, source_identifier=None, source_type=None, - start_time=None, end_time=None, duration=None, - event_categories=None, max_records=None, marker=None): - """ - Returns events related to DB instances, DB security groups, DB - snapshots, and DB parameter groups for the past 14 days. - Events specific to a particular DB instance, DB security - group, database snapshot, or DB parameter group can be - obtained by providing the name as a parameter. By default, the - past hour of events are returned. - - :type source_identifier: string - :param source_identifier: - The identifier of the event source for which events will be returned. - If not specified, then all sources are included in the response. - - Constraints: - - - + If SourceIdentifier is supplied, SourceType must also be provided. - + If the source type is `DBInstance`, then a `DBInstanceIdentifier` - must be supplied. - + If the source type is `DBSecurityGroup`, a `DBSecurityGroupName` must - be supplied. - + If the source type is `DBParameterGroup`, a `DBParameterGroupName` - must be supplied. - + If the source type is `DBSnapshot`, a `DBSnapshotIdentifier` must be - supplied. - + Cannot end with a hyphen or contain two consecutive hyphens. - - :type source_type: string - :param source_type: The event source to retrieve events for. If no - value is specified, all events are returned. - - :type start_time: timestamp - :param start_time: The beginning of the time interval to retrieve - events for, specified in ISO 8601 format. For more information - about ISO 8601, go to the `ISO8601 Wikipedia page.`_ - Example: 2009-07-08T18:00Z - - :type end_time: timestamp - :param end_time: The end of the time interval for which to retrieve - events, specified in ISO 8601 format. For more information about - ISO 8601, go to the `ISO8601 Wikipedia page.`_ - Example: 2009-07-08T18:00Z - - :type duration: integer - :param duration: The number of minutes to retrieve events for. - Default: 60 - - :type event_categories: list - :param event_categories: A list of event categories that trigger - notifications for a event notification subscription. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results may be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - DescribeEvents request. If this parameter is specified, the - response includes only records beyond the marker, up to the value - specified by `MaxRecords`. - - """ - params = {} - if source_identifier is not None: - params['SourceIdentifier'] = source_identifier - if source_type is not None: - params['SourceType'] = source_type - if start_time is not None: - params['StartTime'] = start_time - if end_time is not None: - params['EndTime'] = end_time - if duration is not None: - params['Duration'] = duration - if event_categories is not None: - self.build_list_params(params, - event_categories, - 'EventCategories.member') - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeEvents', - verb='POST', - path='/', params=params) - - def describe_option_group_options(self, engine_name, - major_engine_version=None, - max_records=None, marker=None): - """ - Describes all available options. - - :type engine_name: string - :param engine_name: A required parameter. Options available for the - given Engine name will be described. - - :type major_engine_version: string - :param major_engine_version: If specified, filters the results to - include only options for the specified major engine version. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results can be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - request. If this parameter is specified, the response includes only - records beyond the marker, up to the value specified by - `MaxRecords`. - - """ - params = {'EngineName': engine_name, } - if major_engine_version is not None: - params['MajorEngineVersion'] = major_engine_version - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeOptionGroupOptions', - verb='POST', - path='/', params=params) - - def describe_option_groups(self, option_group_name=None, filters=None, - marker=None, max_records=None, - engine_name=None, major_engine_version=None): - """ - Describes the available option groups. - - :type option_group_name: string - :param option_group_name: The name of the option group to describe. - Cannot be supplied together with EngineName or MajorEngineVersion. - - :type filters: list - :param filters: - - :type marker: string - :param marker: An optional pagination token provided by a previous - DescribeOptionGroups request. If this parameter is specified, the - response includes only records beyond the marker, up to the value - specified by `MaxRecords`. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results can be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type engine_name: string - :param engine_name: Filters the list of option groups to only include - groups associated with a specific database engine. - - :type major_engine_version: string - :param major_engine_version: Filters the list of option groups to only - include groups associated with a specific database engine version. - If specified, then EngineName must also be specified. - - """ - params = {} - if option_group_name is not None: - params['OptionGroupName'] = option_group_name - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if marker is not None: - params['Marker'] = marker - if max_records is not None: - params['MaxRecords'] = max_records - if engine_name is not None: - params['EngineName'] = engine_name - if major_engine_version is not None: - params['MajorEngineVersion'] = major_engine_version - return self._make_request( - action='DescribeOptionGroups', - verb='POST', - path='/', params=params) - - def describe_orderable_db_instance_options(self, engine, - engine_version=None, - db_instance_class=None, - license_model=None, vpc=None, - max_records=None, marker=None): - """ - Returns a list of orderable DB instance options for the - specified engine. - - :type engine: string - :param engine: The name of the engine to retrieve DB instance options - for. - - :type engine_version: string - :param engine_version: The engine version filter value. Specify this - parameter to show only the available offerings matching the - specified engine version. - - :type db_instance_class: string - :param db_instance_class: The DB instance class filter value. Specify - this parameter to show only the available offerings matching the - specified DB instance class. - - :type license_model: string - :param license_model: The license model filter value. Specify this - parameter to show only the available offerings matching the - specified license model. - - :type vpc: boolean - :param vpc: The VPC filter value. Specify this parameter to show only - the available VPC or non-VPC offerings. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more records exist than the specified `MaxRecords` - value, a pagination token called a marker is included in the - response so that the remaining results can be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - DescribeOrderableDBInstanceOptions request. If this parameter is - specified, the response includes only records beyond the marker, up - to the value specified by `MaxRecords` . - - """ - params = {'Engine': engine, } - if engine_version is not None: - params['EngineVersion'] = engine_version - if db_instance_class is not None: - params['DBInstanceClass'] = db_instance_class - if license_model is not None: - params['LicenseModel'] = license_model - if vpc is not None: - params['Vpc'] = str( - vpc).lower() - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeOrderableDBInstanceOptions', - verb='POST', - path='/', params=params) - - def describe_reserved_db_instances(self, reserved_db_instance_id=None, - reserved_db_instances_offering_id=None, - db_instance_class=None, duration=None, - product_description=None, - offering_type=None, multi_az=None, - filters=None, max_records=None, - marker=None): - """ - Returns information about reserved DB instances for this - account, or about a specified reserved DB instance. - - :type reserved_db_instance_id: string - :param reserved_db_instance_id: The reserved DB instance identifier - filter value. Specify this parameter to show only the reservation - that matches the specified reservation ID. - - :type reserved_db_instances_offering_id: string - :param reserved_db_instances_offering_id: The offering identifier - filter value. Specify this parameter to show only purchased - reservations matching the specified offering identifier. - - :type db_instance_class: string - :param db_instance_class: The DB instance class filter value. Specify - this parameter to show only those reservations matching the - specified DB instances class. - - :type duration: string - :param duration: The duration filter value, specified in years or - seconds. Specify this parameter to show only reservations for this - duration. - Valid Values: `1 | 3 | 31536000 | 94608000` - - :type product_description: string - :param product_description: The product description filter value. - Specify this parameter to show only those reservations matching the - specified product description. - - :type offering_type: string - :param offering_type: The offering type filter value. Specify this - parameter to show only the available offerings matching the - specified offering type. - Valid Values: `"Light Utilization" | "Medium Utilization" | "Heavy - Utilization" ` - - :type multi_az: boolean - :param multi_az: The Multi-AZ filter value. Specify this parameter to - show only those reservations matching the specified Multi-AZ - parameter. - - :type filters: list - :param filters: - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more than the `MaxRecords` value is available, a - pagination token called a marker is included in the response so - that the following results can be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - request. If this parameter is specified, the response includes only - records beyond the marker, up to the value specified by - `MaxRecords`. - - """ - params = {} - if reserved_db_instance_id is not None: - params['ReservedDBInstanceId'] = reserved_db_instance_id - if reserved_db_instances_offering_id is not None: - params['ReservedDBInstancesOfferingId'] = reserved_db_instances_offering_id - if db_instance_class is not None: - params['DBInstanceClass'] = db_instance_class - if duration is not None: - params['Duration'] = duration - if product_description is not None: - params['ProductDescription'] = product_description - if offering_type is not None: - params['OfferingType'] = offering_type - if multi_az is not None: - params['MultiAZ'] = str( - multi_az).lower() - if filters is not None: - self.build_complex_list_params( - params, filters, - 'Filters.member', - ('FilterName', 'FilterValue')) - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeReservedDBInstances', - verb='POST', - path='/', params=params) - - def describe_reserved_db_instances_offerings(self, - reserved_db_instances_offering_id=None, - db_instance_class=None, - duration=None, - product_description=None, - offering_type=None, - multi_az=None, - max_records=None, - marker=None): - """ - Lists available reserved DB instance offerings. - - :type reserved_db_instances_offering_id: string - :param reserved_db_instances_offering_id: The offering identifier - filter value. Specify this parameter to show only the available - offering that matches the specified reservation identifier. - Example: `438012d3-4052-4cc7-b2e3-8d3372e0e706` - - :type db_instance_class: string - :param db_instance_class: The DB instance class filter value. Specify - this parameter to show only the available offerings matching the - specified DB instance class. - - :type duration: string - :param duration: Duration filter value, specified in years or seconds. - Specify this parameter to show only reservations for this duration. - Valid Values: `1 | 3 | 31536000 | 94608000` - - :type product_description: string - :param product_description: Product description filter value. Specify - this parameter to show only the available offerings matching the - specified product description. - - :type offering_type: string - :param offering_type: The offering type filter value. Specify this - parameter to show only the available offerings matching the - specified offering type. - Valid Values: `"Light Utilization" | "Medium Utilization" | "Heavy - Utilization" ` - - :type multi_az: boolean - :param multi_az: The Multi-AZ filter value. Specify this parameter to - show only the available offerings matching the specified Multi-AZ - parameter. - - :type max_records: integer - :param max_records: The maximum number of records to include in the - response. If more than the `MaxRecords` value is available, a - pagination token called a marker is included in the response so - that the following results can be retrieved. - Default: 100 - - Constraints: minimum 20, maximum 100 - - :type marker: string - :param marker: An optional pagination token provided by a previous - request. If this parameter is specified, the response includes only - records beyond the marker, up to the value specified by - `MaxRecords`. - - """ - params = {} - if reserved_db_instances_offering_id is not None: - params['ReservedDBInstancesOfferingId'] = reserved_db_instances_offering_id - if db_instance_class is not None: - params['DBInstanceClass'] = db_instance_class - if duration is not None: - params['Duration'] = duration - if product_description is not None: - params['ProductDescription'] = product_description - if offering_type is not None: - params['OfferingType'] = offering_type - if multi_az is not None: - params['MultiAZ'] = str( - multi_az).lower() - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeReservedDBInstancesOfferings', - verb='POST', - path='/', params=params) - - def download_db_log_file_portion(self, db_instance_identifier, - log_file_name, marker=None, - number_of_lines=None): - """ - Downloads the last line of the specified log file. - - :type db_instance_identifier: string - :param db_instance_identifier: - The customer-assigned name of the DB instance that contains the log - files you want to list. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type log_file_name: string - :param log_file_name: The name of the log file to be downloaded. - - :type marker: string - :param marker: The pagination token provided in the previous request. - If this parameter is specified the response includes only records - beyond the marker, up to MaxRecords. - - :type number_of_lines: integer - :param number_of_lines: The number of lines remaining to be downloaded. - - """ - params = { - 'DBInstanceIdentifier': db_instance_identifier, - 'LogFileName': log_file_name, - } - if marker is not None: - params['Marker'] = marker - if number_of_lines is not None: - params['NumberOfLines'] = number_of_lines - return self._make_request( - action='DownloadDBLogFilePortion', - verb='POST', - path='/', params=params) - - def list_tags_for_resource(self, resource_name): - """ - Lists all tags on an Amazon RDS resource. - - For an overview on tagging an Amazon RDS resource, see - `Tagging Amazon RDS Resources`_. - - :type resource_name: string - :param resource_name: The Amazon RDS resource with tags to be listed. - This value is an Amazon Resource Name (ARN). For information about - creating an ARN, see ` Constructing an RDS Amazon Resource Name - (ARN)`_. - - """ - params = {'ResourceName': resource_name, } - return self._make_request( - action='ListTagsForResource', - verb='POST', - path='/', params=params) - - def modify_db_instance(self, db_instance_identifier, - allocated_storage=None, db_instance_class=None, - db_security_groups=None, - vpc_security_group_ids=None, - apply_immediately=None, master_user_password=None, - db_parameter_group_name=None, - backup_retention_period=None, - preferred_backup_window=None, - preferred_maintenance_window=None, multi_az=None, - engine_version=None, - allow_major_version_upgrade=None, - auto_minor_version_upgrade=None, iops=None, - option_group_name=None, - new_db_instance_identifier=None): - """ - Modify settings for a DB instance. You can change one or more - database configuration parameters by specifying these - parameters and the new values in the request. - - :type db_instance_identifier: string - :param db_instance_identifier: - The DB instance identifier. This value is stored as a lowercase string. - - Constraints: - - - + Must be the identifier for an existing DB instance - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type allocated_storage: integer - :param allocated_storage: The new storage capacity of the RDS instance. - Changing this parameter does not result in an outage and the change - is applied during the next maintenance window unless the - `ApplyImmediately` parameter is set to `True` for this request. - **MySQL** - - Default: Uses existing setting - - Valid Values: 5-1024 - - Constraints: Value supplied must be at least 10% greater than the - current value. Values that are not at least 10% greater than the - existing value are rounded up so that they are 10% greater than the - current value. - - Type: Integer - - **Oracle** - - Default: Uses existing setting - - Valid Values: 10-1024 - - Constraints: Value supplied must be at least 10% greater than the - current value. Values that are not at least 10% greater than the - existing value are rounded up so that they are 10% greater than the - current value. - - **SQL Server** - - Cannot be modified. - - If you choose to migrate your DB instance from using standard storage - to using Provisioned IOPS, or from using Provisioned IOPS to using - standard storage, the process can take time. The duration of the - migration depends on several factors such as database load, storage - size, storage type (standard or Provisioned IOPS), amount of IOPS - provisioned (if any), and the number of prior scale storage - operations. Typical migration times are under 24 hours, but the - process can take up to several days in some cases. During the - migration, the DB instance will be available for use, but may - experience performance degradation. While the migration takes - place, nightly backups for the instance will be suspended. No other - Amazon RDS operations can take place for the instance, including - modifying the instance, rebooting the instance, deleting the - instance, creating a read replica for the instance, and creating a - DB snapshot of the instance. - - :type db_instance_class: string - :param db_instance_class: The new compute and memory capacity of the DB - instance. To determine the instance classes that are available for - a particular DB engine, use the DescribeOrderableDBInstanceOptions - action. - Passing a value for this parameter causes an outage during the change - and is applied during the next maintenance window, unless the - `ApplyImmediately` parameter is specified as `True` for this - request. - - Default: Uses existing setting - - Valid Values: `db.t1.micro | db.m1.small | db.m1.medium | db.m1.large | - db.m1.xlarge | db.m2.xlarge | db.m2.2xlarge | db.m2.4xlarge` - - :type db_security_groups: list - :param db_security_groups: - A list of DB security groups to authorize on this DB instance. Changing - this parameter does not result in an outage and the change is - asynchronously applied as soon as possible. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type vpc_security_group_ids: list - :param vpc_security_group_ids: - A list of EC2 VPC security groups to authorize on this DB instance. - This change is asynchronously applied as soon as possible. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type apply_immediately: boolean - :param apply_immediately: Specifies whether or not the modifications in - this request and any pending modifications are asynchronously - applied as soon as possible, regardless of the - `PreferredMaintenanceWindow` setting for the DB instance. - If this parameter is passed as `False`, changes to the DB instance are - applied on the next call to RebootDBInstance, the next maintenance - reboot, or the next failure reboot, whichever occurs first. See - each parameter to determine when a change is applied. - - Default: `False` - - :type master_user_password: string - :param master_user_password: - The new password for the DB instance master user. Can be any printable - ASCII character except "/", '"', or "@". - - Changing this parameter does not result in an outage and the change is - asynchronously applied as soon as possible. Between the time of the - request and the completion of the request, the `MasterUserPassword` - element exists in the `PendingModifiedValues` element of the - operation response. - - Default: Uses existing setting - - Constraints: Must be 8 to 41 alphanumeric characters (MySQL), 8 to 30 - alphanumeric characters (Oracle), or 8 to 128 alphanumeric - characters (SQL Server). - - Amazon RDS API actions never return the password, so this action - provides a way to regain access to a master instance user if the - password is lost. - - :type db_parameter_group_name: string - :param db_parameter_group_name: The name of the DB parameter group to - apply to this DB instance. Changing this parameter does not result - in an outage and the change is applied during the next maintenance - window unless the `ApplyImmediately` parameter is set to `True` for - this request. - Default: Uses existing setting - - Constraints: The DB parameter group must be in the same DB parameter - group family as this DB instance. - - :type backup_retention_period: integer - :param backup_retention_period: - The number of days to retain automated backups. Setting this parameter - to a positive number enables backups. Setting this parameter to 0 - disables automated backups. - - Changing this parameter can result in an outage if you change from 0 to - a non-zero value or from a non-zero value to 0. These changes are - applied during the next maintenance window unless the - `ApplyImmediately` parameter is set to `True` for this request. If - you change the parameter from one non-zero value to another non- - zero value, the change is asynchronously applied as soon as - possible. - - Default: Uses existing setting - - Constraints: - - - + Must be a value from 0 to 8 - + Cannot be set to 0 if the DB instance is a master instance with read - replicas or if the DB instance is a read replica - - :type preferred_backup_window: string - :param preferred_backup_window: - The daily time range during which automated backups are created if - automated backups are enabled, as determined by the - `BackupRetentionPeriod`. Changing this parameter does not result in - an outage and the change is asynchronously applied as soon as - possible. - - Constraints: - - - + Must be in the format hh24:mi-hh24:mi - + Times should be Universal Time Coordinated (UTC) - + Must not conflict with the preferred maintenance window - + Must be at least 30 minutes - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which system maintenance can occur, which may result in an - outage. Changing this parameter does not result in an outage, - except in the following situation, and the change is asynchronously - applied as soon as possible. If there are pending actions that - cause a reboot, and the maintenance window is changed to include - the current time, then changing this parameter will cause a reboot - of the DB instance. If moving this window to the current time, - there must be at least 30 minutes between the current time and end - of the window to ensure pending changes are applied. - Default: Uses existing setting - - Format: ddd:hh24:mi-ddd:hh24:mi - - Valid Days: Mon | Tue | Wed | Thu | Fri | Sat | Sun - - Constraints: Must be at least 30 minutes - - :type multi_az: boolean - :param multi_az: Specifies if the DB instance is a Multi-AZ deployment. - Changing this parameter does not result in an outage and the change - is applied during the next maintenance window unless the - `ApplyImmediately` parameter is set to `True` for this request. - Constraints: Cannot be specified if the DB instance is a read replica. - - :type engine_version: string - :param engine_version: The version number of the database engine to - upgrade to. Changing this parameter results in an outage and the - change is applied during the next maintenance window unless the - `ApplyImmediately` parameter is set to `True` for this request. - For major version upgrades, if a non-default DB parameter group is - currently in use, a new DB parameter group in the DB parameter - group family for the new engine version must be specified. The new - DB parameter group can be the default for that DB parameter group - family. - - Example: `5.1.42` - - :type allow_major_version_upgrade: boolean - :param allow_major_version_upgrade: Indicates that major version - upgrades are allowed. Changing this parameter does not result in an - outage and the change is asynchronously applied as soon as - possible. - Constraints: This parameter must be set to true when specifying a value - for the EngineVersion parameter that is a different major version - than the DB instance's current version. - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: Indicates that minor version - upgrades will be applied automatically to the DB instance during - the maintenance window. Changing this parameter does not result in - an outage except in the following case and the change is - asynchronously applied as soon as possible. An outage will result - if this parameter is set to `True` during the maintenance window, - and a newer minor version is available, and RDS has enabled auto - patching for that engine version. - - :type iops: integer - :param iops: The new Provisioned IOPS (I/O operations per second) value - for the RDS instance. Changing this parameter does not result in an - outage and the change is applied during the next maintenance window - unless the `ApplyImmediately` parameter is set to `True` for this - request. - Default: Uses existing setting - - Constraints: Value supplied must be at least 10% greater than the - current value. Values that are not at least 10% greater than the - existing value are rounded up so that they are 10% greater than the - current value. - - Type: Integer - - If you choose to migrate your DB instance from using standard storage - to using Provisioned IOPS, or from using Provisioned IOPS to using - standard storage, the process can take time. The duration of the - migration depends on several factors such as database load, storage - size, storage type (standard or Provisioned IOPS), amount of IOPS - provisioned (if any), and the number of prior scale storage - operations. Typical migration times are under 24 hours, but the - process can take up to several days in some cases. During the - migration, the DB instance will be available for use, but may - experience performance degradation. While the migration takes - place, nightly backups for the instance will be suspended. No other - Amazon RDS operations can take place for the instance, including - modifying the instance, rebooting the instance, deleting the - instance, creating a read replica for the instance, and creating a - DB snapshot of the instance. - - :type option_group_name: string - :param option_group_name: Indicates that the DB instance should be - associated with the specified option group. Changing this parameter - does not result in an outage except in the following case and the - change is applied during the next maintenance window unless the - `ApplyImmediately` parameter is set to `True` for this request. If - the parameter change results in an option group that enables OEM, - this change can cause a brief (sub-second) period during which new - connections are rejected but existing connections are not - interrupted. - Permanent options, such as the TDE option for Oracle Advanced Security - TDE, cannot be removed from an option group, and that option group - cannot be removed from a DB instance once it is associated with a - DB instance - - :type new_db_instance_identifier: string - :param new_db_instance_identifier: - The new DB instance identifier for the DB instance when renaming a DB - Instance. This value is stored as a lowercase string. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - """ - params = {'DBInstanceIdentifier': db_instance_identifier, } - if allocated_storage is not None: - params['AllocatedStorage'] = allocated_storage - if db_instance_class is not None: - params['DBInstanceClass'] = db_instance_class - if db_security_groups is not None: - self.build_list_params(params, - db_security_groups, - 'DBSecurityGroups.member') - if vpc_security_group_ids is not None: - self.build_list_params(params, - vpc_security_group_ids, - 'VpcSecurityGroupIds.member') - if apply_immediately is not None: - params['ApplyImmediately'] = str( - apply_immediately).lower() - if master_user_password is not None: - params['MasterUserPassword'] = master_user_password - if db_parameter_group_name is not None: - params['DBParameterGroupName'] = db_parameter_group_name - if backup_retention_period is not None: - params['BackupRetentionPeriod'] = backup_retention_period - if preferred_backup_window is not None: - params['PreferredBackupWindow'] = preferred_backup_window - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if multi_az is not None: - params['MultiAZ'] = str( - multi_az).lower() - if engine_version is not None: - params['EngineVersion'] = engine_version - if allow_major_version_upgrade is not None: - params['AllowMajorVersionUpgrade'] = str( - allow_major_version_upgrade).lower() - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - if iops is not None: - params['Iops'] = iops - if option_group_name is not None: - params['OptionGroupName'] = option_group_name - if new_db_instance_identifier is not None: - params['NewDBInstanceIdentifier'] = new_db_instance_identifier - return self._make_request( - action='ModifyDBInstance', - verb='POST', - path='/', params=params) - - def modify_db_parameter_group(self, db_parameter_group_name, parameters): - """ - Modifies the parameters of a DB parameter group. To modify - more than one parameter, submit a list of the following: - `ParameterName`, `ParameterValue`, and `ApplyMethod`. A - maximum of 20 parameters can be modified in a single request. - - The `apply-immediate` method can be used only for dynamic - parameters; the `pending-reboot` method can be used with MySQL - and Oracle DB instances for either dynamic or static - parameters. For Microsoft SQL Server DB instances, the - `pending-reboot` method can be used only for static - parameters. - - :type db_parameter_group_name: string - :param db_parameter_group_name: - The name of the DB parameter group. - - Constraints: - - - + Must be the name of an existing DB parameter group - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type parameters: list - :param parameters: - An array of parameter names, values, and the apply method for the - parameter update. At least one parameter name, value, and apply - method must be supplied; subsequent arguments are optional. A - maximum of 20 parameters may be modified in a single request. - - Valid Values (for the application method): `immediate | pending-reboot` - - You can use the immediate value with dynamic parameters only. You can - use the pending-reboot value for both dynamic and static - parameters, and changes are applied when DB instance reboots. - - """ - params = {'DBParameterGroupName': db_parameter_group_name, } - self.build_complex_list_params( - params, parameters, - 'Parameters.member', - ('ParameterName', 'ParameterValue', 'Description', 'Source', 'ApplyType', 'DataType', 'AllowedValues', 'IsModifiable', 'MinimumEngineVersion', 'ApplyMethod')) - return self._make_request( - action='ModifyDBParameterGroup', - verb='POST', - path='/', params=params) - - def modify_db_subnet_group(self, db_subnet_group_name, subnet_ids, - db_subnet_group_description=None): - """ - Modifies an existing DB subnet group. DB subnet groups must - contain at least one subnet in at least two AZs in the region. - - :type db_subnet_group_name: string - :param db_subnet_group_name: The name for the DB subnet group. This - value is stored as a lowercase string. - Constraints: Must contain no more than 255 alphanumeric characters or - hyphens. Must not be "Default". - - Example: `mySubnetgroup` - - :type db_subnet_group_description: string - :param db_subnet_group_description: The description for the DB subnet - group. - - :type subnet_ids: list - :param subnet_ids: The EC2 subnet IDs for the DB subnet group. - - """ - params = {'DBSubnetGroupName': db_subnet_group_name, } - self.build_list_params(params, - subnet_ids, - 'SubnetIds.member') - if db_subnet_group_description is not None: - params['DBSubnetGroupDescription'] = db_subnet_group_description - return self._make_request( - action='ModifyDBSubnetGroup', - verb='POST', - path='/', params=params) - - def modify_event_subscription(self, subscription_name, - sns_topic_arn=None, source_type=None, - event_categories=None, enabled=None): - """ - Modifies an existing RDS event notification subscription. Note - that you cannot modify the source identifiers using this call; - to change source identifiers for a subscription, use the - AddSourceIdentifierToSubscription and - RemoveSourceIdentifierFromSubscription calls. - - You can see a list of the event categories for a given - SourceType in the `Events`_ topic in the Amazon RDS User Guide - or by using the **DescribeEventCategories** action. - - :type subscription_name: string - :param subscription_name: The name of the RDS event notification - subscription. - - :type sns_topic_arn: string - :param sns_topic_arn: The Amazon Resource Name (ARN) of the SNS topic - created for event notification. The ARN is created by Amazon SNS - when you create a topic and subscribe to it. - - :type source_type: string - :param source_type: The type of source that will be generating the - events. For example, if you want to be notified of events generated - by a DB instance, you would set this parameter to db-instance. if - this value is not specified, all events are returned. - Valid values: db-instance | db-parameter-group | db-security-group | - db-snapshot - - :type event_categories: list - :param event_categories: A list of event categories for a SourceType - that you want to subscribe to. You can see a list of the categories - for a given SourceType in the `Events`_ topic in the Amazon RDS - User Guide or by using the **DescribeEventCategories** action. - - :type enabled: boolean - :param enabled: A Boolean value; set to **true** to activate the - subscription. - - """ - params = {'SubscriptionName': subscription_name, } - if sns_topic_arn is not None: - params['SnsTopicArn'] = sns_topic_arn - if source_type is not None: - params['SourceType'] = source_type - if event_categories is not None: - self.build_list_params(params, - event_categories, - 'EventCategories.member') - if enabled is not None: - params['Enabled'] = str( - enabled).lower() - return self._make_request( - action='ModifyEventSubscription', - verb='POST', - path='/', params=params) - - def modify_option_group(self, option_group_name, options_to_include=None, - options_to_remove=None, apply_immediately=None): - """ - Modifies an existing option group. - - :type option_group_name: string - :param option_group_name: The name of the option group to be modified. - Permanent options, such as the TDE option for Oracle Advanced Security - TDE, cannot be removed from an option group, and that option group - cannot be removed from a DB instance once it is associated with a - DB instance - - :type options_to_include: list - :param options_to_include: Options in this list are added to the option - group or, if already present, the specified configuration is used - to update the existing configuration. - - :type options_to_remove: list - :param options_to_remove: Options in this list are removed from the - option group. - - :type apply_immediately: boolean - :param apply_immediately: Indicates whether the changes should be - applied immediately, or during the next maintenance window for each - instance associated with the option group. - - """ - params = {'OptionGroupName': option_group_name, } - if options_to_include is not None: - self.build_complex_list_params( - params, options_to_include, - 'OptionsToInclude.member', - ('OptionName', 'Port', 'DBSecurityGroupMemberships', 'VpcSecurityGroupMemberships', 'OptionSettings')) - if options_to_remove is not None: - self.build_list_params(params, - options_to_remove, - 'OptionsToRemove.member') - if apply_immediately is not None: - params['ApplyImmediately'] = str( - apply_immediately).lower() - return self._make_request( - action='ModifyOptionGroup', - verb='POST', - path='/', params=params) - - def promote_read_replica(self, db_instance_identifier, - backup_retention_period=None, - preferred_backup_window=None): - """ - Promotes a read replica DB instance to a standalone DB - instance. - - :type db_instance_identifier: string - :param db_instance_identifier: The DB instance identifier. This value - is stored as a lowercase string. - Constraints: - - - + Must be the identifier for an existing read replica DB instance - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - - Example: mydbinstance - - :type backup_retention_period: integer - :param backup_retention_period: - The number of days to retain automated backups. Setting this parameter - to a positive number enables backups. Setting this parameter to 0 - disables automated backups. - - Default: 1 - - Constraints: - - - + Must be a value from 0 to 8 - - :type preferred_backup_window: string - :param preferred_backup_window: The daily time range during which - automated backups are created if automated backups are enabled, - using the `BackupRetentionPeriod` parameter. - Default: A 30-minute window selected at random from an 8-hour block of - time per region. See the Amazon RDS User Guide for the time blocks - for each region from which the default backup windows are assigned. - - Constraints: Must be in the format `hh24:mi-hh24:mi`. Times should be - Universal Time Coordinated (UTC). Must not conflict with the - preferred maintenance window. Must be at least 30 minutes. - - """ - params = {'DBInstanceIdentifier': db_instance_identifier, } - if backup_retention_period is not None: - params['BackupRetentionPeriod'] = backup_retention_period - if preferred_backup_window is not None: - params['PreferredBackupWindow'] = preferred_backup_window - return self._make_request( - action='PromoteReadReplica', - verb='POST', - path='/', params=params) - - def purchase_reserved_db_instances_offering(self, - reserved_db_instances_offering_id, - reserved_db_instance_id=None, - db_instance_count=None, - tags=None): - """ - Purchases a reserved DB instance offering. - - :type reserved_db_instances_offering_id: string - :param reserved_db_instances_offering_id: The ID of the Reserved DB - instance offering to purchase. - Example: 438012d3-4052-4cc7-b2e3-8d3372e0e706 - - :type reserved_db_instance_id: string - :param reserved_db_instance_id: Customer-specified identifier to track - this reservation. - Example: myreservationID - - :type db_instance_count: integer - :param db_instance_count: The number of instances to reserve. - Default: `1` - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'ReservedDBInstancesOfferingId': reserved_db_instances_offering_id, - } - if reserved_db_instance_id is not None: - params['ReservedDBInstanceId'] = reserved_db_instance_id - if db_instance_count is not None: - params['DBInstanceCount'] = db_instance_count - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='PurchaseReservedDBInstancesOffering', - verb='POST', - path='/', params=params) - - def reboot_db_instance(self, db_instance_identifier, force_failover=None): - """ - Rebooting a DB instance restarts the database engine service. - A reboot also applies to the DB instance any modifications to - the associated DB parameter group that were pending. Rebooting - a DB instance results in a momentary outage of the instance, - during which the DB instance status is set to rebooting. If - the RDS instance is configured for MultiAZ, it is possible - that the reboot will be conducted through a failover. An - Amazon RDS event is created when the reboot is completed. - - If your DB instance is deployed in multiple Availability - Zones, you can force a failover from one AZ to the other - during the reboot. You might force a failover to test the - availability of your DB instance deployment or to restore - operations to the original AZ after a failover occurs. - - The time required to reboot is a function of the specific - database engine's crash recovery process. To improve the - reboot time, we recommend that you reduce database activities - as much as possible during the reboot process to reduce - rollback activity for in-transit transactions. - - :type db_instance_identifier: string - :param db_instance_identifier: - The DB instance identifier. This parameter is stored as a lowercase - string. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type force_failover: boolean - :param force_failover: When `True`, the reboot will be conducted - through a MultiAZ failover. - Constraint: You cannot specify `True` if the instance is not configured - for MultiAZ. - - """ - params = {'DBInstanceIdentifier': db_instance_identifier, } - if force_failover is not None: - params['ForceFailover'] = str( - force_failover).lower() - return self._make_request( - action='RebootDBInstance', - verb='POST', - path='/', params=params) - - def remove_source_identifier_from_subscription(self, subscription_name, - source_identifier): - """ - Removes a source identifier from an existing RDS event - notification subscription. - - :type subscription_name: string - :param subscription_name: The name of the RDS event notification - subscription you want to remove a source identifier from. - - :type source_identifier: string - :param source_identifier: The source identifier to be removed from the - subscription, such as the **DB instance identifier** for a DB - instance or the name of a security group. - - """ - params = { - 'SubscriptionName': subscription_name, - 'SourceIdentifier': source_identifier, - } - return self._make_request( - action='RemoveSourceIdentifierFromSubscription', - verb='POST', - path='/', params=params) - - def remove_tags_from_resource(self, resource_name, tag_keys): - """ - Removes metadata tags from an Amazon RDS resource. - - For an overview on tagging an Amazon RDS resource, see - `Tagging Amazon RDS Resources`_. - - :type resource_name: string - :param resource_name: The Amazon RDS resource the tags will be removed - from. This value is an Amazon Resource Name (ARN). For information - about creating an ARN, see ` Constructing an RDS Amazon Resource - Name (ARN)`_. - - :type tag_keys: list - :param tag_keys: The tag key (name) of the tag to be removed. - - """ - params = {'ResourceName': resource_name, } - self.build_list_params(params, - tag_keys, - 'TagKeys.member') - return self._make_request( - action='RemoveTagsFromResource', - verb='POST', - path='/', params=params) - - def reset_db_parameter_group(self, db_parameter_group_name, - reset_all_parameters=None, parameters=None): - """ - Modifies the parameters of a DB parameter group to the - engine/system default value. To reset specific parameters - submit a list of the following: `ParameterName` and - `ApplyMethod`. To reset the entire DB parameter group, specify - the `DBParameterGroup` name and `ResetAllParameters` - parameters. When resetting the entire group, dynamic - parameters are updated immediately and static parameters are - set to `pending-reboot` to take effect on the next DB instance - restart or `RebootDBInstance` request. - - :type db_parameter_group_name: string - :param db_parameter_group_name: - The name of the DB parameter group. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type reset_all_parameters: boolean - :param reset_all_parameters: Specifies whether ( `True`) or not ( - `False`) to reset all parameters in the DB parameter group to - default values. - Default: `True` - - :type parameters: list - :param parameters: An array of parameter names, values, and the apply - method for the parameter update. At least one parameter name, - value, and apply method must be supplied; subsequent arguments are - optional. A maximum of 20 parameters may be modified in a single - request. - **MySQL** - - Valid Values (for Apply method): `immediate` | `pending-reboot` - - You can use the immediate value with dynamic parameters only. You can - use the `pending-reboot` value for both dynamic and static - parameters, and changes are applied when DB instance reboots. - - **Oracle** - - Valid Values (for Apply method): `pending-reboot` - - """ - params = {'DBParameterGroupName': db_parameter_group_name, } - if reset_all_parameters is not None: - params['ResetAllParameters'] = str( - reset_all_parameters).lower() - if parameters is not None: - self.build_complex_list_params( - params, parameters, - 'Parameters.member', - ('ParameterName', 'ParameterValue', 'Description', 'Source', 'ApplyType', 'DataType', 'AllowedValues', 'IsModifiable', 'MinimumEngineVersion', 'ApplyMethod')) - return self._make_request( - action='ResetDBParameterGroup', - verb='POST', - path='/', params=params) - - def restore_db_instance_from_db_snapshot(self, db_instance_identifier, - db_snapshot_identifier, - db_instance_class=None, - port=None, - availability_zone=None, - db_subnet_group_name=None, - multi_az=None, - publicly_accessible=None, - auto_minor_version_upgrade=None, - license_model=None, - db_name=None, engine=None, - iops=None, - option_group_name=None, - tags=None): - """ - Creates a new DB instance from a DB snapshot. The target - database is created from the source database restore point - with the same configuration as the original source database, - except that the new RDS instance is created with the default - security group. - - :type db_instance_identifier: string - :param db_instance_identifier: - The identifier for the DB snapshot to restore from. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type db_snapshot_identifier: string - :param db_snapshot_identifier: Name of the DB instance to create from - the DB snapshot. This parameter isn't case sensitive. - Constraints: - - - + Must contain from 1 to 255 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - - Example: `my-snapshot-id` - - :type db_instance_class: string - :param db_instance_class: The compute and memory capacity of the Amazon - RDS DB instance. - Valid Values: `db.t1.micro | db.m1.small | db.m1.medium | db.m1.large | - db.m1.xlarge | db.m2.2xlarge | db.m2.4xlarge` - - :type port: integer - :param port: The port number on which the database accepts connections. - Default: The same port as the original DB instance - - Constraints: Value must be `1150-65535` - - :type availability_zone: string - :param availability_zone: The EC2 Availability Zone that the database - instance will be created in. - Default: A random, system-chosen Availability Zone. - - Constraint: You cannot specify the AvailabilityZone parameter if the - MultiAZ parameter is set to `True`. - - Example: `us-east-1a` - - :type db_subnet_group_name: string - :param db_subnet_group_name: The DB subnet group name to use for the - new instance. - - :type multi_az: boolean - :param multi_az: Specifies if the DB instance is a Multi-AZ deployment. - Constraint: You cannot specify the AvailabilityZone parameter if the - MultiAZ parameter is set to `True`. - - :type publicly_accessible: boolean - :param publicly_accessible: Specifies the accessibility options for the - DB instance. A value of true specifies an Internet-facing instance - with a publicly resolvable DNS name, which resolves to a public IP - address. A value of false specifies an internal instance with a DNS - name that resolves to a private IP address. - Default: The default behavior varies depending on whether a VPC has - been requested or not. The following list shows the default - behavior in each case. - - - + **Default VPC:**true - + **VPC:**false - - - If no DB subnet group has been specified as part of the request and the - PubliclyAccessible value has not been set, the DB instance will be - publicly accessible. If a specific DB subnet group has been - specified as part of the request and the PubliclyAccessible value - has not been set, the DB instance will be private. - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: Indicates that minor version - upgrades will be applied automatically to the DB instance during - the maintenance window. - - :type license_model: string - :param license_model: License model information for the restored DB - instance. - Default: Same as source. - - Valid values: `license-included` | `bring-your-own-license` | `general- - public-license` - - :type db_name: string - :param db_name: - The database name for the restored DB instance. - - - This parameter doesn't apply to the MySQL engine. - - :type engine: string - :param engine: The database engine to use for the new instance. - Default: The same as source - - Constraint: Must be compatible with the engine of the source - - Example: `oracle-ee` - - :type iops: integer - :param iops: Specifies the amount of provisioned IOPS for the DB - instance, expressed in I/O operations per second. If this parameter - is not specified, the IOPS value will be taken from the backup. If - this parameter is set to 0, the new instance will be converted to a - non-PIOPS instance, which will take additional time, though your DB - instance will be available for connections before the conversion - starts. - Constraints: Must be an integer greater than 1000. - - :type option_group_name: string - :param option_group_name: The name of the option group to be used for - the restored DB instance. - Permanent options, such as the TDE option for Oracle Advanced Security - TDE, cannot be removed from an option group, and that option group - cannot be removed from a DB instance once it is associated with a - DB instance - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'DBInstanceIdentifier': db_instance_identifier, - 'DBSnapshotIdentifier': db_snapshot_identifier, - } - if db_instance_class is not None: - params['DBInstanceClass'] = db_instance_class - if port is not None: - params['Port'] = port - if availability_zone is not None: - params['AvailabilityZone'] = availability_zone - if db_subnet_group_name is not None: - params['DBSubnetGroupName'] = db_subnet_group_name - if multi_az is not None: - params['MultiAZ'] = str( - multi_az).lower() - if publicly_accessible is not None: - params['PubliclyAccessible'] = str( - publicly_accessible).lower() - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - if license_model is not None: - params['LicenseModel'] = license_model - if db_name is not None: - params['DBName'] = db_name - if engine is not None: - params['Engine'] = engine - if iops is not None: - params['Iops'] = iops - if option_group_name is not None: - params['OptionGroupName'] = option_group_name - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='RestoreDBInstanceFromDBSnapshot', - verb='POST', - path='/', params=params) - - def restore_db_instance_to_point_in_time(self, - source_db_instance_identifier, - target_db_instance_identifier, - restore_time=None, - use_latest_restorable_time=None, - db_instance_class=None, - port=None, - availability_zone=None, - db_subnet_group_name=None, - multi_az=None, - publicly_accessible=None, - auto_minor_version_upgrade=None, - license_model=None, - db_name=None, engine=None, - iops=None, - option_group_name=None, - tags=None): - """ - Restores a DB instance to an arbitrary point-in-time. Users - can restore to any point in time before the - latestRestorableTime for up to backupRetentionPeriod days. The - target database is created from the source database with the - same configuration as the original database except that the DB - instance is created with the default DB security group. - - :type source_db_instance_identifier: string - :param source_db_instance_identifier: - The identifier of the source DB instance from which to restore. - - Constraints: - - - + Must be the identifier of an existing database instance - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type target_db_instance_identifier: string - :param target_db_instance_identifier: - The name of the new database instance to be created. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type restore_time: timestamp - :param restore_time: The date and time to restore from. - Valid Values: Value must be a UTC time - - Constraints: - - - + Must be before the latest restorable time for the DB instance - + Cannot be specified if UseLatestRestorableTime parameter is true - - - Example: `2009-09-07T23:45:00Z` - - :type use_latest_restorable_time: boolean - :param use_latest_restorable_time: Specifies whether ( `True`) or not ( - `False`) the DB instance is restored from the latest backup time. - Default: `False` - - Constraints: Cannot be specified if RestoreTime parameter is provided. - - :type db_instance_class: string - :param db_instance_class: The compute and memory capacity of the Amazon - RDS DB instance. - Valid Values: `db.t1.micro | db.m1.small | db.m1.medium | db.m1.large | - db.m1.xlarge | db.m2.2xlarge | db.m2.4xlarge` - - Default: The same DBInstanceClass as the original DB instance. - - :type port: integer - :param port: The port number on which the database accepts connections. - Constraints: Value must be `1150-65535` - - Default: The same port as the original DB instance. - - :type availability_zone: string - :param availability_zone: The EC2 Availability Zone that the database - instance will be created in. - Default: A random, system-chosen Availability Zone. - - Constraint: You cannot specify the AvailabilityZone parameter if the - MultiAZ parameter is set to true. - - Example: `us-east-1a` - - :type db_subnet_group_name: string - :param db_subnet_group_name: The DB subnet group name to use for the - new instance. - - :type multi_az: boolean - :param multi_az: Specifies if the DB instance is a Multi-AZ deployment. - Constraint: You cannot specify the AvailabilityZone parameter if the - MultiAZ parameter is set to `True`. - - :type publicly_accessible: boolean - :param publicly_accessible: Specifies the accessibility options for the - DB instance. A value of true specifies an Internet-facing instance - with a publicly resolvable DNS name, which resolves to a public IP - address. A value of false specifies an internal instance with a DNS - name that resolves to a private IP address. - Default: The default behavior varies depending on whether a VPC has - been requested or not. The following list shows the default - behavior in each case. - - - + **Default VPC:**true - + **VPC:**false - - - If no DB subnet group has been specified as part of the request and the - PubliclyAccessible value has not been set, the DB instance will be - publicly accessible. If a specific DB subnet group has been - specified as part of the request and the PubliclyAccessible value - has not been set, the DB instance will be private. - - :type auto_minor_version_upgrade: boolean - :param auto_minor_version_upgrade: Indicates that minor version - upgrades will be applied automatically to the DB instance during - the maintenance window. - - :type license_model: string - :param license_model: License model information for the restored DB - instance. - Default: Same as source. - - Valid values: `license-included` | `bring-your-own-license` | `general- - public-license` - - :type db_name: string - :param db_name: - The database name for the restored DB instance. - - - This parameter is not used for the MySQL engine. - - :type engine: string - :param engine: The database engine to use for the new instance. - Default: The same as source - - Constraint: Must be compatible with the engine of the source - - Example: `oracle-ee` - - :type iops: integer - :param iops: The amount of Provisioned IOPS (input/output operations - per second) to be initially allocated for the DB instance. - Constraints: Must be an integer greater than 1000. - - :type option_group_name: string - :param option_group_name: The name of the option group to be used for - the restored DB instance. - Permanent options, such as the TDE option for Oracle Advanced Security - TDE, cannot be removed from an option group, and that option group - cannot be removed from a DB instance once it is associated with a - DB instance - - :type tags: list - :param tags: A list of tags. - - """ - params = { - 'SourceDBInstanceIdentifier': source_db_instance_identifier, - 'TargetDBInstanceIdentifier': target_db_instance_identifier, - } - if restore_time is not None: - params['RestoreTime'] = restore_time - if use_latest_restorable_time is not None: - params['UseLatestRestorableTime'] = str( - use_latest_restorable_time).lower() - if db_instance_class is not None: - params['DBInstanceClass'] = db_instance_class - if port is not None: - params['Port'] = port - if availability_zone is not None: - params['AvailabilityZone'] = availability_zone - if db_subnet_group_name is not None: - params['DBSubnetGroupName'] = db_subnet_group_name - if multi_az is not None: - params['MultiAZ'] = str( - multi_az).lower() - if publicly_accessible is not None: - params['PubliclyAccessible'] = str( - publicly_accessible).lower() - if auto_minor_version_upgrade is not None: - params['AutoMinorVersionUpgrade'] = str( - auto_minor_version_upgrade).lower() - if license_model is not None: - params['LicenseModel'] = license_model - if db_name is not None: - params['DBName'] = db_name - if engine is not None: - params['Engine'] = engine - if iops is not None: - params['Iops'] = iops - if option_group_name is not None: - params['OptionGroupName'] = option_group_name - if tags is not None: - self.build_complex_list_params( - params, tags, - 'Tags.member', - ('Key', 'Value')) - return self._make_request( - action='RestoreDBInstanceToPointInTime', - verb='POST', - path='/', params=params) - - def revoke_db_security_group_ingress(self, db_security_group_name, - cidrip=None, - ec2_security_group_name=None, - ec2_security_group_id=None, - ec2_security_group_owner_id=None): - """ - Revokes ingress from a DBSecurityGroup for previously - authorized IP ranges or EC2 or VPC Security Groups. Required - parameters for this API are one of CIDRIP, EC2SecurityGroupId - for VPC, or (EC2SecurityGroupOwnerId and either - EC2SecurityGroupName or EC2SecurityGroupId). - - :type db_security_group_name: string - :param db_security_group_name: The name of the DB security group to - revoke ingress from. - - :type cidrip: string - :param cidrip: The IP range to revoke access from. Must be a valid CIDR - range. If `CIDRIP` is specified, `EC2SecurityGroupName`, - `EC2SecurityGroupId` and `EC2SecurityGroupOwnerId` cannot be - provided. - - :type ec2_security_group_name: string - :param ec2_security_group_name: The name of the EC2 security group to - revoke access from. For VPC DB security groups, - `EC2SecurityGroupId` must be provided. Otherwise, - EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or - `EC2SecurityGroupId` must be provided. - - :type ec2_security_group_id: string - :param ec2_security_group_id: The id of the EC2 security group to - revoke access from. For VPC DB security groups, - `EC2SecurityGroupId` must be provided. Otherwise, - EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or - `EC2SecurityGroupId` must be provided. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: The AWS Account Number of the owner - of the EC2 security group specified in the `EC2SecurityGroupName` - parameter. The AWS Access Key ID is not an acceptable value. For - VPC DB security groups, `EC2SecurityGroupId` must be provided. - Otherwise, EC2SecurityGroupOwnerId and either - `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided. - - """ - params = {'DBSecurityGroupName': db_security_group_name, } - if cidrip is not None: - params['CIDRIP'] = cidrip - if ec2_security_group_name is not None: - params['EC2SecurityGroupName'] = ec2_security_group_name - if ec2_security_group_id is not None: - params['EC2SecurityGroupId'] = ec2_security_group_id - if ec2_security_group_owner_id is not None: - params['EC2SecurityGroupOwnerId'] = ec2_security_group_owner_id - return self._make_request( - action='RevokeDBSecurityGroupIngress', - verb='POST', - path='/', params=params) - - def _make_request(self, action, verb, path, params): - params['ContentType'] = 'JSON' - response = self.make_request(action=action, verb='POST', - path='/', params=params) - body = response.read() - boto.log.debug(body) - if response.status == 200: - return json.loads(body) - else: - json_body = json.loads(body) - fault_name = json_body.get('Error', {}).get('Code', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/redshift/__init__.py b/awx/lib/site-packages/boto/redshift/__init__.py deleted file mode 100644 index f98ececd75..0000000000 --- a/awx/lib/site-packages/boto/redshift/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the AWS Redshift service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.redshift.layer1 import RedshiftConnection - return get_regions('redshift', connection_cls=RedshiftConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/redshift/exceptions.py b/awx/lib/site-packages/boto/redshift/exceptions.py deleted file mode 100644 index 70339225ff..0000000000 --- a/awx/lib/site-packages/boto/redshift/exceptions.py +++ /dev/null @@ -1,459 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import JSONResponseError - - -class ClusterNotFoundFault(JSONResponseError): - pass - - -class InvalidClusterSnapshotStateFault(JSONResponseError): - pass - - -class ClusterSnapshotNotFoundFault(JSONResponseError): - pass - - -class ClusterSecurityGroupQuotaExceededFault(JSONResponseError): - pass - - -class ReservedNodeOfferingNotFoundFault(JSONResponseError): - pass - - -class InvalidSubnet(JSONResponseError): - pass - - -class ClusterSubnetGroupQuotaExceededFault(JSONResponseError): - pass - - -class InvalidClusterStateFault(JSONResponseError): - pass - - -class InvalidClusterParameterGroupStateFault(JSONResponseError): - pass - - -class ClusterParameterGroupAlreadyExistsFault(JSONResponseError): - pass - - -class InvalidClusterSecurityGroupStateFault(JSONResponseError): - pass - - -class InvalidRestoreFault(JSONResponseError): - pass - - -class AuthorizationNotFoundFault(JSONResponseError): - pass - - -class ResizeNotFoundFault(JSONResponseError): - pass - - -class NumberOfNodesQuotaExceededFault(JSONResponseError): - pass - - -class ClusterSnapshotAlreadyExistsFault(JSONResponseError): - pass - - -class AuthorizationQuotaExceededFault(JSONResponseError): - pass - - -class AuthorizationAlreadyExistsFault(JSONResponseError): - pass - - -class ClusterSnapshotQuotaExceededFault(JSONResponseError): - pass - - -class ReservedNodeNotFoundFault(JSONResponseError): - pass - - -class ReservedNodeAlreadyExistsFault(JSONResponseError): - pass - - -class ClusterSecurityGroupAlreadyExistsFault(JSONResponseError): - pass - - -class ClusterParameterGroupNotFoundFault(JSONResponseError): - pass - - -class ReservedNodeQuotaExceededFault(JSONResponseError): - pass - - -class ClusterQuotaExceededFault(JSONResponseError): - pass - - -class ClusterSubnetQuotaExceededFault(JSONResponseError): - pass - - -class UnsupportedOptionFault(JSONResponseError): - pass - - -class InvalidVPCNetworkStateFault(JSONResponseError): - pass - - -class ClusterSecurityGroupNotFoundFault(JSONResponseError): - pass - - -class InvalidClusterSubnetGroupStateFault(JSONResponseError): - pass - - -class ClusterSubnetGroupAlreadyExistsFault(JSONResponseError): - pass - - -class NumberOfNodesPerClusterLimitExceededFault(JSONResponseError): - pass - - -class ClusterSubnetGroupNotFoundFault(JSONResponseError): - pass - - -class ClusterParameterGroupQuotaExceededFault(JSONResponseError): - pass - - -class ClusterAlreadyExistsFault(JSONResponseError): - pass - - -class InsufficientClusterCapacityFault(JSONResponseError): - pass - - -class InvalidClusterSubnetStateFault(JSONResponseError): - pass - - -class SubnetAlreadyInUse(JSONResponseError): - pass - - -class InvalidParameterCombinationFault(JSONResponseError): - pass - - -class AccessToSnapshotDeniedFault(JSONResponseError): - pass - - -class UnauthorizedOperationFault(JSONResponseError): - pass - - -class SnapshotCopyAlreadyDisabled(JSONResponseError): - pass - - -class ClusterNotFound(JSONResponseError): - pass - - -class UnknownSnapshotCopyRegion(JSONResponseError): - pass - - -class InvalidClusterSubnetState(JSONResponseError): - pass - - -class ReservedNodeQuotaExceeded(JSONResponseError): - pass - - -class InvalidClusterState(JSONResponseError): - pass - - -class HsmClientCertificateQuotaExceeded(JSONResponseError): - pass - - -class SubscriptionCategoryNotFound(JSONResponseError): - pass - - -class HsmClientCertificateNotFound(JSONResponseError): - pass - - -class SubscriptionEventIdNotFound(JSONResponseError): - pass - - -class ClusterSecurityGroupAlreadyExists(JSONResponseError): - pass - - -class HsmConfigurationAlreadyExists(JSONResponseError): - pass - - -class NumberOfNodesQuotaExceeded(JSONResponseError): - pass - - -class ReservedNodeOfferingNotFound(JSONResponseError): - pass - - -class BucketNotFound(JSONResponseError): - pass - - -class InsufficientClusterCapacity(JSONResponseError): - pass - - -class InvalidRestore(JSONResponseError): - pass - - -class UnauthorizedOperation(JSONResponseError): - pass - - -class ClusterQuotaExceeded(JSONResponseError): - pass - - -class InvalidVPCNetworkState(JSONResponseError): - pass - - -class ClusterSnapshotNotFound(JSONResponseError): - pass - - -class AuthorizationQuotaExceeded(JSONResponseError): - pass - - -class InvalidHsmClientCertificateState(JSONResponseError): - pass - - -class SNSTopicArnNotFound(JSONResponseError): - pass - - -class ResizeNotFound(JSONResponseError): - pass - - -class ClusterSubnetGroupNotFound(JSONResponseError): - pass - - -class SNSNoAuthorization(JSONResponseError): - pass - - -class ClusterSnapshotQuotaExceeded(JSONResponseError): - pass - - -class AccessToSnapshotDenied(JSONResponseError): - pass - - -class InvalidClusterSecurityGroupState(JSONResponseError): - pass - - -class NumberOfNodesPerClusterLimitExceeded(JSONResponseError): - pass - - -class ClusterSubnetQuotaExceeded(JSONResponseError): - pass - - -class SNSInvalidTopic(JSONResponseError): - pass - - -class ClusterSecurityGroupNotFound(JSONResponseError): - pass - - -class InvalidElasticIp(JSONResponseError): - pass - - -class InvalidClusterParameterGroupState(JSONResponseError): - pass - - -class InvalidHsmConfigurationState(JSONResponseError): - pass - - - -class ClusterAlreadyExists(JSONResponseError): - pass - - -class HsmConfigurationQuotaExceeded(JSONResponseError): - pass - - -class ClusterSnapshotAlreadyExists(JSONResponseError): - pass - - -class SubscriptionSeverityNotFound(JSONResponseError): - pass - - -class SourceNotFound(JSONResponseError): - pass - - -class ReservedNodeAlreadyExists(JSONResponseError): - pass - - -class ClusterSubnetGroupQuotaExceeded(JSONResponseError): - pass - - -class ClusterParameterGroupNotFound(JSONResponseError): - pass - - -class InvalidS3BucketName(JSONResponseError): - pass - - -class InvalidS3KeyPrefix(JSONResponseError): - pass - - -class SubscriptionAlreadyExist(JSONResponseError): - pass - - -class HsmConfigurationNotFound(JSONResponseError): - pass - - -class AuthorizationNotFound(JSONResponseError): - pass - - -class ClusterSecurityGroupQuotaExceeded(JSONResponseError): - pass - - -class EventSubscriptionQuotaExceeded(JSONResponseError): - pass - - -class AuthorizationAlreadyExists(JSONResponseError): - pass - - -class InvalidClusterSnapshotState(JSONResponseError): - pass - - -class ClusterParameterGroupQuotaExceeded(JSONResponseError): - pass - - -class SnapshotCopyDisabled(JSONResponseError): - pass - - -class ClusterSubnetGroupAlreadyExists(JSONResponseError): - pass - - -class ReservedNodeNotFound(JSONResponseError): - pass - - -class HsmClientCertificateAlreadyExists(JSONResponseError): - pass - - -class InvalidClusterSubnetGroupState(JSONResponseError): - pass - - -class SubscriptionNotFound(JSONResponseError): - pass - - -class InsufficientS3BucketPolicy(JSONResponseError): - pass - - -class ClusterParameterGroupAlreadyExists(JSONResponseError): - pass - - -class UnsupportedOption(JSONResponseError): - pass - - -class CopyToRegionDisabled(JSONResponseError): - pass - - -class SnapshotCopyAlreadyEnabled(JSONResponseError): - pass - - -class IncompatibleOrderableOptions(JSONResponseError): - pass - - -class InvalidSubscriptionState(JSONResponseError): - pass diff --git a/awx/lib/site-packages/boto/redshift/layer1.py b/awx/lib/site-packages/boto/redshift/layer1.py deleted file mode 100644 index be1529fdf8..0000000000 --- a/awx/lib/site-packages/boto/redshift/layer1.py +++ /dev/null @@ -1,3097 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.redshift import exceptions - - -class RedshiftConnection(AWSQueryConnection): - """ - Amazon Redshift **Overview** - This is an interface reference for Amazon Redshift. It contains - documentation for one of the programming or command line - interfaces you can use to manage Amazon Redshift clusters. Note - that Amazon Redshift is asynchronous, which means that some - interfaces may require techniques, such as polling or asynchronous - callback handlers, to determine when a command has been applied. - In this reference, the parameter descriptions indicate whether a - change is applied immediately, on the next instance reboot, or - during the next maintenance window. For a summary of the Amazon - Redshift cluster management interfaces, go to `Using the Amazon - Redshift Management Interfaces `_. - - Amazon Redshift manages all the work of setting up, operating, and - scaling a data warehouse: provisioning capacity, monitoring and - backing up the cluster, and applying patches and upgrades to the - Amazon Redshift engine. You can focus on using your data to - acquire new insights for your business and customers. - - If you are a first-time user of Amazon Redshift, we recommend that - you begin by reading the The `Amazon Redshift Getting Started - Guide`_ - - If you are a database developer, the `Amazon Redshift Database - Developer Guide`_ explains how to design, build, query, and - maintain the databases that make up your data warehouse. - """ - APIVersion = "2012-12-01" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "redshift.us-east-1.amazonaws.com" - ResponseError = JSONResponseError - - _faults = { - "SnapshotCopyAlreadyDisabled": exceptions.SnapshotCopyAlreadyDisabled, - "ClusterNotFound": exceptions.ClusterNotFound, - "UnknownSnapshotCopyRegion": exceptions.UnknownSnapshotCopyRegion, - "InvalidClusterSubnetState": exceptions.InvalidClusterSubnetState, - "InvalidSubnet": exceptions.InvalidSubnet, - "ReservedNodeQuotaExceeded": exceptions.ReservedNodeQuotaExceeded, - "InvalidClusterState": exceptions.InvalidClusterState, - "HsmClientCertificateQuotaExceeded": exceptions.HsmClientCertificateQuotaExceeded, - "SubscriptionCategoryNotFound": exceptions.SubscriptionCategoryNotFound, - "HsmClientCertificateNotFound": exceptions.HsmClientCertificateNotFound, - "SubscriptionEventIdNotFound": exceptions.SubscriptionEventIdNotFound, - "ClusterSecurityGroupAlreadyExists": exceptions.ClusterSecurityGroupAlreadyExists, - "HsmConfigurationAlreadyExists": exceptions.HsmConfigurationAlreadyExists, - "NumberOfNodesQuotaExceeded": exceptions.NumberOfNodesQuotaExceeded, - "ReservedNodeOfferingNotFound": exceptions.ReservedNodeOfferingNotFound, - "BucketNotFound": exceptions.BucketNotFound, - "InsufficientClusterCapacity": exceptions.InsufficientClusterCapacity, - "InvalidRestore": exceptions.InvalidRestore, - "UnauthorizedOperation": exceptions.UnauthorizedOperation, - "ClusterQuotaExceeded": exceptions.ClusterQuotaExceeded, - "InvalidVPCNetworkState": exceptions.InvalidVPCNetworkState, - "ClusterSnapshotNotFound": exceptions.ClusterSnapshotNotFound, - "AuthorizationQuotaExceeded": exceptions.AuthorizationQuotaExceeded, - "InvalidHsmClientCertificateState": exceptions.InvalidHsmClientCertificateState, - "SNSTopicArnNotFound": exceptions.SNSTopicArnNotFound, - "ResizeNotFound": exceptions.ResizeNotFound, - "ClusterSubnetGroupNotFound": exceptions.ClusterSubnetGroupNotFound, - "SNSNoAuthorization": exceptions.SNSNoAuthorization, - "ClusterSnapshotQuotaExceeded": exceptions.ClusterSnapshotQuotaExceeded, - "AccessToSnapshotDenied": exceptions.AccessToSnapshotDenied, - "InvalidClusterSecurityGroupState": exceptions.InvalidClusterSecurityGroupState, - "NumberOfNodesPerClusterLimitExceeded": exceptions.NumberOfNodesPerClusterLimitExceeded, - "ClusterSubnetQuotaExceeded": exceptions.ClusterSubnetQuotaExceeded, - "SNSInvalidTopic": exceptions.SNSInvalidTopic, - "ClusterSecurityGroupNotFound": exceptions.ClusterSecurityGroupNotFound, - "InvalidElasticIp": exceptions.InvalidElasticIp, - "InvalidClusterParameterGroupState": exceptions.InvalidClusterParameterGroupState, - "InvalidHsmConfigurationState": exceptions.InvalidHsmConfigurationState, - "ClusterAlreadyExists": exceptions.ClusterAlreadyExists, - "HsmConfigurationQuotaExceeded": exceptions.HsmConfigurationQuotaExceeded, - "ClusterSnapshotAlreadyExists": exceptions.ClusterSnapshotAlreadyExists, - "SubscriptionSeverityNotFound": exceptions.SubscriptionSeverityNotFound, - "SourceNotFound": exceptions.SourceNotFound, - "ReservedNodeAlreadyExists": exceptions.ReservedNodeAlreadyExists, - "ClusterSubnetGroupQuotaExceeded": exceptions.ClusterSubnetGroupQuotaExceeded, - "ClusterParameterGroupNotFound": exceptions.ClusterParameterGroupNotFound, - "InvalidS3BucketName": exceptions.InvalidS3BucketName, - "InvalidS3KeyPrefix": exceptions.InvalidS3KeyPrefix, - "SubscriptionAlreadyExist": exceptions.SubscriptionAlreadyExist, - "HsmConfigurationNotFound": exceptions.HsmConfigurationNotFound, - "InvalidSubscriptionState": exceptions.InvalidSubscriptionState, - "AuthorizationNotFound": exceptions.AuthorizationNotFound, - "ClusterSecurityGroupQuotaExceeded": exceptions.ClusterSecurityGroupQuotaExceeded, - "SubnetAlreadyInUse": exceptions.SubnetAlreadyInUse, - "EventSubscriptionQuotaExceeded": exceptions.EventSubscriptionQuotaExceeded, - "AuthorizationAlreadyExists": exceptions.AuthorizationAlreadyExists, - "InvalidClusterSnapshotState": exceptions.InvalidClusterSnapshotState, - "ClusterParameterGroupQuotaExceeded": exceptions.ClusterParameterGroupQuotaExceeded, - "SnapshotCopyDisabled": exceptions.SnapshotCopyDisabled, - "ClusterSubnetGroupAlreadyExists": exceptions.ClusterSubnetGroupAlreadyExists, - "ReservedNodeNotFound": exceptions.ReservedNodeNotFound, - "HsmClientCertificateAlreadyExists": exceptions.HsmClientCertificateAlreadyExists, - "InvalidClusterSubnetGroupState": exceptions.InvalidClusterSubnetGroupState, - "SubscriptionNotFound": exceptions.SubscriptionNotFound, - "InsufficientS3BucketPolicy": exceptions.InsufficientS3BucketPolicy, - "ClusterParameterGroupAlreadyExists": exceptions.ClusterParameterGroupAlreadyExists, - "UnsupportedOption": exceptions.UnsupportedOption, - "CopyToRegionDisabled": exceptions.CopyToRegionDisabled, - "SnapshotCopyAlreadyEnabled": exceptions.SnapshotCopyAlreadyEnabled, - "IncompatibleOrderableOptions": exceptions.IncompatibleOrderableOptions, - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs or kwargs['host'] is None: - kwargs['host'] = region.endpoint - - super(RedshiftConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def authorize_cluster_security_group_ingress(self, - cluster_security_group_name, - cidrip=None, - ec2_security_group_name=None, - ec2_security_group_owner_id=None): - """ - Adds an inbound (ingress) rule to an Amazon Redshift security - group. Depending on whether the application accessing your - cluster is running on the Internet or an EC2 instance, you can - authorize inbound access to either a Classless Interdomain - Routing (CIDR) IP address range or an EC2 security group. You - can add as many as 20 ingress rules to an Amazon Redshift - security group. - - For an overview of CIDR blocks, see the Wikipedia article on - `Classless Inter-Domain Routing`_. - - You must also associate the security group with a cluster so - that clients running on these IP addresses or the EC2 instance - are authorized to connect to the cluster. For information - about managing security groups, go to `Working with Security - Groups`_ in the Amazon Redshift Management Guide . - - :type cluster_security_group_name: string - :param cluster_security_group_name: The name of the security group to - which the ingress rule is added. - - :type cidrip: string - :param cidrip: The IP range to be added the Amazon Redshift security - group. - - :type ec2_security_group_name: string - :param ec2_security_group_name: The EC2 security group to be added the - Amazon Redshift security group. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: The AWS account number of the owner - of the security group specified by the EC2SecurityGroupName - parameter. The AWS Access Key ID is not an acceptable value. - Example: `111122223333` - - """ - params = { - 'ClusterSecurityGroupName': cluster_security_group_name, - } - if cidrip is not None: - params['CIDRIP'] = cidrip - if ec2_security_group_name is not None: - params['EC2SecurityGroupName'] = ec2_security_group_name - if ec2_security_group_owner_id is not None: - params['EC2SecurityGroupOwnerId'] = ec2_security_group_owner_id - return self._make_request( - action='AuthorizeClusterSecurityGroupIngress', - verb='POST', - path='/', params=params) - - def authorize_snapshot_access(self, snapshot_identifier, - account_with_restore_access, - snapshot_cluster_identifier=None): - """ - Authorizes the specified AWS customer account to restore the - specified snapshot. - - For more information about working with snapshots, go to - `Amazon Redshift Snapshots`_ in the Amazon Redshift Management - Guide . - - :type snapshot_identifier: string - :param snapshot_identifier: The identifier of the snapshot the account - is authorized to restore. - - :type snapshot_cluster_identifier: string - :param snapshot_cluster_identifier: The identifier of the cluster the - snapshot was created from. This parameter is required if your IAM - user has a policy containing a snapshot resource element that - specifies anything other than * for the cluster name. - - :type account_with_restore_access: string - :param account_with_restore_access: The identifier of the AWS customer - account authorized to restore the specified snapshot. - - """ - params = { - 'SnapshotIdentifier': snapshot_identifier, - 'AccountWithRestoreAccess': account_with_restore_access, - } - if snapshot_cluster_identifier is not None: - params['SnapshotClusterIdentifier'] = snapshot_cluster_identifier - return self._make_request( - action='AuthorizeSnapshotAccess', - verb='POST', - path='/', params=params) - - def copy_cluster_snapshot(self, source_snapshot_identifier, - target_snapshot_identifier, - source_snapshot_cluster_identifier=None): - """ - Copies the specified automated cluster snapshot to a new - manual cluster snapshot. The source must be an automated - snapshot and it must be in the available state. - - When you delete a cluster, Amazon Redshift deletes any - automated snapshots of the cluster. Also, when the retention - period of the snapshot expires, Amazon Redshift automatically - deletes it. If you want to keep an automated snapshot for a - longer period, you can make a manual copy of the snapshot. - Manual snapshots are retained until you delete them. - - For more information about working with snapshots, go to - `Amazon Redshift Snapshots`_ in the Amazon Redshift Management - Guide . - - :type source_snapshot_identifier: string - :param source_snapshot_identifier: - The identifier for the source snapshot. - - Constraints: - - - + Must be the identifier for a valid automated snapshot whose state is - `available`. - - :type source_snapshot_cluster_identifier: string - :param source_snapshot_cluster_identifier: - The identifier of the cluster the source snapshot was created from. - This parameter is required if your IAM user has a policy containing - a snapshot resource element that specifies anything other than * - for the cluster name. - - Constraints: - - - + Must be the identifier for a valid cluster. - - :type target_snapshot_identifier: string - :param target_snapshot_identifier: - The identifier given to the new manual snapshot. - - Constraints: - - - + Cannot be null, empty, or blank. - + Must contain from 1 to 255 alphanumeric characters or hyphens. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - + Must be unique for the AWS account that is making the request. - - """ - params = { - 'SourceSnapshotIdentifier': source_snapshot_identifier, - 'TargetSnapshotIdentifier': target_snapshot_identifier, - } - if source_snapshot_cluster_identifier is not None: - params['SourceSnapshotClusterIdentifier'] = source_snapshot_cluster_identifier - return self._make_request( - action='CopyClusterSnapshot', - verb='POST', - path='/', params=params) - - def create_cluster(self, cluster_identifier, node_type, master_username, - master_user_password, db_name=None, cluster_type=None, - cluster_security_groups=None, - vpc_security_group_ids=None, - cluster_subnet_group_name=None, - availability_zone=None, - preferred_maintenance_window=None, - cluster_parameter_group_name=None, - automated_snapshot_retention_period=None, port=None, - cluster_version=None, allow_version_upgrade=None, - number_of_nodes=None, publicly_accessible=None, - encrypted=None, - hsm_client_certificate_identifier=None, - hsm_configuration_identifier=None, elastic_ip=None): - """ - Creates a new cluster. To create the cluster in virtual - private cloud (VPC), you must provide cluster subnet group - name. If you don't provide a cluster subnet group name or the - cluster security group parameter, Amazon Redshift creates a - non-VPC cluster, it associates the default cluster security - group with the cluster. For more information about managing - clusters, go to `Amazon Redshift Clusters`_ in the Amazon - Redshift Management Guide . - - :type db_name: string - :param db_name: - The name of the first database to be created when the cluster is - created. - - To create additional databases after the cluster is created, connect to - the cluster with a SQL client and use SQL commands to create a - database. For more information, go to `Create a Database`_ in the - Amazon Redshift Database Developer Guide. - - Default: `dev` - - Constraints: - - - + Must contain 1 to 64 alphanumeric characters. - + Must contain only lowercase letters. - + Cannot be a word that is reserved by the service. A list of reserved - words can be found in `Reserved Words`_ in the Amazon Redshift - Database Developer Guide. - - :type cluster_identifier: string - :param cluster_identifier: A unique identifier for the cluster. You use - this identifier to refer to the cluster for any subsequent cluster - operations such as deleting or modifying. The identifier also - appears in the Amazon Redshift console. - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens. - + Alphabetic characters must be lowercase. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - + Must be unique for all clusters within an AWS account. - - - Example: `myexamplecluster` - - :type cluster_type: string - :param cluster_type: The type of the cluster. When cluster type is - specified as - - + `single-node`, the **NumberOfNodes** parameter is not required. - + `multi-node`, the **NumberOfNodes** parameter is required. - - - Valid Values: `multi-node` | `single-node` - - Default: `multi-node` - - :type node_type: string - :param node_type: The node type to be provisioned for the cluster. For - information about node types, go to ` Working with Clusters`_ in - the Amazon Redshift Management Guide . - Valid Values: `dw1.xlarge` | `dw1.8xlarge` | `dw2.large` | - `dw2.8xlarge`. - - :type master_username: string - :param master_username: - The user name associated with the master user account for the cluster - that is being created. - - Constraints: - - - + Must be 1 - 128 alphanumeric characters. - + First character must be a letter. - + Cannot be a reserved word. A list of reserved words can be found in - `Reserved Words`_ in the Amazon Redshift Database Developer Guide. - - :type master_user_password: string - :param master_user_password: - The password associated with the master user account for the cluster - that is being created. - - Constraints: - - - + Must be between 8 and 64 characters in length. - + Must contain at least one uppercase letter. - + Must contain at least one lowercase letter. - + Must contain one number. - + Can be any printable ASCII character (ASCII code 33 to 126) except ' - (single quote), " (double quote), \, /, @, or space. - - :type cluster_security_groups: list - :param cluster_security_groups: A list of security groups to be - associated with this cluster. - Default: The default cluster security group for Amazon Redshift. - - :type vpc_security_group_ids: list - :param vpc_security_group_ids: A list of Virtual Private Cloud (VPC) - security groups to be associated with the cluster. - Default: The default VPC security group is associated with the cluster. - - :type cluster_subnet_group_name: string - :param cluster_subnet_group_name: The name of a cluster subnet group to - be associated with this cluster. - If this parameter is not provided the resulting cluster will be - deployed outside virtual private cloud (VPC). - - :type availability_zone: string - :param availability_zone: The EC2 Availability Zone (AZ) in which you - want Amazon Redshift to provision the cluster. For example, if you - have several EC2 instances running in a specific Availability Zone, - then you might want the cluster to be provisioned in the same zone - in order to decrease network latency. - Default: A random, system-chosen Availability Zone in the region that - is specified by the endpoint. - - Example: `us-east-1d` - - Constraint: The specified Availability Zone must be in the same region - as the current endpoint. - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which automated cluster maintenance can occur. - Format: `ddd:hh24:mi-ddd:hh24:mi` - - Default: A 30-minute window selected at random from an 8-hour block of - time per region, occurring on a random day of the week. The - following list shows the time blocks for each region from which the - default maintenance windows are assigned. - - - + **US-East (Northern Virginia) Region:** 03:00-11:00 UTC - + **US-West (Oregon) Region** 06:00-14:00 UTC - + **EU (Ireland) Region** 22:00-06:00 UTC - + **Asia Pacific (Singapore) Region** 14:00-22:00 UTC - + **Asia Pacific (Sydney) Region** 12:00-20:00 UTC - + **Asia Pacific (Tokyo) Region** 17:00-03:00 UTC - - - Valid Days: Mon | Tue | Wed | Thu | Fri | Sat | Sun - - Constraints: Minimum 30-minute window. - - :type cluster_parameter_group_name: string - :param cluster_parameter_group_name: - The name of the parameter group to be associated with this cluster. - - Default: The default Amazon Redshift cluster parameter group. For - information about the default parameter group, go to `Working with - Amazon Redshift Parameter Groups`_ - - Constraints: - - - + Must be 1 to 255 alphanumeric characters or hyphens. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - :type automated_snapshot_retention_period: integer - :param automated_snapshot_retention_period: The number of days that - automated snapshots are retained. If the value is 0, automated - snapshots are disabled. Even if automated snapshots are disabled, - you can still create manual snapshots when you want with - CreateClusterSnapshot. - Default: `1` - - Constraints: Must be a value from 0 to 35. - - :type port: integer - :param port: The port number on which the cluster accepts incoming - connections. - The cluster is accessible only via the JDBC and ODBC connection - strings. Part of the connection string requires the port on which - the cluster will listen for incoming connections. - - Default: `5439` - - Valid Values: `1150-65535` - - :type cluster_version: string - :param cluster_version: The version of the Amazon Redshift engine - software that you want to deploy on the cluster. - The version selected runs on all the nodes in the cluster. - - Constraints: Only version 1.0 is currently available. - - Example: `1.0` - - :type allow_version_upgrade: boolean - :param allow_version_upgrade: If `True`, upgrades can be applied during - the maintenance window to the Amazon Redshift engine that is - running on the cluster. - When a new version of the Amazon Redshift engine is released, you can - request that the service automatically apply upgrades during the - maintenance window to the Amazon Redshift engine that is running on - your cluster. - - Default: `True` - - :type number_of_nodes: integer - :param number_of_nodes: The number of compute nodes in the cluster. - This parameter is required when the **ClusterType** parameter is - specified as `multi-node`. - For information about determining how many nodes you need, go to ` - Working with Clusters`_ in the Amazon Redshift Management Guide . - - If you don't specify this parameter, you get a single-node cluster. - When requesting a multi-node cluster, you must specify the number - of nodes that you want in the cluster. - - Default: `1` - - Constraints: Value must be at least 1 and no more than 100. - - :type publicly_accessible: boolean - :param publicly_accessible: If `True`, the cluster can be accessed from - a public network. - - :type encrypted: boolean - :param encrypted: If `True`, the data in the cluster is encrypted at - rest. - Default: false - - :type hsm_client_certificate_identifier: string - :param hsm_client_certificate_identifier: Specifies the name of the HSM - client certificate the Amazon Redshift cluster uses to retrieve the - data encryption keys stored in an HSM. - - :type hsm_configuration_identifier: string - :param hsm_configuration_identifier: Specifies the name of the HSM - configuration that contains the information the Amazon Redshift - cluster can use to retrieve and store keys in an HSM. - - :type elastic_ip: string - :param elastic_ip: The Elastic IP (EIP) address for the cluster. - Constraints: The cluster must be provisioned in EC2-VPC and publicly- - accessible through an Internet gateway. For more information about - provisioning clusters in EC2-VPC, go to `Supported Platforms to - Launch Your Cluster`_ in the Amazon Redshift Management Guide. - - """ - params = { - 'ClusterIdentifier': cluster_identifier, - 'NodeType': node_type, - 'MasterUsername': master_username, - 'MasterUserPassword': master_user_password, - } - if db_name is not None: - params['DBName'] = db_name - if cluster_type is not None: - params['ClusterType'] = cluster_type - if cluster_security_groups is not None: - self.build_list_params(params, - cluster_security_groups, - 'ClusterSecurityGroups.member') - if vpc_security_group_ids is not None: - self.build_list_params(params, - vpc_security_group_ids, - 'VpcSecurityGroupIds.member') - if cluster_subnet_group_name is not None: - params['ClusterSubnetGroupName'] = cluster_subnet_group_name - if availability_zone is not None: - params['AvailabilityZone'] = availability_zone - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if cluster_parameter_group_name is not None: - params['ClusterParameterGroupName'] = cluster_parameter_group_name - if automated_snapshot_retention_period is not None: - params['AutomatedSnapshotRetentionPeriod'] = automated_snapshot_retention_period - if port is not None: - params['Port'] = port - if cluster_version is not None: - params['ClusterVersion'] = cluster_version - if allow_version_upgrade is not None: - params['AllowVersionUpgrade'] = str( - allow_version_upgrade).lower() - if number_of_nodes is not None: - params['NumberOfNodes'] = number_of_nodes - if publicly_accessible is not None: - params['PubliclyAccessible'] = str( - publicly_accessible).lower() - if encrypted is not None: - params['Encrypted'] = str( - encrypted).lower() - if hsm_client_certificate_identifier is not None: - params['HsmClientCertificateIdentifier'] = hsm_client_certificate_identifier - if hsm_configuration_identifier is not None: - params['HsmConfigurationIdentifier'] = hsm_configuration_identifier - if elastic_ip is not None: - params['ElasticIp'] = elastic_ip - return self._make_request( - action='CreateCluster', - verb='POST', - path='/', params=params) - - def create_cluster_parameter_group(self, parameter_group_name, - parameter_group_family, description): - """ - Creates an Amazon Redshift parameter group. - - Creating parameter groups is independent of creating clusters. - You can associate a cluster with a parameter group when you - create the cluster. You can also associate an existing cluster - with a parameter group after the cluster is created by using - ModifyCluster. - - Parameters in the parameter group define specific behavior - that applies to the databases you create on the cluster. For - more information about managing parameter groups, go to - `Amazon Redshift Parameter Groups`_ in the Amazon Redshift - Management Guide . - - :type parameter_group_name: string - :param parameter_group_name: - The name of the cluster parameter group. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters or hyphens - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - + Must be unique within your AWS account. - - This value is stored as a lower-case string. - - :type parameter_group_family: string - :param parameter_group_family: The Amazon Redshift engine version to - which the cluster parameter group applies. The cluster engine - version determines the set of parameters. - To get a list of valid parameter group family names, you can call - DescribeClusterParameterGroups. By default, Amazon Redshift returns - a list of all the parameter groups that are owned by your AWS - account, including the default parameter groups for each Amazon - Redshift engine version. The parameter group family names - associated with the default parameter groups provide you the valid - values. For example, a valid family name is "redshift-1.0". - - :type description: string - :param description: A description of the parameter group. - - """ - params = { - 'ParameterGroupName': parameter_group_name, - 'ParameterGroupFamily': parameter_group_family, - 'Description': description, - } - return self._make_request( - action='CreateClusterParameterGroup', - verb='POST', - path='/', params=params) - - def create_cluster_security_group(self, cluster_security_group_name, - description): - """ - Creates a new Amazon Redshift security group. You use security - groups to control access to non-VPC clusters. - - For information about managing security groups, go to `Amazon - Redshift Cluster Security Groups`_ in the Amazon Redshift - Management Guide . - - :type cluster_security_group_name: string - :param cluster_security_group_name: The name for the security group. - Amazon Redshift stores the value as a lowercase string. - Constraints: - - - + Must contain no more than 255 alphanumeric characters or hyphens. - + Must not be "Default". - + Must be unique for all security groups that are created by your AWS - account. - - - Example: `examplesecuritygroup` - - :type description: string - :param description: A description for the security group. - - """ - params = { - 'ClusterSecurityGroupName': cluster_security_group_name, - 'Description': description, - } - return self._make_request( - action='CreateClusterSecurityGroup', - verb='POST', - path='/', params=params) - - def create_cluster_snapshot(self, snapshot_identifier, - cluster_identifier): - """ - Creates a manual snapshot of the specified cluster. The - cluster must be in the `available` state. - - For more information about working with snapshots, go to - `Amazon Redshift Snapshots`_ in the Amazon Redshift Management - Guide . - - :type snapshot_identifier: string - :param snapshot_identifier: A unique identifier for the snapshot that - you are requesting. This identifier must be unique for all - snapshots within the AWS account. - Constraints: - - - + Cannot be null, empty, or blank - + Must contain from 1 to 255 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - - Example: `my-snapshot-id` - - :type cluster_identifier: string - :param cluster_identifier: The cluster identifier for which you want a - snapshot. - - """ - params = { - 'SnapshotIdentifier': snapshot_identifier, - 'ClusterIdentifier': cluster_identifier, - } - return self._make_request( - action='CreateClusterSnapshot', - verb='POST', - path='/', params=params) - - def create_cluster_subnet_group(self, cluster_subnet_group_name, - description, subnet_ids): - """ - Creates a new Amazon Redshift subnet group. You must provide a - list of one or more subnets in your existing Amazon Virtual - Private Cloud (Amazon VPC) when creating Amazon Redshift - subnet group. - - For information about subnet groups, go to `Amazon Redshift - Cluster Subnet Groups`_ in the Amazon Redshift Management - Guide . - - :type cluster_subnet_group_name: string - :param cluster_subnet_group_name: The name for the subnet group. Amazon - Redshift stores the value as a lowercase string. - Constraints: - - - + Must contain no more than 255 alphanumeric characters or hyphens. - + Must not be "Default". - + Must be unique for all subnet groups that are created by your AWS - account. - - - Example: `examplesubnetgroup` - - :type description: string - :param description: A description for the subnet group. - - :type subnet_ids: list - :param subnet_ids: An array of VPC subnet IDs. A maximum of 20 subnets - can be modified in a single request. - - """ - params = { - 'ClusterSubnetGroupName': cluster_subnet_group_name, - 'Description': description, - } - self.build_list_params(params, - subnet_ids, - 'SubnetIds.member') - return self._make_request( - action='CreateClusterSubnetGroup', - verb='POST', - path='/', params=params) - - def create_event_subscription(self, subscription_name, sns_topic_arn, - source_type=None, source_ids=None, - event_categories=None, severity=None, - enabled=None): - """ - Creates an Amazon Redshift event notification subscription. - This action requires an ARN (Amazon Resource Name) of an - Amazon SNS topic created by either the Amazon Redshift - console, the Amazon SNS console, or the Amazon SNS API. To - obtain an ARN with Amazon SNS, you must create a topic in - Amazon SNS and subscribe to the topic. The ARN is displayed in - the SNS console. - - You can specify the source type, and lists of Amazon Redshift - source IDs, event categories, and event severities. - Notifications will be sent for all events you want that match - those criteria. For example, you can specify source type = - cluster, source ID = my-cluster-1 and mycluster2, event - categories = Availability, Backup, and severity = ERROR. The - subscription will only send notifications for those ERROR - events in the Availability and Backup categories for the - specified clusters. - - If you specify both the source type and source IDs, such as - source type = cluster and source identifier = my-cluster-1, - notifications will be sent for all the cluster events for my- - cluster-1. If you specify a source type but do not specify a - source identifier, you will receive notice of the events for - the objects of that type in your AWS account. If you do not - specify either the SourceType nor the SourceIdentifier, you - will be notified of events generated from all Amazon Redshift - sources belonging to your AWS account. You must specify a - source type if you specify a source ID. - - :type subscription_name: string - :param subscription_name: - The name of the event subscription to be created. - - Constraints: - - - + Cannot be null, empty, or blank. - + Must contain from 1 to 255 alphanumeric characters or hyphens. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - :type sns_topic_arn: string - :param sns_topic_arn: The Amazon Resource Name (ARN) of the Amazon SNS - topic used to transmit the event notifications. The ARN is created - by Amazon SNS when you create a topic and subscribe to it. - - :type source_type: string - :param source_type: The type of source that will be generating the - events. For example, if you want to be notified of events generated - by a cluster, you would set this parameter to cluster. If this - value is not specified, events are returned for all Amazon Redshift - objects in your AWS account. You must specify a source type in - order to specify source IDs. - Valid values: cluster, cluster-parameter-group, cluster-security-group, - and cluster-snapshot. - - :type source_ids: list - :param source_ids: A list of one or more identifiers of Amazon Redshift - source objects. All of the objects must be of the same type as was - specified in the source type parameter. The event subscription will - return only events generated by the specified objects. If not - specified, then events are returned for all objects within the - source type specified. - Example: my-cluster-1, my-cluster-2 - - Example: my-snapshot-20131010 - - :type event_categories: list - :param event_categories: Specifies the Amazon Redshift event categories - to be published by the event notification subscription. - Values: Configuration, Management, Monitoring, Security - - :type severity: string - :param severity: Specifies the Amazon Redshift event severity to be - published by the event notification subscription. - Values: ERROR, INFO - - :type enabled: boolean - :param enabled: A Boolean value; set to `True` to activate the - subscription, set to `False` to create the subscription but not - active it. - - """ - params = { - 'SubscriptionName': subscription_name, - 'SnsTopicArn': sns_topic_arn, - } - if source_type is not None: - params['SourceType'] = source_type - if source_ids is not None: - self.build_list_params(params, - source_ids, - 'SourceIds.member') - if event_categories is not None: - self.build_list_params(params, - event_categories, - 'EventCategories.member') - if severity is not None: - params['Severity'] = severity - if enabled is not None: - params['Enabled'] = str( - enabled).lower() - return self._make_request( - action='CreateEventSubscription', - verb='POST', - path='/', params=params) - - def create_hsm_client_certificate(self, - hsm_client_certificate_identifier): - """ - Creates an HSM client certificate that an Amazon Redshift - cluster will use to connect to the client's HSM in order to - store and retrieve the keys used to encrypt the cluster - databases. - - The command returns a public key, which you must store in the - HSM. In addition to creating the HSM certificate, you must - create an Amazon Redshift HSM configuration that provides a - cluster the information needed to store and use encryption - keys in the HSM. For more information, go to `Hardware - Security Modules`_ in the Amazon Redshift Management Guide. - - :type hsm_client_certificate_identifier: string - :param hsm_client_certificate_identifier: The identifier to be assigned - to the new HSM client certificate that the cluster will use to - connect to the HSM to use the database encryption keys. - - """ - params = { - 'HsmClientCertificateIdentifier': hsm_client_certificate_identifier, - } - return self._make_request( - action='CreateHsmClientCertificate', - verb='POST', - path='/', params=params) - - def create_hsm_configuration(self, hsm_configuration_identifier, - description, hsm_ip_address, - hsm_partition_name, hsm_partition_password, - hsm_server_public_certificate): - """ - Creates an HSM configuration that contains the information - required by an Amazon Redshift cluster to store and use - database encryption keys in a Hardware Security Module (HSM). - After creating the HSM configuration, you can specify it as a - parameter when creating a cluster. The cluster will then store - its encryption keys in the HSM. - - In addition to creating an HSM configuration, you must also - create an HSM client certificate. For more information, go to - `Hardware Security Modules`_ in the Amazon Redshift Management - Guide. - - :type hsm_configuration_identifier: string - :param hsm_configuration_identifier: The identifier to be assigned to - the new Amazon Redshift HSM configuration. - - :type description: string - :param description: A text description of the HSM configuration to be - created. - - :type hsm_ip_address: string - :param hsm_ip_address: The IP address that the Amazon Redshift cluster - must use to access the HSM. - - :type hsm_partition_name: string - :param hsm_partition_name: The name of the partition in the HSM where - the Amazon Redshift clusters will store their database encryption - keys. - - :type hsm_partition_password: string - :param hsm_partition_password: The password required to access the HSM - partition. - - :type hsm_server_public_certificate: string - :param hsm_server_public_certificate: The HSMs public certificate file. - When using Cloud HSM, the file name is server.pem. - - """ - params = { - 'HsmConfigurationIdentifier': hsm_configuration_identifier, - 'Description': description, - 'HsmIpAddress': hsm_ip_address, - 'HsmPartitionName': hsm_partition_name, - 'HsmPartitionPassword': hsm_partition_password, - 'HsmServerPublicCertificate': hsm_server_public_certificate, - } - return self._make_request( - action='CreateHsmConfiguration', - verb='POST', - path='/', params=params) - - def delete_cluster(self, cluster_identifier, - skip_final_cluster_snapshot=None, - final_cluster_snapshot_identifier=None): - """ - Deletes a previously provisioned cluster. A successful - response from the web service indicates that the request was - received correctly. If a final cluster snapshot is requested - the status of the cluster will be "final-snapshot" while the - snapshot is being taken, then it's "deleting" once Amazon - Redshift begins deleting the cluster. Use DescribeClusters to - monitor the status of the deletion. The delete operation - cannot be canceled or reverted once submitted. For more - information about managing clusters, go to `Amazon Redshift - Clusters`_ in the Amazon Redshift Management Guide . - - :type cluster_identifier: string - :param cluster_identifier: - The identifier of the cluster to be deleted. - - Constraints: - - - + Must contain lowercase characters. - + Must contain from 1 to 63 alphanumeric characters or hyphens. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - :type skip_final_cluster_snapshot: boolean - :param skip_final_cluster_snapshot: Determines whether a final snapshot - of the cluster is created before Amazon Redshift deletes the - cluster. If `True`, a final cluster snapshot is not created. If - `False`, a final cluster snapshot is created before the cluster is - deleted. - Default: `False` - - :type final_cluster_snapshot_identifier: string - :param final_cluster_snapshot_identifier: - The identifier of the final snapshot that is to be created immediately - before deleting the cluster. If this parameter is provided, - SkipFinalClusterSnapshot must be `False`. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - """ - params = {'ClusterIdentifier': cluster_identifier, } - if skip_final_cluster_snapshot is not None: - params['SkipFinalClusterSnapshot'] = str( - skip_final_cluster_snapshot).lower() - if final_cluster_snapshot_identifier is not None: - params['FinalClusterSnapshotIdentifier'] = final_cluster_snapshot_identifier - return self._make_request( - action='DeleteCluster', - verb='POST', - path='/', params=params) - - def delete_cluster_parameter_group(self, parameter_group_name): - """ - Deletes a specified Amazon Redshift parameter group. - - :type parameter_group_name: string - :param parameter_group_name: - The name of the parameter group to be deleted. - - Constraints: - - - + Must be the name of an existing cluster parameter group. - + Cannot delete a default cluster parameter group. - - """ - params = {'ParameterGroupName': parameter_group_name, } - return self._make_request( - action='DeleteClusterParameterGroup', - verb='POST', - path='/', params=params) - - def delete_cluster_security_group(self, cluster_security_group_name): - """ - Deletes an Amazon Redshift security group. - - For information about managing security groups, go to `Amazon - Redshift Cluster Security Groups`_ in the Amazon Redshift - Management Guide . - - :type cluster_security_group_name: string - :param cluster_security_group_name: The name of the cluster security - group to be deleted. - - """ - params = { - 'ClusterSecurityGroupName': cluster_security_group_name, - } - return self._make_request( - action='DeleteClusterSecurityGroup', - verb='POST', - path='/', params=params) - - def delete_cluster_snapshot(self, snapshot_identifier, - snapshot_cluster_identifier=None): - """ - Deletes the specified manual snapshot. The snapshot must be in - the `available` state, with no other users authorized to - access the snapshot. - - Unlike automated snapshots, manual snapshots are retained even - after you delete your cluster. Amazon Redshift does not delete - your manual snapshots. You must delete manual snapshot - explicitly to avoid getting charged. If other accounts are - authorized to access the snapshot, you must revoke all of the - authorizations before you can delete the snapshot. - - :type snapshot_identifier: string - :param snapshot_identifier: The unique identifier of the manual - snapshot to be deleted. - Constraints: Must be the name of an existing snapshot that is in the - `available` state. - - :type snapshot_cluster_identifier: string - :param snapshot_cluster_identifier: The unique identifier of the - cluster the snapshot was created from. This parameter is required - if your IAM user has a policy containing a snapshot resource - element that specifies anything other than * for the cluster name. - Constraints: Must be the name of valid cluster. - - """ - params = {'SnapshotIdentifier': snapshot_identifier, } - if snapshot_cluster_identifier is not None: - params['SnapshotClusterIdentifier'] = snapshot_cluster_identifier - return self._make_request( - action='DeleteClusterSnapshot', - verb='POST', - path='/', params=params) - - def delete_cluster_subnet_group(self, cluster_subnet_group_name): - """ - Deletes the specified cluster subnet group. - - :type cluster_subnet_group_name: string - :param cluster_subnet_group_name: The name of the cluster subnet group - name to be deleted. - - """ - params = { - 'ClusterSubnetGroupName': cluster_subnet_group_name, - } - return self._make_request( - action='DeleteClusterSubnetGroup', - verb='POST', - path='/', params=params) - - def delete_event_subscription(self, subscription_name): - """ - Deletes an Amazon Redshift event notification subscription. - - :type subscription_name: string - :param subscription_name: The name of the Amazon Redshift event - notification subscription to be deleted. - - """ - params = {'SubscriptionName': subscription_name, } - return self._make_request( - action='DeleteEventSubscription', - verb='POST', - path='/', params=params) - - def delete_hsm_client_certificate(self, - hsm_client_certificate_identifier): - """ - Deletes the specified HSM client certificate. - - :type hsm_client_certificate_identifier: string - :param hsm_client_certificate_identifier: The identifier of the HSM - client certificate to be deleted. - - """ - params = { - 'HsmClientCertificateIdentifier': hsm_client_certificate_identifier, - } - return self._make_request( - action='DeleteHsmClientCertificate', - verb='POST', - path='/', params=params) - - def delete_hsm_configuration(self, hsm_configuration_identifier): - """ - Deletes the specified Amazon Redshift HSM configuration. - - :type hsm_configuration_identifier: string - :param hsm_configuration_identifier: The identifier of the Amazon - Redshift HSM configuration to be deleted. - - """ - params = { - 'HsmConfigurationIdentifier': hsm_configuration_identifier, - } - return self._make_request( - action='DeleteHsmConfiguration', - verb='POST', - path='/', params=params) - - def describe_cluster_parameter_groups(self, parameter_group_name=None, - max_records=None, marker=None): - """ - Returns a list of Amazon Redshift parameter groups, including - parameter groups you created and the default parameter group. - For each parameter group, the response includes the parameter - group name, description, and parameter group family name. You - can optionally specify a name to retrieve the description of a - specific parameter group. - - For more information about managing parameter groups, go to - `Amazon Redshift Parameter Groups`_ in the Amazon Redshift - Management Guide . - - :type parameter_group_name: string - :param parameter_group_name: The name of a specific parameter group for - which to return details. By default, details about all parameter - groups and the default parameter group are returned. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeClusterParameterGroups request exceed the value specified - in `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if parameter_group_name is not None: - params['ParameterGroupName'] = parameter_group_name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeClusterParameterGroups', - verb='POST', - path='/', params=params) - - def describe_cluster_parameters(self, parameter_group_name, source=None, - max_records=None, marker=None): - """ - Returns a detailed list of parameters contained within the - specified Amazon Redshift parameter group. For each parameter - the response includes information such as parameter name, - description, data type, value, whether the parameter value is - modifiable, and so on. - - You can specify source filter to retrieve parameters of only - specific type. For example, to retrieve parameters that were - modified by a user action such as from - ModifyClusterParameterGroup, you can specify source equal to - user . - - For more information about managing parameter groups, go to - `Amazon Redshift Parameter Groups`_ in the Amazon Redshift - Management Guide . - - :type parameter_group_name: string - :param parameter_group_name: The name of a cluster parameter group for - which to return details. - - :type source: string - :param source: The parameter types to return. Specify `user` to show - parameters that are different form the default. Similarly, specify - `engine-default` to show parameters that are the same as the - default parameter group. - Default: All parameter types returned. - - Valid Values: `user` | `engine-default` - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeClusterParameters request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {'ParameterGroupName': parameter_group_name, } - if source is not None: - params['Source'] = source - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeClusterParameters', - verb='POST', - path='/', params=params) - - def describe_cluster_security_groups(self, - cluster_security_group_name=None, - max_records=None, marker=None): - """ - Returns information about Amazon Redshift security groups. If - the name of a security group is specified, the response will - contain only information about only that security group. - - For information about managing security groups, go to `Amazon - Redshift Cluster Security Groups`_ in the Amazon Redshift - Management Guide . - - :type cluster_security_group_name: string - :param cluster_security_group_name: The name of a cluster security - group for which you are requesting details. You can specify either - the **Marker** parameter or a **ClusterSecurityGroupName** - parameter, but not both. - Example: `securitygroup1` - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeClusterSecurityGroups request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - Constraints: You can specify either the **ClusterSecurityGroupName** - parameter or the **Marker** parameter, but not both. - - """ - params = {} - if cluster_security_group_name is not None: - params['ClusterSecurityGroupName'] = cluster_security_group_name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeClusterSecurityGroups', - verb='POST', - path='/', params=params) - - def describe_cluster_snapshots(self, cluster_identifier=None, - snapshot_identifier=None, - snapshot_type=None, start_time=None, - end_time=None, max_records=None, - marker=None, owner_account=None): - """ - Returns one or more snapshot objects, which contain metadata - about your cluster snapshots. By default, this operation - returns information about all snapshots of all clusters that - are owned by you AWS customer account. No information is - returned for snapshots owned by inactive AWS customer - accounts. - - :type cluster_identifier: string - :param cluster_identifier: The identifier of the cluster for which - information about snapshots is requested. - - :type snapshot_identifier: string - :param snapshot_identifier: The snapshot identifier of the snapshot - about which to return information. - - :type snapshot_type: string - :param snapshot_type: The type of snapshots for which you are - requesting information. By default, snapshots of all types are - returned. - Valid Values: `automated` | `manual` - - :type start_time: timestamp - :param start_time: A value that requests only snapshots created at or - after the specified time. The time value is specified in ISO 8601 - format. For more information about ISO 8601, go to the `ISO8601 - Wikipedia page.`_ - Example: `2012-07-16T18:00:00Z` - - :type end_time: timestamp - :param end_time: A time value that requests only snapshots created at - or before the specified time. The time value is specified in ISO - 8601 format. For more information about ISO 8601, go to the - `ISO8601 Wikipedia page.`_ - Example: `2012-07-16T18:00:00Z` - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeClusterSnapshots request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - :type owner_account: string - :param owner_account: The AWS customer account used to create or copy - the snapshot. Use this field to filter the results to snapshots - owned by a particular account. To describe snapshots you own, - either specify your AWS customer account, or do not specify the - parameter. - - """ - params = {} - if cluster_identifier is not None: - params['ClusterIdentifier'] = cluster_identifier - if snapshot_identifier is not None: - params['SnapshotIdentifier'] = snapshot_identifier - if snapshot_type is not None: - params['SnapshotType'] = snapshot_type - if start_time is not None: - params['StartTime'] = start_time - if end_time is not None: - params['EndTime'] = end_time - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - if owner_account is not None: - params['OwnerAccount'] = owner_account - return self._make_request( - action='DescribeClusterSnapshots', - verb='POST', - path='/', params=params) - - def describe_cluster_subnet_groups(self, cluster_subnet_group_name=None, - max_records=None, marker=None): - """ - Returns one or more cluster subnet group objects, which - contain metadata about your cluster subnet groups. By default, - this operation returns information about all cluster subnet - groups that are defined in you AWS account. - - :type cluster_subnet_group_name: string - :param cluster_subnet_group_name: The name of the cluster subnet group - for which information is requested. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeClusterSubnetGroups request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if cluster_subnet_group_name is not None: - params['ClusterSubnetGroupName'] = cluster_subnet_group_name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeClusterSubnetGroups', - verb='POST', - path='/', params=params) - - def describe_cluster_versions(self, cluster_version=None, - cluster_parameter_group_family=None, - max_records=None, marker=None): - """ - Returns descriptions of the available Amazon Redshift cluster - versions. You can call this operation even before creating any - clusters to learn more about the Amazon Redshift versions. For - more information about managing clusters, go to `Amazon - Redshift Clusters`_ in the Amazon Redshift Management Guide - - :type cluster_version: string - :param cluster_version: The specific cluster version to return. - Example: `1.0` - - :type cluster_parameter_group_family: string - :param cluster_parameter_group_family: - The name of a specific cluster parameter group family to return details - for. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeClusterVersions request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if cluster_version is not None: - params['ClusterVersion'] = cluster_version - if cluster_parameter_group_family is not None: - params['ClusterParameterGroupFamily'] = cluster_parameter_group_family - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeClusterVersions', - verb='POST', - path='/', params=params) - - def describe_clusters(self, cluster_identifier=None, max_records=None, - marker=None): - """ - Returns properties of provisioned clusters including general - cluster properties, cluster database properties, maintenance - and backup properties, and security and access properties. - This operation supports pagination. For more information about - managing clusters, go to `Amazon Redshift Clusters`_ in the - Amazon Redshift Management Guide . - - :type cluster_identifier: string - :param cluster_identifier: The unique identifier of a cluster whose - properties you are requesting. This parameter is case sensitive. - The default is that all clusters defined for an account are returned. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeClusters request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - Constraints: You can specify either the **ClusterIdentifier** parameter - or the **Marker** parameter, but not both. - - """ - params = {} - if cluster_identifier is not None: - params['ClusterIdentifier'] = cluster_identifier - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeClusters', - verb='POST', - path='/', params=params) - - def describe_default_cluster_parameters(self, parameter_group_family, - max_records=None, marker=None): - """ - Returns a list of parameter settings for the specified - parameter group family. - - For more information about managing parameter groups, go to - `Amazon Redshift Parameter Groups`_ in the Amazon Redshift - Management Guide . - - :type parameter_group_family: string - :param parameter_group_family: The name of the cluster parameter group - family. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeDefaultClusterParameters request exceed the value specified - in `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {'ParameterGroupFamily': parameter_group_family, } - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeDefaultClusterParameters', - verb='POST', - path='/', params=params) - - def describe_event_categories(self, source_type=None): - """ - Displays a list of event categories for all event source - types, or for a specified source type. For a list of the event - categories and source types, go to `Amazon Redshift Event - Notifications`_. - - :type source_type: string - :param source_type: The source type, such as cluster or parameter - group, to which the described event categories apply. - Valid values: cluster, snapshot, parameter group, and security group. - - """ - params = {} - if source_type is not None: - params['SourceType'] = source_type - return self._make_request( - action='DescribeEventCategories', - verb='POST', - path='/', params=params) - - def describe_event_subscriptions(self, subscription_name=None, - max_records=None, marker=None): - """ - Lists descriptions of all the Amazon Redshift event - notifications subscription for a customer account. If you - specify a subscription name, lists the description for that - subscription. - - :type subscription_name: string - :param subscription_name: The name of the Amazon Redshift event - notification subscription to be described. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeEventSubscriptions request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if subscription_name is not None: - params['SubscriptionName'] = subscription_name - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeEventSubscriptions', - verb='POST', - path='/', params=params) - - def describe_events(self, source_identifier=None, source_type=None, - start_time=None, end_time=None, duration=None, - max_records=None, marker=None): - """ - Returns events related to clusters, security groups, - snapshots, and parameter groups for the past 14 days. Events - specific to a particular cluster, security group, snapshot or - parameter group can be obtained by providing the name as a - parameter. By default, the past hour of events are returned. - - :type source_identifier: string - :param source_identifier: - The identifier of the event source for which events will be returned. - If this parameter is not specified, then all sources are included - in the response. - - Constraints: - - If SourceIdentifier is supplied, SourceType must also be provided. - - - + Specify a cluster identifier when SourceType is `cluster`. - + Specify a cluster security group name when SourceType is `cluster- - security-group`. - + Specify a cluster parameter group name when SourceType is `cluster- - parameter-group`. - + Specify a cluster snapshot identifier when SourceType is `cluster- - snapshot`. - - :type source_type: string - :param source_type: - The event source to retrieve events for. If no value is specified, all - events are returned. - - Constraints: - - If SourceType is supplied, SourceIdentifier must also be provided. - - - + Specify `cluster` when SourceIdentifier is a cluster identifier. - + Specify `cluster-security-group` when SourceIdentifier is a cluster - security group name. - + Specify `cluster-parameter-group` when SourceIdentifier is a cluster - parameter group name. - + Specify `cluster-snapshot` when SourceIdentifier is a cluster - snapshot identifier. - - :type start_time: timestamp - :param start_time: The beginning of the time interval to retrieve - events for, specified in ISO 8601 format. For more information - about ISO 8601, go to the `ISO8601 Wikipedia page.`_ - Example: `2009-07-08T18:00Z` - - :type end_time: timestamp - :param end_time: The end of the time interval for which to retrieve - events, specified in ISO 8601 format. For more information about - ISO 8601, go to the `ISO8601 Wikipedia page.`_ - Example: `2009-07-08T18:00Z` - - :type duration: integer - :param duration: The number of minutes prior to the time of the request - for which to retrieve events. For example, if the request is sent - at 18:00 and you specify a duration of 60, then only events which - have occurred after 17:00 will be returned. - Default: `60` - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeEvents request exceed the value specified in `MaxRecords`, - AWS returns a value in the `Marker` field of the response. You can - retrieve the next set of response records by providing the returned - marker value in the `Marker` parameter and retrying the request. - - """ - params = {} - if source_identifier is not None: - params['SourceIdentifier'] = source_identifier - if source_type is not None: - params['SourceType'] = source_type - if start_time is not None: - params['StartTime'] = start_time - if end_time is not None: - params['EndTime'] = end_time - if duration is not None: - params['Duration'] = duration - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeEvents', - verb='POST', - path='/', params=params) - - def describe_hsm_client_certificates(self, - hsm_client_certificate_identifier=None, - max_records=None, marker=None): - """ - Returns information about the specified HSM client - certificate. If no certificate ID is specified, returns - information about all the HSM certificates owned by your AWS - customer account. - - :type hsm_client_certificate_identifier: string - :param hsm_client_certificate_identifier: The identifier of a specific - HSM client certificate for which you want information. If no - identifier is specified, information is returned for all HSM client - certificates owned by your AWS customer account. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeHsmClientCertificates request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if hsm_client_certificate_identifier is not None: - params['HsmClientCertificateIdentifier'] = hsm_client_certificate_identifier - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeHsmClientCertificates', - verb='POST', - path='/', params=params) - - def describe_hsm_configurations(self, hsm_configuration_identifier=None, - max_records=None, marker=None): - """ - Returns information about the specified Amazon Redshift HSM - configuration. If no configuration ID is specified, returns - information about all the HSM configurations owned by your AWS - customer account. - - :type hsm_configuration_identifier: string - :param hsm_configuration_identifier: The identifier of a specific - Amazon Redshift HSM configuration to be described. If no identifier - is specified, information is returned for all HSM configurations - owned by your AWS customer account. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeHsmConfigurations request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if hsm_configuration_identifier is not None: - params['HsmConfigurationIdentifier'] = hsm_configuration_identifier - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeHsmConfigurations', - verb='POST', - path='/', params=params) - - def describe_logging_status(self, cluster_identifier): - """ - Describes whether information, such as queries and connection - attempts, is being logged for the specified Amazon Redshift - cluster. - - :type cluster_identifier: string - :param cluster_identifier: The identifier of the cluster to get the - logging status from. - Example: `examplecluster` - - """ - params = {'ClusterIdentifier': cluster_identifier, } - return self._make_request( - action='DescribeLoggingStatus', - verb='POST', - path='/', params=params) - - def describe_orderable_cluster_options(self, cluster_version=None, - node_type=None, max_records=None, - marker=None): - """ - Returns a list of orderable cluster options. Before you create - a new cluster you can use this operation to find what options - are available, such as the EC2 Availability Zones (AZ) in the - specific AWS region that you can specify, and the node types - you can request. The node types differ by available storage, - memory, CPU and price. With the cost involved you might want - to obtain a list of cluster options in the specific region and - specify values when creating a cluster. For more information - about managing clusters, go to `Amazon Redshift Clusters`_ in - the Amazon Redshift Management Guide - - :type cluster_version: string - :param cluster_version: The version filter value. Specify this - parameter to show only the available offerings matching the - specified version. - Default: All versions. - - Constraints: Must be one of the version returned from - DescribeClusterVersions. - - :type node_type: string - :param node_type: The node type filter value. Specify this parameter to - show only the available offerings matching the specified node type. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeOrderableClusterOptions request exceed the value specified - in `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if cluster_version is not None: - params['ClusterVersion'] = cluster_version - if node_type is not None: - params['NodeType'] = node_type - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeOrderableClusterOptions', - verb='POST', - path='/', params=params) - - def describe_reserved_node_offerings(self, - reserved_node_offering_id=None, - max_records=None, marker=None): - """ - Returns a list of the available reserved node offerings by - Amazon Redshift with their descriptions including the node - type, the fixed and recurring costs of reserving the node and - duration the node will be reserved for you. These descriptions - help you determine which reserve node offering you want to - purchase. You then use the unique offering ID in you call to - PurchaseReservedNodeOffering to reserve one or more nodes for - your Amazon Redshift cluster. - - For more information about managing parameter groups, go to - `Purchasing Reserved Nodes`_ in the Amazon Redshift Management - Guide . - - :type reserved_node_offering_id: string - :param reserved_node_offering_id: The unique identifier for the - offering. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeReservedNodeOfferings request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if reserved_node_offering_id is not None: - params['ReservedNodeOfferingId'] = reserved_node_offering_id - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeReservedNodeOfferings', - verb='POST', - path='/', params=params) - - def describe_reserved_nodes(self, reserved_node_id=None, - max_records=None, marker=None): - """ - Returns the descriptions of the reserved nodes. - - :type reserved_node_id: string - :param reserved_node_id: Identifier for the node reservation. - - :type max_records: integer - :param max_records: The maximum number of response records to return in - each call. If the number of remaining response records exceeds the - specified `MaxRecords` value, a value is returned in a `marker` - field of the response. You can retrieve the next set of records by - retrying the command with the returned marker value. - Default: `100` - - Constraints: minimum 20, maximum 100. - - :type marker: string - :param marker: An optional parameter that specifies the starting point - to return a set of response records. When the results of a - DescribeReservedNodes request exceed the value specified in - `MaxRecords`, AWS returns a value in the `Marker` field of the - response. You can retrieve the next set of response records by - providing the returned marker value in the `Marker` parameter and - retrying the request. - - """ - params = {} - if reserved_node_id is not None: - params['ReservedNodeId'] = reserved_node_id - if max_records is not None: - params['MaxRecords'] = max_records - if marker is not None: - params['Marker'] = marker - return self._make_request( - action='DescribeReservedNodes', - verb='POST', - path='/', params=params) - - def describe_resize(self, cluster_identifier): - """ - Returns information about the last resize operation for the - specified cluster. If no resize operation has ever been - initiated for the specified cluster, a `HTTP 404` error is - returned. If a resize operation was initiated and completed, - the status of the resize remains as `SUCCEEDED` until the next - resize. - - A resize operation can be requested using ModifyCluster and - specifying a different number or type of nodes for the - cluster. - - :type cluster_identifier: string - :param cluster_identifier: The unique identifier of a cluster whose - resize progress you are requesting. This parameter isn't case- - sensitive. - By default, resize operations for all clusters defined for an AWS - account are returned. - - """ - params = {'ClusterIdentifier': cluster_identifier, } - return self._make_request( - action='DescribeResize', - verb='POST', - path='/', params=params) - - def disable_logging(self, cluster_identifier): - """ - Stops logging information, such as queries and connection - attempts, for the specified Amazon Redshift cluster. - - :type cluster_identifier: string - :param cluster_identifier: The identifier of the cluster on which - logging is to be stopped. - Example: `examplecluster` - - """ - params = {'ClusterIdentifier': cluster_identifier, } - return self._make_request( - action='DisableLogging', - verb='POST', - path='/', params=params) - - def disable_snapshot_copy(self, cluster_identifier): - """ - Disables the automatic copying of snapshots from one region to - another region for a specified cluster. - - :type cluster_identifier: string - :param cluster_identifier: The unique identifier of the source cluster - that you want to disable copying of snapshots to a destination - region. - Constraints: Must be the valid name of an existing cluster that has - cross-region snapshot copy enabled. - - """ - params = {'ClusterIdentifier': cluster_identifier, } - return self._make_request( - action='DisableSnapshotCopy', - verb='POST', - path='/', params=params) - - def enable_logging(self, cluster_identifier, bucket_name, - s3_key_prefix=None): - """ - Starts logging information, such as queries and connection - attempts, for the specified Amazon Redshift cluster. - - :type cluster_identifier: string - :param cluster_identifier: The identifier of the cluster on which - logging is to be started. - Example: `examplecluster` - - :type bucket_name: string - :param bucket_name: - The name of an existing S3 bucket where the log files are to be stored. - - Constraints: - - - + Must be in the same region as the cluster - + The cluster must have read bucket and put object permissions - - :type s3_key_prefix: string - :param s3_key_prefix: - The prefix applied to the log file names. - - Constraints: - - - + Cannot exceed 512 characters - + Cannot contain spaces( ), double quotes ("), single quotes ('), a - backslash (\), or control characters. The hexadecimal codes for - invalid characters are: - - + x00 to x20 - + x22 - + x27 - + x5c - + x7f or larger - - """ - params = { - 'ClusterIdentifier': cluster_identifier, - 'BucketName': bucket_name, - } - if s3_key_prefix is not None: - params['S3KeyPrefix'] = s3_key_prefix - return self._make_request( - action='EnableLogging', - verb='POST', - path='/', params=params) - - def enable_snapshot_copy(self, cluster_identifier, destination_region, - retention_period=None): - """ - Enables the automatic copy of snapshots from one region to - another region for a specified cluster. - - :type cluster_identifier: string - :param cluster_identifier: The unique identifier of the source cluster - to copy snapshots from. - Constraints: Must be the valid name of an existing cluster that does - not already have cross-region snapshot copy enabled. - - :type destination_region: string - :param destination_region: The destination region that you want to copy - snapshots to. - Constraints: Must be the name of a valid region. For more information, - see `Regions and Endpoints`_ in the Amazon Web Services General - Reference. - - :type retention_period: integer - :param retention_period: The number of days to retain automated - snapshots in the destination region after they are copied from the - source region. - Default: 7. - - Constraints: Must be at least 1 and no more than 35. - - """ - params = { - 'ClusterIdentifier': cluster_identifier, - 'DestinationRegion': destination_region, - } - if retention_period is not None: - params['RetentionPeriod'] = retention_period - return self._make_request( - action='EnableSnapshotCopy', - verb='POST', - path='/', params=params) - - def modify_cluster(self, cluster_identifier, cluster_type=None, - node_type=None, number_of_nodes=None, - cluster_security_groups=None, - vpc_security_group_ids=None, - master_user_password=None, - cluster_parameter_group_name=None, - automated_snapshot_retention_period=None, - preferred_maintenance_window=None, - cluster_version=None, allow_version_upgrade=None, - hsm_client_certificate_identifier=None, - hsm_configuration_identifier=None, - new_cluster_identifier=None): - """ - Modifies the settings for a cluster. For example, you can add - another security or parameter group, update the preferred - maintenance window, or change the master user password. - Resetting a cluster password or modifying the security groups - associated with a cluster do not need a reboot. However, - modifying a parameter group requires a reboot for parameters - to take effect. For more information about managing clusters, - go to `Amazon Redshift Clusters`_ in the Amazon Redshift - Management Guide - - You can also change node type and the number of nodes to scale - up or down the cluster. When resizing a cluster, you must - specify both the number of nodes and the node type even if one - of the parameters does not change. If you specify the same - number of nodes and node type that are already configured for - the cluster, an error is returned. - - :type cluster_identifier: string - :param cluster_identifier: The unique identifier of the cluster to be - modified. - Example: `examplecluster` - - :type cluster_type: string - :param cluster_type: The new cluster type. - When you submit your cluster resize request, your existing cluster goes - into a read-only mode. After Amazon Redshift provisions a new - cluster based on your resize requirements, there will be outage for - a period while the old cluster is deleted and your connection is - switched to the new cluster. You can use DescribeResize to track - the progress of the resize request. - - Valid Values: ` multi-node | single-node ` - - :type node_type: string - :param node_type: The new node type of the cluster. If you specify a - new node type, you must also specify the number of nodes parameter - also. - When you submit your request to resize a cluster, Amazon Redshift sets - access permissions for the cluster to read-only. After Amazon - Redshift provisions a new cluster according to your resize - requirements, there will be a temporary outage while the old - cluster is deleted and your connection is switched to the new - cluster. When the new connection is complete, the original access - permissions for the cluster are restored. You can use the - DescribeResize to track the progress of the resize request. - - Valid Values: ` dw1.xlarge` | `dw1.8xlarge` | `dw2.large` | - `dw2.8xlarge`. - - :type number_of_nodes: integer - :param number_of_nodes: The new number of nodes of the cluster. If you - specify a new number of nodes, you must also specify the node type - parameter also. - When you submit your request to resize a cluster, Amazon Redshift sets - access permissions for the cluster to read-only. After Amazon - Redshift provisions a new cluster according to your resize - requirements, there will be a temporary outage while the old - cluster is deleted and your connection is switched to the new - cluster. When the new connection is complete, the original access - permissions for the cluster are restored. You can use - DescribeResize to track the progress of the resize request. - - Valid Values: Integer greater than `0`. - - :type cluster_security_groups: list - :param cluster_security_groups: - A list of cluster security groups to be authorized on this cluster. - This change is asynchronously applied as soon as possible. - - Security groups currently associated with the cluster, and not in the - list of groups to apply, will be revoked from the cluster. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters or hyphens - + First character must be a letter - + Cannot end with a hyphen or contain two consecutive hyphens - - :type vpc_security_group_ids: list - :param vpc_security_group_ids: A list of virtual private cloud (VPC) - security groups to be associated with the cluster. - - :type master_user_password: string - :param master_user_password: - The new password for the cluster master user. This change is - asynchronously applied as soon as possible. Between the time of the - request and the completion of the request, the `MasterUserPassword` - element exists in the `PendingModifiedValues` element of the - operation response. - - Default: Uses existing setting. - - Constraints: - - - + Must be between 8 and 64 characters in length. - + Must contain at least one uppercase letter. - + Must contain at least one lowercase letter. - + Must contain one number. - + Can be any printable ASCII character (ASCII code 33 to 126) except ' - (single quote), " (double quote), \, /, @, or space. - - :type cluster_parameter_group_name: string - :param cluster_parameter_group_name: The name of the cluster parameter - group to apply to this cluster. This change is applied only after - the cluster is rebooted. To reboot a cluster use RebootCluster. - Default: Uses existing setting. - - Constraints: The cluster parameter group must be in the same parameter - group family that matches the cluster version. - - :type automated_snapshot_retention_period: integer - :param automated_snapshot_retention_period: The number of days that - automated snapshots are retained. If the value is 0, automated - snapshots are disabled. Even if automated snapshots are disabled, - you can still create manual snapshots when you want with - CreateClusterSnapshot. - If you decrease the automated snapshot retention period from its - current value, existing automated snapshots that fall outside of - the new retention period will be immediately deleted. - - Default: Uses existing setting. - - Constraints: Must be a value from 0 to 35. - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which system maintenance can occur, if necessary. If system - maintenance is necessary during the window, it may result in an - outage. - This maintenance window change is made immediately. If the new - maintenance window indicates the current time, there must be at - least 120 minutes between the current time and end of the window in - order to ensure that pending changes are applied. - - Default: Uses existing setting. - - Format: ddd:hh24:mi-ddd:hh24:mi, for example `wed:07:30-wed:08:00`. - - Valid Days: Mon | Tue | Wed | Thu | Fri | Sat | Sun - - Constraints: Must be at least 30 minutes. - - :type cluster_version: string - :param cluster_version: The new version number of the Amazon Redshift - engine to upgrade to. - For major version upgrades, if a non-default cluster parameter group is - currently in use, a new cluster parameter group in the cluster - parameter group family for the new version must be specified. The - new cluster parameter group can be the default for that cluster - parameter group family. For more information about managing - parameter groups, go to `Amazon Redshift Parameter Groups`_ in the - Amazon Redshift Management Guide . - - Example: `1.0` - - :type allow_version_upgrade: boolean - :param allow_version_upgrade: If `True`, upgrades will be applied - automatically to the cluster during the maintenance window. - Default: `False` - - :type hsm_client_certificate_identifier: string - :param hsm_client_certificate_identifier: Specifies the name of the HSM - client certificate the Amazon Redshift cluster uses to retrieve the - data encryption keys stored in an HSM. - - :type hsm_configuration_identifier: string - :param hsm_configuration_identifier: Specifies the name of the HSM - configuration that contains the information the Amazon Redshift - cluster can use to retrieve and store keys in an HSM. - - :type new_cluster_identifier: string - :param new_cluster_identifier: The new identifier for the cluster. - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens. - + Alphabetic characters must be lowercase. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - + Must be unique for all clusters within an AWS account. - - - Example: `examplecluster` - - """ - params = {'ClusterIdentifier': cluster_identifier, } - if cluster_type is not None: - params['ClusterType'] = cluster_type - if node_type is not None: - params['NodeType'] = node_type - if number_of_nodes is not None: - params['NumberOfNodes'] = number_of_nodes - if cluster_security_groups is not None: - self.build_list_params(params, - cluster_security_groups, - 'ClusterSecurityGroups.member') - if vpc_security_group_ids is not None: - self.build_list_params(params, - vpc_security_group_ids, - 'VpcSecurityGroupIds.member') - if master_user_password is not None: - params['MasterUserPassword'] = master_user_password - if cluster_parameter_group_name is not None: - params['ClusterParameterGroupName'] = cluster_parameter_group_name - if automated_snapshot_retention_period is not None: - params['AutomatedSnapshotRetentionPeriod'] = automated_snapshot_retention_period - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if cluster_version is not None: - params['ClusterVersion'] = cluster_version - if allow_version_upgrade is not None: - params['AllowVersionUpgrade'] = str( - allow_version_upgrade).lower() - if hsm_client_certificate_identifier is not None: - params['HsmClientCertificateIdentifier'] = hsm_client_certificate_identifier - if hsm_configuration_identifier is not None: - params['HsmConfigurationIdentifier'] = hsm_configuration_identifier - if new_cluster_identifier is not None: - params['NewClusterIdentifier'] = new_cluster_identifier - return self._make_request( - action='ModifyCluster', - verb='POST', - path='/', params=params) - - def modify_cluster_parameter_group(self, parameter_group_name, - parameters): - """ - Modifies the parameters of a parameter group. - - For more information about managing parameter groups, go to - `Amazon Redshift Parameter Groups`_ in the Amazon Redshift - Management Guide . - - :type parameter_group_name: string - :param parameter_group_name: The name of the parameter group to be - modified. - - :type parameters: list - :param parameters: An array of parameters to be modified. A maximum of - 20 parameters can be modified in a single request. - For each parameter to be modified, you must supply at least the - parameter name and parameter value; other name-value pairs of the - parameter are optional. - - For the workload management (WLM) configuration, you must supply all - the name-value pairs in the wlm_json_configuration parameter. - - """ - params = {'ParameterGroupName': parameter_group_name, } - self.build_complex_list_params( - params, parameters, - 'Parameters.member', - ('ParameterName', 'ParameterValue', 'Description', 'Source', 'DataType', 'AllowedValues', 'IsModifiable', 'MinimumEngineVersion')) - return self._make_request( - action='ModifyClusterParameterGroup', - verb='POST', - path='/', params=params) - - def modify_cluster_subnet_group(self, cluster_subnet_group_name, - subnet_ids, description=None): - """ - Modifies a cluster subnet group to include the specified list - of VPC subnets. The operation replaces the existing list of - subnets with the new list of subnets. - - :type cluster_subnet_group_name: string - :param cluster_subnet_group_name: The name of the subnet group to be - modified. - - :type description: string - :param description: A text description of the subnet group to be - modified. - - :type subnet_ids: list - :param subnet_ids: An array of VPC subnet IDs. A maximum of 20 subnets - can be modified in a single request. - - """ - params = { - 'ClusterSubnetGroupName': cluster_subnet_group_name, - } - self.build_list_params(params, - subnet_ids, - 'SubnetIds.member') - if description is not None: - params['Description'] = description - return self._make_request( - action='ModifyClusterSubnetGroup', - verb='POST', - path='/', params=params) - - def modify_event_subscription(self, subscription_name, - sns_topic_arn=None, source_type=None, - source_ids=None, event_categories=None, - severity=None, enabled=None): - """ - Modifies an existing Amazon Redshift event notification - subscription. - - :type subscription_name: string - :param subscription_name: The name of the modified Amazon Redshift - event notification subscription. - - :type sns_topic_arn: string - :param sns_topic_arn: The Amazon Resource Name (ARN) of the SNS topic - to be used by the event notification subscription. - - :type source_type: string - :param source_type: The type of source that will be generating the - events. For example, if you want to be notified of events generated - by a cluster, you would set this parameter to cluster. If this - value is not specified, events are returned for all Amazon Redshift - objects in your AWS account. You must specify a source type in - order to specify source IDs. - Valid values: cluster, cluster-parameter-group, cluster-security-group, - and cluster-snapshot. - - :type source_ids: list - :param source_ids: A list of one or more identifiers of Amazon Redshift - source objects. All of the objects must be of the same type as was - specified in the source type parameter. The event subscription will - return only events generated by the specified objects. If not - specified, then events are returned for all objects within the - source type specified. - Example: my-cluster-1, my-cluster-2 - - Example: my-snapshot-20131010 - - :type event_categories: list - :param event_categories: Specifies the Amazon Redshift event categories - to be published by the event notification subscription. - Values: Configuration, Management, Monitoring, Security - - :type severity: string - :param severity: Specifies the Amazon Redshift event severity to be - published by the event notification subscription. - Values: ERROR, INFO - - :type enabled: boolean - :param enabled: A Boolean value indicating if the subscription is - enabled. `True` indicates the subscription is enabled - - """ - params = {'SubscriptionName': subscription_name, } - if sns_topic_arn is not None: - params['SnsTopicArn'] = sns_topic_arn - if source_type is not None: - params['SourceType'] = source_type - if source_ids is not None: - self.build_list_params(params, - source_ids, - 'SourceIds.member') - if event_categories is not None: - self.build_list_params(params, - event_categories, - 'EventCategories.member') - if severity is not None: - params['Severity'] = severity - if enabled is not None: - params['Enabled'] = str( - enabled).lower() - return self._make_request( - action='ModifyEventSubscription', - verb='POST', - path='/', params=params) - - def modify_snapshot_copy_retention_period(self, cluster_identifier, - retention_period): - """ - Modifies the number of days to retain automated snapshots in - the destination region after they are copied from the source - region. - - :type cluster_identifier: string - :param cluster_identifier: The unique identifier of the cluster for - which you want to change the retention period for automated - snapshots that are copied to a destination region. - Constraints: Must be the valid name of an existing cluster that has - cross-region snapshot copy enabled. - - :type retention_period: integer - :param retention_period: The number of days to retain automated - snapshots in the destination region after they are copied from the - source region. - If you decrease the retention period for automated snapshots that are - copied to a destination region, Amazon Redshift will delete any - existing automated snapshots that were copied to the destination - region and that fall outside of the new retention period. - - Constraints: Must be at least 1 and no more than 35. - - """ - params = { - 'ClusterIdentifier': cluster_identifier, - 'RetentionPeriod': retention_period, - } - return self._make_request( - action='ModifySnapshotCopyRetentionPeriod', - verb='POST', - path='/', params=params) - - def purchase_reserved_node_offering(self, reserved_node_offering_id, - node_count=None): - """ - Allows you to purchase reserved nodes. Amazon Redshift offers - a predefined set of reserved node offerings. You can purchase - one of the offerings. You can call the - DescribeReservedNodeOfferings API to obtain the available - reserved node offerings. You can call this API by providing a - specific reserved node offering and the number of nodes you - want to reserve. - - For more information about managing parameter groups, go to - `Purchasing Reserved Nodes`_ in the Amazon Redshift Management - Guide . - - :type reserved_node_offering_id: string - :param reserved_node_offering_id: The unique identifier of the reserved - node offering you want to purchase. - - :type node_count: integer - :param node_count: The number of reserved nodes you want to purchase. - Default: `1` - - """ - params = { - 'ReservedNodeOfferingId': reserved_node_offering_id, - } - if node_count is not None: - params['NodeCount'] = node_count - return self._make_request( - action='PurchaseReservedNodeOffering', - verb='POST', - path='/', params=params) - - def reboot_cluster(self, cluster_identifier): - """ - Reboots a cluster. This action is taken as soon as possible. - It results in a momentary outage to the cluster, during which - the cluster status is set to `rebooting`. A cluster event is - created when the reboot is completed. Any pending cluster - modifications (see ModifyCluster) are applied at this reboot. - For more information about managing clusters, go to `Amazon - Redshift Clusters`_ in the Amazon Redshift Management Guide - - :type cluster_identifier: string - :param cluster_identifier: The cluster identifier. - - """ - params = {'ClusterIdentifier': cluster_identifier, } - return self._make_request( - action='RebootCluster', - verb='POST', - path='/', params=params) - - def reset_cluster_parameter_group(self, parameter_group_name, - reset_all_parameters=None, - parameters=None): - """ - Sets one or more parameters of the specified parameter group - to their default values and sets the source values of the - parameters to "engine-default". To reset the entire parameter - group specify the ResetAllParameters parameter. For parameter - changes to take effect you must reboot any associated - clusters. - - :type parameter_group_name: string - :param parameter_group_name: The name of the cluster parameter group to - be reset. - - :type reset_all_parameters: boolean - :param reset_all_parameters: If `True`, all parameters in the specified - parameter group will be reset to their default values. - Default: `True` - - :type parameters: list - :param parameters: An array of names of parameters to be reset. If - ResetAllParameters option is not used, then at least one parameter - name must be supplied. - Constraints: A maximum of 20 parameters can be reset in a single - request. - - """ - params = {'ParameterGroupName': parameter_group_name, } - if reset_all_parameters is not None: - params['ResetAllParameters'] = str( - reset_all_parameters).lower() - if parameters is not None: - self.build_complex_list_params( - params, parameters, - 'Parameters.member', - ('ParameterName', 'ParameterValue', 'Description', 'Source', 'DataType', 'AllowedValues', 'IsModifiable', 'MinimumEngineVersion')) - return self._make_request( - action='ResetClusterParameterGroup', - verb='POST', - path='/', params=params) - - def restore_from_cluster_snapshot(self, cluster_identifier, - snapshot_identifier, - snapshot_cluster_identifier=None, - port=None, availability_zone=None, - allow_version_upgrade=None, - cluster_subnet_group_name=None, - publicly_accessible=None, - owner_account=None, - hsm_client_certificate_identifier=None, - hsm_configuration_identifier=None, - elastic_ip=None, - cluster_parameter_group_name=None, - cluster_security_groups=None, - vpc_security_group_ids=None, - preferred_maintenance_window=None, - automated_snapshot_retention_period=None): - """ - Creates a new cluster from a snapshot. Amazon Redshift creates - the resulting cluster with the same configuration as the - original cluster from which the snapshot was created, except - that the new cluster is created with the default cluster - security and parameter group. After Amazon Redshift creates - the cluster you can use the ModifyCluster API to associate a - different security group and different parameter group with - the restored cluster. - - If you restore a cluster into a VPC, you must provide a - cluster subnet group where you want the cluster restored. - - For more information about working with snapshots, go to - `Amazon Redshift Snapshots`_ in the Amazon Redshift Management - Guide . - - :type cluster_identifier: string - :param cluster_identifier: The identifier of the cluster that will be - created from restoring the snapshot. - - Constraints: - - - + Must contain from 1 to 63 alphanumeric characters or hyphens. - + Alphabetic characters must be lowercase. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - + Must be unique for all clusters within an AWS account. - - :type snapshot_identifier: string - :param snapshot_identifier: The name of the snapshot from which to - create the new cluster. This parameter isn't case sensitive. - Example: `my-snapshot-id` - - :type snapshot_cluster_identifier: string - :param snapshot_cluster_identifier: The name of the cluster the source - snapshot was created from. This parameter is required if your IAM - user has a policy containing a snapshot resource element that - specifies anything other than * for the cluster name. - - :type port: integer - :param port: The port number on which the cluster accepts connections. - Default: The same port as the original cluster. - - Constraints: Must be between `1115` and `65535`. - - :type availability_zone: string - :param availability_zone: The Amazon EC2 Availability Zone in which to - restore the cluster. - Default: A random, system-chosen Availability Zone. - - Example: `us-east-1a` - - :type allow_version_upgrade: boolean - :param allow_version_upgrade: If `True`, upgrades can be applied during - the maintenance window to the Amazon Redshift engine that is - running on the cluster. - Default: `True` - - :type cluster_subnet_group_name: string - :param cluster_subnet_group_name: The name of the subnet group where - you want to cluster restored. - A snapshot of cluster in VPC can be restored only in VPC. Therefore, - you must provide subnet group name where you want the cluster - restored. - - :type publicly_accessible: boolean - :param publicly_accessible: If `True`, the cluster can be accessed from - a public network. - - :type owner_account: string - :param owner_account: The AWS customer account used to create or copy - the snapshot. Required if you are restoring a snapshot you do not - own, optional if you own the snapshot. - - :type hsm_client_certificate_identifier: string - :param hsm_client_certificate_identifier: Specifies the name of the HSM - client certificate the Amazon Redshift cluster uses to retrieve the - data encryption keys stored in an HSM. - - :type hsm_configuration_identifier: string - :param hsm_configuration_identifier: Specifies the name of the HSM - configuration that contains the information the Amazon Redshift - cluster can use to retrieve and store keys in an HSM. - - :type elastic_ip: string - :param elastic_ip: The elastic IP (EIP) address for the cluster. - - :type cluster_parameter_group_name: string - :param cluster_parameter_group_name: - The name of the parameter group to be associated with this cluster. - - Default: The default Amazon Redshift cluster parameter group. For - information about the default parameter group, go to `Working with - Amazon Redshift Parameter Groups`_. - - Constraints: - - - + Must be 1 to 255 alphanumeric characters or hyphens. - + First character must be a letter. - + Cannot end with a hyphen or contain two consecutive hyphens. - - :type cluster_security_groups: list - :param cluster_security_groups: A list of security groups to be - associated with this cluster. - Default: The default cluster security group for Amazon Redshift. - - Cluster security groups only apply to clusters outside of VPCs. - - :type vpc_security_group_ids: list - :param vpc_security_group_ids: A list of Virtual Private Cloud (VPC) - security groups to be associated with the cluster. - Default: The default VPC security group is associated with the cluster. - - VPC security groups only apply to clusters in VPCs. - - :type preferred_maintenance_window: string - :param preferred_maintenance_window: The weekly time range (in UTC) - during which automated cluster maintenance can occur. - Format: `ddd:hh24:mi-ddd:hh24:mi` - - Default: The value selected for the cluster from which the snapshot was - taken. The following list shows the time blocks for each region - from which the default maintenance windows are assigned. - - - + **US-East (Northern Virginia) Region:** 03:00-11:00 UTC - + **US-West (Oregon) Region** 06:00-14:00 UTC - + **EU (Ireland) Region** 22:00-06:00 UTC - + **Asia Pacific (Singapore) Region** 14:00-22:00 UTC - + **Asia Pacific (Sydney) Region** 12:00-20:00 UTC - + **Asia Pacific (Tokyo) Region** 17:00-03:00 UTC - - - Valid Days: Mon | Tue | Wed | Thu | Fri | Sat | Sun - - Constraints: Minimum 30-minute window. - - :type automated_snapshot_retention_period: integer - :param automated_snapshot_retention_period: The number of days that - automated snapshots are retained. If the value is 0, automated - snapshots are disabled. Even if automated snapshots are disabled, - you can still create manual snapshots when you want with - CreateClusterSnapshot. - Default: The value selected for the cluster from which the snapshot was - taken. - - Constraints: Must be a value from 0 to 35. - - """ - params = { - 'ClusterIdentifier': cluster_identifier, - 'SnapshotIdentifier': snapshot_identifier, - } - if snapshot_cluster_identifier is not None: - params['SnapshotClusterIdentifier'] = snapshot_cluster_identifier - if port is not None: - params['Port'] = port - if availability_zone is not None: - params['AvailabilityZone'] = availability_zone - if allow_version_upgrade is not None: - params['AllowVersionUpgrade'] = str( - allow_version_upgrade).lower() - if cluster_subnet_group_name is not None: - params['ClusterSubnetGroupName'] = cluster_subnet_group_name - if publicly_accessible is not None: - params['PubliclyAccessible'] = str( - publicly_accessible).lower() - if owner_account is not None: - params['OwnerAccount'] = owner_account - if hsm_client_certificate_identifier is not None: - params['HsmClientCertificateIdentifier'] = hsm_client_certificate_identifier - if hsm_configuration_identifier is not None: - params['HsmConfigurationIdentifier'] = hsm_configuration_identifier - if elastic_ip is not None: - params['ElasticIp'] = elastic_ip - if cluster_parameter_group_name is not None: - params['ClusterParameterGroupName'] = cluster_parameter_group_name - if cluster_security_groups is not None: - self.build_list_params(params, - cluster_security_groups, - 'ClusterSecurityGroups.member') - if vpc_security_group_ids is not None: - self.build_list_params(params, - vpc_security_group_ids, - 'VpcSecurityGroupIds.member') - if preferred_maintenance_window is not None: - params['PreferredMaintenanceWindow'] = preferred_maintenance_window - if automated_snapshot_retention_period is not None: - params['AutomatedSnapshotRetentionPeriod'] = automated_snapshot_retention_period - return self._make_request( - action='RestoreFromClusterSnapshot', - verb='POST', - path='/', params=params) - - def revoke_cluster_security_group_ingress(self, - cluster_security_group_name, - cidrip=None, - ec2_security_group_name=None, - ec2_security_group_owner_id=None): - """ - Revokes an ingress rule in an Amazon Redshift security group - for a previously authorized IP range or Amazon EC2 security - group. To add an ingress rule, see - AuthorizeClusterSecurityGroupIngress. For information about - managing security groups, go to `Amazon Redshift Cluster - Security Groups`_ in the Amazon Redshift Management Guide . - - :type cluster_security_group_name: string - :param cluster_security_group_name: The name of the security Group from - which to revoke the ingress rule. - - :type cidrip: string - :param cidrip: The IP range for which to revoke access. This range must - be a valid Classless Inter-Domain Routing (CIDR) block of IP - addresses. If `CIDRIP` is specified, `EC2SecurityGroupName` and - `EC2SecurityGroupOwnerId` cannot be provided. - - :type ec2_security_group_name: string - :param ec2_security_group_name: The name of the EC2 Security Group - whose access is to be revoked. If `EC2SecurityGroupName` is - specified, `EC2SecurityGroupOwnerId` must also be provided and - `CIDRIP` cannot be provided. - - :type ec2_security_group_owner_id: string - :param ec2_security_group_owner_id: The AWS account number of the owner - of the security group specified in the `EC2SecurityGroupName` - parameter. The AWS access key ID is not an acceptable value. If - `EC2SecurityGroupOwnerId` is specified, `EC2SecurityGroupName` must - also be provided. and `CIDRIP` cannot be provided. - Example: `111122223333` - - """ - params = { - 'ClusterSecurityGroupName': cluster_security_group_name, - } - if cidrip is not None: - params['CIDRIP'] = cidrip - if ec2_security_group_name is not None: - params['EC2SecurityGroupName'] = ec2_security_group_name - if ec2_security_group_owner_id is not None: - params['EC2SecurityGroupOwnerId'] = ec2_security_group_owner_id - return self._make_request( - action='RevokeClusterSecurityGroupIngress', - verb='POST', - path='/', params=params) - - def revoke_snapshot_access(self, snapshot_identifier, - account_with_restore_access, - snapshot_cluster_identifier=None): - """ - Removes the ability of the specified AWS customer account to - restore the specified snapshot. If the account is currently - restoring the snapshot, the restore will run to completion. - - For more information about working with snapshots, go to - `Amazon Redshift Snapshots`_ in the Amazon Redshift Management - Guide . - - :type snapshot_identifier: string - :param snapshot_identifier: The identifier of the snapshot that the - account can no longer access. - - :type snapshot_cluster_identifier: string - :param snapshot_cluster_identifier: The identifier of the cluster the - snapshot was created from. This parameter is required if your IAM - user has a policy containing a snapshot resource element that - specifies anything other than * for the cluster name. - - :type account_with_restore_access: string - :param account_with_restore_access: The identifier of the AWS customer - account that can no longer restore the specified snapshot. - - """ - params = { - 'SnapshotIdentifier': snapshot_identifier, - 'AccountWithRestoreAccess': account_with_restore_access, - } - if snapshot_cluster_identifier is not None: - params['SnapshotClusterIdentifier'] = snapshot_cluster_identifier - return self._make_request( - action='RevokeSnapshotAccess', - verb='POST', - path='/', params=params) - - def rotate_encryption_key(self, cluster_identifier): - """ - Rotates the encryption keys for a cluster. - - :type cluster_identifier: string - :param cluster_identifier: The unique identifier of the cluster that - you want to rotate the encryption keys for. - Constraints: Must be the name of valid cluster that has encryption - enabled. - - """ - params = {'ClusterIdentifier': cluster_identifier, } - return self._make_request( - action='RotateEncryptionKey', - verb='POST', - path='/', params=params) - - def _make_request(self, action, verb, path, params): - params['ContentType'] = 'JSON' - response = self.make_request(action=action, verb='POST', - path='/', params=params) - body = response.read().decode('utf-8') - boto.log.debug(body) - if response.status == 200: - return json.loads(body) - else: - json_body = json.loads(body) - fault_name = json_body.get('Error', {}).get('Code', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/regioninfo.py b/awx/lib/site-packages/boto/regioninfo.py deleted file mode 100644 index 6aeda122f9..0000000000 --- a/awx/lib/site-packages/boto/regioninfo.py +++ /dev/null @@ -1,187 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import os - -import boto -from boto.compat import json -from boto.exception import BotoClientError - - -def load_endpoint_json(path): - """ - Loads a given JSON file & returns it. - - :param path: The path to the JSON file - :type path: string - - :returns: The loaded data - """ - with open(path, 'r') as endpoints_file: - return json.load(endpoints_file) - - -def merge_endpoints(defaults, additions): - """ - Given an existing set of endpoint data, this will deep-update it with - any similarly structured data in the additions. - - :param defaults: The existing endpoints data - :type defaults: dict - - :param defaults: The additional endpoints data - :type defaults: dict - - :returns: The modified endpoints data - :rtype: dict - """ - # We can't just do an ``defaults.update(...)`` here, as that could - # *overwrite* regions if present in both. - # We'll iterate instead, essentially doing a deeper merge. - for service, region_info in additions.items(): - # Set the default, if not present, to an empty dict. - defaults.setdefault(service, {}) - defaults[service].update(region_info) - - return defaults - - -def load_regions(): - """ - Actually load the region/endpoint information from the JSON files. - - By default, this loads from the default included ``boto/endpoints.json`` - file. - - Users can override/extend this by supplying either a ``BOTO_ENDPOINTS`` - environment variable or a ``endpoints_path`` config variable, either of - which should be an absolute path to the user's JSON file. - - :returns: The endpoints data - :rtype: dict - """ - # Load the defaults first. - endpoints = load_endpoint_json(boto.ENDPOINTS_PATH) - additional_path = None - - # Try the ENV var. If not, check the config file. - if os.environ.get('BOTO_ENDPOINTS'): - additional_path = os.environ['BOTO_ENDPOINTS'] - elif boto.config.get('Boto', 'endpoints_path'): - additional_path = boto.config.get('Boto', 'endpoints_path') - - # If there's a file provided, we'll load it & additively merge it into - # the endpoints. - if additional_path: - additional = load_endpoint_json(additional_path) - endpoints = merge_endpoints(endpoints, additional) - - return endpoints - - -def get_regions(service_name, region_cls=None, connection_cls=None): - """ - Given a service name (like ``ec2``), returns a list of ``RegionInfo`` - objects for that service. - - This leverages the ``endpoints.json`` file (+ optional user overrides) to - configure/construct all the objects. - - :param service_name: The name of the service to construct the ``RegionInfo`` - objects for. Ex: ``ec2``, ``s3``, ``sns``, etc. - :type service_name: string - - :param region_cls: (Optional) The class to use when constructing. By - default, this is ``RegionInfo``. - :type region_cls: class - - :param connection_cls: (Optional) The connection class for the - ``RegionInfo`` object. Providing this allows the ``connect`` method on - the ``RegionInfo`` to work. Default is ``None`` (no connection). - :type connection_cls: class - - :returns: A list of configured ``RegionInfo`` objects - :rtype: list - """ - endpoints = load_regions() - - if service_name not in endpoints: - raise BotoClientError( - "Service '%s' not found in endpoints." % service_name - ) - - if region_cls is None: - region_cls = RegionInfo - - region_objs = [] - - for region_name, endpoint in endpoints.get(service_name, {}).items(): - region_objs.append( - region_cls( - name=region_name, - endpoint=endpoint, - connection_cls=connection_cls - ) - ) - - return region_objs - - -class RegionInfo(object): - """ - Represents an AWS Region - """ - - def __init__(self, connection=None, name=None, endpoint=None, - connection_cls=None): - self.connection = connection - self.name = name - self.endpoint = endpoint - self.connection_cls = connection_cls - - def __repr__(self): - return 'RegionInfo:%s' % self.name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'regionName': - self.name = value - elif name == 'regionEndpoint': - self.endpoint = value - else: - setattr(self, name, value) - - def connect(self, **kw_params): - """ - Connect to this Region's endpoint. Returns an connection - object pointing to the endpoint associated with this region. - You may pass any of the arguments accepted by the connection - class's constructor as keyword arguments and they will be - passed along to the connection object. - - :rtype: Connection object - :return: The connection to this regions endpoint - """ - if self.connection_cls: - return self.connection_cls(region=self, **kw_params) diff --git a/awx/lib/site-packages/boto/requestlog.py b/awx/lib/site-packages/boto/requestlog.py deleted file mode 100644 index d8009fe76f..0000000000 --- a/awx/lib/site-packages/boto/requestlog.py +++ /dev/null @@ -1,39 +0,0 @@ -import sys -from datetime import datetime -from threading import Thread -import Queue - -from boto.utils import RequestHook -from boto.compat import long_type - - -class RequestLogger(RequestHook): - """ - This class implements a request logger that uses a single thread to - write to a log file. - """ - def __init__(self, filename='/tmp/request_log.csv'): - self.request_log_file = open(filename, 'w') - self.request_log_queue = Queue.Queue(100) - Thread(target=self._request_log_worker).start() - - def handle_request_data(self, request, response, error=False): - len = 0 if error else response.getheader('Content-Length') - now = datetime.now() - time = now.strftime('%Y-%m-%d %H:%M:%S') - td = (now - request.start_time) - duration = (td.microseconds + long_type(td.seconds + td.days * 24 * 3600) * 1e6) / 1e6 - - # write output including timestamp, status code, response time, response size, request action - self.request_log_queue.put("'%s', '%s', '%s', '%s', '%s'\n" % (time, response.status, duration, len, request.params['Action'])) - - def _request_log_worker(self): - while True: - try: - item = self.request_log_queue.get(True) - self.request_log_file.write(item) - self.request_log_file.flush() - self.request_log_queue.task_done() - except: - import traceback - traceback.print_exc(file=sys.stdout) diff --git a/awx/lib/site-packages/boto/resultset.py b/awx/lib/site-packages/boto/resultset.py deleted file mode 100644 index 189a47a3a2..0000000000 --- a/awx/lib/site-packages/boto/resultset.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.s3.user import User - - -class ResultSet(list): - """ - The ResultSet is used to pass results back from the Amazon services - to the client. It is light wrapper around Python's :py:class:`list` class, - with some additional methods for parsing XML results from AWS. - Because I don't really want any dependencies on external libraries, - I'm using the standard SAX parser that comes with Python. The good news is - that it's quite fast and efficient but it makes some things rather - difficult. - - You can pass in, as the marker_elem parameter, a list of tuples. - Each tuple contains a string as the first element which represents - the XML element that the resultset needs to be on the lookout for - and a Python class as the second element of the tuple. Each time the - specified element is found in the XML, a new instance of the class - will be created and popped onto the stack. - - :ivar str next_token: A hash used to assist in paging through very long - result sets. In most cases, passing this value to certain methods - will give you another 'page' of results. - """ - def __init__(self, marker_elem=None): - list.__init__(self) - if isinstance(marker_elem, list): - self.markers = marker_elem - else: - self.markers = [] - self.marker = None - self.key_marker = None - self.next_marker = None # avail when delimiter used - self.next_key_marker = None - self.next_upload_id_marker = None - self.next_version_id_marker = None - self.next_generation_marker = None - self.version_id_marker = None - self.is_truncated = False - self.next_token = None - self.status = True - - def startElement(self, name, attrs, connection): - for t in self.markers: - if name == t[0]: - obj = t[1](connection) - self.append(obj) - return obj - if name == 'Owner': - # Makes owner available for get_service and - # perhaps other lists where not handled by - # another element. - self.owner = User() - return self.owner - return None - - def to_boolean(self, value, true_value='true'): - if value == true_value: - return True - else: - return False - - def endElement(self, name, value, connection): - if name == 'IsTruncated': - self.is_truncated = self.to_boolean(value) - elif name == 'Marker': - self.marker = value - elif name == 'KeyMarker': - self.key_marker = value - elif name == 'NextMarker': - self.next_marker = value - elif name == 'NextKeyMarker': - self.next_key_marker = value - elif name == 'VersionIdMarker': - self.version_id_marker = value - elif name == 'NextVersionIdMarker': - self.next_version_id_marker = value - elif name == 'NextGenerationMarker': - self.next_generation_marker = value - elif name == 'UploadIdMarker': - self.upload_id_marker = value - elif name == 'NextUploadIdMarker': - self.next_upload_id_marker = value - elif name == 'Bucket': - self.bucket = value - elif name == 'MaxUploads': - self.max_uploads = int(value) - elif name == 'MaxItems': - self.max_items = int(value) - elif name == 'Prefix': - self.prefix = value - elif name == 'return': - self.status = self.to_boolean(value) - elif name == 'StatusCode': - self.status = self.to_boolean(value, 'Success') - elif name == 'ItemName': - self.append(value) - elif name == 'NextToken': - self.next_token = value - elif name == 'nextToken': - self.next_token = value - # Code exists which expects nextToken to be available, so we - # set it here to remain backwards-compatibile. - self.nextToken = value - elif name == 'BoxUsage': - try: - connection.box_usage += float(value) - except: - pass - elif name == 'IsValid': - self.status = self.to_boolean(value, 'True') - else: - setattr(self, name, value) - - -class BooleanResult(object): - - def __init__(self, marker_elem=None): - self.status = True - self.request_id = None - self.box_usage = None - - def __repr__(self): - if self.status: - return 'True' - else: - return 'False' - - def __nonzero__(self): - return self.status - - def startElement(self, name, attrs, connection): - return None - - def to_boolean(self, value, true_value='true'): - if value == true_value: - return True - else: - return False - - def endElement(self, name, value, connection): - if name == 'return': - self.status = self.to_boolean(value) - elif name == 'StatusCode': - self.status = self.to_boolean(value, 'Success') - elif name == 'IsValid': - self.status = self.to_boolean(value, 'True') - elif name == 'RequestId': - self.request_id = value - elif name == 'requestId': - self.request_id = value - elif name == 'BoxUsage': - self.request_id = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/roboto/__init__.py b/awx/lib/site-packages/boto/roboto/__init__.py deleted file mode 100644 index 792d600548..0000000000 --- a/awx/lib/site-packages/boto/roboto/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/awx/lib/site-packages/boto/roboto/awsqueryrequest.py b/awx/lib/site-packages/boto/roboto/awsqueryrequest.py deleted file mode 100644 index 793adf90ec..0000000000 --- a/awx/lib/site-packages/boto/roboto/awsqueryrequest.py +++ /dev/null @@ -1,503 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import sys -import os -import boto -import optparse -import copy -import boto.exception -import boto.roboto.awsqueryservice - -import bdb -import traceback -try: - import epdb as debugger -except ImportError: - import pdb as debugger - -def boto_except_hook(debugger_flag, debug_flag): - def excepthook(typ, value, tb): - if typ is bdb.BdbQuit: - sys.exit(1) - sys.excepthook = sys.__excepthook__ - - if debugger_flag and sys.stdout.isatty() and sys.stdin.isatty(): - if debugger.__name__ == 'epdb': - debugger.post_mortem(tb, typ, value) - else: - debugger.post_mortem(tb) - elif debug_flag: - print(traceback.print_tb(tb)) - sys.exit(1) - else: - print(value) - sys.exit(1) - - return excepthook - -class Line(object): - - def __init__(self, fmt, data, label): - self.fmt = fmt - self.data = data - self.label = label - self.line = '%s\t' % label - self.printed = False - - def append(self, datum): - self.line += '%s\t' % datum - - def print_it(self): - if not self.printed: - print(self.line) - self.printed = True - -class RequiredParamError(boto.exception.BotoClientError): - - def __init__(self, required): - self.required = required - s = 'Required parameters are missing: %s' % self.required - super(RequiredParamError, self).__init__(s) - -class EncoderError(boto.exception.BotoClientError): - - def __init__(self, error_msg): - s = 'Error encoding value (%s)' % error_msg - super(EncoderError, self).__init__(s) - -class FilterError(boto.exception.BotoClientError): - - def __init__(self, filters): - self.filters = filters - s = 'Unknown filters: %s' % self.filters - super(FilterError, self).__init__(s) - -class Encoder(object): - - @classmethod - def encode(cls, p, rp, v, label=None): - if p.name.startswith('_'): - return - try: - mthd = getattr(cls, 'encode_'+p.ptype) - mthd(p, rp, v, label) - except AttributeError: - raise EncoderError('Unknown type: %s' % p.ptype) - - @classmethod - def encode_string(cls, p, rp, v, l): - if l: - label = l - else: - label = p.name - rp[label] = v - - encode_file = encode_string - encode_enum = encode_string - - @classmethod - def encode_integer(cls, p, rp, v, l): - if l: - label = l - else: - label = p.name - rp[label] = '%d' % v - - @classmethod - def encode_boolean(cls, p, rp, v, l): - if l: - label = l - else: - label = p.name - if v: - v = 'true' - else: - v = 'false' - rp[label] = v - - @classmethod - def encode_datetime(cls, p, rp, v, l): - if l: - label = l - else: - label = p.name - rp[label] = v - - @classmethod - def encode_array(cls, p, rp, v, l): - v = boto.utils.mklist(v) - if l: - label = l - else: - label = p.name - label = label + '.%d' - for i, value in enumerate(v): - rp[label%(i+1)] = value - -class AWSQueryRequest(object): - - ServiceClass = None - - Description = '' - Params = [] - Args = [] - Filters = [] - Response = {} - - CLITypeMap = {'string' : 'string', - 'integer' : 'int', - 'int' : 'int', - 'enum' : 'choice', - 'datetime' : 'string', - 'dateTime' : 'string', - 'file' : 'string', - 'boolean' : None} - - @classmethod - def name(cls): - return cls.__name__ - - def __init__(self, **args): - self.args = args - self.parser = None - self.cli_options = None - self.cli_args = None - self.cli_output_format = None - self.connection = None - self.list_markers = [] - self.item_markers = [] - self.request_params = {} - self.connection_args = None - - def __repr__(self): - return self.name() - - def get_connection(self, **args): - if self.connection is None: - self.connection = self.ServiceClass(**args) - return self.connection - - @property - def status(self): - retval = None - if self.http_response is not None: - retval = self.http_response.status - return retval - - @property - def reason(self): - retval = None - if self.http_response is not None: - retval = self.http_response.reason - return retval - - @property - def request_id(self): - retval = None - if self.aws_response is not None: - retval = getattr(self.aws_response, 'requestId') - return retval - - def process_filters(self): - filters = self.args.get('filters', []) - filter_names = [f['name'] for f in self.Filters] - unknown_filters = [f for f in filters if f not in filter_names] - if unknown_filters: - raise FilterError('Unknown filters: %s' % unknown_filters) - for i, filter in enumerate(self.Filters): - name = filter['name'] - if name in filters: - self.request_params['Filter.%d.Name' % (i+1)] = name - for j, value in enumerate(boto.utils.mklist(filters[name])): - Encoder.encode(filter, self.request_params, value, - 'Filter.%d.Value.%d' % (i+1, j+1)) - - def process_args(self, **args): - """ - Responsible for walking through Params defined for the request and: - - * Matching them with keyword parameters passed to the request - constructor or via the command line. - * Checking to see if all required parameters have been specified - and raising an exception, if not. - * Encoding each value into the set of request parameters that will - be sent in the request to the AWS service. - """ - self.args.update(args) - self.connection_args = copy.copy(self.args) - if 'debug' in self.args and self.args['debug'] >= 2: - boto.set_stream_logger(self.name()) - required = [p.name for p in self.Params+self.Args if not p.optional] - for param in self.Params+self.Args: - if param.long_name: - python_name = param.long_name.replace('-', '_') - else: - python_name = boto.utils.pythonize_name(param.name, '_') - value = None - if python_name in self.args: - value = self.args[python_name] - if value is None: - value = param.default - if value is not None: - if param.name in required: - required.remove(param.name) - if param.request_param: - if param.encoder: - param.encoder(param, self.request_params, value) - else: - Encoder.encode(param, self.request_params, value) - if python_name in self.args: - del self.connection_args[python_name] - if required: - l = [] - for p in self.Params+self.Args: - if p.name in required: - if p.short_name and p.long_name: - l.append('(%s, %s)' % (p.optparse_short_name, - p.optparse_long_name)) - elif p.short_name: - l.append('(%s)' % p.optparse_short_name) - else: - l.append('(%s)' % p.optparse_long_name) - raise RequiredParamError(','.join(l)) - boto.log.debug('request_params: %s' % self.request_params) - self.process_markers(self.Response) - - def process_markers(self, fmt, prev_name=None): - if fmt and fmt['type'] == 'object': - for prop in fmt['properties']: - self.process_markers(prop, fmt['name']) - elif fmt and fmt['type'] == 'array': - self.list_markers.append(prev_name) - self.item_markers.append(fmt['name']) - - def send(self, verb='GET', **args): - self.process_args(**args) - self.process_filters() - conn = self.get_connection(**self.connection_args) - self.http_response = conn.make_request(self.name(), - self.request_params, - verb=verb) - self.body = self.http_response.read() - boto.log.debug(self.body) - if self.http_response.status == 200: - self.aws_response = boto.jsonresponse.Element(list_marker=self.list_markers, - item_marker=self.item_markers) - h = boto.jsonresponse.XmlHandler(self.aws_response, self) - h.parse(self.body) - return self.aws_response - else: - boto.log.error('%s %s' % (self.http_response.status, - self.http_response.reason)) - boto.log.error('%s' % self.body) - raise conn.ResponseError(self.http_response.status, - self.http_response.reason, - self.body) - - def add_standard_options(self): - group = optparse.OptionGroup(self.parser, 'Standard Options') - # add standard options that all commands get - group.add_option('-D', '--debug', action='store_true', - help='Turn on all debugging output') - group.add_option('--debugger', action='store_true', - default=False, - help='Enable interactive debugger on error') - group.add_option('-U', '--url', action='store', - help='Override service URL with value provided') - group.add_option('--region', action='store', - help='Name of the region to connect to') - group.add_option('-I', '--access-key-id', action='store', - help='Override access key value') - group.add_option('-S', '--secret-key', action='store', - help='Override secret key value') - group.add_option('--version', action='store_true', - help='Display version string') - if self.Filters: - self.group.add_option('--help-filters', action='store_true', - help='Display list of available filters') - self.group.add_option('--filter', action='append', - metavar=' name=value', - help='A filter for limiting the results') - self.parser.add_option_group(group) - - def process_standard_options(self, options, args, d): - if hasattr(options, 'help_filters') and options.help_filters: - print('Available filters:') - for filter in self.Filters: - print('%s\t%s' % (filter.name, filter.doc)) - sys.exit(0) - if options.debug: - self.args['debug'] = 2 - if options.url: - self.args['url'] = options.url - if options.region: - self.args['region'] = options.region - if options.access_key_id: - self.args['aws_access_key_id'] = options.access_key_id - if options.secret_key: - self.args['aws_secret_access_key'] = options.secret_key - if options.version: - # TODO - Where should the version # come from? - print('version x.xx') - exit(0) - sys.excepthook = boto_except_hook(options.debugger, - options.debug) - - def get_usage(self): - s = 'usage: %prog [options] ' - l = [ a.long_name for a in self.Args ] - s += ' '.join(l) - for a in self.Args: - if a.doc: - s += '\n\n\t%s - %s' % (a.long_name, a.doc) - return s - - def build_cli_parser(self): - self.parser = optparse.OptionParser(description=self.Description, - usage=self.get_usage()) - self.add_standard_options() - for param in self.Params: - ptype = action = choices = None - if param.ptype in self.CLITypeMap: - ptype = self.CLITypeMap[param.ptype] - action = 'store' - if param.ptype == 'boolean': - action = 'store_true' - elif param.ptype == 'array': - if len(param.items) == 1: - ptype = param.items[0]['type'] - action = 'append' - elif param.cardinality != 1: - action = 'append' - if ptype or action == 'store_true': - if param.short_name: - self.parser.add_option(param.optparse_short_name, - param.optparse_long_name, - action=action, type=ptype, - choices=param.choices, - help=param.doc) - elif param.long_name: - self.parser.add_option(param.optparse_long_name, - action=action, type=ptype, - choices=param.choices, - help=param.doc) - - def do_cli(self): - if not self.parser: - self.build_cli_parser() - self.cli_options, self.cli_args = self.parser.parse_args() - d = {} - self.process_standard_options(self.cli_options, self.cli_args, d) - for param in self.Params: - if param.long_name: - p_name = param.long_name.replace('-', '_') - else: - p_name = boto.utils.pythonize_name(param.name) - value = getattr(self.cli_options, p_name) - if param.ptype == 'file' and value: - if value == '-': - value = sys.stdin.read() - else: - path = os.path.expanduser(value) - path = os.path.expandvars(path) - if os.path.isfile(path): - fp = open(path) - value = fp.read() - fp.close() - else: - self.parser.error('Unable to read file: %s' % path) - d[p_name] = value - for arg in self.Args: - if arg.long_name: - p_name = arg.long_name.replace('-', '_') - else: - p_name = boto.utils.pythonize_name(arg.name) - value = None - if arg.cardinality == 1: - if len(self.cli_args) >= 1: - value = self.cli_args[0] - else: - value = self.cli_args - d[p_name] = value - self.args.update(d) - if hasattr(self.cli_options, 'filter') and self.cli_options.filter: - d = {} - for filter in self.cli_options.filter: - name, value = filter.split('=') - d[name] = value - if 'filters' in self.args: - self.args['filters'].update(d) - else: - self.args['filters'] = d - try: - response = self.main() - self.cli_formatter(response) - except RequiredParamError as e: - print(e) - sys.exit(1) - except self.ServiceClass.ResponseError as err: - print('Error(%s): %s' % (err.error_code, err.error_message)) - sys.exit(1) - except boto.roboto.awsqueryservice.NoCredentialsError as err: - print('Unable to find credentials.') - sys.exit(1) - except Exception as e: - print(e) - sys.exit(1) - - def _generic_cli_formatter(self, fmt, data, label=''): - if fmt['type'] == 'object': - for prop in fmt['properties']: - if 'name' in fmt: - if fmt['name'] in data: - data = data[fmt['name']] - if fmt['name'] in self.list_markers: - label = fmt['name'] - if label[-1] == 's': - label = label[0:-1] - label = label.upper() - self._generic_cli_formatter(prop, data, label) - elif fmt['type'] == 'array': - for item in data: - line = Line(fmt, item, label) - if isinstance(item, dict): - for field_name in item: - line.append(item[field_name]) - elif isinstance(item, basestring): - line.append(item) - line.print_it() - - def cli_formatter(self, data): - """ - This method is responsible for formatting the output for the - command line interface. The default behavior is to call the - generic CLI formatter which attempts to print something - reasonable. If you want specific formatting, you should - override this method and do your own thing. - - :type data: dict - :param data: The data returned by AWS. - """ - if data: - self._generic_cli_formatter(self.Response, data) - - diff --git a/awx/lib/site-packages/boto/roboto/awsqueryservice.py b/awx/lib/site-packages/boto/roboto/awsqueryservice.py deleted file mode 100644 index 9bf95ac2be..0000000000 --- a/awx/lib/site-packages/boto/roboto/awsqueryservice.py +++ /dev/null @@ -1,122 +0,0 @@ -from __future__ import print_function -import os -import urlparse -import boto -import boto.connection -import boto.jsonresponse -import boto.exception -from boto.roboto import awsqueryrequest - -class NoCredentialsError(boto.exception.BotoClientError): - - def __init__(self): - s = 'Unable to find credentials' - super(NoCredentialsError, self).__init__(s) - -class AWSQueryService(boto.connection.AWSQueryConnection): - - Name = '' - Description = '' - APIVersion = '' - Authentication = 'sign-v2' - Path = '/' - Port = 443 - Provider = 'aws' - EnvURL = 'AWS_URL' - - Regions = [] - - def __init__(self, **args): - self.args = args - self.check_for_credential_file() - self.check_for_env_url() - if 'host' not in self.args: - if self.Regions: - region_name = self.args.get('region_name', - self.Regions[0]['name']) - for region in self.Regions: - if region['name'] == region_name: - self.args['host'] = region['endpoint'] - if 'path' not in self.args: - self.args['path'] = self.Path - if 'port' not in self.args: - self.args['port'] = self.Port - try: - super(AWSQueryService, self).__init__(**self.args) - self.aws_response = None - except boto.exception.NoAuthHandlerFound: - raise NoCredentialsError() - - def check_for_credential_file(self): - """ - Checks for the existence of an AWS credential file. - If the environment variable AWS_CREDENTIAL_FILE is - set and points to a file, that file will be read and - will be searched credentials. - Note that if credentials have been explicitelypassed - into the class constructor, those values always take - precedence. - """ - if 'AWS_CREDENTIAL_FILE' in os.environ: - path = os.environ['AWS_CREDENTIAL_FILE'] - path = os.path.expanduser(path) - path = os.path.expandvars(path) - if os.path.isfile(path): - fp = open(path) - lines = fp.readlines() - fp.close() - for line in lines: - if line[0] != '#': - if '=' in line: - name, value = line.split('=', 1) - if name.strip() == 'AWSAccessKeyId': - if 'aws_access_key_id' not in self.args: - value = value.strip() - self.args['aws_access_key_id'] = value - elif name.strip() == 'AWSSecretKey': - if 'aws_secret_access_key' not in self.args: - value = value.strip() - self.args['aws_secret_access_key'] = value - else: - print('Warning: unable to read AWS_CREDENTIAL_FILE') - - def check_for_env_url(self): - """ - First checks to see if a url argument was explicitly passed - in. If so, that will be used. If not, it checks for the - existence of the environment variable specified in ENV_URL. - If this is set, it should contain a fully qualified URL to the - service you want to use. - Note that any values passed explicitly to the class constructor - will take precedence. - """ - url = self.args.get('url', None) - if url: - del self.args['url'] - if not url and self.EnvURL in os.environ: - url = os.environ[self.EnvURL] - if url: - rslt = urlparse.urlparse(url) - if 'is_secure' not in self.args: - if rslt.scheme == 'https': - self.args['is_secure'] = True - else: - self.args['is_secure'] = False - - host = rslt.netloc - port = None - l = host.split(':') - if len(l) > 1: - host = l[0] - port = int(l[1]) - if 'host' not in self.args: - self.args['host'] = host - if port and 'port' not in self.args: - self.args['port'] = port - - if rslt.path and 'path' not in self.args: - self.args['path'] = rslt.path - - def _required_auth_capability(self): - return [self.Authentication] - diff --git a/awx/lib/site-packages/boto/roboto/param.py b/awx/lib/site-packages/boto/roboto/param.py deleted file mode 100644 index 35a25b4af5..0000000000 --- a/awx/lib/site-packages/boto/roboto/param.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import os - -class Converter(object): - - @classmethod - def convert_string(cls, param, value): - # TODO: could do length validation, etc. here - if not isinstance(value, basestring): - raise ValueError - return value - - @classmethod - def convert_integer(cls, param, value): - # TODO: could do range checking here - return int(value) - - @classmethod - def convert_boolean(cls, param, value): - """ - For command line arguments, just the presence - of the option means True so just return True - """ - return True - - @classmethod - def convert_file(cls, param, value): - if os.path.exists(value) and not os.path.isdir(value): - return value - raise ValueError - - @classmethod - def convert_dir(cls, param, value): - if os.path.isdir(value): - return value - raise ValueError - - @classmethod - def convert(cls, param, value): - try: - if hasattr(cls, 'convert_'+param.ptype): - mthd = getattr(cls, 'convert_'+param.ptype) - else: - mthd = cls.convert_string - return mthd(param, value) - except: - raise ValidationException(param, '') - -class Param(Converter): - - def __init__(self, name=None, ptype='string', optional=True, - short_name=None, long_name=None, doc='', - metavar=None, cardinality=1, default=None, - choices=None, encoder=None, request_param=True): - self.name = name - self.ptype = ptype - self.optional = optional - self.short_name = short_name - self.long_name = long_name - self.doc = doc - self.metavar = metavar - self.cardinality = cardinality - self.default = default - self.choices = choices - self.encoder = encoder - self.request_param = request_param - - @property - def optparse_long_name(self): - ln = None - if self.long_name: - ln = '--%s' % self.long_name - return ln - - @property - def synopsis_long_name(self): - ln = None - if self.long_name: - ln = '--%s' % self.long_name - return ln - - @property - def getopt_long_name(self): - ln = None - if self.long_name: - ln = '%s' % self.long_name - if self.ptype != 'boolean': - ln += '=' - return ln - - @property - def optparse_short_name(self): - sn = None - if self.short_name: - sn = '-%s' % self.short_name - return sn - - @property - def synopsis_short_name(self): - sn = None - if self.short_name: - sn = '-%s' % self.short_name - return sn - - @property - def getopt_short_name(self): - sn = None - if self.short_name: - sn = '%s' % self.short_name - if self.ptype != 'boolean': - sn += ':' - return sn - - def convert(self, value): - """ - Convert a string value as received in the command line - tools and convert to the appropriate type of value. - Raise a ValidationError if the value can't be converted. - - :type value: str - :param value: The value to convert. This should always - be a string. - """ - return super(Param, self).convert(self,value) - - diff --git a/awx/lib/site-packages/boto/route53/__init__.py b/awx/lib/site-packages/boto/route53/__init__.py deleted file mode 100644 index 7b131f921d..0000000000 --- a/awx/lib/site-packages/boto/route53/__init__.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -# this is here for backward compatibility -# originally, the Route53Connection class was defined here -from boto.route53.connection import Route53Connection -from boto.regioninfo import RegionInfo, get_regions - - -class Route53RegionInfo(RegionInfo): - - def connect(self, **kw_params): - """ - Connect to this Region's endpoint. Returns an connection - object pointing to the endpoint associated with this region. - You may pass any of the arguments accepted by the connection - class's constructor as keyword arguments and they will be - passed along to the connection object. - - :rtype: Connection object - :return: The connection to this regions endpoint - """ - if self.connection_cls: - return self.connection_cls(host=self.endpoint, **kw_params) - - -def regions(): - """ - Get all available regions for the Route53 service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` instances - """ - regions = get_regions( - 'route53', - region_cls=Route53RegionInfo, - connection_cls=Route53Connection - ) - - # For historical reasons, we had a "universal" endpoint as well. - regions.append( - Route53RegionInfo( - name='universal', - endpoint='route53.amazonaws.com', - connection_cls=Route53Connection - ) - ) - - return regions - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.route53.connection.Route53Connection`. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.route53.connection.Route53Connection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/route53/connection.py b/awx/lib/site-packages/boto/route53/connection.py deleted file mode 100644 index c13ab2e010..0000000000 --- a/awx/lib/site-packages/boto/route53/connection.py +++ /dev/null @@ -1,543 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# Copyright (c) 2011 Blue Pines Technologies LLC, Brad Carleton -# www.bluepines.org -# Copyright (c) 2012 42 Lines Inc., Jim Browne -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.route53 import exception -import random -import uuid -import xml.sax - -import boto -from boto.connection import AWSAuthConnection -from boto import handler -import boto.jsonresponse -from boto.route53.record import ResourceRecordSets -from boto.route53.zone import Zone -from boto.compat import six, urllib - - -HZXML = """<?xml version="1.0" encoding="UTF-8"?> -<CreateHostedZoneRequest xmlns="%(xmlns)s"> - <Name>%(name)s</Name> - <CallerReference>%(caller_ref)s</CallerReference> - <HostedZoneConfig> - <Comment>%(comment)s</Comment> - </HostedZoneConfig> -</CreateHostedZoneRequest>""" - -# boto.set_stream_logger('dns') - - -class Route53Connection(AWSAuthConnection): - DefaultHost = 'route53.amazonaws.com' - """The default Route53 API endpoint to connect to.""" - - Version = '2013-04-01' - """Route53 API version.""" - - XMLNameSpace = 'https://route53.amazonaws.com/doc/2013-04-01/' - """XML schema for this Route53 API version.""" - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - port=None, proxy=None, proxy_port=None, - host=DefaultHost, debug=0, security_token=None, - validate_certs=True, https_connection_factory=None, - profile_name=None): - super(Route53Connection, self).__init__( - host, - aws_access_key_id, aws_secret_access_key, - True, port, proxy, proxy_port, debug=debug, - security_token=security_token, - validate_certs=validate_certs, - https_connection_factory=https_connection_factory, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['route53'] - - def make_request(self, action, path, headers=None, data='', params=None): - if params: - pairs = [] - for key, val in six.iteritems(params): - if val is None: - continue - pairs.append(key + '=' + urllib.parse.quote(str(val))) - path += '?' + '&'.join(pairs) - return super(Route53Connection, self).make_request( - action, path, headers, data, - retry_handler=self._retry_handler) - - # Hosted Zones - - def get_all_hosted_zones(self, start_marker=None, zone_list=None): - """ - Returns a Python data structure with information about all - Hosted Zones defined for the AWS account. - - :param int start_marker: start marker to pass when fetching additional - results after a truncated list - :param list zone_list: a HostedZones list to prepend to results - """ - params = {} - if start_marker: - params = {'marker': start_marker} - response = self.make_request('GET', '/%s/hostedzone' % self.Version, - params=params) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise exception.DNSServerError(response.status, - response.reason, - body) - e = boto.jsonresponse.Element(list_marker='HostedZones', - item_marker=('HostedZone',)) - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - if zone_list: - e['ListHostedZonesResponse']['HostedZones'].extend(zone_list) - while 'NextMarker' in e['ListHostedZonesResponse']: - next_marker = e['ListHostedZonesResponse']['NextMarker'] - zone_list = e['ListHostedZonesResponse']['HostedZones'] - e = self.get_all_hosted_zones(next_marker, zone_list) - return e - - def get_hosted_zone(self, hosted_zone_id): - """ - Get detailed information about a particular Hosted Zone. - - :type hosted_zone_id: str - :param hosted_zone_id: The unique identifier for the Hosted Zone - - """ - uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id) - response = self.make_request('GET', uri) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise exception.DNSServerError(response.status, - response.reason, - body) - e = boto.jsonresponse.Element(list_marker='NameServers', - item_marker=('NameServer',)) - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - - def get_hosted_zone_by_name(self, hosted_zone_name): - """ - Get detailed information about a particular Hosted Zone. - - :type hosted_zone_name: str - :param hosted_zone_name: The fully qualified domain name for the Hosted - Zone - - """ - if hosted_zone_name[-1] != '.': - hosted_zone_name += '.' - all_hosted_zones = self.get_all_hosted_zones() - for zone in all_hosted_zones['ListHostedZonesResponse']['HostedZones']: - # check that they gave us the FQDN for their zone - if zone['Name'] == hosted_zone_name: - return self.get_hosted_zone(zone['Id'].split('/')[-1]) - - def create_hosted_zone(self, domain_name, caller_ref=None, comment=''): - """ - Create a new Hosted Zone. Returns a Python data structure with - information about the newly created Hosted Zone. - - :type domain_name: str - :param domain_name: The name of the domain. This should be a - fully-specified domain, and should end with a final period - as the last label indication. If you omit the final period, - Amazon Route 53 assumes the domain is relative to the root. - This is the name you have registered with your DNS registrar. - It is also the name you will delegate from your registrar to - the Amazon Route 53 delegation servers returned in - response to this request.A list of strings with the image - IDs wanted. - - :type caller_ref: str - :param caller_ref: A unique string that identifies the request - and that allows failed CreateHostedZone requests to be retried - without the risk of executing the operation twice. If you don't - provide a value for this, boto will generate a Type 4 UUID and - use that. - - :type comment: str - :param comment: Any comments you want to include about the hosted - zone. - - """ - if caller_ref is None: - caller_ref = str(uuid.uuid4()) - params = {'name': domain_name, - 'caller_ref': caller_ref, - 'comment': comment, - 'xmlns': self.XMLNameSpace} - xml_body = HZXML % params - uri = '/%s/hostedzone' % self.Version - response = self.make_request('POST', uri, - {'Content-Type': 'text/xml'}, xml_body) - body = response.read() - boto.log.debug(body) - if response.status == 201: - e = boto.jsonresponse.Element(list_marker='NameServers', - item_marker=('NameServer',)) - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - else: - raise exception.DNSServerError(response.status, - response.reason, - body) - - def delete_hosted_zone(self, hosted_zone_id): - """ - Delete the hosted zone specified by the given id. - - :type hosted_zone_id: str - :param hosted_zone_id: The hosted zone's id - - """ - uri = '/%s/hostedzone/%s' % (self.Version, hosted_zone_id) - response = self.make_request('DELETE', uri) - body = response.read() - boto.log.debug(body) - if response.status not in (200, 204): - raise exception.DNSServerError(response.status, - response.reason, - body) - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - - # Health checks - - POSTHCXMLBody = """<CreateHealthCheckRequest xmlns="%(xmlns)s"> - <CallerReference>%(caller_ref)s</CallerReference> - %(health_check)s - </CreateHealthCheckRequest>""" - - def create_health_check(self, health_check, caller_ref=None): - """ - Create a new Health Check - - :type health_check: HealthCheck - :param health_check: HealthCheck object - - :type caller_ref: str - :param caller_ref: A unique string that identifies the request - and that allows failed CreateHealthCheckRequest requests to be retried - without the risk of executing the operation twice. If you don't - provide a value for this, boto will generate a Type 4 UUID and - use that. - - """ - if caller_ref is None: - caller_ref = str(uuid.uuid4()) - uri = '/%s/healthcheck' % self.Version - params = {'xmlns': self.XMLNameSpace, - 'caller_ref': caller_ref, - 'health_check': health_check.to_xml() - } - xml_body = self.POSTHCXMLBody % params - response = self.make_request('POST', uri, {'Content-Type': 'text/xml'}, xml_body) - body = response.read() - boto.log.debug(body) - if response.status == 201: - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - else: - raise exception.DNSServerError(response.status, response.reason, body) - - def get_list_health_checks(self, maxitems=None, marker=None): - """ - Return a list of health checks - - :type maxitems: int - :param maxitems: Maximum number of items to return - - :type marker: str - :param marker: marker to get next set of items to list - - """ - - params = {} - if maxitems is not None: - params['maxitems'] = maxitems - if marker is not None: - params['marker'] = marker - - uri = '/%s/healthcheck' % (self.Version, ) - response = self.make_request('GET', uri, params=params) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise exception.DNSServerError(response.status, - response.reason, - body) - e = boto.jsonresponse.Element(list_marker='HealthChecks', item_marker=('HealthCheck',)) - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - - def delete_health_check(self, health_check_id): - """ - Delete a health check - - :type health_check_id: str - :param health_check_id: ID of the health check to delete - - """ - uri = '/%s/healthcheck/%s' % (self.Version, health_check_id) - response = self.make_request('DELETE', uri) - body = response.read() - boto.log.debug(body) - if response.status not in (200, 204): - raise exception.DNSServerError(response.status, - response.reason, - body) - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - - # Resource Record Sets - - def get_all_rrsets(self, hosted_zone_id, type=None, - name=None, identifier=None, maxitems=None): - """ - Retrieve the Resource Record Sets defined for this Hosted Zone. - Returns the raw XML data returned by the Route53 call. - - :type hosted_zone_id: str - :param hosted_zone_id: The unique identifier for the Hosted Zone - - :type type: str - :param type: The type of resource record set to begin the record - listing from. Valid choices are: - - * A - * AAAA - * CNAME - * MX - * NS - * PTR - * SOA - * SPF - * SRV - * TXT - - Valid values for weighted resource record sets: - - * A - * AAAA - * CNAME - * TXT - - Valid values for Zone Apex Aliases: - - * A - * AAAA - - :type name: str - :param name: The first name in the lexicographic ordering of domain - names to be retrieved - - :type identifier: str - :param identifier: In a hosted zone that includes weighted resource - record sets (multiple resource record sets with the same DNS - name and type that are differentiated only by SetIdentifier), - if results were truncated for a given DNS name and type, - the value of SetIdentifier for the next resource record - set that has the current DNS name and type - - :type maxitems: int - :param maxitems: The maximum number of records - - """ - params = {'type': type, 'name': name, - 'identifier': identifier, 'maxitems': maxitems} - uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) - response = self.make_request('GET', uri, params=params) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise exception.DNSServerError(response.status, - response.reason, - body) - rs = ResourceRecordSets(connection=self, hosted_zone_id=hosted_zone_id) - h = handler.XmlHandler(rs, self) - xml.sax.parseString(body, h) - return rs - - def change_rrsets(self, hosted_zone_id, xml_body): - """ - Create or change the authoritative DNS information for this - Hosted Zone. - Returns a Python data structure with information about the set of - changes, including the Change ID. - - :type hosted_zone_id: str - :param hosted_zone_id: The unique identifier for the Hosted Zone - - :type xml_body: str - :param xml_body: The list of changes to be made, defined in the - XML schema defined by the Route53 service. - - """ - uri = '/%s/hostedzone/%s/rrset' % (self.Version, hosted_zone_id) - response = self.make_request('POST', uri, - {'Content-Type': 'text/xml'}, - xml_body) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise exception.DNSServerError(response.status, - response.reason, - body) - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - - def get_change(self, change_id): - """ - Get information about a proposed set of changes, as submitted - by the change_rrsets method. - Returns a Python data structure with status information about the - changes. - - :type change_id: str - :param change_id: The unique identifier for the set of changes. - This ID is returned in the response to the change_rrsets method. - - """ - uri = '/%s/change/%s' % (self.Version, change_id) - response = self.make_request('GET', uri) - body = response.read() - boto.log.debug(body) - if response.status >= 300: - raise exception.DNSServerError(response.status, - response.reason, - body) - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - - def create_zone(self, name): - """ - Create a new Hosted Zone. Returns a Zone object for the newly - created Hosted Zone. - - :type name: str - :param name: The name of the domain. This should be a - fully-specified domain, and should end with a final period - as the last label indication. If you omit the final period, - Amazon Route 53 assumes the domain is relative to the root. - This is the name you have registered with your DNS registrar. - It is also the name you will delegate from your registrar to - the Amazon Route 53 delegation servers returned in - response to this request. - """ - zone = self.create_hosted_zone(name) - return Zone(self, zone['CreateHostedZoneResponse']['HostedZone']) - - def get_zone(self, name): - """ - Returns a Zone object for the specified Hosted Zone. - - :param name: The name of the domain. This should be a - fully-specified domain, and should end with a final period - as the last label indication. - """ - name = self._make_qualified(name) - for zone in self.get_zones(): - if name == zone.name: - return zone - - def get_zones(self): - """ - Returns a list of Zone objects, one for each of the Hosted - Zones defined for the AWS account. - - :rtype: list - :returns: A list of Zone objects. - - """ - zones = self.get_all_hosted_zones() - return [Zone(self, zone) for zone in - zones['ListHostedZonesResponse']['HostedZones']] - - def _make_qualified(self, value): - """ - Ensure passed domain names end in a period (.) character. - This will usually make a domain fully qualified. - """ - if type(value) in [list, tuple, set]: - new_list = [] - for record in value: - if record and not record[-1] == '.': - new_list.append("%s." % record) - else: - new_list.append(record) - return new_list - else: - value = value.strip() - if value and not value[-1] == '.': - value = "%s." % value - return value - - def _retry_handler(self, response, i, next_sleep): - status = None - boto.log.debug("Saw HTTP status: %s" % response.status) - - if response.status == 400: - code = response.getheader('Code') - - if code: - # This is a case where we need to ignore a 400 error, as - # Route53 returns this. See - # http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html - if 'PriorRequestNotComplete' in code: - error = 'PriorRequestNotComplete' - elif 'Throttling' in code: - error = 'Throttling' - else: - return status - msg = "%s, retry attempt %s" % ( - error, - i - ) - next_sleep = min(random.random() * (2 ** i), - boto.config.get('Boto', 'max_retry_delay', 60)) - i += 1 - status = (msg, i, next_sleep) - - return status diff --git a/awx/lib/site-packages/boto/route53/domains/__init__.py b/awx/lib/site-packages/boto/route53/domains/__init__.py deleted file mode 100644 index ecd07210d5..0000000000 --- a/awx/lib/site-packages/boto/route53/domains/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon Route 53 Domains service. - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.route53.domains.layer1 import Route53DomainsConnection - return get_regions('route53domains', - connection_cls=Route53DomainsConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/route53/domains/exceptions.py b/awx/lib/site-packages/boto/route53/domains/exceptions.py deleted file mode 100644 index 51eb673003..0000000000 --- a/awx/lib/site-packages/boto/route53/domains/exceptions.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import BotoServerError - - -class DuplicateRequest(BotoServerError): - pass - - -class DomainLimitExceeded(BotoServerError): - pass - - -class InvalidInput(BotoServerError): - pass - - -class OperationLimitExceeded(BotoServerError): - pass - - -class UnsupportedTLD(BotoServerError): - pass - - -class TLDRulesViolation(BotoServerError): - pass diff --git a/awx/lib/site-packages/boto/route53/domains/layer1.py b/awx/lib/site-packages/boto/route53/domains/layer1.py deleted file mode 100644 index 537948f7b7..0000000000 --- a/awx/lib/site-packages/boto/route53/domains/layer1.py +++ /dev/null @@ -1,868 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.route53.domains import exceptions - - -class Route53DomainsConnection(AWSQueryConnection): - """ - - """ - APIVersion = "2014-05-15" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "route53domains.us-east-1.amazonaws.com" - ServiceName = "Route53Domains" - TargetPrefix = "Route53Domains_v20140515" - ResponseError = JSONResponseError - - _faults = { - "DuplicateRequest": exceptions.DuplicateRequest, - "DomainLimitExceeded": exceptions.DomainLimitExceeded, - "InvalidInput": exceptions.InvalidInput, - "OperationLimitExceeded": exceptions.OperationLimitExceeded, - "UnsupportedTLD": exceptions.UnsupportedTLD, - "TLDRulesViolation": exceptions.TLDRulesViolation, - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs or kwargs['host'] is None: - kwargs['host'] = region.endpoint - - super(Route53DomainsConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def check_domain_availability(self, domain_name, idn_lang_code=None): - """ - This operation checks the availability of one domain name. You - can access this API without authenticating. Note that if the - availability status of a domain is pending, you must submit - another request to determine the availability of the domain - name. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - :type idn_lang_code: string - :param idn_lang_code: Reserved for future use. - - """ - params = {'DomainName': domain_name, } - if idn_lang_code is not None: - params['IdnLangCode'] = idn_lang_code - return self.make_request(action='CheckDomainAvailability', - body=json.dumps(params)) - - def disable_domain_transfer_lock(self, domain_name): - """ - This operation removes the transfer lock on the domain - (specifically the `clientTransferProhibited` status) to allow - domain transfers. We recommend you refrain from performing - this action unless you intend to transfer the domain to a - different registrar. Successful submission returns an - operation ID that you can use to track the progress and - completion of the action. If the request is not completed - successfully, the domain registrant will be notified by email. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - """ - params = {'DomainName': domain_name, } - return self.make_request(action='DisableDomainTransferLock', - body=json.dumps(params)) - - def enable_domain_transfer_lock(self, domain_name): - """ - This operation sets the transfer lock on the domain - (specifically the `clientTransferProhibited` status) to - prevent domain transfers. Successful submission returns an - operation ID that you can use to track the progress and - completion of the action. If the request is not completed - successfully, the domain registrant will be notified by email. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - """ - params = {'DomainName': domain_name, } - return self.make_request(action='EnableDomainTransferLock', - body=json.dumps(params)) - - def get_domain_detail(self, domain_name): - """ - This operation returns detailed information about the domain. - The domain's contact information is also returned as part of - the output. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - """ - params = {'DomainName': domain_name, } - return self.make_request(action='GetDomainDetail', - body=json.dumps(params)) - - def get_operation_detail(self, operation_id): - """ - This operation returns the current status of an operation that - is not completed. - - :type operation_id: string - :param operation_id: The identifier for the operation for which you - want to get the status. Amazon Route 53 returned the identifier in - the response to the original request. - Type: String - - Default: None - - Required: Yes - - """ - params = {'OperationId': operation_id, } - return self.make_request(action='GetOperationDetail', - body=json.dumps(params)) - - def list_domains(self, marker=None, max_items=None): - """ - This operation returns all the domain names registered with - Amazon Route 53 for the current AWS account. - - :type marker: string - :param marker: For an initial request for a list of domains, omit this - element. If the number of domains that are associated with the - current AWS account is greater than the value that you specified - for `MaxItems`, you can use `Marker` to return additional domains. - Get the value of `NextPageMarker` from the previous response, and - submit another request that includes the value of `NextPageMarker` - in the `Marker` element. - Type: String - - Default: None - - Constraints: The marker must match the value specified in the previous - request. - - Required: No - - :type max_items: integer - :param max_items: Number of domains to be returned. - Type: Integer - - Default: 20 - - Constraints: A numeral between 1 and 100. - - Required: No - - """ - params = {} - if marker is not None: - params['Marker'] = marker - if max_items is not None: - params['MaxItems'] = max_items - return self.make_request(action='ListDomains', - body=json.dumps(params)) - - def list_operations(self, marker=None, max_items=None): - """ - This operation returns the operation IDs of operations that - are not yet complete. - - :type marker: string - :param marker: For an initial request for a list of operations, omit - this element. If the number of operations that are not yet complete - is greater than the value that you specified for `MaxItems`, you - can use `Marker` to return additional operations. Get the value of - `NextPageMarker` from the previous response, and submit another - request that includes the value of `NextPageMarker` in the `Marker` - element. - Type: String - - Default: None - - Required: No - - :type max_items: integer - :param max_items: Number of domains to be returned. - Type: Integer - - Default: 20 - - Constraints: A value between 1 and 100. - - Required: No - - """ - params = {} - if marker is not None: - params['Marker'] = marker - if max_items is not None: - params['MaxItems'] = max_items - return self.make_request(action='ListOperations', - body=json.dumps(params)) - - def register_domain(self, domain_name, duration_in_years, admin_contact, - registrant_contact, tech_contact, idn_lang_code=None, - auto_renew=None, privacy_protect_admin_contact=None, - privacy_protect_registrant_contact=None, - privacy_protect_tech_contact=None): - """ - This operation registers a domain. Domains are registered by - the AWS registrar partner, Gandi. For some top-level domains - (TLDs), this operation requires extra parameters. - - When you register a domain, Amazon Route 53 does the - following: - - - + Creates a Amazon Route 53 hosted zone that has the same name - as the domain. Amazon Route 53 assigns four name servers to - your hosted zone and automatically updates your domain - registration with the names of these name servers. - + Enables autorenew, so your domain registration will renew - automatically each year. We'll notify you in advance of the - renewal date so you can choose whether to renew the - registration. - + Optionally enables privacy protection, so WHOIS queries - return contact information for our registrar partner, Gandi, - instead of the information you entered for registrant, admin, - and tech contacts. - + If registration is successful, returns an operation ID that - you can use to track the progress and completion of the - action. If the request is not completed successfully, the - domain registrant is notified by email. - + Charges your AWS account an amount based on the top-level - domain. For more information, see `Amazon Route 53 Pricing`_. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - :type idn_lang_code: string - :param idn_lang_code: Reserved for future use. - - :type duration_in_years: integer - :param duration_in_years: The number of years the domain will be - registered. Domains are registered for a minimum of one year. The - maximum period depends on the top-level domain. - Type: Integer - - Default: 1 - - Valid values: Integer from 1 to 10 - - Required: Yes - - :type auto_renew: boolean - :param auto_renew: Indicates whether the domain will be automatically - renewed ( `True`) or not ( `False`). Autorenewal only takes effect - after the account is charged. - Type: Boolean - - Valid values: `True` | `False` - - Default: `True` - - Required: No - - :type admin_contact: dict - :param admin_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type registrant_contact: dict - :param registrant_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type tech_contact: dict - :param tech_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type privacy_protect_admin_contact: boolean - :param privacy_protect_admin_contact: Whether you want to conceal - contact information from WHOIS queries. If you specify true, WHOIS - ("who is") queries will return contact information for our - registrar partner, Gandi, instead of the contact information that - you enter. - Type: Boolean - - Default: `True` - - Valid values: `True` | `False` - - Required: No - - :type privacy_protect_registrant_contact: boolean - :param privacy_protect_registrant_contact: Whether you want to conceal - contact information from WHOIS queries. If you specify true, WHOIS - ("who is") queries will return contact information for our - registrar partner, Gandi, instead of the contact information that - you enter. - Type: Boolean - - Default: `True` - - Valid values: `True` | `False` - - Required: No - - :type privacy_protect_tech_contact: boolean - :param privacy_protect_tech_contact: Whether you want to conceal - contact information from WHOIS queries. If you specify true, WHOIS - ("who is") queries will return contact information for our - registrar partner, Gandi, instead of the contact information that - you enter. - Type: Boolean - - Default: `True` - - Valid values: `True` | `False` - - Required: No - - """ - params = { - 'DomainName': domain_name, - 'DurationInYears': duration_in_years, - 'AdminContact': admin_contact, - 'RegistrantContact': registrant_contact, - 'TechContact': tech_contact, - } - if idn_lang_code is not None: - params['IdnLangCode'] = idn_lang_code - if auto_renew is not None: - params['AutoRenew'] = auto_renew - if privacy_protect_admin_contact is not None: - params['PrivacyProtectAdminContact'] = privacy_protect_admin_contact - if privacy_protect_registrant_contact is not None: - params['PrivacyProtectRegistrantContact'] = privacy_protect_registrant_contact - if privacy_protect_tech_contact is not None: - params['PrivacyProtectTechContact'] = privacy_protect_tech_contact - return self.make_request(action='RegisterDomain', - body=json.dumps(params)) - - def retrieve_domain_auth_code(self, domain_name): - """ - This operation returns the AuthCode for the domain. To - transfer a domain to another registrar, you provide this value - to the new registrar. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - """ - params = {'DomainName': domain_name, } - return self.make_request(action='RetrieveDomainAuthCode', - body=json.dumps(params)) - - def transfer_domain(self, domain_name, duration_in_years, nameservers, - admin_contact, registrant_contact, tech_contact, - idn_lang_code=None, auth_code=None, auto_renew=None, - privacy_protect_admin_contact=None, - privacy_protect_registrant_contact=None, - privacy_protect_tech_contact=None): - """ - This operation transfers a domain from another registrar to - Amazon Route 53. Domains are registered by the AWS registrar, - Gandi upon transfer. - - To transfer a domain, you need to meet all the domain transfer - criteria, including the following: - - - + You must supply nameservers to transfer a domain. - + You must disable the domain transfer lock (if any) before - transferring the domain. - + A minimum of 60 days must have elapsed since the domain's - registration or last transfer. - - - We recommend you use the Amazon Route 53 as the DNS service - for your domain. You can create a hosted zone in Amazon Route - 53 for your current domain before transferring your domain. - - Note that upon transfer, the domain duration is extended for a - year if not otherwise specified. Autorenew is enabled by - default. - - If the transfer is successful, this method returns an - operation ID that you can use to track the progress and - completion of the action. If the request is not completed - successfully, the domain registrant will be notified by email. - - Transferring domains charges your AWS account an amount based - on the top-level domain. For more information, see `Amazon - Route 53 Pricing`_. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - :type idn_lang_code: string - :param idn_lang_code: Reserved for future use. - - :type duration_in_years: integer - :param duration_in_years: The number of years the domain will be - registered. Domains are registered for a minimum of one year. The - maximum period depends on the top-level domain. - Type: Integer - - Default: 1 - - Valid values: Integer from 1 to 10 - - Required: Yes - - :type nameservers: list - :param nameservers: Contains details for the host and glue IP - addresses. - Type: Complex - - Children: `GlueIps`, `Name` - - :type auth_code: string - :param auth_code: The authorization code for the domain. You get this - value from the current registrar. - Type: String - - Required: Yes - - :type auto_renew: boolean - :param auto_renew: Indicates whether the domain will be automatically - renewed (true) or not (false). Autorenewal only takes effect after - the account is charged. - Type: Boolean - - Valid values: `True` | `False` - - Default: true - - Required: No - - :type admin_contact: dict - :param admin_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type registrant_contact: dict - :param registrant_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type tech_contact: dict - :param tech_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type privacy_protect_admin_contact: boolean - :param privacy_protect_admin_contact: Whether you want to conceal - contact information from WHOIS queries. If you specify true, WHOIS - ("who is") queries will return contact information for our - registrar partner, Gandi, instead of the contact information that - you enter. - Type: Boolean - - Default: `True` - - Valid values: `True` | `False` - - Required: No - - :type privacy_protect_registrant_contact: boolean - :param privacy_protect_registrant_contact: Whether you want to conceal - contact information from WHOIS queries. If you specify true, WHOIS - ("who is") queries will return contact information for our - registrar partner, Gandi, instead of the contact information that - you enter. - Type: Boolean - - Default: `True` - - Valid values: `True` | `False` - - Required: No - - :type privacy_protect_tech_contact: boolean - :param privacy_protect_tech_contact: Whether you want to conceal - contact information from WHOIS queries. If you specify true, WHOIS - ("who is") queries will return contact information for our - registrar partner, Gandi, instead of the contact information that - you enter. - Type: Boolean - - Default: `True` - - Valid values: `True` | `False` - - Required: No - - """ - params = { - 'DomainName': domain_name, - 'DurationInYears': duration_in_years, - 'Nameservers': nameservers, - 'AdminContact': admin_contact, - 'RegistrantContact': registrant_contact, - 'TechContact': tech_contact, - } - if idn_lang_code is not None: - params['IdnLangCode'] = idn_lang_code - if auth_code is not None: - params['AuthCode'] = auth_code - if auto_renew is not None: - params['AutoRenew'] = auto_renew - if privacy_protect_admin_contact is not None: - params['PrivacyProtectAdminContact'] = privacy_protect_admin_contact - if privacy_protect_registrant_contact is not None: - params['PrivacyProtectRegistrantContact'] = privacy_protect_registrant_contact - if privacy_protect_tech_contact is not None: - params['PrivacyProtectTechContact'] = privacy_protect_tech_contact - return self.make_request(action='TransferDomain', - body=json.dumps(params)) - - def update_domain_contact(self, domain_name, admin_contact=None, - registrant_contact=None, tech_contact=None): - """ - This operation updates the contact information for a - particular domain. Information for at least one contact - (registrant, administrator, or technical) must be supplied for - update. - - If the update is successful, this method returns an operation - ID that you can use to track the progress and completion of - the action. If the request is not completed successfully, the - domain registrant will be notified by email. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - :type admin_contact: dict - :param admin_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type registrant_contact: dict - :param registrant_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - :type tech_contact: dict - :param tech_contact: Provides detailed contact information. - Type: Complex - - Children: `FirstName`, `MiddleName`, `LastName`, `ContactType`, - `OrganizationName`, `AddressLine1`, `AddressLine2`, `City`, - `State`, `CountryCode`, `ZipCode`, `PhoneNumber`, `Email`, `Fax`, - `ExtraParams` - - Required: Yes - - """ - params = {'DomainName': domain_name, } - if admin_contact is not None: - params['AdminContact'] = admin_contact - if registrant_contact is not None: - params['RegistrantContact'] = registrant_contact - if tech_contact is not None: - params['TechContact'] = tech_contact - return self.make_request(action='UpdateDomainContact', - body=json.dumps(params)) - - def update_domain_contact_privacy(self, domain_name, admin_privacy=None, - registrant_privacy=None, - tech_privacy=None): - """ - This operation updates the specified domain contact's privacy - setting. When the privacy option is enabled, personal - information such as postal or email address is hidden from the - results of a public WHOIS query. The privacy services are - provided by the AWS registrar, Gandi. For more information, - see the `Gandi privacy features`_. - - This operation only affects the privacy of the specified - contact type (registrant, administrator, or tech). Successful - acceptance returns an operation ID that you can use with - GetOperationDetail to track the progress and completion of the - action. If the request is not completed successfully, the - domain registrant will be notified by email. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - :type admin_privacy: boolean - :param admin_privacy: Whether you want to conceal contact information - from WHOIS queries. If you specify true, WHOIS ("who is") queries - will return contact information for our registrar partner, Gandi, - instead of the contact information that you enter. - Type: Boolean - - Default: None - - Valid values: `True` | `False` - - Required: No - - :type registrant_privacy: boolean - :param registrant_privacy: Whether you want to conceal contact - information from WHOIS queries. If you specify true, WHOIS ("who - is") queries will return contact information for our registrar - partner, Gandi, instead of the contact information that you enter. - Type: Boolean - - Default: None - - Valid values: `True` | `False` - - Required: No - - :type tech_privacy: boolean - :param tech_privacy: Whether you want to conceal contact information - from WHOIS queries. If you specify true, WHOIS ("who is") queries - will return contact information for our registrar partner, Gandi, - instead of the contact information that you enter. - Type: Boolean - - Default: None - - Valid values: `True` | `False` - - Required: No - - """ - params = {'DomainName': domain_name, } - if admin_privacy is not None: - params['AdminPrivacy'] = admin_privacy - if registrant_privacy is not None: - params['RegistrantPrivacy'] = registrant_privacy - if tech_privacy is not None: - params['TechPrivacy'] = tech_privacy - return self.make_request(action='UpdateDomainContactPrivacy', - body=json.dumps(params)) - - def update_domain_nameservers(self, domain_name, nameservers): - """ - This operation replaces the current set of name servers for - the domain with the specified set of name servers. If you use - Amazon Route 53 as your DNS service, specify the four name - servers in the delegation set for the hosted zone for the - domain. - - If successful, this operation returns an operation ID that you - can use to track the progress and completion of the action. If - the request is not completed successfully, the domain - registrant will be notified by email. - - :type domain_name: string - :param domain_name: The name of a domain. - Type: String - - Default: None - - Constraints: The domain name can contain only the letters a through z, - the numbers 0 through 9, and hyphen (-). Internationalized Domain - Names are not supported. - - Required: Yes - - :type nameservers: list - :param nameservers: A list of new name servers for the domain. - Type: Complex - - Children: `Name`, `GlueIps` - - Required: Yes - - """ - params = { - 'DomainName': domain_name, - 'Nameservers': nameservers, - } - return self.make_request(action='UpdateDomainNameservers', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) - diff --git a/awx/lib/site-packages/boto/route53/exception.py b/awx/lib/site-packages/boto/route53/exception.py deleted file mode 100644 index 61b33b0c57..0000000000 --- a/awx/lib/site-packages/boto/route53/exception.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.exception import BotoServerError - - -class DNSServerError(BotoServerError): - pass diff --git a/awx/lib/site-packages/boto/route53/healthcheck.py b/awx/lib/site-packages/boto/route53/healthcheck.py deleted file mode 100644 index 43fdf17924..0000000000 --- a/awx/lib/site-packages/boto/route53/healthcheck.py +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright (c) 2014 Tellybug, Matt Millar -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - -""" -From http://docs.aws.amazon.com/Route53/latest/APIReference/API_CreateHealthCheck.html - -POST /2013-04-01/healthcheck HTTP/1.1 - -<?xml version="1.0" encoding="UTF-8"?> -<CreateHealthCheckRequest xmlns="https://route53.amazonaws.com/doc/2013-04-01/"> - <CallerReference>unique description</CallerReference> - <HealthCheckConfig> - <IPAddress>IP address of the endpoint to check</IPAddress> - <Port>port on the endpoint to check</Port> - <Type>HTTP | HTTPS | HTTP_STR_MATCH | HTTPS_STR_MATCH | TCP</Type> - <ResourcePath>path of the file that - you want Amazon Route 53 to request</ResourcePath> - <FullyQualifiedDomainName>domain name of the - endpoint to check</FullyQualifiedDomainName> - <SearchString>if Type is HTTP_STR_MATCH or HTTPS_STR_MATCH, - the string to search for in the response body - from the specified resource</SearchString> - <RequestInterval>10 | 30</RequestInterval> - <FailureThreshold>integer between 1 and 10</FailureThreshold> - </HealthCheckConfig> -</CreateHealthCheckRequest> -""" - - -class HealthCheck(object): - - """An individual health check""" - - POSTXMLBody = """ - <HealthCheckConfig> - %(ip_addr_part)s - <Port>%(port)s</Port> - <Type>%(type)s</Type> - <ResourcePath>%(resource_path)s</ResourcePath> - %(fqdn_part)s - %(string_match_part)s - %(request_interval)s - <FailureThreshold>%(failure_threshold)s</FailureThreshold> - </HealthCheckConfig> - """ - - XMLIpAddrPart = """<IPAddress>%(ip_addr)s</IPAddress>""" - - XMLFQDNPart = """<FullyQualifiedDomainName>%(fqdn)s</FullyQualifiedDomainName>""" - - XMLStringMatchPart = """<SearchString>%(string_match)s</SearchString>""" - - XMLRequestIntervalPart = """<RequestInterval>%(request_interval)d</RequestInterval>""" - - valid_request_intervals = (10, 30) - - def __init__(self, ip_addr, port, hc_type, resource_path, fqdn=None, string_match=None, request_interval=30, failure_threshold=3): - """ - HealthCheck object - - :type ip_addr: str - :param ip_addr: Optional IP Address - - :type port: int - :param port: Port to check - - :type hc_type: str - :param hc_type: One of HTTP | HTTPS | HTTP_STR_MATCH | HTTPS_STR_MATCH | TCP - - :type resource_path: str - :param resource_path: Path to check - - :type fqdn: str - :param fqdn: domain name of the endpoint to check - - :type string_match: str - :param string_match: if hc_type is HTTP_STR_MATCH or HTTPS_STR_MATCH, the string to search for in the response body from the specified resource - - :type request_interval: int - :param request_interval: The number of seconds between the time that Amazon Route 53 gets a response from your endpoint and the time that it sends the next health-check request. - - :type failure_threshold: int - :param failure_threshold: The number of consecutive health checks that an endpoint must pass or fail for Amazon Route 53 to change the current status of the endpoint from unhealthy to healthy or vice versa. - - """ - self.ip_addr = ip_addr - self.port = port - self.hc_type = hc_type - self.resource_path = resource_path - self.fqdn = fqdn - self.string_match = string_match - self.failure_threshold = failure_threshold - - if request_interval in self.valid_request_intervals: - self.request_interval = request_interval - else: - raise AttributeError( - "Valid values for request_interval are: %s" % - ",".join(str(i) for i in self.valid_request_intervals)) - - if failure_threshold < 1 or failure_threshold > 10: - raise AttributeError( - 'Valid values for failure_threshold are 1 - 10.') - - def to_xml(self): - params = { - 'ip_addr_part': '', - 'port': self.port, - 'type': self.hc_type, - 'resource_path': self.resource_path, - 'fqdn_part': "", - 'string_match_part': "", - 'request_interval': (self.XMLRequestIntervalPart % - {'request_interval': self.request_interval}), - 'failure_threshold': self.failure_threshold, - } - if self.fqdn is not None: - params['fqdn_part'] = self.XMLFQDNPart % {'fqdn': self.fqdn} - - if self.ip_addr: - params['ip_addr_part'] = self.XMLIpAddrPart % {'ip_addr': self.ip_addr} - - if self.string_match is not None: - params['string_match_part'] = self.XMLStringMatchPart % {'string_match': self.string_match} - - return self.POSTXMLBody % params diff --git a/awx/lib/site-packages/boto/route53/hostedzone.py b/awx/lib/site-packages/boto/route53/hostedzone.py deleted file mode 100644 index fd8420c442..0000000000 --- a/awx/lib/site-packages/boto/route53/hostedzone.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - -class HostedZone(object): - - def __init__(self, id=None, name=None, owner=None, version=None, - caller_reference=None, config=None): - self.id = id - self.name = name - self.owner = owner - self.version = version - self.caller_reference = caller_reference - self.config = config - - def startElement(self, name, attrs, connection): - if name == 'Config': - self.config = Config() - return self.config - else: - return None - - def endElement(self, name, value, connection): - if name == 'Id': - self.id = value - elif name == 'Name': - self.name = value - elif name == 'Owner': - self.owner = value - elif name == 'Version': - self.version = value - elif name == 'CallerReference': - self.caller_reference = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/route53/record.py b/awx/lib/site-packages/boto/route53/record.py deleted file mode 100644 index d871e0bd8d..0000000000 --- a/awx/lib/site-packages/boto/route53/record.py +++ /dev/null @@ -1,374 +0,0 @@ -# Copyright (c) 2010 Chris Moyer http://coredumped.org/ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -RECORD_TYPES = ['A', 'AAAA', 'TXT', 'CNAME', 'MX', 'PTR', 'SRV', 'SPF'] - -from boto.resultset import ResultSet - - -class ResourceRecordSets(ResultSet): - """ - A list of resource records. - - :ivar hosted_zone_id: The ID of the hosted zone. - :ivar comment: A comment that will be stored with the change. - :ivar changes: A list of changes. - """ - - ChangeResourceRecordSetsBody = """<?xml version="1.0" encoding="UTF-8"?> - <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2013-04-01/"> - <ChangeBatch> - <Comment>%(comment)s</Comment> - <Changes>%(changes)s</Changes> - </ChangeBatch> - </ChangeResourceRecordSetsRequest>""" - - ChangeXML = """<Change> - <Action>%(action)s</Action> - %(record)s - </Change>""" - - def __init__(self, connection=None, hosted_zone_id=None, comment=None): - self.connection = connection - self.hosted_zone_id = hosted_zone_id - self.comment = comment - self.changes = [] - self.next_record_name = None - self.next_record_type = None - self.next_record_identifier = None - super(ResourceRecordSets, self).__init__([('ResourceRecordSet', Record)]) - - def __repr__(self): - if self.changes: - record_list = ','.join([c.__repr__() for c in self.changes]) - else: - record_list = ','.join([record.__repr__() for record in self]) - return '<ResourceRecordSets:%s [%s]' % (self.hosted_zone_id, - record_list) - - def add_change(self, action, name, type, ttl=600, - alias_hosted_zone_id=None, alias_dns_name=None, identifier=None, - weight=None, region=None, alias_evaluate_target_health=None, - health_check=None, failover=None): - """ - Add a change request to the set. - - :type action: str - :param action: The action to perform ('CREATE'|'DELETE'|'UPSERT') - - :type name: str - :param name: The name of the domain you want to perform the action on. - - :type type: str - :param type: The DNS record type. Valid values are: - - * A - * AAAA - * CNAME - * MX - * NS - * PTR - * SOA - * SPF - * SRV - * TXT - - :type ttl: int - :param ttl: The resource record cache time to live (TTL), in seconds. - - :type alias_hosted_zone_id: str - :param alias_dns_name: *Alias resource record sets only* The value - of the hosted zone ID, CanonicalHostedZoneNameId, for - the LoadBalancer. - - :type alias_dns_name: str - :param alias_hosted_zone_id: *Alias resource record sets only* - Information about the domain to which you are redirecting traffic. - - :type identifier: str - :param identifier: *Weighted and latency-based resource record sets - only* An identifier that differentiates among multiple resource - record sets that have the same combination of DNS name and type. - - :type weight: int - :param weight: *Weighted resource record sets only* Among resource - record sets that have the same combination of DNS name and type, - a value that determines what portion of traffic for the current - resource record set is routed to the associated location - - :type region: str - :param region: *Latency-based resource record sets only* Among resource - record sets that have the same combination of DNS name and type, - a value that determines which region this should be associated with - for the latency-based routing - - :type alias_evaluate_target_health: Boolean - :param alias_evaluate_target_health: *Required for alias resource record - sets* Indicates whether this Resource Record Set should respect the - health status of any health checks associated with the ALIAS target - record which it is linked to. - - :type health_check: str - :param health_check: Health check to associate with this record - - :type failover: str - :param failover: *Failover resource record sets only* Whether this is the - primary or secondary resource record set. - """ - change = Record(name, type, ttl, - alias_hosted_zone_id=alias_hosted_zone_id, - alias_dns_name=alias_dns_name, identifier=identifier, - weight=weight, region=region, - alias_evaluate_target_health=alias_evaluate_target_health, - health_check=health_check, failover=failover) - self.changes.append([action, change]) - return change - - def add_change_record(self, action, change): - """Add an existing record to a change set with the specified action""" - self.changes.append([action, change]) - return - - def to_xml(self): - """Convert this ResourceRecordSet into XML - to be saved via the ChangeResourceRecordSetsRequest""" - changesXML = "" - for change in self.changes: - changeParams = {"action": change[0], "record": change[1].to_xml()} - changesXML += self.ChangeXML % changeParams - params = {"comment": self.comment, "changes": changesXML} - return self.ChangeResourceRecordSetsBody % params - - def commit(self): - """Commit this change""" - if not self.connection: - import boto - self.connection = boto.connect_route53() - return self.connection.change_rrsets(self.hosted_zone_id, self.to_xml()) - - def endElement(self, name, value, connection): - """Overwritten to also add the NextRecordName, - NextRecordType and NextRecordIdentifier to the base object""" - if name == 'NextRecordName': - self.next_record_name = value - elif name == 'NextRecordType': - self.next_record_type = value - elif name == 'NextRecordIdentifier': - self.next_record_identifier = value - else: - return super(ResourceRecordSets, self).endElement(name, value, connection) - - def __iter__(self): - """Override the next function to support paging""" - results = super(ResourceRecordSets, self).__iter__() - truncated = self.is_truncated - while results: - for obj in results: - yield obj - if self.is_truncated: - self.is_truncated = False - results = self.connection.get_all_rrsets(self.hosted_zone_id, name=self.next_record_name, - type=self.next_record_type, - identifier=self.next_record_identifier) - else: - results = None - self.is_truncated = truncated - - -class Record(object): - """An individual ResourceRecordSet""" - - HealthCheckBody = """<HealthCheckId>%s</HealthCheckId>""" - - XMLBody = """<ResourceRecordSet> - <Name>%(name)s</Name> - <Type>%(type)s</Type> - %(weight)s - %(body)s - %(health_check)s - </ResourceRecordSet>""" - - WRRBody = """ - <SetIdentifier>%(identifier)s</SetIdentifier> - <Weight>%(weight)s</Weight> - """ - - RRRBody = """ - <SetIdentifier>%(identifier)s</SetIdentifier> - <Region>%(region)s</Region> - """ - - FailoverBody = """ - <SetIdentifier>%(identifier)s</SetIdentifier> - <Failover>%(failover)s</Failover> - """ - - ResourceRecordsBody = """ - <TTL>%(ttl)s</TTL> - <ResourceRecords> - %(records)s - </ResourceRecords>""" - - ResourceRecordBody = """<ResourceRecord> - <Value>%s</Value> - </ResourceRecord>""" - - AliasBody = """<AliasTarget> - <HostedZoneId>%(hosted_zone_id)s</HostedZoneId> - <DNSName>%(dns_name)s</DNSName> - %(eval_target_health)s - </AliasTarget>""" - - EvaluateTargetHealth = """<EvaluateTargetHealth>%s</EvaluateTargetHealth>""" - - def __init__(self, name=None, type=None, ttl=600, resource_records=None, - alias_hosted_zone_id=None, alias_dns_name=None, identifier=None, - weight=None, region=None, alias_evaluate_target_health=None, - health_check=None, failover=None): - self.name = name - self.type = type - self.ttl = ttl - if resource_records is None: - resource_records = [] - self.resource_records = resource_records - self.alias_hosted_zone_id = alias_hosted_zone_id - self.alias_dns_name = alias_dns_name - self.identifier = identifier - self.weight = weight - self.region = region - self.alias_evaluate_target_health = alias_evaluate_target_health - self.health_check = health_check - self.failover = failover - - def __repr__(self): - return '<Record:%s:%s:%s>' % (self.name, self.type, self.to_print()) - - def add_value(self, value): - """Add a resource record value""" - self.resource_records.append(value) - - def set_alias(self, alias_hosted_zone_id, alias_dns_name, - alias_evaluate_target_health=False): - """Make this an alias resource record set""" - self.alias_hosted_zone_id = alias_hosted_zone_id - self.alias_dns_name = alias_dns_name - self.alias_evaluate_target_health = alias_evaluate_target_health - - def to_xml(self): - """Spit this resource record set out as XML""" - if self.alias_hosted_zone_id is not None and self.alias_dns_name is not None: - # Use alias - if self.alias_evaluate_target_health is not None: - eval_target_health = self.EvaluateTargetHealth % ('true' if self.alias_evaluate_target_health else 'false') - else: - eval_target_health = "" - - body = self.AliasBody % {"hosted_zone_id": self.alias_hosted_zone_id, - "dns_name": self.alias_dns_name, - "eval_target_health": eval_target_health} - else: - # Use resource record(s) - records = "" - - for r in self.resource_records: - records += self.ResourceRecordBody % r - - body = self.ResourceRecordsBody % { - "ttl": self.ttl, - "records": records, - } - - weight = "" - - if self.identifier is not None and self.weight is not None: - weight = self.WRRBody % {"identifier": self.identifier, - "weight": self.weight} - elif self.identifier is not None and self.region is not None: - weight = self.RRRBody % {"identifier": self.identifier, - "region": self.region} - elif self.identifier is not None and self.failover is not None: - weight = self.FailoverBody % {"identifier": self.identifier, - "failover": self.failover} - - health_check = "" - if self.health_check is not None: - health_check = self.HealthCheckBody % (self.health_check) - - params = { - "name": self.name, - "type": self.type, - "weight": weight, - "body": body, - "health_check": health_check - } - return self.XMLBody % params - - def to_print(self): - rr = "" - if self.alias_hosted_zone_id is not None and self.alias_dns_name is not None: - # Show alias - rr = 'ALIAS ' + self.alias_hosted_zone_id + ' ' + self.alias_dns_name - if self.alias_evaluate_target_health is not None: - rr += ' (EvalTarget %s)' % self.alias_evaluate_target_health - else: - # Show resource record(s) - rr = ",".join(self.resource_records) - - if self.identifier is not None and self.weight is not None: - rr += ' (WRR id=%s, w=%s)' % (self.identifier, self.weight) - elif self.identifier is not None and self.region is not None: - rr += ' (LBR id=%s, region=%s)' % (self.identifier, self.region) - elif self.identifier is not None and self.failover is not None: - rr += ' (FAILOVER id=%s, failover=%s)' % (self.identifier, self.failover) - - return rr - - def endElement(self, name, value, connection): - if name == 'Name': - self.name = value - elif name == 'Type': - self.type = value - elif name == 'TTL': - self.ttl = value - elif name == 'Value': - self.resource_records.append(value) - elif name == 'HostedZoneId': - self.alias_hosted_zone_id = value - elif name == 'DNSName': - self.alias_dns_name = value - elif name == 'SetIdentifier': - self.identifier = value - elif name == 'EvaluateTargetHealth': - self.alias_evaluate_target_health = value.lower() == 'true' - elif name == 'Weight': - self.weight = value - elif name == 'Region': - self.region = value - elif name == 'Failover': - self.failover = value - elif name == 'HealthCheckId': - self.health_check = value - - def startElement(self, name, attrs, connection): - return None diff --git a/awx/lib/site-packages/boto/route53/status.py b/awx/lib/site-packages/boto/route53/status.py deleted file mode 100644 index 782372a811..0000000000 --- a/awx/lib/site-packages/boto/route53/status.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2011 Blue Pines Technologies LLC, Brad Carleton -# www.bluepines.org -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -class Status(object): - def __init__(self, route53connection, change_dict): - self.route53connection = route53connection - for key in change_dict: - if key == 'Id': - self.__setattr__(key.lower(), - change_dict[key].replace('/change/', '')) - else: - self.__setattr__(key.lower(), change_dict[key]) - - def update(self): - """ Update the status of this request.""" - status = self.route53connection.get_change(self.id)['GetChangeResponse']['ChangeInfo']['Status'] - self.status = status - return status - - def __repr__(self): - return '<Status:%s>' % self.status diff --git a/awx/lib/site-packages/boto/route53/zone.py b/awx/lib/site-packages/boto/route53/zone.py deleted file mode 100644 index b21c8de409..0000000000 --- a/awx/lib/site-packages/boto/route53/zone.py +++ /dev/null @@ -1,419 +0,0 @@ -# Copyright (c) 2011 Blue Pines Technologies LLC, Brad Carleton -# www.bluepines.org -# Copyright (c) 2012 42 Lines Inc., Jim Browne -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -default_ttl = 60 - -import copy -from boto.exception import TooManyRecordsException -from boto.route53.record import ResourceRecordSets -from boto.route53.status import Status - - -class Zone(object): - """ - A Route53 Zone. - - :ivar route53connection: A :class:`boto.route53.connection.Route53Connection` connection - :ivar id: The ID of the hosted zone - """ - def __init__(self, route53connection, zone_dict): - self.route53connection = route53connection - for key in zone_dict: - if key == 'Id': - self.id = zone_dict['Id'].replace('/hostedzone/', '') - else: - self.__setattr__(key.lower(), zone_dict[key]) - - def __repr__(self): - return '<Zone:%s>' % self.name - - def _commit(self, changes): - """ - Commit a set of changes and return the ChangeInfo portion of - the response. - - :type changes: ResourceRecordSets - :param changes: changes to be committed - """ - response = changes.commit() - return response['ChangeResourceRecordSetsResponse']['ChangeInfo'] - - def _new_record(self, changes, resource_type, name, value, ttl, identifier, - comment=""): - """ - Add a CREATE change record to an existing ResourceRecordSets - - :type changes: ResourceRecordSets - :param changes: change set to append to - - :type name: str - :param name: The name of the resource record you want to - perform the action on. - - :type resource_type: str - :param resource_type: The DNS record type - - :param value: Appropriate value for resource_type - - :type ttl: int - :param ttl: The resource record cache time to live (TTL), in seconds. - - :type identifier: tuple - :param identifier: A tuple for setting WRR or LBR attributes. Valid - forms are: - - * (str, int): WRR record [e.g. ('foo',10)] - * (str, str): LBR record [e.g. ('foo','us-east-1') - - :type comment: str - :param comment: A comment that will be stored with the change. - """ - weight = None - region = None - if identifier is not None: - try: - int(identifier[1]) - weight = identifier[1] - identifier = identifier[0] - except: - region = identifier[1] - identifier = identifier[0] - change = changes.add_change("CREATE", name, resource_type, ttl, - identifier=identifier, weight=weight, - region=region) - if type(value) in [list, tuple, set]: - for record in value: - change.add_value(record) - else: - change.add_value(value) - - def add_record(self, resource_type, name, value, ttl=60, identifier=None, - comment=""): - """ - Add a new record to this Zone. See _new_record for parameter - documentation. Returns a Status object. - """ - changes = ResourceRecordSets(self.route53connection, self.id, comment) - self._new_record(changes, resource_type, name, value, ttl, identifier, - comment) - return Status(self.route53connection, self._commit(changes)) - - def update_record(self, old_record, new_value, new_ttl=None, - new_identifier=None, comment=""): - """ - Update an existing record in this Zone. Returns a Status object. - - :type old_record: ResourceRecord - :param old_record: A ResourceRecord (e.g. returned by find_records) - - See _new_record for additional parameter documentation. - """ - new_ttl = new_ttl or default_ttl - record = copy.copy(old_record) - changes = ResourceRecordSets(self.route53connection, self.id, comment) - changes.add_change_record("DELETE", record) - self._new_record(changes, record.type, record.name, - new_value, new_ttl, new_identifier, comment) - return Status(self.route53connection, self._commit(changes)) - - def delete_record(self, record, comment=""): - """ - Delete one or more records from this Zone. Returns a Status object. - - :param record: A ResourceRecord (e.g. returned by - find_records) or list, tuple, or set of ResourceRecords. - - :type comment: str - :param comment: A comment that will be stored with the change. - """ - changes = ResourceRecordSets(self.route53connection, self.id, comment) - if type(record) in [list, tuple, set]: - for r in record: - changes.add_change_record("DELETE", r) - else: - changes.add_change_record("DELETE", record) - return Status(self.route53connection, self._commit(changes)) - - def add_cname(self, name, value, ttl=None, identifier=None, comment=""): - """ - Add a new CNAME record to this Zone. See _new_record for - parameter documentation. Returns a Status object. - """ - ttl = ttl or default_ttl - name = self.route53connection._make_qualified(name) - value = self.route53connection._make_qualified(value) - return self.add_record(resource_type='CNAME', - name=name, - value=value, - ttl=ttl, - identifier=identifier, - comment=comment) - - def add_a(self, name, value, ttl=None, identifier=None, comment=""): - """ - Add a new A record to this Zone. See _new_record for - parameter documentation. Returns a Status object. - """ - ttl = ttl or default_ttl - name = self.route53connection._make_qualified(name) - return self.add_record(resource_type='A', - name=name, - value=value, - ttl=ttl, - identifier=identifier, - comment=comment) - - def add_mx(self, name, records, ttl=None, identifier=None, comment=""): - """ - Add a new MX record to this Zone. See _new_record for - parameter documentation. Returns a Status object. - """ - ttl = ttl or default_ttl - records = self.route53connection._make_qualified(records) - return self.add_record(resource_type='MX', - name=name, - value=records, - ttl=ttl, - identifier=identifier, - comment=comment) - - def find_records(self, name, type, desired=1, all=False, identifier=None): - """ - Search this Zone for records that match given parameters. - Returns None if no results, a ResourceRecord if one result, or - a ResourceRecordSets if more than one result. - - :type name: str - :param name: The name of the records should match this parameter - - :type type: str - :param type: The type of the records should match this parameter - - :type desired: int - :param desired: The number of desired results. If the number of - matching records in the Zone exceeds the value of this parameter, - throw TooManyRecordsException - - :type all: Boolean - :param all: If true return all records that match name, type, and - identifier parameters - - :type identifier: Tuple - :param identifier: A tuple specifying WRR or LBR attributes. Valid - forms are: - - * (str, int): WRR record [e.g. ('foo',10)] - * (str, str): LBR record [e.g. ('foo','us-east-1') - - """ - name = self.route53connection._make_qualified(name) - returned = self.route53connection.get_all_rrsets(self.id, name=name, - type=type) - - # name/type for get_all_rrsets sets the starting record; they - # are not a filter - results = [] - for r in returned: - if r.name == name and r.type == type: - results.append(r) - # Is at the end of the list of matched records. No need to continue - # since the records are sorted by name and type. - else: - break - - weight = None - region = None - if identifier is not None: - try: - int(identifier[1]) - weight = identifier[1] - except: - region = identifier[1] - - if weight is not None: - results = [r for r in results if (r.weight == weight and - r.identifier == identifier[0])] - if region is not None: - results = [r for r in results if (r.region == region and - r.identifier == identifier[0])] - - if ((not all) and (len(results) > desired)): - message = "Search: name %s type %s" % (name, type) - message += "\nFound: " - message += ", ".join(["%s %s %s" % (r.name, r.type, r.to_print()) - for r in results]) - raise TooManyRecordsException(message) - elif len(results) > 1: - return results - elif len(results) == 1: - return results[0] - else: - return None - - def get_cname(self, name, all=False): - """ - Search this Zone for CNAME records that match name. - - Returns a ResourceRecord. - - If there is more than one match return all as a - ResourceRecordSets if all is True, otherwise throws - TooManyRecordsException. - """ - return self.find_records(name, 'CNAME', all=all) - - def get_a(self, name, all=False): - """ - Search this Zone for A records that match name. - - Returns a ResourceRecord. - - If there is more than one match return all as a - ResourceRecordSets if all is True, otherwise throws - TooManyRecordsException. - """ - return self.find_records(name, 'A', all=all) - - def get_mx(self, name, all=False): - """ - Search this Zone for MX records that match name. - - Returns a ResourceRecord. - - If there is more than one match return all as a - ResourceRecordSets if all is True, otherwise throws - TooManyRecordsException. - """ - return self.find_records(name, 'MX', all=all) - - def update_cname(self, name, value, ttl=None, identifier=None, comment=""): - """ - Update the given CNAME record in this Zone to a new value, ttl, - and identifier. Returns a Status object. - - Will throw TooManyRecordsException is name, value does not match - a single record. - """ - name = self.route53connection._make_qualified(name) - value = self.route53connection._make_qualified(value) - old_record = self.get_cname(name) - ttl = ttl or old_record.ttl - return self.update_record(old_record, - new_value=value, - new_ttl=ttl, - new_identifier=identifier, - comment=comment) - - def update_a(self, name, value, ttl=None, identifier=None, comment=""): - """ - Update the given A record in this Zone to a new value, ttl, - and identifier. Returns a Status object. - - Will throw TooManyRecordsException is name, value does not match - a single record. - """ - name = self.route53connection._make_qualified(name) - old_record = self.get_a(name) - ttl = ttl or old_record.ttl - return self.update_record(old_record, - new_value=value, - new_ttl=ttl, - new_identifier=identifier, - comment=comment) - - def update_mx(self, name, value, ttl=None, identifier=None, comment=""): - """ - Update the given MX record in this Zone to a new value, ttl, - and identifier. Returns a Status object. - - Will throw TooManyRecordsException is name, value does not match - a single record. - """ - name = self.route53connection._make_qualified(name) - value = self.route53connection._make_qualified(value) - old_record = self.get_mx(name) - ttl = ttl or old_record.ttl - return self.update_record(old_record, - new_value=value, - new_ttl=ttl, - new_identifier=identifier, - comment=comment) - - def delete_cname(self, name, identifier=None, all=False): - """ - Delete a CNAME record matching name and identifier from - this Zone. Returns a Status object. - - If there is more than one match delete all matching records if - all is True, otherwise throws TooManyRecordsException. - """ - name = self.route53connection._make_qualified(name) - record = self.find_records(name, 'CNAME', identifier=identifier, - all=all) - return self.delete_record(record) - - def delete_a(self, name, identifier=None, all=False): - """ - Delete an A record matching name and identifier from this - Zone. Returns a Status object. - - If there is more than one match delete all matching records if - all is True, otherwise throws TooManyRecordsException. - """ - name = self.route53connection._make_qualified(name) - record = self.find_records(name, 'A', identifier=identifier, - all=all) - return self.delete_record(record) - - def delete_mx(self, name, identifier=None, all=False): - """ - Delete an MX record matching name and identifier from this - Zone. Returns a Status object. - - If there is more than one match delete all matching records if - all is True, otherwise throws TooManyRecordsException. - """ - name = self.route53connection._make_qualified(name) - record = self.find_records(name, 'MX', identifier=identifier, - all=all) - return self.delete_record(record) - - def get_records(self): - """ - Return a ResourceRecordsSets for all of the records in this zone. - """ - return self.route53connection.get_all_rrsets(self.id) - - def delete(self): - """ - Request that this zone be deleted by Amazon. - """ - self.route53connection.delete_hosted_zone(self.id) - - def get_nameservers(self): - """ Get the list of nameservers for this zone.""" - ns = self.find_records(self.name, 'NS') - if ns is not None: - ns = ns.resource_records - return ns diff --git a/awx/lib/site-packages/boto/s3/__init__.py b/awx/lib/site-packages/boto/s3/__init__.py deleted file mode 100644 index 67d53e3bd8..0000000000 --- a/awx/lib/site-packages/boto/s3/__init__.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo, get_regions - - -class S3RegionInfo(RegionInfo): - - def connect(self, **kw_params): - """ - Connect to this Region's endpoint. Returns an connection - object pointing to the endpoint associated with this region. - You may pass any of the arguments accepted by the connection - class's constructor as keyword arguments and they will be - passed along to the connection object. - - :rtype: Connection object - :return: The connection to this regions endpoint - """ - if self.connection_cls: - return self.connection_cls(host=self.endpoint, **kw_params) - - -def regions(): - """ - Get all available regions for the Amazon S3 service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.s3.connection import S3Connection - return get_regions( - 's3', - region_cls=S3RegionInfo, - connection_cls=S3Connection - ) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/s3/acl.py b/awx/lib/site-packages/boto/s3/acl.py deleted file mode 100644 index 51613883e4..0000000000 --- a/awx/lib/site-packages/boto/s3/acl.py +++ /dev/null @@ -1,171 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.s3.user import User - - -CannedACLStrings = ['private', 'public-read', - 'public-read-write', 'authenticated-read', - 'bucket-owner-read', 'bucket-owner-full-control', - 'log-delivery-write'] - - -class Policy(object): - - def __init__(self, parent=None): - self.parent = parent - self.namespace = None - self.acl = None - - def __repr__(self): - grants = [] - for g in self.acl.grants: - if g.id == self.owner.id: - grants.append("%s (owner) = %s" % (g.display_name, g.permission)) - else: - if g.type == 'CanonicalUser': - u = g.display_name - elif g.type == 'Group': - u = g.uri - else: - u = g.email_address - grants.append("%s = %s" % (u, g.permission)) - return "<Policy: %s>" % ", ".join(grants) - - def startElement(self, name, attrs, connection): - if name == 'AccessControlPolicy': - self.namespace = attrs.get('xmlns', None) - return None - if name == 'Owner': - self.owner = User(self) - return self.owner - elif name == 'AccessControlList': - self.acl = ACL(self) - return self.acl - else: - return None - - def endElement(self, name, value, connection): - if name == 'Owner': - pass - elif name == 'AccessControlList': - pass - else: - setattr(self, name, value) - - def to_xml(self): - if self.namespace is not None: - s = '<AccessControlPolicy xmlns="{0}">'.format(self.namespace) - else: - s = '<AccessControlPolicy>' - s += self.owner.to_xml() - s += self.acl.to_xml() - s += '</AccessControlPolicy>' - return s - -class ACL(object): - - def __init__(self, policy=None): - self.policy = policy - self.grants = [] - - def add_grant(self, grant): - self.grants.append(grant) - - def add_email_grant(self, permission, email_address): - grant = Grant(permission=permission, type='AmazonCustomerByEmail', - email_address=email_address) - self.grants.append(grant) - - def add_user_grant(self, permission, user_id, display_name=None): - grant = Grant(permission=permission, type='CanonicalUser', id=user_id, display_name=display_name) - self.grants.append(grant) - - def startElement(self, name, attrs, connection): - if name == 'Grant': - self.grants.append(Grant(self)) - return self.grants[-1] - else: - return None - - def endElement(self, name, value, connection): - if name == 'Grant': - pass - else: - setattr(self, name, value) - - def to_xml(self): - s = '<AccessControlList>' - for grant in self.grants: - s += grant.to_xml() - s += '</AccessControlList>' - return s - -class Grant(object): - - NameSpace = 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' - - def __init__(self, permission=None, type=None, id=None, - display_name=None, uri=None, email_address=None): - self.permission = permission - self.id = id - self.display_name = display_name - self.uri = uri - self.email_address = email_address - self.type = type - - def startElement(self, name, attrs, connection): - if name == 'Grantee': - self.type = attrs['xsi:type'] - return None - - def endElement(self, name, value, connection): - if name == 'ID': - self.id = value - elif name == 'DisplayName': - self.display_name = value - elif name == 'URI': - self.uri = value - elif name == 'EmailAddress': - self.email_address = value - elif name == 'Grantee': - pass - elif name == 'Permission': - self.permission = value - else: - setattr(self, name, value) - - def to_xml(self): - s = '<Grant>' - s += '<Grantee %s xsi:type="%s">' % (self.NameSpace, self.type) - if self.type == 'CanonicalUser': - s += '<ID>%s</ID>' % self.id - s += '<DisplayName>%s</DisplayName>' % self.display_name - elif self.type == 'Group': - s += '<URI>%s</URI>' % self.uri - else: - s += '<EmailAddress>%s</EmailAddress>' % self.email_address - s += '</Grantee>' - s += '<Permission>%s</Permission>' % self.permission - s += '</Grant>' - return s - - diff --git a/awx/lib/site-packages/boto/s3/bucket.py b/awx/lib/site-packages/boto/s3/bucket.py deleted file mode 100644 index 504f24f9bb..0000000000 --- a/awx/lib/site-packages/boto/s3/bucket.py +++ /dev/null @@ -1,1876 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -from boto import handler -from boto.resultset import ResultSet -from boto.exception import BotoClientError -from boto.s3.acl import Policy, CannedACLStrings, Grant -from boto.s3.key import Key -from boto.s3.prefix import Prefix -from boto.s3.deletemarker import DeleteMarker -from boto.s3.multipart import MultiPartUpload -from boto.s3.multipart import CompleteMultiPartUpload -from boto.s3.multidelete import MultiDeleteResult -from boto.s3.multidelete import Error -from boto.s3.bucketlistresultset import BucketListResultSet -from boto.s3.bucketlistresultset import VersionedBucketListResultSet -from boto.s3.bucketlistresultset import MultiPartUploadListResultSet -from boto.s3.lifecycle import Lifecycle -from boto.s3.tagging import Tags -from boto.s3.cors import CORSConfiguration -from boto.s3.bucketlogging import BucketLogging -from boto.s3 import website -import boto.jsonresponse -import boto.utils -import xml.sax -import xml.sax.saxutils -import re -import base64 -from collections import defaultdict -from boto.compat import BytesIO, six, StringIO, urllib - -# as per http://goo.gl/BDuud (02/19/2011) - - -class S3WebsiteEndpointTranslate(object): - - trans_region = defaultdict(lambda: 's3-website-us-east-1') - trans_region['eu-west-1'] = 's3-website-eu-west-1' - trans_region['us-west-1'] = 's3-website-us-west-1' - trans_region['us-west-2'] = 's3-website-us-west-2' - trans_region['sa-east-1'] = 's3-website-sa-east-1' - trans_region['ap-northeast-1'] = 's3-website-ap-northeast-1' - trans_region['ap-southeast-1'] = 's3-website-ap-southeast-1' - trans_region['ap-southeast-2'] = 's3-website-ap-southeast-2' - trans_region['cn-north-1'] = 's3-website.cn-north-1' - - @classmethod - def translate_region(self, reg): - return self.trans_region[reg] - -S3Permissions = ['READ', 'WRITE', 'READ_ACP', 'WRITE_ACP', 'FULL_CONTROL'] - - -class Bucket(object): - - LoggingGroup = 'http://acs.amazonaws.com/groups/s3/LogDelivery' - - BucketPaymentBody = """<?xml version="1.0" encoding="UTF-8"?> - <RequestPaymentConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> - <Payer>%s</Payer> - </RequestPaymentConfiguration>""" - - VersioningBody = """<?xml version="1.0" encoding="UTF-8"?> - <VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> - <Status>%s</Status> - <MfaDelete>%s</MfaDelete> - </VersioningConfiguration>""" - - VersionRE = '<Status>([A-Za-z]+)</Status>' - MFADeleteRE = '<MfaDelete>([A-Za-z]+)</MfaDelete>' - - def __init__(self, connection=None, name=None, key_class=Key): - self.name = name - self.connection = connection - self.key_class = key_class - - def __repr__(self): - return '<Bucket: %s>' % self.name - - def __iter__(self): - return iter(BucketListResultSet(self)) - - def __contains__(self, key_name): - return not (self.get_key(key_name) is None) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Name': - self.name = value - elif name == 'CreationDate': - self.creation_date = value - else: - setattr(self, name, value) - - def set_key_class(self, key_class): - """ - Set the Key class associated with this bucket. By default, this - would be the boto.s3.key.Key class but if you want to subclass that - for some reason this allows you to associate your new class with a - bucket so that when you call bucket.new_key() or when you get a listing - of keys in the bucket you will get an instances of your key class - rather than the default. - - :type key_class: class - :param key_class: A subclass of Key that can be more specific - """ - self.key_class = key_class - - def lookup(self, key_name, headers=None): - """ - Deprecated: Please use get_key method. - - :type key_name: string - :param key_name: The name of the key to retrieve - - :rtype: :class:`boto.s3.key.Key` - :returns: A Key object from this bucket. - """ - return self.get_key(key_name, headers=headers) - - def get_key(self, key_name, headers=None, version_id=None, - response_headers=None, validate=True): - """ - Check to see if a particular key exists within the bucket. This - method uses a HEAD request to check for the existence of the key. - Returns: An instance of a Key object or None - - :param key_name: The name of the key to retrieve - :type key_name: string - - :param headers: The headers to send when retrieving the key - :type headers: dict - - :param version_id: - :type version_id: string - - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - :type response_headers: dict - - :param validate: Verifies whether the key exists. If ``False``, this - will not hit the service, constructing an in-memory object. - Default is ``True``. - :type validate: bool - - :rtype: :class:`boto.s3.key.Key` - :returns: A Key object from this bucket. - """ - if validate is False: - if headers or version_id or response_headers: - raise BotoClientError( - "When providing 'validate=False', no other params " + \ - "are allowed." - ) - - # This leans on the default behavior of ``new_key`` (not hitting - # the service). If that changes, that behavior should migrate here. - return self.new_key(key_name) - - query_args_l = [] - if version_id: - query_args_l.append('versionId=%s' % version_id) - if response_headers: - for rk, rv in six.iteritems(response_headers): - query_args_l.append('%s=%s' % (rk, urllib.parse.quote(rv))) - - key, resp = self._get_key_internal(key_name, headers, query_args_l) - return key - - def _get_key_internal(self, key_name, headers, query_args_l): - query_args = '&'.join(query_args_l) or None - response = self.connection.make_request('HEAD', self.name, key_name, - headers=headers, - query_args=query_args) - response.read() - # Allow any success status (2xx) - for example this lets us - # support Range gets, which return status 206: - if response.status / 100 == 2: - k = self.key_class(self) - provider = self.connection.provider - k.metadata = boto.utils.get_aws_metadata(response.msg, provider) - for field in Key.base_fields: - k.__dict__[field.lower().replace('-', '_')] = \ - response.getheader(field) - # the following machinations are a workaround to the fact that - # apache/fastcgi omits the content-length header on HEAD - # requests when the content-length is zero. - # See http://goo.gl/0Tdax for more details. - clen = response.getheader('content-length') - if clen: - k.size = int(response.getheader('content-length')) - else: - k.size = 0 - k.name = key_name - k.handle_version_headers(response) - k.handle_encryption_headers(response) - k.handle_restore_headers(response) - k.handle_addl_headers(response.getheaders()) - return k, response - else: - if response.status == 404: - return None, response - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, '') - - def list(self, prefix='', delimiter='', marker='', headers=None, - encoding_type=None): - """ - List key objects within a bucket. This returns an instance of an - BucketListResultSet that automatically handles all of the result - paging, etc. from S3. You just need to keep iterating until - there are no more results. - - Called with no arguments, this will return an iterator object across - all keys within the bucket. - - The Key objects returned by the iterator are obtained by parsing - the results of a GET on the bucket, also known as the List Objects - request. The XML returned by this request contains only a subset - of the information about each key. Certain metadata fields such - as Content-Type and user metadata are not available in the XML. - Therefore, if you want these additional metadata fields you will - have to do a HEAD request on the Key in the bucket. - - :type prefix: string - :param prefix: allows you to limit the listing to a particular - prefix. For example, if you call the method with - prefix='/foo/' then the iterator will only cycle through - the keys that begin with the string '/foo/'. - - :type delimiter: string - :param delimiter: can be used in conjunction with the prefix - to allow you to organize and browse your keys - hierarchically. See http://goo.gl/Xx63h for more details. - - :type marker: string - :param marker: The "marker" of where you are in the result set - - :param encoding_type: Requests Amazon S3 to encode the response and - specifies the encoding method to use. - - An object key can contain any Unicode character; however, XML 1.0 - parser cannot parse some characters, such as characters with an - ASCII value from 0 to 10. For characters that are not supported in - XML 1.0, you can add this parameter to request that Amazon S3 - encode the keys in the response. - - Valid options: ``url`` - :type encoding_type: string - - :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet` - :return: an instance of a BucketListResultSet that handles paging, etc - """ - return BucketListResultSet(self, prefix, delimiter, marker, headers, - encoding_type=encoding_type) - - def list_versions(self, prefix='', delimiter='', key_marker='', - version_id_marker='', headers=None, encoding_type=None): - """ - List version objects within a bucket. This returns an - instance of an VersionedBucketListResultSet that automatically - handles all of the result paging, etc. from S3. You just need - to keep iterating until there are no more results. Called - with no arguments, this will return an iterator object across - all keys within the bucket. - - :type prefix: string - :param prefix: allows you to limit the listing to a particular - prefix. For example, if you call the method with - prefix='/foo/' then the iterator will only cycle through - the keys that begin with the string '/foo/'. - - :type delimiter: string - :param delimiter: can be used in conjunction with the prefix - to allow you to organize and browse your keys - hierarchically. See: - - http://aws.amazon.com/releasenotes/Amazon-S3/213 - - for more details. - - :type key_marker: string - :param key_marker: The "marker" of where you are in the result set - - :param encoding_type: Requests Amazon S3 to encode the response and - specifies the encoding method to use. - - An object key can contain any Unicode character; however, XML 1.0 - parser cannot parse some characters, such as characters with an - ASCII value from 0 to 10. For characters that are not supported in - XML 1.0, you can add this parameter to request that Amazon S3 - encode the keys in the response. - - Valid options: ``url`` - :type encoding_type: string - - :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet` - :return: an instance of a BucketListResultSet that handles paging, etc - """ - return VersionedBucketListResultSet(self, prefix, delimiter, - key_marker, version_id_marker, - headers, - encoding_type=encoding_type) - - def list_multipart_uploads(self, key_marker='', - upload_id_marker='', - headers=None, encoding_type=None): - """ - List multipart upload objects within a bucket. This returns an - instance of an MultiPartUploadListResultSet that automatically - handles all of the result paging, etc. from S3. You just need - to keep iterating until there are no more results. - - :type key_marker: string - :param key_marker: The "marker" of where you are in the result set - - :type upload_id_marker: string - :param upload_id_marker: The upload identifier - - :param encoding_type: Requests Amazon S3 to encode the response and - specifies the encoding method to use. - - An object key can contain any Unicode character; however, XML 1.0 - parser cannot parse some characters, such as characters with an - ASCII value from 0 to 10. For characters that are not supported in - XML 1.0, you can add this parameter to request that Amazon S3 - encode the keys in the response. - - Valid options: ``url`` - :type encoding_type: string - - :rtype: :class:`boto.s3.bucketlistresultset.BucketListResultSet` - :return: an instance of a BucketListResultSet that handles paging, etc - """ - return MultiPartUploadListResultSet(self, key_marker, - upload_id_marker, - headers, - encoding_type=encoding_type) - - def _get_all_query_args(self, params, initial_query_string=''): - pairs = [] - - if initial_query_string: - pairs.append(initial_query_string) - - for key, value in sorted(params.items(), key=lambda x: x[0]): - if value is None: - continue - key = key.replace('_', '-') - if key == 'maxkeys': - key = 'max-keys' - if not isinstance(value, six.string_types + (six.binary_type,)): - value = six.text_type(value) - if not isinstance(value, six.binary_type): - value = value.encode('utf-8') - if value: - pairs.append(u'%s=%s' % ( - urllib.parse.quote(key), - urllib.parse.quote(value) - )) - - return '&'.join(pairs) - - def _get_all(self, element_map, initial_query_string='', - headers=None, **params): - query_args = self._get_all_query_args( - params, - initial_query_string=initial_query_string - ) - response = self.connection.make_request('GET', self.name, - headers=headers, - query_args=query_args) - body = response.read() - boto.log.debug(body) - if response.status == 200: - rs = ResultSet(element_map) - h = handler.XmlHandler(rs, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return rs - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def validate_kwarg_names(self, kwargs, names): - """ - Checks that all named arguments are in the specified list of names. - - :type kwargs: dict - :param kwargs: Dictionary of kwargs to validate. - - :type names: list - :param names: List of possible named arguments. - """ - for kwarg in kwargs: - if kwarg not in names: - raise TypeError('Invalid argument "%s"!' % kwarg) - - def get_all_keys(self, headers=None, **params): - """ - A lower-level method for listing contents of a bucket. This - closely models the actual S3 API and requires you to manually - handle the paging of results. For a higher-level method that - handles the details of paging for you, you can use the list - method. - - :type max_keys: int - :param max_keys: The maximum number of keys to retrieve - - :type prefix: string - :param prefix: The prefix of the keys you want to retrieve - - :type marker: string - :param marker: The "marker" of where you are in the result set - - :type delimiter: string - :param delimiter: If this optional, Unicode string parameter - is included with your request, then keys that contain the - same string between the prefix and the first occurrence of - the delimiter will be rolled up into a single result - element in the CommonPrefixes collection. These rolled-up - keys are not returned elsewhere in the response. - - :param encoding_type: Requests Amazon S3 to encode the response and - specifies the encoding method to use. - - An object key can contain any Unicode character; however, XML 1.0 - parser cannot parse some characters, such as characters with an - ASCII value from 0 to 10. For characters that are not supported in - XML 1.0, you can add this parameter to request that Amazon S3 - encode the keys in the response. - - Valid options: ``url`` - :type encoding_type: string - - :rtype: ResultSet - :return: The result from S3 listing the keys requested - - """ - self.validate_kwarg_names(params, ['maxkeys', 'max_keys', 'prefix', - 'marker', 'delimiter', - 'encoding_type']) - return self._get_all([('Contents', self.key_class), - ('CommonPrefixes', Prefix)], - '', headers, **params) - - def get_all_versions(self, headers=None, **params): - """ - A lower-level, version-aware method for listing contents of a - bucket. This closely models the actual S3 API and requires - you to manually handle the paging of results. For a - higher-level method that handles the details of paging for - you, you can use the list method. - - :type max_keys: int - :param max_keys: The maximum number of keys to retrieve - - :type prefix: string - :param prefix: The prefix of the keys you want to retrieve - - :type key_marker: string - :param key_marker: The "marker" of where you are in the result set - with respect to keys. - - :type version_id_marker: string - :param version_id_marker: The "marker" of where you are in the result - set with respect to version-id's. - - :type delimiter: string - :param delimiter: If this optional, Unicode string parameter - is included with your request, then keys that contain the - same string between the prefix and the first occurrence of - the delimiter will be rolled up into a single result - element in the CommonPrefixes collection. These rolled-up - keys are not returned elsewhere in the response. - - :param encoding_type: Requests Amazon S3 to encode the response and - specifies the encoding method to use. - - An object key can contain any Unicode character; however, XML 1.0 - parser cannot parse some characters, such as characters with an - ASCII value from 0 to 10. For characters that are not supported in - XML 1.0, you can add this parameter to request that Amazon S3 - encode the keys in the response. - - Valid options: ``url`` - :type encoding_type: string - - :rtype: ResultSet - :return: The result from S3 listing the keys requested - """ - self.validate_get_all_versions_params(params) - return self._get_all([('Version', self.key_class), - ('CommonPrefixes', Prefix), - ('DeleteMarker', DeleteMarker)], - 'versions', headers, **params) - - def validate_get_all_versions_params(self, params): - """ - Validate that the parameters passed to get_all_versions are valid. - Overridden by subclasses that allow a different set of parameters. - - :type params: dict - :param params: Parameters to validate. - """ - self.validate_kwarg_names( - params, ['maxkeys', 'max_keys', 'prefix', 'key_marker', - 'version_id_marker', 'delimiter', 'encoding_type']) - - def get_all_multipart_uploads(self, headers=None, **params): - """ - A lower-level, version-aware method for listing active - MultiPart uploads for a bucket. This closely models the - actual S3 API and requires you to manually handle the paging - of results. For a higher-level method that handles the - details of paging for you, you can use the list method. - - :type max_uploads: int - :param max_uploads: The maximum number of uploads to retrieve. - Default value is 1000. - - :type key_marker: string - :param key_marker: Together with upload_id_marker, this - parameter specifies the multipart upload after which - listing should begin. If upload_id_marker is not - specified, only the keys lexicographically greater than - the specified key_marker will be included in the list. - - If upload_id_marker is specified, any multipart uploads - for a key equal to the key_marker might also be included, - provided those multipart uploads have upload IDs - lexicographically greater than the specified - upload_id_marker. - - :type upload_id_marker: string - :param upload_id_marker: Together with key-marker, specifies - the multipart upload after which listing should begin. If - key_marker is not specified, the upload_id_marker - parameter is ignored. Otherwise, any multipart uploads - for a key equal to the key_marker might be included in the - list only if they have an upload ID lexicographically - greater than the specified upload_id_marker. - - :type encoding_type: string - :param encoding_type: Requests Amazon S3 to encode the response and - specifies the encoding method to use. - - An object key can contain any Unicode character; however, XML 1.0 - parser cannot parse some characters, such as characters with an - ASCII value from 0 to 10. For characters that are not supported in - XML 1.0, you can add this parameter to request that Amazon S3 - encode the keys in the response. - - Valid options: ``url`` - - :type delimiter: string - :param delimiter: Character you use to group keys. - All keys that contain the same string between the prefix, if - specified, and the first occurrence of the delimiter after the - prefix are grouped under a single result element, CommonPrefixes. - If you don't specify the prefix parameter, then the substring - starts at the beginning of the key. The keys that are grouped - under CommonPrefixes result element are not returned elsewhere - in the response. - - :type prefix: string - :param prefix: Lists in-progress uploads only for those keys that - begin with the specified prefix. You can use prefixes to separate - a bucket into different grouping of keys. (You can think of using - prefix to make groups in the same way you'd use a folder in a - file system.) - - :rtype: ResultSet - :return: The result from S3 listing the uploads requested - - """ - self.validate_kwarg_names(params, ['max_uploads', 'key_marker', - 'upload_id_marker', 'encoding_type', - 'delimiter', 'prefix']) - return self._get_all([('Upload', MultiPartUpload), - ('CommonPrefixes', Prefix)], - 'uploads', headers, **params) - - def new_key(self, key_name=None): - """ - Creates a new key - - :type key_name: string - :param key_name: The name of the key to create - - :rtype: :class:`boto.s3.key.Key` or subclass - :returns: An instance of the newly created key object - """ - if not key_name: - raise ValueError('Empty key names are not allowed') - return self.key_class(self, key_name) - - def generate_url(self, expires_in, method='GET', headers=None, - force_http=False, response_headers=None, - expires_in_absolute=False): - return self.connection.generate_url(expires_in, method, self.name, - headers=headers, - force_http=force_http, - response_headers=response_headers, - expires_in_absolute=expires_in_absolute) - - def delete_keys(self, keys, quiet=False, mfa_token=None, headers=None): - """ - Deletes a set of keys using S3's Multi-object delete API. If a - VersionID is specified for that key then that version is removed. - Returns a MultiDeleteResult Object, which contains Deleted - and Error elements for each key you ask to delete. - - :type keys: list - :param keys: A list of either key_names or (key_name, versionid) pairs - or a list of Key instances. - - :type quiet: boolean - :param quiet: In quiet mode the response includes only keys - where the delete operation encountered an error. For a - successful deletion, the operation does not return any - information about the delete in the response body. - - :type mfa_token: tuple or list of strings - :param mfa_token: A tuple or list consisting of the serial - number from the MFA device and the current value of the - six-digit token associated with the device. This value is - required anytime you are deleting versioned objects from a - bucket that has the MFADelete option on the bucket. - - :returns: An instance of MultiDeleteResult - """ - ikeys = iter(keys) - result = MultiDeleteResult(self) - provider = self.connection.provider - query_args = 'delete' - - def delete_keys2(hdrs): - hdrs = hdrs or {} - data = u"""<?xml version="1.0" encoding="UTF-8"?>""" - data += u"<Delete>" - if quiet: - data += u"<Quiet>true</Quiet>" - count = 0 - while count < 1000: - try: - key = next(ikeys) - except StopIteration: - break - if isinstance(key, six.string_types): - key_name = key - version_id = None - elif isinstance(key, tuple) and len(key) == 2: - key_name, version_id = key - elif (isinstance(key, Key) or isinstance(key, DeleteMarker)) and key.name: - key_name = key.name - version_id = key.version_id - else: - if isinstance(key, Prefix): - key_name = key.name - code = 'PrefixSkipped' # Don't delete Prefix - else: - key_name = repr(key) # try get a string - code = 'InvalidArgument' # other unknown type - message = 'Invalid. No delete action taken for this object.' - error = Error(key_name, code=code, message=message) - result.errors.append(error) - continue - count += 1 - data += u"<Object><Key>%s</Key>" % xml.sax.saxutils.escape(key_name) - if version_id: - data += u"<VersionId>%s</VersionId>" % version_id - data += u"</Object>" - data += u"</Delete>" - if count <= 0: - return False # no more - data = data.encode('utf-8') - fp = BytesIO(data) - md5 = boto.utils.compute_md5(fp) - hdrs['Content-MD5'] = md5[1] - hdrs['Content-Type'] = 'text/xml' - if mfa_token: - hdrs[provider.mfa_header] = ' '.join(mfa_token) - response = self.connection.make_request('POST', self.name, - headers=hdrs, - query_args=query_args, - data=data) - body = response.read() - if response.status == 200: - h = handler.XmlHandler(result, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return count >= 1000 # more? - else: - raise provider.storage_response_error(response.status, - response.reason, - body) - while delete_keys2(headers): - pass - return result - - def delete_key(self, key_name, headers=None, version_id=None, - mfa_token=None): - """ - Deletes a key from the bucket. If a version_id is provided, - only that version of the key will be deleted. - - :type key_name: string - :param key_name: The key name to delete - - :type version_id: string - :param version_id: The version ID (optional) - - :type mfa_token: tuple or list of strings - :param mfa_token: A tuple or list consisting of the serial - number from the MFA device and the current value of the - six-digit token associated with the device. This value is - required anytime you are deleting versioned objects from a - bucket that has the MFADelete option on the bucket. - - :rtype: :class:`boto.s3.key.Key` or subclass - :returns: A key object holding information on what was - deleted. The Caller can see if a delete_marker was - created or removed and what version_id the delete created - or removed. - """ - if not key_name: - raise ValueError('Empty key names are not allowed') - return self._delete_key_internal(key_name, headers=headers, - version_id=version_id, - mfa_token=mfa_token, - query_args_l=None) - - def _delete_key_internal(self, key_name, headers=None, version_id=None, - mfa_token=None, query_args_l=None): - query_args_l = query_args_l or [] - provider = self.connection.provider - if version_id: - query_args_l.append('versionId=%s' % version_id) - query_args = '&'.join(query_args_l) or None - if mfa_token: - if not headers: - headers = {} - headers[provider.mfa_header] = ' '.join(mfa_token) - response = self.connection.make_request('DELETE', self.name, key_name, - headers=headers, - query_args=query_args) - body = response.read() - if response.status != 204: - raise provider.storage_response_error(response.status, - response.reason, body) - else: - # return a key object with information on what was deleted. - k = self.key_class(self) - k.name = key_name - k.handle_version_headers(response) - k.handle_addl_headers(response.getheaders()) - return k - - def copy_key(self, new_key_name, src_bucket_name, - src_key_name, metadata=None, src_version_id=None, - storage_class='STANDARD', preserve_acl=False, - encrypt_key=False, headers=None, query_args=None): - """ - Create a new key in the bucket by copying another existing key. - - :type new_key_name: string - :param new_key_name: The name of the new key - - :type src_bucket_name: string - :param src_bucket_name: The name of the source bucket - - :type src_key_name: string - :param src_key_name: The name of the source key - - :type src_version_id: string - :param src_version_id: The version id for the key. This param - is optional. If not specified, the newest version of the - key will be copied. - - :type metadata: dict - :param metadata: Metadata to be associated with new key. If - metadata is supplied, it will replace the metadata of the - source key being copied. If no metadata is supplied, the - source key's metadata will be copied to the new key. - - :type storage_class: string - :param storage_class: The storage class of the new key. By - default, the new key will use the standard storage class. - Possible values are: STANDARD | REDUCED_REDUNDANCY - - :type preserve_acl: bool - :param preserve_acl: If True, the ACL from the source key will - be copied to the destination key. If False, the - destination key will have the default ACL. Note that - preserving the ACL in the new key object will require two - additional API calls to S3, one to retrieve the current - ACL and one to set that ACL on the new object. If you - don't care about the ACL, a value of False will be - significantly more efficient. - - :type encrypt_key: bool - :param encrypt_key: If True, the new copy of the object will - be encrypted on the server-side by S3 and will be stored - in an encrypted form while at rest in S3. - - :type headers: dict - :param headers: A dictionary of header name/value pairs. - - :type query_args: string - :param query_args: A string of additional querystring arguments - to append to the request - - :rtype: :class:`boto.s3.key.Key` or subclass - :returns: An instance of the newly created key object - """ - headers = headers or {} - provider = self.connection.provider - src_key_name = boto.utils.get_utf8_value(src_key_name) - if preserve_acl: - if self.name == src_bucket_name: - src_bucket = self - else: - src_bucket = self.connection.get_bucket( - src_bucket_name, validate=False) - acl = src_bucket.get_xml_acl(src_key_name) - if encrypt_key: - headers[provider.server_side_encryption_header] = 'AES256' - src = '%s/%s' % (src_bucket_name, urllib.parse.quote(src_key_name)) - if src_version_id: - src += '?versionId=%s' % src_version_id - headers[provider.copy_source_header] = str(src) - # make sure storage_class_header key exists before accessing it - if provider.storage_class_header and storage_class: - headers[provider.storage_class_header] = storage_class - if metadata is not None: - headers[provider.metadata_directive_header] = 'REPLACE' - headers = boto.utils.merge_meta(headers, metadata, provider) - elif not query_args: # Can't use this header with multi-part copy. - headers[provider.metadata_directive_header] = 'COPY' - response = self.connection.make_request('PUT', self.name, new_key_name, - headers=headers, - query_args=query_args) - body = response.read() - if response.status == 200: - key = self.new_key(new_key_name) - h = handler.XmlHandler(key, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - if hasattr(key, 'Error'): - raise provider.storage_copy_error(key.Code, key.Message, body) - key.handle_version_headers(response) - key.handle_addl_headers(response.getheaders()) - if preserve_acl: - self.set_xml_acl(acl, new_key_name) - return key - else: - raise provider.storage_response_error(response.status, - response.reason, body) - - def set_canned_acl(self, acl_str, key_name='', headers=None, - version_id=None): - assert acl_str in CannedACLStrings - - if headers: - headers[self.connection.provider.acl_header] = acl_str - else: - headers = {self.connection.provider.acl_header: acl_str} - - query_args = 'acl' - if version_id: - query_args += '&versionId=%s' % version_id - response = self.connection.make_request('PUT', self.name, key_name, - headers=headers, query_args=query_args) - body = response.read() - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_xml_acl(self, key_name='', headers=None, version_id=None): - query_args = 'acl' - if version_id: - query_args += '&versionId=%s' % version_id - response = self.connection.make_request('GET', self.name, key_name, - query_args=query_args, - headers=headers) - body = response.read() - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - return body - - def set_xml_acl(self, acl_str, key_name='', headers=None, version_id=None, - query_args='acl'): - if version_id: - query_args += '&versionId=%s' % version_id - if not isinstance(acl_str, bytes): - acl_str = acl_str.encode('utf-8') - response = self.connection.make_request('PUT', self.name, key_name, - data=acl_str, - query_args=query_args, - headers=headers) - body = response.read() - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_acl(self, acl_or_str, key_name='', headers=None, version_id=None): - if isinstance(acl_or_str, Policy): - self.set_xml_acl(acl_or_str.to_xml(), key_name, - headers, version_id) - else: - self.set_canned_acl(acl_or_str, key_name, - headers, version_id) - - def get_acl(self, key_name='', headers=None, version_id=None): - query_args = 'acl' - if version_id: - query_args += '&versionId=%s' % version_id - response = self.connection.make_request('GET', self.name, key_name, - query_args=query_args, - headers=headers) - body = response.read() - if response.status == 200: - policy = Policy(self) - h = handler.XmlHandler(policy, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return policy - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_subresource(self, subresource, value, key_name='', headers=None, - version_id=None): - """ - Set a subresource for a bucket or key. - - :type subresource: string - :param subresource: The subresource to set. - - :type value: string - :param value: The value of the subresource. - - :type key_name: string - :param key_name: The key to operate on, or None to operate on the - bucket. - - :type headers: dict - :param headers: Additional HTTP headers to include in the request. - - :type src_version_id: string - :param src_version_id: Optional. The version id of the key to - operate on. If not specified, operate on the newest - version. - """ - if not subresource: - raise TypeError('set_subresource called with subresource=None') - query_args = subresource - if version_id: - query_args += '&versionId=%s' % version_id - if not isinstance(value, bytes): - value = value.encode('utf-8') - response = self.connection.make_request('PUT', self.name, key_name, - data=value, - query_args=query_args, - headers=headers) - body = response.read() - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_subresource(self, subresource, key_name='', headers=None, - version_id=None): - """ - Get a subresource for a bucket or key. - - :type subresource: string - :param subresource: The subresource to get. - - :type key_name: string - :param key_name: The key to operate on, or None to operate on the - bucket. - - :type headers: dict - :param headers: Additional HTTP headers to include in the request. - - :type src_version_id: string - :param src_version_id: Optional. The version id of the key to - operate on. If not specified, operate on the newest - version. - - :rtype: string - :returns: The value of the subresource. - """ - if not subresource: - raise TypeError('get_subresource called with subresource=None') - query_args = subresource - if version_id: - query_args += '&versionId=%s' % version_id - response = self.connection.make_request('GET', self.name, key_name, - query_args=query_args, - headers=headers) - body = response.read() - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - return body - - def make_public(self, recursive=False, headers=None): - self.set_canned_acl('public-read', headers=headers) - if recursive: - for key in self: - self.set_canned_acl('public-read', key.name, headers=headers) - - def add_email_grant(self, permission, email_address, - recursive=False, headers=None): - """ - Convenience method that provides a quick way to add an email grant - to a bucket. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL - and then PUT's the new ACL back to S3. - - :type permission: string - :param permission: The permission being granted. Should be one of: - (READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL). - - :type email_address: string - :param email_address: The email address associated with the AWS - account your are granting the permission to. - - :type recursive: boolean - :param recursive: A boolean value to controls whether the - command will apply the grant to all keys within the bucket - or not. The default value is False. By passing a True - value, the call will iterate through all keys in the - bucket and apply the same grant to each key. CAUTION: If - you have a lot of keys, this could take a long time! - """ - if permission not in S3Permissions: - raise self.connection.provider.storage_permissions_error( - 'Unknown Permission: %s' % permission) - policy = self.get_acl(headers=headers) - policy.acl.add_email_grant(permission, email_address) - self.set_acl(policy, headers=headers) - if recursive: - for key in self: - key.add_email_grant(permission, email_address, headers=headers) - - def add_user_grant(self, permission, user_id, recursive=False, - headers=None, display_name=None): - """ - Convenience method that provides a quick way to add a canonical - user grant to a bucket. This method retrieves the current ACL, - creates a new grant based on the parameters passed in, adds that - grant to the ACL and then PUT's the new ACL back to S3. - - :type permission: string - :param permission: The permission being granted. Should be one of: - (READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL). - - :type user_id: string - :param user_id: The canonical user id associated with the AWS - account your are granting the permission to. - - :type recursive: boolean - :param recursive: A boolean value to controls whether the - command will apply the grant to all keys within the bucket - or not. The default value is False. By passing a True - value, the call will iterate through all keys in the - bucket and apply the same grant to each key. CAUTION: If - you have a lot of keys, this could take a long time! - - :type display_name: string - :param display_name: An option string containing the user's - Display Name. Only required on Walrus. - """ - if permission not in S3Permissions: - raise self.connection.provider.storage_permissions_error( - 'Unknown Permission: %s' % permission) - policy = self.get_acl(headers=headers) - policy.acl.add_user_grant(permission, user_id, - display_name=display_name) - self.set_acl(policy, headers=headers) - if recursive: - for key in self: - key.add_user_grant(permission, user_id, headers=headers, - display_name=display_name) - - def list_grants(self, headers=None): - policy = self.get_acl(headers=headers) - return policy.acl.grants - - def get_location(self): - """ - Returns the LocationConstraint for the bucket. - - :rtype: str - :return: The LocationConstraint for the bucket or the empty - string if no constraint was specified when bucket was created. - """ - response = self.connection.make_request('GET', self.name, - query_args='location') - body = response.read() - if response.status == 200: - rs = ResultSet(self) - h = handler.XmlHandler(rs, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return rs.LocationConstraint - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_xml_logging(self, logging_str, headers=None): - """ - Set logging on a bucket directly to the given xml string. - - :type logging_str: unicode string - :param logging_str: The XML for the bucketloggingstatus which - will be set. The string will be converted to utf-8 before - it is sent. Usually, you will obtain this XML from the - BucketLogging object. - - :rtype: bool - :return: True if ok or raises an exception. - """ - body = logging_str - if not isinstance(body, bytes): - body = body.encode('utf-8') - response = self.connection.make_request('PUT', self.name, data=body, - query_args='logging', headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def enable_logging(self, target_bucket, target_prefix='', - grants=None, headers=None): - """ - Enable logging on a bucket. - - :type target_bucket: bucket or string - :param target_bucket: The bucket to log to. - - :type target_prefix: string - :param target_prefix: The prefix which should be prepended to the - generated log files written to the target_bucket. - - :type grants: list of Grant objects - :param grants: A list of extra permissions which will be granted on - the log files which are created. - - :rtype: bool - :return: True if ok or raises an exception. - """ - if isinstance(target_bucket, Bucket): - target_bucket = target_bucket.name - blogging = BucketLogging(target=target_bucket, prefix=target_prefix, - grants=grants) - return self.set_xml_logging(blogging.to_xml(), headers=headers) - - def disable_logging(self, headers=None): - """ - Disable logging on a bucket. - - :rtype: bool - :return: True if ok or raises an exception. - """ - blogging = BucketLogging() - return self.set_xml_logging(blogging.to_xml(), headers=headers) - - def get_logging_status(self, headers=None): - """ - Get the logging status for this bucket. - - :rtype: :class:`boto.s3.bucketlogging.BucketLogging` - :return: A BucketLogging object for this bucket. - """ - response = self.connection.make_request('GET', self.name, - query_args='logging', headers=headers) - body = response.read() - if response.status == 200: - blogging = BucketLogging() - h = handler.XmlHandler(blogging, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return blogging - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_as_logging_target(self, headers=None): - """ - Setup the current bucket as a logging target by granting the necessary - permissions to the LogDelivery group to write log files to this bucket. - """ - policy = self.get_acl(headers=headers) - g1 = Grant(permission='WRITE', type='Group', uri=self.LoggingGroup) - g2 = Grant(permission='READ_ACP', type='Group', uri=self.LoggingGroup) - policy.acl.add_grant(g1) - policy.acl.add_grant(g2) - self.set_acl(policy, headers=headers) - - def get_request_payment(self, headers=None): - response = self.connection.make_request('GET', self.name, - query_args='requestPayment', headers=headers) - body = response.read() - if response.status == 200: - return body - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_request_payment(self, payer='BucketOwner', headers=None): - body = self.BucketPaymentBody % payer - response = self.connection.make_request('PUT', self.name, data=body, - query_args='requestPayment', headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def configure_versioning(self, versioning, mfa_delete=False, - mfa_token=None, headers=None): - """ - Configure versioning for this bucket. - - ..note:: This feature is currently in beta. - - :type versioning: bool - :param versioning: A boolean indicating whether version is - enabled (True) or disabled (False). - - :type mfa_delete: bool - :param mfa_delete: A boolean indicating whether the - Multi-Factor Authentication Delete feature is enabled - (True) or disabled (False). If mfa_delete is enabled then - all Delete operations will require the token from your MFA - device to be passed in the request. - - :type mfa_token: tuple or list of strings - :param mfa_token: A tuple or list consisting of the serial - number from the MFA device and the current value of the - six-digit token associated with the device. This value is - required when you are changing the status of the MfaDelete - property of the bucket. - """ - if versioning: - ver = 'Enabled' - else: - ver = 'Suspended' - if mfa_delete: - mfa = 'Enabled' - else: - mfa = 'Disabled' - body = self.VersioningBody % (ver, mfa) - if mfa_token: - if not headers: - headers = {} - provider = self.connection.provider - headers[provider.mfa_header] = ' '.join(mfa_token) - response = self.connection.make_request('PUT', self.name, data=body, - query_args='versioning', headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_versioning_status(self, headers=None): - """ - Returns the current status of versioning on the bucket. - - :rtype: dict - :returns: A dictionary containing a key named 'Versioning' - that can have a value of either Enabled, Disabled, or - Suspended. Also, if MFADelete has ever been enabled on the - bucket, the dictionary will contain a key named - 'MFADelete' which will have a value of either Enabled or - Suspended. - """ - response = self.connection.make_request('GET', self.name, - query_args='versioning', headers=headers) - body = response.read() - if not isinstance(body, six.string_types): - body = body.decode('utf-8') - boto.log.debug(body) - if response.status == 200: - d = {} - ver = re.search(self.VersionRE, body) - if ver: - d['Versioning'] = ver.group(1) - mfa = re.search(self.MFADeleteRE, body) - if mfa: - d['MfaDelete'] = mfa.group(1) - return d - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def configure_lifecycle(self, lifecycle_config, headers=None): - """ - Configure lifecycle for this bucket. - - :type lifecycle_config: :class:`boto.s3.lifecycle.Lifecycle` - :param lifecycle_config: The lifecycle configuration you want - to configure for this bucket. - """ - xml = lifecycle_config.to_xml() - #xml = xml.encode('utf-8') - fp = StringIO(xml) - md5 = boto.utils.compute_md5(fp) - if headers is None: - headers = {} - headers['Content-MD5'] = md5[1] - headers['Content-Type'] = 'text/xml' - response = self.connection.make_request('PUT', self.name, - data=fp.getvalue(), - query_args='lifecycle', - headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_lifecycle_config(self, headers=None): - """ - Returns the current lifecycle configuration on the bucket. - - :rtype: :class:`boto.s3.lifecycle.Lifecycle` - :returns: A LifecycleConfig object that describes all current - lifecycle rules in effect for the bucket. - """ - response = self.connection.make_request('GET', self.name, - query_args='lifecycle', headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 200: - lifecycle = Lifecycle() - h = handler.XmlHandler(lifecycle, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return lifecycle - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def delete_lifecycle_configuration(self, headers=None): - """ - Removes all lifecycle configuration from the bucket. - """ - response = self.connection.make_request('DELETE', self.name, - query_args='lifecycle', - headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 204: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def configure_website(self, suffix=None, error_key=None, - redirect_all_requests_to=None, - routing_rules=None, - headers=None): - """ - Configure this bucket to act as a website - - :type suffix: str - :param suffix: Suffix that is appended to a request that is for a - "directory" on the website endpoint (e.g. if the suffix is - index.html and you make a request to samplebucket/images/ - the data that is returned will be for the object with the - key name images/index.html). The suffix must not be empty - and must not include a slash character. - - :type error_key: str - :param error_key: The object key name to use when a 4XX class - error occurs. This is optional. - - :type redirect_all_requests_to: :class:`boto.s3.website.RedirectLocation` - :param redirect_all_requests_to: Describes the redirect behavior for - every request to this bucket's website endpoint. If this value is - non None, no other values are considered when configuring the - website configuration for the bucket. This is an instance of - ``RedirectLocation``. - - :type routing_rules: :class:`boto.s3.website.RoutingRules` - :param routing_rules: Object which specifies conditions - and redirects that apply when the conditions are met. - - """ - config = website.WebsiteConfiguration( - suffix, error_key, redirect_all_requests_to, - routing_rules) - return self.set_website_configuration(config, headers=headers) - - def set_website_configuration(self, config, headers=None): - """ - :type config: boto.s3.website.WebsiteConfiguration - :param config: Configuration data - """ - return self.set_website_configuration_xml(config.to_xml(), - headers=headers) - - - def set_website_configuration_xml(self, xml, headers=None): - """Upload xml website configuration""" - response = self.connection.make_request('PUT', self.name, data=xml, - query_args='website', - headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_website_configuration(self, headers=None): - """ - Returns the current status of website configuration on the bucket. - - :rtype: dict - :returns: A dictionary containing a Python representation - of the XML response from S3. The overall structure is: - - * WebsiteConfiguration - - * IndexDocument - - * Suffix : suffix that is appended to request that - is for a "directory" on the website endpoint - * ErrorDocument - - * Key : name of object to serve when an error occurs - - """ - return self.get_website_configuration_with_xml(headers)[0] - - def get_website_configuration_obj(self, headers=None): - """Get the website configuration as a - :class:`boto.s3.website.WebsiteConfiguration` object. - """ - config_xml = self.get_website_configuration_xml(headers=headers) - config = website.WebsiteConfiguration() - h = handler.XmlHandler(config, self) - xml.sax.parseString(config_xml, h) - return config - - def get_website_configuration_with_xml(self, headers=None): - """ - Returns the current status of website configuration on the bucket as - unparsed XML. - - :rtype: 2-Tuple - :returns: 2-tuple containing: - - 1) A dictionary containing a Python representation \ - of the XML response. The overall structure is: - - * WebsiteConfiguration - - * IndexDocument - - * Suffix : suffix that is appended to request that \ - is for a "directory" on the website endpoint - - * ErrorDocument - - * Key : name of object to serve when an error occurs - - - 2) unparsed XML describing the bucket's website configuration - - """ - - body = self.get_website_configuration_xml(headers=headers) - e = boto.jsonresponse.Element() - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e, body - - def get_website_configuration_xml(self, headers=None): - """Get raw website configuration xml""" - response = self.connection.make_request('GET', self.name, - query_args='website', headers=headers) - body = response.read().decode('utf-8') - boto.log.debug(body) - - if response.status != 200: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - return body - - def delete_website_configuration(self, headers=None): - """ - Removes all website configuration from the bucket. - """ - response = self.connection.make_request('DELETE', self.name, - query_args='website', headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 204: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_website_endpoint(self): - """ - Returns the fully qualified hostname to use is you want to access this - bucket as a website. This doesn't validate whether the bucket has - been correctly configured as a website or not. - """ - l = [self.name] - l.append(S3WebsiteEndpointTranslate.translate_region(self.get_location())) - l.append('.'.join(self.connection.host.split('.')[-2:])) - return '.'.join(l) - - def get_policy(self, headers=None): - """ - Returns the JSON policy associated with the bucket. The policy - is returned as an uninterpreted JSON string. - """ - response = self.connection.make_request('GET', self.name, - query_args='policy', headers=headers) - body = response.read() - if response.status == 200: - return body - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_policy(self, policy, headers=None): - """ - Add or replace the JSON policy associated with the bucket. - - :type policy: str - :param policy: The JSON policy as a string. - """ - response = self.connection.make_request('PUT', self.name, - data=policy, - query_args='policy', - headers=headers) - body = response.read() - if response.status >= 200 and response.status <= 204: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def delete_policy(self, headers=None): - response = self.connection.make_request('DELETE', self.name, - data='/?policy', - query_args='policy', - headers=headers) - body = response.read() - if response.status >= 200 and response.status <= 204: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_cors_xml(self, cors_xml, headers=None): - """ - Set the CORS (Cross-Origin Resource Sharing) for a bucket. - - :type cors_xml: str - :param cors_xml: The XML document describing your desired - CORS configuration. See the S3 documentation for details - of the exact syntax required. - """ - fp = StringIO(cors_xml) - md5 = boto.utils.compute_md5(fp) - if headers is None: - headers = {} - headers['Content-MD5'] = md5[1] - headers['Content-Type'] = 'text/xml' - response = self.connection.make_request('PUT', self.name, - data=fp.getvalue(), - query_args='cors', - headers=headers) - body = response.read() - if response.status == 200: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_cors(self, cors_config, headers=None): - """ - Set the CORS for this bucket given a boto CORSConfiguration - object. - - :type cors_config: :class:`boto.s3.cors.CORSConfiguration` - :param cors_config: The CORS configuration you want - to configure for this bucket. - """ - return self.set_cors_xml(cors_config.to_xml()) - - def get_cors_xml(self, headers=None): - """ - Returns the current CORS configuration on the bucket as an - XML document. - """ - response = self.connection.make_request('GET', self.name, - query_args='cors', headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 200: - return body - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def get_cors(self, headers=None): - """ - Returns the current CORS configuration on the bucket. - - :rtype: :class:`boto.s3.cors.CORSConfiguration` - :returns: A CORSConfiguration object that describes all current - CORS rules in effect for the bucket. - """ - body = self.get_cors_xml(headers) - cors = CORSConfiguration() - h = handler.XmlHandler(cors, self) - xml.sax.parseString(body, h) - return cors - - def delete_cors(self, headers=None): - """ - Removes all CORS configuration from the bucket. - """ - response = self.connection.make_request('DELETE', self.name, - query_args='cors', - headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 204: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def initiate_multipart_upload(self, key_name, headers=None, - reduced_redundancy=False, - metadata=None, encrypt_key=False, - policy=None): - """ - Start a multipart upload operation. - - .. note:: - - Note: After you initiate multipart upload and upload one or more - parts, you must either complete or abort multipart upload in order - to stop getting charged for storage of the uploaded parts. Only - after you either complete or abort multipart upload, Amazon S3 - frees up the parts storage and stops charging you for the parts - storage. - - :type key_name: string - :param key_name: The name of the key that will ultimately - result from this multipart upload operation. This will be - exactly as the key appears in the bucket after the upload - process has been completed. - - :type headers: dict - :param headers: Additional HTTP headers to send and store with the - resulting key in S3. - - :type reduced_redundancy: boolean - :param reduced_redundancy: In multipart uploads, the storage - class is specified when initiating the upload, not when - uploading individual parts. So if you want the resulting - key to use the reduced redundancy storage class set this - flag when you initiate the upload. - - :type metadata: dict - :param metadata: Any metadata that you would like to set on the key - that results from the multipart upload. - - :type encrypt_key: bool - :param encrypt_key: If True, the new copy of the object will - be encrypted on the server-side by S3 and will be stored - in an encrypted form while at rest in S3. - - :type policy: :class:`boto.s3.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the - new key (once completed) in S3. - """ - query_args = 'uploads' - provider = self.connection.provider - headers = headers or {} - if policy: - headers[provider.acl_header] = policy - if reduced_redundancy: - storage_class_header = provider.storage_class_header - if storage_class_header: - headers[storage_class_header] = 'REDUCED_REDUNDANCY' - # TODO: what if the provider doesn't support reduced redundancy? - # (see boto.s3.key.Key.set_contents_from_file) - if encrypt_key: - headers[provider.server_side_encryption_header] = 'AES256' - if metadata is None: - metadata = {} - - headers = boto.utils.merge_meta(headers, metadata, - self.connection.provider) - response = self.connection.make_request('POST', self.name, key_name, - query_args=query_args, - headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 200: - resp = MultiPartUpload(self) - h = handler.XmlHandler(resp, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return resp - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def complete_multipart_upload(self, key_name, upload_id, - xml_body, headers=None): - """ - Complete a multipart upload operation. - """ - query_args = 'uploadId=%s' % upload_id - if headers is None: - headers = {} - headers['Content-Type'] = 'text/xml' - response = self.connection.make_request('POST', self.name, key_name, - query_args=query_args, - headers=headers, data=xml_body) - contains_error = False - body = response.read().decode('utf-8') - # Some errors will be reported in the body of the response - # even though the HTTP response code is 200. This check - # does a quick and dirty peek in the body for an error element. - if body.find('<Error>') > 0: - contains_error = True - boto.log.debug(body) - if response.status == 200 and not contains_error: - resp = CompleteMultiPartUpload(self) - h = handler.XmlHandler(resp, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - # Use a dummy key to parse various response headers - # for versioning, encryption info and then explicitly - # set the completed MPU object values from key. - k = self.key_class(self) - k.handle_version_headers(response) - k.handle_encryption_headers(response) - resp.version_id = k.version_id - resp.encrypted = k.encrypted - return resp - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def cancel_multipart_upload(self, key_name, upload_id, headers=None): - """ - To verify that all parts have been removed, so you don't get charged - for the part storage, you should call the List Parts operation and - ensure the parts list is empty. - """ - query_args = 'uploadId=%s' % upload_id - response = self.connection.make_request('DELETE', self.name, key_name, - query_args=query_args, - headers=headers) - body = response.read() - boto.log.debug(body) - if response.status != 204: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def delete(self, headers=None): - return self.connection.delete_bucket(self.name, headers=headers) - - def get_tags(self): - response = self.get_xml_tags() - tags = Tags() - h = handler.XmlHandler(tags, self) - if not isinstance(response, bytes): - response = response.encode('utf-8') - xml.sax.parseString(response, h) - return tags - - def get_xml_tags(self): - response = self.connection.make_request('GET', self.name, - query_args='tagging', - headers=None) - body = response.read() - if response.status == 200: - return body - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - - def set_xml_tags(self, tag_str, headers=None, query_args='tagging'): - if headers is None: - headers = {} - md5 = boto.utils.compute_md5(StringIO(tag_str)) - headers['Content-MD5'] = md5[1] - headers['Content-Type'] = 'text/xml' - if not isinstance(tag_str, bytes): - tag_str = tag_str.encode('utf-8') - response = self.connection.make_request('PUT', self.name, - data=tag_str, - query_args=query_args, - headers=headers) - body = response.read() - if response.status != 204: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) - return True - - def set_tags(self, tags, headers=None): - return self.set_xml_tags(tags.to_xml(), headers=headers) - - def delete_tags(self, headers=None): - response = self.connection.make_request('DELETE', self.name, - query_args='tagging', - headers=headers) - body = response.read() - boto.log.debug(body) - if response.status == 204: - return True - else: - raise self.connection.provider.storage_response_error( - response.status, response.reason, body) diff --git a/awx/lib/site-packages/boto/s3/bucketlistresultset.py b/awx/lib/site-packages/boto/s3/bucketlistresultset.py deleted file mode 100644 index ab9c65e456..0000000000 --- a/awx/lib/site-packages/boto/s3/bucketlistresultset.py +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.compat import urllib, six - -def bucket_lister(bucket, prefix='', delimiter='', marker='', headers=None, - encoding_type=None): - """ - A generator function for listing keys in a bucket. - """ - more_results = True - k = None - while more_results: - rs = bucket.get_all_keys(prefix=prefix, marker=marker, - delimiter=delimiter, headers=headers, - encoding_type=encoding_type) - for k in rs: - yield k - if k: - marker = rs.next_marker or k.name - if marker and encoding_type == "url": - if isinstance(marker, six.text_type): - marker = marker.encode('utf-8') - marker = urllib.parse.unquote(marker) - more_results= rs.is_truncated - -class BucketListResultSet(object): - """ - A resultset for listing keys within a bucket. Uses the bucket_lister - generator function and implements the iterator interface. This - transparently handles the results paging from S3 so even if you have - many thousands of keys within the bucket you can iterate over all - keys in a reasonably efficient manner. - """ - - def __init__(self, bucket=None, prefix='', delimiter='', marker='', - headers=None, encoding_type=None): - self.bucket = bucket - self.prefix = prefix - self.delimiter = delimiter - self.marker = marker - self.headers = headers - self.encoding_type = encoding_type - - def __iter__(self): - return bucket_lister(self.bucket, prefix=self.prefix, - delimiter=self.delimiter, marker=self.marker, - headers=self.headers, - encoding_type=self.encoding_type) - -def versioned_bucket_lister(bucket, prefix='', delimiter='', - key_marker='', version_id_marker='', headers=None, - encoding_type=None): - """ - A generator function for listing versions in a bucket. - """ - more_results = True - k = None - while more_results: - rs = bucket.get_all_versions(prefix=prefix, key_marker=key_marker, - version_id_marker=version_id_marker, - delimiter=delimiter, headers=headers, - max_keys=999, encoding_type=encoding_type) - for k in rs: - yield k - key_marker = rs.next_key_marker - version_id_marker = rs.next_version_id_marker - more_results= rs.is_truncated - -class VersionedBucketListResultSet(object): - """ - A resultset for listing versions within a bucket. Uses the bucket_lister - generator function and implements the iterator interface. This - transparently handles the results paging from S3 so even if you have - many thousands of keys within the bucket you can iterate over all - keys in a reasonably efficient manner. - """ - - def __init__(self, bucket=None, prefix='', delimiter='', key_marker='', - version_id_marker='', headers=None, encoding_type=None): - self.bucket = bucket - self.prefix = prefix - self.delimiter = delimiter - self.key_marker = key_marker - self.version_id_marker = version_id_marker - self.headers = headers - self.encoding_type = encoding_type - - def __iter__(self): - return versioned_bucket_lister(self.bucket, prefix=self.prefix, - delimiter=self.delimiter, - key_marker=self.key_marker, - version_id_marker=self.version_id_marker, - headers=self.headers, - encoding_type=self.encoding_type) - -def multipart_upload_lister(bucket, key_marker='', - upload_id_marker='', - headers=None, encoding_type=None): - """ - A generator function for listing multipart uploads in a bucket. - """ - more_results = True - k = None - while more_results: - rs = bucket.get_all_multipart_uploads(key_marker=key_marker, - upload_id_marker=upload_id_marker, - headers=headers, - encoding_type=encoding_type) - for k in rs: - yield k - key_marker = rs.next_key_marker - upload_id_marker = rs.next_upload_id_marker - more_results= rs.is_truncated - -class MultiPartUploadListResultSet(object): - """ - A resultset for listing multipart uploads within a bucket. - Uses the multipart_upload_lister generator function and - implements the iterator interface. This - transparently handles the results paging from S3 so even if you have - many thousands of uploads within the bucket you can iterate over all - keys in a reasonably efficient manner. - """ - def __init__(self, bucket=None, key_marker='', - upload_id_marker='', headers=None, encoding_type=None): - self.bucket = bucket - self.key_marker = key_marker - self.upload_id_marker = upload_id_marker - self.headers = headers - self.encoding_type = encoding_type - - def __iter__(self): - return multipart_upload_lister(self.bucket, - key_marker=self.key_marker, - upload_id_marker=self.upload_id_marker, - headers=self.headers, - encoding_type=self.encoding_type) diff --git a/awx/lib/site-packages/boto/s3/bucketlogging.py b/awx/lib/site-packages/boto/s3/bucketlogging.py deleted file mode 100644 index 38cef1140e..0000000000 --- a/awx/lib/site-packages/boto/s3/bucketlogging.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import xml.sax.saxutils -from boto.s3.acl import Grant - -class BucketLogging(object): - - def __init__(self, target=None, prefix=None, grants=None): - self.target = target - self.prefix = prefix - if grants is None: - self.grants = [] - else: - self.grants = grants - - def __repr__(self): - if self.target is None: - return "<BucketLoggingStatus: Disabled>" - grants = [] - for g in self.grants: - if g.type == 'CanonicalUser': - u = g.display_name - elif g.type == 'Group': - u = g.uri - else: - u = g.email_address - grants.append("%s = %s" % (u, g.permission)) - return "<BucketLoggingStatus: %s/%s (%s)>" % (self.target, self.prefix, ", ".join(grants)) - - def add_grant(self, grant): - self.grants.append(grant) - - def startElement(self, name, attrs, connection): - if name == 'Grant': - self.grants.append(Grant()) - return self.grants[-1] - else: - return None - - def endElement(self, name, value, connection): - if name == 'TargetBucket': - self.target = value - elif name == 'TargetPrefix': - self.prefix = value - else: - setattr(self, name, value) - - def to_xml(self): - # caller is responsible to encode to utf-8 - s = u'<?xml version="1.0" encoding="UTF-8"?>' - s += u'<BucketLoggingStatus xmlns="http://doc.s3.amazonaws.com/2006-03-01">' - if self.target is not None: - s += u'<LoggingEnabled>' - s += u'<TargetBucket>%s</TargetBucket>' % self.target - prefix = self.prefix or '' - s += u'<TargetPrefix>%s</TargetPrefix>' % xml.sax.saxutils.escape(prefix) - if self.grants: - s += '<TargetGrants>' - for grant in self.grants: - s += grant.to_xml() - s += '</TargetGrants>' - s += u'</LoggingEnabled>' - s += u'</BucketLoggingStatus>' - return s diff --git a/awx/lib/site-packages/boto/s3/connection.py b/awx/lib/site-packages/boto/s3/connection.py deleted file mode 100644 index 0fcc1f5957..0000000000 --- a/awx/lib/site-packages/boto/s3/connection.py +++ /dev/null @@ -1,665 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import xml.sax -import base64 -from boto.compat import six, urllib -import time - -from boto.auth import detect_potential_s3sigv4 -import boto.utils -from boto.connection import AWSAuthConnection -from boto import handler -from boto.s3.bucket import Bucket -from boto.s3.key import Key -from boto.resultset import ResultSet -from boto.exception import BotoClientError, S3ResponseError - - -def check_lowercase_bucketname(n): - """ - Bucket names must not contain uppercase characters. We check for - this by appending a lowercase character and testing with islower(). - Note this also covers cases like numeric bucket names with dashes. - - >>> check_lowercase_bucketname("Aaaa") - Traceback (most recent call last): - ... - BotoClientError: S3Error: Bucket names cannot contain upper-case - characters when using either the sub-domain or virtual hosting calling - format. - - >>> check_lowercase_bucketname("1234-5678-9123") - True - >>> check_lowercase_bucketname("abcdefg1234") - True - """ - if not (n + 'a').islower(): - raise BotoClientError("Bucket names cannot contain upper-case " \ - "characters when using either the sub-domain or virtual " \ - "hosting calling format.") - return True - - -def assert_case_insensitive(f): - def wrapper(*args, **kwargs): - if len(args) == 3 and check_lowercase_bucketname(args[2]): - pass - return f(*args, **kwargs) - return wrapper - - -class _CallingFormat(object): - - def get_bucket_server(self, server, bucket): - return '' - - def build_url_base(self, connection, protocol, server, bucket, key=''): - url_base = '%s://' % protocol - url_base += self.build_host(server, bucket) - url_base += connection.get_path(self.build_path_base(bucket, key)) - return url_base - - def build_host(self, server, bucket): - if bucket == '': - return server - else: - return self.get_bucket_server(server, bucket) - - def build_auth_path(self, bucket, key=''): - key = boto.utils.get_utf8_value(key) - path = '' - if bucket != '': - path = '/' + bucket - return path + '/%s' % urllib.parse.quote(key) - - def build_path_base(self, bucket, key=''): - key = boto.utils.get_utf8_value(key) - return '/%s' % urllib.parse.quote(key) - - -class SubdomainCallingFormat(_CallingFormat): - - @assert_case_insensitive - def get_bucket_server(self, server, bucket): - return '%s.%s' % (bucket, server) - - -class VHostCallingFormat(_CallingFormat): - - @assert_case_insensitive - def get_bucket_server(self, server, bucket): - return bucket - - -class OrdinaryCallingFormat(_CallingFormat): - - def get_bucket_server(self, server, bucket): - return server - - def build_path_base(self, bucket, key=''): - key = boto.utils.get_utf8_value(key) - path_base = '/' - if bucket: - path_base += "%s/" % bucket - return path_base + urllib.parse.quote(key) - - -class ProtocolIndependentOrdinaryCallingFormat(OrdinaryCallingFormat): - - def build_url_base(self, connection, protocol, server, bucket, key=''): - url_base = '//' - url_base += self.build_host(server, bucket) - url_base += connection.get_path(self.build_path_base(bucket, key)) - return url_base - - -class Location(object): - - DEFAULT = '' # US Classic Region - EU = 'EU' - USWest = 'us-west-1' - USWest2 = 'us-west-2' - SAEast = 'sa-east-1' - APNortheast = 'ap-northeast-1' - APSoutheast = 'ap-southeast-1' - APSoutheast2 = 'ap-southeast-2' - CNNorth1 = 'cn-north-1' - - -class NoHostProvided(object): - # An identifying object to help determine whether the user provided a - # ``host`` or not. Never instantiated. - pass - - -class HostRequiredError(BotoClientError): - pass - - -class S3Connection(AWSAuthConnection): - - DefaultHost = boto.config.get('s3', 'host', 's3.amazonaws.com') - DefaultCallingFormat = boto.config.get('s3', 'calling_format', 'boto.s3.connection.SubdomainCallingFormat') - QueryString = 'Signature=%s&Expires=%d&AWSAccessKeyId=%s' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, - host=NoHostProvided, debug=0, https_connection_factory=None, - calling_format=DefaultCallingFormat, path='/', - provider='aws', bucket_class=Bucket, security_token=None, - suppress_consec_slashes=True, anon=False, - validate_certs=None, profile_name=None): - no_host_provided = False - if host is NoHostProvided: - no_host_provided = True - host = self.DefaultHost - if isinstance(calling_format, six.string_types): - calling_format=boto.utils.find_class(calling_format)() - self.calling_format = calling_format - self.bucket_class = bucket_class - self.anon = anon - super(S3Connection, self).__init__(host, - aws_access_key_id, aws_secret_access_key, - is_secure, port, proxy, proxy_port, proxy_user, proxy_pass, - debug=debug, https_connection_factory=https_connection_factory, - path=path, provider=provider, security_token=security_token, - suppress_consec_slashes=suppress_consec_slashes, - validate_certs=validate_certs, profile_name=profile_name) - # We need to delay until after the call to ``super`` before checking - # to see if SigV4 is in use. - if no_host_provided: - if 'hmac-v4-s3' in self._required_auth_capability(): - raise HostRequiredError( - "When using SigV4, you must specify a 'host' parameter." - ) - - @detect_potential_s3sigv4 - def _required_auth_capability(self): - if self.anon: - return ['anon'] - else: - return ['s3'] - - def __iter__(self): - for bucket in self.get_all_buckets(): - yield bucket - - def __contains__(self, bucket_name): - return not (self.lookup(bucket_name) is None) - - def set_bucket_class(self, bucket_class): - """ - Set the Bucket class associated with this bucket. By default, this - would be the boto.s3.key.Bucket class but if you want to subclass that - for some reason this allows you to associate your new class. - - :type bucket_class: class - :param bucket_class: A subclass of Bucket that can be more specific - """ - self.bucket_class = bucket_class - - def build_post_policy(self, expiration_time, conditions): - """ - Taken from the AWS book Python examples and modified for use with boto - """ - assert isinstance(expiration_time, time.struct_time), \ - 'Policy document must include a valid expiration Time object' - - # Convert conditions object mappings to condition statements - - return '{"expiration": "%s",\n"conditions": [%s]}' % \ - (time.strftime(boto.utils.ISO8601, expiration_time), ",".join(conditions)) - - def build_post_form_args(self, bucket_name, key, expires_in=6000, - acl=None, success_action_redirect=None, - max_content_length=None, - http_method='http', fields=None, - conditions=None, storage_class='STANDARD', - server_side_encryption=None): - """ - Taken from the AWS book Python examples and modified for use with boto - This only returns the arguments required for the post form, not the - actual form. This does not return the file input field which also - needs to be added - - :type bucket_name: string - :param bucket_name: Bucket to submit to - - :type key: string - :param key: Key name, optionally add ${filename} to the end to - attach the submitted filename - - :type expires_in: integer - :param expires_in: Time (in seconds) before this expires, defaults - to 6000 - - :type acl: string - :param acl: A canned ACL. One of: - * private - * public-read - * public-read-write - * authenticated-read - * bucket-owner-read - * bucket-owner-full-control - - :type success_action_redirect: string - :param success_action_redirect: URL to redirect to on success - - :type max_content_length: integer - :param max_content_length: Maximum size for this file - - :type http_method: string - :param http_method: HTTP Method to use, "http" or "https" - - :type storage_class: string - :param storage_class: Storage class to use for storing the object. - Valid values: STANDARD | REDUCED_REDUNDANCY - - :type server_side_encryption: string - :param server_side_encryption: Specifies server-side encryption - algorithm to use when Amazon S3 creates an object. - Valid values: None | AES256 - - :rtype: dict - :return: A dictionary containing field names/values as well as - a url to POST to - - .. code-block:: python - - - """ - if fields is None: - fields = [] - if conditions is None: - conditions = [] - expiration = time.gmtime(int(time.time() + expires_in)) - - # Generate policy document - conditions.append('{"bucket": "%s"}' % bucket_name) - if key.endswith("${filename}"): - conditions.append('["starts-with", "$key", "%s"]' % key[:-len("${filename}")]) - else: - conditions.append('{"key": "%s"}' % key) - if acl: - conditions.append('{"acl": "%s"}' % acl) - fields.append({"name": "acl", "value": acl}) - if success_action_redirect: - conditions.append('{"success_action_redirect": "%s"}' % success_action_redirect) - fields.append({"name": "success_action_redirect", "value": success_action_redirect}) - if max_content_length: - conditions.append('["content-length-range", 0, %i]' % max_content_length) - - if self.provider.security_token: - fields.append({'name': 'x-amz-security-token', - 'value': self.provider.security_token}) - conditions.append('{"x-amz-security-token": "%s"}' % self.provider.security_token) - - if storage_class: - fields.append({'name': 'x-amz-storage-class', - 'value': storage_class}) - conditions.append('{"x-amz-storage-class": "%s"}' % storage_class) - - if server_side_encryption: - fields.append({'name': 'x-amz-server-side-encryption', - 'value': server_side_encryption}) - conditions.append('{"x-amz-server-side-encryption": "%s"}' % server_side_encryption) - - policy = self.build_post_policy(expiration, conditions) - - # Add the base64-encoded policy document as the 'policy' field - policy_b64 = base64.b64encode(policy) - fields.append({"name": "policy", "value": policy_b64}) - - # Add the AWS access key as the 'AWSAccessKeyId' field - fields.append({"name": "AWSAccessKeyId", - "value": self.aws_access_key_id}) - - # Add signature for encoded policy document as the - # 'signature' field - signature = self._auth_handler.sign_string(policy_b64) - fields.append({"name": "signature", "value": signature}) - fields.append({"name": "key", "value": key}) - - # HTTPS protocol will be used if the secure HTTP option is enabled. - url = '%s://%s/' % (http_method, - self.calling_format.build_host(self.server_name(), - bucket_name)) - - return {"action": url, "fields": fields} - - def generate_url_sigv4(self, expires_in, method, bucket='', key='', - headers=None, force_http=False, - response_headers=None, version_id=None, - iso_date=None): - path = self.calling_format.build_path_base(bucket, key) - auth_path = self.calling_format.build_auth_path(bucket, key) - host = self.calling_format.build_host(self.server_name(), bucket) - - # For presigned URLs we should ignore the port if it's HTTPS - if host.endswith(':443'): - host = host[:-4] - - params = {} - if version_id is not None: - params['VersionId'] = version_id - - http_request = self.build_base_http_request(method, path, auth_path, - headers=headers, host=host, - params=params) - - return self._auth_handler.presign(http_request, expires_in, - iso_date=iso_date) - - def generate_url(self, expires_in, method, bucket='', key='', headers=None, - query_auth=True, force_http=False, response_headers=None, - expires_in_absolute=False, version_id=None): - if self._auth_handler.capability[0] == 'hmac-v4-s3': - # Handle the special sigv4 case - return self.generate_url_sigv4(expires_in, method, bucket=bucket, - key=key, headers=headers, force_http=force_http, - response_headers=response_headers, version_id=version_id) - - headers = headers or {} - if expires_in_absolute: - expires = int(expires_in) - else: - expires = int(time.time() + expires_in) - auth_path = self.calling_format.build_auth_path(bucket, key) - auth_path = self.get_path(auth_path) - # optional version_id and response_headers need to be added to - # the query param list. - extra_qp = [] - if version_id is not None: - extra_qp.append("versionId=%s" % version_id) - if response_headers: - for k, v in response_headers.items(): - extra_qp.append("%s=%s" % (k, urllib.parse.quote(v))) - if self.provider.security_token: - headers['x-amz-security-token'] = self.provider.security_token - if extra_qp: - delimiter = '?' if '?' not in auth_path else '&' - auth_path += delimiter + '&'.join(extra_qp) - c_string = boto.utils.canonical_string(method, auth_path, headers, - expires, self.provider) - b64_hmac = self._auth_handler.sign_string(c_string) - encoded_canonical = urllib.parse.quote(b64_hmac, safe='') - self.calling_format.build_path_base(bucket, key) - if query_auth: - query_part = '?' + self.QueryString % (encoded_canonical, expires, - self.aws_access_key_id) - else: - query_part = '' - if headers: - hdr_prefix = self.provider.header_prefix - for k, v in headers.items(): - if k.startswith(hdr_prefix): - # headers used for sig generation must be - # included in the url also. - extra_qp.append("%s=%s" % (k, urllib.parse.quote(v))) - if extra_qp: - delimiter = '?' if not query_part else '&' - query_part += delimiter + '&'.join(extra_qp) - if force_http: - protocol = 'http' - port = 80 - else: - protocol = self.protocol - port = self.port - return self.calling_format.build_url_base(self, protocol, - self.server_name(port), - bucket, key) + query_part - - def get_all_buckets(self, headers=None): - response = self.make_request('GET', headers=headers) - body = response.read() - if response.status > 300: - raise self.provider.storage_response_error( - response.status, response.reason, body) - rs = ResultSet([('Bucket', self.bucket_class)]) - h = handler.XmlHandler(rs, self) - if not isinstance(body, bytes): - body = body.encode('utf-8') - xml.sax.parseString(body, h) - return rs - - def get_canonical_user_id(self, headers=None): - """ - Convenience method that returns the "CanonicalUserID" of the - user who's credentials are associated with the connection. - The only way to get this value is to do a GET request on the - service which returns all buckets associated with the account. - As part of that response, the canonical userid is returned. - This method simply does all of that and then returns just the - user id. - - :rtype: string - :return: A string containing the canonical user id. - """ - rs = self.get_all_buckets(headers=headers) - return rs.owner.id - - def get_bucket(self, bucket_name, validate=True, headers=None): - """ - Retrieves a bucket by name. - - If the bucket does not exist, an ``S3ResponseError`` will be raised. If - you are unsure if the bucket exists or not, you can use the - ``S3Connection.lookup`` method, which will either return a valid bucket - or ``None``. - - If ``validate=False`` is passed, no request is made to the service (no - charge/communication delay). This is only safe to do if you are **sure** - the bucket exists. - - If the default ``validate=True`` is passed, a request is made to the - service to ensure the bucket exists. Prior to Boto v2.25.0, this fetched - a list of keys (but with a max limit set to ``0``, always returning an empty - list) in the bucket (& included better error messages), at an - increased expense. As of Boto v2.25.0, this now performs a HEAD request - (less expensive but worse error messages). - - If you were relying on parsing the error message before, you should call - something like:: - - bucket = conn.get_bucket('<bucket_name>', validate=False) - bucket.get_all_keys(maxkeys=0) - - :type bucket_name: string - :param bucket_name: The name of the bucket - - :type headers: dict - :param headers: Additional headers to pass along with the request to - AWS. - - :type validate: boolean - :param validate: If ``True``, it will try to verify the bucket exists - on the service-side. (Default: ``True``) - """ - if validate: - return self.head_bucket(bucket_name, headers=headers) - else: - return self.bucket_class(self, bucket_name) - - def head_bucket(self, bucket_name, headers=None): - """ - Determines if a bucket exists by name. - - If the bucket does not exist, an ``S3ResponseError`` will be raised. - - :type bucket_name: string - :param bucket_name: The name of the bucket - - :type headers: dict - :param headers: Additional headers to pass along with the request to - AWS. - - :returns: A <Bucket> object - """ - response = self.make_request('HEAD', bucket_name, headers=headers) - body = response.read() - if response.status == 200: - return self.bucket_class(self, bucket_name) - elif response.status == 403: - # For backward-compatibility, we'll populate part of the exception - # with the most-common default. - err = self.provider.storage_response_error( - response.status, - response.reason, - body - ) - err.error_code = 'AccessDenied' - err.error_message = 'Access Denied' - raise err - elif response.status == 404: - # For backward-compatibility, we'll populate part of the exception - # with the most-common default. - err = self.provider.storage_response_error( - response.status, - response.reason, - body - ) - err.error_code = 'NoSuchBucket' - err.error_message = 'The specified bucket does not exist' - raise err - else: - raise self.provider.storage_response_error( - response.status, response.reason, body) - - def lookup(self, bucket_name, validate=True, headers=None): - """ - Attempts to get a bucket from S3. - - Works identically to ``S3Connection.get_bucket``, save for that it - will return ``None`` if the bucket does not exist instead of throwing - an exception. - - :type bucket_name: string - :param bucket_name: The name of the bucket - - :type headers: dict - :param headers: Additional headers to pass along with the request to - AWS. - - :type validate: boolean - :param validate: If ``True``, it will try to fetch all keys within the - given bucket. (Default: ``True``) - """ - try: - bucket = self.get_bucket(bucket_name, validate, headers=headers) - except: - bucket = None - return bucket - - def create_bucket(self, bucket_name, headers=None, - location=Location.DEFAULT, policy=None): - """ - Creates a new located bucket. By default it's in the USA. You can pass - Location.EU to create a European bucket (S3) or European Union bucket - (GCS). - - :type bucket_name: string - :param bucket_name: The name of the new bucket - - :type headers: dict - :param headers: Additional headers to pass along with the request to AWS. - - :type location: str - :param location: The location of the new bucket. You can use one of the - constants in :class:`boto.s3.connection.Location` (e.g. Location.EU, - Location.USWest, etc.). - - :type policy: :class:`boto.s3.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the - new key in S3. - - """ - check_lowercase_bucketname(bucket_name) - - if policy: - if headers: - headers[self.provider.acl_header] = policy - else: - headers = {self.provider.acl_header: policy} - if location == Location.DEFAULT: - data = '' - else: - data = '<CreateBucketConfiguration><LocationConstraint>' + \ - location + '</LocationConstraint></CreateBucketConfiguration>' - response = self.make_request('PUT', bucket_name, headers=headers, - data=data) - body = response.read() - if response.status == 409: - raise self.provider.storage_create_error( - response.status, response.reason, body) - if response.status == 200: - return self.bucket_class(self, bucket_name) - else: - raise self.provider.storage_response_error( - response.status, response.reason, body) - - def delete_bucket(self, bucket, headers=None): - """ - Removes an S3 bucket. - - In order to remove the bucket, it must first be empty. If the bucket is - not empty, an ``S3ResponseError`` will be raised. - - :type bucket_name: string - :param bucket_name: The name of the bucket - - :type headers: dict - :param headers: Additional headers to pass along with the request to - AWS. - """ - response = self.make_request('DELETE', bucket, headers=headers) - body = response.read() - if response.status != 204: - raise self.provider.storage_response_error( - response.status, response.reason, body) - - def make_request(self, method, bucket='', key='', headers=None, data='', - query_args=None, sender=None, override_num_retries=None, - retry_handler=None): - if isinstance(bucket, self.bucket_class): - bucket = bucket.name - if isinstance(key, Key): - key = key.name - path = self.calling_format.build_path_base(bucket, key) - boto.log.debug('path=%s' % path) - auth_path = self.calling_format.build_auth_path(bucket, key) - boto.log.debug('auth_path=%s' % auth_path) - host = self.calling_format.build_host(self.server_name(), bucket) - if query_args: - path += '?' + query_args - boto.log.debug('path=%s' % path) - auth_path += '?' + query_args - boto.log.debug('auth_path=%s' % auth_path) - return super(S3Connection, self).make_request( - method, path, headers, - data, host, auth_path, sender, - override_num_retries=override_num_retries, - retry_handler=retry_handler - ) diff --git a/awx/lib/site-packages/boto/s3/cors.py b/awx/lib/site-packages/boto/s3/cors.py deleted file mode 100644 index d97ee890aa..0000000000 --- a/awx/lib/site-packages/boto/s3/cors.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - -class CORSRule(object): - """ - CORS rule for a bucket. - - :ivar id: A unique identifier for the rule. The ID value can be - up to 255 characters long. The IDs help you find a rule in - the configuration. - - :ivar allowed_methods: An HTTP method that you want to allow the - origin to execute. Each CORSRule must identify at least one - origin and one method. Valid values are: - GET|PUT|HEAD|POST|DELETE - - :ivar allowed_origin: An origin that you want to allow cross-domain - requests from. This can contain at most one * wild character. - Each CORSRule must identify at least one origin and one method. - The origin value can include at most one '*' wild character. - For example, "http://*.example.com". You can also specify - only * as the origin value allowing all origins cross-domain access. - - :ivar allowed_header: Specifies which headers are allowed in a - pre-flight OPTIONS request via the - Access-Control-Request-Headers header. Each header name - specified in the Access-Control-Request-Headers header must - have a corresponding entry in the rule. Amazon S3 will send - only the allowed headers in a response that were requested. - This can contain at most one * wild character. - - :ivar max_age_seconds: The time in seconds that your browser is to - cache the preflight response for the specified resource. - - :ivar expose_header: One or more headers in the response that you - want customers to be able to access from their applications - (for example, from a JavaScript XMLHttpRequest object). You - add one ExposeHeader element in the rule for each header. - """ - - def __init__(self, allowed_method=None, allowed_origin=None, - id=None, allowed_header=None, max_age_seconds=None, - expose_header=None): - if allowed_method is None: - allowed_method = [] - self.allowed_method = allowed_method - if allowed_origin is None: - allowed_origin = [] - self.allowed_origin = allowed_origin - self.id = id - if allowed_header is None: - allowed_header = [] - self.allowed_header = allowed_header - self.max_age_seconds = max_age_seconds - if expose_header is None: - expose_header = [] - self.expose_header = expose_header - - def __repr__(self): - return '<Rule: %s>' % self.id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'ID': - self.id = value - elif name == 'AllowedMethod': - self.allowed_method.append(value) - elif name == 'AllowedOrigin': - self.allowed_origin.append(value) - elif name == 'AllowedHeader': - self.allowed_header.append(value) - elif name == 'MaxAgeSeconds': - self.max_age_seconds = int(value) - elif name == 'ExposeHeader': - self.expose_header.append(value) - else: - setattr(self, name, value) - - def to_xml(self): - s = '<CORSRule>' - for allowed_method in self.allowed_method: - s += '<AllowedMethod>%s</AllowedMethod>' % allowed_method - for allowed_origin in self.allowed_origin: - s += '<AllowedOrigin>%s</AllowedOrigin>' % allowed_origin - for allowed_header in self.allowed_header: - s += '<AllowedHeader>%s</AllowedHeader>' % allowed_header - for expose_header in self.expose_header: - s += '<ExposeHeader>%s</ExposeHeader>' % expose_header - if self.max_age_seconds: - s += '<MaxAgeSeconds>%d</MaxAgeSeconds>' % self.max_age_seconds - if self.id: - s += '<ID>%s</ID>' % self.id - s += '</CORSRule>' - return s - - -class CORSConfiguration(list): - """ - A container for the rules associated with a CORS configuration. - """ - - def startElement(self, name, attrs, connection): - if name == 'CORSRule': - rule = CORSRule() - self.append(rule) - return rule - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - def to_xml(self): - """ - Returns a string containing the XML version of the Lifecycle - configuration as defined by S3. - """ - s = '<CORSConfiguration>' - for rule in self: - s += rule.to_xml() - s += '</CORSConfiguration>' - return s - - def add_rule(self, allowed_method, allowed_origin, - id=None, allowed_header=None, max_age_seconds=None, - expose_header=None): - """ - Add a rule to this CORS configuration. This only adds - the rule to the local copy. To install the new rule(s) on - the bucket, you need to pass this CORS config object - to the set_cors method of the Bucket object. - - :type allowed_methods: list of str - :param allowed_methods: An HTTP method that you want to allow the - origin to execute. Each CORSRule must identify at least one - origin and one method. Valid values are: - GET|PUT|HEAD|POST|DELETE - - :type allowed_origin: list of str - :param allowed_origin: An origin that you want to allow cross-domain - requests from. This can contain at most one * wild character. - Each CORSRule must identify at least one origin and one method. - The origin value can include at most one '*' wild character. - For example, "http://*.example.com". You can also specify - only * as the origin value allowing all origins - cross-domain access. - - :type id: str - :param id: A unique identifier for the rule. The ID value can be - up to 255 characters long. The IDs help you find a rule in - the configuration. - - :type allowed_header: list of str - :param allowed_header: Specifies which headers are allowed in a - pre-flight OPTIONS request via the - Access-Control-Request-Headers header. Each header name - specified in the Access-Control-Request-Headers header must - have a corresponding entry in the rule. Amazon S3 will send - only the allowed headers in a response that were requested. - This can contain at most one * wild character. - - :type max_age_seconds: int - :param max_age_seconds: The time in seconds that your browser is to - cache the preflight response for the specified resource. - - :type expose_header: list of str - :param expose_header: One or more headers in the response that you - want customers to be able to access from their applications - (for example, from a JavaScript XMLHttpRequest object). You - add one ExposeHeader element in the rule for each header. - """ - if not isinstance(allowed_method, (list, tuple)): - allowed_method = [allowed_method] - if not isinstance(allowed_origin, (list, tuple)): - allowed_origin = [allowed_origin] - if not isinstance(allowed_origin, (list, tuple)): - if allowed_origin is None: - allowed_origin = [] - else: - allowed_origin = [allowed_origin] - if not isinstance(expose_header, (list, tuple)): - if expose_header is None: - expose_header = [] - else: - expose_header = [expose_header] - rule = CORSRule(allowed_method, allowed_origin, id, allowed_header, - max_age_seconds, expose_header) - self.append(rule) diff --git a/awx/lib/site-packages/boto/s3/deletemarker.py b/awx/lib/site-packages/boto/s3/deletemarker.py deleted file mode 100644 index d8e7cc8b58..0000000000 --- a/awx/lib/site-packages/boto/s3/deletemarker.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.s3.user import User - -class DeleteMarker(object): - def __init__(self, bucket=None, name=None): - self.bucket = bucket - self.name = name - self.version_id = None - self.is_latest = False - self.last_modified = None - self.owner = None - - def startElement(self, name, attrs, connection): - if name == 'Owner': - self.owner = User(self) - return self.owner - else: - return None - - def endElement(self, name, value, connection): - if name == 'Key': - self.name = value - elif name == 'IsLatest': - if value == 'true': - self.is_latest = True - else: - self.is_latest = False - elif name == 'LastModified': - self.last_modified = value - elif name == 'Owner': - pass - elif name == 'VersionId': - self.version_id = value - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/s3/key.py b/awx/lib/site-packages/boto/s3/key.py deleted file mode 100644 index bc490e30d8..0000000000 --- a/awx/lib/site-packages/boto/s3/key.py +++ /dev/null @@ -1,1919 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011, Nexenta Systems Inc. -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import email.utils -import errno -import hashlib -import mimetypes -import os -import re -import base64 -import binascii -import math -from hashlib import md5 -import boto.utils -from boto.compat import BytesIO, six, urllib, encodebytes - -from boto.exception import BotoClientError -from boto.exception import StorageDataError -from boto.exception import PleaseRetryException -from boto.provider import Provider -from boto.s3.keyfile import KeyFile -from boto.s3.user import User -from boto import UserAgent -from boto.utils import compute_md5, compute_hash -from boto.utils import find_matching_headers -from boto.utils import merge_headers_by_name - - -class Key(object): - """ - Represents a key (object) in an S3 bucket. - - :ivar bucket: The parent :class:`boto.s3.bucket.Bucket`. - :ivar name: The name of this Key object. - :ivar metadata: A dictionary containing user metadata that you - wish to store with the object or that has been retrieved from - an existing object. - :ivar cache_control: The value of the `Cache-Control` HTTP header. - :ivar content_type: The value of the `Content-Type` HTTP header. - :ivar content_encoding: The value of the `Content-Encoding` HTTP header. - :ivar content_disposition: The value of the `Content-Disposition` HTTP - header. - :ivar content_language: The value of the `Content-Language` HTTP header. - :ivar etag: The `etag` associated with this object. - :ivar last_modified: The string timestamp representing the last - time this object was modified in S3. - :ivar owner: The ID of the owner of this object. - :ivar storage_class: The storage class of the object. Currently, one of: - STANDARD | REDUCED_REDUNDANCY | GLACIER - :ivar md5: The MD5 hash of the contents of the object. - :ivar size: The size, in bytes, of the object. - :ivar version_id: The version ID of this object, if it is a versioned - object. - :ivar encrypted: Whether the object is encrypted while at rest on - the server. - """ - - DefaultContentType = 'application/octet-stream' - - RestoreBody = """<?xml version="1.0" encoding="UTF-8"?> - <RestoreRequest xmlns="http://s3.amazonaws.com/doc/2006-03-01"> - <Days>%s</Days> - </RestoreRequest>""" - - - BufferSize = boto.config.getint('Boto', 'key_buffer_size', 8192) - - # The object metadata fields a user can set, other than custom metadata - # fields (i.e., those beginning with a provider-specific prefix like - # x-amz-meta). - base_user_settable_fields = set(["cache-control", "content-disposition", - "content-encoding", "content-language", - "content-md5", "content-type", - "x-robots-tag", "expires"]) - _underscore_base_user_settable_fields = set() - for f in base_user_settable_fields: - _underscore_base_user_settable_fields.add(f.replace('-', '_')) - # Metadata fields, whether user-settable or not, other than custom - # metadata fields (i.e., those beginning with a provider specific prefix - # like x-amz-meta). - base_fields = (base_user_settable_fields | - set(["last-modified", "content-length", "date", "etag"])) - - - - def __init__(self, bucket=None, name=None): - self.bucket = bucket - self.name = name - self.metadata = {} - self.cache_control = None - self.content_type = self.DefaultContentType - self.content_encoding = None - self.content_disposition = None - self.content_language = None - self.filename = None - self.etag = None - self.is_latest = False - self.last_modified = None - self.owner = None - self._storage_class = None - self.path = None - self.resp = None - self.mode = None - self.size = None - self.version_id = None - self.source_version_id = None - self.delete_marker = False - self.encrypted = None - # If the object is being restored, this attribute will be set to True. - # If the object is restored, it will be set to False. Otherwise this - # value will be None. If the restore is completed (ongoing_restore = - # False), the expiry_date will be populated with the expiry date of the - # restored object. - self.ongoing_restore = None - self.expiry_date = None - self.local_hashes = {} - - def __repr__(self): - if self.bucket: - name = u'<Key: %s,%s>' % (self.bucket.name, self.name) - else: - name = u'<Key: None,%s>' % self.name - - # Encode to bytes for Python 2 to prevent display decoding issues - if not isinstance(name, str): - name = name.encode('utf-8') - - return name - - def __iter__(self): - return self - - @property - def provider(self): - provider = None - if self.bucket and self.bucket.connection: - provider = self.bucket.connection.provider - return provider - - def _get_key(self): - return self.name - - def _set_key(self, value): - self.name = value - - key = property(_get_key, _set_key); - - def _get_md5(self): - if 'md5' in self.local_hashes and self.local_hashes['md5']: - return binascii.b2a_hex(self.local_hashes['md5']) - - def _set_md5(self, value): - if value: - self.local_hashes['md5'] = binascii.a2b_hex(value) - elif 'md5' in self.local_hashes: - self.local_hashes.pop('md5', None) - - md5 = property(_get_md5, _set_md5); - - def _get_base64md5(self): - if 'md5' in self.local_hashes and self.local_hashes['md5']: - md5 = self.local_hashes['md5'] - if not isinstance(md5, bytes): - md5 = md5.encode('utf-8') - return binascii.b2a_base64(md5).decode('utf-8').rstrip('\n') - - def _set_base64md5(self, value): - if value: - if not isinstance(value, six.string_types): - value = value.decode('utf-8') - self.local_hashes['md5'] = binascii.a2b_base64(value) - elif 'md5' in self.local_hashes: - del self.local_hashes['md5'] - - base64md5 = property(_get_base64md5, _set_base64md5); - - def _get_storage_class(self): - if self._storage_class is None and self.bucket: - # Attempt to fetch storage class - list_items = list(self.bucket.list(self.name.encode('utf-8'))) - if len(list_items) and getattr(list_items[0], '_storage_class', - None): - self._storage_class = list_items[0]._storage_class - else: - # Key is not yet saved? Just use default... - self._storage_class = 'STANDARD' - - return self._storage_class - - def _set_storage_class(self, value): - self._storage_class = value - - storage_class = property(_get_storage_class, _set_storage_class) - - def get_md5_from_hexdigest(self, md5_hexdigest): - """ - A utility function to create the 2-tuple (md5hexdigest, base64md5) - from just having a precalculated md5_hexdigest. - """ - digest = binascii.unhexlify(md5_hexdigest) - base64md5 = encodebytes(digest) - if base64md5[-1] == '\n': - base64md5 = base64md5[0:-1] - return (md5_hexdigest, base64md5) - - def handle_encryption_headers(self, resp): - provider = self.bucket.connection.provider - if provider.server_side_encryption_header: - self.encrypted = resp.getheader( - provider.server_side_encryption_header, None) - else: - self.encrypted = None - - def handle_version_headers(self, resp, force=False): - provider = self.bucket.connection.provider - # If the Key object already has a version_id attribute value, it - # means that it represents an explicit version and the user is - # doing a get_contents_*(version_id=<foo>) to retrieve another - # version of the Key. In that case, we don't really want to - # overwrite the version_id in this Key object. Comprende? - if self.version_id is None or force: - self.version_id = resp.getheader(provider.version_id, None) - self.source_version_id = resp.getheader(provider.copy_source_version_id, - None) - if resp.getheader(provider.delete_marker, 'false') == 'true': - self.delete_marker = True - else: - self.delete_marker = False - - def handle_restore_headers(self, response): - provider = self.bucket.connection.provider - header = response.getheader(provider.restore_header) - if header is None: - return - parts = header.split(',', 1) - for part in parts: - key, val = [i.strip() for i in part.split('=')] - val = val.replace('"', '') - if key == 'ongoing-request': - self.ongoing_restore = True if val.lower() == 'true' else False - elif key == 'expiry-date': - self.expiry_date = val - - def handle_addl_headers(self, headers): - """ - Used by Key subclasses to do additional, provider-specific - processing of response headers. No-op for this base class. - """ - pass - - def open_read(self, headers=None, query_args='', - override_num_retries=None, response_headers=None): - """ - Open this key for reading - - :type headers: dict - :param headers: Headers to pass in the web request - - :type query_args: string - :param query_args: Arguments to pass in the query string - (ie, 'torrent') - - :type override_num_retries: int - :param override_num_retries: If not None will override configured - num_retries parameter for underlying GET. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - """ - if self.resp is None: - self.mode = 'r' - - provider = self.bucket.connection.provider - self.resp = self.bucket.connection.make_request( - 'GET', self.bucket.name, self.name, headers, - query_args=query_args, - override_num_retries=override_num_retries) - if self.resp.status < 199 or self.resp.status > 299: - body = self.resp.read() - raise provider.storage_response_error(self.resp.status, - self.resp.reason, body) - response_headers = self.resp.msg - self.metadata = boto.utils.get_aws_metadata(response_headers, - provider) - for name, value in response_headers.items(): - # To get correct size for Range GETs, use Content-Range - # header if one was returned. If not, use Content-Length - # header. - if (name.lower() == 'content-length' and - 'Content-Range' not in response_headers): - self.size = int(value) - elif name.lower() == 'content-range': - end_range = re.sub('.*/(.*)', '\\1', value) - self.size = int(end_range) - elif name.lower() in Key.base_fields: - self.__dict__[name.lower().replace('-', '_')] = value - self.handle_version_headers(self.resp) - self.handle_encryption_headers(self.resp) - self.handle_restore_headers(self.resp) - self.handle_addl_headers(self.resp.getheaders()) - - def open_write(self, headers=None, override_num_retries=None): - """ - Open this key for writing. - Not yet implemented - - :type headers: dict - :param headers: Headers to pass in the write request - - :type override_num_retries: int - :param override_num_retries: If not None will override configured - num_retries parameter for underlying PUT. - """ - raise BotoClientError('Not Implemented') - - def open(self, mode='r', headers=None, query_args=None, - override_num_retries=None): - if mode == 'r': - self.mode = 'r' - self.open_read(headers=headers, query_args=query_args, - override_num_retries=override_num_retries) - elif mode == 'w': - self.mode = 'w' - self.open_write(headers=headers, - override_num_retries=override_num_retries) - else: - raise BotoClientError('Invalid mode: %s' % mode) - - closed = False - - def close(self, fast=False): - """ - Close this key. - - :type fast: bool - :param fast: True if you want the connection to be closed without first - reading the content. This should only be used in cases where subsequent - calls don't need to return the content from the open HTTP connection. - Note: As explained at - http://docs.python.org/2/library/httplib.html#httplib.HTTPConnection.getresponse, - callers must read the whole response before sending a new request to the - server. Calling Key.close(fast=True) and making a subsequent request to - the server will work because boto will get an httplib exception and - close/reopen the connection. - - """ - if self.resp and not fast: - self.resp.read() - self.resp = None - self.mode = None - self.closed = True - - def next(self): - """ - By providing a next method, the key object supports use as an iterator. - For example, you can now say: - - for bytes in key: - write bytes to a file or whatever - - All of the HTTP connection stuff is handled for you. - """ - self.open_read() - data = self.resp.read(self.BufferSize) - if not data: - self.close() - raise StopIteration - return data - - # Python 3 iterator support - __next__ = next - - def read(self, size=0): - self.open_read() - if size == 0: - data = self.resp.read() - else: - data = self.resp.read(size) - if not data: - self.close() - return data - - def change_storage_class(self, new_storage_class, dst_bucket=None, - validate_dst_bucket=True): - """ - Change the storage class of an existing key. - Depending on whether a different destination bucket is supplied - or not, this will either move the item within the bucket, preserving - all metadata and ACL info bucket changing the storage class or it - will copy the item to the provided destination bucket, also - preserving metadata and ACL info. - - :type new_storage_class: string - :param new_storage_class: The new storage class for the Key. - Possible values are: - * STANDARD - * REDUCED_REDUNDANCY - - :type dst_bucket: string - :param dst_bucket: The name of a destination bucket. If not - provided the current bucket of the key will be used. - - :type validate_dst_bucket: bool - :param validate_dst_bucket: If True, will validate the dst_bucket - by using an extra list request. - """ - if new_storage_class == 'STANDARD': - return self.copy(self.bucket.name, self.name, - reduced_redundancy=False, preserve_acl=True, - validate_dst_bucket=validate_dst_bucket) - elif new_storage_class == 'REDUCED_REDUNDANCY': - return self.copy(self.bucket.name, self.name, - reduced_redundancy=True, preserve_acl=True, - validate_dst_bucket=validate_dst_bucket) - else: - raise BotoClientError('Invalid storage class: %s' % - new_storage_class) - - def copy(self, dst_bucket, dst_key, metadata=None, - reduced_redundancy=False, preserve_acl=False, - encrypt_key=False, validate_dst_bucket=True): - """ - Copy this Key to another bucket. - - :type dst_bucket: string - :param dst_bucket: The name of the destination bucket - - :type dst_key: string - :param dst_key: The name of the destination key - - :type metadata: dict - :param metadata: Metadata to be associated with new key. If - metadata is supplied, it will replace the metadata of the - source key being copied. If no metadata is supplied, the - source key's metadata will be copied to the new key. - - :type reduced_redundancy: bool - :param reduced_redundancy: If True, this will force the - storage class of the new Key to be REDUCED_REDUNDANCY - regardless of the storage class of the key being copied. - The Reduced Redundancy Storage (RRS) feature of S3, - provides lower redundancy at lower storage cost. - - :type preserve_acl: bool - :param preserve_acl: If True, the ACL from the source key will - be copied to the destination key. If False, the - destination key will have the default ACL. Note that - preserving the ACL in the new key object will require two - additional API calls to S3, one to retrieve the current - ACL and one to set that ACL on the new object. If you - don't care about the ACL, a value of False will be - significantly more efficient. - - :type encrypt_key: bool - :param encrypt_key: If True, the new copy of the object will - be encrypted on the server-side by S3 and will be stored - in an encrypted form while at rest in S3. - - :type validate_dst_bucket: bool - :param validate_dst_bucket: If True, will validate the dst_bucket - by using an extra list request. - - :rtype: :class:`boto.s3.key.Key` or subclass - :returns: An instance of the newly created key object - """ - dst_bucket = self.bucket.connection.lookup(dst_bucket, - validate_dst_bucket) - if reduced_redundancy: - storage_class = 'REDUCED_REDUNDANCY' - else: - storage_class = self.storage_class - return dst_bucket.copy_key(dst_key, self.bucket.name, - self.name, metadata, - storage_class=storage_class, - preserve_acl=preserve_acl, - encrypt_key=encrypt_key) - - def startElement(self, name, attrs, connection): - if name == 'Owner': - self.owner = User(self) - return self.owner - else: - return None - - def endElement(self, name, value, connection): - if name == 'Key': - self.name = value - elif name == 'ETag': - self.etag = value - elif name == 'IsLatest': - if value == 'true': - self.is_latest = True - else: - self.is_latest = False - elif name == 'LastModified': - self.last_modified = value - elif name == 'Size': - self.size = int(value) - elif name == 'StorageClass': - self.storage_class = value - elif name == 'Owner': - pass - elif name == 'VersionId': - self.version_id = value - else: - setattr(self, name, value) - - def exists(self, headers=None): - """ - Returns True if the key exists - - :rtype: bool - :return: Whether the key exists on S3 - """ - return bool(self.bucket.lookup(self.name, headers=headers)) - - def delete(self, headers=None): - """ - Delete this key from S3 - """ - return self.bucket.delete_key(self.name, version_id=self.version_id, - headers=headers) - - def get_metadata(self, name): - return self.metadata.get(name) - - def set_metadata(self, name, value): - # Ensure that metadata that is vital to signing is in the correct - # case. Applies to ``Content-Type`` & ``Content-MD5``. - if name.lower() == 'content-type': - self.metadata['Content-Type'] = value - elif name.lower() == 'content-md5': - self.metadata['Content-MD5'] = value - else: - self.metadata[name] = value - if name.lower() in Key.base_user_settable_fields: - self.__dict__[name.lower().replace('-', '_')] = value - - def update_metadata(self, d): - self.metadata.update(d) - - # convenience methods for setting/getting ACL - def set_acl(self, acl_str, headers=None): - if self.bucket is not None: - self.bucket.set_acl(acl_str, self.name, headers=headers) - - def get_acl(self, headers=None): - if self.bucket is not None: - return self.bucket.get_acl(self.name, headers=headers) - - def get_xml_acl(self, headers=None): - if self.bucket is not None: - return self.bucket.get_xml_acl(self.name, headers=headers) - - def set_xml_acl(self, acl_str, headers=None): - if self.bucket is not None: - return self.bucket.set_xml_acl(acl_str, self.name, headers=headers) - - def set_canned_acl(self, acl_str, headers=None): - return self.bucket.set_canned_acl(acl_str, self.name, headers) - - def get_redirect(self): - """Return the redirect location configured for this key. - - If no redirect is configured (via set_redirect), then None - will be returned. - - """ - response = self.bucket.connection.make_request( - 'HEAD', self.bucket.name, self.name) - if response.status == 200: - return response.getheader('x-amz-website-redirect-location') - else: - raise self.provider.storage_response_error( - response.status, response.reason, response.read()) - - def set_redirect(self, redirect_location, headers=None): - """Configure this key to redirect to another location. - - When the bucket associated with this key is accessed from the website - endpoint, a 301 redirect will be issued to the specified - `redirect_location`. - - :type redirect_location: string - :param redirect_location: The location to redirect. - - """ - if headers is None: - headers = {} - else: - headers = headers.copy() - - headers['x-amz-website-redirect-location'] = redirect_location - response = self.bucket.connection.make_request('PUT', self.bucket.name, - self.name, headers) - if response.status == 200: - return True - else: - raise self.provider.storage_response_error( - response.status, response.reason, response.read()) - - def make_public(self, headers=None): - return self.bucket.set_canned_acl('public-read', self.name, headers) - - def generate_url(self, expires_in, method='GET', headers=None, - query_auth=True, force_http=False, response_headers=None, - expires_in_absolute=False, version_id=None, - policy=None, reduced_redundancy=False, encrypt_key=False): - """ - Generate a URL to access this key. - - :type expires_in: int - :param expires_in: How long the url is valid for, in seconds - - :type method: string - :param method: The method to use for retrieving the file - (default is GET) - - :type headers: dict - :param headers: Any headers to pass along in the request - - :type query_auth: bool - :param query_auth: - - :type force_http: bool - :param force_http: If True, http will be used instead of https. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - - :type expires_in_absolute: bool - :param expires_in_absolute: - - :type version_id: string - :param version_id: The version_id of the object to GET. If specified - this overrides any value in the key. - - :type policy: :class:`boto.s3.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the - new key in S3. - - :type reduced_redundancy: bool - :param reduced_redundancy: If True, this will set the storage - class of the new Key to be REDUCED_REDUNDANCY. The Reduced - Redundancy Storage (RRS) feature of S3, provides lower - redundancy at lower storage cost. - - :type encrypt_key: bool - :param encrypt_key: If True, the new copy of the object will - be encrypted on the server-side by S3 and will be stored - in an encrypted form while at rest in S3. - - :rtype: string - :return: The URL to access the key - """ - provider = self.bucket.connection.provider - version_id = version_id or self.version_id - if headers is None: - headers = {} - else: - headers = headers.copy() - - # add headers accordingly (usually PUT case) - if policy: - headers[provider.acl_header] = policy - if reduced_redundancy: - self.storage_class = 'REDUCED_REDUNDANCY' - if provider.storage_class_header: - headers[provider.storage_class_header] = self.storage_class - if encrypt_key: - headers[provider.server_side_encryption_header] = 'AES256' - headers = boto.utils.merge_meta(headers, self.metadata, provider) - - return self.bucket.connection.generate_url(expires_in, method, - self.bucket.name, self.name, - headers, query_auth, - force_http, - response_headers, - expires_in_absolute, - version_id) - - def send_file(self, fp, headers=None, cb=None, num_cb=10, - query_args=None, chunked_transfer=False, size=None): - """ - Upload a file to a key into a bucket on S3. - - :type fp: file - :param fp: The file pointer to upload. The file pointer must - point point at the offset from which you wish to upload. - ie. if uploading the full file, it should point at the - start of the file. Normally when a file is opened for - reading, the fp will point at the first byte. See the - bytes parameter below for more info. - - :type headers: dict - :param headers: The headers to pass along with the PUT request - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file - transfer. Providing a negative integer will cause your - callback to be called with each buffer read. - - :type query_args: string - :param query_args: (optional) Arguments to pass in the query string. - - :type chunked_transfer: boolean - :param chunked_transfer: (optional) If true, we use chunked - Transfer-Encoding. - - :type size: int - :param size: (optional) The Maximum number of bytes to read - from the file pointer (fp). This is useful when uploading - a file in multiple parts where you are splitting the file - up into different ranges to be uploaded. If not specified, - the default behaviour is to read all bytes from the file - pointer. Less bytes may be available. - """ - self._send_file_internal(fp, headers=headers, cb=cb, num_cb=num_cb, - query_args=query_args, - chunked_transfer=chunked_transfer, size=size) - - def _send_file_internal(self, fp, headers=None, cb=None, num_cb=10, - query_args=None, chunked_transfer=False, size=None, - hash_algs=None): - provider = self.bucket.connection.provider - try: - spos = fp.tell() - except IOError: - spos = None - self.read_from_stream = False - - # If hash_algs is unset and the MD5 hasn't already been computed, - # default to an MD5 hash_alg to hash the data on-the-fly. - if hash_algs is None and not self.md5: - hash_algs = {'md5': md5} - digesters = dict((alg, hash_algs[alg]()) for alg in hash_algs or {}) - - def sender(http_conn, method, path, data, headers): - # This function is called repeatedly for temporary retries - # so we must be sure the file pointer is pointing at the - # start of the data. - if spos is not None and spos != fp.tell(): - fp.seek(spos) - elif spos is None and self.read_from_stream: - # if seek is not supported, and we've read from this - # stream already, then we need to abort retries to - # avoid setting bad data. - raise provider.storage_data_error( - 'Cannot retry failed request. fp does not support seeking.') - - # If the caller explicitly specified host header, tell putrequest - # not to add a second host header. Similarly for accept-encoding. - skips = {} - if boto.utils.find_matching_headers('host', headers): - skips['skip_host'] = 1 - if boto.utils.find_matching_headers('accept-encoding', headers): - skips['skip_accept_encoding'] = 1 - http_conn.putrequest(method, path, **skips) - for key in headers: - http_conn.putheader(key, headers[key]) - http_conn.endheaders() - - save_debug = self.bucket.connection.debug - self.bucket.connection.debug = 0 - # If the debuglevel < 4 we don't want to show connection - # payload, so turn off HTTP connection-level debug output (to - # be restored below). - # Use the getattr approach to allow this to work in AppEngine. - if getattr(http_conn, 'debuglevel', 0) < 4: - http_conn.set_debuglevel(0) - - data_len = 0 - if cb: - if size: - cb_size = size - elif self.size: - cb_size = self.size - else: - cb_size = 0 - if chunked_transfer and cb_size == 0: - # For chunked Transfer, we call the cb for every 1MB - # of data transferred, except when we know size. - cb_count = (1024 * 1024) / self.BufferSize - elif num_cb > 1: - cb_count = int( - math.ceil(cb_size / self.BufferSize / (num_cb - 1.0))) - elif num_cb < 0: - cb_count = -1 - else: - cb_count = 0 - i = 0 - cb(data_len, cb_size) - - bytes_togo = size - if bytes_togo and bytes_togo < self.BufferSize: - chunk = fp.read(bytes_togo) - else: - chunk = fp.read(self.BufferSize) - - if not isinstance(chunk, bytes): - chunk = chunk.encode('utf-8') - - if spos is None: - # read at least something from a non-seekable fp. - self.read_from_stream = True - while chunk: - chunk_len = len(chunk) - data_len += chunk_len - if chunked_transfer: - http_conn.send('%x;\r\n' % chunk_len) - http_conn.send(chunk) - http_conn.send('\r\n') - else: - http_conn.send(chunk) - for alg in digesters: - digesters[alg].update(chunk) - if bytes_togo: - bytes_togo -= chunk_len - if bytes_togo <= 0: - break - if cb: - i += 1 - if i == cb_count or cb_count == -1: - cb(data_len, cb_size) - i = 0 - if bytes_togo and bytes_togo < self.BufferSize: - chunk = fp.read(bytes_togo) - else: - chunk = fp.read(self.BufferSize) - - if not isinstance(chunk, bytes): - chunk = chunk.encode('utf-8') - - self.size = data_len - - for alg in digesters: - self.local_hashes[alg] = digesters[alg].digest() - - if chunked_transfer: - http_conn.send('0\r\n') - # http_conn.send("Content-MD5: %s\r\n" % self.base64md5) - http_conn.send('\r\n') - - if cb and (cb_count <= 1 or i > 0) and data_len > 0: - cb(data_len, cb_size) - - http_conn.set_debuglevel(save_debug) - self.bucket.connection.debug = save_debug - response = http_conn.getresponse() - body = response.read() - - if not self.should_retry(response, chunked_transfer): - raise provider.storage_response_error( - response.status, response.reason, body) - - return response - - if not headers: - headers = {} - else: - headers = headers.copy() - # Overwrite user-supplied user-agent. - for header in find_matching_headers('User-Agent', headers): - del headers[header] - headers['User-Agent'] = UserAgent - # If storage_class is None, then a user has not explicitly requested - # a storage class, so we can assume STANDARD here - if self._storage_class not in [None, 'STANDARD']: - headers[provider.storage_class_header] = self.storage_class - if find_matching_headers('Content-Encoding', headers): - self.content_encoding = merge_headers_by_name( - 'Content-Encoding', headers) - if find_matching_headers('Content-Language', headers): - self.content_language = merge_headers_by_name( - 'Content-Language', headers) - content_type_headers = find_matching_headers('Content-Type', headers) - if content_type_headers: - # Some use cases need to suppress sending of the Content-Type - # header and depend on the receiving server to set the content - # type. This can be achieved by setting headers['Content-Type'] - # to None when calling this method. - if (len(content_type_headers) == 1 and - headers[content_type_headers[0]] is None): - # Delete null Content-Type value to skip sending that header. - del headers[content_type_headers[0]] - else: - self.content_type = merge_headers_by_name( - 'Content-Type', headers) - elif self.path: - self.content_type = mimetypes.guess_type(self.path)[0] - if self.content_type is None: - self.content_type = self.DefaultContentType - headers['Content-Type'] = self.content_type - else: - headers['Content-Type'] = self.content_type - if self.base64md5: - headers['Content-MD5'] = self.base64md5 - if chunked_transfer: - headers['Transfer-Encoding'] = 'chunked' - #if not self.base64md5: - # headers['Trailer'] = "Content-MD5" - else: - headers['Content-Length'] = str(self.size) - # This is terrible. We need a SHA256 of the body for SigV4, but to do - # the chunked ``sender`` behavior above, the ``fp`` isn't available to - # the auth mechanism (because closures). Detect if it's SigV4 & embelish - # while we can before the auth calculations occur. - if 'hmac-v4-s3' in self.bucket.connection._required_auth_capability(): - kwargs = {'fp': fp, 'hash_algorithm': hashlib.sha256} - if size is not None: - kwargs['size'] = size - headers['_sha256'] = compute_hash(**kwargs)[0] - headers['Expect'] = '100-Continue' - headers = boto.utils.merge_meta(headers, self.metadata, provider) - resp = self.bucket.connection.make_request( - 'PUT', - self.bucket.name, - self.name, - headers, - sender=sender, - query_args=query_args - ) - self.handle_version_headers(resp, force=True) - self.handle_addl_headers(resp.getheaders()) - - def should_retry(self, response, chunked_transfer=False): - provider = self.bucket.connection.provider - - if not chunked_transfer: - if response.status in [500, 503]: - # 500 & 503 can be plain retries. - return True - - if response.getheader('location'): - # If there's a redirect, plain retry. - return True - - if 200 <= response.status <= 299: - self.etag = response.getheader('etag') - md5 = self.md5 - if isinstance(md5, bytes): - md5 = md5.decode('utf-8') - - # If you use customer-provided encryption keys, the ETag value that - # Amazon S3 returns in the response will not be the MD5 of the - # object. - server_side_encryption_customer_algorithm = response.getheader( - 'x-amz-server-side-encryption-customer-algorithm', None) - if server_side_encryption_customer_algorithm is None: - if self.etag != '"%s"' % md5: - raise provider.storage_data_error( - 'ETag from S3 did not match computed MD5. ' - '%s vs. %s' % (self.etag, self.md5)) - - return True - - if response.status == 400: - # The 400 must be trapped so the retry handler can check to - # see if it was a timeout. - # If ``RequestTimeout`` is present, we'll retry. Otherwise, bomb - # out. - body = response.read() - err = provider.storage_response_error( - response.status, - response.reason, - body - ) - - if err.error_code in ['RequestTimeout']: - raise PleaseRetryException( - "Saw %s, retrying" % err.error_code, - response=response - ) - - return False - - def compute_md5(self, fp, size=None): - """ - :type fp: file - :param fp: File pointer to the file to MD5 hash. The file - pointer will be reset to the same position before the - method returns. - - :type size: int - :param size: (optional) The Maximum number of bytes to read - from the file pointer (fp). This is useful when uploading - a file in multiple parts where the file is being split - in place into different parts. Less bytes may be available. - """ - hex_digest, b64_digest, data_size = compute_md5(fp, size=size) - # Returned values are MD5 hash, base64 encoded MD5 hash, and data size. - # The internal implementation of compute_md5() needs to return the - # data size but we don't want to return that value to the external - # caller because it changes the class interface (i.e. it might - # break some code) so we consume the third tuple value here and - # return the remainder of the tuple to the caller, thereby preserving - # the existing interface. - self.size = data_size - return (hex_digest, b64_digest) - - def set_contents_from_stream(self, fp, headers=None, replace=True, - cb=None, num_cb=10, policy=None, - reduced_redundancy=False, query_args=None, - size=None): - """ - Store an object using the name of the Key object as the key in - cloud and the contents of the data stream pointed to by 'fp' as - the contents. - - The stream object is not seekable and total size is not known. - This has the implication that we can't specify the - Content-Size and Content-MD5 in the header. So for huge - uploads, the delay in calculating MD5 is avoided but with a - penalty of inability to verify the integrity of the uploaded - data. - - :type fp: file - :param fp: the file whose contents are to be uploaded - - :type headers: dict - :param headers: additional HTTP headers to be sent with the - PUT request. - - :type replace: bool - :param replace: If this parameter is False, the method will first check - to see if an object exists in the bucket with the same key. If it - does, it won't overwrite it. The default value is True which will - overwrite the object. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two integer - parameters, the first representing the number of bytes that have - been successfully transmitted to GS and the second representing the - total number of bytes that need to be transmitted. - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter, this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type policy: :class:`boto.gs.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the new key - in GS. - - :type reduced_redundancy: bool - :param reduced_redundancy: If True, this will set the storage - class of the new Key to be REDUCED_REDUNDANCY. The Reduced - Redundancy Storage (RRS) feature of S3, provides lower - redundancy at lower storage cost. - - :type size: int - :param size: (optional) The Maximum number of bytes to read from - the file pointer (fp). This is useful when uploading a - file in multiple parts where you are splitting the file up - into different ranges to be uploaded. If not specified, - the default behaviour is to read all bytes from the file - pointer. Less bytes may be available. - """ - - provider = self.bucket.connection.provider - if not provider.supports_chunked_transfer(): - raise BotoClientError('%s does not support chunked transfer' - % provider.get_provider_name()) - - # Name of the Object should be specified explicitly for Streams. - if not self.name or self.name == '': - raise BotoClientError('Cannot determine the destination ' - 'object name for the given stream') - - if headers is None: - headers = {} - if policy: - headers[provider.acl_header] = policy - - if reduced_redundancy: - self.storage_class = 'REDUCED_REDUNDANCY' - if provider.storage_class_header: - headers[provider.storage_class_header] = self.storage_class - - if self.bucket is not None: - if not replace: - if self.bucket.lookup(self.name): - return - self.send_file(fp, headers, cb, num_cb, query_args, - chunked_transfer=True, size=size) - - def set_contents_from_file(self, fp, headers=None, replace=True, - cb=None, num_cb=10, policy=None, md5=None, - reduced_redundancy=False, query_args=None, - encrypt_key=False, size=None, rewind=False): - """ - Store an object in S3 using the name of the Key object as the - key in S3 and the contents of the file pointed to by 'fp' as the - contents. The data is read from 'fp' from its current position until - 'size' bytes have been read or EOF. - - :type fp: file - :param fp: the file whose contents to upload - - :type headers: dict - :param headers: Additional HTTP headers that will be sent with - the PUT request. - - :type replace: bool - :param replace: If this parameter is False, the method will - first check to see if an object exists in the bucket with - the same key. If it does, it won't overwrite it. The - default value is True which will overwrite the object. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type policy: :class:`boto.s3.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the - new key in S3. - - :type md5: A tuple containing the hexdigest version of the MD5 - checksum of the file as the first element and the - Base64-encoded version of the plain checksum as the second - element. This is the same format returned by the - compute_md5 method. - :param md5: If you need to compute the MD5 for any reason - prior to upload, it's silly to have to do it twice so this - param, if present, will be used as the MD5 values of the - file. Otherwise, the checksum will be computed. - - :type reduced_redundancy: bool - :param reduced_redundancy: If True, this will set the storage - class of the new Key to be REDUCED_REDUNDANCY. The Reduced - Redundancy Storage (RRS) feature of S3, provides lower - redundancy at lower storage cost. - - :type encrypt_key: bool - :param encrypt_key: If True, the new copy of the object will - be encrypted on the server-side by S3 and will be stored - in an encrypted form while at rest in S3. - - :type size: int - :param size: (optional) The Maximum number of bytes to read - from the file pointer (fp). This is useful when uploading - a file in multiple parts where you are splitting the file - up into different ranges to be uploaded. If not specified, - the default behaviour is to read all bytes from the file - pointer. Less bytes may be available. - - :type rewind: bool - :param rewind: (optional) If True, the file pointer (fp) will - be rewound to the start before any bytes are read from - it. The default behaviour is False which reads from the - current position of the file pointer (fp). - - :rtype: int - :return: The number of bytes written to the key. - """ - provider = self.bucket.connection.provider - headers = headers or {} - if policy: - headers[provider.acl_header] = policy - if encrypt_key: - headers[provider.server_side_encryption_header] = 'AES256' - - if rewind: - # caller requests reading from beginning of fp. - fp.seek(0, os.SEEK_SET) - else: - # The following seek/tell/seek logic is intended - # to detect applications using the older interface to - # set_contents_from_file(), which automatically rewound the - # file each time the Key was reused. This changed with commit - # 14ee2d03f4665fe20d19a85286f78d39d924237e, to support uploads - # split into multiple parts and uploaded in parallel, and at - # the time of that commit this check was added because otherwise - # older programs would get a success status and upload an empty - # object. Unfortuantely, it's very inefficient for fp's implemented - # by KeyFile (used, for example, by gsutil when copying between - # providers). So, we skip the check for the KeyFile case. - # TODO: At some point consider removing this seek/tell/seek - # logic, after enough time has passed that it's unlikely any - # programs remain that assume the older auto-rewind interface. - if not isinstance(fp, KeyFile): - spos = fp.tell() - fp.seek(0, os.SEEK_END) - if fp.tell() == spos: - fp.seek(0, os.SEEK_SET) - if fp.tell() != spos: - # Raise an exception as this is likely a programming - # error whereby there is data before the fp but nothing - # after it. - fp.seek(spos) - raise AttributeError('fp is at EOF. Use rewind option ' - 'or seek() to data start.') - # seek back to the correct position. - fp.seek(spos) - - if reduced_redundancy: - self.storage_class = 'REDUCED_REDUNDANCY' - if provider.storage_class_header: - headers[provider.storage_class_header] = self.storage_class - # TODO - What if provider doesn't support reduced reduncancy? - # What if different providers provide different classes? - if hasattr(fp, 'name'): - self.path = fp.name - if self.bucket is not None: - if not md5 and provider.supports_chunked_transfer(): - # defer md5 calculation to on the fly and - # we don't know anything about size yet. - chunked_transfer = True - self.size = None - else: - chunked_transfer = False - if isinstance(fp, KeyFile): - # Avoid EOF seek for KeyFile case as it's very inefficient. - key = fp.getkey() - size = key.size - fp.tell() - self.size = size - # At present both GCS and S3 use MD5 for the etag for - # non-multipart-uploaded objects. If the etag is 32 hex - # chars use it as an MD5, to avoid having to read the file - # twice while transferring. - if (re.match('^"[a-fA-F0-9]{32}"$', key.etag)): - etag = key.etag.strip('"') - md5 = (etag, base64.b64encode(binascii.unhexlify(etag))) - if not md5: - # compute_md5() and also set self.size to actual - # size of the bytes read computing the md5. - md5 = self.compute_md5(fp, size) - # adjust size if required - size = self.size - elif size: - self.size = size - else: - # If md5 is provided, still need to size so - # calculate based on bytes to end of content - spos = fp.tell() - fp.seek(0, os.SEEK_END) - self.size = fp.tell() - spos - fp.seek(spos) - size = self.size - self.md5 = md5[0] - self.base64md5 = md5[1] - - if self.name is None: - self.name = self.md5 - if not replace: - if self.bucket.lookup(self.name): - return - - self.send_file(fp, headers=headers, cb=cb, num_cb=num_cb, - query_args=query_args, - chunked_transfer=chunked_transfer, size=size) - # return number of bytes written. - return self.size - - def set_contents_from_filename(self, filename, headers=None, replace=True, - cb=None, num_cb=10, policy=None, md5=None, - reduced_redundancy=False, - encrypt_key=False): - """ - Store an object in S3 using the name of the Key object as the - key in S3 and the contents of the file named by 'filename'. - See set_contents_from_file method for details about the - parameters. - - :type filename: string - :param filename: The name of the file that you want to put onto S3 - - :type headers: dict - :param headers: Additional headers to pass along with the - request to AWS. - - :type replace: bool - :param replace: If True, replaces the contents of the file - if it already exists. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type policy: :class:`boto.s3.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the - new key in S3. - - :type md5: A tuple containing the hexdigest version of the MD5 - checksum of the file as the first element and the - Base64-encoded version of the plain checksum as the second - element. This is the same format returned by the - compute_md5 method. - :param md5: If you need to compute the MD5 for any reason - prior to upload, it's silly to have to do it twice so this - param, if present, will be used as the MD5 values of the - file. Otherwise, the checksum will be computed. - - :type reduced_redundancy: bool - :param reduced_redundancy: If True, this will set the storage - class of the new Key to be REDUCED_REDUNDANCY. The Reduced - Redundancy Storage (RRS) feature of S3, provides lower - redundancy at lower storage cost. :type encrypt_key: bool - :param encrypt_key: If True, the new copy of the object - will be encrypted on the server-side by S3 and will be - stored in an encrypted form while at rest in S3. - - :rtype: int - :return: The number of bytes written to the key. - """ - with open(filename, 'rb') as fp: - return self.set_contents_from_file(fp, headers, replace, cb, - num_cb, policy, md5, - reduced_redundancy, - encrypt_key=encrypt_key) - - def set_contents_from_string(self, string_data, headers=None, replace=True, - cb=None, num_cb=10, policy=None, md5=None, - reduced_redundancy=False, - encrypt_key=False): - """ - Store an object in S3 using the name of the Key object as the - key in S3 and the string 's' as the contents. - See set_contents_from_file method for details about the - parameters. - - :type headers: dict - :param headers: Additional headers to pass along with the - request to AWS. - - :type replace: bool - :param replace: If True, replaces the contents of the file if - it already exists. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type policy: :class:`boto.s3.acl.CannedACLStrings` - :param policy: A canned ACL policy that will be applied to the - new key in S3. - - :type md5: A tuple containing the hexdigest version of the MD5 - checksum of the file as the first element and the - Base64-encoded version of the plain checksum as the second - element. This is the same format returned by the - compute_md5 method. - :param md5: If you need to compute the MD5 for any reason - prior to upload, it's silly to have to do it twice so this - param, if present, will be used as the MD5 values of the - file. Otherwise, the checksum will be computed. - - :type reduced_redundancy: bool - :param reduced_redundancy: If True, this will set the storage - class of the new Key to be REDUCED_REDUNDANCY. The Reduced - Redundancy Storage (RRS) feature of S3, provides lower - redundancy at lower storage cost. - - :type encrypt_key: bool - :param encrypt_key: If True, the new copy of the object will - be encrypted on the server-side by S3 and will be stored - in an encrypted form while at rest in S3. - """ - if not isinstance(string_data, bytes): - string_data = string_data.encode("utf-8") - fp = BytesIO(string_data) - r = self.set_contents_from_file(fp, headers, replace, cb, num_cb, - policy, md5, reduced_redundancy, - encrypt_key=encrypt_key) - fp.close() - return r - - def get_file(self, fp, headers=None, cb=None, num_cb=10, - torrent=False, version_id=None, override_num_retries=None, - response_headers=None): - """ - Retrieves a file from an S3 Key - - :type fp: file - :param fp: File pointer to put the data into - - :type headers: string - :param: headers to send when retrieving the files - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type torrent: bool - :param torrent: Flag for whether to get a torrent for the file - - :type override_num_retries: int - :param override_num_retries: If not None will override configured - num_retries parameter for underlying GET. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - - :type version_id: str - :param version_id: The ID of a particular version of the object. - If this parameter is not supplied but the Key object has - a ``version_id`` attribute, that value will be used when - retrieving the object. You can set the Key object's - ``version_id`` attribute to None to always grab the latest - version from a version-enabled bucket. - """ - self._get_file_internal(fp, headers=headers, cb=cb, num_cb=num_cb, - torrent=torrent, version_id=version_id, - override_num_retries=override_num_retries, - response_headers=response_headers, - hash_algs=None, - query_args=None) - - def _get_file_internal(self, fp, headers=None, cb=None, num_cb=10, - torrent=False, version_id=None, override_num_retries=None, - response_headers=None, hash_algs=None, query_args=None): - if headers is None: - headers = {} - save_debug = self.bucket.connection.debug - if self.bucket.connection.debug == 1: - self.bucket.connection.debug = 0 - - query_args = query_args or [] - if torrent: - query_args.append('torrent') - - if hash_algs is None and not torrent: - hash_algs = {'md5': md5} - digesters = dict((alg, hash_algs[alg]()) for alg in hash_algs or {}) - - # If a version_id is passed in, use that. If not, check to see - # if the Key object has an explicit version_id and, if so, use that. - # Otherwise, don't pass a version_id query param. - if version_id is None: - version_id = self.version_id - if version_id: - query_args.append('versionId=%s' % version_id) - if response_headers: - for key in response_headers: - query_args.append('%s=%s' % ( - key, urllib.parse.quote(response_headers[key]))) - query_args = '&'.join(query_args) - self.open('r', headers, query_args=query_args, - override_num_retries=override_num_retries) - - data_len = 0 - if cb: - if self.size is None: - cb_size = 0 - else: - cb_size = self.size - if self.size is None and num_cb != -1: - # If size is not available due to chunked transfer for example, - # we'll call the cb for every 1MB of data transferred. - cb_count = (1024 * 1024) / self.BufferSize - elif num_cb > 1: - cb_count = int(math.ceil(cb_size/self.BufferSize/(num_cb-1.0))) - elif num_cb < 0: - cb_count = -1 - else: - cb_count = 0 - i = 0 - cb(data_len, cb_size) - try: - for bytes in self: - fp.write(bytes) - data_len += len(bytes) - for alg in digesters: - digesters[alg].update(bytes) - if cb: - if cb_size > 0 and data_len >= cb_size: - break - i += 1 - if i == cb_count or cb_count == -1: - cb(data_len, cb_size) - i = 0 - except IOError as e: - if e.errno == errno.ENOSPC: - raise StorageDataError('Out of space for destination file ' - '%s' % fp.name) - raise - if cb and (cb_count <= 1 or i > 0) and data_len > 0: - cb(data_len, cb_size) - for alg in digesters: - self.local_hashes[alg] = digesters[alg].digest() - if self.size is None and not torrent and "Range" not in headers: - self.size = data_len - self.close() - self.bucket.connection.debug = save_debug - - def get_torrent_file(self, fp, headers=None, cb=None, num_cb=10): - """ - Get a torrent file (see to get_file) - - :type fp: file - :param fp: The file pointer of where to put the torrent - - :type headers: dict - :param headers: Headers to be passed - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - """ - return self.get_file(fp, headers, cb, num_cb, torrent=True) - - def get_contents_to_file(self, fp, headers=None, - cb=None, num_cb=10, - torrent=False, - version_id=None, - res_download_handler=None, - response_headers=None): - """ - Retrieve an object from S3 using the name of the Key object as the - key in S3. Write the contents of the object to the file pointed - to by 'fp'. - - :type fp: File -like object - :param fp: - - :type headers: dict - :param headers: additional HTTP headers that will be sent with - the GET request. - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type torrent: bool - :param torrent: If True, returns the contents of a torrent - file as a string. - - :type res_upload_handler: ResumableDownloadHandler - :param res_download_handler: If provided, this handler will - perform the download. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - - :type version_id: str - :param version_id: The ID of a particular version of the object. - If this parameter is not supplied but the Key object has - a ``version_id`` attribute, that value will be used when - retrieving the object. You can set the Key object's - ``version_id`` attribute to None to always grab the latest - version from a version-enabled bucket. - """ - if self.bucket is not None: - if res_download_handler: - res_download_handler.get_file(self, fp, headers, cb, num_cb, - torrent=torrent, - version_id=version_id) - else: - self.get_file(fp, headers, cb, num_cb, torrent=torrent, - version_id=version_id, - response_headers=response_headers) - - def get_contents_to_filename(self, filename, headers=None, - cb=None, num_cb=10, - torrent=False, - version_id=None, - res_download_handler=None, - response_headers=None): - """ - Retrieve an object from S3 using the name of the Key object as the - key in S3. Store contents of the object to a file named by 'filename'. - See get_contents_to_file method for details about the - parameters. - - :type filename: string - :param filename: The filename of where to put the file contents - - :type headers: dict - :param headers: Any additional headers to send in the request - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type torrent: bool - :param torrent: If True, returns the contents of a torrent file - as a string. - - :type res_upload_handler: ResumableDownloadHandler - :param res_download_handler: If provided, this handler will - perform the download. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - - :type version_id: str - :param version_id: The ID of a particular version of the object. - If this parameter is not supplied but the Key object has - a ``version_id`` attribute, that value will be used when - retrieving the object. You can set the Key object's - ``version_id`` attribute to None to always grab the latest - version from a version-enabled bucket. - """ - try: - with open(filename, 'wb') as fp: - self.get_contents_to_file(fp, headers, cb, num_cb, - torrent=torrent, - version_id=version_id, - res_download_handler=res_download_handler, - response_headers=response_headers) - except Exception: - os.remove(filename) - raise - # if last_modified date was sent from s3, try to set file's timestamp - if self.last_modified is not None: - try: - modified_tuple = email.utils.parsedate_tz(self.last_modified) - modified_stamp = int(email.utils.mktime_tz(modified_tuple)) - os.utime(fp.name, (modified_stamp, modified_stamp)) - except Exception: - pass - - def get_contents_as_string(self, headers=None, - cb=None, num_cb=10, - torrent=False, - version_id=None, - response_headers=None, encoding=None): - """ - Retrieve an object from S3 using the name of the Key object as the - key in S3. Return the contents of the object as a string. - See get_contents_to_file method for details about the - parameters. - - :type headers: dict - :param headers: Any additional headers to send in the request - - :type cb: function - :param cb: a callback function that will be called to report - progress on the upload. The callback should accept two - integer parameters, the first representing the number of - bytes that have been successfully transmitted to S3 and - the second representing the size of the to be transmitted - object. - - :type cb: int - :param num_cb: (optional) If a callback is specified with the - cb parameter this parameter determines the granularity of - the callback by defining the maximum number of times the - callback will be called during the file transfer. - - :type torrent: bool - :param torrent: If True, returns the contents of a torrent file - as a string. - - :type response_headers: dict - :param response_headers: A dictionary containing HTTP - headers/values that will override any headers associated - with the stored object in the response. See - http://goo.gl/EWOPb for details. - - :type version_id: str - :param version_id: The ID of a particular version of the object. - If this parameter is not supplied but the Key object has - a ``version_id`` attribute, that value will be used when - retrieving the object. You can set the Key object's - ``version_id`` attribute to None to always grab the latest - version from a version-enabled bucket. - - :type encoding: str - :param encoding: The text encoding to use, such as ``utf-8`` - or ``iso-8859-1``. If set, then a string will be returned. - Defaults to ``None`` and returns bytes. - - :rtype: bytes or str - :returns: The contents of the file as bytes or a string - """ - fp = BytesIO() - self.get_contents_to_file(fp, headers, cb, num_cb, torrent=torrent, - version_id=version_id, - response_headers=response_headers) - value = fp.getvalue() - - if encoding is not None: - value = value.decode(encoding) - - return value - - def add_email_grant(self, permission, email_address, headers=None): - """ - Convenience method that provides a quick way to add an email grant - to a key. This method retrieves the current ACL, creates a new - grant based on the parameters passed in, adds that grant to the ACL - and then PUT's the new ACL back to S3. - - :type permission: string - :param permission: The permission being granted. Should be one of: - (READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL). - - :type email_address: string - :param email_address: The email address associated with the AWS - account your are granting the permission to. - - :type recursive: boolean - :param recursive: A boolean value to controls whether the - command will apply the grant to all keys within the bucket - or not. The default value is False. By passing a True - value, the call will iterate through all keys in the - bucket and apply the same grant to each key. CAUTION: If - you have a lot of keys, this could take a long time! - """ - policy = self.get_acl(headers=headers) - policy.acl.add_email_grant(permission, email_address) - self.set_acl(policy, headers=headers) - - def add_user_grant(self, permission, user_id, headers=None, - display_name=None): - """ - Convenience method that provides a quick way to add a canonical - user grant to a key. This method retrieves the current ACL, - creates a new grant based on the parameters passed in, adds that - grant to the ACL and then PUT's the new ACL back to S3. - - :type permission: string - :param permission: The permission being granted. Should be one of: - (READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL). - - :type user_id: string - :param user_id: The canonical user id associated with the AWS - account your are granting the permission to. - - :type display_name: string - :param display_name: An option string containing the user's - Display Name. Only required on Walrus. - """ - policy = self.get_acl(headers=headers) - policy.acl.add_user_grant(permission, user_id, - display_name=display_name) - self.set_acl(policy, headers=headers) - - def _normalize_metadata(self, metadata): - if type(metadata) == set: - norm_metadata = set() - for k in metadata: - norm_metadata.add(k.lower()) - else: - norm_metadata = {} - for k in metadata: - norm_metadata[k.lower()] = metadata[k] - return norm_metadata - - def _get_remote_metadata(self, headers=None): - """ - Extracts metadata from existing URI into a dict, so we can - overwrite/delete from it to form the new set of metadata to apply to a - key. - """ - metadata = {} - for underscore_name in self._underscore_base_user_settable_fields: - if hasattr(self, underscore_name): - value = getattr(self, underscore_name) - if value: - # Generate HTTP field name corresponding to "_" named field. - field_name = underscore_name.replace('_', '-') - metadata[field_name.lower()] = value - # self.metadata contains custom metadata, which are all user-settable. - prefix = self.provider.metadata_prefix - for underscore_name in self.metadata: - field_name = underscore_name.replace('_', '-') - metadata['%s%s' % (prefix, field_name.lower())] = ( - self.metadata[underscore_name]) - return metadata - - def set_remote_metadata(self, metadata_plus, metadata_minus, preserve_acl, - headers=None): - metadata_plus = self._normalize_metadata(metadata_plus) - metadata_minus = self._normalize_metadata(metadata_minus) - metadata = self._get_remote_metadata() - metadata.update(metadata_plus) - for h in metadata_minus: - if h in metadata: - del metadata[h] - src_bucket = self.bucket - # Boto prepends the meta prefix when adding headers, so strip prefix in - # metadata before sending back in to copy_key() call. - rewritten_metadata = {} - for h in metadata: - if (h.startswith('x-goog-meta-') or h.startswith('x-amz-meta-')): - rewritten_h = (h.replace('x-goog-meta-', '') - .replace('x-amz-meta-', '')) - else: - rewritten_h = h - rewritten_metadata[rewritten_h] = metadata[h] - metadata = rewritten_metadata - src_bucket.copy_key(self.name, self.bucket.name, self.name, - metadata=metadata, preserve_acl=preserve_acl, - headers=headers) - - def restore(self, days, headers=None): - """Restore an object from an archive. - - :type days: int - :param days: The lifetime of the restored object (must - be at least 1 day). If the object is already restored - then this parameter can be used to readjust the lifetime - of the restored object. In this case, the days - param is with respect to the initial time of the request. - If the object has not been restored, this param is with - respect to the completion time of the request. - - """ - response = self.bucket.connection.make_request( - 'POST', self.bucket.name, self.name, - data=self.RestoreBody % days, - headers=headers, query_args='restore') - if response.status not in (200, 202): - provider = self.bucket.connection.provider - raise provider.storage_response_error(response.status, - response.reason, - response.read()) diff --git a/awx/lib/site-packages/boto/s3/keyfile.py b/awx/lib/site-packages/boto/s3/keyfile.py deleted file mode 100644 index 4245413d74..0000000000 --- a/awx/lib/site-packages/boto/s3/keyfile.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright 2013 Google Inc. -# Copyright 2011, Nexenta Systems Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Wrapper class to expose a Key being read via a partial implementaiton of the -Python file interface. The only functions supported are those needed for seeking -in a Key open for reading. -""" - -import os -from boto.exception import StorageResponseError - -class KeyFile(): - - def __init__(self, key): - self.key = key - self.key.open_read() - self.location = 0 - self.closed = False - self.softspace = -1 # Not implemented. - self.mode = 'r' - self.encoding = 'Undefined in KeyFile' - self.errors = 'Undefined in KeyFile' - self.newlines = 'Undefined in KeyFile' - self.name = key.name - - def tell(self): - if self.location is None: - raise ValueError("I/O operation on closed file") - return self.location - - def seek(self, pos, whence=os.SEEK_SET): - self.key.close(fast=True) - if whence == os.SEEK_END: - # We need special handling for this case because sending an HTTP range GET - # with EOF for the range start would cause an invalid range error. Instead - # we position to one before EOF (plus pos) and then read one byte to - # position at EOF. - if self.key.size == 0: - # Don't try to seek with an empty key. - return - pos = self.key.size + pos - 1 - if pos < 0: - raise IOError("Invalid argument") - self.key.open_read(headers={"Range": "bytes=%d-" % pos}) - self.key.read(1) - self.location = pos + 1 - return - - if whence == os.SEEK_SET: - if pos < 0: - raise IOError("Invalid argument") - elif whence == os.SEEK_CUR: - pos += self.location - else: - raise IOError('Invalid whence param (%d) passed to seek' % whence) - try: - self.key.open_read(headers={"Range": "bytes=%d-" % pos}) - except StorageResponseError as e: - # 416 Invalid Range means that the given starting byte was past the end - # of file. We catch this because the Python file interface allows silently - # seeking past the end of the file. - if e.status != 416: - raise - - self.location = pos - - def read(self, size): - self.location += size - return self.key.read(size) - - def close(self): - self.key.close() - self.location = None - self.closed = True - - def isatty(self): - return False - - # Non-file interface, useful for code that wants to dig into underlying Key - # state. - def getkey(self): - return self.key - - # Unimplemented interfaces below here. - - def write(self, buf): - raise NotImplementedError('write not implemented in KeyFile') - - def fileno(self): - raise NotImplementedError('fileno not implemented in KeyFile') - - def flush(self): - raise NotImplementedError('flush not implemented in KeyFile') - - def next(self): - raise NotImplementedError('next not implemented in KeyFile') - - def readinto(self): - raise NotImplementedError('readinto not implemented in KeyFile') - - def readline(self): - raise NotImplementedError('readline not implemented in KeyFile') - - def readlines(self): - raise NotImplementedError('readlines not implemented in KeyFile') - - def truncate(self): - raise NotImplementedError('truncate not implemented in KeyFile') - - def writelines(self): - raise NotImplementedError('writelines not implemented in KeyFile') - - def xreadlines(self): - raise NotImplementedError('xreadlines not implemented in KeyFile') diff --git a/awx/lib/site-packages/boto/s3/lifecycle.py b/awx/lib/site-packages/boto/s3/lifecycle.py deleted file mode 100644 index 8ceb879570..0000000000 --- a/awx/lib/site-packages/boto/s3/lifecycle.py +++ /dev/null @@ -1,236 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from boto.compat import six - -class Rule(object): - """ - A Lifecycle rule for an S3 bucket. - - :ivar id: Unique identifier for the rule. The value cannot be longer - than 255 characters. This value is optional. The server will - generate a unique value for the rule if no value is provided. - - :ivar prefix: Prefix identifying one or more objects to which the - rule applies. If prefix is not provided, Boto generates a default - prefix which will match all objects. - - :ivar status: If 'Enabled', the rule is currently being applied. - If 'Disabled', the rule is not currently being applied. - - :ivar expiration: An instance of `Expiration`. This indicates - the lifetime of the objects that are subject to the rule. - - :ivar transition: An instance of `Transition`. This indicates - when to transition to a different storage class. - - """ - def __init__(self, id=None, prefix=None, status=None, expiration=None, - transition=None): - self.id = id - self.prefix = '' if prefix is None else prefix - self.status = status - if isinstance(expiration, six.integer_types): - # retain backwards compatibility??? - self.expiration = Expiration(days=expiration) - else: - # None or object - self.expiration = expiration - self.transition = transition - - def __repr__(self): - return '<Rule: %s>' % self.id - - def startElement(self, name, attrs, connection): - if name == 'Transition': - self.transition = Transition() - return self.transition - elif name == 'Expiration': - self.expiration = Expiration() - return self.expiration - return None - - def endElement(self, name, value, connection): - if name == 'ID': - self.id = value - elif name == 'Prefix': - self.prefix = value - elif name == 'Status': - self.status = value - else: - setattr(self, name, value) - - def to_xml(self): - s = '<Rule>' - if self.id is not None: - s += '<ID>%s</ID>' % self.id - s += '<Prefix>%s</Prefix>' % self.prefix - s += '<Status>%s</Status>' % self.status - if self.expiration is not None: - s += self.expiration.to_xml() - if self.transition is not None: - s += self.transition.to_xml() - s += '</Rule>' - return s - -class Expiration(object): - """ - When an object will expire. - - :ivar days: The number of days until the object expires - - :ivar date: The date when the object will expire. Must be - in ISO 8601 format. - """ - def __init__(self, days=None, date=None): - self.days = days - self.date = date - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Days': - self.days = int(value) - elif name == 'Date': - self.date = value - - def __repr__(self): - if self.days is None: - how_long = "on: %s" % self.date - else: - how_long = "in: %s days" % self.days - return '<Expiration: %s>' % how_long - - def to_xml(self): - s = '<Expiration>' - if self.days is not None: - s += '<Days>%s</Days>' % self.days - elif self.date is not None: - s += '<Date>%s</Date>' % self.date - s += '</Expiration>' - return s - -class Transition(object): - """ - A transition to a different storage class. - - :ivar days: The number of days until the object should be moved. - - :ivar date: The date when the object should be moved. Should be - in ISO 8601 format. - - :ivar storage_class: The storage class to transition to. Valid - values are GLACIER. - - """ - def __init__(self, days=None, date=None, storage_class=None): - self.days = days - self.date = date - self.storage_class = storage_class - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Days': - self.days = int(value) - elif name == 'Date': - self.date = value - elif name == 'StorageClass': - self.storage_class = value - - def __repr__(self): - if self.days is None: - how_long = "on: %s" % self.date - else: - how_long = "in: %s days" % self.days - return '<Transition: %s, %s>' % (how_long, self.storage_class) - - def to_xml(self): - s = '<Transition>' - s += '<StorageClass>%s</StorageClass>' % self.storage_class - if self.days is not None: - s += '<Days>%s</Days>' % self.days - elif self.date is not None: - s += '<Date>%s</Date>' % self.date - s += '</Transition>' - return s - -class Lifecycle(list): - """ - A container for the rules associated with a Lifecycle configuration. - """ - - def startElement(self, name, attrs, connection): - if name == 'Rule': - rule = Rule() - self.append(rule) - return rule - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - def to_xml(self): - """ - Returns a string containing the XML version of the Lifecycle - configuration as defined by S3. - """ - s = '<?xml version="1.0" encoding="UTF-8"?>' - s += '<LifecycleConfiguration>' - for rule in self: - s += rule.to_xml() - s += '</LifecycleConfiguration>' - return s - - def add_rule(self, id=None, prefix='', status='Enabled', - expiration=None, transition=None): - """ - Add a rule to this Lifecycle configuration. This only adds - the rule to the local copy. To install the new rule(s) on - the bucket, you need to pass this Lifecycle config object - to the configure_lifecycle method of the Bucket object. - - :type id: str - :param id: Unique identifier for the rule. The value cannot be longer - than 255 characters. This value is optional. The server will - generate a unique value for the rule if no value is provided. - - :type prefix: str - :iparam prefix: Prefix identifying one or more objects to which the - rule applies. - - :type status: str - :param status: If 'Enabled', the rule is currently being applied. - If 'Disabled', the rule is not currently being applied. - - :type expiration: int - :param expiration: Indicates the lifetime, in days, of the objects - that are subject to the rule. The value must be a non-zero - positive integer. A Expiration object instance is also perfect. - - :type transition: Transition - :param transition: Indicates when an object transitions to a - different storage class. - """ - rule = Rule(id, prefix, status, expiration, transition) - self.append(rule) diff --git a/awx/lib/site-packages/boto/s3/multidelete.py b/awx/lib/site-packages/boto/s3/multidelete.py deleted file mode 100644 index 3e2d48e32d..0000000000 --- a/awx/lib/site-packages/boto/s3/multidelete.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto import handler -import xml.sax - -class Deleted(object): - """ - A successfully deleted object in a multi-object delete request. - - :ivar key: Key name of the object that was deleted. - - :ivar version_id: Version id of the object that was deleted. - - :ivar delete_marker: If True, indicates the object deleted - was a DeleteMarker. - - :ivar delete_marker_version_id: Version ID of the delete marker - deleted. - """ - def __init__(self, key=None, version_id=None, - delete_marker=False, delete_marker_version_id=None): - self.key = key - self.version_id = version_id - self.delete_marker = delete_marker - self.delete_marker_version_id = delete_marker_version_id - - def __repr__(self): - if self.version_id: - return '<Deleted: %s.%s>' % (self.key, self.version_id) - else: - return '<Deleted: %s>' % self.key - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Key': - self.key = value - elif name == 'VersionId': - self.version_id = value - elif name == 'DeleteMarker': - if value.lower() == 'true': - self.delete_marker = True - elif name == 'DeleteMarkerVersionId': - self.delete_marker_version_id = value - else: - setattr(self, name, value) - -class Error(object): - """ - An unsuccessful deleted object in a multi-object delete request. - - :ivar key: Key name of the object that was not deleted. - - :ivar version_id: Version id of the object that was not deleted. - - :ivar code: Status code of the failed delete operation. - - :ivar message: Status message of the failed delete operation. - """ - def __init__(self, key=None, version_id=None, - code=None, message=None): - self.key = key - self.version_id = version_id - self.code = code - self.message = message - - def __repr__(self): - if self.version_id: - return '<Error: %s.%s(%s)>' % (self.key, self.version_id, - self.code) - else: - return '<Error: %s(%s)>' % (self.key, self.code) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Key': - self.key = value - elif name == 'VersionId': - self.version_id = value - elif name == 'Code': - self.code = value - elif name == 'Message': - self.message = value - else: - setattr(self, name, value) - -class MultiDeleteResult(object): - """ - The status returned from a MultiObject Delete request. - - :ivar deleted: A list of successfully deleted objects. Note that if - the quiet flag was specified in the request, this list will - be empty because only error responses would be returned. - - :ivar errors: A list of unsuccessfully deleted objects. - """ - - def __init__(self, bucket=None): - self.bucket = None - self.deleted = [] - self.errors = [] - - def startElement(self, name, attrs, connection): - if name == 'Deleted': - d = Deleted() - self.deleted.append(d) - return d - elif name == 'Error': - e = Error() - self.errors.append(e) - return e - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - diff --git a/awx/lib/site-packages/boto/s3/multipart.py b/awx/lib/site-packages/boto/s3/multipart.py deleted file mode 100644 index 056f9ca52a..0000000000 --- a/awx/lib/site-packages/boto/s3/multipart.py +++ /dev/null @@ -1,330 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.s3 import user -from boto.s3 import key -from boto import handler -import xml.sax - - -class CompleteMultiPartUpload(object): - """ - Represents a completed MultiPart Upload. Contains the - following useful attributes: - - * location - The URI of the completed upload - * bucket_name - The name of the bucket in which the upload - is contained - * key_name - The name of the new, completed key - * etag - The MD5 hash of the completed, combined upload - * version_id - The version_id of the completed upload - * encrypted - The value of the encryption header - """ - - def __init__(self, bucket=None): - self.bucket = bucket - self.location = None - self.bucket_name = None - self.key_name = None - self.etag = None - self.version_id = None - self.encrypted = None - - def __repr__(self): - return '<CompleteMultiPartUpload: %s.%s>' % (self.bucket_name, - self.key_name) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Location': - self.location = value - elif name == 'Bucket': - self.bucket_name = value - elif name == 'Key': - self.key_name = value - elif name == 'ETag': - self.etag = value - else: - setattr(self, name, value) - - -class Part(object): - """ - Represents a single part in a MultiPart upload. - Attributes include: - - * part_number - The integer part number - * last_modified - The last modified date of this part - * etag - The MD5 hash of this part - * size - The size, in bytes, of this part - """ - - def __init__(self, bucket=None): - self.bucket = bucket - self.part_number = None - self.last_modified = None - self.etag = None - self.size = None - - def __repr__(self): - if isinstance(self.part_number, int): - return '<Part %d>' % self.part_number - else: - return '<Part %s>' % None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'PartNumber': - self.part_number = int(value) - elif name == 'LastModified': - self.last_modified = value - elif name == 'ETag': - self.etag = value - elif name == 'Size': - self.size = int(value) - else: - setattr(self, name, value) - - -def part_lister(mpupload, part_number_marker=None): - """ - A generator function for listing parts of a multipart upload. - """ - more_results = True - part = None - while more_results: - parts = mpupload.get_all_parts(None, part_number_marker) - for part in parts: - yield part - part_number_marker = mpupload.next_part_number_marker - more_results = mpupload.is_truncated - - -class MultiPartUpload(object): - """ - Represents a MultiPart Upload operation. - """ - - def __init__(self, bucket=None): - self.bucket = bucket - self.bucket_name = None - self.key_name = None - self.id = id - self.initiator = None - self.owner = None - self.storage_class = None - self.initiated = None - self.part_number_marker = None - self.next_part_number_marker = None - self.max_parts = None - self.is_truncated = False - self._parts = None - - def __repr__(self): - return '<MultiPartUpload %s>' % self.key_name - - def __iter__(self): - return part_lister(self) - - def to_xml(self): - s = '<CompleteMultipartUpload>\n' - for part in self: - s += ' <Part>\n' - s += ' <PartNumber>%d</PartNumber>\n' % part.part_number - s += ' <ETag>%s</ETag>\n' % part.etag - s += ' </Part>\n' - s += '</CompleteMultipartUpload>' - return s - - def startElement(self, name, attrs, connection): - if name == 'Initiator': - self.initiator = user.User(self) - return self.initiator - elif name == 'Owner': - self.owner = user.User(self) - return self.owner - elif name == 'Part': - part = Part(self.bucket) - self._parts.append(part) - return part - return None - - def endElement(self, name, value, connection): - if name == 'Bucket': - self.bucket_name = value - elif name == 'Key': - self.key_name = value - elif name == 'UploadId': - self.id = value - elif name == 'StorageClass': - self.storage_class = value - elif name == 'PartNumberMarker': - self.part_number_marker = value - elif name == 'NextPartNumberMarker': - self.next_part_number_marker = value - elif name == 'MaxParts': - self.max_parts = int(value) - elif name == 'IsTruncated': - if value == 'true': - self.is_truncated = True - else: - self.is_truncated = False - elif name == 'Initiated': - self.initiated = value - else: - setattr(self, name, value) - - def get_all_parts(self, max_parts=None, part_number_marker=None, - encoding_type=None): - """ - Return the uploaded parts of this MultiPart Upload. This is - a lower-level method that requires you to manually page through - results. To simplify this process, you can just use the - object itself as an iterator and it will automatically handle - all of the paging with S3. - """ - self._parts = [] - query_args = 'uploadId=%s' % self.id - if max_parts: - query_args += '&max-parts=%d' % max_parts - if part_number_marker: - query_args += '&part-number-marker=%s' % part_number_marker - if encoding_type: - query_args += '&encoding-type=%s' % encoding_type - response = self.bucket.connection.make_request('GET', self.bucket.name, - self.key_name, - query_args=query_args) - body = response.read() - if response.status == 200: - h = handler.XmlHandler(self, self) - xml.sax.parseString(body, h) - return self._parts - - def upload_part_from_file(self, fp, part_num, headers=None, replace=True, - cb=None, num_cb=10, md5=None, size=None): - """ - Upload another part of this MultiPart Upload. - - .. note:: - - After you initiate multipart upload and upload one or more parts, - you must either complete or abort multipart upload in order to stop - getting charged for storage of the uploaded parts. Only after you - either complete or abort multipart upload, Amazon S3 frees up the - parts storage and stops charging you for the parts storage. - - :type fp: file - :param fp: The file object you want to upload. - - :type part_num: int - :param part_num: The number of this part. - - The other parameters are exactly as defined for the - :class:`boto.s3.key.Key` set_contents_from_file method. - - :rtype: :class:`boto.s3.key.Key` or subclass - :returns: The uploaded part containing the etag. - """ - if part_num < 1: - raise ValueError('Part numbers must be greater than zero') - query_args = 'uploadId=%s&partNumber=%d' % (self.id, part_num) - key = self.bucket.new_key(self.key_name) - key.set_contents_from_file(fp, headers=headers, replace=replace, - cb=cb, num_cb=num_cb, md5=md5, - reduced_redundancy=False, - query_args=query_args, size=size) - return key - - def copy_part_from_key(self, src_bucket_name, src_key_name, part_num, - start=None, end=None, src_version_id=None, - headers=None): - """ - Copy another part of this MultiPart Upload. - - :type src_bucket_name: string - :param src_bucket_name: Name of the bucket containing the source key - - :type src_key_name: string - :param src_key_name: Name of the source key - - :type part_num: int - :param part_num: The number of this part. - - :type start: int - :param start: Zero-based byte offset to start copying from - - :type end: int - :param end: Zero-based byte offset to copy to - - :type src_version_id: string - :param src_version_id: version_id of source object to copy from - - :type headers: dict - :param headers: Any headers to pass along in the request - """ - if part_num < 1: - raise ValueError('Part numbers must be greater than zero') - query_args = 'uploadId=%s&partNumber=%d' % (self.id, part_num) - if start is not None and end is not None: - rng = 'bytes=%s-%s' % (start, end) - provider = self.bucket.connection.provider - if headers is None: - headers = {} - else: - headers = headers.copy() - headers[provider.copy_source_range_header] = rng - return self.bucket.copy_key(self.key_name, src_bucket_name, - src_key_name, - src_version_id=src_version_id, - storage_class=None, - headers=headers, - query_args=query_args) - - def complete_upload(self): - """ - Complete the MultiPart Upload operation. This method should - be called when all parts of the file have been successfully - uploaded to S3. - - :rtype: :class:`boto.s3.multipart.CompletedMultiPartUpload` - :returns: An object representing the completed upload. - """ - xml = self.to_xml() - return self.bucket.complete_multipart_upload(self.key_name, - self.id, xml) - - def cancel_upload(self): - """ - Cancels a MultiPart Upload operation. The storage consumed by - any previously uploaded parts will be freed. However, if any - part uploads are currently in progress, those part uploads - might or might not succeed. As a result, it might be necessary - to abort a given multipart upload multiple times in order to - completely free all storage consumed by all parts. - """ - self.bucket.cancel_multipart_upload(self.key_name, self.id) diff --git a/awx/lib/site-packages/boto/s3/prefix.py b/awx/lib/site-packages/boto/s3/prefix.py deleted file mode 100644 index adf28e935f..0000000000 --- a/awx/lib/site-packages/boto/s3/prefix.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class Prefix(object): - def __init__(self, bucket=None, name=None): - self.bucket = bucket - self.name = name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Prefix': - self.name = value - else: - setattr(self, name, value) - - @property - def provider(self): - provider = None - if self.bucket and self.bucket.connection: - provider = self.bucket.connection.provider - return provider - diff --git a/awx/lib/site-packages/boto/s3/resumable_download_handler.py b/awx/lib/site-packages/boto/s3/resumable_download_handler.py deleted file mode 100644 index a2a88c74cd..0000000000 --- a/awx/lib/site-packages/boto/s3/resumable_download_handler.py +++ /dev/null @@ -1,352 +0,0 @@ -# Copyright 2010 Google Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import errno -import httplib -import os -import re -import socket -import time -import boto -from boto import config, storage_uri_for_key -from boto.connection import AWSAuthConnection -from boto.exception import ResumableDownloadException -from boto.exception import ResumableTransferDisposition -from boto.s3.keyfile import KeyFile -from boto.gs.key import Key as GSKey - -""" -Resumable download handler. - -Resumable downloads will retry failed downloads, resuming at the byte count -completed by the last download attempt. If too many retries happen with no -progress (per configurable num_retries param), the download will be aborted. - -The caller can optionally specify a tracker_file_name param in the -ResumableDownloadHandler constructor. If you do this, that file will -save the state needed to allow retrying later, in a separate process -(e.g., in a later run of gsutil). - -Note that resumable downloads work across providers (they depend only -on support Range GETs), but this code is in the boto.s3 package -because it is the wrong abstraction level to go in the top-level boto -package. - -TODO: At some point we should refactor the code to have a storage_service -package where all these provider-independent files go. -""" - - -class ByteTranslatingCallbackHandler(object): - """ - Proxy class that translates progress callbacks made by - boto.s3.Key.get_file(), taking into account that we're resuming - a download. - """ - def __init__(self, proxied_cb, download_start_point): - self.proxied_cb = proxied_cb - self.download_start_point = download_start_point - - def call(self, total_bytes_uploaded, total_size): - self.proxied_cb(self.download_start_point + total_bytes_uploaded, - total_size) - - -def get_cur_file_size(fp, position_to_eof=False): - """ - Returns size of file, optionally leaving fp positioned at EOF. - """ - if isinstance(fp, KeyFile) and not position_to_eof: - # Avoid EOF seek for KeyFile case as it's very inefficient. - return fp.getkey().size - if not position_to_eof: - cur_pos = fp.tell() - fp.seek(0, os.SEEK_END) - cur_file_size = fp.tell() - if not position_to_eof: - fp.seek(cur_pos, os.SEEK_SET) - return cur_file_size - - -class ResumableDownloadHandler(object): - """ - Handler for resumable downloads. - """ - - MIN_ETAG_LEN = 5 - - RETRYABLE_EXCEPTIONS = (httplib.HTTPException, IOError, socket.error, - socket.gaierror) - - def __init__(self, tracker_file_name=None, num_retries=None): - """ - Constructor. Instantiate once for each downloaded file. - - :type tracker_file_name: string - :param tracker_file_name: optional file name to save tracking info - about this download. If supplied and the current process fails - the download, it can be retried in a new process. If called - with an existing file containing an unexpired timestamp, - we'll resume the transfer for this file; else we'll start a - new resumable download. - - :type num_retries: int - :param num_retries: the number of times we'll re-try a resumable - download making no progress. (Count resets every time we get - progress, so download can span many more than this number of - retries.) - """ - self.tracker_file_name = tracker_file_name - self.num_retries = num_retries - self.etag_value_for_current_download = None - if tracker_file_name: - self._load_tracker_file_etag() - # Save download_start_point in instance state so caller can - # find how much was transferred by this ResumableDownloadHandler - # (across retries). - self.download_start_point = None - - def _load_tracker_file_etag(self): - f = None - try: - f = open(self.tracker_file_name, 'r') - self.etag_value_for_current_download = f.readline().rstrip('\n') - # We used to match an MD5-based regex to ensure that the etag was - # read correctly. Since ETags need not be MD5s, we now do a simple - # length sanity check instead. - if len(self.etag_value_for_current_download) < self.MIN_ETAG_LEN: - print('Couldn\'t read etag in tracker file (%s). Restarting ' - 'download from scratch.' % self.tracker_file_name) - except IOError as e: - # Ignore non-existent file (happens first time a download - # is attempted on an object), but warn user for other errors. - if e.errno != errno.ENOENT: - # Will restart because - # self.etag_value_for_current_download is None. - print('Couldn\'t read URI tracker file (%s): %s. Restarting ' - 'download from scratch.' % - (self.tracker_file_name, e.strerror)) - finally: - if f: - f.close() - - def _save_tracker_info(self, key): - self.etag_value_for_current_download = key.etag.strip('"\'') - if not self.tracker_file_name: - return - f = None - try: - f = open(self.tracker_file_name, 'w') - f.write('%s\n' % self.etag_value_for_current_download) - except IOError as e: - raise ResumableDownloadException( - 'Couldn\'t write tracker file (%s): %s.\nThis can happen' - 'if you\'re using an incorrectly configured download tool\n' - '(e.g., gsutil configured to save tracker files to an ' - 'unwritable directory)' % - (self.tracker_file_name, e.strerror), - ResumableTransferDisposition.ABORT) - finally: - if f: - f.close() - - def _remove_tracker_file(self): - if (self.tracker_file_name and - os.path.exists(self.tracker_file_name)): - os.unlink(self.tracker_file_name) - - def _attempt_resumable_download(self, key, fp, headers, cb, num_cb, - torrent, version_id, hash_algs): - """ - Attempts a resumable download. - - Raises ResumableDownloadException if any problems occur. - """ - cur_file_size = get_cur_file_size(fp, position_to_eof=True) - - if (cur_file_size and - self.etag_value_for_current_download and - self.etag_value_for_current_download == key.etag.strip('"\'')): - # Try to resume existing transfer. - if cur_file_size > key.size: - raise ResumableDownloadException( - '%s is larger (%d) than %s (%d).\nDeleting tracker file, so ' - 'if you re-try this download it will start from scratch' % - (fp.name, cur_file_size, str(storage_uri_for_key(key)), - key.size), ResumableTransferDisposition.ABORT) - elif cur_file_size == key.size: - if key.bucket.connection.debug >= 1: - print('Download complete.') - return - if key.bucket.connection.debug >= 1: - print('Resuming download.') - headers = headers.copy() - headers['Range'] = 'bytes=%d-%d' % (cur_file_size, key.size - 1) - cb = ByteTranslatingCallbackHandler(cb, cur_file_size).call - self.download_start_point = cur_file_size - else: - if key.bucket.connection.debug >= 1: - print('Starting new resumable download.') - self._save_tracker_info(key) - self.download_start_point = 0 - # Truncate the file, in case a new resumable download is being - # started atop an existing file. - fp.truncate(0) - - # Disable AWSAuthConnection-level retry behavior, since that would - # cause downloads to restart from scratch. - if isinstance(key, GSKey): - key.get_file(fp, headers, cb, num_cb, torrent, version_id, - override_num_retries=0, hash_algs=hash_algs) - else: - key.get_file(fp, headers, cb, num_cb, torrent, version_id, - override_num_retries=0) - fp.flush() - - def get_file(self, key, fp, headers, cb=None, num_cb=10, torrent=False, - version_id=None, hash_algs=None): - """ - Retrieves a file from a Key - :type key: :class:`boto.s3.key.Key` or subclass - :param key: The Key object from which upload is to be downloaded - - :type fp: file - :param fp: File pointer into which data should be downloaded - - :type headers: string - :param: headers to send when retrieving the files - - :type cb: function - :param cb: (optional) a callback function that will be called to report - progress on the download. The callback should accept two integer - parameters, the first representing the number of bytes that have - been successfully transmitted from the storage service and - the second representing the total number of bytes that need - to be transmitted. - - :type num_cb: int - :param num_cb: (optional) If a callback is specified with the cb - parameter this parameter determines the granularity of the callback - by defining the maximum number of times the callback will be - called during the file transfer. - - :type torrent: bool - :param torrent: Flag for whether to get a torrent for the file - - :type version_id: string - :param version_id: The version ID (optional) - - :type hash_algs: dictionary - :param hash_algs: (optional) Dictionary of hash algorithms and - corresponding hashing class that implements update() and digest(). - Defaults to {'md5': hashlib/md5.md5}. - - Raises ResumableDownloadException if a problem occurs during - the transfer. - """ - - debug = key.bucket.connection.debug - if not headers: - headers = {} - - # Use num-retries from constructor if one was provided; else check - # for a value specified in the boto config file; else default to 6. - if self.num_retries is None: - self.num_retries = config.getint('Boto', 'num_retries', 6) - progress_less_iterations = 0 - - while True: # Retry as long as we're making progress. - had_file_bytes_before_attempt = get_cur_file_size(fp) - try: - self._attempt_resumable_download(key, fp, headers, cb, num_cb, - torrent, version_id, hash_algs) - # Download succceded, so remove the tracker file (if have one). - self._remove_tracker_file() - # Previously, check_final_md5() was called here to validate - # downloaded file's checksum, however, to be consistent with - # non-resumable downloads, this call was removed. Checksum - # validation of file contents should be done by the caller. - if debug >= 1: - print('Resumable download complete.') - return - except self.RETRYABLE_EXCEPTIONS as e: - if debug >= 1: - print('Caught exception (%s)' % e.__repr__()) - if isinstance(e, IOError) and e.errno == errno.EPIPE: - # Broken pipe error causes httplib to immediately - # close the socket (http://bugs.python.org/issue5542), - # so we need to close and reopen the key before resuming - # the download. - if isinstance(key, GSKey): - key.get_file(fp, headers, cb, num_cb, torrent, version_id, - override_num_retries=0, hash_algs=hash_algs) - else: - key.get_file(fp, headers, cb, num_cb, torrent, version_id, - override_num_retries=0) - except ResumableDownloadException as e: - if (e.disposition == - ResumableTransferDisposition.ABORT_CUR_PROCESS): - if debug >= 1: - print('Caught non-retryable ResumableDownloadException ' - '(%s)' % e.message) - raise - elif (e.disposition == - ResumableTransferDisposition.ABORT): - if debug >= 1: - print('Caught non-retryable ResumableDownloadException ' - '(%s); aborting and removing tracker file' % - e.message) - self._remove_tracker_file() - raise - else: - if debug >= 1: - print('Caught ResumableDownloadException (%s) - will ' - 'retry' % e.message) - - # At this point we had a re-tryable failure; see if made progress. - if get_cur_file_size(fp) > had_file_bytes_before_attempt: - progress_less_iterations = 0 - else: - progress_less_iterations += 1 - - if progress_less_iterations > self.num_retries: - # Don't retry any longer in the current process. - raise ResumableDownloadException( - 'Too many resumable download attempts failed without ' - 'progress. You might try this download again later', - ResumableTransferDisposition.ABORT_CUR_PROCESS) - - # Close the key, in case a previous download died partway - # through and left data in the underlying key HTTP buffer. - # Do this within a try/except block in case the connection is - # closed (since key.close() attempts to do a final read, in which - # case this read attempt would get an IncompleteRead exception, - # which we can safely ignore. - try: - key.close() - except httplib.IncompleteRead: - pass - - sleep_time_secs = 2**progress_less_iterations - if debug >= 1: - print('Got retryable failure (%d progress-less in a row).\n' - 'Sleeping %d seconds before re-trying' % - (progress_less_iterations, sleep_time_secs)) - time.sleep(sleep_time_secs) diff --git a/awx/lib/site-packages/boto/s3/tagging.py b/awx/lib/site-packages/boto/s3/tagging.py deleted file mode 100644 index 0af6406fb1..0000000000 --- a/awx/lib/site-packages/boto/s3/tagging.py +++ /dev/null @@ -1,71 +0,0 @@ -from boto import handler -import xml.sax - - -class Tag(object): - def __init__(self, key=None, value=None): - self.key = key - self.value = value - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Key': - self.key = value - elif name == 'Value': - self.value = value - - def to_xml(self): - return '<Tag><Key>%s</Key><Value>%s</Value></Tag>' % ( - self.key, self.value) - - def __eq__(self, other): - return (self.key == other.key and self.value == other.value) - - -class TagSet(list): - def startElement(self, name, attrs, connection): - if name == 'Tag': - tag = Tag() - self.append(tag) - return tag - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - def add_tag(self, key, value): - tag = Tag(key, value) - self.append(tag) - - def to_xml(self): - xml = '<TagSet>' - for tag in self: - xml += tag.to_xml() - xml += '</TagSet>' - return xml - - -class Tags(list): - """A container for the tags associated with a bucket.""" - - def startElement(self, name, attrs, connection): - if name == 'TagSet': - tag_set = TagSet() - self.append(tag_set) - return tag_set - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - def to_xml(self): - xml = '<Tagging>' - for tag_set in self: - xml += tag_set.to_xml() - xml +='</Tagging>' - return xml - - def add_tag_set(self, tag_set): - self.append(tag_set) diff --git a/awx/lib/site-packages/boto/s3/user.py b/awx/lib/site-packages/boto/s3/user.py deleted file mode 100644 index f2cbbb7f8f..0000000000 --- a/awx/lib/site-packages/boto/s3/user.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class User(object): - def __init__(self, parent=None, id='', display_name=''): - if parent: - parent.owner = self - self.type = None - self.id = id - self.display_name = display_name - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'DisplayName': - self.display_name = value - elif name == 'ID': - self.id = value - else: - setattr(self, name, value) - - def to_xml(self, element_name='Owner'): - if self.type: - s = '<%s xsi:type="%s">' % (element_name, self.type) - else: - s = '<%s>' % element_name - s += '<ID>%s</ID>' % self.id - s += '<DisplayName>%s</DisplayName>' % self.display_name - s += '</%s>' % element_name - return s diff --git a/awx/lib/site-packages/boto/s3/website.py b/awx/lib/site-packages/boto/s3/website.py deleted file mode 100644 index c307f3e990..0000000000 --- a/awx/lib/site-packages/boto/s3/website.py +++ /dev/null @@ -1,293 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -def tag(key, value): - start = '<%s>' % key - end = '</%s>' % key - return '%s%s%s' % (start, value, end) - - -class WebsiteConfiguration(object): - """ - Website configuration for a bucket. - - :ivar suffix: Suffix that is appended to a request that is for a - "directory" on the website endpoint (e.g. if the suffix is - index.html and you make a request to samplebucket/images/ - the data that is returned will be for the object with the - key name images/index.html). The suffix must not be empty - and must not include a slash character. - - :ivar error_key: The object key name to use when a 4xx class error - occurs. This key identifies the page that is returned when - such an error occurs. - - :ivar redirect_all_requests_to: Describes the redirect behavior for every - request to this bucket's website endpoint. If this value is non None, - no other values are considered when configuring the website - configuration for the bucket. This is an instance of - ``RedirectLocation``. - - :ivar routing_rules: ``RoutingRules`` object which specifies conditions - and redirects that apply when the conditions are met. - - """ - - def __init__(self, suffix=None, error_key=None, - redirect_all_requests_to=None, routing_rules=None): - self.suffix = suffix - self.error_key = error_key - self.redirect_all_requests_to = redirect_all_requests_to - if routing_rules is not None: - self.routing_rules = routing_rules - else: - self.routing_rules = RoutingRules() - - def startElement(self, name, attrs, connection): - if name == 'RoutingRules': - self.routing_rules = RoutingRules() - return self.routing_rules - elif name == 'IndexDocument': - return _XMLKeyValue([('Suffix', 'suffix')], container=self) - elif name == 'ErrorDocument': - return _XMLKeyValue([('Key', 'error_key')], container=self) - - def endElement(self, name, value, connection): - pass - - def to_xml(self): - parts = ['<?xml version="1.0" encoding="UTF-8"?>', - '<WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'] - if self.suffix is not None: - parts.append(tag('IndexDocument', tag('Suffix', self.suffix))) - if self.error_key is not None: - parts.append(tag('ErrorDocument', tag('Key', self.error_key))) - if self.redirect_all_requests_to is not None: - parts.append(self.redirect_all_requests_to.to_xml()) - if self.routing_rules: - parts.append(self.routing_rules.to_xml()) - parts.append('</WebsiteConfiguration>') - return ''.join(parts) - - -class _XMLKeyValue(object): - def __init__(self, translator, container=None): - self.translator = translator - if container: - self.container = container - else: - self.container = self - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - for xml_key, attr_name in self.translator: - if name == xml_key: - setattr(self.container, attr_name, value) - - def to_xml(self): - parts = [] - for xml_key, attr_name in self.translator: - content = getattr(self.container, attr_name) - if content is not None: - parts.append(tag(xml_key, content)) - return ''.join(parts) - - -class RedirectLocation(_XMLKeyValue): - """Specify redirect behavior for every request to a bucket's endpoint. - - :ivar hostname: Name of the host where requests will be redirected. - - :ivar protocol: Protocol to use (http, https) when redirecting requests. - The default is the protocol that is used in the original request. - - """ - TRANSLATOR = [('HostName', 'hostname'), - ('Protocol', 'protocol'), - ] - - def __init__(self, hostname=None, protocol=None): - self.hostname = hostname - self.protocol = protocol - super(RedirectLocation, self).__init__(self.TRANSLATOR) - - def to_xml(self): - return tag('RedirectAllRequestsTo', - super(RedirectLocation, self).to_xml()) - - -class RoutingRules(list): - - def add_rule(self, rule): - """ - - :type rule: :class:`boto.s3.website.RoutingRule` - :param rule: A routing rule. - - :return: This ``RoutingRules`` object is returned, - so that it can chain subsequent calls. - - """ - self.append(rule) - return self - - def startElement(self, name, attrs, connection): - if name == 'RoutingRule': - rule = RoutingRule(Condition(), Redirect()) - self.add_rule(rule) - return rule - - def endElement(self, name, value, connection): - pass - - def __repr__(self): - return "RoutingRules(%s)" % super(RoutingRules, self).__repr__() - - def to_xml(self): - inner_text = [] - for rule in self: - inner_text.append(rule.to_xml()) - return tag('RoutingRules', '\n'.join(inner_text)) - - -class RoutingRule(object): - """Represents a single routing rule. - - There are convenience methods to making creating rules - more concise:: - - rule = RoutingRule.when(key_prefix='foo/').then_redirect('example.com') - - :ivar condition: Describes condition that must be met for the - specified redirect to apply. - - :ivar redirect: Specifies redirect behavior. You can redirect requests to - another host, to another page, or with another protocol. In the event - of an error, you can can specify a different error code to return. - - """ - def __init__(self, condition=None, redirect=None): - self.condition = condition - self.redirect = redirect - - def startElement(self, name, attrs, connection): - if name == 'Condition': - return self.condition - elif name == 'Redirect': - return self.redirect - - def endElement(self, name, value, connection): - pass - - def to_xml(self): - parts = [] - if self.condition: - parts.append(self.condition.to_xml()) - if self.redirect: - parts.append(self.redirect.to_xml()) - return tag('RoutingRule', '\n'.join(parts)) - - @classmethod - def when(cls, key_prefix=None, http_error_code=None): - return cls(Condition(key_prefix=key_prefix, - http_error_code=http_error_code), None) - - def then_redirect(self, hostname=None, protocol=None, replace_key=None, - replace_key_prefix=None, http_redirect_code=None): - self.redirect = Redirect( - hostname=hostname, protocol=protocol, - replace_key=replace_key, - replace_key_prefix=replace_key_prefix, - http_redirect_code=http_redirect_code) - return self - - -class Condition(_XMLKeyValue): - """ - :ivar key_prefix: The object key name prefix when the redirect is applied. - For example, to redirect requests for ExamplePage.html, the key prefix - will be ExamplePage.html. To redirect request for all pages with the - prefix docs/, the key prefix will be /docs, which identifies all - objects in the docs/ folder. - - :ivar http_error_code: The HTTP error code when the redirect is applied. In - the event of an error, if the error code equals this value, then the - specified redirect is applied. - - """ - TRANSLATOR = [ - ('KeyPrefixEquals', 'key_prefix'), - ('HttpErrorCodeReturnedEquals', 'http_error_code'), - ] - - def __init__(self, key_prefix=None, http_error_code=None): - self.key_prefix = key_prefix - self.http_error_code = http_error_code - super(Condition, self).__init__(self.TRANSLATOR) - - def to_xml(self): - return tag('Condition', super(Condition, self).to_xml()) - - -class Redirect(_XMLKeyValue): - """ - :ivar hostname: The host name to use in the redirect request. - - :ivar protocol: The protocol to use in the redirect request. Can be either - 'http' or 'https'. - - :ivar replace_key: The specific object key to use in the redirect request. - For example, redirect request to error.html. - - :ivar replace_key_prefix: The object key prefix to use in the redirect - request. For example, to redirect requests for all pages with prefix - docs/ (objects in the docs/ folder) to documents/, you can set a - condition block with KeyPrefixEquals set to docs/ and in the Redirect - set ReplaceKeyPrefixWith to /documents. - - :ivar http_redirect_code: The HTTP redirect code to use on the response. - - """ - - TRANSLATOR = [ - ('Protocol', 'protocol'), - ('HostName', 'hostname'), - ('ReplaceKeyWith', 'replace_key'), - ('ReplaceKeyPrefixWith', 'replace_key_prefix'), - ('HttpRedirectCode', 'http_redirect_code'), - ] - - def __init__(self, hostname=None, protocol=None, replace_key=None, - replace_key_prefix=None, http_redirect_code=None): - self.hostname = hostname - self.protocol = protocol - self.replace_key = replace_key - self.replace_key_prefix = replace_key_prefix - self.http_redirect_code = http_redirect_code - super(Redirect, self).__init__(self.TRANSLATOR) - - def to_xml(self): - return tag('Redirect', super(Redirect, self).to_xml()) - - diff --git a/awx/lib/site-packages/boto/sdb/__init__.py b/awx/lib/site-packages/boto/sdb/__init__.py deleted file mode 100644 index 1235a88a2e..0000000000 --- a/awx/lib/site-packages/boto/sdb/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.sdb.regioninfo import SDBRegionInfo -from boto.regioninfo import get_regions - - -def regions(): - """ - Get all available regions for the SDB service. - - :rtype: list - :return: A list of :class:`boto.sdb.regioninfo.RegionInfo` instances - """ - return get_regions( - 'sdb', - region_cls=SDBRegionInfo - ) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.sdb.connection.SDBConnection`. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.sdb.connection.SDBConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/sdb/connection.py b/awx/lib/site-packages/boto/sdb/connection.py deleted file mode 100644 index fa7cb83e3e..0000000000 --- a/awx/lib/site-packages/boto/sdb/connection.py +++ /dev/null @@ -1,618 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import xml.sax -import threading -import boto -from boto import handler -from boto.connection import AWSQueryConnection -from boto.sdb.domain import Domain, DomainMetaData -from boto.sdb.item import Item -from boto.sdb.regioninfo import SDBRegionInfo -from boto.exception import SDBResponseError - -class ItemThread(threading.Thread): - """ - A threaded :class:`Item <boto.sdb.item.Item>` retriever utility class. - Retrieved :class:`Item <boto.sdb.item.Item>` objects are stored in the - ``items`` instance variable after :py:meth:`run() <run>` is called. - - .. tip:: The item retrieval will not start until - the :func:`run() <boto.sdb.connection.ItemThread.run>` method is called. - """ - def __init__(self, name, domain_name, item_names): - """ - :param str name: A thread name. Used for identification. - :param str domain_name: The name of a SimpleDB - :class:`Domain <boto.sdb.domain.Domain>` - :type item_names: string or list of strings - :param item_names: The name(s) of the items to retrieve from the specified - :class:`Domain <boto.sdb.domain.Domain>`. - :ivar list items: A list of items retrieved. Starts as empty list. - """ - super(ItemThread, self).__init__(name=name) - #print 'starting %s with %d items' % (name, len(item_names)) - self.domain_name = domain_name - self.conn = SDBConnection() - self.item_names = item_names - self.items = [] - - def run(self): - """ - Start the threaded retrieval of items. Populates the - ``items`` list with :class:`Item <boto.sdb.item.Item>` objects. - """ - for item_name in self.item_names: - item = self.conn.get_attributes(self.domain_name, item_name) - self.items.append(item) - -#boto.set_stream_logger('sdb') - -class SDBConnection(AWSQueryConnection): - """ - This class serves as a gateway to your SimpleDB region (defaults to - us-east-1). Methods within allow access to SimpleDB - :class:`Domain <boto.sdb.domain.Domain>` objects and their associated - :class:`Item <boto.sdb.item.Item>` objects. - - .. tip:: - While you may instantiate this class directly, it may be easier to - go through :py:func:`boto.connect_sdb`. - """ - DefaultRegionName = 'us-east-1' - DefaultRegionEndpoint = 'sdb.us-east-1.amazonaws.com' - APIVersion = '2009-04-15' - ResponseError = SDBResponseError - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - converter=None, security_token=None, validate_certs=True, - profile_name=None): - """ - For any keywords that aren't documented, refer to the parent class, - :py:class:`boto.connection.AWSAuthConnection`. You can avoid having - to worry about these keyword arguments by instantiating these objects - via :py:func:`boto.connect_sdb`. - - :type region: :class:`boto.sdb.regioninfo.SDBRegionInfo` - :keyword region: Explicitly specify a region. Defaults to ``us-east-1`` - if not specified. You may also specify the region in your ``boto.cfg``: - - .. code-block:: cfg - - [SDB] - region = eu-west-1 - - """ - if not region: - region_name = boto.config.get('SDB', 'region', self.DefaultRegionName) - for reg in boto.sdb.regions(): - if reg.name == region_name: - region = reg - break - - self.region = region - super(SDBConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, - proxy_port, proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - self.box_usage = 0.0 - self.converter = converter - self.item_cls = Item - - def _required_auth_capability(self): - return ['sdb'] - - def set_item_cls(self, cls): - """ - While the default item class is :py:class:`boto.sdb.item.Item`, this - default may be overridden. Use this method to change a connection's - item class. - - :param object cls: The new class to set as this connection's item - class. See the default item class for inspiration as to what your - replacement should/could look like. - """ - self.item_cls = cls - - def _build_name_value_list(self, params, attributes, replace=False, - label='Attribute'): - keys = sorted(attributes.keys()) - i = 1 - for key in keys: - value = attributes[key] - if isinstance(value, list): - for v in value: - params['%s.%d.Name' % (label, i)] = key - if self.converter: - v = self.converter.encode(v) - params['%s.%d.Value' % (label, i)] = v - if replace: - params['%s.%d.Replace' % (label, i)] = 'true' - i += 1 - else: - params['%s.%d.Name' % (label, i)] = key - if self.converter: - value = self.converter.encode(value) - params['%s.%d.Value' % (label, i)] = value - if replace: - params['%s.%d.Replace' % (label, i)] = 'true' - i += 1 - - def _build_expected_value(self, params, expected_value): - params['Expected.1.Name'] = expected_value[0] - if expected_value[1] is True: - params['Expected.1.Exists'] = 'true' - elif expected_value[1] is False: - params['Expected.1.Exists'] = 'false' - else: - params['Expected.1.Value'] = expected_value[1] - - def _build_batch_list(self, params, items, replace=False): - item_names = items.keys() - i = 0 - for item_name in item_names: - params['Item.%d.ItemName' % i] = item_name - j = 0 - item = items[item_name] - if item is not None: - attr_names = item.keys() - for attr_name in attr_names: - value = item[attr_name] - if isinstance(value, list): - for v in value: - if self.converter: - v = self.converter.encode(v) - params['Item.%d.Attribute.%d.Name' % (i, j)] = attr_name - params['Item.%d.Attribute.%d.Value' % (i, j)] = v - if replace: - params['Item.%d.Attribute.%d.Replace' % (i, j)] = 'true' - j += 1 - else: - params['Item.%d.Attribute.%d.Name' % (i, j)] = attr_name - if self.converter: - value = self.converter.encode(value) - params['Item.%d.Attribute.%d.Value' % (i, j)] = value - if replace: - params['Item.%d.Attribute.%d.Replace' % (i, j)] = 'true' - j += 1 - i += 1 - - def _build_name_list(self, params, attribute_names): - i = 1 - attribute_names.sort() - for name in attribute_names: - params['Attribute.%d.Name' % i] = name - i += 1 - - def get_usage(self): - """ - Returns the BoxUsage (in USD) accumulated on this specific SDBConnection - instance. - - .. tip:: This can be out of date, and should only be treated as a - rough estimate. Also note that this estimate only applies to the - requests made on this specific connection instance. It is by - no means an account-wide estimate. - - :rtype: float - :return: The accumulated BoxUsage of all requests made on the connection. - """ - return self.box_usage - - def print_usage(self): - """ - Print the BoxUsage and approximate costs of all requests made on - this specific SDBConnection instance. - - .. tip:: This can be out of date, and should only be treated as a - rough estimate. Also note that this estimate only applies to the - requests made on this specific connection instance. It is by - no means an account-wide estimate. - """ - print('Total Usage: %f compute seconds' % self.box_usage) - cost = self.box_usage * 0.14 - print('Approximate Cost: $%f' % cost) - - def get_domain(self, domain_name, validate=True): - """ - Retrieves a :py:class:`boto.sdb.domain.Domain` object whose name - matches ``domain_name``. - - :param str domain_name: The name of the domain to retrieve - :keyword bool validate: When ``True``, check to see if the domain - actually exists. If ``False``, blindly return a - :py:class:`Domain <boto.sdb.domain.Domain>` object with the - specified name set. - - :raises: - :py:class:`boto.exception.SDBResponseError` if ``validate`` is - ``True`` and no match could be found. - - :rtype: :py:class:`boto.sdb.domain.Domain` - :return: The requested domain - """ - domain = Domain(self, domain_name) - if validate: - self.select(domain, """select * from `%s` limit 1""" % domain_name) - return domain - - def lookup(self, domain_name, validate=True): - """ - Lookup an existing SimpleDB domain. This differs from - :py:meth:`get_domain` in that ``None`` is returned if ``validate`` is - ``True`` and no match was found (instead of raising an exception). - - :param str domain_name: The name of the domain to retrieve - - :param bool validate: If ``True``, a ``None`` value will be returned - if the specified domain can't be found. If ``False``, a - :py:class:`Domain <boto.sdb.domain.Domain>` object will be dumbly - returned, regardless of whether it actually exists. - - :rtype: :class:`boto.sdb.domain.Domain` object or ``None`` - :return: The Domain object or ``None`` if the domain does not exist. - """ - try: - domain = self.get_domain(domain_name, validate) - except: - domain = None - return domain - - def get_all_domains(self, max_domains=None, next_token=None): - """ - Returns a :py:class:`boto.resultset.ResultSet` containing - all :py:class:`boto.sdb.domain.Domain` objects associated with - this connection's Access Key ID. - - :keyword int max_domains: Limit the returned - :py:class:`ResultSet <boto.resultset.ResultSet>` to the specified - number of members. - :keyword str next_token: A token string that was returned in an - earlier call to this method as the ``next_token`` attribute - on the returned :py:class:`ResultSet <boto.resultset.ResultSet>` - object. This attribute is set if there are more than Domains than - the value specified in the ``max_domains`` keyword. Pass the - ``next_token`` value from you earlier query in this keyword to - get the next 'page' of domains. - """ - params = {} - if max_domains: - params['MaxNumberOfDomains'] = max_domains - if next_token: - params['NextToken'] = next_token - return self.get_list('ListDomains', params, [('DomainName', Domain)]) - - def create_domain(self, domain_name): - """ - Create a SimpleDB domain. - - :type domain_name: string - :param domain_name: The name of the new domain - - :rtype: :class:`boto.sdb.domain.Domain` object - :return: The newly created domain - """ - params = {'DomainName': domain_name} - d = self.get_object('CreateDomain', params, Domain) - d.name = domain_name - return d - - def get_domain_and_name(self, domain_or_name): - """ - Given a ``str`` or :class:`boto.sdb.domain.Domain`, return a - ``tuple`` with the following members (in order): - - * In instance of :class:`boto.sdb.domain.Domain` for the requested - domain - * The domain's name as a ``str`` - - :type domain_or_name: ``str`` or :class:`boto.sdb.domain.Domain` - :param domain_or_name: The domain or domain name to get the domain - and name for. - - :raises: :class:`boto.exception.SDBResponseError` when an invalid - domain name is specified. - - :rtype: tuple - :return: A ``tuple`` with contents outlined as per above. - """ - if (isinstance(domain_or_name, Domain)): - return (domain_or_name, domain_or_name.name) - else: - return (self.get_domain(domain_or_name), domain_or_name) - - def delete_domain(self, domain_or_name): - """ - Delete a SimpleDB domain. - - .. caution:: This will delete the domain and all items within the domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object. - :param domain_or_name: Either the name of a domain or a Domain object - - :rtype: bool - :return: True if successful - - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'DomainName': domain_name} - return self.get_status('DeleteDomain', params) - - def domain_metadata(self, domain_or_name): - """ - Get the Metadata for a SimpleDB domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object. - :param domain_or_name: Either the name of a domain or a Domain object - - :rtype: :class:`boto.sdb.domain.DomainMetaData` object - :return: The newly created domain metadata object - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'DomainName': domain_name} - d = self.get_object('DomainMetadata', params, DomainMetaData) - d.domain = domain - return d - - def put_attributes(self, domain_or_name, item_name, attributes, - replace=True, expected_value=None): - """ - Store attributes for a given item in a domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object. - :param domain_or_name: Either the name of a domain or a Domain object - - :type item_name: string - :param item_name: The name of the item whose attributes are being - stored. - - :type attribute_names: dict or dict-like object - :param attribute_names: The name/value pairs to store as attributes - - :type expected_value: list - :param expected_value: If supplied, this is a list or tuple consisting - of a single attribute name and expected value. The list can be - of the form: - - * ['name', 'value'] - - In which case the call will first verify that the attribute "name" - of this item has a value of "value". If it does, the delete - will proceed, otherwise a ConditionalCheckFailed error will be - returned. The list can also be of the form: - - * ['name', True|False] - - which will simply check for the existence (True) or - non-existence (False) of the attribute. - - :type replace: bool - :param replace: Whether the attribute values passed in will replace - existing values or will be added as addition values. - Defaults to True. - - :rtype: bool - :return: True if successful - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'DomainName': domain_name, - 'ItemName': item_name} - self._build_name_value_list(params, attributes, replace) - if expected_value: - self._build_expected_value(params, expected_value) - return self.get_status('PutAttributes', params) - - def batch_put_attributes(self, domain_or_name, items, replace=True): - """ - Store attributes for multiple items in a domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object. - :param domain_or_name: Either the name of a domain or a Domain object - - :type items: dict or dict-like object - :param items: A dictionary-like object. The keys of the dictionary are - the item names and the values are themselves dictionaries - of attribute names/values, exactly the same as the - attribute_names parameter of the scalar put_attributes - call. - - :type replace: bool - :param replace: Whether the attribute values passed in will replace - existing values or will be added as addition values. - Defaults to True. - - :rtype: bool - :return: True if successful - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'DomainName': domain_name} - self._build_batch_list(params, items, replace) - return self.get_status('BatchPutAttributes', params, verb='POST') - - def get_attributes(self, domain_or_name, item_name, attribute_names=None, - consistent_read=False, item=None): - """ - Retrieve attributes for a given item in a domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object. - :param domain_or_name: Either the name of a domain or a Domain object - - :type item_name: string - :param item_name: The name of the item whose attributes are - being retrieved. - - :type attribute_names: string or list of strings - :param attribute_names: An attribute name or list of attribute names. - This parameter is optional. If not supplied, all attributes will - be retrieved for the item. - - :type consistent_read: bool - :param consistent_read: When set to true, ensures that the most recent - data is returned. - - :type item: :class:`boto.sdb.item.Item` - :keyword item: Instead of instantiating a new Item object, you may - specify one to update. - - :rtype: :class:`boto.sdb.item.Item` - :return: An Item with the requested attribute name/values set on it - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'DomainName': domain_name, - 'ItemName': item_name} - if consistent_read: - params['ConsistentRead'] = 'true' - if attribute_names: - if not isinstance(attribute_names, list): - attribute_names = [attribute_names] - self.build_list_params(params, attribute_names, 'AttributeName') - response = self.make_request('GetAttributes', params) - body = response.read() - if response.status == 200: - if item is None: - item = self.item_cls(domain, item_name) - h = handler.XmlHandler(item, self) - xml.sax.parseString(body, h) - return item - else: - raise SDBResponseError(response.status, response.reason, body) - - def delete_attributes(self, domain_or_name, item_name, attr_names=None, - expected_value=None): - """ - Delete attributes from a given item in a domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object. - :param domain_or_name: Either the name of a domain or a Domain object - - :type item_name: string - :param item_name: The name of the item whose attributes are being - deleted. - - :type attributes: dict, list or :class:`boto.sdb.item.Item` - :param attributes: Either a list containing attribute names which - will cause all values associated with that attribute - name to be deleted or a dict or Item containing the - attribute names and keys and list of values to - delete as the value. If no value is supplied, - all attribute name/values for the item will be - deleted. - - :type expected_value: list - :param expected_value: If supplied, this is a list or tuple consisting - of a single attribute name and expected value. The list can be - of the form: - - * ['name', 'value'] - - In which case the call will first verify that the attribute "name" - of this item has a value of "value". If it does, the delete - will proceed, otherwise a ConditionalCheckFailed error will be - returned. The list can also be of the form: - - * ['name', True|False] - - which will simply check for the existence (True) or - non-existence (False) of the attribute. - - :rtype: bool - :return: True if successful - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'DomainName': domain_name, - 'ItemName': item_name} - if attr_names: - if isinstance(attr_names, list): - self._build_name_list(params, attr_names) - elif isinstance(attr_names, dict) or isinstance(attr_names, self.item_cls): - self._build_name_value_list(params, attr_names) - if expected_value: - self._build_expected_value(params, expected_value) - return self.get_status('DeleteAttributes', params) - - def batch_delete_attributes(self, domain_or_name, items): - """ - Delete multiple items in a domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object. - :param domain_or_name: Either the name of a domain or a Domain object - - :type items: dict or dict-like object - :param items: A dictionary-like object. The keys of the dictionary are - the item names and the values are either: - - * dictionaries of attribute names/values, exactly the - same as the attribute_names parameter of the scalar - put_attributes call. The attribute name/value pairs - will only be deleted if they match the name/value - pairs passed in. - * None which means that all attributes associated - with the item should be deleted. - - :return: True if successful - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'DomainName': domain_name} - self._build_batch_list(params, items, False) - return self.get_status('BatchDeleteAttributes', params, verb='POST') - - def select(self, domain_or_name, query='', next_token=None, - consistent_read=False): - """ - Returns a set of Attributes for item names within domain_name that - match the query. The query must be expressed in using the SELECT - style syntax rather than the original SimpleDB query language. - Even though the select request does not require a domain object, - a domain object must be passed into this method so the Item objects - returned can point to the appropriate domain. - - :type domain_or_name: string or :class:`boto.sdb.domain.Domain` object - :param domain_or_name: Either the name of a domain or a Domain object - - :type query: string - :param query: The SimpleDB query to be performed. - - :type consistent_read: bool - :param consistent_read: When set to true, ensures that the most recent - data is returned. - - :rtype: ResultSet - :return: An iterator containing the results. - """ - domain, domain_name = self.get_domain_and_name(domain_or_name) - params = {'SelectExpression': query} - if consistent_read: - params['ConsistentRead'] = 'true' - if next_token: - params['NextToken'] = next_token - try: - return self.get_list('Select', params, [('Item', self.item_cls)], - parent=domain) - except SDBResponseError as e: - e.body = "Query: %s\n%s" % (query, e.body) - raise e diff --git a/awx/lib/site-packages/boto/sdb/db/__init__.py b/awx/lib/site-packages/boto/sdb/db/__init__.py deleted file mode 100644 index 71f6b7b738..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. diff --git a/awx/lib/site-packages/boto/sdb/db/blob.py b/awx/lib/site-packages/boto/sdb/db/blob.py deleted file mode 100644 index 6c286ec379..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/blob.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.compat import six - - -class Blob(object): - """Blob object""" - def __init__(self, value=None, file=None, id=None): - self._file = file - self.id = id - self.value = value - - @property - def file(self): - from StringIO import StringIO - if self._file: - f = self._file - else: - f = StringIO(self.value) - return f - - def __str__(self): - return six.text_type(self).encode('utf-8') - - def __unicode__(self): - if hasattr(self.file, "get_contents_as_string"): - value = self.file.get_contents_as_string() - else: - value = self.file.getvalue() - if isinstance(value, six.text_type): - return value - else: - return value.decode('utf-8') - - def read(self): - if hasattr(self.file, "get_contents_as_string"): - return self.file.get_contents_as_string() - else: - return self.file.read() - - def readline(self): - return self.file.readline() - - def next(self): - return next(self.file) - - def __iter__(self): - return iter(self.file) - - @property - def size(self): - if self._file: - return self._file.size - elif self.value: - return len(self.value) - else: - return 0 diff --git a/awx/lib/site-packages/boto/sdb/db/key.py b/awx/lib/site-packages/boto/sdb/db/key.py deleted file mode 100644 index 42f6bc9b3a..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/key.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class Key(object): - - @classmethod - def from_path(cls, *args, **kwds): - raise NotImplementedError("Paths are not currently supported") - - def __init__(self, encoded=None, obj=None): - self.name = None - if obj: - self.id = obj.id - self.kind = obj.kind() - else: - self.id = None - self.kind = None - - def app(self): - raise NotImplementedError("Applications are not currently supported") - - def kind(self): - return self.kind - - def id(self): - return self.id - - def name(self): - raise NotImplementedError("Key Names are not currently supported") - - def id_or_name(self): - return self.id - - def has_id_or_name(self): - return self.id is not None - - def parent(self): - raise NotImplementedError("Key parents are not currently supported") - - def __str__(self): - return self.id_or_name() diff --git a/awx/lib/site-packages/boto/sdb/db/manager/__init__.py b/awx/lib/site-packages/boto/sdb/db/manager/__init__.py deleted file mode 100644 index ded1716cbb..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/manager/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import boto - - -def get_manager(cls): - """ - Returns the appropriate Manager class for a given Model class. It - does this by looking in the boto config for a section like this:: - - [DB] - db_type = SimpleDB - db_user = <aws access key id> - db_passwd = <aws secret access key> - db_name = my_domain - [DB_TestBasic] - db_type = SimpleDB - db_user = <another aws access key id> - db_passwd = <another aws secret access key> - db_name = basic_domain - db_port = 1111 - - The values in the DB section are "generic values" that will be used - if nothing more specific is found. You can also create a section for - a specific Model class that gives the db info for that class. - In the example above, TestBasic is a Model subclass. - """ - db_user = boto.config.get('DB', 'db_user', None) - db_passwd = boto.config.get('DB', 'db_passwd', None) - db_type = boto.config.get('DB', 'db_type', 'SimpleDB') - db_name = boto.config.get('DB', 'db_name', None) - db_table = boto.config.get('DB', 'db_table', None) - db_host = boto.config.get('DB', 'db_host', "sdb.amazonaws.com") - db_port = boto.config.getint('DB', 'db_port', 443) - enable_ssl = boto.config.getbool('DB', 'enable_ssl', True) - sql_dir = boto.config.get('DB', 'sql_dir', None) - debug = boto.config.getint('DB', 'debug', 0) - # first see if there is a fully qualified section name in the Boto config - module_name = cls.__module__.replace('.', '_') - db_section = 'DB_' + module_name + '_' + cls.__name__ - if not boto.config.has_section(db_section): - db_section = 'DB_' + cls.__name__ - if boto.config.has_section(db_section): - db_user = boto.config.get(db_section, 'db_user', db_user) - db_passwd = boto.config.get(db_section, 'db_passwd', db_passwd) - db_type = boto.config.get(db_section, 'db_type', db_type) - db_name = boto.config.get(db_section, 'db_name', db_name) - db_table = boto.config.get(db_section, 'db_table', db_table) - db_host = boto.config.get(db_section, 'db_host', db_host) - db_port = boto.config.getint(db_section, 'db_port', db_port) - enable_ssl = boto.config.getint(db_section, 'enable_ssl', enable_ssl) - debug = boto.config.getint(db_section, 'debug', debug) - elif hasattr(cls, "_db_name") and cls._db_name is not None: - # More specific then the generic DB config is any _db_name class property - db_name = cls._db_name - elif hasattr(cls.__bases__[0], "_manager"): - return cls.__bases__[0]._manager - if db_type == 'SimpleDB': - from boto.sdb.db.manager.sdbmanager import SDBManager - return SDBManager(cls, db_name, db_user, db_passwd, - db_host, db_port, db_table, sql_dir, enable_ssl) - elif db_type == 'XML': - from boto.sdb.db.manager.xmlmanager import XMLManager - return XMLManager(cls, db_name, db_user, db_passwd, - db_host, db_port, db_table, sql_dir, enable_ssl) - else: - raise ValueError('Unknown db_type: %s' % db_type) diff --git a/awx/lib/site-packages/boto/sdb/db/manager/sdbmanager.py b/awx/lib/site-packages/boto/sdb/db/manager/sdbmanager.py deleted file mode 100644 index d964d07a2d..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/manager/sdbmanager.py +++ /dev/null @@ -1,738 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import boto -import re -from boto.utils import find_class -import uuid -from boto.sdb.db.key import Key -from boto.sdb.db.blob import Blob -from boto.sdb.db.property import ListProperty, MapProperty -from datetime import datetime, date, time -from boto.exception import SDBPersistenceError, S3ResponseError -from boto.compat import map, six, long_type - -ISO8601 = '%Y-%m-%dT%H:%M:%SZ' - - -class TimeDecodeError(Exception): - pass - - -class SDBConverter(object): - """ - Responsible for converting base Python types to format compatible - with underlying database. For SimpleDB, that means everything - needs to be converted to a string when stored in SimpleDB and from - a string when retrieved. - - To convert a value, pass it to the encode or decode method. The - encode method will take a Python native value and convert to DB - format. The decode method will take a DB format value and convert - it to Python native format. To find the appropriate method to - call, the generic encode/decode methods will look for the - type-specific method by searching for a method - called"encode_<type name>" or "decode_<type name>". - """ - def __init__(self, manager): - # Do a delayed import to prevent possible circular import errors. - from boto.sdb.db.model import Model - self.model_class = Model - self.manager = manager - self.type_map = {bool: (self.encode_bool, self.decode_bool), - int: (self.encode_int, self.decode_int), - float: (self.encode_float, self.decode_float), - self.model_class: ( - self.encode_reference, self.decode_reference - ), - Key: (self.encode_reference, self.decode_reference), - datetime: (self.encode_datetime, self.decode_datetime), - date: (self.encode_date, self.decode_date), - time: (self.encode_time, self.decode_time), - Blob: (self.encode_blob, self.decode_blob), - str: (self.encode_string, self.decode_string), - } - if six.PY2: - self.type_map[long] = (self.encode_long, self.decode_long) - - def encode(self, item_type, value): - try: - if self.model_class in item_type.mro(): - item_type = self.model_class - except: - pass - if item_type in self.type_map: - encode = self.type_map[item_type][0] - return encode(value) - return value - - def decode(self, item_type, value): - if item_type in self.type_map: - decode = self.type_map[item_type][1] - return decode(value) - return value - - def encode_list(self, prop, value): - if value in (None, []): - return [] - if not isinstance(value, list): - # This is a little trick to avoid encoding when it's just a single value, - # since that most likely means it's from a query - item_type = getattr(prop, "item_type") - return self.encode(item_type, value) - # Just enumerate(value) won't work here because - # we need to add in some zero padding - # We support lists up to 1,000 attributes, since - # SDB technically only supports 1024 attributes anyway - values = {} - for k, v in enumerate(value): - values["%03d" % k] = v - return self.encode_map(prop, values) - - def encode_map(self, prop, value): - import urllib - if value is None: - return None - if not isinstance(value, dict): - raise ValueError('Expected a dict value, got %s' % type(value)) - new_value = [] - for key in value: - item_type = getattr(prop, "item_type") - if self.model_class in item_type.mro(): - item_type = self.model_class - encoded_value = self.encode(item_type, value[key]) - if encoded_value is not None: - new_value.append('%s:%s' % (urllib.quote(key), encoded_value)) - return new_value - - def encode_prop(self, prop, value): - if isinstance(prop, ListProperty): - return self.encode_list(prop, value) - elif isinstance(prop, MapProperty): - return self.encode_map(prop, value) - else: - return self.encode(prop.data_type, value) - - def decode_list(self, prop, value): - if not isinstance(value, list): - value = [value] - if hasattr(prop, 'item_type'): - item_type = getattr(prop, "item_type") - dec_val = {} - for val in value: - if val is not None: - k, v = self.decode_map_element(item_type, val) - try: - k = int(k) - except: - k = v - dec_val[k] = v - value = dec_val.values() - return value - - def decode_map(self, prop, value): - if not isinstance(value, list): - value = [value] - ret_value = {} - item_type = getattr(prop, "item_type") - for val in value: - k, v = self.decode_map_element(item_type, val) - ret_value[k] = v - return ret_value - - def decode_map_element(self, item_type, value): - """Decode a single element for a map""" - import urllib - key = value - if ":" in value: - key, value = value.split(':', 1) - key = urllib.unquote(key) - if self.model_class in item_type.mro(): - value = item_type(id=value) - else: - value = self.decode(item_type, value) - return (key, value) - - def decode_prop(self, prop, value): - if isinstance(prop, ListProperty): - return self.decode_list(prop, value) - elif isinstance(prop, MapProperty): - return self.decode_map(prop, value) - else: - return self.decode(prop.data_type, value) - - def encode_int(self, value): - value = int(value) - value += 2147483648 - return '%010d' % value - - def decode_int(self, value): - try: - value = int(value) - except: - boto.log.error("Error, %s is not an integer" % value) - value = 0 - value = int(value) - value -= 2147483648 - return int(value) - - def encode_long(self, value): - value = long_type(value) - value += 9223372036854775808 - return '%020d' % value - - def decode_long(self, value): - value = long_type(value) - value -= 9223372036854775808 - return value - - def encode_bool(self, value): - if value == True or str(value).lower() in ("true", "yes"): - return 'true' - else: - return 'false' - - def decode_bool(self, value): - if value.lower() == 'true': - return True - else: - return False - - def encode_float(self, value): - """ - See http://tools.ietf.org/html/draft-wood-ldapext-float-00. - """ - s = '%e' % value - l = s.split('e') - mantissa = l[0].ljust(18, '0') - exponent = l[1] - if value == 0.0: - case = '3' - exponent = '000' - elif mantissa[0] != '-' and exponent[0] == '+': - case = '5' - exponent = exponent[1:].rjust(3, '0') - elif mantissa[0] != '-' and exponent[0] == '-': - case = '4' - exponent = 999 + int(exponent) - exponent = '%03d' % exponent - elif mantissa[0] == '-' and exponent[0] == '-': - case = '2' - mantissa = '%f' % (10 + float(mantissa)) - mantissa = mantissa.ljust(18, '0') - exponent = exponent[1:].rjust(3, '0') - else: - case = '1' - mantissa = '%f' % (10 + float(mantissa)) - mantissa = mantissa.ljust(18, '0') - exponent = 999 - int(exponent) - exponent = '%03d' % exponent - return '%s %s %s' % (case, exponent, mantissa) - - def decode_float(self, value): - case = value[0] - exponent = value[2:5] - mantissa = value[6:] - if case == '3': - return 0.0 - elif case == '5': - pass - elif case == '4': - exponent = '%03d' % (int(exponent) - 999) - elif case == '2': - mantissa = '%f' % (float(mantissa) - 10) - exponent = '-' + exponent - else: - mantissa = '%f' % (float(mantissa) - 10) - exponent = '%03d' % abs((int(exponent) - 999)) - return float(mantissa + 'e' + exponent) - - def encode_datetime(self, value): - if isinstance(value, six.string_types): - return value - if isinstance(value, datetime): - return value.strftime(ISO8601) - else: - return value.isoformat() - - def decode_datetime(self, value): - """Handles both Dates and DateTime objects""" - if value is None: - return value - try: - if "T" in value: - if "." in value: - # Handle true "isoformat()" dates, which may have a microsecond on at the end of them - return datetime.strptime(value.split(".")[0], "%Y-%m-%dT%H:%M:%S") - else: - return datetime.strptime(value, ISO8601) - else: - value = value.split("-") - return date(int(value[0]), int(value[1]), int(value[2])) - except Exception: - return None - - def encode_date(self, value): - if isinstance(value, six.string_types): - return value - return value.isoformat() - - def decode_date(self, value): - try: - value = value.split("-") - return date(int(value[0]), int(value[1]), int(value[2])) - except: - return None - - encode_time = encode_date - - def decode_time(self, value): - """ converts strings in the form of HH:MM:SS.mmmmmm - (created by datetime.time.isoformat()) to - datetime.time objects. - - Timzone-aware strings ("HH:MM:SS.mmmmmm+HH:MM") won't - be handled right now and will raise TimeDecodeError. - """ - if '-' in value or '+' in value: - # TODO: Handle tzinfo - raise TimeDecodeError("Can't handle timezone aware objects: %r" % value) - tmp = value.split('.') - arg = map(int, tmp[0].split(':')) - if len(tmp) == 2: - arg.append(int(tmp[1])) - return time(*arg) - - def encode_reference(self, value): - if value in (None, 'None', '', ' '): - return None - if isinstance(value, six.string_types): - return value - else: - return value.id - - def decode_reference(self, value): - if not value or value == "None": - return None - return value - - def encode_blob(self, value): - if not value: - return None - if isinstance(value, six.string_types): - return value - - if not value.id: - bucket = self.manager.get_blob_bucket() - key = bucket.new_key(str(uuid.uuid4())) - value.id = "s3://%s/%s" % (key.bucket.name, key.name) - else: - match = re.match("^s3:\/\/([^\/]*)\/(.*)$", value.id) - if match: - s3 = self.manager.get_s3_connection() - bucket = s3.get_bucket(match.group(1), validate=False) - key = bucket.get_key(match.group(2)) - else: - raise SDBPersistenceError("Invalid Blob ID: %s" % value.id) - - if value.value is not None: - key.set_contents_from_string(value.value) - return value.id - - def decode_blob(self, value): - if not value: - return None - match = re.match("^s3:\/\/([^\/]*)\/(.*)$", value) - if match: - s3 = self.manager.get_s3_connection() - bucket = s3.get_bucket(match.group(1), validate=False) - try: - key = bucket.get_key(match.group(2)) - except S3ResponseError as e: - if e.reason != "Forbidden": - raise - return None - else: - return None - if key: - return Blob(file=key, id="s3://%s/%s" % (key.bucket.name, key.name)) - else: - return None - - def encode_string(self, value): - """Convert ASCII, Latin-1 or UTF-8 to pure Unicode""" - if not isinstance(value, str): - return value - try: - return six.text_type(value, 'utf-8') - except: - # really, this should throw an exception. - # in the interest of not breaking current - # systems, however: - arr = [] - for ch in value: - arr.append(six.unichr(ord(ch))) - return u"".join(arr) - - def decode_string(self, value): - """Decoding a string is really nothing, just - return the value as-is""" - return value - - -class SDBManager(object): - - def __init__(self, cls, db_name, db_user, db_passwd, - db_host, db_port, db_table, ddl_dir, enable_ssl, - consistent=None): - self.cls = cls - self.db_name = db_name - self.db_user = db_user - self.db_passwd = db_passwd - self.db_host = db_host - self.db_port = db_port - self.db_table = db_table - self.ddl_dir = ddl_dir - self.enable_ssl = enable_ssl - self.s3 = None - self.bucket = None - self.converter = SDBConverter(self) - self._sdb = None - self._domain = None - if consistent is None and hasattr(cls, "__consistent__"): - consistent = cls.__consistent__ - self.consistent = consistent - - @property - def sdb(self): - if self._sdb is None: - self._connect() - return self._sdb - - @property - def domain(self): - if self._domain is None: - self._connect() - return self._domain - - def _connect(self): - args = dict(aws_access_key_id=self.db_user, - aws_secret_access_key=self.db_passwd, - is_secure=self.enable_ssl) - try: - region = [x for x in boto.sdb.regions() if x.endpoint == self.db_host][0] - args['region'] = region - except IndexError: - pass - self._sdb = boto.connect_sdb(**args) - # This assumes that the domain has already been created - # It's much more efficient to do it this way rather than - # having this make a roundtrip each time to validate. - # The downside is that if the domain doesn't exist, it breaks - self._domain = self._sdb.lookup(self.db_name, validate=False) - if not self._domain: - self._domain = self._sdb.create_domain(self.db_name) - - def _object_lister(self, cls, query_lister): - for item in query_lister: - obj = self.get_object(cls, item.name, item) - if obj: - yield obj - - def encode_value(self, prop, value): - if value is None: - return None - if not prop: - return str(value) - return self.converter.encode_prop(prop, value) - - def decode_value(self, prop, value): - return self.converter.decode_prop(prop, value) - - def get_s3_connection(self): - if not self.s3: - self.s3 = boto.connect_s3(self.db_user, self.db_passwd) - return self.s3 - - def get_blob_bucket(self, bucket_name=None): - s3 = self.get_s3_connection() - bucket_name = "%s-%s" % (s3.aws_access_key_id, self.domain.name) - bucket_name = bucket_name.lower() - try: - self.bucket = s3.get_bucket(bucket_name) - except: - self.bucket = s3.create_bucket(bucket_name) - return self.bucket - - def load_object(self, obj): - if not obj._loaded: - a = self.domain.get_attributes(obj.id, consistent_read=self.consistent) - if '__type__' in a: - for prop in obj.properties(hidden=False): - if prop.name in a: - value = self.decode_value(prop, a[prop.name]) - value = prop.make_value_from_datastore(value) - try: - setattr(obj, prop.name, value) - except Exception as e: - boto.log.exception(e) - obj._loaded = True - - def get_object(self, cls, id, a=None): - obj = None - if not a: - a = self.domain.get_attributes(id, consistent_read=self.consistent) - if '__type__' in a: - if not cls or a['__type__'] != cls.__name__: - cls = find_class(a['__module__'], a['__type__']) - if cls: - params = {} - for prop in cls.properties(hidden=False): - if prop.name in a: - value = self.decode_value(prop, a[prop.name]) - value = prop.make_value_from_datastore(value) - params[prop.name] = value - obj = cls(id, **params) - obj._loaded = True - else: - s = '(%s) class %s.%s not found' % (id, a['__module__'], a['__type__']) - boto.log.info('sdbmanager: %s' % s) - return obj - - def get_object_from_id(self, id): - return self.get_object(None, id) - - def query(self, query): - query_str = "select * from `%s` %s" % (self.domain.name, self._build_filter_part(query.model_class, query.filters, query.sort_by, query.select)) - if query.limit: - query_str += " limit %s" % query.limit - rs = self.domain.select(query_str, max_items=query.limit, next_token=query.next_token) - query.rs = rs - return self._object_lister(query.model_class, rs) - - def count(self, cls, filters, quick=True, sort_by=None, select=None): - """ - Get the number of results that would - be returned in this query - """ - query = "select count(*) from `%s` %s" % (self.domain.name, self._build_filter_part(cls, filters, sort_by, select)) - count = 0 - for row in self.domain.select(query): - count += int(row['Count']) - if quick: - return count - return count - - def _build_filter(self, property, name, op, val): - if name == "__id__": - name = 'itemName()' - if name != "itemName()": - name = '`%s`' % name - if val is None: - if op in ('is', '='): - return "%(name)s is null" % {"name": name} - elif op in ('is not', '!='): - return "%s is not null" % name - else: - val = "" - if property.__class__ == ListProperty: - if op in ("is", "="): - op = "like" - elif op in ("!=", "not"): - op = "not like" - if not(op in ["like", "not like"] and val.startswith("%")): - val = "%%:%s" % val - return "%s %s '%s'" % (name, op, val.replace("'", "''")) - - def _build_filter_part(self, cls, filters, order_by=None, select=None): - """ - Build the filter part - """ - import types - query_parts = [] - - order_by_filtered = False - - if order_by: - if order_by[0] == "-": - order_by_method = "DESC" - order_by = order_by[1:] - else: - order_by_method = "ASC" - - if select: - if order_by and order_by in select: - order_by_filtered = True - query_parts.append("(%s)" % select) - - if isinstance(filters, six.string_types): - query = "WHERE %s AND `__type__` = '%s'" % (filters, cls.__name__) - if order_by in ["__id__", "itemName()"]: - query += " ORDER BY itemName() %s" % order_by_method - elif order_by is not None: - query += " ORDER BY `%s` %s" % (order_by, order_by_method) - return query - - for filter in filters: - filter_parts = [] - filter_props = filter[0] - if not isinstance(filter_props, list): - filter_props = [filter_props] - for filter_prop in filter_props: - (name, op) = filter_prop.strip().split(" ", 1) - value = filter[1] - property = cls.find_property(name) - if name == order_by: - order_by_filtered = True - if types.TypeType(value) == list: - filter_parts_sub = [] - for val in value: - val = self.encode_value(property, val) - if isinstance(val, list): - for v in val: - filter_parts_sub.append(self._build_filter(property, name, op, v)) - else: - filter_parts_sub.append(self._build_filter(property, name, op, val)) - filter_parts.append("(%s)" % (" OR ".join(filter_parts_sub))) - else: - val = self.encode_value(property, value) - if isinstance(val, list): - for v in val: - filter_parts.append(self._build_filter(property, name, op, v)) - else: - filter_parts.append(self._build_filter(property, name, op, val)) - query_parts.append("(%s)" % (" or ".join(filter_parts))) - - - type_query = "(`__type__` = '%s'" % cls.__name__ - for subclass in self._get_all_decendents(cls).keys(): - type_query += " or `__type__` = '%s'" % subclass - type_query += ")" - query_parts.append(type_query) - - order_by_query = "" - - if order_by: - if not order_by_filtered: - query_parts.append("`%s` LIKE '%%'" % order_by) - if order_by in ["__id__", "itemName()"]: - order_by_query = " ORDER BY itemName() %s" % order_by_method - else: - order_by_query = " ORDER BY `%s` %s" % (order_by, order_by_method) - - if len(query_parts) > 0: - return "WHERE %s %s" % (" AND ".join(query_parts), order_by_query) - else: - return "" - - - def _get_all_decendents(self, cls): - """Get all decendents for a given class""" - decendents = {} - for sc in cls.__sub_classes__: - decendents[sc.__name__] = sc - decendents.update(self._get_all_decendents(sc)) - return decendents - - def query_gql(self, query_string, *args, **kwds): - raise NotImplementedError("GQL queries not supported in SimpleDB") - - def save_object(self, obj, expected_value=None): - if not obj.id: - obj.id = str(uuid.uuid4()) - - attrs = {'__type__': obj.__class__.__name__, - '__module__': obj.__class__.__module__, - '__lineage__': obj.get_lineage()} - del_attrs = [] - for property in obj.properties(hidden=False): - value = property.get_value_for_datastore(obj) - if value is not None: - value = self.encode_value(property, value) - if value == []: - value = None - if value is None: - del_attrs.append(property.name) - continue - attrs[property.name] = value - if property.unique: - try: - args = {property.name: value} - obj2 = next(obj.find(**args)) - if obj2.id != obj.id: - raise SDBPersistenceError("Error: %s must be unique!" % property.name) - except(StopIteration): - pass - # Convert the Expected value to SDB format - if expected_value: - prop = obj.find_property(expected_value[0]) - v = expected_value[1] - if v is not None and not isinstance(v, bool): - v = self.encode_value(prop, v) - expected_value[1] = v - self.domain.put_attributes(obj.id, attrs, replace=True, expected_value=expected_value) - if len(del_attrs) > 0: - self.domain.delete_attributes(obj.id, del_attrs) - return obj - - def delete_object(self, obj): - self.domain.delete_attributes(obj.id) - - def set_property(self, prop, obj, name, value): - setattr(obj, name, value) - value = prop.get_value_for_datastore(obj) - value = self.encode_value(prop, value) - if prop.unique: - try: - args = {prop.name: value} - obj2 = next(obj.find(**args)) - if obj2.id != obj.id: - raise SDBPersistenceError("Error: %s must be unique!" % prop.name) - except(StopIteration): - pass - self.domain.put_attributes(obj.id, {name: value}, replace=True) - - def get_property(self, prop, obj, name): - a = self.domain.get_attributes(obj.id, consistent_read=self.consistent) - - # try to get the attribute value from SDB - if name in a: - value = self.decode_value(prop, a[name]) - value = prop.make_value_from_datastore(value) - setattr(obj, prop.name, value) - return value - raise AttributeError('%s not found' % name) - - def set_key_value(self, obj, name, value): - self.domain.put_attributes(obj.id, {name: value}, replace=True) - - def delete_key_value(self, obj, name): - self.domain.delete_attributes(obj.id, name) - - def get_key_value(self, obj, name): - a = self.domain.get_attributes(obj.id, name, consistent_read=self.consistent) - if name in a: - return a[name] - else: - return None - - def get_raw_item(self, obj): - return self.domain.get_item(obj.id) diff --git a/awx/lib/site-packages/boto/sdb/db/manager/xmlmanager.py b/awx/lib/site-packages/boto/sdb/db/manager/xmlmanager.py deleted file mode 100644 index f457347ad3..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/manager/xmlmanager.py +++ /dev/null @@ -1,517 +0,0 @@ -# Copyright (c) 2006-2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import boto -from boto.utils import find_class, Password -from boto.sdb.db.key import Key -from boto.sdb.db.model import Model -from boto.compat import six, encodebytes -from datetime import datetime -from xml.dom.minidom import getDOMImplementation, parse, parseString, Node - -ISO8601 = '%Y-%m-%dT%H:%M:%SZ' - -class XMLConverter(object): - """ - Responsible for converting base Python types to format compatible with underlying - database. For SimpleDB, that means everything needs to be converted to a string - when stored in SimpleDB and from a string when retrieved. - - To convert a value, pass it to the encode or decode method. The encode method - will take a Python native value and convert to DB format. The decode method will - take a DB format value and convert it to Python native format. To find the appropriate - method to call, the generic encode/decode methods will look for the type-specific - method by searching for a method called "encode_<type name>" or "decode_<type name>". - """ - def __init__(self, manager): - self.manager = manager - self.type_map = { bool : (self.encode_bool, self.decode_bool), - int : (self.encode_int, self.decode_int), - Model : (self.encode_reference, self.decode_reference), - Key : (self.encode_reference, self.decode_reference), - Password : (self.encode_password, self.decode_password), - datetime : (self.encode_datetime, self.decode_datetime)} - if six.PY2: - self.type_map[long] = (self.encode_long, self.decode_long) - - def get_text_value(self, parent_node): - value = '' - for node in parent_node.childNodes: - if node.nodeType == node.TEXT_NODE: - value += node.data - return value - - def encode(self, item_type, value): - if item_type in self.type_map: - encode = self.type_map[item_type][0] - return encode(value) - return value - - def decode(self, item_type, value): - if item_type in self.type_map: - decode = self.type_map[item_type][1] - return decode(value) - else: - value = self.get_text_value(value) - return value - - def encode_prop(self, prop, value): - if isinstance(value, list): - if hasattr(prop, 'item_type'): - new_value = [] - for v in value: - item_type = getattr(prop, "item_type") - if Model in item_type.mro(): - item_type = Model - new_value.append(self.encode(item_type, v)) - return new_value - else: - return value - else: - return self.encode(prop.data_type, value) - - def decode_prop(self, prop, value): - if prop.data_type == list: - if hasattr(prop, 'item_type'): - item_type = getattr(prop, "item_type") - if Model in item_type.mro(): - item_type = Model - values = [] - for item_node in value.getElementsByTagName('item'): - value = self.decode(item_type, item_node) - values.append(value) - return values - else: - return self.get_text_value(value) - else: - return self.decode(prop.data_type, value) - - def encode_int(self, value): - value = int(value) - return '%d' % value - - def decode_int(self, value): - value = self.get_text_value(value) - if value: - value = int(value) - else: - value = None - return value - - def encode_long(self, value): - value = long(value) - return '%d' % value - - def decode_long(self, value): - value = self.get_text_value(value) - return long(value) - - def encode_bool(self, value): - if value == True: - return 'true' - else: - return 'false' - - def decode_bool(self, value): - value = self.get_text_value(value) - if value.lower() == 'true': - return True - else: - return False - - def encode_datetime(self, value): - return value.strftime(ISO8601) - - def decode_datetime(self, value): - value = self.get_text_value(value) - try: - return datetime.strptime(value, ISO8601) - except: - return None - - def encode_reference(self, value): - if isinstance(value, six.string_types): - return value - if value is None: - return '' - else: - val_node = self.manager.doc.createElement("object") - val_node.setAttribute('id', value.id) - val_node.setAttribute('class', '%s.%s' % (value.__class__.__module__, value.__class__.__name__)) - return val_node - - def decode_reference(self, value): - if not value: - return None - try: - value = value.childNodes[0] - class_name = value.getAttribute("class") - id = value.getAttribute("id") - cls = find_class(class_name) - return cls.get_by_ids(id) - except: - return None - - def encode_password(self, value): - if value and len(value) > 0: - return str(value) - else: - return None - - def decode_password(self, value): - value = self.get_text_value(value) - return Password(value) - - -class XMLManager(object): - - def __init__(self, cls, db_name, db_user, db_passwd, - db_host, db_port, db_table, ddl_dir, enable_ssl): - self.cls = cls - if not db_name: - db_name = cls.__name__.lower() - self.db_name = db_name - self.db_user = db_user - self.db_passwd = db_passwd - self.db_host = db_host - self.db_port = db_port - self.db_table = db_table - self.ddl_dir = ddl_dir - self.s3 = None - self.converter = XMLConverter(self) - self.impl = getDOMImplementation() - self.doc = self.impl.createDocument(None, 'objects', None) - - self.connection = None - self.enable_ssl = enable_ssl - self.auth_header = None - if self.db_user: - base64string = encodebytes('%s:%s' % (self.db_user, self.db_passwd))[:-1] - authheader = "Basic %s" % base64string - self.auth_header = authheader - - def _connect(self): - if self.db_host: - if self.enable_ssl: - from httplib import HTTPSConnection as Connection - else: - from httplib import HTTPConnection as Connection - - self.connection = Connection(self.db_host, self.db_port) - - def _make_request(self, method, url, post_data=None, body=None): - """ - Make a request on this connection - """ - if not self.connection: - self._connect() - try: - self.connection.close() - except: - pass - self.connection.connect() - headers = {} - if self.auth_header: - headers["Authorization"] = self.auth_header - self.connection.request(method, url, body, headers) - resp = self.connection.getresponse() - return resp - - def new_doc(self): - return self.impl.createDocument(None, 'objects', None) - - def _object_lister(self, cls, doc): - for obj_node in doc.getElementsByTagName('object'): - if not cls: - class_name = obj_node.getAttribute('class') - cls = find_class(class_name) - id = obj_node.getAttribute('id') - obj = cls(id) - for prop_node in obj_node.getElementsByTagName('property'): - prop_name = prop_node.getAttribute('name') - prop = obj.find_property(prop_name) - if prop: - if hasattr(prop, 'item_type'): - value = self.get_list(prop_node, prop.item_type) - else: - value = self.decode_value(prop, prop_node) - value = prop.make_value_from_datastore(value) - setattr(obj, prop.name, value) - yield obj - - def reset(self): - self._connect() - - def get_doc(self): - return self.doc - - def encode_value(self, prop, value): - return self.converter.encode_prop(prop, value) - - def decode_value(self, prop, value): - return self.converter.decode_prop(prop, value) - - def get_s3_connection(self): - if not self.s3: - self.s3 = boto.connect_s3(self.aws_access_key_id, self.aws_secret_access_key) - return self.s3 - - def get_list(self, prop_node, item_type): - values = [] - try: - items_node = prop_node.getElementsByTagName('items')[0] - except: - return [] - for item_node in items_node.getElementsByTagName('item'): - value = self.converter.decode(item_type, item_node) - values.append(value) - return values - - def get_object_from_doc(self, cls, id, doc): - obj_node = doc.getElementsByTagName('object')[0] - if not cls: - class_name = obj_node.getAttribute('class') - cls = find_class(class_name) - if not id: - id = obj_node.getAttribute('id') - obj = cls(id) - for prop_node in obj_node.getElementsByTagName('property'): - prop_name = prop_node.getAttribute('name') - prop = obj.find_property(prop_name) - value = self.decode_value(prop, prop_node) - value = prop.make_value_from_datastore(value) - if value is not None: - try: - setattr(obj, prop.name, value) - except: - pass - return obj - - def get_props_from_doc(self, cls, id, doc): - """ - Pull out the properties from this document - Returns the class, the properties in a hash, and the id if provided as a tuple - :return: (cls, props, id) - """ - obj_node = doc.getElementsByTagName('object')[0] - if not cls: - class_name = obj_node.getAttribute('class') - cls = find_class(class_name) - if not id: - id = obj_node.getAttribute('id') - props = {} - for prop_node in obj_node.getElementsByTagName('property'): - prop_name = prop_node.getAttribute('name') - prop = cls.find_property(prop_name) - value = self.decode_value(prop, prop_node) - value = prop.make_value_from_datastore(value) - if value is not None: - props[prop.name] = value - return (cls, props, id) - - - def get_object(self, cls, id): - if not self.connection: - self._connect() - - if not self.connection: - raise NotImplementedError("Can't query without a database connection") - url = "/%s/%s" % (self.db_name, id) - resp = self._make_request('GET', url) - if resp.status == 200: - doc = parse(resp) - else: - raise Exception("Error: %s" % resp.status) - return self.get_object_from_doc(cls, id, doc) - - def query(self, cls, filters, limit=None, order_by=None): - if not self.connection: - self._connect() - - if not self.connection: - raise NotImplementedError("Can't query without a database connection") - - from urllib import urlencode - - query = str(self._build_query(cls, filters, limit, order_by)) - if query: - url = "/%s?%s" % (self.db_name, urlencode({"query": query})) - else: - url = "/%s" % self.db_name - resp = self._make_request('GET', url) - if resp.status == 200: - doc = parse(resp) - else: - raise Exception("Error: %s" % resp.status) - return self._object_lister(cls, doc) - - def _build_query(self, cls, filters, limit, order_by): - import types - if len(filters) > 4: - raise Exception('Too many filters, max is 4') - parts = [] - properties = cls.properties(hidden=False) - for filter, value in filters: - name, op = filter.strip().split() - found = False - for property in properties: - if property.name == name: - found = True - if types.TypeType(value) == list: - filter_parts = [] - for val in value: - val = self.encode_value(property, val) - filter_parts.append("'%s' %s '%s'" % (name, op, val)) - parts.append("[%s]" % " OR ".join(filter_parts)) - else: - value = self.encode_value(property, value) - parts.append("['%s' %s '%s']" % (name, op, value)) - if not found: - raise Exception('%s is not a valid field' % name) - if order_by: - if order_by.startswith("-"): - key = order_by[1:] - type = "desc" - else: - key = order_by - type = "asc" - parts.append("['%s' starts-with ''] sort '%s' %s" % (key, key, type)) - return ' intersection '.join(parts) - - def query_gql(self, query_string, *args, **kwds): - raise NotImplementedError("GQL queries not supported in XML") - - def save_list(self, doc, items, prop_node): - items_node = doc.createElement('items') - prop_node.appendChild(items_node) - for item in items: - item_node = doc.createElement('item') - items_node.appendChild(item_node) - if isinstance(item, Node): - item_node.appendChild(item) - else: - text_node = doc.createTextNode(item) - item_node.appendChild(text_node) - - def save_object(self, obj, expected_value=None): - """ - Marshal the object and do a PUT - """ - doc = self.marshal_object(obj) - if obj.id: - url = "/%s/%s" % (self.db_name, obj.id) - else: - url = "/%s" % (self.db_name) - resp = self._make_request("PUT", url, body=doc.toxml()) - new_obj = self.get_object_from_doc(obj.__class__, None, parse(resp)) - obj.id = new_obj.id - for prop in obj.properties(): - try: - propname = prop.name - except AttributeError: - propname = None - if propname: - value = getattr(new_obj, prop.name) - if value: - setattr(obj, prop.name, value) - return obj - - - def marshal_object(self, obj, doc=None): - if not doc: - doc = self.new_doc() - if not doc: - doc = self.doc - obj_node = doc.createElement('object') - - if obj.id: - obj_node.setAttribute('id', obj.id) - - obj_node.setAttribute('class', '%s.%s' % (obj.__class__.__module__, - obj.__class__.__name__)) - root = doc.documentElement - root.appendChild(obj_node) - for property in obj.properties(hidden=False): - prop_node = doc.createElement('property') - prop_node.setAttribute('name', property.name) - prop_node.setAttribute('type', property.type_name) - value = property.get_value_for_datastore(obj) - if value is not None: - value = self.encode_value(property, value) - if isinstance(value, list): - self.save_list(doc, value, prop_node) - elif isinstance(value, Node): - prop_node.appendChild(value) - else: - text_node = doc.createTextNode(six.text_type(value).encode("ascii", "ignore")) - prop_node.appendChild(text_node) - obj_node.appendChild(prop_node) - - return doc - - def unmarshal_object(self, fp, cls=None, id=None): - if isinstance(fp, six.string_types): - doc = parseString(fp) - else: - doc = parse(fp) - return self.get_object_from_doc(cls, id, doc) - - def unmarshal_props(self, fp, cls=None, id=None): - """ - Same as unmarshalling an object, except it returns - from "get_props_from_doc" - """ - if isinstance(fp, six.string_types): - doc = parseString(fp) - else: - doc = parse(fp) - return self.get_props_from_doc(cls, id, doc) - - def delete_object(self, obj): - url = "/%s/%s" % (self.db_name, obj.id) - return self._make_request("DELETE", url) - - def set_key_value(self, obj, name, value): - self.domain.put_attributes(obj.id, {name: value}, replace=True) - - def delete_key_value(self, obj, name): - self.domain.delete_attributes(obj.id, name) - - def get_key_value(self, obj, name): - a = self.domain.get_attributes(obj.id, name) - if name in a: - return a[name] - else: - return None - - def get_raw_item(self, obj): - return self.domain.get_item(obj.id) - - def set_property(self, prop, obj, name, value): - pass - - def get_property(self, prop, obj, name): - pass - - def load_object(self, obj): - if not obj._loaded: - obj = obj.get_by_id(obj.id) - obj._loaded = True - return obj diff --git a/awx/lib/site-packages/boto/sdb/db/model.py b/awx/lib/site-packages/boto/sdb/db/model.py deleted file mode 100644 index 741ad43871..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/model.py +++ /dev/null @@ -1,296 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.sdb.db.property import Property -from boto.sdb.db.key import Key -from boto.sdb.db.query import Query -import boto -from boto.compat import filter - -class ModelMeta(type): - "Metaclass for all Models" - - def __init__(cls, name, bases, dict): - super(ModelMeta, cls).__init__(name, bases, dict) - # Make sure this is a subclass of Model - mainly copied from django ModelBase (thanks!) - cls.__sub_classes__ = [] - - # Do a delayed import to prevent possible circular import errors. - from boto.sdb.db.manager import get_manager - - try: - if filter(lambda b: issubclass(b, Model), bases): - for base in bases: - base.__sub_classes__.append(cls) - cls._manager = get_manager(cls) - # look for all of the Properties and set their names - for key in dict.keys(): - if isinstance(dict[key], Property): - property = dict[key] - property.__property_config__(cls, key) - prop_names = [] - props = cls.properties() - for prop in props: - if not prop.__class__.__name__.startswith('_'): - prop_names.append(prop.name) - setattr(cls, '_prop_names', prop_names) - except NameError: - # 'Model' isn't defined yet, meaning we're looking at our own - # Model class, defined below. - pass - -class Model(object): - __metaclass__ = ModelMeta - __consistent__ = False # Consistent is set off by default - id = None - - @classmethod - def get_lineage(cls): - l = [c.__name__ for c in cls.mro()] - l.reverse() - return '.'.join(l) - - @classmethod - def kind(cls): - return cls.__name__ - - @classmethod - def _get_by_id(cls, id, manager=None): - if not manager: - manager = cls._manager - return manager.get_object(cls, id) - - @classmethod - def get_by_id(cls, ids=None, parent=None): - if isinstance(ids, list): - objs = [cls._get_by_id(id) for id in ids] - return objs - else: - return cls._get_by_id(ids) - - get_by_ids = get_by_id - - @classmethod - def get_by_key_name(cls, key_names, parent=None): - raise NotImplementedError("Key Names are not currently supported") - - @classmethod - def find(cls, limit=None, next_token=None, **params): - q = Query(cls, limit=limit, next_token=next_token) - for key, value in params.items(): - q.filter('%s =' % key, value) - return q - - @classmethod - def all(cls, limit=None, next_token=None): - return cls.find(limit=limit, next_token=next_token) - - @classmethod - def get_or_insert(key_name, **kw): - raise NotImplementedError("get_or_insert not currently supported") - - @classmethod - def properties(cls, hidden=True): - properties = [] - while cls: - for key in cls.__dict__.keys(): - prop = cls.__dict__[key] - if isinstance(prop, Property): - if hidden or not prop.__class__.__name__.startswith('_'): - properties.append(prop) - if len(cls.__bases__) > 0: - cls = cls.__bases__[0] - else: - cls = None - return properties - - @classmethod - def find_property(cls, prop_name): - property = None - while cls: - for key in cls.__dict__.keys(): - prop = cls.__dict__[key] - if isinstance(prop, Property): - if not prop.__class__.__name__.startswith('_') and prop_name == prop.name: - property = prop - if len(cls.__bases__) > 0: - cls = cls.__bases__[0] - else: - cls = None - return property - - @classmethod - def get_xmlmanager(cls): - if not hasattr(cls, '_xmlmanager'): - from boto.sdb.db.manager.xmlmanager import XMLManager - cls._xmlmanager = XMLManager(cls, None, None, None, - None, None, None, None, False) - return cls._xmlmanager - - @classmethod - def from_xml(cls, fp): - xmlmanager = cls.get_xmlmanager() - return xmlmanager.unmarshal_object(fp) - - def __init__(self, id=None, **kw): - self._loaded = False - # first try to initialize all properties to their default values - for prop in self.properties(hidden=False): - try: - setattr(self, prop.name, prop.default_value()) - except ValueError: - pass - if 'manager' in kw: - self._manager = kw['manager'] - self.id = id - for key in kw: - if key != 'manager': - # We don't want any errors populating up when loading an object, - # so if it fails we just revert to it's default value - try: - setattr(self, key, kw[key]) - except Exception as e: - boto.log.exception(e) - - def __repr__(self): - return '%s<%s>' % (self.__class__.__name__, self.id) - - def __str__(self): - return str(self.id) - - def __eq__(self, other): - return other and isinstance(other, Model) and self.id == other.id - - def _get_raw_item(self): - return self._manager.get_raw_item(self) - - def load(self): - if self.id and not self._loaded: - self._manager.load_object(self) - - def reload(self): - if self.id: - self._loaded = False - self._manager.load_object(self) - - def put(self, expected_value=None): - """ - Save this object as it is, with an optional expected value - - :param expected_value: Optional tuple of Attribute, and Value that - must be the same in order to save this object. If this - condition is not met, an SDBResponseError will be raised with a - Confict status code. - :type expected_value: tuple or list - :return: This object - :rtype: :class:`boto.sdb.db.model.Model` - """ - self._manager.save_object(self, expected_value) - return self - - save = put - - def put_attributes(self, attrs): - """ - Save just these few attributes, not the whole object - - :param attrs: Attributes to save, key->value dict - :type attrs: dict - :return: self - :rtype: :class:`boto.sdb.db.model.Model` - """ - assert(isinstance(attrs, dict)), "Argument must be a dict of key->values to save" - for prop_name in attrs: - value = attrs[prop_name] - prop = self.find_property(prop_name) - assert(prop), "Property not found: %s" % prop_name - self._manager.set_property(prop, self, prop_name, value) - self.reload() - return self - - def delete_attributes(self, attrs): - """ - Delete just these attributes, not the whole object. - - :param attrs: Attributes to save, as a list of string names - :type attrs: list - :return: self - :rtype: :class:`boto.sdb.db.model.Model` - """ - assert(isinstance(attrs, list)), "Argument must be a list of names of keys to delete." - self._manager.domain.delete_attributes(self.id, attrs) - self.reload() - return self - - save_attributes = put_attributes - - def delete(self): - self._manager.delete_object(self) - - def key(self): - return Key(obj=self) - - def set_manager(self, manager): - self._manager = manager - - def to_dict(self): - props = {} - for prop in self.properties(hidden=False): - props[prop.name] = getattr(self, prop.name) - obj = {'properties': props, - 'id': self.id} - return {self.__class__.__name__: obj} - - def to_xml(self, doc=None): - xmlmanager = self.get_xmlmanager() - doc = xmlmanager.marshal_object(self, doc) - return doc - - @classmethod - def find_subclass(cls, name): - """Find a subclass with a given name""" - if name == cls.__name__: - return cls - for sc in cls.__sub_classes__: - r = sc.find_subclass(name) - if r is not None: - return r - -class Expando(Model): - - def __setattr__(self, name, value): - if name in self._prop_names: - object.__setattr__(self, name, value) - elif name.startswith('_'): - object.__setattr__(self, name, value) - elif name == 'id': - object.__setattr__(self, name, value) - else: - self._manager.set_key_value(self, name, value) - object.__setattr__(self, name, value) - - def __getattr__(self, name): - if not name.startswith('_'): - value = self._manager.get_key_value(self, name) - if value: - object.__setattr__(self, name, value) - return value - raise AttributeError diff --git a/awx/lib/site-packages/boto/sdb/db/property.py b/awx/lib/site-packages/boto/sdb/db/property.py deleted file mode 100644 index 575aa8924d..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/property.py +++ /dev/null @@ -1,704 +0,0 @@ -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import datetime -from boto.sdb.db.key import Key -from boto.utils import Password -from boto.sdb.db.query import Query -import re -import boto -import boto.s3.key -from boto.sdb.db.blob import Blob -from boto.compat import six, long_type - - -class Property(object): - - data_type = str - type_name = '' - name = '' - verbose_name = '' - - def __init__(self, verbose_name=None, name=None, default=None, - required=False, validator=None, choices=None, unique=False): - self.verbose_name = verbose_name - self.name = name - self.default = default - self.required = required - self.validator = validator - self.choices = choices - if self.name: - self.slot_name = '_' + self.name - else: - self.slot_name = '_' - self.unique = unique - - def __get__(self, obj, objtype): - if obj: - obj.load() - return getattr(obj, self.slot_name) - else: - return None - - def __set__(self, obj, value): - self.validate(value) - - # Fire off any on_set functions - try: - if obj._loaded and hasattr(obj, "on_set_%s" % self.name): - fnc = getattr(obj, "on_set_%s" % self.name) - value = fnc(value) - except Exception: - boto.log.exception("Exception running on_set_%s" % self.name) - - setattr(obj, self.slot_name, value) - - def __property_config__(self, model_class, property_name): - self.model_class = model_class - self.name = property_name - self.slot_name = '_' + self.name - - def default_validator(self, value): - if isinstance(value, six.string_types) or value == self.default_value(): - return - if not isinstance(value, self.data_type): - raise TypeError('Validation Error, %s.%s expecting %s, got %s' % (self.model_class.__name__, self.name, self.data_type, type(value))) - - def default_value(self): - return self.default - - def validate(self, value): - if self.required and value is None: - raise ValueError('%s is a required property' % self.name) - if self.choices and value and value not in self.choices: - raise ValueError('%s not a valid choice for %s.%s' % (value, self.model_class.__name__, self.name)) - if self.validator: - self.validator(value) - else: - self.default_validator(value) - return value - - def empty(self, value): - return not value - - def get_value_for_datastore(self, model_instance): - return getattr(model_instance, self.name) - - def make_value_from_datastore(self, value): - return value - - def get_choices(self): - if callable(self.choices): - return self.choices() - return self.choices - - -def validate_string(value): - if value is None: - return - elif isinstance(value, six.string_types): - if len(value) > 1024: - raise ValueError('Length of value greater than maxlength') - else: - raise TypeError('Expecting String, got %s' % type(value)) - - -class StringProperty(Property): - - type_name = 'String' - - def __init__(self, verbose_name=None, name=None, default='', - required=False, validator=validate_string, - choices=None, unique=False): - super(StringProperty, self).__init__(verbose_name, name, default, required, - validator, choices, unique) - - -class TextProperty(Property): - - type_name = 'Text' - - def __init__(self, verbose_name=None, name=None, default='', - required=False, validator=None, choices=None, - unique=False, max_length=None): - super(TextProperty, self).__init__(verbose_name, name, default, required, - validator, choices, unique) - self.max_length = max_length - - def validate(self, value): - value = super(TextProperty, self).validate(value) - if not isinstance(value, six.string_types): - raise TypeError('Expecting Text, got %s' % type(value)) - if self.max_length and len(value) > self.max_length: - raise ValueError('Length of value greater than maxlength %s' % self.max_length) - - -class PasswordProperty(StringProperty): - """ - - Hashed property whose original value can not be - retrieved, but still can be compared. - - Works by storing a hash of the original value instead - of the original value. Once that's done all that - can be retrieved is the hash. - - The comparison - - obj.password == 'foo' - - generates a hash of 'foo' and compares it to the - stored hash. - - Underlying data type for hashing, storing, and comparing - is boto.utils.Password. The default hash function is - defined there ( currently sha512 in most cases, md5 - where sha512 is not available ) - - It's unlikely you'll ever need to use a different hash - function, but if you do, you can control the behavior - in one of two ways: - - 1) Specifying hashfunc in PasswordProperty constructor - - import hashlib - - class MyModel(model): - password = PasswordProperty(hashfunc=hashlib.sha224) - - 2) Subclassing Password and PasswordProperty - - class SHA224Password(Password): - hashfunc=hashlib.sha224 - - class SHA224PasswordProperty(PasswordProperty): - data_type=MyPassword - type_name="MyPassword" - - class MyModel(Model): - password = SHA224PasswordProperty() - - """ - data_type = Password - type_name = 'Password' - - def __init__(self, verbose_name=None, name=None, default='', required=False, - validator=None, choices=None, unique=False, hashfunc=None): - - """ - The hashfunc parameter overrides the default hashfunc in boto.utils.Password. - - The remaining parameters are passed through to StringProperty.__init__""" - - super(PasswordProperty, self).__init__(verbose_name, name, default, required, - validator, choices, unique) - self.hashfunc = hashfunc - - def make_value_from_datastore(self, value): - p = self.data_type(value, hashfunc=self.hashfunc) - return p - - def get_value_for_datastore(self, model_instance): - value = super(PasswordProperty, self).get_value_for_datastore(model_instance) - if value and len(value): - return str(value) - else: - return None - - def __set__(self, obj, value): - if not isinstance(value, self.data_type): - p = self.data_type(hashfunc=self.hashfunc) - p.set(value) - value = p - super(PasswordProperty, self).__set__(obj, value) - - def __get__(self, obj, objtype): - return self.data_type(super(PasswordProperty, self).__get__(obj, objtype), hashfunc=self.hashfunc) - - def validate(self, value): - value = super(PasswordProperty, self).validate(value) - if isinstance(value, self.data_type): - if len(value) > 1024: - raise ValueError('Length of value greater than maxlength') - else: - raise TypeError('Expecting %s, got %s' % (type(self.data_type), type(value))) - - -class BlobProperty(Property): - data_type = Blob - type_name = "blob" - - def __set__(self, obj, value): - if value != self.default_value(): - if not isinstance(value, Blob): - oldb = self.__get__(obj, type(obj)) - id = None - if oldb: - id = oldb.id - b = Blob(value=value, id=id) - value = b - super(BlobProperty, self).__set__(obj, value) - - -class S3KeyProperty(Property): - - data_type = boto.s3.key.Key - type_name = 'S3Key' - validate_regex = "^s3:\/\/([^\/]*)\/(.*)$" - - def __init__(self, verbose_name=None, name=None, default=None, - required=False, validator=None, choices=None, unique=False): - super(S3KeyProperty, self).__init__(verbose_name, name, default, required, - validator, choices, unique) - - def validate(self, value): - value = super(S3KeyProperty, self).validate(value) - if value == self.default_value() or value == str(self.default_value()): - return self.default_value() - if isinstance(value, self.data_type): - return - match = re.match(self.validate_regex, value) - if match: - return - raise TypeError('Validation Error, expecting %s, got %s' % (self.data_type, type(value))) - - def __get__(self, obj, objtype): - value = super(S3KeyProperty, self).__get__(obj, objtype) - if value: - if isinstance(value, self.data_type): - return value - match = re.match(self.validate_regex, value) - if match: - s3 = obj._manager.get_s3_connection() - bucket = s3.get_bucket(match.group(1), validate=False) - k = bucket.get_key(match.group(2)) - if not k: - k = bucket.new_key(match.group(2)) - k.set_contents_from_string("") - return k - else: - return value - - def get_value_for_datastore(self, model_instance): - value = super(S3KeyProperty, self).get_value_for_datastore(model_instance) - if value: - return "s3://%s/%s" % (value.bucket.name, value.name) - else: - return None - - -class IntegerProperty(Property): - - data_type = int - type_name = 'Integer' - - def __init__(self, verbose_name=None, name=None, default=0, required=False, - validator=None, choices=None, unique=False, max=2147483647, min=-2147483648): - super(IntegerProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - self.max = max - self.min = min - - def validate(self, value): - value = int(value) - value = super(IntegerProperty, self).validate(value) - if value > self.max: - raise ValueError('Maximum value is %d' % self.max) - if value < self.min: - raise ValueError('Minimum value is %d' % self.min) - return value - - def empty(self, value): - return value is None - - def __set__(self, obj, value): - if value == "" or value is None: - value = 0 - return super(IntegerProperty, self).__set__(obj, value) - - -class LongProperty(Property): - - data_type = long_type - type_name = 'Long' - - def __init__(self, verbose_name=None, name=None, default=0, required=False, - validator=None, choices=None, unique=False): - super(LongProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - - def validate(self, value): - value = long_type(value) - value = super(LongProperty, self).validate(value) - min = -9223372036854775808 - max = 9223372036854775807 - if value > max: - raise ValueError('Maximum value is %d' % max) - if value < min: - raise ValueError('Minimum value is %d' % min) - return value - - def empty(self, value): - return value is None - - -class BooleanProperty(Property): - - data_type = bool - type_name = 'Boolean' - - def __init__(self, verbose_name=None, name=None, default=False, required=False, - validator=None, choices=None, unique=False): - super(BooleanProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - - def empty(self, value): - return value is None - - -class FloatProperty(Property): - - data_type = float - type_name = 'Float' - - def __init__(self, verbose_name=None, name=None, default=0.0, required=False, - validator=None, choices=None, unique=False): - super(FloatProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - - def validate(self, value): - value = float(value) - value = super(FloatProperty, self).validate(value) - return value - - def empty(self, value): - return value is None - - -class DateTimeProperty(Property): - """This class handles both the datetime.datetime object - And the datetime.date objects. It can return either one, - depending on the value stored in the database""" - - data_type = datetime.datetime - type_name = 'DateTime' - - def __init__(self, verbose_name=None, auto_now=False, auto_now_add=False, name=None, - default=None, required=False, validator=None, choices=None, unique=False): - super(DateTimeProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - self.auto_now = auto_now - self.auto_now_add = auto_now_add - - def default_value(self): - if self.auto_now or self.auto_now_add: - return self.now() - return super(DateTimeProperty, self).default_value() - - def validate(self, value): - if value is None: - return - if isinstance(value, datetime.date): - return value - return super(DateTimeProperty, self).validate(value) - - def get_value_for_datastore(self, model_instance): - if self.auto_now: - setattr(model_instance, self.name, self.now()) - return super(DateTimeProperty, self).get_value_for_datastore(model_instance) - - def now(self): - return datetime.datetime.utcnow() - - -class DateProperty(Property): - - data_type = datetime.date - type_name = 'Date' - - def __init__(self, verbose_name=None, auto_now=False, auto_now_add=False, name=None, - default=None, required=False, validator=None, choices=None, unique=False): - super(DateProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - self.auto_now = auto_now - self.auto_now_add = auto_now_add - - def default_value(self): - if self.auto_now or self.auto_now_add: - return self.now() - return super(DateProperty, self).default_value() - - def validate(self, value): - value = super(DateProperty, self).validate(value) - if value is None: - return - if not isinstance(value, self.data_type): - raise TypeError('Validation Error, expecting %s, got %s' % (self.data_type, type(value))) - - def get_value_for_datastore(self, model_instance): - if self.auto_now: - setattr(model_instance, self.name, self.now()) - val = super(DateProperty, self).get_value_for_datastore(model_instance) - if isinstance(val, datetime.datetime): - val = val.date() - return val - - def now(self): - return datetime.date.today() - - -class TimeProperty(Property): - data_type = datetime.time - type_name = 'Time' - - def __init__(self, verbose_name=None, name=None, - default=None, required=False, validator=None, choices=None, unique=False): - super(TimeProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - - def validate(self, value): - value = super(TimeProperty, self).validate(value) - if value is None: - return - if not isinstance(value, self.data_type): - raise TypeError('Validation Error, expecting %s, got %s' % (self.data_type, type(value))) - - -class ReferenceProperty(Property): - - data_type = Key - type_name = 'Reference' - - def __init__(self, reference_class=None, collection_name=None, - verbose_name=None, name=None, default=None, required=False, validator=None, choices=None, unique=False): - super(ReferenceProperty, self).__init__(verbose_name, name, default, required, validator, choices, unique) - self.reference_class = reference_class - self.collection_name = collection_name - - def __get__(self, obj, objtype): - if obj: - value = getattr(obj, self.slot_name) - if value == self.default_value(): - return value - # If the value is still the UUID for the referenced object, we need to create - # the object now that is the attribute has actually been accessed. This lazy - # instantiation saves unnecessary roundtrips to SimpleDB - if isinstance(value, six.string_types): - value = self.reference_class(value) - setattr(obj, self.name, value) - return value - - def __set__(self, obj, value): - """Don't allow this object to be associated to itself - This causes bad things to happen""" - if value is not None and (obj.id == value or (hasattr(value, "id") and obj.id == value.id)): - raise ValueError("Can not associate an object with itself!") - return super(ReferenceProperty, self).__set__(obj, value) - - def __property_config__(self, model_class, property_name): - super(ReferenceProperty, self).__property_config__(model_class, property_name) - if self.collection_name is None: - self.collection_name = '%s_%s_set' % (model_class.__name__.lower(), self.name) - if hasattr(self.reference_class, self.collection_name): - raise ValueError('duplicate property: %s' % self.collection_name) - setattr(self.reference_class, self.collection_name, - _ReverseReferenceProperty(model_class, property_name, self.collection_name)) - - def check_uuid(self, value): - # This does a bit of hand waving to "type check" the string - t = value.split('-') - if len(t) != 5: - raise ValueError - - def check_instance(self, value): - try: - obj_lineage = value.get_lineage() - cls_lineage = self.reference_class.get_lineage() - if obj_lineage.startswith(cls_lineage): - return - raise TypeError('%s not instance of %s' % (obj_lineage, cls_lineage)) - except: - raise ValueError('%s is not a Model' % value) - - def validate(self, value): - if self.validator: - self.validator(value) - if self.required and value is None: - raise ValueError('%s is a required property' % self.name) - if value == self.default_value(): - return - if not isinstance(value, six.string_types): - self.check_instance(value) - - -class _ReverseReferenceProperty(Property): - data_type = Query - type_name = 'query' - - def __init__(self, model, prop, name): - self.__model = model - self.__property = prop - self.collection_name = prop - self.name = name - self.item_type = model - - def __get__(self, model_instance, model_class): - """Fetches collection of model instances of this collection property.""" - if model_instance is not None: - query = Query(self.__model) - if isinstance(self.__property, list): - props = [] - for prop in self.__property: - props.append("%s =" % prop) - return query.filter(props, model_instance) - else: - return query.filter(self.__property + ' =', model_instance) - else: - return self - - def __set__(self, model_instance, value): - """Not possible to set a new collection.""" - raise ValueError('Virtual property is read-only') - - -class CalculatedProperty(Property): - - def __init__(self, verbose_name=None, name=None, default=None, - required=False, validator=None, choices=None, - calculated_type=int, unique=False, use_method=False): - super(CalculatedProperty, self).__init__(verbose_name, name, default, required, - validator, choices, unique) - self.calculated_type = calculated_type - self.use_method = use_method - - def __get__(self, obj, objtype): - value = self.default_value() - if obj: - try: - value = getattr(obj, self.slot_name) - if self.use_method: - value = value() - except AttributeError: - pass - return value - - def __set__(self, obj, value): - """Not possible to set a new AutoID.""" - pass - - def _set_direct(self, obj, value): - if not self.use_method: - setattr(obj, self.slot_name, value) - - def get_value_for_datastore(self, model_instance): - if self.calculated_type in [str, int, bool]: - value = self.__get__(model_instance, model_instance.__class__) - return value - else: - return None - - -class ListProperty(Property): - - data_type = list - type_name = 'List' - - def __init__(self, item_type, verbose_name=None, name=None, default=None, **kwds): - if default is None: - default = [] - self.item_type = item_type - super(ListProperty, self).__init__(verbose_name, name, default=default, required=True, **kwds) - - def validate(self, value): - if self.validator: - self.validator(value) - if value is not None: - if not isinstance(value, list): - value = [value] - - if self.item_type in six.integer_types: - item_type = six.integer_types - elif self.item_type in six.string_types: - item_type = six.string_types - else: - item_type = self.item_type - - for item in value: - if not isinstance(item, item_type): - if item_type == six.integer_types: - raise ValueError('Items in the %s list must all be integers.' % self.name) - else: - raise ValueError('Items in the %s list must all be %s instances' % - (self.name, self.item_type.__name__)) - return value - - def empty(self, value): - return value is None - - def default_value(self): - return list(super(ListProperty, self).default_value()) - - def __set__(self, obj, value): - """Override the set method to allow them to set the property to an instance of the item_type instead of requiring a list to be passed in""" - if self.item_type in six.integer_types: - item_type = six.integer_types - elif self.item_type in six.string_types: - item_type = six.string_types - else: - item_type = self.item_type - if isinstance(value, item_type): - value = [value] - elif value is None: # Override to allow them to set this to "None" to remove everything - value = [] - return super(ListProperty, self).__set__(obj, value) - - -class MapProperty(Property): - - data_type = dict - type_name = 'Map' - - def __init__(self, item_type=str, verbose_name=None, name=None, default=None, **kwds): - if default is None: - default = {} - self.item_type = item_type - super(MapProperty, self).__init__(verbose_name, name, default=default, required=True, **kwds) - - def validate(self, value): - value = super(MapProperty, self).validate(value) - if value is not None: - if not isinstance(value, dict): - raise ValueError('Value must of type dict') - - if self.item_type in six.integer_types: - item_type = six.integer_types - elif self.item_type in six.string_types: - item_type = six.string_types - else: - item_type = self.item_type - - for key in value: - if not isinstance(value[key], item_type): - if item_type == six.integer_types: - raise ValueError('Values in the %s Map must all be integers.' % self.name) - else: - raise ValueError('Values in the %s Map must all be %s instances' % - (self.name, self.item_type.__name__)) - return value - - def empty(self, value): - return value is None - - def default_value(self): - return {} diff --git a/awx/lib/site-packages/boto/sdb/db/query.py b/awx/lib/site-packages/boto/sdb/db/query.py deleted file mode 100644 index 8945d4c0aa..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/query.py +++ /dev/null @@ -1,86 +0,0 @@ -from boto.compat import six -# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -class Query(object): - __local_iter__ = None - def __init__(self, model_class, limit=None, next_token=None, manager=None): - self.model_class = model_class - self.limit = limit - self.offset = 0 - if manager: - self.manager = manager - else: - self.manager = self.model_class._manager - self.filters = [] - self.select = None - self.sort_by = None - self.rs = None - self.next_token = next_token - - def __iter__(self): - return iter(self.manager.query(self)) - - def next(self): - if self.__local_iter__ is None: - self.__local_iter__ = self.__iter__() - return next(self.__local_iter__) - - def filter(self, property_operator, value): - self.filters.append((property_operator, value)) - return self - - def fetch(self, limit, offset=0): - """Not currently fully supported, but we can use this - to allow them to set a limit in a chainable method""" - self.limit = limit - self.offset = offset - return self - - def count(self, quick=True): - return self.manager.count(self.model_class, self.filters, quick, self.sort_by, self.select) - - def get_query(self): - return self.manager._build_filter_part(self.model_class, self.filters, self.sort_by, self.select) - - def order(self, key): - self.sort_by = key - return self - - def to_xml(self, doc=None): - if not doc: - xmlmanager = self.model_class.get_xmlmanager() - doc = xmlmanager.new_doc() - for obj in self: - obj.to_xml(doc) - return doc - - def get_next_token(self): - if self.rs: - return self.rs.next_token - if self._next_token: - return self._next_token - return None - - def set_next_token(self, token): - self._next_token = token - - next_token = property(get_next_token, set_next_token) diff --git a/awx/lib/site-packages/boto/sdb/db/sequence.py b/awx/lib/site-packages/boto/sdb/db/sequence.py deleted file mode 100644 index a28798930c..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/sequence.py +++ /dev/null @@ -1,224 +0,0 @@ -# Copyright (c) 2010 Chris Moyer http://coredumped.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.exception import SDBResponseError -from boto.compat import six - -class SequenceGenerator(object): - """Generic Sequence Generator object, this takes a single - string as the "sequence" and uses that to figure out - what the next value in a string is. For example - if you give "ABC" and pass in "A" it will give you "B", - and if you give it "C" it will give you "AA". - - If you set "rollover" to True in the above example, passing - in "C" would give you "A" again. - - The Sequence string can be a string or any iterable - that has the "index" function and is indexable. - """ - __name__ = "SequenceGenerator" - - def __init__(self, sequence_string, rollover=False): - """Create a new SequenceGenerator using the sequence_string - as how to generate the next item. - - :param sequence_string: The string or list that explains - how to generate the next item in the sequence - :type sequence_string: str,iterable - - :param rollover: Rollover instead of incrementing when - we hit the end of the sequence - :type rollover: bool - """ - self.sequence_string = sequence_string - self.sequence_length = len(sequence_string[0]) - self.rollover = rollover - self.last_item = sequence_string[-1] - self.__name__ = "%s('%s')" % (self.__class__.__name__, sequence_string) - - def __call__(self, val, last=None): - """Get the next value in the sequence""" - # If they pass us in a string that's not at least - # the lenght of our sequence, then return the - # first element in our sequence - if val is None or len(val) < self.sequence_length: - return self.sequence_string[0] - last_value = val[-self.sequence_length:] - if (not self.rollover) and (last_value == self.last_item): - val = "%s%s" % (self(val[:-self.sequence_length]), self._inc(last_value)) - else: - val = "%s%s" % (val[:-self.sequence_length], self._inc(last_value)) - return val - - def _inc(self, val): - """Increment a single value""" - assert(len(val) == self.sequence_length) - return self.sequence_string[(self.sequence_string.index(val) + 1) % len(self.sequence_string)] - - -# -# Simple Sequence Functions -# -def increment_by_one(cv=None, lv=None): - if cv is None: - return 0 - return cv + 1 - -def double(cv=None, lv=None): - if cv is None: - return 1 - return cv * 2 - -def fib(cv=1, lv=0): - """The fibonacci sequence, this incrementer uses the - last value""" - if cv is None: - cv = 1 - if lv is None: - lv = 0 - return cv + lv - -increment_string = SequenceGenerator("ABCDEFGHIJKLMNOPQRSTUVWXYZ") - - -class Sequence(object): - """A simple Sequence using the new SDB "Consistent" features - Based largly off of the "Counter" example from mitch garnaat: - http://bitbucket.org/mitch/stupidbototricks/src/tip/counter.py""" - - def __init__(self, id=None, domain_name=None, fnc=increment_by_one, init_val=None): - """Create a new Sequence, using an optional function to - increment to the next number, by default we just increment by one. - Every parameter here is optional, if you don't specify any options - then you'll get a new SequenceGenerator with a random ID stored in the - default domain that increments by one and uses the default botoweb - environment - - :param id: Optional ID (name) for this counter - :type id: str - - :param domain_name: Optional domain name to use, by default we get this out of the - environment configuration - :type domain_name:str - - :param fnc: Optional function to use for the incrementation, by default we just increment by one - There are several functions defined in this module. - Your function must accept "None" to get the initial value - :type fnc: function, str - - :param init_val: Initial value, by default this is the first element in your sequence, - but you can pass in any value, even a string if you pass in a function that uses - strings instead of ints to increment - """ - self._db = None - self._value = None - self.last_value = None - self.domain_name = domain_name - self.id = id - if init_val is None: - init_val = fnc(init_val) - - if self.id is None: - import uuid - self.id = str(uuid.uuid4()) - - self.item_type = type(fnc(None)) - self.timestamp = None - # Allow us to pass in a full name to a function - if isinstance(fnc, six.string_types): - from boto.utils import find_class - fnc = find_class(fnc) - self.fnc = fnc - - # Bootstrap the value last - if not self.val: - self.val = init_val - - def set(self, val): - """Set the value""" - import time - now = time.time() - expected_value = [] - new_val = {} - new_val['timestamp'] = now - if self._value is not None: - new_val['last_value'] = self._value - expected_value = ['current_value', str(self._value)] - new_val['current_value'] = val - try: - self.db.put_attributes(self.id, new_val, expected_value=expected_value) - self.timestamp = new_val['timestamp'] - except SDBResponseError as e: - if e.status == 409: - raise ValueError("Sequence out of sync") - else: - raise - - - def get(self): - """Get the value""" - val = self.db.get_attributes(self.id, consistent_read=True) - if val: - if 'timestamp' in val: - self.timestamp = val['timestamp'] - if 'current_value' in val: - self._value = self.item_type(val['current_value']) - if "last_value" in val and val['last_value'] is not None: - self.last_value = self.item_type(val['last_value']) - return self._value - - val = property(get, set) - - def __repr__(self): - return "%s('%s', '%s', '%s.%s', '%s')" % ( - self.__class__.__name__, - self.id, - self.domain_name, - self.fnc.__module__, self.fnc.__name__, - self.val) - - - def _connect(self): - """Connect to our domain""" - if not self._db: - import boto - sdb = boto.connect_sdb() - if not self.domain_name: - self.domain_name = boto.config.get("DB", "sequence_db", boto.config.get("DB", "db_name", "default")) - try: - self._db = sdb.get_domain(self.domain_name) - except SDBResponseError as e: - if e.status == 400: - self._db = sdb.create_domain(self.domain_name) - else: - raise - return self._db - - db = property(_connect) - - def next(self): - self.val = self.fnc(self.val, self.last_value) - return self.val - - def delete(self): - """Remove this sequence""" - self.db.delete_attributes(self.id) diff --git a/awx/lib/site-packages/boto/sdb/db/test_db.py b/awx/lib/site-packages/boto/sdb/db/test_db.py deleted file mode 100644 index ba2fb3cd5f..0000000000 --- a/awx/lib/site-packages/boto/sdb/db/test_db.py +++ /dev/null @@ -1,231 +0,0 @@ -import logging -import time -from datetime import datetime - -from boto.sdb.db.model import Model -from boto.sdb.db.property import StringProperty, IntegerProperty, BooleanProperty -from boto.sdb.db.property import DateTimeProperty, FloatProperty, ReferenceProperty -from boto.sdb.db.property import PasswordProperty, ListProperty, MapProperty -from boto.exception import SDBPersistenceError - -logging.basicConfig() -log = logging.getLogger('test_db') -log.setLevel(logging.DEBUG) - -_objects = {} - -# -# This will eventually be moved to the boto.tests module and become a real unit test -# but for now it will live here. It shows examples of each of the Property types in -# use and tests the basic operations. -# -class TestBasic(Model): - - name = StringProperty() - size = IntegerProperty() - foo = BooleanProperty() - date = DateTimeProperty() - -class TestFloat(Model): - - name = StringProperty() - value = FloatProperty() - -class TestRequired(Model): - - req = StringProperty(required=True, default='foo') - -class TestReference(Model): - - ref = ReferenceProperty(reference_class=TestBasic, collection_name='refs') - -class TestSubClass(TestBasic): - - answer = IntegerProperty() - -class TestPassword(Model): - password = PasswordProperty() - -class TestList(Model): - - name = StringProperty() - nums = ListProperty(int) - -class TestMap(Model): - - name = StringProperty() - map = MapProperty() - -class TestListReference(Model): - - name = StringProperty() - basics = ListProperty(TestBasic) - -class TestAutoNow(Model): - - create_date = DateTimeProperty(auto_now_add=True) - modified_date = DateTimeProperty(auto_now=True) - -class TestUnique(Model): - name = StringProperty(unique=True) - -def test_basic(): - global _objects - t = TestBasic() - t.name = 'simple' - t.size = -42 - t.foo = True - t.date = datetime.now() - log.debug('saving object') - t.put() - _objects['test_basic_t'] = t - time.sleep(5) - log.debug('now try retrieving it') - tt = TestBasic.get_by_id(t.id) - _objects['test_basic_tt'] = tt - assert tt.id == t.id - l = TestBasic.get_by_id([t.id]) - assert len(l) == 1 - assert l[0].id == t.id - assert t.size == tt.size - assert t.foo == tt.foo - assert t.name == tt.name - #assert t.date == tt.date - return t - -def test_float(): - global _objects - t = TestFloat() - t.name = 'float object' - t.value = 98.6 - log.debug('saving object') - t.save() - _objects['test_float_t'] = t - time.sleep(5) - log.debug('now try retrieving it') - tt = TestFloat.get_by_id(t.id) - _objects['test_float_tt'] = tt - assert tt.id == t.id - assert tt.name == t.name - assert tt.value == t.value - return t - -def test_required(): - global _objects - t = TestRequired() - _objects['test_required_t'] = t - t.put() - return t - -def test_reference(t=None): - global _objects - if not t: - t = test_basic() - tt = TestReference() - tt.ref = t - tt.put() - time.sleep(10) - tt = TestReference.get_by_id(tt.id) - _objects['test_reference_tt'] = tt - assert tt.ref.id == t.id - for o in t.refs: - log.debug(o) - -def test_subclass(): - global _objects - t = TestSubClass() - _objects['test_subclass_t'] = t - t.name = 'a subclass' - t.size = -489 - t.save() - -def test_password(): - global _objects - t = TestPassword() - _objects['test_password_t'] = t - t.password = "foo" - t.save() - time.sleep(5) - # Make sure it stored ok - tt = TestPassword.get_by_id(t.id) - _objects['test_password_tt'] = tt - #Testing password equality - assert tt.password == "foo" - #Testing password not stored as string - assert str(tt.password) != "foo" - -def test_list(): - global _objects - t = TestList() - _objects['test_list_t'] = t - t.name = 'a list of ints' - t.nums = [1, 2, 3, 4, 5] - t.put() - tt = TestList.get_by_id(t.id) - _objects['test_list_tt'] = tt - assert tt.name == t.name - for n in tt.nums: - assert isinstance(n, int) - -def test_list_reference(): - global _objects - t = TestBasic() - t.put() - _objects['test_list_ref_t'] = t - tt = TestListReference() - tt.name = "foo" - tt.basics = [t] - tt.put() - time.sleep(5) - _objects['test_list_ref_tt'] = tt - ttt = TestListReference.get_by_id(tt.id) - assert ttt.basics[0].id == t.id - -def test_unique(): - global _objects - t = TestUnique() - name = 'foo' + str(int(time.time())) - t.name = name - t.put() - _objects['test_unique_t'] = t - time.sleep(10) - tt = TestUnique() - _objects['test_unique_tt'] = tt - tt.name = name - try: - tt.put() - assert False - except(SDBPersistenceError): - pass - -def test_datetime(): - global _objects - t = TestAutoNow() - t.put() - _objects['test_datetime_t'] = t - time.sleep(5) - tt = TestAutoNow.get_by_id(t.id) - assert tt.create_date.timetuple() == t.create_date.timetuple() - -def test(): - log.info('test_basic') - t1 = test_basic() - log.info('test_required') - test_required() - log.info('test_reference') - test_reference(t1) - log.info('test_subclass') - test_subclass() - log.info('test_password') - test_password() - log.info('test_list') - test_list() - log.info('test_list_reference') - test_list_reference() - log.info("test_datetime") - test_datetime() - log.info('test_unique') - test_unique() - -if __name__ == "__main__": - test() diff --git a/awx/lib/site-packages/boto/sdb/domain.py b/awx/lib/site-packages/boto/sdb/domain.py deleted file mode 100644 index faed813326..0000000000 --- a/awx/lib/site-packages/boto/sdb/domain.py +++ /dev/null @@ -1,380 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from __future__ import print_function - -""" -Represents an SDB Domain -""" - -from boto.sdb.queryresultset import SelectResultSet -from boto.compat import six - -class Domain(object): - - def __init__(self, connection=None, name=None): - self.connection = connection - self.name = name - self._metadata = None - - def __repr__(self): - return 'Domain:%s' % self.name - - def __iter__(self): - return iter(self.select("SELECT * FROM `%s`" % self.name)) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'DomainName': - self.name = value - else: - setattr(self, name, value) - - def get_metadata(self): - if not self._metadata: - self._metadata = self.connection.domain_metadata(self) - return self._metadata - - def put_attributes(self, item_name, attributes, - replace=True, expected_value=None): - """ - Store attributes for a given item. - - :type item_name: string - :param item_name: The name of the item whose attributes are being stored. - - :type attribute_names: dict or dict-like object - :param attribute_names: The name/value pairs to store as attributes - - :type expected_value: list - :param expected_value: If supplied, this is a list or tuple consisting - of a single attribute name and expected value. The list can be - of the form: - - * ['name', 'value'] - - In which case the call will first verify that the attribute - "name" of this item has a value of "value". If it does, the delete - will proceed, otherwise a ConditionalCheckFailed error will be - returned. The list can also be of the form: - - * ['name', True|False] - - which will simply check for the existence (True) or non-existence - (False) of the attribute. - - :type replace: bool - :param replace: Whether the attribute values passed in will replace - existing values or will be added as addition values. - Defaults to True. - - :rtype: bool - :return: True if successful - """ - return self.connection.put_attributes(self, item_name, attributes, - replace, expected_value) - - def batch_put_attributes(self, items, replace=True): - """ - Store attributes for multiple items. - - :type items: dict or dict-like object - :param items: A dictionary-like object. The keys of the dictionary are - the item names and the values are themselves dictionaries - of attribute names/values, exactly the same as the - attribute_names parameter of the scalar put_attributes - call. - - :type replace: bool - :param replace: Whether the attribute values passed in will replace - existing values or will be added as addition values. - Defaults to True. - - :rtype: bool - :return: True if successful - """ - return self.connection.batch_put_attributes(self, items, replace) - - def get_attributes(self, item_name, attribute_name=None, - consistent_read=False, item=None): - """ - Retrieve attributes for a given item. - - :type item_name: string - :param item_name: The name of the item whose attributes are being retrieved. - - :type attribute_names: string or list of strings - :param attribute_names: An attribute name or list of attribute names. This - parameter is optional. If not supplied, all attributes - will be retrieved for the item. - - :rtype: :class:`boto.sdb.item.Item` - :return: An Item mapping type containing the requested attribute name/values - """ - return self.connection.get_attributes(self, item_name, attribute_name, - consistent_read, item) - - def delete_attributes(self, item_name, attributes=None, - expected_values=None): - """ - Delete attributes from a given item. - - :type item_name: string - :param item_name: The name of the item whose attributes are being deleted. - - :type attributes: dict, list or :class:`boto.sdb.item.Item` - :param attributes: Either a list containing attribute names which will cause - all values associated with that attribute name to be deleted or - a dict or Item containing the attribute names and keys and list - of values to delete as the value. If no value is supplied, - all attribute name/values for the item will be deleted. - - :type expected_value: list - :param expected_value: If supplied, this is a list or tuple consisting - of a single attribute name and expected value. The list can be of - the form: - - * ['name', 'value'] - - In which case the call will first verify that the attribute "name" - of this item has a value of "value". If it does, the delete - will proceed, otherwise a ConditionalCheckFailed error will be - returned. The list can also be of the form: - - * ['name', True|False] - - which will simply check for the existence (True) or - non-existence (False) of the attribute. - - :rtype: bool - :return: True if successful - """ - return self.connection.delete_attributes(self, item_name, attributes, - expected_values) - - def batch_delete_attributes(self, items): - """ - Delete multiple items in this domain. - - :type items: dict or dict-like object - :param items: A dictionary-like object. The keys of the dictionary are - the item names and the values are either: - - * dictionaries of attribute names/values, exactly the - same as the attribute_names parameter of the scalar - put_attributes call. The attribute name/value pairs - will only be deleted if they match the name/value - pairs passed in. - * None which means that all attributes associated - with the item should be deleted. - - :rtype: bool - :return: True if successful - """ - return self.connection.batch_delete_attributes(self, items) - - def select(self, query='', next_token=None, consistent_read=False, max_items=None): - """ - Returns a set of Attributes for item names within domain_name that match the query. - The query must be expressed in using the SELECT style syntax rather than the - original SimpleDB query language. - - :type query: string - :param query: The SimpleDB query to be performed. - - :rtype: iter - :return: An iterator containing the results. This is actually a generator - function that will iterate across all search results, not just the - first page. - """ - return SelectResultSet(self, query, max_items=max_items, next_token=next_token, - consistent_read=consistent_read) - - def get_item(self, item_name, consistent_read=False): - """ - Retrieves an item from the domain, along with all of its attributes. - - :param string item_name: The name of the item to retrieve. - :rtype: :class:`boto.sdb.item.Item` or ``None`` - :keyword bool consistent_read: When set to true, ensures that the most - recent data is returned. - :return: The requested item, or ``None`` if there was no match found - """ - item = self.get_attributes(item_name, consistent_read=consistent_read) - if item: - item.domain = self - return item - else: - return None - - def new_item(self, item_name): - return self.connection.item_cls(self, item_name) - - def delete_item(self, item): - self.delete_attributes(item.name) - - def to_xml(self, f=None): - """Get this domain as an XML DOM Document - :param f: Optional File to dump directly to - :type f: File or Stream - - :return: File object where the XML has been dumped to - :rtype: file - """ - if not f: - from tempfile import TemporaryFile - f = TemporaryFile() - print('<?xml version="1.0" encoding="UTF-8"?>', file=f) - print('<Domain id="%s">' % self.name, file=f) - for item in self: - print('\t<Item id="%s">' % item.name, file=f) - for k in item: - print('\t\t<attribute id="%s">' % k, file=f) - values = item[k] - if not isinstance(values, list): - values = [values] - for value in values: - print('\t\t\t<value><![CDATA[', end=' ', file=f) - if isinstance(value, six.text_type): - value = value.encode('utf-8', 'replace') - else: - value = six.text_type(value, errors='replace').encode('utf-8', 'replace') - f.write(value) - print(']]></value>', file=f) - print('\t\t</attribute>', file=f) - print('\t</Item>', file=f) - print('</Domain>', file=f) - f.flush() - f.seek(0) - return f - - - def from_xml(self, doc): - """Load this domain based on an XML document""" - import xml.sax - handler = DomainDumpParser(self) - xml.sax.parse(doc, handler) - return handler - - def delete(self): - """ - Delete this domain, and all items under it - """ - return self.connection.delete_domain(self) - - -class DomainMetaData(object): - - def __init__(self, domain=None): - self.domain = domain - self.item_count = None - self.item_names_size = None - self.attr_name_count = None - self.attr_names_size = None - self.attr_value_count = None - self.attr_values_size = None - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'ItemCount': - self.item_count = int(value) - elif name == 'ItemNamesSizeBytes': - self.item_names_size = int(value) - elif name == 'AttributeNameCount': - self.attr_name_count = int(value) - elif name == 'AttributeNamesSizeBytes': - self.attr_names_size = int(value) - elif name == 'AttributeValueCount': - self.attr_value_count = int(value) - elif name == 'AttributeValuesSizeBytes': - self.attr_values_size = int(value) - elif name == 'Timestamp': - self.timestamp = value - else: - setattr(self, name, value) - -import sys -from xml.sax.handler import ContentHandler -class DomainDumpParser(ContentHandler): - """ - SAX parser for a domain that has been dumped - """ - - def __init__(self, domain): - self.uploader = UploaderThread(domain) - self.item_id = None - self.attrs = {} - self.attribute = None - self.value = "" - self.domain = domain - - def startElement(self, name, attrs): - if name == "Item": - self.item_id = attrs['id'] - self.attrs = {} - elif name == "attribute": - self.attribute = attrs['id'] - elif name == "value": - self.value = "" - - def characters(self, ch): - self.value += ch - - def endElement(self, name): - if name == "value": - if self.value and self.attribute: - value = self.value.strip() - attr_name = self.attribute.strip() - if attr_name in self.attrs: - self.attrs[attr_name].append(value) - else: - self.attrs[attr_name] = [value] - elif name == "Item": - self.uploader.items[self.item_id] = self.attrs - # Every 20 items we spawn off the uploader - if len(self.uploader.items) >= 20: - self.uploader.start() - self.uploader = UploaderThread(self.domain) - elif name == "Domain": - # If we're done, spawn off our last Uploader Thread - self.uploader.start() - -from threading import Thread -class UploaderThread(Thread): - """Uploader Thread""" - - def __init__(self, domain): - self.db = domain - self.items = {} - super(UploaderThread, self).__init__() - - def run(self): - try: - self.db.batch_put_attributes(self.items) - except: - print("Exception using batch put, trying regular put instead") - for item_name in self.items: - self.db.put_attributes(item_name, self.items[item_name]) - print(".", end=' ') - sys.stdout.flush() diff --git a/awx/lib/site-packages/boto/sdb/item.py b/awx/lib/site-packages/boto/sdb/item.py deleted file mode 100644 index e09a9d9a2c..0000000000 --- a/awx/lib/site-packages/boto/sdb/item.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import base64 - -class Item(dict): - """ - A ``dict`` sub-class that serves as an object representation of a - SimpleDB item. An item in SDB is similar to a row in a relational - database. Items belong to a :py:class:`Domain <boto.sdb.domain.Domain>`, - which is similar to a table in a relational database. - - The keys on instances of this object correspond to attributes that are - stored on the SDB item. - - .. tip:: While it is possible to instantiate this class directly, you may - want to use the convenience methods on :py:class:`boto.sdb.domain.Domain` - for that purpose. For example, :py:meth:`boto.sdb.domain.Domain.get_item`. - """ - def __init__(self, domain, name='', active=False): - """ - :type domain: :py:class:`boto.sdb.domain.Domain` - :param domain: The domain that this item belongs to. - - :param str name: The name of this item. This name will be used when - querying for items using methods like - :py:meth:`boto.sdb.domain.Domain.get_item` - """ - dict.__init__(self) - self.domain = domain - self.name = name - self.active = active - self.request_id = None - self.encoding = None - self.in_attribute = False - self.converter = self.domain.connection.converter - - def startElement(self, name, attrs, connection): - if name == 'Attribute': - self.in_attribute = True - self.encoding = attrs.get('encoding', None) - return None - - def decode_value(self, value): - if self.encoding == 'base64': - self.encoding = None - return base64.decodestring(value) - else: - return value - - def endElement(self, name, value, connection): - if name == 'ItemName': - self.name = self.decode_value(value) - elif name == 'Name': - if self.in_attribute: - self.last_key = self.decode_value(value) - else: - self.name = self.decode_value(value) - elif name == 'Value': - if self.last_key in self: - if not isinstance(self[self.last_key], list): - self[self.last_key] = [self[self.last_key]] - value = self.decode_value(value) - if self.converter: - value = self.converter.decode(value) - self[self.last_key].append(value) - else: - value = self.decode_value(value) - if self.converter: - value = self.converter.decode(value) - self[self.last_key] = value - elif name == 'BoxUsage': - try: - connection.box_usage += float(value) - except: - pass - elif name == 'RequestId': - self.request_id = value - elif name == 'Attribute': - self.in_attribute = False - else: - setattr(self, name, value) - - def load(self): - """ - Loads or re-loads this item's attributes from SDB. - - .. warning:: - If you have changed attribute values on an Item instance, - this method will over-write the values if they are different in - SDB. For any local attributes that don't yet exist in SDB, - they will be safe. - """ - self.domain.get_attributes(self.name, item=self) - - def save(self, replace=True): - """ - Saves this item to SDB. - - :param bool replace: If ``True``, delete any attributes on the remote - SDB item that have a ``None`` value on this object. - """ - self.domain.put_attributes(self.name, self, replace) - # Delete any attributes set to "None" - if replace: - del_attrs = [] - for name in self: - if self[name] is None: - del_attrs.append(name) - if len(del_attrs) > 0: - self.domain.delete_attributes(self.name, del_attrs) - - def add_value(self, key, value): - """ - Helps set or add to attributes on this item. If you are adding a new - attribute that has yet to be set, it will simply create an attribute - named ``key`` with your given ``value`` as its value. If you are - adding a value to an existing attribute, this method will convert the - attribute to a list (if it isn't already) and append your new value - to said list. - - For clarification, consider the following interactive session: - - .. code-block:: python - - >>> item = some_domain.get_item('some_item') - >>> item.has_key('some_attr') - False - >>> item.add_value('some_attr', 1) - >>> item['some_attr'] - 1 - >>> item.add_value('some_attr', 2) - >>> item['some_attr'] - [1, 2] - - :param str key: The attribute to add a value to. - :param object value: The value to set or append to the attribute. - """ - if key in self: - # We already have this key on the item. - if not isinstance(self[key], list): - # The key isn't already a list, take its current value and - # convert it to a list with the only member being the - # current value. - self[key] = [self[key]] - # Add the new value to the list. - self[key].append(value) - else: - # This is a new attribute, just set it. - self[key] = value - - def delete(self): - """ - Deletes this item in SDB. - - .. note:: This local Python object remains in its current state - after deletion, this only deletes the remote item in SDB. - """ - self.domain.delete_item(self) diff --git a/awx/lib/site-packages/boto/sdb/queryresultset.py b/awx/lib/site-packages/boto/sdb/queryresultset.py deleted file mode 100644 index 54f35238b6..0000000000 --- a/awx/lib/site-packages/boto/sdb/queryresultset.py +++ /dev/null @@ -1,93 +0,0 @@ -from boto.compat import six -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -def query_lister(domain, query='', max_items=None, attr_names=None): - more_results = True - num_results = 0 - next_token = None - while more_results: - rs = domain.connection.query_with_attributes(domain, query, attr_names, - next_token=next_token) - for item in rs: - if max_items: - if num_results == max_items: - raise StopIteration - yield item - num_results += 1 - next_token = rs.next_token - more_results = next_token is not None - -class QueryResultSet(object): - - def __init__(self, domain=None, query='', max_items=None, attr_names=None): - self.max_items = max_items - self.domain = domain - self.query = query - self.attr_names = attr_names - - def __iter__(self): - return query_lister(self.domain, self.query, self.max_items, self.attr_names) - -def select_lister(domain, query='', max_items=None): - more_results = True - num_results = 0 - next_token = None - while more_results: - rs = domain.connection.select(domain, query, next_token=next_token) - for item in rs: - if max_items: - if num_results == max_items: - raise StopIteration - yield item - num_results += 1 - next_token = rs.next_token - more_results = next_token is not None - -class SelectResultSet(object): - - def __init__(self, domain=None, query='', max_items=None, - next_token=None, consistent_read=False): - self.domain = domain - self.query = query - self.consistent_read = consistent_read - self.max_items = max_items - self.next_token = next_token - - def __iter__(self): - more_results = True - num_results = 0 - while more_results: - rs = self.domain.connection.select(self.domain, self.query, - next_token=self.next_token, - consistent_read=self.consistent_read) - for item in rs: - if self.max_items and num_results >= self.max_items: - raise StopIteration - yield item - num_results += 1 - self.next_token = rs.next_token - if self.max_items and num_results >= self.max_items: - raise StopIteration - more_results = self.next_token is not None - - def next(self): - return next(self.__iter__()) diff --git a/awx/lib/site-packages/boto/sdb/regioninfo.py b/awx/lib/site-packages/boto/sdb/regioninfo.py deleted file mode 100644 index cb0211e161..0000000000 --- a/awx/lib/site-packages/boto/sdb/regioninfo.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo - -class SDBRegionInfo(RegionInfo): - - def __init__(self, connection=None, name=None, endpoint=None, - connection_cls=None): - from boto.sdb.connection import SDBConnection - super(SDBRegionInfo, self).__init__(connection, name, endpoint, - SDBConnection) diff --git a/awx/lib/site-packages/boto/services/__init__.py b/awx/lib/site-packages/boto/services/__init__.py deleted file mode 100644 index 449bd162a8..0000000000 --- a/awx/lib/site-packages/boto/services/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - - diff --git a/awx/lib/site-packages/boto/services/bs.py b/awx/lib/site-packages/boto/services/bs.py deleted file mode 100644 index 396c483975..0000000000 --- a/awx/lib/site-packages/boto/services/bs.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2006-2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -from optparse import OptionParser -from boto.services.servicedef import ServiceDef -from boto.services.submit import Submitter -from boto.services.result import ResultProcessor -import boto -import sys, os -from boto.compat import StringIO - -class BS(object): - - Usage = "usage: %prog [options] config_file command" - - Commands = {'reset' : 'Clear input queue and output bucket', - 'submit' : 'Submit local files to the service', - 'start' : 'Start the service', - 'status' : 'Report on the status of the service buckets and queues', - 'retrieve' : 'Retrieve output generated by a batch', - 'batches' : 'List all batches stored in current output_domain'} - - def __init__(self): - self.service_name = None - self.parser = OptionParser(usage=self.Usage) - self.parser.add_option("--help-commands", action="store_true", dest="help_commands", - help="provides help on the available commands") - self.parser.add_option("-a", "--access-key", action="store", type="string", - help="your AWS Access Key") - self.parser.add_option("-s", "--secret-key", action="store", type="string", - help="your AWS Secret Access Key") - self.parser.add_option("-p", "--path", action="store", type="string", dest="path", - help="the path to local directory for submit and retrieve") - self.parser.add_option("-k", "--keypair", action="store", type="string", dest="keypair", - help="the SSH keypair used with launched instance(s)") - self.parser.add_option("-l", "--leave", action="store_true", dest="leave", - help="leave the files (don't retrieve) files during retrieve command") - self.parser.set_defaults(leave=False) - self.parser.add_option("-n", "--num-instances", action="store", type="string", dest="num_instances", - help="the number of launched instance(s)") - self.parser.set_defaults(num_instances=1) - self.parser.add_option("-i", "--ignore-dirs", action="append", type="string", dest="ignore", - help="directories that should be ignored by submit command") - self.parser.add_option("-b", "--batch-id", action="store", type="string", dest="batch", - help="batch identifier required by the retrieve command") - - def print_command_help(self): - print('\nCommands:') - for key in self.Commands.keys(): - print(' %s\t\t%s' % (key, self.Commands[key])) - - def do_reset(self): - iq = self.sd.get_obj('input_queue') - if iq: - print('clearing out input queue') - i = 0 - m = iq.read() - while m: - i += 1 - iq.delete_message(m) - m = iq.read() - print('deleted %d messages' % i) - ob = self.sd.get_obj('output_bucket') - ib = self.sd.get_obj('input_bucket') - if ob: - if ib and ob.name == ib.name: - return - print('delete generated files in output bucket') - i = 0 - for k in ob: - i += 1 - k.delete() - print('deleted %d keys' % i) - - def do_submit(self): - if not self.options.path: - self.parser.error('No path provided') - if not os.path.exists(self.options.path): - self.parser.error('Invalid path (%s)' % self.options.path) - s = Submitter(self.sd) - t = s.submit_path(self.options.path, None, self.options.ignore, None, - None, True, self.options.path) - print('A total of %d files were submitted' % t[1]) - print('Batch Identifier: %s' % t[0]) - - def do_start(self): - ami_id = self.sd.get('ami_id') - instance_type = self.sd.get('instance_type', 'm1.small') - security_group = self.sd.get('security_group', 'default') - if not ami_id: - self.parser.error('ami_id option is required when starting the service') - ec2 = boto.connect_ec2() - if not self.sd.has_section('Credentials'): - self.sd.add_section('Credentials') - self.sd.set('Credentials', 'aws_access_key_id', ec2.aws_access_key_id) - self.sd.set('Credentials', 'aws_secret_access_key', ec2.aws_secret_access_key) - s = StringIO() - self.sd.write(s) - rs = ec2.get_all_images([ami_id]) - img = rs[0] - r = img.run(user_data=s.getvalue(), key_name=self.options.keypair, - max_count=self.options.num_instances, - instance_type=instance_type, - security_groups=[security_group]) - print('Starting AMI: %s' % ami_id) - print('Reservation %s contains the following instances:' % r.id) - for i in r.instances: - print('\t%s' % i.id) - - def do_status(self): - iq = self.sd.get_obj('input_queue') - if iq: - print('The input_queue (%s) contains approximately %s messages' % (iq.id, iq.count())) - ob = self.sd.get_obj('output_bucket') - ib = self.sd.get_obj('input_bucket') - if ob: - if ib and ob.name == ib.name: - return - total = 0 - for k in ob: - total += 1 - print('The output_bucket (%s) contains %d keys' % (ob.name, total)) - - def do_retrieve(self): - if not self.options.path: - self.parser.error('No path provided') - if not os.path.exists(self.options.path): - self.parser.error('Invalid path (%s)' % self.options.path) - if not self.options.batch: - self.parser.error('batch identifier is required for retrieve command') - s = ResultProcessor(self.options.batch, self.sd) - s.get_results(self.options.path, get_file=(not self.options.leave)) - - def do_batches(self): - d = self.sd.get_obj('output_domain') - if d: - print('Available Batches:') - rs = d.query("['type'='Batch']") - for item in rs: - print(' %s' % item.name) - else: - self.parser.error('No output_domain specified for service') - - def main(self): - self.options, self.args = self.parser.parse_args() - if self.options.help_commands: - self.print_command_help() - sys.exit(0) - if len(self.args) != 2: - self.parser.error("config_file and command are required") - self.config_file = self.args[0] - self.sd = ServiceDef(self.config_file) - self.command = self.args[1] - if hasattr(self, 'do_%s' % self.command): - method = getattr(self, 'do_%s' % self.command) - method() - else: - self.parser.error('command (%s) not recognized' % self.command) - -if __name__ == "__main__": - bs = BS() - bs.main() diff --git a/awx/lib/site-packages/boto/services/message.py b/awx/lib/site-packages/boto/services/message.py deleted file mode 100644 index 31f37019fc..0000000000 --- a/awx/lib/site-packages/boto/services/message.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.sqs.message import MHMessage -from boto.utils import get_ts -from socket import gethostname -import os, mimetypes, time - -class ServiceMessage(MHMessage): - - def for_key(self, key, params=None, bucket_name=None): - if params: - self.update(params) - if key.path: - t = os.path.split(key.path) - self['OriginalLocation'] = t[0] - self['OriginalFileName'] = t[1] - mime_type = mimetypes.guess_type(t[1])[0] - if mime_type is None: - mime_type = 'application/octet-stream' - self['Content-Type'] = mime_type - s = os.stat(key.path) - t = time.gmtime(s[7]) - self['FileAccessedDate'] = get_ts(t) - t = time.gmtime(s[8]) - self['FileModifiedDate'] = get_ts(t) - t = time.gmtime(s[9]) - self['FileCreateDate'] = get_ts(t) - else: - self['OriginalFileName'] = key.name - self['OriginalLocation'] = key.bucket.name - self['ContentType'] = key.content_type - self['Host'] = gethostname() - if bucket_name: - self['Bucket'] = bucket_name - else: - self['Bucket'] = key.bucket.name - self['InputKey'] = key.name - self['Size'] = key.size - diff --git a/awx/lib/site-packages/boto/services/result.py b/awx/lib/site-packages/boto/services/result.py deleted file mode 100644 index 879934323b..0000000000 --- a/awx/lib/site-packages/boto/services/result.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import os -from datetime import datetime, timedelta -from boto.utils import parse_ts -import boto - -class ResultProcessor(object): - - LogFileName = 'log.csv' - - def __init__(self, batch_name, sd, mimetype_files=None): - self.sd = sd - self.batch = batch_name - self.log_fp = None - self.num_files = 0 - self.total_time = 0 - self.min_time = timedelta.max - self.max_time = timedelta.min - self.earliest_time = datetime.max - self.latest_time = datetime.min - self.queue = self.sd.get_obj('output_queue') - self.domain = self.sd.get_obj('output_domain') - - def calculate_stats(self, msg): - start_time = parse_ts(msg['Service-Read']) - end_time = parse_ts(msg['Service-Write']) - elapsed_time = end_time - start_time - if elapsed_time > self.max_time: - self.max_time = elapsed_time - if elapsed_time < self.min_time: - self.min_time = elapsed_time - self.total_time += elapsed_time.seconds - if start_time < self.earliest_time: - self.earliest_time = start_time - if end_time > self.latest_time: - self.latest_time = end_time - - def log_message(self, msg, path): - keys = sorted(msg.keys()) - if not self.log_fp: - self.log_fp = open(os.path.join(path, self.LogFileName), 'a') - line = ','.join(keys) - self.log_fp.write(line+'\n') - values = [] - for key in keys: - value = msg[key] - if value.find(',') > 0: - value = '"%s"' % value - values.append(value) - line = ','.join(values) - self.log_fp.write(line+'\n') - - def process_record(self, record, path, get_file=True): - self.log_message(record, path) - self.calculate_stats(record) - outputs = record['OutputKey'].split(',') - if 'OutputBucket' in record: - bucket = boto.lookup('s3', record['OutputBucket']) - else: - bucket = boto.lookup('s3', record['Bucket']) - for output in outputs: - if get_file: - key_name = output.split(';')[0] - key = bucket.lookup(key_name) - file_name = os.path.join(path, key_name) - print('retrieving file: %s to %s' % (key_name, file_name)) - key.get_contents_to_filename(file_name) - self.num_files += 1 - - def get_results_from_queue(self, path, get_file=True, delete_msg=True): - m = self.queue.read() - while m: - if 'Batch' in m and m['Batch'] == self.batch: - self.process_record(m, path, get_file) - if delete_msg: - self.queue.delete_message(m) - m = self.queue.read() - - def get_results_from_domain(self, path, get_file=True): - rs = self.domain.query("['Batch'='%s']" % self.batch) - for item in rs: - self.process_record(item, path, get_file) - - def get_results_from_bucket(self, path): - bucket = self.sd.get_obj('output_bucket') - if bucket: - print('No output queue or domain, just retrieving files from output_bucket') - for key in bucket: - file_name = os.path.join(path, key) - print('retrieving file: %s to %s' % (key, file_name)) - key.get_contents_to_filename(file_name) - self.num_files + 1 - - def get_results(self, path, get_file=True, delete_msg=True): - if not os.path.isdir(path): - os.mkdir(path) - if self.queue: - self.get_results_from_queue(path, get_file) - elif self.domain: - self.get_results_from_domain(path, get_file) - else: - self.get_results_from_bucket(path) - if self.log_fp: - self.log_fp.close() - print('%d results successfully retrieved.' % self.num_files) - if self.num_files > 0: - self.avg_time = float(self.total_time)/self.num_files - print('Minimum Processing Time: %d' % self.min_time.seconds) - print('Maximum Processing Time: %d' % self.max_time.seconds) - print('Average Processing Time: %f' % self.avg_time) - self.elapsed_time = self.latest_time-self.earliest_time - print('Elapsed Time: %d' % self.elapsed_time.seconds) - tput = 1.0 / ((self.elapsed_time.seconds/60.0) / self.num_files) - print('Throughput: %f transactions / minute' % tput) - diff --git a/awx/lib/site-packages/boto/services/service.py b/awx/lib/site-packages/boto/services/service.py deleted file mode 100644 index e1a04c8ec2..0000000000 --- a/awx/lib/site-packages/boto/services/service.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -from boto.services.message import ServiceMessage -from boto.services.servicedef import ServiceDef -from boto.pyami.scriptbase import ScriptBase -from boto.utils import get_ts -import time -import os -import mimetypes - - -class Service(ScriptBase): - - # Time required to process a transaction - ProcessingTime = 60 - - def __init__(self, config_file=None, mimetype_files=None): - super(Service, self).__init__(config_file) - self.name = self.__class__.__name__ - self.working_dir = boto.config.get('Pyami', 'working_dir') - self.sd = ServiceDef(config_file) - self.retry_count = self.sd.getint('retry_count', 5) - self.loop_delay = self.sd.getint('loop_delay', 30) - self.processing_time = self.sd.getint('processing_time', 60) - self.input_queue = self.sd.get_obj('input_queue') - self.output_queue = self.sd.get_obj('output_queue') - self.output_domain = self.sd.get_obj('output_domain') - if mimetype_files: - mimetypes.init(mimetype_files) - - def split_key(key): - if key.find(';') < 0: - t = (key, '') - else: - key, type = key.split(';') - label, mtype = type.split('=') - t = (key, mtype) - return t - - def read_message(self): - boto.log.info('read_message') - message = self.input_queue.read(self.processing_time) - if message: - boto.log.info(message.get_body()) - key = 'Service-Read' - message[key] = get_ts() - return message - - # retrieve the source file from S3 - def get_file(self, message): - bucket_name = message['Bucket'] - key_name = message['InputKey'] - file_name = os.path.join(self.working_dir, message.get('OriginalFileName', 'in_file')) - boto.log.info('get_file: %s/%s to %s' % (bucket_name, key_name, file_name)) - bucket = boto.lookup('s3', bucket_name) - key = bucket.new_key(key_name) - key.get_contents_to_filename(os.path.join(self.working_dir, file_name)) - return file_name - - # process source file, return list of output files - def process_file(self, in_file_name, msg): - return [] - - # store result file in S3 - def put_file(self, bucket_name, file_path, key_name=None): - boto.log.info('putting file %s as %s.%s' % (file_path, bucket_name, key_name)) - bucket = boto.lookup('s3', bucket_name) - key = bucket.new_key(key_name) - key.set_contents_from_filename(file_path) - return key - - def save_results(self, results, input_message, output_message): - output_keys = [] - for file, type in results: - if 'OutputBucket' in input_message: - output_bucket = input_message['OutputBucket'] - else: - output_bucket = input_message['Bucket'] - key_name = os.path.split(file)[1] - key = self.put_file(output_bucket, file, key_name) - output_keys.append('%s;type=%s' % (key.name, type)) - output_message['OutputKey'] = ','.join(output_keys) - - # write message to each output queue - def write_message(self, message): - message['Service-Write'] = get_ts() - message['Server'] = self.name - if 'HOSTNAME' in os.environ: - message['Host'] = os.environ['HOSTNAME'] - else: - message['Host'] = 'unknown' - message['Instance-ID'] = self.instance_id - if self.output_queue: - boto.log.info('Writing message to SQS queue: %s' % self.output_queue.id) - self.output_queue.write(message) - if self.output_domain: - boto.log.info('Writing message to SDB domain: %s' % self.output_domain.name) - item_name = '/'.join([message['Service-Write'], message['Bucket'], message['InputKey']]) - self.output_domain.put_attributes(item_name, message) - - # delete message from input queue - def delete_message(self, message): - boto.log.info('deleting message from %s' % self.input_queue.id) - self.input_queue.delete_message(message) - - # to clean up any files, etc. after each iteration - def cleanup(self): - pass - - def shutdown(self): - on_completion = self.sd.get('on_completion', 'shutdown') - if on_completion == 'shutdown': - if self.instance_id: - time.sleep(60) - c = boto.connect_ec2() - c.terminate_instances([self.instance_id]) - - def main(self, notify=False): - self.notify('Service: %s Starting' % self.name) - empty_reads = 0 - while self.retry_count < 0 or empty_reads < self.retry_count: - try: - input_message = self.read_message() - if input_message: - empty_reads = 0 - output_message = ServiceMessage(None, input_message.get_body()) - input_file = self.get_file(input_message) - results = self.process_file(input_file, output_message) - self.save_results(results, input_message, output_message) - self.write_message(output_message) - self.delete_message(input_message) - self.cleanup() - else: - empty_reads += 1 - time.sleep(self.loop_delay) - except Exception: - boto.log.exception('Service Failed') - empty_reads += 1 - self.notify('Service: %s Shutting Down' % self.name) - self.shutdown() - diff --git a/awx/lib/site-packages/boto/services/servicedef.py b/awx/lib/site-packages/boto/services/servicedef.py deleted file mode 100644 index a43b3f342a..0000000000 --- a/awx/lib/site-packages/boto/services/servicedef.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.pyami.config import Config -from boto.services.message import ServiceMessage -import boto - -class ServiceDef(Config): - - def __init__(self, config_file, aws_access_key_id=None, aws_secret_access_key=None): - super(ServiceDef, self).__init__(config_file) - self.aws_access_key_id = aws_access_key_id - self.aws_secret_access_key = aws_secret_access_key - script = Config.get(self, 'Pyami', 'scripts') - if script: - self.name = script.split('.')[-1] - else: - self.name = None - - - def get(self, name, default=None): - return super(ServiceDef, self).get(self.name, name, default) - - def has_option(self, option): - return super(ServiceDef, self).has_option(self.name, option) - - def getint(self, option, default=0): - try: - val = super(ServiceDef, self).get(self.name, option) - val = int(val) - except: - val = int(default) - return val - - def getbool(self, option, default=False): - try: - val = super(ServiceDef, self).get(self.name, option) - if val.lower() == 'true': - val = True - else: - val = False - except: - val = default - return val - - def get_obj(self, name): - """ - Returns the AWS object associated with a given option. - - The heuristics used are a bit lame. If the option name contains - the word 'bucket' it is assumed to be an S3 bucket, if the name - contains the word 'queue' it is assumed to be an SQS queue and - if it contains the word 'domain' it is assumed to be a SimpleDB - domain. If the option name specified does not exist in the - config file or if the AWS object cannot be retrieved this - returns None. - """ - val = self.get(name) - if not val: - return None - if name.find('queue') >= 0: - obj = boto.lookup('sqs', val) - if obj: - obj.set_message_class(ServiceMessage) - elif name.find('bucket') >= 0: - obj = boto.lookup('s3', val) - elif name.find('domain') >= 0: - obj = boto.lookup('sdb', val) - else: - obj = None - return obj - - diff --git a/awx/lib/site-packages/boto/services/sonofmmm.cfg b/awx/lib/site-packages/boto/services/sonofmmm.cfg deleted file mode 100644 index d70d3794d5..0000000000 --- a/awx/lib/site-packages/boto/services/sonofmmm.cfg +++ /dev/null @@ -1,43 +0,0 @@ -# -# Your AWS Credentials -# You only need to supply these in this file if you are not using -# the boto tools to start your service -# -#[Credentials] -#aws_access_key_id = <AWS Access Key Here> -#aws_secret_access_key = <AWS Secret Key Here> - -# -# Fill out this section if you want emails from the service -# when it starts and stops -# -#[Notification] -#smtp_host = <your smtp host> -#smtp_user = <your smtp username, if necessary> -#smtp_pass = <your smtp password, if necessary> -#smtp_from = <email address for From: field> -#smtp_to = <email address for To: field> - -[Pyami] -scripts = boto.services.sonofmmm.SonOfMMM - -[SonOfMMM] -# id of the AMI to be launched -ami_id = ami-dc799cb5 -# number of times service will read an empty queue before exiting -# a negative value will cause the service to run forever -retry_count = 5 -# seconds to wait after empty queue read before reading again -loop_delay = 10 -# average time it takes to process a transaction -# controls invisibility timeout of messages -processing_time = 60 -ffmpeg_args = -y -i %%s -f mov -r 29.97 -b 1200kb -mbd 2 -flags +4mv+trell -aic 2 -cmp 2 -subcmp 2 -ar 48000 -ab 19200 -s 320x240 -vcodec mpeg4 -acodec libfaac %%s -output_mimetype = video/quicktime -output_ext = .mov -input_bucket = <S3 bucket where source videos live> -output_bucket = <S3 bucket where converted videos should be stored> -output_domain = <SimpleDB domain to store results - optional> -output_queue = <SQS queue to store results - optional> -input_queue = <SQS queue where work to be done will be queued up> - diff --git a/awx/lib/site-packages/boto/services/sonofmmm.py b/awx/lib/site-packages/boto/services/sonofmmm.py deleted file mode 100644 index 3ef60838b8..0000000000 --- a/awx/lib/site-packages/boto/services/sonofmmm.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -from boto.services.service import Service -from boto.services.message import ServiceMessage -import os -import mimetypes - -class SonOfMMM(Service): - - def __init__(self, config_file=None): - super(SonOfMMM, self).__init__(config_file) - self.log_file = '%s.log' % self.instance_id - self.log_path = os.path.join(self.working_dir, self.log_file) - boto.set_file_logger(self.name, self.log_path) - if self.sd.has_option('ffmpeg_args'): - self.command = '/usr/local/bin/ffmpeg ' + self.sd.get('ffmpeg_args') - else: - self.command = '/usr/local/bin/ffmpeg -y -i %s %s' - self.output_mimetype = self.sd.get('output_mimetype') - if self.sd.has_option('output_ext'): - self.output_ext = self.sd.get('output_ext') - else: - self.output_ext = mimetypes.guess_extension(self.output_mimetype) - self.output_bucket = self.sd.get_obj('output_bucket') - self.input_bucket = self.sd.get_obj('input_bucket') - # check to see if there are any messages queue - # if not, create messages for all files in input_bucket - m = self.input_queue.read(1) - if not m: - self.queue_files() - - def queue_files(self): - boto.log.info('Queueing files from %s' % self.input_bucket.name) - for key in self.input_bucket: - boto.log.info('Queueing %s' % key.name) - m = ServiceMessage() - if self.output_bucket: - d = {'OutputBucket' : self.output_bucket.name} - else: - d = None - m.for_key(key, d) - self.input_queue.write(m) - - def process_file(self, in_file_name, msg): - base, ext = os.path.splitext(in_file_name) - out_file_name = os.path.join(self.working_dir, - base+self.output_ext) - command = self.command % (in_file_name, out_file_name) - boto.log.info('running:\n%s' % command) - status = self.run(command) - if status == 0: - return [(out_file_name, self.output_mimetype)] - else: - return [] - - def shutdown(self): - if os.path.isfile(self.log_path): - if self.output_bucket: - key = self.output_bucket.new_key(self.log_file) - key.set_contents_from_filename(self.log_path) - super(SonOfMMM, self).shutdown() diff --git a/awx/lib/site-packages/boto/services/submit.py b/awx/lib/site-packages/boto/services/submit.py deleted file mode 100644 index 69be236adb..0000000000 --- a/awx/lib/site-packages/boto/services/submit.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import time -import os - - -class Submitter(object): - - def __init__(self, sd): - self.sd = sd - self.input_bucket = self.sd.get_obj('input_bucket') - self.output_bucket = self.sd.get_obj('output_bucket') - self.output_domain = self.sd.get_obj('output_domain') - self.queue = self.sd.get_obj('input_queue') - - def get_key_name(self, fullpath, prefix): - key_name = fullpath[len(prefix):] - l = key_name.split(os.sep) - return '/'.join(l) - - def write_message(self, key, metadata): - if self.queue: - m = self.queue.new_message() - m.for_key(key, metadata) - if self.output_bucket: - m['OutputBucket'] = self.output_bucket.name - self.queue.write(m) - - def submit_file(self, path, metadata=None, cb=None, num_cb=0, prefix='/'): - if not metadata: - metadata = {} - key_name = self.get_key_name(path, prefix) - k = self.input_bucket.new_key(key_name) - k.update_metadata(metadata) - k.set_contents_from_filename(path, replace=False, cb=cb, num_cb=num_cb) - self.write_message(k, metadata) - - def submit_path(self, path, tags=None, ignore_dirs=None, cb=None, num_cb=0, status=False, prefix='/'): - path = os.path.expanduser(path) - path = os.path.expandvars(path) - path = os.path.abspath(path) - total = 0 - metadata = {} - if tags: - metadata['Tags'] = tags - l = [] - for t in time.gmtime(): - l.append(str(t)) - metadata['Batch'] = '_'.join(l) - if self.output_domain: - self.output_domain.put_attributes(metadata['Batch'], {'type' : 'Batch'}) - if os.path.isdir(path): - for root, dirs, files in os.walk(path): - if ignore_dirs: - for ignore in ignore_dirs: - if ignore in dirs: - dirs.remove(ignore) - for file in files: - fullpath = os.path.join(root, file) - if status: - print('Submitting %s' % fullpath) - self.submit_file(fullpath, metadata, cb, num_cb, prefix) - total += 1 - elif os.path.isfile(path): - self.submit_file(path, metadata, cb, num_cb) - total += 1 - else: - print('problem with %s' % path) - return (metadata['Batch'], total) diff --git a/awx/lib/site-packages/boto/ses/__init__.py b/awx/lib/site-packages/boto/ses/__init__.py deleted file mode 100644 index ee32451699..0000000000 --- a/awx/lib/site-packages/boto/ses/__init__.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Harry Marr http://hmarr.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.ses.connection import SESConnection -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the SES service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` instances - """ - return get_regions('ses', connection_cls=SESConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.ses.connection.SESConnection`. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.ses.connection.SESConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/ses/connection.py b/awx/lib/site-packages/boto/ses/connection.py deleted file mode 100644 index d9774125f9..0000000000 --- a/awx/lib/site-packages/boto/ses/connection.py +++ /dev/null @@ -1,565 +0,0 @@ -# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Harry Marr http://hmarr.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import re -import base64 - -from boto.compat import six, urllib -from boto.connection import AWSAuthConnection -from boto.exception import BotoServerError -from boto.regioninfo import RegionInfo -import boto -import boto.jsonresponse -from boto.ses import exceptions as ses_exceptions - - -class SESConnection(AWSAuthConnection): - - ResponseError = BotoServerError - DefaultRegionName = 'us-east-1' - DefaultRegionEndpoint = 'email.us-east-1.amazonaws.com' - APIVersion = '2010-12-01' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, profile_name=None): - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - super(SESConnection, self).__init__(self.region.endpoint, - aws_access_key_id, aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, debug, - https_connection_factory, path, - security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _required_auth_capability(self): - return ['ses'] - - def _build_list_params(self, params, items, label): - """Add an AWS API-compatible parameter list to a dictionary. - - :type params: dict - :param params: The parameter dictionary - - :type items: list - :param items: Items to be included in the list - - :type label: string - :param label: The parameter list's name - """ - if isinstance(items, six.string_types): - items = [items] - for i in range(1, len(items) + 1): - params['%s.%d' % (label, i)] = items[i - 1] - - def _make_request(self, action, params=None): - """Make a call to the SES API. - - :type action: string - :param action: The API method to use (e.g. SendRawEmail) - - :type params: dict - :param params: Parameters that will be sent as POST data with the API - call. - """ - ct = 'application/x-www-form-urlencoded; charset=UTF-8' - headers = {'Content-Type': ct} - params = params or {} - params['Action'] = action - - for k, v in params.items(): - if isinstance(v, six.text_type): # UTF-8 encode only if it's Unicode - params[k] = v.encode('utf-8') - - response = super(SESConnection, self).make_request( - 'POST', - '/', - headers=headers, - data=urllib.parse.urlencode(params) - ) - body = response.read().decode('utf-8') - if response.status == 200: - list_markers = ('VerifiedEmailAddresses', 'Identities', - 'DkimTokens', 'VerificationAttributes', - 'SendDataPoints') - item_markers = ('member', 'item', 'entry') - - e = boto.jsonresponse.Element(list_marker=list_markers, - item_marker=item_markers) - h = boto.jsonresponse.XmlHandler(e, None) - h.parse(body) - return e - else: - # HTTP codes other than 200 are considered errors. Go through - # some error handling to determine which exception gets raised, - self._handle_error(response, body) - - def _handle_error(self, response, body): - """ - Handle raising the correct exception, depending on the error. Many - errors share the same HTTP response code, meaning we have to get really - kludgey and do string searches to figure out what went wrong. - """ - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - - if "Address blacklisted." in body: - # Delivery failures happened frequently enough with the recipient's - # email address for Amazon to blacklist it. After a day or three, - # they'll be automatically removed, and delivery can be attempted - # again (if you write the code to do so in your application). - ExceptionToRaise = ses_exceptions.SESAddressBlacklistedError - exc_reason = "Address blacklisted." - elif "Email address is not verified." in body: - # This error happens when the "Reply-To" value passed to - # send_email() hasn't been verified yet. - ExceptionToRaise = ses_exceptions.SESAddressNotVerifiedError - exc_reason = "Email address is not verified." - elif "Daily message quota exceeded." in body: - # Encountered when your account exceeds the maximum total number - # of emails per 24 hours. - ExceptionToRaise = ses_exceptions.SESDailyQuotaExceededError - exc_reason = "Daily message quota exceeded." - elif "Maximum sending rate exceeded." in body: - # Your account has sent above its allowed requests a second rate. - ExceptionToRaise = ses_exceptions.SESMaxSendingRateExceededError - exc_reason = "Maximum sending rate exceeded." - elif "Domain ends with dot." in body: - # Recipient address ends with a dot/period. This is invalid. - ExceptionToRaise = ses_exceptions.SESDomainEndsWithDotError - exc_reason = "Domain ends with dot." - elif "Local address contains control or whitespace" in body: - # I think this pertains to the recipient address. - ExceptionToRaise = ses_exceptions.SESLocalAddressCharacterError - exc_reason = "Local address contains control or whitespace." - elif "Illegal address" in body: - # A clearly mal-formed address. - ExceptionToRaise = ses_exceptions.SESIllegalAddressError - exc_reason = "Illegal address" - # The re.search is to distinguish from the - # SESAddressNotVerifiedError error above. - elif re.search('Identity.*is not verified', body): - ExceptionToRaise = ses_exceptions.SESIdentityNotVerifiedError - exc_reason = "Identity is not verified." - elif "ownership not confirmed" in body: - ExceptionToRaise = ses_exceptions.SESDomainNotConfirmedError - exc_reason = "Domain ownership is not confirmed." - else: - # This is either a common AWS error, or one that we don't devote - # its own exception to. - ExceptionToRaise = self.ResponseError - exc_reason = response.reason - - raise ExceptionToRaise(response.status, exc_reason, body) - - def send_email(self, source, subject, body, to_addresses, - cc_addresses=None, bcc_addresses=None, - format='text', reply_addresses=None, - return_path=None, text_body=None, html_body=None): - """Composes an email message based on input data, and then immediately - queues the message for sending. - - :type source: string - :param source: The sender's email address. - - :type subject: string - :param subject: The subject of the message: A short summary of the - content, which will appear in the recipient's inbox. - - :type body: string - :param body: The message body. - - :type to_addresses: list of strings or string - :param to_addresses: The To: field(s) of the message. - - :type cc_addresses: list of strings or string - :param cc_addresses: The CC: field(s) of the message. - - :type bcc_addresses: list of strings or string - :param bcc_addresses: The BCC: field(s) of the message. - - :type format: string - :param format: The format of the message's body, must be either "text" - or "html". - - :type reply_addresses: list of strings or string - :param reply_addresses: The reply-to email address(es) for the - message. If the recipient replies to the - message, each reply-to address will - receive the reply. - - :type return_path: string - :param return_path: The email address to which bounce notifications are - to be forwarded. If the message cannot be delivered - to the recipient, then an error message will be - returned from the recipient's ISP; this message - will then be forwarded to the email address - specified by the ReturnPath parameter. - - :type text_body: string - :param text_body: The text body to send with this email. - - :type html_body: string - :param html_body: The html body to send with this email. - - """ - format = format.lower().strip() - if body is not None: - if format == "text": - if text_body is not None: - raise Warning("You've passed in both a body and a " - "text_body; please choose one or the other.") - text_body = body - else: - if html_body is not None: - raise Warning("You've passed in both a body and an " - "html_body; please choose one or the other.") - html_body = body - - params = { - 'Source': source, - 'Message.Subject.Data': subject, - } - - if return_path: - params['ReturnPath'] = return_path - - if html_body is not None: - params['Message.Body.Html.Data'] = html_body - if text_body is not None: - params['Message.Body.Text.Data'] = text_body - - if(format not in ("text", "html")): - raise ValueError("'format' argument must be 'text' or 'html'") - - if(not (html_body or text_body)): - raise ValueError("No text or html body found for mail") - - self._build_list_params(params, to_addresses, - 'Destination.ToAddresses.member') - if cc_addresses: - self._build_list_params(params, cc_addresses, - 'Destination.CcAddresses.member') - - if bcc_addresses: - self._build_list_params(params, bcc_addresses, - 'Destination.BccAddresses.member') - - if reply_addresses: - self._build_list_params(params, reply_addresses, - 'ReplyToAddresses.member') - - return self._make_request('SendEmail', params) - - def send_raw_email(self, raw_message, source=None, destinations=None): - """Sends an email message, with header and content specified by the - client. The SendRawEmail action is useful for sending multipart MIME - emails, with attachments or inline content. The raw text of the message - must comply with Internet email standards; otherwise, the message - cannot be sent. - - :type source: string - :param source: The sender's email address. Amazon's docs say: - - If you specify the Source parameter, then bounce notifications and - complaints will be sent to this email address. This takes precedence - over any Return-Path header that you might include in the raw text of - the message. - - :type raw_message: string - :param raw_message: The raw text of the message. The client is - responsible for ensuring the following: - - - Message must contain a header and a body, separated by a blank line. - - All required header fields must be present. - - Each part of a multipart MIME message must be formatted properly. - - MIME content types must be among those supported by Amazon SES. - Refer to the Amazon SES Developer Guide for more details. - - Content must be base64-encoded, if MIME requires it. - - :type destinations: list of strings or string - :param destinations: A list of destinations for the message. - - """ - - if isinstance(raw_message, six.text_type): - raw_message = raw_message.encode('utf-8') - - params = { - 'RawMessage.Data': base64.b64encode(raw_message), - } - - if source: - params['Source'] = source - - if destinations: - self._build_list_params(params, destinations, - 'Destinations.member') - - return self._make_request('SendRawEmail', params) - - def list_verified_email_addresses(self): - """Fetch a list of the email addresses that have been verified. - - :rtype: dict - :returns: A ListVerifiedEmailAddressesResponse structure. Note that - keys must be unicode strings. - """ - return self._make_request('ListVerifiedEmailAddresses') - - def get_send_quota(self): - """Fetches the user's current activity limits. - - :rtype: dict - :returns: A GetSendQuotaResponse structure. Note that keys must be - unicode strings. - """ - return self._make_request('GetSendQuota') - - def get_send_statistics(self): - """Fetches the user's sending statistics. The result is a list of data - points, representing the last two weeks of sending activity. - - Each data point in the list contains statistics for a 15-minute - interval. - - :rtype: dict - :returns: A GetSendStatisticsResponse structure. Note that keys must be - unicode strings. - """ - return self._make_request('GetSendStatistics') - - def delete_verified_email_address(self, email_address): - """Deletes the specified email address from the list of verified - addresses. - - :type email_adddress: string - :param email_address: The email address to be removed from the list of - verified addreses. - - :rtype: dict - :returns: A DeleteVerifiedEmailAddressResponse structure. Note that - keys must be unicode strings. - """ - return self._make_request('DeleteVerifiedEmailAddress', { - 'EmailAddress': email_address, - }) - - def verify_email_address(self, email_address): - """Verifies an email address. This action causes a confirmation email - message to be sent to the specified address. - - :type email_adddress: string - :param email_address: The email address to be verified. - - :rtype: dict - :returns: A VerifyEmailAddressResponse structure. Note that keys must - be unicode strings. - """ - return self._make_request('VerifyEmailAddress', { - 'EmailAddress': email_address, - }) - - def verify_domain_dkim(self, domain): - """ - Returns a set of DNS records, or tokens, that must be published in the - domain name's DNS to complete the DKIM verification process. These - tokens are DNS ``CNAME`` records that point to DKIM public keys hosted - by Amazon SES. To complete the DKIM verification process, these tokens - must be published in the domain's DNS. The tokens must remain - published in order for Easy DKIM signing to function correctly. - - After the tokens are added to the domain's DNS, Amazon SES will be able - to DKIM-sign email originating from that domain. To enable or disable - Easy DKIM signing for a domain, use the ``SetIdentityDkimEnabled`` - action. For more information about Easy DKIM, go to the `Amazon SES - Developer Guide - <http://docs.amazonwebservices.com/ses/latest/DeveloperGuide>`_. - - :type domain: string - :param domain: The domain name. - - """ - return self._make_request('VerifyDomainDkim', { - 'Domain': domain, - }) - - def set_identity_dkim_enabled(self, identity, dkim_enabled): - """Enables or disables DKIM signing of email sent from an identity. - - * If Easy DKIM signing is enabled for a domain name identity (e.g., - * ``example.com``), - then Amazon SES will DKIM-sign all email sent by addresses under that - domain name (e.g., ``user@example.com``) - * If Easy DKIM signing is enabled for an email address, then Amazon SES - will DKIM-sign all email sent by that email address. - - For email addresses (e.g., ``user@example.com``), you can only enable - Easy DKIM signing if the corresponding domain (e.g., ``example.com``) - has been set up for Easy DKIM using the AWS Console or the - ``VerifyDomainDkim`` action. - - :type identity: string - :param identity: An email address or domain name. - - :type dkim_enabled: bool - :param dkim_enabled: Specifies whether or not to enable DKIM signing. - - """ - return self._make_request('SetIdentityDkimEnabled', { - 'Identity': identity, - 'DkimEnabled': 'true' if dkim_enabled else 'false' - }) - - def get_identity_dkim_attributes(self, identities): - """Get attributes associated with a list of verified identities. - - Given a list of verified identities (email addresses and/or domains), - returns a structure describing identity notification attributes. - - :type identities: list - :param identities: A list of verified identities (email addresses - and/or domains). - - """ - params = {} - self._build_list_params(params, identities, 'Identities.member') - return self._make_request('GetIdentityDkimAttributes', params) - - def list_identities(self): - """Returns a list containing all of the identities (email addresses - and domains) for a specific AWS Account, regardless of - verification status. - - :rtype: dict - :returns: A ListIdentitiesResponse structure. Note that - keys must be unicode strings. - """ - return self._make_request('ListIdentities') - - def get_identity_verification_attributes(self, identities): - """Given a list of identities (email addresses and/or domains), - returns the verification status and (for domain identities) - the verification token for each identity. - - :type identities: list of strings or string - :param identities: List of identities. - - :rtype: dict - :returns: A GetIdentityVerificationAttributesResponse structure. - Note that keys must be unicode strings. - """ - params = {} - self._build_list_params(params, identities, - 'Identities.member') - return self._make_request('GetIdentityVerificationAttributes', params) - - def verify_domain_identity(self, domain): - """Verifies a domain. - - :type domain: string - :param domain: The domain to be verified. - - :rtype: dict - :returns: A VerifyDomainIdentityResponse structure. Note that - keys must be unicode strings. - """ - return self._make_request('VerifyDomainIdentity', { - 'Domain': domain, - }) - - def verify_email_identity(self, email_address): - """Verifies an email address. This action causes a confirmation - email message to be sent to the specified address. - - :type email_adddress: string - :param email_address: The email address to be verified. - - :rtype: dict - :returns: A VerifyEmailIdentityResponse structure. Note that keys must - be unicode strings. - """ - return self._make_request('VerifyEmailIdentity', { - 'EmailAddress': email_address, - }) - - def delete_identity(self, identity): - """Deletes the specified identity (email address or domain) from - the list of verified identities. - - :type identity: string - :param identity: The identity to be deleted. - - :rtype: dict - :returns: A DeleteIdentityResponse structure. Note that keys must - be unicode strings. - """ - return self._make_request('DeleteIdentity', { - 'Identity': identity, - }) - - def set_identity_notification_topic(self, identity, notification_type, sns_topic=None): - """Sets an SNS topic to publish bounce or complaint notifications for - emails sent with the given identity as the Source. Publishing to topics - may only be disabled when feedback forwarding is enabled. - - :type identity: string - :param identity: An email address or domain name. - - :type notification_type: string - :param notification_type: The type of feedback notifications that will - be published to the specified topic. - Valid Values: Bounce | Complaint | Delivery - - :type sns_topic: string or None - :param sns_topic: The Amazon Resource Name (ARN) of the Amazon Simple - Notification Service (Amazon SNS) topic. - """ - params = { - 'Identity': identity, - 'NotificationType': notification_type - } - if sns_topic: - params['SnsTopic'] = sns_topic - return self._make_request('SetIdentityNotificationTopic', params) - - def set_identity_feedback_forwarding_enabled(self, identity, forwarding_enabled=True): - """ - Enables or disables SES feedback notification via email. - Feedback forwarding may only be disabled when both complaint and - bounce topics are set. - - :type identity: string - :param identity: An email address or domain name. - - :type forwarding_enabled: bool - :param forwarding_enabled: Specifies whether or not to enable feedback forwarding. - """ - return self._make_request('SetIdentityFeedbackForwardingEnabled', { - 'Identity': identity, - 'ForwardingEnabled': 'true' if forwarding_enabled else 'false' - }) diff --git a/awx/lib/site-packages/boto/ses/exceptions.py b/awx/lib/site-packages/boto/ses/exceptions.py deleted file mode 100644 index d5649f61a6..0000000000 --- a/awx/lib/site-packages/boto/ses/exceptions.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -Various exceptions that are specific to the SES module. -""" -from boto.exception import BotoServerError - - -class SESError(BotoServerError): - """ - Sub-class all SES-related errors from here. Don't raise this error - directly from anywhere. The only thing this gets us is the ability to - catch SESErrors separately from the more generic, top-level - BotoServerError exception. - """ - pass - - -class SESAddressNotVerifiedError(SESError): - """ - Raised when a "Reply-To" address has not been validated in SES yet. - """ - pass - - -class SESIdentityNotVerifiedError(SESError): - """ - Raised when an identity (domain or address) has not been verified in SES yet. - """ - pass - - -class SESDomainNotConfirmedError(SESError): - """ - """ - pass - - -class SESAddressBlacklistedError(SESError): - """ - After you attempt to send mail to an address, and delivery repeatedly - fails, said address is blacklisted for at least 24 hours. The blacklisting - eventually expires, and you are able to attempt delivery again. If you - attempt to send mail to a blacklisted email, this is raised. - """ - pass - - -class SESDailyQuotaExceededError(SESError): - """ - Your account's daily (rolling 24 hour total) allotment of outbound emails - has been exceeded. - """ - pass - - -class SESMaxSendingRateExceededError(SESError): - """ - Your account's requests/second limit has been exceeded. - """ - pass - - -class SESDomainEndsWithDotError(SESError): - """ - Recipient's email address' domain ends with a period/dot. - """ - pass - - -class SESLocalAddressCharacterError(SESError): - """ - An address contained a control or whitespace character. - """ - pass - - -class SESIllegalAddressError(SESError): - """ - Raised when an illegal address is encountered. - """ - pass diff --git a/awx/lib/site-packages/boto/sns/__init__.py b/awx/lib/site-packages/boto/sns/__init__.py deleted file mode 100644 index 2fb882cc41..0000000000 --- a/awx/lib/site-packages/boto/sns/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2010-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010-2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# this is here for backward compatibility -# originally, the SNSConnection class was defined here -from boto.sns.connection import SNSConnection -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the SNS service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` instances - """ - return get_regions('sns', connection_cls=SNSConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.sns.connection.SNSConnection`. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.sns.connection.SNSConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/sns/connection.py b/awx/lib/site-packages/boto/sns/connection.py deleted file mode 100644 index 5a6da205f4..0000000000 --- a/awx/lib/site-packages/boto/sns/connection.py +++ /dev/null @@ -1,765 +0,0 @@ -# Copyright (c) 2010-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import uuid -import hashlib - -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.compat import json -import boto - - -class SNSConnection(AWSQueryConnection): - """ - Amazon Simple Notification Service - Amazon Simple Notification Service (Amazon SNS) is a web service - that enables you to build distributed web-enabled applications. - Applications can use Amazon SNS to easily push real-time - notification messages to interested subscribers over multiple - delivery protocols. For more information about this product see - `http://aws.amazon.com/sns`_. For detailed information about - Amazon SNS features and their associated API calls, see the - `Amazon SNS Developer Guide`_. - - We also provide SDKs that enable you to access Amazon SNS from - your preferred programming language. The SDKs contain - functionality that automatically takes care of tasks such as: - cryptographically signing your service requests, retrying - requests, and handling error responses. For a list of available - SDKs, go to `Tools for Amazon Web Services`_. - """ - DefaultRegionName = boto.config.get('Boto', 'sns_region_name', 'us-east-1') - DefaultRegionEndpoint = boto.config.get('Boto', 'sns_region_endpoint', - 'sns.us-east-1.amazonaws.com') - APIVersion = boto.config.get('Boto', 'sns_version', '2010-03-31') - - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, - profile_name=None): - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint, - connection_cls=SNSConnection) - self.region = region - super(SNSConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - - def _build_dict_as_list_params(self, params, dictionary, name): - """ - Serialize a parameter 'name' which value is a 'dictionary' into a list of parameters. - - See: http://docs.aws.amazon.com/sns/latest/api/API_SetPlatformApplicationAttributes.html - For example:: - - dictionary = {'PlatformPrincipal': 'foo', 'PlatformCredential': 'bar'} - name = 'Attributes' - - would result in params dict being populated with: - Attributes.entry.1.key = PlatformPrincipal - Attributes.entry.1.value = foo - Attributes.entry.2.key = PlatformCredential - Attributes.entry.2.value = bar - - :param params: the resulting parameters will be added to this dict - :param dictionary: dict - value of the serialized parameter - :param name: name of the serialized parameter - """ - items = sorted(dictionary.items(), key=lambda x:x[0]) - for kv, index in zip(items, list(range(1, len(items)+1))): - key, value = kv - prefix = '%s.entry.%s' % (name, index) - params['%s.key' % prefix] = key - params['%s.value' % prefix] = value - - def _required_auth_capability(self): - return ['hmac-v4'] - - def get_all_topics(self, next_token=None): - """ - :type next_token: string - :param next_token: Token returned by the previous call to - this method. - - """ - params = {} - if next_token: - params['NextToken'] = next_token - return self._make_request('ListTopics', params) - - def get_topic_attributes(self, topic): - """ - Get attributes of a Topic - - :type topic: string - :param topic: The ARN of the topic. - - """ - params = {'TopicArn': topic} - return self._make_request('GetTopicAttributes', params) - - def set_topic_attributes(self, topic, attr_name, attr_value): - """ - Get attributes of a Topic - - :type topic: string - :param topic: The ARN of the topic. - - :type attr_name: string - :param attr_name: The name of the attribute you want to set. - Only a subset of the topic's attributes are mutable. - Valid values: Policy | DisplayName - - :type attr_value: string - :param attr_value: The new value for the attribute. - - """ - params = {'TopicArn': topic, - 'AttributeName': attr_name, - 'AttributeValue': attr_value} - return self._make_request('SetTopicAttributes', params) - - def add_permission(self, topic, label, account_ids, actions): - """ - Adds a statement to a topic's access control policy, granting - access for the specified AWS accounts to the specified actions. - - :type topic: string - :param topic: The ARN of the topic. - - :type label: string - :param label: A unique identifier for the new policy statement. - - :type account_ids: list of strings - :param account_ids: The AWS account ids of the users who will be - give access to the specified actions. - - :type actions: list of strings - :param actions: The actions you want to allow for each of the - specified principal(s). - - """ - params = {'TopicArn': topic, - 'Label': label} - self.build_list_params(params, account_ids, 'AWSAccountId.member') - self.build_list_params(params, actions, 'ActionName.member') - return self._make_request('AddPermission', params) - - def remove_permission(self, topic, label): - """ - Removes a statement from a topic's access control policy. - - :type topic: string - :param topic: The ARN of the topic. - - :type label: string - :param label: A unique identifier for the policy statement - to be removed. - - """ - params = {'TopicArn': topic, - 'Label': label} - return self._make_request('RemovePermission', params) - - def create_topic(self, topic): - """ - Create a new Topic. - - :type topic: string - :param topic: The name of the new topic. - - """ - params = {'Name': topic} - return self._make_request('CreateTopic', params) - - def delete_topic(self, topic): - """ - Delete an existing topic - - :type topic: string - :param topic: The ARN of the topic - - """ - params = {'TopicArn': topic} - return self._make_request('DeleteTopic', params, '/', 'GET') - - def publish(self, topic=None, message=None, subject=None, target_arn=None, - message_structure=None, message_attributes=None): - """ - Get properties of a Topic - - :type topic: string - :param topic: The ARN of the new topic. - - :type message: string - :param message: The message you want to send to the topic. - Messages must be UTF-8 encoded strings and - be at most 4KB in size. - - :type message_structure: string - :param message_structure: Optional parameter. If left as ``None``, - plain text will be sent. If set to ``json``, - your message should be a JSON string that - matches the structure described at - http://docs.aws.amazon.com/sns/latest/dg/PublishTopic.html#sns-message-formatting-by-protocol - - :type message_attributes: dict - :param message_attributes: Message attributes to set. Should be - of the form: - - .. code-block:: python - - { - "name1": { - "data_type": "Number", - "string_value": "42" - }, - "name2": { - "data_type": "String", - "string_value": "Bob" - } - } - - :type subject: string - :param subject: Optional parameter to be used as the "Subject" - line of the email notifications. - - :type target_arn: string - :param target_arn: Optional parameter for either TopicArn or - EndpointArn, but not both. - - """ - if message is None: - # To be backwards compatible when message did not have - # a default value and topic and message were required - # args. - raise TypeError("'message' is a required parameter") - params = {'Message': message} - if subject is not None: - params['Subject'] = subject - if topic is not None: - params['TopicArn'] = topic - if target_arn is not None: - params['TargetArn'] = target_arn - if message_structure is not None: - params['MessageStructure'] = message_structure - if message_attributes is not None: - keys = sorted(message_attributes.keys()) - for i, name in enumerate(keys, start=1): - attribute = message_attributes[name] - params['MessageAttributes.entry.{0}.Name'.format(i)] = name - if 'data_type' in attribute: - params['MessageAttributes.entry.{0}.Value.DataType'.format(i)] = \ - attribute['data_type'] - if 'string_value' in attribute: - params['MessageAttributes.entry.{0}.Value.StringValue'.format(i)] = \ - attribute['string_value'] - if 'binary_value' in attribute: - params['MessageAttributes.entry.{0}.Value.BinaryValue'.format(i)] = \ - attribute['binary_value'] - return self._make_request('Publish', params, '/', 'POST') - - def subscribe(self, topic, protocol, endpoint): - """ - Subscribe to a Topic. - - :type topic: string - :param topic: The ARN of the new topic. - - :type protocol: string - :param protocol: The protocol used to communicate with - the subscriber. Current choices are: - email|email-json|http|https|sqs|sms|application - - :type endpoint: string - :param endpoint: The location of the endpoint for - the subscriber. - * For email, this would be a valid email address - * For email-json, this would be a valid email address - * For http, this would be a URL beginning with http - * For https, this would be a URL beginning with https - * For sqs, this would be the ARN of an SQS Queue - * For sms, this would be a phone number of an - SMS-enabled device - * For application, the endpoint is the EndpointArn - of a mobile app and device. - """ - params = {'TopicArn': topic, - 'Protocol': protocol, - 'Endpoint': endpoint} - return self._make_request('Subscribe', params) - - def subscribe_sqs_queue(self, topic, queue): - """ - Subscribe an SQS queue to a topic. - - This is convenience method that handles most of the complexity involved - in using an SQS queue as an endpoint for an SNS topic. To achieve this - the following operations are performed: - - * The correct ARN is constructed for the SQS queue and that ARN is - then subscribed to the topic. - * A JSON policy document is contructed that grants permission to - the SNS topic to send messages to the SQS queue. - * This JSON policy is then associated with the SQS queue using - the queue's set_attribute method. If the queue already has - a policy associated with it, this process will add a Statement to - that policy. If no policy exists, a new policy will be created. - - :type topic: string - :param topic: The ARN of the new topic. - - :type queue: A boto Queue object - :param queue: The queue you wish to subscribe to the SNS Topic. - """ - t = queue.id.split('/') - q_arn = queue.arn - sid = hashlib.md5((topic + q_arn).encode('utf-8')).hexdigest() - sid_exists = False - resp = self.subscribe(topic, 'sqs', q_arn) - attr = queue.get_attributes('Policy') - if 'Policy' in attr: - policy = json.loads(attr['Policy']) - else: - policy = {} - if 'Version' not in policy: - policy['Version'] = '2008-10-17' - if 'Statement' not in policy: - policy['Statement'] = [] - # See if a Statement with the Sid exists already. - for s in policy['Statement']: - if s['Sid'] == sid: - sid_exists = True - if not sid_exists: - statement = {'Action': 'SQS:SendMessage', - 'Effect': 'Allow', - 'Principal': {'AWS': '*'}, - 'Resource': q_arn, - 'Sid': sid, - 'Condition': {'StringLike': {'aws:SourceArn': topic}}} - policy['Statement'].append(statement) - queue.set_attribute('Policy', json.dumps(policy)) - return resp - - def confirm_subscription(self, topic, token, - authenticate_on_unsubscribe=False): - """ - Get properties of a Topic - - :type topic: string - :param topic: The ARN of the new topic. - - :type token: string - :param token: Short-lived token sent to and endpoint during - the Subscribe operation. - - :type authenticate_on_unsubscribe: bool - :param authenticate_on_unsubscribe: Optional parameter indicating - that you wish to disable - unauthenticated unsubscription - of the subscription. - - """ - params = {'TopicArn': topic, 'Token': token} - if authenticate_on_unsubscribe: - params['AuthenticateOnUnsubscribe'] = 'true' - return self._make_request('ConfirmSubscription', params) - - def unsubscribe(self, subscription): - """ - Allows endpoint owner to delete subscription. - Confirmation message will be delivered. - - :type subscription: string - :param subscription: The ARN of the subscription to be deleted. - - """ - params = {'SubscriptionArn': subscription} - return self._make_request('Unsubscribe', params) - - def get_all_subscriptions(self, next_token=None): - """ - Get list of all subscriptions. - - :type next_token: string - :param next_token: Token returned by the previous call to - this method. - - """ - params = {} - if next_token: - params['NextToken'] = next_token - return self._make_request('ListSubscriptions', params) - - def get_all_subscriptions_by_topic(self, topic, next_token=None): - """ - Get list of all subscriptions to a specific topic. - - :type topic: string - :param topic: The ARN of the topic for which you wish to - find subscriptions. - - :type next_token: string - :param next_token: Token returned by the previous call to - this method. - - """ - params = {'TopicArn': topic} - if next_token: - params['NextToken'] = next_token - return self._make_request('ListSubscriptionsByTopic', params) - - def create_platform_application(self, name=None, platform=None, - attributes=None): - """ - The `CreatePlatformApplication` action creates a platform - application object for one of the supported push notification - services, such as APNS and GCM, to which devices and mobile - apps may register. You must specify PlatformPrincipal and - PlatformCredential attributes when using the - `CreatePlatformApplication` action. The PlatformPrincipal is - received from the notification service. For APNS/APNS_SANDBOX, - PlatformPrincipal is "SSL certificate". For GCM, - PlatformPrincipal is not applicable. For ADM, - PlatformPrincipal is "client id". The PlatformCredential is - also received from the notification service. For - APNS/APNS_SANDBOX, PlatformCredential is "private key". For - GCM, PlatformCredential is "API key". For ADM, - PlatformCredential is "client secret". The - PlatformApplicationArn that is returned when using - `CreatePlatformApplication` is then used as an attribute for - the `CreatePlatformEndpoint` action. For more information, see - `Using Amazon SNS Mobile Push Notifications`_. - - :type name: string - :param name: Application names must be made up of only uppercase and - lowercase ASCII letters, numbers, underscores, hyphens, and - periods, and must be between 1 and 256 characters long. - - :type platform: string - :param platform: The following platforms are supported: ADM (Amazon - Device Messaging), APNS (Apple Push Notification Service), - APNS_SANDBOX, and GCM (Google Cloud Messaging). - - :type attributes: map - :param attributes: For a list of attributes, see - `SetPlatformApplicationAttributes`_ - - """ - params = {} - if name is not None: - params['Name'] = name - if platform is not None: - params['Platform'] = platform - if attributes is not None: - self._build_dict_as_list_params(params, attributes, 'Attributes') - return self._make_request(action='CreatePlatformApplication', - params=params) - - def set_platform_application_attributes(self, - platform_application_arn=None, - attributes=None): - """ - The `SetPlatformApplicationAttributes` action sets the - attributes of the platform application object for the - supported push notification services, such as APNS and GCM. - For more information, see `Using Amazon SNS Mobile Push - Notifications`_. - - :type platform_application_arn: string - :param platform_application_arn: PlatformApplicationArn for - SetPlatformApplicationAttributes action. - - :type attributes: map - :param attributes: - A map of the platform application attributes. Attributes in this map - include the following: - - - + `PlatformCredential` -- The credential received from the notification - service. For APNS/APNS_SANDBOX, PlatformCredential is "private - key". For GCM, PlatformCredential is "API key". For ADM, - PlatformCredential is "client secret". - + `PlatformPrincipal` -- The principal received from the notification - service. For APNS/APNS_SANDBOX, PlatformPrincipal is "SSL - certificate". For GCM, PlatformPrincipal is not applicable. For - ADM, PlatformPrincipal is "client id". - + `EventEndpointCreated` -- Topic ARN to which EndpointCreated event - notifications should be sent. - + `EventEndpointDeleted` -- Topic ARN to which EndpointDeleted event - notifications should be sent. - + `EventEndpointUpdated` -- Topic ARN to which EndpointUpdate event - notifications should be sent. - + `EventDeliveryFailure` -- Topic ARN to which DeliveryFailure event - notifications should be sent upon Direct Publish delivery failure - (permanent) to one of the application's endpoints. - - """ - params = {} - if platform_application_arn is not None: - params['PlatformApplicationArn'] = platform_application_arn - if attributes is not None: - self._build_dict_as_list_params(params, attributes, 'Attributes') - return self._make_request(action='SetPlatformApplicationAttributes', - params=params) - - def get_platform_application_attributes(self, - platform_application_arn=None): - """ - The `GetPlatformApplicationAttributes` action retrieves the - attributes of the platform application object for the - supported push notification services, such as APNS and GCM. - For more information, see `Using Amazon SNS Mobile Push - Notifications`_. - - :type platform_application_arn: string - :param platform_application_arn: PlatformApplicationArn for - GetPlatformApplicationAttributesInput. - - """ - params = {} - if platform_application_arn is not None: - params['PlatformApplicationArn'] = platform_application_arn - return self._make_request(action='GetPlatformApplicationAttributes', - params=params) - - def list_platform_applications(self, next_token=None): - """ - The `ListPlatformApplications` action lists the platform - application objects for the supported push notification - services, such as APNS and GCM. The results for - `ListPlatformApplications` are paginated and return a limited - list of applications, up to 100. If additional records are - available after the first page results, then a NextToken - string will be returned. To receive the next page, you call - `ListPlatformApplications` using the NextToken string received - from the previous call. When there are no more records to - return, NextToken will be null. For more information, see - `Using Amazon SNS Mobile Push Notifications`_. - - :type next_token: string - :param next_token: NextToken string is used when calling - ListPlatformApplications action to retrieve additional records that - are available after the first page results. - - """ - params = {} - if next_token is not None: - params['NextToken'] = next_token - return self._make_request(action='ListPlatformApplications', - params=params) - - def list_endpoints_by_platform_application(self, - platform_application_arn=None, - next_token=None): - """ - The `ListEndpointsByPlatformApplication` action lists the - endpoints and endpoint attributes for devices in a supported - push notification service, such as GCM and APNS. The results - for `ListEndpointsByPlatformApplication` are paginated and - return a limited list of endpoints, up to 100. If additional - records are available after the first page results, then a - NextToken string will be returned. To receive the next page, - you call `ListEndpointsByPlatformApplication` again using the - NextToken string received from the previous call. When there - are no more records to return, NextToken will be null. For - more information, see `Using Amazon SNS Mobile Push - Notifications`_. - - :type platform_application_arn: string - :param platform_application_arn: PlatformApplicationArn for - ListEndpointsByPlatformApplicationInput action. - - :type next_token: string - :param next_token: NextToken string is used when calling - ListEndpointsByPlatformApplication action to retrieve additional - records that are available after the first page results. - - """ - params = {} - if platform_application_arn is not None: - params['PlatformApplicationArn'] = platform_application_arn - if next_token is not None: - params['NextToken'] = next_token - return self._make_request(action='ListEndpointsByPlatformApplication', - params=params) - - def delete_platform_application(self, platform_application_arn=None): - """ - The `DeletePlatformApplication` action deletes a platform - application object for one of the supported push notification - services, such as APNS and GCM. For more information, see - `Using Amazon SNS Mobile Push Notifications`_. - - :type platform_application_arn: string - :param platform_application_arn: PlatformApplicationArn of platform - application object to delete. - - """ - params = {} - if platform_application_arn is not None: - params['PlatformApplicationArn'] = platform_application_arn - return self._make_request(action='DeletePlatformApplication', - params=params) - - def create_platform_endpoint(self, platform_application_arn=None, - token=None, custom_user_data=None, - attributes=None): - """ - The `CreatePlatformEndpoint` creates an endpoint for a device - and mobile app on one of the supported push notification - services, such as GCM and APNS. `CreatePlatformEndpoint` - requires the PlatformApplicationArn that is returned from - `CreatePlatformApplication`. The EndpointArn that is returned - when using `CreatePlatformEndpoint` can then be used by the - `Publish` action to send a message to a mobile app or by the - `Subscribe` action for subscription to a topic. For more - information, see `Using Amazon SNS Mobile Push - Notifications`_. - - :type platform_application_arn: string - :param platform_application_arn: PlatformApplicationArn returned from - CreatePlatformApplication is used to create a an endpoint. - - :type token: string - :param token: Unique identifier created by the notification service for - an app on a device. The specific name for Token will vary, - depending on which notification service is being used. For example, - when using APNS as the notification service, you need the device - token. Alternatively, when using GCM or ADM, the device token - equivalent is called the registration ID. - - :type custom_user_data: string - :param custom_user_data: Arbitrary user data to associate with the - endpoint. SNS does not use this data. The data must be in UTF-8 - format and less than 2KB. - - :type attributes: map - :param attributes: For a list of attributes, see - `SetEndpointAttributes`_. - - """ - params = {} - if platform_application_arn is not None: - params['PlatformApplicationArn'] = platform_application_arn - if token is not None: - params['Token'] = token - if custom_user_data is not None: - params['CustomUserData'] = custom_user_data - if attributes is not None: - self._build_dict_as_list_params(params, attributes, 'Attributes') - return self._make_request(action='CreatePlatformEndpoint', - params=params) - - def delete_endpoint(self, endpoint_arn=None): - """ - The `DeleteEndpoint` action, which is idempotent, deletes the - endpoint from SNS. For more information, see `Using Amazon SNS - Mobile Push Notifications`_. - - :type endpoint_arn: string - :param endpoint_arn: EndpointArn of endpoint to delete. - - """ - params = {} - if endpoint_arn is not None: - params['EndpointArn'] = endpoint_arn - return self._make_request(action='DeleteEndpoint', params=params) - - def set_endpoint_attributes(self, endpoint_arn=None, attributes=None): - """ - The `SetEndpointAttributes` action sets the attributes for an - endpoint for a device on one of the supported push - notification services, such as GCM and APNS. For more - information, see `Using Amazon SNS Mobile Push - Notifications`_. - - :type endpoint_arn: string - :param endpoint_arn: EndpointArn used for SetEndpointAttributes action. - - :type attributes: map - :param attributes: - A map of the endpoint attributes. Attributes in this map include the - following: - - - + `CustomUserData` -- arbitrary user data to associate with the - endpoint. SNS does not use this data. The data must be in UTF-8 - format and less than 2KB. - + `Enabled` -- flag that enables/disables delivery to the endpoint. - Message Processor will set this to false when a notification - service indicates to SNS that the endpoint is invalid. Users can - set it back to true, typically after updating Token. - + `Token` -- device token, also referred to as a registration id, for - an app and mobile device. This is returned from the notification - service when an app and mobile device are registered with the - notification service. - - """ - params = {} - if endpoint_arn is not None: - params['EndpointArn'] = endpoint_arn - if attributes is not None: - self._build_dict_as_list_params(params, attributes, 'Attributes') - return self._make_request(action='SetEndpointAttributes', - params=params) - - def get_endpoint_attributes(self, endpoint_arn=None): - """ - The `GetEndpointAttributes` retrieves the endpoint attributes - for a device on one of the supported push notification - services, such as GCM and APNS. For more information, see - `Using Amazon SNS Mobile Push Notifications`_. - - :type endpoint_arn: string - :param endpoint_arn: EndpointArn for GetEndpointAttributes input. - - """ - params = {} - if endpoint_arn is not None: - params['EndpointArn'] = endpoint_arn - return self._make_request(action='GetEndpointAttributes', - params=params) - - def _make_request(self, action, params, path='/', verb='GET'): - params['ContentType'] = 'JSON' - response = self.make_request(action=action, verb=verb, - path=path, params=params) - body = response.read().decode('utf-8') - boto.log.debug(body) - if response.status == 200: - return json.loads(body) - else: - boto.log.error('%s %s' % (response.status, response.reason)) - boto.log.error('%s' % body) - raise self.ResponseError(response.status, response.reason, body) diff --git a/awx/lib/site-packages/boto/sqs/__init__.py b/awx/lib/site-packages/boto/sqs/__init__.py deleted file mode 100644 index ccad732ec3..0000000000 --- a/awx/lib/site-packages/boto/sqs/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.sqs.regioninfo import SQSRegionInfo -from boto.regioninfo import get_regions - - -def regions(): - """ - Get all available regions for the SQS service. - - :rtype: list - :return: A list of :class:`boto.sqs.regioninfo.RegionInfo` - """ - from boto.sqs.connection import SQSConnection - return get_regions( - 'sqs', - region_cls=SQSRegionInfo, - connection_cls=SQSConnection - ) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/sqs/attributes.py b/awx/lib/site-packages/boto/sqs/attributes.py deleted file mode 100644 index 26c720416f..0000000000 --- a/awx/lib/site-packages/boto/sqs/attributes.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an SQS Attribute Name/Value set -""" - -class Attributes(dict): - - def __init__(self, parent): - self.parent = parent - self.current_key = None - self.current_value = None - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Attribute': - self[self.current_key] = self.current_value - elif name == 'Name': - self.current_key = value - elif name == 'Value': - self.current_value = value - else: - setattr(self, name, value) - - diff --git a/awx/lib/site-packages/boto/sqs/batchresults.py b/awx/lib/site-packages/boto/sqs/batchresults.py deleted file mode 100644 index aa5f86b8be..0000000000 --- a/awx/lib/site-packages/boto/sqs/batchresults.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011 Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -A set of results returned by SendMessageBatch. -""" - -class ResultEntry(dict): - """ - The result (successful or unsuccessful) of a single - message within a send_message_batch request. - - In the case of a successful result, this dict-like - object will contain the following items: - - :ivar id: A string containing the user-supplied ID of the message. - :ivar message_id: A string containing the SQS ID of the new message. - :ivar message_md5: A string containing the MD5 hash of the message body. - - In the case of an error, this object will contain the following - items: - - :ivar id: A string containing the user-supplied ID of the message. - :ivar sender_fault: A boolean value. - :ivar error_code: A string containing a short description of the error. - :ivar error_message: A string containing a description of the error. - """ - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'Id': - self['id'] = value - elif name == 'MessageId': - self['message_id'] = value - elif name == 'MD5OfMessageBody': - self['message_md5'] = value - elif name == 'SenderFault': - self['sender_fault'] = value - elif name == 'Code': - self['error_code'] = value - elif name == 'Message': - self['error_message'] = value - -class BatchResults(object): - """ - A container for the results of a send_message_batch request. - - :ivar results: A list of successful results. Each item in the - list will be an instance of :class:`ResultEntry`. - - :ivar errors: A list of unsuccessful results. Each item in the - list will be an instance of :class:`ResultEntry`. - """ - - def __init__(self, parent): - self.parent = parent - self.results = [] - self.errors = [] - - def startElement(self, name, attrs, connection): - if name.endswith('MessageBatchResultEntry'): - entry = ResultEntry() - self.results.append(entry) - return entry - if name == 'BatchResultErrorEntry': - entry = ResultEntry() - self.errors.append(entry) - return entry - return None - - def endElement(self, name, value, connection): - setattr(self, name, value) - - diff --git a/awx/lib/site-packages/boto/sqs/bigmessage.py b/awx/lib/site-packages/boto/sqs/bigmessage.py deleted file mode 100644 index e47ec045a1..0000000000 --- a/awx/lib/site-packages/boto/sqs/bigmessage.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (c) 2013 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import uuid - -import boto -from boto.sqs.message import RawMessage -from boto.exception import SQSDecodeError - - -class BigMessage(RawMessage): - """ - The BigMessage class provides large payloads (up to 5GB) - by storing the payload itself in S3 and then placing a reference - to the S3 object in the actual SQS message payload. - - To create a BigMessage, you should create a BigMessage object - and pass in a file-like object as the ``body`` param and also - pass in the an S3 URL specifying the bucket in which to store - the message body:: - - import boto.sqs - from boto.sqs.bigmessage import BigMessage - - sqs = boto.sqs.connect_to_region('us-west-2') - queue = sqs.get_queue('myqueue') - fp = open('/path/to/bigmessage/data') - msg = BigMessage(queue, fp, 's3://mybucket') - queue.write(msg) - - Passing in a fully-qualified S3 URL (e.g. s3://mybucket/foo) - is interpreted to mean that the body of the message is already - stored in S3 and the that S3 URL is then used directly with no - content uploaded by BigMessage. - """ - - def __init__(self, queue=None, body=None, s3_url=None): - self.s3_url = s3_url - super(BigMessage, self).__init__(queue, body) - - def _get_bucket_key(self, s3_url): - bucket_name = key_name = None - if s3_url: - if s3_url.startswith('s3://'): - # We need to split out the bucket from the key (if - # supplied). We also have to be aware that someone - # may provide a trailing '/' character as in: - # s3://foo/ and we want to handle that. - s3_components = s3_url[5:].split('/', 1) - bucket_name = s3_components[0] - if len(s3_components) > 1: - if s3_components[1]: - key_name = s3_components[1] - else: - msg = 's3_url parameter should start with s3://' - raise SQSDecodeError(msg, self) - return bucket_name, key_name - - def encode(self, value): - """ - :type value: file-like object - :param value: A file-like object containing the content - of the message. The actual content will be stored - in S3 and a link to the S3 object will be stored in - the message body. - """ - bucket_name, key_name = self._get_bucket_key(self.s3_url) - if bucket_name and key_name: - return self.s3_url - key_name = uuid.uuid4() - s3_conn = boto.connect_s3() - s3_bucket = s3_conn.get_bucket(bucket_name) - key = s3_bucket.new_key(key_name) - key.set_contents_from_file(value) - self.s3_url = 's3://%s/%s' % (bucket_name, key_name) - return self.s3_url - - def _get_s3_object(self, s3_url): - bucket_name, key_name = self._get_bucket_key(s3_url) - if bucket_name and key_name: - s3_conn = boto.connect_s3() - s3_bucket = s3_conn.get_bucket(bucket_name) - key = s3_bucket.get_key(key_name) - return key - else: - msg = 'Unable to decode S3 URL: %s' % s3_url - raise SQSDecodeError(msg, self) - - def decode(self, value): - self.s3_url = value - key = self._get_s3_object(value) - return key.get_contents_as_string() - - def delete(self): - # Delete the object in S3 first, then delete the SQS message - if self.s3_url: - key = self._get_s3_object(self.s3_url) - key.delete() - super(BigMessage, self).delete() - diff --git a/awx/lib/site-packages/boto/sqs/connection.py b/awx/lib/site-packages/boto/sqs/connection.py deleted file mode 100644 index e2f59d799b..0000000000 --- a/awx/lib/site-packages/boto/sqs/connection.py +++ /dev/null @@ -1,525 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -from boto.connection import AWSQueryConnection -from boto.sqs.regioninfo import SQSRegionInfo -from boto.sqs.queue import Queue -from boto.sqs.message import Message -from boto.sqs.attributes import Attributes -from boto.sqs.batchresults import BatchResults -from boto.exception import SQSError, BotoServerError - - -class SQSConnection(AWSQueryConnection): - """ - A Connection to the SQS Service. - """ - DefaultRegionName = boto.config.get('Boto', 'sqs_region_name', 'us-east-1') - DefaultRegionEndpoint = boto.config.get('Boto', 'sqs_region_endpoint', - 'queue.amazonaws.com') - APIVersion = boto.config.get('Boto', 'sqs_version', '2012-11-05') - DefaultContentType = 'text/plain' - ResponseError = SQSError - AuthServiceName = 'sqs' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - security_token=None, validate_certs=True, profile_name=None): - if not region: - region = SQSRegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - self.region = region - super(SQSConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, - proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - security_token=security_token, - validate_certs=validate_certs, - profile_name=profile_name) - self.auth_region_name = self.region.name - - def _required_auth_capability(self): - return ['hmac-v4'] - - def create_queue(self, queue_name, visibility_timeout=None): - """ - Create an SQS Queue. - - :type queue_name: str or unicode - :param queue_name: The name of the new queue. Names are - scoped to an account and need to be unique within that - account. Calling this method on an existing queue name - will not return an error from SQS unless the value for - visibility_timeout is different than the value of the - existing queue of that name. This is still an expensive - operation, though, and not the preferred way to check for - the existence of a queue. See the - :func:`boto.sqs.connection.SQSConnection.lookup` method. - - :type visibility_timeout: int - :param visibility_timeout: The default visibility timeout for - all messages written in the queue. This can be overridden - on a per-message. - - :rtype: :class:`boto.sqs.queue.Queue` - :return: The newly created queue. - - """ - params = {'QueueName': queue_name} - if visibility_timeout: - params['Attribute.1.Name'] = 'VisibilityTimeout' - params['Attribute.1.Value'] = int(visibility_timeout) - return self.get_object('CreateQueue', params, Queue) - - def delete_queue(self, queue, force_deletion=False): - """ - Delete an SQS Queue. - - :type queue: A Queue object - :param queue: The SQS queue to be deleted - - :type force_deletion: Boolean - :param force_deletion: A deprecated parameter that is no longer used by - SQS's API. - - :rtype: bool - :return: True if the command succeeded, False otherwise - """ - return self.get_status('DeleteQueue', None, queue.id) - - def get_queue_attributes(self, queue, attribute='All'): - """ - Gets one or all attributes of a Queue - - :type queue: A Queue object - :param queue: The SQS queue to get attributes for - - :type attribute: str - :type attribute: The specific attribute requested. If not - supplied, the default is to return all attributes. Valid - attributes are: - - * All - * ApproximateNumberOfMessages - * ApproximateNumberOfMessagesNotVisible - * VisibilityTimeout - * CreatedTimestamp - * LastModifiedTimestamp - * Policy - * MaximumMessageSize - * MessageRetentionPeriod - * QueueArn - * ApproximateNumberOfMessagesDelayed - * DelaySeconds - * ReceiveMessageWaitTimeSeconds - * RedrivePolicy - - :rtype: :class:`boto.sqs.attributes.Attributes` - :return: An Attributes object containing request value(s). - """ - params = {'AttributeName' : attribute} - return self.get_object('GetQueueAttributes', params, - Attributes, queue.id) - - def set_queue_attribute(self, queue, attribute, value): - params = {'Attribute.Name' : attribute, 'Attribute.Value' : value} - return self.get_status('SetQueueAttributes', params, queue.id) - - def receive_message(self, queue, number_messages=1, - visibility_timeout=None, attributes=None, - wait_time_seconds=None, message_attributes=None): - """ - Read messages from an SQS Queue. - - :type queue: A Queue object - :param queue: The Queue from which messages are read. - - :type number_messages: int - :param number_messages: The maximum number of messages to read - (default=1) - - :type visibility_timeout: int - :param visibility_timeout: The number of seconds the message should - remain invisible to other queue readers - (default=None which uses the Queues default) - - :type attributes: str - :param attributes: The name of additional attribute to return - with response or All if you want all attributes. The - default is to return no additional attributes. Valid - values: - * All - * SenderId - * SentTimestamp - * ApproximateReceiveCount - * ApproximateFirstReceiveTimestamp - - :type wait_time_seconds: int - :param wait_time_seconds: The duration (in seconds) for which the call - will wait for a message to arrive in the queue before returning. - If a message is available, the call will return sooner than - wait_time_seconds. - - :type message_attributes: list - :param message_attributes: The name(s) of additional message - attributes to return. The default is to return no additional - message attributes. Use ``['All']`` or ``['.*']`` to return all. - - :rtype: list - :return: A list of :class:`boto.sqs.message.Message` objects. - - """ - params = {'MaxNumberOfMessages' : number_messages} - if visibility_timeout is not None: - params['VisibilityTimeout'] = visibility_timeout - if attributes is not None: - self.build_list_params(params, attributes, 'AttributeName') - if wait_time_seconds is not None: - params['WaitTimeSeconds'] = wait_time_seconds - if message_attributes is not None: - self.build_list_params(params, message_attributes, - 'MessageAttributeName') - return self.get_list('ReceiveMessage', params, - [('Message', queue.message_class)], - queue.id, queue) - - def delete_message(self, queue, message): - """ - Delete a message from a queue. - - :type queue: A :class:`boto.sqs.queue.Queue` object - :param queue: The Queue from which messages are read. - - :type message: A :class:`boto.sqs.message.Message` object - :param message: The Message to be deleted - - :rtype: bool - :return: True if successful, False otherwise. - """ - params = {'ReceiptHandle' : message.receipt_handle} - return self.get_status('DeleteMessage', params, queue.id) - - def delete_message_batch(self, queue, messages): - """ - Deletes a list of messages from a queue in a single request. - - :type queue: A :class:`boto.sqs.queue.Queue` object. - :param queue: The Queue to which the messages will be written. - - :type messages: List of :class:`boto.sqs.message.Message` objects. - :param messages: A list of message objects. - """ - params = {} - for i, msg in enumerate(messages): - prefix = 'DeleteMessageBatchRequestEntry' - p_name = '%s.%i.Id' % (prefix, (i+1)) - params[p_name] = msg.id - p_name = '%s.%i.ReceiptHandle' % (prefix, (i+1)) - params[p_name] = msg.receipt_handle - return self.get_object('DeleteMessageBatch', params, BatchResults, - queue.id, verb='POST') - - def delete_message_from_handle(self, queue, receipt_handle): - """ - Delete a message from a queue, given a receipt handle. - - :type queue: A :class:`boto.sqs.queue.Queue` object - :param queue: The Queue from which messages are read. - - :type receipt_handle: str - :param receipt_handle: The receipt handle for the message - - :rtype: bool - :return: True if successful, False otherwise. - """ - params = {'ReceiptHandle' : receipt_handle} - return self.get_status('DeleteMessage', params, queue.id) - - def send_message(self, queue, message_content, delay_seconds=None, - message_attributes=None): - """ - Send a new message to the queue. - - :type queue: A :class:`boto.sqs.queue.Queue` object. - :param queue: The Queue to which the messages will be written. - - :type message_content: string - :param message_content: The body of the message - - :type delay_seconds: int - :param delay_seconds: Number of seconds (0 - 900) to delay this - message from being processed. - - :type message_attributes: dict - :param message_attributes: Message attributes to set. Should be - of the form: - - { - "name1": { - "data_type": "Number", - "string_value": "1" - }, - "name2": { - "data_type": "String", - "string_value": "Bob" - } - } - - """ - params = {'MessageBody' : message_content} - if delay_seconds: - params['DelaySeconds'] = int(delay_seconds) - - if message_attributes is not None: - keys = sorted(message_attributes.keys()) - for i, name in enumerate(keys, start=1): - attribute = message_attributes[name] - params['MessageAttribute.%s.Name' % i] = name - if 'data_type' in attribute: - params['MessageAttribute.%s.Value.DataType' % i] = \ - attribute['data_type'] - if 'string_value' in attribute: - params['MessageAttribute.%s.Value.StringValue' % i] = \ - attribute['string_value'] - if 'binary_value' in attribute: - params['MessageAttribute.%s.Value.BinaryValue' % i] = \ - attribute['binary_value'] - if 'string_list_value' in attribute: - params['MessageAttribute.%s.Value.StringListValue' % i] = \ - attribute['string_list_value'] - if 'binary_list_value' in attribute: - params['MessageAttribute.%s.Value.BinaryListValue' % i] = \ - attribute['binary_list_value'] - - return self.get_object('SendMessage', params, Message, - queue.id, verb='POST') - - def send_message_batch(self, queue, messages): - """ - Delivers up to 10 messages to a queue in a single request. - - :type queue: A :class:`boto.sqs.queue.Queue` object. - :param queue: The Queue to which the messages will be written. - - :type messages: List of lists. - :param messages: A list of lists or tuples. Each inner - tuple represents a single message to be written - and consists of and ID (string) that must be unique - within the list of messages, the message body itself - which can be a maximum of 64K in length, an - integer which represents the delay time (in seconds) - for the message (0-900) before the message will - be delivered to the queue, and an optional dict of - message attributes like those passed to ``send_message`` - above. - - """ - params = {} - for i, msg in enumerate(messages): - base = 'SendMessageBatchRequestEntry.%i' % (i + 1) - params['%s.Id' % base] = msg[0] - params['%s.MessageBody' % base] = msg[1] - params['%s.DelaySeconds' % base] = msg[2] - if len(msg) > 3: - base += '.MessageAttribute' - keys = sorted(msg[3].keys()) - for j, name in enumerate(keys): - attribute = msg[3][name] - - p_name = '%s.%i.Name' % (base, j + 1) - params[p_name] = name - - if 'data_type' in attribute: - p_name = '%s.%i.DataType' % (base, j + 1) - params[p_name] = attribute['data_type'] - if 'string_value' in attribute: - p_name = '%s.%i.StringValue' % (base, j + 1) - params[p_name] = attribute['string_value'] - if 'binary_value' in attribute: - p_name = '%s.%i.BinaryValue' % (base, j + 1) - params[p_name] = attribute['binary_value'] - if 'string_list_value' in attribute: - p_name = '%s.%i.StringListValue' % (base, j + 1) - params[p_name] = attribute['string_list_value'] - if 'binary_list_value' in attribute: - p_name = '%s.%i.BinaryListValue' % (base, j + 1) - params[p_name] = attribute['binary_list_value'] - - return self.get_object('SendMessageBatch', params, BatchResults, - queue.id, verb='POST') - - def change_message_visibility(self, queue, receipt_handle, - visibility_timeout): - """ - Extends the read lock timeout for the specified message from - the specified queue to the specified value. - - :type queue: A :class:`boto.sqs.queue.Queue` object - :param queue: The Queue from which messages are read. - - :type receipt_handle: str - :param receipt_handle: The receipt handle associated with the message - whose visibility timeout will be changed. - - :type visibility_timeout: int - :param visibility_timeout: The new value of the message's visibility - timeout in seconds. - """ - params = {'ReceiptHandle' : receipt_handle, - 'VisibilityTimeout' : visibility_timeout} - return self.get_status('ChangeMessageVisibility', params, queue.id) - - def change_message_visibility_batch(self, queue, messages): - """ - A batch version of change_message_visibility that can act - on up to 10 messages at a time. - - :type queue: A :class:`boto.sqs.queue.Queue` object. - :param queue: The Queue to which the messages will be written. - - :type messages: List of tuples. - :param messages: A list of tuples where each tuple consists - of a :class:`boto.sqs.message.Message` object and an integer - that represents the new visibility timeout for that message. - """ - params = {} - for i, t in enumerate(messages): - prefix = 'ChangeMessageVisibilityBatchRequestEntry' - p_name = '%s.%i.Id' % (prefix, (i+1)) - params[p_name] = t[0].id - p_name = '%s.%i.ReceiptHandle' % (prefix, (i+1)) - params[p_name] = t[0].receipt_handle - p_name = '%s.%i.VisibilityTimeout' % (prefix, (i+1)) - params[p_name] = t[1] - return self.get_object('ChangeMessageVisibilityBatch', - params, BatchResults, - queue.id, verb='POST') - - def get_all_queues(self, prefix=''): - """ - Retrieves all queues. - - :keyword str prefix: Optionally, only return queues that start with - this value. - :rtype: list - :returns: A list of :py:class:`boto.sqs.queue.Queue` instances. - """ - params = {} - if prefix: - params['QueueNamePrefix'] = prefix - return self.get_list('ListQueues', params, [('QueueUrl', Queue)]) - - def get_queue(self, queue_name, owner_acct_id=None): - """ - Retrieves the queue with the given name, or ``None`` if no match - was found. - - :param str queue_name: The name of the queue to retrieve. - :param str owner_acct_id: Optionally, the AWS account ID of the account that created the queue. - :rtype: :py:class:`boto.sqs.queue.Queue` or ``None`` - :returns: The requested queue, or ``None`` if no match was found. - """ - params = {'QueueName': queue_name} - if owner_acct_id: - params['QueueOwnerAWSAccountId']=owner_acct_id - try: - return self.get_object('GetQueueUrl', params, Queue) - except SQSError: - return None - - lookup = get_queue - - def get_dead_letter_source_queues(self, queue): - """ - Retrieves the dead letter source queues for a given queue. - - :type queue: A :class:`boto.sqs.queue.Queue` object. - :param queue: The queue for which to get DL source queues - :rtype: list - :returns: A list of :py:class:`boto.sqs.queue.Queue` instances. - """ - params = {'QueueUrl': queue.url} - return self.get_list('ListDeadLetterSourceQueues', params, - [('QueueUrl', Queue)]) - - # - # Permissions methods - # - - def add_permission(self, queue, label, aws_account_id, action_name): - """ - Add a permission to a queue. - - :type queue: :class:`boto.sqs.queue.Queue` - :param queue: The queue object - - :type label: str or unicode - :param label: A unique identification of the permission you are setting. - Maximum of 80 characters ``[0-9a-zA-Z_-]`` - Example, AliceSendMessage - - :type aws_account_id: str or unicode - :param principal_id: The AWS account number of the principal - who will be given permission. The principal must have an - AWS account, but does not need to be signed up for Amazon - SQS. For information about locating the AWS account - identification. - - :type action_name: str or unicode - :param action_name: The action. Valid choices are: - * * - * SendMessage - * ReceiveMessage - * DeleteMessage - * ChangeMessageVisibility - * GetQueueAttributes - - :rtype: bool - :return: True if successful, False otherwise. - - """ - params = {'Label': label, - 'AWSAccountId' : aws_account_id, - 'ActionName' : action_name} - return self.get_status('AddPermission', params, queue.id) - - def remove_permission(self, queue, label): - """ - Remove a permission from a queue. - - :type queue: :class:`boto.sqs.queue.Queue` - :param queue: The queue object - - :type label: str or unicode - :param label: The unique label associated with the permission - being removed. - - :rtype: bool - :return: True if successful, False otherwise. - """ - params = {'Label': label} - return self.get_status('RemovePermission', params, queue.id) diff --git a/awx/lib/site-packages/boto/sqs/jsonmessage.py b/awx/lib/site-packages/boto/sqs/jsonmessage.py deleted file mode 100644 index 520eb8eb06..0000000000 --- a/awx/lib/site-packages/boto/sqs/jsonmessage.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2006-2008 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import base64 - -from boto.sqs.message import MHMessage -from boto.exception import SQSDecodeError -from boto.compat import json - - -class JSONMessage(MHMessage): - """ - Acts like a dictionary but encodes it's data as a Base64 encoded JSON payload. - """ - - def decode(self, value): - try: - value = base64.b64decode(value.encode('utf-8')).decode('utf-8') - value = json.loads(value) - except: - raise SQSDecodeError('Unable to decode message', self) - return value - - def encode(self, value): - value = json.dumps(value) - return base64.b64encode(value.encode('utf-8')).decode('utf-8') diff --git a/awx/lib/site-packages/boto/sqs/message.py b/awx/lib/site-packages/boto/sqs/message.py deleted file mode 100644 index 04d7cec74e..0000000000 --- a/awx/lib/site-packages/boto/sqs/message.py +++ /dev/null @@ -1,268 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -SQS Message - -A Message represents the data stored in an SQS queue. The rules for what is allowed within an SQS -Message are here: - - http://docs.amazonwebservices.com/AWSSimpleQueueService/2008-01-01/SQSDeveloperGuide/Query_QuerySendMessage.html - -So, at it's simplest level a Message just needs to allow a developer to store bytes in it and get the bytes -back out. However, to allow messages to have richer semantics, the Message class must support the -following interfaces: - -The constructor for the Message class must accept a keyword parameter "queue" which is an instance of a -boto Queue object and represents the queue that the message will be stored in. The default value for -this parameter is None. - -The constructor for the Message class must accept a keyword parameter "body" which represents the -content or body of the message. The format of this parameter will depend on the behavior of the -particular Message subclass. For example, if the Message subclass provides dictionary-like behavior to the -user the body passed to the constructor should be a dict-like object that can be used to populate -the initial state of the message. - -The Message class must provide an encode method that accepts a value of the same type as the body -parameter of the constructor and returns a string of characters that are able to be stored in an -SQS message body (see rules above). - -The Message class must provide a decode method that accepts a string of characters that can be -stored (and probably were stored!) in an SQS message and return an object of a type that is consistent -with the "body" parameter accepted on the class constructor. - -The Message class must provide a __len__ method that will return the size of the encoded message -that would be stored in SQS based on the current state of the Message object. - -The Message class must provide a get_body method that will return the body of the message in the -same format accepted in the constructor of the class. - -The Message class must provide a set_body method that accepts a message body in the same format -accepted by the constructor of the class. This method should alter to the internal state of the -Message object to reflect the state represented in the message body parameter. - -The Message class must provide a get_body_encoded method that returns the current body of the message -in the format in which it would be stored in SQS. -""" - -import base64 - -import boto - -from boto.compat import StringIO -from boto.sqs.attributes import Attributes -from boto.sqs.messageattributes import MessageAttributes -from boto.exception import SQSDecodeError - -class RawMessage(object): - """ - Base class for SQS messages. RawMessage does not encode the message - in any way. Whatever you store in the body of the message is what - will be written to SQS and whatever is returned from SQS is stored - directly into the body of the message. - """ - - def __init__(self, queue=None, body=''): - self.queue = queue - self.set_body(body) - self.id = None - self.receipt_handle = None - self.md5 = None - self.attributes = Attributes(self) - self.message_attributes = MessageAttributes(self) - self.md5_message_attributes = None - - def __len__(self): - return len(self.encode(self._body)) - - def startElement(self, name, attrs, connection): - if name == 'Attribute': - return self.attributes - if name == 'MessageAttribute': - return self.message_attributes - return None - - def endElement(self, name, value, connection): - if name == 'Body': - self.set_body(value) - elif name == 'MessageId': - self.id = value - elif name == 'ReceiptHandle': - self.receipt_handle = value - elif name == 'MD5OfBody': - self.md5 = value - elif name == 'MD5OfMessageAttributes': - self.md5_message_attributes = value - else: - setattr(self, name, value) - - def endNode(self, connection): - self.set_body(self.decode(self.get_body())) - - def encode(self, value): - """Transform body object into serialized byte array format.""" - return value - - def decode(self, value): - """Transform seralized byte array into any object.""" - return value - - def set_body(self, body): - """Override the current body for this object, using decoded format.""" - self._body = body - - def get_body(self): - return self._body - - def get_body_encoded(self): - """ - This method is really a semi-private method used by the Queue.write - method when writing the contents of the message to SQS. - You probably shouldn't need to call this method in the normal course of events. - """ - return self.encode(self.get_body()) - - def delete(self): - if self.queue: - return self.queue.delete_message(self) - - def change_visibility(self, visibility_timeout): - if self.queue: - self.queue.connection.change_message_visibility(self.queue, - self.receipt_handle, - visibility_timeout) - -class Message(RawMessage): - """ - The default Message class used for SQS queues. This class automatically - encodes/decodes the message body using Base64 encoding to avoid any - illegal characters in the message body. See: - - https://forums.aws.amazon.com/thread.jspa?threadID=13067 - - for details on why this is a good idea. The encode/decode is meant to - be transparent to the end-user. - """ - - def encode(self, value): - return base64.b64encode(value.encode('utf-8')).decode('utf-8') - - def decode(self, value): - try: - value = base64.b64decode(value.encode('utf-8')).decode('utf-8') - except: - boto.log.warning('Unable to decode message') - return value - return value - -class MHMessage(Message): - """ - The MHMessage class provides a message that provides RFC821-like - headers like this: - - HeaderName: HeaderValue - - The encoding/decoding of this is handled automatically and after - the message body has been read, the message instance can be treated - like a mapping object, i.e. m['HeaderName'] would return 'HeaderValue'. - """ - - def __init__(self, queue=None, body=None, xml_attrs=None): - if body is None or body == '': - body = {} - super(MHMessage, self).__init__(queue, body) - - def decode(self, value): - try: - msg = {} - fp = StringIO(value) - line = fp.readline() - while line: - delim = line.find(':') - key = line[0:delim] - value = line[delim+1:].strip() - msg[key.strip()] = value.strip() - line = fp.readline() - except: - raise SQSDecodeError('Unable to decode message', self) - return msg - - def encode(self, value): - s = '' - for item in value.items(): - s = s + '%s: %s\n' % (item[0], item[1]) - return s - - def __contains__(self, key): - return key in self._body - - def __getitem__(self, key): - if key in self._body: - return self._body[key] - else: - raise KeyError(key) - - def __setitem__(self, key, value): - self._body[key] = value - self.set_body(self._body) - - def keys(self): - return self._body.keys() - - def values(self): - return self._body.values() - - def items(self): - return self._body.items() - - def has_key(self, key): - return key in self._body - - def update(self, d): - self._body.update(d) - self.set_body(self._body) - - def get(self, key, default=None): - return self._body.get(key, default) - -class EncodedMHMessage(MHMessage): - """ - The EncodedMHMessage class provides a message that provides RFC821-like - headers like this: - - HeaderName: HeaderValue - - This variation encodes/decodes the body of the message in base64 automatically. - The message instance can be treated like a mapping object, - i.e. m['HeaderName'] would return 'HeaderValue'. - """ - - def decode(self, value): - try: - value = base64.b64decode(value.encode('utf-8')).decode('utf-8') - except: - raise SQSDecodeError('Unable to decode message', self) - return super(EncodedMHMessage, self).decode(value) - - def encode(self, value): - value = super(EncodedMHMessage, self).encode(value) - return base64.b64encode(value.encode('utf-8')).decode('utf-8') - diff --git a/awx/lib/site-packages/boto/sqs/messageattributes.py b/awx/lib/site-packages/boto/sqs/messageattributes.py deleted file mode 100644 index 7e61bf3668..0000000000 --- a/awx/lib/site-packages/boto/sqs/messageattributes.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2014 Amazon.com, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an SQS MessageAttribute Name/Value set -""" - -class MessageAttributes(dict): - def __init__(self, parent): - self.parent = parent - self.current_key = None - self.current_value = None - - def startElement(self, name, attrs, connection): - if name == 'Value': - self.current_value = MessageAttributeValue(self) - return self.current_value - - def endElement(self, name, value, connection): - if name == 'MessageAttribute': - self[self.current_key] = self.current_value - elif name == 'Name': - self.current_key = value - elif name == 'Value': - pass - else: - setattr(self, name, value) - - -class MessageAttributeValue(dict): - def __init__(self, parent): - self.parent = parent - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'DataType': - self['data_type'] = value - elif name == 'StringValue': - self['string_value'] = value - elif name == 'BinaryValue': - self['binary_value'] = value - elif name == 'StringListValue': - self['string_list_value'] = value - elif name == 'BinaryListValue': - self['binary_list_value'] = value diff --git a/awx/lib/site-packages/boto/sqs/queue.py b/awx/lib/site-packages/boto/sqs/queue.py deleted file mode 100644 index 162ec93cdb..0000000000 --- a/awx/lib/site-packages/boto/sqs/queue.py +++ /dev/null @@ -1,493 +0,0 @@ -# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an SQS Queue -""" -from boto.compat import urllib -from boto.sqs.message import Message - - -class Queue(object): - - def __init__(self, connection=None, url=None, message_class=Message): - self.connection = connection - self.url = url - self.message_class = message_class - self.visibility_timeout = None - - def __repr__(self): - return 'Queue(%s)' % self.url - - def _id(self): - if self.url: - val = urllib.parse.urlparse(self.url)[2] - else: - val = self.url - return val - id = property(_id) - - def _name(self): - if self.url: - val = urllib.parse.urlparse(self.url)[2].split('/')[2] - else: - val = self.url - return val - name = property(_name) - - def _arn(self): - parts = self.id.split('/') - return 'arn:aws:sqs:%s:%s:%s' % ( - self.connection.region.name, parts[1], parts[2]) - arn = property(_arn) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'QueueUrl': - self.url = value - elif name == 'VisibilityTimeout': - self.visibility_timeout = int(value) - else: - setattr(self, name, value) - - def set_message_class(self, message_class): - """ - Set the message class that should be used when instantiating - messages read from the queue. By default, the class - :class:`boto.sqs.message.Message` is used but this can be overriden - with any class that behaves like a message. - - :type message_class: Message-like class - :param message_class: The new Message class - """ - self.message_class = message_class - - def get_attributes(self, attributes='All'): - """ - Retrieves attributes about this queue object and returns - them in an Attribute instance (subclass of a Dictionary). - - :type attributes: string - :param attributes: String containing one of: - ApproximateNumberOfMessages, - ApproximateNumberOfMessagesNotVisible, - VisibilityTimeout, - CreatedTimestamp, - LastModifiedTimestamp, - Policy - ReceiveMessageWaitTimeSeconds - :rtype: Attribute object - :return: An Attribute object which is a mapping type holding the - requested name/value pairs - """ - return self.connection.get_queue_attributes(self, attributes) - - def set_attribute(self, attribute, value): - """ - Set a new value for an attribute of the Queue. - - :type attribute: String - :param attribute: The name of the attribute you want to set. The - only valid value at this time is: VisibilityTimeout - :type value: int - :param value: The new value for the attribute. - For VisibilityTimeout the value must be an - integer number of seconds from 0 to 86400. - - :rtype: bool - :return: True if successful, otherwise False. - """ - return self.connection.set_queue_attribute(self, attribute, value) - - def get_timeout(self): - """ - Get the visibility timeout for the queue. - - :rtype: int - :return: The number of seconds as an integer. - """ - a = self.get_attributes('VisibilityTimeout') - return int(a['VisibilityTimeout']) - - def set_timeout(self, visibility_timeout): - """ - Set the visibility timeout for the queue. - - :type visibility_timeout: int - :param visibility_timeout: The desired timeout in seconds - """ - retval = self.set_attribute('VisibilityTimeout', visibility_timeout) - if retval: - self.visibility_timeout = visibility_timeout - return retval - - def add_permission(self, label, aws_account_id, action_name): - """ - Add a permission to a queue. - - :type label: str or unicode - :param label: A unique identification of the permission you are setting. - Maximum of 80 characters ``[0-9a-zA-Z_-]`` - Example, AliceSendMessage - - :type aws_account_id: str or unicode - :param principal_id: The AWS account number of the principal who - will be given permission. The principal must have an AWS account, - but does not need to be signed up for Amazon SQS. For information - about locating the AWS account identification. - - :type action_name: str or unicode - :param action_name: The action. Valid choices are: - SendMessage|ReceiveMessage|DeleteMessage| - ChangeMessageVisibility|GetQueueAttributes|* - - :rtype: bool - :return: True if successful, False otherwise. - - """ - return self.connection.add_permission(self, label, aws_account_id, - action_name) - - def remove_permission(self, label): - """ - Remove a permission from a queue. - - :type label: str or unicode - :param label: The unique label associated with the permission - being removed. - - :rtype: bool - :return: True if successful, False otherwise. - """ - return self.connection.remove_permission(self, label) - - def read(self, visibility_timeout=None, wait_time_seconds=None, - message_attributes=None): - """ - Read a single message from the queue. - - :type visibility_timeout: int - :param visibility_timeout: The timeout for this message in seconds - - :type wait_time_seconds: int - :param wait_time_seconds: The duration (in seconds) for which the call - will wait for a message to arrive in the queue before returning. - If a message is available, the call will return sooner than - wait_time_seconds. - - :type message_attributes: list - :param message_attributes: The name(s) of additional message - attributes to return. The default is to return no additional - message attributes. Use ``['All']`` or ``['.*']`` to return all. - - :rtype: :class:`boto.sqs.message.Message` - :return: A single message or None if queue is empty - """ - rs = self.get_messages(1, visibility_timeout, - wait_time_seconds=wait_time_seconds, - message_attributes=message_attributes) - if len(rs) == 1: - return rs[0] - else: - return None - - def write(self, message, delay_seconds=None): - """ - Add a single message to the queue. - - :type message: Message - :param message: The message to be written to the queue - - :rtype: :class:`boto.sqs.message.Message` - :return: The :class:`boto.sqs.message.Message` object that was written. - """ - new_msg = self.connection.send_message(self, - message.get_body_encoded(), delay_seconds=delay_seconds, - message_attributes=message.message_attributes) - message.id = new_msg.id - message.md5 = new_msg.md5 - return message - - def write_batch(self, messages): - """ - Delivers up to 10 messages in a single request. - - :type messages: List of lists. - :param messages: A list of lists or tuples. Each inner - tuple represents a single message to be written - and consists of and ID (string) that must be unique - within the list of messages, the message body itself - which can be a maximum of 64K in length, an - integer which represents the delay time (in seconds) - for the message (0-900) before the message will - be delivered to the queue, and an optional dict of - message attributes like those passed to ``send_message`` - in the connection class. - """ - return self.connection.send_message_batch(self, messages) - - def new_message(self, body='', **kwargs): - """ - Create new message of appropriate class. - - :type body: message body - :param body: The body of the newly created message (optional). - - :rtype: :class:`boto.sqs.message.Message` - :return: A new Message object - """ - m = self.message_class(self, body, **kwargs) - m.queue = self - return m - - # get a variable number of messages, returns a list of messages - def get_messages(self, num_messages=1, visibility_timeout=None, - attributes=None, wait_time_seconds=None, - message_attributes=None): - """ - Get a variable number of messages. - - :type num_messages: int - :param num_messages: The maximum number of messages to read from - the queue. - - :type visibility_timeout: int - :param visibility_timeout: The VisibilityTimeout for the messages read. - - :type attributes: str - :param attributes: The name of additional attribute to return - with response or All if you want all attributes. The - default is to return no additional attributes. Valid - values: All SenderId SentTimestamp ApproximateReceiveCount - ApproximateFirstReceiveTimestamp - - :type wait_time_seconds: int - :param wait_time_seconds: The duration (in seconds) for which the call - will wait for a message to arrive in the queue before returning. - If a message is available, the call will return sooner than - wait_time_seconds. - - :type message_attributes: list - :param message_attributes: The name(s) of additional message - attributes to return. The default is to return no additional - message attributes. Use ``['All']`` or ``['.*']`` to return all. - - :rtype: list - :return: A list of :class:`boto.sqs.message.Message` objects. - """ - return self.connection.receive_message( - self, number_messages=num_messages, - visibility_timeout=visibility_timeout, attributes=attributes, - wait_time_seconds=wait_time_seconds, - message_attributes=message_attributes) - - def delete_message(self, message): - """ - Delete a message from the queue. - - :type message: :class:`boto.sqs.message.Message` - :param message: The :class:`boto.sqs.message.Message` object to delete. - - :rtype: bool - :return: True if successful, False otherwise - """ - return self.connection.delete_message(self, message) - - def delete_message_batch(self, messages): - """ - Deletes a list of messages in a single request. - - :type messages: List of :class:`boto.sqs.message.Message` objects. - :param messages: A list of message objects. - """ - return self.connection.delete_message_batch(self, messages) - - def change_message_visibility_batch(self, messages): - """ - A batch version of change_message_visibility that can act - on up to 10 messages at a time. - - :type messages: List of tuples. - :param messages: A list of tuples where each tuple consists - of a :class:`boto.sqs.message.Message` object and an integer - that represents the new visibility timeout for that message. - """ - return self.connection.change_message_visibility_batch(self, messages) - - def delete(self): - """ - Delete the queue. - """ - return self.connection.delete_queue(self) - - def clear(self, page_size=10, vtimeout=10): - """Utility function to remove all messages from a queue""" - n = 0 - l = self.get_messages(page_size, vtimeout) - while l: - for m in l: - self.delete_message(m) - n += 1 - l = self.get_messages(page_size, vtimeout) - return n - - def count(self, page_size=10, vtimeout=10): - """ - Utility function to count the number of messages in a queue. - Note: This function now calls GetQueueAttributes to obtain - an 'approximate' count of the number of messages in a queue. - """ - a = self.get_attributes('ApproximateNumberOfMessages') - return int(a['ApproximateNumberOfMessages']) - - def count_slow(self, page_size=10, vtimeout=10): - """ - Deprecated. This is the old 'count' method that actually counts - the messages by reading them all. This gives an accurate count but - is very slow for queues with non-trivial number of messasges. - Instead, use get_attributes('ApproximateNumberOfMessages') to take - advantage of the new SQS capability. This is retained only for - the unit tests. - """ - n = 0 - l = self.get_messages(page_size, vtimeout) - while l: - for m in l: - n += 1 - l = self.get_messages(page_size, vtimeout) - return n - - def dump(self, file_name, page_size=10, vtimeout=10, sep='\n'): - """Utility function to dump the messages in a queue to a file - NOTE: Page size must be < 10 else SQS errors""" - fp = open(file_name, 'wb') - n = 0 - l = self.get_messages(page_size, vtimeout) - while l: - for m in l: - fp.write(m.get_body()) - if sep: - fp.write(sep) - n += 1 - l = self.get_messages(page_size, vtimeout) - fp.close() - return n - - def save_to_file(self, fp, sep='\n'): - """ - Read all messages from the queue and persist them to file-like object. - Messages are written to the file and the 'sep' string is written - in between messages. Messages are deleted from the queue after - being written to the file. - Returns the number of messages saved. - """ - n = 0 - m = self.read() - while m: - n += 1 - fp.write(m.get_body()) - if sep: - fp.write(sep) - self.delete_message(m) - m = self.read() - return n - - def save_to_filename(self, file_name, sep='\n'): - """ - Read all messages from the queue and persist them to local file. - Messages are written to the file and the 'sep' string is written - in between messages. Messages are deleted from the queue after - being written to the file. - Returns the number of messages saved. - """ - fp = open(file_name, 'wb') - n = self.save_to_file(fp, sep) - fp.close() - return n - - # for backwards compatibility - save = save_to_filename - - def save_to_s3(self, bucket): - """ - Read all messages from the queue and persist them to S3. - Messages are stored in the S3 bucket using a naming scheme of:: - - <queue_id>/<message_id> - - Messages are deleted from the queue after being saved to S3. - Returns the number of messages saved. - """ - n = 0 - m = self.read() - while m: - n += 1 - key = bucket.new_key('%s/%s' % (self.id, m.id)) - key.set_contents_from_string(m.get_body()) - self.delete_message(m) - m = self.read() - return n - - def load_from_s3(self, bucket, prefix=None): - """ - Load messages previously saved to S3. - """ - n = 0 - if prefix: - prefix = '%s/' % prefix - else: - prefix = '%s/' % self.id[1:] - rs = bucket.list(prefix=prefix) - for key in rs: - n += 1 - m = self.new_message(key.get_contents_as_string()) - self.write(m) - return n - - def load_from_file(self, fp, sep='\n'): - """Utility function to load messages from a file-like object to a queue""" - n = 0 - body = '' - l = fp.readline() - while l: - if l == sep: - m = Message(self, body) - self.write(m) - n += 1 - print('writing message %d' % n) - body = '' - else: - body = body + l - l = fp.readline() - return n - - def load_from_filename(self, file_name, sep='\n'): - """Utility function to load messages from a local filename to a queue""" - fp = open(file_name, 'rb') - n = self.load_from_file(fp, sep) - fp.close() - return n - - # for backward compatibility - load = load_from_filename - diff --git a/awx/lib/site-packages/boto/sqs/regioninfo.py b/awx/lib/site-packages/boto/sqs/regioninfo.py deleted file mode 100644 index d21dff9cda..0000000000 --- a/awx/lib/site-packages/boto/sqs/regioninfo.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo - -class SQSRegionInfo(RegionInfo): - - def __init__(self, connection=None, name=None, endpoint=None, - connection_cls=None): - from boto.sqs.connection import SQSConnection - super(SQSRegionInfo, self).__init__(connection, name, endpoint, - SQSConnection) diff --git a/awx/lib/site-packages/boto/storage_uri.py b/awx/lib/site-packages/boto/storage_uri.py deleted file mode 100644 index 34b7b06045..0000000000 --- a/awx/lib/site-packages/boto/storage_uri.py +++ /dev/null @@ -1,891 +0,0 @@ -# Copyright 2010 Google Inc. -# Copyright (c) 2011, Nexenta Systems Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import boto -import os -import sys -import textwrap -from boto.s3.deletemarker import DeleteMarker -from boto.exception import BotoClientError -from boto.exception import InvalidUriError - - -class StorageUri(object): - """ - Base class for representing storage provider-independent bucket and - object name with a shorthand URI-like syntax. - - This is an abstract class: the constructor cannot be called (throws an - exception if you try). - """ - - connection = None - # Optional args that can be set from one of the concrete subclass - # constructors, to change connection behavior (e.g., to override - # https_connection_factory). - connection_args = None - - # Map of provider scheme ('s3' or 'gs') to AWSAuthConnection object. We - # maintain a pool here in addition to the connection pool implemented - # in AWSAuthConnection because the latter re-creates its connection pool - # every time that class is instantiated (so the current pool is used to - # avoid re-instantiating AWSAuthConnection). - provider_pool = {} - - def __init__(self): - """Uncallable constructor on abstract base StorageUri class. - """ - raise BotoClientError('Attempt to instantiate abstract StorageUri ' - 'class') - - def __repr__(self): - """Returns string representation of URI.""" - return self.uri - - def equals(self, uri): - """Returns true if two URIs are equal.""" - return self.uri == uri.uri - - def check_response(self, resp, level, uri): - if resp is None: - raise InvalidUriError('\n'.join(textwrap.wrap( - 'Attempt to get %s for "%s" failed. This can happen if ' - 'the URI refers to a non-existent object or if you meant to ' - 'operate on a directory (e.g., leaving off -R option on gsutil ' - 'cp, mv, or ls of a bucket)' % (level, uri), 80))) - - def _check_bucket_uri(self, function_name): - if issubclass(type(self), BucketStorageUri) and not self.bucket_name: - raise InvalidUriError( - '%s on bucket-less URI (%s)' % (function_name, self.uri)) - - def _check_object_uri(self, function_name): - if issubclass(type(self), BucketStorageUri) and not self.object_name: - raise InvalidUriError('%s on object-less URI (%s)' % - (function_name, self.uri)) - - def _warn_about_args(self, function_name, **args): - for arg in args: - if args[arg]: - sys.stderr.write( - 'Warning: %s ignores argument: %s=%s\n' % - (function_name, arg, str(args[arg]))) - - def connect(self, access_key_id=None, secret_access_key=None, **kwargs): - """ - Opens a connection to appropriate provider, depending on provider - portion of URI. Requires Credentials defined in boto config file (see - boto/pyami/config.py). - @type storage_uri: StorageUri - @param storage_uri: StorageUri specifying a bucket or a bucket+object - @rtype: L{AWSAuthConnection<boto.gs.connection.AWSAuthConnection>} - @return: A connection to storage service provider of the given URI. - """ - connection_args = dict(self.connection_args or ()) - - if (hasattr(self, 'suppress_consec_slashes') and - 'suppress_consec_slashes' not in connection_args): - connection_args['suppress_consec_slashes'] = ( - self.suppress_consec_slashes) - connection_args.update(kwargs) - if not self.connection: - if self.scheme in self.provider_pool: - self.connection = self.provider_pool[self.scheme] - elif self.scheme == 's3': - from boto.s3.connection import S3Connection - self.connection = S3Connection(access_key_id, - secret_access_key, - **connection_args) - self.provider_pool[self.scheme] = self.connection - elif self.scheme == 'gs': - from boto.gs.connection import GSConnection - # Use OrdinaryCallingFormat instead of boto-default - # SubdomainCallingFormat because the latter changes the hostname - # that's checked during cert validation for HTTPS connections, - # which will fail cert validation (when cert validation is - # enabled). - # - # The same is not true for S3's HTTPS certificates. In fact, - # we don't want to do this for S3 because S3 requires the - # subdomain to match the location of the bucket. If the proper - # subdomain is not used, the server will return a 301 redirect - # with no Location header. - # - # Note: the following import can't be moved up to the - # start of this file else it causes a config import failure when - # run from the resumable upload/download tests. - from boto.s3.connection import OrdinaryCallingFormat - connection_args['calling_format'] = OrdinaryCallingFormat() - self.connection = GSConnection(access_key_id, - secret_access_key, - **connection_args) - self.provider_pool[self.scheme] = self.connection - elif self.scheme == 'file': - from boto.file.connection import FileConnection - self.connection = FileConnection(self) - else: - raise InvalidUriError('Unrecognized scheme "%s"' % - self.scheme) - self.connection.debug = self.debug - return self.connection - - def has_version(self): - return (issubclass(type(self), BucketStorageUri) - and ((self.version_id is not None) - or (self.generation is not None))) - - def delete_key(self, validate=False, headers=None, version_id=None, - mfa_token=None): - self._check_object_uri('delete_key') - bucket = self.get_bucket(validate, headers) - return bucket.delete_key(self.object_name, headers, version_id, - mfa_token) - - def list_bucket(self, prefix='', delimiter='', headers=None, - all_versions=False): - self._check_bucket_uri('list_bucket') - bucket = self.get_bucket(headers=headers) - if all_versions: - return (v for v in bucket.list_versions( - prefix=prefix, delimiter=delimiter, headers=headers) - if not isinstance(v, DeleteMarker)) - else: - return bucket.list(prefix=prefix, delimiter=delimiter, - headers=headers) - - def get_all_keys(self, validate=False, headers=None, prefix=None): - bucket = self.get_bucket(validate, headers) - return bucket.get_all_keys(headers) - - def get_bucket(self, validate=False, headers=None): - self._check_bucket_uri('get_bucket') - conn = self.connect() - bucket = conn.get_bucket(self.bucket_name, validate, headers) - self.check_response(bucket, 'bucket', self.uri) - return bucket - - def get_key(self, validate=False, headers=None, version_id=None): - self._check_object_uri('get_key') - bucket = self.get_bucket(validate, headers) - key = bucket.get_key(self.object_name, headers, version_id) - self.check_response(key, 'key', self.uri) - return key - - def new_key(self, validate=False, headers=None): - self._check_object_uri('new_key') - bucket = self.get_bucket(validate, headers) - return bucket.new_key(self.object_name) - - def get_contents_to_stream(self, fp, headers=None, version_id=None): - self._check_object_uri('get_key') - self._warn_about_args('get_key', validate=False) - key = self.get_key(None, headers) - self.check_response(key, 'key', self.uri) - return key.get_contents_to_file(fp, headers, version_id=version_id) - - def get_contents_to_file(self, fp, headers=None, cb=None, num_cb=10, - torrent=False, version_id=None, - res_download_handler=None, response_headers=None, - hash_algs=None): - self._check_object_uri('get_contents_to_file') - key = self.get_key(None, headers) - self.check_response(key, 'key', self.uri) - if hash_algs: - key.get_contents_to_file(fp, headers, cb, num_cb, torrent, - version_id, res_download_handler, - response_headers, - hash_algs=hash_algs) - else: - key.get_contents_to_file(fp, headers, cb, num_cb, torrent, - version_id, res_download_handler, - response_headers) - - def get_contents_as_string(self, validate=False, headers=None, cb=None, - num_cb=10, torrent=False, version_id=None): - self._check_object_uri('get_contents_as_string') - key = self.get_key(validate, headers) - self.check_response(key, 'key', self.uri) - return key.get_contents_as_string(headers, cb, num_cb, torrent, - version_id) - - def acl_class(self): - conn = self.connect() - acl_class = conn.provider.acl_class - self.check_response(acl_class, 'acl_class', self.uri) - return acl_class - - def canned_acls(self): - conn = self.connect() - canned_acls = conn.provider.canned_acls - self.check_response(canned_acls, 'canned_acls', self.uri) - return canned_acls - - -class BucketStorageUri(StorageUri): - """ - StorageUri subclass that handles bucket storage providers. - Callers should instantiate this class by calling boto.storage_uri(). - """ - - delim = '/' - capabilities = set([]) # A set of additional capabilities. - - def __init__(self, scheme, bucket_name=None, object_name=None, - debug=0, connection_args=None, suppress_consec_slashes=True, - version_id=None, generation=None, is_latest=False): - """Instantiate a BucketStorageUri from scheme,bucket,object tuple. - - @type scheme: string - @param scheme: URI scheme naming the storage provider (gs, s3, etc.) - @type bucket_name: string - @param bucket_name: bucket name - @type object_name: string - @param object_name: object name, excluding generation/version. - @type debug: int - @param debug: debug level to pass in to connection (range 0..2) - @type connection_args: map - @param connection_args: optional map containing args to be - passed to {S3,GS}Connection constructor (e.g., to override - https_connection_factory). - @param suppress_consec_slashes: If provided, controls whether - consecutive slashes will be suppressed in key paths. - @param version_id: Object version id (S3-specific). - @param generation: Object generation number (GCS-specific). - @param is_latest: boolean indicating that a versioned object is the - current version - - After instantiation the components are available in the following - fields: scheme, bucket_name, object_name, version_id, generation, - is_latest, versionless_uri, version_specific_uri, uri. - Note: If instantiated without version info, the string representation - for a URI stays versionless; similarly, if instantiated with version - info, the string representation for a URI stays version-specific. If you - call one of the uri.set_contents_from_xyz() methods, a specific object - version will be created, and its version-specific URI string can be - retrieved from version_specific_uri even if the URI was instantiated - without version info. - """ - - self.scheme = scheme - self.bucket_name = bucket_name - self.object_name = object_name - self.debug = debug - if connection_args: - self.connection_args = connection_args - self.suppress_consec_slashes = suppress_consec_slashes - self.version_id = version_id - self.generation = generation and int(generation) - self.is_latest = is_latest - self.is_version_specific = bool(self.generation) or bool(version_id) - self._build_uri_strings() - - def _build_uri_strings(self): - if self.bucket_name and self.object_name: - self.versionless_uri = '%s://%s/%s' % (self.scheme, self.bucket_name, - self.object_name) - if self.generation: - self.version_specific_uri = '%s#%s' % (self.versionless_uri, - self.generation) - elif self.version_id: - self.version_specific_uri = '%s#%s' % ( - self.versionless_uri, self.version_id) - if self.is_version_specific: - self.uri = self.version_specific_uri - else: - self.uri = self.versionless_uri - elif self.bucket_name: - self.uri = ('%s://%s/' % (self.scheme, self.bucket_name)) - else: - self.uri = ('%s://' % self.scheme) - - def _update_from_key(self, key): - self._update_from_values( - getattr(key, 'version_id', None), - getattr(key, 'generation', None), - getattr(key, 'is_latest', None), - getattr(key, 'md5', None)) - - def _update_from_values(self, version_id, generation, is_latest, md5): - self.version_id = version_id - self.generation = generation - self.is_latest = is_latest - self._build_uri_strings() - self.md5 = md5 - - def get_key(self, validate=False, headers=None, version_id=None): - self._check_object_uri('get_key') - bucket = self.get_bucket(validate, headers) - if self.get_provider().name == 'aws': - key = bucket.get_key(self.object_name, headers, - version_id=(version_id or self.version_id)) - elif self.get_provider().name == 'google': - key = bucket.get_key(self.object_name, headers, - generation=self.generation) - self.check_response(key, 'key', self.uri) - return key - - def delete_key(self, validate=False, headers=None, version_id=None, - mfa_token=None): - self._check_object_uri('delete_key') - bucket = self.get_bucket(validate, headers) - if self.get_provider().name == 'aws': - version_id = version_id or self.version_id - return bucket.delete_key(self.object_name, headers, version_id, - mfa_token) - elif self.get_provider().name == 'google': - return bucket.delete_key(self.object_name, headers, - generation=self.generation) - - def clone_replace_name(self, new_name): - """Instantiate a BucketStorageUri from the current BucketStorageUri, - but replacing the object_name. - - @type new_name: string - @param new_name: new object name - """ - self._check_bucket_uri('clone_replace_name') - return BucketStorageUri( - self.scheme, bucket_name=self.bucket_name, object_name=new_name, - debug=self.debug, - suppress_consec_slashes=self.suppress_consec_slashes) - - def clone_replace_key(self, key): - """Instantiate a BucketStorageUri from the current BucketStorageUri, by - replacing the object name with the object name and other metadata found - in the given Key object (including generation). - - @type key: Key - @param key: key for the new StorageUri to represent - """ - self._check_bucket_uri('clone_replace_key') - version_id = None - generation = None - is_latest = False - if hasattr(key, 'version_id'): - version_id = key.version_id - if hasattr(key, 'generation'): - generation = key.generation - if hasattr(key, 'is_latest'): - is_latest = key.is_latest - - return BucketStorageUri( - key.provider.get_provider_name(), - bucket_name=key.bucket.name, - object_name=key.name, - debug=self.debug, - suppress_consec_slashes=self.suppress_consec_slashes, - version_id=version_id, - generation=generation, - is_latest=is_latest) - - def get_acl(self, validate=False, headers=None, version_id=None): - """returns a bucket's acl""" - self._check_bucket_uri('get_acl') - bucket = self.get_bucket(validate, headers) - # This works for both bucket- and object- level ACLs (former passes - # key_name=None): - key_name = self.object_name or '' - if self.get_provider().name == 'aws': - version_id = version_id or self.version_id - acl = bucket.get_acl(key_name, headers, version_id) - else: - acl = bucket.get_acl(key_name, headers, generation=self.generation) - self.check_response(acl, 'acl', self.uri) - return acl - - def get_def_acl(self, validate=False, headers=None): - """returns a bucket's default object acl""" - self._check_bucket_uri('get_def_acl') - bucket = self.get_bucket(validate, headers) - acl = bucket.get_def_acl(headers) - self.check_response(acl, 'acl', self.uri) - return acl - - def get_cors(self, validate=False, headers=None): - """returns a bucket's CORS XML""" - self._check_bucket_uri('get_cors') - bucket = self.get_bucket(validate, headers) - cors = bucket.get_cors(headers) - self.check_response(cors, 'cors', self.uri) - return cors - - def set_cors(self, cors, validate=False, headers=None): - """sets or updates a bucket's CORS XML""" - self._check_bucket_uri('set_cors ') - bucket = self.get_bucket(validate, headers) - bucket.set_cors(cors.to_xml(), headers) - - def get_location(self, validate=False, headers=None): - self._check_bucket_uri('get_location') - bucket = self.get_bucket(validate, headers) - return bucket.get_location() - - def get_storage_class(self, validate=False, headers=None): - self._check_bucket_uri('get_storage_class') - # StorageClass is defined as a bucket param for GCS, but as a key - # param for S3. - if self.scheme != 'gs': - raise ValueError('get_storage_class() not supported for %s ' - 'URIs.' % self.scheme) - bucket = self.get_bucket(validate, headers) - return bucket.get_storage_class() - - def get_subresource(self, subresource, validate=False, headers=None, - version_id=None): - self._check_bucket_uri('get_subresource') - bucket = self.get_bucket(validate, headers) - return bucket.get_subresource(subresource, self.object_name, headers, - version_id) - - def add_group_email_grant(self, permission, email_address, recursive=False, - validate=False, headers=None): - self._check_bucket_uri('add_group_email_grant') - if self.scheme != 'gs': - raise ValueError('add_group_email_grant() not supported for %s ' - 'URIs.' % self.scheme) - if self.object_name: - if recursive: - raise ValueError('add_group_email_grant() on key-ful URI cannot ' - 'specify recursive=True') - key = self.get_key(validate, headers) - self.check_response(key, 'key', self.uri) - key.add_group_email_grant(permission, email_address, headers) - elif self.bucket_name: - bucket = self.get_bucket(validate, headers) - bucket.add_group_email_grant(permission, email_address, recursive, - headers) - else: - raise InvalidUriError('add_group_email_grant() on bucket-less URI ' - '%s' % self.uri) - - def add_email_grant(self, permission, email_address, recursive=False, - validate=False, headers=None): - self._check_bucket_uri('add_email_grant') - if not self.object_name: - bucket = self.get_bucket(validate, headers) - bucket.add_email_grant(permission, email_address, recursive, - headers) - else: - key = self.get_key(validate, headers) - self.check_response(key, 'key', self.uri) - key.add_email_grant(permission, email_address) - - def add_user_grant(self, permission, user_id, recursive=False, - validate=False, headers=None): - self._check_bucket_uri('add_user_grant') - if not self.object_name: - bucket = self.get_bucket(validate, headers) - bucket.add_user_grant(permission, user_id, recursive, headers) - else: - key = self.get_key(validate, headers) - self.check_response(key, 'key', self.uri) - key.add_user_grant(permission, user_id) - - def list_grants(self, headers=None): - self._check_bucket_uri('list_grants ') - bucket = self.get_bucket(headers) - return bucket.list_grants(headers) - - def is_file_uri(self): - """Returns True if this URI names a file or directory.""" - return False - - def is_cloud_uri(self): - """Returns True if this URI names a bucket or object.""" - return True - - def names_container(self): - """ - Returns True if this URI names a directory or bucket. Will return - False for bucket subdirs; providing bucket subdir semantics needs to - be done by the caller (like gsutil does). - """ - return bool(not self.object_name) - - def names_singleton(self): - """Returns True if this URI names a file or object.""" - return bool(self.object_name) - - def names_directory(self): - """Returns True if this URI names a directory.""" - return False - - def names_provider(self): - """Returns True if this URI names a provider.""" - return bool(not self.bucket_name) - - def names_bucket(self): - """Returns True if this URI names a bucket.""" - return bool(self.bucket_name) and bool(not self.object_name) - - def names_file(self): - """Returns True if this URI names a file.""" - return False - - def names_object(self): - """Returns True if this URI names an object.""" - return self.names_singleton() - - def is_stream(self): - """Returns True if this URI represents input/output stream.""" - return False - - def create_bucket(self, headers=None, location='', policy=None, - storage_class=None): - self._check_bucket_uri('create_bucket ') - conn = self.connect() - # Pass storage_class param only if this is a GCS bucket. (In S3 the - # storage class is specified on the key object.) - if self.scheme == 'gs': - return conn.create_bucket(self.bucket_name, headers, location, policy, - storage_class) - else: - return conn.create_bucket(self.bucket_name, headers, location, policy) - - def delete_bucket(self, headers=None): - self._check_bucket_uri('delete_bucket') - conn = self.connect() - return conn.delete_bucket(self.bucket_name, headers) - - def get_all_buckets(self, headers=None): - conn = self.connect() - return conn.get_all_buckets(headers) - - def get_provider(self): - conn = self.connect() - provider = conn.provider - self.check_response(provider, 'provider', self.uri) - return provider - - def set_acl(self, acl_or_str, key_name='', validate=False, headers=None, - version_id=None, if_generation=None, if_metageneration=None): - """Sets or updates a bucket's ACL.""" - self._check_bucket_uri('set_acl') - key_name = key_name or self.object_name or '' - bucket = self.get_bucket(validate, headers) - if self.generation: - bucket.set_acl( - acl_or_str, key_name, headers, generation=self.generation, - if_generation=if_generation, if_metageneration=if_metageneration) - else: - version_id = version_id or self.version_id - bucket.set_acl(acl_or_str, key_name, headers, version_id) - - def set_xml_acl(self, xmlstring, key_name='', validate=False, headers=None, - version_id=None, if_generation=None, if_metageneration=None): - """Sets or updates a bucket's ACL with an XML string.""" - self._check_bucket_uri('set_xml_acl') - key_name = key_name or self.object_name or '' - bucket = self.get_bucket(validate, headers) - if self.generation: - bucket.set_xml_acl( - xmlstring, key_name, headers, generation=self.generation, - if_generation=if_generation, if_metageneration=if_metageneration) - else: - version_id = version_id or self.version_id - bucket.set_xml_acl(xmlstring, key_name, headers, - version_id=version_id) - - def set_def_xml_acl(self, xmlstring, validate=False, headers=None): - """Sets or updates a bucket's default object ACL with an XML string.""" - self._check_bucket_uri('set_def_xml_acl') - self.get_bucket(validate, headers).set_def_xml_acl(xmlstring, headers) - - def set_def_acl(self, acl_or_str, validate=False, headers=None, - version_id=None): - """Sets or updates a bucket's default object ACL.""" - self._check_bucket_uri('set_def_acl') - self.get_bucket(validate, headers).set_def_acl(acl_or_str, headers) - - def set_canned_acl(self, acl_str, validate=False, headers=None, - version_id=None): - """Sets or updates a bucket's acl to a predefined (canned) value.""" - self._check_object_uri('set_canned_acl') - self._warn_about_args('set_canned_acl', version_id=version_id) - key = self.get_key(validate, headers) - self.check_response(key, 'key', self.uri) - key.set_canned_acl(acl_str, headers) - - def set_def_canned_acl(self, acl_str, validate=False, headers=None, - version_id=None): - """Sets or updates a bucket's default object acl to a predefined - (canned) value.""" - self._check_bucket_uri('set_def_canned_acl ') - key = self.get_key(validate, headers) - self.check_response(key, 'key', self.uri) - key.set_def_canned_acl(acl_str, headers, version_id) - - def set_subresource(self, subresource, value, validate=False, headers=None, - version_id=None): - self._check_bucket_uri('set_subresource') - bucket = self.get_bucket(validate, headers) - bucket.set_subresource(subresource, value, self.object_name, headers, - version_id) - - def set_contents_from_string(self, s, headers=None, replace=True, - cb=None, num_cb=10, policy=None, md5=None, - reduced_redundancy=False): - self._check_object_uri('set_contents_from_string') - key = self.new_key(headers=headers) - if self.scheme == 'gs': - if reduced_redundancy: - sys.stderr.write('Warning: GCS does not support ' - 'reduced_redundancy; argument ignored by ' - 'set_contents_from_string') - result = key.set_contents_from_string( - s, headers, replace, cb, num_cb, policy, md5) - else: - result = key.set_contents_from_string( - s, headers, replace, cb, num_cb, policy, md5, - reduced_redundancy) - self._update_from_key(key) - return result - - def set_contents_from_file(self, fp, headers=None, replace=True, cb=None, - num_cb=10, policy=None, md5=None, size=None, - rewind=False, res_upload_handler=None): - self._check_object_uri('set_contents_from_file') - key = self.new_key(headers=headers) - if self.scheme == 'gs': - result = key.set_contents_from_file( - fp, headers, replace, cb, num_cb, policy, md5, size=size, - rewind=rewind, res_upload_handler=res_upload_handler) - if res_upload_handler: - self._update_from_values(None, res_upload_handler.generation, - None, md5) - else: - self._warn_about_args('set_contents_from_file', - res_upload_handler=res_upload_handler) - result = key.set_contents_from_file( - fp, headers, replace, cb, num_cb, policy, md5, size=size, - rewind=rewind) - self._update_from_key(key) - return result - - def set_contents_from_stream(self, fp, headers=None, replace=True, cb=None, - policy=None, reduced_redundancy=False): - self._check_object_uri('set_contents_from_stream') - dst_key = self.new_key(False, headers) - result = dst_key.set_contents_from_stream( - fp, headers, replace, cb, policy=policy, - reduced_redundancy=reduced_redundancy) - self._update_from_key(dst_key) - return result - - def copy_key(self, src_bucket_name, src_key_name, metadata=None, - src_version_id=None, storage_class='STANDARD', - preserve_acl=False, encrypt_key=False, headers=None, - query_args=None, src_generation=None): - """Returns newly created key.""" - self._check_object_uri('copy_key') - dst_bucket = self.get_bucket(validate=False, headers=headers) - if src_generation: - return dst_bucket.copy_key( - new_key_name=self.object_name, - src_bucket_name=src_bucket_name, - src_key_name=src_key_name, metadata=metadata, - storage_class=storage_class, preserve_acl=preserve_acl, - encrypt_key=encrypt_key, headers=headers, query_args=query_args, - src_generation=src_generation) - else: - return dst_bucket.copy_key( - new_key_name=self.object_name, - src_bucket_name=src_bucket_name, src_key_name=src_key_name, - metadata=metadata, src_version_id=src_version_id, - storage_class=storage_class, preserve_acl=preserve_acl, - encrypt_key=encrypt_key, headers=headers, query_args=query_args) - - def enable_logging(self, target_bucket, target_prefix=None, validate=False, - headers=None, version_id=None): - self._check_bucket_uri('enable_logging') - bucket = self.get_bucket(validate, headers) - bucket.enable_logging(target_bucket, target_prefix, headers=headers) - - def disable_logging(self, validate=False, headers=None, version_id=None): - self._check_bucket_uri('disable_logging') - bucket = self.get_bucket(validate, headers) - bucket.disable_logging(headers=headers) - - def get_logging_config(self, validate=False, headers=None, version_id=None): - self._check_bucket_uri('get_logging_config') - bucket = self.get_bucket(validate, headers) - return bucket.get_logging_config(headers=headers) - - def set_website_config(self, main_page_suffix=None, error_key=None, - validate=False, headers=None): - self._check_bucket_uri('set_website_config') - bucket = self.get_bucket(validate, headers) - if not (main_page_suffix or error_key): - bucket.delete_website_configuration(headers) - else: - bucket.configure_website(main_page_suffix, error_key, headers) - - def get_website_config(self, validate=False, headers=None): - self._check_bucket_uri('get_website_config') - bucket = self.get_bucket(validate, headers) - return bucket.get_website_configuration(headers) - - def get_versioning_config(self, headers=None): - self._check_bucket_uri('get_versioning_config') - bucket = self.get_bucket(False, headers) - return bucket.get_versioning_status(headers) - - def configure_versioning(self, enabled, headers=None): - self._check_bucket_uri('configure_versioning') - bucket = self.get_bucket(False, headers) - return bucket.configure_versioning(enabled, headers) - - def set_metadata(self, metadata_plus, metadata_minus, preserve_acl, - headers=None): - return self.get_key(False).set_remote_metadata(metadata_plus, - metadata_minus, - preserve_acl, - headers=headers) - - def compose(self, components, content_type=None, headers=None): - self._check_object_uri('compose') - component_keys = [] - for suri in components: - component_keys.append(suri.new_key()) - component_keys[-1].generation = suri.generation - self.generation = self.new_key().compose( - component_keys, content_type=content_type, headers=headers) - self._build_uri_strings() - return self - - def get_lifecycle_config(self, validate=False, headers=None): - """Returns a bucket's lifecycle configuration.""" - self._check_bucket_uri('get_lifecycle_config') - bucket = self.get_bucket(validate, headers) - lifecycle_config = bucket.get_lifecycle_config(headers) - self.check_response(lifecycle_config, 'lifecycle', self.uri) - return lifecycle_config - - def configure_lifecycle(self, lifecycle_config, validate=False, - headers=None): - """Sets or updates a bucket's lifecycle configuration.""" - self._check_bucket_uri('configure_lifecycle') - bucket = self.get_bucket(validate, headers) - bucket.configure_lifecycle(lifecycle_config, headers) - - def exists(self, headers=None): - """Returns True if the object exists or False if it doesn't""" - if not self.object_name: - raise InvalidUriError('exists on object-less URI (%s)' % self.uri) - bucket = self.get_bucket() - key = bucket.get_key(self.object_name, headers=headers) - return bool(key) - - -class FileStorageUri(StorageUri): - """ - StorageUri subclass that handles files in the local file system. - Callers should instantiate this class by calling boto.storage_uri(). - - See file/README about how we map StorageUri operations onto a file system. - """ - - delim = os.sep - - def __init__(self, object_name, debug, is_stream=False): - """Instantiate a FileStorageUri from a path name. - - @type object_name: string - @param object_name: object name - @type debug: boolean - @param debug: whether to enable debugging on this StorageUri - - After instantiation the components are available in the following - fields: uri, scheme, bucket_name (always blank for this "anonymous" - bucket), object_name. - """ - - self.scheme = 'file' - self.bucket_name = '' - self.object_name = object_name - self.uri = 'file://' + object_name - self.debug = debug - self.stream = is_stream - - def clone_replace_name(self, new_name): - """Instantiate a FileStorageUri from the current FileStorageUri, - but replacing the object_name. - - @type new_name: string - @param new_name: new object name - """ - return FileStorageUri(new_name, self.debug, self.stream) - - def is_file_uri(self): - """Returns True if this URI names a file or directory.""" - return True - - def is_cloud_uri(self): - """Returns True if this URI names a bucket or object.""" - return False - - def names_container(self): - """Returns True if this URI names a directory or bucket.""" - return self.names_directory() - - def names_singleton(self): - """Returns True if this URI names a file (or stream) or object.""" - return not self.names_container() - - def names_directory(self): - """Returns True if this URI names a directory.""" - if self.stream: - return False - return os.path.isdir(self.object_name) - - def names_provider(self): - """Returns True if this URI names a provider.""" - return False - - def names_bucket(self): - """Returns True if this URI names a bucket.""" - return False - - def names_file(self): - """Returns True if this URI names a file.""" - return self.names_singleton() - - def names_object(self): - """Returns True if this URI names an object.""" - return False - - def is_stream(self): - """Returns True if this URI represents input/output stream. - """ - return bool(self.stream) - - def close(self): - """Closes the underlying file. - """ - self.get_key().close() - - def exists(self, _headers_not_used=None): - """Returns True if the file exists or False if it doesn't""" - # The _headers_not_used parameter is ignored. It is only there to ensure - # that this method's signature is identical to the exists method on the - # BucketStorageUri class. - return os.path.exists(self.object_name) diff --git a/awx/lib/site-packages/boto/sts/__init__.py b/awx/lib/site-packages/boto/sts/__init__.py deleted file mode 100644 index 156975ecd1..0000000000 --- a/awx/lib/site-packages/boto/sts/__init__.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (c) 2010-2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010-2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.sts.connection import STSConnection -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the STS service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` instances - """ - return get_regions('sts', connection_cls=STSConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.sts.connection.STSConnection`. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.sts.connection.STSConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/sts/connection.py b/awx/lib/site-packages/boto/sts/connection.py deleted file mode 100644 index e02f0f1e35..0000000000 --- a/awx/lib/site-packages/boto/sts/connection.py +++ /dev/null @@ -1,634 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011, Eucalyptus Systems, Inc. -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.sts.credentials import Credentials, FederationToken, AssumedRole -from boto.sts.credentials import DecodeAuthorizationMessage -import boto -import boto.utils -import datetime -import threading - -_session_token_cache = {} - - -class STSConnection(AWSQueryConnection): - """ - AWS Security Token Service - The AWS Security Token Service is a web service that enables you - to request temporary, limited-privilege credentials for AWS - Identity and Access Management (IAM) users or for users that you - authenticate (federated users). This guide provides descriptions - of the AWS Security Token Service API. - - For more detailed information about using this service, go to - `Using Temporary Security Credentials`_. - - For information about setting up signatures and authorization - through the API, go to `Signing AWS API Requests`_ in the AWS - General Reference . For general information about the Query API, - go to `Making Query Requests`_ in Using IAM . For information - about using security tokens with other AWS products, go to `Using - Temporary Security Credentials to Access AWS`_ in Using Temporary - Security Credentials . - - If you're new to AWS and need additional technical information - about a specific AWS product, you can find the product's technical - documentation at `http://aws.amazon.com/documentation/`_. - - We will refer to Amazon Identity and Access Management using the - abbreviated form IAM. All copyrights and legal protections still - apply. - """ - DefaultRegionName = 'us-east-1' - DefaultRegionEndpoint = 'sts.amazonaws.com' - APIVersion = '2011-06-15' - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - proxy_user=None, proxy_pass=None, debug=0, - https_connection_factory=None, region=None, path='/', - converter=None, validate_certs=True, anon=False, - security_token=None, profile_name=None): - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint, - connection_cls=STSConnection) - self.region = region - self.anon = anon - self._mutex = threading.Semaphore() - super(STSConnection, self).__init__(aws_access_key_id, - aws_secret_access_key, - is_secure, port, proxy, proxy_port, - proxy_user, proxy_pass, - self.region.endpoint, debug, - https_connection_factory, path, - validate_certs=validate_certs, - security_token=security_token, - profile_name=profile_name) - - def _required_auth_capability(self): - if self.anon: - return ['pure-query'] - else: - return ['hmac-v4'] - - def _check_token_cache(self, token_key, duration=None, window_seconds=60): - token = _session_token_cache.get(token_key, None) - if token: - now = datetime.datetime.utcnow() - expires = boto.utils.parse_ts(token.expiration) - delta = expires - now - if delta < datetime.timedelta(seconds=window_seconds): - msg = 'Cached session token %s is expired' % token_key - boto.log.debug(msg) - token = None - return token - - def _get_session_token(self, duration=None, - mfa_serial_number=None, mfa_token=None): - params = {} - if duration: - params['DurationSeconds'] = duration - if mfa_serial_number: - params['SerialNumber'] = mfa_serial_number - if mfa_token: - params['TokenCode'] = mfa_token - return self.get_object('GetSessionToken', params, - Credentials, verb='POST') - - def get_session_token(self, duration=None, force_new=False, - mfa_serial_number=None, mfa_token=None): - """ - Return a valid session token. Because retrieving new tokens - from the Secure Token Service is a fairly heavyweight operation - this module caches previously retrieved tokens and returns - them when appropriate. Each token is cached with a key - consisting of the region name of the STS endpoint - concatenated with the requesting user's access id. If there - is a token in the cache meeting with this key, the session - expiration is checked to make sure it is still valid and if - so, the cached token is returned. Otherwise, a new session - token is requested from STS and it is placed into the cache - and returned. - - :type duration: int - :param duration: The number of seconds the credentials should - remain valid. - - :type force_new: bool - :param force_new: If this parameter is True, a new session token - will be retrieved from the Secure Token Service regardless - of whether there is a valid cached token or not. - - :type mfa_serial_number: str - :param mfa_serial_number: The serial number of an MFA device. - If this is provided and if the mfa_passcode provided is - valid, the temporary session token will be authorized with - to perform operations requiring the MFA device authentication. - - :type mfa_token: str - :param mfa_token: The 6 digit token associated with the - MFA device. - """ - token_key = '%s:%s' % (self.region.name, self.provider.access_key) - token = self._check_token_cache(token_key, duration) - if force_new or not token: - boto.log.debug('fetching a new token for %s' % token_key) - try: - self._mutex.acquire() - token = self._get_session_token(duration, - mfa_serial_number, - mfa_token) - _session_token_cache[token_key] = token - finally: - self._mutex.release() - return token - - def get_federation_token(self, name, duration=None, policy=None): - """ - Returns a set of temporary security credentials (consisting of - an access key ID, a secret access key, and a security token) - for a federated user. A typical use is in a proxy application - that is getting temporary security credentials on behalf of - distributed applications inside a corporate network. Because - you must call the `GetFederationToken` action using the long- - term security credentials of an IAM user, this call is - appropriate in contexts where those credentials can be safely - stored, usually in a server-based application. - - **Note:** Do not use this call in mobile applications or - client-based web applications that directly get temporary - security credentials. For those types of applications, use - `AssumeRoleWithWebIdentity`. - - The `GetFederationToken` action must be called by using the - long-term AWS security credentials of the AWS account or an - IAM user. Credentials that are created by IAM users are valid - for the specified duration, between 900 seconds (15 minutes) - and 129600 seconds (36 hours); credentials that are created by - using account credentials have a maximum duration of 3600 - seconds (1 hour). - - The permissions that are granted to the federated user are the - intersection of the policy that is passed with the - `GetFederationToken` request and policies that are associated - with of the entity making the `GetFederationToken` call. - - For more information about how permissions work, see - `Controlling Permissions in Temporary Credentials`_ in Using - Temporary Security Credentials . For information about using - `GetFederationToken` to create temporary security credentials, - see `Creating Temporary Credentials to Enable Access for - Federated Users`_ in Using Temporary Security Credentials . - - :type name: string - :param name: The name of the federated user. The name is used as an - identifier for the temporary security credentials (such as `Bob`). - For example, you can reference the federated user name in a - resource-based policy, such as in an Amazon S3 bucket policy. - - :type policy: string - :param policy: A policy that specifies the permissions that are granted - to the federated user. By default, federated users have no - permissions; they do not inherit any from the IAM user. When you - specify a policy, the federated user's permissions are intersection - of the specified policy and the IAM user's policy. If you don't - specify a policy, federated users can only access AWS resources - that explicitly allow those federated users in a resource policy, - such as in an Amazon S3 bucket policy. - - :type duration: integer - :param duration: The duration, in seconds, that the session - should last. Acceptable durations for federation sessions range - from 900 seconds (15 minutes) to 129600 seconds (36 hours), with - 43200 seconds (12 hours) as the default. Sessions for AWS account - owners are restricted to a maximum of 3600 seconds (one hour). If - the duration is longer than one hour, the session for AWS account - owners defaults to one hour. - - """ - params = {'Name': name} - if duration: - params['DurationSeconds'] = duration - if policy: - params['Policy'] = policy - return self.get_object('GetFederationToken', params, - FederationToken, verb='POST') - - def assume_role(self, role_arn, role_session_name, policy=None, - duration_seconds=None, external_id=None, - mfa_serial_number=None, - mfa_token=None): - """ - Returns a set of temporary security credentials (consisting of - an access key ID, a secret access key, and a security token) - that you can use to access AWS resources that you might not - normally have access to. Typically, you use `AssumeRole` for - cross-account access or federation. - - For cross-account access, imagine that you own multiple - accounts and need to access resources in each account. You - could create long-term credentials in each account to access - those resources. However, managing all those credentials and - remembering which one can access which account can be time - consuming. Instead, you can create one set of long-term - credentials in one account and then use temporary security - credentials to access all the other accounts by assuming roles - in those accounts. For more information about roles, see - `Roles`_ in Using IAM . - - For federation, you can, for example, grant single sign-on - access to the AWS Management Console. If you already have an - identity and authentication system in your corporate network, - you don't have to recreate user identities in AWS in order to - grant those user identities access to AWS. Instead, after a - user has been authenticated, you call `AssumeRole` (and - specify the role with the appropriate permissions) to get - temporary security credentials for that user. With those - temporary security credentials, you construct a sign-in URL - that users can use to access the console. For more - information, see `Scenarios for Granting Temporary Access`_ in - AWS Security Token Service . - - The temporary security credentials are valid for the duration - that you specified when calling `AssumeRole`, which can be - from 900 seconds (15 minutes) to 3600 seconds (1 hour). The - default is 1 hour. - - The temporary security credentials that are returned from the - `AssumeRoleWithWebIdentity` response have the permissions that - are associated with the access policy of the role being - assumed and any policies that are associated with the AWS - resource being accessed. You can further restrict the - permissions of the temporary security credentials by passing a - policy in the request. The resulting permissions are an - intersection of the role's access policy and the policy that - you passed. These policies and any applicable resource-based - policies are evaluated when calls to AWS service APIs are made - using the temporary security credentials. - - To assume a role, your AWS account must be trusted by the - role. The trust relationship is defined in the role's trust - policy when the IAM role is created. You must also have a - policy that allows you to call `sts:AssumeRole`. - - **Important:** You cannot call `Assumerole` by using AWS - account credentials; access will be denied. You must use IAM - user credentials to call `AssumeRole`. - - :type role_arn: string - :param role_arn: The Amazon Resource Name (ARN) of the role that the - caller is assuming. - - :type role_session_name: string - :param role_session_name: An identifier for the assumed role session. - The session name is included as part of the `AssumedRoleUser`. - - :type policy: string - :param policy: A supplemental policy that is associated with the - temporary security credentials from the `AssumeRole` call. The - resulting permissions of the temporary security credentials are an - intersection of this policy and the access policy that is - associated with the role. Use this policy to further restrict the - permissions of the temporary security credentials. - - :type duration_seconds: integer - :param duration_seconds: The duration, in seconds, of the role session. - The value can range from 900 seconds (15 minutes) to 3600 seconds - (1 hour). By default, the value is set to 3600 seconds. - - :type external_id: string - :param external_id: A unique identifier that is used by third parties - to assume a role in their customers' accounts. For each role that - the third party can assume, they should instruct their customers to - create a role with the external ID that the third party generated. - Each time the third party assumes the role, they must pass the - customer's external ID. The external ID is useful in order to help - third parties bind a role to the customer who created it. For more - information about the external ID, see `About the External ID`_ in - Using Temporary Security Credentials . - - :type mfa_serial_number: string - :param mfa_serial_number: The identification number of the MFA device that - is associated with the user who is making the AssumeRole call. - Specify this value if the trust policy of the role being assumed - includes a condition that requires MFA authentication. The value is - either the serial number for a hardware device (such as - GAHT12345678) or an Amazon Resource Name (ARN) for a virtual device - (such as arn:aws:iam::123456789012:mfa/user). Minimum length of 9. - Maximum length of 256. - - :type mfa_token: string - :param mfa_token: The value provided by the MFA device, if the trust - policy of the role being assumed requires MFA (that is, if the - policy includes a condition that tests for MFA). If the role being - assumed requires MFA and if the TokenCode value is missing or - expired, the AssumeRole call returns an "access denied" errror. - Minimum length of 6. Maximum length of 6. - - """ - params = { - 'RoleArn': role_arn, - 'RoleSessionName': role_session_name - } - if policy is not None: - params['Policy'] = policy - if duration_seconds is not None: - params['DurationSeconds'] = duration_seconds - if external_id is not None: - params['ExternalId'] = external_id - if mfa_serial_number is not None: - params['SerialNumber'] = mfa_serial_number - if mfa_token is not None: - params['TokenCode'] = mfa_token - return self.get_object('AssumeRole', params, AssumedRole, verb='POST') - - def assume_role_with_saml(self, role_arn, principal_arn, saml_assertion, - policy=None, duration_seconds=None): - """ - Returns a set of temporary security credentials for users who - have been authenticated via a SAML authentication response. - This operation provides a mechanism for tying an enterprise - identity store or directory to role-based AWS access without - user-specific credentials or configuration. - - The temporary security credentials returned by this operation - consist of an access key ID, a secret access key, and a - security token. Applications can use these temporary security - credentials to sign calls to AWS services. The credentials are - valid for the duration that you specified when calling - `AssumeRoleWithSAML`, which can be up to 3600 seconds (1 hour) - or until the time specified in the SAML authentication - response's `NotOnOrAfter` value, whichever is shorter. - - The maximum duration for a session is 1 hour, and the minimum - duration is 15 minutes, even if values outside this range are - specified. - - Optionally, you can pass an AWS IAM access policy to this - operation. The temporary security credentials that are - returned by the operation have the permissions that are - associated with the access policy of the role being assumed, - except for any permissions explicitly denied by the policy you - pass. This gives you a way to further restrict the permissions - for the federated user. These policies and any applicable - resource-based policies are evaluated when calls to AWS are - made using the temporary security credentials. - - Before your application can call `AssumeRoleWithSAML`, you - must configure your SAML identity provider (IdP) to issue the - claims required by AWS. Additionally, you must use AWS - Identity and Access Management (AWS IAM) to create a SAML - provider entity in your AWS account that represents your - identity provider, and create an AWS IAM role that specifies - this SAML provider in its trust policy. - - Calling `AssumeRoleWithSAML` does not require the use of AWS - security credentials. The identity of the caller is validated - by using keys in the metadata document that is uploaded for - the SAML provider entity for your identity provider. - - For more information, see the following resources: - - - + `Creating Temporary Security Credentials for SAML - Federation`_ in the Using Temporary Security Credentials - guide. - + `SAML Providers`_ in the Using IAM guide. - + `Configuring a Relying Party and Claims in the Using IAM - guide. `_ - + `Creating a Role for SAML-Based Federation`_ in the Using - IAM guide. - - :type role_arn: string - :param role_arn: The Amazon Resource Name (ARN) of the role that the - caller is assuming. - - :type principal_arn: string - :param principal_arn: The Amazon Resource Name (ARN) of the SAML - provider in AWS IAM that describes the IdP. - - :type saml_assertion: string - :param saml_assertion: The base-64 encoded SAML authentication response - provided by the IdP. - For more information, see `Configuring a Relying Party and Adding - Claims`_ in the Using IAM guide. - - :type policy: string - :param policy: - An AWS IAM policy in JSON format. - - The temporary security credentials that are returned by this operation - have the permissions that are associated with the access policy of - the role being assumed, except for any permissions explicitly - denied by the policy you pass. These policies and any applicable - resource-based policies are evaluated when calls to AWS are made - using the temporary security credentials. - - The policy must be 2048 bytes or shorter, and its packed size must be - less than 450 bytes. - - :type duration_seconds: integer - :param duration_seconds: - The duration, in seconds, of the role session. The value can range from - 900 seconds (15 minutes) to 3600 seconds (1 hour). By default, the - value is set to 3600 seconds. An expiration can also be specified - in the SAML authentication response's `NotOnOrAfter` value. The - actual expiration time is whichever value is shorter. - - The maximum duration for a session is 1 hour, and the minimum duration - is 15 minutes, even if values outside this range are specified. - - """ - params = { - 'RoleArn': role_arn, - 'PrincipalArn': principal_arn, - 'SAMLAssertion': saml_assertion, - } - if policy is not None: - params['Policy'] = policy - if duration_seconds is not None: - params['DurationSeconds'] = duration_seconds - return self.get_object('AssumeRoleWithSAML', params, AssumedRole, - verb='POST') - - def assume_role_with_web_identity(self, role_arn, role_session_name, - web_identity_token, provider_id=None, - policy=None, duration_seconds=None): - """ - Returns a set of temporary security credentials for users who - have been authenticated in a mobile or web application with a - web identity provider, such as Login with Amazon, Facebook, or - Google. `AssumeRoleWithWebIdentity` is an API call that does - not require the use of AWS security credentials. Therefore, - you can distribute an application (for example, on mobile - devices) that requests temporary security credentials without - including long-term AWS credentials in the application or by - deploying server-based proxy services that use long-term AWS - credentials. For more information, see `Creating a Mobile - Application with Third-Party Sign-In`_ in AWS Security Token - Service . - - The temporary security credentials consist of an access key - ID, a secret access key, and a security token. Applications - can use these temporary security credentials to sign calls to - AWS service APIs. The credentials are valid for the duration - that you specified when calling `AssumeRoleWithWebIdentity`, - which can be from 900 seconds (15 minutes) to 3600 seconds (1 - hour). By default, the temporary security credentials are - valid for 1 hour. - - The temporary security credentials that are returned from the - `AssumeRoleWithWebIdentity` response have the permissions that - are associated with the access policy of the role being - assumed. You can further restrict the permissions of the - temporary security credentials by passing a policy in the - request. The resulting permissions are an intersection of the - role's access policy and the policy that you passed. These - policies and any applicable resource-based policies are - evaluated when calls to AWS service APIs are made using the - temporary security credentials. - - Before your application can call `AssumeRoleWithWebIdentity`, - you must have an identity token from a supported identity - provider and create a role that the application can assume. - The role that your application assumes must trust the identity - provider that is associated with the identity token. In other - words, the identity provider must be specified in the role's - trust policy. For more information, see ` Creating Temporary - Security Credentials for Mobile Apps Using Third-Party - Identity Providers`_. - - :type role_arn: string - :param role_arn: The Amazon Resource Name (ARN) of the role that the - caller is assuming. - - :type role_session_name: string - :param role_session_name: An identifier for the assumed role session. - Typically, you pass the name or identifier that is associated with - the user who is using your application. That way, the temporary - security credentials that your application will use are associated - with that user. This session name is included as part of the ARN - and assumed role ID in the `AssumedRoleUser` response element. - - :type web_identity_token: string - :param web_identity_token: The OAuth 2.0 access token or OpenID Connect - ID token that is provided by the identity provider. Your - application must get this token by authenticating the user who is - using your application with a web identity provider before the - application makes an `AssumeRoleWithWebIdentity` call. - - :type provider_id: string - :param provider_id: Specify this value only for OAuth access tokens. Do - not specify this value for OpenID Connect ID tokens, such as - `accounts.google.com`. This is the fully-qualified host component - of the domain name of the identity provider. Do not include URL - schemes and port numbers. Currently, `www.amazon.com` and - `graph.facebook.com` are supported. - - :type policy: string - :param policy: A supplemental policy that is associated with the - temporary security credentials from the `AssumeRoleWithWebIdentity` - call. The resulting permissions of the temporary security - credentials are an intersection of this policy and the access - policy that is associated with the role. Use this policy to further - restrict the permissions of the temporary security credentials. - - :type duration_seconds: integer - :param duration_seconds: The duration, in seconds, of the role session. - The value can range from 900 seconds (15 minutes) to 3600 seconds - (1 hour). By default, the value is set to 3600 seconds. - - """ - params = { - 'RoleArn': role_arn, - 'RoleSessionName': role_session_name, - 'WebIdentityToken': web_identity_token, - } - if provider_id is not None: - params['ProviderId'] = provider_id - if policy is not None: - params['Policy'] = policy - if duration_seconds is not None: - params['DurationSeconds'] = duration_seconds - return self.get_object( - 'AssumeRoleWithWebIdentity', - params, - AssumedRole, - verb='POST' - ) - - def decode_authorization_message(self, encoded_message): - """ - Decodes additional information about the authorization status - of a request from an encoded message returned in response to - an AWS request. - - For example, if a user is not authorized to perform an action - that he or she has requested, the request returns a - `Client.UnauthorizedOperation` response (an HTTP 403 - response). Some AWS actions additionally return an encoded - message that can provide details about this authorization - failure. - Only certain AWS actions return an encoded authorization - message. The documentation for an individual action indicates - whether that action returns an encoded message in addition to - returning an HTTP code. - The message is encoded because the details of the - authorization status can constitute privileged information - that the user who requested the action should not see. To - decode an authorization status message, a user must be granted - permissions via an IAM policy to request the - `DecodeAuthorizationMessage` ( - `sts:DecodeAuthorizationMessage`) action. - - The decoded message includes the following type of - information: - - - + Whether the request was denied due to an explicit deny or - due to the absence of an explicit allow. For more information, - see `Determining Whether a Request is Allowed or Denied`_ in - Using IAM . - + The principal who made the request. - + The requested action. - + The requested resource. - + The values of condition keys in the context of the user's - request. - - :type encoded_message: string - :param encoded_message: The encoded message that was returned with the - response. - - """ - params = { - 'EncodedMessage': encoded_message, - } - return self.get_object( - 'DecodeAuthorizationMessage', - params, - DecodeAuthorizationMessage, - verb='POST' - ) diff --git a/awx/lib/site-packages/boto/sts/credentials.py b/awx/lib/site-packages/boto/sts/credentials.py deleted file mode 100644 index 7ab631942c..0000000000 --- a/awx/lib/site-packages/boto/sts/credentials.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2011, Eucalyptus Systems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import os -import datetime - -import boto.utils -from boto.compat import json - - -class Credentials(object): - """ - :ivar access_key: The AccessKeyID. - :ivar secret_key: The SecretAccessKey. - :ivar session_token: The session token that must be passed with - requests to use the temporary credentials - :ivar expiration: The timestamp for when the credentials will expire - """ - - def __init__(self, parent=None): - self.parent = parent - self.access_key = None - self.secret_key = None - self.session_token = None - self.expiration = None - self.request_id = None - - @classmethod - def from_json(cls, json_doc): - """ - Create and return a new Session Token based on the contents - of a JSON document. - - :type json_doc: str - :param json_doc: A string containing a JSON document with a - previously saved Credentials object. - """ - d = json.loads(json_doc) - token = cls() - token.__dict__.update(d) - return token - - @classmethod - def load(cls, file_path): - """ - Create and return a new Session Token based on the contents - of a previously saved JSON-format file. - - :type file_path: str - :param file_path: The fully qualified path to the JSON-format - file containing the previously saved Session Token information. - """ - fp = open(file_path) - json_doc = fp.read() - fp.close() - return cls.from_json(json_doc) - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'AccessKeyId': - self.access_key = value - elif name == 'SecretAccessKey': - self.secret_key = value - elif name == 'SessionToken': - self.session_token = value - elif name == 'Expiration': - self.expiration = value - elif name == 'RequestId': - self.request_id = value - else: - pass - - def to_dict(self): - """ - Return a Python dict containing the important information - about this Session Token. - """ - return {'access_key': self.access_key, - 'secret_key': self.secret_key, - 'session_token': self.session_token, - 'expiration': self.expiration, - 'request_id': self.request_id} - - def save(self, file_path): - """ - Persist a Session Token to a file in JSON format. - - :type path: str - :param path: The fully qualified path to the file where the - the Session Token data should be written. Any previous - data in the file will be overwritten. To help protect - the credentials contained in the file, the permissions - of the file will be set to readable/writable by owner only. - """ - fp = open(file_path, 'w') - json.dump(self.to_dict(), fp) - fp.close() - os.chmod(file_path, 0o600) - - def is_expired(self, time_offset_seconds=0): - """ - Checks to see if the Session Token is expired or not. By default - it will check to see if the Session Token is expired as of the - moment the method is called. However, you can supply an - optional parameter which is the number of seconds of offset - into the future for the check. For example, if you supply - a value of 5, this method will return a True if the Session - Token will be expired 5 seconds from this moment. - - :type time_offset_seconds: int - :param time_offset_seconds: The number of seconds into the future - to test the Session Token for expiration. - """ - now = datetime.datetime.utcnow() - if time_offset_seconds: - now = now + datetime.timedelta(seconds=time_offset_seconds) - ts = boto.utils.parse_ts(self.expiration) - delta = ts - now - return delta.total_seconds() <= 0 - - -class FederationToken(object): - """ - :ivar credentials: A Credentials object containing the credentials. - :ivar federated_user_arn: ARN specifying federated user using credentials. - :ivar federated_user_id: The ID of the federated user using credentials. - :ivar packed_policy_size: A percentage value indicating the size of - the policy in packed form - """ - - def __init__(self, parent=None): - self.parent = parent - self.credentials = None - self.federated_user_arn = None - self.federated_user_id = None - self.packed_policy_size = None - self.request_id = None - - def startElement(self, name, attrs, connection): - if name == 'Credentials': - self.credentials = Credentials() - return self.credentials - else: - return None - - def endElement(self, name, value, connection): - if name == 'Arn': - self.federated_user_arn = value - elif name == 'FederatedUserId': - self.federated_user_id = value - elif name == 'PackedPolicySize': - self.packed_policy_size = int(value) - elif name == 'RequestId': - self.request_id = value - else: - pass - - -class AssumedRole(object): - """ - :ivar user: The assumed role user. - :ivar credentials: A Credentials object containing the credentials. - """ - def __init__(self, connection=None, credentials=None, user=None): - self._connection = connection - self.credentials = credentials - self.user = user - - def startElement(self, name, attrs, connection): - if name == 'Credentials': - self.credentials = Credentials() - return self.credentials - elif name == 'AssumedRoleUser': - self.user = User() - return self.user - - def endElement(self, name, value, connection): - pass - - -class User(object): - """ - :ivar arn: The arn of the user assuming the role. - :ivar assume_role_id: The identifier of the assumed role. - """ - def __init__(self, arn=None, assume_role_id=None): - self.arn = arn - self.assume_role_id = assume_role_id - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'Arn': - self.arn = value - elif name == 'AssumedRoleId': - self.assume_role_id = value - - -class DecodeAuthorizationMessage(object): - """ - :ivar request_id: The request ID. - :ivar decoded_message: The decoded authorization message (may be JSON). - """ - def __init__(self, request_id=None, decoded_message=None): - self.request_id = request_id - self.decoded_message = decoded_message - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'requestId': - self.request_id = value - elif name == 'DecodedMessage': - self.decoded_message = value diff --git a/awx/lib/site-packages/boto/support/__init__.py b/awx/lib/site-packages/boto/support/__init__.py deleted file mode 100644 index c114a9a373..0000000000 --- a/awx/lib/site-packages/boto/support/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.regioninfo import RegionInfo, get_regions - - -def regions(): - """ - Get all available regions for the Amazon Support service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - from boto.support.layer1 import SupportConnection - return get_regions('support', connection_cls=SupportConnection) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/support/exceptions.py b/awx/lib/site-packages/boto/support/exceptions.py deleted file mode 100644 index cbc19b3a2d..0000000000 --- a/awx/lib/site-packages/boto/support/exceptions.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -from boto.exception import JSONResponseError - - -class CaseIdNotFound(JSONResponseError): - pass - - -class CaseCreationLimitExceeded(JSONResponseError): - pass - - -class InternalServerError(JSONResponseError): - pass - - -class AttachmentLimitExceeded(JSONResponseError): - pass - - -class DescribeAttachmentLimitExceeded(JSONResponseError): - pass - - -class AttachmentSetIdNotFound(JSONResponseError): - pass - - -class AttachmentSetExpired(JSONResponseError): - pass - - -class AttachmentIdNotFound(JSONResponseError): - pass - - -class AttachmentSetSizeLimitExceeded(JSONResponseError): - pass diff --git a/awx/lib/site-packages/boto/support/layer1.py b/awx/lib/site-packages/boto/support/layer1.py deleted file mode 100644 index 33e83cc472..0000000000 --- a/awx/lib/site-packages/boto/support/layer1.py +++ /dev/null @@ -1,674 +0,0 @@ -# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import boto -from boto.compat import json -from boto.connection import AWSQueryConnection -from boto.regioninfo import RegionInfo -from boto.exception import JSONResponseError -from boto.support import exceptions - - -class SupportConnection(AWSQueryConnection): - """ - AWS Support - The AWS Support API reference is intended for programmers who need - detailed information about the AWS Support operations and data - types. This service enables you to manage your AWS Support cases - programmatically. It uses HTTP methods that return results in JSON - format. - - The AWS Support service also exposes a set of `Trusted Advisor`_ - features. You can retrieve a list of checks and their - descriptions, get check results, specify checks to refresh, and - get the refresh status of checks. - - The following list describes the AWS Support case management - operations: - - - + **Service names, issue categories, and available severity - levels. **The DescribeServices and DescribeSeverityLevels - operations return AWS service names, service codes, service - categories, and problem severity levels. You use these values when - you call the CreateCase operation. - + **Case creation, case details, and case resolution.** The - CreateCase, DescribeCases, DescribeAttachment, and ResolveCase - operations create AWS Support cases, retrieve information about - cases, and resolve cases. - + **Case communication.** The DescribeCommunications, - AddCommunicationToCase, and AddAttachmentsToSet operations - retrieve and add communications and attachments to AWS Support - cases. - - - The following list describes the operations available from the AWS - Support service for Trusted Advisor: - - - + DescribeTrustedAdvisorChecks returns the list of checks that run - against your AWS resources. - + Using the `CheckId` for a specific check returned by - DescribeTrustedAdvisorChecks, you can call - DescribeTrustedAdvisorCheckResult to obtain the results for the - check you specified. - + DescribeTrustedAdvisorCheckSummaries returns summarized results - for one or more Trusted Advisor checks. - + RefreshTrustedAdvisorCheck requests that Trusted Advisor rerun a - specified check. - + DescribeTrustedAdvisorCheckRefreshStatuses reports the refresh - status of one or more checks. - - - For authentication of requests, AWS Support uses `Signature - Version 4 Signing Process`_. - - See `About the AWS Support API`_ in the AWS Support User Guide for - information about how to use this service to create and manage - your support cases, and how to call Trusted Advisor for results of - checks on your resources. - """ - APIVersion = "2013-04-15" - DefaultRegionName = "us-east-1" - DefaultRegionEndpoint = "support.us-east-1.amazonaws.com" - ServiceName = "Support" - TargetPrefix = "AWSSupport_20130415" - ResponseError = JSONResponseError - - _faults = { - "CaseCreationLimitExceeded": exceptions.CaseCreationLimitExceeded, - "AttachmentLimitExceeded": exceptions.AttachmentLimitExceeded, - "CaseIdNotFound": exceptions.CaseIdNotFound, - "DescribeAttachmentLimitExceeded": exceptions.DescribeAttachmentLimitExceeded, - "AttachmentSetIdNotFound": exceptions.AttachmentSetIdNotFound, - "InternalServerError": exceptions.InternalServerError, - "AttachmentSetExpired": exceptions.AttachmentSetExpired, - "AttachmentIdNotFound": exceptions.AttachmentIdNotFound, - "AttachmentSetSizeLimitExceeded": exceptions.AttachmentSetSizeLimitExceeded, - } - - - def __init__(self, **kwargs): - region = kwargs.pop('region', None) - if not region: - region = RegionInfo(self, self.DefaultRegionName, - self.DefaultRegionEndpoint) - - if 'host' not in kwargs or kwargs['host'] is None: - kwargs['host'] = region.endpoint - - super(SupportConnection, self).__init__(**kwargs) - self.region = region - - def _required_auth_capability(self): - return ['hmac-v4'] - - def add_attachments_to_set(self, attachments, attachment_set_id=None): - """ - Adds one or more attachments to an attachment set. If an - `AttachmentSetId` is not specified, a new attachment set is - created, and the ID of the set is returned in the response. If - an `AttachmentSetId` is specified, the attachments are added - to the specified set, if it exists. - - An attachment set is a temporary container for attachments - that are to be added to a case or case communication. The set - is available for one hour after it is created; the - `ExpiryTime` returned in the response indicates when the set - expires. The maximum number of attachments in a set is 3, and - the maximum size of any attachment in the set is 5 MB. - - :type attachment_set_id: string - :param attachment_set_id: The ID of the attachment set. If an - `AttachmentSetId` is not specified, a new attachment set is - created, and the ID of the set is returned in the response. If an - `AttachmentSetId` is specified, the attachments are added to the - specified set, if it exists. - - :type attachments: list - :param attachments: One or more attachments to add to the set. The - limit is 3 attachments per set, and the size limit is 5 MB per - attachment. - - """ - params = {'attachments': attachments, } - if attachment_set_id is not None: - params['attachmentSetId'] = attachment_set_id - return self.make_request(action='AddAttachmentsToSet', - body=json.dumps(params)) - - def add_communication_to_case(self, communication_body, case_id=None, - cc_email_addresses=None, - attachment_set_id=None): - """ - Adds additional customer communication to an AWS Support case. - You use the `CaseId` value to identify the case to add - communication to. You can list a set of email addresses to - copy on the communication using the `CcEmailAddresses` value. - The `CommunicationBody` value contains the text of the - communication. - - The response indicates the success or failure of the request. - - This operation implements a subset of the behavior on the AWS - Support `Your Support Cases`_ web form. - - :type case_id: string - :param case_id: The AWS Support case ID requested or returned in the - call. The case ID is an alphanumeric string formatted as shown in - this example: case- 12345678910-2013-c4c1d2bf33c5cf47 - - :type communication_body: string - :param communication_body: The body of an email communication to add to - the support case. - - :type cc_email_addresses: list - :param cc_email_addresses: The email addresses in the CC line of an - email to be added to the support case. - - :type attachment_set_id: string - :param attachment_set_id: The ID of a set of one or more attachments - for the communication to add to the case. Create the set by calling - AddAttachmentsToSet - - """ - params = {'communicationBody': communication_body, } - if case_id is not None: - params['caseId'] = case_id - if cc_email_addresses is not None: - params['ccEmailAddresses'] = cc_email_addresses - if attachment_set_id is not None: - params['attachmentSetId'] = attachment_set_id - return self.make_request(action='AddCommunicationToCase', - body=json.dumps(params)) - - def create_case(self, subject, communication_body, service_code=None, - severity_code=None, category_code=None, - cc_email_addresses=None, language=None, issue_type=None, - attachment_set_id=None): - """ - Creates a new case in the AWS Support Center. This operation - is modeled on the behavior of the AWS Support Center `Open a - new case`_ page. Its parameters require you to specify the - following information: - - - #. **IssueType.** The type of issue for the case. You can - specify either "customer-service" or "technical." If you do - not indicate a value, the default is "technical." - #. **ServiceCode.** The code for an AWS service. You obtain - the `ServiceCode` by calling DescribeServices. - #. **CategoryCode.** The category for the service defined for - the `ServiceCode` value. You also obtain the category code for - a service by calling DescribeServices. Each AWS service - defines its own set of category codes. - #. **SeverityCode.** A value that indicates the urgency of the - case, which in turn determines the response time according to - your service level agreement with AWS Support. You obtain the - SeverityCode by calling DescribeSeverityLevels. - #. **Subject.** The **Subject** field on the AWS Support - Center `Open a new case`_ page. - #. **CommunicationBody.** The **Description** field on the AWS - Support Center `Open a new case`_ page. - #. **AttachmentSetId.** The ID of a set of attachments that - has been created by using AddAttachmentsToSet. - #. **Language.** The human language in which AWS Support - handles the case. English and Japanese are currently - supported. - #. **CcEmailAddresses.** The AWS Support Center **CC** field - on the `Open a new case`_ page. You can list email addresses - to be copied on any correspondence about the case. The account - that opens the case is already identified by passing the AWS - Credentials in the HTTP POST method or in a method or function - call from one of the programming languages supported by an - `AWS SDK`_. - - - A successful CreateCase request returns an AWS Support case - number. Case numbers are used by the DescribeCases operation - to retrieve existing AWS Support cases. - - :type subject: string - :param subject: The title of the AWS Support case. - - :type service_code: string - :param service_code: The code for the AWS service returned by the call - to DescribeServices. - - :type severity_code: string - :param severity_code: The code for the severity level returned by the - call to DescribeSeverityLevels. - - :type category_code: string - :param category_code: The category of problem for the AWS Support case. - - :type communication_body: string - :param communication_body: The communication body text when you create - an AWS Support case by calling CreateCase. - - :type cc_email_addresses: list - :param cc_email_addresses: A list of email addresses that AWS Support - copies on case correspondence. - - :type language: string - :param language: The ISO 639-1 code for the language in which AWS - provides support. AWS Support currently supports English ("en") and - Japanese ("ja"). Language parameters must be passed explicitly for - operations that take them. - - :type issue_type: string - :param issue_type: The type of issue for the case. You can specify - either "customer-service" or "technical." If you do not indicate a - value, the default is "technical." - - :type attachment_set_id: string - :param attachment_set_id: The ID of a set of one or more attachments - for the case. Create the set by using AddAttachmentsToSet. - - """ - params = { - 'subject': subject, - 'communicationBody': communication_body, - } - if service_code is not None: - params['serviceCode'] = service_code - if severity_code is not None: - params['severityCode'] = severity_code - if category_code is not None: - params['categoryCode'] = category_code - if cc_email_addresses is not None: - params['ccEmailAddresses'] = cc_email_addresses - if language is not None: - params['language'] = language - if issue_type is not None: - params['issueType'] = issue_type - if attachment_set_id is not None: - params['attachmentSetId'] = attachment_set_id - return self.make_request(action='CreateCase', - body=json.dumps(params)) - - def describe_attachment(self, attachment_id): - """ - Returns the attachment that has the specified ID. Attachment - IDs are generated by the case management system when you add - an attachment to a case or case communication. Attachment IDs - are returned in the AttachmentDetails objects that are - returned by the DescribeCommunications operation. - - :type attachment_id: string - :param attachment_id: The ID of the attachment to return. Attachment - IDs are returned by the DescribeCommunications operation. - - """ - params = {'attachmentId': attachment_id, } - return self.make_request(action='DescribeAttachment', - body=json.dumps(params)) - - def describe_cases(self, case_id_list=None, display_id=None, - after_time=None, before_time=None, - include_resolved_cases=None, next_token=None, - max_results=None, language=None, - include_communications=None): - """ - Returns a list of cases that you specify by passing one or - more case IDs. In addition, you can filter the cases by date - by setting values for the `AfterTime` and `BeforeTime` request - parameters. - - Case data is available for 12 months after creation. If a case - was created more than 12 months ago, a request for data might - cause an error. - - The response returns the following in JSON format: - - - #. One or more CaseDetails data types. - #. One or more `NextToken` values, which specify where to - paginate the returned records represented by the `CaseDetails` - objects. - - :type case_id_list: list - :param case_id_list: A list of ID numbers of the support cases you want - returned. The maximum number of cases is 100. - - :type display_id: string - :param display_id: The ID displayed for a case in the AWS Support - Center user interface. - - :type after_time: string - :param after_time: The start date for a filtered date search on support - case communications. Case communications are available for 12 - months after creation. - - :type before_time: string - :param before_time: The end date for a filtered date search on support - case communications. Case communications are available for 12 - months after creation. - - :type include_resolved_cases: boolean - :param include_resolved_cases: Specifies whether resolved support cases - should be included in the DescribeCases results. The default is - false . - - :type next_token: string - :param next_token: A resumption point for pagination. - - :type max_results: integer - :param max_results: The maximum number of results to return before - paginating. - - :type language: string - :param language: The ISO 639-1 code for the language in which AWS - provides support. AWS Support currently supports English ("en") and - Japanese ("ja"). Language parameters must be passed explicitly for - operations that take them. - - :type include_communications: boolean - :param include_communications: Specifies whether communications should - be included in the DescribeCases results. The default is true . - - """ - params = {} - if case_id_list is not None: - params['caseIdList'] = case_id_list - if display_id is not None: - params['displayId'] = display_id - if after_time is not None: - params['afterTime'] = after_time - if before_time is not None: - params['beforeTime'] = before_time - if include_resolved_cases is not None: - params['includeResolvedCases'] = include_resolved_cases - if next_token is not None: - params['nextToken'] = next_token - if max_results is not None: - params['maxResults'] = max_results - if language is not None: - params['language'] = language - if include_communications is not None: - params['includeCommunications'] = include_communications - return self.make_request(action='DescribeCases', - body=json.dumps(params)) - - def describe_communications(self, case_id, before_time=None, - after_time=None, next_token=None, - max_results=None): - """ - Returns communications (and attachments) for one or more - support cases. You can use the `AfterTime` and `BeforeTime` - parameters to filter by date. You can use the `CaseId` - parameter to restrict the results to a particular case. - - Case data is available for 12 months after creation. If a case - was created more than 12 months ago, a request for data might - cause an error. - - You can use the `MaxResults` and `NextToken` parameters to - control the pagination of the result set. Set `MaxResults` to - the number of cases you want displayed on each page, and use - `NextToken` to specify the resumption of pagination. - - :type case_id: string - :param case_id: The AWS Support case ID requested or returned in the - call. The case ID is an alphanumeric string formatted as shown in - this example: case- 12345678910-2013-c4c1d2bf33c5cf47 - - :type before_time: string - :param before_time: The end date for a filtered date search on support - case communications. Case communications are available for 12 - months after creation. - - :type after_time: string - :param after_time: The start date for a filtered date search on support - case communications. Case communications are available for 12 - months after creation. - - :type next_token: string - :param next_token: A resumption point for pagination. - - :type max_results: integer - :param max_results: The maximum number of results to return before - paginating. - - """ - params = {'caseId': case_id, } - if before_time is not None: - params['beforeTime'] = before_time - if after_time is not None: - params['afterTime'] = after_time - if next_token is not None: - params['nextToken'] = next_token - if max_results is not None: - params['maxResults'] = max_results - return self.make_request(action='DescribeCommunications', - body=json.dumps(params)) - - def describe_services(self, service_code_list=None, language=None): - """ - Returns the current list of AWS services and a list of service - categories that applies to each one. You then use service - names and categories in your CreateCase requests. Each AWS - service has its own set of categories. - - The service codes and category codes correspond to the values - that are displayed in the **Service** and **Category** drop- - down lists on the AWS Support Center `Open a new case`_ page. - The values in those fields, however, do not necessarily match - the service codes and categories returned by the - `DescribeServices` request. Always use the service codes and - categories obtained programmatically. This practice ensures - that you always have the most recent set of service and - category codes. - - :type service_code_list: list - :param service_code_list: A JSON-formatted list of service codes - available for AWS services. - - :type language: string - :param language: The ISO 639-1 code for the language in which AWS - provides support. AWS Support currently supports English ("en") and - Japanese ("ja"). Language parameters must be passed explicitly for - operations that take them. - - """ - params = {} - if service_code_list is not None: - params['serviceCodeList'] = service_code_list - if language is not None: - params['language'] = language - return self.make_request(action='DescribeServices', - body=json.dumps(params)) - - def describe_severity_levels(self, language=None): - """ - Returns the list of severity levels that you can assign to an - AWS Support case. The severity level for a case is also a - field in the CaseDetails data type included in any CreateCase - request. - - :type language: string - :param language: The ISO 639-1 code for the language in which AWS - provides support. AWS Support currently supports English ("en") and - Japanese ("ja"). Language parameters must be passed explicitly for - operations that take them. - - """ - params = {} - if language is not None: - params['language'] = language - return self.make_request(action='DescribeSeverityLevels', - body=json.dumps(params)) - - def describe_trusted_advisor_check_refresh_statuses(self, check_ids): - """ - Returns the refresh status of the Trusted Advisor checks that - have the specified check IDs. Check IDs can be obtained by - calling DescribeTrustedAdvisorChecks. - - :type check_ids: list - :param check_ids: The IDs of the Trusted Advisor checks. - - """ - params = {'checkIds': check_ids, } - return self.make_request(action='DescribeTrustedAdvisorCheckRefreshStatuses', - body=json.dumps(params)) - - def describe_trusted_advisor_check_result(self, check_id, language=None): - """ - Returns the results of the Trusted Advisor check that has the - specified check ID. Check IDs can be obtained by calling - DescribeTrustedAdvisorChecks. - - The response contains a TrustedAdvisorCheckResult object, - which contains these three objects: - - - + TrustedAdvisorCategorySpecificSummary - + TrustedAdvisorResourceDetail - + TrustedAdvisorResourcesSummary - - - In addition, the response contains these fields: - - - + **Status.** The alert status of the check: "ok" (green), - "warning" (yellow), "error" (red), or "not_available". - + **Timestamp.** The time of the last refresh of the check. - + **CheckId.** The unique identifier for the check. - - :type check_id: string - :param check_id: The unique identifier for the Trusted Advisor check. - - :type language: string - :param language: The ISO 639-1 code for the language in which AWS - provides support. AWS Support currently supports English ("en") and - Japanese ("ja"). Language parameters must be passed explicitly for - operations that take them. - - """ - params = {'checkId': check_id, } - if language is not None: - params['language'] = language - return self.make_request(action='DescribeTrustedAdvisorCheckResult', - body=json.dumps(params)) - - def describe_trusted_advisor_check_summaries(self, check_ids): - """ - Returns the summaries of the results of the Trusted Advisor - checks that have the specified check IDs. Check IDs can be - obtained by calling DescribeTrustedAdvisorChecks. - - The response contains an array of TrustedAdvisorCheckSummary - objects. - - :type check_ids: list - :param check_ids: The IDs of the Trusted Advisor checks. - - """ - params = {'checkIds': check_ids, } - return self.make_request(action='DescribeTrustedAdvisorCheckSummaries', - body=json.dumps(params)) - - def describe_trusted_advisor_checks(self, language): - """ - Returns information about all available Trusted Advisor - checks, including name, ID, category, description, and - metadata. You must specify a language code; English ("en") and - Japanese ("ja") are currently supported. The response contains - a TrustedAdvisorCheckDescription for each check. - - :type language: string - :param language: The ISO 639-1 code for the language in which AWS - provides support. AWS Support currently supports English ("en") and - Japanese ("ja"). Language parameters must be passed explicitly for - operations that take them. - - """ - params = {'language': language, } - return self.make_request(action='DescribeTrustedAdvisorChecks', - body=json.dumps(params)) - - def refresh_trusted_advisor_check(self, check_id): - """ - Requests a refresh of the Trusted Advisor check that has the - specified check ID. Check IDs can be obtained by calling - DescribeTrustedAdvisorChecks. - - The response contains a RefreshTrustedAdvisorCheckResult - object, which contains these fields: - - - + **Status.** The refresh status of the check: "none", - "enqueued", "processing", "success", or "abandoned". - + **MillisUntilNextRefreshable.** The amount of time, in - milliseconds, until the check is eligible for refresh. - + **CheckId.** The unique identifier for the check. - - :type check_id: string - :param check_id: The unique identifier for the Trusted Advisor check. - - """ - params = {'checkId': check_id, } - return self.make_request(action='RefreshTrustedAdvisorCheck', - body=json.dumps(params)) - - def resolve_case(self, case_id=None): - """ - Takes a `CaseId` and returns the initial state of the case - along with the state of the case after the call to ResolveCase - completed. - - :type case_id: string - :param case_id: The AWS Support case ID requested or returned in the - call. The case ID is an alphanumeric string formatted as shown in - this example: case- 12345678910-2013-c4c1d2bf33c5cf47 - - """ - params = {} - if case_id is not None: - params['caseId'] = case_id - return self.make_request(action='ResolveCase', - body=json.dumps(params)) - - def make_request(self, action, body): - headers = { - 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/x-amz-json-1.1', - 'Content-Length': str(len(body)), - } - http_request = self.build_base_http_request( - method='POST', path='/', auth_path='/', params={}, - headers=headers, data=body) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body) - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - exception_class = self._faults.get(fault_name, self.ResponseError) - raise exception_class(response.status, response.reason, - body=json_body) diff --git a/awx/lib/site-packages/boto/swf/__init__.py b/awx/lib/site-packages/boto/swf/__init__.py deleted file mode 100644 index bebbd69632..0000000000 --- a/awx/lib/site-packages/boto/swf/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -from boto.ec2.regioninfo import RegionInfo -from boto.regioninfo import get_regions, load_regions -import boto.swf.layer1 - -REGION_ENDPOINTS = load_regions().get('swf', {}) - - -def regions(**kw_params): - """ - Get all available regions for the Amazon Simple Workflow service. - - :rtype: list - :return: A list of :class:`boto.regioninfo.RegionInfo` - """ - return get_regions('swf', connection_cls=boto.swf.layer1.Layer1) - - -def connect_to_region(region_name, **kw_params): - for region in regions(): - if region.name == region_name: - return region.connect(**kw_params) - return None diff --git a/awx/lib/site-packages/boto/swf/exceptions.py b/awx/lib/site-packages/boto/swf/exceptions.py deleted file mode 100644 index f3ac6aeb73..0000000000 --- a/awx/lib/site-packages/boto/swf/exceptions.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Exceptions that are specific to the swf module. - -This module subclasses the base SWF response exception, -boto.exceptions.SWFResponseError, for some of the SWF specific faults. -""" -from boto.exception import SWFResponseError - - -class SWFDomainAlreadyExistsError(SWFResponseError): - """ - Raised when when the domain already exists. - """ - pass - - -class SWFLimitExceededError(SWFResponseError): - """ - Raised when when a system imposed limitation has been reached. - """ - pass - - -class SWFOperationNotPermittedError(SWFResponseError): - """ - Raised when (reserved for future use). - """ - - -class SWFTypeAlreadyExistsError(SWFResponseError): - """ - Raised when when the workflow type or activity type already exists. - """ - pass - - -class SWFWorkflowExecutionAlreadyStartedError(SWFResponseError): - """ - Raised when an open execution with the same workflow_id is already running - in the specified domain. - """ - - - diff --git a/awx/lib/site-packages/boto/swf/layer1.py b/awx/lib/site-packages/boto/swf/layer1.py deleted file mode 100644 index bba16ad270..0000000000 --- a/awx/lib/site-packages/boto/swf/layer1.py +++ /dev/null @@ -1,1512 +0,0 @@ -# Copyright (c) 2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All Rights Reserved -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# - -import time - -import boto -from boto.connection import AWSAuthConnection -from boto.provider import Provider -from boto.exception import SWFResponseError -from boto.swf import exceptions as swf_exceptions -from boto.compat import json - -# -# To get full debug output, uncomment the following line and set the -# value of Debug to be 2 -# -#boto.set_stream_logger('swf') -Debug = 0 - - -class Layer1(AWSAuthConnection): - """ - Low-level interface to Simple WorkFlow Service. - """ - - DefaultRegionName = 'us-east-1' - """The default region name for Simple Workflow.""" - - ServiceName = 'com.amazonaws.swf.service.model.SimpleWorkflowService' - """The name of the Service""" - - # In some cases, the fault response __type value is mapped to - # an exception class more specific than SWFResponseError. - _fault_excp = { - 'com.amazonaws.swf.base.model#DomainAlreadyExistsFault': - swf_exceptions.SWFDomainAlreadyExistsError, - 'com.amazonaws.swf.base.model#LimitExceededFault': - swf_exceptions.SWFLimitExceededError, - 'com.amazonaws.swf.base.model#OperationNotPermittedFault': - swf_exceptions.SWFOperationNotPermittedError, - 'com.amazonaws.swf.base.model#TypeAlreadyExistsFault': - swf_exceptions.SWFTypeAlreadyExistsError, - 'com.amazonaws.swf.base.model#WorkflowExecutionAlreadyStartedFault': - swf_exceptions.SWFWorkflowExecutionAlreadyStartedError, - } - - ResponseError = SWFResponseError - - def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, - is_secure=True, port=None, proxy=None, proxy_port=None, - debug=0, session_token=None, region=None, profile_name=None): - if not region: - region_name = boto.config.get('SWF', 'region', - self.DefaultRegionName) - for reg in boto.swf.regions(): - if reg.name == region_name: - region = reg - break - - self.region = region - super(Layer1, self).__init__(self.region.endpoint, - aws_access_key_id, aws_secret_access_key, - is_secure, port, proxy, proxy_port, - debug, session_token, profile_name=profile_name) - - def _required_auth_capability(self): - return ['hmac-v4'] - - @classmethod - def _normalize_request_dict(cls, data): - """ - This class method recurses through request data dictionary and removes - any default values. - - :type data: dict - :param data: Specifies request parameters with default values to be removed. - """ - for item in list(data.keys()): - if isinstance(data[item], dict): - cls._normalize_request_dict(data[item]) - if data[item] in (None, {}): - del data[item] - - def json_request(self, action, data, object_hook=None): - """ - This method wraps around make_request() to normalize and serialize the - dictionary with request parameters. - - :type action: string - :param action: Specifies an SWF action. - - :type data: dict - :param data: Specifies request parameters associated with the action. - """ - self._normalize_request_dict(data) - json_input = json.dumps(data) - return self.make_request(action, json_input, object_hook) - - def make_request(self, action, body='', object_hook=None): - """ - :raises: ``SWFResponseError`` if response status is not 200. - """ - headers = {'X-Amz-Target': '%s.%s' % (self.ServiceName, action), - 'Host': self.region.endpoint, - 'Content-Type': 'application/json; charset=UTF-8', - 'Content-Encoding': 'amz-1.0', - 'Content-Length': str(len(body))} - http_request = self.build_base_http_request('POST', '/', '/', - {}, headers, body, None) - response = self._mexe(http_request, sender=None, - override_num_retries=10) - response_body = response.read().decode('utf-8') - boto.log.debug(response_body) - if response.status == 200: - if response_body: - return json.loads(response_body, object_hook=object_hook) - else: - return None - else: - json_body = json.loads(response_body) - fault_name = json_body.get('__type', None) - # Certain faults get mapped to more specific exception classes. - excp_cls = self._fault_excp.get(fault_name, self.ResponseError) - raise excp_cls(response.status, response.reason, body=json_body) - - # Actions related to Activities - - def poll_for_activity_task(self, domain, task_list, identity=None): - """ - Used by workers to get an ActivityTask from the specified - activity taskList. This initiates a long poll, where the - service holds the HTTP connection open and responds as soon as - a task becomes available. The maximum time the service holds - on to the request before responding is 60 seconds. If no task - is available within 60 seconds, the poll will return an empty - result. An empty result, in this context, means that an - ActivityTask is returned, but that the value of taskToken is - an empty string. If a task is returned, the worker should use - its type to identify and process it correctly. - - :type domain: string - :param domain: The name of the domain that contains the task - lists being polled. - - :type task_list: string - :param task_list: Specifies the task list to poll for activity tasks. - - :type identity: string - :param identity: Identity of the worker making the request, which - is recorded in the ActivityTaskStarted event in the workflow - history. This enables diagnostic tracing when problems arise. - The form of this identity is user defined. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('PollForActivityTask', { - 'domain': domain, - 'taskList': {'name': task_list}, - 'identity': identity, - }) - - def respond_activity_task_completed(self, task_token, result=None): - """ - Used by workers to tell the service that the ActivityTask - identified by the taskToken completed successfully with a - result (if provided). - - :type task_token: string - :param task_token: The taskToken of the ActivityTask. - - :type result: string - :param result: The result of the activity task. It is a free - form string that is implementation specific. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RespondActivityTaskCompleted', { - 'taskToken': task_token, - 'result': result, - }) - - def respond_activity_task_failed(self, task_token, - details=None, reason=None): - """ - Used by workers to tell the service that the ActivityTask - identified by the taskToken has failed with reason (if - specified). - - :type task_token: string - :param task_token: The taskToken of the ActivityTask. - - :type details: string - :param details: Optional detailed information about the failure. - - :type reason: string - :param reason: Description of the error that may assist in diagnostics. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RespondActivityTaskFailed', { - 'taskToken': task_token, - 'details': details, - 'reason': reason, - }) - - def respond_activity_task_canceled(self, task_token, details=None): - """ - Used by workers to tell the service that the ActivityTask - identified by the taskToken was successfully - canceled. Additional details can be optionally provided using - the details argument. - - :type task_token: string - :param task_token: The taskToken of the ActivityTask. - - :type details: string - :param details: Optional detailed information about the failure. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RespondActivityTaskCanceled', { - 'taskToken': task_token, - 'details': details, - }) - - def record_activity_task_heartbeat(self, task_token, details=None): - """ - Used by activity workers to report to the service that the - ActivityTask represented by the specified taskToken is still - making progress. The worker can also (optionally) specify - details of the progress, for example percent complete, using - the details parameter. This action can also be used by the - worker as a mechanism to check if cancellation is being - requested for the activity task. If a cancellation is being - attempted for the specified task, then the boolean - cancelRequested flag returned by the service is set to true. - - :type task_token: string - :param task_token: The taskToken of the ActivityTask. - - :type details: string - :param details: If specified, contains details about the - progress of the task. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RecordActivityTaskHeartbeat', { - 'taskToken': task_token, - 'details': details, - }) - - # Actions related to Deciders - - def poll_for_decision_task(self, domain, task_list, identity=None, - maximum_page_size=None, - next_page_token=None, - reverse_order=None): - """ - Used by deciders to get a DecisionTask from the specified - decision taskList. A decision task may be returned for any - open workflow execution that is using the specified task - list. The task includes a paginated view of the history of the - workflow execution. The decider should use the workflow type - and the history to determine how to properly handle the task. - - :type domain: string - :param domain: The name of the domain containing the task - lists to poll. - - :type task_list: string - :param task_list: Specifies the task list to poll for decision tasks. - - :type identity: string - :param identity: Identity of the decider making the request, - which is recorded in the DecisionTaskStarted event in the - workflow history. This enables diagnostic tracing when - problems arise. The form of this identity is user defined. - - :type maximum_page_size: integer :param maximum_page_size: The - maximum number of history events returned in each page. The - default is 100, but the caller can override this value to a - page size smaller than the default. You cannot specify a page - size greater than 100. - - :type next_page_token: string - :param next_page_token: If on a previous call to this method a - NextPageToken was returned, the results are being paginated. - To get the next page of results, repeat the call with the - returned token and all other arguments unchanged. - - :type reverse_order: boolean - :param reverse_order: When set to true, returns the events in - reverse order. By default the results are returned in - ascending order of the eventTimestamp of the events. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('PollForDecisionTask', { - 'domain': domain, - 'taskList': {'name': task_list}, - 'identity': identity, - 'maximumPageSize': maximum_page_size, - 'nextPageToken': next_page_token, - 'reverseOrder': reverse_order, - }) - - def respond_decision_task_completed(self, task_token, - decisions=None, - execution_context=None): - """ - Used by deciders to tell the service that the DecisionTask - identified by the taskToken has successfully completed. - The decisions argument specifies the list of decisions - made while processing the task. - - :type task_token: string - :param task_token: The taskToken of the ActivityTask. - - :type decisions: list - :param decisions: The list of decisions (possibly empty) made by - the decider while processing this decision task. See the docs - for the Decision structure for details. - - :type execution_context: string - :param execution_context: User defined context to add to - workflow execution. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RespondDecisionTaskCompleted', { - 'taskToken': task_token, - 'decisions': decisions, - 'executionContext': execution_context, - }) - - def request_cancel_workflow_execution(self, domain, workflow_id, - run_id=None): - """ - Records a WorkflowExecutionCancelRequested event in the - currently running workflow execution identified by the given - domain, workflowId, and runId. This logically requests the - cancellation of the workflow execution as a whole. It is up to - the decider to take appropriate actions when it receives an - execution history with this event. - - :type domain: string - :param domain: The name of the domain containing the workflow - execution to cancel. - - :type run_id: string - :param run_id: The runId of the workflow execution to cancel. - - :type workflow_id: string - :param workflow_id: The workflowId of the workflow execution - to cancel. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RequestCancelWorkflowExecution', { - 'domain': domain, - 'workflowId': workflow_id, - 'runId': run_id, - }) - - def start_workflow_execution(self, domain, workflow_id, - workflow_name, workflow_version, - task_list=None, child_policy=None, - execution_start_to_close_timeout=None, - input=None, tag_list=None, - task_start_to_close_timeout=None): - """ - Starts an execution of the workflow type in the specified - domain using the provided workflowId and input data. - - :type domain: string - :param domain: The name of the domain in which the workflow - execution is created. - - :type workflow_id: string - :param workflow_id: The user defined identifier associated with - the workflow execution. You can use this to associate a - custom identifier with the workflow execution. You may - specify the same identifier if a workflow execution is - logically a restart of a previous execution. You cannot - have two open workflow executions with the same workflowId - at the same time. - - :type workflow_name: string - :param workflow_name: The name of the workflow type. - - :type workflow_version: string - :param workflow_version: The version of the workflow type. - - :type task_list: string - :param task_list: The task list to use for the decision tasks - generated for this workflow execution. This overrides the - defaultTaskList specified when registering the workflow type. - - :type child_policy: string - :param child_policy: If set, specifies the policy to use for the - child workflow executions of this workflow execution if it - is terminated, by calling the TerminateWorkflowExecution - action explicitly or due to an expired timeout. This policy - overrides the default child policy specified when registering - the workflow type using RegisterWorkflowType. The supported - child policies are: - - * TERMINATE: the child executions will be terminated. - * REQUEST_CANCEL: a request to cancel will be attempted - for each child execution by recording a - WorkflowExecutionCancelRequested event in its history. - It is up to the decider to take appropriate actions - when it receives an execution history with this event. - * ABANDON: no action will be taken. The child executions - will continue to run. - - :type execution_start_to_close_timeout: string - :param execution_start_to_close_timeout: The total duration for - this workflow execution. This overrides the - defaultExecutionStartToCloseTimeout specified when - registering the workflow type. - - :type input: string - :param input: The input for the workflow - execution. This is a free form string which should be - meaningful to the workflow you are starting. This input is - made available to the new workflow execution in the - WorkflowExecutionStarted history event. - - :type tag_list: list :param tag_list: The list of tags to - associate with the workflow execution. You can specify a - maximum of 5 tags. You can list workflow executions with a - specific tag by calling list_open_workflow_executions or - list_closed_workflow_executions and specifying a TagFilter. - - :type task_start_to_close_timeout: string :param - task_start_to_close_timeout: Specifies the maximum duration of - decision tasks for this workflow execution. This parameter - overrides the defaultTaskStartToCloseTimout specified when - registering the workflow type using register_workflow_type. - - :raises: UnknownResourceFault, TypeDeprecatedFault, - SWFWorkflowExecutionAlreadyStartedError, SWFLimitExceededError, - SWFOperationNotPermittedError, DefaultUndefinedFault - """ - return self.json_request('StartWorkflowExecution', { - 'domain': domain, - 'workflowId': workflow_id, - 'workflowType': {'name': workflow_name, - 'version': workflow_version}, - 'taskList': {'name': task_list}, - 'childPolicy': child_policy, - 'executionStartToCloseTimeout': execution_start_to_close_timeout, - 'input': input, - 'tagList': tag_list, - 'taskStartToCloseTimeout': task_start_to_close_timeout, - - }) - - def signal_workflow_execution(self, domain, signal_name, workflow_id, - input=None, run_id=None): - """ - Records a WorkflowExecutionSignaled event in the workflow - execution history and creates a decision task for the workflow - execution identified by the given domain, workflowId and - runId. The event is recorded with the specified user defined - signalName and input (if provided). - - :type domain: string - :param domain: The name of the domain containing the workflow - execution to signal. - - :type signal_name: string - :param signal_name: The name of the signal. This name must be - meaningful to the target workflow. - - :type workflow_id: string - :param workflow_id: The workflowId of the workflow execution - to signal. - - :type input: string - :param input: Data to attach to the WorkflowExecutionSignaled - event in the target workflow execution's history. - - :type run_id: string - :param run_id: The runId of the workflow execution to signal. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('SignalWorkflowExecution', { - 'domain': domain, - 'signalName': signal_name, - 'workflowId': workflow_id, - 'input': input, - 'runId': run_id, - }) - - def terminate_workflow_execution(self, domain, workflow_id, - child_policy=None, details=None, - reason=None, run_id=None): - """ - Records a WorkflowExecutionTerminated event and forces closure - of the workflow execution identified by the given domain, - runId, and workflowId. The child policy, registered with the - workflow type or specified when starting this execution, is - applied to any open child workflow executions of this workflow - execution. - - :type domain: string - :param domain: The domain of the workflow execution to terminate. - - :type workflow_id: string - :param workflow_id: The workflowId of the workflow execution - to terminate. - - :type child_policy: string - :param child_policy: If set, specifies the policy to use for - the child workflow executions of the workflow execution being - terminated. This policy overrides the child policy specified - for the workflow execution at registration time or when - starting the execution. The supported child policies are: - - * TERMINATE: the child executions will be terminated. - - * REQUEST_CANCEL: a request to cancel will be attempted - for each child execution by recording a - WorkflowExecutionCancelRequested event in its - history. It is up to the decider to take appropriate - actions when it receives an execution history with this - event. - - * ABANDON: no action will be taken. The child executions - will continue to run. - - :type details: string - :param details: Optional details for terminating the - workflow execution. - - :type reason: string - :param reason: An optional descriptive reason for terminating - the workflow execution. - - :type run_id: string - :param run_id: The runId of the workflow execution to terminate. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('TerminateWorkflowExecution', { - 'domain': domain, - 'workflowId': workflow_id, - 'childPolicy': child_policy, - 'details': details, - 'reason': reason, - 'runId': run_id, - }) - -# Actions related to Administration - -## Activity Management - - def register_activity_type(self, domain, name, version, task_list=None, - default_task_heartbeat_timeout=None, - default_task_schedule_to_close_timeout=None, - default_task_schedule_to_start_timeout=None, - default_task_start_to_close_timeout=None, - description=None): - """ - Registers a new activity type along with its configuration - settings in the specified domain. - - :type domain: string - :param domain: The name of the domain in which this activity is - to be registered. - - :type name: string - :param name: The name of the activity type within the domain. - - :type version: string - :param version: The version of the activity type. - - :type task_list: string - :param task_list: If set, specifies the default task list to - use for scheduling tasks of this activity type. This default - task list is used if a task list is not provided when a task - is scheduled through the schedule_activity_task Decision. - - :type default_task_heartbeat_timeout: string - :param default_task_heartbeat_timeout: If set, specifies the - default maximum time before which a worker processing a task - of this type must report progress by calling - RecordActivityTaskHeartbeat. If the timeout is exceeded, the - activity task is automatically timed out. This default can be - overridden when scheduling an activity task using the - ScheduleActivityTask Decision. If the activity worker - subsequently attempts to record a heartbeat or returns a - result, the activity worker receives an UnknownResource - fault. In this case, Amazon SWF no longer considers the - activity task to be valid; the activity worker should clean up - the activity task.no docs - - :type default_task_schedule_to_close_timeout: string - :param default_task_schedule_to_close_timeout: If set, - specifies the default maximum duration for a task of this - activity type. This default can be overridden when scheduling - an activity task using the ScheduleActivityTask Decision.no - docs - - :type default_task_schedule_to_start_timeout: string - :param default_task_schedule_to_start_timeout: If set, - specifies the default maximum duration that a task of this - activity type can wait before being assigned to a worker. This - default can be overridden when scheduling an activity task - using the ScheduleActivityTask Decision. - - :type default_task_start_to_close_timeout: string - :param default_task_start_to_close_timeout: If set, specifies - the default maximum duration that a worker can take to process - tasks of this activity type. This default can be overridden - when scheduling an activity task using the - ScheduleActivityTask Decision. - - :type description: string - :param description: A textual description of the activity type. - - :raises: SWFTypeAlreadyExistsError, SWFLimitExceededError, - UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RegisterActivityType', { - 'domain': domain, - 'name': name, - 'version': version, - 'defaultTaskList': {'name': task_list}, - 'defaultTaskHeartbeatTimeout': default_task_heartbeat_timeout, - 'defaultTaskScheduleToCloseTimeout': default_task_schedule_to_close_timeout, - 'defaultTaskScheduleToStartTimeout': default_task_schedule_to_start_timeout, - 'defaultTaskStartToCloseTimeout': default_task_start_to_close_timeout, - 'description': description, - }) - - def deprecate_activity_type(self, domain, activity_name, activity_version): - """ - Returns information about the specified activity type. This - includes configuration settings provided at registration time - as well as other general information about the type. - - :type domain: string - :param domain: The name of the domain in which the activity - type is registered. - - :type activity_name: string - :param activity_name: The name of this activity. - - :type activity_version: string - :param activity_version: The version of this activity. - - :raises: UnknownResourceFault, TypeDeprecatedFault, - SWFOperationNotPermittedError - """ - return self.json_request('DeprecateActivityType', { - 'domain': domain, - 'activityType': {'name': activity_name, - 'version': activity_version} - }) - -## Workflow Management - - def register_workflow_type(self, domain, name, version, - task_list=None, - default_child_policy=None, - default_execution_start_to_close_timeout=None, - default_task_start_to_close_timeout=None, - description=None): - """ - Registers a new workflow type and its configuration settings - in the specified domain. - - :type domain: string - :param domain: The name of the domain in which to register - the workflow type. - - :type name: string - :param name: The name of the workflow type. - - :type version: string - :param version: The version of the workflow type. - - :type task_list: list of name, version of tasks - :param task_list: If set, specifies the default task list to use - for scheduling decision tasks for executions of this workflow - type. This default is used only if a task list is not provided - when starting the execution through the StartWorkflowExecution - Action or StartChildWorkflowExecution Decision. - - :type default_child_policy: string - - :param default_child_policy: If set, specifies the default - policy to use for the child workflow executions when a - workflow execution of this type is terminated, by calling the - TerminateWorkflowExecution action explicitly or due to an - expired timeout. This default can be overridden when starting - a workflow execution using the StartWorkflowExecution action - or the StartChildWorkflowExecution Decision. The supported - child policies are: - - * TERMINATE: the child executions will be terminated. - - * REQUEST_CANCEL: a request to cancel will be attempted - for each child execution by recording a - WorkflowExecutionCancelRequested event in its - history. It is up to the decider to take appropriate - actions when it receives an execution history with this - event. - - * ABANDON: no action will be taken. The child executions - will continue to run.no docs - - :type default_execution_start_to_close_timeout: string - :param default_execution_start_to_close_timeout: If set, - specifies the default maximum duration for executions of this - workflow type. You can override this default when starting an - execution through the StartWorkflowExecution Action or - StartChildWorkflowExecution Decision. - - :type default_task_start_to_close_timeout: string - :param default_task_start_to_close_timeout: If set, specifies - the default maximum duration of decision tasks for this - workflow type. This default can be overridden when starting a - workflow execution using the StartWorkflowExecution action or - the StartChildWorkflowExecution Decision. - - :type description: string - :param description: Textual description of the workflow type. - - :raises: SWFTypeAlreadyExistsError, SWFLimitExceededError, - UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('RegisterWorkflowType', { - 'domain': domain, - 'name': name, - 'version': version, - 'defaultTaskList': {'name': task_list}, - 'defaultChildPolicy': default_child_policy, - 'defaultExecutionStartToCloseTimeout': default_execution_start_to_close_timeout, - 'defaultTaskStartToCloseTimeout': default_task_start_to_close_timeout, - 'description': description, - }) - - def deprecate_workflow_type(self, domain, workflow_name, workflow_version): - """ - Deprecates the specified workflow type. After a workflow type - has been deprecated, you cannot create new executions of that - type. Executions that were started before the type was - deprecated will continue to run. A deprecated workflow type - may still be used when calling visibility actions. - - :type domain: string - :param domain: The name of the domain in which the workflow - type is registered. - - :type workflow_name: string - :param workflow_name: The name of the workflow type. - - :type workflow_version: string - :param workflow_version: The version of the workflow type. - - :raises: UnknownResourceFault, TypeDeprecatedFault, - SWFOperationNotPermittedError - """ - return self.json_request('DeprecateWorkflowType', { - 'domain': domain, - 'workflowType': {'name': workflow_name, - 'version': workflow_version}, - }) - -## Domain Management - - def register_domain(self, name, - workflow_execution_retention_period_in_days, - description=None): - """ - Registers a new domain. - - :type name: string - :param name: Name of the domain to register. The name must be unique. - - :type workflow_execution_retention_period_in_days: string - - :param workflow_execution_retention_period_in_days: Specifies - the duration *in days* for which the record (including the - history) of workflow executions in this domain should be kept - by the service. After the retention period, the workflow - execution will not be available in the results of visibility - calls. If a duration of NONE is specified, the records for - workflow executions in this domain are not retained at all. - - :type description: string - :param description: Textual description of the domain. - - :raises: SWFDomainAlreadyExistsError, SWFLimitExceededError, - SWFOperationNotPermittedError - """ - return self.json_request('RegisterDomain', { - 'name': name, - 'workflowExecutionRetentionPeriodInDays': workflow_execution_retention_period_in_days, - 'description': description, - }) - - def deprecate_domain(self, name): - """ - Deprecates the specified domain. After a domain has been - deprecated it cannot be used to create new workflow executions - or register new types. However, you can still use visibility - actions on this domain. Deprecating a domain also deprecates - all activity and workflow types registered in the - domain. Executions that were started before the domain was - deprecated will continue to run. - - :type name: string - :param name: The name of the domain to deprecate. - - :raises: UnknownResourceFault, DomainDeprecatedFault, - SWFOperationNotPermittedError - """ - return self.json_request('DeprecateDomain', {'name': name}) - -# Visibility Actions - -## Activity Visibility - - def list_activity_types(self, domain, registration_status, - name=None, - maximum_page_size=None, - next_page_token=None, reverse_order=None): - """ - Returns information about all activities registered in the - specified domain that match the specified name and - registration status. The result includes information like - creation date, current status of the activity, etc. The - results may be split into multiple pages. To retrieve - subsequent pages, make the call again using the nextPageToken - returned by the initial call. - - :type domain: string - :param domain: The name of the domain in which the activity - types have been registered. - - :type registration_status: string - :param registration_status: Specifies the registration status - of the activity types to list. Valid values are: - - * REGISTERED - * DEPRECATED - - :type name: string - :param name: If specified, only lists the activity types that - have this name. - - :type maximum_page_size: integer - :param maximum_page_size: The maximum number of results - returned in each page. The default is 100, but the caller can - override this value to a page size smaller than the - default. You cannot specify a page size greater than 100. - - :type next_page_token: string - :param next_page_token: If on a previous call to this method a - NextResultToken was returned, the results have more than one - page. To get the next page of results, repeat the call with - the nextPageToken and keep all other arguments unchanged. - - :type reverse_order: boolean - - :param reverse_order: When set to true, returns the results in - reverse order. By default the results are returned in - ascending alphabetical order of the name of the activity - types. - - :raises: SWFOperationNotPermittedError, UnknownResourceFault - """ - return self.json_request('ListActivityTypes', { - 'domain': domain, - 'name': name, - 'registrationStatus': registration_status, - 'maximumPageSize': maximum_page_size, - 'nextPageToken': next_page_token, - 'reverseOrder': reverse_order, - }) - - def describe_activity_type(self, domain, activity_name, activity_version): - """ - Returns information about the specified activity type. This - includes configuration settings provided at registration time - as well as other general information about the type. - - :type domain: string - :param domain: The name of the domain in which the activity - type is registered. - - :type activity_name: string - :param activity_name: The name of this activity. - - :type activity_version: string - :param activity_version: The version of this activity. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('DescribeActivityType', { - 'domain': domain, - 'activityType': {'name': activity_name, - 'version': activity_version} - }) - -## Workflow Visibility - - def list_workflow_types(self, domain, registration_status, - maximum_page_size=None, name=None, - next_page_token=None, reverse_order=None): - """ - Returns information about workflow types in the specified - domain. The results may be split into multiple pages that can - be retrieved by making the call repeatedly. - - :type domain: string - :param domain: The name of the domain in which the workflow - types have been registered. - - :type registration_status: string - :param registration_status: Specifies the registration status - of the activity types to list. Valid values are: - - * REGISTERED - * DEPRECATED - - :type name: string - :param name: If specified, lists the workflow type with this name. - - :type maximum_page_size: integer - :param maximum_page_size: The maximum number of results - returned in each page. The default is 100, but the caller can - override this value to a page size smaller than the - default. You cannot specify a page size greater than 100. - - :type next_page_token: string - :param next_page_token: If on a previous call to this method a - NextPageToken was returned, the results are being - paginated. To get the next page of results, repeat the call - with the returned token and all other arguments unchanged. - - :type reverse_order: boolean - :param reverse_order: When set to true, returns the results in - reverse order. By default the results are returned in - ascending alphabetical order of the name of the workflow - types. - - :raises: SWFOperationNotPermittedError, UnknownResourceFault - """ - return self.json_request('ListWorkflowTypes', { - 'domain': domain, - 'name': name, - 'registrationStatus': registration_status, - 'maximumPageSize': maximum_page_size, - 'nextPageToken': next_page_token, - 'reverseOrder': reverse_order, - }) - - def describe_workflow_type(self, domain, workflow_name, workflow_version): - """ - Returns information about the specified workflow type. This - includes configuration settings specified when the type was - registered and other information such as creation date, - current status, etc. - - :type domain: string - :param domain: The name of the domain in which this workflow - type is registered. - - :type workflow_name: string - :param workflow_name: The name of the workflow type. - - :type workflow_version: string - :param workflow_version: The version of the workflow type. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('DescribeWorkflowType', { - 'domain': domain, - 'workflowType': {'name': workflow_name, - 'version': workflow_version} - }) - -## Workflow Execution Visibility - - def describe_workflow_execution(self, domain, run_id, workflow_id): - """ - Returns information about the specified workflow execution - including its type and some statistics. - - :type domain: string - :param domain: The name of the domain containing the - workflow execution. - - :type run_id: string - :param run_id: A system generated unique identifier for the - workflow execution. - - :type workflow_id: string - :param workflow_id: The user defined identifier associated - with the workflow execution. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('DescribeWorkflowExecution', { - 'domain': domain, - 'execution': {'runId': run_id, - 'workflowId': workflow_id}, - }) - - def get_workflow_execution_history(self, domain, run_id, workflow_id, - maximum_page_size=None, - next_page_token=None, - reverse_order=None): - """ - Returns the history of the specified workflow execution. The - results may be split into multiple pages. To retrieve - subsequent pages, make the call again using the nextPageToken - returned by the initial call. - - :type domain: string - :param domain: The name of the domain containing the - workflow execution. - - :type run_id: string - :param run_id: A system generated unique identifier for the - workflow execution. - - :type workflow_id: string - :param workflow_id: The user defined identifier associated - with the workflow execution. - - :type maximum_page_size: integer - :param maximum_page_size: Specifies the maximum number of - history events returned in one page. The next page in the - result is identified by the NextPageToken returned. By default - 100 history events are returned in a page but the caller can - override this value to a page size smaller than the - default. You cannot specify a page size larger than 100. - - :type next_page_token: string - :param next_page_token: If a NextPageToken is returned, the - result has more than one pages. To get the next page, repeat - the call and specify the nextPageToken with all other - arguments unchanged. - - :type reverse_order: boolean - :param reverse_order: When set to true, returns the events in - reverse order. By default the results are returned in - ascending order of the eventTimeStamp of the events. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('GetWorkflowExecutionHistory', { - 'domain': domain, - 'execution': {'runId': run_id, - 'workflowId': workflow_id}, - 'maximumPageSize': maximum_page_size, - 'nextPageToken': next_page_token, - 'reverseOrder': reverse_order, - }) - - def count_open_workflow_executions(self, domain, latest_date, oldest_date, - tag=None, - workflow_id=None, - workflow_name=None, - workflow_version=None): - """ - Returns the number of open workflow executions within the - given domain that meet the specified filtering criteria. - - .. note: - workflow_id, workflow_name/workflow_version and tag are mutually - exclusive. You can specify at most one of these in a request. - - :type domain: string - :param domain: The name of the domain containing the - workflow executions to count. - - :type latest_date: timestamp - :param latest_date: Specifies the latest start or close date - and time to return. - - :type oldest_date: timestamp - :param oldest_date: Specifies the oldest start or close date - and time to return. - - :type workflow_name: string - :param workflow_name: Name of the workflow type to filter on. - - :type workflow_version: string - :param workflow_version: Version of the workflow type to filter on. - - :type tag: string - :param tag: If specified, only executions that have a tag - that matches the filter are counted. - - :type workflow_id: string - :param workflow_id: If specified, only workflow executions - matching the workflow_id are counted. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('CountOpenWorkflowExecutions', { - 'domain': domain, - 'startTimeFilter': {'oldestDate': oldest_date, - 'latestDate': latest_date}, - 'typeFilter': {'name': workflow_name, - 'version': workflow_version}, - 'executionFilter': {'workflowId': workflow_id}, - 'tagFilter': {'tag': tag}, - }) - - def list_open_workflow_executions(self, domain, - oldest_date, - latest_date=None, - tag=None, - workflow_id=None, - workflow_name=None, - workflow_version=None, - maximum_page_size=None, - next_page_token=None, - reverse_order=None): - """ - Returns the list of open workflow executions within the - given domain that meet the specified filtering criteria. - - .. note: - workflow_id, workflow_name/workflow_version - and tag are mutually exclusive. You can specify at most - one of these in a request. - - :type domain: string - :param domain: The name of the domain containing the - workflow executions to count. - - :type latest_date: timestamp - :param latest_date: Specifies the latest start or close date - and time to return. - - :type oldest_date: timestamp - :param oldest_date: Specifies the oldest start or close date - and time to return. - - :type tag: string - :param tag: If specified, only executions that have a tag - that matches the filter are counted. - - :type workflow_id: string - :param workflow_id: If specified, only workflow executions - matching the workflow_id are counted. - - :type workflow_name: string - :param workflow_name: Name of the workflow type to filter on. - - :type workflow_version: string - :param workflow_version: Version of the workflow type to filter on. - - :type maximum_page_size: integer - :param maximum_page_size: The maximum number of results - returned in each page. The default is 100, but the caller can - override this value to a page size smaller than the - default. You cannot specify a page size greater than 100. - - :type next_page_token: string - :param next_page_token: If on a previous call to this method a - NextPageToken was returned, the results are being - paginated. To get the next page of results, repeat the call - with the returned token and all other arguments unchanged. - - :type reverse_order: boolean - :param reverse_order: When set to true, returns the results in - reverse order. By default the results are returned in - descending order of the start or the close time of the - executions. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - - """ - return self.json_request('ListOpenWorkflowExecutions', { - 'domain': domain, - 'startTimeFilter': {'oldestDate': oldest_date, - 'latestDate': latest_date}, - 'tagFilter': {'tag': tag}, - 'typeFilter': {'name': workflow_name, - 'version': workflow_version}, - 'executionFilter': {'workflowId': workflow_id}, - 'maximumPageSize': maximum_page_size, - 'nextPageToken': next_page_token, - 'reverseOrder': reverse_order, - }) - - def count_closed_workflow_executions(self, domain, - start_latest_date=None, - start_oldest_date=None, - close_latest_date=None, - close_oldest_date=None, - close_status=None, - tag=None, - workflow_id=None, - workflow_name=None, - workflow_version=None): - """ - Returns the number of closed workflow executions within the - given domain that meet the specified filtering criteria. - - .. note: - close_status, workflow_id, workflow_name/workflow_version - and tag are mutually exclusive. You can specify at most - one of these in a request. - - .. note: - start_latest_date/start_oldest_date and - close_latest_date/close_oldest_date are mutually - exclusive. You can specify at most one of these in a request. - - :type domain: string - :param domain: The name of the domain containing the - workflow executions to count. - - :type start_latest_date: timestamp - :param start_latest_date: If specified, only workflow executions - that meet the start time criteria of the filter are counted. - - :type start_oldest_date: timestamp - :param start_oldest_date: If specified, only workflow executions - that meet the start time criteria of the filter are counted. - - :type close_latest_date: timestamp - :param close_latest_date: If specified, only workflow executions - that meet the close time criteria of the filter are counted. - - :type close_oldest_date: timestamp - :param close_oldest_date: If specified, only workflow executions - that meet the close time criteria of the filter are counted. - - :type close_status: string - :param close_status: The close status that must match the close status - of an execution for it to meet the criteria of this filter. - Valid values are: - - * COMPLETED - * FAILED - * CANCELED - * TERMINATED - * CONTINUED_AS_NEW - * TIMED_OUT - - :type tag: string - :param tag: If specified, only executions that have a tag - that matches the filter are counted. - - :type workflow_id: string - :param workflow_id: If specified, only workflow executions - matching the workflow_id are counted. - - :type workflow_name: string - :param workflow_name: Name of the workflow type to filter on. - - :type workflow_version: string - :param workflow_version: Version of the workflow type to filter on. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('CountClosedWorkflowExecutions', { - 'domain': domain, - 'startTimeFilter': {'oldestDate': start_oldest_date, - 'latestDate': start_latest_date}, - 'closeTimeFilter': {'oldestDate': close_oldest_date, - 'latestDate': close_latest_date}, - 'closeStatusFilter': {'status': close_status}, - 'tagFilter': {'tag': tag}, - 'typeFilter': {'name': workflow_name, - 'version': workflow_version}, - 'executionFilter': {'workflowId': workflow_id} - }) - - def list_closed_workflow_executions(self, domain, - start_latest_date=None, - start_oldest_date=None, - close_latest_date=None, - close_oldest_date=None, - close_status=None, - tag=None, - workflow_id=None, - workflow_name=None, - workflow_version=None, - maximum_page_size=None, - next_page_token=None, - reverse_order=None): - """ - Returns the number of closed workflow executions within the - given domain that meet the specified filtering criteria. - - .. note: - close_status, workflow_id, workflow_name/workflow_version - and tag are mutually exclusive. You can specify at most - one of these in a request. - - .. note: - start_latest_date/start_oldest_date and - close_latest_date/close_oldest_date are mutually - exclusive. You can specify at most one of these in a request. - - :type domain: string - :param domain: The name of the domain containing the - workflow executions to count. - - :type start_latest_date: timestamp - :param start_latest_date: If specified, only workflow executions - that meet the start time criteria of the filter are counted. - - :type start_oldest_date: timestamp - :param start_oldest_date: If specified, only workflow executions - that meet the start time criteria of the filter are counted. - - :type close_latest_date: timestamp - :param close_latest_date: If specified, only workflow executions - that meet the close time criteria of the filter are counted. - - :type close_oldest_date: timestamp - :param close_oldest_date: If specified, only workflow executions - that meet the close time criteria of the filter are counted. - - :type close_status: string - :param close_status: The close status that must match the close status - of an execution for it to meet the criteria of this filter. - Valid values are: - - * COMPLETED - * FAILED - * CANCELED - * TERMINATED - * CONTINUED_AS_NEW - * TIMED_OUT - - :type tag: string - :param tag: If specified, only executions that have a tag - that matches the filter are counted. - - :type workflow_id: string - :param workflow_id: If specified, only workflow executions - matching the workflow_id are counted. - - :type workflow_name: string - :param workflow_name: Name of the workflow type to filter on. - - :type workflow_version: string - :param workflow_version: Version of the workflow type to filter on. - - :type maximum_page_size: integer - :param maximum_page_size: The maximum number of results - returned in each page. The default is 100, but the caller can - override this value to a page size smaller than the - default. You cannot specify a page size greater than 100. - - :type next_page_token: string - :param next_page_token: If on a previous call to this method a - NextPageToken was returned, the results are being - paginated. To get the next page of results, repeat the call - with the returned token and all other arguments unchanged. - - :type reverse_order: boolean - :param reverse_order: When set to true, returns the results in - reverse order. By default the results are returned in - descending order of the start or the close time of the - executions. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('ListClosedWorkflowExecutions', { - 'domain': domain, - 'startTimeFilter': {'oldestDate': start_oldest_date, - 'latestDate': start_latest_date}, - 'closeTimeFilter': {'oldestDate': close_oldest_date, - 'latestDate': close_latest_date}, - 'executionFilter': {'workflowId': workflow_id}, - 'closeStatusFilter': {'status': close_status}, - 'tagFilter': {'tag': tag}, - 'typeFilter': {'name': workflow_name, - 'version': workflow_version}, - 'maximumPageSize': maximum_page_size, - 'nextPageToken': next_page_token, - 'reverseOrder': reverse_order, - }) - -## Domain Visibility - - def list_domains(self, registration_status, - maximum_page_size=None, - next_page_token=None, reverse_order=None): - """ - Returns the list of domains registered in the account. The - results may be split into multiple pages. To retrieve - subsequent pages, make the call again using the nextPageToken - returned by the initial call. - - :type registration_status: string - :param registration_status: Specifies the registration status - of the domains to list. Valid Values: - - * REGISTERED - * DEPRECATED - - :type maximum_page_size: integer - :param maximum_page_size: The maximum number of results - returned in each page. The default is 100, but the caller can - override this value to a page size smaller than the - default. You cannot specify a page size greater than 100. - - :type next_page_token: string - :param next_page_token: If on a previous call to this method a - NextPageToken was returned, the result has more than one - page. To get the next page of results, repeat the call with - the returned token and all other arguments unchanged. - - :type reverse_order: boolean - :param reverse_order: When set to true, returns the results in - reverse order. By default the results are returned in - ascending alphabetical order of the name of the domains. - - :raises: SWFOperationNotPermittedError - """ - return self.json_request('ListDomains', { - 'registrationStatus': registration_status, - 'maximumPageSize': maximum_page_size, - 'nextPageToken': next_page_token, - 'reverseOrder': reverse_order, - }) - - def describe_domain(self, name): - """ - Returns information about the specified domain including - description and status. - - :type name: string - :param name: The name of the domain to describe. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('DescribeDomain', {'name': name}) - -## Task List Visibility - - def count_pending_decision_tasks(self, domain, task_list): - """ - Returns the estimated number of decision tasks in the - specified task list. The count returned is an approximation - and is not guaranteed to be exact. If you specify a task list - that no decision task was ever scheduled in then 0 will be - returned. - - :type domain: string - :param domain: The name of the domain that contains the task list. - - :type task_list: string - :param task_list: The name of the task list. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('CountPendingDecisionTasks', { - 'domain': domain, - 'taskList': {'name': task_list} - }) - - def count_pending_activity_tasks(self, domain, task_list): - """ - Returns the estimated number of activity tasks in the - specified task list. The count returned is an approximation - and is not guaranteed to be exact. If you specify a task list - that no activity task was ever scheduled in then 0 will be - returned. - - :type domain: string - :param domain: The name of the domain that contains the task list. - - :type task_list: string - :param task_list: The name of the task list. - - :raises: UnknownResourceFault, SWFOperationNotPermittedError - """ - return self.json_request('CountPendingActivityTasks', { - 'domain': domain, - 'taskList': {'name': task_list} - }) diff --git a/awx/lib/site-packages/boto/swf/layer1_decisions.py b/awx/lib/site-packages/boto/swf/layer1_decisions.py deleted file mode 100644 index 3f5f74af40..0000000000 --- a/awx/lib/site-packages/boto/swf/layer1_decisions.py +++ /dev/null @@ -1,287 +0,0 @@ -""" -Helper class for creating decision responses. -""" - - -class Layer1Decisions(object): - """ - Use this object to build a list of decisions for a decision response. - Each method call will add append a new decision. Retrieve the list - of decisions from the _data attribute. - - """ - def __init__(self): - self._data = [] - - def schedule_activity_task(self, - activity_id, - activity_type_name, - activity_type_version, - task_list=None, - control=None, - heartbeat_timeout=None, - schedule_to_close_timeout=None, - schedule_to_start_timeout=None, - start_to_close_timeout=None, - input=None): - """ - Schedules an activity task. - - :type activity_id: string - :param activity_id: The activityId of the type of the activity - being scheduled. - - :type activity_type_name: string - :param activity_type_name: The name of the type of the activity - being scheduled. - - :type activity_type_version: string - :param activity_type_version: The version of the type of the - activity being scheduled. - - :type task_list: string - :param task_list: If set, specifies the name of the task list in - which to schedule the activity task. If not specified, the - defaultTaskList registered with the activity type will be used. - Note: a task list for this activity task must be specified either - as a default for the activity type or through this field. If - neither this field is set nor a default task list was specified - at registration time then a fault will be returned. - """ - o = {} - o['decisionType'] = 'ScheduleActivityTask' - attrs = o['scheduleActivityTaskDecisionAttributes'] = {} - attrs['activityId'] = activity_id - attrs['activityType'] = { - 'name': activity_type_name, - 'version': activity_type_version, - } - if task_list is not None: - attrs['taskList'] = {'name': task_list} - if control is not None: - attrs['control'] = control - if heartbeat_timeout is not None: - attrs['heartbeatTimeout'] = heartbeat_timeout - if schedule_to_close_timeout is not None: - attrs['scheduleToCloseTimeout'] = schedule_to_close_timeout - if schedule_to_start_timeout is not None: - attrs['scheduleToStartTimeout'] = schedule_to_start_timeout - if start_to_close_timeout is not None: - attrs['startToCloseTimeout'] = start_to_close_timeout - if input is not None: - attrs['input'] = input - self._data.append(o) - - def request_cancel_activity_task(self, activity_id): - """ - Attempts to cancel a previously scheduled activity task. If - the activity task was scheduled but has not been assigned to a - worker, then it will be canceled. If the activity task was - already assigned to a worker, then the worker will be informed - that cancellation has been requested in the response to - RecordActivityTaskHeartbeat. - """ - o = {} - o['decisionType'] = 'RequestCancelActivityTask' - attrs = o['requestCancelActivityTaskDecisionAttributes'] = {} - attrs['activityId'] = activity_id - self._data.append(o) - - def record_marker(self, marker_name, details=None): - """ - Records a MarkerRecorded event in the history. Markers can be - used for adding custom information in the history for instance - to let deciders know that they do not need to look at the - history beyond the marker event. - """ - o = {} - o['decisionType'] = 'RecordMarker' - attrs = o['recordMarkerDecisionAttributes'] = {} - attrs['markerName'] = marker_name - if details is not None: - attrs['details'] = details - self._data.append(o) - - def complete_workflow_execution(self, result=None): - """ - Closes the workflow execution and records a WorkflowExecutionCompleted - event in the history - """ - o = {} - o['decisionType'] = 'CompleteWorkflowExecution' - attrs = o['completeWorkflowExecutionDecisionAttributes'] = {} - if result is not None: - attrs['result'] = result - self._data.append(o) - - def fail_workflow_execution(self, reason=None, details=None): - """ - Closes the workflow execution and records a - WorkflowExecutionFailed event in the history. - """ - o = {} - o['decisionType'] = 'FailWorkflowExecution' - attrs = o['failWorkflowExecutionDecisionAttributes'] = {} - if reason is not None: - attrs['reason'] = reason - if details is not None: - attrs['details'] = details - self._data.append(o) - - def cancel_workflow_executions(self, details=None): - """ - Closes the workflow execution and records a WorkflowExecutionCanceled - event in the history. - """ - o = {} - o['decisionType'] = 'CancelWorkflowExecution' - attrs = o['cancelWorkflowExecutionsDecisionAttributes'] = {} - if details is not None: - attrs['details'] = details - self._data.append(o) - - def continue_as_new_workflow_execution(self, - child_policy=None, - execution_start_to_close_timeout=None, - input=None, - tag_list=None, - task_list=None, - start_to_close_timeout=None, - workflow_type_version=None): - """ - Closes the workflow execution and starts a new workflow execution of - the same type using the same workflow id and a unique run Id. A - WorkflowExecutionContinuedAsNew event is recorded in the history. - """ - o = {} - o['decisionType'] = 'ContinueAsNewWorkflowExecution' - attrs = o['continueAsNewWorkflowExecutionDecisionAttributes'] = {} - if child_policy is not None: - attrs['childPolicy'] = child_policy - if execution_start_to_close_timeout is not None: - attrs['executionStartToCloseTimeout'] = execution_start_to_close_timeout - if input is not None: - attrs['input'] = input - if tag_list is not None: - attrs['tagList'] = tag_list - if task_list is not None: - attrs['taskList'] = {'name': task_list} - if start_to_close_timeout is not None: - attrs['taskStartToCloseTimeout'] = start_to_close_timeout - if workflow_type_version is not None: - attrs['workflowTypeVersion'] = workflow_type_version - self._data.append(o) - - def start_timer(self, - start_to_fire_timeout, - timer_id, - control=None): - """ - Starts a timer for this workflow execution and records a TimerStarted - event in the history. This timer will fire after the specified delay - and record a TimerFired event. - """ - o = {} - o['decisionType'] = 'StartTimer' - attrs = o['startTimerDecisionAttributes'] = {} - attrs['startToFireTimeout'] = start_to_fire_timeout - attrs['timerId'] = timer_id - if control is not None: - attrs['control'] = control - self._data.append(o) - - def cancel_timer(self, timer_id): - """ - Cancels a previously started timer and records a TimerCanceled - event in the history. - """ - o = {} - o['decisionType'] = 'CancelTimer' - attrs = o['cancelTimerDecisionAttributes'] = {} - attrs['timerId'] = timer_id - self._data.append(o) - - def signal_external_workflow_execution(self, - workflow_id, - signal_name, - run_id=None, - control=None, - input=None): - """ - Requests a signal to be delivered to the specified external workflow - execution and records a SignalExternalWorkflowExecutionInitiated - event in the history. - """ - o = {} - o['decisionType'] = 'SignalExternalWorkflowExecution' - attrs = o['signalExternalWorkflowExecutionDecisionAttributes'] = {} - attrs['workflowId'] = workflow_id - attrs['signalName'] = signal_name - if run_id is not None: - attrs['runId'] = run_id - if control is not None: - attrs['control'] = control - if input is not None: - attrs['input'] = input - self._data.append(o) - - def request_cancel_external_workflow_execution(self, - workflow_id, - control=None, - run_id=None): - """ - Requests that a request be made to cancel the specified - external workflow execution and records a - RequestCancelExternalWorkflowExecutionInitiated event in the - history. - """ - o = {} - o['decisionType'] = 'RequestCancelExternalWorkflowExecution' - attrs = o['requestCancelExternalWorkflowExecutionDecisionAttributes'] = {} - attrs['workflowId'] = workflow_id - if control is not None: - attrs['control'] = control - if run_id is not None: - attrs['runId'] = run_id - self._data.append(o) - - def start_child_workflow_execution(self, - workflow_type_name, - workflow_type_version, - workflow_id, - child_policy=None, - control=None, - execution_start_to_close_timeout=None, - input=None, - tag_list=None, - task_list=None, - task_start_to_close_timeout=None): - """ - Requests that a child workflow execution be started and - records a StartChildWorkflowExecutionInitiated event in the - history. The child workflow execution is a separate workflow - execution with its own history. - """ - o = {} - o['decisionType'] = 'StartChildWorkflowExecution' - attrs = o['startChildWorkflowExecutionDecisionAttributes'] = {} - attrs['workflowType'] = { - 'name': workflow_type_name, - 'version': workflow_type_version, - } - attrs['workflowId'] = workflow_id - if child_policy is not None: - attrs['childPolicy'] = child_policy - if control is not None: - attrs['control'] = control - if execution_start_to_close_timeout is not None: - attrs['executionStartToCloseTimeout'] = execution_start_to_close_timeout - if input is not None: - attrs['input'] = input - if tag_list is not None: - attrs['tagList'] = tag_list - if task_list is not None: - attrs['taskList'] = {'name': task_list} - if task_start_to_close_timeout is not None: - attrs['taskStartToCloseTimeout'] = task_start_to_close_timeout - self._data.append(o) diff --git a/awx/lib/site-packages/boto/swf/layer2.py b/awx/lib/site-packages/boto/swf/layer2.py deleted file mode 100644 index 5ad1c8d344..0000000000 --- a/awx/lib/site-packages/boto/swf/layer2.py +++ /dev/null @@ -1,344 +0,0 @@ -"""Object-oriented interface to SWF wrapping boto.swf.layer1.Layer1""" - -import time -from functools import wraps -from boto.swf.layer1 import Layer1 -from boto.swf.layer1_decisions import Layer1Decisions - -DEFAULT_CREDENTIALS = { - 'aws_access_key_id': None, - 'aws_secret_access_key': None -} - -def set_default_credentials(aws_access_key_id, aws_secret_access_key): - """Set default credentials.""" - DEFAULT_CREDENTIALS.update({ - 'aws_access_key_id': aws_access_key_id, - 'aws_secret_access_key': aws_secret_access_key, - }) - -class SWFBase(object): - - name = None - domain = None - aws_access_key_id = None - aws_secret_access_key = None - region = None - - def __init__(self, **kwargs): - # Set default credentials. - for credkey in ('aws_access_key_id', 'aws_secret_access_key'): - if DEFAULT_CREDENTIALS.get(credkey): - setattr(self, credkey, DEFAULT_CREDENTIALS[credkey]) - # Override attributes with keyword args. - for kwarg in kwargs: - setattr(self, kwarg, kwargs[kwarg]) - - self._swf = Layer1(self.aws_access_key_id, - self.aws_secret_access_key, - region=self.region) - - def __repr__(self): - rep_str = str(self.name) - if hasattr(self, 'version'): - rep_str += '-' + str(getattr(self, 'version')) - return '<%s %r at 0x%x>' % (self.__class__.__name__, rep_str, id(self)) - -class Domain(SWFBase): - - """Simple Workflow Domain.""" - - description = None - retention = 30 - @wraps(Layer1.describe_domain) - def describe(self): - """DescribeDomain.""" - return self._swf.describe_domain(self.name) - - @wraps(Layer1.deprecate_domain) - def deprecate(self): - """DeprecateDomain""" - self._swf.deprecate_domain(self.name) - - @wraps(Layer1.register_domain) - def register(self): - """RegisterDomain.""" - self._swf.register_domain(self.name, str(self.retention), - self.description) - - @wraps(Layer1.list_activity_types) - def activities(self, status='REGISTERED', **kwargs): - """ListActivityTypes.""" - act_types = self._swf.list_activity_types(self.name, status, **kwargs) - act_objects = [] - for act_args in act_types['typeInfos']: - act_ident = act_args['activityType'] - del act_args['activityType'] - act_args.update(act_ident) - act_args.update({ - 'aws_access_key_id': self.aws_access_key_id, - 'aws_secret_access_key': self.aws_secret_access_key, - 'domain': self.name, - }) - act_objects.append(ActivityType(**act_args)) - return act_objects - - @wraps(Layer1.list_workflow_types) - def workflows(self, status='REGISTERED', **kwargs): - """ListWorkflowTypes.""" - wf_types = self._swf.list_workflow_types(self.name, status, **kwargs) - wf_objects = [] - for wf_args in wf_types['typeInfos']: - wf_ident = wf_args['workflowType'] - del wf_args['workflowType'] - wf_args.update(wf_ident) - wf_args.update({ - 'aws_access_key_id': self.aws_access_key_id, - 'aws_secret_access_key': self.aws_secret_access_key, - 'domain': self.name, - }) - - wf_objects.append(WorkflowType(**wf_args)) - return wf_objects - - def executions(self, closed=False, **kwargs): - """List list open/closed executions. - - For a full list of available parameters refer to - :py:func:`boto.swf.layer1.Layer1.list_closed_workflow_executions` and - :py:func:`boto.swf.layer1.Layer1.list_open_workflow_executions` - """ - if closed: - executions = self._swf.list_closed_workflow_executions(self.name, - **kwargs) - else: - if 'oldest_date' not in kwargs: - # Last 24 hours. - kwargs['oldest_date'] = time.time() - (3600 * 24) - executions = self._swf.list_open_workflow_executions(self.name, - **kwargs) - exe_objects = [] - for exe_args in executions['executionInfos']: - for nested_key in ('execution', 'workflowType'): - nested_dict = exe_args[nested_key] - del exe_args[nested_key] - exe_args.update(nested_dict) - - exe_args.update({ - 'aws_access_key_id': self.aws_access_key_id, - 'aws_secret_access_key': self.aws_secret_access_key, - 'domain': self.name, - }) - - exe_objects.append(WorkflowExecution(**exe_args)) - return exe_objects - - @wraps(Layer1.count_pending_activity_tasks) - def count_pending_activity_tasks(self, task_list): - """CountPendingActivityTasks.""" - return self._swf.count_pending_activity_tasks(self.name, task_list) - - @wraps(Layer1.count_pending_decision_tasks) - def count_pending_decision_tasks(self, task_list): - """CountPendingDecisionTasks.""" - return self._swf.count_pending_decision_tasks(self.name, task_list) - - -class Actor(SWFBase): - - task_list = None - last_tasktoken = None - domain = None - - def run(self): - """To be overloaded by subclasses.""" - raise NotImplementedError() - -class ActivityWorker(Actor): - - """Base class for SimpleWorkflow activity workers.""" - - @wraps(Layer1.respond_activity_task_canceled) - def cancel(self, task_token=None, details=None): - """RespondActivityTaskCanceled.""" - if task_token is None: - task_token = self.last_tasktoken - return self._swf.respond_activity_task_canceled(task_token, details) - - @wraps(Layer1.respond_activity_task_completed) - def complete(self, task_token=None, result=None): - """RespondActivityTaskCompleted.""" - if task_token is None: - task_token = self.last_tasktoken - return self._swf.respond_activity_task_completed(task_token, result) - - @wraps(Layer1.respond_activity_task_failed) - def fail(self, task_token=None, details=None, reason=None): - """RespondActivityTaskFailed.""" - if task_token is None: - task_token = self.last_tasktoken - return self._swf.respond_activity_task_failed(task_token, details, - reason) - - @wraps(Layer1.record_activity_task_heartbeat) - def heartbeat(self, task_token=None, details=None): - """RecordActivityTaskHeartbeat.""" - if task_token is None: - task_token = self.last_tasktoken - return self._swf.record_activity_task_heartbeat(task_token, details) - - @wraps(Layer1.poll_for_activity_task) - def poll(self, **kwargs): - """PollForActivityTask.""" - task_list = self.task_list - if 'task_list' in kwargs: - task_list = kwargs.get('task_list') - del kwargs['task_list'] - task = self._swf.poll_for_activity_task(self.domain, task_list, - **kwargs) - self.last_tasktoken = task.get('taskToken') - return task - -class Decider(Actor): - - """Base class for SimpleWorkflow deciders.""" - - @wraps(Layer1.respond_decision_task_completed) - def complete(self, task_token=None, decisions=None, **kwargs): - """RespondDecisionTaskCompleted.""" - if isinstance(decisions, Layer1Decisions): - # Extract decision list from a Layer1Decisions instance. - decisions = decisions._data - if task_token is None: - task_token = self.last_tasktoken - return self._swf.respond_decision_task_completed(task_token, decisions, - **kwargs) - - @wraps(Layer1.poll_for_decision_task) - def poll(self, **kwargs): - """PollForDecisionTask.""" - task_list = self.task_list - if 'task_list' in kwargs: - task_list = kwargs.get('task_list') - del kwargs['task_list'] - decision_task = self._swf.poll_for_decision_task(self.domain, task_list, - **kwargs) - self.last_tasktoken = decision_task.get('taskToken') - return decision_task - -class WorkflowType(SWFBase): - - """A versioned workflow type.""" - - version = None - task_list = None - child_policy = 'TERMINATE' - - @wraps(Layer1.describe_workflow_type) - def describe(self): - """DescribeWorkflowType.""" - return self._swf.describe_workflow_type(self.domain, self.name, - self.version) - @wraps(Layer1.register_workflow_type) - def register(self, **kwargs): - """RegisterWorkflowType.""" - args = { - 'default_execution_start_to_close_timeout': '3600', - 'default_task_start_to_close_timeout': '300', - 'default_child_policy': 'TERMINATE', - } - args.update(kwargs) - self._swf.register_workflow_type(self.domain, self.name, self.version, - **args) - - @wraps(Layer1.deprecate_workflow_type) - def deprecate(self): - """DeprecateWorkflowType.""" - self._swf.deprecate_workflow_type(self.domain, self.name, self.version) - - @wraps(Layer1.start_workflow_execution) - def start(self, **kwargs): - """StartWorkflowExecution.""" - if 'workflow_id' in kwargs: - workflow_id = kwargs['workflow_id'] - del kwargs['workflow_id'] - else: - workflow_id = '%s-%s-%i' % (self.name, self.version, time.time()) - - for def_attr in ('task_list', 'child_policy'): - kwargs[def_attr] = kwargs.get(def_attr, getattr(self, def_attr)) - run_id = self._swf.start_workflow_execution(self.domain, workflow_id, - self.name, self.version, **kwargs)['runId'] - return WorkflowExecution(name=self.name, version=self.version, - runId=run_id, domain=self.domain, workflowId=workflow_id, - aws_access_key_id=self.aws_access_key_id, - aws_secret_access_key=self.aws_secret_access_key) - -class WorkflowExecution(SWFBase): - - """An instance of a workflow.""" - - workflowId = None - runId = None - - @wraps(Layer1.signal_workflow_execution) - def signal(self, signame, **kwargs): - """SignalWorkflowExecution.""" - self._swf.signal_workflow_execution(self.domain, signame, - self.workflowId, **kwargs) - - @wraps(Layer1.terminate_workflow_execution) - def terminate(self, **kwargs): - """TerminateWorkflowExecution (p. 103).""" - return self._swf.terminate_workflow_execution(self.domain, - self.workflowId, **kwargs) - - @wraps(Layer1.get_workflow_execution_history) - def history(self, **kwargs): - """GetWorkflowExecutionHistory.""" - return self._swf.get_workflow_execution_history(self.domain, self.runId, - self.workflowId, **kwargs)['events'] - - @wraps(Layer1.describe_workflow_execution) - def describe(self): - """DescribeWorkflowExecution.""" - return self._swf.describe_workflow_execution(self.domain, self.runId, - self.workflowId) - - @wraps(Layer1.request_cancel_workflow_execution) - def request_cancel(self): - """RequestCancelWorkflowExecution.""" - return self._swf.request_cancel_workflow_execution(self.domain, - self.workflowId, self.runId) - - -class ActivityType(SWFBase): - - """A versioned activity type.""" - - version = None - - @wraps(Layer1.deprecate_activity_type) - def deprecate(self): - """DeprecateActivityType.""" - return self._swf.deprecate_activity_type(self.domain, self.name, - self.version) - - @wraps(Layer1.describe_activity_type) - def describe(self): - """DescribeActivityType.""" - return self._swf.describe_activity_type(self.domain, self.name, - self.version) - - @wraps(Layer1.register_activity_type) - def register(self, **kwargs): - """RegisterActivityType.""" - args = { - 'default_task_heartbeat_timeout': '600', - 'default_task_schedule_to_close_timeout': '3900', - 'default_task_schedule_to_start_timeout': '300', - 'default_task_start_to_close_timeout': '3600', - } - args.update(kwargs) - self._swf.register_activity_type(self.domain, self.name, self.version, - **args) diff --git a/awx/lib/site-packages/boto/utils.py b/awx/lib/site-packages/boto/utils.py deleted file mode 100644 index 0e7e3a79f3..0000000000 --- a/awx/lib/site-packages/boto/utils.py +++ /dev/null @@ -1,1051 +0,0 @@ -# Copyright (c) 2006-2012 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# Copyright (c) 2012 Amazon.com, Inc. or its affiliates. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# -# Parts of this code were copied or derived from sample code supplied by AWS. -# The following notice applies to that code. -# -# This software code is made available "AS IS" without warranties of any -# kind. You may copy, display, modify and redistribute the software -# code either by itself or as incorporated into your code; provided that -# you do not remove any proprietary notices. Your use of this software -# code is at your own risk and you waive any claim against Amazon -# Digital Services, Inc. or its affiliates with respect to your use of -# this software code. (c) 2006 Amazon Digital Services, Inc. or its -# affiliates. - -""" -Some handy utility functions used by several classes. -""" - -import subprocess -import time -import logging.handlers -import boto -import boto.provider -import tempfile -import random -import smtplib -import datetime -import re -import email.mime.multipart -import email.mime.base -import email.mime.text -import email.utils -import email.encoders -import gzip -import threading -import locale -from boto.compat import six, StringIO, urllib, encodebytes - -from contextlib import contextmanager - -from hashlib import md5, sha512 -_hashfn = sha512 - -from boto.compat import json - -try: - from boto.compat.json import JSONDecodeError -except ImportError: - JSONDecodeError = ValueError - -# List of Query String Arguments of Interest -qsa_of_interest = ['acl', 'cors', 'defaultObjectAcl', 'location', 'logging', - 'partNumber', 'policy', 'requestPayment', 'torrent', - 'versioning', 'versionId', 'versions', 'website', - 'uploads', 'uploadId', 'response-content-type', - 'response-content-language', 'response-expires', - 'response-cache-control', 'response-content-disposition', - 'response-content-encoding', 'delete', 'lifecycle', - 'tagging', 'restore', - # storageClass is a QSA for buckets in Google Cloud Storage. - # (StorageClass is associated to individual keys in S3, but - # having it listed here should cause no problems because - # GET bucket?storageClass is not part of the S3 API.) - 'storageClass', - # websiteConfig is a QSA for buckets in Google Cloud - # Storage. - 'websiteConfig', - # compose is a QSA for objects in Google Cloud Storage. - 'compose'] - - -_first_cap_regex = re.compile('(.)([A-Z][a-z]+)') -_number_cap_regex = re.compile('([a-z])([0-9]+)') -_end_cap_regex = re.compile('([a-z0-9])([A-Z])') - - -def unquote_v(nv): - if len(nv) == 1: - return nv - else: - return (nv[0], urllib.parse.unquote(nv[1])) - - -def canonical_string(method, path, headers, expires=None, - provider=None): - """ - Generates the aws canonical string for the given parameters - """ - if not provider: - provider = boto.provider.get_default() - interesting_headers = {} - for key in headers: - lk = key.lower() - if headers[key] is not None and \ - (lk in ['content-md5', 'content-type', 'date'] or - lk.startswith(provider.header_prefix)): - interesting_headers[lk] = str(headers[key]).strip() - - # these keys get empty strings if they don't exist - if 'content-type' not in interesting_headers: - interesting_headers['content-type'] = '' - if 'content-md5' not in interesting_headers: - interesting_headers['content-md5'] = '' - - # just in case someone used this. it's not necessary in this lib. - if provider.date_header in interesting_headers: - interesting_headers['date'] = '' - - # if you're using expires for query string auth, then it trumps date - # (and provider.date_header) - if expires: - interesting_headers['date'] = str(expires) - - sorted_header_keys = sorted(interesting_headers.keys()) - - buf = "%s\n" % method - for key in sorted_header_keys: - val = interesting_headers[key] - if key.startswith(provider.header_prefix): - buf += "%s:%s\n" % (key, val) - else: - buf += "%s\n" % val - - # don't include anything after the first ? in the resource... - # unless it is one of the QSA of interest, defined above - t = path.split('?') - buf += t[0] - - if len(t) > 1: - qsa = t[1].split('&') - qsa = [a.split('=', 1) for a in qsa] - qsa = [unquote_v(a) for a in qsa if a[0] in qsa_of_interest] - if len(qsa) > 0: - qsa.sort(key=lambda x: x[0]) - qsa = ['='.join(a) for a in qsa] - buf += '?' - buf += '&'.join(qsa) - - return buf - - -def merge_meta(headers, metadata, provider=None): - if not provider: - provider = boto.provider.get_default() - metadata_prefix = provider.metadata_prefix - final_headers = headers.copy() - for k in metadata.keys(): - if k.lower() in boto.s3.key.Key.base_user_settable_fields: - final_headers[k] = metadata[k] - else: - final_headers[metadata_prefix + k] = metadata[k] - - return final_headers - - -def get_aws_metadata(headers, provider=None): - if not provider: - provider = boto.provider.get_default() - metadata_prefix = provider.metadata_prefix - metadata = {} - for hkey in headers.keys(): - if hkey.lower().startswith(metadata_prefix): - val = urllib.parse.unquote(headers[hkey]) - if isinstance(val, bytes): - try: - val = val.decode('utf-8') - except UnicodeDecodeError: - # Just leave the value as-is - pass - metadata[hkey[len(metadata_prefix):]] = val - del headers[hkey] - return metadata - - -def retry_url(url, retry_on_404=True, num_retries=10, timeout=None): - """ - Retry a url. This is specifically used for accessing the metadata - service on an instance. Since this address should never be proxied - (for security reasons), we create a ProxyHandler with a NULL - dictionary to override any proxy settings in the environment. - """ - for i in range(0, num_retries): - try: - proxy_handler = urllib.request.ProxyHandler({}) - opener = urllib.request.build_opener(proxy_handler) - req = urllib.request.Request(url) - r = opener.open(req, timeout=timeout) - result = r.read() - - if(not isinstance(result, six.string_types) and - hasattr(result, 'decode')): - result = result.decode('utf-8') - - return result - except urllib.error.HTTPError as e: - code = e.getcode() - if code == 404 and not retry_on_404: - return '' - except Exception as e: - pass - boto.log.exception('Caught exception reading instance data') - # If not on the last iteration of the loop then sleep. - if i + 1 != num_retries: - time.sleep(min(2 ** i, - boto.config.get('Boto', 'max_retry_delay', 60))) - boto.log.error('Unable to read instance data, giving up') - return '' - - -def _get_instance_metadata(url, num_retries, timeout=None): - return LazyLoadMetadata(url, num_retries, timeout) - - -class LazyLoadMetadata(dict): - def __init__(self, url, num_retries, timeout=None): - self._url = url - self._num_retries = num_retries - self._leaves = {} - self._dicts = [] - self._timeout = timeout - data = boto.utils.retry_url(self._url, num_retries=self._num_retries, timeout=self._timeout) - if data: - fields = data.split('\n') - for field in fields: - if field.endswith('/'): - key = field[0:-1] - self._dicts.append(key) - else: - p = field.find('=') - if p > 0: - key = field[p + 1:] - resource = field[0:p] + '/openssh-key' - else: - key = resource = field - self._leaves[key] = resource - self[key] = None - - def _materialize(self): - for key in self: - self[key] - - def __getitem__(self, key): - if key not in self: - # allow dict to throw the KeyError - return super(LazyLoadMetadata, self).__getitem__(key) - - # already loaded - val = super(LazyLoadMetadata, self).__getitem__(key) - if val is not None: - return val - - if key in self._leaves: - resource = self._leaves[key] - last_exception = None - - for i in range(0, self._num_retries): - try: - val = boto.utils.retry_url( - self._url + urllib.parse.quote(resource, - safe="/:"), - num_retries=self._num_retries, - timeout=self._timeout) - if val and val[0] == '{': - val = json.loads(val) - break - else: - p = val.find('\n') - if p > 0: - val = val.split('\n') - break - - except JSONDecodeError as e: - boto.log.debug( - "encountered '%s' exception: %s" % ( - e.__class__.__name__, e)) - boto.log.debug( - 'corrupted JSON data found: %s' % val) - last_exception = e - - except Exception as e: - boto.log.debug("encountered unretryable" + - " '%s' exception, re-raising" % ( - e.__class__.__name__)) - last_exception = e - raise - - boto.log.error("Caught exception reading meta data" + - " for the '%s' try" % (i + 1)) - - if i + 1 != self._num_retries: - next_sleep = min( - random.random() * 2 ** i, - boto.config.get('Boto', 'max_retry_delay', 60)) - time.sleep(next_sleep) - else: - boto.log.error('Unable to read meta data, giving up') - boto.log.error( - "encountered '%s' exception: %s" % ( - last_exception.__class__.__name__, last_exception)) - raise last_exception - - self[key] = val - elif key in self._dicts: - self[key] = LazyLoadMetadata(self._url + key + '/', - self._num_retries) - - return super(LazyLoadMetadata, self).__getitem__(key) - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - - def values(self): - self._materialize() - return super(LazyLoadMetadata, self).values() - - def items(self): - self._materialize() - return super(LazyLoadMetadata, self).items() - - def __str__(self): - self._materialize() - return super(LazyLoadMetadata, self).__str__() - - def __repr__(self): - self._materialize() - return super(LazyLoadMetadata, self).__repr__() - - -def _build_instance_metadata_url(url, version, path): - """ - Builds an EC2 metadata URL for fetching information about an instance. - - Example: - - >>> _build_instance_metadata_url('http://169.254.169.254', 'latest', 'meta-data/') - http://169.254.169.254/latest/meta-data/ - - :type url: string - :param url: URL to metadata service, e.g. 'http://169.254.169.254' - - :type version: string - :param version: Version of the metadata to get, e.g. 'latest' - - :type path: string - :param path: Path of the metadata to get, e.g. 'meta-data/'. If a trailing - slash is required it must be passed in with the path. - - :return: The full metadata URL - """ - return '%s/%s/%s' % (url, version, path) - - -def get_instance_metadata(version='latest', url='http://169.254.169.254', - data='meta-data/', timeout=None, num_retries=5): - """ - Returns the instance metadata as a nested Python dictionary. - Simple values (e.g. local_hostname, hostname, etc.) will be - stored as string values. Values such as ancestor-ami-ids will - be stored in the dict as a list of string values. More complex - fields such as public-keys and will be stored as nested dicts. - - If the timeout is specified, the connection to the specified url - will time out after the specified number of seconds. - - """ - try: - metadata_url = _build_instance_metadata_url(url, version, data) - return _get_instance_metadata(metadata_url, num_retries=num_retries, timeout=timeout) - except urllib.error.URLError: - return None - - -def get_instance_identity(version='latest', url='http://169.254.169.254', - timeout=None, num_retries=5): - """ - Returns the instance identity as a nested Python dictionary. - """ - iid = {} - base_url = _build_instance_metadata_url(url, version, - 'dynamic/instance-identity/') - try: - data = retry_url(base_url, num_retries=num_retries, timeout=timeout) - fields = data.split('\n') - for field in fields: - val = retry_url(base_url + '/' + field + '/', num_retries=num_retries, timeout=timeout) - if val[0] == '{': - val = json.loads(val) - if field: - iid[field] = val - return iid - except urllib.error.URLError: - return None - - -def get_instance_userdata(version='latest', sep=None, - url='http://169.254.169.254', timeout=None, num_retries=5): - ud_url = _build_instance_metadata_url(url, version, 'user-data') - user_data = retry_url(ud_url, retry_on_404=False, num_retries=num_retries, timeout=timeout) - if user_data: - if sep: - l = user_data.split(sep) - user_data = {} - for nvpair in l: - t = nvpair.split('=') - user_data[t[0].strip()] = t[1].strip() - return user_data - -ISO8601 = '%Y-%m-%dT%H:%M:%SZ' -ISO8601_MS = '%Y-%m-%dT%H:%M:%S.%fZ' -RFC1123 = '%a, %d %b %Y %H:%M:%S %Z' -LOCALE_LOCK = threading.Lock() - - -@contextmanager -def setlocale(name): - """ - A context manager to set the locale in a threadsafe manner. - """ - with LOCALE_LOCK: - saved = locale.setlocale(locale.LC_ALL) - - try: - yield locale.setlocale(locale.LC_ALL, name) - finally: - locale.setlocale(locale.LC_ALL, saved) - - -def get_ts(ts=None): - if not ts: - ts = time.gmtime() - return time.strftime(ISO8601, ts) - - -def parse_ts(ts): - with setlocale('C'): - ts = ts.strip() - try: - dt = datetime.datetime.strptime(ts, ISO8601) - return dt - except ValueError: - try: - dt = datetime.datetime.strptime(ts, ISO8601_MS) - return dt - except ValueError: - dt = datetime.datetime.strptime(ts, RFC1123) - return dt - - -def find_class(module_name, class_name=None): - if class_name: - module_name = "%s.%s" % (module_name, class_name) - modules = module_name.split('.') - c = None - - try: - for m in modules[1:]: - if c: - c = getattr(c, m) - else: - c = getattr(__import__(".".join(modules[0:-1])), m) - return c - except: - return None - - -def update_dme(username, password, dme_id, ip_address): - """ - Update your Dynamic DNS record with DNSMadeEasy.com - """ - dme_url = 'https://www.dnsmadeeasy.com/servlet/updateip' - dme_url += '?username=%s&password=%s&id=%s&ip=%s' - s = urllib.request.urlopen(dme_url % (username, password, dme_id, ip_address)) - return s.read() - - -def fetch_file(uri, file=None, username=None, password=None): - """ - Fetch a file based on the URI provided. - If you do not pass in a file pointer a tempfile.NamedTemporaryFile, - or None if the file could not be retrieved is returned. - The URI can be either an HTTP url, or "s3://bucket_name/key_name" - """ - boto.log.info('Fetching %s' % uri) - if file is None: - file = tempfile.NamedTemporaryFile() - try: - if uri.startswith('s3://'): - bucket_name, key_name = uri[len('s3://'):].split('/', 1) - c = boto.connect_s3(aws_access_key_id=username, - aws_secret_access_key=password) - bucket = c.get_bucket(bucket_name) - key = bucket.get_key(key_name) - key.get_contents_to_file(file) - else: - if username and password: - passman = urllib.request.HTTPPasswordMgrWithDefaultRealm() - passman.add_password(None, uri, username, password) - authhandler = urllib.request.HTTPBasicAuthHandler(passman) - opener = urllib.request.build_opener(authhandler) - urllib.request.install_opener(opener) - s = urllib.request.urlopen(uri) - file.write(s.read()) - file.seek(0) - except: - raise - boto.log.exception('Problem Retrieving file: %s' % uri) - file = None - return file - - -class ShellCommand(object): - - def __init__(self, command, wait=True, fail_fast=False, cwd=None): - self.exit_code = 0 - self.command = command - self.log_fp = StringIO() - self.wait = wait - self.fail_fast = fail_fast - self.run(cwd=cwd) - - def run(self, cwd=None): - boto.log.info('running:%s' % self.command) - self.process = subprocess.Popen(self.command, shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=cwd) - if(self.wait): - while self.process.poll() is None: - time.sleep(1) - t = self.process.communicate() - self.log_fp.write(t[0]) - self.log_fp.write(t[1]) - boto.log.info(self.log_fp.getvalue()) - self.exit_code = self.process.returncode - - if self.fail_fast and self.exit_code != 0: - raise Exception("Command " + self.command + - " failed with status " + self.exit_code) - - return self.exit_code - - def setReadOnly(self, value): - raise AttributeError - - def getStatus(self): - return self.exit_code - - status = property(getStatus, setReadOnly, None, - 'The exit code for the command') - - def getOutput(self): - return self.log_fp.getvalue() - - output = property(getOutput, setReadOnly, None, - 'The STDIN and STDERR output of the command') - - -class AuthSMTPHandler(logging.handlers.SMTPHandler): - """ - This class extends the SMTPHandler in the standard Python logging module - to accept a username and password on the constructor and to then use those - credentials to authenticate with the SMTP server. To use this, you could - add something like this in your boto config file: - - [handler_hand07] - class=boto.utils.AuthSMTPHandler - level=WARN - formatter=form07 - args=('localhost', 'username', 'password', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject') - """ - - def __init__(self, mailhost, username, password, - fromaddr, toaddrs, subject): - """ - Initialize the handler. - - We have extended the constructor to accept a username/password - for SMTP authentication. - """ - super(AuthSMTPHandler, self).__init__(mailhost, fromaddr, - toaddrs, subject) - self.username = username - self.password = password - - def emit(self, record): - """ - Emit a record. - - Format the record and send it to the specified addressees. - It would be really nice if I could add authorization to this class - without having to resort to cut and paste inheritance but, no. - """ - try: - port = self.mailport - if not port: - port = smtplib.SMTP_PORT - smtp = smtplib.SMTP(self.mailhost, port) - smtp.login(self.username, self.password) - msg = self.format(record) - msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % ( - self.fromaddr, - ','.join(self.toaddrs), - self.getSubject(record), - email.utils.formatdate(), msg) - smtp.sendmail(self.fromaddr, self.toaddrs, msg) - smtp.quit() - except (KeyboardInterrupt, SystemExit): - raise - except: - self.handleError(record) - - -class LRUCache(dict): - """A dictionary-like object that stores only a certain number of items, and - discards its least recently used item when full. - - >>> cache = LRUCache(3) - >>> cache['A'] = 0 - >>> cache['B'] = 1 - >>> cache['C'] = 2 - >>> len(cache) - 3 - - >>> cache['A'] - 0 - - Adding new items to the cache does not increase its size. Instead, the least - recently used item is dropped: - - >>> cache['D'] = 3 - >>> len(cache) - 3 - >>> 'B' in cache - False - - Iterating over the cache returns the keys, starting with the most recently - used: - - >>> for key in cache: - ... print key - D - A - C - - This code is based on the LRUCache class from Genshi which is based on - `Myghty <http://www.myghty.org>`_'s LRUCache from ``myghtyutils.util``, - written by Mike Bayer and released under the MIT license (Genshi uses the - BSD License). - """ - - class _Item(object): - def __init__(self, key, value): - self.previous = self.next = None - self.key = key - self.value = value - - def __repr__(self): - return repr(self.value) - - def __init__(self, capacity): - self._dict = dict() - self.capacity = capacity - self.head = None - self.tail = None - - def __contains__(self, key): - return key in self._dict - - def __iter__(self): - cur = self.head - while cur: - yield cur.key - cur = cur.next - - def __len__(self): - return len(self._dict) - - def __getitem__(self, key): - item = self._dict[key] - self._update_item(item) - return item.value - - def __setitem__(self, key, value): - item = self._dict.get(key) - if item is None: - item = self._Item(key, value) - self._dict[key] = item - self._insert_item(item) - else: - item.value = value - self._update_item(item) - self._manage_size() - - def __repr__(self): - return repr(self._dict) - - def _insert_item(self, item): - item.previous = None - item.next = self.head - if self.head is not None: - self.head.previous = item - else: - self.tail = item - self.head = item - self._manage_size() - - def _manage_size(self): - while len(self._dict) > self.capacity: - del self._dict[self.tail.key] - if self.tail != self.head: - self.tail = self.tail.previous - self.tail.next = None - else: - self.head = self.tail = None - - def _update_item(self, item): - if self.head == item: - return - - previous = item.previous - previous.next = item.next - if item.next is not None: - item.next.previous = previous - else: - self.tail = previous - - item.previous = None - item.next = self.head - self.head.previous = self.head = item - - -class Password(object): - """ - Password object that stores itself as hashed. - Hash defaults to SHA512 if available, MD5 otherwise. - """ - hashfunc = _hashfn - - def __init__(self, str=None, hashfunc=None): - """ - Load the string from an initial value, this should be the - raw hashed password. - """ - self.str = str - if hashfunc: - self.hashfunc = hashfunc - - def set(self, value): - if not isinstance(value, bytes): - value = value.encode('utf-8') - self.str = self.hashfunc(value).hexdigest() - - def __str__(self): - return str(self.str) - - def __eq__(self, other): - if other is None: - return False - if not isinstance(other, bytes): - other = other.encode('utf-8') - return str(self.hashfunc(other).hexdigest()) == str(self.str) - - def __len__(self): - if self.str: - return len(self.str) - else: - return 0 - - -def notify(subject, body=None, html_body=None, to_string=None, - attachments=None, append_instance_id=True): - attachments = attachments or [] - if append_instance_id: - subject = "[%s] %s" % ( - boto.config.get_value("Instance", "instance-id"), subject) - if not to_string: - to_string = boto.config.get_value('Notification', 'smtp_to', None) - if to_string: - try: - from_string = boto.config.get_value('Notification', - 'smtp_from', 'boto') - msg = email.mime.multipart.MIMEMultipart() - msg['From'] = from_string - msg['Reply-To'] = from_string - msg['To'] = to_string - msg['Date'] = email.utils.formatdate(localtime=True) - msg['Subject'] = subject - - if body: - msg.attach(email.mime.text.MIMEText(body)) - - if html_body: - part = email.mime.base.MIMEBase('text', 'html') - part.set_payload(html_body) - email.encoders.encode_base64(part) - msg.attach(part) - - for part in attachments: - msg.attach(part) - - smtp_host = boto.config.get_value('Notification', - 'smtp_host', 'localhost') - - # Alternate port support - if boto.config.get_value("Notification", "smtp_port"): - server = smtplib.SMTP(smtp_host, int( - boto.config.get_value("Notification", "smtp_port"))) - else: - server = smtplib.SMTP(smtp_host) - - # TLS support - if boto.config.getbool("Notification", "smtp_tls"): - server.ehlo() - server.starttls() - server.ehlo() - smtp_user = boto.config.get_value('Notification', 'smtp_user', '') - smtp_pass = boto.config.get_value('Notification', 'smtp_pass', '') - if smtp_user: - server.login(smtp_user, smtp_pass) - server.sendmail(from_string, to_string, msg.as_string()) - server.quit() - except: - boto.log.exception('notify failed') - - -def get_utf8_value(value): - if not six.PY2 and isinstance(value, bytes): - return value - - if not isinstance(value, six.string_types): - value = six.text_type(value) - - if isinstance(value, six.text_type): - value = value.encode('utf-8') - - return value - - -def mklist(value): - if not isinstance(value, list): - if isinstance(value, tuple): - value = list(value) - else: - value = [value] - return value - - -def pythonize_name(name): - """Convert camel case to a "pythonic" name. - - Examples:: - - pythonize_name('CamelCase') -> 'camel_case' - pythonize_name('already_pythonized') -> 'already_pythonized' - pythonize_name('HTTPRequest') -> 'http_request' - pythonize_name('HTTPStatus200Ok') -> 'http_status_200_ok' - pythonize_name('UPPER') -> 'upper' - pythonize_name('') -> '' - - """ - s1 = _first_cap_regex.sub(r'\1_\2', name) - s2 = _number_cap_regex.sub(r'\1_\2', s1) - return _end_cap_regex.sub(r'\1_\2', s2).lower() - - -def write_mime_multipart(content, compress=False, deftype='text/plain', delimiter=':'): - """Description: - :param content: A list of tuples of name-content pairs. This is used - instead of a dict to ensure that scripts run in order - :type list of tuples: - - :param compress: Use gzip to compress the scripts, defaults to no compression - :type bool: - - :param deftype: The type that should be assumed if nothing else can be figured out - :type str: - - :param delimiter: mime delimiter - :type str: - - :return: Final mime multipart - :rtype: str: - """ - wrapper = email.mime.multipart.MIMEMultipart() - for name, con in content: - definite_type = guess_mime_type(con, deftype) - maintype, subtype = definite_type.split('/', 1) - if maintype == 'text': - mime_con = email.mime.text.MIMEText(con, _subtype=subtype) - else: - mime_con = email.mime.base.MIMEBase(maintype, subtype) - mime_con.set_payload(con) - # Encode the payload using Base64 - email.encoders.encode_base64(mime_con) - mime_con.add_header('Content-Disposition', 'attachment', filename=name) - wrapper.attach(mime_con) - rcontent = wrapper.as_string() - - if compress: - buf = StringIO() - gz = gzip.GzipFile(mode='wb', fileobj=buf) - try: - gz.write(rcontent) - finally: - gz.close() - rcontent = buf.getvalue() - - return rcontent - - -def guess_mime_type(content, deftype): - """Description: Guess the mime type of a block of text - :param content: content we're finding the type of - :type str: - - :param deftype: Default mime type - :type str: - - :rtype: <type>: - :return: <description> - """ - # Mappings recognized by cloudinit - starts_with_mappings = { - '#include': 'text/x-include-url', - '#!': 'text/x-shellscript', - '#cloud-config': 'text/cloud-config', - '#upstart-job': 'text/upstart-job', - '#part-handler': 'text/part-handler', - '#cloud-boothook': 'text/cloud-boothook' - } - rtype = deftype - for possible_type, mimetype in starts_with_mappings.items(): - if content.startswith(possible_type): - rtype = mimetype - break - return(rtype) - - -def compute_md5(fp, buf_size=8192, size=None): - """ - Compute MD5 hash on passed file and return results in a tuple of values. - - :type fp: file - :param fp: File pointer to the file to MD5 hash. The file pointer - will be reset to its current location before the - method returns. - - :type buf_size: integer - :param buf_size: Number of bytes per read request. - - :type size: int - :param size: (optional) The Maximum number of bytes to read from - the file pointer (fp). This is useful when uploading - a file in multiple parts where the file is being - split inplace into different parts. Less bytes may - be available. - - :rtype: tuple - :return: A tuple containing the hex digest version of the MD5 hash - as the first element, the base64 encoded version of the - plain digest as the second element and the data size as - the third element. - """ - return compute_hash(fp, buf_size, size, hash_algorithm=md5) - - -def compute_hash(fp, buf_size=8192, size=None, hash_algorithm=md5): - hash_obj = hash_algorithm() - spos = fp.tell() - if size and size < buf_size: - s = fp.read(size) - else: - s = fp.read(buf_size) - while s: - if not isinstance(s, bytes): - s = s.encode('utf-8') - hash_obj.update(s) - if size: - size -= len(s) - if size <= 0: - break - if size and size < buf_size: - s = fp.read(size) - else: - s = fp.read(buf_size) - hex_digest = hash_obj.hexdigest() - base64_digest = encodebytes(hash_obj.digest()).decode('utf-8') - if base64_digest[-1] == '\n': - base64_digest = base64_digest[0:-1] - # data_size based on bytes read. - data_size = fp.tell() - spos - fp.seek(spos) - return (hex_digest, base64_digest, data_size) - - -def find_matching_headers(name, headers): - """ - Takes a specific header name and a dict of headers {"name": "value"}. - Returns a list of matching header names, case-insensitive. - - """ - return [h for h in headers if h.lower() == name.lower()] - - -def merge_headers_by_name(name, headers): - """ - Takes a specific header name and a dict of headers {"name": "value"}. - Returns a string of all header values, comma-separated, that match the - input header name, case-insensitive. - - """ - matching_headers = find_matching_headers(name, headers) - return ','.join(str(headers[h]) for h in matching_headers - if headers[h] is not None) - - -class RequestHook(object): - """ - This can be extended and supplied to the connection object - to gain access to request and response object after the request completes. - One use for this would be to implement some specific request logging. - """ - def handle_request_data(self, request, response, error=False): - pass diff --git a/awx/lib/site-packages/boto/vendored/__init__.py b/awx/lib/site-packages/boto/vendored/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/boto/vendored/six.py b/awx/lib/site-packages/boto/vendored/six.py deleted file mode 100644 index 55f5c3bfe3..0000000000 --- a/awx/lib/site-packages/boto/vendored/six.py +++ /dev/null @@ -1,756 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2014 Benjamin Peterson -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import functools -import operator -import sys -import types - -__author__ = "Benjamin Peterson <benjamin@python.org>" -__version__ = "1.7.2" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) # Invokes __set__. - # This is a bit ugly, but it avoids running this again. - delattr(obj.__class__, self.name) - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - def __getattr__(self, attr): - _module = self._resolve() - value = getattr(_module, attr) - setattr(self, attr, value) - return value - - -class _LazyModule(types.ModuleType): - - def __init__(self, name): - super(_LazyModule, self).__init__(name) - self.__doc__ = self.__class__.__doc__ - - def __dir__(self): - attrs = ["__doc__", "__name__"] - attrs += [attr.name for attr in self._moved_attributes] - return attrs - - # Subclasses should override this - _moved_attributes = [] - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - -class _SixMetaPathImporter(object): - """ - A meta path importer to import six.moves and its submodules. - - This class implements a PEP302 finder and loader. It should be compatible - with Python 2.5 and all existing versions of Python3 - """ - def __init__(self, six_module_name): - self.name = six_module_name - self.known_modules = {} - - def _add_module(self, mod, *fullnames): - for fullname in fullnames: - self.known_modules[self.name + "." + fullname] = mod - - def _get_module(self, fullname): - return self.known_modules[self.name + "." + fullname] - - def find_module(self, fullname, path=None): - if fullname in self.known_modules: - return self - return None - - def __get_module(self, fullname): - try: - return self.known_modules[fullname] - except KeyError: - raise ImportError("This loader does not know module " + fullname) - - def load_module(self, fullname): - try: - # in case of a reload - return sys.modules[fullname] - except KeyError: - pass - mod = self.__get_module(fullname) - if isinstance(mod, MovedModule): - mod = mod._resolve() - else: - mod.__loader__ = self - sys.modules[fullname] = mod - return mod - - def is_package(self, fullname): - """ - Return true, if the named module is a package. - - We need this method to get correct spec objects with - Python 3.4 (see PEP451) - """ - return hasattr(self.__get_module(fullname), "__path__") - - def get_code(self, fullname): - """Return None - - Required, if is_package is implemented""" - self.__get_module(fullname) # eventually raises ImportError - return None - get_source = get_code # same as get_code - -_importer = _SixMetaPathImporter(__name__) - - -class _MovedItems(_LazyModule): - """Lazy loading of moved objects""" - __path__ = [] # mark as package - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserDict", "UserDict", "collections"), - MovedAttribute("UserList", "UserList", "collections"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), - MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("_thread", "thread", "_thread"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), - MovedModule("xmlrpc_server", "xmlrpclib", "xmlrpc.server"), - MovedModule("winreg", "_winreg"), -] -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) - if isinstance(attr, MovedModule): - _importer._add_module(attr, "moves." + attr.name) -del attr - -_MovedItems._moved_attributes = _moved_attributes - -moves = _MovedItems(__name__ + ".moves") -_importer._add_module(moves, "moves") - - -class Module_six_moves_urllib_parse(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("SplitResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes - -_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), - "moves.urllib_parse", "moves.urllib.parse") - - -class Module_six_moves_urllib_error(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes - -_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), - "moves.urllib_error", "moves.urllib.error") - - -class Module_six_moves_urllib_request(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), - MovedAttribute("proxy_bypass", "urllib", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes - -_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), - "moves.urllib_request", "moves.urllib.request") - - -class Module_six_moves_urllib_response(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes - -_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), - "moves.urllib_response", "moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes - -_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), - "moves.urllib_robotparser", "moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - __path__ = [] # mark as package - parse = _importer._get_module("moves.urllib_parse") - error = _importer._get_module("moves.urllib_error") - request = _importer._get_module("moves.urllib_request") - response = _importer._get_module("moves.urllib_response") - robotparser = _importer._get_module("moves.urllib_robotparser") - - def __dir__(self): - return ['parse', 'error', 'request', 'response', 'robotparser'] - -_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), - "moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.im_func - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -if PY3: - def iterkeys(d, **kw): - return iter(d.keys(**kw)) - - def itervalues(d, **kw): - return iter(d.values(**kw)) - - def iteritems(d, **kw): - return iter(d.items(**kw)) - - def iterlists(d, **kw): - return iter(d.lists(**kw)) -else: - def iterkeys(d, **kw): - return iter(d.iterkeys(**kw)) - - def itervalues(d, **kw): - return iter(d.itervalues(**kw)) - - def iteritems(d, **kw): - return iter(d.iteritems(**kw)) - - def iterlists(d, **kw): - return iter(d.iterlists(**kw)) - -_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") -_add_doc(itervalues, "Return an iterator over the values of a dictionary.") -_add_doc(iteritems, - "Return an iterator over the (key, value) pairs of a dictionary.") -_add_doc(iterlists, - "Return an iterator over the (key, [values]) pairs of a dictionary.") - - -if PY3: - def b(s): - return s.encode("latin-1") - def u(s): - return s - unichr = chr - if sys.version_info[1] <= 1: - def int2byte(i): - return bytes((i,)) - else: - # This is about 2x faster than the implementation above on 3.2+ - int2byte = operator.methodcaller("to_bytes", 1, "big") - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO -else: - def b(s): - return s - # Workaround for standalone backslash - def u(s): - return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") - unichr = unichr - int2byte = chr - def byte2int(bs): - return ord(bs[0]) - def indexbytes(buf, i): - return ord(buf[i]) - def iterbytes(buf): - return (ord(byte) for byte in buf) - import StringIO - StringIO = BytesIO = StringIO.StringIO -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -if PY3: - exec_ = getattr(moves.builtins, "exec") - - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - - -print_ = getattr(moves.builtins, "print", None) -if print_ is None: - def print_(*args, **kwargs): - """The new-style print function for Python 2.4 and 2.5.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - def write(data): - if not isinstance(data, basestring): - data = str(data) - # If the file has an encoding, encode unicode with it. - if (isinstance(fp, file) and - isinstance(data, unicode) and - fp.encoding is not None): - errors = getattr(fp, "errors", None) - if errors is None: - errors = "strict" - data = data.encode(fp.encoding, errors) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) - -_add_doc(reraise, """Reraise an exception.""") - -if sys.version_info[0:2] < (3, 4): - def wraps(wrapped): - def wrapper(f): - f = functools.wraps(wrapped)(f) - f.__wrapped__ = wrapped - return f - return wrapper -else: - wraps = functools.wraps - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a - # dummy metaclass for one level of class instantiation that replaces - # itself with the actual metaclass. Because of internal type checks - # we also need to make sure that we downgrade the custom metaclass - # for one level to something closer to type (that's why __call__ and - # __init__ comes back from type etc.). - class metaclass(meta): - __call__ = type.__call__ - __init__ = type.__init__ - def __new__(cls, name, this_bases, d): - if this_bases is None: - return type.__new__(cls, name, (), d) - return meta(name, bases, d) - return metaclass('temporary_class', None, {}) - - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - -# Complete the moves implementation. -# This code is at the end of this module to speed up module loading. -# Turn this module into a package. -__path__ = [] # required for PEP 302 and PEP 451 -__package__ = __name__ # see PEP 366 @ReservedAssignment -try: - __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable -except NameError: - pass -# Remove other six meta path importers, since they cause problems. This can -# happen if six is removed from sys.modules and then reloaded. (Setuptools does -# this for some reason.) -if sys.meta_path: - for i, importer in enumerate(sys.meta_path): - # Here's some real nastiness: Another "instance" of the six module might - # be floating around. Therefore, we can't use isinstance() to check for - # the six meta path importer, since the other six instance will have - # inserted an importer with different class. - if (type(importer).__name__ == "_SixMetaPathImporter" and - importer.name == __name__): - del sys.meta_path[i] - break - del i, importer -# Finally, add the importer to the meta path import hook. -sys.meta_path.append(_importer) diff --git a/awx/lib/site-packages/boto/vpc/__init__.py b/awx/lib/site-packages/boto/vpc/__init__.py deleted file mode 100644 index 868eabcbab..0000000000 --- a/awx/lib/site-packages/boto/vpc/__init__.py +++ /dev/null @@ -1,1687 +0,0 @@ -# Copyright (c) 2009 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a connection to the EC2 service. -""" - -from boto.ec2.connection import EC2Connection -from boto.resultset import ResultSet -from boto.vpc.vpc import VPC -from boto.vpc.customergateway import CustomerGateway -from boto.vpc.networkacl import NetworkAcl -from boto.vpc.routetable import RouteTable -from boto.vpc.internetgateway import InternetGateway -from boto.vpc.vpngateway import VpnGateway, Attachment -from boto.vpc.dhcpoptions import DhcpOptions -from boto.vpc.subnet import Subnet -from boto.vpc.vpnconnection import VpnConnection -from boto.vpc.vpc_peering_connection import VpcPeeringConnection -from boto.ec2 import RegionData -from boto.regioninfo import RegionInfo, get_regions - - -def regions(**kw_params): - """ - Get all available regions for the EC2 service. - You may pass any of the arguments accepted by the VPCConnection - object's constructor as keyword arguments and they will be - passed along to the VPCConnection object. - - :rtype: list - :return: A list of :class:`boto.ec2.regioninfo.RegionInfo` - """ - return get_regions('ec2', connection_cls=VPCConnection) - - -def connect_to_region(region_name, **kw_params): - """ - Given a valid region name, return a - :class:`boto.vpc.VPCConnection`. - Any additional parameters after the region_name are passed on to - the connect method of the region object. - - :type: str - :param region_name: The name of the region to connect to. - - :rtype: :class:`boto.vpc.VPCConnection` or ``None`` - :return: A connection to the given region, or None if an invalid region - name is given - """ - for region in regions(**kw_params): - if region.name == region_name: - return region.connect(**kw_params) - return None - - -class VPCConnection(EC2Connection): - - # VPC methods - - def get_all_vpcs(self, vpc_ids=None, filters=None, dry_run=False): - """ - Retrieve information about your VPCs. You can filter results to - return information only about those VPCs that match your search - parameters. Otherwise, all VPCs associated with your account - are returned. - - :type vpc_ids: list - :param vpc_ids: A list of strings with the desired VPC ID's - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - Possible filter keys are: - - * *state* - a list of states of the VPC (pending or available) - * *cidrBlock* - a list CIDR blocks of the VPC - * *dhcpOptionsId* - a list of IDs of a set of DHCP options - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpc.vpc.VPC` - """ - params = {} - if vpc_ids: - self.build_list_params(params, vpc_ids, 'VpcId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeVpcs', params, [('item', VPC)]) - - def create_vpc(self, cidr_block, instance_tenancy=None, dry_run=False): - """ - Create a new Virtual Private Cloud. - - :type cidr_block: str - :param cidr_block: A valid CIDR block - - :type instance_tenancy: str - :param instance_tenancy: The supported tenancy options for instances - launched into the VPC. Valid values are 'default' and 'dedicated'. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: The newly created VPC - :return: A :class:`boto.vpc.vpc.VPC` object - """ - params = {'CidrBlock': cidr_block} - if instance_tenancy: - params['InstanceTenancy'] = instance_tenancy - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateVpc', params, VPC) - - def delete_vpc(self, vpc_id, dry_run=False): - """ - Delete a Virtual Private Cloud. - - :type vpc_id: str - :param vpc_id: The ID of the vpc to be deleted. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'VpcId': vpc_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteVpc', params) - - def modify_vpc_attribute(self, vpc_id, - enable_dns_support=None, - enable_dns_hostnames=None, dry_run=False): - """ - Modifies the specified attribute of the specified VPC. - You can only modify one attribute at a time. - - :type vpc_id: str - :param vpc_id: The ID of the vpc to be deleted. - - :type enable_dns_support: bool - :param enable_dns_support: Specifies whether the DNS server - provided by Amazon is enabled for the VPC. - - :type enable_dns_hostnames: bool - :param enable_dns_hostnames: Specifies whether DNS hostnames are - provided for the instances launched in this VPC. You can only - set this attribute to ``true`` if EnableDnsSupport - is also ``true``. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {'VpcId': vpc_id} - if enable_dns_support is not None: - if enable_dns_support: - params['EnableDnsSupport.Value'] = 'true' - else: - params['EnableDnsSupport.Value'] = 'false' - if enable_dns_hostnames is not None: - if enable_dns_hostnames: - params['EnableDnsHostnames.Value'] = 'true' - else: - params['EnableDnsHostnames.Value'] = 'false' - if dry_run: - params['DryRun'] = 'true' - return self.get_status('ModifyVpcAttribute', params) - - # Route Tables - - def get_all_route_tables(self, route_table_ids=None, filters=None, - dry_run=False): - """ - Retrieve information about your routing tables. You can filter results - to return information only about those route tables that match your - search parameters. Otherwise, all route tables associated with your - account are returned. - - :type route_table_ids: list - :param route_table_ids: A list of strings with the desired route table - IDs. - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpc.routetable.RouteTable` - """ - params = {} - if route_table_ids: - self.build_list_params(params, route_table_ids, "RouteTableId") - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeRouteTables', params, - [('item', RouteTable)]) - - def associate_route_table(self, route_table_id, subnet_id, dry_run=False): - """ - Associates a route table with a specific subnet. - - :type route_table_id: str - :param route_table_id: The ID of the route table to associate. - - :type subnet_id: str - :param subnet_id: The ID of the subnet to associate with. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: str - :return: The ID of the association created - """ - params = { - 'RouteTableId': route_table_id, - 'SubnetId': subnet_id - } - if dry_run: - params['DryRun'] = 'true' - result = self.get_object('AssociateRouteTable', params, ResultSet) - return result.associationId - - def disassociate_route_table(self, association_id, dry_run=False): - """ - Removes an association from a route table. This will cause all subnets - that would've used this association to now use the main routing - association instead. - - :type association_id: str - :param association_id: The ID of the association to disassociate. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'AssociationId': association_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DisassociateRouteTable', params) - - def create_route_table(self, vpc_id, dry_run=False): - """ - Creates a new route table. - - :type vpc_id: str - :param vpc_id: The VPC ID to associate this route table with. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: The newly created route table - :return: A :class:`boto.vpc.routetable.RouteTable` object - """ - params = {'VpcId': vpc_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateRouteTable', params, RouteTable) - - def delete_route_table(self, route_table_id, dry_run=False): - """ - Delete a route table. - - :type route_table_id: str - :param route_table_id: The ID of the route table to delete. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'RouteTableId': route_table_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteRouteTable', params) - - def _replace_route_table_association(self, association_id, - route_table_id, dry_run=False): - """ - Helper function for replace_route_table_association and - replace_route_table_association_with_assoc. Should not be used directly. - - :type association_id: str - :param association_id: The ID of the existing association to replace. - - :type route_table_id: str - :param route_table_id: The route table to ID to be used in the - association. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: ResultSet - :return: ResultSet of Amazon resposne - """ - params = { - 'AssociationId': association_id, - 'RouteTableId': route_table_id - } - if dry_run: - params['DryRun'] = 'true' - return self.get_object('ReplaceRouteTableAssociation', params, - ResultSet) - - def replace_route_table_assocation(self, association_id, - route_table_id, dry_run=False): - """ - Replaces a route association with a new route table. This can be - used to replace the 'main' route table by using the main route - table association instead of the more common subnet type - association. - - NOTE: It may be better to use replace_route_table_association_with_assoc - instead of this function; this function does not return the new - association ID. This function is retained for backwards compatibility. - - - :type association_id: str - :param association_id: The ID of the existing association to replace. - - :type route_table_id: str - :param route_table_id: The route table to ID to be used in the - association. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - return self._replace_route_table_association( - association_id, route_table_id, dry_run=dry_run).status - - def replace_route_table_association_with_assoc(self, association_id, - route_table_id, - dry_run=False): - """ - Replaces a route association with a new route table. This can be - used to replace the 'main' route table by using the main route - table association instead of the more common subnet type - association. Returns the new association ID. - - :type association_id: str - :param association_id: The ID of the existing association to replace. - - :type route_table_id: str - :param route_table_id: The route table to ID to be used in the - association. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: str - :return: New association ID - """ - return self._replace_route_table_association( - association_id, route_table_id, dry_run=dry_run).newAssociationId - - def create_route(self, route_table_id, destination_cidr_block, - gateway_id=None, instance_id=None, interface_id=None, - vpc_peering_connection_id=None, - dry_run=False): - """ - Creates a new route in the route table within a VPC. The route's target - can be either a gateway attached to the VPC or a NAT instance in the - VPC. - - :type route_table_id: str - :param route_table_id: The ID of the route table for the route. - - :type destination_cidr_block: str - :param destination_cidr_block: The CIDR address block used for the - destination match. - - :type gateway_id: str - :param gateway_id: The ID of the gateway attached to your VPC. - - :type instance_id: str - :param instance_id: The ID of a NAT instance in your VPC. - - :type interface_id: str - :param interface_id: Allows routing to network interface attachments. - - :type vpc_peering_connection_id: str - :param vpc_peering_connection_id: Allows routing to VPC peering - connection. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = { - 'RouteTableId': route_table_id, - 'DestinationCidrBlock': destination_cidr_block - } - - if gateway_id is not None: - params['GatewayId'] = gateway_id - elif instance_id is not None: - params['InstanceId'] = instance_id - elif interface_id is not None: - params['NetworkInterfaceId'] = interface_id - elif vpc_peering_connection_id is not None: - params['VpcPeeringConnectionId'] = vpc_peering_connection_id - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('CreateRoute', params) - - def replace_route(self, route_table_id, destination_cidr_block, - gateway_id=None, instance_id=None, interface_id=None, - vpc_peering_connection_id=None, - dry_run=False): - """ - Replaces an existing route within a route table in a VPC. - - :type route_table_id: str - :param route_table_id: The ID of the route table for the route. - - :type destination_cidr_block: str - :param destination_cidr_block: The CIDR address block used for the - destination match. - - :type gateway_id: str - :param gateway_id: The ID of the gateway attached to your VPC. - - :type instance_id: str - :param instance_id: The ID of a NAT instance in your VPC. - - :type interface_id: str - :param interface_id: Allows routing to network interface attachments. - - :type vpc_peering_connection_id: str - :param vpc_peering_connection_id: Allows routing to VPC peering - connection. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = { - 'RouteTableId': route_table_id, - 'DestinationCidrBlock': destination_cidr_block - } - - if gateway_id is not None: - params['GatewayId'] = gateway_id - elif instance_id is not None: - params['InstanceId'] = instance_id - elif interface_id is not None: - params['NetworkInterfaceId'] = interface_id - elif vpc_peering_connection_id is not None: - params['VpcPeeringConnectionId'] = vpc_peering_connection_id - if dry_run: - params['DryRun'] = 'true' - - return self.get_status('ReplaceRoute', params) - - def delete_route(self, route_table_id, destination_cidr_block, - dry_run=False): - """ - Deletes a route from a route table within a VPC. - - :type route_table_id: str - :param route_table_id: The ID of the route table with the route. - - :type destination_cidr_block: str - :param destination_cidr_block: The CIDR address block used for - destination match. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = { - 'RouteTableId': route_table_id, - 'DestinationCidrBlock': destination_cidr_block - } - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteRoute', params) - - #Network ACLs - - def get_all_network_acls(self, network_acl_ids=None, filters=None): - """ - Retrieve information about your network acls. You can filter results - to return information only about those network acls that match your - search parameters. Otherwise, all network acls associated with your - account are returned. - - :type network_acl_ids: list - :param network_acl_ids: A list of strings with the desired network ACL - IDs. - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - - :rtype: list - :return: A list of :class:`boto.vpc.networkacl.NetworkAcl` - """ - params = {} - if network_acl_ids: - self.build_list_params(params, network_acl_ids, "NetworkAclId") - if filters: - self.build_filter_params(params, filters) - return self.get_list('DescribeNetworkAcls', params, - [('item', NetworkAcl)]) - - def associate_network_acl(self, network_acl_id, subnet_id): - """ - Associates a network acl with a specific subnet. - - :type network_acl_id: str - :param network_acl_id: The ID of the network ACL to associate. - - :type subnet_id: str - :param subnet_id: The ID of the subnet to associate with. - - :rtype: str - :return: The ID of the association created - """ - - acl = self.get_all_network_acls(filters=[('association.subnet-id', subnet_id)])[0] - association = [ association for association in acl.associations if association.subnet_id == subnet_id ][0] - - params = { - 'AssociationId': association.id, - 'NetworkAclId': network_acl_id - } - - result = self.get_object('ReplaceNetworkAclAssociation', params, ResultSet) - return result.newAssociationId - - def disassociate_network_acl(self, subnet_id, vpc_id=None): - """ - Figures out what the default ACL is for the VPC, and associates - current network ACL with the default. - - :type subnet_id: str - :param subnet_id: The ID of the subnet to which the ACL belongs. - - :type vpc_id: str - :param vpc_id: The ID of the VPC to which the ACL/subnet belongs. Queries EC2 if omitted. - - :rtype: str - :return: The ID of the association created - """ - if not vpc_id: - vpc_id = self.get_all_subnets([subnet_id])[0].vpc_id - acls = self.get_all_network_acls(filters=[('vpc-id', vpc_id), ('default', 'true')]) - default_acl_id = acls[0].id - - return self.associate_network_acl(default_acl_id, subnet_id) - - def create_network_acl(self, vpc_id): - """ - Creates a new network ACL. - - :type vpc_id: str - :param vpc_id: The VPC ID to associate this network ACL with. - - :rtype: The newly created network ACL - :return: A :class:`boto.vpc.networkacl.NetworkAcl` object - """ - params = {'VpcId': vpc_id} - return self.get_object('CreateNetworkAcl', params, NetworkAcl) - - def delete_network_acl(self, network_acl_id): - """ - Delete a network ACL - - :type network_acl_id: str - :param network_acl_id: The ID of the network_acl to delete. - - :rtype: bool - :return: True if successful - """ - params = {'NetworkAclId': network_acl_id} - return self.get_status('DeleteNetworkAcl', params) - - def create_network_acl_entry(self, network_acl_id, rule_number, protocol, rule_action, - cidr_block, egress=None, icmp_code=None, icmp_type=None, - port_range_from=None, port_range_to=None): - """ - Creates a new network ACL entry in a network ACL within a VPC. - - :type network_acl_id: str - :param network_acl_id: The ID of the network ACL for this network ACL entry. - - :type rule_number: int - :param rule_number: The rule number to assign to the entry (for example, 100). - - :type protocol: int - :param protocol: Valid values: -1 or a protocol number - (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml) - - :type rule_action: str - :param rule_action: Indicates whether to allow or deny traffic that matches the rule. - - :type cidr_block: str - :param cidr_block: The CIDR range to allow or deny, in CIDR notation (for example, - 172.16.0.0/24). - - :type egress: bool - :param egress: Indicates whether this rule applies to egress traffic from the subnet (true) - or ingress traffic to the subnet (false). - - :type icmp_type: int - :param icmp_type: For the ICMP protocol, the ICMP type. You can use -1 to specify - all ICMP types. - - :type icmp_code: int - :param icmp_code: For the ICMP protocol, the ICMP code. You can use -1 to specify - all ICMP codes for the given ICMP type. - - :type port_range_from: int - :param port_range_from: The first port in the range. - - :type port_range_to: int - :param port_range_to: The last port in the range. - - - :rtype: bool - :return: True if successful - """ - params = { - 'NetworkAclId': network_acl_id, - 'RuleNumber': rule_number, - 'Protocol': protocol, - 'RuleAction': rule_action, - 'CidrBlock': cidr_block - } - - if egress is not None: - if isinstance(egress, bool): - egress = str(egress).lower() - params['Egress'] = egress - if icmp_code is not None: - params['Icmp.Code'] = icmp_code - if icmp_type is not None: - params['Icmp.Type'] = icmp_type - if port_range_from is not None: - params['PortRange.From'] = port_range_from - if port_range_to is not None: - params['PortRange.To'] = port_range_to - - return self.get_status('CreateNetworkAclEntry', params) - - def replace_network_acl_entry(self, network_acl_id, rule_number, protocol, rule_action, - cidr_block, egress=None, icmp_code=None, icmp_type=None, - port_range_from=None, port_range_to=None): - """ - Creates a new network ACL entry in a network ACL within a VPC. - - :type network_acl_id: str - :param network_acl_id: The ID of the network ACL for the id you want to replace - - :type rule_number: int - :param rule_number: The rule number that you want to replace(for example, 100). - - :type protocol: int - :param protocol: Valid values: -1 or a protocol number - (http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml) - - :type rule_action: str - :param rule_action: Indicates whether to allow or deny traffic that matches the rule. - - :type cidr_block: str - :param cidr_block: The CIDR range to allow or deny, in CIDR notation (for example, - 172.16.0.0/24). - - :type egress: bool - :param egress: Indicates whether this rule applies to egress traffic from the subnet (true) - or ingress traffic to the subnet (false). - - :type icmp_type: int - :param icmp_type: For the ICMP protocol, the ICMP type. You can use -1 to specify - all ICMP types. - - :type icmp_code: int - :param icmp_code: For the ICMP protocol, the ICMP code. You can use -1 to specify - all ICMP codes for the given ICMP type. - - :type port_range_from: int - :param port_range_from: The first port in the range. - - :type port_range_to: int - :param port_range_to: The last port in the range. - - - :rtype: bool - :return: True if successful - """ - params = { - 'NetworkAclId': network_acl_id, - 'RuleNumber': rule_number, - 'Protocol': protocol, - 'RuleAction': rule_action, - 'CidrBlock': cidr_block - } - - if egress is not None: - if isinstance(egress, bool): - egress = str(egress).lower() - params['Egress'] = egress - if icmp_code is not None: - params['Icmp.Code'] = icmp_code - if icmp_type is not None: - params['Icmp.Type'] = icmp_type - if port_range_from is not None: - params['PortRange.From'] = port_range_from - if port_range_to is not None: - params['PortRange.To'] = port_range_to - - return self.get_status('ReplaceNetworkAclEntry', params) - - def delete_network_acl_entry(self, network_acl_id, rule_number, egress=None): - """ - Deletes a network ACL entry from a network ACL within a VPC. - - :type network_acl_id: str - :param network_acl_id: The ID of the network ACL with the network ACL entry. - - :type rule_number: int - :param rule_number: The rule number for the entry to delete. - - :type egress: bool - :param egress: Specifies whether the rule to delete is an egress rule (true) - or ingress rule (false). - - :rtype: bool - :return: True if successful - """ - params = { - 'NetworkAclId': network_acl_id, - 'RuleNumber': rule_number - } - - if egress is not None: - if isinstance(egress, bool): - egress = str(egress).lower() - params['Egress'] = egress - - return self.get_status('DeleteNetworkAclEntry', params) - - # Internet Gateways - - def get_all_internet_gateways(self, internet_gateway_ids=None, - filters=None, dry_run=False): - """ - Get a list of internet gateways. You can filter results to return information - about only those gateways that you're interested in. - - :type internet_gateway_ids: list - :param internet_gateway_ids: A list of strings with the desired gateway IDs. - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - """ - params = {} - - if internet_gateway_ids: - self.build_list_params(params, internet_gateway_ids, - 'InternetGatewayId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeInternetGateways', params, - [('item', InternetGateway)]) - - def create_internet_gateway(self, dry_run=False): - """ - Creates an internet gateway for VPC. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: Newly created internet gateway. - :return: `boto.vpc.internetgateway.InternetGateway` - """ - params = {} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateInternetGateway', params, InternetGateway) - - def delete_internet_gateway(self, internet_gateway_id, dry_run=False): - """ - Deletes an internet gateway from the VPC. - - :type internet_gateway_id: str - :param internet_gateway_id: The ID of the internet gateway to delete. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: Bool - :return: True if successful - """ - params = {'InternetGatewayId': internet_gateway_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteInternetGateway', params) - - def attach_internet_gateway(self, internet_gateway_id, vpc_id, - dry_run=False): - """ - Attach an internet gateway to a specific VPC. - - :type internet_gateway_id: str - :param internet_gateway_id: The ID of the internet gateway to attach. - - :type vpc_id: str - :param vpc_id: The ID of the VPC to attach to. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: Bool - :return: True if successful - """ - params = { - 'InternetGatewayId': internet_gateway_id, - 'VpcId': vpc_id - } - if dry_run: - params['DryRun'] = 'true' - return self.get_status('AttachInternetGateway', params) - - def detach_internet_gateway(self, internet_gateway_id, vpc_id, - dry_run=False): - """ - Detach an internet gateway from a specific VPC. - - :type internet_gateway_id: str - :param internet_gateway_id: The ID of the internet gateway to detach. - - :type vpc_id: str - :param vpc_id: The ID of the VPC to attach to. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: Bool - :return: True if successful - """ - params = { - 'InternetGatewayId': internet_gateway_id, - 'VpcId': vpc_id - } - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DetachInternetGateway', params) - - # Customer Gateways - - def get_all_customer_gateways(self, customer_gateway_ids=None, - filters=None, dry_run=False): - """ - Retrieve information about your CustomerGateways. You can filter - results to return information only about those CustomerGateways that - match your search parameters. Otherwise, all CustomerGateways - associated with your account are returned. - - :type customer_gateway_ids: list - :param customer_gateway_ids: A list of strings with the desired - CustomerGateway ID's. - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - Possible filter keys are: - - - *state*, the state of the CustomerGateway - (pending,available,deleting,deleted) - - *type*, the type of customer gateway (ipsec.1) - - *ipAddress* the IP address of customer gateway's - internet-routable external inteface - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpc.customergateway.CustomerGateway` - """ - params = {} - if customer_gateway_ids: - self.build_list_params(params, customer_gateway_ids, - 'CustomerGatewayId') - if filters: - self.build_filter_params(params, filters) - - if dry_run: - params['DryRun'] = 'true' - - return self.get_list('DescribeCustomerGateways', params, - [('item', CustomerGateway)]) - - def create_customer_gateway(self, type, ip_address, bgp_asn, dry_run=False): - """ - Create a new Customer Gateway - - :type type: str - :param type: Type of VPN Connection. Only valid value currently is 'ipsec.1' - - :type ip_address: str - :param ip_address: Internet-routable IP address for customer's gateway. - Must be a static address. - - :type bgp_asn: int - :param bgp_asn: Customer gateway's Border Gateway Protocol (BGP) - Autonomous System Number (ASN) - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: The newly created CustomerGateway - :return: A :class:`boto.vpc.customergateway.CustomerGateway` object - """ - params = {'Type': type, - 'IpAddress': ip_address, - 'BgpAsn': bgp_asn} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateCustomerGateway', params, CustomerGateway) - - def delete_customer_gateway(self, customer_gateway_id, dry_run=False): - """ - Delete a Customer Gateway. - - :type customer_gateway_id: str - :param customer_gateway_id: The ID of the customer_gateway to be deleted. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'CustomerGatewayId': customer_gateway_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteCustomerGateway', params) - - # VPN Gateways - - def get_all_vpn_gateways(self, vpn_gateway_ids=None, filters=None, - dry_run=False): - """ - Retrieve information about your VpnGateways. You can filter results to - return information only about those VpnGateways that match your search - parameters. Otherwise, all VpnGateways associated with your account - are returned. - - :type vpn_gateway_ids: list - :param vpn_gateway_ids: A list of strings with the desired VpnGateway ID's - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - Possible filter keys are: - - - *state*, a list of states of the VpnGateway - (pending,available,deleting,deleted) - - *type*, a list types of customer gateway (ipsec.1) - - *availabilityZone*, a list of Availability zones the - VPN gateway is in. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpc.customergateway.VpnGateway` - """ - params = {} - if vpn_gateway_ids: - self.build_list_params(params, vpn_gateway_ids, 'VpnGatewayId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeVpnGateways', params, - [('item', VpnGateway)]) - - def create_vpn_gateway(self, type, availability_zone=None, dry_run=False): - """ - Create a new Vpn Gateway - - :type type: str - :param type: Type of VPN Connection. Only valid value currently is 'ipsec.1' - - :type availability_zone: str - :param availability_zone: The Availability Zone where you want the VPN gateway. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: The newly created VpnGateway - :return: A :class:`boto.vpc.vpngateway.VpnGateway` object - """ - params = {'Type': type} - if availability_zone: - params['AvailabilityZone'] = availability_zone - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateVpnGateway', params, VpnGateway) - - def delete_vpn_gateway(self, vpn_gateway_id, dry_run=False): - """ - Delete a Vpn Gateway. - - :type vpn_gateway_id: str - :param vpn_gateway_id: The ID of the vpn_gateway to be deleted. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'VpnGatewayId': vpn_gateway_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteVpnGateway', params) - - def attach_vpn_gateway(self, vpn_gateway_id, vpc_id, dry_run=False): - """ - Attaches a VPN gateway to a VPC. - - :type vpn_gateway_id: str - :param vpn_gateway_id: The ID of the vpn_gateway to attach - - :type vpc_id: str - :param vpc_id: The ID of the VPC you want to attach the gateway to. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: An attachment - :return: a :class:`boto.vpc.vpngateway.Attachment` - """ - params = {'VpnGatewayId': vpn_gateway_id, - 'VpcId': vpc_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_object('AttachVpnGateway', params, Attachment) - - def detach_vpn_gateway(self, vpn_gateway_id, vpc_id, dry_run=False): - """ - Detaches a VPN gateway from a VPC. - - :type vpn_gateway_id: str - :param vpn_gateway_id: The ID of the vpn_gateway to detach - - :type vpc_id: str - :param vpc_id: The ID of the VPC you want to detach the gateway from. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'VpnGatewayId': vpn_gateway_id, - 'VpcId': vpc_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DetachVpnGateway', params) - - # Subnets - - def get_all_subnets(self, subnet_ids=None, filters=None, dry_run=False): - """ - Retrieve information about your Subnets. You can filter results to - return information only about those Subnets that match your search - parameters. Otherwise, all Subnets associated with your account - are returned. - - :type subnet_ids: list - :param subnet_ids: A list of strings with the desired Subnet ID's - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - Possible filter keys are: - - - *state*, a list of states of the Subnet - (pending,available) - - *vpcId*, a list of IDs of the VPC that the subnet is in. - - *cidrBlock*, a list of CIDR blocks of the subnet - - *availabilityZone*, list of the Availability Zones - the subnet is in. - - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpc.subnet.Subnet` - """ - params = {} - if subnet_ids: - self.build_list_params(params, subnet_ids, 'SubnetId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeSubnets', params, [('item', Subnet)]) - - def create_subnet(self, vpc_id, cidr_block, availability_zone=None, - dry_run=False): - """ - Create a new Subnet - - :type vpc_id: str - :param vpc_id: The ID of the VPC where you want to create the subnet. - - :type cidr_block: str - :param cidr_block: The CIDR block you want the subnet to cover. - - :type availability_zone: str - :param availability_zone: The AZ you want the subnet in - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: The newly created Subnet - :return: A :class:`boto.vpc.customergateway.Subnet` object - """ - params = {'VpcId': vpc_id, - 'CidrBlock': cidr_block} - if availability_zone: - params['AvailabilityZone'] = availability_zone - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateSubnet', params, Subnet) - - def delete_subnet(self, subnet_id, dry_run=False): - """ - Delete a subnet. - - :type subnet_id: str - :param subnet_id: The ID of the subnet to be deleted. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'SubnetId': subnet_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteSubnet', params) - - # DHCP Options - - def get_all_dhcp_options(self, dhcp_options_ids=None, filters=None, dry_run=False): - """ - Retrieve information about your DhcpOptions. - - :type dhcp_options_ids: list - :param dhcp_options_ids: A list of strings with the desired DhcpOption ID's - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpc.dhcpoptions.DhcpOptions` - """ - params = {} - if dhcp_options_ids: - self.build_list_params(params, dhcp_options_ids, 'DhcpOptionsId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeDhcpOptions', params, - [('item', DhcpOptions)]) - - def create_dhcp_options(self, domain_name=None, domain_name_servers=None, - ntp_servers=None, netbios_name_servers=None, - netbios_node_type=None, dry_run=False): - """ - Create a new DhcpOption - - This corresponds to - http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateDhcpOptions.html - - :type domain_name: str - :param domain_name: A domain name of your choice (for example, - example.com) - - :type domain_name_servers: list of strings - :param domain_name_servers: The IP address of a domain name server. You - can specify up to four addresses. - - :type ntp_servers: list of strings - :param ntp_servers: The IP address of a Network Time Protocol (NTP) - server. You can specify up to four addresses. - - :type netbios_name_servers: list of strings - :param netbios_name_servers: The IP address of a NetBIOS name server. - You can specify up to four addresses. - - :type netbios_node_type: str - :param netbios_node_type: The NetBIOS node type (1, 2, 4, or 8). For - more information about the values, see RFC 2132. We recommend you - only use 2 at this time (broadcast and multicast are currently not - supported). - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: The newly created DhcpOption - :return: A :class:`boto.vpc.customergateway.DhcpOption` object - """ - - key_counter = 1 - params = {} - - def insert_option(params, name, value): - params['DhcpConfiguration.%d.Key' % (key_counter,)] = name - if isinstance(value, (list, tuple)): - for idx, value in enumerate(value, 1): - key_name = 'DhcpConfiguration.%d.Value.%d' % ( - key_counter, idx) - params[key_name] = value - else: - key_name = 'DhcpConfiguration.%d.Value.1' % (key_counter,) - params[key_name] = value - - return key_counter + 1 - - if domain_name: - key_counter = insert_option(params, - 'domain-name', domain_name) - if domain_name_servers: - key_counter = insert_option(params, - 'domain-name-servers', domain_name_servers) - if ntp_servers: - key_counter = insert_option(params, - 'ntp-servers', ntp_servers) - if netbios_name_servers: - key_counter = insert_option(params, - 'netbios-name-servers', netbios_name_servers) - if netbios_node_type: - key_counter = insert_option(params, - 'netbios-node-type', netbios_node_type) - if dry_run: - params['DryRun'] = 'true' - - return self.get_object('CreateDhcpOptions', params, DhcpOptions) - - def delete_dhcp_options(self, dhcp_options_id, dry_run=False): - """ - Delete a DHCP Options - - :type dhcp_options_id: str - :param dhcp_options_id: The ID of the DHCP Options to be deleted. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'DhcpOptionsId': dhcp_options_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteDhcpOptions', params) - - def associate_dhcp_options(self, dhcp_options_id, vpc_id, dry_run=False): - """ - Associate a set of Dhcp Options with a VPC. - - :type dhcp_options_id: str - :param dhcp_options_id: The ID of the Dhcp Options - - :type vpc_id: str - :param vpc_id: The ID of the VPC. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'DhcpOptionsId': dhcp_options_id, - 'VpcId': vpc_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('AssociateDhcpOptions', params) - - # VPN Connection - - def get_all_vpn_connections(self, vpn_connection_ids=None, filters=None, - dry_run=False): - """ - Retrieve information about your VPN_CONNECTIONs. You can filter results to - return information only about those VPN_CONNECTIONs that match your search - parameters. Otherwise, all VPN_CONNECTIONs associated with your account - are returned. - - :type vpn_connection_ids: list - :param vpn_connection_ids: A list of strings with the desired VPN_CONNECTION ID's - - :type filters: list of tuples or dict - :param filters: A list of tuples or dict containing filters. Each tuple - or dict item consists of a filter key and a filter value. - Possible filter keys are: - - - *state*, a list of states of the VPN_CONNECTION - pending,available,deleting,deleted - - *type*, a list of types of connection, currently 'ipsec.1' - - *customerGatewayId*, a list of IDs of the customer gateway - associated with the VPN - - *vpnGatewayId*, a list of IDs of the VPN gateway associated - with the VPN connection - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpn_connection.vpnconnection.VpnConnection` - """ - params = {} - if vpn_connection_ids: - self.build_list_params(params, vpn_connection_ids, - 'VpnConnectionId') - if filters: - self.build_filter_params(params, filters) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeVpnConnections', params, - [('item', VpnConnection)]) - - def create_vpn_connection(self, type, customer_gateway_id, vpn_gateway_id, - static_routes_only=None, dry_run=False): - """ - Create a new VPN Connection. - - :type type: str - :param type: The type of VPN Connection. Currently only 'ipsec.1' - is supported - - :type customer_gateway_id: str - :param customer_gateway_id: The ID of the customer gateway. - - :type vpn_gateway_id: str - :param vpn_gateway_id: The ID of the VPN gateway. - - :type static_routes_only: bool - :param static_routes_only: Indicates whether the VPN connection - requires static routes. If you are creating a VPN connection - for a device that does not support BGP, you must specify true. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: The newly created VpnConnection - :return: A :class:`boto.vpc.vpnconnection.VpnConnection` object - """ - params = {'Type': type, - 'CustomerGatewayId': customer_gateway_id, - 'VpnGatewayId': vpn_gateway_id} - if static_routes_only is not None: - if isinstance(static_routes_only, bool): - static_routes_only = str(static_routes_only).lower() - params['Options.StaticRoutesOnly'] = static_routes_only - if dry_run: - params['DryRun'] = 'true' - return self.get_object('CreateVpnConnection', params, VpnConnection) - - def delete_vpn_connection(self, vpn_connection_id, dry_run=False): - """ - Delete a VPN Connection. - - :type vpn_connection_id: str - :param vpn_connection_id: The ID of the vpn_connection to be deleted. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = {'VpnConnectionId': vpn_connection_id} - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteVpnConnection', params) - - def disable_vgw_route_propagation(self, route_table_id, gateway_id, - dry_run=False): - """ - Disables a virtual private gateway (VGW) from propagating routes to the - routing tables of an Amazon VPC. - - :type route_table_id: str - :param route_table_id: The ID of the routing table. - - :type gateway_id: str - :param gateway_id: The ID of the virtual private gateway. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = { - 'RouteTableId': route_table_id, - 'GatewayId': gateway_id, - } - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DisableVgwRoutePropagation', params) - - def enable_vgw_route_propagation(self, route_table_id, gateway_id, - dry_run=False): - """ - Enables a virtual private gateway (VGW) to propagate routes to the - routing tables of an Amazon VPC. - - :type route_table_id: str - :param route_table_id: The ID of the routing table. - - :type gateway_id: str - :param gateway_id: The ID of the virtual private gateway. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = { - 'RouteTableId': route_table_id, - 'GatewayId': gateway_id, - } - if dry_run: - params['DryRun'] = 'true' - return self.get_status('EnableVgwRoutePropagation', params) - - def create_vpn_connection_route(self, destination_cidr_block, - vpn_connection_id, dry_run=False): - """ - Creates a new static route associated with a VPN connection between an - existing virtual private gateway and a VPN customer gateway. The static - route allows traffic to be routed from the virtual private gateway to - the VPN customer gateway. - - :type destination_cidr_block: str - :param destination_cidr_block: The CIDR block associated with the local - subnet of the customer data center. - - :type vpn_connection_id: str - :param vpn_connection_id: The ID of the VPN connection. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = { - 'DestinationCidrBlock': destination_cidr_block, - 'VpnConnectionId': vpn_connection_id, - } - if dry_run: - params['DryRun'] = 'true' - return self.get_status('CreateVpnConnectionRoute', params) - - def delete_vpn_connection_route(self, destination_cidr_block, - vpn_connection_id, dry_run=False): - """ - Deletes a static route associated with a VPN connection between an - existing virtual private gateway and a VPN customer gateway. The static - route allows traffic to be routed from the virtual private gateway to - the VPN customer gateway. - - :type destination_cidr_block: str - :param destination_cidr_block: The CIDR block associated with the local - subnet of the customer data center. - - :type vpn_connection_id: str - :param vpn_connection_id: The ID of the VPN connection. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: bool - :return: True if successful - """ - params = { - 'DestinationCidrBlock': destination_cidr_block, - 'VpnConnectionId': vpn_connection_id, - } - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteVpnConnectionRoute', params) - - def get_all_vpc_peering_connections(self, vpc_peering_connection_ids=None, - filters=None, dry_run=False): - """ - Retrieve information about your VPC peering connections. You - can filter results to return information only about those VPC - peering connections that match your search parameters. - Otherwise, all VPC peering connections associated with your - account are returned. - - :type vpc_peering_connection_ids: list - :param vpc_peering_connection_ids: A list of strings with the desired VPC - peering connection ID's - - :type filters: list of tuples - :param filters: A list of tuples containing filters. Each tuple - consists of a filter key and a filter value. - Possible filter keys are: - - * *accepter-vpc-info.cidr-block* - The CIDR block of the peer VPC. - * *accepter-vpc-info.owner-id* - The AWS account ID of the owner - of the peer VPC. - * *accepter-vpc-info.vpc-id* - The ID of the peer VPC. - * *expiration-time* - The expiration date and time for the VPC - peering connection. - * *requester-vpc-info.cidr-block* - The CIDR block of the - requester's VPC. - * *requester-vpc-info.owner-id* - The AWS account ID of the - owner of the requester VPC. - * *requester-vpc-info.vpc-id* - The ID of the requester VPC. - * *status-code* - The status of the VPC peering connection. - * *status-message* - A message that provides more information - about the status of the VPC peering connection, if applicable. - - :type dry_run: bool - :param dry_run: Set to True if the operation should not actually run. - - :rtype: list - :return: A list of :class:`boto.vpc.vpc.VPC` - """ - params = {} - if vpc_peering_connection_ids: - self.build_list_params(params, vpc_peering_connection_ids, 'VpcPeeringConnectionId') - if filters: - self.build_filter_params(params, dict(filters)) - if dry_run: - params['DryRun'] = 'true' - return self.get_list('DescribeVpcPeeringConnections', params, [('item', VpcPeeringConnection)]) - - def create_vpc_peering_connection(self, vpc_id, peer_vpc_id, - peer_owner_id=None, dry_run=False): - """ - Create a new VPN Peering connection. - - :type vpc_id: str - :param vpc_id: The ID of the requester VPC. - - :type peer_vpc_id: str - :param vpc_peer_id: The ID of the VPC with which you are creating the peering connection. - - :type peer_owner_id: str - :param peer_owner_id: The AWS account ID of the owner of the peer VPC. - - :rtype: The newly created VpcPeeringConnection - :return: A :class:`boto.vpc.vpc_peering_connection.VpcPeeringConnection` object - """ - params = {'VpcId': vpc_id, - 'PeerVpcId': peer_vpc_id } - if peer_owner_id is not None: - params['PeerOwnerId'] = peer_owner_id - if dry_run: - params['DryRun'] = 'true' - - return self.get_object('CreateVpcPeeringConnection', params, - VpcPeeringConnection) - - def delete_vpc_peering_connection(self, vpc_peering_connection_id, dry_run=False): - """ - Deletes a VPC peering connection. Either the owner of the requester - VPC or the owner of the peer VPC can delete the VPC peering connection - if it's in the active state. The owner of the requester VPC can delete - a VPC peering connection in the pending-acceptance state. - - :type vpc_peering_connection_id: str - :param vpc_peering_connection_id: The ID of the VPC peering connection. - - :rtype: bool - :return: True if successful - """ - params = { - 'VpcPeeringConnectionId': vpc_peering_connection_id - } - - if dry_run: - params['DryRun'] = 'true' - return self.get_status('DeleteVpcPeeringConnection', params) - - def reject_vpc_peering_connection(self, vpc_peering_connection_id, dry_run=False): - """ - Rejects a VPC peering connection request. The VPC peering connection - must be in the pending-acceptance state. - - :type vpc_peering_connection_id: str - :param vpc_peering_connection_id: The ID of the VPC peering connection. - - :rtype: bool - :return: True if successful - """ - params = { - 'VpcPeeringConnectionId': vpc_peering_connection_id - } - - if dry_run: - params['DryRun'] = 'true' - return self.get_status('RejectVpcPeeringConnection', params) - - def accept_vpc_peering_connection(self, vpc_peering_connection_id, dry_run=False): - """ - Acceptss a VPC peering connection request. The VPC peering connection - must be in the pending-acceptance state. - - :type vpc_peering_connection_id: str - :param vpc_peering_connection_id: The ID of the VPC peering connection. - - :rtype: Accepted VpcPeeringConnection - :return: A :class:`boto.vpc.vpc_peering_connection.VpcPeeringConnection` object - """ - params = { - 'VpcPeeringConnectionId': vpc_peering_connection_id - } - - if dry_run: - params['DryRun'] = 'true' - - return self.get_object('AcceptVpcPeeringConnection', params, - VpcPeeringConnection) - diff --git a/awx/lib/site-packages/boto/vpc/customergateway.py b/awx/lib/site-packages/boto/vpc/customergateway.py deleted file mode 100644 index 8f19a81a56..0000000000 --- a/awx/lib/site-packages/boto/vpc/customergateway.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a Customer Gateway -""" - -from boto.ec2.ec2object import TaggedEC2Object - - -class CustomerGateway(TaggedEC2Object): - - def __init__(self, connection=None): - super(CustomerGateway, self).__init__(connection) - self.id = None - self.type = None - self.state = None - self.ip_address = None - self.bgp_asn = None - - def __repr__(self): - return 'CustomerGateway:%s' % self.id - - def endElement(self, name, value, connection): - if name == 'customerGatewayId': - self.id = value - elif name == 'ipAddress': - self.ip_address = value - elif name == 'type': - self.type = value - elif name == 'state': - self.state = value - elif name == 'bgpAsn': - self.bgp_asn = int(value) - else: - setattr(self, name, value) diff --git a/awx/lib/site-packages/boto/vpc/dhcpoptions.py b/awx/lib/site-packages/boto/vpc/dhcpoptions.py deleted file mode 100644 index 758d452ceb..0000000000 --- a/awx/lib/site-packages/boto/vpc/dhcpoptions.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a DHCP Options set -""" - -from boto.ec2.ec2object import TaggedEC2Object - -class DhcpValueSet(list): - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'value': - self.append(value) - -class DhcpConfigSet(dict): - - def startElement(self, name, attrs, connection): - if name == 'valueSet': - if self._name not in self: - self[self._name] = DhcpValueSet() - return self[self._name] - - def endElement(self, name, value, connection): - if name == 'key': - self._name = value - -class DhcpOptions(TaggedEC2Object): - - def __init__(self, connection=None): - super(DhcpOptions, self).__init__(connection) - self.id = None - self.options = None - - def __repr__(self): - return 'DhcpOptions:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(DhcpOptions, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'dhcpConfigurationSet': - self.options = DhcpConfigSet() - return self.options - - def endElement(self, name, value, connection): - if name == 'dhcpOptionsId': - self.id = value - else: - setattr(self, name, value) - diff --git a/awx/lib/site-packages/boto/vpc/internetgateway.py b/awx/lib/site-packages/boto/vpc/internetgateway.py deleted file mode 100644 index 09f1fe04e7..0000000000 --- a/awx/lib/site-packages/boto/vpc/internetgateway.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents an Internet Gateway -""" - -from boto.ec2.ec2object import TaggedEC2Object -from boto.resultset import ResultSet - -class InternetGateway(TaggedEC2Object): - def __init__(self, connection=None): - super(InternetGateway, self).__init__(connection) - self.id = None - self.attachments = [] - - def __repr__(self): - return 'InternetGateway:%s' % self.id - - def startElement(self, name, attrs, connection): - result = super(InternetGateway, self).startElement(name, attrs, connection) - - if result is not None: - # Parent found an interested element, just return it - return result - - if name == 'attachmentSet': - self.attachments = ResultSet([('item', InternetGatewayAttachment)]) - return self.attachments - else: - return None - - def endElement(self, name, value, connection): - if name == 'internetGatewayId': - self.id = value - else: - setattr(self, name, value) - -class InternetGatewayAttachment(object): - def __init__(self, connection=None): - self.vpc_id = None - self.state = None - - def __repr__(self): - return 'InternetGatewayAttachment:%s' % self.vpc_id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'vpcId': - self.vpc_id = value - elif name == 'state': - self.state = value diff --git a/awx/lib/site-packages/boto/vpc/networkacl.py b/awx/lib/site-packages/boto/vpc/networkacl.py deleted file mode 100644 index 9b8b1cddcf..0000000000 --- a/awx/lib/site-packages/boto/vpc/networkacl.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a Network ACL -""" - -from boto.ec2.ec2object import TaggedEC2Object -from boto.resultset import ResultSet - - -class Icmp(object): - """ - Defines the ICMP code and type. - """ - def __init__(self, connection=None): - self.code = None - self.type = None - - def __repr__(self): - return 'Icmp::code:%s, type:%s)' % ( self.code, self.type) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - - if name == 'code': - self.code = value - elif name == 'type': - self.type = value - -class NetworkAcl(TaggedEC2Object): - - def __init__(self, connection=None): - super(NetworkAcl, self).__init__(connection) - self.id = None - self.vpc_id = None - self.network_acl_entries = [] - self.associations = [] - - def __repr__(self): - return 'NetworkAcl:%s' % self.id - - def startElement(self, name, attrs, connection): - result = super(NetworkAcl, self).startElement(name, attrs, connection) - - if result is not None: - # Parent found an interested element, just return it - return result - - if name == 'entrySet': - self.network_acl_entries = ResultSet([('item', NetworkAclEntry)]) - return self.network_acl_entries - elif name == 'associationSet': - self.associations = ResultSet([('item', NetworkAclAssociation)]) - return self.associations - else: - return None - - def endElement(self, name, value, connection): - if name == 'networkAclId': - self.id = value - elif name == 'vpcId': - self.vpc_id = value - else: - setattr(self, name, value) - -class NetworkAclEntry(object): - def __init__(self, connection=None): - self.rule_number = None - self.protocol = None - self.rule_action = None - self.egress = None - self.cidr_block = None - self.port_range = PortRange() - self.icmp = Icmp() - - def __repr__(self): - return 'Acl:%s' % self.rule_number - - def startElement(self, name, attrs, connection): - - if name == 'portRange': - return self.port_range - elif name == 'icmpTypeCode': - return self.icmp - else: - return None - - def endElement(self, name, value, connection): - if name == 'cidrBlock': - self.cidr_block = value - elif name == 'egress': - self.egress = value - elif name == 'protocol': - self.protocol = value - elif name == 'ruleAction': - self.rule_action = value - elif name == 'ruleNumber': - self.rule_number = value - - -class NetworkAclAssociation(object): - def __init__(self, connection=None): - self.id = None - self.subnet_id = None - self.network_acl_id = None - - def __repr__(self): - return 'NetworkAclAssociation:%s' % self.id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'networkAclAssociationId': - self.id = value - elif name == 'networkAclId': - self.network_acl_id = value - elif name == 'subnetId': - self.subnet_id = value - -class PortRange(object): - """ - Define the port range for the ACL entry if it is tcp / udp - """ - - def __init__(self, connection=None): - self.from_port = None - self.to_port = None - - def __repr__(self): - return 'PortRange:(%s-%s)' % ( self.from_port, self.to_port) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - - if name == 'from': - self.from_port = value - elif name == 'to': - self.to_port = value - - diff --git a/awx/lib/site-packages/boto/vpc/routetable.py b/awx/lib/site-packages/boto/vpc/routetable.py deleted file mode 100644 index 21060ee945..0000000000 --- a/awx/lib/site-packages/boto/vpc/routetable.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a Route Table -""" - -from boto.ec2.ec2object import TaggedEC2Object -from boto.resultset import ResultSet - -class RouteTable(TaggedEC2Object): - - def __init__(self, connection=None): - super(RouteTable, self).__init__(connection) - self.id = None - self.vpc_id = None - self.routes = [] - self.associations = [] - - def __repr__(self): - return 'RouteTable:%s' % self.id - - def startElement(self, name, attrs, connection): - result = super(RouteTable, self).startElement(name, attrs, connection) - - if result is not None: - # Parent found an interested element, just return it - return result - - if name == 'routeSet': - self.routes = ResultSet([('item', Route)]) - return self.routes - elif name == 'associationSet': - self.associations = ResultSet([('item', RouteAssociation)]) - return self.associations - else: - return None - - def endElement(self, name, value, connection): - if name == 'routeTableId': - self.id = value - elif name == 'vpcId': - self.vpc_id = value - else: - setattr(self, name, value) - -class Route(object): - def __init__(self, connection=None): - self.destination_cidr_block = None - self.gateway_id = None - self.instance_id = None - self.interface_id = None - self.vpc_peering_connection_id = None - self.state = None - - def __repr__(self): - return 'Route:%s' % self.destination_cidr_block - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'destinationCidrBlock': - self.destination_cidr_block = value - elif name == 'gatewayId': - self.gateway_id = value - elif name == 'instanceId': - self.instance_id = value - elif name == 'networkInterfaceId': - self.interface_id = value - elif name == 'vpcPeeringConnectionId': - self.vpc_peering_connection_id = value - elif name == 'state': - self.state = value - -class RouteAssociation(object): - def __init__(self, connection=None): - self.id = None - self.route_table_id = None - self.subnet_id = None - self.main = False - - def __repr__(self): - return 'RouteAssociation:%s' % self.id - - def startElement(self, name, attrs, connection): - return None - - def endElement(self, name, value, connection): - if name == 'routeTableAssociationId': - self.id = value - elif name == 'routeTableId': - self.route_table_id = value - elif name == 'subnetId': - self.subnet_id = value - elif name == 'main': - self.main = value == 'true' diff --git a/awx/lib/site-packages/boto/vpc/subnet.py b/awx/lib/site-packages/boto/vpc/subnet.py deleted file mode 100644 index 4d6f902539..0000000000 --- a/awx/lib/site-packages/boto/vpc/subnet.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a Subnet -""" - -from boto.ec2.ec2object import TaggedEC2Object - -class Subnet(TaggedEC2Object): - - def __init__(self, connection=None): - super(Subnet, self).__init__(connection) - self.id = None - self.vpc_id = None - self.state = None - self.cidr_block = None - self.available_ip_address_count = 0 - self.availability_zone = None - - def __repr__(self): - return 'Subnet:%s' % self.id - - def endElement(self, name, value, connection): - if name == 'subnetId': - self.id = value - elif name == 'vpcId': - self.vpc_id = value - elif name == 'state': - self.state = value - elif name == 'cidrBlock': - self.cidr_block = value - elif name == 'availableIpAddressCount': - self.available_ip_address_count = int(value) - elif name == 'availabilityZone': - self.availability_zone = value - else: - setattr(self, name, value) - diff --git a/awx/lib/site-packages/boto/vpc/vpc.py b/awx/lib/site-packages/boto/vpc/vpc.py deleted file mode 100644 index 575a1c4570..0000000000 --- a/awx/lib/site-packages/boto/vpc/vpc.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a Virtual Private Cloud. -""" - -from boto.ec2.ec2object import TaggedEC2Object - -class VPC(TaggedEC2Object): - - def __init__(self, connection=None): - """ - Represents a VPC. - - :ivar id: The unique ID of the VPC. - :ivar dhcp_options_id: The ID of the set of DHCP options you've associated with the VPC - (or default if the default options are associated with the VPC). - :ivar state: The current state of the VPC. - :ivar cidr_block: The CIDR block for the VPC. - :ivar is_default: Indicates whether the VPC is the default VPC. - :ivar instance_tenancy: The allowed tenancy of instances launched into the VPC. - """ - super(VPC, self).__init__(connection) - self.id = None - self.dhcp_options_id = None - self.state = None - self.cidr_block = None - self.is_default = None - self.instance_tenancy = None - - def __repr__(self): - return 'VPC:%s' % self.id - - def endElement(self, name, value, connection): - if name == 'vpcId': - self.id = value - elif name == 'dhcpOptionsId': - self.dhcp_options_id = value - elif name == 'state': - self.state = value - elif name == 'cidrBlock': - self.cidr_block = value - elif name == 'isDefault': - self.is_default = True if value == 'true' else False - elif name == 'instanceTenancy': - self.instance_tenancy = value - else: - setattr(self, name, value) - - def delete(self): - return self.connection.delete_vpc(self.id) - - def _update(self, updated): - self.__dict__.update(updated.__dict__) - - def update(self, validate=False, dry_run=False): - vpc_list = self.connection.get_all_vpcs( - [self.id], - dry_run=dry_run - ) - if len(vpc_list): - updated_vpc = vpc_list[0] - self._update(updated_vpc) - elif validate: - raise ValueError('%s is not a valid VPC ID' % (self.id,)) - return self.state diff --git a/awx/lib/site-packages/boto/vpc/vpc_peering_connection.py b/awx/lib/site-packages/boto/vpc/vpc_peering_connection.py deleted file mode 100644 index cdb9af8dae..0000000000 --- a/awx/lib/site-packages/boto/vpc/vpc_peering_connection.py +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright (c) 2014 Skytap http://skytap.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a VPC Peering Connection. -""" - -from boto.ec2.ec2object import TaggedEC2Object - -class VpcInfo(object): - def __init__(self): - """ - Information on peer Vpc. - - :ivar id: The unique ID of peer Vpc. - :ivar owner_id: Owner of peer Vpc. - :ivar cidr_block: CIDR Block of peer Vpc. - """ - - self.vpc_id = None - self.owner_id = None - self.cidr_block = None - - def __repr__(self): - return 'VpcInfo:%s' % self.vpc_id - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'vpcId': - self.vpc_id = value - elif name == 'ownerId': - self.owner_id = value - elif name == 'cidrBlock': - self.cidr_block = value - else: - setattr(self, name, value) - -class VpcPeeringConnectionStatus(object): - """ - The status of VPC peering connection. - - :ivar code: The status of the VPC peering connection. Valid values are: - - * pending-acceptance - * failed - * expired - * provisioning - * active - * deleted - * rejected - - :ivar message: A message that provides more information about the status of the VPC peering connection, if applicable. - """ - def __init__(self, code=0, message=None): - self.code = code - self.message = message - - def __repr__(self): - return '%s(%d)' % (self.code, self.message) - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'code': - self.code = value - elif name == 'message': - self.message = value - else: - setattr(self, name, value) - - - -class VpcPeeringConnection(TaggedEC2Object): - - def __init__(self, connection=None): - """ - Represents a VPC peering connection. - - :ivar id: The unique ID of the VPC peering connection. - :ivar accepter_vpc_info: Information on peer Vpc. - :ivar requester_vpc_info: Information on requester Vpc. - :ivar expiration_time: The expiration date and time for the VPC peering connection. - :ivar status_code: The status of the VPC peering connection. - :ivar status_message: A message that provides more information about the status of the VPC peering connection, if applicable. - """ - super(VpcPeeringConnection, self).__init__(connection) - self.id = None - self.accepter_vpc_info = VpcInfo() - self.requester_vpc_info = VpcInfo() - self.expiration_time = None - self._status = VpcPeeringConnectionStatus() - - @property - def status_code(self): - return self._status.code - - @property - def status_message(self): - return self._status.message - - def __repr__(self): - return 'VpcPeeringConnection:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(VpcPeeringConnection, self).startElement(name, attrs, connection) - if retval is not None: - return retval - - if name == 'requesterVpcInfo': - return self.requester_vpc_info - elif name == 'accepterVpcInfo': - return self.accepter_vpc_info - elif name == 'status': - return self._status - - return None - - def endElement(self, name, value, connection): - if name == 'vpcPeeringConnectionId': - self.id = value - elif name == 'expirationTime': - self.expiration_time = value - else: - setattr(self, name, value) - - def delete(self): - return self.connection.delete_vpc_peering_connection(self.id) - - def _update(self, updated): - self.__dict__.update(updated.__dict__) - - def update(self, validate=False, dry_run=False): - vpc_peering_connection_list = self.connection.get_all_vpc_peering_connections( - [self.id], - dry_run=dry_run - ) - if len(vpc_peering_connection_list): - updated_vpc_peering_connection = vpc_peering_connection_list[0] - self._update(updated_vpc_peering_connection) - elif validate: - raise ValueError('%s is not a valid VpcPeeringConnection ID' % (self.id,)) - return self.status_code diff --git a/awx/lib/site-packages/boto/vpc/vpnconnection.py b/awx/lib/site-packages/boto/vpc/vpnconnection.py deleted file mode 100644 index cd8b11a62b..0000000000 --- a/awx/lib/site-packages/boto/vpc/vpnconnection.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -import boto -from datetime import datetime -from boto.resultset import ResultSet - -""" -Represents a VPN Connectionn -""" - -from boto.ec2.ec2object import TaggedEC2Object - -class VpnConnectionOptions(object): - """ - Represents VPN connection options - - :ivar static_routes_only: Indicates whether the VPN connection uses static - routes only. Static routes must be used for devices that don't support - BGP. - - """ - def __init__(self, static_routes_only=None): - self.static_routes_only = static_routes_only - - def __repr__(self): - return 'VpnConnectionOptions' - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'staticRoutesOnly': - self.static_routes_only = True if value == 'true' else False - else: - setattr(self, name, value) - -class VpnStaticRoute(object): - """ - Represents a static route for a VPN connection. - - :ivar destination_cidr_block: The CIDR block associated with the local - subnet of the customer data center. - :ivar source: Indicates how the routes were provided. - :ivar state: The current state of the static route. - """ - def __init__(self, destination_cidr_block=None, source=None, state=None): - self.destination_cidr_block = destination_cidr_block - self.source = source - self.available = state - - def __repr__(self): - return 'VpnStaticRoute: %s' % self.destination_cidr_block - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'destinationCidrBlock': - self.destination_cidr_block = value - elif name == 'source': - self.source = value - elif name == 'state': - self.state = value - else: - setattr(self, name, value) - -class VpnTunnel(object): - """ - Represents telemetry for a VPN tunnel - - :ivar outside_ip_address: The Internet-routable IP address of the - virtual private gateway's outside interface. - :ivar status: The status of the VPN tunnel. Valid values: UP | DOWN - :ivar last_status_change: The date and time of the last change in status. - :ivar status_message: If an error occurs, a description of the error. - :ivar accepted_route_count: The number of accepted routes. - """ - def __init__(self, outside_ip_address=None, status=None, last_status_change=None, - status_message=None, accepted_route_count=None): - self.outside_ip_address = outside_ip_address - self.status = status - self.last_status_change = last_status_change - self.status_message = status_message - self.accepted_route_count = accepted_route_count - - def __repr__(self): - return 'VpnTunnel: %s' % self.outside_ip_address - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'outsideIpAddress': - self.outside_ip_address = value - elif name == 'status': - self.status = value - elif name == 'lastStatusChange': - self.last_status_change = datetime.strptime(value, - '%Y-%m-%dT%H:%M:%S.%fZ') - elif name == 'statusMessage': - self.status_message = value - elif name == 'acceptedRouteCount': - try: - value = int(value) - except ValueError: - boto.log.warning('Error converting code (%s) to int' % value) - self.accepted_route_count = value - else: - setattr(self, name, value) - -class VpnConnection(TaggedEC2Object): - """ - Represents a VPN Connection - - :ivar id: The ID of the VPN connection. - :ivar state: The current state of the VPN connection. - Valid values: pending | available | deleting | deleted - :ivar customer_gateway_configuration: The configuration information for the - VPN connection's customer gateway (in the native XML format). This - element is always present in the - :class:`boto.vpc.VPCConnection.create_vpn_connection` response; - however, it's present in the - :class:`boto.vpc.VPCConnection.get_all_vpn_connections` response only - if the VPN connection is in the pending or available state. - :ivar type: The type of VPN connection (ipsec.1). - :ivar customer_gateway_id: The ID of the customer gateway at your end of - the VPN connection. - :ivar vpn_gateway_id: The ID of the virtual private gateway - at the AWS side of the VPN connection. - :ivar tunnels: A list of the vpn tunnels (always 2) - :ivar options: The option set describing the VPN connection. - :ivar static_routes: A list of static routes associated with a VPN - connection. - - """ - def __init__(self, connection=None): - super(VpnConnection, self).__init__(connection) - self.id = None - self.state = None - self.customer_gateway_configuration = None - self.type = None - self.customer_gateway_id = None - self.vpn_gateway_id = None - self.tunnels = [] - self.options = None - self.static_routes = [] - - def __repr__(self): - return 'VpnConnection:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(VpnConnection, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'vgwTelemetry': - self.tunnels = ResultSet([('item', VpnTunnel)]) - return self.tunnels - elif name == 'routes': - self.static_routes = ResultSet([('item', VpnStaticRoute)]) - return self.static_routes - elif name == 'options': - self.options = VpnConnectionOptions() - return self.options - return None - - def endElement(self, name, value, connection): - if name == 'vpnConnectionId': - self.id = value - elif name == 'state': - self.state = value - elif name == 'customerGatewayConfiguration': - self.customer_gateway_configuration = value - elif name == 'type': - self.type = value - elif name == 'customerGatewayId': - self.customer_gateway_id = value - elif name == 'vpnGatewayId': - self.vpn_gateway_id = value - else: - setattr(self, name, value) - - def delete(self, dry_run=False): - return self.connection.delete_vpn_connection( - self.id, - dry_run=dry_run - ) diff --git a/awx/lib/site-packages/boto/vpc/vpngateway.py b/awx/lib/site-packages/boto/vpc/vpngateway.py deleted file mode 100644 index 80598109c3..0000000000 --- a/awx/lib/site-packages/boto/vpc/vpngateway.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/ -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -""" -Represents a Vpn Gateway -""" - -from boto.ec2.ec2object import TaggedEC2Object - -class Attachment(object): - - def __init__(self, connection=None): - self.vpc_id = None - self.state = None - - def startElement(self, name, attrs, connection): - pass - - def endElement(self, name, value, connection): - if name == 'vpcId': - self.vpc_id = value - elif name == 'state': - self.state = value - else: - setattr(self, name, value) - -class VpnGateway(TaggedEC2Object): - - def __init__(self, connection=None): - super(VpnGateway, self).__init__(connection) - self.id = None - self.type = None - self.state = None - self.availability_zone = None - self.attachments = [] - - def __repr__(self): - return 'VpnGateway:%s' % self.id - - def startElement(self, name, attrs, connection): - retval = super(VpnGateway, self).startElement(name, attrs, connection) - if retval is not None: - return retval - if name == 'item': - att = Attachment() - self.attachments.append(att) - return att - - def endElement(self, name, value, connection): - if name == 'vpnGatewayId': - self.id = value - elif name == 'type': - self.type = value - elif name == 'state': - self.state = value - elif name == 'availabilityZone': - self.availability_zone = value - elif name == 'attachments': - pass - else: - setattr(self, name, value) - - def attach(self, vpc_id, dry_run=False): - return self.connection.attach_vpn_gateway( - self.id, - vpc_id, - dry_run=dry_run - ) - diff --git a/awx/lib/site-packages/celery/__init__.py b/awx/lib/site-packages/celery/__init__.py deleted file mode 100644 index 489b6b4e11..0000000000 --- a/awx/lib/site-packages/celery/__init__.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding: utf-8 -*- -"""Distributed Task Queue""" -# :copyright: (c) 2009 - 2012 Ask Solem and individual contributors, -# All rights reserved. -# :copyright: (c) 2012-2013 GoPivotal, Inc., All rights reserved. -# :license: BSD (3 Clause), see LICENSE for more details. - -from __future__ import absolute_import - -from collections import namedtuple - -version_info_t = namedtuple( - 'version_info_t', ('major', 'minor', 'micro', 'releaselevel', 'serial'), -) - -SERIES = 'Cipater' -VERSION = version_info_t(3, 1, 10, '', '') -__version__ = '{0.major}.{0.minor}.{0.micro}{0.releaselevel}'.format(VERSION) -__author__ = 'Ask Solem' -__contact__ = 'ask@celeryproject.org' -__homepage__ = 'http://celeryproject.org' -__docformat__ = 'restructuredtext' -__all__ = [ - 'Celery', 'bugreport', 'shared_task', 'task', - 'current_app', 'current_task', 'maybe_signature', - 'chain', 'chord', 'chunks', 'group', 'signature', - 'xmap', 'xstarmap', 'uuid', 'version', '__version__', -] -VERSION_BANNER = '{0} ({1})'.format(__version__, SERIES) - -# -eof meta- - -import os -import sys -if os.environ.get('C_IMPDEBUG'): # pragma: no cover - from .five import builtins - real_import = builtins.__import__ - - def debug_import(name, locals=None, globals=None, - fromlist=None, level=-1): - glob = globals or getattr(sys, 'emarfteg_'[::-1])(1).f_globals - importer_name = glob and glob.get('__name__') or 'unknown' - print('-- {0} imports {1}'.format(importer_name, name)) - return real_import(name, locals, globals, fromlist, level) - builtins.__import__ = debug_import - -# This is never executed, but tricks static analyzers (PyDev, PyCharm, -# pylint, etc.) into knowing the types of these symbols, and what -# they contain. -STATICA_HACK = True -globals()['kcah_acitats'[::-1].upper()] = False -if STATICA_HACK: # pragma: no cover - from celery.app import shared_task # noqa - from celery.app.base import Celery # noqa - from celery.app.utils import bugreport # noqa - from celery.app.task import Task # noqa - from celery._state import current_app, current_task # noqa - from celery.canvas import ( # noqa - chain, chord, chunks, group, - signature, maybe_signature, xmap, xstarmap, subtask, - ) - from celery.utils import uuid # noqa - -# Eventlet/gevent patching must happen before importing -# anything else, so these tools must be at top-level. - - -def _find_option_with_arg(argv, short_opts=None, long_opts=None): - """Search argv for option specifying its short and longopt - alternatives. - - Return the value of the option if found. - - """ - for i, arg in enumerate(argv): - if arg.startswith('-'): - if long_opts and arg.startswith('--'): - name, _, val = arg.partition('=') - if name in long_opts: - return val - if short_opts and arg in short_opts: - return argv[i + 1] - raise KeyError('|'.join(short_opts or [] + long_opts or [])) - - -def _patch_eventlet(): - import eventlet - import eventlet.debug - eventlet.monkey_patch() - EVENTLET_DBLOCK = int(os.environ.get('EVENTLET_NOBLOCK', 0)) - if EVENTLET_DBLOCK: - eventlet.debug.hub_blocking_detection(EVENTLET_DBLOCK) - - -def _patch_gevent(): - from gevent import monkey, version_info - monkey.patch_all() - if version_info[0] == 0: # pragma: no cover - # Signals aren't working in gevent versions <1.0, - # and are not monkey patched by patch_all() - from gevent import signal as _gevent_signal - _signal = __import__('signal') - _signal.signal = _gevent_signal - - -def maybe_patch_concurrency(argv=sys.argv, - short_opts=['-P'], long_opts=['--pool'], - patches={'eventlet': _patch_eventlet, - 'gevent': _patch_gevent}): - """With short and long opt alternatives that specify the command line - option to set the pool, this makes sure that anything that needs - to be patched is completed as early as possible. - (e.g. eventlet/gevent monkey patches).""" - try: - pool = _find_option_with_arg(argv, short_opts, long_opts) - except KeyError: - pass - else: - try: - patcher = patches[pool] - except KeyError: - pass - else: - patcher() - # set up eventlet/gevent environments ASAP. - from celery import concurrency - concurrency.get_implementation(pool) - -# Lazy loading -from .five import recreate_module - -old_module, new_module = recreate_module( # pragma: no cover - __name__, - by_module={ - 'celery.app': ['Celery', 'bugreport', 'shared_task'], - 'celery.app.task': ['Task'], - 'celery._state': ['current_app', 'current_task'], - 'celery.canvas': ['chain', 'chord', 'chunks', 'group', - 'signature', 'maybe_signature', 'subtask', - 'xmap', 'xstarmap'], - 'celery.utils': ['uuid'], - }, - direct={'task': 'celery.task'}, - __package__='celery', __file__=__file__, - __path__=__path__, __doc__=__doc__, __version__=__version__, - __author__=__author__, __contact__=__contact__, - __homepage__=__homepage__, __docformat__=__docformat__, - VERSION=VERSION, SERIES=SERIES, VERSION_BANNER=VERSION_BANNER, - maybe_patch_concurrency=maybe_patch_concurrency, - _find_option_with_arg=_find_option_with_arg, -) diff --git a/awx/lib/site-packages/celery/__main__.py b/awx/lib/site-packages/celery/__main__.py deleted file mode 100644 index 04448e239b..0000000000 --- a/awx/lib/site-packages/celery/__main__.py +++ /dev/null @@ -1,54 +0,0 @@ -from __future__ import absolute_import - -import sys - -from os.path import basename - -from . import maybe_patch_concurrency - -__all__ = ['main'] - -DEPRECATED_FMT = """ -The {old!r} command is deprecated, please use {new!r} instead: - -$ {new_argv} - -""" - - -def _warn_deprecated(new): - print(DEPRECATED_FMT.format( - old=basename(sys.argv[0]), new=new, - new_argv=' '.join([new] + sys.argv[1:])), - ) - - -def main(): - if 'multi' not in sys.argv: - maybe_patch_concurrency() - from celery.bin.celery import main - main() - - -def _compat_worker(): - maybe_patch_concurrency() - _warn_deprecated('celery worker') - from celery.bin.worker import main - main() - - -def _compat_multi(): - _warn_deprecated('celery multi') - from celery.bin.multi import main - main() - - -def _compat_beat(): - maybe_patch_concurrency() - _warn_deprecated('celery beat') - from celery.bin.beat import main - main() - - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/_state.py b/awx/lib/site-packages/celery/_state.py deleted file mode 100644 index 3af39bf919..0000000000 --- a/awx/lib/site-packages/celery/_state.py +++ /dev/null @@ -1,137 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery._state - ~~~~~~~~~~~~~~~ - - This is an internal module containing thread state - like the ``current_app``, and ``current_task``. - - This module shouldn't be used directly. - -""" -from __future__ import absolute_import, print_function - -import os -import sys -import threading -import weakref - -from celery.local import Proxy -from celery.utils.threads import LocalStack - -try: - from weakref import WeakSet as AppSet -except ImportError: # XXX Py2.6 - - class AppSet(object): # noqa - - def __init__(self): - self._refs = set() - - def add(self, app): - self._refs.add(weakref.ref(app)) - - def __iter__(self): - dirty = [] - try: - for appref in self._refs: - app = appref() - if app is None: - dirty.append(appref) - else: - yield app - finally: - while dirty: - self._refs.discard(dirty.pop()) - -__all__ = ['set_default_app', 'get_current_app', 'get_current_task', - 'get_current_worker_task', 'current_app', 'current_task'] - -#: Global default app used when no current app. -default_app = None - -#: List of all app instances (weakrefs), must not be used directly. -_apps = AppSet() - -_task_join_will_block = False - - -def _set_task_join_will_block(blocks): - global _task_join_will_block - _task_join_will_block = blocks - - -def task_join_will_block(): - return _task_join_will_block - - -class _TLS(threading.local): - #: Apps with the :attr:`~celery.app.base.BaseApp.set_as_current` attribute - #: sets this, so it will always contain the last instantiated app, - #: and is the default app returned by :func:`app_or_default`. - current_app = None -_tls = _TLS() - -_task_stack = LocalStack() - - -def set_default_app(app): - global default_app - default_app = app - - -def _get_current_app(): - if default_app is None: - #: creates the global fallback app instance. - from celery.app import Celery - set_default_app(Celery( - 'default', - loader=os.environ.get('CELERY_LOADER') or 'default', - fixups=[], - set_as_current=False, accept_magic_kwargs=True, - )) - return _tls.current_app or default_app - -C_STRICT_APP = os.environ.get('C_STRICT_APP') -if os.environ.get('C_STRICT_APP'): # pragma: no cover - def get_current_app(): - raise Exception('USES CURRENT APP') - import traceback - print('-- USES CURRENT_APP', file=sys.stderr) # noqa+ - traceback.print_stack(file=sys.stderr) - return _get_current_app() -else: - get_current_app = _get_current_app - - -def get_current_task(): - """Currently executing task.""" - return _task_stack.top - - -def get_current_worker_task(): - """Currently executing task, that was applied by the worker. - - This is used to differentiate between the actual task - executed by the worker and any task that was called within - a task (using ``task.__call__`` or ``task.apply``) - - """ - for task in reversed(_task_stack.stack): - if not task.request.called_directly: - return task - - -#: Proxy to current app. -current_app = Proxy(get_current_app) - -#: Proxy to current task. -current_task = Proxy(get_current_task) - - -def _register_app(app): - _apps.add(app) - - -def _get_active_apps(): - return _apps diff --git a/awx/lib/site-packages/celery/app/__init__.py b/awx/lib/site-packages/celery/app/__init__.py deleted file mode 100644 index 426fed6ce8..0000000000 --- a/awx/lib/site-packages/celery/app/__init__.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app - ~~~~~~~~~~ - - Celery Application. - -""" -from __future__ import absolute_import - -import os - -from celery.local import Proxy -from celery import _state -from celery._state import ( - set_default_app, - get_current_app as current_app, - get_current_task as current_task, - _get_active_apps, - _task_stack, -) -from celery.utils import gen_task_name - -from .builtins import shared_task as _shared_task -from .base import Celery, AppPickler - -__all__ = ['Celery', 'AppPickler', 'default_app', 'app_or_default', - 'bugreport', 'enable_trace', 'disable_trace', 'shared_task', - 'set_default_app', 'current_app', 'current_task', - 'push_current_task', 'pop_current_task'] - -#: Proxy always returning the app set as default. -default_app = Proxy(lambda: _state.default_app) - -#: Function returning the app provided or the default app if none. -#: -#: The environment variable :envvar:`CELERY_TRACE_APP` is used to -#: trace app leaks. When enabled an exception is raised if there -#: is no active app. -app_or_default = None - -#: The 'default' loader is the default loader used by old applications. -#: This is deprecated and should no longer be used as it's set too early -#: to be affected by --loader argument. -default_loader = os.environ.get('CELERY_LOADER') or 'default' # XXX - - -#: Function used to push a task to the thread local stack -#: keeping track of the currently executing task. -#: You must remember to pop the task after. -push_current_task = _task_stack.push - -#: Function used to pop a task from the thread local stack -#: keeping track of the currently executing task. -pop_current_task = _task_stack.pop - - -def bugreport(app=None): - return (app or current_app()).bugreport() - - -def _app_or_default(app=None): - if app is None: - return _state.get_current_app() - return app - - -def _app_or_default_trace(app=None): # pragma: no cover - from traceback import print_stack - from billiard import current_process - if app is None: - if getattr(_state._tls, 'current_app', None): - print('-- RETURNING TO CURRENT APP --') # noqa+ - print_stack() - return _state._tls.current_app - if current_process()._name == 'MainProcess': - raise Exception('DEFAULT APP') - print('-- RETURNING TO DEFAULT APP --') # noqa+ - print_stack() - return _state.default_app - return app - - -def enable_trace(): - global app_or_default - app_or_default = _app_or_default_trace - - -def disable_trace(): - global app_or_default - app_or_default = _app_or_default - -if os.environ.get('CELERY_TRACE_APP'): # pragma: no cover - enable_trace() -else: - disable_trace() - -App = Celery # XXX Compat - - -def shared_task(*args, **kwargs): - """Create shared tasks (decorator). - Will return a proxy that always takes the task from the current apps - task registry. - - This can be used by library authors to create tasks that will work - for any app environment. - - Example: - - >>> from celery import Celery, shared_task - >>> @shared_task - ... def add(x, y): - ... return x + y - - >>> app1 = Celery(broker='amqp://') - >>> add.app is app1 - True - - >>> app2 = Celery(broker='redis://') - >>> add.app is app2 - - """ - - def create_shared_task(**options): - - def __inner(fun): - name = options.get('name') - # Set as shared task so that unfinalized apps, - # and future apps will load the task. - _shared_task(lambda app: app._task_from_fun(fun, **options)) - - # Force all finalized apps to take this task as well. - for app in _get_active_apps(): - if app.finalized: - with app._finalize_mutex: - app._task_from_fun(fun, **options) - - # Return a proxy that always gets the task from the current - # apps task registry. - def task_by_cons(): - app = current_app() - return app.tasks[ - name or gen_task_name(app, fun.__name__, fun.__module__) - ] - return Proxy(task_by_cons) - return __inner - - if len(args) == 1 and callable(args[0]): - return create_shared_task(**kwargs)(args[0]) - return create_shared_task(*args, **kwargs) diff --git a/awx/lib/site-packages/celery/app/amqp.py b/awx/lib/site-packages/celery/app/amqp.py deleted file mode 100644 index b0dae95e02..0000000000 --- a/awx/lib/site-packages/celery/app/amqp.py +++ /dev/null @@ -1,499 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.amqp - ~~~~~~~~~~~~~~~ - - Sending and receiving messages using Kombu. - -""" -from __future__ import absolute_import - -import numbers - -from datetime import timedelta -from weakref import WeakValueDictionary - -from kombu import Connection, Consumer, Exchange, Producer, Queue -from kombu.common import Broadcast -from kombu.pools import ProducerPool -from kombu.utils import cached_property, uuid -from kombu.utils.encoding import safe_repr -from kombu.utils.functional import maybe_list - -from celery import signals -from celery.five import items, string_t -from celery.utils.text import indent as textindent -from celery.utils.timeutils import to_utc - -from . import app_or_default -from . import routes as _routes - -__all__ = ['AMQP', 'Queues', 'TaskProducer', 'TaskConsumer'] - -#: Human readable queue declaration. -QUEUE_FORMAT = """ -.> {0.name:<16} exchange={0.exchange.name}({0.exchange.type}) \ -key={0.routing_key} -""" - - -class Queues(dict): - """Queue name⇒ declaration mapping. - - :param queues: Initial list/tuple or dict of queues. - :keyword create_missing: By default any unknown queues will be - added automatically, but if disabled - the occurrence of unknown queues - in `wanted` will raise :exc:`KeyError`. - :keyword ha_policy: Default HA policy for queues with none set. - - - """ - #: If set, this is a subset of queues to consume from. - #: The rest of the queues are then used for routing only. - _consume_from = None - - def __init__(self, queues=None, default_exchange=None, - create_missing=True, ha_policy=None, autoexchange=None): - dict.__init__(self) - self.aliases = WeakValueDictionary() - self.default_exchange = default_exchange - self.create_missing = create_missing - self.ha_policy = ha_policy - self.autoexchange = Exchange if autoexchange is None else autoexchange - if isinstance(queues, (tuple, list)): - queues = dict((q.name, q) for q in queues) - for name, q in items(queues or {}): - self.add(q) if isinstance(q, Queue) else self.add_compat(name, **q) - - def __getitem__(self, name): - try: - return self.aliases[name] - except KeyError: - return dict.__getitem__(self, name) - - def __setitem__(self, name, queue): - if self.default_exchange and (not queue.exchange or - not queue.exchange.name): - queue.exchange = self.default_exchange - dict.__setitem__(self, name, queue) - if queue.alias: - self.aliases[queue.alias] = queue - - def __missing__(self, name): - if self.create_missing: - return self.add(self.new_missing(name)) - raise KeyError(name) - - def add(self, queue, **kwargs): - """Add new queue. - - The first argument can either be a :class:`kombu.Queue` instance, - or the name of a queue. If the former the rest of the keyword - arguments are ignored, and options are simply taken from the queue - instance. - - :param queue: :class:`kombu.Queue` instance or name of the queue. - :keyword exchange: (if named) specifies exchange name. - :keyword routing_key: (if named) specifies binding key. - :keyword exchange_type: (if named) specifies type of exchange. - :keyword \*\*options: (if named) Additional declaration options. - - """ - if not isinstance(queue, Queue): - return self.add_compat(queue, **kwargs) - if self.ha_policy: - if queue.queue_arguments is None: - queue.queue_arguments = {} - self._set_ha_policy(queue.queue_arguments) - self[queue.name] = queue - return queue - - def add_compat(self, name, **options): - # docs used to use binding_key as routing key - options.setdefault('routing_key', options.get('binding_key')) - if options['routing_key'] is None: - options['routing_key'] = name - if self.ha_policy is not None: - self._set_ha_policy(options.setdefault('queue_arguments', {})) - q = self[name] = Queue.from_dict(name, **options) - return q - - def _set_ha_policy(self, args): - policy = self.ha_policy - if isinstance(policy, (list, tuple)): - return args.update({'x-ha-policy': 'nodes', - 'x-ha-policy-params': list(policy)}) - args['x-ha-policy'] = policy - - def format(self, indent=0, indent_first=True): - """Format routing table into string for log dumps.""" - active = self.consume_from - if not active: - return '' - info = [QUEUE_FORMAT.strip().format(q) - for _, q in sorted(items(active))] - if indent_first: - return textindent('\n'.join(info), indent) - return info[0] + '\n' + textindent('\n'.join(info[1:]), indent) - - def select_add(self, queue, **kwargs): - """Add new task queue that will be consumed from even when - a subset has been selected using the :option:`-Q` option.""" - q = self.add(queue, **kwargs) - if self._consume_from is not None: - self._consume_from[q.name] = q - return q - - def select(self, include): - """Sets :attr:`consume_from` by selecting a subset of the - currently defined queues. - - :param include: Names of queues to consume from. - Can be iterable or string. - """ - if include: - self._consume_from = dict((name, self[name]) - for name in maybe_list(include)) - select_subset = select # XXX compat - - def deselect(self, exclude): - """Deselect queues so that they will not be consumed from. - - :param exclude: Names of queues to avoid consuming from. - Can be iterable or string. - - """ - if exclude: - exclude = maybe_list(exclude) - if self._consume_from is None: - # using selection - return self.select(k for k in self if k not in exclude) - # using all queues - for queue in exclude: - self._consume_from.pop(queue, None) - select_remove = deselect # XXX compat - - def new_missing(self, name): - return Queue(name, self.autoexchange(name), name) - - @property - def consume_from(self): - if self._consume_from is not None: - return self._consume_from - return self - - -class TaskProducer(Producer): - app = None - auto_declare = False - retry = False - retry_policy = None - utc = True - event_dispatcher = None - send_sent_event = False - - def __init__(self, channel=None, exchange=None, *args, **kwargs): - self.retry = kwargs.pop('retry', self.retry) - self.retry_policy = kwargs.pop('retry_policy', - self.retry_policy or {}) - self.send_sent_event = kwargs.pop('send_sent_event', - self.send_sent_event) - exchange = exchange or self.exchange - self.queues = self.app.amqp.queues # shortcut - self.default_queue = self.app.amqp.default_queue - super(TaskProducer, self).__init__(channel, exchange, *args, **kwargs) - - def publish_task(self, task_name, task_args=None, task_kwargs=None, - countdown=None, eta=None, task_id=None, group_id=None, - taskset_id=None, # compat alias to group_id - expires=None, exchange=None, exchange_type=None, - event_dispatcher=None, retry=None, retry_policy=None, - queue=None, now=None, retries=0, chord=None, - callbacks=None, errbacks=None, routing_key=None, - serializer=None, delivery_mode=None, compression=None, - reply_to=None, time_limit=None, soft_time_limit=None, - declare=None, headers=None, - send_before_publish=signals.before_task_publish.send, - before_receivers=signals.before_task_publish.receivers, - send_after_publish=signals.after_task_publish.send, - after_receivers=signals.after_task_publish.receivers, - send_task_sent=signals.task_sent.send, # XXX deprecated - sent_receivers=signals.task_sent.receivers, - **kwargs): - """Send task message.""" - retry = self.retry if retry is None else retry - headers = {} if headers is None else headers - - qname = queue - if queue is None and exchange is None: - queue = self.default_queue - if queue is not None: - if isinstance(queue, string_t): - qname, queue = queue, self.queues[queue] - else: - qname = queue.name - exchange = exchange or queue.exchange.name - routing_key = routing_key or queue.routing_key - if declare is None and queue and not isinstance(queue, Broadcast): - declare = [queue] - - # merge default and custom policy - retry = self.retry if retry is None else retry - _rp = (dict(self.retry_policy, **retry_policy) if retry_policy - else self.retry_policy) - task_id = task_id or uuid() - task_args = task_args or [] - task_kwargs = task_kwargs or {} - if not isinstance(task_args, (list, tuple)): - raise ValueError('task args must be a list or tuple') - if not isinstance(task_kwargs, dict): - raise ValueError('task kwargs must be a dictionary') - if countdown: # Convert countdown to ETA. - now = now or self.app.now() - eta = now + timedelta(seconds=countdown) - if self.utc: - eta = to_utc(eta).astimezone(self.app.timezone) - if isinstance(expires, numbers.Real): - now = now or self.app.now() - expires = now + timedelta(seconds=expires) - if self.utc: - expires = to_utc(expires).astimezone(self.app.timezone) - eta = eta and eta.isoformat() - expires = expires and expires.isoformat() - - body = { - 'task': task_name, - 'id': task_id, - 'args': task_args, - 'kwargs': task_kwargs, - 'retries': retries or 0, - 'eta': eta, - 'expires': expires, - 'utc': self.utc, - 'callbacks': callbacks, - 'errbacks': errbacks, - 'timelimit': (time_limit, soft_time_limit), - 'taskset': group_id or taskset_id, - 'chord': chord, - } - - if before_receivers: - send_before_publish( - sender=task_name, body=body, - exchange=exchange, - routing_key=routing_key, - declare=declare, - headers=headers, - properties=kwargs, - retry_policy=retry_policy, - ) - - self.publish( - body, - exchange=exchange, routing_key=routing_key, - serializer=serializer or self.serializer, - compression=compression or self.compression, - headers=headers, - retry=retry, retry_policy=_rp, - reply_to=reply_to, - correlation_id=task_id, - delivery_mode=delivery_mode, declare=declare, - **kwargs - ) - - if after_receivers: - send_after_publish(sender=task_name, body=body, - exchange=exchange, routing_key=routing_key) - - if sent_receivers: # XXX deprecated - send_task_sent(sender=task_name, task_id=task_id, - task=task_name, args=task_args, - kwargs=task_kwargs, eta=eta, - taskset=group_id or taskset_id) - if self.send_sent_event: - evd = event_dispatcher or self.event_dispatcher - exname = exchange or self.exchange - if isinstance(exname, Exchange): - exname = exname.name - evd.publish( - 'task-sent', - { - 'uuid': task_id, - 'name': task_name, - 'args': safe_repr(task_args), - 'kwargs': safe_repr(task_kwargs), - 'retries': retries, - 'eta': eta, - 'expires': expires, - 'queue': qname, - 'exchange': exname, - 'routing_key': routing_key, - }, - self, retry=retry, retry_policy=retry_policy, - ) - return task_id - delay_task = publish_task # XXX Compat - - @cached_property - def event_dispatcher(self): - # We call Dispatcher.publish with a custom producer - # so don't need the dispatcher to be "enabled". - return self.app.events.Dispatcher(enabled=False) - - -class TaskPublisher(TaskProducer): - """Deprecated version of :class:`TaskProducer`.""" - - def __init__(self, channel=None, exchange=None, *args, **kwargs): - self.app = app_or_default(kwargs.pop('app', self.app)) - self.retry = kwargs.pop('retry', self.retry) - self.retry_policy = kwargs.pop('retry_policy', - self.retry_policy or {}) - exchange = exchange or self.exchange - if not isinstance(exchange, Exchange): - exchange = Exchange(exchange, - kwargs.pop('exchange_type', 'direct')) - self.queues = self.app.amqp.queues # shortcut - super(TaskPublisher, self).__init__(channel, exchange, *args, **kwargs) - - -class TaskConsumer(Consumer): - app = None - - def __init__(self, channel, queues=None, app=None, accept=None, **kw): - self.app = app or self.app - if accept is None: - accept = self.app.conf.CELERY_ACCEPT_CONTENT - super(TaskConsumer, self).__init__( - channel, - queues or list(self.app.amqp.queues.consume_from.values()), - accept=accept, - **kw - ) - - -class AMQP(object): - Connection = Connection - Consumer = Consumer - - #: compat alias to Connection - BrokerConnection = Connection - - producer_cls = TaskProducer - consumer_cls = TaskConsumer - queues_cls = Queues - - #: Cached and prepared routing table. - _rtable = None - - #: Underlying producer pool instance automatically - #: set by the :attr:`producer_pool`. - _producer_pool = None - - # Exchange class/function used when defining automatic queues. - # E.g. you can use ``autoexchange = lambda n: None`` to use the - # amqp default exchange, which is a shortcut to bypass routing - # and instead send directly to the queue named in the routing key. - autoexchange = None - - def __init__(self, app): - self.app = app - - def flush_routes(self): - self._rtable = _routes.prepare(self.app.conf.CELERY_ROUTES) - - def Queues(self, queues, create_missing=None, ha_policy=None, - autoexchange=None): - """Create new :class:`Queues` instance, using queue defaults - from the current configuration.""" - conf = self.app.conf - if create_missing is None: - create_missing = conf.CELERY_CREATE_MISSING_QUEUES - if ha_policy is None: - ha_policy = conf.CELERY_QUEUE_HA_POLICY - if not queues and conf.CELERY_DEFAULT_QUEUE: - queues = (Queue(conf.CELERY_DEFAULT_QUEUE, - exchange=self.default_exchange, - routing_key=conf.CELERY_DEFAULT_ROUTING_KEY), ) - autoexchange = (self.autoexchange if autoexchange is None - else autoexchange) - return self.queues_cls( - queues, self.default_exchange, create_missing, - ha_policy, autoexchange, - ) - - def Router(self, queues=None, create_missing=None): - """Return the current task router.""" - return _routes.Router(self.routes, queues or self.queues, - self.app.either('CELERY_CREATE_MISSING_QUEUES', - create_missing), app=self.app) - - @cached_property - def TaskConsumer(self): - """Return consumer configured to consume from the queues - we are configured for (``app.amqp.queues.consume_from``).""" - return self.app.subclass_with_self(self.consumer_cls, - reverse='amqp.TaskConsumer') - get_task_consumer = TaskConsumer # XXX compat - - @cached_property - def TaskProducer(self): - """Return publisher used to send tasks. - - You should use `app.send_task` instead. - - """ - conf = self.app.conf - return self.app.subclass_with_self( - self.producer_cls, - reverse='amqp.TaskProducer', - exchange=self.default_exchange, - routing_key=conf.CELERY_DEFAULT_ROUTING_KEY, - serializer=conf.CELERY_TASK_SERIALIZER, - compression=conf.CELERY_MESSAGE_COMPRESSION, - retry=conf.CELERY_TASK_PUBLISH_RETRY, - retry_policy=conf.CELERY_TASK_PUBLISH_RETRY_POLICY, - send_sent_event=conf.CELERY_SEND_TASK_SENT_EVENT, - utc=conf.CELERY_ENABLE_UTC, - ) - TaskPublisher = TaskProducer # compat - - @cached_property - def default_queue(self): - return self.queues[self.app.conf.CELERY_DEFAULT_QUEUE] - - @cached_property - def queues(self): - """Queue name⇒ declaration mapping.""" - return self.Queues(self.app.conf.CELERY_QUEUES) - - @queues.setter # noqa - def queues(self, queues): - return self.Queues(queues) - - @property - def routes(self): - if self._rtable is None: - self.flush_routes() - return self._rtable - - @cached_property - def router(self): - return self.Router() - - @property - def producer_pool(self): - if self._producer_pool is None: - self._producer_pool = ProducerPool( - self.app.pool, - limit=self.app.pool.limit, - Producer=self.TaskProducer, - ) - return self._producer_pool - publisher_pool = producer_pool # compat alias - - @cached_property - def default_exchange(self): - return Exchange(self.app.conf.CELERY_DEFAULT_EXCHANGE, - self.app.conf.CELERY_DEFAULT_EXCHANGE_TYPE) diff --git a/awx/lib/site-packages/celery/app/annotations.py b/awx/lib/site-packages/celery/app/annotations.py deleted file mode 100644 index 62ee2e72e0..0000000000 --- a/awx/lib/site-packages/celery/app/annotations.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.annotations - ~~~~~~~~~~~~~~~~~~~~~~ - - Annotations is a nice term for moneky patching - task classes in the configuration. - - This prepares and performs the annotations in the - :setting:`CELERY_ANNOTATIONS` setting. - -""" -from __future__ import absolute_import - -from celery.five import string_t -from celery.utils.functional import firstmethod, mlazy -from celery.utils.imports import instantiate - -_first_match = firstmethod('annotate') -_first_match_any = firstmethod('annotate_any') - -__all__ = ['MapAnnotation', 'prepare', 'resolve_all'] - - -class MapAnnotation(dict): - - def annotate_any(self): - try: - return dict(self['*']) - except KeyError: - pass - - def annotate(self, task): - try: - return dict(self[task.name]) - except KeyError: - pass - - -def prepare(annotations): - """Expands the :setting:`CELERY_ANNOTATIONS` setting.""" - - def expand_annotation(annotation): - if isinstance(annotation, dict): - return MapAnnotation(annotation) - elif isinstance(annotation, string_t): - return mlazy(instantiate, annotation) - return annotation - - if annotations is None: - return () - elif not isinstance(annotations, (list, tuple)): - annotations = (annotations, ) - return [expand_annotation(anno) for anno in annotations] - - -def resolve_all(anno, task): - return (x for x in (_first_match(anno, task), _first_match_any(anno)) if x) diff --git a/awx/lib/site-packages/celery/app/base.py b/awx/lib/site-packages/celery/app/base.py deleted file mode 100644 index 153a5575a2..0000000000 --- a/awx/lib/site-packages/celery/app/base.py +++ /dev/null @@ -1,646 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.base - ~~~~~~~~~~~~~~~ - - Actual App instance implementation. - -""" -from __future__ import absolute_import - -import os -import threading -import warnings - -from collections import defaultdict, deque -from contextlib import contextmanager -from copy import deepcopy -from operator import attrgetter - -from amqp import promise -from billiard.util import register_after_fork -from kombu.clocks import LamportClock -from kombu.common import oid_from -from kombu.utils import cached_property, uuid - -from celery import platforms -from celery import signals -from celery._state import ( - _task_stack, _tls, get_current_app, set_default_app, - _register_app, get_current_worker_task, -) -from celery.exceptions import AlwaysEagerIgnored, ImproperlyConfigured -from celery.five import items, values -from celery.loaders import get_loader_cls -from celery.local import PromiseProxy, maybe_evaluate -from celery.utils.functional import first, maybe_list -from celery.utils.imports import instantiate, symbol_by_name -from celery.utils.objects import mro_lookup - -from .annotations import prepare as prepare_annotations -from .builtins import shared_task, load_shared_tasks -from .defaults import DEFAULTS, find_deprecated_settings -from .registry import TaskRegistry -from .utils import ( - AppPickler, Settings, bugreport, _unpickle_app, _unpickle_app_v2, appstr, -) - -__all__ = ['Celery'] - -_EXECV = os.environ.get('FORKED_BY_MULTIPROCESSING') -BUILTIN_FIXUPS = frozenset([ - 'celery.fixups.django:fixup', -]) - -ERR_ENVVAR_NOT_SET = """\ -The environment variable {0!r} is not set, -and as such the configuration could not be loaded. -Please set this variable and make it point to -a configuration module.""" - - -def app_has_custom(app, attr): - return mro_lookup(app.__class__, attr, stop=(Celery, object), - monkey_patched=[__name__]) - - -def _unpickle_appattr(reverse_name, args): - """Given an attribute name and a list of args, gets - the attribute from the current app and calls it.""" - return get_current_app()._rgetattr(reverse_name)(*args) - - -class Celery(object): - #: This is deprecated, use :meth:`reduce_keys` instead - Pickler = AppPickler - - SYSTEM = platforms.SYSTEM - IS_OSX, IS_WINDOWS = platforms.IS_OSX, platforms.IS_WINDOWS - - amqp_cls = 'celery.app.amqp:AMQP' - backend_cls = None - events_cls = 'celery.events:Events' - loader_cls = 'celery.loaders.app:AppLoader' - log_cls = 'celery.app.log:Logging' - control_cls = 'celery.app.control:Control' - task_cls = 'celery.app.task:Task' - registry_cls = TaskRegistry - _fixups = None - _pool = None - builtin_fixups = BUILTIN_FIXUPS - - def __init__(self, main=None, loader=None, backend=None, - amqp=None, events=None, log=None, control=None, - set_as_current=True, accept_magic_kwargs=False, - tasks=None, broker=None, include=None, changes=None, - config_source=None, fixups=None, task_cls=None, - autofinalize=True, **kwargs): - self.clock = LamportClock() - self.main = main - self.amqp_cls = amqp or self.amqp_cls - self.backend_cls = backend or self.backend_cls - self.events_cls = events or self.events_cls - self.loader_cls = loader or self.loader_cls - self.log_cls = log or self.log_cls - self.control_cls = control or self.control_cls - self.task_cls = task_cls or self.task_cls - self.set_as_current = set_as_current - self.registry_cls = symbol_by_name(self.registry_cls) - self.accept_magic_kwargs = accept_magic_kwargs - self.user_options = defaultdict(set) - self.steps = defaultdict(set) - self.autofinalize = autofinalize - - self.configured = False - self._config_source = config_source - self._pending_defaults = deque() - - self.finalized = False - self._finalize_mutex = threading.Lock() - self._pending = deque() - self._tasks = tasks - if not isinstance(self._tasks, TaskRegistry): - self._tasks = TaskRegistry(self._tasks or {}) - - # If the class defins a custom __reduce_args__ we need to use - # the old way of pickling apps, which is pickling a list of - # args instead of the new way that pickles a dict of keywords. - self._using_v1_reduce = app_has_custom(self, '__reduce_args__') - - # these options are moved to the config to - # simplify pickling of the app object. - self._preconf = changes or {} - if broker: - self._preconf['BROKER_URL'] = broker - if include: - self._preconf['CELERY_IMPORTS'] = include - - # - Apply fixups. - self.fixups = set(self.builtin_fixups) if fixups is None else fixups - # ...store fixup instances in _fixups to keep weakrefs alive. - self._fixups = [symbol_by_name(fixup)(self) for fixup in self.fixups] - - if self.set_as_current: - self.set_current() - - self.on_init() - _register_app(self) - - def set_current(self): - _tls.current_app = self - - def set_default(self): - set_default_app(self) - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - def close(self): - self._maybe_close_pool() - - def on_init(self): - """Optional callback called at init.""" - pass - - def start(self, argv=None): - return instantiate( - 'celery.bin.celery:CeleryCommand', - app=self).execute_from_commandline(argv) - - def worker_main(self, argv=None): - return instantiate( - 'celery.bin.worker:worker', - app=self).execute_from_commandline(argv) - - def task(self, *args, **opts): - """Creates new task class from any callable.""" - if _EXECV and not opts.get('_force_evaluate'): - # When using execv the task in the original module will point to a - # different app, so doing things like 'add.request' will point to - # a differnt task instance. This makes sure it will always use - # the task instance from the current app. - # Really need a better solution for this :( - from . import shared_task as proxies_to_curapp - return proxies_to_curapp(*args, _force_evaluate=True, **opts) - - def inner_create_task_cls(shared=True, filter=None, **opts): - _filt = filter # stupid 2to3 - - def _create_task_cls(fun): - if shared: - cons = lambda app: app._task_from_fun(fun, **opts) - cons.__name__ = fun.__name__ - shared_task(cons) - if self.accept_magic_kwargs: # compat mode - task = self._task_from_fun(fun, **opts) - if filter: - task = filter(task) - return task - - if self.finalized or opts.get('_force_evaluate'): - ret = self._task_from_fun(fun, **opts) - else: - # return a proxy object that evaluates on first use - ret = PromiseProxy(self._task_from_fun, (fun, ), opts, - __doc__=fun.__doc__) - self._pending.append(ret) - if _filt: - return _filt(ret) - return ret - - return _create_task_cls - - if len(args) == 1: - if callable(args[0]): - return inner_create_task_cls(**opts)(*args) - raise TypeError('argument 1 to @task() must be a callable') - if args: - raise TypeError( - '@task() takes exactly 1 argument ({0} given)'.format( - sum([len(args), len(opts)]))) - return inner_create_task_cls(**opts) - - def _task_from_fun(self, fun, **options): - if not self.finalized and not self.autofinalize: - raise RuntimeError('Contract breach: app not finalized') - base = options.pop('base', None) or self.Task - bind = options.pop('bind', False) - - T = type(fun.__name__, (base, ), dict({ - 'app': self, - 'accept_magic_kwargs': False, - 'run': fun if bind else staticmethod(fun), - '_decorated': True, - '__doc__': fun.__doc__, - '__module__': fun.__module__, - '__wrapped__': fun}, **options))() - task = self._tasks[T.name] # return global instance. - return task - - def finalize(self, auto=False): - with self._finalize_mutex: - if not self.finalized: - if auto and not self.autofinalize: - raise RuntimeError('Contract breach: app not finalized') - self.finalized = True - load_shared_tasks(self) - - pending = self._pending - while pending: - maybe_evaluate(pending.popleft()) - - for task in values(self._tasks): - task.bind(self) - - def add_defaults(self, fun): - if not callable(fun): - d, fun = fun, lambda: d - if self.configured: - return self.conf.add_defaults(fun()) - self._pending_defaults.append(fun) - - def config_from_object(self, obj, silent=False, force=False): - self._config_source = obj - if force or self.configured: - del(self.conf) - return self.loader.config_from_object(obj, silent=silent) - - def config_from_envvar(self, variable_name, silent=False, force=False): - module_name = os.environ.get(variable_name) - if not module_name: - if silent: - return False - raise ImproperlyConfigured( - ERR_ENVVAR_NOT_SET.format(variable_name)) - return self.config_from_object(module_name, silent=silent, force=force) - - def config_from_cmdline(self, argv, namespace='celery'): - self.conf.update(self.loader.cmdline_config_parser(argv, namespace)) - - def setup_security(self, allowed_serializers=None, key=None, cert=None, - store=None, digest='sha1', serializer='json'): - from celery.security import setup_security - return setup_security(allowed_serializers, key, cert, - store, digest, serializer, app=self) - - def autodiscover_tasks(self, packages, related_name='tasks', force=False): - if force: - return self._autodiscover_tasks(packages, related_name) - signals.import_modules.connect(promise( - self._autodiscover_tasks, (packages, related_name), - ), weak=False, sender=self) - - def _autodiscover_tasks(self, packages, related_name='tasks', **kwargs): - # argument may be lazy - packages = packages() if callable(packages) else packages - self.loader.autodiscover_tasks(packages, related_name) - - def send_task(self, name, args=None, kwargs=None, countdown=None, - eta=None, task_id=None, producer=None, connection=None, - router=None, result_cls=None, expires=None, - publisher=None, link=None, link_error=None, - add_to_parent=True, reply_to=None, **options): - task_id = task_id or uuid() - producer = producer or publisher # XXX compat - router = router or self.amqp.router - conf = self.conf - if conf.CELERY_ALWAYS_EAGER: # pragma: no cover - warnings.warn(AlwaysEagerIgnored( - 'CELERY_ALWAYS_EAGER has no effect on send_task', - ), stacklevel=2) - options = router.route(options, name, args, kwargs) - if connection: - producer = self.amqp.TaskProducer(connection) - with self.producer_or_acquire(producer) as P: - self.backend.on_task_call(P, task_id) - task_id = P.publish_task( - name, args, kwargs, countdown=countdown, eta=eta, - task_id=task_id, expires=expires, - callbacks=maybe_list(link), errbacks=maybe_list(link_error), - reply_to=reply_to or self.oid, **options - ) - result = (result_cls or self.AsyncResult)(task_id) - if add_to_parent: - parent = get_current_worker_task() - if parent: - parent.add_trail(result) - return result - - def connection(self, hostname=None, userid=None, password=None, - virtual_host=None, port=None, ssl=None, - connect_timeout=None, transport=None, - transport_options=None, heartbeat=None, - login_method=None, failover_strategy=None, **kwargs): - conf = self.conf - return self.amqp.Connection( - hostname or conf.BROKER_URL, - userid or conf.BROKER_USER, - password or conf.BROKER_PASSWORD, - virtual_host or conf.BROKER_VHOST, - port or conf.BROKER_PORT, - transport=transport or conf.BROKER_TRANSPORT, - ssl=self.either('BROKER_USE_SSL', ssl), - heartbeat=heartbeat, - login_method=login_method or conf.BROKER_LOGIN_METHOD, - failover_strategy=( - failover_strategy or conf.BROKER_FAILOVER_STRATEGY - ), - transport_options=dict( - conf.BROKER_TRANSPORT_OPTIONS, **transport_options or {} - ), - connect_timeout=self.either( - 'BROKER_CONNECTION_TIMEOUT', connect_timeout - ), - ) - broker_connection = connection - - @contextmanager - def connection_or_acquire(self, connection=None, pool=True, - *args, **kwargs): - if connection: - yield connection - else: - if pool: - with self.pool.acquire(block=True) as connection: - yield connection - else: - with self.connection() as connection: - yield connection - default_connection = connection_or_acquire # XXX compat - - @contextmanager - def producer_or_acquire(self, producer=None): - if producer: - yield producer - else: - with self.amqp.producer_pool.acquire(block=True) as producer: - yield producer - default_producer = producer_or_acquire # XXX compat - - def prepare_config(self, c): - """Prepare configuration before it is merged with the defaults.""" - return find_deprecated_settings(c) - - def now(self): - return self.loader.now(utc=self.conf.CELERY_ENABLE_UTC) - - def mail_admins(self, subject, body, fail_silently=False): - if self.conf.ADMINS: - to = [admin_email for _, admin_email in self.conf.ADMINS] - return self.loader.mail_admins( - subject, body, fail_silently, to=to, - sender=self.conf.SERVER_EMAIL, - host=self.conf.EMAIL_HOST, - port=self.conf.EMAIL_PORT, - user=self.conf.EMAIL_HOST_USER, - password=self.conf.EMAIL_HOST_PASSWORD, - timeout=self.conf.EMAIL_TIMEOUT, - use_ssl=self.conf.EMAIL_USE_SSL, - use_tls=self.conf.EMAIL_USE_TLS, - ) - - def select_queues(self, queues=None): - return self.amqp.queues.select(queues) - - def either(self, default_key, *values): - """Fallback to the value of a configuration key if none of the - `*values` are true.""" - return first(None, values) or self.conf.get(default_key) - - def bugreport(self): - return bugreport(self) - - def _get_backend(self): - from celery.backends import get_backend_by_url - backend, url = get_backend_by_url( - self.backend_cls or self.conf.CELERY_RESULT_BACKEND, - self.loader) - return backend(app=self, url=url) - - def on_configure(self): - """Callback calld when the app loads configuration""" - pass - - def _get_config(self): - self.on_configure() - if self._config_source: - self.loader.config_from_object(self._config_source) - self.configured = True - s = Settings({}, [self.prepare_config(self.loader.conf), - deepcopy(DEFAULTS)]) - - # load lazy config dict initializers. - pending = self._pending_defaults - while pending: - s.add_defaults(maybe_evaluate(pending.popleft()())) - if self._preconf: - for key, value in items(self._preconf): - setattr(s, key, value) - return s - - def _after_fork(self, obj_): - self._maybe_close_pool() - - def _maybe_close_pool(self): - if self._pool: - self._pool.force_close_all() - self._pool = None - amqp = self.__dict__.get('amqp') - if amqp is not None and amqp._producer_pool is not None: - amqp._producer_pool.force_close_all() - amqp._producer_pool = None - - def signature(self, *args, **kwargs): - kwargs['app'] = self - return self.canvas.signature(*args, **kwargs) - - def create_task_cls(self): - """Creates a base task class using default configuration - taken from this app.""" - return self.subclass_with_self( - self.task_cls, name='Task', attribute='_app', - keep_reduce=True, abstract=True, - ) - - def subclass_with_self(self, Class, name=None, attribute='app', - reverse=None, keep_reduce=False, **kw): - """Subclass an app-compatible class by setting its app attribute - to be this app instance. - - App-compatible means that the class has a class attribute that - provides the default app it should use, e.g. - ``class Foo: app = None``. - - :param Class: The app-compatible class to subclass. - :keyword name: Custom name for the target class. - :keyword attribute: Name of the attribute holding the app, - default is 'app'. - - """ - Class = symbol_by_name(Class) - reverse = reverse if reverse else Class.__name__ - - def __reduce__(self): - return _unpickle_appattr, (reverse, self.__reduce_args__()) - - attrs = dict({attribute: self}, __module__=Class.__module__, - __doc__=Class.__doc__, **kw) - if not keep_reduce: - attrs['__reduce__'] = __reduce__ - - return type(name or Class.__name__, (Class, ), attrs) - - def _rgetattr(self, path): - return attrgetter(path)(self) - - def __repr__(self): - return '<{0} {1}>'.format(type(self).__name__, appstr(self)) - - def __reduce__(self): - if self._using_v1_reduce: - return self.__reduce_v1__() - return (_unpickle_app_v2, (self.__class__, self.__reduce_keys__())) - - def __reduce_v1__(self): - # Reduce only pickles the configuration changes, - # so the default configuration doesn't have to be passed - # between processes. - return ( - _unpickle_app, - (self.__class__, self.Pickler) + self.__reduce_args__(), - ) - - def __reduce_keys__(self): - """Return keyword arguments used to reconstruct the object - when unpickling.""" - return { - 'main': self.main, - 'changes': self.conf.changes, - 'loader': self.loader_cls, - 'backend': self.backend_cls, - 'amqp': self.amqp_cls, - 'events': self.events_cls, - 'log': self.log_cls, - 'control': self.control_cls, - 'accept_magic_kwargs': self.accept_magic_kwargs, - 'fixups': self.fixups, - 'config_source': self._config_source, - 'task_cls': self.task_cls, - } - - def __reduce_args__(self): - """Deprecated method, please use :meth:`__reduce_keys__` instead.""" - return (self.main, self.conf.changes, - self.loader_cls, self.backend_cls, self.amqp_cls, - self.events_cls, self.log_cls, self.control_cls, - self.accept_magic_kwargs, self._config_source) - - @cached_property - def Worker(self): - return self.subclass_with_self('celery.apps.worker:Worker') - - @cached_property - def WorkController(self, **kwargs): - return self.subclass_with_self('celery.worker:WorkController') - - @cached_property - def Beat(self, **kwargs): - return self.subclass_with_self('celery.apps.beat:Beat') - - @cached_property - def Task(self): - return self.create_task_cls() - - @cached_property - def annotations(self): - return prepare_annotations(self.conf.CELERY_ANNOTATIONS) - - @cached_property - def AsyncResult(self): - return self.subclass_with_self('celery.result:AsyncResult') - - @cached_property - def ResultSet(self): - return self.subclass_with_self('celery.result:ResultSet') - - @cached_property - def GroupResult(self): - return self.subclass_with_self('celery.result:GroupResult') - - @cached_property - def TaskSet(self): # XXX compat - """Deprecated! Please use :class:`celery.group` instead.""" - return self.subclass_with_self('celery.task.sets:TaskSet') - - @cached_property - def TaskSetResult(self): # XXX compat - """Deprecated! Please use :attr:`GroupResult` instead.""" - return self.subclass_with_self('celery.result:TaskSetResult') - - @property - def pool(self): - if self._pool is None: - register_after_fork(self, self._after_fork) - limit = self.conf.BROKER_POOL_LIMIT - self._pool = self.connection().Pool(limit=limit) - return self._pool - - @property - def current_task(self): - return _task_stack.top - - @cached_property - def oid(self): - return oid_from(self) - - @cached_property - def amqp(self): - return instantiate(self.amqp_cls, app=self) - - @cached_property - def backend(self): - return self._get_backend() - - @cached_property - def conf(self): - return self._get_config() - - @cached_property - def control(self): - return instantiate(self.control_cls, app=self) - - @cached_property - def events(self): - return instantiate(self.events_cls, app=self) - - @cached_property - def loader(self): - return get_loader_cls(self.loader_cls)(app=self) - - @cached_property - def log(self): - return instantiate(self.log_cls, app=self) - - @cached_property - def canvas(self): - from celery import canvas - return canvas - - @cached_property - def tasks(self): - self.finalize(auto=True) - return self._tasks - - @cached_property - def timezone(self): - from celery.utils.timeutils import timezone - conf = self.conf - tz = conf.CELERY_TIMEZONE - if not tz: - return (timezone.get_timezone('UTC') if conf.CELERY_ENABLE_UTC - else timezone.local) - return timezone.get_timezone(self.conf.CELERY_TIMEZONE) -App = Celery # compat diff --git a/awx/lib/site-packages/celery/app/builtins.py b/awx/lib/site-packages/celery/app/builtins.py deleted file mode 100644 index a609208402..0000000000 --- a/awx/lib/site-packages/celery/app/builtins.py +++ /dev/null @@ -1,394 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.builtins - ~~~~~~~~~~~~~~~~~~~ - - Built-in tasks that are always available in all - app instances. E.g. chord, group and xmap. - -""" -from __future__ import absolute_import - -from collections import deque - -from celery._state import get_current_worker_task -from celery.utils import uuid -from celery.utils.log import get_logger - -__all__ = ['shared_task', 'load_shared_tasks'] - -logger = get_logger(__name__) - -#: global list of functions defining tasks that should be -#: added to all apps. -_shared_tasks = set() - - -def shared_task(constructor): - """Decorator that specifies a function that generates a built-in task. - - The function will then be called for every new app instance created - (lazily, so more exactly when the task registry for that app is needed). - - The function must take a single ``app`` argument. - """ - _shared_tasks.add(constructor) - return constructor - - -def load_shared_tasks(app): - """Create built-in tasks for an app instance.""" - constructors = set(_shared_tasks) - for constructor in constructors: - constructor(app) - - -@shared_task -def add_backend_cleanup_task(app): - """The backend cleanup task can be used to clean up the default result - backend. - - If the configured backend requires periodic cleanup this task is also - automatically configured to run every day at midnight (requires - :program:`celery beat` to be running). - - """ - @app.task(name='celery.backend_cleanup', - shared=False, _force_evaluate=True) - def backend_cleanup(): - app.backend.cleanup() - return backend_cleanup - - -@shared_task -def add_unlock_chord_task(app): - """This task is used by result backends without native chord support. - - It joins chords by creating a task chain polling the header for completion. - - """ - from celery.canvas import signature - from celery.exceptions import ChordError - from celery.result import allow_join_result, result_from_tuple - - default_propagate = app.conf.CELERY_CHORD_PROPAGATES - - @app.task(name='celery.chord_unlock', max_retries=None, shared=False, - default_retry_delay=1, ignore_result=True, _force_evaluate=True) - def unlock_chord(group_id, callback, interval=None, propagate=None, - max_retries=None, result=None, - Result=app.AsyncResult, GroupResult=app.GroupResult, - result_from_tuple=result_from_tuple): - # if propagate is disabled exceptions raised by chord tasks - # will be sent as part of the result list to the chord callback. - # Since 3.1 propagate will be enabled by default, and instead - # the chord callback changes state to FAILURE with the - # exception set to ChordError. - propagate = default_propagate if propagate is None else propagate - if interval is None: - interval = unlock_chord.default_retry_delay - - # check if the task group is ready, and if so apply the callback. - deps = GroupResult( - group_id, - [result_from_tuple(r, app=app) for r in result], - ) - j = deps.join_native if deps.supports_native_join else deps.join - - if deps.ready(): - callback = signature(callback, app=app) - try: - with allow_join_result(): - ret = j(timeout=3.0, propagate=propagate) - except Exception as exc: - try: - culprit = next(deps._failed_join_report()) - reason = 'Dependency {0.id} raised {1!r}'.format( - culprit, exc, - ) - except StopIteration: - reason = repr(exc) - logger.error('Chord %r raised: %r', group_id, exc, exc_info=1) - app.backend.chord_error_from_stack(callback, - ChordError(reason)) - else: - try: - callback.delay(ret) - except Exception as exc: - logger.error('Chord %r raised: %r', group_id, exc, - exc_info=1) - app.backend.chord_error_from_stack( - callback, - exc=ChordError('Callback error: {0!r}'.format(exc)), - ) - else: - raise unlock_chord.retry(countdown=interval, - max_retries=max_retries) - return unlock_chord - - -@shared_task -def add_map_task(app): - from celery.canvas import signature - - @app.task(name='celery.map', shared=False, _force_evaluate=True) - def xmap(task, it): - task = signature(task, app=app).type - return [task(item) for item in it] - return xmap - - -@shared_task -def add_starmap_task(app): - from celery.canvas import signature - - @app.task(name='celery.starmap', shared=False, _force_evaluate=True) - def xstarmap(task, it): - task = signature(task, app=app).type - return [task(*item) for item in it] - return xstarmap - - -@shared_task -def add_chunk_task(app): - from celery.canvas import chunks as _chunks - - @app.task(name='celery.chunks', shared=False, _force_evaluate=True) - def chunks(task, it, n): - return _chunks.apply_chunks(task, it, n) - return chunks - - -@shared_task -def add_group_task(app): - _app = app - from celery.canvas import maybe_signature, signature - from celery.result import result_from_tuple - - class Group(app.Task): - app = _app - name = 'celery.group' - accept_magic_kwargs = False - _decorated = True - - def run(self, tasks, result, group_id, partial_args): - app = self.app - result = result_from_tuple(result, app) - # any partial args are added to all tasks in the group - taskit = (signature(task, app=app).clone(partial_args) - for i, task in enumerate(tasks)) - if self.request.is_eager or app.conf.CELERY_ALWAYS_EAGER: - return app.GroupResult( - result.id, - [stask.apply(group_id=group_id) for stask in taskit], - ) - with app.producer_or_acquire() as pub: - [stask.apply_async(group_id=group_id, producer=pub, - add_to_parent=False) for stask in taskit] - parent = get_current_worker_task() - if parent: - parent.add_trail(result) - return result - - def prepare(self, options, tasks, args, **kwargs): - options['group_id'] = group_id = ( - options.setdefault('task_id', uuid())) - - def prepare_member(task): - task = maybe_signature(task, app=self.app) - task.options['group_id'] = group_id - return task, task.freeze() - - try: - tasks, res = list(zip( - *[prepare_member(task) for task in tasks] - )) - except ValueError: # tasks empty - tasks, res = [], [] - return (tasks, self.app.GroupResult(group_id, res), group_id, args) - - def apply_async(self, partial_args=(), kwargs={}, **options): - if self.app.conf.CELERY_ALWAYS_EAGER: - return self.apply(partial_args, kwargs, **options) - tasks, result, gid, args = self.prepare( - options, args=partial_args, **kwargs - ) - super(Group, self).apply_async(( - list(tasks), result.as_tuple(), gid, args), **options - ) - return result - - def apply(self, args=(), kwargs={}, **options): - return super(Group, self).apply( - self.prepare(options, args=args, **kwargs), - **options).get() - return Group - - -@shared_task -def add_chain_task(app): - from celery.canvas import ( - Signature, chain, chord, group, maybe_signature, maybe_unroll_group, - ) - - _app = app - - class Chain(app.Task): - app = _app - name = 'celery.chain' - accept_magic_kwargs = False - _decorated = True - - def prepare_steps(self, args, tasks): - app = self.app - steps = deque(tasks) - next_step = prev_task = prev_res = None - tasks, results = [], [] - i = 0 - while steps: - # First task get partial args from chain. - task = maybe_signature(steps.popleft(), app=app) - task = task.clone() if i else task.clone(args) - res = task.freeze() - i += 1 - - if isinstance(task, group): - task = maybe_unroll_group(task) - if isinstance(task, chain): - # splice the chain - steps.extendleft(reversed(task.tasks)) - continue - - elif isinstance(task, group) and steps and \ - not isinstance(steps[0], group): - # automatically upgrade group(..) | s to chord(group, s) - try: - next_step = steps.popleft() - # for chords we freeze by pretending it's a normal - # task instead of a group. - res = Signature.freeze(next_step) - task = chord(task, body=next_step, task_id=res.task_id) - except IndexError: - pass # no callback, so keep as group - if prev_task: - # link previous task to this task. - prev_task.link(task) - # set the results parent attribute. - if not res.parent: - res.parent = prev_res - - if not isinstance(prev_task, chord): - results.append(res) - tasks.append(task) - prev_task, prev_res = task, res - - return tasks, results - - def apply_async(self, args=(), kwargs={}, group_id=None, chord=None, - task_id=None, link=None, link_error=None, **options): - if self.app.conf.CELERY_ALWAYS_EAGER: - return self.apply(args, kwargs, **options) - options.pop('publisher', None) - tasks, results = self.prepare_steps(args, kwargs['tasks']) - result = results[-1] - if group_id: - tasks[-1].set(group_id=group_id) - if chord: - tasks[-1].set(chord=chord) - if task_id: - tasks[-1].set(task_id=task_id) - result = tasks[-1].type.AsyncResult(task_id) - # make sure we can do a link() and link_error() on a chain object. - if link: - tasks[-1].set(link=link) - # and if any task in the chain fails, call the errbacks - if link_error: - for task in tasks: - task.set(link_error=link_error) - tasks[0].apply_async(**options) - return result - - def apply(self, args=(), kwargs={}, signature=maybe_signature, - **options): - app = self.app - last, fargs = None, args # fargs passed to first task only - for task in kwargs['tasks']: - res = signature(task, app=app).clone(fargs).apply( - last and (last.get(), ), - ) - res.parent, last, fargs = last, res, None - return last - return Chain - - -@shared_task -def add_chord_task(app): - """Every chord is executed in a dedicated task, so that the chord - can be used as a signature, and this generates the task - responsible for that.""" - from celery import group - from celery.canvas import maybe_signature - _app = app - default_propagate = app.conf.CELERY_CHORD_PROPAGATES - - class Chord(app.Task): - app = _app - name = 'celery.chord' - accept_magic_kwargs = False - ignore_result = False - _decorated = True - - def run(self, header, body, partial_args=(), interval=None, - countdown=1, max_retries=None, propagate=None, - eager=False, **kwargs): - app = self.app - propagate = default_propagate if propagate is None else propagate - group_id = uuid() - - # - convert back to group if serialized - tasks = header.tasks if isinstance(header, group) else header - header = group([ - maybe_signature(s, app=app).clone() for s in tasks - ], app=self.app) - # - eager applies the group inline - if eager: - return header.apply(args=partial_args, task_id=group_id) - - body.setdefault('chord_size', len(header.tasks)) - results = header.freeze(group_id=group_id, chord=body).results - - return self.backend.apply_chord( - header, partial_args, group_id, - body, interval=interval, countdown=countdown, - max_retries=max_retries, propagate=propagate, result=results, - ) - - def apply_async(self, args=(), kwargs={}, task_id=None, - group_id=None, chord=None, **options): - app = self.app - if app.conf.CELERY_ALWAYS_EAGER: - return self.apply(args, kwargs, **options) - header = kwargs.pop('header') - body = kwargs.pop('body') - header, body = (maybe_signature(header, app=app), - maybe_signature(body, app=app)) - # forward certain options to body - if chord is not None: - body.options['chord'] = chord - if group_id is not None: - body.options['group_id'] = group_id - [body.link(s) for s in options.pop('link', [])] - [body.link_error(s) for s in options.pop('link_error', [])] - body_result = body.freeze(task_id) - parent = super(Chord, self).apply_async((header, body, args), - kwargs, **options) - body_result.parent = parent - return body_result - - def apply(self, args=(), kwargs={}, propagate=True, **options): - body = kwargs['body'] - res = super(Chord, self).apply(args, dict(kwargs, eager=True), - **options) - return maybe_signature(body, app=self.app).apply( - args=(res.get(propagate=propagate).get(), )) - return Chord diff --git a/awx/lib/site-packages/celery/app/control.py b/awx/lib/site-packages/celery/app/control.py deleted file mode 100644 index 34076df0e7..0000000000 --- a/awx/lib/site-packages/celery/app/control.py +++ /dev/null @@ -1,307 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.control - ~~~~~~~~~~~~~~~~~~~ - - Client for worker remote control commands. - Server implementation is in :mod:`celery.worker.control`. - -""" -from __future__ import absolute_import - -import warnings - -from kombu.pidbox import Mailbox -from kombu.utils import cached_property - -from celery.exceptions import DuplicateNodenameWarning - -__all__ = ['Inspect', 'Control', 'flatten_reply'] - -W_DUPNODE = """\ -Received multiple replies from node name {0!r}. -Please make sure you give each node a unique nodename using the `-n` option.\ -""" - - -def flatten_reply(reply): - nodes = {} - seen = set() - for item in reply: - dup = next((nodename in seen for nodename in item), None) - if dup: - warnings.warn(DuplicateNodenameWarning( - W_DUPNODE.format(dup), - )) - seen.update(item) - nodes.update(item) - return nodes - - -class Inspect(object): - app = None - - def __init__(self, destination=None, timeout=1, callback=None, - connection=None, app=None, limit=None): - self.app = app or self.app - self.destination = destination - self.timeout = timeout - self.callback = callback - self.connection = connection - self.limit = limit - - def _prepare(self, reply): - if not reply: - return - by_node = flatten_reply(reply) - if self.destination and \ - not isinstance(self.destination, (list, tuple)): - return by_node.get(self.destination) - return by_node - - def _request(self, command, **kwargs): - return self._prepare(self.app.control.broadcast( - command, - arguments=kwargs, - destination=self.destination, - callback=self.callback, - connection=self.connection, - limit=self.limit, - timeout=self.timeout, reply=True, - )) - - def report(self): - return self._request('report') - - def clock(self): - return self._request('clock') - - def active(self, safe=False): - return self._request('dump_active', safe=safe) - - def scheduled(self, safe=False): - return self._request('dump_schedule', safe=safe) - - def reserved(self, safe=False): - return self._request('dump_reserved', safe=safe) - - def stats(self): - return self._request('stats') - - def revoked(self): - return self._request('dump_revoked') - - def registered(self, *taskinfoitems): - return self._request('dump_tasks', taskinfoitems=taskinfoitems) - registered_tasks = registered - - def ping(self): - return self._request('ping') - - def active_queues(self): - return self._request('active_queues') - - def query_task(self, ids): - return self._request('query_task', ids=ids) - - def conf(self, with_defaults=False): - return self._request('dump_conf', with_defaults=with_defaults) - - def hello(self, from_node, revoked=None): - return self._request('hello', from_node=from_node, revoked=revoked) - - def memsample(self): - return self._request('memsample') - - def memdump(self, samples=10): - return self._request('memdump', samples=samples) - - def objgraph(self, type='Request', n=200, max_depth=10): - return self._request('objgraph', num=n, max_depth=max_depth, type=type) - - -class Control(object): - Mailbox = Mailbox - - def __init__(self, app=None): - self.app = app - self.mailbox = self.Mailbox('celery', type='fanout', accept=['json']) - - @cached_property - def inspect(self): - return self.app.subclass_with_self(Inspect, reverse='control.inspect') - - def purge(self, connection=None): - """Discard all waiting tasks. - - This will ignore all tasks waiting for execution, and they will - be deleted from the messaging server. - - :returns: the number of tasks discarded. - - """ - with self.app.connection_or_acquire(connection) as conn: - return self.app.amqp.TaskConsumer(conn).purge() - discard_all = purge - - def election(self, id, topic, action=None, connection=None): - self.broadcast('election', connection=connection, arguments={ - 'id': id, 'topic': topic, 'action': action, - }) - - def revoke(self, task_id, destination=None, terminate=False, - signal='SIGTERM', **kwargs): - """Tell all (or specific) workers to revoke a task by id. - - If a task is revoked, the workers will ignore the task and - not execute it after all. - - :param task_id: Id of the task to revoke. - :keyword terminate: Also terminate the process currently working - on the task (if any). - :keyword signal: Name of signal to send to process if terminate. - Default is TERM. - - See :meth:`broadcast` for supported keyword arguments. - - """ - return self.broadcast('revoke', destination=destination, - arguments={'task_id': task_id, - 'terminate': terminate, - 'signal': signal}, **kwargs) - - def ping(self, destination=None, timeout=1, **kwargs): - """Ping all (or specific) workers. - - Will return the list of answers. - - See :meth:`broadcast` for supported keyword arguments. - - """ - return self.broadcast('ping', reply=True, destination=destination, - timeout=timeout, **kwargs) - - def rate_limit(self, task_name, rate_limit, destination=None, **kwargs): - """Tell all (or specific) workers to set a new rate limit - for task by type. - - :param task_name: Name of task to change rate limit for. - :param rate_limit: The rate limit as tasks per second, or a rate limit - string (`'100/m'`, etc. - see :attr:`celery.task.base.Task.rate_limit` for - more information). - - See :meth:`broadcast` for supported keyword arguments. - - """ - return self.broadcast('rate_limit', destination=destination, - arguments={'task_name': task_name, - 'rate_limit': rate_limit}, - **kwargs) - - def add_consumer(self, queue, exchange=None, exchange_type='direct', - routing_key=None, options=None, **kwargs): - """Tell all (or specific) workers to start consuming from a new queue. - - Only the queue name is required as if only the queue is specified - then the exchange/routing key will be set to the same name ( - like automatic queues do). - - .. note:: - - This command does not respect the default queue/exchange - options in the configuration. - - :param queue: Name of queue to start consuming from. - :keyword exchange: Optional name of exchange. - :keyword exchange_type: Type of exchange (defaults to 'direct') - command to, when empty broadcast to all workers. - :keyword routing_key: Optional routing key. - :keyword options: Additional options as supported - by :meth:`kombu.entitiy.Queue.from_dict`. - - See :meth:`broadcast` for supported keyword arguments. - - """ - return self.broadcast( - 'add_consumer', - arguments=dict({'queue': queue, 'exchange': exchange, - 'exchange_type': exchange_type, - 'routing_key': routing_key}, **options or {}), - **kwargs - ) - - def cancel_consumer(self, queue, **kwargs): - """Tell all (or specific) workers to stop consuming from ``queue``. - - Supports the same keyword arguments as :meth:`broadcast`. - - """ - return self.broadcast( - 'cancel_consumer', arguments={'queue': queue}, **kwargs - ) - - def time_limit(self, task_name, soft=None, hard=None, **kwargs): - """Tell all (or specific) workers to set time limits for - a task by type. - - :param task_name: Name of task to change time limits for. - :keyword soft: New soft time limit (in seconds). - :keyword hard: New hard time limit (in seconds). - - Any additional keyword arguments are passed on to :meth:`broadcast`. - - """ - return self.broadcast( - 'time_limit', - arguments={'task_name': task_name, - 'hard': hard, 'soft': soft}, **kwargs) - - def enable_events(self, destination=None, **kwargs): - """Tell all (or specific) workers to enable events.""" - return self.broadcast('enable_events', {}, destination, **kwargs) - - def disable_events(self, destination=None, **kwargs): - """Tell all (or specific) workers to enable events.""" - return self.broadcast('disable_events', {}, destination, **kwargs) - - def pool_grow(self, n=1, destination=None, **kwargs): - """Tell all (or specific) workers to grow the pool by ``n``. - - Supports the same arguments as :meth:`broadcast`. - - """ - return self.broadcast('pool_grow', {'n': n}, destination, **kwargs) - - def pool_shrink(self, n=1, destination=None, **kwargs): - """Tell all (or specific) workers to shrink the pool by ``n``. - - Supports the same arguments as :meth:`broadcast`. - - """ - return self.broadcast('pool_shrink', {'n': n}, destination, **kwargs) - - def broadcast(self, command, arguments=None, destination=None, - connection=None, reply=False, timeout=1, limit=None, - callback=None, channel=None, **extra_kwargs): - """Broadcast a control command to the celery workers. - - :param command: Name of command to send. - :param arguments: Keyword arguments for the command. - :keyword destination: If set, a list of the hosts to send the - command to, when empty broadcast to all workers. - :keyword connection: Custom broker connection to use, if not set, - a connection will be established automatically. - :keyword reply: Wait for and return the reply. - :keyword timeout: Timeout in seconds to wait for the reply. - :keyword limit: Limit number of replies. - :keyword callback: Callback called immediately for each reply - received. - - """ - with self.app.connection_or_acquire(connection) as conn: - arguments = dict(arguments or {}, **extra_kwargs) - return self.mailbox(conn)._broadcast( - command, arguments, destination, reply, timeout, - limit, callback, channel=channel, - ) diff --git a/awx/lib/site-packages/celery/app/defaults.py b/awx/lib/site-packages/celery/app/defaults.py deleted file mode 100644 index 15f7fcfb60..0000000000 --- a/awx/lib/site-packages/celery/app/defaults.py +++ /dev/null @@ -1,269 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.defaults - ~~~~~~~~~~~~~~~~~~~ - - Configuration introspection and defaults. - -""" -from __future__ import absolute_import - -import sys - -from collections import deque, namedtuple -from datetime import timedelta - -from celery.five import items -from celery.utils import strtobool -from celery.utils.functional import memoize - -__all__ = ['Option', 'NAMESPACES', 'flatten', 'find'] - -is_jython = sys.platform.startswith('java') -is_pypy = hasattr(sys, 'pypy_version_info') - -DEFAULT_POOL = 'prefork' -if is_jython: - DEFAULT_POOL = 'threads' -elif is_pypy: - if sys.pypy_version_info[0:3] < (1, 5, 0): - DEFAULT_POOL = 'solo' - else: - DEFAULT_POOL = 'prefork' - -DEFAULT_ACCEPT_CONTENT = ['json', 'pickle', 'msgpack', 'yaml'] -DEFAULT_PROCESS_LOG_FMT = """ - [%(asctime)s: %(levelname)s/%(processName)s] %(message)s -""".strip() -DEFAULT_LOG_FMT = '[%(asctime)s: %(levelname)s] %(message)s' -DEFAULT_TASK_LOG_FMT = """[%(asctime)s: %(levelname)s/%(processName)s] \ -%(task_name)s[%(task_id)s]: %(message)s""" - -_BROKER_OLD = {'deprecate_by': '2.5', 'remove_by': '4.0', - 'alt': 'BROKER_URL setting'} -_REDIS_OLD = {'deprecate_by': '2.5', 'remove_by': '4.0', - 'alt': 'URL form of CELERY_RESULT_BACKEND'} - -searchresult = namedtuple('searchresult', ('namespace', 'key', 'type')) - - -class Option(object): - alt = None - deprecate_by = None - remove_by = None - typemap = dict(string=str, int=int, float=float, any=lambda v: v, - bool=strtobool, dict=dict, tuple=tuple) - - def __init__(self, default=None, *args, **kwargs): - self.default = default - self.type = kwargs.get('type') or 'string' - for attr, value in items(kwargs): - setattr(self, attr, value) - - def to_python(self, value): - return self.typemap[self.type](value) - - def __repr__(self): - return '<Option: type->{0} default->{1!r}>'.format(self.type, - self.default) - -NAMESPACES = { - 'BROKER': { - 'URL': Option(None, type='string'), - 'CONNECTION_TIMEOUT': Option(4, type='float'), - 'CONNECTION_RETRY': Option(True, type='bool'), - 'CONNECTION_MAX_RETRIES': Option(100, type='int'), - 'FAILOVER_STRATEGY': Option(None, type='string'), - 'HEARTBEAT': Option(None, type='int'), - 'HEARTBEAT_CHECKRATE': Option(3.0, type='int'), - 'LOGIN_METHOD': Option(None, type='string'), - 'POOL_LIMIT': Option(10, type='int'), - 'USE_SSL': Option(False, type='bool'), - 'TRANSPORT': Option(type='string'), - 'TRANSPORT_OPTIONS': Option({}, type='dict'), - 'HOST': Option(type='string', **_BROKER_OLD), - 'PORT': Option(type='int', **_BROKER_OLD), - 'USER': Option(type='string', **_BROKER_OLD), - 'PASSWORD': Option(type='string', **_BROKER_OLD), - 'VHOST': Option(type='string', **_BROKER_OLD), - }, - 'CASSANDRA': { - 'COLUMN_FAMILY': Option(type='string'), - 'DETAILED_MODE': Option(False, type='bool'), - 'KEYSPACE': Option(type='string'), - 'READ_CONSISTENCY': Option(type='string'), - 'SERVERS': Option(type='list'), - 'WRITE_CONSISTENCY': Option(type='string'), - }, - 'CELERY': { - 'ACCEPT_CONTENT': Option(DEFAULT_ACCEPT_CONTENT, type='list'), - 'ACKS_LATE': Option(False, type='bool'), - 'ALWAYS_EAGER': Option(False, type='bool'), - 'ANNOTATIONS': Option(type='any'), - 'BROADCAST_QUEUE': Option('celeryctl'), - 'BROADCAST_EXCHANGE': Option('celeryctl'), - 'BROADCAST_EXCHANGE_TYPE': Option('fanout'), - 'CACHE_BACKEND': Option(), - 'CACHE_BACKEND_OPTIONS': Option({}, type='dict'), - 'CHORD_PROPAGATES': Option(True, type='bool'), - 'COUCHBASE_BACKEND_SETTINGS': Option(None, type='dict'), - 'CREATE_MISSING_QUEUES': Option(True, type='bool'), - 'DEFAULT_RATE_LIMIT': Option(type='string'), - 'DISABLE_RATE_LIMITS': Option(False, type='bool'), - 'DEFAULT_ROUTING_KEY': Option('celery'), - 'DEFAULT_QUEUE': Option('celery'), - 'DEFAULT_EXCHANGE': Option('celery'), - 'DEFAULT_EXCHANGE_TYPE': Option('direct'), - 'DEFAULT_DELIVERY_MODE': Option(2, type='string'), - 'EAGER_PROPAGATES_EXCEPTIONS': Option(False, type='bool'), - 'ENABLE_UTC': Option(True, type='bool'), - 'ENABLE_REMOTE_CONTROL': Option(True, type='bool'), - 'EVENT_SERIALIZER': Option('json'), - 'EVENT_QUEUE_EXPIRES': Option(None, type='float'), - 'EVENT_QUEUE_TTL': Option(None, type='float'), - 'IMPORTS': Option((), type='tuple'), - 'INCLUDE': Option((), type='tuple'), - 'IGNORE_RESULT': Option(False, type='bool'), - 'MAX_CACHED_RESULTS': Option(100, type='int'), - 'MESSAGE_COMPRESSION': Option(type='string'), - 'MONGODB_BACKEND_SETTINGS': Option(type='dict'), - 'REDIS_HOST': Option(type='string', **_REDIS_OLD), - 'REDIS_PORT': Option(type='int', **_REDIS_OLD), - 'REDIS_DB': Option(type='int', **_REDIS_OLD), - 'REDIS_PASSWORD': Option(type='string', **_REDIS_OLD), - 'REDIS_MAX_CONNECTIONS': Option(type='int'), - 'RESULT_BACKEND': Option(type='string'), - 'RESULT_DB_SHORT_LIVED_SESSIONS': Option(False, type='bool'), - 'RESULT_DB_TABLENAMES': Option(type='dict'), - 'RESULT_DBURI': Option(), - 'RESULT_ENGINE_OPTIONS': Option(type='dict'), - 'RESULT_EXCHANGE': Option('celeryresults'), - 'RESULT_EXCHANGE_TYPE': Option('direct'), - 'RESULT_SERIALIZER': Option('pickle'), - 'RESULT_PERSISTENT': Option(None, type='bool'), - 'ROUTES': Option(type='any'), - 'SEND_EVENTS': Option(False, type='bool'), - 'SEND_TASK_ERROR_EMAILS': Option(False, type='bool'), - 'SEND_TASK_SENT_EVENT': Option(False, type='bool'), - 'STORE_ERRORS_EVEN_IF_IGNORED': Option(False, type='bool'), - 'TASK_PUBLISH_RETRY': Option(True, type='bool'), - 'TASK_PUBLISH_RETRY_POLICY': Option({ - 'max_retries': 3, - 'interval_start': 0, - 'interval_max': 1, - 'interval_step': 0.2}, type='dict'), - 'TASK_RESULT_EXPIRES': Option(timedelta(days=1), type='float'), - 'TASK_SERIALIZER': Option('pickle'), - 'TIMEZONE': Option(type='string'), - 'TRACK_STARTED': Option(False, type='bool'), - 'REDIRECT_STDOUTS': Option(True, type='bool'), - 'REDIRECT_STDOUTS_LEVEL': Option('WARNING'), - 'QUEUES': Option(type='dict'), - 'QUEUE_HA_POLICY': Option(None, type='string'), - 'SECURITY_KEY': Option(type='string'), - 'SECURITY_CERTIFICATE': Option(type='string'), - 'SECURITY_CERT_STORE': Option(type='string'), - 'WORKER_DIRECT': Option(False, type='bool'), - }, - 'CELERYD': { - 'AGENT': Option(None, type='string'), - 'AUTOSCALER': Option('celery.worker.autoscale:Autoscaler'), - 'AUTORELOADER': Option('celery.worker.autoreload:Autoreloader'), - 'CONCURRENCY': Option(0, type='int'), - 'TIMER': Option(type='string'), - 'TIMER_PRECISION': Option(1.0, type='float'), - 'FORCE_EXECV': Option(False, type='bool'), - 'HIJACK_ROOT_LOGGER': Option(True, type='bool'), - 'CONSUMER': Option('celery.worker.consumer:Consumer', type='string'), - 'LOG_FORMAT': Option(DEFAULT_PROCESS_LOG_FMT), - 'LOG_COLOR': Option(type='bool'), - 'LOG_LEVEL': Option('WARN', deprecate_by='2.4', remove_by='4.0', - alt='--loglevel argument'), - 'LOG_FILE': Option(deprecate_by='2.4', remove_by='4.0', - alt='--logfile argument'), - 'MAX_TASKS_PER_CHILD': Option(type='int'), - 'POOL': Option(DEFAULT_POOL), - 'POOL_PUTLOCKS': Option(True, type='bool'), - 'POOL_RESTARTS': Option(False, type='bool'), - 'PREFETCH_MULTIPLIER': Option(4, type='int'), - 'STATE_DB': Option(), - 'TASK_LOG_FORMAT': Option(DEFAULT_TASK_LOG_FMT), - 'TASK_SOFT_TIME_LIMIT': Option(type='float'), - 'TASK_TIME_LIMIT': Option(type='float'), - 'WORKER_LOST_WAIT': Option(10.0, type='float') - }, - 'CELERYBEAT': { - 'SCHEDULE': Option({}, type='dict'), - 'SCHEDULER': Option('celery.beat:PersistentScheduler'), - 'SCHEDULE_FILENAME': Option('celerybeat-schedule'), - 'SYNC_EVERY': Option(0, type='int'), - 'MAX_LOOP_INTERVAL': Option(0, type='float'), - 'LOG_LEVEL': Option('INFO', deprecate_by='2.4', remove_by='4.0', - alt='--loglevel argument'), - 'LOG_FILE': Option(deprecate_by='2.4', remove_by='4.0', - alt='--logfile argument'), - }, - 'CELERYMON': { - 'LOG_LEVEL': Option('INFO', deprecate_by='2.4', remove_by='4.0', - alt='--loglevel argument'), - 'LOG_FILE': Option(deprecate_by='2.4', remove_by='4.0', - alt='--logfile argument'), - 'LOG_FORMAT': Option(DEFAULT_LOG_FMT), - }, - 'EMAIL': { - 'HOST': Option('localhost'), - 'PORT': Option(25, type='int'), - 'HOST_USER': Option(), - 'HOST_PASSWORD': Option(), - 'TIMEOUT': Option(2, type='float'), - 'USE_SSL': Option(False, type='bool'), - 'USE_TLS': Option(False, type='bool'), - }, - 'SERVER_EMAIL': Option('celery@localhost'), - 'ADMINS': Option((), type='tuple'), -} - - -def flatten(d, ns=''): - stack = deque([(ns, d)]) - while stack: - name, space = stack.popleft() - for key, value in items(space): - if isinstance(value, dict): - stack.append((name + key + '_', value)) - else: - yield name + key, value -DEFAULTS = dict((key, value.default) for key, value in flatten(NAMESPACES)) - - -def find_deprecated_settings(source): - from celery.utils import warn_deprecated - for name, opt in flatten(NAMESPACES): - if (opt.deprecate_by or opt.remove_by) and getattr(source, name, None): - warn_deprecated(description='The {0!r} setting'.format(name), - deprecation=opt.deprecate_by, - removal=opt.remove_by, - alternative='Use the {0.alt} instead'.format(opt)) - return source - - -@memoize(maxsize=None) -def find(name, namespace='celery'): - # - Try specified namespace first. - namespace = namespace.upper() - try: - return searchresult( - namespace, name.upper(), NAMESPACES[namespace][name.upper()], - ) - except KeyError: - # - Try all the other namespaces. - for ns, keys in items(NAMESPACES): - if ns.upper() == name.upper(): - return searchresult(None, ns, keys) - elif isinstance(keys, dict): - try: - return searchresult(ns, name.upper(), keys[name.upper()]) - except KeyError: - pass - # - See if name is a qualname last. - return searchresult(None, name.upper(), DEFAULTS[name.upper()]) diff --git a/awx/lib/site-packages/celery/app/log.py b/awx/lib/site-packages/celery/app/log.py deleted file mode 100644 index 9dde09b16b..0000000000 --- a/awx/lib/site-packages/celery/app/log.py +++ /dev/null @@ -1,257 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.log - ~~~~~~~~~~~~~~ - - The Celery instances logging section: ``Celery.log``. - - Sets up logging for the worker and other programs, - redirects stdouts, colors log output, patches logging - related compatibility fixes, and so on. - -""" -from __future__ import absolute_import - -import logging -import os -import sys - -from logging.handlers import WatchedFileHandler - -from kombu.log import NullHandler -from kombu.utils.encoding import set_default_encoding_file - -from celery import signals -from celery._state import get_current_task -from celery.five import class_property, string_t -from celery.utils import isatty, node_format -from celery.utils.log import ( - get_logger, mlevel, - ColorFormatter, ensure_process_aware_logger, - LoggingProxy, get_multiprocessing_logger, - reset_multiprocessing_logger, -) -from celery.utils.term import colored - -__all__ = ['TaskFormatter', 'Logging'] - -MP_LOG = os.environ.get('MP_LOG', False) - - -class TaskFormatter(ColorFormatter): - - def format(self, record): - task = get_current_task() - if task and task.request: - record.__dict__.update(task_id=task.request.id, - task_name=task.name) - else: - record.__dict__.setdefault('task_name', '???') - record.__dict__.setdefault('task_id', '???') - return ColorFormatter.format(self, record) - - -class Logging(object): - #: The logging subsystem is only configured once per process. - #: setup_logging_subsystem sets this flag, and subsequent calls - #: will do nothing. - _setup = False - - def __init__(self, app): - self.app = app - self.loglevel = mlevel(self.app.conf.CELERYD_LOG_LEVEL) - self.format = self.app.conf.CELERYD_LOG_FORMAT - self.task_format = self.app.conf.CELERYD_TASK_LOG_FORMAT - self.colorize = self.app.conf.CELERYD_LOG_COLOR - - def setup(self, loglevel=None, logfile=None, redirect_stdouts=False, - redirect_level='WARNING', colorize=None, hostname=None): - handled = self.setup_logging_subsystem( - loglevel, logfile, colorize=colorize, hostname=hostname, - ) - if not handled: - if redirect_stdouts: - self.redirect_stdouts(redirect_level) - os.environ.update( - CELERY_LOG_LEVEL=str(loglevel) if loglevel else '', - CELERY_LOG_FILE=str(logfile) if logfile else '', - ) - return handled - - def redirect_stdouts(self, loglevel=None, name='celery.redirected'): - self.redirect_stdouts_to_logger( - get_logger(name), loglevel=loglevel - ) - os.environ.update( - CELERY_LOG_REDIRECT='1', - CELERY_LOG_REDIRECT_LEVEL=str(loglevel or ''), - ) - - def setup_logging_subsystem(self, loglevel=None, logfile=None, format=None, - colorize=None, hostname=None, **kwargs): - if self.already_setup: - return - if logfile and hostname: - logfile = node_format(logfile, hostname) - self.already_setup = True - loglevel = mlevel(loglevel or self.loglevel) - format = format or self.format - colorize = self.supports_color(colorize, logfile) - reset_multiprocessing_logger() - ensure_process_aware_logger() - receivers = signals.setup_logging.send( - sender=None, loglevel=loglevel, logfile=logfile, - format=format, colorize=colorize, - ) - - if not receivers: - root = logging.getLogger() - - if self.app.conf.CELERYD_HIJACK_ROOT_LOGGER: - root.handlers = [] - get_logger('celery').handlers = [] - get_logger('celery.task').handlers = [] - get_logger('celery.redirected').handlers = [] - - # Configure root logger - self._configure_logger( - root, logfile, loglevel, format, colorize, **kwargs - ) - - # Configure the multiprocessing logger - self._configure_logger( - get_multiprocessing_logger(), - logfile, loglevel if MP_LOG else logging.ERROR, - format, colorize, **kwargs - ) - - signals.after_setup_logger.send( - sender=None, logger=root, - loglevel=loglevel, logfile=logfile, - format=format, colorize=colorize, - ) - - # then setup the root task logger. - self.setup_task_loggers(loglevel, logfile, colorize=colorize) - - try: - stream = logging.getLogger().handlers[0].stream - except (AttributeError, IndexError): - pass - else: - set_default_encoding_file(stream) - - # This is a hack for multiprocessing's fork+exec, so that - # logging before Process.run works. - logfile_name = logfile if isinstance(logfile, string_t) else '' - os.environ.update(_MP_FORK_LOGLEVEL_=str(loglevel), - _MP_FORK_LOGFILE_=logfile_name, - _MP_FORK_LOGFORMAT_=format) - return receivers - - def _configure_logger(self, logger, logfile, loglevel, - format, colorize, **kwargs): - if logger is not None: - self.setup_handlers(logger, logfile, format, - colorize, **kwargs) - if loglevel: - logger.setLevel(loglevel) - - def setup_task_loggers(self, loglevel=None, logfile=None, format=None, - colorize=None, propagate=False, **kwargs): - """Setup the task logger. - - If `logfile` is not specified, then `sys.stderr` is used. - - Will return the base task logger object. - - """ - loglevel = mlevel(loglevel or self.loglevel) - format = format or self.task_format - colorize = self.supports_color(colorize, logfile) - - logger = self.setup_handlers( - get_logger('celery.task'), - logfile, format, colorize, - formatter=TaskFormatter, **kwargs - ) - logger.setLevel(loglevel) - logger.propagate = int(propagate) # this is an int for some reason. - # better to not question why. - signals.after_setup_task_logger.send( - sender=None, logger=logger, - loglevel=loglevel, logfile=logfile, - format=format, colorize=colorize, - ) - return logger - - def redirect_stdouts_to_logger(self, logger, loglevel=None, - stdout=True, stderr=True): - """Redirect :class:`sys.stdout` and :class:`sys.stderr` to a - logging instance. - - :param logger: The :class:`logging.Logger` instance to redirect to. - :param loglevel: The loglevel redirected messages will be logged as. - - """ - proxy = LoggingProxy(logger, loglevel) - if stdout: - sys.stdout = proxy - if stderr: - sys.stderr = proxy - return proxy - - def supports_color(self, colorize=None, logfile=None): - colorize = self.colorize if colorize is None else colorize - if self.app.IS_WINDOWS: - # Windows does not support ANSI color codes. - return False - if colorize or colorize is None: - # Only use color if there is no active log file - # and stderr is an actual terminal. - return logfile is None and isatty(sys.stderr) - return colorize - - def colored(self, logfile=None, enabled=None): - return colored(enabled=self.supports_color(enabled, logfile)) - - def setup_handlers(self, logger, logfile, format, colorize, - formatter=ColorFormatter, **kwargs): - if self._is_configured(logger): - return logger - handler = self._detect_handler(logfile) - handler.setFormatter(formatter(format, use_color=colorize)) - logger.addHandler(handler) - return logger - - def _detect_handler(self, logfile=None): - """Create log handler with either a filename, an open stream - or :const:`None` (stderr).""" - logfile = sys.__stderr__ if logfile is None else logfile - if hasattr(logfile, 'write'): - return logging.StreamHandler(logfile) - return WatchedFileHandler(logfile) - - def _has_handler(self, logger): - if logger.handlers: - return any(not isinstance(h, NullHandler) for h in logger.handlers) - - def _is_configured(self, logger): - return self._has_handler(logger) and not getattr( - logger, '_rudimentary_setup', False) - - def setup_logger(self, name='celery', *args, **kwargs): - """Deprecated: No longer used.""" - self.setup_logging_subsystem(*args, **kwargs) - return logging.root - - def get_default_logger(self, name='celery', **kwargs): - return get_logger(name) - - @class_property - def already_setup(cls): - return cls._setup - - @already_setup.setter # noqa - def already_setup(cls, was_setup): - cls._setup = was_setup diff --git a/awx/lib/site-packages/celery/app/registry.py b/awx/lib/site-packages/celery/app/registry.py deleted file mode 100644 index 7046554d92..0000000000 --- a/awx/lib/site-packages/celery/app/registry.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.registry - ~~~~~~~~~~~~~~~~~~~ - - Registry of available tasks. - -""" -from __future__ import absolute_import - -import inspect - -from importlib import import_module - -from celery._state import get_current_app -from celery.exceptions import NotRegistered -from celery.five import items - -__all__ = ['TaskRegistry'] - - -class TaskRegistry(dict): - NotRegistered = NotRegistered - - def __missing__(self, key): - raise self.NotRegistered(key) - - def register(self, task): - """Register a task in the task registry. - - The task will be automatically instantiated if not already an - instance. - - """ - self[task.name] = inspect.isclass(task) and task() or task - - def unregister(self, name): - """Unregister task by name. - - :param name: name of the task to unregister, or a - :class:`celery.task.base.Task` with a valid `name` attribute. - - :raises celery.exceptions.NotRegistered: if the task has not - been registered. - - """ - try: - self.pop(getattr(name, 'name', name)) - except KeyError: - raise self.NotRegistered(name) - - # -- these methods are irrelevant now and will be removed in 4.0 - def regular(self): - return self.filter_types('regular') - - def periodic(self): - return self.filter_types('periodic') - - def filter_types(self, type): - return dict((name, task) for name, task in items(self) - if getattr(task, 'type', 'regular') == type) - - -def _unpickle_task(name): - return get_current_app().tasks[name] - - -def _unpickle_task_v2(name, module=None): - if module: - import_module(module) - return get_current_app().tasks[name] diff --git a/awx/lib/site-packages/celery/app/routes.py b/awx/lib/site-packages/celery/app/routes.py deleted file mode 100644 index d654f9d705..0000000000 --- a/awx/lib/site-packages/celery/app/routes.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.routes - ~~~~~~~~~~~~~ - - Contains utilities for working with task routers, - (:setting:`CELERY_ROUTES`). - -""" -from __future__ import absolute_import - -from celery.exceptions import QueueNotFound -from celery.five import string_t -from celery.utils import lpmerge -from celery.utils.functional import firstmethod, mlazy -from celery.utils.imports import instantiate - -__all__ = ['MapRoute', 'Router', 'prepare'] - -_first_route = firstmethod('route_for_task') - - -class MapRoute(object): - """Creates a router out of a :class:`dict`.""" - - def __init__(self, map): - self.map = map - - def route_for_task(self, task, *args, **kwargs): - try: - return dict(self.map[task]) - except KeyError: - pass - - -class Router(object): - - def __init__(self, routes=None, queues=None, - create_missing=False, app=None): - self.app = app - self.queues = {} if queues is None else queues - self.routes = [] if routes is None else routes - self.create_missing = create_missing - - def route(self, options, task, args=(), kwargs={}): - options = self.expand_destination(options) # expands 'queue' - if self.routes: - route = self.lookup_route(task, args, kwargs) - if route: # expands 'queue' in route. - return lpmerge(self.expand_destination(route), options) - if 'queue' not in options: - options = lpmerge(self.expand_destination( - self.app.conf.CELERY_DEFAULT_QUEUE), options) - return options - - def expand_destination(self, route): - # Route can be a queue name: convenient for direct exchanges. - if isinstance(route, string_t): - queue, route = route, {} - else: - # can use defaults from configured queue, but override specific - # things (like the routing_key): great for topic exchanges. - queue = route.pop('queue', None) - - if queue: - try: - Q = self.queues[queue] # noqa - except KeyError: - raise QueueNotFound( - 'Queue {0!r} missing from CELERY_QUEUES'.format(queue)) - # needs to be declared by publisher - route['queue'] = Q - return route - - def lookup_route(self, task, args=None, kwargs=None): - return _first_route(self.routes, task, args, kwargs) - - -def prepare(routes): - """Expands the :setting:`CELERY_ROUTES` setting.""" - - def expand_route(route): - if isinstance(route, dict): - return MapRoute(route) - if isinstance(route, string_t): - return mlazy(instantiate, route) - return route - - if routes is None: - return () - if not isinstance(routes, (list, tuple)): - routes = (routes, ) - return [expand_route(route) for route in routes] diff --git a/awx/lib/site-packages/celery/app/task.py b/awx/lib/site-packages/celery/app/task.py deleted file mode 100644 index 79f6d3fca4..0000000000 --- a/awx/lib/site-packages/celery/app/task.py +++ /dev/null @@ -1,921 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.task - ~~~~~~~~~~~~~~~ - - Task Implementation: Task request context, and the base task class. - -""" -from __future__ import absolute_import - -import sys - -from billiard.einfo import ExceptionInfo - -from celery import current_app -from celery import states -from celery._state import _task_stack -from celery.canvas import signature -from celery.exceptions import MaxRetriesExceededError, Reject, Retry -from celery.five import class_property, items, with_metaclass -from celery.local import Proxy -from celery.result import EagerResult -from celery.utils import gen_task_name, fun_takes_kwargs, uuid, maybe_reraise -from celery.utils.functional import mattrgetter, maybe_list -from celery.utils.imports import instantiate -from celery.utils.mail import ErrorMail - -from .annotations import resolve_all as resolve_all_annotations -from .registry import _unpickle_task_v2 -from .utils import appstr - -__all__ = ['Context', 'Task'] - -#: extracts attributes related to publishing a message from an object. -extract_exec_options = mattrgetter( - 'queue', 'routing_key', 'exchange', 'priority', 'expires', - 'serializer', 'delivery_mode', 'compression', 'time_limit', - 'soft_time_limit', 'immediate', 'mandatory', # imm+man is deprecated -) - -# We take __repr__ very seriously around here ;) -R_BOUND_TASK = '<class {0.__name__} of {app}{flags}>' -R_UNBOUND_TASK = '<unbound {0.__name__}{flags}>' -R_SELF_TASK = '<@task {0.name} bound to other {0.__self__}>' -R_INSTANCE = '<@task: {0.name} of {app}{flags}>' - - -class _CompatShared(object): - - def __init__(self, name, cons): - self.name = name - self.cons = cons - - def __hash__(self): - return hash(self.name) - - def __repr__(self): - return '<OldTask: %r>' % (self.name, ) - - def __call__(self, app): - return self.cons(app) - - -def _strflags(flags, default=''): - if flags: - return ' ({0})'.format(', '.join(flags)) - return default - - -def _reprtask(task, fmt=None, flags=None): - flags = list(flags) if flags is not None else [] - flags.append('v2 compatible') if task.__v2_compat__ else None - if not fmt: - fmt = R_BOUND_TASK if task._app else R_UNBOUND_TASK - return fmt.format( - task, flags=_strflags(flags), - app=appstr(task._app) if task._app else None, - ) - - -class Context(object): - # Default context - logfile = None - loglevel = None - hostname = None - id = None - args = None - kwargs = None - retries = 0 - eta = None - expires = None - is_eager = False - headers = None - delivery_info = None - reply_to = None - correlation_id = None - taskset = None # compat alias to group - group = None - chord = None - utc = None - called_directly = True - callbacks = None - errbacks = None - timelimit = None - _children = None # see property - _protected = 0 - - def __init__(self, *args, **kwargs): - self.update(*args, **kwargs) - - def update(self, *args, **kwargs): - return self.__dict__.update(*args, **kwargs) - - def clear(self): - return self.__dict__.clear() - - def get(self, key, default=None): - return getattr(self, key, default) - - def __repr__(self): - return '<Context: {0!r}>'.format(vars(self)) - - @property - def children(self): - # children must be an empy list for every thread - if self._children is None: - self._children = [] - return self._children - - -class TaskType(type): - """Meta class for tasks. - - Automatically registers the task in the task registry (except - if the :attr:`Task.abstract`` attribute is set). - - If no :attr:`Task.name` attribute is provided, then the name is generated - from the module and class name. - - """ - _creation_count = {} # used by old non-abstract task classes - - def __new__(cls, name, bases, attrs): - new = super(TaskType, cls).__new__ - task_module = attrs.get('__module__') or '__main__' - - # - Abstract class: abstract attribute should not be inherited. - abstract = attrs.pop('abstract', None) - if abstract or not attrs.get('autoregister', True): - return new(cls, name, bases, attrs) - - # The 'app' attribute is now a property, with the real app located - # in the '_app' attribute. Previously this was a regular attribute, - # so we should support classes defining it. - app = attrs.pop('_app', None) or attrs.pop('app', None) - - # Attempt to inherit app from one the bases - if not isinstance(app, Proxy) and app is None: - for base in bases: - if getattr(base, '_app', None): - app = base._app - break - else: - app = current_app._get_current_object() - attrs['_app'] = app - - # - Automatically generate missing/empty name. - task_name = attrs.get('name') - if not task_name: - attrs['name'] = task_name = gen_task_name(app, name, task_module) - - if not attrs.get('_decorated'): - # non decorated tasks must also be shared in case - # an app is created multiple times due to modules - # imported under multiple names. - # Hairy stuff, here to be compatible with 2.x. - # People should not use non-abstract task classes anymore, - # use the task decorator. - from celery.app.builtins import shared_task - unique_name = '.'.join([task_module, name]) - if unique_name not in cls._creation_count: - # the creation count is used as a safety - # so that the same task is not added recursively - # to the set of constructors. - cls._creation_count[unique_name] = 1 - shared_task(_CompatShared( - unique_name, - lambda app: TaskType.__new__(cls, name, bases, - dict(attrs, _app=app)), - )) - - # - Create and register class. - # Because of the way import happens (recursively) - # we may or may not be the first time the task tries to register - # with the framework. There should only be one class for each task - # name, so we always return the registered version. - tasks = app._tasks - if task_name not in tasks: - tasks.register(new(cls, name, bases, attrs)) - instance = tasks[task_name] - instance.bind(app) - return instance.__class__ - - def __repr__(cls): - return _reprtask(cls) - - -@with_metaclass(TaskType) -class Task(object): - """Task base class. - - When called tasks apply the :meth:`run` method. This method must - be defined by all tasks (that is unless the :meth:`__call__` method - is overridden). - - """ - __trace__ = None - __v2_compat__ = False # set by old base in celery.task.base - - ErrorMail = ErrorMail - MaxRetriesExceededError = MaxRetriesExceededError - - #: Execution strategy used, or the qualified name of one. - Strategy = 'celery.worker.strategy:default' - - #: This is the instance bound to if the task is a method of a class. - __self__ = None - - #: The application instance associated with this task class. - _app = None - - #: Name of the task. - name = None - - #: If :const:`True` the task is an abstract base class. - abstract = True - - #: If disabled the worker will not forward magic keyword arguments. - #: Deprecated and scheduled for removal in v4.0. - accept_magic_kwargs = False - - #: Maximum number of retries before giving up. If set to :const:`None`, - #: it will **never** stop retrying. - max_retries = 3 - - #: Default time in seconds before a retry of the task should be - #: executed. 3 minutes by default. - default_retry_delay = 3 * 60 - - #: Rate limit for this task type. Examples: :const:`None` (no rate - #: limit), `'100/s'` (hundred tasks a second), `'100/m'` (hundred tasks - #: a minute),`'100/h'` (hundred tasks an hour) - rate_limit = None - - #: If enabled the worker will not store task state and return values - #: for this task. Defaults to the :setting:`CELERY_IGNORE_RESULT` - #: setting. - ignore_result = None - - #: If enabled the request will keep track of subtasks started by - #: this task, and this information will be sent with the result - #: (``result.children``). - trail = True - - #: When enabled errors will be stored even if the task is otherwise - #: configured to ignore results. - store_errors_even_if_ignored = None - - #: If enabled an email will be sent to :setting:`ADMINS` whenever a task - #: of this type fails. - send_error_emails = None - - #: The name of a serializer that are registered with - #: :mod:`kombu.serialization.registry`. Default is `'pickle'`. - serializer = None - - #: Hard time limit. - #: Defaults to the :setting:`CELERYD_TASK_TIME_LIMIT` setting. - time_limit = None - - #: Soft time limit. - #: Defaults to the :setting:`CELERYD_TASK_SOFT_TIME_LIMIT` setting. - soft_time_limit = None - - #: The result store backend used for this task. - backend = None - - #: If disabled this task won't be registered automatically. - autoregister = True - - #: If enabled the task will report its status as 'started' when the task - #: is executed by a worker. Disabled by default as the normal behaviour - #: is to not report that level of granularity. Tasks are either pending, - #: finished, or waiting to be retried. - #: - #: Having a 'started' status can be useful for when there are long - #: running tasks and there is a need to report which task is currently - #: running. - #: - #: The application default can be overridden using the - #: :setting:`CELERY_TRACK_STARTED` setting. - track_started = None - - #: When enabled messages for this task will be acknowledged **after** - #: the task has been executed, and not *just before* which is the - #: default behavior. - #: - #: Please note that this means the task may be executed twice if the - #: worker crashes mid execution (which may be acceptable for some - #: applications). - #: - #: The application default can be overridden with the - #: :setting:`CELERY_ACKS_LATE` setting. - acks_late = None - - #: List/tuple of expected exceptions. - #: - #: These are errors that are expected in normal operation - #: and that should not be regarded as a real error by the worker. - #: Currently this means that the state will be updated to an error - #: state, but the worker will not log the event as an error. - throws = () - - #: Default task expiry time. - expires = None - - #: Some may expect a request to exist even if the task has not been - #: called. This should probably be deprecated. - _default_request = None - - _exec_options = None - - __bound__ = False - - from_config = ( - ('send_error_emails', 'CELERY_SEND_TASK_ERROR_EMAILS'), - ('serializer', 'CELERY_TASK_SERIALIZER'), - ('rate_limit', 'CELERY_DEFAULT_RATE_LIMIT'), - ('track_started', 'CELERY_TRACK_STARTED'), - ('acks_late', 'CELERY_ACKS_LATE'), - ('ignore_result', 'CELERY_IGNORE_RESULT'), - ('store_errors_even_if_ignored', - 'CELERY_STORE_ERRORS_EVEN_IF_IGNORED'), - ) - - _backend = None # set by backend property. - - __bound__ = False - - # - Tasks are lazily bound, so that configuration is not set - # - until the task is actually used - - @classmethod - def bind(self, app): - was_bound, self.__bound__ = self.__bound__, True - self._app = app - conf = app.conf - self._exec_options = None # clear option cache - - for attr_name, config_name in self.from_config: - if getattr(self, attr_name, None) is None: - setattr(self, attr_name, conf[config_name]) - if self.accept_magic_kwargs is None: - self.accept_magic_kwargs = app.accept_magic_kwargs - - # decorate with annotations from config. - if not was_bound: - self.annotate() - - from celery.utils.threads import LocalStack - self.request_stack = LocalStack() - - # PeriodicTask uses this to add itself to the PeriodicTask schedule. - self.on_bound(app) - - return app - - @classmethod - def on_bound(self, app): - """This method can be defined to do additional actions when the - task class is bound to an app.""" - pass - - @classmethod - def _get_app(self): - if self._app is None: - self._app = current_app - if not self.__bound__: - # The app property's __set__ method is not called - # if Task.app is set (on the class), so must bind on use. - self.bind(self._app) - return self._app - app = class_property(_get_app, bind) - - @classmethod - def annotate(self): - for d in resolve_all_annotations(self.app.annotations, self): - for key, value in items(d): - if key.startswith('@'): - self.add_around(key[1:], value) - else: - setattr(self, key, value) - - @classmethod - def add_around(self, attr, around): - orig = getattr(self, attr) - if getattr(orig, '__wrapped__', None): - orig = orig.__wrapped__ - meth = around(orig) - meth.__wrapped__ = orig - setattr(self, attr, meth) - - def __call__(self, *args, **kwargs): - _task_stack.push(self) - self.push_request() - try: - # add self if this is a bound task - if self.__self__ is not None: - return self.run(self.__self__, *args, **kwargs) - return self.run(*args, **kwargs) - finally: - self.pop_request() - _task_stack.pop() - - def __reduce__(self): - # - tasks are pickled into the name of the task only, and the reciever - # - simply grabs it from the local registry. - # - in later versions the module of the task is also included, - # - and the receiving side tries to import that module so that - # - it will work even if the task has not been registered. - mod = type(self).__module__ - mod = mod if mod and mod in sys.modules else None - return (_unpickle_task_v2, (self.name, mod), None) - - def run(self, *args, **kwargs): - """The body of the task executed by workers.""" - raise NotImplementedError('Tasks must define the run method.') - - def start_strategy(self, app, consumer, **kwargs): - return instantiate(self.Strategy, self, app, consumer, **kwargs) - - def delay(self, *args, **kwargs): - """Star argument version of :meth:`apply_async`. - - Does not support the extra options enabled by :meth:`apply_async`. - - :param \*args: positional arguments passed on to the task. - :param \*\*kwargs: keyword arguments passed on to the task. - - :returns :class:`celery.result.AsyncResult`: - - """ - return self.apply_async(args, kwargs) - - def apply_async(self, args=None, kwargs=None, task_id=None, producer=None, - link=None, link_error=None, **options): - """Apply tasks asynchronously by sending a message. - - :keyword args: The positional arguments to pass on to the - task (a :class:`list` or :class:`tuple`). - - :keyword kwargs: The keyword arguments to pass on to the - task (a :class:`dict`) - - :keyword countdown: Number of seconds into the future that the - task should execute. Defaults to immediate - execution. - - :keyword eta: A :class:`~datetime.datetime` object describing - the absolute time and date of when the task should - be executed. May not be specified if `countdown` - is also supplied. - - :keyword expires: Either a :class:`int`, describing the number of - seconds, or a :class:`~datetime.datetime` object - that describes the absolute time and date of when - the task should expire. The task will not be - executed after the expiration time. - - :keyword connection: Re-use existing broker connection instead - of establishing a new one. - - :keyword retry: If enabled sending of the task message will be retried - in the event of connection loss or failure. Default - is taken from the :setting:`CELERY_TASK_PUBLISH_RETRY` - setting. Note you need to handle the - producer/connection manually for this to work. - - :keyword retry_policy: Override the retry policy used. See the - :setting:`CELERY_TASK_PUBLISH_RETRY` setting. - - :keyword routing_key: Custom routing key used to route the task to a - worker server. If in combination with a - ``queue`` argument only used to specify custom - routing keys to topic exchanges. - - :keyword queue: The queue to route the task to. This must be a key - present in :setting:`CELERY_QUEUES`, or - :setting:`CELERY_CREATE_MISSING_QUEUES` must be - enabled. See :ref:`guide-routing` for more - information. - - :keyword exchange: Named custom exchange to send the task to. - Usually not used in combination with the ``queue`` - argument. - - :keyword priority: The task priority, a number between 0 and 9. - Defaults to the :attr:`priority` attribute. - - :keyword serializer: A string identifying the default - serialization method to use. Can be `pickle`, - `json`, `yaml`, `msgpack` or any custom - serialization method that has been registered - with :mod:`kombu.serialization.registry`. - Defaults to the :attr:`serializer` attribute. - - :keyword compression: A string identifying the compression method - to use. Can be one of ``zlib``, ``bzip2``, - or any custom compression methods registered with - :func:`kombu.compression.register`. Defaults to - the :setting:`CELERY_MESSAGE_COMPRESSION` - setting. - :keyword link: A single, or a list of tasks to apply if the - task exits successfully. - :keyword link_error: A single, or a list of tasks to apply - if an error occurs while executing the task. - - :keyword producer: :class:~@amqp.TaskProducer` instance to use. - :keyword add_to_parent: If set to True (default) and the task - is applied while executing another task, then the result - will be appended to the parent tasks ``request.children`` - attribute. Trailing can also be disabled by default using the - :attr:`trail` attribute - :keyword publisher: Deprecated alias to ``producer``. - - Also supports all keyword arguments supported by - :meth:`kombu.Producer.publish`. - - .. note:: - If the :setting:`CELERY_ALWAYS_EAGER` setting is set, it will - be replaced by a local :func:`apply` call instead. - - """ - app = self._get_app() - if app.conf.CELERY_ALWAYS_EAGER: - return self.apply(args, kwargs, task_id=task_id or uuid(), - link=link, link_error=link_error, **options) - # add 'self' if this is a "task_method". - if self.__self__ is not None: - args = args if isinstance(args, tuple) else tuple(args or ()) - args = (self.__self__, ) + args - return app.send_task( - self.name, args, kwargs, task_id=task_id, producer=producer, - link=link, link_error=link_error, result_cls=self.AsyncResult, - **dict(self._get_exec_options(), **options) - ) - - def subtask_from_request(self, request=None, args=None, kwargs=None, - queue=None, **extra_options): - request = self.request if request is None else request - args = request.args if args is None else args - kwargs = request.kwargs if kwargs is None else kwargs - limit_hard, limit_soft = request.timelimit or (None, None) - options = { - 'task_id': request.id, - 'link': request.callbacks, - 'link_error': request.errbacks, - 'group_id': request.group, - 'chord': request.chord, - 'soft_time_limit': limit_soft, - 'time_limit': limit_hard, - } - options.update( - {'queue': queue} if queue else (request.delivery_info or {}) - ) - return self.subtask(args, kwargs, options, type=self, **extra_options) - - def retry(self, args=None, kwargs=None, exc=None, throw=True, - eta=None, countdown=None, max_retries=None, **options): - """Retry the task. - - :param args: Positional arguments to retry with. - :param kwargs: Keyword arguments to retry with. - :keyword exc: Custom exception to report when the max restart - limit has been exceeded (default: - :exc:`~@MaxRetriesExceededError`). - - If this argument is set and retry is called while - an exception was raised (``sys.exc_info()`` is set) - it will attempt to reraise the current exception. - - If no exception was raised it will raise the ``exc`` - argument provided. - :keyword countdown: Time in seconds to delay the retry for. - :keyword eta: Explicit time and date to run the retry at - (must be a :class:`~datetime.datetime` instance). - :keyword max_retries: If set, overrides the default retry limit. - :keyword time_limit: If set, overrides the default time limit. - :keyword soft_time_limit: If set, overrides the default soft - time limit. - :keyword \*\*options: Any extra options to pass on to - meth:`apply_async`. - :keyword throw: If this is :const:`False`, do not raise the - :exc:`~@Retry` exception, - that tells the worker to mark the task as being - retried. Note that this means the task will be - marked as failed if the task raises an exception, - or successful if it returns. - - :raises celery.exceptions.Retry: To tell the worker that - the task has been re-sent for retry. This always happens, - unless the `throw` keyword argument has been explicitly set - to :const:`False`, and is considered normal operation. - - **Example** - - .. code-block:: python - - >>> from imaginary_twitter_lib import Twitter - >>> from proj.celery import app - - >>> @app.task() - ... def tweet(auth, message): - ... twitter = Twitter(oauth=auth) - ... try: - ... twitter.post_status_update(message) - ... except twitter.FailWhale as exc: - ... # Retry in 5 minutes. - ... raise tweet.retry(countdown=60 * 5, exc=exc) - - Although the task will never return above as `retry` raises an - exception to notify the worker, we use `raise` in front of the retry - to convey that the rest of the block will not be executed. - - """ - request = self.request - retries = request.retries + 1 - max_retries = self.max_retries if max_retries is None else max_retries - - # Not in worker or emulated by (apply/always_eager), - # so just raise the original exception. - if request.called_directly: - maybe_reraise() # raise orig stack if PyErr_Occurred - raise exc or Retry('Task can be retried', None) - - if not eta and countdown is None: - countdown = self.default_retry_delay - - is_eager = request.is_eager - S = self.subtask_from_request( - request, args, kwargs, - countdown=countdown, eta=eta, retries=retries, - **options - ) - - if max_retries is not None and retries > max_retries: - if exc: - # first try to reraise the original exception - maybe_reraise() - # or if not in an except block then raise the custom exc. - raise exc() - raise self.MaxRetriesExceededError( - "Can't retry {0}[{1}] args:{2} kwargs:{3}".format( - self.name, request.id, S.args, S.kwargs)) - - # If task was executed eagerly using apply(), - # then the retry must also be executed eagerly. - try: - S.apply().get() if is_eager else S.apply_async() - except Exception as exc: - if is_eager: - raise - raise Reject(exc, requeue=True) - ret = Retry(exc=exc, when=eta or countdown) - if throw: - raise ret - return ret - - def apply(self, args=None, kwargs=None, - link=None, link_error=None, **options): - """Execute this task locally, by blocking until the task returns. - - :param args: positional arguments passed on to the task. - :param kwargs: keyword arguments passed on to the task. - :keyword throw: Re-raise task exceptions. Defaults to - the :setting:`CELERY_EAGER_PROPAGATES_EXCEPTIONS` - setting. - - :rtype :class:`celery.result.EagerResult`: - - """ - # trace imports Task, so need to import inline. - from celery.app.trace import eager_trace_task - - app = self._get_app() - args = args or () - # add 'self' if this is a bound method. - if self.__self__ is not None: - args = (self.__self__, ) + tuple(args) - kwargs = kwargs or {} - task_id = options.get('task_id') or uuid() - retries = options.get('retries', 0) - throw = app.either('CELERY_EAGER_PROPAGATES_EXCEPTIONS', - options.pop('throw', None)) - - # Make sure we get the task instance, not class. - task = app._tasks[self.name] - - request = {'id': task_id, - 'retries': retries, - 'is_eager': True, - 'logfile': options.get('logfile'), - 'loglevel': options.get('loglevel', 0), - 'callbacks': maybe_list(link), - 'errbacks': maybe_list(link_error), - 'headers': options.get('headers'), - 'delivery_info': {'is_eager': True}} - if self.accept_magic_kwargs: - default_kwargs = {'task_name': task.name, - 'task_id': task_id, - 'task_retries': retries, - 'task_is_eager': True, - 'logfile': options.get('logfile'), - 'loglevel': options.get('loglevel', 0), - 'delivery_info': {'is_eager': True}} - supported_keys = fun_takes_kwargs(task.run, default_kwargs) - extend_with = dict((key, val) - for key, val in items(default_kwargs) - if key in supported_keys) - kwargs.update(extend_with) - - tb = None - retval, info = eager_trace_task(task, task_id, args, kwargs, - app=self._get_app(), - request=request, propagate=throw) - if isinstance(retval, ExceptionInfo): - retval, tb = retval.exception, retval.traceback - state = states.SUCCESS if info is None else info.state - return EagerResult(task_id, retval, state, traceback=tb) - - def AsyncResult(self, task_id, **kwargs): - """Get AsyncResult instance for this kind of task. - - :param task_id: Task id to get result for. - - """ - return self._get_app().AsyncResult(task_id, backend=self.backend, - task_name=self.name, **kwargs) - - def subtask(self, args=None, *starargs, **starkwargs): - """Return :class:`~celery.signature` object for - this task, wrapping arguments and execution options - for a single task invocation.""" - starkwargs.setdefault('app', self.app) - return signature(self, args, *starargs, **starkwargs) - - def s(self, *args, **kwargs): - """``.s(*a, **k) -> .subtask(a, k)``""" - return self.subtask(args, kwargs) - - def si(self, *args, **kwargs): - """``.si(*a, **k) -> .subtask(a, k, immutable=True)``""" - return self.subtask(args, kwargs, immutable=True) - - def chunks(self, it, n): - """Creates a :class:`~celery.canvas.chunks` task for this task.""" - from celery import chunks - return chunks(self.s(), it, n, app=self.app) - - def map(self, it): - """Creates a :class:`~celery.canvas.xmap` task from ``it``.""" - from celery import xmap - return xmap(self.s(), it, app=self.app) - - def starmap(self, it): - """Creates a :class:`~celery.canvas.xstarmap` task from ``it``.""" - from celery import xstarmap - return xstarmap(self.s(), it, app=self.app) - - def send_event(self, type_, **fields): - req = self.request - with self.app.events.default_dispatcher(hostname=req.hostname) as d: - return d.send(type_, uuid=req.id, **fields) - - def update_state(self, task_id=None, state=None, meta=None): - """Update task state. - - :keyword task_id: Id of the task to update, defaults to the - id of the current task - :keyword state: New state (:class:`str`). - :keyword meta: State metadata (:class:`dict`). - - - - """ - if task_id is None: - task_id = self.request.id - self.backend.store_result(task_id, meta, state) - - def on_success(self, retval, task_id, args, kwargs): - """Success handler. - - Run by the worker if the task executes successfully. - - :param retval: The return value of the task. - :param task_id: Unique id of the executed task. - :param args: Original arguments for the executed task. - :param kwargs: Original keyword arguments for the executed task. - - The return value of this handler is ignored. - - """ - pass - - def on_retry(self, exc, task_id, args, kwargs, einfo): - """Retry handler. - - This is run by the worker when the task is to be retried. - - :param exc: The exception sent to :meth:`retry`. - :param task_id: Unique id of the retried task. - :param args: Original arguments for the retried task. - :param kwargs: Original keyword arguments for the retried task. - - :keyword einfo: :class:`~billiard.einfo.ExceptionInfo` - instance, containing the traceback. - - The return value of this handler is ignored. - - """ - pass - - def on_failure(self, exc, task_id, args, kwargs, einfo): - """Error handler. - - This is run by the worker when the task fails. - - :param exc: The exception raised by the task. - :param task_id: Unique id of the failed task. - :param args: Original arguments for the task that failed. - :param kwargs: Original keyword arguments for the task - that failed. - - :keyword einfo: :class:`~billiard.einfo.ExceptionInfo` - instance, containing the traceback. - - The return value of this handler is ignored. - - """ - pass - - def after_return(self, status, retval, task_id, args, kwargs, einfo): - """Handler called after the task returns. - - :param status: Current task state. - :param retval: Task return value/exception. - :param task_id: Unique id of the task. - :param args: Original arguments for the task that failed. - :param kwargs: Original keyword arguments for the task - that failed. - - :keyword einfo: :class:`~billiard.einfo.ExceptionInfo` - instance, containing the traceback (if any). - - The return value of this handler is ignored. - - """ - pass - - def send_error_email(self, context, exc, **kwargs): - if self.send_error_emails and \ - not getattr(self, 'disable_error_emails', None): - self.ErrorMail(self, **kwargs).send(context, exc) - - def add_trail(self, result): - if self.trail: - self.request.children.append(result) - return result - - def push_request(self, *args, **kwargs): - self.request_stack.push(Context(*args, **kwargs)) - - def pop_request(self): - self.request_stack.pop() - - def __repr__(self): - """`repr(task)`""" - return _reprtask(self, R_SELF_TASK if self.__self__ else R_INSTANCE) - - def _get_request(self): - """Get current request object.""" - req = self.request_stack.top - if req is None: - # task was not called, but some may still expect a request - # to be there, perhaps that should be deprecated. - if self._default_request is None: - self._default_request = Context() - return self._default_request - return req - request = property(_get_request) - - def _get_exec_options(self): - if self._exec_options is None: - self._exec_options = extract_exec_options(self) - return self._exec_options - - @property - def backend(self): - backend = self._backend - if backend is None: - return self.app.backend - return backend - - @backend.setter - def backend(self, value): # noqa - self._backend = value - - @property - def __name__(self): - return self.__class__.__name__ -BaseTask = Task # compat alias diff --git a/awx/lib/site-packages/celery/app/trace.py b/awx/lib/site-packages/celery/app/trace.py deleted file mode 100644 index b4c271631c..0000000000 --- a/awx/lib/site-packages/celery/app/trace.py +++ /dev/null @@ -1,424 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.trace - ~~~~~~~~~~~~~~~~ - - This module defines how the task execution is traced: - errors are recorded, handlers are applied and so on. - -""" -from __future__ import absolute_import - -# ## --- -# This is the heart of the worker, the inner loop so to speak. -# It used to be split up into nice little classes and methods, -# but in the end it only resulted in bad performance and horrible tracebacks, -# so instead we now use one closure per task class. - -import os -import socket -import sys - -from warnings import warn - -from billiard.einfo import ExceptionInfo -from kombu.exceptions import EncodeError -from kombu.utils import kwdict - -from celery import current_app, group -from celery import states, signals -from celery._state import _task_stack -from celery.app import set_default_app -from celery.app.task import Task as BaseTask, Context -from celery.exceptions import Ignore, Reject, Retry -from celery.utils.log import get_logger -from celery.utils.objects import mro_lookup -from celery.utils.serialization import ( - get_pickleable_exception, - get_pickleable_etype, -) - -__all__ = ['TraceInfo', 'build_tracer', 'trace_task', 'eager_trace_task', - 'setup_worker_optimizations', 'reset_worker_optimizations'] - -_logger = get_logger(__name__) - -send_prerun = signals.task_prerun.send -send_postrun = signals.task_postrun.send -send_success = signals.task_success.send -STARTED = states.STARTED -SUCCESS = states.SUCCESS -IGNORED = states.IGNORED -REJECTED = states.REJECTED -RETRY = states.RETRY -FAILURE = states.FAILURE -EXCEPTION_STATES = states.EXCEPTION_STATES -IGNORE_STATES = frozenset([IGNORED, RETRY, REJECTED]) - -#: set by :func:`setup_worker_optimizations` -_tasks = None -_patched = {} - - -def task_has_custom(task, attr): - """Return true if the task or one of its bases - defines ``attr`` (excluding the one in BaseTask).""" - return mro_lookup(task.__class__, attr, stop=(BaseTask, object), - monkey_patched=['celery.app.task']) - - -class TraceInfo(object): - __slots__ = ('state', 'retval') - - def __init__(self, state, retval=None): - self.state = state - self.retval = retval - - def handle_error_state(self, task, eager=False): - store_errors = not eager - if task.ignore_result: - store_errors = task.store_errors_even_if_ignored - - return { - RETRY: self.handle_retry, - FAILURE: self.handle_failure, - }[self.state](task, store_errors=store_errors) - - def handle_retry(self, task, store_errors=True): - """Handle retry exception.""" - # the exception raised is the Retry semi-predicate, - # and it's exc' attribute is the original exception raised (if any). - req = task.request - type_, _, tb = sys.exc_info() - try: - reason = self.retval - einfo = ExceptionInfo((type_, reason, tb)) - if store_errors: - task.backend.mark_as_retry( - req.id, reason.exc, einfo.traceback, request=req, - ) - task.on_retry(reason.exc, req.id, req.args, req.kwargs, einfo) - signals.task_retry.send(sender=task, request=req, - reason=reason, einfo=einfo) - return einfo - finally: - del(tb) - - def handle_failure(self, task, store_errors=True): - """Handle exception.""" - req = task.request - type_, _, tb = sys.exc_info() - try: - exc = self.retval - einfo = ExceptionInfo() - einfo.exception = get_pickleable_exception(einfo.exception) - einfo.type = get_pickleable_etype(einfo.type) - if store_errors: - task.backend.mark_as_failure( - req.id, exc, einfo.traceback, request=req, - ) - task.on_failure(exc, req.id, req.args, req.kwargs, einfo) - signals.task_failure.send(sender=task, task_id=req.id, - exception=exc, args=req.args, - kwargs=req.kwargs, - traceback=tb, - einfo=einfo) - return einfo - finally: - del(tb) - - -def build_tracer(name, task, loader=None, hostname=None, store_errors=True, - Info=TraceInfo, eager=False, propagate=False, app=None, - IGNORE_STATES=IGNORE_STATES): - """Return a function that traces task execution; catches all - exceptions and updates result backend with the state and result - - If the call was successful, it saves the result to the task result - backend, and sets the task status to `"SUCCESS"`. - - If the call raises :exc:`~@Retry`, it extracts - the original exception, uses that as the result and sets the task state - to `"RETRY"`. - - If the call results in an exception, it saves the exception as the task - result, and sets the task state to `"FAILURE"`. - - Return a function that takes the following arguments: - - :param uuid: The id of the task. - :param args: List of positional args to pass on to the function. - :param kwargs: Keyword arguments mapping to pass on to the function. - :keyword request: Request dict. - - """ - # If the task doesn't define a custom __call__ method - # we optimize it away by simply calling the run method directly, - # saving the extra method call and a line less in the stack trace. - fun = task if task_has_custom(task, '__call__') else task.run - - loader = loader or app.loader - backend = task.backend - ignore_result = task.ignore_result - track_started = task.track_started - track_started = not eager and (task.track_started and not ignore_result) - publish_result = not eager and not ignore_result - hostname = hostname or socket.gethostname() - - loader_task_init = loader.on_task_init - loader_cleanup = loader.on_process_cleanup - - task_on_success = None - task_after_return = None - if task_has_custom(task, 'on_success'): - task_on_success = task.on_success - if task_has_custom(task, 'after_return'): - task_after_return = task.after_return - - store_result = backend.store_result - backend_cleanup = backend.process_cleanup - - pid = os.getpid() - - request_stack = task.request_stack - push_request = request_stack.push - pop_request = request_stack.pop - push_task = _task_stack.push - pop_task = _task_stack.pop - on_chord_part_return = backend.on_chord_part_return - - prerun_receivers = signals.task_prerun.receivers - postrun_receivers = signals.task_postrun.receivers - success_receivers = signals.task_success.receivers - - from celery import canvas - signature = canvas.maybe_signature # maybe_ does not clone if already - - def on_error(request, exc, uuid, state=FAILURE, call_errbacks=True): - if propagate: - raise - I = Info(state, exc) - R = I.handle_error_state(task, eager=eager) - if call_errbacks: - group( - [signature(errback, app=app) - for errback in request.errbacks or []], app=app, - ).apply_async((uuid, )) - return I, R, I.state, I.retval - - def trace_task(uuid, args, kwargs, request=None): - # R - is the possibly prepared return value. - # I - is the Info object. - # retval - is the always unmodified return value. - # state - is the resulting task state. - - # This function is very long because we have unrolled all the calls - # for performance reasons, and because the function is so long - # we want the main variables (I, and R) to stand out visually from the - # the rest of the variables, so breaking PEP8 is worth it ;) - R = I = retval = state = None - kwargs = kwdict(kwargs) - try: - push_task(task) - task_request = Context(request or {}, args=args, - called_directly=False, kwargs=kwargs) - push_request(task_request) - try: - # -*- PRE -*- - if prerun_receivers: - send_prerun(sender=task, task_id=uuid, task=task, - args=args, kwargs=kwargs) - loader_task_init(uuid, task) - if track_started: - store_result( - uuid, {'pid': pid, 'hostname': hostname}, STARTED, - request=task_request, - ) - - # -*- TRACE -*- - try: - R = retval = fun(*args, **kwargs) - state = SUCCESS - except Reject as exc: - I, R = Info(REJECTED, exc), ExceptionInfo(internal=True) - state, retval = I.state, I.retval - except Ignore as exc: - I, R = Info(IGNORED, exc), ExceptionInfo(internal=True) - state, retval = I.state, I.retval - except Retry as exc: - I, R, state, retval = on_error( - task_request, exc, uuid, RETRY, call_errbacks=False, - ) - except Exception as exc: - I, R, state, retval = on_error(task_request, exc, uuid) - except BaseException as exc: - raise - else: - try: - # callback tasks must be applied before the result is - # stored, so that result.children is populated. - group( - [signature(callback, app=app) - for callback in task.request.callbacks or []], - app=app, - ).apply_async((retval, )) - if publish_result: - store_result( - uuid, retval, SUCCESS, request=task_request, - ) - except EncodeError as exc: - I, R, state, retval = on_error(task_request, exc, uuid) - else: - if task_on_success: - task_on_success(retval, uuid, args, kwargs) - if success_receivers: - send_success(sender=task, result=retval) - - # -* POST *- - if state not in IGNORE_STATES: - if task_request.chord: - on_chord_part_return(task, state, R) - if task_after_return: - task_after_return( - state, retval, uuid, args, kwargs, None, - ) - finally: - try: - if postrun_receivers: - send_postrun(sender=task, task_id=uuid, task=task, - args=args, kwargs=kwargs, - retval=retval, state=state) - finally: - pop_task() - pop_request() - if not eager: - try: - backend_cleanup() - loader_cleanup() - except (KeyboardInterrupt, SystemExit, MemoryError): - raise - except Exception as exc: - _logger.error('Process cleanup failed: %r', exc, - exc_info=True) - except MemoryError: - raise - except Exception as exc: - if eager: - raise - R = report_internal_error(task, exc) - return R, I - - return trace_task - - -def trace_task(task, uuid, args, kwargs, request={}, **opts): - try: - if task.__trace__ is None: - task.__trace__ = build_tracer(task.name, task, **opts) - return task.__trace__(uuid, args, kwargs, request)[0] - except Exception as exc: - return report_internal_error(task, exc) - - -def _trace_task_ret(name, uuid, args, kwargs, request={}, app=None, **opts): - return trace_task((app or current_app).tasks[name], - uuid, args, kwargs, request, app=app, **opts) -trace_task_ret = _trace_task_ret - - -def _fast_trace_task(task, uuid, args, kwargs, request={}): - # setup_worker_optimizations will point trace_task_ret to here, - # so this is the function used in the worker. - return _tasks[task].__trace__(uuid, args, kwargs, request)[0] - - -def eager_trace_task(task, uuid, args, kwargs, request=None, **opts): - opts.setdefault('eager', True) - return build_tracer(task.name, task, **opts)( - uuid, args, kwargs, request) - - -def report_internal_error(task, exc): - _type, _value, _tb = sys.exc_info() - try: - _value = task.backend.prepare_exception(exc, 'pickle') - exc_info = ExceptionInfo((_type, _value, _tb), internal=True) - warn(RuntimeWarning( - 'Exception raised outside body: {0!r}:\n{1}'.format( - exc, exc_info.traceback))) - return exc_info - finally: - del(_tb) - - -def setup_worker_optimizations(app): - global _tasks - global trace_task_ret - - # make sure custom Task.__call__ methods that calls super - # will not mess up the request/task stack. - _install_stack_protection() - - # all new threads start without a current app, so if an app is not - # passed on to the thread it will fall back to the "default app", - # which then could be the wrong app. So for the worker - # we set this to always return our app. This is a hack, - # and means that only a single app can be used for workers - # running in the same process. - app.set_current() - set_default_app(app) - - # evaluate all task classes by finalizing the app. - app.finalize() - - # set fast shortcut to task registry - _tasks = app._tasks - - trace_task_ret = _fast_trace_task - from celery.worker import job as job_module - job_module.trace_task_ret = _fast_trace_task - job_module.__optimize__() - - -def reset_worker_optimizations(): - global trace_task_ret - trace_task_ret = _trace_task_ret - try: - delattr(BaseTask, '_stackprotected') - except AttributeError: - pass - try: - BaseTask.__call__ = _patched.pop('BaseTask.__call__') - except KeyError: - pass - from celery.worker import job as job_module - job_module.trace_task_ret = _trace_task_ret - - -def _install_stack_protection(): - # Patches BaseTask.__call__ in the worker to handle the edge case - # where people override it and also call super. - # - # - The worker optimizes away BaseTask.__call__ and instead - # calls task.run directly. - # - so with the addition of current_task and the request stack - # BaseTask.__call__ now pushes to those stacks so that - # they work when tasks are called directly. - # - # The worker only optimizes away __call__ in the case - # where it has not been overridden, so the request/task stack - # will blow if a custom task class defines __call__ and also - # calls super(). - if not getattr(BaseTask, '_stackprotected', False): - _patched['BaseTask.__call__'] = orig = BaseTask.__call__ - - def __protected_call__(self, *args, **kwargs): - stack = self.request_stack - req = stack.top - if req and not req._protected and \ - len(stack) == 1 and not req.called_directly: - req._protected = 1 - return self.run(*args, **kwargs) - return orig(self, *args, **kwargs) - BaseTask.__call__ = __protected_call__ - BaseTask._stackprotected = True diff --git a/awx/lib/site-packages/celery/app/utils.py b/awx/lib/site-packages/celery/app/utils.py deleted file mode 100644 index defdca7b8e..0000000000 --- a/awx/lib/site-packages/celery/app/utils.py +++ /dev/null @@ -1,253 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.app.utils - ~~~~~~~~~~~~~~~~ - - App utilities: Compat settings, bugreport tool, pickling apps. - -""" -from __future__ import absolute_import - -import os -import platform as _platform -import re - -from collections import Mapping -from types import ModuleType - -from celery.datastructures import ConfigurationView -from celery.five import items, string_t, values -from celery.platforms import pyimplementation -from celery.utils.text import pretty -from celery.utils.imports import import_from_cwd, symbol_by_name, qualname - -from .defaults import find - -__all__ = ['Settings', 'appstr', 'bugreport', - 'filter_hidden_settings', 'find_app'] - -#: Format used to generate bugreport information. -BUGREPORT_INFO = """ -software -> celery:{celery_v} kombu:{kombu_v} py:{py_v} - billiard:{billiard_v} {driver_v} -platform -> system:{system} arch:{arch} imp:{py_i} -loader -> {loader} -settings -> transport:{transport} results:{results} - -{human_settings} -""" - -HIDDEN_SETTINGS = re.compile( - 'API|TOKEN|KEY|SECRET|PASS|PROFANITIES_LIST|SIGNATURE|DATABASE', - re.IGNORECASE, -) - - -def appstr(app): - """String used in __repr__ etc, to id app instances.""" - return '{0}:0x{1:x}'.format(app.main or '__main__', id(app)) - - -class Settings(ConfigurationView): - """Celery settings object.""" - - @property - def CELERY_RESULT_BACKEND(self): - return self.first('CELERY_RESULT_BACKEND', 'CELERY_BACKEND') - - @property - def BROKER_TRANSPORT(self): - return self.first('BROKER_TRANSPORT', - 'BROKER_BACKEND', 'CARROT_BACKEND') - - @property - def BROKER_BACKEND(self): - """Deprecated compat alias to :attr:`BROKER_TRANSPORT`.""" - return self.BROKER_TRANSPORT - - @property - def BROKER_URL(self): - return (os.environ.get('CELERY_BROKER_URL') or - self.first('BROKER_URL', 'BROKER_HOST')) - - @property - def CELERY_TIMEZONE(self): - # this way we also support django's time zone. - return self.first('CELERY_TIMEZONE', 'TIME_ZONE') - - def without_defaults(self): - """Return the current configuration, but without defaults.""" - # the last stash is the default settings, so just skip that - return Settings({}, self._order[:-1]) - - def value_set_for(self, key): - return key in self.without_defaults() - - def find_option(self, name, namespace='celery'): - """Search for option by name. - - Will return ``(namespace, key, type)`` tuple, e.g.:: - - >>> from proj.celery import app - >>> app.conf.find_option('disable_rate_limits') - ('CELERY', 'DISABLE_RATE_LIMITS', - <Option: type->bool default->False>)) - - :param name: Name of option, cannot be partial. - :keyword namespace: Preferred namespace (``CELERY`` by default). - - """ - return find(name, namespace) - - def find_value_for_key(self, name, namespace='celery'): - """Shortcut to ``get_by_parts(*find_option(name)[:-1])``""" - return self.get_by_parts(*self.find_option(name, namespace)[:-1]) - - def get_by_parts(self, *parts): - """Return the current value for setting specified as a path. - - Example:: - - >>> from proj.celery import app - >>> app.conf.get_by_parts('CELERY', 'DISABLE_RATE_LIMITS') - False - - """ - return self['_'.join(part for part in parts if part)] - - def table(self, with_defaults=False, censored=True): - filt = filter_hidden_settings if censored else lambda v: v - return filt(dict( - (k, v) for k, v in items( - self if with_defaults else self.without_defaults()) - if k.isupper() and not k.startswith('_') - )) - - def humanize(self, with_defaults=False, censored=True): - """Return a human readable string showing changes to the - configuration.""" - return '\n'.join( - '{0}: {1}'.format(key, pretty(value, width=50)) - for key, value in items(self.table(with_defaults, censored))) - - -class AppPickler(object): - """Old application pickler/unpickler (< 3.1).""" - - def __call__(self, cls, *args): - kwargs = self.build_kwargs(*args) - app = self.construct(cls, **kwargs) - self.prepare(app, **kwargs) - return app - - def prepare(self, app, **kwargs): - app.conf.update(kwargs['changes']) - - def build_kwargs(self, *args): - return self.build_standard_kwargs(*args) - - def build_standard_kwargs(self, main, changes, loader, backend, amqp, - events, log, control, accept_magic_kwargs, - config_source=None): - return dict(main=main, loader=loader, backend=backend, amqp=amqp, - changes=changes, events=events, log=log, control=control, - set_as_current=False, - accept_magic_kwargs=accept_magic_kwargs, - config_source=config_source) - - def construct(self, cls, **kwargs): - return cls(**kwargs) - - -def _unpickle_app(cls, pickler, *args): - """Rebuild app for versions 2.5+""" - return pickler()(cls, *args) - - -def _unpickle_app_v2(cls, kwargs): - """Rebuild app for versions 3.1+""" - kwargs['set_as_current'] = False - return cls(**kwargs) - - -def filter_hidden_settings(conf): - - def maybe_censor(key, value, mask='*' * 8): - if isinstance(value, Mapping): - return filter_hidden_settings(value) - if isinstance(value, string_t) and HIDDEN_SETTINGS.search(key): - return mask - if isinstance(key, string_t) and 'BROKER_URL' in key.upper(): - from kombu import Connection - return Connection(value).as_uri(mask=mask) - return value - - return dict((k, maybe_censor(k, v)) for k, v in items(conf)) - - -def bugreport(app): - """Return a string containing information useful in bug reports.""" - import billiard - import celery - import kombu - - try: - conn = app.connection() - driver_v = '{0}:{1}'.format(conn.transport.driver_name, - conn.transport.driver_version()) - transport = conn.transport_cls - except Exception: - transport = driver_v = '' - - return BUGREPORT_INFO.format( - system=_platform.system(), - arch=', '.join(x for x in _platform.architecture() if x), - py_i=pyimplementation(), - celery_v=celery.VERSION_BANNER, - kombu_v=kombu.__version__, - billiard_v=billiard.__version__, - py_v=_platform.python_version(), - driver_v=driver_v, - transport=transport, - results=app.conf.CELERY_RESULT_BACKEND or 'disabled', - human_settings=app.conf.humanize(), - loader=qualname(app.loader.__class__), - ) - - -def find_app(app, symbol_by_name=symbol_by_name, imp=import_from_cwd): - from .base import Celery - - try: - sym = symbol_by_name(app, imp=imp) - except AttributeError: - # last part was not an attribute, but a module - sym = imp(app) - if isinstance(sym, ModuleType) and ':' not in app: - try: - found = sym.app - if isinstance(found, ModuleType): - raise AttributeError() - except AttributeError: - try: - found = sym.celery - if isinstance(found, ModuleType): - raise AttributeError() - except AttributeError: - if getattr(sym, '__path__', None): - try: - return find_app( - '{0}.celery'.format(app), - symbol_by_name=symbol_by_name, imp=imp, - ) - except ImportError: - pass - for suspect in values(vars(sym)): - if isinstance(suspect, Celery): - return suspect - raise - else: - return found - else: - return found - return sym diff --git a/awx/lib/site-packages/celery/apps/__init__.py b/awx/lib/site-packages/celery/apps/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/apps/beat.py b/awx/lib/site-packages/celery/apps/beat.py deleted file mode 100644 index 46cef9b8bf..0000000000 --- a/awx/lib/site-packages/celery/apps/beat.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.apps.beat - ~~~~~~~~~~~~~~~~ - - This module is the 'program-version' of :mod:`celery.beat`. - - It does everything necessary to run that module - as an actual application, like installing signal handlers - and so on. - -""" -from __future__ import absolute_import, unicode_literals - -import numbers -import socket -import sys - -from celery import VERSION_BANNER, platforms, beat -from celery.utils.imports import qualname -from celery.utils.log import LOG_LEVELS, get_logger -from celery.utils.timeutils import humanize_seconds - -__all__ = ['Beat'] - -STARTUP_INFO_FMT = """ -Configuration -> - . broker -> {conninfo} - . loader -> {loader} - . scheduler -> {scheduler} -{scheduler_info} - . logfile -> {logfile}@%{loglevel} - . maxinterval -> {hmax_interval} ({max_interval}s) -""".strip() - -logger = get_logger('celery.beat') - - -class Beat(object): - Service = beat.Service - app = None - - def __init__(self, max_interval=None, app=None, - socket_timeout=30, pidfile=None, no_color=None, - loglevel=None, logfile=None, schedule=None, - scheduler_cls=None, redirect_stdouts=None, - redirect_stdouts_level=None, **kwargs): - """Starts the beat task scheduler.""" - self.app = app = app or self.app - self.loglevel = self._getopt('log_level', loglevel) - self.logfile = self._getopt('log_file', logfile) - self.schedule = self._getopt('schedule_filename', schedule) - self.scheduler_cls = self._getopt('scheduler', scheduler_cls) - self.redirect_stdouts = self._getopt( - 'redirect_stdouts', redirect_stdouts, - ) - self.redirect_stdouts_level = self._getopt( - 'redirect_stdouts_level', redirect_stdouts_level, - ) - - self.max_interval = max_interval - self.socket_timeout = socket_timeout - self.no_color = no_color - self.colored = app.log.colored( - self.logfile, - enabled=not no_color if no_color is not None else no_color, - ) - self.pidfile = pidfile - - if not isinstance(self.loglevel, numbers.Integral): - self.loglevel = LOG_LEVELS[self.loglevel.upper()] - - def _getopt(self, key, value): - if value is not None: - return value - return self.app.conf.find_value_for_key(key, namespace='celerybeat') - - def run(self): - print(str(self.colored.cyan( - 'celery beat v{0} is starting.'.format(VERSION_BANNER)))) - self.init_loader() - self.set_process_title() - self.start_scheduler() - - def setup_logging(self, colorize=None): - if colorize is None and self.no_color is not None: - colorize = not self.no_color - self.app.log.setup(self.loglevel, self.logfile, - self.redirect_stdouts, self.redirect_stdouts_level, - colorize=colorize) - - def start_scheduler(self): - c = self.colored - if self.pidfile: - platforms.create_pidlock(self.pidfile) - beat = self.Service(app=self.app, - max_interval=self.max_interval, - scheduler_cls=self.scheduler_cls, - schedule_filename=self.schedule) - - print(str(c.blue('__ ', c.magenta('-'), - c.blue(' ... __ '), c.magenta('-'), - c.blue(' _\n'), - c.reset(self.startup_info(beat))))) - self.setup_logging() - if self.socket_timeout: - logger.debug('Setting default socket timeout to %r', - self.socket_timeout) - socket.setdefaulttimeout(self.socket_timeout) - try: - self.install_sync_handler(beat) - beat.start() - except Exception as exc: - logger.critical('beat raised exception %s: %r', - exc.__class__, exc, - exc_info=True) - - def init_loader(self): - # Run the worker init handler. - # (Usually imports task modules and such.) - self.app.loader.init_worker() - self.app.finalize() - - def startup_info(self, beat): - scheduler = beat.get_scheduler(lazy=True) - return STARTUP_INFO_FMT.format( - conninfo=self.app.connection().as_uri(), - logfile=self.logfile or '[stderr]', - loglevel=LOG_LEVELS[self.loglevel], - loader=qualname(self.app.loader), - scheduler=qualname(scheduler), - scheduler_info=scheduler.info, - hmax_interval=humanize_seconds(beat.max_interval), - max_interval=beat.max_interval, - ) - - def set_process_title(self): - arg_start = 'manage' in sys.argv[0] and 2 or 1 - platforms.set_process_title( - 'celery beat', info=' '.join(sys.argv[arg_start:]), - ) - - def install_sync_handler(self, beat): - """Install a `SIGTERM` + `SIGINT` handler that saves - the beat schedule.""" - - def _sync(signum, frame): - beat.sync() - raise SystemExit() - - platforms.signals.update(SIGTERM=_sync, SIGINT=_sync) diff --git a/awx/lib/site-packages/celery/apps/worker.py b/awx/lib/site-packages/celery/apps/worker.py deleted file mode 100644 index d190711082..0000000000 --- a/awx/lib/site-packages/celery/apps/worker.py +++ /dev/null @@ -1,371 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.apps.worker - ~~~~~~~~~~~~~~~~~~ - - This module is the 'program-version' of :mod:`celery.worker`. - - It does everything necessary to run that module - as an actual application, like installing signal handlers, - platform tweaks, and so on. - -""" -from __future__ import absolute_import, print_function, unicode_literals - -import logging -import os -import platform as _platform -import sys -import warnings - -from functools import partial - -from billiard import current_process -from kombu.utils.encoding import safe_str - -from celery import VERSION_BANNER, platforms, signals -from celery.app import trace -from celery.exceptions import ( - CDeprecationWarning, WorkerShutdown, WorkerTerminate, -) -from celery.five import string, string_t -from celery.loaders.app import AppLoader -from celery.platforms import check_privileges -from celery.utils import cry, isatty -from celery.utils.imports import qualname -from celery.utils.log import get_logger, in_sighandler, set_in_sighandler -from celery.utils.text import pluralize -from celery.worker import WorkController - -__all__ = ['Worker'] - -logger = get_logger(__name__) -is_jython = sys.platform.startswith('java') -is_pypy = hasattr(sys, 'pypy_version_info') - -W_PICKLE_DEPRECATED = """ -Starting from version 3.2 Celery will refuse to accept pickle by default. - -The pickle serializer is a security concern as it may give attackers -the ability to execute any command. It's important to secure -your broker from unauthorized access when using pickle, so we think -that enabling pickle should require a deliberate action and not be -the default choice. - -If you depend on pickle then you should set a setting to disable this -warning and to be sure that everything will continue working -when you upgrade to Celery 3.2:: - - CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml'] - -You must only enable the serializers that you will actually use. - -""" - - -def active_thread_count(): - from threading import enumerate - return sum(1 for t in enumerate() - if not t.name.startswith('Dummy-')) - - -def safe_say(msg): - print('\n{0}'.format(msg), file=sys.__stderr__) - -ARTLINES = [ - ' --------------', - '---- **** -----', - '--- * *** * --', - '-- * - **** ---', - '- ** ----------', - '- ** ----------', - '- ** ----------', - '- ** ----------', - '- *** --- * ---', - '-- ******* ----', - '--- ***** -----', - ' --------------', -] - -BANNER = """\ -{hostname} v{version} - -{platform} - -[config] -.> app: {app} -.> transport: {conninfo} -.> results: {results} -.> concurrency: {concurrency} - -[queues] -{queues} -""" - -EXTRA_INFO_FMT = """ -[tasks] -{tasks} -""" - - -class Worker(WorkController): - - def on_before_init(self, **kwargs): - trace.setup_worker_optimizations(self.app) - - # this signal can be used to set up configuration for - # workers by name. - signals.celeryd_init.send( - sender=self.hostname, instance=self, - conf=self.app.conf, options=kwargs, - ) - check_privileges(self.app.conf.CELERY_ACCEPT_CONTENT) - - def on_after_init(self, purge=False, no_color=None, - redirect_stdouts=None, redirect_stdouts_level=None, - **kwargs): - self.redirect_stdouts = self._getopt( - 'redirect_stdouts', redirect_stdouts, - ) - self.redirect_stdouts_level = self._getopt( - 'redirect_stdouts_level', redirect_stdouts_level, - ) - super(Worker, self).setup_defaults(**kwargs) - self.purge = purge - self.no_color = no_color - self._isatty = isatty(sys.stdout) - self.colored = self.app.log.colored( - self.logfile, - enabled=not no_color if no_color is not None else no_color - ) - - def on_init_blueprint(self): - self._custom_logging = self.setup_logging() - # apply task execution optimizations - # -- This will finalize the app! - trace.setup_worker_optimizations(self.app) - - def on_start(self): - if not self._custom_logging and self.redirect_stdouts: - self.app.log.redirect_stdouts(self.redirect_stdouts_level) - - WorkController.on_start(self) - - # this signal can be used to e.g. change queues after - # the -Q option has been applied. - signals.celeryd_after_setup.send( - sender=self.hostname, instance=self, conf=self.app.conf, - ) - - if not self.app.conf.value_set_for('CELERY_ACCEPT_CONTENT'): - warnings.warn(CDeprecationWarning(W_PICKLE_DEPRECATED)) - - if self.purge: - self.purge_messages() - - # Dump configuration to screen so we have some basic information - # for when users sends bug reports. - print(safe_str(''.join([ - string(self.colored.cyan(' \n', self.startup_info())), - string(self.colored.reset(self.extra_info() or '')), - ])), file=sys.__stdout__) - self.set_process_status('-active-') - self.install_platform_tweaks(self) - - def on_consumer_ready(self, consumer): - signals.worker_ready.send(sender=consumer) - print('{0} ready.'.format(safe_str(self.hostname), )) - - def setup_logging(self, colorize=None): - if colorize is None and self.no_color is not None: - colorize = not self.no_color - return self.app.log.setup( - self.loglevel, self.logfile, - redirect_stdouts=False, colorize=colorize, hostname=self.hostname, - ) - - def purge_messages(self): - count = self.app.control.purge() - if count: - print('purge: Erased {0} {1} from the queue.\n'.format( - count, pluralize(count, 'message'))) - - def tasklist(self, include_builtins=True, sep='\n', int_='celery.'): - return sep.join( - ' . {0}'.format(task) for task in sorted(self.app.tasks) - if (not task.startswith(int_) if not include_builtins else task) - ) - - def extra_info(self): - if self.loglevel <= logging.INFO: - include_builtins = self.loglevel <= logging.DEBUG - tasklist = self.tasklist(include_builtins=include_builtins) - return EXTRA_INFO_FMT.format(tasks=tasklist) - - def startup_info(self): - app = self.app - concurrency = string(self.concurrency) - appr = '{0}:0x{1:x}'.format(app.main or '__main__', id(app)) - if not isinstance(app.loader, AppLoader): - loader = qualname(app.loader) - if loader.startswith('celery.loaders'): - loader = loader[14:] - appr += ' ({0})'.format(loader) - if self.autoscale: - max, min = self.autoscale - concurrency = '{{min={0}, max={1}}}'.format(min, max) - pool = self.pool_cls - if not isinstance(pool, string_t): - pool = pool.__module__ - concurrency += ' ({0})'.format(pool.split('.')[-1]) - events = 'ON' - if not self.send_events: - events = 'OFF (enable -E to monitor this worker)' - - banner = BANNER.format( - app=appr, - hostname=safe_str(self.hostname), - version=VERSION_BANNER, - conninfo=self.app.connection().as_uri(), - results=self.app.conf.CELERY_RESULT_BACKEND or 'disabled', - concurrency=concurrency, - platform=safe_str(_platform.platform()), - events=events, - queues=app.amqp.queues.format(indent=0, indent_first=False), - ).splitlines() - - # integrate the ASCII art. - for i, x in enumerate(banner): - try: - banner[i] = ' '.join([ARTLINES[i], banner[i]]) - except IndexError: - banner[i] = ' ' * 16 + banner[i] - return '\n'.join(banner) + '\n' - - def install_platform_tweaks(self, worker): - """Install platform specific tweaks and workarounds.""" - if self.app.IS_OSX: - self.osx_proxy_detection_workaround() - - # Install signal handler so SIGHUP restarts the worker. - if not self._isatty: - # only install HUP handler if detached from terminal, - # so closing the terminal window doesn't restart the worker - # into the background. - if self.app.IS_OSX: - # OS X can't exec from a process using threads. - # See http://github.com/celery/celery/issues#issue/152 - install_HUP_not_supported_handler(worker) - else: - install_worker_restart_handler(worker) - install_worker_term_handler(worker) - install_worker_term_hard_handler(worker) - install_worker_int_handler(worker) - install_cry_handler() - install_rdb_handler() - - def osx_proxy_detection_workaround(self): - """See http://github.com/celery/celery/issues#issue/161""" - os.environ.setdefault('celery_dummy_proxy', 'set_by_celeryd') - - def set_process_status(self, info): - return platforms.set_mp_process_title( - 'celeryd', - info='{0} ({1})'.format(info, platforms.strargv(sys.argv)), - hostname=self.hostname, - ) - - -def _shutdown_handler(worker, sig='TERM', how='Warm', - exc=WorkerShutdown, callback=None): - - def _handle_request(*args): - with in_sighandler(): - from celery.worker import state - if current_process()._name == 'MainProcess': - if callback: - callback(worker) - safe_say('worker: {0} shutdown (MainProcess)'.format(how)) - if active_thread_count() > 1: - setattr(state, {'Warm': 'should_stop', - 'Cold': 'should_terminate'}[how], True) - else: - raise exc() - _handle_request.__name__ = str('worker_{0}'.format(how)) - platforms.signals[sig] = _handle_request -install_worker_term_handler = partial( - _shutdown_handler, sig='SIGTERM', how='Warm', exc=WorkerShutdown, -) -if not is_jython: # pragma: no cover - install_worker_term_hard_handler = partial( - _shutdown_handler, sig='SIGQUIT', how='Cold', exc=WorkerTerminate, - ) -else: # pragma: no cover - install_worker_term_handler = \ - install_worker_term_hard_handler = lambda *a, **kw: None - - -def on_SIGINT(worker): - safe_say('worker: Hitting Ctrl+C again will terminate all running tasks!') - install_worker_term_hard_handler(worker, sig='SIGINT') -if not is_jython: # pragma: no cover - install_worker_int_handler = partial( - _shutdown_handler, sig='SIGINT', callback=on_SIGINT - ) -else: # pragma: no cover - install_worker_int_handler = lambda *a, **kw: None - - -def _reload_current_worker(): - platforms.close_open_fds([ - sys.__stdin__, sys.__stdout__, sys.__stderr__, - ]) - os.execv(sys.executable, [sys.executable] + sys.argv) - - -def install_worker_restart_handler(worker, sig='SIGHUP'): - - def restart_worker_sig_handler(*args): - """Signal handler restarting the current python program.""" - set_in_sighandler(True) - safe_say('Restarting celery worker ({0})'.format(' '.join(sys.argv))) - import atexit - atexit.register(_reload_current_worker) - from celery.worker import state - state.should_stop = True - platforms.signals[sig] = restart_worker_sig_handler - - -def install_cry_handler(sig='SIGUSR1'): - # Jython/PyPy does not have sys._current_frames - if is_jython or is_pypy: # pragma: no cover - return - - def cry_handler(*args): - """Signal handler logging the stacktrace of all active threads.""" - with in_sighandler(): - safe_say(cry()) - platforms.signals[sig] = cry_handler - - -def install_rdb_handler(envvar='CELERY_RDBSIG', - sig='SIGUSR2'): # pragma: no cover - - def rdb_handler(*args): - """Signal handler setting a rdb breakpoint at the current frame.""" - with in_sighandler(): - from celery.contrib.rdb import set_trace, _frame - # gevent does not pass standard signal handler args - frame = args[1] if args else _frame().f_back - set_trace(frame) - if os.environ.get(envvar): - platforms.signals[sig] = rdb_handler - - -def install_HUP_not_supported_handler(worker, sig='SIGHUP'): - - def warn_on_HUP_handler(signum, frame): - with in_sighandler(): - safe_say('{sig} not supported: Restarting with {sig} is ' - 'unstable on this platform!'.format(sig=sig)) - platforms.signals[sig] = warn_on_HUP_handler diff --git a/awx/lib/site-packages/celery/backends/__init__.py b/awx/lib/site-packages/celery/backends/__init__.py deleted file mode 100644 index 421f7f480c..0000000000 --- a/awx/lib/site-packages/celery/backends/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends - ~~~~~~~~~~~~~~~ - - Backend abstract factory (...did I just say that?) and alias definitions. - -""" -from __future__ import absolute_import - -import sys - -from kombu.utils.url import _parse_url - -from celery.local import Proxy -from celery._state import current_app -from celery.five import reraise -from celery.utils.imports import symbol_by_name -from celery.utils.functional import memoize - -__all__ = ['get_backend_cls', 'get_backend_by_url'] - -UNKNOWN_BACKEND = """\ -Unknown result backend: {0!r}. Did you spell that correctly? ({1!r})\ -""" - -BACKEND_ALIASES = { - 'amqp': 'celery.backends.amqp:AMQPBackend', - 'rpc': 'celery.backends.rpc.RPCBackend', - 'cache': 'celery.backends.cache:CacheBackend', - 'redis': 'celery.backends.redis:RedisBackend', - 'mongodb': 'celery.backends.mongodb:MongoBackend', - 'db': 'celery.backends.database:DatabaseBackend', - 'database': 'celery.backends.database:DatabaseBackend', - 'cassandra': 'celery.backends.cassandra:CassandraBackend', - 'couchbase': 'celery.backends.couchbase:CouchBaseBackend', - 'disabled': 'celery.backends.base:DisabledBackend', -} - -#: deprecated alias to ``current_app.backend``. -default_backend = Proxy(lambda: current_app.backend) - - -@memoize(100) -def get_backend_cls(backend=None, loader=None): - """Get backend class by name/alias""" - backend = backend or 'disabled' - loader = loader or current_app.loader - aliases = dict(BACKEND_ALIASES, **loader.override_backends) - try: - return symbol_by_name(backend, aliases) - except ValueError as exc: - reraise(ValueError, ValueError(UNKNOWN_BACKEND.format( - backend, exc)), sys.exc_info()[2]) - - -def get_backend_by_url(backend=None, loader=None): - url = None - if backend and '://' in backend: - url = backend - if '+' in url[:url.index('://')]: - backend, url = url.split('+', 1) - else: - backend, _, _, _, _, _, _ = _parse_url(url) - return get_backend_cls(backend, loader), url diff --git a/awx/lib/site-packages/celery/backends/amqp.py b/awx/lib/site-packages/celery/backends/amqp.py deleted file mode 100644 index 62cf2034ec..0000000000 --- a/awx/lib/site-packages/celery/backends/amqp.py +++ /dev/null @@ -1,317 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.amqp - ~~~~~~~~~~~~~~~~~~~~ - - The AMQP result backend. - - This backend publishes results as messages. - -""" -from __future__ import absolute_import - -import socket - -from collections import deque -from operator import itemgetter - -from kombu import Exchange, Queue, Producer, Consumer - -from celery import states -from celery.exceptions import TimeoutError -from celery.five import range, monotonic -from celery.utils.functional import dictfilter -from celery.utils.log import get_logger -from celery.utils.timeutils import maybe_s_to_ms - -from .base import BaseBackend - -__all__ = ['BacklogLimitExceeded', 'AMQPBackend'] - -logger = get_logger(__name__) - - -class BacklogLimitExceeded(Exception): - """Too much state history to fast-forward.""" - - -def repair_uuid(s): - # Historically the dashes in UUIDS are removed from AMQ entity names, - # but there is no known reason to. Hopefully we'll be able to fix - # this in v4.0. - return '%s-%s-%s-%s-%s' % (s[:8], s[8:12], s[12:16], s[16:20], s[20:]) - - -class NoCacheQueue(Queue): - can_cache_declaration = False - - -class AMQPBackend(BaseBackend): - """Publishes results by sending messages.""" - Exchange = Exchange - Queue = NoCacheQueue - Consumer = Consumer - Producer = Producer - - BacklogLimitExceeded = BacklogLimitExceeded - - persistent = True - supports_autoexpire = True - supports_native_join = True - - retry_policy = { - 'max_retries': 20, - 'interval_start': 0, - 'interval_step': 1, - 'interval_max': 1, - } - - def __init__(self, app, connection=None, exchange=None, exchange_type=None, - persistent=None, serializer=None, auto_delete=True, **kwargs): - super(AMQPBackend, self).__init__(app, **kwargs) - conf = self.app.conf - self._connection = connection - self.persistent = self.prepare_persistent(persistent) - self.delivery_mode = 2 if self.persistent else 1 - exchange = exchange or conf.CELERY_RESULT_EXCHANGE - exchange_type = exchange_type or conf.CELERY_RESULT_EXCHANGE_TYPE - self.exchange = self._create_exchange( - exchange, exchange_type, self.delivery_mode, - ) - self.serializer = serializer or conf.CELERY_RESULT_SERIALIZER - self.auto_delete = auto_delete - - self.expires = None - if 'expires' not in kwargs or kwargs['expires'] is not None: - self.expires = self.prepare_expires(kwargs.get('expires')) - self.queue_arguments = dictfilter({ - 'x-expires': maybe_s_to_ms(self.expires), - }) - - def _create_exchange(self, name, type='direct', delivery_mode=2): - return self.Exchange(name=name, - type=type, - delivery_mode=delivery_mode, - durable=self.persistent, - auto_delete=False) - - def _create_binding(self, task_id): - name = self.rkey(task_id) - return self.Queue(name=name, - exchange=self.exchange, - routing_key=name, - durable=self.persistent, - auto_delete=self.auto_delete, - queue_arguments=self.queue_arguments) - - def revive(self, channel): - pass - - def rkey(self, task_id): - return task_id.replace('-', '') - - def destination_for(self, task_id, request): - if request: - return self.rkey(task_id), request.correlation_id or task_id - return self.rkey(task_id), task_id - - def store_result(self, task_id, result, status, - traceback=None, request=None, **kwargs): - """Send task return value and status.""" - routing_key, correlation_id = self.destination_for(task_id, request) - if not routing_key: - return - with self.app.amqp.producer_pool.acquire(block=True) as producer: - producer.publish( - {'task_id': task_id, 'status': status, - 'result': self.encode_result(result, status), - 'traceback': traceback, - 'children': self.current_task_children(request)}, - exchange=self.exchange, - routing_key=routing_key, - correlation_id=correlation_id, - serializer=self.serializer, - retry=True, retry_policy=self.retry_policy, - declare=self.on_reply_declare(task_id), - delivery_mode=self.delivery_mode, - ) - return result - - def on_reply_declare(self, task_id): - return [self._create_binding(task_id)] - - def wait_for(self, task_id, timeout=None, cache=True, propagate=True, - no_ack=True, on_interval=None, - READY_STATES=states.READY_STATES, - PROPAGATE_STATES=states.PROPAGATE_STATES, - **kwargs): - cached_meta = self._cache.get(task_id) - if cache and cached_meta and \ - cached_meta['status'] in READY_STATES: - meta = cached_meta - else: - try: - meta = self.consume(task_id, timeout=timeout, no_ack=no_ack, - on_interval=on_interval) - except socket.timeout: - raise TimeoutError('The operation timed out.') - - if meta['status'] in PROPAGATE_STATES and propagate: - raise self.exception_to_python(meta['result']) - # consume() always returns READY_STATE. - return meta['result'] - - def get_task_meta(self, task_id, backlog_limit=1000): - # Polling and using basic_get - with self.app.pool.acquire_channel(block=True) as (_, channel): - binding = self._create_binding(task_id)(channel) - binding.declare() - - prev = latest = acc = None - for i in range(backlog_limit): # spool ffwd - acc = binding.get( - accept=self.accept, no_ack=False, - ) - if not acc: # no more messages - break - if acc.payload['task_id'] == task_id: - prev, latest = latest, acc - if prev: - # backends are not expected to keep history, - # so we delete everything except the most recent state. - prev.ack() - prev = None - else: - raise self.BacklogLimitExceeded(task_id) - - if latest: - payload = self._cache[task_id] = latest.payload - latest.requeue() - return payload - else: - # no new state, use previous - try: - return self._cache[task_id] - except KeyError: - # result probably pending. - return {'status': states.PENDING, 'result': None} - poll = get_task_meta # XXX compat - - def drain_events(self, connection, consumer, - timeout=None, on_interval=None, now=monotonic, wait=None): - wait = wait or connection.drain_events - results = {} - - def callback(meta, message): - if meta['status'] in states.READY_STATES: - results[meta['task_id']] = meta - - consumer.callbacks[:] = [callback] - time_start = now() - - while 1: - # Total time spent may exceed a single call to wait() - if timeout and now() - time_start >= timeout: - raise socket.timeout() - wait(timeout=timeout) - if on_interval: - on_interval() - if results: # got event on the wanted channel. - break - self._cache.update(results) - return results - - def consume(self, task_id, timeout=None, no_ack=True, on_interval=None): - wait = self.drain_events - with self.app.pool.acquire_channel(block=True) as (conn, channel): - binding = self._create_binding(task_id) - with self.Consumer(channel, binding, - no_ack=no_ack, accept=self.accept) as consumer: - while 1: - try: - return wait( - conn, consumer, timeout, on_interval)[task_id] - except KeyError: - continue - - def _many_bindings(self, ids): - return [self._create_binding(task_id) for task_id in ids] - - def get_many(self, task_ids, timeout=None, no_ack=True, - now=monotonic, getfields=itemgetter('status', 'task_id'), - READY_STATES=states.READY_STATES, - PROPAGATE_STATES=states.PROPAGATE_STATES, **kwargs): - with self.app.pool.acquire_channel(block=True) as (conn, channel): - ids = set(task_ids) - cached_ids = set() - mark_cached = cached_ids.add - for task_id in ids: - try: - cached = self._cache[task_id] - except KeyError: - pass - else: - if cached['status'] in READY_STATES: - yield task_id, cached - mark_cached(task_id) - ids.difference_update(cached_ids) - results = deque() - push_result = results.append - push_cache = self._cache.__setitem__ - to_exception = self.exception_to_python - - def on_message(message): - body = message.decode() - state, uid = getfields(body) - if state in READY_STATES: - if state in PROPAGATE_STATES: - body['result'] = to_exception(body['result']) - push_result(body) \ - if uid in task_ids else push_cache(uid, body) - - bindings = self._many_bindings(task_ids) - with self.Consumer(channel, bindings, on_message=on_message, - accept=self.accept, no_ack=no_ack): - wait = conn.drain_events - popleft = results.popleft - while ids: - wait(timeout=timeout) - while results: - state = popleft() - task_id = state['task_id'] - ids.discard(task_id) - push_cache(task_id, state) - yield task_id, state - - def reload_task_result(self, task_id): - raise NotImplementedError( - 'reload_task_result is not supported by this backend.') - - def reload_group_result(self, task_id): - """Reload group result, even if it has been previously fetched.""" - raise NotImplementedError( - 'reload_group_result is not supported by this backend.') - - def save_group(self, group_id, result): - raise NotImplementedError( - 'save_group is not supported by this backend.') - - def restore_group(self, group_id, cache=True): - raise NotImplementedError( - 'restore_group is not supported by this backend.') - - def delete_group(self, group_id): - raise NotImplementedError( - 'delete_group is not supported by this backend.') - - def __reduce__(self, args=(), kwargs={}): - kwargs.update( - connection=self._connection, - exchange=self.exchange.name, - exchange_type=self.exchange.type, - persistent=self.persistent, - serializer=self.serializer, - auto_delete=self.auto_delete, - expires=self.expires, - ) - return super(AMQPBackend, self).__reduce__(args, kwargs) diff --git a/awx/lib/site-packages/celery/backends/base.py b/awx/lib/site-packages/celery/backends/base.py deleted file mode 100644 index 2ca4cc0019..0000000000 --- a/awx/lib/site-packages/celery/backends/base.py +++ /dev/null @@ -1,593 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.base - ~~~~~~~~~~~~~~~~~~~~ - - Result backend base classes. - - - :class:`BaseBackend` defines the interface. - - - :class:`KeyValueStoreBackend` is a common base class - using K/V semantics like _get and _put. - -""" -from __future__ import absolute_import - -import time -import sys - -from datetime import timedelta - -from billiard.einfo import ExceptionInfo -from kombu.serialization import ( - dumps, loads, prepare_accept_content, - registry as serializer_registry, -) -from kombu.utils.encoding import bytes_to_str, ensure_bytes, from_utf8 - -from celery import states -from celery import current_app, maybe_signature -from celery.app import current_task -from celery.exceptions import ChordError, TimeoutError, TaskRevokedError -from celery.five import items -from celery.result import ( - GroupResult, ResultBase, allow_join_result, result_from_tuple, -) -from celery.utils import timeutils -from celery.utils.functional import LRUCache -from celery.utils.log import get_logger -from celery.utils.serialization import ( - get_pickled_exception, - get_pickleable_exception, - create_exception_cls, -) - -__all__ = ['BaseBackend', 'KeyValueStoreBackend', 'DisabledBackend'] - -EXCEPTION_ABLE_CODECS = frozenset(['pickle', 'yaml']) -PY3 = sys.version_info >= (3, 0) - -logger = get_logger(__name__) - - -def unpickle_backend(cls, args, kwargs): - """Return an unpickled backend.""" - return cls(*args, app=current_app._get_current_object(), **kwargs) - - -class _nulldict(dict): - - def __setitem__(self, k, v): - pass - - -class BaseBackend(object): - READY_STATES = states.READY_STATES - UNREADY_STATES = states.UNREADY_STATES - EXCEPTION_STATES = states.EXCEPTION_STATES - - TimeoutError = TimeoutError - - #: Time to sleep between polling each individual item - #: in `ResultSet.iterate`. as opposed to the `interval` - #: argument which is for each pass. - subpolling_interval = None - - #: If true the backend must implement :meth:`get_many`. - supports_native_join = False - - #: If true the backend must automatically expire results. - #: The daily backend_cleanup periodic task will not be triggered - #: in this case. - supports_autoexpire = False - - #: Set to true if the backend is peristent by default. - persistent = True - - retry_policy = { - 'max_retries': 20, - 'interval_start': 0, - 'interval_step': 1, - 'interval_max': 1, - } - - def __init__(self, app, serializer=None, - max_cached_results=None, accept=None, **kwargs): - self.app = app - conf = self.app.conf - self.serializer = serializer or conf.CELERY_RESULT_SERIALIZER - (self.content_type, - self.content_encoding, - self.encoder) = serializer_registry._encoders[self.serializer] - cmax = max_cached_results or conf.CELERY_MAX_CACHED_RESULTS - self._cache = _nulldict() if cmax == -1 else LRUCache(limit=cmax) - self.accept = prepare_accept_content( - conf.CELERY_ACCEPT_CONTENT if accept is None else accept, - ) - - def mark_as_started(self, task_id, **meta): - """Mark a task as started""" - return self.store_result(task_id, meta, status=states.STARTED) - - def mark_as_done(self, task_id, result, request=None): - """Mark task as successfully executed.""" - return self.store_result(task_id, result, - status=states.SUCCESS, request=request) - - def mark_as_failure(self, task_id, exc, traceback=None, request=None): - """Mark task as executed with failure. Stores the execption.""" - return self.store_result(task_id, exc, status=states.FAILURE, - traceback=traceback, request=request) - - def chord_error_from_stack(self, callback, exc=None): - from celery import group - app = self.app - backend = app._tasks[callback.task].backend - try: - group( - [app.signature(errback) - for errback in callback.options.get('link_error') or []], - app=app, - ).apply_async((callback.id, )) - except Exception as eb_exc: - return backend.fail_from_current_stack(callback.id, exc=eb_exc) - else: - return backend.fail_from_current_stack(callback.id, exc=exc) - - def fail_from_current_stack(self, task_id, exc=None): - type_, real_exc, tb = sys.exc_info() - try: - exc = real_exc if exc is None else exc - ei = ExceptionInfo((type_, exc, tb)) - self.mark_as_failure(task_id, exc, ei.traceback) - return ei - finally: - del(tb) - - def mark_as_retry(self, task_id, exc, traceback=None, request=None): - """Mark task as being retries. Stores the current - exception (if any).""" - return self.store_result(task_id, exc, status=states.RETRY, - traceback=traceback, request=request) - - def mark_as_revoked(self, task_id, reason='', request=None): - return self.store_result(task_id, TaskRevokedError(reason), - status=states.REVOKED, traceback=None, - request=request) - - def prepare_exception(self, exc, serializer=None): - """Prepare exception for serialization.""" - serializer = self.serializer if serializer is None else serializer - if serializer in EXCEPTION_ABLE_CODECS: - return get_pickleable_exception(exc) - return {'exc_type': type(exc).__name__, 'exc_message': str(exc)} - - def exception_to_python(self, exc): - """Convert serialized exception to Python exception.""" - if self.serializer in EXCEPTION_ABLE_CODECS: - return get_pickled_exception(exc) - return create_exception_cls( - from_utf8(exc['exc_type']), __name__)(exc['exc_message']) - - def prepare_value(self, result): - """Prepare value for storage.""" - if self.serializer != 'pickle' and isinstance(result, ResultBase): - return result.as_tuple() - return result - - def encode(self, data): - _, _, payload = dumps(data, serializer=self.serializer) - return payload - - def decode(self, payload): - payload = PY3 and payload or str(payload) - return loads(payload, - content_type=self.content_type, - content_encoding=self.content_encoding, - accept=self.accept) - - def wait_for(self, task_id, - timeout=None, propagate=True, interval=0.5, no_ack=True, - on_interval=None): - """Wait for task and return its result. - - If the task raises an exception, this exception - will be re-raised by :func:`wait_for`. - - If `timeout` is not :const:`None`, this raises the - :class:`celery.exceptions.TimeoutError` exception if the operation - takes longer than `timeout` seconds. - - """ - - time_elapsed = 0.0 - - while 1: - status = self.get_status(task_id) - if status == states.SUCCESS: - return self.get_result(task_id) - elif status in states.PROPAGATE_STATES: - result = self.get_result(task_id) - if propagate: - raise result - return result - if on_interval: - on_interval() - # avoid hammering the CPU checking status. - time.sleep(interval) - time_elapsed += interval - if timeout and time_elapsed >= timeout: - raise TimeoutError('The operation timed out.') - - def prepare_expires(self, value, type=None): - if value is None: - value = self.app.conf.CELERY_TASK_RESULT_EXPIRES - if isinstance(value, timedelta): - value = timeutils.timedelta_seconds(value) - if value is not None and type: - return type(value) - return value - - def prepare_persistent(self, enabled=None): - if enabled is not None: - return enabled - p = self.app.conf.CELERY_RESULT_PERSISTENT - return self.persistent if p is None else p - - def encode_result(self, result, status): - if status in self.EXCEPTION_STATES and isinstance(result, Exception): - return self.prepare_exception(result) - else: - return self.prepare_value(result) - - def is_cached(self, task_id): - return task_id in self._cache - - def store_result(self, task_id, result, status, - traceback=None, request=None, **kwargs): - """Update task state and result.""" - result = self.encode_result(result, status) - self._store_result(task_id, result, status, traceback, - request=request, **kwargs) - return result - - def forget(self, task_id): - self._cache.pop(task_id, None) - self._forget(task_id) - - def _forget(self, task_id): - raise NotImplementedError('backend does not implement forget.') - - def get_status(self, task_id): - """Get the status of a task.""" - return self.get_task_meta(task_id)['status'] - - def get_traceback(self, task_id): - """Get the traceback for a failed task.""" - return self.get_task_meta(task_id).get('traceback') - - def get_result(self, task_id): - """Get the result of a task.""" - meta = self.get_task_meta(task_id) - if meta['status'] in self.EXCEPTION_STATES: - return self.exception_to_python(meta['result']) - else: - return meta['result'] - - def get_children(self, task_id): - """Get the list of subtasks sent by a task.""" - try: - return self.get_task_meta(task_id)['children'] - except KeyError: - pass - - def get_task_meta(self, task_id, cache=True): - if cache: - try: - return self._cache[task_id] - except KeyError: - pass - - meta = self._get_task_meta_for(task_id) - if cache and meta.get('status') == states.SUCCESS: - self._cache[task_id] = meta - return meta - - def reload_task_result(self, task_id): - """Reload task result, even if it has been previously fetched.""" - self._cache[task_id] = self.get_task_meta(task_id, cache=False) - - def reload_group_result(self, group_id): - """Reload group result, even if it has been previously fetched.""" - self._cache[group_id] = self.get_group_meta(group_id, cache=False) - - def get_group_meta(self, group_id, cache=True): - if cache: - try: - return self._cache[group_id] - except KeyError: - pass - - meta = self._restore_group(group_id) - if cache and meta is not None: - self._cache[group_id] = meta - return meta - - def restore_group(self, group_id, cache=True): - """Get the result for a group.""" - meta = self.get_group_meta(group_id, cache=cache) - if meta: - return meta['result'] - - def save_group(self, group_id, result): - """Store the result of an executed group.""" - return self._save_group(group_id, result) - - def delete_group(self, group_id): - self._cache.pop(group_id, None) - return self._delete_group(group_id) - - def cleanup(self): - """Backend cleanup. Is run by - :class:`celery.task.DeleteExpiredTaskMetaTask`.""" - pass - - def process_cleanup(self): - """Cleanup actions to do at the end of a task worker process.""" - pass - - def on_task_call(self, producer, task_id): - return {} - - def on_chord_part_return(self, task, state, result, propagate=False): - pass - - def fallback_chord_unlock(self, group_id, body, result=None, - countdown=1, **kwargs): - kwargs['result'] = [r.as_tuple() for r in result] - self.app.tasks['celery.chord_unlock'].apply_async( - (group_id, body, ), kwargs, countdown=countdown, - ) - - def apply_chord(self, header, partial_args, group_id, body, **options): - result = header(*partial_args, task_id=group_id) - self.fallback_chord_unlock(group_id, body, **options) - return result - - def current_task_children(self, request=None): - request = request or getattr(current_task(), 'request', None) - if request: - return [r.as_tuple() for r in getattr(request, 'children', [])] - - def __reduce__(self, args=(), kwargs={}): - return (unpickle_backend, (self.__class__, args, kwargs)) -BaseDictBackend = BaseBackend # XXX compat - - -class KeyValueStoreBackend(BaseBackend): - key_t = ensure_bytes - task_keyprefix = 'celery-task-meta-' - group_keyprefix = 'celery-taskset-meta-' - chord_keyprefix = 'chord-unlock-' - implements_incr = False - - def __init__(self, *args, **kwargs): - if hasattr(self.key_t, '__func__'): - self.key_t = self.key_t.__func__ # remove binding - self._encode_prefixes() - super(KeyValueStoreBackend, self).__init__(*args, **kwargs) - if self.implements_incr: - self.apply_chord = self._apply_chord_incr - - def _encode_prefixes(self): - self.task_keyprefix = self.key_t(self.task_keyprefix) - self.group_keyprefix = self.key_t(self.group_keyprefix) - self.chord_keyprefix = self.key_t(self.chord_keyprefix) - - def get(self, key): - raise NotImplementedError('Must implement the get method.') - - def mget(self, keys): - raise NotImplementedError('Does not support get_many') - - def set(self, key, value): - raise NotImplementedError('Must implement the set method.') - - def delete(self, key): - raise NotImplementedError('Must implement the delete method') - - def incr(self, key): - raise NotImplementedError('Does not implement incr') - - def expire(self, key, value): - pass - - def get_key_for_task(self, task_id, key=''): - """Get the cache key for a task by id.""" - key_t = self.key_t - return key_t('').join([ - self.task_keyprefix, key_t(task_id), key_t(key), - ]) - - def get_key_for_group(self, group_id, key=''): - """Get the cache key for a group by id.""" - key_t = self.key_t - return key_t('').join([ - self.group_keyprefix, key_t(group_id), key_t(key), - ]) - - def get_key_for_chord(self, group_id, key=''): - """Get the cache key for the chord waiting on group with given id.""" - key_t = self.key_t - return key_t('').join([ - self.chord_keyprefix, key_t(group_id), key_t(key), - ]) - - def _strip_prefix(self, key): - """Takes bytes, emits string.""" - key = self.key_t(key) - for prefix in self.task_keyprefix, self.group_keyprefix: - if key.startswith(prefix): - return bytes_to_str(key[len(prefix):]) - return bytes_to_str(key) - - def _mget_to_results(self, values, keys): - if hasattr(values, 'items'): - # client returns dict so mapping preserved. - return dict((self._strip_prefix(k), self.decode(v)) - for k, v in items(values) - if v is not None) - else: - # client returns list so need to recreate mapping. - return dict((bytes_to_str(keys[i]), self.decode(value)) - for i, value in enumerate(values) - if value is not None) - - def get_many(self, task_ids, timeout=None, interval=0.5, no_ack=True, - READY_STATES=states.READY_STATES): - interval = 0.5 if interval is None else interval - ids = task_ids if isinstance(task_ids, set) else set(task_ids) - cached_ids = set() - cache = self._cache - for task_id in ids: - try: - cached = cache[task_id] - except KeyError: - pass - else: - if cached['status'] in READY_STATES: - yield bytes_to_str(task_id), cached - cached_ids.add(task_id) - - ids.difference_update(cached_ids) - iterations = 0 - while ids: - keys = list(ids) - r = self._mget_to_results(self.mget([self.get_key_for_task(k) - for k in keys]), keys) - cache.update(r) - ids.difference_update(set(bytes_to_str(v) for v in r)) - for key, value in items(r): - yield bytes_to_str(key), value - if timeout and iterations * interval >= timeout: - raise TimeoutError('Operation timed out ({0})'.format(timeout)) - time.sleep(interval) # don't busy loop. - iterations += 1 - - def _forget(self, task_id): - self.delete(self.get_key_for_task(task_id)) - - def _store_result(self, task_id, result, status, - traceback=None, request=None, **kwargs): - meta = {'status': status, 'result': result, 'traceback': traceback, - 'children': self.current_task_children(request)} - self.set(self.get_key_for_task(task_id), self.encode(meta)) - return result - - def _save_group(self, group_id, result): - self.set(self.get_key_for_group(group_id), - self.encode({'result': result.as_tuple()})) - return result - - def _delete_group(self, group_id): - self.delete(self.get_key_for_group(group_id)) - - def _get_task_meta_for(self, task_id): - """Get task metadata for a task by id.""" - meta = self.get(self.get_key_for_task(task_id)) - if not meta: - return {'status': states.PENDING, 'result': None} - return self.decode(meta) - - def _restore_group(self, group_id): - """Get task metadata for a task by id.""" - meta = self.get(self.get_key_for_group(group_id)) - # previously this was always pickled, but later this - # was extended to support other serializers, so the - # structure is kind of weird. - if meta: - meta = self.decode(meta) - result = meta['result'] - meta['result'] = result_from_tuple(result, self.app) - return meta - - def _apply_chord_incr(self, header, partial_args, group_id, body, - result=None, **options): - self.save_group(group_id, self.app.GroupResult(group_id, result)) - return header(*partial_args, task_id=group_id) - - def on_chord_part_return(self, task, state, result, propagate=None): - if not self.implements_incr: - return - app = self.app - if propagate is None: - propagate = app.conf.CELERY_CHORD_PROPAGATES - gid = task.request.group - if not gid: - return - key = self.get_key_for_chord(gid) - try: - deps = GroupResult.restore(gid, backend=task.backend) - except Exception as exc: - callback = maybe_signature(task.request.chord, app=app) - logger.error('Chord %r raised: %r', gid, exc, exc_info=1) - return self.chord_error_from_stack( - callback, - ChordError('Cannot restore group: {0!r}'.format(exc)), - ) - if deps is None: - try: - raise ValueError(gid) - except ValueError as exc: - callback = maybe_signature(task.request.chord, app=app) - logger.error('Chord callback %r raised: %r', gid, exc, - exc_info=1) - return self.chord_error_from_stack( - callback, - ChordError('GroupResult {0} no longer exists'.format(gid)), - ) - val = self.incr(key) - if val >= len(deps): - callback = maybe_signature(task.request.chord, app=app) - j = deps.join_native if deps.supports_native_join else deps.join - try: - with allow_join_result(): - ret = j(timeout=3.0, propagate=propagate) - except Exception as exc: - try: - culprit = next(deps._failed_join_report()) - reason = 'Dependency {0.id} raised {1!r}'.format( - culprit, exc, - ) - except StopIteration: - reason = repr(exc) - - logger.error('Chord %r raised: %r', gid, reason, exc_info=1) - self.chord_error_from_stack(callback, ChordError(reason)) - else: - try: - callback.delay(ret) - except Exception as exc: - logger.error('Chord %r raised: %r', gid, exc, exc_info=1) - self.chord_error_from_stack( - callback, - ChordError('Callback error: {0!r}'.format(exc)), - ) - finally: - deps.delete() - self.client.delete(key) - else: - self.expire(key, 86400) - - -class DisabledBackend(BaseBackend): - _cache = {} # need this attribute to reset cache in tests. - - def store_result(self, *args, **kwargs): - pass - - def _is_disabled(self, *args, **kwargs): - raise NotImplementedError( - 'No result backend configured. ' - 'Please see the documentation for more information.') - wait_for = get_status = get_result = get_traceback = _is_disabled diff --git a/awx/lib/site-packages/celery/backends/cache.py b/awx/lib/site-packages/celery/backends/cache.py deleted file mode 100644 index ac87100990..0000000000 --- a/awx/lib/site-packages/celery/backends/cache.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.cache - ~~~~~~~~~~~~~~~~~~~~~ - - Memcache and in-memory cache result backend. - -""" -from __future__ import absolute_import - -import sys - -from kombu.utils import cached_property -from kombu.utils.encoding import bytes_to_str, ensure_bytes - -from celery.exceptions import ImproperlyConfigured -from celery.utils.functional import LRUCache - -from .base import KeyValueStoreBackend - -__all__ = ['CacheBackend'] - -_imp = [None] - -PY3 = sys.version_info[0] == 3 - -REQUIRES_BACKEND = """\ -The memcached backend requires either pylibmc or python-memcached.\ -""" - -UNKNOWN_BACKEND = """\ -The cache backend {0!r} is unknown, -Please use one of the following backends instead: {1}\ -""" - - -def import_best_memcache(): - if _imp[0] is None: - is_pylibmc, memcache_key_t = False, ensure_bytes - try: - import pylibmc as memcache - is_pylibmc = True - except ImportError: - try: - import memcache # noqa - except ImportError: - raise ImproperlyConfigured(REQUIRES_BACKEND) - if PY3: - memcache_key_t = bytes_to_str - _imp[0] = (is_pylibmc, memcache, memcache_key_t) - return _imp[0] - - -def get_best_memcache(*args, **kwargs): - is_pylibmc, memcache, key_t = import_best_memcache() - Client = _Client = memcache.Client - - if not is_pylibmc: - def Client(*args, **kwargs): # noqa - kwargs.pop('behaviors', None) - return _Client(*args, **kwargs) - - return Client, key_t - - -class DummyClient(object): - - def __init__(self, *args, **kwargs): - self.cache = LRUCache(limit=5000) - - def get(self, key, *args, **kwargs): - return self.cache.get(key) - - def get_multi(self, keys): - cache = self.cache - return dict((k, cache[k]) for k in keys if k in cache) - - def set(self, key, value, *args, **kwargs): - self.cache[key] = value - - def delete(self, key, *args, **kwargs): - self.cache.pop(key, None) - - def incr(self, key, delta=1): - return self.cache.incr(key, delta) - - -backends = {'memcache': get_best_memcache, - 'memcached': get_best_memcache, - 'pylibmc': get_best_memcache, - 'memory': lambda: (DummyClient, ensure_bytes)} - - -class CacheBackend(KeyValueStoreBackend): - servers = None - supports_autoexpire = True - supports_native_join = True - implements_incr = True - - def __init__(self, app, expires=None, backend=None, - options={}, url=None, **kwargs): - super(CacheBackend, self).__init__(app, **kwargs) - - self.options = dict(self.app.conf.CELERY_CACHE_BACKEND_OPTIONS, - **options) - - self.backend = url or backend or self.app.conf.CELERY_CACHE_BACKEND - if self.backend: - self.backend, _, servers = self.backend.partition('://') - self.servers = servers.rstrip('/').split(';') - self.expires = self.prepare_expires(expires, type=int) - try: - self.Client, self.key_t = backends[self.backend]() - except KeyError: - raise ImproperlyConfigured(UNKNOWN_BACKEND.format( - self.backend, ', '.join(backends))) - self._encode_prefixes() # rencode the keyprefixes - - def get(self, key): - return self.client.get(key) - - def mget(self, keys): - return self.client.get_multi(keys) - - def set(self, key, value): - return self.client.set(key, value, self.expires) - - def delete(self, key): - return self.client.delete(key) - - def _apply_chord_incr(self, header, partial_args, group_id, body, **opts): - self.client.set(self.get_key_for_chord(group_id), '0', time=86400) - return super(CacheBackend, self)._apply_chord_incr( - header, partial_args, group_id, body, **opts - ) - - def incr(self, key): - return self.client.incr(key) - - @cached_property - def client(self): - return self.Client(self.servers, **self.options) - - def __reduce__(self, args=(), kwargs={}): - servers = ';'.join(self.servers) - backend = '{0}://{1}/'.format(self.backend, servers) - kwargs.update( - dict(backend=backend, - expires=self.expires, - options=self.options)) - return super(CacheBackend, self).__reduce__(args, kwargs) diff --git a/awx/lib/site-packages/celery/backends/cassandra.py b/awx/lib/site-packages/celery/backends/cassandra.py deleted file mode 100644 index 774e6b7927..0000000000 --- a/awx/lib/site-packages/celery/backends/cassandra.py +++ /dev/null @@ -1,194 +0,0 @@ -# -* coding: utf-8 -*- -""" - celery.backends.cassandra - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - Apache Cassandra result store backend. - -""" -from __future__ import absolute_import - -try: # pragma: no cover - import pycassa - from thrift import Thrift - C = pycassa.cassandra.ttypes -except ImportError: # pragma: no cover - pycassa = None # noqa - -import socket -import time - -from celery import states -from celery.exceptions import ImproperlyConfigured -from celery.five import monotonic -from celery.utils.log import get_logger -from celery.utils.timeutils import maybe_timedelta, timedelta_seconds - -from .base import BaseBackend - -__all__ = ['CassandraBackend'] - -logger = get_logger(__name__) - - -class CassandraBackend(BaseBackend): - """Highly fault tolerant Cassandra backend. - - .. attribute:: servers - - List of Cassandra servers with format: ``hostname:port``. - - :raises celery.exceptions.ImproperlyConfigured: if - module :mod:`pycassa` is not available. - - """ - servers = [] - keyspace = None - column_family = None - detailed_mode = False - _retry_timeout = 300 - _retry_wait = 3 - supports_autoexpire = True - - def __init__(self, servers=None, keyspace=None, column_family=None, - cassandra_options=None, detailed_mode=False, **kwargs): - """Initialize Cassandra backend. - - Raises :class:`celery.exceptions.ImproperlyConfigured` if - the :setting:`CASSANDRA_SERVERS` setting is not set. - - """ - super(CassandraBackend, self).__init__(**kwargs) - - self.expires = kwargs.get('expires') or maybe_timedelta( - self.app.conf.CELERY_TASK_RESULT_EXPIRES) - - if not pycassa: - raise ImproperlyConfigured( - 'You need to install the pycassa library to use the ' - 'Cassandra backend. See https://github.com/pycassa/pycassa') - - conf = self.app.conf - self.servers = (servers or - conf.get('CASSANDRA_SERVERS') or - self.servers) - self.keyspace = (keyspace or - conf.get('CASSANDRA_KEYSPACE') or - self.keyspace) - self.column_family = (column_family or - conf.get('CASSANDRA_COLUMN_FAMILY') or - self.column_family) - self.cassandra_options = dict(conf.get('CASSANDRA_OPTIONS') or {}, - **cassandra_options or {}) - self.detailed_mode = (detailed_mode or - conf.get('CASSANDRA_DETAILED_MODE') or - self.detailed_mode) - read_cons = conf.get('CASSANDRA_READ_CONSISTENCY') or 'LOCAL_QUORUM' - write_cons = conf.get('CASSANDRA_WRITE_CONSISTENCY') or 'LOCAL_QUORUM' - try: - self.read_consistency = getattr(pycassa.ConsistencyLevel, - read_cons) - except AttributeError: - self.read_consistency = pycassa.ConsistencyLevel.LOCAL_QUORUM - try: - self.write_consistency = getattr(pycassa.ConsistencyLevel, - write_cons) - except AttributeError: - self.write_consistency = pycassa.ConsistencyLevel.LOCAL_QUORUM - - if not self.servers or not self.keyspace or not self.column_family: - raise ImproperlyConfigured( - 'Cassandra backend not configured.') - - self._column_family = None - - def _retry_on_error(self, fun, *args, **kwargs): - ts = monotonic() + self._retry_timeout - while 1: - try: - return fun(*args, **kwargs) - except (pycassa.InvalidRequestException, - pycassa.TimedOutException, - pycassa.UnavailableException, - pycassa.AllServersUnavailable, - socket.error, - socket.timeout, - Thrift.TException) as exc: - if monotonic() > ts: - raise - logger.warning('Cassandra error: %r. Retrying...', exc) - time.sleep(self._retry_wait) - - def _get_column_family(self): - if self._column_family is None: - conn = pycassa.ConnectionPool(self.keyspace, - server_list=self.servers, - **self.cassandra_options) - self._column_family = pycassa.ColumnFamily( - conn, self.column_family, - read_consistency_level=self.read_consistency, - write_consistency_level=self.write_consistency, - ) - return self._column_family - - def process_cleanup(self): - if self._column_family is not None: - self._column_family = None - - def _store_result(self, task_id, result, status, - traceback=None, request=None, **kwargs): - """Store return value and status of an executed task.""" - - def _do_store(): - cf = self._get_column_family() - date_done = self.app.now() - meta = {'status': status, - 'date_done': date_done.strftime('%Y-%m-%dT%H:%M:%SZ'), - 'traceback': self.encode(traceback), - 'children': self.encode( - self.current_task_children(request), - )} - if self.detailed_mode: - meta['result'] = result - cf.insert(task_id, {date_done: self.encode(meta)}, - ttl=self.expires and timedelta_seconds(self.expires)) - else: - meta['result'] = self.encode(result) - cf.insert(task_id, meta, - ttl=self.expires and timedelta_seconds(self.expires)) - - return self._retry_on_error(_do_store) - - def _get_task_meta_for(self, task_id): - """Get task metadata for a task by id.""" - - def _do_get(): - cf = self._get_column_family() - try: - if self.detailed_mode: - row = cf.get(task_id, column_reversed=True, column_count=1) - meta = self.decode(list(row.values())[0]) - meta['task_id'] = task_id - else: - obj = cf.get(task_id) - meta = { - 'task_id': task_id, - 'status': obj['status'], - 'result': self.decode(obj['result']), - 'date_done': obj['date_done'], - 'traceback': self.decode(obj['traceback']), - 'children': self.decode(obj['children']), - } - except (KeyError, pycassa.NotFoundException): - meta = {'status': states.PENDING, 'result': None} - return meta - - return self._retry_on_error(_do_get) - - def __reduce__(self, args=(), kwargs={}): - kwargs.update( - dict(servers=self.servers, - keyspace=self.keyspace, - column_family=self.column_family, - cassandra_options=self.cassandra_options)) - return super(CassandraBackend, self).__reduce__(args, kwargs) diff --git a/awx/lib/site-packages/celery/backends/couchbase.py b/awx/lib/site-packages/celery/backends/couchbase.py deleted file mode 100644 index 2d51b80010..0000000000 --- a/awx/lib/site-packages/celery/backends/couchbase.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.couchbase - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - CouchBase result store backend. - -""" -from __future__ import absolute_import - -import logging - -try: - from couchbase import Couchbase - from couchbase.connection import Connection - from couchbase.exceptions import NotFoundError -except ImportError: - Couchbase = Connection = NotFoundError = None # noqa - -from kombu.utils.url import _parse_url - -from celery.exceptions import ImproperlyConfigured -from celery.utils.timeutils import maybe_timedelta - -from .base import KeyValueStoreBackend - -__all__ = ['CouchBaseBackend'] - - -class CouchBaseBackend(KeyValueStoreBackend): - bucket = 'default' - host = 'localhost' - port = 8091 - username = None - password = None - quiet = False - conncache = None - unlock_gil = True - timeout = 2.5 - transcoder = None - # supports_autoexpire = False - - def __init__(self, url=None, *args, **kwargs): - """Initialize CouchBase backend instance. - - :raises celery.exceptions.ImproperlyConfigured: if - module :mod:`couchbase` is not available. - - """ - super(CouchBaseBackend, self).__init__(*args, **kwargs) - - self.expires = kwargs.get('expires') or maybe_timedelta( - self.app.conf.CELERY_TASK_RESULT_EXPIRES) - - if Couchbase is None: - raise ImproperlyConfigured( - 'You need to install the couchbase library to use the ' - 'CouchBase backend.', - ) - - uhost = uport = uname = upass = ubucket = None - if url: - _, uhost, uport, uname, upass, ubucket, _ = _parse_url(url) - ubucket = ubucket.strip('/') if ubucket else None - - config = self.app.conf.get('CELERY_COUCHBASE_BACKEND_SETTINGS', None) - if config is not None: - if not isinstance(config, dict): - raise ImproperlyConfigured( - 'Couchbase backend settings should be grouped in a dict', - ) - else: - config = {} - - self.host = uhost or config.get('host', self.host) - self.port = int(uport or config.get('port', self.port)) - self.bucket = ubucket or config.get('bucket', self.bucket) - self.username = uname or config.get('username', self.username) - self.password = upass or config.get('password', self.password) - - self._connection = None - - def _get_connection(self): - """Connect to the Couchbase server.""" - if self._connection is None: - kwargs = {'bucket': self.bucket, 'host': self.host} - - if self.port: - kwargs.update({'port': self.port}) - if self.username: - kwargs.update({'username': self.username}) - if self.password: - kwargs.update({'password': self.password}) - - logging.debug('couchbase settings %r', kwargs) - self._connection = Connection(**kwargs) - return self._connection - - @property - def connection(self): - return self._get_connection() - - def get(self, key): - try: - return self.connection.get(key).value - except NotFoundError: - return None - - def set(self, key, value): - self.connection.set(key, value) - - def mget(self, keys): - return [self.get(key) for key in keys] - - def delete(self, key): - self.connection.delete(key) diff --git a/awx/lib/site-packages/celery/backends/database/__init__.py b/awx/lib/site-packages/celery/backends/database/__init__.py deleted file mode 100644 index c52e75879b..0000000000 --- a/awx/lib/site-packages/celery/backends/database/__init__.py +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.database - ~~~~~~~~~~~~~~~~~~~~~~~~ - - SQLAlchemy result store backend. - -""" -from __future__ import absolute_import - -import logging -from contextlib import contextmanager -from functools import wraps - -from celery import states -from celery.backends.base import BaseBackend -from celery.exceptions import ImproperlyConfigured -from celery.five import range -from celery.utils.timeutils import maybe_timedelta - -from .models import Task -from .models import TaskSet -from .session import SessionManager - -logger = logging.getLogger(__name__) - -__all__ = ['DatabaseBackend'] - - -def _sqlalchemy_installed(): - try: - import sqlalchemy - except ImportError: - raise ImproperlyConfigured( - 'The database result backend requires SQLAlchemy to be installed.' - 'See http://pypi.python.org/pypi/SQLAlchemy') - return sqlalchemy -_sqlalchemy_installed() - -from sqlalchemy.exc import DatabaseError, InvalidRequestError -from sqlalchemy.orm.exc import StaleDataError - - -@contextmanager -def session_cleanup(session): - try: - yield - except Exception: - session.rollback() - raise - finally: - session.close() - - -def retry(fun): - - @wraps(fun) - def _inner(*args, **kwargs): - max_retries = kwargs.pop('max_retries', 3) - - for retries in range(max_retries): - try: - return fun(*args, **kwargs) - except (DatabaseError, InvalidRequestError, StaleDataError): - logger.warning( - "Failed operation %s. Retrying %s more times.", - fun.__name__, max_retries - retries - 1, - exc_info=True, - ) - if retries + 1 >= max_retries: - raise - - return _inner - - -class DatabaseBackend(BaseBackend): - """The database result backend.""" - # ResultSet.iterate should sleep this much between each pool, - # to not bombard the database with queries. - subpolling_interval = 0.5 - - def __init__(self, dburi=None, expires=None, - engine_options=None, url=None, **kwargs): - # The `url` argument was added later and is used by - # the app to set backend by url (celery.backends.get_backend_by_url) - super(DatabaseBackend, self).__init__(**kwargs) - conf = self.app.conf - self.expires = maybe_timedelta(self.prepare_expires(expires)) - self.dburi = url or dburi or conf.CELERY_RESULT_DBURI - self.engine_options = dict( - engine_options or {}, - **conf.CELERY_RESULT_ENGINE_OPTIONS or {}) - self.short_lived_sessions = kwargs.get( - 'short_lived_sessions', - conf.CELERY_RESULT_DB_SHORT_LIVED_SESSIONS, - ) - - tablenames = conf.CELERY_RESULT_DB_TABLENAMES or {} - Task.__table__.name = tablenames.get('task', 'celery_taskmeta') - TaskSet.__table__.name = tablenames.get('group', 'celery_tasksetmeta') - - if not self.dburi: - raise ImproperlyConfigured( - 'Missing connection string! Do you have ' - 'CELERY_RESULT_DBURI set to a real value?') - - def ResultSession(self, session_manager=SessionManager()): - return session_manager.session_factory( - dburi=self.dburi, - short_lived_sessions=self.short_lived_sessions, - **self.engine_options - ) - - @retry - def _store_result(self, task_id, result, status, - traceback=None, max_retries=3, **kwargs): - """Store return value and status of an executed task.""" - session = self.ResultSession() - with session_cleanup(session): - task = list(session.query(Task).filter(Task.task_id == task_id)) - task = task and task[0] - if not task: - task = Task(task_id) - session.add(task) - session.flush() - task.result = result - task.status = status - task.traceback = traceback - session.commit() - return result - - @retry - def _get_task_meta_for(self, task_id): - """Get task metadata for a task by id.""" - session = self.ResultSession() - with session_cleanup(session): - task = list(session.query(Task).filter(Task.task_id == task_id)) - task = task and task[0] - if not task: - task = Task(task_id) - task.status = states.PENDING - task.result = None - return task.to_dict() - - @retry - def _save_group(self, group_id, result): - """Store the result of an executed group.""" - session = self.ResultSession() - with session_cleanup(session): - group = TaskSet(group_id, result) - session.add(group) - session.flush() - session.commit() - return result - - @retry - def _restore_group(self, group_id): - """Get metadata for group by id.""" - session = self.ResultSession() - with session_cleanup(session): - group = session.query(TaskSet).filter( - TaskSet.taskset_id == group_id).first() - if group: - return group.to_dict() - - @retry - def _delete_group(self, group_id): - """Delete metadata for group by id.""" - session = self.ResultSession() - with session_cleanup(session): - session.query(TaskSet).filter( - TaskSet.taskset_id == group_id).delete() - session.flush() - session.commit() - - @retry - def _forget(self, task_id): - """Forget about result.""" - session = self.ResultSession() - with session_cleanup(session): - session.query(Task).filter(Task.task_id == task_id).delete() - session.commit() - - def cleanup(self): - """Delete expired metadata.""" - session = self.ResultSession() - expires = self.expires - now = self.app.now() - with session_cleanup(session): - session.query(Task).filter( - Task.date_done < (now - expires)).delete() - session.query(TaskSet).filter( - TaskSet.date_done < (now - expires)).delete() - session.commit() - - def __reduce__(self, args=(), kwargs={}): - kwargs.update( - dict(dburi=self.dburi, - expires=self.expires, - engine_options=self.engine_options)) - return super(DatabaseBackend, self).__reduce__(args, kwargs) diff --git a/awx/lib/site-packages/celery/backends/database/models.py b/awx/lib/site-packages/celery/backends/database/models.py deleted file mode 100644 index 2802a007c0..0000000000 --- a/awx/lib/site-packages/celery/backends/database/models.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.database.models - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Database tables for the SQLAlchemy result store backend. - -""" -from __future__ import absolute_import - -from datetime import datetime - -import sqlalchemy as sa -from sqlalchemy.types import PickleType - -from celery import states - -from .session import ResultModelBase - -__all__ = ['Task', 'TaskSet'] - - -class Task(ResultModelBase): - """Task result/status.""" - __tablename__ = 'celery_taskmeta' - __table_args__ = {'sqlite_autoincrement': True} - - id = sa.Column(sa.Integer, sa.Sequence('task_id_sequence'), - primary_key=True, - autoincrement=True) - task_id = sa.Column(sa.String(255), unique=True) - status = sa.Column(sa.String(50), default=states.PENDING) - result = sa.Column(PickleType, nullable=True) - date_done = sa.Column(sa.DateTime, default=datetime.utcnow, - onupdate=datetime.utcnow, nullable=True) - traceback = sa.Column(sa.Text, nullable=True) - - def __init__(self, task_id): - self.task_id = task_id - - def to_dict(self): - return {'task_id': self.task_id, - 'status': self.status, - 'result': self.result, - 'traceback': self.traceback, - 'date_done': self.date_done} - - def __repr__(self): - return '<Task {0.task_id} state: {0.status}>'.format(self) - - -class TaskSet(ResultModelBase): - """TaskSet result""" - __tablename__ = 'celery_tasksetmeta' - __table_args__ = {'sqlite_autoincrement': True} - - id = sa.Column(sa.Integer, sa.Sequence('taskset_id_sequence'), - autoincrement=True, primary_key=True) - taskset_id = sa.Column(sa.String(255), unique=True) - result = sa.Column(PickleType, nullable=True) - date_done = sa.Column(sa.DateTime, default=datetime.utcnow, - nullable=True) - - def __init__(self, taskset_id, result): - self.taskset_id = taskset_id - self.result = result - - def to_dict(self): - return {'taskset_id': self.taskset_id, - 'result': self.result, - 'date_done': self.date_done} - - def __repr__(self): - return '<TaskSet: {0.taskset_id}>'.format(self) diff --git a/awx/lib/site-packages/celery/backends/database/session.py b/awx/lib/site-packages/celery/backends/database/session.py deleted file mode 100644 index 1575d7f323..0000000000 --- a/awx/lib/site-packages/celery/backends/database/session.py +++ /dev/null @@ -1,62 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.database.session - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - SQLAlchemy sessions. - -""" -from __future__ import absolute_import - -from billiard.util import register_after_fork - -from sqlalchemy import create_engine -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker -from sqlalchemy.pool import NullPool - -ResultModelBase = declarative_base() - -__all__ = ['SessionManager'] - - -class SessionManager(object): - def __init__(self): - self._engines = {} - self._sessions = {} - self.forked = False - self.prepared = False - register_after_fork(self, self._after_fork) - - def _after_fork(self,): - self.forked = True - - def get_engine(self, dburi, **kwargs): - if self.forked: - try: - return self._engines[dburi] - except KeyError: - engine = self._engines[dburi] = create_engine(dburi, **kwargs) - return engine - else: - kwargs['poolclass'] = NullPool - return create_engine(dburi, **kwargs) - - def create_session(self, dburi, short_lived_sessions=False, **kwargs): - engine = self.get_engine(dburi, **kwargs) - if self.forked: - if short_lived_sessions or dburi not in self._sessions: - self._sessions[dburi] = sessionmaker(bind=engine) - return engine, self._sessions[dburi] - else: - return engine, sessionmaker(bind=engine) - - def prepare_models(self, engine): - if not self.prepared: - ResultModelBase.metadata.create_all(engine) - self.prepared = True - - def session_factory(self, dburi, **kwargs): - engine, session = self.create_session(dburi, **kwargs) - self.prepare_models(engine) - return session() diff --git a/awx/lib/site-packages/celery/backends/mongodb.py b/awx/lib/site-packages/celery/backends/mongodb.py deleted file mode 100644 index c3229d51c6..0000000000 --- a/awx/lib/site-packages/celery/backends/mongodb.py +++ /dev/null @@ -1,242 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.mongodb - ~~~~~~~~~~~~~~~~~~~~~~~ - - MongoDB result store backend. - -""" -from __future__ import absolute_import - -from datetime import datetime - -try: - import pymongo -except ImportError: # pragma: no cover - pymongo = None # noqa - -if pymongo: - try: - from bson.binary import Binary - except ImportError: # pragma: no cover - from pymongo.binary import Binary # noqa -else: # pragma: no cover - Binary = None # noqa - -from kombu.syn import detect_environment -from kombu.utils import cached_property - -from celery import states -from celery.exceptions import ImproperlyConfigured -from celery.five import string_t -from celery.utils.timeutils import maybe_timedelta - -from .base import BaseBackend - -__all__ = ['MongoBackend'] - - -class Bunch(object): - - def __init__(self, **kw): - self.__dict__.update(kw) - - -class MongoBackend(BaseBackend): - host = 'localhost' - port = 27017 - user = None - password = None - database_name = 'celery' - taskmeta_collection = 'celery_taskmeta' - max_pool_size = 10 - options = None - - supports_autoexpire = False - - _connection = None - - def __init__(self, *args, **kwargs): - """Initialize MongoDB backend instance. - - :raises celery.exceptions.ImproperlyConfigured: if - module :mod:`pymongo` is not available. - - """ - self.options = {} - super(MongoBackend, self).__init__(*args, **kwargs) - self.expires = kwargs.get('expires') or maybe_timedelta( - self.app.conf.CELERY_TASK_RESULT_EXPIRES) - - if not pymongo: - raise ImproperlyConfigured( - 'You need to install the pymongo library to use the ' - 'MongoDB backend.') - - config = self.app.conf.get('CELERY_MONGODB_BACKEND_SETTINGS') - if config is not None: - if not isinstance(config, dict): - raise ImproperlyConfigured( - 'MongoDB backend settings should be grouped in a dict') - config = dict(config) # do not modify original - - self.host = config.pop('host', self.host) - self.port = int(config.pop('port', self.port)) - self.user = config.pop('user', self.user) - self.password = config.pop('password', self.password) - self.database_name = config.pop('database', self.database_name) - self.taskmeta_collection = config.pop( - 'taskmeta_collection', self.taskmeta_collection, - ) - - self.options = dict(config, **config.pop('options', None) or {}) - - # Set option defaults - self.options.setdefault('ssl', self.app.conf.BROKER_USE_SSL) - self.options.setdefault('max_pool_size', self.max_pool_size) - self.options.setdefault('auto_start_request', False) - - url = kwargs.get('url') - if url: - # Specifying backend as an URL - self.host = url - - def _get_connection(self): - """Connect to the MongoDB server.""" - if self._connection is None: - from pymongo import MongoClient - - # The first pymongo.Connection() argument (host) can be - # a list of ['host:port'] elements or a mongodb connection - # URI. If this is the case, don't use self.port - # but let pymongo get the port(s) from the URI instead. - # This enables the use of replica sets and sharding. - # See pymongo.Connection() for more info. - url = self.host - if isinstance(url, string_t) \ - and not url.startswith('mongodb://'): - url = 'mongodb://{0}:{1}'.format(url, self.port) - if url == 'mongodb://': - url = url + 'localhost' - if detect_environment() != 'default': - self.options['use_greenlets'] = True - self._connection = MongoClient(host=url, **self.options) - - return self._connection - - def process_cleanup(self): - if self._connection is not None: - # MongoDB connection will be closed automatically when object - # goes out of scope - del(self.collection) - del(self.database) - self._connection = None - - def _store_result(self, task_id, result, status, - traceback=None, request=None, **kwargs): - """Store return value and status of an executed task.""" - meta = {'_id': task_id, - 'status': status, - 'result': Binary(self.encode(result)), - 'date_done': datetime.utcnow(), - 'traceback': Binary(self.encode(traceback)), - 'children': Binary(self.encode( - self.current_task_children(request), - ))} - self.collection.save(meta) - - return result - - def _get_task_meta_for(self, task_id): - """Get task metadata for a task by id.""" - - obj = self.collection.find_one({'_id': task_id}) - if not obj: - return {'status': states.PENDING, 'result': None} - - meta = { - 'task_id': obj['_id'], - 'status': obj['status'], - 'result': self.decode(obj['result']), - 'date_done': obj['date_done'], - 'traceback': self.decode(obj['traceback']), - 'children': self.decode(obj['children']), - } - - return meta - - def _save_group(self, group_id, result): - """Save the group result.""" - meta = {'_id': group_id, - 'result': Binary(self.encode(result)), - 'date_done': datetime.utcnow()} - self.collection.save(meta) - - return result - - def _restore_group(self, group_id): - """Get the result for a group by id.""" - obj = self.collection.find_one({'_id': group_id}) - if not obj: - return - - meta = { - 'task_id': obj['_id'], - 'result': self.decode(obj['result']), - 'date_done': obj['date_done'], - } - - return meta - - def _delete_group(self, group_id): - """Delete a group by id.""" - self.collection.remove({'_id': group_id}) - - def _forget(self, task_id): - """ - Remove result from MongoDB. - - :raises celery.exceptions.OperationsError: if the task_id could not be - removed. - """ - # By using safe=True, this will wait until it receives a response from - # the server. Likewise, it will raise an OperationsError if the - # response was unable to be completed. - self.collection.remove({'_id': task_id}) - - def cleanup(self): - """Delete expired metadata.""" - self.collection.remove( - {'date_done': {'$lt': self.app.now() - self.expires}}, - ) - - def __reduce__(self, args=(), kwargs={}): - kwargs.update( - dict(expires=self.expires)) - return super(MongoBackend, self).__reduce__(args, kwargs) - - def _get_database(self): - conn = self._get_connection() - db = conn[self.database_name] - if self.user and self.password: - if not db.authenticate(self.user, - self.password): - raise ImproperlyConfigured( - 'Invalid MongoDB username or password.') - return db - - @cached_property - def database(self): - """Get database from MongoDB connection and perform authentication - if necessary.""" - return self._get_database() - - @cached_property - def collection(self): - """Get the metadata task collection.""" - collection = self.database[self.taskmeta_collection] - - # Ensure an index on date_done is there, if not process the index - # in the background. Once completed cleanup will be much faster - collection.ensure_index('date_done', background='true') - return collection diff --git a/awx/lib/site-packages/celery/backends/redis.py b/awx/lib/site-packages/celery/backends/redis.py deleted file mode 100644 index 314b1d2b8f..0000000000 --- a/awx/lib/site-packages/celery/backends/redis.py +++ /dev/null @@ -1,271 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.redis - ~~~~~~~~~~~~~~~~~~~~~ - - Redis result store backend. - -""" -from __future__ import absolute_import - -from functools import partial - -from kombu.utils import cached_property, retry_over_time -from kombu.utils.url import _parse_url - -from celery import states -from celery.canvas import maybe_signature -from celery.exceptions import ChordError, ImproperlyConfigured -from celery.five import string_t -from celery.utils import deprecated_property, strtobool -from celery.utils.functional import dictfilter -from celery.utils.log import get_logger -from celery.utils.timeutils import humanize_seconds - -from .base import KeyValueStoreBackend - -try: - import redis - from redis.exceptions import ConnectionError - from kombu.transport.redis import get_redis_error_classes -except ImportError: # pragma: no cover - redis = None # noqa - ConnectionError = None # noqa - get_redis_error_classes = None # noqa - -__all__ = ['RedisBackend'] - -REDIS_MISSING = """\ -You need to install the redis library in order to use \ -the Redis result store backend.""" - -logger = get_logger(__name__) -error = logger.error - - -class RedisBackend(KeyValueStoreBackend): - """Redis task result store.""" - - #: redis-py client module. - redis = redis - - #: Maximium number of connections in the pool. - max_connections = None - - supports_autoexpire = True - supports_native_join = True - implements_incr = True - - def __init__(self, host=None, port=None, db=None, password=None, - expires=None, max_connections=None, url=None, - connection_pool=None, new_join=False, **kwargs): - super(RedisBackend, self).__init__(**kwargs) - conf = self.app.conf - if self.redis is None: - raise ImproperlyConfigured(REDIS_MISSING) - - # For compatibility with the old REDIS_* configuration keys. - def _get(key): - for prefix in 'CELERY_REDIS_{0}', 'REDIS_{0}': - try: - return conf[prefix.format(key)] - except KeyError: - pass - if host and '://' in host: - url = host - host = None - - self.max_connections = ( - max_connections or _get('MAX_CONNECTIONS') or self.max_connections - ) - self._ConnectionPool = connection_pool - - self.connparams = { - 'host': _get('HOST') or 'localhost', - 'port': _get('PORT') or 6379, - 'db': _get('DB') or 0, - 'password': _get('PASSWORD'), - 'max_connections': max_connections, - } - if url: - self.connparams = self._params_from_url(url, self.connparams) - self.url = url - self.expires = self.prepare_expires(expires, type=int) - - try: - new_join = strtobool(self.connparams.pop('new_join')) - except KeyError: - pass - if new_join: - self.apply_chord = self._new_chord_apply - self.on_chord_part_return = self._new_chord_return - - self.connection_errors, self.channel_errors = ( - get_redis_error_classes() if get_redis_error_classes - else ((), ())) - - def _params_from_url(self, url, defaults): - scheme, host, port, user, password, path, query = _parse_url(url) - connparams = dict( - defaults, **dictfilter({ - 'host': host, 'port': port, 'password': password, - 'db': query.pop('virtual_host', None)}) - ) - - if scheme == 'socket': - # use 'path' as path to the socket… in this case - # the database number should be given in 'query' - connparams.update({ - 'connection_class': self.redis.UnixDomainSocketConnection, - 'path': '/' + path, - }) - # host+port are invalid options when using this connection type. - connparams.pop('host', None) - connparams.pop('port', None) - else: - connparams['db'] = path - - # db may be string and start with / like in kombu. - db = connparams.get('db') or 0 - db = db.strip('/') if isinstance(db, string_t) else db - connparams['db'] = int(db) - - # Query parameters override other parameters - connparams.update(query) - return connparams - - def get(self, key): - return self.client.get(key) - - def mget(self, keys): - return self.client.mget(keys) - - def ensure(self, fun, args, **policy): - retry_policy = dict(self.retry_policy, **policy) - max_retries = retry_policy.get('max_retries') - return retry_over_time( - fun, self.connection_errors, args, {}, - partial(self.on_connection_error, max_retries), - **retry_policy - ) - - def on_connection_error(self, max_retries, exc, intervals, retries): - tts = next(intervals) - error('Connection to Redis lost: Retry (%s/%s) %s.', - retries, max_retries or 'Inf', - humanize_seconds(tts, 'in ')) - return tts - - def set(self, key, value, **retry_policy): - return self.ensure(self._set, (key, value), **retry_policy) - - def _set(self, key, value): - pipe = self.client.pipeline() - if self.expires: - pipe.setex(key, value, self.expires) - else: - pipe.set(key, value) - pipe.publish(key, value) - pipe.execute() - - def delete(self, key): - self.client.delete(key) - - def incr(self, key): - return self.client.incr(key) - - def expire(self, key, value): - return self.client.expire(key, value) - - def _unpack_chord_result(self, tup, decode, - PROPAGATE_STATES=states.PROPAGATE_STATES): - _, tid, state, retval = decode(tup) - if state in PROPAGATE_STATES: - raise ChordError('Dependency {0} raised {1!r}'.format(tid, retval)) - return retval - - def _new_chord_apply(self, header, partial_args, group_id, body, - result=None, **options): - # avoids saving the group in the redis db. - return header(*partial_args, task_id=group_id) - - def _new_chord_return(self, task, state, result, propagate=None, - PROPAGATE_STATES=states.PROPAGATE_STATES): - app = self.app - if propagate is None: - propagate = self.app.conf.CELERY_CHORD_PROPAGATES - request = task.request - tid, gid = request.id, request.group - if not gid or not tid: - return - - client = self.client - jkey = self.get_key_for_group(gid, '.j') - result = self.encode_result(result, state) - _, readycount, _ = client.pipeline() \ - .rpush(jkey, self.encode([1, tid, state, result])) \ - .llen(jkey) \ - .expire(jkey, 86400) \ - .execute() - - try: - callback = maybe_signature(request.chord, app=app) - total = callback['chord_size'] - if readycount >= total: - decode, unpack = self.decode, self._unpack_chord_result - resl, _ = client.pipeline() \ - .lrange(jkey, 0, total) \ - .delete(jkey) \ - .execute() - try: - callback.delay([unpack(tup, decode) for tup in resl]) - except Exception as exc: - error('Chord callback for %r raised: %r', - request.group, exc, exc_info=1) - app._tasks[callback.task].backend.fail_from_current_stack( - callback.id, - exc=ChordError('Callback error: {0!r}'.format(exc)), - ) - except ChordError as exc: - error('Chord %r raised: %r', request.group, exc, exc_info=1) - app._tasks[callback.task].backend.fail_from_current_stack( - callback.id, exc=exc, - ) - except Exception as exc: - error('Chord %r raised: %r', request.group, exc, exc_info=1) - app._tasks[callback.task].backend.fail_from_current_stack( - callback.id, exc=ChordError('Join error: {0!r}'.format(exc)), - ) - - @property - def ConnectionPool(self): - if self._ConnectionPool is None: - self._ConnectionPool = self.redis.ConnectionPool - return self._ConnectionPool - - @cached_property - def client(self): - return self.redis.Redis( - connection_pool=self.ConnectionPool(**self.connparams), - ) - - def __reduce__(self, args=(), kwargs={}): - return super(RedisBackend, self).__reduce__( - (self.url, ), {'expires': self.expires}, - ) - - @deprecated_property(3.2, 3.3) - def host(self): - return self.connparams['host'] - - @deprecated_property(3.2, 3.3) - def port(self): - return self.connparams['port'] - - @deprecated_property(3.2, 3.3) - def db(self): - return self.connparams['db'] - - @deprecated_property(3.2, 3.3) - def password(self): - return self.connparams['password'] diff --git a/awx/lib/site-packages/celery/backends/rpc.py b/awx/lib/site-packages/celery/backends/rpc.py deleted file mode 100644 index 28d54263f9..0000000000 --- a/awx/lib/site-packages/celery/backends/rpc.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.backends.rpc - ~~~~~~~~~~~~~~~~~~~ - - RPC-style result backend, using reply-to and one queue per client. - -""" -from __future__ import absolute_import - -from kombu import Consumer, Exchange -from kombu.common import maybe_declare -from kombu.utils import cached_property - -from celery import current_task -from celery.backends import amqp - -__all__ = ['RPCBackend'] - - -class RPCBackend(amqp.AMQPBackend): - persistent = False - - class Consumer(Consumer): - auto_declare = False - - def _create_exchange(self, name, type='direct', delivery_mode=2): - # uses direct to queue routing (anon exchange). - return Exchange(None) - - def on_task_call(self, producer, task_id): - maybe_declare(self.binding(producer.channel), retry=True) - - def _create_binding(self, task_id): - return self.binding - - def _many_bindings(self, ids): - return [self.binding] - - def rkey(self, task_id): - return task_id - - def destination_for(self, task_id, request): - # Request is a new argument for backends, so must still support - # old code that rely on current_task - try: - request = request or current_task.request - except AttributeError: - raise RuntimeError( - 'RPC backend missing task request for {0!r}'.format(task_id), - ) - return request.reply_to, request.correlation_id or task_id - - def on_reply_declare(self, task_id): - pass - - @property - def binding(self): - return self.Queue(self.oid, self.exchange, self.oid, - durable=False, auto_delete=False) - - @cached_property - def oid(self): - return self.app.oid diff --git a/awx/lib/site-packages/celery/beat.py b/awx/lib/site-packages/celery/beat.py deleted file mode 100644 index 8205c27812..0000000000 --- a/awx/lib/site-packages/celery/beat.py +++ /dev/null @@ -1,546 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.beat - ~~~~~~~~~~~ - - The periodic task scheduler. - -""" -from __future__ import absolute_import - -import errno -import os -import time -import shelve -import sys -import traceback - -from threading import Event, Thread - -from billiard import Process, ensure_multiprocessing -from billiard.common import reset_signals -from kombu.utils import cached_property, reprcall -from kombu.utils.functional import maybe_evaluate - -from . import __version__ -from . import platforms -from . import signals -from .five import items, reraise, values, monotonic -from .schedules import maybe_schedule, crontab -from .utils.imports import instantiate -from .utils.timeutils import humanize_seconds -from .utils.log import get_logger, iter_open_logger_fds - -__all__ = ['SchedulingError', 'ScheduleEntry', 'Scheduler', - 'PersistentScheduler', 'Service', 'EmbeddedService'] - -logger = get_logger(__name__) -debug, info, error, warning = (logger.debug, logger.info, - logger.error, logger.warning) - -DEFAULT_MAX_INTERVAL = 300 # 5 minutes - - -class SchedulingError(Exception): - """An error occured while scheduling a task.""" - - -class ScheduleEntry(object): - """An entry in the scheduler. - - :keyword name: see :attr:`name`. - :keyword schedule: see :attr:`schedule`. - :keyword args: see :attr:`args`. - :keyword kwargs: see :attr:`kwargs`. - :keyword options: see :attr:`options`. - :keyword last_run_at: see :attr:`last_run_at`. - :keyword total_run_count: see :attr:`total_run_count`. - :keyword relative: Is the time relative to when the server starts? - - """ - - #: The task name - name = None - - #: The schedule (run_every/crontab) - schedule = None - - #: Positional arguments to apply. - args = None - - #: Keyword arguments to apply. - kwargs = None - - #: Task execution options. - options = None - - #: The time and date of when this task was last scheduled. - last_run_at = None - - #: Total number of times this task has been scheduled. - total_run_count = 0 - - def __init__(self, name=None, task=None, last_run_at=None, - total_run_count=None, schedule=None, args=(), kwargs={}, - options={}, relative=False, app=None): - self.app = app - self.name = name - self.task = task - self.args = args - self.kwargs = kwargs - self.options = options - self.schedule = maybe_schedule(schedule, relative, app=self.app) - self.last_run_at = last_run_at or self._default_now() - self.total_run_count = total_run_count or 0 - - def _default_now(self): - return self.schedule.now() if self.schedule else self.app.now() - - def _next_instance(self, last_run_at=None): - """Return a new instance of the same class, but with - its date and count fields updated.""" - return self.__class__(**dict( - self, - last_run_at=last_run_at or self._default_now(), - total_run_count=self.total_run_count + 1, - )) - __next__ = next = _next_instance # for 2to3 - - def __reduce__(self): - return self.__class__, ( - self.name, self.task, self.last_run_at, self.total_run_count, - self.schedule, self.args, self.kwargs, self.options, - ) - - def update(self, other): - """Update values from another entry. - - Does only update "editable" fields (task, schedule, args, kwargs, - options). - - """ - self.__dict__.update({'task': other.task, 'schedule': other.schedule, - 'args': other.args, 'kwargs': other.kwargs, - 'options': other.options}) - - def is_due(self): - """See :meth:`~celery.schedule.schedule.is_due`.""" - return self.schedule.is_due(self.last_run_at) - - def __iter__(self): - return iter(items(vars(self))) - - def __repr__(self): - return '<Entry: {0.name} {call} {0.schedule}'.format( - self, - call=reprcall(self.task, self.args or (), self.kwargs or {}), - ) - - -class Scheduler(object): - """Scheduler for periodic tasks. - - The :program:`celery beat` program may instantiate this class - multiple times for introspection purposes, but then with the - ``lazy`` argument set. It is important for subclasses to - be idempotent when this argument is set. - - :keyword schedule: see :attr:`schedule`. - :keyword max_interval: see :attr:`max_interval`. - :keyword lazy: Do not set up the schedule. - - """ - Entry = ScheduleEntry - - #: The schedule dict/shelve. - schedule = None - - #: Maximum time to sleep between re-checking the schedule. - max_interval = DEFAULT_MAX_INTERVAL - - #: How often to sync the schedule (3 minutes by default) - sync_every = 3 * 60 - - #: How many tasks can be called before a sync is forced. - sync_every_tasks = None - - _last_sync = None - _tasks_since_sync = 0 - - logger = logger # compat - - def __init__(self, app, schedule=None, max_interval=None, - Publisher=None, lazy=False, sync_every_tasks=None, **kwargs): - self.app = app - self.data = maybe_evaluate({} if schedule is None else schedule) - self.max_interval = (max_interval - or app.conf.CELERYBEAT_MAX_LOOP_INTERVAL - or self.max_interval) - self.sync_every_tasks = ( - app.conf.CELERYBEAT_SYNC_EVERY if sync_every_tasks is None - else sync_every_tasks) - self.Publisher = Publisher or app.amqp.TaskProducer - if not lazy: - self.setup_schedule() - - def install_default_entries(self, data): - entries = {} - if self.app.conf.CELERY_TASK_RESULT_EXPIRES and \ - not self.app.backend.supports_autoexpire: - if 'celery.backend_cleanup' not in data: - entries['celery.backend_cleanup'] = { - 'task': 'celery.backend_cleanup', - 'schedule': crontab('0', '4', '*'), - 'options': {'expires': 12 * 3600}} - self.update_from_dict(entries) - - def maybe_due(self, entry, publisher=None): - is_due, next_time_to_run = entry.is_due() - - if is_due: - info('Scheduler: Sending due task %s (%s)', entry.name, entry.task) - try: - result = self.apply_async(entry, publisher=publisher) - except Exception as exc: - error('Message Error: %s\n%s', - exc, traceback.format_stack(), exc_info=True) - else: - debug('%s sent. id->%s', entry.task, result.id) - return next_time_to_run - - def tick(self): - """Run a tick, that is one iteration of the scheduler. - - Executes all due tasks. - - """ - remaining_times = [] - try: - for entry in values(self.schedule): - next_time_to_run = self.maybe_due(entry, self.publisher) - if next_time_to_run: - remaining_times.append(next_time_to_run) - except RuntimeError: - pass - - return min(remaining_times + [self.max_interval]) - - def should_sync(self): - return ( - (not self._last_sync or - (monotonic() - self._last_sync) > self.sync_every) or - (self.sync_every_tasks and - self._tasks_since_sync >= self.sync_every_tasks) - ) - - def reserve(self, entry): - new_entry = self.schedule[entry.name] = next(entry) - return new_entry - - def apply_async(self, entry, publisher=None, **kwargs): - # Update timestamps and run counts before we actually execute, - # so we have that done if an exception is raised (doesn't schedule - # forever.) - entry = self.reserve(entry) - task = self.app.tasks.get(entry.task) - - try: - if task: - result = task.apply_async(entry.args, entry.kwargs, - publisher=publisher, - **entry.options) - else: - result = self.send_task(entry.task, entry.args, entry.kwargs, - publisher=publisher, - **entry.options) - except Exception as exc: - reraise(SchedulingError, SchedulingError( - "Couldn't apply scheduled task {0.name}: {exc}".format( - entry, exc=exc)), sys.exc_info()[2]) - finally: - self._tasks_since_sync += 1 - if self.should_sync(): - self._do_sync() - return result - - def send_task(self, *args, **kwargs): - return self.app.send_task(*args, **kwargs) - - def setup_schedule(self): - self.install_default_entries(self.data) - - def _do_sync(self): - try: - debug('beat: Synchronizing schedule...') - self.sync() - finally: - self._last_sync = monotonic() - self._tasks_since_sync = 0 - - def sync(self): - pass - - def close(self): - self.sync() - - def add(self, **kwargs): - entry = self.Entry(app=self.app, **kwargs) - self.schedule[entry.name] = entry - return entry - - def _maybe_entry(self, name, entry): - if isinstance(entry, self.Entry): - entry.app = self.app - return entry - return self.Entry(**dict(entry, name=name, app=self.app)) - - def update_from_dict(self, dict_): - self.schedule.update(dict( - (name, self._maybe_entry(name, entry)) - for name, entry in items(dict_))) - - def merge_inplace(self, b): - schedule = self.schedule - A, B = set(schedule), set(b) - - # Remove items from disk not in the schedule anymore. - for key in A ^ B: - schedule.pop(key, None) - - # Update and add new items in the schedule - for key in B: - entry = self.Entry(**dict(b[key], name=key, app=self.app)) - if schedule.get(key): - schedule[key].update(entry) - else: - schedule[key] = entry - - def _ensure_connected(self): - # callback called for each retry while the connection - # can't be established. - def _error_handler(exc, interval): - error('beat: Connection error: %s. ' - 'Trying again in %s seconds...', exc, interval) - - return self.connection.ensure_connection( - _error_handler, self.app.conf.BROKER_CONNECTION_MAX_RETRIES - ) - - def get_schedule(self): - return self.data - - def set_schedule(self, schedule): - self.data = schedule - schedule = property(get_schedule, set_schedule) - - @cached_property - def connection(self): - return self.app.connection() - - @cached_property - def publisher(self): - return self.Publisher(self._ensure_connected()) - - @property - def info(self): - return '' - - -class PersistentScheduler(Scheduler): - persistence = shelve - known_suffixes = ('', '.db', '.dat', '.bak', '.dir') - - _store = None - - def __init__(self, *args, **kwargs): - self.schedule_filename = kwargs.get('schedule_filename') - Scheduler.__init__(self, *args, **kwargs) - - def _remove_db(self): - for suffix in self.known_suffixes: - with platforms.ignore_errno(errno.ENOENT): - os.remove(self.schedule_filename + suffix) - - def setup_schedule(self): - try: - self._store = self.persistence.open(self.schedule_filename, - writeback=True) - except Exception as exc: - error('Removing corrupted schedule file %r: %r', - self.schedule_filename, exc, exc_info=True) - self._remove_db() - self._store = self.persistence.open(self.schedule_filename, - writeback=True) - else: - try: - self._store['entries'] - except KeyError: - # new schedule db - self._store['entries'] = {} - else: - if '__version__' not in self._store: - warning('DB Reset: Account for new __version__ field') - self._store.clear() # remove schedule at 2.2.2 upgrade. - elif 'tz' not in self._store: - warning('DB Reset: Account for new tz field') - self._store.clear() # remove schedule at 3.0.8 upgrade - elif 'utc_enabled' not in self._store: - warning('DB Reset: Account for new utc_enabled field') - self._store.clear() # remove schedule at 3.0.9 upgrade - - tz = self.app.conf.CELERY_TIMEZONE - stored_tz = self._store.get('tz') - if stored_tz is not None and stored_tz != tz: - warning('Reset: Timezone changed from %r to %r', stored_tz, tz) - self._store.clear() # Timezone changed, reset db! - utc = self.app.conf.CELERY_ENABLE_UTC - stored_utc = self._store.get('utc_enabled') - if stored_utc is not None and stored_utc != utc: - choices = {True: 'enabled', False: 'disabled'} - warning('Reset: UTC changed from %s to %s', - choices[stored_utc], choices[utc]) - self._store.clear() # UTC setting changed, reset db! - entries = self._store.setdefault('entries', {}) - self.merge_inplace(self.app.conf.CELERYBEAT_SCHEDULE) - self.install_default_entries(self.schedule) - self._store.update(__version__=__version__, tz=tz, utc_enabled=utc) - self.sync() - debug('Current schedule:\n' + '\n'.join( - repr(entry) for entry in values(entries))) - - def get_schedule(self): - return self._store['entries'] - - def set_schedule(self, schedule): - self._store['entries'] = schedule - schedule = property(get_schedule, set_schedule) - - def sync(self): - if self._store is not None: - self._store.sync() - - def close(self): - self.sync() - self._store.close() - - @property - def info(self): - return ' . db -> {self.schedule_filename}'.format(self=self) - - -class Service(object): - scheduler_cls = PersistentScheduler - - def __init__(self, app, max_interval=None, schedule_filename=None, - scheduler_cls=None): - self.app = app - self.max_interval = (max_interval - or app.conf.CELERYBEAT_MAX_LOOP_INTERVAL) - self.scheduler_cls = scheduler_cls or self.scheduler_cls - self.schedule_filename = ( - schedule_filename or app.conf.CELERYBEAT_SCHEDULE_FILENAME) - - self._is_shutdown = Event() - self._is_stopped = Event() - - def __reduce__(self): - return self.__class__, (self.max_interval, self.schedule_filename, - self.scheduler_cls, self.app) - - def start(self, embedded_process=False): - info('beat: Starting...') - debug('beat: Ticking with max interval->%s', - humanize_seconds(self.scheduler.max_interval)) - - signals.beat_init.send(sender=self) - if embedded_process: - signals.beat_embedded_init.send(sender=self) - platforms.set_process_title('celery beat') - - try: - while not self._is_shutdown.is_set(): - interval = self.scheduler.tick() - debug('beat: Waking up %s.', - humanize_seconds(interval, prefix='in ')) - time.sleep(interval) - except (KeyboardInterrupt, SystemExit): - self._is_shutdown.set() - finally: - self.sync() - - def sync(self): - self.scheduler.close() - self._is_stopped.set() - - def stop(self, wait=False): - info('beat: Shutting down...') - self._is_shutdown.set() - wait and self._is_stopped.wait() # block until shutdown done. - - def get_scheduler(self, lazy=False): - filename = self.schedule_filename - scheduler = instantiate(self.scheduler_cls, - app=self.app, - schedule_filename=filename, - max_interval=self.max_interval, - lazy=lazy) - return scheduler - - @cached_property - def scheduler(self): - return self.get_scheduler() - - -class _Threaded(Thread): - """Embedded task scheduler using threading.""" - - def __init__(self, *args, **kwargs): - super(_Threaded, self).__init__() - self.service = Service(*args, **kwargs) - self.daemon = True - self.name = 'Beat' - - def run(self): - self.service.start() - - def stop(self): - self.service.stop(wait=True) - - -try: - ensure_multiprocessing() -except NotImplementedError: # pragma: no cover - _Process = None -else: - class _Process(Process): # noqa - - def __init__(self, *args, **kwargs): - super(_Process, self).__init__() - self.service = Service(*args, **kwargs) - self.name = 'Beat' - - def run(self): - reset_signals(full=False) - platforms.close_open_fds([ - sys.__stdin__, sys.__stdout__, sys.__stderr__, - ] + list(iter_open_logger_fds())) - self.service.start(embedded_process=True) - - def stop(self): - self.service.stop() - self.terminate() - - -def EmbeddedService(*args, **kwargs): - """Return embedded clock service. - - :keyword thread: Run threaded instead of as a separate process. - Uses :mod:`multiprocessing` by default, if available. - - """ - if kwargs.pop('thread', False) or _Process is None: - # Need short max interval to be able to stop thread - # in reasonable time. - kwargs.setdefault('max_interval', 1) - return _Threaded(*args, **kwargs) - return _Process(*args, **kwargs) diff --git a/awx/lib/site-packages/celery/bin/__init__.py b/awx/lib/site-packages/celery/bin/__init__.py deleted file mode 100644 index 3f44b50240..0000000000 --- a/awx/lib/site-packages/celery/bin/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import absolute_import - -from .base import Option - -__all__ = ['Option'] diff --git a/awx/lib/site-packages/celery/bin/amqp.py b/awx/lib/site-packages/celery/bin/amqp.py deleted file mode 100644 index 4dab1527a4..0000000000 --- a/awx/lib/site-packages/celery/bin/amqp.py +++ /dev/null @@ -1,369 +0,0 @@ -# -*- coding: utf-8 -*- -""" -The :program:`celery amqp` command. - -.. program:: celery amqp - -""" -from __future__ import absolute_import, print_function, unicode_literals - -import cmd -import sys -import shlex -import pprint - -from functools import partial -from itertools import count - -from kombu.utils.encoding import safe_str - -from celery.utils.functional import padlist - -from celery.bin.base import Command -from celery.five import string_t -from celery.utils import strtobool - -__all__ = ['AMQPAdmin', 'AMQShell', 'Spec', 'amqp'] - -# Map to coerce strings to other types. -COERCE = {bool: strtobool} - -HELP_HEADER = """ -Commands --------- -""".rstrip() - -EXAMPLE_TEXT = """ -Example: - -> queue.delete myqueue yes no -""" - -say = partial(print, file=sys.stderr) - - -class Spec(object): - """AMQP Command specification. - - Used to convert arguments to Python values and display various help - and tooltips. - - :param args: see :attr:`args`. - :keyword returns: see :attr:`returns`. - - .. attribute args:: - - List of arguments this command takes. Should - contain `(argument_name, argument_type)` tuples. - - .. attribute returns: - - Helpful human string representation of what this command returns. - May be :const:`None`, to signify the return type is unknown. - - """ - def __init__(self, *args, **kwargs): - self.args = args - self.returns = kwargs.get('returns') - - def coerce(self, index, value): - """Coerce value for argument at index.""" - arg_info = self.args[index] - arg_type = arg_info[1] - # Might be a custom way to coerce the string value, - # so look in the coercion map. - return COERCE.get(arg_type, arg_type)(value) - - def str_args_to_python(self, arglist): - """Process list of string arguments to values according to spec. - - e.g: - - >>> spec = Spec([('queue', str), ('if_unused', bool)]) - >>> spec.str_args_to_python('pobox', 'true') - ('pobox', True) - - """ - return tuple( - self.coerce(index, value) for index, value in enumerate(arglist)) - - def format_response(self, response): - """Format the return value of this command in a human-friendly way.""" - if not self.returns: - return 'ok.' if response is None else response - if callable(self.returns): - return self.returns(response) - return self.returns.format(response) - - def format_arg(self, name, type, default_value=None): - if default_value is not None: - return '{0}:{1}'.format(name, default_value) - return name - - def format_signature(self): - return ' '.join(self.format_arg(*padlist(list(arg), 3)) - for arg in self.args) - - -def dump_message(message): - if message is None: - return 'No messages in queue. basic.publish something.' - return {'body': message.body, - 'properties': message.properties, - 'delivery_info': message.delivery_info} - - -def format_declare_queue(ret): - return 'ok. queue:{0} messages:{1} consumers:{2}.'.format(*ret) - - -class AMQShell(cmd.Cmd): - """AMQP API Shell. - - :keyword connect: Function used to connect to the server, must return - connection object. - - :keyword silent: If :const:`True`, the commands won't have annoying - output not relevant when running in non-shell mode. - - - .. attribute: builtins - - Mapping of built-in command names -> method names - - .. attribute:: amqp - - Mapping of AMQP API commands and their :class:`Spec`. - - """ - conn = None - chan = None - prompt_fmt = '{self.counter}> ' - identchars = cmd.IDENTCHARS = '.' - needs_reconnect = False - counter = 1 - inc_counter = count(2) - - builtins = {'EOF': 'do_exit', - 'exit': 'do_exit', - 'help': 'do_help'} - - amqp = { - 'exchange.declare': Spec(('exchange', str), - ('type', str), - ('passive', bool, 'no'), - ('durable', bool, 'no'), - ('auto_delete', bool, 'no'), - ('internal', bool, 'no')), - 'exchange.delete': Spec(('exchange', str), - ('if_unused', bool)), - 'queue.bind': Spec(('queue', str), - ('exchange', str), - ('routing_key', str)), - 'queue.declare': Spec(('queue', str), - ('passive', bool, 'no'), - ('durable', bool, 'no'), - ('exclusive', bool, 'no'), - ('auto_delete', bool, 'no'), - returns=format_declare_queue), - 'queue.delete': Spec(('queue', str), - ('if_unused', bool, 'no'), - ('if_empty', bool, 'no'), - returns='ok. {0} messages deleted.'), - 'queue.purge': Spec(('queue', str), - returns='ok. {0} messages deleted.'), - 'basic.get': Spec(('queue', str), - ('no_ack', bool, 'off'), - returns=dump_message), - 'basic.publish': Spec(('msg', str), - ('exchange', str), - ('routing_key', str), - ('mandatory', bool, 'no'), - ('immediate', bool, 'no')), - 'basic.ack': Spec(('delivery_tag', int)), - } - - def __init__(self, *args, **kwargs): - self.connect = kwargs.pop('connect') - self.silent = kwargs.pop('silent', False) - self.out = kwargs.pop('out', sys.stderr) - cmd.Cmd.__init__(self, *args, **kwargs) - self._reconnect() - - def note(self, m): - """Say something to the user. Disabled if :attr:`silent`.""" - if not self.silent: - say(m, file=self.out) - - def say(self, m): - say(m, file=self.out) - - def get_amqp_api_command(self, cmd, arglist): - """With a command name and a list of arguments, convert the arguments - to Python values and find the corresponding method on the AMQP channel - object. - - :returns: tuple of `(method, processed_args)`. - - """ - spec = self.amqp[cmd] - args = spec.str_args_to_python(arglist) - attr_name = cmd.replace('.', '_') - if self.needs_reconnect: - self._reconnect() - return getattr(self.chan, attr_name), args, spec.format_response - - def do_exit(self, *args): - """The `'exit'` command.""" - self.note("\n-> please, don't leave!") - sys.exit(0) - - def display_command_help(self, cmd, short=False): - spec = self.amqp[cmd] - self.say('{0} {1}'.format(cmd, spec.format_signature())) - - def do_help(self, *args): - if not args: - self.say(HELP_HEADER) - for cmd_name in self.amqp: - self.display_command_help(cmd_name, short=True) - self.say(EXAMPLE_TEXT) - else: - self.display_command_help(args[0]) - - def default(self, line): - self.say("unknown syntax: {0!r}. how about some 'help'?".format(line)) - - def get_names(self): - return set(self.builtins) | set(self.amqp) - - def completenames(self, text, *ignored): - """Return all commands starting with `text`, for tab-completion.""" - names = self.get_names() - first = [cmd for cmd in names - if cmd.startswith(text.replace('_', '.'))] - if first: - return first - return [cmd for cmd in names - if cmd.partition('.')[2].startswith(text)] - - def dispatch(self, cmd, argline): - """Dispatch and execute the command. - - Lookup order is: :attr:`builtins` -> :attr:`amqp`. - - """ - arglist = shlex.split(safe_str(argline)) - if cmd in self.builtins: - return getattr(self, self.builtins[cmd])(*arglist) - fun, args, formatter = self.get_amqp_api_command(cmd, arglist) - return formatter(fun(*args)) - - def parseline(self, line): - """Parse input line. - - :returns: tuple of three items: - `(command_name, arglist, original_line)` - - """ - parts = line.split() - if parts: - return parts[0], ' '.join(parts[1:]), line - return '', '', line - - def onecmd(self, line): - """Parse line and execute command.""" - cmd, arg, line = self.parseline(line) - if not line: - return self.emptyline() - self.lastcmd = line - self.counter = next(self.inc_counter) - try: - self.respond(self.dispatch(cmd, arg)) - except (AttributeError, KeyError) as exc: - self.default(line) - except Exception as exc: - self.say(exc) - self.needs_reconnect = True - - def respond(self, retval): - """What to do with the return value of a command.""" - if retval is not None: - if isinstance(retval, string_t): - self.say(retval) - else: - self.say(pprint.pformat(retval)) - - def _reconnect(self): - """Re-establish connection to the AMQP server.""" - self.conn = self.connect(self.conn) - self.chan = self.conn.default_channel - self.needs_reconnect = False - - @property - def prompt(self): - return self.prompt_fmt.format(self=self) - - -class AMQPAdmin(object): - """The celery :program:`celery amqp` utility.""" - Shell = AMQShell - - def __init__(self, *args, **kwargs): - self.app = kwargs['app'] - self.out = kwargs.setdefault('out', sys.stderr) - self.silent = kwargs.get('silent') - self.args = args - - def connect(self, conn=None): - if conn: - conn.close() - conn = self.app.connection() - self.note('-> connecting to {0}.'.format(conn.as_uri())) - conn.connect() - self.note('-> connected.') - return conn - - def run(self): - shell = self.Shell(connect=self.connect, out=self.out) - if self.args: - return shell.onecmd(' '.join(self.args)) - try: - return shell.cmdloop() - except KeyboardInterrupt: - self.note('(bibi)') - pass - - def note(self, m): - if not self.silent: - say(m, file=self.out) - - -class amqp(Command): - """AMQP Administration Shell. - - Also works for non-amqp transports (but not ones that - store declarations in memory). - - Examples:: - - celery amqp - start shell mode - celery amqp help - show list of commands - - celery amqp exchange.delete name - celery amqp queue.delete queue - celery amqp queue.delete queue yes yes - - """ - - def run(self, *args, **options): - options['app'] = self.app - return AMQPAdmin(*args, **options).run() - - -def main(): - amqp().execute_from_commandline() - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/bin/base.py b/awx/lib/site-packages/celery/bin/base.py deleted file mode 100644 index 9ad7946659..0000000000 --- a/awx/lib/site-packages/celery/bin/base.py +++ /dev/null @@ -1,652 +0,0 @@ -# -*- coding: utf-8 -*- -""" - -.. _preload-options: - -Preload Options ---------------- - -These options are supported by all commands, -and usually parsed before command-specific arguments. - -.. cmdoption:: -A, --app - - app instance to use (e.g. module.attr_name) - -.. cmdoption:: -b, --broker - - url to broker. default is 'amqp://guest@localhost//' - -.. cmdoption:: --loader - - name of custom loader class to use. - -.. cmdoption:: --config - - Name of the configuration module - -.. _daemon-options: - -Daemon Options --------------- - -These options are supported by commands that can detach -into the background (daemon). They will be present -in any command that also has a `--detach` option. - -.. cmdoption:: -f, --logfile - - Path to log file. If no logfile is specified, `stderr` is used. - -.. cmdoption:: --pidfile - - Optional file used to store the process pid. - - The program will not start if this file already exists - and the pid is still alive. - -.. cmdoption:: --uid - - User id, or user name of the user to run as after detaching. - -.. cmdoption:: --gid - - Group id, or group name of the main group to change to after - detaching. - -.. cmdoption:: --umask - - Effective umask of the process after detaching. Default is 0. - -.. cmdoption:: --workdir - - Optional directory to change to after detaching. - -""" -from __future__ import absolute_import, print_function, unicode_literals - -import os -import random -import re -import sys -import warnings -import json - -from collections import defaultdict -from heapq import heappush -from inspect import getargspec -from optparse import OptionParser, IndentedHelpFormatter, make_option as Option -from pprint import pformat - -from celery import VERSION_BANNER, Celery, maybe_patch_concurrency -from celery import signals -from celery.exceptions import CDeprecationWarning, CPendingDeprecationWarning -from celery.five import items, string, string_t -from celery.platforms import EX_FAILURE, EX_OK, EX_USAGE -from celery.utils import term -from celery.utils import text -from celery.utils import node_format, host_format -from celery.utils.imports import symbol_by_name, import_from_cwd - -try: - input = raw_input -except NameError: - pass - -# always enable DeprecationWarnings, so our users can see them. -for warning in (CDeprecationWarning, CPendingDeprecationWarning): - warnings.simplefilter('once', warning, 0) - -ARGV_DISABLED = """ -Unrecognized command-line arguments: {0} - -Try --help? -""" - -find_long_opt = re.compile(r'.+?(--.+?)(?:\s|,|$)') -find_rst_ref = re.compile(r':\w+:`(.+?)`') - -__all__ = ['Error', 'UsageError', 'Extensions', 'HelpFormatter', - 'Command', 'Option', 'daemon_options'] - - -class Error(Exception): - status = EX_FAILURE - - def __init__(self, reason, status=None): - self.reason = reason - self.status = status if status is not None else self.status - super(Error, self).__init__(reason, status) - - def __str__(self): - return self.reason - __unicode__ = __str__ - - -class UsageError(Error): - status = EX_USAGE - - -class Extensions(object): - - def __init__(self, namespace, register): - self.names = [] - self.namespace = namespace - self.register = register - - def add(self, cls, name): - heappush(self.names, name) - self.register(cls, name=name) - - def load(self): - try: - from pkg_resources import iter_entry_points - except ImportError: # pragma: no cover - return - - for ep in iter_entry_points(self.namespace): - sym = ':'.join([ep.module_name, ep.attrs[0]]) - try: - cls = symbol_by_name(sym) - except (ImportError, SyntaxError) as exc: - warnings.warn( - 'Cannot load extension {0!r}: {1!r}'.format(sym, exc)) - else: - self.add(cls, ep.name) - return self.names - - -class HelpFormatter(IndentedHelpFormatter): - - def format_epilog(self, epilog): - if epilog: - return '\n{0}\n\n'.format(epilog) - return '' - - def format_description(self, description): - return text.ensure_2lines(text.fill_paragraphs( - text.dedent(description), self.width)) - - -class Command(object): - """Base class for command-line applications. - - :keyword app: The current app. - :keyword get_app: Callable returning the current app if no app provided. - - """ - Error = Error - UsageError = UsageError - Parser = OptionParser - - #: Arg list used in help. - args = '' - - #: Application version. - version = VERSION_BANNER - - #: If false the parser will raise an exception if positional - #: args are provided. - supports_args = True - - #: List of options (without preload options). - option_list = () - - # module Rst documentation to parse help from (if any) - doc = None - - # Some programs (multi) does not want to load the app specified - # (Issue #1008). - respects_app_option = True - - #: List of options to parse before parsing other options. - preload_options = ( - Option('-A', '--app', default=None), - Option('-b', '--broker', default=None), - Option('--loader', default=None), - Option('--config', default=None), - Option('--workdir', default=None, dest='working_directory'), - Option('--no-color', '-C', action='store_true', default=None), - Option('--quiet', '-q', action='store_true'), - ) - - #: Enable if the application should support config from the cmdline. - enable_config_from_cmdline = False - - #: Default configuration namespace. - namespace = 'celery' - - #: Text to print at end of --help - epilog = None - - #: Text to print in --help before option list. - description = '' - - #: Set to true if this command doesn't have subcommands - leaf = True - - # used by :meth:`say_remote_command_reply`. - show_body = True - # used by :meth:`say_chat`. - show_reply = True - - prog_name = 'celery' - - def __init__(self, app=None, get_app=None, no_color=False, - stdout=None, stderr=None, quiet=False, on_error=None, - on_usage_error=None): - self.app = app - self.get_app = get_app or self._get_default_app - self.stdout = stdout or sys.stdout - self.stderr = stderr or sys.stderr - self._colored = None - self._no_color = no_color - self.quiet = quiet - if not self.description: - self.description = self.__doc__ - if on_error: - self.on_error = on_error - if on_usage_error: - self.on_usage_error = on_usage_error - - def run(self, *args, **options): - """This is the body of the command called by :meth:`handle_argv`.""" - raise NotImplementedError('subclass responsibility') - - def on_error(self, exc): - self.error(self.colored.red('Error: {0}'.format(exc))) - - def on_usage_error(self, exc): - self.handle_error(exc) - - def on_concurrency_setup(self): - pass - - def __call__(self, *args, **kwargs): - random.seed() # maybe we were forked. - self.verify_args(args) - try: - ret = self.run(*args, **kwargs) - return ret if ret is not None else EX_OK - except self.UsageError as exc: - self.on_usage_error(exc) - return exc.status - except self.Error as exc: - self.on_error(exc) - return exc.status - - def verify_args(self, given, _index=0): - S = getargspec(self.run) - _index = 1 if S.args and S.args[0] == 'self' else _index - required = S.args[_index:-len(S.defaults) if S.defaults else None] - missing = required[len(given):] - if missing: - raise self.UsageError('Missing required {0}: {1}'.format( - text.pluralize(len(missing), 'argument'), - ', '.join(missing) - )) - - def execute_from_commandline(self, argv=None): - """Execute application from command-line. - - :keyword argv: The list of command-line arguments. - Defaults to ``sys.argv``. - - """ - if argv is None: - argv = list(sys.argv) - # Should we load any special concurrency environment? - self.maybe_patch_concurrency(argv) - self.on_concurrency_setup() - - # Dump version and exit if '--version' arg set. - self.early_version(argv) - argv = self.setup_app_from_commandline(argv) - self.prog_name = os.path.basename(argv[0]) - return self.handle_argv(self.prog_name, argv[1:]) - - def run_from_argv(self, prog_name, argv=None, command=None): - return self.handle_argv(prog_name, - sys.argv if argv is None else argv, command) - - def maybe_patch_concurrency(self, argv=None): - argv = argv or sys.argv - pool_option = self.with_pool_option(argv) - if pool_option: - maybe_patch_concurrency(argv, *pool_option) - short_opts, long_opts = pool_option - - def usage(self, command): - return '%prog {0} [options] {self.args}'.format(command, self=self) - - def get_options(self): - """Get supported command-line options.""" - return self.option_list - - def expanduser(self, value): - if isinstance(value, string_t): - return os.path.expanduser(value) - return value - - def ask(self, q, choices, default=None): - """Prompt user to choose from a tuple of string values. - - :param q: the question to ask (do not include questionark) - :param choice: tuple of possible choices, must be lowercase. - :param default: Default value if any. - - If a default is not specified the question will be repeated - until the user gives a valid choice. - - Matching is done case insensitively. - - """ - schoices = choices - if default is not None: - schoices = [c.upper() if c == default else c.lower() - for c in choices] - schoices = '/'.join(schoices) - - p = '{0} ({1})? '.format(q.capitalize(), schoices) - while 1: - val = input(p).lower() - if val in choices: - return val - elif default is not None: - break - return default - - def handle_argv(self, prog_name, argv, command=None): - """Parse command-line arguments from ``argv`` and dispatch - to :meth:`run`. - - :param prog_name: The program name (``argv[0]``). - :param argv: Command arguments. - - Exits with an error message if :attr:`supports_args` is disabled - and ``argv`` contains positional arguments. - - """ - options, args = self.prepare_args( - *self.parse_options(prog_name, argv, command)) - return self(*args, **options) - - def prepare_args(self, options, args): - if options: - options = dict((k, self.expanduser(v)) - for k, v in items(vars(options)) - if not k.startswith('_')) - args = [self.expanduser(arg) for arg in args] - self.check_args(args) - return options, args - - def check_args(self, args): - if not self.supports_args and args: - self.die(ARGV_DISABLED.format(', '.join(args)), EX_USAGE) - - def error(self, s): - self.out(s, fh=self.stderr) - - def out(self, s, fh=None): - print(s, file=fh or self.stdout) - - def die(self, msg, status=EX_FAILURE): - self.error(msg) - sys.exit(status) - - def early_version(self, argv): - if '--version' in argv: - print(self.version, file=self.stdout) - sys.exit(0) - - def parse_options(self, prog_name, arguments, command=None): - """Parse the available options.""" - # Don't want to load configuration to just print the version, - # so we handle --version manually here. - self.parser = self.create_parser(prog_name, command) - return self.parser.parse_args(arguments) - - def create_parser(self, prog_name, command=None): - option_list = ( - self.preload_options + - self.get_options() + - tuple(self.app.user_options['preload']) - ) - return self.prepare_parser(self.Parser( - prog=prog_name, - usage=self.usage(command), - version=self.version, - epilog=self.epilog, - formatter=HelpFormatter(), - description=self.description, - option_list=option_list, - )) - - def prepare_parser(self, parser): - docs = [self.parse_doc(doc) for doc in (self.doc, __doc__) if doc] - for doc in docs: - for long_opt, help in items(doc): - option = parser.get_option(long_opt) - if option is not None: - option.help = ' '.join(help).format(default=option.default) - return parser - - def setup_app_from_commandline(self, argv): - preload_options = self.parse_preload_options(argv) - quiet = preload_options.get('quiet') - if quiet is not None: - self.quiet = quiet - try: - self.no_color = preload_options['no_color'] - except KeyError: - pass - workdir = preload_options.get('working_directory') - if workdir: - os.chdir(workdir) - app = (preload_options.get('app') or - os.environ.get('CELERY_APP') or - self.app) - preload_loader = preload_options.get('loader') - if preload_loader: - # Default app takes loader from this env (Issue #1066). - os.environ['CELERY_LOADER'] = preload_loader - loader = (preload_loader, - os.environ.get('CELERY_LOADER') or - 'default') - broker = preload_options.get('broker', None) - if broker: - os.environ['CELERY_BROKER_URL'] = broker - config = preload_options.get('config') - if config: - os.environ['CELERY_CONFIG_MODULE'] = config - if self.respects_app_option: - if app: - self.app = self.find_app(app) - elif self.app is None: - self.app = self.get_app(loader=loader) - if self.enable_config_from_cmdline: - argv = self.process_cmdline_config(argv) - else: - self.app = Celery(fixups=[]) - - user_preload = tuple(self.app.user_options['preload'] or ()) - if user_preload: - user_options = self.preparse_options(argv, user_preload) - for user_option in user_preload: - user_options.setdefault(user_option.dest, user_option.default) - signals.user_preload_options.send( - sender=self, app=self.app, options=user_options, - ) - return argv - - def find_app(self, app): - from celery.app.utils import find_app - return find_app(app, symbol_by_name=self.symbol_by_name) - - def symbol_by_name(self, name, imp=import_from_cwd): - return symbol_by_name(name, imp=imp) - get_cls_by_name = symbol_by_name # XXX compat - - def process_cmdline_config(self, argv): - try: - cargs_start = argv.index('--') - except ValueError: - return argv - argv, cargs = argv[:cargs_start], argv[cargs_start + 1:] - self.app.config_from_cmdline(cargs, namespace=self.namespace) - return argv - - def parse_preload_options(self, args): - return self.preparse_options(args, self.preload_options) - - def preparse_options(self, args, options): - acc = {} - opts = {} - for opt in options: - for t in (opt._long_opts, opt._short_opts): - opts.update(dict(zip(t, [opt] * len(t)))) - index = 0 - length = len(args) - while index < length: - arg = args[index] - if arg.startswith('--'): - if '=' in arg: - key, value = arg.split('=', 1) - opt = opts.get(key) - if opt: - acc[opt.dest] = value - else: - opt = opts.get(arg) - if opt and opt.takes_value(): - # optparse also supports ['--opt', 'value'] - # (Issue #1668) - acc[opt.dest] = args[index + 1] - index += 1 - elif opt and opt.action == 'store_true': - acc[opt.dest] = True - elif arg.startswith('-'): - opt = opts.get(arg) - if opt: - if opt.takes_value(): - try: - acc[opt.dest] = args[index + 1] - except IndexError: - raise ValueError( - 'Missing required argument for {0}'.format( - arg)) - index += 1 - elif opt.action == 'store_true': - acc[opt.dest] = True - index += 1 - return acc - - def parse_doc(self, doc): - options, in_option = defaultdict(list), None - for line in doc.splitlines(): - if line.startswith('.. cmdoption::'): - m = find_long_opt.match(line) - if m: - in_option = m.groups()[0].strip() - assert in_option, 'missing long opt' - elif in_option and line.startswith(' ' * 4): - options[in_option].append( - find_rst_ref.sub(r'\1', line.strip()).replace('`', '')) - return options - - def with_pool_option(self, argv): - """Return tuple of ``(short_opts, long_opts)`` if the command - supports a pool argument, and used to monkey patch eventlet/gevent - environments as early as possible. - - E.g:: - has_pool_option = (['-P'], ['--pool']) - """ - pass - - def node_format(self, s, nodename, **extra): - return node_format(s, nodename, **extra) - - def host_format(self, s, **extra): - return host_format(s, **extra) - - def _get_default_app(self, *args, **kwargs): - from celery._state import get_current_app - return get_current_app() # omit proxy - - def pretty_list(self, n): - c = self.colored - if not n: - return '- empty -' - return '\n'.join( - str(c.reset(c.white('*'), ' {0}'.format(item))) for item in n - ) - - def pretty_dict_ok_error(self, n): - c = self.colored - try: - return (c.green('OK'), - text.indent(self.pretty(n['ok'])[1], 4)) - except KeyError: - pass - return (c.red('ERROR'), - text.indent(self.pretty(n['error'])[1], 4)) - - def say_remote_command_reply(self, replies): - c = self.colored - node = next(iter(replies)) # <-- take first. - reply = replies[node] - status, preply = self.pretty(reply) - self.say_chat('->', c.cyan(node, ': ') + status, - text.indent(preply, 4) if self.show_reply else '') - - def pretty(self, n): - OK = str(self.colored.green('OK')) - if isinstance(n, list): - return OK, self.pretty_list(n) - if isinstance(n, dict): - if 'ok' in n or 'error' in n: - return self.pretty_dict_ok_error(n) - else: - return OK, json.dumps(n, sort_keys=True, indent=4) - if isinstance(n, string_t): - return OK, string(n) - return OK, pformat(n) - - def say_chat(self, direction, title, body=''): - c = self.colored - if direction == '<-' and self.quiet: - return - dirstr = not self.quiet and c.bold(c.white(direction), ' ') or '' - self.out(c.reset(dirstr, title)) - if body and self.show_body: - self.out(body) - - @property - def colored(self): - if self._colored is None: - self._colored = term.colored(enabled=not self.no_color) - return self._colored - - @colored.setter - def colored(self, obj): - self._colored = obj - - @property - def no_color(self): - return self._no_color - - @no_color.setter - def no_color(self, value): - self._no_color = value - if self._colored is not None: - self._colored.enabled = not self._no_color - - -def daemon_options(default_pidfile=None, default_logfile=None): - return ( - Option('-f', '--logfile', default=default_logfile), - Option('--pidfile', default=default_pidfile), - Option('--uid', default=None), - Option('--gid', default=None), - Option('--umask', default=0, type='int'), - ) diff --git a/awx/lib/site-packages/celery/bin/beat.py b/awx/lib/site-packages/celery/bin/beat.py deleted file mode 100644 index 6b5b734682..0000000000 --- a/awx/lib/site-packages/celery/bin/beat.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- coding: utf-8 -*- -""" - -The :program:`celery beat` command. - -.. program:: celery beat - -.. seealso:: - - See :ref:`preload-options` and :ref:`daemon-options`. - -.. cmdoption:: --detach - - Detach and run in the background as a daemon. - -.. cmdoption:: -s, --schedule - - Path to the schedule database. Defaults to `celerybeat-schedule`. - The extension '.db' may be appended to the filename. - Default is {default}. - -.. cmdoption:: -S, --scheduler - - Scheduler class to use. - Default is :class:`celery.beat.PersistentScheduler`. - -.. cmdoption:: --max-interval - - Max seconds to sleep between schedule iterations. - -.. cmdoption:: -f, --logfile - - Path to log file. If no logfile is specified, `stderr` is used. - -.. cmdoption:: -l, --loglevel - - Logging level, choose between `DEBUG`, `INFO`, `WARNING`, - `ERROR`, `CRITICAL`, or `FATAL`. - -""" -from __future__ import absolute_import - -from functools import partial - -from celery.platforms import detached, maybe_drop_privileges - -from celery.bin.base import Command, Option, daemon_options - -__all__ = ['beat'] - - -class beat(Command): - """Start the beat periodic task scheduler. - - Examples:: - - celery beat -l info - celery beat -s /var/run/celery/beat-schedule --detach - celery beat -S djcelery.schedulers.DatabaseScheduler - - """ - doc = __doc__ - enable_config_from_cmdline = True - supports_args = False - - def run(self, detach=False, logfile=None, pidfile=None, uid=None, - gid=None, umask=None, working_directory=None, **kwargs): - if not detach: - maybe_drop_privileges(uid=uid, gid=gid) - workdir = working_directory - kwargs.pop('app', None) - beat = partial(self.app.Beat, - logfile=logfile, pidfile=pidfile, **kwargs) - - if detach: - with detached(logfile, pidfile, uid, gid, umask, workdir): - return beat().run() - else: - return beat().run() - - def get_options(self): - c = self.app.conf - - return ( - (Option('--detach', action='store_true'), - Option('-s', '--schedule', - default=c.CELERYBEAT_SCHEDULE_FILENAME), - Option('--max-interval', type='float'), - Option('-S', '--scheduler', dest='scheduler_cls'), - Option('-l', '--loglevel', default=c.CELERYBEAT_LOG_LEVEL)) - + daemon_options(default_pidfile='celerybeat.pid') - + tuple(self.app.user_options['beat']) - ) - - -def main(app=None): - beat(app=app).execute_from_commandline() - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/bin/celery.py b/awx/lib/site-packages/celery/bin/celery.py deleted file mode 100644 index 10d7c03243..0000000000 --- a/awx/lib/site-packages/celery/bin/celery.py +++ /dev/null @@ -1,826 +0,0 @@ -# -*- coding: utf-8 -*- -""" - -The :program:`celery` umbrella command. - -.. program:: celery - -""" -from __future__ import absolute_import, unicode_literals - -import anyjson -import numbers -import os -import sys - -from functools import partial -from importlib import import_module - -from celery.five import string_t, values -from celery.platforms import EX_OK, EX_FAILURE, EX_UNAVAILABLE, EX_USAGE -from celery.utils import term -from celery.utils import text -from celery.utils.timeutils import maybe_iso8601 - -# Cannot use relative imports here due to a Windows issue (#1111). -from celery.bin.base import Command, Option, Extensions - -# Import commands from other modules -from celery.bin.amqp import amqp -from celery.bin.beat import beat -from celery.bin.events import events -from celery.bin.graph import graph -from celery.bin.worker import worker - -__all__ = ['CeleryCommand', 'main'] - -HELP = """ ----- -- - - ---- Commands- -------------- --- ------------ - -{commands} ----- -- - - --------- -- - -------------- --- ------------ - -Type '{prog_name} <command> --help' for help using a specific command. -""" - -MIGRATE_PROGRESS_FMT = """\ -Migrating task {state.count}/{state.strtotal}: \ -{body[task]}[{body[id]}]\ -""" - -DEBUG = os.environ.get('C_DEBUG', False) - -command_classes = [ - ('Main', ['worker', 'events', 'beat', 'shell', 'multi', 'amqp'], 'green'), - ('Remote Control', ['status', 'inspect', 'control'], 'blue'), - ('Utils', ['purge', 'list', 'migrate', 'call', 'result', 'report'], None), -] -if DEBUG: # pragma: no cover - command_classes.append( - ('Debug', ['graph'], 'red'), - ) - - -def determine_exit_status(ret): - if isinstance(ret, numbers.Integral): - return ret - return EX_OK if ret else EX_FAILURE - - -def main(argv=None): - # Fix for setuptools generated scripts, so that it will - # work with multiprocessing fork emulation. - # (see multiprocessing.forking.get_preparation_data()) - try: - if __name__ != '__main__': # pragma: no cover - sys.modules['__main__'] = sys.modules[__name__] - cmd = CeleryCommand() - cmd.maybe_patch_concurrency() - from billiard import freeze_support - freeze_support() - cmd.execute_from_commandline(argv) - except KeyboardInterrupt: - pass - - -class multi(Command): - """Start multiple worker instances.""" - respects_app_option = False - - def get_options(self): - return () - - def run_from_argv(self, prog_name, argv, command=None): - from celery.bin.multi import MultiTool - multi = MultiTool(quiet=self.quiet, no_color=self.no_color) - return multi.execute_from_commandline( - [command] + argv, prog_name, - ) - - -class list_(Command): - """Get info from broker. - - Examples:: - - celery list bindings - - NOTE: For RabbitMQ the management plugin is required. - """ - args = '[bindings]' - - def list_bindings(self, management): - try: - bindings = management.get_bindings() - except NotImplementedError: - raise self.Error('Your transport cannot list bindings.') - - fmt = lambda q, e, r: self.out('{0:<28} {1:<28} {2}'.format(q, e, r)) - fmt('Queue', 'Exchange', 'Routing Key') - fmt('-' * 16, '-' * 16, '-' * 16) - for b in bindings: - fmt(b['destination'], b['source'], b['routing_key']) - - def run(self, what=None, *_, **kw): - topics = {'bindings': self.list_bindings} - available = ', '.join(topics) - if not what: - raise self.UsageError( - 'You must specify one of {0}'.format(available)) - if what not in topics: - raise self.UsageError( - 'unknown topic {0!r} (choose one of: {1})'.format( - what, available)) - with self.app.connection() as conn: - self.app.amqp.TaskConsumer(conn).declare() - topics[what](conn.manager) - - -class call(Command): - """Call a task by name. - - Examples:: - - celery call tasks.add --args='[2, 2]' - celery call tasks.add --args='[2, 2]' --countdown=10 - """ - args = '<task_name>' - option_list = Command.option_list + ( - Option('--args', '-a', help='positional arguments (json).'), - Option('--kwargs', '-k', help='keyword arguments (json).'), - Option('--eta', help='scheduled time (ISO-8601).'), - Option('--countdown', type='float', - help='eta in seconds from now (float/int).'), - Option('--expires', help='expiry time (ISO-8601/float/int).'), - Option('--serializer', default='json', help='defaults to json.'), - Option('--queue', help='custom queue name.'), - Option('--exchange', help='custom exchange name.'), - Option('--routing-key', help='custom routing key.'), - ) - - def run(self, name, *_, **kw): - # Positional args. - args = kw.get('args') or () - if isinstance(args, string_t): - args = anyjson.loads(args) - - # Keyword args. - kwargs = kw.get('kwargs') or {} - if isinstance(kwargs, string_t): - kwargs = anyjson.loads(kwargs) - - # Expires can be int/float. - expires = kw.get('expires') or None - try: - expires = float(expires) - except (TypeError, ValueError): - # or a string describing an ISO 8601 datetime. - try: - expires = maybe_iso8601(expires) - except (TypeError, ValueError): - raise - - res = self.app.send_task(name, args=args, kwargs=kwargs, - countdown=kw.get('countdown'), - serializer=kw.get('serializer'), - queue=kw.get('queue'), - exchange=kw.get('exchange'), - routing_key=kw.get('routing_key'), - eta=maybe_iso8601(kw.get('eta')), - expires=expires) - self.out(res.id) - - -class purge(Command): - """Erase all messages from all known task queues. - - WARNING: There is no undo operation for this command. - - """ - warn_prelude = ( - '{warning}: This will remove all tasks from {queues}: {names}.\n' - ' There is no undo for this operation!\n\n' - '(to skip this prompt use the -f option)\n' - ) - warn_prompt = 'Are you sure you want to delete all tasks' - fmt_purged = 'Purged {mnum} {messages} from {qnum} known task {queues}.' - fmt_empty = 'No messages purged from {qnum} {queues}' - option_list = Command.option_list + ( - Option('--force', '-f', action='store_true', - help='Do not prompt for verification'), - ) - - def run(self, force=False, **kwargs): - names = list(sorted(self.app.amqp.queues.keys())) - qnum = len(names) - if not force: - self.out(self.warn_prelude.format( - warning=self.colored.red('WARNING'), - queues=text.pluralize(qnum, 'queue'), names=', '.join(names), - )) - if self.ask(self.warn_prompt, ('yes', 'no'), 'no') != 'yes': - return - messages = self.app.control.purge() - fmt = self.fmt_purged if messages else self.fmt_empty - self.out(fmt.format( - mnum=messages, qnum=qnum, - messages=text.pluralize(messages, 'message'), - queues=text.pluralize(qnum, 'queue'))) - - -class result(Command): - """Gives the return value for a given task id. - - Examples:: - - celery result 8f511516-e2f5-4da4-9d2f-0fb83a86e500 - celery result 8f511516-e2f5-4da4-9d2f-0fb83a86e500 -t tasks.add - celery result 8f511516-e2f5-4da4-9d2f-0fb83a86e500 --traceback - - """ - args = '<task_id>' - option_list = Command.option_list + ( - Option('--task', '-t', help='name of task (if custom backend)'), - Option('--traceback', action='store_true', - help='show traceback instead'), - ) - - def run(self, task_id, *args, **kwargs): - result_cls = self.app.AsyncResult - task = kwargs.get('task') - traceback = kwargs.get('traceback', False) - - if task: - result_cls = self.app.tasks[task].AsyncResult - result = result_cls(task_id) - if traceback: - value = result.traceback - else: - value = result.get() - self.out(self.pretty(value)[1]) - - -class _RemoteControl(Command): - name = None - choices = None - leaf = False - option_list = Command.option_list + ( - Option('--timeout', '-t', type='float', - help='Timeout in seconds (float) waiting for reply'), - Option('--destination', '-d', - help='Comma separated list of destination node names.')) - - def __init__(self, *args, **kwargs): - self.show_body = kwargs.pop('show_body', True) - self.show_reply = kwargs.pop('show_reply', True) - super(_RemoteControl, self).__init__(*args, **kwargs) - - @classmethod - def get_command_info(self, command, - indent=0, prefix='', color=None, help=False): - if help: - help = '|' + text.indent(self.choices[command][1], indent + 4) - else: - help = None - try: - # see if it uses args. - meth = getattr(self, command) - return text.join([ - '|' + text.indent('{0}{1} {2}'.format( - prefix, color(command), meth.__doc__), indent), - help, - ]) - - except AttributeError: - return text.join([ - '|' + text.indent(prefix + str(color(command)), indent), help, - ]) - - @classmethod - def list_commands(self, indent=0, prefix='', color=None, help=False): - color = color if color else lambda x: x - prefix = prefix + ' ' if prefix else '' - return '\n'.join(self.get_command_info(c, indent, prefix, color, help) - for c in sorted(self.choices)) - - @property - def epilog(self): - return '\n'.join([ - '[Commands]', - self.list_commands(indent=4, help=True) - ]) - - def usage(self, command): - return '%prog {0} [options] {1} <command> [arg1 .. argN]'.format( - command, self.args) - - def call(self, *args, **kwargs): - raise NotImplementedError('call') - - def run(self, *args, **kwargs): - if not args: - raise self.UsageError( - 'Missing {0.name} method. See --help'.format(self)) - return self.do_call_method(args, **kwargs) - - def do_call_method(self, args, **kwargs): - method = args[0] - if method == 'help': - raise self.Error("Did you mean '{0.name} --help'?".format(self)) - if method not in self.choices: - raise self.UsageError( - 'Unknown {0.name} method {1}'.format(self, method)) - - if self.app.connection().transport.driver_type == 'sql': - raise self.Error('Broadcast not supported by SQL broker transport') - - destination = kwargs.get('destination') - timeout = kwargs.get('timeout') or self.choices[method][0] - if destination and isinstance(destination, string_t): - destination = [dest.strip() for dest in destination.split(',')] - - handler = getattr(self, method, self.call) - - replies = handler(method, *args[1:], timeout=timeout, - destination=destination, - callback=self.say_remote_command_reply) - if not replies: - raise self.Error('No nodes replied within time constraint.', - status=EX_UNAVAILABLE) - return replies - - -class inspect(_RemoteControl): - """Inspect the worker at runtime. - - Availability: RabbitMQ (amqp), Redis, and MongoDB transports. - - Examples:: - - celery inspect active --timeout=5 - celery inspect scheduled -d worker1@example.com - celery inspect revoked -d w1@e.com,w2@e.com - - """ - name = 'inspect' - choices = { - 'active': (1.0, 'dump active tasks (being processed)'), - 'active_queues': (1.0, 'dump queues being consumed from'), - 'scheduled': (1.0, 'dump scheduled tasks (eta/countdown/retry)'), - 'reserved': (1.0, 'dump reserved tasks (waiting to be processed)'), - 'stats': (1.0, 'dump worker statistics'), - 'revoked': (1.0, 'dump of revoked task ids'), - 'registered': (1.0, 'dump of registered tasks'), - 'ping': (0.2, 'ping worker(s)'), - 'clock': (1.0, 'get value of logical clock'), - 'conf': (1.0, 'dump worker configuration'), - 'report': (1.0, 'get bugreport info'), - 'memsample': (1.0, 'sample memory (requires psutil)'), - 'memdump': (1.0, 'dump memory samples (requires psutil)'), - 'objgraph': (60.0, 'create object graph (requires objgraph)'), - } - - def call(self, method, *args, **options): - i = self.app.control.inspect(**options) - return getattr(i, method)(*args) - - def objgraph(self, type_='Request', *args, **kwargs): - return self.call('objgraph', type_, **kwargs) - - def conf(self, with_defaults=False, *args, **kwargs): - return self.call('conf', with_defaults, **kwargs) - - -class control(_RemoteControl): - """Workers remote control. - - Availability: RabbitMQ (amqp), Redis, and MongoDB transports. - - Examples:: - - celery control enable_events --timeout=5 - celery control -d worker1@example.com enable_events - celery control -d w1.e.com,w2.e.com enable_events - - celery control -d w1.e.com add_consumer queue_name - celery control -d w1.e.com cancel_consumer queue_name - - celery control -d w1.e.com add_consumer queue exchange direct rkey - - """ - name = 'control' - choices = { - 'enable_events': (1.0, 'tell worker(s) to enable events'), - 'disable_events': (1.0, 'tell worker(s) to disable events'), - 'add_consumer': (1.0, 'tell worker(s) to start consuming a queue'), - 'cancel_consumer': (1.0, 'tell worker(s) to stop consuming a queue'), - 'rate_limit': ( - 1.0, 'tell worker(s) to modify the rate limit for a task type'), - 'time_limit': ( - 1.0, 'tell worker(s) to modify the time limit for a task type.'), - 'autoscale': (1.0, 'change autoscale settings'), - 'pool_grow': (1.0, 'start more pool processes'), - 'pool_shrink': (1.0, 'use less pool processes'), - } - - def call(self, method, *args, **options): - return getattr(self.app.control, method)(*args, reply=True, **options) - - def pool_grow(self, method, n=1, **kwargs): - """[N=1]""" - return self.call(method, int(n), **kwargs) - - def pool_shrink(self, method, n=1, **kwargs): - """[N=1]""" - return self.call(method, int(n), **kwargs) - - def autoscale(self, method, max=None, min=None, **kwargs): - """[max] [min]""" - return self.call(method, int(max), int(min), **kwargs) - - def rate_limit(self, method, task_name, rate_limit, **kwargs): - """<task_name> <rate_limit> (e.g. 5/s | 5/m | 5/h)>""" - return self.call(method, task_name, rate_limit, **kwargs) - - def time_limit(self, method, task_name, soft, hard=None, **kwargs): - """<task_name> <soft_secs> [hard_secs]""" - return self.call(method, task_name, - float(soft), float(hard), **kwargs) - - def add_consumer(self, method, queue, exchange=None, - exchange_type='direct', routing_key=None, **kwargs): - """<queue> [exchange [type [routing_key]]]""" - return self.call(method, queue, exchange, - exchange_type, routing_key, **kwargs) - - def cancel_consumer(self, method, queue, **kwargs): - """<queue>""" - return self.call(method, queue, **kwargs) - - -class status(Command): - """Show list of workers that are online.""" - option_list = inspect.option_list - - def run(self, *args, **kwargs): - I = inspect( - app=self.app, - no_color=kwargs.get('no_color', False), - stdout=self.stdout, stderr=self.stderr, - show_reply=False, show_body=False, quiet=True, - ) - replies = I.run('ping', **kwargs) - if not replies: - raise self.Error('No nodes replied within time constraint', - status=EX_UNAVAILABLE) - nodecount = len(replies) - if not kwargs.get('quiet', False): - self.out('\n{0} {1} online.'.format( - nodecount, text.pluralize(nodecount, 'node'))) - - -class migrate(Command): - """Migrate tasks from one broker to another. - - Examples:: - - celery migrate redis://localhost amqp://guest@localhost// - celery migrate django:// redis://localhost - - NOTE: This command is experimental, make sure you have - a backup of the tasks before you continue. - """ - args = '<source_url> <dest_url>' - option_list = Command.option_list + ( - Option('--limit', '-n', type='int', - help='Number of tasks to consume (int)'), - Option('--timeout', '-t', type='float', default=1.0, - help='Timeout in seconds (float) waiting for tasks'), - Option('--ack-messages', '-a', action='store_true', - help='Ack messages from source broker.'), - Option('--tasks', '-T', - help='List of task names to filter on.'), - Option('--queues', '-Q', - help='List of queues to migrate.'), - Option('--forever', '-F', action='store_true', - help='Continually migrate tasks until killed.'), - ) - progress_fmt = MIGRATE_PROGRESS_FMT - - def on_migrate_task(self, state, body, message): - self.out(self.progress_fmt.format(state=state, body=body)) - - def run(self, source, destination, **kwargs): - from kombu import Connection - from celery.contrib.migrate import migrate_tasks - - migrate_tasks(Connection(source), - Connection(destination), - callback=self.on_migrate_task, - **kwargs) - - -class shell(Command): # pragma: no cover - """Start shell session with convenient access to celery symbols. - - The following symbols will be added to the main globals: - - - celery: the current application. - - chord, group, chain, chunks, - xmap, xstarmap subtask, Task - - all registered tasks. - - """ - option_list = Command.option_list + ( - Option('--ipython', '-I', - action='store_true', dest='force_ipython', - help='force iPython.'), - Option('--bpython', '-B', - action='store_true', dest='force_bpython', - help='force bpython.'), - Option('--python', '-P', - action='store_true', dest='force_python', - help='force default Python shell.'), - Option('--without-tasks', '-T', action='store_true', - help="don't add tasks to locals."), - Option('--eventlet', action='store_true', - help='use eventlet.'), - Option('--gevent', action='store_true', help='use gevent.'), - ) - - def run(self, force_ipython=False, force_bpython=False, - force_python=False, without_tasks=False, eventlet=False, - gevent=False, **kwargs): - sys.path.insert(0, os.getcwd()) - if eventlet: - import_module('celery.concurrency.eventlet') - if gevent: - import_module('celery.concurrency.gevent') - import celery - import celery.task.base - self.app.loader.import_default_modules() - self.locals = {'app': self.app, - 'celery': self.app, - 'Task': celery.Task, - 'chord': celery.chord, - 'group': celery.group, - 'chain': celery.chain, - 'chunks': celery.chunks, - 'xmap': celery.xmap, - 'xstarmap': celery.xstarmap, - 'subtask': celery.subtask, - 'signature': celery.signature} - - if not without_tasks: - self.locals.update(dict( - (task.__name__, task) for task in values(self.app.tasks) - if not task.name.startswith('celery.')), - ) - - if force_python: - return self.invoke_fallback_shell() - elif force_bpython: - return self.invoke_bpython_shell() - elif force_ipython: - return self.invoke_ipython_shell() - return self.invoke_default_shell() - - def invoke_default_shell(self): - try: - import IPython # noqa - except ImportError: - try: - import bpython # noqa - except ImportError: - return self.invoke_fallback_shell() - else: - return self.invoke_bpython_shell() - else: - return self.invoke_ipython_shell() - - def invoke_fallback_shell(self): - import code - try: - import readline - except ImportError: - pass - else: - import rlcompleter - readline.set_completer( - rlcompleter.Completer(self.locals).complete) - readline.parse_and_bind('tab:complete') - code.interact(local=self.locals) - - def invoke_ipython_shell(self): - try: - from IPython.terminal import embed - embed.TerminalInteractiveShell(user_ns=self.locals).mainloop() - except ImportError: # ipython < 0.11 - from IPython.Shell import IPShell - IPShell(argv=[], user_ns=self.locals).mainloop() - - def invoke_bpython_shell(self): - import bpython - bpython.embed(self.locals) - - -class help(Command): - """Show help screen and exit.""" - - def usage(self, command): - return '%prog <command> [options] {0.args}'.format(self) - - def run(self, *args, **kwargs): - self.parser.print_help() - self.out(HELP.format( - prog_name=self.prog_name, - commands=CeleryCommand.list_commands(colored=self.colored), - )) - - return EX_USAGE - - -class report(Command): - """Shows information useful to include in bugreports.""" - - def run(self, *args, **kwargs): - self.out(self.app.bugreport()) - return EX_OK - - -class CeleryCommand(Command): - namespace = 'celery' - ext_fmt = '{self.namespace}.commands' - commands = { - 'amqp': amqp, - 'beat': beat, - 'call': call, - 'control': control, - 'events': events, - 'graph': graph, - 'help': help, - 'inspect': inspect, - 'list': list_, - 'migrate': migrate, - 'multi': multi, - 'purge': purge, - 'report': report, - 'result': result, - 'shell': shell, - 'status': status, - 'worker': worker, - - } - enable_config_from_cmdline = True - prog_name = 'celery' - - @classmethod - def register_command(cls, fun, name=None): - cls.commands[name or fun.__name__] = fun - return fun - - def execute(self, command, argv=None): - try: - cls = self.commands[command] - except KeyError: - cls, argv = self.commands['help'], ['help'] - cls = self.commands.get(command) or self.commands['help'] - try: - return cls( - app=self.app, on_error=self.on_error, - no_color=self.no_color, quiet=self.quiet, - on_usage_error=partial(self.on_usage_error, command=command), - ).run_from_argv(self.prog_name, argv[1:], command=argv[0]) - except self.UsageError as exc: - self.on_usage_error(exc) - return exc.status - except self.Error as exc: - self.on_error(exc) - return exc.status - - def on_usage_error(self, exc, command=None): - if command: - helps = '{self.prog_name} {command} --help' - else: - helps = '{self.prog_name} --help' - self.error(self.colored.magenta('Error: {0}'.format(exc))) - self.error("""Please try '{0}'""".format(helps.format( - self=self, command=command, - ))) - - def _relocate_args_from_start(self, argv, index=0): - if argv: - rest = [] - while index < len(argv): - value = argv[index] - if value.startswith('--'): - rest.append(value) - elif value.startswith('-'): - # we eat the next argument even though we don't know - # if this option takes an argument or not. - # instead we will assume what is the command name in the - # return statements below. - try: - nxt = argv[index + 1] - if nxt.startswith('-'): - # is another option - rest.append(value) - else: - # is (maybe) a value for this option - rest.extend([value, nxt]) - index += 1 - except IndexError: - rest.append(value) - break - else: - break - index += 1 - if argv[index:]: - # if there are more arguments left then divide and swap - # we assume the first argument in argv[i:] is the command - # name. - return argv[index:] + rest - # if there are no more arguments then the last arg in rest' - # must be the command. - [rest.pop()] + rest - return [] - - def prepare_prog_name(self, name): - if name == '__main__.py': - return sys.modules['__main__'].__file__ - return name - - def handle_argv(self, prog_name, argv): - self.prog_name = self.prepare_prog_name(prog_name) - argv = self._relocate_args_from_start(argv) - _, argv = self.prepare_args(None, argv) - try: - command = argv[0] - except IndexError: - command, argv = 'help', ['help'] - return self.execute(command, argv) - - def execute_from_commandline(self, argv=None): - argv = sys.argv if argv is None else argv - if 'multi' in argv[1:3]: # Issue 1008 - self.respects_app_option = False - try: - sys.exit(determine_exit_status( - super(CeleryCommand, self).execute_from_commandline(argv))) - except KeyboardInterrupt: - sys.exit(EX_FAILURE) - - @classmethod - def get_command_info(self, command, indent=0, color=None, colored=None): - colored = term.colored() if colored is None else colored - colored = colored.names[color] if color else lambda x: x - obj = self.commands[command] - cmd = 'celery {0}'.format(colored(command)) - if obj.leaf: - return '|' + text.indent(cmd, indent) - return text.join([ - ' ', - '|' + text.indent('{0} --help'.format(cmd), indent), - obj.list_commands(indent, 'celery {0}'.format(command), colored), - ]) - - @classmethod - def list_commands(self, indent=0, colored=None): - colored = term.colored() if colored is None else colored - white = colored.white - ret = [] - for cls, commands, color in command_classes: - ret.extend([ - text.indent('+ {0}: '.format(white(cls)), indent), - '\n'.join( - self.get_command_info(command, indent + 4, color, colored) - for command in commands), - '' - ]) - return '\n'.join(ret).strip() - - def with_pool_option(self, argv): - if len(argv) > 1 and 'worker' in argv[0:3]: - # this command supports custom pools - # that may have to be loaded as early as possible. - return (['-P'], ['--pool']) - - def on_concurrency_setup(self): - self.load_extension_commands() - - def load_extension_commands(self): - names = Extensions(self.ext_fmt.format(self=self), - self.register_command).load() - if names: - command_classes.append(('Extensions', names, 'magenta')) - - -def command(*args, **kwargs): - """Deprecated: Use classmethod :meth:`CeleryCommand.register_command` - instead.""" - _register = CeleryCommand.register_command - return _register(args[0]) if args else _register - - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/bin/celeryd_detach.py b/awx/lib/site-packages/celery/bin/celeryd_detach.py deleted file mode 100644 index 1db2ff041d..0000000000 --- a/awx/lib/site-packages/celery/bin/celeryd_detach.py +++ /dev/null @@ -1,168 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.bin.celeryd_detach - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - Program used to daemonize the worker - - Using :func:`os.execv` because forking and multiprocessing - leads to weird issues (it was a long time ago now, but it - could have something to do with the threading mutex bug) - -""" -from __future__ import absolute_import - -import celery -import os -import sys - -from optparse import OptionParser, BadOptionError - -from celery.platforms import EX_FAILURE, detached -from celery.utils.log import get_logger - -from celery.bin.base import daemon_options, Option - -__all__ = ['detached_celeryd', 'detach'] - -logger = get_logger(__name__) - -C_FAKEFORK = os.environ.get('C_FAKEFORK') - -OPTION_LIST = daemon_options(default_pidfile='celeryd.pid') + ( - Option('--fake', - default=False, action='store_true', dest='fake', - help="Don't fork (for debugging purposes)"), -) - - -def detach(path, argv, logfile=None, pidfile=None, uid=None, - gid=None, umask=0, working_directory=None, fake=False, app=None): - fake = 1 if C_FAKEFORK else fake - with detached(logfile, pidfile, uid, gid, umask, working_directory, fake): - try: - os.execv(path, [path] + argv) - except Exception: - if app is None: - from celery import current_app - app = current_app - app.log.setup_logging_subsystem('ERROR', logfile) - logger.critical("Can't exec %r", ' '.join([path] + argv), - exc_info=True) - return EX_FAILURE - - -class PartialOptionParser(OptionParser): - - def __init__(self, *args, **kwargs): - self.leftovers = [] - OptionParser.__init__(self, *args, **kwargs) - - def _process_long_opt(self, rargs, values): - arg = rargs.pop(0) - - if '=' in arg: - opt, next_arg = arg.split('=', 1) - rargs.insert(0, next_arg) - had_explicit_value = True - else: - opt = arg - had_explicit_value = False - - try: - opt = self._match_long_opt(opt) - option = self._long_opt.get(opt) - except BadOptionError: - option = None - - if option: - if option.takes_value(): - nargs = option.nargs - if len(rargs) < nargs: - if nargs == 1: - self.error('{0} requires an argument'.format(opt)) - else: - self.error('{0} requires {1} arguments'.format( - opt, nargs)) - elif nargs == 1: - value = rargs.pop(0) - else: - value = tuple(rargs[0:nargs]) - del rargs[0:nargs] - - elif had_explicit_value: - self.error('{0} option does not take a value'.format(opt)) - else: - value = None - option.process(opt, value, values, self) - else: - self.leftovers.append(arg) - - def _process_short_opts(self, rargs, values): - arg = rargs[0] - try: - OptionParser._process_short_opts(self, rargs, values) - except BadOptionError: - self.leftovers.append(arg) - if rargs and not rargs[0][0] == '-': - self.leftovers.append(rargs.pop(0)) - - -class detached_celeryd(object): - option_list = OPTION_LIST - usage = '%prog [options] [celeryd options]' - version = celery.VERSION_BANNER - description = ('Detaches Celery worker nodes. See `celery worker --help` ' - 'for the list of supported worker arguments.') - command = sys.executable - execv_path = sys.executable - if sys.version_info < (2, 7): # does not support pkg/__main__.py - execv_argv = ['-m', 'celery.__main__', 'worker'] - else: - execv_argv = ['-m', 'celery', 'worker'] - - def __init__(self, app=None): - self.app = app - - def Parser(self, prog_name): - return PartialOptionParser(prog=prog_name, - option_list=self.option_list, - usage=self.usage, - description=self.description, - version=self.version) - - def parse_options(self, prog_name, argv): - parser = self.Parser(prog_name) - options, values = parser.parse_args(argv) - if options.logfile: - parser.leftovers.append('--logfile={0}'.format(options.logfile)) - if options.pidfile: - parser.leftovers.append('--pidfile={0}'.format(options.pidfile)) - return options, values, parser.leftovers - - def execute_from_commandline(self, argv=None): - if argv is None: - argv = sys.argv - config = [] - seen_cargs = 0 - for arg in argv: - if seen_cargs: - config.append(arg) - else: - if arg == '--': - seen_cargs = 1 - config.append(arg) - prog_name = os.path.basename(argv[0]) - options, values, leftovers = self.parse_options(prog_name, argv[1:]) - sys.exit(detach( - app=self.app, path=self.execv_path, - argv=self.execv_argv + leftovers + config, - **vars(options) - )) - - -def main(app=None): - detached_celeryd(app).execute_from_commandline() - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/bin/events.py b/awx/lib/site-packages/celery/bin/events.py deleted file mode 100644 index d98750504c..0000000000 --- a/awx/lib/site-packages/celery/bin/events.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -""" - -The :program:`celery events` command. - -.. program:: celery events - -.. seealso:: - - See :ref:`preload-options` and :ref:`daemon-options`. - -.. cmdoption:: -d, --dump - - Dump events to stdout. - -.. cmdoption:: -c, --camera - - Take snapshots of events using this camera. - -.. cmdoption:: --detach - - Camera: Detach and run in the background as a daemon. - -.. cmdoption:: -F, --freq, --frequency - - Camera: Shutter frequency. Default is every 1.0 seconds. - -.. cmdoption:: -r, --maxrate - - Camera: Optional shutter rate limit (e.g. 10/m). - -.. cmdoption:: -l, --loglevel - - Logging level, choose between `DEBUG`, `INFO`, `WARNING`, - `ERROR`, `CRITICAL`, or `FATAL`. Default is INFO. - -""" -from __future__ import absolute_import, unicode_literals - -import sys - -from functools import partial - -from celery.platforms import detached, set_process_title, strargv -from celery.bin.base import Command, Option, daemon_options - -__all__ = ['events'] - - -class events(Command): - """Event-stream utilities. - - Commands:: - - celery events --app=proj - start graphical monitor (requires curses) - celery events -d --app=proj - dump events to screen. - celery events -b amqp:// - celery events -c <camera> [options] - run snapshot camera. - - Examples:: - - celery events - celery events -d - celery events -c mod.attr -F 1.0 --detach --maxrate=100/m -l info - """ - doc = __doc__ - supports_args = False - - def run(self, dump=False, camera=None, frequency=1.0, maxrate=None, - loglevel='INFO', logfile=None, prog_name='celery events', - pidfile=None, uid=None, gid=None, umask=None, - working_directory=None, detach=False, **kwargs): - self.prog_name = prog_name - - if dump: - return self.run_evdump() - if camera: - return self.run_evcam(camera, freq=frequency, maxrate=maxrate, - loglevel=loglevel, logfile=logfile, - pidfile=pidfile, uid=uid, gid=gid, - umask=umask, - working_directory=working_directory, - detach=detach) - return self.run_evtop() - - def run_evdump(self): - from celery.events.dumper import evdump - self.set_process_status('dump') - return evdump(app=self.app) - - def run_evtop(self): - from celery.events.cursesmon import evtop - self.set_process_status('top') - return evtop(app=self.app) - - def run_evcam(self, camera, logfile=None, pidfile=None, uid=None, - gid=None, umask=None, working_directory=None, - detach=False, **kwargs): - from celery.events.snapshot import evcam - workdir = working_directory - self.set_process_status('cam') - kwargs['app'] = self.app - cam = partial(evcam, camera, - logfile=logfile, pidfile=pidfile, **kwargs) - - if detach: - with detached(logfile, pidfile, uid, gid, umask, workdir): - return cam() - else: - return cam() - - def set_process_status(self, prog, info=''): - prog = '{0}:{1}'.format(self.prog_name, prog) - info = '{0} {1}'.format(info, strargv(sys.argv)) - return set_process_title(prog, info=info) - - def get_options(self): - return ( - (Option('-d', '--dump', action='store_true'), - Option('-c', '--camera'), - Option('--detach', action='store_true'), - Option('-F', '--frequency', '--freq', - type='float', default=1.0), - Option('-r', '--maxrate'), - Option('-l', '--loglevel', default='INFO')) - + daemon_options(default_pidfile='celeryev.pid') - + tuple(self.app.user_options['events']) - ) - - -def main(): - ev = events() - ev.execute_from_commandline() - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/bin/graph.py b/awx/lib/site-packages/celery/bin/graph.py deleted file mode 100644 index 5d5847672b..0000000000 --- a/awx/lib/site-packages/celery/bin/graph.py +++ /dev/null @@ -1,191 +0,0 @@ -# -*- coding: utf-8 -*- -""" - -The :program:`celery graph` command. - -.. program:: celery graph - -""" -from __future__ import absolute_import, unicode_literals - -from operator import itemgetter - -from celery.datastructures import DependencyGraph, GraphFormatter -from celery.five import items - -from .base import Command - -__all__ = ['graph'] - - -class graph(Command): - args = """<TYPE> [arguments] - ..... bootsteps [worker] [consumer] - ..... workers [enumerate] - """ - - def run(self, what=None, *args, **kwargs): - map = {'bootsteps': self.bootsteps, 'workers': self.workers} - if not what: - raise self.UsageError('missing type') - elif what not in map: - raise self.Error('no graph {0} in {1}'.format(what, '|'.join(map))) - return map[what](*args, **kwargs) - - def bootsteps(self, *args, **kwargs): - worker = self.app.WorkController() - include = set(arg.lower() for arg in args or ['worker', 'consumer']) - if 'worker' in include: - graph = worker.blueprint.graph - if 'consumer' in include: - worker.blueprint.connect_with(worker.consumer.blueprint) - else: - graph = worker.consumer.blueprint.graph - graph.to_dot(self.stdout) - - def workers(self, *args, **kwargs): - - def simplearg(arg): - return maybe_list(itemgetter(0, 2)(arg.partition(':'))) - - def maybe_list(l, sep=','): - return (l[0], l[1].split(sep) if sep in l[1] else l[1]) - - args = dict(simplearg(arg) for arg in args) - generic = 'generic' in args - - def generic_label(node): - return '{0} ({1}://)'.format(type(node).__name__, - node._label.split('://')[0]) - - class Node(object): - force_label = None - scheme = {} - - def __init__(self, label, pos=None): - self._label = label - self.pos = pos - - def label(self): - return self._label - - def __str__(self): - return self.label() - - class Thread(Node): - scheme = {'fillcolor': 'lightcyan4', 'fontcolor': 'yellow', - 'shape': 'oval', 'fontsize': 10, 'width': 0.3, - 'color': 'black'} - - def __init__(self, label, **kwargs): - self._label = 'thr-{0}'.format(next(tids)) - self.real_label = label - self.pos = 0 - - class Formatter(GraphFormatter): - - def label(self, obj): - return obj and obj.label() - - def node(self, obj): - scheme = dict(obj.scheme) if obj.pos else obj.scheme - if isinstance(obj, Thread): - scheme['label'] = obj.real_label - return self.draw_node( - obj, dict(self.node_scheme, **scheme), - ) - - def terminal_node(self, obj): - return self.draw_node( - obj, dict(self.term_scheme, **obj.scheme), - ) - - def edge(self, a, b, **attrs): - if isinstance(a, Thread): - attrs.update(arrowhead='none', arrowtail='tee') - return self.draw_edge(a, b, self.edge_scheme, attrs) - - def subscript(n): - S = {'0': 'â‚€', '1': 'â‚', '2': 'â‚‚', '3': '₃', '4': 'â‚„', - '5': 'â‚…', '6': '₆', '7': '₇', '8': '₈', '9': '₉'} - return ''.join([S[i] for i in str(n)]) - - class Worker(Node): - pass - - class Backend(Node): - scheme = {'shape': 'folder', 'width': 2, - 'height': 1, 'color': 'black', - 'fillcolor': 'peachpuff3', 'color': 'peachpuff4'} - - def label(self): - return generic_label(self) if generic else self._label - - class Broker(Node): - scheme = {'shape': 'circle', 'fillcolor': 'cadetblue3', - 'color': 'cadetblue4', 'height': 1} - - def label(self): - return generic_label(self) if generic else self._label - - from itertools import count - tids = count(1) - Wmax = int(args.get('wmax', 4) or 0) - Tmax = int(args.get('tmax', 3) or 0) - - def maybe_abbr(l, name, max=Wmax): - size = len(l) - abbr = max and size > max - if 'enumerate' in args: - l = ['{0}{1}'.format(name, subscript(i + 1)) - for i, obj in enumerate(l)] - if abbr: - l = l[0:max - 1] + [l[size - 1]] - l[max - 2] = '{0}⎨…{1}⎬'.format( - name[0], subscript(size - (max - 1))) - return l - - try: - workers = args['nodes'] - threads = args.get('threads') or [] - except KeyError: - replies = self.app.control.inspect().stats() - workers, threads = [], [] - for worker, reply in items(replies): - workers.append(worker) - threads.append(reply['pool']['max-concurrency']) - - wlen = len(workers) - backend = args.get('backend', self.app.conf.CELERY_RESULT_BACKEND) - threads_for = {} - workers = maybe_abbr(workers, 'Worker') - if Wmax and wlen > Wmax: - threads = threads[0:3] + [threads[-1]] - for i, threads in enumerate(threads): - threads_for[workers[i]] = maybe_abbr( - list(range(int(threads))), 'P', Tmax, - ) - - broker = Broker(args.get('broker', self.app.connection().as_uri())) - backend = Backend(backend) if backend else None - graph = DependencyGraph(formatter=Formatter()) - graph.add_arc(broker) - if backend: - graph.add_arc(backend) - curworker = [0] - for i, worker in enumerate(workers): - worker = Worker(worker, pos=i) - graph.add_arc(worker) - graph.add_edge(worker, broker) - if backend: - graph.add_edge(worker, backend) - threads = threads_for.get(worker._label) - if threads: - for thread in threads: - thread = Thread(thread) - graph.add_arc(thread) - graph.add_edge(thread, worker) - - curworker[0] += 1 - - graph.to_dot(self.stdout) diff --git a/awx/lib/site-packages/celery/bin/multi.py b/awx/lib/site-packages/celery/bin/multi.py deleted file mode 100644 index ca14c0bfed..0000000000 --- a/awx/lib/site-packages/celery/bin/multi.py +++ /dev/null @@ -1,639 +0,0 @@ -# -*- coding: utf-8 -*- -""" - -.. program:: celery multi - -Examples -======== - -.. code-block:: bash - - # Single worker with explicit name and events enabled. - $ celery multi start Leslie -E - - # Pidfiles and logfiles are stored in the current directory - # by default. Use --pidfile and --logfile argument to change - # this. The abbreviation %N will be expanded to the current - # node name. - $ celery multi start Leslie -E --pidfile=/var/run/celery/%N.pid - --logfile=/var/log/celery/%N.log - - - # You need to add the same arguments when you restart, - # as these are not persisted anywhere. - $ celery multi restart Leslie -E --pidfile=/var/run/celery/%N.pid - --logfile=/var/run/celery/%N.log - - # To stop the node, you need to specify the same pidfile. - $ celery multi stop Leslie --pidfile=/var/run/celery/%N.pid - - # 3 workers, with 3 processes each - $ celery multi start 3 -c 3 - celery worker -n celery1@myhost -c 3 - celery worker -n celery2@myhost -c 3 - celery worker -n celery3@myhost -c 3 - - # start 3 named workers - $ celery multi start image video data -c 3 - celery worker -n image@myhost -c 3 - celery worker -n video@myhost -c 3 - celery worker -n data@myhost -c 3 - - # specify custom hostname - $ celery multi start 2 --hostname=worker.example.com -c 3 - celery worker -n celery1@worker.example.com -c 3 - celery worker -n celery2@worker.example.com -c 3 - - # specify fully qualified nodenames - $ celery multi start foo@worker.example.com bar@worker.example.com -c 3 - - # Advanced example starting 10 workers in the background: - # * Three of the workers processes the images and video queue - # * Two of the workers processes the data queue with loglevel DEBUG - # * the rest processes the default' queue. - $ celery multi start 10 -l INFO -Q:1-3 images,video -Q:4,5 data - -Q default -L:4,5 DEBUG - - # You can show the commands necessary to start the workers with - # the 'show' command: - $ celery multi show 10 -l INFO -Q:1-3 images,video -Q:4,5 data - -Q default -L:4,5 DEBUG - - # Additional options are added to each celery worker' comamnd, - # but you can also modify the options for ranges of, or specific workers - - # 3 workers: Two with 3 processes, and one with 10 processes. - $ celery multi start 3 -c 3 -c:1 10 - celery worker -n celery1@myhost -c 10 - celery worker -n celery2@myhost -c 3 - celery worker -n celery3@myhost -c 3 - - # can also specify options for named workers - $ celery multi start image video data -c 3 -c:image 10 - celery worker -n image@myhost -c 10 - celery worker -n video@myhost -c 3 - celery worker -n data@myhost -c 3 - - # ranges and lists of workers in options is also allowed: - # (-c:1-3 can also be written as -c:1,2,3) - $ celery multi start 5 -c 3 -c:1-3 10 - celery worker -n celery1@myhost -c 10 - celery worker -n celery2@myhost -c 10 - celery worker -n celery3@myhost -c 10 - celery worker -n celery4@myhost -c 3 - celery worker -n celery5@myhost -c 3 - - # lists also works with named workers - $ celery multi start foo bar baz xuzzy -c 3 -c:foo,bar,baz 10 - celery worker -n foo@myhost -c 10 - celery worker -n bar@myhost -c 10 - celery worker -n baz@myhost -c 10 - celery worker -n xuzzy@myhost -c 3 - -""" -from __future__ import absolute_import, print_function, unicode_literals - -import errno -import os -import shlex -import signal -import socket -import sys - -from collections import defaultdict, namedtuple -from subprocess import Popen -from time import sleep - -from kombu.utils import cached_property -from kombu.utils.compat import OrderedDict -from kombu.utils.encoding import from_utf8 - -from celery import VERSION_BANNER -from celery.five import items -from celery.platforms import Pidfile, IS_WINDOWS -from celery.utils import term, nodesplit -from celery.utils.text import pluralize - -__all__ = ['MultiTool'] - -SIGNAMES = set(sig for sig in dir(signal) - if sig.startswith('SIG') and '_' not in sig) -SIGMAP = dict((getattr(signal, name), name) for name in SIGNAMES) - -USAGE = """\ -usage: {prog_name} start <node1 node2 nodeN|range> [worker options] - {prog_name} stop <n1 n2 nN|range> [-SIG (default: -TERM)] - {prog_name} restart <n1 n2 nN|range> [-SIG] [worker options] - {prog_name} kill <n1 n2 nN|range> - - {prog_name} show <n1 n2 nN|range> [worker options] - {prog_name} get hostname <n1 n2 nN|range> [-qv] [worker options] - {prog_name} names <n1 n2 nN|range> - {prog_name} expand template <n1 n2 nN|range> - {prog_name} help - -additional options (must appear after command name): - - * --nosplash: Don't display program info. - * --quiet: Don't show as much output. - * --verbose: Show more output. - * --no-color: Don't display colors. -""" - -multi_args_t = namedtuple( - 'multi_args_t', ('name', 'argv', 'expander', 'namespace'), -) - - -def main(): - sys.exit(MultiTool().execute_from_commandline(sys.argv)) - - -CELERY_EXE = 'celery' -if sys.version_info < (2, 7): - # pkg.__main__ first supported in Py2.7 - CELERY_EXE = 'celery.__main__' - - -def celery_exe(*args): - return ' '.join((CELERY_EXE, ) + args) - - -class MultiTool(object): - retcode = 0 # Final exit code. - - def __init__(self, env=None, fh=None, quiet=False, verbose=False, - no_color=False, nosplash=False): - self.fh = fh or sys.stderr - self.env = env - self.nosplash = nosplash - self.quiet = quiet - self.verbose = verbose - self.no_color = no_color - self.prog_name = 'celery multi' - self.commands = {'start': self.start, - 'show': self.show, - 'stop': self.stop, - 'stopwait': self.stopwait, - 'stop_verify': self.stopwait, # compat alias - 'restart': self.restart, - 'kill': self.kill, - 'names': self.names, - 'expand': self.expand, - 'get': self.get, - 'help': self.help} - - def execute_from_commandline(self, argv, cmd='celery worker'): - argv = list(argv) # don't modify callers argv. - - # Reserve the --nosplash|--quiet|-q/--verbose options. - if '--nosplash' in argv: - self.nosplash = argv.pop(argv.index('--nosplash')) - if '--quiet' in argv: - self.quiet = argv.pop(argv.index('--quiet')) - if '-q' in argv: - self.quiet = argv.pop(argv.index('-q')) - if '--verbose' in argv: - self.verbose = argv.pop(argv.index('--verbose')) - if '--no-color' in argv: - self.no_color = argv.pop(argv.index('--no-color')) - - self.prog_name = os.path.basename(argv.pop(0)) - if not argv or argv[0][0] == '-': - return self.error() - - try: - self.commands[argv[0]](argv[1:], cmd) - except KeyError: - self.error('Invalid command: {0}'.format(argv[0])) - - return self.retcode - - def say(self, m, newline=True): - print(m, file=self.fh, end='\n' if newline else '') - - def names(self, argv, cmd): - p = NamespacedOptionParser(argv) - self.say('\n'.join( - n.name for n in multi_args(p, cmd)), - ) - - def get(self, argv, cmd): - wanted = argv[0] - p = NamespacedOptionParser(argv[1:]) - for node in multi_args(p, cmd): - if node.name == wanted: - self.say(' '.join(node.argv)) - return - - def show(self, argv, cmd): - p = NamespacedOptionParser(argv) - self.with_detacher_default_options(p) - self.say('\n'.join( - ' '.join([sys.executable] + n.argv) for n in multi_args(p, cmd)), - ) - - def start(self, argv, cmd): - self.splash() - p = NamespacedOptionParser(argv) - self.with_detacher_default_options(p) - retcodes = [] - self.note('> Starting nodes...') - for node in multi_args(p, cmd): - self.note('\t> {0}: '.format(node.name), newline=False) - retcode = self.waitexec(node.argv) - self.note(retcode and self.FAILED or self.OK) - retcodes.append(retcode) - self.retcode = int(any(retcodes)) - - def with_detacher_default_options(self, p): - _setdefaultopt(p.options, ['--pidfile', '-p'], '%N.pid') - _setdefaultopt(p.options, ['--logfile', '-f'], '%N.log') - p.options.setdefault( - '--cmd', - '-m {0}'.format(celery_exe('worker', '--detach')), - ) - - def signal_node(self, nodename, pid, sig): - try: - os.kill(pid, sig) - except OSError as exc: - if exc.errno != errno.ESRCH: - raise - self.note('Could not signal {0} ({1}): No such process'.format( - nodename, pid)) - return False - return True - - def node_alive(self, pid): - try: - os.kill(pid, 0) - except OSError as exc: - if exc.errno == errno.ESRCH: - return False - raise - return True - - def shutdown_nodes(self, nodes, sig=signal.SIGTERM, retry=None, - callback=None): - if not nodes: - return - P = set(nodes) - - def on_down(node): - P.discard(node) - if callback: - callback(*node) - - self.note(self.colored.blue('> Stopping nodes...')) - for node in list(P): - if node in P: - nodename, _, pid = node - self.note('\t> {0}: {1} -> {2}'.format( - nodename, SIGMAP[sig][3:], pid)) - if not self.signal_node(nodename, pid, sig): - on_down(node) - - def note_waiting(): - left = len(P) - if left: - pids = ', '.join(str(pid) for _, _, pid in P) - self.note(self.colored.blue( - '> Waiting for {0} {1} -> {2}...'.format( - left, pluralize(left, 'node'), pids)), newline=False) - - if retry: - note_waiting() - its = 0 - while P: - for node in P: - its += 1 - self.note('.', newline=False) - nodename, _, pid = node - if not self.node_alive(pid): - self.note('\n\t> {0}: {1}'.format(nodename, self.OK)) - on_down(node) - note_waiting() - break - if P and not its % len(P): - sleep(float(retry)) - self.note('') - - def getpids(self, p, cmd, callback=None): - _setdefaultopt(p.options, ['--pidfile', '-p'], '%N.pid') - - nodes = [] - for node in multi_args(p, cmd): - try: - pidfile_template = _getopt( - p.namespaces[node.namespace], ['--pidfile', '-p'], - ) - except KeyError: - pidfile_template = _getopt(p.options, ['--pidfile', '-p']) - pid = None - pidfile = node.expander(pidfile_template) - try: - pid = Pidfile(pidfile).read_pid() - except ValueError: - pass - if pid: - nodes.append((node.name, tuple(node.argv), pid)) - else: - self.note('> {0.name}: {1}'.format(node, self.DOWN)) - if callback: - callback(node.name, node.argv, pid) - - return nodes - - def kill(self, argv, cmd): - self.splash() - p = NamespacedOptionParser(argv) - for nodename, _, pid in self.getpids(p, cmd): - self.note('Killing node {0} ({1})'.format(nodename, pid)) - self.signal_node(nodename, pid, signal.SIGKILL) - - def stop(self, argv, cmd, retry=None, callback=None): - self.splash() - p = NamespacedOptionParser(argv) - return self._stop_nodes(p, cmd, retry=retry, callback=callback) - - def _stop_nodes(self, p, cmd, retry=None, callback=None): - restargs = p.args[len(p.values):] - self.shutdown_nodes(self.getpids(p, cmd, callback=callback), - sig=findsig(restargs), - retry=retry, - callback=callback) - - def restart(self, argv, cmd): - self.splash() - p = NamespacedOptionParser(argv) - self.with_detacher_default_options(p) - retvals = [] - - def on_node_shutdown(nodename, argv, pid): - self.note(self.colored.blue( - '> Restarting node {0}: '.format(nodename)), newline=False) - retval = self.waitexec(argv) - self.note(retval and self.FAILED or self.OK) - retvals.append(retval) - - self._stop_nodes(p, cmd, retry=2, callback=on_node_shutdown) - self.retval = int(any(retvals)) - - def stopwait(self, argv, cmd): - self.splash() - p = NamespacedOptionParser(argv) - self.with_detacher_default_options(p) - return self._stop_nodes(p, cmd, retry=2) - stop_verify = stopwait # compat - - def expand(self, argv, cmd=None): - template = argv[0] - p = NamespacedOptionParser(argv[1:]) - for node in multi_args(p, cmd): - self.say(node.expander(template)) - - def help(self, argv, cmd=None): - self.say(__doc__) - - def usage(self): - self.splash() - self.say(USAGE.format(prog_name=self.prog_name)) - - def splash(self): - if not self.nosplash: - c = self.colored - self.note(c.cyan('celery multi v{0}'.format(VERSION_BANNER))) - - def waitexec(self, argv, path=sys.executable): - args = ' '.join([path] + list(argv)) - argstr = shlex.split(from_utf8(args), posix=not IS_WINDOWS) - pipe = Popen(argstr, env=self.env) - self.info(' {0}'.format(' '.join(argstr))) - retcode = pipe.wait() - if retcode < 0: - self.note('* Child was terminated by signal {0}'.format(-retcode)) - return -retcode - elif retcode > 0: - self.note('* Child terminated with errorcode {0}'.format(retcode)) - return retcode - - def error(self, msg=None): - if msg: - self.say(msg) - self.usage() - self.retcode = 1 - return 1 - - def info(self, msg, newline=True): - if self.verbose: - self.note(msg, newline=newline) - - def note(self, msg, newline=True): - if not self.quiet: - self.say(str(msg), newline=newline) - - @cached_property - def colored(self): - return term.colored(enabled=not self.no_color) - - @cached_property - def OK(self): - return str(self.colored.green('OK')) - - @cached_property - def FAILED(self): - return str(self.colored.red('FAILED')) - - @cached_property - def DOWN(self): - return str(self.colored.magenta('DOWN')) - - -def multi_args(p, cmd='celery worker', append='', prefix='', suffix=''): - names = p.values - options = dict(p.options) - passthrough = p.passthrough - ranges = len(names) == 1 - if ranges: - try: - noderange = int(names[0]) - except ValueError: - pass - else: - names = [str(n) for n in range(1, noderange + 1)] - prefix = 'celery' - cmd = options.pop('--cmd', cmd) - append = options.pop('--append', append) - hostname = options.pop('--hostname', - options.pop('-n', socket.gethostname())) - prefix = options.pop('--prefix', prefix) or '' - suffix = options.pop('--suffix', suffix) or hostname - if suffix in ('""', "''"): - suffix = '' - - for ns_name, ns_opts in list(items(p.namespaces)): - if ',' in ns_name or (ranges and '-' in ns_name): - for subns in parse_ns_range(ns_name, ranges): - p.namespaces[subns].update(ns_opts) - p.namespaces.pop(ns_name) - - # Numbers in args always refers to the index in the list of names. - # (e.g. `start foo bar baz -c:1` where 1 is foo, 2 is bar, and so on). - for ns_name, ns_opts in list(items(p.namespaces)): - if ns_name.isdigit(): - ns_index = int(ns_name) - 1 - if ns_index < 0: - raise KeyError('Indexes start at 1 got: %r' % (ns_name, )) - try: - p.namespaces[names[ns_index]].update(ns_opts) - except IndexError: - raise KeyError('No node at index %r' % (ns_name, )) - - for name in names: - this_suffix = suffix - if '@' in name: - this_name = options['-n'] = name - nodename, this_suffix = nodesplit(name) - name = nodename - else: - nodename = '%s%s' % (prefix, name) - this_name = options['-n'] = '%s@%s' % (nodename, this_suffix) - expand = abbreviations({'%h': this_name, - '%n': name, - '%N': nodename, - '%d': this_suffix}) - argv = ([expand(cmd)] + - [format_opt(opt, expand(value)) - for opt, value in items(p.optmerge(name, options))] + - [passthrough]) - if append: - argv.append(expand(append)) - yield multi_args_t(this_name, argv, expand, name) - - -class NamespacedOptionParser(object): - - def __init__(self, args): - self.args = args - self.options = OrderedDict() - self.values = [] - self.passthrough = '' - self.namespaces = defaultdict(lambda: OrderedDict()) - - self.parse() - - def parse(self): - rargs = list(self.args) - pos = 0 - while pos < len(rargs): - arg = rargs[pos] - if arg == '--': - self.passthrough = ' '.join(rargs[pos:]) - break - elif arg[0] == '-': - if arg[1] == '-': - self.process_long_opt(arg[2:]) - else: - value = None - if len(rargs) > pos + 1 and rargs[pos + 1][0] != '-': - value = rargs[pos + 1] - pos += 1 - self.process_short_opt(arg[1:], value) - else: - self.values.append(arg) - pos += 1 - - def process_long_opt(self, arg, value=None): - if '=' in arg: - arg, value = arg.split('=', 1) - self.add_option(arg, value, short=False) - - def process_short_opt(self, arg, value=None): - self.add_option(arg, value, short=True) - - def optmerge(self, ns, defaults=None): - if defaults is None: - defaults = self.options - return OrderedDict(defaults, **self.namespaces[ns]) - - def add_option(self, name, value, short=False, ns=None): - prefix = short and '-' or '--' - dest = self.options - if ':' in name: - name, ns = name.split(':') - dest = self.namespaces[ns] - dest[prefix + name] = value - - -def quote(v): - return "\\'".join("'" + p + "'" for p in v.split("'")) - - -def format_opt(opt, value): - if not value: - return opt - if opt.startswith('--'): - return '{0}={1}'.format(opt, value) - return '{0} {1}'.format(opt, value) - - -def parse_ns_range(ns, ranges=False): - ret = [] - for space in ',' in ns and ns.split(',') or [ns]: - if ranges and '-' in space: - start, stop = space.split('-') - ret.extend( - str(n) for n in range(int(start), int(stop) + 1) - ) - else: - ret.append(space) - return ret - - -def abbreviations(mapping): - - def expand(S): - ret = S - if S is not None: - for short_opt, long_opt in items(mapping): - ret = ret.replace(short_opt, long_opt) - return ret - - return expand - - -def findsig(args, default=signal.SIGTERM): - for arg in reversed(args): - if len(arg) == 2 and arg[0] == '-': - try: - return int(arg[1]) - except ValueError: - pass - if arg[0] == '-': - maybe_sig = 'SIG' + arg[1:] - if maybe_sig in SIGNAMES: - return getattr(signal, maybe_sig) - return default - - -def _getopt(d, alt): - for opt in alt: - try: - return d[opt] - except KeyError: - pass - raise KeyError(alt[0]) - - -def _setdefaultopt(d, alt, value): - for opt in alt[1:]: - try: - return d[opt] - except KeyError: - pass - return d.setdefault(alt[0], value) - - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/bin/worker.py b/awx/lib/site-packages/celery/bin/worker.py deleted file mode 100644 index bdc564d4f7..0000000000 --- a/awx/lib/site-packages/celery/bin/worker.py +++ /dev/null @@ -1,265 +0,0 @@ -# -*- coding: utf-8 -*- -""" - -The :program:`celery worker` command (previously known as ``celeryd``) - -.. program:: celery worker - -.. seealso:: - - See :ref:`preload-options`. - -.. cmdoption:: -c, --concurrency - - Number of child processes processing the queue. The default - is the number of CPUs available on your system. - -.. cmdoption:: -P, --pool - - Pool implementation: - - prefork (default), eventlet, gevent, solo or threads. - -.. cmdoption:: -f, --logfile - - Path to log file. If no logfile is specified, `stderr` is used. - -.. cmdoption:: -l, --loglevel - - Logging level, choose between `DEBUG`, `INFO`, `WARNING`, - `ERROR`, `CRITICAL`, or `FATAL`. - -.. cmdoption:: -n, --hostname - - Set custom hostname, e.g. 'w1.%h'. Expands: %h (hostname), - %n (name) and %d, (domain). - -.. cmdoption:: -B, --beat - - Also run the `celery beat` periodic task scheduler. Please note that - there must only be one instance of this service. - -.. cmdoption:: -Q, --queues - - List of queues to enable for this worker, separated by comma. - By default all configured queues are enabled. - Example: `-Q video,image` - -.. cmdoption:: -I, --include - - Comma separated list of additional modules to import. - Example: -I foo.tasks,bar.tasks - -.. cmdoption:: -s, --schedule - - Path to the schedule database if running with the `-B` option. - Defaults to `celerybeat-schedule`. The extension ".db" may be - appended to the filename. - -.. cmdoption:: -O - - Apply optimization profile. Supported: default, fair - -.. cmdoption:: --scheduler - - Scheduler class to use. Default is celery.beat.PersistentScheduler - -.. cmdoption:: -S, --statedb - - Path to the state database. The extension '.db' may - be appended to the filename. Default: {default} - -.. cmdoption:: -E, --events - - Send events that can be captured by monitors like :program:`celery events`, - `celerymon`, and others. - -.. cmdoption:: --without-gossip - - Do not subscribe to other workers events. - -.. cmdoption:: --without-mingle - - Do not synchronize with other workers at startup. - -.. cmdoption:: --without-heartbeat - - Do not send event heartbeats. - -.. cmdoption:: --purge - - Purges all waiting tasks before the daemon is started. - **WARNING**: This is unrecoverable, and the tasks will be - deleted from the messaging server. - -.. cmdoption:: --time-limit - - Enables a hard time limit (in seconds int/float) for tasks. - -.. cmdoption:: --soft-time-limit - - Enables a soft time limit (in seconds int/float) for tasks. - -.. cmdoption:: --maxtasksperchild - - Maximum number of tasks a pool worker can execute before it's - terminated and replaced by a new worker. - -.. cmdoption:: --pidfile - - Optional file used to store the workers pid. - - The worker will not start if this file already exists - and the pid is still alive. - -.. cmdoption:: --autoscale - - Enable autoscaling by providing - max_concurrency, min_concurrency. Example:: - - --autoscale=10,3 - - (always keep 3 processes, but grow to 10 if necessary) - -.. cmdoption:: --autoreload - - Enable autoreloading. - -.. cmdoption:: --no-execv - - Don't do execv after multiprocessing child fork. - -""" -from __future__ import absolute_import, unicode_literals - -import sys - -from celery import concurrency -from celery.bin.base import Command, Option, daemon_options -from celery.bin.celeryd_detach import detached_celeryd -from celery.five import string_t -from celery.platforms import maybe_drop_privileges -from celery.utils import default_nodename -from celery.utils.log import LOG_LEVELS, mlevel - -__all__ = ['worker', 'main'] - -__MODULE_DOC__ = __doc__ - - -class worker(Command): - """Start worker instance. - - Examples:: - - celery worker --app=proj -l info - celery worker -A proj -l info -Q hipri,lopri - - celery worker -A proj --concurrency=4 - celery worker -A proj --concurrency=1000 -P eventlet - - celery worker --autoscale=10,0 - """ - doc = __MODULE_DOC__ # parse help from this too - namespace = 'celeryd' - enable_config_from_cmdline = True - supports_args = False - - def run_from_argv(self, prog_name, argv=None, command=None): - command = sys.argv[0] if command is None else command - argv = sys.argv[1:] if argv is None else argv - # parse options before detaching so errors can be handled. - options, args = self.prepare_args( - *self.parse_options(prog_name, argv, command)) - self.maybe_detach([command] + sys.argv[1:]) - return self(*args, **options) - - def maybe_detach(self, argv, dopts=['-D', '--detach']): - if any(arg in argv for arg in dopts): - argv = [v for v in argv if v not in dopts] - # will never return - detached_celeryd(self.app).execute_from_commandline(argv) - raise SystemExit(0) - - def run(self, hostname=None, pool_cls=None, app=None, uid=None, gid=None, - loglevel=None, logfile=None, pidfile=None, state_db=None, - **kwargs): - maybe_drop_privileges(uid=uid, gid=gid) - # Pools like eventlet/gevent needs to patch libs as early - # as possible. - pool_cls = (concurrency.get_implementation(pool_cls) or - self.app.conf.CELERYD_POOL) - if self.app.IS_WINDOWS and kwargs.get('beat'): - self.die('-B option does not work on Windows. ' - 'Please run celery beat as a separate service.') - hostname = self.host_format(default_nodename(hostname)) - if loglevel: - try: - loglevel = mlevel(loglevel) - except KeyError: # pragma: no cover - self.die('Unknown level {0!r}. Please use one of {1}.'.format( - loglevel, '|'.join( - l for l in LOG_LEVELS if isinstance(l, string_t)))) - - return self.app.Worker( - hostname=hostname, pool_cls=pool_cls, loglevel=loglevel, - logfile=logfile, # node format handled by celery.app.log.setup - pidfile=self.node_format(pidfile, hostname), - state_db=self.node_format(state_db, hostname), **kwargs - ).start() - - def with_pool_option(self, argv): - # this command support custom pools - # that may have to be loaded as early as possible. - return (['-P'], ['--pool']) - - def get_options(self): - conf = self.app.conf - return ( - Option('-c', '--concurrency', - default=conf.CELERYD_CONCURRENCY, type='int'), - Option('-P', '--pool', default=conf.CELERYD_POOL, dest='pool_cls'), - Option('--purge', '--discard', default=False, action='store_true'), - Option('-l', '--loglevel', default=conf.CELERYD_LOG_LEVEL), - Option('-n', '--hostname'), - Option('-B', '--beat', action='store_true'), - Option('-s', '--schedule', dest='schedule_filename', - default=conf.CELERYBEAT_SCHEDULE_FILENAME), - Option('--scheduler', dest='scheduler_cls'), - Option('-S', '--statedb', - default=conf.CELERYD_STATE_DB, dest='state_db'), - Option('-E', '--events', default=conf.CELERY_SEND_EVENTS, - action='store_true', dest='send_events'), - Option('--time-limit', type='float', dest='task_time_limit', - default=conf.CELERYD_TASK_TIME_LIMIT), - Option('--soft-time-limit', dest='task_soft_time_limit', - default=conf.CELERYD_TASK_SOFT_TIME_LIMIT, type='float'), - Option('--maxtasksperchild', dest='max_tasks_per_child', - default=conf.CELERYD_MAX_TASKS_PER_CHILD, type='int'), - Option('--queues', '-Q', default=[]), - Option('--exclude-queues', '-X', default=[]), - Option('--include', '-I', default=[]), - Option('--autoscale'), - Option('--autoreload', action='store_true'), - Option('--no-execv', action='store_true', default=False), - Option('--without-gossip', action='store_true', default=False), - Option('--without-mingle', action='store_true', default=False), - Option('--without-heartbeat', action='store_true', default=False), - Option('-O', dest='optimization'), - Option('-D', '--detach', action='store_true'), - ) + daemon_options() + tuple(self.app.user_options['worker']) - - -def main(app=None): - # Fix for setuptools generated scripts, so that it will - # work with multiprocessing fork emulation. - # (see multiprocessing.forking.get_preparation_data()) - if __name__ != '__main__': # pragma: no cover - sys.modules['__main__'] = sys.modules[__name__] - from billiard import freeze_support - freeze_support() - worker(app=app).execute_from_commandline() - - -if __name__ == '__main__': # pragma: no cover - main() diff --git a/awx/lib/site-packages/celery/bootsteps.py b/awx/lib/site-packages/celery/bootsteps.py deleted file mode 100644 index 9c0427fe69..0000000000 --- a/awx/lib/site-packages/celery/bootsteps.py +++ /dev/null @@ -1,421 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.bootsteps - ~~~~~~~~~~~~~~~~ - - A directed acyclic graph of reusable components. - -""" -from __future__ import absolute_import, unicode_literals - -from collections import deque -from threading import Event - -from kombu.common import ignore_errors -from kombu.utils import symbol_by_name - -from .datastructures import DependencyGraph, GraphFormatter -from .five import values, with_metaclass -from .utils.imports import instantiate, qualname -from .utils.log import get_logger - -try: - from greenlet import GreenletExit - IGNORE_ERRORS = (GreenletExit, ) -except ImportError: # pragma: no cover - IGNORE_ERRORS = () - -__all__ = ['Blueprint', 'Step', 'StartStopStep', 'ConsumerStep'] - -#: States -RUN = 0x1 -CLOSE = 0x2 -TERMINATE = 0x3 - -logger = get_logger(__name__) -debug = logger.debug - - -def _pre(ns, fmt): - return '| {0}: {1}'.format(ns.alias, fmt) - - -def _label(s): - return s.name.rsplit('.', 1)[-1] - - -class StepFormatter(GraphFormatter): - """Graph formatter for :class:`Blueprint`.""" - - blueprint_prefix = '⧉' - conditional_prefix = '∘' - blueprint_scheme = { - 'shape': 'parallelogram', - 'color': 'slategray4', - 'fillcolor': 'slategray3', - } - - def label(self, step): - return step and '{0}{1}'.format( - self._get_prefix(step), - (step.label or _label(step)).encode('utf-8', 'ignore'), - ) - - def _get_prefix(self, step): - if step.last: - return self.blueprint_prefix - if step.conditional: - return self.conditional_prefix - return '' - - def node(self, obj, **attrs): - scheme = self.blueprint_scheme if obj.last else self.node_scheme - return self.draw_node(obj, scheme, attrs) - - def edge(self, a, b, **attrs): - if a.last: - attrs.update(arrowhead='none', color='darkseagreen3') - return self.draw_edge(a, b, self.edge_scheme, attrs) - - -class Blueprint(object): - """Blueprint containing bootsteps that can be applied to objects. - - :keyword steps: List of steps. - :keyword name: Set explicit name for this blueprint. - :keyword app: Set the Celery app for this blueprint. - :keyword on_start: Optional callback applied after blueprint start. - :keyword on_close: Optional callback applied before blueprint close. - :keyword on_stopped: Optional callback applied after blueprint stopped. - - """ - GraphFormatter = StepFormatter - - name = None - state = None - started = 0 - default_steps = set() - state_to_name = { - 0: 'initializing', - RUN: 'running', - CLOSE: 'closing', - TERMINATE: 'terminating', - } - - def __init__(self, steps=None, name=None, app=None, - on_start=None, on_close=None, on_stopped=None): - self.app = app - self.name = name or self.name or qualname(type(self)) - self.types = set(steps or []) | set(self.default_steps) - self.on_start = on_start - self.on_close = on_close - self.on_stopped = on_stopped - self.shutdown_complete = Event() - self.steps = {} - - def start(self, parent): - self.state = RUN - if self.on_start: - self.on_start() - for i, step in enumerate(s for s in parent.steps if s is not None): - self._debug('Starting %s', step.alias) - self.started = i + 1 - step.start(parent) - debug('^-- substep ok') - - def human_state(self): - return self.state_to_name[self.state or 0] - - def info(self, parent): - info = {} - for step in parent.steps: - info.update(step.info(parent) or {}) - return info - - def close(self, parent): - if self.on_close: - self.on_close() - self.send_all(parent, 'close', 'closing', reverse=False) - - def restart(self, parent, method='stop', - description='restarting', propagate=False): - self.send_all(parent, method, description, propagate=propagate) - - def send_all(self, parent, method, - description=None, reverse=True, propagate=True, args=()): - description = description or method.replace('_', ' ') - steps = reversed(parent.steps) if reverse else parent.steps - for step in steps: - if step: - fun = getattr(step, method, None) - if fun is not None: - self._debug('%s %s...', - description.capitalize(), step.alias) - try: - fun(parent, *args) - except Exception as exc: - if propagate: - raise - logger.error( - 'Error on %s %s: %r', - description, step.alias, exc, exc_info=1, - ) - - def stop(self, parent, close=True, terminate=False): - what = 'terminating' if terminate else 'stopping' - if self.state in (CLOSE, TERMINATE): - return - - if self.state != RUN or self.started != len(parent.steps): - # Not fully started, can safely exit. - self.state = TERMINATE - self.shutdown_complete.set() - return - self.close(parent) - self.state = CLOSE - - self.restart( - parent, 'terminate' if terminate else 'stop', - description=what, propagate=False, - ) - - if self.on_stopped: - self.on_stopped() - self.state = TERMINATE - self.shutdown_complete.set() - - def join(self, timeout=None): - try: - # Will only get here if running green, - # makes sure all greenthreads have exited. - self.shutdown_complete.wait(timeout=timeout) - except IGNORE_ERRORS: - pass - - def apply(self, parent, **kwargs): - """Apply the steps in this blueprint to an object. - - This will apply the ``__init__`` and ``include`` methods - of each step, with the object as argument:: - - step = Step(obj) - ... - step.include(obj) - - For :class:`StartStopStep` the services created - will also be added to the objects ``steps`` attribute. - - """ - self._debug('Preparing bootsteps.') - order = self.order = [] - steps = self.steps = self.claim_steps() - - self._debug('Building graph...') - for S in self._finalize_steps(steps): - step = S(parent, **kwargs) - steps[step.name] = step - order.append(step) - self._debug('New boot order: {%s}', - ', '.join(s.alias for s in self.order)) - for step in order: - step.include(parent) - return self - - def connect_with(self, other): - self.graph.adjacent.update(other.graph.adjacent) - self.graph.add_edge(type(other.order[0]), type(self.order[-1])) - - def __getitem__(self, name): - return self.steps[name] - - def _find_last(self): - return next((C for C in values(self.steps) if C.last), None) - - def _firstpass(self, steps): - stream = deque(step.requires for step in values(steps)) - while stream: - for node in stream.popleft(): - node = symbol_by_name(node) - if node.name not in self.steps: - steps[node.name] = node - stream.append(node.requires) - - def _finalize_steps(self, steps): - last = self._find_last() - self._firstpass(steps) - it = ((C, C.requires) for C in values(steps)) - G = self.graph = DependencyGraph( - it, formatter=self.GraphFormatter(root=last), - ) - if last: - for obj in G: - if obj != last: - G.add_edge(last, obj) - try: - return G.topsort() - except KeyError as exc: - raise KeyError('unknown bootstep: %s' % exc) - - def claim_steps(self): - return dict(self.load_step(step) for step in self._all_steps()) - - def _all_steps(self): - return self.types | self.app.steps[self.name.lower()] - - def load_step(self, step): - step = symbol_by_name(step) - return step.name, step - - def _debug(self, msg, *args): - return debug(_pre(self, msg), *args) - - @property - def alias(self): - return _label(self) - - -class StepType(type): - """Metaclass for steps.""" - - def __new__(cls, name, bases, attrs): - module = attrs.get('__module__') - qname = '{0}.{1}'.format(module, name) if module else name - attrs.update( - __qualname__=qname, - name=attrs.get('name') or qname, - requires=attrs.get('requires', ()), - ) - return super(StepType, cls).__new__(cls, name, bases, attrs) - - def __str__(self): - return self.name - - def __repr__(self): - return 'step:{0.name}{{{0.requires!r}}}'.format(self) - - -@with_metaclass(StepType) -class Step(object): - """A Bootstep. - - The :meth:`__init__` method is called when the step - is bound to a parent object, and can as such be used - to initialize attributes in the parent object at - parent instantiation-time. - - """ - - #: Optional step name, will use qualname if not specified. - name = None - - #: Optional short name used for graph outputs and in logs. - label = None - - #: Set this to true if the step is enabled based on some condition. - conditional = False - - #: List of other steps that that must be started before this step. - #: Note that all dependencies must be in the same blueprint. - requires = () - - #: This flag is reserved for the workers Consumer, - #: since it is required to always be started last. - #: There can only be one object marked last - #: in every blueprint. - last = False - - #: This provides the default for :meth:`include_if`. - enabled = True - - def __init__(self, parent, **kwargs): - pass - - def include_if(self, parent): - """An optional predicate that decides whether this - step should be created.""" - return self.enabled - - def instantiate(self, name, *args, **kwargs): - return instantiate(name, *args, **kwargs) - - def _should_include(self, parent): - if self.include_if(parent): - return True, self.create(parent) - return False, None - - def include(self, parent): - return self._should_include(parent)[0] - - def create(self, parent): - """Create the step.""" - pass - - def __repr__(self): - return '<step: {0.alias}>'.format(self) - - @property - def alias(self): - return self.label or _label(self) - - def info(self, obj): - pass - - -class StartStopStep(Step): - - #: Optional obj created by the :meth:`create` method. - #: This is used by :class:`StartStopStep` to keep the - #: original service object. - obj = None - - def start(self, parent): - if self.obj: - return self.obj.start() - - def stop(self, parent): - if self.obj: - return self.obj.stop() - - def close(self, parent): - pass - - def terminate(self, parent): - if self.obj: - return getattr(self.obj, 'terminate', self.obj.stop)() - - def include(self, parent): - inc, ret = self._should_include(parent) - if inc: - self.obj = ret - parent.steps.append(self) - return inc - - -class ConsumerStep(StartStopStep): - requires = ('celery.worker.consumer:Connection', ) - consumers = None - - def get_consumers(self, channel): - raise NotImplementedError('missing get_consumers') - - def start(self, c): - channel = c.connection.channel() - self.consumers = self.get_consumers(channel) - for consumer in self.consumers or []: - consumer.consume() - - def stop(self, c): - self._close(c, True) - - def shutdown(self, c): - self._close(c, False) - - def _close(self, c, cancel_consumers=True): - channels = set() - for consumer in self.consumers or []: - if cancel_consumers: - ignore_errors(c.connection, consumer.cancel) - if consumer.channel: - channels.add(consumer.channel) - for channel in channels: - ignore_errors(c.connection, channel.close) diff --git a/awx/lib/site-packages/celery/canvas.py b/awx/lib/site-packages/celery/canvas.py deleted file mode 100644 index cabc5070c8..0000000000 --- a/awx/lib/site-packages/celery/canvas.py +++ /dev/null @@ -1,661 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.canvas - ~~~~~~~~~~~~~ - - Composing task workflows. - - Documentation for some of these types are in :mod:`celery`. - You should import these from :mod:`celery` and not this module. - - -""" -from __future__ import absolute_import - -from copy import deepcopy -from functools import partial as _partial, reduce -from operator import itemgetter -from itertools import chain as _chain - -from kombu.utils import cached_property, fxrange, kwdict, reprcall, uuid - -from celery._state import current_app -from celery.utils.functional import ( - maybe_list, is_list, regen, - chunks as _chunks, -) -from celery.utils.text import truncate - -__all__ = ['Signature', 'chain', 'xmap', 'xstarmap', 'chunks', - 'group', 'chord', 'signature', 'maybe_signature'] - - -class _getitem_property(object): - """Attribute -> dict key descriptor. - - The target object must support ``__getitem__``, - and optionally ``__setitem__``. - - Example: - - >>> from collections import defaultdict - - >>> class Me(dict): - ... deep = defaultdict(dict) - ... - ... foo = _getitem_property('foo') - ... deep_thing = _getitem_property('deep.thing') - - - >>> me = Me() - >>> me.foo - None - - >>> me.foo = 10 - >>> me.foo - 10 - >>> me['foo'] - 10 - - >>> me.deep_thing = 42 - >>> me.deep_thing - 42 - >>> me.deep - defaultdict(<type 'dict'>, {'thing': 42}) - - """ - - def __init__(self, keypath): - path, _, self.key = keypath.rpartition('.') - self.path = path.split('.') if path else None - - def _path(self, obj): - return (reduce(lambda d, k: d[k], [obj] + self.path) if self.path - else obj) - - def __get__(self, obj, type=None): - if obj is None: - return type - return self._path(obj).get(self.key) - - def __set__(self, obj, value): - self._path(obj)[self.key] = value - - -def maybe_unroll_group(g): - """Unroll group with only one member.""" - # Issue #1656 - try: - size = len(g.tasks) - except TypeError: - try: - size = g.tasks.__length_hint__() - except (AttributeError, TypeError): - pass - else: - return list(g.tasks)[0] if size == 1 else g - else: - return g.tasks[0] if size == 1 else g - - -class Signature(dict): - """Class that wraps the arguments and execution options - for a single task invocation. - - Used as the parts in a :class:`group` and other constructs, - or to pass tasks around as callbacks while being compatible - with serializers with a strict type subset. - - :param task: Either a task class/instance, or the name of a task. - :keyword args: Positional arguments to apply. - :keyword kwargs: Keyword arguments to apply. - :keyword options: Additional options to :meth:`Task.apply_async`. - - Note that if the first argument is a :class:`dict`, the other - arguments will be ignored and the values in the dict will be used - instead. - - >>> s = signature('tasks.add', args=(2, 2)) - >>> signature(s) - {'task': 'tasks.add', args=(2, 2), kwargs={}, options={}} - - """ - TYPES = {} - _app = _type = None - - @classmethod - def register_type(cls, subclass, name=None): - cls.TYPES[name or subclass.__name__] = subclass - return subclass - - @classmethod - def from_dict(self, d, app=None): - typ = d.get('subtask_type') - if typ: - return self.TYPES[typ].from_dict(kwdict(d), app=app) - return Signature(d, app=app) - - def __init__(self, task=None, args=None, kwargs=None, options=None, - type=None, subtask_type=None, immutable=False, - app=None, **ex): - self._app = app - init = dict.__init__ - - if isinstance(task, dict): - return init(self, task) # works like dict(d) - - # Also supports using task class/instance instead of string name. - try: - task_name = task.name - except AttributeError: - task_name = task - else: - self._type = task - - init(self, - task=task_name, args=tuple(args or ()), - kwargs=kwargs or {}, - options=dict(options or {}, **ex), - subtask_type=subtask_type, - immutable=immutable) - - def __call__(self, *partial_args, **partial_kwargs): - args, kwargs, _ = self._merge(partial_args, partial_kwargs, None) - return self.type(*args, **kwargs) - - def delay(self, *partial_args, **partial_kwargs): - return self.apply_async(partial_args, partial_kwargs) - - def apply(self, args=(), kwargs={}, **options): - """Apply this task locally.""" - # For callbacks: extra args are prepended to the stored args. - args, kwargs, options = self._merge(args, kwargs, options) - return self.type.apply(args, kwargs, **options) - - def _merge(self, args=(), kwargs={}, options={}): - if self.immutable: - return (self.args, self.kwargs, - dict(self.options, **options) if options else self.options) - return (tuple(args) + tuple(self.args) if args else self.args, - dict(self.kwargs, **kwargs) if kwargs else self.kwargs, - dict(self.options, **options) if options else self.options) - - def clone(self, args=(), kwargs={}, **opts): - # need to deepcopy options so origins links etc. is not modified. - if args or kwargs or opts: - args, kwargs, opts = self._merge(args, kwargs, opts) - else: - args, kwargs, opts = self.args, self.kwargs, self.options - s = Signature.from_dict({'task': self.task, 'args': tuple(args), - 'kwargs': kwargs, 'options': deepcopy(opts), - 'subtask_type': self.subtask_type, - 'immutable': self.immutable}, app=self._app) - s._type = self._type - return s - partial = clone - - def freeze(self, _id=None, group_id=None, chord=None): - opts = self.options - try: - tid = opts['task_id'] - except KeyError: - tid = opts['task_id'] = _id or uuid() - if 'reply_to' not in opts: - opts['reply_to'] = self.app.oid - if group_id: - opts['group_id'] = group_id - if chord: - opts['chord'] = chord - return self.AsyncResult(tid) - _freeze = freeze - - def replace(self, args=None, kwargs=None, options=None): - s = self.clone() - if args is not None: - s.args = args - if kwargs is not None: - s.kwargs = kwargs - if options is not None: - s.options = options - return s - - def set(self, immutable=None, **options): - if immutable is not None: - self.set_immutable(immutable) - self.options.update(options) - return self - - def set_immutable(self, immutable): - self.immutable = immutable - - def apply_async(self, args=(), kwargs={}, **options): - try: - _apply = self._apply_async - except IndexError: # no tasks for chain, etc to find type - return - # For callbacks: extra args are prepended to the stored args. - if args or kwargs or options: - args, kwargs, options = self._merge(args, kwargs, options) - else: - args, kwargs, options = self.args, self.kwargs, self.options - return _apply(args, kwargs, **options) - - def append_to_list_option(self, key, value): - items = self.options.setdefault(key, []) - if value not in items: - items.append(value) - return value - - def link(self, callback): - return self.append_to_list_option('link', callback) - - def link_error(self, errback): - return self.append_to_list_option('link_error', errback) - - def flatten_links(self): - return list(_chain.from_iterable(_chain( - [[self]], - (link.flatten_links() - for link in maybe_list(self.options.get('link')) or []) - ))) - - def __or__(self, other): - if isinstance(other, group): - other = maybe_unroll_group(other) - if not isinstance(self, chain) and isinstance(other, chain): - return chain((self, ) + other.tasks, app=self._app) - elif isinstance(other, chain): - return chain(*self.tasks + other.tasks, app=self._app) - elif isinstance(other, Signature): - if isinstance(self, chain): - return chain(*self.tasks + (other, ), app=self._app) - return chain(self, other, app=self._app) - return NotImplemented - - def __deepcopy__(self, memo): - memo[id(self)] = self - return dict(self) - - def __invert__(self): - return self.apply_async().get() - - def __reduce__(self): - # for serialization, the task type is lazily loaded, - # and not stored in the dict itself. - return subtask, (dict(self), ) - - def reprcall(self, *args, **kwargs): - args, kwargs, _ = self._merge(args, kwargs, {}) - return reprcall(self['task'], args, kwargs) - - def election(self): - type = self.type - app = type.app - tid = self.options.get('task_id') or uuid() - - with app.producer_or_acquire(None) as P: - props = type.backend.on_task_call(P, tid) - app.control.election(tid, 'task', self.clone(task_id=tid, **props), - connection=P.connection) - return type.AsyncResult(tid) - - def __repr__(self): - return self.reprcall() - - @cached_property - def type(self): - return self._type or self.app.tasks[self['task']] - - @cached_property - def app(self): - return self._app or current_app - - @cached_property - def AsyncResult(self): - try: - return self.type.AsyncResult - except KeyError: # task not registered - return self.app.AsyncResult - - @cached_property - def _apply_async(self): - try: - return self.type.apply_async - except KeyError: - return _partial(self.app.send_task, self['task']) - id = _getitem_property('options.task_id') - task = _getitem_property('task') - args = _getitem_property('args') - kwargs = _getitem_property('kwargs') - options = _getitem_property('options') - subtask_type = _getitem_property('subtask_type') - immutable = _getitem_property('immutable') - - -@Signature.register_type -class chain(Signature): - - def __init__(self, *tasks, **options): - tasks = (regen(tasks[0]) if len(tasks) == 1 and is_list(tasks[0]) - else tasks) - Signature.__init__( - self, 'celery.chain', (), {'tasks': tasks}, **options - ) - self.tasks = tasks - self.subtask_type = 'chain' - - def __call__(self, *args, **kwargs): - if self.tasks: - return self.apply_async(args, kwargs) - - @classmethod - def from_dict(self, d, app=None): - tasks = d['kwargs']['tasks'] - if d['args'] and tasks: - # partial args passed on to first task in chain (Issue #1057). - tasks[0]['args'] = tasks[0]._merge(d['args'])[0] - return chain(*d['kwargs']['tasks'], app=app, **kwdict(d['options'])) - - @property - def type(self): - try: - return self._type or self.tasks[0].type.app.tasks['celery.chain'] - except KeyError: - return self.app.tasks['celery.chain'] - - def __repr__(self): - return ' | '.join(repr(t) for t in self.tasks) - - -class _basemap(Signature): - _task_name = None - _unpack_args = itemgetter('task', 'it') - - def __init__(self, task, it, **options): - Signature.__init__( - self, self._task_name, (), - {'task': task, 'it': regen(it)}, immutable=True, **options - ) - - def apply_async(self, args=(), kwargs={}, **opts): - # need to evaluate generators - task, it = self._unpack_args(self.kwargs) - return self.type.apply_async( - (), {'task': task, 'it': list(it)}, **opts - ) - - @classmethod - def from_dict(cls, d, app=None): - return cls(*cls._unpack_args(d['kwargs']), app=app, **d['options']) - - -@Signature.register_type -class xmap(_basemap): - _task_name = 'celery.map' - - def __repr__(self): - task, it = self._unpack_args(self.kwargs) - return '[{0}(x) for x in {1}]'.format(task.task, - truncate(repr(it), 100)) - - -@Signature.register_type -class xstarmap(_basemap): - _task_name = 'celery.starmap' - - def __repr__(self): - task, it = self._unpack_args(self.kwargs) - return '[{0}(*x) for x in {1}]'.format(task.task, - truncate(repr(it), 100)) - - -@Signature.register_type -class chunks(Signature): - _unpack_args = itemgetter('task', 'it', 'n') - - def __init__(self, task, it, n, **options): - Signature.__init__( - self, 'celery.chunks', (), - {'task': task, 'it': regen(it), 'n': n}, - immutable=True, **options - ) - - @classmethod - def from_dict(self, d, app=None): - return chunks(*self._unpack_args(d['kwargs']), app=app, **d['options']) - - def apply_async(self, args=(), kwargs={}, **opts): - return self.group().apply_async(args, kwargs, **opts) - - def __call__(self, **options): - return self.group()(**options) - - def group(self): - # need to evaluate generators - task, it, n = self._unpack_args(self.kwargs) - return group((xstarmap(task, part, app=self._app) - for part in _chunks(iter(it), n)), - app=self._app) - - @classmethod - def apply_chunks(cls, task, it, n, app=None): - return cls(task, it, n, app=app)() - - -def _maybe_group(tasks): - if isinstance(tasks, group): - tasks = list(tasks.tasks) - elif isinstance(tasks, Signature): - tasks = [tasks] - else: - tasks = regen(tasks) - return tasks - - -def _maybe_clone(tasks, app): - return [s.clone() if isinstance(s, Signature) else signature(s, app=app) - for s in tasks] - - -@Signature.register_type -class group(Signature): - - def __init__(self, *tasks, **options): - if len(tasks) == 1: - tasks = _maybe_group(tasks[0]) - Signature.__init__( - self, 'celery.group', (), {'tasks': tasks}, **options - ) - self.tasks, self.subtask_type = tasks, 'group' - - @classmethod - def from_dict(self, d, app=None): - tasks = d['kwargs']['tasks'] - if d['args'] and tasks: - # partial args passed on to all tasks in the group (Issue #1057). - for task in tasks: - task['args'] = task._merge(d['args'])[0] - return group(tasks, app=app, **kwdict(d['options'])) - - def apply_async(self, args=(), kwargs=None, **options): - tasks = _maybe_clone(self.tasks, app=self._app) - if not tasks: - return self.freeze() - type = self.type - return type(*type.prepare(dict(self.options, **options), - tasks, args)) - - def set_immutable(self, immutable): - for task in self.tasks: - task.set_immutable(immutable) - - def link(self, sig): - # Simply link to first task - sig = sig.clone().set(immutable=True) - return self.tasks[0].link(sig) - - def link_error(self, sig): - sig = sig.clone().set(immutable=True) - return self.tasks[0].link_error(sig) - - def apply(self, *args, **kwargs): - if not self.tasks: - return self.freeze() # empty group returns GroupResult - return Signature.apply(self, *args, **kwargs) - - def __call__(self, *partial_args, **options): - return self.apply_async(partial_args, **options) - - def freeze(self, _id=None, group_id=None, chord=None): - opts = self.options - try: - gid = opts['task_id'] - except KeyError: - gid = opts['task_id'] = uuid() - if group_id: - opts['group_id'] = group_id - if chord: - opts['chord'] = group_id - new_tasks, results = [], [] - for task in self.tasks: - task = maybe_signature(task, app=self._app).clone() - results.append(task.freeze(group_id=group_id, chord=chord)) - new_tasks.append(task) - self.tasks = self.kwargs['tasks'] = new_tasks - return self.app.GroupResult(gid, results) - _freeze = freeze - - def skew(self, start=1.0, stop=None, step=1.0): - it = fxrange(start, stop, step, repeatlast=True) - for task in self.tasks: - task.set(countdown=next(it)) - return self - - def __iter__(self): - return iter(self.tasks) - - def __repr__(self): - return repr(self.tasks) - - @property - def type(self): - if self._type: - return self._type - # taking the app from the first task in the list, there may be a - # better solution for this, e.g. to consolidate tasks with the same - # app and apply them in batches. - app = self._app if self._app else self.tasks[0].type.app - return app.tasks[self['task']] - - -@Signature.register_type -class chord(Signature): - - def __init__(self, header, body=None, task='celery.chord', - args=(), kwargs={}, **options): - Signature.__init__( - self, task, args, - dict(kwargs, header=_maybe_group(header), - body=maybe_signature(body, app=self._app)), **options - ) - self.subtask_type = 'chord' - - def freeze(self, _id=None, group_id=None, chord=None): - return self.body.freeze(_id, group_id=group_id, chord=chord) - - @classmethod - def from_dict(self, d, app=None): - args, d['kwargs'] = self._unpack_args(**kwdict(d['kwargs'])) - return self(*args, app=app, **kwdict(d)) - - @staticmethod - def _unpack_args(header=None, body=None, **kwargs): - # Python signatures are better at extracting keys from dicts - # than manually popping things off. - return (header, body), kwargs - - @property - def type(self): - if self._type: - return self._type - # we will be able to fix this mess in 3.2 when we no longer - # require an actual task implementation for chord/group - if self._app: - app = self._app - else: - try: - app = self.tasks[0].type.app - except IndexError: - app = self.body.type.app - return app.tasks['celery.chord'] - - def apply_async(self, args=(), kwargs={}, task_id=None, - producer=None, publisher=None, connection=None, - router=None, result_cls=None, **options): - body = kwargs.get('body') or self.kwargs['body'] - kwargs = dict(self.kwargs, **kwargs) - body = body.clone(**options) - - _chord = self.type - if _chord.app.conf.CELERY_ALWAYS_EAGER: - return self.apply((), kwargs, task_id=task_id, **options) - res = body.freeze(task_id) - parent = _chord(self.tasks, body, args, **options) - res.parent = parent - return res - - def __call__(self, body=None, **options): - return self.apply_async((), {'body': body} if body else {}, **options) - - def clone(self, *args, **kwargs): - s = Signature.clone(self, *args, **kwargs) - # need to make copy of body - try: - s.kwargs['body'] = s.kwargs['body'].clone() - except (AttributeError, KeyError): - pass - return s - - def link(self, callback): - self.body.link(callback) - return callback - - def link_error(self, errback): - self.body.link_error(errback) - return errback - - def set_immutable(self, immutable): - # changes mutability of header only, not callback. - for task in self.tasks: - task.set_immutable(immutable) - - def __repr__(self): - if self.body: - return self.body.reprcall(self.tasks) - return '<chord without body: {0.tasks!r}>'.format(self) - - tasks = _getitem_property('kwargs.header') - body = _getitem_property('kwargs.body') - - -def signature(varies, *args, **kwargs): - if not (args or kwargs) and isinstance(varies, dict): - if isinstance(varies, Signature): - return varies.clone() - return Signature.from_dict(varies) - return Signature(varies, *args, **kwargs) -subtask = signature # XXX compat - - -def maybe_signature(d, app=None): - if d is not None: - if isinstance(d, dict): - if not isinstance(d, Signature): - return signature(d, app=app) - elif isinstance(d, list): - return [maybe_signature(s, app=app) for s in d] - if app is not None: - d._app = app - return d - -maybe_subtask = maybe_signature # XXX compat diff --git a/awx/lib/site-packages/celery/concurrency/__init__.py b/awx/lib/site-packages/celery/concurrency/__init__.py deleted file mode 100644 index c58fdbc004..0000000000 --- a/awx/lib/site-packages/celery/concurrency/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency - ~~~~~~~~~~~~~~~~~~ - - Pool implementation abstract factory, and alias definitions. - -""" -from __future__ import absolute_import - -# Import from kombu directly as it's used -# early in the import stage, where celery.utils loads -# too much (e.g. for eventlet patching) -from kombu.utils import symbol_by_name - -__all__ = ['get_implementation'] - -ALIASES = { - 'prefork': 'celery.concurrency.prefork:TaskPool', - 'eventlet': 'celery.concurrency.eventlet:TaskPool', - 'gevent': 'celery.concurrency.gevent:TaskPool', - 'threads': 'celery.concurrency.threads:TaskPool', - 'solo': 'celery.concurrency.solo:TaskPool', - 'processes': 'celery.concurrency.prefork:TaskPool', # XXX compat alias -} - - -def get_implementation(cls): - return symbol_by_name(cls, ALIASES) diff --git a/awx/lib/site-packages/celery/concurrency/asynpool.py b/awx/lib/site-packages/celery/concurrency/asynpool.py deleted file mode 100644 index 5c4d5855c9..0000000000 --- a/awx/lib/site-packages/celery/concurrency/asynpool.py +++ /dev/null @@ -1,1212 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency.asynpool - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - .. note:: - - This module will be moved soon, so don't use it directly. - - Non-blocking version of :class:`multiprocessing.Pool`. - - This code deals with three major challenges: - - 1) Starting up child processes and keeping them running. - 2) Sending jobs to the processes and receiving results back. - 3) Safely shutting down this system. - -""" -from __future__ import absolute_import - -import errno -import os -import random -import select -import socket -import struct -import sys -import time - -from collections import deque, namedtuple -from io import BytesIO -from pickle import HIGHEST_PROTOCOL -from time import sleep -from weakref import WeakValueDictionary, ref - -from amqp.utils import promise -from billiard.pool import RUN, TERMINATE, ACK, NACK, WorkersJoined -from billiard import pool as _pool -from billiard.compat import buf_t, setblocking, isblocking -from billiard.einfo import ExceptionInfo -from billiard.queues import _SimpleQueue -from kombu.async import READ, WRITE, ERR -from kombu.serialization import pickle as _pickle -from kombu.utils import fxrange -from kombu.utils.compat import get_errno -from kombu.utils.eventio import SELECT_BAD_FD -from celery.five import Counter, items, values -from celery.utils.log import get_logger -from celery.utils.text import truncate -from celery.worker import state as worker_state - -try: - from _billiard import read as __read__ - from struct import unpack_from as _unpack_from - memoryview = memoryview - readcanbuf = True - - if sys.version_info[0] == 2 and sys.version_info < (2, 7, 6): - - def unpack_from(fmt, view, _unpack_from=_unpack_from): # noqa - return _unpack_from(fmt, view.tobytes()) # <- memoryview - else: - # unpack_from supports memoryview in 2.7.6 and 3.3+ - unpack_from = _unpack_from # noqa - -except (ImportError, NameError): # pragma: no cover - - def __read__(fd, buf, size, read=os.read): # noqa - chunk = read(fd, size) - n = len(chunk) - if n != 0: - buf.write(chunk) - return n - readcanbuf = False # noqa - - def unpack_from(fmt, iobuf, unpack=struct.unpack): # noqa - return unpack(fmt, iobuf.getvalue()) # <-- BytesIO - - -logger = get_logger(__name__) -error, debug = logger.error, logger.debug - -UNAVAIL = frozenset([errno.EAGAIN, errno.EINTR]) - -#: Constant sent by child process when started (ready to accept work) -WORKER_UP = 15 - -#: A process must have started before this timeout (in secs.) expires. -PROC_ALIVE_TIMEOUT = 4.0 - -SCHED_STRATEGY_PREFETCH = 1 -SCHED_STRATEGY_FAIR = 4 - -SCHED_STRATEGIES = { - None: SCHED_STRATEGY_PREFETCH, - 'fair': SCHED_STRATEGY_FAIR, -} - -RESULT_MAXLEN = 128 - -Ack = namedtuple('Ack', ('id', 'fd', 'payload')) - - -def gen_not_started(gen): - # gi_frame is None when generator stopped. - return gen.gi_frame and gen.gi_frame.f_lasti == -1 - - -def _get_job_writer(job): - try: - writer = job._writer - except AttributeError: - pass - else: - return writer() # is a weakref - - -def _select(readers=None, writers=None, err=None, timeout=0): - """Simple wrapper to :class:`~select.select`. - - :param readers: Set of reader fds to test if readable. - :param writers: Set of writer fds to test if writable. - :param err: Set of fds to test for error condition. - - All fd sets passed must be mutable as this function - will remove non-working fds from them, this also means - the caller must make sure there are still fds in the sets - before calling us again. - - :returns: tuple of ``(readable, writable, again)``, where - ``readable`` is a set of fds that have data available for read, - ``writable`` is a set of fds that is ready to be written to - and ``again`` is a flag that if set means the caller must - throw away the result and call us again. - - """ - readers = set() if readers is None else readers - writers = set() if writers is None else writers - err = set() if err is None else err - try: - r, w, e = select.select(readers, writers, err, timeout) - if e: - r = list(set(r) | set(e)) - return r, w, 0 - except (select.error, socket.error) as exc: - if get_errno(exc) == errno.EINTR: - return [], [], 1 - elif get_errno(exc) in SELECT_BAD_FD: - for fd in readers | writers | err: - try: - select.select([fd], [], [], 0) - except (select.error, socket.error) as exc: - if get_errno(exc) not in SELECT_BAD_FD: - raise - readers.discard(fd) - writers.discard(fd) - err.discard(fd) - return [], [], 1 - else: - raise - - -class Worker(_pool.Worker): - """Pool worker process.""" - dead = False - - def on_loop_start(self, pid): - # our version sends a WORKER_UP message when the process is ready - # to accept work, this will tell the parent that the inqueue fd - # is writable. - self.outq.put((WORKER_UP, (pid, ))) - - def prepare_result(self, result, RESULT_MAXLEN=RESULT_MAXLEN): - if not isinstance(result, ExceptionInfo): - return truncate(repr(result), RESULT_MAXLEN) - return result - - -class ResultHandler(_pool.ResultHandler): - """Handles messages from the pool processes.""" - - def __init__(self, *args, **kwargs): - self.fileno_to_outq = kwargs.pop('fileno_to_outq') - self.on_process_alive = kwargs.pop('on_process_alive') - super(ResultHandler, self).__init__(*args, **kwargs) - # add our custom message handler - self.state_handlers[WORKER_UP] = self.on_process_alive - - def _recv_message(self, add_reader, fd, callback, - __read__=__read__, readcanbuf=readcanbuf, - BytesIO=BytesIO, unpack_from=unpack_from, - load=_pickle.load): - Hr = Br = 0 - if readcanbuf: - buf = bytearray(4) - bufv = memoryview(buf) - else: - buf = bufv = BytesIO() - # header - assert not isblocking(fd) - - while Hr < 4: - try: - n = __read__( - fd, bufv[Hr:] if readcanbuf else bufv, 4 - Hr, - ) - except OSError as exc: - if get_errno(exc) not in UNAVAIL: - raise - yield - else: - if n == 0: - raise (OSError('End of file during message') if Hr - else EOFError()) - Hr += n - - body_size, = unpack_from('>i', bufv) - if readcanbuf: - buf = bytearray(body_size) - bufv = memoryview(buf) - else: - buf = bufv = BytesIO() - - while Br < body_size: - try: - n = __read__( - fd, bufv[Br:] if readcanbuf else bufv, body_size - Br, - ) - except OSError as exc: - if get_errno(exc) not in UNAVAIL: - raise - yield - else: - if n == 0: - raise (OSError('End of file during message') if Br - else EOFError()) - Br += n - add_reader(fd, self.handle_event, fd) - if readcanbuf: - message = load(BytesIO(bufv)) - else: - bufv.seek(0) - message = load(bufv) - if message: - callback(message) - - def _make_process_result(self, hub): - """Coroutine that reads messages from the pool processes - and calls the appropriate handler.""" - fileno_to_outq = self.fileno_to_outq - on_state_change = self.on_state_change - add_reader = hub.add_reader - hub_remove = hub.remove - recv_message = self._recv_message - - def on_result_readable(fileno): - try: - fileno_to_outq[fileno] - except KeyError: # process gone - return hub_remove(fileno) - it = recv_message(add_reader, fileno, on_state_change) - try: - next(it) - except StopIteration: - pass - except (IOError, OSError, EOFError): - hub_remove(fileno) - else: - add_reader(fileno, it) - return on_result_readable - - def register_with_event_loop(self, hub): - self.handle_event = self._make_process_result(hub) - - def handle_event(self, fileno): - raise RuntimeError('Not registered with event loop') - - def on_stop_not_started(self): - """This method is always used to stop when the helper thread is not - started.""" - cache = self.cache - check_timeouts = self.check_timeouts - fileno_to_outq = self.fileno_to_outq - on_state_change = self.on_state_change - join_exited_workers = self.join_exited_workers - - # flush the processes outqueues until they have all terminated. - outqueues = set(fileno_to_outq) - while cache and outqueues and self._state != TERMINATE: - if check_timeouts is not None: - # make sure tasks with a time limit will time out. - check_timeouts() - # cannot iterate and remove at the same time - pending_remove_fd = set() - for fd in outqueues: - self._flush_outqueue( - fd, pending_remove_fd.discard, fileno_to_outq, - on_state_change, - ) - try: - join_exited_workers(shutdown=True) - except WorkersJoined: - return debug('result handler: all workers terminated') - outqueues.difference_update(pending_remove_fd) - - def _flush_outqueue(self, fd, remove, process_index, on_state_change): - try: - proc = process_index[fd] - except KeyError: - # process already found terminated - # which means its outqueue has already been processed - # by the worker lost handler. - return remove(fd) - - reader = proc.outq._reader - try: - setblocking(reader, 1) - except (OSError, IOError): - return remove(fd) - try: - if reader.poll(0): - task = reader.recv() - else: - task = None - sleep(0.5) - except (IOError, EOFError): - return remove(fd) - else: - if task: - on_state_change(task) - finally: - try: - setblocking(reader, 0) - except (OSError, IOError): - return remove(fd) - - -class AsynPool(_pool.Pool): - """Pool version that uses AIO instead of helper threads.""" - ResultHandler = ResultHandler - Worker = Worker - - def __init__(self, processes=None, synack=False, - sched_strategy=None, *args, **kwargs): - self.sched_strategy = SCHED_STRATEGIES.get(sched_strategy, - sched_strategy) - processes = self.cpu_count() if processes is None else processes - self.synack = synack - # create queue-pairs for all our processes in advance. - self._queues = dict((self.create_process_queues(), None) - for _ in range(processes)) - - # inqueue fileno -> process mapping - self._fileno_to_inq = {} - # outqueue fileno -> process mapping - self._fileno_to_outq = {} - # synqueue fileno -> process mapping - self._fileno_to_synq = {} - - # We keep track of processes that have not yet - # sent a WORKER_UP message. If a process fails to send - # this message within proc_up_timeout we terminate it - # and hope the next process will recover. - self._proc_alive_timeout = PROC_ALIVE_TIMEOUT - self._waiting_to_start = set() - - # denormalized set of all inqueues. - self._all_inqueues = set() - - # Set of fds being written to (busy) - self._active_writes = set() - - # Set of active co-routines currently writing jobs. - self._active_writers = set() - - # Set of fds that are busy (executing task) - self._busy_workers = set() - self._mark_worker_as_available = self._busy_workers.discard - - # Holds jobs waiting to be written to child processes. - self.outbound_buffer = deque() - - self.write_stats = Counter() - - super(AsynPool, self).__init__(processes, *args, **kwargs) - - for proc in self._pool: - # create initial mappings, these will be updated - # as processes are recycled, or found lost elsewhere. - self._fileno_to_outq[proc.outqR_fd] = proc - self._fileno_to_synq[proc.synqW_fd] = proc - self.on_soft_timeout = self._timeout_handler.on_soft_timeout - self.on_hard_timeout = self._timeout_handler.on_hard_timeout - - def _event_process_exit(self, hub, fd): - # This method is called whenever the process sentinel is readable. - hub.remove(fd) - self.maintain_pool() - - def register_with_event_loop(self, hub): - """Registers the async pool with the current event loop.""" - self._result_handler.register_with_event_loop(hub) - self.handle_result_event = self._result_handler.handle_event - self._create_timelimit_handlers(hub) - self._create_process_handlers(hub) - self._create_write_handlers(hub) - - # Add handler for when a process exits (calls maintain_pool) - [hub.add_reader(fd, self._event_process_exit, hub, fd) - for fd in self.process_sentinels] - # Handle_result_event is called whenever one of the - # result queues are readable. - [hub.add_reader(fd, self.handle_result_event, fd) - for fd in self._fileno_to_outq] - - # Timers include calling maintain_pool at a regular interval - # to be certain processes are restarted. - for handler, interval in items(self.timers): - hub.call_repeatedly(interval, handler) - - hub.on_tick.add(self.on_poll_start) - - def _create_timelimit_handlers(self, hub, now=time.time): - """For async pool this sets up the handlers used - to implement time limits.""" - call_later = hub.call_later - trefs = self._tref_for_id = WeakValueDictionary() - - def on_timeout_set(R, soft, hard): - if soft: - trefs[R._job] = call_later( - soft, self._on_soft_timeout, R._job, soft, hard, hub, - ) - elif hard: - trefs[R._job] = call_later( - hard, self._on_hard_timeout, R._job, - ) - self.on_timeout_set = on_timeout_set - - def _discard_tref(job): - try: - tref = trefs.pop(job) - tref.cancel() - del(tref) - except (KeyError, AttributeError): - pass # out of scope - self._discard_tref = _discard_tref - - def on_timeout_cancel(R): - _discard_tref(R._job) - self.on_timeout_cancel = on_timeout_cancel - - def _on_soft_timeout(self, job, soft, hard, hub, now=time.time): - # only used by async pool. - if hard: - self._tref_for_id[job] = hub.call_at( - now() + (hard - soft), self._on_hard_timeout, job, - ) - try: - result = self._cache[job] - except KeyError: - pass # job ready - else: - self.on_soft_timeout(result) - finally: - if not hard: - # remove tref - self._discard_tref(job) - - def _on_hard_timeout(self, job): - # only used by async pool. - try: - result = self._cache[job] - except KeyError: - pass # job ready - else: - self.on_hard_timeout(result) - finally: - # remove tref - self._discard_tref(job) - - def on_job_ready(self, job, i, obj, inqW_fd): - self._mark_worker_as_available(inqW_fd) - - def _create_process_handlers(self, hub, READ=READ, ERR=ERR): - """For async pool this will create the handlers called - when a process is up/down and etc.""" - add_reader, hub_remove = hub.add_reader, hub.remove - cache = self._cache - all_inqueues = self._all_inqueues - fileno_to_inq = self._fileno_to_inq - fileno_to_outq = self._fileno_to_outq - fileno_to_synq = self._fileno_to_synq - busy_workers = self._busy_workers - event_process_exit = self._event_process_exit - handle_result_event = self.handle_result_event - process_flush_queues = self.process_flush_queues - waiting_to_start = self._waiting_to_start - - def verify_process_alive(proc): - if proc._is_alive() and proc in waiting_to_start: - assert proc.outqR_fd in fileno_to_outq - assert fileno_to_outq[proc.outqR_fd] is proc - assert proc.outqR_fd in hub.readers - error('Timed out waiting for UP message from %r', proc) - os.kill(proc.pid, 9) - - def on_process_up(proc): - """Called when a process has started.""" - # If we got the same fd as a previous process then we will also - # receive jobs in the old buffer, so we need to reset the - # job._write_to and job._scheduled_for attributes used to recover - # message boundaries when processes exit. - infd = proc.inqW_fd - for job in values(cache): - if job._write_to and job._write_to.inqW_fd == infd: - job._write_to = proc - if job._scheduled_for and job._scheduled_for.inqW_fd == infd: - job._scheduled_for = proc - fileno_to_outq[proc.outqR_fd] = proc - # maintain_pool is called whenever a process exits. - add_reader( - proc.sentinel, event_process_exit, hub, proc.sentinel, - ) - - assert not isblocking(proc.outq._reader) - - # handle_result_event is called when the processes outqueue is - # readable. - add_reader(proc.outqR_fd, handle_result_event, proc.outqR_fd) - - waiting_to_start.add(proc) - hub.call_later( - self._proc_alive_timeout, verify_process_alive, proc, - ) - - self.on_process_up = on_process_up - - def _remove_from_index(obj, proc, index, callback=None): - # this remove the file descriptors for a process from - # the indices. we have to make sure we don't overwrite - # another processes fds, as the fds may be reused. - try: - fd = obj.fileno() - except (IOError, OSError): - return - - try: - if index[fd] is proc: - # fd has not been reused so we can remove it from index. - index.pop(fd, None) - except KeyError: - pass - else: - hub_remove(fd) - if callback is not None: - callback(fd) - return fd - - def on_process_down(proc): - """Called when a worker process exits.""" - if proc.dead: - return - process_flush_queues(proc) - _remove_from_index(proc.outq._reader, proc, fileno_to_outq) - if proc.synq: - _remove_from_index(proc.synq._writer, proc, fileno_to_synq) - inq = _remove_from_index(proc.inq._writer, proc, fileno_to_inq, - callback=all_inqueues.discard) - if inq: - busy_workers.discard(inq) - hub_remove(proc.sentinel) - waiting_to_start.discard(proc) - self._active_writes.discard(proc.inqW_fd) - hub_remove(proc.inqW_fd) - hub_remove(proc.outqR_fd) - if proc.synqR_fd: - hub_remove(proc.synqR_fd) - if proc.synqW_fd: - self._active_writes.discard(proc.synqW_fd) - hub_remove(proc.synqW_fd) - self.on_process_down = on_process_down - - def _create_write_handlers(self, hub, - pack=struct.pack, dumps=_pickle.dumps, - protocol=HIGHEST_PROTOCOL): - """For async pool this creates the handlers used to write data to - child processes.""" - fileno_to_inq = self._fileno_to_inq - fileno_to_synq = self._fileno_to_synq - outbound = self.outbound_buffer - pop_message = outbound.popleft - put_message = outbound.append - all_inqueues = self._all_inqueues - active_writes = self._active_writes - active_writers = self._active_writers - busy_workers = self._busy_workers - diff = all_inqueues.difference - add_reader, add_writer = hub.add_reader, hub.add_writer - hub_add, hub_remove = hub.add, hub.remove - mark_write_fd_as_active = active_writes.add - mark_write_gen_as_active = active_writers.add - mark_worker_as_busy = busy_workers.add - write_generator_done = active_writers.discard - get_job = self._cache.__getitem__ - write_stats = self.write_stats - is_fair_strategy = self.sched_strategy == SCHED_STRATEGY_FAIR - revoked_tasks = worker_state.revoked - getpid = os.getpid - - precalc = {ACK: self._create_payload(ACK, (0, )), - NACK: self._create_payload(NACK, (0, ))} - - def _put_back(job, _time=time.time): - # puts back at the end of the queue - if job._terminated is not None or \ - job.correlation_id in revoked_tasks: - if not job._accepted: - job._ack(None, _time(), getpid(), None) - job._set_terminated(job._terminated) - else: - # XXX linear lookup, should find a better way, - # but this happens rarely and is here to protect against races. - if job not in outbound: - outbound.appendleft(job) - self._put_back = _put_back - - # called for every event loop iteration, and if there - # are messages pending this will schedule writing one message - # by registering the 'schedule_writes' function for all currently - # inactive inqueues (not already being written to) - - # consolidate means the event loop will merge them - # and call the callback once with the list writable fds as - # argument. Using this means we minimize the risk of having - # the same fd receive every task if the pipe read buffer is not - # full. - if is_fair_strategy: - - def on_poll_start(): - if outbound and len(busy_workers) < len(all_inqueues): - #print('ALL: %r ACTIVE: %r' % (len(all_inqueues), - # len(active_writes))) - inactive = diff(active_writes) - [hub_add(fd, None, WRITE | ERR, consolidate=True) - for fd in inactive] - else: - [hub_remove(fd) for fd in diff(active_writes)] - else: - def on_poll_start(): # noqa - if outbound: - [hub_add(fd, None, WRITE | ERR, consolidate=True) - for fd in diff(active_writes)] - else: - [hub_remove(fd) for fd in diff(active_writes)] - self.on_poll_start = on_poll_start - - def on_inqueue_close(fd, proc): - # Makes sure the fd is removed from tracking when - # the connection is closed, this is essential as fds may be reused. - busy_workers.discard(fd) - try: - if fileno_to_inq[fd] is proc: - fileno_to_inq.pop(fd, None) - active_writes.discard(fd) - all_inqueues.discard(fd) - hub_remove(fd) - except KeyError: - pass - self.on_inqueue_close = on_inqueue_close - - def schedule_writes(ready_fds, shuffle=random.shuffle): - # Schedule write operation to ready file descriptor. - # The file descriptor is writeable, but that does not - # mean the process is currently reading from the socket. - # The socket is buffered so writeable simply means that - # the buffer can accept at least 1 byte of data. - shuffle(ready_fds) - for ready_fd in ready_fds: - if ready_fd in active_writes: - # already writing to this fd - continue - if is_fair_strategy and ready_fd in busy_workers: - # worker is already busy with another task - continue - if ready_fd not in all_inqueues: - hub_remove(ready_fd) - continue - try: - job = pop_message() - except IndexError: - # no more messages, remove all inactive fds from the hub. - # this is important since the fds are always writeable - # as long as there's 1 byte left in the buffer, and so - # this may create a spinloop where the event loop - # always wakes up. - for inqfd in diff(active_writes): - hub_remove(inqfd) - break - - else: - if not job._accepted: # job not accepted by another worker - try: - # keep track of what process the write operation - # was scheduled for. - proc = job._scheduled_for = fileno_to_inq[ready_fd] - except KeyError: - # write was scheduled for this fd but the process - # has since exited and the message must be sent to - # another process. - put_message(job) - continue - cor = _write_job(proc, ready_fd, job) - job._writer = ref(cor) - mark_write_gen_as_active(cor) - mark_write_fd_as_active(ready_fd) - mark_worker_as_busy(ready_fd) - - # Try to write immediately, in case there's an error. - try: - next(cor) - except StopIteration: - pass - except OSError as exc: - if get_errno(exc) != errno.EBADF: - raise - else: - add_writer(ready_fd, cor) - hub.consolidate_callback = schedule_writes - - def send_job(tup): - # Schedule writing job request for when one of the process - # inqueues are writable. - body = dumps(tup, protocol=protocol) - body_size = len(body) - header = pack('>I', body_size) - # index 1,0 is the job ID. - job = get_job(tup[1][0]) - job._payload = buf_t(header), buf_t(body), body_size - put_message(job) - self._quick_put = send_job - - def on_not_recovering(proc, fd, job): - error('Process inqueue damaged: %r %r' % (proc, proc.exitcode)) - if proc._is_alive(): - proc.terminate() - hub.remove(fd) - self._put_back(job) - - def _write_job(proc, fd, job): - # writes job to the worker process. - # Operation must complete if more than one byte of data - # was written. If the broker connection is lost - # and no data was written the operation shall be cancelled. - header, body, body_size = job._payload - errors = 0 - try: - # job result keeps track of what process the job is sent to. - job._write_to = proc - send = proc.send_job_offset - - Hw = Bw = 0 - # write header - while Hw < 4: - try: - Hw += send(header, Hw) - except Exception as exc: - if get_errno(exc) not in UNAVAIL: - raise - # suspend until more data - errors += 1 - if errors > 100: - on_not_recovering(proc, fd, job) - raise StopIteration() - yield - else: - errors = 0 - - # write body - while Bw < body_size: - try: - Bw += send(body, Bw) - except Exception as exc: - if get_errno(exc) not in UNAVAIL: - raise - # suspend until more data - errors += 1 - if errors > 100: - on_not_recovering(proc, fd, job) - raise StopIteration() - yield - else: - errors = 0 - finally: - hub_remove(fd) - write_stats[proc.index] += 1 - # message written, so this fd is now available - active_writes.discard(fd) - write_generator_done(job._writer()) # is a weakref - - def send_ack(response, pid, job, fd, WRITE=WRITE, ERR=ERR): - # Only used when synack is enabled. - # Schedule writing ack response for when the fd is writeable. - msg = Ack(job, fd, precalc[response]) - callback = promise(write_generator_done) - cor = _write_ack(fd, msg, callback=callback) - mark_write_gen_as_active(cor) - mark_write_fd_as_active(fd) - callback.args = (cor, ) - add_writer(fd, cor) - self.send_ack = send_ack - - def _write_ack(fd, ack, callback=None): - # writes ack back to the worker if synack enabled. - # this operation *MUST* complete, otherwise - # the worker process will hang waiting for the ack. - header, body, body_size = ack[2] - try: - try: - proc = fileno_to_synq[fd] - except KeyError: - # process died, we can safely discard the ack at this - # point. - raise StopIteration() - send = proc.send_syn_offset - - Hw = Bw = 0 - # write header - while Hw < 4: - try: - Hw += send(header, Hw) - except Exception as exc: - if get_errno(exc) not in UNAVAIL: - raise - yield - - # write body - while Bw < body_size: - try: - Bw += send(body, Bw) - except Exception as exc: - if get_errno(exc) not in UNAVAIL: - raise - # suspend until more data - yield - finally: - if callback: - callback() - # message written, so this fd is now available - active_writes.discard(fd) - - def flush(self): - if self._state == TERMINATE: - return - # cancel all tasks that have not been accepted so that NACK is sent. - for job in values(self._cache): - if not job._accepted: - job._cancel() - - # clear the outgoing buffer as the tasks will be redelivered by - # the broker anyway. - if self.outbound_buffer: - self.outbound_buffer.clear() - - self.maintain_pool() - - try: - # ...but we must continue writing the payloads we already started - # to keep message boundaries. - # The messages may be NACK'ed later if synack is enabled. - if self._state == RUN: - # flush outgoing buffers - intervals = fxrange(0.01, 0.1, 0.01, repeatlast=True) - owned_by = {} - for job in values(self._cache): - writer = _get_job_writer(job) - if writer is not None: - owned_by[writer] = job - - while self._active_writers: - writers = list(self._active_writers) - for gen in writers: - if (gen.__name__ == '_write_job' and - gen_not_started(gen)): - # has not started writing the job so can - # discard the task, but we must also remove - # it from the Pool._cache. - try: - job = owned_by[gen] - except KeyError: - pass - else: - # removes from Pool._cache - job.discard() - self._active_writers.discard(gen) - else: - try: - job = owned_by[gen] - except KeyError: - pass - else: - job_proc = job._write_to - if job_proc._is_alive(): - self._flush_writer(job_proc, gen) - # workers may have exited in the meantime. - self.maintain_pool() - sleep(next(intervals)) # don't busyloop - finally: - self.outbound_buffer.clear() - self._active_writers.clear() - self._active_writes.clear() - self._busy_workers.clear() - - def _flush_writer(self, proc, writer): - fds = set([proc.inq._writer]) - try: - while fds: - if not proc._is_alive(): - break # process exited - readable, writable, again = _select( - writers=fds, err=fds, timeout=0.5, - ) - if not again and (writable or readable): - try: - next(writer) - except (StopIteration, OSError, IOError, EOFError): - break - finally: - self._active_writers.discard(writer) - - def get_process_queues(self): - """Get queues for a new process. - - Here we will find an unused slot, as there should always - be one available when we start a new process. - """ - return next(q for q, owner in items(self._queues) - if owner is None) - - def on_grow(self, n): - """Grow the pool by ``n`` proceses.""" - diff = max(self._processes - len(self._queues), 0) - if diff: - self._queues.update( - dict((self.create_process_queues(), None) for _ in range(diff)) - ) - - def on_shrink(self, n): - """Shrink the pool by ``n`` processes.""" - pass - - def create_process_queues(self): - """Creates new in, out (and optionally syn) queues, - returned as a tuple.""" - # NOTE: Pipes must be set O_NONBLOCK at creation time (the original - # fd), otherwise it will not be possible to change the flags until - # there is an actual reader/writer on the other side. - inq = _SimpleQueue(wnonblock=True) - outq = _SimpleQueue(rnonblock=True) - synq = None - assert isblocking(inq._reader) - assert not isblocking(inq._writer) - assert not isblocking(outq._reader) - assert isblocking(outq._writer) - if self.synack: - synq = _SimpleQueue(wnonblock=True) - assert isblocking(synq._reader) - assert not isblocking(synq._writer) - return inq, outq, synq - - def on_process_alive(self, pid): - """Handler called when the :const:`WORKER_UP` message is received - from a child process, which marks the process as ready - to receive work.""" - try: - proc = next(w for w in self._pool if w.pid == pid) - except StopIteration: - return logger.warning('process with pid=%s already exited', pid) - assert proc.inqW_fd not in self._fileno_to_inq - assert proc.inqW_fd not in self._all_inqueues - self._waiting_to_start.discard(proc) - self._fileno_to_inq[proc.inqW_fd] = proc - self._fileno_to_synq[proc.synqW_fd] = proc - self._all_inqueues.add(proc.inqW_fd) - - def on_job_process_down(self, job, pid_gone): - """Handler called for each job when the process it was assigned to - exits.""" - if job._write_to and not job._write_to._is_alive(): - # job was partially written - self.on_partial_read(job, job._write_to) - elif job._scheduled_for and not job._scheduled_for._is_alive(): - # job was only scheduled to be written to this process, - # but no data was sent so put it back on the outbound_buffer. - self._put_back(job) - - def on_job_process_lost(self, job, pid, exitcode): - """Handler called for each *started* job when the process it - was assigned to exited by mysterious means (error exitcodes and - signals)""" - self.mark_as_worker_lost(job, exitcode) - - def human_write_stats(self): - if self.write_stats is None: - return 'N/A' - vals = list(values(self.write_stats)) - total = sum(vals) - - def per(v, total): - return '{0:.2f}%'.format((float(v) / total) * 100.0 if v else 0) - - return { - 'total': total, - 'avg': per(total / len(self.write_stats) if total else 0, total), - 'all': ', '.join(per(v, total) for v in vals), - 'raw': ', '.join(map(str, vals)), - 'inqueues': { - 'total': len(self._all_inqueues), - 'active': len(self._active_writes), - } - } - - def _process_cleanup_queues(self, proc): - """Handler called to clean up a processes queues after process - exit.""" - if not proc.dead: - try: - self._queues[self._find_worker_queues(proc)] = None - except (KeyError, ValueError): - pass - - @staticmethod - def _stop_task_handler(task_handler): - """Called at shutdown to tell processes that we are shutting down.""" - for proc in task_handler.pool: - try: - setblocking(proc.inq._writer, 1) - except (OSError, IOError): - pass - else: - try: - proc.inq.put(None) - except OSError as exc: - if get_errno(exc) != errno.EBADF: - raise - - def create_result_handler(self): - return super(AsynPool, self).create_result_handler( - fileno_to_outq=self._fileno_to_outq, - on_process_alive=self.on_process_alive, - ) - - def _process_register_queues(self, proc, queues): - """Marks new ownership for ``queues`` so that the fileno indices are - updated.""" - assert queues in self._queues - b = len(self._queues) - self._queues[queues] = proc - assert b == len(self._queues) - - def _find_worker_queues(self, proc): - """Find the queues owned by ``proc``.""" - try: - return next(q for q, owner in items(self._queues) - if owner == proc) - except StopIteration: - raise ValueError(proc) - - def _setup_queues(self): - # this is only used by the original pool which uses a shared - # queue for all processes. - - # these attributes makes no sense for us, but we will still - # have to initialize them. - self._inqueue = self._outqueue = \ - self._quick_put = self._quick_get = self._poll_result = None - - def process_flush_queues(self, proc): - """Flushes all queues, including the outbound buffer, so that - all tasks that have not been started will be discarded. - - In Celery this is called whenever the transport connection is lost - (consumer restart). - - """ - resq = proc.outq._reader - on_state_change = self._result_handler.on_state_change - fds = set([resq]) - while fds and not resq.closed and self._state != TERMINATE: - readable, _, again = _select(fds, None, fds, timeout=0.01) - if readable: - try: - task = resq.recv() - except (OSError, IOError, EOFError) as exc: - if get_errno(exc) == errno.EINTR: - continue - elif get_errno(exc) == errno.EAGAIN: - break - else: - debug('got %r while flushing process %r', - exc, proc, exc_info=1) - if get_errno(exc) not in UNAVAIL: - debug('got %r while flushing process %r', - exc, proc, exc_info=1) - break - else: - if task is None: - debug('got sentinel while flushing process %r', proc) - break - else: - on_state_change(task) - else: - break - - def on_partial_read(self, job, proc): - """Called when a job was only partially written to a child process - and it exited.""" - # worker terminated by signal: - # we cannot reuse the sockets again, because we don't know if - # the process wrote/read anything frmo them, and if so we cannot - # restore the message boundaries. - if not job._accepted: - # job was not acked, so find another worker to send it to. - self._put_back(job) - writer = _get_job_writer(job) - if writer: - self._active_writers.discard(writer) - del(writer) - - if not proc.dead: - proc.dead = True - # Replace queues to avoid reuse - before = len(self._queues) - try: - queues = self._find_worker_queues(proc) - if self.destroy_queues(queues, proc): - self._queues[self.create_process_queues()] = None - except ValueError: - pass - # Not in queue map, make sure sockets are closed. - #self.destroy_queues((proc.inq, proc.outq, proc.synq)) - assert len(self._queues) == before - - def destroy_queues(self, queues, proc): - """Destroy queues that can no longer be used, so that they - be replaced by new sockets.""" - assert not proc._is_alive() - self._waiting_to_start.discard(proc) - removed = 1 - try: - self._queues.pop(queues) - except KeyError: - removed = 0 - try: - self.on_inqueue_close(queues[0]._writer.fileno(), proc) - except IOError: - pass - for queue in queues: - if queue: - for sock in (queue._reader, queue._writer): - if not sock.closed: - try: - sock.close() - except (IOError, OSError): - pass - return removed - - def _create_payload(self, type_, args, - dumps=_pickle.dumps, pack=struct.pack, - protocol=HIGHEST_PROTOCOL): - body = dumps((type_, args), protocol=protocol) - size = len(body) - header = pack('>I', size) - return header, body, size - - @classmethod - def _set_result_sentinel(cls, _outqueue, _pool): - # unused - pass - - def _help_stuff_finish_args(self): - # Pool._help_stuff_finished is a classmethod so we have to use this - # trick to modify the arguments passed to it. - return (self._pool, ) - - @classmethod - def _help_stuff_finish(cls, pool): - debug( - 'removing tasks from inqueue until task handler finished', - ) - fileno_to_proc = {} - inqR = set() - for w in pool: - try: - fd = w.inq._reader.fileno() - inqR.add(fd) - fileno_to_proc[fd] = w - except IOError: - pass - while inqR: - readable, _, again = _select(inqR, timeout=0.5) - if again: - continue - if not readable: - break - for fd in readable: - fileno_to_proc[fd].inq._reader.recv() - sleep(0) - - @property - def timers(self): - return {self.maintain_pool: 5.0} diff --git a/awx/lib/site-packages/celery/concurrency/base.py b/awx/lib/site-packages/celery/concurrency/base.py deleted file mode 100644 index 6b3594a960..0000000000 --- a/awx/lib/site-packages/celery/concurrency/base.py +++ /dev/null @@ -1,171 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency.base - ~~~~~~~~~~~~~~~~~~~~~~~ - - TaskPool interface. - -""" -from __future__ import absolute_import - -import logging -import os -import sys - -from billiard.einfo import ExceptionInfo -from billiard.exceptions import WorkerLostError -from kombu.utils.encoding import safe_repr - -from celery.exceptions import WorkerShutdown, WorkerTerminate -from celery.five import monotonic, reraise -from celery.utils import timer2 -from celery.utils.text import truncate -from celery.utils.log import get_logger - -__all__ = ['BasePool', 'apply_target'] - -logger = get_logger('celery.pool') - - -def apply_target(target, args=(), kwargs={}, callback=None, - accept_callback=None, pid=None, getpid=os.getpid, - propagate=(), monotonic=monotonic, **_): - if accept_callback: - accept_callback(pid or getpid(), monotonic()) - try: - ret = target(*args, **kwargs) - except propagate: - raise - except Exception: - raise - except (WorkerShutdown, WorkerTerminate): - raise - except BaseException as exc: - try: - reraise(WorkerLostError, WorkerLostError(repr(exc)), - sys.exc_info()[2]) - except WorkerLostError: - callback(ExceptionInfo()) - else: - callback(ret) - - -class BasePool(object): - RUN = 0x1 - CLOSE = 0x2 - TERMINATE = 0x3 - - Timer = timer2.Timer - - #: set to true if the pool can be shutdown from within - #: a signal handler. - signal_safe = True - - #: set to true if pool uses greenlets. - is_green = False - - _state = None - _pool = None - - #: only used by multiprocessing pool - uses_semaphore = False - - task_join_will_block = True - - def __init__(self, limit=None, putlocks=True, - forking_enable=True, callbacks_propagate=(), **options): - self.limit = limit - self.putlocks = putlocks - self.options = options - self.forking_enable = forking_enable - self.callbacks_propagate = callbacks_propagate - self._does_debug = logger.isEnabledFor(logging.DEBUG) - - def on_start(self): - pass - - def did_start_ok(self): - return True - - def flush(self): - pass - - def on_stop(self): - pass - - def register_with_event_loop(self, loop): - pass - - def on_apply(self, *args, **kwargs): - pass - - def on_terminate(self): - pass - - def on_soft_timeout(self, job): - pass - - def on_hard_timeout(self, job): - pass - - def maintain_pool(self, *args, **kwargs): - pass - - def terminate_job(self, pid): - raise NotImplementedError( - '{0} does not implement kill_job'.format(type(self))) - - def restart(self): - raise NotImplementedError( - '{0} does not implement restart'.format(type(self))) - - def stop(self): - self.on_stop() - self._state = self.TERMINATE - - def terminate(self): - self._state = self.TERMINATE - self.on_terminate() - - def start(self): - self.on_start() - self._state = self.RUN - - def close(self): - self._state = self.CLOSE - self.on_close() - - def on_close(self): - pass - - def apply_async(self, target, args=[], kwargs={}, **options): - """Equivalent of the :func:`apply` built-in function. - - Callbacks should optimally return as soon as possible since - otherwise the thread which handles the result will get blocked. - - """ - if self._does_debug: - logger.debug('TaskPool: Apply %s (args:%s kwargs:%s)', - target, truncate(safe_repr(args), 1024), - truncate(safe_repr(kwargs), 1024)) - - return self.on_apply(target, args, kwargs, - waitforslot=self.putlocks, - callbacks_propagate=self.callbacks_propagate, - **options) - - def _get_info(self): - return {} - - @property - def info(self): - return self._get_info() - - @property - def active(self): - return self._state == self.RUN - - @property - def num_processes(self): - return self.limit diff --git a/awx/lib/site-packages/celery/concurrency/eventlet.py b/awx/lib/site-packages/celery/concurrency/eventlet.py deleted file mode 100644 index e5319a9b85..0000000000 --- a/awx/lib/site-packages/celery/concurrency/eventlet.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency.eventlet - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Eventlet pool implementation. - -""" -from __future__ import absolute_import - -import sys - -from time import time - -__all__ = ['TaskPool'] - -W_RACE = """\ -Celery module with %s imported before eventlet patched\ -""" -RACE_MODS = ('billiard.', 'celery.', 'kombu.') - - -#: Warn if we couldn't patch early enough, -#: and thread/socket depending celery modules have already been loaded. -for mod in (mod for mod in sys.modules if mod.startswith(RACE_MODS)): - for side in ('thread', 'threading', 'socket'): # pragma: no cover - if getattr(mod, side, None): - import warnings - warnings.warn(RuntimeWarning(W_RACE % side)) - - -from celery import signals -from celery.utils import timer2 - -from . import base - - -def apply_target(target, args=(), kwargs={}, callback=None, - accept_callback=None, getpid=None): - return base.apply_target(target, args, kwargs, callback, accept_callback, - pid=getpid()) - - -class Schedule(timer2.Schedule): - - def __init__(self, *args, **kwargs): - from eventlet.greenthread import spawn_after - from greenlet import GreenletExit - super(Schedule, self).__init__(*args, **kwargs) - - self.GreenletExit = GreenletExit - self._spawn_after = spawn_after - self._queue = set() - - def _enter(self, eta, priority, entry): - secs = max(eta - time(), 0) - g = self._spawn_after(secs, entry) - self._queue.add(g) - g.link(self._entry_exit, entry) - g.entry = entry - g.eta = eta - g.priority = priority - g.cancelled = False - return g - - def _entry_exit(self, g, entry): - try: - try: - g.wait() - except self.GreenletExit: - entry.cancel() - g.cancelled = True - finally: - self._queue.discard(g) - - def clear(self): - queue = self._queue - while queue: - try: - queue.pop().cancel() - except (KeyError, self.GreenletExit): - pass - - @property - def queue(self): - return self._queue - - -class Timer(timer2.Timer): - Schedule = Schedule - - def ensure_started(self): - pass - - def stop(self): - self.schedule.clear() - - def cancel(self, tref): - try: - tref.cancel() - except self.schedule.GreenletExit: - pass - - def start(self): - pass - - -class TaskPool(base.BasePool): - Timer = Timer - - signal_safe = False - is_green = True - task_join_will_block = False - - def __init__(self, *args, **kwargs): - from eventlet import greenthread - from eventlet.greenpool import GreenPool - self.Pool = GreenPool - self.getcurrent = greenthread.getcurrent - self.getpid = lambda: id(greenthread.getcurrent()) - self.spawn_n = greenthread.spawn_n - - super(TaskPool, self).__init__(*args, **kwargs) - - def on_start(self): - self._pool = self.Pool(self.limit) - signals.eventlet_pool_started.send(sender=self) - self._quick_put = self._pool.spawn_n - self._quick_apply_sig = signals.eventlet_pool_apply.send - - def on_stop(self): - signals.eventlet_pool_preshutdown.send(sender=self) - if self._pool is not None: - self._pool.waitall() - signals.eventlet_pool_postshutdown.send(sender=self) - - def on_apply(self, target, args=None, kwargs=None, callback=None, - accept_callback=None, **_): - self._quick_apply_sig( - sender=self, target=target, args=args, kwargs=kwargs, - ) - self._quick_put(apply_target, target, args, kwargs, - callback, accept_callback, - self.getpid) diff --git a/awx/lib/site-packages/celery/concurrency/gevent.py b/awx/lib/site-packages/celery/concurrency/gevent.py deleted file mode 100644 index f89de92b2e..0000000000 --- a/awx/lib/site-packages/celery/concurrency/gevent.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency.gevent - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - gevent pool implementation. - -""" -from __future__ import absolute_import - -from time import time - -try: - from gevent import Timeout -except ImportError: # pragma: no cover - Timeout = None # noqa - -from celery.utils import timer2 - -from .base import apply_target, BasePool - -__all__ = ['TaskPool'] - - -def apply_timeout(target, args=(), kwargs={}, callback=None, - accept_callback=None, pid=None, timeout=None, - timeout_callback=None, Timeout=Timeout, - apply_target=apply_target, **rest): - try: - with Timeout(timeout): - return apply_target(target, args, kwargs, callback, - accept_callback, pid, - propagate=(Timeout, ), **rest) - except Timeout: - return timeout_callback(False, timeout) - - -class Schedule(timer2.Schedule): - - def __init__(self, *args, **kwargs): - from gevent.greenlet import Greenlet, GreenletExit - - class _Greenlet(Greenlet): - cancel = Greenlet.kill - - self._Greenlet = _Greenlet - self._GreenletExit = GreenletExit - super(Schedule, self).__init__(*args, **kwargs) - self._queue = set() - - def _enter(self, eta, priority, entry): - secs = max(eta - time(), 0) - g = self._Greenlet.spawn_later(secs, entry) - self._queue.add(g) - g.link(self._entry_exit) - g.entry = entry - g.eta = eta - g.priority = priority - g.cancelled = False - return g - - def _entry_exit(self, g): - try: - g.kill() - finally: - self._queue.discard(g) - - def clear(self): - queue = self._queue - while queue: - try: - queue.pop().kill() - except KeyError: - pass - - @property - def queue(self): - return self._queue - - -class Timer(timer2.Timer): - Schedule = Schedule - - def ensure_started(self): - pass - - def stop(self): - self.schedule.clear() - - def start(self): - pass - - -class TaskPool(BasePool): - Timer = Timer - - signal_safe = False - is_green = True - task_join_will_block = False - - def __init__(self, *args, **kwargs): - from gevent import spawn_raw - from gevent.pool import Pool - self.Pool = Pool - self.spawn_n = spawn_raw - self.timeout = kwargs.get('timeout') - super(TaskPool, self).__init__(*args, **kwargs) - - def on_start(self): - self._pool = self.Pool(self.limit) - self._quick_put = self._pool.spawn - - def on_stop(self): - if self._pool is not None: - self._pool.join() - - def on_apply(self, target, args=None, kwargs=None, callback=None, - accept_callback=None, timeout=None, - timeout_callback=None, **_): - timeout = self.timeout if timeout is None else timeout - return self._quick_put(apply_timeout if timeout else apply_target, - target, args, kwargs, callback, accept_callback, - timeout=timeout, - timeout_callback=timeout_callback) - - def grow(self, n=1): - self._pool._semaphore.counter += n - self._pool.size += n - - def shrink(self, n=1): - self._pool._semaphore.counter -= n - self._pool.size -= n - - @property - def num_processes(self): - return len(self._pool) diff --git a/awx/lib/site-packages/celery/concurrency/prefork.py b/awx/lib/site-packages/celery/concurrency/prefork.py deleted file mode 100644 index b579d0e100..0000000000 --- a/awx/lib/site-packages/celery/concurrency/prefork.py +++ /dev/null @@ -1,175 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency.prefork - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Pool implementation using :mod:`multiprocessing`. - -""" -from __future__ import absolute_import - -import os - -from billiard import forking_enable -from billiard.pool import RUN, CLOSE, Pool as BlockingPool - -from celery import platforms -from celery import signals -from celery._state import set_default_app, _set_task_join_will_block -from celery.app import trace -from celery.concurrency.base import BasePool -from celery.five import items -from celery.utils.functional import noop -from celery.utils.log import get_logger - -from .asynpool import AsynPool - -__all__ = ['TaskPool', 'process_initializer', 'process_destructor'] - -#: List of signals to reset when a child process starts. -WORKER_SIGRESET = frozenset(['SIGTERM', - 'SIGHUP', - 'SIGTTIN', - 'SIGTTOU', - 'SIGUSR1']) - -#: List of signals to ignore when a child process starts. -WORKER_SIGIGNORE = frozenset(['SIGINT']) - -logger = get_logger(__name__) -warning, debug = logger.warning, logger.debug - - -def process_initializer(app, hostname): - """Pool child process initializer. - - This will initialize a child pool process to ensure the correct - app instance is used and things like - logging works. - - """ - _set_task_join_will_block(True) - platforms.signals.reset(*WORKER_SIGRESET) - platforms.signals.ignore(*WORKER_SIGIGNORE) - platforms.set_mp_process_title('celeryd', hostname=hostname) - # This is for Windows and other platforms not supporting - # fork(). Note that init_worker makes sure it's only - # run once per process. - app.loader.init_worker() - app.loader.init_worker_process() - logfile = os.environ.get('CELERY_LOG_FILE') or None - if logfile and '%i' in logfile.lower(): - # logfile path will differ so need to set up logging again. - app.log.already_setup = False - app.log.setup(int(os.environ.get('CELERY_LOG_LEVEL', 0) or 0), - logfile, - bool(os.environ.get('CELERY_LOG_REDIRECT', False)), - str(os.environ.get('CELERY_LOG_REDIRECT_LEVEL')), - hostname=hostname) - if os.environ.get('FORKED_BY_MULTIPROCESSING'): - # pool did execv after fork - trace.setup_worker_optimizations(app) - else: - app.set_current() - set_default_app(app) - app.finalize() - trace._tasks = app._tasks # enables fast_trace_task optimization. - # rebuild execution handler for all tasks. - from celery.app.trace import build_tracer - for name, task in items(app.tasks): - task.__trace__ = build_tracer(name, task, app.loader, hostname, - app=app) - signals.worker_process_init.send(sender=None) - - -def process_destructor(pid, exitcode): - """Pool child process destructor - - Dispatch the :signal:`worker_process_shutdown` signal. - - """ - signals.worker_process_shutdown.send( - sender=None, pid=pid, exitcode=exitcode, - ) - - -class TaskPool(BasePool): - """Multiprocessing Pool implementation.""" - Pool = AsynPool - BlockingPool = BlockingPool - - uses_semaphore = True - write_stats = None - - def on_start(self): - """Run the task pool. - - Will pre-fork all workers so they're ready to accept tasks. - - """ - forking_enable(self.forking_enable) - Pool = (self.BlockingPool if self.options.get('threads', True) - else self.Pool) - P = self._pool = Pool(processes=self.limit, - initializer=process_initializer, - on_process_exit=process_destructor, - synack=False, - **self.options) - - # Create proxy methods - self.on_apply = P.apply_async - self.maintain_pool = P.maintain_pool - self.terminate_job = P.terminate_job - self.grow = P.grow - self.shrink = P.shrink - self.flush = getattr(P, 'flush', None) # FIXME add to billiard - - def restart(self): - self._pool.restart() - self._pool.apply_async(noop) - - def did_start_ok(self): - return self._pool.did_start_ok() - - def register_with_event_loop(self, loop): - try: - reg = self._pool.register_with_event_loop - except AttributeError: - return - return reg(loop) - - def on_stop(self): - """Gracefully stop the pool.""" - if self._pool is not None and self._pool._state in (RUN, CLOSE): - self._pool.close() - self._pool.join() - self._pool = None - - def on_terminate(self): - """Force terminate the pool.""" - if self._pool is not None: - self._pool.terminate() - self._pool = None - - def on_close(self): - if self._pool is not None and self._pool._state == RUN: - self._pool.close() - - def _get_info(self): - try: - write_stats = self._pool.human_write_stats - except AttributeError: - write_stats = lambda: 'N/A' # only supported by asynpool - return { - 'max-concurrency': self.limit, - 'processes': [p.pid for p in self._pool._pool], - 'max-tasks-per-child': self._pool._maxtasksperchild or 'N/A', - 'put-guarded-by-semaphore': self.putlocks, - 'timeouts': (self._pool.soft_timeout or 0, - self._pool.timeout or 0), - 'writes': write_stats() - } - - @property - def num_processes(self): - return self._pool._processes diff --git a/awx/lib/site-packages/celery/concurrency/solo.py b/awx/lib/site-packages/celery/concurrency/solo.py deleted file mode 100644 index a2dc199706..0000000000 --- a/awx/lib/site-packages/celery/concurrency/solo.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency.solo - ~~~~~~~~~~~~~~~~~~~~~~~ - - Single-threaded pool implementation. - -""" -from __future__ import absolute_import - -import os - -from .base import BasePool, apply_target - -__all__ = ['TaskPool'] - - -class TaskPool(BasePool): - """Solo task pool (blocking, inline, fast).""" - - def __init__(self, *args, **kwargs): - super(TaskPool, self).__init__(*args, **kwargs) - self.on_apply = apply_target - - def _get_info(self): - return {'max-concurrency': 1, - 'processes': [os.getpid()], - 'max-tasks-per-child': None, - 'put-guarded-by-semaphore': True, - 'timeouts': ()} diff --git a/awx/lib/site-packages/celery/concurrency/threads.py b/awx/lib/site-packages/celery/concurrency/threads.py deleted file mode 100644 index fee901ecf3..0000000000 --- a/awx/lib/site-packages/celery/concurrency/threads.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.concurrency.threads - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Pool implementation using threads. - -""" -from __future__ import absolute_import - -from celery.five import UserDict - -from .base import apply_target, BasePool - -__all__ = ['TaskPool'] - - -class NullDict(UserDict): - - def __setitem__(self, key, value): - pass - - -class TaskPool(BasePool): - - def __init__(self, *args, **kwargs): - try: - import threadpool - except ImportError: - raise ImportError( - 'The threaded pool requires the threadpool module.') - self.WorkRequest = threadpool.WorkRequest - self.ThreadPool = threadpool.ThreadPool - super(TaskPool, self).__init__(*args, **kwargs) - - def on_start(self): - self._pool = self.ThreadPool(self.limit) - # threadpool stores all work requests until they are processed - # we don't need this dict, and it occupies way too much memory. - self._pool.workRequests = NullDict() - self._quick_put = self._pool.putRequest - self._quick_clear = self._pool._results_queue.queue.clear - - def on_stop(self): - self._pool.dismissWorkers(self.limit, do_join=True) - - def on_apply(self, target, args=None, kwargs=None, callback=None, - accept_callback=None, **_): - req = self.WorkRequest(apply_target, (target, args, kwargs, callback, - accept_callback)) - self._quick_put(req) - # threadpool also has callback support, - # but for some reason the callback is not triggered - # before you've collected the results. - # Clear the results (if any), so it doesn't grow too large. - self._quick_clear() - return req diff --git a/awx/lib/site-packages/celery/contrib/__init__.py b/awx/lib/site-packages/celery/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/contrib/abortable.py b/awx/lib/site-packages/celery/contrib/abortable.py deleted file mode 100644 index 37dc30d921..0000000000 --- a/awx/lib/site-packages/celery/contrib/abortable.py +++ /dev/null @@ -1,169 +0,0 @@ -# -*- coding: utf-8 -*- -""" -========================= -Abortable tasks overview -========================= - -For long-running :class:`Task`'s, it can be desirable to support -aborting during execution. Of course, these tasks should be built to -support abortion specifically. - -The :class:`AbortableTask` serves as a base class for all :class:`Task` -objects that should support abortion by producers. - -* Producers may invoke the :meth:`abort` method on - :class:`AbortableAsyncResult` instances, to request abortion. - -* Consumers (workers) should periodically check (and honor!) the - :meth:`is_aborted` method at controlled points in their task's - :meth:`run` method. The more often, the better. - -The necessary intermediate communication is dealt with by the -:class:`AbortableTask` implementation. - -Usage example -------------- - -In the consumer: - -.. code-block:: python - - from celery.contrib.abortable import AbortableTask - from celery.utils.log import get_task_logger - - logger = get_logger(__name__) - - class MyLongRunningTask(AbortableTask): - - def run(self, **kwargs): - results = [] - for x in range(100): - # Check after every 5 loops.. - if x % 5 == 0: # alternatively, check when some timer is due - if self.is_aborted(**kwargs): - # Respect the aborted status and terminate - # gracefully - logger.warning('Task aborted.') - return - y = do_something_expensive(x) - results.append(y) - logger.info('Task finished.') - return results - - -In the producer: - -.. code-block:: python - - from myproject.tasks import MyLongRunningTask - - def myview(request): - - async_result = MyLongRunningTask.delay() - # async_result is of type AbortableAsyncResult - - # After 10 seconds, abort the task - time.sleep(10) - async_result.abort() - - ... - -After the `async_result.abort()` call, the task execution is not -aborted immediately. In fact, it is not guaranteed to abort at all. Keep -checking the `async_result` status, or call `async_result.wait()` to -have it block until the task is finished. - -.. note:: - - In order to abort tasks, there needs to be communication between the - producer and the consumer. This is currently implemented through the - database backend. Therefore, this class will only work with the - database backends. - -""" -from __future__ import absolute_import - -from celery import Task -from celery.result import AsyncResult - -__all__ = ['AbortableAsyncResult', 'AbortableTask'] - - -""" -Task States ------------ - -.. state:: ABORTED - -ABORTED -~~~~~~~ - -Task is aborted (typically by the producer) and should be -aborted as soon as possible. - -""" -ABORTED = 'ABORTED' - - -class AbortableAsyncResult(AsyncResult): - """Represents a abortable result. - - Specifically, this gives the `AsyncResult` a :meth:`abort()` method, - which sets the state of the underlying Task to `'ABORTED'`. - - """ - - def is_aborted(self): - """Return :const:`True` if the task is (being) aborted.""" - return self.state == ABORTED - - def abort(self): - """Set the state of the task to :const:`ABORTED`. - - Abortable tasks monitor their state at regular intervals and - terminate execution if so. - - Be aware that invoking this method does not guarantee when the - task will be aborted (or even if the task will be aborted at - all). - - """ - # TODO: store_result requires all four arguments to be set, - # but only status should be updated here - return self.backend.store_result(self.id, result=None, - status=ABORTED, traceback=None) - - -class AbortableTask(Task): - """A celery task that serves as a base class for all :class:`Task`'s - that support aborting during execution. - - All subclasses of :class:`AbortableTask` must call the - :meth:`is_aborted` method periodically and act accordingly when - the call evaluates to :const:`True`. - - """ - abstract = True - - def AsyncResult(self, task_id): - """Return the accompanying AbortableAsyncResult instance.""" - return AbortableAsyncResult(task_id, backend=self.backend) - - def is_aborted(self, **kwargs): - """Checks against the backend whether this - :class:`AbortableAsyncResult` is :const:`ABORTED`. - - Always return :const:`False` in case the `task_id` parameter - refers to a regular (non-abortable) :class:`Task`. - - Be aware that invoking this method will cause a hit in the - backend (for example a database query), so find a good balance - between calling it regularly (for responsiveness), but not too - often (for performance). - - """ - task_id = kwargs.get('task_id', self.request.id) - result = self.AsyncResult(task_id) - if not isinstance(result, AbortableAsyncResult): - return False - return result.is_aborted() diff --git a/awx/lib/site-packages/celery/contrib/batches.py b/awx/lib/site-packages/celery/contrib/batches.py deleted file mode 100644 index 0248ebf8d4..0000000000 --- a/awx/lib/site-packages/celery/contrib/batches.py +++ /dev/null @@ -1,248 +0,0 @@ -# -*- coding: utf-8 -*- -""" -celery.contrib.batches -====================== - -Experimental task class that buffers messages and processes them as a list. - -.. warning:: - - For this to work you have to set - :setting:`CELERYD_PREFETCH_MULTIPLIER` to zero, or some value where - the final multiplied value is higher than ``flush_every``. - - In the future we hope to add the ability to direct batching tasks - to a channel with different QoS requirements than the task channel. - -**Simple Example** - -A click counter that flushes the buffer every 100 messages, and every -seconds. Does not do anything with the data, but can easily be modified -to store it in a database. - -.. code-block:: python - - # Flush after 100 messages, or 10 seconds. - @app.task(base=Batches, flush_every=100, flush_interval=10) - def count_click(requests): - from collections import Counter - count = Counter(request.kwargs['url'] for request in requests) - for url, count in count.items(): - print('>>> Clicks: {0} -> {1}'.format(url, count)) - - -Then you can ask for a click to be counted by doing:: - - >>> count_click.delay('http://example.com') - -**Example returning results** - -An interface to the Web of Trust API that flushes the buffer every 100 -messages, and every 10 seconds. - -.. code-block:: python - - import requests - from urlparse import urlparse - - from celery.contrib.batches import Batches - - wot_api_target = 'https://api.mywot.com/0.4/public_link_json' - - @app.task(base=Batches, flush_every=100, flush_interval=10) - def wot_api(requests): - sig = lambda url: url - reponses = wot_api_real( - (sig(*request.args, **request.kwargs) for request in requests) - ) - # use mark_as_done to manually return response data - for response, request in zip(reponses, requests): - app.backend.mark_as_done(request.id, response) - - - def wot_api_real(urls): - domains = [urlparse(url).netloc for url in urls] - response = requests.get( - wot_api_target, - params={'hosts': ('/').join(set(domains)) + '/'} - ) - return [response.json[domain] for domain in domains] - -Using the API is done as follows:: - - >>> wot_api.delay('http://example.com') - -.. note:: - - If you don't have an ``app`` instance then use the current app proxy - instead:: - - from celery import current_app - app.backend.mark_as_done(request.id, response) - -""" -from __future__ import absolute_import - -from itertools import count - -from celery.task import Task -from celery.five import Empty, Queue -from celery.utils.log import get_logger -from celery.worker.job import Request -from celery.utils import noop - -__all__ = ['Batches'] - -logger = get_logger(__name__) - - -def consume_queue(queue): - """Iterator yielding all immediately available items in a - :class:`Queue.Queue`. - - The iterator stops as soon as the queue raises :exc:`Queue.Empty`. - - *Examples* - - >>> q = Queue() - >>> map(q.put, range(4)) - >>> list(consume_queue(q)) - [0, 1, 2, 3] - >>> list(consume_queue(q)) - [] - - """ - get = queue.get_nowait - while 1: - try: - yield get() - except Empty: - break - - -def apply_batches_task(task, args, loglevel, logfile): - task.push_request(loglevel=loglevel, logfile=logfile) - try: - result = task(*args) - except Exception as exc: - result = None - logger.error('Error: %r', exc, exc_info=True) - finally: - task.pop_request() - return result - - -class SimpleRequest(object): - """Pickleable request.""" - - #: task id - id = None - - #: task name - name = None - - #: positional arguments - args = () - - #: keyword arguments - kwargs = {} - - #: message delivery information. - delivery_info = None - - #: worker node name - hostname = None - - def __init__(self, id, name, args, kwargs, delivery_info, hostname): - self.id = id - self.name = name - self.args = args - self.kwargs = kwargs - self.delivery_info = delivery_info - self.hostname = hostname - - @classmethod - def from_request(cls, request): - return cls(request.id, request.name, request.args, - request.kwargs, request.delivery_info, request.hostname) - - -class Batches(Task): - abstract = True - - #: Maximum number of message in buffer. - flush_every = 10 - - #: Timeout in seconds before buffer is flushed anyway. - flush_interval = 30 - - def __init__(self): - self._buffer = Queue() - self._count = count(1) - self._tref = None - self._pool = None - - def run(self, requests): - raise NotImplementedError('must implement run(requests)') - - def Strategy(self, task, app, consumer): - self._pool = consumer.pool - hostname = consumer.hostname - eventer = consumer.event_dispatcher - Req = Request - connection_errors = consumer.connection_errors - timer = consumer.timer - put_buffer = self._buffer.put - flush_buffer = self._do_flush - - def task_message_handler(message, body, ack, reject, callbacks, **kw): - request = Req(body, on_ack=ack, app=app, hostname=hostname, - events=eventer, task=task, - connection_errors=connection_errors, - delivery_info=message.delivery_info) - put_buffer(request) - - if self._tref is None: # first request starts flush timer. - self._tref = timer.call_repeatedly( - self.flush_interval, flush_buffer, - ) - - if not next(self._count) % self.flush_every: - flush_buffer() - - return task_message_handler - - def flush(self, requests): - return self.apply_buffer(requests, ([SimpleRequest.from_request(r) - for r in requests], )) - - def _do_flush(self): - logger.debug('Batches: Wake-up to flush buffer...') - requests = None - if self._buffer.qsize(): - requests = list(consume_queue(self._buffer)) - if requests: - logger.debug('Batches: Buffer complete: %s', len(requests)) - self.flush(requests) - if not requests: - logger.debug('Batches: Cancelling timer: Nothing in buffer.') - self._tref.cancel() # cancel timer. - self._tref = None - - def apply_buffer(self, requests, args=(), kwargs={}): - acks_late = [], [] - [acks_late[r.task.acks_late].append(r) for r in requests] - assert requests and (acks_late[True] or acks_late[False]) - - def on_accepted(pid, time_accepted): - [req.acknowledge() for req in acks_late[False]] - - def on_return(result): - [req.acknowledge() for req in acks_late[True]] - - return self._pool.apply_async( - apply_batches_task, - (self, args, 0, None), - accept_callback=on_accepted, - callback=acks_late[True] and on_return or noop, - ) diff --git a/awx/lib/site-packages/celery/contrib/methods.py b/awx/lib/site-packages/celery/contrib/methods.py deleted file mode 100644 index 56aa7f479c..0000000000 --- a/awx/lib/site-packages/celery/contrib/methods.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- -""" -celery.contrib.methods -====================== - -Task decorator that supports creating tasks out of methods. - -Examples --------- - -.. code-block:: python - - from celery.contrib.methods import task - - class X(object): - - @task() - def add(self, x, y): - return x + y - -or with any task decorator: - -.. code-block:: python - - from celery.contrib.methods import task_method - - class X(object): - - @app.task(filter=task_method) - def add(self, x, y): - return x + y - -.. note:: - - The task must use the new Task base class (:class:`celery.Task`), - and the old base class using classmethods (``celery.task.Task``, - ``celery.task.base.Task``). - - This means that you have to use the task decorator from a Celery app - instance, and not the old-API: - - .. code-block:: python - - - from celery import task # BAD - from celery.task import task # ALSO BAD - - # GOOD: - app = Celery(...) - - @app.task(filter=task_method) - def foo(self): pass - - # ALSO GOOD: - from celery import current_app - - @current_app.task(filter=task_method) - def foo(self): pass - - # ALSO GOOD: - from celery import shared_task - - @shared_task(filter=task_method) - def foo(self): pass - -Caveats -------- - -- Automatic naming won't be able to know what the class name is. - - The name will still be module_name + task_name, - so two methods with the same name in the same module will collide - so that only one task can run: - - .. code-block:: python - - class A(object): - - @task() - def add(self, x, y): - return x + y - - class B(object): - - @task() - def add(self, x, y): - return x + y - - would have to be written as: - - .. code-block:: python - - class A(object): - @task(name='A.add') - def add(self, x, y): - return x + y - - class B(object): - @task(name='B.add') - def add(self, x, y): - return x + y - -""" - -from __future__ import absolute_import - -from celery import current_app - -__all__ = ['task_method', 'task'] - - -class task_method(object): - - def __init__(self, task, *args, **kwargs): - self.task = task - - def __get__(self, obj, type=None): - if obj is None: - return self.task - task = self.task.__class__() - task.__self__ = obj - return task - - -def task(*args, **kwargs): - return current_app.task(*args, **dict(kwargs, filter=task_method)) diff --git a/awx/lib/site-packages/celery/contrib/migrate.py b/awx/lib/site-packages/celery/contrib/migrate.py deleted file mode 100644 index e4a10e9b97..0000000000 --- a/awx/lib/site-packages/celery/contrib/migrate.py +++ /dev/null @@ -1,365 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.contrib.migrate - ~~~~~~~~~~~~~~~~~~~~~~ - - Migration tools. - -""" -from __future__ import absolute_import, print_function, unicode_literals - -import socket - -from functools import partial -from itertools import cycle, islice - -from kombu import eventloop, Queue -from kombu.common import maybe_declare -from kombu.utils.encoding import ensure_bytes - -from celery.app import app_or_default -from celery.five import string, string_t -from celery.utils import worker_direct - -__all__ = ['StopFiltering', 'State', 'republish', 'migrate_task', - 'migrate_tasks', 'move', 'task_id_eq', 'task_id_in', - 'start_filter', 'move_task_by_id', 'move_by_idmap', - 'move_by_taskmap', 'move_direct', 'move_direct_by_id'] - -MOVING_PROGRESS_FMT = """\ -Moving task {state.filtered}/{state.strtotal}: \ -{body[task]}[{body[id]}]\ -""" - - -class StopFiltering(Exception): - pass - - -class State(object): - count = 0 - filtered = 0 - total_apx = 0 - - @property - def strtotal(self): - if not self.total_apx: - return '?' - return string(self.total_apx) - - def __repr__(self): - if self.filtered: - return '^{0.filtered}'.format(self) - return '{0.count}/{0.strtotal}'.format(self) - - -def republish(producer, message, exchange=None, routing_key=None, - remove_props=['application_headers', - 'content_type', - 'content_encoding', - 'headers']): - body = ensure_bytes(message.body) # use raw message body. - info, headers, props = (message.delivery_info, - message.headers, message.properties) - exchange = info['exchange'] if exchange is None else exchange - routing_key = info['routing_key'] if routing_key is None else routing_key - ctype, enc = message.content_type, message.content_encoding - # remove compression header, as this will be inserted again - # when the message is recompressed. - compression = headers.pop('compression', None) - - for key in remove_props: - props.pop(key, None) - - producer.publish(ensure_bytes(body), exchange=exchange, - routing_key=routing_key, compression=compression, - headers=headers, content_type=ctype, - content_encoding=enc, **props) - - -def migrate_task(producer, body_, message, queues=None): - info = message.delivery_info - queues = {} if queues is None else queues - republish(producer, message, - exchange=queues.get(info['exchange']), - routing_key=queues.get(info['routing_key'])) - - -def filter_callback(callback, tasks): - - def filtered(body, message): - if tasks and body['task'] not in tasks: - return - - return callback(body, message) - return filtered - - -def migrate_tasks(source, dest, migrate=migrate_task, app=None, - queues=None, **kwargs): - app = app_or_default(app) - queues = prepare_queues(queues) - producer = app.amqp.TaskProducer(dest) - migrate = partial(migrate, producer, queues=queues) - - def on_declare_queue(queue): - new_queue = queue(producer.channel) - new_queue.name = queues.get(queue.name, queue.name) - if new_queue.routing_key == queue.name: - new_queue.routing_key = queues.get(queue.name, - new_queue.routing_key) - if new_queue.exchange.name == queue.name: - new_queue.exchange.name = queues.get(queue.name, queue.name) - new_queue.declare() - - return start_filter(app, source, migrate, queues=queues, - on_declare_queue=on_declare_queue, **kwargs) - - -def _maybe_queue(app, q): - if isinstance(q, string_t): - return app.amqp.queues[q] - return q - - -def move(predicate, connection=None, exchange=None, routing_key=None, - source=None, app=None, callback=None, limit=None, transform=None, - **kwargs): - """Find tasks by filtering them and move the tasks to a new queue. - - :param predicate: Filter function used to decide which messages - to move. Must accept the standard signature of ``(body, message)`` - used by Kombu consumer callbacks. If the predicate wants the message - to be moved it must return either: - - 1) a tuple of ``(exchange, routing_key)``, or - - 2) a :class:`~kombu.entity.Queue` instance, or - - 3) any other true value which means the specified - ``exchange`` and ``routing_key`` arguments will be used. - - :keyword connection: Custom connection to use. - :keyword source: Optional list of source queues to use instead of the - default (which is the queues in :setting:`CELERY_QUEUES`). - This list can also contain new :class:`~kombu.entity.Queue` instances. - :keyword exchange: Default destination exchange. - :keyword routing_key: Default destination routing key. - :keyword limit: Limit number of messages to filter. - :keyword callback: Callback called after message moved, - with signature ``(state, body, message)``. - :keyword transform: Optional function to transform the return - value (destination) of the filter function. - - Also supports the same keyword arguments as :func:`start_filter`. - - To demonstrate, the :func:`move_task_by_id` operation can be implemented - like this: - - .. code-block:: python - - def is_wanted_task(body, message): - if body['id'] == wanted_id: - return Queue('foo', exchange=Exchange('foo'), - routing_key='foo') - - move(is_wanted_task) - - or with a transform: - - .. code-block:: python - - def transform(value): - if isinstance(value, string_t): - return Queue(value, Exchange(value), value) - return value - - move(is_wanted_task, transform=transform) - - The predicate may also return a tuple of ``(exchange, routing_key)`` - to specify the destination to where the task should be moved, - or a :class:`~kombu.entitiy.Queue` instance. - Any other true value means that the task will be moved to the - default exchange/routing_key. - - """ - app = app_or_default(app) - queues = [_maybe_queue(app, queue) for queue in source or []] or None - with app.connection_or_acquire(connection, pool=False) as conn: - producer = app.amqp.TaskProducer(conn) - state = State() - - def on_task(body, message): - ret = predicate(body, message) - if ret: - if transform: - ret = transform(ret) - if isinstance(ret, Queue): - maybe_declare(ret, conn.default_channel) - ex, rk = ret.exchange.name, ret.routing_key - else: - ex, rk = expand_dest(ret, exchange, routing_key) - republish(producer, message, - exchange=ex, routing_key=rk) - message.ack() - - state.filtered += 1 - if callback: - callback(state, body, message) - if limit and state.filtered >= limit: - raise StopFiltering() - - return start_filter(app, conn, on_task, consume_from=queues, **kwargs) - - -def expand_dest(ret, exchange, routing_key): - try: - ex, rk = ret - except (TypeError, ValueError): - ex, rk = exchange, routing_key - return ex, rk - - -def task_id_eq(task_id, body, message): - return body['id'] == task_id - - -def task_id_in(ids, body, message): - return body['id'] in ids - - -def prepare_queues(queues): - if isinstance(queues, string_t): - queues = queues.split(',') - if isinstance(queues, list): - queues = dict(tuple(islice(cycle(q.split(':')), None, 2)) - for q in queues) - if queues is None: - queues = {} - return queues - - -def start_filter(app, conn, filter, limit=None, timeout=1.0, - ack_messages=False, tasks=None, queues=None, - callback=None, forever=False, on_declare_queue=None, - consume_from=None, state=None, accept=None, **kwargs): - state = state or State() - queues = prepare_queues(queues) - consume_from = [_maybe_queue(app, q) - for q in consume_from or list(queues)] - if isinstance(tasks, string_t): - tasks = set(tasks.split(',')) - if tasks is None: - tasks = set([]) - - def update_state(body, message): - state.count += 1 - if limit and state.count >= limit: - raise StopFiltering() - - def ack_message(body, message): - message.ack() - - consumer = app.amqp.TaskConsumer(conn, queues=consume_from, accept=accept) - - if tasks: - filter = filter_callback(filter, tasks) - update_state = filter_callback(update_state, tasks) - ack_message = filter_callback(ack_message, tasks) - - consumer.register_callback(filter) - consumer.register_callback(update_state) - if ack_messages: - consumer.register_callback(ack_message) - if callback is not None: - callback = partial(callback, state) - if tasks: - callback = filter_callback(callback, tasks) - consumer.register_callback(callback) - - # declare all queues on the new broker. - for queue in consumer.queues: - if queues and queue.name not in queues: - continue - if on_declare_queue is not None: - on_declare_queue(queue) - try: - _, mcount, _ = queue(consumer.channel).queue_declare(passive=True) - if mcount: - state.total_apx += mcount - except conn.channel_errors: - pass - - # start migrating messages. - with consumer: - try: - for _ in eventloop(conn, # pragma: no cover - timeout=timeout, ignore_timeouts=forever): - pass - except socket.timeout: - pass - except StopFiltering: - pass - return state - - -def move_task_by_id(task_id, dest, **kwargs): - """Find a task by id and move it to another queue. - - :param task_id: Id of task to move. - :param dest: Destination queue. - - Also supports the same keyword arguments as :func:`move`. - - """ - return move_by_idmap({task_id: dest}, **kwargs) - - -def move_by_idmap(map, **kwargs): - """Moves tasks by matching from a ``task_id: queue`` mapping, - where ``queue`` is a queue to move the task to. - - Example:: - - >>> move_by_idmap({ - ... '5bee6e82-f4ac-468e-bd3d-13e8600250bc': Queue('name'), - ... 'ada8652d-aef3-466b-abd2-becdaf1b82b3': Queue('name'), - ... '3a2b140d-7db1-41ba-ac90-c36a0ef4ab1f': Queue('name')}, - ... queues=['hipri']) - - """ - def task_id_in_map(body, message): - return map.get(body['id']) - - # adding the limit means that we don't have to consume any more - # when we've found everything. - return move(task_id_in_map, limit=len(map), **kwargs) - - -def move_by_taskmap(map, **kwargs): - """Moves tasks by matching from a ``task_name: queue`` mapping, - where ``queue`` is the queue to move the task to. - - Example:: - - >>> move_by_taskmap({ - ... 'tasks.add': Queue('name'), - ... 'tasks.mul': Queue('name'), - ... }) - - """ - - def task_name_in_map(body, message): - return map.get(body['task']) # <- name of task - - return move(task_name_in_map, **kwargs) - - -def filter_status(state, body, message, **kwargs): - print(MOVING_PROGRESS_FMT.format(state=state, body=body, **kwargs)) - - -move_direct = partial(move, transform=worker_direct) -move_direct_by_id = partial(move_task_by_id, transform=worker_direct) -move_direct_by_idmap = partial(move_by_idmap, transform=worker_direct) -move_direct_by_taskmap = partial(move_by_taskmap, transform=worker_direct) diff --git a/awx/lib/site-packages/celery/contrib/rdb.py b/awx/lib/site-packages/celery/contrib/rdb.py deleted file mode 100644 index 3e9f55bbaa..0000000000 --- a/awx/lib/site-packages/celery/contrib/rdb.py +++ /dev/null @@ -1,180 +0,0 @@ -# -*- coding: utf-8 -*- -""" -celery.contrib.rdb -================== - -Remote debugger for Celery tasks running in multiprocessing pool workers. -Inspired by http://snippets.dzone.com/posts/show/7248 - -**Usage** - -.. code-block:: python - - from celery.contrib import rdb - from celery import task - - @task() - def add(x, y): - result = x + y - rdb.set_trace() - return result - - -**Environment Variables** - -.. envvar:: CELERY_RDB_HOST - - Hostname to bind to. Default is '127.0.01', which means the socket - will only be accessible from the local host. - -.. envvar:: CELERY_RDB_PORT - - Base port to bind to. Default is 6899. - The debugger will try to find an available port starting from the - base port. The selected port will be logged by the worker. - -""" -from __future__ import absolute_import, print_function - -import errno -import os -import socket -import sys - -from pdb import Pdb - -from billiard import current_process - -from celery.five import range -from celery.platforms import ignore_errno - -__all__ = ['CELERY_RDB_HOST', 'CELERY_RDB_PORT', 'default_port', - 'Rdb', 'debugger', 'set_trace'] - -default_port = 6899 - -CELERY_RDB_HOST = os.environ.get('CELERY_RDB_HOST') or '127.0.0.1' -CELERY_RDB_PORT = int(os.environ.get('CELERY_RDB_PORT') or default_port) - -#: Holds the currently active debugger. -_current = [None] - -_frame = getattr(sys, '_getframe') - -NO_AVAILABLE_PORT = """\ -{self.ident}: Couldn't find an available port. - -Please specify one using the CELERY_RDB_PORT environment variable. -""" - -BANNER = """\ -{self.ident}: Please telnet into {self.host} {self.port}. - -Type `exit` in session to continue. - -{self.ident}: Waiting for client... -""" - -SESSION_STARTED = '{self.ident}: Now in session with {self.remote_addr}.' -SESSION_ENDED = '{self.ident}: Session with {self.remote_addr} ended.' - - -class Rdb(Pdb): - me = 'Remote Debugger' - _prev_outs = None - _sock = None - - def __init__(self, host=CELERY_RDB_HOST, port=CELERY_RDB_PORT, - port_search_limit=100, port_skew=+0, out=sys.stdout): - self.active = True - self.out = out - - self._prev_handles = sys.stdin, sys.stdout - - self._sock, this_port = self.get_avail_port( - host, port, port_search_limit, port_skew, - ) - self._sock.setblocking(1) - self._sock.listen(1) - self.ident = '{0}:{1}'.format(self.me, this_port) - self.host = host - self.port = this_port - self.say(BANNER.format(self=self)) - - self._client, address = self._sock.accept() - self._client.setblocking(1) - self.remote_addr = ':'.join(str(v) for v in address) - self.say(SESSION_STARTED.format(self=self)) - self._handle = sys.stdin = sys.stdout = self._client.makefile('rw') - Pdb.__init__(self, completekey='tab', - stdin=self._handle, stdout=self._handle) - - def get_avail_port(self, host, port, search_limit=100, skew=+0): - try: - _, skew = current_process().name.split('-') - skew = int(skew) - except ValueError: - pass - this_port = None - for i in range(search_limit): - _sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - this_port = port + skew + i - try: - _sock.bind((host, this_port)) - except socket.error as exc: - if exc.errno in [errno.EADDRINUSE, errno.EINVAL]: - continue - raise - else: - return _sock, this_port - else: - raise Exception(NO_AVAILABLE_PORT.format(self=self)) - - def say(self, m): - print(m, file=self.out) - - def _close_session(self): - self.stdin, self.stdout = sys.stdin, sys.stdout = self._prev_handles - self._handle.close() - self._client.close() - self._sock.close() - self.active = False - self.say(SESSION_ENDED.format(self=self)) - - def do_continue(self, arg): - self._close_session() - self.set_continue() - return 1 - do_c = do_cont = do_continue - - def do_quit(self, arg): - self._close_session() - self.set_quit() - return 1 - do_q = do_exit = do_quit - - def set_trace(self, frame=None): - if frame is None: - frame = _frame().f_back - with ignore_errno(errno.ECONNRESET): - Pdb.set_trace(self, frame) - - def set_quit(self): - # this raises a BdbQuit exception that we are unable to catch. - sys.settrace(None) - - -def debugger(): - """Return the current debugger instance (if any), - or creates a new one.""" - rdb = _current[0] - if rdb is None or not rdb.active: - rdb = _current[0] = Rdb() - return rdb - - -def set_trace(frame=None): - """Set breakpoint at current location, or a specified frame""" - if frame is None: - frame = _frame().f_back - return debugger().set_trace(frame) diff --git a/awx/lib/site-packages/celery/contrib/sphinx.py b/awx/lib/site-packages/celery/contrib/sphinx.py deleted file mode 100644 index d22d82f5fe..0000000000 --- a/awx/lib/site-packages/celery/contrib/sphinx.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- -""" -celery.contrib.sphinx -===================== - -Sphinx documentation plugin - -**Usage** - -Add the extension to your :file:`docs/conf.py` configuration module: - -.. code-block:: python - - extensions = (..., - 'celery.contrib.sphinx') - -If you would like to change the prefix for tasks in reference documentation -then you can change the ``celery_task_prefix`` configuration value: - -.. code-block:: python - - celery_task_prefix = '(task)' # < default - - -With the extension installed `autodoc` will automatically find -task decorated objects and generate the correct (as well as -add a ``(task)`` prefix), and you can also refer to the tasks -using `:task:proj.tasks.add` syntax. - -Use ``.. autotask::`` to manually document a task. - -""" -from __future__ import absolute_import - -from inspect import formatargspec, getargspec - -from sphinx.domains.python import PyModulelevel -from sphinx.ext.autodoc import FunctionDocumenter - -from celery.app.task import BaseTask - - -class TaskDocumenter(FunctionDocumenter): - objtype = 'task' - member_order = 11 - - @classmethod - def can_document_member(cls, member, membername, isattr, parent): - return isinstance(member, BaseTask) and getattr(member, '__wrapped__') - - def format_args(self): - wrapped = getattr(self.object, '__wrapped__') - if wrapped is not None: - argspec = getargspec(wrapped) - fmt = formatargspec(*argspec) - fmt = fmt.replace('\\', '\\\\') - return fmt - return '' - - def document_members(self, all_members=False): - pass - - -class TaskDirective(PyModulelevel): - - def get_signature_prefix(self, sig): - return self.env.config.celery_task_prefix - - -def setup(app): - app.add_autodocumenter(TaskDocumenter) - app.domains['py'].directives['task'] = TaskDirective - app.add_config_value('celery_task_prefix', '(task)', True) diff --git a/awx/lib/site-packages/celery/datastructures.py b/awx/lib/site-packages/celery/datastructures.py deleted file mode 100644 index 9c36a39575..0000000000 --- a/awx/lib/site-packages/celery/datastructures.py +++ /dev/null @@ -1,667 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.datastructures - ~~~~~~~~~~~~~~~~~~~~~ - - Custom types and data structures. - -""" -from __future__ import absolute_import, print_function, unicode_literals - -import sys -import time - -from collections import defaultdict, Mapping, MutableMapping, MutableSet -from heapq import heappush, heappop -from functools import partial -from itertools import chain - -from billiard.einfo import ExceptionInfo # noqa -from kombu.utils.encoding import safe_str -from kombu.utils.limits import TokenBucket # noqa - -from celery.five import items -from celery.utils.functional import LRUCache, first, uniq # noqa - -try: - from django.utils.functional import LazyObject, LazySettings -except ImportError: - class LazyObject(object): # noqa - pass - LazySettings = LazyObject # noqa - -DOT_HEAD = """ -{IN}{type} {id} {{ -{INp}graph [{attrs}] -""" -DOT_ATTR = '{name}={value}' -DOT_NODE = '{INp}"{0}" [{attrs}]' -DOT_EDGE = '{INp}"{0}" {dir} "{1}" [{attrs}]' -DOT_ATTRSEP = ', ' -DOT_DIRS = {'graph': '--', 'digraph': '->'} -DOT_TAIL = '{IN}}}' - -__all__ = ['GraphFormatter', 'CycleError', 'DependencyGraph', - 'AttributeDictMixin', 'AttributeDict', 'DictAttribute', - 'ConfigurationView', 'LimitedSet'] - - -def force_mapping(m): - if isinstance(m, (LazyObject, LazySettings)): - m = m._wrapped - return DictAttribute(m) if not isinstance(m, Mapping) else m - - -class GraphFormatter(object): - _attr = DOT_ATTR.strip() - _node = DOT_NODE.strip() - _edge = DOT_EDGE.strip() - _head = DOT_HEAD.strip() - _tail = DOT_TAIL.strip() - _attrsep = DOT_ATTRSEP - _dirs = dict(DOT_DIRS) - - scheme = { - 'shape': 'box', - 'arrowhead': 'vee', - 'style': 'filled', - 'fontname': 'HelveticaNeue', - } - edge_scheme = { - 'color': 'darkseagreen4', - 'arrowcolor': 'black', - 'arrowsize': 0.7, - } - node_scheme = {'fillcolor': 'palegreen3', 'color': 'palegreen4'} - term_scheme = {'fillcolor': 'palegreen1', 'color': 'palegreen2'} - graph_scheme = {'bgcolor': 'mintcream'} - - def __init__(self, root=None, type=None, id=None, - indent=0, inw=' ' * 4, **scheme): - self.id = id or 'dependencies' - self.root = root - self.type = type or 'digraph' - self.direction = self._dirs[self.type] - self.IN = inw * (indent or 0) - self.INp = self.IN + inw - self.scheme = dict(self.scheme, **scheme) - self.graph_scheme = dict(self.graph_scheme, root=self.label(self.root)) - - def attr(self, name, value): - value = '"{0}"'.format(value) - return self.FMT(self._attr, name=name, value=value) - - def attrs(self, d, scheme=None): - d = dict(self.scheme, **dict(scheme, **d or {}) if scheme else d) - return self._attrsep.join( - safe_str(self.attr(k, v)) for k, v in items(d) - ) - - def head(self, **attrs): - return self.FMT( - self._head, id=self.id, type=self.type, - attrs=self.attrs(attrs, self.graph_scheme), - ) - - def tail(self): - return self.FMT(self._tail) - - def label(self, obj): - return obj - - def node(self, obj, **attrs): - return self.draw_node(obj, self.node_scheme, attrs) - - def terminal_node(self, obj, **attrs): - return self.draw_node(obj, self.term_scheme, attrs) - - def edge(self, a, b, **attrs): - return self.draw_edge(a, b, **attrs) - - def _enc(self, s): - return s.encode('utf-8', 'ignore') - - def FMT(self, fmt, *args, **kwargs): - return self._enc(fmt.format( - *args, **dict(kwargs, IN=self.IN, INp=self.INp) - )) - - def draw_edge(self, a, b, scheme=None, attrs=None): - return self.FMT( - self._edge, self.label(a), self.label(b), - dir=self.direction, attrs=self.attrs(attrs, self.edge_scheme), - ) - - def draw_node(self, obj, scheme=None, attrs=None): - return self.FMT( - self._node, self.label(obj), attrs=self.attrs(attrs, scheme), - ) - - -class CycleError(Exception): - """A cycle was detected in an acyclic graph.""" - - -class DependencyGraph(object): - """A directed acyclic graph of objects and their dependencies. - - Supports a robust topological sort - to detect the order in which they must be handled. - - Takes an optional iterator of ``(obj, dependencies)`` - tuples to build the graph from. - - .. warning:: - - Does not support cycle detection. - - """ - - def __init__(self, it=None, formatter=None): - self.formatter = formatter or GraphFormatter() - self.adjacent = {} - if it is not None: - self.update(it) - - def add_arc(self, obj): - """Add an object to the graph.""" - self.adjacent.setdefault(obj, []) - - def add_edge(self, A, B): - """Add an edge from object ``A`` to object ``B`` - (``A`` depends on ``B``).""" - self[A].append(B) - - def connect(self, graph): - """Add nodes from another graph.""" - self.adjacent.update(graph.adjacent) - - def topsort(self): - """Sort the graph topologically. - - :returns: a list of objects in the order - in which they must be handled. - - """ - graph = DependencyGraph() - components = self._tarjan72() - - NC = dict((node, component) - for component in components - for node in component) - for component in components: - graph.add_arc(component) - for node in self: - node_c = NC[node] - for successor in self[node]: - successor_c = NC[successor] - if node_c != successor_c: - graph.add_edge(node_c, successor_c) - return [t[0] for t in graph._khan62()] - - def valency_of(self, obj): - """Return the valency (degree) of a vertex in the graph.""" - try: - l = [len(self[obj])] - except KeyError: - return 0 - for node in self[obj]: - l.append(self.valency_of(node)) - return sum(l) - - def update(self, it): - """Update the graph with data from a list - of ``(obj, dependencies)`` tuples.""" - tups = list(it) - for obj, _ in tups: - self.add_arc(obj) - for obj, deps in tups: - for dep in deps: - self.add_edge(obj, dep) - - def edges(self): - """Return generator that yields for all edges in the graph.""" - return (obj for obj, adj in items(self) if adj) - - def _khan62(self): - """Khans simple topological sort algorithm from '62 - - See http://en.wikipedia.org/wiki/Topological_sorting - - """ - count = defaultdict(lambda: 0) - result = [] - - for node in self: - for successor in self[node]: - count[successor] += 1 - ready = [node for node in self if not count[node]] - - while ready: - node = ready.pop() - result.append(node) - - for successor in self[node]: - count[successor] -= 1 - if count[successor] == 0: - ready.append(successor) - result.reverse() - return result - - def _tarjan72(self): - """Tarjan's algorithm to find strongly connected components. - - See http://bit.ly/vIMv3h. - - """ - result, stack, low = [], [], {} - - def visit(node): - if node in low: - return - num = len(low) - low[node] = num - stack_pos = len(stack) - stack.append(node) - - for successor in self[node]: - visit(successor) - low[node] = min(low[node], low[successor]) - - if num == low[node]: - component = tuple(stack[stack_pos:]) - stack[stack_pos:] = [] - result.append(component) - for item in component: - low[item] = len(self) - - for node in self: - visit(node) - - return result - - def to_dot(self, fh, formatter=None): - """Convert the graph to DOT format. - - :param fh: A file, or a file-like object to write the graph to. - - """ - seen = set() - draw = formatter or self.formatter - P = partial(print, file=fh) - - def if_not_seen(fun, obj): - if draw.label(obj) not in seen: - P(fun(obj)) - seen.add(draw.label(obj)) - - P(draw.head()) - for obj, adjacent in items(self): - if not adjacent: - if_not_seen(draw.terminal_node, obj) - for req in adjacent: - if_not_seen(draw.node, obj) - P(draw.edge(obj, req)) - P(draw.tail()) - - def format(self, obj): - return self.formatter(obj) if self.formatter else obj - - def __iter__(self): - return iter(self.adjacent) - - def __getitem__(self, node): - return self.adjacent[node] - - def __len__(self): - return len(self.adjacent) - - def __contains__(self, obj): - return obj in self.adjacent - - def _iterate_items(self): - return items(self.adjacent) - items = iteritems = _iterate_items - - def __repr__(self): - return '\n'.join(self.repr_node(N) for N in self) - - def repr_node(self, obj, level=1, fmt='{0}({1})'): - output = [fmt.format(obj, self.valency_of(obj))] - if obj in self: - for other in self[obj]: - d = fmt.format(other, self.valency_of(other)) - output.append(' ' * level + d) - output.extend(self.repr_node(other, level + 1).split('\n')[1:]) - return '\n'.join(output) - - -class AttributeDictMixin(object): - """Augment classes with a Mapping interface by adding attribute access. - - I.e. `d.key -> d[key]`. - - """ - - def __getattr__(self, k): - """`d.key -> d[key]`""" - try: - return self[k] - except KeyError: - raise AttributeError( - '{0!r} object has no attribute {1!r}'.format( - type(self).__name__, k)) - - def __setattr__(self, key, value): - """`d[key] = value -> d.key = value`""" - self[key] = value - - -class AttributeDict(dict, AttributeDictMixin): - """Dict subclass with attribute access.""" - pass - - -class DictAttribute(object): - """Dict interface to attributes. - - `obj[k] -> obj.k` - `obj[k] = val -> obj.k = val` - - """ - obj = None - - def __init__(self, obj): - object.__setattr__(self, 'obj', obj) - - def __getattr__(self, key): - return getattr(self.obj, key) - - def __setattr__(self, key, value): - return setattr(self.obj, key, value) - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - - def setdefault(self, key, default): - try: - return self[key] - except KeyError: - self[key] = default - return default - - def __getitem__(self, key): - try: - return getattr(self.obj, key) - except AttributeError: - raise KeyError(key) - - def __setitem__(self, key, value): - setattr(self.obj, key, value) - - def __contains__(self, key): - return hasattr(self.obj, key) - - def _iterate_keys(self): - return iter(dir(self.obj)) - iterkeys = _iterate_keys - - def __iter__(self): - return self._iterate_keys() - - def _iterate_items(self): - for key in self._iterate_keys(): - yield key, getattr(self.obj, key) - iteritems = _iterate_items - - def _iterate_values(self): - for key in self._iterate_keys(): - yield getattr(self.obj, key) - itervalues = _iterate_values - - if sys.version_info[0] == 3: # pragma: no cover - items = _iterate_items - keys = _iterate_keys - values = _iterate_values - else: - - def keys(self): - return list(self) - - def items(self): - return list(self._iterate_items()) - - def values(self): - return list(self._iterate_values()) -MutableMapping.register(DictAttribute) - - -class ConfigurationView(AttributeDictMixin): - """A view over an applications configuration dicts. - - Custom (but older) version of :class:`collections.ChainMap`. - - If the key does not exist in ``changes``, the ``defaults`` dicts - are consulted. - - :param changes: Dict containing changes to the configuration. - :param defaults: List of dicts containing the default configuration. - - """ - changes = None - defaults = None - _order = None - - def __init__(self, changes, defaults): - self.__dict__.update(changes=changes, defaults=defaults, - _order=[changes] + defaults) - - def add_defaults(self, d): - d = force_mapping(d) - self.defaults.insert(0, d) - self._order.insert(1, d) - - def __getitem__(self, key): - for d in self._order: - try: - return d[key] - except KeyError: - pass - raise KeyError(key) - - def __setitem__(self, key, value): - self.changes[key] = value - - def first(self, *keys): - return first(None, (self.get(key) for key in keys)) - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - - def clear(self): - """Remove all changes, but keep defaults.""" - self.changes.clear() - - def setdefault(self, key, default): - try: - return self[key] - except KeyError: - self[key] = default - return default - - def update(self, *args, **kwargs): - return self.changes.update(*args, **kwargs) - - def __contains__(self, key): - return any(key in m for m in self._order) - - def __bool__(self): - return any(self._order) - __nonzero__ = __bool__ # Py2 - - def __repr__(self): - return repr(dict(items(self))) - - def __iter__(self): - return self._iterate_keys() - - def __len__(self): - # The logic for iterating keys includes uniq(), - # so to be safe we count by explicitly iterating - return len(set().union(*self._order)) - - def _iter(self, op): - # defaults must be first in the stream, so values in - # changes takes precedence. - return chain(*[op(d) for d in reversed(self._order)]) - - def _iterate_keys(self): - return uniq(self._iter(lambda d: d)) - iterkeys = _iterate_keys - - def _iterate_items(self): - return ((key, self[key]) for key in self) - iteritems = _iterate_items - - def _iterate_values(self): - return (self[key] for key in self) - itervalues = _iterate_values - - if sys.version_info[0] == 3: # pragma: no cover - keys = _iterate_keys - items = _iterate_items - values = _iterate_values - - else: # noqa - def keys(self): - return list(self._iterate_keys()) - - def items(self): - return list(self._iterate_items()) - - def values(self): - return list(self._iterate_values()) - -MutableMapping.register(ConfigurationView) - - -class LimitedSet(object): - """Kind-of Set with limitations. - - Good for when you need to test for membership (`a in set`), - but the list might become too big. - - :keyword maxlen: Maximum number of members before we start - evicting expired members. - :keyword expires: Time in seconds, before a membership expires. - - """ - - def __init__(self, maxlen=None, expires=None, data=None, heap=None): - self.maxlen = maxlen - self.expires = expires - self._data = {} if data is None else data - self._heap = [] if heap is None else heap - # make shortcuts - self.__len__ = self._heap.__len__ - self.__iter__ = self._heap.__iter__ - self.__contains__ = self._data.__contains__ - - def add(self, value, now=time.time): - """Add a new member.""" - # offset is there to modify the length of the list, - # this way we can expire an item before inserting the value, - # and it will end up in correct order. - self.purge(1, offset=1) - inserted = now() - self._data[value] = inserted - heappush(self._heap, (inserted, value)) - - def clear(self): - """Remove all members""" - self._data.clear() - self._heap[:] = [] - - def discard(self, value): - """Remove membership by finding value.""" - try: - itime = self._data[value] - except KeyError: - return - try: - self._heap.remove((value, itime)) - except ValueError: - pass - self._data.pop(value, None) - pop_value = discard # XXX compat - - def purge(self, limit=None, offset=0, now=time.time): - """Purge expired items.""" - H, maxlen = self._heap, self.maxlen - if not maxlen: - return - - # If the data/heap gets corrupted and limit is None - # this will go into an infinite loop, so limit must - # have a value to guard the loop. - limit = len(self) + offset if limit is None else limit - - i = 0 - while len(self) + offset > maxlen: - if i >= limit: - break - try: - item = heappop(H) - except IndexError: - break - if self.expires: - if now() < item[0] + self.expires: - heappush(H, item) - break - try: - self._data.pop(item[1]) - except KeyError: # out of sync with heap - pass - i += 1 - - def update(self, other, heappush=heappush): - if isinstance(other, LimitedSet): - self._data.update(other._data) - self._heap.extend(other._heap) - self._heap.sort() - else: - for obj in other: - self.add(obj) - - def as_dict(self): - return self._data - - def __eq__(self, other): - return self._heap == other._heap - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return 'LimitedSet({0})'.format(len(self)) - - def __iter__(self): - return (item[1] for item in self._heap) - - def __len__(self): - return len(self._heap) - - def __contains__(self, key): - return key in self._data - - def __reduce__(self): - return self.__class__, ( - self.maxlen, self.expires, self._data, self._heap, - ) -MutableSet.register(LimitedSet) diff --git a/awx/lib/site-packages/celery/events/__init__.py b/awx/lib/site-packages/celery/events/__init__.py deleted file mode 100644 index 931f3953ec..0000000000 --- a/awx/lib/site-packages/celery/events/__init__.py +++ /dev/null @@ -1,407 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.events - ~~~~~~~~~~~~~ - - Events is a stream of messages sent for certain actions occurring - in the worker (and clients if :setting:`CELERY_SEND_TASK_SENT_EVENT` - is enabled), used for monitoring purposes. - -""" -from __future__ import absolute_import - -import os -import time -import threading -import warnings - -from collections import deque -from contextlib import contextmanager -from copy import copy -from operator import itemgetter - -from kombu import Exchange, Queue, Producer -from kombu.connection import maybe_channel -from kombu.mixins import ConsumerMixin -from kombu.utils import cached_property - -from celery.app import app_or_default -from celery.utils import anon_nodename, uuid -from celery.utils.functional import dictfilter -from celery.utils.timeutils import adjust_timestamp, utcoffset, maybe_s_to_ms - -__all__ = ['Events', 'Event', 'EventDispatcher', 'EventReceiver'] - -event_exchange = Exchange('celeryev', type='topic') - -_TZGETTER = itemgetter('utcoffset', 'timestamp') - -W_YAJL = """ -anyjson is currently using the yajl library. -This json implementation is broken, it severely truncates floats -so timestamps will not work. - -Please uninstall yajl or force anyjson to use a different library. -""" - -CLIENT_CLOCK_SKEW = -1 - - -def get_exchange(conn): - ex = copy(event_exchange) - if conn.transport.driver_type == 'redis': - # quick hack for Issue #436 - ex.type = 'fanout' - return ex - - -def Event(type, _fields=None, __dict__=dict, __now__=time.time, **fields): - """Create an event. - - An event is a dictionary, the only required field is ``type``. - A ``timestamp`` field will be set to the current time if not provided. - - """ - event = __dict__(_fields, **fields) if _fields else fields - if 'timestamp' not in event: - event.update(timestamp=__now__(), type=type) - else: - event['type'] = type - return event - - -def group_from(type): - """Get the group part of an event type name. - - E.g.:: - - >>> group_from('task-sent') - 'task' - - >>> group_from('custom-my-event') - 'custom' - - """ - return type.split('-', 1)[0] - - -class EventDispatcher(object): - """Dispatches event messages. - - :param connection: Connection to the broker. - - :keyword hostname: Hostname to identify ourselves as, - by default uses the hostname returned by - :func:`~celery.utils.anon_nodename`. - - :keyword groups: List of groups to send events for. :meth:`send` will - ignore send requests to groups not in this list. - If this is :const:`None`, all events will be sent. Example groups - include ``"task"`` and ``"worker"``. - - :keyword enabled: Set to :const:`False` to not actually publish any events, - making :meth:`send` a noop operation. - - :keyword channel: Can be used instead of `connection` to specify - an exact channel to use when sending events. - - :keyword buffer_while_offline: If enabled events will be buffered - while the connection is down. :meth:`flush` must be called - as soon as the connection is re-established. - - You need to :meth:`close` this after use. - - """ - DISABLED_TRANSPORTS = set(['sql']) - - app = None - - # set of callbacks to be called when :meth:`enabled`. - on_enabled = None - - # set of callbacks to be called when :meth:`disabled`. - on_disabled = None - - def __init__(self, connection=None, hostname=None, enabled=True, - channel=None, buffer_while_offline=True, app=None, - serializer=None, groups=None): - self.app = app_or_default(app or self.app) - self.connection = connection - self.channel = channel - self.hostname = hostname or anon_nodename() - self.buffer_while_offline = buffer_while_offline - self.mutex = threading.Lock() - self.producer = None - self._outbound_buffer = deque() - self.serializer = serializer or self.app.conf.CELERY_EVENT_SERIALIZER - self.on_enabled = set() - self.on_disabled = set() - self.groups = set(groups or []) - self.tzoffset = [-time.timezone, -time.altzone] - self.clock = self.app.clock - if not connection and channel: - self.connection = channel.connection.client - self.enabled = enabled - conninfo = self.connection or self.app.connection() - self.exchange = get_exchange(conninfo) - if conninfo.transport.driver_type in self.DISABLED_TRANSPORTS: - self.enabled = False - if self.enabled: - self.enable() - self.headers = {'hostname': self.hostname} - self.pid = os.getpid() - self.warn_if_yajl() - - def warn_if_yajl(self): - import anyjson - if anyjson.implementation.name == 'yajl': - warnings.warn(UserWarning(W_YAJL)) - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - def enable(self): - self.producer = Producer(self.channel or self.connection, - exchange=self.exchange, - serializer=self.serializer) - self.enabled = True - for callback in self.on_enabled: - callback() - - def disable(self): - if self.enabled: - self.enabled = False - self.close() - for callback in self.on_disabled: - callback() - - def publish(self, type, fields, producer, retry=False, - retry_policy=None, blind=False, utcoffset=utcoffset, - Event=Event): - """Publish event using a custom :class:`~kombu.Producer` - instance. - - :param type: Event type name, with group separated by dash (`-`). - :param fields: Dictionary of event fields, must be json serializable. - :param producer: :class:`~kombu.Producer` instance to use, - only the ``publish`` method will be called. - :keyword retry: Retry in the event of connection failure. - :keyword retry_policy: Dict of custom retry policy, see - :meth:`~kombu.Connection.ensure`. - :keyword blind: Don't set logical clock value (also do not forward - the internal logical clock). - :keyword Event: Event type used to create event, - defaults to :func:`Event`. - :keyword utcoffset: Function returning the current utcoffset in hours. - - """ - - with self.mutex: - clock = None if blind else self.clock.forward() - event = Event(type, hostname=self.hostname, utcoffset=utcoffset(), - pid=self.pid, clock=clock, **fields) - exchange = self.exchange - producer.publish( - event, - routing_key=type.replace('-', '.'), - exchange=exchange.name, - retry=retry, - retry_policy=retry_policy, - declare=[exchange], - serializer=self.serializer, - headers=self.headers, - ) - - def send(self, type, blind=False, **fields): - """Send event. - - :param type: Event type name, with group separated by dash (`-`). - :keyword retry: Retry in the event of connection failure. - :keyword retry_policy: Dict of custom retry policy, see - :meth:`~kombu.Connection.ensure`. - :keyword blind: Don't set logical clock value (also do not forward - the internal logical clock). - :keyword Event: Event type used to create event, - defaults to :func:`Event`. - :keyword utcoffset: Function returning the current utcoffset in hours. - :keyword \*\*fields: Event fields, must be json serializable. - - """ - if self.enabled: - groups = self.groups - if groups and group_from(type) not in groups: - return - try: - self.publish(type, fields, self.producer, blind) - except Exception as exc: - if not self.buffer_while_offline: - raise - self._outbound_buffer.append((type, fields, exc)) - - def flush(self): - """Flushes the outbound buffer.""" - while self._outbound_buffer: - try: - type, fields, _ = self._outbound_buffer.popleft() - except IndexError: - return - self.send(type, **fields) - - def extend_buffer(self, other): - """Copies the outbound buffer of another instance.""" - self._outbound_buffer.extend(other._outbound_buffer) - - def close(self): - """Close the event dispatcher.""" - self.mutex.locked() and self.mutex.release() - self.producer = None - - def _get_publisher(self): - return self.producer - - def _set_publisher(self, producer): - self.producer = producer - publisher = property(_get_publisher, _set_publisher) # XXX compat - - -class EventReceiver(ConsumerMixin): - """Capture events. - - :param connection: Connection to the broker. - :keyword handlers: Event handlers. - - :attr:`handlers` is a dict of event types and their handlers, - the special handler `"*"` captures all events that doesn't have a - handler. - - """ - app = None - - def __init__(self, channel, handlers=None, routing_key='#', - node_id=None, app=None, queue_prefix='celeryev', - accept=None): - self.app = app_or_default(app or self.app) - self.channel = maybe_channel(channel) - self.handlers = {} if handlers is None else handlers - self.routing_key = routing_key - self.node_id = node_id or uuid() - self.queue_prefix = queue_prefix - self.exchange = get_exchange(self.connection or self.app.connection()) - self.queue = Queue('.'.join([self.queue_prefix, self.node_id]), - exchange=self.exchange, - routing_key=self.routing_key, - auto_delete=True, - durable=False, - queue_arguments=self._get_queue_arguments()) - self.clock = self.app.clock - self.adjust_clock = self.clock.adjust - self.forward_clock = self.clock.forward - if accept is None: - accept = set([self.app.conf.CELERY_EVENT_SERIALIZER, 'json']) - self.accept = accept - - def _get_queue_arguments(self): - conf = self.app.conf - return dictfilter({ - 'x-message-ttl': maybe_s_to_ms(conf.CELERY_EVENT_QUEUE_TTL), - 'x-expires': maybe_s_to_ms(conf.CELERY_EVENT_QUEUE_EXPIRES), - }) - - def process(self, type, event): - """Process the received event by dispatching it to the appropriate - handler.""" - handler = self.handlers.get(type) or self.handlers.get('*') - handler and handler(event) - - def get_consumers(self, Consumer, channel): - return [Consumer(queues=[self.queue], - callbacks=[self._receive], no_ack=True, - accept=self.accept)] - - def on_consume_ready(self, connection, channel, consumers, - wakeup=True, **kwargs): - if wakeup: - self.wakeup_workers(channel=channel) - - def itercapture(self, limit=None, timeout=None, wakeup=True): - return self.consume(limit=limit, timeout=timeout, wakeup=wakeup) - - def capture(self, limit=None, timeout=None, wakeup=True): - """Open up a consumer capturing events. - - This has to run in the main process, and it will never - stop unless forced via :exc:`KeyboardInterrupt` or :exc:`SystemExit`. - - """ - return list(self.consume(limit=limit, timeout=timeout, wakeup=wakeup)) - - def wakeup_workers(self, channel=None): - self.app.control.broadcast('heartbeat', - connection=self.connection, - channel=channel) - - def event_from_message(self, body, localize=True, - now=time.time, tzfields=_TZGETTER, - adjust_timestamp=adjust_timestamp, - CLIENT_CLOCK_SKEW=CLIENT_CLOCK_SKEW): - type = body['type'] - if type == 'task-sent': - # clients never sync so cannot use their clock value - _c = body['clock'] = (self.clock.value or 1) + CLIENT_CLOCK_SKEW - self.adjust_clock(_c) - else: - try: - clock = body['clock'] - except KeyError: - body['clock'] = self.forward_clock() - else: - self.adjust_clock(clock) - - if localize: - try: - offset, timestamp = tzfields(body) - except KeyError: - pass - else: - body['timestamp'] = adjust_timestamp(timestamp, offset) - body['local_received'] = now() - return type, body - - def _receive(self, body, message): - self.process(*self.event_from_message(body)) - - @property - def connection(self): - return self.channel.connection.client if self.channel else None - - -class Events(object): - - def __init__(self, app=None): - self.app = app - - @cached_property - def Receiver(self): - return self.app.subclass_with_self(EventReceiver, - reverse='events.Receiver') - - @cached_property - def Dispatcher(self): - return self.app.subclass_with_self(EventDispatcher, - reverse='events.Dispatcher') - - @cached_property - def State(self): - return self.app.subclass_with_self('celery.events.state:State', - reverse='events.State') - - @contextmanager - def default_dispatcher(self, hostname=None, enabled=True, - buffer_while_offline=False): - with self.app.amqp.producer_pool.acquire(block=True) as prod: - with self.Dispatcher(prod.connection, hostname, enabled, - prod.channel, buffer_while_offline) as d: - yield d diff --git a/awx/lib/site-packages/celery/events/cursesmon.py b/awx/lib/site-packages/celery/events/cursesmon.py deleted file mode 100644 index 796565fc49..0000000000 --- a/awx/lib/site-packages/celery/events/cursesmon.py +++ /dev/null @@ -1,544 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.events.cursesmon - ~~~~~~~~~~~~~~~~~~~~~~~ - - Graphical monitor of Celery events using curses. - -""" -from __future__ import absolute_import, print_function - -import curses -import sys -import threading - -from datetime import datetime -from itertools import count -from textwrap import wrap -from time import time -from math import ceil - -from celery import VERSION_BANNER -from celery import states -from celery.app import app_or_default -from celery.five import items, values -from celery.utils.text import abbr, abbrtask - -__all__ = ['CursesMonitor', 'evtop'] - -BORDER_SPACING = 4 -LEFT_BORDER_OFFSET = 3 -UUID_WIDTH = 36 -STATE_WIDTH = 8 -TIMESTAMP_WIDTH = 8 -MIN_WORKER_WIDTH = 15 -MIN_TASK_WIDTH = 16 - -# this module is considered experimental -# we don't care about coverage. - -STATUS_SCREEN = """\ -events: {s.event_count} tasks:{s.task_count} workers:{w_alive}/{w_all} -""" - - -class CursesMonitor(object): # pragma: no cover - keymap = {} - win = None - screen_width = None - screen_delay = 10 - selected_task = None - selected_position = 0 - selected_str = 'Selected: ' - foreground = curses.COLOR_BLACK - background = curses.COLOR_WHITE - online_str = 'Workers online: ' - help_title = 'Keys: ' - help = ('j:down k:up i:info t:traceback r:result c:revoke ^c: quit') - greet = 'celery events {0}'.format(VERSION_BANNER) - info_str = 'Info: ' - - def __init__(self, state, app, keymap=None): - self.app = app - self.keymap = keymap or self.keymap - self.state = state - default_keymap = {'J': self.move_selection_down, - 'K': self.move_selection_up, - 'C': self.revoke_selection, - 'T': self.selection_traceback, - 'R': self.selection_result, - 'I': self.selection_info, - 'L': self.selection_rate_limit} - self.keymap = dict(default_keymap, **self.keymap) - self.lock = threading.RLock() - - def format_row(self, uuid, task, worker, timestamp, state): - mx = self.display_width - - # include spacing - detail_width = mx - 1 - STATE_WIDTH - 1 - TIMESTAMP_WIDTH - uuid_space = detail_width - 1 - MIN_TASK_WIDTH - 1 - MIN_WORKER_WIDTH - - if uuid_space < UUID_WIDTH: - uuid_width = uuid_space - else: - uuid_width = UUID_WIDTH - - detail_width = detail_width - uuid_width - 1 - task_width = int(ceil(detail_width / 2.0)) - worker_width = detail_width - task_width - 1 - - uuid = abbr(uuid, uuid_width).ljust(uuid_width) - worker = abbr(worker, worker_width).ljust(worker_width) - task = abbrtask(task, task_width).ljust(task_width) - state = abbr(state, STATE_WIDTH).ljust(STATE_WIDTH) - timestamp = timestamp.ljust(TIMESTAMP_WIDTH) - - row = '{0} {1} {2} {3} {4} '.format(uuid, worker, task, - timestamp, state) - if self.screen_width is None: - self.screen_width = len(row[:mx]) - return row[:mx] - - @property - def screen_width(self): - _, mx = self.win.getmaxyx() - return mx - - @property - def screen_height(self): - my, _ = self.win.getmaxyx() - return my - - @property - def display_width(self): - _, mx = self.win.getmaxyx() - return mx - BORDER_SPACING - - @property - def display_height(self): - my, _ = self.win.getmaxyx() - return my - 10 - - @property - def limit(self): - return self.display_height - - def find_position(self): - if not self.tasks: - return 0 - for i, e in enumerate(self.tasks): - if self.selected_task == e[0]: - return i - return 0 - - def move_selection_up(self): - self.move_selection(-1) - - def move_selection_down(self): - self.move_selection(1) - - def move_selection(self, direction=1): - if not self.tasks: - return - pos = self.find_position() - try: - self.selected_task = self.tasks[pos + direction][0] - except IndexError: - self.selected_task = self.tasks[0][0] - - keyalias = {curses.KEY_DOWN: 'J', - curses.KEY_UP: 'K', - curses.KEY_ENTER: 'I'} - - def handle_keypress(self): - try: - key = self.win.getkey().upper() - except: - return - key = self.keyalias.get(key) or key - handler = self.keymap.get(key) - if handler is not None: - handler() - - def alert(self, callback, title=None): - self.win.erase() - my, mx = self.win.getmaxyx() - y = blank_line = count(2) - if title: - self.win.addstr(next(y), 3, title, - curses.A_BOLD | curses.A_UNDERLINE) - next(blank_line) - callback(my, mx, next(y)) - self.win.addstr(my - 1, 0, 'Press any key to continue...', - curses.A_BOLD) - self.win.refresh() - while 1: - try: - return self.win.getkey().upper() - except: - pass - - def selection_rate_limit(self): - if not self.selected_task: - return curses.beep() - task = self.state.tasks[self.selected_task] - if not task.name: - return curses.beep() - - my, mx = self.win.getmaxyx() - r = 'New rate limit: ' - self.win.addstr(my - 2, 3, r, curses.A_BOLD | curses.A_UNDERLINE) - self.win.addstr(my - 2, len(r) + 3, ' ' * (mx - len(r))) - rlimit = self.readline(my - 2, 3 + len(r)) - - if rlimit: - reply = self.app.control.rate_limit(task.name, - rlimit.strip(), reply=True) - self.alert_remote_control_reply(reply) - - def alert_remote_control_reply(self, reply): - - def callback(my, mx, xs): - y = count(xs) - if not reply: - self.win.addstr( - next(y), 3, 'No replies received in 1s deadline.', - curses.A_BOLD + curses.color_pair(2), - ) - return - - for subreply in reply: - curline = next(y) - - host, response = next(items(subreply)) - host = '{0}: '.format(host) - self.win.addstr(curline, 3, host, curses.A_BOLD) - attr = curses.A_NORMAL - text = '' - if 'error' in response: - text = response['error'] - attr |= curses.color_pair(2) - elif 'ok' in response: - text = response['ok'] - attr |= curses.color_pair(3) - self.win.addstr(curline, 3 + len(host), text, attr) - - return self.alert(callback, 'Remote Control Command Replies') - - def readline(self, x, y): - buffer = str() - curses.echo() - try: - i = 0 - while 1: - ch = self.win.getch(x, y + i) - if ch != -1: - if ch in (10, curses.KEY_ENTER): # enter - break - if ch in (27, ): - buffer = str() - break - buffer += chr(ch) - i += 1 - finally: - curses.noecho() - return buffer - - def revoke_selection(self): - if not self.selected_task: - return curses.beep() - reply = self.app.control.revoke(self.selected_task, reply=True) - self.alert_remote_control_reply(reply) - - def selection_info(self): - if not self.selected_task: - return - - def alert_callback(mx, my, xs): - my, mx = self.win.getmaxyx() - y = count(xs) - task = self.state.tasks[self.selected_task] - info = task.info(extra=['state']) - infoitems = [ - ('args', info.pop('args', None)), - ('kwargs', info.pop('kwargs', None)) - ] + list(info.items()) - for key, value in infoitems: - if key is None: - continue - value = str(value) - curline = next(y) - keys = key + ': ' - self.win.addstr(curline, 3, keys, curses.A_BOLD) - wrapped = wrap(value, mx - 2) - if len(wrapped) == 1: - self.win.addstr( - curline, len(keys) + 3, - abbr(wrapped[0], - self.screen_width - (len(keys) + 3))) - else: - for subline in wrapped: - nexty = next(y) - if nexty >= my - 1: - subline = ' ' * 4 + '[...]' - elif nexty >= my: - break - self.win.addstr( - nexty, 3, - abbr(' ' * 4 + subline, self.screen_width - 4), - curses.A_NORMAL, - ) - - return self.alert( - alert_callback, 'Task details for {0.selected_task}'.format(self), - ) - - def selection_traceback(self): - if not self.selected_task: - return curses.beep() - task = self.state.tasks[self.selected_task] - if task.state not in states.EXCEPTION_STATES: - return curses.beep() - - def alert_callback(my, mx, xs): - y = count(xs) - for line in task.traceback.split('\n'): - self.win.addstr(next(y), 3, line) - - return self.alert( - alert_callback, - 'Task Exception Traceback for {0.selected_task}'.format(self), - ) - - def selection_result(self): - if not self.selected_task: - return - - def alert_callback(my, mx, xs): - y = count(xs) - task = self.state.tasks[self.selected_task] - result = (getattr(task, 'result', None) - or getattr(task, 'exception', None)) - for line in wrap(result, mx - 2): - self.win.addstr(next(y), 3, line) - - return self.alert( - alert_callback, - 'Task Result for {0.selected_task}'.format(self), - ) - - def display_task_row(self, lineno, task): - state_color = self.state_colors.get(task.state) - attr = curses.A_NORMAL - if task.uuid == self.selected_task: - attr = curses.A_STANDOUT - timestamp = datetime.utcfromtimestamp( - task.timestamp or time(), - ) - timef = timestamp.strftime('%H:%M:%S') - hostname = task.worker.hostname if task.worker else '*NONE*' - line = self.format_row(task.uuid, task.name, - hostname, - timef, task.state) - self.win.addstr(lineno, LEFT_BORDER_OFFSET, line, attr) - - if state_color: - self.win.addstr(lineno, - len(line) - STATE_WIDTH + BORDER_SPACING - 1, - task.state, state_color | attr) - - def draw(self): - with self.lock: - win = self.win - self.handle_keypress() - x = LEFT_BORDER_OFFSET - y = blank_line = count(2) - my, mx = win.getmaxyx() - win.erase() - win.bkgd(' ', curses.color_pair(1)) - win.border() - win.addstr(1, x, self.greet, curses.A_DIM | curses.color_pair(5)) - next(blank_line) - win.addstr(next(y), x, self.format_row('UUID', 'TASK', - 'WORKER', 'TIME', 'STATE'), - curses.A_BOLD | curses.A_UNDERLINE) - tasks = self.tasks - if tasks: - for row, (uuid, task) in enumerate(tasks): - if row > self.display_height: - break - - if task.uuid: - lineno = next(y) - self.display_task_row(lineno, task) - - # -- Footer - next(blank_line) - win.hline(my - 6, x, curses.ACS_HLINE, self.screen_width - 4) - - # Selected Task Info - if self.selected_task: - win.addstr(my - 5, x, self.selected_str, curses.A_BOLD) - info = 'Missing extended info' - detail = '' - try: - selection = self.state.tasks[self.selected_task] - except KeyError: - pass - else: - info = selection.info() - if 'runtime' in info: - info['runtime'] = '{0:.2f}'.format(info['runtime']) - if 'result' in info: - info['result'] = abbr(info['result'], 16) - info = ' '.join( - '{0}={1}'.format(key, value) - for key, value in items(info) - ) - detail = '... -> key i' - infowin = abbr(info, - self.screen_width - len(self.selected_str) - 2, - detail) - win.addstr(my - 5, x + len(self.selected_str), infowin) - # Make ellipsis bold - if detail in infowin: - detailpos = len(infowin) - len(detail) - win.addstr(my - 5, x + len(self.selected_str) + detailpos, - detail, curses.A_BOLD) - else: - win.addstr(my - 5, x, 'No task selected', curses.A_NORMAL) - - # Workers - if self.workers: - win.addstr(my - 4, x, self.online_str, curses.A_BOLD) - win.addstr(my - 4, x + len(self.online_str), - ', '.join(sorted(self.workers)), curses.A_NORMAL) - else: - win.addstr(my - 4, x, 'No workers discovered.') - - # Info - win.addstr(my - 3, x, self.info_str, curses.A_BOLD) - win.addstr( - my - 3, x + len(self.info_str), - STATUS_SCREEN.format( - s=self.state, - w_alive=len([w for w in values(self.state.workers) - if w.alive]), - w_all=len(self.state.workers), - ), - curses.A_DIM, - ) - - # Help - self.safe_add_str(my - 2, x, self.help_title, curses.A_BOLD) - self.safe_add_str(my - 2, x + len(self.help_title), self.help, - curses.A_DIM) - win.refresh() - - def safe_add_str(self, y, x, string, *args, **kwargs): - if x + len(string) > self.screen_width: - string = string[:self.screen_width - x] - self.win.addstr(y, x, string, *args, **kwargs) - - def init_screen(self): - with self.lock: - self.win = curses.initscr() - self.win.nodelay(True) - self.win.keypad(True) - curses.start_color() - curses.init_pair(1, self.foreground, self.background) - # exception states - curses.init_pair(2, curses.COLOR_RED, self.background) - # successful state - curses.init_pair(3, curses.COLOR_GREEN, self.background) - # revoked state - curses.init_pair(4, curses.COLOR_MAGENTA, self.background) - # greeting - curses.init_pair(5, curses.COLOR_BLUE, self.background) - # started state - curses.init_pair(6, curses.COLOR_YELLOW, self.foreground) - - self.state_colors = {states.SUCCESS: curses.color_pair(3), - states.REVOKED: curses.color_pair(4), - states.STARTED: curses.color_pair(6)} - for state in states.EXCEPTION_STATES: - self.state_colors[state] = curses.color_pair(2) - - curses.cbreak() - - def resetscreen(self): - with self.lock: - curses.nocbreak() - self.win.keypad(False) - curses.echo() - curses.endwin() - - def nap(self): - curses.napms(self.screen_delay) - - @property - def tasks(self): - return list(self.state.tasks_by_time(limit=self.limit)) - - @property - def workers(self): - return [hostname for hostname, w in items(self.state.workers) - if w.alive] - - -class DisplayThread(threading.Thread): # pragma: no cover - - def __init__(self, display): - self.display = display - self.shutdown = False - threading.Thread.__init__(self) - - def run(self): - while not self.shutdown: - self.display.draw() - self.display.nap() - - -def capture_events(app, state, display): # pragma: no cover - - def on_connection_error(exc, interval): - print('Connection Error: {0!r}. Retry in {1}s.'.format( - exc, interval), file=sys.stderr) - - while 1: - print('-> evtop: starting capture...', file=sys.stderr) - with app.connection() as conn: - try: - conn.ensure_connection(on_connection_error, - app.conf.BROKER_CONNECTION_MAX_RETRIES) - recv = app.events.Receiver(conn, handlers={'*': state.event}) - display.resetscreen() - display.init_screen() - recv.capture() - except conn.connection_errors + conn.channel_errors as exc: - print('Connection lost: {0!r}'.format(exc), file=sys.stderr) - - -def evtop(app=None): # pragma: no cover - app = app_or_default(app) - state = app.events.State() - display = CursesMonitor(state, app) - display.init_screen() - refresher = DisplayThread(display) - refresher.start() - try: - capture_events(app, state, display) - except Exception: - refresher.shutdown = True - refresher.join() - display.resetscreen() - raise - except (KeyboardInterrupt, SystemExit): - refresher.shutdown = True - refresher.join() - display.resetscreen() - - -if __name__ == '__main__': # pragma: no cover - evtop() diff --git a/awx/lib/site-packages/celery/events/dumper.py b/awx/lib/site-packages/celery/events/dumper.py deleted file mode 100644 index 323afc4e1a..0000000000 --- a/awx/lib/site-packages/celery/events/dumper.py +++ /dev/null @@ -1,109 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.events.dumper - ~~~~~~~~~~~~~~~~~~~~ - - This is a simple program that dumps events to the console - as they happen. Think of it like a `tcpdump` for Celery events. - -""" -from __future__ import absolute_import, print_function - -import sys - -from datetime import datetime - -from celery.app import app_or_default -from celery.utils.functional import LRUCache -from celery.utils.timeutils import humanize_seconds - -__all__ = ['Dumper', 'evdump'] - -TASK_NAMES = LRUCache(limit=0xFFF) - -HUMAN_TYPES = {'worker-offline': 'shutdown', - 'worker-online': 'started', - 'worker-heartbeat': 'heartbeat'} - -CONNECTION_ERROR = """\ --> Cannot connect to %s: %s. -Trying again %s -""" - - -def humanize_type(type): - try: - return HUMAN_TYPES[type.lower()] - except KeyError: - return type.lower().replace('-', ' ') - - -class Dumper(object): - - def __init__(self, out=sys.stdout): - self.out = out - - def say(self, msg): - print(msg, file=self.out) - # need to flush so that output can be piped. - try: - self.out.flush() - except AttributeError: - pass - - def on_event(self, ev): - timestamp = datetime.utcfromtimestamp(ev.pop('timestamp')) - type = ev.pop('type').lower() - hostname = ev.pop('hostname') - if type.startswith('task-'): - uuid = ev.pop('uuid') - if type in ('task-received', 'task-sent'): - task = TASK_NAMES[uuid] = '{0}({1}) args={2} kwargs={3}' \ - .format(ev.pop('name'), uuid, - ev.pop('args'), - ev.pop('kwargs')) - else: - task = TASK_NAMES.get(uuid, '') - return self.format_task_event(hostname, timestamp, - type, task, ev) - fields = ', '.join( - '{0}={1}'.format(key, ev[key]) for key in sorted(ev) - ) - sep = fields and ':' or '' - self.say('{0} [{1}] {2}{3} {4}'.format( - hostname, timestamp, humanize_type(type), sep, fields), - ) - - def format_task_event(self, hostname, timestamp, type, task, event): - fields = ', '.join( - '{0}={1}'.format(key, event[key]) for key in sorted(event) - ) - sep = fields and ':' or '' - self.say('{0} [{1}] {2}{3} {4} {5}'.format( - hostname, timestamp, humanize_type(type), sep, task, fields), - ) - - -def evdump(app=None, out=sys.stdout): - app = app_or_default(app) - dumper = Dumper(out=out) - dumper.say('-> evdump: starting capture...') - conn = app.connection().clone() - - def _error_handler(exc, interval): - dumper.say(CONNECTION_ERROR % ( - conn.as_uri(), exc, humanize_seconds(interval, 'in', ' ') - )) - - while 1: - try: - conn.ensure_connection(_error_handler) - recv = app.events.Receiver(conn, handlers={'*': dumper.on_event}) - recv.capture() - except (KeyboardInterrupt, SystemExit): - return conn and conn.close() - except conn.connection_errors + conn.channel_errors: - dumper.say('-> Connection lost, attempting reconnect') - -if __name__ == '__main__': # pragma: no cover - evdump() diff --git a/awx/lib/site-packages/celery/events/snapshot.py b/awx/lib/site-packages/celery/events/snapshot.py deleted file mode 100644 index 0dd41554c8..0000000000 --- a/awx/lib/site-packages/celery/events/snapshot.py +++ /dev/null @@ -1,114 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.events.snapshot - ~~~~~~~~~~~~~~~~~~~~~~ - - Consuming the events as a stream is not always suitable - so this module implements a system to take snapshots of the - state of a cluster at regular intervals. There is a full - implementation of this writing the snapshots to a database - in :mod:`djcelery.snapshots` in the `django-celery` distribution. - -""" -from __future__ import absolute_import - -from kombu.utils.limits import TokenBucket - -from celery import platforms -from celery.app import app_or_default -from celery.utils.timer2 import Timer -from celery.utils.dispatch import Signal -from celery.utils.imports import instantiate -from celery.utils.log import get_logger -from celery.utils.timeutils import rate - -__all__ = ['Polaroid', 'evcam'] - -logger = get_logger('celery.evcam') - - -class Polaroid(object): - timer = None - shutter_signal = Signal(providing_args=('state', )) - cleanup_signal = Signal() - clear_after = False - - _tref = None - _ctref = None - - def __init__(self, state, freq=1.0, maxrate=None, - cleanup_freq=3600.0, timer=None, app=None): - self.app = app_or_default(app) - self.state = state - self.freq = freq - self.cleanup_freq = cleanup_freq - self.timer = timer or self.timer or Timer() - self.logger = logger - self.maxrate = maxrate and TokenBucket(rate(maxrate)) - - def install(self): - self._tref = self.timer.call_repeatedly(self.freq, self.capture) - self._ctref = self.timer.call_repeatedly( - self.cleanup_freq, self.cleanup, - ) - - def on_shutter(self, state): - pass - - def on_cleanup(self): - pass - - def cleanup(self): - logger.debug('Cleanup: Running...') - self.cleanup_signal.send(None) - self.on_cleanup() - - def shutter(self): - if self.maxrate is None or self.maxrate.can_consume(): - logger.debug('Shutter: %s', self.state) - self.shutter_signal.send(self.state) - self.on_shutter(self.state) - - def capture(self): - self.state.freeze_while(self.shutter, clear_after=self.clear_after) - - def cancel(self): - if self._tref: - self._tref() # flush all received events. - self._tref.cancel() - if self._ctref: - self._ctref.cancel() - - def __enter__(self): - self.install() - return self - - def __exit__(self, *exc_info): - self.cancel() - - -def evcam(camera, freq=1.0, maxrate=None, loglevel=0, - logfile=None, pidfile=None, timer=None, app=None): - app = app_or_default(app) - - if pidfile: - platforms.create_pidlock(pidfile) - - app.log.setup_logging_subsystem(loglevel, logfile) - - print('-> evcam: Taking snapshots with {0} (every {1} secs.)'.format( - camera, freq)) - state = app.events.State() - cam = instantiate(camera, state, app=app, freq=freq, - maxrate=maxrate, timer=timer) - cam.install() - conn = app.connection() - recv = app.events.Receiver(conn, handlers={'*': state.event}) - try: - try: - recv.capture(limit=None) - except KeyboardInterrupt: - raise SystemExit - finally: - cam.cancel() - conn.close() diff --git a/awx/lib/site-packages/celery/events/state.py b/awx/lib/site-packages/celery/events/state.py deleted file mode 100644 index c78f2d08a1..0000000000 --- a/awx/lib/site-packages/celery/events/state.py +++ /dev/null @@ -1,656 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.events.state - ~~~~~~~~~~~~~~~~~~~ - - This module implements a datastructure used to keep - track of the state of a cluster of workers and the tasks - it is working on (by consuming events). - - For every event consumed the state is updated, - so the state represents the state of the cluster - at the time of the last event. - - Snapshots (:mod:`celery.events.snapshot`) can be used to - take "pictures" of this state at regular intervals - to e.g. store that in a database. - -""" -from __future__ import absolute_import - -import bisect -import sys -import threading - -from datetime import datetime -from decimal import Decimal -from itertools import islice -from operator import itemgetter -from time import time -from weakref import ref - -from kombu.clocks import timetuple -from kombu.utils import cached_property, kwdict - -from celery import states -from celery.five import class_property, items, values -from celery.utils import deprecated -from celery.utils.functional import LRUCache, memoize -from celery.utils.log import get_logger - -PYPY = hasattr(sys, 'pypy_version_info') - -# The window (in percentage) is added to the workers heartbeat -# frequency. If the time between updates exceeds this window, -# then the worker is considered to be offline. -HEARTBEAT_EXPIRE_WINDOW = 200 - -# Max drift between event timestamp and time of event received -# before we alert that clocks may be unsynchronized. -HEARTBEAT_DRIFT_MAX = 16 - -DRIFT_WARNING = """\ -Substantial drift from %s may mean clocks are out of sync. Current drift is -%s seconds. [orig: %s recv: %s] -""" - -CAN_KWDICT = sys.version_info >= (2, 6, 5) - -logger = get_logger(__name__) -warn = logger.warning - -R_STATE = '<State: events={0.event_count} tasks={0.task_count}>' -R_WORKER = '<Worker: {0.hostname} ({0.status_string} clock:{0.clock})' -R_TASK = '<Task: {0.name}({0.uuid}) {0.state} clock:{0.clock}>' - -__all__ = ['Worker', 'Task', 'State', 'heartbeat_expires'] - - -@memoize(maxsize=1000, keyfun=lambda a, _: a[0]) -def _warn_drift(hostname, drift, local_received, timestamp): - # we use memoize here so the warning is only logged once per hostname - warn(DRIFT_WARNING, hostname, drift, - datetime.fromtimestamp(local_received), - datetime.fromtimestamp(timestamp)) - - -def heartbeat_expires(timestamp, freq=60, - expire_window=HEARTBEAT_EXPIRE_WINDOW, - Decimal=Decimal, float=float, isinstance=isinstance): - # some json implementations returns decimal.Decimal objects, - # which are not compatible with float. - freq = float(freq) if isinstance(freq, Decimal) else freq - if isinstance(timestamp, Decimal): - timestamp = float(timestamp) - return timestamp + (freq * (expire_window / 1e2)) - - -def _depickle_task(cls, fields): - return cls(**(fields if CAN_KWDICT else kwdict(fields))) - - -def with_unique_field(attr): - - def _decorate_cls(cls): - - def __eq__(this, other): - if isinstance(other, this.__class__): - return getattr(this, attr) == getattr(other, attr) - return NotImplemented - cls.__eq__ = __eq__ - - def __ne__(this, other): - return not this.__eq__(other) - cls.__ne__ = __ne__ - - def __hash__(this): - return hash(getattr(this, attr)) - cls.__hash__ = __hash__ - - return cls - return _decorate_cls - - -@with_unique_field('hostname') -class Worker(object): - """Worker State.""" - heartbeat_max = 4 - expire_window = HEARTBEAT_EXPIRE_WINDOW - - _fields = ('hostname', 'pid', 'freq', 'heartbeats', 'clock', - 'active', 'processed', 'loadavg', 'sw_ident', - 'sw_ver', 'sw_sys') - if not PYPY: - __slots__ = _fields + ('event', '__dict__', '__weakref__') - - def __init__(self, hostname=None, pid=None, freq=60, - heartbeats=None, clock=0, active=None, processed=None, - loadavg=None, sw_ident=None, sw_ver=None, sw_sys=None): - self.hostname = hostname - self.pid = pid - self.freq = freq - self.heartbeats = [] if heartbeats is None else heartbeats - self.clock = clock or 0 - self.active = active - self.processed = processed - self.loadavg = loadavg - self.sw_ident = sw_ident - self.sw_ver = sw_ver - self.sw_sys = sw_sys - self.event = self._create_event_handler() - - def __reduce__(self): - return self.__class__, (self.hostname, self.pid, self.freq, - self.heartbeats, self.clock, self.active, - self.processed, self.loadavg, self.sw_ident, - self.sw_ver, self.sw_sys) - - def _create_event_handler(self): - _set = object.__setattr__ - hbmax = self.heartbeat_max - heartbeats = self.heartbeats - hb_pop = self.heartbeats.pop - hb_append = self.heartbeats.append - - def event(type_, timestamp=None, - local_received=None, fields=None, - max_drift=HEARTBEAT_DRIFT_MAX, items=items, abs=abs, int=int, - insort=bisect.insort, len=len): - fields = fields or {} - for k, v in items(fields): - _set(self, k, v) - if type_ == 'offline': - heartbeats[:] = [] - else: - if not local_received or not timestamp: - return - drift = abs(int(local_received) - int(timestamp)) - if drift > HEARTBEAT_DRIFT_MAX: - _warn_drift(self.hostname, drift, - local_received, timestamp) - if local_received: - hearts = len(heartbeats) - if hearts > hbmax - 1: - hb_pop(0) - if hearts and local_received > heartbeats[-1]: - hb_append(local_received) - else: - insort(heartbeats, local_received) - return event - - def update(self, f, **kw): - for k, v in items(dict(f, **kw) if kw else f): - setattr(self, k, v) - - def __repr__(self): - return R_WORKER.format(self) - - @property - def status_string(self): - return 'ONLINE' if self.alive else 'OFFLINE' - - @property - def heartbeat_expires(self): - return heartbeat_expires(self.heartbeats[-1], - self.freq, self.expire_window) - - @property - def alive(self, nowfun=time): - return bool(self.heartbeats and nowfun() < self.heartbeat_expires) - - @property - def id(self): - return '{0.hostname}.{0.pid}'.format(self) - - @deprecated(3.2, 3.3) - def update_heartbeat(self, received, timestamp): - self.event(None, timestamp, received) - - @deprecated(3.2, 3.3) - def on_online(self, timestamp=None, local_received=None, **fields): - self.event('online', timestamp, local_received, fields) - - @deprecated(3.2, 3.3) - def on_offline(self, timestamp=None, local_received=None, **fields): - self.event('offline', timestamp, local_received, fields) - - @deprecated(3.2, 3.3) - def on_heartbeat(self, timestamp=None, local_received=None, **fields): - self.event('heartbeat', timestamp, local_received, fields) - - @class_property - def _defaults(cls): - """Deprecated, to be removed in 3.3""" - source = cls() - return dict((k, getattr(source, k)) for k in cls._fields) - - -@with_unique_field('uuid') -class Task(object): - """Task State.""" - name = received = sent = started = succeeded = failed = retried = \ - revoked = args = kwargs = eta = expires = retries = worker = result = \ - exception = timestamp = runtime = traceback = exchange = \ - routing_key = client = None - state = states.PENDING - clock = 0 - - _fields = ('uuid', 'name', 'state', 'received', 'sent', 'started', - 'succeeded', 'failed', 'retried', 'revoked', 'args', 'kwargs', - 'eta', 'expires', 'retries', 'worker', 'result', 'exception', - 'timestamp', 'runtime', 'traceback', 'exchange', 'routing_key', - 'clock', 'client') - if not PYPY: - __slots__ = ('__dict__', '__weakref__') - - #: How to merge out of order events. - #: Disorder is detected by logical ordering (e.g. :event:`task-received` - #: must have happened before a :event:`task-failed` event). - #: - #: A merge rule consists of a state and a list of fields to keep from - #: that state. ``(RECEIVED, ('name', 'args')``, means the name and args - #: fields are always taken from the RECEIVED state, and any values for - #: these fields received before or after is simply ignored. - merge_rules = {states.RECEIVED: ('name', 'args', 'kwargs', - 'retries', 'eta', 'expires')} - - #: meth:`info` displays these fields by default. - _info_fields = ('args', 'kwargs', 'retries', 'result', 'eta', 'runtime', - 'expires', 'exception', 'exchange', 'routing_key') - - def __init__(self, uuid=None, **kwargs): - self.uuid = uuid - if kwargs: - for k, v in items(kwargs): - setattr(self, k, v) - - def event(self, type_, timestamp=None, local_received=None, fields=None, - precedence=states.precedence, items=items, dict=dict, - PENDING=states.PENDING, RECEIVED=states.RECEIVED, - STARTED=states.STARTED, FAILURE=states.FAILURE, - RETRY=states.RETRY, SUCCESS=states.SUCCESS, - REVOKED=states.REVOKED): - fields = fields or {} - if type_ == 'sent': - state, self.sent = PENDING, timestamp - elif type_ == 'received': - state, self.received = RECEIVED, timestamp - elif type_ == 'started': - state, self.started = STARTED, timestamp - elif type_ == 'failed': - state, self.failed = FAILURE, timestamp - elif type_ == 'retried': - state, self.retried = RETRY, timestamp - elif type_ == 'succeeded': - state, self.succeeded = SUCCESS, timestamp - elif type_ == 'revoked': - state, self.revoked = REVOKED, timestamp - else: - state = type_.upper() - - # note that precedence here is reversed - # see implementation in celery.states.state.__lt__ - if state != RETRY and self.state != RETRY and \ - precedence(state) > precedence(self.state): - # this state logically happens-before the current state, so merge. - keep = self.merge_rules.get(state) - if keep is not None: - fields = dict( - (k, v) for k, v in items(fields) if k in keep - ) - for key, value in items(fields): - setattr(self, key, value) - else: - self.state = state - self.timestamp = timestamp - for key, value in items(fields): - setattr(self, key, value) - - def info(self, fields=None, extra=[]): - """Information about this task suitable for on-screen display.""" - fields = self._info_fields if fields is None else fields - - def _keys(): - for key in list(fields) + list(extra): - value = getattr(self, key, None) - if value is not None: - yield key, value - - return dict(_keys()) - - def __repr__(self): - return R_TASK.format(self) - - def as_dict(self): - get = object.__getattribute__ - return dict( - (k, get(self, k)) for k in self._fields - ) - - def __reduce__(self): - return _depickle_task, (self.__class__, self.as_dict()) - - @property - def origin(self): - return self.client if self.worker is None else self.worker.id - - @property - def ready(self): - return self.state in states.READY_STATES - - @deprecated(3.2, 3.3) - def on_sent(self, timestamp=None, **fields): - self.event('sent', timestamp, fields) - - @deprecated(3.2, 3.3) - def on_received(self, timestamp=None, **fields): - self.event('received', timestamp, fields) - - @deprecated(3.2, 3.3) - def on_started(self, timestamp=None, **fields): - self.event('started', timestamp, fields) - - @deprecated(3.2, 3.3) - def on_failed(self, timestamp=None, **fields): - self.event('failed', timestamp, fields) - - @deprecated(3.2, 3.3) - def on_retried(self, timestamp=None, **fields): - self.event('retried', timestamp, fields) - - @deprecated(3.2, 3.3) - def on_succeeded(self, timestamp=None, **fields): - self.event('succeeded', timestamp, fields) - - @deprecated(3.2, 3.3) - def on_revoked(self, timestamp=None, **fields): - self.event('revoked', timestamp, fields) - - @deprecated(3.2, 3.3) - def on_unknown_event(self, shortype, timestamp=None, **fields): - self.event(shortype, timestamp, fields) - - @deprecated(3.2, 3.3) - def update(self, state, timestamp, fields, - _state=states.state, RETRY=states.RETRY): - return self.event(state, timestamp, None, fields) - - @deprecated(3.2, 3.3) - def merge(self, state, timestamp, fields): - keep = self.merge_rules.get(state) - if keep is not None: - fields = dict((k, v) for k, v in items(fields) if k in keep) - for key, value in items(fields): - setattr(self, key, value) - - @class_property - def _defaults(cls): - """Deprecated, to be removed in 3.3.""" - source = cls() - return dict((k, getattr(source, k)) for k in source._fields) - - -class State(object): - """Records clusters state.""" - Worker = Worker - Task = Task - event_count = 0 - task_count = 0 - heap_multiplier = 4 - - def __init__(self, callback=None, - workers=None, tasks=None, taskheap=None, - max_workers_in_memory=5000, max_tasks_in_memory=10000, - on_node_join=None, on_node_leave=None): - self.event_callback = callback - self.workers = (LRUCache(max_workers_in_memory) - if workers is None else workers) - self.tasks = (LRUCache(max_tasks_in_memory) - if tasks is None else tasks) - self._taskheap = [] if taskheap is None else taskheap - self.max_workers_in_memory = max_workers_in_memory - self.max_tasks_in_memory = max_tasks_in_memory - self.on_node_join = on_node_join - self.on_node_leave = on_node_leave - self._mutex = threading.Lock() - self.handlers = {} - self._seen_types = set() - self.rebuild_taskheap() - - @cached_property - def _event(self): - return self._create_dispatcher() - - def freeze_while(self, fun, *args, **kwargs): - clear_after = kwargs.pop('clear_after', False) - with self._mutex: - try: - return fun(*args, **kwargs) - finally: - if clear_after: - self._clear() - - def clear_tasks(self, ready=True): - with self._mutex: - return self._clear_tasks(ready) - - def _clear_tasks(self, ready=True): - if ready: - in_progress = dict( - (uuid, task) for uuid, task in self.itertasks() - if task.state not in states.READY_STATES) - self.tasks.clear() - self.tasks.update(in_progress) - else: - self.tasks.clear() - self._taskheap[:] = [] - - def _clear(self, ready=True): - self.workers.clear() - self._clear_tasks(ready) - self.event_count = 0 - self.task_count = 0 - - def clear(self, ready=True): - with self._mutex: - return self._clear(ready) - - def get_or_create_worker(self, hostname, **kwargs): - """Get or create worker by hostname. - - Return tuple of ``(worker, was_created)``. - """ - try: - worker = self.workers[hostname] - if kwargs: - worker.update(kwargs) - return worker, False - except KeyError: - worker = self.workers[hostname] = self.Worker( - hostname, **kwargs) - return worker, True - - def get_or_create_task(self, uuid): - """Get or create task by uuid.""" - try: - return self.tasks[uuid], False - except KeyError: - task = self.tasks[uuid] = self.Task(uuid) - return task, True - - def event(self, event): - with self._mutex: - return self._event(event) - - def task_event(self, type_, fields): - """Deprecated, use :meth:`event`.""" - return self._event(dict(fields, type='-'.join(['task', type_])))[0] - - def worker_event(self, type_, fields): - """Deprecated, use :meth:`event`.""" - return self._event(dict(fields, type='-'.join(['worker', type_])))[0] - - def _create_dispatcher(self): - get_handler = self.handlers.__getitem__ - event_callback = self.event_callback - wfields = itemgetter('hostname', 'timestamp', 'local_received') - tfields = itemgetter('uuid', 'hostname', 'timestamp', - 'local_received', 'clock') - taskheap = self._taskheap - th_append = taskheap.append - th_pop = taskheap.pop - # Removing events from task heap is an O(n) operation, - # so easier to just account for the common number of events - # for each task (PENDING->RECEIVED->STARTED->final) - #: an O(n) operation - max_events_in_heap = self.max_tasks_in_memory * self.heap_multiplier - add_type = self._seen_types.add - on_node_join, on_node_leave = self.on_node_join, self.on_node_leave - tasks, Task = self.tasks, self.Task - workers, Worker = self.workers, self.Worker - # avoid updating LRU entry at getitem - get_worker, get_task = workers.data.__getitem__, tasks.data.__getitem__ - - def _event(event, - timetuple=timetuple, KeyError=KeyError, - insort=bisect.insort, created=True): - self.event_count += 1 - if event_callback: - event_callback(self, event) - group, _, subject = event['type'].partition('-') - try: - handler = get_handler(group) - except KeyError: - pass - else: - return handler(subject, event), subject - - if group == 'worker': - try: - hostname, timestamp, local_received = wfields(event) - except KeyError: - pass - else: - is_offline = subject == 'offline' - try: - worker, created = get_worker(hostname), False - except KeyError: - if is_offline: - worker, created = Worker(hostname), False - else: - worker = workers[hostname] = Worker(hostname) - worker.event(subject, timestamp, local_received, event) - if on_node_join and (created or subject == 'online'): - on_node_join(worker) - if on_node_leave and is_offline: - on_node_leave(worker) - workers.pop(hostname, None) - return (worker, created), subject - elif group == 'task': - (uuid, hostname, timestamp, - local_received, clock) = tfields(event) - # task-sent event is sent by client, not worker - is_client_event = subject == 'sent' - try: - task, created = get_task(uuid), False - except KeyError: - task = tasks[uuid] = Task(uuid) - if is_client_event: - task.client = hostname - else: - try: - worker, created = get_worker(hostname), False - except KeyError: - worker = workers[hostname] = Worker(hostname) - task.worker = worker - if worker is not None and local_received: - worker.event(None, local_received, timestamp) - - origin = hostname if is_client_event else worker.id - - # remove oldest event if exceeding the limit. - heaps = len(taskheap) - if heaps + 1 > max_events_in_heap: - th_pop(0) - - # most events will be dated later than the previous. - timetup = timetuple(clock, timestamp, origin, ref(task)) - if heaps and timetup > taskheap[-1]: - th_append(timetup) - else: - insort(taskheap, timetup) - - if subject == 'received': - self.task_count += 1 - task.event(subject, timestamp, local_received, event) - task_name = task.name - if task_name is not None: - add_type(task_name) - return (task, created), subject - return _event - - def rebuild_taskheap(self, timetuple=timetuple): - heap = self._taskheap[:] = [ - timetuple(t.clock, t.timestamp, t.origin, ref(t)) - for t in values(self.tasks) - ] - heap.sort() - - def itertasks(self, limit=None): - for index, row in enumerate(items(self.tasks)): - yield row - if limit and index + 1 >= limit: - break - - def tasks_by_time(self, limit=None): - """Generator giving tasks ordered by time, - in ``(uuid, Task)`` tuples.""" - seen = set() - for evtup in islice(reversed(self._taskheap), 0, limit): - task = evtup[3]() - if task is not None: - uuid = task.uuid - if uuid not in seen: - yield uuid, task - seen.add(uuid) - tasks_by_timestamp = tasks_by_time - - def tasks_by_type(self, name, limit=None): - """Get all tasks by type. - - Return a list of ``(uuid, Task)`` tuples. - - """ - return islice( - ((uuid, task) for uuid, task in self.tasks_by_time() - if task.name == name), - 0, limit, - ) - - def tasks_by_worker(self, hostname, limit=None): - """Get all tasks by worker. - - """ - return islice( - ((uuid, task) for uuid, task in self.tasks_by_time() - if task.worker.hostname == hostname), - 0, limit, - ) - - def task_types(self): - """Return a list of all seen task types.""" - return sorted(self._seen_types) - - def alive_workers(self): - """Return a list of (seemingly) alive workers.""" - return [w for w in values(self.workers) if w.alive] - - def __repr__(self): - return R_STATE.format(self) - - def __reduce__(self): - return self.__class__, ( - self.event_callback, self.workers, self.tasks, None, - self.max_workers_in_memory, self.max_tasks_in_memory, - self.on_node_join, self.on_node_leave, - ) diff --git a/awx/lib/site-packages/celery/exceptions.py b/awx/lib/site-packages/celery/exceptions.py deleted file mode 100644 index ab65019416..0000000000 --- a/awx/lib/site-packages/celery/exceptions.py +++ /dev/null @@ -1,171 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.exceptions - ~~~~~~~~~~~~~~~~~ - - This module contains all exceptions used by the Celery API. - -""" -from __future__ import absolute_import - -import numbers - -from .five import string_t - -from billiard.exceptions import ( # noqa - SoftTimeLimitExceeded, TimeLimitExceeded, WorkerLostError, Terminated, -) - -__all__ = ['SecurityError', 'Ignore', 'QueueNotFound', - 'WorkerShutdown', 'WorkerTerminate', - 'ImproperlyConfigured', 'NotRegistered', 'AlreadyRegistered', - 'TimeoutError', 'MaxRetriesExceededError', 'Retry', - 'TaskRevokedError', 'NotConfigured', 'AlwaysEagerIgnored', - 'InvalidTaskError', 'ChordError', 'CPendingDeprecationWarning', - 'CDeprecationWarning', 'FixupWarning', 'DuplicateNodenameWarning', - 'SoftTimeLimitExceeded', 'TimeLimitExceeded', 'WorkerLostError', - 'Terminated'] - -UNREGISTERED_FMT = """\ -Task of kind {0} is not registered, please make sure it's imported.\ -""" - - -class SecurityError(Exception): - """Security related exceptions. - - Handle with care. - - """ - - -class Ignore(Exception): - """A task can raise this to ignore doing state updates.""" - - -class Reject(Exception): - """A task can raise this if it wants to reject/requeue the message.""" - - def __init__(self, reason=None, requeue=False): - self.reason = reason - self.requeue = requeue - super(Reject, self).__init__(reason, requeue) - - def __repr__(self): - return 'reject requeue=%s: %s' % (self.requeue, self.reason) - - -class WorkerTerminate(SystemExit): - """Signals that the worker should terminate immediately.""" -SystemTerminate = WorkerTerminate # XXX compat - - -class WorkerShutdown(SystemExit): - """Signals that the worker should perform a warm shutdown.""" - - -class QueueNotFound(KeyError): - """Task routed to a queue not in CELERY_QUEUES.""" - - -class ImproperlyConfigured(ImportError): - """Celery is somehow improperly configured.""" - - -class NotRegistered(KeyError): - """The task is not registered.""" - - def __repr__(self): - return UNREGISTERED_FMT.format(self) - - -class AlreadyRegistered(Exception): - """The task is already registered.""" - - -class TimeoutError(Exception): - """The operation timed out.""" - - -class MaxRetriesExceededError(Exception): - """The tasks max restart limit has been exceeded.""" - - -class Retry(Exception): - """The task is to be retried later.""" - - #: Optional message describing context of retry. - message = None - - #: Exception (if any) that caused the retry to happen. - exc = None - - #: Time of retry (ETA), either :class:`numbers.Real` or - #: :class:`~datetime.datetime`. - when = None - - def __init__(self, message=None, exc=None, when=None, **kwargs): - from kombu.utils.encoding import safe_repr - self.message = message - if isinstance(exc, string_t): - self.exc, self.excs = None, exc - else: - self.exc, self.excs = exc, safe_repr(exc) if exc else None - self.when = when - Exception.__init__(self, exc, when, **kwargs) - - def humanize(self): - if isinstance(self.when, numbers.Real): - return 'in {0.when}s'.format(self) - return 'at {0.when}'.format(self) - - def __str__(self): - if self.message: - return self.message - if self.excs: - return 'Retry {0}: {1}'.format(self.humanize(), self.excs) - return 'Retry {0}'.format(self.humanize()) - - def __reduce__(self): - return self.__class__, (self.message, self.excs, self.when) -RetryTaskError = Retry # XXX compat - - -class TaskRevokedError(Exception): - """The task has been revoked, so no result available.""" - - -class NotConfigured(UserWarning): - """Celery has not been configured, as no config module has been found.""" - - -class AlwaysEagerIgnored(UserWarning): - """send_task ignores CELERY_ALWAYS_EAGER option""" - - -class InvalidTaskError(Exception): - """The task has invalid data or is not properly constructed.""" - - -class IncompleteStream(Exception): - """Found the end of a stream of data, but the data is not yet complete.""" - - -class ChordError(Exception): - """A task part of the chord raised an exception.""" - - -class CPendingDeprecationWarning(PendingDeprecationWarning): - pass - - -class CDeprecationWarning(DeprecationWarning): - pass - - -class FixupWarning(UserWarning): - pass - - -class DuplicateNodenameWarning(UserWarning): - """Multiple workers are using the same nodename.""" diff --git a/awx/lib/site-packages/celery/five.py b/awx/lib/site-packages/celery/five.py deleted file mode 100644 index dfee614e4b..0000000000 --- a/awx/lib/site-packages/celery/five.py +++ /dev/null @@ -1,393 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.five - ~~~~~~~~~~~ - - Compatibility implementations of features - only available in newer Python versions. - - -""" -from __future__ import absolute_import - -__all__ = ['Counter', 'reload', 'UserList', 'UserDict', 'Queue', 'Empty', - 'zip_longest', 'map', 'string', 'string_t', - 'long_t', 'text_t', 'range', 'int_types', 'items', 'keys', 'values', - 'nextfun', 'reraise', 'WhateverIO', 'with_metaclass', - 'OrderedDict', 'THREAD_TIMEOUT_MAX', 'format_d', - 'class_property', 'reclassmethod', 'create_module', - 'recreate_module', 'monotonic'] - -import io - -try: - from collections import Counter -except ImportError: # pragma: no cover - from collections import defaultdict - - def Counter(): # noqa - return defaultdict(int) - -############## py3k ######################################################### -import sys -PY3 = sys.version_info[0] == 3 - -try: - reload = reload # noqa -except NameError: # pragma: no cover - from imp import reload # noqa - -try: - from UserList import UserList # noqa -except ImportError: # pragma: no cover - from collections import UserList # noqa - -try: - from UserDict import UserDict # noqa -except ImportError: # pragma: no cover - from collections import UserDict # noqa - - -from kombu.five import monotonic - -if PY3: # pragma: no cover - import builtins - - from queue import Queue, Empty - from itertools import zip_longest - - map = map - string = str - string_t = str - long_t = int - text_t = str - range = range - int_types = (int, ) - _byte_t = bytes - - open_fqdn = 'builtins.open' - - def items(d): - return d.items() - - def keys(d): - return d.keys() - - def values(d): - return d.values() - - def nextfun(it): - return it.__next__ - - exec_ = getattr(builtins, 'exec') - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -else: - import __builtin__ as builtins # noqa - from Queue import Queue, Empty # noqa - from itertools import imap as map, izip_longest as zip_longest # noqa - string = unicode # noqa - string_t = basestring # noqa - text_t = unicode # noqa - long_t = long # noqa - range = xrange # noqa - int_types = (int, long) # noqa - _byte_t = (str, bytes) # noqa - - open_fqdn = '__builtin__.open' - - def items(d): # noqa - return d.iteritems() - - def keys(d): # noqa - return d.iterkeys() - - def values(d): # noqa - return d.itervalues() - - def nextfun(it): # noqa - return it.next - - def exec_(code, globs=None, locs=None): # pragma: no cover - """Execute code in a namespace.""" - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - - exec_("""def reraise(tp, value, tb=None): raise tp, value, tb""") - - -def with_metaclass(Type, skip_attrs=set(['__dict__', '__weakref__'])): - """Class decorator to set metaclass. - - Works with both Python 2 and Python 3 and it does not add - an extra class in the lookup order like ``six.with_metaclass`` does - (that is -- it copies the original class instead of using inheritance). - - """ - - def _clone_with_metaclass(Class): - attrs = dict((key, value) for key, value in items(vars(Class)) - if key not in skip_attrs) - return Type(Class.__name__, Class.__bases__, attrs) - - return _clone_with_metaclass - - -############## collections.OrderedDict ###################################### -# was moved to kombu -from kombu.utils.compat import OrderedDict # noqa - -############## threading.TIMEOUT_MAX ####################################### -try: - from threading import TIMEOUT_MAX as THREAD_TIMEOUT_MAX -except ImportError: - THREAD_TIMEOUT_MAX = 1e10 # noqa - -############## format(int, ',d') ########################## - -if sys.version_info >= (2, 7): # pragma: no cover - def format_d(i): - return format(i, ',d') -else: # pragma: no cover - def format_d(i): # noqa - s = '%d' % i - groups = [] - while s and s[-1].isdigit(): - groups.append(s[-3:]) - s = s[:-3] - return s + ','.join(reversed(groups)) - - -############## Module Generation ########################## - -# Utilities to dynamically -# recreate modules, either for lazy loading or -# to create old modules at runtime instead of -# having them litter the source tree. -import operator -import sys - -# import fails in python 2.5. fallback to reduce in stdlib -try: - from functools import reduce -except ImportError: - pass - -from importlib import import_module -from types import ModuleType - -MODULE_DEPRECATED = """ -The module %s is deprecated and will be removed in a future version. -""" - -DEFAULT_ATTRS = set(['__file__', '__path__', '__doc__', '__all__']) - -# im_func is no longer available in Py3. -# instead the unbound method itself can be used. -if sys.version_info[0] == 3: # pragma: no cover - def fun_of_method(method): - return method -else: - def fun_of_method(method): # noqa - return method.im_func - - -def getappattr(path): - """Gets attribute from the current_app recursively, - e.g. getappattr('amqp.get_task_consumer')``.""" - from celery import current_app - return current_app._rgetattr(path) - - -def _compat_task_decorator(*args, **kwargs): - from celery import current_app - kwargs.setdefault('accept_magic_kwargs', True) - return current_app.task(*args, **kwargs) - - -def _compat_periodic_task_decorator(*args, **kwargs): - from celery.task import periodic_task - kwargs.setdefault('accept_magic_kwargs', True) - return periodic_task(*args, **kwargs) - - -COMPAT_MODULES = { - 'celery': { - 'execute': { - 'send_task': 'send_task', - }, - 'decorators': { - 'task': _compat_task_decorator, - 'periodic_task': _compat_periodic_task_decorator, - }, - 'log': { - 'get_default_logger': 'log.get_default_logger', - 'setup_logger': 'log.setup_logger', - 'setup_loggig_subsystem': 'log.setup_logging_subsystem', - 'redirect_stdouts_to_logger': 'log.redirect_stdouts_to_logger', - }, - 'messaging': { - 'TaskPublisher': 'amqp.TaskPublisher', - 'TaskConsumer': 'amqp.TaskConsumer', - 'establish_connection': 'connection', - 'get_consumer_set': 'amqp.TaskConsumer', - }, - 'registry': { - 'tasks': 'tasks', - }, - }, - 'celery.task': { - 'control': { - 'broadcast': 'control.broadcast', - 'rate_limit': 'control.rate_limit', - 'time_limit': 'control.time_limit', - 'ping': 'control.ping', - 'revoke': 'control.revoke', - 'discard_all': 'control.purge', - 'inspect': 'control.inspect', - }, - 'schedules': 'celery.schedules', - 'chords': 'celery.canvas', - } -} - - -class class_property(object): - - def __init__(self, getter=None, setter=None): - if getter is not None and not isinstance(getter, classmethod): - getter = classmethod(getter) - if setter is not None and not isinstance(setter, classmethod): - setter = classmethod(setter) - self.__get = getter - self.__set = setter - - info = getter.__get__(object) # just need the info attrs. - self.__doc__ = info.__doc__ - self.__name__ = info.__name__ - self.__module__ = info.__module__ - - def __get__(self, obj, type=None): - if obj and type is None: - type = obj.__class__ - return self.__get.__get__(obj, type)() - - def __set__(self, obj, value): - if obj is None: - return self - return self.__set.__get__(obj)(value) - - def setter(self, setter): - return self.__class__(self.__get, setter) - - -def reclassmethod(method): - return classmethod(fun_of_method(method)) - - -class MagicModule(ModuleType): - _compat_modules = () - _all_by_module = {} - _direct = {} - _object_origins = {} - - def __getattr__(self, name): - if name in self._object_origins: - module = __import__(self._object_origins[name], None, None, [name]) - for item in self._all_by_module[module.__name__]: - setattr(self, item, getattr(module, item)) - return getattr(module, name) - elif name in self._direct: # pragma: no cover - module = __import__(self._direct[name], None, None, [name]) - setattr(self, name, module) - return module - return ModuleType.__getattribute__(self, name) - - def __dir__(self): - return list(set(self.__all__) | DEFAULT_ATTRS) - - def __reduce__(self): - return import_module, (self.__name__, ) - - -def create_module(name, attrs, cls_attrs=None, pkg=None, - base=MagicModule, prepare_attr=None): - fqdn = '.'.join([pkg.__name__, name]) if pkg else name - cls_attrs = {} if cls_attrs is None else cls_attrs - pkg, _, modname = name.rpartition('.') - cls_attrs['__module__'] = pkg - - attrs = dict((attr_name, prepare_attr(attr) if prepare_attr else attr) - for attr_name, attr in items(attrs)) - module = sys.modules[fqdn] = type(modname, (base, ), cls_attrs)(fqdn) - module.__dict__.update(attrs) - return module - - -def recreate_module(name, compat_modules=(), by_module={}, direct={}, - base=MagicModule, **attrs): - old_module = sys.modules[name] - origins = get_origins(by_module) - compat_modules = COMPAT_MODULES.get(name, ()) - - cattrs = dict( - _compat_modules=compat_modules, - _all_by_module=by_module, _direct=direct, - _object_origins=origins, - __all__=tuple(set(reduce( - operator.add, - [tuple(v) for v in [compat_modules, origins, direct, attrs]], - ))), - ) - new_module = create_module(name, attrs, cls_attrs=cattrs, base=base) - new_module.__dict__.update(dict((mod, get_compat_module(new_module, mod)) - for mod in compat_modules)) - return old_module, new_module - - -def get_compat_module(pkg, name): - from .local import Proxy - - def prepare(attr): - if isinstance(attr, string_t): - return Proxy(getappattr, (attr, )) - return attr - - attrs = COMPAT_MODULES[pkg.__name__][name] - if isinstance(attrs, string_t): - fqdn = '.'.join([pkg.__name__, name]) - module = sys.modules[fqdn] = import_module(attrs) - return module - attrs['__all__'] = list(attrs) - return create_module(name, dict(attrs), pkg=pkg, prepare_attr=prepare) - - -def get_origins(defs): - origins = {} - for module, attrs in items(defs): - origins.update(dict((attr, module) for attr in attrs)) - return origins - - -_SIO_write = io.StringIO.write -_SIO_init = io.StringIO.__init__ - - -class WhateverIO(io.StringIO): - - def __init__(self, v=None, *a, **kw): - _SIO_init(self, v.decode() if isinstance(v, _byte_t) else v, *a, **kw) - - def write(self, data): - _SIO_write(self, data.decode() if isinstance(data, _byte_t) else data) diff --git a/awx/lib/site-packages/celery/fixups/__init__.py b/awx/lib/site-packages/celery/fixups/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/fixups/django.py b/awx/lib/site-packages/celery/fixups/django.py deleted file mode 100644 index ab20325f59..0000000000 --- a/awx/lib/site-packages/celery/fixups/django.py +++ /dev/null @@ -1,234 +0,0 @@ -from __future__ import absolute_import - -import io -import os -import sys -import warnings - -from kombu.utils import cached_property, symbol_by_name - -from datetime import datetime -from importlib import import_module - -from celery import signals -from celery.exceptions import FixupWarning - -__all__ = ['DjangoFixup', 'fixup'] - -ERR_NOT_INSTALLED = """\ -Environment variable DJANGO_SETTINGS_MODULE is defined -but Django is not installed. Will not apply Django fixups! -""" - - -def _maybe_close_fd(fh): - try: - os.close(fh.fileno()) - except (AttributeError, OSError, TypeError): - # TypeError added for celery#962 - pass - - -def fixup(app, env='DJANGO_SETTINGS_MODULE'): - SETTINGS_MODULE = os.environ.get(env) - if SETTINGS_MODULE and 'django' not in app.loader_cls.lower(): - try: - import django # noqa - except ImportError: - warnings.warn(FixupWarning(ERR_NOT_INSTALLED)) - else: - return DjangoFixup(app).install() - - -class DjangoFixup(object): - - def __init__(self, app): - self.app = app - self.app.set_default() - - def install(self): - # Need to add project directory to path - sys.path.append(os.getcwd()) - - self.app.loader.now = self.now - self.app.loader.mail_admins = self.mail_admins - - signals.worker_init.connect(self.on_worker_init) - return self - - def on_worker_init(self, **kwargs): - # keep reference - self._worker_fixup = DjangoWorkerFixup(self.app).install() - - def now(self, utc=False): - return datetime.utcnow() if utc else self._now() - - def mail_admins(self, subject, body, fail_silently=False, **kwargs): - return self._mail_admins(subject, body, fail_silently=fail_silently) - - @cached_property - def _mail_admins(self): - return symbol_by_name('django.core.mail:mail_admins') - - @cached_property - def _now(self): - try: - return symbol_by_name('django.utils.timezone:now') - except (AttributeError, ImportError): # pre django-1.4 - return datetime.now - - -class DjangoWorkerFixup(object): - _db_recycles = 0 - - def __init__(self, app): - self.app = app - self.db_reuse_max = self.app.conf.get('CELERY_DB_REUSE_MAX', None) - self._db = import_module('django.db') - self._cache = import_module('django.core.cache') - self._settings = symbol_by_name('django.conf:settings') - - # Database-related exceptions. - DatabaseError = symbol_by_name('django.db:DatabaseError') - try: - import MySQLdb as mysql - _my_database_errors = (mysql.DatabaseError, - mysql.InterfaceError, - mysql.OperationalError) - except ImportError: - _my_database_errors = () # noqa - try: - import psycopg2 as pg - _pg_database_errors = (pg.DatabaseError, - pg.InterfaceError, - pg.OperationalError) - except ImportError: - _pg_database_errors = () # noqa - try: - import sqlite3 - _lite_database_errors = (sqlite3.DatabaseError, - sqlite3.InterfaceError, - sqlite3.OperationalError) - except ImportError: - _lite_database_errors = () # noqa - try: - import cx_Oracle as oracle - _oracle_database_errors = (oracle.DatabaseError, - oracle.InterfaceError, - oracle.OperationalError) - except ImportError: - _oracle_database_errors = () # noqa - - try: - self._close_old_connections = symbol_by_name( - 'django.db:close_old_connections', - ) - except (ImportError, AttributeError): - self._close_old_connections = None - self.database_errors = ( - (DatabaseError, ) + - _my_database_errors + - _pg_database_errors + - _lite_database_errors + - _oracle_database_errors - ) - - def validate_models(self): - s = io.StringIO() - try: - from django.core.management.validation import get_validation_errors - except ImportError: - import django - from django.core.management.base import BaseCommand - django.setup() - cmd = BaseCommand() - cmd.stdout, cmd.stderr = sys.stdout, sys.stderr - cmd.check() - else: - num_errors = get_validation_errors(s, None) - if num_errors: - raise RuntimeError( - 'One or more Django models did not validate:\n{0}'.format( - s.getvalue())) - - def install(self): - signals.beat_embedded_init.connect(self.close_database) - signals.worker_ready.connect(self.on_worker_ready) - signals.task_prerun.connect(self.on_task_prerun) - signals.task_postrun.connect(self.on_task_postrun) - signals.worker_process_init.connect(self.on_worker_process_init) - self.validate_models() - self.close_database() - self.close_cache() - return self - - def on_worker_process_init(self, **kwargs): - # the parent process may have established these, - # so need to close them. - - # calling db.close() on some DB connections will cause - # the inherited DB conn to also get broken in the parent - # process so we need to remove it without triggering any - # network IO that close() might cause. - try: - for c in self._db.connections.all(): - if c and c.connection: - _maybe_close_fd(c.connection) - except AttributeError: - if self._db.connection and self._db.connection.connection: - _maybe_close_fd(self._db.connection.connection) - - # use the _ version to avoid DB_REUSE preventing the conn.close() call - self._close_database() - self.close_cache() - - def on_task_prerun(self, sender, **kwargs): - """Called before every task.""" - if not getattr(sender.request, 'is_eager', False): - self.close_database() - - def on_task_postrun(self, sender, **kwargs): - # See http://groups.google.com/group/django-users/ - # browse_thread/thread/78200863d0c07c6d/ - if not getattr(sender.request, 'is_eager', False): - self.close_database() - self.close_cache() - - def close_database(self, **kwargs): - if self._close_old_connections: - return self._close_old_connections() # Django 1.6 - if not self.db_reuse_max: - return self._close_database() - if self._db_recycles >= self.db_reuse_max * 2: - self._db_recycles = 0 - self._close_database() - self._db_recycles += 1 - - def _close_database(self): - try: - funs = [conn.close for conn in self._db.connections] - except AttributeError: - if hasattr(self._db, 'close_old_connections'): # django 1.6 - funs = [self._db.close_old_connections] - else: - # pre multidb, pending deprication in django 1.6 - funs = [self._db.close_connection] - - for close in funs: - try: - close() - except self.database_errors as exc: - str_exc = str(exc) - if 'closed' not in str_exc and 'not connected' not in str_exc: - raise - - def close_cache(self): - try: - self._cache.cache.close() - except (TypeError, AttributeError): - pass - - def on_worker_ready(self, **kwargs): - if self._settings.DEBUG: - warnings.warn('Using settings.DEBUG leads to a memory leak, never ' - 'use this setting in production environments!') diff --git a/awx/lib/site-packages/celery/loaders/__init__.py b/awx/lib/site-packages/celery/loaders/__init__.py deleted file mode 100644 index 2a39ba2ab7..0000000000 --- a/awx/lib/site-packages/celery/loaders/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.loaders - ~~~~~~~~~~~~~~ - - Loaders define how configuration is read, what happens - when workers start, when tasks are executed and so on. - -""" -from __future__ import absolute_import - -from celery._state import current_app -from celery.utils import deprecated -from celery.utils.imports import symbol_by_name, import_from_cwd - -__all__ = ['get_loader_cls'] - -LOADER_ALIASES = {'app': 'celery.loaders.app:AppLoader', - 'default': 'celery.loaders.default:Loader', - 'django': 'djcelery.loaders:DjangoLoader'} - - -def get_loader_cls(loader): - """Get loader class by name/alias""" - return symbol_by_name(loader, LOADER_ALIASES, imp=import_from_cwd) - - -@deprecated(deprecation=2.5, removal=4.0, - alternative='celery.current_app.loader') -def current_loader(): - return current_app.loader - - -@deprecated(deprecation=2.5, removal=4.0, - alternative='celery.current_app.conf') -def load_settings(): - return current_app.conf diff --git a/awx/lib/site-packages/celery/loaders/app.py b/awx/lib/site-packages/celery/loaders/app.py deleted file mode 100644 index 87f034bf61..0000000000 --- a/awx/lib/site-packages/celery/loaders/app.py +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.loaders.app - ~~~~~~~~~~~~~~~~~~ - - The default loader used with custom app instances. - -""" -from __future__ import absolute_import - -from .base import BaseLoader - -__all__ = ['AppLoader'] - - -class AppLoader(BaseLoader): - pass diff --git a/awx/lib/site-packages/celery/loaders/base.py b/awx/lib/site-packages/celery/loaders/base.py deleted file mode 100644 index d73547aadf..0000000000 --- a/awx/lib/site-packages/celery/loaders/base.py +++ /dev/null @@ -1,291 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.loaders.base - ~~~~~~~~~~~~~~~~~~~ - - Loader base class. - -""" -from __future__ import absolute_import - -import anyjson -import imp as _imp -import importlib -import os -import re -import sys - -from datetime import datetime - -from kombu.utils import cached_property -from kombu.utils.encoding import safe_str - -from celery import signals -from celery.datastructures import DictAttribute, force_mapping -from celery.five import reraise, string_t -from celery.utils.functional import maybe_list -from celery.utils.imports import ( - import_from_cwd, symbol_by_name, NotAPackage, find_module, -) - -__all__ = ['BaseLoader'] - -_RACE_PROTECTION = False -CONFIG_INVALID_NAME = """\ -Error: Module '{module}' doesn't exist, or it's not a valid \ -Python module name. -""" - -CONFIG_WITH_SUFFIX = CONFIG_INVALID_NAME + """\ -Did you mean '{suggest}'? -""" - - -class BaseLoader(object): - """The base class for loaders. - - Loaders handles, - - * Reading celery client/worker configurations. - - * What happens when a task starts? - See :meth:`on_task_init`. - - * What happens when the worker starts? - See :meth:`on_worker_init`. - - * What happens when the worker shuts down? - See :meth:`on_worker_shutdown`. - - * What modules are imported to find tasks? - - """ - builtin_modules = frozenset() - configured = False - override_backends = {} - worker_initialized = False - - _conf = None - - def __init__(self, app, **kwargs): - self.app = app - self.task_modules = set() - - def now(self, utc=True): - if utc: - return datetime.utcnow() - return datetime.now() - - def on_task_init(self, task_id, task): - """This method is called before a task is executed.""" - pass - - def on_process_cleanup(self): - """This method is called after a task is executed.""" - pass - - def on_worker_init(self): - """This method is called when the worker (:program:`celery worker`) - starts.""" - pass - - def on_worker_shutdown(self): - """This method is called when the worker (:program:`celery worker`) - shuts down.""" - pass - - def on_worker_process_init(self): - """This method is called when a child process starts.""" - pass - - def import_task_module(self, module): - self.task_modules.add(module) - return self.import_from_cwd(module) - - def import_module(self, module, package=None): - return importlib.import_module(module, package=package) - - def import_from_cwd(self, module, imp=None, package=None): - return import_from_cwd( - module, - self.import_module if imp is None else imp, - package=package, - ) - - def import_default_modules(self): - signals.import_modules.send(sender=self.app) - return [ - self.import_task_module(m) for m in ( - tuple(self.builtin_modules) + - tuple(maybe_list(self.app.conf.CELERY_IMPORTS)) + - tuple(maybe_list(self.app.conf.CELERY_INCLUDE)) - ) - ] - - def init_worker(self): - if not self.worker_initialized: - self.worker_initialized = True - self.import_default_modules() - self.on_worker_init() - - def shutdown_worker(self): - self.on_worker_shutdown() - - def init_worker_process(self): - self.on_worker_process_init() - - def config_from_object(self, obj, silent=False): - if isinstance(obj, string_t): - try: - obj = self._smart_import(obj, imp=self.import_from_cwd) - except (ImportError, AttributeError): - if silent: - return False - raise - self._conf = force_mapping(obj) - return True - - def _smart_import(self, path, imp=None): - imp = self.import_module if imp is None else imp - if ':' in path: - # Path includes attribute so can just jump here. - # e.g. ``os.path:abspath``. - return symbol_by_name(path, imp=imp) - - # Not sure if path is just a module name or if it includes an - # attribute name (e.g. ``os.path``, vs, ``os.path.abspath`` - try: - return imp(path) - except ImportError: - # Not a module name, so try module + attribute. - return symbol_by_name(path, imp=imp) - - def _import_config_module(self, name): - try: - self.find_module(name) - except NotAPackage: - if name.endswith('.py'): - reraise(NotAPackage, NotAPackage(CONFIG_WITH_SUFFIX.format( - module=name, suggest=name[:-3])), sys.exc_info()[2]) - reraise(NotAPackage, NotAPackage(CONFIG_INVALID_NAME.format( - module=name)), sys.exc_info()[2]) - else: - return self.import_from_cwd(name) - - def find_module(self, module): - return find_module(module) - - def cmdline_config_parser( - self, args, namespace='celery', - re_type=re.compile(r'\((\w+)\)'), - extra_types={'json': anyjson.loads}, - override_types={'tuple': 'json', - 'list': 'json', - 'dict': 'json'}): - from celery.app.defaults import Option, NAMESPACES - namespace = namespace.upper() - typemap = dict(Option.typemap, **extra_types) - - def getarg(arg): - """Parse a single configuration definition from - the command-line.""" - - ## find key/value - # ns.key=value|ns_key=value (case insensitive) - key, value = arg.split('=', 1) - key = key.upper().replace('.', '_') - - ## find namespace. - # .key=value|_key=value expands to default namespace. - if key[0] == '_': - ns, key = namespace, key[1:] - else: - # find namespace part of key - ns, key = key.split('_', 1) - - ns_key = (ns and ns + '_' or '') + key - - # (type)value makes cast to custom type. - cast = re_type.match(value) - if cast: - type_ = cast.groups()[0] - type_ = override_types.get(type_, type_) - value = value[len(cast.group()):] - value = typemap[type_](value) - else: - try: - value = NAMESPACES[ns][key].to_python(value) - except ValueError as exc: - # display key name in error message. - raise ValueError('{0!r}: {1}'.format(ns_key, exc)) - return ns_key, value - return dict(getarg(arg) for arg in args) - - def mail_admins(self, subject, body, fail_silently=False, - sender=None, to=None, host=None, port=None, - user=None, password=None, timeout=None, - use_ssl=False, use_tls=False): - message = self.mail.Message(sender=sender, to=to, - subject=safe_str(subject), - body=safe_str(body)) - mailer = self.mail.Mailer(host=host, port=port, - user=user, password=password, - timeout=timeout, use_ssl=use_ssl, - use_tls=use_tls) - mailer.send(message, fail_silently=fail_silently) - - def read_configuration(self, env='CELERY_CONFIG_MODULE'): - try: - custom_config = os.environ[env] - except KeyError: - pass - else: - if custom_config: - usercfg = self._import_config_module(custom_config) - return DictAttribute(usercfg) - return {} - - def autodiscover_tasks(self, packages, related_name='tasks'): - self.task_modules.update( - mod.__name__ for mod in autodiscover_tasks(packages or (), - related_name) if mod) - - @property - def conf(self): - """Loader configuration.""" - if self._conf is None: - self._conf = self.read_configuration() - return self._conf - - @cached_property - def mail(self): - return self.import_module('celery.utils.mail') - - -def autodiscover_tasks(packages, related_name='tasks'): - global _RACE_PROTECTION - - if _RACE_PROTECTION: - return () - _RACE_PROTECTION = True - try: - return [find_related_module(pkg, related_name) for pkg in packages] - finally: - _RACE_PROTECTION = False - - -def find_related_module(package, related_name): - """Given a package name and a module name, tries to find that - module.""" - - try: - pkg_path = importlib.import_module(package).__path__ - except AttributeError: - return - - try: - _imp.find_module(related_name, pkg_path) - except ImportError: - return - - return importlib.import_module('{0}.{1}'.format(package, related_name)) diff --git a/awx/lib/site-packages/celery/loaders/default.py b/awx/lib/site-packages/celery/loaders/default.py deleted file mode 100644 index 60714805e6..0000000000 --- a/awx/lib/site-packages/celery/loaders/default.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.loaders.default - ~~~~~~~~~~~~~~~~~~~~~~ - - The default loader used when no custom app has been initialized. - -""" -from __future__ import absolute_import - -import os -import warnings - -from celery.datastructures import DictAttribute -from celery.exceptions import NotConfigured -from celery.utils import strtobool - -from .base import BaseLoader - -__all__ = ['Loader', 'DEFAULT_CONFIG_MODULE'] - -DEFAULT_CONFIG_MODULE = 'celeryconfig' - -#: Warns if configuration file is missing if :envvar:`C_WNOCONF` is set. -C_WNOCONF = strtobool(os.environ.get('C_WNOCONF', False)) - - -class Loader(BaseLoader): - """The loader used by the default app.""" - - def setup_settings(self, settingsdict): - return DictAttribute(settingsdict) - - def read_configuration(self, fail_silently=True): - """Read configuration from :file:`celeryconfig.py` and configure - celery and Django so it can be used by regular Python.""" - configname = os.environ.get('CELERY_CONFIG_MODULE', - DEFAULT_CONFIG_MODULE) - try: - usercfg = self._import_config_module(configname) - except ImportError: - if not fail_silently: - raise - # billiard sets this if forked using execv - if C_WNOCONF and not os.environ.get('FORKED_BY_MULTIPROCESSING'): - warnings.warn(NotConfigured( - 'No {module} module found! Please make sure it exists and ' - 'is available to Python.'.format(module=configname))) - return self.setup_settings({}) - else: - self.configured = True - return self.setup_settings(usercfg) diff --git a/awx/lib/site-packages/celery/local.py b/awx/lib/site-packages/celery/local.py deleted file mode 100644 index ada6e9381a..0000000000 --- a/awx/lib/site-packages/celery/local.py +++ /dev/null @@ -1,281 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.local - ~~~~~~~~~~~~ - - This module contains critical utilities that - needs to be loaded as soon as possible, and that - shall not load any third party modules. - - Parts of this module is Copyright by Werkzeug Team. - -""" -from __future__ import absolute_import - -import importlib -import sys - -from .five import string - -__all__ = ['Proxy', 'PromiseProxy', 'try_import', 'maybe_evaluate'] - -__module__ = __name__ # used by Proxy class body - -PY3 = sys.version_info[0] == 3 - - -def _default_cls_attr(name, type_, cls_value): - # Proxy uses properties to forward the standard - # class attributes __module__, __name__ and __doc__ to the real - # object, but these needs to be a string when accessed from - # the Proxy class directly. This is a hack to make that work. - # -- See Issue #1087. - - def __new__(cls, getter): - instance = type_.__new__(cls, cls_value) - instance.__getter = getter - return instance - - def __get__(self, obj, cls=None): - return self.__getter(obj) if obj is not None else self - - return type(name, (type_, ), { - '__new__': __new__, '__get__': __get__, - }) - - -def try_import(module, default=None): - """Try to import and return module, or return - None if the module does not exist.""" - try: - return importlib.import_module(module) - except ImportError: - return default - - -class Proxy(object): - """Proxy to another object.""" - - # Code stolen from werkzeug.local.Proxy. - __slots__ = ('__local', '__args', '__kwargs', '__dict__') - - def __init__(self, local, - args=None, kwargs=None, name=None, __doc__=None): - object.__setattr__(self, '_Proxy__local', local) - object.__setattr__(self, '_Proxy__args', args or ()) - object.__setattr__(self, '_Proxy__kwargs', kwargs or {}) - if name is not None: - object.__setattr__(self, '__custom_name__', name) - if __doc__ is not None: - object.__setattr__(self, '__doc__', __doc__) - - @_default_cls_attr('name', str, __name__) - def __name__(self): - try: - return self.__custom_name__ - except AttributeError: - return self._get_current_object().__name__ - - @_default_cls_attr('module', str, __module__) - def __module__(self): - return self._get_current_object().__module__ - - @_default_cls_attr('doc', str, __doc__) - def __doc__(self): - return self._get_current_object().__doc__ - - def _get_class(self): - return self._get_current_object().__class__ - - @property - def __class__(self): - return self._get_class() - - def _get_current_object(self): - """Return the current object. This is useful if you want the real - object behind the proxy at a time for performance reasons or because - you want to pass the object into a different context. - """ - loc = object.__getattribute__(self, '_Proxy__local') - if not hasattr(loc, '__release_local__'): - return loc(*self.__args, **self.__kwargs) - try: - return getattr(loc, self.__name__) - except AttributeError: - raise RuntimeError('no object bound to {0.__name__}'.format(self)) - - @property - def __dict__(self): - try: - return self._get_current_object().__dict__ - except RuntimeError: # pragma: no cover - raise AttributeError('__dict__') - - def __repr__(self): - try: - obj = self._get_current_object() - except RuntimeError: # pragma: no cover - return '<{0} unbound>'.format(self.__class__.__name__) - return repr(obj) - - def __bool__(self): - try: - return bool(self._get_current_object()) - except RuntimeError: # pragma: no cover - return False - __nonzero__ = __bool__ # Py2 - - def __unicode__(self): - try: - return string(self._get_current_object()) - except RuntimeError: # pragma: no cover - return repr(self) - - def __dir__(self): - try: - return dir(self._get_current_object()) - except RuntimeError: # pragma: no cover - return [] - - def __getattr__(self, name): - if name == '__members__': - return dir(self._get_current_object()) - return getattr(self._get_current_object(), name) - - def __setitem__(self, key, value): - self._get_current_object()[key] = value - - def __delitem__(self, key): - del self._get_current_object()[key] - - def __setslice__(self, i, j, seq): - self._get_current_object()[i:j] = seq - - def __delslice__(self, i, j): - del self._get_current_object()[i:j] - - __setattr__ = lambda x, n, v: setattr(x._get_current_object(), n, v) - __delattr__ = lambda x, n: delattr(x._get_current_object(), n) - __str__ = lambda x: str(x._get_current_object()) - __lt__ = lambda x, o: x._get_current_object() < o - __le__ = lambda x, o: x._get_current_object() <= o - __eq__ = lambda x, o: x._get_current_object() == o - __ne__ = lambda x, o: x._get_current_object() != o - __gt__ = lambda x, o: x._get_current_object() > o - __ge__ = lambda x, o: x._get_current_object() >= o - __hash__ = lambda x: hash(x._get_current_object()) - __call__ = lambda x, *a, **kw: x._get_current_object()(*a, **kw) - __len__ = lambda x: len(x._get_current_object()) - __getitem__ = lambda x, i: x._get_current_object()[i] - __iter__ = lambda x: iter(x._get_current_object()) - __contains__ = lambda x, i: i in x._get_current_object() - __getslice__ = lambda x, i, j: x._get_current_object()[i:j] - __add__ = lambda x, o: x._get_current_object() + o - __sub__ = lambda x, o: x._get_current_object() - o - __mul__ = lambda x, o: x._get_current_object() * o - __floordiv__ = lambda x, o: x._get_current_object() // o - __mod__ = lambda x, o: x._get_current_object() % o - __divmod__ = lambda x, o: x._get_current_object().__divmod__(o) - __pow__ = lambda x, o: x._get_current_object() ** o - __lshift__ = lambda x, o: x._get_current_object() << o - __rshift__ = lambda x, o: x._get_current_object() >> o - __and__ = lambda x, o: x._get_current_object() & o - __xor__ = lambda x, o: x._get_current_object() ^ o - __or__ = lambda x, o: x._get_current_object() | o - __div__ = lambda x, o: x._get_current_object().__div__(o) - __truediv__ = lambda x, o: x._get_current_object().__truediv__(o) - __neg__ = lambda x: -(x._get_current_object()) - __pos__ = lambda x: +(x._get_current_object()) - __abs__ = lambda x: abs(x._get_current_object()) - __invert__ = lambda x: ~(x._get_current_object()) - __complex__ = lambda x: complex(x._get_current_object()) - __int__ = lambda x: int(x._get_current_object()) - __float__ = lambda x: float(x._get_current_object()) - __oct__ = lambda x: oct(x._get_current_object()) - __hex__ = lambda x: hex(x._get_current_object()) - __index__ = lambda x: x._get_current_object().__index__() - __coerce__ = lambda x, o: x._get_current_object().__coerce__(o) - __enter__ = lambda x: x._get_current_object().__enter__() - __exit__ = lambda x, *a, **kw: x._get_current_object().__exit__(*a, **kw) - __reduce__ = lambda x: x._get_current_object().__reduce__() - - if not PY3: - __cmp__ = lambda x, o: cmp(x._get_current_object(), o) # noqa - __long__ = lambda x: long(x._get_current_object()) # noqa - - -class PromiseProxy(Proxy): - """This is a proxy to an object that has not yet been evaulated. - - :class:`Proxy` will evaluate the object each time, while the - promise will only evaluate it once. - - """ - - __slots__ = ('__pending__', ) - - def _get_current_object(self): - try: - return object.__getattribute__(self, '__thing') - except AttributeError: - return self.__evaluate__() - - def __then__(self, fun, *args, **kwargs): - if self.__evaluated__(): - return fun(*args, **kwargs) - from collections import deque - try: - pending = object.__getattribute__(self, '__pending__') - except AttributeError: - pending = None - if pending is None: - pending = deque() - object.__setattr__(self, '__pending__', pending) - pending.append((fun, args, kwargs)) - - def __evaluated__(self): - try: - object.__getattribute__(self, '__thing') - except AttributeError: - return False - return True - - def __maybe_evaluate__(self): - return self._get_current_object() - - def __evaluate__(self, - _clean=('_Proxy__local', - '_Proxy__args', - '_Proxy__kwargs')): - try: - thing = Proxy._get_current_object(self) - object.__setattr__(self, '__thing', thing) - return thing - finally: - for attr in _clean: - try: - object.__delattr__(self, attr) - except AttributeError: # pragma: no cover - # May mask errors so ignore - pass - try: - pending = object.__getattribute__(self, '__pending__') - except AttributeError: - pass - else: - try: - while pending: - fun, args, kwargs = pending.popleft() - fun(*args, **kwargs) - finally: - try: - object.__delattr__(self, '__pending__') - except AttributeError: - pass - - -def maybe_evaluate(obj): - try: - return obj.__maybe_evaluate__() - except AttributeError: - return obj diff --git a/awx/lib/site-packages/celery/platforms.py b/awx/lib/site-packages/celery/platforms.py deleted file mode 100644 index c4013b5785..0000000000 --- a/awx/lib/site-packages/celery/platforms.py +++ /dev/null @@ -1,763 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.platforms - ~~~~~~~~~~~~~~~~ - - Utilities dealing with platform specifics: signals, daemonization, - users, groups, and so on. - -""" -from __future__ import absolute_import, print_function - -import atexit -import errno -import math -import numbers -import os -import platform as _platform -import signal as _signal -import sys -import warnings - -from collections import namedtuple - -from billiard import current_process -# fileno used to be in this module -from kombu.utils import maybe_fileno -from kombu.utils.compat import get_errno -from kombu.utils.encoding import safe_str -from contextlib import contextmanager - -from .local import try_import -from .five import items, range, reraise, string_t, zip_longest -from .utils.functional import uniq - -_setproctitle = try_import('setproctitle') -resource = try_import('resource') -pwd = try_import('pwd') -grp = try_import('grp') - -__all__ = ['EX_OK', 'EX_FAILURE', 'EX_UNAVAILABLE', 'EX_USAGE', 'SYSTEM', - 'IS_OSX', 'IS_WINDOWS', 'pyimplementation', 'LockFailed', - 'get_fdmax', 'Pidfile', 'create_pidlock', - 'close_open_fds', 'DaemonContext', 'detached', 'parse_uid', - 'parse_gid', 'setgroups', 'initgroups', 'setgid', 'setuid', - 'maybe_drop_privileges', 'signals', 'set_process_title', - 'set_mp_process_title', 'get_errno_name', 'ignore_errno'] - -# exitcodes -EX_OK = getattr(os, 'EX_OK', 0) -EX_FAILURE = 1 -EX_UNAVAILABLE = getattr(os, 'EX_UNAVAILABLE', 69) -EX_USAGE = getattr(os, 'EX_USAGE', 64) -EX_CANTCREAT = getattr(os, 'EX_CANTCREAT', 73) - -SYSTEM = _platform.system() -IS_OSX = SYSTEM == 'Darwin' -IS_WINDOWS = SYSTEM == 'Windows' - -DAEMON_UMASK = 0 -DAEMON_WORKDIR = '/' - -PIDFILE_FLAGS = os.O_CREAT | os.O_EXCL | os.O_WRONLY -PIDFILE_MODE = ((os.R_OK | os.W_OK) << 6) | ((os.R_OK) << 3) | ((os.R_OK)) - -PIDLOCKED = """ERROR: Pidfile ({0}) already exists. -Seems we're already running? (pid: {1})""" - -_range = namedtuple('_range', ('start', 'stop')) - -C_FORCE_ROOT = os.environ.get('C_FORCE_ROOT', False) - -ROOT_DISALLOWED = """\ -Running a worker with superuser privileges when the -worker accepts messages serialized with pickle is a very bad idea! - -If you really want to continue then you have to set the C_FORCE_ROOT -environment variable (but please think about this before you do). - -User information: uid={uid} euid={euid} gid={gid} egid={egid} -""" - -ROOT_DISCOURAGED = """\ -You are running the worker with superuser privileges, which is -absolutely not recommended! - -Please specify a different user using the -u option. - -User information: uid={uid} euid={euid} gid={gid} egid={egid} -""" - - -def pyimplementation(): - """Return string identifying the current Python implementation.""" - if hasattr(_platform, 'python_implementation'): - return _platform.python_implementation() - elif sys.platform.startswith('java'): - return 'Jython ' + sys.platform - elif hasattr(sys, 'pypy_version_info'): - v = '.'.join(str(p) for p in sys.pypy_version_info[:3]) - if sys.pypy_version_info[3:]: - v += '-' + ''.join(str(p) for p in sys.pypy_version_info[3:]) - return 'PyPy ' + v - else: - return 'CPython' - - -class LockFailed(Exception): - """Raised if a pidlock can't be acquired.""" - - -def get_fdmax(default=None): - """Return the maximum number of open file descriptors - on this system. - - :keyword default: Value returned if there's no file - descriptor limit. - - """ - try: - return os.sysconf('SC_OPEN_MAX') - except: - pass - if resource is None: # Windows - return default - fdmax = resource.getrlimit(resource.RLIMIT_NOFILE)[1] - if fdmax == resource.RLIM_INFINITY: - return default - return fdmax - - -class Pidfile(object): - """Pidfile - - This is the type returned by :func:`create_pidlock`. - - TIP: Use the :func:`create_pidlock` function instead, - which is more convenient and also removes stale pidfiles (when - the process holding the lock is no longer running). - - """ - - #: Path to the pid lock file. - path = None - - def __init__(self, path): - self.path = os.path.abspath(path) - - def acquire(self): - """Acquire lock.""" - try: - self.write_pid() - except OSError as exc: - reraise(LockFailed, LockFailed(str(exc)), sys.exc_info()[2]) - return self - __enter__ = acquire - - def is_locked(self): - """Return true if the pid lock exists.""" - return os.path.exists(self.path) - - def release(self, *args): - """Release lock.""" - self.remove() - __exit__ = release - - def read_pid(self): - """Read and return the current pid.""" - with ignore_errno('ENOENT'): - with open(self.path, 'r') as fh: - line = fh.readline() - if line.strip() == line: # must contain '\n' - raise ValueError( - 'Partial or invalid pidfile {0.path}'.format(self)) - - try: - return int(line.strip()) - except ValueError: - raise ValueError( - 'pidfile {0.path} contents invalid.'.format(self)) - - def remove(self): - """Remove the lock.""" - with ignore_errno(errno.ENOENT, errno.EACCES): - os.unlink(self.path) - - def remove_if_stale(self): - """Remove the lock if the process is not running. - (does not respond to signals).""" - try: - pid = self.read_pid() - except ValueError as exc: - print('Broken pidfile found. Removing it.', file=sys.stderr) - self.remove() - return True - if not pid: - self.remove() - return True - - try: - os.kill(pid, 0) - except os.error as exc: - if exc.errno == errno.ESRCH: - print('Stale pidfile exists. Removing it.', file=sys.stderr) - self.remove() - return True - return False - - def write_pid(self): - pid = os.getpid() - content = '{0}\n'.format(pid) - - pidfile_fd = os.open(self.path, PIDFILE_FLAGS, PIDFILE_MODE) - pidfile = os.fdopen(pidfile_fd, 'w') - try: - pidfile.write(content) - # flush and sync so that the re-read below works. - pidfile.flush() - try: - os.fsync(pidfile_fd) - except AttributeError: # pragma: no cover - pass - finally: - pidfile.close() - - rfh = open(self.path) - try: - if rfh.read() != content: - raise LockFailed( - "Inconsistency: Pidfile content doesn't match at re-read") - finally: - rfh.close() -PIDFile = Pidfile # compat alias - - -def create_pidlock(pidfile): - """Create and verify pidfile. - - If the pidfile already exists the program exits with an error message, - however if the process it refers to is not running anymore, the pidfile - is deleted and the program continues. - - This function will automatically install an :mod:`atexit` handler - to release the lock at exit, you can skip this by calling - :func:`_create_pidlock` instead. - - :returns: :class:`Pidfile`. - - **Example**: - - .. code-block:: python - - pidlock = create_pidlock('/var/run/app.pid') - - """ - pidlock = _create_pidlock(pidfile) - atexit.register(pidlock.release) - return pidlock - - -def _create_pidlock(pidfile): - pidlock = Pidfile(pidfile) - if pidlock.is_locked() and not pidlock.remove_if_stale(): - print(PIDLOCKED.format(pidfile, pidlock.read_pid()), file=sys.stderr) - raise SystemExit(EX_CANTCREAT) - pidlock.acquire() - return pidlock - - -if hasattr(os, 'closerange'): - - def close_open_fds(keep=None): - # must make sure this is 0-inclusive (Issue #1882) - keep = list(uniq(sorted( - f for f in map(maybe_fileno, keep or []) if f is not None - ))) - maxfd = get_fdmax(default=2048) - kL, kH = iter([-1] + keep), iter(keep + [maxfd]) - for low, high in zip_longest(kL, kH): - if low + 1 != high: - os.closerange(low + 1, high) - -else: - - def close_open_fds(keep=None): # noqa - keep = [maybe_fileno(f) - for f in (keep or []) if maybe_fileno(f) is not None] - for fd in reversed(range(get_fdmax(default=2048))): - if fd not in keep: - with ignore_errno(errno.EBADF): - os.close(fd) - - -class DaemonContext(object): - _is_open = False - - def __init__(self, pidfile=None, workdir=None, umask=None, - fake=False, after_chdir=None, **kwargs): - self.workdir = workdir or DAEMON_WORKDIR - self.umask = DAEMON_UMASK if umask is None else umask - self.fake = fake - self.after_chdir = after_chdir - self.stdfds = (sys.stdin, sys.stdout, sys.stderr) - - def redirect_to_null(self, fd): - if fd is not None: - dest = os.open(os.devnull, os.O_RDWR) - os.dup2(dest, fd) - - def open(self): - if not self._is_open: - if not self.fake: - self._detach() - - os.chdir(self.workdir) - os.umask(self.umask) - - if self.after_chdir: - self.after_chdir() - - close_open_fds(self.stdfds) - for fd in self.stdfds: - self.redirect_to_null(maybe_fileno(fd)) - - self._is_open = True - __enter__ = open - - def close(self, *args): - if self._is_open: - self._is_open = False - __exit__ = close - - def _detach(self): - if os.fork() == 0: # first child - os.setsid() # create new session - if os.fork() > 0: # second child - os._exit(0) - else: - os._exit(0) - return self - - -def detached(logfile=None, pidfile=None, uid=None, gid=None, umask=0, - workdir=None, fake=False, **opts): - """Detach the current process in the background (daemonize). - - :keyword logfile: Optional log file. The ability to write to this file - will be verified before the process is detached. - :keyword pidfile: Optional pidfile. The pidfile will not be created, - as this is the responsibility of the child. But the process will - exit if the pid lock exists and the pid written is still running. - :keyword uid: Optional user id or user name to change - effective privileges to. - :keyword gid: Optional group id or group name to change effective - privileges to. - :keyword umask: Optional umask that will be effective in the child process. - :keyword workdir: Optional new working directory. - :keyword fake: Don't actually detach, intented for debugging purposes. - :keyword \*\*opts: Ignored. - - **Example**: - - .. code-block:: python - - from celery.platforms import detached, create_pidlock - - with detached(logfile='/var/log/app.log', pidfile='/var/run/app.pid', - uid='nobody'): - # Now in detached child process with effective user set to nobody, - # and we know that our logfile can be written to, and that - # the pidfile is not locked. - pidlock = create_pidlock('/var/run/app.pid') - - # Run the program - program.run(logfile='/var/log/app.log') - - """ - - if not resource: - raise RuntimeError('This platform does not support detach.') - workdir = os.getcwd() if workdir is None else workdir - - signals.reset('SIGCLD') # Make sure SIGCLD is using the default handler. - maybe_drop_privileges(uid=uid, gid=gid) - - def after_chdir_do(): - # Since without stderr any errors will be silently suppressed, - # we need to know that we have access to the logfile. - logfile and open(logfile, 'a').close() - # Doesn't actually create the pidfile, but makes sure it's not stale. - if pidfile: - _create_pidlock(pidfile).release() - - return DaemonContext( - umask=umask, workdir=workdir, fake=fake, after_chdir=after_chdir_do, - ) - - -def parse_uid(uid): - """Parse user id. - - uid can be an integer (uid) or a string (user name), if a user name - the uid is taken from the system user registry. - - """ - try: - return int(uid) - except ValueError: - try: - return pwd.getpwnam(uid).pw_uid - except (AttributeError, KeyError): - raise KeyError('User does not exist: {0}'.format(uid)) - - -def parse_gid(gid): - """Parse group id. - - gid can be an integer (gid) or a string (group name), if a group name - the gid is taken from the system group registry. - - """ - try: - return int(gid) - except ValueError: - try: - return grp.getgrnam(gid).gr_gid - except (AttributeError, KeyError): - raise KeyError('Group does not exist: {0}'.format(gid)) - - -def _setgroups_hack(groups): - """:fun:`setgroups` may have a platform-dependent limit, - and it is not always possible to know in advance what this limit - is, so we use this ugly hack stolen from glibc.""" - groups = groups[:] - - while 1: - try: - return os.setgroups(groups) - except ValueError: # error from Python's check. - if len(groups) <= 1: - raise - groups[:] = groups[:-1] - except OSError as exc: # error from the OS. - if exc.errno != errno.EINVAL or len(groups) <= 1: - raise - groups[:] = groups[:-1] - - -def setgroups(groups): - """Set active groups from a list of group ids.""" - max_groups = None - try: - max_groups = os.sysconf('SC_NGROUPS_MAX') - except Exception: - pass - try: - return _setgroups_hack(groups[:max_groups]) - except OSError as exc: - if exc.errno != errno.EPERM: - raise - if any(group not in groups for group in os.getgroups()): - # we shouldn't be allowed to change to this group. - raise - - -def initgroups(uid, gid): - """Compat version of :func:`os.initgroups` which was first - added to Python 2.7.""" - if not pwd: # pragma: no cover - return - username = pwd.getpwuid(uid)[0] - if hasattr(os, 'initgroups'): # Python 2.7+ - return os.initgroups(username, gid) - groups = [gr.gr_gid for gr in grp.getgrall() - if username in gr.gr_mem] - setgroups(groups) - - -def setgid(gid): - """Version of :func:`os.setgid` supporting group names.""" - os.setgid(parse_gid(gid)) - - -def setuid(uid): - """Version of :func:`os.setuid` supporting usernames.""" - os.setuid(parse_uid(uid)) - - -def maybe_drop_privileges(uid=None, gid=None): - """Change process privileges to new user/group. - - If UID and GID is specified, the real user/group is changed. - - If only UID is specified, the real user is changed, and the group is - changed to the users primary group. - - If only GID is specified, only the group is changed. - - """ - if sys.platform == 'win32': - return - if os.geteuid(): - # no point trying to setuid unless we're root. - if not os.getuid(): - raise AssertionError('contact support') - uid = uid and parse_uid(uid) - gid = gid and parse_gid(gid) - - if uid: - # If GID isn't defined, get the primary GID of the user. - if not gid and pwd: - gid = pwd.getpwuid(uid).pw_gid - # Must set the GID before initgroups(), as setgid() - # is known to zap the group list on some platforms. - - # setgid must happen before setuid (otherwise the setgid operation - # may fail because of insufficient privileges and possibly stay - # in a privileged group). - setgid(gid) - initgroups(uid, gid) - - # at last: - setuid(uid) - # ... and make sure privileges cannot be restored: - try: - setuid(0) - except OSError as exc: - if get_errno(exc) != errno.EPERM: - raise - pass # Good: cannot restore privileges. - else: - raise RuntimeError( - 'non-root user able to restore privileges after setuid.') - else: - gid and setgid(gid) - - if uid and (not os.getuid()) and not (os.geteuid()): - raise AssertionError('Still root uid after drop privileges!') - if gid and (not os.getgid()) and not (os.getegid()): - raise AssertionError('Still root gid after drop privileges!') - - -class Signals(object): - """Convenience interface to :mod:`signals`. - - If the requested signal is not supported on the current platform, - the operation will be ignored. - - **Examples**: - - .. code-block:: python - - >>> from celery.platforms import signals - - >>> from proj.handlers import my_handler - >>> signals['INT'] = my_handler - - >>> signals['INT'] - my_handler - - >>> signals.supported('INT') - True - - >>> signals.signum('INT') - 2 - - >>> signals.ignore('USR1') - >>> signals['USR1'] == signals.ignored - True - - >>> signals.reset('USR1') - >>> signals['USR1'] == signals.default - True - - >>> from proj.handlers import exit_handler, hup_handler - >>> signals.update(INT=exit_handler, - ... TERM=exit_handler, - ... HUP=hup_handler) - - """ - - ignored = _signal.SIG_IGN - default = _signal.SIG_DFL - - if hasattr(_signal, 'setitimer'): - - def arm_alarm(self, seconds): - _signal.setitimer(_signal.ITIMER_REAL, seconds) - else: # pragma: no cover - try: - from itimer import alarm as _itimer_alarm # noqa - except ImportError: - - def arm_alarm(self, seconds): # noqa - _signal.alarm(math.ceil(seconds)) - else: # pragma: no cover - - def arm_alarm(self, seconds): # noqa - return _itimer_alarm(seconds) # noqa - - def reset_alarm(self): - return _signal.alarm(0) - - def supported(self, signal_name): - """Return true value if ``signal_name`` exists on this platform.""" - try: - return self.signum(signal_name) - except AttributeError: - pass - - def signum(self, signal_name): - """Get signal number from signal name.""" - if isinstance(signal_name, numbers.Integral): - return signal_name - if not isinstance(signal_name, string_t) \ - or not signal_name.isupper(): - raise TypeError('signal name must be uppercase string.') - if not signal_name.startswith('SIG'): - signal_name = 'SIG' + signal_name - return getattr(_signal, signal_name) - - def reset(self, *signal_names): - """Reset signals to the default signal handler. - - Does nothing if the platform doesn't support signals, - or the specified signal in particular. - - """ - self.update((sig, self.default) for sig in signal_names) - - def ignore(self, *signal_names): - """Ignore signal using :const:`SIG_IGN`. - - Does nothing if the platform doesn't support signals, - or the specified signal in particular. - - """ - self.update((sig, self.ignored) for sig in signal_names) - - def __getitem__(self, signal_name): - return _signal.getsignal(self.signum(signal_name)) - - def __setitem__(self, signal_name, handler): - """Install signal handler. - - Does nothing if the current platform doesn't support signals, - or the specified signal in particular. - - """ - try: - _signal.signal(self.signum(signal_name), handler) - except (AttributeError, ValueError): - pass - - def update(self, _d_=None, **sigmap): - """Set signal handlers from a mapping.""" - for signal_name, handler in items(dict(_d_ or {}, **sigmap)): - self[signal_name] = handler - -signals = Signals() -get_signal = signals.signum # compat -install_signal_handler = signals.__setitem__ # compat -reset_signal = signals.reset # compat -ignore_signal = signals.ignore # compat - - -def strargv(argv): - arg_start = 2 if 'manage' in argv[0] else 1 - if len(argv) > arg_start: - return ' '.join(argv[arg_start:]) - return '' - - -def set_process_title(progname, info=None): - """Set the ps name for the currently running process. - - Only works if :mod:`setproctitle` is installed. - - """ - proctitle = '[{0}]'.format(progname) - proctitle = '{0} {1}'.format(proctitle, info) if info else proctitle - if _setproctitle: - _setproctitle.setproctitle(safe_str(proctitle)) - return proctitle - - -if os.environ.get('NOSETPS'): # pragma: no cover - - def set_mp_process_title(*a, **k): - pass -else: - - def set_mp_process_title(progname, info=None, hostname=None): # noqa - """Set the ps name using the multiprocessing process name. - - Only works if :mod:`setproctitle` is installed. - - """ - if hostname: - progname = '{0}: {1}'.format(progname, hostname) - return set_process_title( - '{0}:{1}'.format(progname, current_process().name), info=info) - - -def get_errno_name(n): - """Get errno for string, e.g. ``ENOENT``.""" - if isinstance(n, string_t): - return getattr(errno, n) - return n - - -@contextmanager -def ignore_errno(*errnos, **kwargs): - """Context manager to ignore specific POSIX error codes. - - Takes a list of error codes to ignore, which can be either - the name of the code, or the code integer itself:: - - >>> with ignore_errno('ENOENT'): - ... with open('foo', 'r') as fh: - ... return fh.read() - - >>> with ignore_errno(errno.ENOENT, errno.EPERM): - ... pass - - :keyword types: A tuple of exceptions to ignore (when the errno matches), - defaults to :exc:`Exception`. - """ - types = kwargs.get('types') or (Exception, ) - errnos = [get_errno_name(errno) for errno in errnos] - try: - yield - except types as exc: - if not hasattr(exc, 'errno'): - raise - if exc.errno not in errnos: - raise - - -def check_privileges(accept_content): - uid = os.getuid() if hasattr(os, 'getuid') else 65535 - gid = os.getgid() if hasattr(os, 'getgid') else 65535 - euid = os.geteuid() if hasattr(os, 'geteuid') else 65535 - egid = os.getegid() if hasattr(os, 'getegid') else 65535 - - if hasattr(os, 'fchown'): - if not all(hasattr(os, attr) - for attr in ['getuid', 'getgid', 'geteuid', 'getegid']): - raise AssertionError('suspicious platform, contact support') - - if not uid or not gid or not euid or not egid: - if ('pickle' in accept_content or - 'application/x-python-serialize' in accept_content): - if not C_FORCE_ROOT: - try: - print(ROOT_DISALLOWED.format( - uid=uid, euid=euid, gid=gid, egid=egid, - ), file=sys.stderr) - finally: - os._exit(1) - warnings.warn(RuntimeWarning(ROOT_DISCOURAGED.format( - uid=uid, euid=euid, gid=gid, egid=egid, - ))) diff --git a/awx/lib/site-packages/celery/result.py b/awx/lib/site-packages/celery/result.py deleted file mode 100644 index 069d8fde8c..0000000000 --- a/awx/lib/site-packages/celery/result.py +++ /dev/null @@ -1,910 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.result - ~~~~~~~~~~~~~ - - Task results/state and groups of results. - -""" -from __future__ import absolute_import - -import time -import warnings - -from collections import deque -from contextlib import contextmanager -from copy import copy - -from kombu.utils import cached_property -from kombu.utils.compat import OrderedDict - -from . import current_app -from . import states -from ._state import _set_task_join_will_block, task_join_will_block -from .app import app_or_default -from .datastructures import DependencyGraph, GraphFormatter -from .exceptions import IncompleteStream, TimeoutError -from .five import items, range, string_t, monotonic -from .utils import deprecated - -__all__ = ['ResultBase', 'AsyncResult', 'ResultSet', 'GroupResult', - 'EagerResult', 'result_from_tuple'] - -E_WOULDBLOCK = """\ -Never call result.get() within a task! -See http://docs.celeryq.org/en/latest/userguide/tasks.html\ -#task-synchronous-subtasks - -In Celery 3.2 this will result in an exception being -raised instead of just being a warning. -""" - - -def assert_will_not_block(): - if task_join_will_block(): - warnings.warn(RuntimeWarning(E_WOULDBLOCK)) - - -@contextmanager -def allow_join_result(): - reset_value = task_join_will_block() - _set_task_join_will_block(False) - try: - yield - finally: - _set_task_join_will_block(reset_value) - - -class ResultBase(object): - """Base class for all results""" - - #: Parent result (if part of a chain) - parent = None - - -class AsyncResult(ResultBase): - """Query task state. - - :param id: see :attr:`id`. - :keyword backend: see :attr:`backend`. - - """ - app = None - - #: Error raised for timeouts. - TimeoutError = TimeoutError - - #: The task's UUID. - id = None - - #: The task result backend to use. - backend = None - - def __init__(self, id, backend=None, task_name=None, - app=None, parent=None): - self.app = app_or_default(app or self.app) - self.id = id - self.backend = backend or self.app.backend - self.task_name = task_name - self.parent = parent - self._cache = None - - def as_tuple(self): - parent = self.parent - return (self.id, parent and parent.as_tuple()), None - serializable = as_tuple # XXX compat - - def forget(self): - """Forget about (and possibly remove the result of) this task.""" - self.backend.forget(self.id) - - def revoke(self, connection=None, terminate=False, signal=None, - wait=False, timeout=None): - """Send revoke signal to all workers. - - Any worker receiving the task, or having reserved the - task, *must* ignore it. - - :keyword terminate: Also terminate the process currently working - on the task (if any). - :keyword signal: Name of signal to send to process if terminate. - Default is TERM. - :keyword wait: Wait for replies from workers. Will wait for 1 second - by default or you can specify a custom ``timeout``. - :keyword timeout: Time in seconds to wait for replies if ``wait`` - enabled. - - """ - self.app.control.revoke(self.id, connection=connection, - terminate=terminate, signal=signal, - reply=wait, timeout=timeout) - - def get(self, timeout=None, propagate=True, interval=0.5, no_ack=True, - follow_parents=True): - """Wait until task is ready, and return its result. - - .. warning:: - - Waiting for tasks within a task may lead to deadlocks. - Please read :ref:`task-synchronous-subtasks`. - - :keyword timeout: How long to wait, in seconds, before the - operation times out. - :keyword propagate: Re-raise exception if the task failed. - :keyword interval: Time to wait (in seconds) before retrying to - retrieve the result. Note that this does not have any effect - when using the amqp result store backend, as it does not - use polling. - :keyword no_ack: Enable amqp no ack (automatically acknowledge - message). If this is :const:`False` then the message will - **not be acked**. - :keyword follow_parents: Reraise any exception raised by parent task. - - :raises celery.exceptions.TimeoutError: if `timeout` is not - :const:`None` and the result does not arrive within `timeout` - seconds. - - If the remote call raised an exception then that exception will - be re-raised. - - """ - assert_will_not_block() - on_interval = None - if follow_parents and propagate and self.parent: - on_interval = self._maybe_reraise_parent_error - on_interval() - - if self._cache: - if propagate: - self.maybe_reraise() - return self.result - - try: - return self.backend.wait_for( - self.id, timeout=timeout, - propagate=propagate, - interval=interval, - on_interval=on_interval, - no_ack=no_ack, - ) - finally: - self._get_task_meta() # update self._cache - wait = get # deprecated alias to :meth:`get`. - - def _maybe_reraise_parent_error(self): - for node in reversed(list(self._parents())): - node.maybe_reraise() - - def _parents(self): - node = self.parent - while node: - yield node - node = node.parent - - def collect(self, intermediate=False, **kwargs): - """Iterator, like :meth:`get` will wait for the task to complete, - but will also follow :class:`AsyncResult` and :class:`ResultSet` - returned by the task, yielding ``(result, value)`` tuples for each - result in the tree. - - An example would be having the following tasks: - - .. code-block:: python - - from celery import group - from proj.celery import app - - @app.task(trail=True) - def A(how_many): - return group(B.s(i) for i in range(how_many))() - - @app.task(trail=True) - def B(i): - return pow2.delay(i) - - @app.task(trail=True) - def pow2(i): - return i ** 2 - - Note that the ``trail`` option must be enabled - so that the list of children is stored in ``result.children``. - This is the default but enabled explicitly for illustration. - - Calling :meth:`collect` would return: - - .. code-block:: python - - >>> from celery.result import ResultBase - >>> from proj.tasks import A - - >>> result = A.delay(10) - >>> [v for v in result.collect() - ... if not isinstance(v, (ResultBase, tuple))] - [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] - - """ - for _, R in self.iterdeps(intermediate=intermediate): - yield R, R.get(**kwargs) - - def get_leaf(self): - value = None - for _, R in self.iterdeps(): - value = R.get() - return value - - def iterdeps(self, intermediate=False): - stack = deque([(None, self)]) - - while stack: - parent, node = stack.popleft() - yield parent, node - if node.ready(): - stack.extend((node, child) for child in node.children or []) - else: - if not intermediate: - raise IncompleteStream() - - def ready(self): - """Returns :const:`True` if the task has been executed. - - If the task is still running, pending, or is waiting - for retry then :const:`False` is returned. - - """ - return self.state in self.backend.READY_STATES - - def successful(self): - """Returns :const:`True` if the task executed successfully.""" - return self.state == states.SUCCESS - - def failed(self): - """Returns :const:`True` if the task failed.""" - return self.state == states.FAILURE - - def maybe_reraise(self): - if self.state in states.PROPAGATE_STATES: - raise self.result - - def build_graph(self, intermediate=False, formatter=None): - graph = DependencyGraph( - formatter=formatter or GraphFormatter(root=self.id, shape='oval'), - ) - for parent, node in self.iterdeps(intermediate=intermediate): - graph.add_arc(node) - if parent: - graph.add_edge(parent, node) - return graph - - def __str__(self): - """`str(self) -> self.id`""" - return str(self.id) - - def __hash__(self): - """`hash(self) -> hash(self.id)`""" - return hash(self.id) - - def __repr__(self): - return '<{0}: {1}>'.format(type(self).__name__, self.id) - - def __eq__(self, other): - if isinstance(other, AsyncResult): - return other.id == self.id - elif isinstance(other, string_t): - return other == self.id - return NotImplemented - - def __ne__(self, other): - return not self.__eq__(other) - - def __copy__(self): - return self.__class__( - self.id, self.backend, self.task_name, self.app, self.parent, - ) - - def __reduce__(self): - return self.__class__, self.__reduce_args__() - - def __reduce_args__(self): - return self.id, self.backend, self.task_name, None, self.parent - - def __del__(self): - self._cache = None - - @cached_property - def graph(self): - return self.build_graph() - - @property - def supports_native_join(self): - return self.backend.supports_native_join - - @property - def children(self): - return self._get_task_meta().get('children') - - def _get_task_meta(self): - if self._cache is None: - meta = self.backend.get_task_meta(self.id) - if meta: - state = meta['status'] - if state == states.SUCCESS or state in states.PROPAGATE_STATES: - self._set_cache(meta) - return self._set_cache(meta) - return meta - return self._cache - - def _set_cache(self, d): - state, children = d['status'], d.get('children') - if state in states.EXCEPTION_STATES: - d['result'] = self.backend.exception_to_python(d['result']) - if children: - d['children'] = [ - result_from_tuple(child, self.app) for child in children - ] - self._cache = d - return d - - @property - def result(self): - """When the task has been executed, this contains the return value. - If the task raised an exception, this will be the exception - instance.""" - return self._get_task_meta()['result'] - info = result - - @property - def traceback(self): - """Get the traceback of a failed task.""" - return self._get_task_meta().get('traceback') - - @property - def state(self): - """The tasks current state. - - Possible values includes: - - *PENDING* - - The task is waiting for execution. - - *STARTED* - - The task has been started. - - *RETRY* - - The task is to be retried, possibly because of failure. - - *FAILURE* - - The task raised an exception, or has exceeded the retry limit. - The :attr:`result` attribute then contains the - exception raised by the task. - - *SUCCESS* - - The task executed successfully. The :attr:`result` attribute - then contains the tasks return value. - - """ - return self._get_task_meta()['status'] - status = state - - @property - def task_id(self): - """compat alias to :attr:`id`""" - return self.id - - @task_id.setter # noqa - def task_id(self, id): - self.id = id -BaseAsyncResult = AsyncResult # for backwards compatibility. - - -class ResultSet(ResultBase): - """Working with more than one result. - - :param results: List of result instances. - - """ - app = None - - #: List of results in in the set. - results = None - - def __init__(self, results, app=None, **kwargs): - self.app = app_or_default(app or self.app) - self.results = results - - def add(self, result): - """Add :class:`AsyncResult` as a new member of the set. - - Does nothing if the result is already a member. - - """ - if result not in self.results: - self.results.append(result) - - def remove(self, result): - """Remove result from the set; it must be a member. - - :raises KeyError: if the result is not a member. - - """ - if isinstance(result, string_t): - result = self.app.AsyncResult(result) - try: - self.results.remove(result) - except ValueError: - raise KeyError(result) - - def discard(self, result): - """Remove result from the set if it is a member. - - If it is not a member, do nothing. - - """ - try: - self.remove(result) - except KeyError: - pass - - def update(self, results): - """Update set with the union of itself and an iterable with - results.""" - self.results.extend(r for r in results if r not in self.results) - - def clear(self): - """Remove all results from this set.""" - self.results[:] = [] # don't create new list. - - def successful(self): - """Was all of the tasks successful? - - :returns: :const:`True` if all of the tasks finished - successfully (i.e. did not raise an exception). - - """ - return all(result.successful() for result in self.results) - - def failed(self): - """Did any of the tasks fail? - - :returns: :const:`True` if one of the tasks failed. - (i.e., raised an exception) - - """ - return any(result.failed() for result in self.results) - - def maybe_reraise(self): - for result in self.results: - result.maybe_reraise() - - def waiting(self): - """Are any of the tasks incomplete? - - :returns: :const:`True` if one of the tasks are still - waiting for execution. - - """ - return any(not result.ready() for result in self.results) - - def ready(self): - """Did all of the tasks complete? (either by success of failure). - - :returns: :const:`True` if all of the tasks has been - executed. - - """ - return all(result.ready() for result in self.results) - - def completed_count(self): - """Task completion count. - - :returns: the number of tasks completed. - - """ - return sum(int(result.successful()) for result in self.results) - - def forget(self): - """Forget about (and possible remove the result of) all the tasks.""" - for result in self.results: - result.forget() - - def revoke(self, connection=None, terminate=False, signal=None, - wait=False, timeout=None): - """Send revoke signal to all workers for all tasks in the set. - - :keyword terminate: Also terminate the process currently working - on the task (if any). - :keyword signal: Name of signal to send to process if terminate. - Default is TERM. - :keyword wait: Wait for replies from worker. Will wait for 1 second - by default or you can specify a custom ``timeout``. - :keyword timeout: Time in seconds to wait for replies if ``wait`` - enabled. - - """ - self.app.control.revoke([r.id for r in self.results], - connection=connection, timeout=timeout, - terminate=terminate, signal=signal, reply=wait) - - def __iter__(self): - return iter(self.results) - - def __getitem__(self, index): - """`res[i] -> res.results[i]`""" - return self.results[index] - - @deprecated('3.2', '3.3') - def iterate(self, timeout=None, propagate=True, interval=0.5): - """Deprecated method, use :meth:`get` with a callback argument.""" - elapsed = 0.0 - results = OrderedDict((result.id, copy(result)) - for result in self.results) - - while results: - removed = set() - for task_id, result in items(results): - if result.ready(): - yield result.get(timeout=timeout and timeout - elapsed, - propagate=propagate) - removed.add(task_id) - else: - if result.backend.subpolling_interval: - time.sleep(result.backend.subpolling_interval) - for task_id in removed: - results.pop(task_id, None) - time.sleep(interval) - elapsed += interval - if timeout and elapsed >= timeout: - raise TimeoutError('The operation timed out') - - def get(self, timeout=None, propagate=True, interval=0.5, - callback=None, no_ack=True): - """See :meth:`join` - - This is here for API compatibility with :class:`AsyncResult`, - in addition it uses :meth:`join_native` if available for the - current result backend. - - """ - return (self.join_native if self.supports_native_join else self.join)( - timeout=timeout, propagate=propagate, - interval=interval, callback=callback, no_ack=no_ack) - - def join(self, timeout=None, propagate=True, interval=0.5, - callback=None, no_ack=True): - """Gathers the results of all tasks as a list in order. - - .. note:: - - This can be an expensive operation for result store - backends that must resort to polling (e.g. database). - - You should consider using :meth:`join_native` if your backend - supports it. - - .. warning:: - - Waiting for tasks within a task may lead to deadlocks. - Please see :ref:`task-synchronous-subtasks`. - - :keyword timeout: The number of seconds to wait for results before - the operation times out. - - :keyword propagate: If any of the tasks raises an exception, the - exception will be re-raised. - - :keyword interval: Time to wait (in seconds) before retrying to - retrieve a result from the set. Note that this - does not have any effect when using the amqp - result store backend, as it does not use polling. - - :keyword callback: Optional callback to be called for every result - received. Must have signature ``(task_id, value)`` - No results will be returned by this function if - a callback is specified. The order of results - is also arbitrary when a callback is used. - To get access to the result object for a particular - id you will have to generate an index first: - ``index = {r.id: r for r in gres.results.values()}`` - Or you can create new result objects on the fly: - ``result = app.AsyncResult(task_id)`` (both will - take advantage of the backend cache anyway). - - :keyword no_ack: Automatic message acknowledgement (Note that if this - is set to :const:`False` then the messages *will not be - acknowledged*). - - :raises celery.exceptions.TimeoutError: if ``timeout`` is not - :const:`None` and the operation takes longer than ``timeout`` - seconds. - - """ - assert_will_not_block() - time_start = monotonic() - remaining = None - - results = [] - for result in self.results: - remaining = None - if timeout: - remaining = timeout - (monotonic() - time_start) - if remaining <= 0.0: - raise TimeoutError('join operation timed out') - value = result.get( - timeout=remaining, propagate=propagate, - interval=interval, no_ack=no_ack, - ) - if callback: - callback(result.id, value) - else: - results.append(value) - return results - - def iter_native(self, timeout=None, interval=0.5, no_ack=True): - """Backend optimized version of :meth:`iterate`. - - .. versionadded:: 2.2 - - Note that this does not support collecting the results - for different task types using different backends. - - This is currently only supported by the amqp, Redis and cache - result backends. - - """ - results = self.results - if not results: - return iter([]) - return results[0].backend.get_many( - set(r.id for r in results), - timeout=timeout, interval=interval, no_ack=no_ack, - ) - - def join_native(self, timeout=None, propagate=True, - interval=0.5, callback=None, no_ack=True): - """Backend optimized version of :meth:`join`. - - .. versionadded:: 2.2 - - Note that this does not support collecting the results - for different task types using different backends. - - This is currently only supported by the amqp, Redis and cache - result backends. - - """ - assert_will_not_block() - order_index = None if callback else dict( - (result.id, i) for i, result in enumerate(self.results) - ) - acc = None if callback else [None for _ in range(len(self))] - for task_id, meta in self.iter_native(timeout, interval, no_ack): - value = meta['result'] - if propagate and meta['status'] in states.PROPAGATE_STATES: - raise value - if callback: - callback(task_id, value) - else: - acc[order_index[task_id]] = value - return acc - - def _failed_join_report(self): - return (res for res in self.results - if res.backend.is_cached(res.id) and - res.state in states.PROPAGATE_STATES) - - def __len__(self): - return len(self.results) - - def __eq__(self, other): - if isinstance(other, ResultSet): - return other.results == self.results - return NotImplemented - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return '<{0}: [{1}]>'.format(type(self).__name__, - ', '.join(r.id for r in self.results)) - - @property - def subtasks(self): - """Deprecated alias to :attr:`results`.""" - return self.results - - @property - def supports_native_join(self): - return self.results[0].supports_native_join - - -class GroupResult(ResultSet): - """Like :class:`ResultSet`, but with an associated id. - - This type is returned by :class:`~celery.group`, and the - deprecated TaskSet, meth:`~celery.task.TaskSet.apply_async` method. - - It enables inspection of the tasks state and return values as - a single entity. - - :param id: The id of the group. - :param results: List of result instances. - - """ - - #: The UUID of the group. - id = None - - #: List/iterator of results in the group - results = None - - def __init__(self, id=None, results=None, **kwargs): - self.id = id - ResultSet.__init__(self, results, **kwargs) - - def save(self, backend=None): - """Save group-result for later retrieval using :meth:`restore`. - - Example:: - - >>> def save_and_restore(result): - ... result.save() - ... result = GroupResult.restore(result.id) - - """ - return (backend or self.app.backend).save_group(self.id, self) - - def delete(self, backend=None): - """Remove this result if it was previously saved.""" - (backend or self.app.backend).delete_group(self.id) - - def __reduce__(self): - return self.__class__, self.__reduce_args__() - - def __reduce_args__(self): - return self.id, self.results - - def __eq__(self, other): - if isinstance(other, GroupResult): - return other.id == self.id and other.results == self.results - return NotImplemented - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return '<{0}: {1} [{2}]>'.format(type(self).__name__, self.id, - ', '.join(r.id for r in self.results)) - - def as_tuple(self): - return self.id, [r.as_tuple() for r in self.results] - serializable = as_tuple # XXX compat - - @property - def children(self): - return self.results - - @classmethod - def restore(self, id, backend=None): - """Restore previously saved group result.""" - return ( - backend or (self.app.backend if self.app else current_app.backend) - ).restore_group(id) - - -class TaskSetResult(GroupResult): - """Deprecated version of :class:`GroupResult`""" - - def __init__(self, taskset_id, results=None, **kwargs): - # XXX supports the taskset_id kwarg. - # XXX previously the "results" arg was named "subtasks". - if 'subtasks' in kwargs: - results = kwargs['subtasks'] - GroupResult.__init__(self, taskset_id, results, **kwargs) - - def itersubtasks(self): - """Deprecated. Use ``iter(self.results)`` instead.""" - return iter(self.results) - - @property - def total(self): - """Deprecated: Use ``len(r)``.""" - return len(self) - - @property - def taskset_id(self): - """compat alias to :attr:`self.id`""" - return self.id - - @taskset_id.setter # noqa - def taskset_id(self, id): - self.id = id - - -class EagerResult(AsyncResult): - """Result that we know has already been executed.""" - task_name = None - - def __init__(self, id, ret_value, state, traceback=None): - self.id = id - self._result = ret_value - self._state = state - self._traceback = traceback - - def _get_task_meta(self): - return {'task_id': self.id, 'result': self._result, 'status': - self._state, 'traceback': self._traceback} - - def __reduce__(self): - return self.__class__, self.__reduce_args__() - - def __reduce_args__(self): - return (self.id, self._result, self._state, self._traceback) - - def __copy__(self): - cls, args = self.__reduce__() - return cls(*args) - - def ready(self): - return True - - def get(self, timeout=None, propagate=True, **kwargs): - if self.successful(): - return self.result - elif self.state in states.PROPAGATE_STATES: - if propagate: - raise self.result - return self.result - wait = get - - def forget(self): - pass - - def revoke(self, *args, **kwargs): - self._state = states.REVOKED - - def __repr__(self): - return '<EagerResult: {0.id}>'.format(self) - - @property - def result(self): - """The tasks return value""" - return self._result - - @property - def state(self): - """The tasks state.""" - return self._state - status = state - - @property - def traceback(self): - """The traceback if the task failed.""" - return self._traceback - - @property - def supports_native_join(self): - return False - - -def result_from_tuple(r, app=None): - # earlier backends may just pickle, so check if - # result is already prepared. - app = app_or_default(app) - Result = app.AsyncResult - if not isinstance(r, ResultBase): - res, nodes = r - if nodes: - return app.GroupResult( - res, [result_from_tuple(child, app) for child in nodes], - ) - # previously did not include parent - id, parent = res if isinstance(res, (list, tuple)) else (res, None) - if parent: - parent = result_from_tuple(parent, app) - return Result(id, parent=parent) - return r -from_serializable = result_from_tuple # XXX compat diff --git a/awx/lib/site-packages/celery/schedules.py b/awx/lib/site-packages/celery/schedules.py deleted file mode 100644 index 6424dfa042..0000000000 --- a/awx/lib/site-packages/celery/schedules.py +++ /dev/null @@ -1,593 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.schedules - ~~~~~~~~~~~~~~~~ - - Schedules define the intervals at which periodic tasks - should run. - -""" -from __future__ import absolute_import - -import numbers -import re - -from collections import namedtuple -from datetime import datetime, timedelta - -from kombu.utils import cached_property - -from . import current_app -from .five import range, string_t -from .utils import is_iterable -from .utils.timeutils import ( - timedelta_seconds, weekday, maybe_timedelta, remaining, - humanize_seconds, timezone, maybe_make_aware, ffwd -) -from .datastructures import AttributeDict - -__all__ = ['ParseException', 'schedule', 'crontab', 'crontab_parser', - 'maybe_schedule'] - -schedstate = namedtuple('schedstate', ('is_due', 'next')) - - -CRON_PATTERN_INVALID = """\ -Invalid crontab pattern. Valid range is {min}-{max}. \ -'{value}' was found.\ -""" - -CRON_INVALID_TYPE = """\ -Argument cronspec needs to be of any of the following types: \ -int, str, or an iterable type. {type!r} was given.\ -""" - -CRON_REPR = """\ -<crontab: {0._orig_minute} {0._orig_hour} {0._orig_day_of_week} \ -{0._orig_day_of_month} {0._orig_month_of_year} (m/h/d/dM/MY)>\ -""" - - -def cronfield(s): - return '*' if s is None else s - - -class ParseException(Exception): - """Raised by crontab_parser when the input can't be parsed.""" - - -class schedule(object): - """Schedule for periodic task. - - :param run_every: Interval in seconds (or a :class:`~datetime.timedelta`). - :param relative: If set to True the run time will be rounded to the - resolution of the interval. - :param nowfun: Function returning the current date and time - (class:`~datetime.datetime`). - :param app: Celery app instance. - - """ - relative = False - - def __init__(self, run_every=None, relative=False, nowfun=None, app=None): - self.run_every = maybe_timedelta(run_every) - self.relative = relative - self.nowfun = nowfun - self._app = app - - def now(self): - return (self.nowfun or self.app.now)() - - def remaining_estimate(self, last_run_at): - return remaining( - self.maybe_make_aware(last_run_at), self.run_every, - self.maybe_make_aware(self.now()), self.relative, - ) - - def is_due(self, last_run_at): - """Returns tuple of two items `(is_due, next_time_to_check)`, - where next time to check is in seconds. - - e.g. - - * `(True, 20)`, means the task should be run now, and the next - time to check is in 20 seconds. - - * `(False, 12.3)`, means the task is not due, but that the scheduler - should check again in 12.3 seconds. - - The next time to check is used to save energy/cpu cycles, - it does not need to be accurate but will influence the precision - of your schedule. You must also keep in mind - the value of :setting:`CELERYBEAT_MAX_LOOP_INTERVAL`, - which decides the maximum number of seconds the scheduler can - sleep between re-checking the periodic task intervals. So if you - have a task that changes schedule at runtime then your next_run_at - check will decide how long it will take before a change to the - schedule takes effect. The max loop interval takes precendence - over the next check at value returned. - - .. admonition:: Scheduler max interval variance - - The default max loop interval may vary for different schedulers. - For the default scheduler the value is 5 minutes, but for e.g. - the django-celery database scheduler the value is 5 seconds. - - """ - last_run_at = self.maybe_make_aware(last_run_at) - rem_delta = self.remaining_estimate(last_run_at) - remaining_s = timedelta_seconds(rem_delta) - if remaining_s == 0: - return schedstate(is_due=True, next=self.seconds) - return schedstate(is_due=False, next=remaining_s) - - def maybe_make_aware(self, dt): - if self.utc_enabled: - return maybe_make_aware(dt, self.tz) - return dt - - def __repr__(self): - return '<freq: {0.human_seconds}>'.format(self) - - def __eq__(self, other): - if isinstance(other, schedule): - return self.run_every == other.run_every - return self.run_every == other - - def __ne__(self, other): - return not self.__eq__(other) - - def __reduce__(self): - return self.__class__, (self.run_every, self.relative, self.nowfun) - - @property - def seconds(self): - return timedelta_seconds(self.run_every) - - @property - def human_seconds(self): - return humanize_seconds(self.seconds) - - @property - def app(self): - return self._app or current_app._get_current_object() - - @app.setter # noqa - def app(self, app): - self._app = app - - @cached_property - def tz(self): - return self.app.timezone - - @cached_property - def utc_enabled(self): - return self.app.conf.CELERY_ENABLE_UTC - - def to_local(self, dt): - if not self.utc_enabled: - return timezone.to_local_fallback(dt) - return dt - - -class crontab_parser(object): - """Parser for crontab expressions. Any expression of the form 'groups' - (see BNF grammar below) is accepted and expanded to a set of numbers. - These numbers represent the units of time that the crontab needs to - run on:: - - digit :: '0'..'9' - dow :: 'a'..'z' - number :: digit+ | dow+ - steps :: number - range :: number ( '-' number ) ? - numspec :: '*' | range - expr :: numspec ( '/' steps ) ? - groups :: expr ( ',' expr ) * - - The parser is a general purpose one, useful for parsing hours, minutes and - day_of_week expressions. Example usage:: - - >>> minutes = crontab_parser(60).parse('*/15') - [0, 15, 30, 45] - >>> hours = crontab_parser(24).parse('*/4') - [0, 4, 8, 12, 16, 20] - >>> day_of_week = crontab_parser(7).parse('*') - [0, 1, 2, 3, 4, 5, 6] - - It can also parse day_of_month and month_of_year expressions if initialized - with an minimum of 1. Example usage:: - - >>> days_of_month = crontab_parser(31, 1).parse('*/3') - [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31] - >>> months_of_year = crontab_parser(12, 1).parse('*/2') - [1, 3, 5, 7, 9, 11] - >>> months_of_year = crontab_parser(12, 1).parse('2-12/2') - [2, 4, 6, 8, 10, 12] - - The maximum possible expanded value returned is found by the formula:: - - max_ + min_ - 1 - - """ - ParseException = ParseException - - _range = r'(\w+?)-(\w+)' - _steps = r'/(\w+)?' - _star = r'\*' - - def __init__(self, max_=60, min_=0): - self.max_ = max_ - self.min_ = min_ - self.pats = ( - (re.compile(self._range + self._steps), self._range_steps), - (re.compile(self._range), self._expand_range), - (re.compile(self._star + self._steps), self._star_steps), - (re.compile('^' + self._star + '$'), self._expand_star), - ) - - def parse(self, spec): - acc = set() - for part in spec.split(','): - if not part: - raise self.ParseException('empty part') - acc |= set(self._parse_part(part)) - return acc - - def _parse_part(self, part): - for regex, handler in self.pats: - m = regex.match(part) - if m: - return handler(m.groups()) - return self._expand_range((part, )) - - def _expand_range(self, toks): - fr = self._expand_number(toks[0]) - if len(toks) > 1: - to = self._expand_number(toks[1]) - if to < fr: # Wrap around max_ if necessary - return (list(range(fr, self.min_ + self.max_)) + - list(range(self.min_, to + 1))) - return list(range(fr, to + 1)) - return [fr] - - def _range_steps(self, toks): - if len(toks) != 3 or not toks[2]: - raise self.ParseException('empty filter') - return self._expand_range(toks[:2])[::int(toks[2])] - - def _star_steps(self, toks): - if not toks or not toks[0]: - raise self.ParseException('empty filter') - return self._expand_star()[::int(toks[0])] - - def _expand_star(self, *args): - return list(range(self.min_, self.max_ + self.min_)) - - def _expand_number(self, s): - if isinstance(s, string_t) and s[0] == '-': - raise self.ParseException('negative numbers not supported') - try: - i = int(s) - except ValueError: - try: - i = weekday(s) - except KeyError: - raise ValueError('Invalid weekday literal {0!r}.'.format(s)) - - max_val = self.min_ + self.max_ - 1 - if i > max_val: - raise ValueError( - 'Invalid end range: {0} > {1}.'.format(i, max_val)) - if i < self.min_: - raise ValueError( - 'Invalid beginning range: {0} < {1}.'.format(i, self.min_)) - - return i - - -class crontab(schedule): - """A crontab can be used as the `run_every` value of a - :class:`PeriodicTask` to add cron-like scheduling. - - Like a :manpage:`cron` job, you can specify units of time of when - you would like the task to execute. It is a reasonably complete - implementation of cron's features, so it should provide a fair - degree of scheduling needs. - - You can specify a minute, an hour, a day of the week, a day of the - month, and/or a month in the year in any of the following formats: - - .. attribute:: minute - - - A (list of) integers from 0-59 that represent the minutes of - an hour of when execution should occur; or - - A string representing a crontab pattern. This may get pretty - advanced, like `minute='*/15'` (for every quarter) or - `minute='1,13,30-45,50-59/2'`. - - .. attribute:: hour - - - A (list of) integers from 0-23 that represent the hours of - a day of when execution should occur; or - - A string representing a crontab pattern. This may get pretty - advanced, like `hour='*/3'` (for every three hours) or - `hour='0,8-17/2'` (at midnight, and every two hours during - office hours). - - .. attribute:: day_of_week - - - A (list of) integers from 0-6, where Sunday = 0 and Saturday = - 6, that represent the days of a week that execution should - occur. - - A string representing a crontab pattern. This may get pretty - advanced, like `day_of_week='mon-fri'` (for weekdays only). - (Beware that `day_of_week='*/2'` does not literally mean - 'every two days', but 'every day that is divisible by two'!) - - .. attribute:: day_of_month - - - A (list of) integers from 1-31 that represents the days of the - month that execution should occur. - - A string representing a crontab pattern. This may get pretty - advanced, such as `day_of_month='2-30/3'` (for every even - numbered day) or `day_of_month='1-7,15-21'` (for the first and - third weeks of the month). - - .. attribute:: month_of_year - - - A (list of) integers from 1-12 that represents the months of - the year during which execution can occur. - - A string representing a crontab pattern. This may get pretty - advanced, such as `month_of_year='*/3'` (for the first month - of every quarter) or `month_of_year='2-12/2'` (for every even - numbered month). - - .. attribute:: nowfun - - Function returning the current date and time - (:class:`~datetime.datetime`). - - .. attribute:: app - - The Celery app instance. - - It is important to realize that any day on which execution should - occur must be represented by entries in all three of the day and - month attributes. For example, if `day_of_week` is 0 and `day_of_month` - is every seventh day, only months that begin on Sunday and are also - in the `month_of_year` attribute will have execution events. Or, - `day_of_week` is 1 and `day_of_month` is '1-7,15-21' means every - first and third monday of every month present in `month_of_year`. - - """ - - def __init__(self, minute='*', hour='*', day_of_week='*', - day_of_month='*', month_of_year='*', nowfun=None, app=None): - self._orig_minute = cronfield(minute) - self._orig_hour = cronfield(hour) - self._orig_day_of_week = cronfield(day_of_week) - self._orig_day_of_month = cronfield(day_of_month) - self._orig_month_of_year = cronfield(month_of_year) - self.hour = self._expand_cronspec(hour, 24) - self.minute = self._expand_cronspec(minute, 60) - self.day_of_week = self._expand_cronspec(day_of_week, 7) - self.day_of_month = self._expand_cronspec(day_of_month, 31, 1) - self.month_of_year = self._expand_cronspec(month_of_year, 12, 1) - self.nowfun = nowfun - self._app = app - - @staticmethod - def _expand_cronspec(cronspec, max_, min_=0): - """Takes the given cronspec argument in one of the forms:: - - int (like 7) - str (like '3-5,*/15', '*', or 'monday') - set (like set([0,15,30,45])) - list (like [8-17]) - - And convert it to an (expanded) set representing all time unit - values on which the crontab triggers. Only in case of the base - type being 'str', parsing occurs. (It is fast and - happens only once for each crontab instance, so there is no - significant performance overhead involved.) - - For the other base types, merely Python type conversions happen. - - The argument `max_` is needed to determine the expansion of '*' - and ranges. - The argument `min_` is needed to determine the expansion of '*' - and ranges for 1-based cronspecs, such as day of month or month - of year. The default is sufficient for minute, hour, and day of - week. - - """ - if isinstance(cronspec, numbers.Integral): - result = set([cronspec]) - elif isinstance(cronspec, string_t): - result = crontab_parser(max_, min_).parse(cronspec) - elif isinstance(cronspec, set): - result = cronspec - elif is_iterable(cronspec): - result = set(cronspec) - else: - raise TypeError(CRON_INVALID_TYPE.format(type=type(cronspec))) - - # assure the result does not preceed the min or exceed the max - for number in result: - if number >= max_ + min_ or number < min_: - raise ValueError(CRON_PATTERN_INVALID.format( - min=min_, max=max_ - 1 + min_, value=number)) - return result - - def _delta_to_next(self, last_run_at, next_hour, next_minute): - """ - Takes a datetime of last run, next minute and hour, and - returns a relativedelta for the next scheduled day and time. - Only called when day_of_month and/or month_of_year cronspec - is specified to further limit scheduled task execution. - """ - from bisect import bisect, bisect_left - - datedata = AttributeDict(year=last_run_at.year) - days_of_month = sorted(self.day_of_month) - months_of_year = sorted(self.month_of_year) - - def day_out_of_range(year, month, day): - try: - datetime(year=year, month=month, day=day) - except ValueError: - return True - return False - - def roll_over(): - while 1: - flag = (datedata.dom == len(days_of_month) or - day_out_of_range(datedata.year, - months_of_year[datedata.moy], - days_of_month[datedata.dom]) or - (self.maybe_make_aware(datetime(datedata.year, - months_of_year[datedata.moy], - days_of_month[datedata.dom])) < last_run_at)) - - if flag: - datedata.dom = 0 - datedata.moy += 1 - if datedata.moy == len(months_of_year): - datedata.moy = 0 - datedata.year += 1 - else: - break - - if last_run_at.month in self.month_of_year: - datedata.dom = bisect(days_of_month, last_run_at.day) - datedata.moy = bisect_left(months_of_year, last_run_at.month) - else: - datedata.dom = 0 - datedata.moy = bisect(months_of_year, last_run_at.month) - if datedata.moy == len(months_of_year): - datedata.moy = 0 - roll_over() - - while 1: - th = datetime(year=datedata.year, - month=months_of_year[datedata.moy], - day=days_of_month[datedata.dom]) - if th.isoweekday() % 7 in self.day_of_week: - break - datedata.dom += 1 - roll_over() - - return ffwd(year=datedata.year, - month=months_of_year[datedata.moy], - day=days_of_month[datedata.dom], - hour=next_hour, - minute=next_minute, - second=0, - microsecond=0) - - def now(self): - return (self.nowfun or self.app.now)() - - def __repr__(self): - return CRON_REPR.format(self) - - def __reduce__(self): - return (self.__class__, (self._orig_minute, - self._orig_hour, - self._orig_day_of_week, - self._orig_day_of_month, - self._orig_month_of_year), None) - - def remaining_delta(self, last_run_at, tz=None, ffwd=ffwd): - tz = tz or self.tz - last_run_at = self.maybe_make_aware(last_run_at) - now = self.maybe_make_aware(self.now()) - dow_num = last_run_at.isoweekday() % 7 # Sunday is day 0, not day 7 - - execute_this_date = (last_run_at.month in self.month_of_year and - last_run_at.day in self.day_of_month and - dow_num in self.day_of_week) - - execute_this_hour = (execute_this_date and - last_run_at.day == now.day and - last_run_at.month == now.month and - last_run_at.year == now.year and - last_run_at.hour in self.hour and - last_run_at.minute < max(self.minute)) - - if execute_this_hour: - next_minute = min(minute for minute in self.minute - if minute > last_run_at.minute) - delta = ffwd(minute=next_minute, second=0, microsecond=0) - else: - next_minute = min(self.minute) - execute_today = (execute_this_date and - last_run_at.hour < max(self.hour)) - - if execute_today: - next_hour = min(hour for hour in self.hour - if hour > last_run_at.hour) - delta = ffwd(hour=next_hour, minute=next_minute, - second=0, microsecond=0) - else: - next_hour = min(self.hour) - all_dom_moy = (self._orig_day_of_month == '*' and - self._orig_month_of_year == '*') - if all_dom_moy: - next_day = min([day for day in self.day_of_week - if day > dow_num] or self.day_of_week) - add_week = next_day == dow_num - - delta = ffwd(weeks=add_week and 1 or 0, - weekday=(next_day - 1) % 7, - hour=next_hour, - minute=next_minute, - second=0, - microsecond=0) - else: - delta = self._delta_to_next(last_run_at, - next_hour, next_minute) - return self.to_local(last_run_at), delta, self.to_local(now) - - def remaining_estimate(self, last_run_at, ffwd=ffwd): - """Returns when the periodic task should run next as a timedelta.""" - return remaining(*self.remaining_delta(last_run_at, ffwd=ffwd)) - - def is_due(self, last_run_at): - """Returns tuple of two items `(is_due, next_time_to_run)`, - where next time to run is in seconds. - - See :meth:`celery.schedules.schedule.is_due` for more information. - - """ - rem_delta = self.remaining_estimate(last_run_at) - rem = timedelta_seconds(rem_delta) - due = rem == 0 - if due: - rem_delta = self.remaining_estimate(self.now()) - rem = timedelta_seconds(rem_delta) - return schedstate(due, rem) - - def __eq__(self, other): - if isinstance(other, crontab): - return (other.month_of_year == self.month_of_year and - other.day_of_month == self.day_of_month and - other.day_of_week == self.day_of_week and - other.hour == self.hour and - other.minute == self.minute) - return NotImplemented - - def __ne__(self, other): - return not self.__eq__(other) - - -def maybe_schedule(s, relative=False, app=None): - if s is not None: - if isinstance(s, numbers.Integral): - s = timedelta(seconds=s) - if isinstance(s, timedelta): - return schedule(s, relative, app=app) - else: - s.app = app - return s diff --git a/awx/lib/site-packages/celery/security/__init__.py b/awx/lib/site-packages/celery/security/__init__.py deleted file mode 100644 index 352d400cfc..0000000000 --- a/awx/lib/site-packages/celery/security/__init__.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.security - ~~~~~~~~~~~~~~~ - - Module implementing the signing message serializer. - -""" -from __future__ import absolute_import - -from kombu.serialization import ( - registry, disable_insecure_serializers as _disable_insecure_serializers, -) - -from celery.exceptions import ImproperlyConfigured - -from .serialization import register_auth - -SSL_NOT_INSTALLED = """\ -You need to install the pyOpenSSL library to use the auth serializer. -Please install by: - - $ pip install pyOpenSSL -""" - -SETTING_MISSING = """\ -Sorry, but you have to configure the - * CELERY_SECURITY_KEY - * CELERY_SECURITY_CERTIFICATE, and the - * CELERY_SECURITY_CERT_STORE -configuration settings to use the auth serializer. - -Please see the configuration reference for more information. -""" - -__all__ = ['setup_security'] - - -def setup_security(allowed_serializers=None, key=None, cert=None, store=None, - digest='sha1', serializer='json', app=None): - """See :meth:`@Celery.setup_security`.""" - if app is None: - from celery import current_app - app = current_app._get_current_object() - - _disable_insecure_serializers(allowed_serializers) - - conf = app.conf - if conf.CELERY_TASK_SERIALIZER != 'auth': - return - - try: - from OpenSSL import crypto # noqa - except ImportError: - raise ImproperlyConfigured(SSL_NOT_INSTALLED) - - key = key or conf.CELERY_SECURITY_KEY - cert = cert or conf.CELERY_SECURITY_CERTIFICATE - store = store or conf.CELERY_SECURITY_CERT_STORE - - if not (key and cert and store): - raise ImproperlyConfigured(SETTING_MISSING) - - with open(key) as kf: - with open(cert) as cf: - register_auth(kf.read(), cf.read(), store, digest, serializer) - registry._set_default_serializer('auth') - - -def disable_untrusted_serializers(whitelist=None): - _disable_insecure_serializers(allowed=whitelist) diff --git a/awx/lib/site-packages/celery/security/certificate.py b/awx/lib/site-packages/celery/security/certificate.py deleted file mode 100644 index c1c520c27d..0000000000 --- a/awx/lib/site-packages/celery/security/certificate.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.security.certificate - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - X.509 certificates. - -""" -from __future__ import absolute_import - -import glob -import os - -from kombu.utils.encoding import bytes_to_str - -from celery.exceptions import SecurityError -from celery.five import values - -from .utils import crypto, reraise_errors - -__all__ = ['Certificate', 'CertStore', 'FSCertStore'] - - -class Certificate(object): - """X.509 certificate.""" - - def __init__(self, cert): - assert crypto is not None - with reraise_errors('Invalid certificate: {0!r}'): - self._cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert) - - def has_expired(self): - """Check if the certificate has expired.""" - return self._cert.has_expired() - - def get_serial_number(self): - """Return the serial number in the certificate.""" - return bytes_to_str(self._cert.get_serial_number()) - - def get_issuer(self): - """Return issuer (CA) as a string""" - return ' '.join(bytes_to_str(x[1]) for x in - self._cert.get_issuer().get_components()) - - def get_id(self): - """Serial number/issuer pair uniquely identifies a certificate""" - return '{0} {1}'.format(self.get_issuer(), self.get_serial_number()) - - def verify(self, data, signature, digest): - """Verifies the signature for string containing data.""" - with reraise_errors('Bad signature: {0!r}'): - crypto.verify(self._cert, signature, data, digest) - - -class CertStore(object): - """Base class for certificate stores""" - - def __init__(self): - self._certs = {} - - def itercerts(self): - """an iterator over the certificates""" - for c in values(self._certs): - yield c - - def __getitem__(self, id): - """get certificate by id""" - try: - return self._certs[bytes_to_str(id)] - except KeyError: - raise SecurityError('Unknown certificate: {0!r}'.format(id)) - - def add_cert(self, cert): - cert_id = bytes_to_str(cert.get_id()) - if cert_id in self._certs: - raise SecurityError('Duplicate certificate: {0!r}'.format(id)) - self._certs[cert_id] = cert - - -class FSCertStore(CertStore): - """File system certificate store""" - - def __init__(self, path): - CertStore.__init__(self) - if os.path.isdir(path): - path = os.path.join(path, '*') - for p in glob.glob(path): - with open(p) as f: - cert = Certificate(f.read()) - if cert.has_expired(): - raise SecurityError( - 'Expired certificate: {0!r}'.format(cert.get_id())) - self.add_cert(cert) diff --git a/awx/lib/site-packages/celery/security/key.py b/awx/lib/site-packages/celery/security/key.py deleted file mode 100644 index a5c2620427..0000000000 --- a/awx/lib/site-packages/celery/security/key.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.security.key - ~~~~~~~~~~~~~~~~~~~ - - Private key for the security serializer. - -""" -from __future__ import absolute_import - -from kombu.utils.encoding import ensure_bytes - -from .utils import crypto, reraise_errors - -__all__ = ['PrivateKey'] - - -class PrivateKey(object): - - def __init__(self, key): - with reraise_errors('Invalid private key: {0!r}'): - self._key = crypto.load_privatekey(crypto.FILETYPE_PEM, key) - - def sign(self, data, digest): - """sign string containing data.""" - with reraise_errors('Unable to sign data: {0!r}'): - return crypto.sign(self._key, ensure_bytes(data), digest) diff --git a/awx/lib/site-packages/celery/security/serialization.py b/awx/lib/site-packages/celery/security/serialization.py deleted file mode 100644 index f1cab29148..0000000000 --- a/awx/lib/site-packages/celery/security/serialization.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.security.serialization - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Secure serializer. - -""" -from __future__ import absolute_import - -import base64 - -from kombu.serialization import registry, dumps, loads -from kombu.utils.encoding import bytes_to_str, str_to_bytes, ensure_bytes - -from .certificate import Certificate, FSCertStore -from .key import PrivateKey -from .utils import reraise_errors - -__all__ = ['SecureSerializer', 'register_auth'] - - -def b64encode(s): - return bytes_to_str(base64.b64encode(str_to_bytes(s))) - - -def b64decode(s): - return base64.b64decode(str_to_bytes(s)) - - -class SecureSerializer(object): - - def __init__(self, key=None, cert=None, cert_store=None, - digest='sha1', serializer='json'): - self._key = key - self._cert = cert - self._cert_store = cert_store - self._digest = digest - self._serializer = serializer - - def serialize(self, data): - """serialize data structure into string""" - assert self._key is not None - assert self._cert is not None - with reraise_errors('Unable to serialize: {0!r}', (Exception, )): - content_type, content_encoding, body = dumps( - bytes_to_str(data), serializer=self._serializer) - # What we sign is the serialized body, not the body itself. - # this way the receiver doesn't have to decode the contents - # to verify the signature (and thus avoiding potential flaws - # in the decoding step). - body = ensure_bytes(body) - return self._pack(body, content_type, content_encoding, - signature=self._key.sign(body, self._digest), - signer=self._cert.get_id()) - - def deserialize(self, data): - """deserialize data structure from string""" - assert self._cert_store is not None - with reraise_errors('Unable to deserialize: {0!r}', (Exception, )): - payload = self._unpack(data) - signature, signer, body = (payload['signature'], - payload['signer'], - payload['body']) - self._cert_store[signer].verify(body, signature, self._digest) - return loads(bytes_to_str(body), payload['content_type'], - payload['content_encoding'], force=True) - - def _pack(self, body, content_type, content_encoding, signer, signature, - sep=str_to_bytes('\x00\x01')): - fields = sep.join( - ensure_bytes(s) for s in [signer, signature, content_type, - content_encoding, body] - ) - return b64encode(fields) - - def _unpack(self, payload, sep=str_to_bytes('\x00\x01')): - raw_payload = b64decode(ensure_bytes(payload)) - first_sep = raw_payload.find(sep) - - signer = raw_payload[:first_sep] - signer_cert = self._cert_store[signer] - - sig_len = signer_cert._cert.get_pubkey().bits() >> 3 - signature = raw_payload[ - first_sep + len(sep):first_sep + len(sep) + sig_len - ] - end_of_sig = first_sep + len(sep) + sig_len+len(sep) - - v = raw_payload[end_of_sig:].split(sep) - - return { - 'signer': signer, - 'signature': signature, - 'content_type': bytes_to_str(v[0]), - 'content_encoding': bytes_to_str(v[1]), - 'body': bytes_to_str(v[2]), - } - - -def register_auth(key=None, cert=None, store=None, digest='sha1', - serializer='json'): - """register security serializer""" - s = SecureSerializer(key and PrivateKey(key), - cert and Certificate(cert), - store and FSCertStore(store), - digest=digest, serializer=serializer) - registry.register('auth', s.serialize, s.deserialize, - content_type='application/data', - content_encoding='utf-8') diff --git a/awx/lib/site-packages/celery/security/utils.py b/awx/lib/site-packages/celery/security/utils.py deleted file mode 100644 index d184d0b4c9..0000000000 --- a/awx/lib/site-packages/celery/security/utils.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.security.utils - ~~~~~~~~~~~~~~~~~~~~~ - - Utilities used by the message signing serializer. - -""" -from __future__ import absolute_import - -import sys - -from contextlib import contextmanager - -from celery.exceptions import SecurityError -from celery.five import reraise - -try: - from OpenSSL import crypto -except ImportError: # pragma: no cover - crypto = None # noqa - -__all__ = ['reraise_errors'] - - -@contextmanager -def reraise_errors(msg='{0!r}', errors=None): - assert crypto is not None - errors = (crypto.Error, ) if errors is None else errors - try: - yield - except errors as exc: - reraise(SecurityError, - SecurityError(msg.format(exc)), - sys.exc_info()[2]) diff --git a/awx/lib/site-packages/celery/signals.py b/awx/lib/site-packages/celery/signals.py deleted file mode 100644 index 2091830cb2..0000000000 --- a/awx/lib/site-packages/celery/signals.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.signals - ~~~~~~~~~~~~~~ - - This module defines the signals (Observer pattern) sent by - both workers and clients. - - Functions can be connected to these signals, and connected - functions are called whenever a signal is called. - - See :ref:`signals` for more information. - -""" -from __future__ import absolute_import -from .utils.dispatch import Signal - -__all__ = ['before_task_publish', 'after_task_publish', - 'task_prerun', 'task_postrun', 'task_success', - 'task_retry', 'task_failure', 'task_revoked', 'celeryd_init', - 'celeryd_after_setup', 'worker_init', 'worker_process_init', - 'worker_ready', 'worker_shutdown', 'setup_logging', - 'after_setup_logger', 'after_setup_task_logger', - 'beat_init', 'beat_embedded_init', 'eventlet_pool_started', - 'eventlet_pool_preshutdown', 'eventlet_pool_postshutdown', - 'eventlet_pool_apply'] - -before_task_publish = Signal(providing_args=[ - 'body', 'exchange', 'routing_key', 'headers', 'properties', - 'declare', 'retry_policy', -]) -after_task_publish = Signal(providing_args=[ - 'body', 'exchange', 'routing_key', -]) -#: Deprecated, use after_task_publish instead. -task_sent = Signal(providing_args=[ - 'task_id', 'task', 'args', 'kwargs', 'eta', 'taskset', -]) -task_prerun = Signal(providing_args=['task_id', 'task', 'args', 'kwargs']) -task_postrun = Signal(providing_args=[ - 'task_id', 'task', 'args', 'kwargs', 'retval', -]) -task_success = Signal(providing_args=['result']) -task_retry = Signal(providing_args=[ - 'request', 'reason', 'einfo', -]) -task_failure = Signal(providing_args=[ - 'task_id', 'exception', 'args', 'kwargs', 'traceback', 'einfo', -]) -task_revoked = Signal(providing_args=[ - 'request', 'terminated', 'signum', 'expired', -]) -celeryd_init = Signal(providing_args=['instance', 'conf', 'options']) -celeryd_after_setup = Signal(providing_args=['instance', 'conf']) -import_modules = Signal(providing_args=[]) -worker_init = Signal(providing_args=[]) -worker_process_init = Signal(providing_args=[]) -worker_process_shutdown = Signal(providing_args=[]) -worker_ready = Signal(providing_args=[]) -worker_shutdown = Signal(providing_args=[]) -setup_logging = Signal(providing_args=[ - 'loglevel', 'logfile', 'format', 'colorize', -]) -after_setup_logger = Signal(providing_args=[ - 'logger', 'loglevel', 'logfile', 'format', 'colorize', -]) -after_setup_task_logger = Signal(providing_args=[ - 'logger', 'loglevel', 'logfile', 'format', 'colorize', -]) -beat_init = Signal(providing_args=[]) -beat_embedded_init = Signal(providing_args=[]) -eventlet_pool_started = Signal(providing_args=[]) -eventlet_pool_preshutdown = Signal(providing_args=[]) -eventlet_pool_postshutdown = Signal(providing_args=[]) -eventlet_pool_apply = Signal(providing_args=['target', 'args', 'kwargs']) -user_preload_options = Signal(providing_args=['app', 'options']) diff --git a/awx/lib/site-packages/celery/states.py b/awx/lib/site-packages/celery/states.py deleted file mode 100644 index 665a57baf1..0000000000 --- a/awx/lib/site-packages/celery/states.py +++ /dev/null @@ -1,153 +0,0 @@ -# -*- coding: utf-8 -*- -""" -celery.states -============= - -Built-in task states. - -.. _states: - -States ------- - -See :ref:`task-states`. - -.. _statesets: - -Sets ----- - -.. state:: READY_STATES - -READY_STATES -~~~~~~~~~~~~ - -Set of states meaning the task result is ready (has been executed). - -.. state:: UNREADY_STATES - -UNREADY_STATES -~~~~~~~~~~~~~~ - -Set of states meaning the task result is not ready (has not been executed). - -.. state:: EXCEPTION_STATES - -EXCEPTION_STATES -~~~~~~~~~~~~~~~~ - -Set of states meaning the task returned an exception. - -.. state:: PROPAGATE_STATES - -PROPAGATE_STATES -~~~~~~~~~~~~~~~~ - -Set of exception states that should propagate exceptions to the user. - -.. state:: ALL_STATES - -ALL_STATES -~~~~~~~~~~ - -Set of all possible states. - - -Misc. ------ - -""" -from __future__ import absolute_import - -__all__ = ['PENDING', 'RECEIVED', 'STARTED', 'SUCCESS', 'FAILURE', - 'REVOKED', 'RETRY', 'IGNORED', 'READY_STATES', 'UNREADY_STATES', - 'EXCEPTION_STATES', 'PROPAGATE_STATES', 'precedence', 'state'] - -#: State precedence. -#: None represents the precedence of an unknown state. -#: Lower index means higher precedence. -PRECEDENCE = ['SUCCESS', - 'FAILURE', - None, - 'REVOKED', - 'STARTED', - 'RECEIVED', - 'RETRY', - 'PENDING'] - -#: Hash lookup of PRECEDENCE to index -PRECEDENCE_LOOKUP = dict(zip(PRECEDENCE, range(0, len(PRECEDENCE)))) -NONE_PRECEDENCE = PRECEDENCE_LOOKUP[None] - - -def precedence(state): - """Get the precedence index for state. - - Lower index means higher precedence. - - """ - try: - return PRECEDENCE_LOOKUP[state] - except KeyError: - return NONE_PRECEDENCE - - -class state(str): - """State is a subclass of :class:`str`, implementing comparison - methods adhering to state precedence rules:: - - >>> from celery.states import state, PENDING, SUCCESS - - >>> state(PENDING) < state(SUCCESS) - True - - Any custom state is considered to be lower than :state:`FAILURE` and - :state:`SUCCESS`, but higher than any of the other built-in states:: - - >>> state('PROGRESS') > state(STARTED) - True - - >>> state('PROGRESS') > state('SUCCESS') - False - - """ - - def compare(self, other, fun): - return fun(precedence(self), precedence(other)) - - def __gt__(self, other): - return precedence(self) < precedence(other) - - def __ge__(self, other): - return precedence(self) <= precedence(other) - - def __lt__(self, other): - return precedence(self) > precedence(other) - - def __le__(self, other): - return precedence(self) >= precedence(other) - -#: Task state is unknown (assumed pending since you know the id). -PENDING = 'PENDING' -#: Task was received by a worker. -RECEIVED = 'RECEIVED' -#: Task was started by a worker (:setting:`CELERY_TRACK_STARTED`). -STARTED = 'STARTED' -#: Task succeeded -SUCCESS = 'SUCCESS' -#: Task failed -FAILURE = 'FAILURE' -#: Task was revoked. -REVOKED = 'REVOKED' -#: Task is waiting for retry. -RETRY = 'RETRY' -IGNORED = 'IGNORED' -REJECTED = 'REJECTED' - -READY_STATES = frozenset([SUCCESS, FAILURE, REVOKED]) -UNREADY_STATES = frozenset([PENDING, RECEIVED, STARTED, RETRY]) -EXCEPTION_STATES = frozenset([RETRY, FAILURE, REVOKED]) -PROPAGATE_STATES = frozenset([FAILURE, REVOKED]) - -ALL_STATES = frozenset([PENDING, RECEIVED, STARTED, - SUCCESS, FAILURE, RETRY, REVOKED]) diff --git a/awx/lib/site-packages/celery/task/__init__.py b/awx/lib/site-packages/celery/task/__init__.py deleted file mode 100644 index f8326e887c..0000000000 --- a/awx/lib/site-packages/celery/task/__init__.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.task - ~~~~~~~~~~~ - - This is the old task module, it should not be used anymore, - import from the main 'celery' module instead. - If you're looking for the decorator implementation then that's in - ``celery.app.base.Celery.task``. - -""" -from __future__ import absolute_import - -from celery._state import current_app, current_task as current -from celery.five import MagicModule, recreate_module -from celery.local import Proxy - -__all__ = [ - 'BaseTask', 'Task', 'PeriodicTask', 'task', 'periodic_task', - 'group', 'chord', 'subtask', 'TaskSet', -] - - -STATICA_HACK = True -globals()['kcah_acitats'[::-1].upper()] = False -if STATICA_HACK: # pragma: no cover - # This is never executed, but tricks static analyzers (PyDev, PyCharm, - # pylint, etc.) into knowing the types of these symbols, and what - # they contain. - from celery.canvas import group, chord, subtask - from .base import BaseTask, Task, PeriodicTask, task, periodic_task - from .sets import TaskSet - - -class module(MagicModule): - - def __call__(self, *args, **kwargs): - return self.task(*args, **kwargs) - - -old_module, new_module = recreate_module( # pragma: no cover - __name__, - by_module={ - 'celery.task.base': ['BaseTask', 'Task', 'PeriodicTask', - 'task', 'periodic_task'], - 'celery.canvas': ['group', 'chord', 'subtask'], - 'celery.task.sets': ['TaskSet'], - }, - base=module, - __package__='celery.task', - __file__=__file__, - __path__=__path__, - __doc__=__doc__, - current=current, - discard_all=Proxy(lambda: current_app.control.purge), - backend_cleanup=Proxy( - lambda: current_app.tasks['celery.backend_cleanup'] - ), -) diff --git a/awx/lib/site-packages/celery/task/base.py b/awx/lib/site-packages/celery/task/base.py deleted file mode 100644 index 9d466b57c4..0000000000 --- a/awx/lib/site-packages/celery/task/base.py +++ /dev/null @@ -1,179 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.task.base - ~~~~~~~~~~~~~~~~ - - The task implementation has been moved to :mod:`celery.app.task`. - - This contains the backward compatible Task class used in the old API, - and shouldn't be used in new applications. - -""" -from __future__ import absolute_import - -from kombu import Exchange - -from celery import current_app -from celery.app.task import Context, TaskType, Task as BaseTask # noqa -from celery.five import class_property, reclassmethod -from celery.schedules import maybe_schedule -from celery.utils.log import get_task_logger - -__all__ = ['Task', 'PeriodicTask', 'task'] - -#: list of methods that must be classmethods in the old API. -_COMPAT_CLASSMETHODS = ( - 'delay', 'apply_async', 'retry', 'apply', 'subtask_from_request', - 'AsyncResult', 'subtask', '_get_request', '_get_exec_options', -) - - -class Task(BaseTask): - """Deprecated Task base class. - - Modern applications should use :class:`celery.Task` instead. - - """ - abstract = True - __bound__ = False - __v2_compat__ = True - - #- Deprecated compat. attributes -: - - queue = None - routing_key = None - exchange = None - exchange_type = None - delivery_mode = None - mandatory = False # XXX deprecated - immediate = False # XXX deprecated - priority = None - type = 'regular' - disable_error_emails = False - accept_magic_kwargs = False - - from_config = BaseTask.from_config + ( - ('exchange_type', 'CELERY_DEFAULT_EXCHANGE_TYPE'), - ('delivery_mode', 'CELERY_DEFAULT_DELIVERY_MODE'), - ) - - # In old Celery the @task decorator didn't exist, so one would create - # classes instead and use them directly (e.g. MyTask.apply_async()). - # the use of classmethods was a hack so that it was not necessary - # to instantiate the class before using it, but it has only - # given us pain (like all magic). - for name in _COMPAT_CLASSMETHODS: - locals()[name] = reclassmethod(getattr(BaseTask, name)) - - @class_property - def request(cls): - return cls._get_request() - - @class_property - def backend(cls): - if cls._backend is None: - return cls.app.backend - return cls._backend - - @backend.setter - def backend(cls, value): # noqa - cls._backend = value - - @classmethod - def get_logger(self, **kwargs): - return get_task_logger(self.name) - - @classmethod - def establish_connection(self): - """Deprecated method used to get a broker connection. - - Should be replaced with :meth:`@Celery.connection` - instead, or by acquiring connections from the connection pool: - - .. code-block:: python - - # using the connection pool - with celery.pool.acquire(block=True) as conn: - ... - - # establish fresh connection - with celery.connection() as conn: - ... - """ - return self._get_app().connection() - - def get_publisher(self, connection=None, exchange=None, - exchange_type=None, **options): - """Deprecated method to get the task publisher (now called producer). - - Should be replaced with :class:`@amqp.TaskProducer`: - - .. code-block:: python - - with celery.connection() as conn: - with celery.amqp.TaskProducer(conn) as prod: - my_task.apply_async(producer=prod) - - """ - exchange = self.exchange if exchange is None else exchange - if exchange_type is None: - exchange_type = self.exchange_type - connection = connection or self.establish_connection() - return self._get_app().amqp.TaskProducer( - connection, - exchange=exchange and Exchange(exchange, exchange_type), - routing_key=self.routing_key, **options - ) - - @classmethod - def get_consumer(self, connection=None, queues=None, **kwargs): - """Deprecated method used to get consumer for the queue - this task is sent to. - - Should be replaced with :class:`@amqp.TaskConsumer` instead: - - """ - Q = self._get_app().amqp - connection = connection or self.establish_connection() - if queues is None: - queues = Q.queues[self.queue] if self.queue else Q.default_queue - return Q.TaskConsumer(connection, queues, **kwargs) - - -class PeriodicTask(Task): - """A periodic task is a task that adds itself to the - :setting:`CELERYBEAT_SCHEDULE` setting.""" - abstract = True - ignore_result = True - relative = False - options = None - compat = True - - def __init__(self): - if not hasattr(self, 'run_every'): - raise NotImplementedError( - 'Periodic tasks must have a run_every attribute') - self.run_every = maybe_schedule(self.run_every, self.relative) - super(PeriodicTask, self).__init__() - - @classmethod - def on_bound(cls, app): - app.conf.CELERYBEAT_SCHEDULE[cls.name] = { - 'task': cls.name, - 'schedule': cls.run_every, - 'args': (), - 'kwargs': {}, - 'options': cls.options or {}, - 'relative': cls.relative, - } - - -def task(*args, **kwargs): - """Deprecated decorator, please use :func:`celery.task`.""" - return current_app.task(*args, **dict({'accept_magic_kwargs': False, - 'base': Task}, **kwargs)) - - -def periodic_task(*args, **options): - """Deprecated decorator, please use :setting:`CELERYBEAT_SCHEDULE`.""" - return task(**dict({'base': PeriodicTask}, **options)) diff --git a/awx/lib/site-packages/celery/task/http.py b/awx/lib/site-packages/celery/task/http.py deleted file mode 100644 index e170ec3a59..0000000000 --- a/awx/lib/site-packages/celery/task/http.py +++ /dev/null @@ -1,220 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.task.http - ~~~~~~~~~~~~~~~~ - - Webhook task implementation. - -""" -from __future__ import absolute_import - -import anyjson -import sys - -try: - from urllib.parse import parse_qsl, urlencode, urlparse # Py3 -except ImportError: # pragma: no cover - from urllib import urlencode # noqa - from urlparse import urlparse, parse_qsl # noqa - -from celery import shared_task, __version__ as celery_version -from celery.five import items, reraise -from celery.utils.log import get_task_logger - -__all__ = ['InvalidResponseError', 'RemoteExecuteError', 'UnknownStatusError', - 'HttpDispatch', 'dispatch', 'URL'] - -GET_METHODS = frozenset(['GET', 'HEAD']) -logger = get_task_logger(__name__) - - -if sys.version_info[0] == 3: # pragma: no cover - - from urllib.request import Request, urlopen - - def utf8dict(tup): - if not isinstance(tup, dict): - return dict(tup) - return tup - -else: - - from urllib2 import Request, urlopen # noqa - - def utf8dict(tup): # noqa - """With a dict's items() tuple return a new dict with any utf-8 - keys/values encoded.""" - return dict( - (k.encode('utf-8'), - v.encode('utf-8') if isinstance(v, unicode) else v) # noqa - for k, v in tup) - - -class InvalidResponseError(Exception): - """The remote server gave an invalid response.""" - - -class RemoteExecuteError(Exception): - """The remote task gave a custom error.""" - - -class UnknownStatusError(InvalidResponseError): - """The remote server gave an unknown status.""" - - -def extract_response(raw_response, loads=anyjson.loads): - """Extract the response text from a raw JSON response.""" - if not raw_response: - raise InvalidResponseError('Empty response') - try: - payload = loads(raw_response) - except ValueError as exc: - reraise(InvalidResponseError, InvalidResponseError( - str(exc)), sys.exc_info()[2]) - - status = payload['status'] - if status == 'success': - return payload['retval'] - elif status == 'failure': - raise RemoteExecuteError(payload.get('reason')) - else: - raise UnknownStatusError(str(status)) - - -class MutableURL(object): - """Object wrapping a Uniform Resource Locator. - - Supports editing the query parameter list. - You can convert the object back to a string, the query will be - properly urlencoded. - - Examples - - >>> url = URL('http://www.google.com:6580/foo/bar?x=3&y=4#foo') - >>> url.query - {'x': '3', 'y': '4'} - >>> str(url) - 'http://www.google.com:6580/foo/bar?y=4&x=3#foo' - >>> url.query['x'] = 10 - >>> url.query.update({'George': 'Costanza'}) - >>> str(url) - 'http://www.google.com:6580/foo/bar?y=4&x=10&George=Costanza#foo' - - """ - def __init__(self, url): - self.parts = urlparse(url) - self.query = dict(parse_qsl(self.parts[4])) - - def __str__(self): - scheme, netloc, path, params, query, fragment = self.parts - query = urlencode(utf8dict(items(self.query))) - components = [scheme + '://', netloc, path or '/', - ';{0}'.format(params) if params else '', - '?{0}'.format(query) if query else '', - '#{0}'.format(fragment) if fragment else ''] - return ''.join(c for c in components if c) - - def __repr__(self): - return '<{0}: {1}>'.format(type(self).__name__, self) - - -class HttpDispatch(object): - """Make task HTTP request and collect the task result. - - :param url: The URL to request. - :param method: HTTP method used. Currently supported methods are `GET` - and `POST`. - :param task_kwargs: Task keyword arguments. - :param logger: Logger used for user/system feedback. - - """ - user_agent = 'celery/{version}'.format(version=celery_version) - timeout = 5 - - def __init__(self, url, method, task_kwargs, **kwargs): - self.url = url - self.method = method - self.task_kwargs = task_kwargs - self.logger = kwargs.get('logger') or logger - - def make_request(self, url, method, params): - """Perform HTTP request and return the response.""" - request = Request(url, params) - for key, val in items(self.http_headers): - request.add_header(key, val) - response = urlopen(request) # user catches errors. - return response.read() - - def dispatch(self): - """Dispatch callback and return result.""" - url = MutableURL(self.url) - params = None - if self.method in GET_METHODS: - url.query.update(self.task_kwargs) - else: - params = urlencode(utf8dict(items(self.task_kwargs))) - raw_response = self.make_request(str(url), self.method, params) - return extract_response(raw_response) - - @property - def http_headers(self): - headers = {'User-Agent': self.user_agent} - return headers - - -@shared_task(name='celery.http_dispatch', bind=True, - url=None, method=None, accept_magic_kwargs=False) -def dispatch(self, url=None, method='GET', **kwargs): - """Task dispatching to an URL. - - :keyword url: The URL location of the HTTP callback task. - :keyword method: Method to use when dispatching the callback. Usually - `GET` or `POST`. - :keyword \*\*kwargs: Keyword arguments to pass on to the HTTP callback. - - .. attribute:: url - - If this is set, this is used as the default URL for requests. - Default is to require the user of the task to supply the url as an - argument, as this attribute is intended for subclasses. - - .. attribute:: method - - If this is set, this is the default method used for requests. - Default is to require the user of the task to supply the method as an - argument, as this attribute is intended for subclasses. - - """ - return HttpDispatch( - url or self.url, method or self.method, kwargs, - ).dispatch() - - -class URL(MutableURL): - """HTTP Callback URL - - Supports requesting an URL asynchronously. - - :param url: URL to request. - :keyword dispatcher: Class used to dispatch the request. - By default this is :func:`dispatch`. - - """ - dispatcher = None - - def __init__(self, url, dispatcher=None, app=None): - super(URL, self).__init__(url) - self.app = app - self.dispatcher = dispatcher or self.dispatcher - if self.dispatcher is None: - # Get default dispatcher - self.dispatcher = ( - self.app.tasks['celery.http_dispatch'] if self.app - else dispatch - ) - - def get_async(self, **kwargs): - return self.dispatcher.delay(str(self), 'GET', **kwargs) - - def post_async(self, **kwargs): - return self.dispatcher.delay(str(self), 'POST', **kwargs) diff --git a/awx/lib/site-packages/celery/task/sets.py b/awx/lib/site-packages/celery/task/sets.py deleted file mode 100644 index e277b796dc..0000000000 --- a/awx/lib/site-packages/celery/task/sets.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.task.sets - ~~~~~~~~~~~~~~~~ - - Old ``group`` implementation, this module should - not be used anymore use :func:`celery.group` instead. - -""" -from __future__ import absolute_import - -from celery._state import get_current_worker_task -from celery.app import app_or_default -from celery.canvas import maybe_signature # noqa -from celery.utils import uuid, warn_deprecated - -from celery.canvas import subtask # noqa - -warn_deprecated( - 'celery.task.sets and TaskSet', removal='4.0', - alternative="""\ -Please use "group" instead (see the Canvas section in the userguide)\ -""") - - -class TaskSet(list): - """A task containing several subtasks, making it possible - to track how many, or when all of the tasks have been completed. - - :param tasks: A list of :class:`subtask` instances. - - Example:: - - >>> from myproj.tasks import refresh_feed - - >>> urls = ('http://cnn.com/rss', 'http://bbc.co.uk/rss') - >>> s = TaskSet(refresh_feed.s(url) for url in urls) - >>> taskset_result = s.apply_async() - >>> list_of_return_values = taskset_result.join() # *expensive* - - """ - app = None - - def __init__(self, tasks=None, app=None, Publisher=None): - self.app = app_or_default(app or self.app) - super(TaskSet, self).__init__( - maybe_signature(t, app=self.app) for t in tasks or [] - ) - self.Publisher = Publisher or self.app.amqp.TaskProducer - self.total = len(self) # XXX compat - - def apply_async(self, connection=None, publisher=None, taskset_id=None): - """Apply TaskSet.""" - app = self.app - - if app.conf.CELERY_ALWAYS_EAGER: - return self.apply(taskset_id=taskset_id) - - with app.connection_or_acquire(connection) as conn: - setid = taskset_id or uuid() - pub = publisher or self.Publisher(conn) - results = self._async_results(setid, pub) - - result = app.TaskSetResult(setid, results) - parent = get_current_worker_task() - if parent: - parent.add_trail(result) - return result - - def _async_results(self, taskset_id, publisher): - return [task.apply_async(taskset_id=taskset_id, publisher=publisher) - for task in self] - - def apply(self, taskset_id=None): - """Applies the TaskSet locally by blocking until all tasks return.""" - setid = taskset_id or uuid() - return self.app.TaskSetResult(setid, self._sync_results(setid)) - - def _sync_results(self, taskset_id): - return [task.apply(taskset_id=taskset_id) for task in self] - - @property - def tasks(self): - return self - - @tasks.setter # noqa - def tasks(self, tasks): - self[:] = tasks diff --git a/awx/lib/site-packages/celery/task/trace.py b/awx/lib/site-packages/celery/task/trace.py deleted file mode 100644 index 5e5f5a8e9e..0000000000 --- a/awx/lib/site-packages/celery/task/trace.py +++ /dev/null @@ -1,12 +0,0 @@ -"""This module has moved to celery.app.trace.""" -from __future__ import absolute_import - -import sys - -from celery.utils import warn_deprecated - -warn_deprecated('celery.task.trace', removal='3.2', - alternative='Please use celery.app.trace instead.') - -from celery.app import trace -sys.modules[__name__] = trace diff --git a/awx/lib/site-packages/celery/tests/__init__.py b/awx/lib/site-packages/celery/tests/__init__.py deleted file mode 100644 index 966787270b..0000000000 --- a/awx/lib/site-packages/celery/tests/__init__.py +++ /dev/null @@ -1,87 +0,0 @@ -from __future__ import absolute_import - -import logging -import os -import sys -import warnings - -from importlib import import_module - -try: - WindowsError = WindowsError # noqa -except NameError: - - class WindowsError(Exception): - pass - - -def setup(): - os.environ.update( - # warn if config module not found - C_WNOCONF='yes', - KOMBU_DISABLE_LIMIT_PROTECTION='yes', - ) - - if os.environ.get('COVER_ALL_MODULES') or '--with-coverage' in sys.argv: - from warnings import catch_warnings - with catch_warnings(record=True): - import_all_modules() - warnings.resetwarnings() - from celery.tests.case import Trap - from celery._state import set_default_app - set_default_app(Trap()) - - -def teardown(): - # Don't want SUBDEBUG log messages at finalization. - try: - from multiprocessing.util import get_logger - except ImportError: - pass - else: - get_logger().setLevel(logging.WARNING) - - # Make sure test database is removed. - import os - if os.path.exists('test.db'): - try: - os.remove('test.db') - except WindowsError: - pass - - # Make sure there are no remaining threads at shutdown. - import threading - remaining_threads = [thread for thread in threading.enumerate() - if thread.getName() != 'MainThread'] - if remaining_threads: - sys.stderr.write( - '\n\n**WARNING**: Remaining threads at teardown: %r...\n' % ( - remaining_threads)) - - -def find_distribution_modules(name=__name__, file=__file__): - current_dist_depth = len(name.split('.')) - 1 - current_dist = os.path.join(os.path.dirname(file), - *([os.pardir] * current_dist_depth)) - abs = os.path.abspath(current_dist) - dist_name = os.path.basename(abs) - - for dirpath, dirnames, filenames in os.walk(abs): - package = (dist_name + dirpath[len(abs):]).replace('/', '.') - if '__init__.py' in filenames: - yield package - for filename in filenames: - if filename.endswith('.py') and filename != '__init__.py': - yield '.'.join([package, filename])[:-3] - - -def import_all_modules(name=__name__, file=__file__, - skip=('celery.decorators', - 'celery.contrib.batches', - 'celery.task')): - for module in find_distribution_modules(name, file): - if not module.startswith(skip): - try: - import_module(module) - except ImportError: - pass diff --git a/awx/lib/site-packages/celery/tests/app/__init__.py b/awx/lib/site-packages/celery/tests/app/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/app/test_amqp.py b/awx/lib/site-packages/celery/tests/app/test_amqp.py deleted file mode 100644 index efb398ac6b..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_amqp.py +++ /dev/null @@ -1,228 +0,0 @@ -from __future__ import absolute_import - -import datetime - -import pytz - -from kombu import Exchange, Queue - -from celery.app.amqp import Queues, TaskPublisher -from celery.five import keys -from celery.tests.case import AppCase, Mock - - -class test_TaskProducer(AppCase): - - def test__exit__(self): - publisher = self.app.amqp.TaskProducer(self.app.connection()) - publisher.release = Mock() - with publisher: - pass - publisher.release.assert_called_with() - - def test_declare(self): - publisher = self.app.amqp.TaskProducer(self.app.connection()) - publisher.exchange.name = 'foo' - publisher.declare() - publisher.exchange.name = None - publisher.declare() - - def test_retry_policy(self): - prod = self.app.amqp.TaskProducer(Mock()) - prod.channel.connection.client.declared_entities = set() - prod.publish_task('tasks.add', (2, 2), {}, - retry_policy={'frobulate': 32.4}) - - def test_publish_no_retry(self): - prod = self.app.amqp.TaskProducer(Mock()) - prod.channel.connection.client.declared_entities = set() - prod.publish_task('tasks.add', (2, 2), {}, retry=False, chord=123) - self.assertFalse(prod.connection.ensure.call_count) - - def test_publish_custom_queue(self): - prod = self.app.amqp.TaskProducer(Mock()) - self.app.amqp.queues['some_queue'] = Queue( - 'xxx', Exchange('yyy'), 'zzz', - ) - prod.channel.connection.client.declared_entities = set() - prod.publish = Mock() - prod.publish_task('tasks.add', (8, 8), {}, retry=False, - queue='some_queue') - self.assertEqual(prod.publish.call_args[1]['exchange'], 'yyy') - self.assertEqual(prod.publish.call_args[1]['routing_key'], 'zzz') - - def test_publish_with_countdown(self): - prod = self.app.amqp.TaskProducer(Mock()) - prod.channel.connection.client.declared_entities = set() - prod.publish = Mock() - now = datetime.datetime(2013, 11, 26, 16, 48, 46) - prod.publish_task('tasks.add', (1, 1), {}, retry=False, - countdown=10, now=now) - self.assertEqual( - prod.publish.call_args[0][0]['eta'], - '2013-11-26T16:48:56+00:00', - ) - - def test_publish_with_countdown_and_timezone(self): - # use timezone with fixed offset to be sure it won't be changed - self.app.conf.CELERY_TIMEZONE = pytz.FixedOffset(120) - prod = self.app.amqp.TaskProducer(Mock()) - prod.channel.connection.client.declared_entities = set() - prod.publish = Mock() - now = datetime.datetime(2013, 11, 26, 16, 48, 46) - prod.publish_task('tasks.add', (2, 2), {}, retry=False, - countdown=20, now=now) - self.assertEqual( - prod.publish.call_args[0][0]['eta'], - '2013-11-26T18:49:06+02:00', - ) - - def test_event_dispatcher(self): - prod = self.app.amqp.TaskProducer(Mock()) - self.assertTrue(prod.event_dispatcher) - self.assertFalse(prod.event_dispatcher.enabled) - - -class test_TaskConsumer(AppCase): - - def test_accept_content(self): - with self.app.pool.acquire(block=True) as conn: - self.app.conf.CELERY_ACCEPT_CONTENT = ['application/json'] - self.assertEqual( - self.app.amqp.TaskConsumer(conn).accept, - set(['application/json']) - ) - self.assertEqual( - self.app.amqp.TaskConsumer(conn, accept=['json']).accept, - set(['application/json']), - ) - - -class test_compat_TaskPublisher(AppCase): - - def test_compat_exchange_is_string(self): - producer = TaskPublisher(exchange='foo', app=self.app) - self.assertIsInstance(producer.exchange, Exchange) - self.assertEqual(producer.exchange.name, 'foo') - self.assertEqual(producer.exchange.type, 'direct') - producer = TaskPublisher(exchange='foo', exchange_type='topic', - app=self.app) - self.assertEqual(producer.exchange.type, 'topic') - - def test_compat_exchange_is_Exchange(self): - producer = TaskPublisher(exchange=Exchange('foo'), app=self.app) - self.assertEqual(producer.exchange.name, 'foo') - - -class test_PublisherPool(AppCase): - - def test_setup_nolimit(self): - self.app.conf.BROKER_POOL_LIMIT = None - try: - delattr(self.app, '_pool') - except AttributeError: - pass - self.app.amqp._producer_pool = None - pool = self.app.amqp.producer_pool - self.assertEqual(pool.limit, self.app.pool.limit) - self.assertFalse(pool._resource.queue) - - r1 = pool.acquire() - r2 = pool.acquire() - r1.release() - r2.release() - r1 = pool.acquire() - r2 = pool.acquire() - - def test_setup(self): - self.app.conf.BROKER_POOL_LIMIT = 2 - try: - delattr(self.app, '_pool') - except AttributeError: - pass - self.app.amqp._producer_pool = None - pool = self.app.amqp.producer_pool - self.assertEqual(pool.limit, self.app.pool.limit) - self.assertTrue(pool._resource.queue) - - p1 = r1 = pool.acquire() - p2 = r2 = pool.acquire() - r1.release() - r2.release() - r1 = pool.acquire() - r2 = pool.acquire() - self.assertIs(p2, r1) - self.assertIs(p1, r2) - r1.release() - r2.release() - - -class test_Queues(AppCase): - - def test_queues_format(self): - self.app.amqp.queues._consume_from = {} - self.assertEqual(self.app.amqp.queues.format(), '') - - def test_with_defaults(self): - self.assertEqual(Queues(None), {}) - - def test_add(self): - q = Queues() - q.add('foo', exchange='ex', routing_key='rk') - self.assertIn('foo', q) - self.assertIsInstance(q['foo'], Queue) - self.assertEqual(q['foo'].routing_key, 'rk') - - def test_with_ha_policy(self): - qn = Queues(ha_policy=None, create_missing=False) - qn.add('xyz') - self.assertIsNone(qn['xyz'].queue_arguments) - - qn.add('xyx', queue_arguments={'x-foo': 'bar'}) - self.assertEqual(qn['xyx'].queue_arguments, {'x-foo': 'bar'}) - - q = Queues(ha_policy='all', create_missing=False) - q.add(Queue('foo')) - self.assertEqual(q['foo'].queue_arguments, {'x-ha-policy': 'all'}) - - qq = Queue('xyx2', queue_arguments={'x-foo': 'bari'}) - q.add(qq) - self.assertEqual(q['xyx2'].queue_arguments, { - 'x-ha-policy': 'all', - 'x-foo': 'bari', - }) - - q2 = Queues(ha_policy=['A', 'B', 'C'], create_missing=False) - q2.add(Queue('foo')) - self.assertEqual(q2['foo'].queue_arguments, { - 'x-ha-policy': 'nodes', - 'x-ha-policy-params': ['A', 'B', 'C'], - }) - - def test_select_add(self): - q = Queues() - q.select(['foo', 'bar']) - q.select_add('baz') - self.assertItemsEqual(keys(q._consume_from), ['foo', 'bar', 'baz']) - - def test_deselect(self): - q = Queues() - q.select(['foo', 'bar']) - q.deselect('bar') - self.assertItemsEqual(keys(q._consume_from), ['foo']) - - def test_with_ha_policy_compat(self): - q = Queues(ha_policy='all') - q.add('bar') - self.assertEqual(q['bar'].queue_arguments, {'x-ha-policy': 'all'}) - - def test_add_default_exchange(self): - ex = Exchange('fff', 'fanout') - q = Queues(default_exchange=ex) - q.add(Queue('foo')) - self.assertEqual(q['foo'].exchange, ex) - - def test_alias(self): - q = Queues() - q.add(Queue('foo', alias='barfoo')) - self.assertIs(q['barfoo'], q['foo']) diff --git a/awx/lib/site-packages/celery/tests/app/test_annotations.py b/awx/lib/site-packages/celery/tests/app/test_annotations.py deleted file mode 100644 index 559f5cb010..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_annotations.py +++ /dev/null @@ -1,56 +0,0 @@ -from __future__ import absolute_import - -from celery.app.annotations import MapAnnotation, prepare -from celery.utils.imports import qualname - -from celery.tests.case import AppCase - - -class MyAnnotation(object): - foo = 65 - - -class AnnotationCase(AppCase): - - def setup(self): - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - @self.app.task(shared=False) - def mul(x, y): - return x * y - self.mul = mul - - -class test_MapAnnotation(AnnotationCase): - - def test_annotate(self): - x = MapAnnotation({self.add.name: {'foo': 1}}) - self.assertDictEqual(x.annotate(self.add), {'foo': 1}) - self.assertIsNone(x.annotate(self.mul)) - - def test_annotate_any(self): - x = MapAnnotation({'*': {'foo': 2}}) - self.assertDictEqual(x.annotate_any(), {'foo': 2}) - - x = MapAnnotation() - self.assertIsNone(x.annotate_any()) - - -class test_prepare(AnnotationCase): - - def test_dict_to_MapAnnotation(self): - x = prepare({self.add.name: {'foo': 3}}) - self.assertIsInstance(x[0], MapAnnotation) - - def test_returns_list(self): - self.assertListEqual(prepare(1), [1]) - self.assertListEqual(prepare([1]), [1]) - self.assertListEqual(prepare((1, )), [1]) - self.assertEqual(prepare(None), ()) - - def test_evalutes_qualnames(self): - self.assertEqual(prepare(qualname(MyAnnotation))[0]().foo, 65) - self.assertEqual(prepare([qualname(MyAnnotation)])[0]().foo, 65) diff --git a/awx/lib/site-packages/celery/tests/app/test_app.py b/awx/lib/site-packages/celery/tests/app/test_app.py deleted file mode 100644 index 113dedae14..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_app.py +++ /dev/null @@ -1,720 +0,0 @@ -from __future__ import absolute_import - -import gc -import os -import itertools - -from copy import deepcopy -from pickle import loads, dumps - -from amqp import promise -from kombu import Exchange - -from celery import shared_task, current_app -from celery import app as _app -from celery import _state -from celery.app import base as _appbase -from celery.app import defaults -from celery.exceptions import ImproperlyConfigured -from celery.five import items -from celery.loaders.base import BaseLoader -from celery.platforms import pyimplementation -from celery.utils.serialization import pickle - -from celery.tests.case import ( - CELERY_TEST_CONFIG, - AppCase, - Mock, - depends_on_current_app, - mask_modules, - patch, - platform_pyimp, - sys_platform, - pypy_version, - with_environ, -) -from celery.utils import uuid -from celery.utils.mail import ErrorMail - -THIS_IS_A_KEY = 'this is a value' - - -class ObjectConfig(object): - FOO = 1 - BAR = 2 - -object_config = ObjectConfig() -dict_config = dict(FOO=10, BAR=20) - - -class ObjectConfig2(object): - LEAVE_FOR_WORK = True - MOMENT_TO_STOP = True - CALL_ME_BACK = 123456789 - WANT_ME_TO = False - UNDERSTAND_ME = True - - -class Object(object): - - def __init__(self, **kwargs): - for key, value in items(kwargs): - setattr(self, key, value) - - -def _get_test_config(): - return deepcopy(CELERY_TEST_CONFIG) -test_config = _get_test_config() - - -class test_module(AppCase): - - def test_default_app(self): - self.assertEqual(_app.default_app, _state.default_app) - - def test_bugreport(self): - self.assertTrue(_app.bugreport(app=self.app)) - - -class test_App(AppCase): - - def setup(self): - self.app.add_defaults(test_config) - - def test_task_autofinalize_disabled(self): - with self.Celery('xyzibari', autofinalize=False) as app: - @app.task - def ttafd(): - return 42 - - with self.assertRaises(RuntimeError): - ttafd() - - with self.Celery('xyzibari', autofinalize=False) as app: - @app.task - def ttafd2(): - return 42 - - app.finalize() - self.assertEqual(ttafd2(), 42) - - def test_registry_autofinalize_disabled(self): - with self.Celery('xyzibari', autofinalize=False) as app: - with self.assertRaises(RuntimeError): - app.tasks['celery.chain'] - app.finalize() - self.assertTrue(app.tasks['celery.chain']) - - def test_task(self): - with self.Celery('foozibari') as app: - - def fun(): - pass - - fun.__module__ = '__main__' - task = app.task(fun) - self.assertEqual(task.name, app.main + '.fun') - - def test_with_config_source(self): - with self.Celery(config_source=ObjectConfig) as app: - self.assertEqual(app.conf.FOO, 1) - self.assertEqual(app.conf.BAR, 2) - - @depends_on_current_app - def test_task_windows_execv(self): - prev, _appbase._EXECV = _appbase._EXECV, True - try: - - @self.app.task(shared=False) - def foo(): - pass - - self.assertTrue(foo._get_current_object()) # is proxy - - finally: - _appbase._EXECV = prev - assert not _appbase._EXECV - - def test_task_takes_no_args(self): - with self.assertRaises(TypeError): - @self.app.task(1) - def foo(): - pass - - def test_add_defaults(self): - self.assertFalse(self.app.configured) - _conf = {'FOO': 300} - conf = lambda: _conf - self.app.add_defaults(conf) - self.assertIn(conf, self.app._pending_defaults) - self.assertFalse(self.app.configured) - self.assertEqual(self.app.conf.FOO, 300) - self.assertTrue(self.app.configured) - self.assertFalse(self.app._pending_defaults) - - # defaults not pickled - appr = loads(dumps(self.app)) - with self.assertRaises(AttributeError): - appr.conf.FOO - - # add more defaults after configured - conf2 = {'FOO': 'BAR'} - self.app.add_defaults(conf2) - self.assertEqual(self.app.conf.FOO, 'BAR') - - self.assertIn(_conf, self.app.conf.defaults) - self.assertIn(conf2, self.app.conf.defaults) - - def test_connection_or_acquire(self): - with self.app.connection_or_acquire(block=True): - self.assertTrue(self.app.pool._dirty) - - with self.app.connection_or_acquire(pool=False): - self.assertFalse(self.app.pool._dirty) - - def test_maybe_close_pool(self): - cpool = self.app._pool = Mock() - amqp = self.app.__dict__['amqp'] = Mock() - ppool = amqp._producer_pool - self.app._maybe_close_pool() - cpool.force_close_all.assert_called_with() - ppool.force_close_all.assert_called_with() - self.assertIsNone(self.app._pool) - self.assertIsNone(self.app.__dict__['amqp']._producer_pool) - - self.app._pool = Mock() - self.app._maybe_close_pool() - self.app._maybe_close_pool() - - def test_using_v1_reduce(self): - self.app._using_v1_reduce = True - self.assertTrue(loads(dumps(self.app))) - - def test_autodiscover_tasks_force(self): - self.app.loader.autodiscover_tasks = Mock() - self.app.autodiscover_tasks(['proj.A', 'proj.B'], force=True) - self.app.loader.autodiscover_tasks.assert_called_with( - ['proj.A', 'proj.B'], 'tasks', - ) - self.app.loader.autodiscover_tasks = Mock() - self.app.autodiscover_tasks( - lambda: ['proj.A', 'proj.B'], - related_name='george', - force=True, - ) - self.app.loader.autodiscover_tasks.assert_called_with( - ['proj.A', 'proj.B'], 'george', - ) - - def test_autodiscover_tasks_lazy(self): - with patch('celery.signals.import_modules') as import_modules: - packages = lambda: [1, 2, 3] - self.app.autodiscover_tasks(packages) - self.assertTrue(import_modules.connect.called) - prom = import_modules.connect.call_args[0][0] - self.assertIsInstance(prom, promise) - self.assertEqual(prom.fun, self.app._autodiscover_tasks) - self.assertEqual(prom.args[0](), [1, 2, 3]) - - @with_environ('CELERY_BROKER_URL', '') - def test_with_broker(self): - with self.Celery(broker='foo://baribaz') as app: - self.assertEqual(app.conf.BROKER_URL, 'foo://baribaz') - - def test_repr(self): - self.assertTrue(repr(self.app)) - - def test_custom_task_registry(self): - with self.Celery(tasks=self.app.tasks) as app2: - self.assertIs(app2.tasks, self.app.tasks) - - def test_include_argument(self): - with self.Celery(include=('foo', 'bar.foo')) as app: - self.assertEqual(app.conf.CELERY_IMPORTS, ('foo', 'bar.foo')) - - def test_set_as_current(self): - current = _state._tls.current_app - try: - app = self.Celery(set_as_current=True) - self.assertIs(_state._tls.current_app, app) - finally: - _state._tls.current_app = current - - def test_current_task(self): - @self.app.task - def foo(shared=False): - pass - - _state._task_stack.push(foo) - try: - self.assertEqual(self.app.current_task.name, foo.name) - finally: - _state._task_stack.pop() - - def test_task_not_shared(self): - with patch('celery.app.base.shared_task') as sh: - @self.app.task(shared=False) - def foo(): - pass - self.assertFalse(sh.called) - - def test_task_compat_with_filter(self): - with self.Celery(accept_magic_kwargs=True) as app: - check = Mock() - - def filter(task): - check(task) - return task - - @app.task(filter=filter, shared=False) - def foo(): - pass - check.assert_called_with(foo) - - def test_task_with_filter(self): - with self.Celery(accept_magic_kwargs=False) as app: - check = Mock() - - def filter(task): - check(task) - return task - - assert not _appbase._EXECV - - @app.task(filter=filter, shared=False) - def foo(): - pass - check.assert_called_with(foo) - - def test_task_sets_main_name_MP_MAIN_FILE(self): - from celery import utils as _utils - _utils.MP_MAIN_FILE = __file__ - try: - with self.Celery('xuzzy') as app: - - @app.task - def foo(): - pass - - self.assertEqual(foo.name, 'xuzzy.foo') - finally: - _utils.MP_MAIN_FILE = None - - def test_annotate_decorator(self): - from celery.app.task import Task - - class adX(Task): - abstract = True - - def run(self, y, z, x): - return y, z, x - - check = Mock() - - def deco(fun): - - def _inner(*args, **kwargs): - check(*args, **kwargs) - return fun(*args, **kwargs) - return _inner - - self.app.conf.CELERY_ANNOTATIONS = { - adX.name: {'@__call__': deco} - } - adX.bind(self.app) - self.assertIs(adX.app, self.app) - - i = adX() - i(2, 4, x=3) - check.assert_called_with(i, 2, 4, x=3) - - i.annotate() - i.annotate() - - def test_apply_async_has__self__(self): - @self.app.task(__self__='hello', shared=False) - def aawsX(): - pass - - with patch('celery.app.amqp.TaskProducer.publish_task') as dt: - aawsX.apply_async((4, 5)) - args = dt.call_args[0][1] - self.assertEqual(args, ('hello', 4, 5)) - - def test_apply_async_adds_children(self): - from celery._state import _task_stack - - @self.app.task(shared=False) - def a3cX1(self): - pass - - @self.app.task(shared=False) - def a3cX2(self): - pass - - _task_stack.push(a3cX1) - try: - a3cX1.push_request(called_directly=False) - try: - res = a3cX2.apply_async(add_to_parent=True) - self.assertIn(res, a3cX1.request.children) - finally: - a3cX1.pop_request() - finally: - _task_stack.pop() - - def test_pickle_app(self): - changes = dict(THE_FOO_BAR='bars', - THE_MII_MAR='jars') - self.app.conf.update(changes) - saved = pickle.dumps(self.app) - self.assertLess(len(saved), 2048) - restored = pickle.loads(saved) - self.assertDictContainsSubset(changes, restored.conf) - - def test_worker_main(self): - from celery.bin import worker as worker_bin - - class worker(worker_bin.worker): - - def execute_from_commandline(self, argv): - return argv - - prev, worker_bin.worker = worker_bin.worker, worker - try: - ret = self.app.worker_main(argv=['--version']) - self.assertListEqual(ret, ['--version']) - finally: - worker_bin.worker = prev - - def test_config_from_envvar(self): - os.environ['CELERYTEST_CONFIG_OBJECT'] = 'celery.tests.app.test_app' - self.app.config_from_envvar('CELERYTEST_CONFIG_OBJECT') - self.assertEqual(self.app.conf.THIS_IS_A_KEY, 'this is a value') - - def assert_config2(self): - self.assertTrue(self.app.conf.LEAVE_FOR_WORK) - self.assertTrue(self.app.conf.MOMENT_TO_STOP) - self.assertEqual(self.app.conf.CALL_ME_BACK, 123456789) - self.assertFalse(self.app.conf.WANT_ME_TO) - self.assertTrue(self.app.conf.UNDERSTAND_ME) - - def test_config_from_object__lazy(self): - conf = ObjectConfig2() - self.app.config_from_object(conf) - self.assertFalse(self.app.loader._conf) - self.assertIs(self.app._config_source, conf) - - self.assert_config2() - - def test_config_from_object__force(self): - self.app.config_from_object(ObjectConfig2(), force=True) - self.assertTrue(self.app.loader._conf) - - self.assert_config2() - - def test_config_from_cmdline(self): - cmdline = ['.always_eager=no', - '.result_backend=/dev/null', - 'celeryd.prefetch_multiplier=368', - '.foobarstring=(string)300', - '.foobarint=(int)300', - '.result_engine_options=(dict){"foo": "bar"}'] - self.app.config_from_cmdline(cmdline, namespace='celery') - self.assertFalse(self.app.conf.CELERY_ALWAYS_EAGER) - self.assertEqual(self.app.conf.CELERY_RESULT_BACKEND, '/dev/null') - self.assertEqual(self.app.conf.CELERYD_PREFETCH_MULTIPLIER, 368) - self.assertEqual(self.app.conf.CELERY_FOOBARSTRING, '300') - self.assertEqual(self.app.conf.CELERY_FOOBARINT, 300) - self.assertDictEqual(self.app.conf.CELERY_RESULT_ENGINE_OPTIONS, - {'foo': 'bar'}) - - def test_compat_setting_CELERY_BACKEND(self): - - self.app.config_from_object(Object(CELERY_BACKEND='set_by_us')) - self.assertEqual(self.app.conf.CELERY_RESULT_BACKEND, 'set_by_us') - - def test_setting_BROKER_TRANSPORT_OPTIONS(self): - - _args = {'foo': 'bar', 'spam': 'baz'} - - self.app.config_from_object(Object()) - self.assertEqual(self.app.conf.BROKER_TRANSPORT_OPTIONS, {}) - - self.app.config_from_object(Object(BROKER_TRANSPORT_OPTIONS=_args)) - self.assertEqual(self.app.conf.BROKER_TRANSPORT_OPTIONS, _args) - - def test_Windows_log_color_disabled(self): - self.app.IS_WINDOWS = True - self.assertFalse(self.app.log.supports_color(True)) - - def test_compat_setting_CARROT_BACKEND(self): - self.app.config_from_object(Object(CARROT_BACKEND='set_by_us')) - self.assertEqual(self.app.conf.BROKER_TRANSPORT, 'set_by_us') - - def test_WorkController(self): - x = self.app.WorkController - self.assertIs(x.app, self.app) - - def test_Worker(self): - x = self.app.Worker - self.assertIs(x.app, self.app) - - @depends_on_current_app - def test_AsyncResult(self): - x = self.app.AsyncResult('1') - self.assertIs(x.app, self.app) - r = loads(dumps(x)) - # not set as current, so ends up as default app after reduce - self.assertIs(r.app, current_app._get_current_object()) - - def test_get_active_apps(self): - self.assertTrue(list(_state._get_active_apps())) - - app1 = self.Celery() - appid = id(app1) - self.assertIn(app1, _state._get_active_apps()) - app1.close() - del(app1) - - gc.collect() - - # weakref removed from list when app goes out of scope. - with self.assertRaises(StopIteration): - next(app for app in _state._get_active_apps() if id(app) == appid) - - def test_config_from_envvar_more(self, key='CELERY_HARNESS_CFG1'): - self.assertFalse( - self.app.config_from_envvar( - 'HDSAJIHWIQHEWQU', force=True, silent=True), - ) - with self.assertRaises(ImproperlyConfigured): - self.app.config_from_envvar( - 'HDSAJIHWIQHEWQU', force=True, silent=False, - ) - os.environ[key] = __name__ + '.object_config' - self.assertTrue(self.app.config_from_envvar(key, force=True)) - self.assertEqual(self.app.conf['FOO'], 1) - self.assertEqual(self.app.conf['BAR'], 2) - - os.environ[key] = 'unknown_asdwqe.asdwqewqe' - with self.assertRaises(ImportError): - self.app.config_from_envvar(key, silent=False) - self.assertFalse( - self.app.config_from_envvar(key, force=True, silent=True), - ) - - os.environ[key] = __name__ + '.dict_config' - self.assertTrue(self.app.config_from_envvar(key, force=True)) - self.assertEqual(self.app.conf['FOO'], 10) - self.assertEqual(self.app.conf['BAR'], 20) - - @patch('celery.bin.celery.CeleryCommand.execute_from_commandline') - def test_start(self, execute): - self.app.start() - self.assertTrue(execute.called) - - def test_mail_admins(self): - - class Loader(BaseLoader): - - def mail_admins(*args, **kwargs): - return args, kwargs - - self.app.loader = Loader(app=self.app) - self.app.conf.ADMINS = None - self.assertFalse(self.app.mail_admins('Subject', 'Body')) - self.app.conf.ADMINS = [('George Costanza', 'george@vandelay.com')] - self.assertTrue(self.app.mail_admins('Subject', 'Body')) - - def test_amqp_get_broker_info(self): - self.assertDictContainsSubset( - {'hostname': 'localhost', - 'userid': 'guest', - 'password': 'guest', - 'virtual_host': '/'}, - self.app.connection('pyamqp://').info(), - ) - self.app.conf.BROKER_PORT = 1978 - self.app.conf.BROKER_VHOST = 'foo' - self.assertDictContainsSubset( - {'port': 1978, 'virtual_host': 'foo'}, - self.app.connection('pyamqp://:1978/foo').info(), - ) - conn = self.app.connection('pyamqp:////value') - self.assertDictContainsSubset({'virtual_host': '/value'}, - conn.info()) - - def test_amqp_failover_strategy_selection(self): - # Test passing in a string and make sure the string - # gets there untouched - self.app.conf.BROKER_FAILOVER_STRATEGY = 'foo-bar' - self.assertEqual( - self.app.connection('amqp:////value').failover_strategy, - 'foo-bar', - ) - - # Try passing in None - self.app.conf.BROKER_FAILOVER_STRATEGY = None - self.assertEqual( - self.app.connection('amqp:////value').failover_strategy, - itertools.cycle, - ) - - # Test passing in a method - def my_failover_strategy(it): - yield True - - self.app.conf.BROKER_FAILOVER_STRATEGY = my_failover_strategy - self.assertEqual( - self.app.connection('amqp:////value').failover_strategy, - my_failover_strategy, - ) - - def test_BROKER_BACKEND_alias(self): - self.assertEqual(self.app.conf.BROKER_BACKEND, - self.app.conf.BROKER_TRANSPORT) - - def test_after_fork(self): - p = self.app._pool = Mock() - self.app._after_fork(self.app) - p.force_close_all.assert_called_with() - self.assertIsNone(self.app._pool) - self.app._after_fork(self.app) - - def test_pool_no_multiprocessing(self): - with mask_modules('multiprocessing.util'): - pool = self.app.pool - self.assertIs(pool, self.app._pool) - - def test_bugreport(self): - self.assertTrue(self.app.bugreport()) - - def test_send_task_sent_event(self): - - class Dispatcher(object): - sent = [] - - def publish(self, type, fields, *args, **kwargs): - self.sent.append((type, fields)) - - conn = self.app.connection() - chan = conn.channel() - try: - for e in ('foo_exchange', 'moo_exchange', 'bar_exchange'): - chan.exchange_declare(e, 'direct', durable=True) - chan.queue_declare(e, durable=True) - chan.queue_bind(e, e, e) - finally: - chan.close() - assert conn.transport_cls == 'memory' - - prod = self.app.amqp.TaskProducer( - conn, exchange=Exchange('foo_exchange'), - send_sent_event=True, - ) - - dispatcher = Dispatcher() - self.assertTrue(prod.publish_task('footask', (), {}, - exchange='moo_exchange', - routing_key='moo_exchange', - event_dispatcher=dispatcher)) - self.assertTrue(dispatcher.sent) - self.assertEqual(dispatcher.sent[0][0], 'task-sent') - self.assertTrue(prod.publish_task('footask', (), {}, - event_dispatcher=dispatcher, - exchange='bar_exchange', - routing_key='bar_exchange')) - - def test_error_mail_sender(self): - x = ErrorMail.subject % {'name': 'task_name', - 'id': uuid(), - 'exc': 'FOOBARBAZ', - 'hostname': 'lana'} - self.assertTrue(x) - - def test_error_mail_disabled(self): - task = Mock() - x = ErrorMail(task) - x.should_send = Mock() - x.should_send.return_value = False - x.send(Mock(), Mock()) - self.assertFalse(task.app.mail_admins.called) - - -class test_defaults(AppCase): - - def test_strtobool(self): - for s in ('false', 'no', '0'): - self.assertFalse(defaults.strtobool(s)) - for s in ('true', 'yes', '1'): - self.assertTrue(defaults.strtobool(s)) - with self.assertRaises(TypeError): - defaults.strtobool('unsure') - - -class test_debugging_utils(AppCase): - - def test_enable_disable_trace(self): - try: - _app.enable_trace() - self.assertEqual(_app.app_or_default, _app._app_or_default_trace) - _app.disable_trace() - self.assertEqual(_app.app_or_default, _app._app_or_default) - finally: - _app.disable_trace() - - -class test_pyimplementation(AppCase): - - def test_platform_python_implementation(self): - with platform_pyimp(lambda: 'Xython'): - self.assertEqual(pyimplementation(), 'Xython') - - def test_platform_jython(self): - with platform_pyimp(): - with sys_platform('java 1.6.51'): - self.assertIn('Jython', pyimplementation()) - - def test_platform_pypy(self): - with platform_pyimp(): - with sys_platform('darwin'): - with pypy_version((1, 4, 3)): - self.assertIn('PyPy', pyimplementation()) - with pypy_version((1, 4, 3, 'a4')): - self.assertIn('PyPy', pyimplementation()) - - def test_platform_fallback(self): - with platform_pyimp(): - with sys_platform('darwin'): - with pypy_version(): - self.assertEqual('CPython', pyimplementation()) - - -class test_shared_task(AppCase): - - def test_registers_to_all_apps(self): - with self.Celery('xproj', set_as_current=True) as xproj: - xproj.finalize() - - @shared_task - def foo(): - return 42 - - @shared_task() - def bar(): - return 84 - - self.assertIs(foo.app, xproj) - self.assertIs(bar.app, xproj) - self.assertTrue(foo._get_current_object()) - - with self.Celery('yproj', set_as_current=True) as yproj: - self.assertIs(foo.app, yproj) - self.assertIs(bar.app, yproj) - - @shared_task() - def baz(): - return 168 - - self.assertIs(baz.app, yproj) diff --git a/awx/lib/site-packages/celery/tests/app/test_beat.py b/awx/lib/site-packages/celery/tests/app/test_beat.py deleted file mode 100644 index 62310805a3..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_beat.py +++ /dev/null @@ -1,539 +0,0 @@ -from __future__ import absolute_import - -import errno - -from datetime import datetime, timedelta -from pickle import dumps, loads - -from celery import beat -from celery.five import keys, string_t -from celery.schedules import schedule -from celery.utils import uuid -from celery.tests.case import AppCase, Mock, SkipTest, call, patch - - -class Object(object): - pass - - -class MockShelve(dict): - closed = False - synced = False - - def close(self): - self.closed = True - - def sync(self): - self.synced = True - - -class MockService(object): - started = False - stopped = False - - def __init__(self, *args, **kwargs): - pass - - def start(self, **kwargs): - self.started = True - - def stop(self, **kwargs): - self.stopped = True - - -class test_ScheduleEntry(AppCase): - Entry = beat.ScheduleEntry - - def create_entry(self, **kwargs): - entry = dict( - name='celery.unittest.add', - schedule=timedelta(seconds=10), - args=(2, 2), - options={'routing_key': 'cpu'}, - app=self.app, - ) - return self.Entry(**dict(entry, **kwargs)) - - def test_next(self): - entry = self.create_entry(schedule=10) - self.assertTrue(entry.last_run_at) - self.assertIsInstance(entry.last_run_at, datetime) - self.assertEqual(entry.total_run_count, 0) - - next_run_at = entry.last_run_at + timedelta(seconds=10) - next_entry = entry.next(next_run_at) - self.assertGreaterEqual(next_entry.last_run_at, next_run_at) - self.assertEqual(next_entry.total_run_count, 1) - - def test_is_due(self): - entry = self.create_entry(schedule=timedelta(seconds=10)) - self.assertIs(entry.app, self.app) - self.assertIs(entry.schedule.app, self.app) - due1, next_time_to_run1 = entry.is_due() - self.assertFalse(due1) - self.assertGreater(next_time_to_run1, 9) - - next_run_at = entry.last_run_at - timedelta(seconds=10) - next_entry = entry.next(next_run_at) - due2, next_time_to_run2 = next_entry.is_due() - self.assertTrue(due2) - self.assertGreater(next_time_to_run2, 9) - - def test_repr(self): - entry = self.create_entry() - self.assertIn('<Entry:', repr(entry)) - - def test_update(self): - entry = self.create_entry() - self.assertEqual(entry.schedule, timedelta(seconds=10)) - self.assertTupleEqual(entry.args, (2, 2)) - self.assertDictEqual(entry.kwargs, {}) - self.assertDictEqual(entry.options, {'routing_key': 'cpu'}) - - entry2 = self.create_entry(schedule=timedelta(minutes=20), - args=(16, 16), - kwargs={'callback': 'foo.bar.baz'}, - options={'routing_key': 'urgent'}) - entry.update(entry2) - self.assertEqual(entry.schedule, schedule(timedelta(minutes=20))) - self.assertTupleEqual(entry.args, (16, 16)) - self.assertDictEqual(entry.kwargs, {'callback': 'foo.bar.baz'}) - self.assertDictEqual(entry.options, {'routing_key': 'urgent'}) - - -class mScheduler(beat.Scheduler): - - def __init__(self, *args, **kwargs): - self.sent = [] - beat.Scheduler.__init__(self, *args, **kwargs) - - def send_task(self, name=None, args=None, kwargs=None, **options): - self.sent.append({'name': name, - 'args': args, - 'kwargs': kwargs, - 'options': options}) - return self.app.AsyncResult(uuid()) - - -class mSchedulerSchedulingError(mScheduler): - - def send_task(self, *args, **kwargs): - raise beat.SchedulingError('Could not apply task') - - -class mSchedulerRuntimeError(mScheduler): - - def maybe_due(self, *args, **kwargs): - raise RuntimeError('dict modified while itervalues') - - -class mocked_schedule(schedule): - - def __init__(self, is_due, next_run_at): - self._is_due = is_due - self._next_run_at = next_run_at - self.run_every = timedelta(seconds=1) - self.nowfun = datetime.utcnow - - def is_due(self, last_run_at): - return self._is_due, self._next_run_at - - -always_due = mocked_schedule(True, 1) -always_pending = mocked_schedule(False, 1) - - -class test_Scheduler(AppCase): - - def test_custom_schedule_dict(self): - custom = {'foo': 'bar'} - scheduler = mScheduler(app=self.app, schedule=custom, lazy=True) - self.assertIs(scheduler.data, custom) - - def test_apply_async_uses_registered_task_instances(self): - - @self.app.task(shared=False) - def foo(): - pass - foo.apply_async = Mock(name='foo.apply_async') - assert foo.name in foo._get_app().tasks - - scheduler = mScheduler(app=self.app) - scheduler.apply_async(scheduler.Entry(task=foo.name, app=self.app)) - self.assertTrue(foo.apply_async.called) - - def test_should_sync(self): - - @self.app.task(shared=False) - def not_sync(): - pass - not_sync.apply_async = Mock() - - s = mScheduler(app=self.app) - s._do_sync = Mock() - s.should_sync = Mock() - s.should_sync.return_value = True - s.apply_async(s.Entry(task=not_sync.name, app=self.app)) - s._do_sync.assert_called_with() - - s._do_sync = Mock() - s.should_sync.return_value = False - s.apply_async(s.Entry(task=not_sync.name, app=self.app)) - self.assertFalse(s._do_sync.called) - - def test_should_sync_increments_sync_every_counter(self): - self.app.conf.CELERYBEAT_SYNC_EVERY = 2 - - @self.app.task(shared=False) - def not_sync(): - pass - not_sync.apply_async = Mock() - - s = mScheduler(app=self.app) - self.assertEqual(s.sync_every_tasks, 2) - s._do_sync = Mock() - - s.apply_async(s.Entry(task=not_sync.name, app=self.app)) - self.assertEqual(s._tasks_since_sync, 1) - s.apply_async(s.Entry(task=not_sync.name, app=self.app)) - s._do_sync.assert_called_with() - - self.app.conf.CELERYBEAT_SYNC_EVERY = 0 - - def test_sync_task_counter_resets_on_do_sync(self): - self.app.conf.CELERYBEAT_SYNC_EVERY = 1 - - @self.app.task(shared=False) - def not_sync(): - pass - not_sync.apply_async = Mock() - - s = mScheduler(app=self.app) - self.assertEqual(s.sync_every_tasks, 1) - - s.apply_async(s.Entry(task=not_sync.name, app=self.app)) - self.assertEqual(s._tasks_since_sync, 0) - - self.app.conf.CELERYBEAT_SYNC_EVERY = 0 - - @patch('celery.app.base.Celery.send_task') - def test_send_task(self, send_task): - b = beat.Scheduler(app=self.app) - b.send_task('tasks.add', countdown=10) - send_task.assert_called_with('tasks.add', countdown=10) - - def test_info(self): - scheduler = mScheduler(app=self.app) - self.assertIsInstance(scheduler.info, string_t) - - def test_maybe_entry(self): - s = mScheduler(app=self.app) - entry = s.Entry(name='add every', task='tasks.add', app=self.app) - self.assertIs(s._maybe_entry(entry.name, entry), entry) - self.assertTrue(s._maybe_entry('add every', { - 'task': 'tasks.add', - })) - - def test_set_schedule(self): - s = mScheduler(app=self.app) - s.schedule = {'foo': 'bar'} - self.assertEqual(s.data, {'foo': 'bar'}) - - @patch('kombu.connection.Connection.ensure_connection') - def test_ensure_connection_error_handler(self, ensure): - s = mScheduler(app=self.app) - self.assertTrue(s._ensure_connected()) - self.assertTrue(ensure.called) - callback = ensure.call_args[0][0] - - callback(KeyError(), 5) - - def test_install_default_entries(self): - self.app.conf.CELERY_TASK_RESULT_EXPIRES = None - self.app.conf.CELERYBEAT_SCHEDULE = {} - s = mScheduler(app=self.app) - s.install_default_entries({}) - self.assertNotIn('celery.backend_cleanup', s.data) - self.app.backend.supports_autoexpire = False - - self.app.conf.CELERY_TASK_RESULT_EXPIRES = 30 - s = mScheduler(app=self.app) - s.install_default_entries({}) - self.assertIn('celery.backend_cleanup', s.data) - - self.app.backend.supports_autoexpire = True - self.app.conf.CELERY_TASK_RESULT_EXPIRES = 31 - s = mScheduler(app=self.app) - s.install_default_entries({}) - self.assertNotIn('celery.backend_cleanup', s.data) - - def test_due_tick(self): - scheduler = mScheduler(app=self.app) - scheduler.add(name='test_due_tick', - schedule=always_due, - args=(1, 2), - kwargs={'foo': 'bar'}) - self.assertEqual(scheduler.tick(), 1) - - @patch('celery.beat.error') - def test_due_tick_SchedulingError(self, error): - scheduler = mSchedulerSchedulingError(app=self.app) - scheduler.add(name='test_due_tick_SchedulingError', - schedule=always_due) - self.assertEqual(scheduler.tick(), 1) - self.assertTrue(error.called) - - def test_due_tick_RuntimeError(self): - scheduler = mSchedulerRuntimeError(app=self.app) - scheduler.add(name='test_due_tick_RuntimeError', - schedule=always_due) - self.assertEqual(scheduler.tick(), scheduler.max_interval) - - def test_pending_tick(self): - scheduler = mScheduler(app=self.app) - scheduler.add(name='test_pending_tick', - schedule=always_pending) - self.assertEqual(scheduler.tick(), 1) - - def test_honors_max_interval(self): - scheduler = mScheduler(app=self.app) - maxi = scheduler.max_interval - scheduler.add(name='test_honors_max_interval', - schedule=mocked_schedule(False, maxi * 4)) - self.assertEqual(scheduler.tick(), maxi) - - def test_ticks(self): - scheduler = mScheduler(app=self.app) - nums = [600, 300, 650, 120, 250, 36] - s = dict(('test_ticks%s' % i, - {'schedule': mocked_schedule(False, j)}) - for i, j in enumerate(nums)) - scheduler.update_from_dict(s) - self.assertEqual(scheduler.tick(), min(nums)) - - def test_schedule_no_remain(self): - scheduler = mScheduler(app=self.app) - scheduler.add(name='test_schedule_no_remain', - schedule=mocked_schedule(False, None)) - self.assertEqual(scheduler.tick(), scheduler.max_interval) - - def test_interface(self): - scheduler = mScheduler(app=self.app) - scheduler.sync() - scheduler.setup_schedule() - scheduler.close() - - def test_merge_inplace(self): - a = mScheduler(app=self.app) - b = mScheduler(app=self.app) - a.update_from_dict({'foo': {'schedule': mocked_schedule(True, 10)}, - 'bar': {'schedule': mocked_schedule(True, 20)}}) - b.update_from_dict({'bar': {'schedule': mocked_schedule(True, 40)}, - 'baz': {'schedule': mocked_schedule(True, 10)}}) - a.merge_inplace(b.schedule) - - self.assertNotIn('foo', a.schedule) - self.assertIn('baz', a.schedule) - self.assertEqual(a.schedule['bar'].schedule._next_run_at, 40) - - -def create_persistent_scheduler(shelv=None): - if shelv is None: - shelv = MockShelve() - - class MockPersistentScheduler(beat.PersistentScheduler): - sh = shelv - persistence = Object() - persistence.open = lambda *a, **kw: shelv - tick_raises_exit = False - shutdown_service = None - - def tick(self): - if self.tick_raises_exit: - raise SystemExit() - if self.shutdown_service: - self.shutdown_service._is_shutdown.set() - return 0.0 - - return MockPersistentScheduler, shelv - - -class test_PersistentScheduler(AppCase): - - @patch('os.remove') - def test_remove_db(self, remove): - s = create_persistent_scheduler()[0](app=self.app, - schedule_filename='schedule') - s._remove_db() - remove.assert_has_calls( - [call('schedule' + suffix) for suffix in s.known_suffixes] - ) - err = OSError() - err.errno = errno.ENOENT - remove.side_effect = err - s._remove_db() - err.errno = errno.EPERM - with self.assertRaises(OSError): - s._remove_db() - - def test_setup_schedule(self): - s = create_persistent_scheduler()[0](app=self.app, - schedule_filename='schedule') - opens = s.persistence.open = Mock() - s._remove_db = Mock() - - def effect(*args, **kwargs): - if opens.call_count > 1: - return s.sh - raise OSError() - opens.side_effect = effect - s.setup_schedule() - s._remove_db.assert_called_with() - - s._store = {'__version__': 1} - s.setup_schedule() - - s._store.clear = Mock() - op = s.persistence.open = Mock() - op.return_value = s._store - s._store['tz'] = 'FUNKY' - s.setup_schedule() - op.assert_called_with(s.schedule_filename, writeback=True) - s._store.clear.assert_called_with() - s._store['utc_enabled'] = False - s._store.clear = Mock() - s.setup_schedule() - s._store.clear.assert_called_with() - - def test_get_schedule(self): - s = create_persistent_scheduler()[0]( - schedule_filename='schedule', app=self.app, - ) - s._store = {'entries': {}} - s.schedule = {'foo': 'bar'} - self.assertDictEqual(s.schedule, {'foo': 'bar'}) - self.assertDictEqual(s._store['entries'], s.schedule) - - -class test_Service(AppCase): - - def get_service(self): - Scheduler, mock_shelve = create_persistent_scheduler() - return beat.Service(app=self.app, scheduler_cls=Scheduler), mock_shelve - - def test_pickleable(self): - s = beat.Service(app=self.app, scheduler_cls=Mock) - self.assertTrue(loads(dumps(s))) - - def test_start(self): - s, sh = self.get_service() - schedule = s.scheduler.schedule - self.assertIsInstance(schedule, dict) - self.assertIsInstance(s.scheduler, beat.Scheduler) - scheduled = list(schedule.keys()) - for task_name in keys(sh['entries']): - self.assertIn(task_name, scheduled) - - s.sync() - self.assertTrue(sh.closed) - self.assertTrue(sh.synced) - self.assertTrue(s._is_stopped.isSet()) - s.sync() - s.stop(wait=False) - self.assertTrue(s._is_shutdown.isSet()) - s.stop(wait=True) - self.assertTrue(s._is_shutdown.isSet()) - - p = s.scheduler._store - s.scheduler._store = None - try: - s.scheduler.sync() - finally: - s.scheduler._store = p - - def test_start_embedded_process(self): - s, sh = self.get_service() - s._is_shutdown.set() - s.start(embedded_process=True) - - def test_start_thread(self): - s, sh = self.get_service() - s._is_shutdown.set() - s.start(embedded_process=False) - - def test_start_tick_raises_exit_error(self): - s, sh = self.get_service() - s.scheduler.tick_raises_exit = True - s.start() - self.assertTrue(s._is_shutdown.isSet()) - - def test_start_manages_one_tick_before_shutdown(self): - s, sh = self.get_service() - s.scheduler.shutdown_service = s - s.start() - self.assertTrue(s._is_shutdown.isSet()) - - -class test_EmbeddedService(AppCase): - - def test_start_stop_process(self): - try: - import _multiprocessing # noqa - except ImportError: - raise SkipTest('multiprocessing not available') - - from billiard.process import Process - - s = beat.EmbeddedService(app=self.app) - self.assertIsInstance(s, Process) - self.assertIsInstance(s.service, beat.Service) - s.service = MockService() - - class _Popen(object): - terminated = False - - def terminate(self): - self.terminated = True - - with patch('celery.platforms.close_open_fds'): - s.run() - self.assertTrue(s.service.started) - - s._popen = _Popen() - s.stop() - self.assertTrue(s.service.stopped) - self.assertTrue(s._popen.terminated) - - def test_start_stop_threaded(self): - s = beat.EmbeddedService(thread=True, app=self.app) - from threading import Thread - self.assertIsInstance(s, Thread) - self.assertIsInstance(s.service, beat.Service) - s.service = MockService() - - s.run() - self.assertTrue(s.service.started) - - s.stop() - self.assertTrue(s.service.stopped) - - -class test_schedule(AppCase): - - def test_maybe_make_aware(self): - x = schedule(10, app=self.app) - x.utc_enabled = True - d = x.maybe_make_aware(datetime.utcnow()) - self.assertTrue(d.tzinfo) - x.utc_enabled = False - d2 = x.maybe_make_aware(datetime.utcnow()) - self.assertIsNone(d2.tzinfo) - - def test_to_local(self): - x = schedule(10, app=self.app) - x.utc_enabled = True - d = x.to_local(datetime.utcnow()) - self.assertIsNone(d.tzinfo) - x.utc_enabled = False - d = x.to_local(datetime.utcnow()) - self.assertTrue(d.tzinfo) diff --git a/awx/lib/site-packages/celery/tests/app/test_builtins.py b/awx/lib/site-packages/celery/tests/app/test_builtins.py deleted file mode 100644 index 9b00c1a253..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_builtins.py +++ /dev/null @@ -1,217 +0,0 @@ -from __future__ import absolute_import - -from celery import group, chord -from celery.app import builtins -from celery.canvas import Signature -from celery.five import range -from celery._state import _task_stack -from celery.tests.case import AppCase, Mock, patch - - -class BuiltinsCase(AppCase): - - def setup(self): - @self.app.task(shared=False) - def xsum(x): - return sum(x) - self.xsum = xsum - - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - -class test_backend_cleanup(BuiltinsCase): - - def test_run(self): - self.app.backend.cleanup = Mock() - self.app.backend.cleanup.__name__ = 'cleanup' - cleanup_task = builtins.add_backend_cleanup_task(self.app) - cleanup_task() - self.assertTrue(self.app.backend.cleanup.called) - - -class test_map(BuiltinsCase): - - def test_run(self): - - @self.app.task(shared=False) - def map_mul(x): - return x[0] * x[1] - - res = self.app.tasks['celery.map']( - map_mul, [(2, 2), (4, 4), (8, 8)], - ) - self.assertEqual(res, [4, 16, 64]) - - -class test_starmap(BuiltinsCase): - - def test_run(self): - - @self.app.task(shared=False) - def smap_mul(x, y): - return x * y - - res = self.app.tasks['celery.starmap']( - smap_mul, [(2, 2), (4, 4), (8, 8)], - ) - self.assertEqual(res, [4, 16, 64]) - - -class test_chunks(BuiltinsCase): - - @patch('celery.canvas.chunks.apply_chunks') - def test_run(self, apply_chunks): - - @self.app.task(shared=False) - def chunks_mul(l): - return l - - self.app.tasks['celery.chunks']( - chunks_mul, [(2, 2), (4, 4), (8, 8)], 1, - ) - self.assertTrue(apply_chunks.called) - - -class test_group(BuiltinsCase): - - def setup(self): - self.task = builtins.add_group_task(self.app)() - super(test_group, self).setup() - - def test_apply_async_eager(self): - self.task.apply = Mock() - self.app.conf.CELERY_ALWAYS_EAGER = True - self.task.apply_async() - self.assertTrue(self.task.apply.called) - - def test_apply(self): - x = group([self.add.s(4, 4), self.add.s(8, 8)]) - x.name = self.task.name - res = x.apply() - self.assertEqual(res.get(), [8, 16]) - - def test_apply_async(self): - x = group([self.add.s(4, 4), self.add.s(8, 8)]) - x.apply_async() - - def test_apply_empty(self): - x = group(app=self.app) - x.apply() - res = x.apply_async() - self.assertFalse(res) - self.assertFalse(res.results) - - def test_apply_async_with_parent(self): - _task_stack.push(self.add) - try: - self.add.push_request(called_directly=False) - try: - assert not self.add.request.children - x = group([self.add.s(4, 4), self.add.s(8, 8)]) - res = x() - self.assertTrue(self.add.request.children) - self.assertIn(res, self.add.request.children) - self.assertEqual(len(self.add.request.children), 1) - finally: - self.add.pop_request() - finally: - _task_stack.pop() - - -class test_chain(BuiltinsCase): - - def setup(self): - BuiltinsCase.setup(self) - self.task = builtins.add_chain_task(self.app)() - - def test_apply_async(self): - c = self.add.s(2, 2) | self.add.s(4) | self.add.s(8) - result = c.apply_async() - self.assertTrue(result.parent) - self.assertTrue(result.parent.parent) - self.assertIsNone(result.parent.parent.parent) - - def test_group_to_chord(self): - c = ( - group(self.add.s(i, i) for i in range(5)) | - self.add.s(10) | - self.add.s(20) | - self.add.s(30) - ) - tasks, _ = c.type.prepare_steps((), c.tasks) - self.assertIsInstance(tasks[0], chord) - self.assertTrue(tasks[0].body.options['link']) - self.assertTrue(tasks[0].body.options['link'][0].options['link']) - - c2 = self.add.s(2, 2) | group(self.add.s(i, i) for i in range(10)) - tasks2, _ = c2.type.prepare_steps((), c2.tasks) - self.assertIsInstance(tasks2[1], group) - - def test_apply_options(self): - - class static(Signature): - - def clone(self, *args, **kwargs): - return self - - def s(*args, **kwargs): - return static(self.add, args, kwargs, type=self.add) - - c = s(2, 2) | s(4, 4) | s(8, 8) - r1 = c.apply_async(task_id='some_id') - self.assertEqual(r1.id, 'some_id') - - c.apply_async(group_id='some_group_id') - self.assertEqual(c.tasks[-1].options['group_id'], 'some_group_id') - - c.apply_async(chord='some_chord_id') - self.assertEqual(c.tasks[-1].options['chord'], 'some_chord_id') - - c.apply_async(link=[s(32)]) - self.assertListEqual(c.tasks[-1].options['link'], [s(32)]) - - c.apply_async(link_error=[s('error')]) - for task in c.tasks: - self.assertListEqual(task.options['link_error'], [s('error')]) - - -class test_chord(BuiltinsCase): - - def setup(self): - self.task = builtins.add_chord_task(self.app)() - super(test_chord, self).setup() - - def test_apply_async(self): - x = chord([self.add.s(i, i) for i in range(10)], body=self.xsum.s()) - r = x.apply_async() - self.assertTrue(r) - self.assertTrue(r.parent) - - def test_run_header_not_group(self): - self.task([self.add.s(i, i) for i in range(10)], self.xsum.s()) - - def test_forward_options(self): - body = self.xsum.s() - x = chord([self.add.s(i, i) for i in range(10)], body=body) - x._type = Mock() - x._type.app.conf.CELERY_ALWAYS_EAGER = False - x.apply_async(group_id='some_group_id') - self.assertTrue(x._type.called) - resbody = x._type.call_args[0][1] - self.assertEqual(resbody.options['group_id'], 'some_group_id') - x2 = chord([self.add.s(i, i) for i in range(10)], body=body) - x2._type = Mock() - x2._type.app.conf.CELERY_ALWAYS_EAGER = False - x2.apply_async(chord='some_chord_id') - self.assertTrue(x2._type.called) - resbody = x2._type.call_args[0][1] - self.assertEqual(resbody.options['chord'], 'some_chord_id') - - def test_apply_eager(self): - self.app.conf.CELERY_ALWAYS_EAGER = True - x = chord([self.add.s(i, i) for i in range(10)], body=self.xsum.s()) - r = x.apply_async() - self.assertEqual(r.get(), 90) diff --git a/awx/lib/site-packages/celery/tests/app/test_celery.py b/awx/lib/site-packages/celery/tests/app/test_celery.py deleted file mode 100644 index 5088d353f0..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_celery.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import absolute_import -from celery.tests.case import AppCase - -import celery - - -class test_celery_package(AppCase): - - def test_version(self): - self.assertTrue(celery.VERSION) - self.assertGreaterEqual(len(celery.VERSION), 3) - celery.VERSION = (0, 3, 0) - self.assertGreaterEqual(celery.__version__.count('.'), 2) - - def test_meta(self): - for m in ('__author__', '__contact__', '__homepage__', - '__docformat__'): - self.assertTrue(getattr(celery, m, None)) diff --git a/awx/lib/site-packages/celery/tests/app/test_control.py b/awx/lib/site-packages/celery/tests/app/test_control.py deleted file mode 100644 index ad4bc823a6..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_control.py +++ /dev/null @@ -1,251 +0,0 @@ -from __future__ import absolute_import - -import warnings - -from functools import wraps - -from kombu.pidbox import Mailbox - -from celery.app import control -from celery.utils import uuid -from celery.tests.case import AppCase - - -class MockMailbox(Mailbox): - sent = [] - - def _publish(self, command, *args, **kwargs): - self.__class__.sent.append(command) - - def close(self): - pass - - def _collect(self, *args, **kwargs): - pass - - -class Control(control.Control): - Mailbox = MockMailbox - - -def with_mock_broadcast(fun): - - @wraps(fun) - def _resets(*args, **kwargs): - MockMailbox.sent = [] - try: - return fun(*args, **kwargs) - finally: - MockMailbox.sent = [] - return _resets - - -class test_flatten_reply(AppCase): - - def test_flatten_reply(self): - reply = [ - {'foo@example.com': {'hello': 10}}, - {'foo@example.com': {'hello': 20}}, - {'bar@example.com': {'hello': 30}} - ] - with warnings.catch_warnings(record=True) as w: - nodes = control.flatten_reply(reply) - self.assertIn( - 'multiple replies', - str(w[-1].message), - ) - self.assertIn('foo@example.com', nodes) - self.assertIn('bar@example.com', nodes) - - -class test_inspect(AppCase): - - def setup(self): - self.c = Control(app=self.app) - self.prev, self.app.control = self.app.control, self.c - self.i = self.c.inspect() - - def test_prepare_reply(self): - self.assertDictEqual(self.i._prepare([{'w1': {'ok': 1}}, - {'w2': {'ok': 1}}]), - {'w1': {'ok': 1}, 'w2': {'ok': 1}}) - - i = self.c.inspect(destination='w1') - self.assertEqual(i._prepare([{'w1': {'ok': 1}}]), - {'ok': 1}) - - @with_mock_broadcast - def test_active(self): - self.i.active() - self.assertIn('dump_active', MockMailbox.sent) - - @with_mock_broadcast - def test_clock(self): - self.i.clock() - self.assertIn('clock', MockMailbox.sent) - - @with_mock_broadcast - def test_conf(self): - self.i.conf() - self.assertIn('dump_conf', MockMailbox.sent) - - @with_mock_broadcast - def test_hello(self): - self.i.hello('george@vandelay.com') - self.assertIn('hello', MockMailbox.sent) - - @with_mock_broadcast - def test_memsample(self): - self.i.memsample() - self.assertIn('memsample', MockMailbox.sent) - - @with_mock_broadcast - def test_memdump(self): - self.i.memdump() - self.assertIn('memdump', MockMailbox.sent) - - @with_mock_broadcast - def test_objgraph(self): - self.i.objgraph() - self.assertIn('objgraph', MockMailbox.sent) - - @with_mock_broadcast - def test_scheduled(self): - self.i.scheduled() - self.assertIn('dump_schedule', MockMailbox.sent) - - @with_mock_broadcast - def test_reserved(self): - self.i.reserved() - self.assertIn('dump_reserved', MockMailbox.sent) - - @with_mock_broadcast - def test_stats(self): - self.i.stats() - self.assertIn('stats', MockMailbox.sent) - - @with_mock_broadcast - def test_revoked(self): - self.i.revoked() - self.assertIn('dump_revoked', MockMailbox.sent) - - @with_mock_broadcast - def test_tasks(self): - self.i.registered() - self.assertIn('dump_tasks', MockMailbox.sent) - - @with_mock_broadcast - def test_ping(self): - self.i.ping() - self.assertIn('ping', MockMailbox.sent) - - @with_mock_broadcast - def test_active_queues(self): - self.i.active_queues() - self.assertIn('active_queues', MockMailbox.sent) - - @with_mock_broadcast - def test_report(self): - self.i.report() - self.assertIn('report', MockMailbox.sent) - - -class test_Broadcast(AppCase): - - def setup(self): - self.control = Control(app=self.app) - self.app.control = self.control - - @self.app.task(shared=False) - def mytask(): - pass - self.mytask = mytask - - def test_purge(self): - self.control.purge() - - @with_mock_broadcast - def test_broadcast(self): - self.control.broadcast('foobarbaz', arguments=[]) - self.assertIn('foobarbaz', MockMailbox.sent) - - @with_mock_broadcast - def test_broadcast_limit(self): - self.control.broadcast( - 'foobarbaz1', arguments=[], limit=None, destination=[1, 2, 3], - ) - self.assertIn('foobarbaz1', MockMailbox.sent) - - @with_mock_broadcast - def test_broadcast_validate(self): - with self.assertRaises(ValueError): - self.control.broadcast('foobarbaz2', - destination='foo') - - @with_mock_broadcast - def test_rate_limit(self): - self.control.rate_limit(self.mytask.name, '100/m') - self.assertIn('rate_limit', MockMailbox.sent) - - @with_mock_broadcast - def test_time_limit(self): - self.control.time_limit(self.mytask.name, soft=10, hard=20) - self.assertIn('time_limit', MockMailbox.sent) - - @with_mock_broadcast - def test_add_consumer(self): - self.control.add_consumer('foo') - self.assertIn('add_consumer', MockMailbox.sent) - - @with_mock_broadcast - def test_cancel_consumer(self): - self.control.cancel_consumer('foo') - self.assertIn('cancel_consumer', MockMailbox.sent) - - @with_mock_broadcast - def test_enable_events(self): - self.control.enable_events() - self.assertIn('enable_events', MockMailbox.sent) - - @with_mock_broadcast - def test_disable_events(self): - self.control.disable_events() - self.assertIn('disable_events', MockMailbox.sent) - - @with_mock_broadcast - def test_revoke(self): - self.control.revoke('foozbaaz') - self.assertIn('revoke', MockMailbox.sent) - - @with_mock_broadcast - def test_ping(self): - self.control.ping() - self.assertIn('ping', MockMailbox.sent) - - @with_mock_broadcast - def test_election(self): - self.control.election('some_id', 'topic', 'action') - self.assertIn('election', MockMailbox.sent) - - @with_mock_broadcast - def test_pool_grow(self): - self.control.pool_grow(2) - self.assertIn('pool_grow', MockMailbox.sent) - - @with_mock_broadcast - def test_pool_shrink(self): - self.control.pool_shrink(2) - self.assertIn('pool_shrink', MockMailbox.sent) - - @with_mock_broadcast - def test_revoke_from_result(self): - self.app.AsyncResult('foozbazzbar').revoke() - self.assertIn('revoke', MockMailbox.sent) - - @with_mock_broadcast - def test_revoke_from_resultset(self): - r = self.app.GroupResult(uuid(), - [self.app.AsyncResult(x) - for x in [uuid() for i in range(10)]]) - r.revoke() - self.assertIn('revoke', MockMailbox.sent) diff --git a/awx/lib/site-packages/celery/tests/app/test_defaults.py b/awx/lib/site-packages/celery/tests/app/test_defaults.py deleted file mode 100644 index bf87f80ae1..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_defaults.py +++ /dev/null @@ -1,60 +0,0 @@ -from __future__ import absolute_import - -import sys - -from importlib import import_module - -from celery.app.defaults import NAMESPACES - -from celery.tests.case import ( - AppCase, Mock, patch, pypy_version, sys_platform, -) - - -class test_defaults(AppCase): - - def setup(self): - self._prev = sys.modules.pop('celery.app.defaults', None) - - def teardown(self): - if self._prev: - sys.modules['celery.app.defaults'] = self._prev - - def test_option_repr(self): - self.assertTrue(repr(NAMESPACES['BROKER']['URL'])) - - def test_any(self): - val = object() - self.assertIs(self.defaults.Option.typemap['any'](val), val) - - def test_default_pool_pypy_14(self): - with sys_platform('darwin'): - with pypy_version((1, 4, 0)): - self.assertEqual(self.defaults.DEFAULT_POOL, 'solo') - - def test_default_pool_pypy_15(self): - with sys_platform('darwin'): - with pypy_version((1, 5, 0)): - self.assertEqual(self.defaults.DEFAULT_POOL, 'prefork') - - def test_deprecated(self): - source = Mock() - source.CELERYD_LOG_LEVEL = 2 - with patch('celery.utils.warn_deprecated') as warn: - self.defaults.find_deprecated_settings(source) - self.assertTrue(warn.called) - - def test_default_pool_jython(self): - with sys_platform('java 1.6.51'): - self.assertEqual(self.defaults.DEFAULT_POOL, 'threads') - - def test_find(self): - find = self.defaults.find - - self.assertEqual(find('server_email')[2].default, 'celery@localhost') - self.assertEqual(find('default_queue')[2].default, 'celery') - self.assertEqual(find('celery_default_exchange')[2], 'celery') - - @property - def defaults(self): - return import_module('celery.app.defaults') diff --git a/awx/lib/site-packages/celery/tests/app/test_exceptions.py b/awx/lib/site-packages/celery/tests/app/test_exceptions.py deleted file mode 100644 index 25d2b4ef81..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_exceptions.py +++ /dev/null @@ -1,35 +0,0 @@ -from __future__ import absolute_import - -import pickle - -from datetime import datetime - -from celery.exceptions import Reject, Retry - -from celery.tests.case import AppCase - - -class test_Retry(AppCase): - - def test_when_datetime(self): - x = Retry('foo', KeyError(), when=datetime.utcnow()) - self.assertTrue(x.humanize()) - - def test_pickleable(self): - x = Retry('foo', KeyError(), when=datetime.utcnow()) - self.assertTrue(pickle.loads(pickle.dumps(x))) - - -class test_Reject(AppCase): - - def test_attrs(self): - x = Reject('foo', requeue=True) - self.assertEqual(x.reason, 'foo') - self.assertTrue(x.requeue) - - def test_repr(self): - self.assertTrue(repr(Reject('foo', True))) - - def test_pickleable(self): - x = Retry('foo', True) - self.assertTrue(pickle.loads(pickle.dumps(x))) diff --git a/awx/lib/site-packages/celery/tests/app/test_loaders.py b/awx/lib/site-packages/celery/tests/app/test_loaders.py deleted file mode 100644 index f1b1bb0378..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_loaders.py +++ /dev/null @@ -1,269 +0,0 @@ -from __future__ import absolute_import - -import os -import sys -import warnings - -from celery import loaders -from celery.exceptions import ( - NotConfigured, -) -from celery.loaders import base -from celery.loaders import default -from celery.loaders.app import AppLoader -from celery.utils.imports import NotAPackage -from celery.utils.mail import SendmailWarning - -from celery.tests.case import ( - AppCase, Case, Mock, depends_on_current_app, patch, with_environ, -) - - -class DummyLoader(base.BaseLoader): - - def read_configuration(self): - return {'foo': 'bar', 'CELERY_IMPORTS': ('os', 'sys')} - - -class test_loaders(AppCase): - - def test_get_loader_cls(self): - self.assertEqual(loaders.get_loader_cls('default'), - default.Loader) - - @depends_on_current_app - def test_current_loader(self): - with self.assertPendingDeprecation(): - self.assertIs(loaders.current_loader(), self.app.loader) - - @depends_on_current_app - def test_load_settings(self): - with self.assertPendingDeprecation(): - self.assertIs(loaders.load_settings(), self.app.conf) - - -class test_LoaderBase(AppCase): - message_options = {'subject': 'Subject', - 'body': 'Body', - 'sender': 'x@x.com', - 'to': 'y@x.com'} - server_options = {'host': 'smtp.x.com', - 'port': 1234, - 'user': 'x', - 'password': 'qwerty', - 'timeout': 3} - - def setup(self): - self.loader = DummyLoader(app=self.app) - - def test_handlers_pass(self): - self.loader.on_task_init('foo.task', 'feedface-cafebabe') - self.loader.on_worker_init() - - def test_now(self): - self.assertTrue(self.loader.now(utc=True)) - self.assertTrue(self.loader.now(utc=False)) - - def test_read_configuration_no_env(self): - self.assertDictEqual( - base.BaseLoader(app=self.app).read_configuration( - 'FOO_X_S_WE_WQ_Q_WE'), - {}, - ) - - def test_autodiscovery(self): - with patch('celery.loaders.base.autodiscover_tasks') as auto: - auto.return_value = [Mock()] - auto.return_value[0].__name__ = 'moo' - self.loader.autodiscover_tasks(['A', 'B']) - self.assertIn('moo', self.loader.task_modules) - self.loader.task_modules.discard('moo') - - def test_import_task_module(self): - self.assertEqual(sys, self.loader.import_task_module('sys')) - - def test_init_worker_process(self): - self.loader.on_worker_process_init() - m = self.loader.on_worker_process_init = Mock() - self.loader.init_worker_process() - m.assert_called_with() - - def test_config_from_object_module(self): - self.loader.import_from_cwd = Mock() - self.loader.config_from_object('module_name') - self.loader.import_from_cwd.assert_called_with('module_name') - - def test_conf_property(self): - self.assertEqual(self.loader.conf['foo'], 'bar') - self.assertEqual(self.loader._conf['foo'], 'bar') - self.assertEqual(self.loader.conf['foo'], 'bar') - - def test_import_default_modules(self): - modnames = lambda l: [m.__name__ for m in l] - self.app.conf.CELERY_IMPORTS = ('os', 'sys') - self.assertEqual( - sorted(modnames(self.loader.import_default_modules())), - sorted(modnames([os, sys])), - ) - - def test_import_from_cwd_custom_imp(self): - - def imp(module, package=None): - imp.called = True - imp.called = False - - self.loader.import_from_cwd('foo', imp=imp) - self.assertTrue(imp.called) - - @patch('celery.utils.mail.Mailer._send') - def test_mail_admins_errors(self, send): - send.side_effect = KeyError() - opts = dict(self.message_options, **self.server_options) - - with self.assertWarnsRegex(SendmailWarning, r'KeyError'): - self.loader.mail_admins(fail_silently=True, **opts) - - with self.assertRaises(KeyError): - self.loader.mail_admins(fail_silently=False, **opts) - - @patch('celery.utils.mail.Mailer._send') - def test_mail_admins(self, send): - opts = dict(self.message_options, **self.server_options) - self.loader.mail_admins(**opts) - self.assertTrue(send.call_args) - message = send.call_args[0][0] - self.assertEqual(message.to, [self.message_options['to']]) - self.assertEqual(message.subject, self.message_options['subject']) - self.assertEqual(message.sender, self.message_options['sender']) - self.assertEqual(message.body, self.message_options['body']) - - def test_mail_attribute(self): - from celery.utils import mail - loader = base.BaseLoader(app=self.app) - self.assertIs(loader.mail, mail) - - def test_cmdline_config_ValueError(self): - with self.assertRaises(ValueError): - self.loader.cmdline_config_parser(['broker.port=foobar']) - - -class test_DefaultLoader(AppCase): - - @patch('celery.loaders.base.find_module') - def test_read_configuration_not_a_package(self, find_module): - find_module.side_effect = NotAPackage() - l = default.Loader(app=self.app) - with self.assertRaises(NotAPackage): - l.read_configuration(fail_silently=False) - - @patch('celery.loaders.base.find_module') - @with_environ('CELERY_CONFIG_MODULE', 'celeryconfig.py') - def test_read_configuration_py_in_name(self, find_module): - find_module.side_effect = NotAPackage() - l = default.Loader(app=self.app) - with self.assertRaises(NotAPackage): - l.read_configuration(fail_silently=False) - - @patch('celery.loaders.base.find_module') - def test_read_configuration_importerror(self, find_module): - default.C_WNOCONF = True - find_module.side_effect = ImportError() - l = default.Loader(app=self.app) - with self.assertWarnsRegex(NotConfigured, r'make sure it exists'): - l.read_configuration(fail_silently=True) - default.C_WNOCONF = False - l.read_configuration(fail_silently=True) - - def test_read_configuration(self): - from types import ModuleType - - class ConfigModule(ModuleType): - pass - - configname = os.environ.get('CELERY_CONFIG_MODULE') or 'celeryconfig' - celeryconfig = ConfigModule(configname) - celeryconfig.CELERY_IMPORTS = ('os', 'sys') - - prevconfig = sys.modules.get(configname) - sys.modules[configname] = celeryconfig - try: - l = default.Loader(app=self.app) - l.find_module = Mock(name='find_module') - settings = l.read_configuration(fail_silently=False) - self.assertTupleEqual(settings.CELERY_IMPORTS, ('os', 'sys')) - settings = l.read_configuration(fail_silently=False) - self.assertTupleEqual(settings.CELERY_IMPORTS, ('os', 'sys')) - l.on_worker_init() - finally: - if prevconfig: - sys.modules[configname] = prevconfig - - def test_import_from_cwd(self): - l = default.Loader(app=self.app) - old_path = list(sys.path) - try: - sys.path.remove(os.getcwd()) - except ValueError: - pass - celery = sys.modules.pop('celery', None) - try: - self.assertTrue(l.import_from_cwd('celery')) - sys.modules.pop('celery', None) - sys.path.insert(0, os.getcwd()) - self.assertTrue(l.import_from_cwd('celery')) - finally: - sys.path = old_path - sys.modules['celery'] = celery - - def test_unconfigured_settings(self): - context_executed = [False] - - class _Loader(default.Loader): - - def find_module(self, name): - raise ImportError(name) - - with warnings.catch_warnings(record=True): - l = _Loader(app=self.app) - self.assertFalse(l.configured) - context_executed[0] = True - self.assertTrue(context_executed[0]) - - -class test_AppLoader(AppCase): - - def setup(self): - self.loader = AppLoader(app=self.app) - - def test_on_worker_init(self): - self.app.conf.CELERY_IMPORTS = ('subprocess', ) - sys.modules.pop('subprocess', None) - self.loader.init_worker() - self.assertIn('subprocess', sys.modules) - - -class test_autodiscovery(Case): - - def test_autodiscover_tasks(self): - base._RACE_PROTECTION = True - try: - base.autodiscover_tasks(['foo']) - finally: - base._RACE_PROTECTION = False - with patch('celery.loaders.base.find_related_module') as frm: - base.autodiscover_tasks(['foo']) - self.assertTrue(frm.called) - - def test_find_related_module(self): - with patch('importlib.import_module') as imp: - with patch('imp.find_module') as find: - imp.return_value = Mock() - imp.return_value.__path__ = 'foo' - base.find_related_module(base, 'tasks') - - imp.side_effect = AttributeError() - base.find_related_module(base, 'tasks') - imp.side_effect = None - - find.side_effect = ImportError() - base.find_related_module(base, 'tasks') diff --git a/awx/lib/site-packages/celery/tests/app/test_log.py b/awx/lib/site-packages/celery/tests/app/test_log.py deleted file mode 100644 index f430d8b5b6..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_log.py +++ /dev/null @@ -1,381 +0,0 @@ -from __future__ import absolute_import - -import sys -import logging - -from collections import defaultdict -from io import StringIO -from tempfile import mktemp - -from celery import signals -from celery.app.log import TaskFormatter -from celery.utils.log import LoggingProxy -from celery.utils import uuid -from celery.utils.log import ( - get_logger, - ColorFormatter, - logger as base_logger, - get_task_logger, - task_logger, - in_sighandler, - logger_isa, - ensure_process_aware_logger, -) -from celery.tests.case import ( - AppCase, Mock, SkipTest, - get_handlers, override_stdouts, patch, wrap_logger, restore_logging, -) - - -class test_TaskFormatter(AppCase): - - def test_no_task(self): - class Record(object): - msg = 'hello world' - levelname = 'info' - exc_text = exc_info = None - stack_info = None - - def getMessage(self): - return self.msg - record = Record() - x = TaskFormatter() - x.format(record) - self.assertEqual(record.task_name, '???') - self.assertEqual(record.task_id, '???') - - -class test_logger_isa(AppCase): - - def test_isa(self): - x = get_task_logger('Z1george') - self.assertTrue(logger_isa(x, task_logger)) - prev_x, x.parent = x.parent, None - try: - self.assertFalse(logger_isa(x, task_logger)) - finally: - x.parent = prev_x - - y = get_task_logger('Z1elaine') - y.parent = x - self.assertTrue(logger_isa(y, task_logger)) - self.assertTrue(logger_isa(y, x)) - self.assertTrue(logger_isa(y, y)) - - z = get_task_logger('Z1jerry') - z.parent = y - self.assertTrue(logger_isa(z, task_logger)) - self.assertTrue(logger_isa(z, y)) - self.assertTrue(logger_isa(z, x)) - self.assertTrue(logger_isa(z, z)) - - def test_recursive(self): - x = get_task_logger('X1foo') - prev, x.parent = x.parent, x - try: - with self.assertRaises(RuntimeError): - logger_isa(x, task_logger) - finally: - x.parent = prev - - y = get_task_logger('X2foo') - z = get_task_logger('X2foo') - prev_y, y.parent = y.parent, z - try: - prev_z, z.parent = z.parent, y - try: - with self.assertRaises(RuntimeError): - logger_isa(y, task_logger) - finally: - z.parent = prev_z - finally: - y.parent = prev_y - - -class test_ColorFormatter(AppCase): - - @patch('celery.utils.log.safe_str') - @patch('logging.Formatter.formatException') - def test_formatException_not_string(self, fe, safe_str): - x = ColorFormatter('HELLO') - value = KeyError() - fe.return_value = value - self.assertIs(x.formatException(value), value) - self.assertTrue(fe.called) - self.assertFalse(safe_str.called) - - @patch('logging.Formatter.formatException') - @patch('celery.utils.log.safe_str') - def test_formatException_string(self, safe_str, fe, value='HELLO'): - x = ColorFormatter(value) - fe.return_value = value - self.assertTrue(x.formatException(value)) - if sys.version_info[0] == 2: - self.assertTrue(safe_str.called) - - @patch('logging.Formatter.format') - def test_format_object(self, _format): - x = ColorFormatter(object()) - x.use_color = True - record = Mock() - record.levelname = 'ERROR' - record.msg = object() - self.assertTrue(x.format(record)) - - @patch('celery.utils.log.safe_str') - def test_format_raises(self, safe_str): - x = ColorFormatter('HELLO') - - def on_safe_str(s): - try: - raise ValueError('foo') - finally: - safe_str.side_effect = None - safe_str.side_effect = on_safe_str - - class Record(object): - levelname = 'ERROR' - msg = 'HELLO' - exc_text = 'error text' - stack_info = None - - def __str__(self): - return on_safe_str('') - - def getMessage(self): - return self.msg - - record = Record() - safe_str.return_value = record - - x.format(record) - self.assertIn('<Unrepresentable', record.msg) - self.assertEqual(safe_str.call_count, 1) - - @patch('celery.utils.log.safe_str') - def test_format_raises_no_color(self, safe_str): - if sys.version_info[0] == 3: - raise SkipTest('py3k') - x = ColorFormatter('HELLO', False) - record = Mock() - record.levelname = 'ERROR' - record.msg = 'HELLO' - record.exc_text = 'error text' - x.format(record) - self.assertEqual(safe_str.call_count, 1) - - -class test_default_logger(AppCase): - - def setup(self): - self.setup_logger = self.app.log.setup_logger - self.get_logger = lambda n=None: get_logger(n) if n else logging.root - signals.setup_logging.receivers[:] = [] - self.app.log.already_setup = False - - def test_get_logger_sets_parent(self): - logger = get_logger('celery.test_get_logger') - self.assertEqual(logger.parent.name, base_logger.name) - - def test_get_logger_root(self): - logger = get_logger(base_logger.name) - self.assertIs(logger.parent, logging.root) - - def test_setup_logging_subsystem_misc(self): - with restore_logging(): - self.app.log.setup_logging_subsystem(loglevel=None) - - def test_setup_logging_subsystem_misc2(self): - with restore_logging(): - self.app.conf.CELERYD_HIJACK_ROOT_LOGGER = True - self.app.log.setup_logging_subsystem() - - def test_get_default_logger(self): - self.assertTrue(self.app.log.get_default_logger()) - - def test_configure_logger(self): - logger = self.app.log.get_default_logger() - self.app.log._configure_logger(logger, sys.stderr, None, '', False) - logger.handlers[:] = [] - - def test_setup_logging_subsystem_colorize(self): - with restore_logging(): - self.app.log.setup_logging_subsystem(colorize=None) - self.app.log.setup_logging_subsystem(colorize=True) - - def test_setup_logging_subsystem_no_mputil(self): - from celery.utils import log as logtools - with restore_logging(): - mputil, logtools.mputil = logtools.mputil, None - try: - self.app.log.setup_logging_subsystem() - finally: - logtools.mputil = mputil - - def _assertLog(self, logger, logmsg, loglevel=logging.ERROR): - - with wrap_logger(logger, loglevel=loglevel) as sio: - logger.log(loglevel, logmsg) - return sio.getvalue().strip() - - def assertDidLogTrue(self, logger, logmsg, reason, loglevel=None): - val = self._assertLog(logger, logmsg, loglevel=loglevel) - return self.assertEqual(val, logmsg, reason) - - def assertDidLogFalse(self, logger, logmsg, reason, loglevel=None): - val = self._assertLog(logger, logmsg, loglevel=loglevel) - return self.assertFalse(val, reason) - - def test_setup_logger(self): - with restore_logging(): - logger = self.setup_logger(loglevel=logging.ERROR, logfile=None, - root=False, colorize=True) - logger.handlers = [] - self.app.log.already_setup = False - logger = self.setup_logger(loglevel=logging.ERROR, logfile=None, - root=False, colorize=None) - self.assertIs( - get_handlers(logger)[0].stream, sys.__stderr__, - 'setup_logger logs to stderr without logfile argument.', - ) - - def test_setup_logger_no_handlers_stream(self): - with restore_logging(): - l = self.get_logger() - l.handlers = [] - - with override_stdouts() as outs: - stdout, stderr = outs - l = self.setup_logger(logfile=sys.stderr, - loglevel=logging.INFO, root=False) - l.info('The quick brown fox...') - self.assertIn('The quick brown fox...', stderr.getvalue()) - - @patch('os.fstat') - def test_setup_logger_no_handlers_file(self, *args): - tempfile = mktemp(suffix='unittest', prefix='celery') - _open = ('builtins.open' if sys.version_info[0] == 3 - else '__builtin__.open') - with patch(_open) as osopen: - with restore_logging(): - files = defaultdict(StringIO) - - def open_file(filename, *args, **kwargs): - f = files[filename] - f.fileno = Mock() - f.fileno.return_value = 99 - return f - - osopen.side_effect = open_file - l = self.get_logger() - l.handlers = [] - l = self.setup_logger( - logfile=tempfile, loglevel=logging.INFO, root=False, - ) - self.assertIsInstance( - get_handlers(l)[0], logging.FileHandler, - ) - self.assertIn(tempfile, files) - - def test_redirect_stdouts(self): - with restore_logging(): - logger = self.setup_logger(loglevel=logging.ERROR, logfile=None, - root=False) - try: - with wrap_logger(logger) as sio: - self.app.log.redirect_stdouts_to_logger( - logger, loglevel=logging.ERROR, - ) - logger.error('foo') - self.assertIn('foo', sio.getvalue()) - self.app.log.redirect_stdouts_to_logger( - logger, stdout=False, stderr=False, - ) - finally: - sys.stdout, sys.stderr = sys.__stdout__, sys.__stderr__ - - def test_logging_proxy(self): - with restore_logging(): - logger = self.setup_logger(loglevel=logging.ERROR, logfile=None, - root=False) - - with wrap_logger(logger) as sio: - p = LoggingProxy(logger, loglevel=logging.ERROR) - p.close() - p.write('foo') - self.assertNotIn('foo', sio.getvalue()) - p.closed = False - p.write('foo') - self.assertIn('foo', sio.getvalue()) - lines = ['baz', 'xuzzy'] - p.writelines(lines) - for line in lines: - self.assertIn(line, sio.getvalue()) - p.flush() - p.close() - self.assertFalse(p.isatty()) - - with override_stdouts() as (stdout, stderr): - with in_sighandler(): - p.write('foo') - self.assertTrue(stderr.getvalue()) - - def test_logging_proxy_recurse_protection(self): - with restore_logging(): - logger = self.setup_logger(loglevel=logging.ERROR, logfile=None, - root=False) - p = LoggingProxy(logger, loglevel=logging.ERROR) - p._thread.recurse_protection = True - try: - self.assertIsNone(p.write('FOOFO')) - finally: - p._thread.recurse_protection = False - - -class test_task_logger(test_default_logger): - - def setup(self): - logger = self.logger = get_logger('celery.task') - logger.handlers = [] - logging.root.manager.loggerDict.pop(logger.name, None) - self.uid = uuid() - - @self.app.task(shared=False) - def test_task(): - pass - self.get_logger().handlers = [] - self.task = test_task - from celery._state import _task_stack - _task_stack.push(test_task) - - def teardown(self): - from celery._state import _task_stack - _task_stack.pop() - - def setup_logger(self, *args, **kwargs): - return self.app.log.setup_task_loggers(*args, **kwargs) - - def get_logger(self, *args, **kwargs): - return get_task_logger('test_task_logger') - - -class test_patch_logger_cls(AppCase): - - def test_patches(self): - ensure_process_aware_logger() - with in_sighandler(): - logging.getLoggerClass().log(get_logger('test')) - - -class MockLogger(logging.Logger): - _records = None - - def __init__(self, *args, **kwargs): - self._records = [] - logging.Logger.__init__(self, *args, **kwargs) - - def handle(self, record): - self._records.append(record) - - def isEnabledFor(self, level): - return True diff --git a/awx/lib/site-packages/celery/tests/app/test_registry.py b/awx/lib/site-packages/celery/tests/app/test_registry.py deleted file mode 100644 index 88548062ab..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_registry.py +++ /dev/null @@ -1,78 +0,0 @@ -from __future__ import absolute_import - -from celery.app.registry import _unpickle_task, _unpickle_task_v2 -from celery.tests.case import AppCase, depends_on_current_app - - -def returns(): - return 1 - - -class test_unpickle_task(AppCase): - - @depends_on_current_app - def test_unpickle_v1(self): - self.app.tasks['txfoo'] = 'bar' - self.assertEqual(_unpickle_task('txfoo'), 'bar') - - @depends_on_current_app - def test_unpickle_v2(self): - self.app.tasks['txfoo1'] = 'bar1' - self.assertEqual(_unpickle_task_v2('txfoo1'), 'bar1') - self.assertEqual(_unpickle_task_v2('txfoo1', module='celery'), 'bar1') - - -class test_TaskRegistry(AppCase): - - def setup(self): - self.mytask = self.app.task(name='A', shared=False)(returns) - self.myperiodic = self.app.task( - name='B', shared=False, type='periodic', - )(returns) - - def test_NotRegistered_str(self): - self.assertTrue(repr(self.app.tasks.NotRegistered('tasks.add'))) - - def assertRegisterUnregisterCls(self, r, task): - r.unregister(task) - with self.assertRaises(r.NotRegistered): - r.unregister(task) - r.register(task) - self.assertIn(task.name, r) - - def assertRegisterUnregisterFunc(self, r, task, task_name): - with self.assertRaises(r.NotRegistered): - r.unregister(task_name) - r.register(task, task_name) - self.assertIn(task_name, r) - - def test_task_registry(self): - r = self.app._tasks - self.assertIsInstance(r, dict, 'TaskRegistry is mapping') - - self.assertRegisterUnregisterCls(r, self.mytask) - self.assertRegisterUnregisterCls(r, self.myperiodic) - - r.register(self.myperiodic) - r.unregister(self.myperiodic.name) - self.assertNotIn(self.myperiodic, r) - r.register(self.myperiodic) - - tasks = dict(r) - self.assertIs(tasks.get(self.mytask.name), self.mytask) - self.assertIs(tasks.get(self.myperiodic.name), self.myperiodic) - - self.assertIs(r[self.mytask.name], self.mytask) - self.assertIs(r[self.myperiodic.name], self.myperiodic) - - r.unregister(self.mytask) - self.assertNotIn(self.mytask.name, r) - r.unregister(self.myperiodic) - self.assertNotIn(self.myperiodic.name, r) - - self.assertTrue(self.mytask.run()) - self.assertTrue(self.myperiodic.run()) - - def test_compat(self): - self.assertTrue(self.app.tasks.regular()) - self.assertTrue(self.app.tasks.periodic()) diff --git a/awx/lib/site-packages/celery/tests/app/test_routes.py b/awx/lib/site-packages/celery/tests/app/test_routes.py deleted file mode 100644 index bbc53b4d3f..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_routes.py +++ /dev/null @@ -1,158 +0,0 @@ -from __future__ import absolute_import - -from kombu import Exchange -from kombu.utils.functional import maybe_evaluate - -from celery.app import routes -from celery.exceptions import QueueNotFound -from celery.utils.functional import LRUCache - -from celery.tests.case import AppCase - - -def Router(app, *args, **kwargs): - return routes.Router(*args, app=app, **kwargs) - - -def E(app, queues): - def expand(answer): - return Router(app, [], queues).expand_destination(answer) - return expand - - -def set_queues(app, **queues): - app.conf.CELERY_QUEUES = queues - app.amqp.queues = app.amqp.Queues(queues) - - -class RouteCase(AppCase): - - def setup(self): - self.a_queue = { - 'exchange': 'fooexchange', - 'exchange_type': 'fanout', - 'routing_key': 'xuzzy', - } - self.b_queue = { - 'exchange': 'barexchange', - 'exchange_type': 'topic', - 'routing_key': 'b.b.#', - } - self.d_queue = { - 'exchange': self.app.conf.CELERY_DEFAULT_EXCHANGE, - 'exchange_type': self.app.conf.CELERY_DEFAULT_EXCHANGE_TYPE, - 'routing_key': self.app.conf.CELERY_DEFAULT_ROUTING_KEY, - } - - @self.app.task(shared=False) - def mytask(): - pass - self.mytask = mytask - - -class test_MapRoute(RouteCase): - - def test_route_for_task_expanded_route(self): - set_queues(self.app, foo=self.a_queue, bar=self.b_queue) - expand = E(self.app, self.app.amqp.queues) - route = routes.MapRoute({self.mytask.name: {'queue': 'foo'}}) - self.assertEqual( - expand(route.route_for_task(self.mytask.name))['queue'].name, - 'foo', - ) - self.assertIsNone(route.route_for_task('celery.awesome')) - - def test_route_for_task(self): - set_queues(self.app, foo=self.a_queue, bar=self.b_queue) - expand = E(self.app, self.app.amqp.queues) - route = routes.MapRoute({self.mytask.name: self.b_queue}) - self.assertDictContainsSubset( - self.b_queue, - expand(route.route_for_task(self.mytask.name)), - ) - self.assertIsNone(route.route_for_task('celery.awesome')) - - def test_expand_route_not_found(self): - expand = E(self.app, self.app.amqp.Queues( - self.app.conf.CELERY_QUEUES, False)) - route = routes.MapRoute({'a': {'queue': 'x'}}) - with self.assertRaises(QueueNotFound): - expand(route.route_for_task('a')) - - -class test_lookup_route(RouteCase): - - def test_init_queues(self): - router = Router(self.app, queues=None) - self.assertDictEqual(router.queues, {}) - - def test_lookup_takes_first(self): - set_queues(self.app, foo=self.a_queue, bar=self.b_queue) - R = routes.prepare(({self.mytask.name: {'queue': 'bar'}}, - {self.mytask.name: {'queue': 'foo'}})) - router = Router(self.app, R, self.app.amqp.queues) - self.assertEqual(router.route({}, self.mytask.name, - args=[1, 2], kwargs={})['queue'].name, 'bar') - - def test_expands_queue_in_options(self): - set_queues(self.app) - R = routes.prepare(()) - router = Router( - self.app, R, self.app.amqp.queues, create_missing=True, - ) - # apply_async forwards all arguments, even exchange=None etc, - # so need to make sure it's merged correctly. - route = router.route( - {'queue': 'testq', - 'exchange': None, - 'routing_key': None, - 'immediate': False}, - self.mytask.name, - args=[1, 2], kwargs={}, - ) - self.assertEqual(route['queue'].name, 'testq') - self.assertEqual(route['queue'].exchange, Exchange('testq')) - self.assertEqual(route['queue'].routing_key, 'testq') - self.assertEqual(route['immediate'], False) - - def test_expand_destination_string(self): - set_queues(self.app, foo=self.a_queue, bar=self.b_queue) - x = Router(self.app, {}, self.app.amqp.queues) - dest = x.expand_destination('foo') - self.assertEqual(dest['queue'].name, 'foo') - - def test_lookup_paths_traversed(self): - set_queues( - self.app, foo=self.a_queue, bar=self.b_queue, - **{self.app.conf.CELERY_DEFAULT_QUEUE: self.d_queue} - ) - R = routes.prepare(( - {'celery.xaza': {'queue': 'bar'}}, - {self.mytask.name: {'queue': 'foo'}} - )) - router = Router(self.app, R, self.app.amqp.queues) - self.assertEqual(router.route({}, self.mytask.name, - args=[1, 2], kwargs={})['queue'].name, 'foo') - self.assertEqual( - router.route({}, 'celery.poza')['queue'].name, - self.app.conf.CELERY_DEFAULT_QUEUE, - ) - - -class test_prepare(AppCase): - - def test_prepare(self): - o = object() - R = [{'foo': 'bar'}, - 'celery.utils.functional.LRUCache', o] - p = routes.prepare(R) - self.assertIsInstance(p[0], routes.MapRoute) - self.assertIsInstance(maybe_evaluate(p[1]), LRUCache) - self.assertIs(p[2], o) - - self.assertEqual(routes.prepare(o), [o]) - - def test_prepare_item_is_dict(self): - R = {'foo': 'bar'} - p = routes.prepare(R) - self.assertIsInstance(p[0], routes.MapRoute) diff --git a/awx/lib/site-packages/celery/tests/app/test_schedules.py b/awx/lib/site-packages/celery/tests/app/test_schedules.py deleted file mode 100644 index 8cb3d6d4c7..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_schedules.py +++ /dev/null @@ -1,717 +0,0 @@ -from __future__ import absolute_import - -import time - -from contextlib import contextmanager -from datetime import datetime, timedelta -from pickle import dumps, loads - -from celery.five import items -from celery.schedules import ParseException, crontab, crontab_parser -from celery.tests.case import AppCase, SkipTest - - -@contextmanager -def patch_crontab_nowfun(cls, retval): - prev_nowfun = cls.nowfun - cls.nowfun = lambda: retval - try: - yield - finally: - cls.nowfun = prev_nowfun - - -class test_crontab_parser(AppCase): - - def crontab(self, *args, **kwargs): - return crontab(*args, **dict(kwargs, app=self.app)) - - def test_crontab_reduce(self): - self.assertTrue(loads(dumps(self.crontab('*')))) - - def test_range_steps_not_enough(self): - with self.assertRaises(crontab_parser.ParseException): - crontab_parser(24)._range_steps([1]) - - def test_parse_star(self): - self.assertEqual(crontab_parser(24).parse('*'), set(range(24))) - self.assertEqual(crontab_parser(60).parse('*'), set(range(60))) - self.assertEqual(crontab_parser(7).parse('*'), set(range(7))) - self.assertEqual(crontab_parser(31, 1).parse('*'), - set(range(1, 31 + 1))) - self.assertEqual(crontab_parser(12, 1).parse('*'), - set(range(1, 12 + 1))) - - def test_parse_range(self): - self.assertEqual(crontab_parser(60).parse('1-10'), - set(range(1, 10 + 1))) - self.assertEqual(crontab_parser(24).parse('0-20'), - set(range(0, 20 + 1))) - self.assertEqual(crontab_parser().parse('2-10'), - set(range(2, 10 + 1))) - self.assertEqual(crontab_parser(60, 1).parse('1-10'), - set(range(1, 10 + 1))) - - def test_parse_range_wraps(self): - self.assertEqual(crontab_parser(12).parse('11-1'), - set([11, 0, 1])) - self.assertEqual(crontab_parser(60, 1).parse('2-1'), - set(range(1, 60 + 1))) - - def test_parse_groups(self): - self.assertEqual(crontab_parser().parse('1,2,3,4'), - set([1, 2, 3, 4])) - self.assertEqual(crontab_parser().parse('0,15,30,45'), - set([0, 15, 30, 45])) - self.assertEqual(crontab_parser(min_=1).parse('1,2,3,4'), - set([1, 2, 3, 4])) - - def test_parse_steps(self): - self.assertEqual(crontab_parser(8).parse('*/2'), - set([0, 2, 4, 6])) - self.assertEqual(crontab_parser().parse('*/2'), - set(i * 2 for i in range(30))) - self.assertEqual(crontab_parser().parse('*/3'), - set(i * 3 for i in range(20))) - self.assertEqual(crontab_parser(8, 1).parse('*/2'), - set([1, 3, 5, 7])) - self.assertEqual(crontab_parser(min_=1).parse('*/2'), - set(i * 2 + 1 for i in range(30))) - self.assertEqual(crontab_parser(min_=1).parse('*/3'), - set(i * 3 + 1 for i in range(20))) - - def test_parse_composite(self): - self.assertEqual(crontab_parser(8).parse('*/2'), set([0, 2, 4, 6])) - self.assertEqual(crontab_parser().parse('2-9/5'), set([2, 7])) - self.assertEqual(crontab_parser().parse('2-10/5'), set([2, 7])) - self.assertEqual( - crontab_parser(min_=1).parse('55-5/3'), - set([55, 58, 1, 4]), - ) - self.assertEqual(crontab_parser().parse('2-11/5,3'), set([2, 3, 7])) - self.assertEqual( - crontab_parser().parse('2-4/3,*/5,0-21/4'), - set([0, 2, 4, 5, 8, 10, 12, 15, 16, - 20, 25, 30, 35, 40, 45, 50, 55]), - ) - self.assertEqual( - crontab_parser().parse('1-9/2'), - set([1, 3, 5, 7, 9]), - ) - self.assertEqual(crontab_parser(8, 1).parse('*/2'), set([1, 3, 5, 7])) - self.assertEqual(crontab_parser(min_=1).parse('2-9/5'), set([2, 7])) - self.assertEqual(crontab_parser(min_=1).parse('2-10/5'), set([2, 7])) - self.assertEqual( - crontab_parser(min_=1).parse('2-11/5,3'), - set([2, 3, 7]), - ) - self.assertEqual( - crontab_parser(min_=1).parse('2-4/3,*/5,1-21/4'), - set([1, 2, 5, 6, 9, 11, 13, 16, 17, - 21, 26, 31, 36, 41, 46, 51, 56]), - ) - self.assertEqual( - crontab_parser(min_=1).parse('1-9/2'), - set([1, 3, 5, 7, 9]), - ) - - def test_parse_errors_on_empty_string(self): - with self.assertRaises(ParseException): - crontab_parser(60).parse('') - - def test_parse_errors_on_empty_group(self): - with self.assertRaises(ParseException): - crontab_parser(60).parse('1,,2') - - def test_parse_errors_on_empty_steps(self): - with self.assertRaises(ParseException): - crontab_parser(60).parse('*/') - - def test_parse_errors_on_negative_number(self): - with self.assertRaises(ParseException): - crontab_parser(60).parse('-20') - - def test_parse_errors_on_lt_min(self): - crontab_parser(min_=1).parse('1') - with self.assertRaises(ValueError): - crontab_parser(12, 1).parse('0') - with self.assertRaises(ValueError): - crontab_parser(24, 1).parse('12-0') - - def test_parse_errors_on_gt_max(self): - crontab_parser(1).parse('0') - with self.assertRaises(ValueError): - crontab_parser(1).parse('1') - with self.assertRaises(ValueError): - crontab_parser(60).parse('61-0') - - def test_expand_cronspec_eats_iterables(self): - self.assertEqual( - crontab._expand_cronspec(iter([1, 2, 3]), 100), - set([1, 2, 3]), - ) - self.assertEqual( - crontab._expand_cronspec(iter([1, 2, 3]), 100, 1), - set([1, 2, 3]), - ) - - def test_expand_cronspec_invalid_type(self): - with self.assertRaises(TypeError): - crontab._expand_cronspec(object(), 100) - - def test_repr(self): - self.assertIn('*', repr(self.crontab('*'))) - - def test_eq(self): - self.assertEqual( - self.crontab(day_of_week='1, 2'), - self.crontab(day_of_week='1-2'), - ) - self.assertEqual( - self.crontab(day_of_month='1, 16, 31'), - self.crontab(day_of_month='*/15'), - ) - self.assertEqual( - self.crontab(minute='1', hour='2', day_of_week='5', - day_of_month='10', month_of_year='5'), - self.crontab(minute='1', hour='2', day_of_week='5', - day_of_month='10', month_of_year='5'), - ) - self.assertNotEqual(crontab(minute='1'), crontab(minute='2')) - self.assertNotEqual( - self.crontab(month_of_year='1'), - self.crontab(month_of_year='2'), - ) - self.assertFalse(object() == self.crontab(minute='1')) - self.assertFalse(self.crontab(minute='1') == object()) - - -class test_crontab_remaining_estimate(AppCase): - - def crontab(self, *args, **kwargs): - return crontab(*args, **dict(kwargs, app=self.app)) - - def next_ocurrance(self, crontab, now): - crontab.nowfun = lambda: now - return now + crontab.remaining_estimate(now) - - def test_next_minute(self): - next = self.next_ocurrance( - self.crontab(), datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 11, 14, 31)) - - def test_not_next_minute(self): - next = self.next_ocurrance( - self.crontab(), datetime(2010, 9, 11, 14, 59, 15), - ) - self.assertEqual(next, datetime(2010, 9, 11, 15, 0)) - - def test_this_hour(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42]), datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 11, 14, 42)) - - def test_not_this_hour(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 10, 15]), - datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 11, 15, 5)) - - def test_today(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], hour=[12, 17]), - datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 11, 17, 5)) - - def test_not_today(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], hour=[12]), - datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 12, 12, 5)) - - def test_weekday(self): - next = self.next_ocurrance( - self.crontab(minute=30, hour=14, day_of_week='sat'), - datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 18, 14, 30)) - - def test_not_weekday(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='mon-fri'), - datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 13, 0, 5)) - - def test_monthday(self): - next = self.next_ocurrance( - self.crontab(minute=30, hour=14, day_of_month=18), - datetime(2010, 9, 11, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 9, 18, 14, 30)) - - def test_not_monthday(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_month=29), - datetime(2010, 1, 22, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 1, 29, 0, 5)) - - def test_weekday_monthday(self): - next = self.next_ocurrance( - self.crontab(minute=30, hour=14, - day_of_week='mon', day_of_month=18), - datetime(2010, 1, 18, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 10, 18, 14, 30)) - - def test_monthday_not_weekday(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='sat', day_of_month=29), - datetime(2010, 1, 29, 0, 5, 15), - ) - self.assertEqual(next, datetime(2010, 5, 29, 0, 5)) - - def test_weekday_not_monthday(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='mon', day_of_month=18), - datetime(2010, 1, 11, 0, 5, 15), - ) - self.assertEqual(next, datetime(2010, 1, 18, 0, 5)) - - def test_not_weekday_not_monthday(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='mon', day_of_month=18), - datetime(2010, 1, 10, 0, 5, 15), - ) - self.assertEqual(next, datetime(2010, 1, 18, 0, 5)) - - def test_leapday(self): - next = self.next_ocurrance( - self.crontab(minute=30, hour=14, day_of_month=29), - datetime(2012, 1, 29, 14, 30, 15), - ) - self.assertEqual(next, datetime(2012, 2, 29, 14, 30)) - - def test_not_leapday(self): - next = self.next_ocurrance( - self.crontab(minute=30, hour=14, day_of_month=29), - datetime(2010, 1, 29, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 3, 29, 14, 30)) - - def test_weekmonthdayyear(self): - next = self.next_ocurrance( - self.crontab(minute=30, hour=14, day_of_week='fri', - day_of_month=29, month_of_year=1), - datetime(2010, 1, 22, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 1, 29, 14, 30)) - - def test_monthdayyear_not_week(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='wed,thu', - day_of_month=29, month_of_year='1,4,7'), - datetime(2010, 1, 29, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 4, 29, 0, 5)) - - def test_weekdaymonthyear_not_monthday(self): - next = self.next_ocurrance( - self.crontab(minute=30, hour=14, day_of_week='fri', - day_of_month=29, month_of_year='1-10'), - datetime(2010, 1, 29, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 10, 29, 14, 30)) - - def test_weekmonthday_not_monthyear(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='fri', - day_of_month=29, month_of_year='2-10'), - datetime(2010, 1, 29, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 10, 29, 0, 5)) - - def test_weekday_not_monthdayyear(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='mon', - day_of_month=18, month_of_year='2-10'), - datetime(2010, 1, 11, 0, 5, 15), - ) - self.assertEqual(next, datetime(2010, 10, 18, 0, 5)) - - def test_monthday_not_weekdaymonthyear(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='mon', - day_of_month=29, month_of_year='2-4'), - datetime(2010, 1, 29, 0, 5, 15), - ) - self.assertEqual(next, datetime(2010, 3, 29, 0, 5)) - - def test_monthyear_not_weekmonthday(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='mon', - day_of_month=29, month_of_year='2-4'), - datetime(2010, 2, 28, 0, 5, 15), - ) - self.assertEqual(next, datetime(2010, 3, 29, 0, 5)) - - def test_not_weekmonthdayyear(self): - next = self.next_ocurrance( - self.crontab(minute=[5, 42], day_of_week='fri,sat', - day_of_month=29, month_of_year='2-10'), - datetime(2010, 1, 28, 14, 30, 15), - ) - self.assertEqual(next, datetime(2010, 5, 29, 0, 5)) - - -class test_crontab_is_due(AppCase): - - def getnow(self): - return self.app.now() - - def setup(self): - self.now = self.getnow() - self.next_minute = 60 - self.now.second - 1e-6 * self.now.microsecond - self.every_minute = self.crontab() - self.quarterly = self.crontab(minute='*/15') - self.hourly = self.crontab(minute=30) - self.daily = self.crontab(hour=7, minute=30) - self.weekly = self.crontab(hour=7, minute=30, day_of_week='thursday') - self.monthly = self.crontab( - hour=7, minute=30, day_of_week='thursday', day_of_month='8-14', - ) - self.monthly_moy = self.crontab( - hour=22, day_of_week='*', month_of_year='2', - day_of_month='26,27,28', - ) - self.yearly = self.crontab( - hour=7, minute=30, day_of_week='thursday', - day_of_month='8-14', month_of_year=3, - ) - - def crontab(self, *args, **kwargs): - return crontab(*args, **dict(kwargs, app=self.app)) - - def test_default_crontab_spec(self): - c = self.crontab() - self.assertEqual(c.minute, set(range(60))) - self.assertEqual(c.hour, set(range(24))) - self.assertEqual(c.day_of_week, set(range(7))) - self.assertEqual(c.day_of_month, set(range(1, 32))) - self.assertEqual(c.month_of_year, set(range(1, 13))) - - def test_simple_crontab_spec(self): - c = self.crontab(minute=30) - self.assertEqual(c.minute, set([30])) - self.assertEqual(c.hour, set(range(24))) - self.assertEqual(c.day_of_week, set(range(7))) - self.assertEqual(c.day_of_month, set(range(1, 32))) - self.assertEqual(c.month_of_year, set(range(1, 13))) - - def test_crontab_spec_minute_formats(self): - c = self.crontab(minute=30) - self.assertEqual(c.minute, set([30])) - c = self.crontab(minute='30') - self.assertEqual(c.minute, set([30])) - c = self.crontab(minute=(30, 40, 50)) - self.assertEqual(c.minute, set([30, 40, 50])) - c = self.crontab(minute=set([30, 40, 50])) - self.assertEqual(c.minute, set([30, 40, 50])) - - def test_crontab_spec_invalid_minute(self): - with self.assertRaises(ValueError): - self.crontab(minute=60) - with self.assertRaises(ValueError): - self.crontab(minute='0-100') - - def test_crontab_spec_hour_formats(self): - c = self.crontab(hour=6) - self.assertEqual(c.hour, set([6])) - c = self.crontab(hour='5') - self.assertEqual(c.hour, set([5])) - c = self.crontab(hour=(4, 8, 12)) - self.assertEqual(c.hour, set([4, 8, 12])) - - def test_crontab_spec_invalid_hour(self): - with self.assertRaises(ValueError): - self.crontab(hour=24) - with self.assertRaises(ValueError): - self.crontab(hour='0-30') - - def test_crontab_spec_dow_formats(self): - c = self.crontab(day_of_week=5) - self.assertEqual(c.day_of_week, set([5])) - c = self.crontab(day_of_week='5') - self.assertEqual(c.day_of_week, set([5])) - c = self.crontab(day_of_week='fri') - self.assertEqual(c.day_of_week, set([5])) - c = self.crontab(day_of_week='tuesday,sunday,fri') - self.assertEqual(c.day_of_week, set([0, 2, 5])) - c = self.crontab(day_of_week='mon-fri') - self.assertEqual(c.day_of_week, set([1, 2, 3, 4, 5])) - c = self.crontab(day_of_week='*/2') - self.assertEqual(c.day_of_week, set([0, 2, 4, 6])) - - def test_crontab_spec_invalid_dow(self): - with self.assertRaises(ValueError): - self.crontab(day_of_week='fooday-barday') - with self.assertRaises(ValueError): - self.crontab(day_of_week='1,4,foo') - with self.assertRaises(ValueError): - self.crontab(day_of_week='7') - with self.assertRaises(ValueError): - self.crontab(day_of_week='12') - - def test_crontab_spec_dom_formats(self): - c = self.crontab(day_of_month=5) - self.assertEqual(c.day_of_month, set([5])) - c = self.crontab(day_of_month='5') - self.assertEqual(c.day_of_month, set([5])) - c = self.crontab(day_of_month='2,4,6') - self.assertEqual(c.day_of_month, set([2, 4, 6])) - c = self.crontab(day_of_month='*/5') - self.assertEqual(c.day_of_month, set([1, 6, 11, 16, 21, 26, 31])) - - def test_crontab_spec_invalid_dom(self): - with self.assertRaises(ValueError): - self.crontab(day_of_month=0) - with self.assertRaises(ValueError): - self.crontab(day_of_month='0-10') - with self.assertRaises(ValueError): - self.crontab(day_of_month=32) - with self.assertRaises(ValueError): - self.crontab(day_of_month='31,32') - - def test_crontab_spec_moy_formats(self): - c = self.crontab(month_of_year=1) - self.assertEqual(c.month_of_year, set([1])) - c = self.crontab(month_of_year='1') - self.assertEqual(c.month_of_year, set([1])) - c = self.crontab(month_of_year='2,4,6') - self.assertEqual(c.month_of_year, set([2, 4, 6])) - c = self.crontab(month_of_year='*/2') - self.assertEqual(c.month_of_year, set([1, 3, 5, 7, 9, 11])) - c = self.crontab(month_of_year='2-12/2') - self.assertEqual(c.month_of_year, set([2, 4, 6, 8, 10, 12])) - - def test_crontab_spec_invalid_moy(self): - with self.assertRaises(ValueError): - self.crontab(month_of_year=0) - with self.assertRaises(ValueError): - self.crontab(month_of_year='0-5') - with self.assertRaises(ValueError): - self.crontab(month_of_year=13) - with self.assertRaises(ValueError): - self.crontab(month_of_year='12,13') - - def seconds_almost_equal(self, a, b, precision): - for index, skew in enumerate((+0.1, 0, -0.1)): - try: - self.assertAlmostEqual(a, b + skew, precision) - except AssertionError: - if index + 1 >= 3: - raise - else: - break - - def assertRelativedelta(self, due, last_ran): - try: - from dateutil.relativedelta import relativedelta - except ImportError: - return - l1, d1, n1 = due.remaining_delta(last_ran) - l2, d2, n2 = due.remaining_delta(last_ran, ffwd=relativedelta) - if not isinstance(d1, relativedelta): - self.assertEqual(l1, l2) - for field, value in items(d1._fields()): - self.assertEqual(getattr(d1, field), value) - self.assertFalse(d2.years) - self.assertFalse(d2.months) - self.assertFalse(d2.days) - self.assertFalse(d2.leapdays) - self.assertFalse(d2.hours) - self.assertFalse(d2.minutes) - self.assertFalse(d2.seconds) - self.assertFalse(d2.microseconds) - - def test_every_minute_execution_is_due(self): - last_ran = self.now - timedelta(seconds=61) - due, remaining = self.every_minute.is_due(last_ran) - self.assertRelativedelta(self.every_minute, last_ran) - self.assertTrue(due) - self.seconds_almost_equal(remaining, self.next_minute, 1) - - def test_every_minute_execution_is_not_due(self): - last_ran = self.now - timedelta(seconds=self.now.second) - due, remaining = self.every_minute.is_due(last_ran) - self.assertFalse(due) - self.seconds_almost_equal(remaining, self.next_minute, 1) - - def test_execution_is_due_on_saturday(self): - # 29th of May 2010 is a saturday - with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 29, 10, 30)): - last_ran = self.now - timedelta(seconds=61) - due, remaining = self.every_minute.is_due(last_ran) - self.assertTrue(due) - self.seconds_almost_equal(remaining, self.next_minute, 1) - - def test_execution_is_due_on_sunday(self): - # 30th of May 2010 is a sunday - with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 30, 10, 30)): - last_ran = self.now - timedelta(seconds=61) - due, remaining = self.every_minute.is_due(last_ran) - self.assertTrue(due) - self.seconds_almost_equal(remaining, self.next_minute, 1) - - def test_execution_is_due_on_monday(self): - # 31st of May 2010 is a monday - with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 31, 10, 30)): - last_ran = self.now - timedelta(seconds=61) - due, remaining = self.every_minute.is_due(last_ran) - self.assertTrue(due) - self.seconds_almost_equal(remaining, self.next_minute, 1) - - def test_every_hour_execution_is_due(self): - with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 10, 10, 30)): - due, remaining = self.hourly.is_due(datetime(2010, 5, 10, 6, 30)) - self.assertTrue(due) - self.assertEqual(remaining, 60 * 60) - - def test_every_hour_execution_is_not_due(self): - with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 10, 10, 29)): - due, remaining = self.hourly.is_due(datetime(2010, 5, 10, 9, 30)) - self.assertFalse(due) - self.assertEqual(remaining, 60) - - def test_first_quarter_execution_is_due(self): - with patch_crontab_nowfun( - self.quarterly, datetime(2010, 5, 10, 10, 15)): - due, remaining = self.quarterly.is_due( - datetime(2010, 5, 10, 6, 30), - ) - self.assertTrue(due) - self.assertEqual(remaining, 15 * 60) - - def test_second_quarter_execution_is_due(self): - with patch_crontab_nowfun( - self.quarterly, datetime(2010, 5, 10, 10, 30)): - due, remaining = self.quarterly.is_due( - datetime(2010, 5, 10, 6, 30), - ) - self.assertTrue(due) - self.assertEqual(remaining, 15 * 60) - - def test_first_quarter_execution_is_not_due(self): - with patch_crontab_nowfun( - self.quarterly, datetime(2010, 5, 10, 10, 14)): - due, remaining = self.quarterly.is_due( - datetime(2010, 5, 10, 10, 0), - ) - self.assertFalse(due) - self.assertEqual(remaining, 60) - - def test_second_quarter_execution_is_not_due(self): - with patch_crontab_nowfun( - self.quarterly, datetime(2010, 5, 10, 10, 29)): - due, remaining = self.quarterly.is_due( - datetime(2010, 5, 10, 10, 15), - ) - self.assertFalse(due) - self.assertEqual(remaining, 60) - - def test_daily_execution_is_due(self): - with patch_crontab_nowfun(self.daily, datetime(2010, 5, 10, 7, 30)): - due, remaining = self.daily.is_due(datetime(2010, 5, 9, 7, 30)) - self.assertTrue(due) - self.assertEqual(remaining, 24 * 60 * 60) - - def test_daily_execution_is_not_due(self): - with patch_crontab_nowfun(self.daily, datetime(2010, 5, 10, 10, 30)): - due, remaining = self.daily.is_due(datetime(2010, 5, 10, 7, 30)) - self.assertFalse(due) - self.assertEqual(remaining, 21 * 60 * 60) - - def test_weekly_execution_is_due(self): - with patch_crontab_nowfun(self.weekly, datetime(2010, 5, 6, 7, 30)): - due, remaining = self.weekly.is_due(datetime(2010, 4, 30, 7, 30)) - self.assertTrue(due) - self.assertEqual(remaining, 7 * 24 * 60 * 60) - - def test_weekly_execution_is_not_due(self): - with patch_crontab_nowfun(self.weekly, datetime(2010, 5, 7, 10, 30)): - due, remaining = self.weekly.is_due(datetime(2010, 5, 6, 7, 30)) - self.assertFalse(due) - self.assertEqual(remaining, 6 * 24 * 60 * 60 - 3 * 60 * 60) - - def test_monthly_execution_is_due(self): - with patch_crontab_nowfun(self.monthly, datetime(2010, 5, 13, 7, 30)): - due, remaining = self.monthly.is_due(datetime(2010, 4, 8, 7, 30)) - self.assertTrue(due) - self.assertEqual(remaining, 28 * 24 * 60 * 60) - - def test_monthly_execution_is_not_due(self): - with patch_crontab_nowfun(self.monthly, datetime(2010, 5, 9, 10, 30)): - due, remaining = self.monthly.is_due(datetime(2010, 4, 8, 7, 30)) - self.assertFalse(due) - self.assertEqual(remaining, 4 * 24 * 60 * 60 - 3 * 60 * 60) - - def test_monthly_moy_execution_is_due(self): - with patch_crontab_nowfun( - self.monthly_moy, datetime(2014, 2, 26, 22, 0)): - due, remaining = self.monthly_moy.is_due( - datetime(2013, 7, 4, 10, 0), - ) - self.assertTrue(due) - self.assertEqual(remaining, 60.) - - def test_monthly_moy_execution_is_not_due(self): - raise SkipTest('unstable test') - with patch_crontab_nowfun( - self.monthly_moy, datetime(2013, 6, 28, 14, 30)): - due, remaining = self.monthly_moy.is_due( - datetime(2013, 6, 28, 22, 14), - ) - self.assertFalse(due) - attempt = ( - time.mktime(datetime(2014, 2, 26, 22, 0).timetuple()) - - time.mktime(datetime(2013, 6, 28, 14, 30).timetuple()) - - 60 * 60 - ) - self.assertEqual(remaining, attempt) - - def test_monthly_moy_execution_is_due2(self): - with patch_crontab_nowfun( - self.monthly_moy, datetime(2014, 2, 26, 22, 0)): - due, remaining = self.monthly_moy.is_due( - datetime(2013, 2, 28, 10, 0), - ) - self.assertTrue(due) - self.assertEqual(remaining, 60.) - - def test_monthly_moy_execution_is_not_due2(self): - with patch_crontab_nowfun( - self.monthly_moy, datetime(2014, 2, 26, 21, 0)): - due, remaining = self.monthly_moy.is_due( - datetime(2013, 6, 28, 22, 14), - ) - self.assertFalse(due) - attempt = 60 * 60 - self.assertEqual(remaining, attempt) - - def test_yearly_execution_is_due(self): - with patch_crontab_nowfun(self.yearly, datetime(2010, 3, 11, 7, 30)): - due, remaining = self.yearly.is_due(datetime(2009, 3, 12, 7, 30)) - self.assertTrue(due) - self.assertEqual(remaining, 364 * 24 * 60 * 60) - - def test_yearly_execution_is_not_due(self): - with patch_crontab_nowfun(self.yearly, datetime(2010, 3, 7, 10, 30)): - due, remaining = self.yearly.is_due(datetime(2009, 3, 12, 7, 30)) - self.assertFalse(due) - self.assertEqual(remaining, 4 * 24 * 60 * 60 - 3 * 60 * 60) diff --git a/awx/lib/site-packages/celery/tests/app/test_utils.py b/awx/lib/site-packages/celery/tests/app/test_utils.py deleted file mode 100644 index dc7e381104..0000000000 --- a/awx/lib/site-packages/celery/tests/app/test_utils.py +++ /dev/null @@ -1,30 +0,0 @@ -from __future__ import absolute_import - -from collections import Mapping, MutableMapping - -from celery.app.utils import Settings, bugreport - -from celery.tests.case import AppCase, Mock - - -class TestSettings(AppCase): - """ - Tests of celery.app.utils.Settings - """ - def test_is_mapping(self): - """Settings should be a collections.Mapping""" - self.assertTrue(issubclass(Settings, Mapping)) - - def test_is_mutable_mapping(self): - """Settings should be a collections.MutableMapping""" - self.assertTrue(issubclass(Settings, MutableMapping)) - - -class test_bugreport(AppCase): - - def test_no_conn_driver_info(self): - self.app.connection = Mock() - conn = self.app.connection.return_value = Mock() - conn.transport = None - - bugreport(self.app) diff --git a/awx/lib/site-packages/celery/tests/backends/__init__.py b/awx/lib/site-packages/celery/tests/backends/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/backends/test_amqp.py b/awx/lib/site-packages/celery/tests/backends/test_amqp.py deleted file mode 100644 index 7e5a361966..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_amqp.py +++ /dev/null @@ -1,354 +0,0 @@ -from __future__ import absolute_import - -import pickle -import socket - -from contextlib import contextmanager -from datetime import timedelta -from pickle import dumps, loads - -from billiard.einfo import ExceptionInfo - -from celery import states -from celery.backends.amqp import AMQPBackend -from celery.exceptions import TimeoutError -from celery.five import Empty, Queue, range -from celery.utils import uuid - -from celery.tests.case import ( - AppCase, Mock, depends_on_current_app, patch, sleepdeprived, -) - - -class SomeClass(object): - - def __init__(self, data): - self.data = data - - -class test_AMQPBackend(AppCase): - - def create_backend(self, **opts): - opts = dict(dict(serializer='pickle', persistent=True), **opts) - return AMQPBackend(self.app, **opts) - - def test_mark_as_done(self): - tb1 = self.create_backend(max_cached_results=1) - tb2 = self.create_backend(max_cached_results=1) - - tid = uuid() - - tb1.mark_as_done(tid, 42) - self.assertEqual(tb2.get_status(tid), states.SUCCESS) - self.assertEqual(tb2.get_result(tid), 42) - self.assertTrue(tb2._cache.get(tid)) - self.assertTrue(tb2.get_result(tid), 42) - - @depends_on_current_app - def test_pickleable(self): - self.assertTrue(loads(dumps(self.create_backend()))) - - def test_revive(self): - tb = self.create_backend() - tb.revive(None) - - def test_is_pickled(self): - tb1 = self.create_backend() - tb2 = self.create_backend() - - tid2 = uuid() - result = {'foo': 'baz', 'bar': SomeClass(12345)} - tb1.mark_as_done(tid2, result) - # is serialized properly. - rindb = tb2.get_result(tid2) - self.assertEqual(rindb.get('foo'), 'baz') - self.assertEqual(rindb.get('bar').data, 12345) - - def test_mark_as_failure(self): - tb1 = self.create_backend() - tb2 = self.create_backend() - - tid3 = uuid() - try: - raise KeyError('foo') - except KeyError as exception: - einfo = ExceptionInfo() - tb1.mark_as_failure(tid3, exception, traceback=einfo.traceback) - self.assertEqual(tb2.get_status(tid3), states.FAILURE) - self.assertIsInstance(tb2.get_result(tid3), KeyError) - self.assertEqual(tb2.get_traceback(tid3), einfo.traceback) - - def test_repair_uuid(self): - from celery.backends.amqp import repair_uuid - for i in range(10): - tid = uuid() - self.assertEqual(repair_uuid(tid.replace('-', '')), tid) - - def test_expires_is_int(self): - b = self.create_backend(expires=48) - self.assertEqual(b.queue_arguments.get('x-expires'), 48 * 1000.0) - - def test_expires_is_float(self): - b = self.create_backend(expires=48.3) - self.assertEqual(b.queue_arguments.get('x-expires'), 48.3 * 1000.0) - - def test_expires_is_timedelta(self): - b = self.create_backend(expires=timedelta(minutes=1)) - self.assertEqual(b.queue_arguments.get('x-expires'), 60 * 1000.0) - - @sleepdeprived() - def test_store_result_retries(self): - iterations = [0] - stop_raising_at = [5] - - def publish(*args, **kwargs): - if iterations[0] > stop_raising_at[0]: - return - iterations[0] += 1 - raise KeyError('foo') - - backend = AMQPBackend(self.app) - from celery.app.amqp import TaskProducer - prod, TaskProducer.publish = TaskProducer.publish, publish - try: - with self.assertRaises(KeyError): - backend.retry_policy['max_retries'] = None - backend.store_result('foo', 'bar', 'STARTED') - - with self.assertRaises(KeyError): - backend.retry_policy['max_retries'] = 10 - backend.store_result('foo', 'bar', 'STARTED') - finally: - TaskProducer.publish = prod - - def assertState(self, retval, state): - self.assertEqual(retval['status'], state) - - def test_poll_no_messages(self): - b = self.create_backend() - self.assertState(b.get_task_meta(uuid()), states.PENDING) - - @contextmanager - def _result_context(self): - results = Queue() - - class Message(object): - acked = 0 - requeued = 0 - - def __init__(self, **merge): - self.payload = dict({'status': states.STARTED, - 'result': None}, **merge) - self.body = pickle.dumps(self.payload) - self.content_type = 'application/x-python-serialize' - self.content_encoding = 'binary' - - def ack(self, *args, **kwargs): - self.acked += 1 - - def requeue(self, *args, **kwargs): - self.requeued += 1 - - class MockBinding(object): - - def __init__(self, *args, **kwargs): - self.channel = Mock() - - def __call__(self, *args, **kwargs): - return self - - def declare(self): - pass - - def get(self, no_ack=False, accept=None): - try: - m = results.get(block=False) - if m: - m.accept = accept - return m - except Empty: - pass - - def is_bound(self): - return True - - class MockBackend(AMQPBackend): - Queue = MockBinding - - backend = MockBackend(self.app, max_cached_results=100) - backend._republish = Mock() - - yield results, backend, Message - - def test_backlog_limit_exceeded(self): - with self._result_context() as (results, backend, Message): - for i in range(1001): - results.put(Message(task_id='id', status=states.RECEIVED)) - with self.assertRaises(backend.BacklogLimitExceeded): - backend.get_task_meta('id') - - def test_poll_result(self): - with self._result_context() as (results, backend, Message): - tid = uuid() - # FFWD's to the latest state. - state_messages = [ - Message(task_id=tid, status=states.RECEIVED, seq=1), - Message(task_id=tid, status=states.STARTED, seq=2), - Message(task_id=tid, status=states.FAILURE, seq=3), - ] - for state_message in state_messages: - results.put(state_message) - r1 = backend.get_task_meta(tid) - self.assertDictContainsSubset( - {'status': states.FAILURE, 'seq': 3}, r1, - 'FFWDs to the last state', - ) - - # Caches last known state. - tid = uuid() - results.put(Message(task_id=tid)) - backend.get_task_meta(tid) - self.assertIn(tid, backend._cache, 'Caches last known state') - - self.assertTrue(state_messages[-1].requeued) - - # Returns cache if no new states. - results.queue.clear() - assert not results.qsize() - backend._cache[tid] = 'hello' - self.assertEqual( - backend.get_task_meta(tid), 'hello', - 'Returns cache if no new states', - ) - - def test_wait_for(self): - b = self.create_backend() - - tid = uuid() - with self.assertRaises(TimeoutError): - b.wait_for(tid, timeout=0.1) - b.store_result(tid, None, states.STARTED) - with self.assertRaises(TimeoutError): - b.wait_for(tid, timeout=0.1) - b.store_result(tid, None, states.RETRY) - with self.assertRaises(TimeoutError): - b.wait_for(tid, timeout=0.1) - b.store_result(tid, 42, states.SUCCESS) - self.assertEqual(b.wait_for(tid, timeout=1), 42) - b.store_result(tid, 56, states.SUCCESS) - self.assertEqual(b.wait_for(tid, timeout=1), 42, - 'result is cached') - self.assertEqual(b.wait_for(tid, timeout=1, cache=False), 56) - b.store_result(tid, KeyError('foo'), states.FAILURE) - with self.assertRaises(KeyError): - b.wait_for(tid, timeout=1, cache=False) - self.assertTrue(b.wait_for(tid, timeout=1, propagate=False)) - b.store_result(tid, KeyError('foo'), states.PENDING) - with self.assertRaises(TimeoutError): - b.wait_for(tid, timeout=0.01, cache=False) - - def test_drain_events_remaining_timeouts(self): - - class Connection(object): - - def drain_events(self, timeout=None): - pass - - b = self.create_backend() - with self.app.pool.acquire_channel(block=False) as (_, channel): - binding = b._create_binding(uuid()) - consumer = b.Consumer(channel, binding, no_ack=True) - with self.assertRaises(socket.timeout): - b.drain_events(Connection(), consumer, timeout=0.1) - - def test_get_many(self): - b = self.create_backend(max_cached_results=10) - - tids = [] - for i in range(10): - tid = uuid() - b.store_result(tid, i, states.SUCCESS) - tids.append(tid) - - res = list(b.get_many(tids, timeout=1)) - expected_results = [(tid, {'status': states.SUCCESS, - 'result': i, - 'traceback': None, - 'task_id': tid, - 'children': None}) - for i, tid in enumerate(tids)] - self.assertEqual(sorted(res), sorted(expected_results)) - self.assertDictEqual(b._cache[res[0][0]], res[0][1]) - cached_res = list(b.get_many(tids, timeout=1)) - self.assertEqual(sorted(cached_res), sorted(expected_results)) - - # times out when not ready in cache (this shouldn't happen) - b._cache[res[0][0]]['status'] = states.RETRY - with self.assertRaises(socket.timeout): - list(b.get_many(tids, timeout=0.01)) - - # times out when result not yet ready - with self.assertRaises(socket.timeout): - tids = [uuid()] - b.store_result(tids[0], i, states.PENDING) - list(b.get_many(tids, timeout=0.01)) - - def test_get_many_raises_outer_block(self): - - class Backend(AMQPBackend): - - def Consumer(*args, **kwargs): - raise KeyError('foo') - - b = Backend(self.app) - with self.assertRaises(KeyError): - next(b.get_many(['id1'])) - - def test_get_many_raises_inner_block(self): - with patch('kombu.connection.Connection.drain_events') as drain: - drain.side_effect = KeyError('foo') - b = AMQPBackend(self.app) - with self.assertRaises(KeyError): - next(b.get_many(['id1'])) - - def test_consume_raises_inner_block(self): - with patch('kombu.connection.Connection.drain_events') as drain: - - def se(*args, **kwargs): - drain.side_effect = ValueError() - raise KeyError('foo') - drain.side_effect = se - b = AMQPBackend(self.app) - with self.assertRaises(ValueError): - next(b.consume('id1')) - - def test_no_expires(self): - b = self.create_backend(expires=None) - app = self.app - app.conf.CELERY_TASK_RESULT_EXPIRES = None - b = self.create_backend(expires=None) - with self.assertRaises(KeyError): - b.queue_arguments['x-expires'] - - def test_process_cleanup(self): - self.create_backend().process_cleanup() - - def test_reload_task_result(self): - with self.assertRaises(NotImplementedError): - self.create_backend().reload_task_result('x') - - def test_reload_group_result(self): - with self.assertRaises(NotImplementedError): - self.create_backend().reload_group_result('x') - - def test_save_group(self): - with self.assertRaises(NotImplementedError): - self.create_backend().save_group('x', 'x') - - def test_restore_group(self): - with self.assertRaises(NotImplementedError): - self.create_backend().restore_group('x') - - def test_delete_group(self): - with self.assertRaises(NotImplementedError): - self.create_backend().delete_group('x') diff --git a/awx/lib/site-packages/celery/tests/backends/test_backends.py b/awx/lib/site-packages/celery/tests/backends/test_backends.py deleted file mode 100644 index bba6127703..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_backends.py +++ /dev/null @@ -1,49 +0,0 @@ -from __future__ import absolute_import - -from celery import backends -from celery.backends.amqp import AMQPBackend -from celery.backends.cache import CacheBackend -from celery.tests.case import AppCase, depends_on_current_app, patch - - -class test_backends(AppCase): - - def test_get_backend_aliases(self): - expects = [('amqp://', AMQPBackend), - ('cache+memory://', CacheBackend)] - - for url, expect_cls in expects: - backend, url = backends.get_backend_by_url(url, self.app.loader) - self.assertIsInstance( - backend(app=self.app, url=url), - expect_cls, - ) - - def test_get_backend_cache(self): - backends.get_backend_cls.clear() - hits = backends.get_backend_cls.hits - misses = backends.get_backend_cls.misses - self.assertTrue(backends.get_backend_cls('amqp', self.app.loader)) - self.assertEqual(backends.get_backend_cls.misses, misses + 1) - self.assertTrue(backends.get_backend_cls('amqp', self.app.loader)) - self.assertEqual(backends.get_backend_cls.hits, hits + 1) - - def test_unknown_backend(self): - with self.assertRaises(ImportError): - backends.get_backend_cls('fasodaopjeqijwqe', self.app.loader) - - @depends_on_current_app - def test_default_backend(self): - self.assertEqual(backends.default_backend, self.app.backend) - - def test_backend_by_url(self, url='redis://localhost/1'): - from celery.backends.redis import RedisBackend - backend, url_ = backends.get_backend_by_url(url, self.app.loader) - self.assertIs(backend, RedisBackend) - self.assertEqual(url_, url) - - def test_sym_raises_ValuError(self): - with patch('celery.backends.symbol_by_name') as sbn: - sbn.side_effect = ValueError() - with self.assertRaises(ValueError): - backends.get_backend_cls('xxx.xxx:foo', self.app.loader) diff --git a/awx/lib/site-packages/celery/tests/backends/test_base.py b/awx/lib/site-packages/celery/tests/backends/test_base.py deleted file mode 100644 index 58e3e8d524..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_base.py +++ /dev/null @@ -1,448 +0,0 @@ -from __future__ import absolute_import - -import sys -import types - -from contextlib import contextmanager - -from celery.exceptions import ChordError -from celery.five import items, range -from celery.utils import serialization -from celery.utils.serialization import subclass_exception -from celery.utils.serialization import find_pickleable_exception as fnpe -from celery.utils.serialization import UnpickleableExceptionWrapper -from celery.utils.serialization import get_pickleable_exception as gpe - -from celery import states -from celery import group -from celery.backends.base import ( - BaseBackend, - KeyValueStoreBackend, - DisabledBackend, -) -from celery.result import result_from_tuple -from celery.utils import uuid - -from celery.tests.case import AppCase, Mock, SkipTest, patch - - -class wrapobject(object): - - def __init__(self, *args, **kwargs): - self.args = args - -if sys.version_info[0] == 3 or getattr(sys, 'pypy_version_info', None): - Oldstyle = None -else: - Oldstyle = types.ClassType('Oldstyle', (), {}) -Unpickleable = subclass_exception('Unpickleable', KeyError, 'foo.module') -Impossible = subclass_exception('Impossible', object, 'foo.module') -Lookalike = subclass_exception('Lookalike', wrapobject, 'foo.module') - - -class test_serialization(AppCase): - - def test_create_exception_cls(self): - self.assertTrue(serialization.create_exception_cls('FooError', 'm')) - self.assertTrue(serialization.create_exception_cls('FooError', 'm', - KeyError)) - - -class test_BaseBackend_interface(AppCase): - - def setup(self): - self.b = BaseBackend(self.app) - - def test__forget(self): - with self.assertRaises(NotImplementedError): - self.b._forget('SOMExx-N0Nex1stant-IDxx-') - - def test_forget(self): - with self.assertRaises(NotImplementedError): - self.b.forget('SOMExx-N0nex1stant-IDxx-') - - def test_on_chord_part_return(self): - self.b.on_chord_part_return(None, None, None) - - def test_apply_chord(self, unlock='celery.chord_unlock'): - self.app.tasks[unlock] = Mock() - self.b.apply_chord( - group(app=self.app), (), 'dakj221', None, - result=[self.app.AsyncResult(x) for x in [1, 2, 3]], - ) - self.assertTrue(self.app.tasks[unlock].apply_async.call_count) - - -class test_exception_pickle(AppCase): - - def test_oldstyle(self): - if Oldstyle is None: - raise SkipTest('py3k does not support old style classes') - self.assertTrue(fnpe(Oldstyle())) - - def test_BaseException(self): - self.assertIsNone(fnpe(Exception())) - - def test_get_pickleable_exception(self): - exc = Exception('foo') - self.assertEqual(gpe(exc), exc) - - def test_unpickleable(self): - self.assertIsInstance(fnpe(Unpickleable()), KeyError) - self.assertIsNone(fnpe(Impossible())) - - -class test_prepare_exception(AppCase): - - def setup(self): - self.b = BaseBackend(self.app) - - def test_unpickleable(self): - x = self.b.prepare_exception(Unpickleable(1, 2, 'foo')) - self.assertIsInstance(x, KeyError) - y = self.b.exception_to_python(x) - self.assertIsInstance(y, KeyError) - - def test_impossible(self): - x = self.b.prepare_exception(Impossible()) - self.assertIsInstance(x, UnpickleableExceptionWrapper) - self.assertTrue(str(x)) - y = self.b.exception_to_python(x) - self.assertEqual(y.__class__.__name__, 'Impossible') - if sys.version_info < (2, 5): - self.assertTrue(y.__class__.__module__) - else: - self.assertEqual(y.__class__.__module__, 'foo.module') - - def test_regular(self): - x = self.b.prepare_exception(KeyError('baz')) - self.assertIsInstance(x, KeyError) - y = self.b.exception_to_python(x) - self.assertIsInstance(y, KeyError) - - -class KVBackend(KeyValueStoreBackend): - mget_returns_dict = False - - def __init__(self, app, *args, **kwargs): - self.db = {} - super(KVBackend, self).__init__(app) - - def get(self, key): - return self.db.get(key) - - def set(self, key, value): - self.db[key] = value - - def mget(self, keys): - if self.mget_returns_dict: - return dict((key, self.get(key)) for key in keys) - else: - return [self.get(k) for k in keys] - - def delete(self, key): - self.db.pop(key, None) - - -class DictBackend(BaseBackend): - - def __init__(self, *args, **kwargs): - BaseBackend.__init__(self, *args, **kwargs) - self._data = {'can-delete': {'result': 'foo'}} - - def _restore_group(self, group_id): - if group_id == 'exists': - return {'result': 'group'} - - def _get_task_meta_for(self, task_id): - if task_id == 'task-exists': - return {'result': 'task'} - - def _delete_group(self, group_id): - self._data.pop(group_id, None) - - -class test_BaseBackend_dict(AppCase): - - def setup(self): - self.b = DictBackend(app=self.app) - - def test_delete_group(self): - self.b.delete_group('can-delete') - self.assertNotIn('can-delete', self.b._data) - - def test_prepare_exception_json(self): - x = DictBackend(self.app, serializer='json') - e = x.prepare_exception(KeyError('foo')) - self.assertIn('exc_type', e) - e = x.exception_to_python(e) - self.assertEqual(e.__class__.__name__, 'KeyError') - self.assertEqual(str(e), "'foo'") - - def test_save_group(self): - b = BaseBackend(self.app) - b._save_group = Mock() - b.save_group('foofoo', 'xxx') - b._save_group.assert_called_with('foofoo', 'xxx') - - def test_forget_interface(self): - b = BaseBackend(self.app) - with self.assertRaises(NotImplementedError): - b.forget('foo') - - def test_restore_group(self): - self.assertIsNone(self.b.restore_group('missing')) - self.assertIsNone(self.b.restore_group('missing')) - self.assertEqual(self.b.restore_group('exists'), 'group') - self.assertEqual(self.b.restore_group('exists'), 'group') - self.assertEqual(self.b.restore_group('exists', cache=False), 'group') - - def test_reload_group_result(self): - self.b._cache = {} - self.b.reload_group_result('exists') - self.b._cache['exists'] = {'result': 'group'} - - def test_reload_task_result(self): - self.b._cache = {} - self.b.reload_task_result('task-exists') - self.b._cache['task-exists'] = {'result': 'task'} - - def test_fail_from_current_stack(self): - self.b.mark_as_failure = Mock() - try: - raise KeyError('foo') - except KeyError as exc: - self.b.fail_from_current_stack('task_id') - self.assertTrue(self.b.mark_as_failure.called) - args = self.b.mark_as_failure.call_args[0] - self.assertEqual(args[0], 'task_id') - self.assertIs(args[1], exc) - self.assertTrue(args[2]) - - def test_prepare_value_serializes_group_result(self): - self.b.serializer = 'json' - g = self.app.GroupResult('group_id', [self.app.AsyncResult('foo')]) - v = self.b.prepare_value(g) - self.assertIsInstance(v, (list, tuple)) - self.assertEqual(result_from_tuple(v, app=self.app), g) - - v2 = self.b.prepare_value(g[0]) - self.assertIsInstance(v2, (list, tuple)) - self.assertEqual(result_from_tuple(v2, app=self.app), g[0]) - - self.b.serializer = 'pickle' - self.assertIsInstance(self.b.prepare_value(g), self.app.GroupResult) - - def test_is_cached(self): - b = BaseBackend(app=self.app, max_cached_results=1) - b._cache['foo'] = 1 - self.assertTrue(b.is_cached('foo')) - self.assertFalse(b.is_cached('false')) - - -class test_KeyValueStoreBackend(AppCase): - - def setup(self): - self.b = KVBackend(app=self.app) - - def test_on_chord_part_return(self): - assert not self.b.implements_incr - self.b.on_chord_part_return(None, None, None) - - def test_get_store_delete_result(self): - tid = uuid() - self.b.mark_as_done(tid, 'Hello world') - self.assertEqual(self.b.get_result(tid), 'Hello world') - self.assertEqual(self.b.get_status(tid), states.SUCCESS) - self.b.forget(tid) - self.assertEqual(self.b.get_status(tid), states.PENDING) - - def test_strip_prefix(self): - x = self.b.get_key_for_task('x1b34') - self.assertEqual(self.b._strip_prefix(x), 'x1b34') - self.assertEqual(self.b._strip_prefix('x1b34'), 'x1b34') - - def test_get_many(self): - for is_dict in True, False: - self.b.mget_returns_dict = is_dict - ids = dict((uuid(), i) for i in range(10)) - for id, i in items(ids): - self.b.mark_as_done(id, i) - it = self.b.get_many(list(ids)) - for i, (got_id, got_state) in enumerate(it): - self.assertEqual(got_state['result'], ids[got_id]) - self.assertEqual(i, 9) - self.assertTrue(list(self.b.get_many(list(ids)))) - - def test_get_many_times_out(self): - tasks = [uuid() for _ in range(4)] - self.b._cache[tasks[1]] = {'status': 'PENDING'} - with self.assertRaises(self.b.TimeoutError): - list(self.b.get_many(tasks, timeout=0.01, interval=0.01)) - - def test_chord_part_return_no_gid(self): - self.b.implements_incr = True - task = Mock() - state = 'SUCCESS' - result = 10 - task.request.group = None - self.b.get_key_for_chord = Mock() - self.b.get_key_for_chord.side_effect = AssertionError( - 'should not get here', - ) - self.assertIsNone(self.b.on_chord_part_return(task, state, result)) - - @contextmanager - def _chord_part_context(self, b): - - @self.app.task(shared=False) - def callback(result): - pass - - b.implements_incr = True - b.client = Mock() - with patch('celery.backends.base.GroupResult') as GR: - deps = GR.restore.return_value = Mock(name='DEPS') - deps.__len__ = Mock() - deps.__len__.return_value = 10 - b.incr = Mock() - b.incr.return_value = 10 - b.expire = Mock() - task = Mock() - task.request.group = 'grid' - cb = task.request.chord = callback.s() - task.request.chord.freeze() - callback.backend = b - callback.backend.fail_from_current_stack = Mock() - yield task, deps, cb - - def test_chord_part_return_propagate_set(self): - with self._chord_part_context(self.b) as (task, deps, _): - self.b.on_chord_part_return(task, 'SUCCESS', 10, propagate=True) - self.assertFalse(self.b.expire.called) - deps.delete.assert_called_with() - deps.join_native.assert_called_with(propagate=True, timeout=3.0) - - def test_chord_part_return_propagate_default(self): - with self._chord_part_context(self.b) as (task, deps, _): - self.b.on_chord_part_return(task, 'SUCCESS', 10, propagate=None) - self.assertFalse(self.b.expire.called) - deps.delete.assert_called_with() - deps.join_native.assert_called_with( - propagate=self.b.app.conf.CELERY_CHORD_PROPAGATES, - timeout=3.0, - ) - - def test_chord_part_return_join_raises_internal(self): - with self._chord_part_context(self.b) as (task, deps, callback): - deps._failed_join_report = lambda: iter([]) - deps.join_native.side_effect = KeyError('foo') - self.b.on_chord_part_return(task, 'SUCCESS', 10) - self.assertTrue(self.b.fail_from_current_stack.called) - args = self.b.fail_from_current_stack.call_args - exc = args[1]['exc'] - self.assertIsInstance(exc, ChordError) - self.assertIn('foo', str(exc)) - - def test_chord_part_return_join_raises_task(self): - b = KVBackend(serializer='pickle', app=self.app) - with self._chord_part_context(b) as (task, deps, callback): - deps._failed_join_report = lambda: iter([ - self.app.AsyncResult('culprit'), - ]) - deps.join_native.side_effect = KeyError('foo') - b.on_chord_part_return(task, 'SUCCESS', 10) - self.assertTrue(b.fail_from_current_stack.called) - args = b.fail_from_current_stack.call_args - exc = args[1]['exc'] - self.assertIsInstance(exc, ChordError) - self.assertIn('Dependency culprit raised', str(exc)) - - def test_restore_group_from_json(self): - b = KVBackend(serializer='json', app=self.app) - g = self.app.GroupResult( - 'group_id', - [self.app.AsyncResult('a'), self.app.AsyncResult('b')], - ) - b._save_group(g.id, g) - g2 = b._restore_group(g.id)['result'] - self.assertEqual(g2, g) - - def test_restore_group_from_pickle(self): - b = KVBackend(serializer='pickle', app=self.app) - g = self.app.GroupResult( - 'group_id', - [self.app.AsyncResult('a'), self.app.AsyncResult('b')], - ) - b._save_group(g.id, g) - g2 = b._restore_group(g.id)['result'] - self.assertEqual(g2, g) - - def test_chord_apply_fallback(self): - self.b.implements_incr = False - self.b.fallback_chord_unlock = Mock() - self.b.apply_chord( - group(app=self.app), (), 'group_id', 'body', - result='result', foo=1, - ) - self.b.fallback_chord_unlock.assert_called_with( - 'group_id', 'body', result='result', foo=1, - ) - - def test_get_missing_meta(self): - self.assertIsNone(self.b.get_result('xxx-missing')) - self.assertEqual(self.b.get_status('xxx-missing'), states.PENDING) - - def test_save_restore_delete_group(self): - tid = uuid() - tsr = self.app.GroupResult( - tid, [self.app.AsyncResult(uuid()) for _ in range(10)], - ) - self.b.save_group(tid, tsr) - self.b.restore_group(tid) - self.assertEqual(self.b.restore_group(tid), tsr) - self.b.delete_group(tid) - self.assertIsNone(self.b.restore_group(tid)) - - def test_restore_missing_group(self): - self.assertIsNone(self.b.restore_group('xxx-nonexistant')) - - -class test_KeyValueStoreBackend_interface(AppCase): - - def test_get(self): - with self.assertRaises(NotImplementedError): - KeyValueStoreBackend(self.app).get('a') - - def test_set(self): - with self.assertRaises(NotImplementedError): - KeyValueStoreBackend(self.app).set('a', 1) - - def test_incr(self): - with self.assertRaises(NotImplementedError): - KeyValueStoreBackend(self.app).incr('a') - - def test_cleanup(self): - self.assertFalse(KeyValueStoreBackend(self.app).cleanup()) - - def test_delete(self): - with self.assertRaises(NotImplementedError): - KeyValueStoreBackend(self.app).delete('a') - - def test_mget(self): - with self.assertRaises(NotImplementedError): - KeyValueStoreBackend(self.app).mget(['a']) - - def test_forget(self): - with self.assertRaises(NotImplementedError): - KeyValueStoreBackend(self.app).forget('a') - - -class test_DisabledBackend(AppCase): - - def test_store_result(self): - DisabledBackend(self.app).store_result() - - def test_is_disabled(self): - with self.assertRaises(NotImplementedError): - DisabledBackend(self.app).get_status('foo') diff --git a/awx/lib/site-packages/celery/tests/backends/test_cache.py b/awx/lib/site-packages/celery/tests/backends/test_cache.py deleted file mode 100644 index 051760a8de..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_cache.py +++ /dev/null @@ -1,253 +0,0 @@ -from __future__ import absolute_import - -import sys -import types - -from contextlib import contextmanager - -from kombu.utils.encoding import str_to_bytes - -from celery import signature -from celery import states -from celery import group -from celery.backends.cache import CacheBackend, DummyClient -from celery.exceptions import ImproperlyConfigured -from celery.five import items, string, text_t -from celery.utils import uuid - -from celery.tests.case import ( - AppCase, Mock, mask_modules, patch, reset_modules, -) - -PY3 = sys.version_info[0] == 3 - - -class SomeClass(object): - - def __init__(self, data): - self.data = data - - -class test_CacheBackend(AppCase): - - def setup(self): - self.tb = CacheBackend(backend='memory://', app=self.app) - self.tid = uuid() - - def test_no_backend(self): - self.app.conf.CELERY_CACHE_BACKEND = None - with self.assertRaises(ImproperlyConfigured): - CacheBackend(backend=None, app=self.app) - - def test_mark_as_done(self): - self.assertEqual(self.tb.get_status(self.tid), states.PENDING) - self.assertIsNone(self.tb.get_result(self.tid)) - - self.tb.mark_as_done(self.tid, 42) - self.assertEqual(self.tb.get_status(self.tid), states.SUCCESS) - self.assertEqual(self.tb.get_result(self.tid), 42) - - def test_is_pickled(self): - result = {'foo': 'baz', 'bar': SomeClass(12345)} - self.tb.mark_as_done(self.tid, result) - # is serialized properly. - rindb = self.tb.get_result(self.tid) - self.assertEqual(rindb.get('foo'), 'baz') - self.assertEqual(rindb.get('bar').data, 12345) - - def test_mark_as_failure(self): - try: - raise KeyError('foo') - except KeyError as exception: - self.tb.mark_as_failure(self.tid, exception) - self.assertEqual(self.tb.get_status(self.tid), states.FAILURE) - self.assertIsInstance(self.tb.get_result(self.tid), KeyError) - - def test_apply_chord(self): - tb = CacheBackend(backend='memory://', app=self.app) - gid, res = uuid(), [self.app.AsyncResult(uuid()) for _ in range(3)] - tb.apply_chord(group(app=self.app), (), gid, {}, result=res) - - @patch('celery.result.GroupResult.restore') - def test_on_chord_part_return(self, restore): - tb = CacheBackend(backend='memory://', app=self.app) - - deps = Mock() - deps.__len__ = Mock() - deps.__len__.return_value = 2 - restore.return_value = deps - task = Mock() - task.name = 'foobarbaz' - self.app.tasks['foobarbaz'] = task - task.request.chord = signature(task) - - gid, res = uuid(), [self.app.AsyncResult(uuid()) for _ in range(3)] - task.request.group = gid - tb.apply_chord(group(app=self.app), (), gid, {}, result=res) - - self.assertFalse(deps.join_native.called) - tb.on_chord_part_return(task, 'SUCCESS', 10) - self.assertFalse(deps.join_native.called) - - tb.on_chord_part_return(task, 'SUCCESS', 10) - deps.join_native.assert_called_with(propagate=True, timeout=3.0) - deps.delete.assert_called_with() - - def test_mget(self): - self.tb.set('foo', 1) - self.tb.set('bar', 2) - - self.assertDictEqual(self.tb.mget(['foo', 'bar']), - {'foo': 1, 'bar': 2}) - - def test_forget(self): - self.tb.mark_as_done(self.tid, {'foo': 'bar'}) - x = self.app.AsyncResult(self.tid, backend=self.tb) - x.forget() - self.assertIsNone(x.result) - - def test_process_cleanup(self): - self.tb.process_cleanup() - - def test_expires_as_int(self): - tb = CacheBackend(backend='memory://', expires=10, app=self.app) - self.assertEqual(tb.expires, 10) - - def test_unknown_backend_raises_ImproperlyConfigured(self): - with self.assertRaises(ImproperlyConfigured): - CacheBackend(backend='unknown://', app=self.app) - - -class MyMemcachedStringEncodingError(Exception): - pass - - -class MemcachedClient(DummyClient): - - def set(self, key, value, *args, **kwargs): - if PY3: - key_t, must_be, not_be, cod = bytes, 'string', 'bytes', 'decode' - else: - key_t, must_be, not_be, cod = text_t, 'bytes', 'string', 'encode' - if isinstance(key, key_t): - raise MyMemcachedStringEncodingError( - 'Keys must be {0}, not {1}. Convert your ' - 'strings using mystring.{2}(charset)!'.format( - must_be, not_be, cod)) - return super(MemcachedClient, self).set(key, value, *args, **kwargs) - - -class MockCacheMixin(object): - - @contextmanager - def mock_memcache(self): - memcache = types.ModuleType('memcache') - memcache.Client = MemcachedClient - memcache.Client.__module__ = memcache.__name__ - prev, sys.modules['memcache'] = sys.modules.get('memcache'), memcache - try: - yield True - finally: - if prev is not None: - sys.modules['memcache'] = prev - - @contextmanager - def mock_pylibmc(self): - pylibmc = types.ModuleType('pylibmc') - pylibmc.Client = MemcachedClient - pylibmc.Client.__module__ = pylibmc.__name__ - prev = sys.modules.get('pylibmc') - sys.modules['pylibmc'] = pylibmc - try: - yield True - finally: - if prev is not None: - sys.modules['pylibmc'] = prev - - -class test_get_best_memcache(AppCase, MockCacheMixin): - - def test_pylibmc(self): - with self.mock_pylibmc(): - with reset_modules('celery.backends.cache'): - from celery.backends import cache - cache._imp = [None] - self.assertEqual(cache.get_best_memcache()[0].__module__, - 'pylibmc') - - def test_memcache(self): - with self.mock_memcache(): - with reset_modules('celery.backends.cache'): - with mask_modules('pylibmc'): - from celery.backends import cache - cache._imp = [None] - self.assertEqual(cache.get_best_memcache()[0]().__module__, - 'memcache') - - def test_no_implementations(self): - with mask_modules('pylibmc', 'memcache'): - with reset_modules('celery.backends.cache'): - from celery.backends import cache - cache._imp = [None] - with self.assertRaises(ImproperlyConfigured): - cache.get_best_memcache() - - def test_cached(self): - with self.mock_pylibmc(): - with reset_modules('celery.backends.cache'): - from celery.backends import cache - cache._imp = [None] - cache.get_best_memcache()[0](behaviors={'foo': 'bar'}) - self.assertTrue(cache._imp[0]) - cache.get_best_memcache()[0]() - - def test_backends(self): - from celery.backends.cache import backends - with self.mock_memcache(): - for name, fun in items(backends): - self.assertTrue(fun()) - - -class test_memcache_key(AppCase, MockCacheMixin): - - def test_memcache_unicode_key(self): - with self.mock_memcache(): - with reset_modules('celery.backends.cache'): - with mask_modules('pylibmc'): - from celery.backends import cache - cache._imp = [None] - task_id, result = string(uuid()), 42 - b = cache.CacheBackend(backend='memcache', app=self.app) - b.store_result(task_id, result, status=states.SUCCESS) - self.assertEqual(b.get_result(task_id), result) - - def test_memcache_bytes_key(self): - with self.mock_memcache(): - with reset_modules('celery.backends.cache'): - with mask_modules('pylibmc'): - from celery.backends import cache - cache._imp = [None] - task_id, result = str_to_bytes(uuid()), 42 - b = cache.CacheBackend(backend='memcache', app=self.app) - b.store_result(task_id, result, status=states.SUCCESS) - self.assertEqual(b.get_result(task_id), result) - - def test_pylibmc_unicode_key(self): - with reset_modules('celery.backends.cache'): - with self.mock_pylibmc(): - from celery.backends import cache - cache._imp = [None] - task_id, result = string(uuid()), 42 - b = cache.CacheBackend(backend='memcache', app=self.app) - b.store_result(task_id, result, status=states.SUCCESS) - self.assertEqual(b.get_result(task_id), result) - - def test_pylibmc_bytes_key(self): - with reset_modules('celery.backends.cache'): - with self.mock_pylibmc(): - from celery.backends import cache - cache._imp = [None] - task_id, result = str_to_bytes(uuid()), 42 - b = cache.CacheBackend(backend='memcache', app=self.app) - b.store_result(task_id, result, status=states.SUCCESS) - self.assertEqual(b.get_result(task_id), result) diff --git a/awx/lib/site-packages/celery/tests/backends/test_cassandra.py b/awx/lib/site-packages/celery/tests/backends/test_cassandra.py deleted file mode 100644 index 1a43be9efe..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_cassandra.py +++ /dev/null @@ -1,190 +0,0 @@ -from __future__ import absolute_import - -import socket - -from pickle import loads, dumps - -from celery import states -from celery.exceptions import ImproperlyConfigured -from celery.tests.case import ( - AppCase, Mock, mock_module, depends_on_current_app, -) - - -class Object(object): - pass - - -def install_exceptions(mod): - # py3k: cannot catch exceptions not ineheriting from BaseException. - - class NotFoundException(Exception): - pass - - class TException(Exception): - pass - - class InvalidRequestException(Exception): - pass - - class UnavailableException(Exception): - pass - - class TimedOutException(Exception): - pass - - class AllServersUnavailable(Exception): - pass - - mod.NotFoundException = NotFoundException - mod.TException = TException - mod.InvalidRequestException = InvalidRequestException - mod.TimedOutException = TimedOutException - mod.UnavailableException = UnavailableException - mod.AllServersUnavailable = AllServersUnavailable - - -class test_CassandraBackend(AppCase): - - def setup(self): - self.app.conf.update( - CASSANDRA_SERVERS=['example.com'], - CASSANDRA_KEYSPACE='keyspace', - CASSANDRA_COLUMN_FAMILY='columns', - ) - - def test_init_no_pycassa(self): - with mock_module('pycassa'): - from celery.backends import cassandra as mod - prev, mod.pycassa = mod.pycassa, None - try: - with self.assertRaises(ImproperlyConfigured): - mod.CassandraBackend(app=self.app) - finally: - mod.pycassa = prev - - def test_init_with_and_without_LOCAL_QUROM(self): - with mock_module('pycassa'): - from celery.backends import cassandra as mod - mod.pycassa = Mock() - install_exceptions(mod.pycassa) - cons = mod.pycassa.ConsistencyLevel = Object() - cons.LOCAL_QUORUM = 'foo' - - self.app.conf.CASSANDRA_READ_CONSISTENCY = 'LOCAL_FOO' - self.app.conf.CASSANDRA_WRITE_CONSISTENCY = 'LOCAL_FOO' - - mod.CassandraBackend(app=self.app) - cons.LOCAL_FOO = 'bar' - mod.CassandraBackend(app=self.app) - - # no servers raises ImproperlyConfigured - with self.assertRaises(ImproperlyConfigured): - self.app.conf.CASSANDRA_SERVERS = None - mod.CassandraBackend( - app=self.app, keyspace='b', column_family='c', - ) - - @depends_on_current_app - def test_reduce(self): - with mock_module('pycassa'): - from celery.backends.cassandra import CassandraBackend - self.assertTrue(loads(dumps(CassandraBackend(app=self.app)))) - - def test_get_task_meta_for(self): - with mock_module('pycassa'): - from celery.backends import cassandra as mod - mod.pycassa = Mock() - install_exceptions(mod.pycassa) - mod.Thrift = Mock() - install_exceptions(mod.Thrift) - x = mod.CassandraBackend(app=self.app) - Get_Column = x._get_column_family = Mock() - get_column = Get_Column.return_value = Mock() - get = get_column.get - META = get.return_value = { - 'task_id': 'task_id', - 'status': states.SUCCESS, - 'result': '1', - 'date_done': 'date', - 'traceback': '', - 'children': None, - } - x.decode = Mock() - x.detailed_mode = False - meta = x._get_task_meta_for('task_id') - self.assertEqual(meta['status'], states.SUCCESS) - - x.detailed_mode = True - row = get.return_value = Mock() - row.values.return_value = [Mock()] - x.decode.return_value = META - meta = x._get_task_meta_for('task_id') - self.assertEqual(meta['status'], states.SUCCESS) - x.decode.return_value = Mock() - - x.detailed_mode = False - get.side_effect = KeyError() - meta = x._get_task_meta_for('task_id') - self.assertEqual(meta['status'], states.PENDING) - - calls = [0] - end = [10] - - def work_eventually(*arg): - try: - if calls[0] > end[0]: - return META - raise socket.error() - finally: - calls[0] += 1 - get.side_effect = work_eventually - x._retry_timeout = 10 - x._retry_wait = 0.01 - meta = x._get_task_meta_for('task') - self.assertEqual(meta['status'], states.SUCCESS) - - x._retry_timeout = 0.1 - calls[0], end[0] = 0, 100 - with self.assertRaises(socket.error): - x._get_task_meta_for('task') - - def test_store_result(self): - with mock_module('pycassa'): - from celery.backends import cassandra as mod - mod.pycassa = Mock() - install_exceptions(mod.pycassa) - mod.Thrift = Mock() - install_exceptions(mod.Thrift) - x = mod.CassandraBackend(app=self.app) - Get_Column = x._get_column_family = Mock() - cf = Get_Column.return_value = Mock() - x.detailed_mode = False - x._store_result('task_id', 'result', states.SUCCESS) - self.assertTrue(cf.insert.called) - - cf.insert.reset() - x.detailed_mode = True - x._store_result('task_id', 'result', states.SUCCESS) - self.assertTrue(cf.insert.called) - - def test_process_cleanup(self): - with mock_module('pycassa'): - from celery.backends import cassandra as mod - x = mod.CassandraBackend(app=self.app) - x._column_family = None - x.process_cleanup() - - x._column_family = True - x.process_cleanup() - self.assertIsNone(x._column_family) - - def test_get_column_family(self): - with mock_module('pycassa'): - from celery.backends import cassandra as mod - mod.pycassa = Mock() - install_exceptions(mod.pycassa) - x = mod.CassandraBackend(app=self.app) - self.assertTrue(x._get_column_family()) - self.assertIsNotNone(x._column_family) - self.assertIs(x._get_column_family(), x._column_family) diff --git a/awx/lib/site-packages/celery/tests/backends/test_couchbase.py b/awx/lib/site-packages/celery/tests/backends/test_couchbase.py deleted file mode 100644 index 3dc6aadd0b..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_couchbase.py +++ /dev/null @@ -1,136 +0,0 @@ -from __future__ import absolute_import - -from celery.backends import couchbase as module -from celery.backends.couchbase import CouchBaseBackend -from celery.exceptions import ImproperlyConfigured -from celery import backends -from celery.tests.case import ( - AppCase, MagicMock, Mock, SkipTest, patch, sentinel, -) - -try: - import couchbase -except ImportError: - couchbase = None # noqa - -COUCHBASE_BUCKET = 'celery_bucket' - - -class test_CouchBaseBackend(AppCase): - - def setup(self): - if couchbase is None: - raise SkipTest('couchbase is not installed.') - self.backend = CouchBaseBackend(app=self.app) - - def test_init_no_couchbase(self): - """test init no couchbase raises""" - prev, module.couchbase = module.couchbase, None - try: - with self.assertRaises(ImproperlyConfigured): - CouchBaseBackend(app=self.app) - finally: - module.couchbase = prev - - def test_init_no_settings(self): - """test init no settings""" - self.app.conf.CELERY_COUCHBASE_BACKEND_SETTINGS = [] - with self.assertRaises(ImproperlyConfigured): - CouchBaseBackend(app=self.app) - - def test_init_settings_is_None(self): - """Test init settings is None""" - self.app.conf.CELERY_COUCHBASE_BACKEND_SETTINGS = None - CouchBaseBackend(app=self.app) - - def test_get_connection_connection_exists(self): - with patch('couchbase.connection.Connection') as mock_Connection: - self.backend._connection = sentinel._connection - - connection = self.backend._get_connection() - - self.assertEqual(sentinel._connection, connection) - self.assertFalse(mock_Connection.called) - - def test_get(self): - """test_get - - CouchBaseBackend.get should return and take two params - db conn to couchbase is mocked. - TODO Should test on key not exists - - """ - self.app.conf.CELERY_COUCHBASE_BACKEND_SETTINGS = {} - x = CouchBaseBackend(app=self.app) - x._connection = Mock() - mocked_get = x._connection.get = Mock() - mocked_get.return_value.value = sentinel.retval - # should return None - self.assertEqual(x.get('1f3fab'), sentinel.retval) - x._connection.get.assert_called_once_with('1f3fab') - - def test_set(self): - """test_set - - CouchBaseBackend.set should return None and take two params - db conn to couchbase is mocked. - - """ - self.app.conf.CELERY_COUCHBASE_BACKEND_SETTINGS = None - x = CouchBaseBackend(app=self.app) - x._connection = MagicMock() - x._connection.set = MagicMock() - # should return None - self.assertIsNone(x.set(sentinel.key, sentinel.value)) - - def test_delete(self): - """test_delete - - CouchBaseBackend.delete should return and take two params - db conn to couchbase is mocked. - TODO Should test on key not exists - - """ - self.app.conf.CELERY_COUCHBASE_BACKEND_SETTINGS = {} - x = CouchBaseBackend(app=self.app) - x._connection = Mock() - mocked_delete = x._connection.delete = Mock() - mocked_delete.return_value = None - # should return None - self.assertIsNone(x.delete('1f3fab')) - x._connection.delete.assert_called_once_with('1f3fab') - - def test_config_params(self): - """test_config_params - - celery.conf.CELERY_COUCHBASE_BACKEND_SETTINGS is properly set - """ - self.app.conf.CELERY_COUCHBASE_BACKEND_SETTINGS = { - 'bucket': 'mycoolbucket', - 'host': ['here.host.com', 'there.host.com'], - 'username': 'johndoe', - 'password': 'mysecret', - 'port': '1234', - } - x = CouchBaseBackend(app=self.app) - self.assertEqual(x.bucket, 'mycoolbucket') - self.assertEqual(x.host, ['here.host.com', 'there.host.com'],) - self.assertEqual(x.username, 'johndoe',) - self.assertEqual(x.password, 'mysecret') - self.assertEqual(x.port, 1234) - - def test_backend_by_url(self, url='couchbase://myhost/mycoolbucket'): - from celery.backends.couchbase import CouchBaseBackend - backend, url_ = backends.get_backend_by_url(url, self.app.loader) - self.assertIs(backend, CouchBaseBackend) - self.assertEqual(url_, url) - - def test_backend_params_by_url(self): - url = 'couchbase://johndoe:mysecret@myhost:123/mycoolbucket' - with self.Celery(backend=url) as app: - x = app.backend - self.assertEqual(x.bucket, 'mycoolbucket') - self.assertEqual(x.host, 'myhost') - self.assertEqual(x.username, 'johndoe') - self.assertEqual(x.password, 'mysecret') - self.assertEqual(x.port, 123) diff --git a/awx/lib/site-packages/celery/tests/backends/test_database.py b/awx/lib/site-packages/celery/tests/backends/test_database.py deleted file mode 100644 index 6b5bf9420a..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_database.py +++ /dev/null @@ -1,196 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from datetime import datetime - -from pickle import loads, dumps - -from celery import states -from celery.exceptions import ImproperlyConfigured -from celery.utils import uuid - -from celery.tests.case import ( - AppCase, - SkipTest, - depends_on_current_app, - mask_modules, - skip_if_pypy, - skip_if_jython, -) - -try: - import sqlalchemy # noqa -except ImportError: - DatabaseBackend = Task = TaskSet = retry = None # noqa -else: - from celery.backends.database import DatabaseBackend, retry - from celery.backends.database.models import Task, TaskSet - - -class SomeClass(object): - - def __init__(self, data): - self.data = data - - -class test_DatabaseBackend(AppCase): - - @skip_if_pypy - @skip_if_jython - def setup(self): - if DatabaseBackend is None: - raise SkipTest('sqlalchemy not installed') - self.uri = 'sqlite:///test.db' - - def test_retry_helper(self): - from celery.backends.database import DatabaseError - - calls = [0] - - @retry - def raises(): - calls[0] += 1 - raise DatabaseError(1, 2, 3) - - with self.assertRaises(DatabaseError): - raises(max_retries=5) - self.assertEqual(calls[0], 5) - - def test_missing_SQLAlchemy_raises_ImproperlyConfigured(self): - with mask_modules('sqlalchemy'): - from celery.backends.database import _sqlalchemy_installed - with self.assertRaises(ImproperlyConfigured): - _sqlalchemy_installed() - - def test_missing_dburi_raises_ImproperlyConfigured(self): - self.app.conf.CELERY_RESULT_DBURI = None - with self.assertRaises(ImproperlyConfigured): - DatabaseBackend(app=self.app) - - def test_missing_task_id_is_PENDING(self): - tb = DatabaseBackend(self.uri, app=self.app) - self.assertEqual(tb.get_status('xxx-does-not-exist'), states.PENDING) - - def test_missing_task_meta_is_dict_with_pending(self): - tb = DatabaseBackend(self.uri, app=self.app) - self.assertDictContainsSubset({ - 'status': states.PENDING, - 'task_id': 'xxx-does-not-exist-at-all', - 'result': None, - 'traceback': None - }, tb.get_task_meta('xxx-does-not-exist-at-all')) - - def test_mark_as_done(self): - tb = DatabaseBackend(self.uri, app=self.app) - - tid = uuid() - - self.assertEqual(tb.get_status(tid), states.PENDING) - self.assertIsNone(tb.get_result(tid)) - - tb.mark_as_done(tid, 42) - self.assertEqual(tb.get_status(tid), states.SUCCESS) - self.assertEqual(tb.get_result(tid), 42) - - def test_is_pickled(self): - tb = DatabaseBackend(self.uri, app=self.app) - - tid2 = uuid() - result = {'foo': 'baz', 'bar': SomeClass(12345)} - tb.mark_as_done(tid2, result) - # is serialized properly. - rindb = tb.get_result(tid2) - self.assertEqual(rindb.get('foo'), 'baz') - self.assertEqual(rindb.get('bar').data, 12345) - - def test_mark_as_started(self): - tb = DatabaseBackend(self.uri, app=self.app) - tid = uuid() - tb.mark_as_started(tid) - self.assertEqual(tb.get_status(tid), states.STARTED) - - def test_mark_as_revoked(self): - tb = DatabaseBackend(self.uri, app=self.app) - tid = uuid() - tb.mark_as_revoked(tid) - self.assertEqual(tb.get_status(tid), states.REVOKED) - - def test_mark_as_retry(self): - tb = DatabaseBackend(self.uri, app=self.app) - tid = uuid() - try: - raise KeyError('foo') - except KeyError as exception: - import traceback - trace = '\n'.join(traceback.format_stack()) - tb.mark_as_retry(tid, exception, traceback=trace) - self.assertEqual(tb.get_status(tid), states.RETRY) - self.assertIsInstance(tb.get_result(tid), KeyError) - self.assertEqual(tb.get_traceback(tid), trace) - - def test_mark_as_failure(self): - tb = DatabaseBackend(self.uri, app=self.app) - - tid3 = uuid() - try: - raise KeyError('foo') - except KeyError as exception: - import traceback - trace = '\n'.join(traceback.format_stack()) - tb.mark_as_failure(tid3, exception, traceback=trace) - self.assertEqual(tb.get_status(tid3), states.FAILURE) - self.assertIsInstance(tb.get_result(tid3), KeyError) - self.assertEqual(tb.get_traceback(tid3), trace) - - def test_forget(self): - tb = DatabaseBackend(self.uri, backend='memory://', app=self.app) - tid = uuid() - tb.mark_as_done(tid, {'foo': 'bar'}) - tb.mark_as_done(tid, {'foo': 'bar'}) - x = self.app.AsyncResult(tid, backend=tb) - x.forget() - self.assertIsNone(x.result) - - def test_process_cleanup(self): - tb = DatabaseBackend(self.uri, app=self.app) - tb.process_cleanup() - - @depends_on_current_app - def test_reduce(self): - tb = DatabaseBackend(self.uri, app=self.app) - self.assertTrue(loads(dumps(tb))) - - def test_save__restore__delete_group(self): - tb = DatabaseBackend(self.uri, app=self.app) - - tid = uuid() - res = {'something': 'special'} - self.assertEqual(tb.save_group(tid, res), res) - - res2 = tb.restore_group(tid) - self.assertEqual(res2, res) - - tb.delete_group(tid) - self.assertIsNone(tb.restore_group(tid)) - - self.assertIsNone(tb.restore_group('xxx-nonexisting-id')) - - def test_cleanup(self): - tb = DatabaseBackend(self.uri, app=self.app) - for i in range(10): - tb.mark_as_done(uuid(), 42) - tb.save_group(uuid(), {'foo': 'bar'}) - s = tb.ResultSession() - for t in s.query(Task).all(): - t.date_done = datetime.now() - tb.expires * 2 - for t in s.query(TaskSet).all(): - t.date_done = datetime.now() - tb.expires * 2 - s.commit() - s.close() - - tb.cleanup() - - def test_Task__repr__(self): - self.assertIn('foo', repr(Task('foo'))) - - def test_TaskSet__repr__(self): - self.assertIn('foo', repr(TaskSet('foo', None))) diff --git a/awx/lib/site-packages/celery/tests/backends/test_mongodb.py b/awx/lib/site-packages/celery/tests/backends/test_mongodb.py deleted file mode 100644 index e260d87f00..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_mongodb.py +++ /dev/null @@ -1,324 +0,0 @@ -from __future__ import absolute_import - -import datetime -import uuid - -from pickle import loads, dumps - -from celery import states -from celery.backends import mongodb as module -from celery.backends.mongodb import MongoBackend, Bunch, pymongo -from celery.exceptions import ImproperlyConfigured -from celery.tests.case import ( - AppCase, MagicMock, Mock, SkipTest, ANY, - depends_on_current_app, patch, sentinel, -) - -COLLECTION = 'taskmeta_celery' -TASK_ID = str(uuid.uuid1()) -MONGODB_HOST = 'localhost' -MONGODB_PORT = 27017 -MONGODB_USER = 'mongo' -MONGODB_PASSWORD = '1234' -MONGODB_DATABASE = 'testing' -MONGODB_COLLECTION = 'collection1' - - -class test_MongoBackend(AppCase): - - def setup(self): - if pymongo is None: - raise SkipTest('pymongo is not installed.') - - R = self._reset = {} - R['encode'], MongoBackend.encode = MongoBackend.encode, Mock() - R['decode'], MongoBackend.decode = MongoBackend.decode, Mock() - R['Binary'], module.Binary = module.Binary, Mock() - R['datetime'], datetime.datetime = datetime.datetime, Mock() - - self.backend = MongoBackend(app=self.app) - - def teardown(self): - MongoBackend.encode = self._reset['encode'] - MongoBackend.decode = self._reset['decode'] - module.Binary = self._reset['Binary'] - datetime.datetime = self._reset['datetime'] - - def test_Bunch(self): - x = Bunch(foo='foo', bar=2) - self.assertEqual(x.foo, 'foo') - self.assertEqual(x.bar, 2) - - def test_init_no_mongodb(self): - prev, module.pymongo = module.pymongo, None - try: - with self.assertRaises(ImproperlyConfigured): - MongoBackend(app=self.app) - finally: - module.pymongo = prev - - def test_init_no_settings(self): - self.app.conf.CELERY_MONGODB_BACKEND_SETTINGS = [] - with self.assertRaises(ImproperlyConfigured): - MongoBackend(app=self.app) - - def test_init_settings_is_None(self): - self.app.conf.CELERY_MONGODB_BACKEND_SETTINGS = None - MongoBackend(app=self.app) - - def test_restore_group_no_entry(self): - x = MongoBackend(app=self.app) - x.collection = Mock() - fo = x.collection.find_one = Mock() - fo.return_value = None - self.assertIsNone(x._restore_group('1f3fab')) - - @depends_on_current_app - def test_reduce(self): - x = MongoBackend(app=self.app) - self.assertTrue(loads(dumps(x))) - - def test_get_connection_connection_exists(self): - - with patch('pymongo.MongoClient') as mock_Connection: - self.backend._connection = sentinel._connection - - connection = self.backend._get_connection() - - self.assertEqual(sentinel._connection, connection) - self.assertFalse(mock_Connection.called) - - def test_get_connection_no_connection_host(self): - - with patch('pymongo.MongoClient') as mock_Connection: - self.backend._connection = None - self.backend.host = MONGODB_HOST - self.backend.port = MONGODB_PORT - mock_Connection.return_value = sentinel.connection - - connection = self.backend._get_connection() - mock_Connection.assert_called_once_with( - host='mongodb://localhost:27017', ssl=False, max_pool_size=10, - auto_start_request=False) - self.assertEqual(sentinel.connection, connection) - - def test_get_connection_no_connection_mongodb_uri(self): - - with patch('pymongo.MongoClient') as mock_Connection: - mongodb_uri = 'mongodb://%s:%d' % (MONGODB_HOST, MONGODB_PORT) - self.backend._connection = None - self.backend.host = mongodb_uri - - mock_Connection.return_value = sentinel.connection - - connection = self.backend._get_connection() - mock_Connection.assert_called_once_with( - host=mongodb_uri, ssl=False, max_pool_size=10, - auto_start_request=False) - self.assertEqual(sentinel.connection, connection) - - @patch('celery.backends.mongodb.MongoBackend._get_connection') - def test_get_database_no_existing(self, mock_get_connection): - # Should really check for combinations of these two, to be complete. - self.backend.user = MONGODB_USER - self.backend.password = MONGODB_PASSWORD - - mock_database = Mock() - mock_connection = MagicMock(spec=['__getitem__']) - mock_connection.__getitem__.return_value = mock_database - mock_get_connection.return_value = mock_connection - - database = self.backend.database - - self.assertTrue(database is mock_database) - self.assertTrue(self.backend.__dict__['database'] is mock_database) - mock_database.authenticate.assert_called_once_with( - MONGODB_USER, MONGODB_PASSWORD) - - @patch('celery.backends.mongodb.MongoBackend._get_connection') - def test_get_database_no_existing_no_auth(self, mock_get_connection): - # Should really check for combinations of these two, to be complete. - self.backend.user = None - self.backend.password = None - - mock_database = Mock() - mock_connection = MagicMock(spec=['__getitem__']) - mock_connection.__getitem__.return_value = mock_database - mock_get_connection.return_value = mock_connection - - database = self.backend.database - - self.assertTrue(database is mock_database) - self.assertFalse(mock_database.authenticate.called) - self.assertTrue(self.backend.__dict__['database'] is mock_database) - - def test_process_cleanup(self): - self.backend._connection = None - self.backend.process_cleanup() - self.assertEqual(self.backend._connection, None) - - self.backend._connection = 'not none' - self.backend.process_cleanup() - self.assertEqual(self.backend._connection, None) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_store_result(self, mock_get_database): - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - ret_val = self.backend._store_result( - sentinel.task_id, sentinel.result, sentinel.status) - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION) - mock_collection.save.assert_called_once_with(ANY) - self.assertEqual(sentinel.result, ret_val) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_get_task_meta_for(self, mock_get_database): - datetime.datetime = self._reset['datetime'] - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - mock_collection.find_one.return_value = MagicMock() - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - ret_val = self.backend._get_task_meta_for(sentinel.task_id) - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION) - self.assertEqual( - ['status', 'task_id', 'date_done', 'traceback', 'result', - 'children'], - list(ret_val.keys())) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_get_task_meta_for_no_result(self, mock_get_database): - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - mock_collection.find_one.return_value = None - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - ret_val = self.backend._get_task_meta_for(sentinel.task_id) - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION) - self.assertEqual({'status': states.PENDING, 'result': None}, ret_val) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_save_group(self, mock_get_database): - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - ret_val = self.backend._save_group( - sentinel.taskset_id, sentinel.result) - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION) - mock_collection.save.assert_called_once_with(ANY) - self.assertEqual(sentinel.result, ret_val) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_restore_group(self, mock_get_database): - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - mock_collection.find_one.return_value = MagicMock() - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - ret_val = self.backend._restore_group(sentinel.taskset_id) - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION) - mock_collection.find_one.assert_called_once_with( - {'_id': sentinel.taskset_id}) - self.assertEqual( - ['date_done', 'result', 'task_id'], - list(ret_val.keys()), - ) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_delete_group(self, mock_get_database): - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - self.backend._delete_group(sentinel.taskset_id) - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION) - mock_collection.remove.assert_called_once_with( - {'_id': sentinel.taskset_id}) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_forget(self, mock_get_database): - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - self.backend._forget(sentinel.task_id) - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with( - MONGODB_COLLECTION) - mock_collection.remove.assert_called_once_with( - {'_id': sentinel.task_id}) - - @patch('celery.backends.mongodb.MongoBackend._get_database') - def test_cleanup(self, mock_get_database): - datetime.datetime = self._reset['datetime'] - self.backend.taskmeta_collection = MONGODB_COLLECTION - - mock_database = MagicMock(spec=['__getitem__', '__setitem__']) - mock_collection = Mock() - - mock_get_database.return_value = mock_database - mock_database.__getitem__.return_value = mock_collection - - self.backend.app.now = datetime.datetime.utcnow - self.backend.cleanup() - - mock_get_database.assert_called_once_with() - mock_database.__getitem__.assert_called_once_with( - MONGODB_COLLECTION) - mock_collection.assert_called_once_with() - - def test_get_database_authfailure(self): - x = MongoBackend(app=self.app) - x._get_connection = Mock() - conn = x._get_connection.return_value = {} - db = conn[x.database_name] = Mock() - db.authenticate.return_value = False - x.user = 'jerry' - x.password = 'cere4l' - with self.assertRaises(ImproperlyConfigured): - x._get_database() - db.authenticate.assert_called_with('jerry', 'cere4l') diff --git a/awx/lib/site-packages/celery/tests/backends/test_redis.py b/awx/lib/site-packages/celery/tests/backends/test_redis.py deleted file mode 100644 index 0ecc5258b0..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_redis.py +++ /dev/null @@ -1,275 +0,0 @@ -from __future__ import absolute_import - -from datetime import timedelta - -from pickle import loads, dumps - -from celery import signature -from celery import states -from celery import group -from celery import uuid -from celery.datastructures import AttributeDict -from celery.exceptions import ImproperlyConfigured -from celery.utils.timeutils import timedelta_seconds - -from celery.tests.case import ( - AppCase, Mock, MockCallbacks, SkipTest, depends_on_current_app, patch, -) - - -class Connection(object): - connected = True - - def disconnect(self): - self.connected = False - - -class Pipeline(object): - - def __init__(self, client): - self.client = client - self.steps = [] - - def __getattr__(self, attr): - - def add_step(*args, **kwargs): - self.steps.append((getattr(self.client, attr), args, kwargs)) - return self - return add_step - - def execute(self): - return [step(*a, **kw) for step, a, kw in self.steps] - - -class Redis(MockCallbacks): - Connection = Connection - Pipeline = Pipeline - - def __init__(self, host=None, port=None, db=None, password=None, **kw): - self.host = host - self.port = port - self.db = db - self.password = password - self.keyspace = {} - self.expiry = {} - self.connection = self.Connection() - - def get(self, key): - return self.keyspace.get(key) - - def setex(self, key, value, expires): - self.set(key, value) - self.expire(key, expires) - - def set(self, key, value): - self.keyspace[key] = value - - def expire(self, key, expires): - self.expiry[key] = expires - return expires - - def delete(self, key): - return bool(self.keyspace.pop(key, None)) - - def pipeline(self): - return self.Pipeline(self) - - def _get_list(self, key): - try: - return self.keyspace[key] - except KeyError: - l = self.keyspace[key] = [] - return l - - def rpush(self, key, value): - self._get_list(key).append(value) - - def lrange(self, key, start, stop): - return self._get_list(key)[start:stop] - - def llen(self, key): - return len(self.keyspace.get(key) or []) - - -class redis(object): - Redis = Redis - - class ConnectionPool(object): - - def __init__(self, **kwargs): - pass - - class UnixDomainSocketConnection(object): - - def __init__(self, **kwargs): - pass - - -class test_RedisBackend(AppCase): - - def get_backend(self): - from celery.backends.redis import RedisBackend - - class _RedisBackend(RedisBackend): - redis = redis - - return _RedisBackend - - def setup(self): - self.Backend = self.get_backend() - - @depends_on_current_app - def test_reduce(self): - try: - from celery.backends.redis import RedisBackend - x = RedisBackend(app=self.app, new_join=True) - self.assertTrue(loads(dumps(x))) - except ImportError: - raise SkipTest('redis not installed') - - def test_no_redis(self): - self.Backend.redis = None - with self.assertRaises(ImproperlyConfigured): - self.Backend(app=self.app, new_join=True) - - def test_url(self): - x = self.Backend( - 'redis://:bosco@vandelay.com:123//1', app=self.app, - new_join=True, - ) - self.assertTrue(x.connparams) - self.assertEqual(x.connparams['host'], 'vandelay.com') - self.assertEqual(x.connparams['db'], 1) - self.assertEqual(x.connparams['port'], 123) - self.assertEqual(x.connparams['password'], 'bosco') - - def test_socket_url(self): - x = self.Backend( - 'socket:///tmp/redis.sock?virtual_host=/3', app=self.app, - new_join=True, - ) - self.assertTrue(x.connparams) - self.assertEqual(x.connparams['path'], '/tmp/redis.sock') - self.assertIs( - x.connparams['connection_class'], - redis.UnixDomainSocketConnection, - ) - self.assertNotIn('host', x.connparams) - self.assertNotIn('port', x.connparams) - self.assertEqual(x.connparams['db'], 3) - - def test_compat_propertie(self): - x = self.Backend( - 'redis://:bosco@vandelay.com:123//1', app=self.app, - new_join=True, - ) - with self.assertPendingDeprecation(): - self.assertEqual(x.host, 'vandelay.com') - with self.assertPendingDeprecation(): - self.assertEqual(x.db, 1) - with self.assertPendingDeprecation(): - self.assertEqual(x.port, 123) - with self.assertPendingDeprecation(): - self.assertEqual(x.password, 'bosco') - - def test_conf_raises_KeyError(self): - self.app.conf = AttributeDict({ - 'CELERY_RESULT_SERIALIZER': 'json', - 'CELERY_MAX_CACHED_RESULTS': 1, - 'CELERY_ACCEPT_CONTENT': ['json'], - 'CELERY_TASK_RESULT_EXPIRES': None, - }) - self.Backend(app=self.app, new_join=True) - - def test_expires_defaults_to_config(self): - self.app.conf.CELERY_TASK_RESULT_EXPIRES = 10 - b = self.Backend(expires=None, app=self.app, new_join=True) - self.assertEqual(b.expires, 10) - - def test_expires_is_int(self): - b = self.Backend(expires=48, app=self.app, new_join=True) - self.assertEqual(b.expires, 48) - - def test_set_new_join_from_url_query(self): - b = self.Backend('redis://?new_join=True;foobar=1', app=self.app) - self.assertEqual(b.on_chord_part_return, b._new_chord_return) - self.assertEqual(b.apply_chord, b._new_chord_apply) - - def test_default_is_old_join(self): - b = self.Backend(app=self.app) - self.assertNotEqual(b.on_chord_part_return, b._new_chord_return) - self.assertNotEqual(b.apply_chord, b._new_chord_apply) - - def test_expires_is_None(self): - b = self.Backend(expires=None, app=self.app, new_join=True) - self.assertEqual(b.expires, timedelta_seconds( - self.app.conf.CELERY_TASK_RESULT_EXPIRES)) - - def test_expires_is_timedelta(self): - b = self.Backend( - expires=timedelta(minutes=1), app=self.app, new_join=1, - ) - self.assertEqual(b.expires, 60) - - def test_apply_chord(self): - self.Backend(app=self.app, new_join=True).apply_chord( - group(app=self.app), (), 'group_id', {}, - result=[self.app.AsyncResult(x) for x in [1, 2, 3]], - ) - - def test_mget(self): - b = self.Backend(app=self.app, new_join=True) - self.assertTrue(b.mget(['a', 'b', 'c'])) - b.client.mget.assert_called_with(['a', 'b', 'c']) - - def test_set_no_expire(self): - b = self.Backend(app=self.app, new_join=True) - b.expires = None - b.set('foo', 'bar') - - @patch('celery.result.GroupResult.restore') - def test_on_chord_part_return(self, restore): - b = self.Backend(app=self.app, new_join=True) - - def create_task(): - tid = uuid() - task = Mock(name='task-{0}'.format(tid)) - task.name = 'foobarbaz' - self.app.tasks['foobarbaz'] = task - task.request.chord = signature(task) - task.request.id = tid - task.request.chord['chord_size'] = 10 - task.request.group = 'group_id' - return task - - tasks = [create_task() for i in range(10)] - - for i in range(10): - b.on_chord_part_return(tasks[i], states.SUCCESS, i) - self.assertTrue(b.client.rpush.call_count) - b.client.rpush.reset_mock() - self.assertTrue(b.client.lrange.call_count) - gkey = b.get_key_for_group('group_id', '.j') - b.client.delete.assert_called_with(gkey) - b.client.expire.assert_called_witeh(gkey, 86400) - - def test_process_cleanup(self): - self.Backend(app=self.app, new_join=True).process_cleanup() - - def test_get_set_forget(self): - b = self.Backend(app=self.app, new_join=True) - tid = uuid() - b.store_result(tid, 42, states.SUCCESS) - self.assertEqual(b.get_status(tid), states.SUCCESS) - self.assertEqual(b.get_result(tid), 42) - b.forget(tid) - self.assertEqual(b.get_status(tid), states.PENDING) - - def test_set_expires(self): - b = self.Backend(expires=512, app=self.app, new_join=True) - tid = uuid() - key = b.get_key_for_task(tid) - b.store_result(tid, 42, states.SUCCESS) - b.client.expire.assert_called_with( - key, 512, - ) diff --git a/awx/lib/site-packages/celery/tests/backends/test_rpc.py b/awx/lib/site-packages/celery/tests/backends/test_rpc.py deleted file mode 100644 index 6fe594c19d..0000000000 --- a/awx/lib/site-packages/celery/tests/backends/test_rpc.py +++ /dev/null @@ -1,75 +0,0 @@ -from __future__ import absolute_import - -from celery.backends.rpc import RPCBackend -from celery._state import _task_stack - -from celery.tests.case import AppCase, Mock, patch - - -class test_RPCBackend(AppCase): - - def setup(self): - self.b = RPCBackend(app=self.app) - - def test_oid(self): - oid = self.b.oid - oid2 = self.b.oid - self.assertEqual(oid, oid2) - self.assertEqual(oid, self.app.oid) - - def test_interface(self): - self.b.on_reply_declare('task_id') - - def test_destination_for(self): - req = Mock(name='request') - req.reply_to = 'reply_to' - req.correlation_id = 'corid' - self.assertTupleEqual( - self.b.destination_for('task_id', req), - ('reply_to', 'corid'), - ) - task = Mock() - _task_stack.push(task) - try: - task.request.reply_to = 'reply_to' - task.request.correlation_id = 'corid' - self.assertTupleEqual( - self.b.destination_for('task_id', None), - ('reply_to', 'corid'), - ) - finally: - _task_stack.pop() - - with self.assertRaises(RuntimeError): - self.b.destination_for('task_id', None) - - def test_binding(self): - queue = self.b.binding - self.assertEqual(queue.name, self.b.oid) - self.assertEqual(queue.exchange, self.b.exchange) - self.assertEqual(queue.routing_key, self.b.oid) - self.assertFalse(queue.durable) - self.assertFalse(queue.auto_delete) - - def test_many_bindings(self): - self.assertListEqual( - self.b._many_bindings(['a', 'b']), - [self.b.binding], - ) - - def test_create_binding(self): - self.assertEqual(self.b._create_binding('id'), self.b.binding) - - def test_on_task_call(self): - with patch('celery.backends.rpc.maybe_declare') as md: - with self.app.amqp.producer_pool.acquire() as prod: - self.b.on_task_call(prod, 'task_id'), - md.assert_called_with( - self.b.binding(prod.channel), - retry=True, - ) - - def test_create_exchange(self): - ex = self.b._create_exchange('name') - self.assertIsInstance(ex, self.b.Exchange) - self.assertEqual(ex.name, '') diff --git a/awx/lib/site-packages/celery/tests/bin/__init__.py b/awx/lib/site-packages/celery/tests/bin/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/bin/proj/__init__.py b/awx/lib/site-packages/celery/tests/bin/proj/__init__.py deleted file mode 100644 index ffe8fb0693..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/proj/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import absolute_import - -from celery import Celery - -hello = Celery(set_as_current=False) diff --git a/awx/lib/site-packages/celery/tests/bin/proj/app.py b/awx/lib/site-packages/celery/tests/bin/proj/app.py deleted file mode 100644 index f1fb15e2e4..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/proj/app.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import absolute_import - -from celery import Celery - -app = Celery(set_as_current=False) diff --git a/awx/lib/site-packages/celery/tests/bin/test_amqp.py b/awx/lib/site-packages/celery/tests/bin/test_amqp.py deleted file mode 100644 index 8840a9f102..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_amqp.py +++ /dev/null @@ -1,153 +0,0 @@ -from __future__ import absolute_import - -from celery.bin.amqp import ( - AMQPAdmin, - AMQShell, - dump_message, - amqp, - main, -) - -from celery.tests.case import AppCase, Mock, WhateverIO, patch - - -class test_AMQShell(AppCase): - - def setup(self): - self.fh = WhateverIO() - self.adm = self.create_adm() - self.shell = AMQShell(connect=self.adm.connect, out=self.fh) - - def create_adm(self, *args, **kwargs): - return AMQPAdmin(app=self.app, out=self.fh, *args, **kwargs) - - def test_queue_declare(self): - self.shell.onecmd('queue.declare foo') - self.assertIn('ok', self.fh.getvalue()) - - def test_missing_command(self): - self.shell.onecmd('foo foo') - self.assertIn('unknown syntax', self.fh.getvalue()) - - def RV(self): - raise Exception(self.fh.getvalue()) - - def test_spec_format_response(self): - spec = self.shell.amqp['exchange.declare'] - self.assertEqual(spec.format_response(None), 'ok.') - self.assertEqual(spec.format_response('NO'), 'NO') - - def test_missing_namespace(self): - self.shell.onecmd('ns.cmd arg') - self.assertIn('unknown syntax', self.fh.getvalue()) - - def test_help(self): - self.shell.onecmd('help') - self.assertIn('Example:', self.fh.getvalue()) - - def test_help_command(self): - self.shell.onecmd('help queue.declare') - self.assertIn('passive:no', self.fh.getvalue()) - - def test_help_unknown_command(self): - self.shell.onecmd('help foo.baz') - self.assertIn('unknown syntax', self.fh.getvalue()) - - def test_onecmd_error(self): - self.shell.dispatch = Mock() - self.shell.dispatch.side_effect = MemoryError() - self.shell.say = Mock() - self.assertFalse(self.shell.needs_reconnect) - self.shell.onecmd('hello') - self.assertTrue(self.shell.say.called) - self.assertTrue(self.shell.needs_reconnect) - - def test_exit(self): - with self.assertRaises(SystemExit): - self.shell.onecmd('exit') - self.assertIn("don't leave!", self.fh.getvalue()) - - def test_note_silent(self): - self.shell.silent = True - self.shell.note('foo bar') - self.assertNotIn('foo bar', self.fh.getvalue()) - - def test_reconnect(self): - self.shell.onecmd('queue.declare foo') - self.shell.needs_reconnect = True - self.shell.onecmd('queue.delete foo') - - def test_completenames(self): - self.assertEqual( - self.shell.completenames('queue.dec'), - ['queue.declare'], - ) - self.assertEqual( - sorted(self.shell.completenames('declare')), - sorted(['queue.declare', 'exchange.declare']), - ) - - def test_empty_line(self): - self.shell.emptyline = Mock() - self.shell.default = Mock() - self.shell.onecmd('') - self.shell.emptyline.assert_called_with() - self.shell.onecmd('foo') - self.shell.default.assert_called_with('foo') - - def test_respond(self): - self.shell.respond({'foo': 'bar'}) - self.assertIn('foo', self.fh.getvalue()) - - def test_prompt(self): - self.assertTrue(self.shell.prompt) - - def test_no_returns(self): - self.shell.onecmd('queue.declare foo') - self.shell.onecmd('exchange.declare bar direct yes') - self.shell.onecmd('queue.bind foo bar baz') - self.shell.onecmd('basic.ack 1') - - def test_dump_message(self): - m = Mock() - m.body = 'the quick brown fox' - m.properties = {'a': 1} - m.delivery_info = {'exchange': 'bar'} - self.assertTrue(dump_message(m)) - - def test_dump_message_no_message(self): - self.assertIn('No messages in queue', dump_message(None)) - - def test_note(self): - self.adm.silent = True - self.adm.note('FOO') - self.assertNotIn('FOO', self.fh.getvalue()) - - def test_run(self): - a = self.create_adm('queue.declare foo') - a.run() - self.assertIn('ok', self.fh.getvalue()) - - def test_run_loop(self): - a = self.create_adm() - a.Shell = Mock() - shell = a.Shell.return_value = Mock() - shell.cmdloop = Mock() - a.run() - shell.cmdloop.assert_called_with() - - shell.cmdloop.side_effect = KeyboardInterrupt() - a.run() - self.assertIn('bibi', self.fh.getvalue()) - - @patch('celery.bin.amqp.amqp') - def test_main(self, Command): - c = Command.return_value = Mock() - main() - c.execute_from_commandline.assert_called_with() - - @patch('celery.bin.amqp.AMQPAdmin') - def test_command(self, cls): - x = amqp(app=self.app) - x.run() - self.assertIs(cls.call_args[1]['app'], self.app) diff --git a/awx/lib/site-packages/celery/tests/bin/test_base.py b/awx/lib/site-packages/celery/tests/bin/test_base.py deleted file mode 100644 index 8d1d0d55dd..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_base.py +++ /dev/null @@ -1,316 +0,0 @@ -from __future__ import absolute_import - -import os - -from celery.bin.base import ( - Command, - Option, - Extensions, - HelpFormatter, -) -from celery.tests.case import ( - AppCase, Mock, depends_on_current_app, override_stdouts, patch, -) - - -class Object(object): - pass - - -class MyApp(object): - user_options = {'preload': None} - -APP = MyApp() # <-- Used by test_with_custom_app - - -class MockCommand(Command): - mock_args = ('arg1', 'arg2', 'arg3') - - def parse_options(self, prog_name, arguments, command=None): - options = Object() - options.foo = 'bar' - options.prog_name = prog_name - return options, self.mock_args - - def run(self, *args, **kwargs): - return args, kwargs - - -class test_Extensions(AppCase): - - def test_load(self): - with patch('pkg_resources.iter_entry_points') as iterep: - with patch('celery.bin.base.symbol_by_name') as symbyname: - ep = Mock() - ep.name = 'ep' - ep.module_name = 'foo' - ep.attrs = ['bar', 'baz'] - iterep.return_value = [ep] - cls = symbyname.return_value = Mock() - register = Mock() - e = Extensions('unit', register) - e.load() - symbyname.assert_called_with('foo:bar') - register.assert_called_with(cls, name='ep') - - with patch('celery.bin.base.symbol_by_name') as symbyname: - symbyname.side_effect = SyntaxError() - with patch('warnings.warn') as warn: - e.load() - self.assertTrue(warn.called) - - with patch('celery.bin.base.symbol_by_name') as symbyname: - symbyname.side_effect = KeyError('foo') - with self.assertRaises(KeyError): - e.load() - - -class test_HelpFormatter(AppCase): - - def test_format_epilog(self): - f = HelpFormatter() - self.assertTrue(f.format_epilog('hello')) - self.assertFalse(f.format_epilog('')) - - def test_format_description(self): - f = HelpFormatter() - self.assertTrue(f.format_description('hello')) - - -class test_Command(AppCase): - - def test_get_options(self): - cmd = Command() - cmd.option_list = (1, 2, 3) - self.assertTupleEqual(cmd.get_options(), (1, 2, 3)) - - def test_custom_description(self): - - class C(Command): - description = 'foo' - - c = C() - self.assertEqual(c.description, 'foo') - - def test_register_callbacks(self): - c = Command(on_error=8, on_usage_error=9) - self.assertEqual(c.on_error, 8) - self.assertEqual(c.on_usage_error, 9) - - def test_run_raises_UsageError(self): - cb = Mock() - c = Command(on_usage_error=cb) - c.verify_args = Mock() - c.run = Mock() - exc = c.run.side_effect = c.UsageError('foo', status=3) - - self.assertEqual(c(), exc.status) - cb.assert_called_with(exc) - c.verify_args.assert_called_with(()) - - def test_default_on_usage_error(self): - cmd = Command() - cmd.handle_error = Mock() - exc = Exception() - cmd.on_usage_error(exc) - cmd.handle_error.assert_called_with(exc) - - def test_verify_args_missing(self): - c = Command() - - def run(a, b, c): - pass - c.run = run - - with self.assertRaises(c.UsageError): - c.verify_args((1, )) - c.verify_args((1, 2, 3)) - - def test_run_interface(self): - with self.assertRaises(NotImplementedError): - Command().run() - - @patch('sys.stdout') - def test_early_version(self, stdout): - cmd = Command() - with self.assertRaises(SystemExit): - cmd.early_version(['--version']) - - def test_execute_from_commandline(self): - cmd = MockCommand(app=self.app) - args1, kwargs1 = cmd.execute_from_commandline() # sys.argv - self.assertTupleEqual(args1, cmd.mock_args) - self.assertDictContainsSubset({'foo': 'bar'}, kwargs1) - self.assertTrue(kwargs1.get('prog_name')) - args2, kwargs2 = cmd.execute_from_commandline(['foo']) # pass list - self.assertTupleEqual(args2, cmd.mock_args) - self.assertDictContainsSubset({'foo': 'bar', 'prog_name': 'foo'}, - kwargs2) - - def test_with_bogus_args(self): - with override_stdouts() as (_, stderr): - cmd = MockCommand(app=self.app) - cmd.supports_args = False - with self.assertRaises(SystemExit): - cmd.execute_from_commandline(argv=['--bogus']) - self.assertTrue(stderr.getvalue()) - self.assertIn('Unrecognized', stderr.getvalue()) - - def test_with_custom_config_module(self): - prev = os.environ.pop('CELERY_CONFIG_MODULE', None) - try: - cmd = MockCommand(app=self.app) - cmd.setup_app_from_commandline(['--config=foo.bar.baz']) - self.assertEqual(os.environ.get('CELERY_CONFIG_MODULE'), - 'foo.bar.baz') - finally: - if prev: - os.environ['CELERY_CONFIG_MODULE'] = prev - else: - os.environ.pop('CELERY_CONFIG_MODULE', None) - - def test_with_custom_broker(self): - prev = os.environ.pop('CELERY_BROKER_URL', None) - try: - cmd = MockCommand(app=self.app) - cmd.setup_app_from_commandline(['--broker=xyzza://']) - self.assertEqual( - os.environ.get('CELERY_BROKER_URL'), 'xyzza://', - ) - finally: - if prev: - os.environ['CELERY_BROKER_URL'] = prev - else: - os.environ.pop('CELERY_BROKER_URL', None) - - def test_with_custom_app(self): - cmd = MockCommand(app=self.app) - app = '.'.join([__name__, 'APP']) - cmd.setup_app_from_commandline(['--app=%s' % (app, ), - '--loglevel=INFO']) - self.assertIs(cmd.app, APP) - cmd.setup_app_from_commandline(['-A', app, - '--loglevel=INFO']) - self.assertIs(cmd.app, APP) - - def test_setup_app_sets_quiet(self): - cmd = MockCommand(app=self.app) - cmd.setup_app_from_commandline(['-q']) - self.assertTrue(cmd.quiet) - cmd2 = MockCommand(app=self.app) - cmd2.setup_app_from_commandline(['--quiet']) - self.assertTrue(cmd2.quiet) - - def test_setup_app_sets_chdir(self): - with patch('os.chdir') as chdir: - cmd = MockCommand(app=self.app) - cmd.setup_app_from_commandline(['--workdir=/opt']) - chdir.assert_called_with('/opt') - - def test_setup_app_sets_loader(self): - prev = os.environ.get('CELERY_LOADER') - try: - cmd = MockCommand(app=self.app) - cmd.setup_app_from_commandline(['--loader=X.Y:Z']) - self.assertEqual(os.environ['CELERY_LOADER'], 'X.Y:Z') - finally: - if prev is not None: - os.environ['CELERY_LOADER'] = prev - - def test_setup_app_no_respect(self): - cmd = MockCommand(app=self.app) - cmd.respects_app_option = False - with patch('celery.bin.base.Celery') as cp: - cmd.setup_app_from_commandline(['--app=x.y:z']) - self.assertTrue(cp.called) - - def test_setup_app_custom_app(self): - cmd = MockCommand(app=self.app) - app = cmd.app = Mock() - app.user_options = {'preload': None} - cmd.setup_app_from_commandline([]) - self.assertEqual(cmd.app, app) - - def test_find_app_suspects(self): - cmd = MockCommand(app=self.app) - self.assertTrue(cmd.find_app('celery.tests.bin.proj.app')) - self.assertTrue(cmd.find_app('celery.tests.bin.proj')) - self.assertTrue(cmd.find_app('celery.tests.bin.proj:hello')) - self.assertTrue(cmd.find_app('celery.tests.bin.proj.app:app')) - - with self.assertRaises(AttributeError): - cmd.find_app(__name__) - - def test_host_format(self): - cmd = MockCommand(app=self.app) - with patch('socket.gethostname') as hn: - hn.return_value = 'blacktron.example.com' - self.assertEqual(cmd.host_format(''), '') - self.assertEqual( - cmd.host_format('celery@%h'), - 'celery@blacktron.example.com', - ) - self.assertEqual( - cmd.host_format('celery@%d'), - 'celery@example.com', - ) - self.assertEqual( - cmd.host_format('celery@%n'), - 'celery@blacktron', - ) - - def test_say_chat_quiet(self): - cmd = MockCommand(app=self.app) - cmd.quiet = True - self.assertIsNone(cmd.say_chat('<-', 'foo', 'foo')) - - def test_say_chat_show_body(self): - cmd = MockCommand(app=self.app) - cmd.out = Mock() - cmd.show_body = True - cmd.say_chat('->', 'foo', 'body') - cmd.out.assert_called_with('body') - - def test_say_chat_no_body(self): - cmd = MockCommand(app=self.app) - cmd.out = Mock() - cmd.show_body = False - cmd.say_chat('->', 'foo', 'body') - - @depends_on_current_app - def test_with_cmdline_config(self): - cmd = MockCommand(app=self.app) - cmd.enable_config_from_cmdline = True - cmd.namespace = 'celeryd' - rest = cmd.setup_app_from_commandline(argv=[ - '--loglevel=INFO', '--', - 'broker.url=amqp://broker.example.com', - '.prefetch_multiplier=100']) - self.assertEqual(cmd.app.conf.BROKER_URL, - 'amqp://broker.example.com') - self.assertEqual(cmd.app.conf.CELERYD_PREFETCH_MULTIPLIER, 100) - self.assertListEqual(rest, ['--loglevel=INFO']) - - def test_find_app(self): - cmd = MockCommand(app=self.app) - with patch('celery.bin.base.symbol_by_name') as sbn: - from types import ModuleType - x = ModuleType('proj') - - def on_sbn(*args, **kwargs): - - def after(*args, **kwargs): - x.app = 'quick brown fox' - x.__path__ = None - return x - sbn.side_effect = after - return x - sbn.side_effect = on_sbn - x.__path__ = [True] - self.assertEqual(cmd.find_app('proj'), 'quick brown fox') - - def test_parse_preload_options_shortopt(self): - cmd = Command() - cmd.preload_options = (Option('-s', action='store', dest='silent'), ) - acc = cmd.parse_preload_options(['-s', 'yes']) - self.assertEqual(acc.get('silent'), 'yes') diff --git a/awx/lib/site-packages/celery/tests/bin/test_beat.py b/awx/lib/site-packages/celery/tests/bin/test_beat.py deleted file mode 100644 index 45a74389a4..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_beat.py +++ /dev/null @@ -1,196 +0,0 @@ -from __future__ import absolute_import - -import logging -import sys - -from collections import defaultdict - -from celery import beat -from celery import platforms -from celery.bin import beat as beat_bin -from celery.apps import beat as beatapp - -from celery.tests.case import AppCase, Mock, patch, restore_logging -from kombu.tests.case import redirect_stdouts - - -class MockedShelveModule(object): - shelves = defaultdict(lambda: {}) - - def open(self, filename, *args, **kwargs): - return self.shelves[filename] -mocked_shelve = MockedShelveModule() - - -class MockService(beat.Service): - started = False - in_sync = False - persistence = mocked_shelve - - def start(self): - self.__class__.started = True - - def sync(self): - self.__class__.in_sync = True - - -class MockBeat(beatapp.Beat): - running = False - - def run(self): - MockBeat.running = True - - -class MockBeat2(beatapp.Beat): - Service = MockService - - def install_sync_handler(self, b): - pass - - -class MockBeat3(beatapp.Beat): - Service = MockService - - def install_sync_handler(self, b): - raise TypeError('xxx') - - -class test_Beat(AppCase): - - def test_loglevel_string(self): - b = beatapp.Beat(app=self.app, loglevel='DEBUG', - redirect_stdouts=False) - self.assertEqual(b.loglevel, logging.DEBUG) - - b2 = beatapp.Beat(app=self.app, loglevel=logging.DEBUG, - redirect_stdouts=False) - self.assertEqual(b2.loglevel, logging.DEBUG) - - def test_colorize(self): - self.app.log.setup = Mock() - b = beatapp.Beat(app=self.app, no_color=True, - redirect_stdouts=False) - b.setup_logging() - self.assertTrue(self.app.log.setup.called) - self.assertEqual(self.app.log.setup.call_args[1]['colorize'], False) - - def test_init_loader(self): - b = beatapp.Beat(app=self.app, redirect_stdouts=False) - b.init_loader() - - def test_process_title(self): - b = beatapp.Beat(app=self.app, redirect_stdouts=False) - b.set_process_title() - - def test_run(self): - b = MockBeat2(app=self.app, redirect_stdouts=False) - MockService.started = False - b.run() - self.assertTrue(MockService.started) - - def psig(self, fun, *args, **kwargs): - handlers = {} - - class Signals(platforms.Signals): - - def __setitem__(self, sig, handler): - handlers[sig] = handler - - p, platforms.signals = platforms.signals, Signals() - try: - fun(*args, **kwargs) - return handlers - finally: - platforms.signals = p - - def test_install_sync_handler(self): - b = beatapp.Beat(app=self.app, redirect_stdouts=False) - clock = MockService(app=self.app) - MockService.in_sync = False - handlers = self.psig(b.install_sync_handler, clock) - with self.assertRaises(SystemExit): - handlers['SIGINT']('SIGINT', object()) - self.assertTrue(MockService.in_sync) - MockService.in_sync = False - - def test_setup_logging(self): - with restore_logging(): - try: - # py3k - delattr(sys.stdout, 'logger') - except AttributeError: - pass - b = beatapp.Beat(app=self.app, redirect_stdouts=False) - b.redirect_stdouts = False - b.app.log.already_setup = False - b.setup_logging() - with self.assertRaises(AttributeError): - sys.stdout.logger - - @redirect_stdouts - @patch('celery.apps.beat.logger') - def test_logs_errors(self, logger, stdout, stderr): - with restore_logging(): - b = MockBeat3( - app=self.app, redirect_stdouts=False, socket_timeout=None, - ) - b.start_scheduler() - self.assertTrue(logger.critical.called) - - @redirect_stdouts - @patch('celery.platforms.create_pidlock') - def test_use_pidfile(self, create_pidlock, stdout, stderr): - b = MockBeat2(app=self.app, pidfile='pidfilelockfilepid', - socket_timeout=None, redirect_stdouts=False) - b.start_scheduler() - self.assertTrue(create_pidlock.called) - - -class MockDaemonContext(object): - opened = False - closed = False - - def __init__(self, *args, **kwargs): - pass - - def open(self): - self.__class__.opened = True - return self - __enter__ = open - - def close(self, *args): - self.__class__.closed = True - __exit__ = close - - -class test_div(AppCase): - - def setup(self): - self.prev, beatapp.Beat = beatapp.Beat, MockBeat - self.ctx, beat_bin.detached = ( - beat_bin.detached, MockDaemonContext, - ) - - def teardown(self): - beatapp.Beat = self.prev - - def test_main(self): - sys.argv = [sys.argv[0], '-s', 'foo'] - try: - beat_bin.main(app=self.app) - self.assertTrue(MockBeat.running) - finally: - MockBeat.running = False - - def test_detach(self): - cmd = beat_bin.beat() - cmd.app = self.app - cmd.run(detach=True) - self.assertTrue(MockDaemonContext.opened) - self.assertTrue(MockDaemonContext.closed) - - def test_parse_options(self): - cmd = beat_bin.beat() - cmd.app = self.app - options, args = cmd.parse_options('celery beat', ['-s', 'foo']) - self.assertEqual(options.schedule, 'foo') diff --git a/awx/lib/site-packages/celery/tests/bin/test_celery.py b/awx/lib/site-packages/celery/tests/bin/test_celery.py deleted file mode 100644 index fbfdb62f69..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_celery.py +++ /dev/null @@ -1,588 +0,0 @@ -from __future__ import absolute_import - -import sys - -from anyjson import dumps -from datetime import datetime - -from celery import __main__ -from celery.platforms import EX_FAILURE, EX_USAGE, EX_OK -from celery.bin.base import Error -from celery.bin.celery import ( - Command, - list_, - call, - purge, - result, - inspect, - control, - status, - migrate, - help, - report, - CeleryCommand, - determine_exit_status, - multi, - main as mainfun, - _RemoteControl, - command, -) - -from celery.tests.case import ( - AppCase, Mock, WhateverIO, override_stdouts, patch, -) - - -class test__main__(AppCase): - - def test_warn_deprecated(self): - with override_stdouts() as (stdout, _): - __main__._warn_deprecated('YADDA YADDA') - self.assertIn('command is deprecated', stdout.getvalue()) - self.assertIn('YADDA YADDA', stdout.getvalue()) - - def test_main(self): - with patch('celery.__main__.maybe_patch_concurrency') as mpc: - with patch('celery.bin.celery.main') as main: - __main__.main() - mpc.assert_called_with() - main.assert_called_with() - - def test_compat_worker(self): - with patch('celery.__main__.maybe_patch_concurrency') as mpc: - with patch('celery.__main__._warn_deprecated') as depr: - with patch('celery.bin.worker.main') as main: - __main__._compat_worker() - mpc.assert_called_with() - depr.assert_called_with('celery worker') - main.assert_called_with() - - def test_compat_multi(self): - with patch('celery.__main__.maybe_patch_concurrency') as mpc: - with patch('celery.__main__._warn_deprecated') as depr: - with patch('celery.bin.multi.main') as main: - __main__._compat_multi() - self.assertFalse(mpc.called) - depr.assert_called_with('celery multi') - main.assert_called_with() - - def test_compat_beat(self): - with patch('celery.__main__.maybe_patch_concurrency') as mpc: - with patch('celery.__main__._warn_deprecated') as depr: - with patch('celery.bin.beat.main') as main: - __main__._compat_beat() - mpc.assert_called_with() - depr.assert_called_with('celery beat') - main.assert_called_with() - - -class test_Command(AppCase): - - def test_Error_repr(self): - x = Error('something happened') - self.assertIsNotNone(x.status) - self.assertTrue(x.reason) - self.assertTrue(str(x)) - - def setup(self): - self.out = WhateverIO() - self.err = WhateverIO() - self.cmd = Command(self.app, stdout=self.out, stderr=self.err) - - def test_error(self): - self.cmd.out = Mock() - self.cmd.error('FOO') - self.assertTrue(self.cmd.out.called) - - def test_out(self): - f = Mock() - self.cmd.out('foo', f) - - def test_call(self): - - def ok_run(): - pass - - self.cmd.run = ok_run - self.assertEqual(self.cmd(), EX_OK) - - def error_run(): - raise Error('error', EX_FAILURE) - self.cmd.run = error_run - self.assertEqual(self.cmd(), EX_FAILURE) - - def test_run_from_argv(self): - with self.assertRaises(NotImplementedError): - self.cmd.run_from_argv('prog', ['foo', 'bar']) - - def test_pretty_list(self): - self.assertEqual(self.cmd.pretty([])[1], '- empty -') - self.assertIn('bar', self.cmd.pretty(['foo', 'bar'])[1]) - - def test_pretty_dict(self): - self.assertIn( - 'OK', - str(self.cmd.pretty({'ok': 'the quick brown fox'})[0]), - ) - self.assertIn( - 'ERROR', - str(self.cmd.pretty({'error': 'the quick brown fox'})[0]), - ) - - def test_pretty(self): - self.assertIn('OK', str(self.cmd.pretty('the quick brown'))) - self.assertIn('OK', str(self.cmd.pretty(object()))) - self.assertIn('OK', str(self.cmd.pretty({'foo': 'bar'}))) - - -class test_list(AppCase): - - def test_list_bindings_no_support(self): - l = list_(app=self.app, stderr=WhateverIO()) - management = Mock() - management.get_bindings.side_effect = NotImplementedError() - with self.assertRaises(Error): - l.list_bindings(management) - - def test_run(self): - l = list_(app=self.app, stderr=WhateverIO()) - l.run('bindings') - - with self.assertRaises(Error): - l.run(None) - - with self.assertRaises(Error): - l.run('foo') - - -class test_call(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - @patch('celery.app.base.Celery.send_task') - def test_run(self, send_task): - a = call(app=self.app, stderr=WhateverIO(), stdout=WhateverIO()) - a.run(self.add.name) - self.assertTrue(send_task.called) - - a.run(self.add.name, - args=dumps([4, 4]), - kwargs=dumps({'x': 2, 'y': 2})) - self.assertEqual(send_task.call_args[1]['args'], [4, 4]) - self.assertEqual(send_task.call_args[1]['kwargs'], {'x': 2, 'y': 2}) - - a.run(self.add.name, expires=10, countdown=10) - self.assertEqual(send_task.call_args[1]['expires'], 10) - self.assertEqual(send_task.call_args[1]['countdown'], 10) - - now = datetime.now() - iso = now.isoformat() - a.run(self.add.name, expires=iso) - self.assertEqual(send_task.call_args[1]['expires'], now) - with self.assertRaises(ValueError): - a.run(self.add.name, expires='foobaribazibar') - - -class test_purge(AppCase): - - @patch('celery.app.control.Control.purge') - def test_run(self, purge_): - out = WhateverIO() - a = purge(app=self.app, stdout=out) - purge_.return_value = 0 - a.run(force=True) - self.assertIn('No messages purged', out.getvalue()) - - purge_.return_value = 100 - a.run(force=True) - self.assertIn('100 messages', out.getvalue()) - - -class test_result(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - def test_run(self): - with patch('celery.result.AsyncResult.get') as get: - out = WhateverIO() - r = result(app=self.app, stdout=out) - get.return_value = 'Jerry' - r.run('id') - self.assertIn('Jerry', out.getvalue()) - - get.return_value = 'Elaine' - r.run('id', task=self.add.name) - self.assertIn('Elaine', out.getvalue()) - - with patch('celery.result.AsyncResult.traceback') as tb: - r.run('id', task=self.add.name, traceback=True) - self.assertIn(str(tb), out.getvalue()) - - -class test_status(AppCase): - - @patch('celery.bin.celery.inspect') - def test_run(self, inspect_): - out, err = WhateverIO(), WhateverIO() - ins = inspect_.return_value = Mock() - ins.run.return_value = [] - s = status(self.app, stdout=out, stderr=err) - with self.assertRaises(Error): - s.run() - - ins.run.return_value = ['a', 'b', 'c'] - s.run() - self.assertIn('3 nodes online', out.getvalue()) - s.run(quiet=True) - - -class test_migrate(AppCase): - - @patch('celery.contrib.migrate.migrate_tasks') - def test_run(self, migrate_tasks): - out = WhateverIO() - m = migrate(app=self.app, stdout=out, stderr=WhateverIO()) - with self.assertRaises(TypeError): - m.run() - self.assertFalse(migrate_tasks.called) - - m.run('memory://foo', 'memory://bar') - self.assertTrue(migrate_tasks.called) - - state = Mock() - state.count = 10 - state.strtotal = 30 - m.on_migrate_task(state, {'task': 'tasks.add', 'id': 'ID'}, None) - self.assertIn('10/30', out.getvalue()) - - -class test_report(AppCase): - - def test_run(self): - out = WhateverIO() - r = report(app=self.app, stdout=out) - self.assertEqual(r.run(), EX_OK) - self.assertTrue(out.getvalue()) - - -class test_help(AppCase): - - def test_run(self): - out = WhateverIO() - h = help(app=self.app, stdout=out) - h.parser = Mock() - self.assertEqual(h.run(), EX_USAGE) - self.assertTrue(out.getvalue()) - self.assertTrue(h.usage('help')) - h.parser.print_help.assert_called_with() - - -class test_CeleryCommand(AppCase): - - def test_execute_from_commandline(self): - x = CeleryCommand(app=self.app) - x.handle_argv = Mock() - x.handle_argv.return_value = 1 - with self.assertRaises(SystemExit): - x.execute_from_commandline() - - x.handle_argv.return_value = True - with self.assertRaises(SystemExit): - x.execute_from_commandline() - - x.handle_argv.side_effect = KeyboardInterrupt() - with self.assertRaises(SystemExit): - x.execute_from_commandline() - - x.respects_app_option = True - with self.assertRaises(SystemExit): - x.execute_from_commandline(['celery', 'multi']) - self.assertFalse(x.respects_app_option) - x.respects_app_option = True - with self.assertRaises(SystemExit): - x.execute_from_commandline(['manage.py', 'celery', 'multi']) - self.assertFalse(x.respects_app_option) - - def test_with_pool_option(self): - x = CeleryCommand(app=self.app) - self.assertIsNone(x.with_pool_option(['celery', 'events'])) - self.assertTrue(x.with_pool_option(['celery', 'worker'])) - self.assertTrue(x.with_pool_option(['manage.py', 'celery', 'worker'])) - - def test_load_extensions_no_commands(self): - with patch('celery.bin.celery.Extensions') as Ext: - ext = Ext.return_value = Mock(name='Extension') - ext.load.return_value = None - x = CeleryCommand(app=self.app) - x.load_extension_commands() - - def test_determine_exit_status(self): - self.assertEqual(determine_exit_status('true'), EX_OK) - self.assertEqual(determine_exit_status(''), EX_FAILURE) - - def test_relocate_args_from_start(self): - x = CeleryCommand(app=self.app) - self.assertEqual(x._relocate_args_from_start(None), []) - self.assertEqual( - x._relocate_args_from_start( - ['-l', 'debug', 'worker', '-c', '3', '--foo'], - ), - ['worker', '-c', '3', '--foo', '-l', 'debug'], - ) - self.assertEqual( - x._relocate_args_from_start( - ['--pool=gevent', '-l', 'debug', 'worker', '--foo', '-c', '3'], - ), - ['worker', '--foo', '-c', '3', '--pool=gevent', '-l', 'debug'], - ) - self.assertEqual( - x._relocate_args_from_start(['foo', '--foo=1']), - ['foo', '--foo=1'], - ) - - def test_handle_argv(self): - x = CeleryCommand(app=self.app) - x.execute = Mock() - x.handle_argv('celery', []) - x.execute.assert_called_with('help', ['help']) - - x.handle_argv('celery', ['start', 'foo']) - x.execute.assert_called_with('start', ['start', 'foo']) - - def test_execute(self): - x = CeleryCommand(app=self.app) - Help = x.commands['help'] = Mock() - help = Help.return_value = Mock() - x.execute('fooox', ['a']) - help.run_from_argv.assert_called_with(x.prog_name, [], command='help') - help.reset() - x.execute('help', ['help']) - help.run_from_argv.assert_called_with(x.prog_name, [], command='help') - - Dummy = x.commands['dummy'] = Mock() - dummy = Dummy.return_value = Mock() - exc = dummy.run_from_argv.side_effect = Error( - 'foo', status='EX_FAILURE', - ) - x.on_error = Mock(name='on_error') - help.reset() - x.execute('dummy', ['dummy']) - x.on_error.assert_called_with(exc) - dummy.run_from_argv.assert_called_with( - x.prog_name, [], command='dummy', - ) - help.run_from_argv.assert_called_with( - x.prog_name, [], command='help', - ) - - exc = dummy.run_from_argv.side_effect = x.UsageError('foo') - x.on_usage_error = Mock() - x.execute('dummy', ['dummy']) - x.on_usage_error.assert_called_with(exc) - - def test_on_usage_error(self): - x = CeleryCommand(app=self.app) - x.error = Mock() - x.on_usage_error(x.UsageError('foo'), command=None) - self.assertTrue(x.error.called) - x.on_usage_error(x.UsageError('foo'), command='dummy') - - def test_prepare_prog_name(self): - x = CeleryCommand(app=self.app) - main = Mock(name='__main__') - main.__file__ = '/opt/foo.py' - with patch.dict(sys.modules, __main__=main): - self.assertEqual(x.prepare_prog_name('__main__.py'), '/opt/foo.py') - self.assertEqual(x.prepare_prog_name('celery'), 'celery') - - -class test_RemoteControl(AppCase): - - def test_call_interface(self): - with self.assertRaises(NotImplementedError): - _RemoteControl(app=self.app).call() - - -class test_inspect(AppCase): - - def test_usage(self): - self.assertTrue(inspect(app=self.app).usage('foo')) - - def test_command_info(self): - i = inspect(app=self.app) - self.assertTrue(i.get_command_info( - 'ping', help=True, color=i.colored.red, - )) - - def test_list_commands_color(self): - i = inspect(app=self.app) - self.assertTrue(i.list_commands( - help=True, color=i.colored.red, - )) - self.assertTrue(i.list_commands( - help=False, color=None, - )) - - def test_epilog(self): - self.assertTrue(inspect(app=self.app).epilog) - - def test_do_call_method_sql_transport_type(self): - self.app.connection = Mock() - conn = self.app.connection.return_value = Mock(name='Connection') - conn.transport.driver_type = 'sql' - i = inspect(app=self.app) - with self.assertRaises(i.Error): - i.do_call_method(['ping']) - - def test_say_directions(self): - i = inspect(self.app) - i.out = Mock() - i.quiet = True - i.say_chat('<-', 'hello out') - self.assertFalse(i.out.called) - - i.say_chat('->', 'hello in') - self.assertTrue(i.out.called) - - i.quiet = False - i.out.reset_mock() - i.say_chat('<-', 'hello out', 'body') - self.assertTrue(i.out.called) - - @patch('celery.app.control.Control.inspect') - def test_run(self, real): - out = WhateverIO() - i = inspect(app=self.app, stdout=out) - with self.assertRaises(Error): - i.run() - with self.assertRaises(Error): - i.run('help') - with self.assertRaises(Error): - i.run('xyzzybaz') - - i.run('ping') - self.assertTrue(real.called) - i.run('ping', destination='foo,bar') - self.assertEqual(real.call_args[1]['destination'], ['foo', 'bar']) - self.assertEqual(real.call_args[1]['timeout'], 0.2) - callback = real.call_args[1]['callback'] - - callback({'foo': {'ok': 'pong'}}) - self.assertIn('OK', out.getvalue()) - - instance = real.return_value = Mock() - instance.ping.return_value = None - with self.assertRaises(Error): - i.run('ping') - - out.seek(0) - out.truncate() - i.quiet = True - i.say_chat('<-', 'hello') - self.assertFalse(out.getvalue()) - - -class test_control(AppCase): - - def control(self, patch_call, *args, **kwargs): - kwargs.setdefault('app', Mock(name='app')) - c = control(*args, **kwargs) - if patch_call: - c.call = Mock(name='control.call') - return c - - def test_call(self): - i = self.control(False) - i.call('foo', 1, kw=2) - i.app.control.foo.assert_called_with(1, kw=2, reply=True) - - def test_pool_grow(self): - i = self.control(True) - i.pool_grow('pool_grow', n=2) - i.call.assert_called_with('pool_grow', 2) - - def test_pool_shrink(self): - i = self.control(True) - i.pool_shrink('pool_shrink', n=2) - i.call.assert_called_with('pool_shrink', 2) - - def test_autoscale(self): - i = self.control(True) - i.autoscale('autoscale', max=3, min=2) - i.call.assert_called_with('autoscale', 3, 2) - - def test_rate_limit(self): - i = self.control(True) - i.rate_limit('rate_limit', 'proj.add', '1/s') - i.call.assert_called_with('rate_limit', 'proj.add', '1/s') - - def test_time_limit(self): - i = self.control(True) - i.time_limit('time_limit', 'proj.add', 10, 30) - i.call.assert_called_with('time_limit', 'proj.add', 10, 30) - - def test_add_consumer(self): - i = self.control(True) - i.add_consumer( - 'add_consumer', 'queue', 'exchange', 'topic', 'rkey', - durable=True, - ) - i.call.assert_called_with( - 'add_consumer', 'queue', 'exchange', 'topic', 'rkey', - durable=True, - ) - - def test_cancel_consumer(self): - i = self.control(True) - i.cancel_consumer('cancel_consumer', 'queue') - i.call.assert_called_with('cancel_consumer', 'queue') - - -class test_multi(AppCase): - - def test_get_options(self): - self.assertTupleEqual(multi(app=self.app).get_options(), ()) - - def test_run_from_argv(self): - with patch('celery.bin.multi.MultiTool') as MultiTool: - m = MultiTool.return_value = Mock() - multi(self.app).run_from_argv('celery', ['arg'], command='multi') - m.execute_from_commandline.assert_called_with( - ['multi', 'arg'], 'celery', - ) - - -class test_main(AppCase): - - @patch('celery.bin.celery.CeleryCommand') - def test_main(self, Command): - cmd = Command.return_value = Mock() - mainfun() - cmd.execute_from_commandline.assert_called_with(None) - - @patch('celery.bin.celery.CeleryCommand') - def test_main_KeyboardInterrupt(self, Command): - cmd = Command.return_value = Mock() - cmd.execute_from_commandline.side_effect = KeyboardInterrupt() - mainfun() - cmd.execute_from_commandline.assert_called_with(None) - - -class test_compat(AppCase): - - def test_compat_command_decorator(self): - with patch('celery.bin.celery.CeleryCommand') as CC: - self.assertEqual(command(), CC.register_command) - fun = Mock(name='fun') - command(fun) - CC.register_command.assert_called_with(fun) diff --git a/awx/lib/site-packages/celery/tests/bin/test_celeryd_detach.py b/awx/lib/site-packages/celery/tests/bin/test_celeryd_detach.py deleted file mode 100644 index 2b6e5ae8d4..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_celeryd_detach.py +++ /dev/null @@ -1,100 +0,0 @@ -from __future__ import absolute_import - -from celery.platforms import IS_WINDOWS -from celery.bin.celeryd_detach import ( - detach, - detached_celeryd, - main, -) - -from celery.tests.case import AppCase, Mock, override_stdouts, patch - - -if not IS_WINDOWS: - class test_detached(AppCase): - - @patch('celery.bin.celeryd_detach.detached') - @patch('os.execv') - @patch('celery.bin.celeryd_detach.logger') - @patch('celery.app.log.Logging.setup_logging_subsystem') - def test_execs(self, setup_logs, logger, execv, detached): - context = detached.return_value = Mock() - context.__enter__ = Mock() - context.__exit__ = Mock() - - detach('/bin/boo', ['a', 'b', 'c'], logfile='/var/log', - pidfile='/var/pid') - detached.assert_called_with('/var/log', '/var/pid', None, None, 0, - None, False) - execv.assert_called_with('/bin/boo', ['/bin/boo', 'a', 'b', 'c']) - - execv.side_effect = Exception('foo') - r = detach('/bin/boo', ['a', 'b', 'c'], - logfile='/var/log', pidfile='/var/pid', app=self.app) - context.__enter__.assert_called_with() - self.assertTrue(logger.critical.called) - setup_logs.assert_called_with('ERROR', '/var/log') - self.assertEqual(r, 1) - - -class test_PartialOptionParser(AppCase): - - def test_parser(self): - x = detached_celeryd(self.app) - p = x.Parser('celeryd_detach') - options, values = p.parse_args(['--logfile=foo', '--fake', '--enable', - 'a', 'b', '-c1', '-d', '2']) - self.assertEqual(options.logfile, 'foo') - self.assertEqual(values, ['a', 'b']) - self.assertEqual(p.leftovers, ['--enable', '-c1', '-d', '2']) - - with override_stdouts(): - with self.assertRaises(SystemExit): - p.parse_args(['--logfile']) - p.get_option('--logfile').nargs = 2 - with self.assertRaises(SystemExit): - p.parse_args(['--logfile=a']) - with self.assertRaises(SystemExit): - p.parse_args(['--fake=abc']) - - assert p.get_option('--logfile').nargs == 2 - p.parse_args(['--logfile=a', 'b']) - p.get_option('--logfile').nargs = 1 - - -class test_Command(AppCase): - argv = ['--autoscale=10,2', '-c', '1', - '--logfile=/var/log', '-lDEBUG', - '--', '.disable_rate_limits=1'] - - def test_parse_options(self): - x = detached_celeryd(app=self.app) - o, v, l = x.parse_options('cd', self.argv) - self.assertEqual(o.logfile, '/var/log') - self.assertEqual(l, ['--autoscale=10,2', '-c', '1', - '-lDEBUG', '--logfile=/var/log', - '--pidfile=celeryd.pid']) - x.parse_options('cd', []) # no args - - @patch('sys.exit') - @patch('celery.bin.celeryd_detach.detach') - def test_execute_from_commandline(self, detach, exit): - x = detached_celeryd(app=self.app) - x.execute_from_commandline(self.argv) - self.assertTrue(exit.called) - detach.assert_called_with( - path=x.execv_path, uid=None, gid=None, - umask=0, fake=False, logfile='/var/log', pidfile='celeryd.pid', - argv=x.execv_argv + [ - '-c', '1', '-lDEBUG', - '--logfile=/var/log', '--pidfile=celeryd.pid', - '--', '.disable_rate_limits=1' - ], - app=self.app, - ) - - @patch('celery.bin.celeryd_detach.detached_celeryd') - def test_main(self, command): - c = command.return_value = Mock() - main(self.app) - c.execute_from_commandline.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/bin/test_celeryevdump.py b/awx/lib/site-packages/celery/tests/bin/test_celeryevdump.py deleted file mode 100644 index 09cdc4d1ff..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_celeryevdump.py +++ /dev/null @@ -1,68 +0,0 @@ -from __future__ import absolute_import - -from time import time - -from celery.events.dumper import ( - humanize_type, - Dumper, - evdump, -) - -from celery.tests.case import AppCase, Mock, WhateverIO, patch - - -class test_Dumper(AppCase): - - def setup(self): - self.out = WhateverIO() - self.dumper = Dumper(out=self.out) - - def test_humanize_type(self): - self.assertEqual(humanize_type('worker-offline'), 'shutdown') - self.assertEqual(humanize_type('task-started'), 'task started') - - def test_format_task_event(self): - self.dumper.format_task_event( - 'worker@example.com', time(), 'task-started', 'tasks.add', {}) - self.assertTrue(self.out.getvalue()) - - def test_on_event(self): - event = { - 'hostname': 'worker@example.com', - 'timestamp': time(), - 'uuid': '1ef', - 'name': 'tasks.add', - 'args': '(2, 2)', - 'kwargs': '{}', - } - self.dumper.on_event(dict(event, type='task-received')) - self.assertTrue(self.out.getvalue()) - self.dumper.on_event(dict(event, type='task-revoked')) - self.dumper.on_event(dict(event, type='worker-online')) - - @patch('celery.events.EventReceiver.capture') - def test_evdump(self, capture): - capture.side_effect = KeyboardInterrupt() - evdump(app=self.app) - - def test_evdump_error_handler(self): - app = Mock(name='app') - with patch('celery.events.dumper.Dumper') as Dumper: - Dumper.return_value = Mock(name='dumper') - recv = app.events.Receiver.return_value = Mock() - - def se(*_a, **_k): - recv.capture.side_effect = SystemExit() - raise KeyError() - recv.capture.side_effect = se - - Conn = app.connection.return_value = Mock(name='conn') - conn = Conn.clone.return_value = Mock(name='cloned_conn') - conn.connection_errors = (KeyError, ) - conn.channel_errors = () - - evdump(app) - self.assertTrue(conn.ensure_connection.called) - errback = conn.ensure_connection.call_args[0][0] - errback(KeyError(), 1) - self.assertTrue(conn.as_uri.called) diff --git a/awx/lib/site-packages/celery/tests/bin/test_events.py b/awx/lib/site-packages/celery/tests/bin/test_events.py deleted file mode 100644 index a6e79f75af..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_events.py +++ /dev/null @@ -1,73 +0,0 @@ -from __future__ import absolute_import - -from celery.bin import events - -from celery.tests.case import AppCase, SkipTest, patch, _old_patch - - -class MockCommand(object): - executed = [] - - def execute_from_commandline(self, **kwargs): - self.executed.append(True) - - -def proctitle(prog, info=None): - proctitle.last = (prog, info) -proctitle.last = () - - -class test_events(AppCase): - - def setup(self): - self.ev = events.events(app=self.app) - - @_old_patch('celery.events.dumper', 'evdump', - lambda **kw: 'me dumper, you?') - @_old_patch('celery.bin.events', 'set_process_title', proctitle) - def test_run_dump(self): - self.assertEqual(self.ev.run(dump=True), 'me dumper, you?') - self.assertIn('celery events:dump', proctitle.last[0]) - - def test_run_top(self): - try: - import curses # noqa - except ImportError: - raise SkipTest('curses monitor requires curses') - - @_old_patch('celery.events.cursesmon', 'evtop', - lambda **kw: 'me top, you?') - @_old_patch('celery.bin.events', 'set_process_title', proctitle) - def _inner(): - self.assertEqual(self.ev.run(), 'me top, you?') - self.assertIn('celery events:top', proctitle.last[0]) - return _inner() - - @_old_patch('celery.events.snapshot', 'evcam', - lambda *a, **k: (a, k)) - @_old_patch('celery.bin.events', 'set_process_title', proctitle) - def test_run_cam(self): - a, kw = self.ev.run(camera='foo.bar.baz', logfile='logfile') - self.assertEqual(a[0], 'foo.bar.baz') - self.assertEqual(kw['freq'], 1.0) - self.assertIsNone(kw['maxrate']) - self.assertEqual(kw['loglevel'], 'INFO') - self.assertEqual(kw['logfile'], 'logfile') - self.assertIn('celery events:cam', proctitle.last[0]) - - @patch('celery.events.snapshot.evcam') - @patch('celery.bin.events.detached') - def test_run_cam_detached(self, detached, evcam): - self.ev.prog_name = 'celery events' - self.ev.run_evcam('myapp.Camera', detach=True) - self.assertTrue(detached.called) - self.assertTrue(evcam.called) - - def test_get_options(self): - self.assertTrue(self.ev.get_options()) - - @_old_patch('celery.bin.events', 'events', MockCommand) - def test_main(self): - MockCommand.executed = [] - events.main() - self.assertTrue(MockCommand.executed) diff --git a/awx/lib/site-packages/celery/tests/bin/test_multi.py b/awx/lib/site-packages/celery/tests/bin/test_multi.py deleted file mode 100644 index 0b2ecd9815..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_multi.py +++ /dev/null @@ -1,474 +0,0 @@ -from __future__ import absolute_import - -import errno -import signal -import sys - -from celery.bin.multi import ( - main, - MultiTool, - findsig, - abbreviations, - parse_ns_range, - format_opt, - quote, - NamespacedOptionParser, - multi_args, - __doc__ as doc, -) - -from celery.tests.case import AppCase, Mock, WhateverIO, SkipTest, patch - - -class test_functions(AppCase): - - def test_findsig(self): - self.assertEqual(findsig(['a', 'b', 'c', '-1']), 1) - self.assertEqual(findsig(['--foo=1', '-9']), 9) - self.assertEqual(findsig(['-INT']), signal.SIGINT) - self.assertEqual(findsig([]), signal.SIGTERM) - self.assertEqual(findsig(['-s']), signal.SIGTERM) - self.assertEqual(findsig(['-log']), signal.SIGTERM) - - def test_abbreviations(self): - expander = abbreviations({'%s': 'START', - '%x': 'STOP'}) - self.assertEqual(expander('foo%s'), 'fooSTART') - self.assertEqual(expander('foo%x'), 'fooSTOP') - self.assertEqual(expander('foo%y'), 'foo%y') - self.assertIsNone(expander(None)) - - def test_parse_ns_range(self): - self.assertEqual(parse_ns_range('1-3', True), ['1', '2', '3']) - self.assertEqual(parse_ns_range('1-3', False), ['1-3']) - self.assertEqual(parse_ns_range( - '1-3,10,11,20', True), - ['1', '2', '3', '10', '11', '20'], - ) - - def test_format_opt(self): - self.assertEqual(format_opt('--foo', None), '--foo') - self.assertEqual(format_opt('-c', 1), '-c 1') - self.assertEqual(format_opt('--log', 'foo'), '--log=foo') - - def test_quote(self): - self.assertEqual(quote("the 'quick"), "'the '\\''quick'") - - -class test_NamespacedOptionParser(AppCase): - - def test_parse(self): - x = NamespacedOptionParser(['-c:1,3', '4']) - self.assertEqual(x.namespaces.get('1,3'), {'-c': '4'}) - x = NamespacedOptionParser(['-c:jerry,elaine', '5', - '--loglevel:kramer=DEBUG', - '--flag', - '--logfile=foo', '-Q', 'bar', 'a', 'b', - '--', '.disable_rate_limits=1']) - self.assertEqual(x.options, {'--logfile': 'foo', - '-Q': 'bar', - '--flag': None}) - self.assertEqual(x.values, ['a', 'b']) - self.assertEqual(x.namespaces.get('jerry,elaine'), {'-c': '5'}) - self.assertEqual(x.namespaces.get('kramer'), {'--loglevel': 'DEBUG'}) - self.assertEqual(x.passthrough, '-- .disable_rate_limits=1') - - -class test_multi_args(AppCase): - - @patch('socket.gethostname') - def test_parse(self, gethostname): - p = NamespacedOptionParser([ - '-c:jerry,elaine', '5', - '--loglevel:kramer=DEBUG', - '--flag', - '--logfile=foo', '-Q', 'bar', 'jerry', - 'elaine', 'kramer', - '--', '.disable_rate_limits=1', - ]) - it = multi_args(p, cmd='COMMAND', append='*AP*', - prefix='*P*', suffix='*S*') - names = list(it) - - def assert_line_in(name, args): - self.assertIn(name, [tup[0] for tup in names]) - argv = None - for item in names: - if item[0] == name: - argv = item[1] - self.assertTrue(argv) - for arg in args: - self.assertIn(arg, argv) - - assert_line_in( - '*P*jerry@*S*', - ['COMMAND', '-n *P*jerry@*S*', '-Q bar', - '-c 5', '--flag', '--logfile=foo', - '-- .disable_rate_limits=1', '*AP*'], - ) - assert_line_in( - '*P*elaine@*S*', - ['COMMAND', '-n *P*elaine@*S*', '-Q bar', - '-c 5', '--flag', '--logfile=foo', - '-- .disable_rate_limits=1', '*AP*'], - ) - assert_line_in( - '*P*kramer@*S*', - ['COMMAND', '--loglevel=DEBUG', '-n *P*kramer@*S*', - '-Q bar', '--flag', '--logfile=foo', - '-- .disable_rate_limits=1', '*AP*'], - ) - expand = names[0][2] - self.assertEqual(expand('%h'), '*P*jerry@*S*') - self.assertEqual(expand('%n'), 'jerry') - names2 = list(multi_args(p, cmd='COMMAND', append='', - prefix='*P*', suffix='*S*')) - self.assertEqual(names2[0][1][-1], '-- .disable_rate_limits=1') - - gethostname.return_value = 'example.com' - p2 = NamespacedOptionParser(['10', '-c:1', '5']) - names3 = list(multi_args(p2, cmd='COMMAND')) - self.assertEqual(len(names3), 10) - self.assertEqual( - names3[0][0:2], - ('celery1@example.com', - ['COMMAND', '-n celery1@example.com', '-c 5', '']), - ) - for i, worker in enumerate(names3[1:]): - self.assertEqual( - worker[0:2], - ('celery%s@example.com' % (i + 2), - ['COMMAND', '-n celery%s@example.com' % (i + 2), '']), - ) - - names4 = list(multi_args(p2, cmd='COMMAND', suffix='""')) - self.assertEqual(len(names4), 10) - self.assertEqual( - names4[0][0:2], - ('celery1@', - ['COMMAND', '-n celery1@', '-c 5', '']), - ) - - p3 = NamespacedOptionParser(['foo@', '-c:foo', '5']) - names5 = list(multi_args(p3, cmd='COMMAND', suffix='""')) - self.assertEqual( - names5[0][0:2], - ('foo@', - ['COMMAND', '-n foo@', '-c 5', '']), - ) - - -class test_MultiTool(AppCase): - - def setup(self): - self.fh = WhateverIO() - self.env = {} - self.t = MultiTool(env=self.env, fh=self.fh) - - def test_note(self): - self.t.note('hello world') - self.assertEqual(self.fh.getvalue(), 'hello world\n') - - def test_note_quiet(self): - self.t.quiet = True - self.t.note('hello world') - self.assertFalse(self.fh.getvalue()) - - def test_info(self): - self.t.verbose = True - self.t.info('hello info') - self.assertEqual(self.fh.getvalue(), 'hello info\n') - - def test_info_not_verbose(self): - self.t.verbose = False - self.t.info('hello info') - self.assertFalse(self.fh.getvalue()) - - def test_error(self): - self.t.say = Mock() - self.t.usage = Mock() - self.assertEqual(self.t.error('foo'), 1) - self.t.say.assert_called_with('foo') - self.t.usage.assert_called_with() - - self.t.say = Mock() - self.assertEqual(self.t.error(), 1) - self.assertFalse(self.t.say.called) - - self.assertEqual(self.t.retcode, 1) - - @patch('celery.bin.multi.Popen') - def test_waitexec(self, Popen): - self.t.note = Mock() - pipe = Popen.return_value = Mock() - pipe.wait.return_value = -10 - self.assertEqual(self.t.waitexec(['-m', 'foo'], 'path'), 10) - Popen.assert_called_with(['path', '-m', 'foo'], env=self.t.env) - self.t.note.assert_called_with('* Child was terminated by signal 10') - - pipe.wait.return_value = 2 - self.assertEqual(self.t.waitexec(['-m', 'foo'], 'path'), 2) - self.t.note.assert_called_with( - '* Child terminated with errorcode 2', - ) - - pipe.wait.return_value = 0 - self.assertFalse(self.t.waitexec(['-m', 'foo', 'path'])) - - def test_nosplash(self): - self.t.nosplash = True - self.t.splash() - self.assertFalse(self.fh.getvalue()) - - def test_splash(self): - self.t.nosplash = False - self.t.splash() - self.assertIn('celery multi', self.fh.getvalue()) - - def test_usage(self): - self.t.usage() - self.assertTrue(self.fh.getvalue()) - - def test_help(self): - self.t.help([]) - self.assertIn(doc, self.fh.getvalue()) - - def test_expand(self): - self.t.expand(['foo%n', 'ask', 'klask', 'dask']) - self.assertEqual( - self.fh.getvalue(), 'fooask\nfooklask\nfoodask\n', - ) - - def test_restart(self): - stop = self.t._stop_nodes = Mock() - self.t.restart(['jerry', 'george'], 'celery worker') - waitexec = self.t.waitexec = Mock() - self.assertTrue(stop.called) - callback = stop.call_args[1]['callback'] - self.assertTrue(callback) - - waitexec.return_value = 0 - callback('jerry', ['arg'], 13) - waitexec.assert_called_with(['arg']) - self.assertIn('OK', self.fh.getvalue()) - self.fh.seek(0) - self.fh.truncate() - - waitexec.return_value = 1 - callback('jerry', ['arg'], 13) - self.assertIn('FAILED', self.fh.getvalue()) - - def test_stop(self): - self.t.getpids = Mock() - self.t.getpids.return_value = [2, 3, 4] - self.t.shutdown_nodes = Mock() - self.t.stop(['a', 'b', '-INT'], 'celery worker') - self.t.shutdown_nodes.assert_called_with( - [2, 3, 4], sig=signal.SIGINT, retry=None, callback=None, - - ) - - def test_kill(self): - if not hasattr(signal, 'SIGKILL'): - raise SkipTest('SIGKILL not supported by this platform') - self.t.getpids = Mock() - self.t.getpids.return_value = [ - ('a', None, 10), - ('b', None, 11), - ('c', None, 12) - ] - sig = self.t.signal_node = Mock() - - self.t.kill(['a', 'b', 'c'], 'celery worker') - - sigs = sig.call_args_list - self.assertEqual(len(sigs), 3) - self.assertEqual(sigs[0][0], ('a', 10, signal.SIGKILL)) - self.assertEqual(sigs[1][0], ('b', 11, signal.SIGKILL)) - self.assertEqual(sigs[2][0], ('c', 12, signal.SIGKILL)) - - def prepare_pidfile_for_getpids(self, Pidfile): - class pids(object): - - def __init__(self, path): - self.path = path - - def read_pid(self): - try: - return {'foo.pid': 10, - 'bar.pid': 11}[self.path] - except KeyError: - raise ValueError() - Pidfile.side_effect = pids - - @patch('celery.bin.multi.Pidfile') - @patch('socket.gethostname') - def test_getpids(self, gethostname, Pidfile): - gethostname.return_value = 'e.com' - self.prepare_pidfile_for_getpids(Pidfile) - callback = Mock() - - p = NamespacedOptionParser(['foo', 'bar', 'baz']) - nodes = self.t.getpids(p, 'celery worker', callback=callback) - node_0, node_1 = nodes - self.assertEqual(node_0[0], 'foo@e.com') - self.assertEqual( - sorted(node_0[1]), - sorted(('celery worker', '--pidfile=foo.pid', - '-n foo@e.com', '')), - ) - self.assertEqual(node_0[2], 10) - - self.assertEqual(node_1[0], 'bar@e.com') - self.assertEqual( - sorted(node_1[1]), - sorted(('celery worker', '--pidfile=bar.pid', - '-n bar@e.com', '')), - ) - self.assertEqual(node_1[2], 11) - self.assertTrue(callback.called) - cargs, _ = callback.call_args - self.assertEqual(cargs[0], 'baz@e.com') - self.assertItemsEqual( - cargs[1], - ['celery worker', '--pidfile=baz.pid', '-n baz@e.com', ''], - ) - self.assertIsNone(cargs[2]) - self.assertIn('DOWN', self.fh.getvalue()) - - # without callback, should work - nodes = self.t.getpids(p, 'celery worker', callback=None) - - @patch('celery.bin.multi.Pidfile') - @patch('socket.gethostname') - @patch('celery.bin.multi.sleep') - def test_shutdown_nodes(self, slepp, gethostname, Pidfile): - gethostname.return_value = 'e.com' - self.prepare_pidfile_for_getpids(Pidfile) - self.assertIsNone(self.t.shutdown_nodes([])) - self.t.signal_node = Mock() - node_alive = self.t.node_alive = Mock() - self.t.node_alive.return_value = False - - callback = Mock() - self.t.stop(['foo', 'bar', 'baz'], 'celery worker', callback=callback) - sigs = sorted(self.t.signal_node.call_args_list) - self.assertEqual(len(sigs), 2) - self.assertIn( - ('foo@e.com', 10, signal.SIGTERM), - [tup[0] for tup in sigs], - ) - self.assertIn( - ('bar@e.com', 11, signal.SIGTERM), - [tup[0] for tup in sigs], - ) - self.t.signal_node.return_value = False - self.assertTrue(callback.called) - self.t.stop(['foo', 'bar', 'baz'], 'celery worker', callback=None) - - def on_node_alive(pid): - if node_alive.call_count > 4: - return True - return False - self.t.signal_node.return_value = True - self.t.node_alive.side_effect = on_node_alive - self.t.stop(['foo', 'bar', 'baz'], 'celery worker', retry=True) - - @patch('os.kill') - def test_node_alive(self, kill): - kill.return_value = True - self.assertTrue(self.t.node_alive(13)) - esrch = OSError() - esrch.errno = errno.ESRCH - kill.side_effect = esrch - self.assertFalse(self.t.node_alive(13)) - kill.assert_called_with(13, 0) - - enoent = OSError() - enoent.errno = errno.ENOENT - kill.side_effect = enoent - with self.assertRaises(OSError): - self.t.node_alive(13) - - @patch('os.kill') - def test_signal_node(self, kill): - kill.return_value = True - self.assertTrue(self.t.signal_node('foo', 13, 9)) - esrch = OSError() - esrch.errno = errno.ESRCH - kill.side_effect = esrch - self.assertFalse(self.t.signal_node('foo', 13, 9)) - kill.assert_called_with(13, 9) - self.assertIn('Could not signal foo', self.fh.getvalue()) - - enoent = OSError() - enoent.errno = errno.ENOENT - kill.side_effect = enoent - with self.assertRaises(OSError): - self.t.signal_node('foo', 13, 9) - - def test_start(self): - self.t.waitexec = Mock() - self.t.waitexec.return_value = 0 - self.assertFalse(self.t.start(['foo', 'bar', 'baz'], 'celery worker')) - - self.t.waitexec.return_value = 1 - self.assertFalse(self.t.start(['foo', 'bar', 'baz'], 'celery worker')) - - def test_show(self): - self.t.show(['foo', 'bar', 'baz'], 'celery worker') - self.assertTrue(self.fh.getvalue()) - - @patch('socket.gethostname') - def test_get(self, gethostname): - gethostname.return_value = 'e.com' - self.t.get(['xuzzy@e.com', 'foo', 'bar', 'baz'], 'celery worker') - self.assertFalse(self.fh.getvalue()) - self.t.get(['foo@e.com', 'foo', 'bar', 'baz'], 'celery worker') - self.assertTrue(self.fh.getvalue()) - - @patch('socket.gethostname') - def test_names(self, gethostname): - gethostname.return_value = 'e.com' - self.t.names(['foo', 'bar', 'baz'], 'celery worker') - self.assertIn('foo@e.com\nbar@e.com\nbaz@e.com', self.fh.getvalue()) - - def test_execute_from_commandline(self): - start = self.t.commands['start'] = Mock() - self.t.error = Mock() - self.t.execute_from_commandline(['multi', 'start', 'foo', 'bar']) - self.assertFalse(self.t.error.called) - start.assert_called_with(['foo', 'bar'], 'celery worker') - - self.t.error = Mock() - self.t.execute_from_commandline(['multi', 'frob', 'foo', 'bar']) - self.t.error.assert_called_with('Invalid command: frob') - - self.t.error = Mock() - self.t.execute_from_commandline(['multi']) - self.t.error.assert_called_with() - - self.t.error = Mock() - self.t.execute_from_commandline(['multi', '-foo']) - self.t.error.assert_called_with() - - self.t.execute_from_commandline( - ['multi', 'start', 'foo', - '--nosplash', '--quiet', '-q', '--verbose', '--no-color'], - ) - self.assertTrue(self.t.nosplash) - self.assertTrue(self.t.quiet) - self.assertTrue(self.t.verbose) - self.assertTrue(self.t.no_color) - - def test_stopwait(self): - self.t._stop_nodes = Mock() - self.t.stopwait(['foo', 'bar', 'baz'], 'celery worker') - self.assertEqual(self.t._stop_nodes.call_args[1]['retry'], 2) - - @patch('celery.bin.multi.MultiTool') - def test_main(self, MultiTool): - m = MultiTool.return_value = Mock() - with self.assertRaises(SystemExit): - main() - m.execute_from_commandline.assert_called_with(sys.argv) diff --git a/awx/lib/site-packages/celery/tests/bin/test_worker.py b/awx/lib/site-packages/celery/tests/bin/test_worker.py deleted file mode 100644 index fbb7c52c22..0000000000 --- a/awx/lib/site-packages/celery/tests/bin/test_worker.py +++ /dev/null @@ -1,694 +0,0 @@ -from __future__ import absolute_import - -import logging -import os -import sys - -from functools import wraps - -from billiard import current_process -from kombu import Exchange, Queue - -from celery import platforms -from celery import signals -from celery.app import trace -from celery.apps import worker as cd -from celery.bin.worker import worker, main as worker_main -from celery.exceptions import ( - ImproperlyConfigured, WorkerShutdown, WorkerTerminate, -) -from celery.utils.log import ensure_process_aware_logger -from celery.worker import state - -from celery.tests.case import ( - AppCase, - Mock, - SkipTest, - WhateverIO, - patch, - skip_if_pypy, - skip_if_jython, -) - -ensure_process_aware_logger() - - -class WorkerAppCase(AppCase): - - def tearDown(self): - super(WorkerAppCase, self).tearDown() - trace.reset_worker_optimizations() - - -def disable_stdouts(fun): - - @wraps(fun) - def disable(*args, **kwargs): - prev_out, prev_err = sys.stdout, sys.stderr - prev_rout, prev_rerr = sys.__stdout__, sys.__stderr__ - sys.stdout = sys.__stdout__ = WhateverIO() - sys.stderr = sys.__stderr__ = WhateverIO() - try: - return fun(*args, **kwargs) - finally: - sys.stdout = prev_out - sys.stderr = prev_err - sys.__stdout__ = prev_rout - sys.__stderr__ = prev_rerr - - return disable - - -class Worker(cd.Worker): - redirect_stdouts = False - - def start(self, *args, **kwargs): - self.on_start() - - -class test_Worker(WorkerAppCase): - Worker = Worker - - @disable_stdouts - def test_queues_string(self): - w = self.app.Worker() - w.setup_queues('foo,bar,baz') - self.assertTrue('foo' in self.app.amqp.queues) - - @disable_stdouts - def test_cpu_count(self): - with patch('celery.worker.cpu_count') as cpu_count: - cpu_count.side_effect = NotImplementedError() - w = self.app.Worker(concurrency=None) - self.assertEqual(w.concurrency, 2) - w = self.app.Worker(concurrency=5) - self.assertEqual(w.concurrency, 5) - - @disable_stdouts - def test_windows_B_option(self): - self.app.IS_WINDOWS = True - with self.assertRaises(SystemExit): - worker(app=self.app).run(beat=True) - - def test_setup_concurrency_very_early(self): - x = worker() - x.run = Mock() - with self.assertRaises(ImportError): - x.execute_from_commandline(['worker', '-P', 'xyzybox']) - - def test_run_from_argv_basic(self): - x = worker(app=self.app) - x.run = Mock() - x.maybe_detach = Mock() - - def run(*args, **kwargs): - pass - x.run = run - x.run_from_argv('celery', []) - self.assertTrue(x.maybe_detach.called) - - def test_maybe_detach(self): - x = worker(app=self.app) - with patch('celery.bin.worker.detached_celeryd') as detached: - x.maybe_detach([]) - self.assertFalse(detached.called) - with self.assertRaises(SystemExit): - x.maybe_detach(['--detach']) - self.assertTrue(detached.called) - - @disable_stdouts - def test_invalid_loglevel_gives_error(self): - x = worker(app=self.app) - with self.assertRaises(SystemExit): - x.run(loglevel='GRIM_REAPER') - - def test_no_loglevel(self): - self.app.Worker = Mock() - worker(app=self.app).run(loglevel=None) - - def test_tasklist(self): - worker = self.app.Worker() - self.assertTrue(worker.app.tasks) - self.assertTrue(worker.app.finalized) - self.assertTrue(worker.tasklist(include_builtins=True)) - worker.tasklist(include_builtins=False) - - def test_extra_info(self): - worker = self.app.Worker() - worker.loglevel = logging.WARNING - self.assertFalse(worker.extra_info()) - worker.loglevel = logging.INFO - self.assertTrue(worker.extra_info()) - - @disable_stdouts - def test_loglevel_string(self): - worker = self.Worker(app=self.app, loglevel='INFO') - self.assertEqual(worker.loglevel, logging.INFO) - - @disable_stdouts - def test_run_worker(self): - handlers = {} - - class Signals(platforms.Signals): - - def __setitem__(self, sig, handler): - handlers[sig] = handler - - p = platforms.signals - platforms.signals = Signals() - try: - w = self.Worker(app=self.app) - w._isatty = False - w.on_start() - for sig in 'SIGINT', 'SIGHUP', 'SIGTERM': - self.assertIn(sig, handlers) - - handlers.clear() - w = self.Worker(app=self.app) - w._isatty = True - w.on_start() - for sig in 'SIGINT', 'SIGTERM': - self.assertIn(sig, handlers) - self.assertNotIn('SIGHUP', handlers) - finally: - platforms.signals = p - - @disable_stdouts - def test_startup_info(self): - worker = self.Worker(app=self.app) - worker.on_start() - self.assertTrue(worker.startup_info()) - worker.loglevel = logging.DEBUG - self.assertTrue(worker.startup_info()) - worker.loglevel = logging.INFO - self.assertTrue(worker.startup_info()) - worker.autoscale = 13, 10 - self.assertTrue(worker.startup_info()) - - prev_loader = self.app.loader - worker = self.Worker(app=self.app, queues='foo,bar,baz,xuzzy,do,re,mi') - self.app.loader = Mock() - self.app.loader.__module__ = 'acme.baked_beans' - self.assertTrue(worker.startup_info()) - - self.app.loader = Mock() - self.app.loader.__module__ = 'celery.loaders.foo' - self.assertTrue(worker.startup_info()) - - from celery.loaders.app import AppLoader - self.app.loader = AppLoader(app=self.app) - self.assertTrue(worker.startup_info()) - - self.app.loader = prev_loader - worker.send_events = True - self.assertTrue(worker.startup_info()) - - # test when there are too few output lines - # to draft the ascii art onto - prev, cd.ARTLINES = cd.ARTLINES, ['the quick brown fox'] - self.assertTrue(worker.startup_info()) - - @disable_stdouts - def test_run(self): - self.Worker(app=self.app).on_start() - self.Worker(app=self.app, purge=True).on_start() - worker = self.Worker(app=self.app) - worker.on_start() - - @disable_stdouts - def test_purge_messages(self): - self.Worker(app=self.app).purge_messages() - - @disable_stdouts - def test_init_queues(self): - app = self.app - c = app.conf - app.amqp.queues = app.amqp.Queues({ - 'celery': {'exchange': 'celery', - 'routing_key': 'celery'}, - 'video': {'exchange': 'video', - 'routing_key': 'video'}, - }) - worker = self.Worker(app=self.app) - worker.setup_queues(['video']) - self.assertIn('video', app.amqp.queues) - self.assertIn('video', app.amqp.queues.consume_from) - self.assertIn('celery', app.amqp.queues) - self.assertNotIn('celery', app.amqp.queues.consume_from) - - c.CELERY_CREATE_MISSING_QUEUES = False - del(app.amqp.queues) - with self.assertRaises(ImproperlyConfigured): - self.Worker(app=self.app).setup_queues(['image']) - del(app.amqp.queues) - c.CELERY_CREATE_MISSING_QUEUES = True - worker = self.Worker(app=self.app) - worker.setup_queues(['image']) - self.assertIn('image', app.amqp.queues.consume_from) - self.assertEqual( - Queue('image', Exchange('image'), routing_key='image'), - app.amqp.queues['image'], - ) - - @disable_stdouts - def test_autoscale_argument(self): - worker1 = self.Worker(app=self.app, autoscale='10,3') - self.assertListEqual(worker1.autoscale, [10, 3]) - worker2 = self.Worker(app=self.app, autoscale='10') - self.assertListEqual(worker2.autoscale, [10, 0]) - self.assert_no_logging_side_effect() - - def test_include_argument(self): - worker1 = self.Worker(app=self.app, include='os') - self.assertListEqual(worker1.include, ['os']) - worker2 = self.Worker(app=self.app, - include='os,sys') - self.assertListEqual(worker2.include, ['os', 'sys']) - self.Worker(app=self.app, include=['os', 'sys']) - - @disable_stdouts - def test_unknown_loglevel(self): - with self.assertRaises(SystemExit): - worker(app=self.app).run(loglevel='ALIEN') - worker1 = self.Worker(app=self.app, loglevel=0xFFFF) - self.assertEqual(worker1.loglevel, 0xFFFF) - - @disable_stdouts - @patch('os._exit') - def test_warns_if_running_as_privileged_user(self, _exit): - app = self.app - if app.IS_WINDOWS: - raise SkipTest('Not applicable on Windows') - - with patch('os.getuid') as getuid: - getuid.return_value = 0 - self.app.conf.CELERY_ACCEPT_CONTENT = ['pickle'] - worker = self.Worker(app=self.app) - worker.on_start() - _exit.assert_called_with(1) - from celery import platforms - platforms.C_FORCE_ROOT = True - try: - with self.assertWarnsRegex( - RuntimeWarning, - r'absolutely not recommended'): - worker = self.Worker(app=self.app) - worker.on_start() - finally: - platforms.C_FORCE_ROOT = False - self.app.conf.CELERY_ACCEPT_CONTENT = ['json'] - with self.assertWarnsRegex( - RuntimeWarning, - r'absolutely not recommended'): - worker = self.Worker(app=self.app) - worker.on_start() - - @disable_stdouts - def test_redirect_stdouts(self): - self.Worker(app=self.app, redirect_stdouts=False) - with self.assertRaises(AttributeError): - sys.stdout.logger - - @disable_stdouts - def test_on_start_custom_logging(self): - self.app.log.redirect_stdouts = Mock() - worker = self.Worker(app=self.app, redirect_stoutds=True) - worker._custom_logging = True - worker.on_start() - self.assertFalse(self.app.log.redirect_stdouts.called) - - def test_setup_logging_no_color(self): - worker = self.Worker( - app=self.app, redirect_stdouts=False, no_color=True, - ) - prev, self.app.log.setup = self.app.log.setup, Mock() - worker.setup_logging() - self.assertFalse(self.app.log.setup.call_args[1]['colorize']) - - @disable_stdouts - def test_startup_info_pool_is_str(self): - worker = self.Worker(app=self.app, redirect_stdouts=False) - worker.pool_cls = 'foo' - worker.startup_info() - - def test_redirect_stdouts_already_handled(self): - logging_setup = [False] - - @signals.setup_logging.connect - def on_logging_setup(**kwargs): - logging_setup[0] = True - - try: - worker = self.Worker(app=self.app, redirect_stdouts=False) - worker.app.log.already_setup = False - worker.setup_logging() - self.assertTrue(logging_setup[0]) - with self.assertRaises(AttributeError): - sys.stdout.logger - finally: - signals.setup_logging.disconnect(on_logging_setup) - - @disable_stdouts - def test_platform_tweaks_osx(self): - - class OSXWorker(Worker): - proxy_workaround_installed = False - - def osx_proxy_detection_workaround(self): - self.proxy_workaround_installed = True - - worker = OSXWorker(app=self.app, redirect_stdouts=False) - - def install_HUP_nosupport(controller): - controller.hup_not_supported_installed = True - - class Controller(object): - pass - - prev = cd.install_HUP_not_supported_handler - cd.install_HUP_not_supported_handler = install_HUP_nosupport - try: - worker.app.IS_OSX = True - controller = Controller() - worker.install_platform_tweaks(controller) - self.assertTrue(controller.hup_not_supported_installed) - self.assertTrue(worker.proxy_workaround_installed) - finally: - cd.install_HUP_not_supported_handler = prev - - @disable_stdouts - def test_general_platform_tweaks(self): - - restart_worker_handler_installed = [False] - - def install_worker_restart_handler(worker): - restart_worker_handler_installed[0] = True - - class Controller(object): - pass - - prev = cd.install_worker_restart_handler - cd.install_worker_restart_handler = install_worker_restart_handler - try: - worker = self.Worker(app=self.app) - worker.app.IS_OSX = False - worker.install_platform_tweaks(Controller()) - self.assertTrue(restart_worker_handler_installed[0]) - finally: - cd.install_worker_restart_handler = prev - - @disable_stdouts - def test_on_consumer_ready(self): - worker_ready_sent = [False] - - @signals.worker_ready.connect - def on_worker_ready(**kwargs): - worker_ready_sent[0] = True - - self.Worker(app=self.app).on_consumer_ready(object()) - self.assertTrue(worker_ready_sent[0]) - - -class test_funs(WorkerAppCase): - - def test_active_thread_count(self): - self.assertTrue(cd.active_thread_count()) - - @disable_stdouts - def test_set_process_status(self): - try: - __import__('setproctitle') - except ImportError: - raise SkipTest('setproctitle not installed') - worker = Worker(app=self.app, hostname='xyzza') - prev1, sys.argv = sys.argv, ['Arg0'] - try: - st = worker.set_process_status('Running') - self.assertIn('celeryd', st) - self.assertIn('xyzza', st) - self.assertIn('Running', st) - prev2, sys.argv = sys.argv, ['Arg0', 'Arg1'] - try: - st = worker.set_process_status('Running') - self.assertIn('celeryd', st) - self.assertIn('xyzza', st) - self.assertIn('Running', st) - self.assertIn('Arg1', st) - finally: - sys.argv = prev2 - finally: - sys.argv = prev1 - - @disable_stdouts - def test_parse_options(self): - cmd = worker() - cmd.app = self.app - opts, args = cmd.parse_options('worker', ['--concurrency=512']) - self.assertEqual(opts.concurrency, 512) - - @disable_stdouts - def test_main(self): - p, cd.Worker = cd.Worker, Worker - s, sys.argv = sys.argv, ['worker', '--discard'] - try: - worker_main(app=self.app) - finally: - cd.Worker = p - sys.argv = s - - -class test_signal_handlers(WorkerAppCase): - - class _Worker(object): - stopped = False - terminated = False - - def stop(self, in_sighandler=False): - self.stopped = True - - def terminate(self, in_sighandler=False): - self.terminated = True - - def psig(self, fun, *args, **kwargs): - handlers = {} - - class Signals(platforms.Signals): - def __setitem__(self, sig, handler): - handlers[sig] = handler - - p, platforms.signals = platforms.signals, Signals() - try: - fun(*args, **kwargs) - return handlers - finally: - platforms.signals = p - - @disable_stdouts - def test_worker_int_handler(self): - worker = self._Worker() - handlers = self.psig(cd.install_worker_int_handler, worker) - next_handlers = {} - state.should_stop = False - state.should_terminate = False - - class Signals(platforms.Signals): - - def __setitem__(self, sig, handler): - next_handlers[sig] = handler - - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 3 - p, platforms.signals = platforms.signals, Signals() - try: - handlers['SIGINT']('SIGINT', object()) - self.assertTrue(state.should_stop) - finally: - platforms.signals = p - state.should_stop = False - - try: - next_handlers['SIGINT']('SIGINT', object()) - self.assertTrue(state.should_terminate) - finally: - state.should_terminate = False - - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 1 - p, platforms.signals = platforms.signals, Signals() - try: - with self.assertRaises(WorkerShutdown): - handlers['SIGINT']('SIGINT', object()) - finally: - platforms.signals = p - - with self.assertRaises(WorkerTerminate): - next_handlers['SIGINT']('SIGINT', object()) - - @disable_stdouts - def test_worker_int_handler_only_stop_MainProcess(self): - try: - import _multiprocessing # noqa - except ImportError: - raise SkipTest('only relevant for multiprocessing') - process = current_process() - name, process.name = process.name, 'OtherProcess' - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 3 - try: - worker = self._Worker() - handlers = self.psig(cd.install_worker_int_handler, worker) - handlers['SIGINT']('SIGINT', object()) - self.assertTrue(state.should_stop) - finally: - process.name = name - state.should_stop = False - - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 1 - try: - worker = self._Worker() - handlers = self.psig(cd.install_worker_int_handler, worker) - with self.assertRaises(WorkerShutdown): - handlers['SIGINT']('SIGINT', object()) - finally: - process.name = name - state.should_stop = False - - @disable_stdouts - def test_install_HUP_not_supported_handler(self): - worker = self._Worker() - handlers = self.psig(cd.install_HUP_not_supported_handler, worker) - handlers['SIGHUP']('SIGHUP', object()) - - @disable_stdouts - def test_worker_term_hard_handler_only_stop_MainProcess(self): - try: - import _multiprocessing # noqa - except ImportError: - raise SkipTest('only relevant for multiprocessing') - process = current_process() - name, process.name = process.name, 'OtherProcess' - try: - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 3 - worker = self._Worker() - handlers = self.psig( - cd.install_worker_term_hard_handler, worker) - try: - handlers['SIGQUIT']('SIGQUIT', object()) - self.assertTrue(state.should_terminate) - finally: - state.should_terminate = False - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 1 - worker = self._Worker() - handlers = self.psig( - cd.install_worker_term_hard_handler, worker) - with self.assertRaises(WorkerTerminate): - handlers['SIGQUIT']('SIGQUIT', object()) - finally: - process.name = name - - @disable_stdouts - def test_worker_term_handler_when_threads(self): - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 3 - worker = self._Worker() - handlers = self.psig(cd.install_worker_term_handler, worker) - try: - handlers['SIGTERM']('SIGTERM', object()) - self.assertTrue(state.should_stop) - finally: - state.should_stop = False - - @disable_stdouts - def test_worker_term_handler_when_single_thread(self): - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 1 - worker = self._Worker() - handlers = self.psig(cd.install_worker_term_handler, worker) - try: - with self.assertRaises(WorkerShutdown): - handlers['SIGTERM']('SIGTERM', object()) - finally: - state.should_stop = False - - @patch('sys.__stderr__') - @skip_if_pypy - @skip_if_jython - def test_worker_cry_handler(self, stderr): - handlers = self.psig(cd.install_cry_handler) - self.assertIsNone(handlers['SIGUSR1']('SIGUSR1', object())) - self.assertTrue(stderr.write.called) - - @disable_stdouts - def test_worker_term_handler_only_stop_MainProcess(self): - try: - import _multiprocessing # noqa - except ImportError: - raise SkipTest('only relevant for multiprocessing') - process = current_process() - name, process.name = process.name, 'OtherProcess' - try: - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 3 - worker = self._Worker() - handlers = self.psig(cd.install_worker_term_handler, worker) - handlers['SIGTERM']('SIGTERM', object()) - self.assertTrue(state.should_stop) - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 1 - worker = self._Worker() - handlers = self.psig(cd.install_worker_term_handler, worker) - with self.assertRaises(WorkerShutdown): - handlers['SIGTERM']('SIGTERM', object()) - finally: - process.name = name - state.should_stop = False - - @disable_stdouts - @patch('celery.platforms.close_open_fds') - @patch('atexit.register') - @patch('os.close') - def test_worker_restart_handler(self, _close, register, close_open): - if getattr(os, 'execv', None) is None: - raise SkipTest('platform does not have excv') - argv = [] - - def _execv(*args): - argv.extend(args) - - execv, os.execv = os.execv, _execv - try: - worker = self._Worker() - handlers = self.psig(cd.install_worker_restart_handler, worker) - handlers['SIGHUP']('SIGHUP', object()) - self.assertTrue(state.should_stop) - self.assertTrue(register.called) - callback = register.call_args[0][0] - callback() - self.assertTrue(argv) - finally: - os.execv = execv - state.should_stop = False - - @disable_stdouts - def test_worker_term_hard_handler_when_threaded(self): - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 3 - worker = self._Worker() - handlers = self.psig(cd.install_worker_term_hard_handler, worker) - try: - handlers['SIGQUIT']('SIGQUIT', object()) - self.assertTrue(state.should_terminate) - finally: - state.should_terminate = False - - @disable_stdouts - def test_worker_term_hard_handler_when_single_threaded(self): - with patch('celery.apps.worker.active_thread_count') as c: - c.return_value = 1 - worker = self._Worker() - handlers = self.psig(cd.install_worker_term_hard_handler, worker) - with self.assertRaises(WorkerTerminate): - handlers['SIGQUIT']('SIGQUIT', object()) diff --git a/awx/lib/site-packages/celery/tests/case.py b/awx/lib/site-packages/celery/tests/case.py deleted file mode 100644 index c96fd8ec0c..0000000000 --- a/awx/lib/site-packages/celery/tests/case.py +++ /dev/null @@ -1,860 +0,0 @@ -from __future__ import absolute_import - -try: - import unittest # noqa - unittest.skip - from unittest.util import safe_repr, unorderable_list_difference -except AttributeError: - import unittest2 as unittest # noqa - from unittest2.util import safe_repr, unorderable_list_difference # noqa - -import importlib -import inspect -import logging -import numbers -import os -import platform -import re -import sys -import threading -import time -import types -import warnings - -from contextlib import contextmanager -from copy import deepcopy -from datetime import datetime, timedelta -from functools import partial, wraps -from types import ModuleType - -try: - from unittest import mock -except ImportError: - import mock # noqa -from nose import SkipTest -from kombu import Queue -from kombu.log import NullHandler -from kombu.utils import nested, symbol_by_name - -from celery import Celery -from celery.app import current_app -from celery.backends.cache import CacheBackend, DummyClient -from celery.exceptions import CDeprecationWarning, CPendingDeprecationWarning -from celery.five import ( - WhateverIO, builtins, items, reraise, - string_t, values, open_fqdn, -) -from celery.utils.functional import noop -from celery.utils.imports import qualname - -__all__ = [ - 'Case', 'AppCase', 'Mock', 'MagicMock', 'ANY', - 'patch', 'call', 'sentinel', 'skip_unless_module', - 'wrap_logger', 'with_environ', 'sleepdeprived', - 'skip_if_environ', 'todo', 'skip', 'skip_if', - 'skip_unless', 'mask_modules', 'override_stdouts', 'mock_module', - 'replace_module_value', 'sys_platform', 'reset_modules', - 'patch_modules', 'mock_context', 'mock_open', 'patch_many', - 'assert_signal_called', 'skip_if_pypy', - 'skip_if_jython', 'body_from_sig', 'restore_logging', -] -patch = mock.patch -call = mock.call -sentinel = mock.sentinel -MagicMock = mock.MagicMock -ANY = mock.ANY - -PY3 = sys.version_info[0] == 3 - -CASE_REDEFINES_SETUP = """\ -{name} (subclass of AppCase) redefines private "setUp", should be: "setup"\ -""" -CASE_REDEFINES_TEARDOWN = """\ -{name} (subclass of AppCase) redefines private "tearDown", \ -should be: "teardown"\ -""" -CASE_LOG_REDIRECT_EFFECT = """\ -Test {0} did not disable LoggingProxy for {1}\ -""" -CASE_LOG_LEVEL_EFFECT = """\ -Test {0} Modified the level of the root logger\ -""" -CASE_LOG_HANDLER_EFFECT = """\ -Test {0} Modified handlers for the root logger\ -""" - -CELERY_TEST_CONFIG = { - #: Don't want log output when running suite. - 'CELERYD_HIJACK_ROOT_LOGGER': False, - 'CELERY_SEND_TASK_ERROR_EMAILS': False, - 'CELERY_DEFAULT_QUEUE': 'testcelery', - 'CELERY_DEFAULT_EXCHANGE': 'testcelery', - 'CELERY_DEFAULT_ROUTING_KEY': 'testcelery', - 'CELERY_QUEUES': ( - Queue('testcelery', routing_key='testcelery'), - ), - 'CELERY_ENABLE_UTC': True, - 'CELERY_TIMEZONE': 'UTC', - 'CELERYD_LOG_COLOR': False, - - # Mongo results tests (only executed if installed and running) - 'CELERY_MONGODB_BACKEND_SETTINGS': { - 'host': os.environ.get('MONGO_HOST') or 'localhost', - 'port': os.environ.get('MONGO_PORT') or 27017, - 'database': os.environ.get('MONGO_DB') or 'celery_unittests', - 'taskmeta_collection': (os.environ.get('MONGO_TASKMETA_COLLECTION') - or 'taskmeta_collection'), - 'user': os.environ.get('MONGO_USER'), - 'password': os.environ.get('MONGO_PASSWORD'), - } -} - - -class Trap(object): - - def __getattr__(self, name): - raise RuntimeError('Test depends on current_app') - - -class UnitLogging(symbol_by_name(Celery.log_cls)): - - def __init__(self, *args, **kwargs): - super(UnitLogging, self).__init__(*args, **kwargs) - self.already_setup = True - - -def UnitApp(name=None, broker=None, backend=None, - set_as_current=False, log=UnitLogging, **kwargs): - - app = Celery(name or 'celery.tests', - broker=broker or 'memory://', - backend=backend or 'cache+memory://', - set_as_current=set_as_current, - log=log, - **kwargs) - app.add_defaults(deepcopy(CELERY_TEST_CONFIG)) - return app - - -class Mock(mock.Mock): - - def __init__(self, *args, **kwargs): - attrs = kwargs.pop('attrs', None) or {} - super(Mock, self).__init__(*args, **kwargs) - for attr_name, attr_value in items(attrs): - setattr(self, attr_name, attr_value) - - -class _ContextMock(Mock): - """Dummy class implementing __enter__ and __exit__ - as the with statement requires these to be implemented - in the class, not just the instance.""" - - def __enter__(self): - pass - - def __exit__(self, *exc_info): - pass - - -def ContextMock(*args, **kwargs): - obj = _ContextMock(*args, **kwargs) - obj.attach_mock(_ContextMock(), '__enter__') - obj.attach_mock(_ContextMock(), '__exit__') - obj.__enter__.return_value = obj - # if __exit__ return a value the exception is ignored, - # so it must return None here. - obj.__exit__.return_value = None - return obj - - -def _bind(f, o): - @wraps(f) - def bound_meth(*fargs, **fkwargs): - return f(o, *fargs, **fkwargs) - return bound_meth - - -if PY3: # pragma: no cover - def _get_class_fun(meth): - return meth -else: - def _get_class_fun(meth): - return meth.__func__ - - -class MockCallbacks(object): - - def __new__(cls, *args, **kwargs): - r = Mock(name=cls.__name__) - _get_class_fun(cls.__init__)(r, *args, **kwargs) - for key, value in items(vars(cls)): - if key not in ('__dict__', '__weakref__', '__new__', '__init__'): - if inspect.ismethod(value) or inspect.isfunction(value): - r.__getattr__(key).side_effect = _bind(value, r) - else: - r.__setattr__(key, value) - return r - - -def skip_unless_module(module): - - def _inner(fun): - - @wraps(fun) - def __inner(*args, **kwargs): - try: - importlib.import_module(module) - except ImportError: - raise SkipTest('Does not have %s' % (module, )) - - return fun(*args, **kwargs) - - return __inner - return _inner - - -# -- adds assertWarns from recent unittest2, not in Python 2.7. - -class _AssertRaisesBaseContext(object): - - def __init__(self, expected, test_case, callable_obj=None, - expected_regex=None): - self.expected = expected - self.failureException = test_case.failureException - self.obj_name = None - if isinstance(expected_regex, string_t): - expected_regex = re.compile(expected_regex) - self.expected_regex = expected_regex - - -def _is_magic_module(m): - # some libraries create custom module types that are lazily - # lodaded, e.g. Django installs some modules in sys.modules that - # will load _tkinter and other shit when touched. - - # pyflakes refuses to accept 'noqa' for this isinstance. - cls, modtype = m.__class__, types.ModuleType - return (not cls is modtype and ( - '__getattr__' in vars(m.__class__) or - '__getattribute__' in vars(m.__class__))) - - -class _AssertWarnsContext(_AssertRaisesBaseContext): - """A context manager used to implement TestCase.assertWarns* methods.""" - - def __enter__(self): - # The __warningregistry__'s need to be in a pristine state for tests - # to work properly. - warnings.resetwarnings() - for v in list(values(sys.modules)): - # do not evaluate Django moved modules and other lazily - # initialized modules. - if v and not _is_magic_module(v): - # use raw __getattribute__ to protect even better from - # lazily loaded modules - try: - object.__getattribute__(v, '__warningregistry__') - except AttributeError: - pass - else: - object.__setattr__(v, '__warningregistry__', {}) - self.warnings_manager = warnings.catch_warnings(record=True) - self.warnings = self.warnings_manager.__enter__() - warnings.simplefilter('always', self.expected) - return self - - def __exit__(self, exc_type, exc_value, tb): - self.warnings_manager.__exit__(exc_type, exc_value, tb) - if exc_type is not None: - # let unexpected exceptions pass through - return - try: - exc_name = self.expected.__name__ - except AttributeError: - exc_name = str(self.expected) - first_matching = None - for m in self.warnings: - w = m.message - if not isinstance(w, self.expected): - continue - if first_matching is None: - first_matching = w - if (self.expected_regex is not None and - not self.expected_regex.search(str(w))): - continue - # store warning for later retrieval - self.warning = w - self.filename = m.filename - self.lineno = m.lineno - return - # Now we simply try to choose a helpful failure message - if first_matching is not None: - raise self.failureException( - '%r does not match %r' % ( - self.expected_regex.pattern, str(first_matching))) - if self.obj_name: - raise self.failureException( - '%s not triggered by %s' % (exc_name, self.obj_name)) - else: - raise self.failureException('%s not triggered' % exc_name) - - -class Case(unittest.TestCase): - - def assertWarns(self, expected_warning): - return _AssertWarnsContext(expected_warning, self, None) - - def assertWarnsRegex(self, expected_warning, expected_regex): - return _AssertWarnsContext(expected_warning, self, - None, expected_regex) - - @contextmanager - def assertDeprecated(self): - with self.assertWarnsRegex(CDeprecationWarning, - r'scheduled for removal'): - yield - - @contextmanager - def assertPendingDeprecation(self): - with self.assertWarnsRegex(CPendingDeprecationWarning, - r'scheduled for deprecation'): - yield - - def assertDictContainsSubset(self, expected, actual, msg=None): - missing, mismatched = [], [] - - for key, value in items(expected): - if key not in actual: - missing.append(key) - elif value != actual[key]: - mismatched.append('%s, expected: %s, actual: %s' % ( - safe_repr(key), safe_repr(value), - safe_repr(actual[key]))) - - if not (missing or mismatched): - return - - standard_msg = '' - if missing: - standard_msg = 'Missing: %s' % ','.join(map(safe_repr, missing)) - - if mismatched: - if standard_msg: - standard_msg += '; ' - standard_msg += 'Mismatched values: %s' % ( - ','.join(mismatched)) - - self.fail(self._formatMessage(msg, standard_msg)) - - def assertItemsEqual(self, expected_seq, actual_seq, msg=None): - missing = unexpected = None - try: - expected = sorted(expected_seq) - actual = sorted(actual_seq) - except TypeError: - # Unsortable items (example: set(), complex(), ...) - expected = list(expected_seq) - actual = list(actual_seq) - missing, unexpected = unorderable_list_difference( - expected, actual) - else: - return self.assertSequenceEqual(expected, actual, msg=msg) - - errors = [] - if missing: - errors.append( - 'Expected, but missing:\n %s' % (safe_repr(missing), ) - ) - if unexpected: - errors.append( - 'Unexpected, but present:\n %s' % (safe_repr(unexpected), ) - ) - if errors: - standardMsg = '\n'.join(errors) - self.fail(self._formatMessage(msg, standardMsg)) - - -def depends_on_current_app(fun): - if inspect.isclass(fun): - fun.contained = False - else: - @wraps(fun) - def __inner(self, *args, **kwargs): - self.app.set_current() - return fun(self, *args, **kwargs) - return __inner - - -class AppCase(Case): - contained = True - - def __init__(self, *args, **kwargs): - super(AppCase, self).__init__(*args, **kwargs) - if self.__class__.__dict__.get('setUp'): - raise RuntimeError( - CASE_REDEFINES_SETUP.format(name=qualname(self)), - ) - if self.__class__.__dict__.get('tearDown'): - raise RuntimeError( - CASE_REDEFINES_TEARDOWN.format(name=qualname(self)), - ) - - def Celery(self, *args, **kwargs): - return UnitApp(*args, **kwargs) - - def setUp(self): - self._threads_at_setup = list(threading.enumerate()) - from celery import _state - from celery import result - result.task_join_will_block = \ - _state.task_join_will_block = lambda: False - self._current_app = current_app() - self._default_app = _state.default_app - trap = Trap() - _state.set_default_app(trap) - _state._tls.current_app = trap - - self.app = self.Celery(set_as_current=False) - if not self.contained: - self.app.set_current() - root = logging.getLogger() - self.__rootlevel = root.level - self.__roothandlers = root.handlers - _state._set_task_join_will_block(False) - try: - self.setup() - except: - self._teardown_app() - raise - - def _teardown_app(self): - from celery.utils.log import LoggingProxy - assert sys.stdout - assert sys.stderr - assert sys.__stdout__ - assert sys.__stderr__ - this = self._get_test_name() - if isinstance(sys.stdout, LoggingProxy) or \ - isinstance(sys.__stdout__, LoggingProxy): - raise RuntimeError(CASE_LOG_REDIRECT_EFFECT.format(this, 'stdout')) - if isinstance(sys.stderr, LoggingProxy) or \ - isinstance(sys.__stderr__, LoggingProxy): - raise RuntimeError(CASE_LOG_REDIRECT_EFFECT.format(this, 'stderr')) - backend = self.app.__dict__.get('backend') - if backend is not None: - if isinstance(backend, CacheBackend): - if isinstance(backend.client, DummyClient): - backend.client.cache.clear() - backend._cache.clear() - from celery._state import ( - _tls, set_default_app, _set_task_join_will_block, - ) - _set_task_join_will_block(False) - - set_default_app(self._default_app) - _tls.current_app = self._current_app - if self.app is not self._current_app: - self.app.close() - self.app = None - self.assertEqual( - self._threads_at_setup, list(threading.enumerate()), - ) - - def _get_test_name(self): - return '.'.join([self.__class__.__name__, self._testMethodName]) - - def tearDown(self): - try: - self.teardown() - finally: - self._teardown_app() - self.assert_no_logging_side_effect() - - def assert_no_logging_side_effect(self): - this = self._get_test_name() - root = logging.getLogger() - if root.level != self.__rootlevel: - raise RuntimeError(CASE_LOG_LEVEL_EFFECT.format(this)) - if root.handlers != self.__roothandlers: - raise RuntimeError(CASE_LOG_HANDLER_EFFECT.format(this)) - - def setup(self): - pass - - def teardown(self): - pass - - -def get_handlers(logger): - return [h for h in logger.handlers if not isinstance(h, NullHandler)] - - -@contextmanager -def wrap_logger(logger, loglevel=logging.ERROR): - old_handlers = get_handlers(logger) - sio = WhateverIO() - siohandler = logging.StreamHandler(sio) - logger.handlers = [siohandler] - - try: - yield sio - finally: - logger.handlers = old_handlers - - -def with_environ(env_name, env_value): - - def _envpatched(fun): - - @wraps(fun) - def _patch_environ(*args, **kwargs): - prev_val = os.environ.get(env_name) - os.environ[env_name] = env_value - try: - return fun(*args, **kwargs) - finally: - os.environ[env_name] = prev_val or '' - - return _patch_environ - return _envpatched - - -def sleepdeprived(module=time): - - def _sleepdeprived(fun): - - @wraps(fun) - def __sleepdeprived(*args, **kwargs): - old_sleep = module.sleep - module.sleep = noop - try: - return fun(*args, **kwargs) - finally: - module.sleep = old_sleep - - return __sleepdeprived - - return _sleepdeprived - - -def skip_if_environ(env_var_name): - - def _wrap_test(fun): - - @wraps(fun) - def _skips_if_environ(*args, **kwargs): - if os.environ.get(env_var_name): - raise SkipTest('SKIP %s: %s set\n' % ( - fun.__name__, env_var_name)) - return fun(*args, **kwargs) - - return _skips_if_environ - - return _wrap_test - - -def _skip_test(reason, sign): - - def _wrap_test(fun): - - @wraps(fun) - def _skipped_test(*args, **kwargs): - raise SkipTest('%s: %s' % (sign, reason)) - - return _skipped_test - return _wrap_test - - -def todo(reason): - """TODO test decorator.""" - return _skip_test(reason, 'TODO') - - -def skip(reason): - """Skip test decorator.""" - return _skip_test(reason, 'SKIP') - - -def skip_if(predicate, reason): - """Skip test if predicate is :const:`True`.""" - - def _inner(fun): - return predicate and skip(reason)(fun) or fun - - return _inner - - -def skip_unless(predicate, reason): - """Skip test if predicate is :const:`False`.""" - return skip_if(not predicate, reason) - - -# Taken from -# http://bitbucket.org/runeh/snippets/src/tip/missing_modules.py -@contextmanager -def mask_modules(*modnames): - """Ban some modules from being importable inside the context - - For example: - - >>> with mask_modules('sys'): - ... try: - ... import sys - ... except ImportError: - ... print('sys not found') - sys not found - - >>> import sys # noqa - >>> sys.version - (2, 5, 2, 'final', 0) - - """ - - realimport = builtins.__import__ - - def myimp(name, *args, **kwargs): - if name in modnames: - raise ImportError('No module named %s' % name) - else: - return realimport(name, *args, **kwargs) - - builtins.__import__ = myimp - try: - yield True - finally: - builtins.__import__ = realimport - - -@contextmanager -def override_stdouts(): - """Override `sys.stdout` and `sys.stderr` with `WhateverIO`.""" - prev_out, prev_err = sys.stdout, sys.stderr - mystdout, mystderr = WhateverIO(), WhateverIO() - sys.stdout = sys.__stdout__ = mystdout - sys.stderr = sys.__stderr__ = mystderr - - try: - yield mystdout, mystderr - finally: - sys.stdout = sys.__stdout__ = prev_out - sys.stderr = sys.__stderr__ = prev_err - - -def _old_patch(module, name, mocked): - module = importlib.import_module(module) - - def _patch(fun): - - @wraps(fun) - def __patched(*args, **kwargs): - prev = getattr(module, name) - setattr(module, name, mocked) - try: - return fun(*args, **kwargs) - finally: - setattr(module, name, prev) - return __patched - return _patch - - -@contextmanager -def replace_module_value(module, name, value=None): - has_prev = hasattr(module, name) - prev = getattr(module, name, None) - if value: - setattr(module, name, value) - else: - try: - delattr(module, name) - except AttributeError: - pass - try: - yield - finally: - if prev is not None: - setattr(sys, name, prev) - if not has_prev: - try: - delattr(module, name) - except AttributeError: - pass -pypy_version = partial( - replace_module_value, sys, 'pypy_version_info', -) -platform_pyimp = partial( - replace_module_value, platform, 'python_implementation', -) - - -@contextmanager -def sys_platform(value): - prev, sys.platform = sys.platform, value - try: - yield - finally: - sys.platform = prev - - -@contextmanager -def reset_modules(*modules): - prev = dict((k, sys.modules.pop(k)) for k in modules if k in sys.modules) - try: - yield - finally: - sys.modules.update(prev) - - -@contextmanager -def patch_modules(*modules): - prev = {} - for mod in modules: - prev[mod] = sys.modules.get(mod) - sys.modules[mod] = ModuleType(mod) - try: - yield - finally: - for name, mod in items(prev): - if mod is None: - sys.modules.pop(name, None) - else: - sys.modules[name] = mod - - -@contextmanager -def mock_module(*names): - prev = {} - - class MockModule(ModuleType): - - def __getattr__(self, attr): - setattr(self, attr, Mock()) - return ModuleType.__getattribute__(self, attr) - - mods = [] - for name in names: - try: - prev[name] = sys.modules[name] - except KeyError: - pass - mod = sys.modules[name] = MockModule(name) - mods.append(mod) - try: - yield mods - finally: - for name in names: - try: - sys.modules[name] = prev[name] - except KeyError: - try: - del(sys.modules[name]) - except KeyError: - pass - - -@contextmanager -def mock_context(mock, typ=Mock): - context = mock.return_value = Mock() - context.__enter__ = typ() - context.__exit__ = typ() - - def on_exit(*x): - if x[0]: - reraise(x[0], x[1], x[2]) - context.__exit__.side_effect = on_exit - context.__enter__.return_value = context - try: - yield context - finally: - context.reset() - - -@contextmanager -def mock_open(typ=WhateverIO, side_effect=None): - with patch(open_fqdn) as open_: - with mock_context(open_) as context: - if side_effect is not None: - context.__enter__.side_effect = side_effect - val = context.__enter__.return_value = typ() - val.__exit__ = Mock() - yield val - - -def patch_many(*targets): - return nested(*[patch(target) for target in targets]) - - -@contextmanager -def assert_signal_called(signal, **expected): - handler = Mock() - call_handler = partial(handler) - signal.connect(call_handler) - try: - yield handler - finally: - signal.disconnect(call_handler) - handler.assert_called_with(signal=signal, **expected) - - -def skip_if_pypy(fun): - - @wraps(fun) - def _inner(*args, **kwargs): - if getattr(sys, 'pypy_version_info', None): - raise SkipTest('does not work on PyPy') - return fun(*args, **kwargs) - return _inner - - -def skip_if_jython(fun): - - @wraps(fun) - def _inner(*args, **kwargs): - if sys.platform.startswith('java'): - raise SkipTest('does not work on Jython') - return fun(*args, **kwargs) - return _inner - - -def body_from_sig(app, sig, utc=True): - sig.freeze() - callbacks = sig.options.pop('link', None) - errbacks = sig.options.pop('link_error', None) - countdown = sig.options.pop('countdown', None) - if countdown: - eta = app.now() + timedelta(seconds=countdown) - else: - eta = sig.options.pop('eta', None) - if eta and isinstance(eta, datetime): - eta = eta.isoformat() - expires = sig.options.pop('expires', None) - if expires and isinstance(expires, numbers.Real): - expires = app.now() + timedelta(seconds=expires) - if expires and isinstance(expires, datetime): - expires = expires.isoformat() - return { - 'task': sig.task, - 'id': sig.id, - 'args': sig.args, - 'kwargs': sig.kwargs, - 'callbacks': [dict(s) for s in callbacks] if callbacks else None, - 'errbacks': [dict(s) for s in errbacks] if errbacks else None, - 'eta': eta, - 'utc': utc, - 'expires': expires, - } - - -@contextmanager -def restore_logging(): - outs = sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__ - root = logging.getLogger() - level = root.level - handlers = root.handlers - - try: - yield - finally: - sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__ = outs - root.level = level - root.handlers[:] = handlers diff --git a/awx/lib/site-packages/celery/tests/compat_modules/__init__.py b/awx/lib/site-packages/celery/tests/compat_modules/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/compat_modules/test_compat.py b/awx/lib/site-packages/celery/tests/compat_modules/test_compat.py deleted file mode 100644 index d285188e09..0000000000 --- a/awx/lib/site-packages/celery/tests/compat_modules/test_compat.py +++ /dev/null @@ -1,82 +0,0 @@ -from __future__ import absolute_import - -from datetime import timedelta - -import sys -sys.modules.pop('celery.task', None) - -from celery.schedules import schedule -from celery.task import ( - periodic_task, - PeriodicTask -) -from celery.utils.timeutils import timedelta_seconds - -from celery.tests.case import AppCase, depends_on_current_app - - -class test_Task(AppCase): - - def test_base_task_inherits_magic_kwargs_from_app(self): - from celery.task import Task as OldTask - - class timkX(OldTask): - abstract = True - - with self.Celery(set_as_current=False, - accept_magic_kwargs=True) as app: - timkX.bind(app) - # see #918 - self.assertFalse(timkX.accept_magic_kwargs) - - from celery import Task as NewTask - - class timkY(NewTask): - abstract = True - - timkY.bind(app) - self.assertFalse(timkY.accept_magic_kwargs) - - -@depends_on_current_app -class test_periodic_tasks(AppCase): - - def setup(self): - @periodic_task(app=self.app, shared=False, - run_every=schedule(timedelta(hours=1), app=self.app)) - def my_periodic(): - pass - self.my_periodic = my_periodic - - def now(self): - return self.app.now() - - def test_must_have_run_every(self): - with self.assertRaises(NotImplementedError): - type('Foo', (PeriodicTask, ), {'__module__': __name__}) - - def test_remaining_estimate(self): - s = self.my_periodic.run_every - self.assertIsInstance( - s.remaining_estimate(s.maybe_make_aware(self.now())), - timedelta) - - def test_is_due_not_due(self): - due, remaining = self.my_periodic.run_every.is_due(self.now()) - self.assertFalse(due) - # This assertion may fail if executed in the - # first minute of an hour, thus 59 instead of 60 - self.assertGreater(remaining, 59) - - def test_is_due(self): - p = self.my_periodic - due, remaining = p.run_every.is_due( - self.now() - p.run_every.run_every, - ) - self.assertTrue(due) - self.assertEqual(remaining, - timedelta_seconds(p.run_every.run_every)) - - def test_schedule_repr(self): - p = self.my_periodic - self.assertTrue(repr(p.run_every)) diff --git a/awx/lib/site-packages/celery/tests/compat_modules/test_compat_utils.py b/awx/lib/site-packages/celery/tests/compat_modules/test_compat_utils.py deleted file mode 100644 index b041a0b3e8..0000000000 --- a/awx/lib/site-packages/celery/tests/compat_modules/test_compat_utils.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import absolute_import - -import celery - -from celery.app.task import Task as ModernTask -from celery.task.base import Task as CompatTask - -from celery.tests.case import AppCase, depends_on_current_app - - -@depends_on_current_app -class test_MagicModule(AppCase): - - def test_class_property_set_without_type(self): - self.assertTrue(ModernTask.__dict__['app'].__get__(CompatTask())) - - def test_class_property_set_on_class(self): - self.assertIs(ModernTask.__dict__['app'].__set__(None, None), - ModernTask.__dict__['app']) - - def test_class_property_set(self): - - class X(CompatTask): - pass - ModernTask.__dict__['app'].__set__(X(), self.app) - self.assertIs(X.app, self.app) - - def test_dir(self): - self.assertTrue(dir(celery.messaging)) - - def test_direct(self): - self.assertTrue(celery.task) - - def test_app_attrs(self): - self.assertEqual(celery.task.control.broadcast, - celery.current_app.control.broadcast) - - def test_decorators_task(self): - @celery.decorators.task - def _test_decorators_task(): - pass - - self.assertTrue(_test_decorators_task.accept_magic_kwargs) - - def test_decorators_periodic_task(self): - @celery.decorators.periodic_task(run_every=3600) - def _test_decorators_ptask(): - pass - - self.assertTrue(_test_decorators_ptask.accept_magic_kwargs) diff --git a/awx/lib/site-packages/celery/tests/compat_modules/test_decorators.py b/awx/lib/site-packages/celery/tests/compat_modules/test_decorators.py deleted file mode 100644 index 9f5dff9473..0000000000 --- a/awx/lib/site-packages/celery/tests/compat_modules/test_decorators.py +++ /dev/null @@ -1,39 +0,0 @@ -from __future__ import absolute_import - -import warnings - -from celery.task import base - -from celery.tests.case import AppCase, depends_on_current_app - - -def add(x, y): - return x + y - - -@depends_on_current_app -class test_decorators(AppCase): - - def test_task_alias(self): - from celery import task - self.assertTrue(task.__file__) - self.assertTrue(task(add)) - - def setup(self): - with warnings.catch_warnings(record=True): - from celery import decorators - self.decorators = decorators - - def assertCompatDecorator(self, decorator, type, **opts): - task = decorator(**opts)(add) - self.assertEqual(task(8, 8), 16) - self.assertTrue(task.accept_magic_kwargs) - self.assertIsInstance(task, type) - - def test_task(self): - self.assertCompatDecorator(self.decorators.task, base.BaseTask) - - def test_periodic_task(self): - self.assertCompatDecorator(self.decorators.periodic_task, - base.BaseTask, - run_every=1) diff --git a/awx/lib/site-packages/celery/tests/compat_modules/test_http.py b/awx/lib/site-packages/celery/tests/compat_modules/test_http.py deleted file mode 100644 index 08505f87e5..0000000000 --- a/awx/lib/site-packages/celery/tests/compat_modules/test_http.py +++ /dev/null @@ -1,158 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -from contextlib import contextmanager -from functools import wraps -try: - from urllib import addinfourl -except ImportError: # py3k - from urllib.request import addinfourl # noqa - -from anyjson import dumps -from kombu.utils.encoding import from_utf8 - -from celery.five import WhateverIO, items -from celery.task import http -from celery.tests.case import AppCase, Case - - -@contextmanager -def mock_urlopen(response_method): - - urlopen = http.urlopen - - @wraps(urlopen) - def _mocked(url, *args, **kwargs): - response_data, headers = response_method(url) - return addinfourl(WhateverIO(response_data), headers, url) - - http.urlopen = _mocked - - try: - yield True - finally: - http.urlopen = urlopen - - -def _response(res): - return lambda r: (res, []) - - -def success_response(value): - return _response(dumps({'status': 'success', 'retval': value})) - - -def fail_response(reason): - return _response(dumps({'status': 'failure', 'reason': reason})) - - -def unknown_response(): - return _response(dumps({'status': 'u.u.u.u', 'retval': True})) - - -class test_encodings(Case): - - def test_utf8dict(self): - uk = 'foobar' - d = {'følelser ær langé': 'ærbadægzaå寨Å', - from_utf8(uk): from_utf8('xuzzybaz')} - - for key, value in items(http.utf8dict(items(d))): - self.assertIsInstance(key, str) - self.assertIsInstance(value, str) - - -class test_MutableURL(Case): - - def test_url_query(self): - url = http.MutableURL('http://example.com?x=10&y=20&z=Foo') - self.assertDictContainsSubset({'x': '10', - 'y': '20', - 'z': 'Foo'}, url.query) - url.query['name'] = 'George' - url = http.MutableURL(str(url)) - self.assertDictContainsSubset({'x': '10', - 'y': '20', - 'z': 'Foo', - 'name': 'George'}, url.query) - - def test_url_keeps_everything(self): - url = 'https://e.com:808/foo/bar#zeta?x=10&y=20' - url = http.MutableURL(url) - - self.assertEqual( - str(url).split('?')[0], - 'https://e.com:808/foo/bar#zeta', - ) - - def test___repr__(self): - url = http.MutableURL('http://e.com/foo/bar') - self.assertTrue(repr(url).startswith('<MutableURL: http://e.com')) - - def test_set_query(self): - url = http.MutableURL('http://e.com/foo/bar/?x=10') - url.query = {'zzz': 'xxx'} - url = http.MutableURL(str(url)) - self.assertEqual(url.query, {'zzz': 'xxx'}) - - -class test_HttpDispatch(AppCase): - - def test_dispatch_success(self): - with mock_urlopen(success_response(100)): - d = http.HttpDispatch('http://example.com/mul', 'GET', { - 'x': 10, 'y': 10}) - self.assertEqual(d.dispatch(), 100) - - def test_dispatch_failure(self): - with mock_urlopen(fail_response('Invalid moon alignment')): - d = http.HttpDispatch('http://example.com/mul', 'GET', { - 'x': 10, 'y': 10}) - with self.assertRaises(http.RemoteExecuteError): - d.dispatch() - - def test_dispatch_empty_response(self): - with mock_urlopen(_response('')): - d = http.HttpDispatch('http://example.com/mul', 'GET', { - 'x': 10, 'y': 10}) - with self.assertRaises(http.InvalidResponseError): - d.dispatch() - - def test_dispatch_non_json(self): - with mock_urlopen(_response("{'#{:'''")): - d = http.HttpDispatch('http://example.com/mul', 'GET', { - 'x': 10, 'y': 10}) - with self.assertRaises(http.InvalidResponseError): - d.dispatch() - - def test_dispatch_unknown_status(self): - with mock_urlopen(unknown_response()): - d = http.HttpDispatch('http://example.com/mul', 'GET', { - 'x': 10, 'y': 10}) - with self.assertRaises(http.UnknownStatusError): - d.dispatch() - - def test_dispatch_POST(self): - with mock_urlopen(success_response(100)): - d = http.HttpDispatch('http://example.com/mul', 'POST', { - 'x': 10, 'y': 10}) - self.assertEqual(d.dispatch(), 100) - - -class test_URL(AppCase): - - def test_URL_get_async(self): - self.app.conf.CELERY_ALWAYS_EAGER = True - with mock_urlopen(success_response(100)): - d = http.URL( - 'http://example.com/mul', app=self.app, - ).get_async(x=10, y=10) - self.assertEqual(d.get(), 100) - - def test_URL_post_async(self): - self.app.conf.CELERY_ALWAYS_EAGER = True - with mock_urlopen(success_response(100)): - d = http.URL( - 'http://example.com/mul', app=self.app, - ).post_async(x=10, y=10) - self.assertEqual(d.get(), 100) diff --git a/awx/lib/site-packages/celery/tests/compat_modules/test_messaging.py b/awx/lib/site-packages/celery/tests/compat_modules/test_messaging.py deleted file mode 100644 index 780c2f7b71..0000000000 --- a/awx/lib/site-packages/celery/tests/compat_modules/test_messaging.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import absolute_import - -from celery import messaging -from celery.tests.case import AppCase, depends_on_current_app - - -@depends_on_current_app -class test_compat_messaging_module(AppCase): - - def test_get_consume_set(self): - conn = messaging.establish_connection() - messaging.get_consumer_set(conn).close() - conn.close() diff --git a/awx/lib/site-packages/celery/tests/compat_modules/test_sets.py b/awx/lib/site-packages/celery/tests/compat_modules/test_sets.py deleted file mode 100644 index c1d2c16fad..0000000000 --- a/awx/lib/site-packages/celery/tests/compat_modules/test_sets.py +++ /dev/null @@ -1,244 +0,0 @@ -from __future__ import absolute_import - -import anyjson -import warnings - -from celery import uuid -from celery.result import TaskSetResult -from celery.task import Task -from celery.canvas import Signature - -from celery.tests.tasks.test_result import make_mock_group -from celery.tests.case import AppCase, Mock, patch - - -class SetsCase(AppCase): - - def setup(self): - with warnings.catch_warnings(record=True): - from celery.task import sets - self.sets = sets - self.subtask = sets.subtask - self.TaskSet = sets.TaskSet - - class MockTask(Task): - app = self.app - name = 'tasks.add' - - def run(self, x, y, **kwargs): - return x + y - - @classmethod - def apply_async(cls, args, kwargs, **options): - return (args, kwargs, options) - - @classmethod - def apply(cls, args, kwargs, **options): - return (args, kwargs, options) - self.MockTask = MockTask - - -class test_TaskSetResult(AppCase): - - def setup(self): - self.size = 10 - self.ts = TaskSetResult(uuid(), make_mock_group(self.app, self.size)) - - def test_total(self): - self.assertEqual(self.ts.total, self.size) - - def test_compat_properties(self): - self.assertEqual(self.ts.taskset_id, self.ts.id) - self.ts.taskset_id = 'foo' - self.assertEqual(self.ts.taskset_id, 'foo') - - def test_compat_subtasks_kwarg(self): - x = TaskSetResult(uuid(), subtasks=[1, 2, 3]) - self.assertEqual(x.results, [1, 2, 3]) - - def test_itersubtasks(self): - it = self.ts.itersubtasks() - - for i, t in enumerate(it): - self.assertEqual(t.get(), i) - - -class test_App(AppCase): - - def test_TaskSet(self): - with warnings.catch_warnings(record=True): - ts = self.app.TaskSet() - self.assertListEqual(ts.tasks, []) - self.assertIs(ts.app, self.app) - - -class test_subtask(SetsCase): - - def test_behaves_like_type(self): - s = self.subtask('tasks.add', (2, 2), {'cache': True}, - {'routing_key': 'CPU-bound'}) - self.assertDictEqual(self.subtask(s), s) - - def test_task_argument_can_be_task_cls(self): - s = self.subtask(self.MockTask, (2, 2)) - self.assertEqual(s.task, self.MockTask.name) - - def test_apply_async(self): - s = self.MockTask.subtask( - (2, 2), {'cache': True}, {'routing_key': 'CPU-bound'}, - ) - args, kwargs, options = s.apply_async() - self.assertTupleEqual(args, (2, 2)) - self.assertDictEqual(kwargs, {'cache': True}) - self.assertDictEqual(options, {'routing_key': 'CPU-bound'}) - - def test_delay_argmerge(self): - s = self.MockTask.subtask( - (2, ), {'cache': True}, {'routing_key': 'CPU-bound'}, - ) - args, kwargs, options = s.delay(10, cache=False, other='foo') - self.assertTupleEqual(args, (10, 2)) - self.assertDictEqual(kwargs, {'cache': False, 'other': 'foo'}) - self.assertDictEqual(options, {'routing_key': 'CPU-bound'}) - - def test_apply_async_argmerge(self): - s = self.MockTask.subtask( - (2, ), {'cache': True}, {'routing_key': 'CPU-bound'}, - ) - args, kwargs, options = s.apply_async((10, ), - {'cache': False, 'other': 'foo'}, - routing_key='IO-bound', - exchange='fast') - - self.assertTupleEqual(args, (10, 2)) - self.assertDictEqual(kwargs, {'cache': False, 'other': 'foo'}) - self.assertDictEqual(options, {'routing_key': 'IO-bound', - 'exchange': 'fast'}) - - def test_apply_argmerge(self): - s = self.MockTask.subtask( - (2, ), {'cache': True}, {'routing_key': 'CPU-bound'}, - ) - args, kwargs, options = s.apply((10, ), - {'cache': False, 'other': 'foo'}, - routing_key='IO-bound', - exchange='fast') - - self.assertTupleEqual(args, (10, 2)) - self.assertDictEqual(kwargs, {'cache': False, 'other': 'foo'}) - self.assertDictEqual( - options, {'routing_key': 'IO-bound', 'exchange': 'fast'}, - ) - - def test_is_JSON_serializable(self): - s = self.MockTask.subtask( - (2, ), {'cache': True}, {'routing_key': 'CPU-bound'}, - ) - s.args = list(s.args) # tuples are not preserved - # but this doesn't matter. - self.assertEqual(s, self.subtask(anyjson.loads(anyjson.dumps(s)))) - - def test_repr(self): - s = self.MockTask.subtask((2, ), {'cache': True}) - self.assertIn('2', repr(s)) - self.assertIn('cache=True', repr(s)) - - def test_reduce(self): - s = self.MockTask.subtask((2, ), {'cache': True}) - cls, args = s.__reduce__() - self.assertDictEqual(dict(cls(*args)), dict(s)) - - -class test_TaskSet(SetsCase): - - def test_task_arg_can_be_iterable__compat(self): - ts = self.TaskSet([self.MockTask.subtask((i, i)) - for i in (2, 4, 8)], app=self.app) - self.assertEqual(len(ts), 3) - - def test_respects_ALWAYS_EAGER(self): - app = self.app - - class MockTaskSet(self.TaskSet): - applied = 0 - - def apply(self, *args, **kwargs): - self.applied += 1 - - ts = MockTaskSet( - [self.MockTask.subtask((i, i)) for i in (2, 4, 8)], - app=self.app, - ) - app.conf.CELERY_ALWAYS_EAGER = True - ts.apply_async() - self.assertEqual(ts.applied, 1) - app.conf.CELERY_ALWAYS_EAGER = False - - with patch('celery.task.sets.get_current_worker_task') as gwt: - parent = gwt.return_value = Mock() - ts.apply_async() - self.assertTrue(parent.add_trail.called) - - def test_apply_async(self): - applied = [0] - - class mocksubtask(Signature): - - def apply_async(self, *args, **kwargs): - applied[0] += 1 - - ts = self.TaskSet([mocksubtask(self.MockTask, (i, i)) - for i in (2, 4, 8)], app=self.app) - ts.apply_async() - self.assertEqual(applied[0], 3) - - class Publisher(object): - - def send(self, *args, **kwargs): - pass - - ts.apply_async(publisher=Publisher()) - - # setting current_task - - @self.app.task(shared=False) - def xyz(): - pass - - from celery._state import _task_stack - xyz.push_request() - _task_stack.push(xyz) - try: - ts.apply_async(publisher=Publisher()) - finally: - _task_stack.pop() - xyz.pop_request() - - def test_apply(self): - - applied = [0] - - class mocksubtask(Signature): - - def apply(self, *args, **kwargs): - applied[0] += 1 - - ts = self.TaskSet([mocksubtask(self.MockTask, (i, i)) - for i in (2, 4, 8)], app=self.app) - ts.apply() - self.assertEqual(applied[0], 3) - - def test_set_app(self): - ts = self.TaskSet([], app=self.app) - ts.app = 42 - self.assertEqual(ts.app, 42) - - def test_set_tasks(self): - ts = self.TaskSet([], app=self.app) - ts.tasks = [1, 2, 3] - self.assertEqual(ts, [1, 2, 3]) - - def test_set_Publisher(self): - ts = self.TaskSet([], app=self.app) - ts.Publisher = 42 - self.assertEqual(ts.Publisher, 42) diff --git a/awx/lib/site-packages/celery/tests/concurrency/__init__.py b/awx/lib/site-packages/celery/tests/concurrency/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/concurrency/test_concurrency.py b/awx/lib/site-packages/celery/tests/concurrency/test_concurrency.py deleted file mode 100644 index 2938877416..0000000000 --- a/awx/lib/site-packages/celery/tests/concurrency/test_concurrency.py +++ /dev/null @@ -1,111 +0,0 @@ -from __future__ import absolute_import - -import os - -from itertools import count - -from celery.concurrency.base import apply_target, BasePool -from celery.tests.case import AppCase, Mock - - -class test_BasePool(AppCase): - - def test_apply_target(self): - - scratch = {} - counter = count(0) - - def gen_callback(name, retval=None): - - def callback(*args): - scratch[name] = (next(counter), args) - return retval - - return callback - - apply_target(gen_callback('target', 42), - args=(8, 16), - callback=gen_callback('callback'), - accept_callback=gen_callback('accept_callback')) - - self.assertDictContainsSubset( - {'target': (1, (8, 16)), 'callback': (2, (42, ))}, - scratch, - ) - pa1 = scratch['accept_callback'] - self.assertEqual(0, pa1[0]) - self.assertEqual(pa1[1][0], os.getpid()) - self.assertTrue(pa1[1][1]) - - # No accept callback - scratch.clear() - apply_target(gen_callback('target', 42), - args=(8, 16), - callback=gen_callback('callback'), - accept_callback=None) - self.assertDictEqual(scratch, - {'target': (3, (8, 16)), - 'callback': (4, (42, ))}) - - def test_does_not_debug(self): - x = BasePool(10) - x._does_debug = False - x.apply_async(object) - - def test_num_processes(self): - self.assertEqual(BasePool(7).num_processes, 7) - - def test_interface_on_start(self): - BasePool(10).on_start() - - def test_interface_on_stop(self): - BasePool(10).on_stop() - - def test_interface_on_apply(self): - BasePool(10).on_apply() - - def test_interface_info(self): - self.assertDictEqual(BasePool(10).info, {}) - - def test_active(self): - p = BasePool(10) - self.assertFalse(p.active) - p._state = p.RUN - self.assertTrue(p.active) - - def test_restart(self): - p = BasePool(10) - with self.assertRaises(NotImplementedError): - p.restart() - - def test_interface_on_terminate(self): - p = BasePool(10) - p.on_terminate() - - def test_interface_terminate_job(self): - with self.assertRaises(NotImplementedError): - BasePool(10).terminate_job(101) - - def test_interface_did_start_ok(self): - self.assertTrue(BasePool(10).did_start_ok()) - - def test_interface_register_with_event_loop(self): - self.assertIsNone( - BasePool(10).register_with_event_loop(Mock()), - ) - - def test_interface_on_soft_timeout(self): - self.assertIsNone(BasePool(10).on_soft_timeout(Mock())) - - def test_interface_on_hard_timeout(self): - self.assertIsNone(BasePool(10).on_hard_timeout(Mock())) - - def test_interface_close(self): - p = BasePool(10) - p.on_close = Mock() - p.close() - self.assertEqual(p._state, p.CLOSE) - p.on_close.assert_called_with() - - def test_interface_no_close(self): - self.assertIsNone(BasePool(10).on_close()) diff --git a/awx/lib/site-packages/celery/tests/concurrency/test_eventlet.py b/awx/lib/site-packages/celery/tests/concurrency/test_eventlet.py deleted file mode 100644 index 162e4f2cff..0000000000 --- a/awx/lib/site-packages/celery/tests/concurrency/test_eventlet.py +++ /dev/null @@ -1,118 +0,0 @@ -from __future__ import absolute_import - -import sys - -from celery.app.defaults import is_pypy -from celery.concurrency.eventlet import ( - apply_target, - Schedule, - Timer, - TaskPool, -) - -from celery.tests.case import ( - AppCase, Mock, SkipTest, mock_module, patch, patch_many, skip_if_pypy, -) - - -class EventletCase(AppCase): - - @skip_if_pypy - def setup(self): - if is_pypy: - raise SkipTest('mock_modules not working on PyPy1.9') - try: - self.eventlet = __import__('eventlet') - except ImportError: - raise SkipTest( - 'eventlet not installed, skipping related tests.') - - @skip_if_pypy - def teardown(self): - for mod in [mod for mod in sys.modules if mod.startswith('eventlet')]: - try: - del(sys.modules[mod]) - except KeyError: - pass - - -class test_aaa_eventlet_patch(EventletCase): - - def test_aaa_is_patched(self): - with patch('eventlet.monkey_patch', create=True) as monkey_patch: - from celery import maybe_patch_concurrency - maybe_patch_concurrency(['x', '-P', 'eventlet']) - monkey_patch.assert_called_with() - - -eventlet_modules = ( - 'eventlet', - 'eventlet.debug', - 'eventlet.greenthread', - 'eventlet.greenpool', - 'greenlet', -) - - -class test_Schedule(EventletCase): - - def test_sched(self): - with mock_module(*eventlet_modules): - with patch_many('eventlet.greenthread.spawn_after', - 'greenlet.GreenletExit') as (spawn_after, - GreenletExit): - x = Schedule() - x.GreenletExit = KeyError - entry = Mock() - g = x._enter(1, 0, entry) - self.assertTrue(x.queue) - - x._entry_exit(g, entry) - g.wait.side_effect = KeyError() - x._entry_exit(g, entry) - entry.cancel.assert_called_with() - self.assertFalse(x._queue) - - x._queue.add(g) - x.clear() - x._queue.add(g) - g.cancel.side_effect = KeyError() - x.clear() - - -class test_TaskPool(EventletCase): - - def test_pool(self): - with mock_module(*eventlet_modules): - with patch_many('eventlet.greenpool.GreenPool', - 'eventlet.greenthread') as (GreenPool, - greenthread): - x = TaskPool() - x.on_start() - x.on_stop() - x.on_apply(Mock()) - x._pool = None - x.on_stop() - self.assertTrue(x.getpid()) - - @patch('celery.concurrency.eventlet.base') - def test_apply_target(self, base): - apply_target(Mock(), getpid=Mock()) - self.assertTrue(base.apply_target.called) - - -class test_Timer(EventletCase): - - def test_timer(self): - x = Timer() - x.ensure_started() - x.schedule = Mock() - x.start() - x.stop() - x.schedule.clear.assert_called_with() - - tref = Mock() - x.cancel(tref) - x.schedule.GreenletExit = KeyError - tref.cancel.side_effect = KeyError() - x.cancel(tref) diff --git a/awx/lib/site-packages/celery/tests/concurrency/test_gevent.py b/awx/lib/site-packages/celery/tests/concurrency/test_gevent.py deleted file mode 100644 index baa105ba4b..0000000000 --- a/awx/lib/site-packages/celery/tests/concurrency/test_gevent.py +++ /dev/null @@ -1,146 +0,0 @@ -from __future__ import absolute_import - -from celery.concurrency.gevent import ( - Schedule, - Timer, - TaskPool, - apply_timeout, -) - -from celery.tests.case import ( - AppCase, Mock, SkipTest, mock_module, patch, patch_many, skip_if_pypy, -) - -gevent_modules = ( - 'gevent', - 'gevent.monkey', - 'gevent.greenlet', - 'gevent.pool', - 'greenlet', -) - - -class GeventCase(AppCase): - - @skip_if_pypy - def setup(self): - try: - self.gevent = __import__('gevent') - except ImportError: - raise SkipTest( - 'gevent not installed, skipping related tests.') - - -class test_gevent_patch(GeventCase): - - def test_is_patched(self): - with mock_module(*gevent_modules): - with patch('gevent.monkey.patch_all', create=True) as patch_all: - import gevent - gevent.version_info = (1, 0, 0) - from celery import maybe_patch_concurrency - maybe_patch_concurrency(['x', '-P', 'gevent']) - self.assertTrue(patch_all.called) - - -class test_Schedule(AppCase): - - def test_sched(self): - with mock_module(*gevent_modules): - with patch_many('gevent.greenlet', - 'gevent.greenlet.GreenletExit') as (greenlet, - GreenletExit): - greenlet.Greenlet = object - x = Schedule() - greenlet.Greenlet = Mock() - x._Greenlet.spawn_later = Mock() - x._GreenletExit = KeyError - entry = Mock() - g = x._enter(1, 0, entry) - self.assertTrue(x.queue) - - x._entry_exit(g) - g.kill.assert_called_with() - self.assertFalse(x._queue) - - x._queue.add(g) - x.clear() - x._queue.add(g) - g.kill.side_effect = KeyError() - x.clear() - - g = x._Greenlet() - g.cancel() - - -class test_TaskPool(AppCase): - - def test_pool(self): - with mock_module(*gevent_modules): - with patch_many('gevent.spawn_raw', 'gevent.pool.Pool') as ( - spawn_raw, Pool): - x = TaskPool() - x.on_start() - x.on_stop() - x.on_apply(Mock()) - x._pool = None - x.on_stop() - - x._pool = Mock() - x._pool._semaphore.counter = 1 - x._pool.size = 1 - x.grow() - self.assertEqual(x._pool.size, 2) - self.assertEqual(x._pool._semaphore.counter, 2) - x.shrink() - self.assertEqual(x._pool.size, 1) - self.assertEqual(x._pool._semaphore.counter, 1) - - x._pool = [4, 5, 6] - self.assertEqual(x.num_processes, 3) - - -class test_Timer(AppCase): - - def test_timer(self): - with mock_module(*gevent_modules): - x = Timer() - x.ensure_started() - x.schedule = Mock() - x.start() - x.stop() - x.schedule.clear.assert_called_with() - - -class test_apply_timeout(AppCase): - - def test_apply_timeout(self): - - class Timeout(Exception): - value = None - - def __init__(self, value): - self.__class__.value = value - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - pass - timeout_callback = Mock(name='timeout_callback') - apply_target = Mock(name='apply_target') - apply_timeout( - Mock(), timeout=10, callback=Mock(name='callback'), - timeout_callback=timeout_callback, - apply_target=apply_target, Timeout=Timeout, - ) - self.assertEqual(Timeout.value, 10) - self.assertTrue(apply_target.called) - - apply_target.side_effect = Timeout(10) - apply_timeout( - Mock(), timeout=10, callback=Mock(), - timeout_callback=timeout_callback, - apply_target=apply_target, Timeout=Timeout, - ) - timeout_callback.assert_called_with(False, 10) diff --git a/awx/lib/site-packages/celery/tests/concurrency/test_pool.py b/awx/lib/site-packages/celery/tests/concurrency/test_pool.py deleted file mode 100644 index d1b314b527..0000000000 --- a/awx/lib/site-packages/celery/tests/concurrency/test_pool.py +++ /dev/null @@ -1,82 +0,0 @@ -from __future__ import absolute_import - -import time -import itertools - -from billiard.einfo import ExceptionInfo - -from celery.tests.case import AppCase, SkipTest - - -def do_something(i): - return i * i - - -def long_something(): - time.sleep(1) - - -def raise_something(i): - try: - raise KeyError('FOO EXCEPTION') - except KeyError: - return ExceptionInfo() - - -class test_TaskPool(AppCase): - - def setup(self): - try: - __import__('multiprocessing') - except ImportError: - raise SkipTest('multiprocessing not supported') - from celery.concurrency.prefork import TaskPool - self.TaskPool = TaskPool - - def test_attrs(self): - p = self.TaskPool(2) - self.assertEqual(p.limit, 2) - self.assertIsNone(p._pool) - - def x_apply(self): - p = self.TaskPool(2) - p.start() - scratchpad = {} - proc_counter = itertools.count() - - def mycallback(ret_value): - process = next(proc_counter) - scratchpad[process] = {} - scratchpad[process]['ret_value'] = ret_value - - myerrback = mycallback - - res = p.apply_async(do_something, args=[10], callback=mycallback) - res2 = p.apply_async(raise_something, args=[10], errback=myerrback) - res3 = p.apply_async(do_something, args=[20], callback=mycallback) - - self.assertEqual(res.get(), 100) - time.sleep(0.5) - self.assertDictContainsSubset({'ret_value': 100}, - scratchpad.get(0)) - - self.assertIsInstance(res2.get(), ExceptionInfo) - self.assertTrue(scratchpad.get(1)) - time.sleep(1) - self.assertIsInstance(scratchpad[1]['ret_value'], - ExceptionInfo) - self.assertEqual(scratchpad[1]['ret_value'].exception.args, - ('FOO EXCEPTION', )) - - self.assertEqual(res3.get(), 400) - time.sleep(0.5) - self.assertDictContainsSubset({'ret_value': 400}, - scratchpad.get(2)) - - res3 = p.apply_async(do_something, args=[30], callback=mycallback) - - self.assertEqual(res3.get(), 900) - time.sleep(0.5) - self.assertDictContainsSubset({'ret_value': 900}, - scratchpad.get(3)) - p.stop() diff --git a/awx/lib/site-packages/celery/tests/concurrency/test_prefork.py b/awx/lib/site-packages/celery/tests/concurrency/test_prefork.py deleted file mode 100644 index 7ad247436b..0000000000 --- a/awx/lib/site-packages/celery/tests/concurrency/test_prefork.py +++ /dev/null @@ -1,320 +0,0 @@ -from __future__ import absolute_import - -import errno -import socket -import time - -from itertools import cycle - -from celery.five import items, range -from celery.utils.functional import noop -from celery.tests.case import AppCase, Mock, SkipTest, call, patch -try: - from celery.concurrency import prefork as mp - from celery.concurrency import asynpool -except ImportError: - - class _mp(object): - RUN = 0x1 - - class TaskPool(object): - _pool = Mock() - - def __init__(self, *args, **kwargs): - pass - - def start(self): - pass - - def stop(self): - pass - - def apply_async(self, *args, **kwargs): - pass - mp = _mp() # noqa - asynpool = None # noqa - - -class Object(object): # for writeable attributes. - - def __init__(self, **kwargs): - [setattr(self, k, v) for k, v in items(kwargs)] - - -class MockResult(object): - - def __init__(self, value, pid): - self.value = value - self.pid = pid - - def worker_pids(self): - return [self.pid] - - def get(self): - return self.value - - -class MockPool(object): - started = False - closed = False - joined = False - terminated = False - _state = None - - def __init__(self, *args, **kwargs): - self.started = True - self._timeout_handler = Mock() - self._result_handler = Mock() - self.maintain_pool = Mock() - self._state = mp.RUN - self._processes = kwargs.get('processes') - self._pool = [Object(pid=i, inqW_fd=1, outqR_fd=2) - for i in range(self._processes)] - self._current_proc = cycle(range(self._processes)) - - def close(self): - self.closed = True - self._state = 'CLOSE' - - def join(self): - self.joined = True - - def terminate(self): - self.terminated = True - - def terminate_job(self, *args, **kwargs): - pass - - def restart(self, *args, **kwargs): - pass - - def handle_result_event(self, *args, **kwargs): - pass - - def flush(self): - pass - - def grow(self, n=1): - self._processes += n - - def shrink(self, n=1): - self._processes -= n - - def apply_async(self, *args, **kwargs): - pass - - def register_with_event_loop(self, loop): - pass - - -class ExeMockPool(MockPool): - - def apply_async(self, target, args=(), kwargs={}, callback=noop): - from threading import Timer - res = target(*args, **kwargs) - Timer(0.1, callback, (res, )).start() - return MockResult(res, next(self._current_proc)) - - -class TaskPool(mp.TaskPool): - Pool = BlockingPool = MockPool - - -class ExeMockTaskPool(mp.TaskPool): - Pool = BlockingPool = ExeMockPool - - -class PoolCase(AppCase): - - def setup(self): - try: - import multiprocessing # noqa - except ImportError: - raise SkipTest('multiprocessing not supported') - - -class test_AsynPool(PoolCase): - - def test_gen_not_started(self): - - def gen(): - yield 1 - yield 2 - g = gen() - self.assertTrue(asynpool.gen_not_started(g)) - next(g) - self.assertFalse(asynpool.gen_not_started(g)) - list(g) - self.assertFalse(asynpool.gen_not_started(g)) - - def test_select(self): - ebadf = socket.error() - ebadf.errno = errno.EBADF - with patch('select.select') as select: - select.return_value = ([3], [], []) - self.assertEqual( - asynpool._select(set([3])), - ([3], [], 0), - ) - - select.return_value = ([], [], [3]) - self.assertEqual( - asynpool._select(set([3]), None, set([3])), - ([3], [], 0), - ) - - eintr = socket.error() - eintr.errno = errno.EINTR - select.side_effect = eintr - - readers = set([3]) - self.assertEqual(asynpool._select(readers), ([], [], 1)) - self.assertIn(3, readers) - - with patch('select.select') as select: - select.side_effect = ebadf - readers = set([3]) - self.assertEqual(asynpool._select(readers), ([], [], 1)) - select.assert_has_calls([call([3], [], [], 0)]) - self.assertNotIn(3, readers) - - with patch('select.select') as select: - select.side_effect = MemoryError() - with self.assertRaises(MemoryError): - asynpool._select(set([1])) - - with patch('select.select') as select: - - def se(*args): - select.side_effect = MemoryError() - raise ebadf - select.side_effect = se - with self.assertRaises(MemoryError): - asynpool._select(set([3])) - - with patch('select.select') as select: - - def se2(*args): - select.side_effect = socket.error() - select.side_effect.errno = 1321 - raise ebadf - select.side_effect = se2 - with self.assertRaises(socket.error): - asynpool._select(set([3])) - - with patch('select.select') as select: - - select.side_effect = socket.error() - select.side_effect.errno = 34134 - with self.assertRaises(socket.error): - asynpool._select(set([3])) - - def test_promise(self): - fun = Mock() - x = asynpool.promise(fun, (1, ), {'foo': 1}) - x() - self.assertTrue(x.ready) - fun.assert_called_with(1, foo=1) - - def test_Worker(self): - w = asynpool.Worker(Mock(), Mock()) - w.on_loop_start(1234) - w.outq.put.assert_called_with((asynpool.WORKER_UP, (1234, ))) - - -class test_ResultHandler(PoolCase): - - def test_process_result(self): - x = asynpool.ResultHandler( - Mock(), Mock(), {}, Mock(), - Mock(), Mock(), Mock(), Mock(), - fileno_to_outq={}, - on_process_alive=Mock(), - on_job_ready=Mock(), - ) - self.assertTrue(x) - hub = Mock(name='hub') - recv = x._recv_message = Mock(name='recv_message') - recv.return_value = iter([]) - x.on_state_change = Mock() - x.register_with_event_loop(hub) - proc = x.fileno_to_outq[3] = Mock() - reader = proc.outq._reader - reader.poll.return_value = False - x.handle_event(6) # KeyError - x.handle_event(3) - x._recv_message.assert_called_with( - hub.add_reader, 3, x.on_state_change, - ) - - -class test_TaskPool(PoolCase): - - def test_start(self): - pool = TaskPool(10) - pool.start() - self.assertTrue(pool._pool.started) - self.assertTrue(pool._pool._state == asynpool.RUN) - - _pool = pool._pool - pool.stop() - self.assertTrue(_pool.closed) - self.assertTrue(_pool.joined) - pool.stop() - - pool.start() - _pool = pool._pool - pool.terminate() - pool.terminate() - self.assertTrue(_pool.terminated) - - def test_apply_async(self): - pool = TaskPool(10) - pool.start() - pool.apply_async(lambda x: x, (2, ), {}) - - def test_grow_shrink(self): - pool = TaskPool(10) - pool.start() - self.assertEqual(pool._pool._processes, 10) - pool.grow() - self.assertEqual(pool._pool._processes, 11) - pool.shrink(2) - self.assertEqual(pool._pool._processes, 9) - - def test_info(self): - pool = TaskPool(10) - procs = [Object(pid=i) for i in range(pool.limit)] - - class _Pool(object): - _pool = procs - _maxtasksperchild = None - timeout = 10 - soft_timeout = 5 - - def human_write_stats(self, *args, **kwargs): - return {} - pool._pool = _Pool() - info = pool.info - self.assertEqual(info['max-concurrency'], pool.limit) - self.assertEqual(info['max-tasks-per-child'], 'N/A') - self.assertEqual(info['timeouts'], (5, 10)) - - def test_num_processes(self): - pool = TaskPool(7) - pool.start() - self.assertEqual(pool.num_processes, 7) - - def test_restart(self): - raise SkipTest('functional test') - - def get_pids(pool): - return set([p.pid for p in pool._pool._pool]) - - tp = self.TaskPool(5) - time.sleep(0.5) - tp.start() - pids = get_pids(tp) - tp.restart() - time.sleep(0.5) - self.assertEqual(pids, get_pids(tp)) diff --git a/awx/lib/site-packages/celery/tests/concurrency/test_solo.py b/awx/lib/site-packages/celery/tests/concurrency/test_solo.py deleted file mode 100644 index f701c6c642..0000000000 --- a/awx/lib/site-packages/celery/tests/concurrency/test_solo.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import absolute_import - -import operator - -from celery.concurrency import solo -from celery.utils.functional import noop -from celery.tests.case import AppCase - - -class test_solo_TaskPool(AppCase): - - def test_on_start(self): - x = solo.TaskPool() - x.on_start() - - def test_on_apply(self): - x = solo.TaskPool() - x.on_start() - x.on_apply(operator.add, (2, 2), {}, noop, noop) - - def test_info(self): - x = solo.TaskPool() - x.on_start() - self.assertTrue(x.info) diff --git a/awx/lib/site-packages/celery/tests/concurrency/test_threads.py b/awx/lib/site-packages/celery/tests/concurrency/test_threads.py deleted file mode 100644 index 2eb5e3882f..0000000000 --- a/awx/lib/site-packages/celery/tests/concurrency/test_threads.py +++ /dev/null @@ -1,60 +0,0 @@ -from __future__ import absolute_import - -from celery.concurrency.threads import NullDict, TaskPool, apply_target - -from celery.tests.case import AppCase, Case, Mock, mask_modules, mock_module - - -class test_NullDict(Case): - - def test_setitem(self): - x = NullDict() - x['foo'] = 1 - with self.assertRaises(KeyError): - x['foo'] - - -class test_TaskPool(AppCase): - - def test_without_threadpool(self): - - with mask_modules('threadpool'): - with self.assertRaises(ImportError): - TaskPool() - - def test_with_threadpool(self): - with mock_module('threadpool'): - x = TaskPool() - self.assertTrue(x.ThreadPool) - self.assertTrue(x.WorkRequest) - - def test_on_start(self): - with mock_module('threadpool'): - x = TaskPool() - x.on_start() - self.assertTrue(x._pool) - self.assertIsInstance(x._pool.workRequests, NullDict) - - def test_on_stop(self): - with mock_module('threadpool'): - x = TaskPool() - x.on_start() - x.on_stop() - x._pool.dismissWorkers.assert_called_with(x.limit, do_join=True) - - def test_on_apply(self): - with mock_module('threadpool'): - x = TaskPool() - x.on_start() - callback = Mock() - accept_callback = Mock() - target = Mock() - req = x.on_apply(target, args=(1, 2), kwargs={'a': 10}, - callback=callback, - accept_callback=accept_callback) - x.WorkRequest.assert_called_with( - apply_target, - (target, (1, 2), {'a': 10}, callback, accept_callback), - ) - x._pool.putRequest.assert_called_with(req) - x._pool._results_queue.queue.clear.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/contrib/__init__.py b/awx/lib/site-packages/celery/tests/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/contrib/test_abortable.py b/awx/lib/site-packages/celery/tests/contrib/test_abortable.py deleted file mode 100644 index 4bc2df77b9..0000000000 --- a/awx/lib/site-packages/celery/tests/contrib/test_abortable.py +++ /dev/null @@ -1,49 +0,0 @@ -from __future__ import absolute_import - -from celery.contrib.abortable import AbortableTask, AbortableAsyncResult -from celery.tests.case import AppCase - - -class test_AbortableTask(AppCase): - - def setup(self): - - @self.app.task(base=AbortableTask, shared=False) - def abortable(): - return True - self.abortable = abortable - - def test_async_result_is_abortable(self): - result = self.abortable.apply_async() - tid = result.id - self.assertIsInstance( - self.abortable.AsyncResult(tid), AbortableAsyncResult, - ) - - def test_is_not_aborted(self): - self.abortable.push_request() - try: - result = self.abortable.apply_async() - tid = result.id - self.assertFalse(self.abortable.is_aborted(task_id=tid)) - finally: - self.abortable.pop_request() - - def test_is_aborted_not_abort_result(self): - self.abortable.AsyncResult = self.app.AsyncResult - self.abortable.push_request() - try: - self.abortable.request.id = 'foo' - self.assertFalse(self.abortable.is_aborted()) - finally: - self.abortable.pop_request() - - def test_abort_yields_aborted(self): - self.abortable.push_request() - try: - result = self.abortable.apply_async() - result.abort() - tid = result.id - self.assertTrue(self.abortable.is_aborted(task_id=tid)) - finally: - self.abortable.pop_request() diff --git a/awx/lib/site-packages/celery/tests/contrib/test_methods.py b/awx/lib/site-packages/celery/tests/contrib/test_methods.py deleted file mode 100644 index da74cc98b1..0000000000 --- a/awx/lib/site-packages/celery/tests/contrib/test_methods.py +++ /dev/null @@ -1,34 +0,0 @@ -from __future__ import absolute_import - -from celery.contrib.methods import task_method, task - -from celery.tests.case import AppCase, patch - - -class test_task_method(AppCase): - - def test_task_method(self): - - class X(object): - - def __init__(self): - self.state = 0 - - @self.app.task(shared=False, filter=task_method) - def add(self, x): - self.state += x - - x = X() - x.add(2) - self.assertEqual(x.state, 2) - x.add(4) - self.assertEqual(x.state, 6) - - self.assertTrue(X.add) - self.assertIs(x.add.__self__, x) - - def test_task(self): - with patch('celery.contrib.methods.current_app') as curapp: - fun = object() - task(fun, x=1) - curapp.task.assert_called_with(fun, x=1, filter=task_method) diff --git a/awx/lib/site-packages/celery/tests/contrib/test_migrate.py b/awx/lib/site-packages/celery/tests/contrib/test_migrate.py deleted file mode 100644 index fbd80a536c..0000000000 --- a/awx/lib/site-packages/celery/tests/contrib/test_migrate.py +++ /dev/null @@ -1,314 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from contextlib import contextmanager - -from amqp import ChannelError - -from kombu import Connection, Producer, Queue, Exchange - -from kombu.transport.virtual import QoS - -from celery.contrib.migrate import ( - StopFiltering, - State, - migrate_task, - migrate_tasks, - filter_callback, - _maybe_queue, - filter_status, - move_by_taskmap, - move_by_idmap, - move_task_by_id, - start_filter, - task_id_in, - task_id_eq, - expand_dest, - move, -) -from celery.utils.encoding import bytes_t, ensure_bytes -from celery.tests.case import AppCase, Mock, override_stdouts, patch - -# hack to ignore error at shutdown -QoS.restore_at_shutdown = False - - -def Message(body, exchange='exchange', routing_key='rkey', - compression=None, content_type='application/json', - content_encoding='utf-8'): - return Mock( - attrs={ - 'body': body, - 'delivery_info': { - 'exchange': exchange, - 'routing_key': routing_key, - }, - 'headers': { - 'compression': compression, - }, - 'content_type': content_type, - 'content_encoding': content_encoding, - 'properties': {} - }, - ) - - -class test_State(AppCase): - - def test_strtotal(self): - x = State() - self.assertEqual(x.strtotal, '?') - x.total_apx = 100 - self.assertEqual(x.strtotal, '100') - - def test_repr(self): - x = State() - self.assertTrue(repr(x)) - x.filtered = 'foo' - self.assertTrue(repr(x)) - - -class test_move(AppCase): - - @contextmanager - def move_context(self, **kwargs): - with patch('celery.contrib.migrate.start_filter') as start: - with patch('celery.contrib.migrate.republish') as republish: - pred = Mock(name='predicate') - move(pred, app=self.app, - connection=self.app.connection(), **kwargs) - self.assertTrue(start.called) - callback = start.call_args[0][2] - yield callback, pred, republish - - def msgpair(self, **kwargs): - body = dict({'task': 'add', 'id': 'id'}, **kwargs) - return body, Message(body) - - def test_move(self): - with self.move_context() as (callback, pred, republish): - pred.return_value = None - body, message = self.msgpair() - callback(body, message) - self.assertFalse(message.ack.called) - self.assertFalse(republish.called) - - pred.return_value = 'foo' - callback(body, message) - message.ack.assert_called_with() - self.assertTrue(republish.called) - - def test_move_transform(self): - trans = Mock(name='transform') - trans.return_value = Queue('bar') - with self.move_context(transform=trans) as (callback, pred, republish): - pred.return_value = 'foo' - body, message = self.msgpair() - with patch('celery.contrib.migrate.maybe_declare') as maybed: - callback(body, message) - trans.assert_called_with('foo') - self.assertTrue(maybed.called) - self.assertTrue(republish.called) - - def test_limit(self): - with self.move_context(limit=1) as (callback, pred, republish): - pred.return_value = 'foo' - body, message = self.msgpair() - with self.assertRaises(StopFiltering): - callback(body, message) - self.assertTrue(republish.called) - - def test_callback(self): - cb = Mock() - with self.move_context(callback=cb) as (callback, pred, republish): - pred.return_value = 'foo' - body, message = self.msgpair() - callback(body, message) - self.assertTrue(republish.called) - self.assertTrue(cb.called) - - -class test_start_filter(AppCase): - - def test_start(self): - with patch('celery.contrib.migrate.eventloop') as evloop: - app = Mock() - filt = Mock(name='filter') - conn = Connection('memory://') - evloop.side_effect = StopFiltering() - app.amqp.queues = {'foo': Queue('foo'), 'bar': Queue('bar')} - consumer = app.amqp.TaskConsumer.return_value = Mock(name='consum') - consumer.queues = list(app.amqp.queues.values()) - consumer.channel = conn.default_channel - consumer.__enter__ = Mock(name='consumer.__enter__') - consumer.__exit__ = Mock(name='consumer.__exit__') - consumer.callbacks = [] - - def register_callback(x): - consumer.callbacks.append(x) - consumer.register_callback = register_callback - - start_filter(app, conn, filt, - queues='foo,bar', ack_messages=True) - body = {'task': 'add', 'id': 'id'} - for callback in consumer.callbacks: - callback(body, Message(body)) - consumer.callbacks[:] = [] - cb = Mock(name='callback=') - start_filter(app, conn, filt, tasks='add,mul', callback=cb) - for callback in consumer.callbacks: - callback(body, Message(body)) - self.assertTrue(cb.called) - - on_declare_queue = Mock() - start_filter(app, conn, filt, tasks='add,mul', queues='foo', - on_declare_queue=on_declare_queue) - self.assertTrue(on_declare_queue.called) - start_filter(app, conn, filt, queues=['foo', 'bar']) - consumer.callbacks[:] = [] - state = State() - start_filter(app, conn, filt, - tasks='add,mul', callback=cb, state=state, limit=1) - stop_filtering_raised = False - for callback in consumer.callbacks: - try: - callback(body, Message(body)) - except StopFiltering: - stop_filtering_raised = True - self.assertTrue(state.count) - self.assertTrue(stop_filtering_raised) - - -class test_filter_callback(AppCase): - - def test_filter(self): - callback = Mock() - filt = filter_callback(callback, ['add', 'mul']) - t1 = {'task': 'add'} - t2 = {'task': 'div'} - - message = Mock() - filt(t2, message) - self.assertFalse(callback.called) - filt(t1, message) - callback.assert_called_with(t1, message) - - -class test_utils(AppCase): - - def test_task_id_in(self): - self.assertTrue(task_id_in(['A'], {'id': 'A'}, Mock())) - self.assertFalse(task_id_in(['A'], {'id': 'B'}, Mock())) - - def test_task_id_eq(self): - self.assertTrue(task_id_eq('A', {'id': 'A'}, Mock())) - self.assertFalse(task_id_eq('A', {'id': 'B'}, Mock())) - - def test_expand_dest(self): - self.assertEqual(expand_dest(None, 'foo', 'bar'), ('foo', 'bar')) - self.assertEqual(expand_dest(('b', 'x'), 'foo', 'bar'), ('b', 'x')) - - def test_maybe_queue(self): - app = Mock() - app.amqp.queues = {'foo': 313} - self.assertEqual(_maybe_queue(app, 'foo'), 313) - self.assertEqual(_maybe_queue(app, Queue('foo')), Queue('foo')) - - def test_filter_status(self): - with override_stdouts() as (stdout, stderr): - filter_status(State(), {'id': '1', 'task': 'add'}, Mock()) - self.assertTrue(stdout.getvalue()) - - def test_move_by_taskmap(self): - with patch('celery.contrib.migrate.move') as move: - move_by_taskmap({'add': Queue('foo')}) - self.assertTrue(move.called) - cb = move.call_args[0][0] - self.assertTrue(cb({'task': 'add'}, Mock())) - - def test_move_by_idmap(self): - with patch('celery.contrib.migrate.move') as move: - move_by_idmap({'123f': Queue('foo')}) - self.assertTrue(move.called) - cb = move.call_args[0][0] - self.assertTrue(cb({'id': '123f'}, Mock())) - - def test_move_task_by_id(self): - with patch('celery.contrib.migrate.move') as move: - move_task_by_id('123f', Queue('foo')) - self.assertTrue(move.called) - cb = move.call_args[0][0] - self.assertEqual( - cb({'id': '123f'}, Mock()), - Queue('foo'), - ) - - -class test_migrate_task(AppCase): - - def test_removes_compression_header(self): - x = Message('foo', compression='zlib') - producer = Mock() - migrate_task(producer, x.body, x) - self.assertTrue(producer.publish.called) - args, kwargs = producer.publish.call_args - self.assertIsInstance(args[0], bytes_t) - self.assertNotIn('compression', kwargs['headers']) - self.assertEqual(kwargs['compression'], 'zlib') - self.assertEqual(kwargs['content_type'], 'application/json') - self.assertEqual(kwargs['content_encoding'], 'utf-8') - self.assertEqual(kwargs['exchange'], 'exchange') - self.assertEqual(kwargs['routing_key'], 'rkey') - - -class test_migrate_tasks(AppCase): - - def test_migrate(self, name='testcelery'): - x = Connection('memory://foo') - y = Connection('memory://foo') - # use separate state - x.default_channel.queues = {} - y.default_channel.queues = {} - - ex = Exchange(name, 'direct') - q = Queue(name, exchange=ex, routing_key=name) - q(x.default_channel).declare() - Producer(x).publish('foo', exchange=name, routing_key=name) - Producer(x).publish('bar', exchange=name, routing_key=name) - Producer(x).publish('baz', exchange=name, routing_key=name) - self.assertTrue(x.default_channel.queues) - self.assertFalse(y.default_channel.queues) - - migrate_tasks(x, y, accept=['text/plain'], app=self.app) - - yq = q(y.default_channel) - self.assertEqual(yq.get().body, ensure_bytes('foo')) - self.assertEqual(yq.get().body, ensure_bytes('bar')) - self.assertEqual(yq.get().body, ensure_bytes('baz')) - - Producer(x).publish('foo', exchange=name, routing_key=name) - callback = Mock() - migrate_tasks(x, y, - callback=callback, accept=['text/plain'], app=self.app) - self.assertTrue(callback.called) - migrate = Mock() - Producer(x).publish('baz', exchange=name, routing_key=name) - migrate_tasks(x, y, callback=callback, - migrate=migrate, accept=['text/plain'], app=self.app) - self.assertTrue(migrate.called) - - with patch('kombu.transport.virtual.Channel.queue_declare') as qd: - - def effect(*args, **kwargs): - if kwargs.get('passive'): - raise ChannelError('some channel error') - return 0, 3, 0 - qd.side_effect = effect - migrate_tasks(x, y, app=self.app) - - x = Connection('memory://') - x.default_channel.queues = {} - y.default_channel.queues = {} - callback = Mock() - migrate_tasks(x, y, - callback=callback, accept=['text/plain'], app=self.app) - self.assertFalse(callback.called) diff --git a/awx/lib/site-packages/celery/tests/contrib/test_rdb.py b/awx/lib/site-packages/celery/tests/contrib/test_rdb.py deleted file mode 100644 index a933c60101..0000000000 --- a/awx/lib/site-packages/celery/tests/contrib/test_rdb.py +++ /dev/null @@ -1,102 +0,0 @@ -from __future__ import absolute_import - -import errno -import socket - -from celery.contrib.rdb import ( - Rdb, - debugger, - set_trace, -) -from celery.tests.case import Case, Mock, WhateverIO, patch, skip_if_pypy - - -class SockErr(socket.error): - errno = None - - -class test_Rdb(Case): - - @patch('celery.contrib.rdb.Rdb') - def test_debugger(self, Rdb): - x = debugger() - self.assertTrue(x) - self.assertIs(x, debugger()) - - @patch('celery.contrib.rdb.debugger') - @patch('celery.contrib.rdb._frame') - def test_set_trace(self, _frame, debugger): - self.assertTrue(set_trace(Mock())) - self.assertTrue(set_trace()) - self.assertTrue(debugger.return_value.set_trace.called) - - @patch('celery.contrib.rdb.Rdb.get_avail_port') - @skip_if_pypy - def test_rdb(self, get_avail_port): - sock = Mock() - get_avail_port.return_value = (sock, 8000) - sock.accept.return_value = (Mock(), ['helu']) - out = WhateverIO() - rdb = Rdb(out=out) - self.assertTrue(get_avail_port.called) - self.assertIn('helu', out.getvalue()) - - # set_quit - with patch('sys.settrace') as settrace: - rdb.set_quit() - settrace.assert_called_with(None) - - # set_trace - with patch('celery.contrib.rdb.Pdb.set_trace') as pset: - with patch('celery.contrib.rdb._frame'): - rdb.set_trace() - rdb.set_trace(Mock()) - pset.side_effect = SockErr - pset.side_effect.errno = errno.ECONNRESET - rdb.set_trace() - pset.side_effect.errno = errno.ENOENT - with self.assertRaises(SockErr): - rdb.set_trace() - - # _close_session - rdb._close_session() - - # do_continue - rdb.set_continue = Mock() - rdb.do_continue(Mock()) - rdb.set_continue.assert_called_with() - - # do_quit - rdb.set_quit = Mock() - rdb.do_quit(Mock()) - rdb.set_quit.assert_called_with() - - @patch('socket.socket') - @skip_if_pypy - def test_get_avail_port(self, sock): - out = WhateverIO() - sock.return_value.accept.return_value = (Mock(), ['helu']) - Rdb(out=out) - - with patch('celery.contrib.rdb.current_process') as curproc: - curproc.return_value.name = 'PoolWorker-10' - Rdb(out=out) - - err = sock.return_value.bind.side_effect = SockErr() - err.errno = errno.ENOENT - with self.assertRaises(SockErr): - Rdb(out=out) - err.errno = errno.EADDRINUSE - with self.assertRaises(Exception): - Rdb(out=out) - called = [0] - - def effect(*a, **kw): - try: - if called[0] > 50: - return True - raise err - finally: - called[0] += 1 - sock.return_value.bind.side_effect = effect - Rdb(out=out) diff --git a/awx/lib/site-packages/celery/tests/events/__init__.py b/awx/lib/site-packages/celery/tests/events/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/events/test_cursesmon.py b/awx/lib/site-packages/celery/tests/events/test_cursesmon.py deleted file mode 100644 index c8e615167c..0000000000 --- a/awx/lib/site-packages/celery/tests/events/test_cursesmon.py +++ /dev/null @@ -1,70 +0,0 @@ -from __future__ import absolute_import - -from celery.tests.case import AppCase, SkipTest - - -class MockWindow(object): - - def getmaxyx(self): - return self.y, self.x - - -class test_CursesDisplay(AppCase): - - def setup(self): - try: - import curses # noqa - except ImportError: - raise SkipTest('curses monitor requires curses') - - from celery.events import cursesmon - self.monitor = cursesmon.CursesMonitor(object(), app=self.app) - self.win = MockWindow() - self.monitor.win = self.win - - def test_format_row_with_default_widths(self): - self.win.x, self.win.y = 91, 24 - row = self.monitor.format_row( - '783da208-77d0-40ca-b3d6-37dd6dbb55d3', - 'task.task.task.task.task.task.task.task.task.tas', - 'workerworkerworkerworkerworkerworkerworkerworker', - '21:13:20', - 'SUCCESS') - self.assertEqual('783da208-77d0-40ca-b3d6-37dd6dbb55d3 ' - 'workerworker... task.task.[.]tas 21:13:20 SUCCESS ', - row) - - def test_format_row_with_truncated_uuid(self): - self.win.x, self.win.y = 80, 24 - row = self.monitor.format_row( - '783da208-77d0-40ca-b3d6-37dd6dbb55d3', - 'task.task.task.task.task.task.task.task.task.tas', - 'workerworkerworkerworkerworkerworkerworkerworker', - '21:13:20', - 'SUCCESS') - self.assertEqual('783da208-77d0-40ca-b3d... workerworker... ' - 'task.task.[.]tas 21:13:20 SUCCESS ', - row) - - def test_format_title_row(self): - self.win.x, self.win.y = 80, 24 - row = self.monitor.format_row('UUID', 'TASK', - 'WORKER', 'TIME', 'STATE') - self.assertEqual('UUID WORKER ' - 'TASK TIME STATE ', - row) - - def test_format_row_for_wide_screen_with_short_uuid(self): - self.win.x, self.win.y = 140, 24 - row = self.monitor.format_row( - '783da208-77d0-40ca-b3d6-37dd6dbb55d3', - 'task.task.task.task.task.task.task.task.task.tas', - 'workerworkerworkerworkerworkerworkerworkerworker', - '21:13:20', - 'SUCCESS') - self.assertEqual(136, len(row)) - self.assertEqual('783da208-77d0-40ca-b3d6-37dd6dbb55d3 ' - 'workerworkerworkerworkerworkerworker... ' - 'task.task.task.task.task.task.task.[.]tas ' - '21:13:20 SUCCESS ', - row) diff --git a/awx/lib/site-packages/celery/tests/events/test_events.py b/awx/lib/site-packages/celery/tests/events/test_events.py deleted file mode 100644 index 791f4167ed..0000000000 --- a/awx/lib/site-packages/celery/tests/events/test_events.py +++ /dev/null @@ -1,260 +0,0 @@ -from __future__ import absolute_import - -import socket - -from celery.events import Event -from celery.tests.case import AppCase, Mock - - -class MockProducer(object): - raise_on_publish = False - - def __init__(self, *args, **kwargs): - self.sent = [] - - def publish(self, msg, *args, **kwargs): - if self.raise_on_publish: - raise KeyError() - self.sent.append(msg) - - def close(self): - pass - - def has_event(self, kind): - for event in self.sent: - if event['type'] == kind: - return event - return False - - -class test_Event(AppCase): - - def test_constructor(self): - event = Event('world war II') - self.assertEqual(event['type'], 'world war II') - self.assertTrue(event['timestamp']) - - -class test_EventDispatcher(AppCase): - - def test_redis_uses_fanout_exchange(self): - self.app.connection = Mock() - conn = self.app.connection.return_value = Mock() - conn.transport.driver_type = 'redis' - - dispatcher = self.app.events.Dispatcher(conn, enabled=False) - self.assertEqual(dispatcher.exchange.type, 'fanout') - - def test_others_use_topic_exchange(self): - self.app.connection = Mock() - conn = self.app.connection.return_value = Mock() - conn.transport.driver_type = 'amqp' - dispatcher = self.app.events.Dispatcher(conn, enabled=False) - self.assertEqual(dispatcher.exchange.type, 'topic') - - def test_takes_channel_connection(self): - x = self.app.events.Dispatcher(channel=Mock()) - self.assertIs(x.connection, x.channel.connection.client) - - def test_sql_transports_disabled(self): - conn = Mock() - conn.transport.driver_type = 'sql' - x = self.app.events.Dispatcher(connection=conn) - self.assertFalse(x.enabled) - - def test_send(self): - producer = MockProducer() - producer.connection = self.app.connection() - connection = Mock() - connection.transport.driver_type = 'amqp' - eventer = self.app.events.Dispatcher(connection, enabled=False, - buffer_while_offline=False) - eventer.producer = producer - eventer.enabled = True - eventer.send('World War II', ended=True) - self.assertTrue(producer.has_event('World War II')) - eventer.enabled = False - eventer.send('World War III') - self.assertFalse(producer.has_event('World War III')) - - evs = ('Event 1', 'Event 2', 'Event 3') - eventer.enabled = True - eventer.producer.raise_on_publish = True - eventer.buffer_while_offline = False - with self.assertRaises(KeyError): - eventer.send('Event X') - eventer.buffer_while_offline = True - for ev in evs: - eventer.send(ev) - eventer.producer.raise_on_publish = False - eventer.flush() - for ev in evs: - self.assertTrue(producer.has_event(ev)) - - buf = eventer._outbound_buffer = Mock() - buf.popleft.side_effect = IndexError() - eventer.flush() - - def test_enter_exit(self): - with self.app.connection() as conn: - d = self.app.events.Dispatcher(conn) - d.close = Mock() - with d as _d: - self.assertTrue(_d) - d.close.assert_called_with() - - def test_enable_disable_callbacks(self): - on_enable = Mock() - on_disable = Mock() - with self.app.connection() as conn: - with self.app.events.Dispatcher(conn, enabled=False) as d: - d.on_enabled.add(on_enable) - d.on_disabled.add(on_disable) - d.enable() - on_enable.assert_called_with() - d.disable() - on_disable.assert_called_with() - - def test_enabled_disable(self): - connection = self.app.connection() - channel = connection.channel() - try: - dispatcher = self.app.events.Dispatcher(connection, - enabled=True) - dispatcher2 = self.app.events.Dispatcher(connection, - enabled=True, - channel=channel) - self.assertTrue(dispatcher.enabled) - self.assertTrue(dispatcher.producer.channel) - self.assertEqual(dispatcher.producer.serializer, - self.app.conf.CELERY_EVENT_SERIALIZER) - - created_channel = dispatcher.producer.channel - dispatcher.disable() - dispatcher.disable() # Disable with no active producer - dispatcher2.disable() - self.assertFalse(dispatcher.enabled) - self.assertIsNone(dispatcher.producer) - self.assertFalse(dispatcher2.channel.closed, - 'does not close manually provided channel') - - dispatcher.enable() - self.assertTrue(dispatcher.enabled) - self.assertTrue(dispatcher.producer) - - # XXX test compat attribute - self.assertIs(dispatcher.publisher, dispatcher.producer) - prev, dispatcher.publisher = dispatcher.producer, 42 - try: - self.assertEqual(dispatcher.producer, 42) - finally: - dispatcher.producer = prev - finally: - channel.close() - connection.close() - self.assertTrue(created_channel.closed) - - -class test_EventReceiver(AppCase): - - def test_process(self): - - message = {'type': 'world-war'} - - got_event = [False] - - def my_handler(event): - got_event[0] = True - - connection = Mock() - connection.transport_cls = 'memory' - r = self.app.events.Receiver( - connection, - handlers={'world-war': my_handler}, - node_id='celery.tests', - ) - r._receive(message, object()) - self.assertTrue(got_event[0]) - - def test_catch_all_event(self): - - message = {'type': 'world-war'} - - got_event = [False] - - def my_handler(event): - got_event[0] = True - - connection = Mock() - connection.transport_cls = 'memory' - r = self.app.events.Receiver(connection, node_id='celery.tests') - r.handlers['*'] = my_handler - r._receive(message, object()) - self.assertTrue(got_event[0]) - - def test_itercapture(self): - connection = self.app.connection() - try: - r = self.app.events.Receiver(connection, node_id='celery.tests') - it = r.itercapture(timeout=0.0001, wakeup=False) - - with self.assertRaises(socket.timeout): - next(it) - - with self.assertRaises(socket.timeout): - r.capture(timeout=0.00001) - finally: - connection.close() - - def test_event_from_message_localize_disabled(self): - r = self.app.events.Receiver(Mock(), node_id='celery.tests') - r.adjust_clock = Mock() - ts_adjust = Mock() - - r.event_from_message( - {'type': 'worker-online', 'clock': 313}, - localize=False, - adjust_timestamp=ts_adjust, - ) - self.assertFalse(ts_adjust.called) - r.adjust_clock.assert_called_with(313) - - def test_itercapture_limit(self): - connection = self.app.connection() - channel = connection.channel() - try: - events_received = [0] - - def handler(event): - events_received[0] += 1 - - producer = self.app.events.Dispatcher( - connection, enabled=True, channel=channel, - ) - r = self.app.events.Receiver( - connection, - handlers={'*': handler}, - node_id='celery.tests', - ) - evs = ['ev1', 'ev2', 'ev3', 'ev4', 'ev5'] - for ev in evs: - producer.send(ev) - it = r.itercapture(limit=4, wakeup=True) - next(it) # skip consumer (see itercapture) - list(it) - self.assertEqual(events_received[0], 4) - finally: - channel.close() - connection.close() - - -class test_misc(AppCase): - - def test_State(self): - state = self.app.events.State() - self.assertDictEqual(dict(state.workers), {}) - - def test_default_dispatcher(self): - with self.app.events.default_dispatcher() as d: - self.assertTrue(d) - self.assertTrue(d.connection) diff --git a/awx/lib/site-packages/celery/tests/events/test_snapshot.py b/awx/lib/site-packages/celery/tests/events/test_snapshot.py deleted file mode 100644 index f551751d6a..0000000000 --- a/awx/lib/site-packages/celery/tests/events/test_snapshot.py +++ /dev/null @@ -1,130 +0,0 @@ -from __future__ import absolute_import - -from celery.events import Events -from celery.events.snapshot import Polaroid, evcam -from celery.tests.case import AppCase, patch, restore_logging - - -class TRef(object): - active = True - called = False - - def __call__(self): - self.called = True - - def cancel(self): - self.active = False - - -class MockTimer(object): - installed = [] - - def call_repeatedly(self, secs, fun, *args, **kwargs): - self.installed.append(fun) - return TRef() -timer = MockTimer() - - -class test_Polaroid(AppCase): - - def setup(self): - self.state = self.app.events.State() - - def test_constructor(self): - x = Polaroid(self.state, app=self.app) - self.assertIs(x.app, self.app) - self.assertIs(x.state, self.state) - self.assertTrue(x.freq) - self.assertTrue(x.cleanup_freq) - self.assertTrue(x.logger) - self.assertFalse(x.maxrate) - - def test_install_timers(self): - x = Polaroid(self.state, app=self.app) - x.timer = timer - x.__exit__() - x.__enter__() - self.assertIn(x.capture, MockTimer.installed) - self.assertIn(x.cleanup, MockTimer.installed) - self.assertTrue(x._tref.active) - self.assertTrue(x._ctref.active) - x.__exit__() - self.assertFalse(x._tref.active) - self.assertFalse(x._ctref.active) - self.assertTrue(x._tref.called) - self.assertFalse(x._ctref.called) - - def test_cleanup(self): - x = Polaroid(self.state, app=self.app) - cleanup_signal_sent = [False] - - def handler(**kwargs): - cleanup_signal_sent[0] = True - - x.cleanup_signal.connect(handler) - x.cleanup() - self.assertTrue(cleanup_signal_sent[0]) - - def test_shutter__capture(self): - x = Polaroid(self.state, app=self.app) - shutter_signal_sent = [False] - - def handler(**kwargs): - shutter_signal_sent[0] = True - - x.shutter_signal.connect(handler) - x.shutter() - self.assertTrue(shutter_signal_sent[0]) - - shutter_signal_sent[0] = False - x.capture() - self.assertTrue(shutter_signal_sent[0]) - - def test_shutter_maxrate(self): - x = Polaroid(self.state, app=self.app, maxrate='1/h') - shutter_signal_sent = [0] - - def handler(**kwargs): - shutter_signal_sent[0] += 1 - - x.shutter_signal.connect(handler) - for i in range(30): - x.shutter() - x.shutter() - x.shutter() - self.assertEqual(shutter_signal_sent[0], 1) - - -class test_evcam(AppCase): - - class MockReceiver(object): - raise_keyboard_interrupt = False - - def capture(self, **kwargs): - if self.__class__.raise_keyboard_interrupt: - raise KeyboardInterrupt() - - class MockEvents(Events): - - def Receiver(self, *args, **kwargs): - return test_evcam.MockReceiver() - - def setup(self): - self.app.events = self.MockEvents() - self.app.events.app = self.app - - def test_evcam(self): - with restore_logging(): - evcam(Polaroid, timer=timer, app=self.app) - evcam(Polaroid, timer=timer, loglevel='CRITICAL', app=self.app) - self.MockReceiver.raise_keyboard_interrupt = True - try: - with self.assertRaises(SystemExit): - evcam(Polaroid, timer=timer, app=self.app) - finally: - self.MockReceiver.raise_keyboard_interrupt = False - - @patch('celery.platforms.create_pidlock') - def test_evcam_pidfile(self, create_pidlock): - evcam(Polaroid, timer=timer, pidfile='/var/pid', app=self.app) - create_pidlock.assert_called_with('/var/pid') diff --git a/awx/lib/site-packages/celery/tests/events/test_state.py b/awx/lib/site-packages/celery/tests/events/test_state.py deleted file mode 100644 index b7e35d7cf1..0000000000 --- a/awx/lib/site-packages/celery/tests/events/test_state.py +++ /dev/null @@ -1,581 +0,0 @@ -from __future__ import absolute_import - -import pickle - -from decimal import Decimal -from random import shuffle -from time import time -from itertools import count - -from celery import states -from celery.events import Event -from celery.events.state import ( - State, - Worker, - Task, - HEARTBEAT_EXPIRE_WINDOW, - HEARTBEAT_DRIFT_MAX, -) -from celery.five import range -from celery.utils import uuid -from celery.tests.case import AppCase, Mock, patch - -try: - Decimal(2.6) -except TypeError: # pragma: no cover - # Py2.6: Must first convert float to str - _float_to_decimal = str -else: - _float_to_decimal = lambda f: f # noqa - - -class replay(object): - - def __init__(self, state): - self.state = state - self.rewind() - self.setup() - self.current_clock = 0 - - def setup(self): - pass - - def next_event(self): - ev = self.events[next(self.position)] - ev['local_received'] = ev['timestamp'] - try: - self.current_clock = ev['clock'] - except KeyError: - ev['clock'] = self.current_clock = self.current_clock + 1 - return ev - - def __iter__(self): - return self - - def __next__(self): - try: - self.state.event(self.next_event()) - except IndexError: - raise StopIteration() - next = __next__ - - def rewind(self): - self.position = count(0) - return self - - def play(self): - for _ in self: - pass - - -class ev_worker_online_offline(replay): - - def setup(self): - self.events = [ - Event('worker-online', hostname='utest1'), - Event('worker-offline', hostname='utest1'), - ] - - -class ev_worker_heartbeats(replay): - - def setup(self): - self.events = [ - Event('worker-heartbeat', hostname='utest1', - timestamp=time() - HEARTBEAT_EXPIRE_WINDOW * 2), - Event('worker-heartbeat', hostname='utest1'), - ] - - -class ev_task_states(replay): - - def setup(self): - tid = self.tid = uuid() - self.events = [ - Event('task-received', uuid=tid, name='task1', - args='(2, 2)', kwargs="{'foo': 'bar'}", - retries=0, eta=None, hostname='utest1'), - Event('task-started', uuid=tid, hostname='utest1'), - Event('task-revoked', uuid=tid, hostname='utest1'), - Event('task-retried', uuid=tid, exception="KeyError('bar')", - traceback='line 2 at main', hostname='utest1'), - Event('task-failed', uuid=tid, exception="KeyError('foo')", - traceback='line 1 at main', hostname='utest1'), - Event('task-succeeded', uuid=tid, result='4', - runtime=0.1234, hostname='utest1'), - ] - - -def QTEV(type, uuid, hostname, clock, name=None, timestamp=None): - """Quick task event.""" - return Event('task-{0}'.format(type), uuid=uuid, hostname=hostname, - clock=clock, name=name, timestamp=timestamp or time()) - - -class ev_logical_clock_ordering(replay): - - def __init__(self, state, offset=0, uids=None): - self.offset = offset or 0 - self.uids = self.setuids(uids) - super(ev_logical_clock_ordering, self).__init__(state) - - def setuids(self, uids): - uids = self.tA, self.tB, self.tC = uids or [uuid(), uuid(), uuid()] - return uids - - def setup(self): - offset = self.offset - tA, tB, tC = self.uids - self.events = [ - QTEV('received', tA, 'w1', name='tA', clock=offset + 1), - QTEV('received', tB, 'w2', name='tB', clock=offset + 1), - QTEV('started', tA, 'w1', name='tA', clock=offset + 3), - QTEV('received', tC, 'w2', name='tC', clock=offset + 3), - QTEV('started', tB, 'w2', name='tB', clock=offset + 5), - QTEV('retried', tA, 'w1', name='tA', clock=offset + 7), - QTEV('succeeded', tB, 'w2', name='tB', clock=offset + 9), - QTEV('started', tC, 'w2', name='tC', clock=offset + 10), - QTEV('received', tA, 'w3', name='tA', clock=offset + 13), - QTEV('succeded', tC, 'w2', name='tC', clock=offset + 12), - QTEV('started', tA, 'w3', name='tA', clock=offset + 14), - QTEV('succeeded', tA, 'w3', name='TA', clock=offset + 16), - ] - - def rewind_with_offset(self, offset, uids=None): - self.offset = offset - self.uids = self.setuids(uids or self.uids) - self.setup() - self.rewind() - - -class ev_snapshot(replay): - - def setup(self): - self.events = [ - Event('worker-online', hostname='utest1'), - Event('worker-online', hostname='utest2'), - Event('worker-online', hostname='utest3'), - ] - for i in range(20): - worker = not i % 2 and 'utest2' or 'utest1' - type = not i % 2 and 'task2' or 'task1' - self.events.append(Event('task-received', name=type, - uuid=uuid(), hostname=worker)) - - -class test_Worker(AppCase): - - def test_equality(self): - self.assertEqual(Worker(hostname='foo').hostname, 'foo') - self.assertEqual( - Worker(hostname='foo'), Worker(hostname='foo'), - ) - self.assertNotEqual( - Worker(hostname='foo'), Worker(hostname='bar'), - ) - self.assertEqual( - hash(Worker(hostname='foo')), hash(Worker(hostname='foo')), - ) - self.assertNotEqual( - hash(Worker(hostname='foo')), hash(Worker(hostname='bar')), - ) - - def test_compatible_with_Decimal(self): - w = Worker('george@vandelay.com') - timestamp, local_received = Decimal(_float_to_decimal(time())), time() - w.event('worker-online', timestamp, local_received, fields={ - 'hostname': 'george@vandelay.com', - 'timestamp': timestamp, - 'local_received': local_received, - 'freq': Decimal(_float_to_decimal(5.6335431)), - }) - self.assertTrue(w.alive) - - def test_survives_missing_timestamp(self): - worker = Worker(hostname='foo') - worker.event('heartbeat') - self.assertEqual(worker.heartbeats, []) - - def test_repr(self): - self.assertTrue(repr(Worker(hostname='foo'))) - - def test_drift_warning(self): - worker = Worker(hostname='foo') - with patch('celery.events.state.warn') as warn: - worker.event(None, time() + (HEARTBEAT_DRIFT_MAX * 2), time()) - self.assertTrue(warn.called) - self.assertIn('Substantial drift', warn.call_args[0][0]) - - def test_updates_heartbeat(self): - worker = Worker(hostname='foo') - worker.event(None, time(), time()) - self.assertEqual(len(worker.heartbeats), 1) - h1 = worker.heartbeats[0] - worker.event(None, time(), time() - 10) - self.assertEqual(len(worker.heartbeats), 2) - self.assertEqual(worker.heartbeats[-1], h1) - - -class test_Task(AppCase): - - def test_equality(self): - self.assertEqual(Task(uuid='foo').uuid, 'foo') - self.assertEqual( - Task(uuid='foo'), Task(uuid='foo'), - ) - self.assertNotEqual( - Task(uuid='foo'), Task(uuid='bar'), - ) - self.assertEqual( - hash(Task(uuid='foo')), hash(Task(uuid='foo')), - ) - self.assertNotEqual( - hash(Task(uuid='foo')), hash(Task(uuid='bar')), - ) - - def test_info(self): - task = Task(uuid='abcdefg', - name='tasks.add', - args='(2, 2)', - kwargs='{}', - retries=2, - result=42, - eta=1, - runtime=0.0001, - expires=1, - foo=None, - exception=1, - received=time() - 10, - started=time() - 8, - exchange='celery', - routing_key='celery', - succeeded=time()) - self.assertEqual(sorted(list(task._info_fields)), - sorted(task.info().keys())) - - self.assertEqual(sorted(list(task._info_fields + ('received', ))), - sorted(task.info(extra=('received', )))) - - self.assertEqual(sorted(['args', 'kwargs']), - sorted(task.info(['args', 'kwargs']).keys())) - self.assertFalse(list(task.info('foo'))) - - def test_ready(self): - task = Task(uuid='abcdefg', - name='tasks.add') - task.event('received', time(), time()) - self.assertFalse(task.ready) - task.event('succeeded', time(), time()) - self.assertTrue(task.ready) - - def test_sent(self): - task = Task(uuid='abcdefg', - name='tasks.add') - task.event('sent', time(), time()) - self.assertEqual(task.state, states.PENDING) - - def test_merge(self): - task = Task() - task.event('failed', time(), time()) - task.event('started', time(), time()) - task.event('received', time(), time(), { - 'name': 'tasks.add', 'args': (2, 2), - }) - self.assertEqual(task.state, states.FAILURE) - self.assertEqual(task.name, 'tasks.add') - self.assertTupleEqual(task.args, (2, 2)) - task.event('retried', time(), time()) - self.assertEqual(task.state, states.RETRY) - - def test_repr(self): - self.assertTrue(repr(Task(uuid='xxx', name='tasks.add'))) - - -class test_State(AppCase): - - def test_repr(self): - self.assertTrue(repr(State())) - - def test_pickleable(self): - self.assertTrue(pickle.loads(pickle.dumps(State()))) - - def test_task_logical_clock_ordering(self): - state = State() - r = ev_logical_clock_ordering(state) - tA, tB, tC = r.uids - r.play() - now = list(state.tasks_by_time()) - self.assertEqual(now[0][0], tA) - self.assertEqual(now[1][0], tC) - self.assertEqual(now[2][0], tB) - for _ in range(1000): - shuffle(r.uids) - tA, tB, tC = r.uids - r.rewind_with_offset(r.current_clock + 1, r.uids) - r.play() - now = list(state.tasks_by_time()) - self.assertEqual(now[0][0], tA) - self.assertEqual(now[1][0], tC) - self.assertEqual(now[2][0], tB) - - def test_worker_online_offline(self): - r = ev_worker_online_offline(State()) - next(r) - self.assertTrue(r.state.alive_workers()) - self.assertTrue(r.state.workers['utest1'].alive) - r.play() - self.assertFalse(r.state.alive_workers()) - self.assertFalse(r.state.workers['utest1'].alive) - - def test_itertasks(self): - s = State() - s.tasks = {'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd'} - self.assertEqual(len(list(s.itertasks(limit=2))), 2) - - def test_worker_heartbeat_expire(self): - r = ev_worker_heartbeats(State()) - next(r) - self.assertFalse(r.state.alive_workers()) - self.assertFalse(r.state.workers['utest1'].alive) - r.play() - self.assertTrue(r.state.alive_workers()) - self.assertTrue(r.state.workers['utest1'].alive) - - def test_task_states(self): - r = ev_task_states(State()) - - # RECEIVED - next(r) - self.assertTrue(r.tid in r.state.tasks) - task = r.state.tasks[r.tid] - self.assertEqual(task.state, states.RECEIVED) - self.assertTrue(task.received) - self.assertEqual(task.timestamp, task.received) - self.assertEqual(task.worker.hostname, 'utest1') - - # STARTED - next(r) - self.assertTrue(r.state.workers['utest1'].alive, - 'any task event adds worker heartbeat') - self.assertEqual(task.state, states.STARTED) - self.assertTrue(task.started) - self.assertEqual(task.timestamp, task.started) - self.assertEqual(task.worker.hostname, 'utest1') - - # REVOKED - next(r) - self.assertEqual(task.state, states.REVOKED) - self.assertTrue(task.revoked) - self.assertEqual(task.timestamp, task.revoked) - self.assertEqual(task.worker.hostname, 'utest1') - - # RETRY - next(r) - self.assertEqual(task.state, states.RETRY) - self.assertTrue(task.retried) - self.assertEqual(task.timestamp, task.retried) - self.assertEqual(task.worker.hostname, 'utest1') - self.assertEqual(task.exception, "KeyError('bar')") - self.assertEqual(task.traceback, 'line 2 at main') - - # FAILURE - next(r) - self.assertEqual(task.state, states.FAILURE) - self.assertTrue(task.failed) - self.assertEqual(task.timestamp, task.failed) - self.assertEqual(task.worker.hostname, 'utest1') - self.assertEqual(task.exception, "KeyError('foo')") - self.assertEqual(task.traceback, 'line 1 at main') - - # SUCCESS - next(r) - self.assertEqual(task.state, states.SUCCESS) - self.assertTrue(task.succeeded) - self.assertEqual(task.timestamp, task.succeeded) - self.assertEqual(task.worker.hostname, 'utest1') - self.assertEqual(task.result, '4') - self.assertEqual(task.runtime, 0.1234) - - def assertStateEmpty(self, state): - self.assertFalse(state.tasks) - self.assertFalse(state.workers) - self.assertFalse(state.event_count) - self.assertFalse(state.task_count) - - def assertState(self, state): - self.assertTrue(state.tasks) - self.assertTrue(state.workers) - self.assertTrue(state.event_count) - self.assertTrue(state.task_count) - - def test_freeze_while(self): - s = State() - r = ev_snapshot(s) - r.play() - - def work(): - pass - - s.freeze_while(work, clear_after=True) - self.assertFalse(s.event_count) - - s2 = State() - r = ev_snapshot(s2) - r.play() - s2.freeze_while(work, clear_after=False) - self.assertTrue(s2.event_count) - - def test_clear_tasks(self): - s = State() - r = ev_snapshot(s) - r.play() - self.assertTrue(s.tasks) - s.clear_tasks(ready=False) - self.assertFalse(s.tasks) - - def test_clear(self): - r = ev_snapshot(State()) - r.play() - self.assertTrue(r.state.event_count) - self.assertTrue(r.state.workers) - self.assertTrue(r.state.tasks) - self.assertTrue(r.state.task_count) - - r.state.clear() - self.assertFalse(r.state.event_count) - self.assertFalse(r.state.workers) - self.assertTrue(r.state.tasks) - self.assertFalse(r.state.task_count) - - r.state.clear(False) - self.assertFalse(r.state.tasks) - - def test_task_types(self): - r = ev_snapshot(State()) - r.play() - self.assertEqual(sorted(r.state.task_types()), ['task1', 'task2']) - - def test_tasks_by_timestamp(self): - r = ev_snapshot(State()) - r.play() - self.assertEqual(len(list(r.state.tasks_by_timestamp())), 20) - - def test_tasks_by_type(self): - r = ev_snapshot(State()) - r.play() - self.assertEqual(len(list(r.state.tasks_by_type('task1'))), 10) - self.assertEqual(len(list(r.state.tasks_by_type('task2'))), 10) - - def test_alive_workers(self): - r = ev_snapshot(State()) - r.play() - self.assertEqual(len(r.state.alive_workers()), 3) - - def test_tasks_by_worker(self): - r = ev_snapshot(State()) - r.play() - self.assertEqual(len(list(r.state.tasks_by_worker('utest1'))), 10) - self.assertEqual(len(list(r.state.tasks_by_worker('utest2'))), 10) - - def test_survives_unknown_worker_event(self): - s = State() - s.event({ - 'type': 'worker-unknown-event-xxx', - 'foo': 'bar', - }) - s.event({ - 'type': 'worker-unknown-event-xxx', - 'hostname': 'xxx', - 'foo': 'bar', - }) - - def test_survives_unknown_worker_leaving(self): - s = State(on_node_leave=Mock(name='on_node_leave')) - (worker, created), subject = s.event({ - 'type': 'worker-offline', - 'hostname': 'unknown@vandelay.com', - 'timestamp': time(), - 'local_received': time(), - 'clock': 301030134894833, - }) - self.assertEqual(worker, Worker('unknown@vandelay.com')) - self.assertFalse(created) - self.assertEqual(subject, 'offline') - self.assertNotIn('unknown@vandelay.com', s.workers) - s.on_node_leave.assert_called_with(worker) - - def test_on_node_join_callback(self): - s = State(on_node_join=Mock(name='on_node_join')) - (worker, created), subject = s.event({ - 'type': 'worker-online', - 'hostname': 'george@vandelay.com', - 'timestamp': time(), - 'local_received': time(), - 'clock': 34314, - }) - self.assertTrue(worker) - self.assertTrue(created) - self.assertEqual(subject, 'online') - self.assertIn('george@vandelay.com', s.workers) - s.on_node_join.assert_called_with(worker) - - def test_survives_unknown_task_event(self): - s = State() - s.event( - { - 'type': 'task-unknown-event-xxx', - 'foo': 'bar', - 'uuid': 'x', - 'hostname': 'y', - 'timestamp': time(), - 'local_received': time(), - 'clock': 0, - }, - ) - - def test_limits_maxtasks(self): - s = State(max_tasks_in_memory=1) - s.heap_multiplier = 2 - s.event({ - 'type': 'task-unknown-event-xxx', - 'foo': 'bar', - 'uuid': 'x', - 'hostname': 'y', - 'clock': 3, - 'timestamp': time(), - 'local_received': time(), - }) - s.event({ - 'type': 'task-unknown-event-xxx', - 'foo': 'bar', - 'uuid': 'y', - 'hostname': 'y', - 'clock': 4, - 'timestamp': time(), - 'local_received': time(), - }) - s.event({ - 'type': 'task-unknown-event-xxx', - 'foo': 'bar', - 'uuid': 'z', - 'hostname': 'y', - 'clock': 5, - 'timestamp': time(), - 'local_received': time(), - }) - self.assertEqual(len(s._taskheap), 2) - self.assertEqual(s._taskheap[0].clock, 4) - self.assertEqual(s._taskheap[1].clock, 5) - - s._taskheap.append(s._taskheap[0]) - self.assertTrue(list(s.tasks_by_time())) - - def test_callback(self): - scratch = {} - - def callback(state, event): - scratch['recv'] = True - - s = State(callback=callback) - s.event({'type': 'worker-online'}) - self.assertTrue(scratch.get('recv')) diff --git a/awx/lib/site-packages/celery/tests/fixups/__init__.py b/awx/lib/site-packages/celery/tests/fixups/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/fixups/test_django.py b/awx/lib/site-packages/celery/tests/fixups/test_django.py deleted file mode 100644 index 1d4ec5ceaa..0000000000 --- a/awx/lib/site-packages/celery/tests/fixups/test_django.py +++ /dev/null @@ -1,300 +0,0 @@ -from __future__ import absolute_import - -import os - -from contextlib import contextmanager - -from celery.fixups.django import ( - _maybe_close_fd, - fixup, - DjangoFixup, - DjangoWorkerFixup, -) - -from celery.tests.case import ( - AppCase, Mock, patch, patch_many, patch_modules, mask_modules, -) - - -class FixupCase(AppCase): - Fixup = None - - @contextmanager - def fixup_context(self, app): - with patch('celery.fixups.django.DjangoWorkerFixup.validate_models'): - with patch('celery.fixups.django.symbol_by_name') as symbyname: - with patch('celery.fixups.django.import_module') as impmod: - f = self.Fixup(app) - yield f, impmod, symbyname - - -class test_DjangoFixup(FixupCase): - Fixup = DjangoFixup - - def test_fixup(self): - with patch('celery.fixups.django.DjangoFixup') as Fixup: - with patch.dict(os.environ, DJANGO_SETTINGS_MODULE=''): - fixup(self.app) - self.assertFalse(Fixup.called) - with patch.dict(os.environ, DJANGO_SETTINGS_MODULE='settings'): - with mask_modules('django'): - with self.assertWarnsRegex(UserWarning, 'but Django is'): - fixup(self.app) - self.assertFalse(Fixup.called) - with patch_modules('django'): - fixup(self.app) - self.assertTrue(Fixup.called) - - def test_maybe_close_fd(self): - with patch('os.close'): - _maybe_close_fd(Mock()) - _maybe_close_fd(object()) - - def test_init(self): - with self.fixup_context(self.app) as (f, importmod, sym): - self.assertTrue(f) - - def se(name): - if name == 'django.utils.timezone:now': - raise ImportError() - return Mock() - sym.side_effect = se - self.assertTrue(self.Fixup(self.app)._now) - - def test_install(self): - self.app.loader = Mock() - with self.fixup_context(self.app) as (f, _, _): - with patch_many('os.getcwd', 'sys.path', - 'celery.fixups.django.signals') as (cw, p, sigs): - cw.return_value = '/opt/vandelay' - f.install() - sigs.worker_init.connect.assert_called_with(f.on_worker_init) - self.assertEqual(self.app.loader.now, f.now) - self.assertEqual(self.app.loader.mail_admins, f.mail_admins) - p.append.assert_called_with('/opt/vandelay') - - def test_now(self): - with self.fixup_context(self.app) as (f, _, _): - self.assertTrue(f.now(utc=True)) - self.assertFalse(f._now.called) - self.assertTrue(f.now(utc=False)) - self.assertTrue(f._now.called) - - def test_mail_admins(self): - with self.fixup_context(self.app) as (f, _, _): - f.mail_admins('sub', 'body', True) - f._mail_admins.assert_called_with( - 'sub', 'body', fail_silently=True, - ) - - def test_on_worker_init(self): - with self.fixup_context(self.app) as (f, _, _): - with patch('celery.fixups.django.DjangoWorkerFixup') as DWF: - f.on_worker_init() - DWF.assert_called_with(f.app) - DWF.return_value.install.assert_called_with() - self.assertIs( - f._worker_fixup, DWF.return_value.install.return_value, - ) - - -class test_DjangoWorkerFixup(FixupCase): - Fixup = DjangoWorkerFixup - - def test_init(self): - with self.fixup_context(self.app) as (f, importmod, sym): - self.assertTrue(f) - - def se(name): - if name == 'django.db:close_old_connections': - raise ImportError() - return Mock() - sym.side_effect = se - self.assertIsNone(self.Fixup(self.app)._close_old_connections) - - def test_install(self): - self.app.conf = {'CELERY_DB_REUSE_MAX': None} - self.app.loader = Mock() - with self.fixup_context(self.app) as (f, _, _): - with patch_many('celery.fixups.django.signals') as (sigs, ): - f.install() - sigs.beat_embedded_init.connect.assert_called_with( - f.close_database, - ) - sigs.worker_ready.connect.assert_called_with(f.on_worker_ready) - sigs.task_prerun.connect.assert_called_with(f.on_task_prerun) - sigs.task_postrun.connect.assert_called_with(f.on_task_postrun) - sigs.worker_process_init.connect.assert_called_with( - f.on_worker_process_init, - ) - - def test_on_worker_process_init(self): - with self.fixup_context(self.app) as (f, _, _): - with patch('celery.fixups.django._maybe_close_fd') as mcf: - _all = f._db.connections.all = Mock() - conns = _all.return_value = [ - Mock(), Mock(), - ] - conns[0].connection = None - with patch.object(f, 'close_cache'): - with patch.object(f, '_close_database'): - f.on_worker_process_init() - mcf.assert_called_with(conns[1].connection) - f.close_cache.assert_called_with() - f._close_database.assert_called_with() - - mcf.reset_mock() - _all.side_effect = AttributeError() - f.on_worker_process_init() - mcf.assert_called_with(f._db.connection.connection) - f._db.connection = None - f.on_worker_process_init() - - def test_on_task_prerun(self): - task = Mock() - with self.fixup_context(self.app) as (f, _, _): - task.request.is_eager = False - with patch.object(f, 'close_database'): - f.on_task_prerun(task) - f.close_database.assert_called_with() - - task.request.is_eager = True - with patch.object(f, 'close_database'): - f.on_task_prerun(task) - self.assertFalse(f.close_database.called) - - def test_on_task_postrun(self): - task = Mock() - with self.fixup_context(self.app) as (f, _, _): - with patch.object(f, 'close_cache'): - task.request.is_eager = False - with patch.object(f, 'close_database'): - f.on_task_postrun(task) - self.assertTrue(f.close_database.called) - self.assertTrue(f.close_cache.called) - - # when a task is eager, do not close connections - with patch.object(f, 'close_cache'): - task.request.is_eager = True - with patch.object(f, 'close_database'): - f.on_task_postrun(task) - self.assertFalse(f.close_database.called) - self.assertFalse(f.close_cache.called) - - def test_close_database(self): - with self.fixup_context(self.app) as (f, _, _): - f._close_old_connections = Mock() - f.close_database() - f._close_old_connections.assert_called_with() - f._close_old_connections = None - with patch.object(f, '_close_database') as _close: - f.db_reuse_max = None - f.close_database() - _close.assert_called_with() - _close.reset_mock() - - f.db_reuse_max = 10 - f._db_recycles = 3 - f.close_database() - self.assertFalse(_close.called) - self.assertEqual(f._db_recycles, 4) - _close.reset_mock() - - f._db_recycles = 20 - f.close_database() - _close.assert_called_with() - self.assertEqual(f._db_recycles, 1) - - def test__close_database(self): - with self.fixup_context(self.app) as (f, _, _): - conns = f._db.connections = [Mock(), Mock(), Mock()] - conns[1].close.side_effect = KeyError('already closed') - f.database_errors = (KeyError, ) - - f._close_database() - conns[0].close.assert_called_with() - conns[1].close.assert_called_with() - conns[2].close.assert_called_with() - - conns[1].close.side_effect = KeyError('omg') - with self.assertRaises(KeyError): - f._close_database() - - class Object(object): - pass - o = Object() - o.close_connection = Mock() - f._db = o - f._close_database() - o.close_connection.assert_called_with() - - def test_close_cache(self): - with self.fixup_context(self.app) as (f, _, _): - f.close_cache() - f._cache.cache.close.assert_called_with() - f._cache.cache.close.side_effect = TypeError() - f.close_cache() - - def test_on_worker_ready(self): - with self.fixup_context(self.app) as (f, _, _): - f._settings.DEBUG = False - f.on_worker_ready() - with self.assertWarnsRegex(UserWarning, r'leads to a memory leak'): - f._settings.DEBUG = True - f.on_worker_ready() - - def test_mysql_errors(self): - with patch_modules('MySQLdb'): - import MySQLdb as mod - mod.DatabaseError = Mock() - mod.InterfaceError = Mock() - mod.OperationalError = Mock() - with self.fixup_context(self.app) as (f, _, _): - self.assertIn(mod.DatabaseError, f.database_errors) - self.assertIn(mod.InterfaceError, f.database_errors) - self.assertIn(mod.OperationalError, f.database_errors) - with mask_modules('MySQLdb'): - with self.fixup_context(self.app): - pass - - def test_pg_errors(self): - with patch_modules('psycopg2'): - import psycopg2 as mod - mod.DatabaseError = Mock() - mod.InterfaceError = Mock() - mod.OperationalError = Mock() - with self.fixup_context(self.app) as (f, _, _): - self.assertIn(mod.DatabaseError, f.database_errors) - self.assertIn(mod.InterfaceError, f.database_errors) - self.assertIn(mod.OperationalError, f.database_errors) - with mask_modules('psycopg2'): - with self.fixup_context(self.app): - pass - - def test_sqlite_errors(self): - with patch_modules('sqlite3'): - import sqlite3 as mod - mod.DatabaseError = Mock() - mod.InterfaceError = Mock() - mod.OperationalError = Mock() - with self.fixup_context(self.app) as (f, _, _): - self.assertIn(mod.DatabaseError, f.database_errors) - self.assertIn(mod.InterfaceError, f.database_errors) - self.assertIn(mod.OperationalError, f.database_errors) - with mask_modules('sqlite3'): - with self.fixup_context(self.app): - pass - - def test_oracle_errors(self): - with patch_modules('cx_Oracle'): - import cx_Oracle as mod - mod.DatabaseError = Mock() - mod.InterfaceError = Mock() - mod.OperationalError = Mock() - with self.fixup_context(self.app) as (f, _, _): - self.assertIn(mod.DatabaseError, f.database_errors) - self.assertIn(mod.InterfaceError, f.database_errors) - self.assertIn(mod.OperationalError, f.database_errors) - with mask_modules('cx_Oracle'): - with self.fixup_context(self.app): - pass diff --git a/awx/lib/site-packages/celery/tests/functional/__init__.py b/awx/lib/site-packages/celery/tests/functional/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/functional/case.py b/awx/lib/site-packages/celery/tests/functional/case.py deleted file mode 100644 index 298c684666..0000000000 --- a/awx/lib/site-packages/celery/tests/functional/case.py +++ /dev/null @@ -1,178 +0,0 @@ -from __future__ import absolute_import - -import atexit -import logging -import os -import signal -import socket -import sys -import traceback - -from itertools import count -from time import time - -from celery import current_app -from celery.exceptions import TimeoutError -from celery.app.control import flatten_reply -from celery.utils.imports import qualname - -from celery.tests.case import Case - -HOSTNAME = socket.gethostname() - - -def say(msg): - sys.stderr.write('%s\n' % msg) - - -def try_while(fun, reason='Timed out', timeout=10, interval=0.5): - time_start = time() - for iterations in count(0): - if time() - time_start >= timeout: - raise TimeoutError() - ret = fun() - if ret: - return ret - - -class Worker(object): - started = False - worker_ids = count(1) - _shutdown_called = False - - def __init__(self, hostname, loglevel='error', app=None): - self.hostname = hostname - self.loglevel = loglevel - self.app = app or current_app._get_current_object() - - def start(self): - if not self.started: - self._fork_and_exec() - self.started = True - - def _fork_and_exec(self): - pid = os.fork() - if pid == 0: - self.app.worker_main(['worker', '--loglevel=INFO', - '-n', self.hostname, - '-P', 'solo']) - os._exit(0) - self.pid = pid - - def ping(self, *args, **kwargs): - return self.app.control.ping(*args, **kwargs) - - def is_alive(self, timeout=1): - r = self.ping(destination=[self.hostname], timeout=timeout) - return self.hostname in flatten_reply(r) - - def wait_until_started(self, timeout=10, interval=0.5): - try_while( - lambda: self.is_alive(interval), - "Worker won't start (after %s secs.)" % timeout, - interval=interval, timeout=timeout, - ) - say('--WORKER %s IS ONLINE--' % self.hostname) - - def ensure_shutdown(self, timeout=10, interval=0.5): - os.kill(self.pid, signal.SIGTERM) - try_while( - lambda: not self.is_alive(interval), - "Worker won't shutdown (after %s secs.)" % timeout, - timeout=10, interval=0.5, - ) - say('--WORKER %s IS SHUTDOWN--' % self.hostname) - self._shutdown_called = True - - def ensure_started(self): - self.start() - self.wait_until_started() - - @classmethod - def managed(cls, hostname=None, caller=None): - hostname = hostname or socket.gethostname() - if caller: - hostname = '.'.join([qualname(caller), hostname]) - else: - hostname += str(next(cls.worker_ids())) - worker = cls(hostname) - worker.ensure_started() - stack = traceback.format_stack() - - @atexit.register - def _ensure_shutdown_once(): - if not worker._shutdown_called: - say('-- Found worker not stopped at shutdown: %s\n%s' % ( - worker.hostname, - '\n'.join(stack))) - worker.ensure_shutdown() - - return worker - - -class WorkerCase(Case): - hostname = HOSTNAME - worker = None - - @classmethod - def setUpClass(cls): - logging.getLogger('amqp').setLevel(logging.ERROR) - cls.worker = Worker.managed(cls.hostname, caller=cls) - - @classmethod - def tearDownClass(cls): - cls.worker.ensure_shutdown() - - def assertWorkerAlive(self, timeout=1): - self.assertTrue(self.worker.is_alive) - - def inspect(self, timeout=1): - return self.app.control.inspect([self.worker.hostname], - timeout=timeout) - - def my_response(self, response): - return flatten_reply(response)[self.worker.hostname] - - def is_accepted(self, task_id, interval=0.5): - active = self.inspect(timeout=interval).active() - if active: - for task in active[self.worker.hostname]: - if task['id'] == task_id: - return True - return False - - def is_reserved(self, task_id, interval=0.5): - reserved = self.inspect(timeout=interval).reserved() - if reserved: - for task in reserved[self.worker.hostname]: - if task['id'] == task_id: - return True - return False - - def is_scheduled(self, task_id, interval=0.5): - schedule = self.inspect(timeout=interval).scheduled() - if schedule: - for item in schedule[self.worker.hostname]: - if item['request']['id'] == task_id: - return True - return False - - def is_received(self, task_id, interval=0.5): - return (self.is_reserved(task_id, interval) or - self.is_scheduled(task_id, interval) or - self.is_accepted(task_id, interval)) - - def ensure_accepted(self, task_id, interval=0.5, timeout=10): - return try_while(lambda: self.is_accepted(task_id, interval), - 'Task not accepted within timeout', - interval=0.5, timeout=10) - - def ensure_received(self, task_id, interval=0.5, timeout=10): - return try_while(lambda: self.is_received(task_id, interval), - 'Task not receied within timeout', - interval=0.5, timeout=10) - - def ensure_scheduled(self, task_id, interval=0.5, timeout=10): - return try_while(lambda: self.is_scheduled(task_id, interval), - 'Task not scheduled within timeout', - interval=0.5, timeout=10) diff --git a/awx/lib/site-packages/celery/tests/functional/tasks.py b/awx/lib/site-packages/celery/tests/functional/tasks.py deleted file mode 100644 index 85479b47be..0000000000 --- a/awx/lib/site-packages/celery/tests/functional/tasks.py +++ /dev/null @@ -1,24 +0,0 @@ -from __future__ import absolute_import - -import time - -from celery import task, signature - - -@task() -def add(x, y): - return x + y - - -@task() -def add_cb(x, y, callback=None): - result = x + y - if callback: - return signature(callback).apply_async(result) - return result - - -@task() -def sleeptask(i): - time.sleep(i) - return i diff --git a/awx/lib/site-packages/celery/tests/security/__init__.py b/awx/lib/site-packages/celery/tests/security/__init__.py deleted file mode 100644 index 50b7f4ca54..0000000000 --- a/awx/lib/site-packages/celery/tests/security/__init__.py +++ /dev/null @@ -1,68 +0,0 @@ -from __future__ import absolute_import -""" -Keys and certificates for tests (KEY1 is a private key of CERT1, etc.) - -Generated with `extra/security/get-cert.sh` - -""" -KEY1 = """-----BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQC9Twh0V5q/R1Q8N+Y+CNM4lj9AXeZL0gYowoK1ht2ZLCDU9vN5 -dhV0x3sqaXLjQNeCGd6b2vTbFGdF2E45//IWz6/BdPFWaPm0rtYbcxZHqXDZScRp -vFDLHhMysdqQWHxXVxpqIXXo4B7bnfnGvXhYwYITeEyQylV/rnH53mdV8wIDAQAB -AoGBAKUJN4elr+S9nHP7D6BZNTsJ0Q6eTd0ftfrmx+jVMG8Oh3jh6ZSkG0R5e6iX -0W7I4pgrUWRyWDB98yJy1o+90CAN/D80o8SbmW/zfA2WLBteOujMfCEjNrc/Nodf -6MZ0QQ6PnPH6pp94i3kNmFD8Mlzm+ODrUjPF0dCNf474qeKhAkEA7SXj5cQPyQXM -s15oGX5eb6VOk96eAPtEC72cLSh6o+VYmXyGroV1A2JPm6IzH87mTqjWXG229hjt -XVvDbdY2uQJBAMxblWFaWJhhU6Y1euazaBl/OyLYlqNz4LZ0RzCulEoV/gMGYU32 -PbilD5fpFsyhp5oCxnWNEsUFovYMKjKM3AsCQQCIlOcBoP76ZxWzRK8t56MaKBnu -fiuAIzbYkDbPp12i4Wc61wZ2ozR2Y3u4Bh3tturb6M+04hea+1ZSC5StwM85AkAp -UPLYpe13kWXaGsHoVqlbTk/kcamzDkCGYufpvcIZYGzkq6uMmZZM+II4klWbtasv -BhSdu5Hp54PU/wyg/72VAkBy1/oM3/QJ35Vb6TByHBLFR4nOuORoRclmxcoCPva9 -xqkQQn+UgBtOemRXpFCuKaoXonA3nLeB54SWcC6YUOcR ------END RSA PRIVATE KEY-----""" - -KEY2 = """-----BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQDH22L8b9AmST9ABDmQTQ2DWMdDmK5YXZt4AIY81IcsTQ/ccM0C -fwXEP9tdkYwtcxMCWdASwY5pfMy9vFp0hyrRQMSNfuoxAgONuNWPyQoIvY3ZXRe6 -rS+hb/LN4+vdjX+oxmYiQ2HmSB9rh2bepE6Cw+RLJr5sXXq+xZJ+BLt5tQIDAQAB -AoGBAMGBO0Arip/nP6Rd8tYypKjN5nEefX/1cjgoWdC//fj4zCil1vlZv12abm0U -JWNEDd2y0/G1Eow0V5BFtFcrIFowU44LZEiSf7sKXlNHRHlbZmDgNXFZOt7nVbHn -6SN+oCYjaPjji8idYeb3VQXPtqMoMn73MuyxD3k3tWmVLonpAkEA6hsu62qhUk5k -Nt88UZOauU1YizxsWvT0bHioaceE4TEsbO3NZs7dmdJIcRFcU787lANaaIq7Rw26 -qcumME9XhwJBANqMOzsYQ6BX54UzS6x99Jjlq9MEbTCbAEZr/yjopb9f617SwfuE -AEKnIq3HL6/Tnhv3V8Zy3wYHgDoGNeTVe+MCQQDi/nyeNAQ8RFqTgh2Ak/jAmCi0 -yV/fSgj+bHgQKS/FEuMas/IoL4lbrzQivkyhv5lLSX0ORQaWPM+z+A0qZqRdAkBh -XE+Wx/x4ljCh+nQf6AzrgIXHgBVUrfi1Zq9Jfjs4wnaMy793WRr0lpiwaigoYFHz -i4Ei+1G30eeh8dpYk3KZAkB0ucTOsQynDlL5rLGYZ+IcfSfH3w2l5EszY47kKQG9 -Fxeq/HOp9JYw4gRu6Ycvqu57KHwpHhR0FCXRBxuYcJ5V ------END RSA PRIVATE KEY-----""" - -CERT1 = """-----BEGIN CERTIFICATE----- -MIICVzCCAcACCQC72PP7b7H9BTANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQGEwJV -UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZDZWxlcnkxDzAN -BgNVBAMTBkNFbGVyeTElMCMGCSqGSIb3DQEJARYWY2VydEBjZWxlcnlwcm9qZWN0 -Lm9yZzAeFw0xMzA3MjQxMjExMTRaFw0xNDA3MjQxMjExMTRaMHAxCzAJBgNVBAYT -AlVTMQswCQYDVQQIEwJDQTELMAkGA1UEBxMCU0YxDzANBgNVBAoTBkNlbGVyeTEP -MA0GA1UEAxMGQ0VsZXJ5MSUwIwYJKoZIhvcNAQkBFhZjZXJ0QGNlbGVyeXByb2pl -Y3Qub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9Twh0V5q/R1Q8N+Y+ -CNM4lj9AXeZL0gYowoK1ht2ZLCDU9vN5dhV0x3sqaXLjQNeCGd6b2vTbFGdF2E45 -//IWz6/BdPFWaPm0rtYbcxZHqXDZScRpvFDLHhMysdqQWHxXVxpqIXXo4B7bnfnG -vXhYwYITeEyQylV/rnH53mdV8wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAKA4tD3J -94tsnQxFxHP7Frt7IvGMH+3wMqOiXFgYxPJX2tyaPvOLJ/7ERE4MkrvZO7IRC0iA -yKBe0pucdrTgsJoDV8juahuyjXOjvU14+q7Wv7pj7zqddVavzK8STLX4/FMIDnbK -aMGJl7wyj6V2yy6ANSbmy0uQjHikI6DrZEoK ------END CERTIFICATE-----""" - -CERT2 = """-----BEGIN CERTIFICATE----- -MIICATCCAWoCCQCV/9A2ZBM37TANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTExMDcxOTA5MDkwMloXDTEyMDcxODA5MDkwMlowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx9ti -/G/QJkk/QAQ5kE0Ng1jHQ5iuWF2beACGPNSHLE0P3HDNAn8FxD/bXZGMLXMTAlnQ -EsGOaXzMvbxadIcq0UDEjX7qMQIDjbjVj8kKCL2N2V0Xuq0voW/yzePr3Y1/qMZm -IkNh5kgfa4dm3qROgsPkSya+bF16vsWSfgS7ebUCAwEAATANBgkqhkiG9w0BAQUF -AAOBgQBzaZ5vBkzksPhnWb2oobuy6Ne/LMEtdQ//qeVY4sKl2tOJUCSdWRen9fqP -e+zYdEdkFCd8rp568Eiwkq/553uy4rlE927/AEqs/+KGYmAtibk/9vmi+/+iZXyS -WWZybzzDZFncq1/N1C3Y/hrCBNDFO4TsnTLAhWtZ4c0vDAiacw== ------END CERTIFICATE-----""" diff --git a/awx/lib/site-packages/celery/tests/security/case.py b/awx/lib/site-packages/celery/tests/security/case.py deleted file mode 100644 index ba421a9d57..0000000000 --- a/awx/lib/site-packages/celery/tests/security/case.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import absolute_import - -from celery.tests.case import AppCase, SkipTest - -import sys - - -class SecurityCase(AppCase): - - def setup(self): - if sys.version_info[0] == 3: - raise SkipTest('PyOpenSSL does not work on Python 3') - try: - from OpenSSL import crypto # noqa - except ImportError: - raise SkipTest('OpenSSL.crypto not installed') diff --git a/awx/lib/site-packages/celery/tests/security/test_certificate.py b/awx/lib/site-packages/celery/tests/security/test_certificate.py deleted file mode 100644 index 4b07b5a98f..0000000000 --- a/awx/lib/site-packages/celery/tests/security/test_certificate.py +++ /dev/null @@ -1,77 +0,0 @@ -from __future__ import absolute_import - -from celery.exceptions import SecurityError -from celery.security.certificate import Certificate, CertStore, FSCertStore - -from . import CERT1, CERT2, KEY1 -from .case import SecurityCase - -from celery.tests.case import Mock, mock_open, patch - - -class test_Certificate(SecurityCase): - - def test_valid_certificate(self): - Certificate(CERT1) - Certificate(CERT2) - - def test_invalid_certificate(self): - self.assertRaises((SecurityError, TypeError), Certificate, None) - self.assertRaises(SecurityError, Certificate, '') - self.assertRaises(SecurityError, Certificate, 'foo') - self.assertRaises(SecurityError, Certificate, CERT1[:20] + CERT1[21:]) - self.assertRaises(SecurityError, Certificate, KEY1) - - def test_has_expired(self): - self.assertFalse(Certificate(CERT1).has_expired()) - - -class test_CertStore(SecurityCase): - - def test_itercerts(self): - cert1 = Certificate(CERT1) - cert2 = Certificate(CERT2) - certstore = CertStore() - for c in certstore.itercerts(): - self.assertTrue(False) - certstore.add_cert(cert1) - certstore.add_cert(cert2) - for c in certstore.itercerts(): - self.assertIn(c, (cert1, cert2)) - - def test_duplicate(self): - cert1 = Certificate(CERT1) - certstore = CertStore() - certstore.add_cert(cert1) - self.assertRaises(SecurityError, certstore.add_cert, cert1) - - -class test_FSCertStore(SecurityCase): - - @patch('os.path.isdir') - @patch('glob.glob') - @patch('celery.security.certificate.Certificate') - def test_init(self, Certificate, glob, isdir): - cert = Certificate.return_value = Mock() - cert.has_expired.return_value = False - isdir.return_value = True - glob.return_value = ['foo.cert'] - with mock_open(): - cert.get_id.return_value = 1 - x = FSCertStore('/var/certs') - self.assertIn(1, x._certs) - glob.assert_called_with('/var/certs/*') - - # they both end up with the same id - glob.return_value = ['foo.cert', 'bar.cert'] - with self.assertRaises(SecurityError): - x = FSCertStore('/var/certs') - glob.return_value = ['foo.cert'] - - cert.has_expired.return_value = True - with self.assertRaises(SecurityError): - x = FSCertStore('/var/certs') - - isdir.return_value = False - with self.assertRaises(SecurityError): - x = FSCertStore('/var/certs') diff --git a/awx/lib/site-packages/celery/tests/security/test_key.py b/awx/lib/site-packages/celery/tests/security/test_key.py deleted file mode 100644 index d8551b26b4..0000000000 --- a/awx/lib/site-packages/celery/tests/security/test_key.py +++ /dev/null @@ -1,26 +0,0 @@ -from __future__ import absolute_import - -from celery.exceptions import SecurityError -from celery.security.key import PrivateKey - -from . import CERT1, KEY1, KEY2 -from .case import SecurityCase - - -class test_PrivateKey(SecurityCase): - - def test_valid_private_key(self): - PrivateKey(KEY1) - PrivateKey(KEY2) - - def test_invalid_private_key(self): - self.assertRaises((SecurityError, TypeError), PrivateKey, None) - self.assertRaises(SecurityError, PrivateKey, '') - self.assertRaises(SecurityError, PrivateKey, 'foo') - self.assertRaises(SecurityError, PrivateKey, KEY1[:20] + KEY1[21:]) - self.assertRaises(SecurityError, PrivateKey, CERT1) - - def test_sign(self): - pkey = PrivateKey(KEY1) - pkey.sign('test', 'sha1') - self.assertRaises(ValueError, pkey.sign, 'test', 'unknown') diff --git a/awx/lib/site-packages/celery/tests/security/test_security.py b/awx/lib/site-packages/celery/tests/security/test_security.py deleted file mode 100644 index 227c65a5db..0000000000 --- a/awx/lib/site-packages/celery/tests/security/test_security.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -Keys and certificates for tests (KEY1 is a private key of CERT1, etc.) - -Generated with: - -.. code-block:: bash - - $ openssl genrsa -des3 -passout pass:test -out key1.key 1024 - $ openssl req -new -key key1.key -out key1.csr -passin pass:test - $ cp key1.key key1.key.org - $ openssl rsa -in key1.key.org -out key1.key -passin pass:test - $ openssl x509 -req -days 365 -in cert1.csr \ - -signkey key1.key -out cert1.crt - $ rm key1.key.org cert1.csr - -""" -from __future__ import absolute_import - -from kombu.serialization import disable_insecure_serializers - -from celery.exceptions import ImproperlyConfigured, SecurityError -from celery.five import builtins -from celery.security.utils import reraise_errors -from kombu.serialization import registry - -from .case import SecurityCase - -from celery.tests.case import Mock, mock_open, patch - - -class test_security(SecurityCase): - - def teardown(self): - registry._disabled_content_types.clear() - - def test_disable_insecure_serializers(self): - try: - disabled = registry._disabled_content_types - self.assertTrue(disabled) - - disable_insecure_serializers( - ['application/json', 'application/x-python-serialize'], - ) - self.assertIn('application/x-yaml', disabled) - self.assertNotIn('application/json', disabled) - self.assertNotIn('application/x-python-serialize', disabled) - disabled.clear() - - disable_insecure_serializers(allowed=None) - self.assertIn('application/x-yaml', disabled) - self.assertIn('application/json', disabled) - self.assertIn('application/x-python-serialize', disabled) - finally: - disable_insecure_serializers(allowed=['json']) - - def test_setup_security(self): - disabled = registry._disabled_content_types - self.assertEqual(0, len(disabled)) - - self.app.conf.CELERY_TASK_SERIALIZER = 'json' - self.app.setup_security() - self.assertIn('application/x-python-serialize', disabled) - disabled.clear() - - @patch('celery.security.register_auth') - @patch('celery.security._disable_insecure_serializers') - def test_setup_registry_complete(self, dis, reg, key='KEY', cert='CERT'): - calls = [0] - - def effect(*args): - try: - m = Mock() - m.read.return_value = 'B' if calls[0] else 'A' - return m - finally: - calls[0] += 1 - - self.app.conf.CELERY_TASK_SERIALIZER = 'auth' - with mock_open(side_effect=effect): - with patch('celery.security.registry') as registry: - store = Mock() - self.app.setup_security(['json'], key, cert, store) - dis.assert_called_with(['json']) - reg.assert_called_with('A', 'B', store, 'sha1', 'json') - registry._set_default_serializer.assert_called_with('auth') - - def test_security_conf(self): - self.app.conf.CELERY_TASK_SERIALIZER = 'auth' - with self.assertRaises(ImproperlyConfigured): - self.app.setup_security() - - _import = builtins.__import__ - - def import_hook(name, *args, **kwargs): - if name == 'OpenSSL': - raise ImportError - return _import(name, *args, **kwargs) - - builtins.__import__ = import_hook - with self.assertRaises(ImproperlyConfigured): - self.app.setup_security() - builtins.__import__ = _import - - def test_reraise_errors(self): - with self.assertRaises(SecurityError): - with reraise_errors(errors=(KeyError, )): - raise KeyError('foo') - with self.assertRaises(KeyError): - with reraise_errors(errors=(ValueError, )): - raise KeyError('bar') diff --git a/awx/lib/site-packages/celery/tests/security/test_serialization.py b/awx/lib/site-packages/celery/tests/security/test_serialization.py deleted file mode 100644 index 50bc4bfab4..0000000000 --- a/awx/lib/site-packages/celery/tests/security/test_serialization.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import absolute_import - -import os -import base64 - -from kombu.serialization import registry - -from celery.exceptions import SecurityError -from celery.security.serialization import SecureSerializer, register_auth -from celery.security.certificate import Certificate, CertStore -from celery.security.key import PrivateKey - -from . import CERT1, CERT2, KEY1, KEY2 -from .case import SecurityCase - - -class test_SecureSerializer(SecurityCase): - - def _get_s(self, key, cert, certs): - store = CertStore() - for c in certs: - store.add_cert(Certificate(c)) - return SecureSerializer(PrivateKey(key), Certificate(cert), store) - - def test_serialize(self): - s = self._get_s(KEY1, CERT1, [CERT1]) - self.assertEqual(s.deserialize(s.serialize('foo')), 'foo') - - def test_deserialize(self): - s = self._get_s(KEY1, CERT1, [CERT1]) - self.assertRaises(SecurityError, s.deserialize, 'bad data') - - def test_unmatched_key_cert(self): - s = self._get_s(KEY1, CERT2, [CERT1, CERT2]) - self.assertRaises(SecurityError, - s.deserialize, s.serialize('foo')) - - def test_unknown_source(self): - s1 = self._get_s(KEY1, CERT1, [CERT2]) - s2 = self._get_s(KEY1, CERT1, []) - self.assertRaises(SecurityError, - s1.deserialize, s1.serialize('foo')) - self.assertRaises(SecurityError, - s2.deserialize, s2.serialize('foo')) - - def test_self_send(self): - s1 = self._get_s(KEY1, CERT1, [CERT1]) - s2 = self._get_s(KEY1, CERT1, [CERT1]) - self.assertEqual(s2.deserialize(s1.serialize('foo')), 'foo') - - def test_separate_ends(self): - s1 = self._get_s(KEY1, CERT1, [CERT2]) - s2 = self._get_s(KEY2, CERT2, [CERT1]) - self.assertEqual(s2.deserialize(s1.serialize('foo')), 'foo') - - def test_register_auth(self): - register_auth(KEY1, CERT1, '') - self.assertIn('application/data', registry._decoders) - - def test_lots_of_sign(self): - for i in range(1000): - rdata = base64.urlsafe_b64encode(os.urandom(265)) - s = self._get_s(KEY1, CERT1, [CERT1]) - self.assertEqual(s.deserialize(s.serialize(rdata)), rdata) diff --git a/awx/lib/site-packages/celery/tests/slow/__init__.py b/awx/lib/site-packages/celery/tests/slow/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/tasks/__init__.py b/awx/lib/site-packages/celery/tests/tasks/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/tasks/test_canvas.py b/awx/lib/site-packages/celery/tests/tasks/test_canvas.py deleted file mode 100644 index 8ecbbbbc95..0000000000 --- a/awx/lib/site-packages/celery/tests/tasks/test_canvas.py +++ /dev/null @@ -1,335 +0,0 @@ -from __future__ import absolute_import - -from celery.canvas import ( - Signature, - chain, - group, - chord, - signature, - xmap, - xstarmap, - chunks, - _maybe_group, - maybe_signature, -) -from celery.result import EagerResult - -from celery.tests.case import AppCase, Mock - -SIG = Signature({'task': 'TASK', - 'args': ('A1', ), - 'kwargs': {'K1': 'V1'}, - 'options': {'task_id': 'TASK_ID'}, - 'subtask_type': ''}) - - -class CanvasCase(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - @self.app.task(shared=False) - def mul(x, y): - return x * y - self.mul = mul - - @self.app.task(shared=False) - def div(x, y): - return x / y - self.div = div - - -class test_Signature(CanvasCase): - - def test_getitem_property_class(self): - self.assertTrue(Signature.task) - self.assertTrue(Signature.args) - self.assertTrue(Signature.kwargs) - self.assertTrue(Signature.options) - self.assertTrue(Signature.subtask_type) - - def test_getitem_property(self): - self.assertEqual(SIG.task, 'TASK') - self.assertEqual(SIG.args, ('A1', )) - self.assertEqual(SIG.kwargs, {'K1': 'V1'}) - self.assertEqual(SIG.options, {'task_id': 'TASK_ID'}) - self.assertEqual(SIG.subtask_type, '') - - def test_replace(self): - x = Signature('TASK', ('A'), {}) - self.assertTupleEqual(x.replace(args=('B', )).args, ('B', )) - self.assertDictEqual( - x.replace(kwargs={'FOO': 'BAR'}).kwargs, - {'FOO': 'BAR'}, - ) - self.assertDictEqual( - x.replace(options={'task_id': '123'}).options, - {'task_id': '123'}, - ) - - def test_set(self): - self.assertDictEqual( - Signature('TASK', x=1).set(task_id='2').options, - {'x': 1, 'task_id': '2'}, - ) - - def test_link(self): - x = signature(SIG) - x.link(SIG) - x.link(SIG) - self.assertIn(SIG, x.options['link']) - self.assertEqual(len(x.options['link']), 1) - - def test_link_error(self): - x = signature(SIG) - x.link_error(SIG) - x.link_error(SIG) - self.assertIn(SIG, x.options['link_error']) - self.assertEqual(len(x.options['link_error']), 1) - - def test_flatten_links(self): - tasks = [self.add.s(2, 2), self.mul.s(4), self.div.s(2)] - tasks[0].link(tasks[1]) - tasks[1].link(tasks[2]) - self.assertEqual(tasks[0].flatten_links(), tasks) - - def test_OR(self): - x = self.add.s(2, 2) | self.mul.s(4) - self.assertIsInstance(x, chain) - y = self.add.s(4, 4) | self.div.s(2) - z = x | y - self.assertIsInstance(y, chain) - self.assertIsInstance(z, chain) - self.assertEqual(len(z.tasks), 4) - with self.assertRaises(TypeError): - x | 10 - ax = self.add.s(2, 2) | (self.add.s(4) | self.add.s(8)) - self.assertIsInstance(ax, chain) - self.assertEqual(len(ax.tasks), 3, 'consolidates chain to chain') - - def test_INVERT(self): - x = self.add.s(2, 2) - x.apply_async = Mock() - x.apply_async.return_value = Mock() - x.apply_async.return_value.get = Mock() - x.apply_async.return_value.get.return_value = 4 - self.assertEqual(~x, 4) - self.assertTrue(x.apply_async.called) - - def test_merge_immutable(self): - x = self.add.si(2, 2, foo=1) - args, kwargs, options = x._merge((4, ), {'bar': 2}, {'task_id': 3}) - self.assertTupleEqual(args, (2, 2)) - self.assertDictEqual(kwargs, {'foo': 1}) - self.assertDictEqual(options, {'task_id': 3}) - - def test_set_immutable(self): - x = self.add.s(2, 2) - self.assertFalse(x.immutable) - x.set(immutable=True) - self.assertTrue(x.immutable) - x.set(immutable=False) - self.assertFalse(x.immutable) - - def test_election(self): - x = self.add.s(2, 2) - x.freeze('foo') - x.type.app.control = Mock() - r = x.election() - self.assertTrue(x.type.app.control.election.called) - self.assertEqual(r.id, 'foo') - - def test_AsyncResult_when_not_registered(self): - s = signature('xxx.not.registered', app=self.app) - self.assertTrue(s.AsyncResult) - - def test_apply_async_when_not_registered(self): - s = signature('xxx.not.registered', app=self.app) - self.assertTrue(s._apply_async) - - -class test_xmap_xstarmap(CanvasCase): - - def test_apply(self): - for type, attr in [(xmap, 'map'), (xstarmap, 'starmap')]: - args = [(i, i) for i in range(10)] - s = getattr(self.add, attr)(args) - s.type = Mock() - - s.apply_async(foo=1) - s.type.apply_async.assert_called_with( - (), {'task': self.add.s(), 'it': args}, foo=1, - ) - - self.assertEqual(type.from_dict(dict(s)), s) - self.assertTrue(repr(s)) - - -class test_chunks(CanvasCase): - - def test_chunks(self): - x = self.add.chunks(range(100), 10) - self.assertEqual( - dict(chunks.from_dict(dict(x), app=self.app)), dict(x), - ) - - self.assertTrue(x.group()) - self.assertEqual(len(x.group().tasks), 10) - - x.group = Mock() - gr = x.group.return_value = Mock() - - x.apply_async() - gr.apply_async.assert_called_with((), {}) - - x() - gr.assert_called_with() - - self.app.conf.CELERY_ALWAYS_EAGER = True - chunks.apply_chunks(app=self.app, **x['kwargs']) - - -class test_chain(CanvasCase): - - def test_repr(self): - x = self.add.s(2, 2) | self.add.s(2) - self.assertEqual( - repr(x), '%s(2, 2) | %s(2)' % (self.add.name, self.add.name), - ) - - def test_reverse(self): - x = self.add.s(2, 2) | self.add.s(2) - self.assertIsInstance(signature(x), chain) - self.assertIsInstance(signature(dict(x)), chain) - - def test_always_eager(self): - self.app.conf.CELERY_ALWAYS_EAGER = True - self.assertEqual(~(self.add.s(4, 4) | self.add.s(8)), 16) - - def test_apply(self): - x = chain(self.add.s(4, 4), self.add.s(8), self.add.s(10)) - res = x.apply() - self.assertIsInstance(res, EagerResult) - self.assertEqual(res.get(), 26) - - self.assertEqual(res.parent.get(), 16) - self.assertEqual(res.parent.parent.get(), 8) - self.assertIsNone(res.parent.parent.parent) - - def test_empty_chain_returns_none(self): - self.assertIsNone(chain(app=self.app)()) - self.assertIsNone(chain(app=self.app).apply_async()) - - def test_call_no_tasks(self): - x = chain() - self.assertFalse(x()) - - def test_call_with_tasks(self): - x = self.add.s(2, 2) | self.add.s(4) - x.apply_async = Mock() - x(2, 2, foo=1) - x.apply_async.assert_called_with((2, 2), {'foo': 1}) - - def test_from_dict_no_args__with_args(self): - x = dict(self.add.s(2, 2) | self.add.s(4)) - x['args'] = None - self.assertIsInstance(chain.from_dict(x), chain) - x['args'] = (2, ) - self.assertIsInstance(chain.from_dict(x), chain) - - def test_accepts_generator_argument(self): - x = chain(self.add.s(i) for i in range(10)) - self.assertTrue(x.tasks[0].type, self.add) - self.assertTrue(x.type) - - -class test_group(CanvasCase): - - def test_repr(self): - x = group([self.add.s(2, 2), self.add.s(4, 4)]) - self.assertEqual(repr(x), repr(x.tasks)) - - def test_reverse(self): - x = group([self.add.s(2, 2), self.add.s(4, 4)]) - self.assertIsInstance(signature(x), group) - self.assertIsInstance(signature(dict(x)), group) - - def test_maybe_group_sig(self): - self.assertListEqual( - _maybe_group(self.add.s(2, 2)), [self.add.s(2, 2)], - ) - - def test_from_dict(self): - x = group([self.add.s(2, 2), self.add.s(4, 4)]) - x['args'] = (2, 2) - self.assertTrue(group.from_dict(dict(x))) - x['args'] = None - self.assertTrue(group.from_dict(dict(x))) - - def test_call_empty_group(self): - x = group(app=self.app) - self.assertFalse(len(x())) - - def test_skew(self): - g = group([self.add.s(i, i) for i in range(10)]) - g.skew(start=1, stop=10, step=1) - for i, task in enumerate(g.tasks): - self.assertEqual(task.options['countdown'], i + 1) - - def test_iter(self): - g = group([self.add.s(i, i) for i in range(10)]) - self.assertListEqual(list(iter(g)), g.tasks) - - -class test_chord(CanvasCase): - - def test_reverse(self): - x = chord([self.add.s(2, 2), self.add.s(4, 4)], body=self.mul.s(4)) - self.assertIsInstance(signature(x), chord) - self.assertIsInstance(signature(dict(x)), chord) - - def test_clone_clones_body(self): - x = chord([self.add.s(2, 2), self.add.s(4, 4)], body=self.mul.s(4)) - y = x.clone() - self.assertIsNot(x.kwargs['body'], y.kwargs['body']) - y.kwargs.pop('body') - z = y.clone() - self.assertIsNone(z.kwargs.get('body')) - - def test_links_to_body(self): - x = chord([self.add.s(2, 2), self.add.s(4, 4)], body=self.mul.s(4)) - x.link(self.div.s(2)) - self.assertFalse(x.options.get('link')) - self.assertTrue(x.kwargs['body'].options['link']) - - x.link_error(self.div.s(2)) - self.assertFalse(x.options.get('link_error')) - self.assertTrue(x.kwargs['body'].options['link_error']) - - self.assertTrue(x.tasks) - self.assertTrue(x.body) - - def test_repr(self): - x = chord([self.add.s(2, 2), self.add.s(4, 4)], body=self.mul.s(4)) - self.assertTrue(repr(x)) - x.kwargs['body'] = None - self.assertIn('without body', repr(x)) - - -class test_maybe_signature(CanvasCase): - - def test_is_None(self): - self.assertIsNone(maybe_signature(None, app=self.app)) - - def test_is_dict(self): - self.assertIsInstance( - maybe_signature(dict(self.add.s()), app=self.app), Signature, - ) - - def test_when_sig(self): - s = self.add.s() - self.assertIs(maybe_signature(s, app=self.app), s) diff --git a/awx/lib/site-packages/celery/tests/tasks/test_chord.py b/awx/lib/site-packages/celery/tests/tasks/test_chord.py deleted file mode 100644 index 47e7718419..0000000000 --- a/awx/lib/site-packages/celery/tests/tasks/test_chord.py +++ /dev/null @@ -1,233 +0,0 @@ -from __future__ import absolute_import - -from contextlib import contextmanager - -from celery import group -from celery import canvas -from celery import result -from celery.exceptions import ChordError, Retry -from celery.five import range -from celery.result import AsyncResult, GroupResult, EagerResult -from celery.tests.case import AppCase, Mock - -passthru = lambda x: x - - -class ChordCase(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - -class TSR(GroupResult): - is_ready = True - value = None - - def ready(self): - return self.is_ready - - def join(self, propagate=True, **kwargs): - if propagate: - for value in self.value: - if isinstance(value, Exception): - raise value - return self.value - join_native = join - - def _failed_join_report(self): - for value in self.value: - if isinstance(value, Exception): - yield EagerResult('some_id', value, 'FAILURE') - - -class TSRNoReport(TSR): - - def _failed_join_report(self): - return iter([]) - - -@contextmanager -def patch_unlock_retry(app): - unlock = app.tasks['celery.chord_unlock'] - retry = Mock() - retry.return_value = Retry() - prev, unlock.retry = unlock.retry, retry - try: - yield unlock, retry - finally: - unlock.retry = prev - - -class test_unlock_chord_task(ChordCase): - - def test_unlock_ready(self): - - class AlwaysReady(TSR): - is_ready = True - value = [2, 4, 8, 6] - - with self._chord_context(AlwaysReady) as (cb, retry, _): - cb.type.apply_async.assert_called_with( - ([2, 4, 8, 6], ), {}, task_id=cb.id, - ) - # did not retry - self.assertFalse(retry.call_count) - - def test_callback_fails(self): - - class AlwaysReady(TSR): - is_ready = True - value = [2, 4, 8, 6] - - def setup(callback): - callback.apply_async.side_effect = IOError() - - with self._chord_context(AlwaysReady, setup) as (cb, retry, fail): - self.assertTrue(fail.called) - self.assertEqual( - fail.call_args[0][0], cb.id, - ) - self.assertIsInstance( - fail.call_args[1]['exc'], ChordError, - ) - - def test_unlock_ready_failed(self): - - class Failed(TSR): - is_ready = True - value = [2, KeyError('foo'), 8, 6] - - with self._chord_context(Failed) as (cb, retry, fail_current): - self.assertFalse(cb.type.apply_async.called) - # did not retry - self.assertFalse(retry.call_count) - self.assertTrue(fail_current.called) - self.assertEqual( - fail_current.call_args[0][0], cb.id, - ) - self.assertIsInstance( - fail_current.call_args[1]['exc'], ChordError, - ) - self.assertIn('some_id', str(fail_current.call_args[1]['exc'])) - - def test_unlock_ready_failed_no_culprit(self): - class Failed(TSRNoReport): - is_ready = True - value = [2, KeyError('foo'), 8, 6] - - with self._chord_context(Failed) as (cb, retry, fail_current): - self.assertTrue(fail_current.called) - self.assertEqual( - fail_current.call_args[0][0], cb.id, - ) - self.assertIsInstance( - fail_current.call_args[1]['exc'], ChordError, - ) - - @contextmanager - def _chord_context(self, ResultCls, setup=None, **kwargs): - @self.app.task(shared=False) - def callback(*args, **kwargs): - pass - self.app.finalize() - - pts, result.GroupResult = result.GroupResult, ResultCls - callback.apply_async = Mock() - callback_s = callback.s() - callback_s.id = 'callback_id' - fail_current = self.app.backend.fail_from_current_stack = Mock() - try: - with patch_unlock_retry(self.app) as (unlock, retry): - subtask, canvas.maybe_signature = ( - canvas.maybe_signature, passthru, - ) - if setup: - setup(callback) - try: - assert self.app.tasks['celery.chord_unlock'] is unlock - try: - unlock( - 'group_id', callback_s, - result=[ - self.app.AsyncResult(r) for r in ['1', 2, 3] - ], - GroupResult=ResultCls, **kwargs - ) - except Retry: - pass - finally: - canvas.maybe_signature = subtask - yield callback_s, retry, fail_current - finally: - result.GroupResult = pts - - def test_when_not_ready(self): - class NeverReady(TSR): - is_ready = False - - with self._chord_context(NeverReady, interval=10, max_retries=30) \ - as (cb, retry, _): - self.assertFalse(cb.type.apply_async.called) - # did retry - retry.assert_called_with(countdown=10, max_retries=30) - - def test_is_in_registry(self): - self.assertIn('celery.chord_unlock', self.app.tasks) - - -class test_chord(ChordCase): - - def test_eager(self): - from celery import chord - - @self.app.task(shared=False) - def addX(x, y): - return x + y - - @self.app.task(shared=False) - def sumX(n): - return sum(n) - - self.app.conf.CELERY_ALWAYS_EAGER = True - x = chord(addX.s(i, i) for i in range(10)) - body = sumX.s() - result = x(body) - self.assertEqual(result.get(), sum(i + i for i in range(10))) - - def test_apply(self): - self.app.conf.CELERY_ALWAYS_EAGER = False - from celery import chord - - m = Mock() - m.app.conf.CELERY_ALWAYS_EAGER = False - m.AsyncResult = AsyncResult - prev, chord._type = chord._type, m - try: - x = chord(self.add.s(i, i) for i in range(10)) - body = self.add.s(2) - result = x(body) - self.assertTrue(result.id) - # does not modify original subtask - with self.assertRaises(KeyError): - body.options['task_id'] - self.assertTrue(chord._type.called) - finally: - chord._type = prev - - -class test_Chord_task(ChordCase): - - def test_run(self): - self.app.backend = Mock() - self.app.backend.cleanup = Mock() - self.app.backend.cleanup.__name__ = 'cleanup' - Chord = self.app.tasks['celery.chord'] - - body = dict() - Chord(group(self.add.subtask((i, i)) for i in range(5)), body) - Chord([self.add.subtask((j, j)) for j in range(5)], body) - self.assertEqual(self.app.backend.apply_chord.call_count, 2) diff --git a/awx/lib/site-packages/celery/tests/tasks/test_context.py b/awx/lib/site-packages/celery/tests/tasks/test_context.py deleted file mode 100644 index ecad3f840d..0000000000 --- a/awx/lib/site-packages/celery/tests/tasks/test_context.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*-' -from __future__ import absolute_import - -from celery.app.task import Context -from celery.tests.case import AppCase - - -# Retreive the values of all context attributes as a -# dictionary in an implementation-agnostic manner. -def get_context_as_dict(ctx, getter=getattr): - defaults = {} - for attr_name in dir(ctx): - if attr_name.startswith('_'): - continue # Ignore pseudo-private attributes - attr = getter(ctx, attr_name) - if callable(attr): - continue # Ignore methods and other non-trivial types - defaults[attr_name] = attr - return defaults -default_context = get_context_as_dict(Context()) - - -class test_Context(AppCase): - - def test_default_context(self): - # A bit of a tautological test, since it uses the same - # initializer as the default_context constructor. - defaults = dict(default_context, children=[]) - self.assertDictEqual(get_context_as_dict(Context()), defaults) - - def test_updated_context(self): - expected = dict(default_context) - changes = dict(id='unique id', args=['some', 1], wibble='wobble') - ctx = Context() - expected.update(changes) - ctx.update(changes) - self.assertDictEqual(get_context_as_dict(ctx), expected) - self.assertDictEqual(get_context_as_dict(Context()), default_context) - - def test_modified_context(self): - expected = dict(default_context) - ctx = Context() - expected['id'] = 'unique id' - expected['args'] = ['some', 1] - ctx.id = 'unique id' - ctx.args = ['some', 1] - self.assertDictEqual(get_context_as_dict(ctx), expected) - self.assertDictEqual(get_context_as_dict(Context()), default_context) - - def test_cleared_context(self): - changes = dict(id='unique id', args=['some', 1], wibble='wobble') - ctx = Context() - ctx.update(changes) - ctx.clear() - defaults = dict(default_context, children=[]) - self.assertDictEqual(get_context_as_dict(ctx), defaults) - self.assertDictEqual(get_context_as_dict(Context()), defaults) - - def test_context_get(self): - expected = dict(default_context) - changes = dict(id='unique id', args=['some', 1], wibble='wobble') - ctx = Context() - expected.update(changes) - ctx.update(changes) - ctx_dict = get_context_as_dict(ctx, getter=Context.get) - self.assertDictEqual(ctx_dict, expected) - self.assertDictEqual(get_context_as_dict(Context()), default_context) diff --git a/awx/lib/site-packages/celery/tests/tasks/test_result.py b/awx/lib/site-packages/celery/tests/tasks/test_result.py deleted file mode 100644 index dbaf3f4d4e..0000000000 --- a/awx/lib/site-packages/celery/tests/tasks/test_result.py +++ /dev/null @@ -1,719 +0,0 @@ -from __future__ import absolute_import - -from contextlib import contextmanager - -from celery import states -from celery.exceptions import IncompleteStream, TimeoutError -from celery.five import range -from celery.result import ( - AsyncResult, - EagerResult, - TaskSetResult, - result_from_tuple, -) -from celery.utils import uuid -from celery.utils.serialization import pickle - -from celery.tests.case import AppCase, Mock, depends_on_current_app, patch - - -def mock_task(name, state, result): - return dict(id=uuid(), name=name, state=state, result=result) - - -def save_result(app, task): - traceback = 'Some traceback' - if task['state'] == states.SUCCESS: - app.backend.mark_as_done(task['id'], task['result']) - elif task['state'] == states.RETRY: - app.backend.mark_as_retry( - task['id'], task['result'], traceback=traceback, - ) - else: - app.backend.mark_as_failure( - task['id'], task['result'], traceback=traceback, - ) - - -def make_mock_group(app, size=10): - tasks = [mock_task('ts%d' % i, states.SUCCESS, i) for i in range(size)] - [save_result(app, task) for task in tasks] - return [app.AsyncResult(task['id']) for task in tasks] - - -class test_AsyncResult(AppCase): - - def setup(self): - self.task1 = mock_task('task1', states.SUCCESS, 'the') - self.task2 = mock_task('task2', states.SUCCESS, 'quick') - self.task3 = mock_task('task3', states.FAILURE, KeyError('brown')) - self.task4 = mock_task('task3', states.RETRY, KeyError('red')) - - for task in (self.task1, self.task2, self.task3, self.task4): - save_result(self.app, task) - - @self.app.task(shared=False) - def mytask(): - pass - self.mytask = mytask - - def test_compat_properties(self): - x = self.app.AsyncResult('1') - self.assertEqual(x.task_id, x.id) - x.task_id = '2' - self.assertEqual(x.id, '2') - - def test_children(self): - x = self.app.AsyncResult('1') - children = [EagerResult(str(i), i, states.SUCCESS) for i in range(3)] - x._cache = {'children': children, 'status': states.SUCCESS} - x.backend = Mock() - self.assertTrue(x.children) - self.assertEqual(len(x.children), 3) - - def test_propagates_for_parent(self): - x = self.app.AsyncResult(uuid()) - x.backend = Mock() - x.backend.get_task_meta.return_value = {} - x.parent = EagerResult(uuid(), KeyError('foo'), states.FAILURE) - with self.assertRaises(KeyError): - x.get(propagate=True) - self.assertFalse(x.backend.wait_for.called) - - x.parent = EagerResult(uuid(), 42, states.SUCCESS) - x.get(propagate=True) - self.assertTrue(x.backend.wait_for.called) - - def test_get_children(self): - tid = uuid() - x = self.app.AsyncResult(tid) - child = [self.app.AsyncResult(uuid()).as_tuple() - for i in range(10)] - x._cache = {'children': child} - self.assertTrue(x.children) - self.assertEqual(len(x.children), 10) - - x._cache = {'status': states.SUCCESS} - x.backend._cache[tid] = {'result': None} - self.assertIsNone(x.children) - - def test_build_graph_get_leaf_collect(self): - x = self.app.AsyncResult('1') - x.backend._cache['1'] = {'status': states.SUCCESS, 'result': None} - c = [EagerResult(str(i), i, states.SUCCESS) for i in range(3)] - x.iterdeps = Mock() - x.iterdeps.return_value = ( - (None, x), - (x, c[0]), - (c[0], c[1]), - (c[1], c[2]) - ) - x.backend.READY_STATES = states.READY_STATES - self.assertTrue(x.graph) - - self.assertIs(x.get_leaf(), 2) - - it = x.collect() - self.assertListEqual(list(it), [ - (x, None), - (c[0], 0), - (c[1], 1), - (c[2], 2), - ]) - - def test_iterdeps(self): - x = self.app.AsyncResult('1') - c = [EagerResult(str(i), i, states.SUCCESS) for i in range(3)] - x._cache = {'status': states.SUCCESS, 'result': None, 'children': c} - for child in c: - child.backend = Mock() - child.backend.get_children.return_value = [] - it = x.iterdeps() - self.assertListEqual(list(it), [ - (None, x), - (x, c[0]), - (x, c[1]), - (x, c[2]), - ]) - x._cache = None - x.ready = Mock() - x.ready.return_value = False - with self.assertRaises(IncompleteStream): - list(x.iterdeps()) - list(x.iterdeps(intermediate=True)) - - def test_eq_not_implemented(self): - self.assertFalse(self.app.AsyncResult('1') == object()) - - @depends_on_current_app - def test_reduce(self): - a1 = self.app.AsyncResult('uuid', task_name=self.mytask.name) - restored = pickle.loads(pickle.dumps(a1)) - self.assertEqual(restored.id, 'uuid') - self.assertEqual(restored.task_name, self.mytask.name) - - a2 = self.app.AsyncResult('uuid') - self.assertEqual(pickle.loads(pickle.dumps(a2)).id, 'uuid') - - def test_successful(self): - ok_res = self.app.AsyncResult(self.task1['id']) - nok_res = self.app.AsyncResult(self.task3['id']) - nok_res2 = self.app.AsyncResult(self.task4['id']) - - self.assertTrue(ok_res.successful()) - self.assertFalse(nok_res.successful()) - self.assertFalse(nok_res2.successful()) - - pending_res = self.app.AsyncResult(uuid()) - self.assertFalse(pending_res.successful()) - - def test_str(self): - ok_res = self.app.AsyncResult(self.task1['id']) - ok2_res = self.app.AsyncResult(self.task2['id']) - nok_res = self.app.AsyncResult(self.task3['id']) - self.assertEqual(str(ok_res), self.task1['id']) - self.assertEqual(str(ok2_res), self.task2['id']) - self.assertEqual(str(nok_res), self.task3['id']) - - pending_id = uuid() - pending_res = self.app.AsyncResult(pending_id) - self.assertEqual(str(pending_res), pending_id) - - def test_repr(self): - ok_res = self.app.AsyncResult(self.task1['id']) - ok2_res = self.app.AsyncResult(self.task2['id']) - nok_res = self.app.AsyncResult(self.task3['id']) - self.assertEqual(repr(ok_res), '<AsyncResult: %s>' % ( - self.task1['id'])) - self.assertEqual(repr(ok2_res), '<AsyncResult: %s>' % ( - self.task2['id'])) - self.assertEqual(repr(nok_res), '<AsyncResult: %s>' % ( - self.task3['id'])) - - pending_id = uuid() - pending_res = self.app.AsyncResult(pending_id) - self.assertEqual(repr(pending_res), '<AsyncResult: %s>' % ( - pending_id)) - - def test_hash(self): - self.assertEqual(hash(self.app.AsyncResult('x0w991')), - hash(self.app.AsyncResult('x0w991'))) - self.assertNotEqual(hash(self.app.AsyncResult('x0w991')), - hash(self.app.AsyncResult('x1w991'))) - - def test_get_traceback(self): - ok_res = self.app.AsyncResult(self.task1['id']) - nok_res = self.app.AsyncResult(self.task3['id']) - nok_res2 = self.app.AsyncResult(self.task4['id']) - self.assertFalse(ok_res.traceback) - self.assertTrue(nok_res.traceback) - self.assertTrue(nok_res2.traceback) - - pending_res = self.app.AsyncResult(uuid()) - self.assertFalse(pending_res.traceback) - - def test_get(self): - ok_res = self.app.AsyncResult(self.task1['id']) - ok2_res = self.app.AsyncResult(self.task2['id']) - nok_res = self.app.AsyncResult(self.task3['id']) - nok2_res = self.app.AsyncResult(self.task4['id']) - - self.assertEqual(ok_res.get(), 'the') - self.assertEqual(ok2_res.get(), 'quick') - with self.assertRaises(KeyError): - nok_res.get() - self.assertTrue(nok_res.get(propagate=False)) - self.assertIsInstance(nok2_res.result, KeyError) - self.assertEqual(ok_res.info, 'the') - - def test_get_timeout(self): - res = self.app.AsyncResult(self.task4['id']) # has RETRY state - with self.assertRaises(TimeoutError): - res.get(timeout=0.001) - - pending_res = self.app.AsyncResult(uuid()) - with patch('celery.result.time') as _time: - with self.assertRaises(TimeoutError): - pending_res.get(timeout=0.001, interval=0.001) - _time.sleep.assert_called_with(0.001) - - def test_get_timeout_longer(self): - res = self.app.AsyncResult(self.task4['id']) # has RETRY state - with patch('celery.result.time') as _time: - with self.assertRaises(TimeoutError): - res.get(timeout=1, interval=1) - _time.sleep.assert_called_with(1) - - def test_ready(self): - oks = (self.app.AsyncResult(self.task1['id']), - self.app.AsyncResult(self.task2['id']), - self.app.AsyncResult(self.task3['id'])) - self.assertTrue(all(result.ready() for result in oks)) - self.assertFalse(self.app.AsyncResult(self.task4['id']).ready()) - - self.assertFalse(self.app.AsyncResult(uuid()).ready()) - - -class test_ResultSet(AppCase): - - def test_resultset_repr(self): - self.assertTrue(repr(self.app.ResultSet( - [self.app.AsyncResult(t) for t in ['1', '2', '3']]))) - - def test_eq_other(self): - self.assertFalse(self.app.ResultSet([1, 3, 3]) == 1) - self.assertTrue(self.app.ResultSet([1]) == self.app.ResultSet([1])) - - def test_get(self): - x = self.app.ResultSet([self.app.AsyncResult(t) for t in [1, 2, 3]]) - b = x.results[0].backend = Mock() - b.supports_native_join = False - x.join_native = Mock() - x.join = Mock() - x.get() - self.assertTrue(x.join.called) - b.supports_native_join = True - x.get() - self.assertTrue(x.join_native.called) - - def test_add(self): - x = self.app.ResultSet([1]) - x.add(2) - self.assertEqual(len(x), 2) - x.add(2) - self.assertEqual(len(x), 2) - - @contextmanager - def dummy_copy(self): - with patch('celery.result.copy') as copy: - - def passt(arg): - return arg - copy.side_effect = passt - - yield - - def test_iterate_respects_subpolling_interval(self): - r1 = self.app.AsyncResult(uuid()) - r2 = self.app.AsyncResult(uuid()) - backend = r1.backend = r2.backend = Mock() - backend.subpolling_interval = 10 - - ready = r1.ready = r2.ready = Mock() - - def se(*args, **kwargs): - ready.side_effect = KeyError() - return False - ready.return_value = False - ready.side_effect = se - - x = self.app.ResultSet([r1, r2]) - with self.dummy_copy(): - with patch('celery.result.time') as _time: - with self.assertPendingDeprecation(): - with self.assertRaises(KeyError): - list(x.iterate()) - _time.sleep.assert_called_with(10) - - backend.subpolling_interval = 0 - with patch('celery.result.time') as _time: - with self.assertPendingDeprecation(): - with self.assertRaises(KeyError): - ready.return_value = False - ready.side_effect = se - list(x.iterate()) - self.assertFalse(_time.sleep.called) - - def test_times_out(self): - r1 = self.app.AsyncResult(uuid) - r1.ready = Mock() - r1.ready.return_value = False - x = self.app.ResultSet([r1]) - with self.dummy_copy(): - with patch('celery.result.time'): - with self.assertPendingDeprecation(): - with self.assertRaises(TimeoutError): - list(x.iterate(timeout=1)) - - def test_add_discard(self): - x = self.app.ResultSet([]) - x.add(self.app.AsyncResult('1')) - self.assertIn(self.app.AsyncResult('1'), x.results) - x.discard(self.app.AsyncResult('1')) - x.discard(self.app.AsyncResult('1')) - x.discard('1') - self.assertNotIn(self.app.AsyncResult('1'), x.results) - - x.update([self.app.AsyncResult('2')]) - - def test_clear(self): - x = self.app.ResultSet([]) - r = x.results - x.clear() - self.assertIs(x.results, r) - - -class MockAsyncResultFailure(AsyncResult): - - @property - def result(self): - return KeyError('baz') - - @property - def state(self): - return states.FAILURE - - def get(self, propagate=True, **kwargs): - if propagate: - raise self.result - return self.result - - -class MockAsyncResultSuccess(AsyncResult): - forgotten = False - - def forget(self): - self.forgotten = True - - @property - def result(self): - return 42 - - @property - def state(self): - return states.SUCCESS - - def get(self, **kwargs): - return self.result - - -class SimpleBackend(object): - ids = [] - - def __init__(self, ids=[]): - self.ids = ids - - def get_many(self, *args, **kwargs): - return ((id, {'result': i, 'status': states.SUCCESS}) - for i, id in enumerate(self.ids)) - - -class test_TaskSetResult(AppCase): - - def setup(self): - self.size = 10 - self.ts = TaskSetResult(uuid(), make_mock_group(self.app, self.size)) - - def test_total(self): - self.assertEqual(self.ts.total, self.size) - - def test_compat_properties(self): - self.assertEqual(self.ts.taskset_id, self.ts.id) - self.ts.taskset_id = 'foo' - self.assertEqual(self.ts.taskset_id, 'foo') - - def test_compat_subtasks_kwarg(self): - x = TaskSetResult(uuid(), subtasks=[1, 2, 3]) - self.assertEqual(x.results, [1, 2, 3]) - - def test_itersubtasks(self): - it = self.ts.itersubtasks() - - for i, t in enumerate(it): - self.assertEqual(t.get(), i) - - -class test_GroupResult(AppCase): - - def setup(self): - self.size = 10 - self.ts = self.app.GroupResult( - uuid(), make_mock_group(self.app, self.size), - ) - - @depends_on_current_app - def test_is_pickleable(self): - ts = self.app.GroupResult(uuid(), [self.app.AsyncResult(uuid())]) - self.assertEqual(pickle.loads(pickle.dumps(ts)), ts) - ts2 = self.app.GroupResult(uuid(), [self.app.AsyncResult(uuid())]) - self.assertEqual(pickle.loads(pickle.dumps(ts2)), ts2) - - def test_len(self): - self.assertEqual(len(self.ts), self.size) - - def test_eq_other(self): - self.assertFalse(self.ts == 1) - - @depends_on_current_app - def test_reduce(self): - self.assertTrue(pickle.loads(pickle.dumps(self.ts))) - - def test_iterate_raises(self): - ar = MockAsyncResultFailure(uuid(), app=self.app) - ts = self.app.GroupResult(uuid(), [ar]) - with self.assertPendingDeprecation(): - it = ts.iterate() - with self.assertRaises(KeyError): - next(it) - - def test_forget(self): - subs = [MockAsyncResultSuccess(uuid(), app=self.app), - MockAsyncResultSuccess(uuid(), app=self.app)] - ts = self.app.GroupResult(uuid(), subs) - ts.forget() - for sub in subs: - self.assertTrue(sub.forgotten) - - def test_getitem(self): - subs = [MockAsyncResultSuccess(uuid(), app=self.app), - MockAsyncResultSuccess(uuid(), app=self.app)] - ts = self.app.GroupResult(uuid(), subs) - self.assertIs(ts[0], subs[0]) - - def test_save_restore(self): - subs = [MockAsyncResultSuccess(uuid(), app=self.app), - MockAsyncResultSuccess(uuid(), app=self.app)] - ts = self.app.GroupResult(uuid(), subs) - ts.save() - with self.assertRaises(AttributeError): - ts.save(backend=object()) - self.assertEqual(self.app.GroupResult.restore(ts.id).subtasks, - ts.subtasks) - ts.delete() - self.assertIsNone(self.app.GroupResult.restore(ts.id)) - with self.assertRaises(AttributeError): - self.app.GroupResult.restore(ts.id, backend=object()) - - def test_join_native(self): - backend = SimpleBackend() - subtasks = [self.app.AsyncResult(uuid(), backend=backend) - for i in range(10)] - ts = self.app.GroupResult(uuid(), subtasks) - backend.ids = [subtask.id for subtask in subtasks] - res = ts.join_native() - self.assertEqual(res, list(range(10))) - - def test_join_native_raises(self): - ts = self.app.GroupResult(uuid(), [self.app.AsyncResult(uuid())]) - ts.iter_native = Mock() - ts.iter_native.return_value = iter([ - (uuid(), {'status': states.FAILURE, 'result': KeyError()}) - ]) - with self.assertRaises(KeyError): - ts.join_native(propagate=True) - - def test_failed_join_report(self): - res = Mock() - ts = self.app.GroupResult(uuid(), [res]) - res.state = states.FAILURE - res.backend.is_cached.return_value = True - self.assertIs(next(ts._failed_join_report()), res) - res.backend.is_cached.return_value = False - with self.assertRaises(StopIteration): - next(ts._failed_join_report()) - - def test_repr(self): - self.assertTrue(repr( - self.app.GroupResult(uuid(), [self.app.AsyncResult(uuid())]) - )) - - def test_children_is_results(self): - ts = self.app.GroupResult(uuid(), [self.app.AsyncResult(uuid())]) - self.assertIs(ts.children, ts.results) - - def test_iter_native(self): - backend = SimpleBackend() - subtasks = [self.app.AsyncResult(uuid(), backend=backend) - for i in range(10)] - ts = self.app.GroupResult(uuid(), subtasks) - backend.ids = [subtask.id for subtask in subtasks] - self.assertEqual(len(list(ts.iter_native())), 10) - - def test_iterate_yields(self): - ar = MockAsyncResultSuccess(uuid(), app=self.app) - ar2 = MockAsyncResultSuccess(uuid(), app=self.app) - ts = self.app.GroupResult(uuid(), [ar, ar2]) - with self.assertPendingDeprecation(): - it = ts.iterate() - self.assertEqual(next(it), 42) - self.assertEqual(next(it), 42) - - def test_iterate_eager(self): - ar1 = EagerResult(uuid(), 42, states.SUCCESS) - ar2 = EagerResult(uuid(), 42, states.SUCCESS) - ts = self.app.GroupResult(uuid(), [ar1, ar2]) - with self.assertPendingDeprecation(): - it = ts.iterate() - self.assertEqual(next(it), 42) - self.assertEqual(next(it), 42) - - def test_join_timeout(self): - ar = MockAsyncResultSuccess(uuid(), app=self.app) - ar2 = MockAsyncResultSuccess(uuid(), app=self.app) - ar3 = self.app.AsyncResult(uuid()) - ts = self.app.GroupResult(uuid(), [ar, ar2, ar3]) - with self.assertRaises(TimeoutError): - ts.join(timeout=0.0000001) - - ar4 = self.app.AsyncResult(uuid()) - ar4.get = Mock() - ts2 = self.app.GroupResult(uuid(), [ar4]) - self.assertTrue(ts2.join(timeout=0.1)) - - def test_iter_native_when_empty_group(self): - ts = self.app.GroupResult(uuid(), []) - self.assertListEqual(list(ts.iter_native()), []) - - def test_iterate_simple(self): - with self.assertPendingDeprecation(): - it = self.ts.iterate() - results = sorted(list(it)) - self.assertListEqual(results, list(range(self.size))) - - def test___iter__(self): - self.assertListEqual(list(iter(self.ts)), self.ts.results) - - def test_join(self): - joined = self.ts.join() - self.assertListEqual(joined, list(range(self.size))) - - def test_successful(self): - self.assertTrue(self.ts.successful()) - - def test_failed(self): - self.assertFalse(self.ts.failed()) - - def test_waiting(self): - self.assertFalse(self.ts.waiting()) - - def test_ready(self): - self.assertTrue(self.ts.ready()) - - def test_completed_count(self): - self.assertEqual(self.ts.completed_count(), len(self.ts)) - - -class test_pending_AsyncResult(AppCase): - - def setup(self): - self.task = self.app.AsyncResult(uuid()) - - def test_result(self): - self.assertIsNone(self.task.result) - - -class test_failed_AsyncResult(test_GroupResult): - - def setup(self): - self.size = 11 - subtasks = make_mock_group(self.app, 10) - failed = mock_task('ts11', states.FAILURE, KeyError('Baz')) - save_result(self.app, failed) - failed_res = self.app.AsyncResult(failed['id']) - self.ts = self.app.GroupResult(uuid(), subtasks + [failed_res]) - - def test_completed_count(self): - self.assertEqual(self.ts.completed_count(), len(self.ts) - 1) - - def test_iterate_simple(self): - with self.assertPendingDeprecation(): - it = self.ts.iterate() - - def consume(): - return list(it) - - with self.assertRaises(KeyError): - consume() - - def test_join(self): - with self.assertRaises(KeyError): - self.ts.join() - - def test_successful(self): - self.assertFalse(self.ts.successful()) - - def test_failed(self): - self.assertTrue(self.ts.failed()) - - -class test_pending_Group(AppCase): - - def setup(self): - self.ts = self.app.GroupResult( - uuid(), [self.app.AsyncResult(uuid()), - self.app.AsyncResult(uuid())]) - - def test_completed_count(self): - self.assertEqual(self.ts.completed_count(), 0) - - def test_ready(self): - self.assertFalse(self.ts.ready()) - - def test_waiting(self): - self.assertTrue(self.ts.waiting()) - - def x_join(self): - with self.assertRaises(TimeoutError): - self.ts.join(timeout=0.001) - - def x_join_longer(self): - with self.assertRaises(TimeoutError): - self.ts.join(timeout=1) - - -class test_EagerResult(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def raising(x, y): - raise KeyError(x, y) - self.raising = raising - - def test_wait_raises(self): - res = self.raising.apply(args=[3, 3]) - with self.assertRaises(KeyError): - res.wait() - self.assertTrue(res.wait(propagate=False)) - - def test_wait(self): - res = EagerResult('x', 'x', states.RETRY) - res.wait() - self.assertEqual(res.state, states.RETRY) - self.assertEqual(res.status, states.RETRY) - - def test_forget(self): - res = EagerResult('x', 'x', states.RETRY) - res.forget() - - def test_revoke(self): - res = self.raising.apply(args=[3, 3]) - self.assertFalse(res.revoke()) - - -class test_tuples(AppCase): - - def test_AsyncResult(self): - x = self.app.AsyncResult(uuid()) - self.assertEqual(x, result_from_tuple(x.as_tuple(), self.app)) - self.assertEqual(x, result_from_tuple(x, self.app)) - - def test_with_parent(self): - x = self.app.AsyncResult(uuid()) - x.parent = self.app.AsyncResult(uuid()) - y = result_from_tuple(x.as_tuple(), self.app) - self.assertEqual(y, x) - self.assertEqual(y.parent, x.parent) - self.assertIsInstance(y.parent, AsyncResult) - - def test_compat(self): - uid = uuid() - x = result_from_tuple([uid, []], app=self.app) - self.assertEqual(x.id, uid) - - def test_GroupResult(self): - x = self.app.GroupResult( - uuid(), [self.app.AsyncResult(uuid()) for _ in range(10)], - ) - self.assertEqual(x, result_from_tuple(x.as_tuple(), self.app)) - self.assertEqual(x, result_from_tuple(x, self.app)) diff --git a/awx/lib/site-packages/celery/tests/tasks/test_states.py b/awx/lib/site-packages/celery/tests/tasks/test_states.py deleted file mode 100644 index b30a4ee6a5..0000000000 --- a/awx/lib/site-packages/celery/tests/tasks/test_states.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import absolute_import - -from celery.states import state -from celery import states -from celery.tests.case import Case - - -class test_state_precedence(Case): - - def test_gt(self): - self.assertGreater(state(states.SUCCESS), - state(states.PENDING)) - self.assertGreater(state(states.FAILURE), - state(states.RECEIVED)) - self.assertGreater(state(states.REVOKED), - state(states.STARTED)) - self.assertGreater(state(states.SUCCESS), - state('CRASHED')) - self.assertGreater(state(states.FAILURE), - state('CRASHED')) - self.assertFalse(state(states.REVOKED) > state('CRASHED')) - - def test_lt(self): - self.assertLess(state(states.PENDING), state(states.SUCCESS)) - self.assertLess(state(states.RECEIVED), state(states.FAILURE)) - self.assertLess(state(states.STARTED), state(states.REVOKED)) - self.assertLess(state('CRASHED'), state(states.SUCCESS)) - self.assertLess(state('CRASHED'), state(states.FAILURE)) - self.assertTrue(state(states.REVOKED) < state('CRASHED')) - self.assertTrue(state(states.REVOKED) <= state('CRASHED')) - self.assertTrue(state('CRASHED') >= state(states.REVOKED)) diff --git a/awx/lib/site-packages/celery/tests/tasks/test_tasks.py b/awx/lib/site-packages/celery/tests/tasks/test_tasks.py deleted file mode 100644 index 93a782ecc9..0000000000 --- a/awx/lib/site-packages/celery/tests/tasks/test_tasks.py +++ /dev/null @@ -1,459 +0,0 @@ -from __future__ import absolute_import - -from datetime import datetime, timedelta - -from kombu import Queue - -from celery import Task - -from celery.exceptions import Retry -from celery.five import items, range, string_t -from celery.result import EagerResult -from celery.utils import uuid -from celery.utils.timeutils import parse_iso8601 - -from celery.tests.case import AppCase, depends_on_current_app, patch - - -def return_True(*args, **kwargs): - # Task run functions can't be closures/lambdas, as they're pickled. - return True - - -def raise_exception(self, **kwargs): - raise Exception('%s error' % self.__class__) - - -class MockApplyTask(Task): - abstract = True - applied = 0 - - def run(self, x, y): - return x * y - - def apply_async(self, *args, **kwargs): - self.applied += 1 - - -class TasksCase(AppCase): - - def setup(self): - self.mytask = self.app.task(shared=False)(return_True) - - @self.app.task(bind=True, count=0, shared=False) - def increment_counter(self, increment_by=1): - self.count += increment_by or 1 - return self.count - self.increment_counter = increment_counter - - @self.app.task(shared=False) - def raising(): - raise KeyError('foo') - self.raising = raising - - @self.app.task(bind=True, max_retries=3, iterations=0, shared=False) - def retry_task(self, arg1, arg2, kwarg=1, max_retries=None, care=True): - self.iterations += 1 - rmax = self.max_retries if max_retries is None else max_retries - - assert repr(self.request) - retries = self.request.retries - if care and retries >= rmax: - return arg1 - else: - raise self.retry(countdown=0, max_retries=rmax) - self.retry_task = retry_task - - @self.app.task(bind=True, max_retries=3, iterations=0, shared=False) - def retry_task_noargs(self, **kwargs): - self.iterations += 1 - - if self.request.retries >= 3: - return 42 - else: - raise self.retry(countdown=0) - self.retry_task_noargs = retry_task_noargs - - @self.app.task(bind=True, max_retries=3, iterations=0, - base=MockApplyTask, shared=False) - def retry_task_mockapply(self, arg1, arg2, kwarg=1): - self.iterations += 1 - - retries = self.request.retries - if retries >= 3: - return arg1 - raise self.retry(countdown=0) - self.retry_task_mockapply = retry_task_mockapply - - @self.app.task(bind=True, max_retries=3, iterations=0, shared=False) - def retry_task_customexc(self, arg1, arg2, kwarg=1, **kwargs): - self.iterations += 1 - - retries = self.request.retries - if retries >= 3: - return arg1 + kwarg - else: - try: - raise MyCustomException('Elaine Marie Benes') - except MyCustomException as exc: - kwargs.update(kwarg=kwarg) - raise self.retry(countdown=0, exc=exc) - self.retry_task_customexc = retry_task_customexc - - -class MyCustomException(Exception): - """Random custom exception.""" - - -class test_task_retries(TasksCase): - - def test_retry(self): - self.retry_task.max_retries = 3 - self.retry_task.iterations = 0 - self.retry_task.apply([0xFF, 0xFFFF]) - self.assertEqual(self.retry_task.iterations, 4) - - self.retry_task.max_retries = 3 - self.retry_task.iterations = 0 - self.retry_task.apply([0xFF, 0xFFFF], {'max_retries': 10}) - self.assertEqual(self.retry_task.iterations, 11) - - def test_retry_no_args(self): - self.retry_task_noargs.max_retries = 3 - self.retry_task_noargs.iterations = 0 - self.retry_task_noargs.apply(propagate=True).get() - self.assertEqual(self.retry_task_noargs.iterations, 4) - - def test_retry_kwargs_can_be_empty(self): - self.retry_task_mockapply.push_request() - try: - with self.assertRaises(Retry): - self.retry_task_mockapply.retry(args=[4, 4], kwargs=None) - finally: - self.retry_task_mockapply.pop_request() - - def test_retry_not_eager(self): - self.retry_task_mockapply.push_request() - try: - self.retry_task_mockapply.request.called_directly = False - exc = Exception('baz') - try: - self.retry_task_mockapply.retry( - args=[4, 4], kwargs={'task_retries': 0}, - exc=exc, throw=False, - ) - self.assertTrue(self.retry_task_mockapply.applied) - finally: - self.retry_task_mockapply.applied = 0 - - try: - with self.assertRaises(Retry): - self.retry_task_mockapply.retry( - args=[4, 4], kwargs={'task_retries': 0}, - exc=exc, throw=True) - self.assertTrue(self.retry_task_mockapply.applied) - finally: - self.retry_task_mockapply.applied = 0 - finally: - self.retry_task_mockapply.pop_request() - - def test_retry_with_kwargs(self): - self.retry_task_customexc.max_retries = 3 - self.retry_task_customexc.iterations = 0 - self.retry_task_customexc.apply([0xFF, 0xFFFF], {'kwarg': 0xF}) - self.assertEqual(self.retry_task_customexc.iterations, 4) - - def test_retry_with_custom_exception(self): - self.retry_task_customexc.max_retries = 2 - self.retry_task_customexc.iterations = 0 - result = self.retry_task_customexc.apply( - [0xFF, 0xFFFF], {'kwarg': 0xF}, - ) - with self.assertRaises(MyCustomException): - result.get() - self.assertEqual(self.retry_task_customexc.iterations, 3) - - def test_max_retries_exceeded(self): - self.retry_task.max_retries = 2 - self.retry_task.iterations = 0 - result = self.retry_task.apply([0xFF, 0xFFFF], {'care': False}) - with self.assertRaises(self.retry_task.MaxRetriesExceededError): - result.get() - self.assertEqual(self.retry_task.iterations, 3) - - self.retry_task.max_retries = 1 - self.retry_task.iterations = 0 - result = self.retry_task.apply([0xFF, 0xFFFF], {'care': False}) - with self.assertRaises(self.retry_task.MaxRetriesExceededError): - result.get() - self.assertEqual(self.retry_task.iterations, 2) - - -class test_canvas_utils(TasksCase): - - def test_si(self): - self.assertTrue(self.retry_task.si()) - self.assertTrue(self.retry_task.si().immutable) - - def test_chunks(self): - self.assertTrue(self.retry_task.chunks(range(100), 10)) - - def test_map(self): - self.assertTrue(self.retry_task.map(range(100))) - - def test_starmap(self): - self.assertTrue(self.retry_task.starmap(range(100))) - - def test_on_success(self): - self.retry_task.on_success(1, 1, (), {}) - - -class test_tasks(TasksCase): - - def now(self): - return self.app.now() - - @depends_on_current_app - def test_unpickle_task(self): - import pickle - - @self.app.task(shared=True) - def xxx(): - pass - self.assertIs(pickle.loads(pickle.dumps(xxx)), xxx.app.tasks[xxx.name]) - - def test_AsyncResult(self): - task_id = uuid() - result = self.retry_task.AsyncResult(task_id) - self.assertEqual(result.backend, self.retry_task.backend) - self.assertEqual(result.id, task_id) - - def assertNextTaskDataEqual(self, consumer, presult, task_name, - test_eta=False, test_expires=False, **kwargs): - next_task = consumer.queues[0].get(accept=['pickle']) - task_data = next_task.decode() - self.assertEqual(task_data['id'], presult.id) - self.assertEqual(task_data['task'], task_name) - task_kwargs = task_data.get('kwargs', {}) - if test_eta: - self.assertIsInstance(task_data.get('eta'), string_t) - to_datetime = parse_iso8601(task_data.get('eta')) - self.assertIsInstance(to_datetime, datetime) - if test_expires: - self.assertIsInstance(task_data.get('expires'), string_t) - to_datetime = parse_iso8601(task_data.get('expires')) - self.assertIsInstance(to_datetime, datetime) - for arg_name, arg_value in items(kwargs): - self.assertEqual(task_kwargs.get(arg_name), arg_value) - - def test_incomplete_task_cls(self): - - class IncompleteTask(Task): - app = self.app - name = 'c.unittest.t.itask' - - with self.assertRaises(NotImplementedError): - IncompleteTask().run() - - def test_task_kwargs_must_be_dictionary(self): - with self.assertRaises(ValueError): - self.increment_counter.apply_async([], 'str') - - def test_task_args_must_be_list(self): - with self.assertRaises(ValueError): - self.increment_counter.apply_async('str', {}) - - def test_regular_task(self): - self.assertIsInstance(self.mytask, Task) - self.assertTrue(self.mytask.run()) - self.assertTrue( - callable(self.mytask), 'Task class is callable()', - ) - self.assertTrue(self.mytask(), 'Task class runs run() when called') - - with self.app.connection_or_acquire() as conn: - consumer = self.app.amqp.TaskConsumer(conn) - with self.assertRaises(NotImplementedError): - consumer.receive('foo', 'foo') - consumer.purge() - self.assertIsNone(consumer.queues[0].get()) - self.app.amqp.TaskConsumer(conn, queues=[Queue('foo')]) - - # Without arguments. - presult = self.mytask.delay() - self.assertNextTaskDataEqual(consumer, presult, self.mytask.name) - - # With arguments. - presult2 = self.mytask.apply_async( - kwargs=dict(name='George Costanza'), - ) - self.assertNextTaskDataEqual( - consumer, presult2, self.mytask.name, name='George Costanza', - ) - - # send_task - sresult = self.app.send_task(self.mytask.name, - kwargs=dict(name='Elaine M. Benes')) - self.assertNextTaskDataEqual( - consumer, sresult, self.mytask.name, name='Elaine M. Benes', - ) - - # With eta. - presult2 = self.mytask.apply_async( - kwargs=dict(name='George Costanza'), - eta=self.now() + timedelta(days=1), - expires=self.now() + timedelta(days=2), - ) - self.assertNextTaskDataEqual( - consumer, presult2, self.mytask.name, - name='George Costanza', test_eta=True, test_expires=True, - ) - - # With countdown. - presult2 = self.mytask.apply_async( - kwargs=dict(name='George Costanza'), countdown=10, expires=12, - ) - self.assertNextTaskDataEqual( - consumer, presult2, self.mytask.name, - name='George Costanza', test_eta=True, test_expires=True, - ) - - # Discarding all tasks. - consumer.purge() - self.mytask.apply_async() - self.assertEqual(consumer.purge(), 1) - self.assertIsNone(consumer.queues[0].get()) - - self.assertFalse(presult.successful()) - self.mytask.backend.mark_as_done(presult.id, result=None) - self.assertTrue(presult.successful()) - - def test_repr_v2_compat(self): - self.mytask.__v2_compat__ = True - self.assertIn('v2 compatible', repr(self.mytask)) - - def test_apply_with_self(self): - - @self.app.task(__self__=42, shared=False) - def tawself(self): - return self - - self.assertEqual(tawself.apply().get(), 42) - - self.assertEqual(tawself(), 42) - - def test_context_get(self): - self.mytask.push_request() - try: - request = self.mytask.request - request.foo = 32 - self.assertEqual(request.get('foo'), 32) - self.assertEqual(request.get('bar', 36), 36) - request.clear() - finally: - self.mytask.pop_request() - - def test_task_class_repr(self): - self.assertIn('class Task of', repr(self.mytask.app.Task)) - self.mytask.app.Task._app = None - self.assertIn('unbound', repr(self.mytask.app.Task, )) - - def test_bind_no_magic_kwargs(self): - self.mytask.accept_magic_kwargs = None - self.mytask.bind(self.mytask.app) - - def test_annotate(self): - with patch('celery.app.task.resolve_all_annotations') as anno: - anno.return_value = [{'FOO': 'BAR'}] - - @self.app.task(shared=False) - def task(): - pass - task.annotate() - self.assertEqual(task.FOO, 'BAR') - - def test_after_return(self): - self.mytask.push_request() - try: - self.mytask.request.chord = self.mytask.s() - self.mytask.after_return('SUCCESS', 1.0, 'foobar', (), {}, None) - self.mytask.request.clear() - finally: - self.mytask.pop_request() - - def test_send_task_sent_event(self): - with self.app.connection() as conn: - self.app.conf.CELERY_SEND_TASK_SENT_EVENT = True - self.assertTrue(self.app.amqp.TaskProducer(conn).send_sent_event) - - def test_update_state(self): - - @self.app.task(shared=False) - def yyy(): - pass - - yyy.push_request() - try: - tid = uuid() - yyy.update_state(tid, 'FROBULATING', {'fooz': 'baaz'}) - self.assertEqual(yyy.AsyncResult(tid).status, 'FROBULATING') - self.assertDictEqual(yyy.AsyncResult(tid).result, {'fooz': 'baaz'}) - - yyy.request.id = tid - yyy.update_state(state='FROBUZATING', meta={'fooz': 'baaz'}) - self.assertEqual(yyy.AsyncResult(tid).status, 'FROBUZATING') - self.assertDictEqual(yyy.AsyncResult(tid).result, {'fooz': 'baaz'}) - finally: - yyy.pop_request() - - def test_repr(self): - - @self.app.task(shared=False) - def task_test_repr(): - pass - - self.assertIn('task_test_repr', repr(task_test_repr)) - - def test_has___name__(self): - - @self.app.task(shared=False) - def yyy2(): - pass - - self.assertTrue(yyy2.__name__) - - -class test_apply_task(TasksCase): - - def test_apply_throw(self): - with self.assertRaises(KeyError): - self.raising.apply(throw=True) - - def test_apply_with_CELERY_EAGER_PROPAGATES_EXCEPTIONS(self): - self.app.conf.CELERY_EAGER_PROPAGATES_EXCEPTIONS = True - with self.assertRaises(KeyError): - self.raising.apply() - - def test_apply(self): - self.increment_counter.count = 0 - - e = self.increment_counter.apply() - self.assertIsInstance(e, EagerResult) - self.assertEqual(e.get(), 1) - - e = self.increment_counter.apply(args=[1]) - self.assertEqual(e.get(), 2) - - e = self.increment_counter.apply(kwargs={'increment_by': 4}) - self.assertEqual(e.get(), 6) - - self.assertTrue(e.successful()) - self.assertTrue(e.ready()) - self.assertTrue(repr(e).startswith('<EagerResult:')) - - f = self.raising.apply() - self.assertTrue(f.ready()) - self.assertFalse(f.successful()) - self.assertTrue(f.traceback) - with self.assertRaises(KeyError): - f.get() diff --git a/awx/lib/site-packages/celery/tests/tasks/test_trace.py b/awx/lib/site-packages/celery/tests/tasks/test_trace.py deleted file mode 100644 index 12c6280ef4..0000000000 --- a/awx/lib/site-packages/celery/tests/tasks/test_trace.py +++ /dev/null @@ -1,192 +0,0 @@ -from __future__ import absolute_import - -from celery import uuid -from celery import signals -from celery import states -from celery.exceptions import Ignore, Retry -from celery.app.trace import ( - TraceInfo, - eager_trace_task, - trace_task, - setup_worker_optimizations, - reset_worker_optimizations, -) -from celery.tests.case import AppCase, Mock, patch - - -def trace(app, task, args=(), kwargs={}, propagate=False, **opts): - return eager_trace_task(task, 'id-1', args, kwargs, - propagate=propagate, app=app, **opts) - - -class TraceCase(AppCase): - - def setup(self): - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - @self.app.task(shared=False, ignore_result=True) - def add_cast(x, y): - return x + y - self.add_cast = add_cast - - @self.app.task(shared=False) - def raises(exc): - raise exc - self.raises = raises - - def trace(self, *args, **kwargs): - return trace(self.app, *args, **kwargs) - - -class test_trace(TraceCase): - - def test_trace_successful(self): - retval, info = self.trace(self.add, (2, 2), {}) - self.assertIsNone(info) - self.assertEqual(retval, 4) - - def test_trace_on_success(self): - - @self.app.task(shared=False, on_success=Mock()) - def add_with_success(x, y): - return x + y - - self.trace(add_with_success, (2, 2), {}) - self.assertTrue(add_with_success.on_success.called) - - def test_trace_after_return(self): - - @self.app.task(shared=False, after_return=Mock()) - def add_with_after_return(x, y): - return x + y - - self.trace(add_with_after_return, (2, 2), {}) - self.assertTrue(add_with_after_return.after_return.called) - - def test_with_prerun_receivers(self): - on_prerun = Mock() - signals.task_prerun.connect(on_prerun) - try: - self.trace(self.add, (2, 2), {}) - self.assertTrue(on_prerun.called) - finally: - signals.task_prerun.receivers[:] = [] - - def test_with_postrun_receivers(self): - on_postrun = Mock() - signals.task_postrun.connect(on_postrun) - try: - self.trace(self.add, (2, 2), {}) - self.assertTrue(on_postrun.called) - finally: - signals.task_postrun.receivers[:] = [] - - def test_with_success_receivers(self): - on_success = Mock() - signals.task_success.connect(on_success) - try: - self.trace(self.add, (2, 2), {}) - self.assertTrue(on_success.called) - finally: - signals.task_success.receivers[:] = [] - - def test_when_chord_part(self): - - @self.app.task(shared=False) - def add(x, y): - return x + y - add.backend = Mock() - - self.trace(add, (2, 2), {}, request={'chord': uuid()}) - add.backend.on_chord_part_return.assert_called_with(add, 'SUCCESS', 4) - - def test_when_backend_cleanup_raises(self): - - @self.app.task(shared=False) - def add(x, y): - return x + y - add.backend = Mock(name='backend') - add.backend.process_cleanup.side_effect = KeyError() - self.trace(add, (2, 2), {}, eager=False) - add.backend.process_cleanup.assert_called_with() - add.backend.process_cleanup.side_effect = MemoryError() - with self.assertRaises(MemoryError): - self.trace(add, (2, 2), {}, eager=False) - - def test_when_Ignore(self): - - @self.app.task(shared=False) - def ignored(): - raise Ignore() - - retval, info = self.trace(ignored, (), {}) - self.assertEqual(info.state, states.IGNORED) - - def test_trace_SystemExit(self): - with self.assertRaises(SystemExit): - self.trace(self.raises, (SystemExit(), ), {}) - - def test_trace_Retry(self): - exc = Retry('foo', 'bar') - _, info = self.trace(self.raises, (exc, ), {}) - self.assertEqual(info.state, states.RETRY) - self.assertIs(info.retval, exc) - - def test_trace_exception(self): - exc = KeyError('foo') - _, info = self.trace(self.raises, (exc, ), {}) - self.assertEqual(info.state, states.FAILURE) - self.assertIs(info.retval, exc) - - def test_trace_exception_propagate(self): - with self.assertRaises(KeyError): - self.trace(self.raises, (KeyError('foo'), ), {}, propagate=True) - - @patch('celery.app.trace.build_tracer') - @patch('celery.app.trace.report_internal_error') - def test_outside_body_error(self, report_internal_error, build_tracer): - tracer = Mock() - tracer.side_effect = KeyError('foo') - build_tracer.return_value = tracer - - @self.app.task(shared=False) - def xtask(): - pass - - trace_task(xtask, 'uuid', (), {}) - self.assertTrue(report_internal_error.call_count) - self.assertIs(xtask.__trace__, tracer) - - -class test_TraceInfo(TraceCase): - - class TI(TraceInfo): - __slots__ = TraceInfo.__slots__ + ('__dict__', ) - - def test_handle_error_state(self): - x = self.TI(states.FAILURE) - x.handle_failure = Mock() - x.handle_error_state(self.add_cast) - x.handle_failure.assert_called_with( - self.add_cast, - store_errors=self.add_cast.store_errors_even_if_ignored, - ) - - -class test_stackprotection(AppCase): - - def test_stackprotection(self): - setup_worker_optimizations(self.app) - try: - @self.app.task(shared=False, bind=True) - def foo(self, i): - if i: - return foo(0) - return self.request - - self.assertTrue(foo(1).called_directly) - finally: - reset_worker_optimizations() diff --git a/awx/lib/site-packages/celery/tests/utils/__init__.py b/awx/lib/site-packages/celery/tests/utils/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/utils/test_datastructures.py b/awx/lib/site-packages/celery/tests/utils/test_datastructures.py deleted file mode 100644 index f26fe86f73..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_datastructures.py +++ /dev/null @@ -1,358 +0,0 @@ -from __future__ import absolute_import - -import pickle -import sys - -from billiard.einfo import ExceptionInfo -from time import time - -from celery.datastructures import ( - LimitedSet, - AttributeDict, - DictAttribute, - ConfigurationView, - DependencyGraph, -) -from celery.five import items - -from celery.tests.case import Case, Mock, WhateverIO, SkipTest, patch - - -class Object(object): - pass - - -class test_DictAttribute(Case): - - def test_get_set_keys_values_items(self): - x = DictAttribute(Object()) - x['foo'] = 'The quick brown fox' - self.assertEqual(x['foo'], 'The quick brown fox') - self.assertEqual(x['foo'], x.obj.foo) - self.assertEqual(x.get('foo'), 'The quick brown fox') - self.assertIsNone(x.get('bar')) - with self.assertRaises(KeyError): - x['bar'] - x.foo = 'The quick yellow fox' - self.assertEqual(x['foo'], 'The quick yellow fox') - self.assertIn( - ('foo', 'The quick yellow fox'), - list(x.items()), - ) - self.assertIn('foo', list(x.keys())) - self.assertIn('The quick yellow fox', list(x.values())) - - def test_setdefault(self): - x = DictAttribute(Object()) - self.assertEqual(x.setdefault('foo', 'NEW'), 'NEW') - self.assertEqual(x.setdefault('foo', 'XYZ'), 'NEW') - - def test_contains(self): - x = DictAttribute(Object()) - x['foo'] = 1 - self.assertIn('foo', x) - self.assertNotIn('bar', x) - - def test_items(self): - obj = Object() - obj.attr1 = 1 - x = DictAttribute(obj) - x['attr2'] = 2 - self.assertEqual(x['attr1'], 1) - self.assertEqual(x['attr2'], 2) - - -class test_ConfigurationView(Case): - - def setUp(self): - self.view = ConfigurationView({'changed_key': 1, - 'both': 2}, - [{'default_key': 1, - 'both': 1}]) - - def test_setdefault(self): - self.assertEqual(self.view.setdefault('both', 36), 2) - self.assertEqual(self.view.setdefault('new', 36), 36) - - def test_get(self): - self.assertEqual(self.view.get('both'), 2) - sp = object() - self.assertIs(self.view.get('nonexisting', sp), sp) - - def test_update(self): - changes = dict(self.view.changes) - self.view.update(a=1, b=2, c=3) - self.assertDictEqual(self.view.changes, - dict(changes, a=1, b=2, c=3)) - - def test_contains(self): - self.assertIn('changed_key', self.view) - self.assertIn('default_key', self.view) - self.assertNotIn('new', self.view) - - def test_repr(self): - self.assertIn('changed_key', repr(self.view)) - self.assertIn('default_key', repr(self.view)) - - def test_iter(self): - expected = {'changed_key': 1, - 'default_key': 1, - 'both': 2} - self.assertDictEqual(dict(items(self.view)), expected) - self.assertItemsEqual(list(iter(self.view)), - list(expected.keys())) - self.assertItemsEqual(list(self.view.keys()), list(expected.keys())) - self.assertItemsEqual( - list(self.view.values()), - list(expected.values()), - ) - self.assertIn('changed_key', list(self.view.keys())) - self.assertIn(2, list(self.view.values())) - self.assertIn(('both', 2), list(self.view.items())) - - def test_add_defaults_dict(self): - defaults = {'foo': 10} - self.view.add_defaults(defaults) - self.assertEqual(self.view.foo, 10) - - def test_add_defaults_object(self): - defaults = Object() - defaults.foo = 10 - self.view.add_defaults(defaults) - self.assertEqual(self.view.foo, 10) - - def test_clear(self): - self.view.clear() - self.assertEqual(self.view.both, 1) - self.assertNotIn('changed_key', self.view) - - def test_bool(self): - self.assertTrue(bool(self.view)) - self.view._order[:] = [] - self.assertFalse(bool(self.view)) - - def test_len(self): - self.assertEqual(len(self.view), 3) - self.view.KEY = 33 - self.assertEqual(len(self.view), 4) - self.view.clear() - self.assertEqual(len(self.view), 2) - - def test_isa_mapping(self): - from collections import Mapping - self.assertTrue(issubclass(ConfigurationView, Mapping)) - - def test_isa_mutable_mapping(self): - from collections import MutableMapping - self.assertTrue(issubclass(ConfigurationView, MutableMapping)) - - -class test_ExceptionInfo(Case): - - def test_exception_info(self): - - try: - raise LookupError('The quick brown fox jumps...') - except Exception: - einfo = ExceptionInfo() - self.assertEqual(str(einfo), einfo.traceback) - self.assertIsInstance(einfo.exception, LookupError) - self.assertTupleEqual( - einfo.exception.args, ('The quick brown fox jumps...', ), - ) - self.assertTrue(einfo.traceback) - - r = repr(einfo) - self.assertTrue(r) - - -class test_LimitedSet(Case): - - def setUp(self): - if sys.platform == 'win32': - raise SkipTest('Not working on Windows') - - def test_add(self): - if sys.platform == 'win32': - raise SkipTest('Not working properly on Windows') - s = LimitedSet(maxlen=2) - s.add('foo') - s.add('bar') - for n in 'foo', 'bar': - self.assertIn(n, s) - s.add('baz') - for n in 'bar', 'baz': - self.assertIn(n, s) - self.assertNotIn('foo', s) - - def test_purge(self): - s = LimitedSet(maxlen=None) - [s.add(i) for i in range(10)] - s.maxlen = 2 - s.purge(1) - self.assertEqual(len(s), 9) - s.purge(None) - self.assertEqual(len(s), 2) - - # expired - s = LimitedSet(maxlen=None, expires=1) - [s.add(i) for i in range(10)] - s.maxlen = 2 - s.purge(1, now=lambda: time() + 100) - self.assertEqual(len(s), 9) - s.purge(None, now=lambda: time() + 100) - self.assertEqual(len(s), 2) - - # not expired - s = LimitedSet(maxlen=None, expires=1) - [s.add(i) for i in range(10)] - s.maxlen = 2 - s.purge(1, now=lambda: time() - 100) - self.assertEqual(len(s), 10) - s.purge(None, now=lambda: time() - 100) - self.assertEqual(len(s), 10) - - s = LimitedSet(maxlen=None) - [s.add(i) for i in range(10)] - s.maxlen = 2 - with patch('celery.datastructures.heappop') as hp: - hp.side_effect = IndexError() - s.purge() - hp.assert_called_with(s._heap) - with patch('celery.datastructures.heappop') as hp: - s._data = dict((i * 2, i * 2) for i in range(10)) - s.purge() - self.assertEqual(hp.call_count, 10) - - def test_pickleable(self): - s = LimitedSet(maxlen=2) - s.add('foo') - s.add('bar') - self.assertEqual(pickle.loads(pickle.dumps(s)), s) - - def test_iter(self): - if sys.platform == 'win32': - raise SkipTest('Not working on Windows') - s = LimitedSet(maxlen=3) - items = ['foo', 'bar', 'baz', 'xaz'] - for item in items: - s.add(item) - l = list(iter(s)) - for item in items[1:]: - self.assertIn(item, l) - self.assertNotIn('foo', l) - self.assertListEqual(l, items[1:], 'order by insertion time') - - def test_repr(self): - s = LimitedSet(maxlen=2) - items = 'foo', 'bar' - for item in items: - s.add(item) - self.assertIn('LimitedSet(', repr(s)) - - def test_discard(self): - s = LimitedSet(maxlen=2) - s.add('foo') - s.discard('foo') - self.assertNotIn('foo', s) - s.discard('foo') - - def test_clear(self): - s = LimitedSet(maxlen=2) - s.add('foo') - s.add('bar') - self.assertEqual(len(s), 2) - s.clear() - self.assertFalse(s) - - def test_update(self): - s1 = LimitedSet(maxlen=2) - s1.add('foo') - s1.add('bar') - - s2 = LimitedSet(maxlen=2) - s2.update(s1) - self.assertItemsEqual(list(s2), ['foo', 'bar']) - - s2.update(['bla']) - self.assertItemsEqual(list(s2), ['bla', 'bar']) - - s2.update(['do', 're']) - self.assertItemsEqual(list(s2), ['do', 're']) - - def test_as_dict(self): - s = LimitedSet(maxlen=2) - s.add('foo') - self.assertIsInstance(s.as_dict(), dict) - - -class test_AttributeDict(Case): - - def test_getattr__setattr(self): - x = AttributeDict({'foo': 'bar'}) - self.assertEqual(x['foo'], 'bar') - with self.assertRaises(AttributeError): - x.bar - x.bar = 'foo' - self.assertEqual(x['bar'], 'foo') - - -class test_DependencyGraph(Case): - - def graph1(self): - return DependencyGraph([ - ('A', []), - ('B', []), - ('C', ['A']), - ('D', ['C', 'B']), - ]) - - def test_repr(self): - self.assertTrue(repr(self.graph1())) - - def test_topsort(self): - order = self.graph1().topsort() - # C must start before D - self.assertLess(order.index('C'), order.index('D')) - # and B must start before D - self.assertLess(order.index('B'), order.index('D')) - # and A must start before C - self.assertLess(order.index('A'), order.index('C')) - - def test_edges(self): - self.assertItemsEqual( - list(self.graph1().edges()), - ['C', 'D'], - ) - - def test_connect(self): - x, y = self.graph1(), self.graph1() - x.connect(y) - - def test_valency_of_when_missing(self): - x = self.graph1() - self.assertEqual(x.valency_of('foobarbaz'), 0) - - def test_format(self): - x = self.graph1() - x.formatter = Mock() - obj = Mock() - self.assertTrue(x.format(obj)) - x.formatter.assert_called_with(obj) - x.formatter = None - self.assertIs(x.format(obj), obj) - - def test_items(self): - self.assertDictEqual( - dict(items(self.graph1())), - {'A': [], 'B': [], 'C': ['A'], 'D': ['C', 'B']}, - ) - - def test_repr_node(self): - x = self.graph1() - self.assertTrue(x.repr_node('fasdswewqewq')) - - def test_to_dot(self): - s = WhateverIO() - self.graph1().to_dot(s) - self.assertTrue(s.getvalue()) diff --git a/awx/lib/site-packages/celery/tests/utils/test_dispatcher.py b/awx/lib/site-packages/celery/tests/utils/test_dispatcher.py deleted file mode 100644 index 72a36f3b33..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_dispatcher.py +++ /dev/null @@ -1,138 +0,0 @@ -from __future__ import absolute_import - - -import gc -import sys -import time - -from celery.utils.dispatch import Signal -from celery.tests.case import Case - - -if sys.platform.startswith('java'): - - def garbage_collect(): - # Some JVM GCs will execute finalizers in a different thread, meaning - # we need to wait for that to complete before we go on looking for the - # effects of that. - gc.collect() - time.sleep(0.1) - -elif hasattr(sys, 'pypy_version_info'): - - def garbage_collect(): # noqa - # Collecting weakreferences can take two collections on PyPy. - gc.collect() - gc.collect() -else: - - def garbage_collect(): # noqa - gc.collect() - - -def receiver_1_arg(val, **kwargs): - return val - - -class Callable(object): - - def __call__(self, val, **kwargs): - return val - - def a(self, val, **kwargs): - return val - -a_signal = Signal(providing_args=['val']) - - -class DispatcherTests(Case): - """Test suite for dispatcher (barely started)""" - - def _testIsClean(self, signal): - """Assert that everything has been cleaned up automatically""" - self.assertEqual(signal.receivers, []) - - # force cleanup just in case - signal.receivers = [] - - def test_exact(self): - a_signal.connect(receiver_1_arg, sender=self) - expected = [(receiver_1_arg, 'test')] - result = a_signal.send(sender=self, val='test') - self.assertEqual(result, expected) - a_signal.disconnect(receiver_1_arg, sender=self) - self._testIsClean(a_signal) - - def test_ignored_sender(self): - a_signal.connect(receiver_1_arg) - expected = [(receiver_1_arg, 'test')] - result = a_signal.send(sender=self, val='test') - self.assertEqual(result, expected) - a_signal.disconnect(receiver_1_arg) - self._testIsClean(a_signal) - - def test_garbage_collected(self): - a = Callable() - a_signal.connect(a.a, sender=self) - expected = [] - del a - garbage_collect() - result = a_signal.send(sender=self, val='test') - self.assertEqual(result, expected) - self._testIsClean(a_signal) - - def test_multiple_registration(self): - a = Callable() - a_signal.connect(a) - a_signal.connect(a) - a_signal.connect(a) - a_signal.connect(a) - a_signal.connect(a) - a_signal.connect(a) - result = a_signal.send(sender=self, val='test') - self.assertEqual(len(result), 1) - self.assertEqual(len(a_signal.receivers), 1) - del a - del result - garbage_collect() - self._testIsClean(a_signal) - - def test_uid_registration(self): - - def uid_based_receiver_1(**kwargs): - pass - - def uid_based_receiver_2(**kwargs): - pass - - a_signal.connect(uid_based_receiver_1, dispatch_uid='uid') - a_signal.connect(uid_based_receiver_2, dispatch_uid='uid') - self.assertEqual(len(a_signal.receivers), 1) - a_signal.disconnect(dispatch_uid='uid') - self._testIsClean(a_signal) - - def test_robust(self): - - def fails(val, **kwargs): - raise ValueError('this') - - a_signal.connect(fails) - result = a_signal.send_robust(sender=self, val='test') - err = result[0][1] - self.assertTrue(isinstance(err, ValueError)) - self.assertEqual(err.args, ('this',)) - a_signal.disconnect(fails) - self._testIsClean(a_signal) - - def test_disconnection(self): - receiver_1 = Callable() - receiver_2 = Callable() - receiver_3 = Callable() - a_signal.connect(receiver_1) - a_signal.connect(receiver_2) - a_signal.connect(receiver_3) - a_signal.disconnect(receiver_1) - del receiver_2 - garbage_collect() - a_signal.disconnect(receiver_3) - self._testIsClean(a_signal) diff --git a/awx/lib/site-packages/celery/tests/utils/test_encoding.py b/awx/lib/site-packages/celery/tests/utils/test_encoding.py deleted file mode 100644 index bdd568982d..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_encoding.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from celery.utils import encoding -from celery.tests.case import Case - - -class test_encoding(Case): - - def test_safe_str(self): - self.assertTrue(encoding.safe_str(object())) - self.assertTrue(encoding.safe_str('foo')) - - def test_safe_repr(self): - self.assertTrue(encoding.safe_repr(object())) - - class foo(object): - def __repr__(self): - raise ValueError('foo') - - self.assertTrue(encoding.safe_repr(foo())) diff --git a/awx/lib/site-packages/celery/tests/utils/test_functional.py b/awx/lib/site-packages/celery/tests/utils/test_functional.py deleted file mode 100644 index 79085417c5..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_functional.py +++ /dev/null @@ -1,180 +0,0 @@ -from __future__ import absolute_import - -import pickle - -from kombu.utils.functional import lazy - -from celery.five import THREAD_TIMEOUT_MAX, items, range, nextfun -from celery.utils.functional import ( - LRUCache, - firstmethod, - first, - mlazy, - padlist, - maybe_list, -) - -from celery.tests.case import Case - - -class test_LRUCache(Case): - - def test_expires(self): - limit = 100 - x = LRUCache(limit=limit) - slots = list(range(limit * 2)) - for i in slots: - x[i] = i - self.assertListEqual(list(x.keys()), list(slots[limit:])) - self.assertTrue(x.items()) - self.assertTrue(x.values()) - - def test_is_pickleable(self): - x = LRUCache(limit=10) - x.update(luke=1, leia=2) - y = pickle.loads(pickle.dumps(x)) - self.assertEqual(y.limit, y.limit) - self.assertEqual(y, x) - - def test_update_expires(self): - limit = 100 - x = LRUCache(limit=limit) - slots = list(range(limit * 2)) - for i in slots: - x.update({i: i}) - - self.assertListEqual(list(x.keys()), list(slots[limit:])) - - def test_least_recently_used(self): - x = LRUCache(3) - - x[1], x[2], x[3] = 1, 2, 3 - self.assertEqual(list(x.keys()), [1, 2, 3]) - - x[4], x[5] = 4, 5 - self.assertEqual(list(x.keys()), [3, 4, 5]) - - # access 3, which makes it the last used key. - x[3] - x[6] = 6 - self.assertEqual(list(x.keys()), [5, 3, 6]) - - x[7] = 7 - self.assertEqual(list(x.keys()), [3, 6, 7]) - - def assertSafeIter(self, method, interval=0.01, size=10000): - from threading import Thread, Event - from time import sleep - x = LRUCache(size) - x.update(zip(range(size), range(size))) - - class Burglar(Thread): - - def __init__(self, cache): - self.cache = cache - self.__is_shutdown = Event() - self.__is_stopped = Event() - Thread.__init__(self) - - def run(self): - while not self.__is_shutdown.isSet(): - try: - self.cache.data.popitem(last=False) - except KeyError: - break - self.__is_stopped.set() - - def stop(self): - self.__is_shutdown.set() - self.__is_stopped.wait() - self.join(THREAD_TIMEOUT_MAX) - - burglar = Burglar(x) - burglar.start() - try: - for _ in getattr(x, method)(): - sleep(0.0001) - finally: - burglar.stop() - - def test_safe_to_remove_while_iteritems(self): - self.assertSafeIter('iteritems') - - def test_safe_to_remove_while_keys(self): - self.assertSafeIter('keys') - - def test_safe_to_remove_while_itervalues(self): - self.assertSafeIter('itervalues') - - def test_items(self): - c = LRUCache() - c.update(a=1, b=2, c=3) - self.assertTrue(list(items(c))) - - -class test_utils(Case): - - def test_padlist(self): - self.assertListEqual( - padlist(['George', 'Costanza', 'NYC'], 3), - ['George', 'Costanza', 'NYC'], - ) - self.assertListEqual( - padlist(['George', 'Costanza'], 3), - ['George', 'Costanza', None], - ) - self.assertListEqual( - padlist(['George', 'Costanza', 'NYC'], 4, default='Earth'), - ['George', 'Costanza', 'NYC', 'Earth'], - ) - - def test_firstmethod_AttributeError(self): - self.assertIsNone(firstmethod('foo')([object()])) - - def test_firstmethod_handles_lazy(self): - - class A(object): - - def __init__(self, value=None): - self.value = value - - def m(self): - return self.value - - self.assertEqual('four', firstmethod('m')([ - A(), A(), A(), A('four'), A('five')])) - self.assertEqual('four', firstmethod('m')([ - A(), A(), A(), lazy(lambda: A('four')), A('five')])) - - def test_first(self): - iterations = [0] - - def predicate(value): - iterations[0] += 1 - if value == 5: - return True - return False - - self.assertEqual(5, first(predicate, range(10))) - self.assertEqual(iterations[0], 6) - - iterations[0] = 0 - self.assertIsNone(first(predicate, range(10, 20))) - self.assertEqual(iterations[0], 10) - - def test_maybe_list(self): - self.assertEqual(maybe_list(1), [1]) - self.assertEqual(maybe_list([1]), [1]) - self.assertIsNone(maybe_list(None)) - - -class test_mlazy(Case): - - def test_is_memoized(self): - - it = iter(range(20, 30)) - p = mlazy(nextfun(it)) - self.assertEqual(p(), 20) - self.assertTrue(p.evaluated) - self.assertEqual(p(), 20) - self.assertEqual(repr(p), '20') diff --git a/awx/lib/site-packages/celery/tests/utils/test_imports.py b/awx/lib/site-packages/celery/tests/utils/test_imports.py deleted file mode 100644 index e7d88bc098..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_imports.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import absolute_import - -from celery.utils.imports import ( - qualname, - reload_from_cwd, - module_file, - find_module, - NotAPackage, -) - -from celery.tests.case import Case, Mock, patch - - -class test_import_utils(Case): - - def test_find_module(self): - self.assertTrue(find_module('celery')) - imp = Mock() - imp.return_value = None - with self.assertRaises(NotAPackage): - find_module('foo.bar.baz', imp=imp) - - def test_qualname(self): - Class = type('Fox', (object, ), {'__module__': 'quick.brown'}) - self.assertEqual(qualname(Class), 'quick.brown.Fox') - self.assertEqual(qualname(Class()), 'quick.brown.Fox') - - @patch('celery.utils.imports.reload') - def test_reload_from_cwd(self, reload): - reload_from_cwd('foo') - self.assertTrue(reload.called) - - def test_reload_from_cwd_custom_reloader(self): - reload = Mock() - reload_from_cwd('foo', reload) - self.assertTrue(reload.called) - - def test_module_file(self): - m1 = Mock() - m1.__file__ = '/opt/foo/xyz.pyc' - self.assertEqual(module_file(m1), '/opt/foo/xyz.py') - m2 = Mock() - m2.__file__ = '/opt/foo/xyz.py' - self.assertEqual(module_file(m1), '/opt/foo/xyz.py') diff --git a/awx/lib/site-packages/celery/tests/utils/test_local.py b/awx/lib/site-packages/celery/tests/utils/test_local.py deleted file mode 100644 index 2b50efcdae..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_local.py +++ /dev/null @@ -1,363 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import sys - -from celery.five import string, long_t -from celery.local import ( - Proxy, - PromiseProxy, - maybe_evaluate, - try_import, -) -from celery.tests.case import Case, Mock - -PY3 = sys.version_info[0] == 3 - - -class test_try_import(Case): - - def test_imports(self): - self.assertTrue(try_import(__name__)) - - def test_when_default(self): - default = object() - self.assertIs(try_import('foobar.awqewqe.asdwqewq', default), default) - - -class test_Proxy(Case): - - def test_std_class_attributes(self): - self.assertEqual(Proxy.__name__, 'Proxy') - self.assertEqual(Proxy.__module__, 'celery.local') - self.assertIsInstance(Proxy.__doc__, str) - - def test_name(self): - - def real(): - """real function""" - return 'REAL' - - x = Proxy(lambda: real, name='xyz') - self.assertEqual(x.__name__, 'xyz') - - y = Proxy(lambda: real) - self.assertEqual(y.__name__, 'real') - - self.assertEqual(x.__doc__, 'real function') - - self.assertEqual(x.__class__, type(real)) - self.assertEqual(x.__dict__, real.__dict__) - self.assertEqual(repr(x), repr(real)) - self.assertTrue(x.__module__) - - def test_get_current_local(self): - x = Proxy(lambda: 10) - object.__setattr__(x, '_Proxy_local', Mock()) - self.assertTrue(x._get_current_object()) - - def test_bool(self): - - class X(object): - - def __bool__(self): - return False - __nonzero__ = __bool__ - - x = Proxy(lambda: X()) - self.assertFalse(x) - - def test_slots(self): - - class X(object): - __slots__ = () - - x = Proxy(X) - with self.assertRaises(AttributeError): - x.__dict__ - - def test_unicode(self): - - class X(object): - - def __unicode__(self): - return 'UNICODE' - __str__ = __unicode__ - - def __repr__(self): - return 'REPR' - - x = Proxy(lambda: X()) - self.assertEqual(string(x), 'UNICODE') - del(X.__unicode__) - del(X.__str__) - self.assertEqual(string(x), 'REPR') - - def test_dir(self): - - class X(object): - - def __dir__(self): - return ['a', 'b', 'c'] - - x = Proxy(lambda: X()) - self.assertListEqual(dir(x), ['a', 'b', 'c']) - - class Y(object): - - def __dir__(self): - raise RuntimeError() - y = Proxy(lambda: Y()) - self.assertListEqual(dir(y), []) - - def test_getsetdel_attr(self): - - class X(object): - a = 1 - b = 2 - c = 3 - - def __dir__(self): - return ['a', 'b', 'c'] - - v = X() - - x = Proxy(lambda: v) - self.assertListEqual(x.__members__, ['a', 'b', 'c']) - self.assertEqual(x.a, 1) - self.assertEqual(x.b, 2) - self.assertEqual(x.c, 3) - - setattr(x, 'a', 10) - self.assertEqual(x.a, 10) - - del(x.a) - self.assertEqual(x.a, 1) - - def test_dictproxy(self): - v = {} - x = Proxy(lambda: v) - x['foo'] = 42 - self.assertEqual(x['foo'], 42) - self.assertEqual(len(x), 1) - self.assertIn('foo', x) - del(x['foo']) - with self.assertRaises(KeyError): - x['foo'] - self.assertTrue(iter(x)) - - def test_listproxy(self): - v = [] - x = Proxy(lambda: v) - x.append(1) - x.extend([2, 3, 4]) - self.assertEqual(x[0], 1) - self.assertEqual(x[:-1], [1, 2, 3]) - del(x[-1]) - self.assertEqual(x[:-1], [1, 2]) - x[0] = 10 - self.assertEqual(x[0], 10) - self.assertIn(10, x) - self.assertEqual(len(x), 3) - self.assertTrue(iter(x)) - x[0:2] = [1, 2] - del(x[0:2]) - self.assertTrue(str(x)) - if sys.version_info[0] < 3: - self.assertEqual(x.__cmp__(object()), -1) - - def test_complex_cast(self): - - class O(object): - - def __complex__(self): - return complex(10.333) - - o = Proxy(O) - self.assertEqual(o.__complex__(), complex(10.333)) - - def test_index(self): - - class O(object): - - def __index__(self): - return 1 - - o = Proxy(O) - self.assertEqual(o.__index__(), 1) - - def test_coerce(self): - - class O(object): - - def __coerce__(self, other): - return self, other - - o = Proxy(O) - self.assertTrue(o.__coerce__(3)) - - def test_int(self): - self.assertEqual(Proxy(lambda: 10) + 1, Proxy(lambda: 11)) - self.assertEqual(Proxy(lambda: 10) - 1, Proxy(lambda: 9)) - self.assertEqual(Proxy(lambda: 10) * 2, Proxy(lambda: 20)) - self.assertEqual(Proxy(lambda: 10) ** 2, Proxy(lambda: 100)) - self.assertEqual(Proxy(lambda: 20) / 2, Proxy(lambda: 10)) - self.assertEqual(Proxy(lambda: 20) // 2, Proxy(lambda: 10)) - self.assertEqual(Proxy(lambda: 11) % 2, Proxy(lambda: 1)) - self.assertEqual(Proxy(lambda: 10) << 2, Proxy(lambda: 40)) - self.assertEqual(Proxy(lambda: 10) >> 2, Proxy(lambda: 2)) - self.assertEqual(Proxy(lambda: 10) ^ 7, Proxy(lambda: 13)) - self.assertEqual(Proxy(lambda: 10) | 40, Proxy(lambda: 42)) - self.assertEqual(~Proxy(lambda: 10), Proxy(lambda: -11)) - self.assertEqual(-Proxy(lambda: 10), Proxy(lambda: -10)) - self.assertEqual(+Proxy(lambda: -10), Proxy(lambda: -10)) - self.assertTrue(Proxy(lambda: 10) < Proxy(lambda: 20)) - self.assertTrue(Proxy(lambda: 20) > Proxy(lambda: 10)) - self.assertTrue(Proxy(lambda: 10) >= Proxy(lambda: 10)) - self.assertTrue(Proxy(lambda: 10) <= Proxy(lambda: 10)) - self.assertTrue(Proxy(lambda: 10) == Proxy(lambda: 10)) - self.assertTrue(Proxy(lambda: 20) != Proxy(lambda: 10)) - self.assertTrue(Proxy(lambda: 100).__divmod__(30)) - self.assertTrue(Proxy(lambda: 100).__truediv__(30)) - self.assertTrue(abs(Proxy(lambda: -100))) - - x = Proxy(lambda: 10) - x -= 1 - self.assertEqual(x, 9) - x = Proxy(lambda: 9) - x += 1 - self.assertEqual(x, 10) - x = Proxy(lambda: 10) - x *= 2 - self.assertEqual(x, 20) - x = Proxy(lambda: 20) - x /= 2 - self.assertEqual(x, 10) - x = Proxy(lambda: 10) - x %= 2 - self.assertEqual(x, 0) - x = Proxy(lambda: 10) - x <<= 3 - self.assertEqual(x, 80) - x = Proxy(lambda: 80) - x >>= 4 - self.assertEqual(x, 5) - x = Proxy(lambda: 5) - x ^= 1 - self.assertEqual(x, 4) - x = Proxy(lambda: 4) - x **= 4 - self.assertEqual(x, 256) - x = Proxy(lambda: 256) - x //= 2 - self.assertEqual(x, 128) - x = Proxy(lambda: 128) - x |= 2 - self.assertEqual(x, 130) - x = Proxy(lambda: 130) - x &= 10 - self.assertEqual(x, 2) - - x = Proxy(lambda: 10) - self.assertEqual(type(x.__float__()), float) - self.assertEqual(type(x.__int__()), int) - if not PY3: - self.assertEqual(type(x.__long__()), long_t) - self.assertTrue(hex(x)) - self.assertTrue(oct(x)) - - def test_hash(self): - - class X(object): - - def __hash__(self): - return 1234 - - self.assertEqual(hash(Proxy(lambda: X())), 1234) - - def test_call(self): - - class X(object): - - def __call__(self): - return 1234 - - self.assertEqual(Proxy(lambda: X())(), 1234) - - def test_context(self): - - class X(object): - entered = exited = False - - def __enter__(self): - self.entered = True - return 1234 - - def __exit__(self, *exc_info): - self.exited = True - - v = X() - x = Proxy(lambda: v) - with x as val: - self.assertEqual(val, 1234) - self.assertTrue(x.entered) - self.assertTrue(x.exited) - - def test_reduce(self): - - class X(object): - - def __reduce__(self): - return 123 - - x = Proxy(lambda: X()) - self.assertEqual(x.__reduce__(), 123) - - -class test_PromiseProxy(Case): - - def test_only_evaluated_once(self): - - class X(object): - attr = 123 - evals = 0 - - def __init__(self): - self.__class__.evals += 1 - - p = PromiseProxy(X) - self.assertEqual(p.attr, 123) - self.assertEqual(p.attr, 123) - self.assertEqual(X.evals, 1) - - def test_callbacks(self): - source = Mock(name='source') - p = PromiseProxy(source) - cbA = Mock(name='cbA') - cbB = Mock(name='cbB') - cbC = Mock(name='cbC') - p.__then__(cbA, p) - p.__then__(cbB, p) - self.assertFalse(p.__evaluated__()) - self.assertTrue(object.__getattribute__(p, '__pending__')) - - self.assertTrue(repr(p)) - with self.assertRaises(AttributeError): - object.__getattribute__(p, '__pending__') - cbA.assert_called_with(p) - cbB.assert_called_with(p) - - self.assertTrue(p.__evaluated__()) - p.__then__(cbC, p) - cbC.assert_called_with(p) - - with self.assertRaises(AttributeError): - object.__getattribute__(p, '__pending__') - - def test_maybe_evaluate(self): - x = PromiseProxy(lambda: 30) - self.assertFalse(x.__evaluated__()) - self.assertEqual(maybe_evaluate(x), 30) - self.assertEqual(maybe_evaluate(x), 30) - - self.assertEqual(maybe_evaluate(30), 30) - self.assertTrue(x.__evaluated__()) diff --git a/awx/lib/site-packages/celery/tests/utils/test_mail.py b/awx/lib/site-packages/celery/tests/utils/test_mail.py deleted file mode 100644 index 4006fb0b5e..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_mail.py +++ /dev/null @@ -1,53 +0,0 @@ -from __future__ import absolute_import - -from celery.utils.mail import Message, Mailer, SSLError - -from celery.tests.case import Case, Mock, patch - - -msg = Message(to='george@vandelay.com', sender='elaine@pendant.com', - subject="What's up with Jerry?", body='???!') - - -class test_Message(Case): - - def test_repr(self): - self.assertTrue(repr(msg)) - - def test_str(self): - self.assertTrue(str(msg)) - - -class test_Mailer(Case): - - def test_send_wrapper(self): - mailer = Mailer() - mailer._send = Mock() - mailer.send(msg) - mailer._send.assert_called_with(msg) - - @patch('smtplib.SMTP_SSL', create=True) - def test_send_ssl_tls(self, SMTP_SSL): - mailer = Mailer(use_ssl=True, use_tls=True) - client = SMTP_SSL.return_value = Mock() - mailer._send(msg) - self.assertTrue(client.starttls.called) - self.assertEqual(client.ehlo.call_count, 2) - client.quit.assert_called_with() - client.sendmail.assert_called_with(msg.sender, msg.to, str(msg)) - mailer = Mailer(use_ssl=True, use_tls=True, user='foo', - password='bar') - mailer._send(msg) - client.login.assert_called_with('foo', 'bar') - - @patch('smtplib.SMTP') - def test_send(self, SMTP): - client = SMTP.return_value = Mock() - mailer = Mailer(use_ssl=False, use_tls=False) - mailer._send(msg) - - client.sendmail.assert_called_With(msg.sender, msg.to, str(msg)) - - client.quit.side_effect = SSLError() - mailer._send(msg) - client.close.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/utils/test_pickle.py b/awx/lib/site-packages/celery/tests/utils/test_pickle.py deleted file mode 100644 index 6b65bb3c55..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_pickle.py +++ /dev/null @@ -1,51 +0,0 @@ -from __future__ import absolute_import - -from celery.utils.serialization import pickle -from celery.tests.case import Case - - -class RegularException(Exception): - pass - - -class ArgOverrideException(Exception): - - def __init__(self, message, status_code=10): - self.status_code = status_code - Exception.__init__(self, message, status_code) - - -class test_Pickle(Case): - - def test_pickle_regular_exception(self): - exc = None - try: - raise RegularException('RegularException raised') - except RegularException as exc_: - exc = exc_ - - pickled = pickle.dumps({'exception': exc}) - unpickled = pickle.loads(pickled) - exception = unpickled.get('exception') - self.assertTrue(exception) - self.assertIsInstance(exception, RegularException) - self.assertTupleEqual(exception.args, ('RegularException raised', )) - - def test_pickle_arg_override_exception(self): - - exc = None - try: - raise ArgOverrideException( - 'ArgOverrideException raised', status_code=100, - ) - except ArgOverrideException as exc_: - exc = exc_ - - pickled = pickle.dumps({'exception': exc}) - unpickled = pickle.loads(pickled) - exception = unpickled.get('exception') - self.assertTrue(exception) - self.assertIsInstance(exception, ArgOverrideException) - self.assertTupleEqual(exception.args, ( - 'ArgOverrideException raised', 100)) - self.assertEqual(exception.status_code, 100) diff --git a/awx/lib/site-packages/celery/tests/utils/test_platforms.py b/awx/lib/site-packages/celery/tests/utils/test_platforms.py deleted file mode 100644 index 4e27efd7b0..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_platforms.py +++ /dev/null @@ -1,701 +0,0 @@ -from __future__ import absolute_import - -import errno -import os -import sys -import signal - -from celery import _find_option_with_arg -from celery import platforms -from celery.five import open_fqdn -from celery.platforms import ( - get_fdmax, - ignore_errno, - set_process_title, - signals, - maybe_drop_privileges, - setuid, - setgid, - initgroups, - parse_uid, - parse_gid, - detached, - DaemonContext, - create_pidlock, - Pidfile, - LockFailed, - setgroups, - _setgroups_hack, - close_open_fds, -) - -try: - import resource -except ImportError: # pragma: no cover - resource = None # noqa - -from celery.tests.case import ( - Case, WhateverIO, Mock, SkipTest, - call, override_stdouts, mock_open, patch, -) - - -class test_find_option_with_arg(Case): - - def test_long_opt(self): - self.assertEqual( - _find_option_with_arg(['--foo=bar'], long_opts=['--foo']), - 'bar' - ) - - def test_short_opt(self): - self.assertEqual( - _find_option_with_arg(['-f', 'bar'], short_opts=['-f']), - 'bar' - ) - - -class test_close_open_fds(Case): - - def test_closes(self): - with patch('os.close') as _close: - with patch('os.closerange', create=True) as closerange: - with patch('celery.platforms.get_fdmax') as fdmax: - fdmax.return_value = 3 - close_open_fds() - if not closerange.called: - _close.assert_has_calls([call(2), call(1), call(0)]) - _close.side_effect = OSError() - _close.side_effect.errno = errno.EBADF - close_open_fds() - - -class test_ignore_errno(Case): - - def test_raises_EBADF(self): - with ignore_errno('EBADF'): - exc = OSError() - exc.errno = errno.EBADF - raise exc - - def test_otherwise(self): - with self.assertRaises(OSError): - with ignore_errno('EBADF'): - exc = OSError() - exc.errno = errno.ENOENT - raise exc - - -class test_set_process_title(Case): - - def when_no_setps(self): - prev = platforms._setproctitle = platforms._setproctitle, None - try: - set_process_title('foo') - finally: - platforms._setproctitle = prev - - -class test_Signals(Case): - - @patch('signal.getsignal') - def test_getitem(self, getsignal): - signals['SIGINT'] - getsignal.assert_called_with(signal.SIGINT) - - def test_supported(self): - self.assertTrue(signals.supported('INT')) - self.assertFalse(signals.supported('SIGIMAGINARY')) - - def test_reset_alarm(self): - if sys.platform == 'win32': - raise SkipTest('signal.alarm not available on Windows') - with patch('signal.alarm') as _alarm: - signals.reset_alarm() - _alarm.assert_called_with(0) - - def test_arm_alarm(self): - if hasattr(signal, 'setitimer'): - with patch('signal.setitimer', create=True) as seti: - signals.arm_alarm(30) - self.assertTrue(seti.called) - - def test_signum(self): - self.assertEqual(signals.signum(13), 13) - self.assertEqual(signals.signum('INT'), signal.SIGINT) - self.assertEqual(signals.signum('SIGINT'), signal.SIGINT) - with self.assertRaises(TypeError): - signals.signum('int') - signals.signum(object()) - - @patch('signal.signal') - def test_ignore(self, set): - signals.ignore('SIGINT') - set.assert_called_with(signals.signum('INT'), signals.ignored) - signals.ignore('SIGTERM') - set.assert_called_with(signals.signum('TERM'), signals.ignored) - - @patch('signal.signal') - def test_setitem(self, set): - handle = lambda *a: a - signals['INT'] = handle - set.assert_called_with(signal.SIGINT, handle) - - @patch('signal.signal') - def test_setitem_raises(self, set): - set.side_effect = ValueError() - signals['INT'] = lambda *a: a - - -if not platforms.IS_WINDOWS: - - class test_get_fdmax(Case): - - @patch('resource.getrlimit') - def test_when_infinity(self, getrlimit): - with patch('os.sysconf') as sysconfig: - sysconfig.side_effect = KeyError() - getrlimit.return_value = [None, resource.RLIM_INFINITY] - default = object() - self.assertIs(get_fdmax(default), default) - - @patch('resource.getrlimit') - def test_when_actual(self, getrlimit): - with patch('os.sysconf') as sysconfig: - sysconfig.side_effect = KeyError() - getrlimit.return_value = [None, 13] - self.assertEqual(get_fdmax(None), 13) - - class test_maybe_drop_privileges(Case): - - @patch('celery.platforms.parse_uid') - @patch('pwd.getpwuid') - @patch('celery.platforms.setgid') - @patch('celery.platforms.setuid') - @patch('celery.platforms.initgroups') - def test_with_uid(self, initgroups, setuid, setgid, - getpwuid, parse_uid): - - class pw_struct(object): - pw_gid = 50001 - - def raise_on_second_call(*args, **kwargs): - setuid.side_effect = OSError() - setuid.side_effect.errno = errno.EPERM - setuid.side_effect = raise_on_second_call - getpwuid.return_value = pw_struct() - parse_uid.return_value = 5001 - maybe_drop_privileges(uid='user') - parse_uid.assert_called_with('user') - getpwuid.assert_called_with(5001) - setgid.assert_called_with(50001) - initgroups.assert_called_with(5001, 50001) - setuid.assert_has_calls([call(5001), call(0)]) - - @patch('celery.platforms.parse_uid') - @patch('celery.platforms.parse_gid') - @patch('celery.platforms.setgid') - @patch('celery.platforms.setuid') - @patch('celery.platforms.initgroups') - def test_with_guid(self, initgroups, setuid, setgid, - parse_gid, parse_uid): - - def raise_on_second_call(*args, **kwargs): - setuid.side_effect = OSError() - setuid.side_effect.errno = errno.EPERM - setuid.side_effect = raise_on_second_call - parse_uid.return_value = 5001 - parse_gid.return_value = 50001 - maybe_drop_privileges(uid='user', gid='group') - parse_uid.assert_called_with('user') - parse_gid.assert_called_with('group') - setgid.assert_called_with(50001) - initgroups.assert_called_with(5001, 50001) - setuid.assert_has_calls([call(5001), call(0)]) - - setuid.side_effect = None - with self.assertRaises(RuntimeError): - maybe_drop_privileges(uid='user', gid='group') - setuid.side_effect = OSError() - setuid.side_effect.errno = errno.EINVAL - with self.assertRaises(OSError): - maybe_drop_privileges(uid='user', gid='group') - - @patch('celery.platforms.setuid') - @patch('celery.platforms.setgid') - @patch('celery.platforms.parse_gid') - def test_only_gid(self, parse_gid, setgid, setuid): - parse_gid.return_value = 50001 - maybe_drop_privileges(gid='group') - parse_gid.assert_called_with('group') - setgid.assert_called_with(50001) - self.assertFalse(setuid.called) - - class test_setget_uid_gid(Case): - - @patch('celery.platforms.parse_uid') - @patch('os.setuid') - def test_setuid(self, _setuid, parse_uid): - parse_uid.return_value = 5001 - setuid('user') - parse_uid.assert_called_with('user') - _setuid.assert_called_with(5001) - - @patch('celery.platforms.parse_gid') - @patch('os.setgid') - def test_setgid(self, _setgid, parse_gid): - parse_gid.return_value = 50001 - setgid('group') - parse_gid.assert_called_with('group') - _setgid.assert_called_with(50001) - - def test_parse_uid_when_int(self): - self.assertEqual(parse_uid(5001), 5001) - - @patch('pwd.getpwnam') - def test_parse_uid_when_existing_name(self, getpwnam): - - class pwent(object): - pw_uid = 5001 - - getpwnam.return_value = pwent() - self.assertEqual(parse_uid('user'), 5001) - - @patch('pwd.getpwnam') - def test_parse_uid_when_nonexisting_name(self, getpwnam): - getpwnam.side_effect = KeyError('user') - - with self.assertRaises(KeyError): - parse_uid('user') - - def test_parse_gid_when_int(self): - self.assertEqual(parse_gid(50001), 50001) - - @patch('grp.getgrnam') - def test_parse_gid_when_existing_name(self, getgrnam): - - class grent(object): - gr_gid = 50001 - - getgrnam.return_value = grent() - self.assertEqual(parse_gid('group'), 50001) - - @patch('grp.getgrnam') - def test_parse_gid_when_nonexisting_name(self, getgrnam): - getgrnam.side_effect = KeyError('group') - - with self.assertRaises(KeyError): - parse_gid('group') - - class test_initgroups(Case): - - @patch('pwd.getpwuid') - @patch('os.initgroups', create=True) - def test_with_initgroups(self, initgroups_, getpwuid): - getpwuid.return_value = ['user'] - initgroups(5001, 50001) - initgroups_.assert_called_with('user', 50001) - - @patch('celery.platforms.setgroups') - @patch('grp.getgrall') - @patch('pwd.getpwuid') - def test_without_initgroups(self, getpwuid, getgrall, setgroups): - prev = getattr(os, 'initgroups', None) - try: - delattr(os, 'initgroups') - except AttributeError: - pass - try: - getpwuid.return_value = ['user'] - - class grent(object): - gr_mem = ['user'] - - def __init__(self, gid): - self.gr_gid = gid - - getgrall.return_value = [grent(1), grent(2), grent(3)] - initgroups(5001, 50001) - setgroups.assert_called_with([1, 2, 3]) - finally: - if prev: - os.initgroups = prev - - class test_detached(Case): - - def test_without_resource(self): - prev, platforms.resource = platforms.resource, None - try: - with self.assertRaises(RuntimeError): - detached() - finally: - platforms.resource = prev - - @patch('celery.platforms._create_pidlock') - @patch('celery.platforms.signals') - @patch('celery.platforms.maybe_drop_privileges') - @patch('os.geteuid') - @patch(open_fqdn) - def test_default(self, open, geteuid, maybe_drop, - signals, pidlock): - geteuid.return_value = 0 - context = detached(uid='user', gid='group') - self.assertIsInstance(context, DaemonContext) - signals.reset.assert_called_with('SIGCLD') - maybe_drop.assert_called_with(uid='user', gid='group') - open.return_value = Mock() - - geteuid.return_value = 5001 - context = detached(uid='user', gid='group', logfile='/foo/bar') - self.assertIsInstance(context, DaemonContext) - self.assertTrue(context.after_chdir) - context.after_chdir() - open.assert_called_with('/foo/bar', 'a') - open.return_value.close.assert_called_with() - - context = detached(pidfile='/foo/bar/pid') - self.assertIsInstance(context, DaemonContext) - self.assertTrue(context.after_chdir) - context.after_chdir() - pidlock.assert_called_with('/foo/bar/pid') - - class test_DaemonContext(Case): - - @patch('os.fork') - @patch('os.setsid') - @patch('os._exit') - @patch('os.chdir') - @patch('os.umask') - @patch('os.close') - @patch('os.closerange') - @patch('os.open') - @patch('os.dup2') - def test_open(self, dup2, open, close, closer, umask, chdir, - _exit, setsid, fork): - x = DaemonContext(workdir='/opt/workdir') - x.stdfds = [0, 1, 2] - - fork.return_value = 0 - with x: - self.assertTrue(x._is_open) - with x: - pass - self.assertEqual(fork.call_count, 2) - setsid.assert_called_with() - self.assertFalse(_exit.called) - - chdir.assert_called_with(x.workdir) - umask.assert_called_with(x.umask) - self.assertTrue(dup2.called) - - fork.reset_mock() - fork.return_value = 1 - x = DaemonContext(workdir='/opt/workdir') - x.stdfds = [0, 1, 2] - with x: - pass - self.assertEqual(fork.call_count, 1) - _exit.assert_called_with(0) - - x = DaemonContext(workdir='/opt/workdir', fake=True) - x.stdfds = [0, 1, 2] - x._detach = Mock() - with x: - pass - self.assertFalse(x._detach.called) - - x.after_chdir = Mock() - with x: - pass - x.after_chdir.assert_called_with() - - class test_Pidfile(Case): - - @patch('celery.platforms.Pidfile') - def test_create_pidlock(self, Pidfile): - p = Pidfile.return_value = Mock() - p.is_locked.return_value = True - p.remove_if_stale.return_value = False - with override_stdouts() as (_, err): - with self.assertRaises(SystemExit): - create_pidlock('/var/pid') - self.assertIn('already exists', err.getvalue()) - - p.remove_if_stale.return_value = True - ret = create_pidlock('/var/pid') - self.assertIs(ret, p) - - def test_context(self): - p = Pidfile('/var/pid') - p.write_pid = Mock() - p.remove = Mock() - - with p as _p: - self.assertIs(_p, p) - p.write_pid.assert_called_with() - p.remove.assert_called_with() - - def test_acquire_raises_LockFailed(self): - p = Pidfile('/var/pid') - p.write_pid = Mock() - p.write_pid.side_effect = OSError() - - with self.assertRaises(LockFailed): - with p: - pass - - @patch('os.path.exists') - def test_is_locked(self, exists): - p = Pidfile('/var/pid') - exists.return_value = True - self.assertTrue(p.is_locked()) - exists.return_value = False - self.assertFalse(p.is_locked()) - - def test_read_pid(self): - with mock_open() as s: - s.write('1816\n') - s.seek(0) - p = Pidfile('/var/pid') - self.assertEqual(p.read_pid(), 1816) - - def test_read_pid_partially_written(self): - with mock_open() as s: - s.write('1816') - s.seek(0) - p = Pidfile('/var/pid') - with self.assertRaises(ValueError): - p.read_pid() - - def test_read_pid_raises_ENOENT(self): - exc = IOError() - exc.errno = errno.ENOENT - with mock_open(side_effect=exc): - p = Pidfile('/var/pid') - self.assertIsNone(p.read_pid()) - - def test_read_pid_raises_IOError(self): - exc = IOError() - exc.errno = errno.EAGAIN - with mock_open(side_effect=exc): - p = Pidfile('/var/pid') - with self.assertRaises(IOError): - p.read_pid() - - def test_read_pid_bogus_pidfile(self): - with mock_open() as s: - s.write('eighteensixteen\n') - s.seek(0) - p = Pidfile('/var/pid') - with self.assertRaises(ValueError): - p.read_pid() - - @patch('os.unlink') - def test_remove(self, unlink): - unlink.return_value = True - p = Pidfile('/var/pid') - p.remove() - unlink.assert_called_with(p.path) - - @patch('os.unlink') - def test_remove_ENOENT(self, unlink): - exc = OSError() - exc.errno = errno.ENOENT - unlink.side_effect = exc - p = Pidfile('/var/pid') - p.remove() - unlink.assert_called_with(p.path) - - @patch('os.unlink') - def test_remove_EACCES(self, unlink): - exc = OSError() - exc.errno = errno.EACCES - unlink.side_effect = exc - p = Pidfile('/var/pid') - p.remove() - unlink.assert_called_with(p.path) - - @patch('os.unlink') - def test_remove_OSError(self, unlink): - exc = OSError() - exc.errno = errno.EAGAIN - unlink.side_effect = exc - p = Pidfile('/var/pid') - with self.assertRaises(OSError): - p.remove() - unlink.assert_called_with(p.path) - - @patch('os.kill') - def test_remove_if_stale_process_alive(self, kill): - p = Pidfile('/var/pid') - p.read_pid = Mock() - p.read_pid.return_value = 1816 - kill.return_value = 0 - self.assertFalse(p.remove_if_stale()) - kill.assert_called_with(1816, 0) - p.read_pid.assert_called_with() - - kill.side_effect = OSError() - kill.side_effect.errno = errno.ENOENT - self.assertFalse(p.remove_if_stale()) - - @patch('os.kill') - def test_remove_if_stale_process_dead(self, kill): - with override_stdouts(): - p = Pidfile('/var/pid') - p.read_pid = Mock() - p.read_pid.return_value = 1816 - p.remove = Mock() - exc = OSError() - exc.errno = errno.ESRCH - kill.side_effect = exc - self.assertTrue(p.remove_if_stale()) - kill.assert_called_with(1816, 0) - p.remove.assert_called_with() - - def test_remove_if_stale_broken_pid(self): - with override_stdouts(): - p = Pidfile('/var/pid') - p.read_pid = Mock() - p.read_pid.side_effect = ValueError() - p.remove = Mock() - - self.assertTrue(p.remove_if_stale()) - p.remove.assert_called_with() - - def test_remove_if_stale_no_pidfile(self): - p = Pidfile('/var/pid') - p.read_pid = Mock() - p.read_pid.return_value = None - p.remove = Mock() - - self.assertTrue(p.remove_if_stale()) - p.remove.assert_called_with() - - @patch('os.fsync') - @patch('os.getpid') - @patch('os.open') - @patch('os.fdopen') - @patch(open_fqdn) - def test_write_pid(self, open_, fdopen, osopen, getpid, fsync): - getpid.return_value = 1816 - osopen.return_value = 13 - w = fdopen.return_value = WhateverIO() - w.close = Mock() - r = open_.return_value = WhateverIO() - r.write('1816\n') - r.seek(0) - - p = Pidfile('/var/pid') - p.write_pid() - w.seek(0) - self.assertEqual(w.readline(), '1816\n') - self.assertTrue(w.close.called) - getpid.assert_called_with() - osopen.assert_called_with(p.path, platforms.PIDFILE_FLAGS, - platforms.PIDFILE_MODE) - fdopen.assert_called_with(13, 'w') - fsync.assert_called_with(13) - open_.assert_called_with(p.path) - - @patch('os.fsync') - @patch('os.getpid') - @patch('os.open') - @patch('os.fdopen') - @patch(open_fqdn) - def test_write_reread_fails(self, open_, fdopen, - osopen, getpid, fsync): - getpid.return_value = 1816 - osopen.return_value = 13 - w = fdopen.return_value = WhateverIO() - w.close = Mock() - r = open_.return_value = WhateverIO() - r.write('11816\n') - r.seek(0) - - p = Pidfile('/var/pid') - with self.assertRaises(LockFailed): - p.write_pid() - - class test_setgroups(Case): - - @patch('os.setgroups', create=True) - def test_setgroups_hack_ValueError(self, setgroups): - - def on_setgroups(groups): - if len(groups) <= 200: - setgroups.return_value = True - return - raise ValueError() - setgroups.side_effect = on_setgroups - _setgroups_hack(list(range(400))) - - setgroups.side_effect = ValueError() - with self.assertRaises(ValueError): - _setgroups_hack(list(range(400))) - - @patch('os.setgroups', create=True) - def test_setgroups_hack_OSError(self, setgroups): - exc = OSError() - exc.errno = errno.EINVAL - - def on_setgroups(groups): - if len(groups) <= 200: - setgroups.return_value = True - return - raise exc - setgroups.side_effect = on_setgroups - - _setgroups_hack(list(range(400))) - - setgroups.side_effect = exc - with self.assertRaises(OSError): - _setgroups_hack(list(range(400))) - - exc2 = OSError() - exc.errno = errno.ESRCH - setgroups.side_effect = exc2 - with self.assertRaises(OSError): - _setgroups_hack(list(range(400))) - - @patch('os.sysconf') - @patch('celery.platforms._setgroups_hack') - def test_setgroups(self, hack, sysconf): - sysconf.return_value = 100 - setgroups(list(range(400))) - hack.assert_called_with(list(range(100))) - - @patch('os.sysconf') - @patch('celery.platforms._setgroups_hack') - def test_setgroups_sysconf_raises(self, hack, sysconf): - sysconf.side_effect = ValueError() - setgroups(list(range(400))) - hack.assert_called_with(list(range(400))) - - @patch('os.getgroups') - @patch('os.sysconf') - @patch('celery.platforms._setgroups_hack') - def test_setgroups_raises_ESRCH(self, hack, sysconf, getgroups): - sysconf.side_effect = ValueError() - esrch = OSError() - esrch.errno = errno.ESRCH - hack.side_effect = esrch - with self.assertRaises(OSError): - setgroups(list(range(400))) - - @patch('os.getgroups') - @patch('os.sysconf') - @patch('celery.platforms._setgroups_hack') - def test_setgroups_raises_EPERM(self, hack, sysconf, getgroups): - sysconf.side_effect = ValueError() - eperm = OSError() - eperm.errno = errno.EPERM - hack.side_effect = eperm - getgroups.return_value = list(range(400)) - setgroups(list(range(400))) - getgroups.assert_called_with() - - getgroups.return_value = [1000] - with self.assertRaises(OSError): - setgroups(list(range(400))) - getgroups.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/utils/test_saferef.py b/awx/lib/site-packages/celery/tests/utils/test_saferef.py deleted file mode 100644 index 9c18d71b16..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_saferef.py +++ /dev/null @@ -1,94 +0,0 @@ -from __future__ import absolute_import - -from celery.five import range -from celery.utils.dispatch.saferef import safe_ref -from celery.tests.case import Case - - -class Class1(object): - - def x(self): - pass - - -def fun(obj): - pass - - -class Class2(object): - - def __call__(self, obj): - pass - - -class SaferefTests(Case): - - def setUp(self): - ts = [] - ss = [] - for x in range(5000): - t = Class1() - ts.append(t) - s = safe_ref(t.x, self._closure) - ss.append(s) - ts.append(fun) - ss.append(safe_ref(fun, self._closure)) - for x in range(30): - t = Class2() - ts.append(t) - s = safe_ref(t, self._closure) - ss.append(s) - self.ts = ts - self.ss = ss - self.closureCount = 0 - - def tearDown(self): - del self.ts - del self.ss - - def test_in(self): - """test_in - - Test the "in" operator for safe references (cmp) - - """ - for t in self.ts[:50]: - self.assertTrue(safe_ref(t.x) in self.ss) - - def test_valid(self): - """test_value - - Test that the references are valid (return instance methods) - - """ - for s in self.ss: - self.assertTrue(s()) - - def test_shortcircuit(self): - """test_shortcircuit - - Test that creation short-circuits to reuse existing references - - """ - sd = {} - for s in self.ss: - sd[s] = 1 - for t in self.ts: - if hasattr(t, 'x'): - self.assertIn(safe_ref(t.x), sd) - else: - self.assertIn(safe_ref(t), sd) - - def test_representation(self): - """test_representation - - Test that the reference object's representation works - - XXX Doesn't currently check the results, just that no error - is raised - """ - repr(self.ss[-1]) - - def _closure(self, ref): - """Dumb utility mechanism to increment deletion counter""" - self.closureCount += 1 diff --git a/awx/lib/site-packages/celery/tests/utils/test_serialization.py b/awx/lib/site-packages/celery/tests/utils/test_serialization.py deleted file mode 100644 index 53dfdadebd..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_serialization.py +++ /dev/null @@ -1,42 +0,0 @@ -from __future__ import absolute_import - -import sys - -from celery.utils.serialization import ( - UnpickleableExceptionWrapper, - get_pickleable_etype, -) - -from celery.tests.case import Case, mask_modules - - -class test_AAPickle(Case): - - def test_no_cpickle(self): - prev = sys.modules.pop('celery.utils.serialization', None) - try: - with mask_modules('cPickle'): - from celery.utils.serialization import pickle - import pickle as orig_pickle - self.assertIs(pickle.dumps, orig_pickle.dumps) - finally: - sys.modules['celery.utils.serialization'] = prev - - -class test_UnpickleExceptionWrapper(Case): - - def test_init(self): - x = UnpickleableExceptionWrapper('foo', 'Bar', [10, lambda x: x]) - self.assertTrue(x.exc_args) - self.assertEqual(len(x.exc_args), 2) - - -class test_get_pickleable_etype(Case): - - def test_get_pickleable_etype(self): - - class Unpickleable(Exception): - def __reduce__(self): - raise ValueError('foo') - - self.assertIs(get_pickleable_etype(Unpickleable), Exception) diff --git a/awx/lib/site-packages/celery/tests/utils/test_sysinfo.py b/awx/lib/site-packages/celery/tests/utils/test_sysinfo.py deleted file mode 100644 index 4cd32c7e7e..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_sysinfo.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import absolute_import - -import os - -from celery.utils.sysinfo import load_average, df - -from celery.tests.case import Case, SkipTest, patch - - -class test_load_average(Case): - - def test_avg(self): - if not hasattr(os, 'getloadavg'): - raise SkipTest('getloadavg not available') - with patch('os.getloadavg') as getloadavg: - getloadavg.return_value = 0.54736328125, 0.6357421875, 0.69921875 - l = load_average() - self.assertTrue(l) - self.assertEqual(l, (0.55, 0.64, 0.7)) - - -class test_df(Case): - - def test_df(self): - try: - from posix import statvfs_result # noqa - except ImportError: - raise SkipTest('statvfs not available') - x = df('/') - self.assertTrue(x.total_blocks) - self.assertTrue(x.available) - self.assertTrue(x.capacity) - self.assertTrue(x.stat) diff --git a/awx/lib/site-packages/celery/tests/utils/test_term.py b/awx/lib/site-packages/celery/tests/utils/test_term.py deleted file mode 100644 index 1bd7e4341c..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_term.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import sys - -from celery.utils import term -from celery.utils.term import colored, fg -from celery.five import text_t - -from celery.tests.case import Case, SkipTest - - -class test_colored(Case): - - def setUp(self): - if sys.platform == 'win32': - raise SkipTest('Colors not supported on Windows') - - self._prev_encoding = sys.getdefaultencoding - - def getdefaultencoding(): - return 'utf-8' - - sys.getdefaultencoding = getdefaultencoding - - def tearDown(self): - sys.getdefaultencoding = self._prev_encoding - - def test_colors(self): - colors = ( - ('black', term.BLACK), - ('red', term.RED), - ('green', term.GREEN), - ('yellow', term.YELLOW), - ('blue', term.BLUE), - ('magenta', term.MAGENTA), - ('cyan', term.CYAN), - ('white', term.WHITE), - ) - - for name, key in colors: - self.assertIn(fg(30 + key), str(colored().names[name]('foo'))) - - self.assertTrue(str(colored().bold('f'))) - self.assertTrue(str(colored().underline('f'))) - self.assertTrue(str(colored().blink('f'))) - self.assertTrue(str(colored().reverse('f'))) - self.assertTrue(str(colored().bright('f'))) - self.assertTrue(str(colored().ired('f'))) - self.assertTrue(str(colored().igreen('f'))) - self.assertTrue(str(colored().iyellow('f'))) - self.assertTrue(str(colored().iblue('f'))) - self.assertTrue(str(colored().imagenta('f'))) - self.assertTrue(str(colored().icyan('f'))) - self.assertTrue(str(colored().iwhite('f'))) - self.assertTrue(str(colored().reset('f'))) - - self.assertTrue(text_t(colored().green('∂bar'))) - - self.assertTrue( - colored().red('éefoo') + colored().green('∂bar')) - - self.assertEqual( - colored().red('foo').no_color(), 'foo') - - self.assertTrue( - repr(colored().blue('åfoo'))) - - self.assertIn("''", repr(colored())) - - c = colored() - s = c.red('foo', c.blue('bar'), c.green('baz')) - self.assertTrue(s.no_color()) - - c._fold_no_color(s, 'øfoo') - c._fold_no_color('fooå', s) - - c = colored().red('åfoo') - self.assertEqual( - c._add(c, 'baræ'), - '\x1b[1;31m\xe5foo\x1b[0mbar\xe6', - ) - - c2 = colored().blue('ƒƒz') - c3 = c._add(c, c2) - self.assertEqual( - c3, - '\x1b[1;31m\xe5foo\x1b[0m\x1b[1;34m\u0192\u0192z\x1b[0m', - ) diff --git a/awx/lib/site-packages/celery/tests/utils/test_text.py b/awx/lib/site-packages/celery/tests/utils/test_text.py deleted file mode 100644 index 383bdb6ee9..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_text.py +++ /dev/null @@ -1,88 +0,0 @@ -from __future__ import absolute_import - -from celery.utils.text import ( - indent, - ensure_2lines, - abbr, - truncate, - abbrtask, - pretty, -) -from celery.tests.case import AppCase, Case - -RANDTEXT = """\ -The quick brown -fox jumps -over the -lazy dog\ -""" - -RANDTEXT_RES = """\ - The quick brown - fox jumps - over the - lazy dog\ -""" - -QUEUES = { - 'queue1': { - 'exchange': 'exchange1', - 'exchange_type': 'type1', - 'routing_key': 'bind1', - }, - 'queue2': { - 'exchange': 'exchange2', - 'exchange_type': 'type2', - 'routing_key': 'bind2', - }, -} - - -QUEUE_FORMAT1 = '.> queue1 exchange=exchange1(type1) key=bind1' -QUEUE_FORMAT2 = '.> queue2 exchange=exchange2(type2) key=bind2' - - -class test_Info(AppCase): - - def test_textindent(self): - self.assertEqual(indent(RANDTEXT, 4), RANDTEXT_RES) - - def test_format_queues(self): - self.app.amqp.queues = self.app.amqp.Queues(QUEUES) - self.assertEqual(sorted(self.app.amqp.queues.format().split('\n')), - sorted([QUEUE_FORMAT1, QUEUE_FORMAT2])) - - def test_ensure_2lines(self): - self.assertEqual( - len(ensure_2lines('foo\nbar\nbaz\n').splitlines()), 3, - ) - self.assertEqual( - len(ensure_2lines('foo\nbar').splitlines()), 2, - ) - - -class test_utils(Case): - - def test_truncate_text(self): - self.assertEqual(truncate('ABCDEFGHI', 3), 'ABC...') - self.assertEqual(truncate('ABCDEFGHI', 10), 'ABCDEFGHI') - - def test_abbr(self): - self.assertEqual(abbr(None, 3), '???') - self.assertEqual(abbr('ABCDEFGHI', 6), 'ABC...') - self.assertEqual(abbr('ABCDEFGHI', 20), 'ABCDEFGHI') - self.assertEqual(abbr('ABCDEFGHI', 6, None), 'ABCDEF') - - def test_abbrtask(self): - self.assertEqual(abbrtask(None, 3), '???') - self.assertEqual( - abbrtask('feeds.tasks.refresh', 10), - '[.]refresh', - ) - self.assertEqual( - abbrtask('feeds.tasks.refresh', 30), - 'feeds.tasks.refresh', - ) - - def test_pretty(self): - self.assertTrue(pretty(('a', 'b', 'c'))) diff --git a/awx/lib/site-packages/celery/tests/utils/test_threads.py b/awx/lib/site-packages/celery/tests/utils/test_threads.py deleted file mode 100644 index 4c85b2338b..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_threads.py +++ /dev/null @@ -1,107 +0,0 @@ -from __future__ import absolute_import - -from celery.utils.threads import ( - _LocalStack, - _FastLocalStack, - LocalManager, - Local, - bgThread, -) - -from celery.tests.case import Case, override_stdouts, patch - - -class test_bgThread(Case): - - def test_crash(self): - - class T(bgThread): - - def body(self): - raise KeyError() - - with patch('os._exit') as _exit: - with override_stdouts(): - _exit.side_effect = ValueError() - t = T() - with self.assertRaises(ValueError): - t.run() - _exit.assert_called_with(1) - - def test_interface(self): - x = bgThread() - with self.assertRaises(NotImplementedError): - x.body() - - -class test_Local(Case): - - def test_iter(self): - x = Local() - x.foo = 'bar' - ident = x.__ident_func__() - self.assertIn((ident, {'foo': 'bar'}), list(iter(x))) - - delattr(x, 'foo') - self.assertNotIn((ident, {'foo': 'bar'}), list(iter(x))) - with self.assertRaises(AttributeError): - delattr(x, 'foo') - - self.assertIsNotNone(x(lambda: 'foo')) - - -class test_LocalStack(Case): - - def test_stack(self): - x = _LocalStack() - self.assertIsNone(x.pop()) - x.__release_local__() - ident = x.__ident_func__ - x.__ident_func__ = ident - - with self.assertRaises(RuntimeError): - x()[0] - - x.push(['foo']) - self.assertEqual(x()[0], 'foo') - x.pop() - with self.assertRaises(RuntimeError): - x()[0] - - -class test_FastLocalStack(Case): - - def test_stack(self): - x = _FastLocalStack() - x.push(['foo']) - x.push(['bar']) - self.assertEqual(x.top, ['bar']) - self.assertEqual(len(x), 2) - x.pop() - self.assertEqual(x.top, ['foo']) - x.pop() - self.assertIsNone(x.top) - - -class test_LocalManager(Case): - - def test_init(self): - x = LocalManager() - self.assertListEqual(x.locals, []) - self.assertTrue(x.ident_func) - - ident = lambda: 1 - loc = Local() - x = LocalManager([loc], ident_func=ident) - self.assertListEqual(x.locals, [loc]) - x = LocalManager(loc, ident_func=ident) - self.assertListEqual(x.locals, [loc]) - self.assertIs(x.ident_func, ident) - self.assertIs(x.locals[0].__ident_func__, ident) - self.assertEqual(x.get_ident(), 1) - - with patch('celery.utils.threads.release_local') as release: - x.cleanup() - release.assert_called_with(loc) - - self.assertTrue(repr(x)) diff --git a/awx/lib/site-packages/celery/tests/utils/test_timer2.py b/awx/lib/site-packages/celery/tests/utils/test_timer2.py deleted file mode 100644 index cb18c21239..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_timer2.py +++ /dev/null @@ -1,187 +0,0 @@ -from __future__ import absolute_import - -import sys -import time - -import celery.utils.timer2 as timer2 - -from celery.tests.case import Case, Mock, patch -from kombu.tests.case import redirect_stdouts - - -class test_Entry(Case): - - def test_call(self): - scratch = [None] - - def timed(x, y, moo='foo'): - scratch[0] = (x, y, moo) - - tref = timer2.Entry(timed, (4, 4), {'moo': 'baz'}) - tref() - - self.assertTupleEqual(scratch[0], (4, 4, 'baz')) - - def test_cancel(self): - tref = timer2.Entry(lambda x: x, (1, ), {}) - tref.cancel() - self.assertTrue(tref.cancelled) - - def test_repr(self): - tref = timer2.Entry(lambda x: x(1, ), {}) - self.assertTrue(repr(tref)) - - -class test_Schedule(Case): - - def test_supports_Timer_interface(self): - x = timer2.Schedule() - x.stop() - - tref = Mock() - x.cancel(tref) - tref.cancel.assert_called_with() - - self.assertIs(x.schedule, x) - - def test_handle_error(self): - from datetime import datetime - scratch = [None] - - def on_error(exc_info): - scratch[0] = exc_info - - s = timer2.Schedule(on_error=on_error) - - with patch('kombu.async.timer.to_timestamp') as tot: - tot.side_effect = OverflowError() - s.enter_at(timer2.Entry(lambda: None, (), {}), - eta=datetime.now()) - s.enter_at(timer2.Entry(lambda: None, (), {}), eta=None) - s.on_error = None - with self.assertRaises(OverflowError): - s.enter_at(timer2.Entry(lambda: None, (), {}), - eta=datetime.now()) - exc = scratch[0] - self.assertIsInstance(exc, OverflowError) - - -class test_Timer(Case): - - def test_enter_after(self): - t = timer2.Timer() - try: - done = [False] - - def set_done(): - done[0] = True - - t.call_after(0.3, set_done) - mss = 0 - while not done[0]: - if mss >= 2.0: - raise Exception('test timed out') - time.sleep(0.1) - mss += 0.1 - finally: - t.stop() - - def test_exit_after(self): - t = timer2.Timer() - t.call_after = Mock() - t.exit_after(0.3, priority=10) - t.call_after.assert_called_with(0.3, sys.exit, 10) - - def test_ensure_started_not_started(self): - t = timer2.Timer() - t.running = True - t.start = Mock() - t.ensure_started() - self.assertFalse(t.start.called) - - def test_call_repeatedly(self): - t = timer2.Timer() - try: - t.schedule.enter_after = Mock() - - myfun = Mock() - myfun.__name__ = 'myfun' - t.call_repeatedly(0.03, myfun) - - self.assertEqual(t.schedule.enter_after.call_count, 1) - args1, _ = t.schedule.enter_after.call_args_list[0] - sec1, tref1, _ = args1 - self.assertEqual(sec1, 0.03) - tref1() - - self.assertEqual(t.schedule.enter_after.call_count, 2) - args2, _ = t.schedule.enter_after.call_args_list[1] - sec2, tref2, _ = args2 - self.assertEqual(sec2, 0.03) - tref2.cancelled = True - tref2() - - self.assertEqual(t.schedule.enter_after.call_count, 2) - finally: - t.stop() - - @patch('kombu.async.timer.logger') - def test_apply_entry_error_handled(self, logger): - t = timer2.Timer() - t.schedule.on_error = None - - fun = Mock() - fun.side_effect = ValueError() - - t.schedule.apply_entry(fun) - self.assertTrue(logger.error.called) - - @redirect_stdouts - def test_apply_entry_error_not_handled(self, stdout, stderr): - t = timer2.Timer() - t.schedule.on_error = Mock() - - fun = Mock() - fun.side_effect = ValueError() - t.schedule.apply_entry(fun) - fun.assert_called_with() - self.assertFalse(stderr.getvalue()) - - @patch('os._exit') - def test_thread_crash(self, _exit): - t = timer2.Timer() - t._next_entry = Mock() - t._next_entry.side_effect = OSError(131) - t.run() - _exit.assert_called_with(1) - - def test_gc_race_lost(self): - t = timer2.Timer() - t._is_stopped.set = Mock() - t._is_stopped.set.side_effect = TypeError() - - t._is_shutdown.set() - t.run() - t._is_stopped.set.assert_called_with() - - def test_to_timestamp(self): - self.assertIs(timer2.to_timestamp(3.13), 3.13) - - def test_test_enter(self): - t = timer2.Timer() - t._do_enter = Mock() - e = Mock() - t.enter(e, 13, 0) - t._do_enter.assert_called_with('enter_at', e, 13, priority=0) - - def test_test_enter_after(self): - t = timer2.Timer() - t._do_enter = Mock() - t.enter_after() - t._do_enter.assert_called_with('enter_after') - - def test_cancel(self): - t = timer2.Timer() - tref = Mock() - t.cancel(tref) - tref.cancel.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/utils/test_timeutils.py b/awx/lib/site-packages/celery/tests/utils/test_timeutils.py deleted file mode 100644 index 2258d064d1..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_timeutils.py +++ /dev/null @@ -1,267 +0,0 @@ -from __future__ import absolute_import - -import pytz - -from datetime import datetime, timedelta, tzinfo -from pytz import AmbiguousTimeError - -from celery.utils.timeutils import ( - delta_resolution, - humanize_seconds, - maybe_iso8601, - maybe_timedelta, - timedelta_seconds, - timezone, - rate, - remaining, - make_aware, - maybe_make_aware, - localize, - LocalTimezone, - ffwd, - utcoffset, -) -from celery.utils.iso8601 import parse_iso8601 -from celery.tests.case import Case, Mock, patch - - -class test_LocalTimezone(Case): - - def test_daylight(self): - with patch('celery.utils.timeutils._time') as time: - time.timezone = 3600 - time.daylight = False - x = LocalTimezone() - self.assertEqual(x.STDOFFSET, timedelta(seconds=-3600)) - self.assertEqual(x.DSTOFFSET, x.STDOFFSET) - time.daylight = True - time.altzone = 3600 - y = LocalTimezone() - self.assertEqual(y.STDOFFSET, timedelta(seconds=-3600)) - self.assertEqual(y.DSTOFFSET, timedelta(seconds=-3600)) - - self.assertTrue(repr(y)) - - y._isdst = Mock() - y._isdst.return_value = True - self.assertTrue(y.utcoffset(datetime.now())) - self.assertFalse(y.dst(datetime.now())) - y._isdst.return_value = False - self.assertTrue(y.utcoffset(datetime.now())) - self.assertFalse(y.dst(datetime.now())) - - self.assertTrue(y.tzname(datetime.now())) - - -class test_iso8601(Case): - - def test_parse_with_timezone(self): - d = datetime.utcnow().replace(tzinfo=pytz.utc) - self.assertEqual(parse_iso8601(d.isoformat()), d) - # 2013-06-07T20:12:51.775877+00:00 - iso = d.isoformat() - iso1 = iso.replace('+00:00', '-01:00') - d1 = parse_iso8601(iso1) - self.assertEqual(d1.tzinfo._minutes, -60) - iso2 = iso.replace('+00:00', '+01:00') - d2 = parse_iso8601(iso2) - self.assertEqual(d2.tzinfo._minutes, +60) - iso3 = iso.replace('+00:00', 'Z') - d3 = parse_iso8601(iso3) - self.assertEqual(d3.tzinfo, pytz.UTC) - - -class test_timeutils(Case): - - def test_delta_resolution(self): - D = delta_resolution - dt = datetime(2010, 3, 30, 11, 50, 58, 41065) - deltamap = ((timedelta(days=2), datetime(2010, 3, 30, 0, 0)), - (timedelta(hours=2), datetime(2010, 3, 30, 11, 0)), - (timedelta(minutes=2), datetime(2010, 3, 30, 11, 50)), - (timedelta(seconds=2), dt)) - for delta, shoulda in deltamap: - self.assertEqual(D(dt, delta), shoulda) - - def test_timedelta_seconds(self): - deltamap = ((timedelta(seconds=1), 1), - (timedelta(seconds=27), 27), - (timedelta(minutes=3), 3 * 60), - (timedelta(hours=4), 4 * 60 * 60), - (timedelta(days=3), 3 * 86400)) - for delta, seconds in deltamap: - self.assertEqual(timedelta_seconds(delta), seconds) - - def test_timedelta_seconds_returns_0_on_negative_time(self): - delta = timedelta(days=-2) - self.assertEqual(timedelta_seconds(delta), 0) - - def test_humanize_seconds(self): - t = ((4 * 60 * 60 * 24, '4.00 days'), - (1 * 60 * 60 * 24, '1.00 day'), - (4 * 60 * 60, '4.00 hours'), - (1 * 60 * 60, '1.00 hour'), - (4 * 60, '4.00 minutes'), - (1 * 60, '1.00 minute'), - (4, '4.00 seconds'), - (1, '1.00 second'), - (4.3567631221, '4.36 seconds'), - (0, 'now')) - - for seconds, human in t: - self.assertEqual(humanize_seconds(seconds), human) - - self.assertEqual(humanize_seconds(4, prefix='about '), - 'about 4.00 seconds') - - def test_maybe_iso8601_datetime(self): - now = datetime.now() - self.assertIs(maybe_iso8601(now), now) - - def test_maybe_timedelta(self): - D = maybe_timedelta - - for i in (30, 30.6): - self.assertEqual(D(i), timedelta(seconds=i)) - - self.assertEqual(D(timedelta(days=2)), timedelta(days=2)) - - def test_remaining_relative(self): - remaining(datetime.utcnow(), timedelta(hours=1), relative=True) - - -class test_timezone(Case): - - def test_get_timezone_with_pytz(self): - self.assertTrue(timezone.get_timezone('UTC')) - - def test_tz_or_local(self): - self.assertEqual(timezone.tz_or_local(), timezone.local) - self.assertTrue(timezone.tz_or_local(timezone.utc)) - - def test_to_local(self): - self.assertTrue( - timezone.to_local(make_aware(datetime.utcnow(), timezone.utc)), - ) - self.assertTrue( - timezone.to_local(datetime.utcnow()) - ) - - def test_to_local_fallback(self): - self.assertTrue( - timezone.to_local_fallback( - make_aware(datetime.utcnow(), timezone.utc)), - ) - self.assertTrue( - timezone.to_local_fallback(datetime.utcnow()) - ) - - -class test_make_aware(Case): - - def test_tz_without_localize(self): - tz = tzinfo() - self.assertFalse(hasattr(tz, 'localize')) - wtz = make_aware(datetime.utcnow(), tz) - self.assertEqual(wtz.tzinfo, tz) - - def test_when_has_localize(self): - - class tzz(tzinfo): - raises = False - - def localize(self, dt, is_dst=None): - self.localized = True - if self.raises and is_dst is None: - self.raised = True - raise AmbiguousTimeError() - return 1 # needed by min() in Python 3 (None not hashable) - - tz = tzz() - make_aware(datetime.utcnow(), tz) - self.assertTrue(tz.localized) - - tz2 = tzz() - tz2.raises = True - make_aware(datetime.utcnow(), tz2) - self.assertTrue(tz2.localized) - self.assertTrue(tz2.raised) - - def test_maybe_make_aware(self): - aware = datetime.utcnow().replace(tzinfo=timezone.utc) - self.assertTrue(maybe_make_aware(aware), timezone.utc) - naive = datetime.utcnow() - self.assertTrue(maybe_make_aware(naive)) - - -class test_localize(Case): - - def test_tz_without_normalize(self): - tz = tzinfo() - self.assertFalse(hasattr(tz, 'normalize')) - self.assertTrue(localize(make_aware(datetime.utcnow(), tz), tz)) - - def test_when_has_normalize(self): - - class tzz(tzinfo): - raises = None - - def normalize(self, dt, **kwargs): - self.normalized = True - if self.raises and kwargs and kwargs.get('is_dst') is None: - self.raised = True - raise self.raises - return 1 # needed by min() in Python 3 (None not hashable) - - tz = tzz() - localize(make_aware(datetime.utcnow(), tz), tz) - self.assertTrue(tz.normalized) - - tz2 = tzz() - tz2.raises = AmbiguousTimeError() - localize(make_aware(datetime.utcnow(), tz2), tz2) - self.assertTrue(tz2.normalized) - self.assertTrue(tz2.raised) - - tz3 = tzz() - tz3.raises = TypeError() - localize(make_aware(datetime.utcnow(), tz3), tz3) - self.assertTrue(tz3.normalized) - self.assertTrue(tz3.raised) - - -class test_rate_limit_string(Case): - - def test_conversion(self): - self.assertEqual(rate(999), 999) - self.assertEqual(rate(7.5), 7.5) - self.assertEqual(rate('2.5/s'), 2.5) - self.assertEqual(rate('1456/s'), 1456) - self.assertEqual(rate('100/m'), - 100 / 60.0) - self.assertEqual(rate('10/h'), - 10 / 60.0 / 60.0) - - for zero in (0, None, '0', '0/m', '0/h', '0/s', '0.0/s'): - self.assertEqual(rate(zero), 0) - - -class test_ffwd(Case): - - def test_repr(self): - x = ffwd(year=2012) - self.assertTrue(repr(x)) - - def test_radd_with_unknown_gives_NotImplemented(self): - x = ffwd(year=2012) - self.assertEqual(x.__radd__(object()), NotImplemented) - - -class test_utcoffset(Case): - - def test_utcoffset(self): - with patch('celery.utils.timeutils._time') as _time: - _time.daylight = True - self.assertIsNotNone(utcoffset()) - _time.daylight = False - self.assertIsNotNone(utcoffset()) diff --git a/awx/lib/site-packages/celery/tests/utils/test_utils.py b/awx/lib/site-packages/celery/tests/utils/test_utils.py deleted file mode 100644 index 2837ad6369..0000000000 --- a/awx/lib/site-packages/celery/tests/utils/test_utils.py +++ /dev/null @@ -1,108 +0,0 @@ -from __future__ import absolute_import - -import pytz - -from datetime import datetime, date, time, timedelta - -from kombu import Queue - -from celery.utils import ( - chunks, - is_iterable, - cached_property, - warn_deprecated, - worker_direct, - gen_task_name, - jsonify, -) -from celery.tests.case import Case, Mock, patch - - -def double(x): - return x * 2 - - -class test_worker_direct(Case): - - def test_returns_if_queue(self): - q = Queue('foo') - self.assertIs(worker_direct(q), q) - - -class test_gen_task_name(Case): - - def test_no_module(self): - app = Mock() - app.name == '__main__' - self.assertTrue(gen_task_name(app, 'foo', 'axsadaewe')) - - -class test_jsonify(Case): - - def test_simple(self): - self.assertTrue(jsonify(Queue('foo'))) - self.assertTrue(jsonify(['foo', 'bar', 'baz'])) - self.assertTrue(jsonify({'foo': 'bar'})) - self.assertTrue(jsonify(datetime.utcnow())) - self.assertTrue(jsonify(datetime.utcnow().replace(tzinfo=pytz.utc))) - self.assertTrue(jsonify(datetime.utcnow().replace(microsecond=0))) - self.assertTrue(jsonify(date(2012, 1, 1))) - self.assertTrue(jsonify(time(hour=1, minute=30))) - self.assertTrue(jsonify(time(hour=1, minute=30, microsecond=3))) - self.assertTrue(jsonify(timedelta(seconds=30))) - self.assertTrue(jsonify(10)) - self.assertTrue(jsonify(10.3)) - self.assertTrue(jsonify('hello')) - - with self.assertRaises(ValueError): - jsonify(object()) - - -class test_chunks(Case): - - def test_chunks(self): - - # n == 2 - x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 2) - self.assertListEqual( - list(x), - [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10]], - ) - - # n == 3 - x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 3) - self.assertListEqual( - list(x), - [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]], - ) - - # n == 2 (exact) - x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 2) - self.assertListEqual( - list(x), - [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]], - ) - - -class test_utils(Case): - - def test_is_iterable(self): - for a in 'f', ['f'], ('f', ), {'f': 'f'}: - self.assertTrue(is_iterable(a)) - for b in object(), 1: - self.assertFalse(is_iterable(b)) - - def test_cached_property(self): - - def fun(obj): - return fun.value - - x = cached_property(fun) - self.assertIs(x.__get__(None), x) - self.assertIs(x.__set__(None, None), x) - self.assertIs(x.__delete__(None), x) - - @patch('warnings.warn') - def test_warn_deprecated(self, warn): - warn_deprecated('Foo') - self.assertTrue(warn.called) diff --git a/awx/lib/site-packages/celery/tests/worker/__init__.py b/awx/lib/site-packages/celery/tests/worker/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/celery/tests/worker/test_autoreload.py b/awx/lib/site-packages/celery/tests/worker/test_autoreload.py deleted file mode 100644 index e61b330ca3..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_autoreload.py +++ /dev/null @@ -1,328 +0,0 @@ -from __future__ import absolute_import - -import errno -import select -import sys - -from time import time - -from celery.worker import autoreload -from celery.worker.autoreload import ( - WorkerComponent, - file_hash, - BaseMonitor, - StatMonitor, - KQueueMonitor, - InotifyMonitor, - default_implementation, - Autoreloader, -) - -from celery.tests.case import AppCase, Case, Mock, SkipTest, patch, mock_open - - -class test_WorkerComponent(AppCase): - - def test_create_threaded(self): - w = Mock() - w.use_eventloop = False - x = WorkerComponent(w) - x.instantiate = Mock() - r = x.create(w) - x.instantiate.assert_called_with(w.autoreloader_cls, w) - self.assertIs(r, w.autoreloader) - - @patch('select.kevent', create=True) - @patch('select.kqueue', create=True) - @patch('kombu.utils.eventio.kqueue') - def test_create_ev(self, kq, kqueue, kevent): - w = Mock() - w.use_eventloop = True - x = WorkerComponent(w) - x.instantiate = Mock() - r = x.create(w) - x.instantiate.assert_called_with(w.autoreloader_cls, w) - x.register_with_event_loop(w, w.hub) - self.assertIsNone(r) - w.hub.on_close.add.assert_called_with( - w.autoreloader.on_event_loop_close, - ) - - -class test_file_hash(Case): - - def test_hash(self): - with mock_open() as a: - a.write('the quick brown fox\n') - a.seek(0) - A = file_hash('foo') - with mock_open() as b: - b.write('the quick brown bar\n') - b.seek(0) - B = file_hash('bar') - self.assertNotEqual(A, B) - - -class test_BaseMonitor(Case): - - def test_start_stop_on_change(self): - x = BaseMonitor(['a', 'b']) - - with self.assertRaises(NotImplementedError): - x.start() - x.stop() - x.on_change([]) - x._on_change = Mock() - x.on_change('foo') - x._on_change.assert_called_with('foo') - - -class test_StatMonitor(Case): - - @patch('os.stat') - def test_start(self, stat): - - class st(object): - st_mtime = time() - stat.return_value = st() - x = StatMonitor(['a', 'b']) - - def on_is_set(): - if x.shutdown_event.is_set.call_count > 3: - return True - return False - x.shutdown_event = Mock() - x.shutdown_event.is_set.side_effect = on_is_set - - x.start() - x.shutdown_event = Mock() - stat.side_effect = OSError() - x.start() - - @patch('os.stat') - def test_mtime_stat_raises(self, stat): - stat.side_effect = ValueError() - x = StatMonitor(['a', 'b']) - x._mtime('a') - - -class test_KQueueMonitor(Case): - - @patch('select.kqueue', create=True) - @patch('os.close') - def test_stop(self, close, kqueue): - x = KQueueMonitor(['a', 'b']) - x.poller = Mock() - x.filemap['a'] = 10 - x.stop() - x.poller.close.assert_called_with() - close.assert_called_with(10) - - close.side_effect = OSError() - close.side_effect.errno = errno.EBADF - x.stop() - - def test_register_with_event_loop(self): - from kombu.utils import eventio - if eventio.kqueue is None: - raise SkipTest('version of kombu does not work with pypy') - x = KQueueMonitor(['a', 'b']) - hub = Mock(name='hub') - x.add_events = Mock(name='add_events()') - x.register_with_event_loop(hub) - x.add_events.assert_called_with(x._kq) - self.assertEqual( - x._kq.on_file_change, - x.handle_event, - ) - - def test_on_event_loop_close(self): - x = KQueueMonitor(['a', 'b']) - x.close = Mock() - x._kq = Mock(name='_kq') - x.on_event_loop_close(Mock(name='hub')) - x.close.assert_called_with(x._kq) - - def test_handle_event(self): - x = KQueueMonitor(['a', 'b']) - x.on_change = Mock() - eA = Mock() - eA.ident = 'a' - eB = Mock() - eB.ident = 'b' - x.fdmap = {'a': 'A', 'b': 'B'} - x.handle_event([eA, eB]) - x.on_change.assert_called_with(['A', 'B']) - - @patch('kombu.utils.eventio.kqueue', create=True) - @patch('kombu.utils.eventio.kevent', create=True) - @patch('os.open') - @patch('select.kqueue', create=True) - def test_start(self, _kq, osopen, kevent, kqueue): - from kombu.utils import eventio - prev_poll, eventio.poll = eventio.poll, kqueue - prev = {} - flags = ['KQ_FILTER_VNODE', 'KQ_EV_ADD', 'KQ_EV_ENABLE', - 'KQ_EV_CLEAR', 'KQ_NOTE_WRITE', 'KQ_NOTE_EXTEND'] - for i, flag in enumerate(flags): - prev[flag] = getattr(eventio, flag, None) - if not prev[flag]: - setattr(eventio, flag, i) - try: - kq = kqueue.return_value = Mock() - - class ev(object): - ident = 10 - filter = eventio.KQ_FILTER_VNODE - fflags = eventio.KQ_NOTE_WRITE - kq.control.return_value = [ev()] - x = KQueueMonitor(['a']) - osopen.return_value = 10 - calls = [0] - - def on_is_set(): - calls[0] += 1 - if calls[0] > 2: - return True - return False - x.shutdown_event = Mock() - x.shutdown_event.is_set.side_effect = on_is_set - x.start() - finally: - for flag in flags: - if prev[flag]: - setattr(eventio, flag, prev[flag]) - else: - delattr(eventio, flag) - eventio.poll = prev_poll - - -class test_InotifyMonitor(Case): - - @patch('celery.worker.autoreload.pyinotify') - def test_start(self, inotify): - x = InotifyMonitor(['a']) - inotify.IN_MODIFY = 1 - inotify.IN_ATTRIB = 2 - x.start() - - inotify.WatchManager.side_effect = ValueError() - with self.assertRaises(ValueError): - x.start() - x.stop() - - x._on_change = None - x.process_(Mock()) - x._on_change = Mock() - x.process_(Mock()) - self.assertTrue(x._on_change.called) - - -class test_default_implementation(Case): - - @patch('select.kqueue', create=True) - @patch('kombu.utils.eventio.kqueue', create=True) - def test_kqueue(self, kq, kqueue): - self.assertEqual(default_implementation(), 'kqueue') - - @patch('celery.worker.autoreload.pyinotify') - def test_inotify(self, pyinotify): - kq = getattr(select, 'kqueue', None) - try: - delattr(select, 'kqueue') - except AttributeError: - pass - platform, sys.platform = sys.platform, 'linux' - try: - self.assertEqual(default_implementation(), 'inotify') - ino, autoreload.pyinotify = autoreload.pyinotify, None - try: - self.assertEqual(default_implementation(), 'stat') - finally: - autoreload.pyinotify = ino - finally: - if kq: - select.kqueue = kq - sys.platform = platform - - -class test_Autoreloader(AppCase): - - def test_register_with_event_loop(self): - x = Autoreloader(Mock(), modules=[__name__]) - hub = Mock() - x._monitor = None - x.on_init = Mock() - - def se(*args, **kwargs): - x._monitor = Mock() - x.on_init.side_effect = se - - x.register_with_event_loop(hub) - x.on_init.assert_called_with() - x._monitor.register_with_event_loop.assert_called_with(hub) - - x._monitor.register_with_event_loop.reset_mock() - x.register_with_event_loop(hub) - x._monitor.register_with_event_loop.assert_called_with(hub) - - def test_on_event_loop_close(self): - x = Autoreloader(Mock(), modules=[__name__]) - hub = Mock() - x._monitor = Mock() - x.on_event_loop_close(hub) - x._monitor.on_event_loop_close.assert_called_with(hub) - x._monitor = None - x.on_event_loop_close(hub) - - @patch('celery.worker.autoreload.file_hash') - def test_start(self, fhash): - x = Autoreloader(Mock(), modules=[__name__]) - x.Monitor = Mock() - mon = x.Monitor.return_value = Mock() - mon.start.side_effect = OSError() - mon.start.side_effect.errno = errno.EINTR - x.body() - mon.start.side_effect.errno = errno.ENOENT - with self.assertRaises(OSError): - x.body() - mon.start.side_effect = None - x.body() - - @patch('celery.worker.autoreload.file_hash') - @patch('os.path.exists') - def test_maybe_modified(self, exists, fhash): - exists.return_value = True - fhash.return_value = 'abcd' - x = Autoreloader(Mock(), modules=[__name__]) - x._hashes = {} - x._hashes[__name__] = 'dcba' - self.assertTrue(x._maybe_modified(__name__)) - x._hashes[__name__] = 'abcd' - self.assertFalse(x._maybe_modified(__name__)) - exists.return_value = False - self.assertFalse(x._maybe_modified(__name__)) - - def test_on_change(self): - x = Autoreloader(Mock(), modules=[__name__]) - mm = x._maybe_modified = Mock(0) - mm.return_value = True - x._reload = Mock() - x.file_to_module[__name__] = __name__ - x.on_change([__name__]) - self.assertTrue(x._reload.called) - mm.return_value = False - x.on_change([__name__]) - - def test_reload(self): - x = Autoreloader(Mock(), modules=[__name__]) - x._reload([__name__]) - x.controller.reload.assert_called_with([__name__], reload=True) - - def test_stop(self): - x = Autoreloader(Mock(), modules=[__name__]) - x._monitor = None - x.stop() - x._monitor = Mock() - x.stop() - x._monitor.stop.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/worker/test_autoscale.py b/awx/lib/site-packages/celery/tests/worker/test_autoscale.py deleted file mode 100644 index 45ea488cc0..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_autoscale.py +++ /dev/null @@ -1,198 +0,0 @@ -from __future__ import absolute_import - -import sys - -from celery.concurrency.base import BasePool -from celery.five import monotonic -from celery.worker import state -from celery.worker import autoscale -from celery.tests.case import AppCase, Mock, patch, sleepdeprived - - -class Object(object): - pass - - -class MockPool(BasePool): - shrink_raises_exception = False - shrink_raises_ValueError = False - - def __init__(self, *args, **kwargs): - super(MockPool, self).__init__(*args, **kwargs) - self._pool = Object() - self._pool._processes = self.limit - - def grow(self, n=1): - self._pool._processes += n - - def shrink(self, n=1): - if self.shrink_raises_exception: - raise KeyError('foo') - if self.shrink_raises_ValueError: - raise ValueError('foo') - self._pool._processes -= n - - @property - def num_processes(self): - return self._pool._processes - - -class test_WorkerComponent(AppCase): - - def test_register_with_event_loop(self): - parent = Mock(name='parent') - parent.autoscale = True - parent.consumer.on_task_message = set() - w = autoscale.WorkerComponent(parent) - self.assertIsNone(parent.autoscaler) - self.assertTrue(w.enabled) - - hub = Mock(name='hub') - w.create(parent) - w.register_with_event_loop(parent, hub) - self.assertIn( - parent.autoscaler.maybe_scale, - parent.consumer.on_task_message, - ) - hub.call_repeatedly.assert_called_with( - parent.autoscaler.keepalive, parent.autoscaler.maybe_scale, - ) - - parent.hub = hub - hub.on_init = [] - w.instantiate = Mock() - w.register_with_event_loop(parent, Mock(name='loop')) - self.assertTrue(parent.consumer.on_task_message) - - -class test_Autoscaler(AppCase): - - def setup(self): - self.pool = MockPool(3) - - def test_stop(self): - - class Scaler(autoscale.Autoscaler): - alive = True - joined = False - - def is_alive(self): - return self.alive - - def join(self, timeout=None): - self.joined = True - - worker = Mock(name='worker') - x = Scaler(self.pool, 10, 3, worker=worker) - x._is_stopped.set() - x.stop() - self.assertTrue(x.joined) - x.joined = False - x.alive = False - x.stop() - self.assertFalse(x.joined) - - @sleepdeprived(autoscale) - def test_body(self): - worker = Mock(name='worker') - x = autoscale.Autoscaler(self.pool, 10, 3, worker=worker) - x.body() - self.assertEqual(x.pool.num_processes, 3) - for i in range(20): - state.reserved_requests.add(i) - x.body() - x.body() - self.assertEqual(x.pool.num_processes, 10) - self.assertTrue(worker.consumer._update_prefetch_count.called) - state.reserved_requests.clear() - x.body() - self.assertEqual(x.pool.num_processes, 10) - x._last_action = monotonic() - 10000 - x.body() - self.assertEqual(x.pool.num_processes, 3) - self.assertTrue(worker.consumer._update_prefetch_count.called) - - def test_run(self): - - class Scaler(autoscale.Autoscaler): - scale_called = False - - def body(self): - self.scale_called = True - self._is_shutdown.set() - - worker = Mock(name='worker') - x = Scaler(self.pool, 10, 3, worker=worker) - x.run() - self.assertTrue(x._is_shutdown.isSet()) - self.assertTrue(x._is_stopped.isSet()) - self.assertTrue(x.scale_called) - - def test_shrink_raises_exception(self): - worker = Mock(name='worker') - x = autoscale.Autoscaler(self.pool, 10, 3, worker=worker) - x.scale_up(3) - x._last_action = monotonic() - 10000 - x.pool.shrink_raises_exception = True - x.scale_down(1) - - @patch('celery.worker.autoscale.debug') - def test_shrink_raises_ValueError(self, debug): - worker = Mock(name='worker') - x = autoscale.Autoscaler(self.pool, 10, 3, worker=worker) - x.scale_up(3) - x._last_action = monotonic() - 10000 - x.pool.shrink_raises_ValueError = True - x.scale_down(1) - self.assertTrue(debug.call_count) - - def test_update_and_force(self): - worker = Mock(name='worker') - x = autoscale.Autoscaler(self.pool, 10, 3, worker=worker) - self.assertEqual(x.processes, 3) - x.force_scale_up(5) - self.assertEqual(x.processes, 8) - x.update(5, None) - self.assertEqual(x.processes, 5) - x.force_scale_down(3) - self.assertEqual(x.processes, 2) - x.update(3, None) - self.assertEqual(x.processes, 3) - x.force_scale_down(1000) - self.assertEqual(x.min_concurrency, 0) - self.assertEqual(x.processes, 0) - x.force_scale_up(1000) - x.min_concurrency = 1 - x.force_scale_down(1) - - x.update(max=300, min=10) - x.update(max=300, min=2) - x.update(max=None, min=None) - - def test_info(self): - worker = Mock(name='worker') - x = autoscale.Autoscaler(self.pool, 10, 3, worker=worker) - info = x.info() - self.assertEqual(info['max'], 10) - self.assertEqual(info['min'], 3) - self.assertEqual(info['current'], 3) - - @patch('os._exit') - def test_thread_crash(self, _exit): - - class _Autoscaler(autoscale.Autoscaler): - - def body(self): - self._is_shutdown.set() - raise OSError('foo') - worker = Mock(name='worker') - x = _Autoscaler(self.pool, 10, 3, worker=worker) - - stderr = Mock() - p, sys.stderr = sys.stderr, stderr - try: - x.run() - finally: - sys.stderr = p - _exit.assert_called_with(1) - self.assertTrue(stderr.write.call_count) diff --git a/awx/lib/site-packages/celery/tests/worker/test_bootsteps.py b/awx/lib/site-packages/celery/tests/worker/test_bootsteps.py deleted file mode 100644 index 522d263b3d..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_bootsteps.py +++ /dev/null @@ -1,338 +0,0 @@ -from __future__ import absolute_import - -from celery import bootsteps - -from celery.tests.case import AppCase, Mock, patch - - -class test_StepFormatter(AppCase): - - def test_get_prefix(self): - f = bootsteps.StepFormatter() - s = Mock() - s.last = True - self.assertEqual(f._get_prefix(s), f.blueprint_prefix) - - s2 = Mock() - s2.last = False - s2.conditional = True - self.assertEqual(f._get_prefix(s2), f.conditional_prefix) - - s3 = Mock() - s3.last = s3.conditional = False - self.assertEqual(f._get_prefix(s3), '') - - def test_node(self): - f = bootsteps.StepFormatter() - f.draw_node = Mock() - step = Mock() - step.last = False - f.node(step, x=3) - f.draw_node.assert_called_with(step, f.node_scheme, {'x': 3}) - - step.last = True - f.node(step, x=3) - f.draw_node.assert_called_with(step, f.blueprint_scheme, {'x': 3}) - - def test_edge(self): - f = bootsteps.StepFormatter() - f.draw_edge = Mock() - a, b = Mock(), Mock() - a.last = True - f.edge(a, b, x=6) - f.draw_edge.assert_called_with(a, b, f.edge_scheme, { - 'x': 6, 'arrowhead': 'none', 'color': 'darkseagreen3', - }) - - a.last = False - f.edge(a, b, x=6) - f.draw_edge.assert_called_with(a, b, f.edge_scheme, { - 'x': 6, - }) - - -class test_Step(AppCase): - - class Def(bootsteps.StartStopStep): - name = 'test_Step.Def' - - def setup(self): - self.steps = [] - - def test_blueprint_name(self, bp='test_blueprint_name'): - - class X(bootsteps.Step): - blueprint = bp - name = 'X' - self.assertEqual(X.name, 'X') - - class Y(bootsteps.Step): - name = '%s.Y' % bp - self.assertEqual(Y.name, '%s.Y' % bp) - - def test_init(self): - self.assertTrue(self.Def(self)) - - def test_create(self): - self.Def(self).create(self) - - def test_include_if(self): - x = self.Def(self) - x.enabled = True - self.assertTrue(x.include_if(self)) - - x.enabled = False - self.assertFalse(x.include_if(self)) - - def test_instantiate(self): - self.assertIsInstance(self.Def(self).instantiate(self.Def, self), - self.Def) - - def test_include_when_enabled(self): - x = self.Def(self) - x.create = Mock() - x.create.return_value = 'George' - self.assertTrue(x.include(self)) - - self.assertEqual(x.obj, 'George') - x.create.assert_called_with(self) - - def test_include_when_disabled(self): - x = self.Def(self) - x.enabled = False - x.create = Mock() - - self.assertFalse(x.include(self)) - self.assertFalse(x.create.call_count) - - def test_repr(self): - x = self.Def(self) - self.assertTrue(repr(x)) - - -class test_ConsumerStep(AppCase): - - def test_interface(self): - step = bootsteps.ConsumerStep(self) - with self.assertRaises(NotImplementedError): - step.get_consumers(self) - - def test_start_stop_shutdown(self): - consumer = Mock() - self.connection = Mock() - - class Step(bootsteps.ConsumerStep): - - def get_consumers(self, c): - return [consumer] - - step = Step(self) - self.assertEqual(step.get_consumers(self), [consumer]) - - step.start(self) - consumer.consume.assert_called_with() - step.stop(self) - consumer.cancel.assert_called_with() - - step.shutdown(self) - consumer.channel.close.assert_called_with() - - def test_start_no_consumers(self): - self.connection = Mock() - - class Step(bootsteps.ConsumerStep): - - def get_consumers(self, c): - return () - - step = Step(self) - step.start(self) - - -class test_StartStopStep(AppCase): - - class Def(bootsteps.StartStopStep): - name = 'test_StartStopStep.Def' - - def setup(self): - self.steps = [] - - def test_start__stop(self): - x = self.Def(self) - x.create = Mock() - - # include creates the underlying object and sets - # its x.obj attribute to it, as well as appending - # it to the parent.steps list. - x.include(self) - self.assertTrue(self.steps) - self.assertIs(self.steps[0], x) - - x.start(self) - x.obj.start.assert_called_with() - - x.stop(self) - x.obj.stop.assert_called_with() - - x.obj = None - self.assertIsNone(x.start(self)) - - def test_include_when_disabled(self): - x = self.Def(self) - x.enabled = False - x.include(self) - self.assertFalse(self.steps) - - def test_terminate(self): - x = self.Def(self) - x.create = Mock() - - x.include(self) - delattr(x.obj, 'terminate') - x.terminate(self) - x.obj.stop.assert_called_with() - - -class test_Blueprint(AppCase): - - class Blueprint(bootsteps.Blueprint): - name = 'test_Blueprint' - - def test_steps_added_to_unclaimed(self): - - class tnA(bootsteps.Step): - name = 'test_Blueprint.A' - - class tnB(bootsteps.Step): - name = 'test_Blueprint.B' - - class xxA(bootsteps.Step): - name = 'xx.A' - - class Blueprint(self.Blueprint): - default_steps = [tnA, tnB] - blueprint = Blueprint(app=self.app) - - self.assertIn(tnA, blueprint._all_steps()) - self.assertIn(tnB, blueprint._all_steps()) - self.assertNotIn(xxA, blueprint._all_steps()) - - def test_init(self): - blueprint = self.Blueprint(app=self.app) - self.assertIs(blueprint.app, self.app) - self.assertEqual(blueprint.name, 'test_Blueprint') - - def test_close__on_close_is_None(self): - blueprint = self.Blueprint(app=self.app) - blueprint.on_close = None - blueprint.send_all = Mock() - blueprint.close(1) - blueprint.send_all.assert_called_with( - 1, 'close', 'closing', reverse=False, - ) - - def test_send_all_with_None_steps(self): - parent = Mock() - blueprint = self.Blueprint(app=self.app) - parent.steps = [None, None, None] - blueprint.send_all(parent, 'close', 'Closing', reverse=False) - - def test_join_raises_IGNORE_ERRORS(self): - prev, bootsteps.IGNORE_ERRORS = bootsteps.IGNORE_ERRORS, (KeyError, ) - try: - blueprint = self.Blueprint(app=self.app) - blueprint.shutdown_complete = Mock() - blueprint.shutdown_complete.wait.side_effect = KeyError('luke') - blueprint.join(timeout=10) - blueprint.shutdown_complete.wait.assert_called_with(timeout=10) - finally: - bootsteps.IGNORE_ERRORS = prev - - def test_connect_with(self): - - class b1s1(bootsteps.Step): - pass - - class b1s2(bootsteps.Step): - last = True - - class b2s1(bootsteps.Step): - pass - - class b2s2(bootsteps.Step): - last = True - - b1 = self.Blueprint([b1s1, b1s2], app=self.app) - b2 = self.Blueprint([b2s1, b2s2], app=self.app) - b1.apply(Mock()) - b2.apply(Mock()) - b1.connect_with(b2) - - self.assertIn(b1s1, b1.graph) - self.assertIn(b2s1, b1.graph) - self.assertIn(b2s2, b1.graph) - - self.assertTrue(repr(b1s1)) - self.assertTrue(str(b1s1)) - - def test_topsort_raises_KeyError(self): - - class Step(bootsteps.Step): - requires = ('xyxxx.fsdasewe.Unknown', ) - - b = self.Blueprint([Step], app=self.app) - b.steps = b.claim_steps() - with self.assertRaises(ImportError): - b._finalize_steps(b.steps) - Step.requires = () - - b.steps = b.claim_steps() - b._finalize_steps(b.steps) - - with patch('celery.bootsteps.DependencyGraph') as Dep: - g = Dep.return_value = Mock() - g.topsort.side_effect = KeyError('foo') - with self.assertRaises(KeyError): - b._finalize_steps(b.steps) - - def test_apply(self): - - class MyBlueprint(bootsteps.Blueprint): - name = 'test_apply' - - def modules(self): - return ['A', 'B'] - - class B(bootsteps.Step): - name = 'test_apply.B' - - class C(bootsteps.Step): - name = 'test_apply.C' - requires = [B] - - class A(bootsteps.Step): - name = 'test_apply.A' - requires = [C] - - class D(bootsteps.Step): - name = 'test_apply.D' - last = True - - x = MyBlueprint([A, D], app=self.app) - x.apply(self) - - self.assertIsInstance(x.order[0], B) - self.assertIsInstance(x.order[1], C) - self.assertIsInstance(x.order[2], A) - self.assertIsInstance(x.order[3], D) - self.assertIn(A, x.types) - self.assertIs(x[A.name], x.order[2]) - - def test_find_last_but_no_steps(self): - - class MyBlueprint(bootsteps.Blueprint): - name = 'qwejwioqjewoqiej' - - x = MyBlueprint(app=self.app) - x.apply(self) - self.assertIsNone(x._find_last()) diff --git a/awx/lib/site-packages/celery/tests/worker/test_components.py b/awx/lib/site-packages/celery/tests/worker/test_components.py deleted file mode 100644 index b39865db40..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_components.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import absolute_import - -# some of these are tested in test_worker, so I've only written tests -# here to complete coverage. Should move everyting to this module at some -# point [-ask] - -from celery.worker.components import ( - Queues, - Pool, -) - -from celery.tests.case import AppCase, Mock - - -class test_Queues(AppCase): - - def test_create_when_eventloop(self): - w = Mock() - w.use_eventloop = w.pool_putlocks = w.pool_cls.uses_semaphore = True - q = Queues(w) - q.create(w) - self.assertIs(w.process_task, w._process_task_sem) - - -class test_Pool(AppCase): - - def test_close_terminate(self): - w = Mock() - comp = Pool(w) - pool = w.pool = Mock() - comp.close(w) - pool.close.assert_called_with() - comp.terminate(w) - pool.terminate.assert_called_with() - - w.pool = None - comp.close(w) - comp.terminate(w) diff --git a/awx/lib/site-packages/celery/tests/worker/test_consumer.py b/awx/lib/site-packages/celery/tests/worker/test_consumer.py deleted file mode 100644 index 81199b85df..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_consumer.py +++ /dev/null @@ -1,471 +0,0 @@ -from __future__ import absolute_import - -import errno -import socket - -from billiard.exceptions import RestartFreqExceeded - -from celery.datastructures import LimitedSet -from celery.worker import state as worker_state -from celery.worker.consumer import ( - Consumer, - Heart, - Tasks, - Agent, - Mingle, - Gossip, - dump_body, - CLOSE, -) - -from celery.tests.case import AppCase, ContextMock, Mock, SkipTest, call, patch - - -class test_Consumer(AppCase): - - def get_consumer(self, no_hub=False, **kwargs): - consumer = Consumer( - on_task_request=Mock(), - init_callback=Mock(), - pool=Mock(), - app=self.app, - timer=Mock(), - controller=Mock(), - hub=None if no_hub else Mock(), - **kwargs - ) - consumer.blueprint = Mock() - consumer._restart_state = Mock() - consumer.connection = _amqp_connection() - consumer.connection_errors = (socket.error, OSError, ) - return consumer - - def test_taskbuckets_defaultdict(self): - c = self.get_consumer() - self.assertIsNone(c.task_buckets['fooxasdwx.wewe']) - - def test_dump_body_buffer(self): - msg = Mock() - msg.body = 'str' - try: - buf = buffer(msg.body) - except NameError: - raise SkipTest('buffer type not available') - self.assertTrue(dump_body(msg, buf)) - - def test_sets_heartbeat(self): - c = self.get_consumer(amqheartbeat=10) - self.assertEqual(c.amqheartbeat, 10) - self.app.conf.BROKER_HEARTBEAT = 20 - c = self.get_consumer(amqheartbeat=None) - self.assertEqual(c.amqheartbeat, 20) - - def test_gevent_bug_disables_connection_timeout(self): - with patch('celery.worker.consumer._detect_environment') as de: - de.return_value = 'gevent' - self.app.conf.BROKER_CONNECTION_TIMEOUT = 33.33 - self.get_consumer() - self.assertIsNone(self.app.conf.BROKER_CONNECTION_TIMEOUT) - - def test_limit_task(self): - c = self.get_consumer() - - with patch('celery.worker.consumer.task_reserved') as reserved: - bucket = Mock() - request = Mock() - bucket.can_consume.return_value = True - - c._limit_task(request, bucket, 3) - bucket.can_consume.assert_called_with(3) - reserved.assert_called_with(request) - c.on_task_request.assert_called_with(request) - - with patch('celery.worker.consumer.task_reserved') as reserved: - bucket.can_consume.return_value = False - bucket.expected_time.return_value = 3.33 - c._limit_task(request, bucket, 4) - bucket.can_consume.assert_called_with(4) - c.timer.call_after.assert_called_with( - 3.33, c._limit_task, (request, bucket, 4), - ) - bucket.expected_time.assert_called_with(4) - self.assertFalse(reserved.called) - - def test_start_blueprint_raises_EMFILE(self): - c = self.get_consumer() - exc = c.blueprint.start.side_effect = OSError() - exc.errno = errno.EMFILE - - with self.assertRaises(OSError): - c.start() - - def test_max_restarts_exceeded(self): - c = self.get_consumer() - - def se(*args, **kwargs): - c.blueprint.state = CLOSE - raise RestartFreqExceeded() - c._restart_state.step.side_effect = se - c.blueprint.start.side_effect = socket.error() - - with patch('celery.worker.consumer.sleep') as sleep: - c.start() - sleep.assert_called_with(1) - - def _closer(self, c): - def se(*args, **kwargs): - c.blueprint.state = CLOSE - return se - - def test_collects_at_restart(self): - c = self.get_consumer() - c.connection.collect.side_effect = MemoryError() - c.blueprint.start.side_effect = socket.error() - c.blueprint.restart.side_effect = self._closer(c) - c.start() - c.connection.collect.assert_called_with() - - def test_register_with_event_loop(self): - c = self.get_consumer() - c.register_with_event_loop(Mock(name='loop')) - - def test_on_close_clears_semaphore_timer_and_reqs(self): - with patch('celery.worker.consumer.reserved_requests') as reserved: - c = self.get_consumer() - c.on_close() - c.controller.semaphore.clear.assert_called_with() - c.timer.clear.assert_called_with() - reserved.clear.assert_called_with() - c.pool.flush.assert_called_with() - - c.controller = None - c.timer = None - c.pool = None - c.on_close() - - def test_connect_error_handler(self): - self.app.connection = _amqp_connection() - conn = self.app.connection.return_value - c = self.get_consumer() - self.assertTrue(c.connect()) - self.assertTrue(conn.ensure_connection.called) - errback = conn.ensure_connection.call_args[0][0] - conn.alt = [(1, 2, 3)] - errback(Mock(), 0) - - -class test_Heart(AppCase): - - def test_start(self): - c = Mock() - c.timer = Mock() - c.event_dispatcher = Mock() - - with patch('celery.worker.heartbeat.Heart') as hcls: - h = Heart(c) - self.assertTrue(h.enabled) - self.assertIsNone(c.heart) - - h.start(c) - self.assertTrue(c.heart) - hcls.assert_called_with(c.timer, c.event_dispatcher) - c.heart.start.assert_called_with() - - -class test_Tasks(AppCase): - - def test_stop(self): - c = Mock() - tasks = Tasks(c) - self.assertIsNone(c.task_consumer) - self.assertIsNone(c.qos) - - c.task_consumer = Mock() - tasks.stop(c) - - def test_stop_already_stopped(self): - c = Mock() - tasks = Tasks(c) - tasks.stop(c) - - -class test_Agent(AppCase): - - def test_start(self): - c = Mock() - agent = Agent(c) - agent.instantiate = Mock() - agent.agent_cls = 'foo:Agent' - self.assertIsNotNone(agent.create(c)) - agent.instantiate.assert_called_with(agent.agent_cls, c.connection) - - -class test_Mingle(AppCase): - - def test_start_no_replies(self): - c = Mock() - c.app.connection = _amqp_connection() - mingle = Mingle(c) - I = c.app.control.inspect.return_value = Mock() - I.hello.return_value = {} - mingle.start(c) - - def test_start(self): - try: - c = Mock() - c.app.connection = _amqp_connection() - mingle = Mingle(c) - self.assertTrue(mingle.enabled) - - Aig = LimitedSet() - Big = LimitedSet() - Aig.add('Aig-1') - Aig.add('Aig-2') - Big.add('Big-1') - - I = c.app.control.inspect.return_value = Mock() - I.hello.return_value = { - 'A@example.com': { - 'clock': 312, - 'revoked': Aig._data, - }, - 'B@example.com': { - 'clock': 29, - 'revoked': Big._data, - }, - 'C@example.com': { - 'error': 'unknown method', - }, - } - - mingle.start(c) - I.hello.assert_called_with(c.hostname, worker_state.revoked._data) - c.app.clock.adjust.assert_has_calls([ - call(312), call(29), - ], any_order=True) - self.assertIn('Aig-1', worker_state.revoked) - self.assertIn('Aig-2', worker_state.revoked) - self.assertIn('Big-1', worker_state.revoked) - finally: - worker_state.revoked.clear() - - -def _amqp_connection(): - connection = ContextMock() - connection.return_value = ContextMock() - connection.return_value.transport.driver_type = 'amqp' - return connection - - -class test_Gossip(AppCase): - - def test_init(self): - c = self.Consumer() - c.app.connection = _amqp_connection() - g = Gossip(c) - self.assertTrue(g.enabled) - self.assertIs(c.gossip, g) - - def test_election(self): - c = self.Consumer() - c.app.connection = _amqp_connection() - g = Gossip(c) - g.start(c) - g.election('id', 'topic', 'action') - self.assertListEqual(g.consensus_replies['id'], []) - g.dispatcher.send.assert_called_with( - 'worker-elect', id='id', topic='topic', cver=1, action='action', - ) - - def test_call_task(self): - c = self.Consumer() - c.app.connection = _amqp_connection() - g = Gossip(c) - g.start(c) - - with patch('celery.worker.consumer.signature') as signature: - sig = signature.return_value = Mock() - task = Mock() - g.call_task(task) - signature.assert_called_with(task, app=c.app) - sig.apply_async.assert_called_with() - - sig.apply_async.side_effect = MemoryError() - with patch('celery.worker.consumer.error') as error: - g.call_task(task) - self.assertTrue(error.called) - - def Event(self, id='id', clock=312, - hostname='foo@example.com', pid=4312, - topic='topic', action='action', cver=1): - return { - 'id': id, - 'clock': clock, - 'hostname': hostname, - 'pid': pid, - 'topic': topic, - 'action': action, - 'cver': cver, - } - - def test_on_elect(self): - c = self.Consumer() - c.app.connection = _amqp_connection() - g = Gossip(c) - g.start(c) - - event = self.Event('id1') - g.on_elect(event) - in_heap = g.consensus_requests['id1'] - self.assertTrue(in_heap) - g.dispatcher.send.assert_called_with('worker-elect-ack', id='id1') - - event.pop('clock') - with patch('celery.worker.consumer.error') as error: - g.on_elect(event) - self.assertTrue(error.called) - - def Consumer(self, hostname='foo@x.com', pid=4312): - c = Mock() - c.app.connection = _amqp_connection() - c.hostname = hostname - c.pid = pid - return c - - def setup_election(self, g, c): - g.start(c) - g.clock = self.app.clock - self.assertNotIn('idx', g.consensus_replies) - self.assertIsNone(g.on_elect_ack({'id': 'idx'})) - - g.state.alive_workers.return_value = [ - 'foo@x.com', 'bar@x.com', 'baz@x.com', - ] - g.consensus_replies['id1'] = [] - g.consensus_requests['id1'] = [] - e1 = self.Event('id1', 1, 'foo@x.com') - e2 = self.Event('id1', 2, 'bar@x.com') - e3 = self.Event('id1', 3, 'baz@x.com') - g.on_elect(e1) - g.on_elect(e2) - g.on_elect(e3) - self.assertEqual(len(g.consensus_requests['id1']), 3) - - with patch('celery.worker.consumer.info'): - g.on_elect_ack(e1) - self.assertEqual(len(g.consensus_replies['id1']), 1) - g.on_elect_ack(e2) - self.assertEqual(len(g.consensus_replies['id1']), 2) - g.on_elect_ack(e3) - with self.assertRaises(KeyError): - g.consensus_replies['id1'] - - def test_on_elect_ack_win(self): - c = self.Consumer(hostname='foo@x.com') # I will win - g = Gossip(c) - handler = g.election_handlers['topic'] = Mock() - self.setup_election(g, c) - handler.assert_called_with('action') - - def test_on_elect_ack_lose(self): - c = self.Consumer(hostname='bar@x.com') # I will lose - c.app.connection = _amqp_connection() - g = Gossip(c) - handler = g.election_handlers['topic'] = Mock() - self.setup_election(g, c) - self.assertFalse(handler.called) - - def test_on_elect_ack_win_but_no_action(self): - c = self.Consumer(hostname='foo@x.com') # I will win - g = Gossip(c) - g.election_handlers = {} - with patch('celery.worker.consumer.error') as error: - self.setup_election(g, c) - self.assertTrue(error.called) - - def test_on_node_join(self): - c = self.Consumer() - g = Gossip(c) - with patch('celery.worker.consumer.debug') as debug: - g.on_node_join(c) - debug.assert_called_with('%s joined the party', 'foo@x.com') - - def test_on_node_leave(self): - c = self.Consumer() - g = Gossip(c) - with patch('celery.worker.consumer.debug') as debug: - g.on_node_leave(c) - debug.assert_called_with('%s left', 'foo@x.com') - - def test_on_node_lost(self): - c = self.Consumer() - g = Gossip(c) - with patch('celery.worker.consumer.info') as info: - g.on_node_lost(c) - info.assert_called_with('missed heartbeat from %s', 'foo@x.com') - - def test_register_timer(self): - c = self.Consumer() - g = Gossip(c) - g.register_timer() - c.timer.call_repeatedly.assert_called_with(g.interval, g.periodic) - tref = g._tref - g.register_timer() - tref.cancel.assert_called_with() - - def test_periodic(self): - c = self.Consumer() - g = Gossip(c) - g.on_node_lost = Mock() - state = g.state = Mock() - worker = Mock() - state.workers = {'foo': worker} - worker.alive = True - worker.hostname = 'foo' - g.periodic() - - worker.alive = False - g.periodic() - g.on_node_lost.assert_called_with(worker) - with self.assertRaises(KeyError): - state.workers['foo'] - - def test_on_message(self): - c = self.Consumer() - g = Gossip(c) - self.assertTrue(g.enabled) - prepare = Mock() - prepare.return_value = 'worker-online', {} - c.app.events.State.assert_called_with( - on_node_join=g.on_node_join, - on_node_leave=g.on_node_leave, - max_tasks_in_memory=1, - ) - g.update_state = Mock() - worker = Mock() - g.on_node_join = Mock() - g.on_node_leave = Mock() - g.update_state.return_value = worker, 1 - message = Mock() - message.delivery_info = {'routing_key': 'worker-online'} - message.headers = {'hostname': 'other'} - - handler = g.event_handlers['worker-online'] = Mock() - g.on_message(prepare, message) - handler.assert_called_with(message.payload) - g.event_handlers = {} - - g.on_message(prepare, message) - - message.delivery_info = {'routing_key': 'worker-offline'} - prepare.return_value = 'worker-offline', {} - g.on_message(prepare, message) - - message.delivery_info = {'routing_key': 'worker-baz'} - prepare.return_value = 'worker-baz', {} - g.update_state.return_value = worker, 0 - g.on_message(prepare, message) - - message.headers = {'hostname': g.hostname} - g.on_message(prepare, message) - g.clock.forward.assert_called_with() diff --git a/awx/lib/site-packages/celery/tests/worker/test_control.py b/awx/lib/site-packages/celery/tests/worker/test_control.py deleted file mode 100644 index e613440ff3..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_control.py +++ /dev/null @@ -1,598 +0,0 @@ -from __future__ import absolute_import - -import sys -import socket - -from collections import defaultdict -from datetime import datetime, timedelta - -from kombu import pidbox - -from celery.datastructures import AttributeDict -from celery.five import Queue as FastQueue -from celery.utils import uuid -from celery.utils.timer2 import Timer -from celery.worker import WorkController as _WC -from celery.worker import consumer -from celery.worker import control -from celery.worker import state as worker_state -from celery.worker.job import Request -from celery.worker.state import revoked -from celery.worker.control import Panel -from celery.worker.pidbox import Pidbox, gPidbox - -from celery.tests.case import AppCase, Mock, call, patch - -hostname = socket.gethostname() - - -class WorkController(object): - autoscaler = None - - def stats(self): - return {'total': worker_state.total_count} - - -class Consumer(consumer.Consumer): - - def __init__(self, app): - self.app = app - self.buffer = FastQueue() - self.handle_task = self.buffer.put - self.timer = Timer() - self.event_dispatcher = Mock() - self.controller = WorkController() - self.task_consumer = Mock() - self.prefetch_multiplier = 1 - self.initial_prefetch_count = 1 - - from celery.concurrency.base import BasePool - self.pool = BasePool(10) - self.task_buckets = defaultdict(lambda: None) - - -class test_Pidbox(AppCase): - - def test_shutdown(self): - with patch('celery.worker.pidbox.ignore_errors') as eig: - parent = Mock() - pbox = Pidbox(parent) - pbox._close_channel = Mock() - self.assertIs(pbox.c, parent) - pconsumer = pbox.consumer = Mock() - cancel = pconsumer.cancel - pbox.shutdown(parent) - eig.assert_called_with(parent, cancel) - pbox._close_channel.assert_called_with(parent) - - -class test_Pidbox_green(AppCase): - - def test_stop(self): - parent = Mock() - g = gPidbox(parent) - stopped = g._node_stopped = Mock() - shutdown = g._node_shutdown = Mock() - close_chan = g._close_channel = Mock() - - g.stop(parent) - shutdown.set.assert_called_with() - stopped.wait.assert_called_with() - close_chan.assert_called_with(parent) - self.assertIsNone(g._node_stopped) - self.assertIsNone(g._node_shutdown) - - close_chan.reset() - g.stop(parent) - close_chan.assert_called_with(parent) - - def test_resets(self): - parent = Mock() - g = gPidbox(parent) - g._resets = 100 - g.reset() - self.assertEqual(g._resets, 101) - - def test_loop(self): - parent = Mock() - conn = parent.connect.return_value = self.app.connection() - drain = conn.drain_events = Mock() - g = gPidbox(parent) - parent.connection = Mock() - do_reset = g._do_reset = Mock() - - call_count = [0] - - def se(*args, **kwargs): - if call_count[0] > 2: - g._node_shutdown.set() - g.reset() - call_count[0] += 1 - drain.side_effect = se - g.loop(parent) - - self.assertEqual(do_reset.call_count, 4) - - -class test_ControlPanel(AppCase): - - def setup(self): - self.panel = self.create_panel(consumer=Consumer(self.app)) - - @self.app.task(rate_limit=200, shared=False) - def mytask(): - pass - self.mytask = mytask - - def create_state(self, **kwargs): - kwargs.setdefault('app', self.app) - kwargs.setdefault('hostname', hostname) - return AttributeDict(kwargs) - - def create_panel(self, **kwargs): - return self.app.control.mailbox.Node(hostname=hostname, - state=self.create_state(**kwargs), - handlers=Panel.data) - - def test_enable_events(self): - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - evd = consumer.event_dispatcher - evd.groups = set() - panel.handle('enable_events') - self.assertIn('task', evd.groups) - evd.groups = set(['task']) - self.assertIn('already enabled', panel.handle('enable_events')['ok']) - - def test_disable_events(self): - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - evd = consumer.event_dispatcher - evd.enabled = True - evd.groups = set(['task']) - panel.handle('disable_events') - self.assertNotIn('task', evd.groups) - self.assertIn('already disabled', panel.handle('disable_events')['ok']) - - def test_clock(self): - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - panel.state.app.clock.value = 313 - x = panel.handle('clock') - self.assertEqual(x['clock'], 313) - - def test_hello(self): - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - panel.state.app.clock.value = 313 - worker_state.revoked.add('revoked1') - try: - x = panel.handle('hello', {'from_node': 'george@vandelay.com'}) - self.assertIn('revoked1', x['revoked']) - self.assertEqual(x['clock'], 314) # incremented - finally: - worker_state.revoked.discard('revoked1') - - def test_conf(self): - return - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - self.app.conf.SOME_KEY6 = 'hello world' - x = panel.handle('dump_conf') - self.assertIn('SOME_KEY6', x) - - def test_election(self): - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - consumer.gossip = Mock() - panel.handle( - 'election', {'id': 'id', 'topic': 'topic', 'action': 'action'}, - ) - consumer.gossip.election.assert_called_with('id', 'topic', 'action') - - def test_heartbeat(self): - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - consumer.event_dispatcher.enabled = True - panel.handle('heartbeat') - self.assertIn(('worker-heartbeat', ), - consumer.event_dispatcher.send.call_args) - - def test_time_limit(self): - panel = self.create_panel(consumer=Mock()) - r = panel.handle('time_limit', arguments=dict( - task_name=self.mytask.name, hard=30, soft=10)) - self.assertEqual( - (self.mytask.time_limit, self.mytask.soft_time_limit), - (30, 10), - ) - self.assertIn('ok', r) - r = panel.handle('time_limit', arguments=dict( - task_name=self.mytask.name, hard=None, soft=None)) - self.assertEqual( - (self.mytask.time_limit, self.mytask.soft_time_limit), - (None, None), - ) - self.assertIn('ok', r) - - r = panel.handle('time_limit', arguments=dict( - task_name='248e8afya9s8dh921eh928', hard=30)) - self.assertIn('error', r) - - def test_active_queues(self): - import kombu - - x = kombu.Consumer(self.app.connection(), - [kombu.Queue('foo', kombu.Exchange('foo'), 'foo'), - kombu.Queue('bar', kombu.Exchange('bar'), 'bar')], - auto_declare=False) - consumer = Mock() - consumer.task_consumer = x - panel = self.create_panel(consumer=consumer) - r = panel.handle('active_queues') - self.assertListEqual(list(sorted(q['name'] for q in r)), - ['bar', 'foo']) - - def test_dump_tasks(self): - info = '\n'.join(self.panel.handle('dump_tasks')) - self.assertIn('mytask', info) - self.assertIn('rate_limit=200', info) - - def test_stats(self): - prev_count, worker_state.total_count = worker_state.total_count, 100 - try: - self.assertDictContainsSubset({'total': 100}, - self.panel.handle('stats')) - finally: - worker_state.total_count = prev_count - - def test_report(self): - self.panel.handle('report') - - def test_active(self): - r = Request({ - 'task': self.mytask.name, - 'id': 'do re mi', - 'args': (), - 'kwargs': {}, - }, app=self.app) - worker_state.active_requests.add(r) - try: - self.assertTrue(self.panel.handle('dump_active')) - finally: - worker_state.active_requests.discard(r) - - def test_pool_grow(self): - - class MockPool(object): - - def __init__(self, size=1): - self.size = size - - def grow(self, n=1): - self.size += n - - def shrink(self, n=1): - self.size -= n - - @property - def num_processes(self): - return self.size - - consumer = Consumer(self.app) - consumer.prefetch_multiplier = 8 - consumer.qos = Mock(name='qos') - consumer.pool = MockPool(1) - panel = self.create_panel(consumer=consumer) - - panel.handle('pool_grow') - self.assertEqual(consumer.pool.size, 2) - consumer.qos.increment_eventually.assert_called_with(8) - self.assertEqual(consumer.initial_prefetch_count, 16) - panel.handle('pool_shrink') - self.assertEqual(consumer.pool.size, 1) - consumer.qos.decrement_eventually.assert_called_with(8) - self.assertEqual(consumer.initial_prefetch_count, 8) - - panel.state.consumer = Mock() - panel.state.consumer.controller = Mock() - sc = panel.state.consumer.controller.autoscaler = Mock() - panel.handle('pool_grow') - self.assertTrue(sc.force_scale_up.called) - panel.handle('pool_shrink') - self.assertTrue(sc.force_scale_down.called) - - def test_add__cancel_consumer(self): - - class MockConsumer(object): - queues = [] - cancelled = [] - consuming = False - - def add_queue(self, queue): - self.queues.append(queue.name) - - def consume(self): - self.consuming = True - - def cancel_by_queue(self, queue): - self.cancelled.append(queue) - - def consuming_from(self, queue): - return queue in self.queues - - consumer = Consumer(self.app) - consumer.task_consumer = MockConsumer() - panel = self.create_panel(consumer=consumer) - - panel.handle('add_consumer', {'queue': 'MyQueue'}) - self.assertIn('MyQueue', consumer.task_consumer.queues) - self.assertTrue(consumer.task_consumer.consuming) - panel.handle('add_consumer', {'queue': 'MyQueue'}) - panel.handle('cancel_consumer', {'queue': 'MyQueue'}) - self.assertIn('MyQueue', consumer.task_consumer.cancelled) - - def test_revoked(self): - worker_state.revoked.clear() - worker_state.revoked.add('a1') - worker_state.revoked.add('a2') - - try: - self.assertEqual(sorted(self.panel.handle('dump_revoked')), - ['a1', 'a2']) - finally: - worker_state.revoked.clear() - - def test_dump_schedule(self): - consumer = Consumer(self.app) - panel = self.create_panel(consumer=consumer) - self.assertFalse(panel.handle('dump_schedule')) - r = Request({ - 'task': self.mytask.name, - 'id': 'CAFEBABE', - 'args': (), - 'kwargs': {}, - }, app=self.app) - consumer.timer.schedule.enter_at( - consumer.timer.Entry(lambda x: x, (r, )), - datetime.now() + timedelta(seconds=10)) - consumer.timer.schedule.enter_at( - consumer.timer.Entry(lambda x: x, (object(), )), - datetime.now() + timedelta(seconds=10)) - self.assertTrue(panel.handle('dump_schedule')) - - def test_dump_reserved(self): - consumer = Consumer(self.app) - worker_state.reserved_requests.add(Request({ - 'task': self.mytask.name, - 'id': uuid(), - 'args': (2, 2), - 'kwargs': {}, - }, app=self.app)) - try: - panel = self.create_panel(consumer=consumer) - response = panel.handle('dump_reserved', {'safe': True}) - self.assertDictContainsSubset( - {'name': self.mytask.name, - 'args': (2, 2), - 'kwargs': {}, - 'hostname': socket.gethostname()}, - response[0], - ) - worker_state.reserved_requests.clear() - self.assertFalse(panel.handle('dump_reserved')) - finally: - worker_state.reserved_requests.clear() - - def test_rate_limit_invalid_rate_limit_string(self): - e = self.panel.handle('rate_limit', arguments=dict( - task_name='tasks.add', rate_limit='x1240301#%!')) - self.assertIn('Invalid rate limit string', e.get('error')) - - def test_rate_limit(self): - - class xConsumer(object): - reset = False - - def reset_rate_limits(self): - self.reset = True - - consumer = xConsumer() - panel = self.create_panel(app=self.app, consumer=consumer) - - task = self.app.tasks[self.mytask.name] - panel.handle('rate_limit', arguments=dict(task_name=task.name, - rate_limit='100/m')) - self.assertEqual(task.rate_limit, '100/m') - self.assertTrue(consumer.reset) - consumer.reset = False - panel.handle('rate_limit', arguments=dict(task_name=task.name, - rate_limit=0)) - self.assertEqual(task.rate_limit, 0) - self.assertTrue(consumer.reset) - - def test_rate_limit_nonexistant_task(self): - self.panel.handle('rate_limit', arguments={ - 'task_name': 'xxxx.does.not.exist', - 'rate_limit': '1000/s'}) - - def test_unexposed_command(self): - with self.assertRaises(KeyError): - self.panel.handle('foo', arguments={}) - - def test_revoke_with_name(self): - tid = uuid() - m = {'method': 'revoke', - 'destination': hostname, - 'arguments': {'task_id': tid, - 'task_name': self.mytask.name}} - self.panel.handle_message(m, None) - self.assertIn(tid, revoked) - - def test_revoke_with_name_not_in_registry(self): - tid = uuid() - m = {'method': 'revoke', - 'destination': hostname, - 'arguments': {'task_id': tid, - 'task_name': 'xxxxxxxxx33333333388888'}} - self.panel.handle_message(m, None) - self.assertIn(tid, revoked) - - def test_revoke(self): - tid = uuid() - m = {'method': 'revoke', - 'destination': hostname, - 'arguments': {'task_id': tid}} - self.panel.handle_message(m, None) - self.assertIn(tid, revoked) - - m = {'method': 'revoke', - 'destination': 'does.not.exist', - 'arguments': {'task_id': tid + 'xxx'}} - self.panel.handle_message(m, None) - self.assertNotIn(tid + 'xxx', revoked) - - def test_revoke_terminate(self): - request = Mock() - request.id = tid = uuid() - worker_state.reserved_requests.add(request) - try: - r = control.revoke(Mock(), tid, terminate=True) - self.assertIn(tid, revoked) - self.assertTrue(request.terminate.call_count) - self.assertIn('terminate:', r['ok']) - # unknown task id only revokes - r = control.revoke(Mock(), uuid(), terminate=True) - self.assertIn('tasks unknown', r['ok']) - finally: - worker_state.reserved_requests.discard(request) - - def test_autoscale(self): - self.panel.state.consumer = Mock() - self.panel.state.consumer.controller = Mock() - sc = self.panel.state.consumer.controller.autoscaler = Mock() - sc.update.return_value = 10, 2 - m = {'method': 'autoscale', - 'destination': hostname, - 'arguments': {'max': '10', 'min': '2'}} - r = self.panel.handle_message(m, None) - self.assertIn('ok', r) - - self.panel.state.consumer.controller.autoscaler = None - r = self.panel.handle_message(m, None) - self.assertIn('error', r) - - def test_ping(self): - m = {'method': 'ping', - 'destination': hostname} - r = self.panel.handle_message(m, None) - self.assertEqual(r, {'ok': 'pong'}) - - def test_shutdown(self): - m = {'method': 'shutdown', - 'destination': hostname} - with self.assertRaises(SystemExit): - self.panel.handle_message(m, None) - - def test_panel_reply(self): - - replies = [] - - class _Node(pidbox.Node): - - def reply(self, data, exchange, routing_key, **kwargs): - replies.append(data) - - panel = _Node(hostname=hostname, - state=self.create_state(consumer=Consumer(self.app)), - handlers=Panel.data, - mailbox=self.app.control.mailbox) - r = panel.dispatch('ping', reply_to={'exchange': 'x', - 'routing_key': 'x'}) - self.assertEqual(r, {'ok': 'pong'}) - self.assertDictEqual(replies[0], {panel.hostname: {'ok': 'pong'}}) - - def test_pool_restart(self): - consumer = Consumer(self.app) - consumer.controller = _WC(app=self.app) - consumer.controller.consumer = consumer - consumer.controller.pool.restart = Mock() - consumer.reset_rate_limits = Mock(name='reset_rate_limits()') - consumer.update_strategies = Mock(name='update_strategies()') - consumer.event_dispatcher = Mock(name='evd') - panel = self.create_panel(consumer=consumer) - assert panel.state.consumer.controller.consumer is consumer - panel.app = self.app - _import = panel.app.loader.import_from_cwd = Mock() - _reload = Mock() - - with self.assertRaises(ValueError): - panel.handle('pool_restart', {'reloader': _reload}) - - self.app.conf.CELERYD_POOL_RESTARTS = True - panel.handle('pool_restart', {'reloader': _reload}) - self.assertTrue(consumer.controller.pool.restart.called) - consumer.reset_rate_limits.assert_called_with() - consumer.update_strategies.assert_called_with() - self.assertFalse(_reload.called) - self.assertFalse(_import.called) - - def test_pool_restart_import_modules(self): - consumer = Consumer(self.app) - consumer.controller = _WC(app=self.app) - consumer.controller.consumer = consumer - consumer.controller.pool.restart = Mock() - consumer.reset_rate_limits = Mock(name='reset_rate_limits()') - consumer.update_strategies = Mock(name='update_strategies()') - panel = self.create_panel(consumer=consumer) - panel.app = self.app - assert panel.state.consumer.controller.consumer is consumer - _import = consumer.controller.app.loader.import_from_cwd = Mock() - _reload = Mock() - - self.app.conf.CELERYD_POOL_RESTARTS = True - panel.handle('pool_restart', {'modules': ['foo', 'bar'], - 'reloader': _reload}) - - self.assertTrue(consumer.controller.pool.restart.called) - consumer.reset_rate_limits.assert_called_with() - consumer.update_strategies.assert_called_with() - self.assertFalse(_reload.called) - self.assertItemsEqual( - [call('bar'), call('foo')], - _import.call_args_list, - ) - - def test_pool_restart_reload_modules(self): - consumer = Consumer(self.app) - consumer.controller = _WC(app=self.app) - consumer.controller.consumer = consumer - consumer.controller.pool.restart = Mock() - consumer.reset_rate_limits = Mock(name='reset_rate_limits()') - consumer.update_strategies = Mock(name='update_strategies()') - panel = self.create_panel(consumer=consumer) - panel.app = self.app - _import = panel.app.loader.import_from_cwd = Mock() - _reload = Mock() - - self.app.conf.CELERYD_POOL_RESTARTS = True - with patch.dict(sys.modules, {'foo': None}): - panel.handle('pool_restart', {'modules': ['foo'], - 'reload': False, - 'reloader': _reload}) - - self.assertTrue(consumer.controller.pool.restart.called) - self.assertFalse(_reload.called) - self.assertFalse(_import.called) - - _import.reset_mock() - _reload.reset_mock() - consumer.controller.pool.restart.reset_mock() - - panel.handle('pool_restart', {'modules': ['foo'], - 'reload': True, - 'reloader': _reload}) - - self.assertTrue(consumer.controller.pool.restart.called) - self.assertTrue(_reload.called) - self.assertFalse(_import.called) diff --git a/awx/lib/site-packages/celery/tests/worker/test_heartbeat.py b/awx/lib/site-packages/celery/tests/worker/test_heartbeat.py deleted file mode 100644 index 5568e4ec4c..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_heartbeat.py +++ /dev/null @@ -1,73 +0,0 @@ -from __future__ import absolute_import - -from celery.worker.heartbeat import Heart -from celery.tests.case import AppCase - - -class MockDispatcher(object): - heart = None - next_iter = 0 - - def __init__(self): - self.sent = [] - self.on_enabled = set() - self.on_disabled = set() - self.enabled = True - - def send(self, msg, **_fields): - self.sent.append(msg) - if self.heart: - if self.next_iter > 10: - self.heart._shutdown.set() - self.next_iter += 1 - - -class MockDispatcherRaising(object): - - def send(self, msg): - if msg == 'worker-offline': - raise Exception('foo') - - -class MockTimer(object): - - def call_repeatedly(self, secs, fun, args=(), kwargs={}): - - class entry(tuple): - cancelled = False - - def cancel(self): - self.cancelled = True - - return entry((secs, fun, args, kwargs)) - - def cancel(self, entry): - entry.cancel() - - -class test_Heart(AppCase): - - def test_start_stop(self): - timer = MockTimer() - eventer = MockDispatcher() - h = Heart(timer, eventer, interval=1) - h.start() - self.assertTrue(h.tref) - h.stop() - self.assertIsNone(h.tref) - h.stop() - - def test_start_when_disabled(self): - timer = MockTimer() - eventer = MockDispatcher() - eventer.enabled = False - h = Heart(timer, eventer) - h.start() - self.assertFalse(h.tref) - - def test_stop_when_disabled(self): - timer = MockTimer() - eventer = MockDispatcher() - eventer.enabled = False - h = Heart(timer, eventer) - h.stop() diff --git a/awx/lib/site-packages/celery/tests/worker/test_hub.py b/awx/lib/site-packages/celery/tests/worker/test_hub.py deleted file mode 100644 index 4e9e4906e4..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_hub.py +++ /dev/null @@ -1,341 +0,0 @@ -from __future__ import absolute_import - -from kombu.async import Hub, READ, WRITE, ERR -from kombu.async.debug import callback_for, repr_flag, _rcb -from kombu.async.semaphore import DummyLock, LaxBoundedSemaphore - -from celery.five import range -from celery.tests.case import Case, Mock, call, patch - - -class File(object): - - def __init__(self, fd): - self.fd = fd - - def fileno(self): - return self.fd - - def __eq__(self, other): - if isinstance(other, File): - return self.fd == other.fd - return NotImplemented - - def __hash__(self): - return hash(self.fd) - - -class test_DummyLock(Case): - - def test_context(self): - mutex = DummyLock() - with mutex: - pass - - -class test_LaxBoundedSemaphore(Case): - - def test_acquire_release(self): - x = LaxBoundedSemaphore(2) - - c1 = Mock() - x.acquire(c1, 1) - self.assertEqual(x.value, 1) - c1.assert_called_with(1) - - c2 = Mock() - x.acquire(c2, 2) - self.assertEqual(x.value, 0) - c2.assert_called_with(2) - - c3 = Mock() - x.acquire(c3, 3) - self.assertEqual(x.value, 0) - self.assertFalse(c3.called) - - x.release() - self.assertEqual(x.value, 0) - x.release() - self.assertEqual(x.value, 1) - x.release() - self.assertEqual(x.value, 2) - c3.assert_called_with(3) - - def test_bounded(self): - x = LaxBoundedSemaphore(2) - for i in range(100): - x.release() - self.assertEqual(x.value, 2) - - def test_grow_shrink(self): - x = LaxBoundedSemaphore(1) - self.assertEqual(x.initial_value, 1) - cb1 = Mock() - x.acquire(cb1, 1) - cb1.assert_called_with(1) - self.assertEqual(x.value, 0) - - cb2 = Mock() - x.acquire(cb2, 2) - self.assertFalse(cb2.called) - self.assertEqual(x.value, 0) - - cb3 = Mock() - x.acquire(cb3, 3) - self.assertFalse(cb3.called) - - x.grow(2) - cb2.assert_called_with(2) - cb3.assert_called_with(3) - self.assertEqual(x.value, 2) - self.assertEqual(x.initial_value, 3) - - self.assertFalse(x._waiting) - x.grow(3) - for i in range(x.initial_value): - self.assertTrue(x.acquire(Mock())) - self.assertFalse(x.acquire(Mock())) - x.clear() - - x.shrink(3) - for i in range(x.initial_value): - self.assertTrue(x.acquire(Mock())) - self.assertFalse(x.acquire(Mock())) - self.assertEqual(x.value, 0) - - for i in range(100): - x.release() - self.assertEqual(x.value, x.initial_value) - - def test_clear(self): - x = LaxBoundedSemaphore(10) - for i in range(11): - x.acquire(Mock()) - self.assertTrue(x._waiting) - self.assertEqual(x.value, 0) - - x.clear() - self.assertFalse(x._waiting) - self.assertEqual(x.value, x.initial_value) - - -class test_Hub(Case): - - def test_repr_flag(self): - self.assertEqual(repr_flag(READ), 'R') - self.assertEqual(repr_flag(WRITE), 'W') - self.assertEqual(repr_flag(ERR), '!') - self.assertEqual(repr_flag(READ | WRITE), 'RW') - self.assertEqual(repr_flag(READ | ERR), 'R!') - self.assertEqual(repr_flag(WRITE | ERR), 'W!') - self.assertEqual(repr_flag(READ | WRITE | ERR), 'RW!') - - def test_repr_callback_rcb(self): - - def f(): - pass - - self.assertEqual(_rcb(f), f.__name__) - self.assertEqual(_rcb('foo'), 'foo') - - @patch('kombu.async.hub.poll') - def test_start_stop(self, poll): - hub = Hub() - poll.assert_called_with() - - poller = hub.poller - hub.stop() - hub.close() - poller.close.assert_called_with() - - def test_fire_timers(self): - hub = Hub() - hub.timer = Mock() - hub.timer._queue = [] - self.assertEqual(hub.fire_timers(min_delay=42.324, - max_delay=32.321), 32.321) - - hub.timer._queue = [1] - hub.scheduler = iter([(3.743, None)]) - self.assertEqual(hub.fire_timers(), 3.743) - - e1, e2, e3 = Mock(), Mock(), Mock() - entries = [e1, e2, e3] - - reset = lambda: [m.reset() for m in [e1, e2, e3]] - - def se(): - while 1: - while entries: - yield None, entries.pop() - yield 3.982, None - hub.scheduler = se() - - self.assertEqual(hub.fire_timers(max_timers=10), 3.982) - for E in [e3, e2, e1]: - E.assert_called_with() - reset() - - entries[:] = [Mock() for _ in range(11)] - keep = list(entries) - self.assertEqual(hub.fire_timers(max_timers=10, min_delay=1.13), 1.13) - for E in reversed(keep[1:]): - E.assert_called_with() - reset() - self.assertEqual(hub.fire_timers(max_timers=10), 3.982) - keep[0].assert_called_with() - - def test_fire_timers_raises(self): - hub = Hub() - eback = Mock() - eback.side_effect = KeyError('foo') - hub.timer = Mock() - hub.scheduler = iter([(0, eback)]) - with self.assertRaises(KeyError): - hub.fire_timers(propagate=(KeyError, )) - - eback.side_effect = ValueError('foo') - hub.scheduler = iter([(0, eback)]) - with patch('kombu.async.hub.logger') as logger: - with self.assertRaises(StopIteration): - hub.fire_timers() - self.assertTrue(logger.error.called) - - def test_add_raises_ValueError(self): - hub = Hub() - hub.poller = Mock(name='hub.poller') - hub.poller.register.side_effect = ValueError() - hub._discard = Mock(name='hub.discard') - with self.assertRaises(ValueError): - hub.add(2, Mock(), READ) - hub._discard.assert_called_with(2) - - def test_repr_active(self): - hub = Hub() - hub.readers = {1: Mock(), 2: Mock()} - hub.writers = {3: Mock(), 4: Mock()} - for value in list(hub.readers.values()) + list(hub.writers.values()): - value.__name__ = 'mock' - self.assertTrue(hub.repr_active()) - - def test_repr_events(self): - hub = Hub() - hub.readers = {6: Mock(), 7: Mock(), 8: Mock()} - hub.writers = {9: Mock()} - for value in list(hub.readers.values()) + list(hub.writers.values()): - value.__name__ = 'mock' - self.assertTrue(hub.repr_events([ - (6, READ), - (7, ERR), - (8, READ | ERR), - (9, WRITE), - (10, 13213), - ])) - - def test_callback_for(self): - hub = Hub() - reader, writer = Mock(), Mock() - hub.readers = {6: reader} - hub.writers = {7: writer} - - self.assertEqual(callback_for(hub, 6, READ), reader) - self.assertEqual(callback_for(hub, 7, WRITE), writer) - with self.assertRaises(KeyError): - callback_for(hub, 6, WRITE) - self.assertEqual(callback_for(hub, 6, WRITE, 'foo'), 'foo') - - def test_add_remove_readers(self): - hub = Hub() - P = hub.poller = Mock() - - read_A = Mock() - read_B = Mock() - hub.add_reader(10, read_A, 10) - hub.add_reader(File(11), read_B, 11) - - P.register.assert_has_calls([ - call(10, hub.READ | hub.ERR), - call(11, hub.READ | hub.ERR), - ], any_order=True) - - self.assertEqual(hub.readers[10], (read_A, (10, ))) - self.assertEqual(hub.readers[11], (read_B, (11, ))) - - hub.remove(10) - self.assertNotIn(10, hub.readers) - hub.remove(File(11)) - self.assertNotIn(11, hub.readers) - P.unregister.assert_has_calls([ - call(10), call(11), - ]) - - def test_can_remove_unknown_fds(self): - hub = Hub() - hub.poller = Mock() - hub.remove(30) - hub.remove(File(301)) - - def test_remove__unregister_raises(self): - hub = Hub() - hub.poller = Mock() - hub.poller.unregister.side_effect = OSError() - - hub.remove(313) - - def test_add_writers(self): - hub = Hub() - P = hub.poller = Mock() - - write_A = Mock() - write_B = Mock() - hub.add_writer(20, write_A) - hub.add_writer(File(21), write_B) - - P.register.assert_has_calls([ - call(20, hub.WRITE), - call(21, hub.WRITE), - ], any_order=True) - - self.assertEqual(hub.writers[20], (write_A, ())) - self.assertEqual(hub.writers[21], (write_B, ())) - - hub.remove(20) - self.assertNotIn(20, hub.writers) - hub.remove(File(21)) - self.assertNotIn(21, hub.writers) - P.unregister.assert_has_calls([ - call(20), call(21), - ]) - - def test_enter__exit(self): - hub = Hub() - P = hub.poller = Mock() - on_close = Mock() - hub.on_close.add(on_close) - - try: - read_A = Mock() - read_B = Mock() - hub.add_reader(10, read_A) - hub.add_reader(File(11), read_B) - write_A = Mock() - write_B = Mock() - hub.add_writer(20, write_A) - hub.add_writer(File(21), write_B) - self.assertTrue(hub.readers) - self.assertTrue(hub.writers) - finally: - assert hub.poller - hub.close() - self.assertFalse(hub.readers) - self.assertFalse(hub.writers) - - P.unregister.assert_has_calls([ - call(10), call(11), call(20), call(21), - ], any_order=True) - - on_close.assert_called_with(hub) - - def test_scheduler_property(self): - hub = Hub(timer=[1, 2, 3]) - self.assertEqual(list(hub.scheduler), [1, 2, 3]) diff --git a/awx/lib/site-packages/celery/tests/worker/test_loops.py b/awx/lib/site-packages/celery/tests/worker/test_loops.py deleted file mode 100644 index 00c5d960f1..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_loops.py +++ /dev/null @@ -1,416 +0,0 @@ -from __future__ import absolute_import - -import socket - -from kombu.async import Hub, READ, WRITE, ERR - -from celery.bootsteps import CLOSE, RUN -from celery.exceptions import InvalidTaskError, WorkerShutdown, WorkerTerminate -from celery.five import Empty -from celery.worker import state -from celery.worker.consumer import Consumer -from celery.worker.loops import asynloop, synloop - -from celery.tests.case import AppCase, Mock, body_from_sig - - -class X(object): - - def __init__(self, app, heartbeat=None, on_task_message=None): - hub = Hub() - ( - self.obj, - self.connection, - self.consumer, - self.blueprint, - self.hub, - self.qos, - self.heartbeat, - self.clock, - ) = self.args = [Mock(name='obj'), - Mock(name='connection'), - Mock(name='consumer'), - Mock(name='blueprint'), - hub, - Mock(name='qos'), - heartbeat, - Mock(name='clock')] - self.connection.supports_heartbeats = True - self.connection.get_heartbeat_interval.side_effect = ( - lambda: self.heartbeat - ) - self.consumer.callbacks = [] - self.obj.strategies = {} - self.connection.connection_errors = (socket.error, ) - self.hub.readers = {} - self.hub.writers = {} - self.hub.consolidate = set() - self.hub.timer = Mock(name='hub.timer') - self.hub.timer._queue = [Mock()] - self.hub.fire_timers = Mock(name='hub.fire_timers') - self.hub.fire_timers.return_value = 1.7 - self.hub.poller = Mock(name='hub.poller') - self.hub.close = Mock(name='hub.close()') # asynloop calls hub.close - self.Hub = self.hub - self.blueprint.state = RUN - # need this for create_task_handler - _consumer = Consumer(Mock(), timer=Mock(), app=app) - _consumer.on_task_message = on_task_message or [] - self.obj.create_task_handler = _consumer.create_task_handler - self.on_unknown_message = self.obj.on_unknown_message = Mock( - name='on_unknown_message', - ) - _consumer.on_unknown_message = self.on_unknown_message - self.on_unknown_task = self.obj.on_unknown_task = Mock( - name='on_unknown_task', - ) - _consumer.on_unknown_task = self.on_unknown_task - self.on_invalid_task = self.obj.on_invalid_task = Mock( - name='on_invalid_task', - ) - _consumer.on_invalid_task = self.on_invalid_task - _consumer.strategies = self.obj.strategies - - def timeout_then_error(self, mock): - - def first(*args, **kwargs): - mock.side_effect = socket.error() - self.connection.more_to_read = False - raise socket.timeout() - mock.side_effect = first - - def close_then_error(self, mock=None, mod=0, exc=None): - mock = Mock() if mock is None else mock - - def first(*args, **kwargs): - if not mod or mock.call_count > mod: - self.close() - self.connection.more_to_read = False - raise (socket.error() if exc is None else exc) - mock.side_effect = first - return mock - - def close(self, *args, **kwargs): - self.blueprint.state = CLOSE - - def closer(self, mock=None, mod=0): - mock = Mock() if mock is None else mock - - def closing(*args, **kwargs): - if not mod or mock.call_count >= mod: - self.close() - mock.side_effect = closing - return mock - - -def get_task_callback(*args, **kwargs): - x = X(*args, **kwargs) - x.blueprint.state = CLOSE - asynloop(*x.args) - return x, x.consumer.callbacks[0] - - -class test_asynloop(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def add(x, y): - return x + y - self.add = add - - def test_setup_heartbeat(self): - x = X(self.app, heartbeat=10) - x.hub.call_repeatedly = Mock(name='x.hub.call_repeatedly()') - x.blueprint.state = CLOSE - asynloop(*x.args) - x.consumer.consume.assert_called_with() - x.obj.on_ready.assert_called_with() - x.hub.call_repeatedly.assert_called_with( - 10 / 2.0, x.connection.heartbeat_check, 2.0, - ) - - def task_context(self, sig, **kwargs): - x, on_task = get_task_callback(self.app, **kwargs) - body = body_from_sig(self.app, sig) - message = Mock() - strategy = x.obj.strategies[sig.task] = Mock() - return x, on_task, body, message, strategy - - def test_on_task_received(self): - _, on_task, body, msg, strategy = self.task_context(self.add.s(2, 2)) - on_task(body, msg) - strategy.assert_called_with( - msg, body, msg.ack_log_error, msg.reject_log_error, [], - ) - - def test_on_task_received_executes_on_task_message(self): - cbs = [Mock(), Mock(), Mock()] - _, on_task, body, msg, strategy = self.task_context( - self.add.s(2, 2), on_task_message=cbs, - ) - on_task(body, msg) - strategy.assert_called_with( - msg, body, msg.ack_log_error, msg.reject_log_error, cbs, - ) - - def test_on_task_message_missing_name(self): - x, on_task, body, msg, strategy = self.task_context(self.add.s(2, 2)) - body.pop('task') - on_task(body, msg) - x.on_unknown_message.assert_called_with(body, msg) - - def test_on_task_not_registered(self): - x, on_task, body, msg, strategy = self.task_context(self.add.s(2, 2)) - exc = strategy.side_effect = KeyError(self.add.name) - on_task(body, msg) - x.on_unknown_task.assert_called_with(body, msg, exc) - - def test_on_task_InvalidTaskError(self): - x, on_task, body, msg, strategy = self.task_context(self.add.s(2, 2)) - exc = strategy.side_effect = InvalidTaskError() - on_task(body, msg) - x.on_invalid_task.assert_called_with(body, msg, exc) - - def test_should_terminate(self): - x = X(self.app) - # XXX why aren't the errors propagated?!? - state.should_terminate = True - try: - with self.assertRaises(WorkerTerminate): - asynloop(*x.args) - finally: - state.should_terminate = False - - def test_should_terminate_hub_close_raises(self): - x = X(self.app) - # XXX why aren't the errors propagated?!? - state.should_terminate = True - x.hub.close.side_effect = MemoryError() - try: - with self.assertRaises(WorkerTerminate): - asynloop(*x.args) - finally: - state.should_terminate = False - - def test_should_stop(self): - x = X(self.app) - state.should_stop = True - try: - with self.assertRaises(WorkerShutdown): - asynloop(*x.args) - finally: - state.should_stop = False - - def test_updates_qos(self): - x = X(self.app) - x.qos.prev = 3 - x.qos.value = 3 - x.hub.on_tick.add(x.closer(mod=2)) - x.hub.timer._queue = [1] - asynloop(*x.args) - self.assertFalse(x.qos.update.called) - - x = X(self.app) - x.qos.prev = 1 - x.qos.value = 6 - x.hub.on_tick.add(x.closer(mod=2)) - asynloop(*x.args) - x.qos.update.assert_called_with() - x.hub.fire_timers.assert_called_with(propagate=(socket.error, )) - - def test_poll_empty(self): - x = X(self.app) - x.hub.readers = {6: Mock()} - x.hub.timer._queue = [1] - x.close_then_error(x.hub.poller.poll) - x.hub.fire_timers.return_value = 33.37 - poller = x.hub.poller - poller.poll.return_value = [] - with self.assertRaises(socket.error): - asynloop(*x.args) - poller.poll.assert_called_with(33.37) - - def test_poll_readable(self): - x = X(self.app) - reader = Mock(name='reader') - x.hub.add_reader(6, reader, 6) - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), mod=4)) - poller = x.hub.poller - poller.poll.return_value = [(6, READ)] - with self.assertRaises(socket.error): - asynloop(*x.args) - reader.assert_called_with(6) - self.assertTrue(poller.poll.called) - - def test_poll_readable_raises_Empty(self): - x = X(self.app) - reader = Mock(name='reader') - x.hub.add_reader(6, reader, 6) - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), 2)) - poller = x.hub.poller - poller.poll.return_value = [(6, READ)] - reader.side_effect = Empty() - with self.assertRaises(socket.error): - asynloop(*x.args) - reader.assert_called_with(6) - self.assertTrue(poller.poll.called) - - def test_poll_writable(self): - x = X(self.app) - writer = Mock(name='writer') - x.hub.add_writer(6, writer, 6) - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), 2)) - poller = x.hub.poller - poller.poll.return_value = [(6, WRITE)] - with self.assertRaises(socket.error): - asynloop(*x.args) - writer.assert_called_with(6) - self.assertTrue(poller.poll.called) - - def test_poll_writable_none_registered(self): - x = X(self.app) - writer = Mock(name='writer') - x.hub.add_writer(6, writer, 6) - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), 2)) - poller = x.hub.poller - poller.poll.return_value = [(7, WRITE)] - with self.assertRaises(socket.error): - asynloop(*x.args) - self.assertTrue(poller.poll.called) - - def test_poll_unknown_event(self): - x = X(self.app) - writer = Mock(name='reader') - x.hub.add_writer(6, writer, 6) - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), 2)) - poller = x.hub.poller - poller.poll.return_value = [(6, 0)] - with self.assertRaises(socket.error): - asynloop(*x.args) - self.assertTrue(poller.poll.called) - - def test_poll_keep_draining_disabled(self): - x = X(self.app) - x.hub.writers = {6: Mock()} - poll = x.hub.poller.poll - - def se(*args, **kwargs): - poll.side_effect = socket.error() - poll.side_effect = se - - poller = x.hub.poller - poll.return_value = [(6, 0)] - with self.assertRaises(socket.error): - asynloop(*x.args) - self.assertTrue(poller.poll.called) - - def test_poll_err_writable(self): - x = X(self.app) - writer = Mock(name='writer') - x.hub.add_writer(6, writer, 6, 48) - x.hub.on_tick.add(x.close_then_error(Mock(), 2)) - poller = x.hub.poller - poller.poll.return_value = [(6, ERR)] - with self.assertRaises(socket.error): - asynloop(*x.args) - writer.assert_called_with(6, 48) - self.assertTrue(poller.poll.called) - - def test_poll_write_generator(self): - x = X(self.app) - x.hub.remove = Mock(name='hub.remove()') - - def Gen(): - yield 1 - yield 2 - gen = Gen() - - x.hub.add_writer(6, gen) - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), 2)) - x.hub.poller.poll.return_value = [(6, WRITE)] - with self.assertRaises(socket.error): - asynloop(*x.args) - self.assertTrue(gen.gi_frame.f_lasti != -1) - self.assertFalse(x.hub.remove.called) - - def test_poll_write_generator_stopped(self): - x = X(self.app) - - def Gen(): - raise StopIteration() - yield - gen = Gen() - x.hub.add_writer(6, gen) - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), 2)) - x.hub.poller.poll.return_value = [(6, WRITE)] - x.hub.remove = Mock(name='hub.remove()') - with self.assertRaises(socket.error): - asynloop(*x.args) - self.assertIsNone(gen.gi_frame) - - def test_poll_write_generator_raises(self): - x = X(self.app) - - def Gen(): - raise ValueError('foo') - yield - gen = Gen() - x.hub.add_writer(6, gen) - x.hub.remove = Mock(name='hub.remove()') - x.hub.on_tick.add(x.close_then_error(Mock(name='tick'), 2)) - x.hub.poller.poll.return_value = [(6, WRITE)] - with self.assertRaises(ValueError): - asynloop(*x.args) - self.assertIsNone(gen.gi_frame) - x.hub.remove.assert_called_with(6) - - def test_poll_err_readable(self): - x = X(self.app) - reader = Mock(name='reader') - x.hub.add_reader(6, reader, 6, 24) - x.hub.on_tick.add(x.close_then_error(Mock(), 2)) - poller = x.hub.poller - poller.poll.return_value = [(6, ERR)] - with self.assertRaises(socket.error): - asynloop(*x.args) - reader.assert_called_with(6, 24) - self.assertTrue(poller.poll.called) - - def test_poll_raises_ValueError(self): - x = X(self.app) - x.hub.readers = {6: Mock()} - poller = x.hub.poller - x.close_then_error(poller.poll, exc=ValueError) - asynloop(*x.args) - self.assertTrue(poller.poll.called) - - -class test_synloop(AppCase): - - def test_timeout_ignored(self): - x = X(self.app) - x.timeout_then_error(x.connection.drain_events) - with self.assertRaises(socket.error): - synloop(*x.args) - self.assertEqual(x.connection.drain_events.call_count, 2) - - def test_updates_qos_when_changed(self): - x = X(self.app) - x.qos.prev = 2 - x.qos.value = 2 - x.timeout_then_error(x.connection.drain_events) - with self.assertRaises(socket.error): - synloop(*x.args) - self.assertFalse(x.qos.update.called) - - x.qos.value = 4 - x.timeout_then_error(x.connection.drain_events) - with self.assertRaises(socket.error): - synloop(*x.args) - x.qos.update.assert_called_with() - - def test_ignores_socket_errors_when_closed(self): - x = X(self.app) - x.close_then_error(x.connection.drain_events) - self.assertIsNone(synloop(*x.args)) diff --git a/awx/lib/site-packages/celery/tests/worker/test_request.py b/awx/lib/site-packages/celery/tests/worker/test_request.py deleted file mode 100644 index 488ea72f4d..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_request.py +++ /dev/null @@ -1,962 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import anyjson -import os -import signal -import socket -import sys - -from datetime import datetime, timedelta - -from billiard.einfo import ExceptionInfo -from kombu.transport.base import Message -from kombu.utils.encoding import from_utf8, default_encode - -from celery import states -from celery.app.trace import ( - trace_task, - _trace_task_ret, - TraceInfo, - mro_lookup, - build_tracer, - setup_worker_optimizations, - reset_worker_optimizations, -) -from celery.concurrency.base import BasePool -from celery.exceptions import ( - Ignore, - InvalidTaskError, - Retry, - TaskRevokedError, - Terminated, - WorkerLostError, -) -from celery.five import keys, monotonic -from celery.signals import task_revoked -from celery.utils import uuid -from celery.worker import job as module -from celery.worker.job import Request, logger as req_logger -from celery.worker.state import revoked - -from celery.tests.case import ( - AppCase, - Case, - Mock, - SkipTest, - assert_signal_called, - body_from_sig, - patch, -) - - -class test_mro_lookup(Case): - - def test_order(self): - - class A(object): - pass - - class B(A): - pass - - class C(B): - pass - - class D(C): - - @classmethod - def mro(cls): - return () - - A.x = 10 - self.assertEqual(mro_lookup(C, 'x'), A) - self.assertIsNone(mro_lookup(C, 'x', stop=(A, ))) - B.x = 10 - self.assertEqual(mro_lookup(C, 'x'), B) - C.x = 10 - self.assertEqual(mro_lookup(C, 'x'), C) - self.assertIsNone(mro_lookup(D, 'x')) - - -def jail(app, task_id, name, args, kwargs): - request = {'id': task_id} - task = app.tasks[name] - task.__trace__ = None # rebuild - return trace_task( - task, task_id, args, kwargs, request=request, eager=False, app=app, - ) - - -class test_default_encode(AppCase): - - def setup(self): - if sys.version_info >= (3, 0): - raise SkipTest('py3k: not relevant') - - def test_jython(self): - prev, sys.platform = sys.platform, 'java 1.6.1' - try: - self.assertEqual(default_encode(bytes('foo')), 'foo') - finally: - sys.platform = prev - - def test_cpython(self): - prev, sys.platform = sys.platform, 'darwin' - gfe, sys.getfilesystemencoding = ( - sys.getfilesystemencoding, - lambda: 'utf-8', - ) - try: - self.assertEqual(default_encode(bytes('foo')), 'foo') - finally: - sys.platform = prev - sys.getfilesystemencoding = gfe - - -class test_Retry(AppCase): - - def test_retry_semipredicate(self): - try: - raise Exception('foo') - except Exception as exc: - ret = Retry('Retrying task', exc) - self.assertEqual(ret.exc, exc) - - -class test_trace_task(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def mytask(i, **kwargs): - return i ** i - self.mytask = mytask - - @self.app.task(shared=False) - def mytask_raising(i): - raise KeyError(i) - self.mytask_raising = mytask_raising - - @patch('celery.app.trace._logger') - def test_process_cleanup_fails(self, _logger): - self.mytask.backend = Mock() - self.mytask.backend.process_cleanup = Mock(side_effect=KeyError()) - tid = uuid() - ret = jail(self.app, tid, self.mytask.name, [2], {}) - self.assertEqual(ret, 4) - self.assertTrue(self.mytask.backend.store_result.called) - self.assertIn('Process cleanup failed', _logger.error.call_args[0][0]) - - def test_process_cleanup_BaseException(self): - self.mytask.backend = Mock() - self.mytask.backend.process_cleanup = Mock(side_effect=SystemExit()) - with self.assertRaises(SystemExit): - jail(self.app, uuid(), self.mytask.name, [2], {}) - - def test_execute_jail_success(self): - ret = jail(self.app, uuid(), self.mytask.name, [2], {}) - self.assertEqual(ret, 4) - - def test_marked_as_started(self): - _started = [] - - def store_result(tid, meta, state, **kwars): - if state == states.STARTED: - _started.append(tid) - self.mytask.backend.store_result = Mock(name='store_result') - self.mytask.backend.store_result.side_effect = store_result - self.mytask.track_started = True - - tid = uuid() - jail(self.app, tid, self.mytask.name, [2], {}) - self.assertIn(tid, _started) - - self.mytask.ignore_result = True - tid = uuid() - jail(self.app, tid, self.mytask.name, [2], {}) - self.assertNotIn(tid, _started) - - def test_execute_jail_failure(self): - ret = jail( - self.app, uuid(), self.mytask_raising.name, [4], {}, - ) - self.assertIsInstance(ret, ExceptionInfo) - self.assertTupleEqual(ret.exception.args, (4, )) - - def test_execute_ignore_result(self): - - @self.app.task(shared=False, ignore_result=True) - def ignores_result(i): - return i ** i - - task_id = uuid() - ret = jail(self.app, task_id, ignores_result.name, [4], {}) - self.assertEqual(ret, 256) - self.assertFalse(self.app.AsyncResult(task_id).ready()) - - -class MockEventDispatcher(object): - - def __init__(self): - self.sent = [] - self.enabled = True - - def send(self, event, **fields): - self.sent.append(event) - - -class test_Request(AppCase): - - def setup(self): - - @self.app.task(shared=False) - def add(x, y, **kw_): - return x + y - self.add = add - - @self.app.task(shared=False) - def mytask(i, **kwargs): - return i ** i - self.mytask = mytask - - @self.app.task(shared=False) - def mytask_raising(i): - raise KeyError(i) - self.mytask_raising = mytask_raising - - def get_request(self, sig, Request=Request, **kwargs): - return Request( - body_from_sig(self.app, sig), - on_ack=Mock(), - eventer=Mock(), - app=self.app, - connection_errors=(socket.error, ), - task=sig.type, - **kwargs - ) - - def test_invalid_eta_raises_InvalidTaskError(self): - with self.assertRaises(InvalidTaskError): - self.get_request(self.add.s(2, 2).set(eta='12345')) - - def test_invalid_expires_raises_InvalidTaskError(self): - with self.assertRaises(InvalidTaskError): - self.get_request(self.add.s(2, 2).set(expires='12345')) - - def test_valid_expires_with_utc_makes_aware(self): - with patch('celery.worker.job.maybe_make_aware') as mma: - self.get_request(self.add.s(2, 2).set(expires=10)) - self.assertTrue(mma.called) - - def test_maybe_expire_when_expires_is_None(self): - req = self.get_request(self.add.s(2, 2)) - self.assertFalse(req.maybe_expire()) - - def test_on_retry_acks_if_late(self): - self.add.acks_late = True - req = self.get_request(self.add.s(2, 2)) - req.on_retry(Mock()) - req.on_ack.assert_called_with(req_logger, req.connection_errors) - - def test_on_failure_Termianted(self): - einfo = None - try: - raise Terminated('9') - except Terminated: - einfo = ExceptionInfo() - self.assertIsNotNone(einfo) - req = self.get_request(self.add.s(2, 2)) - req.on_failure(einfo) - req.eventer.send.assert_called_with( - 'task-revoked', - uuid=req.id, terminated=True, signum='9', expired=False, - ) - - def test_log_error_propagates_MemoryError(self): - einfo = None - try: - raise MemoryError() - except MemoryError: - einfo = ExceptionInfo(internal=True) - self.assertIsNotNone(einfo) - req = self.get_request(self.add.s(2, 2)) - with self.assertRaises(MemoryError): - req._log_error(einfo) - - def test_log_error_when_Ignore(self): - einfo = None - try: - raise Ignore() - except Ignore: - einfo = ExceptionInfo(internal=True) - self.assertIsNotNone(einfo) - req = self.get_request(self.add.s(2, 2)) - req._log_error(einfo) - req.on_ack.assert_called_with(req_logger, req.connection_errors) - - def test_tzlocal_is_cached(self): - req = self.get_request(self.add.s(2, 2)) - req._tzlocal = 'foo' - self.assertEqual(req.tzlocal, 'foo') - - def test_execute_magic_kwargs(self): - task = self.add.s(2, 2) - task.freeze() - req = self.get_request(task) - self.add.accept_magic_kwargs = True - pool = Mock() - req.execute_using_pool(pool) - self.assertTrue(pool.apply_async.called) - args = pool.apply_async.call_args[1]['args'] - self.assertEqual(args[0], task.task) - self.assertEqual(args[1], task.id) - self.assertEqual(args[2], task.args) - kwargs = args[3] - self.assertEqual(kwargs.get('task_name'), task.task) - - def xRequest(self, body=None, **kwargs): - body = dict({'task': self.mytask.name, - 'id': uuid(), - 'args': [1], - 'kwargs': {'f': 'x'}}, **body or {}) - return Request(body, app=self.app, **kwargs) - - def test_task_wrapper_repr(self): - self.assertTrue(repr(self.xRequest())) - - @patch('celery.worker.job.kwdict') - def test_kwdict(self, kwdict): - prev, module.NEEDS_KWDICT = module.NEEDS_KWDICT, True - try: - self.xRequest() - self.assertTrue(kwdict.called) - finally: - module.NEEDS_KWDICT = prev - - def test_sets_store_errors(self): - self.mytask.ignore_result = True - job = self.xRequest() - self.assertFalse(job.store_errors) - - self.mytask.store_errors_even_if_ignored = True - job = self.xRequest() - self.assertTrue(job.store_errors) - - def test_send_event(self): - job = self.xRequest() - job.eventer = MockEventDispatcher() - job.send_event('task-frobulated') - self.assertIn('task-frobulated', job.eventer.sent) - - def test_on_retry(self): - job = Request({ - 'task': self.mytask.name, - 'id': uuid(), - 'args': [1], - 'kwargs': {'f': 'x'}, - }, app=self.app) - job.eventer = MockEventDispatcher() - try: - raise Retry('foo', KeyError('moofoobar')) - except: - einfo = ExceptionInfo() - job.on_failure(einfo) - self.assertIn('task-retried', job.eventer.sent) - prev, module._does_info = module._does_info, False - try: - job.on_failure(einfo) - finally: - module._does_info = prev - einfo.internal = True - job.on_failure(einfo) - - def test_compat_properties(self): - job = Request({ - 'task': self.mytask.name, - 'id': uuid(), - 'args': [1], - 'kwargs': {'f': 'x'}, - }, app=self.app) - self.assertEqual(job.task_id, job.id) - self.assertEqual(job.task_name, job.name) - job.task_id = 'ID' - self.assertEqual(job.id, 'ID') - job.task_name = 'NAME' - self.assertEqual(job.name, 'NAME') - - def test_terminate__task_started(self): - pool = Mock() - signum = signal.SIGTERM - job = Request({ - 'task': self.mytask.name, - 'id': uuid(), - 'args': [1], - 'kwrgs': {'f': 'x'}, - }, app=self.app) - with assert_signal_called( - task_revoked, sender=job.task, request=job, - terminated=True, expired=False, signum=signum): - job.time_start = monotonic() - job.worker_pid = 313 - job.terminate(pool, signal='TERM') - pool.terminate_job.assert_called_with(job.worker_pid, signum) - - def test_terminate__task_reserved(self): - pool = Mock() - job = Request({ - 'task': self.mytask.name, - 'id': uuid(), - 'args': [1], - 'kwargs': {'f': 'x'}, - }, app=self.app) - job.time_start = None - job.terminate(pool, signal='TERM') - self.assertFalse(pool.terminate_job.called) - self.assertTupleEqual(job._terminate_on_ack, (pool, 15)) - job.terminate(pool, signal='TERM') - - def test_revoked_expires_expired(self): - job = Request({ - 'task': self.mytask.name, - 'id': uuid(), - 'args': [1], - 'kwargs': {'f': 'x'}, - 'expires': datetime.utcnow() - timedelta(days=1), - }, app=self.app) - with assert_signal_called( - task_revoked, sender=job.task, request=job, - terminated=False, expired=True, signum=None): - job.revoked() - self.assertIn(job.id, revoked) - self.assertEqual( - self.mytask.backend.get_status(job.id), - states.REVOKED, - ) - - def test_revoked_expires_not_expired(self): - job = self.xRequest({ - 'expires': datetime.utcnow() + timedelta(days=1), - }) - job.revoked() - self.assertNotIn(job.id, revoked) - self.assertNotEqual( - self.mytask.backend.get_status(job.id), - states.REVOKED, - ) - - def test_revoked_expires_ignore_result(self): - self.mytask.ignore_result = True - job = self.xRequest({ - 'expires': datetime.utcnow() - timedelta(days=1), - }) - job.revoked() - self.assertIn(job.id, revoked) - self.assertNotEqual( - self.mytask.backend.get_status(job.id), states.REVOKED, - ) - - def test_send_email(self): - app = self.app - mail_sent = [False] - - def mock_mail_admins(*args, **kwargs): - mail_sent[0] = True - - def get_ei(): - try: - raise KeyError('moofoobar') - except: - return ExceptionInfo() - - app.mail_admins = mock_mail_admins - self.mytask.send_error_emails = True - job = self.xRequest() - einfo = get_ei() - job.on_failure(einfo) - self.assertTrue(mail_sent[0]) - - einfo = get_ei() - mail_sent[0] = False - self.mytask.send_error_emails = False - job.on_failure(einfo) - self.assertFalse(mail_sent[0]) - - einfo = get_ei() - mail_sent[0] = False - self.mytask.send_error_emails = True - job.on_failure(einfo) - self.assertTrue(mail_sent[0]) - - def test_already_revoked(self): - job = self.xRequest() - job._already_revoked = True - self.assertTrue(job.revoked()) - - def test_revoked(self): - job = self.xRequest() - with assert_signal_called( - task_revoked, sender=job.task, request=job, - terminated=False, expired=False, signum=None): - revoked.add(job.id) - self.assertTrue(job.revoked()) - self.assertTrue(job._already_revoked) - self.assertTrue(job.acknowledged) - - def test_execute_does_not_execute_revoked(self): - job = self.xRequest() - revoked.add(job.id) - job.execute() - - def test_execute_acks_late(self): - self.mytask_raising.acks_late = True - job = self.xRequest({ - 'task': self.mytask_raising.name, - 'kwargs': {}, - }) - job.execute() - self.assertTrue(job.acknowledged) - job.execute() - - def test_execute_using_pool_does_not_execute_revoked(self): - job = self.xRequest() - revoked.add(job.id) - with self.assertRaises(TaskRevokedError): - job.execute_using_pool(None) - - def test_on_accepted_acks_early(self): - job = self.xRequest() - job.on_accepted(pid=os.getpid(), time_accepted=monotonic()) - self.assertTrue(job.acknowledged) - prev, module._does_debug = module._does_debug, False - try: - job.on_accepted(pid=os.getpid(), time_accepted=monotonic()) - finally: - module._does_debug = prev - - def test_on_accepted_acks_late(self): - job = self.xRequest() - self.mytask.acks_late = True - job.on_accepted(pid=os.getpid(), time_accepted=monotonic()) - self.assertFalse(job.acknowledged) - - def test_on_accepted_terminates(self): - signum = signal.SIGTERM - pool = Mock() - job = self.xRequest() - with assert_signal_called( - task_revoked, sender=job.task, request=job, - terminated=True, expired=False, signum=signum): - job.terminate(pool, signal='TERM') - self.assertFalse(pool.terminate_job.call_count) - job.on_accepted(pid=314, time_accepted=monotonic()) - pool.terminate_job.assert_called_with(314, signum) - - def test_on_success_acks_early(self): - job = self.xRequest() - job.time_start = 1 - job.on_success(42) - prev, module._does_info = module._does_info, False - try: - job.on_success(42) - self.assertFalse(job.acknowledged) - finally: - module._does_info = prev - - def test_on_success_BaseException(self): - job = self.xRequest() - job.time_start = 1 - with self.assertRaises(SystemExit): - try: - raise SystemExit() - except SystemExit: - job.on_success(ExceptionInfo()) - else: - assert False - - def test_on_success_eventer(self): - job = self.xRequest() - job.time_start = 1 - job.eventer = Mock() - job.eventer.send = Mock() - job.on_success(42) - self.assertTrue(job.eventer.send.called) - - def test_on_success_when_failure(self): - job = self.xRequest() - job.time_start = 1 - job.on_failure = Mock() - try: - raise KeyError('foo') - except Exception: - job.on_success(ExceptionInfo()) - self.assertTrue(job.on_failure.called) - - def test_on_success_acks_late(self): - job = self.xRequest() - job.time_start = 1 - self.mytask.acks_late = True - job.on_success(42) - self.assertTrue(job.acknowledged) - - def test_on_failure_WorkerLostError(self): - - def get_ei(): - try: - raise WorkerLostError('do re mi') - except WorkerLostError: - return ExceptionInfo() - - job = self.xRequest() - exc_info = get_ei() - job.on_failure(exc_info) - self.assertEqual( - self.mytask.backend.get_status(job.id), states.FAILURE, - ) - - self.mytask.ignore_result = True - exc_info = get_ei() - job = self.xRequest() - job.on_failure(exc_info) - self.assertEqual( - self.mytask.backend.get_status(job.id), states.PENDING, - ) - - def test_on_failure_acks_late(self): - job = self.xRequest() - job.time_start = 1 - self.mytask.acks_late = True - try: - raise KeyError('foo') - except KeyError: - exc_info = ExceptionInfo() - job.on_failure(exc_info) - self.assertTrue(job.acknowledged) - - def test_from_message_invalid_kwargs(self): - body = dict(task=self.mytask.name, id=1, args=(), kwargs='foo') - with self.assertRaises(InvalidTaskError): - Request(body, message=None, app=self.app) - - @patch('celery.worker.job.error') - @patch('celery.worker.job.warn') - def test_on_timeout(self, warn, error): - - job = self.xRequest() - job.on_timeout(soft=True, timeout=1337) - self.assertIn('Soft time limit', warn.call_args[0][0]) - job.on_timeout(soft=False, timeout=1337) - self.assertIn('Hard time limit', error.call_args[0][0]) - self.assertEqual( - self.mytask.backend.get_status(job.id), states.FAILURE, - ) - - self.mytask.ignore_result = True - job = self.xRequest() - job.on_timeout(soft=True, timeout=1336) - self.assertEqual( - self.mytask.backend.get_status(job.id), states.PENDING, - ) - - def test_fast_trace_task(self): - from celery.app import trace - setup_worker_optimizations(self.app) - self.assertIs(trace.trace_task_ret, trace._fast_trace_task) - try: - self.mytask.__trace__ = build_tracer( - self.mytask.name, self.mytask, self.app.loader, 'test', - app=self.app, - ) - res = trace.trace_task_ret(self.mytask.name, uuid(), [4], {}) - self.assertEqual(res, 4 ** 4) - finally: - reset_worker_optimizations() - self.assertIs(trace.trace_task_ret, trace._trace_task_ret) - delattr(self.mytask, '__trace__') - res = trace.trace_task_ret( - self.mytask.name, uuid(), [4], {}, app=self.app, - ) - self.assertEqual(res, 4 ** 4) - - def test_trace_task_ret(self): - self.mytask.__trace__ = build_tracer( - self.mytask.name, self.mytask, self.app.loader, 'test', - app=self.app, - ) - res = _trace_task_ret(self.mytask.name, uuid(), [4], {}, app=self.app) - self.assertEqual(res, 4 ** 4) - - def test_trace_task_ret__no_trace(self): - try: - delattr(self.mytask, '__trace__') - except AttributeError: - pass - res = _trace_task_ret(self.mytask.name, uuid(), [4], {}, app=self.app) - self.assertEqual(res, 4 ** 4) - - def test_trace_catches_exception(self): - - def _error_exec(self, *args, **kwargs): - raise KeyError('baz') - - @self.app.task(request=None, shared=False) - def raising(): - raise KeyError('baz') - - with self.assertWarnsRegex(RuntimeWarning, - r'Exception raised outside'): - res = trace_task(raising, uuid(), [], {}, app=self.app) - self.assertIsInstance(res, ExceptionInfo) - - def test_worker_task_trace_handle_retry(self): - tid = uuid() - self.mytask.push_request(id=tid) - try: - raise ValueError('foo') - except Exception as exc: - try: - raise Retry(str(exc), exc=exc) - except Retry as exc: - w = TraceInfo(states.RETRY, exc) - w.handle_retry(self.mytask, store_errors=False) - self.assertEqual( - self.mytask.backend.get_status(tid), states.PENDING, - ) - w.handle_retry(self.mytask, store_errors=True) - self.assertEqual( - self.mytask.backend.get_status(tid), states.RETRY, - ) - finally: - self.mytask.pop_request() - - def test_worker_task_trace_handle_failure(self): - tid = uuid() - self.mytask.push_request() - try: - self.mytask.request.id = tid - try: - raise ValueError('foo') - except Exception as exc: - w = TraceInfo(states.FAILURE, exc) - w.handle_failure(self.mytask, store_errors=False) - self.assertEqual( - self.mytask.backend.get_status(tid), states.PENDING, - ) - w.handle_failure(self.mytask, store_errors=True) - self.assertEqual( - self.mytask.backend.get_status(tid), states.FAILURE, - ) - finally: - self.mytask.pop_request() - - def test_task_wrapper_mail_attrs(self): - job = self.xRequest({'args': [], 'kwargs': {}}) - x = job.success_msg % { - 'name': job.name, - 'id': job.id, - 'return_value': 10, - 'runtime': 0.3641, - } - self.assertTrue(x) - x = job.error_msg % { - 'name': job.name, - 'id': job.id, - 'exc': 'FOOBARBAZ', - 'description': 'raised unexpected', - 'traceback': 'foobarbaz', - } - self.assertTrue(x) - - def test_from_message(self): - us = 'æØåveéðƒeæ' - body = {'task': self.mytask.name, 'id': uuid(), - 'args': [2], 'kwargs': {us: 'bar'}} - m = Message(None, body=anyjson.dumps(body), backend='foo', - content_type='application/json', - content_encoding='utf-8') - job = Request(m.decode(), message=m, app=self.app) - self.assertIsInstance(job, Request) - self.assertEqual(job.name, body['task']) - self.assertEqual(job.id, body['id']) - self.assertEqual(job.args, body['args']) - us = from_utf8(us) - if sys.version_info < (2, 6): - self.assertEqual(next(keys(job.kwargs)), us) - self.assertIsInstance(next(keys(job.kwargs)), str) - - def test_from_message_empty_args(self): - body = {'task': self.mytask.name, 'id': uuid()} - m = Message(None, body=anyjson.dumps(body), backend='foo', - content_type='application/json', - content_encoding='utf-8') - job = Request(m.decode(), message=m, app=self.app) - self.assertIsInstance(job, Request) - self.assertEqual(job.args, []) - self.assertEqual(job.kwargs, {}) - - def test_from_message_missing_required_fields(self): - body = {} - m = Message(None, body=anyjson.dumps(body), backend='foo', - content_type='application/json', - content_encoding='utf-8') - with self.assertRaises(KeyError): - Request(m.decode(), message=m, app=self.app) - - def test_from_message_nonexistant_task(self): - body = {'task': 'cu.mytask.doesnotexist', 'id': uuid(), - 'args': [2], 'kwargs': {'æØåveéðƒeæ': 'bar'}} - m = Message(None, body=anyjson.dumps(body), backend='foo', - content_type='application/json', - content_encoding='utf-8') - with self.assertRaises(KeyError): - Request(m.decode(), message=m, app=self.app) - - def test_execute(self): - tid = uuid() - job = self.xRequest({'id': tid, 'args': [4], 'kwargs': {}}) - self.assertEqual(job.execute(), 256) - meta = self.mytask.backend.get_task_meta(tid) - self.assertEqual(meta['status'], states.SUCCESS) - self.assertEqual(meta['result'], 256) - - def test_execute_success_no_kwargs(self): - - @self.app.task # traverses coverage for decorator without parens - def mytask_no_kwargs(i): - return i ** i - - tid = uuid() - job = self.xRequest({ - 'task': mytask_no_kwargs.name, - 'id': tid, - 'args': [4], - 'kwargs': {}, - }) - self.assertEqual(job.execute(), 256) - meta = mytask_no_kwargs.backend.get_task_meta(tid) - self.assertEqual(meta['result'], 256) - self.assertEqual(meta['status'], states.SUCCESS) - - def test_execute_success_some_kwargs(self): - scratch = {'task_id': None} - - @self.app.task(shared=False, accept_magic_kwargs=True) - def mytask_some_kwargs(i, task_id): - scratch['task_id'] = task_id - return i ** i - - tid = uuid() - job = self.xRequest({ - 'task': mytask_some_kwargs.name, - 'id': tid, - 'args': [4], - 'kwargs': {}, - }) - self.assertEqual(job.execute(), 256) - meta = mytask_some_kwargs.backend.get_task_meta(tid) - self.assertEqual(scratch.get('task_id'), tid) - self.assertEqual(meta['result'], 256) - self.assertEqual(meta['status'], states.SUCCESS) - - def test_execute_ack(self): - scratch = {'ACK': False} - - def on_ack(*args, **kwargs): - scratch['ACK'] = True - - tid = uuid() - job = self.xRequest({'id': tid, 'args': [4]}, on_ack=on_ack) - self.assertEqual(job.execute(), 256) - meta = self.mytask.backend.get_task_meta(tid) - self.assertTrue(scratch['ACK']) - self.assertEqual(meta['result'], 256) - self.assertEqual(meta['status'], states.SUCCESS) - - def test_execute_fail(self): - tid = uuid() - job = self.xRequest({ - 'task': self.mytask_raising.name, - 'id': tid, - 'args': [4], - 'kwargs': {}, - }) - self.assertIsInstance(job.execute(), ExceptionInfo) - meta = self.mytask_raising.backend.get_task_meta(tid) - self.assertEqual(meta['status'], states.FAILURE) - self.assertIsInstance(meta['result'], KeyError) - - def test_execute_using_pool(self): - tid = uuid() - job = self.xRequest({'id': tid, 'args': [4]}) - - class MockPool(BasePool): - target = None - args = None - kwargs = None - - def __init__(self, *args, **kwargs): - pass - - def apply_async(self, target, args=None, kwargs=None, - *margs, **mkwargs): - self.target = target - self.args = args - self.kwargs = kwargs - - p = MockPool() - job.execute_using_pool(p) - self.assertTrue(p.target) - self.assertEqual(p.args[0], self.mytask.name) - self.assertEqual(p.args[1], tid) - self.assertEqual(p.args[2], [4]) - self.assertIn('f', p.args[3]) - self.assertIn([4], p.args) - - job.task.accept_magic_kwargs = False - job.execute_using_pool(p) - - def test_default_kwargs(self): - self.maxDiff = 3000 - tid = uuid() - job = self.xRequest({'id': tid, 'args': [4]}) - self.assertDictEqual( - job.extend_with_default_kwargs(), { - 'f': 'x', - 'logfile': None, - 'loglevel': None, - 'task_id': job.id, - 'task_retries': 0, - 'task_is_eager': False, - 'delivery_info': { - 'exchange': None, - 'routing_key': None, - 'priority': 0, - 'redelivered': False, - }, - 'task_name': job.name}) - - @patch('celery.worker.job.logger') - def _test_on_failure(self, exception, logger): - app = self.app - tid = uuid() - job = self.xRequest({'id': tid, 'args': [4]}) - try: - raise exception - except Exception: - exc_info = ExceptionInfo() - app.conf.CELERY_SEND_TASK_ERROR_EMAILS = True - job.on_failure(exc_info) - self.assertTrue(logger.log.called) - context = logger.log.call_args[0][2] - self.assertEqual(self.mytask.name, context['name']) - self.assertIn(tid, context['id']) - - def test_on_failure(self): - self._test_on_failure(Exception('Inside unit tests')) - - def test_on_failure_unicode_exception(self): - self._test_on_failure(Exception('Бобры атакуют')) - - def test_on_failure_utf8_exception(self): - self._test_on_failure(Exception( - from_utf8('Бобры атакуют'))) diff --git a/awx/lib/site-packages/celery/tests/worker/test_revoke.py b/awx/lib/site-packages/celery/tests/worker/test_revoke.py deleted file mode 100644 index 4d5ad02121..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_revoke.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import absolute_import - -from celery.worker import state -from celery.tests.case import AppCase - - -class test_revoked(AppCase): - - def test_is_working(self): - state.revoked.add('foo') - self.assertIn('foo', state.revoked) - state.revoked.pop_value('foo') - self.assertNotIn('foo', state.revoked) diff --git a/awx/lib/site-packages/celery/tests/worker/test_state.py b/awx/lib/site-packages/celery/tests/worker/test_state.py deleted file mode 100644 index ede9a00a13..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_state.py +++ /dev/null @@ -1,161 +0,0 @@ -from __future__ import absolute_import - -import pickle - -from time import time - -from celery.datastructures import LimitedSet -from celery.exceptions import WorkerShutdown, WorkerTerminate -from celery.worker import state - -from celery.tests.case import AppCase, Mock, patch - - -class StateResetCase(AppCase): - - def setup(self): - self.reset_state() - - def teardown(self): - self.reset_state() - - def reset_state(self): - state.active_requests.clear() - state.revoked.clear() - state.total_count.clear() - - -class MockShelve(dict): - filename = None - in_sync = False - closed = False - - def open(self, filename, **kwargs): - self.filename = filename - return self - - def sync(self): - self.in_sync = True - - def close(self): - self.closed = True - - -class MyPersistent(state.Persistent): - storage = MockShelve() - - -class test_maybe_shutdown(AppCase): - - def teardown(self): - state.should_stop = False - state.should_terminate = False - - def test_should_stop(self): - state.should_stop = True - with self.assertRaises(WorkerShutdown): - state.maybe_shutdown() - - def test_should_terminate(self): - state.should_terminate = True - with self.assertRaises(WorkerTerminate): - state.maybe_shutdown() - - -class test_Persistent(StateResetCase): - - def setup(self): - self.reset_state() - self.p = MyPersistent(state, filename='celery-state') - - def test_close_twice(self): - self.p._is_open = False - self.p.close() - - def test_constructor(self): - self.assertDictEqual(self.p.db, {}) - self.assertEqual(self.p.db.filename, self.p.filename) - - def test_save(self): - self.p.db['foo'] = 'bar' - self.p.save() - self.assertTrue(self.p.db.in_sync) - self.assertTrue(self.p.db.closed) - - def add_revoked(self, *ids): - for id in ids: - self.p.db.setdefault('revoked', LimitedSet()).add(id) - - def test_merge(self, data=['foo', 'bar', 'baz']): - self.add_revoked(*data) - self.p.merge() - for item in data: - self.assertIn(item, state.revoked) - - def test_merge_dict(self): - self.p.clock = Mock() - self.p.clock.adjust.return_value = 626 - d = {'revoked': {'abc': time()}, 'clock': 313} - self.p._merge_with(d) - self.p.clock.adjust.assert_called_with(313) - self.assertEqual(d['clock'], 626) - self.assertIn('abc', state.revoked) - - def test_sync_clock_and_purge(self): - passthrough = Mock() - passthrough.side_effect = lambda x: x - with patch('celery.worker.state.revoked') as revoked: - d = {'clock': 0} - self.p.clock = Mock() - self.p.clock.forward.return_value = 627 - self.p._dumps = passthrough - self.p.compress = passthrough - self.p._sync_with(d) - revoked.purge.assert_called_with() - self.assertEqual(d['clock'], 627) - self.assertNotIn('revoked', d) - self.assertIs(d['zrevoked'], revoked) - - def test_sync(self, data1=['foo', 'bar', 'baz'], - data2=['baz', 'ini', 'koz']): - self.add_revoked(*data1) - for item in data2: - state.revoked.add(item) - self.p.sync() - - self.assertTrue(self.p.db['zrevoked']) - pickled = self.p.decompress(self.p.db['zrevoked']) - self.assertTrue(pickled) - saved = pickle.loads(pickled) - for item in data2: - self.assertIn(item, saved) - - -class SimpleReq(object): - - def __init__(self, name): - self.name = name - - -class test_state(StateResetCase): - - def test_accepted(self, requests=[SimpleReq('foo'), - SimpleReq('bar'), - SimpleReq('baz'), - SimpleReq('baz')]): - for request in requests: - state.task_accepted(request) - for req in requests: - self.assertIn(req, state.active_requests) - self.assertEqual(state.total_count['foo'], 1) - self.assertEqual(state.total_count['bar'], 1) - self.assertEqual(state.total_count['baz'], 2) - - def test_ready(self, requests=[SimpleReq('foo'), - SimpleReq('bar')]): - for request in requests: - state.task_accepted(request) - self.assertEqual(len(state.active_requests), 2) - for request in requests: - state.task_ready(request) - self.assertEqual(len(state.active_requests), 0) diff --git a/awx/lib/site-packages/celery/tests/worker/test_strategy.py b/awx/lib/site-packages/celery/tests/worker/test_strategy.py deleted file mode 100644 index 7edf78bff2..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_strategy.py +++ /dev/null @@ -1,139 +0,0 @@ -from __future__ import absolute_import - -from collections import defaultdict -from contextlib import contextmanager - -from kombu.utils.limits import TokenBucket - -from celery.worker import state -from celery.utils.timeutils import rate - -from celery.tests.case import AppCase, Mock, patch, body_from_sig - - -class test_default_strategy(AppCase): - - def setup(self): - @self.app.task(shared=False) - def add(x, y): - return x + y - - self.add = add - - class Context(object): - - def __init__(self, sig, s, reserved, consumer, message, body): - self.sig = sig - self.s = s - self.reserved = reserved - self.consumer = consumer - self.message = message - self.body = body - - def __call__(self, **kwargs): - return self.s( - self.message, self.body, - self.message.ack, self.message.reject, [], **kwargs - ) - - def was_reserved(self): - return self.reserved.called - - def was_rate_limited(self): - assert not self.was_reserved() - return self.consumer._limit_task.called - - def was_scheduled(self): - assert not self.was_reserved() - assert not self.was_rate_limited() - return self.consumer.timer.call_at.called - - def event_sent(self): - return self.consumer.event_dispatcher.send.call_args - - def get_request(self): - if self.was_reserved(): - return self.reserved.call_args[0][0] - if self.was_rate_limited(): - return self.consumer._limit_task.call_args[0][0] - if self.was_scheduled(): - return self.consumer.timer.call_at.call_args[0][0] - raise ValueError('request not handled') - - @contextmanager - def _context(self, sig, - rate_limits=True, events=True, utc=True, limit=None): - self.assertTrue(sig.type.Strategy) - - reserved = Mock() - consumer = Mock() - consumer.task_buckets = defaultdict(lambda: None) - if limit: - bucket = TokenBucket(rate(limit), capacity=1) - consumer.task_buckets[sig.task] = bucket - consumer.disable_rate_limits = not rate_limits - consumer.event_dispatcher.enabled = events - s = sig.type.start_strategy(self.app, consumer, task_reserved=reserved) - self.assertTrue(s) - - message = Mock() - body = body_from_sig(self.app, sig, utc=utc) - - yield self.Context(sig, s, reserved, consumer, message, body) - - def test_when_logging_disabled(self): - with patch('celery.worker.strategy.logger') as logger: - logger.isEnabledFor.return_value = False - with self._context(self.add.s(2, 2)) as C: - C() - self.assertFalse(logger.info.called) - - def test_task_strategy(self): - with self._context(self.add.s(2, 2)) as C: - C() - self.assertTrue(C.was_reserved()) - req = C.get_request() - C.consumer.on_task_request.assert_called_with(req) - self.assertTrue(C.event_sent()) - - def test_when_events_disabled(self): - with self._context(self.add.s(2, 2), events=False) as C: - C() - self.assertTrue(C.was_reserved()) - self.assertFalse(C.event_sent()) - - def test_eta_task(self): - with self._context(self.add.s(2, 2).set(countdown=10)) as C: - C() - self.assertTrue(C.was_scheduled()) - C.consumer.qos.increment_eventually.assert_called_with() - - def test_eta_task_utc_disabled(self): - with self._context(self.add.s(2, 2).set(countdown=10), utc=False) as C: - C() - self.assertTrue(C.was_scheduled()) - C.consumer.qos.increment_eventually.assert_called_with() - - def test_when_rate_limited(self): - task = self.add.s(2, 2) - with self._context(task, rate_limits=True, limit='1/m') as C: - C() - self.assertTrue(C.was_rate_limited()) - - def test_when_rate_limited__limits_disabled(self): - task = self.add.s(2, 2) - with self._context(task, rate_limits=False, limit='1/m') as C: - C() - self.assertTrue(C.was_reserved()) - - def test_when_revoked(self): - task = self.add.s(2, 2) - task.freeze() - state.revoked.add(task.id) - try: - with self._context(task) as C: - C() - with self.assertRaises(ValueError): - C.get_request() - finally: - state.revoked.discard(task.id) diff --git a/awx/lib/site-packages/celery/tests/worker/test_worker.py b/awx/lib/site-packages/celery/tests/worker/test_worker.py deleted file mode 100644 index b700a6ca61..0000000000 --- a/awx/lib/site-packages/celery/tests/worker/test_worker.py +++ /dev/null @@ -1,1128 +0,0 @@ -from __future__ import absolute_import, print_function - -import os -import socket - -from collections import deque -from datetime import datetime, timedelta -from threading import Event - -from amqp import ChannelError -from kombu import Connection -from kombu.common import QoS, ignore_errors -from kombu.transport.base import Message - -from celery.app.defaults import DEFAULTS -from celery.bootsteps import RUN, CLOSE, StartStopStep -from celery.concurrency.base import BasePool -from celery.datastructures import AttributeDict -from celery.exceptions import ( - WorkerShutdown, WorkerTerminate, TaskRevokedError, -) -from celery.five import Empty, range, Queue as FastQueue -from celery.utils import uuid -from celery.worker import components -from celery.worker import consumer -from celery.worker.consumer import Consumer as __Consumer -from celery.worker.job import Request -from celery.utils import worker_direct -from celery.utils.serialization import pickle -from celery.utils.timer2 import Timer - -from celery.tests.case import AppCase, Mock, SkipTest, patch, restore_logging - - -def MockStep(step=None): - step = Mock() if step is None else step - step.blueprint = Mock() - step.blueprint.name = 'MockNS' - step.name = 'MockStep(%s)' % (id(step), ) - return step - - -def mock_event_dispatcher(): - evd = Mock(name='event_dispatcher') - evd.groups = ['worker'] - evd._outbound_buffer = deque() - return evd - - -class PlaceHolder(object): - pass - - -def find_step(obj, typ): - return obj.blueprint.steps[typ.name] - - -class Consumer(__Consumer): - - def __init__(self, *args, **kwargs): - kwargs.setdefault('without_mingle', True) # disable Mingle step - kwargs.setdefault('without_gossip', True) # disable Gossip step - kwargs.setdefault('without_heartbeat', True) # disable Heart step - super(Consumer, self).__init__(*args, **kwargs) - - -class _MyKombuConsumer(Consumer): - broadcast_consumer = Mock() - task_consumer = Mock() - - def __init__(self, *args, **kwargs): - kwargs.setdefault('pool', BasePool(2)) - super(_MyKombuConsumer, self).__init__(*args, **kwargs) - - def restart_heartbeat(self): - self.heart = None - - -class MyKombuConsumer(Consumer): - - def loop(self, *args, **kwargs): - pass - - -class MockNode(object): - commands = [] - - def handle_message(self, body, message): - self.commands.append(body.pop('command', None)) - - -class MockEventDispatcher(object): - sent = [] - closed = False - flushed = False - _outbound_buffer = [] - - def send(self, event, *args, **kwargs): - self.sent.append(event) - - def close(self): - self.closed = True - - def flush(self): - self.flushed = True - - -class MockHeart(object): - closed = False - - def stop(self): - self.closed = True - - -def create_message(channel, **data): - data.setdefault('id', uuid()) - channel.no_ack_consumers = set() - m = Message(channel, body=pickle.dumps(dict(**data)), - content_type='application/x-python-serialize', - content_encoding='binary', - delivery_info={'consumer_tag': 'mock'}) - m.accept = ['application/x-python-serialize'] - return m - - -class test_Consumer(AppCase): - - def setup(self): - self.buffer = FastQueue() - self.timer = Timer() - - @self.app.task(shared=False) - def foo_task(x, y, z): - return x * y * z - self.foo_task = foo_task - - def teardown(self): - self.timer.stop() - - def test_info(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.task_consumer = Mock() - l.qos = QoS(l.task_consumer.qos, 10) - l.connection = Mock() - l.connection.info.return_value = {'foo': 'bar'} - l.controller = l.app.WorkController() - l.controller.pool = Mock() - l.controller.pool.info.return_value = [Mock(), Mock()] - l.controller.consumer = l - info = l.controller.stats() - self.assertEqual(info['prefetch_count'], 10) - self.assertTrue(info['broker']) - - def test_start_when_closed(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = CLOSE - l.start() - - def test_connection(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - - l.blueprint.start(l) - self.assertIsInstance(l.connection, Connection) - - l.blueprint.state = RUN - l.event_dispatcher = None - l.blueprint.restart(l) - self.assertTrue(l.connection) - - l.blueprint.state = RUN - l.shutdown() - self.assertIsNone(l.connection) - self.assertIsNone(l.task_consumer) - - l.blueprint.start(l) - self.assertIsInstance(l.connection, Connection) - l.blueprint.restart(l) - - l.stop() - l.shutdown() - self.assertIsNone(l.connection) - self.assertIsNone(l.task_consumer) - - def test_close_connection(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - step = find_step(l, consumer.Connection) - conn = l.connection = Mock() - step.shutdown(l) - self.assertTrue(conn.close.called) - self.assertIsNone(l.connection) - - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - eventer = l.event_dispatcher = mock_event_dispatcher() - eventer.enabled = True - heart = l.heart = MockHeart() - l.blueprint.state = RUN - Events = find_step(l, consumer.Events) - Events.shutdown(l) - Heart = find_step(l, consumer.Heart) - Heart.shutdown(l) - self.assertTrue(eventer.close.call_count) - self.assertTrue(heart.closed) - - @patch('celery.worker.consumer.warn') - def test_receive_message_unknown(self, warn): - l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.steps.pop() - backend = Mock() - m = create_message(backend, unknown={'baz': '!!!'}) - l.event_dispatcher = mock_event_dispatcher() - l.node = MockNode() - - callback = self._get_on_message(l) - callback(m.decode(), m) - self.assertTrue(warn.call_count) - - @patch('celery.worker.strategy.to_timestamp') - def test_receive_message_eta_OverflowError(self, to_timestamp): - to_timestamp.side_effect = OverflowError() - l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.steps.pop() - m = create_message(Mock(), task=self.foo_task.name, - args=('2, 2'), - kwargs={}, - eta=datetime.now().isoformat()) - l.event_dispatcher = mock_event_dispatcher() - l.node = MockNode() - l.update_strategies() - l.qos = Mock() - - callback = self._get_on_message(l) - callback(m.decode(), m) - self.assertTrue(m.acknowledged) - - @patch('celery.worker.consumer.error') - def test_receive_message_InvalidTaskError(self, error): - l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.event_dispatcher = mock_event_dispatcher() - l.steps.pop() - m = create_message(Mock(), task=self.foo_task.name, - args=(1, 2), kwargs='foobarbaz', id=1) - l.update_strategies() - l.event_dispatcher = mock_event_dispatcher() - - callback = self._get_on_message(l) - callback(m.decode(), m) - self.assertIn('Received invalid task message', error.call_args[0][0]) - - @patch('celery.worker.consumer.crit') - def test_on_decode_error(self, crit): - l = Consumer(self.buffer.put, timer=self.timer, app=self.app) - - class MockMessage(Mock): - content_type = 'application/x-msgpack' - content_encoding = 'binary' - body = 'foobarbaz' - - message = MockMessage() - l.on_decode_error(message, KeyError('foo')) - self.assertTrue(message.ack.call_count) - self.assertIn("Can't decode message body", crit.call_args[0][0]) - - def _get_on_message(self, l): - if l.qos is None: - l.qos = Mock() - l.event_dispatcher = mock_event_dispatcher() - l.task_consumer = Mock() - l.connection = Mock() - l.connection.drain_events.side_effect = WorkerShutdown() - - with self.assertRaises(WorkerShutdown): - l.loop(*l.loop_args()) - self.assertTrue(l.task_consumer.register_callback.called) - return l.task_consumer.register_callback.call_args[0][0] - - def test_receieve_message(self): - l = Consumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.event_dispatcher = mock_event_dispatcher() - m = create_message(Mock(), task=self.foo_task.name, - args=[2, 4, 8], kwargs={}) - l.update_strategies() - callback = self._get_on_message(l) - callback(m.decode(), m) - - in_bucket = self.buffer.get_nowait() - self.assertIsInstance(in_bucket, Request) - self.assertEqual(in_bucket.name, self.foo_task.name) - self.assertEqual(in_bucket.execute(), 2 * 4 * 8) - self.assertTrue(self.timer.empty()) - - def test_start_channel_error(self): - - class MockConsumer(Consumer): - iterations = 0 - - def loop(self, *args, **kwargs): - if not self.iterations: - self.iterations = 1 - raise KeyError('foo') - raise SyntaxError('bar') - - l = MockConsumer(self.buffer.put, timer=self.timer, - send_events=False, pool=BasePool(), app=self.app) - l.channel_errors = (KeyError, ) - with self.assertRaises(KeyError): - l.start() - l.timer.stop() - - def test_start_connection_error(self): - - class MockConsumer(Consumer): - iterations = 0 - - def loop(self, *args, **kwargs): - if not self.iterations: - self.iterations = 1 - raise KeyError('foo') - raise SyntaxError('bar') - - l = MockConsumer(self.buffer.put, timer=self.timer, - send_events=False, pool=BasePool(), app=self.app) - - l.connection_errors = (KeyError, ) - self.assertRaises(SyntaxError, l.start) - l.timer.stop() - - def test_loop_ignores_socket_timeout(self): - - class Connection(self.app.connection().__class__): - obj = None - - def drain_events(self, **kwargs): - self.obj.connection = None - raise socket.timeout(10) - - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.connection = Connection() - l.task_consumer = Mock() - l.connection.obj = l - l.qos = QoS(l.task_consumer.qos, 10) - l.loop(*l.loop_args()) - - def test_loop_when_socket_error(self): - - class Connection(self.app.connection().__class__): - obj = None - - def drain_events(self, **kwargs): - self.obj.connection = None - raise socket.error('foo') - - l = Consumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - c = l.connection = Connection() - l.connection.obj = l - l.task_consumer = Mock() - l.qos = QoS(l.task_consumer.qos, 10) - with self.assertRaises(socket.error): - l.loop(*l.loop_args()) - - l.blueprint.state = CLOSE - l.connection = c - l.loop(*l.loop_args()) - - def test_loop(self): - - class Connection(self.app.connection().__class__): - obj = None - - def drain_events(self, **kwargs): - self.obj.connection = None - - l = Consumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.connection = Connection() - l.connection.obj = l - l.task_consumer = Mock() - l.qos = QoS(l.task_consumer.qos, 10) - - l.loop(*l.loop_args()) - l.loop(*l.loop_args()) - self.assertTrue(l.task_consumer.consume.call_count) - l.task_consumer.qos.assert_called_with(prefetch_count=10) - self.assertEqual(l.qos.value, 10) - l.qos.decrement_eventually() - self.assertEqual(l.qos.value, 9) - l.qos.update() - self.assertEqual(l.qos.value, 9) - l.task_consumer.qos.assert_called_with(prefetch_count=9) - - def test_ignore_errors(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.connection_errors = (AttributeError, KeyError, ) - l.channel_errors = (SyntaxError, ) - ignore_errors(l, Mock(side_effect=AttributeError('foo'))) - ignore_errors(l, Mock(side_effect=KeyError('foo'))) - ignore_errors(l, Mock(side_effect=SyntaxError('foo'))) - with self.assertRaises(IndexError): - ignore_errors(l, Mock(side_effect=IndexError('foo'))) - - def test_apply_eta_task(self): - from celery.worker import state - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.qos = QoS(None, 10) - - task = object() - qos = l.qos.value - l.apply_eta_task(task) - self.assertIn(task, state.reserved_requests) - self.assertEqual(l.qos.value, qos - 1) - self.assertIs(self.buffer.get_nowait(), task) - - def test_receieve_message_eta_isoformat(self): - l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.steps.pop() - m = create_message( - Mock(), task=self.foo_task.name, - eta=(datetime.now() + timedelta(days=1)).isoformat(), - args=[2, 4, 8], kwargs={}, - ) - - l.task_consumer = Mock() - l.qos = QoS(l.task_consumer.qos, 1) - current_pcount = l.qos.value - l.event_dispatcher = mock_event_dispatcher() - l.enabled = False - l.update_strategies() - callback = self._get_on_message(l) - callback(m.decode(), m) - l.timer.stop() - l.timer.join(1) - - items = [entry[2] for entry in self.timer.queue] - found = 0 - for item in items: - if item.args[0].name == self.foo_task.name: - found = True - self.assertTrue(found) - self.assertGreater(l.qos.value, current_pcount) - l.timer.stop() - - def test_pidbox_callback(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - con = find_step(l, consumer.Control).box - con.node = Mock() - con.reset = Mock() - - con.on_message('foo', 'bar') - con.node.handle_message.assert_called_with('foo', 'bar') - - con.node = Mock() - con.node.handle_message.side_effect = KeyError('foo') - con.on_message('foo', 'bar') - con.node.handle_message.assert_called_with('foo', 'bar') - - con.node = Mock() - con.node.handle_message.side_effect = ValueError('foo') - con.on_message('foo', 'bar') - con.node.handle_message.assert_called_with('foo', 'bar') - self.assertTrue(con.reset.called) - - def test_revoke(self): - l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.steps.pop() - backend = Mock() - id = uuid() - t = create_message(backend, task=self.foo_task.name, args=[2, 4, 8], - kwargs={}, id=id) - from celery.worker.state import revoked - revoked.add(id) - - callback = self._get_on_message(l) - callback(t.decode(), t) - self.assertTrue(self.buffer.empty()) - - def test_receieve_message_not_registered(self): - l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - l.steps.pop() - backend = Mock() - m = create_message(backend, task='x.X.31x', args=[2, 4, 8], kwargs={}) - - l.event_dispatcher = mock_event_dispatcher() - callback = self._get_on_message(l) - self.assertFalse(callback(m.decode(), m)) - with self.assertRaises(Empty): - self.buffer.get_nowait() - self.assertTrue(self.timer.empty()) - - @patch('celery.worker.consumer.warn') - @patch('celery.worker.consumer.logger') - def test_receieve_message_ack_raises(self, logger, warn): - l = Consumer(self.buffer.put, timer=self.timer, app=self.app) - l.blueprint.state = RUN - backend = Mock() - m = create_message(backend, args=[2, 4, 8], kwargs={}) - - l.event_dispatcher = mock_event_dispatcher() - l.connection_errors = (socket.error, ) - m.reject = Mock() - m.reject.side_effect = socket.error('foo') - callback = self._get_on_message(l) - self.assertFalse(callback(m.decode(), m)) - self.assertTrue(warn.call_count) - with self.assertRaises(Empty): - self.buffer.get_nowait() - self.assertTrue(self.timer.empty()) - m.reject.assert_called_with(requeue=False) - self.assertTrue(logger.critical.call_count) - - def test_receive_message_eta(self): - import sys - from functools import partial - if os.environ.get('C_DEBUG_TEST'): - pp = partial(print, file=sys.__stderr__) - else: - def pp(*args, **kwargs): - pass - pp('TEST RECEIVE MESSAGE ETA') - pp('+CREATE MYKOMBUCONSUMER') - l = _MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - pp('-CREATE MYKOMBUCONSUMER') - l.steps.pop() - l.event_dispatcher = mock_event_dispatcher() - backend = Mock() - pp('+ CREATE MESSAGE') - m = create_message( - backend, task=self.foo_task.name, - args=[2, 4, 8], kwargs={}, - eta=(datetime.now() + timedelta(days=1)).isoformat(), - ) - pp('- CREATE MESSAGE') - - try: - pp('+ BLUEPRINT START 1') - l.blueprint.start(l) - pp('- BLUEPRINT START 1') - p = l.app.conf.BROKER_CONNECTION_RETRY - l.app.conf.BROKER_CONNECTION_RETRY = False - pp('+ BLUEPRINT START 2') - l.blueprint.start(l) - pp('- BLUEPRINT START 2') - l.app.conf.BROKER_CONNECTION_RETRY = p - pp('+ BLUEPRINT RESTART') - l.blueprint.restart(l) - pp('- BLUEPRINT RESTART') - l.event_dispatcher = mock_event_dispatcher() - pp('+ GET ON MESSAGE') - callback = self._get_on_message(l) - pp('- GET ON MESSAGE') - pp('+ CALLBACK') - callback(m.decode(), m) - pp('- CALLBACK') - finally: - pp('+ STOP TIMER') - l.timer.stop() - pp('- STOP TIMER') - try: - pp('+ JOIN TIMER') - l.timer.join() - pp('- JOIN TIMER') - except RuntimeError: - pass - - in_hold = l.timer.queue[0] - self.assertEqual(len(in_hold), 3) - eta, priority, entry = in_hold - task = entry.args[0] - self.assertIsInstance(task, Request) - self.assertEqual(task.name, self.foo_task.name) - self.assertEqual(task.execute(), 2 * 4 * 8) - with self.assertRaises(Empty): - self.buffer.get_nowait() - - def test_reset_pidbox_node(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - con = find_step(l, consumer.Control).box - con.node = Mock() - chan = con.node.channel = Mock() - l.connection = Mock() - chan.close.side_effect = socket.error('foo') - l.connection_errors = (socket.error, ) - con.reset() - chan.close.assert_called_with() - - def test_reset_pidbox_node_green(self): - from celery.worker.pidbox import gPidbox - pool = Mock() - pool.is_green = True - l = MyKombuConsumer(self.buffer.put, timer=self.timer, pool=pool, - app=self.app) - con = find_step(l, consumer.Control) - self.assertIsInstance(con.box, gPidbox) - con.start(l) - l.pool.spawn_n.assert_called_with( - con.box.loop, l, - ) - - def test__green_pidbox_node(self): - pool = Mock() - pool.is_green = True - l = MyKombuConsumer(self.buffer.put, timer=self.timer, pool=pool, - app=self.app) - l.node = Mock() - controller = find_step(l, consumer.Control) - - class BConsumer(Mock): - - def __enter__(self): - self.consume() - return self - - def __exit__(self, *exc_info): - self.cancel() - - controller.box.node.listen = BConsumer() - connections = [] - - class Connection(object): - calls = 0 - - def __init__(self, obj): - connections.append(self) - self.obj = obj - self.default_channel = self.channel() - self.closed = False - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - def channel(self): - return Mock() - - def as_uri(self): - return 'dummy://' - - def drain_events(self, **kwargs): - if not self.calls: - self.calls += 1 - raise socket.timeout() - self.obj.connection = None - controller.box._node_shutdown.set() - - def close(self): - self.closed = True - - l.connection = Mock() - l.connect = lambda: Connection(obj=l) - controller = find_step(l, consumer.Control) - controller.box.loop(l) - - self.assertTrue(controller.box.node.listen.called) - self.assertTrue(controller.box.consumer) - controller.box.consumer.consume.assert_called_with() - - self.assertIsNone(l.connection) - self.assertTrue(connections[0].closed) - - @patch('kombu.connection.Connection._establish_connection') - @patch('kombu.utils.sleep') - def test_connect_errback(self, sleep, connect): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - from kombu.transport.memory import Transport - Transport.connection_errors = (ChannelError, ) - - def effect(): - if connect.call_count > 1: - return - raise ChannelError('error') - connect.side_effect = effect - l.connect() - connect.assert_called_with() - - def test_stop_pidbox_node(self): - l = MyKombuConsumer(self.buffer.put, timer=self.timer, app=self.app) - cont = find_step(l, consumer.Control) - cont._node_stopped = Event() - cont._node_shutdown = Event() - cont._node_stopped.set() - cont.stop(l) - - def test_start__loop(self): - - class _QoS(object): - prev = 3 - value = 4 - - def update(self): - self.prev = self.value - - class _Consumer(MyKombuConsumer): - iterations = 0 - - def reset_connection(self): - if self.iterations >= 1: - raise KeyError('foo') - - init_callback = Mock() - l = _Consumer(self.buffer.put, timer=self.timer, - init_callback=init_callback, app=self.app) - l.task_consumer = Mock() - l.broadcast_consumer = Mock() - l.qos = _QoS() - l.connection = Connection() - l.iterations = 0 - - def raises_KeyError(*args, **kwargs): - l.iterations += 1 - if l.qos.prev != l.qos.value: - l.qos.update() - if l.iterations >= 2: - raise KeyError('foo') - - l.loop = raises_KeyError - with self.assertRaises(KeyError): - l.start() - self.assertEqual(l.iterations, 2) - self.assertEqual(l.qos.prev, l.qos.value) - - init_callback.reset_mock() - l = _Consumer(self.buffer.put, timer=self.timer, app=self.app, - send_events=False, init_callback=init_callback) - l.qos = _QoS() - l.task_consumer = Mock() - l.broadcast_consumer = Mock() - l.connection = Connection() - l.loop = Mock(side_effect=socket.error('foo')) - with self.assertRaises(socket.error): - l.start() - self.assertTrue(l.loop.call_count) - - def test_reset_connection_with_no_node(self): - l = Consumer(self.buffer.put, timer=self.timer, app=self.app) - l.steps.pop() - self.assertEqual(None, l.pool) - l.blueprint.start(l) - - -class test_WorkController(AppCase): - - def setup(self): - self.worker = self.create_worker() - from celery import worker - self._logger = worker.logger - self._comp_logger = components.logger - self.logger = worker.logger = Mock() - self.comp_logger = components.logger = Mock() - - @self.app.task(shared=False) - def foo_task(x, y, z): - return x * y * z - self.foo_task = foo_task - - def teardown(self): - from celery import worker - worker.logger = self._logger - components.logger = self._comp_logger - - def create_worker(self, **kw): - worker = self.app.WorkController(concurrency=1, loglevel=0, **kw) - worker.blueprint.shutdown_complete.set() - return worker - - def test_on_consumer_ready(self): - self.worker.on_consumer_ready(Mock()) - - def test_setup_queues_worker_direct(self): - self.app.conf.CELERY_WORKER_DIRECT = True - self.app.amqp.__dict__['queues'] = Mock() - self.worker.setup_queues({}) - self.app.amqp.queues.select_add.assert_called_with( - worker_direct(self.worker.hostname), - ) - - def test_send_worker_shutdown(self): - with patch('celery.signals.worker_shutdown') as ws: - self.worker._send_worker_shutdown() - ws.send.assert_called_with(sender=self.worker) - - def test_process_shutdown_on_worker_shutdown(self): - raise SkipTest('unstable test') - from celery.concurrency.prefork import process_destructor - from celery.concurrency.asynpool import Worker - with patch('celery.signals.worker_process_shutdown') as ws: - Worker._make_shortcuts = Mock() - with patch('os._exit') as _exit: - worker = Worker(None, None, on_exit=process_destructor) - worker._do_exit(22, 3.1415926) - ws.send.assert_called_with( - sender=None, pid=22, exitcode=3.1415926, - ) - _exit.assert_called_with(3.1415926) - - def test_process_task_revoked_release_semaphore(self): - self.worker._quick_release = Mock() - req = Mock() - req.execute_using_pool.side_effect = TaskRevokedError - self.worker._process_task(req) - self.worker._quick_release.assert_called_with() - - delattr(self.worker, '_quick_release') - self.worker._process_task(req) - - def test_shutdown_no_blueprint(self): - self.worker.blueprint = None - self.worker._shutdown() - - @patch('celery.platforms.create_pidlock') - def test_use_pidfile(self, create_pidlock): - create_pidlock.return_value = Mock() - worker = self.create_worker(pidfile='pidfilelockfilepid') - worker.steps = [] - worker.start() - self.assertTrue(create_pidlock.called) - worker.stop() - self.assertTrue(worker.pidlock.release.called) - - @patch('celery.platforms.signals') - @patch('celery.platforms.set_mp_process_title') - def test_process_initializer(self, set_mp_process_title, _signals): - with restore_logging(): - from celery import signals - from celery._state import _tls - from celery.concurrency.prefork import ( - process_initializer, WORKER_SIGRESET, WORKER_SIGIGNORE, - ) - - def on_worker_process_init(**kwargs): - on_worker_process_init.called = True - on_worker_process_init.called = False - signals.worker_process_init.connect(on_worker_process_init) - - def Loader(*args, **kwargs): - loader = Mock(*args, **kwargs) - loader.conf = {} - loader.override_backends = {} - return loader - - with self.Celery(loader=Loader) as app: - app.conf = AttributeDict(DEFAULTS) - process_initializer(app, 'awesome.worker.com') - _signals.ignore.assert_any_call(*WORKER_SIGIGNORE) - _signals.reset.assert_any_call(*WORKER_SIGRESET) - self.assertTrue(app.loader.init_worker.call_count) - self.assertTrue(on_worker_process_init.called) - self.assertIs(_tls.current_app, app) - set_mp_process_title.assert_called_with( - 'celeryd', hostname='awesome.worker.com', - ) - - with patch('celery.app.trace.setup_worker_optimizations') as S: - os.environ['FORKED_BY_MULTIPROCESSING'] = "1" - try: - process_initializer(app, 'luke.worker.com') - S.assert_called_with(app) - finally: - os.environ.pop('FORKED_BY_MULTIPROCESSING', None) - - def test_attrs(self): - worker = self.worker - self.assertIsNotNone(worker.timer) - self.assertIsInstance(worker.timer, Timer) - self.assertIsNotNone(worker.pool) - self.assertIsNotNone(worker.consumer) - self.assertTrue(worker.steps) - - def test_with_embedded_beat(self): - worker = self.app.WorkController(concurrency=1, loglevel=0, beat=True) - self.assertTrue(worker.beat) - self.assertIn(worker.beat, [w.obj for w in worker.steps]) - - def test_with_autoscaler(self): - worker = self.create_worker( - autoscale=[10, 3], send_events=False, - timer_cls='celery.utils.timer2.Timer', - ) - self.assertTrue(worker.autoscaler) - - def test_dont_stop_or_terminate(self): - worker = self.app.WorkController(concurrency=1, loglevel=0) - worker.stop() - self.assertNotEqual(worker.blueprint.state, CLOSE) - worker.terminate() - self.assertNotEqual(worker.blueprint.state, CLOSE) - - sigsafe, worker.pool.signal_safe = worker.pool.signal_safe, False - try: - worker.blueprint.state = RUN - worker.stop(in_sighandler=True) - self.assertNotEqual(worker.blueprint.state, CLOSE) - worker.terminate(in_sighandler=True) - self.assertNotEqual(worker.blueprint.state, CLOSE) - finally: - worker.pool.signal_safe = sigsafe - - def test_on_timer_error(self): - worker = self.app.WorkController(concurrency=1, loglevel=0) - - try: - raise KeyError('foo') - except KeyError as exc: - components.Timer(worker).on_timer_error(exc) - msg, args = self.comp_logger.error.call_args[0] - self.assertIn('KeyError', msg % args) - - def test_on_timer_tick(self): - worker = self.app.WorkController(concurrency=1, loglevel=10) - - components.Timer(worker).on_timer_tick(30.0) - xargs = self.comp_logger.debug.call_args[0] - fmt, arg = xargs[0], xargs[1] - self.assertEqual(30.0, arg) - self.assertIn('Next eta %s secs', fmt) - - def test_process_task(self): - worker = self.worker - worker.pool = Mock() - backend = Mock() - m = create_message(backend, task=self.foo_task.name, args=[4, 8, 10], - kwargs={}) - task = Request(m.decode(), message=m, app=self.app) - worker._process_task(task) - self.assertEqual(worker.pool.apply_async.call_count, 1) - worker.pool.stop() - - def test_process_task_raise_base(self): - worker = self.worker - worker.pool = Mock() - worker.pool.apply_async.side_effect = KeyboardInterrupt('Ctrl+C') - backend = Mock() - m = create_message(backend, task=self.foo_task.name, args=[4, 8, 10], - kwargs={}) - task = Request(m.decode(), message=m, app=self.app) - worker.steps = [] - worker.blueprint.state = RUN - with self.assertRaises(KeyboardInterrupt): - worker._process_task(task) - - def test_process_task_raise_WorkerTerminate(self): - worker = self.worker - worker.pool = Mock() - worker.pool.apply_async.side_effect = WorkerTerminate() - backend = Mock() - m = create_message(backend, task=self.foo_task.name, args=[4, 8, 10], - kwargs={}) - task = Request(m.decode(), message=m, app=self.app) - worker.steps = [] - worker.blueprint.state = RUN - with self.assertRaises(SystemExit): - worker._process_task(task) - - def test_process_task_raise_regular(self): - worker = self.worker - worker.pool = Mock() - worker.pool.apply_async.side_effect = KeyError('some exception') - backend = Mock() - m = create_message(backend, task=self.foo_task.name, args=[4, 8, 10], - kwargs={}) - task = Request(m.decode(), message=m, app=self.app) - worker._process_task(task) - worker.pool.stop() - - def test_start_catches_base_exceptions(self): - worker1 = self.create_worker() - worker1.blueprint.state = RUN - stc = MockStep() - stc.start.side_effect = WorkerTerminate() - worker1.steps = [stc] - worker1.start() - stc.start.assert_called_with(worker1) - self.assertTrue(stc.terminate.call_count) - - worker2 = self.create_worker() - worker2.blueprint.state = RUN - sec = MockStep() - sec.start.side_effect = WorkerShutdown() - sec.terminate = None - worker2.steps = [sec] - worker2.start() - self.assertTrue(sec.stop.call_count) - - def test_state_db(self): - from celery.worker import state - Persistent = state.Persistent - - state.Persistent = Mock() - try: - worker = self.create_worker(state_db='statefilename') - self.assertTrue(worker._persistence) - finally: - state.Persistent = Persistent - - def test_process_task_sem(self): - worker = self.worker - worker._quick_acquire = Mock() - - req = Mock() - worker._process_task_sem(req) - worker._quick_acquire.assert_called_with(worker._process_task, req) - - def test_signal_consumer_close(self): - worker = self.worker - worker.consumer = Mock() - - worker.signal_consumer_close() - worker.consumer.close.assert_called_with() - - worker.consumer.close.side_effect = AttributeError() - worker.signal_consumer_close() - - def test_start__stop(self): - worker = self.worker - worker.blueprint.shutdown_complete.set() - worker.steps = [MockStep(StartStopStep(self)) for _ in range(4)] - worker.blueprint.state = RUN - worker.blueprint.started = 4 - for w in worker.steps: - w.start = Mock() - w.close = Mock() - w.stop = Mock() - - worker.start() - for w in worker.steps: - self.assertTrue(w.start.call_count) - worker.consumer = Mock() - worker.stop() - for stopstep in worker.steps: - self.assertTrue(stopstep.close.call_count) - self.assertTrue(stopstep.stop.call_count) - - # Doesn't close pool if no pool. - worker.start() - worker.pool = None - worker.stop() - - # test that stop of None is not attempted - worker.steps[-1] = None - worker.start() - worker.stop() - - def test_step_raises(self): - worker = self.worker - step = Mock() - worker.steps = [step] - step.start.side_effect = TypeError() - worker.stop = Mock() - worker.start() - worker.stop.assert_called_with() - - def test_state(self): - self.assertTrue(self.worker.state) - - def test_start__terminate(self): - worker = self.worker - worker.blueprint.shutdown_complete.set() - worker.blueprint.started = 5 - worker.blueprint.state = RUN - worker.steps = [MockStep() for _ in range(5)] - worker.start() - for w in worker.steps[:3]: - self.assertTrue(w.start.call_count) - self.assertTrue(worker.blueprint.started, len(worker.steps)) - self.assertEqual(worker.blueprint.state, RUN) - worker.terminate() - for step in worker.steps: - self.assertTrue(step.terminate.call_count) - - def test_Queues_pool_no_sem(self): - w = Mock() - w.pool_cls.uses_semaphore = False - components.Queues(w).create(w) - self.assertIs(w.process_task, w._process_task) - - def test_Hub_crate(self): - w = Mock() - x = components.Hub(w) - x.create(w) - self.assertTrue(w.timer.max_interval) - - def test_Pool_crate_threaded(self): - w = Mock() - w._conninfo.connection_errors = w._conninfo.channel_errors = () - w.pool_cls = Mock() - w.use_eventloop = False - pool = components.Pool(w) - pool.create(w) - - def test_Pool_create(self): - from kombu.async.semaphore import LaxBoundedSemaphore - w = Mock() - w._conninfo.connection_errors = w._conninfo.channel_errors = () - w.hub = Mock() - - PoolImp = Mock() - poolimp = PoolImp.return_value = Mock() - poolimp._pool = [Mock(), Mock()] - poolimp._cache = {} - poolimp._fileno_to_inq = {} - poolimp._fileno_to_outq = {} - - from celery.concurrency.prefork import TaskPool as _TaskPool - - class MockTaskPool(_TaskPool): - Pool = PoolImp - - @property - def timers(self): - return {Mock(): 30} - - w.pool_cls = MockTaskPool - w.use_eventloop = True - w.consumer.restart_count = -1 - pool = components.Pool(w) - pool.create(w) - pool.register_with_event_loop(w, w.hub) - self.assertIsInstance(w.semaphore, LaxBoundedSemaphore) - P = w.pool - P.start() diff --git a/awx/lib/site-packages/celery/utils/__init__.py b/awx/lib/site-packages/celery/utils/__init__.py deleted file mode 100644 index 24205090bb..0000000000 --- a/awx/lib/site-packages/celery/utils/__init__.py +++ /dev/null @@ -1,397 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils - ~~~~~~~~~~~~ - - Utility functions. - -""" -from __future__ import absolute_import, print_function - -import numbers -import os -import re -import socket -import sys -import traceback -import warnings -import datetime - -from collections import Callable -from functools import partial, wraps -from inspect import getargspec -from pprint import pprint - -from kombu.entity import Exchange, Queue - -from celery.exceptions import CPendingDeprecationWarning, CDeprecationWarning -from celery.five import WhateverIO, items, reraise, string_t - -__all__ = ['worker_direct', 'warn_deprecated', 'deprecated', 'lpmerge', - 'is_iterable', 'isatty', 'cry', 'maybe_reraise', 'strtobool', - 'jsonify', 'gen_task_name', 'nodename', 'nodesplit', - 'cached_property'] - -PY3 = sys.version_info[0] == 3 - - -PENDING_DEPRECATION_FMT = """ - {description} is scheduled for deprecation in \ - version {deprecation} and removal in version v{removal}. \ - {alternative} -""" - -DEPRECATION_FMT = """ - {description} is deprecated and scheduled for removal in - version {removal}. {alternative} -""" - -#: Billiard sets this when execv is enabled. -#: We use it to find out the name of the original ``__main__`` -#: module, so that we can properly rewrite the name of the -#: task to be that of ``App.main``. -MP_MAIN_FILE = os.environ.get('MP_MAIN_FILE') or None - -#: Exchange for worker direct queues. -WORKER_DIRECT_EXCHANGE = Exchange('C.dq') - -#: Format for worker direct queue names. -WORKER_DIRECT_QUEUE_FORMAT = '{hostname}.dq' - -#: Separator for worker node name and hostname. -NODENAME_SEP = '@' - -NODENAME_DEFAULT = 'celery' -RE_FORMAT = re.compile(r'%(\w)') - - -def worker_direct(hostname): - """Return :class:`kombu.Queue` that is a direct route to - a worker by hostname. - - :param hostname: The fully qualified node name of a worker - (e.g. ``w1@example.com``). If passed a - :class:`kombu.Queue` instance it will simply return - that instead. - """ - if isinstance(hostname, Queue): - return hostname - return Queue(WORKER_DIRECT_QUEUE_FORMAT.format(hostname=hostname), - WORKER_DIRECT_EXCHANGE, - hostname, auto_delete=True) - - -def warn_deprecated(description=None, deprecation=None, - removal=None, alternative=None, stacklevel=2): - ctx = {'description': description, - 'deprecation': deprecation, 'removal': removal, - 'alternative': alternative} - if deprecation is not None: - w = CPendingDeprecationWarning(PENDING_DEPRECATION_FMT.format(**ctx)) - else: - w = CDeprecationWarning(DEPRECATION_FMT.format(**ctx)) - warnings.warn(w, stacklevel=stacklevel) - - -def deprecated(deprecation=None, removal=None, - alternative=None, description=None): - """Decorator for deprecated functions. - - A deprecation warning will be emitted when the function is called. - - :keyword deprecation: Version that marks first deprecation, if this - argument is not set a ``PendingDeprecationWarning`` will be emitted - instead. - :keyword removal: Future version when this feature will be removed. - :keyword alternative: Instructions for an alternative solution (if any). - :keyword description: Description of what is being deprecated. - - """ - def _inner(fun): - - @wraps(fun) - def __inner(*args, **kwargs): - from .imports import qualname - warn_deprecated(description=description or qualname(fun), - deprecation=deprecation, - removal=removal, - alternative=alternative, - stacklevel=3) - return fun(*args, **kwargs) - return __inner - return _inner - - -def deprecated_property(deprecation=None, removal=None, - alternative=None, description=None): - def _inner(fun): - return _deprecated_property( - fun, deprecation=deprecation, removal=removal, - alternative=alternative, description=description or fun.__name__) - return _inner - - -class _deprecated_property(object): - - def __init__(self, fget=None, fset=None, fdel=None, doc=None, **depreinfo): - self.__get = fget - self.__set = fset - self.__del = fdel - self.__name__, self.__module__, self.__doc__ = ( - fget.__name__, fget.__module__, fget.__doc__, - ) - self.depreinfo = depreinfo - self.depreinfo.setdefault('stacklevel', 3) - - def __get__(self, obj, type=None): - if obj is None: - return self - warn_deprecated(**self.depreinfo) - return self.__get(obj) - - def __set__(self, obj, value): - if obj is None: - return self - if self.__set is None: - raise AttributeError('cannot set attribute') - warn_deprecated(**self.depreinfo) - self.__set(obj, value) - - def __delete__(self, obj): - if obj is None: - return self - if self.__del is None: - raise AttributeError('cannot delete attribute') - warn_deprecated(**self.depreinfo) - self.__del(obj) - - def setter(self, fset): - return self.__class__(self.__get, fset, self.__del, **self.depreinfo) - - def deleter(self, fdel): - return self.__class__(self.__get, self.__set, fdel, **self.depreinfo) - - -def lpmerge(L, R): - """In place left precedent dictionary merge. - - Keeps values from `L`, if the value in `R` is :const:`None`.""" - set = L.__setitem__ - [set(k, v) for k, v in items(R) if v is not None] - return L - - -def is_iterable(obj): - try: - iter(obj) - except TypeError: - return False - return True - - -def fun_takes_kwargs(fun, kwlist=[]): - # deprecated - S = getattr(fun, 'argspec', getargspec(fun)) - if S.keywords is not None: - return kwlist - return [kw for kw in kwlist if kw in S.args] - - -def isatty(fh): - try: - return fh.isatty() - except AttributeError: - pass - - -def cry(out=None, sepchr='=', seplen=49): # pragma: no cover - """Return stacktrace of all active threads, - taken from https://gist.github.com/737056.""" - import threading - - out = WhateverIO() if out is None else out - P = partial(print, file=out) - - # get a map of threads by their ID so we can print their names - # during the traceback dump - tmap = dict((t.ident, t) for t in threading.enumerate()) - - sep = sepchr * seplen - for tid, frame in items(sys._current_frames()): - thread = tmap.get(tid) - if not thread: - # skip old junk (left-overs from a fork) - continue - P('{0.name}'.format(thread)) - P(sep) - traceback.print_stack(frame, file=out) - P(sep) - P('LOCAL VARIABLES') - P(sep) - pprint(frame.f_locals, stream=out) - P('\n') - return out.getvalue() - - -def maybe_reraise(): - """Re-raise if an exception is currently being handled, or return - otherwise.""" - exc_info = sys.exc_info() - try: - if exc_info[2]: - reraise(exc_info[0], exc_info[1], exc_info[2]) - finally: - # see http://docs.python.org/library/sys.html#sys.exc_info - del(exc_info) - - -def strtobool(term, table={'false': False, 'no': False, '0': False, - 'true': True, 'yes': True, '1': True, - 'on': True, 'off': False}): - """Convert common terms for true/false to bool - (true/false/yes/no/on/off/1/0).""" - if isinstance(term, string_t): - try: - return table[term.lower()] - except KeyError: - raise TypeError('Cannot coerce {0!r} to type bool'.format(term)) - return term - - -def jsonify(obj, - builtin_types=(numbers.Real, string_t), key=None, - keyfilter=None, - unknown_type_filter=None): - """Transforms object making it suitable for json serialization""" - from kombu.abstract import Object as KombuDictType - _jsonify = partial(jsonify, builtin_types=builtin_types, key=key, - keyfilter=keyfilter, - unknown_type_filter=unknown_type_filter) - - if isinstance(obj, KombuDictType): - obj = obj.as_dict(recurse=True) - - if obj is None or isinstance(obj, builtin_types): - return obj - elif isinstance(obj, (tuple, list)): - return [_jsonify(v) for v in obj] - elif isinstance(obj, dict): - return dict((k, _jsonify(v, key=k)) - for k, v in items(obj) - if (keyfilter(k) if keyfilter else 1)) - elif isinstance(obj, datetime.datetime): - # See "Date Time String Format" in the ECMA-262 specification. - r = obj.isoformat() - if obj.microsecond: - r = r[:23] + r[26:] - if r.endswith('+00:00'): - r = r[:-6] + 'Z' - return r - elif isinstance(obj, datetime.date): - return obj.isoformat() - elif isinstance(obj, datetime.time): - r = obj.isoformat() - if obj.microsecond: - r = r[:12] - return r - elif isinstance(obj, datetime.timedelta): - return str(obj) - else: - if unknown_type_filter is None: - raise ValueError( - 'Unsupported type: {0!r} {1!r} (parent: {2})'.format( - type(obj), obj, key)) - return unknown_type_filter(obj) - - -def gen_task_name(app, name, module_name): - """Generate task name from name/module pair.""" - try: - module = sys.modules[module_name] - except KeyError: - # Fix for manage.py shell_plus (Issue #366) - module = None - - if module is not None: - module_name = module.__name__ - # - If the task module is used as the __main__ script - # - we need to rewrite the module part of the task name - # - to match App.main. - if MP_MAIN_FILE and module.__file__ == MP_MAIN_FILE: - # - see comment about :envvar:`MP_MAIN_FILE` above. - module_name = '__main__' - if module_name == '__main__' and app.main: - return '.'.join([app.main, name]) - return '.'.join(p for p in (module_name, name) if p) - - -def nodename(name, hostname): - """Create node name from name/hostname pair.""" - return NODENAME_SEP.join((name, hostname)) - - -def anon_nodename(hostname=None, prefix='gen'): - return nodename(''.join([prefix, str(os.getpid())]), - hostname or socket.gethostname()) - - -def nodesplit(nodename): - """Split node name into tuple of name/hostname.""" - parts = nodename.split(NODENAME_SEP, 1) - if len(parts) == 1: - return None, parts[0] - return parts - - -def default_nodename(hostname): - name, host = nodesplit(hostname or '') - return nodename(name or NODENAME_DEFAULT, host or socket.gethostname()) - - -def node_format(s, nodename, **extra): - name, host = nodesplit(nodename) - return host_format( - s, host, n=name or NODENAME_DEFAULT, **extra) - - -def _fmt_process_index(prefix='', default='0'): - from .log import current_process_index - index = current_process_index() - return '{0}{1}'.format(prefix, index) if index else default -_fmt_process_index_with_prefix = partial(_fmt_process_index, '-', '') - - -def host_format(s, host=None, **extra): - host = host or socket.gethostname() - name, _, domain = host.partition('.') - keys = dict({ - 'h': host, 'n': name, 'd': domain, - 'i': _fmt_process_index, 'I': _fmt_process_index_with_prefix, - }, **extra) - return simple_format(s, keys) - - -def simple_format(s, keys, pattern=RE_FORMAT, expand=r'\1'): - if s: - keys.setdefault('%', '%') - - def resolve(match): - resolver = keys[match.expand(expand)] - if isinstance(resolver, Callable): - return resolver() - return resolver - - return pattern.sub(resolve, s) - return s - - -# ------------------------------------------------------------------------ # -# > XXX Compat -from .log import LOG_LEVELS # noqa -from .imports import ( # noqa - qualname as get_full_cls_name, symbol_by_name as get_cls_by_name, - instantiate, import_from_cwd -) -from .functional import chunks, noop # noqa -from kombu.utils import cached_property, kwdict, uuid # noqa -gen_unique_id = uuid diff --git a/awx/lib/site-packages/celery/utils/compat.py b/awx/lib/site-packages/celery/utils/compat.py deleted file mode 100644 index 6f62964897..0000000000 --- a/awx/lib/site-packages/celery/utils/compat.py +++ /dev/null @@ -1 +0,0 @@ -from celery.five import * # noqa diff --git a/awx/lib/site-packages/celery/utils/debug.py b/awx/lib/site-packages/celery/utils/debug.py deleted file mode 100644 index 79ac4e1e31..0000000000 --- a/awx/lib/site-packages/celery/utils/debug.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.debug - ~~~~~~~~~~~~~~~~~~ - - Utilities for debugging memory usage. - -""" -from __future__ import absolute_import, print_function, unicode_literals - -import os - -from contextlib import contextmanager -from functools import partial - -from celery.five import range -from celery.platforms import signals - -try: - from psutil import Process -except ImportError: - Process = None # noqa - -__all__ = [ - 'blockdetection', 'sample_mem', 'memdump', 'sample', - 'humanbytes', 'mem_rss', 'ps', -] - -UNITS = ( - (2 ** 40.0, 'TB'), - (2 ** 30.0, 'GB'), - (2 ** 20.0, 'MB'), - (2 ** 10.0, 'kB'), - (0.0, '{0!d}b'), -) - -_process = None -_mem_sample = [] - - -def _on_blocking(signum, frame): - import inspect - raise RuntimeError( - 'Blocking detection timed-out at: {0}'.format( - inspect.getframeinfo(frame) - ) - ) - - -@contextmanager -def blockdetection(timeout): - """A timeout context using ``SIGALRM`` that can be used to detect blocking - functions.""" - if not timeout: - yield - else: - old_handler = signals['ALRM'] - old_handler = None if old_handler == _on_blocking else old_handler - - signals['ALRM'] = _on_blocking - - try: - yield signals.arm_alarm(timeout) - finally: - if old_handler: - signals['ALRM'] = old_handler - signals.reset_alarm() - - -def sample_mem(): - """Sample RSS memory usage. - - Statistics can then be output by calling :func:`memdump`. - - """ - current_rss = mem_rss() - _mem_sample.append(current_rss) - return current_rss - - -def _memdump(samples=10): - S = _mem_sample - prev = list(S) if len(S) <= samples else sample(S, samples) - _mem_sample[:] = [] - import gc - gc.collect() - after_collect = mem_rss() - return prev, after_collect - - -def memdump(samples=10, file=None): - """Dump memory statistics. - - Will print a sample of all RSS memory samples added by - calling :func:`sample_mem`, and in addition print - used RSS memory after :func:`gc.collect`. - - """ - say = partial(print, file=file) - if ps() is None: - say('- rss: (psutil not installed).') - return - prev, after_collect = _memdump(samples) - if prev: - say('- rss (sample):') - for mem in prev: - say('- > {0},'.format(mem)) - say('- rss (end): {0}.'.format(after_collect)) - - -def sample(x, n, k=0): - """Given a list `x` a sample of length ``n`` of that list is returned. - - E.g. if `n` is 10, and `x` has 100 items, a list of every 10th - item is returned. - - ``k`` can be used as offset. - - """ - j = len(x) // n - for _ in range(n): - try: - yield x[k] - except IndexError: - break - k += j - - -def hfloat(f, p=5): - """Convert float to value suitable for humans. - - :keyword p: Float precision. - - """ - i = int(f) - return i if i == f else '{0:.{p}}'.format(f, p=p) - - -def humanbytes(s): - """Convert bytes to human-readable form (e.g. kB, MB).""" - return next( - '{0}{1}'.format(hfloat(s / div if div else s), unit) - for div, unit in UNITS if s >= div - ) - - -def mem_rss(): - """Return RSS memory usage as a humanized string.""" - p = ps() - if p is not None: - return humanbytes(p.get_memory_info().rss) - - -def ps(): - """Return the global :class:`psutil.Process` instance, - or :const:`None` if :mod:`psutil` is not installed.""" - global _process - if _process is None and Process is not None: - _process = Process(os.getpid()) - return _process diff --git a/awx/lib/site-packages/celery/utils/dispatch/__init__.py b/awx/lib/site-packages/celery/utils/dispatch/__init__.py deleted file mode 100644 index b6e8d0b23b..0000000000 --- a/awx/lib/site-packages/celery/utils/dispatch/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import - -from .signal import Signal - -__all__ = ['Signal'] diff --git a/awx/lib/site-packages/celery/utils/dispatch/saferef.py b/awx/lib/site-packages/celery/utils/dispatch/saferef.py deleted file mode 100644 index cd818bb2d4..0000000000 --- a/awx/lib/site-packages/celery/utils/dispatch/saferef.py +++ /dev/null @@ -1,286 +0,0 @@ -# -*- coding: utf-8 -*- -""" -"Safe weakrefs", originally from pyDispatcher. - -Provides a way to safely weakref any function, including bound methods (which -aren't handled by the core weakref module). -""" -from __future__ import absolute_import - -import sys -import traceback -import weakref - -__all__ = ['safe_ref'] - -PY3 = sys.version_info[0] == 3 - - -def safe_ref(target, on_delete=None): # pragma: no cover - """Return a *safe* weak reference to a callable target - - :param target: the object to be weakly referenced, if it's a - bound method reference, will create a :class:`BoundMethodWeakref`, - otherwise creates a simple :class:`weakref.ref`. - - :keyword on_delete: if provided, will have a hard reference stored - to the callable to be called after the safe reference - goes out of scope with the reference object, (either a - :class:`weakref.ref` or a :class:`BoundMethodWeakref`) as argument. - """ - if getattr(target, '__self__', None) is not None: - # Turn a bound method into a BoundMethodWeakref instance. - # Keep track of these instances for lookup by disconnect(). - assert hasattr(target, '__func__'), \ - """safe_ref target {0!r} has __self__, but no __func__: \ - don't know how to create reference""".format(target) - return get_bound_method_weakref(target=target, - on_delete=on_delete) - if callable(on_delete): - return weakref.ref(target, on_delete) - else: - return weakref.ref(target) - - -class BoundMethodWeakref(object): # pragma: no cover - """'Safe' and reusable weak references to instance methods. - - BoundMethodWeakref objects provide a mechanism for - referencing a bound method without requiring that the - method object itself (which is normally a transient - object) is kept alive. Instead, the BoundMethodWeakref - object keeps weak references to both the object and the - function which together define the instance method. - - .. attribute:: key - - the identity key for the reference, calculated - by the class's :meth:`calculate_key` method applied to the - target instance method - - .. attribute:: deletion_methods - - sequence of callable objects taking - single argument, a reference to this object which - will be called when *either* the target object or - target function is garbage collected (i.e. when - this object becomes invalid). These are specified - as the on_delete parameters of :func:`safe_ref` calls. - - .. attribute:: weak_self - - weak reference to the target object - - .. attribute:: weak_fun - - weak reference to the target function - - .. attribute:: _all_instances - - class attribute pointing to all live - BoundMethodWeakref objects indexed by the class's - `calculate_key(target)` method applied to the target - objects. This weak value dictionary is used to - short-circuit creation so that multiple references - to the same (object, function) pair produce the - same BoundMethodWeakref instance. - - """ - - _all_instances = weakref.WeakValueDictionary() - - def __new__(cls, target, on_delete=None, *arguments, **named): - """Create new instance or return current instance - - Basically this method of construction allows us to - short-circuit creation of references to already- - referenced instance methods. The key corresponding - to the target is calculated, and if there is already - an existing reference, that is returned, with its - deletionMethods attribute updated. Otherwise the - new instance is created and registered in the table - of already-referenced methods. - - """ - key = cls.calculate_key(target) - current = cls._all_instances.get(key) - if current is not None: - current.deletion_methods.append(on_delete) - return current - else: - base = super(BoundMethodWeakref, cls).__new__(cls) - cls._all_instances[key] = base - base.__init__(target, on_delete, *arguments, **named) - return base - - def __init__(self, target, on_delete=None): - """Return a weak-reference-like instance for a bound method - - :param target: the instance-method target for the weak - reference, must have `__self__` and `__func__` attributes - and be reconstructable via:: - - target.__func__.__get__(target.__self__) - - which is true of built-in instance methods. - - :keyword on_delete: optional callback which will be called - when this weak reference ceases to be valid - (i.e. either the object or the function is garbage - collected). Should take a single argument, - which will be passed a pointer to this object. - - """ - def remove(weak, self=self): - """Set self.is_dead to true when method or instance is destroyed""" - methods = self.deletion_methods[:] - del(self.deletion_methods[:]) - try: - del(self.__class__._all_instances[self.key]) - except KeyError: - pass - for function in methods: - try: - if callable(function): - function(self) - except Exception as exc: - try: - traceback.print_exc() - except AttributeError: - print('Exception during saferef {0} cleanup function ' - '{1}: {2}'.format(self, function, exc)) - - self.deletion_methods = [on_delete] - self.key = self.calculate_key(target) - self.weak_self = weakref.ref(target.__self__, remove) - self.weak_fun = weakref.ref(target.__func__, remove) - self.self_name = str(target.__self__) - self.fun_name = str(target.__func__.__name__) - - def calculate_key(cls, target): - """Calculate the reference key for this reference - - Currently this is a two-tuple of the `id()`'s of the - target object and the target function respectively. - """ - return id(target.__self__), id(target.__func__) - calculate_key = classmethod(calculate_key) - - def __str__(self): - """Give a friendly representation of the object""" - return '{0}( {1}.{2} )'.format( - type(self).__name__, - self.self_name, - self.fun_name, - ) - - __repr__ = __str__ - - def __bool__(self): - """Whether we are still a valid reference""" - return self() is not None - __nonzero__ = __bool__ # py2 - - if not PY3: - def __cmp__(self, other): - """Compare with another reference""" - if not isinstance(other, self.__class__): - return cmp(self.__class__, type(other)) # noqa - return cmp(self.key, other.key) # noqa - - def __call__(self): - """Return a strong reference to the bound method - - If the target cannot be retrieved, then will - return None, otherwise return a bound instance - method for our object and function. - - Note: - You may call this method any number of times, - as it does not invalidate the reference. - """ - target = self.weak_self() - if target is not None: - function = self.weak_fun() - if function is not None: - return function.__get__(target) - - -class BoundNonDescriptorMethodWeakref(BoundMethodWeakref): # pragma: no cover - """A specialized :class:`BoundMethodWeakref`, for platforms where - instance methods are not descriptors. - - It assumes that the function name and the target attribute name are the - same, instead of assuming that the function is a descriptor. This approach - is equally fast, but not 100% reliable because functions can be stored on - an attribute named differenty than the function's name such as in:: - - >>> class A(object): - ... pass - - >>> def foo(self): - ... return 'foo' - >>> A.bar = foo - - But this shouldn't be a common use case. So, on platforms where methods - aren't descriptors (such as Jython) this implementation has the advantage - of working in the most cases. - - """ - def __init__(self, target, on_delete=None): - """Return a weak-reference-like instance for a bound method - - :param target: the instance-method target for the weak - reference, must have `__self__` and `__func__` attributes - and be reconstructable via:: - - target.__func__.__get__(target.__self__) - - which is true of built-in instance methods. - - :keyword on_delete: optional callback which will be called - when this weak reference ceases to be valid - (i.e. either the object or the function is garbage - collected). Should take a single argument, - which will be passed a pointer to this object. - - """ - assert getattr(target.__self__, target.__name__) == target - super(BoundNonDescriptorMethodWeakref, self).__init__(target, - on_delete) - - def __call__(self): - """Return a strong reference to the bound method - - If the target cannot be retrieved, then will - return None, otherwise return a bound instance - method for our object and function. - - Note: - You may call this method any number of times, - as it does not invalidate the reference. - - """ - target = self.weak_self() - if target is not None: - function = self.weak_fun() - if function is not None: - # Using curry() would be another option, but it erases the - # "signature" of the function. That is, after a function is - # curried, the inspect module can't be used to determine how - # many arguments the function expects, nor what keyword - # arguments it supports, and pydispatcher needs this - # information. - return getattr(target, function.__name__) - - -def get_bound_method_weakref(target, on_delete): # pragma: no cover - """Instantiates the appropiate :class:`BoundMethodWeakRef`, depending - on the details of the underlying class method implementation.""" - if hasattr(target, '__get__'): - # target method is a descriptor, so the default implementation works: - return BoundMethodWeakref(target=target, on_delete=on_delete) - else: - # no luck, use the alternative implementation: - return BoundNonDescriptorMethodWeakref(target=target, - on_delete=on_delete) diff --git a/awx/lib/site-packages/celery/utils/dispatch/signal.py b/awx/lib/site-packages/celery/utils/dispatch/signal.py deleted file mode 100644 index 7d4b337a9e..0000000000 --- a/awx/lib/site-packages/celery/utils/dispatch/signal.py +++ /dev/null @@ -1,241 +0,0 @@ -# -*- coding: utf-8 -*- -"""Signal class.""" -from __future__ import absolute_import - -import weakref -from . import saferef - -from celery.five import range -from celery.local import PromiseProxy, Proxy - -__all__ = ['Signal'] - -WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref) - - -def _make_id(target): # pragma: no cover - if isinstance(target, Proxy): - target = target._get_current_object() - if hasattr(target, '__func__'): - return (id(target.__self__), id(target.__func__)) - return id(target) - - -class Signal(object): # pragma: no cover - """Base class for all signals - - - .. attribute:: receivers - Internal attribute, holds a dictionary of - `{receiverkey (id): weakref(receiver)}` mappings. - - """ - - def __init__(self, providing_args=None): - """Create a new signal. - - :param providing_args: A list of the arguments this signal can pass - along in a :meth:`send` call. - - """ - self.receivers = [] - if providing_args is None: - providing_args = [] - self.providing_args = set(providing_args) - - def _connect_proxy(self, fun, sender, weak, dispatch_uid): - return self.connect( - fun, sender=sender._get_current_object(), - weak=weak, dispatch_uid=dispatch_uid, - ) - - def connect(self, *args, **kwargs): - """Connect receiver to sender for signal. - - :param receiver: A function or an instance method which is to - receive signals. Receivers must be hashable objects. - - if weak is :const:`True`, then receiver must be weak-referencable - (more precisely :func:`saferef.safe_ref()` must be able to create a - reference to the receiver). - - Receivers must be able to accept keyword arguments. - - If receivers have a `dispatch_uid` attribute, the receiver will - not be added if another receiver already exists with that - `dispatch_uid`. - - :keyword sender: The sender to which the receiver should respond. - Must either be of type :class:`Signal`, or :const:`None` to receive - events from any sender. - - :keyword weak: Whether to use weak references to the receiver. - By default, the module will attempt to use weak references to the - receiver objects. If this parameter is false, then strong - references will be used. - - :keyword dispatch_uid: An identifier used to uniquely identify a - particular instance of a receiver. This will usually be a - string, though it may be anything hashable. - - """ - def _handle_options(sender=None, weak=True, dispatch_uid=None): - - def _connect_signal(fun): - receiver = fun - - if isinstance(sender, PromiseProxy): - sender.__then__( - self._connect_proxy, fun, sender, weak, dispatch_uid, - ) - return fun - - if dispatch_uid: - lookup_key = (dispatch_uid, _make_id(sender)) - else: - lookup_key = (_make_id(receiver), _make_id(sender)) - - if weak: - receiver = saferef.safe_ref( - receiver, on_delete=self._remove_receiver, - ) - - for r_key, _ in self.receivers: - if r_key == lookup_key: - break - else: - self.receivers.append((lookup_key, receiver)) - - return fun - - return _connect_signal - - if args and callable(args[0]): - return _handle_options(*args[1:], **kwargs)(args[0]) - return _handle_options(*args, **kwargs) - - def disconnect(self, receiver=None, sender=None, weak=True, - dispatch_uid=None): - """Disconnect receiver from sender for signal. - - If weak references are used, disconnect need not be called. The - receiver will be removed from dispatch automatically. - - :keyword receiver: The registered receiver to disconnect. May be - none if `dispatch_uid` is specified. - - :keyword sender: The registered sender to disconnect. - - :keyword weak: The weakref state to disconnect. - - :keyword dispatch_uid: the unique identifier of the receiver - to disconnect - - """ - if dispatch_uid: - lookup_key = (dispatch_uid, _make_id(sender)) - else: - lookup_key = (_make_id(receiver), _make_id(sender)) - - for index in range(len(self.receivers)): - (r_key, _) = self.receivers[index] - if r_key == lookup_key: - del self.receivers[index] - break - - def send(self, sender, **named): - """Send signal from sender to all connected receivers. - - If any receiver raises an error, the error propagates back through - send, terminating the dispatch loop, so it is quite possible to not - have all receivers called if a raises an error. - - :param sender: The sender of the signal. Either a specific - object or :const:`None`. - - :keyword \*\*named: Named arguments which will be passed to receivers. - - :returns: a list of tuple pairs: `[(receiver, response), … ]`. - - """ - responses = [] - if not self.receivers: - return responses - - for receiver in self._live_receivers(_make_id(sender)): - response = receiver(signal=self, sender=sender, **named) - responses.append((receiver, response)) - return responses - - def send_robust(self, sender, **named): - """Send signal from sender to all connected receivers catching errors. - - :param sender: The sender of the signal. Can be any python object - (normally one registered with a connect if you actually want - something to occur). - - :keyword \*\*named: Named arguments which will be passed to receivers. - These arguments must be a subset of the argument names defined in - :attr:`providing_args`. - - :returns: a list of tuple pairs: `[(receiver, response), … ]`. - - :raises DispatcherKeyError: - - if any receiver raises an error (specifically any subclass of - :exc:`Exception`), the error instance is returned as the result - for that receiver. - - """ - responses = [] - if not self.receivers: - return responses - - # Call each receiver with whatever arguments it can accept. - # Return a list of tuple pairs [(receiver, response), … ]. - for receiver in self._live_receivers(_make_id(sender)): - try: - response = receiver(signal=self, sender=sender, **named) - except Exception as err: - responses.append((receiver, err)) - else: - responses.append((receiver, response)) - return responses - - def _live_receivers(self, senderkey): - """Filter sequence of receivers to get resolved, live receivers. - - This checks for weak references and resolves them, then returning only - live receivers. - - """ - none_senderkey = _make_id(None) - receivers = [] - - for (receiverkey, r_senderkey), receiver in self.receivers: - if r_senderkey == none_senderkey or r_senderkey == senderkey: - if isinstance(receiver, WEAKREF_TYPES): - # Dereference the weak reference. - receiver = receiver() - if receiver is not None: - receivers.append(receiver) - else: - receivers.append(receiver) - return receivers - - def _remove_receiver(self, receiver): - """Remove dead receivers from connections.""" - - to_remove = [] - for key, connected_receiver in self.receivers: - if connected_receiver == receiver: - to_remove.append(key) - for key in to_remove: - for idx, (r_key, _) in enumerate(self.receivers): - if r_key == key: - del self.receivers[idx] - - def __repr__(self): - return '<Signal: {0}>'.format(type(self).__name__) - - __str__ = __repr__ diff --git a/awx/lib/site-packages/celery/utils/encoding.py b/awx/lib/site-packages/celery/utils/encoding.py deleted file mode 100644 index 3ddcd35ebc..0000000000 --- a/awx/lib/site-packages/celery/utils/encoding.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.encoding - ~~~~~~~~~~~~~~~~~~~~~ - - This module has moved to :mod:`kombu.utils.encoding`. - -""" -from __future__ import absolute_import - -from kombu.utils.encoding import ( # noqa - default_encode, default_encoding, bytes_t, bytes_to_str, str_t, - str_to_bytes, ensure_bytes, from_utf8, safe_str, safe_repr, -) diff --git a/awx/lib/site-packages/celery/utils/functional.py b/awx/lib/site-packages/celery/utils/functional.py deleted file mode 100644 index faa272b323..0000000000 --- a/awx/lib/site-packages/celery/utils/functional.py +++ /dev/null @@ -1,306 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.functional - ~~~~~~~~~~~~~~~~~~~~~~~ - - Utilities for functions. - -""" -from __future__ import absolute_import - -import sys -import threading - -from functools import wraps -from itertools import islice - -from kombu.utils import cached_property -from kombu.utils.functional import lazy, maybe_evaluate, is_list, maybe_list -from kombu.utils.compat import OrderedDict - -from celery.five import UserDict, UserList, items, keys - -__all__ = ['LRUCache', 'is_list', 'maybe_list', 'memoize', 'mlazy', 'noop', - 'first', 'firstmethod', 'chunks', 'padlist', 'mattrgetter', 'uniq', - 'regen', 'dictfilter', 'lazy', 'maybe_evaluate'] - -KEYWORD_MARK = object() - - -class LRUCache(UserDict): - """LRU Cache implementation using a doubly linked list to track access. - - :keyword limit: The maximum number of keys to keep in the cache. - When a new key is inserted and the limit has been exceeded, - the *Least Recently Used* key will be discarded from the - cache. - - """ - - def __init__(self, limit=None): - self.limit = limit - self.mutex = threading.RLock() - self.data = OrderedDict() - - def __getitem__(self, key): - with self.mutex: - value = self[key] = self.data.pop(key) - return value - - def update(self, *args, **kwargs): - with self.mutex: - data, limit = self.data, self.limit - data.update(*args, **kwargs) - if limit and len(data) > limit: - # pop additional items in case limit exceeded - # negative overflow will lead to an empty list - for item in islice(iter(data), len(data) - limit): - data.pop(item) - - def __setitem__(self, key, value): - # remove least recently used key. - with self.mutex: - if self.limit and len(self.data) >= self.limit: - self.data.pop(next(iter(self.data))) - self.data[key] = value - - def __iter__(self): - return iter(self.data) - - def _iterate_items(self): - for k in self: - try: - yield (k, self.data[k]) - except KeyError: # pragma: no cover - pass - iteritems = _iterate_items - - def _iterate_values(self): - for k in self: - try: - yield self.data[k] - except KeyError: # pragma: no cover - pass - itervalues = _iterate_values - - def _iterate_keys(self): - # userdict.keys in py3k calls __getitem__ - return keys(self.data) - iterkeys = _iterate_keys - - def incr(self, key, delta=1): - with self.mutex: - # this acts as memcached does- store as a string, but return a - # integer as long as it exists and we can cast it - newval = int(self.data.pop(key)) + delta - self[key] = str(newval) - return newval - - def __getstate__(self): - d = dict(vars(self)) - d.pop('mutex') - return d - - def __setstate__(self, state): - self.__dict__ = state - self.mutex = threading.RLock() - - if sys.version_info[0] == 3: # pragma: no cover - keys = _iterate_keys - values = _iterate_values - items = _iterate_items - else: # noqa - - def keys(self): - return list(self._iterate_keys()) - - def values(self): - return list(self._iterate_values()) - - def items(self): - return list(self._iterate_items()) - - -def memoize(maxsize=None, keyfun=None, Cache=LRUCache): - - def _memoize(fun): - mutex = threading.Lock() - cache = Cache(limit=maxsize) - - @wraps(fun) - def _M(*args, **kwargs): - if keyfun: - key = keyfun(args, kwargs) - else: - key = args + (KEYWORD_MARK, ) + tuple(sorted(kwargs.items())) - try: - with mutex: - value = cache[key] - except KeyError: - value = fun(*args, **kwargs) - _M.misses += 1 - with mutex: - cache[key] = value - else: - _M.hits += 1 - return value - - def clear(): - """Clear the cache and reset cache statistics.""" - cache.clear() - _M.hits = _M.misses = 0 - - _M.hits = _M.misses = 0 - _M.clear = clear - _M.original_func = fun - return _M - - return _memoize - - -class mlazy(lazy): - """Memoized lazy evaluation. - - The function is only evaluated once, every subsequent access - will return the same value. - - .. attribute:: evaluated - - Set to to :const:`True` after the object has been evaluated. - - """ - evaluated = False - _value = None - - def evaluate(self): - if not self.evaluated: - self._value = super(mlazy, self).evaluate() - self.evaluated = True - return self._value - - -def noop(*args, **kwargs): - """No operation. - - Takes any arguments/keyword arguments and does nothing. - - """ - pass - - -def first(predicate, it): - """Return the first element in `iterable` that `predicate` Gives a - :const:`True` value for. - - If `predicate` is None it will return the first item that is not None. - - """ - return next( - (v for v in it if (predicate(v) if predicate else v is not None)), - None, - ) - - -def firstmethod(method): - """Return a function that with a list of instances, - finds the first instance that gives a value for the given method. - - The list can also contain lazy instances - (:class:`~kombu.utils.functional.lazy`.) - - """ - - def _matcher(it, *args, **kwargs): - for obj in it: - try: - answer = getattr(maybe_evaluate(obj), method)(*args, **kwargs) - except AttributeError: - pass - else: - if answer is not None: - return answer - - return _matcher - - -def chunks(it, n): - """Split an iterator into chunks with `n` elements each. - - Examples - - # n == 2 - >>> x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 2) - >>> list(x) - [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10]] - - # n == 3 - >>> x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 3) - >>> list(x) - [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]] - - """ - # XXX This function is not used anymore, at least not by Celery itself. - for first in it: - yield [first] + list(islice(it, n - 1)) - - -def padlist(container, size, default=None): - """Pad list with default elements. - - Examples: - - >>> first, last, city = padlist(['George', 'Costanza', 'NYC'], 3) - ('George', 'Costanza', 'NYC') - >>> first, last, city = padlist(['George', 'Costanza'], 3) - ('George', 'Costanza', None) - >>> first, last, city, planet = padlist( - ... ['George', 'Costanza', 'NYC'], 4, default='Earth', - ... ) - ('George', 'Costanza', 'NYC', 'Earth') - - """ - return list(container)[:size] + [default] * (size - len(container)) - - -def mattrgetter(*attrs): - """Like :func:`operator.itemgetter` but return :const:`None` on missing - attributes instead of raising :exc:`AttributeError`.""" - return lambda obj: dict((attr, getattr(obj, attr, None)) - for attr in attrs) - - -def uniq(it): - """Return all unique elements in ``it``, preserving order.""" - seen = set() - return (seen.add(obj) or obj for obj in it if obj not in seen) - - -def regen(it): - """Regen takes any iterable, and if the object is an - generator it will cache the evaluated list on first access, - so that the generator can be "consumed" multiple times.""" - if isinstance(it, (list, tuple)): - return it - return _regen(it) - - -class _regen(UserList, list): - # must be subclass of list so that json can encode. - def __init__(self, it): - self.__it = it - - def __reduce__(self): - return list, (self.data, ) - - def __length_hint__(self): - return self.__it.__length_hint__() - - @cached_property - def data(self): - return list(self.__it) - - -def dictfilter(d=None, **kw): - """Remove all keys from dict ``d`` whose value is :const:`None`""" - d = kw if d is None else (dict(d, **kw) if kw else d) - return dict((k, v) for k, v in items(d) if v is not None) diff --git a/awx/lib/site-packages/celery/utils/imports.py b/awx/lib/site-packages/celery/utils/imports.py deleted file mode 100644 index 22a2fdcd31..0000000000 --- a/awx/lib/site-packages/celery/utils/imports.py +++ /dev/null @@ -1,114 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.import - ~~~~~~~~~~~~~~~~~~~ - - Utilities related to importing modules and symbols by name. - -""" -from __future__ import absolute_import - -import imp as _imp -import importlib -import os -import sys - -from contextlib import contextmanager - -from kombu.utils import symbol_by_name - -from celery.five import reload - -__all__ = [ - 'NotAPackage', 'qualname', 'instantiate', 'symbol_by_name', 'cwd_in_path', - 'find_module', 'import_from_cwd', 'reload_from_cwd', 'module_file', -] - - -class NotAPackage(Exception): - pass - - -if sys.version_info > (3, 3): # pragma: no cover - def qualname(obj): - if not hasattr(obj, '__name__') and hasattr(obj, '__class__'): - obj = obj.__class__ - q = getattr(obj, '__qualname__', None) - if '.' not in q: - q = '.'.join((obj.__module__, q)) - return q -else: - def qualname(obj): # noqa - if not hasattr(obj, '__name__') and hasattr(obj, '__class__'): - obj = obj.__class__ - return '.'.join((obj.__module__, obj.__name__)) - - -def instantiate(name, *args, **kwargs): - """Instantiate class by name. - - See :func:`symbol_by_name`. - - """ - return symbol_by_name(name)(*args, **kwargs) - - -@contextmanager -def cwd_in_path(): - cwd = os.getcwd() - if cwd in sys.path: - yield - else: - sys.path.insert(0, cwd) - try: - yield cwd - finally: - try: - sys.path.remove(cwd) - except ValueError: # pragma: no cover - pass - - -def find_module(module, path=None, imp=None): - """Version of :func:`imp.find_module` supporting dots.""" - if imp is None: - imp = importlib.import_module - with cwd_in_path(): - if '.' in module: - last = None - parts = module.split('.') - for i, part in enumerate(parts[:-1]): - mpart = imp('.'.join(parts[:i + 1])) - try: - path = mpart.__path__ - except AttributeError: - raise NotAPackage(module) - last = _imp.find_module(parts[i + 1], path) - return last - return _imp.find_module(module) - - -def import_from_cwd(module, imp=None, package=None): - """Import module, but make sure it finds modules - located in the current directory. - - Modules located in the current directory has - precedence over modules located in `sys.path`. - """ - if imp is None: - imp = importlib.import_module - with cwd_in_path(): - return imp(module, package=package) - - -def reload_from_cwd(module, reloader=None): - if reloader is None: - reloader = reload - with cwd_in_path(): - return reloader(module) - - -def module_file(module): - """Return the correct original file name of a module.""" - name = module.__file__ - return name[:-1] if name.endswith('.pyc') else name diff --git a/awx/lib/site-packages/celery/utils/iso8601.py b/awx/lib/site-packages/celery/utils/iso8601.py deleted file mode 100644 index c951cf6ea8..0000000000 --- a/awx/lib/site-packages/celery/utils/iso8601.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -Originally taken from pyiso8601 (http://code.google.com/p/pyiso8601/) - -Modified to match the behavior of dateutil.parser: - - - raise ValueError instead of ParseError - - return naive datetimes by default - - uses pytz.FixedOffset - -This is the original License: - -Copyright (c) 2007 Michael Twomey - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -""" -from __future__ import absolute_import - -import re - -from datetime import datetime -from pytz import FixedOffset - -__all__ = ['parse_iso8601'] - -# Adapted from http://delete.me.uk/2005/03/iso8601.html -ISO8601_REGEX = re.compile( - r'(?P<year>[0-9]{4})(-(?P<month>[0-9]{1,2})(-(?P<day>[0-9]{1,2})' - r'((?P<separator>.)(?P<hour>[0-9]{2}):(?P<minute>[0-9]{2})' - '(:(?P<second>[0-9]{2})(\.(?P<fraction>[0-9]+))?)?' - r'(?P<timezone>Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?' -) -TIMEZONE_REGEX = re.compile( - '(?P<prefix>[+-])(?P<hours>[0-9]{2}).(?P<minutes>[0-9]{2})' -) - - -def parse_iso8601(datestring): - """Parse and convert ISO 8601 string into a datetime object""" - m = ISO8601_REGEX.match(datestring) - if not m: - raise ValueError('unable to parse date string %r' % datestring) - groups = m.groupdict() - tz = groups['timezone'] - if tz == 'Z': - tz = FixedOffset(0) - elif tz: - m = TIMEZONE_REGEX.match(tz) - prefix, hours, minutes = m.groups() - hours, minutes = int(hours), int(minutes) - if prefix == '-': - hours = -hours - minutes = -minutes - tz = FixedOffset(minutes + hours * 60) - frac = groups['fraction'] or 0 - return datetime( - int(groups['year']), int(groups['month']), int(groups['day']), - int(groups['hour']), int(groups['minute']), int(groups['second']), - int(frac), tz - ) diff --git a/awx/lib/site-packages/celery/utils/log.py b/awx/lib/site-packages/celery/utils/log.py deleted file mode 100644 index 2cef638776..0000000000 --- a/awx/lib/site-packages/celery/utils/log.py +++ /dev/null @@ -1,291 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.log - ~~~~~~~~~~~~~~~~ - - Logging utilities. - -""" -from __future__ import absolute_import, print_function - -import logging -import numbers -import os -import sys -import threading -import traceback - -from contextlib import contextmanager -from billiard import current_process, util as mputil -from kombu.five import values -from kombu.log import get_logger as _get_logger, LOG_LEVELS -from kombu.utils.encoding import safe_str - -from celery.five import string_t, text_t - -from .term import colored - -__all__ = ['ColorFormatter', 'LoggingProxy', 'base_logger', - 'set_in_sighandler', 'in_sighandler', 'get_logger', - 'get_task_logger', 'mlevel', 'ensure_process_aware_logger', - 'get_multiprocessing_logger', 'reset_multiprocessing_logger'] - -_process_aware = False -PY3 = sys.version_info[0] == 3 - -MP_LOG = os.environ.get('MP_LOG', False) - - -# Sets up our logging hierarchy. -# -# Every logger in the celery package inherits from the "celery" -# logger, and every task logger inherits from the "celery.task" -# logger. -base_logger = logger = _get_logger('celery') -mp_logger = _get_logger('multiprocessing') - -_in_sighandler = False - - -def set_in_sighandler(value): - global _in_sighandler - _in_sighandler = value - - -def iter_open_logger_fds(): - seen = set() - loggers = (list(values(logging.Logger.manager.loggerDict)) + - [logging.getLogger(None)]) - for logger in loggers: - try: - for handler in logger.handlers: - try: - if handler not in seen: - yield handler.stream - seen.add(handler) - except AttributeError: - pass - except AttributeError: # PlaceHolder does not have handlers - pass - - -@contextmanager -def in_sighandler(): - set_in_sighandler(True) - try: - yield - finally: - set_in_sighandler(False) - - -def logger_isa(l, p): - this, seen = l, set() - while this: - if this == p: - return True - else: - if this in seen: - raise RuntimeError( - 'Logger {0!r} parents recursive'.format(l), - ) - seen.add(this) - this = this.parent - return False - - -def get_logger(name): - l = _get_logger(name) - if logging.root not in (l, l.parent) and l is not base_logger: - if not logger_isa(l, base_logger): - l.parent = base_logger - return l -task_logger = get_logger('celery.task') -worker_logger = get_logger('celery.worker') - - -def get_task_logger(name): - logger = get_logger(name) - if not logger_isa(logger, task_logger): - logger.parent = task_logger - return logger - - -def mlevel(level): - if level and not isinstance(level, numbers.Integral): - return LOG_LEVELS[level.upper()] - return level - - -class ColorFormatter(logging.Formatter): - #: Loglevel -> Color mapping. - COLORS = colored().names - colors = {'DEBUG': COLORS['blue'], 'WARNING': COLORS['yellow'], - 'ERROR': COLORS['red'], 'CRITICAL': COLORS['magenta']} - - def __init__(self, fmt=None, use_color=True): - logging.Formatter.__init__(self, fmt) - self.use_color = use_color - - def formatException(self, ei): - if ei and not isinstance(ei, tuple): - ei = sys.exc_info() - r = logging.Formatter.formatException(self, ei) - if isinstance(r, str) and not PY3: - return safe_str(r) - return r - - def format(self, record): - sformat = logging.Formatter.format - color = self.colors.get(record.levelname) - - if color and self.use_color: - msg = record.msg - try: - # safe_str will repr the color object - # and color will break on non-string objects - # so need to reorder calls based on type. - # Issue #427 - try: - if isinstance(msg, string_t): - record.msg = text_t(color(safe_str(msg))) - else: - record.msg = safe_str(color(msg)) - except UnicodeDecodeError: - record.msg = safe_str(msg) # skip colors - except Exception as exc: - record.msg = '<Unrepresentable {0!r}: {1!r}>'.format( - type(msg), exc) - record.exc_info = True - return sformat(self, record) - else: - return safe_str(sformat(self, record)) - - -class LoggingProxy(object): - """Forward file object to :class:`logging.Logger` instance. - - :param logger: The :class:`logging.Logger` instance to forward to. - :param loglevel: Loglevel to use when writing messages. - - """ - mode = 'w' - name = None - closed = False - loglevel = logging.ERROR - _thread = threading.local() - - def __init__(self, logger, loglevel=None): - self.logger = logger - self.loglevel = mlevel(loglevel or self.logger.level or self.loglevel) - self._safewrap_handlers() - - def _safewrap_handlers(self): - """Make the logger handlers dump internal errors to - `sys.__stderr__` instead of `sys.stderr` to circumvent - infinite loops.""" - - def wrap_handler(handler): # pragma: no cover - - class WithSafeHandleError(logging.Handler): - - def handleError(self, record): - exc_info = sys.exc_info() - try: - try: - traceback.print_exception(exc_info[0], - exc_info[1], - exc_info[2], - None, sys.__stderr__) - except IOError: - pass # see python issue 5971 - finally: - del(exc_info) - - handler.handleError = WithSafeHandleError().handleError - return [wrap_handler(h) for h in self.logger.handlers] - - def write(self, data): - """Write message to logging object.""" - if _in_sighandler: - return print(safe_str(data), file=sys.__stderr__) - if getattr(self._thread, 'recurse_protection', False): - # Logger is logging back to this file, so stop recursing. - return - data = data.strip() - if data and not self.closed: - self._thread.recurse_protection = True - try: - self.logger.log(self.loglevel, safe_str(data)) - finally: - self._thread.recurse_protection = False - - def writelines(self, sequence): - """`writelines(sequence_of_strings) -> None`. - - Write the strings to the file. - - The sequence can be any iterable object producing strings. - This is equivalent to calling :meth:`write` for each string. - - """ - for part in sequence: - self.write(part) - - def flush(self): - """This object is not buffered so any :meth:`flush` requests - are ignored.""" - pass - - def close(self): - """When the object is closed, no write requests are forwarded to - the logging object anymore.""" - self.closed = True - - def isatty(self): - """Always return :const:`False`. Just here for file support.""" - return False - - -def ensure_process_aware_logger(force=False): - """Make sure process name is recorded when loggers are used.""" - global _process_aware - if force or not _process_aware: - logging._acquireLock() - try: - _process_aware = True - Logger = logging.getLoggerClass() - if getattr(Logger, '_process_aware', False): # pragma: no cover - return - - class ProcessAwareLogger(Logger): - _signal_safe = True - _process_aware = True - - def makeRecord(self, *args, **kwds): - record = Logger.makeRecord(self, *args, **kwds) - record.processName = current_process()._name - return record - - def log(self, *args, **kwargs): - if _in_sighandler: - return - return Logger.log(self, *args, **kwargs) - logging.setLoggerClass(ProcessAwareLogger) - finally: - logging._releaseLock() - - -def get_multiprocessing_logger(): - return mputil.get_logger() if mputil else None - - -def reset_multiprocessing_logger(): - if mputil and hasattr(mputil, '_logger'): - mputil._logger = None - - -def current_process_index(base=1): - if current_process: - index = getattr(current_process(), 'index', None) - return index + base if index is not None else index -ensure_process_aware_logger() diff --git a/awx/lib/site-packages/celery/utils/mail.py b/awx/lib/site-packages/celery/utils/mail.py deleted file mode 100644 index 00c5f29a9d..0000000000 --- a/awx/lib/site-packages/celery/utils/mail.py +++ /dev/null @@ -1,190 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.mail - ~~~~~~~~~~~~~~~~~ - - How task error emails are formatted and sent. - -""" -from __future__ import absolute_import - -import smtplib -import socket -import traceback -import warnings - -from email.mime.text import MIMEText - -from .functional import maybe_list - -try: - from ssl import SSLError -except ImportError: # pragma: no cover - class SSLError(Exception): # noqa - """fallback used when ssl module not compiled.""" - -__all__ = ['SendmailWarning', 'Message', 'Mailer', 'ErrorMail'] - -_local_hostname = None - - -def get_local_hostname(): - global _local_hostname - if _local_hostname is None: - _local_hostname = socket.getfqdn() - return _local_hostname - - -class SendmailWarning(UserWarning): - """Problem happened while sending the email message.""" - - -class Message(object): - - def __init__(self, to=None, sender=None, subject=None, - body=None, charset='us-ascii'): - self.to = maybe_list(to) - self.sender = sender - self.subject = subject - self.body = body - self.charset = charset - - def __repr__(self): - return '<Email: To:{0.to!r} Subject:{0.subject!r}>'.format(self) - - def __str__(self): - msg = MIMEText(self.body, 'plain', self.charset) - msg['Subject'] = self.subject - msg['From'] = self.sender - msg['To'] = ', '.join(self.to) - return msg.as_string() - - -class Mailer(object): - - def __init__(self, host='localhost', port=0, user=None, password=None, - timeout=2, use_ssl=False, use_tls=False): - self.host = host - self.port = port - self.user = user - self.password = password - self.timeout = timeout - self.use_ssl = use_ssl - self.use_tls = use_tls - - def send(self, message, fail_silently=False, **kwargs): - try: - self._send(message, **kwargs) - except Exception as exc: - if not fail_silently: - raise - warnings.warn(SendmailWarning( - 'Mail could not be sent: {0!r} {1!r}\n{2!r}'.format( - exc, {'To': ', '.join(message.to), - 'Subject': message.subject}, - traceback.format_stack()))) - - def _send(self, message, **kwargs): - Client = smtplib.SMTP_SSL if self.use_ssl else smtplib.SMTP - client = Client(self.host, self.port, timeout=self.timeout, - local_hostname=get_local_hostname(), **kwargs) - - if self.use_tls: - client.ehlo() - client.starttls() - client.ehlo() - - if self.user and self.password: - client.login(self.user, self.password) - - client.sendmail(message.sender, message.to, str(message)) - try: - client.quit() - except SSLError: - client.close() - - -class ErrorMail(object): - """Defines how and when task error e-mails should be sent. - - :param task: The task instance that raised the error. - - :attr:`subject` and :attr:`body` are format strings which - are passed a context containing the following keys: - - * name - - Name of the task. - - * id - - UUID of the task. - - * exc - - String representation of the exception. - - * args - - Positional arguments. - - * kwargs - - Keyword arguments. - - * traceback - - String representation of the traceback. - - * hostname - - Worker nodename. - - """ - - # pep8.py borks on a inline signature separator and - # says "trailing whitespace" ;) - EMAIL_SIGNATURE_SEP = '-- ' - - #: Format string used to generate error email subjects. - subject = """\ - [{hostname}] Error: Task {name} ({id}): {exc!r} - """ - - #: Format string used to generate error email content. - body = """ -Task {{name}} with id {{id}} raised exception:\n{{exc!r}} - - -Task was called with args: {{args}} kwargs: {{kwargs}}. - -The contents of the full traceback was: - -{{traceback}} - -{EMAIL_SIGNATURE_SEP} -Just to let you know, -py-celery at {{hostname}}. -""".format(EMAIL_SIGNATURE_SEP=EMAIL_SIGNATURE_SEP) - - def __init__(self, task, **kwargs): - self.task = task - self.subject = kwargs.get('subject', self.subject) - self.body = kwargs.get('body', self.body) - - def should_send(self, context, exc): - """Return true or false depending on if a task error mail - should be sent for this type of error.""" - return True - - def format_subject(self, context): - return self.subject.strip().format(**context) - - def format_body(self, context): - return self.body.strip().format(**context) - - def send(self, context, exc, fail_silently=True): - if self.should_send(context, exc): - self.task.app.mail_admins(self.format_subject(context), - self.format_body(context), - fail_silently=fail_silently) diff --git a/awx/lib/site-packages/celery/utils/objects.py b/awx/lib/site-packages/celery/utils/objects.py deleted file mode 100644 index b2ad646b36..0000000000 --- a/awx/lib/site-packages/celery/utils/objects.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.objects - ~~~~~~~~~~~~~~~~~~~~ - - Object related utilities including introspection, etc. - -""" -from __future__ import absolute_import - -__all__ = ['mro_lookup'] - - -def mro_lookup(cls, attr, stop=(), monkey_patched=[]): - """Return the first node by MRO order that defines an attribute. - - :keyword stop: A list of types that if reached will stop the search. - :keyword monkey_patched: Use one of the stop classes if the attr's - module origin is not in this list, this to detect monkey patched - attributes. - - :returns None: if the attribute was not found. - - """ - for node in cls.mro(): - if node in stop: - try: - attr = node.__dict__[attr] - module_origin = attr.__module__ - except (AttributeError, KeyError): - pass - else: - if module_origin not in monkey_patched: - return node - return - if attr in node.__dict__: - return node diff --git a/awx/lib/site-packages/celery/utils/serialization.py b/awx/lib/site-packages/celery/utils/serialization.py deleted file mode 100644 index d5509f1c20..0000000000 --- a/awx/lib/site-packages/celery/utils/serialization.py +++ /dev/null @@ -1,167 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.serialization - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Utilities for safely pickling exceptions. - -""" -from __future__ import absolute_import - -from inspect import getmro -from itertools import takewhile - -try: - import cPickle as pickle -except ImportError: - import pickle # noqa - -from .encoding import safe_repr - -__all__ = ['UnpickleableExceptionWrapper', 'subclass_exception', - 'find_pickleable_exception', 'create_exception_cls', - 'get_pickleable_exception', 'get_pickleable_etype', - 'get_pickled_exception'] - -#: List of base classes we probably don't want to reduce to. -try: - unwanted_base_classes = (StandardError, Exception, BaseException, object) -except NameError: # pragma: no cover - unwanted_base_classes = (Exception, BaseException, object) # py3k - - -def subclass_exception(name, parent, module): # noqa - return type(name, (parent, ), {'__module__': module}) - - -def find_pickleable_exception(exc, loads=pickle.loads, - dumps=pickle.dumps): - """With an exception instance, iterate over its super classes (by mro) - and find the first super exception that is pickleable. It does - not go below :exc:`Exception` (i.e. it skips :exc:`Exception`, - :class:`BaseException` and :class:`object`). If that happens - you should use :exc:`UnpickleableException` instead. - - :param exc: An exception instance. - - Will return the nearest pickleable parent exception class - (except :exc:`Exception` and parents), or if the exception is - pickleable it will return :const:`None`. - - :rtype :exc:`Exception`: - - """ - exc_args = getattr(exc, 'args', []) - for supercls in itermro(exc.__class__, unwanted_base_classes): - try: - superexc = supercls(*exc_args) - loads(dumps(superexc)) - except: - pass - else: - return superexc -find_nearest_pickleable_exception = find_pickleable_exception # XXX compat - - -def itermro(cls, stop): - return takewhile(lambda sup: sup not in stop, getmro(cls)) - - -def create_exception_cls(name, module, parent=None): - """Dynamically create an exception class.""" - if not parent: - parent = Exception - return subclass_exception(name, parent, module) - - -class UnpickleableExceptionWrapper(Exception): - """Wraps unpickleable exceptions. - - :param exc_module: see :attr:`exc_module`. - :param exc_cls_name: see :attr:`exc_cls_name`. - :param exc_args: see :attr:`exc_args` - - **Example** - - .. code-block:: python - - >>> def pickle_it(raising_function): - ... try: - ... raising_function() - ... except Exception as e: - ... exc = UnpickleableExceptionWrapper( - ... e.__class__.__module__, - ... e.__class__.__name__, - ... e.args, - ... ) - ... pickle.dumps(exc) # Works fine. - - """ - - #: The module of the original exception. - exc_module = None - - #: The name of the original exception class. - exc_cls_name = None - - #: The arguments for the original exception. - exc_args = None - - def __init__(self, exc_module, exc_cls_name, exc_args, text=None): - safe_exc_args = [] - for arg in exc_args: - try: - pickle.dumps(arg) - safe_exc_args.append(arg) - except Exception: - safe_exc_args.append(safe_repr(arg)) - self.exc_module = exc_module - self.exc_cls_name = exc_cls_name - self.exc_args = safe_exc_args - self.text = text - Exception.__init__(self, exc_module, exc_cls_name, safe_exc_args, text) - - def restore(self): - return create_exception_cls(self.exc_cls_name, - self.exc_module)(*self.exc_args) - - def __str__(self): - return self.text - - @classmethod - def from_exception(cls, exc): - return cls(exc.__class__.__module__, - exc.__class__.__name__, - getattr(exc, 'args', []), - safe_repr(exc)) - - -def get_pickleable_exception(exc): - """Make sure exception is pickleable.""" - try: - pickle.loads(pickle.dumps(exc)) - except Exception: - pass - else: - return exc - nearest = find_pickleable_exception(exc) - if nearest: - return nearest - return UnpickleableExceptionWrapper.from_exception(exc) - - -def get_pickleable_etype(cls, loads=pickle.loads, dumps=pickle.dumps): - try: - loads(dumps(cls)) - except: - return Exception - else: - return cls - - -def get_pickled_exception(exc): - """Get original exception from exception pickled using - :meth:`get_pickleable_exception`.""" - if isinstance(exc, UnpickleableExceptionWrapper): - return exc.restore() - return exc diff --git a/awx/lib/site-packages/celery/utils/sysinfo.py b/awx/lib/site-packages/celery/utils/sysinfo.py deleted file mode 100644 index 65073a6f9d..0000000000 --- a/awx/lib/site-packages/celery/utils/sysinfo.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import - -import os - -from math import ceil - -from kombu.utils import cached_property - -__all__ = ['load_average', 'df'] - - -if hasattr(os, 'getloadavg'): - - def load_average(): - return tuple(ceil(l * 1e2) / 1e2 for l in os.getloadavg()) - -else: # pragma: no cover - # Windows doesn't have getloadavg - def load_average(): # noqa - return (0.0, 0.0, 0.0) - - -class df(object): - - def __init__(self, path): - self.path = path - - @property - def total_blocks(self): - return self.stat.f_blocks * self.stat.f_frsize / 1024 - - @property - def available(self): - return self.stat.f_bavail * self.stat.f_frsize / 1024 - - @property - def capacity(self): - avail = self.stat.f_bavail - used = self.stat.f_blocks - self.stat.f_bfree - return int(ceil(used * 100.0 / (used + avail) + 0.5)) - - @cached_property - def stat(self): - return os.statvfs(os.path.abspath(self.path)) diff --git a/awx/lib/site-packages/celery/utils/term.py b/awx/lib/site-packages/celery/utils/term.py deleted file mode 100644 index f6f08d44cb..0000000000 --- a/awx/lib/site-packages/celery/utils/term.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.term - ~~~~~~~~~~~~~~~~~ - - Terminals and colors. - -""" -from __future__ import absolute_import, unicode_literals - -import platform - -from functools import reduce - -from kombu.utils.encoding import safe_str -from celery.five import string - -__all__ = ['colored'] - -BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) -OP_SEQ = '\033[%dm' -RESET_SEQ = '\033[0m' -COLOR_SEQ = '\033[1;%dm' -fg = lambda s: COLOR_SEQ % s - -IS_WINDOWS = platform.system() == 'Windows' - - -class colored(object): - """Terminal colored text. - - Example:: - >>> c = colored(enabled=True) - >>> print(str(c.red('the quick '), c.blue('brown ', c.bold('fox ')), - ... c.magenta(c.underline('jumps over')), - ... c.yellow(' the lazy '), - ... c.green('dog '))) - - """ - - def __init__(self, *s, **kwargs): - self.s = s - self.enabled = not IS_WINDOWS and kwargs.get('enabled', True) - self.op = kwargs.get('op', '') - self.names = {'black': self.black, - 'red': self.red, - 'green': self.green, - 'yellow': self.yellow, - 'blue': self.blue, - 'magenta': self.magenta, - 'cyan': self.cyan, - 'white': self.white} - - def _add(self, a, b): - return string(a) + string(b) - - def _fold_no_color(self, a, b): - try: - A = a.no_color() - except AttributeError: - A = string(a) - try: - B = b.no_color() - except AttributeError: - B = string(b) - - return ''.join((string(A), string(B))) - - def no_color(self): - if self.s: - return string(reduce(self._fold_no_color, self.s)) - return '' - - def embed(self): - prefix = '' - if self.enabled: - prefix = self.op - return ''.join((string(prefix), string(reduce(self._add, self.s)))) - - def __unicode__(self): - suffix = '' - if self.enabled: - suffix = RESET_SEQ - return string(''.join((self.embed(), string(suffix)))) - - def __str__(self): - return safe_str(self.__unicode__()) - - def node(self, s, op): - return self.__class__(enabled=self.enabled, op=op, *s) - - def black(self, *s): - return self.node(s, fg(30 + BLACK)) - - def red(self, *s): - return self.node(s, fg(30 + RED)) - - def green(self, *s): - return self.node(s, fg(30 + GREEN)) - - def yellow(self, *s): - return self.node(s, fg(30 + YELLOW)) - - def blue(self, *s): - return self.node(s, fg(30 + BLUE)) - - def magenta(self, *s): - return self.node(s, fg(30 + MAGENTA)) - - def cyan(self, *s): - return self.node(s, fg(30 + CYAN)) - - def white(self, *s): - return self.node(s, fg(30 + WHITE)) - - def __repr__(self): - return repr(self.no_color()) - - def bold(self, *s): - return self.node(s, OP_SEQ % 1) - - def underline(self, *s): - return self.node(s, OP_SEQ % 4) - - def blink(self, *s): - return self.node(s, OP_SEQ % 5) - - def reverse(self, *s): - return self.node(s, OP_SEQ % 7) - - def bright(self, *s): - return self.node(s, OP_SEQ % 8) - - def ired(self, *s): - return self.node(s, fg(40 + RED)) - - def igreen(self, *s): - return self.node(s, fg(40 + GREEN)) - - def iyellow(self, *s): - return self.node(s, fg(40 + YELLOW)) - - def iblue(self, *s): - return self.node(s, fg(40 + BLUE)) - - def imagenta(self, *s): - return self.node(s, fg(40 + MAGENTA)) - - def icyan(self, *s): - return self.node(s, fg(40 + CYAN)) - - def iwhite(self, *s): - return self.node(s, fg(40 + WHITE)) - - def reset(self, *s): - return self.node(s or [''], RESET_SEQ) - - def __add__(self, other): - return string(self) + string(other) diff --git a/awx/lib/site-packages/celery/utils/text.py b/awx/lib/site-packages/celery/utils/text.py deleted file mode 100644 index ffd2d72fa1..0000000000 --- a/awx/lib/site-packages/celery/utils/text.py +++ /dev/null @@ -1,86 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.text - ~~~~~~~~~~~~~~~~~ - - Text formatting utilities - -""" -from __future__ import absolute_import - -from textwrap import fill - -from pprint import pformat - -__all__ = ['dedent_initial', 'dedent', 'fill_paragraphs', 'join', - 'ensure_2lines', 'abbr', 'abbrtask', 'indent', 'truncate', - 'pluralize', 'pretty'] - - -def dedent_initial(s, n=4): - return s[n:] if s[:n] == ' ' * n else s - - -def dedent(s, n=4, sep='\n'): - return sep.join(dedent_initial(l) for l in s.splitlines()) - - -def fill_paragraphs(s, width, sep='\n'): - return sep.join(fill(p, width) for p in s.split(sep)) - - -def join(l, sep='\n'): - return sep.join(v for v in l if v) - - -def ensure_2lines(s, sep='\n'): - if len(s.splitlines()) <= 2: - return s + sep - return s - - -def abbr(S, max, ellipsis='...'): - if S is None: - return '???' - if len(S) > max: - return ellipsis and (S[:max - len(ellipsis)] + ellipsis) or S[:max] - return S - - -def abbrtask(S, max): - if S is None: - return '???' - if len(S) > max: - module, _, cls = S.rpartition('.') - module = abbr(module, max - len(cls) - 3, False) - return module + '[.]' + cls - return S - - -def indent(t, indent=0, sep='\n'): - """Indent text.""" - return sep.join(' ' * indent + p for p in t.split(sep)) - - -def truncate(text, maxlen=128, suffix='...'): - """Truncates text to a maximum number of characters.""" - if len(text) >= maxlen: - return text[:maxlen].rsplit(' ', 1)[0] + suffix - return text - - -def pluralize(n, text, suffix='s'): - if n > 1: - return text + suffix - return text - - -def pretty(value, width=80, nl_width=80, sep='\n', **kw): - if isinstance(value, dict): - return '{{{0} {1}'.format(sep, pformat(value, 4, nl_width)[1:]) - elif isinstance(value, tuple): - return '{0}{1}{2}'.format( - sep, ' ' * 4, pformat(value, width=nl_width, **kw), - ) - else: - return pformat(value, width=width, **kw) diff --git a/awx/lib/site-packages/celery/utils/threads.py b/awx/lib/site-packages/celery/utils/threads.py deleted file mode 100644 index 5d42373295..0000000000 --- a/awx/lib/site-packages/celery/utils/threads.py +++ /dev/null @@ -1,329 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.threads - ~~~~~~~~~~~~~~~~~~~~ - - Threading utilities. - -""" -from __future__ import absolute_import, print_function - -import os -import socket -import sys -import threading -import traceback - -from contextlib import contextmanager - -from celery.local import Proxy -from celery.five import THREAD_TIMEOUT_MAX, items - -__all__ = ['bgThread', 'Local', 'LocalStack', 'LocalManager', - 'get_ident', 'default_socket_timeout'] - -USE_FAST_LOCALS = os.environ.get('USE_FAST_LOCALS') -PY3 = sys.version_info[0] == 3 - - -@contextmanager -def default_socket_timeout(timeout): - prev = socket.getdefaulttimeout() - socket.setdefaulttimeout(timeout) - yield - socket.setdefaulttimeout(prev) - - -class bgThread(threading.Thread): - - def __init__(self, name=None, **kwargs): - super(bgThread, self).__init__() - self._is_shutdown = threading.Event() - self._is_stopped = threading.Event() - self.daemon = True - self.name = name or self.__class__.__name__ - - def body(self): - raise NotImplementedError('subclass responsibility') - - def on_crash(self, msg, *fmt, **kwargs): - print(msg.format(*fmt), file=sys.stderr) - exc_info = sys.exc_info() - try: - traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], - None, sys.stderr) - finally: - del(exc_info) - - def run(self): - body = self.body - shutdown_set = self._is_shutdown.is_set - try: - while not shutdown_set(): - try: - body() - except Exception as exc: - try: - self.on_crash('{0!r} crashed: {1!r}', self.name, exc) - self._set_stopped() - finally: - os._exit(1) # exiting by normal means won't work - finally: - self._set_stopped() - - def _set_stopped(self): - try: - self._is_stopped.set() - except TypeError: # pragma: no cover - # we lost the race at interpreter shutdown, - # so gc collected built-in modules. - pass - - def stop(self): - """Graceful shutdown.""" - self._is_shutdown.set() - self._is_stopped.wait() - if self.is_alive(): - self.join(THREAD_TIMEOUT_MAX) - -try: - from greenlet import getcurrent as get_ident -except ImportError: # pragma: no cover - try: - from _thread import get_ident # noqa - except ImportError: - try: - from thread import get_ident # noqa - except ImportError: # pragma: no cover - try: - from _dummy_thread import get_ident # noqa - except ImportError: - from dummy_thread import get_ident # noqa - - -def release_local(local): - """Releases the contents of the local for the current context. - This makes it possible to use locals without a manager. - - Example:: - - >>> loc = Local() - >>> loc.foo = 42 - >>> release_local(loc) - >>> hasattr(loc, 'foo') - False - - With this function one can release :class:`Local` objects as well - as :class:`StackLocal` objects. However it is not possible to - release data held by proxies that way, one always has to retain - a reference to the underlying local object in order to be able - to release it. - - .. versionadded:: 0.6.1 - """ - local.__release_local__() - - -class Local(object): - __slots__ = ('__storage__', '__ident_func__') - - def __init__(self): - object.__setattr__(self, '__storage__', {}) - object.__setattr__(self, '__ident_func__', get_ident) - - def __iter__(self): - return iter(items(self.__storage__)) - - def __call__(self, proxy): - """Create a proxy for a name.""" - return Proxy(self, proxy) - - def __release_local__(self): - self.__storage__.pop(self.__ident_func__(), None) - - def __getattr__(self, name): - try: - return self.__storage__[self.__ident_func__()][name] - except KeyError: - raise AttributeError(name) - - def __setattr__(self, name, value): - ident = self.__ident_func__() - storage = self.__storage__ - try: - storage[ident][name] = value - except KeyError: - storage[ident] = {name: value} - - def __delattr__(self, name): - try: - del self.__storage__[self.__ident_func__()][name] - except KeyError: - raise AttributeError(name) - - -class _LocalStack(object): - """This class works similar to a :class:`Local` but keeps a stack - of objects instead. This is best explained with an example:: - - >>> ls = LocalStack() - >>> ls.push(42) - >>> ls.top - 42 - >>> ls.push(23) - >>> ls.top - 23 - >>> ls.pop() - 23 - >>> ls.top - 42 - - They can be force released by using a :class:`LocalManager` or with - the :func:`release_local` function but the correct way is to pop the - item from the stack after using. When the stack is empty it will - no longer be bound to the current context (and as such released). - - By calling the stack without arguments it will return a proxy that - resolves to the topmost item on the stack. - - """ - - def __init__(self): - self._local = Local() - - def __release_local__(self): - self._local.__release_local__() - - def _get__ident_func__(self): - return self._local.__ident_func__ - - def _set__ident_func__(self, value): - object.__setattr__(self._local, '__ident_func__', value) - __ident_func__ = property(_get__ident_func__, _set__ident_func__) - del _get__ident_func__, _set__ident_func__ - - def __call__(self): - def _lookup(): - rv = self.top - if rv is None: - raise RuntimeError('object unbound') - return rv - return Proxy(_lookup) - - def push(self, obj): - """Pushes a new item to the stack""" - rv = getattr(self._local, 'stack', None) - if rv is None: - self._local.stack = rv = [] - rv.append(obj) - return rv - - def pop(self): - """Remove the topmost item from the stack, will return the - old value or `None` if the stack was already empty. - """ - stack = getattr(self._local, 'stack', None) - if stack is None: - return None - elif len(stack) == 1: - release_local(self._local) - return stack[-1] - else: - return stack.pop() - - def __len__(self): - stack = getattr(self._local, 'stack', None) - return len(stack) if stack else 0 - - @property - def stack(self): - """get_current_worker_task uses this to find - the original task that was executed by the worker.""" - stack = getattr(self._local, 'stack', None) - if stack is not None: - return stack - return [] - - @property - def top(self): - """The topmost item on the stack. If the stack is empty, - `None` is returned. - """ - try: - return self._local.stack[-1] - except (AttributeError, IndexError): - return None - - -class LocalManager(object): - """Local objects cannot manage themselves. For that you need a local - manager. You can pass a local manager multiple locals or add them - later by appending them to `manager.locals`. Everytime the manager - cleans up it, will clean up all the data left in the locals for this - context. - - The `ident_func` parameter can be added to override the default ident - function for the wrapped locals. - - """ - - def __init__(self, locals=None, ident_func=None): - if locals is None: - self.locals = [] - elif isinstance(locals, Local): - self.locals = [locals] - else: - self.locals = list(locals) - if ident_func is not None: - self.ident_func = ident_func - for local in self.locals: - object.__setattr__(local, '__ident_func__', ident_func) - else: - self.ident_func = get_ident - - def get_ident(self): - """Return the context identifier the local objects use internally - for this context. You cannot override this method to change the - behavior but use it to link other context local objects (such as - SQLAlchemy's scoped sessions) to the Werkzeug locals.""" - return self.ident_func() - - def cleanup(self): - """Manually clean up the data in the locals for this context. - - Call this at the end of the request or use `make_middleware()`. - - """ - for local in self.locals: - release_local(local) - - def __repr__(self): - return '<{0} storages: {1}>'.format( - self.__class__.__name__, len(self.locals)) - - -class _FastLocalStack(threading.local): - - def __init__(self): - self.stack = [] - self.push = self.stack.append - self.pop = self.stack.pop - - @property - def top(self): - try: - return self.stack[-1] - except (AttributeError, IndexError): - return None - - def __len__(self): - return len(self.stack) - -if USE_FAST_LOCALS: # pragma: no cover - LocalStack = _FastLocalStack -else: - # - See #706 - # since each thread has its own greenlet we can just use those as - # identifiers for the context. If greenlets are not available we - # fall back to the current thread ident. - LocalStack = _LocalStack # noqa diff --git a/awx/lib/site-packages/celery/utils/timer2.py b/awx/lib/site-packages/celery/utils/timer2.py deleted file mode 100644 index d462c65748..0000000000 --- a/awx/lib/site-packages/celery/utils/timer2.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -""" - timer2 - ~~~~~~ - - Scheduler for Python functions. - -""" -from __future__ import absolute_import - -import os -import sys -import threading - -from itertools import count -from time import sleep - -from celery.five import THREAD_TIMEOUT_MAX -from kombu.async.timer import Entry, Timer as Schedule, to_timestamp, logger - -TIMER_DEBUG = os.environ.get('TIMER_DEBUG') - -__all__ = ['Entry', 'Schedule', 'Timer', 'to_timestamp'] - - -class Timer(threading.Thread): - Entry = Entry - Schedule = Schedule - - running = False - on_tick = None - _timer_count = count(1) - - if TIMER_DEBUG: # pragma: no cover - def start(self, *args, **kwargs): - import traceback - print('- Timer starting') - traceback.print_stack() - super(Timer, self).start(*args, **kwargs) - - def __init__(self, schedule=None, on_error=None, on_tick=None, - on_start=None, max_interval=None, **kwargs): - self.schedule = schedule or self.Schedule(on_error=on_error, - max_interval=max_interval) - self.on_start = on_start - self.on_tick = on_tick or self.on_tick - threading.Thread.__init__(self) - self._is_shutdown = threading.Event() - self._is_stopped = threading.Event() - self.mutex = threading.Lock() - self.not_empty = threading.Condition(self.mutex) - self.daemon = True - self.name = 'Timer-{0}'.format(next(self._timer_count)) - - def _next_entry(self): - with self.not_empty: - delay, entry = next(self.scheduler) - if entry is None: - if delay is None: - self.not_empty.wait(1.0) - return delay - return self.schedule.apply_entry(entry) - __next__ = next = _next_entry # for 2to3 - - def run(self): - try: - self.running = True - self.scheduler = iter(self.schedule) - - while not self._is_shutdown.isSet(): - delay = self._next_entry() - if delay: - if self.on_tick: - self.on_tick(delay) - if sleep is None: # pragma: no cover - break - sleep(delay) - try: - self._is_stopped.set() - except TypeError: # pragma: no cover - # we lost the race at interpreter shutdown, - # so gc collected built-in modules. - pass - except Exception as exc: - logger.error('Thread Timer crashed: %r', exc, exc_info=True) - os._exit(1) - - def stop(self): - if self.running: - self._is_shutdown.set() - self._is_stopped.wait() - self.join(THREAD_TIMEOUT_MAX) - self.running = False - - def ensure_started(self): - if not self.running and not self.isAlive(): - if self.on_start: - self.on_start(self) - self.start() - - def _do_enter(self, meth, *args, **kwargs): - self.ensure_started() - with self.mutex: - entry = getattr(self.schedule, meth)(*args, **kwargs) - self.not_empty.notify() - return entry - - def enter(self, entry, eta, priority=None): - return self._do_enter('enter_at', entry, eta, priority=priority) - - def call_at(self, *args, **kwargs): - return self._do_enter('call_at', *args, **kwargs) - - def enter_after(self, *args, **kwargs): - return self._do_enter('enter_after', *args, **kwargs) - - def call_after(self, *args, **kwargs): - return self._do_enter('call_after', *args, **kwargs) - - def call_repeatedly(self, *args, **kwargs): - return self._do_enter('call_repeatedly', *args, **kwargs) - - def exit_after(self, secs, priority=10): - self.call_after(secs, sys.exit, priority) - - def cancel(self, tref): - tref.cancel() - - def clear(self): - self.schedule.clear() - - def empty(self): - return not len(self) - - def __len__(self): - return len(self.schedule) - - def __bool__(self): - return True - __nonzero__ = __bool__ - - @property - def queue(self): - return self.schedule.queue diff --git a/awx/lib/site-packages/celery/utils/timeutils.py b/awx/lib/site-packages/celery/utils/timeutils.py deleted file mode 100644 index 5b75b83a89..0000000000 --- a/awx/lib/site-packages/celery/utils/timeutils.py +++ /dev/null @@ -1,348 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.utils.timeutils - ~~~~~~~~~~~~~~~~~~~~~~ - - This module contains various utilities related to dates and times. - -""" -from __future__ import absolute_import - -import numbers -import os -import time as _time - -from calendar import monthrange -from datetime import date, datetime, timedelta, tzinfo - -from kombu.utils import cached_property, reprcall -from kombu.utils.compat import timedelta_seconds - -from pytz import timezone as _timezone, AmbiguousTimeError - -from celery.five import string_t - -from .functional import dictfilter -from .iso8601 import parse_iso8601 -from .text import pluralize - -__all__ = ['LocalTimezone', 'timezone', 'maybe_timedelta', 'timedelta_seconds', - 'delta_resolution', 'remaining', 'rate', 'weekday', - 'humanize_seconds', 'maybe_iso8601', 'is_naive', 'make_aware', - 'localize', 'to_utc', 'maybe_make_aware', 'ffwd', 'utcoffset', - 'adjust_timestamp', 'maybe_s_to_ms'] - -C_REMDEBUG = os.environ.get('C_REMDEBUG', False) - -DAYNAMES = 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' -WEEKDAYS = dict(zip(DAYNAMES, range(7))) - -RATE_MODIFIER_MAP = {'s': lambda n: n, - 'm': lambda n: n / 60.0, - 'h': lambda n: n / 60.0 / 60.0} - -TIME_UNITS = (('day', 60 * 60 * 24.0, lambda n: format(n, '.2f')), - ('hour', 60 * 60.0, lambda n: format(n, '.2f')), - ('minute', 60.0, lambda n: format(n, '.2f')), - ('second', 1.0, lambda n: format(n, '.2f'))) - -ZERO = timedelta(0) - -_local_timezone = None - -__timezone__ = -_time.timezone -__altzone__ = -_time.altzone - - -class LocalTimezone(tzinfo): - """Local time implementation taken from Python's docs. - - Used only when UTC is not enabled. - """ - - def __init__(self): - # This code is moved in __init__ to execute it as late as possible - # See get_default_timezone(). - self.STDOFFSET = timedelta(seconds=-_time.timezone) - if _time.daylight: - self.DSTOFFSET = timedelta(seconds=-_time.altzone) - else: - self.DSTOFFSET = self.STDOFFSET - self.DSTDIFF = self.DSTOFFSET - self.STDOFFSET - tzinfo.__init__(self) - - def __repr__(self): - return '<LocalTimezone>' - - def utcoffset(self, dt): - if self._isdst(dt): - return self.DSTOFFSET - else: - return self.STDOFFSET - - def dst(self, dt): - if self._isdst(dt): - return self.DSTDIFF - else: - return ZERO - - def tzname(self, dt): - return _time.tzname[self._isdst(dt)] - - def _isdst(self, dt): - tt = (dt.year, dt.month, dt.day, - dt.hour, dt.minute, dt.second, - dt.weekday(), 0, 0) - stamp = _time.mktime(tt) - tt = _time.localtime(stamp) - return tt.tm_isdst > 0 - - -class _Zone(object): - - def tz_or_local(self, tzinfo=None): - if tzinfo is None: - return self.local - return self.get_timezone(tzinfo) - - def to_local(self, dt, local=None, orig=None): - if is_naive(dt): - dt = make_aware(dt, orig or self.utc) - return localize(dt, self.tz_or_local(local)) - - def to_system(self, dt): - return localize(dt, self.local) - - def to_local_fallback(self, dt): - if is_naive(dt): - return make_aware(dt, self.local) - return localize(dt, self.local) - - def get_timezone(self, zone): - if isinstance(zone, string_t): - return _timezone(zone) - return zone - - @cached_property - def local(self): - return LocalTimezone() - - @cached_property - def utc(self): - return self.get_timezone('UTC') -timezone = _Zone() - - -def maybe_timedelta(delta): - """Coerces integer to timedelta if `delta` is an integer.""" - if isinstance(delta, numbers.Real): - return timedelta(seconds=delta) - return delta - - -def delta_resolution(dt, delta): - """Round a datetime to the resolution of a timedelta. - - If the timedelta is in days, the datetime will be rounded - to the nearest days, if the timedelta is in hours the datetime - will be rounded to the nearest hour, and so on until seconds - which will just return the original datetime. - - """ - delta = timedelta_seconds(delta) - - resolutions = ((3, lambda x: x / 86400), - (4, lambda x: x / 3600), - (5, lambda x: x / 60)) - - args = dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second - for res, predicate in resolutions: - if predicate(delta) >= 1.0: - return datetime(*args[:res], tzinfo=dt.tzinfo) - return dt - - -def remaining(start, ends_in, now=None, relative=False): - """Calculate the remaining time for a start date and a timedelta. - - e.g. "how many seconds left for 30 seconds after start?" - - :param start: Start :class:`~datetime.datetime`. - :param ends_in: The end delta as a :class:`~datetime.timedelta`. - :keyword relative: If enabled the end time will be - calculated using :func:`delta_resolution` (i.e. rounded to the - resolution of `ends_in`). - :keyword now: Function returning the current time and date, - defaults to :func:`datetime.utcnow`. - - """ - now = now or datetime.utcnow() - end_date = start + ends_in - if relative: - end_date = delta_resolution(end_date, ends_in) - ret = end_date - now - if C_REMDEBUG: # pragma: no cover - print('rem: NOW:%r START:%r ENDS_IN:%r END_DATE:%s REM:%s' % ( - now, start, ends_in, end_date, ret)) - return ret - - -def rate(rate): - """Parse rate strings, such as `"100/m"`, `"2/h"` or `"0.5/s"` - and convert them to seconds.""" - if rate: - if isinstance(rate, string_t): - ops, _, modifier = rate.partition('/') - return RATE_MODIFIER_MAP[modifier or 's'](float(ops)) or 0 - return rate or 0 - return 0 - - -def weekday(name): - """Return the position of a weekday (0 - 7, where 0 is Sunday). - - Example:: - - >>> weekday('sunday'), weekday('sun'), weekday('mon') - (0, 0, 1) - - """ - abbreviation = name[0:3].lower() - try: - return WEEKDAYS[abbreviation] - except KeyError: - # Show original day name in exception, instead of abbr. - raise KeyError(name) - - -def humanize_seconds(secs, prefix='', sep='', now='now'): - """Show seconds in human form, e.g. 60 is "1 minute", 7200 is "2 - hours". - - :keyword prefix: Can be used to add a preposition to the output, - e.g. 'in' will give 'in 1 second', but add nothing to 'now'. - - """ - secs = float(secs) - for unit, divider, formatter in TIME_UNITS: - if secs >= divider: - w = secs / divider - return '{0}{1}{2} {3}'.format(prefix, sep, formatter(w), - pluralize(w, unit)) - return now - - -def maybe_iso8601(dt): - """`Either datetime | str -> datetime or None -> None`""" - if not dt: - return - if isinstance(dt, datetime): - return dt - return parse_iso8601(dt) - - -def is_naive(dt): - """Return :const:`True` if the datetime is naive - (does not have timezone information).""" - return dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None - - -def make_aware(dt, tz): - """Sets the timezone for a datetime object.""" - try: - _localize = tz.localize - except AttributeError: - return dt.replace(tzinfo=tz) - else: - # works on pytz timezones - try: - return _localize(dt, is_dst=None) - except AmbiguousTimeError: - return min(_localize(dt, is_dst=True), - _localize(dt, is_dst=False)) - - -def localize(dt, tz): - """Convert aware datetime to another timezone.""" - dt = dt.astimezone(tz) - try: - _normalize = tz.normalize - except AttributeError: # non-pytz tz - return dt - else: - try: - return _normalize(dt, is_dst=None) - except TypeError: - return _normalize(dt) - except AmbiguousTimeError: - return min(_normalize(dt, is_dst=True), - _normalize(dt, is_dst=False)) - - -def to_utc(dt): - """Converts naive datetime to UTC""" - return make_aware(dt, timezone.utc) - - -def maybe_make_aware(dt, tz=None): - if is_naive(dt): - dt = to_utc(dt) - return localize( - dt, timezone.utc if tz is None else timezone.tz_or_local(tz), - ) - - -class ffwd(object): - """Version of relativedelta that only supports addition.""" - - def __init__(self, year=None, month=None, weeks=0, weekday=None, day=None, - hour=None, minute=None, second=None, microsecond=None, - **kwargs): - self.year = year - self.month = month - self.weeks = weeks - self.weekday = weekday - self.day = day - self.hour = hour - self.minute = minute - self.second = second - self.microsecond = microsecond - self.days = weeks * 7 - self._has_time = self.hour is not None or self.minute is not None - - def __repr__(self): - return reprcall('ffwd', (), self._fields(weeks=self.weeks, - weekday=self.weekday)) - - def __radd__(self, other): - if not isinstance(other, date): - return NotImplemented - year = self.year or other.year - month = self.month or other.month - day = min(monthrange(year, month)[1], self.day or other.day) - ret = other.replace(**dict(dictfilter(self._fields()), - year=year, month=month, day=day)) - if self.weekday is not None: - ret += timedelta(days=(7 - ret.weekday() + self.weekday) % 7) - return ret + timedelta(days=self.days) - - def _fields(self, **extra): - return dictfilter({ - 'year': self.year, 'month': self.month, 'day': self.day, - 'hour': self.hour, 'minute': self.minute, - 'second': self.second, 'microsecond': self.microsecond, - }, **extra) - - -def utcoffset(): - if _time.daylight: - return __altzone__ // 3600 - return __timezone__ // 3600 - - -def adjust_timestamp(ts, offset, here=utcoffset): - return ts - (offset - here()) * 3600 - - -def maybe_s_to_ms(v): - return int(float(v) * 1000.0) if v is not None else v diff --git a/awx/lib/site-packages/celery/worker/__init__.py b/awx/lib/site-packages/celery/worker/__init__.py deleted file mode 100644 index 217902d2e1..0000000000 --- a/awx/lib/site-packages/celery/worker/__init__.py +++ /dev/null @@ -1,388 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker - ~~~~~~~~~~~~~ - - :class:`WorkController` can be used to instantiate in-process workers. - - The worker consists of several components, all managed by bootsteps - (mod:`celery.bootsteps`). - -""" -from __future__ import absolute_import - -import os -import sys -import traceback -try: - import resource -except ImportError: # pragma: no cover - resource = None # noqa - -from billiard import cpu_count -from billiard.util import Finalize -from kombu.syn import detect_environment - -from celery import bootsteps -from celery.bootsteps import RUN, TERMINATE -from celery import concurrency as _concurrency -from celery import platforms -from celery import signals -from celery.exceptions import ( - ImproperlyConfigured, WorkerTerminate, TaskRevokedError, -) -from celery.five import string_t, values -from celery.utils import default_nodename, worker_direct -from celery.utils.imports import reload_from_cwd -from celery.utils.log import mlevel, worker_logger as logger -from celery.utils.threads import default_socket_timeout - -from . import state - -__all__ = ['WorkController', 'default_nodename'] - -#: Default socket timeout at shutdown. -SHUTDOWN_SOCKET_TIMEOUT = 5.0 - -SELECT_UNKNOWN_QUEUE = """\ -Trying to select queue subset of {0!r}, but queue {1} is not -defined in the CELERY_QUEUES setting. - -If you want to automatically declare unknown queues you can -enable the CELERY_CREATE_MISSING_QUEUES setting. -""" - -DESELECT_UNKNOWN_QUEUE = """\ -Trying to deselect queue subset of {0!r}, but queue {1} is not -defined in the CELERY_QUEUES setting. -""" - - -def str_to_list(s): - if isinstance(s, string_t): - return s.split(',') - return s - - -class WorkController(object): - """Unmanaged worker instance.""" - app = None - - pidlock = None - blueprint = None - pool = None - semaphore = None - - class Blueprint(bootsteps.Blueprint): - """Worker bootstep blueprint.""" - name = 'Worker' - default_steps = set([ - 'celery.worker.components:Hub', - 'celery.worker.components:Queues', - 'celery.worker.components:Pool', - 'celery.worker.components:Beat', - 'celery.worker.components:Timer', - 'celery.worker.components:StateDB', - 'celery.worker.components:Consumer', - 'celery.worker.autoscale:WorkerComponent', - 'celery.worker.autoreload:WorkerComponent', - - ]) - - def __init__(self, app=None, hostname=None, **kwargs): - self.app = app or self.app - self.hostname = default_nodename(hostname) - self.app.loader.init_worker() - self.on_before_init(**kwargs) - self.setup_defaults(**kwargs) - self.on_after_init(**kwargs) - - self.setup_instance(**self.prepare_args(**kwargs)) - self._finalize = [ - Finalize(self, self._send_worker_shutdown, exitpriority=10), - ] - - def setup_instance(self, queues=None, ready_callback=None, pidfile=None, - include=None, use_eventloop=None, exclude_queues=None, - **kwargs): - self.pidfile = pidfile - self.setup_queues(queues, exclude_queues) - self.setup_includes(str_to_list(include)) - - # Set default concurrency - if not self.concurrency: - try: - self.concurrency = cpu_count() - except NotImplementedError: - self.concurrency = 2 - - # Options - self.loglevel = mlevel(self.loglevel) - self.ready_callback = ready_callback or self.on_consumer_ready - - # this connection is not established, only used for params - self._conninfo = self.app.connection() - self.use_eventloop = ( - self.should_use_eventloop() if use_eventloop is None - else use_eventloop - ) - self.options = kwargs - - signals.worker_init.send(sender=self) - - # Initialize bootsteps - self.pool_cls = _concurrency.get_implementation(self.pool_cls) - self.steps = [] - self.on_init_blueprint() - self.blueprint = self.Blueprint(app=self.app, - on_start=self.on_start, - on_close=self.on_close, - on_stopped=self.on_stopped) - self.blueprint.apply(self, **kwargs) - - def on_init_blueprint(self): - pass - - def on_before_init(self, **kwargs): - pass - - def on_after_init(self, **kwargs): - pass - - def on_start(self): - if self.pidfile: - self.pidlock = platforms.create_pidlock(self.pidfile) - - def on_consumer_ready(self, consumer): - pass - - def on_close(self): - self.app.loader.shutdown_worker() - - def on_stopped(self): - self.timer.stop() - self.consumer.shutdown() - - if self.pidlock: - self.pidlock.release() - - def setup_queues(self, include, exclude=None): - include = str_to_list(include) - exclude = str_to_list(exclude) - try: - self.app.amqp.queues.select(include) - except KeyError as exc: - raise ImproperlyConfigured( - SELECT_UNKNOWN_QUEUE.format(include, exc)) - try: - self.app.amqp.queues.deselect(exclude) - except KeyError as exc: - raise ImproperlyConfigured( - DESELECT_UNKNOWN_QUEUE.format(exclude, exc)) - if self.app.conf.CELERY_WORKER_DIRECT: - self.app.amqp.queues.select_add(worker_direct(self.hostname)) - - def setup_includes(self, includes): - # Update celery_include to have all known task modules, so that we - # ensure all task modules are imported in case an execv happens. - prev = tuple(self.app.conf.CELERY_INCLUDE) - if includes: - prev += tuple(includes) - [self.app.loader.import_task_module(m) for m in includes] - self.include = includes - task_modules = set(task.__class__.__module__ - for task in values(self.app.tasks)) - self.app.conf.CELERY_INCLUDE = tuple(set(prev) | task_modules) - - def prepare_args(self, **kwargs): - return kwargs - - def _send_worker_shutdown(self): - signals.worker_shutdown.send(sender=self) - - def start(self): - """Starts the workers main loop.""" - try: - self.blueprint.start(self) - except WorkerTerminate: - self.terminate() - except Exception as exc: - logger.error('Unrecoverable error: %r', exc, exc_info=True) - self.stop() - except (KeyboardInterrupt, SystemExit): - self.stop() - - def register_with_event_loop(self, hub): - self.blueprint.send_all( - self, 'register_with_event_loop', args=(hub, ), - description='hub.register', - ) - - def _process_task_sem(self, req): - return self._quick_acquire(self._process_task, req) - - def _process_task(self, req): - """Process task by sending it to the pool of workers.""" - try: - req.execute_using_pool(self.pool) - except TaskRevokedError: - try: - self._quick_release() # Issue 877 - except AttributeError: - pass - except Exception as exc: - logger.critical('Internal error: %r\n%s', - exc, traceback.format_exc(), exc_info=True) - - def signal_consumer_close(self): - try: - self.consumer.close() - except AttributeError: - pass - - def should_use_eventloop(self): - return (detect_environment() == 'default' and - self._conninfo.is_evented and not self.app.IS_WINDOWS) - - def stop(self, in_sighandler=False): - """Graceful shutdown of the worker server.""" - if self.blueprint.state == RUN: - self.signal_consumer_close() - if not in_sighandler or self.pool.signal_safe: - self._shutdown(warm=True) - - def terminate(self, in_sighandler=False): - """Not so graceful shutdown of the worker server.""" - if self.blueprint.state != TERMINATE: - self.signal_consumer_close() - if not in_sighandler or self.pool.signal_safe: - self._shutdown(warm=False) - - def _shutdown(self, warm=True): - # if blueprint does not exist it means that we had an - # error before the bootsteps could be initialized. - if self.blueprint is not None: - with default_socket_timeout(SHUTDOWN_SOCKET_TIMEOUT): # Issue 975 - self.blueprint.stop(self, terminate=not warm) - self.blueprint.join() - - def reload(self, modules=None, reload=False, reloader=None): - modules = self.app.loader.task_modules if modules is None else modules - imp = self.app.loader.import_from_cwd - - for module in set(modules or ()): - if module not in sys.modules: - logger.debug('importing module %s', module) - imp(module) - elif reload: - logger.debug('reloading module %s', module) - reload_from_cwd(sys.modules[module], reloader) - - if self.consumer: - self.consumer.update_strategies() - self.consumer.reset_rate_limits() - self.pool.restart() - - def info(self): - return {'total': self.state.total_count, - 'pid': os.getpid(), - 'clock': str(self.app.clock)} - - def rusage(self): - if resource is None: - raise NotImplementedError('rusage not supported by this platform') - s = resource.getrusage(resource.RUSAGE_SELF) - return { - 'utime': s.ru_utime, - 'stime': s.ru_stime, - 'maxrss': s.ru_maxrss, - 'ixrss': s.ru_ixrss, - 'idrss': s.ru_idrss, - 'isrss': s.ru_isrss, - 'minflt': s.ru_minflt, - 'majflt': s.ru_majflt, - 'nswap': s.ru_nswap, - 'inblock': s.ru_inblock, - 'oublock': s.ru_oublock, - 'msgsnd': s.ru_msgsnd, - 'msgrcv': s.ru_msgrcv, - 'nsignals': s.ru_nsignals, - 'nvcsw': s.ru_nvcsw, - 'nivcsw': s.ru_nivcsw, - } - - def stats(self): - info = self.info() - info.update(self.blueprint.info(self)) - info.update(self.consumer.blueprint.info(self.consumer)) - try: - info['rusage'] = self.rusage() - except NotImplementedError: - info['rusage'] = 'N/A' - return info - - def __repr__(self): - return '<Worker: {self.hostname} ({state})>'.format( - self=self, state=self.blueprint.human_state(), - ) - - def __str__(self): - return self.hostname - - @property - def state(self): - return state - - def setup_defaults(self, concurrency=None, loglevel=None, logfile=None, - send_events=None, pool_cls=None, consumer_cls=None, - timer_cls=None, timer_precision=None, - autoscaler_cls=None, autoreloader_cls=None, - pool_putlocks=None, pool_restarts=None, - force_execv=None, state_db=None, - schedule_filename=None, scheduler_cls=None, - task_time_limit=None, task_soft_time_limit=None, - max_tasks_per_child=None, prefetch_multiplier=None, - disable_rate_limits=None, worker_lost_wait=None, **_kw): - self.concurrency = self._getopt('concurrency', concurrency) - self.loglevel = self._getopt('log_level', loglevel) - self.logfile = self._getopt('log_file', logfile) - self.send_events = self._getopt('send_events', send_events) - self.pool_cls = self._getopt('pool', pool_cls) - self.consumer_cls = self._getopt('consumer', consumer_cls) - self.timer_cls = self._getopt('timer', timer_cls) - self.timer_precision = self._getopt('timer_precision', timer_precision) - self.autoscaler_cls = self._getopt('autoscaler', autoscaler_cls) - self.autoreloader_cls = self._getopt('autoreloader', autoreloader_cls) - self.pool_putlocks = self._getopt('pool_putlocks', pool_putlocks) - self.pool_restarts = self._getopt('pool_restarts', pool_restarts) - self.force_execv = self._getopt('force_execv', force_execv) - self.state_db = self._getopt('state_db', state_db) - self.schedule_filename = self._getopt( - 'schedule_filename', schedule_filename, - ) - self.scheduler_cls = self._getopt( - 'celerybeat_scheduler', scheduler_cls, - ) - self.task_time_limit = self._getopt( - 'task_time_limit', task_time_limit, - ) - self.task_soft_time_limit = self._getopt( - 'task_soft_time_limit', task_soft_time_limit, - ) - self.max_tasks_per_child = self._getopt( - 'max_tasks_per_child', max_tasks_per_child, - ) - self.prefetch_multiplier = int(self._getopt( - 'prefetch_multiplier', prefetch_multiplier, - )) - self.disable_rate_limits = self._getopt( - 'disable_rate_limits', disable_rate_limits, - ) - self.worker_lost_wait = self._getopt( - 'worker_lost_wait', worker_lost_wait, - ) - - def _getopt(self, key, value): - if value is not None: - return value - return self.app.conf.find_value_for_key(key, namespace='celeryd') diff --git a/awx/lib/site-packages/celery/worker/autoreload.py b/awx/lib/site-packages/celery/worker/autoreload.py deleted file mode 100644 index 8ade32fb2d..0000000000 --- a/awx/lib/site-packages/celery/worker/autoreload.py +++ /dev/null @@ -1,302 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.autoreload - ~~~~~~~~~~~~~~~~~~~~~~~~ - - This module implements automatic module reloading -""" -from __future__ import absolute_import - -import hashlib -import os -import select -import sys -import time - -from collections import defaultdict -from threading import Event - -from kombu.utils import eventio -from kombu.utils.encoding import ensure_bytes - -from celery import bootsteps -from celery.five import items -from celery.platforms import ignore_errno -from celery.utils.imports import module_file -from celery.utils.log import get_logger -from celery.utils.threads import bgThread - -from .components import Pool - -try: # pragma: no cover - import pyinotify - _ProcessEvent = pyinotify.ProcessEvent -except ImportError: # pragma: no cover - pyinotify = None # noqa - _ProcessEvent = object # noqa - -__all__ = [ - 'WorkerComponent', 'Autoreloader', 'Monitor', 'BaseMonitor', - 'StatMonitor', 'KQueueMonitor', 'InotifyMonitor', 'file_hash', -] - -logger = get_logger(__name__) - - -class WorkerComponent(bootsteps.StartStopStep): - label = 'Autoreloader' - conditional = True - requires = (Pool, ) - - def __init__(self, w, autoreload=None, **kwargs): - self.enabled = w.autoreload = autoreload - w.autoreloader = None - - def create(self, w): - w.autoreloader = self.instantiate(w.autoreloader_cls, w) - return w.autoreloader if not w.use_eventloop else None - - def register_with_event_loop(self, w, hub): - w.autoreloader.register_with_event_loop(hub) - hub.on_close.add(w.autoreloader.on_event_loop_close) - - -def file_hash(filename, algorithm='md5'): - hobj = hashlib.new(algorithm) - with open(filename, 'rb') as f: - for chunk in iter(lambda: f.read(2 ** 20), ''): - hobj.update(ensure_bytes(chunk)) - return hobj.digest() - - -class BaseMonitor(object): - - def __init__(self, files, - on_change=None, shutdown_event=None, interval=0.5): - self.files = files - self.interval = interval - self._on_change = on_change - self.modify_times = defaultdict(int) - self.shutdown_event = shutdown_event or Event() - - def start(self): - raise NotImplementedError('Subclass responsibility') - - def stop(self): - pass - - def on_change(self, modified): - if self._on_change: - return self._on_change(modified) - - def on_event_loop_close(self, hub): - pass - - -class StatMonitor(BaseMonitor): - """File change monitor based on the ``stat`` system call.""" - - def _mtimes(self): - return ((f, self._mtime(f)) for f in self.files) - - def _maybe_modified(self, f, mt): - return mt is not None and self.modify_times[f] != mt - - def register_with_event_loop(self, hub): - hub.call_repeatedly(2.0, self.find_changes) - - def find_changes(self): - maybe_modified = self._maybe_modified - modified = dict((f, mt) for f, mt in self._mtimes() - if maybe_modified(f, mt)) - if modified: - self.on_change(modified) - self.modify_times.update(modified) - - def start(self): - while not self.shutdown_event.is_set(): - self.find_changes() - time.sleep(self.interval) - - @staticmethod - def _mtime(path): - try: - return os.stat(path).st_mtime - except Exception: - pass - - -class KQueueMonitor(BaseMonitor): - """File change monitor based on BSD kernel event notifications""" - - def __init__(self, *args, **kwargs): - super(KQueueMonitor, self).__init__(*args, **kwargs) - self.filemap = dict((f, None) for f in self.files) - self.fdmap = {} - - def register_with_event_loop(self, hub): - if eventio.kqueue is not None: - self._kq = eventio._kqueue() - self.add_events(self._kq) - self._kq.on_file_change = self.handle_event - hub.add_reader(self._kq._kqueue, self._kq.poll, 0) - - def on_event_loop_close(self, hub): - self.close(self._kq) - - def add_events(self, poller): - for f in self.filemap: - self.filemap[f] = fd = os.open(f, os.O_RDONLY) - self.fdmap[fd] = f - poller.watch_file(fd) - - def handle_event(self, events): - self.on_change([self.fdmap[e.ident] for e in events]) - - def start(self): - self.poller = eventio.poll() - self.add_events(self.poller) - self.poller.on_file_change = self.handle_event - while not self.shutdown_event.is_set(): - self.poller.poll(1) - - def close(self, poller): - for f, fd in items(self.filemap): - if fd is not None: - poller.unregister(fd) - with ignore_errno('EBADF'): # pragma: no cover - os.close(fd) - self.filemap.clear() - self.fdmap.clear() - - def stop(self): - self.close(self.poller) - self.poller.close() - - -class InotifyMonitor(_ProcessEvent): - """File change monitor based on Linux kernel `inotify` subsystem""" - - def __init__(self, modules, on_change=None, **kwargs): - assert pyinotify - self._modules = modules - self._on_change = on_change - self._wm = None - self._notifier = None - - def register_with_event_loop(self, hub): - self.create_notifier() - hub.add_reader(self._wm.get_fd(), self.on_readable) - - def on_event_loop_close(self, hub): - pass - - def on_readable(self): - self._notifier.read_events() - self._notifier.process_events() - - def create_notifier(self): - self._wm = pyinotify.WatchManager() - self._notifier = pyinotify.Notifier(self._wm, self) - add_watch = self._wm.add_watch - flags = pyinotify.IN_MODIFY | pyinotify.IN_ATTRIB - for m in self._modules: - add_watch(m, flags) - - def start(self): - try: - self.create_notifier() - self._notifier.loop() - finally: - if self._wm: - self._wm.close() - # Notifier.close is called at the end of Notifier.loop - self._wm = self._notifier = None - - def stop(self): - pass - - def process_(self, event): - self.on_change([event.path]) - - process_IN_ATTRIB = process_IN_MODIFY = process_ - - def on_change(self, modified): - if self._on_change: - return self._on_change(modified) - - -def default_implementation(): - if hasattr(select, 'kqueue') and eventio.kqueue is not None: - return 'kqueue' - elif sys.platform.startswith('linux') and pyinotify: - return 'inotify' - else: - return 'stat' - -implementations = {'kqueue': KQueueMonitor, - 'inotify': InotifyMonitor, - 'stat': StatMonitor} -Monitor = implementations[ - os.environ.get('CELERYD_FSNOTIFY') or default_implementation()] - - -class Autoreloader(bgThread): - """Tracks changes in modules and fires reload commands""" - Monitor = Monitor - - def __init__(self, controller, modules=None, monitor_cls=None, **options): - super(Autoreloader, self).__init__() - self.controller = controller - app = self.controller.app - self.modules = app.loader.task_modules if modules is None else modules - self.options = options - self._monitor = None - self._hashes = None - self.file_to_module = {} - - def on_init(self): - files = self.file_to_module - files.update(dict( - (module_file(sys.modules[m]), m) for m in self.modules)) - - self._monitor = self.Monitor( - files, self.on_change, - shutdown_event=self._is_shutdown, **self.options) - self._hashes = dict([(f, file_hash(f)) for f in files]) - - def register_with_event_loop(self, hub): - if self._monitor is None: - self.on_init() - self._monitor.register_with_event_loop(hub) - - def on_event_loop_close(self, hub): - if self._monitor is not None: - self._monitor.on_event_loop_close(hub) - - def body(self): - self.on_init() - with ignore_errno('EINTR', 'EAGAIN'): - self._monitor.start() - - def _maybe_modified(self, f): - if os.path.exists(f): - digest = file_hash(f) - if digest != self._hashes[f]: - self._hashes[f] = digest - return True - return False - - def on_change(self, files): - modified = [f for f in files if self._maybe_modified(f)] - if modified: - names = [self.file_to_module[module] for module in modified] - logger.info('Detected modified modules: %r', names) - self._reload(names) - - def _reload(self, modules): - self.controller.reload(modules, reload=True) - - def stop(self): - if self._monitor: - self._monitor.stop() diff --git a/awx/lib/site-packages/celery/worker/autoscale.py b/awx/lib/site-packages/celery/worker/autoscale.py deleted file mode 100644 index 14afc2e95b..0000000000 --- a/awx/lib/site-packages/celery/worker/autoscale.py +++ /dev/null @@ -1,162 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.autoscale - ~~~~~~~~~~~~~~~~~~~~~~~ - - This module implements the internal thread responsible - for growing and shrinking the pool according to the - current autoscale settings. - - The autoscale thread is only enabled if :option:`--autoscale` - has been enabled on the command-line. - -""" -from __future__ import absolute_import - -import os -import threading - -from time import sleep - -from kombu.async.semaphore import DummyLock - -from celery import bootsteps -from celery.five import monotonic -from celery.utils.log import get_logger -from celery.utils.threads import bgThread - -from . import state -from .components import Pool - -__all__ = ['Autoscaler', 'WorkerComponent'] - -logger = get_logger(__name__) -debug, info, error = logger.debug, logger.info, logger.error - -AUTOSCALE_KEEPALIVE = float(os.environ.get('AUTOSCALE_KEEPALIVE', 30)) - - -class WorkerComponent(bootsteps.StartStopStep): - label = 'Autoscaler' - conditional = True - requires = (Pool, ) - - def __init__(self, w, **kwargs): - self.enabled = w.autoscale - w.autoscaler = None - - def create(self, w): - scaler = w.autoscaler = self.instantiate( - w.autoscaler_cls, - w.pool, w.max_concurrency, w.min_concurrency, - worker=w, mutex=DummyLock() if w.use_eventloop else None, - ) - return scaler if not w.use_eventloop else None - - def register_with_event_loop(self, w, hub): - w.consumer.on_task_message.add(w.autoscaler.maybe_scale) - hub.call_repeatedly( - w.autoscaler.keepalive, w.autoscaler.maybe_scale, - ) - - -class Autoscaler(bgThread): - - def __init__(self, pool, max_concurrency, - min_concurrency=0, worker=None, - keepalive=AUTOSCALE_KEEPALIVE, mutex=None): - super(Autoscaler, self).__init__() - self.pool = pool - self.mutex = mutex or threading.Lock() - self.max_concurrency = max_concurrency - self.min_concurrency = min_concurrency - self.keepalive = keepalive - self._last_action = None - self.worker = worker - - assert self.keepalive, 'cannot scale down too fast.' - - def body(self): - with self.mutex: - self.maybe_scale() - sleep(1.0) - - def _maybe_scale(self): - procs = self.processes - cur = min(self.qty, self.max_concurrency) - if cur > procs: - self.scale_up(cur - procs) - return True - elif cur < procs: - self.scale_down((procs - cur) - self.min_concurrency) - return True - - def maybe_scale(self): - if self._maybe_scale(): - self.pool.maintain_pool() - - def update(self, max=None, min=None): - with self.mutex: - if max is not None: - if max < self.max_concurrency: - self._shrink(self.processes - max) - self.max_concurrency = max - if min is not None: - if min > self.min_concurrency: - self._grow(min - self.min_concurrency) - self.min_concurrency = min - return self.max_concurrency, self.min_concurrency - - def force_scale_up(self, n): - with self.mutex: - new = self.processes + n - if new > self.max_concurrency: - self.max_concurrency = new - self.min_concurrency += 1 - self._grow(n) - - def force_scale_down(self, n): - with self.mutex: - new = self.processes - n - if new < self.min_concurrency: - self.min_concurrency = max(new, 0) - self._shrink(min(n, self.processes)) - - def scale_up(self, n): - self._last_action = monotonic() - return self._grow(n) - - def scale_down(self, n): - if n and self._last_action and ( - monotonic() - self._last_action > self.keepalive): - self._last_action = monotonic() - return self._shrink(n) - - def _grow(self, n): - info('Scaling up %s processes.', n) - self.pool.grow(n) - self.worker.consumer._update_prefetch_count(n) - - def _shrink(self, n): - info('Scaling down %s processes.', n) - try: - self.pool.shrink(n) - except ValueError: - debug("Autoscaler won't scale down: all processes busy.") - except Exception as exc: - error('Autoscaler: scale_down: %r', exc, exc_info=True) - self.worker.consumer._update_prefetch_count(-n) - - def info(self): - return {'max': self.max_concurrency, - 'min': self.min_concurrency, - 'current': self.processes, - 'qty': self.qty} - - @property - def qty(self): - return len(state.reserved_requests) - - @property - def processes(self): - return self.pool.num_processes diff --git a/awx/lib/site-packages/celery/worker/components.py b/awx/lib/site-packages/celery/worker/components.py deleted file mode 100644 index d23a3b6b84..0000000000 --- a/awx/lib/site-packages/celery/worker/components.py +++ /dev/null @@ -1,247 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.components - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Default worker bootsteps. - -""" -from __future__ import absolute_import - -import atexit -import warnings - -from kombu.async import Hub as _Hub, get_event_loop, set_event_loop -from kombu.async.semaphore import DummyLock, LaxBoundedSemaphore -from kombu.async.timer import Timer as _Timer - -from celery import bootsteps -from celery._state import _set_task_join_will_block -from celery.exceptions import ImproperlyConfigured -from celery.five import string_t -from celery.utils.log import worker_logger as logger - -__all__ = ['Timer', 'Hub', 'Queues', 'Pool', 'Beat', 'StateDB', 'Consumer'] - -ERR_B_GREEN = """\ --B option doesn't work with eventlet/gevent pools: \ -use standalone beat instead.\ -""" - -W_POOL_SETTING = """ -The CELERYD_POOL setting should not be used to select the eventlet/gevent -pools, instead you *must use the -P* argument so that patches are applied -as early as possible. -""" - - -class Timer(bootsteps.Step): - """This step initializes the internal timer used by the worker.""" - - def create(self, w): - if w.use_eventloop: - # does not use dedicated timer thread. - w.timer = _Timer(max_interval=10.0) - else: - if not w.timer_cls: - # Default Timer is set by the pool, as e.g. eventlet - # needs a custom implementation. - w.timer_cls = w.pool_cls.Timer - w.timer = self.instantiate(w.timer_cls, - max_interval=w.timer_precision, - on_timer_error=self.on_timer_error, - on_timer_tick=self.on_timer_tick) - - def on_timer_error(self, exc): - logger.error('Timer error: %r', exc, exc_info=True) - - def on_timer_tick(self, delay): - logger.debug('Timer wake-up! Next eta %s secs.', delay) - - -class Hub(bootsteps.StartStopStep): - requires = (Timer, ) - - def __init__(self, w, **kwargs): - w.hub = None - - def include_if(self, w): - return w.use_eventloop - - def create(self, w): - w.hub = get_event_loop() - if w.hub is None: - w.hub = set_event_loop(_Hub(w.timer)) - self._patch_thread_primitives(w) - return self - - def start(self, w): - pass - - def stop(self, w): - w.hub.close() - - def terminate(self, w): - w.hub.close() - - def _patch_thread_primitives(self, w): - # make clock use dummy lock - w.app.clock.mutex = DummyLock() - # multiprocessing's ApplyResult uses this lock. - try: - from billiard import pool - except ImportError: - pass - else: - pool.Lock = DummyLock - - -class Queues(bootsteps.Step): - """This bootstep initializes the internal queues - used by the worker.""" - label = 'Queues (intra)' - requires = (Hub, ) - - def create(self, w): - w.process_task = w._process_task - if w.use_eventloop: - if w.pool_putlocks and w.pool_cls.uses_semaphore: - w.process_task = w._process_task_sem - - -class Pool(bootsteps.StartStopStep): - """Bootstep managing the worker pool. - - Describes how to initialize the worker pool, and starts and stops - the pool during worker startup/shutdown. - - Adds attributes: - - * autoscale - * pool - * max_concurrency - * min_concurrency - - """ - requires = (Queues, ) - - def __init__(self, w, autoscale=None, autoreload=None, - no_execv=False, optimization=None, **kwargs): - if isinstance(autoscale, string_t): - max_c, _, min_c = autoscale.partition(',') - autoscale = [int(max_c), min_c and int(min_c) or 0] - w.autoscale = autoscale - w.pool = None - w.max_concurrency = None - w.min_concurrency = w.concurrency - w.no_execv = no_execv - if w.autoscale: - w.max_concurrency, w.min_concurrency = w.autoscale - self.autoreload_enabled = autoreload - self.optimization = optimization - - def close(self, w): - if w.pool: - w.pool.close() - - def terminate(self, w): - if w.pool: - w.pool.terminate() - - def create(self, w, semaphore=None, max_restarts=None): - if w.app.conf.CELERYD_POOL in ('eventlet', 'gevent'): - warnings.warn(UserWarning(W_POOL_SETTING)) - threaded = not w.use_eventloop - procs = w.min_concurrency - forking_enable = w.no_execv if w.force_execv else True - if not threaded: - semaphore = w.semaphore = LaxBoundedSemaphore(procs) - w._quick_acquire = w.semaphore.acquire - w._quick_release = w.semaphore.release - max_restarts = 100 - allow_restart = self.autoreload_enabled or w.pool_restarts - pool = w.pool = self.instantiate( - w.pool_cls, w.min_concurrency, - initargs=(w.app, w.hostname), - maxtasksperchild=w.max_tasks_per_child, - timeout=w.task_time_limit, - soft_timeout=w.task_soft_time_limit, - putlocks=w.pool_putlocks and threaded, - lost_worker_timeout=w.worker_lost_wait, - threads=threaded, - max_restarts=max_restarts, - allow_restart=allow_restart, - forking_enable=forking_enable, - semaphore=semaphore, - sched_strategy=self.optimization, - ) - _set_task_join_will_block(pool.task_join_will_block) - return pool - - def info(self, w): - return {'pool': w.pool.info if w.pool else 'N/A'} - - def register_with_event_loop(self, w, hub): - w.pool.register_with_event_loop(hub) - - -class Beat(bootsteps.StartStopStep): - """Step used to embed a beat process. - - This will only be enabled if the ``beat`` - argument is set. - - """ - label = 'Beat' - conditional = True - - def __init__(self, w, beat=False, **kwargs): - self.enabled = w.beat = beat - w.beat = None - - def create(self, w): - from celery.beat import EmbeddedService - if w.pool_cls.__module__.endswith(('gevent', 'eventlet')): - raise ImproperlyConfigured(ERR_B_GREEN) - b = w.beat = EmbeddedService(app=w.app, - schedule_filename=w.schedule_filename, - scheduler_cls=w.scheduler_cls) - return b - - -class StateDB(bootsteps.Step): - """This bootstep sets up the workers state db if enabled.""" - - def __init__(self, w, **kwargs): - self.enabled = w.state_db - w._persistence = None - - def create(self, w): - w._persistence = w.state.Persistent(w.state, w.state_db, w.app.clock) - atexit.register(w._persistence.save) - - -class Consumer(bootsteps.StartStopStep): - last = True - - def create(self, w): - if w.max_concurrency: - prefetch_count = max(w.min_concurrency, 1) * w.prefetch_multiplier - else: - prefetch_count = w.concurrency * w.prefetch_multiplier - c = w.consumer = self.instantiate( - w.consumer_cls, w.process_task, - hostname=w.hostname, - send_events=w.send_events, - init_callback=w.ready_callback, - initial_prefetch_count=prefetch_count, - pool=w.pool, - timer=w.timer, - app=w.app, - controller=w, - hub=w.hub, - worker_options=w.options, - disable_rate_limits=w.disable_rate_limits, - prefetch_multiplier=w.prefetch_multiplier, - ) - return c diff --git a/awx/lib/site-packages/celery/worker/consumer.py b/awx/lib/site-packages/celery/worker/consumer.py deleted file mode 100644 index 16fa0ff4e7..0000000000 --- a/awx/lib/site-packages/celery/worker/consumer.py +++ /dev/null @@ -1,804 +0,0 @@ -# -*- coding: utf-8 -*- -""" -celery.worker.consumer -~~~~~~~~~~~~~~~~~~~~~~ - -This module contains the components responsible for consuming messages -from the broker, processing the messages and keeping the broker connections -up and running. - -""" -from __future__ import absolute_import - -import errno -import kombu -import logging -import os -import socket - -from collections import defaultdict -from functools import partial -from heapq import heappush -from operator import itemgetter -from time import sleep - -from billiard.common import restart_state -from billiard.exceptions import RestartFreqExceeded -from kombu.async.semaphore import DummyLock -from kombu.common import QoS, ignore_errors -from kombu.syn import _detect_environment -from kombu.utils.compat import get_errno -from kombu.utils.encoding import safe_repr, bytes_t -from kombu.utils.limits import TokenBucket - -from celery import bootsteps -from celery.app.trace import build_tracer -from celery.canvas import signature -from celery.exceptions import InvalidTaskError -from celery.five import items, values -from celery.utils.functional import noop -from celery.utils.log import get_logger -from celery.utils.text import truncate -from celery.utils.timeutils import humanize_seconds, rate - -from . import heartbeat, loops, pidbox -from .state import task_reserved, maybe_shutdown, revoked, reserved_requests - -try: - buffer_t = buffer -except NameError: # pragma: no cover - # Py3 does not have buffer, but we only need isinstance. - - class buffer_t(object): # noqa - pass - -__all__ = [ - 'Consumer', 'Connection', 'Events', 'Heart', 'Control', - 'Tasks', 'Evloop', 'Agent', 'Mingle', 'Gossip', 'dump_body', -] - -CLOSE = bootsteps.CLOSE -logger = get_logger(__name__) -debug, info, warn, error, crit = (logger.debug, logger.info, logger.warning, - logger.error, logger.critical) - -CONNECTION_RETRY = """\ -consumer: Connection to broker lost. \ -Trying to re-establish the connection...\ -""" - -CONNECTION_RETRY_STEP = """\ -Trying again {when}...\ -""" - -CONNECTION_ERROR = """\ -consumer: Cannot connect to %s: %s. -%s -""" - -CONNECTION_FAILOVER = """\ -Will retry using next failover.\ -""" - -UNKNOWN_FORMAT = """\ -Received and deleted unknown message. Wrong destination?!? - -The full contents of the message body was: %s -""" - -#: Error message for when an unregistered task is received. -UNKNOWN_TASK_ERROR = """\ -Received unregistered task of type %s. -The message has been ignored and discarded. - -Did you remember to import the module containing this task? -Or maybe you are using relative imports? -Please see http://bit.ly/gLye1c for more information. - -The full contents of the message body was: -%s -""" - -#: Error message for when an invalid task message is received. -INVALID_TASK_ERROR = """\ -Received invalid task message: %s -The message has been ignored and discarded. - -Please ensure your message conforms to the task -message protocol as described here: http://bit.ly/hYj41y - -The full contents of the message body was: -%s -""" - -MESSAGE_DECODE_ERROR = """\ -Can't decode message body: %r [type:%r encoding:%r headers:%s] - -body: %s -""" - -MESSAGE_REPORT = """\ -body: {0} -{{content_type:{1} content_encoding:{2} - delivery_info:{3} headers={4}}} -""" - -MINGLE_GET_FIELDS = itemgetter('clock', 'revoked') - - -def dump_body(m, body): - if isinstance(body, buffer_t): - body = bytes_t(body) - return '{0} ({1}b)'.format(truncate(safe_repr(body), 1024), - len(m.body)) - - -class Consumer(object): - Strategies = dict - - #: set when consumer is shutting down. - in_shutdown = False - - #: Optional callback called the first time the worker - #: is ready to receive tasks. - init_callback = None - - #: The current worker pool instance. - pool = None - - #: A timer used for high-priority internal tasks, such - #: as sending heartbeats. - timer = None - - restart_count = -1 # first start is the same as a restart - - class Blueprint(bootsteps.Blueprint): - name = 'Consumer' - default_steps = [ - 'celery.worker.consumer:Connection', - 'celery.worker.consumer:Mingle', - 'celery.worker.consumer:Events', - 'celery.worker.consumer:Gossip', - 'celery.worker.consumer:Heart', - 'celery.worker.consumer:Control', - 'celery.worker.consumer:Tasks', - 'celery.worker.consumer:Evloop', - 'celery.worker.consumer:Agent', - ] - - def shutdown(self, parent): - self.send_all(parent, 'shutdown') - - def __init__(self, on_task_request, - init_callback=noop, hostname=None, - pool=None, app=None, - timer=None, controller=None, hub=None, amqheartbeat=None, - worker_options=None, disable_rate_limits=False, - initial_prefetch_count=2, prefetch_multiplier=1, **kwargs): - self.app = app - self.controller = controller - self.init_callback = init_callback - self.hostname = hostname or socket.gethostname() - self.pid = os.getpid() - self.pool = pool - self.timer = timer - self.strategies = self.Strategies() - conninfo = self.app.connection() - self.connection_errors = conninfo.connection_errors - self.channel_errors = conninfo.channel_errors - self._restart_state = restart_state(maxR=5, maxT=1) - - self._does_info = logger.isEnabledFor(logging.INFO) - self.on_task_request = on_task_request - self.on_task_message = set() - self.amqheartbeat_rate = self.app.conf.BROKER_HEARTBEAT_CHECKRATE - self.disable_rate_limits = disable_rate_limits - self.initial_prefetch_count = initial_prefetch_count - self.prefetch_multiplier = prefetch_multiplier - - # this contains a tokenbucket for each task type by name, used for - # rate limits, or None if rate limits are disabled for that task. - self.task_buckets = defaultdict(lambda: None) - self.reset_rate_limits() - - self.hub = hub - if self.hub: - self.amqheartbeat = amqheartbeat - if self.amqheartbeat is None: - self.amqheartbeat = self.app.conf.BROKER_HEARTBEAT - else: - self.amqheartbeat = 0 - - if not hasattr(self, 'loop'): - self.loop = loops.asynloop if hub else loops.synloop - - if _detect_environment() == 'gevent': - # there's a gevent bug that causes timeouts to not be reset, - # so if the connection timeout is exceeded once, it can NEVER - # connect again. - self.app.conf.BROKER_CONNECTION_TIMEOUT = None - - self.steps = [] - self.blueprint = self.Blueprint( - app=self.app, on_close=self.on_close, - ) - self.blueprint.apply(self, **dict(worker_options or {}, **kwargs)) - - def bucket_for_task(self, type): - limit = rate(getattr(type, 'rate_limit', None)) - return TokenBucket(limit, capacity=1) if limit else None - - def reset_rate_limits(self): - self.task_buckets.update( - (n, self.bucket_for_task(t)) for n, t in items(self.app.tasks) - ) - - def _update_prefetch_count(self, index=0): - """Update prefetch count after pool/shrink grow operations. - - Index must be the change in number of processes as a positive - (increasing) or negative (decreasing) number. - - .. note:: - - Currently pool grow operations will end up with an offset - of +1 if the initial size of the pool was 0 (e.g. - ``--autoscale=1,0``). - - """ - num_processes = self.pool.num_processes - if not self.initial_prefetch_count or not num_processes: - return # prefetch disabled - self.initial_prefetch_count = ( - self.pool.num_processes * self.prefetch_multiplier - ) - return self._update_qos_eventually(index) - - def _update_qos_eventually(self, index): - return (self.qos.decrement_eventually if index < 0 - else self.qos.increment_eventually)( - abs(index) * self.prefetch_multiplier) - - def _limit_task(self, request, bucket, tokens): - if not bucket.can_consume(tokens): - hold = bucket.expected_time(tokens) - self.timer.call_after( - hold, self._limit_task, (request, bucket, tokens), - ) - else: - task_reserved(request) - self.on_task_request(request) - - def start(self): - blueprint, loop = self.blueprint, self.loop - while blueprint.state != CLOSE: - self.restart_count += 1 - maybe_shutdown() - try: - blueprint.start(self) - except self.connection_errors as exc: - if isinstance(exc, OSError) and get_errno(exc) == errno.EMFILE: - raise # Too many open files - maybe_shutdown() - try: - self._restart_state.step() - except RestartFreqExceeded as exc: - crit('Frequent restarts detected: %r', exc, exc_info=1) - sleep(1) - if blueprint.state != CLOSE and self.connection: - warn(CONNECTION_RETRY, exc_info=True) - try: - self.connection.collect() - except Exception: - pass - self.on_close() - blueprint.restart(self) - - def register_with_event_loop(self, hub): - self.blueprint.send_all( - self, 'register_with_event_loop', args=(hub, ), - description='Hub.register', - ) - - def shutdown(self): - self.in_shutdown = True - self.blueprint.shutdown(self) - - def stop(self): - self.blueprint.stop(self) - - def on_ready(self): - callback, self.init_callback = self.init_callback, None - if callback: - callback(self) - - def loop_args(self): - return (self, self.connection, self.task_consumer, - self.blueprint, self.hub, self.qos, self.amqheartbeat, - self.app.clock, self.amqheartbeat_rate) - - def on_decode_error(self, message, exc): - """Callback called if an error occurs while decoding - a message received. - - Simply logs the error and acknowledges the message so it - doesn't enter a loop. - - :param message: The message with errors. - :param exc: The original exception instance. - - """ - crit(MESSAGE_DECODE_ERROR, - exc, message.content_type, message.content_encoding, - safe_repr(message.headers), dump_body(message, message.body), - exc_info=1) - message.ack() - - def on_close(self): - # Clear internal queues to get rid of old messages. - # They can't be acked anyway, as a delivery tag is specific - # to the current channel. - if self.controller and self.controller.semaphore: - self.controller.semaphore.clear() - if self.timer: - self.timer.clear() - reserved_requests.clear() - if self.pool and self.pool.flush: - self.pool.flush() - - def connect(self): - """Establish the broker connection. - - Will retry establishing the connection if the - :setting:`BROKER_CONNECTION_RETRY` setting is enabled - - """ - conn = self.app.connection(heartbeat=self.amqheartbeat) - - # Callback called for each retry while the connection - # can't be established. - def _error_handler(exc, interval, next_step=CONNECTION_RETRY_STEP): - if getattr(conn, 'alt', None) and interval == 0: - next_step = CONNECTION_FAILOVER - error(CONNECTION_ERROR, conn.as_uri(), exc, - next_step.format(when=humanize_seconds(interval, 'in', ' '))) - - # remember that the connection is lazy, it won't establish - # until needed. - if not self.app.conf.BROKER_CONNECTION_RETRY: - # retry disabled, just call connect directly. - conn.connect() - return conn - - conn = conn.ensure_connection( - _error_handler, self.app.conf.BROKER_CONNECTION_MAX_RETRIES, - callback=maybe_shutdown, - ) - if self.hub: - conn.transport.register_with_event_loop(conn.connection, self.hub) - return conn - - def add_task_queue(self, queue, exchange=None, exchange_type=None, - routing_key=None, **options): - cset = self.task_consumer - queues = self.app.amqp.queues - # Must use in' here, as __missing__ will automatically - # create queues when CELERY_CREATE_MISSING_QUEUES is enabled. - # (Issue #1079) - if queue in queues: - q = queues[queue] - else: - exchange = queue if exchange is None else exchange - exchange_type = ('direct' if exchange_type is None - else exchange_type) - q = queues.select_add(queue, - exchange=exchange, - exchange_type=exchange_type, - routing_key=routing_key, **options) - if not cset.consuming_from(queue): - cset.add_queue(q) - cset.consume() - info('Started consuming from %s', queue) - - def cancel_task_queue(self, queue): - info('Cancelling queue %s', queue) - self.app.amqp.queues.deselect(queue) - self.task_consumer.cancel_by_queue(queue) - - def apply_eta_task(self, task): - """Method called by the timer to apply a task with an - ETA/countdown.""" - task_reserved(task) - self.on_task_request(task) - self.qos.decrement_eventually() - - def _message_report(self, body, message): - return MESSAGE_REPORT.format(dump_body(message, body), - safe_repr(message.content_type), - safe_repr(message.content_encoding), - safe_repr(message.delivery_info), - safe_repr(message.headers)) - - def on_unknown_message(self, body, message): - warn(UNKNOWN_FORMAT, self._message_report(body, message)) - message.reject_log_error(logger, self.connection_errors) - - def on_unknown_task(self, body, message, exc): - error(UNKNOWN_TASK_ERROR, exc, dump_body(message, body), exc_info=True) - message.reject_log_error(logger, self.connection_errors) - - def on_invalid_task(self, body, message, exc): - error(INVALID_TASK_ERROR, exc, dump_body(message, body), exc_info=True) - message.reject_log_error(logger, self.connection_errors) - - def update_strategies(self): - loader = self.app.loader - for name, task in items(self.app.tasks): - self.strategies[name] = task.start_strategy(self.app, self) - task.__trace__ = build_tracer(name, task, loader, self.hostname, - app=self.app) - - def create_task_handler(self): - strategies = self.strategies - on_unknown_message = self.on_unknown_message - on_unknown_task = self.on_unknown_task - on_invalid_task = self.on_invalid_task - callbacks = self.on_task_message - - def on_task_received(body, message): - try: - name = body['task'] - except (KeyError, TypeError): - return on_unknown_message(body, message) - - try: - strategies[name](message, body, - message.ack_log_error, - message.reject_log_error, - callbacks) - except KeyError as exc: - on_unknown_task(body, message, exc) - except InvalidTaskError as exc: - on_invalid_task(body, message, exc) - - return on_task_received - - def __repr__(self): - return '<Consumer: {self.hostname} ({state})>'.format( - self=self, state=self.blueprint.human_state(), - ) - - -class Connection(bootsteps.StartStopStep): - - def __init__(self, c, **kwargs): - c.connection = None - - def start(self, c): - c.connection = c.connect() - info('Connected to %s', c.connection.as_uri()) - - def shutdown(self, c): - # We must set self.connection to None here, so - # that the green pidbox thread exits. - connection, c.connection = c.connection, None - if connection: - ignore_errors(connection, connection.close) - - def info(self, c, params='N/A'): - if c.connection: - params = c.connection.info() - params.pop('password', None) # don't send password. - return {'broker': params} - - -class Events(bootsteps.StartStopStep): - requires = (Connection, ) - - def __init__(self, c, send_events=None, **kwargs): - self.send_events = True - self.groups = None if send_events else ['worker'] - c.event_dispatcher = None - - def start(self, c): - # flush events sent while connection was down. - prev = self._close(c) - dis = c.event_dispatcher = c.app.events.Dispatcher( - c.connect(), hostname=c.hostname, - enabled=self.send_events, groups=self.groups, - ) - if prev: - dis.extend_buffer(prev) - dis.flush() - - def stop(self, c): - pass - - def _close(self, c): - if c.event_dispatcher: - dispatcher = c.event_dispatcher - # remember changes from remote control commands: - self.groups = dispatcher.groups - - # close custom connection - if dispatcher.connection: - ignore_errors(c, dispatcher.connection.close) - ignore_errors(c, dispatcher.close) - c.event_dispatcher = None - return dispatcher - - def shutdown(self, c): - self._close(c) - - -class Heart(bootsteps.StartStopStep): - requires = (Events, ) - - def __init__(self, c, without_heartbeat=False, **kwargs): - self.enabled = not without_heartbeat - c.heart = None - - def start(self, c): - c.heart = heartbeat.Heart(c.timer, c.event_dispatcher) - c.heart.start() - - def stop(self, c): - c.heart = c.heart and c.heart.stop() - shutdown = stop - - -class Mingle(bootsteps.StartStopStep): - label = 'Mingle' - requires = (Events, ) - compatible_transports = set(['amqp', 'redis']) - - def __init__(self, c, without_mingle=False, **kwargs): - self.enabled = not without_mingle and self.compatible_transport(c.app) - - def compatible_transport(self, app): - with app.connection() as conn: - return conn.transport.driver_type in self.compatible_transports - - def start(self, c): - info('mingle: searching for neighbors') - I = c.app.control.inspect(timeout=1.0, connection=c.connection) - replies = I.hello(c.hostname, revoked._data) or {} - replies.pop(c.hostname, None) - if replies: - info('mingle: sync with %s nodes', - len([reply for reply, value in items(replies) if value])) - for reply in values(replies): - if reply: - try: - other_clock, other_revoked = MINGLE_GET_FIELDS(reply) - except KeyError: # reply from pre-3.1 worker - pass - else: - c.app.clock.adjust(other_clock) - revoked.update(other_revoked) - info('mingle: sync complete') - else: - info('mingle: all alone') - - -class Tasks(bootsteps.StartStopStep): - requires = (Mingle, ) - - def __init__(self, c, **kwargs): - c.task_consumer = c.qos = None - - def start(self, c): - c.update_strategies() - c.task_consumer = c.app.amqp.TaskConsumer( - c.connection, on_decode_error=c.on_decode_error, - ) - c.qos = QoS(c.task_consumer.qos, c.initial_prefetch_count) - c.qos.update() # set initial prefetch count - - def stop(self, c): - if c.task_consumer: - debug('Cancelling task consumer...') - ignore_errors(c, c.task_consumer.cancel) - - def shutdown(self, c): - if c.task_consumer: - self.stop(c) - debug('Closing consumer channel...') - ignore_errors(c, c.task_consumer.close) - c.task_consumer = None - - def info(self, c): - return {'prefetch_count': c.qos.value if c.qos else 'N/A'} - - -class Agent(bootsteps.StartStopStep): - conditional = True - requires = (Connection, ) - - def __init__(self, c, **kwargs): - self.agent_cls = self.enabled = c.app.conf.CELERYD_AGENT - - def create(self, c): - agent = c.agent = self.instantiate(self.agent_cls, c.connection) - return agent - - -class Control(bootsteps.StartStopStep): - requires = (Tasks, ) - - def __init__(self, c, **kwargs): - self.is_green = c.pool is not None and c.pool.is_green - self.box = (pidbox.gPidbox if self.is_green else pidbox.Pidbox)(c) - self.start = self.box.start - self.stop = self.box.stop - self.shutdown = self.box.shutdown - - def include_if(self, c): - return c.app.conf.CELERY_ENABLE_REMOTE_CONTROL - - -class Gossip(bootsteps.ConsumerStep): - label = 'Gossip' - requires = (Mingle, ) - _cons_stamp_fields = itemgetter( - 'id', 'clock', 'hostname', 'pid', 'topic', 'action', 'cver', - ) - compatible_transports = set(['amqp', 'redis']) - - def __init__(self, c, without_gossip=False, interval=5.0, **kwargs): - self.enabled = not without_gossip and self.compatible_transport(c.app) - self.app = c.app - c.gossip = self - self.Receiver = c.app.events.Receiver - self.hostname = c.hostname - self.full_hostname = '.'.join([self.hostname, str(c.pid)]) - - self.timer = c.timer - if self.enabled: - self.state = c.app.events.State( - on_node_join=self.on_node_join, - on_node_leave=self.on_node_leave, - max_tasks_in_memory=1, - ) - if c.hub: - c._mutex = DummyLock() - self.update_state = self.state.event - self.interval = interval - self._tref = None - self.consensus_requests = defaultdict(list) - self.consensus_replies = {} - self.event_handlers = { - 'worker.elect': self.on_elect, - 'worker.elect.ack': self.on_elect_ack, - } - self.clock = c.app.clock - - self.election_handlers = { - 'task': self.call_task - } - - def compatible_transport(self, app): - with app.connection() as conn: - return conn.transport.driver_type in self.compatible_transports - - def election(self, id, topic, action=None): - self.consensus_replies[id] = [] - self.dispatcher.send( - 'worker-elect', - id=id, topic=topic, action=action, cver=1, - ) - - def call_task(self, task): - try: - signature(task, app=self.app).apply_async() - except Exception as exc: - error('Could not call task: %r', exc, exc_info=1) - - def on_elect(self, event): - try: - (id_, clock, hostname, pid, - topic, action, _) = self._cons_stamp_fields(event) - except KeyError as exc: - return error('election request missing field %s', exc, exc_info=1) - heappush( - self.consensus_requests[id_], - (clock, '%s.%s' % (hostname, pid), topic, action), - ) - self.dispatcher.send('worker-elect-ack', id=id_) - - def start(self, c): - super(Gossip, self).start(c) - self.dispatcher = c.event_dispatcher - - def on_elect_ack(self, event): - id = event['id'] - try: - replies = self.consensus_replies[id] - except KeyError: - return # not for us - alive_workers = self.state.alive_workers() - replies.append(event['hostname']) - - if len(replies) >= len(alive_workers): - _, leader, topic, action = self.clock.sort_heap( - self.consensus_requests[id], - ) - if leader == self.full_hostname: - info('I won the election %r', id) - try: - handler = self.election_handlers[topic] - except KeyError: - error('Unknown election topic %r', topic, exc_info=1) - else: - handler(action) - else: - info('node %s elected for %r', leader, id) - self.consensus_requests.pop(id, None) - self.consensus_replies.pop(id, None) - - def on_node_join(self, worker): - debug('%s joined the party', worker.hostname) - - def on_node_leave(self, worker): - debug('%s left', worker.hostname) - - def on_node_lost(self, worker): - info('missed heartbeat from %s', worker.hostname) - - def register_timer(self): - if self._tref is not None: - self._tref.cancel() - self._tref = self.timer.call_repeatedly(self.interval, self.periodic) - - def periodic(self): - workers = self.state.workers - dirty = set() - for worker in values(workers): - if not worker.alive: - dirty.add(worker) - self.on_node_lost(worker) - for worker in dirty: - workers.pop(worker.hostname, None) - - def get_consumers(self, channel): - self.register_timer() - ev = self.Receiver(channel, routing_key='worker.#') - return [kombu.Consumer( - channel, - queues=[ev.queue], - on_message=partial(self.on_message, ev.event_from_message), - no_ack=True - )] - - def on_message(self, prepare, message): - _type = message.delivery_info['routing_key'] - - # For redis when `fanout_patterns=False` (See Issue #1882) - if _type.split('.', 1)[0] == 'task': - return - try: - handler = self.event_handlers[_type] - except KeyError: - pass - else: - return handler(message.payload) - - hostname = (message.headers.get('hostname') or - message.payload['hostname']) - if hostname != self.hostname: - type, event = prepare(message.payload) - obj, subject = self.update_state(event) - else: - self.clock.forward() - - -class Evloop(bootsteps.StartStopStep): - label = 'event loop' - last = True - - def start(self, c): - self.patch_all(c) - c.loop(*c.loop_args()) - - def patch_all(self, c): - c.qos._mutex = DummyLock() diff --git a/awx/lib/site-packages/celery/worker/control.py b/awx/lib/site-packages/celery/worker/control.py deleted file mode 100644 index fcaf040815..0000000000 --- a/awx/lib/site-packages/celery/worker/control.py +++ /dev/null @@ -1,380 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.control - ~~~~~~~~~~~~~~~~~~~~~ - - Remote control commands. - -""" -from __future__ import absolute_import - -import io -import tempfile - -from kombu.utils.encoding import safe_repr - -from celery.exceptions import WorkerShutdown -from celery.five import UserDict, items -from celery.platforms import signals as _signals -from celery.utils import timeutils -from celery.utils.functional import maybe_list -from celery.utils.log import get_logger -from celery.utils import jsonify - -from . import state as worker_state -from .state import revoked -from .job import Request - -__all__ = ['Panel'] -DEFAULT_TASK_INFO_ITEMS = ('exchange', 'routing_key', 'rate_limit') -logger = get_logger(__name__) - - -class Panel(UserDict): - data = dict() # Global registry. - - @classmethod - def register(cls, method, name=None): - cls.data[name or method.__name__] = method - return method - - -def _find_requests_by_id(ids, requests): - found, total = 0, len(ids) - for request in requests: - if request.id in ids: - yield request - found += 1 - if found >= total: - break - - -@Panel.register -def query_task(state, ids, **kwargs): - ids = maybe_list(ids) - - def reqinfo(state, req): - return state, req.info() - - reqs = dict((req.id, ('reserved', req.info())) - for req in _find_requests_by_id( - ids, worker_state.reserved_requests)) - reqs.update(dict( - (req.id, ('active', req.info())) - for req in _find_requests_by_id( - ids, worker_state.active_requests, - ) - )) - - return reqs - - -@Panel.register -def revoke(state, task_id, terminate=False, signal=None, **kwargs): - """Revoke task by task id.""" - # supports list argument since 3.1 - task_ids, task_id = set(maybe_list(task_id) or []), None - size = len(task_ids) - terminated = set() - - revoked.update(task_ids) - if terminate: - signum = _signals.signum(signal or 'TERM') - # reserved_requests changes size during iteration - # so need to consume the items first, then terminate after. - requests = set(_find_requests_by_id( - task_ids, - worker_state.reserved_requests, - )) - for request in requests: - if request.id not in terminated: - terminated.add(request.id) - logger.info('Terminating %s (%s)', request.id, signum) - request.terminate(state.consumer.pool, signal=signum) - if len(terminated) >= size: - break - - if not terminated: - return {'ok': 'terminate: tasks unknown'} - return {'ok': 'terminate: {0}'.format(', '.join(terminated))} - - idstr = ', '.join(task_ids) - logger.info('Tasks flagged as revoked: %s', idstr) - return {'ok': 'tasks {0} flagged as revoked'.format(idstr)} - - -@Panel.register -def report(state): - return {'ok': state.app.bugreport()} - - -@Panel.register -def enable_events(state): - dispatcher = state.consumer.event_dispatcher - if 'task' not in dispatcher.groups: - dispatcher.groups.add('task') - logger.info('Events of group {task} enabled by remote.') - return {'ok': 'task events enabled'} - return {'ok': 'task events already enabled'} - - -@Panel.register -def disable_events(state): - dispatcher = state.consumer.event_dispatcher - if 'task' in dispatcher.groups: - dispatcher.groups.discard('task') - logger.info('Events of group {task} disabled by remote.') - return {'ok': 'task events disabled'} - return {'ok': 'task events already disabled'} - - -@Panel.register -def heartbeat(state): - logger.debug('Heartbeat requested by remote.') - dispatcher = state.consumer.event_dispatcher - dispatcher.send('worker-heartbeat', freq=5, **worker_state.SOFTWARE_INFO) - - -@Panel.register -def rate_limit(state, task_name, rate_limit, **kwargs): - """Set new rate limit for a task type. - - See :attr:`celery.task.base.Task.rate_limit`. - - :param task_name: Type of task. - :param rate_limit: New rate limit. - - """ - - try: - timeutils.rate(rate_limit) - except ValueError as exc: - return {'error': 'Invalid rate limit string: {0!r}'.format(exc)} - - try: - state.app.tasks[task_name].rate_limit = rate_limit - except KeyError: - logger.error('Rate limit attempt for unknown task %s', - task_name, exc_info=True) - return {'error': 'unknown task'} - - state.consumer.reset_rate_limits() - - if not rate_limit: - logger.info('Rate limits disabled for tasks of type %s', task_name) - return {'ok': 'rate limit disabled successfully'} - - logger.info('New rate limit for tasks of type %s: %s.', - task_name, rate_limit) - return {'ok': 'new rate limit set successfully'} - - -@Panel.register -def time_limit(state, task_name=None, hard=None, soft=None, **kwargs): - try: - task = state.app.tasks[task_name] - except KeyError: - logger.error('Change time limit attempt for unknown task %s', - task_name, exc_info=True) - return {'error': 'unknown task'} - - task.soft_time_limit = soft - task.time_limit = hard - - logger.info('New time limits for tasks of type %s: soft=%s hard=%s', - task_name, soft, hard) - return {'ok': 'time limits set successfully'} - - -@Panel.register -def dump_schedule(state, safe=False, **kwargs): - - def prepare_entries(): - for waiting in state.consumer.timer.schedule.queue: - try: - arg0 = waiting.entry.args[0] - except (IndexError, TypeError): - continue - else: - if isinstance(arg0, Request): - yield {'eta': arg0.eta.isoformat() if arg0.eta else None, - 'priority': waiting.priority, - 'request': arg0.info(safe=safe)} - return list(prepare_entries()) - - -@Panel.register -def dump_reserved(state, safe=False, **kwargs): - reserved = worker_state.reserved_requests - worker_state.active_requests - if not reserved: - return [] - return [request.info(safe=safe) for request in reserved] - - -@Panel.register -def dump_active(state, safe=False, **kwargs): - return [request.info(safe=safe) - for request in worker_state.active_requests] - - -@Panel.register -def stats(state, **kwargs): - return state.consumer.controller.stats() - - -@Panel.register -def objgraph(state, num=200, max_depth=10, type='Request'): # pragma: no cover - try: - import objgraph - except ImportError: - raise ImportError('Requires the objgraph library') - print('Dumping graph for type %r' % (type, )) - with tempfile.NamedTemporaryFile(prefix='cobjg', - suffix='.png', delete=False) as fh: - objects = objgraph.by_type(type)[:num] - objgraph.show_backrefs( - objects, - max_depth=max_depth, highlight=lambda v: v in objects, - filename=fh.name, - ) - return {'filename': fh.name} - - -@Panel.register -def memsample(state, **kwargs): # pragma: no cover - from celery.utils.debug import sample_mem - return sample_mem() - - -@Panel.register -def memdump(state, samples=10, **kwargs): # pragma: no cover - from celery.utils.debug import memdump - out = io.StringIO() - memdump(file=out) - return out.getvalue() - - -@Panel.register -def clock(state, **kwargs): - return {'clock': state.app.clock.value} - - -@Panel.register -def dump_revoked(state, **kwargs): - return list(worker_state.revoked) - - -@Panel.register -def hello(state, from_node, revoked=None, **kwargs): - if from_node != state.hostname: - logger.info('sync with %s', from_node) - if revoked: - worker_state.revoked.update(revoked) - return {'revoked': worker_state.revoked._data, - 'clock': state.app.clock.forward()} - - -@Panel.register -def dump_tasks(state, taskinfoitems=None, **kwargs): - tasks = state.app.tasks - taskinfoitems = taskinfoitems or DEFAULT_TASK_INFO_ITEMS - - def _extract_info(task): - fields = dict((field, str(getattr(task, field, None))) - for field in taskinfoitems - if getattr(task, field, None) is not None) - if fields: - info = ['='.join(f) for f in items(fields)] - return '{0} [{1}]'.format(task.name, ' '.join(info)) - return task.name - - return [_extract_info(tasks[task]) for task in sorted(tasks)] - - -@Panel.register -def ping(state, **kwargs): - return {'ok': 'pong'} - - -@Panel.register -def pool_grow(state, n=1, **kwargs): - if state.consumer.controller.autoscaler: - state.consumer.controller.autoscaler.force_scale_up(n) - else: - state.consumer.pool.grow(n) - state.consumer._update_prefetch_count(n) - return {'ok': 'pool will grow'} - - -@Panel.register -def pool_shrink(state, n=1, **kwargs): - if state.consumer.controller.autoscaler: - state.consumer.controller.autoscaler.force_scale_down(n) - else: - state.consumer.pool.shrink(n) - state.consumer._update_prefetch_count(-n) - return {'ok': 'pool will shrink'} - - -@Panel.register -def pool_restart(state, modules=None, reload=False, reloader=None, **kwargs): - if state.app.conf.CELERYD_POOL_RESTARTS: - state.consumer.controller.reload(modules, reload, reloader=reloader) - return {'ok': 'reload started'} - else: - raise ValueError('Pool restarts not enabled') - - -@Panel.register -def autoscale(state, max=None, min=None): - autoscaler = state.consumer.controller.autoscaler - if autoscaler: - max_, min_ = autoscaler.update(max, min) - return {'ok': 'autoscale now min={0} max={1}'.format(max_, min_)} - raise ValueError('Autoscale not enabled') - - -@Panel.register -def shutdown(state, msg='Got shutdown from remote', **kwargs): - logger.warning(msg) - raise WorkerShutdown(msg) - - -@Panel.register -def add_consumer(state, queue, exchange=None, exchange_type=None, - routing_key=None, **options): - state.consumer.add_task_queue(queue, exchange, exchange_type, - routing_key, **options) - return {'ok': 'add consumer {0}'.format(queue)} - - -@Panel.register -def cancel_consumer(state, queue=None, **_): - state.consumer.cancel_task_queue(queue) - return {'ok': 'no longer consuming from {0}'.format(queue)} - - -@Panel.register -def active_queues(state): - """Return information about the queues a worker consumes from.""" - if state.consumer.task_consumer: - return [dict(queue.as_dict(recurse=True)) - for queue in state.consumer.task_consumer.queues] - return [] - - -def _wanted_config_key(key): - return key.isupper() and not key.startswith('__') - - -@Panel.register -def dump_conf(state, with_defaults=False, **kwargs): - return jsonify(state.app.conf.table(with_defaults=with_defaults), - keyfilter=_wanted_config_key, - unknown_type_filter=safe_repr) - - -@Panel.register -def election(state, id, topic, action=None, **kwargs): - if state.consumer.gossip: - state.consumer.gossip.election(id, topic, action) diff --git a/awx/lib/site-packages/celery/worker/heartbeat.py b/awx/lib/site-packages/celery/worker/heartbeat.py deleted file mode 100644 index cf46ab0c87..0000000000 --- a/awx/lib/site-packages/celery/worker/heartbeat.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.heartbeat - ~~~~~~~~~~~~~~~~~~~~~~~ - - This is the internal thread that sends heartbeat events - at regular intervals. - -""" -from __future__ import absolute_import - -from celery.utils.sysinfo import load_average - -from .state import SOFTWARE_INFO, active_requests, all_total_count - -__all__ = ['Heart'] - - -class Heart(object): - """Timer sending heartbeats at regular intervals. - - :param timer: Timer instance. - :param eventer: Event dispatcher used to send the event. - :keyword interval: Time in seconds between heartbeats. - Default is 2 seconds. - - """ - - def __init__(self, timer, eventer, interval=None): - self.timer = timer - self.eventer = eventer - self.interval = float(interval or 2.0) - self.tref = None - - # Make event dispatcher start/stop us when enabled/disabled. - self.eventer.on_enabled.add(self.start) - self.eventer.on_disabled.add(self.stop) - - def _send(self, event): - return self.eventer.send(event, freq=self.interval, - active=len(active_requests), - processed=all_total_count[0], - loadavg=load_average(), - **SOFTWARE_INFO) - - def start(self): - if self.eventer.enabled: - self._send('worker-online') - self.tref = self.timer.call_repeatedly( - self.interval, self._send, ('worker-heartbeat', ), - ) - - def stop(self): - if self.tref is not None: - self.timer.cancel(self.tref) - self.tref = None - if self.eventer.enabled: - self._send('worker-offline') diff --git a/awx/lib/site-packages/celery/worker/job.py b/awx/lib/site-packages/celery/worker/job.py deleted file mode 100644 index b277520e37..0000000000 --- a/awx/lib/site-packages/celery/worker/job.py +++ /dev/null @@ -1,587 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.job - ~~~~~~~~~~~~~~~~~ - - This module defines the :class:`Request` class, - which specifies how tasks are executed. - -""" -from __future__ import absolute_import, unicode_literals - -import logging -import socket -import sys - -from billiard.einfo import ExceptionInfo -from datetime import datetime -from weakref import ref - -from kombu.utils import kwdict, reprcall -from kombu.utils.encoding import safe_repr, safe_str - -from celery import signals -from celery.app.trace import trace_task, trace_task_ret -from celery.exceptions import ( - Ignore, TaskRevokedError, InvalidTaskError, - SoftTimeLimitExceeded, TimeLimitExceeded, - WorkerLostError, Terminated, Retry, Reject, -) -from celery.five import items, monotonic, string, string_t -from celery.platforms import signals as _signals -from celery.utils import fun_takes_kwargs -from celery.utils.functional import noop -from celery.utils.log import get_logger -from celery.utils.serialization import get_pickled_exception -from celery.utils.text import truncate -from celery.utils.timeutils import maybe_iso8601, timezone, maybe_make_aware - -from . import state - -__all__ = ['Request'] - -IS_PYPY = hasattr(sys, 'pypy_version_info') - -logger = get_logger(__name__) -debug, info, warn, error = (logger.debug, logger.info, - logger.warning, logger.error) -_does_info = False -_does_debug = False - -#: Max length of result representation -RESULT_MAXLEN = 128 - - -def __optimize__(): - # this is also called by celery.app.trace.setup_worker_optimizations - global _does_debug - global _does_info - _does_debug = logger.isEnabledFor(logging.DEBUG) - _does_info = logger.isEnabledFor(logging.INFO) -__optimize__() - -# Localize -tz_utc = timezone.utc -tz_or_local = timezone.tz_or_local -send_revoked = signals.task_revoked.send - -task_accepted = state.task_accepted -task_ready = state.task_ready -revoked_tasks = state.revoked - -NEEDS_KWDICT = sys.version_info <= (2, 6) - -#: Use when no message object passed to :class:`Request`. -DEFAULT_FIELDS = { - 'headers': None, - 'reply_to': None, - 'correlation_id': None, - 'delivery_info': { - 'exchange': None, - 'routing_key': None, - 'priority': 0, - 'redelivered': False, - }, -} - - -class Request(object): - """A request for task execution.""" - if not IS_PYPY: # pragma: no cover - __slots__ = ( - 'app', 'name', 'id', 'args', 'kwargs', 'on_ack', - 'hostname', 'eventer', 'connection_errors', 'task', 'eta', - 'expires', 'request_dict', 'acknowledged', 'on_reject', - 'utc', 'time_start', 'worker_pid', '_already_revoked', - '_terminate_on_ack', '_apply_result', - '_tzlocal', '__weakref__', '__dict__', - ) - - #: Format string used to log task success. - success_msg = """\ - Task %(name)s[%(id)s] succeeded in %(runtime)ss: %(return_value)s - """ - - #: Format string used to log task failure. - error_msg = """\ - Task %(name)s[%(id)s] %(description)s: %(exc)s - """ - - #: Format string used to log internal error. - internal_error_msg = """\ - Task %(name)s[%(id)s] %(description)s: %(exc)s - """ - - ignored_msg = """\ - Task %(name)s[%(id)s] %(description)s - """ - - rejected_msg = """\ - Task %(name)s[%(id)s] %(exc)s - """ - - #: Format string used to log task retry. - retry_msg = """Task %(name)s[%(id)s] retry: %(exc)s""" - - def __init__(self, body, on_ack=noop, - hostname=None, eventer=None, app=None, - connection_errors=None, request_dict=None, - message=None, task=None, on_reject=noop, **opts): - self.app = app - name = self.name = body['task'] - self.id = body['id'] - self.args = body.get('args', []) - self.kwargs = body.get('kwargs', {}) - try: - self.kwargs.items - except AttributeError: - raise InvalidTaskError( - 'Task keyword arguments is not a mapping') - if NEEDS_KWDICT: - self.kwargs = kwdict(self.kwargs) - eta = body.get('eta') - expires = body.get('expires') - utc = self.utc = body.get('utc', False) - self.on_ack = on_ack - self.on_reject = on_reject - self.hostname = hostname or socket.gethostname() - self.eventer = eventer - self.connection_errors = connection_errors or () - self.task = task or self.app.tasks[name] - self.acknowledged = self._already_revoked = False - self.time_start = self.worker_pid = self._terminate_on_ack = None - self._apply_result = None - self._tzlocal = None - - # timezone means the message is timezone-aware, and the only timezone - # supported at this point is UTC. - if eta is not None: - try: - self.eta = maybe_iso8601(eta) - except (AttributeError, ValueError, TypeError) as exc: - raise InvalidTaskError( - 'invalid eta value {0!r}: {1}'.format(eta, exc)) - if utc: - self.eta = maybe_make_aware(self.eta, self.tzlocal) - else: - self.eta = None - if expires is not None: - try: - self.expires = maybe_iso8601(expires) - except (AttributeError, ValueError, TypeError) as exc: - raise InvalidTaskError( - 'invalid expires value {0!r}: {1}'.format(expires, exc)) - if utc: - self.expires = maybe_make_aware(self.expires, self.tzlocal) - else: - self.expires = None - - if message: - delivery_info = message.delivery_info or {} - properties = message.properties or {} - body.update({ - 'headers': message.headers, - 'reply_to': properties.get('reply_to'), - 'correlation_id': properties.get('correlation_id'), - 'delivery_info': { - 'exchange': delivery_info.get('exchange'), - 'routing_key': delivery_info.get('routing_key'), - 'priority': delivery_info.get('priority'), - 'redelivered': delivery_info.get('redelivered'), - } - - }) - else: - body.update(DEFAULT_FIELDS) - self.request_dict = body - - @property - def delivery_info(self): - return self.request_dict['delivery_info'] - - def extend_with_default_kwargs(self): - """Extend the tasks keyword arguments with standard task arguments. - - Currently these are `logfile`, `loglevel`, `task_id`, - `task_name`, `task_retries`, and `delivery_info`. - - See :meth:`celery.task.base.Task.run` for more information. - - Magic keyword arguments are deprecated and will be removed - in version 4.0. - - """ - kwargs = dict(self.kwargs) - default_kwargs = {'logfile': None, # deprecated - 'loglevel': None, # deprecated - 'task_id': self.id, - 'task_name': self.name, - 'task_retries': self.request_dict.get('retries', 0), - 'task_is_eager': False, - 'delivery_info': self.delivery_info} - fun = self.task.run - supported_keys = fun_takes_kwargs(fun, default_kwargs) - extend_with = dict((key, val) for key, val in items(default_kwargs) - if key in supported_keys) - kwargs.update(extend_with) - return kwargs - - def execute_using_pool(self, pool, **kwargs): - """Used by the worker to send this task to the pool. - - :param pool: A :class:`celery.concurrency.base.TaskPool` instance. - - :raises celery.exceptions.TaskRevokedError: if the task was revoked - and ignored. - - """ - uuid = self.id - task = self.task - if self.revoked(): - raise TaskRevokedError(uuid) - - hostname = self.hostname - kwargs = self.kwargs - if task.accept_magic_kwargs: - kwargs = self.extend_with_default_kwargs() - request = self.request_dict - request.update({'hostname': hostname, 'is_eager': False, - 'delivery_info': self.delivery_info, - 'group': self.request_dict.get('taskset')}) - timeout, soft_timeout = request.get('timelimit', (None, None)) - timeout = timeout or task.time_limit - soft_timeout = soft_timeout or task.soft_time_limit - result = pool.apply_async( - trace_task_ret, - args=(self.name, uuid, self.args, kwargs, request), - accept_callback=self.on_accepted, - timeout_callback=self.on_timeout, - callback=self.on_success, - error_callback=self.on_failure, - soft_timeout=soft_timeout, - timeout=timeout, - correlation_id=uuid, - ) - # cannot create weakref to None - self._apply_result = ref(result) if result is not None else result - return result - - def execute(self, loglevel=None, logfile=None): - """Execute the task in a :func:`~celery.app.trace.trace_task`. - - :keyword loglevel: The loglevel used by the task. - :keyword logfile: The logfile used by the task. - - """ - if self.revoked(): - return - - # acknowledge task as being processed. - if not self.task.acks_late: - self.acknowledge() - - kwargs = self.kwargs - if self.task.accept_magic_kwargs: - kwargs = self.extend_with_default_kwargs() - request = self.request_dict - request.update({'loglevel': loglevel, 'logfile': logfile, - 'hostname': self.hostname, 'is_eager': False, - 'delivery_info': self.delivery_info}) - retval = trace_task(self.task, self.id, self.args, kwargs, request, - hostname=self.hostname, loader=self.app.loader, - app=self.app) - self.acknowledge() - return retval - - def maybe_expire(self): - """If expired, mark the task as revoked.""" - if self.expires: - now = datetime.now(tz_or_local(self.tzlocal) if self.utc else None) - if now > self.expires: - revoked_tasks.add(self.id) - return True - - def terminate(self, pool, signal=None): - signal = _signals.signum(signal or 'TERM') - if self.time_start: - pool.terminate_job(self.worker_pid, signal) - self._announce_revoked('terminated', True, signal, False) - else: - self._terminate_on_ack = pool, signal - if self._apply_result is not None: - obj = self._apply_result() # is a weakref - if obj is not None: - obj.terminate(signal) - - def _announce_revoked(self, reason, terminated, signum, expired): - task_ready(self) - self.send_event('task-revoked', - terminated=terminated, signum=signum, expired=expired) - if self.store_errors: - self.task.backend.mark_as_revoked(self.id, reason, request=self) - self.acknowledge() - self._already_revoked = True - send_revoked(self.task, request=self, - terminated=terminated, signum=signum, expired=expired) - - def revoked(self): - """If revoked, skip task and mark state.""" - expired = False - if self._already_revoked: - return True - if self.expires: - expired = self.maybe_expire() - if self.id in revoked_tasks: - info('Discarding revoked task: %s[%s]', self.name, self.id) - self._announce_revoked( - 'expired' if expired else 'revoked', False, None, expired, - ) - return True - return False - - def send_event(self, type, **fields): - if self.eventer and self.eventer.enabled: - self.eventer.send(type, uuid=self.id, **fields) - - def on_accepted(self, pid, time_accepted): - """Handler called when task is accepted by worker pool.""" - self.worker_pid = pid - self.time_start = time_accepted - task_accepted(self) - if not self.task.acks_late: - self.acknowledge() - self.send_event('task-started') - if _does_debug: - debug('Task accepted: %s[%s] pid:%r', self.name, self.id, pid) - if self._terminate_on_ack is not None: - self.terminate(*self._terminate_on_ack) - - def on_timeout(self, soft, timeout): - """Handler called if the task times out.""" - task_ready(self) - if soft: - warn('Soft time limit (%ss) exceeded for %s[%s]', - timeout, self.name, self.id) - exc = SoftTimeLimitExceeded(timeout) - else: - error('Hard time limit (%ss) exceeded for %s[%s]', - timeout, self.name, self.id) - exc = TimeLimitExceeded(timeout) - - if self.store_errors: - self.task.backend.mark_as_failure(self.id, exc, request=self) - - if self.task.acks_late: - self.acknowledge() - - def on_success(self, ret_value, now=None, nowfun=monotonic): - """Handler called if the task was successfully processed.""" - if isinstance(ret_value, ExceptionInfo): - if isinstance(ret_value.exception, ( - SystemExit, KeyboardInterrupt)): - raise ret_value.exception - return self.on_failure(ret_value) - task_ready(self) - - if self.task.acks_late: - self.acknowledge() - - if self.eventer and self.eventer.enabled: - now = nowfun() - runtime = self.time_start and (now - self.time_start) or 0 - self.send_event('task-succeeded', - result=safe_repr(ret_value), runtime=runtime) - - if _does_info: - now = now or nowfun() - runtime = self.time_start and (now - self.time_start) or 0 - info(self.success_msg.strip(), { - 'id': self.id, 'name': self.name, - 'return_value': self.repr_result(ret_value), - 'runtime': runtime}) - - def on_retry(self, exc_info): - """Handler called if the task should be retried.""" - if self.task.acks_late: - self.acknowledge() - - self.send_event('task-retried', - exception=safe_repr(exc_info.exception.exc), - traceback=safe_str(exc_info.traceback)) - - if _does_info: - info(self.retry_msg.strip(), - {'id': self.id, 'name': self.name, - 'exc': exc_info.exception}) - - def on_failure(self, exc_info): - """Handler called if the task raised an exception.""" - task_ready(self) - send_failed_event = True - - if not exc_info.internal: - exc = exc_info.exception - - if isinstance(exc, Retry): - return self.on_retry(exc_info) - - # These are special cases where the process would not have had - # time to write the result. - if self.store_errors: - if isinstance(exc, WorkerLostError): - self.task.backend.mark_as_failure( - self.id, exc, request=self, - ) - elif isinstance(exc, Terminated): - self._announce_revoked( - 'terminated', True, string(exc), False) - send_failed_event = False # already sent revoked event - # (acks_late) acknowledge after result stored. - if self.task.acks_late: - self.acknowledge() - self._log_error(exc_info, send_failed_event=send_failed_event) - - def _log_error(self, einfo, send_failed_event=True): - einfo.exception = get_pickled_exception(einfo.exception) - eobj = einfo.exception - exception, traceback, exc_info, internal, sargs, skwargs = ( - safe_repr(eobj), - safe_str(einfo.traceback), - einfo.exc_info, - einfo.internal, - safe_repr(self.args), - safe_repr(self.kwargs), - ) - task = self.task - if task.throws and isinstance(eobj, task.throws): - severity, exc_info = logging.INFO, None - description = 'raised expected' - else: - severity = logging.ERROR - description = 'raised unexpected' - format = self.error_msg - if send_failed_event: - self.send_event( - 'task-failed', exception=exception, traceback=traceback, - ) - - if internal: - if isinstance(einfo.exception, MemoryError): - raise MemoryError('Process got: %s' % (einfo.exception, )) - elif isinstance(einfo.exception, Reject): - format = self.rejected_msg - description = 'rejected' - severity = logging.WARN - exc_info = einfo - self.reject(requeue=einfo.exception.requeue) - elif isinstance(einfo.exception, Ignore): - format = self.ignored_msg - description = 'ignored' - severity = logging.INFO - exc_info = None - self.acknowledge() - else: - format = self.internal_error_msg - description = 'INTERNAL ERROR' - severity = logging.CRITICAL - - context = { - 'hostname': self.hostname, - 'id': self.id, - 'name': self.name, - 'exc': exception, - 'traceback': traceback, - 'args': sargs, - 'kwargs': skwargs, - 'description': description, - } - - logger.log(severity, format.strip(), context, - exc_info=exc_info, - extra={'data': {'id': self.id, - 'name': self.name, - 'args': sargs, - 'kwargs': skwargs, - 'hostname': self.hostname, - 'internal': internal}}) - - task.send_error_email(context, einfo.exception) - - def acknowledge(self): - """Acknowledge task.""" - if not self.acknowledged: - self.on_ack(logger, self.connection_errors) - self.acknowledged = True - - def reject(self, requeue=False): - if not self.acknowledged: - self.on_reject(logger, self.connection_errors, requeue) - self.acknowledged = True - - def repr_result(self, result, maxlen=RESULT_MAXLEN): - # 46 is the length needed to fit - # 'the quick brown fox jumps over the lazy dog' :) - if not isinstance(result, string_t): - result = safe_repr(result) - return truncate(result) if len(result) > maxlen else result - - def info(self, safe=False): - return {'id': self.id, - 'name': self.name, - 'args': self.args if safe else safe_repr(self.args), - 'kwargs': self.kwargs if safe else safe_repr(self.kwargs), - 'hostname': self.hostname, - 'time_start': self.time_start, - 'acknowledged': self.acknowledged, - 'delivery_info': self.delivery_info, - 'worker_pid': self.worker_pid} - - def __str__(self): - return '{0.name}[{0.id}]{1}{2}'.format(self, - ' eta:[{0}]'.format(self.eta) if self.eta else '', - ' expires:[{0}]'.format(self.expires) if self.expires else '') - shortinfo = __str__ - - def __repr__(self): - return '<{0} {1}: {2}>'.format( - type(self).__name__, self.id, - reprcall(self.name, self.args, self.kwargs)) - - @property - def tzlocal(self): - if self._tzlocal is None: - self._tzlocal = self.app.conf.CELERY_TIMEZONE - return self._tzlocal - - @property - def store_errors(self): - return (not self.task.ignore_result - or self.task.store_errors_even_if_ignored) - - @property - def task_id(self): - # XXX compat - return self.id - - @task_id.setter # noqa - def task_id(self, value): - self.id = value - - @property - def task_name(self): - # XXX compat - return self.name - - @task_name.setter # noqa - def task_name(self, value): - self.name = value - - @property - def reply_to(self): - # used by rpc backend when failures reported by parent process - return self.request_dict['reply_to'] - - @property - def correlation_id(self): - # used similarly to reply_to - return self.request_dict['correlation_id'] diff --git a/awx/lib/site-packages/celery/worker/loops.py b/awx/lib/site-packages/celery/worker/loops.py deleted file mode 100644 index 0891f51a6c..0000000000 --- a/awx/lib/site-packages/celery/worker/loops.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -celery.worker.loop -~~~~~~~~~~~~~~~~~~ - -The consumers highly-optimized inner loop. - -""" -from __future__ import absolute_import - -import socket - -from celery.bootsteps import RUN -from celery.exceptions import WorkerShutdown, WorkerTerminate, WorkerLostError -from celery.utils.log import get_logger - -from . import state - -__all__ = ['asynloop', 'synloop'] - -logger = get_logger(__name__) -error = logger.error - - -def asynloop(obj, connection, consumer, blueprint, hub, qos, - heartbeat, clock, hbrate=2.0, RUN=RUN): - """Non-blocking event loop consuming messages until connection is lost, - or shutdown is requested.""" - update_qos = qos.update - readers, writers = hub.readers, hub.writers - hbtick = connection.heartbeat_check - errors = connection.connection_errors - heartbeat = connection.get_heartbeat_interval() # negotiated - hub_add, hub_remove = hub.add, hub.remove - - on_task_received = obj.create_task_handler() - - if heartbeat and connection.supports_heartbeats: - hub.call_repeatedly(heartbeat / hbrate, hbtick, hbrate) - - consumer.callbacks = [on_task_received] - consumer.consume() - obj.on_ready() - obj.controller.register_with_event_loop(hub) - obj.register_with_event_loop(hub) - - # did_start_ok will verify that pool processes were able to start, - # but this will only work the first time we start, as - # maxtasksperchild will mess up metrics. - if not obj.restart_count and not obj.pool.did_start_ok(): - raise WorkerLostError('Could not start worker processes') - - # FIXME: Use loop.run_forever - # Tried and works, but no time to test properly before release. - hub.propagate_errors = errors - loop = hub.create_loop() - - try: - while blueprint.state == RUN and obj.connection: - # shutdown if signal handlers told us to. - if state.should_stop: - raise WorkerShutdown() - elif state.should_terminate: - raise WorkerTerminate() - - # We only update QoS when there is no more messages to read. - # This groups together qos calls, and makes sure that remote - # control commands will be prioritized over task messages. - if qos.prev != qos.value: - update_qos() - - try: - next(loop) - except StopIteration: - loop = hub.create_loop() - finally: - try: - hub.reset() - except Exception as exc: - error( - 'Error cleaning up after event loop: %r', exc, exc_info=1, - ) - - -def synloop(obj, connection, consumer, blueprint, hub, qos, - heartbeat, clock, hbrate=2.0, **kwargs): - """Fallback blocking event loop for transports that doesn't support AIO.""" - - on_task_received = obj.create_task_handler() - consumer.register_callback(on_task_received) - consumer.consume() - - obj.on_ready() - - while blueprint.state == RUN and obj.connection: - state.maybe_shutdown() - if qos.prev != qos.value: - qos.update() - try: - connection.drain_events(timeout=2.0) - except socket.timeout: - pass - except socket.error: - if blueprint.state == RUN: - raise diff --git a/awx/lib/site-packages/celery/worker/pidbox.py b/awx/lib/site-packages/celery/worker/pidbox.py deleted file mode 100644 index 99c7a1a396..0000000000 --- a/awx/lib/site-packages/celery/worker/pidbox.py +++ /dev/null @@ -1,115 +0,0 @@ -from __future__ import absolute_import - -import socket -import threading - -from kombu.common import ignore_errors -from kombu.utils.encoding import safe_str - -from celery.datastructures import AttributeDict -from celery.utils.log import get_logger - -from . import control - -__all__ = ['Pidbox', 'gPidbox'] - -logger = get_logger(__name__) -debug, error, info = logger.debug, logger.error, logger.info - - -class Pidbox(object): - consumer = None - - def __init__(self, c): - self.c = c - self.hostname = c.hostname - self.node = c.app.control.mailbox.Node( - safe_str(c.hostname), - handlers=control.Panel.data, - state=AttributeDict(app=c.app, hostname=c.hostname, consumer=c), - ) - self._forward_clock = self.c.app.clock.forward - - def on_message(self, body, message): - self._forward_clock() # just increase clock as clients usually don't - # have a valid clock to adjust with. - try: - self.node.handle_message(body, message) - except KeyError as exc: - error('No such control command: %s', exc) - except Exception as exc: - error('Control command error: %r', exc, exc_info=True) - self.reset() - - def start(self, c): - self.node.channel = c.connection.channel() - self.consumer = self.node.listen(callback=self.on_message) - self.consumer.on_decode_error = c.on_decode_error - - def on_stop(self): - pass - - def stop(self, c): - self.on_stop() - self.consumer = self._close_channel(c) - - def reset(self): - """Sets up the process mailbox.""" - self.stop(self.c) - self.start(self.c) - - def _close_channel(self, c): - if self.node and self.node.channel: - ignore_errors(c, self.node.channel.close) - - def shutdown(self, c): - self.on_stop() - if self.consumer: - debug('Cancelling broadcast consumer...') - ignore_errors(c, self.consumer.cancel) - self.stop(self.c) - - -class gPidbox(Pidbox): - _node_shutdown = None - _node_stopped = None - _resets = 0 - - def start(self, c): - c.pool.spawn_n(self.loop, c) - - def on_stop(self): - if self._node_stopped: - self._node_shutdown.set() - debug('Waiting for broadcast thread to shutdown...') - self._node_stopped.wait() - self._node_stopped = self._node_shutdown = None - - def reset(self): - self._resets += 1 - - def _do_reset(self, c, connection): - self._close_channel(c) - self.node.channel = connection.channel() - self.consumer = self.node.listen(callback=self.on_message) - self.consumer.consume() - - def loop(self, c): - resets = [self._resets] - shutdown = self._node_shutdown = threading.Event() - stopped = self._node_stopped = threading.Event() - try: - with c.connect() as connection: - - info('pidbox: Connected to %s.', connection.as_uri()) - self._do_reset(c, connection) - while not shutdown.is_set() and c.connection: - if resets[0] < self._resets: - resets[0] += 1 - self._do_reset(c, connection) - try: - connection.drain_events(timeout=1.0) - except socket.timeout: - pass - finally: - stopped.set() diff --git a/awx/lib/site-packages/celery/worker/state.py b/awx/lib/site-packages/celery/worker/state.py deleted file mode 100644 index 8abaa5d738..0000000000 --- a/awx/lib/site-packages/celery/worker/state.py +++ /dev/null @@ -1,238 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.state - ~~~~~~~~~~~~~~~~~~~ - - Internal worker state (global) - - This includes the currently active and reserved tasks, - statistics, and revoked tasks. - -""" -from __future__ import absolute_import - -import os -import sys -import platform -import shelve -import zlib - -from kombu.serialization import pickle, pickle_protocol -from kombu.utils import cached_property - -from celery import __version__ -from celery.datastructures import LimitedSet -from celery.exceptions import WorkerShutdown, WorkerTerminate -from celery.five import Counter - -__all__ = ['SOFTWARE_INFO', 'reserved_requests', 'active_requests', - 'total_count', 'revoked', 'task_reserved', 'maybe_shutdown', - 'task_accepted', 'task_ready', 'task_reserved', 'task_ready', - 'Persistent'] - -#: Worker software/platform information. -SOFTWARE_INFO = {'sw_ident': 'py-celery', - 'sw_ver': __version__, - 'sw_sys': platform.system()} - -#: maximum number of revokes to keep in memory. -REVOKES_MAX = 50000 - -#: how many seconds a revoke will be active before -#: being expired when the max limit has been exceeded. -REVOKE_EXPIRES = 10800 - -#: set of all reserved :class:`~celery.worker.job.Request`'s. -reserved_requests = set() - -#: set of currently active :class:`~celery.worker.job.Request`'s. -active_requests = set() - -#: count of tasks accepted by the worker, sorted by type. -total_count = Counter() - -#: count of all tasks accepted by the worker -all_total_count = [0] - -#: the list of currently revoked tasks. Persistent if statedb set. -revoked = LimitedSet(maxlen=REVOKES_MAX, expires=REVOKE_EXPIRES) - -#: Update global state when a task has been reserved. -task_reserved = reserved_requests.add - -should_stop = False -should_terminate = False - - -def maybe_shutdown(): - if should_stop: - raise WorkerShutdown() - elif should_terminate: - raise WorkerTerminate() - - -def task_accepted(request, _all_total_count=all_total_count): - """Updates global state when a task has been accepted.""" - active_requests.add(request) - total_count[request.name] += 1 - all_total_count[0] += 1 - - -def task_ready(request): - """Updates global state when a task is ready.""" - active_requests.discard(request) - reserved_requests.discard(request) - - -C_BENCH = os.environ.get('C_BENCH') or os.environ.get('CELERY_BENCH') -C_BENCH_EVERY = int(os.environ.get('C_BENCH_EVERY') or - os.environ.get('CELERY_BENCH_EVERY') or 1000) -if C_BENCH: # pragma: no cover - import atexit - - from billiard import current_process - from celery.five import monotonic - from celery.utils.debug import memdump, sample_mem - - all_count = 0 - bench_first = None - bench_start = None - bench_last = None - bench_every = C_BENCH_EVERY - bench_sample = [] - __reserved = task_reserved - __ready = task_ready - - if current_process()._name == 'MainProcess': - @atexit.register - def on_shutdown(): - if bench_first is not None and bench_last is not None: - print('- Time spent in benchmark: {0!r}'.format( - bench_last - bench_first)) - print('- Avg: {0}'.format( - sum(bench_sample) / len(bench_sample))) - memdump() - - def task_reserved(request): # noqa - global bench_start - global bench_first - now = None - if bench_start is None: - bench_start = now = monotonic() - if bench_first is None: - bench_first = now - - return __reserved(request) - - def task_ready(request): # noqa - global all_count - global bench_start - global bench_last - all_count += 1 - if not all_count % bench_every: - now = monotonic() - diff = now - bench_start - print('- Time spent processing {0} tasks (since first ' - 'task received): ~{1:.4f}s\n'.format(bench_every, diff)) - sys.stdout.flush() - bench_start = bench_last = now - bench_sample.append(diff) - sample_mem() - return __ready(request) - - -class Persistent(object): - """This is the persistent data stored by the worker when - :option:`--statedb` is enabled. - - It currently only stores revoked task id's. - - """ - storage = shelve - protocol = pickle_protocol - compress = zlib.compress - decompress = zlib.decompress - _is_open = False - - def __init__(self, state, filename, clock=None): - self.state = state - self.filename = filename - self.clock = clock - self.merge() - - def open(self): - return self.storage.open( - self.filename, protocol=self.protocol, writeback=True, - ) - - def merge(self): - self._merge_with(self.db) - - def sync(self): - self._sync_with(self.db) - self.db.sync() - - def close(self): - if self._is_open: - self.db.close() - self._is_open = False - - def save(self): - self.sync() - self.close() - - def _merge_with(self, d): - self._merge_revoked(d) - self._merge_clock(d) - return d - - def _sync_with(self, d): - self._revoked_tasks.purge() - d.update( - __proto__=3, - zrevoked=self.compress(self._dumps(self._revoked_tasks)), - clock=self.clock.forward() if self.clock else 0, - ) - return d - - def _merge_clock(self, d): - if self.clock: - d['clock'] = self.clock.adjust(d.get('clock') or 0) - - def _merge_revoked(self, d): - try: - self._merge_revoked_v3(d['zrevoked']) - except KeyError: - try: - self._merge_revoked_v2(d.pop('revoked')) - except KeyError: - pass - # purge expired items at boot - self._revoked_tasks.purge() - - def _merge_revoked_v3(self, zrevoked): - if zrevoked: - self._revoked_tasks.update(pickle.loads(self.decompress(zrevoked))) - - def _merge_revoked_v2(self, saved): - if not isinstance(saved, LimitedSet): - # (pre 3.0.18) used to be stored as a dict - return self._merge_revoked_v1(saved) - self._revoked_tasks.update(saved) - - def _merge_revoked_v1(self, saved): - add = self._revoked_tasks.add - for item in saved: - add(item) - - def _dumps(self, obj): - return pickle.dumps(obj, protocol=self.protocol) - - @property - def _revoked_tasks(self): - return self.state.revoked - - @cached_property - def db(self): - self._is_open = True - return self.open() diff --git a/awx/lib/site-packages/celery/worker/strategy.py b/awx/lib/site-packages/celery/worker/strategy.py deleted file mode 100644 index 0b0d327c31..0000000000 --- a/awx/lib/site-packages/celery/worker/strategy.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.worker.strategy - ~~~~~~~~~~~~~~~~~~~~~~ - - Task execution strategy (optimization). - -""" -from __future__ import absolute_import - -import logging - -from kombu.async.timer import to_timestamp -from kombu.utils.encoding import safe_repr - -from celery.utils.log import get_logger -from celery.utils.timeutils import timezone - -from .job import Request -from .state import task_reserved - -__all__ = ['default'] - -logger = get_logger(__name__) - - -def default(task, app, consumer, - info=logger.info, error=logger.error, task_reserved=task_reserved, - to_system_tz=timezone.to_system): - hostname = consumer.hostname - eventer = consumer.event_dispatcher - Req = Request - connection_errors = consumer.connection_errors - _does_info = logger.isEnabledFor(logging.INFO) - events = eventer and eventer.enabled - send_event = eventer.send - call_at = consumer.timer.call_at - apply_eta_task = consumer.apply_eta_task - rate_limits_enabled = not consumer.disable_rate_limits - bucket = consumer.task_buckets[task.name] - handle = consumer.on_task_request - limit_task = consumer._limit_task - - def task_message_handler(message, body, ack, reject, callbacks, - to_timestamp=to_timestamp): - req = Req(body, on_ack=ack, on_reject=reject, - app=app, hostname=hostname, - eventer=eventer, task=task, - connection_errors=connection_errors, - message=message) - if req.revoked(): - return - - if _does_info: - info('Received task: %s', req) - - if events: - send_event( - 'task-received', - uuid=req.id, name=req.name, - args=safe_repr(req.args), kwargs=safe_repr(req.kwargs), - retries=req.request_dict.get('retries', 0), - eta=req.eta and req.eta.isoformat(), - expires=req.expires and req.expires.isoformat(), - ) - - if req.eta: - try: - if req.utc: - eta = to_timestamp(to_system_tz(req.eta)) - else: - eta = to_timestamp(req.eta, timezone.local) - except OverflowError as exc: - error("Couldn't convert eta %s to timestamp: %r. Task: %r", - req.eta, exc, req.info(safe=True), exc_info=True) - req.acknowledge() - else: - consumer.qos.increment_eventually() - call_at(eta, apply_eta_task, (req, ), priority=6) - else: - if rate_limits_enabled: - if bucket: - return limit_task(req, bucket, 1) - task_reserved(req) - if callbacks: - [callback() for callback in callbacks] - handle(req) - - return task_message_handler diff --git a/awx/lib/site-packages/cinderclient/__init__.py b/awx/lib/site-packages/cinderclient/__init__.py deleted file mode 100644 index 29e35c8e1a..0000000000 --- a/awx/lib/site-packages/cinderclient/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -__all__ = ['__version__'] - -import pbr.version - -version_info = pbr.version.VersionInfo('python-cinderclient') -# We have a circular import problem when we first run python setup.py sdist -# It's harmless, so deflect it. -try: - __version__ = version_info.version_string() -except AttributeError: - __version__ = None diff --git a/awx/lib/site-packages/cinderclient/auth_plugin.py b/awx/lib/site-packages/cinderclient/auth_plugin.py deleted file mode 100644 index 2101b93bf6..0000000000 --- a/awx/lib/site-packages/cinderclient/auth_plugin.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 Spanish National Research Council. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import pkg_resources - -import six - -from cinderclient import exceptions -from cinderclient import utils - - -logger = logging.getLogger(__name__) - - -_discovered_plugins = {} - - -def discover_auth_systems(): - """Discover the available auth-systems. - - This won't take into account the old style auth-systems. - """ - ep_name = 'openstack.client.auth_plugin' - for ep in pkg_resources.iter_entry_points(ep_name): - try: - auth_plugin = ep.load() - except (ImportError, pkg_resources.UnknownExtra, AttributeError) as e: - logger.debug("ERROR: Cannot load auth plugin %s" % ep.name) - logger.debug(e, exc_info=1) - else: - _discovered_plugins[ep.name] = auth_plugin - - -def load_auth_system_opts(parser): - """Load options needed by the available auth-systems into a parser. - - This function will try to populate the parser with options from the - available plugins. - """ - for name, auth_plugin in six.iteritems(_discovered_plugins): - add_opts_fn = getattr(auth_plugin, "add_opts", None) - if add_opts_fn: - group = parser.add_argument_group("Auth-system '%s' options" % - name) - add_opts_fn(group) - - -def load_plugin(auth_system): - if auth_system in _discovered_plugins: - return _discovered_plugins[auth_system]() - - # NOTE(aloga): If we arrive here, the plugin will be an old-style one, - # so we have to create a fake AuthPlugin for it. - return DeprecatedAuthPlugin(auth_system) - - -class BaseAuthPlugin(object): - """Base class for authentication plugins. - - An authentication plugin needs to override at least the authenticate - method to be a valid plugin. - """ - def __init__(self): - self.opts = {} - - def get_auth_url(self): - """Return the auth url for the plugin (if any).""" - return None - - @staticmethod - def add_opts(parser): - """Populate and return the parser with the options for this plugin. - - If the plugin does not need any options, it should return the same - parser untouched. - """ - return parser - - def parse_opts(self, args): - """Parse the actual auth-system options if any. - - This method is expected to populate the attribute self.opts with a - dict containing the options and values needed to make authentication. - If the dict is empty, the client should assume that it needs the same - options as the 'keystone' auth system (i.e. os_username and - os_password). - - Returns the self.opts dict. - """ - return self.opts - - def authenticate(self, cls, auth_url): - """Authenticate using plugin defined method.""" - raise exceptions.AuthSystemNotFound(self.auth_system) - - -class DeprecatedAuthPlugin(object): - """Class to mimic the AuthPlugin class for deprecated auth systems. - - Old auth systems only define two entry points: openstack.client.auth_url - and openstack.client.authenticate. This class will load those entry points - into a class similar to a valid AuthPlugin. - """ - def __init__(self, auth_system): - self.auth_system = auth_system - - def authenticate(cls, auth_url): - raise exceptions.AuthSystemNotFound(self.auth_system) - - self.opts = {} - - self.get_auth_url = lambda: None - self.authenticate = authenticate - - self._load_endpoints() - - def _load_endpoints(self): - ep_name = 'openstack.client.auth_url' - fn = utils._load_entry_point(ep_name, name=self.auth_system) - if fn: - self.get_auth_url = fn - - ep_name = 'openstack.client.authenticate' - fn = utils._load_entry_point(ep_name, name=self.auth_system) - if fn: - self.authenticate = fn - - def parse_opts(self, args): - return self.opts diff --git a/awx/lib/site-packages/cinderclient/base.py b/awx/lib/site-packages/cinderclient/base.py deleted file mode 100644 index 5274f24ceb..0000000000 --- a/awx/lib/site-packages/cinderclient/base.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright (c) 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" -import abc -import contextlib -import hashlib -import os - -import six - -from cinderclient import exceptions -from cinderclient.openstack.common.apiclient import base as common_base -from cinderclient import utils - - -Resource = common_base.Resource - - -# Python 2.4 compat -try: - all -except NameError: - def all(iterable): - return True not in (not x for x in iterable) - - -def getid(obj): - """ - Abstracts the common pattern of allowing both an object or an object's ID - as a parameter when dealing with relationships. - """ - try: - return obj.id - except AttributeError: - return obj - - -class Manager(utils.HookableMixin): - """ - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, api): - self.api = api - - def _list(self, url, response_key, obj_class=None, body=None): - resp = None - if body: - resp, body = self.api.client.post(url, body=body) - else: - resp, body = self.api.client.get(url) - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - if isinstance(data, dict): - try: - data = data['values'] - except KeyError: - pass - - with self.completion_cache('human_id', obj_class, mode="w"): - with self.completion_cache('uuid', obj_class, mode="w"): - return [obj_class(self, res, loaded=True) - for res in data if res] - - @contextlib.contextmanager - def completion_cache(self, cache_type, obj_class, mode): - """ - The completion cache store items that can be used for bash - autocompletion, like UUIDs or human-friendly IDs. - - A resource listing will clear and repopulate the cache. - - A resource create will append to the cache. - - Delete is not handled because listings are assumed to be performed - often enough to keep the cache reasonably up-to-date. - """ - base_dir = utils.env('CINDERCLIENT_UUID_CACHE_DIR', - default="~/.cinderclient") - - # NOTE(sirp): Keep separate UUID caches for each username + endpoint - # pair - username = utils.env('OS_USERNAME', 'CINDER_USERNAME') - url = utils.env('OS_URL', 'CINDER_URL') - uniqifier = hashlib.md5(username.encode('utf-8') + - url.encode('utf-8')).hexdigest() - - cache_dir = os.path.expanduser(os.path.join(base_dir, uniqifier)) - - try: - os.makedirs(cache_dir, 0o755) - except OSError: - # NOTE(kiall): This is typically either permission denied while - # attempting to create the directory, or the directory - # already exists. Either way, don't fail. - pass - - resource = obj_class.__name__.lower() - filename = "%s-%s-cache" % (resource, cache_type.replace('_', '-')) - path = os.path.join(cache_dir, filename) - - cache_attr = "_%s_cache" % cache_type - - try: - setattr(self, cache_attr, open(path, mode)) - except IOError: - # NOTE(kiall): This is typically a permission denied while - # attempting to write the cache file. - pass - - try: - yield - finally: - cache = getattr(self, cache_attr, None) - if cache: - cache.close() - delattr(self, cache_attr) - - def write_to_completion_cache(self, cache_type, val): - cache = getattr(self, "_%s_cache" % cache_type, None) - if cache: - cache.write("%s\n" % val) - - def _get(self, url, response_key=None): - resp, body = self.api.client.get(url) - if response_key: - return self.resource_class(self, body[response_key], loaded=True) - else: - return self.resource_class(self, body, loaded=True) - - def _create(self, url, body, response_key, return_raw=False, **kwargs): - self.run_hooks('modify_body_for_create', body, **kwargs) - resp, body = self.api.client.post(url, body=body) - if return_raw: - return body[response_key] - - with self.completion_cache('human_id', self.resource_class, mode="a"): - with self.completion_cache('uuid', self.resource_class, mode="a"): - return self.resource_class(self, body[response_key]) - - def _delete(self, url): - resp, body = self.api.client.delete(url) - - def _update(self, url, body, **kwargs): - self.run_hooks('modify_body_for_update', body, **kwargs) - resp, body = self.api.client.put(url, body=body) - return body - - -class ManagerWithFind(six.with_metaclass(abc.ABCMeta, Manager)): - """ - Like a `Manager`, but with additional `find()`/`findall()` methods. - """ - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """ - Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - matches = self.findall(**kwargs) - num_matches = len(matches) - if num_matches == 0: - msg = "No %s matching %s." % (self.resource_class.__name__, kwargs) - raise exceptions.NotFound(404, msg) - elif num_matches > 1: - raise exceptions.NoUniqueMatch - else: - return matches[0] - - def findall(self, **kwargs): - """ - Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - found = [] - searches = list(kwargs.items()) - - # Want to search for all tenants here so that when attempting to delete - # that a user like admin doesn't get a failure when trying to delete - # another tenant's volume by name. - for obj in self.list(search_opts={'all_tenants': 1}): - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - found.append(obj) - except AttributeError: - continue - - return found diff --git a/awx/lib/site-packages/cinderclient/client.py b/awx/lib/site-packages/cinderclient/client.py deleted file mode 100644 index a436841cc1..0000000000 --- a/awx/lib/site-packages/cinderclient/client.py +++ /dev/null @@ -1,537 +0,0 @@ -# Copyright (c) 2011 OpenStack Foundation -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Piston Cloud Computing, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -from __future__ import print_function - -import logging - -from keystoneclient import access -from keystoneclient import adapter -from keystoneclient.auth.identity import base -import requests - -from cinderclient import exceptions -from cinderclient.openstack.common import strutils -from cinderclient import utils - - -try: - import urlparse -except ImportError: - import urllib.parse as urlparse - -try: - from eventlet import sleep -except ImportError: - from time import sleep - -try: - import json -except ImportError: - import simplejson as json - -# Python 2.5 compat fix -if not hasattr(urlparse, 'parse_qsl'): - import cgi - urlparse.parse_qsl = cgi.parse_qsl - -_VALID_VERSIONS = ['v1', 'v2'] - - -def get_volume_api_from_url(url): - scheme, netloc, path, query, frag = urlparse.urlsplit(url) - components = path.split("/") - - for version in _VALID_VERSIONS: - if version in components: - return version[1:] - - msg = "Invalid client version '%s'. must be one of: %s" % ( - (version, ', '.join(valid_versions))) - raise exceptions.UnsupportedVersion(msg) - - -class SessionClient(adapter.LegacyJsonAdapter): - - def __init__(self, **kwargs): - kwargs.setdefault('user_agent', 'python-cinderclient') - kwargs.setdefault('service_type', 'volume') - super(SessionClient, self).__init__(**kwargs) - - def request(self, *args, **kwargs): - kwargs.setdefault('authenticated', False) - return super(SessionClient, self).request(*args, **kwargs) - - def _cs_request(self, url, method, **kwargs): - # this function is mostly redundant but makes compatibility easier - kwargs.setdefault('authenticated', True) - return self.request(url, method, **kwargs) - - def get(self, url, **kwargs): - return self._cs_request(url, 'GET', **kwargs) - - def post(self, url, **kwargs): - return self._cs_request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - return self._cs_request(url, 'PUT', **kwargs) - - def delete(self, url, **kwargs): - return self._cs_request(url, 'DELETE', **kwargs) - - def _invalidate(self, auth=None): - # NOTE(jamielennox): This is being implemented in keystoneclient - return self.session.invalidate(auth or self.auth) - - def _get_token(self, auth=None): - # NOTE(jamielennox): This is being implemented in keystoneclient - return self.session.get_token(auth or self.auth) - - def _get_endpoint(self, auth=None, **kwargs): - # NOTE(jamielennox): This is being implemented in keystoneclient - if self.service_type: - kwargs.setdefault('service_type', self.service_type) - if self.service_name: - kwargs.setdefault('service_name', self.service_name) - if self.interface: - kwargs.setdefault('interface', self.interface) - if self.region_name: - kwargs.setdefault('region_name', self.region_name) - return self.session.get_endpoint(auth or self.auth, **kwargs) - - def get_volume_api_version_from_endpoint(self): - return get_volume_api_from_url(self._get_endpoint()) - - def authenticate(self, auth=None): - self._invalidate(auth) - return self._get_token(auth) - - @property - def service_catalog(self): - # NOTE(jamielennox): This is ugly and should be deprecated. - auth = self.auth or self.session.auth - - if isinstance(auth, base.BaseIdentityPlugin): - return auth.get_access(self.session).service_catalog - - raise AttributeError('There is no service catalog for this type of ' - 'auth plugin.') - - -class HTTPClient(object): - - USER_AGENT = 'python-cinderclient' - - def __init__(self, user, password, projectid, auth_url=None, - insecure=False, timeout=None, tenant_id=None, - proxy_tenant_id=None, proxy_token=None, region_name=None, - endpoint_type='publicURL', service_type=None, - service_name=None, volume_service_name=None, retries=None, - http_log_debug=False, cacert=None, - auth_system='keystone', auth_plugin=None): - self.user = user - self.password = password - self.projectid = projectid - self.tenant_id = tenant_id - - if auth_system and auth_system != 'keystone' and not auth_plugin: - raise exceptions.AuthSystemNotFound(auth_system) - - if not auth_url and auth_system and auth_system != 'keystone': - auth_url = auth_plugin.get_auth_url() - if not auth_url: - raise exceptions.EndpointNotFound() - - self.auth_url = auth_url.rstrip('/') - self.version = 'v1' - self.region_name = region_name - self.endpoint_type = endpoint_type - self.service_type = service_type - self.service_name = service_name - self.volume_service_name = volume_service_name - self.retries = int(retries or 0) - self.http_log_debug = http_log_debug - - self.management_url = None - self.auth_token = None - self.proxy_token = proxy_token - self.proxy_tenant_id = proxy_tenant_id - self.timeout = timeout - - if insecure: - self.verify_cert = False - else: - if cacert: - self.verify_cert = cacert - else: - self.verify_cert = True - - self.auth_system = auth_system - self.auth_plugin = auth_plugin - - self._logger = logging.getLogger(__name__) - - def http_log_req(self, args, kwargs): - if not self.http_log_debug: - return - - string_parts = ['curl -i'] - for element in args: - if element in ('GET', 'POST', 'DELETE', 'PUT'): - string_parts.append(' -X %s' % element) - else: - string_parts.append(' %s' % element) - - for element in kwargs['headers']: - header = ' -H "%s: %s"' % (element, kwargs['headers'][element]) - string_parts.append(header) - - if 'data' in kwargs: - if "password" in kwargs['data']: - data = strutils.mask_password(kwargs['data']) - else: - data = kwargs['data'] - string_parts.append(" -d '%s'" % (data)) - self._logger.debug("\nREQ: %s\n" % "".join(string_parts)) - - def http_log_resp(self, resp): - if not self.http_log_debug: - return - self._logger.debug( - "RESP: [%s] %s\nRESP BODY: %s\n", - resp.status_code, - resp.headers, - resp.text) - - def request(self, url, method, **kwargs): - kwargs.setdefault('headers', kwargs.get('headers', {})) - kwargs['headers']['User-Agent'] = self.USER_AGENT - kwargs['headers']['Accept'] = 'application/json' - if 'body' in kwargs: - kwargs['headers']['Content-Type'] = 'application/json' - kwargs['data'] = json.dumps(kwargs['body']) - del kwargs['body'] - - if self.timeout: - kwargs.setdefault('timeout', self.timeout) - self.http_log_req((url, method,), kwargs) - resp = requests.request( - method, - url, - verify=self.verify_cert, - **kwargs) - self.http_log_resp(resp) - - if resp.text: - try: - body = json.loads(resp.text) - except ValueError: - pass - body = None - else: - body = None - - if resp.status_code >= 400: - raise exceptions.from_response(resp, body) - - return resp, body - - def _cs_request(self, url, method, **kwargs): - auth_attempts = 0 - attempts = 0 - backoff = 1 - while True: - attempts += 1 - if not self.management_url or not self.auth_token: - self.authenticate() - kwargs.setdefault('headers', {})['X-Auth-Token'] = self.auth_token - if self.projectid: - kwargs['headers']['X-Auth-Project-Id'] = self.projectid - try: - resp, body = self.request(self.management_url + url, method, - **kwargs) - return resp, body - except exceptions.BadRequest as e: - if attempts > self.retries: - raise - except exceptions.Unauthorized: - if auth_attempts > 0: - raise - self._logger.debug("Unauthorized, reauthenticating.") - self.management_url = self.auth_token = None - # First reauth. Discount this attempt. - attempts -= 1 - auth_attempts += 1 - continue - except exceptions.ClientException as e: - if attempts > self.retries: - raise - if 500 <= e.code <= 599: - pass - else: - raise - except requests.exceptions.ConnectionError as e: - self._logger.debug("Connection error: %s" % e) - if attempts > self.retries: - msg = 'Unable to establish connection: %s' % e - raise exceptions.ConnectionError(msg) - self._logger.debug( - "Failed attempt(%s of %s), retrying in %s seconds" % - (attempts, self.retries, backoff)) - sleep(backoff) - backoff *= 2 - - def get(self, url, **kwargs): - return self._cs_request(url, 'GET', **kwargs) - - def post(self, url, **kwargs): - return self._cs_request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - return self._cs_request(url, 'PUT', **kwargs) - - def delete(self, url, **kwargs): - return self._cs_request(url, 'DELETE', **kwargs) - - def get_volume_api_version_from_endpoint(self): - return get_volume_api_from_url(self.management_url) - - def _extract_service_catalog(self, url, resp, body, extract_token=True): - """See what the auth service told us and process the response. - We may get redirected to another site, fail or actually get - back a service catalog with a token and our endpoints. - """ - - if resp.status_code == 200: # content must always present - try: - self.auth_url = url - self.auth_ref = access.AccessInfo.factory(resp, body) - self.service_catalog = self.auth_ref.service_catalog - - if extract_token: - self.auth_token = self.auth_ref.auth_token - - management_url = self.service_catalog.url_for( - region_name=self.region_name, - endpoint_type=self.endpoint_type, - service_type=self.service_type) - self.management_url = management_url.rstrip('/') - return None - except exceptions.AmbiguousEndpoints: - print("Found more than one valid endpoint. Use a more " - "restrictive filter") - raise - except KeyError: - raise exceptions.AuthorizationFailure() - except exceptions.EndpointNotFound: - print("Could not find any suitable endpoint. Correct region?") - raise - - elif resp.status_code == 305: - return resp['location'] - else: - raise exceptions.from_response(resp, body) - - def _fetch_endpoints_from_auth(self, url): - """We have a token, but don't know the final endpoint for - the region. We have to go back to the auth service and - ask again. This request requires an admin-level token - to work. The proxy token supplied could be from a low-level enduser. - - We can't get this from the keystone service endpoint, we have to use - the admin endpoint. - - This will overwrite our admin token with the user token. - """ - - # GET ...:5001/v2.0/tokens/#####/endpoints - url = '/'.join([url, 'tokens', '%s?belongsTo=%s' - % (self.proxy_token, self.proxy_tenant_id)]) - self._logger.debug("Using Endpoint URL: %s" % url) - resp, body = self.request(url, "GET", - headers={'X-Auth-Token': self.auth_token}) - return self._extract_service_catalog(url, resp, body, - extract_token=False) - - def authenticate(self): - magic_tuple = urlparse.urlsplit(self.auth_url) - scheme, netloc, path, query, frag = magic_tuple - port = magic_tuple.port - if port is None: - port = 80 - path_parts = path.split('/') - for part in path_parts: - if len(part) > 0 and part[0] == 'v': - self.version = part - break - - # TODO(sandy): Assume admin endpoint is 35357 for now. - # Ideally this is going to have to be provided by the service catalog. - new_netloc = netloc.replace(':%d' % port, ':%d' % (35357,)) - admin_url = urlparse.urlunsplit((scheme, new_netloc, - path, query, frag)) - - auth_url = self.auth_url - if self.version == "v2.0": - while auth_url: - if not self.auth_system or self.auth_system == 'keystone': - auth_url = self._v2_auth(auth_url) - else: - auth_url = self._plugin_auth(auth_url) - - # Are we acting on behalf of another user via an - # existing token? If so, our actual endpoints may - # be different than that of the admin token. - if self.proxy_token: - self._fetch_endpoints_from_auth(admin_url) - # Since keystone no longer returns the user token - # with the endpoints any more, we need to replace - # our service account token with the user token. - self.auth_token = self.proxy_token - else: - try: - while auth_url: - auth_url = self._v1_auth(auth_url) - # In some configurations cinder makes redirection to - # v2.0 keystone endpoint. Also, new location does not contain - # real endpoint, only hostname and port. - except exceptions.AuthorizationFailure: - if auth_url.find('v2.0') < 0: - auth_url = auth_url + '/v2.0' - self._v2_auth(auth_url) - - def _v1_auth(self, url): - if self.proxy_token: - raise exceptions.NoTokenLookupException() - - headers = {'X-Auth-User': self.user, - 'X-Auth-Key': self.password} - if self.projectid: - headers['X-Auth-Project-Id'] = self.projectid - - resp, body = self.request(url, 'GET', headers=headers) - if resp.status_code in (200, 204): # in some cases we get No Content - try: - mgmt_header = 'x-server-management-url' - self.management_url = resp.headers[mgmt_header].rstrip('/') - self.auth_token = resp.headers['x-auth-token'] - self.auth_url = url - except (KeyError, TypeError): - raise exceptions.AuthorizationFailure() - elif resp.status_code == 305: - return resp.headers['location'] - else: - raise exceptions.from_response(resp, body) - - def _plugin_auth(self, auth_url): - return self.auth_plugin.authenticate(self, auth_url) - - def _v2_auth(self, url): - """Authenticate against a v2.0 auth service.""" - body = {"auth": { - "passwordCredentials": {"username": self.user, - "password": self.password}}} - - if self.projectid: - body['auth']['tenantName'] = self.projectid - elif self.tenant_id: - body['auth']['tenantId'] = self.tenant_id - - self._authenticate(url, body) - - def _authenticate(self, url, body): - """Authenticate and extract the service catalog.""" - token_url = url + "/tokens" - - # Make sure we follow redirects when trying to reach Keystone - resp, body = self.request( - token_url, - "POST", - body=body, - allow_redirects=True) - - return self._extract_service_catalog(url, resp, body) - - -def _construct_http_client(username=None, password=None, project_id=None, - auth_url=None, insecure=False, timeout=None, - proxy_tenant_id=None, proxy_token=None, - region_name=None, endpoint_type='publicURL', - service_type='volume', - service_name=None, volume_service_name=None, - retries=None, - http_log_debug=False, - auth_system='keystone', auth_plugin=None, - cacert=None, tenant_id=None, - session=None, - auth=None, - **kwargs): - - if session: - kwargs.setdefault('interface', endpoint_type) - return SessionClient(session=session, - auth=auth, - service_type=service_type, - service_name=service_name, - region_name=region_name, - **kwargs) - else: - # FIXME(jamielennox): username and password are now optional. Need - # to test that they were provided in this mode. - return HTTPClient(username, - password, - projectid=project_id, - auth_url=auth_url, - insecure=insecure, - timeout=timeout, - tenant_id=tenant_id, - proxy_token=proxy_token, - proxy_tenant_id=proxy_tenant_id, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - retries=retries, - http_log_debug=http_log_debug, - cacert=cacert, - auth_system=auth_system, - auth_plugin=auth_plugin, - ) - - -def get_client_class(version): - version_map = { - '1': 'cinderclient.v1.client.Client', - '2': 'cinderclient.v2.client.Client', - } - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = "Invalid client version '%s'. must be one of: %s" % ( - (version, ', '.join(version_map))) - raise exceptions.UnsupportedVersion(msg) - - return utils.import_class(client_path) - - -def Client(version, *args, **kwargs): - client_class = get_client_class(version) - return client_class(*args, **kwargs) diff --git a/awx/lib/site-packages/cinderclient/exceptions.py b/awx/lib/site-packages/cinderclient/exceptions.py deleted file mode 100644 index 751e425923..0000000000 --- a/awx/lib/site-packages/cinderclient/exceptions.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Exception definitions. -""" - - -class UnsupportedVersion(Exception): - """Indicates that the user is trying to use an unsupported - version of the API. - """ - pass - - -class InvalidAPIVersion(Exception): - pass - - -class CommandError(Exception): - pass - - -class AuthorizationFailure(Exception): - pass - - -class NoUniqueMatch(Exception): - pass - - -class AuthSystemNotFound(Exception): - """When the user specify a AuthSystem but not installed.""" - def __init__(self, auth_system): - self.auth_system = auth_system - - def __str__(self): - return "AuthSystemNotFound: %s" % repr(self.auth_system) - - -class NoTokenLookupException(Exception): - """This form of authentication does not support looking up - endpoints from an existing token. - """ - pass - - -class EndpointNotFound(Exception): - """Could not find Service or Region in Service Catalog.""" - pass - - -class ConnectionError(Exception): - """Could not open a connection to the API service.""" - pass - - -class AmbiguousEndpoints(Exception): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - self.endpoints = endpoints - - def __str__(self): - return "AmbiguousEndpoints: %s" % repr(self.endpoints) - - -class ClientException(Exception): - """ - The base exception class for all exceptions this library raises. - """ - def __init__(self, code, message=None, details=None, request_id=None): - self.code = code - self.message = message or self.__class__.message - self.details = details - self.request_id = request_id - - def __str__(self): - formatted_string = "%s (HTTP %s)" % (self.message, self.code) - if self.request_id: - formatted_string += " (Request-ID: %s)" % self.request_id - - return formatted_string - - -class BadRequest(ClientException): - """ - HTTP 400 - Bad request: you sent some malformed data. - """ - http_status = 400 - message = "Bad request" - - -class Unauthorized(ClientException): - """ - HTTP 401 - Unauthorized: bad credentials. - """ - http_status = 401 - message = "Unauthorized" - - -class Forbidden(ClientException): - """ - HTTP 403 - Forbidden: your credentials don't give you access to this - resource. - """ - http_status = 403 - message = "Forbidden" - - -class NotFound(ClientException): - """ - HTTP 404 - Not found - """ - http_status = 404 - message = "Not found" - - -class OverLimit(ClientException): - """ - HTTP 413 - Over limit: you're over the API limits for this time period. - """ - http_status = 413 - message = "Over limit" - - -# NotImplemented is a python keyword. -class HTTPNotImplemented(ClientException): - """ - HTTP 501 - Not Implemented: the server does not support this operation. - """ - http_status = 501 - message = "Not Implemented" - - -# In Python 2.4 Exception is old-style and thus doesn't have a __subclasses__() -# so we can do this: -# _code_map = dict((c.http_status, c) -# for c in ClientException.__subclasses__()) -# -# Instead, we have to hardcode it: -_code_map = dict((c.http_status, c) for c in [BadRequest, Unauthorized, - Forbidden, NotFound, - OverLimit, HTTPNotImplemented]) - - -def from_response(response, body): - """ - Return an instance of an ClientException or subclass - based on an requests response. - - Usage:: - - resp, body = requests.request(...) - if resp.status_code != 200: - raise exception_from_response(resp, rest.text) - """ - cls = _code_map.get(response.status_code, ClientException) - if response.headers: - request_id = response.headers.get('x-compute-request-id') - else: - request_id = None - if body: - message = "n/a" - details = "n/a" - if hasattr(body, 'keys'): - error = body[list(body)[0]] - message = error.get('message', None) - details = error.get('details', None) - return cls(code=response.status_code, message=message, details=details, - request_id=request_id) - else: - return cls(code=response.status_code, request_id=request_id, - message=response.reason) diff --git a/awx/lib/site-packages/cinderclient/extension.py b/awx/lib/site-packages/cinderclient/extension.py deleted file mode 100644 index 84c67e9795..0000000000 --- a/awx/lib/site-packages/cinderclient/extension.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import base -from cinderclient import utils - - -class Extension(utils.HookableMixin): - """Extension descriptor.""" - - SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') - - def __init__(self, name, module): - self.name = name - self.module = module - self._parse_extension_module() - - def _parse_extension_module(self): - self.manager_class = None - for attr_name, attr_value in list(self.module.__dict__.items()): - if attr_name in self.SUPPORTED_HOOKS: - self.add_hook(attr_name, attr_value) - elif utils.safe_issubclass(attr_value, base.Manager): - self.manager_class = attr_value - - def __repr__(self): - return "<Extension '%s'>" % self.name diff --git a/awx/lib/site-packages/cinderclient/openstack/__init__.py b/awx/lib/site-packages/cinderclient/openstack/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/openstack/common/__init__.py b/awx/lib/site-packages/cinderclient/openstack/common/__init__.py deleted file mode 100644 index d1223eaf76..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - - -six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox')) diff --git a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/__init__.py b/awx/lib/site-packages/cinderclient/openstack/common/apiclient/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/auth.py b/awx/lib/site-packages/cinderclient/openstack/common/apiclient/auth.py deleted file mode 100644 index 1a713b0e10..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/auth.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 Spanish National Research Council. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import abc -import argparse -import os - -import six -from stevedore import extension - -from cinderclient.openstack.common.apiclient import exceptions - - -_discovered_plugins = {} - - -def discover_auth_systems(): - """Discover the available auth-systems. - - This won't take into account the old style auth-systems. - """ - global _discovered_plugins - _discovered_plugins = {} - - def add_plugin(ext): - _discovered_plugins[ext.name] = ext.plugin - - ep_namespace = "cinderclient.openstack.common.apiclient.auth" - mgr = extension.ExtensionManager(ep_namespace) - mgr.map(add_plugin) - - -def load_auth_system_opts(parser): - """Load options needed by the available auth-systems into a parser. - - This function will try to populate the parser with options from the - available plugins. - """ - group = parser.add_argument_group("Common auth options") - BaseAuthPlugin.add_common_opts(group) - for name, auth_plugin in six.iteritems(_discovered_plugins): - group = parser.add_argument_group( - "Auth-system '%s' options" % name, - conflict_handler="resolve") - auth_plugin.add_opts(group) - - -def load_plugin(auth_system): - try: - plugin_class = _discovered_plugins[auth_system] - except KeyError: - raise exceptions.AuthSystemNotFound(auth_system) - return plugin_class(auth_system=auth_system) - - -def load_plugin_from_args(args): - """Load required plugin and populate it with options. - - Try to guess auth system if it is not specified. Systems are tried in - alphabetical order. - - :type args: argparse.Namespace - :raises: AuthorizationFailure - """ - auth_system = args.os_auth_system - if auth_system: - plugin = load_plugin(auth_system) - plugin.parse_opts(args) - plugin.sufficient_options() - return plugin - - for plugin_auth_system in sorted(six.iterkeys(_discovered_plugins)): - plugin_class = _discovered_plugins[plugin_auth_system] - plugin = plugin_class() - plugin.parse_opts(args) - try: - plugin.sufficient_options() - except exceptions.AuthPluginOptionsMissing: - continue - return plugin - raise exceptions.AuthPluginOptionsMissing(["auth_system"]) - - -@six.add_metaclass(abc.ABCMeta) -class BaseAuthPlugin(object): - """Base class for authentication plugins. - - An authentication plugin needs to override at least the authenticate - method to be a valid plugin. - """ - - auth_system = None - opt_names = [] - common_opt_names = [ - "auth_system", - "username", - "password", - "tenant_name", - "token", - "auth_url", - ] - - def __init__(self, auth_system=None, **kwargs): - self.auth_system = auth_system or self.auth_system - self.opts = dict((name, kwargs.get(name)) - for name in self.opt_names) - - @staticmethod - def _parser_add_opt(parser, opt): - """Add an option to parser in two variants. - - :param opt: option name (with underscores) - """ - dashed_opt = opt.replace("_", "-") - env_var = "OS_%s" % opt.upper() - arg_default = os.environ.get(env_var, "") - arg_help = "Defaults to env[%s]." % env_var - parser.add_argument( - "--os-%s" % dashed_opt, - metavar="<%s>" % dashed_opt, - default=arg_default, - help=arg_help) - parser.add_argument( - "--os_%s" % opt, - metavar="<%s>" % dashed_opt, - help=argparse.SUPPRESS) - - @classmethod - def add_opts(cls, parser): - """Populate the parser with the options for this plugin. - """ - for opt in cls.opt_names: - # use `BaseAuthPlugin.common_opt_names` since it is never - # changed in child classes - if opt not in BaseAuthPlugin.common_opt_names: - cls._parser_add_opt(parser, opt) - - @classmethod - def add_common_opts(cls, parser): - """Add options that are common for several plugins. - """ - for opt in cls.common_opt_names: - cls._parser_add_opt(parser, opt) - - @staticmethod - def get_opt(opt_name, args): - """Return option name and value. - - :param opt_name: name of the option, e.g., "username" - :param args: parsed arguments - """ - return (opt_name, getattr(args, "os_%s" % opt_name, None)) - - def parse_opts(self, args): - """Parse the actual auth-system options if any. - - This method is expected to populate the attribute `self.opts` with a - dict containing the options and values needed to make authentication. - """ - self.opts.update(dict(self.get_opt(opt_name, args) - for opt_name in self.opt_names)) - - def authenticate(self, http_client): - """Authenticate using plugin defined method. - - The method usually analyses `self.opts` and performs - a request to authentication server. - - :param http_client: client object that needs authentication - :type http_client: HTTPClient - :raises: AuthorizationFailure - """ - self.sufficient_options() - self._do_authenticate(http_client) - - @abc.abstractmethod - def _do_authenticate(self, http_client): - """Protected method for authentication. - """ - - def sufficient_options(self): - """Check if all required options are present. - - :raises: AuthPluginOptionsMissing - """ - missing = [opt - for opt in self.opt_names - if not self.opts.get(opt)] - if missing: - raise exceptions.AuthPluginOptionsMissing(missing) - - @abc.abstractmethod - def token_and_endpoint(self, endpoint_type, service_type): - """Return token and endpoint. - - :param service_type: Service type of the endpoint - :type service_type: string - :param endpoint_type: Type of endpoint. - Possible values: public or publicURL, - internal or internalURL, - admin or adminURL - :type endpoint_type: string - :returns: tuple of token and endpoint strings - :raises: EndpointException - """ diff --git a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/base.py b/awx/lib/site-packages/cinderclient/openstack/common/apiclient/base.py deleted file mode 100644 index bc4a1588b2..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/base.py +++ /dev/null @@ -1,491 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2012 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -# E1102: %s is not callable -# pylint: disable=E1102 - -import abc - -import six -from six.moves.urllib import parse - -from cinderclient.openstack.common.apiclient import exceptions -from cinderclient.openstack.common import strutils - - -def getid(obj): - """Return id if argument is a Resource. - - Abstracts the common pattern of allowing both an object or an object's ID - (UUID) as a parameter when dealing with relationships. - """ - try: - if obj.uuid: - return obj.uuid - except AttributeError: - pass - try: - return obj.id - except AttributeError: - return obj - - -# TODO(aababilov): call run_hooks() in HookableMixin's child classes -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - """Add a new hook of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param hook_func: hook function - """ - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - """Run all hooks of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param **args: args to be passed to every hook function - :param **kwargs: kwargs to be passed to every hook function - """ - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - -class BaseManager(HookableMixin): - """Basic manager type providing common operations. - - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, client): - """Initializes BaseManager with `client`. - - :param client: instance of BaseClient descendant for HTTP requests - """ - super(BaseManager, self).__init__() - self.client = client - - def _list(self, url, response_key, obj_class=None, json=None): - """List the collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param obj_class: class for constructing the returned objects - (self.resource_class will be used by default) - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - """ - if json: - body = self.client.post(url, json=json).json() - else: - body = self.client.get(url).json() - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - try: - data = data['values'] - except (KeyError, TypeError): - pass - - return [obj_class(self, res, loaded=True) for res in data if res] - - def _get(self, url, response_key): - """Get an object from collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'server' - """ - body = self.client.get(url).json() - return self.resource_class(self, body[response_key], loaded=True) - - def _head(self, url): - """Retrieve request headers for an object. - - :param url: a partial URL, e.g., '/servers' - """ - resp = self.client.head(url) - return resp.status_code == 204 - - def _post(self, url, json, response_key, return_raw=False): - """Create an object. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param return_raw: flag to force returning raw JSON instead of - Python object of self.resource_class - """ - body = self.client.post(url, json=json).json() - if return_raw: - return body[response_key] - return self.resource_class(self, body[response_key]) - - def _put(self, url, json=None, response_key=None): - """Update an object with PUT method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - """ - resp = self.client.put(url, json=json) - # PUT requests may not return a body - if resp.content: - body = resp.json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _patch(self, url, json=None, response_key=None): - """Update an object with PATCH method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - """ - body = self.client.patch(url, json=json).json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _delete(self, url): - """Delete an object. - - :param url: a partial URL, e.g., '/servers/my-server' - """ - return self.client.delete(url) - - -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(BaseManager): - """Manager with additional `find()`/`findall()` methods.""" - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - matches = self.findall(**kwargs) - num_matches = len(matches) - if num_matches == 0: - msg = "No %s matching %s." % (self.resource_class.__name__, kwargs) - raise exceptions.NotFound(msg) - elif num_matches > 1: - raise exceptions.NoUniqueMatch() - else: - return matches[0] - - def findall(self, **kwargs): - """Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - found = [] - searches = kwargs.items() - - for obj in self.list(): - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - found.append(obj) - except AttributeError: - continue - - return found - - -class CrudManager(BaseManager): - """Base manager class for manipulating entities. - - Children of this class are expected to define a `collection_key` and `key`. - - - `collection_key`: Usually a plural noun by convention (e.g. `entities`); - used to refer collections in both URL's (e.g. `/v3/entities`) and JSON - objects containing a list of member resources (e.g. `{'entities': [{}, - {}, {}]}`). - - `key`: Usually a singular noun by convention (e.g. `entity`); used to - refer to an individual member of the collection. - - """ - collection_key = None - key = None - - def build_url(self, base_url=None, **kwargs): - """Builds a resource URL for the given kwargs. - - Given an example collection where `collection_key = 'entities'` and - `key = 'entity'`, the following URL's could be generated. - - By default, the URL will represent a collection of entities, e.g.:: - - /entities - - If kwargs contains an `entity_id`, then the URL will represent a - specific member, e.g.:: - - /entities/{entity_id} - - :param base_url: if provided, the generated URL will be appended to it - """ - url = base_url if base_url is not None else '' - - url += '/%s' % self.collection_key - - # do we have a specific entity? - entity_id = kwargs.get('%s_id' % self.key) - if entity_id is not None: - url += '/%s' % entity_id - - return url - - def _filter_kwargs(self, kwargs): - """Drop null values and handle ids.""" - for key, ref in six.iteritems(kwargs.copy()): - if ref is None: - kwargs.pop(key) - else: - if isinstance(ref, Resource): - kwargs.pop(key) - kwargs['%s_id' % key] = getid(ref) - return kwargs - - def create(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._post( - self.build_url(**kwargs), - {self.key: kwargs}, - self.key) - - def get(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._get( - self.build_url(**kwargs), - self.key) - - def head(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._head(self.build_url(**kwargs)) - - def list(self, base_url=None, **kwargs): - """List the collection. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - - def put(self, base_url=None, **kwargs): - """Update an element. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._put(self.build_url(base_url=base_url, **kwargs)) - - def update(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - params = kwargs.copy() - params.pop('%s_id' % self.key) - - return self._patch( - self.build_url(**kwargs), - {self.key: params}, - self.key) - - def delete(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - - return self._delete( - self.build_url(**kwargs)) - - def find(self, base_url=None, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - rl = self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - num = len(rl) - - if num == 0: - msg = "No %s matching %s." % (self.resource_class.__name__, kwargs) - raise exceptions.NotFound(404, msg) - elif num > 1: - raise exceptions.NoUniqueMatch - else: - return rl[0] - - -class Extension(HookableMixin): - """Extension descriptor.""" - - SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') - manager_class = None - - def __init__(self, name, module): - super(Extension, self).__init__() - self.name = name - self.module = module - self._parse_extension_module() - - def _parse_extension_module(self): - self.manager_class = None - for attr_name, attr_value in self.module.__dict__.items(): - if attr_name in self.SUPPORTED_HOOKS: - self.add_hook(attr_name, attr_value) - else: - try: - if issubclass(attr_value, BaseManager): - self.manager_class = attr_value - except TypeError: - pass - - def __repr__(self): - return "<Extension '%s'>" % self.name - - -class Resource(object): - """Base class for OpenStack resources (tenant, user, etc.). - - This is pretty much just a bag for attributes. - """ - - HUMAN_ID = False - NAME_ATTR = 'name' - - def __init__(self, manager, info, loaded=False): - """Populate and bind to a manager. - - :param manager: BaseManager object - :param info: dictionary representing resource attributes - :param loaded: prevent lazy-loading if set to True - """ - self.manager = manager - self._info = info - self._add_details(info) - self._loaded = loaded - - def __repr__(self): - reprkeys = sorted(k - for k in self.__dict__.keys() - if k[0] != '_' and k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) - - @property - def human_id(self): - """Human-readable ID which can be used for bash completion. - """ - if self.NAME_ATTR in self.__dict__ and self.HUMAN_ID: - return strutils.to_slug(getattr(self, self.NAME_ATTR)) - return None - - def _add_details(self, info): - for (k, v) in six.iteritems(info): - try: - setattr(self, k, v) - self._info[k] = v - except AttributeError: - # In this case we already defined the attribute on the class - pass - - def __getattr__(self, k): - if k not in self.__dict__: - #NOTE(bcwaldon): disallow lazy-loading if already loaded once - if not self.is_loaded(): - self.get() - return self.__getattr__(k) - - raise AttributeError(k) - else: - return self.__dict__[k] - - def get(self): - # set_loaded() first ... so if we have to bail, we know we tried. - self.set_loaded(True) - if not hasattr(self.manager, 'get'): - return - - new = self.manager.get(self.id) - if new: - self._add_details(new._info) - - def __eq__(self, other): - if not isinstance(other, Resource): - return NotImplemented - # two resources of different types are not equal - if not isinstance(other, self.__class__): - return False - if hasattr(self, 'id') and hasattr(other, 'id'): - return self.id == other.id - return self._info == other._info - - def is_loaded(self): - return self._loaded - - def set_loaded(self, val): - self._loaded = val diff --git a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/client.py b/awx/lib/site-packages/cinderclient/openstack/common/apiclient/client.py deleted file mode 100644 index da2e177381..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/client.py +++ /dev/null @@ -1,358 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Piston Cloud Computing, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import logging -import time - -try: - import simplejson as json -except ImportError: - import json - -import requests - -from cinderclient.openstack.common.apiclient import exceptions -from cinderclient.openstack.common import importutils - - -_logger = logging.getLogger(__name__) - - -class HTTPClient(object): - """This client handles sending HTTP requests to OpenStack servers. - - Features: - - share authentication information between several clients to different - services (e.g., for compute and image clients); - - reissue authentication request for expired tokens; - - encode/decode JSON bodies; - - raise exceptions on HTTP errors; - - pluggable authentication; - - store authentication information in a keyring; - - store time spent for requests; - - register clients for particular services, so one can use - `http_client.identity` or `http_client.compute`; - - log requests and responses in a format that is easy to copy-and-paste - into terminal and send the same request with curl. - """ - - user_agent = "cinderclient.openstack.common.apiclient" - - def __init__(self, - auth_plugin, - region_name=None, - endpoint_type="publicURL", - original_ip=None, - verify=True, - cert=None, - timeout=None, - timings=False, - keyring_saver=None, - debug=False, - user_agent=None, - http=None): - self.auth_plugin = auth_plugin - - self.endpoint_type = endpoint_type - self.region_name = region_name - - self.original_ip = original_ip - self.timeout = timeout - self.verify = verify - self.cert = cert - - self.keyring_saver = keyring_saver - self.debug = debug - self.user_agent = user_agent or self.user_agent - - self.times = [] # [("item", starttime, endtime), ...] - self.timings = timings - - # requests within the same session can reuse TCP connections from pool - self.http = http or requests.Session() - - self.cached_token = None - - def _http_log_req(self, method, url, kwargs): - if not self.debug: - return - - string_parts = [ - "curl -i", - "-X '%s'" % method, - "'%s'" % url, - ] - - for element in kwargs['headers']: - header = "-H '%s: %s'" % (element, kwargs['headers'][element]) - string_parts.append(header) - - _logger.debug("REQ: %s" % " ".join(string_parts)) - if 'data' in kwargs: - _logger.debug("REQ BODY: %s\n" % (kwargs['data'])) - - def _http_log_resp(self, resp): - if not self.debug: - return - _logger.debug( - "RESP: [%s] %s\n", - resp.status_code, - resp.headers) - if resp._content_consumed: - _logger.debug( - "RESP BODY: %s\n", - resp.text) - - def serialize(self, kwargs): - if kwargs.get('json') is not None: - kwargs['headers']['Content-Type'] = 'application/json' - kwargs['data'] = json.dumps(kwargs['json']) - try: - del kwargs['json'] - except KeyError: - pass - - def get_timings(self): - return self.times - - def reset_timings(self): - self.times = [] - - def request(self, method, url, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around `requests.Session.request` to handle tasks such as - setting headers, JSON encoding/decoding, and error handling. - - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to -' requests.Session.request (such as `headers`) or `json` - that will be encoded as JSON and used as `data` argument - """ - kwargs.setdefault("headers", kwargs.get("headers", {})) - kwargs["headers"]["User-Agent"] = self.user_agent - if self.original_ip: - kwargs["headers"]["Forwarded"] = "for=%s;by=%s" % ( - self.original_ip, self.user_agent) - if self.timeout is not None: - kwargs.setdefault("timeout", self.timeout) - kwargs.setdefault("verify", self.verify) - if self.cert is not None: - kwargs.setdefault("cert", self.cert) - self.serialize(kwargs) - - self._http_log_req(method, url, kwargs) - if self.timings: - start_time = time.time() - resp = self.http.request(method, url, **kwargs) - if self.timings: - self.times.append(("%s %s" % (method, url), - start_time, time.time())) - self._http_log_resp(resp) - - if resp.status_code >= 400: - _logger.debug( - "Request returned failure status: %s", - resp.status_code) - raise exceptions.from_response(resp, method, url) - - return resp - - @staticmethod - def concat_url(endpoint, url): - """Concatenate endpoint and final URL. - - E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to - "http://keystone/v2.0/tokens". - - :param endpoint: the base URL - :param url: the final URL - """ - return "%s/%s" % (endpoint.rstrip("/"), url.strip("/")) - - def client_request(self, client, method, url, **kwargs): - """Send an http request using `client`'s endpoint and specified `url`. - - If request was rejected as unauthorized (possibly because the token is - expired), issue one authorization attempt and send the request once - again. - - :param client: instance of BaseClient descendant - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to -' `HTTPClient.request` - """ - - filter_args = { - "endpoint_type": client.endpoint_type or self.endpoint_type, - "service_type": client.service_type, - } - token, endpoint = (self.cached_token, client.cached_endpoint) - just_authenticated = False - if not (token and endpoint): - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - pass - if not (token and endpoint): - self.authenticate() - just_authenticated = True - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - if not (token and endpoint): - raise exceptions.AuthorizationFailure( - "Cannot find endpoint or token for request") - - old_token_endpoint = (token, endpoint) - kwargs.setdefault("headers", {})["X-Auth-Token"] = token - self.cached_token = token - client.cached_endpoint = endpoint - # Perform the request once. If we get Unauthorized, then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - except exceptions.Unauthorized as unauth_ex: - if just_authenticated: - raise - self.cached_token = None - client.cached_endpoint = None - self.authenticate() - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - raise unauth_ex - if (not (token and endpoint) or - old_token_endpoint == (token, endpoint)): - raise unauth_ex - self.cached_token = token - client.cached_endpoint = endpoint - kwargs["headers"]["X-Auth-Token"] = token - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - - def add_client(self, base_client_instance): - """Add a new instance of :class:`BaseClient` descendant. - - `self` will store a reference to `base_client_instance`. - - Example: - - >>> def test_clients(): - ... from keystoneclient.auth import keystone - ... from openstack.common.apiclient import client - ... auth = keystone.KeystoneAuthPlugin( - ... username="user", password="pass", tenant_name="tenant", - ... auth_url="http://auth:5000/v2.0") - ... openstack_client = client.HTTPClient(auth) - ... # create nova client - ... from novaclient.v1_1 import client - ... client.Client(openstack_client) - ... # create keystone client - ... from keystoneclient.v2_0 import client - ... client.Client(openstack_client) - ... # use them - ... openstack_client.identity.tenants.list() - ... openstack_client.compute.servers.list() - """ - service_type = base_client_instance.service_type - if service_type and not hasattr(self, service_type): - setattr(self, service_type, base_client_instance) - - def authenticate(self): - self.auth_plugin.authenticate(self) - # Store the authentication results in the keyring for later requests - if self.keyring_saver: - self.keyring_saver.save(self) - - -class BaseClient(object): - """Top-level object to access the OpenStack API. - - This client uses :class:`HTTPClient` to send requests. :class:`HTTPClient` - will handle a bunch of issues such as authentication. - """ - - service_type = None - endpoint_type = None # "publicURL" will be used - cached_endpoint = None - - def __init__(self, http_client, extensions=None): - self.http_client = http_client - http_client.add_client(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - def client_request(self, method, url, **kwargs): - return self.http_client.client_request( - self, method, url, **kwargs) - - def head(self, url, **kwargs): - return self.client_request("HEAD", url, **kwargs) - - def get(self, url, **kwargs): - return self.client_request("GET", url, **kwargs) - - def post(self, url, **kwargs): - return self.client_request("POST", url, **kwargs) - - def put(self, url, **kwargs): - return self.client_request("PUT", url, **kwargs) - - def delete(self, url, **kwargs): - return self.client_request("DELETE", url, **kwargs) - - def patch(self, url, **kwargs): - return self.client_request("PATCH", url, **kwargs) - - @staticmethod - def get_class(api_name, version, version_map): - """Returns the client class for the requested API version - - :param api_name: the name of the API, e.g. 'compute', 'image', etc - :param version: the requested API version - :param version_map: a dict of client classes keyed by version - :rtype: a client class for the requested API version - """ - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = "Invalid %s client version '%s'. must be one of: %s" % ( - (api_name, version, ', '.join(version_map.keys()))) - raise exceptions.UnsupportedVersion(msg) - - return importutils.import_class(client_path) diff --git a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/exceptions.py b/awx/lib/site-packages/cinderclient/openstack/common/apiclient/exceptions.py deleted file mode 100644 index 4776d58724..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/exceptions.py +++ /dev/null @@ -1,444 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Nebula, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception definitions. -""" - -import inspect -import sys - -import six - - -class ClientException(Exception): - """The base exception class for all exceptions this library raises. - """ - pass - - -class MissingArgs(ClientException): - """Supplied arguments are not sufficient for calling a function.""" - def __init__(self, missing): - self.missing = missing - msg = "Missing argument(s): %s" % ", ".join(missing) - super(MissingArgs, self).__init__(msg) - - -class ValidationError(ClientException): - """Error in validation on API client side.""" - pass - - -class UnsupportedVersion(ClientException): - """User is trying to use an unsupported version of the API.""" - pass - - -class CommandError(ClientException): - """Error in CLI tool.""" - pass - - -class AuthorizationFailure(ClientException): - """Cannot authorize API client.""" - pass - - -class ConnectionRefused(ClientException): - """Cannot connect to API service.""" - pass - - -class AuthPluginOptionsMissing(AuthorizationFailure): - """Auth plugin misses some options.""" - def __init__(self, opt_names): - super(AuthPluginOptionsMissing, self).__init__( - "Authentication failed. Missing options: %s" % - ", ".join(opt_names)) - self.opt_names = opt_names - - -class AuthSystemNotFound(AuthorizationFailure): - """User has specified a AuthSystem that is not installed.""" - def __init__(self, auth_system): - super(AuthSystemNotFound, self).__init__( - "AuthSystemNotFound: %s" % repr(auth_system)) - self.auth_system = auth_system - - -class NoUniqueMatch(ClientException): - """Multiple entities found instead of one.""" - pass - - -class EndpointException(ClientException): - """Something is rotten in Service Catalog.""" - pass - - -class EndpointNotFound(EndpointException): - """Could not find requested endpoint in Service Catalog.""" - pass - - -class AmbiguousEndpoints(EndpointException): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - super(AmbiguousEndpoints, self).__init__( - "AmbiguousEndpoints: %s" % repr(endpoints)) - self.endpoints = endpoints - - -class HttpError(ClientException): - """The base exception class for all HTTP exceptions. - """ - http_status = 0 - message = "HTTP Error" - - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None): - self.http_status = http_status or self.http_status - self.message = message or self.message - self.details = details - self.request_id = request_id - self.response = response - self.url = url - self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) - if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HttpError, self).__init__(formatted_string) - - -class HTTPClientError(HttpError): - """Client-side HTTP error. - - Exception for cases in which the client seems to have erred. - """ - message = "HTTP Client Error" - - -class HttpServerError(HttpError): - """Server-side HTTP error. - - Exception for cases in which the server is aware that it has - erred or is incapable of performing the request. - """ - message = "HTTP Server Error" - - -class BadRequest(HTTPClientError): - """HTTP 400 - Bad Request. - - The request cannot be fulfilled due to bad syntax. - """ - http_status = 400 - message = "Bad Request" - - -class Unauthorized(HTTPClientError): - """HTTP 401 - Unauthorized. - - Similar to 403 Forbidden, but specifically for use when authentication - is required and has failed or has not yet been provided. - """ - http_status = 401 - message = "Unauthorized" - - -class PaymentRequired(HTTPClientError): - """HTTP 402 - Payment Required. - - Reserved for future use. - """ - http_status = 402 - message = "Payment Required" - - -class Forbidden(HTTPClientError): - """HTTP 403 - Forbidden. - - The request was a valid request, but the server is refusing to respond - to it. - """ - http_status = 403 - message = "Forbidden" - - -class NotFound(HTTPClientError): - """HTTP 404 - Not Found. - - The requested resource could not be found but may be available again - in the future. - """ - http_status = 404 - message = "Not Found" - - -class MethodNotAllowed(HTTPClientError): - """HTTP 405 - Method Not Allowed. - - A request was made of a resource using a request method not supported - by that resource. - """ - http_status = 405 - message = "Method Not Allowed" - - -class NotAcceptable(HTTPClientError): - """HTTP 406 - Not Acceptable. - - The requested resource is only capable of generating content not - acceptable according to the Accept headers sent in the request. - """ - http_status = 406 - message = "Not Acceptable" - - -class ProxyAuthenticationRequired(HTTPClientError): - """HTTP 407 - Proxy Authentication Required. - - The client must first authenticate itself with the proxy. - """ - http_status = 407 - message = "Proxy Authentication Required" - - -class RequestTimeout(HTTPClientError): - """HTTP 408 - Request Timeout. - - The server timed out waiting for the request. - """ - http_status = 408 - message = "Request Timeout" - - -class Conflict(HTTPClientError): - """HTTP 409 - Conflict. - - Indicates that the request could not be processed because of conflict - in the request, such as an edit conflict. - """ - http_status = 409 - message = "Conflict" - - -class Gone(HTTPClientError): - """HTTP 410 - Gone. - - Indicates that the resource requested is no longer available and will - not be available again. - """ - http_status = 410 - message = "Gone" - - -class LengthRequired(HTTPClientError): - """HTTP 411 - Length Required. - - The request did not specify the length of its content, which is - required by the requested resource. - """ - http_status = 411 - message = "Length Required" - - -class PreconditionFailed(HTTPClientError): - """HTTP 412 - Precondition Failed. - - The server does not meet one of the preconditions that the requester - put on the request. - """ - http_status = 412 - message = "Precondition Failed" - - -class RequestEntityTooLarge(HTTPClientError): - """HTTP 413 - Request Entity Too Large. - - The request is larger than the server is willing or able to process. - """ - http_status = 413 - message = "Request Entity Too Large" - - def __init__(self, *args, **kwargs): - try: - self.retry_after = int(kwargs.pop('retry_after')) - except (KeyError, ValueError): - self.retry_after = 0 - - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) - - -class RequestUriTooLong(HTTPClientError): - """HTTP 414 - Request-URI Too Long. - - The URI provided was too long for the server to process. - """ - http_status = 414 - message = "Request-URI Too Long" - - -class UnsupportedMediaType(HTTPClientError): - """HTTP 415 - Unsupported Media Type. - - The request entity has a media type which the server or resource does - not support. - """ - http_status = 415 - message = "Unsupported Media Type" - - -class RequestedRangeNotSatisfiable(HTTPClientError): - """HTTP 416 - Requested Range Not Satisfiable. - - The client has asked for a portion of the file, but the server cannot - supply that portion. - """ - http_status = 416 - message = "Requested Range Not Satisfiable" - - -class ExpectationFailed(HTTPClientError): - """HTTP 417 - Expectation Failed. - - The server cannot meet the requirements of the Expect request-header field. - """ - http_status = 417 - message = "Expectation Failed" - - -class UnprocessableEntity(HTTPClientError): - """HTTP 422 - Unprocessable Entity. - - The request was well-formed but was unable to be followed due to semantic - errors. - """ - http_status = 422 - message = "Unprocessable Entity" - - -class InternalServerError(HttpServerError): - """HTTP 500 - Internal Server Error. - - A generic error message, given when no more specific message is suitable. - """ - http_status = 500 - message = "Internal Server Error" - - -# NotImplemented is a python keyword. -class HttpNotImplemented(HttpServerError): - """HTTP 501 - Not Implemented. - - The server either does not recognize the request method, or it lacks - the ability to fulfill the request. - """ - http_status = 501 - message = "Not Implemented" - - -class BadGateway(HttpServerError): - """HTTP 502 - Bad Gateway. - - The server was acting as a gateway or proxy and received an invalid - response from the upstream server. - """ - http_status = 502 - message = "Bad Gateway" - - -class ServiceUnavailable(HttpServerError): - """HTTP 503 - Service Unavailable. - - The server is currently unavailable. - """ - http_status = 503 - message = "Service Unavailable" - - -class GatewayTimeout(HttpServerError): - """HTTP 504 - Gateway Timeout. - - The server was acting as a gateway or proxy and did not receive a timely - response from the upstream server. - """ - http_status = 504 - message = "Gateway Timeout" - - -class HttpVersionNotSupported(HttpServerError): - """HTTP 505 - HttpVersion Not Supported. - - The server does not support the HTTP protocol version used in the request. - """ - http_status = 505 - message = "HTTP Version Not Supported" - - -# _code_map contains all the classes that have http_status attribute. -_code_map = dict( - (getattr(obj, 'http_status', None), obj) - for name, obj in six.iteritems(vars(sys.modules[__name__])) - if inspect.isclass(obj) and getattr(obj, 'http_status', False) -) - - -def from_response(response, method, url): - """Returns an instance of :class:`HttpError` or subclass based on response. - - :param response: instance of `requests.Response` class - :param method: HTTP method used for request - :param url: URL used for request - """ - kwargs = { - "http_status": response.status_code, - "response": response, - "method": method, - "url": url, - "request_id": response.headers.get("x-compute-request-id"), - } - if "retry-after" in response.headers: - kwargs["retry_after"] = response.headers["retry-after"] - - content_type = response.headers.get("Content-Type", "") - if content_type.startswith("application/json"): - try: - body = response.json() - except ValueError: - pass - else: - if hasattr(body, "keys"): - error = body[body.keys()[0]] - kwargs["message"] = error.get("message", None) - kwargs["details"] = error.get("details", None) - elif content_type.startswith("text/"): - kwargs["details"] = response.text - - try: - cls = _code_map[response.status_code] - except KeyError: - if 500 <= response.status_code < 600: - cls = HttpServerError - elif 400 <= response.status_code < 500: - cls = HTTPClientError - else: - cls = HttpError - return cls(**kwargs) diff --git a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/fake_client.py b/awx/lib/site-packages/cinderclient/openstack/common/apiclient/fake_client.py deleted file mode 100644 index dcc2a5be66..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/apiclient/fake_client.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -# W0102: Dangerous default value %s as argument -# pylint: disable=W0102 - -import json - -import requests -import six -from six.moves.urllib import parse - -from cinderclient.openstack.common.apiclient import client - - -def assert_has_keys(dct, required=[], optional=[]): - for k in required: - try: - assert k in dct - except AssertionError: - extra_keys = set(dct.keys()).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class TestResponse(requests.Response): - """Wrap requests.Response and provide a convenient initialization. - """ - - def __init__(self, data): - super(TestResponse, self).__init__() - self._content_consumed = True - if isinstance(data, dict): - self.status_code = data.get('status_code', 200) - # Fake the text attribute to streamline Response creation - text = data.get('text', "") - if isinstance(text, (dict, list)): - self._content = json.dumps(text) - default_headers = { - "Content-Type": "application/json", - } - else: - self._content = text - default_headers = {} - if six.PY3 and isinstance(self._content, six.string_types): - self._content = self._content.encode('utf-8', 'strict') - self.headers = data.get('headers') or default_headers - else: - self.status_code = data - - def __eq__(self, other): - return (self.status_code == other.status_code and - self.headers == other.headers and - self._content == other._content) - - -class FakeHTTPClient(client.HTTPClient): - - def __init__(self, *args, **kwargs): - self.callstack = [] - self.fixtures = kwargs.pop("fixtures", None) or {} - if not args and not "auth_plugin" in kwargs: - args = (None, ) - super(FakeHTTPClient, self).__init__(*args, **kwargs) - - def assert_called(self, method, url, body=None, pos=-1): - """Assert than an API method was just called. - """ - expected = (method, url) - called = self.callstack[pos][0:2] - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - assert expected == called, 'Expected %s %s; got %s %s' % \ - (expected + called) - - if body is not None: - if self.callstack[pos][3] != body: - raise AssertionError('%r != %r' % - (self.callstack[pos][3], body)) - - def assert_called_anytime(self, method, url, body=None): - """Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - found = False - entry = None - for entry in self.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s %s; got %s' % \ - (method, url, self.callstack) - if body is not None: - assert entry[3] == body, "%s != %s" % (entry[3], body) - - self.callstack = [] - - def clear_callstack(self): - self.callstack = [] - - def authenticate(self): - pass - - def client_request(self, client, method, url, **kwargs): - # Check that certain things are called correctly - if method in ["GET", "DELETE"]: - assert "json" not in kwargs - - # Note the call - self.callstack.append( - (method, - url, - kwargs.get("headers") or {}, - kwargs.get("json") or kwargs.get("data"))) - try: - fixture = self.fixtures[url][method] - except KeyError: - pass - else: - return TestResponse({"headers": fixture[0], - "text": fixture[1]}) - - # Call the method - args = parse.parse_qsl(parse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - resp = getattr(self, callback)(**kwargs) - if len(resp) == 3: - status, headers, body = resp - else: - status, body = resp - headers = {} - return TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) diff --git a/awx/lib/site-packages/cinderclient/openstack/common/gettextutils.py b/awx/lib/site-packages/cinderclient/openstack/common/gettextutils.py deleted file mode 100644 index 1516be14a0..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/gettextutils.py +++ /dev/null @@ -1,479 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -gettext for openstack-common modules. - -Usual usage in an openstack.common module: - - from openstack.common.gettextutils import _ -""" - -import copy -import gettext -import locale -from logging import handlers -import os - -from babel import localedata -import six - -_AVAILABLE_LANGUAGES = {} - -# FIXME(dhellmann): Remove this when moving to oslo.i18n. -USE_LAZY = False - - -class TranslatorFactory(object): - """Create translator functions - """ - - def __init__(self, domain, localedir=None): - """Establish a set of translation functions for the domain. - - :param domain: Name of translation domain, - specifying a message catalog. - :type domain: str - :param lazy: Delays translation until a message is emitted. - Defaults to False. - :type lazy: Boolean - :param localedir: Directory with translation catalogs. - :type localedir: str - """ - self.domain = domain - if localedir is None: - localedir = os.environ.get(domain.upper() + '_LOCALEDIR') - self.localedir = localedir - - def _make_translation_func(self, domain=None): - """Return a new translation function ready for use. - - Takes into account whether or not lazy translation is being - done. - - The domain can be specified to override the default from the - factory, but the localedir from the factory is always used - because we assume the log-level translation catalogs are - installed in the same directory as the main application - catalog. - - """ - if domain is None: - domain = self.domain - t = gettext.translation(domain, - localedir=self.localedir, - fallback=True) - # Use the appropriate method of the translation object based - # on the python version. - m = t.gettext if six.PY3 else t.ugettext - - def f(msg): - """oslo.i18n.gettextutils translation function.""" - if USE_LAZY: - return Message(msg, domain=domain) - return m(msg) - return f - - @property - def primary(self): - "The default translation function." - return self._make_translation_func() - - def _make_log_translation_func(self, level): - return self._make_translation_func(self.domain + '-log-' + level) - - @property - def log_info(self): - "Translate info-level log messages." - return self._make_log_translation_func('info') - - @property - def log_warning(self): - "Translate warning-level log messages." - return self._make_log_translation_func('warning') - - @property - def log_error(self): - "Translate error-level log messages." - return self._make_log_translation_func('error') - - @property - def log_critical(self): - "Translate critical-level log messages." - return self._make_log_translation_func('critical') - - -# NOTE(dhellmann): When this module moves out of the incubator into -# oslo.i18n, these global variables can be moved to an integration -# module within each application. - -# Create the global translation functions. -_translators = TranslatorFactory('cinderclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical - -# NOTE(dhellmann): End of globals that will move to the application's -# integration module. - - -def enable_lazy(): - """Convenience function for configuring _() to use lazy gettext - - Call this at the start of execution to enable the gettextutils._ - function to use lazy gettext functionality. This is useful if - your project is importing _ directly instead of using the - gettextutils.install() way of importing the _ function. - """ - global USE_LAZY - USE_LAZY = True - - -def install(domain): - """Install a _() function using the given translation domain. - - Given a translation domain, install a _() function using gettext's - install() function. - - The main difference from gettext.install() is that we allow - overriding the default localedir (e.g. /usr/share/locale) using - a translation-domain-specific environment variable (e.g. - NOVA_LOCALEDIR). - - Note that to enable lazy translation, enable_lazy must be - called. - - :param domain: the translation domain - """ - from six import moves - tf = TranslatorFactory(domain) - moves.builtins.__dict__['_'] = tf.primary - - -class Message(six.text_type): - """A Message object is a unicode object that can be translated. - - Translation of Message is done explicitly using the translate() method. - For all non-translation intents and purposes, a Message is simply unicode, - and can be treated as such. - """ - - def __new__(cls, msgid, msgtext=None, params=None, - domain='cinderclient', *args): - """Create a new Message object. - - In order for translation to work gettext requires a message ID, this - msgid will be used as the base unicode text. It is also possible - for the msgid and the base unicode text to be different by passing - the msgtext parameter. - """ - # If the base msgtext is not given, we use the default translation - # of the msgid (which is in English) just in case the system locale is - # not English, so that the base text will be in that locale by default. - if not msgtext: - msgtext = Message._translate_msgid(msgid, domain) - # We want to initialize the parent unicode with the actual object that - # would have been plain unicode if 'Message' was not enabled. - msg = super(Message, cls).__new__(cls, msgtext) - msg.msgid = msgid - msg.domain = domain - msg.params = params - return msg - - def translate(self, desired_locale=None): - """Translate this message to the desired locale. - - :param desired_locale: The desired locale to translate the message to, - if no locale is provided the message will be - translated to the system's default locale. - - :returns: the translated message in unicode - """ - - translated_message = Message._translate_msgid(self.msgid, - self.domain, - desired_locale) - if self.params is None: - # No need for more translation - return translated_message - - # This Message object may have been formatted with one or more - # Message objects as substitution arguments, given either as a single - # argument, part of a tuple, or as one or more values in a dictionary. - # When translating this Message we need to translate those Messages too - translated_params = _translate_args(self.params, desired_locale) - - translated_message = translated_message % translated_params - - return translated_message - - @staticmethod - def _translate_msgid(msgid, domain, desired_locale=None): - if not desired_locale: - system_locale = locale.getdefaultlocale() - # If the system locale is not available to the runtime use English - if not system_locale[0]: - desired_locale = 'en_US' - else: - desired_locale = system_locale[0] - - locale_dir = os.environ.get(domain.upper() + '_LOCALEDIR') - lang = gettext.translation(domain, - localedir=locale_dir, - languages=[desired_locale], - fallback=True) - if six.PY3: - translator = lang.gettext - else: - translator = lang.ugettext - - translated_message = translator(msgid) - return translated_message - - def __mod__(self, other): - # When we mod a Message we want the actual operation to be performed - # by the parent class (i.e. unicode()), the only thing we do here is - # save the original msgid and the parameters in case of a translation - params = self._sanitize_mod_params(other) - unicode_mod = super(Message, self).__mod__(params) - modded = Message(self.msgid, - msgtext=unicode_mod, - params=params, - domain=self.domain) - return modded - - def _sanitize_mod_params(self, other): - """Sanitize the object being modded with this Message. - - - Add support for modding 'None' so translation supports it - - Trim the modded object, which can be a large dictionary, to only - those keys that would actually be used in a translation - - Snapshot the object being modded, in case the message is - translated, it will be used as it was when the Message was created - """ - if other is None: - params = (other,) - elif isinstance(other, dict): - # Merge the dictionaries - # Copy each item in case one does not support deep copy. - params = {} - if isinstance(self.params, dict): - for key, val in self.params.items(): - params[key] = self._copy_param(val) - for key, val in other.items(): - params[key] = self._copy_param(val) - else: - params = self._copy_param(other) - return params - - def _copy_param(self, param): - try: - return copy.deepcopy(param) - except Exception: - # Fallback to casting to unicode this will handle the - # python code-like objects that can't be deep-copied - return six.text_type(param) - - def __add__(self, other): - msg = _('Message objects do not support addition.') - raise TypeError(msg) - - def __radd__(self, other): - return self.__add__(other) - - if six.PY2: - def __str__(self): - # NOTE(luisg): Logging in python 2.6 tries to str() log records, - # and it expects specifically a UnicodeError in order to proceed. - msg = _('Message objects do not support str() because they may ' - 'contain non-ascii characters. ' - 'Please use unicode() or translate() instead.') - raise UnicodeError(msg) - - -def get_available_languages(domain): - """Lists the available languages for the given translation domain. - - :param domain: the domain to get languages for - """ - if domain in _AVAILABLE_LANGUAGES: - return copy.copy(_AVAILABLE_LANGUAGES[domain]) - - localedir = '%s_LOCALEDIR' % domain.upper() - find = lambda x: gettext.find(domain, - localedir=os.environ.get(localedir), - languages=[x]) - - # NOTE(mrodden): en_US should always be available (and first in case - # order matters) since our in-line message strings are en_US - language_list = ['en_US'] - # NOTE(luisg): Babel <1.0 used a function called list(), which was - # renamed to locale_identifiers() in >=1.0, the requirements master list - # requires >=0.9.6, uncapped, so defensively work with both. We can remove - # this check when the master list updates to >=1.0, and update all projects - list_identifiers = (getattr(localedata, 'list', None) or - getattr(localedata, 'locale_identifiers')) - locale_identifiers = list_identifiers() - - for i in locale_identifiers: - if find(i) is not None: - language_list.append(i) - - # NOTE(luisg): Babel>=1.0,<1.3 has a bug where some OpenStack supported - # locales (e.g. 'zh_CN', and 'zh_TW') aren't supported even though they - # are perfectly legitimate locales: - # https://github.com/mitsuhiko/babel/issues/37 - # In Babel 1.3 they fixed the bug and they support these locales, but - # they are still not explicitly "listed" by locale_identifiers(). - # That is why we add the locales here explicitly if necessary so that - # they are listed as supported. - aliases = {'zh': 'zh_CN', - 'zh_Hant_HK': 'zh_HK', - 'zh_Hant': 'zh_TW', - 'fil': 'tl_PH'} - for (locale_, alias) in six.iteritems(aliases): - if locale_ in language_list and alias not in language_list: - language_list.append(alias) - - _AVAILABLE_LANGUAGES[domain] = language_list - return copy.copy(language_list) - - -def translate(obj, desired_locale=None): - """Gets the translated unicode representation of the given object. - - If the object is not translatable it is returned as-is. - If the locale is None the object is translated to the system locale. - - :param obj: the object to translate - :param desired_locale: the locale to translate the message to, if None the - default system locale will be used - :returns: the translated object in unicode, or the original object if - it could not be translated - """ - message = obj - if not isinstance(message, Message): - # If the object to translate is not already translatable, - # let's first get its unicode representation - message = six.text_type(obj) - if isinstance(message, Message): - # Even after unicoding() we still need to check if we are - # running with translatable unicode before translating - return message.translate(desired_locale) - return obj - - -def _translate_args(args, desired_locale=None): - """Translates all the translatable elements of the given arguments object. - - This method is used for translating the translatable values in method - arguments which include values of tuples or dictionaries. - If the object is not a tuple or a dictionary the object itself is - translated if it is translatable. - - If the locale is None the object is translated to the system locale. - - :param args: the args to translate - :param desired_locale: the locale to translate the args to, if None the - default system locale will be used - :returns: a new args object with the translated contents of the original - """ - if isinstance(args, tuple): - return tuple(translate(v, desired_locale) for v in args) - if isinstance(args, dict): - translated_dict = {} - for (k, v) in six.iteritems(args): - translated_v = translate(v, desired_locale) - translated_dict[k] = translated_v - return translated_dict - return translate(args, desired_locale) - - -class TranslationHandler(handlers.MemoryHandler): - """Handler that translates records before logging them. - - The TranslationHandler takes a locale and a target logging.Handler object - to forward LogRecord objects to after translating them. This handler - depends on Message objects being logged, instead of regular strings. - - The handler can be configured declaratively in the logging.conf as follows: - - [handlers] - keys = translatedlog, translator - - [handler_translatedlog] - class = handlers.WatchedFileHandler - args = ('/var/log/api-localized.log',) - formatter = context - - [handler_translator] - class = openstack.common.log.TranslationHandler - target = translatedlog - args = ('zh_CN',) - - If the specified locale is not available in the system, the handler will - log in the default locale. - """ - - def __init__(self, locale=None, target=None): - """Initialize a TranslationHandler - - :param locale: locale to use for translating messages - :param target: logging.Handler object to forward - LogRecord objects to after translation - """ - # NOTE(luisg): In order to allow this handler to be a wrapper for - # other handlers, such as a FileHandler, and still be able to - # configure it using logging.conf, this handler has to extend - # MemoryHandler because only the MemoryHandlers' logging.conf - # parsing is implemented such that it accepts a target handler. - handlers.MemoryHandler.__init__(self, capacity=0, target=target) - self.locale = locale - - def setFormatter(self, fmt): - self.target.setFormatter(fmt) - - def emit(self, record): - # We save the message from the original record to restore it - # after translation, so other handlers are not affected by this - original_msg = record.msg - original_args = record.args - - try: - self._translate_and_log_record(record) - finally: - record.msg = original_msg - record.args = original_args - - def _translate_and_log_record(self, record): - record.msg = translate(record.msg, self.locale) - - # In addition to translating the message, we also need to translate - # arguments that were passed to the log method that were not part - # of the main message e.g., log.info(_('Some message %s'), this_one)) - record.args = _translate_args(record.args, self.locale) - - self.target.emit(record) diff --git a/awx/lib/site-packages/cinderclient/openstack/common/importutils.py b/awx/lib/site-packages/cinderclient/openstack/common/importutils.py deleted file mode 100644 index 4fd9ae2bc2..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/importutils.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class.""" - mod_str, _sep, class_str = import_str.rpartition('.') - try: - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - except (ValueError, AttributeError): - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """Tries to import object from default namespace. - - Imports a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/awx/lib/site-packages/cinderclient/openstack/common/strutils.py b/awx/lib/site-packages/cinderclient/openstack/common/strutils.py deleted file mode 100644 index dcccf6162a..0000000000 --- a/awx/lib/site-packages/cinderclient/openstack/common/strutils.py +++ /dev/null @@ -1,295 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -System-level utilities and helper functions. -""" - -import math -import re -import sys -import unicodedata - -import six - -from cinderclient.openstack.common.gettextutils import _ - - -UNIT_PREFIX_EXPONENT = { - 'k': 1, - 'K': 1, - 'Ki': 1, - 'M': 2, - 'Mi': 2, - 'G': 3, - 'Gi': 3, - 'T': 4, - 'Ti': 4, -} -UNIT_SYSTEM_INFO = { - 'IEC': (1024, re.compile(r'(^[-+]?\d*\.?\d+)([KMGT]i?)?(b|bit|B)$')), - 'SI': (1000, re.compile(r'(^[-+]?\d*\.?\d+)([kMGT])?(b|bit|B)$')), -} - -TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes') -FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no') - -SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]") -SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+") - - -# NOTE(flaper87): The following 3 globals are used by `mask_password` -_SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password'] - -# NOTE(ldbragst): Let's build a list of regex objects using the list of -# _SANITIZE_KEYS we already have. This way, we only have to add the new key -# to the list of _SANITIZE_KEYS and we can generate regular expressions -# for XML and JSON automatically. -_SANITIZE_PATTERNS = [] -_FORMAT_PATTERNS = [r'(%(key)s\s*[=]\s*[\"\']).*?([\"\'])', - r'(<%(key)s>).*?(</%(key)s>)', - r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])', - r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])', - r'([\'"].*?%(key)s[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?[\'"])' - '.*?([\'"])', - r'(%(key)s\s*--?[A-z]+\s*)\S+(\s*)'] - -for key in _SANITIZE_KEYS: - for pattern in _FORMAT_PATTERNS: - reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) - _SANITIZE_PATTERNS.append(reg_ex) - - -def int_from_bool_as_string(subject): - """Interpret a string as a boolean and return either 1 or 0. - - Any string value in: - - ('True', 'true', 'On', 'on', '1') - - is interpreted as a boolean True. - - Useful for JSON-decoded stuff and config file parsing - """ - return bool_from_string(subject) and 1 or 0 - - -def bool_from_string(subject, strict=False, default=False): - """Interpret a string as a boolean. - - A case-insensitive match is performed such that strings matching 't', - 'true', 'on', 'y', 'yes', or '1' are considered True and, when - `strict=False`, anything else returns the value specified by 'default'. - - Useful for JSON-decoded stuff and config file parsing. - - If `strict=True`, unrecognized values, including None, will raise a - ValueError which is useful when parsing values passed in from an API call. - Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. - """ - if not isinstance(subject, six.string_types): - subject = six.text_type(subject) - - lowered = subject.strip().lower() - - if lowered in TRUE_STRINGS: - return True - elif lowered in FALSE_STRINGS: - return False - elif strict: - acceptable = ', '.join( - "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) - msg = _("Unrecognized value '%(val)s', acceptable values are:" - " %(acceptable)s") % {'val': subject, - 'acceptable': acceptable} - raise ValueError(msg) - else: - return default - - -def safe_decode(text, incoming=None, errors='strict'): - """Decodes incoming text/bytes string using `incoming` if they're not - already unicode. - - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a unicode `incoming` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be decoded" % type(text)) - - if isinstance(text, six.text_type): - return text - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - try: - return text.decode(incoming, errors) - except UnicodeDecodeError: - # Note(flaper87) If we get here, it means that - # sys.stdin.encoding / sys.getdefaultencoding - # didn't return a suitable encoding to decode - # text. This happens mostly when global LANG - # var is not set correctly and there's no - # default encoding. In this case, most likely - # python will use ASCII or ANSI encoders as - # default encodings but they won't be capable - # of decoding non-ASCII characters. - # - # Also, UTF-8 is being used since it's an ASCII - # extension. - return text.decode('utf-8', errors) - - -def safe_encode(text, incoming=None, - encoding='utf-8', errors='strict'): - """Encodes incoming text/bytes string using `encoding`. - - If incoming is not specified, text is expected to be encoded with - current python's default encoding. (`sys.getdefaultencoding`) - - :param incoming: Text's current encoding - :param encoding: Expected encoding for text (Default UTF-8) - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a bytestring `encoding` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be encoded" % type(text)) - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - if isinstance(text, six.text_type): - return text.encode(encoding, errors) - elif text and encoding != incoming: - # Decode text before encoding it with `encoding` - text = safe_decode(text, incoming, errors) - return text.encode(encoding, errors) - else: - return text - - -def string_to_bytes(text, unit_system='IEC', return_int=False): - """Converts a string into an float representation of bytes. - - The units supported for IEC :: - - Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it) - KB, KiB, MB, MiB, GB, GiB, TB, TiB - - The units supported for SI :: - - kb(it), Mb(it), Gb(it), Tb(it) - kB, MB, GB, TB - - Note that the SI unit system does not support capital letter 'K' - - :param text: String input for bytes size conversion. - :param unit_system: Unit system for byte size conversion. - :param return_int: If True, returns integer representation of text - in bytes. (default: decimal) - :returns: Numerical representation of text in bytes. - :raises ValueError: If text has an invalid value. - - """ - try: - base, reg_ex = UNIT_SYSTEM_INFO[unit_system] - except KeyError: - msg = _('Invalid unit system: "%s"') % unit_system - raise ValueError(msg) - match = reg_ex.match(text) - if match: - magnitude = float(match.group(1)) - unit_prefix = match.group(2) - if match.group(3) in ['b', 'bit']: - magnitude /= 8 - else: - msg = _('Invalid string format: %s') % text - raise ValueError(msg) - if not unit_prefix: - res = magnitude - else: - res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix]) - if return_int: - return int(math.ceil(res)) - return res - - -def to_slug(value, incoming=None, errors="strict"): - """Normalize string. - - Convert to lowercase, remove non-word characters, and convert spaces - to hyphens. - - Inspired by Django's `slugify` filter. - - :param value: Text to slugify - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: slugified unicode representation of `value` - :raises TypeError: If text is not an instance of str - """ - value = safe_decode(value, incoming, errors) - # NOTE(aababilov): no need to use safe_(encode|decode) here: - # encodings are always "ascii", error handling is always "ignore" - # and types are always known (first: unicode; second: str) - value = unicodedata.normalize("NFKD", value).encode( - "ascii", "ignore").decode("ascii") - value = SLUGIFY_STRIP_RE.sub("", value).strip().lower() - return SLUGIFY_HYPHENATE_RE.sub("-", value) - - -def mask_password(message, secret="***"): - """Replace password with 'secret' in message. - - :param message: The string which includes security information. - :param secret: value with which to replace passwords. - :returns: The unicode value of message with the password fields masked. - - For example: - - >>> mask_password("'adminPass' : 'aaaaa'") - "'adminPass' : '***'" - >>> mask_password("'admin_pass' : 'aaaaa'") - "'admin_pass' : '***'" - >>> mask_password('"password" : "aaaaa"') - '"password" : "***"' - >>> mask_password("'original_password' : 'aaaaa'") - "'original_password' : '***'" - >>> mask_password("u'original_password' : u'aaaaa'") - "u'original_password' : u'***'" - """ - message = six.text_type(message) - - # NOTE(ldbragst): Check to see if anything in message contains any key - # specified in _SANITIZE_KEYS, if not then just return the message since - # we don't have to mask any passwords. - if not any(key in message for key in _SANITIZE_KEYS): - return message - - secret = r'\g<1>' + secret + r'\g<2>' - for pattern in _SANITIZE_PATTERNS: - message = re.sub(pattern, secret, message) - return message diff --git a/awx/lib/site-packages/cinderclient/service_catalog.py b/awx/lib/site-packages/cinderclient/service_catalog.py deleted file mode 100644 index ce78b47be0..0000000000 --- a/awx/lib/site-packages/cinderclient/service_catalog.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright (c) 2011 OpenStack Foundation -# Copyright 2011, Piston Cloud Computing, Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import cinderclient.exceptions - - -class ServiceCatalog(object): - """Helper methods for dealing with a Keystone Service Catalog.""" - - def __init__(self, resource_dict): - self.catalog = resource_dict - - def get_token(self): - return self.catalog['access']['token']['id'] - - def url_for(self, attr=None, filter_value=None, - service_type=None, endpoint_type='publicURL', - service_name=None, volume_service_name=None): - """Fetch the public URL from the Compute service for - a particular endpoint attribute. If none given, return - the first. See tests for sample service catalog. - """ - matching_endpoints = [] - if 'endpoints' in self.catalog: - # We have a bastardized service catalog. Treat it special. :/ - for endpoint in self.catalog['endpoints']: - if not filter_value or endpoint[attr] == filter_value: - matching_endpoints.append(endpoint) - if not matching_endpoints: - raise cinderclient.exceptions.EndpointNotFound() - - # We don't always get a service catalog back ... - if 'serviceCatalog' not in self.catalog['access']: - return None - - # Full catalog ... - catalog = self.catalog['access']['serviceCatalog'] - - for service in catalog: - - # NOTE(thingee): For backwards compatibility, if they have v2 - # enabled and the service_type is set to 'volume', go ahead and - # accept that. - skip_service_type_check = False - if service_type == 'volumev2' and service['type'] == 'volume': - version = service['endpoints'][0]['publicURL'].split('/')[3] - if version == 'v2': - skip_service_type_check = True - - if (not skip_service_type_check - and service.get("type") != service_type): - continue - - if (volume_service_name and service_type in ('volume', 'volumev2') - and service.get('name') != volume_service_name): - continue - - endpoints = service['endpoints'] - for endpoint in endpoints: - if not filter_value or endpoint.get(attr) == filter_value: - endpoint["serviceName"] = service.get("name") - matching_endpoints.append(endpoint) - - if not matching_endpoints: - raise cinderclient.exceptions.EndpointNotFound() - elif len(matching_endpoints) > 1: - try: - eplist = [ep[attr] for ep in matching_endpoints] - except KeyError: - eplist = matching_endpoints - raise cinderclient.exceptions.AmbiguousEndpoints(endpoints=eplist) - else: - return matching_endpoints[0][endpoint_type] diff --git a/awx/lib/site-packages/cinderclient/shell.py b/awx/lib/site-packages/cinderclient/shell.py deleted file mode 100644 index 04dfe715e3..0000000000 --- a/awx/lib/site-packages/cinderclient/shell.py +++ /dev/null @@ -1,858 +0,0 @@ - -# Copyright 2011-2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Command-line interface to the OpenStack Cinder API. -""" - -from __future__ import print_function - -import argparse -import glob -import imp -import itertools -import logging -import os -import pkgutil -import sys - -import requests - -from cinderclient import client -from cinderclient import exceptions as exc -from cinderclient import utils -import cinderclient.auth_plugin -import cinderclient.extension -from cinderclient.openstack.common import strutils -from cinderclient.openstack.common.gettextutils import _ -from cinderclient.v1 import shell as shell_v1 -from cinderclient.v2 import shell as shell_v2 - -from keystoneclient import discover -from keystoneclient import session -from keystoneclient.auth.identity import v2 as v2_auth -from keystoneclient.auth.identity import v3 as v3_auth -from keystoneclient.exceptions import DiscoveryFailure -import six.moves.urllib.parse as urlparse - - -DEFAULT_OS_VOLUME_API_VERSION = "1" -DEFAULT_CINDER_ENDPOINT_TYPE = 'publicURL' -DEFAULT_CINDER_SERVICE_TYPE = 'volume' - -logging.basicConfig() -logger = logging.getLogger(__name__) - - -class CinderClientArgumentParser(argparse.ArgumentParser): - - def __init__(self, *args, **kwargs): - super(CinderClientArgumentParser, self).__init__(*args, **kwargs) - - def error(self, message): - """error(message: string) - - Prints a usage message incorporating the message to stderr and - exits. - """ - self.print_usage(sys.stderr) - # FIXME(lzyeval): if changes occur in argparse.ArgParser._check_value - choose_from = ' (choose from' - progparts = self.prog.partition(' ') - self.exit(2, "error: %(errmsg)s\nTry '%(mainp)s help %(subp)s'" - " for more information.\n" % - {'errmsg': message.split(choose_from)[0], - 'mainp': progparts[0], - 'subp': progparts[2]}) - - def _get_option_tuples(self, option_string): - """Avoid ambiguity in argument abbreviation. - - The idea of this method is to override the default behaviour to - avoid ambiguity in the abbreviation feature of argparse. - In the case that the ambiguity is generated by 2 or more parameters - and only one is visible in the help and the others are with - help=argparse.SUPPRESS, the ambiguity is solved by taking the visible - one. - The use case is for parameters that are left hidden for backward - compatibility. - """ - - result = super(CinderClientArgumentParser, self)._get_option_tuples( - option_string) - - if len(result) > 1: - aux = [x for x in result if x[0].help != argparse.SUPPRESS] - if len(aux) == 1: - result = aux - - return result - - -class OpenStackCinderShell(object): - - def get_base_parser(self): - parser = CinderClientArgumentParser( - prog='cinder', - description=__doc__.strip(), - epilog='Run "cinder help SUBCOMMAND" for help on a subcommand.', - add_help=False, - formatter_class=OpenStackHelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS) - - parser.add_argument('--version', - action='version', - version=cinderclient.__version__) - - parser.add_argument('--debug', - action='store_true', - default=utils.env('CINDERCLIENT_DEBUG', - default=False), - help="Shows debugging output.") - - parser.add_argument('--os-auth-system', - metavar='<auth-system>', - default=utils.env('OS_AUTH_SYSTEM'), - help='Defaults to env[OS_AUTH_SYSTEM].') - parser.add_argument('--os_auth_system', - help=argparse.SUPPRESS) - - parser.add_argument('--service-type', - metavar='<service-type>', - help='Service type. ' - 'For most actions, default is volume.') - parser.add_argument('--service_type', - help=argparse.SUPPRESS) - - parser.add_argument('--service-name', - metavar='<service-name>', - default=utils.env('CINDER_SERVICE_NAME'), - help='Service name. ' - 'Default=env[CINDER_SERVICE_NAME].') - parser.add_argument('--service_name', - help=argparse.SUPPRESS) - - parser.add_argument('--volume-service-name', - metavar='<volume-service-name>', - default=utils.env('CINDER_VOLUME_SERVICE_NAME'), - help='Volume service name. ' - 'Default=env[CINDER_VOLUME_SERVICE_NAME].') - parser.add_argument('--volume_service_name', - help=argparse.SUPPRESS) - - parser.add_argument('--endpoint-type', - metavar='<endpoint-type>', - default=utils.env('CINDER_ENDPOINT_TYPE', - default=DEFAULT_CINDER_ENDPOINT_TYPE), - help='Endpoint type, which is publicURL or ' - 'internalURL. ' - 'Default=nova env[CINDER_ENDPOINT_TYPE] or ' - + DEFAULT_CINDER_ENDPOINT_TYPE + '.') - - parser.add_argument('--endpoint_type', - help=argparse.SUPPRESS) - - parser.add_argument('--os-volume-api-version', - metavar='<volume-api-ver>', - default=utils.env('OS_VOLUME_API_VERSION', - default=None), - help='Block Storage API version. ' - 'Valid values are 1 or 2. ' - 'Default=env[OS_VOLUME_API_VERSION].') - parser.add_argument('--os_volume_api_version', - help=argparse.SUPPRESS) - - parser.add_argument('--retries', - metavar='<retries>', - type=int, - default=0, - help='Number of retries.') - - self._append_global_identity_args(parser) - - # The auth-system-plugins might require some extra options - cinderclient.auth_plugin.discover_auth_systems() - cinderclient.auth_plugin.load_auth_system_opts(parser) - - return parser - - def _append_global_identity_args(self, parser): - # FIXME(bklei): these are global identity (Keystone) arguments which - # should be consistent and shared by all service clients. Therefore, - # they should be provided by python-keystoneclient. We will need to - # refactor this code once this functionality is available in - # python-keystoneclient. - - parser.add_argument( - '--os-auth-strategy', metavar='<auth-strategy>', - default=utils.env('OS_AUTH_STRATEGY', default='keystone'), - help=_('Authentication strategy (Env: OS_AUTH_STRATEGY' - ', default keystone). For now, any other value will' - ' disable the authentication')) - parser.add_argument( - '--os_auth_strategy', - help=argparse.SUPPRESS) - - parser.add_argument('--os-username', - metavar='<auth-user-name>', - default=utils.env('OS_USERNAME', - 'CINDER_USERNAME'), - help='OpenStack user name. ' - 'Default=env[OS_USERNAME].') - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-password', - metavar='<auth-password>', - default=utils.env('OS_PASSWORD', - 'CINDER_PASSWORD'), - help='Password for OpenStack user. ' - 'Default=env[OS_PASSWORD].') - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - metavar='<auth-tenant-name>', - default=utils.env('OS_TENANT_NAME', - 'CINDER_PROJECT_ID'), - help='Tenant name. ' - 'Default=env[OS_TENANT_NAME].') - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - metavar='<auth-tenant-id>', - default=utils.env('OS_TENANT_ID', - 'CINDER_TENANT_ID'), - help='ID for the tenant. ' - 'Default=env[OS_TENANT_ID].') - parser.add_argument('--os_tenant_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-url', - metavar='<auth-url>', - default=utils.env('OS_AUTH_URL', - 'CINDER_URL'), - help='URL for the authentication service. ' - 'Default=env[OS_AUTH_URL].') - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-id', metavar='<auth-user-id>', - default=utils.env('OS_USER_ID'), - help=_('Authentication user ID (Env: OS_USER_ID)')) - - parser.add_argument( - '--os_user_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-domain-id', - metavar='<auth-user-domain-id>', - default=utils.env('OS_USER_DOMAIN_ID'), - help='OpenStack user domain ID. ' - 'Defaults to env[OS_USER_DOMAIN_ID].') - - parser.add_argument( - '--os_user_domain_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-domain-name', - metavar='<auth-user-domain-name>', - default=utils.env('OS_USER_DOMAIN_NAME'), - help='OpenStack user domain name. ' - 'Defaults to env[OS_USER_DOMAIN_NAME].') - - parser.add_argument( - '--os_user_domain_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-project-id', - metavar='<auth-project-id>', - default=utils.env('OS_PROJECT_ID'), - help='Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - ' --os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].') - - parser.add_argument( - '--os_project_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-project-name', - metavar='<auth-project-name>', - default=utils.env('OS_PROJECT_NAME'), - help='Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - ' --os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].') - - parser.add_argument( - '--os_project_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-project-domain-id', - metavar='<auth-project-domain-id>', - default=utils.env('OS_PROJECT_DOMAIN_ID'), - help='Defaults to env[OS_PROJECT_DOMAIN_ID].') - - parser.add_argument( - '--os-project-domain-name', - metavar='<auth-project-domain-name>', - default=utils.env('OS_PROJECT_DOMAIN_NAME'), - help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') - - parser.add_argument( - '--os-cert', - metavar='<certificate>', - default=utils.env('OS_CERT'), - help='Defaults to env[OS_CERT].') - - parser.add_argument( - '--os-key', - metavar='<key>', - default=utils.env('OS_KEY'), - help='Defaults to env[OS_KEY].') - - parser.add_argument('--os-region-name', - metavar='<region-name>', - default=utils.env('OS_REGION_NAME', - 'CINDER_REGION_NAME'), - help='Region name. ' - 'Default=env[OS_REGION_NAME].') - parser.add_argument('--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-token', metavar='<token>', - default=utils.env('OS_TOKEN'), - help=_('Defaults to env[OS_TOKEN]')) - parser.add_argument( - '--os_token', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-url', metavar='<url>', - default=utils.env('OS_URL'), - help=_('Defaults to env[OS_URL]')) - parser.add_argument( - '--os_url', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-cacert', - metavar='<ca-certificate>', - default=utils.env('OS_CACERT', default=None), - help=_("Specify a CA bundle file to use in " - "verifying a TLS (https) server certificate. " - "Defaults to env[OS_CACERT]")) - - parser.add_argument('--insecure', - default=utils.env('CINDERCLIENT_INSECURE', - default=False), - action='store_true', - help=argparse.SUPPRESS) - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='<subcommand>') - - try: - actions_module = { - '1.1': shell_v1, - '2': shell_v2, - }[version] - except KeyError: - actions_module = shell_v1 - - self._find_actions(subparsers, actions_module) - self._find_actions(subparsers, self) - - for extension in self.extensions: - self._find_actions(subparsers, extension.module) - - self._add_bash_completion_subparser(subparsers) - - return parser - - def _discover_extensions(self, version): - extensions = [] - for name, module in itertools.chain( - self._discover_via_python_path(version), - self._discover_via_contrib_path(version)): - - extension = cinderclient.extension.Extension(name, module) - extensions.append(extension) - - return extensions - - def _discover_via_python_path(self, version): - for (module_loader, name, ispkg) in pkgutil.iter_modules(): - if name.endswith('python_cinderclient_ext'): - if not hasattr(module_loader, 'load_module'): - # Python 2.6 compat: actually get an ImpImporter obj - module_loader = module_loader.find_module(name) - - module = module_loader.load_module(name) - yield name, module - - def _discover_via_contrib_path(self, version): - module_path = os.path.dirname(os.path.abspath(__file__)) - version_str = "v%s" % version.replace('.', '_') - ext_path = os.path.join(module_path, version_str, 'contrib') - ext_glob = os.path.join(ext_path, "*.py") - - for ext_path in glob.iglob(ext_glob): - name = os.path.basename(ext_path)[:-3] - - if name == "__init__": - continue - - module = imp.load_source(name, ext_path) - yield name, module - - def _add_bash_completion_subparser(self, subparsers): - subparser = subparsers.add_parser( - 'bash_completion', - add_help=False, - formatter_class=OpenStackHelpFormatter) - - self.subcommands['bash_completion'] = subparser - subparser.set_defaults(func=self.do_bash_completion) - - def _find_actions(self, subparsers, actions_module): - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hyphen-separated instead of underscores. - command = attr[3:].replace('_', '-') - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - help = desc.strip().split('\n')[0] - arguments = getattr(callback, 'arguments', []) - - subparser = subparsers.add_parser( - command, - help=help, - description=desc, - add_help=False, - formatter_class=OpenStackHelpFormatter) - - subparser.add_argument('-h', '--help', - action='help', - help=argparse.SUPPRESS,) - - self.subcommands[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - def setup_debugging(self, debug): - if not debug: - return - - streamhandler = logging.StreamHandler() - streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" - streamhandler.setFormatter(logging.Formatter(streamformat)) - logger.setLevel(logging.WARNING) - logger.addHandler(streamhandler) - - client_logger = logging.getLogger(client.__name__) - ch = logging.StreamHandler() - client_logger.setLevel(logging.DEBUG) - client_logger.addHandler(ch) - if hasattr(requests, 'logging'): - requests.logging.getLogger(requests.__name__).addHandler(ch) - # required for logging when using a keystone session - ks_logger = logging.getLogger("keystoneclient") - ks_logger.setLevel(logging.DEBUG) - - def main(self, argv): - - # Parse args once to find version and debug settings - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - self.setup_debugging(options.debug) - api_version_input = True - self.options = options - - if not options.os_volume_api_version: - # Environment variable OS_VOLUME_API_VERSION was - # not set and '--os-volume-api-version' option doesn't - # specify a value. Fall back to default. - options.os_volume_api_version = DEFAULT_OS_VOLUME_API_VERSION - api_version_input = False - - # build available subcommands based on version - self.extensions = self._discover_extensions( - options.os_volume_api_version) - self._run_extension_hooks('__pre_parse_args__') - - subcommand_parser = self.get_subcommand_parser( - options.os_volume_api_version) - self.parser = subcommand_parser - - if options.help or not argv: - subcommand_parser.print_help() - return 0 - - args = subcommand_parser.parse_args(argv) - self._run_extension_hooks('__post_parse_args__', args) - - # Short-circuit and deal with help right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion(args) - return 0 - - (os_username, os_password, os_tenant_name, os_auth_url, - os_region_name, os_tenant_id, endpoint_type, insecure, - service_type, service_name, volume_service_name, - cacert, os_auth_system) = ( - args.os_username, args.os_password, - args.os_tenant_name, args.os_auth_url, - args.os_region_name, args.os_tenant_id, - args.endpoint_type, args.insecure, - args.service_type, args.service_name, - args.volume_service_name, args.os_cacert, - args.os_auth_system) - - if os_auth_system and os_auth_system != "keystone": - auth_plugin = cinderclient.auth_plugin.load_plugin(os_auth_system) - else: - auth_plugin = None - - if not endpoint_type: - endpoint_type = DEFAULT_CINDER_ENDPOINT_TYPE - - if not service_type: - service_type = DEFAULT_CINDER_SERVICE_TYPE - service_type = utils.get_service_type(args.func) or service_type - - # FIXME(usrleon): Here should be restrict for project id same as - # for os_username or os_password but for compatibility it is not. - - if not utils.isunauthenticated(args.func): - if auth_plugin: - auth_plugin.parse_opts(args) - - if not auth_plugin or not auth_plugin.opts: - if not os_username: - raise exc.CommandError("You must provide a user name " - "through --os-username or " - "env[OS_USERNAME].") - - if not os_password: - raise exc.CommandError("You must provide a password " - "through --os-password or " - "env[OS_PASSWORD].") - - if not (os_tenant_name or os_tenant_id): - raise exc.CommandError("You must provide a tenant ID " - "through --os-tenant-id or " - "env[OS_TENANT_ID].") - - # V3 stuff - project_info_provided = self.options.os_tenant_name or \ - self.options.os_tenant_id or \ - (self.options.os_project_name and - (self.options.project_domain_name or - self.options.project_domain_id)) or \ - self.options.os_project_id - - if (not project_info_provided): - raise exc.CommandError( - _("You must provide a tenant_name, tenant_id, " - "project_id or project_name (with " - "project_domain_name or project_domain_id) via " - " --os-tenant-name (env[OS_TENANT_NAME])," - " --os-tenant-id (env[OS_TENANT_ID])," - " --os-project-id (env[OS_PROJECT_ID])" - " --os-project-name (env[OS_PROJECT_NAME])," - " --os-project-domain-id " - "(env[OS_PROJECT_DOMAIN_ID])" - " --os-project-domain-name " - "(env[OS_PROJECT_DOMAIN_NAME])")) - - if not os_auth_url: - if os_auth_system and os_auth_system != 'keystone': - os_auth_url = auth_plugin.get_auth_url() - - if not os_auth_url: - raise exc.CommandError( - "You must provide an authentication URL " - "through --os-auth-url or env[OS_AUTH_URL].") - - if not (os_tenant_name or os_tenant_id): - raise exc.CommandError( - "You must provide a tenant ID " - "through --os-tenant-id or env[OS_TENANT_ID].") - - if not os_auth_url: - raise exc.CommandError( - "You must provide an authentication URL " - "through --os-auth-url or env[OS_AUTH_URL].") - - auth_session = self._get_keystone_session() - - self.cs = client.Client(options.os_volume_api_version, os_username, - os_password, os_tenant_name, os_auth_url, - insecure, region_name=os_region_name, - tenant_id=os_tenant_id, - endpoint_type=endpoint_type, - extensions=self.extensions, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - retries=options.retries, - http_log_debug=args.debug, - cacert=cacert, auth_system=os_auth_system, - auth_plugin=auth_plugin, - session=auth_session) - - try: - if not utils.isunauthenticated(args.func): - self.cs.authenticate() - except exc.Unauthorized: - raise exc.CommandError("OpenStack credentials are not valid.") - except exc.AuthorizationFailure: - raise exc.CommandError("Unable to authorize user.") - - endpoint_api_version = None - # Try to get the API version from the endpoint URL. If that fails fall - # back to trying to use what the user specified via - # --os-volume-api-version or with the OS_VOLUME_API_VERSION environment - # variable. Fail safe is to use the default API setting. - try: - endpoint_api_version = \ - self.cs.get_volume_api_version_from_endpoint() - if endpoint_api_version != options.os_volume_api_version: - msg = (("OpenStack Block Storage API version is set to %s " - "but you are accessing a %s endpoint. " - "Change its value through --os-volume-api-version " - "or env[OS_VOLUME_API_VERSION].") - % (options.os_volume_api_version, endpoint_api_version)) - raise exc.InvalidAPIVersion(msg) - except exc.UnsupportedVersion: - endpoint_api_version = options.os_volume_api_version - if api_version_input: - logger.warning("Cannot determine the API version from " - "the endpoint URL. Falling back to the " - "user-specified version: %s" % - endpoint_api_version) - else: - logger.warning("Cannot determine the API version from the " - "endpoint URL or user input. Falling back " - "to the default API version: %s" % - endpoint_api_version) - - args.func(self.cs, args) - - def _run_extension_hooks(self, hook_type, *args, **kwargs): - """Runs hooks for all registered extensions.""" - for extension in self.extensions: - extension.run_hooks(hook_type, *args, **kwargs) - - def do_bash_completion(self, args): - """Prints arguments for bash_completion. - - Prints all commands and options to stdout so that the - cinder.bash_completion script does not have to hard code them. - """ - commands = set() - options = set() - for sc_str, sc in list(self.subcommands.items()): - commands.add(sc_str) - for option in sc._optionals._option_string_actions: - options.add(option) - - commands.remove('bash-completion') - commands.remove('bash_completion') - print(' '.join(commands | options)) - - @utils.arg('command', metavar='<subcommand>', nargs='?', - help='Shows help for <subcommand>.') - def do_help(self, args): - """ - Shows help about this program or one of its subcommands. - """ - if args.command: - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError("'%s' is not a valid subcommand" % - args.command) - else: - self.parser.print_help() - - def get_v2_auth(self, v2_auth_url): - - username = self.options.os_username - password = self.options.os_password - tenant_id = self.options.os_tenant_id - tenant_name = self.options.os_tenant_name - - return v2_auth.Password( - v2_auth_url, - username=username, - password=password, - tenant_id=tenant_id, - tenant_name=tenant_name) - - def get_v3_auth(self, v3_auth_url): - - username = self.options.os_username - user_id = self.options.os_user_id - user_domain_name = self.options.os_user_domain_name - user_domain_id = self.options.os_user_domain_id - password = self.options.os_password - project_id = self.options.os_project_id or self.options.os_tenant_id - project_name = (self.options.os_project_name - or self.options.os_tenant_name) - project_domain_name = self.options.os_project_domain_name - project_domain_id = self.options.os_project_domain_id - - return v3_auth.Password( - v3_auth_url, - username=username, - password=password, - user_id=user_id, - user_domain_name=user_domain_name, - user_domain_id=user_domain_id, - project_id=project_id, - project_name=project_name, - project_domain_name=project_domain_name, - project_domain_id=project_domain_id, - ) - - def _discover_auth_versions(self, session, auth_url): - # discover the API versions the server is supporting based on the - # given URL - v2_auth_url = None - v3_auth_url = None - try: - ks_discover = discover.Discover(session=session, auth_url=auth_url) - v2_auth_url = ks_discover.url_for('2.0') - v3_auth_url = ks_discover.url_for('3.0') - except DiscoveryFailure: - # Discovery response mismatch. Raise the error - raise - except Exception: - # Some public clouds throw some other exception or doesn't support - # discovery. In that case try to determine version from auth_url - # API version from the original URL - url_parts = urlparse.urlparse(auth_url) - (scheme, netloc, path, params, query, fragment) = url_parts - path = path.lower() - if path.startswith('/v3'): - v3_auth_url = auth_url - elif path.startswith('/v2'): - v2_auth_url = auth_url - else: - raise exc.CommandError('Unable to determine the Keystone' - ' version to authenticate with ' - 'using the given auth_url.') - - return (v2_auth_url, v3_auth_url) - - def _get_keystone_session(self, **kwargs): - # first create a Keystone session - cacert = self.options.os_cacert or None - cert = self.options.os_cert or None - insecure = self.options.insecure or False - - if insecure: - verify = False - else: - verify = cacert or True - - ks_session = session.Session(verify=verify, cert=cert) - # discover the supported keystone versions using the given url - (v2_auth_url, v3_auth_url) = self._discover_auth_versions( - session=ks_session, - auth_url=self.options.os_auth_url) - - username = self.options.os_username or None - user_domain_name = self.options.os_user_domain_name or None - user_domain_id = self.options.os_user_domain_id or None - - auth = None - if v3_auth_url and v2_auth_url: - # support both v2 and v3 auth. Use v3 if possible. - if username: - if user_domain_name or user_domain_id: - # use v3 auth - auth = self.get_v3_auth(v3_auth_url) - else: - # use v2 auth - auth = self.get_v2_auth(v2_auth_url) - - elif v3_auth_url: - # support only v3 - auth = self.get_v3_auth(v3_auth_url) - elif v2_auth_url: - # support only v2 - auth = self.get_v2_auth(v2_auth_url) - else: - raise exc.CommandError('Unable to determine the Keystone version ' - 'to authenticate with using the given ' - 'auth_url.') - - ks_session.auth = auth - return ks_session - -# I'm picky about my shell help. - - -class OpenStackHelpFormatter(argparse.HelpFormatter): - - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(OpenStackHelpFormatter, self).start_section(heading) - - -def main(): - try: - if sys.version_info >= (3, 0): - OpenStackCinderShell().main(sys.argv[1:]) - else: - OpenStackCinderShell().main(map(strutils.safe_decode, - sys.argv[1:])) - except KeyboardInterrupt: - print("... terminating cinder client", file=sys.stderr) - sys.exit(130) - except Exception as e: - logger.debug(e, exc_info=1) - print("ERROR: %s" % strutils.six.text_type(e), file=sys.stderr) - sys.exit(1) - - -if __name__ == "__main__": - - main() diff --git a/awx/lib/site-packages/cinderclient/tests/__init__.py b/awx/lib/site-packages/cinderclient/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/tests/fakes.py b/awx/lib/site-packages/cinderclient/tests/fakes.py deleted file mode 100644 index eede6945dd..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/fakes.py +++ /dev/null @@ -1,118 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -from __future__ import print_function - - -def assert_has_keys(dict, required=[], optional=[]): - for k in required: - try: - assert k in dict - except AssertionError: - extra_keys = set(dict).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class FakeClient(object): - - def _dict_match(self, partial, real): - - result = True - try: - for key, value in partial.items(): - if type(value) is dict: - result = self._dict_match(value, real[key]) - else: - assert real[key] == value - result = True - except (AssertionError, KeyError): - result = False - return result - - def assert_called(self, method, url, body=None, - partial_body=None, pos=-1, **kwargs): - """ - Assert than an API method was just called. - """ - expected = (method, url) - called = self.client.callstack[pos][0:2] - - assert self.client.callstack, ("Expected %s %s but no calls " - "were made." % expected) - - assert expected == called, 'Expected %s %s; got %s %s' % ( - expected + called) - - if body is not None: - assert self.client.callstack[pos][2] == body - - if partial_body is not None: - try: - assert self._dict_match(partial_body, - self.client.callstack[pos][2]) - except AssertionError: - print(self.client.callstack[pos][2]) - print("does not contain") - print(partial_body) - raise - - def assert_called_anytime(self, method, url, body=None, partial_body=None): - """ - Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.client.callstack, ("Expected %s %s but no calls " - "were made." % expected) - - found = False - for entry in self.client.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s %s; got %s' % ( - expected + (self.client.callstack, )) - - if body is not None: - try: - assert entry[2] == body - except AssertionError: - print(entry[2]) - print("!=") - print(body) - raise - - if partial_body is not None: - try: - assert self._dict_match(partial_body, entry[2]) - except AssertionError: - print(entry[2]) - print("does not contain") - print(partial_body) - raise - - def clear_callstack(self): - self.client.callstack = [] - - def authenticate(self): - pass diff --git a/awx/lib/site-packages/cinderclient/tests/fixture_data/__init__.py b/awx/lib/site-packages/cinderclient/tests/fixture_data/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/tests/fixture_data/availability_zones.py b/awx/lib/site-packages/cinderclient/tests/fixture_data/availability_zones.py deleted file mode 100644 index bb1bc68f12..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/fixture_data/availability_zones.py +++ /dev/null @@ -1,80 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from datetime import datetime -from cinderclient.tests.fixture_data import base - -# FIXME(jamielennox): use timeutils from oslo -FORMAT = '%Y-%m-%d %H:%M:%S' - - -class Fixture(base.Fixture): - - base_url = 'os-availability-zone' - - def setUp(self): - super(Fixture, self).setUp() - - get_availability = { - "availabilityZoneInfo": [ - { - "zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": None, - }, - { - "zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None, - }, - ] - } - self.requests.register_uri('GET', self.url(), json=get_availability) - - updated_1 = datetime(2012, 12, 26, 14, 45, 25, 0).strftime(FORMAT) - updated_2 = datetime(2012, 12, 26, 14, 45, 24, 0).strftime(FORMAT) - get_detail = { - "availabilityZoneInfo": [ - { - "zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "cinder-volume": { - "active": True, - "available": True, - "updated_at": updated_1, - } - } - } - }, - { - "zoneName": "internal", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "cinder-sched": { - "active": True, - "available": True, - "updated_at": updated_2, - } - } - } - }, - { - "zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None, - }, - ] - } - self.requests.register_uri('GET', self.url('detail'), json=get_detail) diff --git a/awx/lib/site-packages/cinderclient/tests/fixture_data/base.py b/awx/lib/site-packages/cinderclient/tests/fixture_data/base.py deleted file mode 100644 index 9406daf9ea..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/fixture_data/base.py +++ /dev/null @@ -1,38 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures - -IDENTITY_URL = 'http://identityserver:5000/v2.0' -VOLUME_URL = 'http://volume.host' - - -class Fixture(fixtures.Fixture): - - base_url = None - json_headers = {'Content-Type': 'application/json'} - - def __init__(self, requests, - volume_url=VOLUME_URL, - identity_url=IDENTITY_URL): - super(Fixture, self).__init__() - self.requests = requests - self.volume_url = volume_url - self.identity_url = identity_url - - def url(self, *args): - url_args = [self.volume_url] - - if self.base_url: - url_args.append(self.base_url) - - return '/'.join(str(a).strip('/') for a in tuple(url_args) + args) diff --git a/awx/lib/site-packages/cinderclient/tests/fixture_data/client.py b/awx/lib/site-packages/cinderclient/tests/fixture_data/client.py deleted file mode 100644 index 47bbb64583..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/fixture_data/client.py +++ /dev/null @@ -1,64 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import fixture - -from cinderclient.tests.fixture_data import base -from cinderclient.v1 import client as v1client -from cinderclient.v2 import client as v2client - - -class Base(base.Fixture): - - def __init__(self, *args, **kwargs): - super(Base, self).__init__(*args, **kwargs) - - self.token = fixture.V2Token() - self.token.set_scope() - - def setUp(self): - super(Base, self).setUp() - - auth_url = '%s/tokens' % self.identity_url - self.requests.register_uri('POST', auth_url, - json=self.token, - headers=self.json_headers) - - -class V1(Base): - - def __init__(self, *args, **kwargs): - super(V1, self).__init__(*args, **kwargs) - - svc = self.token.add_service('volume') - svc.add_endpoint(self.volume_url) - - def new_client(self): - return v1client.Client(username='xx', - api_key='xx', - project_id='xx', - auth_url=self.identity_url) - - -class V2(Base): - - def __init__(self, *args, **kwargs): - super(V2, self).__init__(*args, **kwargs) - - svc = self.token.add_service('volumev2') - svc.add_endpoint(self.volume_url) - - def new_client(self): - return v2client.Client(username='xx', - api_key='xx', - project_id='xx', - auth_url=self.identity_url) diff --git a/awx/lib/site-packages/cinderclient/tests/fixture_data/keystone_client.py b/awx/lib/site-packages/cinderclient/tests/fixture_data/keystone_client.py deleted file mode 100644 index dc4c6c6d10..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/fixture_data/keystone_client.py +++ /dev/null @@ -1,230 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import json -import uuid - - -# these are copied from python-keystoneclient tests -BASE_HOST = 'http://keystone.example.com' -BASE_URL = "%s:5000/" % BASE_HOST -UPDATED = '2013-03-06T00:00:00Z' - -V2_URL = "%sv2.0" % BASE_URL -V2_DESCRIBED_BY_HTML = {'href': 'http://docs.openstack.org/api/' - 'openstack-identity-service/2.0/content/', - 'rel': 'describedby', - 'type': 'text/html'} - -V2_DESCRIBED_BY_PDF = {'href': 'http://docs.openstack.org/api/openstack-ident' - 'ity-service/2.0/identity-dev-guide-2.0.pdf', - 'rel': 'describedby', - 'type': 'application/pdf'} - -V2_VERSION = {'id': 'v2.0', - 'links': [{'href': V2_URL, 'rel': 'self'}, - V2_DESCRIBED_BY_HTML, V2_DESCRIBED_BY_PDF], - 'status': 'stable', - 'updated': UPDATED} - -V3_URL = "%sv3" % BASE_URL -V3_MEDIA_TYPES = [{'base': 'application/json', - 'type': 'application/vnd.openstack.identity-v3+json'}, - {'base': 'application/xml', - 'type': 'application/vnd.openstack.identity-v3+xml'}] - -V3_VERSION = {'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED} - -WRONG_VERSION_RESPONSE = {'id': 'v2.0', - 'links': [V2_DESCRIBED_BY_HTML, V2_DESCRIBED_BY_PDF], - 'status': 'stable', - 'updated': UPDATED} - - -def _create_version_list(versions): - return json.dumps({'versions': {'values': versions}}) - - -def _create_single_version(version): - return json.dumps({'version': version}) - - -V3_VERSION_LIST = _create_version_list([V3_VERSION, V2_VERSION]) -V2_VERSION_LIST = _create_version_list([V2_VERSION]) - -V3_VERSION_ENTRY = _create_single_version(V3_VERSION) -V2_VERSION_ENTRY = _create_single_version(V2_VERSION) - -CINDER_ENDPOINT = 'http://www.cinder.com/v1' - - -def _get_normalized_token_data(**kwargs): - ref = copy.deepcopy(kwargs) - # normalized token data - ref['user_id'] = ref.get('user_id', uuid.uuid4().hex) - ref['username'] = ref.get('username', uuid.uuid4().hex) - ref['project_id'] = ref.get('project_id', - ref.get('tenant_id', uuid.uuid4().hex)) - ref['project_name'] = ref.get('tenant_name', - ref.get('tenant_name', uuid.uuid4().hex)) - ref['user_domain_id'] = ref.get('user_domain_id', uuid.uuid4().hex) - ref['user_domain_name'] = ref.get('user_domain_name', uuid.uuid4().hex) - ref['project_domain_id'] = ref.get('project_domain_id', uuid.uuid4().hex) - ref['project_domain_name'] = ref.get('project_domain_name', - uuid.uuid4().hex) - ref['roles'] = ref.get('roles', [{'name': uuid.uuid4().hex, - 'id': uuid.uuid4().hex}]) - ref['roles_link'] = ref.get('roles_link', []) - ref['cinder_url'] = ref.get('cinder_url', CINDER_ENDPOINT) - - return ref - - -def generate_v2_project_scoped_token(**kwargs): - """Generate a Keystone V2 token based on auth request.""" - ref = _get_normalized_token_data(**kwargs) - token = uuid.uuid4().hex - - o = {'access': {'token': {'id': token, - 'expires': '2099-05-22T00:02:43.941430Z', - 'issued_at': '2013-05-21T00:02:43.941473Z', - 'tenant': {'enabled': True, - 'id': ref.get('project_id'), - 'name': ref.get('project_id') - } - }, - 'user': {'id': ref.get('user_id'), - 'name': uuid.uuid4().hex, - 'username': ref.get('username'), - 'roles': ref.get('roles'), - 'roles_links': ref.get('roles_links') - } - }} - - # we only care about Neutron and Keystone endpoints - o['access']['serviceCatalog'] = [ - {'endpoints': [ - {'publicURL': 'public_' + ref.get('cinder_url'), - 'internalURL': 'internal_' + ref.get('cinder_url'), - 'adminURL': 'admin_' + (ref.get('auth_url') or ""), - 'id': uuid.uuid4().hex, - 'region': 'RegionOne' - }], - 'endpoints_links': [], - 'name': 'Neutron', - 'type': 'network'}, - {'endpoints': [ - {'publicURL': ref.get('auth_url'), - 'adminURL': ref.get('auth_url'), - 'internalURL': ref.get('auth_url'), - 'id': uuid.uuid4().hex, - 'region': 'RegionOne' - }], - 'endpoint_links': [], - 'name': 'keystone', - 'type': 'identity'}] - - return token, o - - -def generate_v3_project_scoped_token(**kwargs): - """Generate a Keystone V3 token based on auth request.""" - ref = _get_normalized_token_data(**kwargs) - - o = {'token': {'expires_at': '2099-05-22T00:02:43.941430Z', - 'issued_at': '2013-05-21T00:02:43.941473Z', - 'methods': ['password'], - 'project': {'id': ref.get('project_id'), - 'name': ref.get('project_name'), - 'domain': {'id': ref.get('project_domain_id'), - 'name': ref.get( - 'project_domain_name') - } - }, - 'user': {'id': ref.get('user_id'), - 'name': ref.get('username'), - 'domain': {'id': ref.get('user_domain_id'), - 'name': ref.get('user_domain_name') - } - }, - 'roles': ref.get('roles') - }} - - # we only care about Neutron and Keystone endpoints - o['token']['catalog'] = [ - {'endpoints': [ - { - 'id': uuid.uuid4().hex, - 'interface': 'public', - 'region': 'RegionOne', - 'url': 'public_' + ref.get('cinder_url') - }, - { - 'id': uuid.uuid4().hex, - 'interface': 'internal', - 'region': 'RegionOne', - 'url': 'internal_' + ref.get('cinder_url') - }, - { - 'id': uuid.uuid4().hex, - 'interface': 'admin', - 'region': 'RegionOne', - 'url': 'admin_' + ref.get('cinder_url') - }], - 'id': uuid.uuid4().hex, - 'type': 'network'}, - {'endpoints': [ - { - 'id': uuid.uuid4().hex, - 'interface': 'public', - 'region': 'RegionOne', - 'url': ref.get('auth_url') - }, - { - 'id': uuid.uuid4().hex, - 'interface': 'admin', - 'region': 'RegionOne', - 'url': ref.get('auth_url') - }], - 'id': uuid.uuid4().hex, - 'type': 'identity'}] - - # token ID is conveyed via the X-Subject-Token header so we are generating - # one to stash there - token_id = uuid.uuid4().hex - - return token_id, o - - -def keystone_request_callback(request, context): - context.headers['Content-Type'] = 'application/json' - - if request.url == BASE_URL: - return V3_VERSION_LIST - elif request.url == BASE_URL + "/v2.0": - token_id, token_data = generate_v2_project_scoped_token() - return token_data - elif request.url == BASE_URL + "/v3": - token_id, token_data = generate_v3_project_scoped_token() - context.headers["X-Subject-Token"] = token_id - context.status_code = 201 - return token_data - elif "WrongDiscoveryResponse.discovery.com" in request.url: - return str(WRONG_VERSION_RESPONSE) - else: - context.status_code = 500 - return str(WRONG_VERSION_RESPONSE) diff --git a/awx/lib/site-packages/cinderclient/tests/fixture_data/snapshots.py b/awx/lib/site-packages/cinderclient/tests/fixture_data/snapshots.py deleted file mode 100644 index c37963923d..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/fixture_data/snapshots.py +++ /dev/null @@ -1,56 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json - -from cinderclient.tests.fixture_data import base - - -def _stub_snapshot(**kwargs): - snapshot = { - "created_at": "2012-08-28T16:30:31.000000", - "display_description": None, - "display_name": None, - "id": '11111111-1111-1111-1111-111111111111', - "size": 1, - "status": "available", - "volume_id": '00000000-0000-0000-0000-000000000000', - } - snapshot.update(kwargs) - return snapshot - - -class Fixture(base.Fixture): - - base_url = 'snapshots' - - def setUp(self): - super(Fixture, self).setUp() - - snapshot_1234 = _stub_snapshot(id='1234') - self.requests.register_uri('GET', self.url('1234'), - json={'snapshot': snapshot_1234}) - - def action_1234(request, context): - return '' - body = json.loads(request.body.decode('utf-8')) - assert len(list(body)) == 1 - action = list(body)[0] - if action == 'os-reset_status': - assert 'status' in body['os-reset_status'] - elif action == 'os-update_snapshot_status': - assert 'status' in body['os-update_snapshot_status'] - else: - raise AssertionError("Unexpected action: %s" % action) - return '' - self.requests.register_uri('POST', self.url('1234', 'action'), - text=action_1234, status_code=202) diff --git a/awx/lib/site-packages/cinderclient/tests/test_auth_plugins.py b/awx/lib/site-packages/cinderclient/tests/test_auth_plugins.py deleted file mode 100644 index 9a951148e9..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/test_auth_plugins.py +++ /dev/null @@ -1,346 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import mock -import pkg_resources -import requests - -try: - import json -except ImportError: - import simplejson as json - -from cinderclient import auth_plugin -from cinderclient import exceptions -from cinderclient.tests import utils -from cinderclient.v1 import client - - -def mock_http_request(resp=None): - """Mock an HTTP Request.""" - if not resp: - resp = { - "access": { - "token": { - "expires": "12345", - "id": "FAKE_ID", - "tenant": { - "id": "FAKE_TENANT_ID", - } - }, - "serviceCatalog": [ - { - "type": "volume", - "endpoints": [ - { - "region": "RegionOne", - "adminURL": "http://localhost:8774/v1.1", - "internalURL": "http://localhost:8774/v1.1", - "publicURL": "http://localhost:8774/v1.1/", - }, - ], - }, - ], - }, - } - - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - return mock.Mock(return_value=(auth_response)) - - -def requested_headers(cs): - """Return requested passed headers.""" - return { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - - -class DeprecatedAuthPluginTest(utils.TestCase): - def test_auth_system_success(self): - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.authenticate - - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - def mock_iter_entry_points(_type, name): - if _type == 'openstack.client.authenticate': - return [MockEntrypoint("fake", "fake", ["fake"])] - else: - return [] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - plugin = auth_plugin.DeprecatedAuthPlugin("fake") - cs = client.Client("username", "password", "project_id", - "auth_url/v2.0", auth_system="fake", - auth_plugin=plugin) - cs.client.authenticate() - - headers = requested_headers(cs) - token_url = cs.client.auth_url + "/tokens" - - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data='{"fake": "me"}', - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - test_auth_call() - - def test_auth_system_not_exists(self): - def mock_iter_entry_points(_t, name=None): - return [pkg_resources.EntryPoint("fake", "fake", ["fake"])] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - auth_plugin.discover_auth_systems() - plugin = auth_plugin.DeprecatedAuthPlugin("notexists") - cs = client.Client("username", "password", "project_id", - "auth_url/v2.0", auth_system="notexists", - auth_plugin=plugin) - self.assertRaises(exceptions.AuthSystemNotFound, - cs.client.authenticate) - - test_auth_call() - - def test_auth_system_defining_auth_url(self): - class MockAuthUrlEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.auth_url - - def auth_url(self): - return "http://faked/v2.0" - - class MockAuthenticateEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.authenticate - - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - def mock_iter_entry_points(_type, name): - if _type == 'openstack.client.auth_url': - return [MockAuthUrlEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["auth_url"])] - elif _type == 'openstack.client.authenticate': - return [MockAuthenticateEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["authenticate"])] - else: - return [] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl") - cs = client.Client("username", "password", "project_id", - auth_system="fakewithauthurl", - auth_plugin=plugin) - cs.client.authenticate() - self.assertEqual(cs.client.auth_url, "http://faked/v2.0") - - test_auth_call() - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_client_raises_exc_without_auth_url(self, mock_iter_entry_points): - class MockAuthUrlEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.auth_url - - def auth_url(self): - return None - - mock_iter_entry_points.side_effect = lambda _t, name: [ - MockAuthUrlEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["auth_url"])] - - plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl") - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fakewithauthurl", auth_plugin=plugin) - - -class AuthPluginTest(utils.TestCase): - @mock.patch.object(requests, "request") - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_auth_system_success(self, mock_iter_entry_points, mock_request): - """Test that we can authenticate using the auth system.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - mock_request.side_effect = mock_http_request() - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - cs = client.Client("username", "password", "project_id", - "auth_url/v2.0", auth_system="fake", - auth_plugin=plugin) - cs.client.authenticate() - - headers = requested_headers(cs) - token_url = cs.client.auth_url + "/tokens" - - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data='{"fake": "me"}', - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_discover_auth_system_options(self, mock_iter_entry_points): - """Test that we can load the auth system options.""" - class FakePlugin(auth_plugin.BaseAuthPlugin): - @staticmethod - def add_opts(parser): - parser.add_argument('--auth_system_opt', - default=False, - action='store_true', - help="Fake option") - return parser - - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - parser = argparse.ArgumentParser() - auth_plugin.discover_auth_systems() - auth_plugin.load_auth_system_opts(parser) - opts, args = parser.parse_known_args(['--auth_system_opt']) - - self.assertTrue(opts.auth_system_opt) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_parse_auth_system_options(self, mock_iter_entry_points): - """Test that we can parse the auth system options.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def __init__(self): - self.opts = {"fake_argument": True} - - def parse_opts(self, args): - return self.opts - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - plugin.parse_opts([]) - self.assertIn("fake_argument", plugin.opts) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_auth_system_defining_url(self, mock_iter_entry_points): - """Test the auth_system defining an url.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def get_auth_url(self): - return "http://faked/v2.0" - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - cs = client.Client("username", "password", "project_id", - auth_system="fakewithauthurl", - auth_plugin=plugin) - self.assertEqual(cs.client.auth_url, "http://faked/v2.0") - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_exception_if_no_authenticate(self, mock_iter_entry_points): - """Test that no authenticate raises a proper exception.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - pass - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fake", auth_plugin=plugin) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_exception_if_no_url(self, mock_iter_entry_points): - """Test that no auth_url at all raises exception.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - pass - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fake", auth_plugin=plugin) diff --git a/awx/lib/site-packages/cinderclient/tests/test_base.py b/awx/lib/site-packages/cinderclient/tests/test_base.py deleted file mode 100644 index 665940cde1..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/test_base.py +++ /dev/null @@ -1,61 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from cinderclient import base -from cinderclient import exceptions -from cinderclient.v1 import volumes -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class BaseTest(utils.TestCase): - - def test_resource_repr(self): - r = base.Resource(None, dict(foo="bar", baz="spam")) - self.assertEqual("<Resource baz=spam, foo=bar>", repr(r)) - - def test_getid(self): - self.assertEqual(4, base.getid(4)) - - class TmpObject(object): - id = 4 - self.assertEqual(4, base.getid(TmpObject)) - - def test_eq(self): - # Two resources of the same type with the same id: equal - r1 = base.Resource(None, {'id': 1, 'name': 'hi'}) - r2 = base.Resource(None, {'id': 1, 'name': 'hello'}) - self.assertEqual(r1, r2) - - # Two resoruces of different types: never equal - r1 = base.Resource(None, {'id': 1}) - r2 = volumes.Volume(None, {'id': 1}) - self.assertNotEqual(r1, r2) - - # Two resources with no ID: equal if their info is equal - r1 = base.Resource(None, {'name': 'joe', 'age': 12}) - r2 = base.Resource(None, {'name': 'joe', 'age': 12}) - self.assertEqual(r1, r2) - - def test_findall_invalid_attribute(self): - # Make sure findall with an invalid attribute doesn't cause errors. - # The following should not raise an exception. - cs.volumes.findall(vegetable='carrot') - - # However, find() should raise an error - self.assertRaises(exceptions.NotFound, - cs.volumes.find, - vegetable='carrot') diff --git a/awx/lib/site-packages/cinderclient/tests/test_client.py b/awx/lib/site-packages/cinderclient/tests/test_client.py deleted file mode 100644 index bc70f1bb8f..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/test_client.py +++ /dev/null @@ -1,63 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging - -import fixtures - -import cinderclient.client -import cinderclient.v1.client -import cinderclient.v2.client -from cinderclient.tests import utils - - -class ClientTest(utils.TestCase): - - def test_get_client_class_v1(self): - output = cinderclient.client.get_client_class('1') - self.assertEqual(cinderclient.v1.client.Client, output) - - def test_get_client_class_v2(self): - output = cinderclient.client.get_client_class('2') - self.assertEqual(cinderclient.v2.client.Client, output) - - def test_get_client_class_unknown(self): - self.assertRaises(cinderclient.exceptions.UnsupportedVersion, - cinderclient.client.get_client_class, '0') - - def test_log_req(self): - self.logger = self.useFixture( - fixtures.FakeLogger( - format="%(message)s", - level=logging.DEBUG, - nuke_handlers=True - ) - ) - - kwargs = {} - kwargs['headers'] = {"X-Foo": "bar"} - kwargs['data'] = ('{"auth": {"tenantName": "fakeService",' - ' "passwordCredentials": {"username": "fakeUser",' - ' "password": "fakePassword"}}}') - - cs = cinderclient.client.HTTPClient("user", None, None, - "http://127.0.0.1:5000") - cs.http_log_debug = True - cs.http_log_req('PUT', kwargs) - - output = self.logger.output.split('\n') - - print("JSBRYANT: output is", output) - - self.assertNotIn("fakePassword", output[1]) - self.assertIn("fakeUser", output[1]) diff --git a/awx/lib/site-packages/cinderclient/tests/test_http.py b/awx/lib/site-packages/cinderclient/tests/test_http.py deleted file mode 100644 index f0121ea94c..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/test_http.py +++ /dev/null @@ -1,243 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock - -import requests - -from cinderclient import client -from cinderclient import exceptions -from cinderclient.tests import utils - - -fake_response = utils.TestResponse({ - "status_code": 200, - "text": '{"hi": "there"}', -}) - -fake_response_empty = utils.TestResponse({ - "status_code": 200, - "text": '{"access": {}}' -}) - -mock_request = mock.Mock(return_value=(fake_response)) -mock_request_empty = mock.Mock(return_value=(fake_response_empty)) - -bad_400_response = utils.TestResponse({ - "status_code": 400, - "text": '{"error": {"message": "n/a", "details": "Terrible!"}}', -}) -bad_400_request = mock.Mock(return_value=(bad_400_response)) - -bad_401_response = utils.TestResponse({ - "status_code": 401, - "text": '{"error": {"message": "FAILED!", "details": "DETAILS!"}}', -}) -bad_401_request = mock.Mock(return_value=(bad_401_response)) - -bad_500_response = utils.TestResponse({ - "status_code": 500, - "text": '{"error": {"message": "FAILED!", "details": "DETAILS!"}}', -}) -bad_500_request = mock.Mock(return_value=(bad_500_response)) - -connection_error_request = mock.Mock( - side_effect=requests.exceptions.ConnectionError) - - -def get_client(retries=0): - cl = client.HTTPClient("username", "password", - "project_id", "auth_test", retries=retries) - return cl - - -def get_authed_client(retries=0): - cl = get_client(retries=retries) - cl.management_url = "http://example.com" - cl.auth_token = "token" - return cl - - -class ClientTest(utils.TestCase): - - def test_get(self): - cl = get_authed_client() - - @mock.patch.object(requests, "request", mock_request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - headers = {"X-Auth-Token": "token", - "X-Auth-Project-Id": "project_id", - "User-Agent": cl.USER_AGENT, - 'Accept': 'application/json', } - mock_request.assert_called_with( - "GET", - "http://example.com/hi", - headers=headers, - **self.TEST_REQUEST_BASE) - # Automatic JSON parsing - self.assertEqual({"hi": "there"}, body) - - test_get_call() - - def test_get_reauth_0_retries(self): - cl = get_authed_client(retries=0) - - self.requests = [bad_401_request, mock_request] - - def request(*args, **kwargs): - next_request = self.requests.pop(0) - return next_request(*args, **kwargs) - - def reauth(): - cl.management_url = "http://example.com" - cl.auth_token = "token" - - @mock.patch.object(cl, 'authenticate', reauth) - @mock.patch.object(requests, "request", request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - - test_get_call() - self.assertEqual([], self.requests) - - def test_get_retry_500(self): - cl = get_authed_client(retries=1) - - self.requests = [bad_500_request, mock_request] - - def request(*args, **kwargs): - next_request = self.requests.pop(0) - return next_request(*args, **kwargs) - - @mock.patch.object(requests, "request", request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - - test_get_call() - self.assertEqual([], self.requests) - - def test_get_retry_connection_error(self): - cl = get_authed_client(retries=1) - - self.requests = [connection_error_request, mock_request] - - def request(*args, **kwargs): - next_request = self.requests.pop(0) - return next_request(*args, **kwargs) - - @mock.patch.object(requests, "request", request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - - test_get_call() - self.assertEqual(self.requests, []) - - def test_retry_limit(self): - cl = get_authed_client(retries=1) - - self.requests = [bad_500_request, bad_500_request, mock_request] - - def request(*args, **kwargs): - next_request = self.requests.pop(0) - return next_request(*args, **kwargs) - - @mock.patch.object(requests, "request", request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - - self.assertRaises(exceptions.ClientException, test_get_call) - self.assertEqual([mock_request], self.requests) - - def test_get_no_retry_400(self): - cl = get_authed_client(retries=0) - - self.requests = [bad_400_request, mock_request] - - def request(*args, **kwargs): - next_request = self.requests.pop(0) - return next_request(*args, **kwargs) - - @mock.patch.object(requests, "request", request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - - self.assertRaises(exceptions.BadRequest, test_get_call) - self.assertEqual([mock_request], self.requests) - - def test_get_retry_400_socket(self): - cl = get_authed_client(retries=1) - - self.requests = [bad_400_request, mock_request] - - def request(*args, **kwargs): - next_request = self.requests.pop(0) - return next_request(*args, **kwargs) - - @mock.patch.object(requests, "request", request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - - test_get_call() - self.assertEqual([], self.requests) - - def test_post(self): - cl = get_authed_client() - - @mock.patch.object(requests, "request", mock_request) - def test_post_call(): - cl.post("/hi", body=[1, 2, 3]) - headers = { - "X-Auth-Token": "token", - "X-Auth-Project-Id": "project_id", - "Content-Type": "application/json", - 'Accept': 'application/json', - "User-Agent": cl.USER_AGENT - } - mock_request.assert_called_with( - "POST", - "http://example.com/hi", - headers=headers, - data='[1, 2, 3]', - **self.TEST_REQUEST_BASE) - - test_post_call() - - def test_auth_failure(self): - cl = get_client() - - # response must not have x-server-management-url header - @mock.patch.object(requests, "request", mock_request_empty) - def test_auth_call(): - self.assertRaises(exceptions.AuthorizationFailure, - cl.authenticate) - - test_auth_call() - - def test_auth_not_implemented(self): - cl = get_client() - - # response must not have x-server-management-url header - # {'hi': 'there'} is neither V2 or V3 - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - self.assertRaises(NotImplementedError, cl.authenticate) - - test_auth_call() diff --git a/awx/lib/site-packages/cinderclient/tests/test_service_catalog.py b/awx/lib/site-packages/cinderclient/tests/test_service_catalog.py deleted file mode 100644 index 214b9e7f79..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/test_service_catalog.py +++ /dev/null @@ -1,275 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from cinderclient import exceptions -from cinderclient import service_catalog -from cinderclient.tests import utils - - -# Taken directly from keystone/content/common/samples/auth.json -# Do not edit this structure. Instead, grab the latest from there. - -SERVICE_CATALOG = { - "access": { - "token": { - "id": "ab48a9efdfedb23ty3494", - "expires": "2010-11-01T03:32:15-05:00", - "tenant": { - "id": "345", - "name": "My Project" - } - }, - "user": { - "id": "123", - "name": "jqsmith", - "roles": [ - { - "id": "234", - "name": "compute:admin", - }, - { - "id": "235", - "name": "object-store:admin", - "tenantId": "1", - } - ], - "roles_links": [], - }, - "serviceCatalog": [ - { - "name": "Cloud Servers", - "type": "compute", - "endpoints": [ - { - "tenantId": "1", - "publicURL": "https://compute1.host/v1/1234", - "internalURL": "https://compute1.host/v1/1234", - "region": "North", - "versionId": "1.0", - "versionInfo": "https://compute1.host/v1/", - "versionList": "https://compute1.host/" - }, - { - "tenantId": "2", - "publicURL": "https://compute1.host/v1/3456", - "internalURL": "https://compute1.host/v1/3456", - "region": "North", - "versionId": "1.1", - "versionInfo": "https://compute1.host/v1/", - "versionList": "https://compute1.host/" - }, - ], - "endpoints_links": [], - }, - { - "name": "Cinder Volume Service", - "type": "volume", - "endpoints": [ - { - "tenantId": "1", - "publicURL": "https://volume1.host/v1/1234", - "internalURL": "https://volume1.host/v1/1234", - "region": "South", - "versionId": "1.0", - "versionInfo": "uri", - "versionList": "uri" - }, - { - "tenantId": "2", - "publicURL": "https://volume1.host/v1/3456", - "internalURL": "https://volume1.host/v1/3456", - "region": "South", - "versionId": "1.1", - "versionInfo": "https://volume1.host/v1/", - "versionList": "https://volume1.host/" - }, - ], - "endpoints_links": [ - { - "rel": "next", - "href": "https://identity1.host/v2.0/endpoints" - }, - ], - }, - { - "name": "Cinder Volume Service V2", - "type": "volumev2", - "endpoints": [ - { - "tenantId": "1", - "publicURL": "https://volume1.host/v2/1234", - "internalURL": "https://volume1.host/v2/1234", - "region": "South", - "versionId": "2.0", - "versionInfo": "uri", - "versionList": "uri" - }, - { - "tenantId": "2", - "publicURL": "https://volume1.host/v2/3456", - "internalURL": "https://volume1.host/v2/3456", - "region": "South", - "versionId": "1.1", - "versionInfo": "https://volume1.host/v2/", - "versionList": "https://volume1.host/" - }, - ], - "endpoints_links": [ - { - "rel": "next", - "href": "https://identity1.host/v2.0/endpoints" - }, - ], - }, - ], - "serviceCatalog_links": [ - { - "rel": "next", - "href": "https://identity.host/v2.0/endpoints?session=2hfh8Ar", - }, - ], - }, -} - -SERVICE_COMPATIBILITY_CATALOG = { - "access": { - "token": { - "id": "ab48a9efdfedb23ty3494", - "expires": "2010-11-01T03:32:15-05:00", - "tenant": { - "id": "345", - "name": "My Project" - } - }, - "user": { - "id": "123", - "name": "jqsmith", - "roles": [ - { - "id": "234", - "name": "compute:admin", - }, - { - "id": "235", - "name": "object-store:admin", - "tenantId": "1", - } - ], - "roles_links": [], - }, - "serviceCatalog": [ - { - "name": "Cloud Servers", - "type": "compute", - "endpoints": [ - { - "tenantId": "1", - "publicURL": "https://compute1.host/v1/1234", - "internalURL": "https://compute1.host/v1/1234", - "region": "North", - "versionId": "1.0", - "versionInfo": "https://compute1.host/v1/", - "versionList": "https://compute1.host/" - }, - { - "tenantId": "2", - "publicURL": "https://compute1.host/v1/3456", - "internalURL": "https://compute1.host/v1/3456", - "region": "North", - "versionId": "1.1", - "versionInfo": "https://compute1.host/v1/", - "versionList": "https://compute1.host/" - }, - ], - "endpoints_links": [], - }, - { - "name": "Cinder Volume Service V2", - "type": "volume", - "endpoints": [ - { - "tenantId": "1", - "publicURL": "https://volume1.host/v2/1234", - "internalURL": "https://volume1.host/v2/1234", - "region": "South", - "versionId": "2.0", - "versionInfo": "uri", - "versionList": "uri" - }, - { - "tenantId": "2", - "publicURL": "https://volume1.host/v2/3456", - "internalURL": "https://volume1.host/v2/3456", - "region": "South", - "versionId": "1.1", - "versionInfo": "https://volume1.host/v2/", - "versionList": "https://volume1.host/" - }, - ], - "endpoints_links": [ - { - "rel": "next", - "href": "https://identity1.host/v2.0/endpoints" - }, - ], - }, - ], - "serviceCatalog_links": [ - { - "rel": "next", - "href": "https://identity.host/v2.0/endpoints?session=2hfh8Ar", - }, - ], - }, -} - - -class ServiceCatalogTest(utils.TestCase): - def test_building_a_service_catalog(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - service_type='compute') - self.assertEqual("https://compute1.host/v1/1234", - sc.url_for('tenantId', '1', service_type='compute')) - self.assertEqual("https://compute1.host/v1/3456", - sc.url_for('tenantId', '2', service_type='compute')) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - "region", "South", service_type='compute') - - def test_alternate_service_type(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - service_type='volume') - self.assertEqual("https://volume1.host/v1/1234", - sc.url_for('tenantId', '1', service_type='volume')) - self.assertEqual("https://volume1.host/v1/3456", - sc.url_for('tenantId', '2', service_type='volume')) - - self.assertEqual("https://volume1.host/v2/3456", - sc.url_for('tenantId', '2', service_type='volumev2')) - self.assertEqual("https://volume1.host/v2/3456", - sc.url_for('tenantId', '2', service_type='volumev2')) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - "region", "North", service_type='volume') - - def test_compatibility_service_type(self): - sc = service_catalog.ServiceCatalog(SERVICE_COMPATIBILITY_CATALOG) - - self.assertEqual("https://volume1.host/v2/1234", - sc.url_for('tenantId', '1', service_type='volume')) - self.assertEqual("https://volume1.host/v2/3456", - sc.url_for('tenantId', '2', service_type='volume')) diff --git a/awx/lib/site-packages/cinderclient/tests/test_shell.py b/awx/lib/site-packages/cinderclient/tests/test_shell.py deleted file mode 100644 index 27e4f69e64..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/test_shell.py +++ /dev/null @@ -1,154 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import re -import sys - -import fixtures -import requests_mock -from six import moves -from testtools import matchers - -from cinderclient import exceptions -from cinderclient import shell -from cinderclient.tests import utils -from cinderclient.tests.fixture_data import keystone_client -from keystoneclient.exceptions import DiscoveryFailure - - -class ShellTest(utils.TestCase): - - FAKE_ENV = { - 'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': 'http://no.where', - } - - # Patch os.environ to avoid required auth info. - def setUp(self): - super(ShellTest, self).setUp() - for var in self.FAKE_ENV: - self.useFixture(fixtures.EnvironmentVariable(var, - self.FAKE_ENV[var])) - - def shell(self, argstr): - orig = sys.stdout - try: - sys.stdout = moves.StringIO() - _shell = shell.OpenStackCinderShell() - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(0, exc_value.code) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - - return out - - def test_help_unknown_command(self): - self.assertRaises(exceptions.CommandError, self.shell, 'help foofoo') - - def test_help(self): - required = [ - '.*?^usage: ', - '.*?(?m)^\s+create\s+Creates a volume.', - '.*?(?m)^Run "cinder help SUBCOMMAND" for help on a subcommand.', - ] - help_text = self.shell('help') - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_help_on_subcommand(self): - required = [ - '.*?^usage: cinder list', - '.*?(?m)^Lists all volumes.', - ] - help_text = self.shell('help list') - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def register_keystone_auth_fixture(self, mocker, url): - mocker.register_uri('GET', url, - text=keystone_client.keystone_request_callback) - - @requests_mock.Mocker() - def test_version_discovery(self, mocker): - _shell = shell.OpenStackCinderShell() - - os_auth_url = "https://WrongDiscoveryResponse.discovery.com:35357/v2.0" - self.register_keystone_auth_fixture(mocker, os_auth_url) - self.assertRaises(DiscoveryFailure, _shell._discover_auth_versions, - None, auth_url=os_auth_url) - - os_auth_url = "https://DiscoveryNotSupported.discovery.com:35357/v2.0" - self.register_keystone_auth_fixture(mocker, os_auth_url) - v2_url, v3_url = _shell._discover_auth_versions( - None, auth_url=os_auth_url) - self.assertEqual(v2_url, os_auth_url, "Expected v2 url") - self.assertEqual(v3_url, None, "Expected no v3 url") - - os_auth_url = "https://DiscoveryNotSupported.discovery.com:35357/v3.0" - self.register_keystone_auth_fixture(mocker, os_auth_url) - v2_url, v3_url = _shell._discover_auth_versions( - None, auth_url=os_auth_url) - self.assertEqual(v3_url, os_auth_url, "Expected v3 url") - self.assertEqual(v2_url, None, "Expected no v2 url") - - -class CinderClientArgumentParserTest(utils.TestCase): - - def test_ambiguity_solved_for_one_visible_argument(self): - parser = shell.CinderClientArgumentParser(add_help=False) - parser.add_argument('--test-parameter', - dest='visible_param', - action='store_true') - parser.add_argument('--test_parameter', - dest='hidden_param', - action='store_true', - help=argparse.SUPPRESS) - - opts = parser.parse_args(['--test']) - - # visible argument must be set - self.assertTrue(opts.visible_param) - self.assertFalse(opts.hidden_param) - - def test_raise_ambiguity_error_two_visible_argument(self): - parser = shell.CinderClientArgumentParser(add_help=False) - parser.add_argument('--test-parameter', - dest="visible_param1", - action='store_true') - parser.add_argument('--test_parameter', - dest="visible_param2", - action='store_true') - - self.assertRaises(SystemExit, parser.parse_args, ['--test']) - - def test_raise_ambiguity_error_two_hidden_argument(self): - parser = shell.CinderClientArgumentParser(add_help=False) - parser.add_argument('--test-parameter', - dest="hidden_param1", - action='store_true', - help=argparse.SUPPRESS) - parser.add_argument('--test_parameter', - dest="hidden_param2", - action='store_true', - help=argparse.SUPPRESS) - - self.assertRaises(SystemExit, parser.parse_args, ['--test']) diff --git a/awx/lib/site-packages/cinderclient/tests/test_utils.py b/awx/lib/site-packages/cinderclient/tests/test_utils.py deleted file mode 100644 index a62af2f7c9..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/test_utils.py +++ /dev/null @@ -1,140 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import collections -import sys - -from six import moves - -from cinderclient import exceptions -from cinderclient import utils -from cinderclient import base -from cinderclient.tests import utils as test_utils - -UUID = '8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0' - - -class FakeResource(object): - - def __init__(self, _id, properties): - self.id = _id - try: - self.name = properties['name'] - except KeyError: - pass - try: - self.display_name = properties['display_name'] - except KeyError: - pass - - -class FakeManager(base.ManagerWithFind): - - resource_class = FakeResource - - resources = [ - FakeResource('1234', {'name': 'entity_one'}), - FakeResource(UUID, {'name': 'entity_two'}), - FakeResource('4242', {'display_name': 'entity_three'}), - FakeResource('5678', {'name': '9876'}) - ] - - def get(self, resource_id): - for resource in self.resources: - if resource.id == str(resource_id): - return resource - raise exceptions.NotFound(resource_id) - - def list(self, search_opts): - return self.resources - - -class FindResourceTestCase(test_utils.TestCase): - - def setUp(self): - super(FindResourceTestCase, self).setUp() - self.manager = FakeManager(None) - - def test_find_none(self): - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - 'asdf') - - def test_find_by_integer_id(self): - output = utils.find_resource(self.manager, 1234) - self.assertEqual(self.manager.get('1234'), output) - - def test_find_by_str_id(self): - output = utils.find_resource(self.manager, '1234') - self.assertEqual(self.manager.get('1234'), output) - - def test_find_by_uuid(self): - output = utils.find_resource(self.manager, UUID) - self.assertEqual(self.manager.get(UUID), output) - - def test_find_by_str_name(self): - output = utils.find_resource(self.manager, 'entity_one') - self.assertEqual(self.manager.get('1234'), output) - - def test_find_by_str_displayname(self): - output = utils.find_resource(self.manager, 'entity_three') - self.assertEqual(self.manager.get('4242'), output) - - -class CaptureStdout(object): - """Context manager for capturing stdout from statments in its's block.""" - def __enter__(self): - self.real_stdout = sys.stdout - self.stringio = moves.StringIO() - sys.stdout = self.stringio - return self - - def __exit__(self, *args): - sys.stdout = self.real_stdout - self.stringio.seek(0) - self.read = self.stringio.read - - -class PrintListTestCase(test_utils.TestCase): - - def test_print_list_with_list(self): - Row = collections.namedtuple('Row', ['a', 'b']) - to_print = [Row(a=1, b=2), Row(a=3, b=4)] - with CaptureStdout() as cso: - utils.print_list(to_print, ['a', 'b']) - self.assertEqual("""\ -+---+---+ -| a | b | -+---+---+ -| 1 | 2 | -| 3 | 4 | -+---+---+ -""", cso.read()) - - def test_print_list_with_generator(self): - Row = collections.namedtuple('Row', ['a', 'b']) - - def gen_rows(): - for row in [Row(a=1, b=2), Row(a=3, b=4)]: - yield row - with CaptureStdout() as cso: - utils.print_list(gen_rows(), ['a', 'b']) - self.assertEqual("""\ -+---+---+ -| a | b | -+---+---+ -| 1 | 2 | -| 3 | 4 | -+---+---+ -""", cso.read()) diff --git a/awx/lib/site-packages/cinderclient/tests/utils.py b/awx/lib/site-packages/cinderclient/tests/utils.py deleted file mode 100644 index 25e7ee0d15..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/utils.py +++ /dev/null @@ -1,99 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import os - -import fixtures -import requests -from requests_mock.contrib import fixture as requests_mock_fixture -import six -import testtools - - -class TestCase(testtools.TestCase): - TEST_REQUEST_BASE = { - 'verify': True, - } - - def setUp(self): - super(TestCase, self).setUp() - if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or - os.environ.get('OS_STDOUT_CAPTURE') == '1'): - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or - os.environ.get('OS_STDERR_CAPTURE') == '1'): - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - - -class FixturedTestCase(TestCase): - - client_fixture_class = None - data_fixture_class = None - - def setUp(self): - super(FixturedTestCase, self).setUp() - - self.requests = self.useFixture(requests_mock_fixture.Fixture()) - self.data_fixture = None - self.client_fixture = None - self.cs = None - - if self.client_fixture_class: - fix = self.client_fixture_class(self.requests) - self.client_fixture = self.useFixture(fix) - self.cs = self.client_fixture.new_client() - - if self.data_fixture_class: - fix = self.data_fixture_class(self.requests) - self.data_fixture = self.useFixture(fix) - - def assert_called(self, method, path, body=None): - self.assertEqual(self.requests.last_request.method, method) - self.assertEqual(self.requests.last_request.path_url, path) - - if body: - req_data = self.requests.last_request.body - if isinstance(req_data, six.binary_type): - req_data = req_data.decode('utf-8') - if not isinstance(body, six.string_types): - # json load if the input body to match against is not a string - req_data = json.loads(req_data) - self.assertEqual(req_data, body) - - -class TestResponse(requests.Response): - """Class used to wrap requests.Response and provide some - convenience to initialize with a dict. - """ - - def __init__(self, data): - self._text = None - super(TestResponse, self) - if isinstance(data, dict): - self.status_code = data.get('status_code', None) - self.headers = data.get('headers', None) - self.reason = data.get('reason', '') - # Fake the text attribute to streamline Response creation - self._text = data.get('text', None) - else: - self.status_code = data - - def __eq__(self, other): - return self.__dict__ == other.__dict__ - - @property - def text(self): - return self._text diff --git a/awx/lib/site-packages/cinderclient/tests/v1/__init__.py b/awx/lib/site-packages/cinderclient/tests/v1/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/tests/v1/contrib/__init__.py b/awx/lib/site-packages/cinderclient/tests/v1/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/tests/v1/contrib/test_list_extensions.py b/awx/lib/site-packages/cinderclient/tests/v1/contrib/test_list_extensions.py deleted file mode 100644 index 96f5e35ffc..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/contrib/test_list_extensions.py +++ /dev/null @@ -1,34 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from cinderclient import extension -from cinderclient.v1.contrib import list_extensions - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -extensions = [ - extension.Extension(list_extensions.__name__.split(".")[-1], - list_extensions), -] -cs = fakes.FakeClient(extensions=extensions) - - -class ListExtensionsTests(utils.TestCase): - def test_list_extensions(self): - all_exts = cs.list_extensions.show_all() - cs.assert_called('GET', '/extensions') - self.assertTrue(len(all_exts) > 0) - for r in all_exts: - self.assertTrue(len(r.summary) > 0) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/fakes.py b/awx/lib/site-packages/cinderclient/tests/v1/fakes.py deleted file mode 100644 index f191b4a620..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/fakes.py +++ /dev/null @@ -1,795 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright (c) 2011 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from datetime import datetime - -try: - import urlparse -except ImportError: - import urllib.parse as urlparse - -from cinderclient import client as base_client -from cinderclient.tests import fakes -import cinderclient.tests.utils as utils -from cinderclient.v1 import client - - -def _stub_volume(**kwargs): - volume = { - 'id': '1234', - 'display_name': None, - 'display_description': None, - "attachments": [], - "bootable": "false", - "availability_zone": "cinder", - "created_at": "2012-08-27T00:00:00.000000", - "id": '00000000-0000-0000-0000-000000000000', - "metadata": {}, - "size": 1, - "snapshot_id": None, - "status": "available", - "volume_type": "None", - } - volume.update(kwargs) - return volume - - -def _stub_snapshot(**kwargs): - snapshot = { - "created_at": "2012-08-28T16:30:31.000000", - "display_description": None, - "display_name": None, - "id": '11111111-1111-1111-1111-111111111111', - "size": 1, - "status": "available", - "volume_id": '00000000-0000-0000-0000-000000000000', - } - snapshot.update(kwargs) - return snapshot - - -def _self_href(base_uri, tenant_id, backup_id): - return '%s/v1/%s/backups/%s' % (base_uri, tenant_id, backup_id) - - -def _bookmark_href(base_uri, tenant_id, backup_id): - return '%s/%s/backups/%s' % (base_uri, tenant_id, backup_id) - - -def _stub_backup_full(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'backup', - 'description': 'nightly backup', - 'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b', - 'container': 'volumebackups', - 'object_count': 220, - 'size': 10, - 'availability_zone': 'az1', - 'created_at': '2013-04-12T08:16:37.000000', - 'status': 'available', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_backup(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'backup', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_restore(): - return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'} - - -def _stub_qos_full(id, base_uri, tenant_id, name=None, specs=None): - if not name: - name = 'fake-name' - if not specs: - specs = {} - - return { - 'qos_specs': { - 'id': id, - 'name': name, - 'consumer': 'back-end', - 'specs': specs, - }, - 'links': { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - } - - -def _stub_qos_associates(id, name): - return { - 'assoications_type': 'volume_type', - 'name': name, - 'id': id, - } - - -def _stub_transfer_full(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'transfer', - 'volume_id': '8c05f861-6052-4df6-b3e0-0aebfbe686cc', - 'created_at': '2013-04-12T08:16:37.000000', - 'auth_key': '123456', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_transfer(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'transfer', - 'volume_id': '8c05f861-6052-4df6-b3e0-0aebfbe686cc', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_extend(id, new_size): - return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'} - - -class FakeClient(fakes.FakeClient, client.Client): - - def __init__(self, *args, **kwargs): - client.Client.__init__(self, 'username', 'password', - 'project_id', 'auth_url', - extensions=kwargs.get('extensions')) - self.client = FakeHTTPClient(**kwargs) - - def get_volume_api_version_from_endpoint(self): - return self.client.get_volume_api_version_from_endpoint() - - -class FakeHTTPClient(base_client.HTTPClient): - - def __init__(self, **kwargs): - self.username = 'username' - self.password = 'password' - self.auth_url = 'auth_url' - self.callstack = [] - self.management_url = 'http://10.0.2.15:8776/v1/fake' - - def _cs_request(self, url, method, **kwargs): - # Check that certain things are called correctly - if method in ['GET', 'DELETE']: - assert 'body' not in kwargs - elif method == 'PUT': - assert 'body' in kwargs - - # Call the method - args = urlparse.parse_qsl(urlparse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - # Note the call - self.callstack.append((method, url, kwargs.get('body', None))) - status, headers, body = getattr(self, callback)(**kwargs) - r = utils.TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) - return r, body - - if hasattr(status, 'items'): - return utils.TestResponse(status), body - else: - return utils.TestResponse({"status": status}), body - - def get_volume_api_version_from_endpoint(self): - magic_tuple = urlparse.urlsplit(self.management_url) - scheme, netloc, path, query, frag = magic_tuple - return path.lstrip('/').split('/')[0][1:] - - # - # Snapshots - # - - def get_snapshots_detail(self, **kw): - return (200, {}, {'snapshots': [ - _stub_snapshot(), - ]}) - - def get_snapshots_1234(self, **kw): - return (200, {}, {'snapshot': _stub_snapshot(id='1234')}) - - def get_snapshots_5678(self, **kw): - return (200, {}, {'snapshot': _stub_snapshot(id='5678')}) - - def put_snapshots_1234(self, **kw): - snapshot = _stub_snapshot(id='1234') - snapshot.update(kw['body']['snapshot']) - return (200, {}, {'snapshot': snapshot}) - - def post_snapshots_1234_action(self, body, **kw): - _body = None - resp = 202 - assert len(list(body)) == 1 - action = list(body)[0] - if action == 'os-reset_status': - assert 'status' in body['os-reset_status'] - elif action == 'os-update_snapshot_status': - assert 'status' in body['os-update_snapshot_status'] - else: - raise AssertionError("Unexpected action: %s" % action) - return (resp, {}, _body) - - def post_snapshots_5678_action(self, body, **kw): - return self.post_snapshots_1234_action(body, **kw) - - def delete_snapshots_1234(self, **kw): - return (202, {}, {}) - - def delete_snapshots_5678(self, **kw): - return (202, {}, {}) - - # - # Volumes - # - - def put_volumes_1234(self, **kw): - volume = _stub_volume(id='1234') - volume.update(kw['body']['volume']) - return (200, {}, {'volume': volume}) - - def get_volumes(self, **kw): - return (200, {}, {"volumes": [ - {'id': 1234, 'name': 'sample-volume'}, - {'id': 5678, 'name': 'sample-volume2'} - ]}) - - # TODO(jdg): This will need to change - # at the very least it's not complete - def get_volumes_detail(self, **kw): - return (200, {}, {"volumes": [ - {'id': kw.get('id', 1234), - 'name': 'sample-volume', - 'attachments': [{'server_id': 1234}]}, - ]}) - - def get_volumes_1234(self, **kw): - r = {'volume': self.get_volumes_detail(id=1234)[2]['volumes'][0]} - return (200, {}, r) - - def get_volumes_5678(self, **kw): - r = {'volume': self.get_volumes_detail(id=5678)[2]['volumes'][0]} - return (200, {}, r) - - def get_volumes_1234_encryption(self, **kw): - r = {'encryption_key_id': 'id'} - return (200, {}, r) - - def post_volumes_1234_action(self, body, **kw): - _body = None - resp = 202 - assert len(list(body)) == 1 - action = list(body)[0] - if action == 'os-attach': - assert sorted(list(body[action])) == ['instance_uuid', - 'mode', - 'mountpoint'] - elif action == 'os-detach': - assert body[action] is None - elif action == 'os-reserve': - assert body[action] is None - elif action == 'os-unreserve': - assert body[action] is None - elif action == 'os-initialize_connection': - assert list(body[action]) == ['connector'] - return (202, {}, {'connection_info': 'foos'}) - elif action == 'os-terminate_connection': - assert list(body[action]) == ['connector'] - elif action == 'os-begin_detaching': - assert body[action] is None - elif action == 'os-roll_detaching': - assert body[action] is None - elif action == 'os-reset_status': - assert 'status' in body[action] - elif action == 'os-extend': - assert list(body[action]) == ['new_size'] - elif action == 'os-migrate_volume': - assert 'host' in body[action] - assert 'force_host_copy' in body[action] - elif action == 'os-update_readonly_flag': - assert list(body[action]) == ['readonly'] - elif action == 'os-set_bootable': - assert list(body[action]) == ['bootable'] - else: - raise AssertionError("Unexpected action: %s" % action) - return (resp, {}, _body) - - def post_volumes_5678_action(self, body, **kw): - return self.post_volumes_1234_action(body, **kw) - - def post_volumes(self, **kw): - return (202, {}, {'volume': {}}) - - def delete_volumes_1234(self, **kw): - return (202, {}, None) - - def delete_volumes_5678(self, **kw): - return (202, {}, None) - - # - # Quotas - # - - def get_os_quota_sets_test(self, **kw): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'volumes': 1, - 'snapshots': 1, - 'gigabytes': 1}}) - - def get_os_quota_sets_test_defaults(self): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'volumes': 1, - 'snapshots': 1, - 'gigabytes': 1}}) - - def put_os_quota_sets_test(self, body, **kw): - assert list(body) == ['quota_set'] - fakes.assert_has_keys(body['quota_set'], - required=['tenant_id']) - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'volumes': 2, - 'snapshots': 2, - 'gigabytes': 1}}) - - def delete_os_quota_sets_1234(self, **kw): - return (200, {}, {}) - - def delete_os_quota_sets_test(self, **kw): - return (200, {}, {}) - - # - # Quota Classes - # - - def get_os_quota_class_sets_test(self, **kw): - return (200, {}, {'quota_class_set': { - 'class_name': 'test', - 'metadata_items': [], - 'volumes': 1, - 'snapshots': 1, - 'gigabytes': 1}}) - - def put_os_quota_class_sets_test(self, body, **kw): - assert list(body) == ['quota_class_set'] - fakes.assert_has_keys(body['quota_class_set'], - required=['class_name']) - return (200, {}, {'quota_class_set': { - 'class_name': 'test', - 'metadata_items': [], - 'volumes': 2, - 'snapshots': 2, - 'gigabytes': 1}}) - - # - # VolumeTypes - # - def get_types(self, **kw): - return (200, {}, { - 'volume_types': [{'id': 1, - 'name': 'test-type-1', - 'extra_specs': {}}, - {'id': 2, - 'name': 'test-type-2', - 'extra_specs': {}}]}) - - def get_types_1(self, **kw): - return (200, {}, {'volume_type': {'id': 1, - 'name': 'test-type-1', - 'extra_specs': {}}}) - - def get_types_2(self, **kw): - return (200, {}, {'volume_type': {'id': 2, - 'name': 'test-type-2', - 'extra_specs': {}}}) - - def post_types(self, body, **kw): - return (202, {}, {'volume_type': {'id': 3, - 'name': 'test-type-3', - 'extra_specs': {}}}) - - def post_types_1_extra_specs(self, body, **kw): - assert list(body) == ['extra_specs'] - return (200, {}, {'extra_specs': {'k': 'v'}}) - - def delete_types_1_extra_specs_k(self, **kw): - return(204, {}, None) - - def delete_types_1(self, **kw): - return (202, {}, None) - - # - # VolumeEncryptionTypes - # - def get_types_1_encryption(self, **kw): - return (200, {}, {'id': 1, 'volume_type_id': 1, 'provider': 'test', - 'cipher': 'test', 'key_size': 1, - 'control_location': 'front-end'}) - - def get_types_2_encryption(self, **kw): - return (200, {}, {}) - - def post_types_2_encryption(self, body, **kw): - return (200, {}, {'encryption': body}) - - def put_types_1_encryption_1(self, body, **kw): - return (200, {}, {}) - - def delete_types_1_encryption_provider(self, **kw): - return (202, {}, None) - - # - # Set/Unset metadata - # - def delete_volumes_1234_metadata_test_key(self, **kw): - return (204, {}, None) - - def delete_volumes_1234_metadata_key1(self, **kw): - return (204, {}, None) - - def delete_volumes_1234_metadata_key2(self, **kw): - return (204, {}, None) - - def post_volumes_1234_metadata(self, **kw): - return (204, {}, {'metadata': {'test_key': 'test_value'}}) - - # - # List all extensions - # - def get_extensions(self, **kw): - exts = [ - { - "alias": "FAKE-1", - "description": "Fake extension number 1", - "links": [], - "name": "Fake1", - "namespace": ("http://docs.openstack.org/" - "/ext/fake1/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" - }, - { - "alias": "FAKE-2", - "description": "Fake extension number 2", - "links": [], - "name": "Fake2", - "namespace": ("http://docs.openstack.org/" - "/ext/fake1/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" - }, - ] - return (200, {}, {"extensions": exts, }) - - # - # VolumeBackups - # - - def get_backups_76a17945_3c6f_435c_975b_b5685db10b62(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' - return (200, {}, - {'backup': _stub_backup_full(backup1, base_uri, tenant_id)}) - - def get_backups_detail(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' - backup2 = 'd09534c6-08b8-4441-9e87-8976f3a8f699' - return (200, {}, - {'backups': [ - _stub_backup_full(backup1, base_uri, tenant_id), - _stub_backup_full(backup2, base_uri, tenant_id)]}) - - def delete_backups_76a17945_3c6f_435c_975b_b5685db10b62(self, **kw): - return (202, {}, None) - - def post_backups(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' - return (202, {}, - {'backup': _stub_backup(backup1, base_uri, tenant_id)}) - - def post_backups_76a17945_3c6f_435c_975b_b5685db10b62_restore(self, **kw): - return (200, {}, - {'restore': _stub_restore()}) - - def post_backups_1234_restore(self, **kw): - return (200, {}, - {'restore': _stub_restore()}) - - # - # QoSSpecs - # - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - return (200, {}, - _stub_qos_full(qos_id1, base_uri, tenant_id)) - - def get_qos_specs(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - qos_id2 = '0FD8DD14-A396-4E55-9573-1FE59042E95B' - return (200, {}, - {'qos_specs': [ - _stub_qos_full(qos_id1, base_uri, tenant_id, 'name-1'), - _stub_qos_full(qos_id2, base_uri, tenant_id)]}) - - def post_qos_specs(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - qos_name = 'qos-name' - return (202, {}, - _stub_qos_full(qos_id, base_uri, tenant_id, qos_name)) - - def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw): - return (202, {}, None) - - def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_delete_keys( - self, **kw): - return (202, {}, None) - - def delete_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw): - return (202, {}, None) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associations( - self, **kw): - type_id1 = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF' - type_id2 = '4230B13A-AB37-4E84-B777-EFBA6FCEE4FF' - type_name1 = 'type1' - type_name2 = 'type2' - return (202, {}, - {'qos_associations': [ - _stub_qos_associates(type_id1, type_name1), - _stub_qos_associates(type_id2, type_name2)]}) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associate( - self, **kw): - return (202, {}, None) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate( - self, **kw): - return (202, {}, None) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate_all( - self, **kw): - return (202, {}, None) - - # - # VolumeTransfers - # - - def get_os_volume_transfer_5678(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - return (200, {}, - {'transfer': - _stub_transfer_full(transfer1, base_uri, tenant_id)}) - - def get_os_volume_transfer_detail(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - transfer2 = 'f625ec3e-13dd-4498-a22a-50afd534cc41' - return (200, {}, - {'transfers': [ - _stub_transfer_full(transfer1, base_uri, tenant_id), - _stub_transfer_full(transfer2, base_uri, tenant_id)]}) - - def delete_os_volume_transfer_5678(self, **kw): - return (202, {}, None) - - def post_os_volume_transfer(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - return (202, {}, - {'transfer': _stub_transfer(transfer1, base_uri, tenant_id)}) - - def post_os_volume_transfer_5678_accept(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - return (200, {}, - {'transfer': _stub_transfer(transfer1, base_uri, tenant_id)}) - - # - # Services - # - def get_os_services(self, **kw): - host = kw.get('host', None) - binary = kw.get('binary', None) - services = [ - { - 'binary': 'cinder-volume', - 'host': 'host1', - 'zone': 'cinder', - 'status': 'enabled', - 'state': 'up', - 'updated_at': datetime(2012, 10, 29, 13, 42, 2) - }, - { - 'binary': 'cinder-volume', - 'host': 'host2', - 'zone': 'cinder', - 'status': 'disabled', - 'state': 'down', - 'updated_at': datetime(2012, 9, 18, 8, 3, 38) - }, - { - 'binary': 'cinder-scheduler', - 'host': 'host2', - 'zone': 'cinder', - 'status': 'disabled', - 'state': 'down', - 'updated_at': datetime(2012, 9, 18, 8, 3, 38) - }, - ] - if host: - services = filter(lambda i: i['host'] == host, services) - if binary: - services = filter(lambda i: i['binary'] == binary, services) - return (200, {}, {'services': services}) - - def put_os_services_enable(self, body, **kw): - return (200, {}, {'host': body['host'], 'binary': body['binary'], - 'status': 'enabled'}) - - def put_os_services_disable(self, body, **kw): - return (200, {}, {'host': body['host'], 'binary': body['binary'], - 'status': 'disabled'}) - - def put_os_services_disable_log_reason(self, body, **kw): - return (200, {}, {'host': body['host'], 'binary': body['binary'], - 'status': 'disabled', - 'disabled_reason': body['disabled_reason']}) - - def get_os_availability_zone(self, **kw): - return (200, {}, { - "availabilityZoneInfo": [ - { - "zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": None, - }, - { - "zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None, - }, - ] - }) - - def get_os_availability_zone_detail(self, **kw): - return (200, {}, { - "availabilityZoneInfo": [ - { - "zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "cinder-volume": { - "active": True, - "available": True, - "updated_at": - datetime(2012, 12, 26, 14, 45, 25, 0) - } - } - } - }, - { - "zoneName": "internal", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "cinder-sched": { - "active": True, - "available": True, - "updated_at": - datetime(2012, 12, 26, 14, 45, 24, 0) - } - } - } - }, - { - "zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None, - }, - ] - }) - - def post_snapshots_1234_metadata(self, **kw): - return (200, {}, {"metadata": {"key1": "val1", "key2": "val2"}}) - - def delete_snapshots_1234_metadata_key1(self, **kw): - return (200, {}, None) - - def delete_snapshots_1234_metadata_key2(self, **kw): - return (200, {}, None) - - def put_volumes_1234_metadata(self, **kw): - return (200, {}, {"metadata": {"key1": "val1", "key2": "val2"}}) - - def put_snapshots_1234_metadata(self, **kw): - return (200, {}, {"metadata": {"key1": "val1", "key2": "val2"}}) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_auth.py b/awx/lib/site-packages/cinderclient/tests/v1/test_auth.py deleted file mode 100644 index 47da0e217a..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_auth.py +++ /dev/null @@ -1,338 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import mock - -import requests - -from cinderclient.v1 import client -from cinderclient import exceptions -from cinderclient.tests import utils - - -class AuthenticateAgainstKeystoneTests(utils.TestCase): - def test_authenticate_success(self): - cs = client.Client("username", "password", "project_id", - "http://localhost:8776/v1", service_type='volume') - resp = { - "access": { - "token": { - "expires": "2014-11-01T03:32:15-05:00", - "id": "FAKE_ID", - }, - "serviceCatalog": [ - { - "type": "volume", - "endpoints": [ - { - "region": "RegionOne", - "adminURL": "http://localhost:8776/v1", - "internalURL": "http://localhost:8776/v1", - "publicURL": "http://localhost:8776/v1", - }, - ], - }, - ], - }, - } - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(public_url, cs.client.management_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(token_id, cs.client.auth_token) - - test_auth_call() - - def test_authenticate_tenant_id(self): - cs = client.Client("username", "password", - auth_url="http://localhost:8776/v1", - tenant_id='tenant_id', service_type='volume') - resp = { - "access": { - "token": { - "expires": "2014-11-01T03:32:15-05:00", - "id": "FAKE_ID", - "tenant": { - "description": None, - "enabled": True, - "id": "tenant_id", - "name": "demo" - } # tenant associated with token - }, - "serviceCatalog": [ - { - "type": "volume", - "endpoints": [ - { - "region": "RegionOne", - "adminURL": "http://localhost:8776/v1", - "internalURL": "http://localhost:8776/v1", - "publicURL": "http://localhost:8776/v1", - }, - ], - }, - ], - }, - } - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantId': cs.client.tenant_id, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(public_url, cs.client.management_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(token_id, cs.client.auth_token) - tenant_id = resp["access"]["token"]["tenant"]["id"] - self.assertEqual(tenant_id, cs.client.tenant_id) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", "project_id", - "http://localhost:8776/v1") - resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}} - auth_response = utils.TestResponse({ - "status_code": 401, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_auth_redirect(self): - cs = client.Client("username", "password", "project_id", - "http://localhost:8776/v1", service_type='volume') - dict_correct_response = { - "access": { - "token": { - "expires": "2014-11-01T03:32:15-05:00", - "id": "FAKE_ID", - }, - "serviceCatalog": [ - { - "type": "volume", - "endpoints": [ - { - "adminURL": "http://localhost:8776/v1", - "region": "RegionOne", - "internalURL": "http://localhost:8776/v1", - "publicURL": "http://localhost:8776/v1/", - }, - ], - }, - ], - }, - } - correct_response = json.dumps(dict_correct_response) - dict_responses = [ - {"headers": {'location': 'http://127.0.0.1:5001'}, - "status_code": 305, - "text": "Use proxy"}, - # Configured on admin port, cinder redirects to v2.0 port. - # When trying to connect on it, keystone auth succeed by v1.0 - # protocol (through headers) but tokens are being returned in - # body (looks like keystone bug). Leaved for compatibility. - {"headers": {}, - "status_code": 200, - "text": correct_response}, - {"headers": {}, - "status_code": 200, - "text": correct_response} - ] - - responses = [(utils.TestResponse(resp)) for resp in dict_responses] - - def side_effect(*args, **kwargs): - return responses.pop(0) - - mock_request = mock.Mock(side_effect=side_effect) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - resp = dict_correct_response - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(public_url, cs.client.management_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(token_id, cs.client.auth_token) - - test_auth_call() - - -class AuthenticationTests(utils.TestCase): - def test_authenticate_success(self): - cs = client.Client("username", "password", "project_id", "auth_url") - management_url = 'https://localhost/v1.1/443470' - auth_response = utils.TestResponse({ - 'status_code': 204, - 'headers': { - 'x-server-management-url': management_url, - 'x-auth-token': '1b751d74-de0c-46ae-84f0-915744b582d1', - }, - }) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'Accept': 'application/json', - 'X-Auth-User': 'username', - 'X-Auth-Key': 'password', - 'X-Auth-Project-Id': 'project_id', - 'User-Agent': cs.client.USER_AGENT - } - mock_request.assert_called_with( - "GET", - cs.client.auth_url, - headers=headers, - **self.TEST_REQUEST_BASE) - - self.assertEqual(auth_response.headers['x-server-management-url'], - cs.client.management_url) - self.assertEqual(auth_response.headers['x-auth-token'], - cs.client.auth_token) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", "project_id", "auth_url") - auth_response = utils.TestResponse({"status_code": 401}) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_auth_automatic(self): - cs = client.Client("username", "password", "project_id", "auth_url") - http_client = cs.client - http_client.management_url = '' - mock_request = mock.Mock(return_value=(None, None)) - - @mock.patch.object(http_client, 'request', mock_request) - @mock.patch.object(http_client, 'authenticate') - def test_auth_call(m): - http_client.get('/') - m.assert_called() - mock_request.assert_called() - - test_auth_call() - - def test_auth_manual(self): - cs = client.Client("username", "password", "project_id", "auth_url") - - @mock.patch.object(cs.client, 'authenticate') - def test_auth_call(m): - cs.authenticate() - m.assert_called() - - test_auth_call() diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_availability_zone.py b/awx/lib/site-packages/cinderclient/tests/v1/test_availability_zone.py deleted file mode 100644 index e3e7d1f01f..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_availability_zone.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2011-2013 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from cinderclient.v1 import availability_zones -from cinderclient.v1 import shell -from cinderclient.tests.fixture_data import client -from cinderclient.tests.fixture_data import availability_zones as azfixture -from cinderclient.tests import utils - - -class AvailabilityZoneTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = azfixture.Fixture - - def _assertZone(self, zone, name, status): - self.assertEqual(name, zone.zoneName) - self.assertEqual(status, zone.zoneState) - - def test_list_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=False) - self.assert_called('GET', '/os-availability-zone') - - for zone in zones: - self.assertIsInstance(zone, - availability_zones.AvailabilityZone) - - self.assertEqual(2, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('zone-2'), six.u('not available')] - - z0 = shell._treeizeAvailabilityZone(zones[0]) - z1 = shell._treeizeAvailabilityZone(zones[1]) - - self.assertEqual((1, 1), (len(z0), len(z1))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z1[0], l1[0], l1[1]) - - def test_detail_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=True) - self.assert_called('GET', '/os-availability-zone/detail') - - for zone in zones: - self.assertIsInstance(zone, - availability_zones.AvailabilityZone) - - self.assertEqual(3, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('|- fake_host-1'), six.u('')] - l2 = [six.u('| |- cinder-volume'), - six.u('enabled :-) 2012-12-26 14:45:25')] - l3 = [six.u('internal'), six.u('available')] - l4 = [six.u('|- fake_host-1'), six.u('')] - l5 = [six.u('| |- cinder-sched'), - six.u('enabled :-) 2012-12-26 14:45:24')] - l6 = [six.u('zone-2'), six.u('not available')] - - z0 = shell._treeizeAvailabilityZone(zones[0]) - z1 = shell._treeizeAvailabilityZone(zones[1]) - z2 = shell._treeizeAvailabilityZone(zones[2]) - - self.assertEqual((3, 3, 1), (len(z0), len(z1), len(z2))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z0[1], l1[0], l1[1]) - self._assertZone(z0[2], l2[0], l2[1]) - self._assertZone(z1[0], l3[0], l3[1]) - self._assertZone(z1[1], l4[0], l4[1]) - self._assertZone(z1[2], l5[0], l5[1]) - self._assertZone(z2[0], l6[0], l6[1]) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_limits.py b/awx/lib/site-packages/cinderclient/tests/v1/test_limits.py deleted file mode 100644 index cfcf78bd20..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_limits.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock - -from cinderclient.tests import utils -from cinderclient.v1 import limits - - -def _get_default_RateLimit(verb="verb1", uri="uri1", regex="regex1", - value="value1", - remain="remain1", unit="unit1", - next_available="next1"): - return limits.RateLimit(verb, uri, regex, value, remain, unit, - next_available) - - -class TestLimits(utils.TestCase): - def test_repr(self): - l = limits.Limits(None, {"foo": "bar"}) - self.assertEqual("<Limits>", repr(l)) - - def test_absolute(self): - l = limits.Limits(None, - {"absolute": {"name1": "value1", "name2": "value2"}}) - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name2", "value2") - for item in l.absolute: - self.assertIn(item, [l1, l2]) - - def test_rate(self): - l = limits.Limits(None, - { - "rate": [ - { - "uri": "uri1", - "regex": "regex1", - "limit": [ - { - "verb": "verb1", - "value": "value1", - "remaining": "remain1", - "unit": "unit1", - "next-available": "next1", - }, - ], - }, - { - "uri": "uri2", - "regex": "regex2", - "limit": [ - { - "verb": "verb2", - "value": "value2", - "remaining": "remain2", - "unit": "unit2", - "next-available": "next2", - }, - ], - }, - ], - }) - l1 = limits.RateLimit("verb1", "uri1", "regex1", "value1", "remain1", - "unit1", "next1") - l2 = limits.RateLimit("verb2", "uri2", "regex2", "value2", "remain2", - "unit2", "next2") - for item in l.rate: - self.assertIn(item, [l1, l2]) - - -class TestRateLimit(utils.TestCase): - def test_equal(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit() - self.assertEqual(l1, l2) - - def test_not_equal_verbs(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(verb="verb2") - self.assertNotEqual(l1, l2) - - def test_not_equal_uris(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(uri="uri2") - self.assertNotEqual(l1, l2) - - def test_not_equal_regexps(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(regex="regex2") - self.assertNotEqual(l1, l2) - - def test_not_equal_values(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(value="value2") - self.assertNotEqual(l1, l2) - - def test_not_equal_remains(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(remain="remain2") - self.assertNotEqual(l1, l2) - - def test_not_equal_units(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(unit="unit2") - self.assertNotEqual(l1, l2) - - def test_not_equal_next_available(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(next_available="next2") - self.assertNotEqual(l1, l2) - - def test_repr(self): - l1 = _get_default_RateLimit() - self.assertEqual("<RateLimit: method=verb1 uri=uri1>", repr(l1)) - - -class TestAbsoluteLimit(utils.TestCase): - def test_equal(self): - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name1", "value1") - self.assertEqual(l1, l2) - - def test_not_equal_values(self): - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name1", "value2") - self.assertNotEqual(l1, l2) - - def test_not_equal_names(self): - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name2", "value1") - self.assertNotEqual(l1, l2) - - def test_repr(self): - l1 = limits.AbsoluteLimit("name1", "value1") - self.assertEqual("<AbsoluteLimit: name=name1>", repr(l1)) - - -class TestLimitsManager(utils.TestCase): - def test_get(self): - api = mock.Mock() - api.client.get.return_value = ( - None, - {"limits": {"absolute": {"name1": "value1", }}, - "no-limits": {"absolute": {"name2": "value2", }}}) - l1 = limits.AbsoluteLimit("name1", "value1") - limitsManager = limits.LimitsManager(api) - - lim = limitsManager.get() - - self.assertIsInstance(lim, limits.Limits) - for l in lim.absolute: - self.assertEqual(l1, l) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_qos.py b/awx/lib/site-packages/cinderclient/tests/v1/test_qos.py deleted file mode 100644 index e127a4716f..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_qos.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2013 eBay Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class QoSSpecsTest(utils.TestCase): - - def test_create(self): - specs = dict(k1='v1', k2='v2') - cs.qos_specs.create('qos-name', specs) - cs.assert_called('POST', '/qos-specs') - - def test_get(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.get(qos_id) - cs.assert_called('GET', '/qos-specs/%s' % qos_id) - - def test_list(self): - cs.qos_specs.list() - cs.assert_called('GET', '/qos-specs') - - def test_delete(self): - cs.qos_specs.delete('1B6B6A04-A927-4AEB-810B-B7BAAD49F57C') - cs.assert_called('DELETE', - '/qos-specs/1B6B6A04-A927-4AEB-810B-B7BAAD49F57C?' - 'force=False') - - def test_set_keys(self): - body = {'qos_specs': dict(k1='v1')} - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.set_keys(qos_id, body) - cs.assert_called('PUT', '/qos-specs/%s' % qos_id) - - def test_unset_keys(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - body = {'keys': ['k1']} - cs.qos_specs.unset_keys(qos_id, body) - cs.assert_called('PUT', '/qos-specs/%s/delete_keys' % qos_id) - - def test_get_associations(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.get_associations(qos_id) - cs.assert_called('GET', '/qos-specs/%s/associations' % qos_id) - - def test_associate(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF' - cs.qos_specs.associate(qos_id, type_id) - cs.assert_called('GET', '/qos-specs/%s/associate?vol_type_id=%s' - % (qos_id, type_id)) - - def test_disassociate(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF' - cs.qos_specs.disassociate(qos_id, type_id) - cs.assert_called('GET', '/qos-specs/%s/disassociate?vol_type_id=%s' - % (qos_id, type_id)) - - def test_disassociate_all(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.disassociate_all(qos_id) - cs.assert_called('GET', '/qos-specs/%s/disassociate_all' % qos_id) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_quota_classes.py b/awx/lib/site-packages/cinderclient/tests/v1/test_quota_classes.py deleted file mode 100644 index 0cb3122b0d..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_quota_classes.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class QuotaClassSetsTest(utils.TestCase): - - def test_class_quotas_get(self): - class_name = 'test' - cs.quota_classes.get(class_name) - cs.assert_called('GET', '/os-quota-class-sets/%s' % class_name) - - def test_update_quota(self): - q = cs.quota_classes.get('test') - q.update(volumes=2, snapshots=2) - cs.assert_called('PUT', '/os-quota-class-sets/test') - - def test_refresh_quota(self): - q = cs.quota_classes.get('test') - q2 = cs.quota_classes.get('test') - self.assertEqual(q.volumes, q2.volumes) - q2.volumes = 0 - self.assertNotEqual(q.volumes, q2.volumes) - q2.get() - self.assertEqual(q.volumes, q2.volumes) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_quotas.py b/awx/lib/site-packages/cinderclient/tests/v1/test_quotas.py deleted file mode 100644 index beb5b5dcba..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_quotas.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class QuotaSetsTest(utils.TestCase): - - def test_tenant_quotas_get(self): - tenant_id = 'test' - cs.quotas.get(tenant_id) - cs.assert_called('GET', '/os-quota-sets/%s?usage=False' % tenant_id) - - def test_tenant_quotas_defaults(self): - tenant_id = 'test' - cs.quotas.defaults(tenant_id) - cs.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id) - - def test_update_quota(self): - q = cs.quotas.get('test') - q.update(volumes=2) - q.update(snapshots=2) - cs.assert_called('PUT', '/os-quota-sets/test') - - def test_refresh_quota(self): - q = cs.quotas.get('test') - q2 = cs.quotas.get('test') - self.assertEqual(q.volumes, q2.volumes) - self.assertEqual(q.snapshots, q2.snapshots) - q2.volumes = 0 - self.assertNotEqual(q.volumes, q2.volumes) - q2.snapshots = 0 - self.assertNotEqual(q.snapshots, q2.snapshots) - q2.get() - self.assertEqual(q.volumes, q2.volumes) - self.assertEqual(q.snapshots, q2.snapshots) - - def test_delete_quota(self): - tenant_id = 'test' - cs.quotas.delete(tenant_id) - cs.assert_called('DELETE', '/os-quota-sets/test') diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_services.py b/awx/lib/site-packages/cinderclient/tests/v1/test_services.py deleted file mode 100644 index 8f444cdb27..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_services.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes -from cinderclient.v1 import services - - -cs = fakes.FakeClient() - - -class ServicesTest(utils.TestCase): - - def test_list_services(self): - svs = cs.services.list() - cs.assert_called('GET', '/os-services') - self.assertEqual(3, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - - def test_list_services_with_hostname(self): - svs = cs.services.list(host='host2') - cs.assert_called('GET', '/os-services?host=host2') - self.assertEqual(2, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - [self.assertEqual('host2', s.host) for s in svs] - - def test_list_services_with_binary(self): - svs = cs.services.list(binary='cinder-volume') - cs.assert_called('GET', '/os-services?binary=cinder-volume') - self.assertEqual(2, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - [self.assertEqual('cinder-volume', s.binary) for s in svs] - - def test_list_services_with_host_binary(self): - svs = cs.services.list('host2', 'cinder-volume') - cs.assert_called('GET', '/os-services?host=host2&binary=cinder-volume') - self.assertEqual(1, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - [self.assertEqual('host2', s.host) for s in svs] - [self.assertEqual('cinder-volume', s.binary) for s in svs] - - def test_services_enable(self): - s = cs.services.enable('host1', 'cinder-volume') - values = {"host": "host1", 'binary': 'cinder-volume'} - cs.assert_called('PUT', '/os-services/enable', values) - self.assertIsInstance(s, services.Service) - self.assertEqual('enabled', s.status) - - def test_services_disable(self): - s = cs.services.disable('host1', 'cinder-volume') - values = {"host": "host1", 'binary': 'cinder-volume'} - cs.assert_called('PUT', '/os-services/disable', values) - self.assertIsInstance(s, services.Service) - self.assertEqual('disabled', s.status) - - def test_services_disable_log_reason(self): - s = cs.services.disable_log_reason( - 'host1', 'cinder-volume', 'disable bad host') - values = {"host": "host1", 'binary': 'cinder-volume', - "disabled_reason": "disable bad host"} - cs.assert_called('PUT', '/os-services/disable-log-reason', values) - self.assertIsInstance(s, services.Service) - self.assertEqual('disabled', s.status) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_shell.py b/awx/lib/site-packages/cinderclient/tests/v1/test_shell.py deleted file mode 100644 index fb4232863e..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_shell.py +++ /dev/null @@ -1,402 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright (c) 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -from requests_mock.contrib import fixture as requests_mock_fixture - -from cinderclient import client -from cinderclient import exceptions -from cinderclient import shell -from cinderclient.v1 import shell as shell_v1 -from cinderclient.tests.v1 import fakes -from cinderclient.tests import utils -from cinderclient.tests.fixture_data import keystone_client - - -class ShellTest(utils.TestCase): - - FAKE_ENV = { - 'CINDER_USERNAME': 'username', - 'CINDER_PASSWORD': 'password', - 'CINDER_PROJECT_ID': 'project_id', - 'OS_VOLUME_API_VERSION': '1', - 'CINDER_URL': keystone_client.BASE_URL, - } - - # Patch os.environ to avoid required auth info. - def setUp(self): - """Run before each test.""" - super(ShellTest, self).setUp() - for var in self.FAKE_ENV: - self.useFixture(fixtures.EnvironmentVariable(var, - self.FAKE_ENV[var])) - - self.shell = shell.OpenStackCinderShell() - - # HACK(bcwaldon): replace this when we start using stubs - self.old_get_client_class = client.get_client_class - client.get_client_class = lambda *_: fakes.FakeClient - - self.requests = self.useFixture(requests_mock_fixture.Fixture()) - self.requests.register_uri( - 'GET', keystone_client.BASE_URL, - text=keystone_client.keystone_request_callback) - - def tearDown(self): - # For some method like test_image_meta_bad_action we are - # testing a SystemExit to be thrown and object self.shell has - # no time to get instantatiated which is OK in this case, so - # we make sure the method is there before launching it. - if hasattr(self.shell, 'cs'): - self.shell.cs.clear_callstack() - - # HACK(bcwaldon): replace this when we start using stubs - client.get_client_class = self.old_get_client_class - super(ShellTest, self).tearDown() - - def run_command(self, cmd): - self.shell.main(cmd.split()) - - def assert_called(self, method, url, body=None, **kwargs): - return self.shell.cs.assert_called(method, url, body, **kwargs) - - def assert_called_anytime(self, method, url, body=None): - return self.shell.cs.assert_called_anytime(method, url, body) - - def test_extract_metadata(self): - # mimic the result of argparse's parse_args() method - class Arguments: - - def __init__(self, metadata=[]): - self.metadata = metadata - - inputs = [ - ([], {}), - (["key=value"], {"key": "value"}), - (["key"], {"key": None}), - (["k1=v1", "k2=v2"], {"k1": "v1", "k2": "v2"}), - (["k1=v1", "k2"], {"k1": "v1", "k2": None}), - (["k1", "k2=v2"], {"k1": None, "k2": "v2"}) - ] - - for input in inputs: - args = Arguments(metadata=input[0]) - self.assertEqual(input[1], shell_v1._extract_metadata(args)) - - def test_translate_volume_keys(self): - cs = fakes.FakeClient() - v = cs.volumes.list()[0] - setattr(v, 'os-vol-tenant-attr:tenant_id', 'fake_tenant') - setattr(v, '_info', {'attachments': [{'server_id': 1234}], - 'id': 1234, 'name': 'sample-volume', - 'os-vol-tenant-attr:tenant_id': 'fake_tenant'}) - shell_v1._translate_volume_keys([v]) - self.assertEqual(v.tenant_id, 'fake_tenant') - - def test_list(self): - self.run_command('list') - # NOTE(jdg): we default to detail currently - self.assert_called('GET', '/volumes/detail') - - def test_list_filter_status(self): - self.run_command('list --status=available') - self.assert_called('GET', '/volumes/detail?status=available') - - def test_list_filter_display_name(self): - self.run_command('list --display-name=1234') - self.assert_called('GET', '/volumes/detail?display_name=1234') - - def test_list_all_tenants(self): - self.run_command('list --all-tenants=1') - self.assert_called('GET', '/volumes/detail?all_tenants=1') - - def test_list_availability_zone(self): - self.run_command('availability-zone-list') - self.assert_called('GET', '/os-availability-zone') - - def test_show(self): - self.run_command('show 1234') - self.assert_called('GET', '/volumes/1234') - - def test_delete(self): - self.run_command('delete 1234') - self.assert_called('DELETE', '/volumes/1234') - - def test_delete_by_name(self): - self.run_command('delete sample-volume') - self.assert_called_anytime('GET', '/volumes/detail?all_tenants=1') - self.assert_called('DELETE', '/volumes/1234') - - def test_delete_multiple(self): - self.run_command('delete 1234 5678') - self.assert_called_anytime('DELETE', '/volumes/1234') - self.assert_called('DELETE', '/volumes/5678') - - def test_backup(self): - self.run_command('backup-create 1234') - self.assert_called('POST', '/backups') - - def test_restore(self): - self.run_command('backup-restore 1234') - self.assert_called('POST', '/backups/1234/restore') - - def test_snapshot_list_filter_volume_id(self): - self.run_command('snapshot-list --volume-id=1234') - self.assert_called('GET', '/snapshots/detail?volume_id=1234') - - def test_snapshot_list_filter_status_and_volume_id(self): - self.run_command('snapshot-list --status=available --volume-id=1234') - self.assert_called('GET', '/snapshots/detail?' - 'status=available&volume_id=1234') - - def test_rename(self): - # basic rename with positional arguments - self.run_command('rename 1234 new-name') - expected = {'volume': {'display_name': 'new-name'}} - self.assert_called('PUT', '/volumes/1234', body=expected) - # change description only - self.run_command('rename 1234 --display-description=new-description') - expected = {'volume': {'display_description': 'new-description'}} - self.assert_called('PUT', '/volumes/1234', body=expected) - # rename and change description - self.run_command('rename 1234 new-name ' - '--display-description=new-description') - expected = {'volume': { - 'display_name': 'new-name', - 'display_description': 'new-description', - }} - self.assert_called('PUT', '/volumes/1234', body=expected) - - # Call rename with no arguments - self.assertRaises(SystemExit, self.run_command, 'rename') - - def test_rename_snapshot(self): - # basic rename with positional arguments - self.run_command('snapshot-rename 1234 new-name') - expected = {'snapshot': {'display_name': 'new-name'}} - self.assert_called('PUT', '/snapshots/1234', body=expected) - # change description only - self.run_command('snapshot-rename 1234 ' - '--display-description=new-description') - expected = {'snapshot': {'display_description': 'new-description'}} - self.assert_called('PUT', '/snapshots/1234', body=expected) - # snapshot-rename and change description - self.run_command('snapshot-rename 1234 new-name ' - '--display-description=new-description') - expected = {'snapshot': { - 'display_name': 'new-name', - 'display_description': 'new-description', - }} - self.assert_called('PUT', '/snapshots/1234', body=expected) - - # Call snapshot-rename with no arguments - self.assertRaises(SystemExit, self.run_command, 'snapshot-rename') - - def test_set_metadata_set(self): - self.run_command('metadata 1234 set key1=val1 key2=val2') - self.assert_called('POST', '/volumes/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_set_metadata_delete_dict(self): - self.run_command('metadata 1234 unset key1=val1 key2=val2') - self.assert_called('DELETE', '/volumes/1234/metadata/key1') - self.assert_called('DELETE', '/volumes/1234/metadata/key2', pos=-2) - - def test_set_metadata_delete_keys(self): - self.run_command('metadata 1234 unset key1 key2') - self.assert_called('DELETE', '/volumes/1234/metadata/key1') - self.assert_called('DELETE', '/volumes/1234/metadata/key2', pos=-2) - - def test_reset_state(self): - self.run_command('reset-state 1234') - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_reset_state_with_flag(self): - self.run_command('reset-state --state error 1234') - expected = {'os-reset_status': {'status': 'error'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_reset_state_multiple(self): - self.run_command('reset-state 1234 5678 --state error') - expected = {'os-reset_status': {'status': 'error'}} - self.assert_called_anytime('POST', '/volumes/1234/action', - body=expected) - self.assert_called_anytime('POST', '/volumes/5678/action', - body=expected) - - def test_reset_state_two_with_one_nonexistent(self): - cmd = 'reset-state 1234 123456789' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called_anytime('POST', '/volumes/1234/action', - body=expected) - - def test_reset_state_one_with_one_nonexistent(self): - cmd = 'reset-state 123456789' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_snapshot_reset_state(self): - self.run_command('snapshot-reset-state 1234') - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called('POST', '/snapshots/1234/action', body=expected) - - def test_snapshot_reset_state_with_flag(self): - self.run_command('snapshot-reset-state --state error 1234') - expected = {'os-reset_status': {'status': 'error'}} - self.assert_called('POST', '/snapshots/1234/action', body=expected) - - def test_snapshot_reset_state_multiple(self): - self.run_command('snapshot-reset-state 1234 5678') - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called_anytime('POST', '/snapshots/1234/action', - body=expected) - self.assert_called_anytime('POST', '/snapshots/5678/action', - body=expected) - - def test_encryption_type_list(self): - """ - Test encryption-type-list shell command. - - Verify a series of GET requests are made: - - one to get the volume type list information - - one per volume type to retrieve the encryption type information - """ - self.run_command('encryption-type-list') - self.assert_called_anytime('GET', '/types') - self.assert_called_anytime('GET', '/types/1/encryption') - self.assert_called_anytime('GET', '/types/2/encryption') - - def test_encryption_type_show(self): - """ - Test encryption-type-show shell command. - - Verify two GET requests are made per command invocation: - - one to get the volume type information - - one to get the encryption type information - """ - self.run_command('encryption-type-show 1') - self.assert_called('GET', '/types/1/encryption') - self.assert_called_anytime('GET', '/types/1') - - def test_encryption_type_create(self): - """ - Test encryption-type-create shell command. - - Verify GET and POST requests are made per command invocation: - - one GET request to retrieve the relevant volume type information - - one POST request to create the new encryption type - """ - expected = {'encryption': {'cipher': None, 'key_size': None, - 'provider': 'TestProvider', - 'control_location': 'front-end'}} - self.run_command('encryption-type-create 2 TestProvider') - self.assert_called('POST', '/types/2/encryption', body=expected) - self.assert_called_anytime('GET', '/types/2') - - def test_encryption_type_update(self): - """ - Test encryption-type-update shell command. - - Verify two GETs/one PUT requests are made per command invocation: - - one GET request to retrieve the relevant volume type information - - one GET request to retrieve the relevant encryption type information - - one PUT request to update the encryption type information - """ - self.skipTest("Not implemented") - - def test_encryption_type_delete(self): - """ - Test encryption-type-delete shell command. - - Verify one GET/one DELETE requests are made per command invocation: - - one GET request to retrieve the relevant volume type information - - one DELETE request to delete the encryption type information - """ - self.run_command('encryption-type-delete 1') - self.assert_called('DELETE', '/types/1/encryption/provider') - self.assert_called_anytime('GET', '/types/1') - - def test_migrate_volume(self): - self.run_command('migrate 1234 fakehost --force-host-copy=True') - expected = {'os-migrate_volume': {'force_host_copy': 'True', - 'host': 'fakehost'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_snapshot_metadata_set(self): - self.run_command('snapshot-metadata 1234 set key1=val1 key2=val2') - self.assert_called('POST', '/snapshots/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_snapshot_metadata_unset_dict(self): - self.run_command('snapshot-metadata 1234 unset key1=val1 key2=val2') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key1') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key2') - - def test_snapshot_metadata_unset_keys(self): - self.run_command('snapshot-metadata 1234 unset key1 key2') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key1') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key2') - - def test_volume_metadata_update_all(self): - self.run_command('metadata-update-all 1234 key1=val1 key2=val2') - self.assert_called('PUT', '/volumes/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_snapshot_metadata_update_all(self): - self.run_command('snapshot-metadata-update-all\ - 1234 key1=val1 key2=val2') - self.assert_called('PUT', '/snapshots/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_readonly_mode_update(self): - self.run_command('readonly-mode-update 1234 True') - expected = {'os-update_readonly_flag': {'readonly': True}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - self.run_command('readonly-mode-update 1234 False') - expected = {'os-update_readonly_flag': {'readonly': False}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_service_disable(self): - self.run_command('service-disable host cinder-volume') - self.assert_called('PUT', '/os-services/disable', - {"binary": "cinder-volume", "host": "host"}) - - def test_services_disable_with_reason(self): - cmd = 'service-disable host cinder-volume --reason no_reason' - self.run_command(cmd) - body = {'host': 'host', 'binary': 'cinder-volume', - 'disabled_reason': 'no_reason'} - self.assert_called('PUT', '/os-services/disable-log-reason', body) - - def test_service_enable(self): - self.run_command('service-enable host cinder-volume') - self.assert_called('PUT', '/os-services/enable', - {"binary": "cinder-volume", "host": "host"}) - - def test_snapshot_delete(self): - self.run_command('snapshot-delete 1234') - self.assert_called('DELETE', '/snapshots/1234') - - def test_quota_delete(self): - self.run_command('quota-delete 1234') - self.assert_called('DELETE', '/os-quota-sets/1234') - - def test_snapshot_delete_multiple(self): - self.run_command('snapshot-delete 1234 5678') - self.assert_called('DELETE', '/snapshots/5678') diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_snapshot_actions.py b/awx/lib/site-packages/cinderclient/tests/v1/test_snapshot_actions.py deleted file mode 100644 index c9bb81e5b3..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_snapshot_actions.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.fixture_data import client -from cinderclient.tests.fixture_data import snapshots - - -class SnapshotActionsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = snapshots.Fixture - - def test_update_snapshot_status(self): - s = self.cs.volume_snapshots.get('1234') - stat = {'status': 'available'} - self.cs.volume_snapshots.update_snapshot_status(s, stat) - self.assert_called('POST', '/snapshots/1234/action') - - def test_update_snapshot_status_with_progress(self): - s = self.cs.volume_snapshots.get('1234') - stat = {'status': 'available', 'progress': '73%'} - self.cs.volume_snapshots.update_snapshot_status(s, stat) - self.assert_called('POST', '/snapshots/1234/action') diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_types.py b/awx/lib/site-packages/cinderclient/tests/v1/test_types.py deleted file mode 100644 index 90ba775415..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_types.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from cinderclient.v1 import volume_types -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - -cs = fakes.FakeClient() - - -class TypesTest(utils.TestCase): - def test_list_types(self): - tl = cs.volume_types.list() - cs.assert_called('GET', '/types') - for t in tl: - self.assertIsInstance(t, volume_types.VolumeType) - - def test_create(self): - t = cs.volume_types.create('test-type-3') - cs.assert_called('POST', '/types') - self.assertIsInstance(t, volume_types.VolumeType) - - def test_set_key(self): - t = cs.volume_types.get(1) - t.set_keys({'k': 'v'}) - cs.assert_called('POST', - '/types/1/extra_specs', - {'extra_specs': {'k': 'v'}}) - - def test_unsset_keys(self): - t = cs.volume_types.get(1) - t.unset_keys(['k']) - cs.assert_called('DELETE', '/types/1/extra_specs/k') - - def test_delete(self): - cs.volume_types.delete(1) - cs.assert_called('DELETE', '/types/1') diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_volume_backups.py b/awx/lib/site-packages/cinderclient/tests/v1/test_volume_backups.py deleted file mode 100644 index dd7ec0dab5..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_volume_backups.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class VolumeBackupsTest(utils.TestCase): - - def test_create(self): - cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4') - cs.assert_called('POST', '/backups') - - def test_get(self): - backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' - cs.backups.get(backup_id) - cs.assert_called('GET', '/backups/%s' % backup_id) - - def test_list(self): - cs.backups.list() - cs.assert_called('GET', '/backups/detail') - - def test_delete(self): - b = cs.backups.list()[0] - b.delete() - cs.assert_called('DELETE', - '/backups/76a17945-3c6f-435c-975b-b5685db10b62') - cs.backups.delete('76a17945-3c6f-435c-975b-b5685db10b62') - cs.assert_called('DELETE', - '/backups/76a17945-3c6f-435c-975b-b5685db10b62') - cs.backups.delete(b) - cs.assert_called('DELETE', - '/backups/76a17945-3c6f-435c-975b-b5685db10b62') - - def test_restore(self): - backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' - cs.restores.restore(backup_id) - cs.assert_called('POST', '/backups/%s/restore' % backup_id) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_volume_encryption_types.py b/awx/lib/site-packages/cinderclient/tests/v1/test_volume_encryption_types.py deleted file mode 100644 index f8951d2477..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_volume_encryption_types.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (c) 2013 The Johns Hopkins University/Applied Physics Laboratory -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.v1.volume_encryption_types import VolumeEncryptionType -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - -cs = fakes.FakeClient() - - -class VolumeEncryptionTypesTest(utils.TestCase): - """ - Test suite for the Volume Encryption Types Resource and Manager. - """ - - def test_list(self): - """ - Unit test for VolumeEncryptionTypesManager.list - - Verify that a series of GET requests are made: - - one GET request for the list of volume types - - one GET request per volume type for encryption type information - - Verify that all returned information is :class: VolumeEncryptionType - """ - encryption_types = cs.volume_encryption_types.list() - cs.assert_called_anytime('GET', '/types') - cs.assert_called_anytime('GET', '/types/2/encryption') - cs.assert_called_anytime('GET', '/types/1/encryption') - for encryption_type in encryption_types: - self.assertIsInstance(encryption_type, VolumeEncryptionType) - - def test_get(self): - """ - Unit test for VolumeEncryptionTypesManager.get - - Verify that one GET request is made for the volume type encryption - type information. Verify that returned information is :class: - VolumeEncryptionType - """ - encryption_type = cs.volume_encryption_types.get(1) - cs.assert_called('GET', '/types/1/encryption') - self.assertIsInstance(encryption_type, VolumeEncryptionType) - - def test_get_no_encryption(self): - """ - Unit test for VolumeEncryptionTypesManager.get - - Verify that a request on a volume type with no associated encryption - type information returns a VolumeEncryptionType with no attributes. - """ - encryption_type = cs.volume_encryption_types.get(2) - self.assertIsInstance(encryption_type, VolumeEncryptionType) - self.assertFalse(hasattr(encryption_type, 'id'), - 'encryption type has an id') - - def test_create(self): - """ - Unit test for VolumeEncryptionTypesManager.create - - Verify that one POST request is made for the encryption type creation. - Verify that encryption type creation returns a VolumeEncryptionType. - """ - result = cs.volume_encryption_types.create(2, {'provider': 'Test', - 'key_size': None, - 'cipher': None, - 'control_location': - None}) - cs.assert_called('POST', '/types/2/encryption') - self.assertIsInstance(result, VolumeEncryptionType) - - def test_update(self): - """ - Unit test for VolumeEncryptionTypesManager.update - """ - self.skipTest("Not implemented") - - def test_delete(self): - """ - Unit test for VolumeEncryptionTypesManager.delete - - Verify that one DELETE request is made for encryption type deletion - Verify that encryption type deletion returns None - """ - result = cs.volume_encryption_types.delete(1) - cs.assert_called('DELETE', '/types/1/encryption/provider') - self.assertIsNone(result, "delete result must be None") diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_volume_transfers.py b/awx/lib/site-packages/cinderclient/tests/v1/test_volume_transfers.py deleted file mode 100644 index 47656d7940..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_volume_transfers.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class VolumeTransfersTest(utils.TestCase): - - def test_create(self): - cs.transfers.create('1234') - cs.assert_called('POST', '/os-volume-transfer') - - def test_get(self): - transfer_id = '5678' - cs.transfers.get(transfer_id) - cs.assert_called('GET', '/os-volume-transfer/%s' % transfer_id) - - def test_list(self): - cs.transfers.list() - cs.assert_called('GET', '/os-volume-transfer/detail') - - def test_delete(self): - b = cs.transfers.list()[0] - b.delete() - cs.assert_called('DELETE', '/os-volume-transfer/5678') - cs.transfers.delete('5678') - cs.assert_called('DELETE', '/os-volume-transfer/5678') - cs.transfers.delete(b) - cs.assert_called('DELETE', '/os-volume-transfer/5678') - - def test_accept(self): - transfer_id = '5678' - auth_key = '12345' - cs.transfers.accept(transfer_id, auth_key) - cs.assert_called('POST', '/os-volume-transfer/%s/accept' % transfer_id) diff --git a/awx/lib/site-packages/cinderclient/tests/v1/test_volumes.py b/awx/lib/site-packages/cinderclient/tests/v1/test_volumes.py deleted file mode 100644 index 1b59f7f03b..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/test_volumes.py +++ /dev/null @@ -1,113 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class VolumesTest(utils.TestCase): - - def test_delete_volume(self): - v = cs.volumes.list()[0] - v.delete() - cs.assert_called('DELETE', '/volumes/1234') - cs.volumes.delete('1234') - cs.assert_called('DELETE', '/volumes/1234') - cs.volumes.delete(v) - cs.assert_called('DELETE', '/volumes/1234') - - def test_create_volume(self): - cs.volumes.create(1) - cs.assert_called('POST', '/volumes') - - def test_attach(self): - v = cs.volumes.get('1234') - cs.volumes.attach(v, 1, '/dev/vdc', mode='rw') - cs.assert_called('POST', '/volumes/1234/action') - - def test_detach(self): - v = cs.volumes.get('1234') - cs.volumes.detach(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_reserve(self): - v = cs.volumes.get('1234') - cs.volumes.reserve(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_unreserve(self): - v = cs.volumes.get('1234') - cs.volumes.unreserve(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_begin_detaching(self): - v = cs.volumes.get('1234') - cs.volumes.begin_detaching(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_roll_detaching(self): - v = cs.volumes.get('1234') - cs.volumes.roll_detaching(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_initialize_connection(self): - v = cs.volumes.get('1234') - cs.volumes.initialize_connection(v, {}) - cs.assert_called('POST', '/volumes/1234/action') - - def test_terminate_connection(self): - v = cs.volumes.get('1234') - cs.volumes.terminate_connection(v, {}) - cs.assert_called('POST', '/volumes/1234/action') - - def test_set_metadata(self): - cs.volumes.set_metadata(1234, {'k1': 'v1'}) - cs.assert_called('POST', '/volumes/1234/metadata', - {'metadata': {'k1': 'v1'}}) - - def test_delete_metadata(self): - keys = ['key1'] - cs.volumes.delete_metadata(1234, keys) - cs.assert_called('DELETE', '/volumes/1234/metadata/key1') - - def test_extend(self): - v = cs.volumes.get('1234') - cs.volumes.extend(v, 2) - cs.assert_called('POST', '/volumes/1234/action') - - def test_get_encryption_metadata(self): - cs.volumes.get_encryption_metadata('1234') - cs.assert_called('GET', '/volumes/1234/encryption') - - def test_migrate(self): - v = cs.volumes.get('1234') - cs.volumes.migrate_volume(v, 'dest', False) - cs.assert_called('POST', '/volumes/1234/action') - - def test_metadata_update_all(self): - cs.volumes.update_all_metadata(1234, {'k1': 'v1'}) - cs.assert_called('PUT', '/volumes/1234/metadata', - {'metadata': {'k1': 'v1'}}) - - def test_readonly_mode_update(self): - v = cs.volumes.get('1234') - cs.volumes.update_readonly_flag(v, True) - cs.assert_called('POST', '/volumes/1234/action') - - def test_set_bootable(self): - v = cs.volumes.get('1234') - cs.volumes.set_bootable(v, True) - cs.assert_called('POST', '/volumes/1234/action') diff --git a/awx/lib/site-packages/cinderclient/tests/v1/testfile.txt b/awx/lib/site-packages/cinderclient/tests/v1/testfile.txt deleted file mode 100644 index e4e860f38a..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v1/testfile.txt +++ /dev/null @@ -1 +0,0 @@ -BLAH diff --git a/awx/lib/site-packages/cinderclient/tests/v2/__init__.py b/awx/lib/site-packages/cinderclient/tests/v2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/tests/v2/contrib/__init__.py b/awx/lib/site-packages/cinderclient/tests/v2/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/tests/v2/contrib/test_list_extensions.py b/awx/lib/site-packages/cinderclient/tests/v2/contrib/test_list_extensions.py deleted file mode 100644 index 66126be26d..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/contrib/test_list_extensions.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import extension -from cinderclient.v2.contrib import list_extensions -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -extensions = [ - extension.Extension(list_extensions.__name__.split(".")[-1], - list_extensions), -] -cs = fakes.FakeClient(extensions=extensions) - - -class ListExtensionsTests(utils.TestCase): - def test_list_extensions(self): - all_exts = cs.list_extensions.show_all() - cs.assert_called('GET', '/extensions') - self.assertTrue(len(all_exts) > 0) - for r in all_exts: - self.assertTrue(len(r.summary) > 0) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/fakes.py b/awx/lib/site-packages/cinderclient/tests/v2/fakes.py deleted file mode 100644 index dbb50f2b4b..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/fakes.py +++ /dev/null @@ -1,910 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from datetime import datetime - -try: - import urlparse -except ImportError: - import urllib.parse as urlparse - -from cinderclient import client as base_client -from cinderclient.tests import fakes -import cinderclient.tests.utils as utils -from cinderclient.v2 import client - - -def _stub_volume(**kwargs): - volume = { - 'id': '1234', - 'name': None, - 'description': None, - "attachments": [], - "bootable": "false", - "availability_zone": "cinder", - "created_at": "2012-08-27T00:00:00.000000", - "id": '00000000-0000-0000-0000-000000000000', - "metadata": {}, - "size": 1, - "snapshot_id": None, - "status": "available", - "volume_type": "None", - "links": [ - { - "href": "http://localhost/v2/fake/volumes/1234", - "rel": "self" - }, - { - "href": "http://localhost/fake/volumes/1234", - "rel": "bookmark" - } - ], - } - volume.update(kwargs) - return volume - - -def _stub_snapshot(**kwargs): - snapshot = { - "created_at": "2012-08-28T16:30:31.000000", - "display_description": None, - "display_name": None, - "id": '11111111-1111-1111-1111-111111111111', - "size": 1, - "status": "available", - "volume_id": '00000000-0000-0000-0000-000000000000', - } - snapshot.update(kwargs) - return snapshot - - -def _stub_consistencygroup(**kwargs): - consistencygroup = { - "created_at": "2012-08-28T16:30:31.000000", - "description": None, - "name": "cg", - "id": "11111111-1111-1111-1111-111111111111", - "availability_zone": "myzone", - "status": "available", - } - consistencygroup.update(kwargs) - return consistencygroup - - -def _stub_cgsnapshot(**kwargs): - cgsnapshot = { - "created_at": "2012-08-28T16:30:31.000000", - "description": None, - "name": None, - "id": "11111111-1111-1111-1111-111111111111", - "status": "available", - "consistencygroup_id": "00000000-0000-0000-0000-000000000000", - } - cgsnapshot.update(kwargs) - return cgsnapshot - - -def _self_href(base_uri, tenant_id, backup_id): - return '%s/v2/%s/backups/%s' % (base_uri, tenant_id, backup_id) - - -def _bookmark_href(base_uri, tenant_id, backup_id): - return '%s/%s/backups/%s' % (base_uri, tenant_id, backup_id) - - -def _stub_backup_full(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'backup', - 'description': 'nightly backup', - 'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b', - 'container': 'volumebackups', - 'object_count': 220, - 'size': 10, - 'availability_zone': 'az1', - 'created_at': '2013-04-12T08:16:37.000000', - 'status': 'available', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_backup(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'backup', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_qos_full(id, base_uri, tenant_id, name=None, specs=None): - if not name: - name = 'fake-name' - if not specs: - specs = {} - - return { - 'qos_specs': { - 'id': id, - 'name': name, - 'consumer': 'back-end', - 'specs': specs, - }, - 'links': { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - } - - -def _stub_qos_associates(id, name): - return { - 'assoications_type': 'volume_type', - 'name': name, - 'id': id, - } - - -def _stub_restore(): - return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'} - - -def _stub_transfer_full(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'transfer', - 'volume_id': '8c05f861-6052-4df6-b3e0-0aebfbe686cc', - 'created_at': '2013-04-12T08:16:37.000000', - 'auth_key': '123456', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_transfer(id, base_uri, tenant_id): - return { - 'id': id, - 'name': 'transfer', - 'volume_id': '8c05f861-6052-4df6-b3e0-0aebfbe686cc', - 'links': [ - { - 'href': _self_href(base_uri, tenant_id, id), - 'rel': 'self' - }, - { - 'href': _bookmark_href(base_uri, tenant_id, id), - 'rel': 'bookmark' - } - ] - } - - -def _stub_extend(id, new_size): - return {'volume_id': '712f4980-5ac1-41e5-9383-390aa7c9f58b'} - - -class FakeClient(fakes.FakeClient, client.Client): - - def __init__(self, *args, **kwargs): - client.Client.__init__(self, 'username', 'password', - 'project_id', 'auth_url', - extensions=kwargs.get('extensions')) - self.client = FakeHTTPClient(**kwargs) - - def get_volume_api_version_from_endpoint(self): - return self.client.get_volume_api_version_from_endpoint() - - -class FakeHTTPClient(base_client.HTTPClient): - - def __init__(self, **kwargs): - self.username = 'username' - self.password = 'password' - self.auth_url = 'auth_url' - self.callstack = [] - self.management_url = 'http://10.0.2.15:8776/v2/fake' - - def _cs_request(self, url, method, **kwargs): - # Check that certain things are called correctly - if method in ['GET', 'DELETE']: - assert 'body' not in kwargs - elif method == 'PUT': - assert 'body' in kwargs - - # Call the method - args = urlparse.parse_qsl(urlparse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - # Note the call - self.callstack.append((method, url, kwargs.get('body', None))) - status, headers, body = getattr(self, callback)(**kwargs) - r = utils.TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) - return r, body - - if hasattr(status, 'items'): - return utils.TestResponse(status), body - else: - return utils.TestResponse({"status": status}), body - - def get_volume_api_version_from_endpoint(self): - magic_tuple = urlparse.urlsplit(self.management_url) - scheme, netloc, path, query, frag = magic_tuple - return path.lstrip('/').split('/')[0][1:] - - # - # Snapshots - # - - def get_snapshots_detail(self, **kw): - return (200, {}, {'snapshots': [ - _stub_snapshot(), - ]}) - - def get_snapshots_1234(self, **kw): - return (200, {}, {'snapshot': _stub_snapshot(id='1234')}) - - def get_snapshots_5678(self, **kw): - return (200, {}, {'snapshot': _stub_snapshot(id='5678')}) - - def put_snapshots_1234(self, **kw): - snapshot = _stub_snapshot(id='1234') - snapshot.update(kw['body']['snapshot']) - return (200, {}, {'snapshot': snapshot}) - - def post_snapshots_1234_action(self, body, **kw): - _body = None - resp = 202 - assert len(list(body)) == 1 - action = list(body)[0] - if action == 'os-reset_status': - assert 'status' in body['os-reset_status'] - elif action == 'os-update_snapshot_status': - assert 'status' in body['os-update_snapshot_status'] - else: - raise AssertionError('Unexpected action: %s' % action) - return (resp, {}, _body) - - def post_snapshots_5678_action(self, body, **kw): - return self.post_snapshots_1234_action(body, **kw) - - def delete_snapshots_1234(self, **kw): - return (202, {}, {}) - - def delete_snapshots_5678(self, **kw): - return (202, {}, {}) - - # - # Volumes - # - - def put_volumes_1234(self, **kw): - volume = _stub_volume(id='1234') - volume.update(kw['body']['volume']) - return (200, {}, {'volume': volume}) - - def get_volumes(self, **kw): - return (200, {}, {"volumes": [ - {'id': 1234, 'name': 'sample-volume'}, - {'id': 5678, 'name': 'sample-volume2'} - ]}) - - # TODO(jdg): This will need to change - # at the very least it's not complete - def get_volumes_detail(self, **kw): - return (200, {}, {"volumes": [ - {'id': kw.get('id', 1234), - 'name': 'sample-volume', - 'attachments': [{'server_id': 1234}]}, - ]}) - - def get_volumes_1234(self, **kw): - r = {'volume': self.get_volumes_detail(id=1234)[2]['volumes'][0]} - return (200, {}, r) - - def get_volumes_5678(self, **kw): - r = {'volume': self.get_volumes_detail(id=5678)[2]['volumes'][0]} - return (200, {}, r) - - def get_volumes_1234_encryption(self, **kw): - r = {'encryption_key_id': 'id'} - return (200, {}, r) - - def post_volumes_1234_action(self, body, **kw): - _body = None - resp = 202 - assert len(list(body)) == 1 - action = list(body)[0] - if action == 'os-attach': - assert sorted(list(body[action])) == ['instance_uuid', - 'mode', - 'mountpoint'] - elif action == 'os-detach': - assert body[action] is None - elif action == 'os-reserve': - assert body[action] is None - elif action == 'os-unreserve': - assert body[action] is None - elif action == 'os-initialize_connection': - assert list(body[action]) == ['connector'] - return (202, {}, {'connection_info': 'foos'}) - elif action == 'os-terminate_connection': - assert list(body[action]) == ['connector'] - elif action == 'os-begin_detaching': - assert body[action] is None - elif action == 'os-roll_detaching': - assert body[action] is None - elif action == 'os-reset_status': - assert 'status' in body[action] - elif action == 'os-extend': - assert list(body[action]) == ['new_size'] - elif action == 'os-migrate_volume': - assert 'host' in body[action] - assert 'force_host_copy' in body[action] - elif action == 'os-update_readonly_flag': - assert list(body[action]) == ['readonly'] - elif action == 'os-retype': - assert 'new_type' in body[action] - elif action == 'os-set_bootable': - assert list(body[action]) == ['bootable'] - elif action == 'os-unmanage': - assert body[action] is None - elif action == 'os-promote-replica': - assert body[action] is None - elif action == 'os-reenable-replica': - assert body[action] is None - else: - raise AssertionError("Unexpected action: %s" % action) - return (resp, {}, _body) - - def post_volumes_5678_action(self, body, **kw): - return self.post_volumes_1234_action(body, **kw) - - def post_volumes(self, **kw): - size = kw['body']['volume'].get('size', 1) - volume = _stub_volume(id='1234', size=size) - return (202, {}, {'volume': volume}) - - def delete_volumes_1234(self, **kw): - return (202, {}, None) - - def delete_volumes_5678(self, **kw): - return (202, {}, None) - - # - # Consistencygroups - # - - def get_consistencygroups_detail(self, **kw): - return (200, {}, {"consistencygroups": [ - _stub_consistencygroup(id='1234'), - _stub_consistencygroup(id='4567')]}) - - def get_consistencygroups_1234(self, **kw): - return (200, {}, {'consistencygroup': - _stub_consistencygroup(id='1234')}) - - def post_consistencygroups(self, **kw): - return (202, {}, {'consistencygroup': {}}) - - def post_consistencygroups_1234_delete(self, **kw): - return (202, {}, {}) - - # - # Cgsnapshots - # - - def get_cgsnapshots_detail(self, **kw): - return (200, {}, {"cgsnapshots": [ - _stub_cgsnapshot(id='1234'), - _stub_cgsnapshot(id='4567')]}) - - def get_cgsnapshots_1234(self, **kw): - return (200, {}, {'cgsnapshot': _stub_cgsnapshot(id='1234')}) - - def post_cgsnapshots(self, **kw): - return (202, {}, {'cgsnapshot': {}}) - - def delete_cgsnapshots_1234(self, **kw): - return (202, {}, {}) - - # - # Quotas - # - - def get_os_quota_sets_test(self, **kw): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'volumes': 1, - 'snapshots': 1, - 'gigabytes': 1}}) - - def get_os_quota_sets_test_defaults(self): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'volumes': 1, - 'snapshots': 1, - 'gigabytes': 1}}) - - def put_os_quota_sets_test(self, body, **kw): - assert list(body) == ['quota_set'] - fakes.assert_has_keys(body['quota_set'], - required=['tenant_id']) - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'volumes': 2, - 'snapshots': 2, - 'gigabytes': 1}}) - - def delete_os_quota_sets_1234(self, **kw): - return (200, {}, {}) - - def delete_os_quota_sets_test(self, **kw): - return (200, {}, {}) - - # - # Quota Classes - # - - def get_os_quota_class_sets_test(self, **kw): - return (200, {}, {'quota_class_set': { - 'class_name': 'test', - 'metadata_items': [], - 'volumes': 1, - 'snapshots': 1, - 'gigabytes': 1}}) - - def put_os_quota_class_sets_test(self, body, **kw): - assert list(body) == ['quota_class_set'] - fakes.assert_has_keys(body['quota_class_set'], - required=['class_name']) - return (200, {}, {'quota_class_set': { - 'class_name': 'test', - 'metadata_items': [], - 'volumes': 2, - 'snapshots': 2, - 'gigabytes': 1}}) - - # - # VolumeTypes - # - def get_types(self, **kw): - return (200, {}, { - 'volume_types': [{'id': 1, - 'name': 'test-type-1', - 'extra_specs': {}}, - {'id': 2, - 'name': 'test-type-2', - 'extra_specs': {}}]}) - - def get_types_1(self, **kw): - return (200, {}, {'volume_type': {'id': 1, - 'name': 'test-type-1', - 'extra_specs': {}}}) - - def get_types_2(self, **kw): - return (200, {}, {'volume_type': {'id': 2, - 'name': 'test-type-2', - 'extra_specs': {}}}) - - def post_types(self, body, **kw): - return (202, {}, {'volume_type': {'id': 3, - 'name': 'test-type-3', - 'extra_specs': {}}}) - - def post_types_1_extra_specs(self, body, **kw): - assert list(body) == ['extra_specs'] - return (200, {}, {'extra_specs': {'k': 'v'}}) - - def delete_types_1_extra_specs_k(self, **kw): - return(204, {}, None) - - def delete_types_1(self, **kw): - return (202, {}, None) - - # - # VolumeEncryptionTypes - # - def get_types_1_encryption(self, **kw): - return (200, {}, {'id': 1, 'volume_type_id': 1, 'provider': 'test', - 'cipher': 'test', 'key_size': 1, - 'control_location': 'front-end'}) - - def get_types_2_encryption(self, **kw): - return (200, {}, {}) - - def post_types_2_encryption(self, body, **kw): - return (200, {}, {'encryption': body}) - - def put_types_1_encryption_1(self, body, **kw): - return (200, {}, {}) - - def delete_types_1_encryption_provider(self, **kw): - return (202, {}, None) - - # - # Set/Unset metadata - # - def delete_volumes_1234_metadata_test_key(self, **kw): - return (204, {}, None) - - def delete_volumes_1234_metadata_key1(self, **kw): - return (204, {}, None) - - def delete_volumes_1234_metadata_key2(self, **kw): - return (204, {}, None) - - def post_volumes_1234_metadata(self, **kw): - return (204, {}, {'metadata': {'test_key': 'test_value'}}) - - # - # List all extensions - # - def get_extensions(self, **kw): - exts = [ - { - "alias": "FAKE-1", - "description": "Fake extension number 1", - "links": [], - "name": "Fake1", - "namespace": ("http://docs.openstack.org/" - "/ext/fake1/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" - }, - { - "alias": "FAKE-2", - "description": "Fake extension number 2", - "links": [], - "name": "Fake2", - "namespace": ("http://docs.openstack.org/" - "/ext/fake1/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" - }, - ] - return (200, {}, {"extensions": exts, }) - - # - # VolumeBackups - # - - def get_backups_76a17945_3c6f_435c_975b_b5685db10b62(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' - return (200, {}, - {'backup': _stub_backup_full(backup1, base_uri, tenant_id)}) - - def get_backups_detail(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' - backup2 = 'd09534c6-08b8-4441-9e87-8976f3a8f699' - return (200, {}, - {'backups': [ - _stub_backup_full(backup1, base_uri, tenant_id), - _stub_backup_full(backup2, base_uri, tenant_id)]}) - - def delete_backups_76a17945_3c6f_435c_975b_b5685db10b62(self, **kw): - return (202, {}, None) - - def post_backups(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' - return (202, {}, - {'backup': _stub_backup(backup1, base_uri, tenant_id)}) - - def post_backups_76a17945_3c6f_435c_975b_b5685db10b62_restore(self, **kw): - return (200, {}, - {'restore': _stub_restore()}) - - def post_backups_1234_restore(self, **kw): - return (200, {}, - {'restore': _stub_restore()}) - - def get_backups_76a17945_3c6f_435c_975b_b5685db10b62_export_record(self, - **kw): - return (200, - {}, - {'backup-record': {'backup_service': 'fake-backup-service', - 'backup_url': 'fake-backup-url'}}) - - def get_backups_1234_export_record(self, **kw): - return (200, - {}, - {'backup-record': {'backup_service': 'fake-backup-service', - 'backup_url': 'fake-backup-url'}}) - - def post_backups_import_record(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' - return (200, - {}, - {'backup': _stub_backup(backup1, base_uri, tenant_id)}) - - # - # QoSSpecs - # - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - return (200, {}, - _stub_qos_full(qos_id1, base_uri, tenant_id)) - - def get_qos_specs(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - qos_id1 = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - qos_id2 = '0FD8DD14-A396-4E55-9573-1FE59042E95B' - return (200, {}, - {'qos_specs': [ - _stub_qos_full(qos_id1, base_uri, tenant_id, 'name-1'), - _stub_qos_full(qos_id2, base_uri, tenant_id)]}) - - def post_qos_specs(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - qos_name = 'qos-name' - return (202, {}, - _stub_qos_full(qos_id, base_uri, tenant_id, qos_name)) - - def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw): - return (202, {}, None) - - def put_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_delete_keys( - self, **kw): - return (202, {}, None) - - def delete_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C(self, **kw): - return (202, {}, None) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associations( - self, **kw): - type_id1 = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF' - type_id2 = '4230B13A-AB37-4E84-B777-EFBA6FCEE4FF' - type_name1 = 'type1' - type_name2 = 'type2' - return (202, {}, - {'qos_associations': [ - _stub_qos_associates(type_id1, type_name1), - _stub_qos_associates(type_id2, type_name2)]}) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_associate( - self, **kw): - return (202, {}, None) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate( - self, **kw): - return (202, {}, None) - - def get_qos_specs_1B6B6A04_A927_4AEB_810B_B7BAAD49F57C_disassociate_all( - self, **kw): - return (202, {}, None) - - # - # - # VolumeTransfers - # - - def get_os_volume_transfer_5678(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - return (200, {}, - {'transfer': - _stub_transfer_full(transfer1, base_uri, tenant_id)}) - - def get_os_volume_transfer_detail(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - transfer2 = 'f625ec3e-13dd-4498-a22a-50afd534cc41' - return (200, {}, - {'transfers': [ - _stub_transfer_full(transfer1, base_uri, tenant_id), - _stub_transfer_full(transfer2, base_uri, tenant_id)]}) - - def delete_os_volume_transfer_5678(self, **kw): - return (202, {}, None) - - def post_os_volume_transfer(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - return (202, {}, - {'transfer': _stub_transfer(transfer1, base_uri, tenant_id)}) - - def post_os_volume_transfer_5678_accept(self, **kw): - base_uri = 'http://localhost:8776' - tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' - transfer1 = '5678' - return (200, {}, - {'transfer': _stub_transfer(transfer1, base_uri, tenant_id)}) - - # - # Services - # - def get_os_services(self, **kw): - host = kw.get('host', None) - binary = kw.get('binary', None) - services = [ - { - 'binary': 'cinder-volume', - 'host': 'host1', - 'zone': 'cinder', - 'status': 'enabled', - 'state': 'up', - 'updated_at': datetime(2012, 10, 29, 13, 42, 2) - }, - { - 'binary': 'cinder-volume', - 'host': 'host2', - 'zone': 'cinder', - 'status': 'disabled', - 'state': 'down', - 'updated_at': datetime(2012, 9, 18, 8, 3, 38) - }, - { - 'binary': 'cinder-scheduler', - 'host': 'host2', - 'zone': 'cinder', - 'status': 'disabled', - 'state': 'down', - 'updated_at': datetime(2012, 9, 18, 8, 3, 38) - }, - ] - if host: - services = filter(lambda i: i['host'] == host, services) - if binary: - services = filter(lambda i: i['binary'] == binary, services) - return (200, {}, {'services': services}) - - def put_os_services_enable(self, body, **kw): - return (200, {}, {'host': body['host'], 'binary': body['binary'], - 'status': 'enabled'}) - - def put_os_services_disable(self, body, **kw): - return (200, {}, {'host': body['host'], 'binary': body['binary'], - 'status': 'disabled'}) - - def put_os_services_disable_log_reason(self, body, **kw): - return (200, {}, {'host': body['host'], 'binary': body['binary'], - 'status': 'disabled', - 'disabled_reason': body['disabled_reason']}) - - def get_os_availability_zone(self, **kw): - return (200, {}, { - "availabilityZoneInfo": [ - { - "zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": None, - }, - { - "zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None, - }, - ] - }) - - def get_os_availability_zone_detail(self, **kw): - return (200, {}, { - "availabilityZoneInfo": [ - { - "zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "cinder-volume": { - "active": True, - "available": True, - "updated_at": - datetime(2012, 12, 26, 14, 45, 25, 0) - } - } - } - }, - { - "zoneName": "internal", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "cinder-sched": { - "active": True, - "available": True, - "updated_at": - datetime(2012, 12, 26, 14, 45, 24, 0) - } - } - } - }, - { - "zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None, - }, - ] - }) - - def post_snapshots_1234_metadata(self, **kw): - return (200, {}, {"metadata": {"key1": "val1", "key2": "val2"}}) - - def delete_snapshots_1234_metadata_key1(self, **kw): - return (200, {}, None) - - def delete_snapshots_1234_metadata_key2(self, **kw): - return (200, {}, None) - - def put_volumes_1234_metadata(self, **kw): - return (200, {}, {"metadata": {"key1": "val1", "key2": "val2"}}) - - def put_snapshots_1234_metadata(self, **kw): - return (200, {}, {"metadata": {"key1": "val1", "key2": "val2"}}) - - def post_os_volume_manage(self, **kw): - volume = _stub_volume(id='1234') - volume.update(kw['body']['volume']) - return (202, {}, {'volume': volume}) - - def post_os_promote_replica_1234(self, **kw): - return (202, {}, {}) - - def post_os_reenable_replica_1234(self, **kw): - return (202, {}, {}) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_auth.py b/awx/lib/site-packages/cinderclient/tests/v2/test_auth.py deleted file mode 100644 index cb6dcadf2a..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_auth.py +++ /dev/null @@ -1,341 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json - -import mock -import requests - -from cinderclient import exceptions -from cinderclient.v2 import client -from cinderclient.tests import utils - - -class AuthenticateAgainstKeystoneTests(utils.TestCase): - def test_authenticate_success(self): - cs = client.Client("username", "password", "project_id", - "http://localhost:8776/v2", service_type='volumev2') - resp = { - "access": { - "token": { - "expires": "2014-11-01T03:32:15-05:00", - "id": "FAKE_ID", - }, - "serviceCatalog": [ - { - "type": "volumev2", - "endpoints": [ - { - "region": "RegionOne", - "adminURL": "http://localhost:8776/v2", - "internalURL": "http://localhost:8776/v2", - "publicURL": "http://localhost:8776/v2", - }, - ], - }, - ], - }, - } - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(public_url, cs.client.management_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(token_id, cs.client.auth_token) - - test_auth_call() - - def test_authenticate_tenant_id(self): - cs = client.Client("username", "password", - auth_url="http://localhost:8776/v2", - tenant_id='tenant_id', service_type='volumev2') - resp = { - "access": { - "token": { - "expires": "2014-11-01T03:32:15-05:00", - "id": "FAKE_ID", - "tenant": { - "description": None, - "enabled": True, - "id": "tenant_id", - "name": "demo" - } # tenant associated with token - }, - "serviceCatalog": [ - { - "type": 'volumev2', - "endpoints": [ - { - "region": "RegionOne", - "adminURL": "http://localhost:8776/v2", - "internalURL": "http://localhost:8776/v2", - "publicURL": "http://localhost:8776/v2", - }, - ], - }, - ], - }, - } - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantId': cs.client.tenant_id, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(public_url, cs.client.management_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(token_id, cs.client.auth_token) - tenant_id = resp["access"]["token"]["tenant"]["id"] - self.assertEqual(tenant_id, cs.client.tenant_id) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", "project_id", - "http://localhost:8776/v2") - resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}} - auth_response = utils.TestResponse({ - "status_code": 401, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_auth_redirect(self): - cs = client.Client("username", "password", "project_id", - "http://localhost:8776/v2", service_type='volumev2') - dict_correct_response = { - "access": { - "token": { - "expires": "2014-11-01T03:32:15-05:00", - "id": "FAKE_ID", - }, - "serviceCatalog": [ - { - "type": "volumev2", - "endpoints": [ - { - "adminURL": "http://localhost:8776/v2", - "region": "RegionOne", - "internalURL": "http://localhost:8776/v2", - "publicURL": "http://localhost:8776/v2/", - }, - ], - }, - ], - }, - } - correct_response = json.dumps(dict_correct_response) - dict_responses = [ - {"headers": {'location': 'http://127.0.0.1:5001'}, - "status_code": 305, - "text": "Use proxy"}, - # Configured on admin port, cinder redirects to v2.0 port. - # When trying to connect on it, keystone auth succeed by v1.0 - # protocol (through headers) but tokens are being returned in - # body (looks like keystone bug). Leaved for compatibility. - {"headers": {}, - "status_code": 200, - "text": correct_response}, - {"headers": {}, - "status_code": 200, - "text": correct_response} - ] - - responses = [(utils.TestResponse(resp)) for resp in dict_responses] - - def side_effect(*args, **kwargs): - return responses.pop(0) - - mock_request = mock.Mock(side_effect=side_effect) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - resp = dict_correct_response - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(public_url, cs.client.management_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(token_id, cs.client.auth_token) - - test_auth_call() - - -class AuthenticationTests(utils.TestCase): - def test_authenticate_success(self): - cs = client.Client("username", "password", "project_id", "auth_url") - management_url = 'https://localhost/v2.1/443470' - auth_response = utils.TestResponse({ - 'status_code': 204, - 'headers': { - 'x-server-management-url': management_url, - 'x-auth-token': '1b751d74-de0c-46ae-84f0-915744b582d1', - }, - }) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'Accept': 'application/json', - 'X-Auth-User': 'username', - 'X-Auth-Key': 'password', - 'X-Auth-Project-Id': 'project_id', - 'User-Agent': cs.client.USER_AGENT - } - mock_request.assert_called_with( - "GET", - cs.client.auth_url, - headers=headers, - **self.TEST_REQUEST_BASE) - - self.assertEqual(auth_response.headers['x-server-management-url'], - cs.client.management_url) - self.assertEqual(auth_response.headers['x-auth-token'], - cs.client.auth_token) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", "project_id", "auth_url") - auth_response = utils.TestResponse({"status_code": 401}) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_auth_automatic(self): - cs = client.Client("username", "password", "project_id", "auth_url") - http_client = cs.client - http_client.management_url = '' - mock_request = mock.Mock(return_value=(None, None)) - - @mock.patch.object(http_client, 'request', mock_request) - @mock.patch.object(http_client, 'authenticate') - def test_auth_call(m): - http_client.get('/') - m.assert_called() - mock_request.assert_called() - - test_auth_call() - - def test_auth_manual(self): - cs = client.Client("username", "password", "project_id", "auth_url") - - @mock.patch.object(cs.client, 'authenticate') - def test_auth_call(m): - cs.authenticate() - m.assert_called() - - test_auth_call() diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_availability_zone.py b/awx/lib/site-packages/cinderclient/tests/v2/test_availability_zone.py deleted file mode 100644 index 599e884f57..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_availability_zone.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2011-2013 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from cinderclient.v2 import availability_zones -from cinderclient.v2 import shell -from cinderclient.tests.fixture_data import client -from cinderclient.tests.fixture_data import availability_zones as azfixture -from cinderclient.tests import utils - - -class AvailabilityZoneTest(utils.FixturedTestCase): - - client_fixture_class = client.V2 - data_fixture_class = azfixture.Fixture - - def _assertZone(self, zone, name, status): - self.assertEqual(name, zone.zoneName) - self.assertEqual(status, zone.zoneState) - - def test_list_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=False) - self.assert_called('GET', '/os-availability-zone') - - for zone in zones: - self.assertIsInstance(zone, - availability_zones.AvailabilityZone) - - self.assertEqual(2, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('zone-2'), six.u('not available')] - - z0 = shell._treeizeAvailabilityZone(zones[0]) - z1 = shell._treeizeAvailabilityZone(zones[1]) - - self.assertEqual((1, 1), (len(z0), len(z1))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z1[0], l1[0], l1[1]) - - def test_detail_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=True) - self.assert_called('GET', '/os-availability-zone/detail') - - for zone in zones: - self.assertIsInstance(zone, - availability_zones.AvailabilityZone) - - self.assertEqual(3, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('|- fake_host-1'), six.u('')] - l2 = [six.u('| |- cinder-volume'), - six.u('enabled :-) 2012-12-26 14:45:25')] - l3 = [six.u('internal'), six.u('available')] - l4 = [six.u('|- fake_host-1'), six.u('')] - l5 = [six.u('| |- cinder-sched'), - six.u('enabled :-) 2012-12-26 14:45:24')] - l6 = [six.u('zone-2'), six.u('not available')] - - z0 = shell._treeizeAvailabilityZone(zones[0]) - z1 = shell._treeizeAvailabilityZone(zones[1]) - z2 = shell._treeizeAvailabilityZone(zones[2]) - - self.assertEqual((3, 3, 1), (len(z0), len(z1), len(z2))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z0[1], l1[0], l1[1]) - self._assertZone(z0[2], l2[0], l2[1]) - self._assertZone(z1[0], l3[0], l3[1]) - self._assertZone(z1[1], l4[0], l4[1]) - self._assertZone(z1[2], l5[0], l5[1]) - self._assertZone(z2[0], l6[0], l6[1]) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_cgsnapshots.py b/awx/lib/site-packages/cinderclient/tests/v2/test_cgsnapshots.py deleted file mode 100644 index 0d5fad333f..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_cgsnapshots.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (C) 2012 - 2014 EMC Corporation. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - - -cs = fakes.FakeClient() - - -class cgsnapshotsTest(utils.TestCase): - - def test_delete_cgsnapshot(self): - v = cs.cgsnapshots.list()[0] - v.delete() - cs.assert_called('DELETE', '/cgsnapshots/1234') - cs.cgsnapshots.delete('1234') - cs.assert_called('DELETE', '/cgsnapshots/1234') - cs.cgsnapshots.delete(v) - cs.assert_called('DELETE', '/cgsnapshots/1234') - - def test_create_cgsnapshot(self): - cs.cgsnapshots.create('cgsnap') - cs.assert_called('POST', '/cgsnapshots') - - def test_create_cgsnapshot_with_cg_id(self): - cs.cgsnapshots.create('1234') - expected = {'cgsnapshot': {'status': 'creating', - 'description': None, - 'user_id': None, - 'name': None, - 'consistencygroup_id': '1234', - 'project_id': None}} - cs.assert_called('POST', '/cgsnapshots', body=expected) - - def test_list_cgsnapshot(self): - cs.cgsnapshots.list() - cs.assert_called('GET', '/cgsnapshots/detail') - - def test_get_cgsnapshot(self): - cgsnapshot_id = '1234' - cs.cgsnapshots.get(cgsnapshot_id) - cs.assert_called('GET', '/cgsnapshots/%s' % cgsnapshot_id) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_consistencygroups.py b/awx/lib/site-packages/cinderclient/tests/v2/test_consistencygroups.py deleted file mode 100644 index 234cb3ce93..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_consistencygroups.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (C) 2012 - 2014 EMC Corporation. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - - -cs = fakes.FakeClient() - - -class ConsistencygroupsTest(utils.TestCase): - - def test_delete_consistencygroup(self): - v = cs.consistencygroups.list()[0] - v.delete(force='True') - cs.assert_called('POST', '/consistencygroups/1234/delete') - cs.consistencygroups.delete('1234', force=True) - cs.assert_called('POST', '/consistencygroups/1234/delete') - cs.consistencygroups.delete(v, force=True) - cs.assert_called('POST', '/consistencygroups/1234/delete') - - def test_create_consistencygroup(self): - cs.consistencygroups.create('type1,type2', 'cg') - cs.assert_called('POST', '/consistencygroups') - - def test_create_consistencygroup_with_volume_types(self): - cs.consistencygroups.create('type1,type2', 'cg') - expected = {'consistencygroup': {'status': 'creating', - 'description': None, - 'availability_zone': None, - 'user_id': None, - 'name': 'cg', - 'volume_types': 'type1,type2', - 'project_id': None}} - cs.assert_called('POST', '/consistencygroups', body=expected) - - def test_list_consistencygroup(self): - cs.consistencygroups.list() - cs.assert_called('GET', '/consistencygroups/detail') diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_limits.py b/awx/lib/site-packages/cinderclient/tests/v2/test_limits.py deleted file mode 100644 index 126f2bf9a4..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_limits.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock - -from cinderclient.tests import utils -from cinderclient.v2 import limits - - -def _get_default_RateLimit(verb="verb1", uri="uri1", regex="regex1", - value="value1", - remain="remain1", unit="unit1", - next_available="next1"): - return limits.RateLimit(verb, uri, regex, value, remain, unit, - next_available) - - -class TestLimits(utils.TestCase): - def test_repr(self): - l = limits.Limits(None, {"foo": "bar"}) - self.assertEqual("<Limits>", repr(l)) - - def test_absolute(self): - l = limits.Limits(None, - {"absolute": {"name1": "value1", "name2": "value2"}}) - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name2", "value2") - for item in l.absolute: - self.assertIn(item, [l1, l2]) - - def test_rate(self): - l = limits.Limits(None, - { - "rate": [ - { - "uri": "uri1", - "regex": "regex1", - "limit": [ - { - "verb": "verb1", - "value": "value1", - "remaining": "remain1", - "unit": "unit1", - "next-available": "next1", - }, - ], - }, - { - "uri": "uri2", - "regex": "regex2", - "limit": [ - { - "verb": "verb2", - "value": "value2", - "remaining": "remain2", - "unit": "unit2", - "next-available": "next2", - }, - ], - }, - ], - }) - l1 = limits.RateLimit("verb1", "uri1", "regex1", "value1", "remain1", - "unit1", "next1") - l2 = limits.RateLimit("verb2", "uri2", "regex2", "value2", "remain2", - "unit2", "next2") - for item in l.rate: - self.assertIn(item, [l1, l2]) - - -class TestRateLimit(utils.TestCase): - def test_equal(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit() - self.assertEqual(l1, l2) - - def test_not_equal_verbs(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(verb="verb2") - self.assertNotEqual(l1, l2) - - def test_not_equal_uris(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(uri="uri2") - self.assertNotEqual(l1, l2) - - def test_not_equal_regexps(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(regex="regex2") - self.assertNotEqual(l1, l2) - - def test_not_equal_values(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(value="value2") - self.assertNotEqual(l1, l2) - - def test_not_equal_remains(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(remain="remain2") - self.assertNotEqual(l1, l2) - - def test_not_equal_units(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(unit="unit2") - self.assertNotEqual(l1, l2) - - def test_not_equal_next_available(self): - l1 = _get_default_RateLimit() - l2 = _get_default_RateLimit(next_available="next2") - self.assertNotEqual(l1, l2) - - def test_repr(self): - l1 = _get_default_RateLimit() - self.assertEqual("<RateLimit: method=verb1 uri=uri1>", repr(l1)) - - -class TestAbsoluteLimit(utils.TestCase): - def test_equal(self): - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name1", "value1") - self.assertEqual(l1, l2) - - def test_not_equal_values(self): - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name1", "value2") - self.assertNotEqual(l1, l2) - - def test_not_equal_names(self): - l1 = limits.AbsoluteLimit("name1", "value1") - l2 = limits.AbsoluteLimit("name2", "value1") - self.assertNotEqual(l1, l2) - - def test_repr(self): - l1 = limits.AbsoluteLimit("name1", "value1") - self.assertEqual("<AbsoluteLimit: name=name1>", repr(l1)) - - -class TestLimitsManager(utils.TestCase): - def test_get(self): - api = mock.Mock() - api.client.get.return_value = ( - None, - {"limits": {"absolute": {"name1": "value1", }}, - "no-limits": {"absolute": {"name2": "value2", }}}) - l1 = limits.AbsoluteLimit("name1", "value1") - limitsManager = limits.LimitsManager(api) - - lim = limitsManager.get() - - self.assertIsInstance(lim, limits.Limits) - for l in lim.absolute: - self.assertEqual(l1, l) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_qos.py b/awx/lib/site-packages/cinderclient/tests/v2/test_qos.py deleted file mode 100644 index 3f3e6cf2ce..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_qos.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2013 eBay Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - - -cs = fakes.FakeClient() - - -class QoSSpecsTest(utils.TestCase): - - def test_create(self): - specs = dict(k1='v1', k2='v2') - cs.qos_specs.create('qos-name', specs) - cs.assert_called('POST', '/qos-specs') - - def test_get(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.get(qos_id) - cs.assert_called('GET', '/qos-specs/%s' % qos_id) - - def test_list(self): - cs.qos_specs.list() - cs.assert_called('GET', '/qos-specs') - - def test_delete(self): - cs.qos_specs.delete('1B6B6A04-A927-4AEB-810B-B7BAAD49F57C') - cs.assert_called('DELETE', - '/qos-specs/1B6B6A04-A927-4AEB-810B-B7BAAD49F57C?' - 'force=False') - - def test_set_keys(self): - body = {'qos_specs': dict(k1='v1')} - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.set_keys(qos_id, body) - cs.assert_called('PUT', '/qos-specs/%s' % qos_id) - - def test_unset_keys(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - body = {'keys': ['k1']} - cs.qos_specs.unset_keys(qos_id, body) - cs.assert_called('PUT', '/qos-specs/%s/delete_keys' % qos_id) - - def test_get_associations(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.get_associations(qos_id) - cs.assert_called('GET', '/qos-specs/%s/associations' % qos_id) - - def test_associate(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF' - cs.qos_specs.associate(qos_id, type_id) - cs.assert_called('GET', '/qos-specs/%s/associate?vol_type_id=%s' - % (qos_id, type_id)) - - def test_disassociate(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - type_id = '4230B13A-7A37-4E84-B777-EFBA6FCEE4FF' - cs.qos_specs.disassociate(qos_id, type_id) - cs.assert_called('GET', '/qos-specs/%s/disassociate?vol_type_id=%s' - % (qos_id, type_id)) - - def test_disassociate_all(self): - qos_id = '1B6B6A04-A927-4AEB-810B-B7BAAD49F57C' - cs.qos_specs.disassociate_all(qos_id) - cs.assert_called('GET', '/qos-specs/%s/disassociate_all' % qos_id) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_quota_classes.py b/awx/lib/site-packages/cinderclient/tests/v2/test_quota_classes.py deleted file mode 100644 index 0fee1e8d72..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_quota_classes.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - - -cs = fakes.FakeClient() - - -class QuotaClassSetsTest(utils.TestCase): - - def test_class_quotas_get(self): - class_name = 'test' - cs.quota_classes.get(class_name) - cs.assert_called('GET', '/os-quota-class-sets/%s' % class_name) - - def test_update_quota(self): - q = cs.quota_classes.get('test') - q.update(volumes=2, snapshots=2) - cs.assert_called('PUT', '/os-quota-class-sets/test') - - def test_refresh_quota(self): - q = cs.quota_classes.get('test') - q2 = cs.quota_classes.get('test') - self.assertEqual(q.volumes, q2.volumes) - q2.volumes = 0 - self.assertNotEqual(q.volumes, q2.volumes) - q2.get() - self.assertEqual(q.volumes, q2.volumes) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_quotas.py b/awx/lib/site-packages/cinderclient/tests/v2/test_quotas.py deleted file mode 100644 index e4a723aef5..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_quotas.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - - -cs = fakes.FakeClient() - - -class QuotaSetsTest(utils.TestCase): - - def test_tenant_quotas_get(self): - tenant_id = 'test' - cs.quotas.get(tenant_id) - cs.assert_called('GET', '/os-quota-sets/%s?usage=False' % tenant_id) - - def test_tenant_quotas_defaults(self): - tenant_id = 'test' - cs.quotas.defaults(tenant_id) - cs.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id) - - def test_update_quota(self): - q = cs.quotas.get('test') - q.update(volumes=2) - q.update(snapshots=2) - cs.assert_called('PUT', '/os-quota-sets/test') - - def test_refresh_quota(self): - q = cs.quotas.get('test') - q2 = cs.quotas.get('test') - self.assertEqual(q.volumes, q2.volumes) - self.assertEqual(q.snapshots, q2.snapshots) - q2.volumes = 0 - self.assertNotEqual(q.volumes, q2.volumes) - q2.snapshots = 0 - self.assertNotEqual(q.snapshots, q2.snapshots) - q2.get() - self.assertEqual(q.volumes, q2.volumes) - self.assertEqual(q.snapshots, q2.snapshots) - - def test_delete_quota(self): - tenant_id = 'test' - cs.quotas.delete(tenant_id) - cs.assert_called('DELETE', '/os-quota-sets/test') diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_services.py b/awx/lib/site-packages/cinderclient/tests/v2/test_services.py deleted file mode 100644 index ddce61c8f4..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_services.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes -from cinderclient.v2 import services - - -cs = fakes.FakeClient() - - -class ServicesTest(utils.TestCase): - - def test_list_services(self): - svs = cs.services.list() - cs.assert_called('GET', '/os-services') - self.assertEqual(3, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - - def test_list_services_with_hostname(self): - svs = cs.services.list(host='host2') - cs.assert_called('GET', '/os-services?host=host2') - self.assertEqual(2, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - [self.assertEqual('host2', s.host) for s in svs] - - def test_list_services_with_binary(self): - svs = cs.services.list(binary='cinder-volume') - cs.assert_called('GET', '/os-services?binary=cinder-volume') - self.assertEqual(2, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - [self.assertEqual('cinder-volume', s.binary) for s in svs] - - def test_list_services_with_host_binary(self): - svs = cs.services.list('host2', 'cinder-volume') - cs.assert_called('GET', '/os-services?host=host2&binary=cinder-volume') - self.assertEqual(1, len(svs)) - [self.assertIsInstance(s, services.Service) for s in svs] - [self.assertEqual('host2', s.host) for s in svs] - [self.assertEqual('cinder-volume', s.binary) for s in svs] - - def test_services_enable(self): - s = cs.services.enable('host1', 'cinder-volume') - values = {"host": "host1", 'binary': 'cinder-volume'} - cs.assert_called('PUT', '/os-services/enable', values) - self.assertIsInstance(s, services.Service) - self.assertEqual('enabled', s.status) - - def test_services_disable(self): - s = cs.services.disable('host1', 'cinder-volume') - values = {"host": "host1", 'binary': 'cinder-volume'} - cs.assert_called('PUT', '/os-services/disable', values) - self.assertIsInstance(s, services.Service) - self.assertEqual('disabled', s.status) - - def test_services_disable_log_reason(self): - s = cs.services.disable_log_reason( - 'host1', 'cinder-volume', 'disable bad host') - values = {"host": "host1", 'binary': 'cinder-volume', - "disabled_reason": "disable bad host"} - cs.assert_called('PUT', '/os-services/disable-log-reason', values) - self.assertIsInstance(s, services.Service) - self.assertEqual('disabled', s.status) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_shell.py b/awx/lib/site-packages/cinderclient/tests/v2/test_shell.py deleted file mode 100644 index 696d627db8..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_shell.py +++ /dev/null @@ -1,542 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -from requests_mock.contrib import fixture as requests_mock_fixture - -from cinderclient import client -from cinderclient import exceptions -from cinderclient import shell -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes -from cinderclient.tests.fixture_data import keystone_client - - -class ShellTest(utils.TestCase): - - FAKE_ENV = { - 'CINDER_USERNAME': 'username', - 'CINDER_PASSWORD': 'password', - 'CINDER_PROJECT_ID': 'project_id', - 'OS_VOLUME_API_VERSION': '2', - 'CINDER_URL': keystone_client.BASE_URL, - } - - # Patch os.environ to avoid required auth info. - def setUp(self): - """Run before each test.""" - super(ShellTest, self).setUp() - for var in self.FAKE_ENV: - self.useFixture(fixtures.EnvironmentVariable(var, - self.FAKE_ENV[var])) - - self.shell = shell.OpenStackCinderShell() - - # HACK(bcwaldon): replace this when we start using stubs - self.old_get_client_class = client.get_client_class - client.get_client_class = lambda *_: fakes.FakeClient - - self.requests = self.useFixture(requests_mock_fixture.Fixture()) - self.requests.register_uri( - 'GET', keystone_client.BASE_URL, - text=keystone_client.keystone_request_callback) - - def tearDown(self): - # For some method like test_image_meta_bad_action we are - # testing a SystemExit to be thrown and object self.shell has - # no time to get instantatiated which is OK in this case, so - # we make sure the method is there before launching it. - if hasattr(self.shell, 'cs'): - self.shell.cs.clear_callstack() - - # HACK(bcwaldon): replace this when we start using stubs - client.get_client_class = self.old_get_client_class - super(ShellTest, self).tearDown() - - def run_command(self, cmd): - self.shell.main(cmd.split()) - - def assert_called(self, method, url, body=None, - partial_body=None, **kwargs): - return self.shell.cs.assert_called(method, url, body, - partial_body, **kwargs) - - def assert_called_anytime(self, method, url, body=None, - partial_body=None): - return self.shell.cs.assert_called_anytime(method, url, body, - partial_body) - - def test_list(self): - self.run_command('list') - # NOTE(jdg): we default to detail currently - self.assert_called('GET', '/volumes/detail') - - def test_list_filter_status(self): - self.run_command('list --status=available') - self.assert_called('GET', '/volumes/detail?status=available') - - def test_list_filter_name(self): - self.run_command('list --name=1234') - self.assert_called('GET', '/volumes/detail?name=1234') - - def test_list_all_tenants(self): - self.run_command('list --all-tenants=1') - self.assert_called('GET', '/volumes/detail?all_tenants=1') - - def test_list_marker(self): - self.run_command('list --marker=1234') - self.assert_called('GET', '/volumes/detail?marker=1234') - - def test_list_limit(self): - self.run_command('list --limit=10') - self.assert_called('GET', '/volumes/detail?limit=10') - - def test_list_sort(self): - self.run_command('list --sort_key=name --sort_dir=asc') - self.assert_called('GET', '/volumes/detail?sort_dir=asc&sort_key=name') - - def test_list_availability_zone(self): - self.run_command('availability-zone-list') - self.assert_called('GET', '/os-availability-zone') - - def test_create_volume_from_snapshot(self): - expected = {'volume': {'size': None}} - - expected['volume']['snapshot_id'] = '1234' - self.run_command('create --snapshot-id=1234') - self.assert_called_anytime('POST', '/volumes', partial_body=expected) - self.assert_called('GET', '/volumes/1234') - - expected['volume']['size'] = 2 - self.run_command('create --snapshot-id=1234 2') - self.assert_called_anytime('POST', '/volumes', partial_body=expected) - self.assert_called('GET', '/volumes/1234') - - def test_create_volume_from_volume(self): - expected = {'volume': {'size': None}} - - expected['volume']['source_volid'] = '1234' - self.run_command('create --source-volid=1234') - self.assert_called_anytime('POST', '/volumes', partial_body=expected) - self.assert_called('GET', '/volumes/1234') - - expected['volume']['size'] = 2 - self.run_command('create --source-volid=1234 2') - self.assert_called_anytime('POST', '/volumes', partial_body=expected) - self.assert_called('GET', '/volumes/1234') - - def test_create_volume_from_replica(self): - expected = {'volume': {'size': None}} - - expected['volume']['source_replica'] = '1234' - self.run_command('create --source-replica=1234') - self.assert_called_anytime('POST', '/volumes', partial_body=expected) - self.assert_called('GET', '/volumes/1234') - - def test_create_size_required_if_not_snapshot_or_clone(self): - self.assertRaises(SystemExit, self.run_command, 'create') - - def test_show(self): - self.run_command('show 1234') - self.assert_called('GET', '/volumes/1234') - - def test_delete(self): - self.run_command('delete 1234') - self.assert_called('DELETE', '/volumes/1234') - - def test_delete_by_name(self): - self.run_command('delete sample-volume') - self.assert_called_anytime('GET', '/volumes/detail?all_tenants=1') - self.assert_called('DELETE', '/volumes/1234') - - def test_delete_multiple(self): - self.run_command('delete 1234 5678') - self.assert_called_anytime('DELETE', '/volumes/1234') - self.assert_called('DELETE', '/volumes/5678') - - def test_backup(self): - self.run_command('backup-create 1234') - self.assert_called('POST', '/backups') - - def test_restore(self): - self.run_command('backup-restore 1234') - self.assert_called('POST', '/backups/1234/restore') - - def test_record_export(self): - self.run_command('backup-export 1234') - self.assert_called('GET', '/backups/1234/export_record') - - def test_record_import(self): - self.run_command('backup-import fake.driver URL_STRING') - expected = {'backup-record': {'backup_service': 'fake.driver', - 'backup_url': 'URL_STRING'}} - self.assert_called('POST', '/backups/import_record', expected) - - def test_snapshot_list_filter_volume_id(self): - self.run_command('snapshot-list --volume-id=1234') - self.assert_called('GET', '/snapshots/detail?volume_id=1234') - - def test_snapshot_list_filter_status_and_volume_id(self): - self.run_command('snapshot-list --status=available --volume-id=1234') - self.assert_called('GET', '/snapshots/detail?' - 'status=available&volume_id=1234') - - def test_rename(self): - # basic rename with positional arguments - self.run_command('rename 1234 new-name') - expected = {'volume': {'name': 'new-name'}} - self.assert_called('PUT', '/volumes/1234', body=expected) - # change description only - self.run_command('rename 1234 --description=new-description') - expected = {'volume': {'description': 'new-description'}} - self.assert_called('PUT', '/volumes/1234', body=expected) - # rename and change description - self.run_command('rename 1234 new-name ' - '--description=new-description') - expected = {'volume': { - 'name': 'new-name', - 'description': 'new-description', - }} - self.assert_called('PUT', '/volumes/1234', body=expected) - - # Call rename with no arguments - self.assertRaises(SystemExit, self.run_command, 'rename') - - def test_rename_snapshot(self): - # basic rename with positional arguments - self.run_command('snapshot-rename 1234 new-name') - expected = {'snapshot': {'name': 'new-name'}} - self.assert_called('PUT', '/snapshots/1234', body=expected) - # change description only - self.run_command('snapshot-rename 1234 ' - '--description=new-description') - expected = {'snapshot': {'description': 'new-description'}} - self.assert_called('PUT', '/snapshots/1234', body=expected) - # snapshot-rename and change description - self.run_command('snapshot-rename 1234 new-name ' - '--description=new-description') - expected = {'snapshot': { - 'name': 'new-name', - 'description': 'new-description', - }} - self.assert_called('PUT', '/snapshots/1234', body=expected) - - # Call snapshot-rename with no arguments - self.assertRaises(SystemExit, self.run_command, 'snapshot-rename') - - def test_set_metadata_set(self): - self.run_command('metadata 1234 set key1=val1 key2=val2') - self.assert_called('POST', '/volumes/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_set_metadata_delete_dict(self): - self.run_command('metadata 1234 unset key1=val1 key2=val2') - self.assert_called('DELETE', '/volumes/1234/metadata/key1') - self.assert_called('DELETE', '/volumes/1234/metadata/key2', pos=-2) - - def test_set_metadata_delete_keys(self): - self.run_command('metadata 1234 unset key1 key2') - self.assert_called('DELETE', '/volumes/1234/metadata/key1') - self.assert_called('DELETE', '/volumes/1234/metadata/key2', pos=-2) - - def test_reset_state(self): - self.run_command('reset-state 1234') - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_reset_state_with_flag(self): - self.run_command('reset-state --state error 1234') - expected = {'os-reset_status': {'status': 'error'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_reset_state_multiple(self): - self.run_command('reset-state 1234 5678 --state error') - expected = {'os-reset_status': {'status': 'error'}} - self.assert_called_anytime('POST', '/volumes/1234/action', - body=expected) - self.assert_called_anytime('POST', '/volumes/5678/action', - body=expected) - - def test_reset_state_two_with_one_nonexistent(self): - cmd = 'reset-state 1234 123456789' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called_anytime('POST', '/volumes/1234/action', - body=expected) - - def test_reset_state_one_with_one_nonexistent(self): - cmd = 'reset-state 123456789' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_snapshot_reset_state(self): - self.run_command('snapshot-reset-state 1234') - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called('POST', '/snapshots/1234/action', body=expected) - - def test_snapshot_reset_state_with_flag(self): - self.run_command('snapshot-reset-state --state error 1234') - expected = {'os-reset_status': {'status': 'error'}} - self.assert_called('POST', '/snapshots/1234/action', body=expected) - - def test_snapshot_reset_state_multiple(self): - self.run_command('snapshot-reset-state 1234 5678') - expected = {'os-reset_status': {'status': 'available'}} - self.assert_called_anytime('POST', '/snapshots/1234/action', - body=expected) - self.assert_called_anytime('POST', '/snapshots/5678/action', - body=expected) - - def test_encryption_type_list(self): - """ - Test encryption-type-list shell command. - - Verify a series of GET requests are made: - - one to get the volume type list information - - one per volume type to retrieve the encryption type information - """ - self.run_command('encryption-type-list') - self.assert_called_anytime('GET', '/types') - self.assert_called_anytime('GET', '/types/1/encryption') - self.assert_called_anytime('GET', '/types/2/encryption') - - def test_encryption_type_show(self): - """ - Test encryption-type-show shell command. - - Verify two GET requests are made per command invocation: - - one to get the volume type information - - one to get the encryption type information - """ - self.run_command('encryption-type-show 1') - self.assert_called('GET', '/types/1/encryption') - self.assert_called_anytime('GET', '/types/1') - - def test_encryption_type_create(self): - """ - Test encryption-type-create shell command. - - Verify GET and POST requests are made per command invocation: - - one GET request to retrieve the relevant volume type information - - one POST request to create the new encryption type - """ - - expected = {'encryption': {'cipher': None, 'key_size': None, - 'provider': 'TestProvider', - 'control_location': 'front-end'}} - self.run_command('encryption-type-create 2 TestProvider') - self.assert_called('POST', '/types/2/encryption', body=expected) - self.assert_called_anytime('GET', '/types/2') - - def test_encryption_type_update(self): - """ - Test encryption-type-update shell command. - - Verify two GETs/one PUT requests are made per command invocation: - - one GET request to retrieve the relevant volume type information - - one GET request to retrieve the relevant encryption type information - - one PUT request to update the encryption type information - """ - self.skipTest("Not implemented") - - def test_encryption_type_delete(self): - """ - Test encryption-type-delete shell command. - - Verify one GET/one DELETE requests are made per command invocation: - - one GET request to retrieve the relevant volume type information - - one DELETE request to delete the encryption type information - """ - self.run_command('encryption-type-delete 1') - self.assert_called('DELETE', '/types/1/encryption/provider') - self.assert_called_anytime('GET', '/types/1') - - def test_migrate_volume(self): - self.run_command('migrate 1234 fakehost --force-host-copy=True') - expected = {'os-migrate_volume': {'force_host_copy': 'True', - 'host': 'fakehost'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_snapshot_metadata_set(self): - self.run_command('snapshot-metadata 1234 set key1=val1 key2=val2') - self.assert_called('POST', '/snapshots/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_snapshot_metadata_unset_dict(self): - self.run_command('snapshot-metadata 1234 unset key1=val1 key2=val2') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key1') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key2') - - def test_snapshot_metadata_unset_keys(self): - self.run_command('snapshot-metadata 1234 unset key1 key2') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key1') - self.assert_called_anytime('DELETE', '/snapshots/1234/metadata/key2') - - def test_volume_metadata_update_all(self): - self.run_command('metadata-update-all 1234 key1=val1 key2=val2') - self.assert_called('PUT', '/volumes/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_snapshot_metadata_update_all(self): - self.run_command('snapshot-metadata-update-all\ - 1234 key1=val1 key2=val2') - self.assert_called('PUT', '/snapshots/1234/metadata', - {'metadata': {'key1': 'val1', 'key2': 'val2'}}) - - def test_readonly_mode_update(self): - self.run_command('readonly-mode-update 1234 True') - expected = {'os-update_readonly_flag': {'readonly': True}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - self.run_command('readonly-mode-update 1234 False') - expected = {'os-update_readonly_flag': {'readonly': False}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_service_disable(self): - self.run_command('service-disable host cinder-volume') - self.assert_called('PUT', '/os-services/disable', - {"binary": "cinder-volume", "host": "host"}) - - def test_services_disable_with_reason(self): - cmd = 'service-disable host cinder-volume --reason no_reason' - self.run_command(cmd) - body = {'host': 'host', 'binary': 'cinder-volume', - 'disabled_reason': 'no_reason'} - self.assert_called('PUT', '/os-services/disable-log-reason', body) - - def test_service_enable(self): - self.run_command('service-enable host cinder-volume') - self.assert_called('PUT', '/os-services/enable', - {"binary": "cinder-volume", "host": "host"}) - - def test_retype_with_policy(self): - self.run_command('retype 1234 foo --migration-policy=on-demand') - expected = {'os-retype': {'new_type': 'foo', - 'migration_policy': 'on-demand'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_retype_default_policy(self): - self.run_command('retype 1234 foo') - expected = {'os-retype': {'new_type': 'foo', - 'migration_policy': 'never'}} - self.assert_called('POST', '/volumes/1234/action', body=expected) - - def test_snapshot_delete(self): - self.run_command('snapshot-delete 1234') - self.assert_called('DELETE', '/snapshots/1234') - - def test_quota_delete(self): - self.run_command('quota-delete 1234') - self.assert_called('DELETE', '/os-quota-sets/1234') - - def test_snapshot_delete_multiple(self): - self.run_command('snapshot-delete 5678') - self.assert_called('DELETE', '/snapshots/5678') - - def test_volume_manage(self): - self.run_command('manage host1 key1=val1 key2=val2 ' - '--name foo --description bar ' - '--volume-type baz --availability-zone az ' - '--metadata k1=v1 k2=v2') - expected = {'volume': {'host': 'host1', - 'ref': {'key1': 'val1', 'key2': 'val2'}, - 'name': 'foo', - 'description': 'bar', - 'volume_type': 'baz', - 'availability_zone': 'az', - 'metadata': {'k1': 'v1', 'k2': 'v2'}, - 'bootable': False}} - self.assert_called_anytime('POST', '/os-volume-manage', body=expected) - - def test_volume_manage_bootable(self): - """ - Tests the --bootable option - - If this flag is specified, then the resulting POST should contain - bootable: True. - """ - self.run_command('manage host1 key1=val1 key2=val2 ' - '--name foo --description bar --bootable ' - '--volume-type baz --availability-zone az ' - '--metadata k1=v1 k2=v2') - expected = {'volume': {'host': 'host1', - 'ref': {'key1': 'val1', 'key2': 'val2'}, - 'name': 'foo', - 'description': 'bar', - 'volume_type': 'baz', - 'availability_zone': 'az', - 'metadata': {'k1': 'v1', 'k2': 'v2'}, - 'bootable': True}} - self.assert_called_anytime('POST', '/os-volume-manage', body=expected) - - def test_volume_manage_source_name(self): - """ - Tests the --source-name option. - - Checks that the --source-name option correctly updates the - ref structure that is passed in the HTTP POST - """ - self.run_command('manage host1 key1=val1 key2=val2 ' - '--source-name VolName ' - '--name foo --description bar ' - '--volume-type baz --availability-zone az ' - '--metadata k1=v1 k2=v2') - expected = {'volume': {'host': 'host1', - 'ref': {'source-name': 'VolName', - 'key1': 'val1', 'key2': 'val2'}, - 'name': 'foo', - 'description': 'bar', - 'volume_type': 'baz', - 'availability_zone': 'az', - 'metadata': {'k1': 'v1', 'k2': 'v2'}, - 'bootable': False}} - self.assert_called_anytime('POST', '/os-volume-manage', body=expected) - - def test_volume_manage_source_id(self): - """ - Tests the --source-id option. - - Checks that the --source-id option correctly updates the - ref structure that is passed in the HTTP POST - """ - self.run_command('manage host1 key1=val1 key2=val2 ' - '--source-id 1234 ' - '--name foo --description bar ' - '--volume-type baz --availability-zone az ' - '--metadata k1=v1 k2=v2') - expected = {'volume': {'host': 'host1', - 'ref': {'source-id': '1234', - 'key1': 'val1', 'key2': 'val2'}, - 'name': 'foo', - 'description': 'bar', - 'volume_type': 'baz', - 'availability_zone': 'az', - 'metadata': {'k1': 'v1', 'k2': 'v2'}, - 'bootable': False}} - self.assert_called_anytime('POST', '/os-volume-manage', body=expected) - - def test_volume_unmanage(self): - self.run_command('unmanage 1234') - self.assert_called('POST', '/volumes/1234/action', - body={'os-unmanage': None}) - - def test_replication_promote(self): - self.run_command('replication-promote 1234') - self.assert_called('POST', '/volumes/1234/action', - body={'os-promote-replica': None}) - - def test_replication_reenable(self): - self.run_command('replication-reenable 1234') - self.assert_called('POST', '/volumes/1234/action', - body={'os-reenable-replica': None}) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_snapshot_actions.py b/awx/lib/site-packages/cinderclient/tests/v2/test_snapshot_actions.py deleted file mode 100644 index f220541e03..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_snapshot_actions.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.fixture_data import client -from cinderclient.tests.fixture_data import snapshots - - -class SnapshotActionsTest(utils.FixturedTestCase): - - client_fixture_class = client.V2 - data_fixture_class = snapshots.Fixture - - def test_update_snapshot_status(self): - s = self.cs.volume_snapshots.get('1234') - stat = {'status': 'available'} - self.cs.volume_snapshots.update_snapshot_status(s, stat) - self.assert_called('POST', '/snapshots/1234/action') - - def test_update_snapshot_status_with_progress(self): - s = self.cs.volume_snapshots.get('1234') - stat = {'status': 'available', 'progress': '73%'} - self.cs.volume_snapshots.update_snapshot_status(s, stat) - self.assert_called('POST', '/snapshots/1234/action') diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_types.py b/awx/lib/site-packages/cinderclient/tests/v2/test_types.py deleted file mode 100644 index 2cfcce7295..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_types.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.v2 import volume_types -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - -cs = fakes.FakeClient() - - -class TypesTest(utils.TestCase): - def test_list_types(self): - tl = cs.volume_types.list() - cs.assert_called('GET', '/types') - for t in tl: - self.assertIsInstance(t, volume_types.VolumeType) - - def test_create(self): - t = cs.volume_types.create('test-type-3') - cs.assert_called('POST', '/types') - self.assertIsInstance(t, volume_types.VolumeType) - - def test_set_key(self): - t = cs.volume_types.get(1) - t.set_keys({'k': 'v'}) - cs.assert_called('POST', - '/types/1/extra_specs', - {'extra_specs': {'k': 'v'}}) - - def test_unsset_keys(self): - t = cs.volume_types.get(1) - t.unset_keys(['k']) - cs.assert_called('DELETE', '/types/1/extra_specs/k') - - def test_delete(self): - cs.volume_types.delete(1) - cs.assert_called('DELETE', '/types/1') diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_volume_backups.py b/awx/lib/site-packages/cinderclient/tests/v2/test_volume_backups.py deleted file mode 100644 index 916938de1e..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_volume_backups.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - - -cs = fakes.FakeClient() - - -class VolumeBackupsTest(utils.TestCase): - - def test_create(self): - cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4') - cs.assert_called('POST', '/backups') - - def test_get(self): - backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' - cs.backups.get(backup_id) - cs.assert_called('GET', '/backups/%s' % backup_id) - - def test_list(self): - cs.backups.list() - cs.assert_called('GET', '/backups/detail') - - def test_delete(self): - b = cs.backups.list()[0] - b.delete() - cs.assert_called('DELETE', - '/backups/76a17945-3c6f-435c-975b-b5685db10b62') - cs.backups.delete('76a17945-3c6f-435c-975b-b5685db10b62') - cs.assert_called('DELETE', - '/backups/76a17945-3c6f-435c-975b-b5685db10b62') - cs.backups.delete(b) - cs.assert_called('DELETE', - '/backups/76a17945-3c6f-435c-975b-b5685db10b62') - - def test_restore(self): - backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' - cs.restores.restore(backup_id) - cs.assert_called('POST', '/backups/%s/restore' % backup_id) - - def test_record_export(self): - backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' - cs.backups.export_record(backup_id) - cs.assert_called('GET', - '/backups/%s/export_record' % backup_id) - - def test_record_import(self): - backup_service = 'fake-backup-service' - backup_url = 'fake-backup-url' - expected_body = {'backup-record': {'backup_service': backup_service, - 'backup_url': backup_url}} - cs.backups.import_record(backup_service, backup_url) - cs.assert_called('POST', '/backups/import_record', expected_body) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_volume_encryption_types.py b/awx/lib/site-packages/cinderclient/tests/v2/test_volume_encryption_types.py deleted file mode 100644 index bba6503193..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_volume_encryption_types.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (c) 2013 The Johns Hopkins University/Applied Physics Laboratory -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.v2.volume_encryption_types import VolumeEncryptionType -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - -cs = fakes.FakeClient() - - -class VolumeEncryptionTypesTest(utils.TestCase): - """ - Test suite for the Volume Encryption Types Resource and Manager. - """ - - def test_list(self): - """ - Unit test for VolumeEncryptionTypesManager.list - - Verify that a series of GET requests are made: - - one GET request for the list of volume types - - one GET request per volume type for encryption type information - - Verify that all returned information is :class: VolumeEncryptionType - """ - encryption_types = cs.volume_encryption_types.list() - cs.assert_called_anytime('GET', '/types') - cs.assert_called_anytime('GET', '/types/2/encryption') - cs.assert_called_anytime('GET', '/types/1/encryption') - for encryption_type in encryption_types: - self.assertIsInstance(encryption_type, VolumeEncryptionType) - - def test_get(self): - """ - Unit test for VolumeEncryptionTypesManager.get - - Verify that one GET request is made for the volume type encryption - type information. Verify that returned information is :class: - VolumeEncryptionType - """ - encryption_type = cs.volume_encryption_types.get(1) - cs.assert_called('GET', '/types/1/encryption') - self.assertIsInstance(encryption_type, VolumeEncryptionType) - - def test_get_no_encryption(self): - """ - Unit test for VolumeEncryptionTypesManager.get - - Verify that a request on a volume type with no associated encryption - type information returns a VolumeEncryptionType with no attributes. - """ - encryption_type = cs.volume_encryption_types.get(2) - self.assertIsInstance(encryption_type, VolumeEncryptionType) - self.assertFalse(hasattr(encryption_type, 'id'), - 'encryption type has an id') - - def test_create(self): - """ - Unit test for VolumeEncryptionTypesManager.create - - Verify that one POST request is made for the encryption type creation. - Verify that encryption type creation returns a VolumeEncryptionType. - """ - result = cs.volume_encryption_types.create(2, {'provider': 'Test', - 'key_size': None, - 'cipher': None, - 'control_location': - None}) - cs.assert_called('POST', '/types/2/encryption') - self.assertIsInstance(result, VolumeEncryptionType) - - def test_update(self): - """ - Unit test for VolumeEncryptionTypesManager.update - """ - self.skipTest("Not implemented") - - def test_delete(self): - """ - Unit test for VolumeEncryptionTypesManager.delete - - Verify that one DELETE request is made for encryption type deletion - Verify that encryption type deletion returns None - """ - result = cs.volume_encryption_types.delete(1) - cs.assert_called('DELETE', '/types/1/encryption/provider') - self.assertIsNone(result, "delete result must be None") diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_volume_transfers.py b/awx/lib/site-packages/cinderclient/tests/v2/test_volume_transfers.py deleted file mode 100644 index 47656d7940..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_volume_transfers.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v1 import fakes - - -cs = fakes.FakeClient() - - -class VolumeTransfersTest(utils.TestCase): - - def test_create(self): - cs.transfers.create('1234') - cs.assert_called('POST', '/os-volume-transfer') - - def test_get(self): - transfer_id = '5678' - cs.transfers.get(transfer_id) - cs.assert_called('GET', '/os-volume-transfer/%s' % transfer_id) - - def test_list(self): - cs.transfers.list() - cs.assert_called('GET', '/os-volume-transfer/detail') - - def test_delete(self): - b = cs.transfers.list()[0] - b.delete() - cs.assert_called('DELETE', '/os-volume-transfer/5678') - cs.transfers.delete('5678') - cs.assert_called('DELETE', '/os-volume-transfer/5678') - cs.transfers.delete(b) - cs.assert_called('DELETE', '/os-volume-transfer/5678') - - def test_accept(self): - transfer_id = '5678' - auth_key = '12345' - cs.transfers.accept(transfer_id, auth_key) - cs.assert_called('POST', '/os-volume-transfer/%s/accept' % transfer_id) diff --git a/awx/lib/site-packages/cinderclient/tests/v2/test_volumes.py b/awx/lib/site-packages/cinderclient/tests/v2/test_volumes.py deleted file mode 100644 index 165742d4e9..0000000000 --- a/awx/lib/site-packages/cinderclient/tests/v2/test_volumes.py +++ /dev/null @@ -1,178 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.tests import utils -from cinderclient.tests.v2 import fakes - - -cs = fakes.FakeClient() - - -class VolumesTest(utils.TestCase): - - def test_list_volumes_with_marker_limit(self): - cs.volumes.list(marker=1234, limit=2) - cs.assert_called('GET', '/volumes/detail?limit=2&marker=1234') - - def test_list_volumes_with_sort_key_dir(self): - cs.volumes.list(sort_key='id', sort_dir='asc') - cs.assert_called('GET', '/volumes/detail?sort_dir=asc&sort_key=id') - - def test_list_volumes_with_invalid_sort_key(self): - self.assertRaises(ValueError, - cs.volumes.list, sort_key='invalid', sort_dir='asc') - - def test_list_volumes_with_invalid_sort_dir(self): - self.assertRaises(ValueError, - cs.volumes.list, sort_key='id', sort_dir='invalid') - - def test_delete_volume(self): - v = cs.volumes.list()[0] - v.delete() - cs.assert_called('DELETE', '/volumes/1234') - cs.volumes.delete('1234') - cs.assert_called('DELETE', '/volumes/1234') - cs.volumes.delete(v) - cs.assert_called('DELETE', '/volumes/1234') - - def test_create_volume(self): - cs.volumes.create(1) - cs.assert_called('POST', '/volumes') - - def test_create_volume_with_hint(self): - cs.volumes.create(1, scheduler_hints='uuid') - expected = {'volume': {'status': 'creating', - 'description': None, - 'availability_zone': None, - 'source_volid': None, - 'snapshot_id': None, - 'size': 1, - 'user_id': None, - 'name': None, - 'imageRef': None, - 'attach_status': 'detached', - 'volume_type': None, - 'project_id': None, - 'metadata': {}, - 'source_replica': None, - 'consistencygroup_id': None}, - 'OS-SCH-HNT:scheduler_hints': 'uuid'} - cs.assert_called('POST', '/volumes', body=expected) - - def test_attach(self): - v = cs.volumes.get('1234') - cs.volumes.attach(v, 1, '/dev/vdc', mode='ro') - cs.assert_called('POST', '/volumes/1234/action') - - def test_detach(self): - v = cs.volumes.get('1234') - cs.volumes.detach(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_reserve(self): - v = cs.volumes.get('1234') - cs.volumes.reserve(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_unreserve(self): - v = cs.volumes.get('1234') - cs.volumes.unreserve(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_begin_detaching(self): - v = cs.volumes.get('1234') - cs.volumes.begin_detaching(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_roll_detaching(self): - v = cs.volumes.get('1234') - cs.volumes.roll_detaching(v) - cs.assert_called('POST', '/volumes/1234/action') - - def test_initialize_connection(self): - v = cs.volumes.get('1234') - cs.volumes.initialize_connection(v, {}) - cs.assert_called('POST', '/volumes/1234/action') - - def test_terminate_connection(self): - v = cs.volumes.get('1234') - cs.volumes.terminate_connection(v, {}) - cs.assert_called('POST', '/volumes/1234/action') - - def test_set_metadata(self): - cs.volumes.set_metadata(1234, {'k1': 'v2'}) - cs.assert_called('POST', '/volumes/1234/metadata', - {'metadata': {'k1': 'v2'}}) - - def test_delete_metadata(self): - keys = ['key1'] - cs.volumes.delete_metadata(1234, keys) - cs.assert_called('DELETE', '/volumes/1234/metadata/key1') - - def test_extend(self): - v = cs.volumes.get('1234') - cs.volumes.extend(v, 2) - cs.assert_called('POST', '/volumes/1234/action') - - def test_get_encryption_metadata(self): - cs.volumes.get_encryption_metadata('1234') - cs.assert_called('GET', '/volumes/1234/encryption') - - def test_migrate(self): - v = cs.volumes.get('1234') - cs.volumes.migrate_volume(v, 'dest', False) - cs.assert_called('POST', '/volumes/1234/action') - - def test_metadata_update_all(self): - cs.volumes.update_all_metadata(1234, {'k1': 'v1'}) - cs.assert_called('PUT', '/volumes/1234/metadata', - {'metadata': {'k1': 'v1'}}) - - def test_readonly_mode_update(self): - v = cs.volumes.get('1234') - cs.volumes.update_readonly_flag(v, True) - cs.assert_called('POST', '/volumes/1234/action') - - def test_retype(self): - v = cs.volumes.get('1234') - cs.volumes.retype(v, 'foo', 'on-demand') - cs.assert_called('POST', '/volumes/1234/action', - {'os-retype': {'new_type': 'foo', - 'migration_policy': 'on-demand'}}) - - def test_set_bootable(self): - v = cs.volumes.get('1234') - cs.volumes.set_bootable(v, True) - cs.assert_called('POST', '/volumes/1234/action') - - def test_volume_manage(self): - cs.volumes.manage('host1', {'k': 'v'}) - expected = {'host': 'host1', 'name': None, 'availability_zone': None, - 'description': None, 'metadata': None, 'ref': {'k': 'v'}, - 'volume_type': None, 'bootable': False} - cs.assert_called('POST', '/os-volume-manage', {'volume': expected}) - - def test_volume_manage_bootable(self): - cs.volumes.manage('host1', {'k': 'v'}, bootable=True) - expected = {'host': 'host1', 'name': None, 'availability_zone': None, - 'description': None, 'metadata': None, 'ref': {'k': 'v'}, - 'volume_type': None, 'bootable': True} - cs.assert_called('POST', '/os-volume-manage', {'volume': expected}) - - def test_volume_unmanage(self): - v = cs.volumes.get('1234') - cs.volumes.unmanage(v) - cs.assert_called('POST', '/volumes/1234/action', {'os-unmanage': None}) diff --git a/awx/lib/site-packages/cinderclient/utils.py b/awx/lib/site-packages/cinderclient/utils.py deleted file mode 100644 index 018f12acdd..0000000000 --- a/awx/lib/site-packages/cinderclient/utils.py +++ /dev/null @@ -1,317 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import os -import pkg_resources -import re -import sys -import uuid - -import six -import prettytable - -from cinderclient import exceptions -from cinderclient.openstack.common import strutils - - -def arg(*args, **kwargs): - """Decorator for CLI args.""" - def _decorator(func): - add_arg(func, *args, **kwargs) - return func - return _decorator - - -def env(*vars, **kwargs): - """ - returns the first environment variable set - if none are non-empty, defaults to '' or keyword arg default - """ - for v in vars: - value = os.environ.get(v, None) - if value: - return value - return kwargs.get('default', '') - - -def add_arg(f, *args, **kwargs): - """Bind CLI arguments to a shell.py `do_foo` function.""" - - if not hasattr(f, 'arguments'): - f.arguments = [] - - # NOTE(sirp): avoid dups that can occur when the module is shared across - # tests. - if (args, kwargs) not in f.arguments: - # Because of the semantics of decorator composition if we just append - # to the options list positional options will appear to be backwards. - f.arguments.insert(0, (args, kwargs)) - - -def add_resource_manager_extra_kwargs_hook(f, hook): - """Adds hook to bind CLI arguments to ResourceManager calls. - - The `do_foo` calls in shell.py will receive CLI args and then in turn pass - them through to the ResourceManager. Before passing through the args, the - hooks registered here will be called, giving us a chance to add extra - kwargs (taken from the command-line) to what's passed to the - ResourceManager. - """ - if not hasattr(f, 'resource_manager_kwargs_hooks'): - f.resource_manager_kwargs_hooks = [] - - names = [h.__name__ for h in f.resource_manager_kwargs_hooks] - if hook.__name__ not in names: - f.resource_manager_kwargs_hooks.append(hook) - - -def get_resource_manager_extra_kwargs(f, args, allow_conflicts=False): - """Return extra_kwargs by calling resource manager kwargs hooks.""" - hooks = getattr(f, "resource_manager_kwargs_hooks", []) - extra_kwargs = {} - for hook in hooks: - hook_name = hook.__name__ - hook_kwargs = hook(args) - - conflicting_keys = set(hook_kwargs.keys()) & set(extra_kwargs.keys()) - if conflicting_keys and not allow_conflicts: - msg = ("Hook '%(hook_name)s' is attempting to redefine attributes " - "'%(conflicting_keys)s'" % { - 'hook_name': hook_name, - 'conflicting_keys': conflicting_keys - }) - raise Exception(msg) - - extra_kwargs.update(hook_kwargs) - - return extra_kwargs - - -def unauthenticated(f): - """ - Adds 'unauthenticated' attribute to decorated function. - Usage: - @unauthenticated - def mymethod(f): - ... - """ - f.unauthenticated = True - return f - - -def isunauthenticated(f): - """ - Checks to see if the function is marked as not requiring authentication - with the @unauthenticated decorator. Returns True if decorator is - set to True, False otherwise. - """ - return getattr(f, 'unauthenticated', False) - - -def service_type(stype): - """ - Adds 'service_type' attribute to decorated function. - Usage: - @service_type('volume') - def mymethod(f): - ... - """ - def inner(f): - f.service_type = stype - return f - return inner - - -def get_service_type(f): - """ - Retrieves service type from function - """ - return getattr(f, 'service_type', None) - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def _print(pt, order): - if sys.version_info >= (3, 0): - print(pt.get_string(sortby=order)) - else: - print(strutils.safe_encode(pt.get_string(sortby=order))) - - -def print_list(objs, fields, formatters={}, order_by=None): - mixed_case_fields = ['serverId'] - pt = prettytable.PrettyTable([f for f in fields], caching=False) - pt.aligns = ['l' for f in fields] - - for o in objs: - row = [] - for field in fields: - if field in formatters: - row.append(formatters[field](o)) - else: - if field in mixed_case_fields: - field_name = field.replace(' ', '_') - else: - field_name = field.lower().replace(' ', '_') - if type(o) == dict and field in o: - data = o[field] - else: - data = getattr(o, field_name, '') - row.append(data) - pt.add_row(row) - - if order_by is None: - order_by = fields[0] - _print(pt, order_by) - - -def print_dict(d, property="Property"): - pt = prettytable.PrettyTable([property, 'Value'], caching=False) - pt.aligns = ['l', 'l'] - [pt.add_row(list(r)) for r in six.iteritems(d)] - _print(pt, property) - - -def find_resource(manager, name_or_id): - """Helper for the _find_* methods.""" - # first try to get entity as integer id - try: - if isinstance(name_or_id, int) or name_or_id.isdigit(): - return manager.get(int(name_or_id)) - except exceptions.NotFound: - pass - - if sys.version_info <= (3, 0): - name_or_id = strutils.safe_decode(name_or_id) - - # now try to get entity as uuid - try: - uuid.UUID(name_or_id) - return manager.get(name_or_id) - except (ValueError, exceptions.NotFound): - pass - - try: - try: - return manager.find(human_id=name_or_id) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - return manager.find(name=name_or_id) - except exceptions.NotFound: - try: - return manager.find(display_name=name_or_id) - except (UnicodeDecodeError, exceptions.NotFound): - try: - # Volumes does not have name, but display_name - return manager.find(display_name=name_or_id) - except exceptions.NotFound: - msg = "No %s with a name or ID of '%s' exists." % \ - (manager.resource_class.__name__.lower(), name_or_id) - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = ("Multiple %s matches found for '%s', use an ID to be more" - " specific." % (manager.resource_class.__name__.lower(), - name_or_id)) - raise exceptions.CommandError(msg) - - -def find_volume(cs, volume): - """Get a volume by name or ID.""" - return find_resource(cs.volumes, volume) - - -def _format_servers_list_networks(server): - output = [] - for (network, addresses) in list(server.networks.items()): - if len(addresses) == 0: - continue - addresses_csv = ', '.join(addresses) - group = "%s=%s" % (network, addresses_csv) - output.append(group) - - return '; '.join(output) - - -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - -def safe_issubclass(*args): - """Like issubclass, but will just return False if not a class.""" - - try: - if issubclass(*args): - return True - except TypeError: - pass - - return False - - -def import_class(import_str): - """Returns a class from a string including module and class.""" - mod_str, _sep, class_str = import_str.rpartition('.') - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - - -def _load_entry_point(ep_name, name=None): - """Try to load the entry point ep_name that matches name.""" - for ep in pkg_resources.iter_entry_points(ep_name, name=name): - try: - return ep.load() - except (ImportError, pkg_resources.UnknownExtra, AttributeError): - continue - -_slugify_strip_re = re.compile(r'[^\w\s-]') -_slugify_hyphenate_re = re.compile(r'[-\s]+') - - -# http://code.activestate.com/recipes/ -# 577257-slugify-make-a-string-usable-in-a-url-or-filename/ -def slugify(value): - """ - Normalizes string, converts to lowercase, removes non-alpha characters, - and converts spaces to hyphens. - - From Django's "django/template/defaultfilters.py". - """ - import unicodedata - if not isinstance(value, six.text_type): - value = six.text_type(value) - value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') - value = six.text_type(_slugify_strip_re.sub('', value).strip().lower()) - return _slugify_hyphenate_re.sub('-', value) diff --git a/awx/lib/site-packages/cinderclient/v1/__init__.py b/awx/lib/site-packages/cinderclient/v1/__init__.py deleted file mode 100644 index 3637ffdda9..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.v1.client import Client # noqa diff --git a/awx/lib/site-packages/cinderclient/v1/availability_zones.py b/awx/lib/site-packages/cinderclient/v1/availability_zones.py deleted file mode 100644 index b85d6dd3cf..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/availability_zones.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2011-2013 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Availability Zone interface (v1 extension)""" - -from cinderclient import base - - -class AvailabilityZone(base.Resource): - NAME_ATTR = 'display_name' - - def __repr__(self): - return "<AvailabilityZone: %s>" % self.zoneName - - -class AvailabilityZoneManager(base.ManagerWithFind): - """Manage :class:`AvailabilityZone` resources.""" - resource_class = AvailabilityZone - - def list(self, detailed=False): - """Lists all availability zones. - - :rtype: list of :class:`AvailabilityZone` - """ - if detailed is True: - return self._list("/os-availability-zone/detail", - "availabilityZoneInfo") - else: - return self._list("/os-availability-zone", "availabilityZoneInfo") diff --git a/awx/lib/site-packages/cinderclient/v1/client.py b/awx/lib/site-packages/cinderclient/v1/client.py deleted file mode 100644 index c11a954635..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/client.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import client -from cinderclient.v1 import availability_zones -from cinderclient.v1 import limits -from cinderclient.v1 import qos_specs -from cinderclient.v1 import quota_classes -from cinderclient.v1 import quotas -from cinderclient.v1 import services -from cinderclient.v1 import volumes -from cinderclient.v1 import volume_snapshots -from cinderclient.v1 import volume_types -from cinderclient.v1 import volume_encryption_types -from cinderclient.v1 import volume_backups -from cinderclient.v1 import volume_backups_restore -from cinderclient.v1 import volume_transfers - - -class Client(object): - """ - Top-level object to access the OpenStack Volume API. - - Create an instance with your creds:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) - - Then call methods on its managers:: - - >>> client.volumes.list() - ... - - """ - - def __init__(self, username=None, api_key=None, project_id=None, - auth_url='', insecure=False, timeout=None, tenant_id=None, - proxy_tenant_id=None, proxy_token=None, region_name=None, - endpoint_type='publicURL', extensions=None, - service_type='volume', service_name=None, - volume_service_name=None, retries=None, http_log_debug=False, - cacert=None, auth_system='keystone', auth_plugin=None, - session=None, **kwargs): - # FIXME(comstud): Rename the api_key argument above when we - # know it's not being used as keyword argument - password = api_key - self.limits = limits.LimitsManager(self) - - # extensions - self.volumes = volumes.VolumeManager(self) - self.volume_snapshots = volume_snapshots.SnapshotManager(self) - self.volume_types = volume_types.VolumeTypeManager(self) - self.volume_encryption_types = \ - volume_encryption_types.VolumeEncryptionTypeManager(self) - self.qos_specs = qos_specs.QoSSpecsManager(self) - self.quota_classes = quota_classes.QuotaClassSetManager(self) - self.quotas = quotas.QuotaSetManager(self) - self.backups = volume_backups.VolumeBackupManager(self) - self.restores = volume_backups_restore.VolumeBackupRestoreManager(self) - self.transfers = volume_transfers.VolumeTransferManager(self) - self.services = services.ServiceManager(self) - self.availability_zones = \ - availability_zones.AvailabilityZoneManager(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - self.client = client._construct_http_client( - username=username, - password=password, - project_id=project_id, - auth_url=auth_url, - insecure=insecure, - timeout=timeout, - tenant_id=tenant_id, - proxy_tenant_id=tenant_id, - proxy_token=proxy_token, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - retries=retries, - http_log_debug=http_log_debug, - cacert=cacert, - auth_system=auth_system, - auth_plugin=auth_plugin, - session=session, - **kwargs) - - def authenticate(self): - """ - Authenticate against the server. - - Normally this is called automatically when you first access the API, - but you can call this method to force authentication right now. - - Returns on success; raises :exc:`exceptions.Unauthorized` if the - credentials are wrong. - """ - self.client.authenticate() - - def get_volume_api_version_from_endpoint(self): - return self.client.get_volume_api_version_from_endpoint() diff --git a/awx/lib/site-packages/cinderclient/v1/contrib/__init__.py b/awx/lib/site-packages/cinderclient/v1/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/v1/contrib/list_extensions.py b/awx/lib/site-packages/cinderclient/v1/contrib/list_extensions.py deleted file mode 100644 index 308d39683d..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/contrib/list_extensions.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import base -from cinderclient import utils - - -class ListExtResource(base.Resource): - @property - def summary(self): - descr = self.description.strip() - if not descr: - return '??' - lines = descr.split("\n") - if len(lines) == 1: - return lines[0] - else: - return lines[0] + "..." - - -class ListExtManager(base.Manager): - resource_class = ListExtResource - - def show_all(self): - return self._list("/extensions", 'extensions') - - -@utils.service_type('volume') -def do_list_extensions(client, _args): - """ - Lists all available os-api extensions. - """ - extensions = client.list_extensions.show_all() - fields = ["Name", "Summary", "Alias", "Updated"] - utils.print_list(extensions, fields) diff --git a/awx/lib/site-packages/cinderclient/v1/limits.py b/awx/lib/site-packages/cinderclient/v1/limits.py deleted file mode 100644 index 1ae2815240..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/limits.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from cinderclient import base - - -class Limits(base.Resource): - """A collection of RateLimit and AbsoluteLimit objects.""" - - def __repr__(self): - return "<Limits>" - - @property - def absolute(self): - for (name, value) in list(self._info['absolute'].items()): - yield AbsoluteLimit(name, value) - - @property - def rate(self): - for group in self._info['rate']: - uri = group['uri'] - regex = group['regex'] - for rate in group['limit']: - yield RateLimit(rate['verb'], uri, regex, rate['value'], - rate['remaining'], rate['unit'], - rate['next-available']) - - -class RateLimit(object): - """Data model that represents a flattened view of a single rate limit.""" - - def __init__(self, verb, uri, regex, value, remain, - unit, next_available): - self.verb = verb - self.uri = uri - self.regex = regex - self.value = value - self.remain = remain - self.unit = unit - self.next_available = next_available - - def __eq__(self, other): - return self.uri == other.uri \ - and self.regex == other.regex \ - and self.value == other.value \ - and self.verb == other.verb \ - and self.remain == other.remain \ - and self.unit == other.unit \ - and self.next_available == other.next_available - - def __repr__(self): - return "<RateLimit: method=%s uri=%s>" % (self.verb, self.uri) - - -class AbsoluteLimit(object): - """Data model that represents a single absolute limit.""" - - def __init__(self, name, value): - self.name = name - self.value = value - - def __eq__(self, other): - return self.value == other.value and self.name == other.name - - def __repr__(self): - return "<AbsoluteLimit: name=%s>" % (self.name) - - -class LimitsManager(base.Manager): - """Manager object used to interact with limits resource.""" - - resource_class = Limits - - def get(self): - """ - Get a specific extension. - - :rtype: :class:`Limits` - """ - return self._get("/limits", "limits") diff --git a/awx/lib/site-packages/cinderclient/v1/qos_specs.py b/awx/lib/site-packages/cinderclient/v1/qos_specs.py deleted file mode 100644 index b4e4272ae2..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/qos_specs.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (c) 2013 eBay Inc. -# Copyright (c) OpenStack LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -""" -QoS Specs interface. -""" - -from cinderclient import base - - -class QoSSpecs(base.Resource): - """QoS specs entity represents quality-of-service parameters/requirements. - - A QoS specs is a set of parameters or requirements for quality-of-service - purpose, which can be associated with volume types (for now). In future, - QoS specs may be extended to be associated other entities, such as single - volume. - """ - def __repr__(self): - return "<QoSSpecs: %s>" % self.name - - def delete(self): - return self.manager.delete(self) - - -class QoSSpecsManager(base.ManagerWithFind): - """ - Manage :class:`QoSSpecs` resources. - """ - resource_class = QoSSpecs - - def list(self): - """Get a list of all qos specs. - - :rtype: list of :class:`QoSSpecs`. - """ - return self._list("/qos-specs", "qos_specs") - - def get(self, qos_specs): - """Get a specific qos specs. - - :param qos_specs: The ID of the :class:`QoSSpecs` to get. - :rtype: :class:`QoSSpecs` - """ - return self._get("/qos-specs/%s" % base.getid(qos_specs), "qos_specs") - - def delete(self, qos_specs, force=False): - """Delete a specific qos specs. - - :param qos_specs: The ID of the :class:`QoSSpecs` to be removed. - :param force: Flag that indicates whether to delete target qos specs - if it was in-use. - """ - self._delete("/qos-specs/%s?force=%s" % - (base.getid(qos_specs), force)) - - def create(self, name, specs): - """Create a qos specs. - - :param name: Descriptive name of the qos specs, must be unique - :param specs: A dict of key/value pairs to be set - :rtype: :class:`QoSSpecs` - """ - - body = { - "qos_specs": { - "name": name, - } - } - - body["qos_specs"].update(specs) - return self._create("/qos-specs", body, "qos_specs") - - def set_keys(self, qos_specs, specs): - """Update a qos specs with new specifications. - - :param qos_specs: The ID of qos specs - :param specs: A dict of key/value pairs to be set - :rtype: :class:`QoSSpecs` - """ - - body = { - "qos_specs": {} - } - - body["qos_specs"].update(specs) - return self._update("/qos-specs/%s" % qos_specs, body) - - def unset_keys(self, qos_specs, specs): - """Update a qos specs with new specifications. - - :param qos_specs: The ID of qos specs - :param specs: A list of key to be unset - :rtype: :class:`QoSSpecs` - """ - - body = {'keys': specs} - - return self._update("/qos-specs/%s/delete_keys" % qos_specs, - body) - - def get_associations(self, qos_specs): - """Get associated entities of a qos specs. - - :param qos_specs: The id of the :class: `QoSSpecs` - :return: a list of entities that associated with specific qos specs. - """ - return self._list("/qos-specs/%s/associations" % base.getid(qos_specs), - "qos_associations") - - def associate(self, qos_specs, vol_type_id): - """Associate a volume type with specific qos specs. - - :param qos_specs: The qos specs to be associated with - :param vol_type_id: The volume type id to be associated with - """ - self.api.client.get("/qos-specs/%s/associate?vol_type_id=%s" % - (base.getid(qos_specs), vol_type_id)) - - def disassociate(self, qos_specs, vol_type_id): - """Disassociate qos specs from volume type. - - :param qos_specs: The qos specs to be associated with - :param vol_type_id: The volume type id to be associated with - """ - self.api.client.get("/qos-specs/%s/disassociate?vol_type_id=%s" % - (base.getid(qos_specs), vol_type_id)) - - def disassociate_all(self, qos_specs): - """Disassociate all entities from specific qos specs. - - :param qos_specs: The qos specs to be associated with - """ - self.api.client.get("/qos-specs/%s/disassociate_all" % - base.getid(qos_specs)) diff --git a/awx/lib/site-packages/cinderclient/v1/quota_classes.py b/awx/lib/site-packages/cinderclient/v1/quota_classes.py deleted file mode 100644 index 9e81e2cca4..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/quota_classes.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import base - - -class QuotaClassSet(base.Resource): - - @property - def id(self): - """QuotaClassSet does not have a 'id' attribute but base.Resource - needs it to self-refresh and QuotaSet is indexed by class_name. - """ - return self.class_name - - def update(self, *args, **kwargs): - self.manager.update(self.class_name, *args, **kwargs) - - -class QuotaClassSetManager(base.Manager): - resource_class = QuotaClassSet - - def get(self, class_name): - return self._get("/os-quota-class-sets/%s" % (class_name), - "quota_class_set") - - def update(self, class_name, **updates): - body = {'quota_class_set': {'class_name': class_name}} - - for update in updates: - body['quota_class_set'][update] = updates[update] - - self._update('/os-quota-class-sets/%s' % (class_name), body) diff --git a/awx/lib/site-packages/cinderclient/v1/quotas.py b/awx/lib/site-packages/cinderclient/v1/quotas.py deleted file mode 100644 index 7453cb7fe4..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/quotas.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import base - - -class QuotaSet(base.Resource): - - @property - def id(self): - """QuotaSet does not have a 'id' attribute but base. Resource needs it - to self-refresh and QuotaSet is indexed by tenant_id. - """ - return self.tenant_id - - def update(self, *args, **kwargs): - return self.manager.update(self.tenant_id, *args, **kwargs) - - -class QuotaSetManager(base.Manager): - resource_class = QuotaSet - - def get(self, tenant_id, usage=False): - if hasattr(tenant_id, 'tenant_id'): - tenant_id = tenant_id.tenant_id - return self._get("/os-quota-sets/%s?usage=%s" % (tenant_id, usage), - "quota_set") - - def update(self, tenant_id, **updates): - body = {'quota_set': {'tenant_id': tenant_id}} - - for update in updates: - body['quota_set'][update] = updates[update] - - result = self._update('/os-quota-sets/%s' % (tenant_id), body) - return self.resource_class(self, result['quota_set'], loaded=True) - - def defaults(self, tenant_id): - return self._get('/os-quota-sets/%s/defaults' % tenant_id, - 'quota_set') - - def delete(self, tenant_id): - if hasattr(tenant_id, 'tenant_id'): - tenant_id = tenant_id.tenant_id - return self._delete("/os-quota-sets/%s" % tenant_id) diff --git a/awx/lib/site-packages/cinderclient/v1/services.py b/awx/lib/site-packages/cinderclient/v1/services.py deleted file mode 100644 index 3bc4b3b43e..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/services.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -service interface -""" -from cinderclient import base - - -class Service(base.Resource): - - def __repr__(self): - return "<Service: %s>" % self.service - - -class ServiceManager(base.ManagerWithFind): - resource_class = Service - - def list(self, host=None, binary=None): - """ - Describes service list for host. - - :param host: destination host name. - :param binary: service binary. - """ - url = "/os-services" - filters = [] - if host: - filters.append("host=%s" % host) - if binary: - filters.append("binary=%s" % binary) - if filters: - url = "%s?%s" % (url, "&".join(filters)) - return self._list(url, "services") - - def enable(self, host, binary): - """Enable the service specified by hostname and binary.""" - body = {"host": host, "binary": binary} - result = self._update("/os-services/enable", body) - return self.resource_class(self, result) - - def disable(self, host, binary): - """Disable the service specified by hostname and binary.""" - body = {"host": host, "binary": binary} - result = self._update("/os-services/disable", body) - return self.resource_class(self, result) - - def disable_log_reason(self, host, binary, reason): - """Disable the service with reason.""" - body = {"host": host, "binary": binary, "disabled_reason": reason} - result = self._update("/os-services/disable-log-reason", body) - return self.resource_class(self, result) diff --git a/awx/lib/site-packages/cinderclient/v1/shell.py b/awx/lib/site-packages/cinderclient/v1/shell.py deleted file mode 100644 index bdad700da5..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/shell.py +++ /dev/null @@ -1,1448 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# -# Copyright (c) 2011-2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import print_function - -import argparse -import copy -import os -import sys -import time - -from cinderclient import exceptions -from cinderclient.openstack.common import strutils -from cinderclient import utils -from cinderclient.v1 import availability_zones - - -def _poll_for_status(poll_fn, obj_id, action, final_ok_states, - poll_period=5, show_progress=True): - """Blocks while an action occurs. Periodically shows progress.""" - def print_progress(progress): - if show_progress: - msg = ('\rInstance %(action)s... %(progress)s%% complete' - % dict(action=action, progress=progress)) - else: - msg = '\rInstance %(action)s...' % dict(action=action) - - sys.stdout.write(msg) - sys.stdout.flush() - - print() - while True: - obj = poll_fn(obj_id) - status = obj.status.lower() - progress = getattr(obj, 'progress', None) or 0 - if status in final_ok_states: - print_progress(100) - print("\nFinished") - break - elif status == "error": - print("\nError %(action)s instance" % {'action': action}) - break - else: - print_progress(progress) - time.sleep(poll_period) - - -def _find_volume_snapshot(cs, snapshot): - """Gets a volume snapshot by name or ID.""" - return utils.find_resource(cs.volume_snapshots, snapshot) - - -def _find_backup(cs, backup): - """Gets a backup by name or ID.""" - return utils.find_resource(cs.backups, backup) - - -def _find_transfer(cs, transfer): - """Gets a transfer by name or ID.""" - return utils.find_resource(cs.transfers, transfer) - - -def _find_qos_specs(cs, qos_specs): - """Gets a qos specs by ID.""" - return utils.find_resource(cs.qos_specs, qos_specs) - - -def _print_volume(volume): - utils.print_dict(volume._info) - - -def _print_volume_snapshot(snapshot): - utils.print_dict(snapshot._info) - - -def _print_volume_image(image): - utils.print_dict(image[1]['os-volume_upload_image']) - - -def _translate_keys(collection, convert): - for item in collection: - keys = item.__dict__ - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _translate_volume_keys(collection): - convert = [('displayName', 'display_name'), ('volumeType', 'volume_type'), - ('os-vol-tenant-attr:tenant_id', 'tenant_id')] - _translate_keys(collection, convert) - - -def _translate_volume_snapshot_keys(collection): - convert = [('displayName', 'display_name'), ('volumeId', 'volume_id')] - _translate_keys(collection, convert) - - -def _translate_availability_zone_keys(collection): - convert = [('zoneName', 'name'), ('zoneState', 'status')] - _translate_keys(collection, convert) - - -def _extract_metadata(args): - metadata = {} - for metadatum in args.metadata: - # unset doesn't require a val, so we have the if/else - if '=' in metadatum: - (key, value) = metadatum.split('=', 1) - else: - key = metadatum - value = None - - metadata[key] = value - return metadata - - -@utils.arg( - '--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Shows details for all tenants. Admin only.') -@utils.arg( - '--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@utils.arg( - '--display-name', - metavar='<display-name>', - default=None, - help='Filters list by a volume display name. Default=None.') -@utils.arg( - '--status', - metavar='<status>', - default=None, - help='Filters list by a status. Default=None.') -@utils.arg( - '--metadata', - type=str, - nargs='*', - metavar='<key=value>', - help='Filters list by metadata key and value pair. ' - 'Default=None.', - default=None) -@utils.service_type('volume') -def do_list(cs, args): - """Lists all volumes.""" - all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants)) - search_opts = { - 'all_tenants': all_tenants, - 'display_name': args.display_name, - 'status': args.status, - 'metadata': _extract_metadata(args) if args.metadata else None, - } - volumes = cs.volumes.list(search_opts=search_opts) - _translate_volume_keys(volumes) - - # Create a list of servers to which the volume is attached - for vol in volumes: - servers = [s.get('server_id') for s in vol.attachments] - setattr(vol, 'attached_to', ','.join(map(str, servers))) - if all_tenants: - key_list = ['ID', 'Tenant ID', 'Status', 'Display Name', - 'Size', 'Volume Type', 'Bootable', 'Attached to'] - else: - key_list = ['ID', 'Status', 'Display Name', - 'Size', 'Volume Type', 'Bootable', 'Attached to'] - utils.print_list(volumes, key_list) - - -@utils.arg('volume', metavar='<volume>', help='Volume name or ID.') -@utils.service_type('volume') -def do_show(cs, args): - """Shows volume details.""" - volume = utils.find_volume(cs, args.volume) - _print_volume(volume) - - -@utils.arg('size', - metavar='<size>', - type=int, - help='Volume size, in GBs.') -@utils.arg( - '--snapshot-id', - metavar='<snapshot-id>', - default=None, - help='Creates volume from snapshot ID. ' - 'Default=None.') -@utils.arg( - '--snapshot_id', - help=argparse.SUPPRESS) -@utils.arg( - '--source-volid', - metavar='<source-volid>', - default=None, - help='Creates volume from volume ID. ' - 'Default=None.') -@utils.arg( - '--source_volid', - help=argparse.SUPPRESS) -@utils.arg( - '--image-id', - metavar='<image-id>', - default=None, - help='Creates volume from image ID. ' - 'Default=None.') -@utils.arg( - '--image_id', - help=argparse.SUPPRESS) -@utils.arg( - '--display-name', - metavar='<display-name>', - default=None, - help='Volume name. ' - 'Default=None.') -@utils.arg( - '--display_name', - help=argparse.SUPPRESS) -@utils.arg( - '--display-description', - metavar='<display-description>', - default=None, - help='Volume description. ' - 'Default=None.') -@utils.arg( - '--display_description', - help=argparse.SUPPRESS) -@utils.arg( - '--volume-type', - metavar='<volume-type>', - default=None, - help='Volume type. ' - 'Default=None.') -@utils.arg( - '--volume_type', - help=argparse.SUPPRESS) -@utils.arg( - '--availability-zone', - metavar='<availability-zone>', - default=None, - help='Availability zone for volume. ' - 'Default=None.') -@utils.arg( - '--availability_zone', - help=argparse.SUPPRESS) -@utils.arg('--metadata', - type=str, - nargs='*', - metavar='<key=value>', - help='Metadata key and value pairs. ' - 'Default=None.', - default=None) -@utils.service_type('volume') -def do_create(cs, args): - """Creates a volume.""" - - volume_metadata = None - if args.metadata is not None: - volume_metadata = _extract_metadata(args) - - volume = cs.volumes.create(args.size, - args.snapshot_id, - args.source_volid, - args.display_name, - args.display_description, - args.volume_type, - availability_zone=args.availability_zone, - imageRef=args.image_id, - metadata=volume_metadata) - _print_volume(volume) - - -@utils.arg('volume', metavar='<volume>', nargs='+', - help='Name or ID of volume to delete. ' - 'Separate multiple volumes with a space.') -@utils.service_type('volume') -def do_delete(cs, args): - """Removes one or more volumes.""" - failure_count = 0 - for volume in args.volume: - try: - utils.find_volume(cs, volume).delete() - except Exception as e: - failure_count += 1 - print("Delete for volume %s failed: %s" % (volume, e)) - if failure_count == len(args.volume): - raise exceptions.CommandError("Unable to delete any of the specified " - "volumes.") - - -@utils.arg('volume', metavar='<volume>', nargs='+', - help='Name or ID of volume to delete. ' - 'Separate multiple volumes with a space.') -@utils.service_type('volume') -def do_force_delete(cs, args): - """Attempts force-delete of volume, regardless of state.""" - failure_count = 0 - for volume in args.volume: - try: - utils.find_volume(cs, volume).force_delete() - except Exception as e: - failure_count += 1 - print("Delete for volume %s failed: %s" % (volume, e)) - if failure_count == len(args.volume): - raise exceptions.CommandError("Unable to force delete any of the " - "specified volumes.") - - -@utils.arg('volume', metavar='<volume>', nargs='+', - help='Name or ID of volume to modify. ' - 'Separate multiple volumes with a space.') -@utils.arg('--state', metavar='<state>', default='available', - help=('The state to assign to the volume. Valid values are ' - '"available," "error," "creating," "deleting," or ' - '"error_deleting." ' - 'Default is "available."')) -@utils.service_type('volume') -def do_reset_state(cs, args): - """Explicitly updates the volume state.""" - failure_flag = False - - for volume in args.volume: - try: - utils.find_volume(cs, volume).reset_state(args.state) - except Exception as e: - failure_flag = True - msg = "Reset state for volume %s failed: %s" % (volume, e) - print(msg) - - if failure_flag: - msg = "Unable to reset the state for the specified volume(s)." - raise exceptions.CommandError(msg) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume to rename.') -@utils.arg('display_name', nargs='?', metavar='<display-name>', - help='New display name for volume.') -@utils.arg('--display-description', metavar='<display-description>', - help='Volume description. Default=None.', - default=None) -@utils.service_type('volume') -def do_rename(cs, args): - """Renames a volume.""" - kwargs = {} - if args.display_name is not None: - kwargs['display_name'] = args.display_name - if args.display_description is not None: - kwargs['display_description'] = args.display_description - - if not any(kwargs): - msg = 'Must supply either display-name or display-description.' - raise exceptions.ClientException(code=1, message=msg) - - utils.find_volume(cs, args.volume).update(**kwargs) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume for which to update metadata.') -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='The metadata key and pair to set or unset. ' - 'For unset, specify only the key. ' - 'Default=[].') -@utils.service_type('volume') -def do_metadata(cs, args): - """Sets or deletes volume metadata.""" - volume = utils.find_volume(cs, args.volume) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.volumes.set_metadata(volume, metadata) - elif args.action == 'unset': - # NOTE(zul): Make sure py2/py3 sorting is the same - cs.volumes.delete_metadata(volume, sorted(metadata.keys(), - reverse=True)) - - -@utils.arg( - '--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Shows details for all tenants. Admin only.') -@utils.arg( - '--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@utils.arg( - '--display-name', - metavar='<display-name>', - default=None, - help='Filters list by a display name. Default=None.') -@utils.arg( - '--status', - metavar='<status>', - default=None, - help='Filters list by a status. Default=None.') -@utils.arg( - '--volume-id', - metavar='<volume-id>', - default=None, - help='Filters list by a volume ID. Default=None.') -@utils.service_type('volume') -def do_snapshot_list(cs, args): - """Lists all snapshots.""" - all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants)) - search_opts = { - 'all_tenants': all_tenants, - 'display_name': args.display_name, - 'status': args.status, - 'volume_id': args.volume_id, - } - - snapshots = cs.volume_snapshots.list(search_opts=search_opts) - _translate_volume_snapshot_keys(snapshots) - utils.print_list(snapshots, - ['ID', 'Volume ID', 'Status', 'Display Name', 'Size']) - - -@utils.arg('snapshot', metavar='<snapshot>', - help='Name or ID of snapshot.') -@utils.service_type('volume') -def do_snapshot_show(cs, args): - """Shows snapshot details.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - _print_volume_snapshot(snapshot) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume to snapshot.') -@utils.arg('--force', - metavar='<True|False>', - help='Allows or disallows snapshot of ' - 'a volume when the volume is attached to an instance. ' - 'If set to True, ignores the current status of the ' - 'volume when attempting to snapshot it rather ' - 'than forcing it to be available. ' - 'Default=False.', - default=False) -@utils.arg( - '--display-name', - metavar='<display-name>', - default=None, - help='The snapshot name. Default=None.') -@utils.arg( - '--display_name', - help=argparse.SUPPRESS) -@utils.arg( - '--display-description', - metavar='<display-description>', - default=None, - help='The snapshot description. Default=None.') -@utils.arg( - '--display_description', - help=argparse.SUPPRESS) -@utils.service_type('volume') -def do_snapshot_create(cs, args): - """Creates a snapshot.""" - volume = utils.find_volume(cs, args.volume) - snapshot = cs.volume_snapshots.create(volume.id, - args.force, - args.display_name, - args.display_description) - _print_volume_snapshot(snapshot) - - -@utils.arg('snapshot', - metavar='<snapshot>', nargs='+', - help='Name or ID of the snapshot(s) to delete.') -@utils.service_type('volume') -def do_snapshot_delete(cs, args): - """Remove one or more snapshots.""" - failure_count = 0 - for snapshot in args.snapshot: - try: - _find_volume_snapshot(cs, snapshot).delete() - except Exception as e: - failure_count += 1 - print("Delete for snapshot %s failed: %s" % (snapshot, e)) - if failure_count == len(args.snapshot): - raise exceptions.CommandError("Unable to delete any of the specified " - "snapshots.") - - -@utils.arg('snapshot', metavar='<snapshot>', - help='Name or ID of snapshot.') -@utils.arg('display_name', nargs='?', metavar='<display-name>', - help='New display name for snapshot.') -@utils.arg('--display-description', metavar='<display-description>', - help='Snapshot description. Default=None.', - default=None) -@utils.service_type('volume') -def do_snapshot_rename(cs, args): - """Renames a snapshot.""" - kwargs = {} - if args.display_name is not None: - kwargs['display_name'] = args.display_name - if args.display_description is not None: - kwargs['display_description'] = args.display_description - - if not any(kwargs): - msg = 'Must supply either display-name or display-description.' - raise exceptions.ClientException(code=1, message=msg) - - _find_volume_snapshot(cs, args.snapshot).update(**kwargs) - - -@utils.arg('snapshot', metavar='<snapshot>', nargs='+', - help='Name or ID of snapshot to modify.') -@utils.arg('--state', metavar='<state>', - default='available', - help=('The state to assign to the snapshot. Valid values are ' - '"available," "error," "creating," "deleting," or ' - '"error_deleting." ' - 'Default is "available."')) -@utils.service_type('volume') -def do_snapshot_reset_state(cs, args): - """Explicitly updates the snapshot state.""" - failure_count = 0 - - single = (len(args.snapshot) == 1) - - for snapshot in args.snapshot: - try: - _find_volume_snapshot(cs, snapshot).reset_state(args.state) - except Exception as e: - failure_count += 1 - msg = "Reset state for snapshot %s failed: %s" % (snapshot, e) - if not single: - print(msg) - - if failure_count == len(args.snapshot): - if not single: - msg = ("Unable to reset the state for any of the the specified " - "snapshots.") - raise exceptions.CommandError(msg) - - -def _print_volume_type_list(vtypes): - utils.print_list(vtypes, ['ID', 'Name']) - - -@utils.service_type('volume') -def do_type_list(cs, args): - """Lists available 'volume types'.""" - vtypes = cs.volume_types.list() - _print_volume_type_list(vtypes) - - -@utils.service_type('volume') -def do_extra_specs_list(cs, args): - """Lists current volume types and extra specs.""" - vtypes = cs.volume_types.list() - utils.print_list(vtypes, ['ID', 'Name', 'extra_specs']) - - -@utils.arg('name', - metavar='<name>', - help="Name for the volume type.") -@utils.service_type('volume') -def do_type_create(cs, args): - """Creates a volume type.""" - vtype = cs.volume_types.create(args.name) - _print_volume_type_list([vtype]) - - -@utils.arg('id', - metavar='<id>', - help="ID of volume type to delete.") -@utils.service_type('volume') -def do_type_delete(cs, args): - """Deletes a specified volume type.""" - volume_type = _find_volume_type(cs, args.id) - cs.volume_types.delete(volume_type) - - -@utils.arg('vtype', - metavar='<vtype>', - help="Name or ID of volume type.") -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', - metavar='<key=value>', - nargs='*', - default=None, - help='The extra specs key and value pair to set or unset. ' - 'For unset, specify only the key. Default=None.') -@utils.service_type('volume') -def do_type_key(cs, args): - """Sets or unsets extra_spec for a volume type.""" - vtype = _find_volume_type(cs, args.vtype) - - if args.metadata is not None: - keypair = _extract_metadata(args) - - if args.action == 'set': - vtype.set_keys(keypair) - elif args.action == 'unset': - vtype.unset_keys(list(keypair)) - - -def do_endpoints(cs, args): - """Discovers endpoints registered by authentication service.""" - catalog = cs.client.service_catalog.catalog - for e in catalog['serviceCatalog']: - utils.print_dict(e['endpoints'][0], e['name']) - - -def do_credentials(cs, args): - """Shows user credentials returned from auth.""" - catalog = cs.client.service_catalog.catalog - utils.print_dict(catalog['user'], "User Credentials") - utils.print_dict(catalog['token'], "Token") - - -_quota_resources = ['volumes', 'snapshots', 'gigabytes'] -_quota_infos = ['Type', 'In_use', 'Reserved', 'Limit'] - - -def _quota_show(quotas): - quota_dict = {} - for resource in quotas._info: - good_name = False - for name in _quota_resources: - if resource.startswith(name): - good_name = True - if not good_name: - continue - quota_dict[resource] = getattr(quotas, resource, None) - utils.print_dict(quota_dict) - - -def _quota_usage_show(quotas): - quota_list = [] - for resource in quotas._info.keys(): - good_name = False - for name in _quota_resources: - if resource.startswith(name): - good_name = True - if not good_name: - continue - quota_info = getattr(quotas, resource, None) - quota_info['Type'] = resource - quota_info = dict((k.capitalize(), v) for k, v in quota_info.items()) - quota_list.append(quota_info) - utils.print_list(quota_list, _quota_infos) - - -def _quota_update(manager, identifier, args): - updates = {} - for resource in _quota_resources: - val = getattr(args, resource, None) - if val is not None: - if args.volume_type: - resource = resource + '_%s' % args.volume_type - updates[resource] = val - - if updates: - _quota_show(manager.update(identifier, **updates)) - - -@utils.arg('tenant', metavar='<tenant_id>', - help='ID of the tenant for which to list quotas.') -@utils.service_type('volume') -def do_quota_show(cs, args): - """Lists quotas for a tenant.""" - - _quota_show(cs.quotas.get(args.tenant)) - - -@utils.arg('tenant', metavar='<tenant_id>', - help='ID of the tenant for which to list quota usage.') -@utils.service_type('volume') -def do_quota_usage(cs, args): - """Lists quota usage for a tenant.""" - - _quota_usage_show(cs.quotas.get(args.tenant, usage=True)) - - -@utils.arg('tenant', metavar='<tenant_id>', - help='ID of the tenant for which to list default quotas.') -@utils.service_type('volume') -def do_quota_defaults(cs, args): - """Lists default quotas for a tenant.""" - - _quota_show(cs.quotas.defaults(args.tenant)) - - -@utils.arg('tenant', metavar='<tenant_id>', - help='ID of the tenant for which to set quotas.') -@utils.arg('--volumes', - metavar='<volumes>', - type=int, default=None, - help='The new "volumes" quota value. Default=None.') -@utils.arg('--snapshots', - metavar='<snapshots>', - type=int, default=None, - help='The new "snapshots" quota value. Default=None.') -@utils.arg('--gigabytes', - metavar='<gigabytes>', - type=int, default=None, - help='The new "gigabytes" quota value. Default=None.') -@utils.arg('--volume-type', - metavar='<volume_type_name>', - default=None, - help='Volume type. Default=None.') -@utils.service_type('volume') -def do_quota_update(cs, args): - """Updates quotas for a tenant.""" - - _quota_update(cs.quotas, args.tenant, args) - - -@utils.arg('tenant', metavar='<tenant_id>', - help='UUID of tenant to delete the quotas for.') -@utils.service_type('volume') -def do_quota_delete(cs, args): - """Delete the quotas for a tenant.""" - - cs.quotas.delete(args.tenant) - - -@utils.arg('class_name', metavar='<class>', - help='Name of quota class for which to list quotas.') -@utils.service_type('volume') -def do_quota_class_show(cs, args): - """Lists quotas for a quota class.""" - - _quota_show(cs.quota_classes.get(args.class_name)) - - -@utils.arg('class_name', metavar='<class>', - help='Name of quota class for which to set quotas.') -@utils.arg('--volumes', - metavar='<volumes>', - type=int, default=None, - help='The new "volumes" quota value. Default=None.') -@utils.arg('--snapshots', - metavar='<snapshots>', - type=int, default=None, - help='The new "snapshots" quota value. Default=None.') -@utils.arg('--gigabytes', - metavar='<gigabytes>', - type=int, default=None, - help='The new "gigabytes" quota value. Default=None.') -@utils.arg('--volume-type', - metavar='<volume_type_name>', - default=None, - help='Volume type. Default=None.') -@utils.service_type('volume') -def do_quota_class_update(cs, args): - """Updates quotas for a quota class.""" - - _quota_update(cs.quota_classes, args.class_name, args) - - -@utils.service_type('volume') -def do_absolute_limits(cs, args): - """Lists absolute limits for a user.""" - limits = cs.limits.get().absolute - columns = ['Name', 'Value'] - utils.print_list(limits, columns) - - -@utils.service_type('volume') -def do_rate_limits(cs, args): - """Lists rate limits for a user.""" - limits = cs.limits.get().rate - columns = ['Verb', 'URI', 'Value', 'Remain', 'Unit', 'Next_Available'] - utils.print_list(limits, columns) - - -def _find_volume_type(cs, vtype): - """Gets a volume type by name or ID.""" - return utils.find_resource(cs.volume_types, vtype) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume to upload to an image.') -@utils.arg('--force', - metavar='<True|False>', - help='Enables or disables upload of ' - 'a volume that is attached to an instance. ' - 'Default=False.', - default=False) -@utils.arg('--container-format', - metavar='<container-format>', - help='Container format type. ' - 'Default is bare.', - default='bare') -@utils.arg('--disk-format', - metavar='<disk-format>', - help='Disk format type. ' - 'Default is raw.', - default='raw') -@utils.arg('image_name', - metavar='<image-name>', - help='The new image name.') -@utils.service_type('volume') -def do_upload_to_image(cs, args): - """Uploads volume to Image Service as an image.""" - volume = utils.find_volume(cs, args.volume) - _print_volume_image(volume.upload_to_image(args.force, - args.image_name, - args.container_format, - args.disk_format)) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume to back up.') -@utils.arg('--container', metavar='<container>', - help='Backup container name. Default=None.', - default=None) -@utils.arg('--display-name', metavar='<display-name>', - help='Backup name. Default=None.', - default=None) -@utils.arg('--display-description', metavar='<display-description>', - help='Backup description. Default=None.', - default=None) -@utils.service_type('volume') -def do_backup_create(cs, args): - """Creates a volume backup.""" - volume = utils.find_volume(cs, args.volume) - backup = cs.backups.create(volume.id, - args.container, - args.display_name, - args.display_description) - - info = {"volume_id": volume.id} - info.update(backup._info) - - if 'links' in info: - info.pop('links') - - utils.print_dict(info) - - -@utils.arg('backup', metavar='<backup>', help='Name or ID of backup.') -@utils.service_type('volume') -def do_backup_show(cs, args): - """Show backup details.""" - backup = _find_backup(cs, args.backup) - info = dict() - info.update(backup._info) - - if 'links' in info: - info.pop('links') - - utils.print_dict(info) - - -@utils.service_type('volume') -def do_backup_list(cs, args): - """Lists all backups.""" - backups = cs.backups.list() - columns = ['ID', 'Volume ID', 'Status', 'Name', 'Size', 'Object Count', - 'Container'] - utils.print_list(backups, columns) - - -@utils.arg('backup', metavar='<backup>', - help='Name or ID of backup to delete.') -@utils.service_type('volume') -def do_backup_delete(cs, args): - """Removes a backup.""" - backup = _find_backup(cs, args.backup) - backup.delete() - - -@utils.arg('backup', metavar='<backup>', - help='ID of backup to restore.') -@utils.arg('--volume-id', metavar='<volume>', - help='ID or name of backup volume to ' - 'which to restore. Default=None.', - default=None) -@utils.service_type('volume') -def do_backup_restore(cs, args): - """Restores a backup.""" - if args.volume_id: - volume_id = utils.find_volume(cs, args.volume_id).id - else: - volume_id = None - cs.restores.restore(args.backup, volume_id) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume to transfer.') -@utils.arg('--display-name', metavar='<display-name>', - help='Transfer name. Default=None.', - default=None) -@utils.service_type('volume') -def do_transfer_create(cs, args): - """Creates a volume transfer.""" - volume = utils.find_volume(cs, args.volume) - transfer = cs.transfers.create(volume.id, - args.display_name) - info = dict() - info.update(transfer._info) - - if 'links' in info: - info.pop('links') - - utils.print_dict(info) - - -@utils.arg('transfer', metavar='<transfer>', - help='Name or ID of transfer to delete.') -@utils.service_type('volume') -def do_transfer_delete(cs, args): - """Undoes a transfer.""" - transfer = _find_transfer(cs, args.transfer) - transfer.delete() - - -@utils.arg('transfer', metavar='<transfer>', - help='ID of transfer to accept.') -@utils.arg('auth_key', metavar='<auth_key>', - help='Authentication key of transfer to accept.') -@utils.service_type('volume') -def do_transfer_accept(cs, args): - """Accepts a volume transfer.""" - transfer = cs.transfers.accept(args.transfer, args.auth_key) - info = dict() - info.update(transfer._info) - - if 'links' in info: - info.pop('links') - - utils.print_dict(info) - - -@utils.service_type('volume') -def do_transfer_list(cs, args): - """Lists all transfers.""" - transfers = cs.transfers.list() - columns = ['ID', 'Volume ID', 'Name'] - utils.print_list(transfers, columns) - - -@utils.arg('transfer', metavar='<transfer>', - help='Name or ID of transfer to accept.') -@utils.service_type('volume') -def do_transfer_show(cs, args): - """Show transfer details.""" - transfer = _find_transfer(cs, args.transfer) - info = dict() - info.update(transfer._info) - - if 'links' in info: - info.pop('links') - - utils.print_dict(info) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume to extend.') -@utils.arg('new_size', - metavar='<new-size>', - type=int, - help='Size of volume, in GBs.') -@utils.service_type('volume') -def do_extend(cs, args): - """Attempts to extend size of an existing volume.""" - volume = utils.find_volume(cs, args.volume) - cs.volumes.extend(volume, args.new_size) - - -@utils.arg('--host', metavar='<hostname>', default=None, - help='Host name. Default=None.') -@utils.arg('--binary', metavar='<binary>', default=None, - help='Service binary. Default=None.') -@utils.service_type('volume') -def do_service_list(cs, args): - """Lists all services. Filter by host and service binary.""" - result = cs.services.list(host=args.host, binary=args.binary) - columns = ["Binary", "Host", "Zone", "Status", "State", "Updated_at"] - # NOTE(jay-lau-513): we check if the response has disabled_reason - # so as not to add the column when the extended ext is not enabled. - if result and hasattr(result[0], 'disabled_reason'): - columns.append("Disabled Reason") - utils.print_list(result, columns) - - -@utils.arg('host', metavar='<hostname>', help='Host name.') -@utils.arg('binary', metavar='<binary>', help='Service binary.') -@utils.service_type('volume') -def do_service_enable(cs, args): - """Enables the service.""" - result = cs.services.enable(args.host, args.binary) - columns = ["Host", "Binary", "Status"] - utils.print_list([result], columns) - - -@utils.arg('host', metavar='<hostname>', help='Host name.') -@utils.arg('binary', metavar='<binary>', help='Service binary.') -@utils.arg('--reason', metavar='<reason>', - help='Reason for disabling service.') -@utils.service_type('volume') -def do_service_disable(cs, args): - """Disables the service.""" - columns = ["Host", "Binary", "Status"] - if args.reason: - columns.append('Disabled Reason') - result = cs.services.disable_log_reason(args.host, args.binary, - args.reason) - else: - result = cs.services.disable(args.host, args.binary) - utils.print_list([result], columns) - - -def _treeizeAvailabilityZone(zone): - """Builds a tree view for availability zones.""" - AvailabilityZone = availability_zones.AvailabilityZone - - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - result = [] - - # Zone tree view item - az.zoneName = zone.zoneName - az.zoneState = ('available' - if zone.zoneState['available'] else 'not available') - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - if getattr(zone, "hosts", None) and zone.hosts is not None: - for (host, services) in zone.hosts.items(): - # Host tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '|- %s' % host - az.zoneState = '' - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - for (svc, state) in services.items(): - # Service tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '| |- %s' % svc - az.zoneState = '%s %s %s' % ( - 'enabled' if state['active'] else 'disabled', - ':-)' if state['available'] else 'XXX', - state['updated_at']) - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - return result - - -@utils.service_type('volume') -def do_availability_zone_list(cs, _args): - """Lists all availability zones.""" - try: - availability_zones = cs.availability_zones.list() - except exceptions.Forbidden as e: # policy doesn't allow probably - try: - availability_zones = cs.availability_zones.list(detailed=False) - except Exception: - raise e - - result = [] - for zone in availability_zones: - result += _treeizeAvailabilityZone(zone) - _translate_availability_zone_keys(result) - utils.print_list(result, ['Name', 'Status']) - - -def _print_volume_encryption_type_list(encryption_types): - """ - Lists volume encryption types. - - :param encryption_types: a list of :class: VolumeEncryptionType instances - """ - utils.print_list(encryption_types, ['Volume Type ID', 'Provider', - 'Cipher', 'Key Size', - 'Control Location']) - - -@utils.service_type('volume') -def do_encryption_type_list(cs, args): - """Shows encryption type details for volume types. Admin only.""" - result = cs.volume_encryption_types.list() - utils.print_list(result, ['Volume Type ID', 'Provider', 'Cipher', - 'Key Size', 'Control Location']) - - -@utils.arg('volume_type', - metavar='<volume_type>', - type=str, - help="Name or ID of volume type.") -@utils.service_type('volume') -def do_encryption_type_show(cs, args): - """Shows encryption type details for volume type. Admin only.""" - volume_type = _find_volume_type(cs, args.volume_type) - - result = cs.volume_encryption_types.get(volume_type) - - # Display result or an empty table if no result - if hasattr(result, 'volume_type_id'): - _print_volume_encryption_type_list([result]) - else: - _print_volume_encryption_type_list([]) - - -@utils.arg('volume_type', - metavar='<volume_type>', - type=str, - help="Name or ID of volume type.") -@utils.arg('provider', - metavar='<provider>', - type=str, - help='The class that provides encryption support. ' - 'For example, a volume driver class path.') -@utils.arg('--cipher', - metavar='<cipher>', - type=str, - required=False, - default=None, - help='The encryption algorithm and mode. ' - 'For example, aes-xts-plain64. Default=None.') -@utils.arg('--key_size', - metavar='<key_size>', - type=int, - required=False, - default=None, - help='Size of encryption key, in bits. ' - 'For example, 128 or 256. Default=None.') -@utils.arg('--control_location', - metavar='<control_location>', - choices=['front-end', 'back-end'], - type=str, - required=False, - default='front-end', - help='Notional service where encryption is performed. ' - 'Valid values are "front-end" or "back-end." ' - 'For example, front-end=Nova. ' - 'Default is "front-end."') -@utils.service_type('volume') -def do_encryption_type_create(cs, args): - """Creates encryption type for a volume type. Admin only.""" - volume_type = _find_volume_type(cs, args.volume_type) - - body = {} - body['provider'] = args.provider - body['cipher'] = args.cipher - body['key_size'] = args.key_size - body['control_location'] = args.control_location - - result = cs.volume_encryption_types.create(volume_type, body) - _print_volume_encryption_type_list([result]) - - -@utils.arg('volume_type', - metavar='<volume_type>', - type=str, - help="Name or ID of volume type.") -@utils.service_type('volume') -def do_encryption_type_delete(cs, args): - """Deletes encryption type for a volume type. Admin only.""" - volume_type = _find_volume_type(cs, args.volume_type) - cs.volume_encryption_types.delete(volume_type) - - -@utils.arg('volume', metavar='<volume>', help='ID of volume to migrate.') -@utils.arg('host', metavar='<host>', help='Destination host.') -@utils.arg('--force-host-copy', metavar='<True|False>', - choices=['True', 'False'], required=False, - help='Enables or disables generic host-based ' - 'force-migration, which bypasses driver ' - 'optimizations. Default=False.', - default=False) -@utils.service_type('volume') -def do_migrate(cs, args): - """Migrates volume to a new host.""" - volume = utils.find_volume(cs, args.volume) - - volume.migrate_volume(args.host, args.force_host_copy) - - -def _print_qos_specs(qos_specs): - utils.print_dict(qos_specs._info) - - -def _print_qos_specs_list(q_specs): - utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs']) - - -def _print_qos_specs_and_associations_list(q_specs): - utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs']) - - -def _print_associations_list(associations): - utils.print_list(associations, ['Association_Type', 'Name', 'ID']) - - -@utils.arg('name', - metavar='<name>', - help="Name of new QoS specifications.") -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='Specifications for QoS.') -@utils.service_type('volume') -def do_qos_create(cs, args): - """Creates a qos specs.""" - keypair = None - if args.metadata is not None: - keypair = _extract_metadata(args) - qos_specs = cs.qos_specs.create(args.name, keypair) - _print_qos_specs(qos_specs) - - -@utils.service_type('volume') -def do_qos_list(cs, args): - """Lists qos specs.""" - qos_specs = cs.qos_specs.list() - _print_qos_specs_list(qos_specs) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.service_type('volume') -def do_qos_show(cs, args): - """Shows a specified qos specs.""" - qos_specs = _find_qos_specs(cs, args.qos_specs) - _print_qos_specs(qos_specs) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.arg('--force', - metavar='<True|False>', - default=False, - help='Enables or disables deletion of in-use ' - 'QoS specifications. Default=False.') -@utils.service_type('volume') -def do_qos_delete(cs, args): - """Deletes a specified qos specs.""" - force = strutils.bool_from_string(args.force) - qos_specs = _find_qos_specs(cs, args.qos_specs) - cs.qos_specs.delete(qos_specs, force) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.arg('vol_type_id', metavar='<volume_type_id>', - help='ID of volume type.') -@utils.service_type('volume') -def do_qos_associate(cs, args): - """Associates qos specs with specified volume type.""" - cs.qos_specs.associate(args.qos_specs, args.vol_type_id) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.arg('vol_type_id', metavar='<volume_type_id>', - help='ID of volume type.') -@utils.service_type('volume') -def do_qos_disassociate(cs, args): - """Disassociates qos specs from specified volume type.""" - cs.qos_specs.disassociate(args.qos_specs, args.vol_type_id) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.service_type('volume') -def do_qos_disassociate_all(cs, args): - """Disassociates qos specs from all associations.""" - cs.qos_specs.disassociate_all(args.qos_specs) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', metavar='key=value', - nargs='+', - default=[], - help='Metadata key and value pair to set or unset. ' - 'For unset, specify only the key.') -def do_qos_key(cs, args): - """Sets or unsets specifications for a qos spec.""" - keypair = _extract_metadata(args) - - if args.action == 'set': - cs.qos_specs.set_keys(args.qos_specs, keypair) - elif args.action == 'unset': - cs.qos_specs.unset_keys(args.qos_specs, list(keypair)) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.service_type('volume') -def do_qos_get_association(cs, args): - """Gets all associations for specified qos specs.""" - associations = cs.qos_specs.get_associations(args.qos_specs) - _print_associations_list(associations) - - -@utils.arg('snapshot', - metavar='<snapshot>', - help='ID of snapshot for which to update metadata.') -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='The metadata key and value pair to set or unset. ' - 'For unset, specify only the key.') -@utils.service_type('volume') -def do_snapshot_metadata(cs, args): - """Sets or deletes snapshot metadata.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - metadata = _extract_metadata(args) - - if args.action == 'set': - metadata = snapshot.set_metadata(metadata) - utils.print_dict(metadata._info) - elif args.action == 'unset': - snapshot.delete_metadata(list(metadata.keys())) - - -@utils.arg('snapshot', metavar='<snapshot>', - help='ID of snapshot.') -@utils.service_type('volume') -def do_snapshot_metadata_show(cs, args): - """Shows snapshot metadata.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - utils.print_dict(snapshot._info['metadata'], 'Metadata-property') - - -@utils.arg('volume', metavar='<volume>', - help='ID of volume.') -@utils.service_type('volume') -def do_metadata_show(cs, args): - """Shows volume metadata.""" - volume = utils.find_volume(cs, args.volume) - utils.print_dict(volume._info['metadata'], 'Metadata-property') - - -@utils.arg('volume', - metavar='<volume>', - help='ID of volume for which to update metadata.') -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='Metadata key and value pair or pairs to update. ' - 'Default=[].') -@utils.service_type('volume') -def do_metadata_update_all(cs, args): - """Updates volume metadata.""" - volume = utils.find_volume(cs, args.volume) - metadata = _extract_metadata(args) - metadata = volume.update_all_metadata(metadata) - utils.print_dict(metadata) - - -@utils.arg('snapshot', - metavar='<snapshot>', - help='ID of snapshot for which to update metadata.') -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='Metadata key and value pair or pairs to update. ' - 'Default=[].') -@utils.service_type('volume') -def do_snapshot_metadata_update_all(cs, args): - """Updates snapshot metadata.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - metadata = _extract_metadata(args) - metadata = snapshot.update_all_metadata(metadata) - utils.print_dict(metadata) - - -@utils.arg('volume', metavar='<volume>', help='ID of volume to update.') -@utils.arg('read_only', - metavar='<True|true|False|false>', - choices=['True', 'true', 'False', 'false'], - help='Enables or disables update of volume to ' - 'read-only access mode.') -@utils.service_type('volume') -def do_readonly_mode_update(cs, args): - """Updates volume read-only access-mode flag.""" - volume = utils.find_volume(cs, args.volume) - cs.volumes.update_readonly_flag(volume, - strutils.bool_from_string(args.read_only)) - - -@utils.arg('volume', metavar='<volume>', help='ID of the volume to update.') -@utils.arg('bootable', - metavar='<True|true|False|false>', - choices=['True', 'true', 'False', 'false'], - help='Flag to indicate whether volume is bootable.') -@utils.service_type('volume') -def do_set_bootable(cs, args): - """Update bootable status of a volume.""" - volume = utils.find_volume(cs, args.volume) - cs.volumes.set_bootable(volume, - strutils.bool_from_string(args.bootable)) diff --git a/awx/lib/site-packages/cinderclient/v1/volume_backups.py b/awx/lib/site-packages/cinderclient/v1/volume_backups.py deleted file mode 100644 index 8e1f2e756d..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/volume_backups.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume Backups interface (1.1 extension). -""" - -from cinderclient import base - - -class VolumeBackup(base.Resource): - """A volume backup is a block level backup of a volume.""" - def __repr__(self): - return "<VolumeBackup: %s>" % self.id - - def delete(self): - """Delete this volume backup.""" - return self.manager.delete(self) - - -class VolumeBackupManager(base.ManagerWithFind): - """Manage :class:`VolumeBackup` resources.""" - resource_class = VolumeBackup - - def create(self, volume_id, container=None, - name=None, description=None): - """Creates a volume backup. - - :param volume_id: The ID of the volume to backup. - :param container: The name of the backup service container. - :param name: The name of the backup. - :param description: The description of the backup. - :rtype: :class:`VolumeBackup` - """ - body = {'backup': {'volume_id': volume_id, - 'container': container, - 'name': name, - 'description': description}} - return self._create('/backups', body, 'backup') - - def get(self, backup_id): - """Show details of a volume backup. - - :param backup_id: The ID of the backup to display. - :rtype: :class:`VolumeBackup` - """ - return self._get("/backups/%s" % backup_id, "backup") - - def list(self, detailed=True): - """Get a list of all volume backups. - - :rtype: list of :class:`VolumeBackup` - """ - if detailed is True: - return self._list("/backups/detail", "backups") - else: - return self._list("/backups", "backups") - - def delete(self, backup): - """Delete a volume backup. - - :param backup: The :class:`VolumeBackup` to delete. - """ - self._delete("/backups/%s" % base.getid(backup)) diff --git a/awx/lib/site-packages/cinderclient/v1/volume_backups_restore.py b/awx/lib/site-packages/cinderclient/v1/volume_backups_restore.py deleted file mode 100644 index 0eafa8220c..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/volume_backups_restore.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Volume Backups Restore interface (1.1 extension). - -This is part of the Volume Backups interface. -""" - -from cinderclient import base - - -class VolumeBackupsRestore(base.Resource): - """A Volume Backups Restore represents a restore operation.""" - def __repr__(self): - return "<VolumeBackupsRestore: %s>" % self.volume_id - - -class VolumeBackupRestoreManager(base.Manager): - """Manage :class:`VolumeBackupsRestore` resources.""" - resource_class = VolumeBackupsRestore - - def restore(self, backup_id, volume_id=None): - """Restore a backup to a volume. - - :param backup_id: The ID of the backup to restore. - :param volume_id: The ID of the volume to restore the backup to. - :rtype: :class:`Restore` - """ - body = {'restore': {'volume_id': volume_id}} - return self._create("/backups/%s/restore" % backup_id, - body, "restore") diff --git a/awx/lib/site-packages/cinderclient/v1/volume_encryption_types.py b/awx/lib/site-packages/cinderclient/v1/volume_encryption_types.py deleted file mode 100644 index 1099bc37b4..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/volume_encryption_types.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2013 The Johns Hopkins University/Applied Physics Laboratory -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -""" -Volume Encryption Type interface -""" - -from cinderclient import base - - -class VolumeEncryptionType(base.Resource): - """ - A Volume Encryption Type is a collection of settings used to conduct - encryption for a specific volume type. - """ - def __repr__(self): - return "<VolumeEncryptionType: %s>" % self.name - - -class VolumeEncryptionTypeManager(base.ManagerWithFind): - """ - Manage :class: `VolumeEncryptionType` resources. - """ - resource_class = VolumeEncryptionType - - def list(self, search_opts=None): - """ - List all volume encryption types. - - :param volume_types: a list of volume types - :return: a list of :class: VolumeEncryptionType instances - """ - # Since the encryption type is a volume type extension, we cannot get - # all encryption types without going through all volume types. - volume_types = self.api.volume_types.list() - encryption_types = [] - for volume_type in volume_types: - encryption_type = self._get("/types/%s/encryption" - % base.getid(volume_type)) - if hasattr(encryption_type, 'volume_type_id'): - encryption_types.append(encryption_type) - return encryption_types - - def get(self, volume_type): - """ - Get the volume encryption type for the specified volume type. - - :param volume_type: the volume type to query - :return: an instance of :class: VolumeEncryptionType - """ - return self._get("/types/%s/encryption" % base.getid(volume_type)) - - def create(self, volume_type, specs): - """ - Creates encryption type for a volume type. Default: admin only. - - :param volume_type: the volume type on which to add an encryption type - :param specs: the encryption type specifications to add - :return: an instance of :class: VolumeEncryptionType - """ - body = {'encryption': specs} - return self._create("/types/%s/encryption" % base.getid(volume_type), - body, "encryption") - - def update(self, volume_type, specs): - """ - Update the encryption type information for the specified volume type. - - :param volume_type: the volume type whose encryption type information - must be updated - :param specs: the encryption type specifications to update - :return: an instance of :class: VolumeEncryptionType - """ - raise NotImplementedError() - - def delete(self, volume_type): - """ - Delete the encryption type information for the specified volume type. - - :param volume_type: the volume type whose encryption type information - must be deleted - """ - return self._delete("/types/%s/encryption/provider" % - base.getid(volume_type)) diff --git a/awx/lib/site-packages/cinderclient/v1/volume_snapshots.py b/awx/lib/site-packages/cinderclient/v1/volume_snapshots.py deleted file mode 100644 index 690fd01233..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/volume_snapshots.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright 2011 Denali Systems, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume snapshot interface (1.1 extension). -""" - -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - -from cinderclient import base -import six - - -class Snapshot(base.Resource): - """ - A Snapshot is a point-in-time snapshot of an openstack volume. - """ - def __repr__(self): - return "<Snapshot: %s>" % self.id - - def delete(self): - """ - Delete this snapshot. - """ - self.manager.delete(self) - - def update(self, **kwargs): - """ - Update the display_name or display_description for this snapshot. - """ - self.manager.update(self, **kwargs) - - @property - def progress(self): - return self._info.get('os-extended-snapshot-attributes:progress') - - @property - def project_id(self): - return self._info.get('os-extended-snapshot-attributes:project_id') - - def reset_state(self, state): - """Update the snapshot with the privided state.""" - self.manager.reset_state(self, state) - - def set_metadata(self, metadata): - """Set metadata of this snapshot.""" - return self.manager.set_metadata(self, metadata) - - def delete_metadata(self, keys): - """Delete metadata of this snapshot.""" - return self.manager.delete_metadata(self, keys) - - def update_all_metadata(self, metadata): - """Update_all metadata of this snapshot.""" - return self.manager.update_all_metadata(self, metadata) - - -class SnapshotManager(base.ManagerWithFind): - """ - Manage :class:`Snapshot` resources. - """ - resource_class = Snapshot - - def create(self, volume_id, force=False, - display_name=None, display_description=None): - - """ - Create a snapshot of the given volume. - - :param volume_id: The ID of the volume to snapshot. - :param force: If force is True, create a snapshot even if the volume is - attached to an instance. Default is False. - :param display_name: Name of the snapshot - :param display_description: Description of the snapshot - :rtype: :class:`Snapshot` - """ - body = {'snapshot': {'volume_id': volume_id, - 'force': force, - 'display_name': display_name, - 'display_description': display_description}} - return self._create('/snapshots', body, 'snapshot') - - def get(self, snapshot_id): - """ - Get a snapshot. - - :param snapshot_id: The ID of the snapshot to get. - :rtype: :class:`Snapshot` - """ - return self._get("/snapshots/%s" % snapshot_id, "snapshot") - - def list(self, detailed=True, search_opts=None): - """ - Get a list of all snapshots. - - :rtype: list of :class:`Snapshot` - """ - - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - if qparams: - new_qparams = sorted(qparams.items(), key=lambda x: x[0]) - query_string = "?%s" % urlencode(new_qparams) - else: - query_string = "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/snapshots%s%s" % (detail, query_string), - "snapshots") - - def delete(self, snapshot): - """ - Delete a snapshot. - - :param snapshot: The :class:`Snapshot` to delete. - """ - self._delete("/snapshots/%s" % base.getid(snapshot)) - - def update(self, snapshot, **kwargs): - """ - Update the display_name or display_description for a snapshot. - - :param snapshot: The :class:`Snapshot` to update. - """ - if not kwargs: - return - - body = {"snapshot": kwargs} - - self._update("/snapshots/%s" % base.getid(snapshot), body) - - def reset_state(self, snapshot, state): - """Update the specified volume with the provided state.""" - return self._action('os-reset_status', snapshot, {'status': state}) - - def _action(self, action, snapshot, info=None, **kwargs): - """Perform a snapshot action.""" - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/snapshots/%s/action' % base.getid(snapshot) - return self.api.client.post(url, body=body) - - def update_snapshot_status(self, snapshot, update_dict): - return self._action('os-update_snapshot_status', - base.getid(snapshot), update_dict) - - def set_metadata(self, snapshot, metadata): - """Update/Set a snapshots metadata. - - :param snapshot: The :class:`Snapshot`. - :param metadata: A list of keys to be set. - """ - body = {'metadata': metadata} - return self._create("/snapshots/%s/metadata" % base.getid(snapshot), - body, "metadata") - - def delete_metadata(self, snapshot, keys): - """Delete specified keys from snapshot metadata. - - :param snapshot: The :class:`Snapshot`. - :param keys: A list of keys to be removed. - """ - snapshot_id = base.getid(snapshot) - for k in keys: - self._delete("/snapshots/%s/metadata/%s" % (snapshot_id, k)) - - def update_all_metadata(self, snapshot, metadata): - """Update_all snapshot metadata. - - :param snapshot: The :class:`Snapshot`. - :param metadata: A list of keys to be updated. - """ - body = {'metadata': metadata} - return self._update("/snapshots/%s/metadata" % base.getid(snapshot), - body) diff --git a/awx/lib/site-packages/cinderclient/v1/volume_transfers.py b/awx/lib/site-packages/cinderclient/v1/volume_transfers.py deleted file mode 100644 index 00daf3ec5e..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/volume_transfers.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume transfer interface (1.1 extension). -""" - -from cinderclient import base - - -class VolumeTransfer(base.Resource): - """Transfer a volume from one tenant to another""" - def __repr__(self): - return "<VolumeTransfer: %s>" % self.id - - def delete(self): - """Delete this volume transfer.""" - return self.manager.delete(self) - - -class VolumeTransferManager(base.ManagerWithFind): - """Manage :class:`VolumeTransfer` resources.""" - resource_class = VolumeTransfer - - def create(self, volume_id, name=None): - """Creates a volume transfer. - - :param volume_id: The ID of the volume to transfer. - :param name: The name of the transfer. - :rtype: :class:`VolumeTransfer` - """ - body = {'transfer': {'volume_id': volume_id, - 'name': name}} - return self._create('/os-volume-transfer', body, 'transfer') - - def accept(self, transfer_id, auth_key): - """Accept a volume transfer. - - :param transfer_id: The ID of the transfer to accept. - :param auth_key: The auth_key of the transfer. - :rtype: :class:`VolumeTransfer` - """ - body = {'accept': {'auth_key': auth_key}} - return self._create('/os-volume-transfer/%s/accept' % transfer_id, - body, 'transfer') - - def get(self, transfer_id): - """Show details of a volume transfer. - - :param transfer_id: The ID of the volume transfer to display. - :rtype: :class:`VolumeTransfer` - """ - return self._get("/os-volume-transfer/%s" % transfer_id, "transfer") - - def list(self, detailed=True, search_opts=None): - """Get a list of all volume transfer. - - :rtype: list of :class:`VolumeTransfer` - """ - if detailed is True: - return self._list("/os-volume-transfer/detail", "transfers") - else: - return self._list("/os-volume-transfer", "transfers") - - def delete(self, transfer_id): - """Delete a volume transfer. - - :param transfer_id: The :class:`VolumeTransfer` to delete. - """ - self._delete("/os-volume-transfer/%s" % base.getid(transfer_id)) diff --git a/awx/lib/site-packages/cinderclient/v1/volume_types.py b/awx/lib/site-packages/cinderclient/v1/volume_types.py deleted file mode 100644 index 7e1a779f66..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/volume_types.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright (c) 2011 Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -""" -Volume Type interface. -""" - -from cinderclient import base - - -class VolumeType(base.Resource): - """ - A Volume Type is the type of volume to be created - """ - def __repr__(self): - return "<VolumeType: %s>" % self.name - - def get_keys(self): - """ - Get extra specs from a volume type. - - :param vol_type: The :class:`VolumeType` to get extra specs from - """ - _resp, body = self.manager.api.client.get( - "/types/%s/extra_specs" % - base.getid(self)) - return body["extra_specs"] - - def set_keys(self, metadata): - """ - Set extra specs on a volume type. - - :param type : The :class:`VolumeType` to set extra spec on - :param metadata: A dict of key/value pairs to be set - """ - body = {'extra_specs': metadata} - return self.manager._create( - "/types/%s/extra_specs" % base.getid(self), - body, - "extra_specs", - return_raw=True) - - def unset_keys(self, keys): - """ - Unset extra specs on a volume type. - - :param type_id: The :class:`VolumeType` to unset extra spec on - :param keys: A list of keys to be unset - """ - - # NOTE(jdg): This wasn't actually doing all of the keys before - # the return in the loop resulted in ony ONE key being unset. - # since on success the return was NONE, we'll only interrupt the loop - # and return if there's an error - resp = None - for k in keys: - resp = self.manager._delete( - "/types/%s/extra_specs/%s" % ( - base.getid(self), k)) - if resp is not None: - return resp - - -class VolumeTypeManager(base.ManagerWithFind): - """ - Manage :class:`VolumeType` resources. - """ - resource_class = VolumeType - - def list(self, search_opts=None): - """ - Get a list of all volume types. - - :rtype: list of :class:`VolumeType`. - """ - return self._list("/types", "volume_types") - - def get(self, volume_type): - """ - Get a specific volume type. - - :param volume_type: The ID of the :class:`VolumeType` to get. - :rtype: :class:`VolumeType` - """ - return self._get("/types/%s" % base.getid(volume_type), "volume_type") - - def delete(self, volume_type): - """ - Delete a specific volume_type. - - :param volume_type: The name or ID of the :class:`VolumeType` to get. - """ - self._delete("/types/%s" % base.getid(volume_type)) - - def create(self, name): - """ - Creates a volume type. - - :param name: Descriptive name of the volume type - :rtype: :class:`VolumeType` - """ - - body = { - "volume_type": { - "name": name, - } - } - - return self._create("/types", body, "volume_type") diff --git a/awx/lib/site-packages/cinderclient/v1/volumes.py b/awx/lib/site-packages/cinderclient/v1/volumes.py deleted file mode 100644 index 37a4b88d13..0000000000 --- a/awx/lib/site-packages/cinderclient/v1/volumes.py +++ /dev/null @@ -1,432 +0,0 @@ -# Copyright 2011 Denali Systems, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume interface (1.1 extension). -""" - -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode -import six -from cinderclient import base - - -class Volume(base.Resource): - """A volume is an extra block level storage to the OpenStack instances.""" - def __repr__(self): - return "<Volume: %s>" % self.id - - def delete(self): - """Delete this volume.""" - self.manager.delete(self) - - def update(self, **kwargs): - """Update the display_name or display_description for this volume.""" - self.manager.update(self, **kwargs) - - def attach(self, instance_uuid, mountpoint, mode='rw'): - """Set attachment metadata. - - :param instance_uuid: uuid of the attaching instance. - :param mountpoint: mountpoint on the attaching instance. - :param mode: the access mode - """ - return self.manager.attach(self, instance_uuid, mountpoint, mode) - - def detach(self): - """Clear attachment metadata.""" - return self.manager.detach(self) - - def reserve(self, volume): - """Reserve this volume.""" - return self.manager.reserve(self) - - def unreserve(self, volume): - """Unreserve this volume.""" - return self.manager.unreserve(self) - - def begin_detaching(self, volume): - """Begin detaching volume.""" - return self.manager.begin_detaching(self) - - def roll_detaching(self, volume): - """Roll detaching volume.""" - return self.manager.roll_detaching(self) - - def initialize_connection(self, volume, connector): - """Initialize a volume connection. - - :param connector: connector dict from nova. - """ - return self.manager.initialize_connection(self, connector) - - def terminate_connection(self, volume, connector): - """Terminate a volume connection. - - :param connector: connector dict from nova. - """ - return self.manager.terminate_connection(self, connector) - - def set_metadata(self, volume, metadata): - """Set or Append metadata to a volume. - - :param volume : The :class: `Volume` to set metadata on - :param metadata: A dict of key/value pairs to set - """ - return self.manager.set_metadata(self, metadata) - - def upload_to_image(self, force, image_name, container_format, - disk_format): - """Upload a volume to image service as an image.""" - return self.manager.upload_to_image(self, force, image_name, - container_format, disk_format) - - def force_delete(self): - """Delete the specified volume ignoring its current state. - - :param volume: The UUID of the volume to force-delete. - """ - self.manager.force_delete(self) - - def reset_state(self, state): - """Update the volume with the provided state.""" - self.manager.reset_state(self, state) - - def extend(self, volume, new_size): - """Extend the size of the specified volume. - - :param volume: The UUID of the volume to extend. - :param new_size: The desired size to extend volume to. - """ - self.manager.extend(self, new_size) - - def migrate_volume(self, host, force_host_copy): - """Migrate the volume to a new host.""" - self.manager.migrate_volume(self, host, force_host_copy) - -# def migrate_volume_completion(self, old_volume, new_volume, error): -# """Complete the migration of the volume.""" -# self.manager.migrate_volume_completion(self, old_volume, -# new_volume, error) - - def update_all_metadata(self, metadata): - """Update all metadata of this volume.""" - return self.manager.update_all_metadata(self, metadata) - - def update_readonly_flag(self, volume, read_only): - """Update the read-only access mode flag of the specified volume. - - :param volume: The UUID of the volume to update. - :param read_only: The value to indicate whether to update volume to - read-only access mode. - """ - self.manager.update_readonly_flag(self, read_only) - - -class VolumeManager(base.ManagerWithFind): - """ - Manage :class:`Volume` resources. - """ - resource_class = Volume - - def create(self, size, snapshot_id=None, source_volid=None, - display_name=None, display_description=None, - volume_type=None, user_id=None, - project_id=None, availability_zone=None, - metadata=None, imageRef=None): - """ - Creates a volume. - - :param size: Size of volume in GB - :param snapshot_id: ID of the snapshot - :param display_name: Name of the volume - :param display_description: Description of the volume - :param volume_type: Type of volume - :param user_id: User id derived from context - :param project_id: Project id derived from context - :param availability_zone: Availability Zone to use - :param metadata: Optional metadata to set on volume creation - :param imageRef: reference to an image stored in glance - :param source_volid: ID of source volume to clone from - :rtype: :class:`Volume` - """ - - if metadata is None: - volume_metadata = {} - else: - volume_metadata = metadata - - body = {'volume': {'size': size, - 'snapshot_id': snapshot_id, - 'display_name': display_name, - 'display_description': display_description, - 'volume_type': volume_type, - 'user_id': user_id, - 'project_id': project_id, - 'availability_zone': availability_zone, - 'status': "creating", - 'attach_status': "detached", - 'metadata': volume_metadata, - 'imageRef': imageRef, - 'source_volid': source_volid, - }} - return self._create('/volumes', body, 'volume') - - def get(self, volume_id): - """ - Get a volume. - - :param volume_id: The ID of the volume to get. - :rtype: :class:`Volume` - """ - return self._get("/volumes/%s" % volume_id, "volume") - - def list(self, detailed=True, search_opts=None): - """ - Get a list of all volumes. - - :rtype: list of :class:`Volume` - """ - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - query_string = "?%s" % urlencode(qparams) if qparams else "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/volumes%s%s" % (detail, query_string), - "volumes") - - def delete(self, volume): - """ - Delete a volume. - - :param volume: The :class:`Volume` to delete. - """ - self._delete("/volumes/%s" % base.getid(volume)) - - def update(self, volume, **kwargs): - """ - Update the display_name or display_description for a volume. - - :param volume: The :class:`Volume` to update. - """ - if not kwargs: - return - - body = {"volume": kwargs} - - self._update("/volumes/%s" % base.getid(volume), body) - - def _action(self, action, volume, info=None, **kwargs): - """ - Perform a volume "action." - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/volumes/%s/action' % base.getid(volume) - return self.api.client.post(url, body=body) - - def attach(self, volume, instance_uuid, mountpoint, mode='rw'): - """ - Set attachment metadata. - - :param volume: The :class:`Volume` (or its ID) - you would like to attach. - :param instance_uuid: uuid of the attaching instance. - :param mountpoint: mountpoint on the attaching instance. - :param mode: the access mode. - """ - return self._action('os-attach', - volume, - {'instance_uuid': instance_uuid, - 'mountpoint': mountpoint, - 'mode': mode}) - - def detach(self, volume): - """ - Clear attachment metadata. - - :param volume: The :class:`Volume` (or its ID) - you would like to detach. - """ - return self._action('os-detach', volume) - - def reserve(self, volume): - """ - Reserve this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to reserve. - """ - return self._action('os-reserve', volume) - - def unreserve(self, volume): - """ - Unreserve this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to unreserve. - """ - return self._action('os-unreserve', volume) - - def begin_detaching(self, volume): - """ - Begin detaching this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to detach. - """ - return self._action('os-begin_detaching', volume) - - def roll_detaching(self, volume): - """ - Roll detaching this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to roll detaching. - """ - return self._action('os-roll_detaching', volume) - - def initialize_connection(self, volume, connector): - """ - Initialize a volume connection. - - :param volume: The :class:`Volume` (or its ID). - :param connector: connector dict from nova. - """ - return self._action('os-initialize_connection', volume, - {'connector': connector})[1]['connection_info'] - - def terminate_connection(self, volume, connector): - """ - Terminate a volume connection. - - :param volume: The :class:`Volume` (or its ID). - :param connector: connector dict from nova. - """ - self._action('os-terminate_connection', volume, - {'connector': connector}) - - def set_metadata(self, volume, metadata): - """ - Update/Set a volumes metadata. - - :param volume: The :class:`Volume`. - :param metadata: A list of keys to be set. - """ - body = {'metadata': metadata} - return self._create("/volumes/%s/metadata" % base.getid(volume), - body, "metadata") - - def delete_metadata(self, volume, keys): - """ - Delete specified keys from volumes metadata. - - :param volume: The :class:`Volume`. - :param keys: A list of keys to be removed. - """ - for k in keys: - self._delete("/volumes/%s/metadata/%s" % (base.getid(volume), k)) - - def upload_to_image(self, volume, force, image_name, container_format, - disk_format): - """ - Upload volume to image service as image. - - :param volume: The :class:`Volume` to upload. - """ - return self._action('os-volume_upload_image', - volume, - {'force': force, - 'image_name': image_name, - 'container_format': container_format, - 'disk_format': disk_format}) - - def force_delete(self, volume): - return self._action('os-force_delete', base.getid(volume)) - - def reset_state(self, volume, state): - """Update the provided volume with the provided state.""" - return self._action('os-reset_status', volume, {'status': state}) - - def extend(self, volume, new_size): - return self._action('os-extend', - base.getid(volume), - {'new_size': new_size}) - - def get_encryption_metadata(self, volume_id): - """ - Retrieve the encryption metadata from the desired volume. - - :param volume_id: the id of the volume to query - :return: a dictionary of volume encryption metadata - """ - return self._get("/volumes/%s/encryption" % volume_id)._info - - def migrate_volume(self, volume, host, force_host_copy): - """Migrate volume to new host. - - :param volume: The :class:`Volume` to migrate - :param host: The destination host - :param force_host_copy: Skip driver optimizations - """ - - return self._action('os-migrate_volume', - volume, - {'host': host, 'force_host_copy': force_host_copy}) - - def migrate_volume_completion(self, old_volume, new_volume, error): - """Complete the migration from the old volume to the temp new one. - - :param old_volume: The original :class:`Volume` in the migration - :param new_volume: The new temporary :class:`Volume` in the migration - :param error: Inform of an error to cause migration cleanup - """ - - new_volume_id = base.getid(new_volume) - return self._action('os-migrate_volume_completion', - old_volume, - {'new_volume': new_volume_id, 'error': error})[1] - - def update_all_metadata(self, volume, metadata): - """Update all metadata of a volume. - - :param volume: The :class:`Volume`. - :param metadata: A list of keys to be updated. - """ - body = {'metadata': metadata} - return self._update("/volumes/%s/metadata" % base.getid(volume), - body) - - def update_readonly_flag(self, volume, flag): - return self._action('os-update_readonly_flag', - base.getid(volume), - {'readonly': flag}) - - def set_bootable(self, volume, flag): - return self._action('os-set_bootable', - base.getid(volume), - {'bootable': flag}) diff --git a/awx/lib/site-packages/cinderclient/v2/__init__.py b/awx/lib/site-packages/cinderclient/v2/__init__.py deleted file mode 100644 index 75afdec8f7..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient.v2.client import Client # noqa diff --git a/awx/lib/site-packages/cinderclient/v2/availability_zones.py b/awx/lib/site-packages/cinderclient/v2/availability_zones.py deleted file mode 100644 index aec2279ab3..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/availability_zones.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2011-2013 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Availability Zone interface (v2 extension)""" - -from cinderclient import base - - -class AvailabilityZone(base.Resource): - NAME_ATTR = 'display_name' - - def __repr__(self): - return "<AvailabilityZone: %s>" % self.zoneName - - -class AvailabilityZoneManager(base.ManagerWithFind): - """Manage :class:`AvailabilityZone` resources.""" - resource_class = AvailabilityZone - - def list(self, detailed=False): - """Lists all availability zones. - - :rtype: list of :class:`AvailabilityZone` - """ - if detailed is True: - return self._list("/os-availability-zone/detail", - "availabilityZoneInfo") - else: - return self._list("/os-availability-zone", "availabilityZoneInfo") diff --git a/awx/lib/site-packages/cinderclient/v2/cgsnapshots.py b/awx/lib/site-packages/cinderclient/v2/cgsnapshots.py deleted file mode 100644 index 29513a9abf..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/cgsnapshots.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright (C) 2012 - 2014 EMC Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""cgsnapshot interface (v2 extension).""" - -import six -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - -from cinderclient import base - - -class Cgsnapshot(base.Resource): - """A cgsnapshot is snapshot of a consistency group.""" - def __repr__(self): - return "<cgsnapshot: %s>" % self.id - - def delete(self): - """Delete this cgsnapshot.""" - self.manager.delete(self) - - def update(self, **kwargs): - """Update the name or description for this cgsnapshot.""" - self.manager.update(self, **kwargs) - - -class CgsnapshotManager(base.ManagerWithFind): - """Manage :class:`Cgsnapshot` resources.""" - resource_class = Cgsnapshot - - def create(self, consistencygroup_id, name=None, description=None, - user_id=None, - project_id=None): - """Creates a cgsnapshot. - - :param consistencygroup: Name or uuid of a consistencygroup - :param name: Name of the cgsnapshot - :param description: Description of the cgsnapshot - :param user_id: User id derived from context - :param project_id: Project id derived from context - :rtype: :class:`Cgsnapshot` - """ - - body = {'cgsnapshot': {'consistencygroup_id': consistencygroup_id, - 'name': name, - 'description': description, - 'user_id': user_id, - 'project_id': project_id, - 'status': "creating", - }} - - return self._create('/cgsnapshots', body, 'cgsnapshot') - - def get(self, cgsnapshot_id): - """Get a cgsnapshot. - - :param cgsnapshot_id: The ID of the cgsnapshot to get. - :rtype: :class:`Cgsnapshot` - """ - return self._get("/cgsnapshots/%s" % cgsnapshot_id, "cgsnapshot") - - def list(self, detailed=True, search_opts=None): - """Lists all cgsnapshots. - - :rtype: list of :class:`Cgsnapshot` - """ - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - query_string = "?%s" % urlencode(qparams) if qparams else "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/cgsnapshots%s%s" % (detail, query_string), - "cgsnapshots") - - def delete(self, cgsnapshot): - """Delete a cgsnapshot. - - :param cgsnapshot: The :class:`Cgsnapshot` to delete. - """ - self._delete("/cgsnapshots/%s" % base.getid(cgsnapshot)) - - def update(self, cgsnapshot, **kwargs): - """Update the name or description for a cgsnapshot. - - :param cgsnapshot: The :class:`Cgsnapshot` to update. - """ - if not kwargs: - return - - body = {"cgsnapshot": kwargs} - - self._update("/cgsnapshots/%s" % base.getid(cgsnapshot), body) - - def _action(self, action, cgsnapshot, info=None, **kwargs): - """Perform a cgsnapshot "action." - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/cgsnapshots/%s/action' % base.getid(cgsnapshot) - return self.api.client.post(url, body=body) diff --git a/awx/lib/site-packages/cinderclient/v2/client.py b/awx/lib/site-packages/cinderclient/v2/client.py deleted file mode 100644 index f18972149c..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/client.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import client -from cinderclient.v2 import availability_zones -from cinderclient.v2 import cgsnapshots -from cinderclient.v2 import consistencygroups -from cinderclient.v2 import limits -from cinderclient.v2 import qos_specs -from cinderclient.v2 import quota_classes -from cinderclient.v2 import quotas -from cinderclient.v2 import services -from cinderclient.v2 import volumes -from cinderclient.v2 import volume_snapshots -from cinderclient.v2 import volume_types -from cinderclient.v2 import volume_encryption_types -from cinderclient.v2 import volume_backups -from cinderclient.v2 import volume_backups_restore -from cinderclient.v1 import volume_transfers - - -class Client(object): - """Top-level object to access the OpenStack Volume API. - - Create an instance with your creds:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) - - Then call methods on its managers:: - - >>> client.volumes.list() - ... - """ - - def __init__(self, username=None, api_key=None, project_id=None, - auth_url='', insecure=False, timeout=None, tenant_id=None, - proxy_tenant_id=None, proxy_token=None, region_name=None, - endpoint_type='publicURL', extensions=None, - service_type='volumev2', service_name=None, - volume_service_name=None, retries=None, http_log_debug=False, - cacert=None, auth_system='keystone', auth_plugin=None, - session=None, **kwargs): - # FIXME(comstud): Rename the api_key argument above when we - # know it's not being used as keyword argument - password = api_key - self.limits = limits.LimitsManager(self) - - # extensions - self.volumes = volumes.VolumeManager(self) - self.volume_snapshots = volume_snapshots.SnapshotManager(self) - self.volume_types = volume_types.VolumeTypeManager(self) - self.volume_encryption_types = \ - volume_encryption_types.VolumeEncryptionTypeManager(self) - self.qos_specs = qos_specs.QoSSpecsManager(self) - self.quota_classes = quota_classes.QuotaClassSetManager(self) - self.quotas = quotas.QuotaSetManager(self) - self.backups = volume_backups.VolumeBackupManager(self) - self.restores = volume_backups_restore.VolumeBackupRestoreManager(self) - self.transfers = volume_transfers.VolumeTransferManager(self) - self.services = services.ServiceManager(self) - self.consistencygroups = consistencygroups.\ - ConsistencygroupManager(self) - self.cgsnapshots = cgsnapshots.CgsnapshotManager(self) - self.availability_zones = \ - availability_zones.AvailabilityZoneManager(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - self.client = client._construct_http_client( - username=username, - password=password, - project_id=project_id, - auth_url=auth_url, - insecure=insecure, - timeout=timeout, - tenant_id=tenant_id, - proxy_tenant_id=tenant_id, - proxy_token=proxy_token, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - retries=retries, - http_log_debug=http_log_debug, - cacert=cacert, - auth_system=auth_system, - auth_plugin=auth_plugin, - session=session, - **kwargs) - - def authenticate(self): - """Authenticate against the server. - - Normally this is called automatically when you first access the API, - but you can call this method to force authentication right now. - - Returns on success; raises :exc:`exceptions.Unauthorized` if the - credentials are wrong. - """ - self.client.authenticate() - - def get_volume_api_version_from_endpoint(self): - return self.client.get_volume_api_version_from_endpoint() diff --git a/awx/lib/site-packages/cinderclient/v2/consistencygroups.py b/awx/lib/site-packages/cinderclient/v2/consistencygroups.py deleted file mode 100644 index b20cb8b6ff..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/consistencygroups.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright (C) 2012 - 2014 EMC Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Consistencygroup interface (v2 extension).""" - -import six -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - -from cinderclient import base - - -class Consistencygroup(base.Resource): - """A Consistencygroup of volumes.""" - def __repr__(self): - return "<Consistencygroup: %s>" % self.id - - def delete(self, force='False'): - """Delete this consistencygroup.""" - self.manager.delete(self, force) - - def update(self, **kwargs): - """Update the name or description for this consistencygroup.""" - self.manager.update(self, **kwargs) - - -class ConsistencygroupManager(base.ManagerWithFind): - """Manage :class:`Consistencygroup` resources.""" - resource_class = Consistencygroup - - def create(self, volume_types, name=None, - description=None, user_id=None, - project_id=None, availability_zone=None): - """Creates a consistencygroup. - - :param name: Name of the ConsistencyGroup - :param description: Description of the ConsistencyGroup - :param volume_types: Types of volume - :param user_id: User id derived from context - :param project_id: Project id derived from context - :param availability_zone: Availability Zone to use - :rtype: :class:`Consistencygroup` - """ - - body = {'consistencygroup': {'name': name, - 'description': description, - 'volume_types': volume_types, - 'user_id': user_id, - 'project_id': project_id, - 'availability_zone': availability_zone, - 'status': "creating", - }} - - return self._create('/consistencygroups', body, 'consistencygroup') - - def get(self, group_id): - """Get a consistencygroup. - - :param group_id: The ID of the consistencygroup to get. - :rtype: :class:`Consistencygroup` - """ - return self._get("/consistencygroups/%s" % group_id, - "consistencygroup") - - def list(self, detailed=True, search_opts=None): - """Lists all consistencygroups. - - :rtype: list of :class:`Consistencygroup` - """ - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - query_string = "?%s" % urlencode(qparams) if qparams else "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/consistencygroups%s%s" % (detail, query_string), - "consistencygroups") - - def delete(self, consistencygroup, force=False): - """Delete a consistencygroup. - - :param Consistencygroup: The :class:`Consistencygroup` to delete. - """ - body = {'consistencygroup': {'force': force}} - self.run_hooks('modify_body_for_action', body, 'consistencygroup') - url = '/consistencygroups/%s/delete' % base.getid(consistencygroup) - return self.api.client.post(url, body=body) - - def update(self, consistencygroup, **kwargs): - """Update the name or description for a consistencygroup. - - :param Consistencygroup: The :class:`Consistencygroup` to update. - """ - if not kwargs: - return - - body = {"consistencygroup": kwargs} - - self._update("/consistencygroups/%s" % base.getid(consistencygroup), - body) - - def _action(self, action, consistencygroup, info=None, **kwargs): - """Perform a consistencygroup "action." - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/consistencygroups/%s/action' % base.getid(consistencygroup) - return self.api.client.post(url, body=body) diff --git a/awx/lib/site-packages/cinderclient/v2/contrib/__init__.py b/awx/lib/site-packages/cinderclient/v2/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/cinderclient/v2/contrib/list_extensions.py b/awx/lib/site-packages/cinderclient/v2/contrib/list_extensions.py deleted file mode 100644 index e457e8bb99..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/contrib/list_extensions.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import base -from cinderclient import utils - - -class ListExtResource(base.Resource): - @property - def summary(self): - descr = self.description.strip() - if not descr: - return '??' - lines = descr.split("\n") - if len(lines) == 1: - return lines[0] - else: - return lines[0] + "..." - - -class ListExtManager(base.Manager): - resource_class = ListExtResource - - def show_all(self): - return self._list("/extensions", 'extensions') - - -@utils.service_type('volumev2') -def do_list_extensions(client, _args): - """ - Lists all available os-api extensions. - """ - extensions = client.list_extensions.show_all() - fields = ["Name", "Summary", "Alias", "Updated"] - utils.print_list(extensions, fields) diff --git a/awx/lib/site-packages/cinderclient/v2/limits.py b/awx/lib/site-packages/cinderclient/v2/limits.py deleted file mode 100644 index 512a58dec6..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/limits.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from cinderclient import base - - -class Limits(base.Resource): - """A collection of RateLimit and AbsoluteLimit objects.""" - - def __repr__(self): - return "<Limits>" - - @property - def absolute(self): - for (name, value) in list(self._info['absolute'].items()): - yield AbsoluteLimit(name, value) - - @property - def rate(self): - for group in self._info['rate']: - uri = group['uri'] - regex = group['regex'] - for rate in group['limit']: - yield RateLimit(rate['verb'], uri, regex, rate['value'], - rate['remaining'], rate['unit'], - rate['next-available']) - - -class RateLimit(object): - """Data model that represents a flattened view of a single rate limit.""" - - def __init__(self, verb, uri, regex, value, remain, - unit, next_available): - self.verb = verb - self.uri = uri - self.regex = regex - self.value = value - self.remain = remain - self.unit = unit - self.next_available = next_available - - def __eq__(self, other): - return self.uri == other.uri \ - and self.regex == other.regex \ - and self.value == other.value \ - and self.verb == other.verb \ - and self.remain == other.remain \ - and self.unit == other.unit \ - and self.next_available == other.next_available - - def __repr__(self): - return "<RateLimit: method=%s uri=%s>" % (self.verb, self.uri) - - -class AbsoluteLimit(object): - """Data model that represents a single absolute limit.""" - - def __init__(self, name, value): - self.name = name - self.value = value - - def __eq__(self, other): - return self.value == other.value and self.name == other.name - - def __repr__(self): - return "<AbsoluteLimit: name=%s>" % (self.name) - - -class LimitsManager(base.Manager): - """Manager object used to interact with limits resource.""" - - resource_class = Limits - - def get(self): - """Get a specific extension. - - :rtype: :class:`Limits` - """ - return self._get("/limits", "limits") diff --git a/awx/lib/site-packages/cinderclient/v2/qos_specs.py b/awx/lib/site-packages/cinderclient/v2/qos_specs.py deleted file mode 100644 index b4e4272ae2..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/qos_specs.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (c) 2013 eBay Inc. -# Copyright (c) OpenStack LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -""" -QoS Specs interface. -""" - -from cinderclient import base - - -class QoSSpecs(base.Resource): - """QoS specs entity represents quality-of-service parameters/requirements. - - A QoS specs is a set of parameters or requirements for quality-of-service - purpose, which can be associated with volume types (for now). In future, - QoS specs may be extended to be associated other entities, such as single - volume. - """ - def __repr__(self): - return "<QoSSpecs: %s>" % self.name - - def delete(self): - return self.manager.delete(self) - - -class QoSSpecsManager(base.ManagerWithFind): - """ - Manage :class:`QoSSpecs` resources. - """ - resource_class = QoSSpecs - - def list(self): - """Get a list of all qos specs. - - :rtype: list of :class:`QoSSpecs`. - """ - return self._list("/qos-specs", "qos_specs") - - def get(self, qos_specs): - """Get a specific qos specs. - - :param qos_specs: The ID of the :class:`QoSSpecs` to get. - :rtype: :class:`QoSSpecs` - """ - return self._get("/qos-specs/%s" % base.getid(qos_specs), "qos_specs") - - def delete(self, qos_specs, force=False): - """Delete a specific qos specs. - - :param qos_specs: The ID of the :class:`QoSSpecs` to be removed. - :param force: Flag that indicates whether to delete target qos specs - if it was in-use. - """ - self._delete("/qos-specs/%s?force=%s" % - (base.getid(qos_specs), force)) - - def create(self, name, specs): - """Create a qos specs. - - :param name: Descriptive name of the qos specs, must be unique - :param specs: A dict of key/value pairs to be set - :rtype: :class:`QoSSpecs` - """ - - body = { - "qos_specs": { - "name": name, - } - } - - body["qos_specs"].update(specs) - return self._create("/qos-specs", body, "qos_specs") - - def set_keys(self, qos_specs, specs): - """Update a qos specs with new specifications. - - :param qos_specs: The ID of qos specs - :param specs: A dict of key/value pairs to be set - :rtype: :class:`QoSSpecs` - """ - - body = { - "qos_specs": {} - } - - body["qos_specs"].update(specs) - return self._update("/qos-specs/%s" % qos_specs, body) - - def unset_keys(self, qos_specs, specs): - """Update a qos specs with new specifications. - - :param qos_specs: The ID of qos specs - :param specs: A list of key to be unset - :rtype: :class:`QoSSpecs` - """ - - body = {'keys': specs} - - return self._update("/qos-specs/%s/delete_keys" % qos_specs, - body) - - def get_associations(self, qos_specs): - """Get associated entities of a qos specs. - - :param qos_specs: The id of the :class: `QoSSpecs` - :return: a list of entities that associated with specific qos specs. - """ - return self._list("/qos-specs/%s/associations" % base.getid(qos_specs), - "qos_associations") - - def associate(self, qos_specs, vol_type_id): - """Associate a volume type with specific qos specs. - - :param qos_specs: The qos specs to be associated with - :param vol_type_id: The volume type id to be associated with - """ - self.api.client.get("/qos-specs/%s/associate?vol_type_id=%s" % - (base.getid(qos_specs), vol_type_id)) - - def disassociate(self, qos_specs, vol_type_id): - """Disassociate qos specs from volume type. - - :param qos_specs: The qos specs to be associated with - :param vol_type_id: The volume type id to be associated with - """ - self.api.client.get("/qos-specs/%s/disassociate?vol_type_id=%s" % - (base.getid(qos_specs), vol_type_id)) - - def disassociate_all(self, qos_specs): - """Disassociate all entities from specific qos specs. - - :param qos_specs: The qos specs to be associated with - """ - self.api.client.get("/qos-specs/%s/disassociate_all" % - base.getid(qos_specs)) diff --git a/awx/lib/site-packages/cinderclient/v2/quota_classes.py b/awx/lib/site-packages/cinderclient/v2/quota_classes.py deleted file mode 100644 index bf80db0f6f..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/quota_classes.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import base - - -class QuotaClassSet(base.Resource): - - @property - def id(self): - """Needed by base.Resource to self-refresh and be indexed.""" - return self.class_name - - def update(self, *args, **kwargs): - self.manager.update(self.class_name, *args, **kwargs) - - -class QuotaClassSetManager(base.Manager): - resource_class = QuotaClassSet - - def get(self, class_name): - return self._get("/os-quota-class-sets/%s" % (class_name), - "quota_class_set") - - def update(self, class_name, **updates): - body = {'quota_class_set': {'class_name': class_name}} - - for update in updates: - body['quota_class_set'][update] = updates[update] - - self._update('/os-quota-class-sets/%s' % (class_name), body) diff --git a/awx/lib/site-packages/cinderclient/v2/quotas.py b/awx/lib/site-packages/cinderclient/v2/quotas.py deleted file mode 100644 index fbc691450c..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/quotas.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from cinderclient import base - - -class QuotaSet(base.Resource): - - @property - def id(self): - """Needed by base.Resource to self-refresh and be indexed.""" - return self.tenant_id - - def update(self, *args, **kwargs): - return self.manager.update(self.tenant_id, *args, **kwargs) - - -class QuotaSetManager(base.Manager): - resource_class = QuotaSet - - def get(self, tenant_id, usage=False): - if hasattr(tenant_id, 'tenant_id'): - tenant_id = tenant_id.tenant_id - return self._get("/os-quota-sets/%s?usage=%s" % (tenant_id, usage), - "quota_set") - - def update(self, tenant_id, **updates): - body = {'quota_set': {'tenant_id': tenant_id}} - - for update in updates: - body['quota_set'][update] = updates[update] - - result = self._update('/os-quota-sets/%s' % (tenant_id), body) - return self.resource_class(self, result['quota_set'], loaded=True) - - def defaults(self, tenant_id): - return self._get('/os-quota-sets/%s/defaults' % tenant_id, - 'quota_set') - - def delete(self, tenant_id): - if hasattr(tenant_id, 'tenant_id'): - tenant_id = tenant_id.tenant_id - return self._delete("/os-quota-sets/%s" % tenant_id) diff --git a/awx/lib/site-packages/cinderclient/v2/services.py b/awx/lib/site-packages/cinderclient/v2/services.py deleted file mode 100644 index 3bc4b3b43e..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/services.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -service interface -""" -from cinderclient import base - - -class Service(base.Resource): - - def __repr__(self): - return "<Service: %s>" % self.service - - -class ServiceManager(base.ManagerWithFind): - resource_class = Service - - def list(self, host=None, binary=None): - """ - Describes service list for host. - - :param host: destination host name. - :param binary: service binary. - """ - url = "/os-services" - filters = [] - if host: - filters.append("host=%s" % host) - if binary: - filters.append("binary=%s" % binary) - if filters: - url = "%s?%s" % (url, "&".join(filters)) - return self._list(url, "services") - - def enable(self, host, binary): - """Enable the service specified by hostname and binary.""" - body = {"host": host, "binary": binary} - result = self._update("/os-services/enable", body) - return self.resource_class(self, result) - - def disable(self, host, binary): - """Disable the service specified by hostname and binary.""" - body = {"host": host, "binary": binary} - result = self._update("/os-services/disable", body) - return self.resource_class(self, result) - - def disable_log_reason(self, host, binary, reason): - """Disable the service with reason.""" - body = {"host": host, "binary": binary, "disabled_reason": reason} - result = self._update("/os-services/disable-log-reason", body) - return self.resource_class(self, result) diff --git a/awx/lib/site-packages/cinderclient/v2/shell.py b/awx/lib/site-packages/cinderclient/v2/shell.py deleted file mode 100644 index 41972a1e8f..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/shell.py +++ /dev/null @@ -1,1898 +0,0 @@ -# Copyright (c) 2013-2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import print_function - -import argparse -import copy -import os -import sys -import time - -import six - -from cinderclient import exceptions -from cinderclient import utils -from cinderclient.openstack.common import strutils -from cinderclient.v2 import availability_zones - - -def _poll_for_status(poll_fn, obj_id, action, final_ok_states, - poll_period=5, show_progress=True): - """Blocks while an action occurs. Periodically shows progress.""" - def print_progress(progress): - if show_progress: - msg = ('\rInstance %(action)s... %(progress)s%% complete' - % dict(action=action, progress=progress)) - else: - msg = '\rInstance %(action)s...' % dict(action=action) - - sys.stdout.write(msg) - sys.stdout.flush() - - print() - while True: - obj = poll_fn(obj_id) - status = obj.status.lower() - progress = getattr(obj, 'progress', None) or 0 - if status in final_ok_states: - print_progress(100) - print("\nFinished") - break - elif status == "error": - print("\nError %(action)s instance" % {'action': action}) - break - else: - print_progress(progress) - time.sleep(poll_period) - - -def _find_volume_snapshot(cs, snapshot): - """Gets a volume snapshot by name or ID.""" - return utils.find_resource(cs.volume_snapshots, snapshot) - - -def _find_backup(cs, backup): - """Gets a backup by name or ID.""" - return utils.find_resource(cs.backups, backup) - - -def _find_consistencygroup(cs, consistencygroup): - """Gets a consistencygroup by name or ID.""" - return utils.find_resource(cs.consistencygroups, consistencygroup) - - -def _find_cgsnapshot(cs, cgsnapshot): - """Gets a cgsnapshot by name or ID.""" - return utils.find_resource(cs.cgsnapshots, cgsnapshot) - - -def _find_transfer(cs, transfer): - """Gets a transfer by name or ID.""" - return utils.find_resource(cs.transfers, transfer) - - -def _find_qos_specs(cs, qos_specs): - """Gets a qos specs by ID.""" - return utils.find_resource(cs.qos_specs, qos_specs) - - -def _print_volume_snapshot(snapshot): - utils.print_dict(snapshot._info) - - -def _print_volume_image(image): - utils.print_dict(image[1]['os-volume_upload_image']) - - -def _translate_keys(collection, convert): - for item in collection: - keys = item.__dict__ - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _translate_volume_keys(collection): - convert = [('volumeType', 'volume_type'), - ('os-vol-tenant-attr:tenant_id', 'tenant_id')] - _translate_keys(collection, convert) - - -def _translate_volume_snapshot_keys(collection): - convert = [('volumeId', 'volume_id')] - _translate_keys(collection, convert) - - -def _translate_availability_zone_keys(collection): - convert = [('zoneName', 'name'), ('zoneState', 'status')] - _translate_keys(collection, convert) - - -def _extract_metadata(args): - metadata = {} - for metadatum in args.metadata: - # unset doesn't require a val, so we have the if/else - if '=' in metadatum: - (key, value) = metadatum.split('=', 1) - else: - key = metadatum - value = None - - metadata[key] = value - return metadata - - -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Shows details for all tenants. Admin only.') -@utils.arg('--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@utils.arg('--name', - metavar='<name>', - default=None, - help='Filters results by a name. OPTIONAL: Default=None.') -@utils.arg('--display-name', - help=argparse.SUPPRESS) -@utils.arg('--status', - metavar='<status>', - default=None, - help='Filters results by a status. OPTIONAL: Default=None.') -@utils.arg('--metadata', - type=str, - nargs='*', - metavar='<key=value>', - help='Filters results by a metadata key and value pair. ' - 'OPTIONAL: Default=None.', - default=None) -@utils.arg('--marker', - metavar='<marker>', - default=None, - help='Begin returning volumes that appear later in the volume ' - 'list than that represented by this volume id. ' - 'OPTIONAL: Default=None.') -@utils.arg('--limit', - metavar='<limit>', - default=None, - help='Maximum number of volumes to return. OPTIONAL: Default=None.') -@utils.arg('--sort_key', - metavar='<sort_key>', - default=None, - help='Key to be sorted, should be (`id`, `status`, `size`, ' - '`availability_zone`, `name`, `bootable`, `created_at`). ' - 'OPTIONAL: Default=None.') -@utils.arg('--sort_dir', - metavar='<sort_dir>', - default=None, - help='Sort direction, should be `desc` or `asc`. ' - 'OPTIONAL: Default=None.') -@utils.service_type('volumev2') -def do_list(cs, args): - """Lists all volumes.""" - # NOTE(thingee): Backwards-compatibility with v1 args - if args.display_name is not None: - args.name = args.display_name - - all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants)) - search_opts = { - 'all_tenants': all_tenants, - 'name': args.name, - 'status': args.status, - 'metadata': _extract_metadata(args) if args.metadata else None, - } - volumes = cs.volumes.list(search_opts=search_opts, marker=args.marker, - limit=args.limit, sort_key=args.sort_key, - sort_dir=args.sort_dir) - _translate_volume_keys(volumes) - - # Create a list of servers to which the volume is attached - for vol in volumes: - servers = [s.get('server_id') for s in vol.attachments] - setattr(vol, 'attached_to', ','.join(map(str, servers))) - - if all_tenants: - key_list = ['ID', 'Tenant ID', 'Status', 'Name', - 'Size', 'Volume Type', 'Bootable', 'Attached to'] - else: - key_list = ['ID', 'Status', 'Name', - 'Size', 'Volume Type', 'Bootable', 'Attached to'] - utils.print_list(volumes, key_list) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume.') -@utils.service_type('volumev2') -def do_show(cs, args): - """Shows volume details.""" - info = dict() - volume = utils.find_volume(cs, args.volume) - info.update(volume._info) - - info.pop('links', None) - utils.print_dict(info) - - -class CheckSizeArgForCreate(argparse.Action): - def __call__(self, parser, args, values, option_string=None): - if (values or args.snapshot_id or args.source_volid - or args.source_replica) is None: - parser.error('Size is a required parameter if snapshot ' - 'or source volume is not specified.') - setattr(args, self.dest, values) - - -@utils.arg('size', - metavar='<size>', - nargs='?', - type=int, - action=CheckSizeArgForCreate, - help='Size of volume, in GBs. (Required unless ' - 'snapshot-id/source-volid is specified).') -@utils.arg('--consisgroup-id', - metavar='<consistencygroup-id>', - default=None, - help='ID of a consistency group where the new volume belongs to. ' - 'Default=None.') -@utils.arg('--snapshot-id', - metavar='<snapshot-id>', - default=None, - help='Creates volume from snapshot ID. Default=None.') -@utils.arg('--snapshot_id', - help=argparse.SUPPRESS) -@utils.arg('--source-volid', - metavar='<source-volid>', - default=None, - help='Creates volume from volume ID. Default=None.') -@utils.arg('--source_volid', - help=argparse.SUPPRESS) -@utils.arg('--source-replica', - metavar='<source-replica>', - default=None, - help='Creates volume from replicated volume ID. Default=None.') -@utils.arg('--image-id', - metavar='<image-id>', - default=None, - help='Creates volume from image ID. Default=None.') -@utils.arg('--image_id', - help=argparse.SUPPRESS) -@utils.arg('--name', - metavar='<name>', - default=None, - help='Volume name. Default=None.') -@utils.arg('--display-name', - help=argparse.SUPPRESS) -@utils.arg('--display_name', - help=argparse.SUPPRESS) -@utils.arg('--description', - metavar='<description>', - default=None, - help='Volume description. Default=None.') -@utils.arg('--display-description', - help=argparse.SUPPRESS) -@utils.arg('--display_description', - help=argparse.SUPPRESS) -@utils.arg('--volume-type', - metavar='<volume-type>', - default=None, - help='Volume type. Default=None.') -@utils.arg('--volume_type', - help=argparse.SUPPRESS) -@utils.arg('--availability-zone', - metavar='<availability-zone>', - default=None, - help='Availability zone for volume. Default=None.') -@utils.arg('--availability_zone', - help=argparse.SUPPRESS) -@utils.arg('--metadata', - type=str, - nargs='*', - metavar='<key=value>', - help='Metadata key and value pairs. Default=None.', - default=None) -@utils.arg('--hint', - metavar='<key=value>', - dest='scheduler_hints', - action='append', - default=[], - help='Scheduler hint, like in nova.') -@utils.service_type('volumev2') -def do_create(cs, args): - """Creates a volume.""" - # NOTE(thingee): Backwards-compatibility with v1 args - if args.display_name is not None: - args.name = args.display_name - - if args.display_description is not None: - args.description = args.display_description - - volume_metadata = None - if args.metadata is not None: - volume_metadata = _extract_metadata(args) - - #NOTE(N.S.): take this piece from novaclient - hints = {} - if args.scheduler_hints: - for hint in args.scheduler_hints: - key, _sep, value = hint.partition('=') - # NOTE(vish): multiple copies of same hint will - # result in a list of values - if key in hints: - if isinstance(hints[key], six.string_types): - hints[key] = [hints[key]] - hints[key] += [value] - else: - hints[key] = value - #NOTE(N.S.): end of taken piece - - volume = cs.volumes.create(args.size, - args.consisgroup_id, - args.snapshot_id, - args.source_volid, - args.name, - args.description, - args.volume_type, - availability_zone=args.availability_zone, - imageRef=args.image_id, - metadata=volume_metadata, - scheduler_hints=hints, - source_replica=args.source_replica) - - info = dict() - volume = cs.volumes.get(volume.id) - info.update(volume._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('volume', - metavar='<volume>', nargs='+', - help='Name or ID of volume or volumes to delete.') -@utils.service_type('volumev2') -def do_delete(cs, args): - """Removes one or more volumes.""" - failure_count = 0 - for volume in args.volume: - try: - utils.find_volume(cs, volume).delete() - except Exception as e: - failure_count += 1 - print("Delete for volume %s failed: %s" % (volume, e)) - if failure_count == len(args.volume): - raise exceptions.CommandError("Unable to delete any of specified " - "volumes.") - - -@utils.arg('volume', - metavar='<volume>', nargs='+', - help='Name or ID of volume or volumes to delete.') -@utils.service_type('volumev2') -def do_force_delete(cs, args): - """Attempts force-delete of volume, regardless of state.""" - failure_count = 0 - for volume in args.volume: - try: - utils.find_volume(cs, volume).force_delete() - except Exception as e: - failure_count += 1 - print("Delete for volume %s failed: %s" % (volume, e)) - if failure_count == len(args.volume): - raise exceptions.CommandError("Unable to force delete any of " - "specified volumes.") - - -@utils.arg('volume', metavar='<volume>', nargs='+', - help='Name or ID of volume to modify.') -@utils.arg('--state', metavar='<state>', default='available', - help=('The state to assign to the volume. Valid values are ' - '"available," "error," "creating," "deleting," and ' - '"error_deleting." ' - 'Default=available.')) -@utils.service_type('volumev2') -def do_reset_state(cs, args): - """Explicitly updates the volume state.""" - failure_flag = False - - for volume in args.volume: - try: - utils.find_volume(cs, volume).reset_state(args.state) - except Exception as e: - failure_flag = True - msg = "Reset state for volume %s failed: %s" % (volume, e) - print(msg) - - if failure_flag: - msg = "Unable to reset the state for the specified volume(s)." - raise exceptions.CommandError(msg) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume to rename.') -@utils.arg('name', - nargs='?', - metavar='<name>', - help='New name for volume.') -@utils.arg('--description', metavar='<description>', - help='Volume description. Default=None.', - default=None) -@utils.arg('--display-description', - help=argparse.SUPPRESS) -@utils.arg('--display_description', - help=argparse.SUPPRESS) -@utils.service_type('volumev2') -def do_rename(cs, args): - """Renames a volume.""" - kwargs = {} - - if args.name is not None: - kwargs['name'] = args.name - if args.display_description is not None: - kwargs['description'] = args.display_description - elif args.description is not None: - kwargs['description'] = args.description - - if not any(kwargs): - msg = 'Must supply either name or description.' - raise exceptions.ClientException(code=1, message=msg) - - utils.find_volume(cs, args.volume).update(**kwargs) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume for which to update metadata.') -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='Metadata key and value pair to set or unset. ' - 'For unset, specify only the key.') -@utils.service_type('volumev2') -def do_metadata(cs, args): - """Sets or deletes volume metadata.""" - volume = utils.find_volume(cs, args.volume) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.volumes.set_metadata(volume, metadata) - elif args.action == 'unset': - # NOTE(zul): Make sure py2/py3 sorting is the same - cs.volumes.delete_metadata(volume, sorted(metadata.keys(), - reverse=True)) - - -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Shows details for all tenants. Admin only.') -@utils.arg('--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@utils.arg('--name', - metavar='<name>', - default=None, - help='Filters results by a name. Default=None.') -@utils.arg('--display-name', - help=argparse.SUPPRESS) -@utils.arg('--display_name', - help=argparse.SUPPRESS) -@utils.arg('--status', - metavar='<status>', - default=None, - help='Filters results by a status. Default=None.') -@utils.arg('--volume-id', - metavar='<volume-id>', - default=None, - help='Filters results by a volume ID. Default=None.') -@utils.arg('--volume_id', - help=argparse.SUPPRESS) -@utils.service_type('volumev2') -def do_snapshot_list(cs, args): - """Lists all snapshots.""" - all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants)) - - if args.display_name is not None: - args.name = args.display_name - - search_opts = { - 'all_tenants': all_tenants, - 'display_name': args.name, - 'status': args.status, - 'volume_id': args.volume_id, - } - - snapshots = cs.volume_snapshots.list(search_opts=search_opts) - _translate_volume_snapshot_keys(snapshots) - utils.print_list(snapshots, - ['ID', 'Volume ID', 'Status', 'Name', 'Size']) - - -@utils.arg('snapshot', - metavar='<snapshot>', - help='Name or ID of snapshot.') -@utils.service_type('volumev2') -def do_snapshot_show(cs, args): - """Shows snapshot details.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - _print_volume_snapshot(snapshot) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume to snapshot.') -@utils.arg('--force', - metavar='<True|False>', - help='Allows or disallows snapshot of ' - 'a volume when the volume is attached to an instance. ' - 'If set to True, ignores the current status of the ' - 'volume when attempting to snapshot it rather ' - 'than forcing it to be available. ' - 'Default=False.', - default=False) -@utils.arg('--name', - metavar='<name>', - default=None, - help='Snapshot name. Default=None.') -@utils.arg('--display-name', - help=argparse.SUPPRESS) -@utils.arg('--display_name', - help=argparse.SUPPRESS) -@utils.arg('--description', - metavar='<description>', - default=None, - help='Snapshot description. Default=None.') -@utils.arg('--display-description', - help=argparse.SUPPRESS) -@utils.arg('--display_description', - help=argparse.SUPPRESS) -@utils.service_type('volumev2') -def do_snapshot_create(cs, args): - """Creates a snapshot.""" - if args.display_name is not None: - args.name = args.display_name - - if args.display_description is not None: - args.description = args.display_description - - volume = utils.find_volume(cs, args.volume) - snapshot = cs.volume_snapshots.create(volume.id, - args.force, - args.name, - args.description) - _print_volume_snapshot(snapshot) - - -@utils.arg('snapshot', - metavar='<snapshot>', nargs='+', - help='Name or ID of the snapshot(s) to delete.') -@utils.service_type('volumev2') -def do_snapshot_delete(cs, args): - """Removes one or more snapshots.""" - failure_count = 0 - for snapshot in args.snapshot: - try: - _find_volume_snapshot(cs, snapshot).delete() - except Exception as e: - failure_count += 1 - print("Delete for snapshot %s failed: %s" % (snapshot, e)) - if failure_count == len(args.snapshot): - raise exceptions.CommandError("Unable to delete any of the specified " - "snapshots.") - - -@utils.arg('snapshot', metavar='<snapshot>', - help='Name or ID of snapshot.') -@utils.arg('name', nargs='?', metavar='<name>', - help='New name for snapshot.') -@utils.arg('--description', metavar='<description>', - help='Snapshot description. Default=None.', - default=None) -@utils.arg('--display-description', - help=argparse.SUPPRESS) -@utils.arg('--display_description', - help=argparse.SUPPRESS) -@utils.service_type('volumev2') -def do_snapshot_rename(cs, args): - """Renames a snapshot.""" - kwargs = {} - - if args.name is not None: - kwargs['name'] = args.name - - if args.description is not None: - kwargs['description'] = args.description - elif args.display_description is not None: - kwargs['description'] = args.display_description - - if not any(kwargs): - msg = 'Must supply either name or description.' - raise exceptions.ClientException(code=1, message=msg) - - _find_volume_snapshot(cs, args.snapshot).update(**kwargs) - - -@utils.arg('snapshot', metavar='<snapshot>', nargs='+', - help='Name or ID of snapshot to modify.') -@utils.arg('--state', metavar='<state>', - default='available', - help=('The state to assign to the snapshot. Valid values are ' - '"available," "error," "creating," "deleting," and ' - '"error_deleting." ' - 'Default is "available."')) -@utils.service_type('volumev2') -def do_snapshot_reset_state(cs, args): - """Explicitly updates the snapshot state.""" - failure_count = 0 - - single = (len(args.snapshot) == 1) - - for snapshot in args.snapshot: - try: - _find_volume_snapshot(cs, snapshot).reset_state(args.state) - except Exception as e: - failure_count += 1 - msg = "Reset state for snapshot %s failed: %s" % (snapshot, e) - if not single: - print(msg) - - if failure_count == len(args.snapshot): - if not single: - msg = ("Unable to reset the state for any of the specified " - "snapshots.") - raise exceptions.CommandError(msg) - - -def _print_volume_type_list(vtypes): - utils.print_list(vtypes, ['ID', 'Name']) - - -@utils.service_type('volumev2') -def do_type_list(cs, args): - """Lists available 'volume types'.""" - vtypes = cs.volume_types.list() - _print_volume_type_list(vtypes) - - -@utils.service_type('volumev2') -def do_extra_specs_list(cs, args): - """Lists current volume types and extra specs.""" - vtypes = cs.volume_types.list() - utils.print_list(vtypes, ['ID', 'Name', 'extra_specs']) - - -@utils.arg('name', - metavar='<name>', - help="Name of new volume type.") -@utils.service_type('volumev2') -def do_type_create(cs, args): - """Creates a volume type.""" - vtype = cs.volume_types.create(args.name) - _print_volume_type_list([vtype]) - - -@utils.arg('id', - metavar='<id>', - help="ID of volume type to delete.") -@utils.service_type('volumev2') -def do_type_delete(cs, args): - """Deletes a volume type.""" - cs.volume_types.delete(args.id) - - -@utils.arg('vtype', - metavar='<vtype>', - help="Name or ID of volume type.") -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='The extra specs key and value pair to set or unset. ' - 'For unset, specify only the key.') -@utils.service_type('volumev2') -def do_type_key(cs, args): - """Sets or unsets extra_spec for a volume type.""" - vtype = _find_volume_type(cs, args.vtype) - keypair = _extract_metadata(args) - - if args.action == 'set': - vtype.set_keys(keypair) - elif args.action == 'unset': - vtype.unset_keys(list(keypair)) - - -@utils.service_type('volumev2') -def do_endpoints(cs, args): - """Discovers endpoints registered by authentication service.""" - catalog = cs.client.service_catalog.catalog - for e in catalog['serviceCatalog']: - utils.print_dict(e['endpoints'][0], e['name']) - - -@utils.service_type('volumev2') -def do_credentials(cs, args): - """Shows user credentials returned from auth.""" - catalog = cs.client.service_catalog.catalog - utils.print_dict(catalog['user'], "User Credentials") - utils.print_dict(catalog['token'], "Token") - - -_quota_resources = ['volumes', 'snapshots', 'gigabytes'] -_quota_infos = ['Type', 'In_use', 'Reserved', 'Limit'] - - -def _quota_show(quotas): - quota_dict = {} - for resource in quotas._info: - good_name = False - for name in _quota_resources: - if resource.startswith(name): - good_name = True - if not good_name: - continue - quota_dict[resource] = getattr(quotas, resource, None) - utils.print_dict(quota_dict) - - -def _quota_usage_show(quotas): - quota_list = [] - for resource in quotas._info.keys(): - good_name = False - for name in _quota_resources: - if resource.startswith(name): - good_name = True - if not good_name: - continue - quota_info = getattr(quotas, resource, None) - quota_info['Type'] = resource - quota_info = dict((k.capitalize(), v) for k, v in quota_info.items()) - quota_list.append(quota_info) - utils.print_list(quota_list, _quota_infos) - - -def _quota_update(manager, identifier, args): - updates = {} - for resource in _quota_resources: - val = getattr(args, resource, None) - if val is not None: - if args.volume_type: - resource = resource + '_%s' % args.volume_type - updates[resource] = val - - if updates: - _quota_show(manager.update(identifier, **updates)) - - -@utils.arg('tenant', - metavar='<tenant_id>', - help='ID of tenant for which to list quotas.') -@utils.service_type('volumev2') -def do_quota_show(cs, args): - """Lists quotas for a tenant.""" - - _quota_show(cs.quotas.get(args.tenant)) - - -@utils.arg('tenant', metavar='<tenant_id>', - help='ID of tenant for which to list quota usage.') -@utils.service_type('volumev2') -def do_quota_usage(cs, args): - """Lists quota usage for a tenant.""" - - _quota_usage_show(cs.quotas.get(args.tenant, usage=True)) - - -@utils.arg('tenant', - metavar='<tenant_id>', - help='ID of tenant for which to list quota defaults.') -@utils.service_type('volumev2') -def do_quota_defaults(cs, args): - """Lists default quotas for a tenant.""" - - _quota_show(cs.quotas.defaults(args.tenant)) - - -@utils.arg('tenant', - metavar='<tenant_id>', - help='ID of tenant for which to set quotas.') -@utils.arg('--volumes', - metavar='<volumes>', - type=int, default=None, - help='The new "volumes" quota value. Default=None.') -@utils.arg('--snapshots', - metavar='<snapshots>', - type=int, default=None, - help='The new "snapshots" quota value. Default=None.') -@utils.arg('--gigabytes', - metavar='<gigabytes>', - type=int, default=None, - help='The new "gigabytes" quota value. Default=None.') -@utils.arg('--volume-type', - metavar='<volume_type_name>', - default=None, - help='Volume type. Default=None.') -@utils.service_type('volumev2') -def do_quota_update(cs, args): - """Updates quotas for a tenant.""" - - _quota_update(cs.quotas, args.tenant, args) - - -@utils.arg('tenant', metavar='<tenant_id>', - help='UUID of tenant to delete the quotas for.') -@utils.service_type('volume') -def do_quota_delete(cs, args): - """Delete the quotas for a tenant.""" - - cs.quotas.delete(args.tenant) - - -@utils.arg('class_name', - metavar='<class>', - help='Name of quota class for which to list quotas.') -@utils.service_type('volumev2') -def do_quota_class_show(cs, args): - """Lists quotas for a quota class.""" - - _quota_show(cs.quota_classes.get(args.class_name)) - - -@utils.arg('class-name', - metavar='<class-name>', - help='Name of quota class for which to set quotas.') -@utils.arg('--volumes', - metavar='<volumes>', - type=int, default=None, - help='The new "volumes" quota value. Default=None.') -@utils.arg('--snapshots', - metavar='<snapshots>', - type=int, default=None, - help='The new "snapshots" quota value. Default=None.') -@utils.arg('--gigabytes', - metavar='<gigabytes>', - type=int, default=None, - help='The new "gigabytes" quota value. Default=None.') -@utils.arg('--volume-type', - metavar='<volume_type_name>', - default=None, - help='Volume type. Default=None.') -@utils.service_type('volumev2') -def do_quota_class_update(cs, args): - """Updates quotas for a quota class.""" - - _quota_update(cs.quota_classes, args.class_name, args) - - -@utils.service_type('volumev2') -def do_absolute_limits(cs, args): - """Lists absolute limits for a user.""" - limits = cs.limits.get().absolute - columns = ['Name', 'Value'] - utils.print_list(limits, columns) - - -@utils.service_type('volumev2') -def do_rate_limits(cs, args): - """Lists rate limits for a user.""" - limits = cs.limits.get().rate - columns = ['Verb', 'URI', 'Value', 'Remain', 'Unit', 'Next_Available'] - utils.print_list(limits, columns) - - -def _find_volume_type(cs, vtype): - """Gets a volume type by name or ID.""" - return utils.find_resource(cs.volume_types, vtype) - - -@utils.arg('volume', - metavar='<volume>', - help='Name or ID of volume to snapshot.') -@utils.arg('--force', - metavar='<True|False>', - help='Enables or disables upload of ' - 'a volume that is attached to an instance. ' - 'Default=False.', - default=False) -@utils.arg('--container-format', - metavar='<container-format>', - help='Container format type. ' - 'Default is bare.', - default='bare') -@utils.arg('--container_format', - help=argparse.SUPPRESS) -@utils.arg('--disk-format', - metavar='<disk-format>', - help='Disk format type. ' - 'Default is raw.', - default='raw') -@utils.arg('--disk_format', - help=argparse.SUPPRESS) -@utils.arg('image_name', - metavar='<image-name>', - help='The new image name.') -@utils.arg('--image_name', - help=argparse.SUPPRESS) -@utils.service_type('volumev2') -def do_upload_to_image(cs, args): - """Uploads volume to Image Service as an image.""" - volume = utils.find_volume(cs, args.volume) - _print_volume_image(volume.upload_to_image(args.force, - args.image_name, - args.container_format, - args.disk_format)) - - -@utils.arg('volume', metavar='<volume>', help='ID of volume to migrate.') -@utils.arg('host', metavar='<host>', help='Destination host.') -@utils.arg('--force-host-copy', metavar='<True|False>', - choices=['True', 'False'], required=False, - help='Enables or disables generic host-based ' - 'force-migration, which bypasses driver ' - 'optimizations. Default=False.', - default=False) -@utils.service_type('volumev2') -def do_migrate(cs, args): - """Migrates volume to a new host.""" - volume = utils.find_volume(cs, args.volume) - volume.migrate_volume(args.host, args.force_host_copy) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume for which to modify type.') -@utils.arg('new_type', metavar='<volume-type>', help='New volume type.') -@utils.arg('--migration-policy', metavar='<never|on-demand>', required=False, - choices=['never', 'on-demand'], default='never', - help='Migration policy during retype of volume.') -@utils.service_type('volumev2') -def do_retype(cs, args): - """Changes the volume type for a volume.""" - volume = utils.find_volume(cs, args.volume) - volume.retype(args.new_type, args.migration_policy) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume to backup.') -@utils.arg('--container', metavar='<container>', - help='Backup container name. Default=None.', - default=None) -@utils.arg('--display-name', - help=argparse.SUPPRESS) -@utils.arg('--name', metavar='<name>', - help='Backup name. Default=None.', - default=None) -@utils.arg('--display-description', - help=argparse.SUPPRESS) -@utils.arg('--description', - metavar='<description>', - default=None, - help='Backup description. Default=None.') -@utils.service_type('volumev2') -def do_backup_create(cs, args): - """Creates a volume backup.""" - if args.display_name is not None: - args.name = args.display_name - - if args.display_description is not None: - args.description = args.display_description - - volume = utils.find_volume(cs, args.volume) - backup = cs.backups.create(volume.id, - args.container, - args.name, - args.description) - - info = {"volume_id": volume.id} - info.update(backup._info) - - if 'links' in info: - info.pop('links') - - utils.print_dict(info) - - -@utils.arg('backup', metavar='<backup>', help='Name or ID of backup.') -@utils.service_type('volumev2') -def do_backup_show(cs, args): - """Shows backup details.""" - backup = _find_backup(cs, args.backup) - info = dict() - info.update(backup._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.service_type('volumev2') -def do_backup_list(cs, args): - """Lists all backups.""" - backups = cs.backups.list() - columns = ['ID', 'Volume ID', 'Status', 'Name', 'Size', 'Object Count', - 'Container'] - utils.print_list(backups, columns) - - -@utils.arg('backup', metavar='<backup>', - help='Name or ID of backup to delete.') -@utils.service_type('volumev2') -def do_backup_delete(cs, args): - """Removes a backup.""" - backup = _find_backup(cs, args.backup) - backup.delete() - - -@utils.arg('backup', metavar='<backup>', - help='ID of backup to restore.') -@utils.arg('--volume-id', metavar='<volume>', - help=argparse.SUPPRESS, - default=None) -@utils.arg('--volume', metavar='<volume>', - help='Name or ID of volume to which to restore. ' - 'Default=None.', - default=None) -@utils.service_type('volumev2') -def do_backup_restore(cs, args): - """Restores a backup.""" - vol = args.volume or args.volume_id - if vol: - volume_id = utils.find_volume(cs, vol).id - else: - volume_id = None - cs.restores.restore(args.backup, volume_id) - - -@utils.arg('backup', metavar='<backup>', - help='ID of the backup to export.') -@utils.service_type('volumev2') -def do_backup_export(cs, args): - """Export backup metadata record.""" - info = cs.backups.export_record(args.backup) - utils.print_dict(info) - - -@utils.arg('backup_service', metavar='<backup_service>', - help='Backup service to use for importing the backup.') -@utils.arg('backup_url', metavar='<backup_url>', - help='Backup URL for importing the backup metadata.') -@utils.service_type('volumev2') -def do_backup_import(cs, args): - """Import backup metadata record.""" - info = cs.backups.import_record(args.backup_service, args.backup_url) - info.pop('links', None) - - utils.print_dict(info) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume to transfer.') -@utils.arg('--name', - metavar='<name>', - default=None, - help='Transfer name. Default=None.') -@utils.arg('--display-name', - help=argparse.SUPPRESS) -@utils.service_type('volumev2') -def do_transfer_create(cs, args): - """Creates a volume transfer.""" - if args.display_name is not None: - args.name = args.display_name - - volume = utils.find_volume(cs, args.volume) - transfer = cs.transfers.create(volume.id, - args.name) - info = dict() - info.update(transfer._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('transfer', metavar='<transfer>', - help='Name or ID of transfer to delete.') -@utils.service_type('volumev2') -def do_transfer_delete(cs, args): - """Undoes a transfer.""" - transfer = _find_transfer(cs, args.transfer) - transfer.delete() - - -@utils.arg('transfer', metavar='<transfer>', - help='ID of transfer to accept.') -@utils.arg('auth_key', metavar='<auth_key>', - help='Authentication key of transfer to accept.') -@utils.service_type('volumev2') -def do_transfer_accept(cs, args): - """Accepts a volume transfer.""" - transfer = cs.transfers.accept(args.transfer, args.auth_key) - info = dict() - info.update(transfer._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.service_type('volumev2') -def do_transfer_list(cs, args): - """Lists all transfers.""" - transfers = cs.transfers.list() - columns = ['ID', 'Volume ID', 'Name'] - utils.print_list(transfers, columns) - - -@utils.arg('transfer', metavar='<transfer>', - help='Name or ID of transfer to accept.') -@utils.service_type('volumev2') -def do_transfer_show(cs, args): - """Shows transfer details.""" - transfer = _find_transfer(cs, args.transfer) - info = dict() - info.update(transfer._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of volume to extend.') -@utils.arg('new_size', - metavar='<new_size>', - type=int, - help='New size of volume, in GBs.') -@utils.service_type('volumev2') -def do_extend(cs, args): - """Attempts to extend size of an existing volume.""" - volume = utils.find_volume(cs, args.volume) - cs.volumes.extend(volume, args.new_size) - - -@utils.arg('--host', metavar='<hostname>', default=None, - help='Host name. Default=None.') -@utils.arg('--binary', metavar='<binary>', default=None, - help='Service binary. Default=None.') -@utils.service_type('volumev2') -def do_service_list(cs, args): - """Lists all services. Filter by host and service binary.""" - result = cs.services.list(host=args.host, binary=args.binary) - columns = ["Binary", "Host", "Zone", "Status", "State", "Updated_at"] - # NOTE(jay-lau-513): we check if the response has disabled_reason - # so as not to add the column when the extended ext is not enabled. - if result and hasattr(result[0], 'disabled_reason'): - columns.append("Disabled Reason") - utils.print_list(result, columns) - - -@utils.arg('host', metavar='<hostname>', help='Host name.') -@utils.arg('binary', metavar='<binary>', help='Service binary.') -@utils.service_type('volumev2') -def do_service_enable(cs, args): - """Enables the service.""" - result = cs.services.enable(args.host, args.binary) - columns = ["Host", "Binary", "Status"] - utils.print_list([result], columns) - - -@utils.arg('host', metavar='<hostname>', help='Host name.') -@utils.arg('binary', metavar='<binary>', help='Service binary.') -@utils.arg('--reason', metavar='<reason>', - help='Reason for disabling service.') -@utils.service_type('volumev2') -def do_service_disable(cs, args): - """Disables the service.""" - columns = ["Host", "Binary", "Status"] - if args.reason: - columns.append('Disabled Reason') - result = cs.services.disable_log_reason(args.host, args.binary, - args.reason) - else: - result = cs.services.disable(args.host, args.binary) - utils.print_list([result], columns) - - -def _treeizeAvailabilityZone(zone): - """Builds a tree view for availability zones.""" - AvailabilityZone = availability_zones.AvailabilityZone - - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - result = [] - - # Zone tree view item - az.zoneName = zone.zoneName - az.zoneState = ('available' - if zone.zoneState['available'] else 'not available') - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - if getattr(zone, "hosts", None) and zone.hosts is not None: - for (host, services) in zone.hosts.items(): - # Host tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '|- %s' % host - az.zoneState = '' - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - for (svc, state) in services.items(): - # Service tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '| |- %s' % svc - az.zoneState = '%s %s %s' % ( - 'enabled' if state['active'] else 'disabled', - ':-)' if state['available'] else 'XXX', - state['updated_at']) - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - return result - - -@utils.service_type('volumev2') -def do_availability_zone_list(cs, _args): - """Lists all availability zones.""" - try: - availability_zones = cs.availability_zones.list() - except exceptions.Forbidden as e: # policy doesn't allow probably - try: - availability_zones = cs.availability_zones.list(detailed=False) - except Exception: - raise e - - result = [] - for zone in availability_zones: - result += _treeizeAvailabilityZone(zone) - _translate_availability_zone_keys(result) - utils.print_list(result, ['Name', 'Status']) - - -def _print_volume_encryption_type_list(encryption_types): - """ - Lists volume encryption types. - - :param encryption_types: a list of :class: VolumeEncryptionType instances - """ - utils.print_list(encryption_types, ['Volume Type ID', 'Provider', - 'Cipher', 'Key Size', - 'Control Location']) - - -@utils.service_type('volumev2') -def do_encryption_type_list(cs, args): - """Shows encryption type details for volume types. Admin only.""" - result = cs.volume_encryption_types.list() - utils.print_list(result, ['Volume Type ID', 'Provider', 'Cipher', - 'Key Size', 'Control Location']) - - -@utils.arg('volume_type', - metavar='<volume_type>', - type=str, - help="Name or ID of volume type.") -@utils.service_type('volumev2') -def do_encryption_type_show(cs, args): - """Shows encryption type details for a volume type. Admin only.""" - volume_type = _find_volume_type(cs, args.volume_type) - - result = cs.volume_encryption_types.get(volume_type) - - # Display result or an empty table if no result - if hasattr(result, 'volume_type_id'): - _print_volume_encryption_type_list([result]) - else: - _print_volume_encryption_type_list([]) - - -@utils.arg('volume_type', - metavar='<volume_type>', - type=str, - help="Name or ID of volume type.") -@utils.arg('provider', - metavar='<provider>', - type=str, - help='The class that provides encryption support. ' - 'For example, LuksEncryptor.') -@utils.arg('--cipher', - metavar='<cipher>', - type=str, - required=False, - default=None, - help='The encryption algorithm or mode. ' - 'For example, aes-xts-plain64. Default=None.') -@utils.arg('--key_size', - metavar='<key_size>', - type=int, - required=False, - default=None, - help='Size of encryption key, in bits. ' - 'For example, 128 or 256. Default=None.') -@utils.arg('--control_location', - metavar='<control_location>', - choices=['front-end', 'back-end'], - type=str, - required=False, - default='front-end', - help='Notional service where encryption is performed. ' - 'Valid values are "front-end" or "back-end." ' - 'For example, front-end=Nova. Default is "front-end."') -@utils.service_type('volumev2') -def do_encryption_type_create(cs, args): - """Creates encryption type for a volume type. Admin only.""" - volume_type = _find_volume_type(cs, args.volume_type) - - body = {} - body['provider'] = args.provider - body['cipher'] = args.cipher - body['key_size'] = args.key_size - body['control_location'] = args.control_location - - result = cs.volume_encryption_types.create(volume_type, body) - _print_volume_encryption_type_list([result]) - - -@utils.arg('volume_type', - metavar='<volume_type>', - type=str, - help="Name or ID of volume type.") -@utils.service_type('volumev2') -def do_encryption_type_delete(cs, args): - """Deletes encryption type for a volume type. Admin only.""" - volume_type = _find_volume_type(cs, args.volume_type) - cs.volume_encryption_types.delete(volume_type) - - -def _print_qos_specs(qos_specs): - utils.print_dict(qos_specs._info) - - -def _print_qos_specs_list(q_specs): - utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs']) - - -def _print_qos_specs_and_associations_list(q_specs): - utils.print_list(q_specs, ['ID', 'Name', 'Consumer', 'specs']) - - -def _print_associations_list(associations): - utils.print_list(associations, ['Association_Type', 'Name', 'ID']) - - -@utils.arg('name', - metavar='<name>', - help="Name of new QoS specifications.") -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help="QoS specifications.") -@utils.service_type('volumev2') -def do_qos_create(cs, args): - """Creates a qos specs.""" - keypair = None - if args.metadata is not None: - keypair = _extract_metadata(args) - qos_specs = cs.qos_specs.create(args.name, keypair) - _print_qos_specs(qos_specs) - - -@utils.service_type('volumev2') -def do_qos_list(cs, args): - """Lists qos specs.""" - qos_specs = cs.qos_specs.list() - _print_qos_specs_list(qos_specs) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help="ID of QoS specifications to show.") -@utils.service_type('volumev2') -def do_qos_show(cs, args): - """Shows qos specs details.""" - qos_specs = _find_qos_specs(cs, args.qos_specs) - _print_qos_specs(qos_specs) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help="ID of QoS specifications to delete.") -@utils.arg('--force', - metavar='<True|False>', - default=False, - help='Enables or disables deletion of in-use ' - 'QoS specifications. Default=False.') -@utils.service_type('volumev2') -def do_qos_delete(cs, args): - """Deletes a specified qos specs.""" - force = strutils.bool_from_string(args.force) - qos_specs = _find_qos_specs(cs, args.qos_specs) - cs.qos_specs.delete(qos_specs, force) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.arg('vol_type_id', metavar='<volume_type_id>', - help='ID of volume type with which to associate ' - 'QoS specifications.') -@utils.service_type('volumev2') -def do_qos_associate(cs, args): - """Associates qos specs with specified volume type.""" - cs.qos_specs.associate(args.qos_specs, args.vol_type_id) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.arg('vol_type_id', metavar='<volume_type_id>', - help='ID of volume type with which to associate ' - 'QoS specifications.') -@utils.service_type('volumev2') -def do_qos_disassociate(cs, args): - """Disassociates qos specs from specified volume type.""" - cs.qos_specs.disassociate(args.qos_specs, args.vol_type_id) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications on which to operate.') -@utils.service_type('volumev2') -def do_qos_disassociate_all(cs, args): - """Disassociates qos specs from all its associations.""" - cs.qos_specs.disassociate_all(args.qos_specs) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', metavar='key=value', - nargs='+', - default=[], - help='Metadata key and value pair to set or unset. ' - 'For unset, specify only the key.') -def do_qos_key(cs, args): - """Sets or unsets specifications for a qos spec.""" - keypair = _extract_metadata(args) - - if args.action == 'set': - cs.qos_specs.set_keys(args.qos_specs, keypair) - elif args.action == 'unset': - cs.qos_specs.unset_keys(args.qos_specs, list(keypair)) - - -@utils.arg('qos_specs', metavar='<qos_specs>', - help='ID of QoS specifications.') -@utils.service_type('volumev2') -def do_qos_get_association(cs, args): - """Lists all associations for specified qos specs.""" - associations = cs.qos_specs.get_associations(args.qos_specs) - _print_associations_list(associations) - - -@utils.arg('snapshot', - metavar='<snapshot>', - help='ID of snapshot for which to update metadata.') -@utils.arg('action', - metavar='<action>', - choices=['set', 'unset'], - help="The action. Valid values are 'set' or 'unset.'") -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='Metadata key and value pair to set or unset. ' - 'For unset, specify only the key.') -@utils.service_type('volumev2') -def do_snapshot_metadata(cs, args): - """Sets or deletes snapshot metadata.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - metadata = _extract_metadata(args) - - if args.action == 'set': - metadata = snapshot.set_metadata(metadata) - utils.print_dict(metadata._info) - elif args.action == 'unset': - snapshot.delete_metadata(list(metadata.keys())) - - -@utils.arg('snapshot', metavar='<snapshot>', - help='ID of snapshot.') -@utils.service_type('volumev2') -def do_snapshot_metadata_show(cs, args): - """Shows snapshot metadata.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - utils.print_dict(snapshot._info['metadata'], 'Metadata-property') - - -@utils.arg('volume', metavar='<volume>', - help='ID of volume.') -@utils.service_type('volumev2') -def do_metadata_show(cs, args): - """Shows volume metadata.""" - volume = utils.find_volume(cs, args.volume) - utils.print_dict(volume._info['metadata'], 'Metadata-property') - - -@utils.arg('volume', - metavar='<volume>', - help='ID of volume for which to update metadata.') -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='Metadata key and value pair or pairs to update.') -@utils.service_type('volumev2') -def do_metadata_update_all(cs, args): - """Updates volume metadata.""" - volume = utils.find_volume(cs, args.volume) - metadata = _extract_metadata(args) - metadata = volume.update_all_metadata(metadata) - utils.print_dict(metadata) - - -@utils.arg('snapshot', - metavar='<snapshot>', - help='ID of snapshot for which to update metadata.') -@utils.arg('metadata', - metavar='<key=value>', - nargs='+', - default=[], - help='Metadata key and value pair to update.') -@utils.service_type('volumev2') -def do_snapshot_metadata_update_all(cs, args): - """Updates snapshot metadata.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - metadata = _extract_metadata(args) - metadata = snapshot.update_all_metadata(metadata) - utils.print_dict(metadata) - - -@utils.arg('volume', metavar='<volume>', help='ID of volume to update.') -@utils.arg('read_only', - metavar='<True|true|False|false>', - choices=['True', 'true', 'False', 'false'], - help='Enables or disables update of volume to ' - 'read-only access mode.') -@utils.service_type('volumev2') -def do_readonly_mode_update(cs, args): - """Updates volume read-only access-mode flag.""" - volume = utils.find_volume(cs, args.volume) - cs.volumes.update_readonly_flag(volume, - strutils.bool_from_string(args.read_only)) - - -@utils.arg('volume', metavar='<volume>', help='ID of the volume to update.') -@utils.arg('bootable', - metavar='<True|true|False|false>', - choices=['True', 'true', 'False', 'false'], - help='Flag to indicate whether volume is bootable.') -@utils.service_type('volumev2') -def do_set_bootable(cs, args): - """Update bootable status of a volume.""" - volume = utils.find_volume(cs, args.volume) - cs.volumes.set_bootable(volume, - strutils.bool_from_string(args.bootable)) - - -@utils.arg('host', - metavar='<host>', - help='Cinder host on which the existing volume resides') -@utils.arg('ref', - type=str, - nargs='*', - metavar='<key=value>', - help='Driver-specific reference to the existing volume as ' - 'key=value pairs') -@utils.arg('--source-name', - metavar='<source-name>', - help='Name of the volume to manage (Optional)') -@utils.arg('--source-id', - metavar='<source-id>', - help='ID of the volume to manage (Optional)') -@utils.arg('--name', - metavar='<name>', - help='Volume name (Optional, Default=None)') -@utils.arg('--description', - metavar='<description>', - help='Volume description (Optional, Default=None)') -@utils.arg('--volume-type', - metavar='<volume-type>', - help='Volume type (Optional, Default=None)') -@utils.arg('--availability-zone', - metavar='<availability-zone>', - help='Availability zone for volume (Optional, Default=None)') -@utils.arg('--metadata', - type=str, - nargs='*', - metavar='<key=value>', - help='Metadata key=value pairs (Optional, Default=None)') -@utils.arg('--bootable', - action='store_true', - help='Specifies that the newly created volume should be' - ' marked as bootable') -@utils.service_type('volumev2') -def do_manage(cs, args): - """Manage an existing volume.""" - volume_metadata = None - if args.metadata is not None: - volume_metadata = _extract_metadata(args) - - # Build a dictionary of key/value pairs to pass to the API. - ref_dict = {} - for pair in args.ref: - (k, v) = pair.split('=', 1) - ref_dict[k] = v - - # The recommended way to specify an existing volume is by ID or name, and - # have the Cinder driver look for 'source-name' or 'source-id' elements in - # the ref structure. To make things easier for the user, we have special - # --source-name and --source-id CLI options that add the appropriate - # element to the ref structure. - # - # Note how argparse converts hyphens to underscores. We use hyphens in the - # dictionary so that it is consistent with what the user specified on the - # CLI. - if hasattr(args, 'source_name') and \ - args.source_name is not None: - ref_dict['source-name'] = args.source_name - if hasattr(args, 'source_id') and \ - args.source_id is not None: - ref_dict['source-id'] = args.source_id - - volume = cs.volumes.manage(host=args.host, - ref=ref_dict, - name=args.name, - description=args.description, - volume_type=args.volume_type, - availability_zone=args.availability_zone, - metadata=volume_metadata, - bootable=args.bootable) - - info = {} - volume = cs.volumes.get(volume.id) - info.update(volume._info) - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of the volume to unmanage.') -@utils.service_type('volumev2') -def do_unmanage(cs, args): - utils.find_volume(cs, args.volume).unmanage(args.volume) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of the volume to promote.') -@utils.service_type('volumev2') -def do_replication_promote(cs, args): - """Promote a secondary volume to primary for a relationship.""" - utils.find_volume(cs, args.volume).promote(args.volume) - - -@utils.arg('volume', metavar='<volume>', - help='Name or ID of the volume to reenable replication.') -@utils.service_type('volumev2') -def do_replication_reenable(cs, args): - """Sync the secondary volume with primary for a relationship.""" - utils.find_volume(cs, args.volume).reenable(args.volume) - - -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Shows details for all tenants. Admin only.') -@utils.service_type('volumev2') -def do_consisgroup_list(cs, args): - """Lists all consistencygroups.""" - consistencygroups = cs.consistencygroups.list() - - columns = ['ID', 'Status', 'Name'] - utils.print_list(consistencygroups, columns) - - -@utils.arg('consistencygroup', - metavar='<consistencygroup>', - help='Name or ID of a consistency group.') -@utils.service_type('volumev2') -def do_consisgroup_show(cs, args): - """Shows details of a consistency group.""" - info = dict() - consistencygroup = _find_consistencygroup(cs, args.consistencygroup) - info.update(consistencygroup._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('volumetypes', - metavar='<volume-types>', - help='Volume types.') -@utils.arg('--name', - metavar='<name>', - help='Name of a consistency group.') -@utils.arg('--description', - metavar='<description>', - default=None, - help='Description of a consistency group. Default=None.') -@utils.arg('--availability-zone', - metavar='<availability-zone>', - default=None, - help='Availability zone for volume. Default=None.') -@utils.service_type('volumev2') -def do_consisgroup_create(cs, args): - """Creates a consistency group.""" - - consistencygroup = cs.consistencygroups.create( - args.volumetypes, - args.name, - args.description, - availability_zone=args.availability_zone) - - info = dict() - consistencygroup = cs.consistencygroups.get(consistencygroup.id) - info.update(consistencygroup._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('consistencygroup', - metavar='<consistencygroup>', nargs='+', - help='Name or ID of one or more consistency groups ' - 'to be deleted.') -@utils.arg('--force', - action='store_true', - help='Allows or disallows consistency groups ' - 'to be deleted. If the consistency group is empty, ' - 'it can be deleted without the force flag. ' - 'If the consistency group is not empty, the force ' - 'flag is required for it to be deleted.', - default=False) -@utils.service_type('volumev2') -def do_consisgroup_delete(cs, args): - """Removes one or more consistency groups.""" - failure_count = 0 - for consistencygroup in args.consistencygroup: - try: - _find_consistencygroup(cs, consistencygroup).delete(args.force) - except Exception as e: - failure_count += 1 - print("Delete for consistency group %s failed: %s" % - (consistencygroup, e)) - if failure_count == len(args.consistencygroup): - raise exceptions.CommandError("Unable to delete any of specified " - "consistency groups.") - - -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0, - help='Shows details for all tenants. Admin only.') -@utils.arg('--status', - metavar='<status>', - default=None, - help='Filters results by a status. Default=None.') -@utils.arg('--consistencygroup-id', - metavar='<consistencygroup_id>', - default=None, - help='Filters results by a consistency group ID. Default=None.') -@utils.service_type('volumev2') -def do_cgsnapshot_list(cs, args): - """Lists all cgsnapshots.""" - cgsnapshots = cs.cgsnapshots.list() - - all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants)) - - search_opts = { - 'all_tenants': all_tenants, - 'status': args.status, - 'consistencygroup_id': args.consistencygroup_id, - } - - cgsnapshots = cs.cgsnapshots.list(search_opts=search_opts) - - columns = ['ID', 'Status', 'Name'] - utils.print_list(cgsnapshots, columns) - - -@utils.arg('cgsnapshot', - metavar='<cgsnapshot>', - help='Name or ID of cgsnapshot.') -@utils.service_type('volumev2') -def do_cgsnapshot_show(cs, args): - """Shows cgsnapshot details.""" - info = dict() - cgsnapshot = _find_cgsnapshot(cs, args.cgsnapshot) - info.update(cgsnapshot._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('consistencygroup', - metavar='<consistencygroup>', - help='Name or ID of a consistency group.') -@utils.arg('--name', - metavar='<name>', - default=None, - help='Cgsnapshot name. Default=None.') -@utils.arg('--description', - metavar='<description>', - default=None, - help='Cgsnapshot description. Default=None.') -@utils.service_type('volumev2') -def do_cgsnapshot_create(cs, args): - """Creates a cgsnapshot.""" - consistencygroup = _find_consistencygroup(cs, args.consistencygroup) - cgsnapshot = cs.cgsnapshots.create( - consistencygroup.id, - args.name, - args.description) - - info = dict() - cgsnapshot = cs.cgsnapshots.get(cgsnapshot.id) - info.update(cgsnapshot._info) - - info.pop('links', None) - utils.print_dict(info) - - -@utils.arg('cgsnapshot', - metavar='<cgsnapshot>', nargs='+', - help='Name or ID of one or more cgsnapshots to be deleted.') -@utils.service_type('volumev2') -def do_cgsnapshot_delete(cs, args): - """Removes one or more cgsnapshots.""" - failure_count = 0 - for cgsnapshot in args.cgsnapshot: - try: - _find_cgsnapshot(cs, cgsnapshot).delete() - except Exception as e: - failure_count += 1 - print("Delete for cgsnapshot %s failed: %s" % (cgsnapshot, e)) - if failure_count == len(args.cgsnapshot): - raise exceptions.CommandError("Unable to delete any of specified " - "cgsnapshots.") diff --git a/awx/lib/site-packages/cinderclient/v2/volume_backups.py b/awx/lib/site-packages/cinderclient/v2/volume_backups.py deleted file mode 100644 index ae232c2744..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/volume_backups.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume Backups interface (1.1 extension). -""" - -from cinderclient import base - - -class VolumeBackup(base.Resource): - """A volume backup is a block level backup of a volume.""" - def __repr__(self): - return "<VolumeBackup: %s>" % self.id - - def delete(self): - """Delete this volume backup.""" - return self.manager.delete(self) - - -class VolumeBackupManager(base.ManagerWithFind): - """Manage :class:`VolumeBackup` resources.""" - resource_class = VolumeBackup - - def create(self, volume_id, container=None, - name=None, description=None): - """Creates a volume backup. - - :param volume_id: The ID of the volume to backup. - :param container: The name of the backup service container. - :param name: The name of the backup. - :param description: The description of the backup. - :rtype: :class:`VolumeBackup` - """ - body = {'backup': {'volume_id': volume_id, - 'container': container, - 'name': name, - 'description': description}} - return self._create('/backups', body, 'backup') - - def get(self, backup_id): - """Show volume backup details. - - :param backup_id: The ID of the backup to display. - :rtype: :class:`VolumeBackup` - """ - return self._get("/backups/%s" % backup_id, "backup") - - def list(self, detailed=True): - """Get a list of all volume backups. - - :rtype: list of :class:`VolumeBackup` - """ - if detailed is True: - return self._list("/backups/detail", "backups") - else: - return self._list("/backups", "backups") - - def delete(self, backup): - """Delete a volume backup. - - :param backup: The :class:`VolumeBackup` to delete. - """ - self._delete("/backups/%s" % base.getid(backup)) - - def export_record(self, backup_id): - """Export volume backup metadata record. - - :param backup_id: The ID of the backup to export. - :rtype: :class:`VolumeBackup` - """ - resp, body = \ - self.api.client.get("/backups/%s/export_record" % backup_id) - return body['backup-record'] - - def import_record(self, backup_service, backup_url): - """Export volume backup metadata record. - - :param backup_service: Backup service to use for importing the backup - :param backup_urlBackup URL for importing the backup metadata - :rtype: :class:`VolumeBackup` - """ - body = {'backup-record': {'backup_service': backup_service, - 'backup_url': backup_url}} - self.run_hooks('modify_body_for_update', body, 'backup-record') - resp, body = self.api.client.post("/backups/import_record", body=body) - return body['backup'] diff --git a/awx/lib/site-packages/cinderclient/v2/volume_backups_restore.py b/awx/lib/site-packages/cinderclient/v2/volume_backups_restore.py deleted file mode 100644 index 0eafa8220c..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/volume_backups_restore.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Volume Backups Restore interface (1.1 extension). - -This is part of the Volume Backups interface. -""" - -from cinderclient import base - - -class VolumeBackupsRestore(base.Resource): - """A Volume Backups Restore represents a restore operation.""" - def __repr__(self): - return "<VolumeBackupsRestore: %s>" % self.volume_id - - -class VolumeBackupRestoreManager(base.Manager): - """Manage :class:`VolumeBackupsRestore` resources.""" - resource_class = VolumeBackupsRestore - - def restore(self, backup_id, volume_id=None): - """Restore a backup to a volume. - - :param backup_id: The ID of the backup to restore. - :param volume_id: The ID of the volume to restore the backup to. - :rtype: :class:`Restore` - """ - body = {'restore': {'volume_id': volume_id}} - return self._create("/backups/%s/restore" % backup_id, - body, "restore") diff --git a/awx/lib/site-packages/cinderclient/v2/volume_encryption_types.py b/awx/lib/site-packages/cinderclient/v2/volume_encryption_types.py deleted file mode 100644 index 1099bc37b4..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/volume_encryption_types.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2013 The Johns Hopkins University/Applied Physics Laboratory -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -""" -Volume Encryption Type interface -""" - -from cinderclient import base - - -class VolumeEncryptionType(base.Resource): - """ - A Volume Encryption Type is a collection of settings used to conduct - encryption for a specific volume type. - """ - def __repr__(self): - return "<VolumeEncryptionType: %s>" % self.name - - -class VolumeEncryptionTypeManager(base.ManagerWithFind): - """ - Manage :class: `VolumeEncryptionType` resources. - """ - resource_class = VolumeEncryptionType - - def list(self, search_opts=None): - """ - List all volume encryption types. - - :param volume_types: a list of volume types - :return: a list of :class: VolumeEncryptionType instances - """ - # Since the encryption type is a volume type extension, we cannot get - # all encryption types without going through all volume types. - volume_types = self.api.volume_types.list() - encryption_types = [] - for volume_type in volume_types: - encryption_type = self._get("/types/%s/encryption" - % base.getid(volume_type)) - if hasattr(encryption_type, 'volume_type_id'): - encryption_types.append(encryption_type) - return encryption_types - - def get(self, volume_type): - """ - Get the volume encryption type for the specified volume type. - - :param volume_type: the volume type to query - :return: an instance of :class: VolumeEncryptionType - """ - return self._get("/types/%s/encryption" % base.getid(volume_type)) - - def create(self, volume_type, specs): - """ - Creates encryption type for a volume type. Default: admin only. - - :param volume_type: the volume type on which to add an encryption type - :param specs: the encryption type specifications to add - :return: an instance of :class: VolumeEncryptionType - """ - body = {'encryption': specs} - return self._create("/types/%s/encryption" % base.getid(volume_type), - body, "encryption") - - def update(self, volume_type, specs): - """ - Update the encryption type information for the specified volume type. - - :param volume_type: the volume type whose encryption type information - must be updated - :param specs: the encryption type specifications to update - :return: an instance of :class: VolumeEncryptionType - """ - raise NotImplementedError() - - def delete(self, volume_type): - """ - Delete the encryption type information for the specified volume type. - - :param volume_type: the volume type whose encryption type information - must be deleted - """ - return self._delete("/types/%s/encryption/provider" % - base.getid(volume_type)) diff --git a/awx/lib/site-packages/cinderclient/v2/volume_snapshots.py b/awx/lib/site-packages/cinderclient/v2/volume_snapshots.py deleted file mode 100644 index a398b0eb92..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/volume_snapshots.py +++ /dev/null @@ -1,187 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Volume snapshot interface (1.1 extension).""" - -import six -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - -from cinderclient import base - - -class Snapshot(base.Resource): - """A Snapshot is a point-in-time snapshot of an openstack volume.""" - def __repr__(self): - return "<Snapshot: %s>" % self.id - - def delete(self): - """Delete this snapshot.""" - self.manager.delete(self) - - def update(self, **kwargs): - """Update the name or description for this snapshot.""" - self.manager.update(self, **kwargs) - - @property - def progress(self): - return self._info.get('os-extended-snapshot-attributes:progress') - - @property - def project_id(self): - return self._info.get('os-extended-snapshot-attributes:project_id') - - def reset_state(self, state): - """Update the snapshot with the provided state.""" - self.manager.reset_state(self, state) - - def set_metadata(self, metadata): - """Set metadata of this snapshot.""" - return self.manager.set_metadata(self, metadata) - - def delete_metadata(self, keys): - """Delete metadata of this snapshot.""" - return self.manager.delete_metadata(self, keys) - - def update_all_metadata(self, metadata): - """Update_all metadata of this snapshot.""" - return self.manager.update_all_metadata(self, metadata) - - -class SnapshotManager(base.ManagerWithFind): - """Manage :class:`Snapshot` resources.""" - resource_class = Snapshot - - def create(self, volume_id, force=False, - name=None, description=None): - - """Creates a snapshot of the given volume. - - :param volume_id: The ID of the volume to snapshot. - :param force: If force is True, create a snapshot even if the volume is - attached to an instance. Default is False. - :param name: Name of the snapshot - :param description: Description of the snapshot - :rtype: :class:`Snapshot` - """ - body = {'snapshot': {'volume_id': volume_id, - 'force': force, - 'name': name, - 'description': description}} - return self._create('/snapshots', body, 'snapshot') - - def get(self, snapshot_id): - """Shows snapshot details. - - :param snapshot_id: The ID of the snapshot to get. - :rtype: :class:`Snapshot` - """ - return self._get("/snapshots/%s" % snapshot_id, "snapshot") - - def list(self, detailed=True, search_opts=None): - """Get a list of all snapshots. - - :rtype: list of :class:`Snapshot` - """ - - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - if qparams: - new_qparams = sorted(qparams.items(), key=lambda x: x[0]) - query_string = "?%s" % urlencode(new_qparams) - else: - query_string = "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/snapshots%s%s" % (detail, query_string), - "snapshots") - - def delete(self, snapshot): - """Delete a snapshot. - - :param snapshot: The :class:`Snapshot` to delete. - """ - self._delete("/snapshots/%s" % base.getid(snapshot)) - - def update(self, snapshot, **kwargs): - """Update the name or description for a snapshot. - - :param snapshot: The :class:`Snapshot` to update. - """ - if not kwargs: - return - - body = {"snapshot": kwargs} - - self._update("/snapshots/%s" % base.getid(snapshot), body) - - def reset_state(self, snapshot, state): - """Update the specified snapshot with the provided state.""" - return self._action('os-reset_status', snapshot, {'status': state}) - - def _action(self, action, snapshot, info=None, **kwargs): - """Perform a snapshot action.""" - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/snapshots/%s/action' % base.getid(snapshot) - return self.api.client.post(url, body=body) - - def update_snapshot_status(self, snapshot, update_dict): - return self._action('os-update_snapshot_status', - base.getid(snapshot), update_dict) - - def set_metadata(self, snapshot, metadata): - """Update/Set a snapshots metadata. - - :param snapshot: The :class:`Snapshot`. - :param metadata: A list of keys to be set. - """ - body = {'metadata': metadata} - return self._create("/snapshots/%s/metadata" % base.getid(snapshot), - body, "metadata") - - def delete_metadata(self, snapshot, keys): - """Delete specified keys from snapshot metadata. - - :param snapshot: The :class:`Snapshot`. - :param keys: A list of keys to be removed. - """ - snapshot_id = base.getid(snapshot) - for k in keys: - self._delete("/snapshots/%s/metadata/%s" % (snapshot_id, k)) - - def update_all_metadata(self, snapshot, metadata): - """Update_all snapshot metadata. - - :param snapshot: The :class:`Snapshot`. - :param metadata: A list of keys to be updated. - """ - body = {'metadata': metadata} - return self._update("/snapshots/%s/metadata" % base.getid(snapshot), - body) diff --git a/awx/lib/site-packages/cinderclient/v2/volume_transfers.py b/awx/lib/site-packages/cinderclient/v2/volume_transfers.py deleted file mode 100644 index 00daf3ec5e..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/volume_transfers.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume transfer interface (1.1 extension). -""" - -from cinderclient import base - - -class VolumeTransfer(base.Resource): - """Transfer a volume from one tenant to another""" - def __repr__(self): - return "<VolumeTransfer: %s>" % self.id - - def delete(self): - """Delete this volume transfer.""" - return self.manager.delete(self) - - -class VolumeTransferManager(base.ManagerWithFind): - """Manage :class:`VolumeTransfer` resources.""" - resource_class = VolumeTransfer - - def create(self, volume_id, name=None): - """Creates a volume transfer. - - :param volume_id: The ID of the volume to transfer. - :param name: The name of the transfer. - :rtype: :class:`VolumeTransfer` - """ - body = {'transfer': {'volume_id': volume_id, - 'name': name}} - return self._create('/os-volume-transfer', body, 'transfer') - - def accept(self, transfer_id, auth_key): - """Accept a volume transfer. - - :param transfer_id: The ID of the transfer to accept. - :param auth_key: The auth_key of the transfer. - :rtype: :class:`VolumeTransfer` - """ - body = {'accept': {'auth_key': auth_key}} - return self._create('/os-volume-transfer/%s/accept' % transfer_id, - body, 'transfer') - - def get(self, transfer_id): - """Show details of a volume transfer. - - :param transfer_id: The ID of the volume transfer to display. - :rtype: :class:`VolumeTransfer` - """ - return self._get("/os-volume-transfer/%s" % transfer_id, "transfer") - - def list(self, detailed=True, search_opts=None): - """Get a list of all volume transfer. - - :rtype: list of :class:`VolumeTransfer` - """ - if detailed is True: - return self._list("/os-volume-transfer/detail", "transfers") - else: - return self._list("/os-volume-transfer", "transfers") - - def delete(self, transfer_id): - """Delete a volume transfer. - - :param transfer_id: The :class:`VolumeTransfer` to delete. - """ - self._delete("/os-volume-transfer/%s" % base.getid(transfer_id)) diff --git a/awx/lib/site-packages/cinderclient/v2/volume_types.py b/awx/lib/site-packages/cinderclient/v2/volume_types.py deleted file mode 100644 index dc2ec5bbab..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/volume_types.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -"""Volume Type interface.""" - -from cinderclient import base - - -class VolumeType(base.Resource): - """A Volume Type is the type of volume to be created.""" - def __repr__(self): - return "<VolumeType: %s>" % self.name - - def get_keys(self): - """Get extra specs from a volume type. - - :param vol_type: The :class:`VolumeType` to get extra specs from - """ - _resp, body = self.manager.api.client.get( - "/types/%s/extra_specs" % - base.getid(self)) - return body["extra_specs"] - - def set_keys(self, metadata): - """Set extra specs on a volume type. - - :param type : The :class:`VolumeType` to set extra spec on - :param metadata: A dict of key/value pairs to be set - """ - body = {'extra_specs': metadata} - return self.manager._create( - "/types/%s/extra_specs" % base.getid(self), - body, - "extra_specs", - return_raw=True) - - def unset_keys(self, keys): - """Unset extra specs on a volue type. - - :param type_id: The :class:`VolumeType` to unset extra spec on - :param keys: A list of keys to be unset - """ - - # NOTE(jdg): This wasn't actually doing all of the keys before - # the return in the loop resulted in ony ONE key being unset. - # since on success the return was NONE, we'll only interrupt the loop - # and return if there's an error - for k in keys: - resp = self.manager._delete( - "/types/%s/extra_specs/%s" % ( - base.getid(self), k)) - if resp is not None: - return resp - - -class VolumeTypeManager(base.ManagerWithFind): - """Manage :class:`VolumeType` resources.""" - resource_class = VolumeType - - def list(self, search_opts=None): - """Lists all volume types. - - :rtype: list of :class:`VolumeType`. - """ - return self._list("/types", "volume_types") - - def get(self, volume_type): - """Get a specific volume type. - - :param volume_type: The ID of the :class:`VolumeType` to get. - :rtype: :class:`VolumeType` - """ - return self._get("/types/%s" % base.getid(volume_type), "volume_type") - - def delete(self, volume_type): - """Deletes a specific volume_type. - - :param volume_type: The name or ID of the :class:`VolumeType` to get. - """ - self._delete("/types/%s" % base.getid(volume_type)) - - def create(self, name): - """Creates a volume type. - - :param name: Descriptive name of the volume type - :rtype: :class:`VolumeType` - """ - - body = { - "volume_type": { - "name": name, - } - } - - return self._create("/types", body, "volume_type") diff --git a/awx/lib/site-packages/cinderclient/v2/volumes.py b/awx/lib/site-packages/cinderclient/v2/volumes.py deleted file mode 100644 index ae8ed29097..0000000000 --- a/awx/lib/site-packages/cinderclient/v2/volumes.py +++ /dev/null @@ -1,521 +0,0 @@ -# Copyright (c) 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Volume interface (v2 extension).""" - -import six -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - -from cinderclient import base - - -SORT_DIR_VALUES = ('asc', 'desc') -SORT_KEY_VALUES = ('id', 'status', 'size', 'availability_zone', 'name', - 'bootable', 'created_at') - - -class Volume(base.Resource): - """A volume is an extra block level storage to the OpenStack instances.""" - def __repr__(self): - return "<Volume: %s>" % self.id - - def delete(self): - """Delete this volume.""" - self.manager.delete(self) - - def update(self, **kwargs): - """Update the name or description for this volume.""" - self.manager.update(self, **kwargs) - - def attach(self, instance_uuid, mountpoint, mode='rw'): - """Set attachment metadata. - - :param instance_uuid: uuid of the attaching instance. - :param mountpoint: mountpoint on the attaching instance. - :param mode: the access mode. - """ - return self.manager.attach(self, instance_uuid, mountpoint, mode) - - def detach(self): - """Clear attachment metadata.""" - return self.manager.detach(self) - - def reserve(self, volume): - """Reserve this volume.""" - return self.manager.reserve(self) - - def unreserve(self, volume): - """Unreserve this volume.""" - return self.manager.unreserve(self) - - def begin_detaching(self, volume): - """Begin detaching volume.""" - return self.manager.begin_detaching(self) - - def roll_detaching(self, volume): - """Roll detaching volume.""" - return self.manager.roll_detaching(self) - - def initialize_connection(self, volume, connector): - """Initialize a volume connection. - - :param connector: connector dict from nova. - """ - return self.manager.initialize_connection(self, connector) - - def terminate_connection(self, volume, connector): - """Terminate a volume connection. - - :param connector: connector dict from nova. - """ - return self.manager.terminate_connection(self, connector) - - def set_metadata(self, volume, metadata): - """Set or Append metadata to a volume. - - :param volume : The :class: `Volume` to set metadata on - :param metadata: A dict of key/value pairs to set - """ - return self.manager.set_metadata(self, metadata) - - def upload_to_image(self, force, image_name, container_format, - disk_format): - """Upload a volume to image service as an image.""" - return self.manager.upload_to_image(self, force, image_name, - container_format, disk_format) - - def force_delete(self): - """Delete the specified volume ignoring its current state. - - :param volume: The UUID of the volume to force-delete. - """ - self.manager.force_delete(self) - - def reset_state(self, state): - """Update the volume with the provided state.""" - self.manager.reset_state(self, state) - - def extend(self, volume, new_size): - """Extend the size of the specified volume. - :param volume: The UUID of the volume to extend - :param new_size: The desired size to extend volume to. - """ - - self.manager.extend(self, new_size) - - def migrate_volume(self, host, force_host_copy): - """Migrate the volume to a new host.""" - self.manager.migrate_volume(self, host, force_host_copy) - - def retype(self, volume_type, policy): - """Change a volume's type.""" - self.manager.retype(self, volume_type, policy) - - def update_all_metadata(self, metadata): - """Update all metadata of this volume.""" - return self.manager.update_all_metadata(self, metadata) - - def update_readonly_flag(self, volume, read_only): - """Update the read-only access mode flag of the specified volume. - - :param volume: The UUID of the volume to update. - :param read_only: The value to indicate whether to update volume to - read-only access mode. - """ - self.manager.update_readonly_flag(self, read_only) - - def manage(self, host, ref, name=None, description=None, - volume_type=None, availability_zone=None, metadata=None, - bootable=False): - """Manage an existing volume.""" - self.manager.manage(host=host, ref=ref, name=name, - description=description, volume_type=volume_type, - availability_zone=availability_zone, - metadata=metadata, bootable=bootable) - - def unmanage(self, volume): - """Unmanage a volume.""" - self.manager.unmanage(volume) - - def promote(self, volume): - """Promote secondary to be primary in relationship.""" - self.manager.promote(volume) - - def reenable(self, volume): - """Sync the secondary volume with primary for a relationship.""" - self.manager.reenable(volume) - - -class VolumeManager(base.ManagerWithFind): - """Manage :class:`Volume` resources.""" - resource_class = Volume - - def create(self, size, consistencygroup_id=None, snapshot_id=None, - source_volid=None, name=None, description=None, - volume_type=None, user_id=None, - project_id=None, availability_zone=None, - metadata=None, imageRef=None, scheduler_hints=None, - source_replica=None): - """Creates a volume. - - :param size: Size of volume in GB - :param consistencygroup_id: ID of the consistencygroup - :param snapshot_id: ID of the snapshot - :param name: Name of the volume - :param description: Description of the volume - :param volume_type: Type of volume - :param user_id: User id derived from context - :param project_id: Project id derived from context - :param availability_zone: Availability Zone to use - :param metadata: Optional metadata to set on volume creation - :param imageRef: reference to an image stored in glance - :param source_volid: ID of source volume to clone from - :param source_replica: ID of source volume to clone replica - :param scheduler_hints: (optional extension) arbitrary key-value pairs - specified by the client to help boot an instance - :rtype: :class:`Volume` - """ - - if metadata is None: - volume_metadata = {} - else: - volume_metadata = metadata - - body = {'volume': {'size': size, - 'consistencygroup_id': consistencygroup_id, - 'snapshot_id': snapshot_id, - 'name': name, - 'description': description, - 'volume_type': volume_type, - 'user_id': user_id, - 'project_id': project_id, - 'availability_zone': availability_zone, - 'status': "creating", - 'attach_status': "detached", - 'metadata': volume_metadata, - 'imageRef': imageRef, - 'source_volid': source_volid, - 'source_replica': source_replica, - }} - - if scheduler_hints: - body['OS-SCH-HNT:scheduler_hints'] = scheduler_hints - - return self._create('/volumes', body, 'volume') - - def get(self, volume_id): - """Get a volume. - - :param volume_id: The ID of the volume to get. - :rtype: :class:`Volume` - """ - return self._get("/volumes/%s" % volume_id, "volume") - - def list(self, detailed=True, search_opts=None, marker=None, limit=None, - sort_key=None, sort_dir=None): - """Lists all volumes. - - :param detailed: Whether to return detailed volume info. - :param search_opts: Search options to filter out volumes. - :param marker: Begin returning volumes that appear later in the volume - list than that represented by this volume id. - :param limit: Maximum number of volumes to return. - :param sort_key: Key to be sorted. - :param sort_dir: Sort direction, should be 'desc' or 'asc'. - :rtype: list of :class:`Volume` - """ - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - if sort_key is not None: - if sort_key in SORT_KEY_VALUES: - qparams['sort_key'] = sort_key - else: - raise ValueError('sort_key must be one of the following: %s.' - % ', '.join(SORT_KEY_VALUES)) - - if sort_dir is not None: - if sort_dir in SORT_DIR_VALUES: - qparams['sort_dir'] = sort_dir - else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(SORT_DIR_VALUES)) - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - if qparams: - new_qparams = sorted(qparams.items(), key=lambda x: x[0]) - query_string = "?%s" % urlencode(new_qparams) - else: - query_string = "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/volumes%s%s" % (detail, query_string), - "volumes") - - def delete(self, volume): - """Delete a volume. - - :param volume: The :class:`Volume` to delete. - """ - self._delete("/volumes/%s" % base.getid(volume)) - - def update(self, volume, **kwargs): - """Update the name or description for a volume. - - :param volume: The :class:`Volume` to update. - """ - if not kwargs: - return - - body = {"volume": kwargs} - - self._update("/volumes/%s" % base.getid(volume), body) - - def _action(self, action, volume, info=None, **kwargs): - """Perform a volume "action." - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/volumes/%s/action' % base.getid(volume) - return self.api.client.post(url, body=body) - - def attach(self, volume, instance_uuid, mountpoint, mode='rw'): - """Set attachment metadata. - - :param volume: The :class:`Volume` (or its ID) - you would like to attach. - :param instance_uuid: uuid of the attaching instance. - :param mountpoint: mountpoint on the attaching instance. - :param mode: the access mode. - """ - return self._action('os-attach', - volume, - {'instance_uuid': instance_uuid, - 'mountpoint': mountpoint, - 'mode': mode}) - - def detach(self, volume): - """Clear attachment metadata. - - :param volume: The :class:`Volume` (or its ID) - you would like to detach. - """ - return self._action('os-detach', volume) - - def reserve(self, volume): - """Reserve this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to reserve. - """ - return self._action('os-reserve', volume) - - def unreserve(self, volume): - """Unreserve this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to unreserve. - """ - return self._action('os-unreserve', volume) - - def begin_detaching(self, volume): - """Begin detaching this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to detach. - """ - return self._action('os-begin_detaching', volume) - - def roll_detaching(self, volume): - """Roll detaching this volume. - - :param volume: The :class:`Volume` (or its ID) - you would like to roll detaching. - """ - return self._action('os-roll_detaching', volume) - - def initialize_connection(self, volume, connector): - """Initialize a volume connection. - - :param volume: The :class:`Volume` (or its ID). - :param connector: connector dict from nova. - """ - return self._action('os-initialize_connection', volume, - {'connector': connector})[1]['connection_info'] - - def terminate_connection(self, volume, connector): - """Terminate a volume connection. - - :param volume: The :class:`Volume` (or its ID). - :param connector: connector dict from nova. - """ - self._action('os-terminate_connection', volume, - {'connector': connector}) - - def set_metadata(self, volume, metadata): - """Update/Set a volumes metadata. - - :param volume: The :class:`Volume`. - :param metadata: A list of keys to be set. - """ - body = {'metadata': metadata} - return self._create("/volumes/%s/metadata" % base.getid(volume), - body, "metadata") - - def delete_metadata(self, volume, keys): - """Delete specified keys from volumes metadata. - - :param volume: The :class:`Volume`. - :param keys: A list of keys to be removed. - """ - for k in keys: - self._delete("/volumes/%s/metadata/%s" % (base.getid(volume), k)) - - def upload_to_image(self, volume, force, image_name, container_format, - disk_format): - """Upload volume to image service as image. - - :param volume: The :class:`Volume` to upload. - """ - return self._action('os-volume_upload_image', - volume, - {'force': force, - 'image_name': image_name, - 'container_format': container_format, - 'disk_format': disk_format}) - - def force_delete(self, volume): - return self._action('os-force_delete', base.getid(volume)) - - def reset_state(self, volume, state): - """Update the provided volume with the provided state.""" - return self._action('os-reset_status', volume, {'status': state}) - - def extend(self, volume, new_size): - return self._action('os-extend', - base.getid(volume), - {'new_size': new_size}) - - def get_encryption_metadata(self, volume_id): - """ - Retrieve the encryption metadata from the desired volume. - - :param volume_id: the id of the volume to query - :return: a dictionary of volume encryption metadata - """ - return self._get("/volumes/%s/encryption" % volume_id)._info - - def migrate_volume(self, volume, host, force_host_copy): - """Migrate volume to new host. - - :param volume: The :class:`Volume` to migrate - :param host: The destination host - :param force_host_copy: Skip driver optimizations - """ - - return self._action('os-migrate_volume', - volume, - {'host': host, 'force_host_copy': force_host_copy}) - - def migrate_volume_completion(self, old_volume, new_volume, error): - """Complete the migration from the old volume to the temp new one. - - :param old_volume: The original :class:`Volume` in the migration - :param new_volume: The new temporary :class:`Volume` in the migration - :param error: Inform of an error to cause migration cleanup - """ - - new_volume_id = base.getid(new_volume) - return self._action('os-migrate_volume_completion', - old_volume, - {'new_volume': new_volume_id, 'error': error})[1] - - def update_all_metadata(self, volume, metadata): - """Update all metadata of a volume. - - :param volume: The :class:`Volume`. - :param metadata: A list of keys to be updated. - """ - body = {'metadata': metadata} - return self._update("/volumes/%s/metadata" % base.getid(volume), - body) - - def update_readonly_flag(self, volume, flag): - return self._action('os-update_readonly_flag', - base.getid(volume), - {'readonly': flag}) - - def retype(self, volume, volume_type, policy): - """Change a volume's type. - - :param volume: The :class:`Volume` to retype - :param volume_type: New volume type - :param policy: Policy for migration during the retype - """ - return self._action('os-retype', - volume, - {'new_type': volume_type, - 'migration_policy': policy}) - - def set_bootable(self, volume, flag): - return self._action('os-set_bootable', - base.getid(volume), - {'bootable': flag}) - - def manage(self, host, ref, name=None, description=None, - volume_type=None, availability_zone=None, metadata=None, - bootable=False): - """Manage an existing volume.""" - body = {'volume': {'host': host, - 'ref': ref, - 'name': name, - 'description': description, - 'volume_type': volume_type, - 'availability_zone': availability_zone, - 'metadata': metadata, - 'bootable': bootable - }} - return self._create('/os-volume-manage', body, 'volume') - - def unmanage(self, volume): - """Unmanage a volume.""" - return self._action('os-unmanage', volume, None) - - def promote(self, volume): - """Promote secondary to be primary in relationship.""" - return self._action('os-promote-replica', volume, None) - - def reenable(self, volume): - """Sync the secondary volume with primary for a relationship.""" - return self._action('os-reenable-replica', volume, None) diff --git a/awx/lib/site-packages/crum/__init__.py b/awx/lib/site-packages/crum/__init__.py deleted file mode 100644 index fb26142466..0000000000 --- a/awx/lib/site-packages/crum/__init__.py +++ /dev/null @@ -1,87 +0,0 @@ -# Python -import contextlib -import logging -import threading - -_thread_locals = threading.local() - -_logger = logging.getLogger('crum') - -__version__ = '0.6.1' - -__all__ = ['get_current_request', 'get_current_user', 'impersonate'] - - -@contextlib.contextmanager -def impersonate(user=None): - """Temporarily impersonate the given user for audit trails.""" - try: - current_user = get_current_user(_return_false=True) - set_current_user(user) - yield user - finally: - set_current_user(current_user) - - -def get_current_request(): - """Return the request associated with the current thread.""" - return getattr(_thread_locals, 'request', None) - - -def set_current_request(request=None): - """Update the request associated with the current thread.""" - _thread_locals.request = request - # Clear the current user if also clearing the request. - if not request: - set_current_user(False) - - -def get_current_user(_return_false=False): - """Return the user associated with the current request thread.""" - from crum.signals import current_user_getter - top_priority = -9999 - top_user = False if _return_false else None - results = current_user_getter.send_robust(get_current_user) - for receiver, response in results: - priority = 0 - if isinstance(response, Exception): - _logger.exception('%r raised exception: %s', receiver, response) - continue - elif isinstance(response, (tuple, list)) and response: - user = response[0] - if len(response) > 1: - priority = response[1] - elif response or response in (None, False): - user = response - else: - _logger.error('%r returned invalid response: %r', receiver, - response) - continue - if user is not False: - if priority > top_priority: - top_priority = priority - top_user = user - return top_user - - -def set_current_user(user=None): - """Update the user associated with the current request thread.""" - from crum.signals import current_user_setter - results = current_user_setter.send_robust(set_current_user, user=user) - for receiver, response in results: - if isinstance(response, Exception): - _logger.exception('%r raised exception: %s', receiver, response) - - -class CurrentRequestUserMiddleware(object): - """Middleware to capture the request and user from the current thread.""" - - def process_request(self, request): - set_current_request(request) - - def process_response(self, request, response): - set_current_request(None) - return response - - def process_exception(self, request, exception): - set_current_request(None) diff --git a/awx/lib/site-packages/crum/signals.py b/awx/lib/site-packages/crum/signals.py deleted file mode 100644 index 6ca41a373f..0000000000 --- a/awx/lib/site-packages/crum/signals.py +++ /dev/null @@ -1,44 +0,0 @@ -# Django -from django.dispatch import Signal, receiver - -__all__ = ['current_user_getter'] - - -# Signal used when getting current user. Receivers should return a tuple of -# (user, priority). -current_user_getter = Signal(providing_args=[]) - - -# Signal used when setting current user. Receivers should store the current -# user as needed. Return values are ignored. -current_user_setter = Signal(providing_args=['user']) - - -@receiver(current_user_getter) -def _get_current_user_from_request(sender, **kwargs): - """Signal handler to retrieve current user from request.""" - from crum import get_current_request - return (getattr(get_current_request(), 'user', False), -10) - - -@receiver(current_user_getter) -def _get_current_user_from_thread_locals(sender, **kwargs): - """Signal handler to retrieve current user from thread locals.""" - from crum import _thread_locals - return (getattr(_thread_locals, 'user', False), 10) - - -@receiver(current_user_setter) -def _set_current_user_on_request(sender, **kwargs): - """Signal handler to store current user to request.""" - from crum import get_current_request - request = get_current_request() - if request: - request.user = kwargs['user'] - - -@receiver(current_user_setter) -def _set_current_user_on_thread_locals(sender, **kwargs): - """Signal handler to store current user on thread locals.""" - from crum import _thread_locals - _thread_locals.user = kwargs['user'] diff --git a/awx/lib/site-packages/d2to1/__init__.py b/awx/lib/site-packages/d2to1/__init__.py deleted file mode 100644 index 4089e8fa52..0000000000 --- a/awx/lib/site-packages/d2to1/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -try: - __version__ = __import__('pkg_resources').get_distribution('d2to1').version -except: - __version__ = '' diff --git a/awx/lib/site-packages/d2to1/core.py b/awx/lib/site-packages/d2to1/core.py deleted file mode 100644 index 929f575764..0000000000 --- a/awx/lib/site-packages/d2to1/core.py +++ /dev/null @@ -1,83 +0,0 @@ -import os -import sys -import warnings - -from distutils.core import Distribution as _Distribution -from distutils.errors import DistutilsFileError, DistutilsSetupError -from setuptools.dist import _get_unpatched - -from .extern import six -from .util import DefaultGetDict, IgnoreDict, cfg_to_args - - -_Distribution = _get_unpatched(_Distribution) - - -def d2to1(dist, attr, value): - """Implements the actual d2to1 setup() keyword. When used, this should be - the only keyword in your setup() aside from `setup_requires`. - - If given as a string, the value of d2to1 is assumed to be the relative path - to the setup.cfg file to use. Otherwise, if it evaluates to true, it - simply assumes that d2to1 should be used, and the default 'setup.cfg' is - used. - - This works by reading the setup.cfg file, parsing out the supported - metadata and command options, and using them to rebuild the - `DistributionMetadata` object and set the newly added command options. - - The reason for doing things this way is that a custom `Distribution` class - will not play nicely with setup_requires; however, this implementation may - not work well with distributions that do use a `Distribution` subclass. - """ - - if not value: - return - if isinstance(value, six.string_types): - path = os.path.abspath(value) - else: - path = os.path.abspath('setup.cfg') - if not os.path.exists(path): - raise DistutilsFileError( - 'The setup.cfg file %s does not exist.' % path) - - # Converts the setup.cfg file to setup() arguments - try: - attrs = cfg_to_args(path) - except: - e = sys.exc_info()[1] - raise DistutilsSetupError( - 'Error parsing %s: %s: %s' % (path, e.__class__.__name__, - e.args[0])) - - # Repeat some of the Distribution initialization code with the newly - # provided attrs - if attrs: - # Skips 'options' and 'licence' support which are rarely used; may add - # back in later if demanded - for key, val in six.iteritems(attrs): - if hasattr(dist.metadata, 'set_' + key): - getattr(dist.metadata, 'set_' + key)(val) - elif hasattr(dist.metadata, key): - setattr(dist.metadata, key, val) - elif hasattr(dist, key): - setattr(dist, key, val) - else: - msg = 'Unknown distribution option: %s' % repr(key) - warnings.warn(msg) - - # Re-finalize the underlying Distribution - _Distribution.finalize_options(dist) - - # This bit comes out of distribute/setuptools - if isinstance(dist.metadata.version, six.integer_types + (float,)): - # Some people apparently take "version number" too literally :) - dist.metadata.version = str(dist.metadata.version) - - # This bit of hackery is necessary so that the Distribution will ignore - # normally unsupport command options (namely pre-hooks and post-hooks). - # dist.command_options is normally a dict mapping command names to dicts of - # their options. Now it will be a defaultdict that returns IgnoreDicts for - # the each command's options so we can pass through the unsupported options - ignore = ['pre_hook.*', 'post_hook.*'] - dist.command_options = DefaultGetDict(lambda: IgnoreDict(ignore)) diff --git a/awx/lib/site-packages/d2to1/extern/__init__.py b/awx/lib/site-packages/d2to1/extern/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/d2to1/extern/six.py b/awx/lib/site-packages/d2to1/extern/six.py deleted file mode 100644 index 0cdd1c7e3d..0000000000 --- a/awx/lib/site-packages/d2to1/extern/six.py +++ /dev/null @@ -1,386 +0,0 @@ -# Copyright (c) 2010-2011 Benjamin Peterson -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -"""Utilities for writing code that runs on Python 2 and 3""" - -import operator -import sys -import types - -__author__ = "Benjamin Peterson <benjamin@python.org>" -__version__ = "1.2.0" - - -# True if we are running on Python 3. -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform == "java": - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) - # This is a bit ugly, but it avoids running this again. - delattr(tp, self.name) - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - - -class _MovedItems(types.ModuleType): - """Lazy loading of moved objects""" - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("reload_module", "__builtin__", "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("winreg", "_winreg"), -] -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) -del attr - -moves = sys.modules["six.moves"] = _MovedItems("moves") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_code = "__code__" - _func_defaults = "__defaults__" - - _iterkeys = "keys" - _itervalues = "values" - _iteritems = "items" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_code = "func_code" - _func_defaults = "func_defaults" - - _iterkeys = "iterkeys" - _itervalues = "itervalues" - _iteritems = "iteritems" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -if PY3: - def get_unbound_function(unbound): - return unbound - - Iterator = object - - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) -else: - def get_unbound_function(unbound): - return unbound.im_func - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) - - -def iterkeys(d): - """Return an iterator over the keys of a dictionary.""" - return iter(getattr(d, _iterkeys)()) - -def itervalues(d): - """Return an iterator over the values of a dictionary.""" - return iter(getattr(d, _itervalues)()) - -def iteritems(d): - """Return an iterator over the (key, value) pairs of a dictionary.""" - return iter(getattr(d, _iteritems)()) - - -if PY3: - def b(s): - return s.encode("latin-1") - def u(s): - return s - if sys.version_info[1] <= 1: - def int2byte(i): - return bytes((i,)) - else: - # This is about 2x faster than the implementation above on 3.2+ - int2byte = operator.methodcaller("to_bytes", 1, "big") - import io - StringIO = io.StringIO - BytesIO = io.BytesIO -else: - def b(s): - return s - def u(s): - return unicode(s, "unicode_escape") - int2byte = chr - import StringIO - StringIO = BytesIO = StringIO.StringIO -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -if PY3: - import builtins - exec_ = getattr(builtins, "exec") - - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - - print_ = getattr(builtins, "print") - del builtins - -else: - def exec_(code, globs=None, locs=None): - """Execute code in a namespace.""" - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - - - def print_(*args, **kwargs): - """The new-style print function.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - def write(data): - if not isinstance(data, basestring): - data = str(data) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) - -_add_doc(reraise, """Reraise an exception.""") - - -def with_metaclass(meta, base=object): - """Create a base class with a metaclass.""" - return meta("NewBase", (base,), {}) diff --git a/awx/lib/site-packages/d2to1/util.py b/awx/lib/site-packages/d2to1/util.py deleted file mode 100644 index 88c262314f..0000000000 --- a/awx/lib/site-packages/d2to1/util.py +++ /dev/null @@ -1,580 +0,0 @@ -"""The code in this module is mostly copy/pasted out of the distutils2 source -code, as recommended by Tarek Ziade. As such, it may be subject to some change -as distutils2 development continues, and will have to be kept up to date. - -I didn't want to use it directly from distutils2 itself, since I do not want it -to be an installation dependency for our packages yet--it is still too unstable -(the latest version on PyPI doesn't even install). -""" - -# These first two imports are not used, but are needed to get around an -# irritating Python bug that can crop up when using ./setup.py test. -# See: http://www.eby-sarna.com/pipermail/peak/2010-May/003355.html -try: - import multiprocessing -except ImportError: - pass -import logging - -import os -import re -import sys -import traceback - -from collections import defaultdict - -import distutils.ccompiler - -from distutils import log -from distutils.errors import (DistutilsOptionError, DistutilsModuleError, - DistutilsFileError) -from setuptools.command.egg_info import manifest_maker -from setuptools.dist import Distribution -from setuptools.extension import Extension - -from .extern.six import moves as m -RawConfigParser = m.configparser.RawConfigParser - - -# A simplified RE for this; just checks that the line ends with version -# predicates in () -_VERSION_SPEC_RE = re.compile(r'\s*(.*?)\s*\((.*)\)\s*$') - - -# Mappings from setup() keyword arguments to setup.cfg options; -# The values are (section, option) tuples, or simply (section,) tuples if -# the option has the same name as the setup() argument -D1_D2_SETUP_ARGS = { - "name": ("metadata",), - "version": ("metadata",), - "author": ("metadata",), - "author_email": ("metadata",), - "maintainer": ("metadata",), - "maintainer_email": ("metadata",), - "url": ("metadata", "home_page"), - "description": ("metadata", "summary"), - "keywords": ("metadata",), - "long_description": ("metadata", "description"), - "download-url": ("metadata",), - "classifiers": ("metadata", "classifier"), - "platforms": ("metadata", "platform"), # ** - "license": ("metadata",), - # Use setuptools install_requires, not - # broken distutils requires - "install_requires": ("metadata", "requires_dist"), - "setup_requires": ("metadata", "setup_requires_dist"), - "provides": ("metadata", "provides_dist"), # ** - "obsoletes": ("metadata", "obsoletes_dist"), # ** - "package_dir": ("files", 'packages_root'), - "packages": ("files",), - "package_data": ("files",), - "data_files": ("files",), - "scripts": ("files",), - "py_modules": ("files", "modules"), # ** - "cmdclass": ("global", "commands"), - # Not supported in distutils2, but provided for - # backwards compatibility with setuptools - "use_2to3": ("backwards_compat", "use_2to3"), - "zip_safe": ("backwards_compat", "zip_safe"), - "tests_require": ("backwards_compat", "tests_require"), - "dependency_links": ("backwards_compat",), - "include_package_data": ("backwards_compat",), -} - -# setup() arguments that can have multiple values in setup.cfg -MULTI_FIELDS = ("classifiers", - "platforms", - "install_requires", - "provides", - "obsoletes", - "packages", - "package_data", - "data_files", - "scripts", - "py_modules", - "dependency_links", - "setup_requires", - "tests_require", - "cmdclass") - -# setup() arguments that contain boolean values -BOOL_FIELDS = ("use_2to3", "zip_safe", "include_package_data") - - -CSV_FIELDS = ("keywords",) - - -log.set_verbosity(log.INFO) - - -def resolve_name(name): - """Resolve a name like ``module.object`` to an object and return it. - - Raise ImportError if the module or name is not found. - """ - - parts = name.split('.') - cursor = len(parts) - 1 - module_name = parts[:cursor] - attr_name = parts[-1] - - while cursor > 0: - try: - ret = __import__('.'.join(module_name), fromlist=[attr_name]) - break - except ImportError: - if cursor == 0: - raise - cursor -= 1 - module_name = parts[:cursor] - attr_name = parts[cursor] - ret = '' - - for part in parts[cursor:]: - try: - ret = getattr(ret, part) - except AttributeError: - raise ImportError(name) - - return ret - - -def cfg_to_args(path='setup.cfg'): - """ Distutils2 to distutils1 compatibility util. - - This method uses an existing setup.cfg to generate a dictionary of - keywords that can be used by distutils.core.setup(kwargs**). - - :param file: - The setup.cfg path. - :raises DistutilsFileError: - When the setup.cfg file is not found. - - """ - - # The method source code really starts here. - parser = RawConfigParser() - if not os.path.exists(path): - raise DistutilsFileError("file '%s' does not exist" % - os.path.abspath(path)) - parser.read(path) - config = {} - for section in parser.sections(): - config[section] = dict(parser.items(section)) - - # Run setup_hooks, if configured - setup_hooks = has_get_option(config, 'global', 'setup_hooks') - package_dir = has_get_option(config, 'files', 'packages_root') - - # Add the source package directory to sys.path in case it contains - # additional hooks, and to make sure it's on the path before any existing - # installations of the package - if package_dir: - package_dir = os.path.abspath(package_dir) - sys.path.insert(0, package_dir) - - try: - if setup_hooks: - setup_hooks = split_multiline(setup_hooks) - for hook in setup_hooks: - hook_fn = resolve_name(hook) - try : - hook_fn(config) - except SystemExit: - log.error('setup hook %s terminated the installation') - except: - e = sys.exc_info()[1] - log.error('setup hook %s raised exception: %s\n' % - (hook, e)) - log.error(traceback.format_exc()) - sys.exit(1) - - kwargs = setup_cfg_to_setup_kwargs(config) - - register_custom_compilers(config) - - ext_modules = get_extension_modules(config) - if ext_modules: - kwargs['ext_modules'] = ext_modules - - entry_points = get_entry_points(config) - if entry_points: - kwargs['entry_points'] = entry_points - - wrap_commands(kwargs) - - # Handle the [files]/extra_files option - extra_files = has_get_option(config, 'files', 'extra_files') - if extra_files: - extra_files = split_multiline(extra_files) - # Let's do a sanity check - for filename in extra_files: - if not os.path.exists(filename): - raise DistutilsFileError( - '%s from the extra_files option in setup.cfg does not ' - 'exist' % filename) - # Unfortunately the only really sensible way to do this is to - # monkey-patch the manifest_maker class - @monkeypatch_method(manifest_maker) - def add_defaults(self, extra_files=extra_files, log=log): - log.info('[d2to1] running patched manifest_maker command ' - 'with extra_files support') - add_defaults._orig(self) - self.filelist.extend(extra_files) - - finally: - # Perform cleanup if any paths were added to sys.path - if package_dir: - sys.path.pop(0) - - return kwargs - - -def setup_cfg_to_setup_kwargs(config): - """Processes the setup.cfg options and converts them to arguments accepted - by setuptools' setup() function. - """ - - kwargs = {} - - for arg in D1_D2_SETUP_ARGS: - if len(D1_D2_SETUP_ARGS[arg]) == 2: - # The distutils field name is different than distutils2's. - section, option = D1_D2_SETUP_ARGS[arg] - - elif len(D1_D2_SETUP_ARGS[arg]) == 1: - # The distutils field name is the same thant distutils2's. - section = D1_D2_SETUP_ARGS[arg][0] - option = arg - - in_cfg_value = has_get_option(config, section, option) - if not in_cfg_value: - # There is no such option in the setup.cfg - if arg == "long_description": - in_cfg_value = has_get_option(config, section, - "description_file") - if in_cfg_value: - in_cfg_value = split_multiline(in_cfg_value) - value = '' - for filename in in_cfg_value: - description_file = open(filename) - try: - value += description_file.read().strip() + '\n\n' - finally: - description_file.close() - in_cfg_value = value - else: - continue - - if arg in CSV_FIELDS: - in_cfg_value = split_csv(in_cfg_value) - if arg in MULTI_FIELDS: - in_cfg_value = split_multiline(in_cfg_value) - elif arg in BOOL_FIELDS: - # Provide some flexibility here... - if in_cfg_value.lower() in ('true', 't', '1', 'yes', 'y'): - in_cfg_value = True - else: - in_cfg_value = False - - if in_cfg_value: - if arg in ('install_requires', 'tests_require'): - # Replaces PEP345-style version specs with the sort expected by - # setuptools - in_cfg_value = [_VERSION_SPEC_RE.sub(r'\1\2', pred) - for pred in in_cfg_value] - elif arg == 'package_dir': - in_cfg_value = {'': in_cfg_value} - elif arg in ('package_data', 'data_files'): - data_files = {} - firstline = True - prev = None - for line in in_cfg_value: - if '=' in line: - key, value = line.split('=', 1) - key, value = (key.strip(), value.strip()) - if key in data_files: - # Multiple duplicates of the same package name; - # this is for backwards compatibility of the old - # format prior to d2to1 0.2.6. - prev = data_files[key] - prev.extend(value.split()) - else: - prev = data_files[key.strip()] = value.split() - elif firstline: - raise DistutilsOptionError( - 'malformed package_data first line %r (misses ' - '"=")' % line) - else: - prev.extend(line.strip().split()) - firstline = False - if arg == 'data_files': - # the data_files value is a pointlessly different structure - # from the package_data value - data_files = list(data_files.items()) - in_cfg_value = data_files - elif arg == 'cmdclass': - cmdclass = {} - dist = Distribution() - for cls in in_cfg_value: - cls = resolve_name(cls) - cmd = cls(dist) - cmdclass[cmd.get_command_name()] = cls - in_cfg_value = cmdclass - - kwargs[arg] = in_cfg_value - - return kwargs - - -def register_custom_compilers(config): - """Handle custom compilers; this has no real equivalent in distutils, where - additional compilers could only be added programmatically, so we have to - hack it in somehow. - """ - - compilers = has_get_option(config, 'global', 'compilers') - if compilers: - compilers = split_multiline(compilers) - for compiler in compilers: - compiler = resolve_name(compiler) - - # In distutils2 compilers these class attributes exist; for - # distutils1 we just have to make something up - if hasattr(compiler, 'name'): - name = compiler.name - else: - name = compiler.__name__ - if hasattr(compiler, 'description'): - desc = compiler.description - else: - desc = 'custom compiler %s' % name - - module_name = compiler.__module__ - # Note; this *will* override built in compilers with the same name - # TODO: Maybe display a warning about this? - cc = distutils.ccompiler.compiler_class - cc[name] = (module_name, compiler.__name__, desc) - - # HACK!!!! Distutils assumes all compiler modules are in the - # distutils package - sys.modules['distutils.' + module_name] = sys.modules[module_name] - - -def get_extension_modules(config): - """Handle extension modules""" - - EXTENSION_FIELDS = ("sources", - "include_dirs", - "define_macros", - "undef_macros", - "library_dirs", - "libraries", - "runtime_library_dirs", - "extra_objects", - "extra_compile_args", - "extra_link_args", - "export_symbols", - "swig_opts", - "depends") - - ext_modules = [] - for section in config: - if ':' in section: - labels = section.split(':', 1) - else: - # Backwards compatibility for old syntax; don't use this though - labels = section.split('=', 1) - labels = [l.strip() for l in labels] - if (len(labels) == 2) and (labels[0] == 'extension'): - ext_args = {} - for field in EXTENSION_FIELDS: - value = has_get_option(config, section, field) - # All extension module options besides name can have multiple - # values - if not value: - continue - value = split_multiline(value) - if field == 'define_macros': - macros = [] - for macro in value: - macro = macro.split('=', 1) - if len(macro) == 1: - macro = (macro[0].strip(), None) - else: - macro = (macro[0].strip(), macro[1].strip()) - macros.append(macro) - value = macros - ext_args[field] = value - if ext_args: - if 'name' not in ext_args: - ext_args['name'] = labels[1] - ext_modules.append(Extension(ext_args.pop('name'), - **ext_args)) - return ext_modules - - -def get_entry_points(config): - """Process the [entry_points] section of setup.cfg to handle setuptools - entry points. This is, of course, not a standard feature of - distutils2/packaging, but as there is not currently a standard alternative - in packaging, we provide support for them. - """ - - if not 'entry_points' in config: - return {} - - return dict((option, split_multiline(value)) - for option, value in config['entry_points'].items()) - - -def wrap_commands(kwargs): - dist = Distribution() - - # This should suffice to get the same config values and command classes - # that the actual Distribution will see (not counting cmdclass, which is - # handled below) - dist.parse_config_files() - - for cmd, _ in dist.get_command_list(): - hooks = {} - for opt, val in dist.get_option_dict(cmd).items(): - val = val[1] - if opt.startswith('pre_hook.') or opt.startswith('post_hook.'): - hook_type, alias = opt.split('.', 1) - hook_dict = hooks.setdefault(hook_type, {}) - hook_dict[alias] = val - if not hooks: - continue - - if 'cmdclass' in kwargs and cmd in kwargs['cmdclass']: - cmdclass = kwargs['cmdclass'][cmd] - else: - cmdclass = dist.get_command_class(cmd) - - new_cmdclass = wrap_command(cmd, cmdclass, hooks) - kwargs.setdefault('cmdclass', {})[cmd] = new_cmdclass - - -def wrap_command(cmd, cmdclass, hooks): - def run(self, cmdclass=cmdclass): - self.run_command_hooks('pre_hook') - cmdclass.run(self) - self.run_command_hooks('post_hook') - - return type(cmd, (cmdclass, object), - {'run': run, 'run_command_hooks': run_command_hooks, - 'pre_hook': hooks.get('pre_hook'), - 'post_hook': hooks.get('post_hook')}) - - -def run_command_hooks(cmd_obj, hook_kind): - """Run hooks registered for that command and phase. - - *cmd_obj* is a finalized command object; *hook_kind* is either - 'pre_hook' or 'post_hook'. - """ - - if hook_kind not in ('pre_hook', 'post_hook'): - raise ValueError('invalid hook kind: %r' % hook_kind) - - hooks = getattr(cmd_obj, hook_kind, None) - - if hooks is None: - return - - for hook in hooks.values(): - if isinstance(hook, str): - try: - hook_obj = resolve_name(hook) - except ImportError: - err = sys.exc_info()[1] # For py3k - raise DistutilsModuleError('cannot find hook %s: %s' % - (hook,err)) - else: - hook_obj = hook - - if not hasattr(hook_obj, '__call__'): - raise DistutilsOptionError('hook %r is not callable' % hook) - - log.info('running %s %s for command %s', - hook_kind, hook, cmd_obj.get_command_name()) - - try : - hook_obj(cmd_obj) - except: - e = sys.exc_info()[1] - log.error('hook %s raised exception: %s\n' % (hook, e)) - log.error(traceback.format_exc()) - sys.exit(1) - - -def has_get_option(config, section, option): - if section in config and option in config[section]: - return config[section][option] - elif section in config and option.replace('_', '-') in config[section]: - return config[section][option.replace('_', '-')] - else: - return False - - -def split_multiline(value): - """Special behaviour when we have a multi line options""" - - value = [element for element in - (line.strip() for line in value.split('\n')) - if element] - return value - - -def split_csv(value): - """Special behaviour when we have a comma separated options""" - - value = [element for element in - (chunk.strip() for chunk in value.split(',')) - if element] - return value - - -def monkeypatch_method(cls): - """A function decorator to monkey-patch a method of the same name on the - given class. - """ - - def wrapper(func): - orig = getattr(cls, func.__name__, None) - if orig and not hasattr(orig, '_orig'): # Already patched - setattr(func, '_orig', orig) - setattr(cls, func.__name__, func) - return func - - return wrapper - - -# The following classes are used to hack Distribution.command_options a bit -class DefaultGetDict(defaultdict): - """Like defaultdict, but the get() method also sets and returns the default - value. - """ - - def get(self, key, default=None): - if default is None: - default = self.default_factory() - return super(DefaultGetDict, self).setdefault(key, default) - - -class IgnoreDict(dict): - """A dictionary that ignores any insertions in which the key is a string - matching any string in `ignore`. The ignore list can also contain wildcard - patterns using '*'. - """ - - def __init__(self, ignore): - self.__ignore = re.compile(r'(%s)' % ('|'.join( - [pat.replace('*', '.*') - for pat in ignore]))) - - def __setitem__(self, key, val): - if self.__ignore.match(key): - return - super(IgnoreDict, self).__setitem__(key, val) diff --git a/awx/lib/site-packages/d2to1/zestreleaser.py b/awx/lib/site-packages/d2to1/zestreleaser.py deleted file mode 100644 index a2b663208a..0000000000 --- a/awx/lib/site-packages/d2to1/zestreleaser.py +++ /dev/null @@ -1,161 +0,0 @@ -"""zest.releaser entry points to support projects using distutils2-like -setup.cfg files. The only actual functionality this adds is to update the -version option in a setup.cfg file, if it exists. If setup.cfg does not exist, -or does not contain a version option, then this does nothing. - -TODO: d2to1 theoretically supports using a different filename for setup.cfg; -this does not support that. We could hack in support, though I'm not sure how -useful the original functionality is to begin with (and it might be removed) so -we ignore that for now. - -TODO: There exists a proposal -(http://mail.python.org/pipermail/distutils-sig/2011-March/017628.html) to add -a 'version-from-file' option (or something of the like) to distutils2; if this -is added then support for it should be included here as well. -""" - - -import logging -import os - -from .extern.six import print_ -from .extern.six import moves as m -ConfigParser = m.configparser.ConfigParser - - -logger = logging.getLogger(__name__) - - - -def update_setupcfg_version(filename, version): - """Opens the given setup.cfg file, locates the version option in the - [metadata] section, updates it to the new version. - """ - - setup_cfg = open(filename).readlines() - current_section = None - updated = False - - for idx, line in enumerate(setup_cfg): - m = ConfigParser.SECTCRE.match(line) - if m: - if current_section == 'metadata': - # We already parsed the entire metadata section without finding - # a version line, and are now moving into a new section - break - current_section = m.group('header') - continue - - if '=' not in line: - continue - - opt, val = line.split('=', 1) - opt, val = opt.strip(), val.strip() - if current_section == 'metadata' and opt == 'version': - setup_cfg[idx] = 'version = %s\n' % version - updated = True - break - - if updated: - open(filename, 'w').writelines(setup_cfg) - logger.info("Set %s's version to %r" % (os.path.basename(filename), - version)) - - -def prereleaser_middle(data): - filename = os.path.join(data['workingdir'], 'setup.cfg') - if os.path.exists(filename): - update_setupcfg_version(filename, data['new_version']) - - -def releaser_middle(data): - """ - releaser.middle hook to monkey-patch zest.releaser to support signed - tagging--currently this is the only way to do this. Also monkey-patches to - disable an annoyance where zest.releaser only creates .zip source - distributions. This is supposedly a workaround for a bug in Python 2.4, - but we don't care about Python 2.4. - """ - - import os - import sys - - from zest.releaser.git import Git - from zest.releaser.release import Releaser - - # Copied verbatim from zest.releaser, but with the cmd string modified to - # use the -s option to create a signed tag - def _my_create_tag(self, version): - msg = "Tagging %s" % (version,) - cmd = 'git tag -s %s -m "%s"' % (version, msg) - if os.path.isdir('.git/svn'): - print_("\nEXPERIMENTAL support for git-svn tagging!\n") - cur_branch = open('.git/HEAD').read().strip().split('/')[-1] - print_("You are on branch %s." % (cur_branch,)) - if cur_branch != 'master': - print_("Only the master branch is supported for git-svn " - "tagging.") - print_("Please tag yourself.") - print_("'git tag' needs to list tag named %s." % (version,)) - sys.exit() - cmd = [cmd] - local_head = open('.git/refs/heads/master').read() - trunk = open('.git/refs/remotes/trunk').read() - if local_head != trunk: - print_("Your local master diverges from trunk.\n") - # dcommit before local tagging - cmd.insert(0, 'git svn dcommit') - # create tag in svn - cmd.append('git svn tag -m "%s" %s' % (msg, version)) - return cmd - - # Similarly copied from zer.releaser to support use of 'v' in front - # of the version number - def _my_make_tag(self): - from zest.releaser import utils - from os import system - - if self.data['tag_already_exists']: - return - cmds = self.vcs.cmd_create_tag(self.data['version']) - if not isinstance(cmds, list): - cmds = [cmds] - if len(cmds) == 1: - print_("Tag needed to proceed, you can use the following command:") - for cmd in cmds: - print_(cmd) - if utils.ask("Run this command"): - print_(system(cmd)) - else: - # all commands are needed in order to proceed normally - print_("Please create a tag for %s yourself and rerun." % \ - (self.data['version'],)) - sys.exit() - if not self.vcs.tag_exists('v' + self.data['version']): - print_("\nFailed to create tag %s!" % (self.data['version'],)) - sys.exit() - - # Normally all this does is to return '--formats=zip', which is currently - # hard-coded as an option to always add to the sdist command; they ought to - # make this actually optional - def _my_sdist_options(self): - return '' - - Git.cmd_create_tag = _my_create_tag - Releaser._make_tag = _my_make_tag - Releaser._sdist_options = _my_sdist_options - - -def postreleaser_before(data): - """ - Fix the irritating .dev0 default appended to new development versions by - zest.releaser to just append ".dev" without the "0". - """ - - data['dev_version_template'] = '%(new_version)s.dev' - - -def postreleaser_middle(data): - filename = os.path.join(data['workingdir'], 'setup.cfg') - if os.path.exists(filename): - update_setupcfg_version(filename, data['dev_version']) diff --git a/awx/lib/site-packages/dateutil/__init__.py b/awx/lib/site-packages/dateutil/__init__.py deleted file mode 100644 index f8fde9ba08..0000000000 --- a/awx/lib/site-packages/dateutil/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -__version__ = "2.4.0" diff --git a/awx/lib/site-packages/dateutil/easter.py b/awx/lib/site-packages/dateutil/easter.py deleted file mode 100644 index 8d30c4ebda..0000000000 --- a/awx/lib/site-packages/dateutil/easter.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers a generic easter computing method for any given year, using -Western, Orthodox or Julian algorithms. -""" - -import datetime - -__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"] - -EASTER_JULIAN = 1 -EASTER_ORTHODOX = 2 -EASTER_WESTERN = 3 - - -def easter(year, method=EASTER_WESTERN): - """ - This method was ported from the work done by GM Arts, - on top of the algorithm by Claus Tondering, which was - based in part on the algorithm of Ouding (1940), as - quoted in "Explanatory Supplement to the Astronomical - Almanac", P. Kenneth Seidelmann, editor. - - This algorithm implements three different easter - calculation methods: - - 1 - Original calculation in Julian calendar, valid in - dates after 326 AD - 2 - Original method, with date converted to Gregorian - calendar, valid in years 1583 to 4099 - 3 - Revised method, in Gregorian calendar, valid in - years 1583 to 4099 as well - - These methods are represented by the constants: - - EASTER_JULIAN = 1 - EASTER_ORTHODOX = 2 - EASTER_WESTERN = 3 - - The default method is method 3. - - More about the algorithm may be found at: - - http://users.chariot.net.au/~gmarts/eastalg.htm - - and - - http://www.tondering.dk/claus/calendar.html - - """ - - if not (1 <= method <= 3): - raise ValueError("invalid method") - - # g - Golden year - 1 - # c - Century - # h - (23 - Epact) mod 30 - # i - Number of days from March 21 to Paschal Full Moon - # j - Weekday for PFM (0=Sunday, etc) - # p - Number of days from March 21 to Sunday on or before PFM - # (-6 to 28 methods 1 & 3, to 56 for method 2) - # e - Extra days to add for method 2 (converting Julian - # date to Gregorian date) - - y = year - g = y % 19 - e = 0 - if method < 3: - # Old method - i = (19*g + 15) % 30 - j = (y + y//4 + i) % 7 - if method == 2: - # Extra dates to convert Julian to Gregorian date - e = 10 - if y > 1600: - e = e + y//100 - 16 - (y//100 - 16)//4 - else: - # New method - c = y//100 - h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30 - i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11)) - j = (y + y//4 + i + 2 - c + c//4) % 7 - - # p can be from -6 to 56 corresponding to dates 22 March to 23 May - # (later dates apply to method 2, although 23 May never actually occurs) - p = i - j + e - d = 1 + (p + 27 + (p + 6)//40) % 31 - m = 3 + (p + 26)//30 - return datetime.date(int(y), int(m), int(d)) diff --git a/awx/lib/site-packages/dateutil/parser.py b/awx/lib/site-packages/dateutil/parser.py deleted file mode 100644 index 8b6c2d28b8..0000000000 --- a/awx/lib/site-packages/dateutil/parser.py +++ /dev/null @@ -1,935 +0,0 @@ -# -*- coding:iso-8859-1 -*- -""" -This module offers a generic date/time string parser which is able to parse -most known formats to represent a date and/or time. -""" -from __future__ import unicode_literals - -import datetime -import string -import time -import collections -from io import StringIO - -from six import text_type, binary_type, integer_types - -from . import relativedelta -from . import tz - -__all__ = ["parse", "parserinfo"] - - -# Some pointers: -# -# http://www.cl.cam.ac.uk/~mgk25/iso-time.html -# http://www.iso.ch/iso/en/prods-services/popstds/datesandtime.html -# http://www.w3.org/TR/NOTE-datetime -# http://ringmaster.arc.nasa.gov/tools/time_formats.html -# http://search.cpan.org/author/MUIR/Time-modules-2003.0211/lib/Time/ParseDate.pm -# http://stein.cshl.org/jade/distrib/docs/java.text.SimpleDateFormat.html - - -class _timelex(object): - - def __init__(self, instream): - if isinstance(instream, text_type): - instream = StringIO(instream) - self.instream = instream - self.wordchars = ('abcdfeghijklmnopqrstuvwxyz' - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_' - 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ' - 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ') - self.numchars = '0123456789' - self.whitespace = ' \t\r\n' - self.charstack = [] - self.tokenstack = [] - self.eof = False - - def get_token(self): - if self.tokenstack: - return self.tokenstack.pop(0) - seenletters = False - token = None - state = None - wordchars = self.wordchars - numchars = self.numchars - whitespace = self.whitespace - while not self.eof: - if self.charstack: - nextchar = self.charstack.pop(0) - else: - nextchar = self.instream.read(1) - while nextchar == '\x00': - nextchar = self.instream.read(1) - if not nextchar: - self.eof = True - break - elif not state: - token = nextchar - if nextchar in wordchars: - state = 'a' - elif nextchar in numchars: - state = '0' - elif nextchar in whitespace: - token = ' ' - break # emit token - else: - break # emit token - elif state == 'a': - seenletters = True - if nextchar in wordchars: - token += nextchar - elif nextchar == '.': - token += nextchar - state = 'a.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == '0': - if nextchar in numchars: - token += nextchar - elif nextchar == '.': - token += nextchar - state = '0.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == 'a.': - seenletters = True - if nextchar == '.' or nextchar in wordchars: - token += nextchar - elif nextchar in numchars and token[-1] == '.': - token += nextchar - state = '0.' - else: - self.charstack.append(nextchar) - break # emit token - elif state == '0.': - if nextchar == '.' or nextchar in numchars: - token += nextchar - elif nextchar in wordchars and token[-1] == '.': - token += nextchar - state = 'a.' - else: - self.charstack.append(nextchar) - break # emit token - if (state in ('a.', '0.') and (seenletters or token.count('.') > 1 or - token[-1] == '.')): - l = token.split('.') - token = l[0] - for tok in l[1:]: - self.tokenstack.append('.') - if tok: - self.tokenstack.append(tok) - return token - - def __iter__(self): - return self - - def __next__(self): - token = self.get_token() - if token is None: - raise StopIteration - return token - - def next(self): - return self.__next__() # Python 2.x support - - def split(cls, s): - return list(cls(s)) - split = classmethod(split) - - -class _resultbase(object): - - def __init__(self): - for attr in self.__slots__: - setattr(self, attr, None) - - def _repr(self, classname): - l = [] - for attr in self.__slots__: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (classname, ", ".join(l)) - - def __repr__(self): - return self._repr(self.__class__.__name__) - - -class parserinfo(object): - - # m from a.m/p.m, t from ISO T separator - JUMP = [" ", ".", ",", ";", "-", "/", "'", - "at", "on", "and", "ad", "m", "t", "of", - "st", "nd", "rd", "th"] - - WEEKDAYS = [("Mon", "Monday"), - ("Tue", "Tuesday"), - ("Wed", "Wednesday"), - ("Thu", "Thursday"), - ("Fri", "Friday"), - ("Sat", "Saturday"), - ("Sun", "Sunday")] - MONTHS = [("Jan", "January"), - ("Feb", "February"), - ("Mar", "March"), - ("Apr", "April"), - ("May", "May"), - ("Jun", "June"), - ("Jul", "July"), - ("Aug", "August"), - ("Sep", "Sept", "September"), - ("Oct", "October"), - ("Nov", "November"), - ("Dec", "December")] - HMS = [("h", "hour", "hours"), - ("m", "minute", "minutes"), - ("s", "second", "seconds")] - AMPM = [("am", "a"), - ("pm", "p")] - UTCZONE = ["UTC", "GMT", "Z"] - PERTAIN = ["of"] - TZOFFSET = {} - - def __init__(self, dayfirst=False, yearfirst=False): - self._jump = self._convert(self.JUMP) - self._weekdays = self._convert(self.WEEKDAYS) - self._months = self._convert(self.MONTHS) - self._hms = self._convert(self.HMS) - self._ampm = self._convert(self.AMPM) - self._utczone = self._convert(self.UTCZONE) - self._pertain = self._convert(self.PERTAIN) - - self.dayfirst = dayfirst - self.yearfirst = yearfirst - - self._year = time.localtime().tm_year - self._century = self._year//100*100 - - def _convert(self, lst): - dct = {} - for i in range(len(lst)): - v = lst[i] - if isinstance(v, tuple): - for v in v: - dct[v.lower()] = i - else: - dct[v.lower()] = i - return dct - - def jump(self, name): - return name.lower() in self._jump - - def weekday(self, name): - if len(name) >= 3: - try: - return self._weekdays[name.lower()] - except KeyError: - pass - return None - - def month(self, name): - if len(name) >= 3: - try: - return self._months[name.lower()]+1 - except KeyError: - pass - return None - - def hms(self, name): - try: - return self._hms[name.lower()] - except KeyError: - return None - - def ampm(self, name): - try: - return self._ampm[name.lower()] - except KeyError: - return None - - def pertain(self, name): - return name.lower() in self._pertain - - def utczone(self, name): - return name.lower() in self._utczone - - def tzoffset(self, name): - if name in self._utczone: - return 0 - return self.TZOFFSET.get(name) - - def convertyear(self, year): - if year < 100: - year += self._century - if abs(year-self._year) >= 50: - if year < self._year: - year += 100 - else: - year -= 100 - return year - - def validate(self, res): - # move to info - if res.year is not None: - res.year = self.convertyear(res.year) - if res.tzoffset == 0 and not res.tzname or res.tzname == 'Z': - res.tzname = "UTC" - res.tzoffset = 0 - elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): - res.tzoffset = 0 - return True - - -class parser(object): - - def __init__(self, info=None): - self.info = info or parserinfo() - - def parse(self, timestr, default=None, ignoretz=False, tzinfos=None, - **kwargs): - if not default: - default = datetime.datetime.now().replace(hour=0, minute=0, - second=0, microsecond=0) - - if kwargs.get('fuzzy_with_tokens', False): - res, skipped_tokens = self._parse(timestr, **kwargs) - else: - res = self._parse(timestr, **kwargs) - - if res is None: - raise ValueError("unknown string format") - repl = {} - for attr in ["year", "month", "day", "hour", - "minute", "second", "microsecond"]: - value = getattr(res, attr) - if value is not None: - repl[attr] = value - ret = default.replace(**repl) - if res.weekday is not None and not res.day: - ret = ret+relativedelta.relativedelta(weekday=res.weekday) - if not ignoretz: - if (isinstance(tzinfos, collections.Callable) or - tzinfos and res.tzname in tzinfos): - if isinstance(tzinfos, collections.Callable): - tzdata = tzinfos(res.tzname, res.tzoffset) - else: - tzdata = tzinfos.get(res.tzname) - if isinstance(tzdata, datetime.tzinfo): - tzinfo = tzdata - elif isinstance(tzdata, text_type): - tzinfo = tz.tzstr(tzdata) - elif isinstance(tzdata, integer_types): - tzinfo = tz.tzoffset(res.tzname, tzdata) - else: - raise ValueError("offset must be tzinfo subclass, " - "tz string, or int offset") - ret = ret.replace(tzinfo=tzinfo) - elif res.tzname and res.tzname in time.tzname: - ret = ret.replace(tzinfo=tz.tzlocal()) - elif res.tzoffset == 0: - ret = ret.replace(tzinfo=tz.tzutc()) - elif res.tzoffset: - ret = ret.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) - - if kwargs.get('fuzzy_with_tokens', False): - return ret, skipped_tokens - else: - return ret - - class _result(_resultbase): - __slots__ = ["year", "month", "day", "weekday", - "hour", "minute", "second", "microsecond", - "tzname", "tzoffset"] - - def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False, - fuzzy_with_tokens=False): - if fuzzy_with_tokens: - fuzzy = True - - info = self.info - if dayfirst is None: - dayfirst = info.dayfirst - if yearfirst is None: - yearfirst = info.yearfirst - res = self._result() - l = _timelex.split(timestr) - - # keep up with the last token skipped so we can recombine - # consecutively skipped tokens (-2 for when i begins at 0). - last_skipped_token_i = -2 - skipped_tokens = list() - - try: - - # year/month/day list - ymd = [] - - # Index of the month string in ymd - mstridx = -1 - - len_l = len(l) - i = 0 - while i < len_l: - - # Check if it's a number - try: - value_repr = l[i] - value = float(value_repr) - except ValueError: - value = None - - if value is not None: - # Token is a number - len_li = len(l[i]) - i += 1 - if (len(ymd) == 3 and len_li in (2, 4) - and (i >= len_l or (l[i] != ':' and - info.hms(l[i]) is None))): - # 19990101T23[59] - s = l[i-1] - res.hour = int(s[:2]) - if len_li == 4: - res.minute = int(s[2:]) - elif len_li == 6 or (len_li > 6 and l[i-1].find('.') == 6): - # YYMMDD or HHMMSS[.ss] - s = l[i-1] - if not ymd and l[i-1].find('.') == -1: - ymd.append(info.convertyear(int(s[:2]))) - ymd.append(int(s[2:4])) - ymd.append(int(s[4:])) - else: - # 19990101T235959[.59] - res.hour = int(s[:2]) - res.minute = int(s[2:4]) - res.second, res.microsecond = _parsems(s[4:]) - elif len_li == 8: - # YYYYMMDD - s = l[i-1] - ymd.append(int(s[:4])) - ymd.append(int(s[4:6])) - ymd.append(int(s[6:])) - elif len_li in (12, 14): - # YYYYMMDDhhmm[ss] - s = l[i-1] - ymd.append(int(s[:4])) - ymd.append(int(s[4:6])) - ymd.append(int(s[6:8])) - res.hour = int(s[8:10]) - res.minute = int(s[10:12]) - if len_li == 14: - res.second = int(s[12:]) - elif ((i < len_l and info.hms(l[i]) is not None) or - (i+1 < len_l and l[i] == ' ' and - info.hms(l[i+1]) is not None)): - # HH[ ]h or MM[ ]m or SS[.ss][ ]s - if l[i] == ' ': - i += 1 - idx = info.hms(l[i]) - while True: - if idx == 0: - res.hour = int(value) - if value % 1: - res.minute = int(60*(value % 1)) - elif idx == 1: - res.minute = int(value) - if value % 1: - res.second = int(60*(value % 1)) - elif idx == 2: - res.second, res.microsecond = \ - _parsems(value_repr) - i += 1 - if i >= len_l or idx == 2: - break - # 12h00 - try: - value_repr = l[i] - value = float(value_repr) - except ValueError: - break - else: - i += 1 - idx += 1 - if i < len_l: - newidx = info.hms(l[i]) - if newidx is not None: - idx = newidx - elif (i == len_l and l[i-2] == ' ' and - info.hms(l[i-3]) is not None): - # X h MM or X m SS - idx = info.hms(l[i-3]) + 1 - if idx == 1: - res.minute = int(value) - if value % 1: - res.second = int(60*(value % 1)) - elif idx == 2: - res.second, res.microsecond = \ - _parsems(value_repr) - i += 1 - elif i+1 < len_l and l[i] == ':': - # HH:MM[:SS[.ss]] - res.hour = int(value) - i += 1 - value = float(l[i]) - res.minute = int(value) - if value % 1: - res.second = int(60*(value % 1)) - i += 1 - if i < len_l and l[i] == ':': - res.second, res.microsecond = _parsems(l[i+1]) - i += 2 - elif i < len_l and l[i] in ('-', '/', '.'): - sep = l[i] - ymd.append(int(value)) - i += 1 - if i < len_l and not info.jump(l[i]): - try: - # 01-01[-01] - ymd.append(int(l[i])) - except ValueError: - # 01-Jan[-01] - value = info.month(l[i]) - if value is not None: - ymd.append(value) - assert mstridx == -1 - mstridx = len(ymd)-1 - else: - return None - i += 1 - if i < len_l and l[i] == sep: - # We have three members - i += 1 - value = info.month(l[i]) - if value is not None: - ymd.append(value) - mstridx = len(ymd)-1 - assert mstridx == -1 - else: - ymd.append(int(l[i])) - i += 1 - elif i >= len_l or info.jump(l[i]): - if i+1 < len_l and info.ampm(l[i+1]) is not None: - # 12 am - res.hour = int(value) - if res.hour < 12 and info.ampm(l[i+1]) == 1: - res.hour += 12 - elif res.hour == 12 and info.ampm(l[i+1]) == 0: - res.hour = 0 - i += 1 - else: - # Year, month or day - ymd.append(int(value)) - i += 1 - elif info.ampm(l[i]) is not None: - # 12am - res.hour = int(value) - if res.hour < 12 and info.ampm(l[i]) == 1: - res.hour += 12 - elif res.hour == 12 and info.ampm(l[i]) == 0: - res.hour = 0 - i += 1 - elif not fuzzy: - return None - else: - i += 1 - continue - - # Check weekday - value = info.weekday(l[i]) - if value is not None: - res.weekday = value - i += 1 - continue - - # Check month name - value = info.month(l[i]) - if value is not None: - ymd.append(value) - assert mstridx == -1 - mstridx = len(ymd)-1 - i += 1 - if i < len_l: - if l[i] in ('-', '/'): - # Jan-01[-99] - sep = l[i] - i += 1 - ymd.append(int(l[i])) - i += 1 - if i < len_l and l[i] == sep: - # Jan-01-99 - i += 1 - ymd.append(int(l[i])) - i += 1 - elif (i+3 < len_l and l[i] == l[i+2] == ' ' - and info.pertain(l[i+1])): - # Jan of 01 - # In this case, 01 is clearly year - try: - value = int(l[i+3]) - except ValueError: - # Wrong guess - pass - else: - # Convert it here to become unambiguous - ymd.append(info.convertyear(value)) - i += 4 - continue - - # Check am/pm - value = info.ampm(l[i]) - if value is not None: - if value == 1 and res.hour < 12: - res.hour += 12 - elif value == 0 and res.hour == 12: - res.hour = 0 - i += 1 - continue - - # Check for a timezone name - if (res.hour is not None and len(l[i]) <= 5 and - res.tzname is None and res.tzoffset is None and - not [x for x in l[i] if x not in - string.ascii_uppercase]): - res.tzname = l[i] - res.tzoffset = info.tzoffset(res.tzname) - i += 1 - - # Check for something like GMT+3, or BRST+3. Notice - # that it doesn't mean "I am 3 hours after GMT", but - # "my time +3 is GMT". If found, we reverse the - # logic so that timezone parsing code will get it - # right. - if i < len_l and l[i] in ('+', '-'): - l[i] = ('+', '-')[l[i] == '+'] - res.tzoffset = None - if info.utczone(res.tzname): - # With something like GMT+3, the timezone - # is *not* GMT. - res.tzname = None - - continue - - # Check for a numbered timezone - if res.hour is not None and l[i] in ('+', '-'): - signal = (-1, 1)[l[i] == '+'] - i += 1 - len_li = len(l[i]) - if len_li == 4: - # -0300 - res.tzoffset = int(l[i][:2])*3600+int(l[i][2:])*60 - elif i+1 < len_l and l[i+1] == ':': - # -03:00 - res.tzoffset = int(l[i])*3600+int(l[i+2])*60 - i += 2 - elif len_li <= 2: - # -[0]3 - res.tzoffset = int(l[i][:2])*3600 - else: - return None - i += 1 - res.tzoffset *= signal - - # Look for a timezone name between parenthesis - if (i+3 < len_l and - info.jump(l[i]) and l[i+1] == '(' and l[i+3] == ')' and - 3 <= len(l[i+2]) <= 5 and - not [x for x in l[i+2] - if x not in string.ascii_uppercase]): - # -0300 (BRST) - res.tzname = l[i+2] - i += 4 - continue - - # Check jumps - if not (info.jump(l[i]) or fuzzy): - return None - - if last_skipped_token_i == i - 1: - # recombine the tokens - skipped_tokens[-1] += l[i] - else: - # just append - skipped_tokens.append(l[i]) - last_skipped_token_i = i - i += 1 - - # Process year/month/day - len_ymd = len(ymd) - if len_ymd > 3: - # More than three members!? - return None - elif len_ymd == 1 or (mstridx != -1 and len_ymd == 2): - # One member, or two members with a month string - if mstridx != -1: - res.month = ymd[mstridx] - del ymd[mstridx] - if len_ymd > 1 or mstridx == -1: - if ymd[0] > 31: - res.year = ymd[0] - else: - res.day = ymd[0] - elif len_ymd == 2: - # Two members with numbers - if ymd[0] > 31: - # 99-01 - res.year, res.month = ymd - elif ymd[1] > 31: - # 01-99 - res.month, res.year = ymd - elif dayfirst and ymd[1] <= 12: - # 13-01 - res.day, res.month = ymd - else: - # 01-13 - res.month, res.day = ymd - if len_ymd == 3: - # Three members - if mstridx == 0: - res.month, res.day, res.year = ymd - elif mstridx == 1: - if ymd[0] > 31 or (yearfirst and ymd[2] <= 31): - # 99-Jan-01 - res.year, res.month, res.day = ymd - else: - # 01-Jan-01 - # Give precendence to day-first, since - # two-digit years is usually hand-written. - res.day, res.month, res.year = ymd - elif mstridx == 2: - # WTF!? - if ymd[1] > 31: - # 01-99-Jan - res.day, res.year, res.month = ymd - else: - # 99-01-Jan - res.year, res.day, res.month = ymd - else: - if ymd[0] > 31 or \ - (yearfirst and ymd[1] <= 12 and ymd[2] <= 31): - # 99-01-01 - res.year, res.month, res.day = ymd - elif ymd[0] > 12 or (dayfirst and ymd[1] <= 12): - # 13-01-01 - res.day, res.month, res.year = ymd - else: - # 01-13-01 - res.month, res.day, res.year = ymd - - except (IndexError, ValueError, AssertionError): - return None - - if not info.validate(res): - return None - - if fuzzy_with_tokens: - return res, tuple(skipped_tokens) - else: - return res - -DEFAULTPARSER = parser() - - -def parse(timestr, parserinfo=None, **kwargs): - # Python 2.x support: datetimes return their string presentation as - # bytes in 2.x and unicode in 3.x, so it's reasonable to expect that - # the parser will get both kinds. Internally we use unicode only. - if isinstance(timestr, binary_type): - timestr = timestr.decode() - if parserinfo: - return parser(parserinfo).parse(timestr, **kwargs) - else: - return DEFAULTPARSER.parse(timestr, **kwargs) - - -class _tzparser(object): - - class _result(_resultbase): - - __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset", - "start", "end"] - - class _attr(_resultbase): - __slots__ = ["month", "week", "weekday", - "yday", "jyday", "day", "time"] - - def __repr__(self): - return self._repr("") - - def __init__(self): - _resultbase.__init__(self) - self.start = self._attr() - self.end = self._attr() - - def parse(self, tzstr): - res = self._result() - l = _timelex.split(tzstr) - try: - - len_l = len(l) - - i = 0 - while i < len_l: - # BRST+3[BRDT[+2]] - j = i - while j < len_l and not [x for x in l[j] - if x in "0123456789:,-+"]: - j += 1 - if j != i: - if not res.stdabbr: - offattr = "stdoffset" - res.stdabbr = "".join(l[i:j]) - else: - offattr = "dstoffset" - res.dstabbr = "".join(l[i:j]) - i = j - if (i < len_l and (l[i] in ('+', '-') or l[i][0] in - "0123456789")): - if l[i] in ('+', '-'): - # Yes, that's right. See the TZ variable - # documentation. - signal = (1, -1)[l[i] == '+'] - i += 1 - else: - signal = -1 - len_li = len(l[i]) - if len_li == 4: - # -0300 - setattr(res, offattr, (int(l[i][:2])*3600 + - int(l[i][2:])*60)*signal) - elif i+1 < len_l and l[i+1] == ':': - # -03:00 - setattr(res, offattr, - (int(l[i])*3600+int(l[i+2])*60)*signal) - i += 2 - elif len_li <= 2: - # -[0]3 - setattr(res, offattr, - int(l[i][:2])*3600*signal) - else: - return None - i += 1 - if res.dstabbr: - break - else: - break - - if i < len_l: - for j in range(i, len_l): - if l[j] == ';': - l[j] = ',' - - assert l[i] == ',' - - i += 1 - - if i >= len_l: - pass - elif (8 <= l.count(',') <= 9 and - not [y for x in l[i:] if x != ',' - for y in x if y not in "0123456789"]): - # GMT0BST,3,0,30,3600,10,0,26,7200[,3600] - for x in (res.start, res.end): - x.month = int(l[i]) - i += 2 - if l[i] == '-': - value = int(l[i+1])*-1 - i += 1 - else: - value = int(l[i]) - i += 2 - if value: - x.week = value - x.weekday = (int(l[i])-1) % 7 - else: - x.day = int(l[i]) - i += 2 - x.time = int(l[i]) - i += 2 - if i < len_l: - if l[i] in ('-', '+'): - signal = (-1, 1)[l[i] == "+"] - i += 1 - else: - signal = 1 - res.dstoffset = (res.stdoffset+int(l[i]))*signal - elif (l.count(',') == 2 and l[i:].count('/') <= 2 and - not [y for x in l[i:] if x not in (',', '/', 'J', 'M', - '.', '-', ':') - for y in x if y not in "0123456789"]): - for x in (res.start, res.end): - if l[i] == 'J': - # non-leap year day (1 based) - i += 1 - x.jyday = int(l[i]) - elif l[i] == 'M': - # month[-.]week[-.]weekday - i += 1 - x.month = int(l[i]) - i += 1 - assert l[i] in ('-', '.') - i += 1 - x.week = int(l[i]) - if x.week == 5: - x.week = -1 - i += 1 - assert l[i] in ('-', '.') - i += 1 - x.weekday = (int(l[i])-1) % 7 - else: - # year day (zero based) - x.yday = int(l[i])+1 - - i += 1 - - if i < len_l and l[i] == '/': - i += 1 - # start time - len_li = len(l[i]) - if len_li == 4: - # -0300 - x.time = (int(l[i][:2])*3600+int(l[i][2:])*60) - elif i+1 < len_l and l[i+1] == ':': - # -03:00 - x.time = int(l[i])*3600+int(l[i+2])*60 - i += 2 - if i+1 < len_l and l[i+1] == ':': - i += 2 - x.time += int(l[i]) - elif len_li <= 2: - # -[0]3 - x.time = (int(l[i][:2])*3600) - else: - return None - i += 1 - - assert i == len_l or l[i] == ',' - - i += 1 - - assert i >= len_l - - except (IndexError, ValueError, AssertionError): - return None - - return res - - -DEFAULTTZPARSER = _tzparser() - - -def _parsetz(tzstr): - return DEFAULTTZPARSER.parse(tzstr) - - -def _parsems(value): - """Parse a I[.F] seconds value into (seconds, microseconds).""" - if "." not in value: - return int(value), 0 - else: - i, f = value.split(".") - return int(i), int(f.ljust(6, "0")[:6]) - - -# vim:ts=4:sw=4:et diff --git a/awx/lib/site-packages/dateutil/relativedelta.py b/awx/lib/site-packages/dateutil/relativedelta.py deleted file mode 100644 index 2b5557a96f..0000000000 --- a/awx/lib/site-packages/dateutil/relativedelta.py +++ /dev/null @@ -1,448 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -import calendar - -from six import integer_types - -__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] - - -class weekday(object): - __slots__ = ["weekday", "n"] - - def __init__(self, weekday, n=None): - self.weekday = weekday - self.n = n - - def __call__(self, n): - if n == self.n: - return self - else: - return self.__class__(self.weekday, n) - - def __eq__(self, other): - try: - if self.weekday != other.weekday or self.n != other.n: - return False - except AttributeError: - return False - return True - - def __repr__(self): - s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] - if not self.n: - return s - else: - return "%s(%+d)" % (s, self.n) - -MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)]) - - -class relativedelta(object): - """ -The relativedelta type is based on the specification of the excellent -work done by M.-A. Lemburg in his -`mx.DateTime <http://www.egenix.com/files/python/mxDateTime.html>`_ extension. -However, notice that this type does *NOT* implement the same algorithm as -his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. - -There are two different ways to build a relativedelta instance. The -first one is passing it two date/datetime classes:: - - relativedelta(datetime1, datetime2) - -The second one is passing it any number of the following keyword arguments:: - - relativedelta(arg1=x,arg2=y,arg3=z...) - - year, month, day, hour, minute, second, microsecond: - Absolute information (argument is singular); adding or subtracting a - relativedelta with absolute information does not perform an aritmetic - operation, but rather REPLACES the corresponding value in the - original datetime with the value(s) in relativedelta. - - years, months, weeks, days, hours, minutes, seconds, microseconds: - Relative information, may be negative (argument is plural); adding - or subtracting a relativedelta with relative information performs - the corresponding aritmetic operation on the original datetime value - with the information in the relativedelta. - - weekday: - One of the weekday instances (MO, TU, etc). These instances may - receive a parameter N, specifying the Nth weekday, which could - be positive or negative (like MO(+1) or MO(-2). Not specifying - it is the same as specifying +1. You can also use an integer, - where 0=MO. - - leapdays: - Will add given days to the date found, if year is a leap - year, and the date found is post 28 of february. - - yearday, nlyearday: - Set the yearday or the non-leap year day (jump leap days). - These are converted to day/month/leapdays information. - -Here is the behavior of operations with relativedelta: - -1. Calculate the absolute year, using the 'year' argument, or the - original datetime year, if the argument is not present. - -2. Add the relative 'years' argument to the absolute year. - -3. Do steps 1 and 2 for month/months. - -4. Calculate the absolute day, using the 'day' argument, or the - original datetime day, if the argument is not present. Then, - subtract from the day until it fits in the year and month - found after their operations. - -5. Add the relative 'days' argument to the absolute day. Notice - that the 'weeks' argument is multiplied by 7 and added to - 'days'. - -6. Do steps 1 and 2 for hour/hours, minute/minutes, second/seconds, - microsecond/microseconds. - -7. If the 'weekday' argument is present, calculate the weekday, - with the given (wday, nth) tuple. wday is the index of the - weekday (0-6, 0=Mon), and nth is the number of weeks to add - forward or backward, depending on its signal. Notice that if - the calculated date is already Monday, for example, using - (0, 1) or (0, -1) won't change the day. - """ - - def __init__(self, dt1=None, dt2=None, - years=0, months=0, days=0, leapdays=0, weeks=0, - hours=0, minutes=0, seconds=0, microseconds=0, - year=None, month=None, day=None, weekday=None, - yearday=None, nlyearday=None, - hour=None, minute=None, second=None, microsecond=None): - if dt1 and dt2: - # datetime is a subclass of date. So both must be date - if not (isinstance(dt1, datetime.date) and - isinstance(dt2, datetime.date)): - raise TypeError("relativedelta only diffs datetime/date") - # We allow two dates, or two datetimes, so we coerce them to be - # of the same type - if (isinstance(dt1, datetime.datetime) != - isinstance(dt2, datetime.datetime)): - if not isinstance(dt1, datetime.datetime): - dt1 = datetime.datetime.fromordinal(dt1.toordinal()) - elif not isinstance(dt2, datetime.datetime): - dt2 = datetime.datetime.fromordinal(dt2.toordinal()) - self.years = 0 - self.months = 0 - self.days = 0 - self.leapdays = 0 - self.hours = 0 - self.minutes = 0 - self.seconds = 0 - self.microseconds = 0 - self.year = None - self.month = None - self.day = None - self.weekday = None - self.hour = None - self.minute = None - self.second = None - self.microsecond = None - self._has_time = 0 - - months = (dt1.year*12+dt1.month)-(dt2.year*12+dt2.month) - self._set_months(months) - dtm = self.__radd__(dt2) - if dt1 < dt2: - while dt1 > dtm: - months += 1 - self._set_months(months) - dtm = self.__radd__(dt2) - else: - while dt1 < dtm: - months -= 1 - self._set_months(months) - dtm = self.__radd__(dt2) - delta = dt1 - dtm - self.seconds = delta.seconds+delta.days*86400 - self.microseconds = delta.microseconds - else: - self.years = years - self.months = months - self.days = days+weeks*7 - self.leapdays = leapdays - self.hours = hours - self.minutes = minutes - self.seconds = seconds - self.microseconds = microseconds - self.year = year - self.month = month - self.day = day - self.hour = hour - self.minute = minute - self.second = second - self.microsecond = microsecond - - if isinstance(weekday, integer_types): - self.weekday = weekdays[weekday] - else: - self.weekday = weekday - - yday = 0 - if nlyearday: - yday = nlyearday - elif yearday: - yday = yearday - if yearday > 59: - self.leapdays = -1 - if yday: - ydayidx = [31, 59, 90, 120, 151, 181, 212, - 243, 273, 304, 334, 366] - for idx, ydays in enumerate(ydayidx): - if yday <= ydays: - self.month = idx+1 - if idx == 0: - self.day = yday - else: - self.day = yday-ydayidx[idx-1] - break - else: - raise ValueError("invalid year day (%d)" % yday) - - self._fix() - - def _fix(self): - if abs(self.microseconds) > 999999: - s = self.microseconds//abs(self.microseconds) - div, mod = divmod(self.microseconds*s, 1000000) - self.microseconds = mod*s - self.seconds += div*s - if abs(self.seconds) > 59: - s = self.seconds//abs(self.seconds) - div, mod = divmod(self.seconds*s, 60) - self.seconds = mod*s - self.minutes += div*s - if abs(self.minutes) > 59: - s = self.minutes//abs(self.minutes) - div, mod = divmod(self.minutes*s, 60) - self.minutes = mod*s - self.hours += div*s - if abs(self.hours) > 23: - s = self.hours//abs(self.hours) - div, mod = divmod(self.hours*s, 24) - self.hours = mod*s - self.days += div*s - if abs(self.months) > 11: - s = self.months//abs(self.months) - div, mod = divmod(self.months*s, 12) - self.months = mod*s - self.years += div*s - if (self.hours or self.minutes or self.seconds or self.microseconds - or self.hour is not None or self.minute is not None or - self.second is not None or self.microsecond is not None): - self._has_time = 1 - else: - self._has_time = 0 - - def _set_months(self, months): - self.months = months - if abs(self.months) > 11: - s = self.months//abs(self.months) - div, mod = divmod(self.months*s, 12) - self.months = mod*s - self.years = div*s - else: - self.years = 0 - - def __add__(self, other): - if isinstance(other, relativedelta): - return relativedelta(years=other.years+self.years, - months=other.months+self.months, - days=other.days+self.days, - hours=other.hours+self.hours, - minutes=other.minutes+self.minutes, - seconds=other.seconds+self.seconds, - microseconds=(other.microseconds + - self.microseconds), - leapdays=other.leapdays or self.leapdays, - year=other.year or self.year, - month=other.month or self.month, - day=other.day or self.day, - weekday=other.weekday or self.weekday, - hour=other.hour or self.hour, - minute=other.minute or self.minute, - second=other.second or self.second, - microsecond=(other.microsecond or - self.microsecond)) - if not isinstance(other, datetime.date): - raise TypeError("unsupported type for add operation") - elif self._has_time and not isinstance(other, datetime.datetime): - other = datetime.datetime.fromordinal(other.toordinal()) - year = (self.year or other.year)+self.years - month = self.month or other.month - if self.months: - assert 1 <= abs(self.months) <= 12 - month += self.months - if month > 12: - year += 1 - month -= 12 - elif month < 1: - year -= 1 - month += 12 - day = min(calendar.monthrange(year, month)[1], - self.day or other.day) - repl = {"year": year, "month": month, "day": day} - for attr in ["hour", "minute", "second", "microsecond"]: - value = getattr(self, attr) - if value is not None: - repl[attr] = value - days = self.days - if self.leapdays and month > 2 and calendar.isleap(year): - days += self.leapdays - ret = (other.replace(**repl) - + datetime.timedelta(days=days, - hours=self.hours, - minutes=self.minutes, - seconds=self.seconds, - microseconds=self.microseconds)) - if self.weekday: - weekday, nth = self.weekday.weekday, self.weekday.n or 1 - jumpdays = (abs(nth)-1)*7 - if nth > 0: - jumpdays += (7-ret.weekday()+weekday) % 7 - else: - jumpdays += (ret.weekday()-weekday) % 7 - jumpdays *= -1 - ret += datetime.timedelta(days=jumpdays) - return ret - - def __radd__(self, other): - return self.__add__(other) - - def __rsub__(self, other): - return self.__neg__().__radd__(other) - - def __sub__(self, other): - if not isinstance(other, relativedelta): - raise TypeError("unsupported type for sub operation") - return relativedelta(years=self.years-other.years, - months=self.months-other.months, - days=self.days-other.days, - hours=self.hours-other.hours, - minutes=self.minutes-other.minutes, - seconds=self.seconds-other.seconds, - microseconds=self.microseconds-other.microseconds, - leapdays=self.leapdays or other.leapdays, - year=self.year or other.year, - month=self.month or other.month, - day=self.day or other.day, - weekday=self.weekday or other.weekday, - hour=self.hour or other.hour, - minute=self.minute or other.minute, - second=self.second or other.second, - microsecond=self.microsecond or other.microsecond) - - def __neg__(self): - return relativedelta(years=-self.years, - months=-self.months, - days=-self.days, - hours=-self.hours, - minutes=-self.minutes, - seconds=-self.seconds, - microseconds=-self.microseconds, - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - - def __bool__(self): - return not (not self.years and - not self.months and - not self.days and - not self.hours and - not self.minutes and - not self.seconds and - not self.microseconds and - not self.leapdays and - self.year is None and - self.month is None and - self.day is None and - self.weekday is None and - self.hour is None and - self.minute is None and - self.second is None and - self.microsecond is None) - - def __mul__(self, other): - f = float(other) - return relativedelta(years=int(self.years*f), - months=int(self.months*f), - days=int(self.days*f), - hours=int(self.hours*f), - minutes=int(self.minutes*f), - seconds=int(self.seconds*f), - microseconds=int(self.microseconds*f), - leapdays=self.leapdays, - year=self.year, - month=self.month, - day=self.day, - weekday=self.weekday, - hour=self.hour, - minute=self.minute, - second=self.second, - microsecond=self.microsecond) - - __rmul__ = __mul__ - - def __eq__(self, other): - if not isinstance(other, relativedelta): - return False - if self.weekday or other.weekday: - if not self.weekday or not other.weekday: - return False - if self.weekday.weekday != other.weekday.weekday: - return False - n1, n2 = self.weekday.n, other.weekday.n - if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): - return False - return (self.years == other.years and - self.months == other.months and - self.days == other.days and - self.hours == other.hours and - self.minutes == other.minutes and - self.seconds == other.seconds and - self.leapdays == other.leapdays and - self.year == other.year and - self.month == other.month and - self.day == other.day and - self.hour == other.hour and - self.minute == other.minute and - self.second == other.second and - self.microsecond == other.microsecond) - - def __ne__(self, other): - return not self.__eq__(other) - - def __div__(self, other): - return self.__mul__(1/float(other)) - - __truediv__ = __div__ - - def __repr__(self): - l = [] - for attr in ["years", "months", "days", "leapdays", - "hours", "minutes", "seconds", "microseconds"]: - value = getattr(self, attr) - if value: - l.append("%s=%+d" % (attr, value)) - for attr in ["year", "month", "day", "weekday", - "hour", "minute", "second", "microsecond"]: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) - -# vim:ts=4:sw=4:et diff --git a/awx/lib/site-packages/dateutil/rrule.py b/awx/lib/site-packages/dateutil/rrule.py deleted file mode 100644 index 401bc8ab03..0000000000 --- a/awx/lib/site-packages/dateutil/rrule.py +++ /dev/null @@ -1,1356 +0,0 @@ -# -*- coding: utf-8 -*- -""" -The rrule module offers a small, complete, and very fast, implementation of -the recurrence rules documented in the -`iCalendar RFC <http://www.ietf.org/rfc/rfc2445.txt>`_, -including support for caching of results. -""" -import itertools -import datetime -import calendar -import sys - -from fractions import gcd - -from six import advance_iterator, integer_types -from six.moves import _thread - -__all__ = ["rrule", "rruleset", "rrulestr", - "YEARLY", "MONTHLY", "WEEKLY", "DAILY", - "HOURLY", "MINUTELY", "SECONDLY", - "MO", "TU", "WE", "TH", "FR", "SA", "SU"] - -# Every mask is 7 days longer to handle cross-year weekly periods. -M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30 + - [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7) -M365MASK = list(M366MASK) -M29, M30, M31 = list(range(1, 30)), list(range(1, 31)), list(range(1, 32)) -MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) -MDAY365MASK = list(MDAY366MASK) -M29, M30, M31 = list(range(-29, 0)), list(range(-30, 0)), list(range(-31, 0)) -NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) -NMDAY365MASK = list(NMDAY366MASK) -M366RANGE = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366) -M365RANGE = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) -WDAYMASK = [0, 1, 2, 3, 4, 5, 6]*55 -del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31] -MDAY365MASK = tuple(MDAY365MASK) -M365MASK = tuple(M365MASK) - -(YEARLY, - MONTHLY, - WEEKLY, - DAILY, - HOURLY, - MINUTELY, - SECONDLY) = list(range(7)) - -# Imported on demand. -easter = None -parser = None - - -class weekday(object): - __slots__ = ["weekday", "n"] - - def __init__(self, weekday, n=None): - if n == 0: - raise ValueError("Can't create weekday with n == 0") - self.weekday = weekday - self.n = n - - def __call__(self, n): - if n == self.n: - return self - else: - return self.__class__(self.weekday, n) - - def __eq__(self, other): - try: - if self.weekday != other.weekday or self.n != other.n: - return False - except AttributeError: - return False - return True - - def __repr__(self): - s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] - if not self.n: - return s - else: - return "%s(%+d)" % (s, self.n) - -MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)]) - - -class rrulebase(object): - def __init__(self, cache=False): - if cache: - self._cache = [] - self._cache_lock = _thread.allocate_lock() - self._cache_gen = self._iter() - self._cache_complete = False - else: - self._cache = None - self._cache_complete = False - self._len = None - - def __iter__(self): - if self._cache_complete: - return iter(self._cache) - elif self._cache is None: - return self._iter() - else: - return self._iter_cached() - - def _iter_cached(self): - i = 0 - gen = self._cache_gen - cache = self._cache - acquire = self._cache_lock.acquire - release = self._cache_lock.release - while gen: - if i == len(cache): - acquire() - if self._cache_complete: - break - try: - for j in range(10): - cache.append(advance_iterator(gen)) - except StopIteration: - self._cache_gen = gen = None - self._cache_complete = True - break - release() - yield cache[i] - i += 1 - while i < self._len: - yield cache[i] - i += 1 - - def __getitem__(self, item): - if self._cache_complete: - return self._cache[item] - elif isinstance(item, slice): - if item.step and item.step < 0: - return list(iter(self))[item] - else: - return list(itertools.islice(self, - item.start or 0, - item.stop or sys.maxsize, - item.step or 1)) - elif item >= 0: - gen = iter(self) - try: - for i in range(item+1): - res = advance_iterator(gen) - except StopIteration: - raise IndexError - return res - else: - return list(iter(self))[item] - - def __contains__(self, item): - if self._cache_complete: - return item in self._cache - else: - for i in self: - if i == item: - return True - elif i > item: - return False - return False - - # __len__() introduces a large performance penality. - def count(self): - """ Returns the number of recurrences in this set. It will have go - trough the whole recurrence, if this hasn't been done before. """ - if self._len is None: - for x in self: - pass - return self._len - - def before(self, dt, inc=False): - """ Returns the last recurrence before the given datetime instance. The - inc keyword defines what happens if dt is an occurrence. With - inc=True, if dt itself is an occurrence, it will be returned. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - last = None - if inc: - for i in gen: - if i > dt: - break - last = i - else: - for i in gen: - if i >= dt: - break - last = i - return last - - def after(self, dt, inc=False): - """ Returns the first recurrence after the given datetime instance. The - inc keyword defines what happens if dt is an occurrence. With - inc=True, if dt itself is an occurrence, it will be returned. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - if inc: - for i in gen: - if i >= dt: - return i - else: - for i in gen: - if i > dt: - return i - return None - - def between(self, after, before, inc=False): - """ Returns all the occurrences of the rrule between after and before. - The inc keyword defines what happens if after and/or before are - themselves occurrences. With inc=True, they will be included in the - list, if they are found in the recurrence set. """ - if self._cache_complete: - gen = self._cache - else: - gen = self - started = False - l = [] - if inc: - for i in gen: - if i > before: - break - elif not started: - if i >= after: - started = True - l.append(i) - else: - l.append(i) - else: - for i in gen: - if i >= before: - break - elif not started: - if i > after: - started = True - l.append(i) - else: - l.append(i) - return l - - -class rrule(rrulebase): - """ - That's the base of the rrule operation. It accepts all the keywords - defined in the RFC as its constructor parameters (except byday, - which was renamed to byweekday) and more. The constructor prototype is:: - - rrule(freq) - - Where freq must be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, - or SECONDLY. - - Additionally, it supports the following keyword arguments: - - :param cache: - If given, it must be a boolean value specifying to enable or disable - caching of results. If you will use the same rrule instance multiple - times, enabling caching will improve the performance considerably. - :param dtstart: - The recurrence start. Besides being the base for the recurrence, - missing parameters in the final recurrence instances will also be - extracted from this date. If not given, datetime.now() will be used - instead. - :param interval: - The interval between each freq iteration. For example, when using - YEARLY, an interval of 2 means once every two years, but with HOURLY, - it means once every two hours. The default interval is 1. - :param wkst: - The week start day. Must be one of the MO, TU, WE constants, or an - integer, specifying the first day of the week. This will affect - recurrences based on weekly periods. The default week start is got - from calendar.firstweekday(), and may be modified by - calendar.setfirstweekday(). - :param count: - How many occurrences will be generated. - :param until: - If given, this must be a datetime instance, that will specify the - limit of the recurrence. If a recurrence instance happens to be the - same as the datetime instance given in the until keyword, this will - be the last occurrence. - :param bysetpos: - If given, it must be either an integer, or a sequence of integers, - positive or negative. Each given integer will specify an occurrence - number, corresponding to the nth occurrence of the rule inside the - frequency period. For example, a bysetpos of -1 if combined with a - MONTHLY frequency, and a byweekday of (MO, TU, WE, TH, FR), will - result in the last work day of every month. - :param bymonth: - If given, it must be either an integer, or a sequence of integers, - meaning the months to apply the recurrence to. - :param bymonthday: - If given, it must be either an integer, or a sequence of integers, - meaning the month days to apply the recurrence to. - :param byyearday: - If given, it must be either an integer, or a sequence of integers, - meaning the year days to apply the recurrence to. - :param byweekno: - If given, it must be either an integer, or a sequence of integers, - meaning the week numbers to apply the recurrence to. Week numbers - have the meaning described in ISO8601, that is, the first week of - the year is that containing at least four days of the new year. - :param byweekday: - If given, it must be either an integer (0 == MO), a sequence of - integers, one of the weekday constants (MO, TU, etc), or a sequence - of these constants. When given, these variables will define the - weekdays where the recurrence will be applied. It's also possible to - use an argument n for the weekday instances, which will mean the nth - occurrence of this weekday in the period. For example, with MONTHLY, - or with YEARLY and BYMONTH, using FR(+1) in byweekday will specify the - first friday of the month where the recurrence happens. Notice that in - the RFC documentation, this is specified as BYDAY, but was renamed to - avoid the ambiguity of that keyword. - :param byhour: - If given, it must be either an integer, or a sequence of integers, - meaning the hours to apply the recurrence to. - :param byminute: - If given, it must be either an integer, or a sequence of integers, - meaning the minutes to apply the recurrence to. - :param bysecond: - If given, it must be either an integer, or a sequence of integers, - meaning the seconds to apply the recurrence to. - :param byeaster: - If given, it must be either an integer, or a sequence of integers, - positive or negative. Each integer will define an offset from the - Easter Sunday. Passing the offset 0 to byeaster will yield the Easter - Sunday itself. This is an extension to the RFC specification. - """ - def __init__(self, freq, dtstart=None, - interval=1, wkst=None, count=None, until=None, bysetpos=None, - bymonth=None, bymonthday=None, byyearday=None, byeaster=None, - byweekno=None, byweekday=None, - byhour=None, byminute=None, bysecond=None, - cache=False): - super(rrule, self).__init__(cache) - global easter - if not dtstart: - dtstart = datetime.datetime.now().replace(microsecond=0) - elif not isinstance(dtstart, datetime.datetime): - dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) - else: - dtstart = dtstart.replace(microsecond=0) - self._dtstart = dtstart - self._tzinfo = dtstart.tzinfo - self._freq = freq - self._interval = interval - self._count = count - - if until and not isinstance(until, datetime.datetime): - until = datetime.datetime.fromordinal(until.toordinal()) - self._until = until - - if wkst is None: - self._wkst = calendar.firstweekday() - elif isinstance(wkst, integer_types): - self._wkst = wkst - else: - self._wkst = wkst.weekday - - if bysetpos is None: - self._bysetpos = None - elif isinstance(bysetpos, integer_types): - if bysetpos == 0 or not (-366 <= bysetpos <= 366): - raise ValueError("bysetpos must be between 1 and 366, " - "or between -366 and -1") - self._bysetpos = (bysetpos,) - else: - self._bysetpos = tuple(bysetpos) - for pos in self._bysetpos: - if pos == 0 or not (-366 <= pos <= 366): - raise ValueError("bysetpos must be between 1 and 366, " - "or between -366 and -1") - - if (byweekno is None and byyearday is None and bymonthday is None and - byweekday is None and byeaster is None): - if freq == YEARLY: - if bymonth is None: - bymonth = dtstart.month - bymonthday = dtstart.day - elif freq == MONTHLY: - bymonthday = dtstart.day - elif freq == WEEKLY: - byweekday = dtstart.weekday() - - # bymonth - if bymonth is None: - self._bymonth = None - else: - if isinstance(bymonth, integer_types): - bymonth = (bymonth,) - - self._bymonth = set(bymonth) - - # byyearday - if byyearday is None: - self._byyearday = None - else: - if isinstance(byyearday, integer_types): - byyearday = (byyearday,) - - self._byyearday = set(byyearday) - - # byeaster - if byeaster is not None: - if not easter: - from dateutil import easter - if isinstance(byeaster, integer_types): - self._byeaster = (byeaster,) - else: - self._byeaster = tuple(byeaster) - else: - self._byeaster = None - - # bymonthay - if bymonthday is None: - self._bymonthday = () - self._bynmonthday = () - else: - if isinstance(bymonthday, integer_types): - bymonthday = (bymonthday,) - - self._bymonthday = set([x for x in bymonthday if x > 0]) - self._bynmonthday = set([x for x in bymonthday if x < 0]) - - # byweekno - if byweekno is None: - self._byweekno = None - else: - if isinstance(byweekno, integer_types): - byweekno = (byweekno,) - - self._byweekno = set(byweekno) - - # byweekday / bynweekday - if byweekday is None: - self._byweekday = None - self._bynweekday = None - else: - if isinstance(byweekday, integer_types): - byweekday = (byweekday,) - elif hasattr(byweekday, "n"): - byweekday = (byweekday.weekday,) - - self._byweekday = set() - self._bynweekday = set() - for wday in byweekday: - if isinstance(wday, integer_types): - self._byweekday.add(wday) - elif not wday.n or freq > MONTHLY: - self._byweekday.add(wday.weekday) - else: - self._bynweekday.add((wday.weekday, wday.n)) - - if not self._byweekday: - self._byweekday = None - elif not self._bynweekday: - self._bynweekday = None - - # byhour - if byhour is None: - if freq < HOURLY: - self._byhour = set((dtstart.hour,)) - else: - self._byhour = None - else: - if isinstance(byhour, integer_types): - byhour = (byhour,) - - if freq == HOURLY: - self._byhour = self.__construct_byset(start=dtstart.hour, - byxxx=byhour, - base=24) - else: - self._byhour = set(byhour) - - # byminute - if byminute is None: - if freq < MINUTELY: - self._byminute = set((dtstart.minute,)) - else: - self._byminute = None - else: - if isinstance(byminute, integer_types): - byminute = (byminute,) - - if freq == MINUTELY: - self._byminute = self.__construct_byset(start=dtstart.minute, - byxxx=byminute, - base=60) - else: - self._byminute = set(byminute) - - # bysecond - if bysecond is None: - if freq < SECONDLY: - self._bysecond = ((dtstart.second,)) - else: - self._bysecond = None - else: - if isinstance(bysecond, integer_types): - bysecond = (bysecond,) - - self._bysecond = set(bysecond) - - if freq == SECONDLY: - self._bysecond = self.__construct_byset(start=dtstart.second, - byxxx=bysecond, - base=60) - else: - self._bysecond = set(bysecond) - - if self._freq >= HOURLY: - self._timeset = None - else: - self._timeset = [] - for hour in self._byhour: - for minute in self._byminute: - for second in self._bysecond: - self._timeset.append( - datetime.time(hour, minute, second, - tzinfo=self._tzinfo)) - self._timeset.sort() - self._timeset = tuple(self._timeset) - - def _iter(self): - year, month, day, hour, minute, second, weekday, yearday, _ = \ - self._dtstart.timetuple() - - # Some local variables to speed things up a bit - freq = self._freq - interval = self._interval - wkst = self._wkst - until = self._until - bymonth = self._bymonth - byweekno = self._byweekno - byyearday = self._byyearday - byweekday = self._byweekday - byeaster = self._byeaster - bymonthday = self._bymonthday - bynmonthday = self._bynmonthday - bysetpos = self._bysetpos - byhour = self._byhour - byminute = self._byminute - bysecond = self._bysecond - - ii = _iterinfo(self) - ii.rebuild(year, month) - - getdayset = {YEARLY: ii.ydayset, - MONTHLY: ii.mdayset, - WEEKLY: ii.wdayset, - DAILY: ii.ddayset, - HOURLY: ii.ddayset, - MINUTELY: ii.ddayset, - SECONDLY: ii.ddayset}[freq] - - if freq < HOURLY: - timeset = self._timeset - else: - gettimeset = {HOURLY: ii.htimeset, - MINUTELY: ii.mtimeset, - SECONDLY: ii.stimeset}[freq] - if ((freq >= HOURLY and - self._byhour and hour not in self._byhour) or - (freq >= MINUTELY and - self._byminute and minute not in self._byminute) or - (freq >= SECONDLY and - self._bysecond and second not in self._bysecond)): - timeset = () - else: - timeset = gettimeset(hour, minute, second) - - total = 0 - count = self._count - while True: - # Get dayset with the right frequency - dayset, start, end = getdayset(year, month, day) - - # Do the "hard" work ;-) - filtered = False - for i in dayset[start:end]: - if ((bymonth and ii.mmask[i] not in bymonth) or - (byweekno and not ii.wnomask[i]) or - (byweekday and ii.wdaymask[i] not in byweekday) or - (ii.nwdaymask and not ii.nwdaymask[i]) or - (byeaster and not ii.eastermask[i]) or - ((bymonthday or bynmonthday) and - ii.mdaymask[i] not in bymonthday and - ii.nmdaymask[i] not in bynmonthday) or - (byyearday and - ((i < ii.yearlen and i+1 not in byyearday and - -ii.yearlen+i not in byyearday) or - (i >= ii.yearlen and i+1-ii.yearlen not in byyearday and - -ii.nextyearlen+i-ii.yearlen not in byyearday)))): - dayset[i] = None - filtered = True - - # Output results - if bysetpos and timeset: - poslist = [] - for pos in bysetpos: - if pos < 0: - daypos, timepos = divmod(pos, len(timeset)) - else: - daypos, timepos = divmod(pos-1, len(timeset)) - try: - i = [x for x in dayset[start:end] - if x is not None][daypos] - time = timeset[timepos] - except IndexError: - pass - else: - date = datetime.date.fromordinal(ii.yearordinal+i) - res = datetime.datetime.combine(date, time) - if res not in poslist: - poslist.append(res) - poslist.sort() - for res in poslist: - if until and res > until: - self._len = total - return - elif res >= self._dtstart: - total += 1 - yield res - if count: - count -= 1 - if not count: - self._len = total - return - else: - for i in dayset[start:end]: - if i is not None: - date = datetime.date.fromordinal(ii.yearordinal+i) - for time in timeset: - res = datetime.datetime.combine(date, time) - if until and res > until: - self._len = total - return - elif res >= self._dtstart: - total += 1 - yield res - if count: - count -= 1 - if not count: - self._len = total - return - - # Handle frequency and interval - fixday = False - if freq == YEARLY: - year += interval - if year > datetime.MAXYEAR: - self._len = total - return - ii.rebuild(year, month) - elif freq == MONTHLY: - month += interval - if month > 12: - div, mod = divmod(month, 12) - month = mod - year += div - if month == 0: - month = 12 - year -= 1 - if year > datetime.MAXYEAR: - self._len = total - return - ii.rebuild(year, month) - elif freq == WEEKLY: - if wkst > weekday: - day += -(weekday+1+(6-wkst))+self._interval*7 - else: - day += -(weekday-wkst)+self._interval*7 - weekday = wkst - fixday = True - elif freq == DAILY: - day += interval - fixday = True - elif freq == HOURLY: - if filtered: - # Jump to one iteration before next day - hour += ((23-hour)//interval)*interval - - if byhour: - ndays, hour = self.__mod_distance(value=hour, - byxxx=self._byhour, - base=24) - else: - ndays, hour = divmod(hour+interval, 24) - - if ndays: - day += ndays - fixday = True - - timeset = gettimeset(hour, minute, second) - elif freq == MINUTELY: - if filtered: - # Jump to one iteration before next day - minute += ((1439-(hour*60+minute))//interval)*interval - - valid = False - rep_rate = (24*60) - for j in range(rep_rate // gcd(interval, rep_rate)): - if byminute: - nhours, minute = \ - self.__mod_distance(value=minute, - byxxx=self._byminute, - base=60) - else: - nhours, minute = divmod(minute+interval, 60) - - div, hour = divmod(hour+nhours, 24) - if div: - day += div - fixday = True - filtered = False - - if not byhour or hour in byhour: - valid = True - break - - if not valid: - raise ValueError('Invalid combination of interval and ' + - 'byhour resulting in empty rule.') - - timeset = gettimeset(hour, minute, second) - elif freq == SECONDLY: - if filtered: - # Jump to one iteration before next day - second += (((86399-(hour*3600+minute*60+second)) - // interval)*interval) - - rep_rate = (24*3600) - valid = False - for j in range(0, rep_rate // gcd(interval, rep_rate)): - if bysecond: - nminutes, second = \ - self.__mod_distance(value=second, - byxxx=self._bysecond, - base=60) - else: - nminutes, second = divmod(second+interval, 60) - - div, minute = divmod(minute+nminutes, 60) - if div: - hour += div - div, hour = divmod(hour, 24) - if div: - day += div - fixday = True - - if ((not byhour or hour in byhour) and - (not byminute or minute in byminute) and - (not bysecond or second in bysecond)): - valid = True - break - - if not valid: - raise ValueError('Invalid combination of interval, ' + - 'byhour and byminute resulting in empty' + - ' rule.') - - timeset = gettimeset(hour, minute, second) - - if fixday and day > 28: - daysinmonth = calendar.monthrange(year, month)[1] - if day > daysinmonth: - while day > daysinmonth: - day -= daysinmonth - month += 1 - if month == 13: - month = 1 - year += 1 - if year > datetime.MAXYEAR: - self._len = total - return - daysinmonth = calendar.monthrange(year, month)[1] - ii.rebuild(year, month) - - def __construct_byset(self, start, byxxx, base): - """ - If a `BYXXX` sequence is passed to the constructor at the same level as - `FREQ` (e.g. `FREQ=HOURLY,BYHOUR={2,4,7},INTERVAL=3`), there are some - specifications which cannot be reached given some starting conditions. - - This occurs whenever the interval is not coprime with the base of a - given unit and the difference between the starting position and the - ending position is not coprime with the greatest common denominator - between the interval and the base. For example, with a FREQ of hourly - starting at 17:00 and an interval of 4, the only valid values for - BYHOUR would be {21, 1, 5, 9, 13, 17}, because 4 and 24 are not - coprime. - - :param:`start` specifies the starting position. - :param:`byxxx` is an iterable containing the list of allowed values. - :param:`base` is the largest allowable value for the specified - frequency (e.g. 24 hours, 60 minutes). - - This does not preserve the type of the iterable, returning a set, since - the values should be unique and the order is irrelevant, this will - speed up later lookups. - - In the event of an empty set, raises a :exception:`ValueError`, as this - results in an empty rrule. - """ - - cset = set() - - # Support a single byxxx value. - if isinstance(byxxx, integer_types): - byxxx = (byxxx) - - for num in byxxx: - i_gcd = gcd(self._interval, base) - # Use divmod rather than % because we need to wrap negative nums. - if i_gcd == 1 or divmod(num - start, i_gcd)[1] == 0: - cset.add(num) - - if len(cset) == 0: - raise ValueError("Invalid rrule byxxx generates an empty set.") - - return cset - - def __mod_distance(self, value, byxxx, base): - """ - Calculates the next value in a sequence where the `FREQ` parameter is - specified along with a `BYXXX` parameter at the same "level" - (e.g. `HOURLY` specified with `BYHOUR`). - - :param:`value` is the old value of the component. - :param:`byxxx` is the `BYXXX` set, which should have been generated - by `rrule._construct_byset`, or something else which - checks that a valid rule is present. - :param:`base` is the largest allowable value for the specified - frequency (e.g. 24 hours, 60 minutes). - - If a valid value is not found after `base` iterations (the maximum - number before the sequence would start to repeat), this raises a - :exception:`ValueError`, as no valid values were found. - - This returns a tuple of `divmod(n*interval, base)`, where `n` is the - smallest number of `interval` repetitions until the next specified - value in `byxxx` is found. - """ - accumulator = 0 - for ii in range(1, base + 1): - # Using divmod() over % to account for negative intervals - div, value = divmod(value + self._interval, base) - accumulator += div - if value in byxxx: - return (accumulator, value) - - -class _iterinfo(object): - __slots__ = ["rrule", "lastyear", "lastmonth", - "yearlen", "nextyearlen", "yearordinal", "yearweekday", - "mmask", "mrange", "mdaymask", "nmdaymask", - "wdaymask", "wnomask", "nwdaymask", "eastermask"] - - def __init__(self, rrule): - for attr in self.__slots__: - setattr(self, attr, None) - self.rrule = rrule - - def rebuild(self, year, month): - # Every mask is 7 days longer to handle cross-year weekly periods. - rr = self.rrule - if year != self.lastyear: - self.yearlen = 365+calendar.isleap(year) - self.nextyearlen = 365+calendar.isleap(year+1) - firstyday = datetime.date(year, 1, 1) - self.yearordinal = firstyday.toordinal() - self.yearweekday = firstyday.weekday() - - wday = datetime.date(year, 1, 1).weekday() - if self.yearlen == 365: - self.mmask = M365MASK - self.mdaymask = MDAY365MASK - self.nmdaymask = NMDAY365MASK - self.wdaymask = WDAYMASK[wday:] - self.mrange = M365RANGE - else: - self.mmask = M366MASK - self.mdaymask = MDAY366MASK - self.nmdaymask = NMDAY366MASK - self.wdaymask = WDAYMASK[wday:] - self.mrange = M366RANGE - - if not rr._byweekno: - self.wnomask = None - else: - self.wnomask = [0]*(self.yearlen+7) - # no1wkst = firstwkst = self.wdaymask.index(rr._wkst) - no1wkst = firstwkst = (7-self.yearweekday+rr._wkst) % 7 - if no1wkst >= 4: - no1wkst = 0 - # Number of days in the year, plus the days we got - # from last year. - wyearlen = self.yearlen+(self.yearweekday-rr._wkst) % 7 - else: - # Number of days in the year, minus the days we - # left in last year. - wyearlen = self.yearlen-no1wkst - div, mod = divmod(wyearlen, 7) - numweeks = div+mod//4 - for n in rr._byweekno: - if n < 0: - n += numweeks+1 - if not (0 < n <= numweeks): - continue - if n > 1: - i = no1wkst+(n-1)*7 - if no1wkst != firstwkst: - i -= 7-firstwkst - else: - i = no1wkst - for j in range(7): - self.wnomask[i] = 1 - i += 1 - if self.wdaymask[i] == rr._wkst: - break - if 1 in rr._byweekno: - # Check week number 1 of next year as well - # TODO: Check -numweeks for next year. - i = no1wkst+numweeks*7 - if no1wkst != firstwkst: - i -= 7-firstwkst - if i < self.yearlen: - # If week starts in next year, we - # don't care about it. - for j in range(7): - self.wnomask[i] = 1 - i += 1 - if self.wdaymask[i] == rr._wkst: - break - if no1wkst: - # Check last week number of last year as - # well. If no1wkst is 0, either the year - # started on week start, or week number 1 - # got days from last year, so there are no - # days from last year's last week number in - # this year. - if -1 not in rr._byweekno: - lyearweekday = datetime.date(year-1, 1, 1).weekday() - lno1wkst = (7-lyearweekday+rr._wkst) % 7 - lyearlen = 365+calendar.isleap(year-1) - if lno1wkst >= 4: - lno1wkst = 0 - lnumweeks = 52+(lyearlen + - (lyearweekday-rr._wkst) % 7) % 7//4 - else: - lnumweeks = 52+(self.yearlen-no1wkst) % 7//4 - else: - lnumweeks = -1 - if lnumweeks in rr._byweekno: - for i in range(no1wkst): - self.wnomask[i] = 1 - - if (rr._bynweekday and (month != self.lastmonth or - year != self.lastyear)): - ranges = [] - if rr._freq == YEARLY: - if rr._bymonth: - for month in rr._bymonth: - ranges.append(self.mrange[month-1:month+1]) - else: - ranges = [(0, self.yearlen)] - elif rr._freq == MONTHLY: - ranges = [self.mrange[month-1:month+1]] - if ranges: - # Weekly frequency won't get here, so we may not - # care about cross-year weekly periods. - self.nwdaymask = [0]*self.yearlen - for first, last in ranges: - last -= 1 - for wday, n in rr._bynweekday: - if n < 0: - i = last+(n+1)*7 - i -= (self.wdaymask[i]-wday) % 7 - else: - i = first+(n-1)*7 - i += (7-self.wdaymask[i]+wday) % 7 - if first <= i <= last: - self.nwdaymask[i] = 1 - - if rr._byeaster: - self.eastermask = [0]*(self.yearlen+7) - eyday = easter.easter(year).toordinal()-self.yearordinal - for offset in rr._byeaster: - self.eastermask[eyday+offset] = 1 - - self.lastyear = year - self.lastmonth = month - - def ydayset(self, year, month, day): - return list(range(self.yearlen)), 0, self.yearlen - - def mdayset(self, year, month, day): - dset = [None]*self.yearlen - start, end = self.mrange[month-1:month+1] - for i in range(start, end): - dset[i] = i - return dset, start, end - - def wdayset(self, year, month, day): - # We need to handle cross-year weeks here. - dset = [None]*(self.yearlen+7) - i = datetime.date(year, month, day).toordinal()-self.yearordinal - start = i - for j in range(7): - dset[i] = i - i += 1 - # if (not (0 <= i < self.yearlen) or - # self.wdaymask[i] == self.rrule._wkst): - # This will cross the year boundary, if necessary. - if self.wdaymask[i] == self.rrule._wkst: - break - return dset, start, i - - def ddayset(self, year, month, day): - dset = [None]*self.yearlen - i = datetime.date(year, month, day).toordinal()-self.yearordinal - dset[i] = i - return dset, i, i+1 - - def htimeset(self, hour, minute, second): - tset = [] - rr = self.rrule - for minute in rr._byminute: - for second in rr._bysecond: - tset.append(datetime.time(hour, minute, second, - tzinfo=rr._tzinfo)) - tset.sort() - return tset - - def mtimeset(self, hour, minute, second): - tset = [] - rr = self.rrule - for second in rr._bysecond: - tset.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo)) - tset.sort() - return tset - - def stimeset(self, hour, minute, second): - return (datetime.time(hour, minute, second, - tzinfo=self.rrule._tzinfo),) - - -class rruleset(rrulebase): - """ The rruleset type allows more complex recurrence setups, mixing - multiple rules, dates, exclusion rules, and exclusion dates. The type - constructor takes the following keyword arguments: - - :param cache: If True, caching of results will be enabled, improving - performance of multiple queries considerably. """ - - class _genitem(object): - def __init__(self, genlist, gen): - try: - self.dt = advance_iterator(gen) - genlist.append(self) - except StopIteration: - pass - self.genlist = genlist - self.gen = gen - - def __next__(self): - try: - self.dt = advance_iterator(self.gen) - except StopIteration: - self.genlist.remove(self) - - next = __next__ - - def __lt__(self, other): - return self.dt < other.dt - - def __gt__(self, other): - return self.dt > other.dt - - def __eq__(self, other): - return self.dt == other.dt - - def __ne__(self, other): - return self.dt != other.dt - - def __init__(self, cache=False): - super(rruleset, self).__init__(cache) - self._rrule = [] - self._rdate = [] - self._exrule = [] - self._exdate = [] - - def rrule(self, rrule): - """ Include the given :py:class:`rrule` instance in the recurrence set - generation. """ - self._rrule.append(rrule) - - def rdate(self, rdate): - """ Include the given :py:class:`datetime` instance in the recurrence - set generation. """ - self._rdate.append(rdate) - - def exrule(self, exrule): - """ Include the given rrule instance in the recurrence set exclusion - list. Dates which are part of the given recurrence rules will not - be generated, even if some inclusive rrule or rdate matches them. - """ - self._exrule.append(exrule) - - def exdate(self, exdate): - """ Include the given datetime instance in the recurrence set - exclusion list. Dates included that way will not be generated, - even if some inclusive rrule or rdate matches them. """ - self._exdate.append(exdate) - - def _iter(self): - rlist = [] - self._rdate.sort() - self._genitem(rlist, iter(self._rdate)) - for gen in [iter(x) for x in self._rrule]: - self._genitem(rlist, gen) - rlist.sort() - exlist = [] - self._exdate.sort() - self._genitem(exlist, iter(self._exdate)) - for gen in [iter(x) for x in self._exrule]: - self._genitem(exlist, gen) - exlist.sort() - lastdt = None - total = 0 - while rlist: - ritem = rlist[0] - if not lastdt or lastdt != ritem.dt: - while exlist and exlist[0] < ritem: - advance_iterator(exlist[0]) - exlist.sort() - if not exlist or ritem != exlist[0]: - total += 1 - yield ritem.dt - lastdt = ritem.dt - advance_iterator(ritem) - rlist.sort() - self._len = total - - -class _rrulestr(object): - - _freq_map = {"YEARLY": YEARLY, - "MONTHLY": MONTHLY, - "WEEKLY": WEEKLY, - "DAILY": DAILY, - "HOURLY": HOURLY, - "MINUTELY": MINUTELY, - "SECONDLY": SECONDLY} - - _weekday_map = {"MO": 0, "TU": 1, "WE": 2, "TH": 3, - "FR": 4, "SA": 5, "SU": 6} - - def _handle_int(self, rrkwargs, name, value, **kwargs): - rrkwargs[name.lower()] = int(value) - - def _handle_int_list(self, rrkwargs, name, value, **kwargs): - rrkwargs[name.lower()] = [int(x) for x in value.split(',')] - - _handle_INTERVAL = _handle_int - _handle_COUNT = _handle_int - _handle_BYSETPOS = _handle_int_list - _handle_BYMONTH = _handle_int_list - _handle_BYMONTHDAY = _handle_int_list - _handle_BYYEARDAY = _handle_int_list - _handle_BYEASTER = _handle_int_list - _handle_BYWEEKNO = _handle_int_list - _handle_BYHOUR = _handle_int_list - _handle_BYMINUTE = _handle_int_list - _handle_BYSECOND = _handle_int_list - - def _handle_FREQ(self, rrkwargs, name, value, **kwargs): - rrkwargs["freq"] = self._freq_map[value] - - def _handle_UNTIL(self, rrkwargs, name, value, **kwargs): - global parser - if not parser: - from dateutil import parser - try: - rrkwargs["until"] = parser.parse(value, - ignoretz=kwargs.get("ignoretz"), - tzinfos=kwargs.get("tzinfos")) - except ValueError: - raise ValueError("invalid until date") - - def _handle_WKST(self, rrkwargs, name, value, **kwargs): - rrkwargs["wkst"] = self._weekday_map[value] - - def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwarsg): - l = [] - for wday in value.split(','): - for i in range(len(wday)): - if wday[i] not in '+-0123456789': - break - n = wday[:i] or None - w = wday[i:] - if n: - n = int(n) - l.append(weekdays[self._weekday_map[w]](n)) - rrkwargs["byweekday"] = l - - _handle_BYDAY = _handle_BYWEEKDAY - - def _parse_rfc_rrule(self, line, - dtstart=None, - cache=False, - ignoretz=False, - tzinfos=None): - if line.find(':') != -1: - name, value = line.split(':') - if name != "RRULE": - raise ValueError("unknown parameter name") - else: - value = line - rrkwargs = {} - for pair in value.split(';'): - name, value = pair.split('=') - name = name.upper() - value = value.upper() - try: - getattr(self, "_handle_"+name)(rrkwargs, name, value, - ignoretz=ignoretz, - tzinfos=tzinfos) - except AttributeError: - raise ValueError("unknown parameter '%s'" % name) - except (KeyError, ValueError): - raise ValueError("invalid '%s': %s" % (name, value)) - return rrule(dtstart=dtstart, cache=cache, **rrkwargs) - - def _parse_rfc(self, s, - dtstart=None, - cache=False, - unfold=False, - forceset=False, - compatible=False, - ignoretz=False, - tzinfos=None): - global parser - if compatible: - forceset = True - unfold = True - s = s.upper() - if not s.strip(): - raise ValueError("empty string") - if unfold: - lines = s.splitlines() - i = 0 - while i < len(lines): - line = lines[i].rstrip() - if not line: - del lines[i] - elif i > 0 and line[0] == " ": - lines[i-1] += line[1:] - del lines[i] - else: - i += 1 - else: - lines = s.split() - if (not forceset and len(lines) == 1 and (s.find(':') == -1 or - s.startswith('RRULE:'))): - return self._parse_rfc_rrule(lines[0], cache=cache, - dtstart=dtstart, ignoretz=ignoretz, - tzinfos=tzinfos) - else: - rrulevals = [] - rdatevals = [] - exrulevals = [] - exdatevals = [] - for line in lines: - if not line: - continue - if line.find(':') == -1: - name = "RRULE" - value = line - else: - name, value = line.split(':', 1) - parms = name.split(';') - if not parms: - raise ValueError("empty property name") - name = parms[0] - parms = parms[1:] - if name == "RRULE": - for parm in parms: - raise ValueError("unsupported RRULE parm: "+parm) - rrulevals.append(value) - elif name == "RDATE": - for parm in parms: - if parm != "VALUE=DATE-TIME": - raise ValueError("unsupported RDATE parm: "+parm) - rdatevals.append(value) - elif name == "EXRULE": - for parm in parms: - raise ValueError("unsupported EXRULE parm: "+parm) - exrulevals.append(value) - elif name == "EXDATE": - for parm in parms: - if parm != "VALUE=DATE-TIME": - raise ValueError("unsupported RDATE parm: "+parm) - exdatevals.append(value) - elif name == "DTSTART": - for parm in parms: - raise ValueError("unsupported DTSTART parm: "+parm) - if not parser: - from dateutil import parser - dtstart = parser.parse(value, ignoretz=ignoretz, - tzinfos=tzinfos) - else: - raise ValueError("unsupported property: "+name) - if (forceset or len(rrulevals) > 1 or rdatevals - or exrulevals or exdatevals): - if not parser and (rdatevals or exdatevals): - from dateutil import parser - rset = rruleset(cache=cache) - for value in rrulevals: - rset.rrule(self._parse_rfc_rrule(value, dtstart=dtstart, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in rdatevals: - for datestr in value.split(','): - rset.rdate(parser.parse(datestr, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in exrulevals: - rset.exrule(self._parse_rfc_rrule(value, dtstart=dtstart, - ignoretz=ignoretz, - tzinfos=tzinfos)) - for value in exdatevals: - for datestr in value.split(','): - rset.exdate(parser.parse(datestr, - ignoretz=ignoretz, - tzinfos=tzinfos)) - if compatible and dtstart: - rset.rdate(dtstart) - return rset - else: - return self._parse_rfc_rrule(rrulevals[0], - dtstart=dtstart, - cache=cache, - ignoretz=ignoretz, - tzinfos=tzinfos) - - def __call__(self, s, **kwargs): - return self._parse_rfc(s, **kwargs) - -rrulestr = _rrulestr() - -# vim:ts=4:sw=4:et diff --git a/awx/lib/site-packages/dateutil/tz.py b/awx/lib/site-packages/dateutil/tz.py deleted file mode 100644 index 31879e8be9..0000000000 --- a/awx/lib/site-packages/dateutil/tz.py +++ /dev/null @@ -1,986 +0,0 @@ -# -*- coding: utf-8 -*- -""" -This module offers timezone implementations subclassing the abstract -:py:`datetime.tzinfo` type. There are classes to handle tzfile format files -(usually are in :file:`/etc/localtime`, :file:`/usr/share/zoneinfo`, etc), TZ -environment string (in all known formats), given ranges (with help from -relative deltas), local machine timezone, fixed offset timezone, and UTC -timezone. -""" -import datetime -import struct -import time -import sys -import os - -from six import string_types, PY3 - -try: - from dateutil.tzwin import tzwin, tzwinlocal -except ImportError: - tzwin = tzwinlocal = None - -relativedelta = None -parser = None -rrule = None - -__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", - "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz"] - - -def tzname_in_python2(myfunc): - """Change unicode output into bytestrings in Python 2 - - tzname() API changed in Python 3. It used to return bytes, but was changed - to unicode strings - """ - def inner_func(*args, **kwargs): - if PY3: - return myfunc(*args, **kwargs) - else: - return myfunc(*args, **kwargs).encode() - return inner_func - -ZERO = datetime.timedelta(0) -EPOCHORDINAL = datetime.datetime.utcfromtimestamp(0).toordinal() - - -class tzutc(datetime.tzinfo): - - def utcoffset(self, dt): - return ZERO - - def dst(self, dt): - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return "UTC" - - def __eq__(self, other): - return (isinstance(other, tzutc) or - (isinstance(other, tzoffset) and other._offset == ZERO)) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s()" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -class tzoffset(datetime.tzinfo): - - def __init__(self, name, offset): - self._name = name - self._offset = datetime.timedelta(seconds=offset) - - def utcoffset(self, dt): - return self._offset - - def dst(self, dt): - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return self._name - - def __eq__(self, other): - return (isinstance(other, tzoffset) and - self._offset == other._offset) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s(%s, %s)" % (self.__class__.__name__, - repr(self._name), - self._offset.days*86400+self._offset.seconds) - - __reduce__ = object.__reduce__ - - -class tzlocal(datetime.tzinfo): - - _std_offset = datetime.timedelta(seconds=-time.timezone) - if time.daylight: - _dst_offset = datetime.timedelta(seconds=-time.altzone) - else: - _dst_offset = _std_offset - - def utcoffset(self, dt): - if self._isdst(dt): - return self._dst_offset - else: - return self._std_offset - - def dst(self, dt): - if self._isdst(dt): - return self._dst_offset-self._std_offset - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return time.tzname[self._isdst(dt)] - - def _isdst(self, dt): - # We can't use mktime here. It is unstable when deciding if - # the hour near to a change is DST or not. - # - # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour, - # dt.minute, dt.second, dt.weekday(), 0, -1)) - # return time.localtime(timestamp).tm_isdst - # - # The code above yields the following result: - # - # >>> import tz, datetime - # >>> t = tz.tzlocal() - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRDT' - # >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname() - # 'BRST' - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRST' - # >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname() - # 'BRDT' - # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() - # 'BRDT' - # - # Here is a more stable implementation: - # - timestamp = ((dt.toordinal() - EPOCHORDINAL) * 86400 - + dt.hour * 3600 - + dt.minute * 60 - + dt.second) - return time.localtime(timestamp+time.timezone).tm_isdst - - def __eq__(self, other): - if not isinstance(other, tzlocal): - return False - return (self._std_offset == other._std_offset and - self._dst_offset == other._dst_offset) - return True - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s()" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -class _ttinfo(object): - __slots__ = ["offset", "delta", "isdst", "abbr", "isstd", "isgmt"] - - def __init__(self): - for attr in self.__slots__: - setattr(self, attr, None) - - def __repr__(self): - l = [] - for attr in self.__slots__: - value = getattr(self, attr) - if value is not None: - l.append("%s=%s" % (attr, repr(value))) - return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) - - def __eq__(self, other): - if not isinstance(other, _ttinfo): - return False - return (self.offset == other.offset and - self.delta == other.delta and - self.isdst == other.isdst and - self.abbr == other.abbr and - self.isstd == other.isstd and - self.isgmt == other.isgmt) - - def __ne__(self, other): - return not self.__eq__(other) - - def __getstate__(self): - state = {} - for name in self.__slots__: - state[name] = getattr(self, name, None) - return state - - def __setstate__(self, state): - for name in self.__slots__: - if name in state: - setattr(self, name, state[name]) - - -class tzfile(datetime.tzinfo): - - # http://www.twinsun.com/tz/tz-link.htm - # ftp://ftp.iana.org/tz/tz*.tar.gz - - def __init__(self, fileobj, filename=None): - file_opened_here = False - if isinstance(fileobj, string_types): - self._filename = fileobj - fileobj = open(fileobj, 'rb') - file_opened_here = True - elif filename is not None: - self._filename = filename - elif hasattr(fileobj, "name"): - self._filename = fileobj.name - else: - self._filename = repr(fileobj) - - # From tzfile(5): - # - # The time zone information files used by tzset(3) - # begin with the magic characters "TZif" to identify - # them as time zone information files, followed by - # sixteen bytes reserved for future use, followed by - # six four-byte values of type long, written in a - # ``standard'' byte order (the high-order byte - # of the value is written first). - try: - if fileobj.read(4).decode() != "TZif": - raise ValueError("magic not found") - - fileobj.read(16) - - ( - # The number of UTC/local indicators stored in the file. - ttisgmtcnt, - - # The number of standard/wall indicators stored in the file. - ttisstdcnt, - - # The number of leap seconds for which data is - # stored in the file. - leapcnt, - - # The number of "transition times" for which data - # is stored in the file. - timecnt, - - # The number of "local time types" for which data - # is stored in the file (must not be zero). - typecnt, - - # The number of characters of "time zone - # abbreviation strings" stored in the file. - charcnt, - - ) = struct.unpack(">6l", fileobj.read(24)) - - # The above header is followed by tzh_timecnt four-byte - # values of type long, sorted in ascending order. - # These values are written in ``standard'' byte order. - # Each is used as a transition time (as returned by - # time(2)) at which the rules for computing local time - # change. - - if timecnt: - self._trans_list = struct.unpack(">%dl" % timecnt, - fileobj.read(timecnt*4)) - else: - self._trans_list = [] - - # Next come tzh_timecnt one-byte values of type unsigned - # char; each one tells which of the different types of - # ``local time'' types described in the file is associated - # with the same-indexed transition time. These values - # serve as indices into an array of ttinfo structures that - # appears next in the file. - - if timecnt: - self._trans_idx = struct.unpack(">%dB" % timecnt, - fileobj.read(timecnt)) - else: - self._trans_idx = [] - - # Each ttinfo structure is written as a four-byte value - # for tt_gmtoff of type long, in a standard byte - # order, followed by a one-byte value for tt_isdst - # and a one-byte value for tt_abbrind. In each - # structure, tt_gmtoff gives the number of - # seconds to be added to UTC, tt_isdst tells whether - # tm_isdst should be set by localtime(3), and - # tt_abbrind serves as an index into the array of - # time zone abbreviation characters that follow the - # ttinfo structure(s) in the file. - - ttinfo = [] - - for i in range(typecnt): - ttinfo.append(struct.unpack(">lbb", fileobj.read(6))) - - abbr = fileobj.read(charcnt).decode() - - # Then there are tzh_leapcnt pairs of four-byte - # values, written in standard byte order; the - # first value of each pair gives the time (as - # returned by time(2)) at which a leap second - # occurs; the second gives the total number of - # leap seconds to be applied after the given time. - # The pairs of values are sorted in ascending order - # by time. - - # Not used, for now - # if leapcnt: - # leap = struct.unpack(">%dl" % (leapcnt*2), - # fileobj.read(leapcnt*8)) - - # Then there are tzh_ttisstdcnt standard/wall - # indicators, each stored as a one-byte value; - # they tell whether the transition times associated - # with local time types were specified as standard - # time or wall clock time, and are used when - # a time zone file is used in handling POSIX-style - # time zone environment variables. - - if ttisstdcnt: - isstd = struct.unpack(">%db" % ttisstdcnt, - fileobj.read(ttisstdcnt)) - - # Finally, there are tzh_ttisgmtcnt UTC/local - # indicators, each stored as a one-byte value; - # they tell whether the transition times associated - # with local time types were specified as UTC or - # local time, and are used when a time zone file - # is used in handling POSIX-style time zone envi- - # ronment variables. - - if ttisgmtcnt: - isgmt = struct.unpack(">%db" % ttisgmtcnt, - fileobj.read(ttisgmtcnt)) - - # ** Everything has been read ** - finally: - if file_opened_here: - fileobj.close() - - # Build ttinfo list - self._ttinfo_list = [] - for i in range(typecnt): - gmtoff, isdst, abbrind = ttinfo[i] - # Round to full-minutes if that's not the case. Python's - # datetime doesn't accept sub-minute timezones. Check - # http://python.org/sf/1447945 for some information. - gmtoff = (gmtoff+30)//60*60 - tti = _ttinfo() - tti.offset = gmtoff - tti.delta = datetime.timedelta(seconds=gmtoff) - tti.isdst = isdst - tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)] - tti.isstd = (ttisstdcnt > i and isstd[i] != 0) - tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0) - self._ttinfo_list.append(tti) - - # Replace ttinfo indexes for ttinfo objects. - trans_idx = [] - for idx in self._trans_idx: - trans_idx.append(self._ttinfo_list[idx]) - self._trans_idx = tuple(trans_idx) - - # Set standard, dst, and before ttinfos. before will be - # used when a given time is before any transitions, - # and will be set to the first non-dst ttinfo, or to - # the first dst, if all of them are dst. - self._ttinfo_std = None - self._ttinfo_dst = None - self._ttinfo_before = None - if self._ttinfo_list: - if not self._trans_list: - self._ttinfo_std = self._ttinfo_first = self._ttinfo_list[0] - else: - for i in range(timecnt-1, -1, -1): - tti = self._trans_idx[i] - if not self._ttinfo_std and not tti.isdst: - self._ttinfo_std = tti - elif not self._ttinfo_dst and tti.isdst: - self._ttinfo_dst = tti - if self._ttinfo_std and self._ttinfo_dst: - break - else: - if self._ttinfo_dst and not self._ttinfo_std: - self._ttinfo_std = self._ttinfo_dst - - for tti in self._ttinfo_list: - if not tti.isdst: - self._ttinfo_before = tti - break - else: - self._ttinfo_before = self._ttinfo_list[0] - - # Now fix transition times to become relative to wall time. - # - # I'm not sure about this. In my tests, the tz source file - # is setup to wall time, and in the binary file isstd and - # isgmt are off, so it should be in wall time. OTOH, it's - # always in gmt time. Let me know if you have comments - # about this. - laststdoffset = 0 - self._trans_list = list(self._trans_list) - for i in range(len(self._trans_list)): - tti = self._trans_idx[i] - if not tti.isdst: - # This is std time. - self._trans_list[i] += tti.offset - laststdoffset = tti.offset - else: - # This is dst time. Convert to std. - self._trans_list[i] += laststdoffset - self._trans_list = tuple(self._trans_list) - - def _find_ttinfo(self, dt, laststd=0): - timestamp = ((dt.toordinal() - EPOCHORDINAL) * 86400 - + dt.hour * 3600 - + dt.minute * 60 - + dt.second) - idx = 0 - for trans in self._trans_list: - if timestamp < trans: - break - idx += 1 - else: - return self._ttinfo_std - if idx == 0: - return self._ttinfo_before - if laststd: - while idx > 0: - tti = self._trans_idx[idx-1] - if not tti.isdst: - return tti - idx -= 1 - else: - return self._ttinfo_std - else: - return self._trans_idx[idx-1] - - def utcoffset(self, dt): - if not self._ttinfo_std: - return ZERO - return self._find_ttinfo(dt).delta - - def dst(self, dt): - if not self._ttinfo_dst: - return ZERO - tti = self._find_ttinfo(dt) - if not tti.isdst: - return ZERO - - # The documentation says that utcoffset()-dst() must - # be constant for every dt. - return tti.delta-self._find_ttinfo(dt, laststd=1).delta - - # An alternative for that would be: - # - # return self._ttinfo_dst.offset-self._ttinfo_std.offset - # - # However, this class stores historical changes in the - # dst offset, so I belive that this wouldn't be the right - # way to implement this. - - @tzname_in_python2 - def tzname(self, dt): - if not self._ttinfo_std: - return None - return self._find_ttinfo(dt).abbr - - def __eq__(self, other): - if not isinstance(other, tzfile): - return False - return (self._trans_list == other._trans_list and - self._trans_idx == other._trans_idx and - self._ttinfo_list == other._ttinfo_list) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._filename)) - - def __reduce__(self): - if not os.path.isfile(self._filename): - raise ValueError("Unpickable %s class" % self.__class__.__name__) - return (self.__class__, (self._filename,)) - - -class tzrange(datetime.tzinfo): - def __init__(self, stdabbr, stdoffset=None, - dstabbr=None, dstoffset=None, - start=None, end=None): - global relativedelta - if not relativedelta: - from dateutil import relativedelta - self._std_abbr = stdabbr - self._dst_abbr = dstabbr - if stdoffset is not None: - self._std_offset = datetime.timedelta(seconds=stdoffset) - else: - self._std_offset = ZERO - if dstoffset is not None: - self._dst_offset = datetime.timedelta(seconds=dstoffset) - elif dstabbr and stdoffset is not None: - self._dst_offset = self._std_offset+datetime.timedelta(hours=+1) - else: - self._dst_offset = ZERO - if dstabbr and start is None: - self._start_delta = relativedelta.relativedelta( - hours=+2, month=4, day=1, weekday=relativedelta.SU(+1)) - else: - self._start_delta = start - if dstabbr and end is None: - self._end_delta = relativedelta.relativedelta( - hours=+1, month=10, day=31, weekday=relativedelta.SU(-1)) - else: - self._end_delta = end - - def utcoffset(self, dt): - if self._isdst(dt): - return self._dst_offset - else: - return self._std_offset - - def dst(self, dt): - if self._isdst(dt): - return self._dst_offset-self._std_offset - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - if self._isdst(dt): - return self._dst_abbr - else: - return self._std_abbr - - def _isdst(self, dt): - if not self._start_delta: - return False - year = datetime.datetime(dt.year, 1, 1) - start = year+self._start_delta - end = year+self._end_delta - dt = dt.replace(tzinfo=None) - if start < end: - return dt >= start and dt < end - else: - return dt >= start or dt < end - - def __eq__(self, other): - if not isinstance(other, tzrange): - return False - return (self._std_abbr == other._std_abbr and - self._dst_abbr == other._dst_abbr and - self._std_offset == other._std_offset and - self._dst_offset == other._dst_offset and - self._start_delta == other._start_delta and - self._end_delta == other._end_delta) - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return "%s(...)" % self.__class__.__name__ - - __reduce__ = object.__reduce__ - - -class tzstr(tzrange): - - def __init__(self, s): - global parser - if not parser: - from dateutil import parser - self._s = s - - res = parser._parsetz(s) - if res is None: - raise ValueError("unknown string format") - - # Here we break the compatibility with the TZ variable handling. - # GMT-3 actually *means* the timezone -3. - if res.stdabbr in ("GMT", "UTC"): - res.stdoffset *= -1 - - # We must initialize it first, since _delta() needs - # _std_offset and _dst_offset set. Use False in start/end - # to avoid building it two times. - tzrange.__init__(self, res.stdabbr, res.stdoffset, - res.dstabbr, res.dstoffset, - start=False, end=False) - - if not res.dstabbr: - self._start_delta = None - self._end_delta = None - else: - self._start_delta = self._delta(res.start) - if self._start_delta: - self._end_delta = self._delta(res.end, isend=1) - - def _delta(self, x, isend=0): - kwargs = {} - if x.month is not None: - kwargs["month"] = x.month - if x.weekday is not None: - kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week) - if x.week > 0: - kwargs["day"] = 1 - else: - kwargs["day"] = 31 - elif x.day: - kwargs["day"] = x.day - elif x.yday is not None: - kwargs["yearday"] = x.yday - elif x.jyday is not None: - kwargs["nlyearday"] = x.jyday - if not kwargs: - # Default is to start on first sunday of april, and end - # on last sunday of october. - if not isend: - kwargs["month"] = 4 - kwargs["day"] = 1 - kwargs["weekday"] = relativedelta.SU(+1) - else: - kwargs["month"] = 10 - kwargs["day"] = 31 - kwargs["weekday"] = relativedelta.SU(-1) - if x.time is not None: - kwargs["seconds"] = x.time - else: - # Default is 2AM. - kwargs["seconds"] = 7200 - if isend: - # Convert to standard time, to follow the documented way - # of working with the extra hour. See the documentation - # of the tzinfo class. - delta = self._dst_offset-self._std_offset - kwargs["seconds"] -= delta.seconds+delta.days*86400 - return relativedelta.relativedelta(**kwargs) - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._s)) - - -class _tzicalvtzcomp(object): - def __init__(self, tzoffsetfrom, tzoffsetto, isdst, - tzname=None, rrule=None): - self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom) - self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto) - self.tzoffsetdiff = self.tzoffsetto-self.tzoffsetfrom - self.isdst = isdst - self.tzname = tzname - self.rrule = rrule - - -class _tzicalvtz(datetime.tzinfo): - def __init__(self, tzid, comps=[]): - self._tzid = tzid - self._comps = comps - self._cachedate = [] - self._cachecomp = [] - - def _find_comp(self, dt): - if len(self._comps) == 1: - return self._comps[0] - dt = dt.replace(tzinfo=None) - try: - return self._cachecomp[self._cachedate.index(dt)] - except ValueError: - pass - lastcomp = None - lastcompdt = None - for comp in self._comps: - if not comp.isdst: - # Handle the extra hour in DST -> STD - compdt = comp.rrule.before(dt-comp.tzoffsetdiff, inc=True) - else: - compdt = comp.rrule.before(dt, inc=True) - if compdt and (not lastcompdt or lastcompdt < compdt): - lastcompdt = compdt - lastcomp = comp - if not lastcomp: - # RFC says nothing about what to do when a given - # time is before the first onset date. We'll look for the - # first standard component, or the first component, if - # none is found. - for comp in self._comps: - if not comp.isdst: - lastcomp = comp - break - else: - lastcomp = comp[0] - self._cachedate.insert(0, dt) - self._cachecomp.insert(0, lastcomp) - if len(self._cachedate) > 10: - self._cachedate.pop() - self._cachecomp.pop() - return lastcomp - - def utcoffset(self, dt): - return self._find_comp(dt).tzoffsetto - - def dst(self, dt): - comp = self._find_comp(dt) - if comp.isdst: - return comp.tzoffsetdiff - else: - return ZERO - - @tzname_in_python2 - def tzname(self, dt): - return self._find_comp(dt).tzname - - def __repr__(self): - return "<tzicalvtz %s>" % repr(self._tzid) - - __reduce__ = object.__reduce__ - - -class tzical(object): - def __init__(self, fileobj): - global rrule - if not rrule: - from dateutil import rrule - - if isinstance(fileobj, string_types): - self._s = fileobj - # ical should be encoded in UTF-8 with CRLF - fileobj = open(fileobj, 'r') - elif hasattr(fileobj, "name"): - self._s = fileobj.name - else: - self._s = repr(fileobj) - - self._vtz = {} - - self._parse_rfc(fileobj.read()) - - def keys(self): - return list(self._vtz.keys()) - - def get(self, tzid=None): - if tzid is None: - keys = list(self._vtz.keys()) - if len(keys) == 0: - raise ValueError("no timezones defined") - elif len(keys) > 1: - raise ValueError("more than one timezone available") - tzid = keys[0] - return self._vtz.get(tzid) - - def _parse_offset(self, s): - s = s.strip() - if not s: - raise ValueError("empty offset") - if s[0] in ('+', '-'): - signal = (-1, +1)[s[0] == '+'] - s = s[1:] - else: - signal = +1 - if len(s) == 4: - return (int(s[:2])*3600+int(s[2:])*60)*signal - elif len(s) == 6: - return (int(s[:2])*3600+int(s[2:4])*60+int(s[4:]))*signal - else: - raise ValueError("invalid offset: "+s) - - def _parse_rfc(self, s): - lines = s.splitlines() - if not lines: - raise ValueError("empty string") - - # Unfold - i = 0 - while i < len(lines): - line = lines[i].rstrip() - if not line: - del lines[i] - elif i > 0 and line[0] == " ": - lines[i-1] += line[1:] - del lines[i] - else: - i += 1 - - tzid = None - comps = [] - invtz = False - comptype = None - for line in lines: - if not line: - continue - name, value = line.split(':', 1) - parms = name.split(';') - if not parms: - raise ValueError("empty property name") - name = parms[0].upper() - parms = parms[1:] - if invtz: - if name == "BEGIN": - if value in ("STANDARD", "DAYLIGHT"): - # Process component - pass - else: - raise ValueError("unknown component: "+value) - comptype = value - founddtstart = False - tzoffsetfrom = None - tzoffsetto = None - rrulelines = [] - tzname = None - elif name == "END": - if value == "VTIMEZONE": - if comptype: - raise ValueError("component not closed: "+comptype) - if not tzid: - raise ValueError("mandatory TZID not found") - if not comps: - raise ValueError( - "at least one component is needed") - # Process vtimezone - self._vtz[tzid] = _tzicalvtz(tzid, comps) - invtz = False - elif value == comptype: - if not founddtstart: - raise ValueError("mandatory DTSTART not found") - if tzoffsetfrom is None: - raise ValueError( - "mandatory TZOFFSETFROM not found") - if tzoffsetto is None: - raise ValueError( - "mandatory TZOFFSETFROM not found") - # Process component - rr = None - if rrulelines: - rr = rrule.rrulestr("\n".join(rrulelines), - compatible=True, - ignoretz=True, - cache=True) - comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto, - (comptype == "DAYLIGHT"), - tzname, rr) - comps.append(comp) - comptype = None - else: - raise ValueError("invalid component end: "+value) - elif comptype: - if name == "DTSTART": - rrulelines.append(line) - founddtstart = True - elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"): - rrulelines.append(line) - elif name == "TZOFFSETFROM": - if parms: - raise ValueError( - "unsupported %s parm: %s " % (name, parms[0])) - tzoffsetfrom = self._parse_offset(value) - elif name == "TZOFFSETTO": - if parms: - raise ValueError( - "unsupported TZOFFSETTO parm: "+parms[0]) - tzoffsetto = self._parse_offset(value) - elif name == "TZNAME": - if parms: - raise ValueError( - "unsupported TZNAME parm: "+parms[0]) - tzname = value - elif name == "COMMENT": - pass - else: - raise ValueError("unsupported property: "+name) - else: - if name == "TZID": - if parms: - raise ValueError( - "unsupported TZID parm: "+parms[0]) - tzid = value - elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"): - pass - else: - raise ValueError("unsupported property: "+name) - elif name == "BEGIN" and value == "VTIMEZONE": - tzid = None - comps = [] - invtz = True - - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, repr(self._s)) - -if sys.platform != "win32": - TZFILES = ["/etc/localtime", "localtime"] - TZPATHS = ["/usr/share/zoneinfo", "/usr/lib/zoneinfo", "/etc/zoneinfo"] -else: - TZFILES = [] - TZPATHS = [] - - -def gettz(name=None): - tz = None - if not name: - try: - name = os.environ["TZ"] - except KeyError: - pass - if name is None or name == ":": - for filepath in TZFILES: - if not os.path.isabs(filepath): - filename = filepath - for path in TZPATHS: - filepath = os.path.join(path, filename) - if os.path.isfile(filepath): - break - else: - continue - if os.path.isfile(filepath): - try: - tz = tzfile(filepath) - break - except (IOError, OSError, ValueError): - pass - else: - tz = tzlocal() - else: - if name.startswith(":"): - name = name[:-1] - if os.path.isabs(name): - if os.path.isfile(name): - tz = tzfile(name) - else: - tz = None - else: - for path in TZPATHS: - filepath = os.path.join(path, name) - if not os.path.isfile(filepath): - filepath = filepath.replace(' ', '_') - if not os.path.isfile(filepath): - continue - try: - tz = tzfile(filepath) - break - except (IOError, OSError, ValueError): - pass - else: - tz = None - if tzwin is not None: - try: - tz = tzwin(name) - except WindowsError: - tz = None - if not tz: - from dateutil.zoneinfo import gettz - tz = gettz(name) - if not tz: - for c in name: - # name must have at least one offset to be a tzstr - if c in "0123456789": - try: - tz = tzstr(name) - except ValueError: - pass - break - else: - if name in ("GMT", "UTC"): - tz = tzutc() - elif name in time.tzname: - tz = tzlocal() - return tz - -# vim:ts=4:sw=4:et diff --git a/awx/lib/site-packages/dateutil/tzwin.py b/awx/lib/site-packages/dateutil/tzwin.py deleted file mode 100644 index e8a82d7587..0000000000 --- a/awx/lib/site-packages/dateutil/tzwin.py +++ /dev/null @@ -1,184 +0,0 @@ -# This code was originally contributed by Jeffrey Harris. -import datetime -import struct - -from six.moves import winreg - -__all__ = ["tzwin", "tzwinlocal"] - -ONEWEEK = datetime.timedelta(7) - -TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" -TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones" -TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" - - -def _settzkeyname(): - handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - try: - winreg.OpenKey(handle, TZKEYNAMENT).Close() - TZKEYNAME = TZKEYNAMENT - except WindowsError: - TZKEYNAME = TZKEYNAME9X - handle.Close() - return TZKEYNAME - -TZKEYNAME = _settzkeyname() - - -class tzwinbase(datetime.tzinfo): - """tzinfo class based on win32's timezones available in the registry.""" - - def utcoffset(self, dt): - if self._isdst(dt): - return datetime.timedelta(minutes=self._dstoffset) - else: - return datetime.timedelta(minutes=self._stdoffset) - - def dst(self, dt): - if self._isdst(dt): - minutes = self._dstoffset - self._stdoffset - return datetime.timedelta(minutes=minutes) - else: - return datetime.timedelta(0) - - def tzname(self, dt): - if self._isdst(dt): - return self._dstname - else: - return self._stdname - - def list(): - """Return a list of all time zones known to the system.""" - handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - tzkey = winreg.OpenKey(handle, TZKEYNAME) - result = [winreg.EnumKey(tzkey, i) - for i in range(winreg.QueryInfoKey(tzkey)[0])] - tzkey.Close() - handle.Close() - return result - list = staticmethod(list) - - def display(self): - return self._display - - def _isdst(self, dt): - if not self._dstmonth: - # dstmonth == 0 signals the zone has no daylight saving time - return False - dston = picknthweekday(dt.year, self._dstmonth, self._dstdayofweek, - self._dsthour, self._dstminute, - self._dstweeknumber) - dstoff = picknthweekday(dt.year, self._stdmonth, self._stddayofweek, - self._stdhour, self._stdminute, - self._stdweeknumber) - if dston < dstoff: - return dston <= dt.replace(tzinfo=None) < dstoff - else: - return not dstoff <= dt.replace(tzinfo=None) < dston - - -class tzwin(tzwinbase): - - def __init__(self, name): - self._name = name - - # multiple contexts only possible in 2.7 and 3.1, we still support 2.6 - with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: - with winreg.OpenKey(handle, - "%s\%s" % (TZKEYNAME, name)) as tzkey: - keydict = valuestodict(tzkey) - - self._stdname = keydict["Std"].encode("iso-8859-1") - self._dstname = keydict["Dlt"].encode("iso-8859-1") - - self._display = keydict["Display"] - - # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm - tup = struct.unpack("=3l16h", keydict["TZI"]) - self._stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1 - self._dstoffset = self._stdoffset-tup[2] # + DaylightBias * -1 - - # for the meaning see the win32 TIME_ZONE_INFORMATION structure docs - # http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx - (self._stdmonth, - self._stddayofweek, # Sunday = 0 - self._stdweeknumber, # Last = 5 - self._stdhour, - self._stdminute) = tup[4:9] - - (self._dstmonth, - self._dstdayofweek, # Sunday = 0 - self._dstweeknumber, # Last = 5 - self._dsthour, - self._dstminute) = tup[12:17] - - def __repr__(self): - return "tzwin(%s)" % repr(self._name) - - def __reduce__(self): - return (self.__class__, (self._name,)) - - -class tzwinlocal(tzwinbase): - - def __init__(self): - - with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: - - with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: - keydict = valuestodict(tzlocalkey) - - self._stdname = keydict["StandardName"].encode("iso-8859-1") - self._dstname = keydict["DaylightName"].encode("iso-8859-1") - - try: - with winreg.OpenKey( - handle, "%s\%s" % (TZKEYNAME, self._stdname)) as tzkey: - _keydict = valuestodict(tzkey) - self._display = _keydict["Display"] - except OSError: - self._display = None - - self._stdoffset = -keydict["Bias"]-keydict["StandardBias"] - self._dstoffset = self._stdoffset-keydict["DaylightBias"] - - # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm - tup = struct.unpack("=8h", keydict["StandardStart"]) - - (self._stdmonth, - self._stddayofweek, # Sunday = 0 - self._stdweeknumber, # Last = 5 - self._stdhour, - self._stdminute) = tup[1:6] - - tup = struct.unpack("=8h", keydict["DaylightStart"]) - - (self._dstmonth, - self._dstdayofweek, # Sunday = 0 - self._dstweeknumber, # Last = 5 - self._dsthour, - self._dstminute) = tup[1:6] - - def __reduce__(self): - return (self.__class__, ()) - - -def picknthweekday(year, month, dayofweek, hour, minute, whichweek): - """dayofweek == 0 means Sunday, whichweek 5 means last instance""" - first = datetime.datetime(year, month, 1, hour, minute) - weekdayone = first.replace(day=((dayofweek-first.isoweekday()) % 7+1)) - for n in range(whichweek): - dt = weekdayone+(whichweek-n)*ONEWEEK - if dt.month == month: - return dt - - -def valuestodict(key): - """Convert a registry key's values to a dictionary.""" - dict = {} - size = winreg.QueryInfoKey(key)[1] - for i in range(size): - data = winreg.EnumValue(key, i) - dict[data[0]] = data[1] - return dict diff --git a/awx/lib/site-packages/dateutil/zoneinfo/__init__.py b/awx/lib/site-packages/dateutil/zoneinfo/__init__.py deleted file mode 100644 index 53d9dfee0c..0000000000 --- a/awx/lib/site-packages/dateutil/zoneinfo/__init__.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -import logging -import os -import warnings -import tempfile -import shutil -from subprocess import check_call -from tarfile import TarFile -from pkgutil import get_data -from io import BytesIO -from contextlib import closing - -from dateutil.tz import tzfile - -__all__ = ["setcachesize", "gettz", "rebuild"] - -_ZONEFILENAME = "dateutil-zoneinfo.tar.gz" - -# python2.6 compatability. Note that TarFile.__exit__ != TarFile.close, but -# it's close enough for python2.6 -_tar_open = TarFile.open -if not hasattr(TarFile, '__exit__'): - def _tar_open(*args, **kwargs): - return closing(TarFile.open(*args, **kwargs)) - - -class tzfile(tzfile): - def __reduce__(self): - return (gettz, (self._filename,)) - - -def getzoneinfofile_stream(): - try: - return BytesIO(get_data(__name__, _ZONEFILENAME)) - except IOError as e: # TODO switch to FileNotFoundError? - warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror)) - return None - - -class ZoneInfoFile(object): - def __init__(self, zonefile_stream=None): - if zonefile_stream is not None: - with _tar_open(fileobj=zonefile_stream, mode='r') as tf: - # dict comprehension does not work on python2.6 - # TODO: get back to the nicer syntax when we ditch python2.6 - # self.zones = {zf.name: tzfile(tf.extractfile(zf), - # filename = zf.name) - # for zf in tf.getmembers() if zf.isfile()} - self.zones = dict((zf.name, tzfile(tf.extractfile(zf), - filename=zf.name)) - for zf in tf.getmembers() if zf.isfile()) - # deal with links: They'll point to their parent object. Less - # waste of memory - # links = {zl.name: self.zones[zl.linkname] - # for zl in tf.getmembers() if zl.islnk() or zl.issym()} - links = dict((zl.name, self.zones[zl.linkname]) - for zl in tf.getmembers() if - zl.islnk() or zl.issym()) - self.zones.update(links) - else: - self.zones = dict() - - -# The current API has gettz as a module function, although in fact it taps into -# a stateful class. So as a workaround for now, without changing the API, we -# will create a new "global" class instance the first time a user requests a -# timezone. Ugly, but adheres to the api. -# -# TODO: deprecate this. -_CLASS_ZONE_INSTANCE = list() - - -def gettz(name): - if len(_CLASS_ZONE_INSTANCE) == 0: - _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) - return _CLASS_ZONE_INSTANCE[0].zones.get(name) - - -def rebuild(filename, tag=None, format="gz", zonegroups=[]): - """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar* - - filename is the timezone tarball from ftp.iana.org/tz. - - """ - tmpdir = tempfile.mkdtemp() - zonedir = os.path.join(tmpdir, "zoneinfo") - moduledir = os.path.dirname(__file__) - try: - with _tar_open(filename) as tf: - for name in zonegroups: - tf.extract(name, tmpdir) - filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - try: - check_call(["zic", "-d", zonedir] + filepaths) - except OSError as e: - if e.errno == 2: - logging.error( - "Could not find zic. Perhaps you need to install " - "libc-bin or some other package that provides it, " - "or it's not in your PATH?") - raise - target = os.path.join(moduledir, _ZONEFILENAME) - with _tar_open(target, "w:%s" % format) as tf: - for entry in os.listdir(zonedir): - entrypath = os.path.join(zonedir, entry) - tf.add(entrypath, entry) - finally: - shutil.rmtree(tmpdir) diff --git a/awx/lib/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz b/awx/lib/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz deleted file mode 100644 index 4c95eda3e4..0000000000 Binary files a/awx/lib/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz and /dev/null differ diff --git a/awx/lib/site-packages/django_auth_ldap/__init__.py b/awx/lib/site-packages/django_auth_ldap/__init__.py deleted file mode 100644 index fe08020d3d..0000000000 --- a/awx/lib/site-packages/django_auth_ldap/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -version = (1, 1, 8) -version_string = '.'.join(map(str, version)) diff --git a/awx/lib/site-packages/django_auth_ldap/backend.py b/awx/lib/site-packages/django_auth_ldap/backend.py deleted file mode 100644 index e0bcc64e6d..0000000000 --- a/awx/lib/site-packages/django_auth_ldap/backend.py +++ /dev/null @@ -1,871 +0,0 @@ -# Copyright (c) 2009, Peter Sagerson -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# - Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -LDAP authentication backend - -Complete documentation can be found in docs/howto/auth-ldap.txt (or the thing it -compiles to). - -Use of this backend requires the python-ldap module. To support unit tests, we -import ldap in a single centralized place (config._LDAPConfig) so that the test -harness can insert a mock object. - -A few notes on naming conventions. If an identifier ends in _dn, it is a string -representation of a distinguished name. If it ends in _info, it is a 2-tuple -containing a DN and a dictionary of lists of attributes. ldap.search_s returns a -list of such structures. An identifier that ends in _attrs is the dictionary of -attributes from the _info structure. - -A connection is an LDAPObject that has been successfully bound with a DN and -password. The identifier 'user' always refers to a User model object; LDAP user -information will be user_dn or user_info. - -Additional classes can be found in the config module next to this one. -""" - -import ldap -import sys -import traceback -import pprint -import copy - -from django.contrib.auth.models import User, Group, Permission, SiteProfileNotAvailable -from django.core.cache import cache -from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist -import django.dispatch - -# Support Django 1.5's custom user models -try: - from django.contrib.auth import get_user_model - get_user_username = lambda u: u.get_username() -except ImportError: - get_user_model = lambda: User # noqa - get_user_username = lambda u: u.username - - -from django_auth_ldap.config import _LDAPConfig, LDAPSearch - - -logger = _LDAPConfig.get_logger() - - -# Signals for populating user objects. -populate_user = django.dispatch.Signal(providing_args=["user", "ldap_user"]) -populate_user_profile = django.dispatch.Signal(providing_args=["profile", "ldap_user"]) - - -class LDAPBackend(object): - """ - The main backend class. This implements the auth backend API, although it - actually delegates most of its work to _LDAPUser, which is defined next. - """ - supports_anonymous_user = False - supports_object_permissions = True - supports_inactive_user = False - - _settings = None - _ldap = None # The cached ldap module (or mock object) - - # This is prepended to our internal setting names to produce the names we - # expect in Django's settings file. Subclasses can change this in order to - # support multiple collections of settings. - settings_prefix = 'AUTH_LDAP_' - - def __getstate__(self): - """ - Exclude certain cached properties from pickling. - """ - state = filter( - lambda (k, v): k not in ['_settings', '_ldap'], - self.__dict__.iteritems() - ) - - return dict(state) - - def _get_settings(self): - if self._settings is None: - self._settings = LDAPSettings(self.settings_prefix) - - return self._settings - - def _set_settings(self, settings): - self._settings = settings - - settings = property(_get_settings, _set_settings) - - def _get_ldap(self): - if self._ldap is None: - from django.conf import settings - - options = getattr(settings, 'AUTH_LDAP_GLOBAL_OPTIONS', None) - - self._ldap = _LDAPConfig.get_ldap(options) - - return self._ldap - ldap = property(_get_ldap) - - def get_user_model(self): - """ - By default, this will return the model class configured by - AUTH_USER_MODEL. Subclasses may wish to override it and return a proxy - model. - """ - return get_user_model() - - # - # The Django auth backend API - # - - def authenticate(self, username, password): - if len(password) == 0 and not self.settings.PERMIT_EMPTY_PASSWORD: - logger.debug('Rejecting empty password for %s' % username) - return None - - ldap_user = _LDAPUser(self, username=username.strip()) - user = ldap_user.authenticate(password) - - return user - - def get_user(self, user_id): - user = None - - try: - user = self.get_user_model().objects.get(pk=user_id) - _LDAPUser(self, user=user) # This sets user.ldap_user - except ObjectDoesNotExist: - pass - - return user - - def has_perm(self, user, perm, obj=None): - return perm in self.get_all_permissions(user, obj) - - def has_module_perms(self, user, app_label): - for perm in self.get_all_permissions(user): - if perm[:perm.index('.')] == app_label: - return True - - return False - - def get_all_permissions(self, user, obj=None): - return self.get_group_permissions(user, obj) - - def get_group_permissions(self, user, obj=None): - if not hasattr(user, 'ldap_user') and self.settings.AUTHORIZE_ALL_USERS: - _LDAPUser(self, user=user) # This sets user.ldap_user - - if hasattr(user, 'ldap_user'): - return user.ldap_user.get_group_permissions() - else: - return set() - - # - # Bonus API: populate the Django user from LDAP without authenticating. - # - - def populate_user(self, username): - ldap_user = _LDAPUser(self, username=username) - user = ldap_user.populate_user() - - return user - - # - # Hooks for subclasses - # - - def get_or_create_user(self, username, ldap_user): - """ - This must return a (User, created) 2-tuple for the given LDAP user. - username is the Django-friendly username of the user. ldap_user.dn is - the user's DN and ldap_user.attrs contains all of their LDAP attributes. - """ - model = self.get_user_model() - username_field = getattr(model, 'USERNAME_FIELD', 'username') - - kwargs = { - username_field + '__iexact': username, - 'defaults': {username_field: username.lower()} - } - - return model.objects.get_or_create(**kwargs) - - def ldap_to_django_username(self, username): - return username - - def django_to_ldap_username(self, username): - return username - - -class _LDAPUser(object): - """ - Represents an LDAP user and ultimately fields all requests that the - backend receives. This class exists for two reasons. First, it's - convenient to have a separate object for each request so that we can use - object attributes without running into threading problems. Second, these - objects get attached to the User objects, which allows us to cache - expensive LDAP information, especially around groups and permissions. - - self.backend is a reference back to the LDAPBackend instance, which we need - to access the ldap module and any hooks that a subclass has overridden. - """ - class AuthenticationFailed(Exception): - pass - - # Defaults - _user = None - _user_dn = None - _user_attrs = None - _groups = None - _group_permissions = None - _connection = None - _connection_bound = False - - # - # Initialization - # - - def __init__(self, backend, username=None, user=None): - """ - A new LDAPUser must be initialized with either a username or an - authenticated User object. If a user is given, the username will be - ignored. - """ - self.backend = backend - self._username = username - - if user is not None: - self._set_authenticated_user(user) - - if username is None and user is None: - raise Exception("Internal error: _LDAPUser improperly initialized.") - - def __deepcopy__(self, memo): - obj = object.__new__(self.__class__) - obj.backend = self.backend - obj._user = copy.deepcopy(self._user, memo) - - # This is all just cached immutable data. There's no point copying it. - obj._username = self._username - obj._user_dn = self._user_dn - obj._user_attrs = self._user_attrs - obj._groups = self._groups - obj._group_permissions = self._group_permissions - - # The connection couldn't be copied even if we wanted to - obj._connection = self._connection - obj._connection_bound = self._connection_bound - - return obj - - def __getstate__(self): - """ - Most of our properties are cached from the LDAP server. We only want to - pickle a few crucial things. - """ - state = filter( - lambda (k, v): k in ['backend', '_username', '_user'], - self.__dict__.iteritems() - ) - - return dict(state) - - def _set_authenticated_user(self, user): - self._user = user - self._username = self.backend.django_to_ldap_username(get_user_username(user)) - - user.ldap_user = self - user.ldap_username = self._username - - def _get_ldap(self): - return self.backend.ldap - ldap = property(_get_ldap) - - def _get_settings(self): - return self.backend.settings - settings = property(_get_settings) - - # - # Entry points - # - - def authenticate(self, password): - """ - Authenticates against the LDAP directory and returns the corresponding - User object if successful. Returns None on failure. - """ - user = None - - try: - self._authenticate_user_dn(password) - self._check_requirements() - self._get_or_create_user() - - user = self._user - except self.AuthenticationFailed, e: - logger.debug(u"Authentication failed for %s" % self._username) - except ldap.LDAPError, e: - logger.warning(u"Caught LDAPError while authenticating %s: %s", - self._username, pprint.pformat(e)) - except Exception: - logger.exception(u"Caught Exception while authenticating %s", - self._username) - raise - - return user - - def get_group_permissions(self): - """ - If allowed by the configuration, this returns the set of permissions - defined by the user's LDAP group memberships. - """ - if self._group_permissions is None: - self._group_permissions = set() - - if self.settings.FIND_GROUP_PERMS: - try: - self._load_group_permissions() - except ldap.LDAPError, e: - logger.warning("Caught LDAPError loading group permissions: %s", - pprint.pformat(e)) - - return self._group_permissions - - def populate_user(self): - """ - Populates the Django user object using the default bind credentials. - """ - user = None - - try: - # self.attrs will only be non-None if we were able to load this user - # from the LDAP directory, so this filters out nonexistent users. - if self.attrs is not None: - self._get_or_create_user(force_populate=True) - - user = self._user - except ldap.LDAPError, e: - logger.warning(u"Caught LDAPError while authenticating %s: %s", - self._username, pprint.pformat(e)) - except Exception, e: - logger.error(u"Caught Exception while authenticating %s: %s", - self._username, pprint.pformat(e)) - logger.error(''.join(traceback.format_tb(sys.exc_info()[2]))) - raise - - return user - - # - # Public properties (callbacks). These are all lazy for performance reasons. - # - - def _get_user_dn(self): - if self._user_dn is None: - self._load_user_dn() - - return self._user_dn - dn = property(_get_user_dn) - - def _get_user_attrs(self): - if self._user_attrs is None: - self._load_user_attrs() - - return self._user_attrs - attrs = property(_get_user_attrs) - - def _get_group_dns(self): - return self._get_groups().get_group_dns() - group_dns = property(_get_group_dns) - - def _get_group_names(self): - return self._get_groups().get_group_names() - group_names = property(_get_group_names) - - def _get_bound_connection(self): - if not self._connection_bound: - self._bind() - - return self._get_connection() - connection = property(_get_bound_connection) - - # - # Authentication - # - - def _authenticate_user_dn(self, password): - """ - Binds to the LDAP server with the user's DN and password. Raises - AuthenticationFailed on failure. - """ - if self.dn is None: - raise self.AuthenticationFailed("Failed to map the username to a DN.") - - try: - sticky = self.settings.BIND_AS_AUTHENTICATING_USER - - self._bind_as(self.dn, password, sticky=sticky) - except ldap.INVALID_CREDENTIALS: - raise self.AuthenticationFailed("User DN/password rejected by LDAP server.") - - def _load_user_attrs(self): - if self.dn is not None: - search = LDAPSearch(self.dn, ldap.SCOPE_BASE) - results = search.execute(self.connection) - - if results is not None and len(results) > 0: - self._user_attrs = results[0][1] - - def _load_user_dn(self): - """ - Populates self._user_dn with the distinguished name of our user. This - will either construct the DN from a template in - AUTH_LDAP_USER_DN_TEMPLATE or connect to the server and search for it. - """ - if self._using_simple_bind_mode(): - self._construct_simple_user_dn() - else: - self._search_for_user_dn() - - def _using_simple_bind_mode(self): - return (self.settings.USER_DN_TEMPLATE is not None) - - def _construct_simple_user_dn(self): - template = self.settings.USER_DN_TEMPLATE - username = ldap.dn.escape_dn_chars(self._username) - - self._user_dn = template % {'user': username} - - def _search_for_user_dn(self): - """ - Searches the directory for a user matching AUTH_LDAP_USER_SEARCH. - Populates self._user_dn and self._user_attrs. - """ - search = self.settings.USER_SEARCH - if search is None: - raise ImproperlyConfigured('AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance.') - - results = search.execute(self.connection, {'user': self._username}) - if results is not None and len(results) == 1: - (self._user_dn, self._user_attrs) = results[0] - - def _check_requirements(self): - """ - Checks all authentication requirements beyond credentials. Raises - AuthenticationFailed on failure. - """ - self._check_required_group() - self._check_denied_group() - - def _check_required_group(self): - """ - Returns True if the group requirement (AUTH_LDAP_REQUIRE_GROUP) is - met. Always returns True if AUTH_LDAP_REQUIRE_GROUP is None. - """ - required_group_dn = self.settings.REQUIRE_GROUP - - if required_group_dn is not None: - is_member = self._get_groups().is_member_of(required_group_dn) - if not is_member: - raise self.AuthenticationFailed("User is not a member of AUTH_LDAP_REQUIRE_GROUP") - - return True - - def _check_denied_group(self): - """ - Returns True if the negative group requirement (AUTH_LDAP_DENY_GROUP) - is met. Always returns True if AUTH_LDAP_DENY_GROUP is None. - """ - denied_group_dn = self.settings.DENY_GROUP - - if denied_group_dn is not None: - is_member = self._get_groups().is_member_of(denied_group_dn) - if is_member: - raise self.AuthenticationFailed("User is a member of AUTH_LDAP_DENY_GROUP") - - return True - - # - # User management - # - - def _get_or_create_user(self, force_populate=False): - """ - Loads the User model object from the database or creates it if it - doesn't exist. Also populates the fields, subject to - AUTH_LDAP_ALWAYS_UPDATE_USER. - """ - save_user = False - - username = self.backend.ldap_to_django_username(self._username) - - self._user, created = self.backend.get_or_create_user(username, self) - self._user.ldap_user = self - self._user.ldap_username = self._username - - should_populate = force_populate or self.settings.ALWAYS_UPDATE_USER or created - - if created: - logger.debug("Created Django user %s", username) - self._user.set_unusable_password() - save_user = True - - if should_populate: - logger.debug("Populating Django user %s", username) - self._populate_user() - save_user = True - - if self.settings.MIRROR_GROUPS: - self._mirror_groups() - - # Give the client a chance to finish populating the user just before - # saving. - if should_populate: - signal_responses = populate_user.send(self.backend.__class__, user=self._user, ldap_user=self) - if len(signal_responses) > 0: - save_user = True - - if save_user: - self._user.save() - - # We populate the profile after the user model is saved to give the - # client a chance to create the profile. Custom user models in Django - # 1.5 probably won't have a get_profile method. - if should_populate and hasattr(self._user, 'get_profile'): - self._populate_and_save_user_profile() - - def _populate_user(self): - """ - Populates our User object with information from the LDAP directory. - """ - self._populate_user_from_attributes() - self._populate_user_from_group_memberships() - - def _populate_user_from_attributes(self): - for field, attr in self.settings.USER_ATTR_MAP.iteritems(): - try: - setattr(self._user, field, self.attrs[attr][0]) - except StandardError: - logger.warning("%s does not have a value for the attribute %s", self.dn, attr) - - def _populate_user_from_group_memberships(self): - for field, group_dns in self.settings.USER_FLAGS_BY_GROUP.iteritems(): - if isinstance(group_dns, basestring): - group_dns = [group_dns] - value = any(self._get_groups().is_member_of(dn) for dn in group_dns) - setattr(self._user, field, value) - - def _populate_and_save_user_profile(self): - """ - Populates a User profile object with fields from the LDAP directory. - """ - try: - profile = self._user.get_profile() - save_profile = False - - logger.debug("Populating Django user profile for %s", get_user_username(self._user)) - - save_profile = self._populate_profile_from_attributes(profile) or save_profile - save_profile = self._populate_profile_from_group_memberships(profile) or save_profile - - signal_responses = populate_user_profile.send(self.backend.__class__, profile=profile, ldap_user=self) - if len(signal_responses) > 0: - save_profile = True - - if save_profile: - profile.save() - except (SiteProfileNotAvailable, ObjectDoesNotExist): - logger.debug("Django user %s does not have a profile to populate", get_user_username(self._user)) - - def _populate_profile_from_attributes(self, profile): - """ - Populate the given profile object from AUTH_LDAP_PROFILE_ATTR_MAP. - Returns True if the profile was modified. - """ - save_profile = False - - for field, attr in self.settings.PROFILE_ATTR_MAP.iteritems(): - try: - # user_attrs is a hash of lists of attribute values - setattr(profile, field, self.attrs[attr][0]) - save_profile = True - except StandardError: - logger.warning("%s does not have a value for the attribute %s", self.dn, attr) - - return save_profile - - def _populate_profile_from_group_memberships(self, profile): - """ - Populate the given profile object from AUTH_LDAP_PROFILE_FLAGS_BY_GROUP. - Returns True if the profile was modified. - """ - save_profile = False - - for field, group_dns in self.settings.PROFILE_FLAGS_BY_GROUP.iteritems(): - if isinstance(group_dns, basestring): - group_dns = [group_dns] - value = any(self._get_groups().is_member_of(dn) for dn in group_dns) - setattr(profile, field, value) - save_profile = True - - return save_profile - - def _mirror_groups(self): - """ - Mirrors the user's LDAP groups in the Django database and updates the - user's membership. - """ - group_names = self._get_groups().get_group_names() - groups = [Group.objects.get_or_create(name=group_name)[0] for group_name - in group_names] - - self._user.groups = groups - - # - # Group information - # - - def _load_group_permissions(self): - """ - Populates self._group_permissions based on LDAP group membership and - Django group permissions. - """ - group_names = self._get_groups().get_group_names() - - perms = Permission.objects.filter(group__name__in=group_names) - perms = perms.values_list('content_type__app_label', 'codename') - perms = perms.order_by() - - self._group_permissions = set(["%s.%s" % (ct, name) for ct, name in perms]) - - def _get_groups(self): - """ - Returns an _LDAPUserGroups object, which can determine group - membership. - """ - if self._groups is None: - self._groups = _LDAPUserGroups(self) - - return self._groups - - # - # LDAP connection - # - - def _bind(self): - """ - Binds to the LDAP server with AUTH_LDAP_BIND_DN and - AUTH_LDAP_BIND_PASSWORD. - """ - self._bind_as(self.settings.BIND_DN, self.settings.BIND_PASSWORD, - sticky=True) - - def _bind_as(self, bind_dn, bind_password, sticky=False): - """ - Binds to the LDAP server with the given credentials. This does not trap - exceptions. - - If sticky is True, then we will consider the connection to be bound for - the life of this object. If False, then the caller only wishes to test - the credentials, after which the connection will be considered unbound. - """ - self._get_connection().simple_bind_s(bind_dn.encode('utf-8'), - bind_password.encode('utf-8')) - - self._connection_bound = sticky - - def _get_connection(self): - """ - Returns our cached LDAPObject, which may or may not be bound. - """ - if self._connection is None: - uri = self.settings.SERVER_URI - if callable(uri): - uri = uri() - - self._connection = self.backend.ldap.initialize(uri) - - for opt, value in self.settings.CONNECTION_OPTIONS.iteritems(): - self._connection.set_option(opt, value) - - if self.settings.START_TLS: - logger.debug("Initiating TLS") - self._connection.start_tls_s() - - return self._connection - - -class _LDAPUserGroups(object): - """ - Represents the set of groups that a user belongs to. - """ - def __init__(self, ldap_user): - self.settings = ldap_user.settings - self._ldap_user = ldap_user - self._group_type = None - self._group_search = None - self._group_infos = None - self._group_dns = None - self._group_names = None - - self._init_group_settings() - - def _init_group_settings(self): - """ - Loads the settings we need to deal with groups. Raises - ImproperlyConfigured if anything's not right. - """ - self._group_type = self.settings.GROUP_TYPE - if self._group_type is None: - raise ImproperlyConfigured("AUTH_LDAP_GROUP_TYPE must be an LDAPGroupType instance.") - - self._group_search = self.settings.GROUP_SEARCH - if self._group_search is None: - raise ImproperlyConfigured("AUTH_LDAP_GROUP_SEARCH must be an LDAPSearch instance.") - - def get_group_names(self): - """ - Returns the set of Django group names that this user belongs to by - virtue of LDAP group memberships. - """ - if self._group_names is None: - self._load_cached_attr("_group_names") - - if self._group_names is None: - group_infos = self._get_group_infos() - self._group_names = set( - self._group_type.group_name_from_info(group_info) - for group_info in group_infos - ) - self._cache_attr("_group_names") - - return self._group_names - - def is_member_of(self, group_dn): - """ - Returns true if our user is a member of the given group. - """ - is_member = None - - # Normalize the DN - group_dn = group_dn.lower() - - # If we have self._group_dns, we'll use it. Otherwise, we'll try to - # avoid the cost of loading it. - if self._group_dns is None: - is_member = self._group_type.is_member(self._ldap_user, group_dn) - - if is_member is None: - is_member = (group_dn in self.get_group_dns()) - - logger.debug("%s is%sa member of %s", self._ldap_user.dn, - is_member and " " or " not ", group_dn) - - return is_member - - def get_group_dns(self): - """ - Returns a (cached) set of the distinguished names in self._group_infos. - """ - if self._group_dns is None: - group_infos = self._get_group_infos() - self._group_dns = set(group_info[0] for group_info in group_infos) - - return self._group_dns - - def _get_group_infos(self): - """ - Returns a (cached) list of group_info structures for the groups that our - user is a member of. - """ - if self._group_infos is None: - self._group_infos = self._group_type.user_groups(self._ldap_user, - self._group_search) - - return self._group_infos - - def _load_cached_attr(self, attr_name): - if self.settings.CACHE_GROUPS: - key = self._cache_key(attr_name) - value = cache.get(key) - setattr(self, attr_name, value) - - def _cache_attr(self, attr_name): - if self.settings.CACHE_GROUPS: - key = self._cache_key(attr_name) - value = getattr(self, attr_name, None) - cache.set(key, value, self.settings.GROUP_CACHE_TIMEOUT) - - def _cache_key(self, attr_name): - """ - Memcache keys can't have spaces in them, so we'll remove them from the - DN for maximum compatibility. - """ - dn = self._ldap_user.dn.replace(' ', '%20') - key = u'auth_ldap.%s.%s.%s' % (self.__class__.__name__, attr_name, dn) - - return key - - -class LDAPSettings(object): - """ - This is a simple class to take the place of the global settings object. An - instance will contain all of our settings as attributes, with default values - if they are not specified by the configuration. - """ - defaults = { - 'ALWAYS_UPDATE_USER': True, - 'AUTHORIZE_ALL_USERS': False, - 'BIND_AS_AUTHENTICATING_USER': False, - 'BIND_DN': '', - 'BIND_PASSWORD': '', - 'CACHE_GROUPS': False, - 'CONNECTION_OPTIONS': {}, - 'DENY_GROUP': None, - 'FIND_GROUP_PERMS': False, - 'GROUP_CACHE_TIMEOUT': None, - 'GROUP_SEARCH': None, - 'GROUP_TYPE': None, - 'MIRROR_GROUPS': False, - 'PERMIT_EMPTY_PASSWORD': False, - 'PROFILE_ATTR_MAP': {}, - 'PROFILE_FLAGS_BY_GROUP': {}, - 'REQUIRE_GROUP': None, - 'SERVER_URI': 'ldap://localhost', - 'START_TLS': False, - 'USER_ATTR_MAP': {}, - 'USER_DN_TEMPLATE': None, - 'USER_FLAGS_BY_GROUP': {}, - 'USER_SEARCH': None, - } - - def __init__(self, prefix='AUTH_LDAP_'): - """ - Loads our settings from django.conf.settings, applying defaults for any - that are omitted. - """ - from django.conf import settings - - for name, default in self.defaults.iteritems(): - value = getattr(settings, prefix + name, default) - setattr(self, name, value) diff --git a/awx/lib/site-packages/django_auth_ldap/config.py b/awx/lib/site-packages/django_auth_ldap/config.py deleted file mode 100644 index 4b792a7212..0000000000 --- a/awx/lib/site-packages/django_auth_ldap/config.py +++ /dev/null @@ -1,554 +0,0 @@ -# Copyright (c) 2009, Peter Sagerson -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# - Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -""" -This module contains classes that will be needed for configuration of LDAP -authentication. Unlike backend.py, this is safe to import into settings.py. -Please see the docstring on the backend module for more information, including -notes on naming conventions. -""" - -import ldap -import logging -import pprint - - -class _LDAPConfig(object): - """ - A private class that loads and caches some global objects. - """ - ldap = None - logger = None - - _ldap_configured = False - - def get_ldap(cls, global_options=None): - """ - Returns the ldap module. The unit test harness will assign a mock object - to _LDAPConfig.ldap. It is imperative that the ldap module not be - imported anywhere else so that the unit tests will pass in the absence - of python-ldap. - """ - if cls.ldap is None: - import ldap.filter - - # Support for python-ldap < 2.0.6 - try: - import ldap.dn - except ImportError: - from django_auth_ldap import dn - ldap.dn = dn - - cls.ldap = ldap - - # Apply global LDAP options once - if (not cls._ldap_configured) and (global_options is not None): - for opt, value in global_options.iteritems(): - cls.ldap.set_option(opt, value) - - cls._ldap_configured = True - - return cls.ldap - get_ldap = classmethod(get_ldap) - - def get_logger(cls): - """ - Initializes and returns our logger instance. - """ - if cls.logger is None: - class NullHandler(logging.Handler): - def emit(self, record): - pass - - cls.logger = logging.getLogger('django_auth_ldap') - cls.logger.addHandler(NullHandler()) - - return cls.logger - get_logger = classmethod(get_logger) - - -# Our global logger -logger = _LDAPConfig.get_logger() - - -class LDAPSearch(object): - """ - Public class that holds a set of LDAP search parameters. Objects of this - class should be considered immutable. Only the initialization method is - documented for configuration purposes. Internal clients may use the other - methods to refine and execute the search. - """ - def __init__(self, base_dn, scope, filterstr=u'(objectClass=*)'): - """ - These parameters are the same as the first three parameters to - ldap.search_s. - """ - self.base_dn = base_dn - self.scope = scope - self.filterstr = filterstr - self.ldap = _LDAPConfig.get_ldap() - - def search_with_additional_terms(self, term_dict, escape=True): - """ - Returns a new search object with additional search terms and-ed to the - filter string. term_dict maps attribute names to assertion values. If - you don't want the values escaped, pass escape=False. - """ - term_strings = [self.filterstr] - - for name, value in term_dict.iteritems(): - if escape: - value = self.ldap.filter.escape_filter_chars(value) - term_strings.append(u'(%s=%s)' % (name, value)) - - filterstr = u'(&%s)' % ''.join(term_strings) - - return self.__class__(self.base_dn, self.scope, filterstr) - - def search_with_additional_term_string(self, filterstr): - """ - Returns a new search object with filterstr and-ed to the original filter - string. The caller is responsible for passing in a properly escaped - string. - """ - filterstr = u'(&%s%s)' % (self.filterstr, filterstr) - - return self.__class__(self.base_dn, self.scope, filterstr) - - def execute(self, connection, filterargs=()): - """ - Executes the search on the given connection (an LDAPObject). filterargs - is an object that will be used for expansion of the filter string. - - The python-ldap library returns utf8-encoded strings. For the sake of - sanity, this method will decode all result strings and return them as - Unicode. - """ - try: - filterstr = self.filterstr % filterargs - results = connection.search_s(self.base_dn.encode('utf-8'), - self.scope, - filterstr.encode('utf-8')) - except ldap.LDAPError, e: - results = [] - logger.error(u"search_s('%s', %d, '%s') raised %s" % - (self.base_dn, self.scope, filterstr, pprint.pformat(e))) - - return self._process_results(results) - - def _begin(self, connection, filterargs=()): - """ - Begins an asynchronous search and returns the message id to retrieve - the results. - """ - try: - filterstr = self.filterstr % filterargs - msgid = connection.search(self.base_dn.encode('utf-8'), - self.scope, filterstr.encode('utf-8')) - except ldap.LDAPError, e: - msgid = None - logger.error(u"search('%s', %d, '%s') raised %s" % - (self.base_dn, self.scope, filterstr, pprint.pformat(e))) - - return msgid - - def _results(self, connection, msgid): - """ - Returns the result of a previous asynchronous query. - """ - try: - kind, results = connection.result(msgid) - if kind != ldap.RES_SEARCH_RESULT: - results = [] - except ldap.LDAPError, e: - results = [] - logger.error(u"result(%d) raised %s" % (msgid, pprint.pformat(e))) - - return self._process_results(results) - - def _process_results(self, results): - """ - Returns a sanitized copy of raw LDAP results. This scrubs out - references, decodes utf8, normalizes DNs, etc. - """ - results = filter(lambda r: r[0] is not None, results) - results = _DeepStringCoder('utf-8').decode(results) - - # The normal form of a DN is lower case. - results = map(lambda r: (r[0].lower(), r[1]), results) - - result_dns = [result[0] for result in results] - logger.debug(u"search_s('%s', %d, '%s') returned %d objects: %s" % - (self.base_dn, self.scope, self.filterstr, len(result_dns), - "; ".join(result_dns))) - - return results - - -class LDAPSearchUnion(object): - """ - A compound search object that returns the union of the results. Instantiate - it with one or more LDAPSearch objects. - """ - def __init__(self, *args): - self.searches = args - self.ldap = _LDAPConfig.get_ldap() - - def search_with_additional_terms(self, term_dict, escape=True): - searches = [s.search_with_additional_terms(term_dict, escape) - for s in self.searches] - - return self.__class__(*searches) - - def search_with_additional_term_string(self, filterstr): - searches = [s.search_with_additional_term_string(filterstr) - for s in self.searches] - - return self.__class__(*searches) - - def execute(self, connection, filterargs=()): - msgids = [search._begin(connection, filterargs) for search in self.searches] - results = {} - - for search, msgid in zip(self.searches, msgids): - result = search._results(connection, msgid) - results.update(dict(result)) - - return results.items() - - -class _DeepStringCoder(object): - """ - Encodes and decodes strings in a nested structure of lists, tuples, and - dicts. This is helpful when interacting with the Unicode-unaware - python-ldap. - """ - def __init__(self, encoding): - self.encoding = encoding - self.ldap = _LDAPConfig.get_ldap() - - def decode(self, value): - try: - if isinstance(value, str): - value = value.decode(self.encoding) - elif isinstance(value, list): - value = self._decode_list(value) - elif isinstance(value, tuple): - value = tuple(self._decode_list(value)) - elif isinstance(value, dict): - value = self._decode_dict(value) - except UnicodeDecodeError: - pass - - return value - - def _decode_list(self, value): - return [self.decode(v) for v in value] - - def _decode_dict(self, value): - # Attribute dictionaries should be case-insensitive. python-ldap - # defines this, although for some reason, it doesn't appear to use it - # for search results. - decoded = self.ldap.cidict.cidict() - - for k, v in value.iteritems(): - decoded[self.decode(k)] = self.decode(v) - - return decoded - - -class LDAPGroupType(object): - """ - This is an abstract base class for classes that determine LDAP group - membership. A group can mean many different things in LDAP, so we will need - a concrete subclass for each grouping mechanism. Clients may subclass this - if they have a group mechanism that is not handled by a built-in - implementation. - - name_attr is the name of the LDAP attribute from which we will take the - Django group name. - - Subclasses in this file must use self.ldap to access the python-ldap module. - This will be a mock object during unit tests. - """ - def __init__(self, name_attr="cn"): - self.name_attr = name_attr - self.ldap = _LDAPConfig.get_ldap() - - def user_groups(self, ldap_user, group_search): - """ - Returns a list of group_info structures, each one a group to which - ldap_user belongs. group_search is an LDAPSearch object that returns all - of the groups that the user might belong to. Typical implementations - will apply additional filters to group_search and return the results of - the search. ldap_user represents the user and has the following three - properties: - - dn: the distinguished name - attrs: a dictionary of LDAP attributes (with lists of values) - connection: an LDAPObject that has been bound with credentials - - This is the primitive method in the API and must be implemented. - """ - return [] - - def is_member(self, ldap_user, group_dn): - """ - This method is an optimization for determining group membership without - loading all of the user's groups. Subclasses that are able to do this - may return True or False. ldap_user is as above. group_dn is the - distinguished name of the group in question. - - The base implementation returns None, which means we don't have enough - information. The caller will have to call user_groups() instead and look - for group_dn in the results. - """ - return None - - def group_name_from_info(self, group_info): - """ - Given the (DN, attrs) 2-tuple of an LDAP group, this returns the name of - the Django group. This may return None to indicate that a particular - LDAP group has no corresponding Django group. - - The base implementation returns the value of the cn attribute, or - whichever attribute was given to __init__ in the name_attr - parameter. - """ - try: - name = group_info[1][self.name_attr][0] - except (KeyError, IndexError): - name = None - - return name - - -class PosixGroupType(LDAPGroupType): - """ - An LDAPGroupType subclass that handles groups of class posixGroup. - """ - def user_groups(self, ldap_user, group_search): - """ - Searches for any group that is either the user's primary or contains the - user as a member. - """ - groups = [] - - try: - user_uid = ldap_user.attrs['uid'][0] - - if 'gidNumber' in ldap_user.attrs: - user_gid = ldap_user.attrs['gidNumber'][0] - filterstr = u'(|(gidNumber=%s)(memberUid=%s))' % ( - self.ldap.filter.escape_filter_chars(user_gid), - self.ldap.filter.escape_filter_chars(user_uid) - ) - else: - filterstr = u'(memberUid=%s)' % ( - self.ldap.filter.escape_filter_chars(user_uid), - ) - - search = group_search.search_with_additional_term_string(filterstr) - groups = search.execute(ldap_user.connection) - except (KeyError, IndexError): - pass - - return groups - - def is_member(self, ldap_user, group_dn): - """ - Returns True if the group is the user's primary group or if the user is - listed in the group's memberUid attribute. - """ - try: - user_uid = ldap_user.attrs['uid'][0] - - try: - is_member = ldap_user.connection.compare_s(group_dn.encode('utf-8'), 'memberUid', user_uid.encode('utf-8')) - except (ldap.UNDEFINED_TYPE, ldap.NO_SUCH_ATTRIBUTE): - is_member = False - - if not is_member: - try: - user_gid = ldap_user.attrs['gidNumber'][0] - is_member = ldap_user.connection.compare_s(group_dn.encode('utf-8'), 'gidNumber', user_gid.encode('utf-8')) - except (ldap.UNDEFINED_TYPE, ldap.NO_SUCH_ATTRIBUTE): - is_member = False - except (KeyError, IndexError): - is_member = False - - return is_member - - -class MemberDNGroupType(LDAPGroupType): - """ - A group type that stores lists of members as distinguished names. - """ - def __init__(self, member_attr, name_attr='cn'): - """ - member_attr is the attribute on the group object that holds the list of - member DNs. - """ - self.member_attr = member_attr - - super(MemberDNGroupType, self).__init__(name_attr) - - def user_groups(self, ldap_user, group_search): - search = group_search.search_with_additional_terms({self.member_attr: ldap_user.dn}) - groups = search.execute(ldap_user.connection) - - return groups - - def is_member(self, ldap_user, group_dn): - try: - result = ldap_user.connection.compare_s( - group_dn.encode('utf-8'), - self.member_attr.encode('utf-8'), - ldap_user.dn.encode('utf-8') - ) - except (ldap.UNDEFINED_TYPE, ldap.NO_SUCH_ATTRIBUTE): - result = 0 - - return result - - -class NestedMemberDNGroupType(LDAPGroupType): - """ - A group type that stores lists of members as distinguished names and - supports nested groups. There is no shortcut for is_member in this case, so - it's left unimplemented. - """ - def __init__(self, member_attr, name_attr='cn'): - """ - member_attr is the attribute on the group object that holds the list of - member DNs. - """ - self.member_attr = member_attr - - super(NestedMemberDNGroupType, self).__init__(name_attr) - - def user_groups(self, ldap_user, group_search): - """ - This searches for all of a user's groups from the bottom up. In other - words, it returns the groups that the user belongs to, the groups that - those groups belong to, etc. Circular references will be detected and - pruned. - """ - group_info_map = {} # Maps group_dn to group_info of groups we've found - member_dn_set = set([ldap_user.dn]) # Member DNs to search with next - handled_dn_set = set() # Member DNs that we've already searched with - - while len(member_dn_set) > 0: - group_infos = self.find_groups_with_any_member(member_dn_set, - group_search, - ldap_user.connection) - new_group_info_map = dict([(info[0], info) for info in group_infos]) - group_info_map.update(new_group_info_map) - handled_dn_set.update(member_dn_set) - - # Get ready for the next iteration. To avoid cycles, we make sure - # never to search with the same member DN twice. - member_dn_set = set(new_group_info_map.keys()) - handled_dn_set - - return group_info_map.values() - - def find_groups_with_any_member(self, member_dn_set, group_search, connection): - terms = [ - u"(%s=%s)" % (self.member_attr, self.ldap.filter.escape_filter_chars(dn)) - for dn in member_dn_set - ] - - filterstr = u"(|%s)" % "".join(terms) - search = group_search.search_with_additional_term_string(filterstr) - - return search.execute(connection) - - -class GroupOfNamesType(MemberDNGroupType): - """ - An LDAPGroupType subclass that handles groups of class groupOfNames. - """ - def __init__(self, name_attr='cn'): - super(GroupOfNamesType, self).__init__('member', name_attr) - - -class NestedGroupOfNamesType(NestedMemberDNGroupType): - """ - An LDAPGroupType subclass that handles groups of class groupOfNames with - nested group references. - """ - def __init__(self, name_attr='cn'): - super(NestedGroupOfNamesType, self).__init__('member', name_attr) - - -class GroupOfUniqueNamesType(MemberDNGroupType): - """ - An LDAPGroupType subclass that handles groups of class groupOfUniqueNames. - """ - def __init__(self, name_attr='cn'): - super(GroupOfUniqueNamesType, self).__init__('uniqueMember', name_attr) - - -class NestedGroupOfUniqueNamesType(NestedMemberDNGroupType): - """ - An LDAPGroupType subclass that handles groups of class groupOfUniqueNames - with nested group references. - """ - def __init__(self, name_attr='cn'): - super(NestedGroupOfUniqueNamesType, self).__init__('uniqueMember', name_attr) - - -class ActiveDirectoryGroupType(MemberDNGroupType): - """ - An LDAPGroupType subclass that handles Active Directory groups. - """ - def __init__(self, name_attr='cn'): - super(ActiveDirectoryGroupType, self).__init__('member', name_attr) - - -class NestedActiveDirectoryGroupType(NestedMemberDNGroupType): - """ - An LDAPGroupType subclass that handles Active Directory groups with nested - group references. - """ - def __init__(self, name_attr='cn'): - super(NestedActiveDirectoryGroupType, self).__init__('member', name_attr) - - -class OrganizationalRoleGroupType(MemberDNGroupType): - """ - An LDAPGroupType subclass that handles groups of class organizationalRole. - """ - def __init__(self, name_attr='cn'): - super(OrganizationalRoleGroupType, self).__init__('roleOccupant', name_attr) - - -class NestedOrganizationalRoleGroupType(NestedMemberDNGroupType): - """ - An LDAPGroupType subclass that handles groups of class OrganizationalRoleGroupType - with nested group references. - """ - def __init__(self, name_attr='cn'): - super(NestedOrganizationalRoleGroupType, self).__init__('roleOccupant', name_attr) diff --git a/awx/lib/site-packages/django_auth_ldap/dn.py b/awx/lib/site-packages/django_auth_ldap/dn.py deleted file mode 100644 index e234303f5f..0000000000 --- a/awx/lib/site-packages/django_auth_ldap/dn.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2009, Peter Sagerson -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# - Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -""" -This is an ldap.dn replacement for old versions of python-ldap. It contains -(often naive) implementations of the methods we care about. -""" - - -def escape_dn_chars(dn): - "Old versions of python-ldap won't get DN escaping. Use with care." - return dn diff --git a/awx/lib/site-packages/django_auth_ldap/models.py b/awx/lib/site-packages/django_auth_ldap/models.py deleted file mode 100644 index b48d7a38ca..0000000000 --- a/awx/lib/site-packages/django_auth_ldap/models.py +++ /dev/null @@ -1,31 +0,0 @@ -from django.db import models - - -# Support for testing Django 1.5's custom user models. -try: - from django.contrib.auth.models import AbstractBaseUser -except ImportError: - from django.contrib.auth.models import User - - TestUser = User -else: - class TestUser(AbstractBaseUser): - identifier = models.CharField(max_length=40, unique=True, db_index=True) - - USERNAME_FIELD = 'identifier' - - def get_full_name(self): - return self.identifier - - def get_short_name(self): - return self.identifier - - -class TestProfile(models.Model): - """ - A user profile model for use by unit tests. This has nothing to do with the - authentication backend itself. - """ - user = models.OneToOneField('auth.User') - is_special = models.BooleanField(default=False) - populated = models.BooleanField(default=False) diff --git a/awx/lib/site-packages/django_auth_ldap/tests.py b/awx/lib/site-packages/django_auth_ldap/tests.py deleted file mode 100644 index b83abe4612..0000000000 --- a/awx/lib/site-packages/django_auth_ldap/tests.py +++ /dev/null @@ -1,1132 +0,0 @@ -# coding: utf-8 - -# Copyright (c) 2009, Peter Sagerson -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# - Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -from copy import deepcopy -import logging -import pickle - -import ldap -try: - import mockldap -except ImportError: - mockldap = None - -from django.conf import settings -import django.db.models.signals -from django.contrib.auth.models import User, Permission, Group -from django.test import TestCase -from django.utils import unittest -try: - from django.test.utils import override_settings -except ImportError: - override_settings = lambda *args, **kwargs: (lambda v: v) - -from django_auth_ldap.models import TestUser, TestProfile -from django_auth_ldap import backend -from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion -from django_auth_ldap.config import PosixGroupType, MemberDNGroupType, NestedMemberDNGroupType -from django_auth_ldap.config import GroupOfNamesType - - -class TestSettings(backend.LDAPSettings): - """ - A replacement for backend.LDAPSettings that does not load settings - from django.conf. - """ - def __init__(self, **kwargs): - for name, default in self.defaults.iteritems(): - value = kwargs.get(name, default) - setattr(self, name, value) - - -class LDAPTest(TestCase): - top = ("o=test", {"o": "test"}) - people = ("ou=people,o=test", {"ou": "people"}) - groups = ("ou=groups,o=test", {"ou": "groups"}) - moregroups = ("ou=moregroups,o=test", {"ou": "moregroups"}) - - alice = ("uid=alice,ou=people,o=test", { - "uid": ["alice"], - "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"], - "userPassword": ["password"], - "uidNumber": ["1000"], - "gidNumber": ["1000"], - "givenName": ["Alice"], - "sn": ["Adams"] - }) - bob = ("uid=bob,ou=people,o=test", { - "uid": ["bob"], - "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"], - "userPassword": ["password"], - "uidNumber": ["1001"], - "gidNumber": ["50"], - "givenName": ["Robert"], - "sn": ["Barker"] - }) - dressler = (u"uid=dreßler,ou=people,o=test".encode('utf-8'), { - "uid": [u"dreßler".encode('utf-8')], - "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"], - "userPassword": ["password"], - "uidNumber": ["1002"], - "gidNumber": ["50"], - "givenName": ["Wolfgang"], - "sn": [u"Dreßler".encode('utf-8')] - }) - nobody = ("uid=nobody,ou=people,o=test", { - "uid": ["nobody"], - "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"], - "userPassword": ["password"], - "binaryAttr": ["\xb2"] # Invalid UTF-8 - }) - - # posixGroup objects - active_px = ("cn=active_px,ou=groups,o=test", { - "cn": ["active_px"], - "objectClass": ["posixGroup"], - "gidNumber": ["1000"], - "memberUid": [], - }) - staff_px = ("cn=staff_px,ou=groups,o=test", { - "cn": ["staff_px"], - "objectClass": ["posixGroup"], - "gidNumber": ["1001"], - "memberUid": ["alice"], - }) - superuser_px = ("cn=superuser_px,ou=groups,o=test", { - "cn": ["superuser_px"], - "objectClass": ["posixGroup"], - "gidNumber": ["1002"], - "memberUid": ["alice"], - }) - - # groupOfNames groups - empty_gon = ("cn=empty_gon,ou=groups,o=test", { - "cn": ["empty_gon"], - "objectClass": ["groupOfNames"], - "member": [] - }) - active_gon = ("cn=active_gon,ou=groups,o=test", { - "cn": ["active_gon"], - "objectClass": ["groupOfNames"], - "member": ["uid=alice,ou=people,o=test"] - }) - staff_gon = ("cn=staff_gon,ou=groups,o=test", { - "cn": ["staff_gon"], - "objectClass": ["groupOfNames"], - "member": ["uid=alice,ou=people,o=test"] - }) - superuser_gon = ("cn=superuser_gon,ou=groups,o=test", { - "cn": ["superuser_gon"], - "objectClass": ["groupOfNames"], - "member": ["uid=alice,ou=people,o=test"] - }) - other_gon = ("cn=other_gon,ou=moregroups,o=test", { - "cn": ["other_gon"], - "objectClass": ["groupOfNames"], - "member": ["uid=bob,ou=people,o=test"] - }) - - # Nested groups with a circular reference - parent_gon = ("cn=parent_gon,ou=groups,o=test", { - "cn": ["parent_gon"], - "objectClass": ["groupOfNames"], - "member": ["cn=nested_gon,ou=groups,o=test"] - }) - nested_gon = ("CN=nested_gon,ou=groups,o=test", { - "cn": ["nested_gon"], - "objectClass": ["groupOfNames"], - "member": [ - "uid=alice,ou=people,o=test", - "cn=circular_gon,ou=groups,o=test" - ] - }) - circular_gon = ("cn=circular_gon,ou=groups,o=test", { - "cn": ["circular_gon"], - "objectClass": ["groupOfNames"], - "member": ["cn=parent_gon,ou=groups,o=test"] - }) - - directory = dict([top, people, groups, moregroups, alice, bob, dressler, - nobody, active_px, staff_px, superuser_px, empty_gon, - active_gon, staff_gon, superuser_gon, other_gon, - parent_gon, nested_gon, circular_gon]) - - @classmethod - def configure_logger(cls): - logger = logging.getLogger('django_auth_ldap') - formatter = logging.Formatter("LDAP auth - %(levelname)s - %(message)s") - handler = logging.StreamHandler() - - handler.setLevel(logging.DEBUG) - handler.setFormatter(formatter) - logger.addHandler(handler) - - logger.setLevel(logging.CRITICAL) - - @classmethod - def setUpClass(cls): - cls.configure_logger() - cls.mockldap = mockldap.MockLdap(cls.directory) - - @classmethod - def tearDownClass(cls): - del cls.mockldap - - def setUp(self): - self.mockldap.start() - self.ldapobj = self.mockldap['ldap://localhost'] - - self.backend = backend.LDAPBackend() - self.backend.ldap # Force global configuration - - def tearDown(self): - self.mockldap.stop() - del self.ldapobj - - def test_options(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - CONNECTION_OPTIONS={'opt1': 'value1'} - ) - self.backend.authenticate(username='alice', password='password') - - self.assertEqual(self.ldapobj.get_option('opt1'), 'value1') - - def test_callable_server_uri(self): - self._init_settings( - SERVER_URI=lambda: 'ldap://ldap.example.com', - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - - self.backend.authenticate(username='alice', password='password') - - ldapobj = self.mockldap['ldap://ldap.example.com'] - self.assertEqual( - ldapobj.methods_called(with_args=True), - [('initialize', ('ldap://ldap.example.com',), {}), - ('simple_bind_s', ('uid=alice,ou=people,o=test', 'password'), {})] - ) - - def test_simple_bind(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - user_count = User.objects.count() - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(not user.has_usable_password()) - self.assertEqual(user.username, 'alice') - self.assertEqual(User.objects.count(), user_count + 1) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s'] - ) - - def test_new_user_lowercase(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - user_count = User.objects.count() - - user = self.backend.authenticate(username='Alice', password='password') - - self.assertTrue(not user.has_usable_password()) - self.assertEqual(user.username, 'alice') - self.assertEqual(User.objects.count(), user_count + 1) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s'] - ) - - def test_deepcopy(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - - user = self.backend.authenticate(username='Alice', password='password') - user = deepcopy(user) - - @override_settings(AUTH_USER_MODEL='django_auth_ldap.TestUser') - def test_auth_custom_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - ) - - user = self.backend.authenticate(username='Alice', password='password') - - self.assertTrue(isinstance(user, TestUser)) - - @override_settings(AUTH_USER_MODEL='django_auth_ldap.TestUser') - def test_get_custom_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - ) - - user = self.backend.authenticate(username='Alice', password='password') - user = self.backend.get_user(user.id) - - self.assertTrue(isinstance(user, TestUser)) - - def test_new_user_whitespace(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - user_count = User.objects.count() - - user = self.backend.authenticate(username=' alice', password='password') - user = self.backend.authenticate(username='alice ', password='password') - - self.assertTrue(not user.has_usable_password()) - self.assertEqual(user.username, 'alice') - self.assertEqual(User.objects.count(), user_count + 1) - - def test_simple_bind_bad_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - user_count = User.objects.count() - - user = self.backend.authenticate(username='evil_alice', password='password') - - self.assertTrue(user is None) - self.assertEqual(User.objects.count(), user_count) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s'] - ) - - def test_simple_bind_bad_password(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - user_count = User.objects.count() - - user = self.backend.authenticate(username='alice', password='bogus') - - self.assertTrue(user is None) - self.assertEqual(User.objects.count(), user_count) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s'] - ) - - def test_existing_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - User.objects.create(username='alice') - user_count = User.objects.count() - - user = self.backend.authenticate(username='alice', password='password') - - # Make sure we only created one user - self.assertTrue(user is not None) - self.assertEqual(User.objects.count(), user_count) - - def test_existing_user_insensitive(self): - self._init_settings( - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - # mockldap doesn't handle case-insensitive matching properly. - self.ldapobj.search_s.seed('ou=people,o=test', ldap.SCOPE_SUBTREE, - '(uid=Alice)')([self.alice]) - User.objects.create(username='alice') - - user = self.backend.authenticate(username='Alice', password='password') - - self.assertTrue(user is not None) - self.assertEqual(user.username, 'alice') - self.assertEqual(User.objects.count(), 1) - - def test_convert_username(self): - class MyBackend(backend.LDAPBackend): - def ldap_to_django_username(self, username): - return 'ldap_%s' % username - - def django_to_ldap_username(self, username): - return username[5:] - - self.backend = MyBackend() - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - user_count = User.objects.count() - - user1 = self.backend.authenticate(username='alice', password='password') - user2 = self.backend.get_user(user1.pk) - - self.assertEqual(User.objects.count(), user_count + 1) - self.assertEqual(user1.username, 'ldap_alice') - self.assertEqual(user1.ldap_user._username, 'alice') - self.assertEqual(user1.ldap_username, 'alice') - self.assertEqual(user2.username, 'ldap_alice') - self.assertEqual(user2.ldap_user._username, 'alice') - self.assertEqual(user2.ldap_username, 'alice') - - def test_search_bind(self): - self._init_settings( - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - user_count = User.objects.count() - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(user is not None) - self.assertEqual(User.objects.count(), user_count + 1) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s', 'simple_bind_s'] - ) - - def test_search_bind_no_user(self): - self._init_settings( - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(cn=%(user)s)' - ) - ) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(user is None) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s'] - ) - - def test_search_bind_multiple_users(self): - self._init_settings( - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=*)' - ) - ) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(user is None) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s'] - ) - - def test_search_bind_bad_password(self): - self._init_settings( - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - - user = self.backend.authenticate(username='alice', password='bogus') - - self.assertTrue(user is None) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s', 'simple_bind_s'] - ) - - def test_search_bind_with_credentials(self): - self._init_settings( - BIND_DN='uid=bob,ou=people,o=test', - BIND_PASSWORD='password', - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(user is not None) - self.assertTrue(user.ldap_user is not None) - self.assertEqual(user.ldap_user.dn, self.alice[0]) - self.assertEqual(user.ldap_user.attrs, ldap.cidict.cidict(self.alice[1])) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s', 'simple_bind_s'] - ) - - def test_search_bind_with_bad_credentials(self): - self._init_settings( - BIND_DN='uid=bob,ou=people,o=test', - BIND_PASSWORD='bogus', - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(user is None) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s'] - ) - - def test_unicode_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn'} - ) - - user = self.backend.authenticate(username=u'dreßler', password='password') - self.assertTrue(user is not None) - self.assertEqual(user.username, u'dreßler') - self.assertEqual(user.last_name, u'Dreßler') - - def test_cidict(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - ) - - user = self.backend.authenticate(username="alice", password="password") - self.assertTrue(isinstance(user.ldap_user.attrs, ldap.cidict.cidict)) - - def test_populate_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn'} - ) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertEqual(user.username, 'alice') - self.assertEqual(user.first_name, 'Alice') - self.assertEqual(user.last_name, 'Adams') - - # init, bind as user, bind anonymous, lookup user attrs - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'simple_bind_s', 'search_s'] - ) - - def test_bind_as_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn'}, - BIND_AS_AUTHENTICATING_USER=True, - ) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertEqual(user.username, 'alice') - self.assertEqual(user.first_name, 'Alice') - self.assertEqual(user.last_name, 'Adams') - - # init, bind as user, lookup user attrs - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s'] - ) - - def test_signal_populate_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - - def handle_populate_user(sender, **kwargs): - self.assertTrue('user' in kwargs and 'ldap_user' in kwargs) - kwargs['user'].populate_user_handled = True - backend.populate_user.connect(handle_populate_user) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(user.populate_user_handled) - - def test_signal_populate_user_profile(self): - settings.AUTH_PROFILE_MODULE = 'django_auth_ldap.TestProfile' - - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test' - ) - - def handle_user_saved(sender, **kwargs): - if kwargs['created']: - TestProfile.objects.create(user=kwargs['instance']) - - def handle_populate_user_profile(sender, **kwargs): - self.assertTrue('profile' in kwargs and 'ldap_user' in kwargs) - kwargs['profile'].populated = True - - django.db.models.signals.post_save.connect(handle_user_saved, sender=User) - backend.populate_user_profile.connect(handle_populate_user_profile) - - user = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(user.get_profile().populated) - - def test_no_update_existing(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn'}, - ALWAYS_UPDATE_USER=False - ) - User.objects.create(username='alice', first_name='Alicia', last_name='Astro') - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertEqual(alice.first_name, 'Alicia') - self.assertEqual(alice.last_name, 'Astro') - self.assertEqual(bob.first_name, 'Robert') - self.assertEqual(bob.last_name, 'Barker') - - def test_require_group(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=groupOfNames)'), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - REQUIRE_GROUP="cn=active_gon,ou=groups,o=test" - ) - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice is not None) - self.assertTrue(bob is None) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'simple_bind_s', 'compare_s', - 'initialize', 'simple_bind_s', 'simple_bind_s', 'compare_s'] - ) - - def test_group_union(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearchUnion( - LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=groupOfNames)'), - LDAPSearch('ou=moregroups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=groupOfNames)') - ), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - REQUIRE_GROUP="cn=other_gon,ou=moregroups,o=test" - ) - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice is None) - self.assertTrue(bob is not None) - self.assertEqual(bob.ldap_user.group_names, set(['other_gon'])) - - def test_nested_group_union(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearchUnion( - LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=groupOfNames)'), - LDAPSearch('ou=moregroups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=groupOfNames)') - ), - GROUP_TYPE=NestedMemberDNGroupType(member_attr='member'), - REQUIRE_GROUP="cn=other_gon,ou=moregroups,o=test" - ) - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice is None) - self.assertTrue(bob is not None) - self.assertEqual(bob.ldap_user.group_names, set(['other_gon'])) - - def test_denied_group(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - DENY_GROUP="cn=active_gon,ou=groups,o=test" - ) - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice is None) - self.assertTrue(bob is not None) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'simple_bind_s', 'compare_s', - 'initialize', 'simple_bind_s', 'simple_bind_s', 'compare_s'] - ) - - def test_group_dns(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - ) - alice = self.backend.authenticate(username='alice', password='password') - - self.assertEqual(alice.ldap_user.group_dns, set((g[0].lower() for g in [self.active_gon, self.staff_gon, self.superuser_gon, self.nested_gon]))) - - def test_group_names(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - ) - alice = self.backend.authenticate(username='alice', password='password') - - self.assertEqual(alice.ldap_user.group_names, set(['active_gon', 'staff_gon', 'superuser_gon', 'nested_gon'])) - - def test_dn_group_membership(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - USER_FLAGS_BY_GROUP={ - 'is_active': "cn=active_gon,ou=groups,o=test", - 'is_staff': ["cn=empty_gon,ou=groups,o=test", - "cn=staff_gon,ou=groups,o=test"], - 'is_superuser': "cn=superuser_gon,ou=groups,o=test" - } - ) - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice.is_active) - self.assertTrue(alice.is_staff) - self.assertTrue(alice.is_superuser) - self.assertTrue(not bob.is_active) - self.assertTrue(not bob.is_staff) - self.assertTrue(not bob.is_superuser) - - def test_posix_membership(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=PosixGroupType(), - USER_FLAGS_BY_GROUP={ - 'is_active': "cn=active_px,ou=groups,o=test", - 'is_staff': "cn=staff_px,ou=groups,o=test", - 'is_superuser': "cn=superuser_px,ou=groups,o=test" - } - ) - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice.is_active) - self.assertTrue(alice.is_staff) - self.assertTrue(alice.is_superuser) - self.assertTrue(not bob.is_active) - self.assertTrue(not bob.is_staff) - self.assertTrue(not bob.is_superuser) - - def test_nested_dn_group_membership(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=NestedMemberDNGroupType(member_attr='member'), - USER_FLAGS_BY_GROUP={ - 'is_active': "cn=parent_gon,ou=groups,o=test", - 'is_staff': "cn=parent_gon,ou=groups,o=test", - } - ) - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice.is_active) - self.assertTrue(alice.is_staff) - self.assertTrue(not bob.is_active) - self.assertTrue(not bob.is_staff) - - def test_posix_missing_attributes(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=PosixGroupType(), - USER_FLAGS_BY_GROUP={ - 'is_active': "cn=active_px,ou=groups,o=test" - } - ) - - nobody = self.backend.authenticate(username='nobody', password='password') - - self.assertTrue(not nobody.is_active) - - def test_profile_flags(self): - settings.AUTH_PROFILE_MODULE = 'django_auth_ldap.TestProfile' - - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - PROFILE_FLAGS_BY_GROUP={ - 'is_special': ["cn=superuser_gon,ou=groups,o=test"] - } - ) - - def handle_user_saved(sender, **kwargs): - if kwargs['created']: - TestProfile.objects.create(user=kwargs['instance']) - - django.db.models.signals.post_save.connect(handle_user_saved, sender=User) - - alice = self.backend.authenticate(username='alice', password='password') - bob = self.backend.authenticate(username='bob', password='password') - - self.assertTrue(alice.get_profile().is_special) - self.assertTrue(not bob.get_profile().is_special) - - def test_dn_group_permissions(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - FIND_GROUP_PERMS=True - ) - self._init_groups() - - alice = User.objects.create(username='alice') - alice = self.backend.get_user(alice.pk) - - self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertEqual(self.backend.get_all_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertTrue(self.backend.has_perm(alice, "auth.add_user")) - self.assertTrue(self.backend.has_module_perms(alice, "auth")) - - def test_empty_group_permissions(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - FIND_GROUP_PERMS=True - ) - self._init_groups() - - bob = User.objects.create(username='bob') - bob = self.backend.get_user(bob.pk) - - self.assertEqual(self.backend.get_group_permissions(bob), set()) - self.assertEqual(self.backend.get_all_permissions(bob), set()) - self.assertTrue(not self.backend.has_perm(bob, "auth.add_user")) - self.assertTrue(not self.backend.has_module_perms(bob, "auth")) - - def test_posix_group_permissions(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, - '(objectClass=posixGroup)'), - GROUP_TYPE=PosixGroupType(), - FIND_GROUP_PERMS=True - ) - self._init_groups() - - alice = User.objects.create(username='alice') - alice = self.backend.get_user(alice.pk) - - self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertEqual(self.backend.get_all_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertTrue(self.backend.has_perm(alice, "auth.add_user")) - self.assertTrue(self.backend.has_module_perms(alice, "auth")) - - def test_posix_group_permissions_no_gid(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, - '(objectClass=posixGroup)'), - GROUP_TYPE=PosixGroupType(), - FIND_GROUP_PERMS=True - ) - self._init_groups() - self.ldapobj.modify_s(self.alice[0], [(ldap.MOD_DELETE, 'gidNumber', None)]) - self.ldapobj.modify_s(self.active_px[0], [(ldap.MOD_ADD, 'memberUid', ['alice'])]) - - alice = User.objects.create(username='alice') - alice = self.backend.get_user(alice.pk) - - self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertEqual(self.backend.get_all_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertTrue(self.backend.has_perm(alice, "auth.add_user")) - self.assertTrue(self.backend.has_module_perms(alice, "auth")) - - def test_foreign_user_permissions(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - FIND_GROUP_PERMS=True - ) - self._init_groups() - - alice = User.objects.create(username='alice') - - self.assertEqual(self.backend.get_group_permissions(alice), set()) - - def test_group_cache(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - FIND_GROUP_PERMS=True, - CACHE_GROUPS=True - ) - self._init_groups() - - alice_id = User.objects.create(username='alice').pk - bob_id = User.objects.create(username='bob').pk - - # Check permissions twice for each user - for i in range(2): - alice = self.backend.get_user(alice_id) - self.assertEqual( - self.backend.get_group_permissions(alice), - set(["auth.add_user", "auth.change_user"]) - ) - - bob = self.backend.get_user(bob_id) - self.assertEqual(self.backend.get_group_permissions(bob), set()) - - # Should have executed one LDAP search per user - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search_s', - 'initialize', 'simple_bind_s', 'search_s'] - ) - - def test_group_mirroring(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, - '(objectClass=posixGroup)'), - GROUP_TYPE=PosixGroupType(), - MIRROR_GROUPS=True, - ) - - self.assertEqual(Group.objects.count(), 0) - - alice = self.backend.authenticate(username='alice', password='password') - - self.assertEqual(Group.objects.count(), 3) - self.assertEqual(set(alice.groups.all()), set(Group.objects.all())) - - def test_nested_group_mirroring(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, - '(objectClass=groupOfNames)'), - GROUP_TYPE=NestedMemberDNGroupType(member_attr='member'), - MIRROR_GROUPS=True, - ) - - alice = self.backend.authenticate(username='alice', password='password') - - self.assertEqual( - set(Group.objects.all().values_list('name', flat=True)), - set(['active_gon', 'staff_gon', 'superuser_gon', 'nested_gon', - 'parent_gon', 'circular_gon']) - ) - self.assertEqual(set(alice.groups.all()), set(Group.objects.all())) - - def test_authorize_external_users(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - FIND_GROUP_PERMS=True, - AUTHORIZE_ALL_USERS=True - ) - self._init_groups() - - alice = User.objects.create(username='alice') - - self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) - - def test_create_without_auth(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - ) - - alice = self.backend.populate_user('alice') - bob = self.backend.populate_user('bob') - - self.assertTrue(alice is not None) - self.assertEqual(alice.first_name, u"") - self.assertEqual(alice.last_name, u"") - self.assertTrue(alice.is_active) - self.assertTrue(not alice.is_staff) - self.assertTrue(not alice.is_superuser) - self.assertTrue(bob is not None) - self.assertEqual(bob.first_name, u"") - self.assertEqual(bob.last_name, u"") - self.assertTrue(bob.is_active) - self.assertTrue(not bob.is_staff) - self.assertTrue(not bob.is_superuser) - - def test_populate_without_auth(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - ALWAYS_UPDATE_USER=False, - USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn'}, - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=GroupOfNamesType(), - USER_FLAGS_BY_GROUP={ - 'is_active': "cn=active_gon,ou=groups,o=test", - 'is_staff': "cn=staff_gon,ou=groups,o=test", - 'is_superuser': "cn=superuser_gon,ou=groups,o=test" - } - ) - - User.objects.create(username='alice') - User.objects.create(username='bob') - - alice = self.backend.populate_user('alice') - bob = self.backend.populate_user('bob') - - self.assertTrue(alice is not None) - self.assertEqual(alice.first_name, u"Alice") - self.assertEqual(alice.last_name, u"Adams") - self.assertTrue(alice.is_active) - self.assertTrue(alice.is_staff) - self.assertTrue(alice.is_superuser) - self.assertTrue(bob is not None) - self.assertEqual(bob.first_name, u"Robert") - self.assertEqual(bob.last_name, u"Barker") - self.assertTrue(not bob.is_active) - self.assertTrue(not bob.is_staff) - self.assertTrue(not bob.is_superuser) - - def test_populate_bogus_user(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - ) - - bogus = self.backend.populate_user('bogus') - - self.assertEqual(bogus, None) - - def test_start_tls_missing(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - START_TLS=False, - ) - - self.assertTrue(not self.ldapobj.tls_enabled) - self.backend.authenticate(username='alice', password='password') - self.assertTrue(not self.ldapobj.tls_enabled) - - def test_start_tls(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - START_TLS=True, - ) - - self.assertTrue(not self.ldapobj.tls_enabled) - self.backend.authenticate(username='alice', password='password') - self.assertTrue(self.ldapobj.tls_enabled) - - def test_null_search_results(self): - """ - Make sure we're not phased by referrals. - """ - self._init_settings( - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - self.backend.authenticate(username='alice', password='password') - - def test_union_search(self): - self._init_settings( - USER_SEARCH=LDAPSearchUnion( - LDAPSearch("ou=groups,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'), - LDAPSearch("ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)'), - ) - ) - alice = self.backend.authenticate(username='alice', password='password') - - self.assertTrue(alice is not None) - - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s', 'search', 'search', 'result', - 'result', 'simple_bind_s'] - ) - - def test_deny_empty_password(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - ) - - alice = self.backend.authenticate(username=u'alice', password=u'') - - self.assertEqual(alice, None) - self.assertEqual(self.ldapobj.methods_called(), []) - - def test_permit_empty_password(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - PERMIT_EMPTY_PASSWORD=True, - ) - - alice = self.backend.authenticate(username=u'alice', password=u'') - - self.assertEqual(alice, None) - self.assertEqual( - self.ldapobj.methods_called(), - ['initialize', 'simple_bind_s'] - ) - - def test_pickle(self): - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), - GROUP_TYPE=MemberDNGroupType(member_attr='member'), - FIND_GROUP_PERMS=True - ) - self._init_groups() - - alice0 = self.backend.authenticate(username=u'alice', password=u'password') - - pickled = pickle.dumps(alice0, pickle.HIGHEST_PROTOCOL) - alice = pickle.loads(pickled) - alice.ldap_user.backend.settings = alice0.ldap_user.backend.settings - - self.assertTrue(alice is not None) - self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertEqual(self.backend.get_all_permissions(alice), set(["auth.add_user", "auth.change_user"])) - self.assertTrue(self.backend.has_perm(alice, "auth.add_user")) - self.assertTrue(self.backend.has_module_perms(alice, "auth")) - - def _init_settings(self, **kwargs): - self.backend.settings = TestSettings(**kwargs) - - def _init_groups(self): - permissions = [ - Permission.objects.get(codename="add_user"), - Permission.objects.get(codename="change_user") - ] - - active_gon = Group.objects.create(name='active_gon') - active_gon.permissions.add(*permissions) - - active_px = Group.objects.create(name='active_px') - active_px.permissions.add(*permissions) - - -# Python 2.5-compatible class decoration -LDAPTest = unittest.skipIf(mockldap is None, "django_auth_ldap tests require the mockldap package.")(LDAPTest) diff --git a/awx/lib/site-packages/django_extensions/__init__.py b/awx/lib/site-packages/django_extensions/__init__.py deleted file mode 100644 index a28dfa9a91..0000000000 --- a/awx/lib/site-packages/django_extensions/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ - -VERSION = (1, 3, 3) - -# Dynamically calculate the version based on VERSION tuple -if len(VERSION) > 2 and VERSION[2] is not None: - if isinstance(VERSION[2], int): - str_version = "%s.%s.%s" % VERSION[:3] - else: - str_version = "%s.%s_%s" % VERSION[:3] -else: - str_version = "%s.%s" % VERSION[:2] - -__version__ = str_version diff --git a/awx/lib/site-packages/django_extensions/admin/__init__.py b/awx/lib/site-packages/django_extensions/admin/__init__.py deleted file mode 100644 index fdeceeeb42..0000000000 --- a/awx/lib/site-packages/django_extensions/admin/__init__.py +++ /dev/null @@ -1,148 +0,0 @@ -# -# Autocomplete feature for admin panel -# - -import six -import operator -from six.moves import reduce -from django.http import HttpResponse, HttpResponseNotFound -from django.db import models -from django.db.models.query import QuerySet -from django.utils.encoding import smart_str -from django.utils.translation import ugettext as _ -from django.utils.text import get_text_list -try: - from functools import update_wrapper - assert update_wrapper -except ImportError: - from django.utils.functional import update_wrapper - -from django_extensions.admin.widgets import ForeignKeySearchInput - -from django.conf import settings - -if 'reversion' in settings.INSTALLED_APPS: - from reversion.admin import VersionAdmin as ModelAdmin - assert ModelAdmin -else: - from django.contrib.admin import ModelAdmin - - -class ForeignKeyAutocompleteAdmin(ModelAdmin): - """Admin class for models using the autocomplete feature. - - There are two additional fields: - - related_search_fields: defines fields of managed model that - have to be represented by autocomplete input, together with - a list of target model fields that are searched for - input string, e.g.: - - related_search_fields = { - 'author': ('first_name', 'email'), - } - - - related_string_functions: contains optional functions which - take target model instance as only argument and return string - representation. By default __unicode__() method of target - object is used. - - And also an optional additional field to set the limit on the - results returned by the autocomplete query. You can set this integer - value in your settings file using FOREIGNKEY_AUTOCOMPLETE_LIMIT or - you can set this per ForeignKeyAutocompleteAdmin basis. If any value - is set the results will not be limited. - """ - - related_search_fields = {} - related_string_functions = {} - autocomplete_limit = getattr(settings, 'FOREIGNKEY_AUTOCOMPLETE_LIMIT', None) - - def get_urls(self): - from django.conf.urls import patterns, url - - def wrap(view): - def wrapper(*args, **kwargs): - return self.admin_site.admin_view(view)(*args, **kwargs) - return update_wrapper(wrapper, view) - - info = self.model._meta.app_label, self.model._meta.module_name - - urlpatterns = patterns('', url(r'foreignkey_autocomplete/$', wrap(self.foreignkey_autocomplete), name='%s_%s_autocomplete' % info)) - urlpatterns += super(ForeignKeyAutocompleteAdmin, self).get_urls() - return urlpatterns - - def foreignkey_autocomplete(self, request): - """ - Searches in the fields of the given related model and returns the - result as a simple string to be used by the jQuery Autocomplete plugin - """ - query = request.GET.get('q', None) - app_label = request.GET.get('app_label', None) - model_name = request.GET.get('model_name', None) - search_fields = request.GET.get('search_fields', None) - object_pk = request.GET.get('object_pk', None) - - try: - to_string_function = self.related_string_functions[model_name] - except KeyError: - to_string_function = lambda x: x.__unicode__() - - if search_fields and app_label and model_name and (query or object_pk): - def construct_search(field_name): - # use different lookup methods depending on the notation - if field_name.startswith('^'): - return "%s__istartswith" % field_name[1:] - elif field_name.startswith('='): - return "%s__iexact" % field_name[1:] - elif field_name.startswith('@'): - return "%s__search" % field_name[1:] - else: - return "%s__icontains" % field_name - model = models.get_model(app_label, model_name) - queryset = model._default_manager.all() - data = '' - if query: - for bit in query.split(): - or_queries = [models.Q(**{construct_search(smart_str(field_name)): smart_str(bit)}) for field_name in search_fields.split(',')] - other_qs = QuerySet(model) - other_qs.query.select_related = queryset.query.select_related - other_qs = other_qs.filter(reduce(operator.or_, or_queries)) - queryset = queryset & other_qs - - if self.autocomplete_limit: - queryset = queryset[:self.autocomplete_limit] - - data = ''.join([six.u('%s|%s\n') % (to_string_function(f), f.pk) for f in queryset]) - elif object_pk: - try: - obj = queryset.get(pk=object_pk) - except: - pass - else: - data = to_string_function(obj) - return HttpResponse(data) - return HttpResponseNotFound() - - def get_help_text(self, field_name, model_name): - searchable_fields = self.related_search_fields.get(field_name, None) - if searchable_fields: - help_kwargs = { - 'model_name': model_name, - 'field_list': get_text_list(searchable_fields, _('and')), - } - return _('Use the left field to do %(model_name)s lookups in the fields %(field_list)s.') % help_kwargs - return '' - - def formfield_for_dbfield(self, db_field, **kwargs): - """ - Overrides the default widget for Foreignkey fields if they are - specified in the related_search_fields class attribute. - """ - if (isinstance(db_field, models.ForeignKey) and db_field.name in self.related_search_fields): - model_name = db_field.rel.to._meta.object_name - help_text = self.get_help_text(db_field.name, model_name) - if kwargs.get('help_text'): - help_text = six.u('%s %s' % (kwargs['help_text'], help_text)) - kwargs['widget'] = ForeignKeySearchInput(db_field.rel, self.related_search_fields[db_field.name]) - kwargs['help_text'] = help_text - return super(ForeignKeyAutocompleteAdmin, self).formfield_for_dbfield(db_field, **kwargs) diff --git a/awx/lib/site-packages/django_extensions/admin/widgets.py b/awx/lib/site-packages/django_extensions/admin/widgets.py deleted file mode 100644 index 090ee19a85..0000000000 --- a/awx/lib/site-packages/django_extensions/admin/widgets.py +++ /dev/null @@ -1,88 +0,0 @@ -import six -import django - -from django import forms -from django.contrib.admin.sites import site -from django.utils.safestring import mark_safe -from django.utils.text import Truncator -from django.template.loader import render_to_string -from django.contrib.admin.widgets import ForeignKeyRawIdWidget - - -class ForeignKeySearchInput(ForeignKeyRawIdWidget): - """ - A Widget for displaying ForeignKeys in an autocomplete search input - instead in a <select> box. - """ - # Set in subclass to render the widget with a different template - widget_template = None - # Set this to the patch of the search view - search_path = '../foreignkey_autocomplete/' - - def _media(self): - js_files = ['django_extensions/js/jquery.bgiframe.min.js', - 'django_extensions/js/jquery.ajaxQueue.js', - 'django_extensions/js/jquery.autocomplete.js'] - - # Use a newer version of jquery if django version <= 1.5.x - # When removing this compatibility code also remove jquery-1.7.2.min.js file. - if int(django.get_version()[2]) <= 5: - js_files.insert(0, 'django_extensions/js/jquery-1.7.2.min.js') - - return forms.Media(css={'all': ('django_extensions/css/jquery.autocomplete.css',)}, - js=js_files) - - media = property(_media) - - def label_for_value(self, value): - key = self.rel.get_related_field().name - obj = self.rel.to._default_manager.get(**{key: value}) - - return Truncator(obj).words(14, truncate='...') - - def __init__(self, rel, search_fields, attrs=None): - self.search_fields = search_fields - super(ForeignKeySearchInput, self).__init__(rel, site, attrs) - - def render(self, name, value, attrs=None): - if attrs is None: - attrs = {} - #output = [super(ForeignKeySearchInput, self).render(name, value, attrs)] - opts = self.rel.to._meta - app_label = opts.app_label - model_name = opts.object_name.lower() - related_url = '../../../%s/%s/' % (app_label, model_name) - params = self.url_parameters() - if params: - url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()]) - else: - url = '' - - if not 'class' in attrs: - attrs['class'] = 'vForeignKeyRawIdAdminField' - # Call the TextInput render method directly to have more control - output = [forms.TextInput.render(self, name, value, attrs)] - - if value: - label = self.label_for_value(value) - else: - label = six.u('') - - context = { - 'url': url, - 'related_url': related_url, - 'search_path': self.search_path, - 'search_fields': ','.join(self.search_fields), - 'app_label': app_label, - 'model_name': model_name, - 'label': label, - 'name': name, - } - output.append(render_to_string(self.widget_template or ( - 'django_extensions/widgets/%s/%s/foreignkey_searchinput.html' % (app_label, model_name), - 'django_extensions/widgets/%s/foreignkey_searchinput.html' % app_label, - 'django_extensions/widgets/foreignkey_searchinput.html', - ), context)) - output.reverse() - - return mark_safe(six.u('').join(output)) diff --git a/awx/lib/site-packages/django_extensions/conf/app_template/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/app_template/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/app_template/forms.py.tmpl b/awx/lib/site-packages/django_extensions/conf/app_template/forms.py.tmpl deleted file mode 100644 index 6b477f9e46..0000000000 --- a/awx/lib/site-packages/django_extensions/conf/app_template/forms.py.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -from django import forms - -# place form definition here \ No newline at end of file diff --git a/awx/lib/site-packages/django_extensions/conf/app_template/models.py.tmpl b/awx/lib/site-packages/django_extensions/conf/app_template/models.py.tmpl deleted file mode 100644 index 71a8362390..0000000000 --- a/awx/lib/site-packages/django_extensions/conf/app_template/models.py.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/awx/lib/site-packages/django_extensions/conf/app_template/urls.py.tmpl b/awx/lib/site-packages/django_extensions/conf/app_template/urls.py.tmpl deleted file mode 100644 index 96ef53f2cf..0000000000 --- a/awx/lib/site-packages/django_extensions/conf/app_template/urls.py.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -try: - from django.conf.urls import * -except ImportError: # django < 1.4 - from django.conf.urls.defaults import * - -# place app url patterns here diff --git a/awx/lib/site-packages/django_extensions/conf/app_template/views.py.tmpl b/awx/lib/site-packages/django_extensions/conf/app_template/views.py.tmpl deleted file mode 100644 index 60f00ef0ef..0000000000 --- a/awx/lib/site-packages/django_extensions/conf/app_template/views.py.tmpl +++ /dev/null @@ -1 +0,0 @@ -# Create your views here. diff --git a/awx/lib/site-packages/django_extensions/conf/command_template/management/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/command_template/management/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/command_template/management/commands/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/command_template/management/commands/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/command_template/management/commands/sample.py.tmpl b/awx/lib/site-packages/django_extensions/conf/command_template/management/commands/sample.py.tmpl deleted file mode 100644 index eb9df1b9a1..0000000000 --- a/awx/lib/site-packages/django_extensions/conf/command_template/management/commands/sample.py.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -from django.core.management.base import {{ base_command }} - -class Command({{ base_command }}): - help = "My shiny new management command." - - def {{ handle_method }}: - raise NotImplementedError() \ No newline at end of file diff --git a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/daily/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/daily/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/hourly/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/hourly/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/monthly/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/monthly/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/sample.py.tmpl b/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/sample.py.tmpl deleted file mode 100644 index 1a1517986c..0000000000 --- a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/sample.py.tmpl +++ /dev/null @@ -1,8 +0,0 @@ -from django_extensions.management.jobs import BaseJob - -class Job(BaseJob): - help = "My sample job." - - def execute(self): - # executing empty sample job - pass diff --git a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/weekly/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/weekly/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/yearly/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/jobs_template/jobs/yearly/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/template_tags_template/templatetags/__init__.py.tmpl b/awx/lib/site-packages/django_extensions/conf/template_tags_template/templatetags/__init__.py.tmpl deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/conf/template_tags_template/templatetags/sample.py.tmpl b/awx/lib/site-packages/django_extensions/conf/template_tags_template/templatetags/sample.py.tmpl deleted file mode 100644 index d0b488128e..0000000000 --- a/awx/lib/site-packages/django_extensions/conf/template_tags_template/templatetags/sample.py.tmpl +++ /dev/null @@ -1,4 +0,0 @@ -from django import template - -register = template.Library() - diff --git a/awx/lib/site-packages/django_extensions/db/__init__.py b/awx/lib/site-packages/django_extensions/db/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/db/fields/__init__.py b/awx/lib/site-packages/django_extensions/db/fields/__init__.py deleted file mode 100644 index 0639f170c5..0000000000 --- a/awx/lib/site-packages/django_extensions/db/fields/__init__.py +++ /dev/null @@ -1,292 +0,0 @@ -""" -Django Extensions additional model fields -""" -import re -import six -try: - import uuid - HAS_UUID = True -except ImportError: - HAS_UUID = False - -from django.core.exceptions import ImproperlyConfigured -from django.template.defaultfilters import slugify -from django.db.models import DateTimeField, CharField, SlugField - -try: - from django.utils.timezone import now as datetime_now - assert datetime_now -except ImportError: - import datetime - datetime_now = datetime.datetime.now - -try: - from django.utils.encoding import force_unicode # NOQA -except ImportError: - from django.utils.encoding import force_text as force_unicode # NOQA - - -class AutoSlugField(SlugField): - """ AutoSlugField - - By default, sets editable=False, blank=True. - - Required arguments: - - populate_from - Specifies which field or list of fields the slug is populated from. - - Optional arguments: - - separator - Defines the used separator (default: '-') - - overwrite - If set to True, overwrites the slug on every save (default: False) - - Inspired by SmileyChris' Unique Slugify snippet: - http://www.djangosnippets.org/snippets/690/ - """ - def __init__(self, *args, **kwargs): - kwargs.setdefault('blank', True) - kwargs.setdefault('editable', False) - - populate_from = kwargs.pop('populate_from', None) - if populate_from is None: - raise ValueError("missing 'populate_from' argument") - else: - self._populate_from = populate_from - self.separator = kwargs.pop('separator', six.u('-')) - self.overwrite = kwargs.pop('overwrite', False) - self.allow_duplicates = kwargs.pop('allow_duplicates', False) - super(AutoSlugField, self).__init__(*args, **kwargs) - - def _slug_strip(self, value): - """ - Cleans up a slug by removing slug separator characters that occur at - the beginning or end of a slug. - - If an alternate separator is used, it will also replace any instances - of the default '-' separator with the new separator. - """ - re_sep = '(?:-|%s)' % re.escape(self.separator) - value = re.sub('%s+' % re_sep, self.separator, value) - return re.sub(r'^%s+|%s+$' % (re_sep, re_sep), '', value) - - def get_queryset(self, model_cls, slug_field): - for field, model in model_cls._meta.get_fields_with_model(): - if model and field == slug_field: - return model._default_manager.all() - return model_cls._default_manager.all() - - def slugify_func(self, content): - if content: - return slugify(content) - return '' - - def create_slug(self, model_instance, add): - # get fields to populate from and slug field to set - if not isinstance(self._populate_from, (list, tuple)): - self._populate_from = (self._populate_from, ) - slug_field = model_instance._meta.get_field(self.attname) - - if add or self.overwrite: - # slugify the original field content and set next step to 2 - slug_for_field = lambda field: self.slugify_func(getattr(model_instance, field)) - slug = self.separator.join(map(slug_for_field, self._populate_from)) - next = 2 - else: - # get slug from the current model instance - slug = getattr(model_instance, self.attname) - # model_instance is being modified, and overwrite is False, - # so instead of doing anything, just return the current slug - return slug - - # strip slug depending on max_length attribute of the slug field - # and clean-up - slug_len = slug_field.max_length - if slug_len: - slug = slug[:slug_len] - slug = self._slug_strip(slug) - original_slug = slug - - if self.allow_duplicates: - return slug - - # exclude the current model instance from the queryset used in finding - # the next valid slug - queryset = self.get_queryset(model_instance.__class__, slug_field) - if model_instance.pk: - queryset = queryset.exclude(pk=model_instance.pk) - - # form a kwarg dict used to impliment any unique_together contraints - kwargs = {} - for params in model_instance._meta.unique_together: - if self.attname in params: - for param in params: - kwargs[param] = getattr(model_instance, param, None) - kwargs[self.attname] = slug - - # increases the number while searching for the next valid slug - # depending on the given slug, clean-up - while not slug or queryset.filter(**kwargs): - slug = original_slug - end = '%s%s' % (self.separator, next) - end_len = len(end) - if slug_len and len(slug) + end_len > slug_len: - slug = slug[:slug_len - end_len] - slug = self._slug_strip(slug) - slug = '%s%s' % (slug, end) - kwargs[self.attname] = slug - next += 1 - return slug - - def pre_save(self, model_instance, add): - value = force_unicode(self.create_slug(model_instance, add)) - setattr(model_instance, self.attname, value) - return value - - def get_internal_type(self): - return "SlugField" - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect the _actual_ field. - from south.modelsinspector import introspector - field_class = '%s.AutoSlugField' % self.__module__ - args, kwargs = introspector(self) - kwargs.update({ - 'populate_from': repr(self._populate_from), - 'separator': repr(self.separator), - 'overwrite': repr(self.overwrite), - 'allow_duplicates': repr(self.allow_duplicates), - }) - # That's our definition! - return (field_class, args, kwargs) - - -class CreationDateTimeField(DateTimeField): - """ CreationDateTimeField - - By default, sets editable=False, blank=True, default=datetime.now - """ - - def __init__(self, *args, **kwargs): - kwargs.setdefault('editable', False) - kwargs.setdefault('blank', True) - kwargs.setdefault('default', datetime_now) - DateTimeField.__init__(self, *args, **kwargs) - - def get_internal_type(self): - return "DateTimeField" - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect ourselves, since we inherit. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.DateTimeField" - args, kwargs = introspector(self) - return (field_class, args, kwargs) - - -class ModificationDateTimeField(CreationDateTimeField): - """ ModificationDateTimeField - - By default, sets editable=False, blank=True, default=datetime.now - - Sets value to datetime.now() on each save of the model. - """ - - def pre_save(self, model, add): - value = datetime_now() - setattr(model, self.attname, value) - return value - - def get_internal_type(self): - return "DateTimeField" - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect ourselves, since we inherit. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.DateTimeField" - args, kwargs = introspector(self) - return (field_class, args, kwargs) - - -class UUIDVersionError(Exception): - pass - - -class UUIDField(CharField): - """ UUIDField - - By default uses UUID version 4 (randomly generated UUID). - - The field support all uuid versions which are natively supported by the uuid python module, except version 2. - For more information see: http://docs.python.org/lib/module-uuid.html - """ - - def __init__(self, verbose_name=None, name=None, auto=True, version=4, node=None, clock_seq=None, namespace=None, **kwargs): - if not HAS_UUID: - raise ImproperlyConfigured("'uuid' module is required for UUIDField. (Do you have Python 2.5 or higher installed ?)") - kwargs.setdefault('max_length', 36) - if auto: - self.empty_strings_allowed = False - kwargs['blank'] = True - kwargs.setdefault('editable', False) - self.auto = auto - self.version = version - if version == 1: - self.node, self.clock_seq = node, clock_seq - elif version == 3 or version == 5: - self.namespace, self.name = namespace, name - CharField.__init__(self, verbose_name, name, **kwargs) - - def get_internal_type(self): - return CharField.__name__ - - def create_uuid(self): - if not self.version or self.version == 4: - return uuid.uuid4() - elif self.version == 1: - return uuid.uuid1(self.node, self.clock_seq) - elif self.version == 2: - raise UUIDVersionError("UUID version 2 is not supported.") - elif self.version == 3: - return uuid.uuid3(self.namespace, self.name) - elif self.version == 5: - return uuid.uuid5(self.namespace, self.name) - else: - raise UUIDVersionError("UUID version %s is not valid." % self.version) - - def pre_save(self, model_instance, add): - value = super(UUIDField, self).pre_save(model_instance, add) - if self.auto and add and value is None: - value = force_unicode(self.create_uuid()) - setattr(model_instance, self.attname, value) - return value - else: - if self.auto and not value: - value = force_unicode(self.create_uuid()) - setattr(model_instance, self.attname, value) - return value - - def formfield(self, **kwargs): - if self.auto: - return None - return super(UUIDField, self).formfield(**kwargs) - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect the _actual_ field. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.CharField" - args, kwargs = introspector(self) - # That's our definition! - return (field_class, args, kwargs) - - -class PostgreSQLUUIDField(UUIDField): - def db_type(self, connection=None): - return "UUID" diff --git a/awx/lib/site-packages/django_extensions/db/fields/encrypted.py b/awx/lib/site-packages/django_extensions/db/fields/encrypted.py deleted file mode 100644 index fd0158ca0c..0000000000 --- a/awx/lib/site-packages/django_extensions/db/fields/encrypted.py +++ /dev/null @@ -1,138 +0,0 @@ -import six -from django.db import models -from django.core.exceptions import ImproperlyConfigured -from django import forms -from django.conf import settings -import warnings - -try: - from keyczar import keyczar -except ImportError: - raise ImportError('Using an encrypted field requires the Keyczar module. ' - 'You can obtain Keyczar from http://www.keyczar.org/.') - - -class EncryptionWarning(RuntimeWarning): - pass - - -class BaseEncryptedField(models.Field): - prefix = 'enc_str:::' - - def __init__(self, *args, **kwargs): - if not hasattr(settings, 'ENCRYPTED_FIELD_KEYS_DIR'): - raise ImproperlyConfigured('You must set the settings.ENCRYPTED_FIELD_KEYS_DIR ' - 'setting to your Keyczar keys directory.') - crypt_class = self.get_crypt_class() - self.crypt = crypt_class.Read(settings.ENCRYPTED_FIELD_KEYS_DIR) - - # Encrypted size is larger than unencrypted - self.unencrypted_length = max_length = kwargs.get('max_length', None) - if max_length: - max_length = len(self.prefix) + len(self.crypt.Encrypt('x' * max_length)) - # TODO: Re-examine if this logic will actually make a large-enough - # max-length for unicode strings that have non-ascii characters in them. - kwargs['max_length'] = max_length - - super(BaseEncryptedField, self).__init__(*args, **kwargs) - - def get_crypt_class(self): - """ - Get the Keyczar class to use. - - The class can be customized with the ENCRYPTED_FIELD_MODE setting. By default, - this setting is DECRYPT_AND_ENCRYPT. Set this to ENCRYPT to disable decryption. - This is necessary if you are only providing public keys to Keyczar. - - Returns: - keyczar.Encrypter if ENCRYPTED_FIELD_MODE is ENCRYPT. - keyczar.Crypter if ENCRYPTED_FIELD_MODE is DECRYPT_AND_ENCRYPT. - - Override this method to customize the type of Keyczar class returned. - """ - - crypt_type = getattr(settings, 'ENCRYPTED_FIELD_MODE', 'DECRYPT_AND_ENCRYPT') - if crypt_type == 'ENCRYPT': - crypt_class_name = 'Encrypter' - elif crypt_type == 'DECRYPT_AND_ENCRYPT': - crypt_class_name = 'Crypter' - else: - raise ImproperlyConfigured( - 'ENCRYPTED_FIELD_MODE must be either DECRYPT_AND_ENCRYPT ' - 'or ENCRYPT, not %s.' % crypt_type) - return getattr(keyczar, crypt_class_name) - - def to_python(self, value): - if isinstance(self.crypt.primary_key, keyczar.keys.RsaPublicKey): - retval = value - elif value and (value.startswith(self.prefix)): - if hasattr(self.crypt, 'Decrypt'): - retval = self.crypt.Decrypt(value[len(self.prefix):]) - if retval: - retval = retval.decode('utf-8') - else: - retval = value - else: - retval = value - return retval - - def get_db_prep_value(self, value, connection, prepared=False): - if value and not value.startswith(self.prefix): - # We need to encode a unicode string into a byte string, first. - # keyczar expects a bytestring, not a unicode string. - if type(value) == six.types.UnicodeType: - value = value.encode('utf-8') - # Truncated encrypted content is unreadable, - # so truncate before encryption - max_length = self.unencrypted_length - if max_length and len(value) > max_length: - warnings.warn("Truncating field %s from %d to %d bytes" % ( - self.name, len(value), max_length), EncryptionWarning - ) - value = value[:max_length] - - value = self.prefix + self.crypt.Encrypt(value) - return value - - -class EncryptedTextField(six.with_metaclass(models.SubfieldBase, - BaseEncryptedField)): - def get_internal_type(self): - return 'TextField' - - def formfield(self, **kwargs): - defaults = {'widget': forms.Textarea} - defaults.update(kwargs) - return super(EncryptedTextField, self).formfield(**defaults) - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect the _actual_ field. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.TextField" - args, kwargs = introspector(self) - # That's our definition! - return (field_class, args, kwargs) - - -class EncryptedCharField(six.with_metaclass(models.SubfieldBase, - BaseEncryptedField)): - def __init__(self, *args, **kwargs): - super(EncryptedCharField, self).__init__(*args, **kwargs) - - def get_internal_type(self): - return "CharField" - - def formfield(self, **kwargs): - defaults = {'max_length': self.max_length} - defaults.update(kwargs) - return super(EncryptedCharField, self).formfield(**defaults) - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect the _actual_ field. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.CharField" - args, kwargs = introspector(self) - # That's our definition! - return (field_class, args, kwargs) diff --git a/awx/lib/site-packages/django_extensions/db/fields/json.py b/awx/lib/site-packages/django_extensions/db/fields/json.py deleted file mode 100644 index ef1705914f..0000000000 --- a/awx/lib/site-packages/django_extensions/db/fields/json.py +++ /dev/null @@ -1,98 +0,0 @@ -""" -JSONField automatically serializes most Python terms to JSON data. -Creates a TEXT field with a default value of "{}". See test_json.py for -more information. - - from django.db import models - from django_extensions.db.fields import json - - class LOL(models.Model): - extra = json.JSONField() -""" - -import six -from decimal import Decimal -from django.db import models -from django.conf import settings -from django.core.serializers.json import DjangoJSONEncoder - -try: - # Django <= 1.6 backwards compatibility - from django.utils import simplejson as json -except ImportError: - # Django >= 1.7 - import json - - -def dumps(value): - return DjangoJSONEncoder().encode(value) - - -def loads(txt): - value = json.loads( - txt, - parse_float=Decimal, - encoding=settings.DEFAULT_CHARSET - ) - return value - - -class JSONDict(dict): - """ - Hack so repr() called by dumpdata will output JSON instead of - Python formatted data. This way fixtures will work! - """ - def __repr__(self): - return dumps(self) - - -class JSONList(list): - """ - As above - """ - def __repr__(self): - return dumps(self) - - -class JSONField(six.with_metaclass(models.SubfieldBase, models.TextField)): - """JSONField is a generic textfield that neatly serializes/unserializes - JSON objects seamlessly. Main thingy must be a dict object.""" - - def __init__(self, *args, **kwargs): - default = kwargs.get('default', None) - if default is None: - kwargs['default'] = '{}' - elif isinstance(default, (list, dict)): - kwargs['default'] = dumps(default) - models.TextField.__init__(self, *args, **kwargs) - - def to_python(self, value): - """Convert our string value to JSON after we load it from the DB""" - if value is None or value == '': - return {} - elif isinstance(value, six.string_types): - res = loads(value) - if isinstance(res, dict): - return JSONDict(**res) - else: - return JSONList(res) - - else: - return value - - def get_db_prep_save(self, value, connection): - """Convert our JSON object to a string before we save""" - if not isinstance(value, (list, dict)): - return super(JSONField, self).get_db_prep_save("", connection=connection) - else: - return super(JSONField, self).get_db_prep_save(dumps(value), - connection=connection) - - def south_field_triple(self): - "Returns a suitable description of this field for South." - # We'll just introspect the _actual_ field. - from south.modelsinspector import introspector - field_class = "django.db.models.fields.TextField" - args, kwargs = introspector(self) - # That's our definition! - return (field_class, args, kwargs) diff --git a/awx/lib/site-packages/django_extensions/db/models.py b/awx/lib/site-packages/django_extensions/db/models.py deleted file mode 100644 index 6f21b098ae..0000000000 --- a/awx/lib/site-packages/django_extensions/db/models.py +++ /dev/null @@ -1,78 +0,0 @@ -""" -Django Extensions abstract base model classes. -""" -from django.db import models -from django.utils.translation import ugettext_lazy as _ -from django_extensions.db.fields import (ModificationDateTimeField, - CreationDateTimeField, AutoSlugField) - -try: - from django.utils.timezone import now as datetime_now - assert datetime_now -except ImportError: - import datetime - datetime_now = datetime.datetime.now - - -class TimeStampedModel(models.Model): - """ TimeStampedModel - An abstract base class model that provides self-managed "created" and - "modified" fields. - """ - created = CreationDateTimeField(_('created')) - modified = ModificationDateTimeField(_('modified')) - - class Meta: - get_latest_by = 'modified' - ordering = ('-modified', '-created',) - abstract = True - - -class TitleSlugDescriptionModel(models.Model): - """ TitleSlugDescriptionModel - An abstract base class model that provides title and description fields - and a self-managed "slug" field that populates from the title. - """ - title = models.CharField(_('title'), max_length=255) - slug = AutoSlugField(_('slug'), populate_from='title') - description = models.TextField(_('description'), blank=True, null=True) - - class Meta: - abstract = True - - -class ActivatorModelManager(models.Manager): - """ ActivatorModelManager - Manager to return instances of ActivatorModel: SomeModel.objects.active() / .inactive() - """ - def active(self): - """ Returns active instances of ActivatorModel: SomeModel.objects.active() """ - return self.get_query_set().filter(status=ActivatorModel.ACTIVE_STATUS) - - def inactive(self): - """ Returns inactive instances of ActivatorModel: SomeModel.objects.inactive() """ - return self.get_query_set().filter(status=ActivatorModel.INACTIVE_STATUS) - - -class ActivatorModel(models.Model): - """ ActivatorModel - An abstract base class model that provides activate and deactivate fields. - """ - INACTIVE_STATUS, ACTIVE_STATUS = range(2) - STATUS_CHOICES = ( - (INACTIVE_STATUS, _('Inactive')), - (ACTIVE_STATUS, _('Active')), - ) - status = models.IntegerField(_('status'), choices=STATUS_CHOICES, default=ACTIVE_STATUS) - activate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for an immediate activation')) - deactivate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for indefinite activation')) - objects = ActivatorModelManager() - - class Meta: - ordering = ('status', '-activate_date',) - abstract = True - - def save(self, *args, **kwargs): - if not self.activate_date: - self.activate_date = datetime_now() - super(ActivatorModel, self).save(*args, **kwargs) diff --git a/awx/lib/site-packages/django_extensions/future_1_5.py b/awx/lib/site-packages/django_extensions/future_1_5.py deleted file mode 100644 index d7144ca383..0000000000 --- a/awx/lib/site-packages/django_extensions/future_1_5.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -A forwards compatibility module. - -Implements some features of Django 1.5 related to the 'Custom User Model' feature -when the application is run with a lower version of Django. -""" -from __future__ import unicode_literals - -from django.contrib.auth.models import User - -User.USERNAME_FIELD = "username" -User.get_username = lambda self: self.username - - -def get_user_model(): - return User diff --git a/awx/lib/site-packages/django_extensions/jobs/__init__.py b/awx/lib/site-packages/django_extensions/jobs/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/jobs/daily/__init__.py b/awx/lib/site-packages/django_extensions/jobs/daily/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/jobs/daily/cache_cleanup.py b/awx/lib/site-packages/django_extensions/jobs/daily/cache_cleanup.py deleted file mode 100644 index b598e0de9e..0000000000 --- a/awx/lib/site-packages/django_extensions/jobs/daily/cache_cleanup.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Daily cleanup job. - -Can be run as a cronjob to clean out old data from the database (only expired -sessions at the moment). -""" - -import six -from django_extensions.management.jobs import DailyJob - - -class Job(DailyJob): - help = "Cache (db) cleanup Job" - - def execute(self): - from django.conf import settings - from django.db import transaction - import os - - try: - from django.utils import timezone - except ImportError: - timezone = None - - if hasattr(settings, 'CACHES') and timezone: - from django.core.cache import get_cache - from django.db import router, connections - - for cache_name, cache_options in six.iteritems(settings.CACHES): - if cache_options['BACKEND'].endswith("DatabaseCache"): - cache = get_cache(cache_name) - db = router.db_for_write(cache.cache_model_class) - cursor = connections[db].cursor() - now = timezone.now() - cache._cull(db, cursor, now) - transaction.commit_unless_managed(using=db) - return - - if hasattr(settings, 'CACHE_BACKEND'): - if settings.CACHE_BACKEND.startswith('db://'): - from django.db import connection - os.environ['TZ'] = settings.TIME_ZONE - table_name = settings.CACHE_BACKEND[5:] - cursor = connection.cursor() - cursor.execute( - "DELETE FROM %s WHERE %s < current_timestamp;" % ( - connection.ops.quote_name(table_name), - connection.ops.quote_name('expires') - ) - ) - transaction.commit_unless_managed() diff --git a/awx/lib/site-packages/django_extensions/jobs/daily/daily_cleanup.py b/awx/lib/site-packages/django_extensions/jobs/daily/daily_cleanup.py deleted file mode 100644 index 8e7172cd5c..0000000000 --- a/awx/lib/site-packages/django_extensions/jobs/daily/daily_cleanup.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Daily cleanup job. - -Can be run as a cronjob to clean out old data from the database (only expired -sessions at the moment). -""" - -from django_extensions.management.jobs import DailyJob - - -class Job(DailyJob): - help = "Django Daily Cleanup Job" - - def execute(self): - from django.core import management - management.call_command("cleanup") diff --git a/awx/lib/site-packages/django_extensions/jobs/hourly/__init__.py b/awx/lib/site-packages/django_extensions/jobs/hourly/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/jobs/minutely/__init__.py b/awx/lib/site-packages/django_extensions/jobs/minutely/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/jobs/monthly/__init__.py b/awx/lib/site-packages/django_extensions/jobs/monthly/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/jobs/weekly/__init__.py b/awx/lib/site-packages/django_extensions/jobs/weekly/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/jobs/yearly/__init__.py b/awx/lib/site-packages/django_extensions/jobs/yearly/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/locale/cs/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/cs/LC_MESSAGES/django.mo deleted file mode 100644 index c2635d7ec1..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/cs/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/cs/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/cs/LC_MESSAGES/django.po deleted file mode 100644 index 0bf050e7a4..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/cs/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:42+0100\n" -"PO-Revision-Date: 2011-02-02 10:42+0000\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: cs\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" - -#: db/models.py:15 -msgid "created" -msgstr "" - -#: db/models.py:16 -msgid "modified" -msgstr "" - -#: db/models.py:26 -msgid "title" -msgstr "" - -#: db/models.py:27 -msgid "slug" -msgstr "" - -#: db/models.py:28 -msgid "description" -msgstr "" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "" diff --git a/awx/lib/site-packages/django_extensions/locale/da/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/da/LC_MESSAGES/django.mo deleted file mode 100644 index 1972c4f810..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/da/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/da/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/da/LC_MESSAGES/django.po deleted file mode 100644 index 42e323e935..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/da/LC_MESSAGES/django.po +++ /dev/null @@ -1,79 +0,0 @@ -# django_extentions in Danish. -# django_extensions pÃ¥ Dansk. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# Michael Lind Mortensen <illio@cs.au.dk>, 2009. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:42+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "og" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"Brug feltet til venstre til at lave %(model_name)s lookups i felterne %" -"(field_list)s." - -#: db/models.py:15 -msgid "created" -msgstr "skabt" - -#: db/models.py:16 -msgid "modified" -msgstr "ændret" - -#: db/models.py:26 -msgid "title" -msgstr "titel" - -#: db/models.py:27 -msgid "slug" -msgstr "slug" - -#: db/models.py:28 -msgid "description" -msgstr "beskrivelse" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Lookup" diff --git a/awx/lib/site-packages/django_extensions/locale/de/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/de/LC_MESSAGES/django.mo deleted file mode 100644 index 6367477a60..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/de/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/de/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/de/LC_MESSAGES/django.po deleted file mode 100644 index 81a35db99e..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/de/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:42+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "und" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"Das linke Feld benutzen, um %(model_name)s Abfragen in den Feldern %" -"(field_list)s durchführen." - -#: db/models.py:15 -msgid "created" -msgstr "erstellt" - -#: db/models.py:16 -msgid "modified" -msgstr "geändert" - -#: db/models.py:26 -msgid "title" -msgstr "Titel" - -#: db/models.py:27 -msgid "slug" -msgstr "Slug" - -#: db/models.py:28 -msgid "description" -msgstr "Beschreibung" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Inaktiv" - -#: db/models.py:51 -msgid "Active" -msgstr "Aktiv" - -#: db/models.py:53 -msgid "status" -msgstr "Status" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "Leer lassen für sofortige Aktivierung" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "Leer lassen für unbefristete Aktivierung" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "%s ist kein urlpattern Objekt" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Abfrage" diff --git a/awx/lib/site-packages/django_extensions/locale/el/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/el/LC_MESSAGES/django.mo deleted file mode 100644 index de23560b7e..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/el/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/el/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/el/LC_MESSAGES/django.po deleted file mode 100644 index 19355db51d..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/el/LC_MESSAGES/django.po +++ /dev/null @@ -1,79 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:42+0100\n" -"PO-Revision-Date: 2011-02-02 10:38+0000\n" -"Last-Translator: Jannis <jannis@leidel.info>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: el\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "και" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"ΧÏησιμοποίησε το αÏιστεÏÏŒ πεδίο για να κάνεις αναζήτηση του %(model_name)s " -"με βάσει τα πεδία %(field_list)s." - -#: db/models.py:15 -msgid "created" -msgstr "δημιουÏγήθηκε" - -#: db/models.py:16 -msgid "modified" -msgstr "Ï„Ïοποποιήθηκε" - -#: db/models.py:26 -msgid "title" -msgstr "τίτλος" - -#: db/models.py:27 -msgid "slug" -msgstr "μίνι-όνομα" - -#: db/models.py:28 -msgid "description" -msgstr "πεÏιγÏαφή" - -#: db/models.py:50 -msgid "Inactive" -msgstr "ανενεÏγό" - -#: db/models.py:51 -msgid "Active" -msgstr "ΕνεÏγό" - -#: db/models.py:53 -msgid "status" -msgstr "κατάσταση" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "αφήστε άδειο για άμεση ενεÏγοποίηση" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "αφήστε άδειο για αόÏιστη ενεÏγοποίηση" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "% s δεν φαίνεται να είναι ένα αντικείμενο urlpattern" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Αναζήτηση" diff --git a/awx/lib/site-packages/django_extensions/locale/en/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/en/LC_MESSAGES/django.mo deleted file mode 100644 index 4ed8824d31..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/en/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/en/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/en/LC_MESSAGES/django.po deleted file mode 100644 index 8fd54f3259..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/en/LC_MESSAGES/django.po +++ /dev/null @@ -1,76 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:42+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" - -#: db/models.py:15 -msgid "created" -msgstr "" - -#: db/models.py:16 -msgid "modified" -msgstr "" - -#: db/models.py:26 -msgid "title" -msgstr "" - -#: db/models.py:27 -msgid "slug" -msgstr "" - -#: db/models.py:28 -msgid "description" -msgstr "" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "" diff --git a/awx/lib/site-packages/django_extensions/locale/es/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/es/LC_MESSAGES/django.mo deleted file mode 100644 index 8ff3f06505..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/es/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/es/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/es/LC_MESSAGES/django.po deleted file mode 100644 index e85b113afc..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/es/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "y" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"Utilice el campo de la izquierda para hacer búsquedas en los campos %" -"(field_list)s de %(model_name)s." - -#: db/models.py:15 -msgid "created" -msgstr "creado" - -#: db/models.py:16 -msgid "modified" -msgstr "modificado" - -#: db/models.py:26 -msgid "title" -msgstr "titulo" - -#: db/models.py:27 -msgid "slug" -msgstr "slug" - -#: db/models.py:28 -msgid "description" -msgstr "descripción" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Inactivo" - -#: db/models.py:51 -msgid "Active" -msgstr "Activo" - -#: db/models.py:53 -msgid "status" -msgstr "estado" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "mantener vacío para una activación inmediata" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "deje vacío para mantener la activación indefinida" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "% s no parece ser un objeto urlpattern" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Buscar" diff --git a/awx/lib/site-packages/django_extensions/locale/et/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/et/LC_MESSAGES/django.mo deleted file mode 100644 index caac6b973f..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/et/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/et/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/et/LC_MESSAGES/django.po deleted file mode 100644 index 8a3c51a34c..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/et/LC_MESSAGES/django.po +++ /dev/null @@ -1,75 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "ja" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" - -#: db/models.py:15 -msgid "created" -msgstr "" - -#: db/models.py:16 -msgid "modified" -msgstr "" - -#: db/models.py:26 -msgid "title" -msgstr "" - -#: db/models.py:27 -msgid "slug" -msgstr "" - -#: db/models.py:28 -msgid "description" -msgstr "" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "" diff --git a/awx/lib/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.mo deleted file mode 100644 index bc4e1cd7c3..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.po deleted file mode 100644 index 02a00a07ba..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.po +++ /dev/null @@ -1,81 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# mathiasuk, 2014 -# mathiasuk, 2014 -# stevandoh <stevandoh@gmail.com>, 2013 -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:42+0100\n" -"PO-Revision-Date: 2014-01-11 11:14+0000\n" -"Last-Translator: mathiasuk\n" -"Language-Team: French (http://www.transifex.com/projects/p/django-extensions/language/fr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "et" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields " -"%(field_list)s." -msgstr "Utilisez le champ de gauche pour faire des recheres de %(model_name)s dans les champs %(field_list)s." - -#: db/models.py:15 -msgid "created" -msgstr "créé" - -#: db/models.py:16 -msgid "modified" -msgstr "mis à jour" - -#: db/models.py:26 -msgid "title" -msgstr "titre" - -#: db/models.py:27 -msgid "slug" -msgstr "slug" - -#: db/models.py:28 -msgid "description" -msgstr "description" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Inactif" - -#: db/models.py:51 -msgid "Active" -msgstr "Actif" - -#: db/models.py:53 -msgid "status" -msgstr "état" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "laisser vide pour activation immédiate" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "laisser vide pour activation indéterminée" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "%s ne semble pas etre un object urlpattern" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Recherche" diff --git a/awx/lib/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.mo deleted file mode 100644 index 2f98573ee2..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.po deleted file mode 100644 index 50ec58e476..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "és" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"Használd a baloldali mezÅ‘t hogy keress a %(model_name)s %(field_list)s. " -"mezÅ‘iben" - -#: db/models.py:15 -msgid "created" -msgstr "létrehozva" - -#: db/models.py:16 -msgid "modified" -msgstr "módosítva" - -#: db/models.py:26 -msgid "title" -msgstr "Cím" - -#: db/models.py:27 -msgid "slug" -msgstr "Slug" - -#: db/models.py:28 -msgid "description" -msgstr "Leírás" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Inaktív" - -#: db/models.py:51 -msgid "Active" -msgstr "Aktív" - -#: db/models.py:53 -msgid "status" -msgstr "Ãllapot" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "Üresen hagyni azonnali aktiváláshoz" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "Üresen hagyni korlátlan aktiváláshoz" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "Úgy néz ki hogy %s nem egy urlpattern objektum" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Lekérdezés" diff --git a/awx/lib/site-packages/django_extensions/locale/it/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/it/LC_MESSAGES/django.mo deleted file mode 100644 index c7fa82971b..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/it/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/it/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/it/LC_MESSAGES/django.po deleted file mode 100644 index 14af204353..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/it/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "e" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"Utilizzare il campo a sinistra per fare ricerche nei campi %(field_list)s " -"del modello %(model_name)s." - -#: db/models.py:15 -msgid "created" -msgstr "creato" - -#: db/models.py:16 -msgid "modified" -msgstr "modificato" - -#: db/models.py:26 -msgid "title" -msgstr "titolo" - -#: db/models.py:27 -msgid "slug" -msgstr "slug" - -#: db/models.py:28 -msgid "description" -msgstr "descrizione" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Inattivo" - -#: db/models.py:51 -msgid "Active" -msgstr "Attivo" - -#: db/models.py:53 -msgid "status" -msgstr "stato" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "lasciare vuoto per attivazione immediata" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "lasciare vuoti per attivazione indefinita" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "% s non sembra essere un oggetto urlPattern" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Ricerca" diff --git a/awx/lib/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.mo deleted file mode 100644 index 95b488d8cf..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.po deleted file mode 100644 index ed42a0e180..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "ã¨" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"%(field_list)s フィールドã®å†…容ã‹ã‚‰ %(model_name)s を検索ã™ã‚‹ã«ã¯å·¦ã®ãƒ•ィール" -"ドを使用ã—ã¦ä¸‹ã•ã„。" - -#: db/models.py:15 -msgid "created" -msgstr "ä½œæˆæ—¥æ™‚" - -#: db/models.py:16 -msgid "modified" -msgstr "変更日時" - -#: db/models.py:26 -msgid "title" -msgstr "タイトル" - -#: db/models.py:27 -msgid "slug" -msgstr "スラグ" - -#: db/models.py:28 -msgid "description" -msgstr "説明" - -#: db/models.py:50 -msgid "Inactive" -msgstr "éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–" - -#: db/models.py:51 -msgid "Active" -msgstr "アクティブ" - -#: db/models.py:53 -msgid "status" -msgstr "ステータス" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "ã™ãã«æœ‰åŠ¹åŒ–ã™ã‚‹å ´åˆã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¦ä¸‹ã•ã„" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "無期é™ã«æœ‰åŠ¹åŒ–ã—ã¦ãŠãå ´åˆã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¦ä¸‹ã•ã„" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "%s 㯠urlpattern オブジェクトã§ã¯ãªã„よã†ã§ã™" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "検索" diff --git a/awx/lib/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.mo deleted file mode 100644 index bf43c6447f..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.po deleted file mode 100644 index 446e142866..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Zbigniew Siciarz <antyqjon@gmail.com>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "i" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"Użyj pola po lewej, by wyszukać pola %(field_list)s w modelu %(model_name)s." - -#: db/models.py:15 -msgid "created" -msgstr "utworzony" - -#: db/models.py:16 -msgid "modified" -msgstr "zmodyfikowany" - -#: db/models.py:26 -msgid "title" -msgstr "tytuÅ‚" - -#: db/models.py:27 -msgid "slug" -msgstr "slug" - -#: db/models.py:28 -msgid "description" -msgstr "opis" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Nieaktywny" - -#: db/models.py:51 -msgid "Active" -msgstr "Aktywny" - -#: db/models.py:53 -msgid "status" -msgstr "stan" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "pozostaw puste, by aktywować od razu" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "pozostaw puste, by nie definiować daty deaktywacji" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "%s nie jest obiektem typu urlpattern" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Szukaj" diff --git a/awx/lib/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.mo deleted file mode 100644 index 7f9a633ede..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.po deleted file mode 100644 index eb6c68b4b4..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: 2010-11-15 22:06-0300\n" -"Last-Translator: Fernando Silva <fernand at liquuid dot net>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "e" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"Use o campo esquerdo para fazer com que o modelo %(model_name)s procure nos " -"campos %(field_list)s." - -#: db/models.py:15 -msgid "created" -msgstr "criado" - -#: db/models.py:16 -msgid "modified" -msgstr "modificado" - -#: db/models.py:26 -msgid "title" -msgstr "título" - -#: db/models.py:27 -msgid "slug" -msgstr "slug" - -#: db/models.py:28 -msgid "description" -msgstr "descrição" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Inativo" - -#: db/models.py:51 -msgid "Active" -msgstr "Ativo" - -#: db/models.py:53 -msgid "status" -msgstr "estado" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "deixe vazio para ativação imediata" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "deixe vazio para ativação por tempo indeterminado" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "%s não parece ser um objeto urlpattern" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Busca" diff --git a/awx/lib/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.mo deleted file mode 100644 index 0282342d4f..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.po deleted file mode 100644 index c5e12b0bd1..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.po +++ /dev/null @@ -1,79 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# Claudemiro Alves Feitosa Neto <dimiro1@gmail.com>, 2013. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-09-13 22:49-0300\n" -"PO-Revision-Date: 2013-09-13 22:49-0300\n" -"Last-Translator: Claudemiro Alves Feitosa <dimiro1@gmail.com>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: admin/__init__.py:128 -msgid "and" -msgstr "e" - -#: admin/__init__.py:130 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "Use o campo da esquerda para fazer com que o modelo %(model_name)s procure nos " -"campos %(field_list)s" - -#: db/models.py:22 mongodb/models.py:17 -msgid "created" -msgstr "criado" - -#: db/models.py:23 mongodb/models.py:18 -msgid "modified" -msgstr "modificado" - -#: db/models.py:36 mongodb/models.py:29 -msgid "title" -msgstr "título" - -#: db/models.py:37 mongodb/models.py:30 -msgid "slug" -msgstr "slug" - -#: db/models.py:38 mongodb/models.py:31 -msgid "description" -msgstr "descrição" - -#: db/models.py:63 mongodb/models.py:55 -msgid "Inactive" -msgstr "Inativo" - -#: db/models.py:64 mongodb/models.py:56 -msgid "Active" -msgstr "Ativo" - -#: db/models.py:66 mongodb/models.py:58 -msgid "status" -msgstr "status" - -#: db/models.py:67 mongodb/models.py:59 -msgid "keep empty for an immediate activation" -msgstr "deixe vazio para uma ativação imediata" - -#: db/models.py:68 mongodb/models.py:60 -msgid "keep empty for indefinite activation" -msgstr "deixe vazio para ativação por tempo indeterminado" - -#: mongodb/fields/__init__.py:24 -#, python-format -msgid "String (up to %(max_length)s)" -msgstr "Cadeia de Caracteres (até %(max_length)s)" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Busca" diff --git a/awx/lib/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.mo deleted file mode 100644 index 00626a0d2b..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.po deleted file mode 100644 index 8f4180ed1b..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.po +++ /dev/null @@ -1,80 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: 2011-02-02 10:38+0000\n" -"Last-Translator: Jannis <jannis@leidel.info>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ro\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " -"20)) ? 1 : 2)\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "È™i" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" -"FoloseÈ™te câmpul din stânga pentru a efectua căutări de %(model_name)s în " -"câmpurile %(field_list)s." - -#: db/models.py:15 -msgid "created" -msgstr "creat" - -#: db/models.py:16 -msgid "modified" -msgstr "modificat" - -#: db/models.py:26 -msgid "title" -msgstr "Titlu" - -#: db/models.py:27 -msgid "slug" -msgstr "Slug" - -#: db/models.py:28 -msgid "description" -msgstr "Descriere" - -#: db/models.py:50 -msgid "Inactive" -msgstr "Inactiv" - -#: db/models.py:51 -msgid "Active" -msgstr "Activ" - -#: db/models.py:53 -msgid "status" -msgstr "Stare" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "A se lăsa gol pentru activare imediată" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "A se lăsa gol pentru activare nelimitată" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "%s nu pare să fie un obiect urlpattern" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "Căutare" diff --git a/awx/lib/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.mo deleted file mode 100644 index c02cf9cdb3..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.po deleted file mode 100644 index fd0bd4d26a..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.po +++ /dev/null @@ -1,78 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: 2011-02-02 10:42+0000\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ru\n" -"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" -"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" - -#: db/models.py:15 -msgid "created" -msgstr "" - -#: db/models.py:16 -msgid "modified" -msgstr "" - -#: db/models.py:26 -msgid "title" -msgstr "" - -#: db/models.py:27 -msgid "slug" -msgstr "" - -#: db/models.py:28 -msgid "description" -msgstr "" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "" diff --git a/awx/lib/site-packages/django_extensions/locale/sk/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/sk/LC_MESSAGES/django.mo deleted file mode 100644 index 3fdc5cfe4e..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/sk/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/sk/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/sk/LC_MESSAGES/django.po deleted file mode 100644 index 33964168ae..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/sk/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: 2011-02-02 10:42+0000\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sk\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" - -#: db/models.py:15 -msgid "created" -msgstr "" - -#: db/models.py:16 -msgid "modified" -msgstr "" - -#: db/models.py:26 -msgid "title" -msgstr "" - -#: db/models.py:27 -msgid "slug" -msgstr "" - -#: db/models.py:28 -msgid "description" -msgstr "" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "" diff --git a/awx/lib/site-packages/django_extensions/locale/tr/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/tr/LC_MESSAGES/django.mo deleted file mode 100644 index 800d1fe154..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/tr/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/tr/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/tr/LC_MESSAGES/django.po deleted file mode 100644 index 45e600a16d..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/tr/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: 2011-02-02 10:42+0000\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: tr\n" -"Plural-Forms: nplurals=1; plural=0\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" - -#: db/models.py:15 -msgid "created" -msgstr "" - -#: db/models.py:16 -msgid "modified" -msgstr "" - -#: db/models.py:26 -msgid "title" -msgstr "" - -#: db/models.py:27 -msgid "slug" -msgstr "" - -#: db/models.py:28 -msgid "description" -msgstr "" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "" diff --git a/awx/lib/site-packages/django_extensions/locale/zh_CN/LC_MESSAGES/django.mo b/awx/lib/site-packages/django_extensions/locale/zh_CN/LC_MESSAGES/django.mo deleted file mode 100644 index 5276f0c207..0000000000 Binary files a/awx/lib/site-packages/django_extensions/locale/zh_CN/LC_MESSAGES/django.mo and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/locale/zh_CN/LC_MESSAGES/django.po b/awx/lib/site-packages/django_extensions/locale/zh_CN/LC_MESSAGES/django.po deleted file mode 100644 index 93547531e1..0000000000 --- a/awx/lib/site-packages/django_extensions/locale/zh_CN/LC_MESSAGES/django.po +++ /dev/null @@ -1,77 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: django-extensions\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-02 11:43+0100\n" -"PO-Revision-Date: 2011-02-02 10:42+0000\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"Plural-Forms: nplurals=1; plural=0\n" - -#: admin/__init__.py:121 -msgid "and" -msgstr "" - -#: admin/__init__.py:123 -#, python-format -msgid "" -"Use the left field to do %(model_name)s lookups in the fields %(field_list)s." -msgstr "" - -#: db/models.py:15 -msgid "created" -msgstr "" - -#: db/models.py:16 -msgid "modified" -msgstr "" - -#: db/models.py:26 -msgid "title" -msgstr "" - -#: db/models.py:27 -msgid "slug" -msgstr "" - -#: db/models.py:28 -msgid "description" -msgstr "" - -#: db/models.py:50 -msgid "Inactive" -msgstr "" - -#: db/models.py:51 -msgid "Active" -msgstr "" - -#: db/models.py:53 -msgid "status" -msgstr "" - -#: db/models.py:56 -msgid "keep empty for an immediate activation" -msgstr "" - -#: db/models.py:58 -msgid "keep empty for indefinite activation" -msgstr "" - -#: management/commands/show_urls.py:34 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "" - -#: templates/django_extensions/widgets/foreignkey_searchinput.html:4 -msgid "Lookup" -msgstr "" diff --git a/awx/lib/site-packages/django_extensions/management/__init__.py b/awx/lib/site-packages/django_extensions/management/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/management/base.py b/awx/lib/site-packages/django_extensions/management/base.py deleted file mode 100644 index 6da68b234c..0000000000 --- a/awx/lib/site-packages/django_extensions/management/base.py +++ /dev/null @@ -1,53 +0,0 @@ -import sys - -from django.core.management.base import BaseCommand -from django.utils.log import getLogger - - -logger = getLogger('django.commands') - - -class LoggingBaseCommand(BaseCommand): - """ - A subclass of BaseCommand that logs run time errors to `django.commands`. - To use this, create a management command subclassing LoggingBaseCommand: - - from django_extensions.management.base import LoggingBaseCommand - - class Command(LoggingBaseCommand): - help = 'Test error' - - def handle(self, *args, **options): - raise Exception - - - And then define a logging handler in settings.py: - - LOGGING = { - ... # Other stuff here - - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - }, - }, - 'loggers': { - 'django.commands': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': False, - }, - } - - } - - """ - - def execute(self, *args, **options): - try: - super(LoggingBaseCommand, self).execute(*args, **options) - except Exception as e: - logger.error(e, exc_info=sys.exc_info(), extra={'status_code': 500}) - raise diff --git a/awx/lib/site-packages/django_extensions/management/color.py b/awx/lib/site-packages/django_extensions/management/color.py deleted file mode 100644 index ccd84069d0..0000000000 --- a/awx/lib/site-packages/django_extensions/management/color.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Sets up the terminal color scheme. -""" - -from django.core.management import color -from django.utils import termcolors - - -def color_style(): - style = color.color_style() - if color.supports_color(): - style.INFO = termcolors.make_style(fg='green') - style.WARN = termcolors.make_style(fg='yellow') - style.BOLD = termcolors.make_style(opts=('bold',)) - style.URL = termcolors.make_style(fg='green', opts=('bold',)) - style.MODULE = termcolors.make_style(fg='yellow') - style.MODULE_NAME = termcolors.make_style(opts=('bold',)) - style.URL_NAME = termcolors.make_style(fg='red') - return style diff --git a/awx/lib/site-packages/django_extensions/management/commands/__init__.py b/awx/lib/site-packages/django_extensions/management/commands/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/management/commands/clean_pyc.py b/awx/lib/site-packages/django_extensions/management/commands/clean_pyc.py deleted file mode 100644 index b409ddaed8..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/clean_pyc.py +++ /dev/null @@ -1,37 +0,0 @@ -from django.core.management.base import NoArgsCommand -from django_extensions.management.utils import get_project_root -from optparse import make_option -from os.path import join as _j -import os - - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option('--optimize', '-o', '-O', action='store_true', dest='optimize', - help='Remove optimized python bytecode files'), - make_option('--path', '-p', action='store', dest='path', - help='Specify path to recurse into'), - ) - help = "Removes all python bytecode compiled files from the project." - - requires_model_validation = False - - def handle_noargs(self, **options): - project_root = options.get("path", None) - if not project_root: - project_root = get_project_root() - exts = options.get("optimize", False) and [".pyc", ".pyo"] or [".pyc"] - verbose = int(options.get("verbosity", 1)) - - if verbose > 1: - print("Project Root: %s" % project_root) - - for root, dirs, files in os.walk(project_root): - for file in files: - ext = os.path.splitext(file)[1] - if ext in exts: - full_path = _j(root, file) - if verbose > 1: - print(full_path) - os.remove(full_path) - diff --git a/awx/lib/site-packages/django_extensions/management/commands/compile_pyc.py b/awx/lib/site-packages/django_extensions/management/commands/compile_pyc.py deleted file mode 100644 index f978d3e37b..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/compile_pyc.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.core.management.base import NoArgsCommand -from django_extensions.management.utils import get_project_root -from optparse import make_option -from os.path import join as _j -import py_compile -import os - - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option('--path', '-p', action='store', dest='path', help='Specify path to recurse into'), - ) - help = "Compile python bytecode files for the project." - - requires_model_validation = False - - def handle_noargs(self, **options): - project_root = options.get("path", None) - if not project_root: - project_root = get_project_root() - verbose = int(options.get("verbosity", 1)) > 1 - - for root, dirs, files in os.walk(project_root): - for file in files: - ext = os.path.splitext(file)[1] - if ext == ".py": - full_path = _j(root, file) - if verbose: - print("%sc" % full_path) - py_compile.compile(full_path) diff --git a/awx/lib/site-packages/django_extensions/management/commands/create_app.py b/awx/lib/site-packages/django_extensions/management/commands/create_app.py deleted file mode 100644 index a27913c86a..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/create_app.py +++ /dev/null @@ -1,138 +0,0 @@ -import os -import re -import sys -import django_extensions -from django.conf import settings -from django.db import connection -from django.core.management.base import CommandError, LabelCommand -from django.template import Template, Context -from django_extensions.settings import REPLACEMENTS -from django_extensions.utils.dia2django import dia2django -from django_extensions.management.utils import _make_writeable -from optparse import make_option - - -class Command(LabelCommand): - option_list = LabelCommand.option_list + ( - make_option('--template', '-t', action='store', dest='app_template', - help='The path to the app template'), - make_option('--parent_path', '-p', action='store', dest='parent_path', - help='The parent path of the application to be created'), - make_option('-d', action='store_true', dest='dia_parse', - help='Generate model.py and admin.py from [APP_NAME].dia file'), - make_option('--diagram', action='store', dest='dia_path', - help='The diagram path of the app to be created. -d is implied'), - ) - - help = ("Creates an application directory structure for the specified application name.") - args = "APP_NAME" - label = 'application name' - - requires_model_validation = False - can_import_settings = True - - def handle_label(self, label, **options): - project_dir = os.getcwd() - project_name = os.path.split(project_dir)[-1] - app_name = label - app_template = options.get('app_template') or os.path.join(django_extensions.__path__[0], 'conf', 'app_template') - app_dir = os.path.join(options.get('parent_path') or project_dir, app_name) - dia_path = options.get('dia_path') or os.path.join(project_dir, '%s.dia' % app_name) - - if not os.path.exists(app_template): - raise CommandError("The template path, %r, does not exist." % app_template) - - if not re.search(r'^\w+$', label): - raise CommandError("%r is not a valid application name. Please use only numbers, letters and underscores." % label) - - dia_parse = options.get('dia_path') or options.get('dia_parse') - if dia_parse: - if not os.path.exists(dia_path): - raise CommandError("The diagram path, %r, does not exist." % dia_path) - if app_name in settings.INSTALLED_APPS: - raise CommandError("The application %s should not be defined in the settings file. Please remove %s now, and add it after using this command." % (app_name, app_name)) - tables = [name for name in connection.introspection.table_names() if name.startswith('%s_' % app_name)] - if tables: - raise CommandError("%r application has tables in the database. Please delete them." % app_name) - - try: - os.makedirs(app_dir) - except OSError as e: - raise CommandError(e) - - copy_template(app_template, app_dir, project_name, app_name) - - if dia_parse: - generate_models_and_admin(dia_path, app_dir, project_name, app_name) - print("Application %r created." % app_name) - print("Please add now %r and any other dependent application in settings.INSTALLED_APPS, and run 'manage syncdb'" % app_name) - - -def copy_template(app_template, copy_to, project_name, app_name): - """copies the specified template directory to the copy_to location""" - import shutil - - app_template = os.path.normpath(app_template) - # walks the template structure and copies it - for d, subdirs, files in os.walk(app_template): - relative_dir = d[len(app_template) + 1:] - d_new = os.path.join(copy_to, relative_dir).replace('app_name', app_name) - if relative_dir and not os.path.exists(d_new): - os.mkdir(d_new) - for i, subdir in enumerate(subdirs): - if subdir.startswith('.'): - del subdirs[i] - replacements = {'app_name': app_name, 'project_name': project_name} - replacements.update(REPLACEMENTS) - for f in files: - if f.endswith('.pyc') or f.startswith('.DS_Store'): - continue - path_old = os.path.join(d, f) - path_new = os.path.join(d_new, f.replace('app_name', app_name)) - if os.path.exists(path_new): - path_new = os.path.join(d_new, f) - if os.path.exists(path_new): - continue - if path_new.endswith('.tmpl'): - path_new = path_new[:-5] - fp_old = open(path_old, 'r') - fp_new = open(path_new, 'w') - fp_new.write(Template(fp_old.read()).render(Context(replacements))) - fp_old.close() - fp_new.close() - try: - shutil.copymode(path_old, path_new) - _make_writeable(path_new) - except OSError: - sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new) - - -def generate_models_and_admin(dia_path, app_dir, project_name, app_name): - """Generates the models.py and admin.py files""" - - def format_text(string, indent=False): - """format string in lines of 80 or less characters""" - retval = '' - while string: - line = string[:77] - last_space = line.rfind(' ') - if last_space != -1 and len(string) > 77: - retval += "%s \\\n" % string[:last_space] - string = string[last_space + 1:] - else: - retval += "%s\n" % string - string = '' - if string and indent: - string = ' %s' % string - return retval - - model_path = os.path.join(app_dir, 'models.py') - admin_path = os.path.join(app_dir, 'admin.py') - - models_txt = 'from django.db import models\n' + dia2django(dia_path) - open(model_path, 'w').write(models_txt) - - classes = re.findall('class (\w+)', models_txt) - admin_txt = 'from django.contrib.admin import site, ModelAdmin\n' + format_text('from %s.%s.models import %s' % (project_name, app_name, ', '.join(classes)), indent=True) - admin_txt += format_text('\n\n%s' % '\n'.join(map((lambda t: 'site.register(%s)' % t), classes))) - open(admin_path, 'w').write(admin_txt) diff --git a/awx/lib/site-packages/django_extensions/management/commands/create_command.py b/awx/lib/site-packages/django_extensions/management/commands/create_command.py deleted file mode 100644 index 6339b462a1..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/create_command.py +++ /dev/null @@ -1,73 +0,0 @@ -import os -import sys -from django.core.management.base import AppCommand -from django_extensions.management.utils import _make_writeable -from optparse import make_option - - -class Command(AppCommand): - option_list = AppCommand.option_list + ( - make_option('--name', '-n', action='store', dest='command_name', default='sample', - help='The name to use for the management command'), - make_option('--base', '-b', action='store', dest='base_command', default='Base', - help='The base class used for implementation of this command. Should be one of Base, App, Label, or NoArgs'), - ) - - help = ("Creates a Django management command directory structure for the given app name" - " in the app's directory.") - args = "[appname]" - label = 'application name' - - requires_model_validation = False - # Can't import settings during this command, because they haven't - # necessarily been created. - can_import_settings = True - - def handle_app(self, app, **options): - app_dir = os.path.dirname(app.__file__) - copy_template('command_template', app_dir, options.get('command_name'), '%sCommand' % options.get('base_command')) - - -def copy_template(template_name, copy_to, command_name, base_command): - """copies the specified template directory to the copy_to location""" - import django_extensions - import shutil - - template_dir = os.path.join(django_extensions.__path__[0], 'conf', template_name) - - handle_method = "handle(self, *args, **options)" - if base_command == 'AppCommand': - handle_method = "handle_app(self, app, **options)" - elif base_command == 'LabelCommand': - handle_method = "handle_label(self, label, **options)" - elif base_command == 'NoArgsCommand': - handle_method = "handle_noargs(self, **options)" - - # walks the template structure and copies it - for d, subdirs, files in os.walk(template_dir): - relative_dir = d[len(template_dir) + 1:] - if relative_dir and not os.path.exists(os.path.join(copy_to, relative_dir)): - os.mkdir(os.path.join(copy_to, relative_dir)) - for i, subdir in enumerate(subdirs): - if subdir.startswith('.'): - del subdirs[i] - for f in files: - if f.endswith('.pyc') or f.startswith('.DS_Store'): - continue - path_old = os.path.join(d, f) - path_new = os.path.join(copy_to, relative_dir, f.replace('sample', command_name)) - if os.path.exists(path_new): - path_new = os.path.join(copy_to, relative_dir, f) - if os.path.exists(path_new): - continue - path_new = path_new.rstrip(".tmpl") - fp_old = open(path_old, 'r') - fp_new = open(path_new, 'w') - fp_new.write(fp_old.read().replace('{{ command_name }}', command_name).replace('{{ base_command }}', base_command).replace('{{ handle_method }}', handle_method)) - fp_old.close() - fp_new.close() - try: - shutil.copymode(path_old, path_new) - _make_writeable(path_new) - except OSError: - sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new) diff --git a/awx/lib/site-packages/django_extensions/management/commands/create_jobs.py b/awx/lib/site-packages/django_extensions/management/commands/create_jobs.py deleted file mode 100644 index c0ce48b3f4..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/create_jobs.py +++ /dev/null @@ -1,56 +0,0 @@ -import os -import sys -from django.core.management.base import AppCommand -from django_extensions.management.utils import _make_writeable - - -class Command(AppCommand): - help = ("Creates a Django jobs command directory structure for the given app name in the current directory.") - args = "[appname]" - label = 'application name' - - requires_model_validation = False - # Can't import settings during this command, because they haven't - # necessarily been created. - can_import_settings = True - - def handle_app(self, app, **options): - app_dir = os.path.dirname(app.__file__) - copy_template('jobs_template', app_dir) - - -def copy_template(template_name, copy_to): - """copies the specified template directory to the copy_to location""" - import django_extensions - import shutil - - template_dir = os.path.join(django_extensions.__path__[0], 'conf', template_name) - - # walks the template structure and copies it - for d, subdirs, files in os.walk(template_dir): - relative_dir = d[len(template_dir) + 1:] - if relative_dir and not os.path.exists(os.path.join(copy_to, relative_dir)): - os.mkdir(os.path.join(copy_to, relative_dir)) - for i, subdir in enumerate(subdirs): - if subdir.startswith('.'): - del subdirs[i] - for f in files: - if f.endswith('.pyc') or f.startswith('.DS_Store'): - continue - path_old = os.path.join(d, f) - path_new = os.path.join(copy_to, relative_dir, f) - if os.path.exists(path_new): - path_new = os.path.join(copy_to, relative_dir, f) - if os.path.exists(path_new): - continue - path_new = path_new.rstrip(".tmpl") - fp_old = open(path_old, 'r') - fp_new = open(path_new, 'w') - fp_new.write(fp_old.read()) - fp_old.close() - fp_new.close() - try: - shutil.copymode(path_old, path_new) - _make_writeable(path_new) - except OSError: - sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new) diff --git a/awx/lib/site-packages/django_extensions/management/commands/create_template_tags.py b/awx/lib/site-packages/django_extensions/management/commands/create_template_tags.py deleted file mode 100644 index d8f33c6cc0..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/create_template_tags.py +++ /dev/null @@ -1,68 +0,0 @@ -import os -import sys -from django.core.management.base import AppCommand -from django_extensions.management.utils import _make_writeable -from optparse import make_option - - -class Command(AppCommand): - option_list = AppCommand.option_list + ( - make_option('--name', '-n', action='store', dest='tag_library_name', default='appname_tags', - help='The name to use for the template tag base name. Defaults to `appname`_tags.'), - make_option('--base', '-b', action='store', dest='base_command', default='Base', - help='The base class used for implementation of this command. Should be one of Base, App, Label, or NoArgs'), - ) - - help = ("Creates a Django template tags directory structure for the given app name" - " in the apps's directory") - args = "[appname]" - label = 'application name' - - requires_model_validation = False - # Can't import settings during this command, because they haven't - # necessarily been created. - can_import_settings = True - - def handle_app(self, app, **options): - app_dir = os.path.dirname(app.__file__) - tag_library_name = options.get('tag_library_name') - if tag_library_name == 'appname_tags': - tag_library_name = '%s_tags' % os.path.basename(app_dir) - copy_template('template_tags_template', app_dir, tag_library_name) - - -def copy_template(template_name, copy_to, tag_library_name): - """copies the specified template directory to the copy_to location""" - import django_extensions - import shutil - - template_dir = os.path.join(django_extensions.__path__[0], 'conf', template_name) - - # walks the template structure and copies it - for d, subdirs, files in os.walk(template_dir): - relative_dir = d[len(template_dir) + 1:] - if relative_dir and not os.path.exists(os.path.join(copy_to, relative_dir)): - os.mkdir(os.path.join(copy_to, relative_dir)) - for i, subdir in enumerate(subdirs): - if subdir.startswith('.'): - del subdirs[i] - for f in files: - if f.endswith('.pyc') or f.startswith('.DS_Store'): - continue - path_old = os.path.join(d, f) - path_new = os.path.join(copy_to, relative_dir, f.replace('sample', tag_library_name)) - if os.path.exists(path_new): - path_new = os.path.join(copy_to, relative_dir, f) - if os.path.exists(path_new): - continue - path_new = path_new.rstrip(".tmpl") - fp_old = open(path_old, 'r') - fp_new = open(path_new, 'w') - fp_new.write(fp_old.read()) - fp_old.close() - fp_new.close() - try: - shutil.copymode(path_old, path_new) - _make_writeable(path_new) - except OSError: - sys.stderr.write("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new) diff --git a/awx/lib/site-packages/django_extensions/management/commands/describe_form.py b/awx/lib/site-packages/django_extensions/management/commands/describe_form.py deleted file mode 100644 index 9e6d46449d..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/describe_form.py +++ /dev/null @@ -1,66 +0,0 @@ -from django.core.management.base import LabelCommand, CommandError -from django.utils.encoding import force_unicode - - -class Command(LabelCommand): - help = "Outputs the specified model as a form definition to the shell." - args = "[app.model]" - label = 'application name and model name' - - requires_model_validation = True - can_import_settings = True - - def handle_label(self, label, **options): - return describe_form(label) - - -def describe_form(label, fields=None): - """ - Returns a string describing a form based on the model - """ - from django.db.models.loading import get_model - try: - app_name, model_name = label.split('.')[-2:] - except (IndexError, ValueError): - raise CommandError("Need application and model name in the form: appname.model") - model = get_model(app_name, model_name) - - opts = model._meta - field_list = [] - for f in opts.fields + opts.many_to_many: - if not f.editable: - continue - if fields and not f.name in fields: - continue - formfield = f.formfield() - if not '__dict__' in dir(formfield): - continue - attrs = {} - valid_fields = ['required', 'initial', 'max_length', 'min_length', 'max_value', 'min_value', 'max_digits', 'decimal_places', 'choices', 'help_text', 'label'] - for k, v in formfield.__dict__.items(): - if k in valid_fields and v is not None: - # ignore defaults, to minimize verbosity - if k == 'required' and v: - continue - if k == 'help_text' and not v: - continue - if k == 'widget': - attrs[k] = v.__class__ - elif k in ['help_text', 'label']: - attrs[k] = force_unicode(v).strip() - else: - attrs[k] = v - - params = ', '.join(['%s=%r' % (k, v) for k, v in attrs.items()]) - field_list.append(' %(field_name)s = forms.%(field_type)s(%(params)s)' % { - 'field_name': f.name, - 'field_type': formfield.__class__.__name__, - 'params': params - }) - return ''' -from django import forms -from %(app_name)s.models import %(object_name)s - -class %(object_name)sForm(forms.Form): -%(field_list)s -''' % {'app_name': app_name, 'object_name': opts.object_name, 'field_list': '\n'.join(field_list)} diff --git a/awx/lib/site-packages/django_extensions/management/commands/dumpscript.py b/awx/lib/site-packages/django_extensions/management/commands/dumpscript.py deleted file mode 100644 index d00fb567d3..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/dumpscript.py +++ /dev/null @@ -1,762 +0,0 @@ -# -*- coding: UTF-8 -*- -""" - Title: Dumpscript management command - Project: Hardytools (queryset-refactor version) - Author: Will Hardy (http://willhardy.com.au) - Date: June 2008 - Usage: python manage.py dumpscript appname > scripts/scriptname.py - $Revision: 217 $ - -Description: - Generates a Python script that will repopulate the database using objects. - The advantage of this approach is that it is easy to understand, and more - flexible than directly populating the database, or using XML. - - * It also allows for new defaults to take effect and only transfers what is - needed. - * If a new database schema has a NEW ATTRIBUTE, it is simply not - populated (using a default value will make the transition smooth :) - * If a new database schema REMOVES AN ATTRIBUTE, it is simply ignored - and the data moves across safely (I'm assuming we don't want this - attribute anymore. - * Problems may only occur if there is a new model and is now a required - ForeignKey for an existing model. But this is easy to fix by editing the - populate script. Half of the job is already done as all ForeingKey - lookups occur though the locate_object() function in the generated script. - -Improvements: - See TODOs and FIXMEs scattered throughout :-) - -""" - -import sys -import datetime -import six - -import django -from django.db.models import AutoField, BooleanField, FileField, ForeignKey, DateField, DateTimeField -from django.core.exceptions import ObjectDoesNotExist -from django.core.management.base import BaseCommand - -# conditional import, force_unicode was renamed in Django 1.5 -from django.contrib.contenttypes.models import ContentType -try: - from django.utils.encoding import smart_unicode, force_unicode # NOQA -except ImportError: - from django.utils.encoding import smart_text as smart_unicode, force_text as force_unicode # NOQA - - -def orm_item_locator(orm_obj): - """ - This function is called every time an object that will not be exported is required. - Where orm_obj is the referred object. - We postpone the lookup to locate_object() which will be run on the generated script - - """ - - the_class = orm_obj._meta.object_name - original_class = the_class - pk_name = orm_obj._meta.pk.name - original_pk_name = pk_name - pk_value = getattr(orm_obj, pk_name) - - while hasattr(pk_value, "_meta") and hasattr(pk_value._meta, "pk") and hasattr(pk_value._meta.pk, "name"): - the_class = pk_value._meta.object_name - pk_name = pk_value._meta.pk.name - pk_value = getattr(pk_value, pk_name) - - clean_dict = make_clean_dict(orm_obj.__dict__) - - for key in clean_dict: - v = clean_dict[key] - if v is not None and not isinstance(v, (six.string_types, six.integer_types, float, datetime.datetime)): - clean_dict[key] = six.u("%s" % v) - - output = """ importer.locate_object(%s, "%s", %s, "%s", %s, %s ) """ % ( - original_class, original_pk_name, - the_class, pk_name, pk_value, clean_dict - ) - return output - - -class Command(BaseCommand): - help = 'Dumps the data as a customised python script.' - args = '[appname ...]' - - def handle(self, *app_labels, **options): - - # Get the models we want to export - models = get_models(app_labels) - - # A dictionary is created to keep track of all the processed objects, - # so that foreign key references can be made using python variable names. - # This variable "context" will be passed around like the town bicycle. - context = {} - - # Create a dumpscript object and let it format itself as a string - self.stdout.write(str(Script(models=models, context=context, stdout=self.stdout, stderr=self.stderr))) - self.stdout.write("\n") - - -def get_models(app_labels): - """ Gets a list of models for the given app labels, with some exceptions. - TODO: If a required model is referenced, it should also be included. - Or at least discovered with a get_or_create() call. - """ - - from django.db.models import get_app, get_apps, get_model - from django.db.models import get_models as get_all_models - - # These models are not to be output, e.g. because they can be generated automatically - # TODO: This should be "appname.modelname" string - EXCLUDED_MODELS = (ContentType, ) - - models = [] - - # If no app labels are given, return all - if not app_labels: - for app in get_apps(): - models += [m for m in get_all_models(app) if m not in EXCLUDED_MODELS] - - # Get all relevant apps - for app_label in app_labels: - # If a specific model is mentioned, get only that model - if "." in app_label: - app_label, model_name = app_label.split(".", 1) - models.append(get_model(app_label, model_name)) - # Get all models for a given app - else: - models += [m for m in get_all_models(get_app(app_label)) if m not in EXCLUDED_MODELS] - - return models - - -class Code(object): - """ A snippet of python script. - This keeps track of import statements and can be output to a string. - In the future, other features such as custom indentation might be included - in this class. - """ - - def __init__(self, indent=-1, stdout=None, stderr=None): - - if not stdout: - stdout = sys.stdout - if not stderr: - stderr = sys.stderr - - self.indent = indent - self.stdout = stdout - self.stderr = stderr - - def __str__(self): - """ Returns a string representation of this script. - """ - if self.imports: - self.stderr.write(repr(self.import_lines)) - return flatten_blocks([""] + self.import_lines + [""] + self.lines, num_indents=self.indent) - else: - return flatten_blocks(self.lines, num_indents=self.indent) - - def get_import_lines(self): - """ Takes the stored imports and converts them to lines - """ - if self.imports: - return ["from %s import %s" % (value, key) for key, value in self.imports.items()] - else: - return [] - import_lines = property(get_import_lines) - - -class ModelCode(Code): - " Produces a python script that can recreate data for a given model class. " - - def __init__(self, model, context=None, stdout=None, stderr=None): - super(ModelCode, self).__init__(indent=0, stdout=stdout, stderr=stderr) - self.model = model - if context is None: - context = {} - self.context = context - self.instances = [] - - def get_imports(self): - """ Returns a dictionary of import statements, with the variable being - defined as the key. - """ - return {self.model.__name__: smart_unicode(self.model.__module__)} - imports = property(get_imports) - - def get_lines(self): - """ Returns a list of lists or strings, representing the code body. - Each list is a block, each string is a statement. - """ - code = [] - - for counter, item in enumerate(self.model._default_manager.all()): - instance = InstanceCode(instance=item, id=counter + 1, context=self.context, stdout=self.stdout, stderr=self.stderr) - self.instances.append(instance) - if instance.waiting_list: - code += instance.lines - - # After each instance has been processed, try again. - # This allows self referencing fields to work. - for instance in self.instances: - if instance.waiting_list: - code += instance.lines - - return code - - lines = property(get_lines) - - -class InstanceCode(Code): - " Produces a python script that can recreate data for a given model instance. " - - def __init__(self, instance, id, context=None, stdout=None, stderr=None): - """ We need the instance in question and an id """ - - super(InstanceCode, self).__init__(indent=0, stdout=stdout, stderr=stderr) - self.imports = {} - - self.instance = instance - self.model = self.instance.__class__ - if context is None: - context = {} - self.context = context - self.variable_name = "%s_%s" % (self.instance._meta.db_table, id) - self.skip_me = None - self.instantiated = False - - self.waiting_list = list(self.model._meta.fields) - - self.many_to_many_waiting_list = {} - for field in self.model._meta.many_to_many: - self.many_to_many_waiting_list[field] = list(getattr(self.instance, field.name).all()) - - def get_lines(self, force=False): - """ Returns a list of lists or strings, representing the code body. - Each list is a block, each string is a statement. - - force (True or False): if an attribute object cannot be included, - it is usually skipped to be processed later. With 'force' set, there - will be no waiting: a get_or_create() call is written instead. - """ - code_lines = [] - - # Don't return anything if this is an instance that should be skipped - if self.skip(): - return [] - - # Initialise our new object - # e.g. model_name_35 = Model() - code_lines += self.instantiate() - - # Add each field - # e.g. model_name_35.field_one = 1034.91 - # model_name_35.field_two = "text" - code_lines += self.get_waiting_list() - - if force: - # TODO: Check that M2M are not affected - code_lines += self.get_waiting_list(force=force) - - # Print the save command for our new object - # e.g. model_name_35.save() - if code_lines: - code_lines.append("%s = importer.save_or_locate(%s)\n" % (self.variable_name, self.variable_name)) - - code_lines += self.get_many_to_many_lines(force=force) - - return code_lines - lines = property(get_lines) - - def skip(self): - """ Determine whether or not this object should be skipped. - If this model instance is a parent of a single subclassed - instance, skip it. The subclassed instance will create this - parent instance for us. - - TODO: Allow the user to force its creation? - """ - - if self.skip_me is not None: - return self.skip_me - - def get_skip_version(): - """ Return which version of the skip code should be run - - Django's deletion code was refactored in r14507 which - was just two days before 1.3 alpha 1 (r14519) - """ - if not hasattr(self, '_SKIP_VERSION'): - version = django.VERSION - # no, it isn't lisp. I swear. - self._SKIP_VERSION = ( - version[0] > 1 or ( # django 2k... someday :) - version[0] == 1 and ( # 1.x - version[1] >= 4 or # 1.4+ - version[1] == 3 and not ( # 1.3.x - (version[3] == 'alpha' and version[1] == 0) - ) - ) - ) - ) and 2 or 1 # NOQA - return self._SKIP_VERSION - - if get_skip_version() == 1: - try: - # Django trunk since r7722 uses CollectedObjects instead of dict - from django.db.models.query import CollectedObjects - sub_objects = CollectedObjects() - except ImportError: - # previous versions don't have CollectedObjects - sub_objects = {} - self.instance._collect_sub_objects(sub_objects) - sub_objects = sub_objects.keys() - - elif get_skip_version() == 2: - from django.db.models.deletion import Collector - from django.db import router - cls = self.instance.__class__ - using = router.db_for_write(cls, instance=self.instance) - collector = Collector(using=using) - collector.collect([self.instance], collect_related=False) - - # collector stores its instances in two places. I *think* we - # only need collector.data, but using the batches is needed - # to perfectly emulate the old behaviour - # TODO: check if batches are really needed. If not, remove them. - sub_objects = sum([list(i) for i in collector.data.values()], []) - - if hasattr(collector, 'batches'): - # Django 1.6 removed batches for being dead code - # https://github.com/django/django/commit/a170c3f755351beb35f8166ec3c7e9d524d9602 - for batch in collector.batches.values(): - # batch.values can be sets, which must be converted to lists - sub_objects += sum([list(i) for i in batch.values()], []) - - sub_objects_parents = [so._meta.parents for so in sub_objects] - if [self.model in p for p in sub_objects_parents].count(True) == 1: - # since this instance isn't explicitly created, it's variable name - # can't be referenced in the script, so record None in context dict - pk_name = self.instance._meta.pk.name - key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name)) - self.context[key] = None - self.skip_me = True - else: - self.skip_me = False - - return self.skip_me - - def instantiate(self): - " Write lines for instantiation " - # e.g. model_name_35 = Model() - code_lines = [] - - if not self.instantiated: - code_lines.append("%s = %s()" % (self.variable_name, self.model.__name__)) - self.instantiated = True - - # Store our variable name for future foreign key references - pk_name = self.instance._meta.pk.name - key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name)) - self.context[key] = self.variable_name - - return code_lines - - def get_waiting_list(self, force=False): - " Add lines for any waiting fields that can be completed now. " - - code_lines = [] - - # Process normal fields - for field in list(self.waiting_list): - try: - # Find the value, add the line, remove from waiting list and move on - value = get_attribute_value(self.instance, field, self.context, force=force) - code_lines.append('%s.%s = %s' % (self.variable_name, field.name, value)) - self.waiting_list.remove(field) - except SkipValue: - # Remove from the waiting list and move on - self.waiting_list.remove(field) - continue - except DoLater: - # Move on, maybe next time - continue - - return code_lines - - def get_many_to_many_lines(self, force=False): - """ Generates lines that define many to many relations for this instance. """ - - lines = [] - - for field, rel_items in self.many_to_many_waiting_list.items(): - for rel_item in list(rel_items): - try: - pk_name = rel_item._meta.pk.name - key = '%s_%s' % (rel_item.__class__.__name__, getattr(rel_item, pk_name)) - value = "%s" % self.context[key] - lines.append('%s.%s.add(%s)' % (self.variable_name, field.name, value)) - self.many_to_many_waiting_list[field].remove(rel_item) - except KeyError: - if force: - item_locator = orm_item_locator(rel_item) - self.context["__extra_imports"][rel_item._meta.object_name] = rel_item.__module__ - lines.append('%s.%s.add( %s )' % (self.variable_name, field.name, item_locator)) - self.many_to_many_waiting_list[field].remove(rel_item) - - if lines: - lines.append("") - - return lines - - -class Script(Code): - " Produces a complete python script that can recreate data for the given apps. " - - def __init__(self, models, context=None, stdout=None, stderr=None): - super(Script, self).__init__(stdout=stdout, stderr=stderr) - self.imports = {} - - self.models = models - if context is None: - context = {} - self.context = context - - self.context["__avaliable_models"] = set(models) - self.context["__extra_imports"] = {} - - def _queue_models(self, models, context): - """ Works an an appropriate ordering for the models. - This isn't essential, but makes the script look nicer because - more instances can be defined on their first try. - """ - - # Max number of cycles allowed before we call it an infinite loop. - MAX_CYCLES = 5 - - model_queue = [] - number_remaining_models = len(models) - allowed_cycles = MAX_CYCLES - - while number_remaining_models > 0: - previous_number_remaining_models = number_remaining_models - - model = models.pop(0) - - # If the model is ready to be processed, add it to the list - if check_dependencies(model, model_queue, context["__avaliable_models"]): - model_class = ModelCode(model=model, context=context, stdout=self.stdout, stderr=self.stderr) - model_queue.append(model_class) - - # Otherwise put the model back at the end of the list - else: - models.append(model) - - # Check for infinite loops. - # This means there is a cyclic foreign key structure - # That cannot be resolved by re-ordering - number_remaining_models = len(models) - if number_remaining_models == previous_number_remaining_models: - allowed_cycles -= 1 - if allowed_cycles <= 0: - # Add the remaining models, but do not remove them from the model list - missing_models = [ModelCode(model=m, context=context, stdout=self.stdout, stderr=self.stderr) for m in models] - model_queue += missing_models - # Replace the models with the model class objects - # (sure, this is a little bit of hackery) - models[:] = missing_models - break - else: - allowed_cycles = MAX_CYCLES - - return model_queue - - def get_lines(self): - """ Returns a list of lists or strings, representing the code body. - Each list is a block, each string is a statement. - """ - code = [self.FILE_HEADER.strip()] - - # Queue and process the required models - for model_class in self._queue_models(self.models, context=self.context): - msg = 'Processing model: %s\n' % model_class.model.__name__ - self.stderr.write(msg) - code.append(" #" + msg) - code.append(model_class.import_lines) - code.append("") - code.append(model_class.lines) - - # Process left over foreign keys from cyclic models - for model in self.models: - msg = 'Re-processing model: %s\n' % model.model.__name__ - self.stderr.write(msg) - code.append(" #" + msg) - for instance in model.instances: - if instance.waiting_list or instance.many_to_many_waiting_list: - code.append(instance.get_lines(force=True)) - - code.insert(1, " #initial imports") - code.insert(2, "") - for key, value in self.context["__extra_imports"].items(): - code.insert(2, " from %s import %s" % (value, key)) - - return code - - lines = property(get_lines) - - # A user-friendly file header - FILE_HEADER = """ - -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# This file has been automatically generated. -# Instead of changing it, create a file called import_helper.py -# and put there a class called ImportHelper(object) in it. -# -# This class will be specially casted so that instead of extending object, -# it will actually extend the class BasicImportHelper() -# -# That means you just have to overload the methods you want to -# change, leaving the other ones inteact. -# -# Something that you might want to do is use transactions, for example. -# -# Also, don't forget to add the necessary Django imports. -# -# This file was generated with the following command: -# %s -# -# to restore it, run -# manage.py runscript module_name.this_script_name -# -# example: if manage.py is at ./manage.py -# and the script is at ./some_folder/some_script.py -# you must make sure ./some_folder/__init__.py exists -# and run ./manage.py runscript some_folder.some_script - -from django.db import transaction - -class BasicImportHelper(object): - - def pre_import(self): - pass - - # You probably want to uncomment on of these two lines - # @transaction.atomic # Django 1.6 - # @transaction.commit_on_success # Django <1.6 - def run_import(self, import_data): - import_data() - - def post_import(self): - pass - - def locate_similar(self, current_object, search_data): - #you will probably want to call this method from save_or_locate() - #example: - #new_obj = self.locate_similar(the_obj, {"national_id": the_obj.national_id } ) - - the_obj = current_object.__class__.objects.get(**search_data) - return the_obj - - def locate_object(self, original_class, original_pk_name, the_class, pk_name, pk_value, obj_content): - #You may change this function to do specific lookup for specific objects - # - #original_class class of the django orm's object that needs to be located - #original_pk_name the primary key of original_class - #the_class parent class of original_class which contains obj_content - #pk_name the primary key of original_class - #pk_value value of the primary_key - #obj_content content of the object which was not exported. - # - #you should use obj_content to locate the object on the target db - # - #and example where original_class and the_class are different is - #when original_class is Farmer and - #the_class is Person. The table may refer to a Farmer but you will actually - #need to locate Person in order to instantiate that Farmer - # - #example: - #if the_class == SurveyResultFormat or the_class == SurveyType or the_class == SurveyState: - # pk_name="name" - # pk_value=obj_content[pk_name] - #if the_class == StaffGroup: - # pk_value=8 - - search_data = { pk_name: pk_value } - the_obj = the_class.objects.get(**search_data) - #print(the_obj) - return the_obj - - - def save_or_locate(self, the_obj): - #change this if you want to locate the object in the database - try: - the_obj.save() - except: - print("---------------") - print("Error saving the following object:") - print(the_obj.__class__) - print(" ") - print(the_obj.__dict__) - print(" ") - print(the_obj) - print(" ") - print("---------------") - - raise - return the_obj - - -importer = None -try: - import import_helper - #we need this so ImportHelper can extend BasicImportHelper, although import_helper.py - #has no knowlodge of this class - importer = type("DynamicImportHelper", (import_helper.ImportHelper, BasicImportHelper ) , {} )() -except ImportError as e: - if str(e) == "No module named import_helper": - importer = BasicImportHelper() - else: - raise - -import datetime -from decimal import Decimal -from django.contrib.contenttypes.models import ContentType - -try: - import dateutil.parser -except ImportError: - print("Please install python-dateutil") - sys.exit(os.EX_USAGE) - -def run(): - importer.pre_import() - importer.run_import(import_data) - importer.post_import() - -def import_data(): - -""" % " ".join(sys.argv) - - -# HELPER FUNCTIONS -#------------------------------------------------------------------------------- - -def flatten_blocks(lines, num_indents=-1): - """ Takes a list (block) or string (statement) and flattens it into a string - with indentation. - """ - - # The standard indent is four spaces - INDENTATION = " " * 4 - - if not lines: - return "" - - # If this is a string, add the indentation and finish here - if isinstance(lines, six.string_types): - return INDENTATION * num_indents + lines - - # If this is not a string, join the lines and recurse - return "\n".join([flatten_blocks(line, num_indents + 1) for line in lines]) - - -def get_attribute_value(item, field, context, force=False): - """ Gets a string version of the given attribute's value, like repr() might. """ - - # Find the value of the field, catching any database issues - try: - value = getattr(item, field.name) - except ObjectDoesNotExist: - raise SkipValue('Could not find object for %s.%s, ignoring.\n' % (item.__class__.__name__, field.name)) - - # AutoField: We don't include the auto fields, they'll be automatically recreated - if isinstance(field, AutoField): - raise SkipValue() - - # Some databases (eg MySQL) might store boolean values as 0/1, this needs to be cast as a bool - elif isinstance(field, BooleanField) and value is not None: - return repr(bool(value)) - - # Post file-storage-refactor, repr() on File/ImageFields no longer returns the path - elif isinstance(field, FileField): - return repr(force_unicode(value)) - - # ForeignKey fields, link directly using our stored python variable name - elif isinstance(field, ForeignKey) and value is not None: - - # Special case for contenttype foreign keys: no need to output any - # content types in this script, as they can be generated again - # automatically. - # NB: Not sure if "is" will always work - if field.rel.to is ContentType: - return 'ContentType.objects.get(app_label="%s", model="%s")' % (value.app_label, value.model) - - # Generate an identifier (key) for this foreign object - pk_name = value._meta.pk.name - key = '%s_%s' % (value.__class__.__name__, getattr(value, pk_name)) - - if key in context: - variable_name = context[key] - # If the context value is set to None, this should be skipped. - # This identifies models that have been skipped (inheritance) - if variable_name is None: - raise SkipValue() - # Return the variable name listed in the context - return "%s" % variable_name - elif value.__class__ not in context["__avaliable_models"] or force: - context["__extra_imports"][value._meta.object_name] = value.__module__ - item_locator = orm_item_locator(value) - return item_locator - else: - raise DoLater('(FK) %s.%s\n' % (item.__class__.__name__, field.name)) - - elif isinstance(field, (DateField, DateTimeField)): - return "dateutil.parser.parse(\"%s\")" % value.isoformat() - - # A normal field (e.g. a python built-in) - else: - return repr(value) - - -def make_clean_dict(the_dict): - if "_state" in the_dict: - clean_dict = the_dict.copy() - del clean_dict["_state"] - return clean_dict - return the_dict - - -def check_dependencies(model, model_queue, avaliable_models): - " Check that all the depenedencies for this model are already in the queue. " - - # A list of allowed links: existing fields, itself and the special case ContentType - allowed_links = [m.model.__name__ for m in model_queue] + [model.__name__, 'ContentType'] - - # For each ForeignKey or ManyToMany field, check that a link is possible - - for field in model._meta.fields: - if field.rel and field.rel.to.__name__ not in allowed_links: - if field.rel.to not in avaliable_models: - continue - return False - - for field in model._meta.many_to_many: - if field.rel and field.rel.to.__name__ not in allowed_links: - return False - - return True - - -# EXCEPTIONS -#------------------------------------------------------------------------------- - -class SkipValue(Exception): - """ Value could not be parsed or should simply be skipped. """ - - -class DoLater(Exception): - """ Value could not be parsed or should simply be skipped. """ diff --git a/awx/lib/site-packages/django_extensions/management/commands/export_emails.py b/awx/lib/site-packages/django_extensions/management/commands/export_emails.py deleted file mode 100644 index 05a8689b05..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/export_emails.py +++ /dev/null @@ -1,133 +0,0 @@ -from django.core.management.base import BaseCommand, CommandError -try: - from django.contrib.auth import get_user_model # Django 1.5 -except ImportError: - from django_extensions.future_1_5 import get_user_model -from django.contrib.auth.models import Group -from optparse import make_option -from sys import stdout -from csv import writer -import six - -FORMATS = [ - 'address', - 'emails', - 'google', - 'outlook', - 'linkedin', - 'vcard', -] - - -def full_name(first_name, last_name, username, **extra): - name = six.u(" ").join(n for n in [first_name, last_name] if n) - if not name: - return username - return name - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--group', '-g', action='store', dest='group', default=None, - help='Limit to users which are part of the supplied group name'), - make_option('--format', '-f', action='store', dest='format', default=FORMATS[0], - help="output format. May be one of '" + "', '".join(FORMATS) + "'."), - ) - - help = ("Export user email address list in one of a number of formats.") - args = "[output file]" - label = 'filename to save to' - - requires_model_validation = True - can_import_settings = True - encoding = 'utf-8' # RED_FLAG: add as an option -DougN - - def handle(self, *args, **options): - if len(args) > 1: - raise CommandError("extra arguments supplied") - group = options['group'] - if group and not Group.objects.filter(name=group).count() == 1: - names = six.u("', '").join(g['name'] for g in Group.objects.values('name')).encode('utf-8') - if names: - names = "'" + names + "'." - raise CommandError("Unknown group '" + group + "'. Valid group names are: " + names) - if len(args) and args[0] != '-': - outfile = open(args[0], 'w') - else: - outfile = stdout - - User = get_user_model() - qs = User.objects.all().order_by('last_name', 'first_name', 'username', 'email') - if group: - qs = qs.filter(group__name=group).distinct() - qs = qs.values('last_name', 'first_name', 'username', 'email') - getattr(self, options['format'])(qs, outfile) - - def address(self, qs, out): - """simple single entry per line in the format of: - "full name" <my@address.com>; - """ - out.write(six.u("\n").join(six.u('"%s" <%s>;' % (full_name(**ent), ent['email'])) - for ent in qs).encode(self.encoding)) - out.write("\n") - - def emails(self, qs, out): - """simpler single entry with email only in the format of: - my@address.com, - """ - out.write(six.u(",\n").join(six.u('%s' % (ent['email'])) for ent in qs).encode(self.encoding)) - out.write("\n") - - def google(self, qs, out): - """CSV format suitable for importing into google GMail - """ - csvf = writer(out) - csvf.writerow(['Name', 'Email']) - for ent in qs: - csvf.writerow([full_name(**ent).encode(self.encoding), - ent['email'].encode(self.encoding)]) - - def outlook(self, qs, out): - """CSV format suitable for importing into outlook - """ - csvf = writer(out) - columns = ['Name', 'E-mail Address', 'Notes', 'E-mail 2 Address', 'E-mail 3 Address', - 'Mobile Phone', 'Pager', 'Company', 'Job Title', 'Home Phone', 'Home Phone 2', - 'Home Fax', 'Home Address', 'Business Phone', 'Business Phone 2', - 'Business Fax', 'Business Address', 'Other Phone', 'Other Fax', 'Other Address'] - csvf.writerow(columns) - empty = [''] * (len(columns) - 2) - for ent in qs: - csvf.writerow([full_name(**ent).encode(self.encoding), - ent['email'].encode(self.encoding)] + empty) - - def linkedin(self, qs, out): - """CSV format suitable for importing into linkedin Groups. - perfect for pre-approving members of a linkedin group. - """ - csvf = writer(out) - csvf.writerow(['First Name', 'Last Name', 'Email']) - for ent in qs: - csvf.writerow([ent['first_name'].encode(self.encoding), - ent['last_name'].encode(self.encoding), - ent['email'].encode(self.encoding)]) - - def vcard(self, qs, out): - try: - import vobject - except ImportError: - print(self.style.ERROR("Please install python-vobject to use the vcard export format.")) - import sys - sys.exit(1) - for ent in qs: - card = vobject.vCard() - card.add('fn').value = full_name(**ent) - if not ent['last_name'] and not ent['first_name']: - # fallback to fullname, if both first and lastname are not declared - card.add('n').value = vobject.vcard.Name(full_name(**ent)) - else: - card.add('n').value = vobject.vcard.Name(ent['last_name'], ent['first_name']) - emailpart = card.add('email') - emailpart.value = ent['email'] - emailpart.type_param = 'INTERNET' - out.write(card.serialize().encode(self.encoding)) diff --git a/awx/lib/site-packages/django_extensions/management/commands/find_template.py b/awx/lib/site-packages/django_extensions/management/commands/find_template.py deleted file mode 100644 index 1513779365..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/find_template.py +++ /dev/null @@ -1,35 +0,0 @@ -from django.core.management.base import LabelCommand -from django.template import loader -from django.template import TemplateDoesNotExist -import sys - - -def get_template_path(path): - try: - template = loader.find_template(path) - if template[1]: - return template[1].name - # work arround https://code.djangoproject.com/ticket/17199 issue - for template_loader in loader.template_source_loaders: - try: - source, origin = template_loader.load_template_source(path) - return origin - except TemplateDoesNotExist: - pass - raise TemplateDoesNotExist(path) - except TemplateDoesNotExist: - return None - - -class Command(LabelCommand): - help = "Finds the location of the given template by resolving its path" - args = "[template_path]" - label = 'template path' - - def handle_label(self, template_path, **options): - path = get_template_path(template_path) - if path is None: - sys.stderr.write("No template found\n") - sys.exit(1) - else: - print(path) diff --git a/awx/lib/site-packages/django_extensions/management/commands/generate_secret_key.py b/awx/lib/site-packages/django_extensions/management/commands/generate_secret_key.py deleted file mode 100644 index 1d9ed25403..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/generate_secret_key.py +++ /dev/null @@ -1,11 +0,0 @@ -from random import choice -from django.core.management.base import NoArgsCommand - - -class Command(NoArgsCommand): - help = "Generates a new SECRET_KEY that can be used in a project settings file." - - requires_model_validation = False - - def handle_noargs(self, **options): - return ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)]) diff --git a/awx/lib/site-packages/django_extensions/management/commands/graph_models.py b/awx/lib/site-packages/django_extensions/management/commands/graph_models.py deleted file mode 100644 index 5d5873d472..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/graph_models.py +++ /dev/null @@ -1,147 +0,0 @@ -import six -import sys -from optparse import make_option, NO_DEFAULT -from django.core.management.base import BaseCommand, CommandError -from django.conf import settings -from django_extensions.management.modelviz import generate_dot - - -try: - import pygraphviz - HAS_PYGRAPHVIZ = True -except ImportError: - HAS_PYGRAPHVIZ = False - -try: - import pydot - HAS_PYDOT = True -except ImportError: - HAS_PYDOT = False - - -class Command(BaseCommand): - graph_models_options = ( - make_option('--pygraphviz', action='store_true', dest='pygraphviz', - help='Use PyGraphViz to generate the image.'), - make_option('--pydot', action='store_true', dest='pydot', - help='Use PyDot to generate the image.'), - make_option('--disable-fields', '-d', action='store_true', dest='disable_fields', - help='Do not show the class member fields'), - make_option('--group-models', '-g', action='store_true', dest='group_models', - help='Group models together respective to their application'), - make_option('--all-applications', '-a', action='store_true', dest='all_applications', - help='Automatically include all applications from INSTALLED_APPS'), - make_option('--output', '-o', action='store', dest='outputfile', - help='Render output file. Type of output dependend on file extensions. Use png or jpg to render graph to image.'), - make_option('--layout', '-l', action='store', dest='layout', default='dot', - help='Layout to be used by GraphViz for visualization. Layouts: circo dot fdp neato nop nop1 nop2 twopi'), - make_option('--verbose-names', '-n', action='store_true', dest='verbose_names', - help='Use verbose_name of models and fields'), - make_option('--language', '-L', action='store', dest='language', - help='Specify language used for verbose_name localization'), - make_option('--exclude-columns', '-x', action='store', dest='exclude_columns', - help='Exclude specific column(s) from the graph. Can also load exclude list from file.'), - make_option('--exclude-models', '-X', action='store', dest='exclude_models', - help='Exclude specific model(s) from the graph. Can also load exclude list from file.'), - make_option('--inheritance', '-e', action='store_true', dest='inheritance', default=True, - help='Include inheritance arrows (default)'), - make_option('--no-inheritance', '-E', action='store_false', dest='inheritance', - help='Do not include inheritance arrows'), - make_option('--hide-relations-from-fields', '-R', action='store_false', dest="relations_as_fields", - default=True, help="Do not show relations as fields in the graph."), - make_option('--disable-sort-fields', '-S', action="store_false", dest="sort_fields", - default=True, help="Do not sort fields"), - ) - option_list = BaseCommand.option_list + graph_models_options - - help = "Creates a GraphViz dot file for the specified app names. You can pass multiple app names and they will all be combined into a single model. Output is usually directed to a dot file." - args = "[appname]" - label = 'application name' - - requires_model_validation = True - can_import_settings = True - - def handle(self, *args, **options): - self.options_from_settings(options) - - if len(args) < 1 and not options['all_applications']: - raise CommandError("need one or more arguments for appname") - - use_pygraphviz = options.get('pygraphviz', False) - use_pydot = options.get('pydot', False) - cli_options = ' '.join(sys.argv[2:]) - dotdata = generate_dot(args, cli_options=cli_options, **options) - dotdata = dotdata.encode('utf-8') - if options['outputfile']: - if not use_pygraphviz and not use_pydot: - if HAS_PYGRAPHVIZ: - use_pygraphviz = True - elif HAS_PYDOT: - use_pydot = True - if use_pygraphviz: - self.render_output_pygraphviz(dotdata, **options) - elif use_pydot: - self.render_output_pydot(dotdata, **options) - else: - raise CommandError("Neither pygraphviz nor pydot could be found to generate the image") - else: - self.print_output(dotdata) - - def options_from_settings(self, options): - defaults = getattr(settings, 'GRAPH_MODELS', None) - if defaults: - for option in self.graph_models_options: - long_opt = option._long_opts[0] - if long_opt: - long_opt = long_opt.lstrip("-").replace("-", "_") - if long_opt in defaults: - default_value = None - if not option.default == NO_DEFAULT: - default_value = option.default - if options[option.dest] == default_value: - options[option.dest] = defaults[long_opt] - - def print_output(self, dotdata): - if six.PY3 and isinstance(dotdata, six.binary_type): - dotdata = dotdata.decode() - - print(dotdata) - - def render_output_pygraphviz(self, dotdata, **kwargs): - """Renders the image using pygraphviz""" - if not HAS_PYGRAPHVIZ: - raise CommandError("You need to install pygraphviz python module") - - version = pygraphviz.__version__.rstrip("-svn") - try: - if tuple(int(v) for v in version.split('.')) < (0, 36): - # HACK around old/broken AGraph before version 0.36 (ubuntu ships with this old version) - import tempfile - tmpfile = tempfile.NamedTemporaryFile() - tmpfile.write(dotdata) - tmpfile.seek(0) - dotdata = tmpfile.name - except ValueError: - pass - - graph = pygraphviz.AGraph(dotdata) - graph.layout(prog=kwargs['layout']) - graph.draw(kwargs['outputfile']) - - def render_output_pydot(self, dotdata, **kwargs): - """Renders the image using pydot""" - if not HAS_PYDOT: - raise CommandError("You need to install pydot python module") - - graph = pydot.graph_from_dot_data(dotdata) - if not graph: - raise CommandError("pydot returned an error") - output_file = kwargs['outputfile'] - formats = ['bmp', 'canon', 'cmap', 'cmapx', 'cmapx_np', 'dot', 'dia', 'emf', - 'em', 'fplus', 'eps', 'fig', 'gd', 'gd2', 'gif', 'gv', 'imap', - 'imap_np', 'ismap', 'jpe', 'jpeg', 'jpg', 'metafile', 'pdf', - 'pic', 'plain', 'plain-ext', 'png', 'pov', 'ps', 'ps2', 'svg', - 'svgz', 'tif', 'tiff', 'tk', 'vml', 'vmlz', 'vrml', 'wbmp', 'xdot'] - ext = output_file[output_file.rfind('.') + 1:] - format = ext if ext in formats else 'raw' - graph.write(output_file, format=format) diff --git a/awx/lib/site-packages/django_extensions/management/commands/mail_debug.py b/awx/lib/site-packages/django_extensions/management/commands/mail_debug.py deleted file mode 100644 index cd834d9709..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/mail_debug.py +++ /dev/null @@ -1,80 +0,0 @@ -from django_extensions.management.utils import setup_logger -from django.core.management.base import BaseCommand, CommandError -from optparse import make_option -from smtpd import SMTPServer -import sys -import asyncore -from logging import getLogger - - -logger = getLogger(__name__) - - -class ExtensionDebuggingServer(SMTPServer): - """Duplication of smtpd.DebuggingServer, but using logging instead of print.""" - # Do something with the gathered message - def process_message(self, peer, mailfrom, rcpttos, data): - """Output will be sent to the module logger at INFO level.""" - inheaders = 1 - lines = data.split('\n') - logger.info('---------- MESSAGE FOLLOWS ----------') - for line in lines: - # headers first - if inheaders and not line: - logger.info('X-Peer: %s' % peer[0]) - inheaders = 0 - logger.info(line) - logger.info('------------ END MESSAGE ------------') - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--output', dest='output_file', default=None, - help='Specifies an output file to send a copy of all messages (not flushed immediately).'), - make_option('--use-settings', dest='use_settings', - action='store_true', default=False, - help='Uses EMAIL_HOST and HOST_PORT from Django settings.'), - ) - help = "Starts a test mail server for development." - args = '[optional port number or ippaddr:port]' - - requires_model_validation = False - - def handle(self, addrport='', *args, **options): - if args: - raise CommandError('Usage is mail_debug %s' % self.args) - if not addrport: - if options.get('use_settings', False): - from django.conf import settings - addr = getattr(settings, 'EMAIL_HOST', '') - port = str(getattr(settings, 'EMAIL_PORT', '1025')) - else: - addr = '' - port = '1025' - else: - try: - addr, port = addrport.split(':') - except ValueError: - addr, port = '', addrport - if not addr: - addr = '127.0.0.1' - - if not port.isdigit(): - raise CommandError("%r is not a valid port number." % port) - else: - port = int(port) - - # Add console handler - setup_logger(logger, stream=self.stdout, filename=options.get('output_file', None)) - - def inner_run(): - quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C' - print("Now accepting mail at %s:%s -- use %s to quit" % (addr, port, quit_command)) - - ExtensionDebuggingServer((addr, port), None) - asyncore.loop() - - try: - inner_run() - except KeyboardInterrupt: - pass diff --git a/awx/lib/site-packages/django_extensions/management/commands/notes.py b/awx/lib/site-packages/django_extensions/management/commands/notes.py deleted file mode 100644 index cdd2ec1814..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/notes.py +++ /dev/null @@ -1,48 +0,0 @@ -from __future__ import with_statement -from django.core.management.base import BaseCommand -from django.conf import settings -import os -import re - -ANNOTATION_RE = re.compile("\{?#[\s]*?(TODO|FIXME|BUG|HACK|WARNING|NOTE|XXX)[\s:]?(.+)") -ANNOTATION_END_RE = re.compile("(.*)#\}(.*)") - - -class Command(BaseCommand): - help = 'Show all annotations like TODO, FIXME, BUG, HACK, WARNING, NOTE or XXX in your py and HTML files.' - args = 'tag' - label = 'annotation tag (TODO, FIXME, BUG, HACK, WARNING, NOTE, XXX)' - - def handle(self, *args, **options): - # don't add django internal code - apps = filter(lambda app: not app.startswith('django.contrib'), settings.INSTALLED_APPS) - template_dirs = getattr(settings, 'TEMPLATE_DIRS', []) - if template_dirs: - apps += template_dirs - for app_dir in apps: - app_dir = app_dir.replace(".", "/") - for top, dirs, files in os.walk(app_dir): - for f in files: - if os.path.splitext(f)[1] in ('.py', '.html'): - fpath = os.path.join(top, f) - annotation_lines = [] - with open(fpath, 'r') as f: - i = 0 - for line in f.readlines(): - i += 1 - if ANNOTATION_RE.search(line): - tag, msg = ANNOTATION_RE.findall(line)[0] - if len(args) == 1: - search_for_tag = args[0].upper() - if not search_for_tag == tag: - break - - if ANNOTATION_END_RE.search(msg.strip()): - msg = ANNOTATION_END_RE.findall(msg.strip())[0][0] - - annotation_lines.append("[%3s] %-5s %s" % (i, tag, msg.strip())) - if annotation_lines: - print("%s:" % fpath) - for annotation in annotation_lines: - print(" * %s" % annotation) - print("") diff --git a/awx/lib/site-packages/django_extensions/management/commands/passwd.py b/awx/lib/site-packages/django_extensions/management/commands/passwd.py deleted file mode 100644 index 6f084b143d..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/passwd.py +++ /dev/null @@ -1,42 +0,0 @@ -from django.core.management.base import BaseCommand, CommandError -try: - from django.contrib.auth import get_user_model # Django 1.5 -except ImportError: - from django_extensions.future_1_5 import get_user_model -import getpass - - -class Command(BaseCommand): - help = "Clone of the UNIX program ``passwd'', for django.contrib.auth." - - requires_model_validation = False - - def handle(self, *args, **options): - if len(args) > 1: - raise CommandError("need exactly one or zero arguments for username") - - if args: - username, = args - else: - username = getpass.getuser() - - User = get_user_model() - try: - u = User.objects.get(username=username) - except User.DoesNotExist: - raise CommandError("user %s does not exist" % username) - - print("Changing password for user: %s" % u.username) - p1 = p2 = "" - while "" in (p1, p2) or p1 != p2: - p1 = getpass.getpass() - p2 = getpass.getpass("Password (again): ") - if p1 != p2: - print("Passwords do not match, try again") - elif "" in (p1, p2): - raise CommandError("aborted") - - u.set_password(p1) - u.save() - - return "Password changed successfully for user %s\n" % u.username diff --git a/awx/lib/site-packages/django_extensions/management/commands/pipchecker.py b/awx/lib/site-packages/django_extensions/management/commands/pipchecker.py deleted file mode 100644 index c853338731..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/pipchecker.py +++ /dev/null @@ -1,255 +0,0 @@ -import os -import pip -import sys -import json -import urllib2 -import urlparse -import xmlrpclib -from distutils.version import LooseVersion -from django.core.management.base import NoArgsCommand -from django_extensions.management.color import color_style -from optparse import make_option -from pip.req import parse_requirements - -try: - import requests - HAS_REQUESTS = True -except ImportError: - HAS_REQUESTS = False - - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option( - "-t", "--github-api-token", action="store", dest="github_api_token", - help="A github api authentication token." - ), - make_option( - "-r", "--requirement", action="append", dest="requirements", - default=[], metavar="FILENAME", - help="Check all the packages listed in the given requirements file. " - "This option can be used multiple times." - ), - make_option( - "-n", "--newer", action="store_true", dest="show_newer", - help="Also show when newer version then available is installed." - ), - ) - help = "Scan pip requirement files for out-of-date packages." - - def handle_noargs(self, **options): - self.style = color_style() - - self.options = options - if options["requirements"]: - req_files = options["requirements"] - elif os.path.exists("requirements.txt"): - req_files = ["requirements.txt"] - elif os.path.exists("requirements"): - req_files = ["requirements/{0}".format(f) for f in os.listdir("requirements") - if os.path.isfile(os.path.join("requirements", f)) and - f.lower().endswith(".txt")] - else: - sys.exit("requirements not found") - - self.reqs = {} - for filename in req_files: - class Object(object): - pass - mockoptions = Object() - mockoptions.default_vcs = "git" - mockoptions.skip_requirements_regex = None - for req in parse_requirements(filename, options=mockoptions): - self.reqs[req.name] = { - "pip_req": req, - "url": req.url, - } - - if options["github_api_token"]: - self.github_api_token = options["github_api_token"] - elif os.environ.get("GITHUB_API_TOKEN"): - self.github_api_token = os.environ.get("GITHUB_API_TOKEN") - else: - self.github_api_token = None # only 50 requests per hour - - self.check_pypi() - if HAS_REQUESTS: - self.check_github() - else: - print(self.style.ERROR("Cannot check github urls. The requests library is not installed. ( pip install requests )")) - self.check_other() - - def _urlopen_as_json(self, url, headers=None): - """Shorcut for return contents as json""" - req = urllib2.Request(url, headers=headers) - return json.loads(urllib2.urlopen(req).read()) - - def check_pypi(self): - """ - If the requirement is frozen to pypi, check for a new version. - """ - for dist in pip.get_installed_distributions(): - name = dist.project_name - if name in self.reqs.keys(): - self.reqs[name]["dist"] = dist - - pypi = xmlrpclib.ServerProxy("http://pypi.python.org/pypi") - for name, req in self.reqs.items(): - if req["url"]: - continue # skipping github packages. - elif "dist" in req: - dist = req["dist"] - dist_version = LooseVersion(dist.version) - available = pypi.package_releases(req["pip_req"].url_name) - try: - available_version = LooseVersion(available[0]) - except IndexError: - available_version = None - - if not available_version: - msg = self.style.WARN("release is not on pypi (check capitalization and/or --extra-index-url)") - elif self.options['show_newer'] and dist_version > available_version: - msg = self.style.INFO("{0} available (newer installed)".format(available_version)) - elif available_version > dist_version: - msg = self.style.INFO("{0} available".format(available_version)) - else: - msg = "up to date" - del self.reqs[name] - continue - pkg_info = self.style.BOLD("{dist.project_name} {dist.version}".format(dist=dist)) - else: - msg = "not installed" - pkg_info = name - print("{pkg_info:40} {msg}".format(pkg_info=pkg_info, msg=msg)) - del self.reqs[name] - - def check_github(self): - """ - If the requirement is frozen to a github url, check for new commits. - - API Tokens - ---------- - For more than 50 github api calls per hour, pipchecker requires - authentication with the github api by settings the environemnt - variable ``GITHUB_API_TOKEN`` or setting the command flag - --github-api-token='mytoken'``. - - To create a github api token for use at the command line:: - curl -u 'rizumu' -d '{"scopes":["repo"], "note":"pipchecker"}' https://api.github.com/authorizations - - For more info on github api tokens: - https://help.github.com/articles/creating-an-oauth-token-for-command-line-use - http://developer.github.com/v3/oauth/#oauth-authorizations-api - - Requirement Format - ------------------ - Pipchecker gets the sha of frozen repo and checks if it is - found at the head of any branches. If it is not found then - the requirement is considered to be out of date. - - Therefore, freezing at the commit hash will provide the expected - results, but if freezing at a branch or tag name, pipchecker will - not be able to determine with certainty if the repo is out of date. - - Freeze at the commit hash (sha):: - git+git://github.com/django/django.git@393c268e725f5b229ecb554f3fac02cfc250d2df#egg=Django - - Freeze with a branch name:: - git+git://github.com/django/django.git@master#egg=Django - - Freeze with a tag:: - git+git://github.com/django/django.git@1.5b2#egg=Django - - Do not freeze:: - git+git://github.com/django/django.git#egg=Django - - """ - for name, req in self.reqs.items(): - req_url = req["url"] - if not req_url: - continue - if req_url.startswith("git") and "github.com/" not in req_url: - continue - if req_url.endswith(".tar.gz") or req_url.endswith(".tar.bz2") or req_url.endswith(".zip"): - continue - - headers = { - "content-type": "application/json", - } - if self.github_api_token: - headers["Authorization"] = "token {0}".format(self.github_api_token) - try: - user, repo = urlparse.urlparse(req_url).path.split("#")[0].strip("/").rstrip("/").split("/") - except (ValueError, IndexError) as e: - print(self.style.ERROR("\nFailed to parse %r: %s\n" % (req_url, e))) - continue - - try: - #test_auth = self._urlopen_as_json("https://api.github.com/django/", headers=headers) - test_auth = requests.get("https://api.github.com/django/", headers=headers).json() - except urllib2.HTTPError as e: - print("\n%s\n" % str(e)) - return - - if "message" in test_auth and test_auth["message"] == "Bad credentials": - print(self.style.ERROR("\nGithub API: Bad credentials. Aborting!\n")) - return - elif "message" in test_auth and test_auth["message"].startswith("API Rate Limit Exceeded"): - print(self.style.ERROR("\nGithub API: Rate Limit Exceeded. Aborting!\n")) - return - - frozen_commit_sha = None - if ".git" in repo: - repo_name, frozen_commit_full = repo.split(".git") - if frozen_commit_full.startswith("@"): - frozen_commit_sha = frozen_commit_full[1:] - elif "@" in repo: - repo_name, frozen_commit_sha = repo.split("@") - - if frozen_commit_sha is None: - msg = self.style.ERROR("repo is not frozen") - - if frozen_commit_sha: - branch_url = "https://api.github.com/repos/{0}/{1}/branches".format(user, repo_name) - #branch_data = self._urlopen_as_json(branch_url, headers=headers) - branch_data = requests.get(branch_url, headers=headers).json() - - frozen_commit_url = "https://api.github.com/repos/{0}/{1}/commits/{2}".format( - user, repo_name, frozen_commit_sha - ) - #frozen_commit_data = self._urlopen_as_json(frozen_commit_url, headers=headers) - frozen_commit_data = requests.get(frozen_commit_url, headers=headers).json() - - if "message" in frozen_commit_data and frozen_commit_data["message"] == "Not Found": - msg = self.style.ERROR("{0} not found in {1}. Repo may be private.".format(frozen_commit_sha[:10], name)) - elif frozen_commit_sha in [branch["commit"]["sha"] for branch in branch_data]: - msg = self.style.BOLD("up to date") - else: - msg = self.style.INFO("{0} is not the head of any branch".format(frozen_commit_data["sha"][:10])) - - if "dist" in req: - pkg_info = "{dist.project_name} {dist.version}".format(dist=req["dist"]) - elif frozen_commit_sha is None: - pkg_info = name - else: - pkg_info = "{0} {1}".format(name, frozen_commit_sha[:10]) - print("{pkg_info:40} {msg}".format(pkg_info=pkg_info, msg=msg)) - del self.reqs[name] - - def check_other(self): - """ - If the requirement is frozen somewhere other than pypi or github, skip. - - If you have a private pypi or use --extra-index-url, consider contributing - support here. - """ - if self.reqs: - print(self.style.ERROR("\nOnly pypi and github based requirements are supported:")) - for name, req in self.reqs.items(): - if "dist" in req: - pkg_info = "{dist.project_name} {dist.version}".format(dist=req["dist"]) - elif "url" in req: - pkg_info = "{url}".format(url=req["url"]) - else: - pkg_info = "unknown package" - print(self.style.BOLD("{pkg_info:40} is not a pypi or github requirement".format(pkg_info=pkg_info))) diff --git a/awx/lib/site-packages/django_extensions/management/commands/print_settings.py b/awx/lib/site-packages/django_extensions/management/commands/print_settings.py deleted file mode 100644 index be23510749..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/print_settings.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -print_settings -============== - -Django command similar to 'diffsettings' but shows all active Django settings. -""" - -from django.core.management.base import NoArgsCommand -from django.conf import settings -from optparse import make_option - - -class Command(NoArgsCommand): - """print_settings command""" - - help = "Print the active Django settings." - - option_list = NoArgsCommand.option_list + ( - make_option('--format', default='simple', dest='format', - help='Specifies output format.'), - make_option('--indent', default=4, dest='indent', type='int', - help='Specifies indent level for JSON and YAML'), - ) - - def handle_noargs(self, **options): - a_dict = {} - - for attr in dir(settings): - if self.include_attr(attr): - value = getattr(settings, attr) - a_dict[attr] = value - - output_format = options.get('format', 'json') - indent = options.get('indent', 4) - - if output_format == 'json': - json = self.import_json() - print(json.dumps(a_dict, indent=indent)) - elif output_format == 'yaml': - import yaml # requires PyYAML - print(yaml.dump(a_dict, indent=indent)) - elif output_format == 'pprint': - from pprint import pprint - pprint(a_dict) - else: - self.print_simple(a_dict) - - @staticmethod - def include_attr(attr): - """Whether or not to include attribute in output""" - - if attr.startswith('__'): - return False - else: - return True - - @staticmethod - def print_simple(a_dict): - """A very simple output format""" - - for key, value in a_dict.items(): - print('%-40s = %r' % (key, value)) - - @staticmethod - def import_json(): - """Import a module for JSON""" - - try: - import json - except ImportError: - import simplejson as json # NOQA - return json diff --git a/awx/lib/site-packages/django_extensions/management/commands/print_user_for_session.py b/awx/lib/site-packages/django_extensions/management/commands/print_user_for_session.py deleted file mode 100644 index d61059fcc2..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/print_user_for_session.py +++ /dev/null @@ -1,66 +0,0 @@ -from importlib import import_module -from django.conf import settings -from django.core.management.base import BaseCommand, CommandError - -try: - from django.contrib.auth import get_user_model # Django 1.5 -except ImportError: - from django_extensions.future_1_5 import get_user_model - -try: - from django.contrib.sessions.backends.base import VALID_KEY_CHARS # Django 1.5 -except ImportError: - VALID_KEY_CHARS = "abcdef0123456789" - - -class Command(BaseCommand): - help = ("print the user information for the provided session key. " - "this is very helpful when trying to track down the person who " - "experienced a site crash.") - args = "session_key" - label = 'session key for the user' - - requires_model_validation = True - can_import_settings = True - - def handle(self, *args, **options): - if len(args) > 1: - raise CommandError("extra arguments supplied") - - if len(args) < 1: - raise CommandError("session_key argument missing") - - key = args[0].lower() - - if not set(key).issubset(set(VALID_KEY_CHARS)): - raise CommandError("malformed session key") - - engine = import_module(settings.SESSION_ENGINE) - - if not engine.SessionStore().exists(key): - print("Session Key does not exist. Expired?") - return - - session = engine.SessionStore(key) - data = session.load() - - print('Session to Expire: %s' % session.get_expiry_date()) - print('Raw Data: %s' % data) - - uid = data.get('_auth_user_id', None) - - if uid is None: - print('No user associated with session') - return - - print("User id: %s" % uid) - - User = get_user_model() - try: - user = User.objects.get(pk=uid) - except User.DoesNotExist: - print("No user associated with that id.") - return - - for key in ['username', 'email', 'first_name', 'last_name']: - print("%s: %s" % (key, getattr(user, key))) diff --git a/awx/lib/site-packages/django_extensions/management/commands/reset_db.py b/awx/lib/site-packages/django_extensions/management/commands/reset_db.py deleted file mode 100644 index df96d5a64c..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/reset_db.py +++ /dev/null @@ -1,160 +0,0 @@ -""" -originally from http://www.djangosnippets.org/snippets/828/ by dnordberg -""" -import logging -from optparse import make_option - -from django.conf import settings -from django.core.management.base import CommandError, BaseCommand -from six.moves import input - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--noinput', action='store_false', - dest='interactive', default=True, - help='Tells Django to NOT prompt the user for input of any kind.'), - make_option('--no-utf8', action='store_true', - dest='no_utf8_support', default=False, - help='Tells Django to not create a UTF-8 charset database'), - make_option('-U', '--user', action='store', - dest='user', default=None, - help='Use another user for the database then defined in settings.py'), - make_option('-O', '--owner', action='store', - dest='owner', default=None, - help='Use another owner for creating the database then the user defined in settings or via --user'), - make_option('-P', '--password', action='store', - dest='password', default=None, - help='Use another password for the database then defined in settings.py'), - make_option('-D', '--dbname', action='store', - dest='dbname', default=None, - help='Use another database name then defined in settings.py'), - make_option('-R', '--router', action='store', - dest='router', default='default', - help='Use this router-database other then defined in settings.py'), - ) - help = "Resets the database for this project." - - def handle(self, *args, **options): - """ - Resets the database for this project. - - Note: Transaction wrappers are in reverse as a work around for - autocommit, anybody know how to do this the right way? - """ - - if args: - raise CommandError("reset_db takes no arguments") - - router = options.get('router') - dbinfo = settings.DATABASES.get(router) - if dbinfo is None: - raise CommandError("Unknown database router %s" % router) - - engine = dbinfo.get('ENGINE').split('.')[-1] - user = options.get('user') or dbinfo.get('USER') - password = options.get('password') or dbinfo.get('PASSWORD') - owner = options.get('owner') or user - - database_name = options.get('dbname') or dbinfo.get('NAME') - if database_name == '': - raise CommandError("You need to specify DATABASE_NAME in your Django settings file.") - - database_host = dbinfo.get('HOST') - database_port = dbinfo.get('PORT') - - verbosity = int(options.get('verbosity', 1)) - if options.get('interactive'): - confirm = input(""" -You have requested a database reset. -This will IRREVERSIBLY DESTROY -ALL data in the database "%s". -Are you sure you want to do this? - -Type 'yes' to continue, or 'no' to cancel: """ % (database_name,)) - else: - confirm = 'yes' - - if confirm != 'yes': - print("Reset cancelled.") - return - - if engine in ('sqlite3', 'spatialite'): - import os - try: - logging.info("Unlinking %s database" % engine) - os.unlink(database_name) - except OSError: - pass - - elif engine in ('mysql',): - import MySQLdb as Database - kwargs = { - 'user': user, - 'passwd': password, - } - if database_host.startswith('/'): - kwargs['unix_socket'] = database_host - else: - kwargs['host'] = database_host - - if database_port: - kwargs['port'] = int(database_port) - - connection = Database.connect(**kwargs) - drop_query = 'DROP DATABASE IF EXISTS `%s`' % database_name - utf8_support = options.get('no_utf8_support', False) and '' or 'CHARACTER SET utf8' - create_query = 'CREATE DATABASE `%s` %s' % (database_name, utf8_support) - logging.info('Executing... "' + drop_query + '"') - connection.query(drop_query) - logging.info('Executing... "' + create_query + '"') - connection.query(create_query) - - elif engine in ('postgresql', 'postgresql_psycopg2', 'postgis'): - if engine == 'postgresql': - import psycopg as Database # NOQA - elif engine in ('postgresql_psycopg2', 'postgis'): - import psycopg2 as Database # NOQA - - conn_string = "dbname=template1" - if user: - conn_string += " user=%s" % user - if password: - conn_string += " password='%s'" % password - if database_host: - conn_string += " host=%s" % database_host - if database_port: - conn_string += " port=%s" % database_port - - connection = Database.connect(conn_string) - connection.set_isolation_level(0) # autocommit false - cursor = connection.cursor() - drop_query = 'DROP DATABASE %s;' % database_name - logging.info('Executing... "' + drop_query + '"') - - try: - cursor.execute(drop_query) - except Database.ProgrammingError as e: - logging.info("Error: %s" % str(e)) - - create_query = "CREATE DATABASE %s" % database_name - if owner: - create_query += " WITH OWNER = \"%s\" " % owner - create_query += " ENCODING = 'UTF8'" - - if engine == 'postgis': - create_query += ' TEMPLATE = template_postgis' - - if settings.DEFAULT_TABLESPACE: - create_query += ' TABLESPACE = %s;' % settings.DEFAULT_TABLESPACE - else: - create_query += ';' - - logging.info('Executing... "' + create_query + '"') - cursor.execute(create_query) - - else: - raise CommandError("Unknown database engine %s" % engine) - - if verbosity >= 2 or options.get('interactive'): - print("Reset successful.") diff --git a/awx/lib/site-packages/django_extensions/management/commands/runjob.py b/awx/lib/site-packages/django_extensions/management/commands/runjob.py deleted file mode 100644 index b698054013..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/runjob.py +++ /dev/null @@ -1,52 +0,0 @@ -from django.core.management.base import LabelCommand -from optparse import make_option -from django_extensions.management.jobs import get_job, print_jobs - - -class Command(LabelCommand): - option_list = LabelCommand.option_list + ( - make_option('--list', '-l', action="store_true", dest="list_jobs", - help="List all jobs with their description"), - ) - help = "Run a single maintenance job." - args = "[app_name] job_name" - label = "" - - requires_model_validation = True - - def runjob(self, app_name, job_name, options): - verbosity = int(options.get('verbosity', 1)) - if verbosity > 1: - print("Executing job: %s (app: %s)" % (job_name, app_name)) - try: - job = get_job(app_name, job_name) - except KeyError: - if app_name: - print("Error: Job %s for applabel %s not found" % (app_name, job_name)) - else: - print("Error: Job %s not found" % job_name) - print("Use -l option to view all the available jobs") - return - try: - job().execute() - except Exception: - import traceback - print("ERROR OCCURED IN JOB: %s (APP: %s)" % (job_name, app_name)) - print("START TRACEBACK:") - traceback.print_exc() - print("END TRACEBACK\n") - - def handle(self, *args, **options): - app_name = None - job_name = None - if len(args) == 1: - job_name = args[0] - elif len(args) == 2: - app_name, job_name = args - if options.get('list_jobs'): - print_jobs(only_scheduled=False, show_when=True, show_appname=True) - else: - if not job_name: - print("Run a single maintenance job. Please specify the name of the job.") - return - self.runjob(app_name, job_name, options) diff --git a/awx/lib/site-packages/django_extensions/management/commands/runjobs.py b/awx/lib/site-packages/django_extensions/management/commands/runjobs.py deleted file mode 100644 index c8a5d621b1..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/runjobs.py +++ /dev/null @@ -1,89 +0,0 @@ -from django.core.management.base import LabelCommand -from optparse import make_option -from django_extensions.management.jobs import get_jobs, print_jobs - - -class Command(LabelCommand): - option_list = LabelCommand.option_list + ( - make_option('--list', '-l', action="store_true", dest="list_jobs", - help="List all jobs with their description"), - ) - help = "Runs scheduled maintenance jobs." - args = "[minutely quarter_hourly hourly daily weekly monthly yearly]" - label = "" - - requires_model_validation = True - - def usage_msg(self): - print("Run scheduled jobs. Please specify 'minutely', 'quarter_hourly', 'hourly', 'daily', 'weekly', 'monthly' or 'yearly'") - - def runjobs(self, when, options): - verbosity = int(options.get('verbosity', 1)) - jobs = get_jobs(when, only_scheduled=True) - list = jobs.keys() - list.sort() - for app_name, job_name in list: - job = jobs[(app_name, job_name)] - if verbosity > 1: - print("Executing %s job: %s (app: %s)" % (when, job_name, app_name)) - try: - job().execute() - except Exception: - import traceback - print("ERROR OCCURED IN %s JOB: %s (APP: %s)" % (when.upper(), job_name, app_name)) - print("START TRACEBACK:") - traceback.print_exc() - print("END TRACEBACK\n") - - def runjobs_by_signals(self, when, options): - """ Run jobs from the signals """ - # Thanks for Ian Holsman for the idea and code - from django_extensions.management import signals - from django.db import models - from django.conf import settings - - verbosity = int(options.get('verbosity', 1)) - for app_name in settings.INSTALLED_APPS: - try: - __import__(app_name + '.management', '', '', ['']) - except ImportError: - pass - - for app in models.get_apps(): - if verbosity > 1: - app_name = '.'.join(app.__name__.rsplit('.')[:-1]) - print("Sending %s job signal for: %s" % (when, app_name)) - if when == 'minutely': - signals.run_minutely_jobs.send(sender=app, app=app) - elif when == 'quarter_hourly': - signals.run_quarter_hourly_jobs.send(sender=app, app=app) - elif when == 'hourly': - signals.run_hourly_jobs.send(sender=app, app=app) - elif when == 'daily': - signals.run_daily_jobs.send(sender=app, app=app) - elif when == 'weekly': - signals.run_weekly_jobs.send(sender=app, app=app) - elif when == 'monthly': - signals.run_monthly_jobs.send(sender=app, app=app) - elif when == 'yearly': - signals.run_yearly_jobs.send(sender=app, app=app) - - def handle(self, *args, **options): - when = None - if len(args) > 1: - self.usage_msg() - return - elif len(args) == 1: - if not args[0] in ['minutely', 'quarter_hourly', 'hourly', 'daily', 'weekly', 'monthly', 'yearly']: - self.usage_msg() - return - else: - when = args[0] - if options.get('list_jobs'): - print_jobs(when, only_scheduled=True, show_when=True, show_appname=True) - else: - if not when: - self.usage_msg() - return - self.runjobs(when, options) - self.runjobs_by_signals(when, options) diff --git a/awx/lib/site-packages/django_extensions/management/commands/runprofileserver.py b/awx/lib/site-packages/django_extensions/management/commands/runprofileserver.py deleted file mode 100644 index cd82a1cece..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/runprofileserver.py +++ /dev/null @@ -1,308 +0,0 @@ -""" -runprofileserver.py - - Starts a lightweight Web server with profiling enabled. - -Credits for kcachegrind support taken from lsprofcalltree.py go to: - David Allouche - Jp Calderone & Itamar Shtull-Trauring - Johan Dahlin -""" - -from django.core.management.base import BaseCommand, CommandError -from optparse import make_option -from datetime import datetime -from django.conf import settings -import sys - -try: - from django.contrib.staticfiles.handlers import StaticFilesHandler - USE_STATICFILES = 'django.contrib.staticfiles' in settings.INSTALLED_APPS -except ImportError as e: - USE_STATICFILES = False - -try: - any -except NameError: - # backwards compatibility for <2.5 - def any(iterable): - for element in iterable: - if element: - return True - return False - - -def label(code): - if isinstance(code, str): - return ('~', 0, code) # built-in functions ('~' sorts at the end) - else: - return '%s %s:%d' % (code.co_name, - code.co_filename, - code.co_firstlineno) - - -class KCacheGrind(object): - def __init__(self, profiler): - self.data = profiler.getstats() - self.out_file = None - - def output(self, out_file): - self.out_file = out_file - self.out_file.write('events: Ticks\n') - self._print_summary() - for entry in self.data: - self._entry(entry) - - def _print_summary(self): - max_cost = 0 - for entry in self.data: - totaltime = int(entry.totaltime * 1000) - max_cost = max(max_cost, totaltime) - self.out_file.write('summary: %d\n' % (max_cost,)) - - def _entry(self, entry): - out_file = self.out_file - - code = entry.code - #print >> out_file, 'ob=%s' % (code.co_filename,) - if isinstance(code, str): - out_file.write('fi=~\n') - else: - out_file.write('fi=%s\n' % (code.co_filename,)) - out_file.write('fn=%s\n' % (label(code),)) - - inlinetime = int(entry.inlinetime * 1000) - if isinstance(code, str): - out_file.write('0 %s\n' % inlinetime) - else: - out_file.write('%d %d\n' % (code.co_firstlineno, inlinetime)) - - # recursive calls are counted in entry.calls - if entry.calls: - calls = entry.calls - else: - calls = [] - - if isinstance(code, str): - lineno = 0 - else: - lineno = code.co_firstlineno - - for subentry in calls: - self._subentry(lineno, subentry) - out_file.write("\n") - - def _subentry(self, lineno, subentry): - out_file = self.out_file - code = subentry.code - #out_file.write('cob=%s\n' % (code.co_filename,)) - out_file.write('cfn=%s\n' % (label(code),)) - if isinstance(code, str): - out_file.write('cfi=~\n') - out_file.write('calls=%d 0\n' % (subentry.callcount,)) - else: - out_file.write('cfi=%s\n' % (code.co_filename,)) - out_file.write('calls=%d %d\n' % (subentry.callcount, code.co_firstlineno)) - - totaltime = int(subentry.totaltime * 1000) - out_file.write('%d %d\n' % (lineno, totaltime)) - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--noreload', action='store_false', dest='use_reloader', default=True, - help='Tells Django to NOT use the auto-reloader.'), - make_option('--adminmedia', dest='admin_media_path', default='', - help='Specifies the directory from which to serve admin media.'), - make_option('--prof-path', dest='prof_path', default='/tmp', - help='Specifies the directory which to save profile information in.'), - make_option('--prof-file', dest='prof_file', default='{path}.{duration:06d}ms.{time}', - help='Set filename format, default if "{path}.{duration:06d}ms.{time}".'), - make_option('--nomedia', action='store_true', dest='no_media', default=False, - help='Do not profile MEDIA_URL and ADMIN_MEDIA_URL'), - make_option('--use-cprofile', action='store_true', dest='use_cprofile', default=False, - help='Use cProfile if available, this is disabled per default because of incompatibilities.'), - make_option('--kcachegrind', action='store_true', dest='use_lsprof', default=False, - help='Create kcachegrind compatible lsprof files, this requires and automatically enables cProfile.'), - ) - if USE_STATICFILES: - option_list += ( - make_option('--nostatic', action="store_false", dest='use_static_handler', default=True, - help='Tells Django to NOT automatically serve static files at STATIC_URL.'), - make_option('--insecure', action="store_true", dest='insecure_serving', default=False, - help='Allows serving static files even if DEBUG is False.'), - ) - help = "Starts a lightweight Web server with profiling enabled." - args = '[optional port number, or ipaddr:port]' - - # Validation is called explicitly each time the server is reloaded. - requires_model_validation = False - - def handle(self, addrport='', *args, **options): - import django - import socket - import errno - from django.core.servers.basehttp import run - try: - from django.core.servers.basehttp import get_internal_wsgi_application as WSGIHandler - except ImportError: - from django.core.handlers.wsgi import WSGIHandler # noqa - - try: - from django.core.servers.basehttp import AdminMediaHandler - HAS_ADMINMEDIAHANDLER = True - except ImportError: - HAS_ADMINMEDIAHANDLER = False - - try: - from django.core.servers.basehttp import WSGIServerException as wsgi_server_exc_cls - except ImportError: # Django 1.6 - wsgi_server_exc_cls = socket.error - - if args: - raise CommandError('Usage is runserver %s' % self.args) - if not addrport: - addr = '' - port = '8000' - else: - try: - addr, port = addrport.split(':') - except ValueError: - addr, port = '', addrport - if not addr: - addr = '127.0.0.1' - - if not port.isdigit(): - raise CommandError("%r is not a valid port number." % port) - - use_reloader = options.get('use_reloader', True) - shutdown_message = options.get('shutdown_message', '') - no_media = options.get('no_media', False) - quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C' - - def inner_run(): - import os - import time - try: - import hotshot - except ImportError: - pass # python 3.x - USE_CPROFILE = options.get('use_cprofile', False) - USE_LSPROF = options.get('use_lsprof', False) - if USE_LSPROF: - USE_CPROFILE = True - if USE_CPROFILE: - try: - import cProfile - USE_CPROFILE = True - except ImportError: - print("cProfile disabled, module cannot be imported!") - USE_CPROFILE = False - if USE_LSPROF and not USE_CPROFILE: - raise SystemExit("Kcachegrind compatible output format required cProfile from Python 2.5") - prof_path = options.get('prof_path', '/tmp') - - prof_file = options.get('prof_file', '{path}.{duration:06d}ms.{time}') - if not prof_file.format(path='1', duration=2, time=3): - prof_file = '{path}.{duration:06d}ms.{time}' - print("Filename format is wrong. Default format used: '{path}.{duration:06d}ms.{time}'.") - - def get_exclude_paths(): - exclude_paths = [] - media_url = getattr(settings, 'MEDIA_URL', None) - if media_url: - exclude_paths.append(media_url) - static_url = getattr(settings, 'STATIC_URL', None) - if static_url: - exclude_paths.append(static_url) - admin_media_prefix = getattr(settings, 'ADMIN_MEDIA_PREFIX', None) - if admin_media_prefix: - exclude_paths.append(admin_media_prefix) - return exclude_paths - - def make_profiler_handler(inner_handler): - def handler(environ, start_response): - path_info = environ['PATH_INFO'] - # when using something like a dynamic site middleware is could be necessary - # to refetch the exclude_paths every time since they could change per site. - if no_media and any(path_info.startswith(p) for p in get_exclude_paths()): - return inner_handler(environ, start_response) - path_name = path_info.strip("/").replace('/', '.') or "root" - profname = "%s.%d.prof" % (path_name, time.time()) - profname = os.path.join(prof_path, profname) - if USE_CPROFILE: - prof = cProfile.Profile() - else: - prof = hotshot.Profile(profname) - start = datetime.now() - try: - return prof.runcall(inner_handler, environ, start_response) - finally: - # seeing how long the request took is important! - elap = datetime.now() - start - elapms = elap.seconds * 1000.0 + elap.microseconds / 1000.0 - if USE_LSPROF: - kg = KCacheGrind(prof) - kg.output(open(profname, 'w')) - elif USE_CPROFILE: - prof.dump_stats(profname) - profname2 = prof_file.format(path=path_name, duration=int(elapms), time=int(time.time())) - profname2 = os.path.join(prof_path, "%s.prof" % profname2) - if not USE_CPROFILE: - prof.close() - os.rename(profname, profname2) - return handler - - print("Validating models...") - self.validate(display_num_errors=True) - print("\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)) - print("Development server is running at http://%s:%s/" % (addr, port)) - print("Quit the server with %s." % quit_command) - path = options.get('admin_media_path', '') - if not path: - admin_media_path = os.path.join(django.__path__[0], 'contrib/admin/static/admin') - if os.path.isdir(admin_media_path): - path = admin_media_path - else: - path = os.path.join(django.__path__[0], 'contrib/admin/media') - try: - handler = WSGIHandler() - if HAS_ADMINMEDIAHANDLER: - handler = AdminMediaHandler(handler, path) - if USE_STATICFILES: - use_static_handler = options.get('use_static_handler', True) - insecure_serving = options.get('insecure_serving', False) - if (use_static_handler and (settings.DEBUG or insecure_serving)): - handler = StaticFilesHandler(handler) - handler = make_profiler_handler(handler) - run(addr, int(port), handler) - except wsgi_server_exc_cls as e: - # Use helpful error messages instead of ugly tracebacks. - ERRORS = { - errno.EACCES: "You don't have permission to access that port.", - errno.EADDRINUSE: "That port is already in use.", - errno.EADDRNOTAVAIL: "That IP address can't be assigned-to.", - } - if not isinstance(e, socket.error): # Django < 1.6 - ERRORS[13] = ERRORS.pop(errno.EACCES) - ERRORS[98] = ERRORS.pop(errno.EADDRINUSE) - ERRORS[99] = ERRORS.pop(errno.EADDRNOTAVAIL) - try: - if not isinstance(e, socket.error): # Django < 1.6 - error_text = ERRORS[e.args[0].args[0]] - else: - error_text = ERRORS[e.errno] - except (AttributeError, KeyError): - error_text = str(e) - sys.stderr.write(self.style.ERROR("Error: %s" % error_text) + '\n') - # Need to use an OS exit because sys.exit doesn't work in a thread - os._exit(1) - except KeyboardInterrupt: - if shutdown_message: - print(shutdown_message) - sys.exit(0) - if use_reloader: - from django.utils import autoreload - autoreload.main(inner_run) - else: - inner_run() diff --git a/awx/lib/site-packages/django_extensions/management/commands/runscript.py b/awx/lib/site-packages/django_extensions/management/commands/runscript.py deleted file mode 100644 index 8b063c3797..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/runscript.py +++ /dev/null @@ -1,147 +0,0 @@ -from django.core.management.base import BaseCommand -from django.conf import settings -from optparse import make_option -import imp - - -def vararg_callback(option, opt_str, opt_value, parser): - parser.rargs.insert(0, opt_value) - value = [] - for arg in parser.rargs: - # stop on --foo like options - if arg[:2] == "--" and len(arg) > 2: - break - # stop on -a like options - if arg[:1] == "-": - break - value.append(arg) - - del parser.rargs[:len(value)] - setattr(parser.values, option.dest, value) - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--fixtures', action='store_true', dest='infixtures', default=False, - help='Only look in app.fixtures subdir'), - make_option('--noscripts', action='store_true', dest='noscripts', default=False, - help='Look in app.scripts subdir'), - make_option('-s', '--silent', action='store_true', dest='silent', default=False, - help='Run silently, do not show errors and tracebacks'), - make_option('--no-traceback', action='store_true', dest='no_traceback', default=False, - help='Do not show tracebacks'), - make_option('--script-args', action='callback', callback=vararg_callback, type='string', - help='Space-separated argument list to be passed to the scripts. Note that the ' - 'same arguments will be passed to all named scripts.'), - ) - help = 'Runs a script in django context.' - args = "script [script ...]" - - def handle(self, *scripts, **options): - NOTICE = self.style.SQL_TABLE - NOTICE2 = self.style.SQL_FIELD - ERROR = self.style.ERROR - ERROR2 = self.style.NOTICE - - subdirs = [] - - if not options.get('noscripts'): - subdirs.append('scripts') - if options.get('infixtures'): - subdirs.append('fixtures') - verbosity = int(options.get('verbosity', 1)) - show_traceback = options.get('traceback', True) - if show_traceback is None: - # XXX: traceback is set to None from Django ? - show_traceback = True - no_traceback = options.get('no_traceback', False) - if no_traceback: - show_traceback = False - silent = options.get('silent', False) - if silent: - verbosity = 0 - - if len(subdirs) < 1: - print(NOTICE("No subdirs to run left.")) - return - - if len(scripts) < 1: - print(ERROR("Script name required.")) - return - - def run_script(mod, *script_args): - try: - mod.run(*script_args) - except Exception: - if silent: - return - if verbosity > 0: - print(ERROR("Exception while running run() in '%s'" % mod.__name__)) - if show_traceback: - raise - - def my_import(mod): - if verbosity > 1: - print(NOTICE("Check for %s" % mod)) - # check if module exists before importing - try: - path = None - for package in mod.split('.')[:-1]: - module_tuple = imp.find_module(package, path) - path = imp.load_module(package, *module_tuple).__path__ - imp.find_module(mod.split('.')[-1], path) - t = __import__(mod, [], [], [" "]) - except (ImportError, AttributeError): - return False - - #if verbosity > 1: - # print(NOTICE("Found script %s ..." % mod)) - if hasattr(t, "run"): - if verbosity > 1: - print(NOTICE2("Found script '%s' ..." % mod)) - #if verbosity > 1: - # print(NOTICE("found run() in %s. executing..." % mod)) - return t - else: - if verbosity > 1: - print(ERROR2("Find script '%s' but no run() function found." % mod)) - - def find_modules_for_script(script): - """ find script module which contains 'run' attribute """ - modules = [] - # first look in apps - for app in settings.INSTALLED_APPS: - for subdir in subdirs: - mod = my_import("%s.%s.%s" % (app, subdir, script)) - if mod: - modules.append(mod) - - # try app.DIR.script import - sa = script.split(".") - for subdir in subdirs: - nn = ".".join(sa[:-1] + [subdir, sa[-1]]) - mod = my_import(nn) - if mod: - modules.append(mod) - - # try direct import - if script.find(".") != -1: - mod = my_import(script) - if mod: - modules.append(mod) - - return modules - - if options.get('script_args'): - script_args = options['script_args'] - else: - script_args = [] - for script in scripts: - modules = find_modules_for_script(script) - if not modules: - if verbosity > 0 and not silent: - print(ERROR("No module for script '%s' found" % script)) - for mod in modules: - if verbosity > 1: - print(NOTICE2("Running script '%s' ..." % mod.__name__)) - run_script(mod, *script_args) diff --git a/awx/lib/site-packages/django_extensions/management/commands/runserver_plus.py b/awx/lib/site-packages/django_extensions/management/commands/runserver_plus.py deleted file mode 100644 index b7cebcaa7f..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/runserver_plus.py +++ /dev/null @@ -1,293 +0,0 @@ -import os -import re -import socket -import sys -import time - -from optparse import make_option - -from django.conf import settings -from django.core.management.base import BaseCommand, CommandError -from django_extensions.management.utils import setup_logger, RedirectHandler -from django_extensions.management.technical_response import null_technical_500_response - - -try: - if 'django.contrib.staticfiles' in settings.INSTALLED_APPS: - from django.contrib.staticfiles.handlers import StaticFilesHandler - USE_STATICFILES = True - elif 'staticfiles' in settings.INSTALLED_APPS: - from staticfiles.handlers import StaticFilesHandler # noqa - USE_STATICFILES = True - else: - USE_STATICFILES = False -except ImportError: - USE_STATICFILES = False - - -naiveip_re = re.compile(r"""^(?: -(?P<addr> - (?P<ipv4>\d{1,3}(?:\.\d{1,3}){3}) | # IPv4 address - (?P<ipv6>\[[a-fA-F0-9:]+\]) | # IPv6 address - (?P<fqdn>[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*) # FQDN -):)?(?P<port>\d+)$""", re.X) -DEFAULT_PORT = "8000" - - -import logging -logger = logging.getLogger(__name__) - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--ipv6', '-6', action='store_true', dest='use_ipv6', default=False, - help='Tells Django to use a IPv6 address.'), - make_option('--noreload', action='store_false', dest='use_reloader', default=True, - help='Tells Django to NOT use the auto-reloader.'), - make_option('--browser', action='store_true', dest='open_browser', - help='Tells Django to open a browser.'), - make_option('--adminmedia', dest='admin_media_path', default='', - help='Specifies the directory from which to serve admin media.'), - make_option('--threaded', action='store_true', dest='threaded', - help='Run in multithreaded mode.'), - make_option('--output', dest='output_file', default=None, - help='Specifies an output file to send a copy of all messages (not flushed immediately).'), - make_option('--print-sql', action='store_true', default=False, - help="Print SQL queries as they're executed"), - make_option('--cert', dest='cert_path', action="store", type="string", - help='To use SSL, specify certificate path.'), - - ) - if USE_STATICFILES: - option_list += ( - make_option('--nostatic', action="store_false", dest='use_static_handler', default=True, - help='Tells Django to NOT automatically serve static files at STATIC_URL.'), - make_option('--insecure', action="store_true", dest='insecure_serving', default=False, - help='Allows serving static files even if DEBUG is False.'), - ) - help = "Starts a lightweight Web server for development." - args = '[optional port number, or ipaddr:port]' - - # Validation is called explicitly each time the server is reloaded. - requires_model_validation = False - - def handle(self, addrport='', *args, **options): - import django - - setup_logger(logger, self.stderr, filename=options.get('output_file', None)) # , fmt="[%(name)s] %(message)s") - logredirect = RedirectHandler(__name__) - - # Redirect werkzeug log items - werklogger = logging.getLogger('werkzeug') - werklogger.setLevel(logging.INFO) - werklogger.addHandler(logredirect) - werklogger.propagate = False - - if options.get("print_sql", False): - from django.db.backends import util - try: - import sqlparse - except ImportError: - sqlparse = None # noqa - - class PrintQueryWrapper(util.CursorDebugWrapper): - def execute(self, sql, params=()): - starttime = time.time() - try: - return self.cursor.execute(sql, params) - finally: - raw_sql = self.db.ops.last_executed_query(self.cursor, sql, params) - execution_time = time.time() - starttime - therest = ' -- [Execution time: %.6fs] [Database: %s]' % (execution_time, self.db.alias) - if sqlparse: - logger.info(sqlparse.format(raw_sql, reindent=True) + therest) - else: - logger.info(raw_sql + therest) - - util.CursorDebugWrapper = PrintQueryWrapper - - try: - from django.core.servers.basehttp import AdminMediaHandler - USE_ADMINMEDIAHANDLER = True - except ImportError: - USE_ADMINMEDIAHANDLER = False - - try: - from django.core.servers.basehttp import get_internal_wsgi_application as WSGIHandler - except ImportError: - from django.core.handlers.wsgi import WSGIHandler # noqa - - try: - from werkzeug import run_simple, DebuggedApplication - - # Set colored output - if settings.DEBUG: - try: - set_werkzeug_log_color() - except: # We are dealing with some internals, anything could go wrong - print("Wrapping internal werkzeug logger for color highlighting has failed!") - pass - - except ImportError: - raise CommandError("Werkzeug is required to use runserver_plus. Please visit http://werkzeug.pocoo.org/ or install via pip. (pip install Werkzeug)") - - # usurp django's handler - from django.views import debug - debug.technical_500_response = null_technical_500_response - - self.use_ipv6 = options.get('use_ipv6') - if self.use_ipv6 and not socket.has_ipv6: - raise CommandError('Your Python does not support IPv6.') - self._raw_ipv6 = False - if not addrport: - try: - addrport = settings.RUNSERVERPLUS_SERVER_ADDRESS_PORT - except AttributeError: - pass - if not addrport: - self.addr = '' - self.port = DEFAULT_PORT - else: - m = re.match(naiveip_re, addrport) - if m is None: - raise CommandError('"%s" is not a valid port number ' - 'or address:port pair.' % addrport) - self.addr, _ipv4, _ipv6, _fqdn, self.port = m.groups() - if not self.port.isdigit(): - raise CommandError("%r is not a valid port number." % - self.port) - if self.addr: - if _ipv6: - self.addr = self.addr[1:-1] - self.use_ipv6 = True - self._raw_ipv6 = True - elif self.use_ipv6 and not _fqdn: - raise CommandError('"%s" is not a valid IPv6 address.' - % self.addr) - if not self.addr: - self.addr = '::1' if self.use_ipv6 else '127.0.0.1' - - threaded = options.get('threaded', False) - use_reloader = options.get('use_reloader', True) - open_browser = options.get('open_browser', False) - cert_path = options.get("cert_path") - quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C' - bind_url = "http://%s:%s/" % ( - self.addr if not self._raw_ipv6 else '[%s]' % self.addr, self.port) - - def inner_run(): - print("Validating models...") - self.validate(display_num_errors=True) - print("\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)) - print("Development server is running at %s" % (bind_url,)) - print("Using the Werkzeug debugger (http://werkzeug.pocoo.org/)") - print("Quit the server with %s." % quit_command) - path = options.get('admin_media_path', '') - if not path: - admin_media_path = os.path.join(django.__path__[0], 'contrib/admin/static/admin') - if os.path.isdir(admin_media_path): - path = admin_media_path - else: - path = os.path.join(django.__path__[0], 'contrib/admin/media') - handler = WSGIHandler() - if USE_ADMINMEDIAHANDLER: - handler = AdminMediaHandler(handler, path) - if USE_STATICFILES: - use_static_handler = options.get('use_static_handler', True) - insecure_serving = options.get('insecure_serving', False) - if use_static_handler and (settings.DEBUG or insecure_serving): - handler = StaticFilesHandler(handler) - if open_browser: - import webbrowser - webbrowser.open(bind_url) - if cert_path: - """ - OpenSSL is needed for SSL support. - - This will make flakes8 throw warning since OpenSSL is not used - directly, alas, this is the only way to show meaningful error - messages. See: - http://lucumr.pocoo.org/2011/9/21/python-import-blackbox/ - for more information on python imports. - """ - try: - import OpenSSL # NOQA - except ImportError: - raise CommandError("Python OpenSSL Library is " - "required to use runserver_plus with ssl support. " - "Install via pip (pip install pyOpenSSL).") - - dir_path, cert_file = os.path.split(cert_path) - if not dir_path: - dir_path = os.getcwd() - root, ext = os.path.splitext(cert_file) - certfile = os.path.join(dir_path, root + ".crt") - keyfile = os.path.join(dir_path, root + ".key") - try: - from werkzeug.serving import make_ssl_devcert - if os.path.exists(certfile) and \ - os.path.exists(keyfile): - ssl_context = (certfile, keyfile) - else: # Create cert, key files ourselves. - ssl_context = make_ssl_devcert( - os.path.join(dir_path, root), host='localhost') - except ImportError: - print("Werkzeug version is less than 0.9, trying adhoc certificate.") - ssl_context = "adhoc" - - else: - ssl_context = None - run_simple( - self.addr, - int(self.port), - DebuggedApplication(handler, True), - use_reloader=use_reloader, - use_debugger=True, - threaded=threaded, - ssl_context=ssl_context - ) - inner_run() - - -def set_werkzeug_log_color(): - """Try to set color to the werkzeug log. - """ - from django.core.management.color import color_style - from werkzeug.serving import WSGIRequestHandler - from werkzeug._internal import _log - - _style = color_style() - _orig_log = WSGIRequestHandler.log - - def werk_log(self, type, message, *args): - try: - msg = '%s - - [%s] %s' % ( - self.address_string(), - self.log_date_time_string(), - message % args, - ) - http_code = str(args[1]) - except: - return _orig_log(type, message, *args) - - # Utilize terminal colors, if available - if http_code[0] == '2': - # Put 2XX first, since it should be the common case - msg = _style.HTTP_SUCCESS(msg) - elif http_code[0] == '1': - msg = _style.HTTP_INFO(msg) - elif http_code == '304': - msg = _style.HTTP_NOT_MODIFIED(msg) - elif http_code[0] == '3': - msg = _style.HTTP_REDIRECT(msg) - elif http_code == '404': - msg = _style.HTTP_NOT_FOUND(msg) - elif http_code[0] == '4': - msg = _style.HTTP_BAD_REQUEST(msg) - else: - # Any 5XX, or any other response - msg = _style.HTTP_SERVER_ERROR(msg) - - _log(type, msg) - - WSGIRequestHandler.log = werk_log diff --git a/awx/lib/site-packages/django_extensions/management/commands/set_default_site.py b/awx/lib/site-packages/django_extensions/management/commands/set_default_site.py deleted file mode 100644 index 6bb0f78082..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/set_default_site.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -set_default_site.py -""" -import socket -from optparse import make_option - -from django.core.management.base import NoArgsCommand, CommandError - - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option('--name', dest='site_name', default=None, - help='Use this as site name.'), - make_option('--domain', dest='site_domain', default=None, - help='Use this as site domain.'), - make_option('--system-fqdn', dest='set_as_system_fqdn', default=False, - action="store_true", help='Use the systems FQDN (Fully Qualified Domain Name) as name and domain. Can be used in combination with --name'), - ) - help = "Set parameters of the default django.contrib.sites Site" - requires_model_validation = True - - def handle_noargs(self, **options): - from django.contrib.sites.models import Site - - try: - site = Site.objects.get(pk=1) - except Site.DoesNotExist: - raise CommandError("Default site with pk=1 does not exist") - else: - name = options.get("site_name", None) - domain = options.get("site_domain", None) - if options.get('set_as_system_fqdn', False): - domain = socket.getfqdn() - if not domain: - raise CommandError("Cannot find systems FQDN") - if name is None: - name = domain - - update_kwargs = {} - if name and name != site.name: - update_kwargs["name"] = name - - if domain and domain != site.domain: - update_kwargs["domain"] = domain - - if update_kwargs: - Site.objects.filter(pk=1).update(**update_kwargs) - site = Site.objects.get(pk=1) - print("Updated default site. You might need to restart django as sites are cached aggressively.") - else: - print("Nothing to update (need --name, --domain and/or --system-fqdn)") - - print("Default Site:") - print("\tid = %s" % site.id) - print("\tname = %s" % site.name) - print("\tdomain = %s" % site.domain) diff --git a/awx/lib/site-packages/django_extensions/management/commands/set_fake_emails.py b/awx/lib/site-packages/django_extensions/management/commands/set_fake_emails.py deleted file mode 100644 index effeb476e2..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/set_fake_emails.py +++ /dev/null @@ -1,81 +0,0 @@ -""" -set_fake_emails.py - - Give all users a new email account. Useful for testing in a - development environment. As such, this command is only available when - setting.DEBUG is True. - -""" -from optparse import make_option - -from django.conf import settings -from django.core.management.base import NoArgsCommand, CommandError - -DEFAULT_FAKE_EMAIL = '%(username)s@example.com' - - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option('--email', dest='default_email', default=DEFAULT_FAKE_EMAIL, - help='Use this as the new email format.'), - make_option('-a', '--no-admin', action="store_true", dest='no_admin', default=False, - help='Do not change administrator accounts'), - make_option('-s', '--no-staff', action="store_true", dest='no_staff', default=False, - help='Do not change staff accounts'), - make_option('--include', dest='include_regexp', default=None, - help='Include usernames matching this regexp.'), - make_option('--exclude', dest='exclude_regexp', default=None, - help='Exclude usernames matching this regexp.'), - make_option('--include-groups', dest='include_groups', default=None, - help='Include users matching this group. (use comma seperation for multiple groups)'), - make_option('--exclude-groups', dest='exclude_groups', default=None, - help='Exclude users matching this group. (use comma seperation for multiple groups)'), - ) - help = '''DEBUG only: give all users a new email based on their account data ("%s" by default). Possible parameters are: username, first_name, last_name''' % (DEFAULT_FAKE_EMAIL, ) - requires_model_validation = False - - def handle_noargs(self, **options): - if not settings.DEBUG: - raise CommandError('Only available in debug mode') - - try: - from django.contrib.auth import get_user_model # Django 1.5 - except ImportError: - from django_extensions.future_1_5 import get_user_model - from django.contrib.auth.models import Group - email = options.get('default_email', DEFAULT_FAKE_EMAIL) - include_regexp = options.get('include_regexp', None) - exclude_regexp = options.get('exclude_regexp', None) - include_groups = options.get('include_groups', None) - exclude_groups = options.get('exclude_groups', None) - no_admin = options.get('no_admin', False) - no_staff = options.get('no_staff', False) - - User = get_user_model() - users = User.objects.all() - if no_admin: - users = users.exclude(is_superuser=True) - if no_staff: - users = users.exclude(is_staff=True) - if exclude_groups: - groups = Group.objects.filter(name__in=exclude_groups.split(",")) - if groups: - users = users.exclude(groups__in=groups) - else: - raise CommandError("No group matches filter: %s" % exclude_groups) - if include_groups: - groups = Group.objects.filter(name__in=include_groups.split(",")) - if groups: - users = users.filter(groups__in=groups) - else: - raise CommandError("No groups matches filter: %s" % include_groups) - if exclude_regexp: - users = users.exclude(username__regex=exclude_regexp) - if include_regexp: - users = users.filter(username__regex=include_regexp) - for user in users: - user.email = email % {'username': user.username, - 'first_name': user.first_name, - 'last_name': user.last_name} - user.save() - print('Changed %d emails' % users.count()) diff --git a/awx/lib/site-packages/django_extensions/management/commands/set_fake_passwords.py b/awx/lib/site-packages/django_extensions/management/commands/set_fake_passwords.py deleted file mode 100644 index e502fbfdb4..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/set_fake_passwords.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -set_fake_passwords.py - - Reset all user passwords to a common value. Useful for testing in a - development environment. As such, this command is only available when - setting.DEBUG is True. - -""" -from optparse import make_option - -from django.conf import settings -from django.core.management.base import NoArgsCommand, CommandError - -DEFAULT_FAKE_PASSWORD = 'password' - - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option('--prompt', dest='prompt_passwd', default=False, action='store_true', - help='Prompts for the new password to apply to all users'), - make_option('--password', dest='default_passwd', default=DEFAULT_FAKE_PASSWORD, - help='Use this as default password.'), - ) - help = 'DEBUG only: sets all user passwords to a common value ("%s" by default)' % (DEFAULT_FAKE_PASSWORD, ) - requires_model_validation = False - - def handle_noargs(self, **options): - if not settings.DEBUG: - raise CommandError('Only available in debug mode') - - try: - from django.contrib.auth import get_user_model # Django 1.5 - except ImportError: - from django_extensions.future_1_5 import get_user_model - - if options.get('prompt_passwd', False): - from getpass import getpass - passwd = getpass('Password: ') - if not passwd: - raise CommandError('You must enter a valid password') - else: - passwd = options.get('default_passwd', DEFAULT_FAKE_PASSWORD) - - User = get_user_model() - user = User() - user.set_password(passwd) - count = User.objects.all().update(password=user.password) - - print('Reset %d passwords' % count) diff --git a/awx/lib/site-packages/django_extensions/management/commands/shell_plus.py b/awx/lib/site-packages/django_extensions/management/commands/shell_plus.py deleted file mode 100644 index 707dd6cb07..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/shell_plus.py +++ /dev/null @@ -1,170 +0,0 @@ -import os -import six -import time -from optparse import make_option - -from django.core.management.base import NoArgsCommand -from django.conf import settings - -from django_extensions.management.shells import import_objects - - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option('--plain', action='store_true', dest='plain', - help='Tells Django to use plain Python, not BPython nor IPython.'), - make_option('--bpython', action='store_true', dest='bpython', - help='Tells Django to use BPython, not IPython.'), - make_option('--ipython', action='store_true', dest='ipython', - help='Tells Django to use IPython, not BPython.'), - make_option('--notebook', action='store_true', dest='notebook', - help='Tells Django to use IPython Notebook.'), - make_option('--use-pythonrc', action='store_true', dest='use_pythonrc', - help='Tells Django to execute PYTHONSTARTUP file (BE CAREFULL WITH THIS!)'), - make_option('--print-sql', action='store_true', default=False, - help="Print SQL queries as they're executed"), - make_option('--dont-load', action='append', dest='dont_load', default=[], - help='Ignore autoloading of some apps/models. Can be used several times.'), - make_option('--quiet-load', action='store_true', default=False, dest='quiet_load', - help='Do not display loaded models messages'), - ) - help = "Like the 'shell' command but autoloads the models of all installed Django apps." - - requires_model_validation = True - - def handle_noargs(self, **options): - use_notebook = options.get('notebook', False) - use_ipython = options.get('ipython', False) - use_bpython = options.get('bpython', False) - use_plain = options.get('plain', False) - use_pythonrc = options.get('use_pythonrc', True) - - if options.get("print_sql", False): - # Code from http://gist.github.com/118990 - from django.db.backends import util - sqlparse = None - try: - import sqlparse - except ImportError: - pass - - class PrintQueryWrapper(util.CursorDebugWrapper): - def execute(self, sql, params=()): - starttime = time.time() - try: - return self.cursor.execute(sql, params) - finally: - execution_time = time.time() - starttime - raw_sql = self.db.ops.last_executed_query(self.cursor, sql, params) - if sqlparse: - print(sqlparse.format(raw_sql, reindent=True)) - else: - print(raw_sql) - print("") - print('Execution time: %.6fs [Database: %s]' % (execution_time, self.db.alias)) - print("") - - util.CursorDebugWrapper = PrintQueryWrapper - - def run_notebook(): - from django.conf import settings - try: - from IPython.html.notebookapp import NotebookApp - except ImportError: - from IPython.frontend.html.notebook import notebookapp - NotebookApp = notebookapp.NotebookApp - app = NotebookApp.instance() - ipython_arguments = getattr(settings, 'IPYTHON_ARGUMENTS', ['--ext', 'django_extensions.management.notebook_extension']) - app.initialize(ipython_arguments) - app.start() - - def run_plain(): - # Using normal Python shell - import code - imported_objects = import_objects(options, self.style) - try: - # Try activating rlcompleter, because it's handy. - import readline - except ImportError: - pass - else: - # We don't have to wrap the following import in a 'try', because - # we already know 'readline' was imported successfully. - import rlcompleter - readline.set_completer(rlcompleter.Completer(imported_objects).complete) - readline.parse_and_bind("tab:complete") - - # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system - # conventions and get $PYTHONSTARTUP first then import user. - if use_pythonrc: - pythonrc = os.environ.get("PYTHONSTARTUP") - if pythonrc and os.path.isfile(pythonrc): - global_ns = {} - with open(pythonrc) as rcfile: - try: - six.exec_(compile(rcfile.read(), pythonrc, 'exec'), global_ns) - imported_objects.update(global_ns) - except NameError: - pass - # This will import .pythonrc.py as a side-effect - try: - import user # NOQA - except ImportError: - pass - code.interact(local=imported_objects) - - def run_bpython(): - from bpython import embed - imported_objects = import_objects(options, self.style) - embed(imported_objects) - - def run_ipython(): - try: - from IPython import embed - imported_objects = import_objects(options, self.style) - embed(user_ns=imported_objects) - except ImportError: - # IPython < 0.11 - # Explicitly pass an empty list as arguments, because otherwise - # IPython would use sys.argv from this script. - # Notebook not supported for IPython < 0.11. - from IPython.Shell import IPShell - imported_objects = import_objects(options, self.style) - shell = IPShell(argv=[], user_ns=imported_objects) - shell.mainloop() - - shells = ( - ('bpython', run_bpython), - ('ipython', run_ipython), - ('plain', run_plain), - ) - SETTINGS_SHELL_PLUS = getattr(settings, 'SHELL_PLUS', None) - - if use_notebook: - run_notebook() - elif use_plain: - run_plain() - elif use_ipython: - run_ipython() - elif use_bpython: - run_bpython() - elif SETTINGS_SHELL_PLUS: - try: - dict(shells)[SETTINGS_SHELL_PLUS]() - except ImportError: - import traceback - traceback.print_exc() - print(self.style.ERROR("Could not load '%s' Python environment." % SETTINGS_SHELL_PLUS)) - else: - for shell_name, func in shells: - try: - func() - except ImportError: - continue - else: - break - else: - import traceback - traceback.print_exc() - print(self.style.ERROR("Could not load any interactive Python environment.")) - diff --git a/awx/lib/site-packages/django_extensions/management/commands/show_templatetags.py b/awx/lib/site-packages/django_extensions/management/commands/show_templatetags.py deleted file mode 100644 index 506f9f29f6..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/show_templatetags.py +++ /dev/null @@ -1,106 +0,0 @@ -import os -import six -import inspect -from django.conf import settings -from django.core.management.base import BaseCommand -from django.core.management import color -from django.template import get_library -from django.utils import termcolors - -try: - from django.utils.encoding import smart_text -except ImportError: - smart_text = six.u - - -def color_style(): - style = color.color_style() - style.FILTER = termcolors.make_style(fg='yellow', opts=('bold',)) - style.MODULE_NAME = termcolors.make_style(fg='green', opts=('bold',)) - style.TAG = termcolors.make_style(fg='red', opts=('bold',)) - style.TAGLIB = termcolors.make_style(fg='blue', opts=('bold',)) - return style - - -def format_block(block, nlspaces=0): - '''Format the given block of text, trimming leading/trailing - empty lines and any leading whitespace that is common to all lines. - The purpose is to let us list a code block as a multiline, - triple-quoted Python string, taking care of - indentation concerns. - http://code.activestate.com/recipes/145672/''' - - import re - - # separate block into lines - lines = smart_text(block).split('\n') - - # remove leading/trailing empty lines - while lines and not lines[0]: - del lines[0] - while lines and not lines[-1]: - del lines[-1] - - # look at first line to see how much indentation to trim - ws = re.match(r'\s*', lines[0]).group(0) - if ws: - lines = map(lambda x: x.replace(ws, '', 1), lines) - - # remove leading/trailing blank lines (after leading ws removal) - # we do this again in case there were pure-whitespace lines - while lines and not lines[0]: - del lines[0] - while lines and not lines[-1]: - del lines[-1] - - # account for user-specified leading spaces - flines = ['%s%s' % (' ' * nlspaces, line) for line in lines] - - return '\n'.join(flines) + '\n' - - -class Command(BaseCommand): - help = "Displays template tags and filters available in the current project." - results = "" - - def add_result(self, s, depth=0): - self.results += '%s\n' % s.rjust(depth * 4 + len(s)) - - def handle(self, *args, **options): - if args: - appname, = args - - style = color_style() - - if settings.ADMIN_FOR: - settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR] - else: - settings_modules = [settings] - - for settings_mod in settings_modules: - for app in settings_mod.INSTALLED_APPS: - try: - templatetag_mod = __import__(app + '.templatetags', {}, {}, ['']) - except ImportError: - continue - mod_path = inspect.getabsfile(templatetag_mod) - mod_files = os.listdir(os.path.dirname(mod_path)) - tag_files = [i.rstrip('.py') for i in mod_files if i.endswith('.py') and i[0] != '_'] - app_labeled = False - for taglib in tag_files: - try: - lib = get_library(taglib) - except: - continue - if not app_labeled: - self.add_result('App: %s' % style.MODULE_NAME(app)) - app_labeled = True - self.add_result('load: %s' % style.TAGLIB(taglib), 1) - for items, label, style_func in [(lib.tags, 'Tag:', style.TAG), (lib.filters, 'Filter:', style.FILTER)]: - for item in items: - self.add_result('%s %s' % (label, style_func(item)), 2) - doc = inspect.getdoc(items[item]) - if doc: - self.add_result(format_block(doc, 12)) - return self.results - # return "\n".join(results) diff --git a/awx/lib/site-packages/django_extensions/management/commands/show_urls.py b/awx/lib/site-packages/django_extensions/management/commands/show_urls.py deleted file mode 100644 index 1212357748..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/show_urls.py +++ /dev/null @@ -1,103 +0,0 @@ -from django.conf import settings -from django.core.exceptions import ViewDoesNotExist -from django.core.urlresolvers import RegexURLPattern, RegexURLResolver -from django.core.management.base import BaseCommand -from optparse import make_option - -try: - # 2008-05-30 admindocs found in newforms-admin brand - from django.contrib.admindocs.views import simplify_regex - assert simplify_regex -except ImportError: - # fall back to trunk, pre-NFA merge - from django.contrib.admin.views.doc import simplify_regex -import re - -from django_extensions.management.color import color_style - - -def extract_views_from_urlpatterns(urlpatterns, base=''): - """ - Return a list of views from a list of urlpatterns. - - Each object in the returned list is a two-tuple: (view_func, regex) - """ - views = [] - for p in urlpatterns: - if isinstance(p, RegexURLPattern): - try: - views.append((p.callback, base + p.regex.pattern, p.name)) - except ViewDoesNotExist: - continue - elif isinstance(p, RegexURLResolver): - try: - patterns = p.url_patterns - except ImportError: - continue - views.extend(extract_views_from_urlpatterns(patterns, base + p.regex.pattern)) - elif hasattr(p, '_get_callback'): - try: - views.append((p._get_callback(), base + p.regex.pattern, p.name)) - except ViewDoesNotExist: - continue - elif hasattr(p, 'url_patterns') or hasattr(p, '_get_url_patterns'): - try: - patterns = p.url_patterns - except ImportError: - continue - views.extend(extract_views_from_urlpatterns(patterns, base + p.regex.pattern)) - else: - raise TypeError("%s does not appear to be a urlpattern object" % p) - return views - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option("--unsorted", "-u", action="store_true", dest="unsorted", - help="Show urls unsorted but same order as found in url patterns"), - ) - - help = "Displays all of the url matching routes for the project." - - requires_model_validation = True - - def handle(self, *args, **options): - if args: - appname, = args - - style = color_style() - - if settings.ADMIN_FOR: - settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR] - else: - settings_modules = [settings] - - views = [] - for settings_mod in settings_modules: - try: - urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, ['']) - except Exception as e: - if options.get('traceback', None): - import traceback - traceback.print_exc() - print(style.ERROR("Error occurred while trying to load %s: %s" % (settings_mod.ROOT_URLCONF, str(e)))) - continue - view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) - for (func, regex, url_name) in view_functions: - if hasattr(func, '__name__'): - func_name = func.__name__ - elif hasattr(func, '__class__'): - func_name = '%s()' % func.__class__.__name__ - else: - func_name = re.sub(r' at 0x[0-9a-f]+', '', repr(func)) - views.append("%(url)s\t%(module)s.%(name)s\t%(url_name)s" % { - 'name': style.MODULE_NAME(func_name), - 'module': style.MODULE(func.__module__), - 'url_name': style.URL_NAME(url_name or ''), - 'url': style.URL(simplify_regex(regex)) - }) - - if not options.get('unsorted', False): - views = sorted(views) - - return "\n".join([v for v in views]) + "\n" diff --git a/awx/lib/site-packages/django_extensions/management/commands/sqlcreate.py b/awx/lib/site-packages/django_extensions/management/commands/sqlcreate.py deleted file mode 100644 index 3f749ded91..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/sqlcreate.py +++ /dev/null @@ -1,72 +0,0 @@ -import sys -import socket - -from optparse import make_option - -from django.conf import settings -from django.core.management.base import CommandError, BaseCommand - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('-R', '--router', action='store', - dest='router', default='default', - help='Use this router-database other then defined in settings.py'), - make_option('-D', '--drop', action='store_true', - dest='drop', default=False, - help='If given, includes commands to drop any existing user and database.'), - ) - help = """Generates the SQL to create your database for you, as specified in settings.py -The envisioned use case is something like this: - - ./manage.py sqlcreate [--router=<routername>] | mysql -u <db_administrator> -p - ./manage.py sqlcreate [--router=<routername>] | psql -U <db_administrator> -W""" - - requires_model_validation = False - can_import_settings = True - - def handle(self, *args, **options): - - router = options.get('router') - dbinfo = settings.DATABASES.get(router) - if dbinfo is None: - raise CommandError("Unknown database router %s" % router) - - engine = dbinfo.get('ENGINE').split('.')[-1] - dbuser = dbinfo.get('USER') - dbpass = dbinfo.get('PASSWORD') - dbname = dbinfo.get('NAME') - dbhost = dbinfo.get('HOST') - dbclient = socket.gethostname() - - # django settings file tells you that localhost should be specified by leaving - # the DATABASE_HOST blank - if not dbhost: - dbhost = 'localhost' - - if engine == 'mysql': - sys.stderr.write("""-- WARNING!: https://docs.djangoproject.com/en/dev/ref/databases/#collation-settings --- Please read this carefully! Collation will be set to utf8_bin to have case-sensitive data. -""") - print("CREATE DATABASE %s CHARACTER SET utf8 COLLATE utf8_bin;" % dbname) - print("GRANT ALL PRIVILEGES ON %s.* to '%s'@'%s' identified by '%s';" % ( - dbname, dbuser, dbclient, dbpass - )) - - elif engine == 'postgresql_psycopg2': - if options.get('drop'): - print("DROP DATABASE IF EXISTS %s;" % (dbname,)) - print("DROP USER IF EXISTS %s;" % (dbuser,)) - - print("CREATE USER %s WITH ENCRYPTED PASSWORD '%s' CREATEDB;" % (dbuser, dbpass)) - print("CREATE DATABASE %s WITH ENCODING 'UTF-8' OWNER \"%s\";" % (dbname, dbuser)) - print("GRANT ALL PRIVILEGES ON DATABASE %s TO %s;" % (dbname, dbuser)) - - elif engine == 'sqlite3': - sys.stderr.write("-- manage.py syncdb will automatically create a sqlite3 database file.\n") - - else: - # CREATE DATABASE is not SQL standard, but seems to be supported by most. - sys.stderr.write("-- Don't know how to handle '%s' falling back to SQL.\n" % engine) - print("CREATE DATABASE %s;" % dbname) - print("GRANT ALL PRIVILEGES ON DATABASE %s to %s" % (dbname, dbuser)) diff --git a/awx/lib/site-packages/django_extensions/management/commands/sqldiff.py b/awx/lib/site-packages/django_extensions/management/commands/sqldiff.py deleted file mode 100644 index 2301f8de13..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/sqldiff.py +++ /dev/null @@ -1,757 +0,0 @@ -""" -sqldiff.py - Prints the (approximated) difference between models and database - -TODO: - - better support for relations - - better support for constraints (mainly postgresql?) - - support for table spaces with postgresql - - when a table is not managed (meta.managed==False) then only do a one-way - sqldiff ? show differences from db->table but not the other way around since - it's not managed. - -KNOWN ISSUES: - - MySQL has by far the most problems with introspection. Please be - carefull when using MySQL with sqldiff. - - Booleans are reported back as Integers, so there's know way to know if - there was a real change. - - Varchar sizes are reported back without unicode support so their size - may change in comparison to the real length of the varchar. - - Some of the 'fixes' to counter these problems might create false - positives or false negatives. -""" - -import six -from django.core.management.base import BaseCommand -from django.core.management import sql as _sql -from django.core.management import CommandError -from django.core.management.color import no_style -from django.db import transaction, connection -from django.db.models.fields import IntegerField -from optparse import make_option - -ORDERING_FIELD = IntegerField('_order', null=True) - - -def flatten(l, ltypes=(list, tuple)): - ltype = type(l) - l = list(l) - i = 0 - while i < len(l): - while isinstance(l[i], ltypes): - if not l[i]: - l.pop(i) - i -= 1 - break - else: - l[i:i + 1] = l[i] - i += 1 - return ltype(l) - - -def all_local_fields(meta): - all_fields = [] - if meta.managed: - if meta.proxy: - for parent in meta.parents: - all_fields.extend(all_local_fields(parent._meta)) - else: - for f in meta.local_fields: - col_type = f.db_type(connection=connection) - if col_type is None: - continue - all_fields.append(f) - return all_fields - - -class SQLDiff(object): - DATA_TYPES_REVERSE_OVERRIDE = {} - - DIFF_TYPES = [ - 'error', - 'comment', - 'table-missing-in-db', - 'field-missing-in-db', - 'field-missing-in-model', - 'fkey-missing-in-db', - 'fkey-missing-in-model', - 'index-missing-in-db', - 'index-missing-in-model', - 'unique-missing-in-db', - 'unique-missing-in-model', - 'field-type-differ', - 'field-parameter-differ', - 'notnull-differ', - ] - DIFF_TEXTS = { - 'error': 'error: %(0)s', - 'comment': 'comment: %(0)s', - 'table-missing-in-db': "table '%(0)s' missing in database", - 'field-missing-in-db': "field '%(1)s' defined in model but missing in database", - 'field-missing-in-model': "field '%(1)s' defined in database but missing in model", - 'fkey-missing-in-db': "field '%(1)s' FOREIGN KEY defined in model but missing in database", - 'fkey-missing-in-model': "field '%(1)s' FOREIGN KEY defined in database but missing in model", - 'index-missing-in-db': "field '%(1)s' INDEX defined in model but missing in database", - 'index-missing-in-model': "field '%(1)s' INDEX defined in database schema but missing in model", - 'unique-missing-in-db': "field '%(1)s' UNIQUE defined in model but missing in database", - 'unique-missing-in-model': "field '%(1)s' UNIQUE defined in database schema but missing in model", - 'field-type-differ': "field '%(1)s' not of same type: db='%(3)s', model='%(2)s'", - 'field-parameter-differ': "field '%(1)s' parameters differ: db='%(3)s', model='%(2)s'", - 'notnull-differ': "field '%(1)s' null differ: db='%(3)s', model='%(2)s'", - } - - SQL_FIELD_MISSING_IN_DB = lambda self, style, qn, args: "%s %s\n\t%s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('ADD COLUMN'), style.SQL_FIELD(qn(args[1])), ' '.join(style.SQL_COLTYPE(a) if i == 0 else style.SQL_KEYWORD(a) for i, a in enumerate(args[2:]))) - SQL_FIELD_MISSING_IN_MODEL = lambda self, style, qn, args: "%s %s\n\t%s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('DROP COLUMN'), style.SQL_FIELD(qn(args[1]))) - SQL_FKEY_MISSING_IN_DB = lambda self, style, qn, args: "%s %s\n\t%s %s %s %s %s (%s)%s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('ADD COLUMN'), style.SQL_FIELD(qn(args[1])), ' '.join(style.SQL_COLTYPE(a) if i == 0 else style.SQL_KEYWORD(a) for i, a in enumerate(args[4:])), style.SQL_KEYWORD('REFERENCES'), style.SQL_TABLE(qn(args[2])), style.SQL_FIELD(qn(args[3])), connection.ops.deferrable_sql()) - SQL_INDEX_MISSING_IN_DB = lambda self, style, qn, args: "%s %s\n\t%s %s (%s%s);" % (style.SQL_KEYWORD('CREATE INDEX'), style.SQL_TABLE(qn("%s" % '_'.join(a for a in args[0:3] if a))), style.SQL_KEYWORD('ON'), style.SQL_TABLE(qn(args[0])), style.SQL_FIELD(qn(args[1])), style.SQL_KEYWORD(args[3])) - # FIXME: need to lookup index name instead of just appending _idx to table + fieldname - SQL_INDEX_MISSING_IN_MODEL = lambda self, style, qn, args: "%s %s;" % (style.SQL_KEYWORD('DROP INDEX'), style.SQL_TABLE(qn("%s" % '_'.join(a for a in args[0:3] if a)))) - SQL_UNIQUE_MISSING_IN_DB = lambda self, style, qn, args: "%s %s\n\t%s %s (%s);" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('ADD COLUMN'), style.SQL_KEYWORD('UNIQUE'), style.SQL_FIELD(qn(args[1]))) - # FIXME: need to lookup unique constraint name instead of appending _key to table + fieldname - SQL_UNIQUE_MISSING_IN_MODEL = lambda self, style, qn, args: "%s %s\n\t%s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('DROP'), style.SQL_KEYWORD('CONSTRAINT'), style.SQL_TABLE(qn("%s_key" % ('_'.join(args[:2]))))) - SQL_FIELD_TYPE_DIFFER = lambda self, style, qn, args: "%s %s\n\t%s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD("MODIFY"), style.SQL_FIELD(qn(args[1])), style.SQL_COLTYPE(args[2])) - SQL_FIELD_PARAMETER_DIFFER = lambda self, style, qn, args: "%s %s\n\t%s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD("MODIFY"), style.SQL_FIELD(qn(args[1])), style.SQL_COLTYPE(args[2])) - SQL_NOTNULL_DIFFER = lambda self, style, qn, args: "%s %s\n\t%s %s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('MODIFY'), style.SQL_FIELD(qn(args[1])), style.SQL_KEYWORD(args[2]), style.SQL_KEYWORD('NOT NULL')) - SQL_ERROR = lambda self, style, qn, args: style.NOTICE('-- Error: %s' % style.ERROR(args[0])) - SQL_COMMENT = lambda self, style, qn, args: style.NOTICE('-- Comment: %s' % style.SQL_TABLE(args[0])) - SQL_TABLE_MISSING_IN_DB = lambda self, style, qn, args: style.NOTICE('-- Table missing: %s' % args[0]) - - can_detect_notnull_differ = False - - def __init__(self, app_models, options): - self.app_models = app_models - self.options = options - self.dense = options.get('dense_output', False) - - try: - self.introspection = connection.introspection - except AttributeError: - from django.db import get_introspection_module - self.introspection = get_introspection_module() - - self.cursor = connection.cursor() - self.django_tables = self.get_django_tables(options.get('only_existing', True)) - self.db_tables = self.introspection.get_table_list(self.cursor) - self.differences = [] - self.unknown_db_fields = {} - self.new_db_fields = set() - self.null = {} - - self.DIFF_SQL = { - 'error': self.SQL_ERROR, - 'comment': self.SQL_COMMENT, - 'table-missing-in-db': self.SQL_TABLE_MISSING_IN_DB, - 'field-missing-in-db': self.SQL_FIELD_MISSING_IN_DB, - 'field-missing-in-model': self.SQL_FIELD_MISSING_IN_MODEL, - 'fkey-missing-in-db': self.SQL_FKEY_MISSING_IN_DB, - 'fkey-missing-in-model': self.SQL_FIELD_MISSING_IN_MODEL, - 'index-missing-in-db': self.SQL_INDEX_MISSING_IN_DB, - 'index-missing-in-model': self.SQL_INDEX_MISSING_IN_MODEL, - 'unique-missing-in-db': self.SQL_UNIQUE_MISSING_IN_DB, - 'unique-missing-in-model': self.SQL_UNIQUE_MISSING_IN_MODEL, - 'field-type-differ': self.SQL_FIELD_TYPE_DIFFER, - 'field-parameter-differ': self.SQL_FIELD_PARAMETER_DIFFER, - 'notnull-differ': self.SQL_NOTNULL_DIFFER, - } - - if self.can_detect_notnull_differ: - self.load_null() - - def load_null(self): - raise NotImplementedError("load_null functions must be implemented if diff backend has 'can_detect_notnull_differ' set to True") - - def add_app_model_marker(self, app_label, model_name): - self.differences.append((app_label, model_name, [])) - - def add_difference(self, diff_type, *args): - assert diff_type in self.DIFF_TYPES, 'Unknown difference type' - self.differences[-1][-1].append((diff_type, args)) - - def get_django_tables(self, only_existing): - try: - django_tables = self.introspection.django_table_names(only_existing=only_existing) - except AttributeError: - # backwards compatibility for before introspection refactoring (r8296) - try: - django_tables = _sql.django_table_names(only_existing=only_existing) - except AttributeError: - # backwards compatibility for before svn r7568 - django_tables = _sql.django_table_list(only_existing=only_existing) - return django_tables - - def sql_to_dict(self, query, param): - """ sql_to_dict(query, param) -> list of dicts - - code from snippet at http://www.djangosnippets.org/snippets/1383/ - """ - cursor = connection.cursor() - cursor.execute(query, param) - fieldnames = [name[0] for name in cursor.description] - result = [] - for row in cursor.fetchall(): - rowset = [] - for field in zip(fieldnames, row): - rowset.append(field) - result.append(dict(rowset)) - return result - - def get_field_model_type(self, field): - return field.db_type(connection=connection) - - def get_field_db_type(self, description, field=None, table_name=None): - from django.db import models - # DB-API cursor.description - #(name, type_code, display_size, internal_size, precision, scale, null_ok) = description - type_code = description[1] - if type_code in self.DATA_TYPES_REVERSE_OVERRIDE: - reverse_type = self.DATA_TYPES_REVERSE_OVERRIDE[type_code] - else: - try: - try: - reverse_type = self.introspection.data_types_reverse[type_code] - except AttributeError: - # backwards compatibility for before introspection refactoring (r8296) - reverse_type = self.introspection.DATA_TYPES_REVERSE.get(type_code) - except KeyError: - reverse_type = self.get_field_db_type_lookup(type_code) - if not reverse_type: - # type_code not found in data_types_reverse map - key = (self.differences[-1][:2], description[:2]) - if key not in self.unknown_db_fields: - self.unknown_db_fields[key] = 1 - self.add_difference('comment', "Unknown database type for field '%s' (%s)" % (description[0], type_code)) - return None - - kwargs = {} - if isinstance(reverse_type, tuple): - kwargs.update(reverse_type[1]) - reverse_type = reverse_type[0] - - if reverse_type == "CharField" and description[3]: - kwargs['max_length'] = description[3] - - if reverse_type == "DecimalField": - kwargs['max_digits'] = description[4] - kwargs['decimal_places'] = description[5] and abs(description[5]) or description[5] - - if description[6]: - kwargs['blank'] = True - if not reverse_type in ('TextField', 'CharField'): - kwargs['null'] = True - - if '.' in reverse_type: - from django.utils import importlib - # TODO: when was importlib added to django.utils ? and do we - # need to add backwards compatibility code ? - module_path, package_name = reverse_type.rsplit('.', 1) - module = importlib.import_module(module_path) - field_db_type = getattr(module, package_name)(**kwargs).db_type(connection=connection) - else: - field_db_type = getattr(models, reverse_type)(**kwargs).db_type(connection=connection) - return field_db_type - - def get_field_db_type_lookup(self, type_code): - return None - - def get_field_db_nullable(self, field, table_name): - tablespace = field.db_tablespace - if tablespace == "": - tablespace = "public" - return self.null.get((tablespace, table_name, field.attname), 'fixme') - - def strip_parameters(self, field_type): - if field_type and field_type != 'double precision': - return field_type.split(" ")[0].split("(")[0].lower() - return field_type - - def find_unique_missing_in_db(self, meta, table_indexes, table_name): - for field in all_local_fields(meta): - if field.unique: - attname = field.db_column or field.attname - if attname in table_indexes and table_indexes[attname]['unique']: - continue - self.add_difference('unique-missing-in-db', table_name, attname) - - def find_unique_missing_in_model(self, meta, table_indexes, table_name): - # TODO: Postgresql does not list unique_togethers in table_indexes - # MySQL does - fields = dict([(field.db_column or field.name, field.unique) for field in all_local_fields(meta)]) - for att_name, att_opts in six.iteritems(table_indexes): - if att_opts['unique'] and att_name in fields and not fields[att_name]: - if att_name in flatten(meta.unique_together): - continue - self.add_difference('unique-missing-in-model', table_name, att_name) - - def find_index_missing_in_db(self, meta, table_indexes, table_name): - for field in all_local_fields(meta): - if field.db_index: - attname = field.db_column or field.attname - if not attname in table_indexes: - self.add_difference('index-missing-in-db', table_name, attname, '', '') - db_type = field.db_type(connection=connection) - if db_type.startswith('varchar'): - self.add_difference('index-missing-in-db', table_name, attname, 'like', ' varchar_pattern_ops') - if db_type.startswith('text'): - self.add_difference('index-missing-in-db', table_name, attname, 'like', ' text_pattern_ops') - - def find_index_missing_in_model(self, meta, table_indexes, table_name): - fields = dict([(field.name, field) for field in all_local_fields(meta)]) - for att_name, att_opts in six.iteritems(table_indexes): - if att_name in fields: - field = fields[att_name] - if field.db_index: - continue - if att_opts['primary_key'] and field.primary_key: - continue - if att_opts['unique'] and field.unique: - continue - if att_opts['unique'] and att_name in flatten(meta.unique_together): - continue - self.add_difference('index-missing-in-model', table_name, att_name) - db_type = field.db_type(connection=connection) - if db_type.startswith('varchar') or db_type.startswith('text'): - self.add_difference('index-missing-in-model', table_name, att_name, 'like') - - def find_field_missing_in_model(self, fieldmap, table_description, table_name): - for row in table_description: - if row[0] not in fieldmap: - self.add_difference('field-missing-in-model', table_name, row[0]) - - def find_field_missing_in_db(self, fieldmap, table_description, table_name): - db_fields = [row[0] for row in table_description] - for field_name, field in six.iteritems(fieldmap): - if field_name not in db_fields: - field_output = [] - if field.rel: - field_output.extend([field.rel.to._meta.db_table, field.rel.to._meta.get_field(field.rel.field_name).column]) - op = 'fkey-missing-in-db' - else: - op = 'field-missing-in-db' - field_output.append(field.db_type(connection=connection)) - if not field.null: - field_output.append('NOT NULL') - self.add_difference(op, table_name, field_name, *field_output) - self.new_db_fields.add((table_name, field_name)) - - def find_field_type_differ(self, meta, table_description, table_name, func=None): - db_fields = dict([(row[0], row) for row in table_description]) - for field in all_local_fields(meta): - if field.name not in db_fields: - continue - description = db_fields[field.name] - - model_type = self.get_field_model_type(field) - db_type = self.get_field_db_type(description, field) - - # use callback function if defined - if func: - model_type, db_type = func(field, description, model_type, db_type) - - if not self.strip_parameters(db_type) == self.strip_parameters(model_type): - self.add_difference('field-type-differ', table_name, field.name, model_type, db_type) - - def find_field_parameter_differ(self, meta, table_description, table_name, func=None): - db_fields = dict([(row[0], row) for row in table_description]) - for field in all_local_fields(meta): - if field.name not in db_fields: - continue - description = db_fields[field.name] - - model_type = self.get_field_model_type(field) - db_type = self.get_field_db_type(description, field, table_name) - - if not self.strip_parameters(model_type) == self.strip_parameters(db_type): - continue - - # use callback function if defined - if func: - model_type, db_type = func(field, description, model_type, db_type) - - if not model_type == db_type: - self.add_difference('field-parameter-differ', table_name, field.name, model_type, db_type) - - def find_field_notnull_differ(self, meta, table_description, table_name): - if not self.can_detect_notnull_differ: - return - - for field in all_local_fields(meta): - if (table_name, field.attname) in self.new_db_fields: - continue - null = self.get_field_db_nullable(field, table_name) - if field.null != null: - action = field.null and 'DROP' or 'SET' - self.add_difference('notnull-differ', table_name, field.attname, action) - - @transaction.commit_manually - def find_differences(self): - cur_app_label = None - for app_model in self.app_models: - meta = app_model._meta - table_name = meta.db_table - app_label = meta.app_label - - if cur_app_label != app_label: - # Marker indicating start of difference scan for this table_name - self.add_app_model_marker(app_label, app_model.__name__) - - #if not table_name in self.django_tables: - if not table_name in self.db_tables: - # Table is missing from database - self.add_difference('table-missing-in-db', table_name) - continue - - table_indexes = self.introspection.get_indexes(self.cursor, table_name) - fieldmap = dict([(field.db_column or field.get_attname(), field) for field in all_local_fields(meta)]) - - # add ordering field if model uses order_with_respect_to - if meta.order_with_respect_to: - fieldmap['_order'] = ORDERING_FIELD - - try: - table_description = self.introspection.get_table_description(self.cursor, table_name) - except Exception as e: - self.add_difference('error', 'unable to introspect table: %s' % str(e).strip()) - transaction.rollback() # reset transaction - continue - else: - transaction.commit() - - # Fields which are defined in database but not in model - # 1) find: 'unique-missing-in-model' - self.find_unique_missing_in_model(meta, table_indexes, table_name) - # 2) find: 'index-missing-in-model' - self.find_index_missing_in_model(meta, table_indexes, table_name) - # 3) find: 'field-missing-in-model' - self.find_field_missing_in_model(fieldmap, table_description, table_name) - - # Fields which are defined in models but not in database - # 4) find: 'field-missing-in-db' - self.find_field_missing_in_db(fieldmap, table_description, table_name) - # 5) find: 'unique-missing-in-db' - self.find_unique_missing_in_db(meta, table_indexes, table_name) - # 6) find: 'index-missing-in-db' - self.find_index_missing_in_db(meta, table_indexes, table_name) - - # Fields which have a different type or parameters - # 7) find: 'type-differs' - self.find_field_type_differ(meta, table_description, table_name) - # 8) find: 'type-parameter-differs' - self.find_field_parameter_differ(meta, table_description, table_name) - # 9) find: 'field-notnull' - self.find_field_notnull_differ(meta, table_description, table_name) - - def print_diff(self, style=no_style()): - """ print differences to stdout """ - if self.options.get('sql', True): - self.print_diff_sql(style) - else: - self.print_diff_text(style) - - def print_diff_text(self, style): - if not self.can_detect_notnull_differ: - print(style.NOTICE("# Detecting notnull changes not implemented for this database backend")) - print("") - - cur_app_label = None - for app_label, model_name, diffs in self.differences: - if not diffs: - continue - if not self.dense and cur_app_label != app_label: - print("%s %s" % (style.NOTICE("+ Application:"), style.SQL_TABLE(app_label))) - cur_app_label = app_label - if not self.dense: - print("%s %s" % (style.NOTICE("|-+ Differences for model:"), style.SQL_TABLE(model_name))) - for diff in diffs: - diff_type, diff_args = diff - text = self.DIFF_TEXTS[diff_type] % dict((str(i), style.SQL_TABLE(e)) for i, e in enumerate(diff_args)) - text = "'".join(i % 2 == 0 and style.ERROR(e) or e for i, e in enumerate(text.split("'"))) - if not self.dense: - print("%s %s" % (style.NOTICE("|--+"), text)) - else: - print("%s %s %s %s %s" % (style.NOTICE("App"), style.SQL_TABLE(app_label), style.NOTICE('Model'), style.SQL_TABLE(model_name), text)) - - def print_diff_sql(self, style): - if not self.can_detect_notnull_differ: - print(style.NOTICE("-- Detecting notnull changes not implemented for this database backend")) - print("") - - cur_app_label = None - qn = connection.ops.quote_name - has_differences = max([len(diffs) for app_label, model_name, diffs in self.differences]) - if not has_differences: - if not self.dense: - print(style.SQL_KEYWORD("-- No differences")) - else: - print(style.SQL_KEYWORD("BEGIN;")) - for app_label, model_name, diffs in self.differences: - if not diffs: - continue - if not self.dense and cur_app_label != app_label: - print(style.NOTICE("-- Application: %s" % style.SQL_TABLE(app_label))) - cur_app_label = app_label - if not self.dense: - print(style.NOTICE("-- Model: %s" % style.SQL_TABLE(model_name))) - for diff in diffs: - diff_type, diff_args = diff - text = self.DIFF_SQL[diff_type](style, qn, diff_args) - if self.dense: - text = text.replace("\n\t", " ") - print(text) - print(style.SQL_KEYWORD("COMMIT;")) - - -class GenericSQLDiff(SQLDiff): - can_detect_notnull_differ = False - - -class MySQLDiff(SQLDiff): - can_detect_notnull_differ = False - - # All the MySQL hacks together create something of a problem - # Fixing one bug in MySQL creates another issue. So just keep in mind - # that this is way unreliable for MySQL atm. - def get_field_db_type(self, description, field=None, table_name=None): - from MySQLdb.constants import FIELD_TYPE - # weird bug? in mysql db-api where it returns three times the correct value for field length - # if i remember correctly it had something todo with unicode strings - # TODO: Fix this is a more meaningful and better understood manner - description = list(description) - if description[1] not in [FIELD_TYPE.TINY, FIELD_TYPE.SHORT]: # exclude tinyints from conversion. - description[3] = description[3] / 3 - description[4] = description[4] / 3 - db_type = super(MySQLDiff, self).get_field_db_type(description) - if not db_type: - return - if field: - if field.primary_key and (db_type == 'integer' or db_type == 'bigint'): - db_type += ' AUTO_INCREMENT' - # MySQL isn't really sure about char's and varchar's like sqlite - field_type = self.get_field_model_type(field) - # Fix char/varchar inconsistencies - if self.strip_parameters(field_type) == 'char' and self.strip_parameters(db_type) == 'varchar': - db_type = db_type.lstrip("var") - # They like to call 'bool's 'tinyint(1)' and introspection makes that a integer - # just convert it back to it's proper type, a bool is a bool and nothing else. - if db_type == 'integer' and description[1] == FIELD_TYPE.TINY and description[4] == 1: - db_type = 'bool' - if db_type == 'integer' and description[1] == FIELD_TYPE.SHORT: - db_type = 'smallint UNSIGNED' # FIXME: what about if it's not UNSIGNED ? - return db_type - - -class SqliteSQLDiff(SQLDiff): - can_detect_notnull_differ = True - - def load_null(self): - for table_name in self.db_tables: - # sqlite does not support tablespaces - tablespace = "public" - # index, column_name, column_type, nullable, default_value - # see: http://www.sqlite.org/pragma.html#pragma_table_info - for table_info in self.sql_to_dict("PRAGMA table_info(%s);" % table_name, []): - key = (tablespace, table_name, table_info['name']) - self.null[key] = not table_info['notnull'] - - # Unique does not seem to be implied on Sqlite for Primary_key's - # if this is more generic among databases this might be usefull - # to add to the superclass's find_unique_missing_in_db method - def find_unique_missing_in_db(self, meta, table_indexes, table_name): - for field in all_local_fields(meta): - if field.unique: - attname = field.db_column or field.attname - if attname in table_indexes and table_indexes[attname]['unique']: - continue - if attname in table_indexes and table_indexes[attname]['primary_key']: - continue - self.add_difference('unique-missing-in-db', table_name, attname) - - # Finding Indexes by using the get_indexes dictionary doesn't seem to work - # for sqlite. - def find_index_missing_in_db(self, meta, table_indexes, table_name): - pass - - def find_index_missing_in_model(self, meta, table_indexes, table_name): - pass - - def get_field_db_type(self, description, field=None, table_name=None): - db_type = super(SqliteSQLDiff, self).get_field_db_type(description) - if not db_type: - return - if field: - field_type = self.get_field_model_type(field) - # Fix char/varchar inconsistencies - if self.strip_parameters(field_type) == 'char' and self.strip_parameters(db_type) == 'varchar': - db_type = db_type.lstrip("var") - return db_type - - -class PostgresqlSQLDiff(SQLDiff): - can_detect_notnull_differ = True - - DATA_TYPES_REVERSE_OVERRIDE = { - 1042: 'CharField', - # postgis types (TODO: support is very incomplete) - 17506: 'django.contrib.gis.db.models.fields.PointField', - 55902: 'django.contrib.gis.db.models.fields.MultiPolygonField', - } - - DATA_TYPES_REVERSE_NAME = { - 'hstore': 'django_hstore.hstore.DictionaryField', - } - - # Hopefully in the future we can add constraint checking and other more - # advanced checks based on this database. - SQL_LOAD_CONSTRAINTS = """ - SELECT nspname, relname, conname, attname, pg_get_constraintdef(pg_constraint.oid) - FROM pg_constraint - INNER JOIN pg_attribute ON pg_constraint.conrelid = pg_attribute.attrelid AND pg_attribute.attnum = any(pg_constraint.conkey) - INNER JOIN pg_class ON conrelid=pg_class.oid - INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace - ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END,contype,nspname,relname,conname; - """ - SQL_LOAD_NULL = """ - SELECT nspname, relname, attname, attnotnull - FROM pg_attribute - INNER JOIN pg_class ON attrelid=pg_class.oid - INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace; - """ - - SQL_FIELD_TYPE_DIFFER = lambda self, style, qn, args: "%s %s\n\t%s %s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('ALTER'), style.SQL_FIELD(qn(args[1])), style.SQL_KEYWORD("TYPE"), style.SQL_COLTYPE(args[2])) - SQL_FIELD_PARAMETER_DIFFER = lambda self, style, qn, args: "%s %s\n\t%s %s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('ALTER'), style.SQL_FIELD(qn(args[1])), style.SQL_KEYWORD("TYPE"), style.SQL_COLTYPE(args[2])) - SQL_NOTNULL_DIFFER = lambda self, style, qn, args: "%s %s\n\t%s %s %s %s;" % (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(args[0])), style.SQL_KEYWORD('ALTER COLUMN'), style.SQL_FIELD(qn(args[1])), style.SQL_KEYWORD(args[2]), style.SQL_KEYWORD('NOT NULL')) - - def __init__(self, app_models, options): - SQLDiff.__init__(self, app_models, options) - self.check_constraints = {} - self.load_constraints() - - def load_null(self): - for dct in self.sql_to_dict(self.SQL_LOAD_NULL, []): - key = (dct['nspname'], dct['relname'], dct['attname']) - self.null[key] = not dct['attnotnull'] - - def load_constraints(self): - for dct in self.sql_to_dict(self.SQL_LOAD_CONSTRAINTS, []): - key = (dct['nspname'], dct['relname'], dct['attname']) - if 'CHECK' in dct['pg_get_constraintdef']: - self.check_constraints[key] = dct - - def get_field_db_type(self, description, field=None, table_name=None): - db_type = super(PostgresqlSQLDiff, self).get_field_db_type(description) - if not db_type: - return - if field: - if field.primary_key: - if db_type == 'integer': - db_type = 'serial' - elif db_type == 'bigint': - db_type = 'bigserial' - if table_name: - tablespace = field.db_tablespace - if tablespace == "": - tablespace = "public" - check_constraint = self.check_constraints.get((tablespace, table_name, field.attname), {}).get('pg_get_constraintdef', None) - if check_constraint: - check_constraint = check_constraint.replace("((", "(") - check_constraint = check_constraint.replace("))", ")") - check_constraint = '("'.join([')' in e and '" '.join(p.strip('"') for p in e.split(" ", 1)) or e for e in check_constraint.split("(")]) - # TODO: might be more then one constraint in definition ? - db_type += ' ' + check_constraint - return db_type - - @transaction.autocommit - def get_field_db_type_lookup(self, type_code): - try: - name = self.sql_to_dict("SELECT typname FROM pg_type WHERE typelem=%s;", [type_code])[0]['typname'] - return self.DATA_TYPES_REVERSE_NAME.get(name.strip('_')) - except (IndexError, KeyError): - pass - - """ - def find_field_type_differ(self, meta, table_description, table_name): - def callback(field, description, model_type, db_type): - if field.primary_key and db_type=='integer': - db_type = 'serial' - return model_type, db_type - super(PostgresqlSQLDiff, self).find_field_type_differ(meta, table_description, table_name, callback) - """ - -DATABASE_SQLDIFF_CLASSES = { - 'postgis': PostgresqlSQLDiff, - 'postgresql_psycopg2': PostgresqlSQLDiff, - 'postgresql': PostgresqlSQLDiff, - 'mysql': MySQLDiff, - 'sqlite3': SqliteSQLDiff, - 'oracle': GenericSQLDiff -} - - -class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--all-applications', '-a', action='store_true', dest='all_applications', - help="Automaticly include all application from INSTALLED_APPS."), - make_option('--not-only-existing', '-e', action='store_false', dest='only_existing', - help="Check all tables that exist in the database, not only tables that should exist based on models."), - make_option('--dense-output', '-d', action='store_true', dest='dense_output', - help="Shows the output in dense format, normally output is spreaded over multiple lines."), - make_option('--output_text', '-t', action='store_false', dest='sql', default=True, - help="Outputs the differences as descriptive text instead of SQL"), - ) - - help = """Prints the (approximated) difference between models and fields in the database for the given app name(s). - -It indicates how columns in the database are different from the sql that would -be generated by Django. This command is not a database migration tool. (Though -it can certainly help) It's purpose is to show the current differences as a way -to check/debug ur models compared to the real database tables and columns.""" - - output_transaction = False - args = '<appname appname ...>' - - def handle(self, *app_labels, **options): - from django.db import models - from django.conf import settings - - engine = None - if hasattr(settings, 'DATABASES'): - engine = settings.DATABASES['default']['ENGINE'] - else: - engine = settings.DATABASE_ENGINE - - if engine == 'dummy': - # This must be the "dummy" database backend, which means the user - # hasn't set DATABASE_ENGINE. - raise CommandError("""Django doesn't know which syntax to use for your SQL statements, -because you haven't specified the DATABASE_ENGINE setting. -Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.""") - - if options.get('all_applications', False): - app_models = models.get_models(include_auto_created=True) - else: - if not app_labels: - raise CommandError('Enter at least one appname.') - try: - app_list = [models.get_app(app_label) for app_label in app_labels] - except (models.ImproperlyConfigured, ImportError) as e: - raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e) - - app_models = [] - for app in app_list: - app_models.extend(models.get_models(app, include_auto_created=True)) - - ## remove all models that are not managed by Django - #app_models = [model for model in app_models if getattr(model._meta, 'managed', True)] - - if not app_models: - raise CommandError('Unable to execute sqldiff no models founds.') - - if not engine: - engine = connection.__module__.split('.')[-2] - - if '.' in engine: - engine = engine.split('.')[-1] - - cls = DATABASE_SQLDIFF_CLASSES.get(engine, GenericSQLDiff) - sqldiff_instance = cls(app_models, options) - sqldiff_instance.find_differences() - sqldiff_instance.print_diff(self.style) - return diff --git a/awx/lib/site-packages/django_extensions/management/commands/sync_media_s3.py b/awx/lib/site-packages/django_extensions/management/commands/sync_media_s3.py deleted file mode 100644 index dfa93dea31..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/sync_media_s3.py +++ /dev/null @@ -1,292 +0,0 @@ -import warnings -warnings.simplefilter('default') -warnings.warn("sync_media_s3 is deprecated and will be removed on march 2014; use sync_s3 instead.", - PendingDeprecationWarning) - - -import datetime -import email -import mimetypes -from optparse import make_option -import os -import time -import gzip -try: - from cStringIO import StringIO - assert StringIO -except ImportError: - from StringIO import StringIO - - -from django.conf import settings -from django.core.management.base import BaseCommand, CommandError - -# Make sure boto is available -try: - import boto - import boto.exception - HAS_BOTO = True -except ImportError: - HAS_BOTO = False - - -class Command(BaseCommand): - # Extra variables to avoid passing these around - AWS_ACCESS_KEY_ID = '' - AWS_SECRET_ACCESS_KEY = '' - AWS_BUCKET_NAME = '' - AWS_CLOUDFRONT_DISTRIBUTION = '' - SYNC_S3_RENAME_GZIP_EXT = '' - - DIRECTORY = '' - FILTER_LIST = ['.DS_Store', '.svn', '.hg', '.git', 'Thumbs.db'] - GZIP_CONTENT_TYPES = ( - 'text/css', - 'application/javascript', - 'application/x-javascript', - 'text/javascript' - ) - - uploaded_files = [] - upload_count = 0 - skip_count = 0 - - option_list = BaseCommand.option_list + ( - make_option('-p', '--prefix', - dest='prefix', - default=getattr(settings, 'SYNC_MEDIA_S3_PREFIX', ''), - help="The prefix to prepend to the path on S3."), - make_option('-d', '--dir', - dest='dir', default=settings.MEDIA_ROOT, - help="The root directory to use instead of your MEDIA_ROOT"), - make_option('--gzip', - action='store_true', dest='gzip', default=False, - help="Enables gzipping CSS and Javascript files."), - make_option('--renamegzip', - action='store_true', dest='renamegzip', default=False, - help="Enables renaming of gzipped assets to have '.gz' appended to the filename."), - make_option('--expires', - action='store_true', dest='expires', default=False, - help="Enables setting a far future expires header."), - make_option('--force', - action='store_true', dest='force', default=False, - help="Skip the file mtime check to force upload of all files."), - make_option('--filter-list', dest='filter_list', - action='store', default='', - help="Override default directory and file exclusion filters. (enter as comma seperated line)"), - make_option('--invalidate', dest='invalidate', default=False, - action='store_true', - help='Invalidates the associated objects in CloudFront') - ) - - help = 'Syncs the complete MEDIA_ROOT structure and files to S3 into the given bucket name.' - args = 'bucket_name' - - can_import_settings = True - - def handle(self, *args, **options): - if not HAS_BOTO: - raise ImportError("The boto Python library is not installed.") - - # Check for AWS keys in settings - if not hasattr(settings, 'AWS_ACCESS_KEY_ID') or not hasattr(settings, 'AWS_SECRET_ACCESS_KEY'): - raise CommandError('Missing AWS keys from settings file. Please supply both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.') - else: - self.AWS_ACCESS_KEY_ID = settings.AWS_ACCESS_KEY_ID - self.AWS_SECRET_ACCESS_KEY = settings.AWS_SECRET_ACCESS_KEY - - if not hasattr(settings, 'AWS_BUCKET_NAME'): - raise CommandError('Missing bucket name from settings file. Please add the AWS_BUCKET_NAME to your settings file.') - else: - if not settings.AWS_BUCKET_NAME: - raise CommandError('AWS_BUCKET_NAME cannot be empty.') - self.AWS_BUCKET_NAME = settings.AWS_BUCKET_NAME - - if not hasattr(settings, 'MEDIA_ROOT'): - raise CommandError('MEDIA_ROOT must be set in your settings.') - else: - if not settings.MEDIA_ROOT: - raise CommandError('MEDIA_ROOT must be set in your settings.') - - self.AWS_CLOUDFRONT_DISTRIBUTION = getattr(settings, 'AWS_CLOUDFRONT_DISTRIBUTION', '') - - self.SYNC_S3_RENAME_GZIP_EXT = \ - getattr(settings, 'SYNC_S3_RENAME_GZIP_EXT', '.gz') - - self.verbosity = int(options.get('verbosity')) - self.prefix = options.get('prefix') - self.do_gzip = options.get('gzip') - self.rename_gzip = options.get('renamegzip') - self.do_expires = options.get('expires') - self.do_force = options.get('force') - self.invalidate = options.get('invalidate') - self.DIRECTORY = options.get('dir') - self.FILTER_LIST = getattr(settings, 'FILTER_LIST', self.FILTER_LIST) - filter_list = options.get('filter_list') - if filter_list: - # command line option overrides default filter_list and - # settings.filter_list - self.FILTER_LIST = filter_list.split(',') - - # Now call the syncing method to walk the MEDIA_ROOT directory and - # upload all files found. - self.sync_s3() - - # Sending the invalidation request to CloudFront if the user - # requested this action - if self.invalidate: - self.invalidate_objects_cf() - - print("") - print("%d files uploaded." % self.upload_count) - print("%d files skipped." % self.skip_count) - - def open_cf(self): - """ - Returns an open connection to CloudFront - """ - return boto.connect_cloudfront( - self.AWS_ACCESS_KEY_ID, self.AWS_SECRET_ACCESS_KEY) - - def invalidate_objects_cf(self): - """ - Split the invalidation request in groups of 1000 objects - """ - if not self.AWS_CLOUDFRONT_DISTRIBUTION: - raise CommandError( - 'An object invalidation was requested but the variable ' - 'AWS_CLOUDFRONT_DISTRIBUTION is not present in your settings.') - - # We can't send more than 1000 objects in the same invalidation - # request. - chunk = 1000 - - # Connecting to CloudFront - conn = self.open_cf() - - # Splitting the object list - objs = self.uploaded_files - chunks = [objs[i:i + chunk] for i in range(0, len(objs), chunk)] - - # Invalidation requests - for paths in chunks: - conn.create_invalidation_request( - self.AWS_CLOUDFRONT_DISTRIBUTION, paths) - - def sync_s3(self): - """ - Walks the media directory and syncs files to S3 - """ - bucket, key = self.open_s3() - os.path.walk(self.DIRECTORY, self.upload_s3, (bucket, key, self.AWS_BUCKET_NAME, self.DIRECTORY)) - - def compress_string(self, s): - """Gzip a given string.""" - zbuf = StringIO() - zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf) - zfile.write(s) - zfile.close() - return zbuf.getvalue() - - def open_s3(self): - """ - Opens connection to S3 returning bucket and key - """ - conn = boto.connect_s3(self.AWS_ACCESS_KEY_ID, self.AWS_SECRET_ACCESS_KEY) - try: - bucket = conn.get_bucket(self.AWS_BUCKET_NAME) - except boto.exception.S3ResponseError: - bucket = conn.create_bucket(self.AWS_BUCKET_NAME) - return bucket, boto.s3.key.Key(bucket) - - def upload_s3(self, arg, dirname, names): - """ - This is the callback to os.path.walk and where much of the work happens - """ - bucket, key, bucket_name, root_dir = arg - - # Skip directories we don't want to sync - if os.path.basename(dirname) in self.FILTER_LIST: - # prevent walk from processing subfiles/subdirs below the ignored one - del names[:] - return - - # Later we assume the MEDIA_ROOT ends with a trailing slash - if not root_dir.endswith(os.path.sep): - root_dir = root_dir + os.path.sep - - for file in names: - headers = {} - - if file in self.FILTER_LIST: - continue # Skip files we don't want to sync - - filename = os.path.join(dirname, file) - if os.path.isdir(filename): - continue # Don't try to upload directories - - file_key = filename[len(root_dir):] - if self.prefix: - file_key = '%s/%s' % (self.prefix, file_key) - - # Check if file on S3 is older than local file, if so, upload - if not self.do_force: - s3_key = bucket.get_key(file_key) - if s3_key: - s3_datetime = datetime.datetime(*time.strptime( - s3_key.last_modified, '%a, %d %b %Y %H:%M:%S %Z')[0:6]) - local_datetime = datetime.datetime.utcfromtimestamp( - os.stat(filename).st_mtime) - if local_datetime < s3_datetime: - self.skip_count += 1 - if self.verbosity > 1: - print("File %s hasn't been modified since last being uploaded" % file_key) - continue - - # File is newer, let's process and upload - if self.verbosity > 0: - print("Uploading %s..." % file_key) - - content_type = mimetypes.guess_type(filename)[0] - if content_type: - headers['Content-Type'] = content_type - file_obj = open(filename, 'rb') - file_size = os.fstat(file_obj.fileno()).st_size - filedata = file_obj.read() - if self.do_gzip: - # Gzipping only if file is large enough (>1K is recommended) - # and only if file is a common text type (not a binary file) - if file_size > 1024 and content_type in self.GZIP_CONTENT_TYPES: - filedata = self.compress_string(filedata) - if self.rename_gzip: - # If rename_gzip is True, then rename the file - # by appending an extension (like '.gz)' to - # original filename. - file_key = '%s.%s' % ( - file_key, self.SYNC_S3_RENAME_GZIP_EXT) - headers['Content-Encoding'] = 'gzip' - if self.verbosity > 1: - print("\tgzipped: %dk to %dk" % (file_size / 1024, len(filedata) / 1024)) - if self.do_expires: - # HTTP/1.0 - headers['Expires'] = '%s GMT' % (email.Utils.formatdate(time.mktime((datetime.datetime.now() + datetime.timedelta(days=365 * 2)).timetuple()))) - # HTTP/1.1 - headers['Cache-Control'] = 'max-age %d' % (3600 * 24 * 365 * 2) - if self.verbosity > 1: - print("\texpires: %s" % headers['Expires']) - print("\tcache-control: %s" % headers['Cache-Control']) - - try: - key.name = file_key - key.set_contents_from_string(filedata, headers, replace=True) - key.set_acl('public-read') - except boto.exception.S3CreateError as e: - print("Failed: %s" % e) - except Exception as e: - print(e) - raise - else: - self.upload_count += 1 - self.uploaded_files.append(file_key) - - file_obj.close() diff --git a/awx/lib/site-packages/django_extensions/management/commands/sync_s3.py b/awx/lib/site-packages/django_extensions/management/commands/sync_s3.py deleted file mode 100644 index d00208cabe..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/sync_s3.py +++ /dev/null @@ -1,384 +0,0 @@ -""" -Sync Media to S3 -================ - -Django command that scans all files in your settings.MEDIA_ROOT and -settings.STATIC_ROOT folders and uploads them to S3 with the same directory -structure. - -This command can optionally do the following but it is off by default: -* gzip compress any CSS and Javascript files it finds and adds the appropriate - 'Content-Encoding' header. -* set a far future 'Expires' header for optimal caching. -* upload only media or static files. -* use any other provider compatible with Amazon S3. -* set other than 'public-read' ACL. - -Note: This script requires the Python boto library and valid Amazon Web -Services API keys. - -Required settings.py variables: -AWS_ACCESS_KEY_ID = '' -AWS_SECRET_ACCESS_KEY = '' -AWS_BUCKET_NAME = '' - -When you call this command with the `--renamegzip` param, it will add -the '.gz' extension to the file name. But Safari just doesn't recognize -'.gz' files and your site won't work on it! To fix this problem, you can -set any other extension (like .jgz) in the `SYNC_S3_RENAME_GZIP_EXT` -variable. - -Command options are: - -p PREFIX, --prefix=PREFIX - The prefix to prepend to the path on S3. - --gzip Enables gzipping CSS and Javascript files. - --expires Enables setting a far future expires header. - --force Skip the file mtime check to force upload of all - files. - --filter-list Override default directory and file exclusion - filters. (enter as comma separated line) - --renamegzip Enables renaming of gzipped files by appending '.gz'. - to the original file name. This way your original - assets will not be replaced by the gzipped ones. - You can change the extension setting the - `SYNC_S3_RENAME_GZIP_EXT` var in your settings.py - file. - --invalidate Invalidates the objects in CloudFront after uploading - stuff to s3. - --media-only Only MEDIA_ROOT files will be uploaded to S3. - --static-only Only STATIC_ROOT files will be uploaded to S3. - --s3host Override default s3 host. - --acl Override default ACL settings ('public-read' if - settings.AWS_DEFAULT_ACL is not defined). - -TODO: - * Use fnmatch (or regex) to allow more complex FILTER_LIST rules. - -""" -import datetime -import email -import mimetypes -from optparse import make_option -import os -import time -import gzip -try: - from cStringIO import StringIO - assert StringIO -except ImportError: - from StringIO import StringIO - - -from django.conf import settings -from django.core.management.base import BaseCommand, CommandError - -# Make sure boto is available -try: - import boto - import boto.exception - HAS_BOTO = True -except ImportError: - HAS_BOTO = False - - -class Command(BaseCommand): - # Extra variables to avoid passing these around - AWS_ACCESS_KEY_ID = '' - AWS_SECRET_ACCESS_KEY = '' - AWS_BUCKET_NAME = '' - AWS_CLOUDFRONT_DISTRIBUTION = '' - SYNC_S3_RENAME_GZIP_EXT = '' - - DIRECTORIES = '' - FILTER_LIST = ['.DS_Store', '.svn', '.hg', '.git', 'Thumbs.db'] - GZIP_CONTENT_TYPES = ( - 'text/css', - 'application/javascript', - 'application/x-javascript', - 'text/javascript' - ) - - uploaded_files = [] - upload_count = 0 - skip_count = 0 - - option_list = BaseCommand.option_list + ( - make_option('-p', '--prefix', - dest='prefix', - default=getattr(settings, 'SYNC_MEDIA_S3_PREFIX', ''), - help="The prefix to prepend to the path on S3."), - make_option('-d', '--dir', - dest='dir', - help="Custom static root directory to use"), - make_option('--s3host', - dest='s3host', - default=getattr(settings, 'AWS_S3_HOST', ''), - help="The s3 host (enables connecting to other providers/regions)"), - make_option('--acl', - dest='acl', - default=getattr(settings, 'AWS_DEFAULT_ACL', 'public-read'), - help="Enables to override default acl (public-read)."), - make_option('--gzip', - action='store_true', dest='gzip', default=False, - help="Enables gzipping CSS and Javascript files."), - make_option('--renamegzip', - action='store_true', dest='renamegzip', default=False, - help="Enables renaming of gzipped assets to have '.gz' appended to the filename."), - make_option('--expires', - action='store_true', dest='expires', default=False, - help="Enables setting a far future expires header."), - make_option('--force', - action='store_true', dest='force', default=False, - help="Skip the file mtime check to force upload of all files."), - make_option('--filter-list', dest='filter_list', - action='store', default='', - help="Override default directory and file exclusion filters. (enter as comma seperated line)"), - make_option('--invalidate', dest='invalidate', default=False, - action='store_true', - help='Invalidates the associated objects in CloudFront'), - make_option('--media-only', dest='media_only', default='', - action='store_true', - help="Only MEDIA_ROOT files will be uploaded to S3"), - make_option('--static-only', dest='static_only', default='', - action='store_true', - help="Only STATIC_ROOT files will be uploaded to S3"), - ) - - help = 'Syncs the complete MEDIA_ROOT structure and files to S3 into the given bucket name.' - args = 'bucket_name' - - can_import_settings = True - - def handle(self, *args, **options): - if not HAS_BOTO: - raise ImportError("The boto Python library is not installed.") - - # Check for AWS keys in settings - if not hasattr(settings, 'AWS_ACCESS_KEY_ID') or not hasattr(settings, 'AWS_SECRET_ACCESS_KEY'): - raise CommandError('Missing AWS keys from settings file. Please supply both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.') - else: - self.AWS_ACCESS_KEY_ID = settings.AWS_ACCESS_KEY_ID - self.AWS_SECRET_ACCESS_KEY = settings.AWS_SECRET_ACCESS_KEY - - if not hasattr(settings, 'AWS_BUCKET_NAME'): - raise CommandError('Missing bucket name from settings file. Please add the AWS_BUCKET_NAME to your settings file.') - else: - if not settings.AWS_BUCKET_NAME: - raise CommandError('AWS_BUCKET_NAME cannot be empty.') - self.AWS_BUCKET_NAME = settings.AWS_BUCKET_NAME - - if not hasattr(settings, 'MEDIA_ROOT'): - raise CommandError('MEDIA_ROOT must be set in your settings.') - else: - if not settings.MEDIA_ROOT: - raise CommandError('MEDIA_ROOT must be set in your settings.') - - self.AWS_CLOUDFRONT_DISTRIBUTION = getattr(settings, 'AWS_CLOUDFRONT_DISTRIBUTION', '') - - self.SYNC_S3_RENAME_GZIP_EXT = \ - getattr(settings, 'SYNC_S3_RENAME_GZIP_EXT', '.gz') - - self.verbosity = int(options.get('verbosity')) - self.prefix = options.get('prefix') - self.do_gzip = options.get('gzip') - self.rename_gzip = options.get('renamegzip') - self.do_expires = options.get('expires') - self.do_force = options.get('force') - self.invalidate = options.get('invalidate') - self.DIRECTORIES = options.get('dir') - self.s3host = options.get('s3host') - self.default_acl = options.get('acl') - self.FILTER_LIST = getattr(settings, 'FILTER_LIST', self.FILTER_LIST) - filter_list = options.get('filter_list') - if filter_list: - # command line option overrides default filter_list and - # settings.filter_list - self.FILTER_LIST = filter_list.split(',') - - self.media_only = options.get('media_only') - self.static_only = options.get('static_only') - # Get directories - if self.media_only and self.static_only: - raise CommandError("Can't use --media-only and --static-only together. Better not use anything...") - elif self.media_only: - self.DIRECTORIES = [settings.MEDIA_ROOT] - elif self.static_only: - self.DIRECTORIES = [settings.STATIC_ROOT] - elif self.DIRECTORIES: - self.DIRECTORIES = [self.DIRECTORIES] - else: - self.DIRECTORIES = [settings.MEDIA_ROOT, settings.STATIC_ROOT] - - # Now call the syncing method to walk the MEDIA_ROOT directory and - # upload all files found. - self.sync_s3() - - # Sending the invalidation request to CloudFront if the user - # requested this action - if self.invalidate: - self.invalidate_objects_cf() - - print("") - print("%d files uploaded." % self.upload_count) - print("%d files skipped." % self.skip_count) - - def open_cf(self): - """ - Returns an open connection to CloudFront - """ - return boto.connect_cloudfront( - self.AWS_ACCESS_KEY_ID, self.AWS_SECRET_ACCESS_KEY) - - def invalidate_objects_cf(self): - """ - Split the invalidation request in groups of 1000 objects - """ - if not self.AWS_CLOUDFRONT_DISTRIBUTION: - raise CommandError( - 'An object invalidation was requested but the variable ' - 'AWS_CLOUDFRONT_DISTRIBUTION is not present in your settings.') - - # We can't send more than 1000 objects in the same invalidation - # request. - chunk = 1000 - - # Connecting to CloudFront - conn = self.open_cf() - - # Splitting the object list - objs = self.uploaded_files - chunks = [objs[i:i + chunk] for i in range(0, len(objs), chunk)] - - # Invalidation requests - for paths in chunks: - conn.create_invalidation_request( - self.AWS_CLOUDFRONT_DISTRIBUTION, paths) - - def sync_s3(self): - """ - Walks the media/static directories and syncs files to S3 - """ - bucket, key = self.open_s3() - for directory in self.DIRECTORIES: - os.path.walk(directory, self.upload_s3, (bucket, key, self.AWS_BUCKET_NAME, directory)) - - def compress_string(self, s): - """Gzip a given string.""" - zbuf = StringIO() - zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf) - zfile.write(s) - zfile.close() - return zbuf.getvalue() - - def get_s3connection_kwargs(self): - """Returns connection kwargs as a dict""" - kwargs = {} - if self.s3host: - kwargs['host'] = self.s3host - return kwargs - - def open_s3(self): - """ - Opens connection to S3 returning bucket and key - """ - conn = boto.connect_s3( - self.AWS_ACCESS_KEY_ID, - self.AWS_SECRET_ACCESS_KEY, - **self.get_s3connection_kwargs()) - try: - bucket = conn.get_bucket(self.AWS_BUCKET_NAME) - except boto.exception.S3ResponseError: - bucket = conn.create_bucket(self.AWS_BUCKET_NAME) - return bucket, boto.s3.key.Key(bucket) - - def upload_s3(self, arg, dirname, names): - """ - This is the callback to os.path.walk and where much of the work happens - """ - bucket, key, bucket_name, root_dir = arg - - # Skip directories we don't want to sync - if os.path.basename(dirname) in self.FILTER_LIST: - # prevent walk from processing subfiles/subdirs below the ignored one - del names[:] - return - - # Later we assume the MEDIA_ROOT ends with a trailing slash - if not root_dir.endswith(os.path.sep): - root_dir = root_dir + os.path.sep - - for file in names: - headers = {} - - if file in self.FILTER_LIST: - continue # Skip files we don't want to sync - - filename = os.path.join(dirname, file) - if os.path.isdir(filename): - continue # Don't try to upload directories - - file_key = filename[len(root_dir):] - if self.prefix: - file_key = '%s/%s' % (self.prefix, file_key) - - # Check if file on S3 is older than local file, if so, upload - if not self.do_force: - s3_key = bucket.get_key(file_key) - if s3_key: - s3_datetime = datetime.datetime(*time.strptime( - s3_key.last_modified, '%a, %d %b %Y %H:%M:%S %Z')[0:6]) - local_datetime = datetime.datetime.utcfromtimestamp( - os.stat(filename).st_mtime) - if local_datetime < s3_datetime: - self.skip_count += 1 - if self.verbosity > 1: - print("File %s hasn't been modified since last being uploaded" % file_key) - continue - - # File is newer, let's process and upload - if self.verbosity > 0: - print("Uploading %s..." % file_key) - - content_type = mimetypes.guess_type(filename)[0] - if content_type: - headers['Content-Type'] = content_type - file_obj = open(filename, 'rb') - file_size = os.fstat(file_obj.fileno()).st_size - filedata = file_obj.read() - if self.do_gzip: - # Gzipping only if file is large enough (>1K is recommended) - # and only if file is a common text type (not a binary file) - if file_size > 1024 and content_type in self.GZIP_CONTENT_TYPES: - filedata = self.compress_string(filedata) - if self.rename_gzip: - # If rename_gzip is True, then rename the file - # by appending an extension (like '.gz)' to - # original filename. - file_key = '%s.%s' % ( - file_key, self.SYNC_S3_RENAME_GZIP_EXT) - headers['Content-Encoding'] = 'gzip' - if self.verbosity > 1: - print("\tgzipped: %dk to %dk" % (file_size / 1024, len(filedata) / 1024)) - if self.do_expires: - # HTTP/1.0 - headers['Expires'] = '%s GMT' % (email.Utils.formatdate(time.mktime((datetime.datetime.now() + datetime.timedelta(days=365 * 2)).timetuple()))) - # HTTP/1.1 - headers['Cache-Control'] = 'max-age %d' % (3600 * 24 * 365 * 2) - if self.verbosity > 1: - print("\texpires: %s" % headers['Expires']) - print("\tcache-control: %s" % headers['Cache-Control']) - - try: - key.name = file_key - key.set_contents_from_string(filedata, headers, replace=True, - policy=self.default_acl) - except boto.exception.S3CreateError as e: - print("Failed: %s" % e) - except Exception as e: - print(e) - raise - else: - self.upload_count += 1 - self.uploaded_files.append(file_key) - - file_obj.close() diff --git a/awx/lib/site-packages/django_extensions/management/commands/syncdata.py b/awx/lib/site-packages/django_extensions/management/commands/syncdata.py deleted file mode 100644 index 4ff2295f7f..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/syncdata.py +++ /dev/null @@ -1,201 +0,0 @@ -""" -SyncData -======== - -Django command similar to 'loaddata' but also deletes. -After 'syncdata' has run, the database will have the same data as the fixture - anything -missing will of been added, anything different will of been updated, -and anything extra will of been deleted. -""" - -import os -import sys -import six -from django.core.management.base import BaseCommand -from django.core.management.color import no_style - - -class Command(BaseCommand): - """ syncdata command """ - - help = 'Makes the current database have the same data as the fixture(s), no more, no less.' - args = "fixture [fixture ...]" - - def remove_objects_not_in(self, objects_to_keep, verbosity): - """ - Deletes all the objects in the database that are not in objects_to_keep. - - objects_to_keep: A map where the keys are classes, and the values are a - set of the objects of that class we should keep. - """ - for class_ in objects_to_keep.keys(): - current = class_.objects.all() - current_ids = set([x.id for x in current]) - keep_ids = set([x.id for x in objects_to_keep[class_]]) - - remove_these_ones = current_ids.difference(keep_ids) - if remove_these_ones: - for obj in current: - if obj.id in remove_these_ones: - obj.delete() - if verbosity >= 2: - print("Deleted object: %s" % six.u(obj)) - - if verbosity > 0 and remove_these_ones: - num_deleted = len(remove_these_ones) - if num_deleted > 1: - type_deleted = six.u(class_._meta.verbose_name_plural) - else: - type_deleted = six.u(class_._meta.verbose_name) - - print("Deleted %s %s" % (str(num_deleted), type_deleted)) - - def handle(self, *fixture_labels, **options): - """ Main method of a Django command """ - from django.db.models import get_apps - from django.core import serializers - from django.db import connection, transaction - from django.conf import settings - - self.style = no_style() - - verbosity = int(options.get('verbosity', 1)) - show_traceback = options.get('traceback', False) - - # Keep a count of the installed objects and fixtures - fixture_count = 0 - object_count = 0 - objects_per_fixture = [] - models = set() - - humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path' - - # Get a cursor (even though we don't need one yet). This has - # the side effect of initializing the test database (if - # it isn't already initialized). - cursor = connection.cursor() - - # Start transaction management. All fixtures are installed in a - # single transaction to ensure that all references are resolved. - transaction.commit_unless_managed() - transaction.enter_transaction_management() - transaction.managed(True) - - app_fixtures = [os.path.join(os.path.dirname(app.__file__), 'fixtures') for app in get_apps()] - for fixture_label in fixture_labels: - parts = fixture_label.split('.') - if len(parts) == 1: - fixture_name = fixture_label - formats = serializers.get_public_serializer_formats() - else: - fixture_name, format = '.'.join(parts[:-1]), parts[-1] - if format in serializers.get_public_serializer_formats(): - formats = [format] - else: - formats = [] - - if formats: - if verbosity > 1: - print("Loading '%s' fixtures..." % fixture_name) - else: - sys.stderr.write(self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format." % (fixture_name, format))) - transaction.rollback() - transaction.leave_transaction_management() - return - - if os.path.isabs(fixture_name): - fixture_dirs = [fixture_name] - else: - fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + [''] - - for fixture_dir in fixture_dirs: - if verbosity > 1: - print("Checking %s for fixtures..." % humanize(fixture_dir)) - - label_found = False - for format in formats: - #serializer = serializers.get_serializer(format) - if verbosity > 1: - print("Trying %s for %s fixture '%s'..." % (humanize(fixture_dir), format, fixture_name)) - try: - full_path = os.path.join(fixture_dir, '.'.join([fixture_name, format])) - fixture = open(full_path, 'r') - if label_found: - fixture.close() - print(self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting." % (fixture_name, humanize(fixture_dir)))) - transaction.rollback() - transaction.leave_transaction_management() - return - else: - fixture_count += 1 - objects_per_fixture.append(0) - if verbosity > 0: - print("Installing %s fixture '%s' from %s." % (format, fixture_name, humanize(fixture_dir))) - try: - objects_to_keep = {} - objects = serializers.deserialize(format, fixture) - for obj in objects: - object_count += 1 - objects_per_fixture[-1] += 1 - - class_ = obj.object.__class__ - if not class_ in objects_to_keep: - objects_to_keep[class_] = set() - objects_to_keep[class_].add(obj.object) - - models.add(class_) - obj.save() - - self.remove_objects_not_in(objects_to_keep, verbosity) - - label_found = True - except (SystemExit, KeyboardInterrupt): - raise - except Exception: - import traceback - fixture.close() - transaction.rollback() - transaction.leave_transaction_management() - if show_traceback: - traceback.print_exc() - else: - sys.stderr.write(self.style.ERROR("Problem installing fixture '%s': %s\n" % (full_path, traceback.format_exc()))) - return - fixture.close() - except: - if verbosity > 1: - print("No %s fixture '%s' in %s." % (format, fixture_name, humanize(fixture_dir))) - - # If any of the fixtures we loaded contain 0 objects, assume that an - # error was encountered during fixture loading. - if 0 in objects_per_fixture: - sys.stderr.write( - self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)" % (fixture_name))) - transaction.rollback() - transaction.leave_transaction_management() - return - - # If we found even one object in a fixture, we need to reset the - # database sequences. - if object_count > 0: - sequence_sql = connection.ops.sequence_reset_sql(self.style, models) - if sequence_sql: - if verbosity > 1: - print("Resetting sequences") - for line in sequence_sql: - cursor.execute(line) - - transaction.commit() - transaction.leave_transaction_management() - - if object_count == 0: - if verbosity > 1: - print("No fixtures found.") - else: - if verbosity > 0: - print("Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count)) - - # Close the DB connection. This is required as a workaround for an - # edge case in MySQL: if the same connection is used to - # create tables, load data, and query, the query can return - # incorrect results. See Django #7572, MySQL #37735. - connection.close() diff --git a/awx/lib/site-packages/django_extensions/management/commands/unreferenced_files.py b/awx/lib/site-packages/django_extensions/management/commands/unreferenced_files.py deleted file mode 100644 index 3f4dfae2f2..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/unreferenced_files.py +++ /dev/null @@ -1,47 +0,0 @@ -from collections import defaultdict -import os -from django.conf import settings -from django.core.management.base import NoArgsCommand -from django.db import models -from django.db.models.loading import cache - - -class Command(NoArgsCommand): - help = "Prints a list of all files in MEDIA_ROOT that are not referenced in the database." - - def handle_noargs(self, **options): - - if settings.MEDIA_ROOT == '': - print("MEDIA_ROOT is not set, nothing to do") - return - - # Get a list of all files under MEDIA_ROOT - media = [] - for root, dirs, files in os.walk(settings.MEDIA_ROOT): - for f in files: - media.append(os.path.abspath(os.path.join(root, f))) - - # Get list of all fields (value) for each model (key) - # that is a FileField or subclass of a FileField - model_dict = defaultdict(list) - for app in cache.get_apps(): - model_list = cache.get_models(app) - for model in model_list: - for field in model._meta.fields: - if issubclass(field.__class__, models.FileField): - model_dict[model].append(field) - - # Get a list of all files referenced in the database - referenced = [] - for model in model_dict.iterkeys(): - all = model.objects.all().iterator() - for object in all: - for field in model_dict[model]: - target_file = getattr(object, field.name) - if target_file: - referenced.append(os.path.abspath(target_file.path)) - - # Print each file in MEDIA_ROOT that is not referenced in the database - for m in media: - if m not in referenced: - print(m) diff --git a/awx/lib/site-packages/django_extensions/management/commands/update_permissions.py b/awx/lib/site-packages/django_extensions/management/commands/update_permissions.py deleted file mode 100644 index 0a84627701..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/update_permissions.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.core.management.base import BaseCommand -from django.db.models import get_models, get_app -from django.contrib.auth.management import create_permissions - - -class Command(BaseCommand): - args = '<app app ...>' - help = 'reloads permissions for specified apps, or all apps if no args are specified' - - def handle(self, *args, **options): - if not args: - apps = [] - for model in get_models(): - apps.append(get_app(model._meta.app_label)) - else: - apps = [] - for arg in args: - apps.append(get_app(arg)) - for app in apps: - create_permissions(app, get_models(), options.get('verbosity', 0)) - diff --git a/awx/lib/site-packages/django_extensions/management/commands/validate_templates.py b/awx/lib/site-packages/django_extensions/management/commands/validate_templates.py deleted file mode 100644 index 860c18e085..0000000000 --- a/awx/lib/site-packages/django_extensions/management/commands/validate_templates.py +++ /dev/null @@ -1,71 +0,0 @@ -import os -from optparse import make_option -from django.core.management.base import BaseCommand, CommandError -from django.core.management.color import color_style -from django.template.base import add_to_builtins -from django.template.loaders.filesystem import Loader -from django_extensions.utils import validatingtemplatetags - -# -# TODO: Render the template with fake request object ? -# - - -class Command(BaseCommand): - args = '' - help = "Validate templates on syntax and compile errors" - option_list = BaseCommand.option_list + ( - make_option('--break', '-b', action='store_true', dest='break', - default=False, help="Break on first error."), - make_option('--check-urls', '-u', action='store_true', dest='check_urls', - default=False, help="Check url tag view names are quoted appropriately"), - make_option('--force-new-urls', '-n', action='store_true', dest='force_new_urls', - default=False, help="Error on usage of old style url tags (without {% load urls from future %}"), - make_option('--include', '-i', action='append', dest='includes', - default=[], help="Append these paths to TEMPLATE_DIRS") - ) - - def handle(self, *args, **options): - from django.conf import settings - style = color_style() - template_dirs = set(settings.TEMPLATE_DIRS) - template_dirs |= set(options.get('includes', [])) - template_dirs |= set(getattr(settings, 'VALIDATE_TEMPLATES_EXTRA_TEMPLATE_DIRS', [])) - settings.TEMPLATE_DIRS = list(template_dirs) - settings.TEMPLATE_DEBUG = True - verbosity = int(options.get('verbosity', 1)) - errors = 0 - - template_loader = Loader() - - # Replace built in template tags with our own validating versions - if options.get('check_urls', False): - add_to_builtins('django_extensions.utils.validatingtemplatetags') - - for template_dir in template_dirs: - for root, dirs, filenames in os.walk(template_dir): - for filename in filenames: - if filename.endswith(".swp"): - continue - if filename.endswith("~"): - continue - filepath = os.path.join(root, filename) - if verbosity > 1: - print(filepath) - validatingtemplatetags.before_new_template(options.get('force_new_urls', False)) - try: - template_loader.load_template(filename, [root]) - except Exception as e: - errors += 1 - print("%s: %s" % (filepath, style.ERROR("%s %s" % (e.__class__.__name__, str(e))))) - template_errors = validatingtemplatetags.get_template_errors() - for origin, line, message in template_errors: - errors += 1 - print("%s(%s): %s" % (origin, line, style.ERROR(message))) - if errors and options.get('break', False): - raise CommandError("Errors found") - - if errors: - raise CommandError("%s errors found" % errors) - print("%s errors found" % errors) - diff --git a/awx/lib/site-packages/django_extensions/management/jobs.py b/awx/lib/site-packages/django_extensions/management/jobs.py deleted file mode 100644 index 9269b4e200..0000000000 --- a/awx/lib/site-packages/django_extensions/management/jobs.py +++ /dev/null @@ -1,181 +0,0 @@ -""" -django_extensions.management.jobs -""" - -import os -from imp import find_module - -_jobs = None - - -def noneimplementation(meth): - return None - - -class JobError(Exception): - pass - - -class BaseJob(object): - help = "undefined job description." - when = None - - def execute(self): - raise NotImplementedError("Job needs to implement the execute method") - - -class MinutelyJob(BaseJob): - when = "minutely" - - -class QuarterHourlyJob(BaseJob): - when = "quarter_hourly" - - -class HourlyJob(BaseJob): - when = "hourly" - - -class DailyJob(BaseJob): - when = "daily" - - -class WeeklyJob(BaseJob): - when = "weekly" - - -class MonthlyJob(BaseJob): - when = "monthly" - - -class YearlyJob(BaseJob): - when = "yearly" - - -def my_import(name): - try: - imp = __import__(name) - except ImportError as err: - raise JobError("Failed to import %s with error %s" % (name, err)) - - mods = name.split('.') - if len(mods) > 1: - for mod in mods[1:]: - imp = getattr(imp, mod) - return imp - - -def find_jobs(jobs_dir): - try: - return [f[:-3] for f in os.listdir(jobs_dir) if not f.startswith('_') and f.endswith(".py")] - except OSError: - return [] - - -def find_job_module(app_name, when=None): - parts = app_name.split('.') - parts.append('jobs') - if when: - parts.append(when) - parts.reverse() - path = None - while parts: - part = parts.pop() - f, path, descr = find_module(part, path and [path] or None) - return path - - -def import_job(app_name, name, when=None): - jobmodule = "%s.jobs.%s%s" % (app_name, when and "%s." % when or "", name) - job_mod = my_import(jobmodule) - # todo: more friendly message for AttributeError if job_mod does not exist - try: - job = job_mod.Job - except: - raise JobError("Job module %s does not contain class instance named 'Job'" % jobmodule) - if when and not (job.when == when or job.when is None): - raise JobError("Job %s is not a %s job." % (jobmodule, when)) - return job - - -def get_jobs(when=None, only_scheduled=False): - """ - Returns a dictionary mapping of job names together with their respective - application class. - """ - # FIXME: HACK: make sure the project dir is on the path when executed as ./manage.py - import sys - try: - cpath = os.path.dirname(os.path.realpath(sys.argv[0])) - ppath = os.path.dirname(cpath) - if ppath not in sys.path: - sys.path.append(ppath) - except: - pass - _jobs = {} - if True: - from django.conf import settings - for app_name in settings.INSTALLED_APPS: - scandirs = (None, 'minutely', 'quarter_hourly', 'hourly', 'daily', 'weekly', 'monthly', 'yearly') - if when: - scandirs = None, when - for subdir in scandirs: - try: - path = find_job_module(app_name, subdir) - for name in find_jobs(path): - if (app_name, name) in _jobs: - raise JobError("Duplicate job %s" % name) - job = import_job(app_name, name, subdir) - if only_scheduled and job.when is None: - # only include jobs which are scheduled - continue - if when and job.when != when: - # generic job not in same schedule - continue - _jobs[(app_name, name)] = job - except ImportError: - # No job module -- continue scanning - pass - return _jobs - - -def get_job(app_name, job_name): - jobs = get_jobs() - if app_name: - return jobs[(app_name, job_name)] - else: - for a, j in jobs.keys(): - if j == job_name: - return jobs[(a, j)] - raise KeyError("Job not found: %s" % job_name) - - -def print_jobs(when=None, only_scheduled=False, show_when=True, show_appname=False, show_header=True): - jobmap = get_jobs(when, only_scheduled=only_scheduled) - print("Job List: %i jobs" % len(jobmap)) - jlist = jobmap.keys() - jlist.sort() - appname_spacer = "%%-%is" % max(len(e[0]) for e in jlist) - name_spacer = "%%-%is" % max(len(e[1]) for e in jlist) - when_spacer = "%%-%is" % max(len(e.when) for e in jobmap.values() if e.when) - if show_header: - line = " " - if show_appname: - line += appname_spacer % "appname" + " - " - line += name_spacer % "jobname" - if show_when: - line += " - " + when_spacer % "when" - line += " - help" - print(line) - print("-" * 80) - - for app_name, job_name in jlist: - job = jobmap[(app_name, job_name)] - line = " " - if show_appname: - line += appname_spacer % app_name + " - " - line += name_spacer % job_name - if show_when: - line += " - " + when_spacer % (job.when and job.when or "") - line += " - " + job.help - print(line) diff --git a/awx/lib/site-packages/django_extensions/management/modelviz.py b/awx/lib/site-packages/django_extensions/management/modelviz.py deleted file mode 100644 index 9705820097..0000000000 --- a/awx/lib/site-packages/django_extensions/management/modelviz.py +++ /dev/null @@ -1,294 +0,0 @@ -""" -modelviz.py - DOT file generator for Django Models - -Based on: - Django model to DOT (Graphviz) converter - by Antonio Cavedoni <antonio@cavedoni.org> - Adapted to be used with django-extensions -""" - -__version__ = "1.0" -__license__ = "Python" -__author__ = "Bas van Oostveen <v.oostveen@gmail.com>", -__contributors__ = [ - "Antonio Cavedoni <http://cavedoni.com/>" - "Stefano J. Attardi <http://attardi.org/>", - "limodou <http://www.donews.net/limodou/>", - "Carlo C8E Miron", - "Andre Campos <cahenan@gmail.com>", - "Justin Findlay <jfindlay@gmail.com>", - "Alexander Houben <alexander@houben.ch>", - "Joern Hees <gitdev@joernhees.de>", -] - -import os -import datetime -from django.utils.translation import activate as activate_language -from django.utils.safestring import mark_safe -from django.template import Context, loader, Template -from django.db import models -from django.db.models import get_models -from django.db.models.fields.related import ForeignKey, OneToOneField, ManyToManyField, RelatedField - -try: - from django.db.models.fields.generic import GenericRelation - assert GenericRelation -except ImportError: - from django.contrib.contenttypes.generic import GenericRelation - - -def parse_file_or_list(arg): - if not arg: - return [] - if not ',' in arg and os.path.isfile(arg): - return [e.strip() for e in open(arg).readlines()] - return arg.split(',') - - -def generate_dot(app_labels, **kwargs): - cli_options = kwargs.get('cli_options', None) - disable_fields = kwargs.get('disable_fields', False) - include_models = parse_file_or_list(kwargs.get('include_models', "")) - all_applications = kwargs.get('all_applications', False) - use_subgraph = kwargs.get('group_models', False) - verbose_names = kwargs.get('verbose_names', False) - inheritance = kwargs.get('inheritance', True) - relations_as_fields = kwargs.get("relations_as_fields", True) - sort_fields = kwargs.get("sort_fields", True) - language = kwargs.get('language', None) - if language is not None: - activate_language(language) - exclude_columns = parse_file_or_list(kwargs.get('exclude_columns', "")) - exclude_models = parse_file_or_list(kwargs.get('exclude_models', "")) - - def skip_field(field): - if exclude_columns: - if verbose_names and field.verbose_name: - if field.verbose_name in exclude_columns: - return True - if field.name in exclude_columns: - return True - return False - - apps = [] - if all_applications: - apps = models.get_apps() - - for app_label in app_labels: - app = models.get_app(app_label) - if not app in apps: - apps.append(app) - - graphs = [] - for app in apps: - graph = Context({ - 'name': '"%s"' % app.__name__, - 'app_name': "%s" % '.'.join(app.__name__.split('.')[:-1]), - 'cluster_app_name': "cluster_%s" % app.__name__.replace(".", "_"), - 'models': [] - }) - - appmodels = get_models(app) - abstract_models = [] - for appmodel in appmodels: - abstract_models = abstract_models + [abstract_model for abstract_model in appmodel.__bases__ if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract] - abstract_models = list(set(abstract_models)) # remove duplicates - appmodels = abstract_models + appmodels - - for appmodel in appmodels: - appmodel_abstracts = [abstract_model.__name__ for abstract_model in appmodel.__bases__ if hasattr(abstract_model, '_meta') and abstract_model._meta.abstract] - - # collect all attribs of abstract superclasses - def getBasesAbstractFields(c): - _abstract_fields = [] - for e in c.__bases__: - if hasattr(e, '_meta') and e._meta.abstract: - _abstract_fields.extend(e._meta.fields) - _abstract_fields.extend(getBasesAbstractFields(e)) - return _abstract_fields - abstract_fields = getBasesAbstractFields(appmodel) - - model = { - 'app_name': appmodel.__module__.replace(".", "_"), - 'name': appmodel.__name__, - 'abstracts': appmodel_abstracts, - 'fields': [], - 'relations': [] - } - - # consider given model name ? - def consider(model_name): - if exclude_models and model_name in exclude_models: - return False - return not include_models or model_name in include_models - - if not consider(appmodel._meta.object_name): - continue - - if verbose_names and appmodel._meta.verbose_name: - model['label'] = appmodel._meta.verbose_name.decode("utf8") - else: - model['label'] = model['name'] - - # model attributes - def add_attributes(field): - if verbose_names and field.verbose_name: - label = field.verbose_name.decode("utf8") - if label.islower(): - label = label.capitalize() - else: - label = field.name - - t = type(field).__name__ - if isinstance(field, (OneToOneField, ForeignKey)): - t += " ({0})".format(field.rel.field_name) - # TODO: ManyToManyField, GenericRelation - - model['fields'].append({ - 'name': field.name, - 'label': label, - 'type': t, - 'blank': field.blank, - 'abstract': field in abstract_fields, - 'relation': isinstance(field, RelatedField), - 'primary_key': field.primary_key, - }) - - attributes = [field for field in appmodel._meta.local_fields] - if not relations_as_fields: - # Find all the 'real' attributes. Relations are depicted as graph edges instead of attributes - attributes = [field for field in attributes if not isinstance(field, RelatedField)] - - # find primary key and print it first, ignoring implicit id if other pk exists - pk = appmodel._meta.pk - if pk and not appmodel._meta.abstract and pk in attributes: - add_attributes(pk) - - for field in attributes: - if skip_field(field): - continue - if pk and field == pk: - continue - add_attributes(field) - - if sort_fields: - model['fields'] = sorted(model['fields'], key=lambda field: (not field['primary_key'], not field['relation'], field['label'])) - - # FIXME: actually many_to_many fields aren't saved in this model's db table, so why should we add an attribute-line for them in the resulting graph? - #if appmodel._meta.many_to_many: - # for field in appmodel._meta.many_to_many: - # if skip_field(field): - # continue - # add_attributes(field) - - # relations - def add_relation(field, extras=""): - if verbose_names and field.verbose_name: - label = field.verbose_name.decode("utf8") - if label.islower(): - label = label.capitalize() - else: - label = field.name - - # show related field name - if hasattr(field, 'related_query_name'): - related_query_name = field.related_query_name() - if verbose_names and related_query_name.islower(): - related_query_name = related_query_name.replace('_', ' ').capitalize() - label += ' (%s)' % related_query_name - - # handle self-relationships - if field.rel.to == 'self': - target_model = field.model - else: - target_model = field.rel.to - - _rel = { - 'target_app': target_model.__module__.replace('.', '_'), - 'target': target_model.__name__, - 'type': type(field).__name__, - 'name': field.name, - 'label': label, - 'arrows': extras, - 'needs_node': True - } - if _rel not in model['relations'] and consider(_rel['target']): - model['relations'].append(_rel) - - for field in appmodel._meta.local_fields: - if field.attname.endswith('_ptr_id'): # excluding field redundant with inheritance relation - continue - if field in abstract_fields: # excluding fields inherited from abstract classes. they too show as local_fields - continue - if skip_field(field): - continue - if isinstance(field, OneToOneField): - add_relation(field, '[arrowhead=none, arrowtail=none, dir=both]') - elif isinstance(field, ForeignKey): - add_relation(field, '[arrowhead=none, arrowtail=dot, dir=both]') - - for field in appmodel._meta.local_many_to_many: - if skip_field(field): - continue - if isinstance(field, ManyToManyField): - if (getattr(field, 'creates_table', False) or # django 1.1. - (hasattr(field.rel.through, '_meta') and field.rel.through._meta.auto_created)): # django 1.2 - add_relation(field, '[arrowhead=dot arrowtail=dot, dir=both]') - elif isinstance(field, GenericRelation): - add_relation(field, mark_safe('[style="dotted", arrowhead=normal, arrowtail=normal, dir=both]')) - - if inheritance: - # add inheritance arrows - for parent in appmodel.__bases__: - if hasattr(parent, "_meta"): # parent is a model - l = "multi-table" - if parent._meta.abstract: - l = "abstract" - if appmodel._meta.proxy: - l = "proxy" - l += r"\ninheritance" - _rel = { - 'target_app': parent.__module__.replace(".", "_"), - 'target': parent.__name__, - 'type': "inheritance", - 'name': "inheritance", - 'label': l, - 'arrows': '[arrowhead=empty, arrowtail=none, dir=both]', - 'needs_node': True, - } - # TODO: seems as if abstract models aren't part of models.getModels, which is why they are printed by this without any attributes. - if _rel not in model['relations'] and consider(_rel['target']): - model['relations'].append(_rel) - - graph['models'].append(model) - if graph['models']: - graphs.append(graph) - - nodes = [] - for graph in graphs: - nodes.extend([e['name'] for e in graph['models']]) - - for graph in graphs: - for model in graph['models']: - for relation in model['relations']: - if relation['target'] in nodes: - relation['needs_node'] = False - - now = datetime.datetime.now() - t = loader.get_template('django_extensions/graph_models/digraph.dot') - - if not isinstance(t, Template): - raise Exception("Default Django template loader isn't used. " - "This can lead to the incorrect template rendering. " - "Please, check the settings.") - - c = Context({ - 'created_at': now.strftime("%Y-%m-%d %H:%M"), - 'cli_options': cli_options, - 'disable_fields': disable_fields, - 'use_subgraph': use_subgraph, - 'graphs': graphs, - }) - dot = t.render(c) - - return dot diff --git a/awx/lib/site-packages/django_extensions/management/notebook_extension.py b/awx/lib/site-packages/django_extensions/management/notebook_extension.py deleted file mode 100644 index 8fc806f79d..0000000000 --- a/awx/lib/site-packages/django_extensions/management/notebook_extension.py +++ /dev/null @@ -1,6 +0,0 @@ -def load_ipython_extension(ipython): - from django.core.management.color import no_style - from django_extensions.management.shells import import_objects - imported_objects = import_objects(options={'dont_load': []}, - style=no_style()) - ipython.push(imported_objects) diff --git a/awx/lib/site-packages/django_extensions/management/shells.py b/awx/lib/site-packages/django_extensions/management/shells.py deleted file mode 100644 index ff2c9d3a0a..0000000000 --- a/awx/lib/site-packages/django_extensions/management/shells.py +++ /dev/null @@ -1,159 +0,0 @@ -import six -import traceback - - -class ObjectImportError(Exception): - pass - - -def import_items(import_directives): - """ - Import the items in import_directives and return a list of the imported items - - Each item in import_directives should be one of the following forms - * a tuple like ('module.submodule', ('classname1', 'classname2')), which indicates a 'from module.submodule import classname1, classname2' - * a tuple like ('module.submodule', 'classname1'), which indicates a 'from module.submodule import classname1' - * a tuple like ('module.submodule', '*'), which indicates a 'from module.submodule import *' - * a simple 'module.submodule' which indicates 'import module.submodule'. - - Returns a dict mapping the names to the imported items - """ - imported_objects = {} - for directive in import_directives: - try: - # First try a straight import - if type(directive) is str: - imported_object = __import__(directive) - imported_objects[directive.split('.')[0]] = imported_object - print("import %s" % directive) - continue - try: - # Try the ('module.submodule', ('classname1', 'classname2')) form - for name in directive[1]: - imported_object = getattr(__import__(directive[0], {}, {}, name), name) - imported_objects[name] = imported_object - print("from %s import %s" % (directive[0], ', '.join(directive[1]))) - # If it is a tuple, but the second item isn't a list, so we have something like ('module.submodule', 'classname1') - except AttributeError: - # Check for the special '*' to import all - if directive[1] == '*': - imported_object = __import__(directive[0], {}, {}, directive[1]) - for k in dir(imported_object): - imported_objects[k] = getattr(imported_object, k) - print("from %s import *" % directive[0]) - else: - imported_object = getattr(__import__(directive[0], {}, {}, directive[1]), directive[1]) - imported_objects[directive[1]] = imported_object - print("from %s import %s" % (directive[0], directive[1])) - except ImportError: - try: - print("Unable to import %s" % directive) - except TypeError: - print("Unable to import %s from %s" % directive) - - return imported_objects - - -def import_objects(options, style): - # XXX: (Temporary) workaround for ticket #1796: force early loading of all - # models from installed apps. (this is fixed by now, but leaving it here - # for people using 0.96 or older trunk (pre [5919]) versions. - from django.db.models.loading import get_models, get_apps - mongoengine = False - try: - from mongoengine.base import _document_registry - mongoengine = True - except: - pass - - loaded_models = get_models() # NOQA - - from django.conf import settings - imported_objects = {} - - dont_load_cli = options.get('dont_load') # optparse will set this to [] if it doensnt exists - dont_load_conf = getattr(settings, 'SHELL_PLUS_DONT_LOAD', []) - dont_load = dont_load_cli + dont_load_conf - quiet_load = options.get('quiet_load') - - model_aliases = getattr(settings, 'SHELL_PLUS_MODEL_ALIASES', {}) - - # Perform pre-imports before any other imports - imports = import_items(getattr(settings, 'SHELL_PLUS_PRE_IMPORTS', {})) - for k, v in six.iteritems(imports): - imported_objects[k] = v - - load_models = {} - - if getattr(settings, 'SHELL_PLUS_DJANGO_IMPORTS', True): - load_models.update({ - 'django.core.cache': ['cache'], - 'django.core.urlresolvers': ['reverse'], - 'django.conf': ['settings'], - 'django.db': ['transaction'], - 'django.db.models': ['Avg', 'Count', 'F', 'Max', 'Min', 'Sum', 'Q'], - 'django.utils': ['timezone'], - }) - - if mongoengine: - for name, mod in six.iteritems(_document_registry): - name = name.split('.')[-1] - app_name = mod.__module__.split('.')[-2] - if app_name in dont_load or ("%s.%s" % (app_name, name)) in dont_load: - continue - - load_models.setdefault(mod.__module__, []) - load_models[mod.__module__].append(name) - - for app_mod in get_apps(): - app_models = get_models(app_mod) - if not app_models: - continue - - app_name = app_mod.__name__.split('.')[-2] - if app_name in dont_load: - continue - - app_aliases = model_aliases.get(app_name, {}) - for mod in app_models: - if "%s.%s" % (app_name, mod.__name__) in dont_load: - continue - - load_models.setdefault(mod.__module__, []) - load_models[mod.__module__].append(mod.__name__) - - for app_mod, models in sorted(six.iteritems(load_models)): - app_name = app_mod.split('.')[-2] - app_aliases = model_aliases.get(app_name, {}) - model_labels = [] - - for model_name in sorted(models): - try: - imported_object = getattr(__import__(app_mod, {}, {}, model_name), model_name) - - if "%s.%s" % (app_name, model_name) in dont_load: - continue - - alias = app_aliases.get(model_name, model_name) - imported_objects[alias] = imported_object - if model_name == alias: - model_labels.append(model_name) - else: - model_labels.append("%s (as %s)" % (model_name, alias)) - - except AttributeError as e: - if options.get("traceback"): - traceback.print_exc() - if not quiet_load: - print(style.ERROR("Failed to import '%s' from '%s' reason: %s" % (model_name, app_mod, str(e)))) - continue - - if not quiet_load: - print(style.SQL_COLTYPE("from %s import %s" % (app_mod, ", ".join(model_labels)))) - - # Perform post-imports after any other imports - imports = import_items(getattr(settings, 'SHELL_PLUS_POST_IMPORTS', {})) - for k, v in six.iteritems(imports): - imported_objects[k] = v - - return imported_objects diff --git a/awx/lib/site-packages/django_extensions/management/signals.py b/awx/lib/site-packages/django_extensions/management/signals.py deleted file mode 100644 index 6b198c0196..0000000000 --- a/awx/lib/site-packages/django_extensions/management/signals.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -signals we use to trigger regular batch jobs -""" -from django.dispatch import Signal - -run_minutely_jobs = Signal() -run_quarter_hourly_jobs = Signal() -run_hourly_jobs = Signal() -run_daily_jobs = Signal() -run_weekly_jobs = Signal() -run_monthly_jobs = Signal() -run_yearly_jobs = Signal() diff --git a/awx/lib/site-packages/django_extensions/management/technical_response.py b/awx/lib/site-packages/django_extensions/management/technical_response.py deleted file mode 100644 index 3e34e9e5ee..0000000000 --- a/awx/lib/site-packages/django_extensions/management/technical_response.py +++ /dev/null @@ -1,6 +0,0 @@ -import six - - -def null_technical_500_response(request, exc_type, exc_value, tb): - six.reraise(exc_type, exc_value, tb) - diff --git a/awx/lib/site-packages/django_extensions/management/utils.py b/awx/lib/site-packages/django_extensions/management/utils.py deleted file mode 100644 index 45cd046bb9..0000000000 --- a/awx/lib/site-packages/django_extensions/management/utils.py +++ /dev/null @@ -1,69 +0,0 @@ -from django.conf import settings -import os -import sys -import logging - -try: - from importlib import import_module -except ImportError: - try: - from django.utils.importlib import import_module - except ImportError: - def import_module(module): - return __import__(module, {}, {}, ['']) - - -def get_project_root(): - """ get the project root directory """ - django_settings_module = os.environ.get('DJANGO_SETTINGS_MODULE') - if not django_settings_module: - module_str = settings.SETTINGS_MODULE - else: - module_str = django_settings_module.split(".")[0] - mod = import_module(module_str) - return os.path.dirname(os.path.abspath(mod.__file__)) - - -def _make_writeable(filename): - """ - Make sure that the file is writeable. Useful if our source is - read-only. - - """ - import stat - if sys.platform.startswith('java'): - # On Jython there is no os.access() - return - if not os.access(filename, os.W_OK): - st = os.stat(filename) - new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR - os.chmod(filename, new_permissions) - - -def setup_logger(logger, stream, filename=None, fmt=None): - """Sets up a logger (if no handlers exist) for console output, - and file 'tee' output if desired.""" - if len(logger.handlers) < 1: - console = logging.StreamHandler(stream) - console.setLevel(logging.DEBUG) - console.setFormatter(logging.Formatter(fmt)) - logger.addHandler(console) - logger.setLevel(logging.DEBUG) - - if filename: - outfile = logging.FileHandler(filename) - outfile.setLevel(logging.INFO) - outfile.setFormatter(logging.Formatter("%(asctime)s " + (fmt if fmt else '%(message)s'))) - logger.addHandler(outfile) - - -class RedirectHandler(logging.Handler): - """Redirect logging sent to one logger (name) to another.""" - def __init__(self, name, level=logging.DEBUG): - # Contemplate feasibility of copying a destination (allow original handler) and redirecting. - logging.Handler.__init__(self, level) - self.name = name - self.logger = logging.getLogger(name) - - def emit(self, record): - self.logger.handle(record) diff --git a/awx/lib/site-packages/django_extensions/migrations/0001_empty.py b/awx/lib/site-packages/django_extensions/migrations/0001_empty.py deleted file mode 100644 index e631efd366..0000000000 --- a/awx/lib/site-packages/django_extensions/migrations/0001_empty.py +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- -from south.v2 import SchemaMigration - - -class Migration(SchemaMigration): - - def forwards(self, orm): - pass - - def backwards(self, orm): - pass - - models = { - - } - - complete_apps = ['django_extensions'] diff --git a/awx/lib/site-packages/django_extensions/migrations/__init__.py b/awx/lib/site-packages/django_extensions/migrations/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/models.py b/awx/lib/site-packages/django_extensions/models.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/mongodb/__init__.py b/awx/lib/site-packages/django_extensions/mongodb/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/mongodb/fields/__init__.py b/awx/lib/site-packages/django_extensions/mongodb/fields/__init__.py deleted file mode 100644 index d36ddb8405..0000000000 --- a/awx/lib/site-packages/django_extensions/mongodb/fields/__init__.py +++ /dev/null @@ -1,248 +0,0 @@ -""" -MongoDB model fields emulating Django Extensions' additional model fields - -These fields are essentially identical to existing Extensions fields, but South hooks have been removed (since mongo requires no schema migration) - -""" - -import six -from django.template.defaultfilters import slugify -from django import forms -from mongoengine.fields import StringField, DateTimeField -import datetime -import re -from django.utils.translation import ugettext_lazy as _ - -try: - import uuid - assert uuid -except ImportError: - from django_extensions.utils import uuid - - -class SlugField(StringField): - description = _("String (up to %(max_length)s)") - - def __init__(self, *args, **kwargs): - kwargs['max_length'] = kwargs.get('max_length', 50) - # Set db_index=True unless it's been set manually. - if 'db_index' not in kwargs: - kwargs['db_index'] = True - super(SlugField, self).__init__(*args, **kwargs) - - def get_internal_type(self): - return "SlugField" - - def formfield(self, **kwargs): - defaults = {'form_class': forms.SlugField} - defaults.update(kwargs) - return super(SlugField, self).formfield(**defaults) - - -class AutoSlugField(SlugField): - """ AutoSlugField, adapted for MongoDB - - By default, sets editable=False, blank=True. - - Required arguments: - - populate_from - Specifies which field or list of fields the slug is populated from. - - Optional arguments: - - separator - Defines the used separator (default: '-') - - overwrite - If set to True, overwrites the slug on every save (default: False) - - Inspired by SmileyChris' Unique Slugify snippet: - http://www.djangosnippets.org/snippets/690/ - """ - def __init__(self, *args, **kwargs): - kwargs.setdefault('blank', True) - kwargs.setdefault('editable', False) - - populate_from = kwargs.pop('populate_from', None) - if populate_from is None: - raise ValueError("missing 'populate_from' argument") - else: - self._populate_from = populate_from - self.separator = kwargs.pop('separator', six.u('-')) - self.overwrite = kwargs.pop('overwrite', False) - super(AutoSlugField, self).__init__(*args, **kwargs) - - def _slug_strip(self, value): - """ - Cleans up a slug by removing slug separator characters that occur at - the beginning or end of a slug. - - If an alternate separator is used, it will also replace any instances - of the default '-' separator with the new separator. - """ - re_sep = '(?:-|%s)' % re.escape(self.separator) - value = re.sub('%s+' % re_sep, self.separator, value) - return re.sub(r'^%s+|%s+$' % (re_sep, re_sep), '', value) - - def slugify_func(self, content): - return slugify(content) - - def create_slug(self, model_instance, add): - # get fields to populate from and slug field to set - if not isinstance(self._populate_from, (list, tuple)): - self._populate_from = (self._populate_from, ) - slug_field = model_instance._meta.get_field(self.attname) - - if add or self.overwrite: - # slugify the original field content and set next step to 2 - slug_for_field = lambda field: self.slugify_func(getattr(model_instance, field)) - slug = self.separator.join(map(slug_for_field, self._populate_from)) - next = 2 - else: - # get slug from the current model instance and calculate next - # step from its number, clean-up - slug = self._slug_strip(getattr(model_instance, self.attname)) - next = slug.split(self.separator)[-1] - if next.isdigit(): - slug = self.separator.join(slug.split(self.separator)[:-1]) - next = int(next) - else: - next = 2 - - # strip slug depending on max_length attribute of the slug field - # and clean-up - slug_len = slug_field.max_length - if slug_len: - slug = slug[:slug_len] - slug = self._slug_strip(slug) - original_slug = slug - - # exclude the current model instance from the queryset used in finding - # the next valid slug - queryset = model_instance.__class__._default_manager.all() - if model_instance.pk: - queryset = queryset.exclude(pk=model_instance.pk) - - # form a kwarg dict used to impliment any unique_together contraints - kwargs = {} - for params in model_instance._meta.unique_together: - if self.attname in params: - for param in params: - kwargs[param] = getattr(model_instance, param, None) - kwargs[self.attname] = slug - - # increases the number while searching for the next valid slug - # depending on the given slug, clean-up - while not slug or queryset.filter(**kwargs): - slug = original_slug - end = '%s%s' % (self.separator, next) - end_len = len(end) - if slug_len and len(slug) + end_len > slug_len: - slug = slug[:slug_len - end_len] - slug = self._slug_strip(slug) - slug = '%s%s' % (slug, end) - kwargs[self.attname] = slug - next += 1 - return slug - - def pre_save(self, model_instance, add): - value = six.u(self.create_slug(model_instance, add)) - setattr(model_instance, self.attname, value) - return value - - def get_internal_type(self): - return "SlugField" - - -class CreationDateTimeField(DateTimeField): - """ CreationDateTimeField - - By default, sets editable=False, blank=True, default=datetime.now - """ - - def __init__(self, *args, **kwargs): - kwargs.setdefault('default', datetime.datetime.now) - DateTimeField.__init__(self, *args, **kwargs) - - def get_internal_type(self): - return "DateTimeField" - - -class ModificationDateTimeField(CreationDateTimeField): - """ ModificationDateTimeField - - By default, sets editable=False, blank=True, default=datetime.now - - Sets value to datetime.now() on each save of the model. - """ - - def pre_save(self, model, add): - value = datetime.datetime.now() - setattr(model, self.attname, value) - return value - - def get_internal_type(self): - return "DateTimeField" - - -class UUIDVersionError(Exception): - pass - - -class UUIDField(StringField): - """ UUIDField - - By default uses UUID version 1 (generate from host ID, sequence number and current time) - - The field support all uuid versions which are natively supported by the uuid python module. - For more information see: http://docs.python.org/lib/module-uuid.html - """ - - def __init__(self, verbose_name=None, name=None, auto=True, version=1, node=None, clock_seq=None, namespace=None, **kwargs): - kwargs['max_length'] = 36 - self.auto = auto - self.version = version - if version == 1: - self.node, self.clock_seq = node, clock_seq - elif version == 3 or version == 5: - self.namespace, self.name = namespace, name - StringField.__init__(self, verbose_name, name, **kwargs) - - def get_internal_type(self): - return StringField.__name__ - - def contribute_to_class(self, cls, name): - if self.primary_key: - assert not cls._meta.has_auto_field, "A model can't have more than one AutoField: %s %s %s; have %s" % (self, cls, name, cls._meta.auto_field) - super(UUIDField, self).contribute_to_class(cls, name) - cls._meta.has_auto_field = True - cls._meta.auto_field = self - else: - super(UUIDField, self).contribute_to_class(cls, name) - - def create_uuid(self): - if not self.version or self.version == 4: - return uuid.uuid4() - elif self.version == 1: - return uuid.uuid1(self.node, self.clock_seq) - elif self.version == 2: - raise UUIDVersionError("UUID version 2 is not supported.") - elif self.version == 3: - return uuid.uuid3(self.namespace, self.name) - elif self.version == 5: - return uuid.uuid5(self.namespace, self.name) - else: - raise UUIDVersionError("UUID version %s is not valid." % self.version) - - def pre_save(self, model_instance, add): - if self.auto and add: - value = six.u(self.create_uuid()) - setattr(model_instance, self.attname, value) - return value - else: - value = super(UUIDField, self).pre_save(model_instance, add) - if self.auto and not value: - value = six.u(self.create_uuid()) - setattr(model_instance, self.attname, value) - return value diff --git a/awx/lib/site-packages/django_extensions/mongodb/fields/encrypted.py b/awx/lib/site-packages/django_extensions/mongodb/fields/encrypted.py deleted file mode 100644 index 2c8d7f782c..0000000000 --- a/awx/lib/site-packages/django_extensions/mongodb/fields/encrypted.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Encrypted fields from Django Extensions, modified for use with mongoDB -""" -from mongoengine.base import BaseField -from django.core.exceptions import ImproperlyConfigured -from django import forms -from django.conf import settings - -try: - from keyczar import keyczar -except ImportError: - raise ImportError('Using an encrypted field requires the Keyczar module. You can obtain Keyczar from http://www.keyczar.org/.') - - -class BaseEncryptedField(BaseField): - prefix = 'enc_str:::' - - def __init__(self, *args, **kwargs): - if not hasattr(settings, 'ENCRYPTED_FIELD_KEYS_DIR'): - raise ImproperlyConfigured('You must set settings.ENCRYPTED_FIELD_KEYS_DIR to your Keyczar keys directory.') - self.crypt = keyczar.Crypter.Read(settings.ENCRYPTED_FIELD_KEYS_DIR) - super(BaseEncryptedField, self).__init__(*args, **kwargs) - - def to_python(self, value): - if (value.startswith(self.prefix)): - retval = self.crypt.Decrypt(value[len(self.prefix):]) - else: - retval = value - - return retval - - def get_db_prep_value(self, value): - if not value.startswith(self.prefix): - value = self.prefix + self.crypt.Encrypt(value) - return value - - -class EncryptedTextField(BaseEncryptedField): - def get_internal_type(self): - return 'StringField' - - def formfield(self, **kwargs): - defaults = {'widget': forms.Textarea} - defaults.update(kwargs) - return super(EncryptedTextField, self).formfield(**defaults) - - -class EncryptedCharField(BaseEncryptedField): - def __init__(self, max_length=None, *args, **kwargs): - if max_length: - max_length += len(self.prefix) - - super(EncryptedCharField, self).__init__(max_length=max_length, *args, **kwargs) - - def get_internal_type(self): - return "StringField" - - def formfield(self, **kwargs): - defaults = {'max_length': self.max_length} - defaults.update(kwargs) - return super(EncryptedCharField, self).formfield(**defaults) diff --git a/awx/lib/site-packages/django_extensions/mongodb/fields/json.py b/awx/lib/site-packages/django_extensions/mongodb/fields/json.py deleted file mode 100644 index 5bccd4ef0c..0000000000 --- a/awx/lib/site-packages/django_extensions/mongodb/fields/json.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -JSONField automatically serializes most Python terms to JSON data. -Creates a TEXT field with a default value of "{}". See test_json.py for -more information. - - from django.db import models - from django_extensions.db.fields import json - - class LOL(models.Model): - extra = json.JSONField() -""" - -import six -import datetime -from decimal import Decimal -from django.conf import settings -from django.utils import simplejson -from mongoengine.fields import StringField - - -class JSONEncoder(simplejson.JSONEncoder): - def default(self, obj): - if isinstance(obj, Decimal): - return str(obj) - elif isinstance(obj, datetime.datetime): - assert settings.TIME_ZONE == 'UTC' - return obj.strftime('%Y-%m-%dT%H:%M:%SZ') - return simplejson.JSONEncoder.default(self, obj) - - -def dumps(value): - assert isinstance(value, dict) - return JSONEncoder().encode(value) - - -def loads(txt): - value = simplejson.loads(txt, parse_float=Decimal, encoding=settings.DEFAULT_CHARSET) - assert isinstance(value, dict) - return value - - -class JSONDict(dict): - """ - Hack so repr() called by dumpdata will output JSON instead of - Python formatted data. This way fixtures will work! - """ - def __repr__(self): - return dumps(self) - - -class JSONField(StringField): - """JSONField is a generic textfield that neatly serializes/unserializes - JSON objects seamlessly. Main thingy must be a dict object.""" - - def __init__(self, *args, **kwargs): - if 'default' not in kwargs: - kwargs['default'] = '{}' - StringField.__init__(self, *args, **kwargs) - - def to_python(self, value): - """Convert our string value to JSON after we load it from the DB""" - if not value: - return {} - elif isinstance(value, six.string_types): - res = loads(value) - assert isinstance(res, dict) - return JSONDict(**res) - else: - return value - - def get_db_prep_save(self, value): - """Convert our JSON object to a string before we save""" - if not value: - return super(JSONField, self).get_db_prep_save("") - else: - return super(JSONField, self).get_db_prep_save(dumps(value)) - diff --git a/awx/lib/site-packages/django_extensions/mongodb/models.py b/awx/lib/site-packages/django_extensions/mongodb/models.py deleted file mode 100644 index 11f114f67b..0000000000 --- a/awx/lib/site-packages/django_extensions/mongodb/models.py +++ /dev/null @@ -1,69 +0,0 @@ -""" -Django Extensions abstract base mongoengine Document classes. -""" -import datetime -from mongoengine.document import Document -from mongoengine.fields import StringField, IntField, DateTimeField -from mongoengine.queryset import QuerySetManager -from django.utils.translation import ugettext_lazy as _ -from django_extensions.mongodb.fields import ModificationDateTimeField, CreationDateTimeField, AutoSlugField - - -class TimeStampedModel(Document): - """ TimeStampedModel - An abstract base class model that provides self-managed "created" and - "modified" fields. - """ - created = CreationDateTimeField(_('created')) - modified = ModificationDateTimeField(_('modified')) - - class Meta: - abstract = True - - -class TitleSlugDescriptionModel(Document): - """ TitleSlugDescriptionModel - An abstract base class model that provides title and description fields - and a self-managed "slug" field that populates from the title. - """ - title = StringField(_('title'), max_length=255) - slug = AutoSlugField(_('slug'), populate_from='title') - description = StringField(_('description'), blank=True, null=True) - - class Meta: - abstract = True - - -class ActivatorModelManager(QuerySetManager): - """ ActivatorModelManager - Manager to return instances of ActivatorModel: SomeModel.objects.active() / .inactive() - """ - def active(self): - """ Returns active instances of ActivatorModel: SomeModel.objects.active() """ - return super(ActivatorModelManager, self).get_query_set().filter(status=1) - - def inactive(self): - """ Returns inactive instances of ActivatorModel: SomeModel.objects.inactive() """ - return super(ActivatorModelManager, self).get_query_set().filter(status=0) - - -class ActivatorModel(Document): - """ ActivatorModel - An abstract base class model that provides activate and deactivate fields. - """ - STATUS_CHOICES = ( - (0, _('Inactive')), - (1, _('Active')), - ) - status = IntField(_('status'), choices=STATUS_CHOICES, default=1) - activate_date = DateTimeField(blank=True, null=True, help_text=_('keep empty for an immediate activation')) - deactivate_date = DateTimeField(blank=True, null=True, help_text=_('keep empty for indefinite activation')) - objects = ActivatorModelManager() - - class Meta: - abstract = True - - def save(self, *args, **kwargs): - if not self.activate_date: - self.activate_date = datetime.datetime.now() - super(ActivatorModel, self).save(*args, **kwargs) diff --git a/awx/lib/site-packages/django_extensions/settings.py b/awx/lib/site-packages/django_extensions/settings.py deleted file mode 100644 index 9e7b5d45cc..0000000000 --- a/awx/lib/site-packages/django_extensions/settings.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.conf import settings - -REPLACEMENTS = { -} -add_replacements = getattr(settings, 'EXTENSIONS_REPLACEMENTS', {}) -REPLACEMENTS.update(add_replacements) - diff --git a/awx/lib/site-packages/django_extensions/static/django_extensions/css/jquery.autocomplete.css b/awx/lib/site-packages/django_extensions/static/django_extensions/css/jquery.autocomplete.css deleted file mode 100644 index c9d97b0396..0000000000 --- a/awx/lib/site-packages/django_extensions/static/django_extensions/css/jquery.autocomplete.css +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @fileOverview CSS for jquery-autocomplete, the jQuery Autocompleter - * @author <a href="mailto:dylan@dyve.net">Dylan Verheul</a> - * @license MIT | GPL | Apache 2.0, see LICENSE.txt - * @see https://github.com/dyve/jquery-autocomplete - */ -.acResults { - padding: 0px; - border: 1px solid WindowFrame; - background-color: Window; - overflow: hidden; -} - -.acResults ul { - margin: 0px; - padding: 0px; - list-style-position: outside; - list-style: none; -} - -.acResults ul li { - margin: 0px; - padding: 2px 5px; - cursor: pointer; - display: block; - font: menu; - font-size: 12px; - overflow: hidden; -} - -.acLoading { - background : url('../img/indicator.gif') right center no-repeat; -} - -.acSelect { - background-color: Highlight; - color: HighlightText; -} diff --git a/awx/lib/site-packages/django_extensions/static/django_extensions/img/indicator.gif b/awx/lib/site-packages/django_extensions/static/django_extensions/img/indicator.gif deleted file mode 100644 index 085ccaecaf..0000000000 Binary files a/awx/lib/site-packages/django_extensions/static/django_extensions/img/indicator.gif and /dev/null differ diff --git a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery-1.7.2.min.js b/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery-1.7.2.min.js deleted file mode 100644 index 16ad06c5ac..0000000000 --- a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery-1.7.2.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.7.2 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( -a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f -.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.ajaxQueue.js b/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.ajaxQueue.js deleted file mode 100644 index cd4492c13c..0000000000 --- a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.ajaxQueue.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Ajax Queue Plugin - * - * Homepage: http://jquery.com/plugins/project/ajaxqueue - * Documentation: http://docs.jquery.com/AjaxQueue - */ - -/** - -<script> -$(function(){ - jQuery.ajaxQueue({ - url: "test.php", - success: function(html){ jQuery("ul").append(html); } - }); - jQuery.ajaxQueue({ - url: "test.php", - success: function(html){ jQuery("ul").append(html); } - }); - jQuery.ajaxSync({ - url: "test.php", - success: function(html){ jQuery("ul").append("<b>"+html+"</b>"); } - }); - jQuery.ajaxSync({ - url: "test.php", - success: function(html){ jQuery("ul").append("<b>"+html+"</b>"); } - }); -}); -</script> -<ul style="position: absolute; top: 5px; right: 5px;"></ul> - - */ -/* - * Queued Ajax requests. - * A new Ajax request won't be started until the previous queued - * request has finished. - */ - -/* - * Synced Ajax requests. - * The Ajax request will happen as soon as you call this method, but - * the callbacks (success/error/complete) won't fire until all previous - * synced requests have been completed. - */ - - -(function(jQuery) { - - var ajax = jQuery.ajax; - - var pendingRequests = {}; - - var synced = []; - var syncedData = []; - - jQuery.ajax = function(settings) { - // create settings for compatibility with ajaxSetup - settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings)); - - var port = settings.port; - - switch(settings.mode) { - case "abort": - if ( pendingRequests[port] ) { - pendingRequests[port].abort(); - } - return pendingRequests[port] = ajax.apply(this, arguments); - case "queue": - var _old = settings.complete; - settings.complete = function(){ - if ( _old ) - _old.apply( this, arguments ); - jQuery([ajax]).dequeue("ajax" + port );; - }; - - jQuery([ ajax ]).queue("ajax" + port, function(){ - ajax( settings ); - }); - return; - case "sync": - var pos = synced.length; - - synced[ pos ] = { - error: settings.error, - success: settings.success, - complete: settings.complete, - done: false - }; - - syncedData[ pos ] = { - error: [], - success: [], - complete: [] - }; - - settings.error = function(){ syncedData[ pos ].error = arguments; }; - settings.success = function(){ syncedData[ pos ].success = arguments; }; - settings.complete = function(){ - syncedData[ pos ].complete = arguments; - synced[ pos ].done = true; - - if ( pos == 0 || !synced[ pos-1 ] ) - for ( var i = pos; i < synced.length && synced[i].done; i++ ) { - if ( synced[i].error ) synced[i].error.apply( jQuery, syncedData[i].error ); - if ( synced[i].success ) synced[i].success.apply( jQuery, syncedData[i].success ); - if ( synced[i].complete ) synced[i].complete.apply( jQuery, syncedData[i].complete ); - - synced[i] = null; - syncedData[i] = null; - } - }; - } - return ajax.apply(this, arguments); - }; - -})((typeof window.jQuery == 'undefined' && typeof window.django != 'undefined') - ? django.jQuery - : jQuery -); diff --git a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js b/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js deleted file mode 100644 index 7ba5d7402a..0000000000 --- a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js +++ /dev/null @@ -1,1152 +0,0 @@ -/** - * @fileOverview jquery-autocomplete, the jQuery Autocompleter - * @author <a href="mailto:dylan@dyve.net">Dylan Verheul</a> - * @version 2.4.4 - * @requires jQuery 1.6+ - * @license MIT | GPL | Apache 2.0, see LICENSE.txt - * @see https://github.com/dyve/jquery-autocomplete - */ -(function($) { - "use strict"; - - /** - * jQuery autocomplete plugin - * @param {object|string} options - * @returns (object} jQuery object - */ - $.fn.autocomplete = function(options) { - var url; - if (arguments.length > 1) { - url = options; - options = arguments[1]; - options.url = url; - } else if (typeof options === 'string') { - url = options; - options = { url: url }; - } - var opts = $.extend({}, $.fn.autocomplete.defaults, options); - return this.each(function() { - var $this = $(this); - $this.data('autocompleter', new $.Autocompleter( - $this, - $.meta ? $.extend({}, opts, $this.data()) : opts - )); - }); - }; - - /** - * Store default options - * @type {object} - */ - $.fn.autocomplete.defaults = { - inputClass: 'acInput', - loadingClass: 'acLoading', - resultsClass: 'acResults', - selectClass: 'acSelect', - queryParamName: 'q', - extraParams: {}, - remoteDataType: false, - lineSeparator: '\n', - cellSeparator: '|', - minChars: 2, - maxItemsToShow: 10, - delay: 400, - useCache: true, - maxCacheLength: 10, - matchSubset: true, - matchCase: false, - matchInside: true, - mustMatch: false, - selectFirst: false, - selectOnly: false, - showResult: null, - preventDefaultReturn: 1, - preventDefaultTab: 0, - autoFill: false, - filterResults: true, - filter: true, - sortResults: true, - sortFunction: null, - onItemSelect: null, - onNoMatch: null, - onFinish: null, - matchStringConverter: null, - beforeUseConverter: null, - autoWidth: 'min-width', - useDelimiter: false, - delimiterChar: ',', - delimiterKeyCode: 188, - processData: null, - onError: null, - enabled: true - }; - - /** - * Sanitize result - * @param {Object} result - * @returns {Object} object with members value (String) and data (Object) - * @private - */ - var sanitizeResult = function(result) { - var value, data; - var type = typeof result; - if (type === 'string') { - value = result; - data = {}; - } else if ($.isArray(result)) { - value = result[0]; - data = result.slice(1); - } else if (type === 'object') { - value = result.value; - data = result.data; - } - value = String(value); - if (typeof data !== 'object') { - data = {}; - } - return { - value: value, - data: data - }; - }; - - /** - * Sanitize integer - * @param {mixed} value - * @param {Object} options - * @returns {Number} integer - * @private - */ - var sanitizeInteger = function(value, stdValue, options) { - var num = parseInt(value, 10); - options = options || {}; - if (isNaN(num) || (options.min && num < options.min)) { - num = stdValue; - } - return num; - }; - - /** - * Create partial url for a name/value pair - */ - var makeUrlParam = function(name, value) { - return [name, encodeURIComponent(value)].join('='); - }; - - /** - * Build an url - * @param {string} url Base url - * @param {object} [params] Dictionary of parameters - */ - var makeUrl = function(url, params) { - var urlAppend = []; - $.each(params, function(index, value) { - urlAppend.push(makeUrlParam(index, value)); - }); - if (urlAppend.length) { - url += url.indexOf('?') === -1 ? '?' : '&'; - url += urlAppend.join('&'); - } - return url; - }; - - /** - * Default sort filter - * @param {object} a - * @param {object} b - * @param {boolean} matchCase - * @returns {number} - */ - var sortValueAlpha = function(a, b, matchCase) { - a = String(a.value); - b = String(b.value); - if (!matchCase) { - a = a.toLowerCase(); - b = b.toLowerCase(); - } - if (a > b) { - return 1; - } - if (a < b) { - return -1; - } - return 0; - }; - - /** - * Parse data received in text format - * @param {string} text Plain text input - * @param {string} lineSeparator String that separates lines - * @param {string} cellSeparator String that separates cells - * @returns {array} Array of autocomplete data objects - */ - var plainTextParser = function(text, lineSeparator, cellSeparator) { - var results = []; - var i, j, data, line, value, lines; - // Be nice, fix linebreaks before splitting on lineSeparator - lines = String(text).replace('\r\n', '\n').split(lineSeparator); - for (i = 0; i < lines.length; i++) { - line = lines[i].split(cellSeparator); - data = []; - for (j = 0; j < line.length; j++) { - data.push(decodeURIComponent(line[j])); - } - value = data.shift(); - results.push({ value: value, data: data }); - } - return results; - }; - - /** - * Autocompleter class - * @param {object} $elem jQuery object with one input tag - * @param {object} options Settings - * @constructor - */ - $.Autocompleter = function($elem, options) { - - /** - * Assert parameters - */ - if (!$elem || !($elem instanceof $) || $elem.length !== 1 || $elem.get(0).tagName.toUpperCase() !== 'INPUT') { - throw new Error('Invalid parameter for jquery.Autocompleter, jQuery object with one element with INPUT tag expected.'); - } - - /** - * @constant Link to this instance - * @type object - * @private - */ - var self = this; - - /** - * @property {object} Options for this instance - * @public - */ - this.options = options; - - /** - * @property object Cached data for this instance - * @private - */ - this.cacheData_ = {}; - - /** - * @property {number} Number of cached data items - * @private - */ - this.cacheLength_ = 0; - - /** - * @property {string} Class name to mark selected item - * @private - */ - this.selectClass_ = 'jquery-autocomplete-selected-item'; - - /** - * @property {number} Handler to activation timeout - * @private - */ - this.keyTimeout_ = null; - - /** - * @property {number} Handler to finish timeout - * @private - */ - this.finishTimeout_ = null; - - /** - * @property {number} Last key pressed in the input field (store for behavior) - * @private - */ - this.lastKeyPressed_ = null; - - /** - * @property {string} Last value processed by the autocompleter - * @private - */ - this.lastProcessedValue_ = null; - - /** - * @property {string} Last value selected by the user - * @private - */ - this.lastSelectedValue_ = null; - - /** - * @property {boolean} Is this autocompleter active (showing results)? - * @see showResults - * @private - */ - this.active_ = false; - - /** - * @property {boolean} Is this autocompleter allowed to finish on blur? - * @private - */ - this.finishOnBlur_ = true; - - /** - * Sanitize options - */ - this.options.minChars = sanitizeInteger(this.options.minChars, $.fn.autocomplete.defaults.minChars, { min: 0 }); - this.options.maxItemsToShow = sanitizeInteger(this.options.maxItemsToShow, $.fn.autocomplete.defaults.maxItemsToShow, { min: 0 }); - this.options.maxCacheLength = sanitizeInteger(this.options.maxCacheLength, $.fn.autocomplete.defaults.maxCacheLength, { min: 1 }); - this.options.delay = sanitizeInteger(this.options.delay, $.fn.autocomplete.defaults.delay, { min: 0 }); - if (this.options.preventDefaultReturn != 2) { - this.options.preventDefaultReturn = this.options.preventDefaultReturn ? 1 : 0; - } - if (this.options.preventDefaultTab != 2) { - this.options.preventDefaultTab = this.options.preventDefaultTab ? 1 : 0; - } - - /** - * Init DOM elements repository - */ - this.dom = {}; - - /** - * Store the input element we're attached to in the repository - */ - this.dom.$elem = $elem; - - /** - * Switch off the native autocomplete and add the input class - */ - this.dom.$elem.attr('autocomplete', 'off').addClass(this.options.inputClass); - - /** - * Create DOM element to hold results, and force absolute position - */ - this.dom.$results = $('<div></div>').hide().addClass(this.options.resultsClass).css({ - position: 'absolute' - }); - $('body').append(this.dom.$results); - - /** - * Attach keyboard monitoring to $elem - */ - $elem.keydown(function(e) { - self.lastKeyPressed_ = e.keyCode; - switch(self.lastKeyPressed_) { - - case self.options.delimiterKeyCode: // comma = 188 - if (self.options.useDelimiter && self.active_) { - self.selectCurrent(); - } - break; - - // ignore navigational & special keys - case 35: // end - case 36: // home - case 16: // shift - case 17: // ctrl - case 18: // alt - case 37: // left - case 39: // right - break; - - case 38: // up - e.preventDefault(); - if (self.active_) { - self.focusPrev(); - } else { - self.activate(); - } - return false; - - case 40: // down - e.preventDefault(); - if (self.active_) { - self.focusNext(); - } else { - self.activate(); - } - return false; - - case 9: // tab - if (self.active_) { - self.selectCurrent(); - if (self.options.preventDefaultTab) { - e.preventDefault(); - return false; - } - } - if (self.options.preventDefaultTab === 2) { - e.preventDefault(); - return false; - } - break; - - case 13: // return - if (self.active_) { - self.selectCurrent(); - if (self.options.preventDefaultReturn) { - e.preventDefault(); - return false; - } - } - if (self.options.preventDefaultReturn === 2) { - e.preventDefault(); - return false; - } - break; - - case 27: // escape - if (self.active_) { - e.preventDefault(); - self.deactivate(true); - return false; - } - break; - - default: - self.activate(); - - } - }); - - /** - * Attach paste event listener because paste may occur much later then keydown or even without a keydown at all - */ - $elem.on('paste', function() { - self.activate(); - }); - - /** - * Finish on blur event - * Use a timeout because instant blur gives race conditions - */ - var onBlurFunction = function() { - self.deactivate(true); - } - $elem.blur(function() { - if (self.finishOnBlur_) { - self.finishTimeout_ = setTimeout(onBlurFunction, 200); - } - }); - /** - * Catch a race condition on form submit - */ - $elem.parents('form').on('submit', onBlurFunction); - - }; - - /** - * Position output DOM elements - * @private - */ - $.Autocompleter.prototype.position = function() { - var offset = this.dom.$elem.offset(); - var height = this.dom.$results.outerHeight(); - var totalHeight = $(window).outerHeight(); - var inputBottom = offset.top + this.dom.$elem.outerHeight(); - var bottomIfDown = inputBottom + height; - // Set autocomplete results at the bottom of input - var position = {top: inputBottom, left: offset.left}; - if (bottomIfDown > totalHeight) { - // Try to set autocomplete results at the top of input - var topIfUp = offset.top - height; - if (topIfUp >= 0) { - position.top = topIfUp; - } - } - this.dom.$results.css(position); - }; - - /** - * Read from cache - * @private - */ - $.Autocompleter.prototype.cacheRead = function(filter) { - var filterLength, searchLength, search, maxPos, pos; - if (this.options.useCache) { - filter = String(filter); - filterLength = filter.length; - if (this.options.matchSubset) { - searchLength = 1; - } else { - searchLength = filterLength; - } - while (searchLength <= filterLength) { - if (this.options.matchInside) { - maxPos = filterLength - searchLength; - } else { - maxPos = 0; - } - pos = 0; - while (pos <= maxPos) { - search = filter.substr(0, searchLength); - if (this.cacheData_[search] !== undefined) { - return this.cacheData_[search]; - } - pos++; - } - searchLength++; - } - } - return false; - }; - - /** - * Write to cache - * @private - */ - $.Autocompleter.prototype.cacheWrite = function(filter, data) { - if (this.options.useCache) { - if (this.cacheLength_ >= this.options.maxCacheLength) { - this.cacheFlush(); - } - filter = String(filter); - if (this.cacheData_[filter] !== undefined) { - this.cacheLength_++; - } - this.cacheData_[filter] = data; - return this.cacheData_[filter]; - } - return false; - }; - - /** - * Flush cache - * @public - */ - $.Autocompleter.prototype.cacheFlush = function() { - this.cacheData_ = {}; - this.cacheLength_ = 0; - }; - - /** - * Call hook - * Note that all called hooks are passed the autocompleter object - * @param {string} hook - * @param data - * @returns Result of called hook, false if hook is undefined - */ - $.Autocompleter.prototype.callHook = function(hook, data) { - var f = this.options[hook]; - if (f && $.isFunction(f)) { - return f(data, this); - } - return false; - }; - - /** - * Set timeout to activate autocompleter - */ - $.Autocompleter.prototype.activate = function() { - if (!this.options.enabled) return; - var self = this; - if (this.keyTimeout_) { - clearTimeout(this.keyTimeout_); - } - this.keyTimeout_ = setTimeout(function() { - self.activateNow(); - }, this.options.delay); - }; - - /** - * Activate autocompleter immediately - */ - $.Autocompleter.prototype.activateNow = function() { - var value = this.beforeUseConverter(this.dom.$elem.val()); - if (value !== this.lastProcessedValue_ && value !== this.lastSelectedValue_) { - this.fetchData(value); - } - }; - - /** - * Get autocomplete data for a given value - * @param {string} value Value to base autocompletion on - * @private - */ - $.Autocompleter.prototype.fetchData = function(value) { - var self = this; - var processResults = function(results, filter) { - if (self.options.processData) { - results = self.options.processData(results); - } - self.showResults(self.filterResults(results, filter), filter); - }; - this.lastProcessedValue_ = value; - if (value.length < this.options.minChars) { - processResults([], value); - } else if (this.options.data) { - processResults(this.options.data, value); - } else { - this.fetchRemoteData(value, function(remoteData) { - processResults(remoteData, value); - }); - } - }; - - /** - * Get remote autocomplete data for a given value - * @param {string} filter The filter to base remote data on - * @param {function} callback The function to call after data retrieval - * @private - */ - $.Autocompleter.prototype.fetchRemoteData = function(filter, callback) { - var data = this.cacheRead(filter); - if (data) { - callback(data); - } else { - var self = this; - var dataType = self.options.remoteDataType === 'json' ? 'json' : 'text'; - var ajaxCallback = function(data) { - var parsed = false; - if (data !== false) { - parsed = self.parseRemoteData(data); - self.cacheWrite(filter, parsed); - } - self.dom.$elem.removeClass(self.options.loadingClass); - callback(parsed); - }; - this.dom.$elem.addClass(this.options.loadingClass); - $.ajax({ - url: this.makeUrl(filter), - success: ajaxCallback, - error: function(jqXHR, textStatus, errorThrown) { - if($.isFunction(self.options.onError)) { - self.options.onError(jqXHR, textStatus, errorThrown); - } else { - ajaxCallback(false); - } - }, - dataType: dataType - }); - } - }; - - /** - * Create or update an extra parameter for the remote request - * @param {string} name Parameter name - * @param {string} value Parameter value - * @public - */ - $.Autocompleter.prototype.setExtraParam = function(name, value) { - var index = $.trim(String(name)); - if (index) { - if (!this.options.extraParams) { - this.options.extraParams = {}; - } - if (this.options.extraParams[index] !== value) { - this.options.extraParams[index] = value; - this.cacheFlush(); - } - } - - return this; - }; - - /** - * Build the url for a remote request - * If options.queryParamName === false, append query to url instead of using a GET parameter - * @param {string} param The value parameter to pass to the backend - * @returns {string} The finished url with parameters - */ - $.Autocompleter.prototype.makeUrl = function(param) { - var self = this; - var url = this.options.url; - var params = $.extend({}, this.options.extraParams); - - if (this.options.queryParamName === false) { - url += encodeURIComponent(param); - } else { - params[this.options.queryParamName] = param; - } - - return makeUrl(url, params); - }; - - /** - * Parse data received from server - * @param remoteData Data received from remote server - * @returns {array} Parsed data - */ - $.Autocompleter.prototype.parseRemoteData = function(remoteData) { - var remoteDataType; - var data = remoteData; - if (this.options.remoteDataType === 'json') { - remoteDataType = typeof(remoteData); - switch (remoteDataType) { - case 'object': - data = remoteData; - break; - case 'string': - data = $.parseJSON(remoteData); - break; - default: - throw new Error("Unexpected remote data type: " + remoteDataType); - } - return data; - } - return plainTextParser(data, this.options.lineSeparator, this.options.cellSeparator); - }; - - /** - * Default filter for results - * @param {Object} result - * @param {String} filter - * @returns {boolean} Include this result - * @private - */ - $.Autocompleter.prototype.defaultFilter = function(result, filter) { - if (!result.value) { - return false; - } - if (this.options.filterResults) { - var pattern = this.matchStringConverter(filter); - var testValue = this.matchStringConverter(result.value); - if (!this.options.matchCase) { - pattern = pattern.toLowerCase(); - testValue = testValue.toLowerCase(); - } - var patternIndex = testValue.indexOf(pattern); - if (this.options.matchInside) { - return patternIndex > -1; - } else { - return patternIndex === 0; - } - } - return true; - }; - - /** - * Filter result - * @param {Object} result - * @param {String} filter - * @returns {boolean} Include this result - * @private - */ - $.Autocompleter.prototype.filterResult = function(result, filter) { - // No filter - if (this.options.filter === false) { - return true; - } - // Custom filter - if ($.isFunction(this.options.filter)) { - return this.options.filter(result, filter); - } - // Default filter - return this.defaultFilter(result, filter); - }; - - /** - * Filter results - * @param results - * @param filter - */ - $.Autocompleter.prototype.filterResults = function(results, filter) { - var filtered = []; - var i, result; - - for (i = 0; i < results.length; i++) { - result = sanitizeResult(results[i]); - if (this.filterResult(result, filter)) { - filtered.push(result); - } - } - if (this.options.sortResults) { - filtered = this.sortResults(filtered, filter); - } - if (this.options.maxItemsToShow > 0 && this.options.maxItemsToShow < filtered.length) { - filtered.length = this.options.maxItemsToShow; - } - return filtered; - }; - - /** - * Sort results - * @param results - * @param filter - */ - $.Autocompleter.prototype.sortResults = function(results, filter) { - var self = this; - var sortFunction = this.options.sortFunction; - if (!$.isFunction(sortFunction)) { - sortFunction = function(a, b, f) { - return sortValueAlpha(a, b, self.options.matchCase); - }; - } - results.sort(function(a, b) { - return sortFunction(a, b, filter, self.options); - }); - return results; - }; - - /** - * Convert string before matching - * @param s - * @param a - * @param b - */ - $.Autocompleter.prototype.matchStringConverter = function(s, a, b) { - var converter = this.options.matchStringConverter; - if ($.isFunction(converter)) { - s = converter(s, a, b); - } - return s; - }; - - /** - * Convert string before use - * @param {String} s - */ - $.Autocompleter.prototype.beforeUseConverter = function(s) { - s = this.getValue(s); - var converter = this.options.beforeUseConverter; - if ($.isFunction(converter)) { - s = converter(s); - } - return s; - }; - - /** - * Enable finish on blur event - */ - $.Autocompleter.prototype.enableFinishOnBlur = function() { - this.finishOnBlur_ = true; - }; - - /** - * Disable finish on blur event - */ - $.Autocompleter.prototype.disableFinishOnBlur = function() { - this.finishOnBlur_ = false; - }; - - /** - * Create a results item (LI element) from a result - * @param result - */ - $.Autocompleter.prototype.createItemFromResult = function(result) { - var self = this; - var $li = $('<li/>'); - $li.html(this.showResult(result.value, result.data)); - $li.data({value: result.value, data: result.data}) - .click(function() { - self.selectItem($li); - }) - .mousedown(self.disableFinishOnBlur) - .mouseup(self.enableFinishOnBlur) - ; - return $li; - }; - - /** - * Get all items from the results list - * @param result - */ - $.Autocompleter.prototype.getItems = function() { - return $('>ul>li', this.dom.$results); - }; - - /** - * Show all results - * @param results - * @param filter - */ - $.Autocompleter.prototype.showResults = function(results, filter) { - var numResults = results.length; - var self = this; - var $ul = $('<ul></ul>'); - var i, result, $li, autoWidth, first = false, $first = false; - - if (numResults) { - for (i = 0; i < numResults; i++) { - result = results[i]; - $li = this.createItemFromResult(result); - $ul.append($li); - if (first === false) { - first = String(result.value); - $first = $li; - $li.addClass(this.options.firstItemClass); - } - if (i === numResults - 1) { - $li.addClass(this.options.lastItemClass); - } - } - - this.dom.$results.html($ul).show(); - - // Always recalculate position since window size or - // input element location may have changed. - this.position(); - if (this.options.autoWidth) { - autoWidth = this.dom.$elem.outerWidth() - this.dom.$results.outerWidth() + this.dom.$results.width(); - this.dom.$results.css(this.options.autoWidth, autoWidth); - } - this.getItems().hover( - function() { self.focusItem(this); }, - function() { /* void */ } - ); - if (this.autoFill(first, filter) || this.options.selectFirst || (this.options.selectOnly && numResults === 1)) { - this.focusItem($first); - } - this.active_ = true; - } else { - this.hideResults(); - this.active_ = false; - } - }; - - $.Autocompleter.prototype.showResult = function(value, data) { - if ($.isFunction(this.options.showResult)) { - return this.options.showResult(value, data); - } else { - return $('<p></p>').text(value).html(); - } - }; - - $.Autocompleter.prototype.autoFill = function(value, filter) { - var lcValue, lcFilter, valueLength, filterLength; - if (this.options.autoFill && this.lastKeyPressed_ !== 8) { - lcValue = String(value).toLowerCase(); - lcFilter = String(filter).toLowerCase(); - valueLength = value.length; - filterLength = filter.length; - if (lcValue.substr(0, filterLength) === lcFilter) { - var d = this.getDelimiterOffsets(); - var pad = d.start ? ' ' : ''; // if there is a preceding delimiter - this.setValue( pad + value ); - var start = filterLength + d.start + pad.length; - var end = valueLength + d.start + pad.length; - this.selectRange(start, end); - return true; - } - } - return false; - }; - - $.Autocompleter.prototype.focusNext = function() { - this.focusMove(+1); - }; - - $.Autocompleter.prototype.focusPrev = function() { - this.focusMove(-1); - }; - - $.Autocompleter.prototype.focusMove = function(modifier) { - var $items = this.getItems(); - modifier = sanitizeInteger(modifier, 0); - if (modifier) { - for (var i = 0; i < $items.length; i++) { - if ($($items[i]).hasClass(this.selectClass_)) { - this.focusItem(i + modifier); - return; - } - } - } - this.focusItem(0); - }; - - $.Autocompleter.prototype.focusItem = function(item) { - var $item, $items = this.getItems(); - if ($items.length) { - $items.removeClass(this.selectClass_).removeClass(this.options.selectClass); - if (typeof item === 'number') { - if (item < 0) { - item = 0; - } else if (item >= $items.length) { - item = $items.length - 1; - } - $item = $($items[item]); - } else { - $item = $(item); - } - if ($item) { - $item.addClass(this.selectClass_).addClass(this.options.selectClass); - } - } - }; - - $.Autocompleter.prototype.selectCurrent = function() { - var $item = $('li.' + this.selectClass_, this.dom.$results); - if ($item.length === 1) { - this.selectItem($item); - } else { - this.deactivate(false); - } - }; - - $.Autocompleter.prototype.selectItem = function($li) { - var value = $li.data('value'); - var data = $li.data('data'); - var displayValue = this.displayValue(value, data); - var processedDisplayValue = this.beforeUseConverter(displayValue); - this.lastProcessedValue_ = processedDisplayValue; - this.lastSelectedValue_ = processedDisplayValue; - var d = this.getDelimiterOffsets(); - var delimiter = this.options.delimiterChar; - var elem = this.dom.$elem; - var extraCaretPos = 0; - if ( this.options.useDelimiter ) { - // if there is a preceding delimiter, add a space after the delimiter - if ( elem.val().substring(d.start-1, d.start) == delimiter && delimiter != ' ' ) { - displayValue = ' ' + displayValue; - } - // if there is not already a delimiter trailing this value, add it - if ( elem.val().substring(d.end, d.end+1) != delimiter && this.lastKeyPressed_ != this.options.delimiterKeyCode ) { - displayValue = displayValue + delimiter; - } else { - // move the cursor after the existing trailing delimiter - extraCaretPos = 1; - } - } - this.setValue(displayValue); - this.setCaret(d.start + displayValue.length + extraCaretPos); - this.callHook('onItemSelect', { value: value, data: data }); - this.deactivate(true); - elem.focus(); - }; - - $.Autocompleter.prototype.displayValue = function(value, data) { - if ($.isFunction(this.options.displayValue)) { - return this.options.displayValue(value, data); - } - return value; - }; - - $.Autocompleter.prototype.hideResults = function() { - this.dom.$results.hide(); - }; - - $.Autocompleter.prototype.deactivate = function(finish) { - if (this.finishTimeout_) { - clearTimeout(this.finishTimeout_); - } - if (this.keyTimeout_) { - clearTimeout(this.keyTimeout_); - } - if (finish) { - if (this.lastProcessedValue_ !== this.lastSelectedValue_) { - if (this.options.mustMatch) { - this.setValue(''); - } - this.callHook('onNoMatch'); - } - if (this.active_) { - this.callHook('onFinish'); - } - this.lastKeyPressed_ = null; - this.lastProcessedValue_ = null; - this.lastSelectedValue_ = null; - this.active_ = false; - } - this.hideResults(); - }; - - $.Autocompleter.prototype.selectRange = function(start, end) { - var input = this.dom.$elem.get(0); - if (input.setSelectionRange) { - input.focus(); - input.setSelectionRange(start, end); - } else if (input.createTextRange) { - var range = input.createTextRange(); - range.collapse(true); - range.moveEnd('character', end); - range.moveStart('character', start); - range.select(); - } - }; - - /** - * Move caret to position - * @param {Number} pos - */ - $.Autocompleter.prototype.setCaret = function(pos) { - this.selectRange(pos, pos); - }; - - /** - * Get caret position - */ - $.Autocompleter.prototype.getCaret = function() { - var $elem = this.dom.$elem; - var elem = $elem[0]; - var val, selection, range, start, end, stored_range; - if (elem.createTextRange) { // IE - selection = document.selection; - if (elem.tagName.toLowerCase() != 'textarea') { - val = $elem.val(); - range = selection.createRange().duplicate(); - range.moveEnd('character', val.length); - if (range.text === '') { - start = val.length; - } else { - start = val.lastIndexOf(range.text); - } - range = selection.createRange().duplicate(); - range.moveStart('character', -val.length); - end = range.text.length; - } else { - range = selection.createRange(); - stored_range = range.duplicate(); - stored_range.moveToElementText(elem); - stored_range.setEndPoint('EndToEnd', range); - start = stored_range.text.length - range.text.length; - end = start + range.text.length; - } - } else { - start = $elem[0].selectionStart; - end = $elem[0].selectionEnd; - } - return { - start: start, - end: end - }; - }; - - /** - * Set the value that is currently being autocompleted - * @param {String} value - */ - $.Autocompleter.prototype.setValue = function(value) { - if ( this.options.useDelimiter ) { - // set the substring between the current delimiters - var val = this.dom.$elem.val(); - var d = this.getDelimiterOffsets(); - var preVal = val.substring(0, d.start); - var postVal = val.substring(d.end); - value = preVal + value + postVal; - } - this.dom.$elem.val(value); - }; - - /** - * Get the value currently being autocompleted - * @param {String} value - */ - $.Autocompleter.prototype.getValue = function(value) { - if ( this.options.useDelimiter ) { - var d = this.getDelimiterOffsets(); - return value.substring(d.start, d.end).trim(); - } else { - return value; - } - }; - - /** - * Get the offsets of the value currently being autocompleted - */ - $.Autocompleter.prototype.getDelimiterOffsets = function() { - var val = this.dom.$elem.val(); - if ( this.options.useDelimiter ) { - var preCaretVal = val.substring(0, this.getCaret().start); - var start = preCaretVal.lastIndexOf(this.options.delimiterChar) + 1; - var postCaretVal = val.substring(this.getCaret().start); - var end = postCaretVal.indexOf(this.options.delimiterChar); - if ( end == -1 ) end = val.length; - end += this.getCaret().start; - } else { - start = 0; - end = val.length; - } - return { - start: start, - end: end - }; - }; - -})(jQuery); diff --git a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.min.js b/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.min.js deleted file mode 100644 index 7165d7a3d8..0000000000 --- a/awx/lib/site-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net) - * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. - * - * $LastChangedDate: 2007-07-22 01:45:56 +0200 (Son, 22 Jul 2007) $ - * $Rev: 2447 $ - * - * Version 2.1.1 - */ -(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};})((typeof window.jQuery=='undefined' && typeof window.django!='undefined')? django.jQuery : jQuery); \ No newline at end of file diff --git a/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/digraph.dot b/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/digraph.dot deleted file mode 100644 index 85ef0f5d31..0000000000 --- a/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/digraph.dot +++ /dev/null @@ -1,26 +0,0 @@ -{% block digraph %}digraph model_graph { - # Dotfile by Django-Extensions graph_models - # Created: {{ created_at }} - {% if cli_options %}# Cli Options: {{ cli_options }}{% endif %} - - {% block digraph_options %}fontname = "Helvetica" - fontsize = 8 - splines = true{% endblock %} - - node [{% block node_options %} - fontname = "Helvetica" - fontsize = 8 - shape = "plaintext" - {% endblock %}] - - edge [{% block edge_options %} - fontname = "Helvetica" - fontsize = 8 - {% endblock %}] - - # Labels -{% block labels %}{% for graph in graphs %}{% include "django_extensions/graph_models/label.dot" %}{% endfor %}{% endblock %} - - # Relations -{% block relations %}{% for graph in graphs %}{% include "django_extensions/graph_models/relation.dot" %}{% endfor %}{% endblock %} -}{% endblock %} diff --git a/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/label.dot b/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/label.dot deleted file mode 100644 index 91ef18f3f1..0000000000 --- a/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/label.dot +++ /dev/null @@ -1,30 +0,0 @@ -{% load indent_text %}{% if use_subgraph %} subgraph {{ graph.cluster_app_name }} { - label=< - <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"> - <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER"> - <FONT FACE="Helvetica Bold" COLOR="Black" POINT-SIZE="12"> - {{ graph.app_name }} - </FONT> - </TD></TR> - </TABLE> - > - color=olivedrab4 - style="rounded"{% endif %} -{% indentby 2 if use_subgraph %}{% for model in graph.models %} - {{ model.app_name }}_{{ model.name }} [label=< - <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> - <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4"> - <FONT FACE="Helvetica Bold" COLOR="white"> - {{ model.label }}{% if model.abstracts %}<BR/><<FONT FACE="Helvetica Italic">{{ model.abstracts|join:"," }}</FONT>>{% endif %} - </FONT></TD></TR> - {% if not disable_fields %}{% for field in model.fields %} - <TR><TD ALIGN="LEFT" BORDER="0"> - <FONT {% if not field.primary_key and field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica {% if field.abstract %}Italic{% endif %}{% if field.relation or field.primary_key %}Bold{% endif %}">{{ field.label }}</FONT> - </TD><TD ALIGN="LEFT"> - <FONT {% if not field.primary_key and field.blank %}COLOR="#7B7B7B" {% endif %}FACE="Helvetica {% if field.abstract %}Italic{% endif %}{% if field.relation or field.primary_key %}Bold{% endif %}">{{ field.type }}</FONT> - </TD></TR> - {% endfor %}{% endif %} - </TABLE> - >] -{% endfor %}{% endindentby %} -{% if use_subgraph %} }{% endif %} diff --git a/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/relation.dot b/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/relation.dot deleted file mode 100644 index aa351e669a..0000000000 --- a/awx/lib/site-packages/django_extensions/templates/django_extensions/graph_models/relation.dot +++ /dev/null @@ -1,10 +0,0 @@ -{% for model in graph.models %}{% for relation in model.relations %}{% if relation.needs_node %} {{ relation.target_app }}_{{ relation.target }} [label=< - <TABLE BGCOLOR="palegoldenrod" BORDER="0" CELLBORDER="0" CELLSPACING="0"> - <TR><TD COLSPAN="2" CELLPADDING="4" ALIGN="CENTER" BGCOLOR="olivedrab4"> - <FONT FACE="Helvetica Bold" COLOR="white">{{ relation.target }}</FONT> - </TD></TR> - </TABLE> - >]{% endif %} - {{ model.app_name }}_{{ model.name }} -> {{ relation.target_app }}_{{ relation.target }} - [label="{{ relation.label }}"] {{ relation.arrows }}; -{% endfor %}{% endfor %} \ No newline at end of file diff --git a/awx/lib/site-packages/django_extensions/templates/django_extensions/widgets/foreignkey_searchinput.html b/awx/lib/site-packages/django_extensions/templates/django_extensions/widgets/foreignkey_searchinput.html deleted file mode 100644 index bf6e3cc080..0000000000 --- a/awx/lib/site-packages/django_extensions/templates/django_extensions/widgets/foreignkey_searchinput.html +++ /dev/null @@ -1,61 +0,0 @@ -{% load i18n staticfiles %} -<input type="text" id="lookup_{{ name }}" value="{{ label }}" style="display:none;" /> -<a href="{{ related_url }}{{ url }}" class="related-lookup" id="lookup_id_{{ name }}" onclick="return showRelatedObjectLookupPopup(this);"> - <img src="{% static "admin/img/selector-search.gif" %}" width="16" height="16" alt="{% trans "Lookup" %}" /> -</a> -<script type="text/javascript"> -(function($) { - // Show lookup input - $('#lookup_{{ name }}').show(); - function reset() { - $('#id_{{ name }}, #lookup_{{ name }}').val(''); - }; - function lookup(query) { - $.get('{{ search_path }}', { - 'search_fields': '{{ search_fields }}', - 'app_label': '{{ app_label }}', - 'model_name': '{{ model_name }}', - 'object_pk': query - }, function(data) { - $('#lookup_{{ name }}').val(data); - {{ name }}_value = query; - }); - }; - $('#id_{{ name }}').bind('keyup', function(event) { - if ($(this).val()) { - if (event.keyCode == 27) { - reset(); - } else { - lookup($(this).val()); - }; - }; - }); - $('#lookup_{{ name }}').bind('keyup', function(event) { - if ($(this).val()) { - if (event.keyCode == 27) { - reset(); - } - } - }); - $('#lookup_{{ name }}').autocomplete('{{ search_path }}', { - extraParams: { - 'search_fields': '{{ search_fields }}', - 'app_label': '{{ app_label }}', - 'model_name': '{{ model_name }}' - }, - onItemSelect: function(item) { - $('#id_{{ name }}').val(item.data[0]); - } - }); - var {{ name }}_value = $('#id_{{ name }}').val(); - function check() { - {{ name }}_check = $('#id_{{ name }}').val(); - if ({{ name }}_check) { - if ({{ name }}_check != {{ name }}_value) { - lookup({{ name }}_check); - } - } - }; - timeout = window.setInterval(check, 300); -})((typeof window.jQuery == 'undefined' && typeof window.django != 'undefined')? django.jQuery : jQuery); -</script> diff --git a/awx/lib/site-packages/django_extensions/templatetags/__init__.py b/awx/lib/site-packages/django_extensions/templatetags/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/templatetags/highlighting.py b/awx/lib/site-packages/django_extensions/templatetags/highlighting.py deleted file mode 100644 index 78f6dbcfab..0000000000 --- a/awx/lib/site-packages/django_extensions/templatetags/highlighting.py +++ /dev/null @@ -1,91 +0,0 @@ -""" -Similar to syntax_color.py but this is intended more for being able to -copy+paste actual code into your Django templates without needing to -escape or anything crazy. - -http://lobstertech.com/2008/aug/30/django_syntax_highlight_template_tag/ - -Example: - - {% load highlighting %} - - <style> - @import url("http://lobstertech.com/media/css/highlight.css"); - .highlight { background: #f8f8f8; } - .highlight { font-size: 11px; margin: 1em; border: 1px solid #ccc; - border-left: 3px solid #F90; padding: 0; } - .highlight pre { padding: 1em; overflow: auto; line-height: 120%; margin: 0; } - .predesc { margin: 1.5em 1.5em -2.5em 1em; text-align: right; - font: bold 12px Tahoma, Arial, sans-serif; - letter-spacing: 1px; color: #333; } - </style> - - <h2>check out this code</h2> - - {% highlight 'python' 'Excerpt: blah.py' %} - def need_food(self): - print("Love is <colder> than &death&") - {% endhighlight %} - -""" - -from pygments import highlight as pyghighlight -from pygments.lexers import get_lexer_by_name -from pygments.formatters import HtmlFormatter -from django import template -from django.template import Template, Context, Node, Variable, TemplateSyntaxError -from django.template.defaultfilters import stringfilter -from django.utils.safestring import mark_safe - -register = template.Library() - - -@register.filter -@stringfilter -def parse_template(value): - return mark_safe(Template(value).render(Context())) -parse_template.is_safe = True - - -class CodeNode(Node): - def __init__(self, language, nodelist, name=''): - self.language = Variable(language) - self.nodelist = nodelist - if name: - self.name = Variable(name) - else: - self.name = None - - def render(self, context): - code = self.nodelist.render(context).strip() - lexer = get_lexer_by_name(self.language.resolve(context)) - formatter = HtmlFormatter(linenos=False) - html = "" - if self.name: - name = self.name.resolve(context) - html = '<div class="predesc"><span>%s</span></div>' % (name) - return html + pyghighlight(code, lexer, formatter) - - -@register.tag -def highlight(parser, token): - """ - Allows you to put a highlighted source code <pre> block in your code. - This takes two arguments, the language and a little explaination message - that will be generated before the code. The second argument is optional. - - Your code will be fed through pygments so you can use any language it - supports. - - {% load highlighting %} - {% highlight 'python' 'Excerpt: blah.py' %} - def need_food(self): - print("Love is colder than death") - {% endhighlight %} - """ - nodelist = parser.parse(('endhighlight',)) - parser.delete_first_token() - bits = token.split_contents()[1:] - if len(bits) < 1: - raise TemplateSyntaxError("'highlight' statement requires an argument") - return CodeNode(bits[0], nodelist, *bits[1:]) diff --git a/awx/lib/site-packages/django_extensions/templatetags/indent_text.py b/awx/lib/site-packages/django_extensions/templatetags/indent_text.py deleted file mode 100644 index 008542380b..0000000000 --- a/awx/lib/site-packages/django_extensions/templatetags/indent_text.py +++ /dev/null @@ -1,55 +0,0 @@ -from django import template - -register = template.Library() - - -class IndentByNode(template.Node): - def __init__(self, nodelist, indent_level, if_statement): - self.nodelist = nodelist - self.indent_level = template.Variable(indent_level) - if if_statement: - self.if_statement = template.Variable(if_statement) - else: - self.if_statement = None - - def render(self, context): - indent_level = self.indent_level.resolve(context) - if self.if_statement: - try: - if_statement = bool(self.if_statement.resolve(context)) - except template.VariableDoesNotExist: - if_statement = False - else: - if_statement = True - output = self.nodelist.render(context) - if if_statement: - indent = " " * indent_level - output = indent + indent.join(output.splitlines(True)) - return output - - -def indentby(parser, token): - """ - Adds indentation to text between the tags by the given indentation level. - - {% indentby <indent_level> [if <statement>] %} - ... - {% endindentby %} - - Arguments: - indent_level - Number of spaces to indent text with. - statement - Only apply indent_level if the boolean statement evalutates to True. - """ - args = token.split_contents() - largs = len(args) - if largs not in (2, 4): - raise template.TemplateSyntaxError("%r tag requires 1 or 3 arguments") - indent_level = args[1] - if_statement = None - if largs == 4: - if_statement = args[3] - nodelist = parser.parse(('endindentby', )) - parser.delete_first_token() - return IndentByNode(nodelist, indent_level, if_statement) - -indentby = register.tag(indentby) diff --git a/awx/lib/site-packages/django_extensions/templatetags/syntax_color.py b/awx/lib/site-packages/django_extensions/templatetags/syntax_color.py deleted file mode 100644 index 4c4c23dca3..0000000000 --- a/awx/lib/site-packages/django_extensions/templatetags/syntax_color.py +++ /dev/null @@ -1,97 +0,0 @@ -r""" -Template filter for rendering a string with syntax highlighting. -It relies on Pygments to accomplish this. - -Some standard usage examples (from within Django templates). -Coloring a string with the Python lexer: - - {% load syntax_color %} - {{ code_string|colorize:"python" }} - -You may use any lexer in Pygments. The complete list of which -can be found [on the Pygments website][1]. - -[1]: http://pygments.org/docs/lexers/ - -You may also have Pygments attempt to guess the correct lexer for -a particular string. However, if may not be able to choose a lexer, -in which case it will simply return the string unmodified. This is -less efficient compared to specifying the lexer to use. - - {{ code_string|colorize }} - -You may also render the syntax highlighed text with line numbers. - - {% load syntax_color %} - {{ some_code|colorize_table:"html+django" }} - {{ let_pygments_pick_for_this_code|colorize_table }} - -Please note that before you can load the ``syntax_color`` template filters -you will need to add the ``django_extensions.utils`` application to the -``INSTALLED_APPS``setting in your project's ``settings.py`` file. -""" - -__author__ = 'Will Larson <lethain@gmail.com>' - - -from django import template -from django.template.defaultfilters import stringfilter -from django.utils.safestring import mark_safe -from django.core.exceptions import ImproperlyConfigured - -try: - from pygments import highlight - from pygments.formatters import HtmlFormatter - from pygments.lexers import get_lexer_by_name, guess_lexer, ClassNotFound -except ImportError: - raise ImproperlyConfigured( - "Please install 'pygments' library to use syntax_color.") - -register = template.Library() - - -@register.simple_tag -def pygments_css(): - return HtmlFormatter().get_style_defs('.highlight') - - -def generate_pygments_css(path=None): - if path is None: - import os - path = os.path.join(os.getcwd(), 'pygments.css') - f = open(path, 'w') - f.write(pygments_css()) - f.close() - - -def get_lexer(value, arg): - if arg is None: - return guess_lexer(value) - return get_lexer_by_name(arg) - - -@register.filter(name='colorize') -@stringfilter -def colorize(value, arg=None): - try: - return mark_safe(highlight(value, get_lexer(value, arg), HtmlFormatter())) - except ClassNotFound: - return value - - -@register.filter(name='colorize_table') -@stringfilter -def colorize_table(value, arg=None): - try: - return mark_safe(highlight(value, get_lexer(value, arg), HtmlFormatter(linenos='table'))) - except ClassNotFound: - return value - - -@register.filter(name='colorize_noclasses') -@stringfilter -def colorize_noclasses(value, arg=None): - try: - return mark_safe(highlight(value, get_lexer(value, arg), HtmlFormatter(noclasses=True))) - except ClassNotFound: - return value diff --git a/awx/lib/site-packages/django_extensions/templatetags/truncate_letters.py b/awx/lib/site-packages/django_extensions/templatetags/truncate_letters.py deleted file mode 100644 index b77a6b1fc8..0000000000 --- a/awx/lib/site-packages/django_extensions/templatetags/truncate_letters.py +++ /dev/null @@ -1,28 +0,0 @@ -import django -from django import template -from django.template.defaultfilters import stringfilter - -register = template.Library() - - -def truncateletters(value, arg): - """ - Truncates a string after a certain number of letters - - Argument: Number of letters to truncate after - """ - from django_extensions.utils.text import truncate_letters - try: - length = int(arg) - except ValueError: # invalid literal for int() - return value # Fail silently - return truncate_letters(value, length) - -if django.get_version() >= "1.4": - truncateletters = stringfilter(truncateletters) - register.filter(truncateletters, is_safe=True) -else: - truncateletters.is_safe = True - truncateletters = stringfilter(truncateletters) - register.filter(truncateletters) - diff --git a/awx/lib/site-packages/django_extensions/templatetags/widont.py b/awx/lib/site-packages/django_extensions/templatetags/widont.py deleted file mode 100644 index a2d0af30f4..0000000000 --- a/awx/lib/site-packages/django_extensions/templatetags/widont.py +++ /dev/null @@ -1,65 +0,0 @@ -import re -from django.template import Library -try: - from django.utils.encoding import force_text -except ImportError: - # Django 1.4 compatibility - from django.utils.encoding import force_unicode as force_text - -register = Library() -re_widont = re.compile(r'\s+(\S+\s*)$') -re_widont_html = re.compile(r'([^<>\s])\s+([^<>\s]+\s*)(</?(?:address|blockquote|br|dd|div|dt|fieldset|form|h[1-6]|li|noscript|p|td|th)[^>]*>|$)', re.IGNORECASE) - - -def widont(value, count=1): - """ - Adds an HTML non-breaking space between the final two words of the string to - avoid "widowed" words. - - Examples: - - >>> print(widont('Test me out')) - Test me out - - >>> widont('It works with trailing spaces too ') - u'It works with trailing spaces too ' - - >>> print(widont('NoEffect')) - NoEffect - """ - def replace(matchobj): - return force_text(' %s' % matchobj.group(1)) - for i in range(count): - value = re_widont.sub(replace, force_text(value)) - return value - - -def widont_html(value): - """ - Adds an HTML non-breaking space between the final two words at the end of - (and in sentences just outside of) block level tags to avoid "widowed" - words. - - Examples: - - >>> print(widont_html('<h2>Here is a simple example </h2> <p>Single</p>')) - <h2>Here is a simple example </h2> <p>Single</p> - - >>> print(widont_html('<p>test me<br /> out</p><h2>Ok?</h2>Not in a p<p title="test me">and this</p>')) - <p>test me<br /> out</p><h2>Ok?</h2>Not in a p<p title="test me">and this</p> - - >>> print(widont_html('leading text <p>test me out</p> trailing text')) - leading text <p>test me out</p> trailing text - """ - def replace(matchobj): - return force_text('%s %s%s' % matchobj.groups()) - return re_widont_html.sub(replace, force_text(value)) - -register.filter(widont) -register.filter(widont_html) - -if __name__ == "__main__": - def _test(): - import doctest - doctest.testmod() - _test() diff --git a/awx/lib/site-packages/django_extensions/tests/__init__.py b/awx/lib/site-packages/django_extensions/tests/__init__.py deleted file mode 100644 index 5e97235156..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -from django.db import models # NOQA -from django_extensions.tests.test_dumpscript import DumpScriptTests -from django_extensions.tests.utils import TruncateLetterTests -from django_extensions.tests.json_field import JsonFieldTest -from django_extensions.tests.uuid_field import UUIDFieldTest -from django_extensions.tests.fields import AutoSlugFieldTest -from django_extensions.tests.management_command import CommandTest, ShowTemplateTagsTests -from django_extensions.tests.test_templatetags import TemplateTagsTests - -__test_classes__ = [ - DumpScriptTests, JsonFieldTest, UUIDFieldTest, AutoSlugFieldTest, CommandTest, - ShowTemplateTagsTests, TruncateLetterTests, TemplateTagsTests -] - -try: - from django_extensions.tests.encrypted_fields import EncryptedFieldsTestCase - __test_classes__.append(EncryptedFieldsTestCase) -except ImportError: - pass diff --git a/awx/lib/site-packages/django_extensions/tests/encrypted_fields.py b/awx/lib/site-packages/django_extensions/tests/encrypted_fields.py deleted file mode 100644 index dee9fd3b57..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/encrypted_fields.py +++ /dev/null @@ -1,258 +0,0 @@ -from contextlib import contextmanager -import functools - -from django.conf import settings -from django.db import connection, models -from django.db.models import loading - -from django_extensions.tests.models import Secret -from django_extensions.tests.fields import FieldTestCase - -# Only perform encrypted fields tests if keyczar is present. Resolves -# http://github.com/django-extensions/django-extensions/issues/#issue/17 -try: - from django_extensions.db.fields.encrypted import EncryptedTextField, EncryptedCharField # NOQA - from keyczar import keyczar, keyczart, keyinfo # NOQA - keyczar_active = True -except ImportError: - keyczar_active = False - - -def run_if_active(func): - "Method decorator that only runs a test if KeyCzar is available." - - @functools.wraps(func) - def inner(self): - if not keyczar_active: - return - return func(self) - return inner - - -# Locations of both private and public keys. -KEY_LOCS = getattr(settings, 'ENCRYPTED_FIELD_KEYS_DIR', {}) - - -@contextmanager -def keys(purpose, mode=None): - """ - A context manager that sets up the correct KeyCzar environment for a test. - - Arguments: - purpose: Either keyczar.keyinfo.DECRYPT_AND_ENCRYPT or - keyczar.keyinfo.ENCRYPT. - mode: If truthy, settings.ENCRYPTED_FIELD_MODE will be set to (and then - reverted from) this value. If falsy, settings.ENCRYPTED_FIELD_MODE - will not be changed. Optional. Default: None. - - Yields: - A Keyczar subclass for the stated purpose. This will be keyczar.Crypter - for DECRYPT_AND_ENCRYPT or keyczar.Encrypter for ENCRYPT. In addition, - settings.ENCRYPTED_FIELD_KEYS_DIR will be set correctly, and then - reverted when the manager exits. - """ - # Store the original settings so we can restore when the manager exits. - orig_setting_dir = getattr(settings, 'ENCRYPTED_FIELD_KEYS_DIR', None) - orig_setting_mode = getattr(settings, 'ENCRYPTED_FIELD_MODE', None) - try: - if mode: - settings.ENCRYPTED_FIELD_MODE = mode - - if purpose == keyinfo.DECRYPT_AND_ENCRYPT: - settings.ENCRYPTED_FIELD_KEYS_DIR = KEY_LOCS['DECRYPT_AND_ENCRYPT'] - yield keyczar.Crypter.Read(settings.ENCRYPTED_FIELD_KEYS_DIR) - else: - settings.ENCRYPTED_FIELD_KEYS_DIR = KEY_LOCS['ENCRYPT'] - yield keyczar.Encrypter.Read(settings.ENCRYPTED_FIELD_KEYS_DIR) - - except: - raise # Reraise any exceptions. - - finally: - # Restore settings. - settings.ENCRYPTED_FIELD_KEYS_DIR = orig_setting_dir - if mode: - if orig_setting_mode: - settings.ENCRYPTED_FIELD_MODE = orig_setting_mode - else: - del settings.ENCRYPTED_FIELD_MODE - - -@contextmanager -def secret_model(): - """ - A context manager that yields a Secret model defined at runtime. - - All EncryptedField init logic occurs at model class definition time, not at - object instantiation time. This means that in order to test different keys - and modes, we must generate a new class definition at runtime, after - establishing the correct KeyCzar settings. This context manager handles - that process. - - See http://dynamic-models.readthedocs.org/en/latest/ and - https://docs.djangoproject.com/en/dev/topics/db/models/ - #differences-between-proxy-inheritance-and-unmanaged-models - """ - - # Store Django's cached model, if present, so we can restore when the - # manager exits. - orig_model = None - try: - orig_model = loading.cache.app_models['tests']['secret'] - del loading.cache.app_models['tests']['secret'] - except KeyError: - pass - - try: - # Create a new class that shadows tests.models.Secret. - attrs = { - 'name': EncryptedCharField("Name", max_length=Secret._meta.get_field('name').max_length), - 'text': EncryptedTextField("Text"), - '__module__': 'django_extensions.tests.models', - 'Meta': type('Meta', (object, ), { - 'managed': False, - 'db_table': Secret._meta.db_table - }) - } - yield type('Secret', (models.Model, ), attrs) - - except: - raise # Reraise any exceptions. - - finally: - # Restore Django's model cache. - try: - loading.cache.app_models['tests']['secret'] = orig_model - except KeyError: - pass - - -class EncryptedFieldsTestCase(FieldTestCase): - @run_if_active - def testCharFieldCreate(self): - """ - Uses a private key to encrypt data on model creation. - Verifies the data is encrypted in the database and can be decrypted. - """ - with keys(keyinfo.DECRYPT_AND_ENCRYPT) as crypt: - with secret_model() as model: - test_val = "Test Secret" - secret = model.objects.create(name=test_val) - - cursor = connection.cursor() - query = "SELECT name FROM %s WHERE id = %d" % (model._meta.db_table, secret.id) - cursor.execute(query) - db_val, = cursor.fetchone() - decrypted_val = crypt.Decrypt(db_val[len(EncryptedCharField.prefix):]) - self.assertEqual(test_val, decrypted_val) - - @run_if_active - def testCharFieldRead(self): - """ - Uses a private key to encrypt data on model creation. - Verifies the data is decrypted when reading the value back from the - model. - """ - with keys(keyinfo.DECRYPT_AND_ENCRYPT): - with secret_model() as model: - test_val = "Test Secret" - secret = model.objects.create(name=test_val) - retrieved_secret = model.objects.get(id=secret.id) - self.assertEqual(test_val, retrieved_secret.name) - - @run_if_active - def testTextFieldCreate(self): - """ - Uses a private key to encrypt data on model creation. - Verifies the data is encrypted in the database and can be decrypted. - """ - with keys(keyinfo.DECRYPT_AND_ENCRYPT) as crypt: - with secret_model() as model: - test_val = "Test Secret" - secret = model.objects.create(text=test_val) - cursor = connection.cursor() - query = "SELECT text FROM %s WHERE id = %d" % (model._meta.db_table, secret.id) - cursor.execute(query) - db_val, = cursor.fetchone() - decrypted_val = crypt.Decrypt(db_val[len(EncryptedCharField.prefix):]) - self.assertEqual(test_val, decrypted_val) - - @run_if_active - def testTextFieldRead(self): - """ - Uses a private key to encrypt data on model creation. - Verifies the data is decrypted when reading the value back from the - model. - """ - with keys(keyinfo.DECRYPT_AND_ENCRYPT): - with secret_model() as model: - test_val = "Test Secret" - secret = model.objects.create(text=test_val) - retrieved_secret = model.objects.get(id=secret.id) - self.assertEqual(test_val, retrieved_secret.text) - - @run_if_active - def testCannotDecrypt(self): - """ - Uses a public key to encrypt data on model creation. - Verifies that the data cannot be decrypted using the same key. - """ - with keys(keyinfo.ENCRYPT, mode=keyinfo.ENCRYPT.name): - with secret_model() as model: - test_val = "Test Secret" - secret = model.objects.create(name=test_val) - retrieved_secret = model.objects.get(id=secret.id) - self.assertNotEqual(test_val, retrieved_secret.name) - self.assertTrue(retrieved_secret.name.startswith(EncryptedCharField.prefix)) - - @run_if_active - def testUnacceptablePurpose(self): - """ - Tries to create an encrypted field with a mode mismatch. - A purpose of "DECRYPT_AND_ENCRYPT" cannot be used with a public key, - since public keys cannot be used for decryption. This should raise an - exception. - """ - with self.assertRaises(keyczar.errors.KeyczarError): - with keys(keyinfo.ENCRYPT): - with secret_model(): - # A KeyCzar exception should get raised during class - # definition time, so any code in here would never get run. - pass - - @run_if_active - def testDecryptionForbidden(self): - """ - Uses a private key to encrypt data, but decryption is not allowed. - ENCRYPTED_FIELD_MODE is explicitly set to ENCRYPT, meaning data should - not be decrypted, even though the key would allow for it. - """ - with keys(keyinfo.DECRYPT_AND_ENCRYPT, mode=keyinfo.ENCRYPT.name): - with secret_model() as model: - test_val = "Test Secret" - secret = model.objects.create(name=test_val) - retrieved_secret = model.objects.get(id=secret.id) - self.assertNotEqual(test_val, retrieved_secret.name) - self.assertTrue(retrieved_secret.name.startswith(EncryptedCharField.prefix)) - - @run_if_active - def testEncryptPublicDecryptPrivate(self): - """ - Uses a public key to encrypt, and a private key to decrypt data. - """ - test_val = "Test Secret" - - # First, encrypt data with public key and save to db. - with keys(keyinfo.ENCRYPT, mode=keyinfo.ENCRYPT.name): - with secret_model() as model: - secret = model.objects.create(name=test_val) - enc_retrieved_secret = model.objects.get(id=secret.id) - self.assertNotEqual(test_val, enc_retrieved_secret.name) - self.assertTrue(enc_retrieved_secret.name.startswith(EncryptedCharField.prefix)) - - # Next, retrieve data from db, and decrypt with private key. - with keys(keyinfo.DECRYPT_AND_ENCRYPT): - with secret_model() as model: - retrieved_secret = model.objects.get(id=secret.id) - self.assertEqual(test_val, retrieved_secret.name) - diff --git a/awx/lib/site-packages/django_extensions/tests/fields.py b/awx/lib/site-packages/django_extensions/tests/fields.py deleted file mode 100644 index ab35067259..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/fields.py +++ /dev/null @@ -1,121 +0,0 @@ -from django.conf import settings -from django.core.management import call_command -from django.db.models import loading -from django.db import models -from django.utils import unittest - -from django_extensions.db.fields import AutoSlugField - - -class SluggedTestModel(models.Model): - title = models.CharField(max_length=42) - slug = AutoSlugField(populate_from='title') - - -class ChildSluggedTestModel(SluggedTestModel): - pass - - -class FieldTestCase(unittest.TestCase): - def setUp(self): - self.old_installed_apps = settings.INSTALLED_APPS - settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) - settings.INSTALLED_APPS.append('django_extensions.tests') - loading.cache.loaded = False - - # Don't migrate if south is installed - migrate = 'south' not in settings.INSTALLED_APPS - call_command('syncdb', verbosity=0, migrate=migrate) - - def tearDown(self): - settings.INSTALLED_APPS = self.old_installed_apps - - -class AutoSlugFieldTest(FieldTestCase): - def tearDown(self): - super(AutoSlugFieldTest, self).tearDown() - - SluggedTestModel.objects.all().delete() - - def testAutoCreateSlug(self): - m = SluggedTestModel(title='foo') - m.save() - self.assertEqual(m.slug, 'foo') - - def testAutoCreateNextSlug(self): - m = SluggedTestModel(title='foo') - m.save() - - m = SluggedTestModel(title='foo') - m.save() - self.assertEqual(m.slug, 'foo-2') - - def testAutoCreateSlugWithNumber(self): - m = SluggedTestModel(title='foo 2012') - m.save() - self.assertEqual(m.slug, 'foo-2012') - - def testAutoUpdateSlugWithNumber(self): - m = SluggedTestModel(title='foo 2012') - m.save() - m.save() - self.assertEqual(m.slug, 'foo-2012') - - def testUpdateSlug(self): - m = SluggedTestModel(title='foo') - m.save() - self.assertEqual(m.slug, 'foo') - - # update m instance without using `save' - SluggedTestModel.objects.filter(pk=m.pk).update(slug='foo-2012') - # update m instance with new data from the db - m = SluggedTestModel.objects.get(pk=m.pk) - self.assertEqual(m.slug, 'foo-2012') - - m.save() - self.assertEqual(m.title, 'foo') - self.assertEqual(m.slug, 'foo-2012') - - # Check slug is not overwrite - m.title = 'bar' - m.save() - self.assertEqual(m.title, 'bar') - self.assertEqual(m.slug, 'foo-2012') - - def testSimpleSlugSource(self): - m = SluggedTestModel(title='-foo') - m.save() - self.assertEqual(m.slug, 'foo') - - n = SluggedTestModel(title='-foo') - n.save() - self.assertEqual(n.slug, 'foo-2') - - n.save() - self.assertEqual(n.slug, 'foo-2') - - def testEmptySlugSource(self): - # regression test - - m = SluggedTestModel(title='') - m.save() - self.assertEqual(m.slug, '-2') - - n = SluggedTestModel(title='') - n.save() - self.assertEqual(n.slug, '-3') - - n.save() - self.assertEqual(n.slug, '-3') - - def testInheritanceCreatesNextSlug(self): - m = SluggedTestModel(title='foo') - m.save() - - n = ChildSluggedTestModel(title='foo') - n.save() - self.assertEqual(n.slug, 'foo-2') - - o = SluggedTestModel(title='foo') - o.save() - self.assertEqual(o.slug, 'foo-3') diff --git a/awx/lib/site-packages/django_extensions/tests/json_field.py b/awx/lib/site-packages/django_extensions/tests/json_field.py deleted file mode 100644 index 73221a129c..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/json_field.py +++ /dev/null @@ -1,24 +0,0 @@ -from django.db import models - -from django_extensions.db.fields.json import JSONField -from django_extensions.tests.fields import FieldTestCase - - -class TestModel(models.Model): - a = models.IntegerField() - j_field = JSONField() - - -class JsonFieldTest(FieldTestCase): - def testCharFieldCreate(self): - j = TestModel.objects.create(a=6, j_field=dict(foo='bar')) - self.assertEqual(j.a, 6) - - def testDefault(self): - j = TestModel.objects.create(a=1) - self.assertEqual(j.j_field, {}) - - def testEmptyList(self): - j = TestModel.objects.create(a=6, j_field=[]) - self.assertTrue(isinstance(j.j_field, list)) - self.assertEqual(j.j_field, []) diff --git a/awx/lib/site-packages/django_extensions/tests/management/__init__.py b/awx/lib/site-packages/django_extensions/tests/management/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/tests/management/commands/__init__.py b/awx/lib/site-packages/django_extensions/tests/management/commands/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/tests/management/commands/error_raising_command.py b/awx/lib/site-packages/django_extensions/tests/management/commands/error_raising_command.py deleted file mode 100644 index 3bc646cf53..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/management/commands/error_raising_command.py +++ /dev/null @@ -1,10 +0,0 @@ - -from django_extensions.management.base import LoggingBaseCommand - - -class Command(LoggingBaseCommand): - help = 'Test error' - - def handle(self, *args, **options): - raise Exception("Test Error") - diff --git a/awx/lib/site-packages/django_extensions/tests/management_command.py b/awx/lib/site-packages/django_extensions/tests/management_command.py deleted file mode 100644 index 86c6d38197..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/management_command.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -import logging - -try: - from cStringIO import StringIO # NOQA -except ImportError: - from io import StringIO # NOQA - -try: - import importlib # NOQA -except ImportError: - from django.utils import importlib # NOQA - -from django.core.management import call_command -from django.test import TestCase - - -class MockLoggingHandler(logging.Handler): - """ Mock logging handler to check for expected logs. """ - - def __init__(self, *args, **kwargs): - self.reset() - logging.Handler.__init__(self, *args, **kwargs) - - def emit(self, record): - self.messages[record.levelname.lower()].append(record.getMessage()) - - def reset(self): - self.messages = { - 'debug': [], - 'info': [], - 'warning': [], - 'error': [], - 'critical': [], - } - - -class CommandTest(TestCase): - def test_error_logging(self): - # Ensure command errors are properly logged and reraised - from django_extensions.management.base import logger - logger.addHandler(MockLoggingHandler()) - module_path = "django_extensions.tests.management.commands.error_raising_command" - module = importlib.import_module(module_path) - error_raising_command = module.Command() - self.assertRaises(Exception, error_raising_command.execute) - handler = logger.handlers[0] - self.assertEqual(len(handler.messages['error']), 1) - - -class ShowTemplateTagsTests(TestCase): - def test_some_output(self): - out = StringIO() - call_command('show_templatetags', stdout=out) - output = out.getvalue() - # Once django_extension is installed during tests it should appear with - # its templatetags - self.assertIn('django_extensions', output) - # let's check at least one - self.assertIn('truncate_letters', output) diff --git a/awx/lib/site-packages/django_extensions/tests/models.py b/awx/lib/site-packages/django_extensions/tests/models.py deleted file mode 100644 index b3a0aadbd1..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/models.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.db import models - - -class Secret(models.Model): - name = models.CharField(blank=True, max_length=255, null=True) - text = models.TextField(blank=True, null=True) - - -class Name(models.Model): - name = models.CharField(max_length=50) - - -class Note(models.Model): - note = models.TextField() - - -class Person(models.Model): - name = models.ForeignKey(Name) - age = models.PositiveIntegerField() - children = models.ManyToManyField('self') - notes = models.ManyToManyField(Note) diff --git a/awx/lib/site-packages/django_extensions/tests/test_dumpscript.py b/awx/lib/site-packages/django_extensions/tests/test_dumpscript.py deleted file mode 100644 index f528147aa6..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/test_dumpscript.py +++ /dev/null @@ -1,86 +0,0 @@ -import sys -import six - -if sys.version_info[:2] >= (2, 6): - import ast as compiler # NOQA -else: - import compiler # NOQA - -from django.core.management import call_command - -from django_extensions.tests.models import Name, Note, Person -from django_extensions.tests.fields import FieldTestCase - - -class DumpScriptTests(FieldTestCase): - def setUp(self): - super(DumpScriptTests, self).setUp() - - self.real_stdout = sys.stdout - self.real_stderr = sys.stderr - sys.stdout = six.StringIO() - sys.stderr = six.StringIO() - - def tearDown(self): - super(DumpScriptTests, self).tearDown() - - sys.stdout = self.real_stdout - sys.stderr = self.real_stderr - - def test_runs(self): - # lame test...does it run? - n = Name(name='Gabriel') - n.save() - call_command('dumpscript', 'tests') - self.assertTrue('Gabriel' in sys.stdout.getvalue()) - - #---------------------------------------------------------------------- - def test_replaced_stdout(self): - # check if stdout can be replaced - sys.stdout = six.StringIO() - n = Name(name='Mike') - n.save() - tmp_out = six.StringIO() - call_command('dumpscript', 'tests', stdout=tmp_out) - self.assertTrue('Mike' in tmp_out.getvalue()) # script should go to tmp_out - self.assertEqual(0, len(sys.stdout.getvalue())) # there should not be any output to sys.stdout - tmp_out.close() - - #---------------------------------------------------------------------- - def test_replaced_stderr(self): - # check if stderr can be replaced, without changing stdout - n = Name(name='Fred') - n.save() - tmp_err = six.StringIO() - sys.stderr = six.StringIO() - call_command('dumpscript', 'tests', stderr=tmp_err) - self.assertTrue('Fred' in sys.stdout.getvalue()) # script should still go to stdout - self.assertTrue('Name' in tmp_err.getvalue()) # error output should go to tmp_err - self.assertEqual(0, len(sys.stderr.getvalue())) # there should not be any output to sys.stderr - tmp_err.close() - - #---------------------------------------------------------------------- - def test_valid_syntax(self): - n1 = Name(name='John') - n1.save() - p1 = Person(name=n1, age=40) - p1.save() - n2 = Name(name='Jane') - n2.save() - p2 = Person(name=n2, age=18) - p2.save() - p2.children.add(p1) - note1 = Note(note="This is the first note.") - note1.save() - note2 = Note(note="This is the second note.") - note2.save() - p2.notes.add(note1, note2) - tmp_out = six.StringIO() - call_command('dumpscript', 'tests', stdout=tmp_out) - ast_syntax_tree = compiler.parse(tmp_out.getvalue()) - if hasattr(ast_syntax_tree, 'body'): - self.assertTrue(len(ast_syntax_tree.body) > 1) - else: - self.assertTrue(len(ast_syntax_tree.asList()) > 1) - tmp_out.close() - diff --git a/awx/lib/site-packages/django_extensions/tests/test_templatetags.py b/awx/lib/site-packages/django_extensions/tests/test_templatetags.py deleted file mode 100644 index db69fa0ac9..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/test_templatetags.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.test import TestCase - -from django_extensions.templatetags.widont import widont, widont_html - - -class TemplateTagsTests(TestCase): - def test_widont(self): - widont('Test Value') - widont(u'Test Value') - - def test_widont_html(self): - widont_html('Test Value') - widont_html(u'Test Value') diff --git a/awx/lib/site-packages/django_extensions/tests/urls.py b/awx/lib/site-packages/django_extensions/tests/urls.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/tests/utils.py b/awx/lib/site-packages/django_extensions/tests/utils.py deleted file mode 100644 index 23935b66e0..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/utils.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -import sys -import six - -from django.test import TestCase -from django.utils.unittest import skipIf - -from django_extensions.utils.text import truncate_letters -try: - import uuid - assert uuid -except ImportError: - from django_extensions.utils import uuid - - -class TruncateLetterTests(TestCase): - def test_truncate_more_than_text_length(self): - self.assertEqual(six.u("hello tests"), truncate_letters("hello tests", 100)) - - def test_truncate_text(self): - self.assertEqual(six.u("hello..."), truncate_letters("hello tests", 5)) - - def test_truncate_with_range(self): - for i in range(10, -1, -1): - self.assertEqual( - six.u('hello tests'[:i]) + '...', - truncate_letters("hello tests", i) - ) - - def test_with_non_ascii_characters(self): - self.assertEqual( - six.u('\u5ce0 (\u3068\u3046\u3052 t\u014dg...'), - truncate_letters("å³  (ã¨ã†ã’ tÅge - mountain pass)", 10) - ) - - -class UUIDTests(TestCase): - @skipIf(sys.version_info >= (2, 5, 0), 'uuid already in stdlib') - def test_uuid3(self): - # make a UUID using an MD5 hash of a namespace UUID and a name - self.assertEqual( - uuid.UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e'), - uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') - ) - - @skipIf(sys.version_info >= (2, 5, 0), 'uuid already in stdlib') - def test_uuid5(self): - # make a UUID using a SHA-1 hash of a namespace UUID and a name - self.assertEqual( - uuid.UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d'), - uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') - ) - - @skipIf(sys.version_info >= (2, 5, 0), 'uuid already in stdlib') - def test_uuid_str(self): - # make a UUID from a string of hex digits (braces and hyphens ignored) - x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') - # convert a UUID to a string of hex digits in standard form - self.assertEqual('00010203-0405-0607-0809-0a0b0c0d0e0f', str(x)) - - @skipIf(sys.version_info >= (2, 5, 0), 'uuid already in stdlib') - def test_uuid_bytes(self): - # make a UUID from a string of hex digits (braces and hyphens ignored) - x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') - # get the raw 16 bytes of the UUID - self.assertEqual( - '\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f', - x.bytes - ) - - @skipIf(sys.version_info >= (2, 5, 0), 'uuid already in stdlib') - def test_make_uuid_from_byte_string(self): - self.assertEqual( - uuid.UUID(bytes='\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f'), - uuid.UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') - ) diff --git a/awx/lib/site-packages/django_extensions/tests/uuid_field.py b/awx/lib/site-packages/django_extensions/tests/uuid_field.py deleted file mode 100644 index 72c793ba80..0000000000 --- a/awx/lib/site-packages/django_extensions/tests/uuid_field.py +++ /dev/null @@ -1,46 +0,0 @@ -import six - -from django.db import models - -from django_extensions.db.fields import UUIDField -from django_extensions.tests.fields import FieldTestCase - - -class TestModel_field(models.Model): - a = models.IntegerField() - uuid_field = UUIDField() - - -class TestModel_pk(models.Model): - uuid_field = UUIDField(primary_key=True) - - -class TestAgregateModel(TestModel_pk): - a = models.IntegerField() - - -class TestManyToManyModel(TestModel_pk): - many = models.ManyToManyField(TestModel_field) - - -class UUIDFieldTest(FieldTestCase): - def testUUIDFieldCreate(self): - j = TestModel_field.objects.create(a=6, uuid_field=six.u('550e8400-e29b-41d4-a716-446655440000')) - self.assertEqual(j.uuid_field, six.u('550e8400-e29b-41d4-a716-446655440000')) - - def testUUIDField_pkCreate(self): - j = TestModel_pk.objects.create(uuid_field=six.u('550e8400-e29b-41d4-a716-446655440000')) - self.assertEqual(j.uuid_field, six.u('550e8400-e29b-41d4-a716-446655440000')) - self.assertEqual(j.pk, six.u('550e8400-e29b-41d4-a716-446655440000')) - - def testUUIDField_pkAgregateCreate(self): - j = TestAgregateModel.objects.create(a=6, uuid_field=six.u('550e8400-e29b-41d4-a716-446655440001')) - self.assertEqual(j.a, 6) - self.assertIsInstance(j.pk, six.string_types) - self.assertEqual(len(j.pk), 36) - - def testUUIDFieldManyToManyCreate(self): - j = TestManyToManyModel.objects.create(uuid_field=six.u('550e8400-e29b-41d4-a716-446655440010')) - self.assertEqual(j.uuid_field, six.u('550e8400-e29b-41d4-a716-446655440010')) - self.assertEqual(j.pk, six.u('550e8400-e29b-41d4-a716-446655440010')) - diff --git a/awx/lib/site-packages/django_extensions/utils/__init__.py b/awx/lib/site-packages/django_extensions/utils/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/django_extensions/utils/dia2django.py b/awx/lib/site-packages/django_extensions/utils/dia2django.py deleted file mode 100644 index 28d664b733..0000000000 --- a/awx/lib/site-packages/django_extensions/utils/dia2django.py +++ /dev/null @@ -1,214 +0,0 @@ -# -*- coding: UTF-8 -*- -##Author Igor Támara igor@tamarapatino.org -##Use this little program as you wish, if you -#include it in your work, let others know you -#are using it preserving this note, you have -#the right to make derivative works, Use it -#at your own risk. -#Tested to work on(etch testing 13-08-2007): -# Python 2.4.4 (#2, Jul 17 2007, 11:56:54) -# [GCC 4.1.3 20070629 (prerelease) (Debian 4.1.2-13)] on linux2 - -dependclasses = ["User", "Group", "Permission", "Message"] - -import re -import six -import sys -import gzip -import codecs -from xml.dom.minidom import * # NOQA - -#Type dictionary translation types SQL -> Django -tsd = { - "text": "TextField", - "date": "DateField", - "varchar": "CharField", - "int": "IntegerField", - "float": "FloatField", - "serial": "AutoField", - "boolean": "BooleanField", - "numeric": "FloatField", - "timestamp": "DateTimeField", - "bigint": "IntegerField", - "datetime": "DateTimeField", - "date": "DateField", - "time": "TimeField", - "bool": "BooleanField", - "int": "IntegerField", -} - -#convert varchar -> CharField -v2c = re.compile('varchar\((\d+)\)') - - -def index(fks, id): - """Looks for the id on fks, fks is an array of arrays, each array has on [1] - the id of the class in a dia diagram. When not present returns None, else - it returns the position of the class with id on fks""" - for i, j in fks.items(): - if fks[i][1] == id: - return i - return None - - -def addparentstofks(rels, fks): - """Gets a list of relations, between parents and sons and a dict of - clases named in dia, and modifies the fks to add the parent as fk to get - order on the output of classes and replaces the base class of the son, to - put the class parent name. - """ - for j in rels: - son = index(fks, j[1]) - parent = index(fks, j[0]) - fks[son][2] = fks[son][2].replace("models.Model", parent) - if parent not in fks[son][0]: - fks[son][0].append(parent) - - -def dia2django(archivo): - models_txt = '' - f = codecs.open(archivo, "rb") - #dia files are gzipped - data = gzip.GzipFile(fileobj=f).read() - ppal = parseString(data) - #diagram -> layer -> object -> UML - Class -> name, (attribs : composite -> name,type) - datos = ppal.getElementsByTagName("dia:diagram")[0].getElementsByTagName("dia:layer")[0].getElementsByTagName("dia:object") - clases = {} - herit = [] - imports = six.u("") - for i in datos: - #Look for the classes - if i.getAttribute("type") == "UML - Class": - myid = i.getAttribute("id") - for j in i.childNodes: - if j.nodeType == Node.ELEMENT_NODE and j.hasAttributes(): - if j.getAttribute("name") == "name": - actclas = j.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1] - myname = "\nclass %s(models.Model) :\n" % actclas - clases[actclas] = [[], myid, myname, 0] - if j.getAttribute("name") == "attributes": - for l in j.getElementsByTagName("dia:composite"): - if l.getAttribute("type") == "umlattribute": - #Look for the attribute name and type - for k in l.getElementsByTagName("dia:attribute"): - if k.getAttribute("name") == "name": - nc = k.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1] - elif k.getAttribute("name") == "type": - tc = k.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1] - elif k.getAttribute("name") == "value": - val = k.getElementsByTagName("dia:string")[0].childNodes[0].data[1:-1] - if val == '##': - val = '' - elif k.getAttribute("name") == "visibility" and k.getElementsByTagName("dia:enum")[0].getAttribute("val") == "2": - if tc.replace(" ", "").lower().startswith("manytomanyfield("): - #If we find a class not in our model that is marked as being to another model - newc = tc.replace(" ", "")[16:-1] - if dependclasses.count(newc) == 0: - dependclasses.append(newc) - if tc.replace(" ", "").lower().startswith("foreignkey("): - #If we find a class not in our model that is marked as being to another model - newc = tc.replace(" ", "")[11:-1] - if dependclasses.count(newc) == 0: - dependclasses.append(newc) - - #Mapping SQL types to Django - varch = v2c.search(tc) - if tc.replace(" ", "").startswith("ManyToManyField("): - myfor = tc.replace(" ", "")[16:-1] - if actclas == myfor: - #In case of a recursive type, we use 'self' - tc = tc.replace(myfor, "'self'") - elif clases[actclas][0].count(myfor) == 0: - #Adding related class - if myfor not in dependclasses: - #In case we are using Auth classes or external via protected dia visibility - clases[actclas][0].append(myfor) - tc = "models." + tc - if len(val) > 0: - tc = tc.replace(")", "," + val + ")") - elif tc.find("Field") != -1: - if tc.count("()") > 0 and len(val) > 0: - tc = "models.%s" % tc.replace(")", "," + val + ")") - else: - tc = "models.%s(%s)" % (tc, val) - elif tc.replace(" ", "").startswith("ForeignKey("): - myfor = tc.replace(" ", "")[11:-1] - if actclas == myfor: - #In case of a recursive type, we use 'self' - tc = tc.replace(myfor, "'self'") - elif clases[actclas][0].count(myfor) == 0: - #Adding foreign classes - if myfor not in dependclasses: - #In case we are using Auth classes - clases[actclas][0].append(myfor) - tc = "models." + tc - if len(val) > 0: - tc = tc.replace(")", "," + val + ")") - elif varch is None: - tc = "models." + tsd[tc.strip().lower()] + "(" + val + ")" - else: - tc = "models.CharField(max_length=" + varch.group(1) + ")" - if len(val) > 0: - tc = tc.replace(")", ", " + val + " )") - if not (nc == "id" and tc == "AutoField()"): - clases[actclas][2] = clases[actclas][2] + (" %s = %s\n" % (nc, tc)) - elif i.getAttribute("type") == "UML - Generalization": - mycons = ['A', 'A'] - a = i.getElementsByTagName("dia:connection") - for j in a: - if len(j.getAttribute("to")): - mycons[int(j.getAttribute("handle"))] = j.getAttribute("to") - print(mycons) - if not 'A' in mycons: - herit.append(mycons) - elif i.getAttribute("type") == "UML - SmallPackage": - a = i.getElementsByTagName("dia:string") - for j in a: - if len(j.childNodes[0].data[1:-1]): - imports += six.u("from %s.models import *" % j.childNodes[0].data[1:-1]) - - addparentstofks(herit, clases) - #Ordering the appearance of classes - #First we make a list of the classes each classs is related to. - ordered = [] - for j, k in six.iteritems(clases): - k[2] = k[2] + "\n def __unicode__(self):\n return u\"\"\n" - for fk in k[0]: - if fk not in dependclasses: - clases[fk][3] += 1 - ordered.append([j] + k) - - i = 0 - while i < len(ordered): - mark = i - j = i + 1 - while j < len(ordered): - if ordered[i][0] in ordered[j][1]: - mark = j - j += 1 - if mark == i: - i += 1 - else: - # swap %s in %s" % ( ordered[i] , ordered[mark]) to make ordered[i] to be at the end - if ordered[i][0] in ordered[mark][1] and ordered[mark][0] in ordered[i][1]: - #Resolving simplistic circular ForeignKeys - print("Not able to resolve circular ForeignKeys between %s and %s" % (ordered[i][1], ordered[mark][0])) - break - a = ordered[i] - ordered[i] = ordered[mark] - ordered[mark] = a - if i == len(ordered) - 1: - break - ordered.reverse() - if imports: - models_txt = str(imports) - for i in ordered: - models_txt += '%s\n' % str(i[3]) - - return models_txt - -if __name__ == '__main__': - if len(sys.argv) == 2: - dia2django(sys.argv[1]) - else: - print(" Use:\n \n " + sys.argv[0] + " diagram.dia\n\n") diff --git a/awx/lib/site-packages/django_extensions/utils/text.py b/awx/lib/site-packages/django_extensions/utils/text.py deleted file mode 100644 index fd650cf4e5..0000000000 --- a/awx/lib/site-packages/django_extensions/utils/text.py +++ /dev/null @@ -1,23 +0,0 @@ -import six - -from django.utils.functional import allow_lazy - -# conditional import, force_unicode was renamed in Django 1.5 -try: - from django.utils.encoding import force_unicode # NOQA -except ImportError: - from django.utils.encoding import force_text as force_unicode # NOQA - - -def truncate_letters(s, num): - """ - truncates a string to a number of letters, similar to truncate_words - """ - s = force_unicode(s) - length = int(num) - if len(s) > length: - s = s[:length] - if not s.endswith('...'): - s += '...' - return s -truncate_letters = allow_lazy(truncate_letters, six.text_type) diff --git a/awx/lib/site-packages/django_extensions/utils/validatingtemplatetags.py b/awx/lib/site-packages/django_extensions/utils/validatingtemplatetags.py deleted file mode 100644 index b36ca7e172..0000000000 --- a/awx/lib/site-packages/django_extensions/utils/validatingtemplatetags.py +++ /dev/null @@ -1,91 +0,0 @@ -from django.template.base import Library, Node -from django.template import defaulttags -from django.templatetags import future -register = Library() - -error_on_old_style_url_tag = False -new_style_url_tag = False -errors = [] - - -def before_new_template(force_new_urls): - """Reset state ready for new template""" - global new_style_url_tag, error_on_old_style_url_tag, errors - new_style_url_tag = False - error_on_old_style_url_tag = force_new_urls - errors = [] - - -def get_template_errors(): - return errors - - -# Disable extends and include as they are not needed, slow parsing down, and cause duplicate errors -class NoOpNode(Node): - def render(self, context): - return '' - - -@register.tag -def extends(parser, token): - return NoOpNode() - - -@register.tag -def include(parser, token): - return NoOpNode() - - -# We replace load to determine whether new style urls are in use and re-patch url after -# a future version is loaded -@register.tag -def load(parser, token): - global new_style_url_tag - bits = token.contents.split() - - reloaded_url_tag = False - if len(bits) >= 4 and bits[-2] == "from" and bits[-1] == "future": - for name in bits[1:-2]: - if name == "url": - new_style_url_tag = True - reloaded_url_tag = True - - try: - return defaulttags.load(parser, token) - finally: - if reloaded_url_tag: - parser.tags['url'] = new_style_url - - -@register.tag(name='url') -def old_style_url(parser, token): - global error_on_old_style_url_tag - - bits = token.split_contents() - view = bits[1] - - if error_on_old_style_url_tag: - _error("Old style url tag used (only reported once per file): {%% %s %%}" % (" ".join(bits)), token) - error_on_old_style_url_tag = False - - if view[0] in "\"'" and view[0] == view[-1]: - _error("Old style url tag with quotes around view name: {%% %s %%}" % (" ".join(bits)), token) - - return defaulttags.url(parser, token) - - -def new_style_url(parser, token): - bits = token.split_contents() - view = bits[1] - - if view[0] not in "\"'" or view[0] != view[-1]: - _error("New style url tag without quotes around view name: {%% %s %%}" % (" ".join(bits)), token) - - return future.url(parser, token) - - -def _error(message, token): - origin, (start, upto) = token.source - source = origin.reload() - line = source.count("\n", 0, start) + 1 # 1 based line numbering - errors.append((origin, line, message)) diff --git a/awx/lib/site-packages/djcelery/__init__.py b/awx/lib/site-packages/djcelery/__init__.py deleted file mode 100644 index 5ff946410f..0000000000 --- a/awx/lib/site-packages/djcelery/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Old django celery integration project.""" -# :copyright: (c) 2009 - 2012 by Ask Solem. -# :license: BSD, see LICENSE for more details. -from __future__ import absolute_import, unicode_literals - -import os - -VERSION = (3, 1, 10) -__version__ = '.'.join(map(str, VERSION[0:3])) + ''.join(VERSION[3:]) -__author__ = 'Ask Solem' -__contact__ = 'ask@celeryproject.org' -__homepage__ = 'http://celeryproject.org' -__docformat__ = 'restructuredtext' -__license__ = 'BSD (3 clause)' - -# -eof meta- - - -def setup_loader(): - os.environ.setdefault('CELERY_LOADER', 'djcelery.loaders.DjangoLoader') - -from celery import current_app as celery # noqa diff --git a/awx/lib/site-packages/djcelery/admin.py b/awx/lib/site-packages/djcelery/admin.py deleted file mode 100644 index 0cab8e5fdc..0000000000 --- a/awx/lib/site-packages/djcelery/admin.py +++ /dev/null @@ -1,337 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from anyjson import loads - -from django import forms -from django.conf import settings -from django.contrib import admin -from django.contrib.admin import helpers -from django.contrib.admin.views import main as main_views -from django.shortcuts import render_to_response -from django.template import RequestContext -from django.utils.html import escape -from django.utils.translation import ugettext_lazy as _ - -from celery import current_app -from celery import states -from celery.task.control import broadcast, revoke, rate_limit -from celery.utils.text import abbrtask - -from .admin_utils import action, display_field, fixedwidth -from .models import ( - TaskState, WorkerState, - PeriodicTask, IntervalSchedule, CrontabSchedule, -) -from .humanize import naturaldate -from .utils import is_database_scheduler - -try: - from django.utils.encoding import force_text -except ImportError: - from django.utils.encoding import force_unicode as force_text # noqa - - -TASK_STATE_COLORS = {states.SUCCESS: 'green', - states.FAILURE: 'red', - states.REVOKED: 'magenta', - states.STARTED: 'yellow', - states.RETRY: 'orange', - 'RECEIVED': 'blue'} -NODE_STATE_COLORS = {'ONLINE': 'green', - 'OFFLINE': 'gray'} - - -class MonitorList(main_views.ChangeList): - - def __init__(self, *args, **kwargs): - super(MonitorList, self).__init__(*args, **kwargs) - self.title = self.model_admin.list_page_title - - -@display_field(_('state'), 'state') -def colored_state(task): - state = escape(task.state) - color = TASK_STATE_COLORS.get(task.state, 'black') - return '<b><span style="color: {0};">{1}</span></b>'.format(color, state) - - -@display_field(_('state'), 'last_heartbeat') -def node_state(node): - state = node.is_alive() and 'ONLINE' or 'OFFLINE' - color = NODE_STATE_COLORS[state] - return '<b><span style="color: {0};">{1}</span></b>'.format(color, state) - - -@display_field(_('ETA'), 'eta') -def eta(task): - if not task.eta: - return '<span style="color: gray;">none</span>' - return escape(task.eta) - - -@display_field(_('when'), 'tstamp') -def tstamp(task): - return '<div title="{0}">{1}</div>'.format( - escape(str(task.tstamp)), escape(naturaldate(task.tstamp)), - ) - - -@display_field(_('name'), 'name') -def name(task): - short_name = abbrtask(task.name, 16) - return '<div title="{0}"><b>{1}</b></div>'.format( - escape(task.name), escape(short_name), - ) - - -class ModelMonitor(admin.ModelAdmin): - can_add = False - can_delete = False - - def get_changelist(self, request, **kwargs): - return MonitorList - - def change_view(self, request, object_id, extra_context=None): - extra_context = extra_context or {} - extra_context.setdefault('title', self.detail_title) - return super(ModelMonitor, self).change_view( - request, object_id, extra_context=extra_context, - ) - - def has_delete_permission(self, request, obj=None): - if not self.can_delete: - return False - return super(ModelMonitor, self).has_delete_permission(request, obj) - - def has_add_permission(self, request): - if not self.can_add: - return False - return super(ModelMonitor, self).has_add_permission(request) - - -class TaskMonitor(ModelMonitor): - detail_title = _('Task detail') - list_page_title = _('Tasks') - rate_limit_confirmation_template = 'djcelery/confirm_rate_limit.html' - date_hierarchy = 'tstamp' - fieldsets = ( - (None, { - 'fields': ('state', 'task_id', 'name', 'args', 'kwargs', - 'eta', 'runtime', 'worker', 'tstamp'), - 'classes': ('extrapretty', ), - }), - ('Details', { - 'classes': ('collapse', 'extrapretty'), - 'fields': ('result', 'traceback', 'expires'), - }), - ) - list_display = ( - fixedwidth('task_id', name=_('UUID'), pt=8), - colored_state, - name, - fixedwidth('args', pretty=True), - fixedwidth('kwargs', pretty=True), - eta, - tstamp, - 'worker', - ) - readonly_fields = ( - 'state', 'task_id', 'name', 'args', 'kwargs', - 'eta', 'runtime', 'worker', 'result', 'traceback', - 'expires', 'tstamp', - ) - list_filter = ('state', 'name', 'tstamp', 'eta', 'worker') - search_fields = ('name', 'task_id', 'args', 'kwargs', 'worker__hostname') - actions = ['revoke_tasks', - 'terminate_tasks', - 'kill_tasks', - 'rate_limit_tasks'] - - class Media: - css = {'all': ('djcelery/style.css', )} - - @action(_('Revoke selected tasks')) - def revoke_tasks(self, request, queryset): - with current_app.default_connection() as connection: - for state in queryset: - revoke(state.task_id, connection=connection) - - @action(_('Terminate selected tasks')) - def terminate_tasks(self, request, queryset): - with current_app.default_connection() as connection: - for state in queryset: - revoke(state.task_id, connection=connection, terminate=True) - - @action(_('Kill selected tasks')) - def kill_tasks(self, request, queryset): - with current_app.default_connection() as connection: - for state in queryset: - revoke(state.task_id, connection=connection, - terminate=True, signal='KILL') - - @action(_('Rate limit selected tasks')) - def rate_limit_tasks(self, request, queryset): - tasks = set([task.name for task in queryset]) - opts = self.model._meta - app_label = opts.app_label - if request.POST.get('post'): - rate = request.POST['rate_limit'] - with current_app.default_connection() as connection: - for task_name in tasks: - rate_limit(task_name, rate, connection=connection) - return None - - context = { - 'title': _('Rate limit selection'), - 'queryset': queryset, - 'object_name': force_text(opts.verbose_name), - 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, - 'opts': opts, - 'app_label': app_label, - } - - return render_to_response( - self.rate_limit_confirmation_template, context, - context_instance=RequestContext(request), - ) - - def get_actions(self, request): - actions = super(TaskMonitor, self).get_actions(request) - actions.pop('delete_selected', None) - return actions - - def get_queryset(self, request): - qs = super(TaskMonitor, self).get_queryset(request) - return qs.select_related('worker') - - -class WorkerMonitor(ModelMonitor): - can_add = True - detail_title = _('Node detail') - list_page_title = _('Worker Nodes') - list_display = ('hostname', node_state) - readonly_fields = ('last_heartbeat', ) - actions = ['shutdown_nodes', - 'enable_events', - 'disable_events'] - - @action(_('Shutdown selected worker nodes')) - def shutdown_nodes(self, request, queryset): - broadcast('shutdown', destination=[n.hostname for n in queryset]) - - @action(_('Enable event mode for selected nodes.')) - def enable_events(self, request, queryset): - broadcast('enable_events', - destination=[n.hostname for n in queryset]) - - @action(_('Disable event mode for selected nodes.')) - def disable_events(self, request, queryset): - broadcast('disable_events', - destination=[n.hostname for n in queryset]) - - def get_actions(self, request): - actions = super(WorkerMonitor, self).get_actions(request) - actions.pop('delete_selected', None) - return actions - -admin.site.register(TaskState, TaskMonitor) -admin.site.register(WorkerState, WorkerMonitor) - - -# ### Periodic Tasks - - -class LaxChoiceField(forms.ChoiceField): - - def valid_value(self, value): - return True - - -def periodic_task_form(): - current_app.loader.import_default_modules() - tasks = list(sorted(name for name in current_app.tasks - if not name.startswith('celery.'))) - choices = (('', ''), ) + tuple(zip(tasks, tasks)) - - class PeriodicTaskForm(forms.ModelForm): - regtask = LaxChoiceField(label=_('Task (registered)'), - choices=choices, required=False) - task = forms.CharField(label=_('Task (custom)'), required=False, - max_length=200) - - class Meta: - model = PeriodicTask - exclude = () - - def clean(self): - data = super(PeriodicTaskForm, self).clean() - regtask = data.get('regtask') - if regtask: - data['task'] = regtask - if not data['task']: - exc = forms.ValidationError(_('Need name of task')) - self._errors['task'] = self.error_class(exc.messages) - raise exc - return data - - def _clean_json(self, field): - value = self.cleaned_data[field] - try: - loads(value) - except ValueError as exc: - raise forms.ValidationError( - _('Unable to parse JSON: %s') % exc, - ) - return value - - def clean_args(self): - return self._clean_json('args') - - def clean_kwargs(self): - return self._clean_json('kwargs') - - return PeriodicTaskForm - - -class PeriodicTaskAdmin(admin.ModelAdmin): - model = PeriodicTask - form = periodic_task_form() - list_display = ('__unicode__', 'enabled') - fieldsets = ( - (None, { - 'fields': ('name', 'regtask', 'task', 'enabled'), - 'classes': ('extrapretty', 'wide'), - }), - ('Schedule', { - 'fields': ('interval', 'crontab'), - 'classes': ('extrapretty', 'wide', ), - }), - ('Arguments', { - 'fields': ('args', 'kwargs'), - 'classes': ('extrapretty', 'wide', 'collapse'), - }), - ('Execution Options', { - 'fields': ('expires', 'queue', 'exchange', 'routing_key'), - 'classes': ('extrapretty', 'wide', 'collapse'), - }), - ) - - def __init__(self, *args, **kwargs): - super(PeriodicTaskAdmin, self).__init__(*args, **kwargs) - self.form = periodic_task_form() - - def changelist_view(self, request, extra_context=None): - extra_context = extra_context or {} - scheduler = getattr(settings, 'CELERYBEAT_SCHEDULER', None) - extra_context['wrong_scheduler'] = not is_database_scheduler(scheduler) - return super(PeriodicTaskAdmin, self).changelist_view(request, - extra_context) - - def get_queryset(self, request): - qs = super(PeriodicTaskAdmin, self).get_queryset(request) - return qs.select_related('interval', 'crontab') - - -admin.site.register(IntervalSchedule) -admin.site.register(CrontabSchedule) -admin.site.register(PeriodicTask, PeriodicTaskAdmin) diff --git a/awx/lib/site-packages/djcelery/admin_utils.py b/awx/lib/site-packages/djcelery/admin_utils.py deleted file mode 100644 index da5b39eb1d..0000000000 --- a/awx/lib/site-packages/djcelery/admin_utils.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from pprint import pformat - -from django.utils.html import escape - -FIXEDWIDTH_STYLE = '''\ -<span title="{0}" style="font-size: {1}pt; \ -font-family: Menlo, Courier; ">{2}</span> \ -''' - - -def attrs(**kwargs): - def _inner(fun): - for attr_name, attr_value in kwargs.items(): - setattr(fun, attr_name, attr_value) - return fun - return _inner - - -def display_field(short_description, admin_order_field, - allow_tags=True, **kwargs): - return attrs(short_description=short_description, - admin_order_field=admin_order_field, - allow_tags=allow_tags, **kwargs) - - -def action(short_description, **kwargs): - return attrs(short_description=short_description, **kwargs) - - -def fixedwidth(field, name=None, pt=6, width=16, maxlen=64, pretty=False): - - @display_field(name or field, field) - def f(task): - val = getattr(task, field) - if pretty: - val = pformat(val, width=width) - if val.startswith("u'") or val.startswith('u"'): - val = val[2:-1] - shortval = val.replace(',', ',\n') - shortval = shortval.replace('\n', '|br/|') - - if len(shortval) > maxlen: - shortval = shortval[:maxlen] + '...' - styled = FIXEDWIDTH_STYLE.format( - escape(val[:255]), pt, escape(shortval), - ) - return styled.replace('|br/|', '<br/>') - return f diff --git a/awx/lib/site-packages/djcelery/app.py b/awx/lib/site-packages/djcelery/app.py deleted file mode 100644 index 7b75759431..0000000000 --- a/awx/lib/site-packages/djcelery/app.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from celery import current_app - - -#: The Django-Celery app instance. -app = current_app._get_current_object() diff --git a/awx/lib/site-packages/djcelery/backends/__init__.py b/awx/lib/site-packages/djcelery/backends/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/backends/cache.py b/awx/lib/site-packages/djcelery/backends/cache.py deleted file mode 100644 index 7006bf06f9..0000000000 --- a/awx/lib/site-packages/djcelery/backends/cache.py +++ /dev/null @@ -1,68 +0,0 @@ -"""celery.backends.cache""" -from __future__ import absolute_import, unicode_literals - -from datetime import timedelta - -import django -from django.utils.encoding import smart_str -from django.core.cache import cache, get_cache - -from celery import current_app -from celery.utils.timeutils import timedelta_seconds -from celery.backends.base import KeyValueStoreBackend - -# CELERY_CACHE_BACKEND overrides the django-global(tm) backend settings. -if current_app.conf.CELERY_CACHE_BACKEND: - cache = get_cache(current_app.conf.CELERY_CACHE_BACKEND) # noqa - - -class DjangoMemcacheWrapper(object): - """Wrapper class to django's memcache backend class, that overrides the - :meth:`get` method in order to remove the forcing of unicode strings - since it may cause binary or pickled data to break.""" - - def __init__(self, cache): - self.cache = cache - - def get(self, key, default=None): - val = self.cache._cache.get(smart_str(key)) - if val is None: - return default - else: - return val - - def set(self, key, value, timeout=0): - self.cache.set(key, value, timeout) - -# Check if django is using memcache as the cache backend. If so, wrap the -# cache object in a DjangoMemcacheWrapper for Django < 1.2 that fixes a bug -# with retrieving pickled data. -from django.core.cache.backends.base import InvalidCacheBackendError -try: - from django.core.cache.backends.memcached import CacheClass -except (ImportError, AttributeError, InvalidCacheBackendError): - pass -else: - if django.VERSION[0:2] < (1, 2) and isinstance(cache, CacheClass): - cache = DjangoMemcacheWrapper(cache) - - -class CacheBackend(KeyValueStoreBackend): - """Backend using the Django cache framework to store task metadata.""" - - def __init__(self, *args, **kwargs): - super(CacheBackend, self).__init__(*args, **kwargs) - expires = kwargs.get('expires', - current_app.conf.CELERY_TASK_RESULT_EXPIRES) - if isinstance(expires, timedelta): - expires = int(timedelta_seconds(expires)) - self.expires = expires - - def get(self, key): - return cache.get(key) - - def set(self, key, value): - cache.set(key, value, self.expires) - - def delete(self, key): - cache.delete(key) diff --git a/awx/lib/site-packages/djcelery/backends/database.py b/awx/lib/site-packages/djcelery/backends/database.py deleted file mode 100644 index fd43f23959..0000000000 --- a/awx/lib/site-packages/djcelery/backends/database.py +++ /dev/null @@ -1,61 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from celery import current_app -from celery.backends.base import BaseDictBackend -from celery.utils.timeutils import maybe_timedelta - -from ..models import TaskMeta, TaskSetMeta - - -class DatabaseBackend(BaseDictBackend): - """The database backend. - - Using Django models to store task state. - - """ - TaskModel = TaskMeta - TaskSetModel = TaskSetMeta - - expires = current_app.conf.CELERY_TASK_RESULT_EXPIRES - create_django_tables = True - - subpolling_interval = 0.5 - - def _store_result(self, task_id, result, status, - traceback=None, request=None): - """Store return value and status of an executed task.""" - self.TaskModel._default_manager.store_result( - task_id, result, status, - traceback=traceback, children=self.current_task_children(request), - ) - return result - - def _save_group(self, group_id, result): - """Store the result of an executed group.""" - self.TaskSetModel._default_manager.store_result(group_id, result) - return result - - def _get_task_meta_for(self, task_id): - """Get task metadata for a task by id.""" - return self.TaskModel._default_manager.get_task(task_id).to_dict() - - def _restore_group(self, group_id): - """Get group metadata for a group by id.""" - meta = self.TaskSetModel._default_manager.restore_taskset(group_id) - if meta: - return meta.to_dict() - - def _delete_group(self, group_id): - self.TaskSetModel._default_manager.delete_taskset(group_id) - - def _forget(self, task_id): - try: - self.TaskModel._default_manager.get(task_id=task_id).delete() - except self.TaskModel.DoesNotExist: - pass - - def cleanup(self): - """Delete expired metadata.""" - expires = maybe_timedelta(self.expires) - for model in self.TaskModel, self.TaskSetModel: - model._default_manager.delete_expired(expires) diff --git a/awx/lib/site-packages/djcelery/common.py b/awx/lib/site-packages/djcelery/common.py deleted file mode 100644 index a6535dbca0..0000000000 --- a/awx/lib/site-packages/djcelery/common.py +++ /dev/null @@ -1,72 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from contextlib import contextmanager -from functools import wraps - -from django.utils import translation - - -@contextmanager -def respect_language(language): - """Context manager that changes the current translation language for - all code inside the following block. - - Can e.g. be used inside tasks like this:: - - from celery import task - from djcelery.common import respect_language - - @task - def my_task(language=None): - with respect_language(language): - pass - """ - if language: - prev = translation.get_language() - translation.activate(language) - try: - yield - finally: - translation.activate(prev) - else: - yield - - -def respects_language(fun): - """Decorator for tasks with respect to site's current language. - You can use this decorator on your tasks together with default @task - decorator (remember that the task decorator must be applied last). - - See also the with-statement alternative :func:`respect_language`. - - **Example**: - - .. code-block:: python - - @task - @respects_language - def my_task() - # localize something. - - The task will then accept a ``language`` argument that will be - used to set the language in the task, and the task can thus be - called like: - - .. code-block:: python - - from django.utils import translation - from myapp.tasks import my_task - - # Pass the current language on to the task - my_task.delay(language=translation.get_language()) - - # or set the language explicitly - my_task.delay(language='no.no') - - """ - - @wraps(fun) - def _inner(*args, **kwargs): - with respect_language(kwargs.pop('language', None)): - return fun(*args, **kwargs) - return _inner diff --git a/awx/lib/site-packages/djcelery/contrib/__init__.py b/awx/lib/site-packages/djcelery/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/contrib/test_runner.py b/awx/lib/site-packages/djcelery/contrib/test_runner.py deleted file mode 100644 index e65de297ee..0000000000 --- a/awx/lib/site-packages/djcelery/contrib/test_runner.py +++ /dev/null @@ -1,69 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from django.conf import settings -try: - from django.test.runner import DiscoverRunner -except ImportError: - from django.test.simple import DjangoTestSuiteRunner as DiscoverRunner - -from celery import current_app -from celery.task import Task -from djcelery.backends.database import DatabaseBackend - - -USAGE = """\ -Custom test runner to allow testing of celery delayed tasks. -""" - - -def _set_eager(): - settings.CELERY_ALWAYS_EAGER = True - current_app.conf.CELERY_ALWAYS_EAGER = True - settings.CELERY_EAGER_PROPAGATES_EXCEPTIONS = True # Issue #75 - current_app.conf.CELERY_EAGER_PROPAGATES_EXCEPTIONS = True - - -class CeleryTestSuiteRunner(DiscoverRunner): - """Django test runner allowing testing of celery delayed tasks. - - All tasks are run locally, not in a worker. - - To use this runner set ``settings.TEST_RUNNER``:: - - TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner' - - """ - def setup_test_environment(self, **kwargs): - _set_eager() - super(CeleryTestSuiteRunner, self).setup_test_environment(**kwargs) - - -class CeleryTestSuiteRunnerStoringResult(DiscoverRunner): - """Django test runner allowing testing of celery delayed tasks, - and storing the results of those tasks in ``TaskMeta``. - - Requires setting CELERY_RESULT_BACKEND = 'database'. - - USAGE: - - In ``settings.py``:: - - TEST_RUNNER = ''' - djcelery.contrib.test_runner.CeleryTestSuiteRunnerStoringResult - '''.strip() - - """ - - def setup_test_environment(self, **kwargs): - # Monkey-patch Task.on_success() method - def on_success_patched(self, retval, task_id, args, kwargs): - app = current_app._get_current_object() - DatabaseBackend(app=app).store_result(task_id, retval, 'SUCCESS') - Task.on_success = classmethod(on_success_patched) - - super(CeleryTestSuiteRunnerStoringResult, self).setup_test_environment( - **kwargs - ) - - settings.CELERY_RESULT_BACKEND = 'database' - _set_eager() diff --git a/awx/lib/site-packages/djcelery/db.py b/awx/lib/site-packages/djcelery/db.py deleted file mode 100644 index 2204083a5c..0000000000 --- a/awx/lib/site-packages/djcelery/db.py +++ /dev/null @@ -1,63 +0,0 @@ -from __future__ import absolute_import - -import django - -from contextlib import contextmanager -from django.db import transaction - -if django.VERSION < (1, 6): # pragma: no cover - - def get_queryset(s): - return s.get_query_set() -else: - def get_queryset(s): # noqa - return s.get_queryset() - -try: - from django.db.transaction import atomic # noqa -except ImportError: # pragma: no cover - - try: - from django.db.transaction import Transaction # noqa - except ImportError: - @contextmanager - def commit_on_success(*args, **kwargs): - try: - transaction.enter_transaction_management(*args, **kwargs) - transaction.managed(True, *args, **kwargs) - try: - yield - except: - if transaction.is_dirty(*args, **kwargs): - transaction.rollback(*args, **kwargs) - raise - else: - if transaction.is_dirty(*args, **kwargs): - try: - transaction.commit(*args, **kwargs) - except: - transaction.rollback(*args, **kwargs) - raise - finally: - transaction.leave_transaction_management(*args, **kwargs) - else: # pragma: no cover - from django.db.transaction import commit_on_success # noqa - - commit_unless_managed = transaction.commit_unless_managed - rollback_unless_managed = transaction.rollback_unless_managed -else: - @contextmanager - def commit_on_success(using=None): # noqa - connection = transaction.get_connection(using) - if connection.features.autocommits_when_autocommit_is_off: - # ignore stupid warnings and errors - yield - else: - with transaction.atomic(using): - yield - - def commit_unless_managed(*args, **kwargs): # noqa - pass - - def rollback_unless_managed(*args, **kwargs): # noqa - pass diff --git a/awx/lib/site-packages/djcelery/humanize.py b/awx/lib/site-packages/djcelery/humanize.py deleted file mode 100644 index 9ddc7a4382..0000000000 --- a/awx/lib/site-packages/djcelery/humanize.py +++ /dev/null @@ -1,85 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from datetime import datetime - -from django.utils.translation import ungettext, ugettext as _ -from .utils import now - - -def pluralize_year(n): - return ungettext(_('{num} year ago'), _('{num} years ago'), n) - - -def pluralize_month(n): - return ungettext(_('{num} month ago'), _('{num} months ago'), n) - - -def pluralize_week(n): - return ungettext(_('{num} week ago'), _('{num} weeks ago'), n) - - -def pluralize_day(n): - return ungettext(_('{num} day ago'), _('{num} days ago'), n) - - -OLDER_CHUNKS = ( - (365.0, pluralize_year), - (30.0, pluralize_month), - (7.0, pluralize_week), - (1.0, pluralize_day), -) - - -def _un(singular__plural, n=None): - singular, plural = singular__plural - return ungettext(singular, plural, n) - - -def naturaldate(date, include_seconds=False): - """Convert datetime into a human natural date string.""" - - if not date: - return '' - - right_now = now() - today = datetime(right_now.year, right_now.month, - right_now.day, tzinfo=right_now.tzinfo) - delta = right_now - date - delta_midnight = today - date - - days = delta.days - hours = int(round(delta.seconds / 3600, 0)) - minutes = delta.seconds / 60 - seconds = delta.seconds - - if days < 0: - return _('just now') - - if days == 0: - if hours == 0: - if minutes > 0: - return ungettext( - _('{minutes} minute ago'), - _('{minutes} minutes ago'), minutes - ).format(minutes=minutes) - else: - if include_seconds and seconds: - return ungettext( - _('{seconds} second ago'), - _('{seconds} seconds ago'), seconds - ).format(seconds=seconds) - return _('just now') - else: - return ungettext( - _('{hours} hour ago'), _('{hours} hours ago'), hours - ).format(hours=hours) - - if delta_midnight.days == 0: - return _('yesterday at {time}').format(time=date.strftime('%H:%M')) - - count = 0 - for chunk, pluralizefun in OLDER_CHUNKS: - if days >= chunk: - count = round((delta_midnight.days + 1) / chunk, 0) - fmt = pluralizefun(count) - return fmt.format(num=count) diff --git a/awx/lib/site-packages/djcelery/loaders.py b/awx/lib/site-packages/djcelery/loaders.py deleted file mode 100644 index df0a668f3a..0000000000 --- a/awx/lib/site-packages/djcelery/loaders.py +++ /dev/null @@ -1,203 +0,0 @@ -from __future__ import absolute_import - -import os -import imp -import importlib - -from datetime import datetime -from warnings import warn - -from celery import signals -from celery.datastructures import DictAttribute -from celery.loaders.base import BaseLoader - -import django -from django import db -from django.conf import settings -from django.core import cache -from django.core.mail import mail_admins - -from .utils import DATABASE_ERRORS, now - -_RACE_PROTECTION = False -NO_TZ = django.VERSION < (1, 4) - - -def _maybe_close_fd(fh): - try: - os.close(fh.fileno()) - except (AttributeError, OSError, TypeError): - # TypeError added for celery#962 - pass - - -class DjangoLoader(BaseLoader): - """The Django loader.""" - _db_reuse = 0 - - override_backends = { - 'database': 'djcelery.backends.database.DatabaseBackend', - 'cache': 'djcelery.backends.cache.CacheBackend', - } - - def __init__(self, *args, **kwargs): - super(DjangoLoader, self).__init__(*args, **kwargs) - self._install_signal_handlers() - - def _install_signal_handlers(self): - # Need to close any open database connection after - # any embedded celerybeat process forks. - signals.beat_embedded_init.connect(self.close_database) - signals.worker_ready.connect(self.warn_if_debug) - - def now(self, utc=False): - return datetime.utcnow() if utc else now() - - def read_configuration(self): - """Load configuration from Django settings.""" - self.configured = True - # Default backend needs to be the database backend for backward - # compatibility. - backend = (getattr(settings, 'CELERY_RESULT_BACKEND', None) or - getattr(settings, 'CELERY_BACKEND', None)) - if not backend: - settings.CELERY_RESULT_BACKEND = 'database' - if NO_TZ: - if getattr(settings, 'CELERY_ENABLE_UTC', None): - warn('CELERY_ENABLE_UTC requires Django 1.4+') - settings.CELERY_ENABLE_UTC = False - return DictAttribute(settings) - - def _close_database(self): - try: - funs = [conn.close for conn in db.connections] - except AttributeError: - if hasattr(db, 'close_old_connections'): # Django 1.6+ - funs = [db.close_old_connections] - else: - funs = [db.close_connection] # pre multidb - - for close in funs: - try: - close() - except DATABASE_ERRORS as exc: - str_exc = str(exc) - if 'closed' not in str_exc and 'not connected' not in str_exc: - raise - - def close_database(self, **kwargs): - db_reuse_max = self.conf.get('CELERY_DB_REUSE_MAX', None) - if not db_reuse_max: - return self._close_database() - if self._db_reuse >= db_reuse_max * 2: - self._db_reuse = 0 - self._close_database() - self._db_reuse += 1 - - def close_cache(self): - try: - cache.cache.close() - except (TypeError, AttributeError): - pass - - def on_process_cleanup(self): - """Does everything necessary for Django to work in a long-living, - multiprocessing environment. - - """ - # See http://groups.google.com/group/django-users/ - # browse_thread/thread/78200863d0c07c6d/ - self.close_database() - self.close_cache() - - def on_task_init(self, task_id, task): - """Called before every task.""" - try: - is_eager = task.request.is_eager - except AttributeError: - is_eager = False - if not is_eager: - self.close_database() - - def on_worker_init(self): - """Called when the worker starts. - - Automatically discovers any ``tasks.py`` files in the applications - listed in ``INSTALLED_APPS``. - - """ - self.import_default_modules() - - self.close_database() - self.close_cache() - - def warn_if_debug(self, **kwargs): - if settings.DEBUG: - warn('Using settings.DEBUG leads to a memory leak, never ' - 'use this setting in production environments!') - - def import_default_modules(self): - super(DjangoLoader, self).import_default_modules() - self.autodiscover() - - def autodiscover(self): - self.task_modules.update(mod.__name__ for mod in autodiscover() or ()) - - def on_worker_process_init(self): - # the parent process may have established these, - # so need to close them. - - # calling db.close() on some DB connections will cause - # the inherited DB conn to also get broken in the parent - # process so we need to remove it without triggering any - # network IO that close() might cause. - try: - for c in db.connections.all(): - if c and c.connection: - _maybe_close_fd(c.connection) - except AttributeError: - if db.connection and db.connection.connection: - _maybe_close_fd(db.connection.connection) - - # use the _ version to avoid DB_REUSE preventing the conn.close() call - self._close_database() - self.close_cache() - - def mail_admins(self, subject, body, fail_silently=False, **kwargs): - return mail_admins(subject, body, fail_silently=fail_silently) - - -def autodiscover(): - """Include tasks for all applications in ``INSTALLED_APPS``.""" - global _RACE_PROTECTION - - if _RACE_PROTECTION: - return - _RACE_PROTECTION = True - try: - return filter(None, [find_related_module(app, 'tasks') - for app in settings.INSTALLED_APPS]) - finally: - _RACE_PROTECTION = False - - -def find_related_module(app, related_name): - """Given an application name and a module name, tries to find that - module in the application.""" - - try: - app_path = importlib.import_module(app).__path__ - except ImportError as exc: - warn('Autodiscover: Error importing %s.%s: %r' % ( - app, related_name, exc, - )) - return - except AttributeError: - return - - try: - imp.find_module(related_name, app_path) - except ImportError: - return - - return importlib.import_module('{0}.{1}'.format(app, related_name)) diff --git a/awx/lib/site-packages/djcelery/management/__init__.py b/awx/lib/site-packages/djcelery/management/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/management/base.py b/awx/lib/site-packages/djcelery/management/base.py deleted file mode 100644 index b1190f801d..0000000000 --- a/awx/lib/site-packages/djcelery/management/base.py +++ /dev/null @@ -1,112 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import os -import sys - -from django.core.management.base import BaseCommand - -import celery -import djcelery - -DB_SHARED_THREAD = """\ -DatabaseWrapper objects created in a thread can only \ -be used in that same thread. The object with alias '{0}' \ -was created in thread id {1} and this is thread id {2}.\ -""" - - -def patch_thread_ident(): - # monkey patch django. - # This patch make sure that we use real threads to get the ident which - # is going to happen if we are using gevent or eventlet. - # -- patch taken from gunicorn - if getattr(patch_thread_ident, 'called', False): - return - try: - from django.db.backends import BaseDatabaseWrapper, DatabaseError - - if 'validate_thread_sharing' in BaseDatabaseWrapper.__dict__: - import thread - _get_ident = thread.get_ident - - __old__init__ = BaseDatabaseWrapper.__init__ - - def _init(self, *args, **kwargs): - __old__init__(self, *args, **kwargs) - self._thread_ident = _get_ident() - - def _validate_thread_sharing(self): - if (not self.allow_thread_sharing - and self._thread_ident != _get_ident()): - raise DatabaseError( - DB_SHARED_THREAD % ( - self.alias, self._thread_ident, _get_ident()), - ) - - BaseDatabaseWrapper.__init__ = _init - BaseDatabaseWrapper.validate_thread_sharing = \ - _validate_thread_sharing - - patch_thread_ident.called = True - except ImportError: - pass -patch_thread_ident() - - -class CeleryCommand(BaseCommand): - options = BaseCommand.option_list - skip_opts = ['--app', '--loader', '--config'] - keep_base_opts = False - - def get_version(self): - return 'celery {c.__version__}\ndjango-celery {d.__version__}'.format( - c=celery, d=djcelery, - ) - - def execute(self, *args, **options): - broker = options.get('broker') - if broker: - self.set_broker(broker) - super(CeleryCommand, self).execute(*args, **options) - - def set_broker(self, broker): - os.environ['CELERY_BROKER_URL'] = broker - - def run_from_argv(self, argv): - self.handle_default_options(argv[2:]) - return super(CeleryCommand, self).run_from_argv(argv) - - def handle_default_options(self, argv): - acc = [] - broker = None - for i, arg in enumerate(argv): - # --settings and --pythonpath are also handled - # by BaseCommand.handle_default_options, but that is - # called with the resulting options parsed by optparse. - if '--settings=' in arg: - _, settings_module = arg.split('=') - os.environ['DJANGO_SETTINGS_MODULE'] = settings_module - elif '--pythonpath=' in arg: - _, pythonpath = arg.split('=') - sys.path.insert(0, pythonpath) - elif '--broker=' in arg: - _, broker = arg.split('=') - elif arg == '-b': - broker = argv[i + 1] - else: - acc.append(arg) - if broker: - self.set_broker(broker) - return argv if self.keep_base_opts else acc - - def die(self, msg): - sys.stderr.write(msg) - sys.stderr.write('\n') - sys.exit() - - def _is_unwanted_option(self, option): - return option._long_opts and option._long_opts[0] in self.skip_opts - - @property - def option_list(self): - return [x for x in self.options if not self._is_unwanted_option(x)] diff --git a/awx/lib/site-packages/djcelery/management/commands/__init__.py b/awx/lib/site-packages/djcelery/management/commands/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/management/commands/celery.py b/awx/lib/site-packages/djcelery/management/commands/celery.py deleted file mode 100644 index c47626a9ea..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/celery.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from celery.bin import celery - -from djcelery.app import app -from djcelery.management.base import CeleryCommand - -base = celery.CeleryCommand(app=app) - - -class Command(CeleryCommand): - """The celery command.""" - help = 'celery commands, see celery help' - requires_model_validation = True - options = (CeleryCommand.options - + base.get_options() - + base.preload_options) - - def run_from_argv(self, argv): - argv = self.handle_default_options(argv) - if self.requires_model_validation: - self.validate() - base.execute_from_commandline( - ['{0[0]} {0[1]}'.format(argv)] + argv[2:], - ) diff --git a/awx/lib/site-packages/djcelery/management/commands/celerybeat.py b/awx/lib/site-packages/djcelery/management/commands/celerybeat.py deleted file mode 100644 index c91a13475f..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/celerybeat.py +++ /dev/null @@ -1,24 +0,0 @@ -""" - -Start the celery clock service from the Django management command. - -""" -from __future__ import absolute_import, unicode_literals - -from celery.bin import beat - -from djcelery.app import app -from djcelery.management.base import CeleryCommand - -beat = beat.beat(app=app) - - -class Command(CeleryCommand): - """Run the celery periodic task scheduler.""" - options = (CeleryCommand.options - + beat.get_options() - + beat.preload_options) - help = 'Old alias to the "celery beat" command.' - - def handle(self, *args, **options): - beat.run(*args, **options) diff --git a/awx/lib/site-packages/djcelery/management/commands/celerycam.py b/awx/lib/site-packages/djcelery/management/commands/celerycam.py deleted file mode 100644 index 8686a5ae7f..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/celerycam.py +++ /dev/null @@ -1,26 +0,0 @@ -""" - -Shortcut to the Django snapshot service. - -""" -from __future__ import absolute_import, unicode_literals - -from celery.bin import events - -from djcelery.app import app -from djcelery.management.base import CeleryCommand - -ev = events.events(app=app) - - -class Command(CeleryCommand): - """Run the celery curses event viewer.""" - options = (CeleryCommand.options - + ev.get_options() - + ev.preload_options) - help = 'Takes snapshots of the clusters state to the database.' - - def handle(self, *args, **options): - """Handle the management command.""" - options['camera'] = 'djcelery.snapshot.Camera' - ev.run(*args, **options) diff --git a/awx/lib/site-packages/djcelery/management/commands/celeryd.py b/awx/lib/site-packages/djcelery/management/commands/celeryd.py deleted file mode 100644 index 1e3262ccf1..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/celeryd.py +++ /dev/null @@ -1,26 +0,0 @@ -""" - -Start the celery daemon from the Django management command. - -""" -from __future__ import absolute_import, unicode_literals - -from celery.bin import worker - -from djcelery.app import app -from djcelery.management.base import CeleryCommand - -worker = worker.worker(app=app) - - -class Command(CeleryCommand): - """Run the celery daemon.""" - help = 'Old alias to the "celery worker" command.' - requires_model_validation = True - options = (CeleryCommand.options - + worker.get_options() - + worker.preload_options) - - def handle(self, *args, **options): - worker.check_args(args) - worker.run(**options) diff --git a/awx/lib/site-packages/djcelery/management/commands/celeryd_detach.py b/awx/lib/site-packages/djcelery/management/commands/celeryd_detach.py deleted file mode 100644 index f620b8da17..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/celeryd_detach.py +++ /dev/null @@ -1,26 +0,0 @@ -""" - -Start detached worker node from the Django management utility. - -""" -from __future__ import absolute_import, unicode_literals - -import os -import sys - -from celery.bin import celeryd_detach - -from djcelery.management.base import CeleryCommand - - -class Command(CeleryCommand): - """Run the celery daemon.""" - help = 'Runs a detached Celery worker node.' - requires_model_validation = True - options = celeryd_detach.OPTION_LIST - - def run_from_argv(self, argv): - - class detached(celeryd_detach.detached_celeryd): - execv_argv = [os.path.abspath(sys.argv[0]), 'celery', 'worker'] - detached().execute_from_commandline(argv) diff --git a/awx/lib/site-packages/djcelery/management/commands/celeryd_multi.py b/awx/lib/site-packages/djcelery/management/commands/celeryd_multi.py deleted file mode 100644 index a0a88b5b14..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/celeryd_multi.py +++ /dev/null @@ -1,26 +0,0 @@ -""" - -Utility to manage multiple worker instances. - -""" -from __future__ import absolute_import, unicode_literals - -from celery.bin import multi - -from djcelery.management.base import CeleryCommand - - -class Command(CeleryCommand): - """Run the celery daemon.""" - args = '[name1, [name2, [...]> [worker options]' - help = 'Manage multiple Celery worker nodes.' - requires_model_validation = True - options = () - keep_base_opts = True - - def run_from_argv(self, argv): - argv = self.handle_default_options(argv) - argv.append('--cmd={0[0]} celeryd_detach'.format(argv)) - multi.MultiTool().execute_from_commandline( - ['{0[0]} {0[1]}'.format(argv)] + argv[2:], - ) diff --git a/awx/lib/site-packages/djcelery/management/commands/celerymon.py b/awx/lib/site-packages/djcelery/management/commands/celerymon.py deleted file mode 100644 index 7c42484631..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/celerymon.py +++ /dev/null @@ -1,42 +0,0 @@ -""" - -Start the celery clock service from the Django management command. - -""" -from __future__ import absolute_import, unicode_literals - -import sys - -from djcelery.app import app -from djcelery.management.base import CeleryCommand - -try: - from celerymon.bin.celerymon import MonitorCommand - mon = MonitorCommand(app=app) -except ImportError: - mon = None - -MISSING = """ -You don't have celerymon installed, please install it by running the following -command: - - $ pip install -U celerymon - -or if you're still using easy_install (shame on you!) - - $ easy_install -U celerymon -""" - - -class Command(CeleryCommand): - """Run the celery monitor.""" - options = (CeleryCommand.options - + (mon and mon.get_options() + mon.preload_options or ())) - help = 'Run the celery monitor' - - def handle(self, *args, **options): - """Handle the management command.""" - if mon is None: - sys.stderr.write(MISSING) - else: - mon.run(**options) diff --git a/awx/lib/site-packages/djcelery/management/commands/djcelerymon.py b/awx/lib/site-packages/djcelery/management/commands/djcelerymon.py deleted file mode 100644 index 9310155180..0000000000 --- a/awx/lib/site-packages/djcelery/management/commands/djcelerymon.py +++ /dev/null @@ -1,48 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import sys -import threading - -from celery.bin import events - -from django.core.management.commands import runserver - -from djcelery.app import app -from djcelery.management.base import CeleryCommand - -ev = events.events(app=app) - - -class WebserverThread(threading.Thread): - - def __init__(self, addrport='', *args, **options): - threading.Thread.__init__(self) - self.addrport = addrport - self.args = args - self.options = options - - def run(self): - options = dict(self.options, use_reloader=False) - command = runserver.Command() - # see http://code.djangoproject.com/changeset/13319 - command.stdout, command.stderr = sys.stdout, sys.stderr - command.handle(self.addrport, *self.args, **options) - - -class Command(CeleryCommand): - """Run the celery curses event viewer.""" - args = '[optional port number, or ipaddr:port]' - options = (runserver.Command.option_list - + ev.get_options() - + ev.preload_options) - help = 'Starts Django Admin instance and celerycam in the same process.' - # see http://code.djangoproject.com/changeset/13319. - stdout, stderr = sys.stdout, sys.stderr - - def handle(self, addrport='', *args, **options): - """Handle the management command.""" - server = WebserverThread(addrport, *args, **options) - server.start() - options['camera'] = 'djcelery.snapshot.Camera' - options['prog_name'] = 'djcelerymon' - ev.run(*args, **options) diff --git a/awx/lib/site-packages/djcelery/managers.py b/awx/lib/site-packages/djcelery/managers.py deleted file mode 100644 index 3224802e4f..0000000000 --- a/awx/lib/site-packages/djcelery/managers.py +++ /dev/null @@ -1,245 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import warnings - -from functools import wraps -from itertools import count - -from django.db import connection -try: - from django.db import connections, router -except ImportError: # pre-Django 1.2 - connections = router = None # noqa - -from django.db import models -from django.db.models.query import QuerySet -from django.conf import settings - -from celery.utils.timeutils import maybe_timedelta - -from .db import commit_on_success, get_queryset, rollback_unless_managed -from .utils import now - - -class TxIsolationWarning(UserWarning): - pass - - -def transaction_retry(max_retries=1): - """Decorator for methods doing database operations. - - If the database operation fails, it will retry the operation - at most ``max_retries`` times. - - """ - def _outer(fun): - - @wraps(fun) - def _inner(*args, **kwargs): - _max_retries = kwargs.pop('exception_retry_count', max_retries) - for retries in count(0): - try: - return fun(*args, **kwargs) - except Exception: # pragma: no cover - # Depending on the database backend used we can experience - # various exceptions. E.g. psycopg2 raises an exception - # if some operation breaks the transaction, so saving - # the task result won't be possible until we rollback - # the transaction. - if retries >= _max_retries: - raise - try: - rollback_unless_managed() - except Exception: - pass - return _inner - - return _outer - - -def update_model_with_dict(obj, fields): - [setattr(obj, attr_name, attr_value) - for attr_name, attr_value in fields.items()] - obj.save() - return obj - - -class ExtendedQuerySet(QuerySet): - - def update_or_create(self, **kwargs): - obj, created = self.get_or_create(**kwargs) - - if not created: - fields = dict(kwargs.pop('defaults', {})) - fields.update(kwargs) - update_model_with_dict(obj, fields) - - return obj - - -class ExtendedManager(models.Manager): - - def get_queryset(self): - return ExtendedQuerySet(self.model) - get_query_set = get_queryset # Pre django 1.6 - - def update_or_create(self, **kwargs): - return get_queryset(self).update_or_create(**kwargs) - - def connection_for_write(self): - if connections: - return connections[router.db_for_write(self.model)] - return connection - - def connection_for_read(self): - if connections: - return connections[self.db] - return connection - - def current_engine(self): - try: - return settings.DATABASES[self.db]['ENGINE'] - except AttributeError: - return settings.DATABASE_ENGINE - - -class ResultManager(ExtendedManager): - - def get_all_expired(self, expires): - """Get all expired task results.""" - return self.filter(date_done__lt=now() - maybe_timedelta(expires)) - - def delete_expired(self, expires): - """Delete all expired taskset results.""" - meta = self.model._meta - with commit_on_success(): - self.get_all_expired(expires).update(hidden=True) - cursor = self.connection_for_write().cursor() - cursor.execute( - 'DELETE FROM {0.db_table} WHERE hidden=%s'.format(meta), - (True, ), - ) - - -class PeriodicTaskManager(ExtendedManager): - - def enabled(self): - return self.filter(enabled=True) - - -class TaskManager(ResultManager): - """Manager for :class:`celery.models.Task` models.""" - _last_id = None - - def get_task(self, task_id): - """Get task meta for task by ``task_id``. - - :keyword exception_retry_count: How many times to retry by - transaction rollback on exception. This could theoretically - happen in a race condition if another worker is trying to - create the same task. The default is to retry once. - - """ - try: - return self.get(task_id=task_id) - except self.model.DoesNotExist: - if self._last_id == task_id: - self.warn_if_repeatable_read() - self._last_id = task_id - return self.model(task_id=task_id) - - @transaction_retry(max_retries=2) - def store_result(self, task_id, result, status, - traceback=None, children=None): - """Store the result and status of a task. - - :param task_id: task id - - :param result: The return value of the task, or an exception - instance raised by the task. - - :param status: Task status. See - :meth:`celery.result.AsyncResult.get_status` for a list of - possible status values. - - :keyword traceback: The traceback at the point of exception (if the - task failed). - - :keyword children: List of serialized results of subtasks - of this task. - - :keyword exception_retry_count: How many times to retry by - transaction rollback on exception. This could theoretically - happen in a race condition if another worker is trying to - create the same task. The default is to retry twice. - - """ - return self.update_or_create(task_id=task_id, - defaults={'status': status, - 'result': result, - 'traceback': traceback, - 'meta': {'children': children}}) - - def warn_if_repeatable_read(self): - if 'mysql' in self.current_engine().lower(): - cursor = self.connection_for_read().cursor() - if cursor.execute('SELECT @@tx_isolation'): - isolation = cursor.fetchone()[0] - if isolation == 'REPEATABLE-READ': - warnings.warn(TxIsolationWarning( - 'Polling results with transaction isolation level ' - 'repeatable-read within the same transaction ' - 'may give outdated results. Be sure to commit the ' - 'transaction for each poll iteration.')) - - -class TaskSetManager(ResultManager): - """Manager for :class:`celery.models.TaskSet` models.""" - - def restore_taskset(self, taskset_id): - """Get the async result instance by taskset id.""" - try: - return self.get(taskset_id=taskset_id) - except self.model.DoesNotExist: - pass - - def delete_taskset(self, taskset_id): - """Delete a saved taskset result.""" - s = self.restore_taskset(taskset_id) - if s: - s.delete() - - @transaction_retry(max_retries=2) - def store_result(self, taskset_id, result): - """Store the async result instance of a taskset. - - :param taskset_id: task set id - - :param result: The return value of the taskset - - """ - return self.update_or_create(taskset_id=taskset_id, - defaults={'result': result}) - - -class TaskStateManager(ExtendedManager): - - def active(self): - return self.filter(hidden=False) - - def expired(self, states, expires, nowfun=now): - return self.filter(state__in=states, - tstamp__lte=nowfun() - maybe_timedelta(expires)) - - def expire_by_states(self, states, expires): - if expires is not None: - return self.expired(states, expires).update(hidden=True) - - def purge(self): - with commit_on_success(): - meta = self.model._meta - cursor = self.connection_for_write().cursor() - cursor.execute( - 'DELETE FROM {0.db_table} WHERE hidden=%s'.format(meta), - (True, ), - ) diff --git a/awx/lib/site-packages/djcelery/migrations/0001_initial.py b/awx/lib/site-packages/djcelery/migrations/0001_initial.py deleted file mode 100644 index ffe60491ad..0000000000 --- a/awx/lib/site-packages/djcelery/migrations/0001_initial.py +++ /dev/null @@ -1,206 +0,0 @@ -# encoding: utf-8 -from __future__ import absolute_import - -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models -from django.db import DatabaseError - - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding model 'TaskMeta' - db.create_table('celery_taskmeta', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('task_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), - ('status', self.gf('django.db.models.fields.CharField')(default='PENDING', max_length=50)), - ('result', self.gf('djcelery.picklefield.PickledObjectField')(default=None, null=True)), - ('date_done', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), - ('traceback', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),)) - db.send_create_signal('djcelery', ['TaskMeta']) - - # Adding model 'TaskSetMeta' - db.create_table('celery_tasksetmeta', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('taskset_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), - ('result', self.gf('djcelery.picklefield.PickledObjectField')()), - ('date_done', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),)) - db.send_create_signal('djcelery', ['TaskSetMeta']) - - # Adding model 'IntervalSchedule' - db.create_table('djcelery_intervalschedule', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('every', self.gf('django.db.models.fields.IntegerField')()), - ('period', self.gf('django.db.models.fields.CharField')(max_length=24)),)) - db.send_create_signal('djcelery', ['IntervalSchedule']) - - # Adding model 'CrontabSchedule' - db.create_table('djcelery_crontabschedule', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('minute', self.gf('django.db.models.fields.CharField')(default='*', max_length=64)), - ('hour', self.gf('django.db.models.fields.CharField')(default='*', max_length=64)), - ('day_of_week', self.gf('django.db.models.fields.CharField')(default='*', max_length=64)),)) - db.send_create_signal('djcelery', ['CrontabSchedule']) - - # Adding model 'PeriodicTasks' - db.create_table('djcelery_periodictasks', ( - ('ident', self.gf('django.db.models.fields.SmallIntegerField')(default=1, unique=True, primary_key=True)), - ('last_update', self.gf('django.db.models.fields.DateTimeField')()),)) - db.send_create_signal('djcelery', ['PeriodicTasks']) - - # Adding model 'PeriodicTask' - db.create_table('djcelery_periodictask', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=200)), - ('task', self.gf('django.db.models.fields.CharField')(max_length=200)), - ('interval', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['djcelery.IntervalSchedule'], null=True, blank=True)), - ('crontab', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['djcelery.CrontabSchedule'], null=True, blank=True)), - ('args', self.gf('django.db.models.fields.TextField')(default='[]', blank=True)), - ('kwargs', self.gf('django.db.models.fields.TextField')(default='{}', blank=True)), - ('queue', self.gf('django.db.models.fields.CharField')(default=None, max_length=200, null=True, blank=True)), - ('exchange', self.gf('django.db.models.fields.CharField')(default=None, max_length=200, null=True, blank=True)), - ('routing_key', self.gf('django.db.models.fields.CharField')(default=None, max_length=200, null=True, blank=True)), - ('expires', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), - ('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('last_run_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), - ('total_run_count', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), - ('date_changed', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),)) - db.send_create_signal('djcelery', ['PeriodicTask']) - - # Adding model 'WorkerState' - db.create_table('djcelery_workerstate', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('hostname', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), - ('last_heartbeat', self.gf('django.db.models.fields.DateTimeField')(null=True, db_index=True)),)) - db.send_create_signal('djcelery', ['WorkerState']) - - # Adding model 'TaskState' - db.create_table('djcelery_taskstate', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('state', self.gf('django.db.models.fields.CharField')(max_length=64, db_index=True)), - ('task_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=36)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=200, null=True, db_index=True)), - ('tstamp', self.gf('django.db.models.fields.DateTimeField')(db_index=True)), - ('args', self.gf('django.db.models.fields.TextField')(null=True)), - ('kwargs', self.gf('django.db.models.fields.TextField')(null=True)), - ('eta', self.gf('django.db.models.fields.DateTimeField')(null=True)), - ('expires', self.gf('django.db.models.fields.DateTimeField')(null=True)), - ('result', self.gf('django.db.models.fields.TextField')(null=True)), - ('traceback', self.gf('django.db.models.fields.TextField')(null=True)), - ('runtime', self.gf('django.db.models.fields.FloatField')(null=True)), - ('retries', self.gf('django.db.models.fields.IntegerField')(default=0)), - ('worker', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['djcelery.WorkerState'], null=True)), - ('hidden', self.gf('django.db.models.fields.BooleanField')(default=False, db_index=True)),)) - db.send_create_signal('djcelery', ['TaskState']) - - - def backwards(self, orm): - - # Deleting model 'TaskMeta' - db.delete_table('celery_taskmeta') - - # Deleting model 'TaskSetMeta' - db.delete_table('celery_tasksetmeta') - - # Deleting model 'IntervalSchedule' - db.delete_table('djcelery_intervalschedule') - - # Deleting model 'CrontabSchedule' - db.delete_table('djcelery_crontabschedule') - - # Deleting model 'PeriodicTasks' - db.delete_table('djcelery_periodictasks') - - # Deleting model 'PeriodicTask' - db.delete_table('djcelery_periodictask') - - # Deleting model 'WorkerState' - db.delete_table('djcelery_workerstate') - - # Deleting model 'TaskState' - db.delete_table('djcelery_taskstate') - - - models = { - 'djcelery.crontabschedule': { - 'Meta': {'object_name': 'CrontabSchedule'}, - 'day_of_week': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'hour': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'minute': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}) - }, - 'djcelery.intervalschedule': { - 'Meta': {'object_name': 'IntervalSchedule'}, - 'every': ('django.db.models.fields.IntegerField', [], {}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'period': ('django.db.models.fields.CharField', [], {'max_length': '24'}) - }, - 'djcelery.periodictask': { - 'Meta': {'object_name': 'PeriodicTask'}, - 'args': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}), - 'crontab': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.CrontabSchedule']", 'null': 'True', 'blank': 'True'}), - 'date_changed': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'exchange': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'interval': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.IntervalSchedule']", 'null': 'True', 'blank': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'default': "'{}'", 'blank': 'True'}), - 'last_run_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}), - 'queue': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'routing_key': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'task': ('django.db.models.fields.CharField', [], {'max_length': '200'}), - 'total_run_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) - }, - 'djcelery.periodictasks': { - 'Meta': {'object_name': 'PeriodicTasks'}, - 'ident': ('django.db.models.fields.SmallIntegerField', [], {'default': '1', 'unique': 'True', 'primary_key': 'True'}), - 'last_update': ('django.db.models.fields.DateTimeField', [], {}) - }, - 'djcelery.taskmeta': { - 'Meta': {'object_name': 'TaskMeta', 'db_table': "'celery_taskmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {'default': 'None', 'null': 'True'}), - 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '50'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) - }, - 'djcelery.tasksetmeta': { - 'Meta': {'object_name': 'TaskSetMeta', 'db_table': "'celery_tasksetmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {}), - 'taskset_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) - }, - 'djcelery.taskstate': { - 'Meta': {'ordering': "['-tstamp']", 'object_name': 'TaskState'}, - 'args': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'eta': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'db_index': 'True'}), - 'result': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'retries': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'runtime': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'tstamp': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), - 'worker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.WorkerState']", 'null': 'True'}) - }, - 'djcelery.workerstate': { - 'Meta': {'ordering': "['-last_heartbeat']", 'object_name': 'WorkerState'}, - 'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_heartbeat': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}) - } - } - - complete_apps = ['djcelery'] diff --git a/awx/lib/site-packages/djcelery/migrations/0002_v25_changes.py b/awx/lib/site-packages/djcelery/migrations/0002_v25_changes.py deleted file mode 100644 index d4e81371e9..0000000000 --- a/awx/lib/site-packages/djcelery/migrations/0002_v25_changes.py +++ /dev/null @@ -1,146 +0,0 @@ -# encoding: utf-8 -from __future__ import absolute_import -from south.db import db -from south.v2 import SchemaMigration -from django.db import connections - - -class Migration(SchemaMigration): - - def forwards(self, orm): - conn = connections[db.db_alias] - table_list = conn.introspection.get_table_list(conn.cursor()) - if 'celery_taskmeta' not in table_list: - self.create_celery_taskmeta() - if 'celery_tasksetmeta' not in table_list: - self.create_celery_tasksetmeta() - self.apply_current_migration() - - def create_celery_taskmeta(self): - # Adding model 'TaskMeta' - db.create_table('celery_taskmeta', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('task_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), - ('status', self.gf('django.db.models.fields.CharField')(default='PENDING', max_length=50)), - ('result', self.gf('djcelery.picklefield.PickledObjectField')(default=None, null=True)), - ('date_done', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), - ('traceback', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), - )) - db.send_create_signal('djcelery', ['TaskMeta']) - - def create_celery_tasksetmeta(self): - # Adding model 'TaskSetMeta' - db.create_table('celery_tasksetmeta', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('taskset_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), - ('result', self.gf('djcelery.picklefield.PickledObjectField')()), - ('date_done', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), - )) - db.send_create_signal('djcelery', ['TaskSetMeta']) - - def apply_current_migration(self): - # Adding field 'PeriodicTask.description' - db.add_column('djcelery_periodictask', 'description', self.gf('django.db.models.fields.TextField')(default='', blank=True), keep_default=False) - - # Adding field 'TaskMeta.hidden' - db.add_column('celery_taskmeta', 'hidden', self.gf('django.db.models.fields.BooleanField')(default=False, db_index=True), keep_default=False) - - # Adding field 'TaskSetMeta.hidden' - db.add_column('celery_tasksetmeta', 'hidden', self.gf('django.db.models.fields.BooleanField')(default=False, db_index=True), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'PeriodicTask.description' - db.delete_column('djcelery_periodictask', 'description') - - # Deleting field 'TaskMeta.hidden' - db.delete_column('celery_taskmeta', 'hidden') - - # Deleting field 'TaskSetMeta.hidden' - db.delete_column('celery_tasksetmeta', 'hidden') - - - models = { - 'djcelery.crontabschedule': { - 'Meta': {'object_name': 'CrontabSchedule'}, - 'day_of_week': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'hour': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'minute': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}) - }, - 'djcelery.intervalschedule': { - 'Meta': {'object_name': 'IntervalSchedule'}, - 'every': ('django.db.models.fields.IntegerField', [], {}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'period': ('django.db.models.fields.CharField', [], {'max_length': '24'}) - }, - 'djcelery.periodictask': { - 'Meta': {'object_name': 'PeriodicTask'}, - 'args': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}), - 'crontab': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.CrontabSchedule']", 'null': 'True', 'blank': 'True'}), - 'date_changed': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'exchange': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'interval': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.IntervalSchedule']", 'null': 'True', 'blank': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'default': "'{}'", 'blank': 'True'}), - 'last_run_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}), - 'queue': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'routing_key': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'task': ('django.db.models.fields.CharField', [], {'max_length': '200'}), - 'total_run_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) - }, - 'djcelery.periodictasks': { - 'Meta': {'object_name': 'PeriodicTasks'}, - 'ident': ('django.db.models.fields.SmallIntegerField', [], {'default': '1', 'unique': 'True', 'primary_key': 'True'}), - 'last_update': ('django.db.models.fields.DateTimeField', [], {}) - }, - 'djcelery.taskmeta': { - 'Meta': {'object_name': 'TaskMeta', 'db_table': "'celery_taskmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {'default': 'None', 'null': 'True'}), - 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '50'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) - }, - 'djcelery.tasksetmeta': { - 'Meta': {'object_name': 'TaskSetMeta', 'db_table': "'celery_tasksetmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {}), - 'taskset_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) - }, - 'djcelery.taskstate': { - 'Meta': {'ordering': "['-tstamp']", 'object_name': 'TaskState'}, - 'args': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'eta': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'db_index': 'True'}), - 'result': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'retries': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'runtime': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'tstamp': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), - 'worker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.WorkerState']", 'null': 'True'}) - }, - 'djcelery.workerstate': { - 'Meta': {'ordering': "['-last_heartbeat']", 'object_name': 'WorkerState'}, - 'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_heartbeat': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}) - } - } - - complete_apps = ['djcelery'] diff --git a/awx/lib/site-packages/djcelery/migrations/0003_v26_changes.py b/awx/lib/site-packages/djcelery/migrations/0003_v26_changes.py deleted file mode 100644 index 09bef1d1af..0000000000 --- a/awx/lib/site-packages/djcelery/migrations/0003_v26_changes.py +++ /dev/null @@ -1,112 +0,0 @@ -# encoding: utf-8 -from __future__ import absolute_import -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'CrontabSchedule.day_of_month' - db.add_column('djcelery_crontabschedule', 'day_of_month', self.gf('django.db.models.fields.CharField')(default='*', max_length=64), keep_default=False) - - # Adding field 'CrontabSchedule.month_of_year' - db.add_column('djcelery_crontabschedule', 'month_of_year', self.gf('django.db.models.fields.CharField')(default='*', max_length=64), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'CrontabSchedule.day_of_month' - db.delete_column('djcelery_crontabschedule', 'day_of_month') - - # Deleting field 'CrontabSchedule.month_of_year' - db.delete_column('djcelery_crontabschedule', 'month_of_year') - - - models = { - 'djcelery.crontabschedule': { - 'Meta': {'object_name': 'CrontabSchedule'}, - 'day_of_month': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'day_of_week': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'hour': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'minute': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'month_of_year': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}) - }, - 'djcelery.intervalschedule': { - 'Meta': {'object_name': 'IntervalSchedule'}, - 'every': ('django.db.models.fields.IntegerField', [], {}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'period': ('django.db.models.fields.CharField', [], {'max_length': '24'}) - }, - 'djcelery.periodictask': { - 'Meta': {'object_name': 'PeriodicTask'}, - 'args': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}), - 'crontab': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.CrontabSchedule']", 'null': 'True', 'blank': 'True'}), - 'date_changed': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'exchange': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'interval': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.IntervalSchedule']", 'null': 'True', 'blank': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'default': "'{}'", 'blank': 'True'}), - 'last_run_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}), - 'queue': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'routing_key': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'task': ('django.db.models.fields.CharField', [], {'max_length': '200'}), - 'total_run_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) - }, - 'djcelery.periodictasks': { - 'Meta': {'object_name': 'PeriodicTasks'}, - 'ident': ('django.db.models.fields.SmallIntegerField', [], {'default': '1', 'unique': 'True', 'primary_key': 'True'}), - 'last_update': ('django.db.models.fields.DateTimeField', [], {}) - }, - 'djcelery.taskmeta': { - 'Meta': {'object_name': 'TaskMeta', 'db_table': "'celery_taskmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {'default': 'None', 'null': 'True'}), - 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '50'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) - }, - 'djcelery.tasksetmeta': { - 'Meta': {'object_name': 'TaskSetMeta', 'db_table': "'celery_tasksetmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {}), - 'taskset_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) - }, - 'djcelery.taskstate': { - 'Meta': {'ordering': "['-tstamp']", 'object_name': 'TaskState'}, - 'args': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'eta': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'db_index': 'True'}), - 'result': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'retries': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'runtime': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'tstamp': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), - 'worker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.WorkerState']", 'null': 'True'}) - }, - 'djcelery.workerstate': { - 'Meta': {'ordering': "['-last_heartbeat']", 'object_name': 'WorkerState'}, - 'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_heartbeat': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}) - } - } - - complete_apps = ['djcelery'] diff --git a/awx/lib/site-packages/djcelery/migrations/0004_v30_changes.py b/awx/lib/site-packages/djcelery/migrations/0004_v30_changes.py deleted file mode 100644 index c28be7d9ad..0000000000 --- a/awx/lib/site-packages/djcelery/migrations/0004_v30_changes.py +++ /dev/null @@ -1,107 +0,0 @@ -# encoding: utf-8 -from __future__ import absolute_import -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding field 'TaskMeta.meta' - db.add_column('celery_taskmeta', 'meta', self.gf('djcelery.picklefield.PickledObjectField')(default=None, null=True), keep_default=False) - - - def backwards(self, orm): - - # Deleting field 'TaskMeta.meta' - db.delete_column('celery_taskmeta', 'meta') - - - models = { - 'djcelery.crontabschedule': { - 'Meta': {'object_name': 'CrontabSchedule'}, - 'day_of_month': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'day_of_week': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'hour': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'minute': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}), - 'month_of_year': ('django.db.models.fields.CharField', [], {'default': "'*'", 'max_length': '64'}) - }, - 'djcelery.intervalschedule': { - 'Meta': {'object_name': 'IntervalSchedule'}, - 'every': ('django.db.models.fields.IntegerField', [], {}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'period': ('django.db.models.fields.CharField', [], {'max_length': '24'}) - }, - 'djcelery.periodictask': { - 'Meta': {'object_name': 'PeriodicTask'}, - 'args': ('django.db.models.fields.TextField', [], {'default': "'[]'", 'blank': 'True'}), - 'crontab': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.CrontabSchedule']", 'null': 'True', 'blank': 'True'}), - 'date_changed': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'exchange': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'interval': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.IntervalSchedule']", 'null': 'True', 'blank': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'default': "'{}'", 'blank': 'True'}), - 'last_run_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}), - 'queue': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'routing_key': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'task': ('django.db.models.fields.CharField', [], {'max_length': '200'}), - 'total_run_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) - }, - 'djcelery.periodictasks': { - 'Meta': {'object_name': 'PeriodicTasks'}, - 'ident': ('django.db.models.fields.SmallIntegerField', [], {'default': '1', 'unique': 'True', 'primary_key': 'True'}), - 'last_update': ('django.db.models.fields.DateTimeField', [], {}) - }, - 'djcelery.taskmeta': { - 'Meta': {'object_name': 'TaskMeta', 'db_table': "'celery_taskmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'meta': ('djcelery.picklefield.PickledObjectField', [], {'default': 'None', 'null': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {'default': 'None', 'null': 'True'}), - 'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '50'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) - }, - 'djcelery.tasksetmeta': { - 'Meta': {'object_name': 'TaskSetMeta', 'db_table': "'celery_tasksetmeta'"}, - 'date_done': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'result': ('djcelery.picklefield.PickledObjectField', [], {}), - 'taskset_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) - }, - 'djcelery.taskstate': { - 'Meta': {'ordering': "['-tstamp']", 'object_name': 'TaskState'}, - 'args': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'eta': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), - 'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kwargs': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'db_index': 'True'}), - 'result': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'retries': ('django.db.models.fields.IntegerField', [], {'default': '0'}), - 'runtime': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'task_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}), - 'traceback': ('django.db.models.fields.TextField', [], {'null': 'True'}), - 'tstamp': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), - 'worker': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djcelery.WorkerState']", 'null': 'True'}) - }, - 'djcelery.workerstate': { - 'Meta': {'ordering': "['-last_heartbeat']", 'object_name': 'WorkerState'}, - 'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_heartbeat': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}) - } - } - - complete_apps = ['djcelery'] diff --git a/awx/lib/site-packages/djcelery/migrations/__init__.py b/awx/lib/site-packages/djcelery/migrations/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/models.py b/awx/lib/site-packages/djcelery/models.py deleted file mode 100644 index 02386e4975..0000000000 --- a/awx/lib/site-packages/djcelery/models.py +++ /dev/null @@ -1,372 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from datetime import timedelta, datetime -from time import time, mktime - -from django.core.exceptions import MultipleObjectsReturned, ValidationError -from django.db import models -from django.db.models import signals -from django.utils.translation import ugettext_lazy as _ - -from celery import schedules -from celery import states -from celery.events.state import heartbeat_expires -from celery.utils.timeutils import timedelta_seconds - -from . import managers -from .picklefield import PickledObjectField -from .utils import now - -TASK_STATE_CHOICES = zip(states.ALL_STATES, states.ALL_STATES) - - -class TaskMeta(models.Model): - """Task result/status.""" - task_id = models.CharField(_('task id'), max_length=255, unique=True) - status = models.CharField( - _('state'), - max_length=50, default=states.PENDING, choices=TASK_STATE_CHOICES, - ) - result = PickledObjectField(null=True, default=None, editable=False) - date_done = models.DateTimeField(_('done at'), auto_now=True) - traceback = models.TextField(_('traceback'), blank=True, null=True) - hidden = models.BooleanField(editable=False, default=False, db_index=True) - # TODO compression was enabled by mistake, we need to disable it - # but this is a backwards incompatible change that needs planning. - meta = PickledObjectField( - compress=True, null=True, default=None, editable=False, - ) - - objects = managers.TaskManager() - - class Meta: - verbose_name = _('task state') - verbose_name_plural = _('task states') - db_table = 'celery_taskmeta' - - def to_dict(self): - return {'task_id': self.task_id, - 'status': self.status, - 'result': self.result, - 'date_done': self.date_done, - 'traceback': self.traceback, - 'children': (self.meta or {}).get('children')} - - def __unicode__(self): - return '<Task: {0.task_id} state={0.status}>'.format(self) - - -class TaskSetMeta(models.Model): - """TaskSet result""" - taskset_id = models.CharField(_('group id'), max_length=255, unique=True) - result = PickledObjectField() - date_done = models.DateTimeField(_('created at'), auto_now=True) - hidden = models.BooleanField(editable=False, default=False, db_index=True) - - objects = managers.TaskSetManager() - - class Meta: - """Model meta-data.""" - verbose_name = _('saved group result') - verbose_name_plural = _('saved group results') - db_table = 'celery_tasksetmeta' - - def to_dict(self): - return {'taskset_id': self.taskset_id, - 'result': self.result, - 'date_done': self.date_done} - - def __unicode__(self): - return '<TaskSet: {0.taskset_id}>'.format(self) - - -PERIOD_CHOICES = (('days', _('Days')), - ('hours', _('Hours')), - ('minutes', _('Minutes')), - ('seconds', _('Seconds')), - ('microseconds', _('Microseconds'))) - - -class IntervalSchedule(models.Model): - every = models.IntegerField(_('every'), null=False) - period = models.CharField( - _('period'), max_length=24, choices=PERIOD_CHOICES, - ) - - class Meta: - verbose_name = _('interval') - verbose_name_plural = _('intervals') - ordering = ['period', 'every'] - - @property - def schedule(self): - return schedules.schedule(timedelta(**{self.period: self.every})) - - @classmethod - def from_schedule(cls, schedule, period='seconds'): - every = timedelta_seconds(schedule.run_every) - try: - return cls.objects.get(every=every, period=period) - except cls.DoesNotExist: - return cls(every=every, period=period) - except MultipleObjectsReturned: - cls.objects.filter(every=every, period=period).delete() - return cls(every=every, period=period) - - def __unicode__(self): - if self.every == 1: - return _('every {0.period_singular}').format(self) - return _('every {0.every} {0.period}').format(self) - - @property - def period_singular(self): - return self.period[:-1] - - -class CrontabSchedule(models.Model): - minute = models.CharField(_('minute'), max_length=64, default='*') - hour = models.CharField(_('hour'), max_length=64, default='*') - day_of_week = models.CharField( - _('day of week'), max_length=64, default='*', - ) - day_of_month = models.CharField( - _('day of month'), max_length=64, default='*', - ) - month_of_year = models.CharField( - _('month of year'), max_length=64, default='*', - ) - - class Meta: - verbose_name = _('crontab') - verbose_name_plural = _('crontabs') - ordering = ['month_of_year', 'day_of_month', - 'day_of_week', 'hour', 'minute'] - - def __unicode__(self): - rfield = lambda f: f and str(f).replace(' ', '') or '*' - return '{0} {1} {2} {3} {4} (m/h/d/dM/MY)'.format( - rfield(self.minute), rfield(self.hour), rfield(self.day_of_week), - rfield(self.day_of_month), rfield(self.month_of_year), - ) - - @property - def schedule(self): - return schedules.crontab(minute=self.minute, - hour=self.hour, - day_of_week=self.day_of_week, - day_of_month=self.day_of_month, - month_of_year=self.month_of_year) - - @classmethod - def from_schedule(cls, schedule): - spec = {'minute': schedule._orig_minute, - 'hour': schedule._orig_hour, - 'day_of_week': schedule._orig_day_of_week, - 'day_of_month': schedule._orig_day_of_month, - 'month_of_year': schedule._orig_month_of_year} - try: - return cls.objects.get(**spec) - except cls.DoesNotExist: - return cls(**spec) - except MultipleObjectsReturned: - cls.objects.filter(**spec).delete() - return cls(**spec) - - -class PeriodicTasks(models.Model): - ident = models.SmallIntegerField(default=1, primary_key=True, unique=True) - last_update = models.DateTimeField(null=False) - - objects = managers.ExtendedManager() - - @classmethod - def changed(cls, instance, **kwargs): - if not instance.no_changes: - cls.objects.update_or_create(ident=1, - defaults={'last_update': now()}) - - @classmethod - def last_change(cls): - try: - return cls.objects.get(ident=1).last_update - except cls.DoesNotExist: - pass - - -class PeriodicTask(models.Model): - name = models.CharField( - _('name'), max_length=200, unique=True, - help_text=_('Useful description'), - ) - task = models.CharField(_('task name'), max_length=200) - interval = models.ForeignKey( - IntervalSchedule, - null=True, blank=True, verbose_name=_('interval'), - ) - crontab = models.ForeignKey( - CrontabSchedule, null=True, blank=True, verbose_name=_('crontab'), - help_text=_('Use one of interval/crontab'), - ) - args = models.TextField( - _('Arguments'), blank=True, default='[]', - help_text=_('JSON encoded positional arguments'), - ) - kwargs = models.TextField( - _('Keyword arguments'), blank=True, default='{}', - help_text=_('JSON encoded keyword arguments'), - ) - queue = models.CharField( - _('queue'), max_length=200, blank=True, null=True, default=None, - help_text=_('Queue defined in CELERY_QUEUES'), - ) - exchange = models.CharField( - _('exchange'), max_length=200, blank=True, null=True, default=None, - ) - routing_key = models.CharField( - _('routing key'), max_length=200, blank=True, null=True, default=None, - ) - expires = models.DateTimeField( - _('expires'), blank=True, null=True, - ) - enabled = models.BooleanField( - _('enabled'), default=True, - ) - last_run_at = models.DateTimeField( - auto_now=False, auto_now_add=False, - editable=False, blank=True, null=True, - ) - total_run_count = models.PositiveIntegerField( - default=0, editable=False, - ) - date_changed = models.DateTimeField(auto_now=True) - description = models.TextField(_('description'), blank=True) - - objects = managers.PeriodicTaskManager() - no_changes = False - - class Meta: - verbose_name = _('periodic task') - verbose_name_plural = _('periodic tasks') - - def validate_unique(self, *args, **kwargs): - super(PeriodicTask, self).validate_unique(*args, **kwargs) - if not self.interval and not self.crontab: - raise ValidationError( - {'interval': ['One of interval or crontab must be set.']}) - if self.interval and self.crontab: - raise ValidationError( - {'crontab': ['Only one of interval or crontab must be set']}) - - def save(self, *args, **kwargs): - self.exchange = self.exchange or None - self.routing_key = self.routing_key or None - self.queue = self.queue or None - if not self.enabled: - self.last_run_at = None - super(PeriodicTask, self).save(*args, **kwargs) - - def __unicode__(self): - fmt = '{0.name}: {{no schedule}}' - if self.interval: - fmt = '{0.name}: {0.interval}' - if self.crontab: - fmt = '{0.name}: {0.crontab}' - return fmt.format(self) - - @property - def schedule(self): - if self.interval: - return self.interval.schedule - if self.crontab: - return self.crontab.schedule - -signals.pre_delete.connect(PeriodicTasks.changed, sender=PeriodicTask) -signals.pre_save.connect(PeriodicTasks.changed, sender=PeriodicTask) - - -class WorkerState(models.Model): - hostname = models.CharField(_('hostname'), max_length=255, unique=True) - last_heartbeat = models.DateTimeField(_('last heartbeat'), null=True, - db_index=True) - - objects = managers.ExtendedManager() - - class Meta: - """Model meta-data.""" - verbose_name = _('worker') - verbose_name_plural = _('workers') - get_latest_by = 'last_heartbeat' - ordering = ['-last_heartbeat'] - - def __unicode__(self): - return self.hostname - - def __repr__(self): - return '<WorkerState: {0.hostname}>'.format(self) - - def is_alive(self): - if self.last_heartbeat: - return time() < heartbeat_expires(self.heartbeat_timestamp) - return False - - @property - def heartbeat_timestamp(self): - return mktime(self.last_heartbeat.timetuple()) - - -class TaskState(models.Model): - state = models.CharField( - _('state'), max_length=64, choices=TASK_STATE_CHOICES, db_index=True, - ) - task_id = models.CharField(_('UUID'), max_length=36, unique=True) - name = models.CharField( - _('name'), max_length=200, null=True, db_index=True, - ) - tstamp = models.DateTimeField(_('event received at'), db_index=True) - args = models.TextField(_('Arguments'), null=True) - kwargs = models.TextField(_('Keyword arguments'), null=True) - eta = models.DateTimeField(_('ETA'), null=True) - expires = models.DateTimeField(_('expires'), null=True) - result = models.TextField(_('result'), null=True) - traceback = models.TextField(_('traceback'), null=True) - runtime = models.FloatField( - _('execution time'), null=True, - help_text=_('in seconds if task succeeded'), - ) - retries = models.IntegerField(_('number of retries'), default=0) - worker = models.ForeignKey( - WorkerState, null=True, verbose_name=_('worker'), - ) - hidden = models.BooleanField(editable=False, default=False, db_index=True) - - objects = managers.TaskStateManager() - - class Meta: - """Model meta-data.""" - verbose_name = _('task') - verbose_name_plural = _('tasks') - get_latest_by = 'tstamp' - ordering = ['-tstamp'] - - def save(self, *args, **kwargs): - if self.eta is not None: - self.eta = datetime.utcfromtimestamp(float('%d.%s' % ( - mktime(self.eta.timetuple()), self.eta.microsecond, - ))) - if self.expires is not None: - self.expires = datetime.utcfromtimestamp(float('%d.%s' % ( - mktime(self.expires.timetuple()), self.expires.microsecond, - ))) - super(TaskState, self).save(*args, **kwargs) - - def __unicode__(self): - name = self.name or 'UNKNOWN' - s = '{0.state:<10} {0.task_id:<36} {1}'.format(self, name) - if self.eta: - s += ' eta:{0.eta}'.format(self) - return s - - def __repr__(self): - return '<TaskState: {0.state} {1}[{0.task_id}] ts:{0.tstamp}>'.format( - self, self.name or 'UNKNOWN', - ) diff --git a/awx/lib/site-packages/djcelery/mon.py b/awx/lib/site-packages/djcelery/mon.py deleted file mode 100644 index c46d7cd42a..0000000000 --- a/awx/lib/site-packages/djcelery/mon.py +++ /dev/null @@ -1,72 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import os -import sys -import types - -from celery.app.defaults import strtobool -from celery.utils import import_from_cwd - -DEFAULT_APPS = ('django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.admin', - 'django.contrib.admindocs', - 'djcelery') - -DEFAULTS = {'ROOT_URLCONF': 'djcelery.monproj.urls', - 'DATABASE_ENGINE': 'sqlite3', - 'DATABASE_NAME': 'djcelerymon.db', - 'DATABASES': {'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'djcelerymon.db'}}, - 'BROKER_URL': 'amqp://', - 'SITE_ID': 1, - 'INSTALLED_APPS': DEFAULT_APPS, - 'DEBUG': strtobool(os.environ.get('DJCELERYMON_DEBUG', '0'))} - - -def default_settings(name='__default_settings__'): - c = type(name, (types.ModuleType, ), DEFAULTS)(name) - c.__dict__.update({'__file__': __file__}) - sys.modules[name] = c - return name - - -def configure(): - from celery import current_app - from celery.loaders.default import DEFAULT_CONFIG_MODULE - from django.conf import settings - - app = current_app - conf = {} - - if not settings.configured: - if 'loader' in app.__dict__ and app.loader.configured: - conf = current_app.loader.conf - else: - os.environ.pop('CELERY_LOADER', None) - settings_module = os.environ.get('CELERY_CONFIG_MODULE', - DEFAULT_CONFIG_MODULE) - try: - import_from_cwd(settings_module) - except ImportError: - settings_module = default_settings() - settings.configure(SETTINGS_MODULE=settings_module, - **dict(DEFAULTS, **conf)) - - -def run_monitor(argv): - from .management.commands import djcelerymon - djcelerymon.Command().run_from_argv([argv[0], 'djcelerymon'] + argv[1:]) - - -def main(argv=sys.argv): - from django.core import management - os.environ['CELERY_LOADER'] = 'default' - configure() - management.call_command('syncdb') - run_monitor(argv) - -if __name__ == '__main__': - main() diff --git a/awx/lib/site-packages/djcelery/monproj/__init__.py b/awx/lib/site-packages/djcelery/monproj/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/monproj/urls.py b/awx/lib/site-packages/djcelery/monproj/urls.py deleted file mode 100644 index c65e0fb744..0000000000 --- a/awx/lib/site-packages/djcelery/monproj/urls.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -try: - from django.conf.urls import (patterns, include, url, - handler500, handler404) -except ImportError: - from django.conf.urls.defaults import (patterns, include, url, # noqa - handler500, handler404) -from django.contrib import admin - -admin.autodiscover() - -urlpatterns = patterns( - '', - # Uncomment the admin/doc line below and add 'django.contrib.admindocs' - # to INSTALLED_APPS to enable admin documentation: - (r'^doc/', include('django.contrib.admindocs.urls')), - - (r'', include(admin.site.urls)), -) diff --git a/awx/lib/site-packages/djcelery/picklefield.py b/awx/lib/site-packages/djcelery/picklefield.py deleted file mode 100644 index 0156cd4eb2..0000000000 --- a/awx/lib/site-packages/djcelery/picklefield.py +++ /dev/null @@ -1,119 +0,0 @@ -""" - Based on django-picklefield which is - Copyright (c) 2009-2010 Gintautas Miliauskas - but some improvements including not deepcopying values. - - Provides an implementation of a pickled object field. - Such fields can contain any picklable objects. - - The implementation is taken and adopted from Django snippet #1694 - <http://www.djangosnippets.org/snippets/1694/> by Taavi Taijala, - which is in turn based on Django snippet #513 - <http://www.djangosnippets.org/snippets/513/> by Oliver Beattie. - -""" -from __future__ import absolute_import, unicode_literals - -from base64 import b64encode, b64decode -from zlib import compress, decompress - -from celery.five import with_metaclass -from celery.utils.serialization import pickle -from kombu.utils.encoding import bytes_to_str, str_to_bytes - -from django.db import models - -try: - from django.utils.encoding import force_text -except ImportError: - from django.utils.encoding import force_unicode as force_text # noqa - -DEFAULT_PROTOCOL = 2 - -NO_DECOMPRESS_HEADER = b'\x1e\x00r8d9qwwerwhA@' - - -@with_metaclass(models.SubfieldBase, skip_attrs=set([ - 'db_type', - 'get_db_prep_save' - ])) -class BaseField(models.Field): - pass - - -class PickledObject(str): - pass - - -def maybe_compress(value, do_compress=False): - if do_compress: - return compress(str_to_bytes(value)) - return value - - -def maybe_decompress(value, do_decompress=False): - if do_decompress: - if str_to_bytes(value[:15]) != NO_DECOMPRESS_HEADER: - return decompress(str_to_bytes(value)) - return value - - -def encode(value, compress_object=False, pickle_protocol=DEFAULT_PROTOCOL): - return bytes_to_str(b64encode(maybe_compress( - pickle.dumps(value, pickle_protocol), compress_object), - )) - - -def decode(value, compress_object=False): - return pickle.loads(maybe_decompress(b64decode(value), compress_object)) - - -class PickledObjectField(BaseField): - - def __init__(self, compress=False, protocol=DEFAULT_PROTOCOL, - *args, **kwargs): - self.compress = compress - self.protocol = protocol - kwargs.setdefault('editable', False) - super(PickledObjectField, self).__init__(*args, **kwargs) - - def get_default(self): - if self.has_default(): - return self.default() if callable(self.default) else self.default - return super(PickledObjectField, self).get_default() - - def to_python(self, value): - if value is not None: - try: - return decode(value, self.compress) - except Exception: - if isinstance(value, PickledObject): - raise - return value - - def get_db_prep_value(self, value, **kwargs): - if value is not None and not isinstance(value, PickledObject): - return force_text(encode(value, self.compress, self.protocol)) - return value - - def value_to_string(self, obj): - return self.get_db_prep_value(self._get_val_from_obj(obj)) - - def get_internal_type(self): - return 'TextField' - - def get_db_prep_lookup(self, lookup_type, value, *args, **kwargs): - if lookup_type not in ['exact', 'in', 'isnull']: - raise TypeError( - 'Lookup type {0} is not supported.'.format(lookup_type)) - return super(PickledObjectField, self) \ - .get_db_prep_lookup(*args, **kwargs) - -try: - from south.modelsinspector import add_introspection_rules -except ImportError: - pass -else: - add_introspection_rules( - [], [r'^djcelery\.picklefield\.PickledObjectField'], - ) diff --git a/awx/lib/site-packages/djcelery/schedulers.py b/awx/lib/site-packages/djcelery/schedulers.py deleted file mode 100644 index 06c252985d..0000000000 --- a/awx/lib/site-packages/djcelery/schedulers.py +++ /dev/null @@ -1,255 +0,0 @@ -from __future__ import absolute_import - -import logging - -from multiprocessing.util import Finalize - -from anyjson import loads, dumps -from celery import current_app -from celery import schedules -from celery.beat import Scheduler, ScheduleEntry -from celery.utils.encoding import safe_str, safe_repr -from celery.utils.log import get_logger -from celery.utils.timeutils import is_naive - -from django.db import transaction -from django.core.exceptions import ObjectDoesNotExist - -from .db import commit_on_success -from .models import (PeriodicTask, PeriodicTasks, - CrontabSchedule, IntervalSchedule) -from .utils import DATABASE_ERRORS, make_aware - -# This scheduler must wake up more frequently than the -# regular of 5 minutes because it needs to take external -# changes to the schedule into account. -DEFAULT_MAX_INTERVAL = 5 # seconds - -ADD_ENTRY_ERROR = """\ -Couldn't add entry %r to database schedule: %r. Contents: %r -""" - -logger = get_logger(__name__) -debug, info, error = logger.debug, logger.info, logger.error - - -class ModelEntry(ScheduleEntry): - model_schedules = ((schedules.crontab, CrontabSchedule, 'crontab'), - (schedules.schedule, IntervalSchedule, 'interval')) - save_fields = ['last_run_at', 'total_run_count', 'no_changes'] - - def __init__(self, model): - self.app = current_app._get_current_object() - self.name = model.name - self.task = model.task - try: - self.schedule = model.schedule - except model.DoesNotExist: - logger.error('Schedule was removed from database') - logger.warning('Disabling %s', self.name) - self._disable(model) - try: - self.args = loads(model.args or '[]') - self.kwargs = loads(model.kwargs or '{}') - except ValueError: - logging.error('Failed to serialize arguments for %s.', self.name, - exc_info=1) - logging.warning('Disabling %s', self.name) - self._disable(model) - - self.options = {'queue': model.queue, - 'exchange': model.exchange, - 'routing_key': model.routing_key, - 'expires': model.expires} - self.total_run_count = model.total_run_count - self.model = model - - if not model.last_run_at: - model.last_run_at = self._default_now() - orig = self.last_run_at = model.last_run_at - if not is_naive(self.last_run_at): - self.last_run_at = self.last_run_at.replace(tzinfo=None) - assert orig.hour == self.last_run_at.hour # timezone sanity - - def _disable(self, model): - model.no_changes = True - model.enabled = False - model.save() - - def is_due(self): - if not self.model.enabled: - return False, 5.0 # 5 second delay for re-enable. - return self.schedule.is_due(self.last_run_at) - - def _default_now(self): - return self.app.now() - - def __next__(self): - self.model.last_run_at = self.app.now() - self.model.total_run_count += 1 - self.model.no_changes = True - return self.__class__(self.model) - next = __next__ # for 2to3 - - def save(self): - # Object may not be synchronized, so only - # change the fields we care about. - obj = self.model._default_manager.get(pk=self.model.pk) - for field in self.save_fields: - setattr(obj, field, getattr(self.model, field)) - obj.last_run_at = make_aware(obj.last_run_at) - obj.save() - - @classmethod - def to_model_schedule(cls, schedule): - for schedule_type, model_type, model_field in cls.model_schedules: - schedule = schedules.maybe_schedule(schedule) - if isinstance(schedule, schedule_type): - model_schedule = model_type.from_schedule(schedule) - model_schedule.save() - return model_schedule, model_field - raise ValueError( - 'Cannot convert schedule type {0!r} to model'.format(schedule)) - - @classmethod - def from_entry(cls, name, skip_fields=('relative', 'options'), **entry): - options = entry.get('options') or {} - fields = dict(entry) - for skip_field in skip_fields: - fields.pop(skip_field, None) - schedule = fields.pop('schedule') - model_schedule, model_field = cls.to_model_schedule(schedule) - fields[model_field] = model_schedule - fields['args'] = dumps(fields.get('args') or []) - fields['kwargs'] = dumps(fields.get('kwargs') or {}) - fields['queue'] = options.get('queue') - fields['exchange'] = options.get('exchange') - fields['routing_key'] = options.get('routing_key') - return cls(PeriodicTask._default_manager.update_or_create( - name=name, defaults=fields, - )) - - def __repr__(self): - return '<ModelEntry: {0} {1}(*{2}, **{3}) {{4}}>'.format( - safe_str(self.name), self.task, safe_repr(self.args), - safe_repr(self.kwargs), self.schedule, - ) - - -class DatabaseScheduler(Scheduler): - Entry = ModelEntry - Model = PeriodicTask - Changes = PeriodicTasks - _schedule = None - _last_timestamp = None - _initial_read = False - - def __init__(self, *args, **kwargs): - self._dirty = set() - self._finalize = Finalize(self, self.sync, exitpriority=5) - Scheduler.__init__(self, *args, **kwargs) - self.max_interval = ( - kwargs.get('max_interval') or - self.app.conf.CELERYBEAT_MAX_LOOP_INTERVAL or - DEFAULT_MAX_INTERVAL) - - def setup_schedule(self): - self.install_default_entries(self.schedule) - self.update_from_dict(self.app.conf.CELERYBEAT_SCHEDULE) - - def all_as_schedule(self): - debug('DatabaseScheduler: Fetching database schedule') - s = {} - for model in self.Model.objects.enabled(): - try: - s[model.name] = self.Entry(model) - except ValueError: - pass - return s - - def schedule_changed(self): - try: - # If MySQL is running with transaction isolation level - # REPEATABLE-READ (default), then we won't see changes done by - # other transactions until the current transaction is - # committed (Issue #41). - try: - transaction.commit() - except transaction.TransactionManagementError: - pass # not in transaction management. - - last, ts = self._last_timestamp, self.Changes.last_change() - except DATABASE_ERRORS as exc: - error('Database gave error: %r', exc, exc_info=1) - return False - try: - if ts and ts > (last if last else ts): - return True - finally: - self._last_timestamp = ts - return False - - def reserve(self, entry): - new_entry = Scheduler.reserve(self, entry) - # Need to store entry by name, because the entry may change - # in the mean time. - self._dirty.add(new_entry.name) - return new_entry - - def sync(self): - info('Writing entries...') - _tried = set() - try: - with commit_on_success(): - while self._dirty: - try: - name = self._dirty.pop() - _tried.add(name) - self.schedule[name].save() - except (KeyError, ObjectDoesNotExist): - pass - except DATABASE_ERRORS as exc: - # retry later - self._dirty |= _tried - error('Database error while sync: %r', exc, exc_info=1) - - def update_from_dict(self, dict_): - s = {} - for name, entry in dict_.items(): - try: - s[name] = self.Entry.from_entry(name, **entry) - except Exception as exc: - error(ADD_ENTRY_ERROR, name, exc, entry) - self.schedule.update(s) - - def install_default_entries(self, data): - entries = {} - if self.app.conf.CELERY_TASK_RESULT_EXPIRES: - entries.setdefault( - 'celery.backend_cleanup', { - 'task': 'celery.backend_cleanup', - 'schedule': schedules.crontab('0', '4', '*'), - 'options': {'expires': 12 * 3600}, - }, - ) - self.update_from_dict(entries) - - @property - def schedule(self): - update = False - if not self._initial_read: - debug('DatabaseScheduler: intial read') - update = True - self._initial_read = True - elif self.schedule_changed(): - info('DatabaseScheduler: Schedule changed.') - update = True - - if update: - self.sync() - self._schedule = self.all_as_schedule() - if logger.isEnabledFor(logging.DEBUG): - debug('Current schedule:\n%s', '\n'.join( - repr(entry) for entry in self._schedule.itervalues()), - ) - return self._schedule diff --git a/awx/lib/site-packages/djcelery/snapshot.py b/awx/lib/site-packages/djcelery/snapshot.py deleted file mode 100644 index f5227a26c1..0000000000 --- a/awx/lib/site-packages/djcelery/snapshot.py +++ /dev/null @@ -1,150 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from collections import defaultdict -from datetime import datetime, timedelta - -from django.conf import settings - -from celery import states -from celery.events.state import Task -from celery.events.snapshot import Polaroid -from celery.five import monotonic -from celery.utils.log import get_logger -from celery.utils.timeutils import maybe_iso8601 - -from .models import WorkerState, TaskState -from .utils import maybe_make_aware - -WORKER_UPDATE_FREQ = 60 # limit worker timestamp write freq. -SUCCESS_STATES = frozenset([states.SUCCESS]) - -# Expiry can be timedelta or None for never expire. -EXPIRE_SUCCESS = getattr(settings, 'CELERYCAM_EXPIRE_SUCCESS', - timedelta(days=1)) -EXPIRE_ERROR = getattr(settings, 'CELERYCAM_EXPIRE_ERROR', - timedelta(days=3)) -EXPIRE_PENDING = getattr(settings, 'CELERYCAM_EXPIRE_PENDING', - timedelta(days=5)) -NOT_SAVED_ATTRIBUTES = frozenset(['name', 'args', 'kwargs', 'eta']) - -logger = get_logger(__name__) -debug = logger.debug - - -def aware_tstamp(secs): - """Event timestamps uses the local timezone.""" - return maybe_make_aware(datetime.utcfromtimestamp(secs)) - - -class Camera(Polaroid): - TaskState = TaskState - WorkerState = WorkerState - - clear_after = True - worker_update_freq = WORKER_UPDATE_FREQ - expire_states = { - SUCCESS_STATES: EXPIRE_SUCCESS, - states.EXCEPTION_STATES: EXPIRE_ERROR, - states.UNREADY_STATES: EXPIRE_PENDING, - } - - def __init__(self, *args, **kwargs): - super(Camera, self).__init__(*args, **kwargs) - self._last_worker_write = defaultdict(lambda: (None, None)) - - def get_heartbeat(self, worker): - try: - heartbeat = worker.heartbeats[-1] - except IndexError: - return - # Check for timezone settings - if getattr(settings, "USE_TZ", False): - return aware_tstamp(heartbeat) - return datetime.fromtimestamp(heartbeat) - - def handle_worker(self, hostname_worker): - (hostname, worker) = hostname_worker - last_write, obj = self._last_worker_write[hostname] - if not last_write or \ - monotonic() - last_write > self.worker_update_freq: - obj = self.WorkerState.objects.update_or_create( - hostname=hostname, - defaults={'last_heartbeat': self.get_heartbeat(worker)}, - ) - self._last_worker_write[hostname] = (monotonic(), obj) - return obj - - def handle_task(self, uuid_task, worker=None): - """Handle snapshotted event.""" - uuid, task = uuid_task - if task.worker and task.worker.hostname: - worker = self.handle_worker( - (task.worker.hostname, task.worker), - ) - - defaults = { - 'name': task.name, - 'args': task.args, - 'kwargs': task.kwargs, - 'eta': maybe_make_aware(maybe_iso8601(task.eta)), - 'expires': maybe_make_aware(maybe_iso8601(task.expires)), - 'state': task.state, - 'tstamp': aware_tstamp(task.timestamp), - 'result': task.result or task.exception, - 'traceback': task.traceback, - 'runtime': task.runtime, - 'worker': worker - } - # Some fields are only stored in the RECEIVED event, - # so we should remove these from default values, - # so that they are not overwritten by subsequent states. - [defaults.pop(attr, None) for attr in NOT_SAVED_ATTRIBUTES - if defaults[attr] is None] - return self.update_task(task.state, - task_id=uuid, defaults=defaults) - - def update_task(self, state, **kwargs): - objects = self.TaskState.objects - defaults = kwargs.pop('defaults', None) or {} - if not defaults.get('name'): - return - obj, created = objects.get_or_create(defaults=defaults, **kwargs) - if created: - return obj - else: - if states.state(state) < states.state(obj.state): - keep = Task.merge_rules[states.RECEIVED] - defaults = dict( - (k, v) for k, v in defaults.items() - if k not in keep - ) - - for k, v in defaults.items(): - setattr(obj, k, v) - for datefield in ('eta', 'expires', 'tstamp'): - # Brute force trying to fix #183 - setattr(obj, datefield, maybe_make_aware(getattr(obj, datefield))) - obj.save() - - return obj - - def on_shutter(self, state, commit_every=100): - - def _handle_tasks(): - for i, task in enumerate(state.tasks.items()): - self.handle_task(task) - - for worker in state.workers.items(): - self.handle_worker(worker) - _handle_tasks() - - def on_cleanup(self): - expired = (self.TaskState.objects.expire_by_states(states, expires) - for states, expires in self.expire_states.items()) - dirty = sum(item for item in expired if item is not None) - if dirty: - debug('Cleanup: Marked %s objects as dirty.', dirty) - self.TaskState.objects.purge() - debug('Cleanup: %s objects purged.', dirty) - return dirty - return 0 diff --git a/awx/lib/site-packages/djcelery/tests/__init__.py b/awx/lib/site-packages/djcelery/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/tests/req.py b/awx/lib/site-packages/djcelery/tests/req.py deleted file mode 100644 index 17692b8a01..0000000000 --- a/awx/lib/site-packages/djcelery/tests/req.py +++ /dev/null @@ -1,74 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from django.test import Client -from django.core.handlers.wsgi import WSGIRequest -from django.core.handlers.base import BaseHandler - -from celery.utils.compat import WhateverIO - - -class RequestFactory(Client): - """Class that lets you create mock Request objects for use in testing. - - Usage: - - rf = RequestFactory() - get_request = rf.get('/hello/') - post_request = rf.post('/submit/', {'foo': 'bar'}) - - This class re-uses the django.test.client.Client interface, docs here: - http://www.djangoproject.com/documentation/testing/#the-test-client - - Once you have a request object you can pass it to any view function, - just as if that view had been hooked up using a URLconf. - - """ - - def request(self, **request): - """Similar to parent class, but returns the request object as - soon as it has created it.""" - environ = { - 'HTTP_COOKIE': self.cookies, - 'HTTP_USER_AGENT': 'Django UnitTest Client 1.0', - 'REMOTE_ADDR': '127.0.0.1', - 'PATH_INFO': '/', - 'QUERY_STRING': '', - 'REQUEST_METHOD': 'GET', - 'SCRIPT_NAME': '', - 'SERVER_NAME': 'testserver', - 'SERVER_PORT': 80, - 'SERVER_PROTOCOL': 'HTTP/1.1', - 'wsgi.input': WhateverIO(), - } - - environ.update(self.defaults) - environ.update(request) - return WSGIRequest(environ) - - -class MockRequest(object): - - def __init__(self): - handler = BaseHandler() - handler.load_middleware() - self.request_factory = RequestFactory() - self.middleware = handler._request_middleware - - def _make_request(self, request_method, *args, **kwargs): - request_method_handler = getattr(self.request_factory, request_method) - request = request_method_handler(*args, **kwargs) - [middleware_processor(request) - for middleware_processor in self.middleware] - return request - - def get(self, *args, **kwargs): - return self._make_request('get', *args, **kwargs) - - def post(self, *args, **kwargs): - return self._make_request('post', *args, **kwargs) - - def put(self, *args, **kwargs): - return self._make_request('put', *args, **kwargs) - - def delete(self, *args, **kwargs): - return self._make_request('delete', *args, **kwargs) diff --git a/awx/lib/site-packages/djcelery/tests/test_backends/__init__.py b/awx/lib/site-packages/djcelery/tests/test_backends/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/djcelery/tests/test_backends/test_cache.py b/awx/lib/site-packages/djcelery/tests/test_backends/test_cache.py deleted file mode 100644 index f7b4cbc91a..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_backends/test_cache.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import sys - -from datetime import timedelta - -from billiard.einfo import ExceptionInfo -import django -from django.core.cache.backends.base import InvalidCacheBackendError - -from celery import result -from celery import states -from celery.utils import gen_unique_id - -from djcelery.app import app -from djcelery.backends.cache import CacheBackend -from djcelery.tests.utils import unittest - - -class SomeClass(object): - - def __init__(self, data): - self.data = data - - -class test_CacheBackend(unittest.TestCase): - - def test_mark_as_done(self): - cb = CacheBackend(app=app) - - tid = gen_unique_id() - - self.assertEqual(cb.get_status(tid), states.PENDING) - self.assertIsNone(cb.get_result(tid)) - - cb.mark_as_done(tid, 42) - self.assertEqual(cb.get_status(tid), states.SUCCESS) - self.assertEqual(cb.get_result(tid), 42) - self.assertTrue(cb.get_result(tid), 42) - - def test_forget(self): - b = CacheBackend(app=app) - tid = gen_unique_id() - b.mark_as_done(tid, {'foo': 'bar'}) - self.assertEqual(b.get_result(tid).get('foo'), 'bar') - b.forget(tid) - self.assertNotIn(tid, b._cache) - self.assertIsNone(b.get_result(tid)) - - def test_save_restore_delete_group(self): - backend = CacheBackend(app=app) - group_id = gen_unique_id() - subtask_ids = [gen_unique_id() for i in range(10)] - subtasks = map(result.AsyncResult, subtask_ids) - res = result.GroupResult(group_id, subtasks) - res.save(backend=backend) - saved = result.GroupResult.restore(group_id, backend=backend) - self.assertListEqual(saved.subtasks, subtasks) - self.assertEqual(saved.id, group_id) - saved.delete(backend=backend) - self.assertIsNone(result.GroupResult.restore(group_id, - backend=backend)) - - def test_is_pickled(self): - cb = CacheBackend(app=app) - - tid2 = gen_unique_id() - result = {'foo': 'baz', 'bar': SomeClass(12345)} - cb.mark_as_done(tid2, result) - # is serialized properly. - rindb = cb.get_result(tid2) - self.assertEqual(rindb.get('foo'), 'baz') - self.assertEqual(rindb.get('bar').data, 12345) - - def test_mark_as_failure(self): - cb = CacheBackend(app=app) - - einfo = None - tid3 = gen_unique_id() - try: - raise KeyError('foo') - except KeyError as exception: - einfo = ExceptionInfo(sys.exc_info()) - pass - cb.mark_as_failure(tid3, exception, traceback=einfo.traceback) - self.assertEqual(cb.get_status(tid3), states.FAILURE) - self.assertIsInstance(cb.get_result(tid3), KeyError) - self.assertEqual(cb.get_traceback(tid3), einfo.traceback) - - def test_process_cleanup(self): - cb = CacheBackend(app=app) - cb.process_cleanup() - - def test_set_expires(self): - cb1 = CacheBackend(app=app, expires=timedelta(seconds=16)) - self.assertEqual(cb1.expires, 16) - cb2 = CacheBackend(app=app, expires=32) - self.assertEqual(cb2.expires, 32) - - -class test_custom_CacheBackend(unittest.TestCase): - - def test_custom_cache_backend(self): - from celery import current_app - prev_backend = current_app.conf.CELERY_CACHE_BACKEND - prev_module = sys.modules['djcelery.backends.cache'] - - if django.VERSION >= (1, 3): - current_app.conf.CELERY_CACHE_BACKEND = \ - 'django.core.cache.backends.dummy.DummyCache' - else: - # Django 1.2 used 'scheme://' style cache backends - current_app.conf.CELERY_CACHE_BACKEND = 'dummy://' - sys.modules.pop('djcelery.backends.cache') - try: - from djcelery.backends.cache import cache - from django.core.cache import cache as django_cache - self.assertEqual(cache.__class__.__module__, - 'django.core.cache.backends.dummy') - self.assertIsNot(cache, django_cache) - finally: - current_app.conf.CELERY_CACHE_BACKEND = prev_backend - sys.modules['djcelery.backends.cache'] = prev_module - - -class test_MemcacheWrapper(unittest.TestCase): - - def test_memcache_wrapper(self): - - try: - from django.core.cache.backends import memcached - from django.core.cache.backends import locmem - except InvalidCacheBackendError: - sys.stderr.write( - '\n* Memcache library is not installed. Skipping test.\n') - return - try: - prev_cache_cls = memcached.CacheClass - memcached.CacheClass = locmem.CacheClass - except AttributeError: - return - prev_backend_module = sys.modules.pop('djcelery.backends.cache') - try: - from djcelery.backends.cache import cache - key = 'cu.test_memcache_wrapper' - val = 'The quick brown fox.' - default = 'The lazy dog.' - - self.assertEqual(cache.get(key, default=default), default) - cache.set(key, val) - self.assertEqual(cache.get(key, default=default), val) - finally: - memcached.CacheClass = prev_cache_cls - sys.modules['djcelery.backends.cache'] = prev_backend_module diff --git a/awx/lib/site-packages/djcelery/tests/test_backends/test_database.py b/awx/lib/site-packages/djcelery/tests/test_backends/test_database.py deleted file mode 100644 index 848d7714f0..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_backends/test_database.py +++ /dev/null @@ -1,105 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import celery - -from datetime import timedelta - -from celery import current_app -from celery import states -from celery.result import AsyncResult -from celery.task import PeriodicTask -from celery.utils import gen_unique_id - -from djcelery.app import app -from djcelery.backends.database import DatabaseBackend -from djcelery.utils import now -from djcelery.tests.utils import unittest - - -class SomeClass(object): - - def __init__(self, data): - self.data = data - - -class MyPeriodicTask(PeriodicTask): - name = 'c.u.my-periodic-task-244' - run_every = timedelta(seconds=1) - - def run(self, **kwargs): - return 42 - - -class TestDatabaseBackend(unittest.TestCase): - - def test_backend(self): - b = DatabaseBackend(app=app) - tid = gen_unique_id() - - self.assertEqual(b.get_status(tid), states.PENDING) - self.assertIsNone(b.get_result(tid)) - - b.mark_as_done(tid, 42) - self.assertEqual(b.get_status(tid), states.SUCCESS) - self.assertEqual(b.get_result(tid), 42) - - tid2 = gen_unique_id() - result = {'foo': 'baz', 'bar': SomeClass(12345)} - b.mark_as_done(tid2, result) - # is serialized properly. - rindb = b.get_result(tid2) - self.assertEqual(rindb.get('foo'), 'baz') - self.assertEqual(rindb.get('bar').data, 12345) - - tid3 = gen_unique_id() - try: - raise KeyError('foo') - except KeyError as exception: - pass - b.mark_as_failure(tid3, exception) - self.assertEqual(b.get_status(tid3), states.FAILURE) - self.assertIsInstance(b.get_result(tid3), KeyError) - - def test_forget(self): - b = DatabaseBackend(app=app) - tid = gen_unique_id() - b.mark_as_done(tid, {'foo': 'bar'}) - x = AsyncResult(tid) - self.assertEqual(x.result.get('foo'), 'bar') - x.forget() - if celery.VERSION[0:3] == (3, 1, 10): - # bug in 3.1.10 means result did not clear cache after forget. - x._cache = None - self.assertIsNone(x.result) - - def test_group_store(self): - b = DatabaseBackend(app=app) - tid = gen_unique_id() - - self.assertIsNone(b.restore_group(tid)) - - result = {'foo': 'baz', 'bar': SomeClass(12345)} - b.save_group(tid, result) - rindb = b.restore_group(tid) - self.assertIsNotNone(rindb) - self.assertEqual(rindb.get('foo'), 'baz') - self.assertEqual(rindb.get('bar').data, 12345) - b.delete_group(tid) - self.assertIsNone(b.restore_group(tid)) - - def test_cleanup(self): - b = DatabaseBackend(app=app) - b.TaskModel._default_manager.all().delete() - ids = [gen_unique_id() for _ in xrange(3)] - for i, res in enumerate((16, 32, 64)): - b.mark_as_done(ids[i], res) - - self.assertEqual(b.TaskModel._default_manager.count(), 3) - - then = now() - current_app.conf.CELERY_TASK_RESULT_EXPIRES * 2 - # Have to avoid save() because it applies the auto_now=True. - b.TaskModel._default_manager.filter(task_id__in=ids[:-1]) \ - .update(date_done=then) - - b.cleanup() - self.assertEqual(b.TaskModel._default_manager.count(), 1) diff --git a/awx/lib/site-packages/djcelery/tests/test_discovery.py b/awx/lib/site-packages/djcelery/tests/test_discovery.py deleted file mode 100644 index 22ebb4ed2c..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_discovery.py +++ /dev/null @@ -1,35 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import warnings - -from django.conf import settings - -from celery.registry import tasks - -from djcelery.loaders import autodiscover -from djcelery.tests.utils import unittest - - -class TestDiscovery(unittest.TestCase): - - def assertDiscovery(self): - apps = autodiscover() - self.assertTrue(apps) - self.assertIn('c.unittest.SomeAppTask', tasks) - self.assertEqual(tasks['c.unittest.SomeAppTask'].run(), 42) - - def test_discovery(self): - if 'someapp' in settings.INSTALLED_APPS: - self.assertDiscovery() - - def test_discovery_with_broken(self): - warnings.resetwarnings() - if 'someapp' in settings.INSTALLED_APPS: - installed_apps = list(settings.INSTALLED_APPS) - settings.INSTALLED_APPS = installed_apps + ['xxxnot.aexist'] - try: - with warnings.catch_warnings(record=True) as log: - autodiscover() - self.assertTrue(log) - finally: - settings.INSTALLED_APPS = installed_apps diff --git a/awx/lib/site-packages/djcelery/tests/test_loaders.py b/awx/lib/site-packages/djcelery/tests/test_loaders.py deleted file mode 100644 index 2170e9b163..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_loaders.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from celery import loaders - -from djcelery import loaders as djloaders -from djcelery.app import app -from djcelery.tests.utils import unittest - - -class TestDjangoLoader(unittest.TestCase): - - def setUp(self): - self.loader = djloaders.DjangoLoader(app=app) - - def test_get_loader_cls(self): - - self.assertEqual(loaders.get_loader_cls('django'), - self.loader.__class__) - # Execute cached branch. - self.assertEqual(loaders.get_loader_cls('django'), - self.loader.__class__) - - def test_on_worker_init(self): - from django.conf import settings - old_imports = getattr(settings, 'CELERY_IMPORTS', ()) - settings.CELERY_IMPORTS = ('xxx.does.not.exist', ) - try: - self.assertRaises(ImportError, self.loader.import_default_modules) - finally: - settings.CELERY_IMPORTS = old_imports - - def test_race_protection(self): - djloaders._RACE_PROTECTION = True - try: - self.assertFalse(self.loader.on_worker_init()) - finally: - djloaders._RACE_PROTECTION = False - - def test_find_related_module_no_path(self): - self.assertFalse(djloaders.find_related_module('sys', 'tasks')) - - def test_find_related_module_no_related(self): - self.assertFalse( - djloaders.find_related_module('someapp', 'frobulators'), - ) diff --git a/awx/lib/site-packages/djcelery/tests/test_models.py b/awx/lib/site-packages/djcelery/tests/test_models.py deleted file mode 100644 index 69f4bfc800..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_models.py +++ /dev/null @@ -1,101 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from datetime import datetime, timedelta - -from celery import states -from celery.utils import gen_unique_id - -from djcelery import celery -from djcelery.models import TaskMeta, TaskSetMeta -from djcelery.utils import now -from djcelery.tests.utils import unittest - - -class TestModels(unittest.TestCase): - - def createTaskMeta(self): - id = gen_unique_id() - taskmeta, created = TaskMeta.objects.get_or_create(task_id=id) - return taskmeta - - def createTaskSetMeta(self): - id = gen_unique_id() - tasksetmeta, created = TaskSetMeta.objects.get_or_create(taskset_id=id) - return tasksetmeta - - def test_taskmeta(self): - m1 = self.createTaskMeta() - m2 = self.createTaskMeta() - m3 = self.createTaskMeta() - self.assertTrue(unicode(m1).startswith('<Task:')) - self.assertTrue(m1.task_id) - self.assertIsInstance(m1.date_done, datetime) - - self.assertEqual( - TaskMeta.objects.get_task(m1.task_id).task_id, - m1.task_id, - ) - self.assertNotEqual(TaskMeta.objects.get_task(m1.task_id).status, - states.SUCCESS) - TaskMeta.objects.store_result(m1.task_id, True, status=states.SUCCESS) - TaskMeta.objects.store_result(m2.task_id, True, status=states.SUCCESS) - self.assertEqual(TaskMeta.objects.get_task(m1.task_id).status, - states.SUCCESS) - self.assertEqual(TaskMeta.objects.get_task(m2.task_id).status, - states.SUCCESS) - - # Have to avoid save() because it applies the auto_now=True. - TaskMeta.objects.filter( - task_id=m1.task_id - ).update(date_done=now() - timedelta(days=10)) - - expired = TaskMeta.objects.get_all_expired( - celery.conf.CELERY_TASK_RESULT_EXPIRES, - ) - self.assertIn(m1, expired) - self.assertNotIn(m2, expired) - self.assertNotIn(m3, expired) - - TaskMeta.objects.delete_expired( - celery.conf.CELERY_TASK_RESULT_EXPIRES, - ) - self.assertNotIn(m1, TaskMeta.objects.all()) - - def test_tasksetmeta(self): - m1 = self.createTaskSetMeta() - m2 = self.createTaskSetMeta() - m3 = self.createTaskSetMeta() - self.assertTrue(unicode(m1).startswith('<TaskSet:')) - self.assertTrue(m1.taskset_id) - self.assertIsInstance(m1.date_done, datetime) - - self.assertEqual( - TaskSetMeta.objects.restore_taskset(m1.taskset_id).taskset_id, - m1.taskset_id, - ) - - # Have to avoid save() because it applies the auto_now=True. - TaskSetMeta.objects.filter( - taskset_id=m1.taskset_id, - ).update(date_done=now() - timedelta(days=10)) - - expired = TaskSetMeta.objects.get_all_expired( - celery.conf.CELERY_TASK_RESULT_EXPIRES, - ) - self.assertIn(m1, expired) - self.assertNotIn(m2, expired) - self.assertNotIn(m3, expired) - - TaskSetMeta.objects.delete_expired( - celery.conf.CELERY_TASK_RESULT_EXPIRES, - ) - self.assertNotIn(m1, TaskSetMeta.objects.all()) - - m4 = self.createTaskSetMeta() - self.assertEqual( - TaskSetMeta.objects.restore_taskset(m4.taskset_id).taskset_id, - m4.taskset_id, - ) - - TaskSetMeta.objects.delete_taskset(m4.taskset_id) - self.assertIsNone(TaskSetMeta.objects.restore_taskset(m4.taskset_id)) diff --git a/awx/lib/site-packages/djcelery/tests/test_schedulers.py b/awx/lib/site-packages/djcelery/tests/test_schedulers.py deleted file mode 100644 index 0401791ddf..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_schedulers.py +++ /dev/null @@ -1,290 +0,0 @@ -from __future__ import absolute_import - -from datetime import datetime, timedelta -from itertools import count - -from celery.five import monotonic -from celery.schedules import schedule, crontab -from celery.utils.timeutils import timedelta_seconds - -from djcelery import schedulers -from djcelery import celery -from djcelery.app import app -from djcelery.models import PeriodicTask, IntervalSchedule, CrontabSchedule -from djcelery.models import PeriodicTasks -from djcelery.tests.utils import unittest - - -def create_model_interval(schedule, **kwargs): - return create_model(interval=IntervalSchedule.from_schedule(schedule), - **kwargs) - - -def create_model_crontab(schedule, **kwargs): - return create_model(crontab=CrontabSchedule.from_schedule(schedule), - **kwargs) - -_next_id = count(0).next - - -def create_model(Model=PeriodicTask, **kwargs): - entry = dict(name='thefoo{0}'.format(_next_id()), - task='djcelery.unittest.add{0}'.format(_next_id()), - args='[2, 2]', - kwargs='{"callback": "foo"}', - queue='xaz', - routing_key='cpu', - exchange='foo') - return Model(**dict(entry, **kwargs)) - - -class EntryTrackSave(schedulers.ModelEntry): - - def __init__(self, *args, **kwargs): - self.saved = 0 - super(EntryTrackSave, self).__init__(*args, **kwargs) - - def save(self): - self.saved += 1 - super(EntryTrackSave, self).save() - - -class EntrySaveRaises(schedulers.ModelEntry): - - def save(self): - raise RuntimeError('this is expected') - - -class TrackingScheduler(schedulers.DatabaseScheduler): - Entry = EntryTrackSave - - def __init__(self, *args, **kwargs): - self.flushed = 0 - schedulers.DatabaseScheduler.__init__(self, *args, **kwargs) - - def sync(self): - self.flushed += 1 - schedulers.DatabaseScheduler.sync(self) - - -class test_ModelEntry(unittest.TestCase): - Entry = EntryTrackSave - - def tearDown(self): - PeriodicTask.objects.all().delete() - - def test_entry(self): - m = create_model_interval(schedule(timedelta(seconds=10))) - e = self.Entry(m) - - self.assertListEqual(e.args, [2, 2]) - self.assertDictEqual(e.kwargs, {'callback': 'foo'}) - self.assertTrue(e.schedule) - self.assertEqual(e.total_run_count, 0) - self.assertIsInstance(e.last_run_at, datetime) - self.assertDictContainsSubset({'queue': 'xaz', - 'exchange': 'foo', - 'routing_key': 'cpu'}, e.options) - - right_now = celery.now() - m2 = create_model_interval(schedule(timedelta(seconds=10)), - last_run_at=right_now) - self.assertTrue(m2.last_run_at) - e2 = self.Entry(m2) - self.assertIs(e2.last_run_at, right_now) - - e3 = e2.next() - self.assertGreater(e3.last_run_at, e2.last_run_at) - self.assertEqual(e3.total_run_count, 1) - - -class test_DatabaseScheduler(unittest.TestCase): - Scheduler = TrackingScheduler - - def setUp(self): - PeriodicTask.objects.all().delete() - self.prev_schedule = celery.conf.CELERYBEAT_SCHEDULE - celery.conf.CELERYBEAT_SCHEDULE = {} - m1 = create_model_interval(schedule(timedelta(seconds=10))) - m2 = create_model_interval(schedule(timedelta(minutes=20))) - m3 = create_model_crontab(crontab(minute='2,4,5')) - for obj in m1, m2, m3: - obj.save() - self.s = self.Scheduler(app=app) - self.m1 = PeriodicTask.objects.get(name=m1.name) - self.m2 = PeriodicTask.objects.get(name=m2.name) - self.m3 = PeriodicTask.objects.get(name=m3.name) - - def tearDown(self): - celery.conf.CELERYBEAT_SCHEDULE = self.prev_schedule - PeriodicTask.objects.all().delete() - - def test_constructor(self): - self.assertIsInstance(self.s._dirty, set) - self.assertIsNone(self.s._last_sync) - self.assertTrue(self.s.sync_every) - - def test_all_as_schedule(self): - sched = self.s.schedule - self.assertTrue(sched) - self.assertEqual(len(sched), 4) - self.assertIn('celery.backend_cleanup', sched) - for n, e in sched.items(): - self.assertIsInstance(e, self.s.Entry) - - def test_schedule_changed(self): - self.m2.args = '[16, 16]' - self.m2.save() - e2 = self.s.schedule[self.m2.name] - self.assertListEqual(e2.args, [16, 16]) - - self.m1.args = '[32, 32]' - self.m1.save() - e1 = self.s.schedule[self.m1.name] - self.assertListEqual(e1.args, [32, 32]) - e1 = self.s.schedule[self.m1.name] - self.assertListEqual(e1.args, [32, 32]) - - self.m3.delete() - self.assertRaises(KeyError, self.s.schedule.__getitem__, self.m3.name) - - def test_should_sync(self): - self.assertTrue(self.s.should_sync()) - self.s._last_sync = monotonic() - self.assertFalse(self.s.should_sync()) - self.s._last_sync -= self.s.sync_every - self.assertTrue(self.s.should_sync()) - - def test_reserve(self): - e1 = self.s.schedule[self.m1.name] - self.s.schedule[self.m1.name] = self.s.reserve(e1) - self.assertEqual(self.s.flushed, 1) - - e2 = self.s.schedule[self.m2.name] - self.s.schedule[self.m2.name] = self.s.reserve(e2) - self.assertEqual(self.s.flushed, 1) - self.assertIn(self.m2.name, self.s._dirty) - - def test_sync_saves_last_run_at(self): - e1 = self.s.schedule[self.m2.name] - last_run = e1.last_run_at - last_run2 = last_run - timedelta(days=1) - e1.model.last_run_at = last_run2 - self.s._dirty.add(self.m2.name) - self.s.sync() - - e2 = self.s.schedule[self.m2.name] - self.assertEqual(e2.last_run_at, last_run2) - - def test_sync_syncs_before_save(self): - # Get the entry for m2 - e1 = self.s.schedule[self.m2.name] - - # Increment the entry (but make sure it doesn't sync) - self.s._last_sync = monotonic() - e2 = self.s.schedule[e1.name] = self.s.reserve(e1) - self.assertEqual(self.s.flushed, 1) - - # Fetch the raw object from db, change the args - # and save the changes. - m2 = PeriodicTask.objects.get(pk=self.m2.pk) - m2.args = '[16, 16]' - m2.save() - - # get_schedule should now see the schedule has changed. - # and also sync the dirty objects. - e3 = self.s.schedule[self.m2.name] - self.assertEqual(self.s.flushed, 2) - self.assertEqual(e3.last_run_at, e2.last_run_at) - self.assertListEqual(e3.args, [16, 16]) - - def test_sync_not_dirty(self): - self.s._dirty.clear() - self.s.sync() - - def test_sync_object_gone(self): - self.s._dirty.add('does-not-exist') - self.s.sync() - - def test_sync_rollback_on_save_error(self): - self.s.schedule[self.m1.name] = EntrySaveRaises(self.m1) - self.s._dirty.add(self.m1.name) - self.assertRaises(RuntimeError, self.s.sync) - - -class test_models(unittest.TestCase): - - def test_IntervalSchedule_unicode(self): - self.assertEqual(unicode(IntervalSchedule(every=1, period='seconds')), - 'every second') - self.assertEqual(unicode(IntervalSchedule(every=10, period='seconds')), - 'every 10 seconds') - - def test_CrontabSchedule_unicode(self): - self.assertEqual(unicode(CrontabSchedule(minute=3, - hour=3, - day_of_week=None)), - '3 3 * * * (m/h/d/dM/MY)') - self.assertEqual(unicode(CrontabSchedule(minute=3, - hour=3, - day_of_week='tue', - day_of_month='*/2', - month_of_year='4,6')), - '3 3 tue */2 4,6 (m/h/d/dM/MY)') - - def test_PeriodicTask_unicode_interval(self): - p = create_model_interval(schedule(timedelta(seconds=10))) - self.assertEqual(unicode(p), - '{0}: every 10.0 seconds'.format(p.name)) - - def test_PeriodicTask_unicode_crontab(self): - p = create_model_crontab(crontab(hour='4, 5', day_of_week='4, 5')) - self.assertEqual(unicode(p), - '{0}: * 4,5 4,5 * * (m/h/d/dM/MY)'.format(p.name)) - - def test_PeriodicTask_schedule_property(self): - p1 = create_model_interval(schedule(timedelta(seconds=10))) - s1 = p1.schedule - self.assertEqual(timedelta_seconds(s1.run_every), 10) - - p2 = create_model_crontab(crontab(hour='4, 5', - minute='10,20,30', - day_of_month='1-7', - month_of_year='*/3')) - s2 = p2.schedule - self.assertSetEqual(s2.hour, set([4, 5])) - self.assertSetEqual(s2.minute, set([10, 20, 30])) - self.assertSetEqual(s2.day_of_week, set([0, 1, 2, 3, 4, 5, 6])) - self.assertSetEqual(s2.day_of_month, set([1, 2, 3, 4, 5, 6, 7])) - self.assertSetEqual(s2.month_of_year, set([1, 4, 7, 10])) - - def test_PeriodicTask_unicode_no_schedule(self): - p = create_model() - self.assertEqual(unicode(p), '{0}: {{no schedule}}'.format(p.name)) - - def test_CrontabSchedule_schedule(self): - s = CrontabSchedule(minute='3, 7', hour='3, 4', day_of_week='*', - day_of_month='1, 16', month_of_year='1, 7') - self.assertEqual(s.schedule.minute, set([3, 7])) - self.assertEqual(s.schedule.hour, set([3, 4])) - self.assertEqual(s.schedule.day_of_week, set([0, 1, 2, 3, 4, 5, 6])) - self.assertEqual(s.schedule.day_of_month, set([1, 16])) - self.assertEqual(s.schedule.month_of_year, set([1, 7])) - - -class test_model_PeriodicTasks(unittest.TestCase): - - def setUp(self): - PeriodicTasks.objects.all().delete() - - def test_track_changes(self): - self.assertIsNone(PeriodicTasks.last_change()) - m1 = create_model_interval(schedule(timedelta(seconds=10))) - m1.save() - x = PeriodicTasks.last_change() - self.assertTrue(x) - m1.args = '(23, 24)' - m1.save() - y = PeriodicTasks.last_change() - self.assertTrue(y) - self.assertGreater(y, x) diff --git a/awx/lib/site-packages/djcelery/tests/test_snapshot.py b/awx/lib/site-packages/djcelery/tests/test_snapshot.py deleted file mode 100644 index 4bf608ed82..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_snapshot.py +++ /dev/null @@ -1,192 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from datetime import datetime -from itertools import count -from time import time - -from celery import states -from celery.events import Event as _Event -from celery.events.state import State, Worker, Task -from celery.utils import gen_unique_id - -from djcelery import celery -from djcelery import snapshot -from djcelery import models -from djcelery.utils import make_aware -from djcelery.tests.utils import unittest - -_next_id = count(0).next -_next_clock = count(1).next - - -def Event(*args, **kwargs): - kwargs.setdefault('clock', _next_clock()) - kwargs.setdefault('local_received', time()) - return _Event(*args, **kwargs) - - -def create_task(worker, **kwargs): - d = dict(uuid=gen_unique_id(), - name='djcelery.unittest.task{0}'.format(_next_id()), - worker=worker) - return Task(**dict(d, **kwargs)) - - -class test_Camera(unittest.TestCase): - Camera = snapshot.Camera - - def setUp(self): - self.state = State() - self.cam = self.Camera(self.state) - - def test_constructor(self): - cam = self.Camera(State()) - self.assertTrue(cam.state) - self.assertTrue(cam.freq) - self.assertTrue(cam.cleanup_freq) - self.assertTrue(cam.logger) - - def test_get_heartbeat(self): - worker = Worker(hostname='fuzzie') - self.assertIsNone(self.cam.get_heartbeat(worker)) - t1 = time() - t2 = time() - t3 = time() - for t in t1, t2, t3: - worker.event('heartbeat', t, t, {}) - self.state.workers[worker.hostname] = worker - self.assertEqual(self.cam.get_heartbeat(worker), - make_aware(datetime.fromtimestamp(t3))) - - def test_handle_worker(self): - worker = Worker(hostname='fuzzie') - worker.event('online', time(), time(), {}) - self.cam._last_worker_write.clear() - m = self.cam.handle_worker((worker.hostname, worker)) - self.assertTrue(m) - self.assertTrue(m.hostname) - self.assertTrue(m.last_heartbeat) - self.assertTrue(m.is_alive()) - self.assertEqual(unicode(m), unicode(m.hostname)) - self.assertTrue(repr(m)) - - def test_handle_task_received(self): - worker = Worker(hostname='fuzzie') - worker.event('oneline', time(), time(), {}) - self.cam.handle_worker((worker.hostname, worker)) - - task = create_task(worker) - task.event('received', time(), time(), {}) - self.assertEqual(task.state, 'RECEIVED') - mt = self.cam.handle_task((task.uuid, task)) - self.assertEqual(mt.name, task.name) - self.assertTrue(unicode(mt)) - self.assertTrue(repr(mt)) - mt.eta = celery.now() - self.assertIn('eta', unicode(mt)) - self.assertIn(mt, models.TaskState.objects.active()) - - def test_handle_task(self): - worker1 = Worker(hostname='fuzzie') - worker1.event('online', time(), time(), {}) - mw = self.cam.handle_worker((worker1.hostname, worker1)) - task1 = create_task(worker1) - task1.event('received', time(), time(), {}) - mt = self.cam.handle_task((task1.uuid, task1)) - self.assertEqual(mt.worker, mw) - - worker2 = Worker(hostname=None) - task2 = create_task(worker2) - task2.event('received', time(), time(), {}) - mt = self.cam.handle_task((task2.uuid, task2)) - self.assertIsNone(mt.worker) - - task1.event('succeeded', time(), time(), {'result': 42}) - self.assertEqual(task1.state, states.SUCCESS) - self.assertEqual(task1.result, 42) - mt = self.cam.handle_task((task1.uuid, task1)) - self.assertEqual(mt.name, task1.name) - self.assertEqual(mt.result, 42) - - task3 = create_task(worker1, name=None) - task3.event('revoked', time(), time(), {}) - mt = self.cam.handle_task((task3.uuid, task3)) - self.assertIsNone(mt) - - def assertExpires(self, dec, expired, tasks=10): - worker = Worker(hostname='fuzzie') - worker.event('online', time(), time(), {}) - for total in xrange(tasks): - task = create_task(worker) - task.event('received', time() - dec, time() - dec, {}) - task.event('succeeded', time() - dec, time() - dec, {'result': 42}) - self.assertTrue(task.name) - self.assertTrue(self.cam.handle_task((task.uuid, task))) - self.assertEqual(self.cam.on_cleanup(), expired) - - def test_on_cleanup_expires(self, dec=332000): - self.assertExpires(dec, 10) - - def test_on_cleanup_does_not_expire_new(self, dec=0): - self.assertExpires(dec, 0) - - def test_on_shutter(self): - state = self.state - cam = self.cam - - ws = ['worker1.ex.com', 'worker2.ex.com', 'worker3.ex.com'] - uus = [gen_unique_id() for i in xrange(50)] - - events = [Event('worker-online', hostname=ws[0]), - Event('worker-online', hostname=ws[1]), - Event('worker-online', hostname=ws[2]), - Event('task-received', - uuid=uus[0], name='A', hostname=ws[0]), - Event('task-started', - uuid=uus[0], name='A', hostname=ws[0]), - Event('task-received', - uuid=uus[1], name='B', hostname=ws[1]), - Event('task-revoked', - uuid=uus[2], name='C', hostname=ws[2])] - - for event in events: - event['local_received'] = time() - state.event(event) - cam.on_shutter(state) - - for host in ws: - worker = models.WorkerState.objects.get(hostname=host) - self.assertTrue(worker.is_alive()) - - t1 = models.TaskState.objects.get(task_id=uus[0]) - self.assertEqual(t1.state, 'STARTED') - self.assertEqual(t1.name, 'A') - t2 = models.TaskState.objects.get(task_id=uus[1]) - self.assertEqual(t2.state, 'RECEIVED') - t3 = models.TaskState.objects.get(task_id=uus[2]) - self.assertEqual(t3.state, 'REVOKED') - - events = [Event('task-succeeded', - uuid=uus[0], hostname=ws[0], result=42), - Event('task-failed', - uuid=uus[1], exception="KeyError('foo')", - hostname=ws[1]), - Event('worker-offline', hostname=ws[0])] - map(state.event, events) - cam._last_worker_write.clear() - cam.on_shutter(state) - - w1 = models.WorkerState.objects.get(hostname=ws[0]) - self.assertFalse(w1.is_alive()) - - t1 = models.TaskState.objects.get(task_id=uus[0]) - self.assertEqual(t1.state, 'SUCCESS') - self.assertEqual(t1.result, '42') - self.assertEqual(t1.worker, w1) - - t2 = models.TaskState.objects.get(task_id=uus[1]) - self.assertEqual(t2.state, 'FAILURE') - self.assertEqual(t2.result, "KeyError('foo')") - self.assertEqual(t2.worker.hostname, ws[1]) - - cam.on_shutter(state) diff --git a/awx/lib/site-packages/djcelery/tests/test_views.py b/awx/lib/site-packages/djcelery/tests/test_views.py deleted file mode 100644 index 81879ca2e6..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_views.py +++ /dev/null @@ -1,207 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import sys - -from functools import partial - -from billiard.einfo import ExceptionInfo -from django.core.urlresolvers import reverse -from django.http import HttpResponse -from django.test.testcases import TestCase as DjangoTestCase -from django.template import TemplateDoesNotExist - -from anyjson import deserialize - -from celery import current_app -from celery import states -from celery.task import task -from celery.utils import gen_unique_id, get_full_cls_name - -from djcelery.views import task_webhook -from djcelery.tests.req import MockRequest - - -def reversestar(name, **kwargs): - return reverse(name, kwargs=kwargs) - - -class MyError(Exception): - # On Py2.4 repr(exc) includes the object id, so comparing - # texts is pointless when the id the "same" KeyError does not match. - - def __repr__(self): - return '<{0.__class__.__name__}: {0.args!r}>'.format(self) - - -class MyRetryTaskError(MyError): - pass - - -task_is_successful = partial(reversestar, 'celery-is_task_successful') -task_status = partial(reversestar, 'celery-task_status') -task_apply = partial(reverse, 'celery-apply') -registered_tasks = partial(reverse, 'celery-tasks') -scratch = {} - - -@task() -def mytask(x, y): - ret = scratch['result'] = int(x) * int(y) - return ret - - -def create_exception(name, base=Exception): - return type(name, (base, ), {}) - - -def catch_exception(exception): - try: - raise exception - except exception.__class__ as exc: - exc = current_app.backend.prepare_exception(exc) - return exc, ExceptionInfo(sys.exc_info()).traceback - - -class ViewTestCase(DjangoTestCase): - - def assertJSONEqual(self, json, py): - json = isinstance(json, HttpResponse) and json.content or json - try: - self.assertEqual(deserialize(json), py) - except TypeError as exc: - raise TypeError('{0}: {1}'.format(exc, json)) - - def assertIn(self, expected, source, *args): - try: - DjangoTestCase.assertIn(self, expected, source, *args) - except AttributeError: - self.assertTrue(expected in source) - - def assertDictContainsSubset(self, a, b, *args): - try: - DjangoTestCase.assertDictContainsSubset(self, a, b, *args) - except AttributeError: - for key, value in a.items(): - self.assertTrue(key in b) - self.assertEqual(b[key], value) - - -class test_task_apply(ViewTestCase): - - def test_apply(self): - current_app.conf.CELERY_ALWAYS_EAGER = True - try: - self.client.get( - task_apply(kwargs={'task_name': mytask.name}) + '?x=4&y=4', - ) - self.assertEqual(scratch['result'], 16) - finally: - current_app.conf.CELERY_ALWAYS_EAGER = False - - def test_apply_raises_404_on_unregistered_task(self): - current_app.conf.CELERY_ALWAYS_EAGER = True - try: - name = 'xxx.does.not.exist' - action = partial( - self.client.get, - task_apply(kwargs={'task_name': name}) + '?x=4&y=4', - ) - try: - res = action() - except TemplateDoesNotExist: - pass # pre Django 1.5 - else: - self.assertEqual(res.status_code, 404) - finally: - current_app.conf.CELERY_ALWAYS_EAGER = False - - -class test_registered_tasks(ViewTestCase): - - def test_list_registered_tasks(self): - json = self.client.get(registered_tasks()) - tasks = deserialize(json.content) - self.assertIn('celery.backend_cleanup', tasks['regular']) - - -class test_webhook_task(ViewTestCase): - - def test_successful_request(self): - - @task_webhook - def add_webhook(request): - x = int(request.GET['x']) - y = int(request.GET['y']) - return x + y - - request = MockRequest().get('/tasks/add', dict(x=10, y=10)) - response = add_webhook(request) - self.assertDictContainsSubset({'status': 'success', 'retval': 20}, - deserialize(response.content)) - - def test_failed_request(self): - - @task_webhook - def error_webhook(request): - x = int(request.GET['x']) - y = int(request.GET['y']) - raise MyError(x + y) - - request = MockRequest().get('/tasks/error', dict(x=10, y=10)) - response = error_webhook(request) - self.assertDictContainsSubset({'status': 'failure', - 'reason': '<MyError: (20,)>'}, - deserialize(response.content)) - - -class test_task_status(ViewTestCase): - - def assertStatusForIs(self, status, res, traceback=None): - uuid = gen_unique_id() - current_app.backend.store_result(uuid, res, status, - traceback=traceback) - json = self.client.get(task_status(task_id=uuid)) - expect = dict(id=uuid, status=status, result=res) - if status in current_app.backend.EXCEPTION_STATES: - instore = current_app.backend.get_result(uuid) - self.assertEqual(str(instore.args[0]), str(res.args[0])) - expect['result'] = repr(res) - expect['exc'] = get_full_cls_name(res.__class__) - expect['traceback'] = traceback - - self.assertJSONEqual(json, dict(task=expect)) - - def test_success(self): - self.assertStatusForIs(states.SUCCESS, 'The quick brown fox') - - def test_failure(self): - exc, tb = catch_exception(MyError('foo')) - self.assertStatusForIs(states.FAILURE, exc, tb) - - def test_retry(self): - oexc, _ = catch_exception(MyError('Resource not available')) - exc, tb = catch_exception(MyRetryTaskError(str(oexc), oexc)) - self.assertStatusForIs(states.RETRY, exc, tb) - - -class test_task_is_successful(ViewTestCase): - - def assertStatusForIs(self, status, outcome): - uuid = gen_unique_id() - result = gen_unique_id() - current_app.backend.store_result(uuid, result, status) - json = self.client.get(task_is_successful(task_id=uuid)) - self.assertJSONEqual(json, {'task': {'id': uuid, - 'executed': outcome}}) - - def test_success(self): - self.assertStatusForIs(states.SUCCESS, True) - - def test_pending(self): - self.assertStatusForIs(states.PENDING, False) - - def test_failure(self): - self.assertStatusForIs(states.FAILURE, False) - - def test_retry(self): - self.assertStatusForIs(states.RETRY, False) diff --git a/awx/lib/site-packages/djcelery/tests/test_worker_job.py b/awx/lib/site-packages/djcelery/tests/test_worker_job.py deleted file mode 100644 index 548aaeda86..0000000000 --- a/awx/lib/site-packages/djcelery/tests/test_worker_job.py +++ /dev/null @@ -1,80 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -from django.core import cache - -from celery.utils import gen_unique_id -from celery.task import task as task_dec - -from celery.tests.worker.test_request import jail - -from djcelery.app import app -from djcelery.tests.utils import unittest - - -@task_dec() -def mytask(i): - return i ** i - - -@task_dec() -def get_db_connection(i): - from django.db import connection - return id(connection) -get_db_connection.ignore_result = True - - -class TestJail(unittest.TestCase): - - def test_django_db_connection_is_closed(self): - from django.db import connection - connection._was_closed = False - old_connection_close = connection.close - - def monkeypatched_connection_close(*args, **kwargs): - connection._was_closed = True - return old_connection_close(*args, **kwargs) - - connection.close = monkeypatched_connection_close - try: - jail(app, gen_unique_id(), get_db_connection.name, [2], {}) - self.assertTrue(connection._was_closed) - finally: - connection.close = old_connection_close - - def test_django_cache_connection_is_closed(self): - old_cache_close = getattr(cache.cache, 'close', None) - cache._was_closed = False - old_cache_parse_backend = getattr(cache, 'parse_backend_uri', None) - if old_cache_parse_backend: # checks to make sure attr exists - delattr(cache, 'parse_backend_uri') - - def monkeypatched_cache_close(*args, **kwargs): - cache._was_closed = True - - cache.cache.close = monkeypatched_cache_close - - jail(app, gen_unique_id(), mytask.name, [4], {}) - self.assertTrue(cache._was_closed) - cache.cache.close = old_cache_close - if old_cache_parse_backend: - cache.parse_backend_uri = old_cache_parse_backend - - def test_django_cache_connection_is_closed_django_1_1(self): - old_cache_close = getattr(cache.cache, 'close', None) - cache._was_closed = False - old_cache_parse_backend = getattr(cache, 'parse_backend_uri', None) - cache.parse_backend_uri = lambda uri: ['libmemcached', '1', '2'] - - def monkeypatched_cache_close(*args, **kwargs): - cache._was_closed = True - - cache.cache.close = monkeypatched_cache_close - - jail(app, gen_unique_id(), mytask.name, [4], {}) - self.assertTrue(cache._was_closed) - cache.cache.close = old_cache_close - if old_cache_parse_backend: - cache.parse_backend_uri = old_cache_parse_backend - else: - del(cache.parse_backend_uri) diff --git a/awx/lib/site-packages/djcelery/tests/utils.py b/awx/lib/site-packages/djcelery/tests/utils.py deleted file mode 100644 index 1d932615c4..0000000000 --- a/awx/lib/site-packages/djcelery/tests/utils.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -try: - import unittest - unittest.skip -except AttributeError: - import unittest2 as unittest # noqa diff --git a/awx/lib/site-packages/djcelery/transport/__init__.py b/awx/lib/site-packages/djcelery/transport/__init__.py deleted file mode 100644 index e4512f0367..0000000000 --- a/awx/lib/site-packages/djcelery/transport/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -""" - -This module is an alias to :mod:`kombu.transport.django` - -""" -from __future__ import absolute_import, unicode_literals - -import kombu.transport.django as transport - -__path__.extend(transport.__path__) diff --git a/awx/lib/site-packages/djcelery/urls.py b/awx/lib/site-packages/djcelery/urls.py deleted file mode 100644 index b6e5cad4ef..0000000000 --- a/awx/lib/site-packages/djcelery/urls.py +++ /dev/null @@ -1,32 +0,0 @@ -""" - -URLs defined for celery. - -* ``/$task_id/done/`` - - URL to :func:`~celery.views.is_successful`. - -* ``/$task_id/status/`` - - URL to :func:`~celery.views.task_status`. - -""" -from __future__ import absolute_import, unicode_literals - -try: - from django.conf.urls import patterns, url -except ImportError: # deprecated since Django 1.4 - from django.conf.urls.defaults import patterns, url # noqa - -from . import views - -task_pattern = r'(?P<task_id>[\w\d\-\.]+)' - -urlpatterns = patterns( - '', - url(r'^%s/done/?$' % task_pattern, views.is_task_successful, - name='celery-is_task_successful'), - url(r'^%s/status/?$' % task_pattern, views.task_status, - name='celery-task_status'), - url(r'^tasks/?$', views.registered_tasks, name='celery-tasks'), -) diff --git a/awx/lib/site-packages/djcelery/utils.py b/awx/lib/site-packages/djcelery/utils.py deleted file mode 100644 index 625906de93..0000000000 --- a/awx/lib/site-packages/djcelery/utils.py +++ /dev/null @@ -1,95 +0,0 @@ -# -- XXX This module must not use translation as that causes -# -- a recursive loader import! -from __future__ import absolute_import, unicode_literals - -from datetime import datetime - -from django.conf import settings - -# Database-related exceptions. -from django.db import DatabaseError -try: - import MySQLdb as mysql - _my_database_errors = (mysql.DatabaseError, - mysql.InterfaceError, - mysql.OperationalError) -except ImportError: - _my_database_errors = () # noqa -try: - import psycopg2 as pg - _pg_database_errors = (pg.DatabaseError, - pg.InterfaceError, - pg.OperationalError) -except ImportError: - _pg_database_errors = () # noqa -try: - import sqlite3 - _lite_database_errors = (sqlite3.DatabaseError, - sqlite3.InterfaceError, - sqlite3.OperationalError) -except ImportError: - _lite_database_errors = () # noqa -try: - import cx_Oracle as oracle - _oracle_database_errors = (oracle.DatabaseError, - oracle.InterfaceError, - oracle.OperationalError) -except ImportError: - _oracle_database_errors = () # noqa - -DATABASE_ERRORS = ((DatabaseError, ) + - _my_database_errors + - _pg_database_errors + - _lite_database_errors + - _oracle_database_errors) - - -try: - from django.utils import timezone - is_aware = timezone.is_aware - - # see Issue #222 - now_localtime = getattr(timezone, 'template_localtime', timezone.localtime) - - def make_aware(value): - if getattr(settings, 'USE_TZ', False): - # naive datetimes are assumed to be in UTC. - if timezone.is_naive(value): - value = timezone.make_aware(value, timezone.utc) - # then convert to the Django configured timezone. - default_tz = timezone.get_default_timezone() - value = timezone.localtime(value, default_tz) - return value - - def make_naive(value): - if getattr(settings, 'USE_TZ', False): - default_tz = timezone.get_default_timezone() - value = timezone.make_naive(value, default_tz) - return value - - def now(): - if getattr(settings, 'USE_TZ', False): - return now_localtime(timezone.now()) - else: - return timezone.now() - -except ImportError: - now = datetime.now - make_aware = make_naive = lambda x: x - is_aware = lambda x: False - - -def maybe_make_aware(value): - if isinstance(value, datetime) and is_aware(value): - return value - if value: - return make_aware(value) - return value - - -def is_database_scheduler(scheduler): - if not scheduler: - return False - from kombu.utils import symbol_by_name - from .schedulers import DatabaseScheduler - return issubclass(symbol_by_name(scheduler), DatabaseScheduler) diff --git a/awx/lib/site-packages/djcelery/views.py b/awx/lib/site-packages/djcelery/views.py deleted file mode 100644 index 34cb3077ad..0000000000 --- a/awx/lib/site-packages/djcelery/views.py +++ /dev/null @@ -1,124 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -from functools import wraps - -from django.http import HttpResponse, Http404 - -from anyjson import serialize - -from celery import states -from celery.registry import tasks -from celery.result import AsyncResult -from celery.utils import get_full_cls_name, kwdict -from celery.utils.encoding import safe_repr - -# Ensure built-in tasks are loaded for task_list view -import celery.task # noqa - - -def JsonResponse(response): - return HttpResponse(serialize(response), content_type='application/json') - - -def task_view(task): - """Decorator turning any task into a view that applies the task - asynchronously. Keyword arguments (via URLconf, etc.) will - supercede GET or POST parameters when there are conflicts. - - Returns a JSON dictionary containing the keys ``ok``, and - ``task_id``. - - """ - - def _applier(request, **options): - kwargs = kwdict(request.method == 'POST' and - request.POST or request.GET) - # no multivalue - kwargs = dict(((k, v) for k, v in kwargs.iteritems()), **options) - result = task.apply_async(kwargs=kwargs) - return JsonResponse({'ok': 'true', 'task_id': result.task_id}) - - return _applier - - -def apply(request, task_name): - """View applying a task. - - **Note:** Please use this with caution. Preferably you shouldn't make this - publicly accessible without ensuring your code is safe! - - """ - try: - task = tasks[task_name] - except KeyError: - raise Http404('apply: no such task') - return task_view(task)(request) - - -def is_task_successful(request, task_id): - """Returns task execute status in JSON format.""" - return JsonResponse({'task': { - 'id': task_id, - 'executed': AsyncResult(task_id).successful(), - }}) - - -def task_status(request, task_id): - """Returns task status and result in JSON format.""" - result = AsyncResult(task_id) - state, retval = result.state, result.result - response_data = dict(id=task_id, status=state, result=retval) - if state in states.EXCEPTION_STATES: - traceback = result.traceback - response_data.update({'result': safe_repr(retval), - 'exc': get_full_cls_name(retval.__class__), - 'traceback': traceback}) - return JsonResponse({'task': response_data}) - - -def registered_tasks(request): - """View returning all defined tasks as a JSON object.""" - return JsonResponse({'regular': tasks.regular().keys(), - 'periodic': tasks.periodic().keys()}) - - -def task_webhook(fun): - """Decorator turning a function into a task webhook. - - If an exception is raised within the function, the decorated - function catches this and returns an error JSON response, otherwise - it returns the result as a JSON response. - - - Example: - - .. code-block:: python - - @task_webhook - def add(request): - x = int(request.GET['x']) - y = int(request.GET['y']) - return x + y - - def view(request): - response = add(request) - print(response.content) - - Gives:: - - "{'status': 'success', 'retval': 100}" - - """ - - @wraps(fun) - def _inner(*args, **kwargs): - try: - retval = fun(*args, **kwargs) - except Exception as exc: - response = {'status': 'failure', 'reason': safe_repr(exc)} - else: - response = {'status': 'success', 'retval': retval} - - return JsonResponse(response) - - return _inner diff --git a/awx/lib/site-packages/dogpile/__init__.py b/awx/lib/site-packages/dogpile/__init__.py deleted file mode 100644 index f48ad10528..0000000000 --- a/awx/lib/site-packages/dogpile/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - from pkgutil import extend_path - __path__ = extend_path(__path__, __name__) diff --git a/awx/lib/site-packages/dogpile/cache/__init__.py b/awx/lib/site-packages/dogpile/cache/__init__.py deleted file mode 100644 index 6a3aea34bf..0000000000 --- a/awx/lib/site-packages/dogpile/cache/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -__version__ = '0.5.6' - -from .region import CacheRegion, register_backend, make_region # noqa diff --git a/awx/lib/site-packages/dogpile/cache/api.py b/awx/lib/site-packages/dogpile/cache/api.py deleted file mode 100644 index 85b6de181c..0000000000 --- a/awx/lib/site-packages/dogpile/cache/api.py +++ /dev/null @@ -1,195 +0,0 @@ -import operator -from .compat import py3k - - -class NoValue(object): - """Describe a missing cache value. - - The :attr:`.NO_VALUE` module global - should be used. - - """ - @property - def payload(self): - return self - - if py3k: - def __bool__(self): # pragma NO COVERAGE - return False - else: - def __nonzero__(self): # pragma NO COVERAGE - return False - -NO_VALUE = NoValue() -"""Value returned from ``get()`` that describes -a key not present.""" - - -class CachedValue(tuple): - """Represent a value stored in the cache. - - :class:`.CachedValue` is a two-tuple of - ``(payload, metadata)``, where ``metadata`` - is dogpile.cache's tracking information ( - currently the creation time). The metadata - and tuple structure is pickleable, if - the backend requires serialization. - - """ - payload = property(operator.itemgetter(0)) - """Named accessor for the payload.""" - - metadata = property(operator.itemgetter(1)) - """Named accessor for the dogpile.cache metadata dictionary.""" - - def __new__(cls, payload, metadata): - return tuple.__new__(cls, (payload, metadata)) - - def __reduce__(self): - return CachedValue, (self.payload, self.metadata) - - -class CacheBackend(object): - """Base class for backend implementations.""" - - key_mangler = None - """Key mangling function. - - May be None, or otherwise declared - as an ordinary instance method. - - """ - - def __init__(self, arguments): # pragma NO COVERAGE - """Construct a new :class:`.CacheBackend`. - - Subclasses should override this to - handle the given arguments. - - :param arguments: The ``arguments`` parameter - passed to :func:`.make_registry`. - - """ - raise NotImplementedError() - - @classmethod - def from_config_dict(cls, config_dict, prefix): - prefix_len = len(prefix) - return cls( - dict( - (key[prefix_len:], config_dict[key]) - for key in config_dict - if key.startswith(prefix) - ) - ) - - def get_mutex(self, key): - """Return an optional mutexing object for the given key. - - This object need only provide an ``acquire()`` - and ``release()`` method. - - May return ``None``, in which case the dogpile - lock will use a regular ``threading.Lock`` - object to mutex concurrent threads for - value creation. The default implementation - returns ``None``. - - Different backends may want to provide various - kinds of "mutex" objects, such as those which - link to lock files, distributed mutexes, - memcached semaphores, etc. Whatever - kind of system is best suited for the scope - and behavior of the caching backend. - - A mutex that takes the key into account will - allow multiple regenerate operations across - keys to proceed simultaneously, while a mutex - that does not will serialize regenerate operations - to just one at a time across all keys in the region. - The latter approach, or a variant that involves - a modulus of the given key's hash value, - can be used as a means of throttling the total - number of value recreation operations that may - proceed at one time. - - """ - return None - - def get(self, key): # pragma NO COVERAGE - """Retrieve a value from the cache. - - The returned value should be an instance of - :class:`.CachedValue`, or ``NO_VALUE`` if - not present. - - """ - raise NotImplementedError() - - def get_multi(self, keys): # pragma NO COVERAGE - """Retrieve multiple values from the cache. - - The returned value should be a list, corresponding - to the list of keys given. - - .. versionadded:: 0.5.0 - - """ - raise NotImplementedError() - - def set(self, key, value): # pragma NO COVERAGE - """Set a value in the cache. - - The key will be whatever was passed - to the registry, processed by the - "key mangling" function, if any. - The value will always be an instance - of :class:`.CachedValue`. - - """ - raise NotImplementedError() - - def set_multi(self, mapping): # pragma NO COVERAGE - """Set multiple values in the cache. - - The key will be whatever was passed - to the registry, processed by the - "key mangling" function, if any. - The value will always be an instance - of :class:`.CachedValue`. - - .. versionadded:: 0.5.0 - - """ - raise NotImplementedError() - - def delete(self, key): # pragma NO COVERAGE - """Delete a value from the cache. - - The key will be whatever was passed - to the registry, processed by the - "key mangling" function, if any. - - The behavior here should be idempotent, - that is, can be called any number of times - regardless of whether or not the - key exists. - """ - raise NotImplementedError() - - def delete_multi(self, keys): # pragma NO COVERAGE - """Delete multiple values from the cache. - - The key will be whatever was passed - to the registry, processed by the - "key mangling" function, if any. - - The behavior here should be idempotent, - that is, can be called any number of times - regardless of whether or not the - key exists. - - .. versionadded:: 0.5.0 - - """ - raise NotImplementedError() diff --git a/awx/lib/site-packages/dogpile/cache/backends/__init__.py b/awx/lib/site-packages/dogpile/cache/backends/__init__.py deleted file mode 100644 index 041f05a3ed..0000000000 --- a/awx/lib/site-packages/dogpile/cache/backends/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -from dogpile.cache.region import register_backend - -register_backend( - "dogpile.cache.null", "dogpile.cache.backends.null", "NullBackend") -register_backend( - "dogpile.cache.dbm", "dogpile.cache.backends.file", "DBMBackend") -register_backend( - "dogpile.cache.pylibmc", "dogpile.cache.backends.memcached", - "PylibmcBackend") -register_backend( - "dogpile.cache.bmemcached", "dogpile.cache.backends.memcached", - "BMemcachedBackend") -register_backend( - "dogpile.cache.memcached", "dogpile.cache.backends.memcached", - "MemcachedBackend") -register_backend( - "dogpile.cache.memory", "dogpile.cache.backends.memory", "MemoryBackend") -register_backend( - "dogpile.cache.memory_pickle", "dogpile.cache.backends.memory", - "MemoryPickleBackend") -register_backend( - "dogpile.cache.redis", "dogpile.cache.backends.redis", "RedisBackend") diff --git a/awx/lib/site-packages/dogpile/cache/backends/file.py b/awx/lib/site-packages/dogpile/cache/backends/file.py deleted file mode 100644 index 42d749299c..0000000000 --- a/awx/lib/site-packages/dogpile/cache/backends/file.py +++ /dev/null @@ -1,447 +0,0 @@ -""" -File Backends ------------------- - -Provides backends that deal with local filesystem access. - -""" - -from __future__ import with_statement -from dogpile.cache.api import CacheBackend, NO_VALUE -from contextlib import contextmanager -from dogpile.cache import compat -from dogpile.cache import util -import os - -__all__ = 'DBMBackend', 'FileLock', 'AbstractFileLock' - - -class DBMBackend(CacheBackend): - """A file-backend using a dbm file to store keys. - - Basic usage:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.dbm', - expiration_time = 3600, - arguments = { - "filename":"/path/to/cachefile.dbm" - } - ) - - DBM access is provided using the Python ``anydbm`` module, - which selects a platform-specific dbm module to use. - This may be made to be more configurable in a future - release. - - Note that different dbm modules have different behaviors. - Some dbm implementations handle their own locking, while - others don't. The :class:`.DBMBackend` uses a read/write - lockfile by default, which is compatible even with those - DBM implementations for which this is unnecessary, - though the behavior can be disabled. - - The DBM backend by default makes use of two lockfiles. - One is in order to protect the DBM file itself from - concurrent writes, the other is to coordinate - value creation (i.e. the dogpile lock). By default, - these lockfiles use the ``flock()`` system call - for locking; this is **only available on Unix - platforms**. An alternative lock implementation, such as one - which is based on threads or uses a third-party system - such as `portalocker <https://pypi.python.org/pypi/portalocker>`_, - can be dropped in using the ``lock_factory`` argument - in conjunction with the :class:`.AbstractFileLock` base class. - - Currently, the dogpile lock is against the entire - DBM file, not per key. This means there can - only be one "creator" job running at a time - per dbm file. - - A future improvement might be to have the dogpile lock - using a filename that's based on a modulus of the key. - Locking on a filename that uniquely corresponds to the - key is problematic, since it's not generally safe to - delete lockfiles as the application runs, implying an - unlimited number of key-based files would need to be - created and never deleted. - - Parameters to the ``arguments`` dictionary are - below. - - :param filename: path of the filename in which to - create the DBM file. Note that some dbm backends - will change this name to have additional suffixes. - :param rw_lockfile: the name of the file to use for - read/write locking. If omitted, a default name - is used by appending the suffix ".rw.lock" to the - DBM filename. If False, then no lock is used. - :param dogpile_lockfile: the name of the file to use - for value creation, i.e. the dogpile lock. If - omitted, a default name is used by appending the - suffix ".dogpile.lock" to the DBM filename. If - False, then dogpile.cache uses the default dogpile - lock, a plain thread-based mutex. - :param lock_factory: a function or class which provides - for a read/write lock. Defaults to :class:`.FileLock`. - Custom implementations need to implement context-manager - based ``read()`` and ``write()`` functions - the - :class:`.AbstractFileLock` class is provided as a base class - which provides these methods based on individual read/write lock - functions. E.g. to replace the lock with the dogpile.core - :class:`.ReadWriteMutex`:: - - from dogpile.core.readwrite_lock import ReadWriteMutex - from dogpile.cache.backends.file import AbstractFileLock - - class MutexLock(AbstractFileLock): - def __init__(self, filename): - self.mutex = ReadWriteMutex() - - def acquire_read_lock(self, wait): - ret = self.mutex.acquire_read_lock(wait) - return wait or ret - - def acquire_write_lock(self, wait): - ret = self.mutex.acquire_write_lock(wait) - return wait or ret - - def release_read_lock(self): - return self.mutex.release_read_lock() - - def release_write_lock(self): - return self.mutex.release_write_lock() - - from dogpile.cache import make_region - - region = make_region().configure( - "dogpile.cache.dbm", - expiration_time=300, - arguments={ - "filename": "file.dbm", - "lock_factory": MutexLock - } - ) - - While the included :class:`.FileLock` uses ``os.flock()``, a - windows-compatible implementation can be built using a library - such as `portalocker <https://pypi.python.org/pypi/portalocker>`_. - - .. versionadded:: 0.5.2 - - - - """ - def __init__(self, arguments): - self.filename = os.path.abspath( - os.path.normpath(arguments['filename']) - ) - dir_, filename = os.path.split(self.filename) - - self.lock_factory = arguments.get("lock_factory", FileLock) - self._rw_lock = self._init_lock( - arguments.get('rw_lockfile'), - ".rw.lock", dir_, filename) - self._dogpile_lock = self._init_lock( - arguments.get('dogpile_lockfile'), - ".dogpile.lock", - dir_, filename, - util.KeyReentrantMutex.factory) - - # TODO: make this configurable - if compat.py3k: - import dbm - else: - import anydbm as dbm - self.dbmmodule = dbm - self._init_dbm_file() - - def _init_lock(self, argument, suffix, basedir, basefile, wrapper=None): - if argument is None: - lock = self.lock_factory(os.path.join(basedir, basefile + suffix)) - elif argument is not False: - lock = self.lock_factory( - os.path.abspath( - os.path.normpath(argument) - )) - else: - return None - if wrapper: - lock = wrapper(lock) - return lock - - def _init_dbm_file(self): - exists = os.access(self.filename, os.F_OK) - if not exists: - for ext in ('db', 'dat', 'pag', 'dir'): - if os.access(self.filename + os.extsep + ext, os.F_OK): - exists = True - break - if not exists: - fh = self.dbmmodule.open(self.filename, 'c') - fh.close() - - def get_mutex(self, key): - # using one dogpile for the whole file. Other ways - # to do this might be using a set of files keyed to a - # hash/modulus of the key. the issue is it's never - # really safe to delete a lockfile as this can - # break other processes trying to get at the file - # at the same time - so handling unlimited keys - # can't imply unlimited filenames - if self._dogpile_lock: - return self._dogpile_lock(key) - else: - return None - - @contextmanager - def _use_rw_lock(self, write): - if self._rw_lock is None: - yield - elif write: - with self._rw_lock.write(): - yield - else: - with self._rw_lock.read(): - yield - - @contextmanager - def _dbm_file(self, write): - with self._use_rw_lock(write): - dbm = self.dbmmodule.open( - self.filename, - "w" if write else "r") - yield dbm - dbm.close() - - def get(self, key): - with self._dbm_file(False) as dbm: - if hasattr(dbm, 'get'): - value = dbm.get(key, NO_VALUE) - else: - # gdbm objects lack a .get method - try: - value = dbm[key] - except KeyError: - value = NO_VALUE - if value is not NO_VALUE: - value = compat.pickle.loads(value) - return value - - def get_multi(self, keys): - return [self.get(key) for key in keys] - - def set(self, key, value): - with self._dbm_file(True) as dbm: - dbm[key] = compat.pickle.dumps(value, - compat.pickle.HIGHEST_PROTOCOL) - - def set_multi(self, mapping): - with self._dbm_file(True) as dbm: - for key, value in mapping.items(): - dbm[key] = compat.pickle.dumps(value, - compat.pickle.HIGHEST_PROTOCOL) - - def delete(self, key): - with self._dbm_file(True) as dbm: - try: - del dbm[key] - except KeyError: - pass - - def delete_multi(self, keys): - with self._dbm_file(True) as dbm: - for key in keys: - try: - del dbm[key] - except KeyError: - pass - - -class AbstractFileLock(object): - """Coordinate read/write access to a file. - - typically is a file-based lock but doesn't necessarily have to be. - - The default implementation here is :class:`.FileLock`. - - Implementations should provide the following methods:: - - * __init__() - * acquire_read_lock() - * acquire_write_lock() - * release_read_lock() - * release_write_lock() - - The ``__init__()`` method accepts a single argument "filename", which - may be used as the "lock file", for those implementations that use a lock - file. - - Note that multithreaded environments must provide a thread-safe - version of this lock. The recommended approach for file- - descriptor-based locks is to use a Python ``threading.local()`` so - that a unique file descriptor is held per thread. See the source - code of :class:`.FileLock` for an implementation example. - - - """ - - def __init__(self, filename): - """Constructor, is given the filename of a potential lockfile. - - The usage of this filename is optional and no file is - created by default. - - Raises ``NotImplementedError`` by default, must be - implemented by subclasses. - """ - raise NotImplementedError() - - def acquire(self, wait=True): - """Acquire the "write" lock. - - This is a direct call to :meth:`.AbstractFileLock.acquire_write_lock`. - - """ - return self.acquire_write_lock(wait) - - def release(self): - """Release the "write" lock. - - This is a direct call to :meth:`.AbstractFileLock.release_write_lock`. - - """ - self.release_write_lock() - - @contextmanager - def read(self): - """Provide a context manager for the "read" lock. - - This method makes use of :meth:`.AbstractFileLock.acquire_read_lock` - and :meth:`.AbstractFileLock.release_read_lock` - - """ - - self.acquire_read_lock(True) - try: - yield - finally: - self.release_read_lock() - - @contextmanager - def write(self): - """Provide a context manager for the "write" lock. - - This method makes use of :meth:`.AbstractFileLock.acquire_write_lock` - and :meth:`.AbstractFileLock.release_write_lock` - - """ - - self.acquire_write_lock(True) - try: - yield - finally: - self.release_write_lock() - - @property - def is_open(self): - """optional method.""" - raise NotImplementedError() - - def acquire_read_lock(self, wait): - """Acquire a 'reader' lock. - - Raises ``NotImplementedError`` by default, must be - implemented by subclasses. - """ - raise NotImplementedError() - - def acquire_write_lock(self, wait): - """Acquire a 'write' lock. - - Raises ``NotImplementedError`` by default, must be - implemented by subclasses. - """ - raise NotImplementedError() - - def release_read_lock(self): - """Release a 'reader' lock. - - Raises ``NotImplementedError`` by default, must be - implemented by subclasses. - """ - raise NotImplementedError() - - def release_write_lock(self): - """Release a 'writer' lock. - - Raises ``NotImplementedError`` by default, must be - implemented by subclasses. - """ - raise NotImplementedError() - - -class FileLock(AbstractFileLock): - """Use lockfiles to coordinate read/write access to a file. - - Only works on Unix systems, using - `fcntl.flock() <http://docs.python.org/library/fcntl.html>`_. - - """ - - def __init__(self, filename): - self._filedescriptor = compat.threading.local() - self.filename = filename - - @util.memoized_property - def _module(self): - import fcntl - return fcntl - - @property - def is_open(self): - return hasattr(self._filedescriptor, 'fileno') - - def acquire_read_lock(self, wait): - return self._acquire(wait, os.O_RDONLY, self._module.LOCK_SH) - - def acquire_write_lock(self, wait): - return self._acquire(wait, os.O_WRONLY, self._module.LOCK_EX) - - def release_read_lock(self): - self._release() - - def release_write_lock(self): - self._release() - - def _acquire(self, wait, wrflag, lockflag): - wrflag |= os.O_CREAT - fileno = os.open(self.filename, wrflag) - try: - if not wait: - lockflag |= self._module.LOCK_NB - self._module.flock(fileno, lockflag) - except IOError: - os.close(fileno) - if not wait: - # this is typically - # "[Errno 35] Resource temporarily unavailable", - # because of LOCK_NB - return False - else: - raise - else: - self._filedescriptor.fileno = fileno - return True - - def _release(self): - try: - fileno = self._filedescriptor.fileno - except AttributeError: - return - else: - self._module.flock(fileno, self._module.LOCK_UN) - os.close(fileno) - del self._filedescriptor.fileno diff --git a/awx/lib/site-packages/dogpile/cache/backends/memcached.py b/awx/lib/site-packages/dogpile/cache/backends/memcached.py deleted file mode 100644 index 80acc77b42..0000000000 --- a/awx/lib/site-packages/dogpile/cache/backends/memcached.py +++ /dev/null @@ -1,351 +0,0 @@ -""" -Memcached Backends ------------------- - -Provides backends for talking to `memcached <http://memcached.org>`_. - -""" - -from dogpile.cache.api import CacheBackend, NO_VALUE -from dogpile.cache import compat -from dogpile.cache import util -import random -import time - -__all__ = 'GenericMemcachedBackend', 'MemcachedBackend',\ - 'PylibmcBackend', 'BMemcachedBackend', 'MemcachedLock' - - -class MemcachedLock(object): - """Simple distributed lock using memcached. - - This is an adaptation of the lock featured at - http://amix.dk/blog/post/19386 - - """ - - def __init__(self, client_fn, key): - self.client_fn = client_fn - self.key = "_lock" + key - - def acquire(self, wait=True): - client = self.client_fn() - i = 0 - while True: - if client.add(self.key, 1): - return True - elif not wait: - return False - else: - sleep_time = (((i + 1) * random.random()) + 2 ** i) / 2.5 - time.sleep(sleep_time) - if i < 15: - i += 1 - - def release(self): - client = self.client_fn() - client.delete(self.key) - - -class GenericMemcachedBackend(CacheBackend): - """Base class for memcached backends. - - This base class accepts a number of paramters - common to all backends. - - :param url: the string URL to connect to. Can be a single - string or a list of strings. This is the only argument - that's required. - :param distributed_lock: boolean, when True, will use a - memcached-lock as the dogpile lock (see :class:`.MemcachedLock`). - Use this when multiple - processes will be talking to the same memcached instance. - When left at False, dogpile will coordinate on a regular - threading mutex. - :param memcached_expire_time: integer, when present will - be passed as the ``time`` parameter to ``pylibmc.Client.set``. - This is used to set the memcached expiry time for a value. - - .. note:: - - This parameter is **different** from Dogpile's own - ``expiration_time``, which is the number of seconds after - which Dogpile will consider the value to be expired. - When Dogpile considers a value to be expired, - it **continues to use the value** until generation - of a new value is complete, when using - :meth:`.CacheRegion.get_or_create`. - Therefore, if you are setting ``memcached_expire_time``, you'll - want to make sure it is greater than ``expiration_time`` - by at least enough seconds for new values to be generated, - else the value won't be available during a regeneration, - forcing all threads to wait for a regeneration each time - a value expires. - - The :class:`.GenericMemachedBackend` uses a ``threading.local()`` - object to store individual client objects per thread, - as most modern memcached clients do not appear to be inherently - threadsafe. - - In particular, ``threading.local()`` has the advantage over pylibmc's - built-in thread pool in that it automatically discards objects - associated with a particular thread when that thread ends. - - """ - - set_arguments = {} - """Additional arguments which will be passed - to the :meth:`set` method.""" - - def __init__(self, arguments): - self._imports() - # using a plain threading.local here. threading.local - # automatically deletes the __dict__ when a thread ends, - # so the idea is that this is superior to pylibmc's - # own ThreadMappedPool which doesn't handle this - # automatically. - self.url = util.to_list(arguments['url']) - self.distributed_lock = arguments.get('distributed_lock', False) - self.memcached_expire_time = arguments.get( - 'memcached_expire_time', 0) - - def _imports(self): - """client library imports go here.""" - raise NotImplementedError() - - def _create_client(self): - """Creation of a Client instance goes here.""" - raise NotImplementedError() - - @util.memoized_property - def _clients(self): - backend = self - - class ClientPool(compat.threading.local): - def __init__(self): - self.memcached = backend._create_client() - - return ClientPool() - - @property - def client(self): - """Return the memcached client. - - This uses a threading.local by - default as it appears most modern - memcached libs aren't inherently - threadsafe. - - """ - return self._clients.memcached - - def get_mutex(self, key): - if self.distributed_lock: - return MemcachedLock(lambda: self.client, key) - else: - return None - - def get(self, key): - value = self.client.get(key) - if value is None: - return NO_VALUE - else: - return value - - def get_multi(self, keys): - values = self.client.get_multi(keys) - return [ - NO_VALUE if key not in values - else values[key] for key in keys - ] - - def set(self, key, value): - self.client.set( - key, - value, - **self.set_arguments - ) - - def set_multi(self, mapping): - self.client.set_multi( - mapping, - **self.set_arguments - ) - - def delete(self, key): - self.client.delete(key) - - def delete_multi(self, keys): - self.client.delete_multi(keys) - - -class MemcacheArgs(object): - """Mixin which provides support for the 'time' argument to set(), - 'min_compress_len' to other methods. - - """ - def __init__(self, arguments): - self.min_compress_len = arguments.get('min_compress_len', 0) - - self.set_arguments = {} - if "memcached_expire_time" in arguments: - self.set_arguments["time"] = arguments["memcached_expire_time"] - if "min_compress_len" in arguments: - self.set_arguments["min_compress_len"] = \ - arguments["min_compress_len"] - super(MemcacheArgs, self).__init__(arguments) - -pylibmc = None - - -class PylibmcBackend(MemcacheArgs, GenericMemcachedBackend): - """A backend for the - `pylibmc <http://sendapatch.se/projects/pylibmc/index.html>`_ - memcached client. - - A configuration illustrating several of the optional - arguments described in the pylibmc documentation:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.pylibmc', - expiration_time = 3600, - arguments = { - 'url':["127.0.0.1"], - 'binary':True, - 'behaviors':{"tcp_nodelay": True,"ketama":True} - } - ) - - Arguments accepted here include those of - :class:`.GenericMemcachedBackend`, as well as - those below. - - :param binary: sets the ``binary`` flag understood by - ``pylibmc.Client``. - :param behaviors: a dictionary which will be passed to - ``pylibmc.Client`` as the ``behaviors`` parameter. - :param min_compress_len: Integer, will be passed as the - ``min_compress_len`` parameter to the ``pylibmc.Client.set`` - method. - - """ - - def __init__(self, arguments): - self.binary = arguments.get('binary', False) - self.behaviors = arguments.get('behaviors', {}) - super(PylibmcBackend, self).__init__(arguments) - - def _imports(self): - global pylibmc - import pylibmc # noqa - - def _create_client(self): - return pylibmc.Client( - self.url, - binary=self.binary, - behaviors=self.behaviors - ) - -memcache = None - - -class MemcachedBackend(MemcacheArgs, GenericMemcachedBackend): - """A backend using the standard - `Python-memcached <http://www.tummy.com/Community/software/\ - python-memcached/>`_ - library. - - Example:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.memcached', - expiration_time = 3600, - arguments = { - 'url':"127.0.0.1:11211" - } - ) - - """ - def _imports(self): - global memcache - import memcache # noqa - - def _create_client(self): - return memcache.Client(self.url) - - -bmemcached = None - - -class BMemcachedBackend(GenericMemcachedBackend): - """A backend for the - `python-binary-memcached <https://github.com/jaysonsantos/\ - python-binary-memcached>`_ - memcached client. - - This is a pure Python memcached client which - includes the ability to authenticate with a memcached - server using SASL. - - A typical configuration using username/password:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.bmemcached', - expiration_time = 3600, - arguments = { - 'url':["127.0.0.1"], - 'username':'scott', - 'password':'tiger' - } - ) - - Arguments which can be passed to the ``arguments`` - dictionary include: - - :param username: optional username, will be used for - SASL authentication. - :param password: optional password, will be used for - SASL authentication. - - """ - def __init__(self, arguments): - self.username = arguments.get('username', None) - self.password = arguments.get('password', None) - super(BMemcachedBackend, self).__init__(arguments) - - def _imports(self): - global bmemcached - import bmemcached - - class RepairBMemcachedAPI(bmemcached.Client): - """Repairs BMemcached's non-standard method - signatures, which was fixed in BMemcached - ef206ed4473fec3b639e. - - """ - - def add(self, key, value): - try: - return super(RepairBMemcachedAPI, self).add(key, value) - except ValueError: - return False - - self.Client = RepairBMemcachedAPI - - def _create_client(self): - return self.Client( - self.url, - username=self.username, - password=self.password - ) - - def delete_multi(self, keys): - """python-binary-memcached api does not implements delete_multi""" - for key in keys: - self.delete(key) diff --git a/awx/lib/site-packages/dogpile/cache/backends/memory.py b/awx/lib/site-packages/dogpile/cache/backends/memory.py deleted file mode 100644 index 2f9bd3a4ec..0000000000 --- a/awx/lib/site-packages/dogpile/cache/backends/memory.py +++ /dev/null @@ -1,124 +0,0 @@ -""" -Memory Backends ---------------- - -Provides simple dictionary-based backends. - -The two backends are :class:`.MemoryBackend` and :class:`.MemoryPickleBackend`; -the latter applies a serialization step to cached values while the former -places the value as given into the dictionary. - -""" - -from dogpile.cache.api import CacheBackend, NO_VALUE -from dogpile.cache.compat import pickle - - -class MemoryBackend(CacheBackend): - """A backend that uses a plain dictionary. - - There is no size management, and values which - are placed into the dictionary will remain - until explicitly removed. Note that - Dogpile's expiration of items is based on - timestamps and does not remove them from - the cache. - - E.g.:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.memory' - ) - - - To use a Python dictionary of your choosing, - it can be passed in with the ``cache_dict`` - argument:: - - my_dictionary = {} - region = make_region().configure( - 'dogpile.cache.memory', - arguments={ - "cache_dict":my_dictionary - } - ) - - - """ - pickle_values = False - - def __init__(self, arguments): - self._cache = arguments.pop("cache_dict", {}) - - def get(self, key): - value = self._cache.get(key, NO_VALUE) - if value is not NO_VALUE and self.pickle_values: - value = pickle.loads(value) - return value - - def get_multi(self, keys): - ret = [ - self._cache.get(key, NO_VALUE) - for key in keys] - if self.pickle_values: - ret = [ - pickle.loads(value) - if value is not NO_VALUE else value - for value in ret - ] - return ret - - def set(self, key, value): - if self.pickle_values: - value = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) - self._cache[key] = value - - def set_multi(self, mapping): - pickle_values = self.pickle_values - for key, value in mapping.items(): - if pickle_values: - value = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) - self._cache[key] = value - - def delete(self, key): - self._cache.pop(key, None) - - def delete_multi(self, keys): - for key in keys: - self._cache.pop(key, None) - - -class MemoryPickleBackend(MemoryBackend): - """A backend that uses a plain dictionary, but serializes objects on - :meth:`.MemoryBackend.set` and deserializes :meth:`.MemoryBackend.get`. - - E.g.:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.memory_pickle' - ) - - The usage of pickle to serialize cached values allows an object - as placed in the cache to be a copy of the original given object, so - that any subsequent changes to the given object aren't reflected - in the cached value, thus making the backend behave the same way - as other backends which make use of serialization. - - The serialization is performed via pickle, and incurs the same - performance hit in doing so as that of other backends; in this way - the :class:`.MemoryPickleBackend` performance is somewhere in between - that of the pure :class:`.MemoryBackend` and the remote server oriented - backends such as that of Memcached or Redis. - - Pickle behavior here is the same as that of the Redis backend, using - either ``cPickle`` or ``pickle`` and specifying ``HIGHEST_PROTOCOL`` - upon serialize. - - .. versionadded:: 0.5.3 - - """ - pickle_values = True diff --git a/awx/lib/site-packages/dogpile/cache/backends/null.py b/awx/lib/site-packages/dogpile/cache/backends/null.py deleted file mode 100644 index c1f46a9d6d..0000000000 --- a/awx/lib/site-packages/dogpile/cache/backends/null.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Null Backend -------------- - -The Null backend does not do any caching at all. It can be -used to test behavior without caching, or as a means of disabling -caching for a region that is otherwise used normally. - -.. versionadded:: 0.5.4 - -""" - -from dogpile.cache.api import CacheBackend, NO_VALUE - - -__all__ = ['NullBackend'] - - -class NullLock(object): - def acquire(self): - pass - - def release(self): - pass - - -class NullBackend(CacheBackend): - """A "null" backend that effectively disables all cache operations. - - Basic usage:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.null' - ) - - """ - - def __init__(self, arguments): - pass - - def get_mutex(self, key): - return NullLock() - - def get(self, key): - return NO_VALUE - - def get_multi(self, keys): - return [NO_VALUE for k in keys] - - def set(self, key, value): - pass - - def set_multi(self, mapping): - pass - - def delete(self, key): - pass - - def delete_multi(self, keys): - pass diff --git a/awx/lib/site-packages/dogpile/cache/backends/redis.py b/awx/lib/site-packages/dogpile/cache/backends/redis.py deleted file mode 100644 index 7c6d1aab96..0000000000 --- a/awx/lib/site-packages/dogpile/cache/backends/redis.py +++ /dev/null @@ -1,180 +0,0 @@ -""" -Redis Backends ------------------- - -Provides backends for talking to `Redis <http://redis.io>`_. - -""" - -from __future__ import absolute_import -from dogpile.cache.api import CacheBackend, NO_VALUE -from dogpile.cache.compat import pickle, u - -redis = None - -__all__ = 'RedisBackend', - - -class RedisBackend(CacheBackend): - """A `Redis <http://redis.io/>`_ backend, using the - `redis-py <http://pypi.python.org/pypi/redis/>`_ backend. - - Example configuration:: - - from dogpile.cache import make_region - - region = make_region().configure( - 'dogpile.cache.redis', - arguments = { - 'host': 'localhost', - 'port': 6379, - 'db': 0, - 'redis_expiration_time': 60*60*2, # 2 hours - 'distributed_lock': True - } - ) - - Arguments accepted in the arguments dictionary: - - :param url: string. If provided, will override separate host/port/db - params. The format is that accepted by ``StrictRedis.from_url()``. - - .. versionadded:: 0.4.1 - - :param host: string, default is ``localhost``. - - :param password: string, default is no password. - - .. versionadded:: 0.4.1 - - :param port: integer, default is ``6379``. - - :param db: integer, default is ``0``. - - :param redis_expiration_time: integer, number of seconds after setting - a value that Redis should expire it. This should be larger than dogpile's - cache expiration. By default no expiration is set. - - :param distributed_lock: boolean, when True, will use a - redis-lock as the dogpile lock. - Use this when multiple - processes will be talking to the same redis instance. - When left at False, dogpile will coordinate on a regular - threading mutex. - - :param lock_timeout: integer, number of seconds after acquiring a lock that - Redis should expire it. This argument is only valid when - ``distributed_lock`` is ``True``. - - .. versionadded:: 0.5.0 - - :param socket_timeout: float, seconds for socket timeout. - Default is None (no timeout). - - .. versionadded:: 0.5.4 - - :param lock_sleep: integer, number of seconds to sleep when failed to - acquire a lock. This argument is only valid when - ``distributed_lock`` is ``True``. - - .. versionadded:: 0.5.0 - - :param connection_pool: ``redis.ConnectionPool`` object. If provided, - this object supersedes other connection arguments passed to the - ``redis.StrictRedis`` instance, including url and/or host as well as - socket_timeout, and will be passed to ``redis.StrictRedis`` as the - source of connectivity. - - .. versionadded:: 0.5.4 - - - """ - - def __init__(self, arguments): - self._imports() - self.url = arguments.pop('url', None) - self.host = arguments.pop('host', 'localhost') - self.password = arguments.pop('password', None) - self.port = arguments.pop('port', 6379) - self.db = arguments.pop('db', 0) - self.distributed_lock = arguments.get('distributed_lock', False) - self.socket_timeout = arguments.pop('socket_timeout', None) - - self.lock_timeout = arguments.get('lock_timeout', None) - self.lock_sleep = arguments.get('lock_sleep', 0.1) - - self.redis_expiration_time = arguments.pop('redis_expiration_time', 0) - self.connection_pool = arguments.get('connection_pool', None) - self.client = self._create_client() - - def _imports(self): - # defer imports until backend is used - global redis - import redis # noqa - - def _create_client(self): - if self.connection_pool is not None: - # the connection pool already has all other connection - # options present within, so here we disregard socket_timeout - # and others. - return redis.StrictRedis(connection_pool=self.connection_pool) - - args = {} - if self.socket_timeout: - args['socket_timeout'] = self.socket_timeout - - if self.url is not None: - args.update(url=self.url) - return redis.StrictRedis.from_url(**args) - else: - args.update( - host=self.host, password=self.password, - port=self.port, db=self.db - ) - return redis.StrictRedis(**args) - - def get_mutex(self, key): - if self.distributed_lock: - return self.client.lock(u('_lock{0}').format(key), - self.lock_timeout, self.lock_sleep) - else: - return None - - def get(self, key): - value = self.client.get(key) - if value is None: - return NO_VALUE - return pickle.loads(value) - - def get_multi(self, keys): - values = self.client.mget(keys) - return [ - pickle.loads(v) if v is not None else NO_VALUE - for v in values] - - def set(self, key, value): - if self.redis_expiration_time: - self.client.setex(key, self.redis_expiration_time, - pickle.dumps(value, pickle.HIGHEST_PROTOCOL)) - else: - self.client.set(key, pickle.dumps(value, pickle.HIGHEST_PROTOCOL)) - - def set_multi(self, mapping): - mapping = dict( - (k, pickle.dumps(v, pickle.HIGHEST_PROTOCOL)) - for k, v in mapping.items() - ) - - if not self.redis_expiration_time: - self.client.mset(mapping) - else: - pipe = self.client.pipeline() - for key, value in mapping.items(): - pipe.setex(key, self.redis_expiration_time, value) - pipe.execute() - - def delete(self, key): - self.client.delete(key) - - def delete_multi(self, keys): - self.client.delete(*keys) diff --git a/awx/lib/site-packages/dogpile/cache/compat.py b/awx/lib/site-packages/dogpile/cache/compat.py deleted file mode 100644 index 3e12ee65b5..0000000000 --- a/awx/lib/site-packages/dogpile/cache/compat.py +++ /dev/null @@ -1,65 +0,0 @@ -import sys - -py2k = sys.version_info < (3, 0) -py3k = sys.version_info >= (3, 0) -py32 = sys.version_info >= (3, 2) -py27 = sys.version_info >= (2, 7) -jython = sys.platform.startswith('java') -win32 = sys.platform.startswith('win') - -try: - import threading -except ImportError: - import dummy_threading as threading # noqa - - -if py3k: # pragma: no cover - string_types = str, - text_type = str - string_type = str - - if py32: - callable = callable - else: - def callable(fn): - return hasattr(fn, '__call__') - - def u(s): - return s - - def ue(s): - return s - - import configparser - import io - import _thread as thread -else: - string_types = basestring, - text_type = unicode - string_type = str - - def u(s): - return unicode(s, "utf-8") - - def ue(s): - return unicode(s, "unicode_escape") - - import ConfigParser as configparser # noqa - import StringIO as io # noqa - - callable = callable # noqa - import thread # noqa - - -if py3k or jython: - import pickle -else: - import cPickle as pickle # noqa - - -def timedelta_total_seconds(td): - if py27: - return td.total_seconds() - else: - return (td.microseconds + ( - td.seconds + td.days * 24 * 3600) * 1e6) / 1e6 diff --git a/awx/lib/site-packages/dogpile/cache/exception.py b/awx/lib/site-packages/dogpile/cache/exception.py deleted file mode 100644 index 58068f8bc1..0000000000 --- a/awx/lib/site-packages/dogpile/cache/exception.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Exception classes for dogpile.cache.""" - - -class DogpileCacheException(Exception): - """Base Exception for dogpile.cache exceptions to inherit from.""" - - -class RegionAlreadyConfigured(DogpileCacheException): - """CacheRegion instance is already configured.""" - - -class RegionNotConfigured(DogpileCacheException): - """CacheRegion instance has not been configured.""" - - -class ValidationError(DogpileCacheException): - """Error validating a value or option.""" diff --git a/awx/lib/site-packages/dogpile/cache/plugins/__init__.py b/awx/lib/site-packages/dogpile/cache/plugins/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/dogpile/cache/plugins/mako_cache.py b/awx/lib/site-packages/dogpile/cache/plugins/mako_cache.py deleted file mode 100644 index 61f4ffaf32..0000000000 --- a/awx/lib/site-packages/dogpile/cache/plugins/mako_cache.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -Mako Integration ----------------- - -dogpile.cache includes a `Mako <http://www.makotemplates.org>`_ plugin -that replaces `Beaker <http://beaker.groovie.org>`_ -as the cache backend. -Setup a Mako template lookup using the "dogpile.cache" cache implementation -and a region dictionary:: - - from dogpile.cache import make_region - from mako.lookup import TemplateLookup - - my_regions = { - "local":make_region().configure( - "dogpile.cache.dbm", - expiration_time=360, - arguments={"filename":"file.dbm"} - ), - "memcached":make_region().configure( - "dogpile.cache.pylibmc", - expiration_time=3600, - arguments={"url":["127.0.0.1"]} - ) - } - - mako_lookup = TemplateLookup( - directories=["/myapp/templates"], - cache_impl="dogpile.cache", - cache_args={ - 'regions':my_regions - } - ) - -To use the above configuration in a template, use the ``cached=True`` -argument on any Mako tag which accepts it, in conjunction with the -name of the desired region as the ``cache_region`` argument:: - - <%def name="mysection()" cached="True" cache_region="memcached"> - some content that's cached - </%def> - - -""" -from mako.cache import CacheImpl - - -class MakoPlugin(CacheImpl): - """A Mako ``CacheImpl`` which talks to dogpile.cache.""" - - def __init__(self, cache): - super(MakoPlugin, self).__init__(cache) - try: - self.regions = self.cache.template.cache_args['regions'] - except KeyError: - raise KeyError( - "'cache_regions' argument is required on the " - "Mako Lookup or Template object for usage " - "with the dogpile.cache plugin.") - - def _get_region(self, **kw): - try: - region = kw['region'] - except KeyError: - raise KeyError( - "'cache_region' argument must be specified with 'cache=True'" - "within templates for usage with the dogpile.cache plugin.") - try: - return self.regions[region] - except KeyError: - raise KeyError("No such region '%s'" % region) - - def get_and_replace(self, key, creation_function, **kw): - expiration_time = kw.pop("timeout", None) - return self._get_region(**kw).get_or_create( - key, creation_function, - expiration_time=expiration_time) - - def get_or_create(self, key, creation_function, **kw): - return self.get_and_replace(key, creation_function, **kw) - - def put(self, key, value, **kw): - self._get_region(**kw).put(key, value) - - def get(self, key, **kw): - expiration_time = kw.pop("timeout", None) - return self._get_region(**kw).get(key, expiration_time=expiration_time) - - def invalidate(self, key, **kw): - self._get_region(**kw).delete(key) diff --git a/awx/lib/site-packages/dogpile/cache/proxy.py b/awx/lib/site-packages/dogpile/cache/proxy.py deleted file mode 100644 index 7fe49d6e5d..0000000000 --- a/awx/lib/site-packages/dogpile/cache/proxy.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -Proxy Backends ------------------- - -Provides a utility and a decorator class that allow for modifying the behavior -of different backends without altering the class itself or having to extend the -base backend. - -.. versionadded:: 0.5.0 Added support for the :class:`.ProxyBackend` class. - -""" - -from .api import CacheBackend - - -class ProxyBackend(CacheBackend): - """A decorator class for altering the functionality of backends. - - Basic usage:: - - from dogpile.cache import make_region - from dogpile.cache.proxy import ProxyBackend - - class MyFirstProxy(ProxyBackend): - def get(self, key): - # ... custom code goes here ... - return self.proxied.get(key) - - def set(self, key, value): - # ... custom code goes here ... - self.proxied.set(key) - - class MySecondProxy(ProxyBackend): - def get(self, key): - # ... custom code goes here ... - return self.proxied.get(key) - - - region = make_region().configure( - 'dogpile.cache.dbm', - expiration_time = 3600, - arguments = { - "filename":"/path/to/cachefile.dbm" - }, - wrap = [ MyFirstProxy, MySecondProxy ] - ) - - Classes that extend :class:`.ProxyBackend` can be stacked - together. The ``.proxied`` property will always - point to either the concrete backend instance or - the next proxy in the chain that a method can be - delegated towards. - - .. versionadded:: 0.5.0 - - """ - - def __init__(self, *args, **kwargs): - self.proxied = None - - def wrap(self, backend): - ''' Take a backend as an argument and setup the self.proxied property. - Return an object that be used as a backend by a :class:`.CacheRegion` - object. - ''' - assert( - isinstance(backend, CacheBackend) or - isinstance(backend, ProxyBackend)) - self.proxied = backend - return self - - # - # Delegate any functions that are not already overridden to - # the proxies backend - # - def get(self, key): - return self.proxied.get(key) - - def set(self, key, value): - self.proxied.set(key, value) - - def delete(self, key): - self.proxied.delete(key) - - def get_multi(self, keys): - return self.proxied.get_multi(keys) - - def set_multi(self, keys): - self.proxied.set_multi(keys) - - def delete_multi(self, keys): - self.proxied.delete_multi(keys) - - def get_mutex(self, key): - return self.proxied.get_mutex(key) diff --git a/awx/lib/site-packages/dogpile/cache/region.py b/awx/lib/site-packages/dogpile/cache/region.py deleted file mode 100644 index afa2b547c1..0000000000 --- a/awx/lib/site-packages/dogpile/cache/region.py +++ /dev/null @@ -1,1287 +0,0 @@ -from __future__ import with_statement -from dogpile.core import Lock, NeedRegenerationException -from dogpile.core.nameregistry import NameRegistry -from . import exception -from .util import function_key_generator, PluginLoader, \ - memoized_property, coerce_string_conf, function_multi_key_generator -from .api import NO_VALUE, CachedValue -from .proxy import ProxyBackend -from . import compat -import time -import datetime -from numbers import Number -from functools import wraps -import threading - -_backend_loader = PluginLoader("dogpile.cache") -register_backend = _backend_loader.register -from . import backends # noqa - -value_version = 1 -"""An integer placed in the :class:`.CachedValue` -so that new versions of dogpile.cache can detect cached -values from a previous, backwards-incompatible version. - -""" - - -class CacheRegion(object): - """A front end to a particular cache backend. - - :param name: Optional, a string name for the region. - This isn't used internally - but can be accessed via the ``.name`` parameter, helpful - for configuring a region from a config file. - :param function_key_generator: Optional. A - function that will produce a "cache key" given - a data creation function and arguments, when using - the :meth:`.CacheRegion.cache_on_arguments` method. - The structure of this function - should be two levels: given the data creation function, - return a new function that generates the key based on - the given arguments. Such as:: - - def my_key_generator(namespace, fn, **kw): - fname = fn.__name__ - def generate_key(*arg): - return namespace + "_" + fname + "_".join(str(s) for s in arg) - return generate_key - - - region = make_region( - function_key_generator = my_key_generator - ).configure( - "dogpile.cache.dbm", - expiration_time=300, - arguments={ - "filename":"file.dbm" - } - ) - - The ``namespace`` is that passed to - :meth:`.CacheRegion.cache_on_arguments`. It's not consulted - outside this function, so in fact can be of any form. - For example, it can be passed as a tuple, used to specify - arguments to pluck from \**kw:: - - def my_key_generator(namespace, fn): - def generate_key(*arg, **kw): - return ":".join( - [kw[k] for k in namespace] + - [str(x) for x in arg] - ) - return generate_key - - - Where the decorator might be used as:: - - @my_region.cache_on_arguments(namespace=('x', 'y')) - def my_function(a, b, **kw): - return my_data() - - :param function_multi_key_generator: Optional. - Similar to ``function_key_generator`` parameter, but it's used in - :meth:`.CacheRegion.cache_multi_on_arguments`. Generated function - should return list of keys. For example:: - - def my_multi_key_generator(namespace, fn, **kw): - namespace = fn.__name__ + (namespace or '') - - def generate_keys(*args): - return [namespace + ':' + str(a) for a in args] - - return generate_keys - - :param key_mangler: Function which will be used on all incoming - keys before passing to the backend. Defaults to ``None``, - in which case the key mangling function recommended by - the cache backend will be used. A typical mangler - is the SHA1 mangler found at :func:`.sha1_mangle_key` - which coerces keys into a SHA1 - hash, so that the string length is fixed. To - disable all key mangling, set to ``False``. Another typical - mangler is the built-in Python function ``str``, which can be used - to convert non-string or Unicode keys to bytestrings, which is - needed when using a backend such as bsddb or dbm under Python 2.x - in conjunction with Unicode keys. - :param async_creation_runner: A callable that, when specified, - will be passed to and called by dogpile.lock when - there is a stale value present in the cache. It will be passed the - mutex and is responsible releasing that mutex when finished. - This can be used to defer the computation of expensive creator - functions to later points in the future by way of, for example, a - background thread, a long-running queue, or a task manager system - like Celery. - - For a specific example using async_creation_runner, new values can - be created in a background thread like so:: - - import threading - - def async_creation_runner(cache, somekey, creator, mutex): - ''' Used by dogpile.core:Lock when appropriate ''' - def runner(): - try: - value = creator() - cache.set(somekey, value) - finally: - mutex.release() - - thread = threading.Thread(target=runner) - thread.start() - - - region = make_region( - async_creation_runner=async_creation_runner, - ).configure( - 'dogpile.cache.memcached', - expiration_time=5, - arguments={ - 'url': '127.0.0.1:11211', - 'distributed_lock': True, - } - ) - - Remember that the first request for a key with no associated - value will always block; async_creator will not be invoked. - However, subsequent requests for cached-but-expired values will - still return promptly. They will be refreshed by whatever - asynchronous means the provided async_creation_runner callable - implements. - - By default the async_creation_runner is disabled and is set - to ``None``. - - .. versionadded:: 0.4.2 added the async_creation_runner - feature. - - """ - - def __init__( - self, - name=None, - function_key_generator=function_key_generator, - function_multi_key_generator=function_multi_key_generator, - key_mangler=None, - async_creation_runner=None, - ): - """Construct a new :class:`.CacheRegion`.""" - self.name = name - self.function_key_generator = function_key_generator - self.function_multi_key_generator = function_multi_key_generator - if key_mangler: - self.key_mangler = key_mangler - else: - self.key_mangler = None - self._hard_invalidated = None - self._soft_invalidated = None - self.async_creation_runner = async_creation_runner - - def configure( - self, backend, - expiration_time=None, - arguments=None, - _config_argument_dict=None, - _config_prefix=None, - wrap=None - ): - """Configure a :class:`.CacheRegion`. - - The :class:`.CacheRegion` itself - is returned. - - :param backend: Required. This is the name of the - :class:`.CacheBackend` to use, and is resolved by loading - the class from the ``dogpile.cache`` entrypoint. - - :param expiration_time: Optional. The expiration time passed - to the dogpile system. May be passed as an integer number - of seconds, or as a ``datetime.timedelta`` value. - - .. versionadded 0.5.0 - ``expiration_time`` may be optionally passed as a - ``datetime.timedelta`` value. - - The :meth:`.CacheRegion.get_or_create` - method as well as the :meth:`.CacheRegion.cache_on_arguments` - decorator (though note: **not** the :meth:`.CacheRegion.get` - method) will call upon the value creation function after this - time period has passed since the last generation. - - :param arguments: Optional. The structure here is passed - directly to the constructor of the :class:`.CacheBackend` - in use, though is typically a dictionary. - - :param wrap: Optional. A list of :class:`.ProxyBackend` - classes and/or instances, each of which will be applied - in a chain to ultimately wrap the original backend, - so that custom functionality augmentation can be applied. - - .. versionadded:: 0.5.0 - - .. seealso:: - - :ref:`changing_backend_behavior` - - """ - - if "backend" in self.__dict__: - raise exception.RegionAlreadyConfigured( - "This region is already " - "configured with backend: %s" - % self.backend) - backend_cls = _backend_loader.load(backend) - if _config_argument_dict: - self.backend = backend_cls.from_config_dict( - _config_argument_dict, - _config_prefix - ) - else: - self.backend = backend_cls(arguments or {}) - - if not expiration_time or isinstance(expiration_time, Number): - self.expiration_time = expiration_time - elif isinstance(expiration_time, datetime.timedelta): - self.expiration_time = int( - compat.timedelta_total_seconds(expiration_time)) - else: - raise exception.ValidationError( - 'expiration_time is not a number or timedelta.') - - if self.key_mangler is None: - self.key_mangler = self.backend.key_mangler - - self._lock_registry = NameRegistry(self._create_mutex) - - if getattr(wrap, '__iter__', False): - for wrapper in reversed(wrap): - self.wrap(wrapper) - - return self - - def wrap(self, proxy): - ''' Takes a ProxyBackend instance or class and wraps the - attached backend. ''' - - # if we were passed a type rather than an instance then - # initialize it. - if type(proxy) == type: - proxy = proxy() - - if not issubclass(type(proxy), ProxyBackend): - raise TypeError("Type %s is not a valid ProxyBackend" - % type(proxy)) - - self.backend = proxy.wrap(self.backend) - - def _mutex(self, key): - return self._lock_registry.get(key) - - class _LockWrapper(object): - """weakref-capable wrapper for threading.Lock""" - def __init__(self): - self.lock = threading.Lock() - - def acquire(self, wait=True): - return self.lock.acquire(wait) - - def release(self): - self.lock.release() - - def _create_mutex(self, key): - mutex = self.backend.get_mutex(key) - if mutex is not None: - return mutex - else: - return self._LockWrapper() - - def invalidate(self, hard=True): - """Invalidate this :class:`.CacheRegion`. - - Invalidation works by setting a current timestamp - (using ``time.time()``) - representing the "minimum creation time" for - a value. Any retrieved value whose creation - time is prior to this timestamp - is considered to be stale. It does not - affect the data in the cache in any way, and is also - local to this instance of :class:`.CacheRegion`. - - Once set, the invalidation time is honored by - the :meth:`.CacheRegion.get_or_create`, - :meth:`.CacheRegion.get_or_create_multi` and - :meth:`.CacheRegion.get` methods. - - The method supports both "hard" and "soft" invalidation - options. With "hard" invalidation, - :meth:`.CacheRegion.get_or_create` will force an immediate - regeneration of the value which all getters will wait for. - With "soft" invalidation, subsequent getters will return the - "old" value until the new one is available. - - Usage of "soft" invalidation requires that the region or the method - is given a non-None expiration time. - - .. versionadded:: 0.3.0 - - :param hard: if True, cache values will all require immediate - regeneration; dogpile logic won't be used. If False, the - creation time of existing values will be pushed back before - the expiration time so that a return+regen will be invoked. - - .. versionadded:: 0.5.1 - - """ - if hard: - self._hard_invalidated = time.time() - self._soft_invalidated = None - else: - self._hard_invalidated = None - self._soft_invalidated = time.time() - - def configure_from_config(self, config_dict, prefix): - """Configure from a configuration dictionary - and a prefix. - - Example:: - - local_region = make_region() - memcached_region = make_region() - - # regions are ready to use for function - # decorators, but not yet for actual caching - - # later, when config is available - myconfig = { - "cache.local.backend":"dogpile.cache.dbm", - "cache.local.arguments.filename":"/path/to/dbmfile.dbm", - "cache.memcached.backend":"dogpile.cache.pylibmc", - "cache.memcached.arguments.url":"127.0.0.1, 10.0.0.1", - } - local_region.configure_from_config(myconfig, "cache.local.") - memcached_region.configure_from_config(myconfig, - "cache.memcached.") - - """ - config_dict = coerce_string_conf(config_dict) - return self.configure( - config_dict["%sbackend" % prefix], - expiration_time=config_dict.get( - "%sexpiration_time" % prefix, None), - _config_argument_dict=config_dict, - _config_prefix="%sarguments." % prefix, - wrap=config_dict.get( - "%swrap" % prefix, None), - ) - - @memoized_property - def backend(self): - raise exception.RegionNotConfigured( - "No backend is configured on this region.") - - @property - def is_configured(self): - """Return True if the backend has been configured via the - :meth:`.CacheRegion.configure` method already. - - .. versionadded:: 0.5.1 - - """ - return 'backend' in self.__dict__ - - def get(self, key, expiration_time=None, ignore_expiration=False): - """Return a value from the cache, based on the given key. - - If the value is not present, the method returns the token - ``NO_VALUE``. ``NO_VALUE`` evaluates to False, but is separate from - ``None`` to distinguish between a cached value of ``None``. - - By default, the configured expiration time of the - :class:`.CacheRegion`, or alternatively the expiration - time supplied by the ``expiration_time`` argument, - is tested against the creation time of the retrieved - value versus the current time (as reported by ``time.time()``). - If stale, the cached value is ignored and the ``NO_VALUE`` - token is returned. Passing the flag ``ignore_expiration=True`` - bypasses the expiration time check. - - .. versionchanged:: 0.3.0 - :meth:`.CacheRegion.get` now checks the value's creation time - against the expiration time, rather than returning - the value unconditionally. - - The method also interprets the cached value in terms - of the current "invalidation" time as set by - the :meth:`.invalidate` method. If a value is present, - but its creation time is older than the current - invalidation time, the ``NO_VALUE`` token is returned. - Passing the flag ``ignore_expiration=True`` bypasses - the invalidation time check. - - .. versionadded:: 0.3.0 - Support for the :meth:`.CacheRegion.invalidate` - method. - - :param key: Key to be retrieved. While it's typical for a key to be a - string, it is ultimately passed directly down to the cache backend, - before being optionally processed by the key_mangler function, so can - be of any type recognized by the backend or by the key_mangler - function, if present. - - :param expiration_time: Optional expiration time value - which will supersede that configured on the :class:`.CacheRegion` - itself. - - .. versionadded:: 0.3.0 - - :param ignore_expiration: if ``True``, the value is returned - from the cache if present, regardless of configured - expiration times or whether or not :meth:`.invalidate` - was called. - - .. versionadded:: 0.3.0 - - """ - - if self.key_mangler: - key = self.key_mangler(key) - value = self.backend.get(key) - value = self._unexpired_value_fn( - expiration_time, ignore_expiration)(value) - - return value.payload - - def _unexpired_value_fn(self, expiration_time, ignore_expiration): - if ignore_expiration: - return lambda value: value - else: - if expiration_time is None: - expiration_time = self.expiration_time - - current_time = time.time() - - invalidated = self._hard_invalidated or self._soft_invalidated - - def value_fn(value): - if value is NO_VALUE: - return value - elif expiration_time is not None and \ - current_time - value.metadata["ct"] > expiration_time: - return NO_VALUE - elif invalidated and \ - value.metadata["ct"] < invalidated: - return NO_VALUE - else: - return value - - return value_fn - - def get_multi(self, keys, expiration_time=None, ignore_expiration=False): - """Return multiple values from the cache, based on the given keys. - - Returns values as a list matching the keys given. - - E.g.:: - - values = region.get_multi(["one", "two", "three"]) - - To convert values to a dictionary, use ``zip()``:: - - keys = ["one", "two", "three"] - values = region.get_multi(keys) - dictionary = dict(zip(keys, values)) - - Keys which aren't present in the list are returned as - the ``NO_VALUE`` token. ``NO_VALUE`` evaluates to False, - but is separate from - ``None`` to distinguish between a cached value of ``None``. - - By default, the configured expiration time of the - :class:`.CacheRegion`, or alternatively the expiration - time supplied by the ``expiration_time`` argument, - is tested against the creation time of the retrieved - value versus the current time (as reported by ``time.time()``). - If stale, the cached value is ignored and the ``NO_VALUE`` - token is returned. Passing the flag ``ignore_expiration=True`` - bypasses the expiration time check. - - .. versionadded:: 0.5.0 - - """ - if not keys: - return [] - - if self.key_mangler: - keys = list(map(lambda key: self.key_mangler(key), keys)) - - backend_values = self.backend.get_multi(keys) - - _unexpired_value_fn = self._unexpired_value_fn( - expiration_time, ignore_expiration) - return [ - value.payload if value is not NO_VALUE else value - for value in - ( - _unexpired_value_fn(value) for value in - backend_values - ) - ] - - def get_or_create( - self, key, creator, expiration_time=None, should_cache_fn=None): - """Return a cached value based on the given key. - - If the value does not exist or is considered to be expired - based on its creation time, the given - creation function may or may not be used to recreate the value - and persist the newly generated value in the cache. - - Whether or not the function is used depends on if the - *dogpile lock* can be acquired or not. If it can't, it means - a different thread or process is already running a creation - function for this key against the cache. When the dogpile - lock cannot be acquired, the method will block if no - previous value is available, until the lock is released and - a new value available. If a previous value - is available, that value is returned immediately without blocking. - - If the :meth:`.invalidate` method has been called, and - the retrieved value's timestamp is older than the invalidation - timestamp, the value is unconditionally prevented from - being returned. The method will attempt to acquire the dogpile - lock to generate a new value, or will wait - until the lock is released to return the new value. - - .. versionchanged:: 0.3.0 - The value is unconditionally regenerated if the creation - time is older than the last call to :meth:`.invalidate`. - - :param key: Key to be retrieved. While it's typical for a key to be a - string, it is ultimately passed directly down to the cache backend, - before being optionally processed by the key_mangler function, so can - be of any type recognized by the backend or by the key_mangler - function, if present. - - :param creator: function which creates a new value. - - :param expiration_time: optional expiration time which will overide - the expiration time already configured on this :class:`.CacheRegion` - if not None. To set no expiration, use the value -1. - - :param should_cache_fn: optional callable function which will receive - the value returned by the "creator", and will then return True or - False, indicating if the value should actually be cached or not. If - it returns False, the value is still returned, but isn't cached. - E.g.:: - - def dont_cache_none(value): - return value is not None - - value = region.get_or_create("some key", - create_value, - should_cache_fn=dont_cache_none) - - Above, the function returns the value of create_value() if - the cache is invalid, however if the return value is None, - it won't be cached. - - .. versionadded:: 0.4.3 - - .. seealso:: - - :meth:`.CacheRegion.cache_on_arguments` - applies - :meth:`.get_or_create` to any function using a decorator. - - :meth:`.CacheRegion.get_or_create_multi` - multiple key/value - version - - """ - orig_key = key - if self.key_mangler: - key = self.key_mangler(key) - - def get_value(): - value = self.backend.get(key) - if value is NO_VALUE or \ - value.metadata['v'] != value_version or \ - ( - self._hard_invalidated and - value.metadata["ct"] < self._hard_invalidated): - raise NeedRegenerationException() - ct = value.metadata["ct"] - if self._soft_invalidated: - if ct < self._soft_invalidated: - ct = time.time() - expiration_time - .0001 - - return value.payload, ct - - def gen_value(): - created_value = creator() - value = self._value(created_value) - - if not should_cache_fn or \ - should_cache_fn(created_value): - self.backend.set(key, value) - - return value.payload, value.metadata["ct"] - - if expiration_time is None: - expiration_time = self.expiration_time - - if expiration_time is None and self._soft_invalidated: - raise exception.DogpileCacheException( - "Non-None expiration time required " - "for soft invalidation") - - if expiration_time == -1: - expiration_time = None - - if self.async_creation_runner: - def async_creator(mutex): - return self.async_creation_runner( - self, orig_key, creator, mutex) - else: - async_creator = None - - with Lock( - self._mutex(key), - gen_value, - get_value, - expiration_time, - async_creator) as value: - return value - - def get_or_create_multi( - self, keys, creator, expiration_time=None, should_cache_fn=None): - """Return a sequence of cached values based on a sequence of keys. - - The behavior for generation of values based on keys corresponds - to that of :meth:`.Region.get_or_create`, with the exception that - the ``creator()`` function may be asked to generate any subset of - the given keys. The list of keys to be generated is passed to - ``creator()``, and ``creator()`` should return the generated values - as a sequence corresponding to the order of the keys. - - The method uses the same approach as :meth:`.Region.get_multi` - and :meth:`.Region.set_multi` to get and set values from the - backend. - - :param keys: Sequence of keys to be retrieved. - - :param creator: function which accepts a sequence of keys and - returns a sequence of new values. - - :param expiration_time: optional expiration time which will overide - the expiration time already configured on this :class:`.CacheRegion` - if not None. To set no expiration, use the value -1. - - :param should_cache_fn: optional callable function which will receive - each value returned by the "creator", and will then return True or - False, indicating if the value should actually be cached or not. If - it returns False, the value is still returned, but isn't cached. - - .. versionadded:: 0.5.0 - - .. seealso:: - - - :meth:`.CacheRegion.cache_multi_on_arguments` - - :meth:`.CacheRegion.get_or_create` - - """ - - def get_value(key): - value = values.get(key, NO_VALUE) - - if value is NO_VALUE or \ - value.metadata['v'] != value_version or \ - (self._hard_invalidated and - value.metadata["ct"] < self._hard_invalidated): - # dogpile.core understands a 0 here as - # "the value is not available", e.g. - # _has_value() will return False. - return value.payload, 0 - else: - ct = value.metadata["ct"] - if self._soft_invalidated: - if ct < self._soft_invalidated: - ct = time.time() - expiration_time - .0001 - - return value.payload, ct - - def gen_value(): - raise NotImplementedError() - - def async_creator(key, mutex): - mutexes[key] = mutex - - if expiration_time is None: - expiration_time = self.expiration_time - - if expiration_time is None and self._soft_invalidated: - raise exception.DogpileCacheException( - "Non-None expiration time required " - "for soft invalidation") - - if expiration_time == -1: - expiration_time = None - - mutexes = {} - - sorted_unique_keys = sorted(set(keys)) - - if self.key_mangler: - mangled_keys = [self.key_mangler(k) for k in sorted_unique_keys] - else: - mangled_keys = sorted_unique_keys - - orig_to_mangled = dict(zip(sorted_unique_keys, mangled_keys)) - - values = dict(zip(mangled_keys, self.backend.get_multi(mangled_keys))) - - for orig_key, mangled_key in orig_to_mangled.items(): - with Lock( - self._mutex(mangled_key), - gen_value, - lambda: get_value(mangled_key), - expiration_time, - async_creator=lambda mutex: async_creator(orig_key, mutex) - ): - pass - try: - if mutexes: - # sort the keys, the idea is to prevent deadlocks. - # though haven't been able to simulate one anyway. - keys_to_get = sorted(mutexes) - new_values = creator(*keys_to_get) - - values_w_created = dict( - (orig_to_mangled[k], self._value(v)) - for k, v in zip(keys_to_get, new_values) - ) - - if not should_cache_fn: - self.backend.set_multi(values_w_created) - else: - self.backend.set_multi(dict( - (k, v) - for k, v in values_w_created.items() - if should_cache_fn(v[0]) - )) - - values.update(values_w_created) - return [values[orig_to_mangled[k]].payload for k in keys] - finally: - for mutex in mutexes.values(): - mutex.release() - - def _value(self, value): - """Return a :class:`.CachedValue` given a value.""" - return CachedValue( - value, - { - "ct": time.time(), - "v": value_version - }) - - def set(self, key, value): - """Place a new value in the cache under the given key.""" - - if self.key_mangler: - key = self.key_mangler(key) - self.backend.set(key, self._value(value)) - - def set_multi(self, mapping): - """Place new values in the cache under the given keys. - - .. versionadded:: 0.5.0 - - """ - if not mapping: - return - - if self.key_mangler: - mapping = dict(( - self.key_mangler(k), self._value(v)) - for k, v in mapping.items()) - else: - mapping = dict((k, self._value(v)) for k, v in mapping.items()) - self.backend.set_multi(mapping) - - def delete(self, key): - """Remove a value from the cache. - - This operation is idempotent (can be called multiple times, or on a - non-existent key, safely) - """ - - if self.key_mangler: - key = self.key_mangler(key) - - self.backend.delete(key) - - def delete_multi(self, keys): - """Remove multiple values from the cache. - - This operation is idempotent (can be called multiple times, or on a - non-existent key, safely) - - .. versionadded:: 0.5.0 - - """ - - if self.key_mangler: - keys = list(map(lambda key: self.key_mangler(key), keys)) - - self.backend.delete_multi(keys) - - def cache_on_arguments( - self, namespace=None, - expiration_time=None, - should_cache_fn=None, - to_str=compat.string_type, - function_key_generator=None): - """A function decorator that will cache the return - value of the function using a key derived from the - function itself and its arguments. - - The decorator internally makes use of the - :meth:`.CacheRegion.get_or_create` method to access the - cache and conditionally call the function. See that - method for additional behavioral details. - - E.g.:: - - @someregion.cache_on_arguments() - def generate_something(x, y): - return somedatabase.query(x, y) - - The decorated function can then be called normally, where - data will be pulled from the cache region unless a new - value is needed:: - - result = generate_something(5, 6) - - The function is also given an attribute ``invalidate()``, which - provides for invalidation of the value. Pass to ``invalidate()`` - the same arguments you'd pass to the function itself to represent - a particular value:: - - generate_something.invalidate(5, 6) - - Another attribute ``set()`` is added to provide extra caching - possibilities relative to the function. This is a convenience - method for :meth:`.CacheRegion.set` which will store a given - value directly without calling the decorated function. - The value to be cached is passed as the first argument, and the - arguments which would normally be passed to the function - should follow:: - - generate_something.set(3, 5, 6) - - The above example is equivalent to calling - ``generate_something(5, 6)``, if the function were to produce - the value ``3`` as the value to be cached. - - .. versionadded:: 0.4.1 Added ``set()`` method to decorated function. - - Similar to ``set()`` is ``refresh()``. This attribute will - invoke the decorated function and populate a new value into - the cache with the new value, as well as returning that value:: - - newvalue = generate_something.refresh(5, 6) - - .. versionadded:: 0.5.0 Added ``refresh()`` method to decorated - function. - - Lastly, the ``get()`` method returns either the value cached - for the given key, or the token ``NO_VALUE`` if no such key - exists:: - - value = generate_something.get(5, 6) - - .. versionadded:: 0.5.3 Added ``get()`` method to decorated - function. - - The default key generation will use the name - of the function, the module name for the function, - the arguments passed, as well as an optional "namespace" - parameter in order to generate a cache key. - - Given a function ``one`` inside the module - ``myapp.tools``:: - - @region.cache_on_arguments(namespace="foo") - def one(a, b): - return a + b - - Above, calling ``one(3, 4)`` will produce a - cache key as follows:: - - myapp.tools:one|foo|3 4 - - The key generator will ignore an initial argument - of ``self`` or ``cls``, making the decorator suitable - (with caveats) for use with instance or class methods. - Given the example:: - - class MyClass(object): - @region.cache_on_arguments(namespace="foo") - def one(self, a, b): - return a + b - - The cache key above for ``MyClass().one(3, 4)`` will - again produce the same cache key of ``myapp.tools:one|foo|3 4`` - - the name ``self`` is skipped. - - The ``namespace`` parameter is optional, and is used - normally to disambiguate two functions of the same - name within the same module, as can occur when decorating - instance or class methods as below:: - - class MyClass(object): - @region.cache_on_arguments(namespace='MC') - def somemethod(self, x, y): - "" - - class MyOtherClass(object): - @region.cache_on_arguments(namespace='MOC') - def somemethod(self, x, y): - "" - - Above, the ``namespace`` parameter disambiguates - between ``somemethod`` on ``MyClass`` and ``MyOtherClass``. - Python class declaration mechanics otherwise prevent - the decorator from having awareness of the ``MyClass`` - and ``MyOtherClass`` names, as the function is received - by the decorator before it becomes an instance method. - - The function key generation can be entirely replaced - on a per-region basis using the ``function_key_generator`` - argument present on :func:`.make_region` and - :class:`.CacheRegion`. If defaults to - :func:`.function_key_generator`. - - :param namespace: optional string argument which will be - established as part of the cache key. This may be needed - to disambiguate functions of the same name within the same - source file, such as those - associated with classes - note that the decorator itself - can't see the parent class on a function as the class is - being declared. - - :param expiration_time: if not None, will override the normal - expiration time. - - May be specified as a callable, taking no arguments, that - returns a value to be used as the ``expiration_time``. This callable - will be called whenever the decorated function itself is called, in - caching or retrieving. Thus, this can be used to - determine a *dynamic* expiration time for the cached function - result. Example use cases include "cache the result until the - end of the day, week or time period" and "cache until a certain date - or time passes". - - .. versionchanged:: 0.5.0 - ``expiration_time`` may be passed as a callable to - :meth:`.CacheRegion.cache_on_arguments`. - - :param should_cache_fn: passed to :meth:`.CacheRegion.get_or_create`. - - .. versionadded:: 0.4.3 - - :param to_str: callable, will be called on each function argument - in order to convert to a string. Defaults to ``str()``. If the - function accepts non-ascii unicode arguments on Python 2.x, the - ``unicode()`` builtin can be substituted, but note this will - produce unicode cache keys which may require key mangling before - reaching the cache. - - .. versionadded:: 0.5.0 - - :param function_key_generator: a function that will produce a - "cache key". This function will supersede the one configured on the - :class:`.CacheRegion` itself. - - .. versionadded:: 0.5.5 - - .. seealso:: - - :meth:`.CacheRegion.cache_multi_on_arguments` - - :meth:`.CacheRegion.get_or_create` - - """ - expiration_time_is_callable = compat.callable(expiration_time) - - if function_key_generator is None: - function_key_generator = self.function_key_generator - - def decorator(fn): - if to_str is compat.string_type: - # backwards compatible - key_generator = function_key_generator(namespace, fn) - else: - key_generator = function_key_generator( - namespace, fn, - to_str=to_str) - - @wraps(fn) - def decorate(*arg, **kw): - key = key_generator(*arg, **kw) - - @wraps(fn) - def creator(): - return fn(*arg, **kw) - timeout = expiration_time() if expiration_time_is_callable \ - else expiration_time - return self.get_or_create(key, creator, timeout, - should_cache_fn) - - def invalidate(*arg, **kw): - key = key_generator(*arg, **kw) - self.delete(key) - - def set_(value, *arg, **kw): - key = key_generator(*arg, **kw) - self.set(key, value) - - def get(*arg, **kw): - key = key_generator(*arg, **kw) - return self.get(key) - - def refresh(*arg, **kw): - key = key_generator(*arg, **kw) - value = fn(*arg, **kw) - self.set(key, value) - return value - - decorate.set = set_ - decorate.invalidate = invalidate - decorate.refresh = refresh - decorate.get = get - - return decorate - return decorator - - def cache_multi_on_arguments( - self, namespace=None, expiration_time=None, - should_cache_fn=None, - asdict=False, to_str=compat.string_type, - function_multi_key_generator=None): - """A function decorator that will cache multiple return - values from the function using a sequence of keys derived from the - function itself and the arguments passed to it. - - This method is the "multiple key" analogue to the - :meth:`.CacheRegion.cache_on_arguments` method. - - Example:: - - @someregion.cache_multi_on_arguments() - def generate_something(*keys): - return [ - somedatabase.query(key) - for key in keys - ] - - The decorated function can be called normally. The decorator - will produce a list of cache keys using a mechanism similar to - that of :meth:`.CacheRegion.cache_on_arguments`, combining the - name of the function with the optional namespace and with the - string form of each key. It will then consult the cache using - the same mechanism as that of :meth:`.CacheRegion.get_multi` - to retrieve all current values; the originally passed keys - corresponding to those values which aren't generated or need - regeneration will be assembled into a new argument list, and - the decorated function is then called with that subset of - arguments. - - The returned result is a list:: - - result = generate_something("key1", "key2", "key3") - - The decorator internally makes use of the - :meth:`.CacheRegion.get_or_create_multi` method to access the - cache and conditionally call the function. See that - method for additional behavioral details. - - Unlike the :meth:`.CacheRegion.cache_on_arguments` method, - :meth:`.CacheRegion.cache_multi_on_arguments` works only with - a single function signature, one which takes a simple list of - keys as arguments. - - Like :meth:`.CacheRegion.cache_on_arguments`, the decorated function - is also provided with a ``set()`` method, which here accepts a - mapping of keys and values to set in the cache:: - - generate_something.set({"k1": "value1", - "k2": "value2", "k3": "value3"}) - - ...an ``invalidate()`` method, which has the effect of deleting - the given sequence of keys using the same mechanism as that of - :meth:`.CacheRegion.delete_multi`:: - - generate_something.invalidate("k1", "k2", "k3") - - ...a ``refresh()`` method, which will call the creation - function, cache the new values, and return them:: - - values = generate_something.refresh("k1", "k2", "k3") - - ...and a ``get()`` method, which will return values - based on the given arguments:: - - values = generate_something.get("k1", "k2", "k3") - - .. versionadded:: 0.5.3 Added ``get()`` method to decorated - function. - - Parameters passed to :meth:`.CacheRegion.cache_multi_on_arguments` - have the same meaning as those passed to - :meth:`.CacheRegion.cache_on_arguments`. - - :param namespace: optional string argument which will be - established as part of each cache key. - - :param expiration_time: if not None, will override the normal - expiration time. May be passed as an integer or a - callable. - - :param should_cache_fn: passed to - :meth:`.CacheRegion.get_or_create_multi`. This function is given a - value as returned by the creator, and only if it returns True will - that value be placed in the cache. - - :param asdict: if ``True``, the decorated function should return - its result as a dictionary of keys->values, and the final result - of calling the decorated function will also be a dictionary. - If left at its default value of ``False``, the decorated function - should return its result as a list of values, and the final - result of calling the decorated function will also be a list. - - When ``asdict==True`` if the dictionary returned by the decorated - function is missing keys, those keys will not be cached. - - :param to_str: callable, will be called on each function argument - in order to convert to a string. Defaults to ``str()``. If the - function accepts non-ascii unicode arguments on Python 2.x, the - ``unicode()`` builtin can be substituted, but note this will - produce unicode cache keys which may require key mangling before - reaching the cache. - - .. versionadded:: 0.5.0 - - :param function_multi_key_generator: a function that will produce a - list of keys. This function will supersede the one configured on the - :class:`.CacheRegion` itself. - - .. versionadded:: 0.5.5 - - .. seealso:: - - :meth:`.CacheRegion.cache_on_arguments` - - :meth:`.CacheRegion.get_or_create_multi` - - """ - expiration_time_is_callable = compat.callable(expiration_time) - - if function_multi_key_generator is None: - function_multi_key_generator = self.function_multi_key_generator - - def decorator(fn): - key_generator = function_multi_key_generator( - namespace, fn, - to_str=to_str) - - @wraps(fn) - def decorate(*arg, **kw): - cache_keys = arg - keys = key_generator(*arg, **kw) - key_lookup = dict(zip(keys, cache_keys)) - - @wraps(fn) - def creator(*keys_to_create): - return fn(*[key_lookup[k] for k in keys_to_create]) - - timeout = expiration_time() if expiration_time_is_callable \ - else expiration_time - - if asdict: - def dict_create(*keys): - d_values = creator(*keys) - return [ - d_values.get(key_lookup[k], NO_VALUE) - for k in keys] - - def wrap_cache_fn(value): - if value is NO_VALUE: - return False - elif not should_cache_fn: - return True - else: - return should_cache_fn(value) - - result = self.get_or_create_multi( - keys, dict_create, timeout, wrap_cache_fn) - result = dict( - (k, v) for k, v in zip(cache_keys, result) - if v is not NO_VALUE) - else: - result = self.get_or_create_multi( - keys, creator, timeout, - should_cache_fn) - - return result - - def invalidate(*arg): - keys = key_generator(*arg) - self.delete_multi(keys) - - def set_(mapping): - keys = list(mapping) - gen_keys = key_generator(*keys) - self.set_multi(dict( - (gen_key, mapping[key]) - for gen_key, key - in zip(gen_keys, keys)) - ) - - def get(*arg): - keys = key_generator(*arg) - return self.get_multi(keys) - - def refresh(*arg): - keys = key_generator(*arg) - values = fn(*arg) - if asdict: - self.set_multi( - dict(zip(keys, [values[a] for a in arg])) - ) - return values - else: - self.set_multi( - dict(zip(keys, values)) - ) - return values - - decorate.set = set_ - decorate.invalidate = invalidate - decorate.refresh = refresh - decorate.get = get - - return decorate - return decorator - - -def make_region(*arg, **kw): - """Instantiate a new :class:`.CacheRegion`. - - Currently, :func:`.make_region` is a passthrough - to :class:`.CacheRegion`. See that class for - constructor arguments. - - """ - return CacheRegion(*arg, **kw) diff --git a/awx/lib/site-packages/dogpile/cache/util.py b/awx/lib/site-packages/dogpile/cache/util.py deleted file mode 100644 index 51fe483fd6..0000000000 --- a/awx/lib/site-packages/dogpile/cache/util.py +++ /dev/null @@ -1,195 +0,0 @@ -from hashlib import sha1 -import inspect -import re -import collections -from . import compat - - -def coerce_string_conf(d): - result = {} - for k, v in d.items(): - if not isinstance(v, compat.string_types): - result[k] = v - continue - - v = v.strip() - if re.match(r'^[-+]?\d+$', v): - result[k] = int(v) - elif re.match(r'^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?$', v): - result[k] = float(v) - elif v.lower() in ('false', 'true'): - result[k] = v.lower() == 'true' - elif v == 'None': - result[k] = None - else: - result[k] = v - return result - - -class PluginLoader(object): - def __init__(self, group): - self.group = group - self.impls = {} - - def load(self, name): - if name in self.impls: - return self.impls[name]() - else: # pragma NO COVERAGE - import pkg_resources - for impl in pkg_resources.iter_entry_points( - self.group, name): - self.impls[name] = impl.load - return impl.load() - else: - raise Exception( - "Can't load plugin %s %s" % - (self.group, name)) - - def register(self, name, modulepath, objname): - def load(): - mod = __import__(modulepath, fromlist=[objname]) - return getattr(mod, objname) - self.impls[name] = load - - -def function_key_generator(namespace, fn, to_str=compat.string_type): - """Return a function that generates a string - key, based on a given function as well as - arguments to the returned function itself. - - This is used by :meth:`.CacheRegion.cache_on_arguments` - to generate a cache key from a decorated function. - - It can be replaced using the ``function_key_generator`` - argument passed to :func:`.make_region`. - - """ - - if namespace is None: - namespace = '%s:%s' % (fn.__module__, fn.__name__) - else: - namespace = '%s:%s|%s' % (fn.__module__, fn.__name__, namespace) - - args = inspect.getargspec(fn) - has_self = args[0] and args[0][0] in ('self', 'cls') - - def generate_key(*args, **kw): - if kw: - raise ValueError( - "dogpile.cache's default key creation " - "function does not accept keyword arguments.") - if has_self: - args = args[1:] - - return namespace + "|" + " ".join(map(to_str, args)) - return generate_key - - -def function_multi_key_generator(namespace, fn, to_str=compat.string_type): - - if namespace is None: - namespace = '%s:%s' % (fn.__module__, fn.__name__) - else: - namespace = '%s:%s|%s' % (fn.__module__, fn.__name__, namespace) - - args = inspect.getargspec(fn) - has_self = args[0] and args[0][0] in ('self', 'cls') - - def generate_keys(*args, **kw): - if kw: - raise ValueError( - "dogpile.cache's default key creation " - "function does not accept keyword arguments.") - if has_self: - args = args[1:] - return [namespace + "|" + key for key in map(to_str, args)] - return generate_keys - - -def sha1_mangle_key(key): - """a SHA1 key mangler.""" - - return sha1(key).hexdigest() - - -def length_conditional_mangler(length, mangler): - """a key mangler that mangles if the length of the key is - past a certain threshold. - - """ - def mangle(key): - if len(key) >= length: - return mangler(key) - else: - return key - return mangle - - -class memoized_property(object): - """A read-only @property that is only evaluated once.""" - def __init__(self, fget, doc=None): - self.fget = fget - self.__doc__ = doc or fget.__doc__ - self.__name__ = fget.__name__ - - def __get__(self, obj, cls): - if obj is None: - return self - obj.__dict__[self.__name__] = result = self.fget(obj) - return result - - -def to_list(x, default=None): - """Coerce to a list.""" - if x is None: - return default - if not isinstance(x, (list, tuple)): - return [x] - else: - return x - - -class KeyReentrantMutex(object): - - def __init__(self, key, mutex, keys): - self.key = key - self.mutex = mutex - self.keys = keys - - @classmethod - def factory(cls, mutex): - # this collection holds zero or one - # thread idents as the key; a set of - # keynames held as the value. - keystore = collections.defaultdict(set) - - def fac(key): - return KeyReentrantMutex(key, mutex, keystore) - return fac - - def acquire(self, wait=True): - current_thread = compat.threading.current_thread().ident - keys = self.keys.get(current_thread) - if keys is not None and \ - self.key not in keys: - # current lockholder, new key. add it in - keys.add(self.key) - return True - elif self.mutex.acquire(wait=wait): - # after acquire, create new set and add our key - self.keys[current_thread].add(self.key) - return True - else: - return False - - def release(self): - current_thread = compat.threading.current_thread().ident - keys = self.keys.get(current_thread) - assert keys is not None, "this thread didn't do the acquire" - assert self.key in keys, "No acquire held for key '%s'" % self.key - keys.remove(self.key) - if not keys: - # when list of keys empty, remove - # the thread ident and unlock. - del self.keys[current_thread] - self.mutex.release() diff --git a/awx/lib/site-packages/dogpile/core/__init__.py b/awx/lib/site-packages/dogpile/core/__init__.py deleted file mode 100644 index fb9d756d67..0000000000 --- a/awx/lib/site-packages/dogpile/core/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from .dogpile import NeedRegenerationException, Lock -from .nameregistry import NameRegistry -from .readwrite_lock import ReadWriteMutex -from .legacy import Dogpile, SyncReaderDogpile - -__all__ = [ - 'Dogpile', 'SyncReaderDogpile', 'NeedRegenerationException', - 'NameRegistry', 'ReadWriteMutex', 'Lock'] - -__version__ = '0.4.1' - diff --git a/awx/lib/site-packages/dogpile/core/dogpile.py b/awx/lib/site-packages/dogpile/core/dogpile.py deleted file mode 100644 index 2e3ca0e931..0000000000 --- a/awx/lib/site-packages/dogpile/core/dogpile.py +++ /dev/null @@ -1,162 +0,0 @@ -import time -import logging - -log = logging.getLogger(__name__) - -class NeedRegenerationException(Exception): - """An exception that when raised in the 'with' block, - forces the 'has_value' flag to False and incurs a - regeneration of the value. - - """ - -NOT_REGENERATED = object() - -class Lock(object): - """Dogpile lock class. - - Provides an interface around an arbitrary mutex - that allows one thread/process to be elected as - the creator of a new value, while other threads/processes - continue to return the previous version - of that value. - - .. versionadded:: 0.4.0 - The :class:`.Lock` class was added as a single-use object - representing the dogpile API without dependence on - any shared state between multiple instances. - - :param mutex: A mutex object that provides ``acquire()`` - and ``release()`` methods. - :param creator: Callable which returns a tuple of the form - (new_value, creation_time). "new_value" should be a newly - generated value representing completed state. "creation_time" - should be a floating point time value which is relative - to Python's ``time.time()`` call, representing the time - at which the value was created. This time value should - be associated with the created value. - :param value_and_created_fn: Callable which returns - a tuple of the form (existing_value, creation_time). This - basically should return what the last local call to the ``creator()`` - callable has returned, i.e. the value and the creation time, - which would be assumed here to be from a cache. If the - value is not available, the :class:`.NeedRegenerationException` - exception should be thrown. - :param expiretime: Expiration time in seconds. Set to - ``None`` for never expires. This timestamp is compared - to the creation_time result and ``time.time()`` to determine if - the value returned by value_and_created_fn is "expired". - :param async_creator: A callable. If specified, this callable will be - passed the mutex as an argument and is responsible for releasing the mutex - after it finishes some asynchronous value creation. The intent is for - this to be used to defer invocation of the creator callable until some - later time. - - .. versionadded:: 0.4.1 added the async_creator argument. - - """ - - def __init__(self, - mutex, - creator, - value_and_created_fn, - expiretime, - async_creator=None, - ): - self.mutex = mutex - self.creator = creator - self.value_and_created_fn = value_and_created_fn - self.expiretime = expiretime - self.async_creator = async_creator - - def _is_expired(self, createdtime): - """Return true if the expiration time is reached, or no - value is available.""" - - return not self._has_value(createdtime) or \ - ( - self.expiretime is not None and - time.time() - createdtime > self.expiretime - ) - - def _has_value(self, createdtime): - """Return true if the creation function has proceeded - at least once.""" - return createdtime > 0 - - def _enter(self): - value_fn = self.value_and_created_fn - - try: - value = value_fn() - value, createdtime = value - except NeedRegenerationException: - log.debug("NeedRegenerationException") - value = NOT_REGENERATED - createdtime = -1 - - generated = self._enter_create(createdtime) - - if generated is not NOT_REGENERATED: - generated, createdtime = generated - return generated - elif value is NOT_REGENERATED: - try: - value, createdtime = value_fn() - return value - except NeedRegenerationException: - raise Exception("Generation function should " - "have just been called by a concurrent " - "thread.") - else: - return value - - def _enter_create(self, createdtime): - - if not self._is_expired(createdtime): - return NOT_REGENERATED - - async = False - - if self._has_value(createdtime): - if not self.mutex.acquire(False): - log.debug("creation function in progress " - "elsewhere, returning") - return NOT_REGENERATED - else: - log.debug("no value, waiting for create lock") - self.mutex.acquire() - - try: - log.debug("value creation lock %r acquired" % self.mutex) - - # see if someone created the value already - try: - value, createdtime = self.value_and_created_fn() - except NeedRegenerationException: - pass - else: - if not self._is_expired(createdtime): - log.debug("value already present") - return value, createdtime - elif self.async_creator: - log.debug("Passing creation lock to async runner") - self.async_creator(self.mutex) - async = True - return value, createdtime - - log.debug("Calling creation function") - created = self.creator() - return created - finally: - if not async: - self.mutex.release() - log.debug("Released creation lock") - - - def __enter__(self): - return self._enter() - - def __exit__(self, type, value, traceback): - pass - diff --git a/awx/lib/site-packages/dogpile/core/legacy.py b/awx/lib/site-packages/dogpile/core/legacy.py deleted file mode 100644 index dad4e1609d..0000000000 --- a/awx/lib/site-packages/dogpile/core/legacy.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import with_statement - -from .util import threading -from .readwrite_lock import ReadWriteMutex -from .dogpile import Lock -import time -import contextlib - -class Dogpile(object): - """Dogpile lock class. - - .. deprecated:: 0.4.0 - The :class:`.Lock` object specifies the full - API of the :class:`.Dogpile` object in a single way, - rather than providing multiple modes of usage which - don't necessarily work in the majority of cases. - :class:`.Dogpile` is now a wrapper around the :class:`.Lock` object - which provides dogpile.core's original usage pattern. - This usage pattern began as something simple, but was - not of general use in real-world caching environments without - several extra complicating factors; the :class:`.Lock` - object presents the "real-world" API more succinctly, - and also fixes a cross-process concurrency issue. - - :param expiretime: Expiration time in seconds. Set to - ``None`` for never expires. - :param init: if True, set the 'createdtime' to the - current time. - :param lock: a mutex object that provides - ``acquire()`` and ``release()`` methods. - - """ - def __init__(self, expiretime, init=False, lock=None): - """Construct a new :class:`.Dogpile`. - - """ - if lock: - self.dogpilelock = lock - else: - self.dogpilelock = threading.Lock() - - self.expiretime = expiretime - if init: - self.createdtime = time.time() - - createdtime = -1 - """The last known 'creation time' of the value, - stored as an epoch (i.e. from ``time.time()``). - - If the value here is -1, it is assumed the value - should recreate immediately. - - """ - - def acquire(self, creator, - value_fn=None, - value_and_created_fn=None): - """Acquire the lock, returning a context manager. - - :param creator: Creation function, used if this thread - is chosen to create a new value. - - :param value_fn: Optional function that returns - the value from some datasource. Will be returned - if regeneration is not needed. - - :param value_and_created_fn: Like value_fn, but returns a tuple - of (value, createdtime). The returned createdtime - will replace the "createdtime" value on this dogpile - lock. This option removes the need for the dogpile lock - itself to remain persistent across usages; another - dogpile can come along later and pick up where the - previous one left off. - - """ - - if value_and_created_fn is None: - if value_fn is None: - def value_and_created_fn(): - return None, self.createdtime - else: - def value_and_created_fn(): - return value_fn(), self.createdtime - - def creator_wrapper(): - value = creator() - self.createdtime = time.time() - return value, self.createdtime - else: - def creator_wrapper(): - value = creator() - self.createdtime = time.time() - return value - - return Lock( - self.dogpilelock, - creator_wrapper, - value_and_created_fn, - self.expiretime - ) - - @property - def is_expired(self): - """Return true if the expiration time is reached, or no - value is available.""" - - return not self.has_value or \ - ( - self.expiretime is not None and - time.time() - self.createdtime > self.expiretime - ) - - @property - def has_value(self): - """Return true if the creation function has proceeded - at least once.""" - return self.createdtime > 0 - - -class SyncReaderDogpile(Dogpile): - """Provide a read-write lock function on top of the :class:`.Dogpile` - class. - - .. deprecated:: 0.4.0 - The :class:`.ReadWriteMutex` object can be used directly. - - """ - def __init__(self, *args, **kw): - super(SyncReaderDogpile, self).__init__(*args, **kw) - self.readwritelock = ReadWriteMutex() - - @contextlib.contextmanager - def acquire_write_lock(self): - """Return the "write" lock context manager. - - This will provide a section that is mutexed against - all readers/writers for the dogpile-maintained value. - - """ - - self.readwritelock.acquire_write_lock() - try: - yield - finally: - self.readwritelock.release_write_lock() - - @contextlib.contextmanager - def acquire(self, *arg, **kw): - with super(SyncReaderDogpile, self).acquire(*arg, **kw) as value: - self.readwritelock.acquire_read_lock() - try: - yield value - finally: - self.readwritelock.release_read_lock() diff --git a/awx/lib/site-packages/dogpile/core/nameregistry.py b/awx/lib/site-packages/dogpile/core/nameregistry.py deleted file mode 100644 index a73f450c71..0000000000 --- a/awx/lib/site-packages/dogpile/core/nameregistry.py +++ /dev/null @@ -1,83 +0,0 @@ -from .util import threading -import weakref - -class NameRegistry(object): - """Generates and return an object, keeping it as a - singleton for a certain identifier for as long as its - strongly referenced. - - e.g.:: - - class MyFoo(object): - "some important object." - def __init__(self, identifier): - self.identifier = identifier - - registry = NameRegistry(MyFoo) - - # thread 1: - my_foo = registry.get("foo1") - - # thread 2 - my_foo = registry.get("foo1") - - Above, ``my_foo`` in both thread #1 and #2 will - be *the same object*. The constructor for - ``MyFoo`` will be called once, passing the - identifier ``foo1`` as the argument. - - When thread 1 and thread 2 both complete or - otherwise delete references to ``my_foo``, the - object is *removed* from the :class:`.NameRegistry` as - a result of Python garbage collection. - - :param creator: A function that will create a new - value, given the identifier passed to the :meth:`.NameRegistry.get` - method. - - """ - _locks = weakref.WeakValueDictionary() - _mutex = threading.RLock() - - def __init__(self, creator): - """Create a new :class:`.NameRegistry`. - - - """ - self._values = weakref.WeakValueDictionary() - self._mutex = threading.RLock() - self.creator = creator - - def get(self, identifier, *args, **kw): - """Get and possibly create the value. - - :param identifier: Hash key for the value. - If the creation function is called, this identifier - will also be passed to the creation function. - :param \*args, \**kw: Additional arguments which will - also be passed to the creation function if it is - called. - - """ - try: - if identifier in self._values: - return self._values[identifier] - else: - return self._sync_get(identifier, *args, **kw) - except KeyError: - return self._sync_get(identifier, *args, **kw) - - def _sync_get(self, identifier, *args, **kw): - self._mutex.acquire() - try: - try: - if identifier in self._values: - return self._values[identifier] - else: - self._values[identifier] = value = self.creator(identifier, *args, **kw) - return value - except KeyError: - self._values[identifier] = value = self.creator(identifier, *args, **kw) - return value - finally: - self._mutex.release() diff --git a/awx/lib/site-packages/dogpile/core/readwrite_lock.py b/awx/lib/site-packages/dogpile/core/readwrite_lock.py deleted file mode 100644 index 1ea25e47ab..0000000000 --- a/awx/lib/site-packages/dogpile/core/readwrite_lock.py +++ /dev/null @@ -1,130 +0,0 @@ -from .util import threading - -import logging -log = logging.getLogger(__name__) - -class LockError(Exception): - pass - -class ReadWriteMutex(object): - """A mutex which allows multiple readers, single writer. - - :class:`.ReadWriteMutex` uses a Python ``threading.Condition`` - to provide this functionality across threads within a process. - - The Beaker package also contained a file-lock based version - of this concept, so that readers/writers could be synchronized - across processes with a common filesystem. A future Dogpile - release may include this additional class at some point. - - """ - - def __init__(self): - # counts how many asynchronous methods are executing - self.async = 0 - - # pointer to thread that is the current sync operation - self.current_sync_operation = None - - # condition object to lock on - self.condition = threading.Condition(threading.Lock()) - - def acquire_read_lock(self, wait = True): - """Acquire the 'read' lock.""" - self.condition.acquire() - try: - # see if a synchronous operation is waiting to start - # or is already running, in which case we wait (or just - # give up and return) - if wait: - while self.current_sync_operation is not None: - self.condition.wait() - else: - if self.current_sync_operation is not None: - return False - - self.async += 1 - log.debug("%s acquired read lock", self) - finally: - self.condition.release() - - if not wait: - return True - - def release_read_lock(self): - """Release the 'read' lock.""" - self.condition.acquire() - try: - self.async -= 1 - - # check if we are the last asynchronous reader thread - # out the door. - if self.async == 0: - # yes. so if a sync operation is waiting, notifyAll to wake - # it up - if self.current_sync_operation is not None: - self.condition.notifyAll() - elif self.async < 0: - raise LockError("Synchronizer error - too many " - "release_read_locks called") - log.debug("%s released read lock", self) - finally: - self.condition.release() - - def acquire_write_lock(self, wait = True): - """Acquire the 'write' lock.""" - self.condition.acquire() - try: - # here, we are not a synchronous reader, and after returning, - # assuming waiting or immediate availability, we will be. - - if wait: - # if another sync is working, wait - while self.current_sync_operation is not None: - self.condition.wait() - else: - # if another sync is working, - # we dont want to wait, so forget it - if self.current_sync_operation is not None: - return False - - # establish ourselves as the current sync - # this indicates to other read/write operations - # that they should wait until this is None again - self.current_sync_operation = threading.currentThread() - - # now wait again for asyncs to finish - if self.async > 0: - if wait: - # wait - self.condition.wait() - else: - # we dont want to wait, so forget it - self.current_sync_operation = None - return False - log.debug("%s acquired write lock", self) - finally: - self.condition.release() - - if not wait: - return True - - def release_write_lock(self): - """Release the 'write' lock.""" - self.condition.acquire() - try: - if self.current_sync_operation is not threading.currentThread(): - raise LockError("Synchronizer error - current thread doesn't " - "have the write lock") - - # reset the current sync operation so - # another can get it - self.current_sync_operation = None - - # tell everyone to get ready - self.condition.notifyAll() - - log.debug("%s released write lock", self) - finally: - # everyone go !! - self.condition.release() diff --git a/awx/lib/site-packages/dogpile/core/util.py b/awx/lib/site-packages/dogpile/core/util.py deleted file mode 100644 index f53c6818c4..0000000000 --- a/awx/lib/site-packages/dogpile/core/util.py +++ /dev/null @@ -1,8 +0,0 @@ -import sys -py3k = sys.version_info >= (3, 0) - -try: - import threading -except ImportError: - import dummy_threading as threading - diff --git a/awx/lib/site-packages/easy_install.py b/awx/lib/site-packages/easy_install.py deleted file mode 100644 index d87e984034..0000000000 --- a/awx/lib/site-packages/easy_install.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Run the EasyInstall command""" - -if __name__ == '__main__': - from setuptools.command.easy_install import main - main() diff --git a/awx/lib/site-packages/funtests/__init__.py b/awx/lib/site-packages/funtests/__init__.py deleted file mode 100644 index 1bea48807d..0000000000 --- a/awx/lib/site-packages/funtests/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -import os -import sys - -sys.path.insert(0, os.pardir) -sys.path.insert(0, os.getcwd()) diff --git a/awx/lib/site-packages/funtests/setup.py b/awx/lib/site-packages/funtests/setup.py deleted file mode 100644 index 8159fc4e8b..0000000000 --- a/awx/lib/site-packages/funtests/setup.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -try: - from setuptools import setup - from setuptools.command.install import install -except ImportError: - from ez_setup import use_setuptools - use_setuptools() - from setuptools import setup # noqa - from setuptools.command.install import install # noqa - - -class no_install(install): - - def run(self, *args, **kwargs): - import sys - sys.stderr.write(""" -------------------------------------------------------- -The billiard functional test suite cannot be installed. -------------------------------------------------------- - - -But you can execute the tests by running the command: - - $ python setup.py test - - -""") - - -setup( - name='billiard-funtests', - version='DEV', - description='Functional test suite for billiard', - author='Ask Solem', - author_email='ask@celeryproject.org', - url='http://github.com/celery/billiard', - platforms=['any'], - packages=[], - data_files=[], - zip_safe=False, - cmdclass={'install': no_install}, - test_suite='nose.collector', - build_requires=[ - 'nose', - 'nose-cover3', - 'unittest2', - 'coverage>=3.0', - ], - classifiers=[ - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: C' - 'License :: OSI Approved :: BSD License', - 'Intended Audience :: Developers', - ], - long_description='Do not install this package', -) diff --git a/awx/lib/site-packages/geventwebsocket/__init__.py b/awx/lib/site-packages/geventwebsocket/__init__.py deleted file mode 100644 index 7e2e0167d8..0000000000 --- a/awx/lib/site-packages/geventwebsocket/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -VERSION = (0, 9, 3, 'final', 0) - -__all__ = [ - 'WebSocketApplication', - 'Resource', - 'WebSocketServer', - 'WebSocketError', - 'get_version' -] - - -def get_version(*args, **kwargs): - from .utils import get_version - return get_version(*args, **kwargs) - -try: - from .resource import WebSocketApplication, Resource - from .server import WebSocketServer - from .exceptions import WebSocketError -except ImportError: - pass diff --git a/awx/lib/site-packages/geventwebsocket/exceptions.py b/awx/lib/site-packages/geventwebsocket/exceptions.py deleted file mode 100644 index e066727e57..0000000000 --- a/awx/lib/site-packages/geventwebsocket/exceptions.py +++ /dev/null @@ -1,19 +0,0 @@ -from socket import error as socket_error - - -class WebSocketError(socket_error): - """ - Base class for all websocket errors. - """ - - -class ProtocolError(WebSocketError): - """ - Raised if an error occurs when de/encoding the websocket protocol. - """ - - -class FrameTooLargeException(ProtocolError): - """ - Raised if a frame is received that is too large. - """ diff --git a/awx/lib/site-packages/geventwebsocket/gunicorn/__init__.py b/awx/lib/site-packages/geventwebsocket/gunicorn/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/geventwebsocket/gunicorn/workers.py b/awx/lib/site-packages/geventwebsocket/gunicorn/workers.py deleted file mode 100644 index d0aa136943..0000000000 --- a/awx/lib/site-packages/geventwebsocket/gunicorn/workers.py +++ /dev/null @@ -1,6 +0,0 @@ -from geventwebsocket.handler import WebSocketHandler -from gunicorn.workers.ggevent import GeventPyWSGIWorker - - -class GeventWebSocketWorker(GeventPyWSGIWorker): - wsgi_handler = WebSocketHandler diff --git a/awx/lib/site-packages/geventwebsocket/handler.py b/awx/lib/site-packages/geventwebsocket/handler.py deleted file mode 100644 index a016ae3d74..0000000000 --- a/awx/lib/site-packages/geventwebsocket/handler.py +++ /dev/null @@ -1,278 +0,0 @@ -import base64 -import hashlib -import warnings - -from gevent.pywsgi import WSGIHandler -from .websocket import WebSocket, Stream -from .logging import create_logger - - -class Client(object): - def __init__(self, address, ws): - self.address = address - self.ws = ws - - -class WebSocketHandler(WSGIHandler): - """ - Automatically upgrades the connection to a websocket. - - To prevent the WebSocketHandler to call the underlying WSGI application, - but only setup the WebSocket negotiations, do: - - mywebsockethandler.prevent_wsgi_call = True - - before calling run_application(). This is useful if you want to do more - things before calling the app, and want to off-load the WebSocket - negotiations to this library. Socket.IO needs this for example, to send - the 'ack' before yielding the control to your WSGI app. - """ - - SUPPORTED_VERSIONS = ('13', '8', '7') - GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" - - def run_websocket(self): - """ - Called when a websocket has been created successfully. - """ - - if getattr(self, 'prevent_wsgi_call', False): - return - - # In case WebSocketServer is not used - if not hasattr(self.server, 'clients'): - self.server.clients = {} - - # Since we're now a websocket connection, we don't care what the - # application actually responds with for the http response - - try: - self.server.clients[self.client_address] = Client( - self.client_address, self.websocket) - self.application(self.environ, lambda s, h: []) - finally: - del self.server.clients[self.client_address] - if not self.websocket.closed: - self.websocket.close() - self.environ.update({ - 'wsgi.websocket': None - }) - self.websocket = None - - def run_application(self): - if (hasattr(self.server, 'pre_start_hook') - and self.server.pre_start_hook): - self.logger.debug("Calling pre-start hook") - if self.server.pre_start_hook(self): - return super(WebSocketHandler, self).run_application() - - self.logger.debug("Initializing WebSocket") - self.result = self.upgrade_websocket() - - if hasattr(self, 'websocket'): - if self.status and not self.headers_sent: - self.write('') - - self.run_websocket() - else: - if self.status: - # A status was set, likely an error so just send the response - if not self.result: - self.result = [] - - self.process_result() - return - - # This handler did not handle the request, so defer it to the - # underlying application object - return super(WebSocketHandler, self).run_application() - - def upgrade_websocket(self): - """ - Attempt to upgrade the current environ into a websocket enabled - connection. If successful, the environ dict with be updated with two - new entries, `wsgi.websocket` and `wsgi.websocket_version`. - - :returns: Whether the upgrade was successful. - """ - - # Some basic sanity checks first - - self.logger.debug("Validating WebSocket request") - - if self.environ.get('REQUEST_METHOD', '') != 'GET': - # This is not a websocket request, so we must not handle it - self.logger.debug('Can only upgrade connection if using GET method.') - return - - upgrade = self.environ.get('HTTP_UPGRADE', '').lower() - - if upgrade == 'websocket': - connection = self.environ.get('HTTP_CONNECTION', '').lower() - - if 'upgrade' not in connection: - # This is not a websocket request, so we must not handle it - self.logger.warning("Client didn't ask for a connection " - "upgrade") - return - else: - # This is not a websocket request, so we must not handle it - return - - if self.request_version != 'HTTP/1.1': - self.start_response('402 Bad Request', []) - self.logger.warning("Bad server protocol in headers") - - return ['Bad protocol version'] - - if self.environ.get('HTTP_SEC_WEBSOCKET_VERSION'): - return self.upgrade_connection() - else: - self.logger.warning("No protocol defined") - self.start_response('426 Upgrade Required', [ - ('Sec-WebSocket-Version', ', '.join(self.SUPPORTED_VERSIONS))]) - - return ['No Websocket protocol version defined'] - - def upgrade_connection(self): - """ - Validate and 'upgrade' the HTTP request to a WebSocket request. - - If an upgrade succeeded then then handler will have `start_response` - with a status of `101`, the environ will also be updated with - `wsgi.websocket` and `wsgi.websocket_version` keys. - - :param environ: The WSGI environ dict. - :param start_response: The callable used to start the response. - :param stream: File like object that will be read from/written to by - the underlying WebSocket object, if created. - :return: The WSGI response iterator is something went awry. - """ - - self.logger.debug("Attempting to upgrade connection") - - version = self.environ.get("HTTP_SEC_WEBSOCKET_VERSION") - - if version not in self.SUPPORTED_VERSIONS: - msg = "Unsupported WebSocket Version: {0}".format(version) - - self.logger.warning(msg) - self.start_response('400 Bad Request', [ - ('Sec-WebSocket-Version', ', '.join(self.SUPPORTED_VERSIONS)) - ]) - - return [msg] - - key = self.environ.get("HTTP_SEC_WEBSOCKET_KEY", '').strip() - - if not key: - # 5.2.1 (3) - msg = "Sec-WebSocket-Key header is missing/empty" - - self.logger.warning(msg) - self.start_response('400 Bad Request', []) - - return [msg] - - try: - key_len = len(base64.b64decode(key)) - except TypeError: - msg = "Invalid key: {0}".format(key) - - self.logger.warning(msg) - self.start_response('400 Bad Request', []) - - return [msg] - - if key_len != 16: - # 5.2.1 (3) - msg = "Invalid key: {0}".format(key) - - self.logger.warning(msg) - self.start_response('400 Bad Request', []) - - return [msg] - - # Check for WebSocket Protocols - requested_protocols = self.environ.get( - 'HTTP_SEC_WEBSOCKET_PROTOCOL', '') - protocol = None - - if hasattr(self.application, 'app_protocol'): - allowed_protocol = self.application.app_protocol( - self.environ['PATH_INFO']) - - if allowed_protocol and allowed_protocol in requested_protocols: - protocol = allowed_protocol - self.logger.debug("Protocol allowed: {0}".format(protocol)) - - self.websocket = WebSocket(self.environ, Stream(self), self) - self.environ.update({ - 'wsgi.websocket_version': version, - 'wsgi.websocket': self.websocket - }) - - headers = [ - ("Upgrade", "websocket"), - ("Connection", "Upgrade"), - ("Sec-WebSocket-Accept", base64.b64encode( - hashlib.sha1(key + self.GUID).digest())), - ] - - if protocol: - headers.append(("Sec-WebSocket-Protocol", protocol)) - - self.logger.debug("WebSocket request accepted, switching protocols") - self.start_response("101 Switching Protocols", headers) - - @property - def logger(self): - if not hasattr(self.server, 'logger'): - self.server.logger = create_logger(__name__) - - return self.server.logger - - def log_request(self): - if '101' not in self.status: - self.logger.info(self.format_request()) - - @property - def active_client(self): - return self.server.clients[self.client_address] - - def start_response(self, status, headers, exc_info=None): - """ - Called when the handler is ready to send a response back to the remote - endpoint. A websocket connection may have not been created. - """ - writer = super(WebSocketHandler, self).start_response( - status, headers, exc_info=exc_info) - - self._prepare_response() - - return writer - - def _prepare_response(self): - """ - Sets up the ``pywsgi.Handler`` to work with a websocket response. - - This is used by other projects that need to support WebSocket - connections as part of a larger effort. - """ - assert not self.headers_sent - - if not self.environ.get('wsgi.websocket'): - # a WebSocket connection is not established, do nothing - return - - # So that `finalize_headers` doesn't write a Content-Length header - self.provided_content_length = False - - # The websocket is now controlling the response - self.response_use_chunked = False - - # Once the request is over, the connection must be closed - self.close_connection = True - - # Prevents the Date header from being written - self.provided_date = True diff --git a/awx/lib/site-packages/geventwebsocket/logging.py b/awx/lib/site-packages/geventwebsocket/logging.py deleted file mode 100644 index 554ca02d61..0000000000 --- a/awx/lib/site-packages/geventwebsocket/logging.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import absolute_import - -from logging import getLogger, StreamHandler, getLoggerClass, Formatter, DEBUG - - -def create_logger(name, debug=False, format=None): - Logger = getLoggerClass() - - class DebugLogger(Logger): - def getEffectiveLevel(x): - if x.level == 0 and debug: - return DEBUG - else: - return Logger.getEffectiveLevel(x) - - class DebugHandler(StreamHandler): - def emit(x, record): - StreamHandler.emit(x, record) if debug else None - - handler = DebugHandler() - handler.setLevel(DEBUG) - - if format: - handler.setFormatter(Formatter(format)) - - logger = getLogger(name) - del logger.handlers[:] - logger.__class__ = DebugLogger - logger.addHandler(handler) - - return logger diff --git a/awx/lib/site-packages/geventwebsocket/protocols/__init__.py b/awx/lib/site-packages/geventwebsocket/protocols/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/geventwebsocket/protocols/base.py b/awx/lib/site-packages/geventwebsocket/protocols/base.py deleted file mode 100644 index 1c05ab620a..0000000000 --- a/awx/lib/site-packages/geventwebsocket/protocols/base.py +++ /dev/null @@ -1,35 +0,0 @@ -class BaseProtocol(object): - PROTOCOL_NAME = '' - - def __init__(self, app): - self._app = app - - def on_open(self): - self.app.on_open() - - def on_message(self, message): - self.app.on_message(message) - - def on_close(self, reason=None): - self.app.on_close(reason) - - @property - def app(self): - if self._app: - return self._app - else: - raise Exception("No application coupled") - - @property - def server(self): - if not hasattr(self.app, 'ws'): - return None - - return self.app.ws.handler.server - - @property - def handler(self): - if not hasattr(self.app, 'ws'): - return None - - return self.app.ws.handler diff --git a/awx/lib/site-packages/geventwebsocket/protocols/wamp.py b/awx/lib/site-packages/geventwebsocket/protocols/wamp.py deleted file mode 100644 index 954486549e..0000000000 --- a/awx/lib/site-packages/geventwebsocket/protocols/wamp.py +++ /dev/null @@ -1,229 +0,0 @@ -import inspect -import random -import string -import types - -try: - import ujson as json -except ImportError: - try: - import simplejson as json - except ImportError: - import json - -from ..exceptions import WebSocketError -from .base import BaseProtocol - - -def export_rpc(arg=None): - if isinstance(arg, types.FunctionType): - arg._rpc = arg.__name__ - return arg - - -def serialize(data): - return json.dumps(data) - - -class Prefixes(object): - def __init__(self): - self.prefixes = {} - - def add(self, prefix, uri): - self.prefixes[prefix] = uri - - def resolve(self, curie_or_uri): - if "http://" in curie_or_uri: - return curie_or_uri - elif ':' in curie_or_uri: - prefix, proc = curie_or_uri.split(':', 1) - return self.prefixes[prefix] + proc - else: - raise Exception(curie_or_uri) - - -class RemoteProcedures(object): - def __init__(self): - self.calls = {} - - def register_procedure(self, uri, proc): - self.calls[uri] = proc - - def register_object(self, uri, obj): - for k in inspect.getmembers(obj, inspect.ismethod): - if '_rpc' in k[1].__dict__: - proc_uri = uri + k[1]._rpc - self.calls[proc_uri] = (obj, k[1]) - - def call(self, uri, args): - if uri in self.calls: - proc = self.calls[uri] - - # Do the correct call whether it's a function or instance method. - if isinstance(proc, tuple): - if proc[1].__self__ is None: - # Create instance of object and call method - return proc[1](proc[0](), *args) - else: - # Call bound method on instance - return proc[1](*args) - else: - return self.calls[uri](*args) - else: - raise Exception("no such uri '{}'".format(uri)) - - -class Channels(object): - def __init__(self): - self.channels = {} - - def create(self, uri, prefix_matching=False): - if uri not in self.channels: - self.channels[uri] = [] - - # TODO: implement prefix matching - - def subscribe(self, uri, client): - if uri in self.channels: - self.channels[uri].append(client) - - def unsubscribe(self, uri, client): - if uri not in self.channels: - return - - client_index = self.channels[uri].index(client) - self.channels[uri].pop(client_index) - - if len(self.channels[uri]) == 0: - del self.channels[uri] - - def publish(self, uri, event, exclude=None, eligible=None): - if uri not in self.channels: - return - - # TODO: exclude & eligible - - msg = [WampProtocol.MSG_EVENT, uri, event] - - for client in self.channels[uri]: - try: - client.ws.send(serialize(msg)) - except WebSocketError: - # Seems someone didn't unsubscribe before disconnecting - self.channels[uri].remove(client) - - -class WampProtocol(BaseProtocol): - MSG_WELCOME = 0 - MSG_PREFIX = 1 - MSG_CALL = 2 - MSG_CALL_RESULT = 3 - MSG_CALL_ERROR = 4 - MSG_SUBSCRIBE = 5 - MSG_UNSUBSCRIBE = 6 - MSG_PUBLISH = 7 - MSG_EVENT = 8 - - PROTOCOL_NAME = "wamp" - - def __init__(self, *args, **kwargs): - self.procedures = RemoteProcedures() - self.prefixes = Prefixes() - self.session_id = ''.join( - [random.choice(string.digits + string.letters) - for i in xrange(16)]) - - super(WampProtocol, self).__init__(*args, **kwargs) - - def register_procedure(self, *args, **kwargs): - self.procedures.register_procedure(*args, **kwargs) - - def register_object(self, *args, **kwargs): - self.procedures.register_object(*args, **kwargs) - - def register_pubsub(self, *args, **kwargs): - if not hasattr(self.server, 'channels'): - self.server.channels = Channels() - - self.server.channels.create(*args, **kwargs) - - def do_handshake(self): - from geventwebsocket import get_version - - welcome = [ - self.MSG_WELCOME, - self.session_id, - 1, - 'gevent-websocket/' + get_version() - ] - self.app.ws.send(serialize(welcome)) - - def rpc_call(self, data): - call_id, curie_or_uri = data[1:3] - args = data[3:] - - if not isinstance(call_id, (str, unicode)): - raise Exception() - if not isinstance(curie_or_uri, (str, unicode)): - raise Exception() - - uri = self.prefixes.resolve(curie_or_uri) - - try: - result = self.procedures.call(uri, args) - result_msg = [self.MSG_CALL_RESULT, call_id, result] - except Exception, e: - result_msg = [self.MSG_CALL_ERROR, - call_id, 'http://TODO#generic', - str(type(e)), str(e)] - - self.app.on_message(serialize(result_msg)) - - def pubsub_action(self, data): - action = data[0] - curie_or_uri = data[1] - - if not isinstance(action, int): - raise Exception() - if not isinstance(curie_or_uri, (str, unicode)): - raise Exception() - - uri = self.prefixes.resolve(curie_or_uri) - - if action == self.MSG_SUBSCRIBE and len(data) == 2: - self.server.channels.subscribe(data[1], self.handler.active_client) - - elif action == self.MSG_UNSUBSCRIBE and len(data) == 2: - self.server.channels.unsubscribe( - data[1], self.handler.active_client) - - elif action == self.MSG_PUBLISH and len(data) >= 3: - payload = data[2] if len(data) >= 3 else None - exclude = data[3] if len(data) >= 4 else None - eligible = data[4] if len(data) >= 5 else None - - self.server.channels.publish(uri, payload, exclude, eligible) - - def on_open(self): - self.app.on_open() - self.do_handshake() - - def on_message(self, message): - data = json.loads(message) - - if not isinstance(data, list): - raise Exception('incoming data is no list') - - if data[0] == self.MSG_PREFIX and len(data) == 3: - prefix, uri = data[1:3] - self.prefixes.add(prefix, uri) - - elif data[0] == self.MSG_CALL and len(data) >= 3: - return self.rpc_call(data) - - elif data[0] in (self.MSG_SUBSCRIBE, self.MSG_UNSUBSCRIBE, - self.MSG_PUBLISH): - return self.pubsub_action(data) - else: - raise Exception("Unknown call") - diff --git a/awx/lib/site-packages/geventwebsocket/resource.py b/awx/lib/site-packages/geventwebsocket/resource.py deleted file mode 100644 index 36c1fb367c..0000000000 --- a/awx/lib/site-packages/geventwebsocket/resource.py +++ /dev/null @@ -1,74 +0,0 @@ -import re - -from .protocols.base import BaseProtocol -from .exceptions import WebSocketError - - -class WebSocketApplication(object): - protocol_class = BaseProtocol - - def __init__(self, ws): - self.protocol = self.protocol_class(self) - self.ws = ws - - def handle(self): - self.protocol.on_open() - - while True: - try: - message = self.ws.receive() - except WebSocketError: - self.protocol.on_close() - break - - self.protocol.on_message(message) - - def on_open(self, *args, **kwargs): - pass - - def on_close(self, *args, **kwargs): - pass - - def on_message(self, message, *args, **kwargs): - self.ws.send(message, **kwargs) - - @classmethod - def protocol_name(cls): - return cls.protocol_class.PROTOCOL_NAME - - -class Resource(object): - def __init__(self, apps=None): - self.apps = apps if apps else [] - - def _app_by_path(self, environ_path): - # Which app matched the current path? - - for path, app in self.apps.iteritems(): - if re.match(path, environ_path): - return app - - def app_protocol(self, path): - app = self._app_by_path(path) - - if hasattr(app, 'protocol_name'): - return app.protocol_name() - else: - return '' - - def __call__(self, environ, start_response): - environ = environ - current_app = self._app_by_path(environ['PATH_INFO']) - - if current_app is None: - raise Exception("No apps defined") - - if 'wsgi.websocket' in environ: - ws = environ['wsgi.websocket'] - current_app = current_app(ws) - current_app.ws = ws # TODO: needed? - current_app.handle() - - return None - else: - return current_app(environ, start_response) diff --git a/awx/lib/site-packages/geventwebsocket/server.py b/awx/lib/site-packages/geventwebsocket/server.py deleted file mode 100644 index 00443b8a32..0000000000 --- a/awx/lib/site-packages/geventwebsocket/server.py +++ /dev/null @@ -1,34 +0,0 @@ -from gevent.pywsgi import WSGIServer - -from .handler import WebSocketHandler -from .logging import create_logger - - -class WebSocketServer(WSGIServer): - debug_log_format = ( - '-' * 80 + '\n' + - '%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' + - '%(message)s\n' + - '-' * 80 - ) - - def __init__(self, *args, **kwargs): - self.debug = kwargs.pop('debug', False) - self.pre_start_hook = kwargs.pop('pre_start_hook', None) - self._logger = None - self.clients = {} - - kwargs['handler_class'] = WebSocketHandler - super(WebSocketServer, self).__init__(*args, **kwargs) - - def handle(self, socket, address): - handler = self.handler_class(socket, address, self) - handler.handle() - - @property - def logger(self): - if not self._logger: - self._logger = create_logger( - __name__, self.debug, self.debug_log_format) - - return self._logger diff --git a/awx/lib/site-packages/geventwebsocket/utf8validator.py b/awx/lib/site-packages/geventwebsocket/utf8validator.py deleted file mode 100644 index b8a3e8a5ad..0000000000 --- a/awx/lib/site-packages/geventwebsocket/utf8validator.py +++ /dev/null @@ -1,128 +0,0 @@ -############################################################################### -## -## Copyright 2011-2013 Tavendo GmbH -## -## Note: -## -## This code is a Python implementation of the algorithm -## -## "Flexible and Economical UTF-8 Decoder" -## -## by Bjoern Hoehrmann -## -## bjoern@hoehrmann.de -## http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. -## -############################################################################### - - -## use Cython implementation of UTF8 validator if available -## -try: - from wsaccel.utf8validator import Utf8Validator -except: - ## fallback to pure Python implementation - - class Utf8Validator: - """ - Incremental UTF-8 validator with constant memory consumption (minimal - state). - - Implements the algorithm "Flexible and Economical UTF-8 Decoder" by - Bjoern Hoehrmann (http://bjoern.hoehrmann.de/utf-8/decoder/dfa/). - """ - - ## DFA transitions - UTF8VALIDATOR_DFA = [ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, # 00..1f - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, # 20..3f - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, # 40..5f - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, # 60..7f - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, # 80..9f - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, # a0..bf - 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, # c0..df - 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, # e0..ef - 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, # f0..ff - 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, # s0..s0 - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, # s1..s2 - 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, # s3..s4 - 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, # s5..s6 - 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, # s7..s8 - ] - - UTF8_ACCEPT = 0 - UTF8_REJECT = 1 - - def __init__(self): - self.reset() - - def decode(self, b): - """ - Eat one UTF-8 octet, and validate on the fly. - - Returns UTF8_ACCEPT when enough octets have been consumed, in which case - self.codepoint contains the decoded Unicode code point. - - Returns UTF8_REJECT when invalid UTF-8 was encountered. - - Returns some other positive integer when more octets need to be eaten. - """ - type = Utf8Validator.UTF8VALIDATOR_DFA[b] - - if self.state != Utf8Validator.UTF8_ACCEPT: - self.codepoint = (b & 0x3f) | (self.codepoint << 6) - else: - self.codepoint = (0xff >> type) & b - - self.state = Utf8Validator.UTF8VALIDATOR_DFA[256 + self.state * 16 + type] - - return self.state - - def reset(self): - """ - Reset validator to start new incremental UTF-8 decode/validation. - """ - self.state = Utf8Validator.UTF8_ACCEPT - self.codepoint = 0 - self.i = 0 - - def validate(self, ba): - """ - Incrementally validate a chunk of bytes provided as string. - - Will return a quad (valid?, endsOnCodePoint?, currentIndex, totalIndex). - - As soon as an octet is encountered which renders the octet sequence - invalid, a quad with valid? == False is returned. currentIndex returns - the index within the currently consumed chunk, and totalIndex the - index within the total consumed sequence that was the point of bail out. - When valid? == True, currentIndex will be len(ba) and totalIndex the - total amount of consumed bytes. - """ - - l = len(ba) - - for i in xrange(l): - ## optimized version of decode(), since we are not interested in actual code points - - self.state = Utf8Validator.UTF8VALIDATOR_DFA[256 + (self.state << 4) + Utf8Validator.UTF8VALIDATOR_DFA[ord(ba[i])]] - - if self.state == Utf8Validator.UTF8_REJECT: - self.i += i - return False, False, i, self.i - - self.i += l - - return True, self.state == Utf8Validator.UTF8_ACCEPT, l, self.i diff --git a/awx/lib/site-packages/geventwebsocket/utils.py b/awx/lib/site-packages/geventwebsocket/utils.py deleted file mode 100644 index 2e5bc3b7ee..0000000000 --- a/awx/lib/site-packages/geventwebsocket/utils.py +++ /dev/null @@ -1,45 +0,0 @@ -import subprocess - - -def get_version(version=None): - "Returns a PEP 386-compliant version number from VERSION." - - if version is None: - from geventwebsocket import VERSION as version - else: - assert len(version) == 5 - assert version[3] in ('alpha', 'beta', 'rc', 'final') - - # Now build the two parts of the version number: - # main = X.Y[.Z] - # sub = .devN - for pre-alpha releases - # | {a|b|c}N - for alpha, beta and rc releases - - parts = 2 if version[2] == 0 else 3 - main = '.'.join(str(x) for x in version[:parts]) - - sub = '' - if version[3] == 'alpha' and version[4] == 0: - hg_changeset = get_hg_changeset() - if hg_changeset: - sub = '.dev{0}'.format(hg_changeset) - - elif version[3] != 'final': - mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'c'} - sub = mapping[version[3]] + str(version[4]) - - return str(main + sub) - - -def get_hg_changeset(): - rev, err = subprocess.Popen( - 'hg id -i', - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE - ).communicate() - - if err: - return None - else: - return rev.strip().replace('+', '') diff --git a/awx/lib/site-packages/geventwebsocket/websocket.py b/awx/lib/site-packages/geventwebsocket/websocket.py deleted file mode 100644 index 6d4f76d32f..0000000000 --- a/awx/lib/site-packages/geventwebsocket/websocket.py +++ /dev/null @@ -1,543 +0,0 @@ -import struct - -from socket import error - -from .exceptions import ProtocolError -from .exceptions import WebSocketError -from .exceptions import FrameTooLargeException - -from .utf8validator import Utf8Validator - - -MSG_SOCKET_DEAD = "Socket is dead" -MSG_ALREADY_CLOSED = "Connection is already closed" -MSG_CLOSED = "Connection closed" - - -class WebSocket(object): - """ - Base class for supporting websocket operations. - - :ivar environ: The http environment referenced by this connection. - :ivar closed: Whether this connection is closed/closing. - :ivar stream: The underlying file like object that will be read from / - written to by this WebSocket object. - """ - - __slots__ = ('utf8validator', 'utf8validate_last', 'environ', 'closed', - 'stream', 'raw_write', 'raw_read', 'handler') - - OPCODE_CONTINUATION = 0x00 - OPCODE_TEXT = 0x01 - OPCODE_BINARY = 0x02 - OPCODE_CLOSE = 0x08 - OPCODE_PING = 0x09 - OPCODE_PONG = 0x0a - - def __init__(self, environ, stream, handler): - self.environ = environ - self.closed = False - - self.stream = stream - - self.raw_write = stream.write - self.raw_read = stream.read - - self.utf8validator = Utf8Validator() - self.handler = handler - - def __del__(self): - try: - self.close() - except: - # close() may fail if __init__ didn't complete - pass - - def _decode_bytes(self, bytestring): - """ - Internal method used to convert the utf-8 encoded bytestring into - unicode. - - If the conversion fails, the socket will be closed. - """ - - if not bytestring: - return u'' - - try: - return bytestring.decode('utf-8') - except UnicodeDecodeError: - self.close(1007) - - raise - - def _encode_bytes(self, text): - """ - :returns: The utf-8 byte string equivalent of `text`. - """ - - if isinstance(text, str): - return text - - if not isinstance(text, unicode): - text = unicode(text or '') - - return text.encode('utf-8') - - def _is_valid_close_code(self, code): - """ - :returns: Whether the returned close code is a valid hybi return code. - """ - if code < 1000: - return False - - if 1004 <= code <= 1006: - return False - - if 1012 <= code <= 1016: - return False - - if code == 1100: - # not sure about this one but the autobahn fuzzer requires it. - return False - - if 2000 <= code <= 2999: - return False - - return True - - @property - def current_app(self): - if hasattr(self.handler.server.application, 'current_app'): - return self.handler.server.application.current_app - else: - # For backwards compatibility reasons - class MockApp(): - def on_close(self, *args): - pass - - return MockApp() - - @property - def origin(self): - if not self.environ: - return - - return self.environ.get('HTTP_ORIGIN') - - @property - def protocol(self): - if not self.environ: - return - - return self.environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL') - - @property - def version(self): - if not self.environ: - return - - return self.environ.get('HTTP_SEC_WEBSOCKET_VERSION') - - @property - def path(self): - if not self.environ: - return - - return self.environ.get('PATH_INFO') - - @property - def logger(self): - return self.handler.logger - - def handle_close(self, header, payload): - """ - Called when a close frame has been decoded from the stream. - - :param header: The decoded `Header`. - :param payload: The bytestring payload associated with the close frame. - """ - if not payload: - self.close(1000, None) - - return - - if len(payload) < 2: - raise ProtocolError('Invalid close frame: {0} {1}'.format( - header, payload)) - - code = struct.unpack('!H', str(payload[:2]))[0] - payload = payload[2:] - - if payload: - validator = Utf8Validator() - val = validator.validate(payload) - - if not val[0]: - raise UnicodeError - - if not self._is_valid_close_code(code): - raise ProtocolError('Invalid close code {0}'.format(code)) - - self.close(code, payload) - - def handle_ping(self, header, payload): - self.send_frame(payload, self.OPCODE_PONG) - - def handle_pong(self, header, payload): - pass - - def read_frame(self): - """ - Block until a full frame has been read from the socket. - - This is an internal method as calling this will not cleanup correctly - if an exception is called. Use `receive` instead. - - :return: The header and payload as a tuple. - """ - - header = Header.decode_header(self.stream) - - if header.flags: - raise ProtocolError - - if not header.length: - return header, '' - - try: - payload = self.raw_read(header.length) - except error: - payload = '' - except Exception: - # TODO log out this exception - payload = '' - - if len(payload) != header.length: - raise WebSocketError('Unexpected EOF reading frame payload') - - if header.mask: - payload = header.unmask_payload(payload) - - return header, payload - - def validate_utf8(self, payload): - # Make sure the frames are decodable independently - self.utf8validate_last = self.utf8validator.validate(payload) - - if not self.utf8validate_last[0]: - raise UnicodeError("Encountered invalid UTF-8 while processing " - "text message at payload octet index " - "{0:d}".format(self.utf8validate_last[3])) - - def read_message(self): - """ - Return the next text or binary message from the socket. - - This is an internal method as calling this will not cleanup correctly - if an exception is called. Use `receive` instead. - """ - opcode = None - message = "" - - while True: - header, payload = self.read_frame() - f_opcode = header.opcode - - if f_opcode in (self.OPCODE_TEXT, self.OPCODE_BINARY): - # a new frame - if opcode: - raise ProtocolError("The opcode in non-fin frame is " - "expected to be zero, got " - "{0!r}".format(f_opcode)) - - # Start reading a new message, reset the validator - self.utf8validator.reset() - self.utf8validate_last = (True, True, 0, 0) - - opcode = f_opcode - - elif f_opcode == self.OPCODE_CONTINUATION: - if not opcode: - raise ProtocolError("Unexpected frame with opcode=0") - - elif f_opcode == self.OPCODE_PING: - self.handle_ping(header, payload) - continue - - elif f_opcode == self.OPCODE_PONG: - self.handle_pong(header, payload) - continue - - elif f_opcode == self.OPCODE_CLOSE: - self.handle_close(header, payload) - return - - else: - raise ProtocolError("Unexpected opcode={0!r}".format(f_opcode)) - - if opcode == self.OPCODE_TEXT: - self.validate_utf8(payload) - - message += payload - - if header.fin: - break - - if opcode == self.OPCODE_TEXT: - self.validate_utf8(message) - return message - else: - return bytearray(message) - - def receive(self): - """ - Read and return a message from the stream. If `None` is returned, then - the socket is considered closed/errored. - """ - - if self.closed: - self.current_app.on_close(MSG_ALREADY_CLOSED) - raise WebSocketError(MSG_ALREADY_CLOSED) - - try: - return self.read_message() - except UnicodeError: - self.close(1007) - except ProtocolError: - self.close(1002) - except error: - self.close() - self.current_app.on_close(MSG_CLOSED) - - return None - - def send_frame(self, message, opcode): - """ - Send a frame over the websocket with message as its payload - """ - if self.closed: - self.current_app.on_close(MSG_ALREADY_CLOSED) - raise WebSocketError(MSG_ALREADY_CLOSED) - - if opcode == self.OPCODE_TEXT: - message = self._encode_bytes(message) - elif opcode == self.OPCODE_BINARY: - message = str(message) - - header = Header.encode_header(True, opcode, '', len(message), 0) - - try: - self.raw_write(header + message) - except error: - raise WebSocketError(MSG_SOCKET_DEAD) - - def send(self, message, binary=None): - """ - Send a frame over the websocket with message as its payload - """ - if binary is None: - binary = not isinstance(message, (str, unicode)) - - opcode = self.OPCODE_BINARY if binary else self.OPCODE_TEXT - - try: - self.send_frame(message, opcode) - except WebSocketError: - self.current_app.on_close(MSG_SOCKET_DEAD) - raise WebSocketError(MSG_SOCKET_DEAD) - - def close(self, code=1000, message=''): - """ - Close the websocket and connection, sending the specified code and - message. The underlying socket object is _not_ closed, that is the - responsibility of the initiator. - """ - - if self.closed: - self.current_app.on_close(MSG_ALREADY_CLOSED) - - try: - message = self._encode_bytes(message) - - self.send_frame( - struct.pack('!H%ds' % len(message), code, message), - opcode=self.OPCODE_CLOSE) - except WebSocketError: - # Failed to write the closing frame but it's ok because we're - # closing the socket anyway. - self.logger.debug("Failed to write closing frame -> closing socket") - finally: - self.logger.debug("Closed WebSocket") - self.closed = True - - self.stream = None - self.raw_write = None - self.raw_read = None - - self.environ = None - - #self.current_app.on_close(MSG_ALREADY_CLOSED) - - -class Stream(object): - """ - Wraps the handler's socket/rfile attributes and makes it in to a file like - object that can be read from/written to by the lower level websocket api. - """ - - __slots__ = ('handler', 'read', 'write') - - def __init__(self, handler): - self.handler = handler - self.read = handler.rfile.read - self.write = handler.socket.sendall - - -class Header(object): - __slots__ = ('fin', 'mask', 'opcode', 'flags', 'length') - - FIN_MASK = 0x80 - OPCODE_MASK = 0x0f - MASK_MASK = 0x80 - LENGTH_MASK = 0x7f - - RSV0_MASK = 0x40 - RSV1_MASK = 0x20 - RSV2_MASK = 0x10 - - # bitwise mask that will determine the reserved bits for a frame header - HEADER_FLAG_MASK = RSV0_MASK | RSV1_MASK | RSV2_MASK - - def __init__(self, fin=0, opcode=0, flags=0, length=0): - self.mask = '' - self.fin = fin - self.opcode = opcode - self.flags = flags - self.length = length - - def mask_payload(self, payload): - payload = bytearray(payload) - mask = bytearray(self.mask) - - for i in xrange(self.length): - payload[i] ^= mask[i % 4] - - return str(payload) - - # it's the same operation - unmask_payload = mask_payload - - def __repr__(self): - return ("<Header fin={0} opcode={1} length={2} flags={3} at " - "0x{4:x}>").format(self.fin, self.opcode, self.length, - self.flags, id(self)) - - @classmethod - def decode_header(cls, stream): - """ - Decode a WebSocket header. - - :param stream: A file like object that can be 'read' from. - :returns: A `Header` instance. - """ - read = stream.read - data = read(2) - - if len(data) != 2: - raise WebSocketError("Unexpected EOF while decoding header") - - first_byte, second_byte = struct.unpack('!BB', data) - - header = cls( - fin=first_byte & cls.FIN_MASK == cls.FIN_MASK, - opcode=first_byte & cls.OPCODE_MASK, - flags=first_byte & cls.HEADER_FLAG_MASK, - length=second_byte & cls.LENGTH_MASK) - - has_mask = second_byte & cls.MASK_MASK == cls.MASK_MASK - - if header.opcode > 0x07: - if not header.fin: - raise ProtocolError( - "Received fragmented control frame: {0!r}".format(data)) - - # Control frames MUST have a payload length of 125 bytes or less - if header.length > 125: - raise FrameTooLargeException( - "Control frame cannot be larger than 125 bytes: " - "{0!r}".format(data)) - - if header.length == 126: - # 16 bit length - data = read(2) - - if len(data) != 2: - raise WebSocketError('Unexpected EOF while decoding header') - - header.length = struct.unpack('!H', data)[0] - elif header.length == 127: - # 64 bit length - data = read(8) - - if len(data) != 8: - raise WebSocketError('Unexpected EOF while decoding header') - - header.length = struct.unpack('!Q', data)[0] - - if has_mask: - mask = read(4) - - if len(mask) != 4: - raise WebSocketError('Unexpected EOF while decoding header') - - header.mask = mask - - return header - - @classmethod - def encode_header(cls, fin, opcode, mask, length, flags): - """ - Encodes a WebSocket header. - - :param fin: Whether this is the final frame for this opcode. - :param opcode: The opcode of the payload, see `OPCODE_*` - :param mask: Whether the payload is masked. - :param length: The length of the frame. - :param flags: The RSV* flags. - :return: A bytestring encoded header. - """ - first_byte = opcode - second_byte = 0 - extra = '' - - if fin: - first_byte |= cls.FIN_MASK - - if flags & cls.RSV0_MASK: - first_byte |= cls.RSV0_MASK - - if flags & cls.RSV1_MASK: - first_byte |= cls.RSV1_MASK - - if flags & cls.RSV2_MASK: - first_byte |= cls.RSV2_MASK - - # now deal with length complexities - if length < 126: - second_byte += length - elif length <= 0xffff: - second_byte += 126 - extra = struct.pack('!H', length) - elif length <= 0xffffffffffffffff: - second_byte += 127 - extra = struct.pack('!Q', length) - else: - raise FrameTooLargeException - - if mask: - second_byte |= cls.MASK_MASK - - extra += mask - - return chr(first_byte) + chr(second_byte) + extra diff --git a/awx/lib/site-packages/glanceclient/__init__.py b/awx/lib/site-packages/glanceclient/__init__.py deleted file mode 100644 index f967031298..0000000000 --- a/awx/lib/site-packages/glanceclient/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -#NOTE(bcwaldon): this try/except block is needed to run setup.py due to -# its need to import local code before installing required dependencies -try: - import glanceclient.client - Client = glanceclient.client.Client -except ImportError: - import warnings - warnings.warn("Could not import glanceclient.client", ImportWarning) - -import pbr.version - -version_info = pbr.version.VersionInfo('python-glanceclient') - -try: - __version__ = version_info.version_string() -except AttributeError: - __version__ = None diff --git a/awx/lib/site-packages/glanceclient/_i18n.py b/awx/lib/site-packages/glanceclient/_i18n.py deleted file mode 100644 index 6963c076c5..0000000000 --- a/awx/lib/site-packages/glanceclient/_i18n.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -try: - import oslo_i18n as i18n -except ImportError: - from oslo import i18n - - -_translators = i18n.TranslatorFactory(domain='glanceclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/glanceclient/client.py b/awx/lib/site-packages/glanceclient/client.py deleted file mode 100644 index 74afff1ebf..0000000000 --- a/awx/lib/site-packages/glanceclient/client.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - -from glanceclient.common import utils - - -def Client(version=None, endpoint=None, *args, **kwargs): - if version is not None: - warnings.warn(("`version` keyword is being deprecated. Please pass the" - " version as part of the URL. " - "http://$HOST:$PORT/v$VERSION_NUMBER"), - DeprecationWarning) - - endpoint, url_version = utils.strip_version(endpoint) - - if not url_version and not version: - msg = ("Please provide either the version or an url with the form " - "http://$HOST:$PORT/v$VERSION_NUMBER") - raise RuntimeError(msg) - - version = int(version or url_version) - - module = utils.import_versioned_module(version, 'client') - client_class = getattr(module, 'Client') - return client_class(endpoint, *args, **kwargs) diff --git a/awx/lib/site-packages/glanceclient/common/__init__.py b/awx/lib/site-packages/glanceclient/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/glanceclient/common/base.py b/awx/lib/site-packages/glanceclient/common/base.py deleted file mode 100644 index 55f265e49f..0000000000 --- a/awx/lib/site-packages/glanceclient/common/base.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. - -DEPRECATED post v.0.12.0. Use 'glanceclient.openstack.common.apiclient.base' -instead of this module." -""" - -import warnings - -from glanceclient.openstack.common.apiclient import base - - -warnings.warn("The 'glanceclient.common.base' module is deprecated post " - "v.0.12.0. Use 'glanceclient.openstack.common.apiclient.base' " - "instead of this one.", DeprecationWarning) - - -getid = base.getid -Manager = base.ManagerWithFind -Resource = base.Resource diff --git a/awx/lib/site-packages/glanceclient/common/exceptions.py b/awx/lib/site-packages/glanceclient/common/exceptions.py deleted file mode 100644 index 64cc01ee49..0000000000 --- a/awx/lib/site-packages/glanceclient/common/exceptions.py +++ /dev/null @@ -1,3 +0,0 @@ -# This is here for compatibility purposes. Once all known OpenStack clients -# are updated to use glanceclient.exc, this file should be removed -from glanceclient.exc import * diff --git a/awx/lib/site-packages/glanceclient/common/http.py b/awx/lib/site-packages/glanceclient/common/http.py deleted file mode 100644 index f746db5844..0000000000 --- a/awx/lib/site-packages/glanceclient/common/http.py +++ /dev/null @@ -1,285 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import logging -import socket - -from oslo_utils import importutils -from oslo_utils import netutils -import requests -try: - from requests.packages.urllib3.exceptions import ProtocolError -except ImportError: - ProtocolError = requests.exceptions.ConnectionError -import six -from six.moves.urllib import parse - -try: - import json -except ImportError: - import simplejson as json - -# Python 2.5 compat fix -if not hasattr(parse, 'parse_qsl'): - import cgi - parse.parse_qsl = cgi.parse_qsl - -from oslo_utils import encodeutils - -from glanceclient.common import https -from glanceclient.common.utils import safe_header -from glanceclient import exc - -osprofiler_web = importutils.try_import("osprofiler.web") - -LOG = logging.getLogger(__name__) -USER_AGENT = 'python-glanceclient' -CHUNKSIZE = 1024 * 64 # 64kB - - -class HTTPClient(object): - - def __init__(self, endpoint, **kwargs): - self.endpoint = endpoint - self.identity_headers = kwargs.get('identity_headers') - self.auth_token = kwargs.get('token') - if self.identity_headers: - if self.identity_headers.get('X-Auth-Token'): - self.auth_token = self.identity_headers.get('X-Auth-Token') - del self.identity_headers['X-Auth-Token'] - - self.session = requests.Session() - self.session.headers["User-Agent"] = USER_AGENT - - if self.auth_token: - self.session.headers["X-Auth-Token"] = self.auth_token - - self.timeout = float(kwargs.get('timeout', 600)) - - if self.endpoint.startswith("https"): - compression = kwargs.get('ssl_compression', True) - - if not compression: - self.session.mount("glance+https://", https.HTTPSAdapter()) - self.endpoint = 'glance+' + self.endpoint - - self.session.verify = ( - kwargs.get('cacert', requests.certs.where()), - kwargs.get('insecure', False)) - - else: - if kwargs.get('insecure', False) is True: - self.session.verify = False - else: - if kwargs.get('cacert', None) is not '': - self.session.verify = kwargs.get('cacert', True) - - self.session.cert = (kwargs.get('cert_file'), - kwargs.get('key_file')) - - @staticmethod - def parse_endpoint(endpoint): - return netutils.urlsplit(endpoint) - - def log_curl_request(self, method, url, headers, data, kwargs): - curl = ['curl -g -i -X %s' % method] - - headers = copy.deepcopy(headers) - headers.update(self.session.headers) - - for (key, value) in six.iteritems(headers): - header = '-H \'%s: %s\'' % safe_header(key, value) - curl.append(header) - - if not self.session.verify: - curl.append('-k') - else: - if isinstance(self.session.verify, six.string_types): - curl.append(' --cacert %s' % self.session.verify) - - if self.session.cert: - curl.append(' --cert %s --key %s' % self.session.cert) - - if data and isinstance(data, six.string_types): - curl.append('-d \'%s\'' % data) - - curl.append(url) - - msg = ' '.join([encodeutils.safe_decode(item, errors='ignore') - for item in curl]) - LOG.debug(msg) - - @staticmethod - def log_http_response(resp, body=None): - status = (resp.raw.version / 10.0, resp.status_code, resp.reason) - dump = ['\nHTTP/%.1f %s %s' % status] - headers = resp.headers.items() - dump.extend(['%s: %s' % safe_header(k, v) for k, v in headers]) - dump.append('') - if body: - body = encodeutils.safe_decode(body) - dump.extend([body, '']) - LOG.debug('\n'.join([encodeutils.safe_decode(x, errors='ignore') - for x in dump])) - - @staticmethod - def encode_headers(headers): - """Encodes headers. - - Note: This should be used right before - sending anything out. - - :param headers: Headers to encode - :returns: Dictionary with encoded headers' - names and values - """ - return dict((encodeutils.safe_encode(h), encodeutils.safe_encode(v)) - for h, v in six.iteritems(headers) if v is not None) - - def _request(self, method, url, **kwargs): - """Send an http request with the specified characteristics. - Wrapper around httplib.HTTP(S)Connection.request to handle tasks such - as setting headers and error handling. - """ - # Copy the kwargs so we can reuse the original in case of redirects - headers = kwargs.pop("headers", {}) - headers = headers and copy.deepcopy(headers) or {} - - if self.identity_headers: - for k, v in six.iteritems(self.identity_headers): - headers.setdefault(k, v) - - # Default Content-Type is octet-stream - content_type = headers.get('Content-Type', 'application/octet-stream') - - def chunk_body(body): - chunk = body - while chunk: - chunk = body.read(CHUNKSIZE) - if chunk == '': - break - yield chunk - - data = kwargs.pop("data", None) - if data is not None and not isinstance(data, six.string_types): - try: - data = json.dumps(data) - content_type = 'application/json' - except TypeError: - # Here we assume it's - # a file-like object - # and we'll chunk it - data = chunk_body(data) - - headers['Content-Type'] = content_type - stream = True if content_type == 'application/octet-stream' else False - - if osprofiler_web: - headers.update(osprofiler_web.get_trace_id_headers()) - - # Note(flaper87): Before letting headers / url fly, - # they should be encoded otherwise httplib will - # complain. - headers = self.encode_headers(headers) - - try: - if self.endpoint.endswith("/") or url.startswith("/"): - conn_url = "%s%s" % (self.endpoint, url) - else: - conn_url = "%s/%s" % (self.endpoint, url) - self.log_curl_request(method, conn_url, headers, data, kwargs) - resp = self.session.request(method, - conn_url, - data=data, - stream=stream, - headers=headers, - **kwargs) - except requests.exceptions.Timeout as e: - message = ("Error communicating with %(endpoint)s %(e)s" % - dict(url=conn_url, e=e)) - raise exc.InvalidEndpoint(message=message) - except (requests.exceptions.ConnectionError, ProtocolError) as e: - message = ("Error finding address for %(url)s: %(e)s" % - dict(url=conn_url, e=e)) - raise exc.CommunicationError(message=message) - except socket.gaierror as e: - message = "Error finding address for %s: %s" % ( - self.endpoint_hostname, e) - raise exc.InvalidEndpoint(message=message) - except (socket.error, socket.timeout) as e: - endpoint = self.endpoint - message = ("Error communicating with %(endpoint)s %(e)s" % - {'endpoint': endpoint, 'e': e}) - raise exc.CommunicationError(message=message) - - if not resp.ok: - LOG.debug("Request returned failure status %s." % resp.status_code) - raise exc.from_response(resp, resp.text) - elif resp.status_code == requests.codes.MULTIPLE_CHOICES: - raise exc.from_response(resp) - - content_type = resp.headers.get('Content-Type') - - # Read body into string if it isn't obviously image data - if content_type == 'application/octet-stream': - # Do not read all response in memory when - # downloading an image. - body_iter = _close_after_stream(resp, CHUNKSIZE) - self.log_http_response(resp) - else: - content = resp.text - self.log_http_response(resp, content) - if content_type and content_type.startswith('application/json'): - # Let's use requests json method, - # it should take care of response - # encoding - body_iter = resp.json() - else: - body_iter = six.StringIO(content) - try: - body_iter = json.loads(''.join([c for c in body_iter])) - except ValueError: - body_iter = None - return resp, body_iter - - def head(self, url, **kwargs): - return self._request('HEAD', url, **kwargs) - - def get(self, url, **kwargs): - return self._request('GET', url, **kwargs) - - def post(self, url, **kwargs): - return self._request('POST', url, **kwargs) - - def put(self, url, **kwargs): - return self._request('PUT', url, **kwargs) - - def patch(self, url, **kwargs): - return self._request('PATCH', url, **kwargs) - - def delete(self, url, **kwargs): - return self._request('DELETE', url, **kwargs) - - -def _close_after_stream(response, chunk_size): - """Iterate over the content and ensure the response is closed after.""" - # Yield each chunk in the response body - for chunk in response.iter_content(chunk_size=chunk_size): - yield chunk - # Once we're done streaming the body, ensure everything is closed. - # This will return the connection to the HTTPConnectionPool in urllib3 - # and ideally reduce the number of HTTPConnectionPool full warnings. - response.close() diff --git a/awx/lib/site-packages/glanceclient/common/https.py b/awx/lib/site-packages/glanceclient/common/https.py deleted file mode 100644 index e3a4780433..0000000000 --- a/awx/lib/site-packages/glanceclient/common/https.py +++ /dev/null @@ -1,348 +0,0 @@ -# Copyright 2014 Red Hat, Inc -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import socket -import ssl -import struct - -import OpenSSL -from requests import adapters -from requests import compat -try: - from requests.packages.urllib3 import connectionpool -except ImportError: - from urllib3 import connectionpool - -from oslo_utils import encodeutils -import six -# NOTE(jokke): simplified transition to py3, behaves like py2 xrange -from six.moves import range - -from glanceclient.common import utils - -try: - from eventlet import patcher - # Handle case where we are running in a monkey patched environment - if patcher.is_monkey_patched('socket'): - from eventlet.green.httplib import HTTPSConnection - from eventlet.green.OpenSSL.SSL import GreenConnection as Connection - from eventlet.greenio import GreenSocket - # TODO(mclaren): A getsockopt workaround: see 'getsockopt' doc string - GreenSocket.getsockopt = utils.getsockopt - else: - raise ImportError -except ImportError: - try: - from httplib import HTTPSConnection - except ImportError: - from http.client import HTTPSConnection - from OpenSSL.SSL import Connection as Connection - - -from glanceclient import exc - - -def verify_callback(host=None): - """ - We use a partial around the 'real' verify_callback function - so that we can stash the host value without holding a - reference on the VerifiedHTTPSConnection. - """ - def wrapper(connection, x509, errnum, - depth, preverify_ok, host=host): - return do_verify_callback(connection, x509, errnum, - depth, preverify_ok, host=host) - return wrapper - - -def do_verify_callback(connection, x509, errnum, - depth, preverify_ok, host=None): - """ - Verify the server's SSL certificate. - - This is a standalone function rather than a method to avoid - issues around closing sockets if a reference is held on - a VerifiedHTTPSConnection by the callback function. - """ - if x509.has_expired(): - msg = "SSL Certificate expired on '%s'" % x509.get_notAfter() - raise exc.SSLCertificateError(msg) - - if depth == 0 and preverify_ok: - # We verify that the host matches against the last - # certificate in the chain - return host_matches_cert(host, x509) - else: - # Pass through OpenSSL's default result - return preverify_ok - - -def host_matches_cert(host, x509): - """ - Verify that the x509 certificate we have received - from 'host' correctly identifies the server we are - connecting to, ie that the certificate's Common Name - or a Subject Alternative Name matches 'host'. - """ - def check_match(name): - # Directly match the name - if name == host: - return True - - # Support single wildcard matching - if name.startswith('*.') and host.find('.') > 0: - if name[2:] == host.split('.', 1)[1]: - return True - - common_name = x509.get_subject().commonName - - # First see if we can match the CN - if check_match(common_name): - return True - # Also try Subject Alternative Names for a match - san_list = None - for i in range(x509.get_extension_count()): - ext = x509.get_extension(i) - if ext.get_short_name() == b'subjectAltName': - san_list = str(ext) - for san in ''.join(san_list.split()).split(','): - if san.startswith('DNS:'): - if check_match(san.split(':', 1)[1]): - return True - - # Server certificate does not match host - msg = ('Host "%s" does not match x509 certificate contents: ' - 'CommonName "%s"' % (host, common_name)) - if san_list is not None: - msg = msg + ', subjectAltName "%s"' % san_list - raise exc.SSLCertificateError(msg) - - -def to_bytes(s): - if isinstance(s, six.string_types): - return six.b(s) - else: - return s - - -class HTTPSAdapter(adapters.HTTPAdapter): - """ - This adapter will be used just when - ssl compression should be disabled. - - The init method overwrites the default - https pool by setting glanceclient's - one. - """ - - def request_url(self, request, proxies): - # NOTE(flaper87): Make sure the url is encoded, otherwise - # python's standard httplib will fail with a TypeError. - url = super(HTTPSAdapter, self).request_url(request, proxies) - return encodeutils.safe_encode(url) - - def _create_glance_httpsconnectionpool(self, url): - kw = self.poolmanager.connection_kw - # Parse the url to get the scheme, host, and port - parsed = compat.urlparse(url) - # If there is no port specified, we should use the standard HTTPS port - port = parsed.port or 443 - pool = HTTPSConnectionPool(parsed.host, port, **kw) - - with self.poolmanager.pools.lock: - self.poolmanager.pools[(parsed.scheme, parsed.host, port)] = pool - - return pool - - def get_connection(self, url, proxies=None): - try: - return super(HTTPSAdapter, self).get_connection(url, proxies) - except KeyError: - # NOTE(sigamvirus24): This works around modifying a module global - # which fixes bug #1396550 - # The scheme is most likely glance+https but check anyway - if not url.startswith('glance+https://'): - raise - - return self._create_glance_httpsconnectionpool(url) - - def cert_verify(self, conn, url, verify, cert): - super(HTTPSAdapter, self).cert_verify(conn, url, verify, cert) - conn.ca_certs = verify[0] - conn.insecure = verify[1] - - -class HTTPSConnectionPool(connectionpool.HTTPSConnectionPool): - """ - HTTPSConnectionPool will be instantiated when a new - connection is requested to the HTTPSAdapter.This - implementation overwrites the _new_conn method and - returns an instances of glanceclient's VerifiedHTTPSConnection - which handles no compression. - - ssl_compression is hard-coded to False because this will - be used just when the user sets --no-ssl-compression. - """ - - scheme = 'glance+https' - - def _new_conn(self): - self.num_connections += 1 - return VerifiedHTTPSConnection(host=self.host, - port=self.port, - key_file=self.key_file, - cert_file=self.cert_file, - cacert=self.ca_certs, - insecure=self.insecure, - ssl_compression=False) - - -class OpenSSLConnectionDelegator(object): - """ - An OpenSSL.SSL.Connection delegator. - - Supplies an additional 'makefile' method which httplib requires - and is not present in OpenSSL.SSL.Connection. - - Note: Since it is not possible to inherit from OpenSSL.SSL.Connection - a delegator must be used. - """ - def __init__(self, *args, **kwargs): - self.connection = Connection(*args, **kwargs) - - def __getattr__(self, name): - return getattr(self.connection, name) - - def makefile(self, *args, **kwargs): - return socket._fileobject(self.connection, *args, **kwargs) - - -class VerifiedHTTPSConnection(HTTPSConnection): - """ - Extended HTTPSConnection which uses the OpenSSL library - for enhanced SSL support. - Note: Much of this functionality can eventually be replaced - with native Python 3.3 code. - """ - # Restrict the set of client supported cipher suites - CIPHERS = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:'\ - 'eCDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:'\ - 'RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS' - - def __init__(self, host, port=None, key_file=None, cert_file=None, - cacert=None, timeout=None, insecure=False, - ssl_compression=True): - # List of exceptions reported by Python3 instead of - # SSLConfigurationError - if six.PY3: - excp_lst = (TypeError, FileNotFoundError, ssl.SSLError) - else: - # NOTE(jamespage) - # Accomodate changes in behaviour for pep-0467, introduced - # in python 2.7.9. - # https://github.com/python/peps/blob/master/pep-0476.txt - excp_lst = (TypeError, IOError, ssl.SSLError) - try: - HTTPSConnection.__init__(self, host, port, - key_file=key_file, - cert_file=cert_file) - self.key_file = key_file - self.cert_file = cert_file - self.timeout = timeout - self.insecure = insecure - # NOTE(flaper87): `is_verified` is needed for - # requests' urllib3. If insecure is True then - # the request is not `verified`, hence `not insecure` - self.is_verified = not insecure - self.ssl_compression = ssl_compression - self.cacert = None if cacert is None else str(cacert) - self.set_context() - # ssl exceptions are reported in various form in Python 3 - # so to be compatible, we report the same kind as under - # Python2 - except excp_lst as e: - raise exc.SSLConfigurationError(str(e)) - - def set_context(self): - """ - Set up the OpenSSL context. - """ - self.context = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD) - self.context.set_cipher_list(self.CIPHERS) - - if self.ssl_compression is False: - self.context.set_options(0x20000) # SSL_OP_NO_COMPRESSION - - if self.insecure is not True: - self.context.set_verify(OpenSSL.SSL.VERIFY_PEER, - verify_callback(host=self.host)) - else: - self.context.set_verify(OpenSSL.SSL.VERIFY_NONE, - lambda *args: True) - - if self.cert_file: - try: - self.context.use_certificate_file(self.cert_file) - except Exception as e: - msg = 'Unable to load cert from "%s" %s' % (self.cert_file, e) - raise exc.SSLConfigurationError(msg) - if self.key_file is None: - # We support having key and cert in same file - try: - self.context.use_privatekey_file(self.cert_file) - except Exception as e: - msg = ('No key file specified and unable to load key ' - 'from "%s" %s' % (self.cert_file, e)) - raise exc.SSLConfigurationError(msg) - - if self.key_file: - try: - self.context.use_privatekey_file(self.key_file) - except Exception as e: - msg = 'Unable to load key from "%s" %s' % (self.key_file, e) - raise exc.SSLConfigurationError(msg) - - if self.cacert: - try: - self.context.load_verify_locations(to_bytes(self.cacert)) - except Exception as e: - msg = 'Unable to load CA from "%s" %s' % (self.cacert, e) - raise exc.SSLConfigurationError(msg) - else: - self.context.set_default_verify_paths() - - def connect(self): - """ - Connect to an SSL port using the OpenSSL library and apply - per-connection parameters. - """ - result = socket.getaddrinfo(self.host, self.port, 0, - socket.SOCK_STREAM) - if result: - socket_family = result[0][0] - if socket_family == socket.AF_INET6: - sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - else: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - else: - # If due to some reason the address lookup fails - we still connect - # to IPv4 socket. This retains the older behavior. - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if self.timeout is not None: - # '0' microseconds - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, - struct.pack('LL', self.timeout, 0)) - self.sock = OpenSSLConnectionDelegator(self.context, sock) - self.sock.connect((self.host, self.port)) diff --git a/awx/lib/site-packages/glanceclient/common/progressbar.py b/awx/lib/site-packages/glanceclient/common/progressbar.py deleted file mode 100644 index cd4ffe50a1..0000000000 --- a/awx/lib/site-packages/glanceclient/common/progressbar.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -import six - - -class _ProgressBarBase(object): - """ - Base abstract class used by specific class wrapper to show a progress bar - when the wrapped object are consumed. - - :param wrapped: Object to wrap that hold data to be consumed. - :param totalsize: The total size of the data in the wrapped object. - - :note: The progress will be displayed only if sys.stdout is a tty. - """ - - def __init__(self, wrapped, totalsize): - self._wrapped = wrapped - self._totalsize = float(totalsize) - self._show_progress = sys.stdout.isatty() and self._totalsize != 0 - self._percent = 0 - - def _display_progress_bar(self, size_read): - if self._show_progress: - self._percent += size_read / self._totalsize - # Output something like this: [==========> ] 49% - sys.stdout.write('\r[{0:<30}] {1:.0%}'.format( - '=' * int(round(self._percent * 29)) + '>', self._percent - )) - sys.stdout.flush() - - def __getattr__(self, attr): - # Forward other attribute access to the wrapped object. - return getattr(self._wrapped, attr) - - -class VerboseFileWrapper(_ProgressBarBase): - """ - A file wrapper that show and advance a progress bar whenever file's read - method is called. - """ - - def read(self, *args, **kwargs): - data = self._wrapped.read(*args, **kwargs) - if data: - self._display_progress_bar(len(data)) - else: - if self._show_progress: - # Break to a new line from the progress bar for incoming - # output. - sys.stdout.write('\n') - return data - - -class VerboseIteratorWrapper(_ProgressBarBase): - """ - An iterator wrapper that show and advance a progress bar whenever - data is consumed from the iterator. - - :note: Use only with iterator that yield strings. - """ - - def __iter__(self): - return self - - def next(self): - try: - data = six.next(self._wrapped) - # NOTE(mouad): Assuming that data is a string b/c otherwise calling - # len function will not make any sense. - self._display_progress_bar(len(data)) - return data - except StopIteration: - if self._show_progress: - # Break to a new line from the progress bar for incoming - # output. - sys.stdout.write('\n') - raise - - # In Python 3, __next__() has replaced next(). - __next__ = next diff --git a/awx/lib/site-packages/glanceclient/common/utils.py b/awx/lib/site-packages/glanceclient/common/utils.py deleted file mode 100644 index e51643fd6f..0000000000 --- a/awx/lib/site-packages/glanceclient/common/utils.py +++ /dev/null @@ -1,441 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import errno -import hashlib -import json -import os -import re -import sys -import threading -import uuid - -from oslo_utils import importutils -import six - -if os.name == 'nt': - import msvcrt -else: - msvcrt = None - -from oslo_utils import encodeutils -from oslo_utils import strutils -import prettytable - -from glanceclient import exc - -_memoized_property_lock = threading.Lock() - -SENSITIVE_HEADERS = ('X-Auth-Token', ) - - -# Decorator for cli-args -def arg(*args, **kwargs): - def _decorator(func): - # Because of the sematics of decorator composition if we just append - # to the options list positional options will appear to be backwards. - func.__dict__.setdefault('arguments', []).insert(0, (args, kwargs)) - return func - return _decorator - - -def schema_args(schema_getter, omit=None): - omit = omit or [] - typemap = { - 'string': str, - 'integer': int, - 'boolean': strutils.bool_from_string, - 'array': list - } - - def _decorator(func): - schema = schema_getter() - if schema is None: - param = '<unavailable>' - kwargs = { - 'help': ("Please run with connection parameters set to " - "retrieve the schema for generating help for this " - "command") - } - func.__dict__.setdefault('arguments', []).insert(0, ((param, ), - kwargs)) - else: - properties = schema.get('properties', {}) - for name, property in six.iteritems(properties): - if name in omit: - continue - param = '--' + name.replace('_', '-') - kwargs = {} - - type_str = property.get('type', 'string') - - if isinstance(type_str, list): - # NOTE(flaper87): This means the server has - # returned something like `['null', 'string']`, - # therfore we use the first non-`null` type as - # the valid type. - for t in type_str: - if t != 'null': - type_str = t - break - - if type_str == 'array': - items = property.get('items') - kwargs['type'] = typemap.get(items.get('type')) - kwargs['nargs'] = '+' - else: - kwargs['type'] = typemap.get(type_str) - - if type_str == 'boolean': - kwargs['metavar'] = '[True|False]' - else: - kwargs['metavar'] = '<%s>' % name.upper() - - description = property.get('description', "") - if 'enum' in property: - if len(description): - description += " " - - # NOTE(flaper87): Make sure all values are `str/unicode` - # for the `join` to succeed. Enum types can also be `None` - # therfore, join's call would fail without the following - # list comprehension - vals = [six.text_type(val) for val in property.get('enum')] - description += ('Valid values: ' + ', '.join(vals)) - kwargs['help'] = description - - func.__dict__.setdefault('arguments', - []).insert(0, ((param, ), kwargs)) - return func - - return _decorator - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def print_list(objs, fields, formatters=None, field_settings=None): - formatters = formatters or {} - field_settings = field_settings or {} - pt = prettytable.PrettyTable([f for f in fields], caching=False) - pt.align = 'l' - - for o in objs: - row = [] - for field in fields: - if field in field_settings: - for setting, value in six.iteritems(field_settings[field]): - setting_dict = getattr(pt, setting) - setting_dict[field] = value - - if field in formatters: - row.append(formatters[field](o)) - else: - field_name = field.lower().replace(' ', '_') - data = getattr(o, field_name, None) or '' - row.append(data) - pt.add_row(row) - - print(encodeutils.safe_decode(pt.get_string())) - - -def print_dict(d, max_column_width=80): - pt = prettytable.PrettyTable(['Property', 'Value'], caching=False) - pt.align = 'l' - pt.max_width = max_column_width - for k, v in six.iteritems(d): - if isinstance(v, (dict, list)): - v = json.dumps(v) - pt.add_row([k, v]) - print(encodeutils.safe_decode(pt.get_string(sortby='Property'))) - - -def find_resource(manager, name_or_id): - """Helper for the _find_* methods.""" - # first try to get entity as integer id - try: - if isinstance(name_or_id, int) or name_or_id.isdigit(): - return manager.get(int(name_or_id)) - except exc.NotFound: - pass - - # now try to get entity as uuid - try: - # This must be unicode for Python 3 compatibility. - # If you pass a bytestring to uuid.UUID, you will get a TypeError - uuid.UUID(encodeutils.safe_decode(name_or_id)) - return manager.get(name_or_id) - except (ValueError, exc.NotFound): - pass - - # finally try to find entity by name - matches = list(manager.list(filters={'name': name_or_id})) - num_matches = len(matches) - if num_matches == 0: - msg = "No %s with a name or ID of '%s' exists." % \ - (manager.resource_class.__name__.lower(), name_or_id) - raise exc.CommandError(msg) - elif num_matches > 1: - msg = ("Multiple %s matches found for '%s', use an ID to be more" - " specific." % (manager.resource_class.__name__.lower(), - name_or_id)) - raise exc.CommandError(msg) - else: - return matches[0] - - -def skip_authentication(f): - """Function decorator used to indicate a caller may be unauthenticated.""" - f.require_authentication = False - return f - - -def is_authentication_required(f): - """Checks to see if the function requires authentication. - - Use the skip_authentication decorator to indicate a caller may - skip the authentication step. - """ - return getattr(f, 'require_authentication', True) - - -def env(*vars, **kwargs): - """Search for the first defined of possibly many env vars - - Returns the first environment variable defined in vars, or - returns the default defined in kwargs. - """ - for v in vars: - value = os.environ.get(v, None) - if value: - return value - return kwargs.get('default', '') - - -def import_versioned_module(version, submodule=None): - module = 'glanceclient.v%s' % version - if submodule: - module = '.'.join((module, submodule)) - return importutils.import_module(module) - - -def exit(msg='', exit_code=1): - if msg: - print(encodeutils.safe_decode(msg), file=sys.stderr) - sys.exit(exit_code) - - -def save_image(data, path): - """ - Save an image to the specified path. - - :param data: binary data of the image - :param path: path to save the image to - """ - if path is None: - image = sys.stdout - else: - image = open(path, 'wb') - try: - for chunk in data: - image.write(chunk) - finally: - if path is not None: - image.close() - - -def make_size_human_readable(size): - suffix = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB'] - base = 1024.0 - - index = 0 - while size >= base: - index = index + 1 - size = size / base - - padded = '%.1f' % size - stripped = padded.rstrip('0').rstrip('.') - - return '%s%s' % (stripped, suffix[index]) - - -def getsockopt(self, *args, **kwargs): - """ - A function which allows us to monkey patch eventlet's - GreenSocket, adding a required 'getsockopt' method. - TODO: (mclaren) we can remove this once the eventlet fix - (https://bitbucket.org/eventlet/eventlet/commits/609f230) - lands in mainstream packages. - """ - return self.fd.getsockopt(*args, **kwargs) - - -def exception_to_str(exc): - try: - error = six.text_type(exc) - except UnicodeError: - try: - error = str(exc) - except UnicodeError: - error = ("Caught '%(exception)s' exception." % - {"exception": exc.__class__.__name__}) - return encodeutils.safe_decode(error, errors='ignore') - - -def get_file_size(file_obj): - """ - Analyze file-like object and attempt to determine its size. - - :param file_obj: file-like object. - :retval The file's size or None if it cannot be determined. - """ - if (hasattr(file_obj, 'seek') and hasattr(file_obj, 'tell') and - (six.PY2 or six.PY3 and file_obj.seekable())): - try: - curr = file_obj.tell() - file_obj.seek(0, os.SEEK_END) - size = file_obj.tell() - file_obj.seek(curr) - return size - except IOError as e: - if e.errno == errno.ESPIPE: - # Illegal seek. This means the file object - # is a pipe (e.g. the user is trying - # to pipe image data to the client, - # echo testdata | bin/glance add blah...), or - # that file object is empty, or that a file-like - # object which doesn't support 'seek/tell' has - # been supplied. - return - else: - raise - - -def get_data_file(args): - if args.file: - return open(args.file, 'rb') - else: - # distinguish cases where: - # (1) stdin is not valid (as in cron jobs): - # glance ... <&- - # (2) image data is provided through standard input: - # glance ... < /tmp/file or cat /tmp/file | glance ... - # (3) no image data provided: - # glance ... - try: - os.fstat(0) - except OSError: - # (1) stdin is not valid (closed...) - return None - if not sys.stdin.isatty(): - # (2) image data is provided through standard input - if msvcrt: - msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) - return sys.stdin - else: - # (3) no image data provided - return None - - -def strip_version(endpoint): - """Strip version from the last component of endpoint if present.""" - # NOTE(flaper87): This shouldn't be necessary if - # we make endpoint the first argument. However, we - # can't do that just yet because we need to keep - # backwards compatibility. - if not isinstance(endpoint, six.string_types): - raise ValueError("Expected endpoint") - - version = None - # Get rid of trailing '/' if present - endpoint = endpoint.rstrip('/') - url_bits = endpoint.split('/') - # regex to match 'v1' or 'v2.0' etc - if re.match('v\d+\.?\d*', url_bits[-1]): - version = float(url_bits[-1].lstrip('v')) - endpoint = '/'.join(url_bits[:-1]) - return endpoint, version - - -def print_image(image_obj, max_col_width=None): - ignore = ['self', 'access', 'file', 'schema'] - image = dict([item for item in six.iteritems(image_obj) - if item[0] not in ignore]) - if str(max_col_width).isdigit(): - print_dict(image, max_column_width=max_col_width) - else: - print_dict(image) - - -def integrity_iter(iter, checksum): - """ - Check image data integrity. - - :raises: IOError - """ - md5sum = hashlib.md5() - for chunk in iter: - yield chunk - if isinstance(chunk, six.string_types): - chunk = six.b(chunk) - md5sum.update(chunk) - md5sum = md5sum.hexdigest() - if md5sum != checksum: - raise IOError(errno.EPIPE, - 'Corrupt image download. Checksum was %s expected %s' % - (md5sum, checksum)) - - -def memoized_property(fn): - attr_name = '_lazy_once_' + fn.__name__ - - @property - def _memoized_property(self): - if hasattr(self, attr_name): - return getattr(self, attr_name) - else: - with _memoized_property_lock: - if not hasattr(self, attr_name): - setattr(self, attr_name, fn(self)) - return getattr(self, attr_name) - return _memoized_property - - -def safe_header(name, value): - if name in SENSITIVE_HEADERS: - v = value.encode('utf-8') - h = hashlib.sha1(v) - d = h.hexdigest() - return name, "{SHA1}%s" % d - else: - return name, value - - -class IterableWithLength(object): - def __init__(self, iterable, length): - self.iterable = iterable - self.length = length - - def __iter__(self): - return self.iterable - - def next(self): - return next(self.iterable) - - def __len__(self): - return self.length diff --git a/awx/lib/site-packages/glanceclient/exc.py b/awx/lib/site-packages/glanceclient/exc.py deleted file mode 100644 index 06a91262ed..0000000000 --- a/awx/lib/site-packages/glanceclient/exc.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import sys - - -class BaseException(Exception): - """An error occurred.""" - def __init__(self, message=None): - self.message = message - - def __str__(self): - return self.message or self.__class__.__doc__ - - -class CommandError(BaseException): - """Invalid usage of CLI.""" - - -class InvalidEndpoint(BaseException): - """The provided endpoint is invalid.""" - - -class CommunicationError(BaseException): - """Unable to communicate with server.""" - - -class ClientException(Exception): - """DEPRECATED!""" - - -class HTTPException(ClientException): - """Base exception for all HTTP-derived exceptions.""" - code = 'N/A' - - def __init__(self, details=None): - self.details = details or self.__class__.__name__ - - def __str__(self): - return "%s (HTTP %s)" % (self.details, self.code) - - -class HTTPMultipleChoices(HTTPException): - code = 300 - - def __str__(self): - self.details = ("Requested version of OpenStack Images API is not " - "available.") - return "%s (HTTP %s) %s" % (self.__class__.__name__, self.code, - self.details) - - -class BadRequest(HTTPException): - """DEPRECATED!""" - code = 400 - - -class HTTPBadRequest(BadRequest): - pass - - -class Unauthorized(HTTPException): - """DEPRECATED!""" - code = 401 - - -class HTTPUnauthorized(Unauthorized): - pass - - -class Forbidden(HTTPException): - """DEPRECATED!""" - code = 403 - - -class HTTPForbidden(Forbidden): - pass - - -class NotFound(HTTPException): - """DEPRECATED!""" - code = 404 - - -class HTTPNotFound(NotFound): - pass - - -class HTTPMethodNotAllowed(HTTPException): - code = 405 - - -class Conflict(HTTPException): - """DEPRECATED!""" - code = 409 - - -class HTTPConflict(Conflict): - pass - - -class OverLimit(HTTPException): - """DEPRECATED!""" - code = 413 - - -class HTTPOverLimit(OverLimit): - pass - - -class HTTPInternalServerError(HTTPException): - code = 500 - - -class HTTPNotImplemented(HTTPException): - code = 501 - - -class HTTPBadGateway(HTTPException): - code = 502 - - -class ServiceUnavailable(HTTPException): - """DEPRECATED!""" - code = 503 - - -class HTTPServiceUnavailable(ServiceUnavailable): - pass - - -# NOTE(bcwaldon): Build a mapping of HTTP codes to corresponding exception -# classes -_code_map = {} -for obj_name in dir(sys.modules[__name__]): - if obj_name.startswith('HTTP'): - obj = getattr(sys.modules[__name__], obj_name) - _code_map[obj.code] = obj - - -def from_response(response, body=None): - """Return an instance of an HTTPException based on httplib response.""" - cls = _code_map.get(response.status_code, HTTPException) - if body and 'json' in response.headers['content-type']: - # Iterate over the nested objects and retreive the "message" attribute. - messages = [obj.get('message') for obj in response.json().values()] - # Join all of the messages together nicely and filter out any objects - # that don't have a "message" attr. - details = '\n'.join(i for i in messages if i is not None) - return cls(details=details) - elif body and 'html' in response.headers['content-type']: - # Split the lines, strip whitespace and inline HTML from the response. - details = [re.sub(r'<.+?>', '', i.strip()) - for i in response.text.splitlines()] - details = [i for i in details if i] - # Remove duplicates from the list. - details_seen = set() - details_temp = [] - for i in details: - if i not in details_seen: - details_temp.append(i) - details_seen.add(i) - # Return joined string separated by colons. - details = ': '.join(details_temp) - return cls(details=details) - elif body: - details = body.replace('\n\n', '\n') - return cls(details=details) - - return cls() - - -class NoTokenLookupException(Exception): - """DEPRECATED!""" - pass - - -class EndpointNotFound(Exception): - """DEPRECATED!""" - pass - - -class SSLConfigurationError(BaseException): - pass - - -class SSLCertificateError(BaseException): - pass diff --git a/awx/lib/site-packages/glanceclient/openstack/__init__.py b/awx/lib/site-packages/glanceclient/openstack/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/glanceclient/openstack/common/__init__.py b/awx/lib/site-packages/glanceclient/openstack/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/glanceclient/openstack/common/_i18n.py b/awx/lib/site-packages/glanceclient/openstack/common/_i18n.py deleted file mode 100644 index cee8f01367..0000000000 --- a/awx/lib/site-packages/glanceclient/openstack/common/_i18n.py +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html - -""" - -try: - import oslo.i18n - - # NOTE(dhellmann): This reference to o-s-l-o will be replaced by the - # application name when this module is synced into the separate - # repository. It is OK to have more than one translation function - # using the same domain, since there will still only be one message - # catalog. - _translators = oslo.i18n.TranslatorFactory(domain='glanceclient') - - # The primary translation function using the well-known name "_" - _ = _translators.primary - - # Translators for log levels. - # - # The abbreviated names are meant to reflect the usual use of a short - # name like '_'. The "L" is for "log" and the other letter comes from - # the level. - _LI = _translators.log_info - _LW = _translators.log_warning - _LE = _translators.log_error - _LC = _translators.log_critical -except ImportError: - # NOTE(dims): Support for cases where a project wants to use - # code from oslo-incubator, but is not ready to be internationalized - # (like tempest) - _ = _LI = _LW = _LE = _LC = lambda x: x diff --git a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/__init__.py b/awx/lib/site-packages/glanceclient/openstack/common/apiclient/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/auth.py b/awx/lib/site-packages/glanceclient/openstack/common/apiclient/auth.py deleted file mode 100644 index 771df04ed8..0000000000 --- a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/auth.py +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 Spanish National Research Council. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -######################################################################## -# -# THIS MODULE IS DEPRECATED -# -# Please refer to -# https://etherpad.openstack.org/p/kilo-glanceclient-library-proposals for -# the discussion leading to this deprecation. -# -# We recommend checking out the python-openstacksdk project -# (https://launchpad.net/python-openstacksdk) instead. -# -######################################################################## - -import abc -import argparse -import os - -import six -from stevedore import extension - -from glanceclient.openstack.common.apiclient import exceptions - - -_discovered_plugins = {} - - -def discover_auth_systems(): - """Discover the available auth-systems. - - This won't take into account the old style auth-systems. - """ - global _discovered_plugins - _discovered_plugins = {} - - def add_plugin(ext): - _discovered_plugins[ext.name] = ext.plugin - - ep_namespace = "glanceclient.openstack.common.apiclient.auth" - mgr = extension.ExtensionManager(ep_namespace) - mgr.map(add_plugin) - - -def load_auth_system_opts(parser): - """Load options needed by the available auth-systems into a parser. - - This function will try to populate the parser with options from the - available plugins. - """ - group = parser.add_argument_group("Common auth options") - BaseAuthPlugin.add_common_opts(group) - for name, auth_plugin in six.iteritems(_discovered_plugins): - group = parser.add_argument_group( - "Auth-system '%s' options" % name, - conflict_handler="resolve") - auth_plugin.add_opts(group) - - -def load_plugin(auth_system): - try: - plugin_class = _discovered_plugins[auth_system] - except KeyError: - raise exceptions.AuthSystemNotFound(auth_system) - return plugin_class(auth_system=auth_system) - - -def load_plugin_from_args(args): - """Load required plugin and populate it with options. - - Try to guess auth system if it is not specified. Systems are tried in - alphabetical order. - - :type args: argparse.Namespace - :raises: AuthPluginOptionsMissing - """ - auth_system = args.os_auth_system - if auth_system: - plugin = load_plugin(auth_system) - plugin.parse_opts(args) - plugin.sufficient_options() - return plugin - - for plugin_auth_system in sorted(six.iterkeys(_discovered_plugins)): - plugin_class = _discovered_plugins[plugin_auth_system] - plugin = plugin_class() - plugin.parse_opts(args) - try: - plugin.sufficient_options() - except exceptions.AuthPluginOptionsMissing: - continue - return plugin - raise exceptions.AuthPluginOptionsMissing(["auth_system"]) - - -@six.add_metaclass(abc.ABCMeta) -class BaseAuthPlugin(object): - """Base class for authentication plugins. - - An authentication plugin needs to override at least the authenticate - method to be a valid plugin. - """ - - auth_system = None - opt_names = [] - common_opt_names = [ - "auth_system", - "username", - "password", - "tenant_name", - "token", - "auth_url", - ] - - def __init__(self, auth_system=None, **kwargs): - self.auth_system = auth_system or self.auth_system - self.opts = dict((name, kwargs.get(name)) - for name in self.opt_names) - - @staticmethod - def _parser_add_opt(parser, opt): - """Add an option to parser in two variants. - - :param opt: option name (with underscores) - """ - dashed_opt = opt.replace("_", "-") - env_var = "OS_%s" % opt.upper() - arg_default = os.environ.get(env_var, "") - arg_help = "Defaults to env[%s]." % env_var - parser.add_argument( - "--os-%s" % dashed_opt, - metavar="<%s>" % dashed_opt, - default=arg_default, - help=arg_help) - parser.add_argument( - "--os_%s" % opt, - metavar="<%s>" % dashed_opt, - help=argparse.SUPPRESS) - - @classmethod - def add_opts(cls, parser): - """Populate the parser with the options for this plugin. - """ - for opt in cls.opt_names: - # use `BaseAuthPlugin.common_opt_names` since it is never - # changed in child classes - if opt not in BaseAuthPlugin.common_opt_names: - cls._parser_add_opt(parser, opt) - - @classmethod - def add_common_opts(cls, parser): - """Add options that are common for several plugins. - """ - for opt in cls.common_opt_names: - cls._parser_add_opt(parser, opt) - - @staticmethod - def get_opt(opt_name, args): - """Return option name and value. - - :param opt_name: name of the option, e.g., "username" - :param args: parsed arguments - """ - return (opt_name, getattr(args, "os_%s" % opt_name, None)) - - def parse_opts(self, args): - """Parse the actual auth-system options if any. - - This method is expected to populate the attribute `self.opts` with a - dict containing the options and values needed to make authentication. - """ - self.opts.update(dict(self.get_opt(opt_name, args) - for opt_name in self.opt_names)) - - def authenticate(self, http_client): - """Authenticate using plugin defined method. - - The method usually analyses `self.opts` and performs - a request to authentication server. - - :param http_client: client object that needs authentication - :type http_client: HTTPClient - :raises: AuthorizationFailure - """ - self.sufficient_options() - self._do_authenticate(http_client) - - @abc.abstractmethod - def _do_authenticate(self, http_client): - """Protected method for authentication. - """ - - def sufficient_options(self): - """Check if all required options are present. - - :raises: AuthPluginOptionsMissing - """ - missing = [opt - for opt in self.opt_names - if not self.opts.get(opt)] - if missing: - raise exceptions.AuthPluginOptionsMissing(missing) - - @abc.abstractmethod - def token_and_endpoint(self, endpoint_type, service_type): - """Return token and endpoint. - - :param service_type: Service type of the endpoint - :type service_type: string - :param endpoint_type: Type of endpoint. - Possible values: public or publicURL, - internal or internalURL, - admin or adminURL - :type endpoint_type: string - :returns: tuple of token and endpoint strings - :raises: EndpointException - """ diff --git a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/base.py b/awx/lib/site-packages/glanceclient/openstack/common/apiclient/base.py deleted file mode 100644 index b208b062d3..0000000000 --- a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/base.py +++ /dev/null @@ -1,532 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2012 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -######################################################################## -# -# THIS MODULE IS DEPRECATED -# -# Please refer to -# https://etherpad.openstack.org/p/kilo-glanceclient-library-proposals for -# the discussion leading to this deprecation. -# -# We recommend checking out the python-openstacksdk project -# (https://launchpad.net/python-openstacksdk) instead. -# -######################################################################## - - -# E1102: %s is not callable -# pylint: disable=E1102 - -import abc -import copy - -from oslo_utils import strutils -import six -from six.moves.urllib import parse - -from glanceclient.openstack.common._i18n import _ -from glanceclient.openstack.common.apiclient import exceptions - - -def getid(obj): - """Return id if argument is a Resource. - - Abstracts the common pattern of allowing both an object or an object's ID - (UUID) as a parameter when dealing with relationships. - """ - try: - if obj.uuid: - return obj.uuid - except AttributeError: - pass - try: - return obj.id - except AttributeError: - return obj - - -# TODO(aababilov): call run_hooks() in HookableMixin's child classes -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - """Add a new hook of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param hook_func: hook function - """ - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - """Run all hooks of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param args: args to be passed to every hook function - :param kwargs: kwargs to be passed to every hook function - """ - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - -class BaseManager(HookableMixin): - """Basic manager type providing common operations. - - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, client): - """Initializes BaseManager with `client`. - - :param client: instance of BaseClient descendant for HTTP requests - """ - super(BaseManager, self).__init__() - self.client = client - - def _list(self, url, response_key=None, obj_class=None, json=None): - """List the collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - :param obj_class: class for constructing the returned objects - (self.resource_class will be used by default) - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - """ - if json: - body = self.client.post(url, json=json).json() - else: - body = self.client.get(url).json() - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] if response_key is not None else body - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - try: - data = data['values'] - except (KeyError, TypeError): - pass - - return [obj_class(self, res, loaded=True) for res in data if res] - - def _get(self, url, response_key=None): - """Get an object from collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'server'. If response_key is None - all response body - will be used. - """ - body = self.client.get(url).json() - data = body[response_key] if response_key is not None else body - return self.resource_class(self, data, loaded=True) - - def _head(self, url): - """Retrieve request headers for an object. - - :param url: a partial URL, e.g., '/servers' - """ - resp = self.client.head(url) - return resp.status_code == 204 - - def _post(self, url, json, response_key=None, return_raw=False): - """Create an object. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'server'. If response_key is None - all response body - will be used. - :param return_raw: flag to force returning raw JSON instead of - Python object of self.resource_class - """ - body = self.client.post(url, json=json).json() - data = body[response_key] if response_key is not None else body - if return_raw: - return data - return self.resource_class(self, data) - - def _put(self, url, json=None, response_key=None): - """Update an object with PUT method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - """ - resp = self.client.put(url, json=json) - # PUT requests may not return a body - if resp.content: - body = resp.json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _patch(self, url, json=None, response_key=None): - """Update an object with PATCH method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - """ - body = self.client.patch(url, json=json).json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _delete(self, url): - """Delete an object. - - :param url: a partial URL, e.g., '/servers/my-server' - """ - return self.client.delete(url) - - -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(BaseManager): - """Manager with additional `find()`/`findall()` methods.""" - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - matches = self.findall(**kwargs) - num_matches = len(matches) - if num_matches == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(msg) - elif num_matches > 1: - raise exceptions.NoUniqueMatch() - else: - return matches[0] - - def findall(self, **kwargs): - """Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - found = [] - searches = kwargs.items() - - for obj in self.list(): - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - found.append(obj) - except AttributeError: - continue - - return found - - -class CrudManager(BaseManager): - """Base manager class for manipulating entities. - - Children of this class are expected to define a `collection_key` and `key`. - - - `collection_key`: Usually a plural noun by convention (e.g. `entities`); - used to refer collections in both URL's (e.g. `/v3/entities`) and JSON - objects containing a list of member resources (e.g. `{'entities': [{}, - {}, {}]}`). - - `key`: Usually a singular noun by convention (e.g. `entity`); used to - refer to an individual member of the collection. - - """ - collection_key = None - key = None - - def build_url(self, base_url=None, **kwargs): - """Builds a resource URL for the given kwargs. - - Given an example collection where `collection_key = 'entities'` and - `key = 'entity'`, the following URL's could be generated. - - By default, the URL will represent a collection of entities, e.g.:: - - /entities - - If kwargs contains an `entity_id`, then the URL will represent a - specific member, e.g.:: - - /entities/{entity_id} - - :param base_url: if provided, the generated URL will be appended to it - """ - url = base_url if base_url is not None else '' - - url += '/%s' % self.collection_key - - # do we have a specific entity? - entity_id = kwargs.get('%s_id' % self.key) - if entity_id is not None: - url += '/%s' % entity_id - - return url - - def _filter_kwargs(self, kwargs): - """Drop null values and handle ids.""" - for key, ref in six.iteritems(kwargs.copy()): - if ref is None: - kwargs.pop(key) - else: - if isinstance(ref, Resource): - kwargs.pop(key) - kwargs['%s_id' % key] = getid(ref) - return kwargs - - def create(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._post( - self.build_url(**kwargs), - {self.key: kwargs}, - self.key) - - def get(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._get( - self.build_url(**kwargs), - self.key) - - def head(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._head(self.build_url(**kwargs)) - - def list(self, base_url=None, **kwargs): - """List the collection. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - - def put(self, base_url=None, **kwargs): - """Update an element. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._put(self.build_url(base_url=base_url, **kwargs)) - - def update(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - params = kwargs.copy() - params.pop('%s_id' % self.key) - - return self._patch( - self.build_url(**kwargs), - {self.key: params}, - self.key) - - def delete(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - - return self._delete( - self.build_url(**kwargs)) - - def find(self, base_url=None, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - rl = self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - num = len(rl) - - if num == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(404, msg) - elif num > 1: - raise exceptions.NoUniqueMatch - else: - return rl[0] - - -class Extension(HookableMixin): - """Extension descriptor.""" - - SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') - manager_class = None - - def __init__(self, name, module): - super(Extension, self).__init__() - self.name = name - self.module = module - self._parse_extension_module() - - def _parse_extension_module(self): - self.manager_class = None - for attr_name, attr_value in self.module.__dict__.items(): - if attr_name in self.SUPPORTED_HOOKS: - self.add_hook(attr_name, attr_value) - else: - try: - if issubclass(attr_value, BaseManager): - self.manager_class = attr_value - except TypeError: - pass - - def __repr__(self): - return "<Extension '%s'>" % self.name - - -class Resource(object): - """Base class for OpenStack resources (tenant, user, etc.). - - This is pretty much just a bag for attributes. - """ - - HUMAN_ID = False - NAME_ATTR = 'name' - - def __init__(self, manager, info, loaded=False): - """Populate and bind to a manager. - - :param manager: BaseManager object - :param info: dictionary representing resource attributes - :param loaded: prevent lazy-loading if set to True - """ - self.manager = manager - self._info = info - self._add_details(info) - self._loaded = loaded - - def __repr__(self): - reprkeys = sorted(k - for k in self.__dict__.keys() - if k[0] != '_' and k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) - - @property - def human_id(self): - """Human-readable ID which can be used for bash completion. - """ - if self.HUMAN_ID: - name = getattr(self, self.NAME_ATTR, None) - if name is not None: - return strutils.to_slug(name) - return None - - def _add_details(self, info): - for (k, v) in six.iteritems(info): - try: - setattr(self, k, v) - self._info[k] = v - except AttributeError: - # In this case we already defined the attribute on the class - pass - - def __getattr__(self, k): - if k not in self.__dict__: - # NOTE(bcwaldon): disallow lazy-loading if already loaded once - if not self.is_loaded(): - self.get() - return self.__getattr__(k) - - raise AttributeError(k) - else: - return self.__dict__[k] - - def get(self): - """Support for lazy loading details. - - Some clients, such as novaclient have the option to lazy load the - details, details which can be loaded with this function. - """ - # set_loaded() first ... so if we have to bail, we know we tried. - self.set_loaded(True) - if not hasattr(self.manager, 'get'): - return - - new = self.manager.get(self.id) - if new: - self._add_details(new._info) - self._add_details( - {'x_request_id': self.manager.client.last_request_id}) - - def __eq__(self, other): - if not isinstance(other, Resource): - return NotImplemented - # two resources of different types are not equal - if not isinstance(other, self.__class__): - return False - if hasattr(self, 'id') and hasattr(other, 'id'): - return self.id == other.id - return self._info == other._info - - def is_loaded(self): - return self._loaded - - def set_loaded(self, val): - self._loaded = val - - def to_dict(self): - return copy.deepcopy(self._info) diff --git a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/client.py b/awx/lib/site-packages/glanceclient/openstack/common/apiclient/client.py deleted file mode 100644 index ec2150ee37..0000000000 --- a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/client.py +++ /dev/null @@ -1,388 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Piston Cloud Computing, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import hashlib -import logging -import time - -try: - import simplejson as json -except ImportError: - import json - -from oslo_utils import encodeutils -from oslo_utils import importutils -import requests - -from glanceclient.openstack.common._i18n import _ -from glanceclient.openstack.common.apiclient import exceptions - -_logger = logging.getLogger(__name__) -SENSITIVE_HEADERS = ('X-Auth-Token', 'X-Subject-Token',) - - -class HTTPClient(object): - """This client handles sending HTTP requests to OpenStack servers. - - Features: - - - share authentication information between several clients to different - services (e.g., for compute and image clients); - - reissue authentication request for expired tokens; - - encode/decode JSON bodies; - - raise exceptions on HTTP errors; - - pluggable authentication; - - store authentication information in a keyring; - - store time spent for requests; - - register clients for particular services, so one can use - `http_client.identity` or `http_client.compute`; - - log requests and responses in a format that is easy to copy-and-paste - into terminal and send the same request with curl. - """ - - user_agent = "glanceclient.openstack.common.apiclient" - - def __init__(self, - auth_plugin, - region_name=None, - endpoint_type="publicURL", - original_ip=None, - verify=True, - cert=None, - timeout=None, - timings=False, - keyring_saver=None, - debug=False, - user_agent=None, - http=None): - self.auth_plugin = auth_plugin - - self.endpoint_type = endpoint_type - self.region_name = region_name - - self.original_ip = original_ip - self.timeout = timeout - self.verify = verify - self.cert = cert - - self.keyring_saver = keyring_saver - self.debug = debug - self.user_agent = user_agent or self.user_agent - - self.times = [] # [("item", starttime, endtime), ...] - self.timings = timings - - # requests within the same session can reuse TCP connections from pool - self.http = http or requests.Session() - - self.cached_token = None - self.last_request_id = None - - def _safe_header(self, name, value): - if name in SENSITIVE_HEADERS: - # because in python3 byte string handling is ... ug - v = value.encode('utf-8') - h = hashlib.sha1(v) - d = h.hexdigest() - return encodeutils.safe_decode(name), "{SHA1}%s" % d - else: - return (encodeutils.safe_decode(name), - encodeutils.safe_decode(value)) - - def _http_log_req(self, method, url, kwargs): - if not self.debug: - return - - string_parts = [ - "curl -g -i", - "-X '%s'" % method, - "'%s'" % url, - ] - - for element in kwargs['headers']: - header = ("-H '%s: %s'" % - self._safe_header(element, kwargs['headers'][element])) - string_parts.append(header) - - _logger.debug("REQ: %s" % " ".join(string_parts)) - if 'data' in kwargs: - _logger.debug("REQ BODY: %s\n" % (kwargs['data'])) - - def _http_log_resp(self, resp): - if not self.debug: - return - _logger.debug( - "RESP: [%s] %s\n", - resp.status_code, - resp.headers) - if resp._content_consumed: - _logger.debug( - "RESP BODY: %s\n", - resp.text) - - def serialize(self, kwargs): - if kwargs.get('json') is not None: - kwargs['headers']['Content-Type'] = 'application/json' - kwargs['data'] = json.dumps(kwargs['json']) - try: - del kwargs['json'] - except KeyError: - pass - - def get_timings(self): - return self.times - - def reset_timings(self): - self.times = [] - - def request(self, method, url, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around `requests.Session.request` to handle tasks such as - setting headers, JSON encoding/decoding, and error handling. - - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - requests.Session.request (such as `headers`) or `json` - that will be encoded as JSON and used as `data` argument - """ - kwargs.setdefault("headers", {}) - kwargs["headers"]["User-Agent"] = self.user_agent - if self.original_ip: - kwargs["headers"]["Forwarded"] = "for=%s;by=%s" % ( - self.original_ip, self.user_agent) - if self.timeout is not None: - kwargs.setdefault("timeout", self.timeout) - kwargs.setdefault("verify", self.verify) - if self.cert is not None: - kwargs.setdefault("cert", self.cert) - self.serialize(kwargs) - - self._http_log_req(method, url, kwargs) - if self.timings: - start_time = time.time() - resp = self.http.request(method, url, **kwargs) - if self.timings: - self.times.append(("%s %s" % (method, url), - start_time, time.time())) - self._http_log_resp(resp) - - self.last_request_id = resp.headers.get('x-openstack-request-id') - - if resp.status_code >= 400: - _logger.debug( - "Request returned failure status: %s", - resp.status_code) - raise exceptions.from_response(resp, method, url) - - return resp - - @staticmethod - def concat_url(endpoint, url): - """Concatenate endpoint and final URL. - - E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to - "http://keystone/v2.0/tokens". - - :param endpoint: the base URL - :param url: the final URL - """ - return "%s/%s" % (endpoint.rstrip("/"), url.strip("/")) - - def client_request(self, client, method, url, **kwargs): - """Send an http request using `client`'s endpoint and specified `url`. - - If request was rejected as unauthorized (possibly because the token is - expired), issue one authorization attempt and send the request once - again. - - :param client: instance of BaseClient descendant - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - `HTTPClient.request` - """ - - filter_args = { - "endpoint_type": client.endpoint_type or self.endpoint_type, - "service_type": client.service_type, - } - token, endpoint = (self.cached_token, client.cached_endpoint) - just_authenticated = False - if not (token and endpoint): - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - pass - if not (token and endpoint): - self.authenticate() - just_authenticated = True - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - if not (token and endpoint): - raise exceptions.AuthorizationFailure( - _("Cannot find endpoint or token for request")) - - old_token_endpoint = (token, endpoint) - kwargs.setdefault("headers", {})["X-Auth-Token"] = token - self.cached_token = token - client.cached_endpoint = endpoint - # Perform the request once. If we get Unauthorized, then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - except exceptions.Unauthorized as unauth_ex: - if just_authenticated: - raise - self.cached_token = None - client.cached_endpoint = None - if self.auth_plugin.opts.get('token'): - self.auth_plugin.opts['token'] = None - if self.auth_plugin.opts.get('endpoint'): - self.auth_plugin.opts['endpoint'] = None - self.authenticate() - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - raise unauth_ex - if (not (token and endpoint) or - old_token_endpoint == (token, endpoint)): - raise unauth_ex - self.cached_token = token - client.cached_endpoint = endpoint - kwargs["headers"]["X-Auth-Token"] = token - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - - def add_client(self, base_client_instance): - """Add a new instance of :class:`BaseClient` descendant. - - `self` will store a reference to `base_client_instance`. - - Example: - - >>> def test_clients(): - ... from keystoneclient.auth import keystone - ... from openstack.common.apiclient import client - ... auth = keystone.KeystoneAuthPlugin( - ... username="user", password="pass", tenant_name="tenant", - ... auth_url="http://auth:5000/v2.0") - ... openstack_client = client.HTTPClient(auth) - ... # create nova client - ... from novaclient.v1_1 import client - ... client.Client(openstack_client) - ... # create keystone client - ... from keystoneclient.v2_0 import client - ... client.Client(openstack_client) - ... # use them - ... openstack_client.identity.tenants.list() - ... openstack_client.compute.servers.list() - """ - service_type = base_client_instance.service_type - if service_type and not hasattr(self, service_type): - setattr(self, service_type, base_client_instance) - - def authenticate(self): - self.auth_plugin.authenticate(self) - # Store the authentication results in the keyring for later requests - if self.keyring_saver: - self.keyring_saver.save(self) - - -class BaseClient(object): - """Top-level object to access the OpenStack API. - - This client uses :class:`HTTPClient` to send requests. :class:`HTTPClient` - will handle a bunch of issues such as authentication. - """ - - service_type = None - endpoint_type = None # "publicURL" will be used - cached_endpoint = None - - def __init__(self, http_client, extensions=None): - self.http_client = http_client - http_client.add_client(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - def client_request(self, method, url, **kwargs): - return self.http_client.client_request( - self, method, url, **kwargs) - - @property - def last_request_id(self): - return self.http_client.last_request_id - - def head(self, url, **kwargs): - return self.client_request("HEAD", url, **kwargs) - - def get(self, url, **kwargs): - return self.client_request("GET", url, **kwargs) - - def post(self, url, **kwargs): - return self.client_request("POST", url, **kwargs) - - def put(self, url, **kwargs): - return self.client_request("PUT", url, **kwargs) - - def delete(self, url, **kwargs): - return self.client_request("DELETE", url, **kwargs) - - def patch(self, url, **kwargs): - return self.client_request("PATCH", url, **kwargs) - - @staticmethod - def get_class(api_name, version, version_map): - """Returns the client class for the requested API version - - :param api_name: the name of the API, e.g. 'compute', 'image', etc - :param version: the requested API version - :param version_map: a dict of client classes keyed by version - :rtype: a client class for the requested API version - """ - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = _("Invalid %(api_name)s client version '%(version)s'. " - "Must be one of: %(version_map)s") % { - 'api_name': api_name, - 'version': version, - 'version_map': ', '.join(version_map.keys())} - raise exceptions.UnsupportedVersion(msg) - - return importutils.import_class(client_path) diff --git a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/exceptions.py b/awx/lib/site-packages/glanceclient/openstack/common/apiclient/exceptions.py deleted file mode 100644 index be234a9c79..0000000000 --- a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/exceptions.py +++ /dev/null @@ -1,479 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Nebula, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception definitions. -""" - -######################################################################## -# -# THIS MODULE IS DEPRECATED -# -# Please refer to -# https://etherpad.openstack.org/p/kilo-glanceclient-library-proposals for -# the discussion leading to this deprecation. -# -# We recommend checking out the python-openstacksdk project -# (https://launchpad.net/python-openstacksdk) instead. -# -######################################################################## - -import inspect -import sys - -import six - -from glanceclient.openstack.common._i18n import _ - - -class ClientException(Exception): - """The base exception class for all exceptions this library raises. - """ - pass - - -class ValidationError(ClientException): - """Error in validation on API client side.""" - pass - - -class UnsupportedVersion(ClientException): - """User is trying to use an unsupported version of the API.""" - pass - - -class CommandError(ClientException): - """Error in CLI tool.""" - pass - - -class AuthorizationFailure(ClientException): - """Cannot authorize API client.""" - pass - - -class ConnectionError(ClientException): - """Cannot connect to API service.""" - pass - - -class ConnectionRefused(ConnectionError): - """Connection refused while trying to connect to API service.""" - pass - - -class AuthPluginOptionsMissing(AuthorizationFailure): - """Auth plugin misses some options.""" - def __init__(self, opt_names): - super(AuthPluginOptionsMissing, self).__init__( - _("Authentication failed. Missing options: %s") % - ", ".join(opt_names)) - self.opt_names = opt_names - - -class AuthSystemNotFound(AuthorizationFailure): - """User has specified an AuthSystem that is not installed.""" - def __init__(self, auth_system): - super(AuthSystemNotFound, self).__init__( - _("AuthSystemNotFound: %r") % auth_system) - self.auth_system = auth_system - - -class NoUniqueMatch(ClientException): - """Multiple entities found instead of one.""" - pass - - -class EndpointException(ClientException): - """Something is rotten in Service Catalog.""" - pass - - -class EndpointNotFound(EndpointException): - """Could not find requested endpoint in Service Catalog.""" - pass - - -class AmbiguousEndpoints(EndpointException): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - super(AmbiguousEndpoints, self).__init__( - _("AmbiguousEndpoints: %r") % endpoints) - self.endpoints = endpoints - - -class HttpError(ClientException): - """The base exception class for all HTTP exceptions. - """ - http_status = 0 - message = _("HTTP Error") - - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None): - self.http_status = http_status or self.http_status - self.message = message or self.message - self.details = details - self.request_id = request_id - self.response = response - self.url = url - self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) - if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HttpError, self).__init__(formatted_string) - - -class HTTPRedirection(HttpError): - """HTTP Redirection.""" - message = _("HTTP Redirection") - - -class HTTPClientError(HttpError): - """Client-side HTTP error. - - Exception for cases in which the client seems to have erred. - """ - message = _("HTTP Client Error") - - -class HttpServerError(HttpError): - """Server-side HTTP error. - - Exception for cases in which the server is aware that it has - erred or is incapable of performing the request. - """ - message = _("HTTP Server Error") - - -class MultipleChoices(HTTPRedirection): - """HTTP 300 - Multiple Choices. - - Indicates multiple options for the resource that the client may follow. - """ - - http_status = 300 - message = _("Multiple Choices") - - -class BadRequest(HTTPClientError): - """HTTP 400 - Bad Request. - - The request cannot be fulfilled due to bad syntax. - """ - http_status = 400 - message = _("Bad Request") - - -class Unauthorized(HTTPClientError): - """HTTP 401 - Unauthorized. - - Similar to 403 Forbidden, but specifically for use when authentication - is required and has failed or has not yet been provided. - """ - http_status = 401 - message = _("Unauthorized") - - -class PaymentRequired(HTTPClientError): - """HTTP 402 - Payment Required. - - Reserved for future use. - """ - http_status = 402 - message = _("Payment Required") - - -class Forbidden(HTTPClientError): - """HTTP 403 - Forbidden. - - The request was a valid request, but the server is refusing to respond - to it. - """ - http_status = 403 - message = _("Forbidden") - - -class NotFound(HTTPClientError): - """HTTP 404 - Not Found. - - The requested resource could not be found but may be available again - in the future. - """ - http_status = 404 - message = _("Not Found") - - -class MethodNotAllowed(HTTPClientError): - """HTTP 405 - Method Not Allowed. - - A request was made of a resource using a request method not supported - by that resource. - """ - http_status = 405 - message = _("Method Not Allowed") - - -class NotAcceptable(HTTPClientError): - """HTTP 406 - Not Acceptable. - - The requested resource is only capable of generating content not - acceptable according to the Accept headers sent in the request. - """ - http_status = 406 - message = _("Not Acceptable") - - -class ProxyAuthenticationRequired(HTTPClientError): - """HTTP 407 - Proxy Authentication Required. - - The client must first authenticate itself with the proxy. - """ - http_status = 407 - message = _("Proxy Authentication Required") - - -class RequestTimeout(HTTPClientError): - """HTTP 408 - Request Timeout. - - The server timed out waiting for the request. - """ - http_status = 408 - message = _("Request Timeout") - - -class Conflict(HTTPClientError): - """HTTP 409 - Conflict. - - Indicates that the request could not be processed because of conflict - in the request, such as an edit conflict. - """ - http_status = 409 - message = _("Conflict") - - -class Gone(HTTPClientError): - """HTTP 410 - Gone. - - Indicates that the resource requested is no longer available and will - not be available again. - """ - http_status = 410 - message = _("Gone") - - -class LengthRequired(HTTPClientError): - """HTTP 411 - Length Required. - - The request did not specify the length of its content, which is - required by the requested resource. - """ - http_status = 411 - message = _("Length Required") - - -class PreconditionFailed(HTTPClientError): - """HTTP 412 - Precondition Failed. - - The server does not meet one of the preconditions that the requester - put on the request. - """ - http_status = 412 - message = _("Precondition Failed") - - -class RequestEntityTooLarge(HTTPClientError): - """HTTP 413 - Request Entity Too Large. - - The request is larger than the server is willing or able to process. - """ - http_status = 413 - message = _("Request Entity Too Large") - - def __init__(self, *args, **kwargs): - try: - self.retry_after = int(kwargs.pop('retry_after')) - except (KeyError, ValueError): - self.retry_after = 0 - - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) - - -class RequestUriTooLong(HTTPClientError): - """HTTP 414 - Request-URI Too Long. - - The URI provided was too long for the server to process. - """ - http_status = 414 - message = _("Request-URI Too Long") - - -class UnsupportedMediaType(HTTPClientError): - """HTTP 415 - Unsupported Media Type. - - The request entity has a media type which the server or resource does - not support. - """ - http_status = 415 - message = _("Unsupported Media Type") - - -class RequestedRangeNotSatisfiable(HTTPClientError): - """HTTP 416 - Requested Range Not Satisfiable. - - The client has asked for a portion of the file, but the server cannot - supply that portion. - """ - http_status = 416 - message = _("Requested Range Not Satisfiable") - - -class ExpectationFailed(HTTPClientError): - """HTTP 417 - Expectation Failed. - - The server cannot meet the requirements of the Expect request-header field. - """ - http_status = 417 - message = _("Expectation Failed") - - -class UnprocessableEntity(HTTPClientError): - """HTTP 422 - Unprocessable Entity. - - The request was well-formed but was unable to be followed due to semantic - errors. - """ - http_status = 422 - message = _("Unprocessable Entity") - - -class InternalServerError(HttpServerError): - """HTTP 500 - Internal Server Error. - - A generic error message, given when no more specific message is suitable. - """ - http_status = 500 - message = _("Internal Server Error") - - -# NotImplemented is a python keyword. -class HttpNotImplemented(HttpServerError): - """HTTP 501 - Not Implemented. - - The server either does not recognize the request method, or it lacks - the ability to fulfill the request. - """ - http_status = 501 - message = _("Not Implemented") - - -class BadGateway(HttpServerError): - """HTTP 502 - Bad Gateway. - - The server was acting as a gateway or proxy and received an invalid - response from the upstream server. - """ - http_status = 502 - message = _("Bad Gateway") - - -class ServiceUnavailable(HttpServerError): - """HTTP 503 - Service Unavailable. - - The server is currently unavailable. - """ - http_status = 503 - message = _("Service Unavailable") - - -class GatewayTimeout(HttpServerError): - """HTTP 504 - Gateway Timeout. - - The server was acting as a gateway or proxy and did not receive a timely - response from the upstream server. - """ - http_status = 504 - message = _("Gateway Timeout") - - -class HttpVersionNotSupported(HttpServerError): - """HTTP 505 - HttpVersion Not Supported. - - The server does not support the HTTP protocol version used in the request. - """ - http_status = 505 - message = _("HTTP Version Not Supported") - - -# _code_map contains all the classes that have http_status attribute. -_code_map = dict( - (getattr(obj, 'http_status', None), obj) - for name, obj in six.iteritems(vars(sys.modules[__name__])) - if inspect.isclass(obj) and getattr(obj, 'http_status', False) -) - - -def from_response(response, method, url): - """Returns an instance of :class:`HttpError` or subclass based on response. - - :param response: instance of `requests.Response` class - :param method: HTTP method used for request - :param url: URL used for request - """ - - req_id = response.headers.get("x-openstack-request-id") - # NOTE(hdd) true for older versions of nova and cinder - if not req_id: - req_id = response.headers.get("x-compute-request-id") - kwargs = { - "http_status": response.status_code, - "response": response, - "method": method, - "url": url, - "request_id": req_id, - } - if "retry-after" in response.headers: - kwargs["retry_after"] = response.headers["retry-after"] - - content_type = response.headers.get("Content-Type", "") - if content_type.startswith("application/json"): - try: - body = response.json() - except ValueError: - pass - else: - if isinstance(body, dict): - error = body.get(list(body)[0]) - if isinstance(error, dict): - kwargs["message"] = (error.get("message") or - error.get("faultstring")) - kwargs["details"] = (error.get("details") or - six.text_type(body)) - elif content_type.startswith("text/"): - kwargs["details"] = response.text - - try: - cls = _code_map[response.status_code] - except KeyError: - if 500 <= response.status_code < 600: - cls = HttpServerError - elif 400 <= response.status_code < 500: - cls = HTTPClientError - else: - cls = HttpError - return cls(**kwargs) diff --git a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/fake_client.py b/awx/lib/site-packages/glanceclient/openstack/common/apiclient/fake_client.py deleted file mode 100644 index a6a736a06f..0000000000 --- a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/fake_client.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -######################################################################## -# -# THIS MODULE IS DEPRECATED -# -# Please refer to -# https://etherpad.openstack.org/p/kilo-glanceclient-library-proposals for -# the discussion leading to this deprecation. -# -# We recommend checking out the python-openstacksdk project -# (https://launchpad.net/python-openstacksdk) instead. -# -######################################################################## - -# W0102: Dangerous default value %s as argument -# pylint: disable=W0102 - -import json - -import requests -import six -from six.moves.urllib import parse - -from glanceclient.openstack.common.apiclient import client - - -def assert_has_keys(dct, required=None, optional=None): - required = required or [] - optional = optional or [] - for k in required: - try: - assert k in dct - except AssertionError: - extra_keys = set(dct.keys()).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class TestResponse(requests.Response): - """Wrap requests.Response and provide a convenient initialization. - """ - - def __init__(self, data): - super(TestResponse, self).__init__() - self._content_consumed = True - if isinstance(data, dict): - self.status_code = data.get('status_code', 200) - # Fake the text attribute to streamline Response creation - text = data.get('text', "") - if isinstance(text, (dict, list)): - self._content = json.dumps(text) - default_headers = { - "Content-Type": "application/json", - } - else: - self._content = text - default_headers = {} - if six.PY3 and isinstance(self._content, six.string_types): - self._content = self._content.encode('utf-8', 'strict') - self.headers = data.get('headers') or default_headers - else: - self.status_code = data - - def __eq__(self, other): - return (self.status_code == other.status_code and - self.headers == other.headers and - self._content == other._content) - - -class FakeHTTPClient(client.HTTPClient): - - def __init__(self, *args, **kwargs): - self.callstack = [] - self.fixtures = kwargs.pop("fixtures", None) or {} - if not args and "auth_plugin" not in kwargs: - args = (None, ) - super(FakeHTTPClient, self).__init__(*args, **kwargs) - - def assert_called(self, method, url, body=None, pos=-1): - """Assert than an API method was just called. - """ - expected = (method, url) - called = self.callstack[pos][0:2] - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - assert expected == called, 'Expected %s %s; got %s %s' % \ - (expected + called) - - if body is not None: - if self.callstack[pos][3] != body: - raise AssertionError('%r != %r' % - (self.callstack[pos][3], body)) - - def assert_called_anytime(self, method, url, body=None): - """Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - found = False - entry = None - for entry in self.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s %s; got %s' % \ - (method, url, self.callstack) - if body is not None: - assert entry[3] == body, "%s != %s" % (entry[3], body) - - self.callstack = [] - - def clear_callstack(self): - self.callstack = [] - - def authenticate(self): - pass - - def client_request(self, client, method, url, **kwargs): - # Check that certain things are called correctly - if method in ["GET", "DELETE"]: - assert "json" not in kwargs - - # Note the call - self.callstack.append( - (method, - url, - kwargs.get("headers") or {}, - kwargs.get("json") or kwargs.get("data"))) - try: - fixture = self.fixtures[url][method] - except KeyError: - pass - else: - return TestResponse({"headers": fixture[0], - "text": fixture[1]}) - - # Call the method - args = parse.parse_qsl(parse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - resp = getattr(self, callback)(**kwargs) - if len(resp) == 3: - status, headers, body = resp - else: - status, body = resp - headers = {} - self.last_request_id = headers.get('x-openstack-request-id', - 'req-test') - return TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) diff --git a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/utils.py b/awx/lib/site-packages/glanceclient/openstack/common/apiclient/utils.py deleted file mode 100644 index 7110d92610..0000000000 --- a/awx/lib/site-packages/glanceclient/openstack/common/apiclient/utils.py +++ /dev/null @@ -1,100 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -######################################################################## -# -# THIS MODULE IS DEPRECATED -# -# Please refer to -# https://etherpad.openstack.org/p/kilo-glanceclient-library-proposals for -# the discussion leading to this deprecation. -# -# We recommend checking out the python-openstacksdk project -# (https://launchpad.net/python-openstacksdk) instead. -# -######################################################################## - -from oslo_utils import encodeutils -from oslo_utils import uuidutils -import six - -from glanceclient.openstack.common._i18n import _ -from glanceclient.openstack.common.apiclient import exceptions - - -def find_resource(manager, name_or_id, **find_args): - """Look for resource in a given manager. - - Used as a helper for the _find_* methods. - Example: - - .. code-block:: python - - def _find_hypervisor(cs, hypervisor): - #Get a hypervisor by name or ID. - return cliutils.find_resource(cs.hypervisors, hypervisor) - """ - # first try to get entity as integer id - try: - return manager.get(int(name_or_id)) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # now try to get entity as uuid - try: - if six.PY2: - tmp_id = encodeutils.safe_encode(name_or_id) - else: - tmp_id = encodeutils.safe_decode(name_or_id) - - if uuidutils.is_uuid_like(tmp_id): - return manager.get(tmp_id) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # for str id which is not uuid - if getattr(manager, 'is_alphanum_id_allowed', False): - try: - return manager.get(name_or_id) - except exceptions.NotFound: - pass - - try: - try: - return manager.find(human_id=name_or_id, **find_args) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - resource = getattr(manager, 'resource_class', None) - name_attr = resource.NAME_ATTR if resource else 'name' - kwargs = {name_attr: name_or_id} - kwargs.update(find_args) - return manager.find(**kwargs) - except exceptions.NotFound: - msg = _("No %(name)s with a name or " - "ID of '%(name_or_id)s' exists.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = _("Multiple %(name)s matches found for " - "'%(name_or_id)s', use an ID to be more specific.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) diff --git a/awx/lib/site-packages/glanceclient/shell.py b/awx/lib/site-packages/glanceclient/shell.py deleted file mode 100644 index f212323d1b..0000000000 --- a/awx/lib/site-packages/glanceclient/shell.py +++ /dev/null @@ -1,706 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Command-line interface to the OpenStack Images API. -""" - -from __future__ import print_function - -import argparse -import copy -import getpass -import json -import logging -import os -from os.path import expanduser -import sys -import traceback - -from oslo_utils import encodeutils -from oslo_utils import importutils -import six.moves.urllib.parse as urlparse - -import glanceclient -from glanceclient import _i18n -from glanceclient.common import utils -from glanceclient import exc - -from keystoneclient.auth.identity import v2 as v2_auth -from keystoneclient.auth.identity import v3 as v3_auth -from keystoneclient import discover -from keystoneclient.openstack.common.apiclient import exceptions as ks_exc -from keystoneclient import session - -osprofiler_profiler = importutils.try_import("osprofiler.profiler") -_ = _i18n._ - - -class OpenStackImagesShell(object): - - def _append_global_identity_args(self, parser): - # FIXME(bobt): these are global identity (Keystone) arguments which - # should be consistent and shared by all service clients. Therefore, - # they should be provided by python-keystoneclient. We will need to - # refactor this code once this functionality is avaible in - # python-keystoneclient. See - # - # https://bugs.launchpad.net/python-keystoneclient/+bug/1332337 - # - parser.add_argument('-k', '--insecure', - default=False, - action='store_true', - help='Explicitly allow glanceclient to perform ' - '\"insecure SSL\" (https) requests. The server\'s ' - 'certificate will not be verified against any ' - 'certificate authorities. This option should ' - 'be used with caution.') - - parser.add_argument('--os-cert', - help='Path of certificate file to use in SSL ' - 'connection. This file can optionally be ' - 'prepended with the private key.') - - parser.add_argument('--cert-file', - dest='os_cert', - help='DEPRECATED! Use --os-cert.') - - parser.add_argument('--os-key', - help='Path of client key to use in SSL ' - 'connection. This option is not necessary ' - 'if your key is prepended to your cert file.') - - parser.add_argument('--key-file', - dest='os_key', - help='DEPRECATED! Use --os-key.') - - parser.add_argument('--os-cacert', - metavar='<ca-certificate-file>', - dest='os_cacert', - default=utils.env('OS_CACERT'), - help='Path of CA TLS certificate(s) used to ' - 'verify the remote server\'s certificate. ' - 'Without this option glance looks for the ' - 'default system CA certificates.') - - parser.add_argument('--ca-file', - dest='os_cacert', - help='DEPRECATED! Use --os-cacert.') - - parser.add_argument('--os-username', - default=utils.env('OS_USERNAME'), - help='Defaults to env[OS_USERNAME].') - - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-user-id', - default=utils.env('OS_USER_ID'), - help='Defaults to env[OS_USER_ID].') - - parser.add_argument('--os-user-domain-id', - default=utils.env('OS_USER_DOMAIN_ID'), - help='Defaults to env[OS_USER_DOMAIN_ID].') - - parser.add_argument('--os-user-domain-name', - default=utils.env('OS_USER_DOMAIN_NAME'), - help='Defaults to env[OS_USER_DOMAIN_NAME].') - - parser.add_argument('--os-project-id', - default=utils.env('OS_PROJECT_ID'), - help='Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - ' --os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].') - - parser.add_argument('--os-project-name', - default=utils.env('OS_PROJECT_NAME'), - help='Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - ' --os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].') - - parser.add_argument('--os-project-domain-id', - default=utils.env('OS_PROJECT_DOMAIN_ID'), - help='Defaults to env[OS_PROJECT_DOMAIN_ID].') - - parser.add_argument('--os-project-domain-name', - default=utils.env('OS_PROJECT_DOMAIN_NAME'), - help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') - - parser.add_argument('--os-password', - default=utils.env('OS_PASSWORD'), - help='Defaults to env[OS_PASSWORD].') - - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - default=utils.env('OS_TENANT_ID'), - help='Defaults to env[OS_TENANT_ID].') - - parser.add_argument('--os_tenant_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - default=utils.env('OS_TENANT_NAME'), - help='Defaults to env[OS_TENANT_NAME].') - - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-url', - default=utils.env('OS_AUTH_URL'), - help='Defaults to env[OS_AUTH_URL].') - - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-region-name', - default=utils.env('OS_REGION_NAME'), - help='Defaults to env[OS_REGION_NAME].') - - parser.add_argument('--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-token', - default=utils.env('OS_AUTH_TOKEN'), - help='Defaults to env[OS_AUTH_TOKEN].') - - parser.add_argument('--os_auth_token', - help=argparse.SUPPRESS) - - parser.add_argument('--os-service-type', - default=utils.env('OS_SERVICE_TYPE'), - help='Defaults to env[OS_SERVICE_TYPE].') - - parser.add_argument('--os_service_type', - help=argparse.SUPPRESS) - - parser.add_argument('--os-endpoint-type', - default=utils.env('OS_ENDPOINT_TYPE'), - help='Defaults to env[OS_ENDPOINT_TYPE].') - - parser.add_argument('--os_endpoint_type', - help=argparse.SUPPRESS) - - def get_base_parser(self): - parser = argparse.ArgumentParser( - prog='glance', - description=__doc__.strip(), - epilog='See "glance help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=HelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS, - ) - - parser.add_argument('--version', - action='version', - version=glanceclient.__version__) - - parser.add_argument('-d', '--debug', - default=bool(utils.env('GLANCECLIENT_DEBUG')), - action='store_true', - help='Defaults to env[GLANCECLIENT_DEBUG].') - - parser.add_argument('-v', '--verbose', - default=False, action="store_true", - help="Print more verbose output") - - parser.add_argument('--get-schema', - default=False, action="store_true", - dest='get_schema', - help='Ignores cached copy and forces retrieval ' - 'of schema that generates portions of the ' - 'help text. Ignored with API version 1.') - - parser.add_argument('--timeout', - default=600, - help='Number of seconds to wait for a response') - - parser.add_argument('--no-ssl-compression', - dest='ssl_compression', - default=True, action='store_false', - help='Disable SSL compression when using https.') - - parser.add_argument('-f', '--force', - dest='force', - default=False, action='store_true', - help='Prevent select actions from requesting ' - 'user confirmation.') - - parser.add_argument('--os-image-url', - default=utils.env('OS_IMAGE_URL'), - help=('Defaults to env[OS_IMAGE_URL]. ' - 'If the provided image url contains ' - 'a version number and ' - '`--os-image-api-version` is omitted ' - 'the version of the URL will be picked as ' - 'the image api version to use.')) - - parser.add_argument('--os_image_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-image-api-version', - default=utils.env('OS_IMAGE_API_VERSION', - default=None), - help='Defaults to env[OS_IMAGE_API_VERSION] or 1.') - - parser.add_argument('--os_image_api_version', - help=argparse.SUPPRESS) - - if osprofiler_profiler: - parser.add_argument('--profile', - metavar='HMAC_KEY', - help='HMAC key to use for encrypting context ' - 'data for performance profiling of operation. ' - 'This key should be the value of HMAC key ' - 'configured in osprofiler middleware in ' - 'glance, it is specified in paste ' - 'configuration file at ' - '/etc/glance/api-paste.ini and ' - '/etc/glance/registry-paste.ini. Without key ' - 'the profiling will not be triggered even ' - 'if osprofiler is enabled on server side.') - - # FIXME(bobt): this method should come from python-keystoneclient - self._append_global_identity_args(parser) - - return parser - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='<subcommand>') - try: - submodule = utils.import_versioned_module(version, 'shell') - except ImportError: - print('"%s" is not a supported API version. Example ' - 'values are "1" or "2".' % version) - utils.exit() - - self._find_actions(subparsers, submodule) - self._find_actions(subparsers, self) - - self._add_bash_completion_subparser(subparsers) - - return parser - - def _find_actions(self, subparsers, actions_module): - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hypen-separated instead of underscores. - command = attr[3:].replace('_', '-') - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - help = desc.strip().split('\n')[0] - arguments = getattr(callback, 'arguments', []) - - subparser = subparsers.add_parser(command, - help=help, - description=desc, - add_help=False, - formatter_class=HelpFormatter - ) - subparser.add_argument('-h', '--help', - action='help', - help=argparse.SUPPRESS, - ) - self.subcommands[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - def _add_bash_completion_subparser(self, subparsers): - subparser = subparsers.add_parser('bash_completion', - add_help=False, - formatter_class=HelpFormatter) - self.subcommands['bash_completion'] = subparser - subparser.set_defaults(func=self.do_bash_completion) - - def _get_image_url(self, args): - """Translate the available url-related options into a single string. - - Return the endpoint that should be used to talk to Glance if a - clear decision can be made. Otherwise, return None. - """ - if args.os_image_url: - return args.os_image_url - else: - return None - - def _discover_auth_versions(self, session, auth_url): - # discover the API versions the server is supporting base on the - # given URL - v2_auth_url = None - v3_auth_url = None - try: - ks_discover = discover.Discover(session=session, auth_url=auth_url) - v2_auth_url = ks_discover.url_for('2.0') - v3_auth_url = ks_discover.url_for('3.0') - except ks_exc.ClientException as e: - # Identity service may not support discover API version. - # Lets trying to figure out the API version from the original URL. - url_parts = urlparse.urlparse(auth_url) - (scheme, netloc, path, params, query, fragment) = url_parts - path = path.lower() - if path.startswith('/v3'): - v3_auth_url = auth_url - elif path.startswith('/v2'): - v2_auth_url = auth_url - else: - # not enough information to determine the auth version - msg = ('Unable to determine the Keystone version ' - 'to authenticate with using the given ' - 'auth_url. Identity service may not support API ' - 'version discovery. Please provide a versioned ' - 'auth_url instead. error=%s') % (e) - raise exc.CommandError(msg) - - return (v2_auth_url, v3_auth_url) - - def _get_keystone_session(self, **kwargs): - ks_session = session.Session.construct(kwargs) - - # discover the supported keystone versions using the given auth url - auth_url = kwargs.pop('auth_url', None) - (v2_auth_url, v3_auth_url) = self._discover_auth_versions( - session=ks_session, - auth_url=auth_url) - - # Determine which authentication plugin to use. First inspect the - # auth_url to see the supported version. If both v3 and v2 are - # supported, then use the highest version if possible. - user_id = kwargs.pop('user_id', None) - username = kwargs.pop('username', None) - password = kwargs.pop('password', None) - user_domain_name = kwargs.pop('user_domain_name', None) - user_domain_id = kwargs.pop('user_domain_id', None) - # project and tenant can be used interchangeably - project_id = (kwargs.pop('project_id', None) or - kwargs.pop('tenant_id', None)) - project_name = (kwargs.pop('project_name', None) or - kwargs.pop('tenant_name', None)) - project_domain_id = kwargs.pop('project_domain_id', None) - project_domain_name = kwargs.pop('project_domain_name', None) - auth = None - - use_domain = (user_domain_id or - user_domain_name or - project_domain_id or - project_domain_name) - use_v3 = v3_auth_url and (use_domain or (not v2_auth_url)) - use_v2 = v2_auth_url and not use_domain - - if use_v3: - auth = v3_auth.Password( - v3_auth_url, - user_id=user_id, - username=username, - password=password, - user_domain_id=user_domain_id, - user_domain_name=user_domain_name, - project_id=project_id, - project_name=project_name, - project_domain_id=project_domain_id, - project_domain_name=project_domain_name) - elif use_v2: - auth = v2_auth.Password( - v2_auth_url, - username, - password, - tenant_id=project_id, - tenant_name=project_name) - else: - # if we get here it means domain information is provided - # (caller meant to use Keystone V3) but the auth url is - # actually Keystone V2. Obviously we can't authenticate a V3 - # user using V2. - exc.CommandError("Credential and auth_url mismatch. The given " - "auth_url is using Keystone V2 endpoint, which " - "may not able to handle Keystone V3 credentials. " - "Please provide a correct Keystone V3 auth_url.") - - ks_session.auth = auth - return ks_session - - def _get_endpoint_and_token(self, args, force_auth=False): - image_url = self._get_image_url(args) - auth_token = args.os_auth_token - - auth_reqd = force_auth or (utils.is_authentication_required(args.func) - and not (auth_token and image_url)) - - if not auth_reqd: - endpoint = image_url - token = args.os_auth_token - else: - - if not args.os_username: - raise exc.CommandError( - _("You must provide a username via" - " either --os-username or " - "env[OS_USERNAME]")) - - if not args.os_password: - # No password, If we've got a tty, try prompting for it - if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): - # Check for Ctl-D - try: - args.os_password = getpass.getpass('OS Password: ') - except EOFError: - pass - # No password because we didn't have a tty or the - # user Ctl-D when prompted. - if not args.os_password: - raise exc.CommandError( - _("You must provide a password via " - "either --os-password, " - "env[OS_PASSWORD], " - "or prompted response")) - - # Validate password flow auth - project_info = ( - args.os_tenant_name or args.os_tenant_id or ( - args.os_project_name and ( - args.os_project_domain_name or - args.os_project_domain_id - ) - ) or args.os_project_id - ) - - if not project_info: - # tenant is deprecated in Keystone v3. Use the latest - # terminology instead. - raise exc.CommandError( - _("You must provide a project_id or project_name (" - "with project_domain_name or project_domain_id) " - "via " - " --os-project-id (env[OS_PROJECT_ID])" - " --os-project-name (env[OS_PROJECT_NAME])," - " --os-project-domain-id " - "(env[OS_PROJECT_DOMAIN_ID])" - " --os-project-domain-name " - "(env[OS_PROJECT_DOMAIN_NAME])")) - - if not args.os_auth_url: - raise exc.CommandError( - _("You must provide an auth url via" - " either --os-auth-url or " - "via env[OS_AUTH_URL]")) - - kwargs = { - 'auth_url': args.os_auth_url, - 'username': args.os_username, - 'user_id': args.os_user_id, - 'user_domain_id': args.os_user_domain_id, - 'user_domain_name': args.os_user_domain_name, - 'password': args.os_password, - 'tenant_name': args.os_tenant_name, - 'tenant_id': args.os_tenant_id, - 'project_name': args.os_project_name, - 'project_id': args.os_project_id, - 'project_domain_name': args.os_project_domain_name, - 'project_domain_id': args.os_project_domain_id, - 'insecure': args.insecure, - 'cacert': args.os_cacert, - 'cert': args.os_cert, - 'key': args.os_key - } - ks_session = self._get_keystone_session(**kwargs) - token = args.os_auth_token or ks_session.get_token() - - endpoint_type = args.os_endpoint_type or 'public' - service_type = args.os_service_type or 'image' - endpoint = args.os_image_url or ks_session.get_endpoint( - service_type=service_type, - interface=endpoint_type, - region_name=args.os_region_name) - - return endpoint, token - - def _get_versioned_client(self, api_version, args, force_auth=False): - endpoint, token = self._get_endpoint_and_token(args, - force_auth=force_auth) - - kwargs = { - 'token': token, - 'insecure': args.insecure, - 'timeout': args.timeout, - 'cacert': args.os_cacert, - 'cert': args.os_cert, - 'key': args.os_key, - 'ssl_compression': args.ssl_compression - } - client = glanceclient.Client(api_version, endpoint, **kwargs) - return client - - def _cache_schemas(self, options, home_dir='~/.glanceclient'): - homedir = expanduser(home_dir) - if not os.path.exists(homedir): - os.makedirs(homedir) - - resources = ['image', 'metadefs/namespace', 'metadefs/resource_type'] - schema_file_paths = [homedir + os.sep + x + '_schema.json' - for x in ['image', 'namespace', 'resource_type']] - - client = None - for resource, schema_file_path in zip(resources, schema_file_paths): - if (not os.path.exists(schema_file_path)) or options.get_schema: - try: - if not client: - client = self._get_versioned_client('2', options, - force_auth=True) - schema = client.schemas.get(resource) - - with open(schema_file_path, 'w') as f: - f.write(json.dumps(schema.raw())) - except Exception: - # NOTE(esheffield) do nothing here, we'll get a message - # later if the schema is missing - pass - - def main(self, argv): - # Parse args once to find version - - # NOTE(flepied) Under Python3, parsed arguments are removed - # from the list so make a copy for the first parsing - base_argv = copy.deepcopy(argv) - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(base_argv) - - try: - # NOTE(flaper87): Try to get the version from the - # image-url first. If no version was specified, fallback - # to the api-image-version arg. If both of these fail then - # fallback to the minimum supported one and let keystone - # do the magic. - endpoint = self._get_image_url(options) - endpoint, url_version = utils.strip_version(endpoint) - except ValueError: - # NOTE(flaper87): ValueError is raised if no endpoint is povided - url_version = None - - # build available subcommands based on version - try: - api_version = int(options.os_image_api_version or url_version or 1) - except ValueError: - print("Invalid API version parameter") - utils.exit() - - if api_version == 2: - self._cache_schemas(options) - - subcommand_parser = self.get_subcommand_parser(api_version) - self.parser = subcommand_parser - - # Handle top-level --help/-h before attempting to parse - # a command off the command line - if options.help or not argv: - self.do_help(options) - return 0 - - # Parse args again and call whatever callback was selected - args = subcommand_parser.parse_args(argv) - - # Short-circuit and deal with help command right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion(args) - return 0 - - LOG = logging.getLogger('glanceclient') - LOG.addHandler(logging.StreamHandler()) - LOG.setLevel(logging.DEBUG if args.debug else logging.INFO) - - profile = osprofiler_profiler and options.profile - if profile: - osprofiler_profiler.init(options.profile) - - client = self._get_versioned_client(api_version, args, - force_auth=False) - - try: - args.func(client, args) - except exc.Unauthorized: - raise exc.CommandError("Invalid OpenStack Identity credentials.") - except Exception: - # NOTE(kragniz) Print any exceptions raised to stderr if the - # --debug flag is set - if args.debug: - traceback.print_exc() - raise - finally: - if profile: - trace_id = osprofiler_profiler.get().get_base_id() - print("Profiling trace ID: %s" % trace_id) - print("To display trace use next command:\n" - "osprofiler trace show --html %s " % trace_id) - - @utils.arg('command', metavar='<subcommand>', nargs='?', - help='Display help for <subcommand>.') - def do_help(self, args): - """ - Display help about this program or one of its subcommands. - """ - if getattr(args, 'command', None): - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError("'%s' is not a valid subcommand" % - args.command) - else: - self.parser.print_help() - - def do_bash_completion(self, _args): - """Prints arguments for bash_completion. - - Prints all of the commands and options to stdout so that the - glance.bash_completion script doesn't have to hard code them. - """ - commands = set() - options = set() - for sc_str, sc in self.subcommands.items(): - commands.add(sc_str) - for option in sc._optionals._option_string_actions.keys(): - options.add(option) - - commands.remove('bash_completion') - commands.remove('bash-completion') - print(' '.join(commands | options)) - - -class HelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(HelpFormatter, self).start_section(heading) - - -def main(): - try: - OpenStackImagesShell().main(map(encodeutils.safe_decode, sys.argv[1:])) - except KeyboardInterrupt: - utils.exit('... terminating glance client', exit_code=130) - except Exception as e: - utils.exit(utils.exception_to_str(e)) diff --git a/awx/lib/site-packages/glanceclient/v1/__init__.py b/awx/lib/site-packages/glanceclient/v1/__init__.py deleted file mode 100644 index 39e1d5a8f5..0000000000 --- a/awx/lib/site-packages/glanceclient/v1/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glanceclient.v1.client import Client # noqa diff --git a/awx/lib/site-packages/glanceclient/v1/client.py b/awx/lib/site-packages/glanceclient/v1/client.py deleted file mode 100644 index 668ccfb31c..0000000000 --- a/awx/lib/site-packages/glanceclient/v1/client.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glanceclient.common import http -from glanceclient.common import utils -from glanceclient.v1.image_members import ImageMemberManager -from glanceclient.v1.images import ImageManager - - -class Client(object): - """Client for the OpenStack Images v1 API. - - :param string endpoint: A user-supplied endpoint URL for the glance - service. - :param string token: Token for authentication. - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - """ - - def __init__(self, endpoint, *args, **kwargs): - """Initialize a new client for the Images v1 API.""" - endpoint, version = utils.strip_version(endpoint) - self.version = version or 1.0 - self.http_client = http.HTTPClient(endpoint, *args, **kwargs) - self.images = ImageManager(self.http_client) - self.image_members = ImageMemberManager(self.http_client) diff --git a/awx/lib/site-packages/glanceclient/v1/image_members.py b/awx/lib/site-packages/glanceclient/v1/image_members.py deleted file mode 100644 index d940a5f854..0000000000 --- a/awx/lib/site-packages/glanceclient/v1/image_members.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glanceclient.openstack.common.apiclient import base - - -class ImageMember(base.Resource): - def __repr__(self): - return "<ImageMember %s>" % self._info - - @property - def id(self): - return self.member_id - - def delete(self): - self.manager.delete(self) - - -class ImageMemberManager(base.ManagerWithFind): - resource_class = ImageMember - - def get(self, image, member_id): - image_id = base.getid(image) - url = '/v1/images/%s/members/%s' % (image_id, member_id) - resp, body = self.client.get(url) - member = body['member'] - member['image_id'] = image_id - return ImageMember(self, member, loaded=True) - - def list(self, image=None, member=None): - out = [] - if image and member: - try: - out.append(self.get(image, member)) - #TODO(bcwaldon): narrow this down to 404 - except Exception: - pass - elif image: - out.extend(self._list_by_image(image)) - elif member: - out.extend(self._list_by_member(member)) - else: - #TODO(bcwaldon): figure out what is appropriate to do here as we - # are unable to provide the requested response - pass - return out - - def _list_by_image(self, image): - image_id = base.getid(image) - url = '/v1/images/%s/members' % image_id - resp, body = self.client.get(url) - out = [] - for member in body['members']: - member['image_id'] = image_id - out.append(ImageMember(self, member, loaded=True)) - return out - - def _list_by_member(self, member): - member_id = base.getid(member) - url = '/v1/shared-images/%s' % member_id - resp, body = self.client.get(url) - out = [] - for member in body['shared_images']: - member['member_id'] = member_id - out.append(ImageMember(self, member, loaded=True)) - return out - - def delete(self, image_id, member_id): - self._delete("/v1/images/%s/members/%s" % (image_id, member_id)) - - def create(self, image, member_id, can_share=False): - """Creates an image.""" - url = '/v1/images/%s/members/%s' % (base.getid(image), member_id) - body = {'member': {'can_share': can_share}} - self.client.put(url, data=body) - - def replace(self, image, members): - memberships = [] - for member in members: - try: - obj = { - 'member_id': member.member_id, - 'can_share': member.can_share, - } - except AttributeError: - obj = {'member_id': member['member_id']} - if 'can_share' in member: - obj['can_share'] = member['can_share'] - memberships.append(obj) - url = '/v1/images/%s/members' % base.getid(image) - self.client.put(url, data={'memberships': memberships}) diff --git a/awx/lib/site-packages/glanceclient/v1/images.py b/awx/lib/site-packages/glanceclient/v1/images.py deleted file mode 100644 index 11a56ba9c7..0000000000 --- a/awx/lib/site-packages/glanceclient/v1/images.py +++ /dev/null @@ -1,365 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -from oslo_utils import encodeutils -from oslo_utils import strutils -import six -import six.moves.urllib.parse as urlparse - -from glanceclient.common import utils -from glanceclient.openstack.common.apiclient import base - -UPDATE_PARAMS = ('name', 'disk_format', 'container_format', 'min_disk', - 'min_ram', 'owner', 'size', 'is_public', 'protected', - 'location', 'checksum', 'copy_from', 'properties', - #NOTE(bcwaldon: an attempt to update 'deleted' will be - # ignored, but we need to support it for backwards- - # compatibility with the legacy client library - 'deleted') - -CREATE_PARAMS = UPDATE_PARAMS + ('id', 'store') - -DEFAULT_PAGE_SIZE = 20 - -SORT_DIR_VALUES = ('asc', 'desc') -SORT_KEY_VALUES = ('name', 'status', 'container_format', 'disk_format', - 'size', 'id', 'created_at', 'updated_at') - -OS_REQ_ID_HDR = 'x-openstack-request-id' - - -class Image(base.Resource): - def __repr__(self): - return "<Image %s>" % self._info - - def update(self, **fields): - self.manager.update(self, **fields) - - def delete(self, **kwargs): - return self.manager.delete(self) - - def data(self, **kwargs): - return self.manager.data(self, **kwargs) - - -class ImageManager(base.ManagerWithFind): - resource_class = Image - - def _list(self, url, response_key, obj_class=None, body=None): - resp, body = self.client.get(url) - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] - return ([obj_class(self, res, loaded=True) for res in data if res], - resp) - - def _image_meta_from_headers(self, headers): - meta = {'properties': {}} - safe_decode = encodeutils.safe_decode - for key, value in six.iteritems(headers): - value = safe_decode(value, incoming='utf-8') - if key.startswith('x-image-meta-property-'): - _key = safe_decode(key[22:], incoming='utf-8') - meta['properties'][_key] = value - elif key.startswith('x-image-meta-'): - _key = safe_decode(key[13:], incoming='utf-8') - meta[_key] = value - - for key in ['is_public', 'protected', 'deleted']: - if key in meta: - meta[key] = strutils.bool_from_string(meta[key]) - - return self._format_image_meta_for_user(meta) - - def _image_meta_to_headers(self, fields): - headers = {} - fields_copy = copy.deepcopy(fields) - - # NOTE(flaper87): Convert to str, headers - # that are not instance of basestring. All - # headers will be encoded later, before the - # request is sent. - def to_str(value): - if not isinstance(value, six.string_types): - return str(value) - return value - - for key, value in six.iteritems(fields_copy.pop('properties', {})): - headers['x-image-meta-property-%s' % key] = to_str(value) - for key, value in six.iteritems(fields_copy): - headers['x-image-meta-%s' % key] = to_str(value) - return headers - - @staticmethod - def _format_image_meta_for_user(meta): - for key in ['size', 'min_ram', 'min_disk']: - if key in meta: - try: - meta[key] = int(meta[key]) if meta[key] else 0 - except ValueError: - pass - return meta - - def get(self, image, **kwargs): - """Get the metadata for a specific image. - - :param image: image object or id to look up - :rtype: :class:`Image` - """ - image_id = base.getid(image) - resp, body = self.client.head('/v1/images/%s' - % urlparse.quote(str(image_id))) - meta = self._image_meta_from_headers(resp.headers) - return_request_id = kwargs.get('return_req_id', None) - if return_request_id is not None: - return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) - return Image(self, meta) - - def data(self, image, do_checksum=True, **kwargs): - """Get the raw data for a specific image. - - :param image: image object or id to look up - :param do_checksum: Enable/disable checksum validation - :rtype: iterable containing image data - """ - image_id = base.getid(image) - resp, body = self.client.get('/v1/images/%s' - % urlparse.quote(str(image_id))) - content_length = int(resp.headers.get('content-length', 0)) - checksum = resp.headers.get('x-image-meta-checksum', None) - if do_checksum and checksum is not None: - body = utils.integrity_iter(body, checksum) - return_request_id = kwargs.get('return_req_id', None) - if return_request_id is not None: - return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) - - return utils.IterableWithLength(body, content_length) - - def _build_params(self, parameters): - params = {'limit': parameters.get('page_size', DEFAULT_PAGE_SIZE)} - - if 'marker' in parameters: - params['marker'] = parameters['marker'] - - sort_key = parameters.get('sort_key') - if sort_key is not None: - if sort_key in SORT_KEY_VALUES: - params['sort_key'] = sort_key - else: - raise ValueError('sort_key must be one of the following: %s.' - % ', '.join(SORT_KEY_VALUES)) - - sort_dir = parameters.get('sort_dir') - if sort_dir is not None: - if sort_dir in SORT_DIR_VALUES: - params['sort_dir'] = sort_dir - else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(SORT_DIR_VALUES)) - - filters = parameters.get('filters', {}) - properties = filters.pop('properties', {}) - for key, value in properties.items(): - params['property-%s' % key] = value - params.update(filters) - if parameters.get('owner') is not None: - params['is_public'] = None - if 'is_public' in parameters: - params['is_public'] = parameters['is_public'] - - return params - - def list(self, **kwargs): - """Get a list of images. - - :param page_size: number of items to request in each paginated request - :param limit: maximum number of images to return - :param marker: begin returning images that appear later in the image - list than that represented by this image id - :param filters: dict of direct comparison filters that mimics the - structure of an image object - :param owner: If provided, only images with this owner (tenant id) - will be listed. An empty string ('') matches ownerless - images. - :param return_request_id: If an empty list is provided, populate this - list with the request ID value from the header - x-openstack-request-id - :rtype: list of :class:`Image` - """ - absolute_limit = kwargs.get('limit') - page_size = kwargs.get('page_size', DEFAULT_PAGE_SIZE) - owner = kwargs.get('owner', None) - - def filter_owner(owner, image): - # If client side owner 'filter' is specified - # only return images that match 'owner'. - if owner is None: - # Do not filter based on owner - return False - if (not hasattr(image, 'owner')) or image.owner is None: - # ownerless image - return not (owner == '') - else: - return not (image.owner == owner) - - def paginate(qp, return_request_id=None): - for param, value in six.iteritems(qp): - if isinstance(value, six.string_types): - # Note(flaper87) Url encoding should - # be moved inside http utils, at least - # shouldn't be here. - # - # Making sure all params are str before - # trying to encode them - qp[param] = encodeutils.safe_decode(value) - - url = '/v1/images/detail?%s' % urlparse.urlencode(qp) - images, resp = self._list(url, "images") - - if return_request_id is not None: - return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) - - for image in images: - yield image - - return_request_id = kwargs.get('return_req_id', None) - - params = self._build_params(kwargs) - - seen = 0 - while True: - seen_last_page = 0 - filtered = 0 - for image in paginate(params, return_request_id): - last_image = image.id - - if filter_owner(owner, image): - # Note(kragniz): ignore this image - filtered += 1 - continue - - if (absolute_limit is not None and - seen + seen_last_page >= absolute_limit): - # Note(kragniz): we've seen enough images - return - else: - seen_last_page += 1 - yield image - - seen += seen_last_page - - if seen_last_page + filtered == 0: - # Note(kragniz): we didn't get any images in the last page - return - - if absolute_limit is not None and seen >= absolute_limit: - # Note(kragniz): reached the limit of images to return - return - - if page_size and seen_last_page + filtered < page_size: - # Note(kragniz): we've reached the last page of the images - return - - # Note(kragniz): there are more images to come - params['marker'] = last_image - seen_last_page = 0 - - def delete(self, image, **kwargs): - """Delete an image.""" - url = "/v1/images/%s" % base.getid(image) - resp, body = self.client.delete(url) - return_request_id = kwargs.get('return_req_id', None) - if return_request_id is not None: - return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) - - def create(self, **kwargs): - """Create an image - - TODO(bcwaldon): document accepted params - """ - image_data = kwargs.pop('data', None) - if image_data is not None: - image_size = utils.get_file_size(image_data) - if image_size is not None: - kwargs.setdefault('size', image_size) - - fields = {} - for field in kwargs: - if field in CREATE_PARAMS: - fields[field] = kwargs[field] - elif field == 'return_req_id': - continue - else: - msg = 'create() got an unexpected keyword argument \'%s\'' - raise TypeError(msg % field) - - copy_from = fields.pop('copy_from', None) - hdrs = self._image_meta_to_headers(fields) - if copy_from is not None: - hdrs['x-glance-api-copy-from'] = copy_from - - resp, body = self.client.post('/v1/images', - headers=hdrs, - data=image_data) - return_request_id = kwargs.get('return_req_id', None) - if return_request_id is not None: - return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) - - return Image(self, self._format_image_meta_for_user(body['image'])) - - def update(self, image, **kwargs): - """Update an image - - TODO(bcwaldon): document accepted params - """ - image_data = kwargs.pop('data', None) - if image_data is not None: - image_size = utils.get_file_size(image_data) - if image_size is not None: - kwargs.setdefault('size', image_size) - - hdrs = {} - purge_props = 'false' - purge_props_bool = kwargs.pop('purge_props', None) - if purge_props_bool: - purge_props = 'true' - - hdrs['x-glance-registry-purge-props'] = purge_props - fields = {} - for field in kwargs: - if field in UPDATE_PARAMS: - fields[field] = kwargs[field] - elif field == 'return_req_id': - continue - else: - msg = 'update() got an unexpected keyword argument \'%s\'' - raise TypeError(msg % field) - - copy_from = fields.pop('copy_from', None) - hdrs.update(self._image_meta_to_headers(fields)) - if copy_from is not None: - hdrs['x-glance-api-copy-from'] = copy_from - - url = '/v1/images/%s' % base.getid(image) - resp, body = self.client.put(url, headers=hdrs, data=image_data) - return_request_id = kwargs.get('return_req_id', None) - if return_request_id is not None: - return_request_id.append(resp.headers.get(OS_REQ_ID_HDR, None)) - - return Image(self, self._format_image_meta_for_user(body['image'])) diff --git a/awx/lib/site-packages/glanceclient/v1/shell.py b/awx/lib/site-packages/glanceclient/v1/shell.py deleted file mode 100644 index bc689da02c..0000000000 --- a/awx/lib/site-packages/glanceclient/v1/shell.py +++ /dev/null @@ -1,414 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import copy -import functools -import os -import six -import sys - -from oslo_utils import encodeutils -from oslo_utils import strutils - -from glanceclient.common import progressbar -from glanceclient.common import utils -from glanceclient import exc -import glanceclient.v1.images - -CONTAINER_FORMATS = 'Acceptable formats: ami, ari, aki, bare, and ovf.' -DISK_FORMATS = ('Acceptable formats: ami, ari, aki, vhd, vmdk, raw, ' - 'qcow2, vdi, and iso.') - -_bool_strict = functools.partial(strutils.bool_from_string, strict=True) - - -@utils.arg('--name', metavar='<NAME>', - help='Filter images to those that have this name.') -@utils.arg('--status', metavar='<STATUS>', - help='Filter images to those that have this status.') -@utils.arg('--container-format', metavar='<CONTAINER_FORMAT>', - help='Filter images to those that have this container format. ' - + CONTAINER_FORMATS) -@utils.arg('--disk-format', metavar='<DISK_FORMAT>', - help='Filter images to those that have this disk format. ' - + DISK_FORMATS) -@utils.arg('--size-min', metavar='<SIZE>', type=int, - help='Filter images to those with a size greater than this.') -@utils.arg('--size-max', metavar='<SIZE>', type=int, - help='Filter images to those with a size less than this.') -@utils.arg('--property-filter', metavar='<KEY=VALUE>', - help="Filter images by a user-defined image property.", - action='append', dest='properties', default=[]) -@utils.arg('--page-size', metavar='<SIZE>', default=None, type=int, - help='Number of images to request in each paginated request.') -@utils.arg('--human-readable', action='store_true', default=False, - help='Print image size in a human-friendly format.') -@utils.arg('--sort-key', default='name', - choices=glanceclient.v1.images.SORT_KEY_VALUES, - help='Sort image list by specified field.') -@utils.arg('--sort-dir', default='asc', - choices=glanceclient.v1.images.SORT_DIR_VALUES, - help='Sort image list in specified direction.') -@utils.arg('--is-public', - type=_bool_strict, metavar='{True,False}', - help=('Allows the user to select a listing of public or non ' - 'public images.')) -@utils.arg('--owner', default=None, metavar='<TENANT_ID>', - help='Display only images owned by this tenant id. Filtering ' - 'occurs on the client side so may be inefficient. This option ' - 'is mainly intended for admin use. Use an empty string (\'\') ' - 'to list images with no owner. Note: This option overrides ' - 'the --is-public argument if present. Note: the v2 API ' - 'supports more efficient server-side owner based filtering.') -@utils.arg('--all-tenants', action='store_true', default=False, - help=('Allows the admin user to list all images ' - 'irrespective of the image\'s owner or is_public value.')) -def do_image_list(gc, args): - """List images you can access.""" - filter_keys = ['name', 'status', 'container_format', 'disk_format', - 'size_min', 'size_max', 'is_public'] - filter_items = [(key, getattr(args, key)) for key in filter_keys] - filters = dict([item for item in filter_items if item[1] is not None]) - - if args.properties: - property_filter_items = [p.split('=', 1) for p in args.properties] - if any(len(pair) != 2 for pair in property_filter_items): - utils.exit('Argument --property-filter requires properties in the' - ' format KEY=VALUE') - - filters['properties'] = dict(property_filter_items) - - kwargs = {'filters': filters} - if args.page_size is not None: - kwargs['page_size'] = args.page_size - - kwargs['sort_key'] = args.sort_key - kwargs['sort_dir'] = args.sort_dir - kwargs['owner'] = args.owner - if args.all_tenants is True: - kwargs['is_public'] = None - - images = gc.images.list(**kwargs) - - if args.human_readable: - def convert_size(image): - image.size = utils.make_size_human_readable(image.size) - return image - - images = (convert_size(image) for image in images) - - columns = ['ID', 'Name', 'Disk Format', 'Container Format', - 'Size', 'Status'] - utils.print_list(images, columns) - - -def _image_show(image, human_readable=False, max_column_width=80): - # Flatten image properties dict for display - info = copy.deepcopy(image._info) - if human_readable: - info['size'] = utils.make_size_human_readable(info['size']) - for (k, v) in six.iteritems(info.pop('properties')): - info['Property \'%s\'' % k] = v - - utils.print_dict(info, max_column_width=max_column_width) - - -def _set_data_field(fields, args): - if 'location' not in fields and 'copy_from' not in fields: - fields['data'] = utils.get_data_file(args) - - -@utils.arg('image', metavar='<IMAGE>', help='Name or ID of image to describe.') -@utils.arg('--human-readable', action='store_true', default=False, - help='Print image size in a human-friendly format.') -@utils.arg('--max-column-width', metavar='<integer>', default=80, - help='The max column width of the printed table.') -def do_image_show(gc, args): - """Describe a specific image.""" - image_id = utils.find_resource(gc.images, args.image).id - image = gc.images.get(image_id) - _image_show(image, args.human_readable, - max_column_width=int(args.max_column_width)) - - -@utils.arg('--file', metavar='<FILE>', - help='Local file to save downloaded image data to. ' - 'If this is not specified the image data will be ' - 'written to stdout.') -@utils.arg('image', metavar='<IMAGE>', help='Name or ID of image to download.') -@utils.arg('--progress', action='store_true', default=False, - help='Show download progress bar.') -def do_image_download(gc, args): - """Download a specific image.""" - image = utils.find_resource(gc.images, args.image) - body = image.data() - if args.progress: - body = progressbar.VerboseIteratorWrapper(body, len(body)) - utils.save_image(body, args.file) - - -@utils.arg('--id', metavar='<IMAGE_ID>', - help='ID of image to reserve.') -@utils.arg('--name', metavar='<NAME>', - help='Name of image.') -@utils.arg('--store', metavar='<STORE>', - help='Store to upload image to.') -@utils.arg('--disk-format', metavar='<DISK_FORMAT>', - help='Disk format of image. ' + DISK_FORMATS) -@utils.arg('--container-format', metavar='<CONTAINER_FORMAT>', - help='Container format of image. ' + CONTAINER_FORMATS) -@utils.arg('--owner', metavar='<TENANT_ID>', - help='Tenant who should own image.') -@utils.arg('--size', metavar='<SIZE>', type=int, - help=('Size of image data (in bytes). Only used with' - ' \'--location\' and \'--copy_from\'.')) -@utils.arg('--min-disk', metavar='<DISK_GB>', type=int, - help='Minimum size of disk needed to boot image (in gigabytes).') -@utils.arg('--min-ram', metavar='<DISK_RAM>', type=int, - help='Minimum amount of ram needed to boot image (in megabytes).') -@utils.arg('--location', metavar='<IMAGE_URL>', - help=('URL where the data for this image already resides. For ' - 'example, if the image data is stored in swift, you could ' - 'specify \'swift+http://tenant%%3Aaccount:key@auth_url/' - 'v2.0/container/obj\'. ' - '(Note: \'%%3A\' is \':\' URL encoded.)')) -@utils.arg('--file', metavar='<FILE>', - help=('Local file that contains disk image to be uploaded during' - ' creation. Alternatively, images can be passed to the client' - ' via stdin.')) -@utils.arg('--checksum', metavar='<CHECKSUM>', - help=('Hash of image data used Glance can use for verification.' - ' Provide a md5 checksum here.')) -@utils.arg('--copy-from', metavar='<IMAGE_URL>', - help=('Similar to \'--location\' in usage, but this indicates that' - ' the Glance server should immediately copy the data and' - ' store it in its configured image store.')) -@utils.arg('--is-public', - type=_bool_strict, metavar='{True,False}', - help='Make image accessible to the public.') -@utils.arg('--is-protected', - type=_bool_strict, metavar='{True,False}', - help='Prevent image from being deleted.') -@utils.arg('--property', metavar="<key=value>", action='append', default=[], - help=("Arbitrary property to associate with image. " - "May be used multiple times.")) -@utils.arg('--human-readable', action='store_true', default=False, - help='Print image size in a human-friendly format.') -@utils.arg('--progress', action='store_true', default=False, - help='Show upload progress bar.') -def do_image_create(gc, args): - """Create a new image.""" - # Filter out None values - fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) - - fields['is_public'] = fields.get('is_public') - - if 'is_protected' in fields: - fields['protected'] = fields.pop('is_protected') - - raw_properties = fields.pop('property') - fields['properties'] = {} - for datum in raw_properties: - key, value = datum.split('=', 1) - fields['properties'][key] = value - - # Filter out values we can't use - CREATE_PARAMS = glanceclient.v1.images.CREATE_PARAMS - fields = dict(filter(lambda x: x[0] in CREATE_PARAMS, fields.items())) - - _set_data_field(fields, args) - - # Only show progress bar for local image files - if fields.get('data') and args.progress: - filesize = utils.get_file_size(fields['data']) - if filesize is not None: - # NOTE(kragniz): do not show a progress bar if the size of the - # input is unknown (most likely a piped input) - fields['data'] = progressbar.VerboseFileWrapper( - fields['data'], filesize - ) - - image = gc.images.create(**fields) - _image_show(image, args.human_readable) - - -def _is_image_data_provided(args): - """Return True if some image data has probably been provided by the user""" - # NOTE(kragniz): Check stdin works, then check is there is any data - # on stdin or a filename has been provided with --file - try: - os.fstat(0) - except OSError: - return False - return not sys.stdin.isatty() or args.file or args.copy_from - - -@utils.arg('image', metavar='<IMAGE>', help='Name or ID of image to modify.') -@utils.arg('--name', metavar='<NAME>', - help='Name of image.') -@utils.arg('--disk-format', metavar='<DISK_FORMAT>', - help='Disk format of image. ' + DISK_FORMATS) -@utils.arg('--container-format', metavar='<CONTAINER_FORMAT>', - help='Container format of image. ' + CONTAINER_FORMATS) -@utils.arg('--owner', metavar='<TENANT_ID>', - help='Tenant who should own image.') -@utils.arg('--size', metavar='<SIZE>', type=int, - help='Size of image data (in bytes).') -@utils.arg('--min-disk', metavar='<DISK_GB>', type=int, - help='Minimum size of disk needed to boot image (in gigabytes).') -@utils.arg('--min-ram', metavar='<DISK_RAM>', type=int, - help='Minimum amount of ram needed to boot image (in megabytes).') -@utils.arg('--location', metavar='<IMAGE_URL>', - help=('URL where the data for this image already resides. For ' - 'example, if the image data is stored in swift, you could ' - 'specify \'swift+http://tenant%%3Aaccount:key@auth_url/' - 'v2.0/container/obj\'. ' - '(Note: \'%%3A\' is \':\' URL encoded.)')) -@utils.arg('--file', metavar='<FILE>', - help=('Local file that contains disk image to be uploaded during' - ' update. Alternatively, images can be passed to the client' - ' via stdin.')) -@utils.arg('--checksum', metavar='<CHECKSUM>', - help='Hash of image data used Glance can use for verification.') -@utils.arg('--copy-from', metavar='<IMAGE_URL>', - help=('Similar to \'--location\' in usage, but this indicates that' - ' the Glance server should immediately copy the data and' - ' store it in its configured image store.')) -@utils.arg('--is-public', - type=_bool_strict, metavar='{True,False}', - help='Make image accessible to the public.') -@utils.arg('--is-protected', - type=_bool_strict, metavar='{True,False}', - help='Prevent image from being deleted.') -@utils.arg('--property', metavar="<key=value>", action='append', default=[], - help=("Arbitrary property to associate with image. " - "May be used multiple times.")) -@utils.arg('--purge-props', action='store_true', default=False, - help=("If this flag is present, delete all image properties " - "not explicitly set in the update request. Otherwise, " - "those properties not referenced are preserved.")) -@utils.arg('--human-readable', action='store_true', default=False, - help='Print image size in a human-friendly format.') -@utils.arg('--progress', action='store_true', default=False, - help='Show upload progress bar.') -def do_image_update(gc, args): - """Update a specific image.""" - # Filter out None values - fields = dict(filter(lambda x: x[1] is not None, vars(args).items())) - - image_arg = fields.pop('image') - image = utils.find_resource(gc.images, image_arg) - - if 'is_protected' in fields: - fields['protected'] = fields.pop('is_protected') - - raw_properties = fields.pop('property') - fields['properties'] = {} - for datum in raw_properties: - key, value = datum.split('=', 1) - fields['properties'][key] = value - - # Filter out values we can't use - UPDATE_PARAMS = glanceclient.v1.images.UPDATE_PARAMS - fields = dict(filter(lambda x: x[0] in UPDATE_PARAMS, fields.items())) - - if image.status == 'queued': - _set_data_field(fields, args) - - if args.progress: - filesize = utils.get_file_size(fields['data']) - fields['data'] = progressbar.VerboseFileWrapper( - fields['data'], filesize - ) - - elif _is_image_data_provided(args): - # NOTE(kragniz): Exit with an error if the status is not queued - # and image data was provided - utils.exit('Unable to upload image data to an image which ' - 'is %s.' % image.status) - - image = gc.images.update(image, purge_props=args.purge_props, **fields) - _image_show(image, args.human_readable) - - -@utils.arg('images', metavar='<IMAGE>', nargs='+', - help='Name or ID of image(s) to delete.') -def do_image_delete(gc, args): - """Delete specified image(s).""" - for args_image in args.images: - image = utils.find_resource(gc.images, args_image) - if image and image.status == "deleted": - msg = "No image with an ID of '%s' exists." % image.id - raise exc.CommandError(msg) - try: - if args.verbose: - print('Requesting image delete for %s ...' % - encodeutils.safe_decode(args_image), end=' ') - - gc.images.delete(image) - - if args.verbose: - print('[Done]') - - except exc.HTTPException as e: - if args.verbose: - print('[Fail]') - print('%s: Unable to delete image %s' % (e, args_image)) - - -@utils.arg('--image-id', metavar='<IMAGE_ID>', - help='Filter results by an image ID.') -@utils.arg('--tenant-id', metavar='<TENANT_ID>', - help='Filter results by a tenant ID.') -def do_member_list(gc, args): - """Describe sharing permissions by image or tenant.""" - if args.image_id and args.tenant_id: - utils.exit('Unable to filter members by both --image-id and' - ' --tenant-id.') - elif args.image_id: - kwargs = {'image': args.image_id} - elif args.tenant_id: - kwargs = {'member': args.tenant_id} - else: - utils.exit('Unable to list all members. Specify --image-id or' - ' --tenant-id') - - members = gc.image_members.list(**kwargs) - columns = ['Image ID', 'Member ID', 'Can Share'] - utils.print_list(members, columns) - - -@utils.arg('image', metavar='<IMAGE>', - help='Image to add member to.') -@utils.arg('tenant_id', metavar='<TENANT_ID>', - help='Tenant to add as member') -@utils.arg('--can-share', action='store_true', default=False, - help='Allow the specified tenant to share this image.') -def do_member_create(gc, args): - """Share a specific image with a tenant.""" - image = utils.find_resource(gc.images, args.image) - gc.image_members.create(image, args.tenant_id, args.can_share) - - -@utils.arg('image', metavar='<IMAGE>', - help='Image from which to remove member.') -@utils.arg('tenant_id', metavar='<TENANT_ID>', - help='Tenant to remove as member.') -def do_member_delete(gc, args): - """Remove a shared image from a tenant.""" - image_id = utils.find_resource(gc.images, args.image).id - gc.image_members.delete(image_id, args.tenant_id) diff --git a/awx/lib/site-packages/glanceclient/v2/__init__.py b/awx/lib/site-packages/glanceclient/v2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/glanceclient/v2/client.py b/awx/lib/site-packages/glanceclient/v2/client.py deleted file mode 100644 index 8d6f00abd3..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/client.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from glanceclient.common import http -from glanceclient.common import utils -from glanceclient.v2 import image_members -from glanceclient.v2 import image_tags -from glanceclient.v2 import images -from glanceclient.v2 import metadefs -from glanceclient.v2 import schemas -from glanceclient.v2 import tasks - - -class Client(object): - """Client for the OpenStack Images v2 API. - - :param string endpoint: A user-supplied endpoint URL for the glance - service. - :param string token: Token for authentication. - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - """ - - def __init__(self, endpoint, *args, **kwargs): - endpoint, version = utils.strip_version(endpoint) - self.version = version or 2.0 - self.http_client = http.HTTPClient(endpoint, *args, **kwargs) - - self.schemas = schemas.Controller(self.http_client) - - self.images = images.Controller(self.http_client, self.schemas) - self.image_tags = image_tags.Controller(self.http_client, - self.schemas) - self.image_members = image_members.Controller(self.http_client, - self.schemas) - - self.tasks = tasks.Controller(self.http_client, self.schemas) - - self.metadefs_resource_type = ( - metadefs.ResourceTypeController(self.http_client, self.schemas)) - - self.metadefs_property = ( - metadefs.PropertyController(self.http_client, self.schemas)) - - self.metadefs_object = ( - metadefs.ObjectController(self.http_client, self.schemas)) - - self.metadefs_namespace = ( - metadefs.NamespaceController(self.http_client, self.schemas)) diff --git a/awx/lib/site-packages/glanceclient/v2/image_members.py b/awx/lib/site-packages/glanceclient/v2/image_members.py deleted file mode 100644 index 5d07b9b5e8..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/image_members.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warlock - -from glanceclient.common import utils -from glanceclient.v2 import schemas - - -MEMBER_STATUS_VALUES = ('accepted', 'rejected', 'pending') - - -class Controller(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('member') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def list(self, image_id): - url = '/v2/images/%s/members' % image_id - resp, body = self.http_client.get(url) - for member in body['members']: - yield self.model(member) - - def delete(self, image_id, member_id): - self.http_client.delete('/v2/images/%s/members/%s' % - (image_id, member_id)) - - def update(self, image_id, member_id, member_status): - url = '/v2/images/%s/members/%s' % (image_id, member_id) - body = {'status': member_status} - resp, updated_member = self.http_client.put(url, data=body) - return self.model(updated_member) - - def create(self, image_id, member_id): - url = '/v2/images/%s/members' % image_id - body = {'member': member_id} - resp, created_member = self.http_client.post(url, data=body) - return self.model(created_member) diff --git a/awx/lib/site-packages/glanceclient/v2/image_tags.py b/awx/lib/site-packages/glanceclient/v2/image_tags.py deleted file mode 100644 index 0f2f1bb469..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/image_tags.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warlock - -from glanceclient.common import utils -from glanceclient.v2 import schemas - - -class Controller(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('image') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def update(self, image_id, tag_value): - """ - Update an image with the given tag. - - :param image_id: image to be updated with the given tag. - :param tag_value: value of the tag. - """ - url = '/v2/images/%s/tags/%s' % (image_id, tag_value) - self.http_client.put(url) - - def delete(self, image_id, tag_value): - """ - Delete the tag associated with the given image. - - :param image_id: Image whose tag to be deleted. - :param tag_value: tag value to be deleted. - """ - url = '/v2/images/%s/tags/%s' % (image_id, tag_value) - self.http_client.delete(url) diff --git a/awx/lib/site-packages/glanceclient/v2/images.py b/awx/lib/site-packages/glanceclient/v2/images.py deleted file mode 100644 index c9fb0a7cbf..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/images.py +++ /dev/null @@ -1,357 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json - -from oslo_utils import encodeutils -import six -from six.moves.urllib import parse -import warlock - -from glanceclient.common import utils -from glanceclient import exc -from glanceclient.v2 import schemas - -DEFAULT_PAGE_SIZE = 20 - -SORT_DIR_VALUES = ('asc', 'desc') -SORT_KEY_VALUES = ('name', 'status', 'container_format', 'disk_format', - 'size', 'id', 'created_at', 'updated_at') - - -class Controller(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('image') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - @staticmethod - def _wrap(value): - if isinstance(value, six.string_types): - return [value] - return value - - @staticmethod - def _validate_sort_param(sort): - """Validates sorting argument for invalid keys and directions values. - - :param sort: comma-separated list of sort keys with optional <:dir> - after each key - """ - for sort_param in sort.strip().split(','): - key, _sep, dir = sort_param.partition(':') - if dir and dir not in SORT_DIR_VALUES: - msg = ('Invalid sort direction: %(sort_dir)s.' - ' It must be one of the following: %(available)s.' - ) % {'sort_dir': dir, - 'available': ', '.join(SORT_DIR_VALUES)} - raise exc.HTTPBadRequest(msg) - if key not in SORT_KEY_VALUES: - msg = ('Invalid sort key: %(sort_key)s.' - ' It must be one of the following: %(available)s.' - ) % {'sort_key': key, - 'available': ', '.join(SORT_KEY_VALUES)} - raise exc.HTTPBadRequest(msg) - return sort - - def list(self, **kwargs): - """Retrieve a listing of Image objects - - :param page_size: Number of images to request in each paginated request - :returns generator over list of Images - """ - - ori_validate_fun = self.model.validate - empty_fun = lambda *args, **kwargs: None - - limit = kwargs.get('limit') - # NOTE(flaper87): Don't use `get('page_size', DEFAULT_SIZE)` otherwise, - # it could be possible to send invalid data to the server by passing - # page_size=None. - page_size = kwargs.get('page_size') or DEFAULT_PAGE_SIZE - - def paginate(url, page_size, limit=None): - next_url = url - - while True: - if limit and page_size > limit: - # NOTE(flaper87): Avoid requesting 2000 images when limit - # is 1 - next_url = next_url.replace("limit=%s" % page_size, - "limit=%s" % limit) - - resp, body = self.http_client.get(next_url) - for image in body['images']: - # NOTE(bcwaldon): remove 'self' for now until we have - # an elegant way to pass it into the model constructor - # without conflict. - image.pop('self', None) - yield self.model(**image) - # NOTE(zhiyan): In order to resolve the performance issue - # of JSON schema validation for image listing case, we - # don't validate each image entry but do it only on first - # image entry for each page. - self.model.validate = empty_fun - - if limit: - limit -= 1 - if limit <= 0: - raise StopIteration - - # NOTE(zhiyan); Reset validation function. - self.model.validate = ori_validate_fun - - try: - next_url = body['next'] - except KeyError: - return - - filters = kwargs.get('filters', {}) - # NOTE(flaper87): We paginate in the client, hence we use - # the page_size as Glance's limit. - filters['limit'] = page_size - - tags = filters.pop('tag', []) - tags_url_params = [] - - for tag in tags: - if isinstance(tag, six.string_types): - tags_url_params.append({'tag': encodeutils.safe_encode(tag)}) - - for param, value in six.iteritems(filters): - if isinstance(value, six.string_types): - filters[param] = encodeutils.safe_encode(value) - - url = '/v2/images?%s' % parse.urlencode(filters) - - for param in tags_url_params: - url = '%s&%s' % (url, parse.urlencode(param)) - - if 'sort' in kwargs: - if 'sort_key' in kwargs or 'sort_dir' in kwargs: - raise exc.HTTPBadRequest("The 'sort' argument is not supported" - " with 'sort_key' or 'sort_dir'.") - url = '%s&sort=%s' % (url, - self._validate_sort_param( - kwargs['sort'])) - else: - sort_dir = self._wrap(kwargs.get('sort_dir', [])) - sort_key = self._wrap(kwargs.get('sort_key', [])) - - if len(sort_key) != len(sort_dir) and len(sort_dir) > 1: - raise exc.HTTPBadRequest( - "Unexpected number of sort directions: " - "either provide a single sort direction or an equal " - "number of sort keys and sort directions.") - for key in sort_key: - url = '%s&sort_key=%s' % (url, key) - - for dir in sort_dir: - url = '%s&sort_dir=%s' % (url, dir) - - for image in paginate(url, page_size, limit): - yield image - - def get(self, image_id): - url = '/v2/images/%s' % image_id - resp, body = self.http_client.get(url) - #NOTE(bcwaldon): remove 'self' for now until we have an elegant - # way to pass it into the model constructor without conflict - body.pop('self', None) - return self.model(**body) - - def data(self, image_id, do_checksum=True): - """ - Retrieve data of an image. - - :param image_id: ID of the image to download. - :param do_checksum: Enable/disable checksum validation. - """ - url = '/v2/images/%s/file' % image_id - resp, body = self.http_client.get(url) - checksum = resp.headers.get('content-md5', None) - content_length = int(resp.headers.get('content-length', 0)) - - if do_checksum and checksum is not None: - body = utils.integrity_iter(body, checksum) - - return utils.IterableWithLength(body, content_length) - - def upload(self, image_id, image_data, image_size=None): - """ - Upload the data for an image. - - :param image_id: ID of the image to upload data for. - :param image_data: File-like object supplying the data to upload. - :param image_size: Total size in bytes of image to be uploaded. - """ - url = '/v2/images/%s/file' % image_id - hdrs = {'Content-Type': 'application/octet-stream'} - if image_size: - body = {'image_data': image_data, - 'image_size': image_size} - else: - body = image_data - self.http_client.put(url, headers=hdrs, data=body) - - def delete(self, image_id): - """Delete an image.""" - url = '/v2/images/%s' % image_id - self.http_client.delete(url) - - def create(self, **kwargs): - """Create an image.""" - url = '/v2/images' - - image = self.model() - for (key, value) in kwargs.items(): - try: - setattr(image, key, value) - except warlock.InvalidOperation as e: - raise TypeError(utils.exception_to_str(e)) - - resp, body = self.http_client.post(url, data=image) - #NOTE(esheffield): remove 'self' for now until we have an elegant - # way to pass it into the model constructor without conflict - body.pop('self', None) - return self.model(**body) - - def update(self, image_id, remove_props=None, **kwargs): - """ - Update attributes of an image. - - :param image_id: ID of the image to modify. - :param remove_props: List of property names to remove - :param **kwargs: Image attribute names and their new values. - """ - image = self.get(image_id) - for (key, value) in kwargs.items(): - try: - setattr(image, key, value) - except warlock.InvalidOperation as e: - raise TypeError(utils.exception_to_str(e)) - - if remove_props is not None: - cur_props = image.keys() - new_props = kwargs.keys() - #NOTE(esheffield): Only remove props that currently exist on the - # image and are NOT in the properties being updated / added - props_to_remove = set(cur_props).intersection( - set(remove_props).difference(new_props)) - - for key in props_to_remove: - delattr(image, key) - - url = '/v2/images/%s' % image_id - hdrs = {'Content-Type': 'application/openstack-images-v2.1-json-patch'} - self.http_client.patch(url, headers=hdrs, data=image.patch) - - #NOTE(bcwaldon): calling image.patch doesn't clear the changes, so - # we need to fetch the image again to get a clean history. This is - # an obvious optimization for warlock - return self.get(image_id) - - def _get_image_with_locations_or_fail(self, image_id): - image = self.get(image_id) - if getattr(image, 'locations', None) is None: - raise exc.HTTPBadRequest('The administrator has disabled ' - 'API access to image locations') - return image - - def _send_image_update_request(self, image_id, patch_body): - url = '/v2/images/%s' % image_id - hdrs = {'Content-Type': 'application/openstack-images-v2.1-json-patch'} - self.http_client.patch(url, headers=hdrs, data=json.dumps(patch_body)) - - def add_location(self, image_id, url, metadata): - """Add a new location entry to an image's list of locations. - - It is an error to add a URL that is already present in the list of - locations. - - :param image_id: ID of image to which the location is to be added. - :param url: URL of the location to add. - :param metadata: Metadata associated with the location. - :returns: The updated image - """ - image = self._get_image_with_locations_or_fail(image_id) - url_list = [l['url'] for l in image.locations] - if url in url_list: - err_str = 'A location entry at %s already exists' % url - raise exc.HTTPConflict(err_str) - - add_patch = [{'op': 'add', 'path': '/locations/-', - 'value': {'url': url, 'metadata': metadata}}] - self._send_image_update_request(image_id, add_patch) - return self.get(image_id) - - def delete_locations(self, image_id, url_set): - """Remove one or more location entries of an image. - - :param image_id: ID of image from which locations are to be removed. - :param url_set: set of URLs of location entries to remove. - :returns: None - """ - image = self._get_image_with_locations_or_fail(image_id) - current_urls = [l['url'] for l in image.locations] - - missing_locs = url_set.difference(set(current_urls)) - if missing_locs: - raise exc.HTTPNotFound('Unknown URL(s): %s' % list(missing_locs)) - - # NOTE: warlock doesn't generate the most efficient patch for remove - # operations (it shifts everything up and deletes the tail elements) so - # we do it ourselves. - url_indices = [current_urls.index(url) for url in url_set] - url_indices.sort(reverse=True) - patches = [{'op': 'remove', 'path': '/locations/%s' % url_idx} - for url_idx in url_indices] - self._send_image_update_request(image_id, patches) - - def update_location(self, image_id, url, metadata): - """Update an existing location entry in an image's list of locations. - - The URL specified must be already present in the image's list of - locations. - - :param image_id: ID of image whose location is to be updated. - :param url: URL of the location to update. - :param metadata: Metadata associated with the location. - :returns: The updated image - """ - image = self._get_image_with_locations_or_fail(image_id) - url_map = dict([(l['url'], l) for l in image.locations]) - if url not in url_map: - raise exc.HTTPNotFound('Unknown URL: %s' % url) - - if url_map[url]['metadata'] == metadata: - return image - - # NOTE: The server (as of now) doesn't support modifying individual - # location entries. So we must: - # 1. Empty existing list of locations. - # 2. Send another request to set 'locations' to the new list - # of locations. - url_map[url]['metadata'] = metadata - patches = [{'op': 'replace', - 'path': '/locations', - 'value': p} for p in ([], list(url_map.values()))] - self._send_image_update_request(image_id, patches) - - return self.get(image_id) diff --git a/awx/lib/site-packages/glanceclient/v2/metadefs.py b/awx/lib/site-packages/glanceclient/v2/metadefs.py deleted file mode 100644 index b6ba492f90..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/metadefs.py +++ /dev/null @@ -1,387 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils import encodeutils -import six -from six.moves.urllib import parse -import warlock - -from glanceclient.common import utils -from glanceclient.v2 import schemas - -DEFAULT_PAGE_SIZE = 20 -SORT_DIR_VALUES = ('asc', 'desc') -SORT_KEY_VALUES = ('created_at', 'namespace') - - -class NamespaceController(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('metadefs/namespace') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def create(self, **kwargs): - """Create a namespace. - - :param kwargs: Unpacked namespace object. - """ - url = '/v2/metadefs/namespaces' - try: - namespace = self.model(kwargs) - except (warlock.InvalidOperation, ValueError) as e: - raise TypeError(utils.exception_to_str(e)) - - resp, body = self.http_client.post(url, data=namespace) - body.pop('self', None) - return self.model(**body) - - def update(self, namespace_name, **kwargs): - """Update a namespace. - - :param namespace_name: Name of a namespace (old one). - :param kwargs: Unpacked namespace object. - """ - namespace = self.get(namespace_name) - for (key, value) in six.iteritems(kwargs): - try: - setattr(namespace, key, value) - except warlock.InvalidOperation as e: - raise TypeError(utils.exception_to_str(e)) - - # Remove read-only parameters. - read_only = ['schema', 'updated_at', 'created_at'] - for elem in read_only: - if elem in namespace: - del namespace[elem] - - url = '/v2/metadefs/namespaces/{0}'.format(namespace_name) - self.http_client.put(url, data=namespace) - - return self.get(namespace.namespace) - - def get(self, namespace, **kwargs): - """Get one namespace.""" - query_params = parse.urlencode(kwargs) - if kwargs: - query_params = '?%s' % query_params - - url = '/v2/metadefs/namespaces/{0}{1}'.format(namespace, query_params) - resp, body = self.http_client.get(url) - # NOTE(bcwaldon): remove 'self' for now until we have an elegant - # way to pass it into the model constructor without conflict - body.pop('self', None) - return self.model(**body) - - def list(self, **kwargs): - """Retrieve a listing of Namespace objects - :param page_size: Number of items to request in each paginated request - :param limit: Use to request a specific page size. Expect a response - to a limited request to return between zero and limit - items. - :param marker: Specifies the namespace of the last-seen namespace. - The typical pattern of limit and marker is to make an - initial limited request and then to use the last - namespace from the response as the marker parameter - in a subsequent limited request. - :param sort_key: The field to sort on (for example, 'created_at') - :param sort_dir: The direction to sort ('asc' or 'desc') - :returns generator over list of Namespaces - """ - - ori_validate_fun = self.model.validate - empty_fun = lambda *args, **kwargs: None - - def paginate(url): - resp, body = self.http_client.get(url) - for namespace in body['namespaces']: - # NOTE(bcwaldon): remove 'self' for now until we have - # an elegant way to pass it into the model constructor - # without conflict. - namespace.pop('self', None) - yield self.model(**namespace) - # NOTE(zhiyan): In order to resolve the performance issue - # of JSON schema validation for image listing case, we - # don't validate each image entry but do it only on first - # image entry for each page. - self.model.validate = empty_fun - - # NOTE(zhiyan); Reset validation function. - self.model.validate = ori_validate_fun - - try: - next_url = body['next'] - except KeyError: - return - else: - for namespace in paginate(next_url): - yield namespace - - filters = kwargs.get('filters', {}) - filters = {} if filters is None else filters - - if not kwargs.get('page_size'): - filters['limit'] = DEFAULT_PAGE_SIZE - else: - filters['limit'] = kwargs['page_size'] - - if 'marker' in kwargs: - filters['marker'] = kwargs['marker'] - - sort_key = kwargs.get('sort_key') - if sort_key is not None: - if sort_key in SORT_KEY_VALUES: - filters['sort_key'] = sort_key - else: - raise ValueError('sort_key must be one of the following: %s.' - % ', '.join(SORT_KEY_VALUES)) - - sort_dir = kwargs.get('sort_dir') - if sort_dir is not None: - if sort_dir in SORT_DIR_VALUES: - filters['sort_dir'] = sort_dir - else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(SORT_DIR_VALUES)) - - for param, value in six.iteritems(filters): - if isinstance(value, list): - filters[param] = encodeutils.safe_encode(','.join(value)) - elif isinstance(value, six.string_types): - filters[param] = encodeutils.safe_encode(value) - - url = '/v2/metadefs/namespaces?%s' % parse.urlencode(filters) - - for namespace in paginate(url): - yield namespace - - def delete(self, namespace): - """Delete a namespace.""" - url = '/v2/metadefs/namespaces/{0}'.format(namespace) - self.http_client.delete(url) - - -class ResourceTypeController(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('metadefs/resource_type') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def associate(self, namespace, **kwargs): - """Associate a resource type with a namespace.""" - try: - res_type = self.model(kwargs) - except (warlock.InvalidOperation, ValueError) as e: - raise TypeError(utils.exception_to_str(e)) - - url = '/v2/metadefs/namespaces/{0}/resource_types'.format(namespace, - res_type) - resp, body = self.http_client.post(url, data=res_type) - body.pop('self', None) - return self.model(**body) - - def deassociate(self, namespace, resource): - """Deasociate a resource type with a namespace.""" - url = '/v2/metadefs/namespaces/{0}/resource_types/{1}'. \ - format(namespace, resource) - self.http_client.delete(url) - - def list(self): - """Retrieve a listing of available resource types - - :returns generator over list of resource_types - """ - - url = '/v2/metadefs/resource_types' - resp, body = self.http_client.get(url) - for resource_type in body['resource_types']: - yield self.model(**resource_type) - - def get(self, namespace): - url = '/v2/metadefs/namespaces/{0}/resource_types'.format(namespace) - resp, body = self.http_client.get(url) - body.pop('self', None) - for resource_type in body['resource_type_associations']: - yield self.model(**resource_type) - - -class PropertyController(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('metadefs/property') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def create(self, namespace, **kwargs): - """Create a property. - - :param namespace: Name of a namespace the property will belong. - :param kwargs: Unpacked property object. - """ - try: - prop = self.model(kwargs) - except (warlock.InvalidOperation, ValueError) as e: - raise TypeError(utils.exception_to_str(e)) - - url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace) - - resp, body = self.http_client.post(url, data=prop) - body.pop('self', None) - return self.model(**body) - - def update(self, namespace, prop_name, **kwargs): - """Update a property. - - :param namespace: Name of a namespace the property belongs. - :param prop_name: Name of a property (old one). - :param kwargs: Unpacked property object. - """ - prop = self.get(namespace, prop_name) - for (key, value) in kwargs.items(): - try: - setattr(prop, key, value) - except warlock.InvalidOperation as e: - raise TypeError(utils.exception_to_str(e)) - - url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace, - prop_name) - self.http_client.put(url, data=prop) - - return self.get(namespace, prop.name) - - def get(self, namespace, prop_name): - url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace, - prop_name) - resp, body = self.http_client.get(url) - body.pop('self', None) - body['name'] = prop_name - return self.model(**body) - - def list(self, namespace, **kwargs): - """Retrieve a listing of metadata properties - - :returns generator over list of objects - """ - url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace) - - resp, body = self.http_client.get(url) - - for key, value in body['properties'].items(): - value['name'] = key - yield self.model(value) - - def delete(self, namespace, prop_name): - """Delete a property.""" - url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace, - prop_name) - self.http_client.delete(url) - - def delete_all(self, namespace): - """Delete all properties in a namespace.""" - url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace) - self.http_client.delete(url) - - -class ObjectController(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('metadefs/object') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def create(self, namespace, **kwargs): - """Create an object. - - :param namespace: Name of a namespace the object belongs. - :param kwargs: Unpacked object. - """ - try: - obj = self.model(kwargs) - except (warlock.InvalidOperation, ValueError) as e: - raise TypeError(utils.exception_to_str(e)) - - url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace) - - resp, body = self.http_client.post(url, data=obj) - body.pop('self', None) - return self.model(**body) - - def update(self, namespace, object_name, **kwargs): - """Update an object. - - :param namespace: Name of a namespace the object belongs. - :param prop_name: Name of an object (old one). - :param kwargs: Unpacked object. - """ - obj = self.get(namespace, object_name) - for (key, value) in kwargs.items(): - try: - setattr(obj, key, value) - except warlock.InvalidOperation as e: - raise TypeError(utils.exception_to_str(e)) - - # Remove read-only parameters. - read_only = ['schema', 'updated_at', 'created_at'] - for elem in read_only: - if elem in namespace: - del namespace[elem] - - url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace, - object_name) - self.http_client.put(url, data=obj) - - return self.get(namespace, obj.name) - - def get(self, namespace, object_name): - url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace, - object_name) - resp, body = self.http_client.get(url) - body.pop('self', None) - return self.model(**body) - - def list(self, namespace, **kwargs): - """Retrieve a listing of metadata objects - - :returns generator over list of objects - """ - url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace,) - resp, body = self.http_client.get(url) - - for obj in body['objects']: - yield self.model(obj) - - def delete(self, namespace, object_name): - """Delete an object.""" - url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace, - object_name) - self.http_client.delete(url) - - def delete_all(self, namespace): - """Delete all objects in a namespace.""" - url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace) - self.http_client.delete(url) diff --git a/awx/lib/site-packages/glanceclient/v2/schemas.py b/awx/lib/site-packages/glanceclient/v2/schemas.py deleted file mode 100644 index 5c31741e88..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/schemas.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import json -import jsonpatch -import six -import warlock.model as warlock - - -class SchemaBasedModel(warlock.Model): - """Glance specific subclass of the warlock Model - - This implementation alters the function of the patch property - to take into account the schema's core properties. With this version - undefined properties which are core will generated 'replace' - operations rather than 'add' since this is what the Glance API - expects. - """ - - def _make_custom_patch(self, new, original): - if not self.get('tags'): - tags_patch = [] - else: - tags_patch = [{"path": "/tags", - "value": self.get('tags'), - "op": "replace"}] - - patch_string = jsonpatch.make_patch(original, new).to_string() - patch = json.loads(patch_string) - if not patch: - return json.dumps(tags_patch) - else: - return json.dumps(patch + tags_patch) - - @warlock.Model.patch.getter - def patch(self): - """Return a jsonpatch object representing the delta.""" - original = copy.deepcopy(self.__dict__['__original__']) - new = dict(self) - if self.schema: - for (name, prop) in six.iteritems(self.schema['properties']): - if (name not in original and name in new and - prop.get('is_base', True)): - original[name] = None - - original['tags'] = None - new['tags'] = None - return self._make_custom_patch(new, original) - - -class SchemaProperty(object): - def __init__(self, name, **kwargs): - self.name = name - self.description = kwargs.get('description') - - -def translate_schema_properties(schema_properties): - """Parse the properties dictionary of a schema document - - :returns list of SchemaProperty objects - """ - properties = [] - for (name, prop) in schema_properties.items(): - properties.append(SchemaProperty(name, **prop)) - return properties - - -class Schema(object): - def __init__(self, raw_schema): - self._raw_schema = raw_schema - self.name = raw_schema['name'] - raw_properties = raw_schema['properties'] - self.properties = translate_schema_properties(raw_properties) - - def is_core_property(self, property_name): - for prop in self.properties: - if property_name == prop.name: - return True - return False - - def raw(self): - return copy.deepcopy(self._raw_schema) - - -class Controller(object): - def __init__(self, http_client): - self.http_client = http_client - - def get(self, schema_name): - uri = '/v2/schemas/%s' % schema_name - _, raw_schema = self.http_client.get(uri) - return Schema(raw_schema) diff --git a/awx/lib/site-packages/glanceclient/v2/shell.py b/awx/lib/site-packages/glanceclient/v2/shell.py deleted file mode 100644 index 31d02532d4..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/shell.py +++ /dev/null @@ -1,822 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from glanceclient.common import progressbar -from glanceclient.common import utils -from glanceclient import exc -from glanceclient.v2.image_members import MEMBER_STATUS_VALUES -from glanceclient.v2 import images -from glanceclient.v2 import tasks -import json -import os -from os.path import expanduser - -IMAGE_SCHEMA = None - - -def get_image_schema(): - global IMAGE_SCHEMA - if IMAGE_SCHEMA is None: - schema_path = expanduser("~/.glanceclient/image_schema.json") - if os.path.isfile(schema_path): - with open(schema_path, "r") as f: - schema_raw = f.read() - IMAGE_SCHEMA = json.loads(schema_raw) - return IMAGE_SCHEMA - - -@utils.schema_args(get_image_schema, omit=['created_at', 'updated_at', 'file', - 'checksum', 'virtual_size', 'size', - 'status', 'schema', 'direct_url']) -@utils.arg('--property', metavar="<key=value>", action='append', - default=[], help=('Arbitrary property to associate with image.' - ' May be used multiple times.')) -@utils.arg('--file', metavar='<FILE>', - help='Local file that contains disk image to be uploaded ' - 'during creation. Alternatively, images can be passed ' - 'to the client via stdin.') -@utils.arg('--progress', action='store_true', default=False, - help='Show upload progress bar.') -def do_image_create(gc, args): - """Create a new image.""" - schema = gc.schemas.get("image") - _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()] - fields = dict(filter(lambda x: x[1] is not None and - (x[0] == 'property' or - schema.is_core_property(x[0])), - _args)) - - raw_properties = fields.pop('property', []) - for datum in raw_properties: - key, value = datum.split('=', 1) - fields[key] = value - - file_name = fields.pop('file', None) - if file_name is not None and os.access(file_name, os.R_OK) is False: - utils.exit("File %s does not exist or user does not have read " - "privileges to it" % file_name) - image = gc.images.create(**fields) - try: - if utils.get_data_file(args) is not None: - args.id = image['id'] - args.size = None - do_image_upload(gc, args) - image = gc.images.get(args.id) - finally: - utils.print_image(image) - - -@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to update.') -@utils.schema_args(get_image_schema, omit=['id', 'locations', 'created_at', - 'updated_at', 'file', 'checksum', - 'virtual_size', 'size', 'status', - 'schema', 'direct_url', 'tags']) -@utils.arg('--property', metavar="<key=value>", action='append', - default=[], help=('Arbitrary property to associate with image.' - ' May be used multiple times.')) -@utils.arg('--remove-property', metavar="key", action='append', default=[], - help="Name of arbitrary property to remove from the image.") -def do_image_update(gc, args): - """Update an existing image.""" - schema = gc.schemas.get("image") - _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()] - fields = dict(filter(lambda x: x[1] is not None and - (x[0] in ['property', 'remove_property'] or - schema.is_core_property(x[0])), - _args)) - - raw_properties = fields.pop('property', []) - for datum in raw_properties: - key, value = datum.split('=', 1) - fields[key] = value - - remove_properties = fields.pop('remove_property', None) - - image_id = fields.pop('id') - image = gc.images.update(image_id, remove_properties, **fields) - utils.print_image(image) - - -@utils.arg('--limit', metavar='<LIMIT>', default=None, type=int, - help='Maximum number of images to get.') -@utils.arg('--page-size', metavar='<SIZE>', default=None, type=int, - help='Number of images to request in each paginated request.') -@utils.arg('--visibility', metavar='<VISIBILITY>', - help='The visibility of the images to display.') -@utils.arg('--member-status', metavar='<MEMBER_STATUS>', - help='The status of images to display.') -@utils.arg('--owner', metavar='<OWNER>', - help='Display images owned by <OWNER>.') -@utils.arg('--property-filter', metavar='<KEY=VALUE>', - help="Filter images by a user-defined image property.", - action='append', dest='properties', default=[]) -@utils.arg('--checksum', metavar='<CHECKSUM>', - help='Displays images that match the checksum.') -@utils.arg('--tag', metavar='<TAG>', action='append', - help="Filter images by a user-defined tag.") -@utils.arg('--sort-key', default=[], action='append', - choices=images.SORT_KEY_VALUES, - help='Sort image list by specified fields.') -@utils.arg('--sort-dir', default=[], action='append', - choices=images.SORT_DIR_VALUES, - help='Sort image list in specified directions.') -@utils.arg('--sort', metavar='<key>[:<direction>]', default=None, - help=(("Comma-separated list of sort keys and directions in the " - "form of <key>[:<asc|desc>]. Valid keys: %s. OPTIONAL: " - "Default='name:asc'.") % ', '.join(images.SORT_KEY_VALUES))) -def do_image_list(gc, args): - """List images you can access.""" - filter_keys = ['visibility', 'member_status', 'owner', 'checksum', 'tag'] - filter_items = [(key, getattr(args, key)) for key in filter_keys] - if args.properties: - filter_properties = [prop.split('=', 1) for prop in args.properties] - if False in (len(pair) == 2 for pair in filter_properties): - utils.exit('Argument --property-filter expected properties in the' - ' format KEY=VALUE') - filter_items += filter_properties - filters = dict([item for item in filter_items if item[1] is not None]) - - kwargs = {'filters': filters} - if args.limit is not None: - kwargs['limit'] = args.limit - if args.page_size is not None: - kwargs['page_size'] = args.page_size - - if args.sort_key: - kwargs['sort_key'] = args.sort_key - if args.sort_dir: - kwargs['sort_dir'] = args.sort_dir - if args.sort is not None: - kwargs['sort'] = args.sort - elif not args.sort_dir and not args.sort_key: - kwargs['sort'] = 'name:asc' - - images = gc.images.list(**kwargs) - columns = ['ID', 'Name'] - utils.print_list(images, columns) - - -@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to describe.') -@utils.arg('--max-column-width', metavar='<integer>', default=80, - help='The max column width of the printed table.') -def do_image_show(gc, args): - """Describe a specific image.""" - image = gc.images.get(args.id) - utils.print_image(image, int(args.max_column_width)) - - -@utils.arg('--image-id', metavar='<IMAGE_ID>', required=True, - help='Image to display members of.') -def do_member_list(gc, args): - """Describe sharing permissions by image.""" - - members = gc.image_members.list(args.image_id) - columns = ['Image ID', 'Member ID', 'Status'] - utils.print_list(members, columns) - - -@utils.arg('image_id', metavar='<IMAGE_ID>', - help='Image from which to remove member.') -@utils.arg('member_id', metavar='<MEMBER_ID>', - help='Tenant to remove as member.') -def do_member_delete(gc, args): - """Delete image member.""" - if not (args.image_id and args.member_id): - utils.exit('Unable to delete member. Specify image_id and member_id') - else: - gc.image_members.delete(args.image_id, args.member_id) - - -@utils.arg('image_id', metavar='<IMAGE_ID>', - help='Image from which to update member.') -@utils.arg('member_id', metavar='<MEMBER_ID>', - help='Tenant to update.') -@utils.arg('member_status', metavar='<MEMBER_STATUS>', - choices=MEMBER_STATUS_VALUES, - help='Updated status of member.' - ' Valid Values: %s' % - ', '.join(str(val) for val in MEMBER_STATUS_VALUES)) -def do_member_update(gc, args): - """Update the status of a member for a given image.""" - if not (args.image_id and args.member_id and args.member_status): - utils.exit('Unable to update member. Specify image_id, member_id and' - ' member_status') - else: - member = gc.image_members.update(args.image_id, args.member_id, - args.member_status) - member = [member] - columns = ['Image ID', 'Member ID', 'Status'] - utils.print_list(member, columns) - - -@utils.arg('image_id', metavar='<IMAGE_ID>', - help='Image with which to create member.') -@utils.arg('member_id', metavar='<MEMBER_ID>', - help='Tenant to add as member.') -def do_member_create(gc, args): - """Create member for a given image.""" - if not (args.image_id and args.member_id): - utils.exit('Unable to create member. Specify image_id and member_id') - else: - member = gc.image_members.create(args.image_id, args.member_id) - member = [member] - columns = ['Image ID', 'Member ID', 'Status'] - utils.print_list(member, columns) - - -@utils.arg('model', metavar='<MODEL>', help='Name of model to describe.') -def do_explain(gc, args): - """Describe a specific model.""" - try: - schema = gc.schemas.get(args.model) - except exc.HTTPNotFound: - utils.exit('Unable to find requested model \'%s\'' % args.model) - else: - formatters = {'Attribute': lambda m: m.name} - columns = ['Attribute', 'Description'] - utils.print_list(schema.properties, columns, formatters) - - -@utils.arg('--file', metavar='<FILE>', - help='Local file to save downloaded image data to. ' - 'If this is not specified the image data will be ' - 'written to stdout.') -@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to download.') -@utils.arg('--progress', action='store_true', default=False, - help='Show download progress bar.') -def do_image_download(gc, args): - """Download a specific image.""" - body = gc.images.data(args.id) - if args.progress: - body = progressbar.VerboseIteratorWrapper(body, len(body)) - utils.save_image(body, args.file) - - -@utils.arg('--file', metavar='<FILE>', - help=('Local file that contains disk image to be uploaded.' - ' Alternatively, images can be passed' - ' to the client via stdin.')) -@utils.arg('--size', metavar='<IMAGE_SIZE>', type=int, - help='Size in bytes of image to be uploaded. Default is to get ' - 'size from provided data object but this is supported in case ' - 'where size cannot be inferred.', - default=None) -@utils.arg('--progress', action='store_true', default=False, - help='Show upload progress bar.') -@utils.arg('id', metavar='<IMAGE_ID>', - help='ID of image to upload data to.') -def do_image_upload(gc, args): - """Upload data for a specific image.""" - image_data = utils.get_data_file(args) - if args.progress: - filesize = utils.get_file_size(image_data) - if filesize is not None: - # NOTE(kragniz): do not show a progress bar if the size of the - # input is unknown (most likely a piped input) - image_data = progressbar.VerboseFileWrapper(image_data, filesize) - gc.images.upload(args.id, image_data, args.size) - - -@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to delete.') -def do_image_delete(gc, args): - """Delete specified image.""" - image = gc.images.get(args.id) - if image and image.status == "deleted": - msg = "No image with an ID of '%s' exists." % image.id - utils.exit(msg) - gc.images.delete(args.id) - - -@utils.arg('image_id', metavar='<IMAGE_ID>', - help='Image to be updated with the given tag.') -@utils.arg('tag_value', metavar='<TAG_VALUE>', - help='Value of the tag.') -def do_image_tag_update(gc, args): - """Update an image with the given tag.""" - if not (args.image_id and args.tag_value): - utils.exit('Unable to update tag. Specify image_id and tag_value') - else: - gc.image_tags.update(args.image_id, args.tag_value) - image = gc.images.get(args.image_id) - image = [image] - columns = ['ID', 'Tags'] - utils.print_list(image, columns) - - -@utils.arg('image_id', metavar='<IMAGE_ID>', - help='ID of the image from which to delete tag.') -@utils.arg('tag_value', metavar='<TAG_VALUE>', - help='Value of the tag.') -def do_image_tag_delete(gc, args): - """Delete the tag associated with the given image.""" - if not (args.image_id and args.tag_value): - utils.exit('Unable to delete tag. Specify image_id and tag_value') - else: - gc.image_tags.delete(args.image_id, args.tag_value) - - -@utils.arg('--url', metavar='<URL>', required=True, - help='URL of location to add.') -@utils.arg('--metadata', metavar='<STRING>', default='{}', - help=('Metadata associated with the location. ' - 'Must be a valid JSON object (default: %(default)s)')) -@utils.arg('id', metavar='<ID>', - help='ID of image to which the location is to be added.') -def do_location_add(gc, args): - """Add a location (and related metadata) to an image.""" - try: - metadata = json.loads(args.metadata) - except ValueError: - utils.exit('Metadata is not a valid JSON object.') - else: - image = gc.images.add_location(args.id, args.url, metadata) - utils.print_dict(image) - - -@utils.arg('--url', metavar='<URL>', action='append', required=True, - help='URL of location to remove. May be used multiple times.') -@utils.arg('id', metavar='<ID>', - help='ID of image whose locations are to be removed.') -def do_location_delete(gc, args): - """Remove locations (and related metadata) from an image.""" - gc.images.delete_locations(args.id, set(args.url)) - - -@utils.arg('--url', metavar='<URL>', required=True, - help='URL of location to update.') -@utils.arg('--metadata', metavar='<STRING>', default='{}', - help=('Metadata associated with the location. ' - 'Must be a valid JSON object (default: %(default)s)')) -@utils.arg('id', metavar='<ID>', - help='ID of image whose location is to be updated.') -def do_location_update(gc, args): - """Update metadata of an image's location.""" - try: - metadata = json.loads(args.metadata) - except ValueError: - utils.exit('Metadata is not a valid JSON object.') - else: - image = gc.images.update_location(args.id, args.url, metadata) - utils.print_dict(image) - - -# Metadata - catalog -NAMESPACE_SCHEMA = None - - -def get_namespace_schema(): - global NAMESPACE_SCHEMA - if NAMESPACE_SCHEMA is None: - schema_path = expanduser("~/.glanceclient/namespace_schema.json") - if os.path.isfile(schema_path): - with open(schema_path, "r") as f: - schema_raw = f.read() - NAMESPACE_SCHEMA = json.loads(schema_raw) - return NAMESPACE_SCHEMA - - -def _namespace_show(namespace, max_column_width=None): - namespace = dict(namespace) # Warlock objects are compatible with dicts - # Flatten dicts for display - if 'properties' in namespace: - props = [k for k in namespace['properties']] - namespace['properties'] = props - if 'resource_type_associations' in namespace: - assocs = [assoc['name'] - for assoc in namespace['resource_type_associations']] - namespace['resource_type_associations'] = assocs - if 'objects' in namespace: - objects = [obj['name'] for obj in namespace['objects']] - namespace['objects'] = objects - - if max_column_width: - utils.print_dict(namespace, max_column_width) - else: - utils.print_dict(namespace) - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of the namespace.') -@utils.schema_args(get_namespace_schema, omit=['namespace', 'property_count', - 'properties', 'tag_count', - 'tags', 'object_count', - 'objects', 'resource_types']) -def do_md_namespace_create(gc, args): - """Create a new metadata definitions namespace.""" - schema = gc.schemas.get('metadefs/namespace') - _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()] - fields = dict(filter(lambda x: x[1] is not None and - (schema.is_core_property(x[0])), - _args)) - namespace = gc.metadefs_namespace.create(**fields) - - _namespace_show(namespace) - - -@utils.arg('--file', metavar='<FILEPATH>', - help='Path to file with namespace schema to import. Alternatively, ' - 'namespaces schema can be passed to the client via stdin.') -def do_md_namespace_import(gc, args): - """Import a metadata definitions namespace from file or standard input.""" - namespace_data = utils.get_data_file(args) - if not namespace_data: - utils.exit('No metadata definition namespace passed via stdin or ' - '--file argument.') - - try: - namespace_json = json.load(namespace_data) - except ValueError: - utils.exit('Schema is not a valid JSON object.') - else: - namespace = gc.metadefs_namespace.create(**namespace_json) - _namespace_show(namespace) - - -@utils.arg('id', metavar='<NAMESPACE>', help='Name of namespace to update.') -@utils.schema_args(get_namespace_schema, omit=['property_count', 'properties', - 'tag_count', 'tags', - 'object_count', 'objects', - 'resource_type_associations', - 'schema']) -def do_md_namespace_update(gc, args): - """Update an existing metadata definitions namespace.""" - schema = gc.schemas.get('metadefs/namespace') - - _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()] - fields = dict(filter(lambda x: x[1] is not None and - (schema.is_core_property(x[0])), - _args)) - namespace = gc.metadefs_namespace.update(args.id, **fields) - - _namespace_show(namespace) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace to describe.') -@utils.arg('--resource-type', metavar='<RESOURCE_TYPE>', - help='Applies prefix of given resource type associated to a ' - 'namespace to all properties of a namespace.', default=None) -@utils.arg('--max-column-width', metavar='<integer>', default=80, - help='The max column width of the printed table.') -def do_md_namespace_show(gc, args): - """Describe a specific metadata definitions namespace. - - Lists also the namespace properties, objects and resource type - associations. - """ - kwargs = {} - if args.resource_type: - kwargs['resource_type'] = args.resource_type - - namespace = gc.metadefs_namespace.get(args.namespace, **kwargs) - _namespace_show(namespace, int(args.max_column_width)) - - -@utils.arg('--resource-types', metavar='<RESOURCE_TYPES>', action='append', - help='Resource type to filter namespaces.') -@utils.arg('--visibility', metavar='<VISIBILITY>', - help='Visibility parameter to filter namespaces.') -@utils.arg('--page-size', metavar='<SIZE>', default=None, type=int, - help='Number of namespaces to request in each paginated request.') -def do_md_namespace_list(gc, args): - """List metadata definitions namespaces.""" - filter_keys = ['resource_types', 'visibility'] - filter_items = [(key, getattr(args, key, None)) for key in filter_keys] - filters = dict([item for item in filter_items if item[1] is not None]) - - kwargs = {'filters': filters} - if args.page_size is not None: - kwargs['page_size'] = args.page_size - - namespaces = gc.metadefs_namespace.list(**kwargs) - columns = ['namespace'] - utils.print_list(namespaces, columns) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace to delete.') -def do_md_namespace_delete(gc, args): - """Delete specified metadata definitions namespace with its contents.""" - gc.metadefs_namespace.delete(args.namespace) - - -# Metadata - catalog -RESOURCE_TYPE_SCHEMA = None - - -def get_resource_type_schema(): - global RESOURCE_TYPE_SCHEMA - if RESOURCE_TYPE_SCHEMA is None: - schema_path = expanduser("~/.glanceclient/resource_type_schema.json") - if os.path.isfile(schema_path): - with open(schema_path, "r") as f: - schema_raw = f.read() - RESOURCE_TYPE_SCHEMA = json.loads(schema_raw) - return RESOURCE_TYPE_SCHEMA - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of namespace.') -@utils.schema_args(get_resource_type_schema) -def do_md_resource_type_associate(gc, args): - """Associate resource type with a metadata definitions namespace.""" - schema = gc.schemas.get('metadefs/resource_type') - _args = [(x[0].replace('-', '_'), x[1]) for x in vars(args).items()] - fields = dict(filter(lambda x: x[1] is not None and - (schema.is_core_property(x[0])), - _args)) - resource_type = gc.metadefs_resource_type.associate(args.namespace, - **fields) - utils.print_dict(resource_type) - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of namespace.') -@utils.arg('resource_type', metavar='<RESOURCE_TYPE>', - help='Name of resource type.') -def do_md_resource_type_deassociate(gc, args): - """Deassociate resource type with a metadata definitions namespace.""" - gc.metadefs_resource_type.deassociate(args.namespace, args.resource_type) - - -def do_md_resource_type_list(gc, args): - """List available resource type names.""" - resource_types = gc.metadefs_resource_type.list() - utils.print_list(resource_types, ['name']) - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of namespace.') -def do_md_namespace_resource_type_list(gc, args): - """List resource types associated to specific namespace.""" - resource_types = gc.metadefs_resource_type.get(args.namespace) - utils.print_list(resource_types, ['name', 'prefix', 'properties_target']) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the property will belong.') -@utils.arg('--name', metavar='<NAME>', required=True, - help='Internal name of a property.') -@utils.arg('--title', metavar='<TITLE>', required=True, - help='Property name displayed to the user.') -@utils.arg('--schema', metavar='<SCHEMA>', required=True, - help='Valid JSON schema of a property.') -def do_md_property_create(gc, args): - """Create a new metadata definitions property inside a namespace.""" - try: - schema = json.loads(args.schema) - except ValueError: - utils.exit('Schema is not a valid JSON object.') - else: - fields = {'name': args.name, 'title': args.title} - fields.update(schema) - new_property = gc.metadefs_property.create(args.namespace, **fields) - utils.print_dict(new_property) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the property belongs.') -@utils.arg('property', metavar='<PROPERTY>', help='Name of a property.') -@utils.arg('--name', metavar='<NAME>', default=None, - help='New name of a property.') -@utils.arg('--title', metavar='<TITLE>', default=None, - help='Property name displayed to the user.') -@utils.arg('--schema', metavar='<SCHEMA>', default=None, - help='Valid JSON schema of a property.') -def do_md_property_update(gc, args): - """Update metadata definitions property inside a namespace.""" - fields = {} - if args.name: - fields['name'] = args.name - if args.title: - fields['title'] = args.title - if args.schema: - try: - schema = json.loads(args.schema) - except ValueError: - utils.exit('Schema is not a valid JSON object.') - else: - fields.update(schema) - - new_property = gc.metadefs_property.update(args.namespace, args.property, - **fields) - utils.print_dict(new_property) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the property belongs.') -@utils.arg('property', metavar='<PROPERTY>', help='Name of a property.') -@utils.arg('--max-column-width', metavar='<integer>', default=80, - help='The max column width of the printed table.') -def do_md_property_show(gc, args): - """Describe a specific metadata definitions property inside a namespace.""" - prop = gc.metadefs_property.get(args.namespace, args.property) - utils.print_dict(prop, int(args.max_column_width)) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the property belongs.') -@utils.arg('property', metavar='<PROPERTY>', help='Name of a property.') -def do_md_property_delete(gc, args): - """Delete a specific metadata definitions property inside a namespace.""" - gc.metadefs_property.delete(args.namespace, args.property) - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of namespace.') -def do_md_namespace_properties_delete(gc, args): - """Delete all metadata definitions property inside a specific namespace.""" - gc.metadefs_property.delete_all(args.namespace) - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of namespace.') -def do_md_property_list(gc, args): - """List metadata definitions properties inside a specific namespace.""" - properties = gc.metadefs_property.list(args.namespace) - columns = ['name', 'title', 'type'] - utils.print_list(properties, columns) - - -def _object_show(obj, max_column_width=None): - obj = dict(obj) # Warlock objects are compatible with dicts - # Flatten dicts for display - if 'properties' in obj: - objects = [k for k in obj['properties']] - obj['properties'] = objects - - if max_column_width: - utils.print_dict(obj, max_column_width) - else: - utils.print_dict(obj) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the object will belong.') -@utils.arg('--name', metavar='<NAME>', required=True, - help='Internal name of an object.') -@utils.arg('--schema', metavar='<SCHEMA>', required=True, - help='Valid JSON schema of an object.') -def do_md_object_create(gc, args): - """Create a new metadata definitions object inside a namespace.""" - try: - schema = json.loads(args.schema) - except ValueError: - utils.exit('Schema is not a valid JSON object.') - else: - fields = {'name': args.name} - fields.update(schema) - new_object = gc.metadefs_object.create(args.namespace, **fields) - _object_show(new_object) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the object belongs.') -@utils.arg('object', metavar='<OBJECT>', help='Name of an object.') -@utils.arg('--name', metavar='<NAME>', default=None, - help='New name of an object.') -@utils.arg('--schema', metavar='<SCHEMA>', default=None, - help='Valid JSON schema of an object.') -def do_md_object_update(gc, args): - """Update metadata definitions object inside a namespace.""" - fields = {} - if args.name: - fields['name'] = args.name - if args.schema: - try: - schema = json.loads(args.schema) - except ValueError: - utils.exit('Schema is not a valid JSON object.') - else: - fields.update(schema) - - new_object = gc.metadefs_object.update(args.namespace, args.object, - **fields) - _object_show(new_object) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the object belongs.') -@utils.arg('object', metavar='<OBJECT>', help='Name of an object.') -@utils.arg('--max-column-width', metavar='<integer>', default=80, - help='The max column width of the printed table.') -def do_md_object_show(gc, args): - """Describe a specific metadata definitions object inside a namespace.""" - obj = gc.metadefs_object.get(args.namespace, args.object) - _object_show(obj, int(args.max_column_width)) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the object belongs.') -@utils.arg('object', metavar='<OBJECT>', help='Name of an object.') -@utils.arg('property', metavar='<PROPERTY>', help='Name of a property.') -@utils.arg('--max-column-width', metavar='<integer>', default=80, - help='The max column width of the printed table.') -def do_md_object_property_show(gc, args): - """Describe a specific metadata definitions property inside an object.""" - obj = gc.metadefs_object.get(args.namespace, args.object) - try: - prop = obj['properties'][args.property] - prop['name'] = args.property - except KeyError: - utils.exit('Property %s not found in object %s.' % (args.property, - args.object)) - utils.print_dict(prop, int(args.max_column_width)) - - -@utils.arg('namespace', metavar='<NAMESPACE>', - help='Name of namespace the object belongs.') -@utils.arg('object', metavar='<OBJECT>', help='Name of an object.') -def do_md_object_delete(gc, args): - """Delete a specific metadata definitions object inside a namespace.""" - gc.metadefs_object.delete(args.namespace, args.object) - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of namespace.') -def do_md_namespace_objects_delete(gc, args): - """Delete all metadata definitions objects inside a specific namespace.""" - gc.metadefs_object.delete_all(args.namespace) - - -@utils.arg('namespace', metavar='<NAMESPACE>', help='Name of namespace.') -def do_md_object_list(gc, args): - """List metadata definitions objects inside a specific namespace.""" - objects = gc.metadefs_object.list(args.namespace) - columns = ['name', 'description'] - column_settings = { - "description": { - "max_width": 50, - "align": "l" - } - } - utils.print_list(objects, columns, field_settings=column_settings) - - -@utils.arg('--sort-key', default='status', - choices=tasks.SORT_KEY_VALUES, - help='Sort task list by specified field.') -@utils.arg('--sort-dir', default='desc', - choices=tasks.SORT_DIR_VALUES, - help='Sort task list in specified direction.') -@utils.arg('--page-size', metavar='<SIZE>', default=None, type=int, - help='Number of tasks to request in each paginated request.') -@utils.arg('--type', metavar='<TYPE>', - help='Filter tasks to those that have this type.') -@utils.arg('--status', metavar='<STATUS>', - help='Filter tasks to those that have this status.') -def do_task_list(gc, args): - """List tasks you can access.""" - filter_keys = ['type', 'status'] - filter_items = [(key, getattr(args, key)) for key in filter_keys] - filters = dict([item for item in filter_items if item[1] is not None]) - - kwargs = {'filters': filters} - if args.page_size is not None: - kwargs['page_size'] = args.page_size - - kwargs['sort_key'] = args.sort_key - kwargs['sort_dir'] = args.sort_dir - - tasks = gc.tasks.list(**kwargs) - - columns = ['ID', 'Type', 'Status', 'Owner'] - utils.print_list(tasks, columns) - - -@utils.arg('id', metavar='<TASK_ID>', help='ID of task to describe.') -def do_task_show(gc, args): - """Describe a specific task.""" - task = gc.tasks.get(args.id) - ignore = ['self', 'schema'] - task = dict([item for item in task.iteritems() if item[0] not in ignore]) - utils.print_dict(task) - - -@utils.arg('--type', metavar='<TYPE>', - help='Type of Task. Please refer to Glance schema or documentation' - ' to see which tasks are supported.') -@utils.arg('--input', metavar='<STRING>', default='{}', - help='Parameters of the task to be launched') -def do_task_create(gc, args): - """Create a new task.""" - if not (args.type and args.input): - utils.exit('Unable to create task. Specify task type and input.') - else: - try: - input = json.loads(args.input) - except ValueError: - utils.exit('Failed to parse the "input" parameter. Must be a ' - 'valid JSON object.') - - task_values = {'type': args.type, 'input': input} - task = gc.tasks.create(**task_values) - ignore = ['self', 'schema'] - task = dict([item for item in task.iteritems() - if item[0] not in ignore]) - utils.print_dict(task) diff --git a/awx/lib/site-packages/glanceclient/v2/tasks.py b/awx/lib/site-packages/glanceclient/v2/tasks.py deleted file mode 100644 index 37801915a8..0000000000 --- a/awx/lib/site-packages/glanceclient/v2/tasks.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2013 OpenStack LLC. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils import encodeutils -import six -import warlock - -from glanceclient.common import utils -from glanceclient.v2 import schemas - -DEFAULT_PAGE_SIZE = 20 - -SORT_DIR_VALUES = ('asc', 'desc') -SORT_KEY_VALUES = ('id', 'type', 'status') - - -class Controller(object): - def __init__(self, http_client, schema_client): - self.http_client = http_client - self.schema_client = schema_client - - @utils.memoized_property - def model(self): - schema = self.schema_client.get('task') - return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel) - - def list(self, **kwargs): - """Retrieve a listing of Task objects - - :param page_size: Number of tasks to request in each paginated request - :returns generator over list of Tasks - """ - def paginate(url): - resp, body = self.http_client.get(url) - for task in body['tasks']: - yield task - try: - next_url = body['next'] - except KeyError: - return - else: - for task in paginate(next_url): - yield task - - filters = kwargs.get('filters', {}) - - if not kwargs.get('page_size'): - filters['limit'] = DEFAULT_PAGE_SIZE - else: - filters['limit'] = kwargs['page_size'] - - if 'marker' in kwargs: - filters['marker'] = kwargs['marker'] - - sort_key = kwargs.get('sort_key') - if sort_key is not None: - if sort_key in SORT_KEY_VALUES: - filters['sort_key'] = sort_key - else: - raise ValueError('sort_key must be one of the following: %s.' - % ', '.join(SORT_KEY_VALUES)) - - sort_dir = kwargs.get('sort_dir') - if sort_dir is not None: - if sort_dir in SORT_DIR_VALUES: - filters['sort_dir'] = sort_dir - else: - raise ValueError('sort_dir must be one of the following: %s.' - % ', '.join(SORT_DIR_VALUES)) - - for param, value in filters.items(): - if isinstance(value, six.string_types): - filters[param] = encodeutils.safe_encode(value) - - url = '/v2/tasks?%s' % six.moves.urllib.parse.urlencode(filters) - for task in paginate(url): - #NOTE(flwang): remove 'self' for now until we have an elegant - # way to pass it into the model constructor without conflict - task.pop('self', None) - yield self.model(**task) - - def get(self, task_id): - """Get a task based on given task id.""" - url = '/v2/tasks/%s' % task_id - resp, body = self.http_client.get(url) - #NOTE(flwang): remove 'self' for now until we have an elegant - # way to pass it into the model constructor without conflict - body.pop('self', None) - return self.model(**body) - - def create(self, **kwargs): - """Create a new task.""" - url = '/v2/tasks' - task = self.model() - - for (key, value) in kwargs.items(): - try: - setattr(task, key, value) - except warlock.InvalidOperation as e: - raise TypeError(unicode(e)) - - resp, body = self.http_client.post(url, data=task) - #NOTE(flwang): remove 'self' for now until we have an elegant - # way to pass it into the model constructor without conflict - body.pop('self', None) - return self.model(**body) diff --git a/awx/lib/site-packages/httplib2/__init__.py b/awx/lib/site-packages/httplib2/__init__.py deleted file mode 100644 index d1212b57fb..0000000000 --- a/awx/lib/site-packages/httplib2/__init__.py +++ /dev/null @@ -1,1680 +0,0 @@ -from __future__ import generators -""" -httplib2 - -A caching http interface that supports ETags and gzip -to conserve bandwidth. - -Requires Python 2.3 or later - -Changelog: -2007-08-18, Rick: Modified so it's able to use a socks proxy if needed. - -""" - -__author__ = "Joe Gregorio (joe@bitworking.org)" -__copyright__ = "Copyright 2006, Joe Gregorio" -__contributors__ = ["Thomas Broyer (t.broyer@ltgt.net)", - "James Antill", - "Xavier Verges Farrero", - "Jonathan Feinberg", - "Blair Zajac", - "Sam Ruby", - "Louis Nyffenegger"] -__license__ = "MIT" -__version__ = "0.9" - -import re -import sys -import email -import email.Utils -import email.Message -import email.FeedParser -import StringIO -import gzip -import zlib -import httplib -import urlparse -import urllib -import base64 -import os -import copy -import calendar -import time -import random -import errno -try: - from hashlib import sha1 as _sha, md5 as _md5 -except ImportError: - # prior to Python 2.5, these were separate modules - import sha - import md5 - _sha = sha.new - _md5 = md5.new -import hmac -from gettext import gettext as _ -import socket - -try: - from httplib2 import socks -except ImportError: - try: - import socks - except (ImportError, AttributeError): - socks = None - -# Build the appropriate socket wrapper for ssl -try: - import ssl # python 2.6 - ssl_SSLError = ssl.SSLError - def _ssl_wrap_socket(sock, key_file, cert_file, - disable_validation, ca_certs): - if disable_validation: - cert_reqs = ssl.CERT_NONE - else: - cert_reqs = ssl.CERT_REQUIRED - # We should be specifying SSL version 3 or TLS v1, but the ssl module - # doesn't expose the necessary knobs. So we need to go with the default - # of SSLv23. - return ssl.wrap_socket(sock, keyfile=key_file, certfile=cert_file, - cert_reqs=cert_reqs, ca_certs=ca_certs) -except (AttributeError, ImportError): - ssl_SSLError = None - def _ssl_wrap_socket(sock, key_file, cert_file, - disable_validation, ca_certs): - if not disable_validation: - raise CertificateValidationUnsupported( - "SSL certificate validation is not supported without " - "the ssl module installed. To avoid this error, install " - "the ssl module, or explicity disable validation.") - ssl_sock = socket.ssl(sock, key_file, cert_file) - return httplib.FakeSocket(sock, ssl_sock) - - -if sys.version_info >= (2,3): - from iri2uri import iri2uri -else: - def iri2uri(uri): - return uri - -def has_timeout(timeout): # python 2.6 - if hasattr(socket, '_GLOBAL_DEFAULT_TIMEOUT'): - return (timeout is not None and timeout is not socket._GLOBAL_DEFAULT_TIMEOUT) - return (timeout is not None) - -__all__ = [ - 'Http', 'Response', 'ProxyInfo', 'HttpLib2Error', 'RedirectMissingLocation', - 'RedirectLimit', 'FailedToDecompressContent', - 'UnimplementedDigestAuthOptionError', - 'UnimplementedHmacDigestAuthOptionError', - 'debuglevel', 'ProxiesUnavailableError'] - - -# The httplib debug level, set to a non-zero value to get debug output -debuglevel = 0 - -# A request will be tried 'RETRIES' times if it fails at the socket/connection level. -RETRIES = 2 - -# Python 2.3 support -if sys.version_info < (2,4): - def sorted(seq): - seq.sort() - return seq - -# Python 2.3 support -def HTTPResponse__getheaders(self): - """Return list of (header, value) tuples.""" - if self.msg is None: - raise httplib.ResponseNotReady() - return self.msg.items() - -if not hasattr(httplib.HTTPResponse, 'getheaders'): - httplib.HTTPResponse.getheaders = HTTPResponse__getheaders - -# All exceptions raised here derive from HttpLib2Error -class HttpLib2Error(Exception): pass - -# Some exceptions can be caught and optionally -# be turned back into responses. -class HttpLib2ErrorWithResponse(HttpLib2Error): - def __init__(self, desc, response, content): - self.response = response - self.content = content - HttpLib2Error.__init__(self, desc) - -class RedirectMissingLocation(HttpLib2ErrorWithResponse): pass -class RedirectLimit(HttpLib2ErrorWithResponse): pass -class FailedToDecompressContent(HttpLib2ErrorWithResponse): pass -class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse): pass -class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse): pass - -class MalformedHeader(HttpLib2Error): pass -class RelativeURIError(HttpLib2Error): pass -class ServerNotFoundError(HttpLib2Error): pass -class ProxiesUnavailableError(HttpLib2Error): pass -class CertificateValidationUnsupported(HttpLib2Error): pass -class SSLHandshakeError(HttpLib2Error): pass -class NotSupportedOnThisPlatform(HttpLib2Error): pass -class CertificateHostnameMismatch(SSLHandshakeError): - def __init__(self, desc, host, cert): - HttpLib2Error.__init__(self, desc) - self.host = host - self.cert = cert - -# Open Items: -# ----------- -# Proxy support - -# Are we removing the cached content too soon on PUT (only delete on 200 Maybe?) - -# Pluggable cache storage (supports storing the cache in -# flat files by default. We need a plug-in architecture -# that can support Berkeley DB and Squid) - -# == Known Issues == -# Does not handle a resource that uses conneg and Last-Modified but no ETag as a cache validator. -# Does not handle Cache-Control: max-stale -# Does not use Age: headers when calculating cache freshness. - - -# The number of redirections to follow before giving up. -# Note that only GET redirects are automatically followed. -# Will also honor 301 requests by saving that info and never -# requesting that URI again. -DEFAULT_MAX_REDIRECTS = 5 - -try: - # Users can optionally provide a module that tells us where the CA_CERTS - # are located. - import ca_certs_locater - CA_CERTS = ca_certs_locater.get() -except ImportError: - # Default CA certificates file bundled with httplib2. - CA_CERTS = os.path.join( - os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") - -# Which headers are hop-by-hop headers by default -HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade'] - -def _get_end2end_headers(response): - hopbyhop = list(HOP_BY_HOP) - hopbyhop.extend([x.strip() for x in response.get('connection', '').split(',')]) - return [header for header in response.keys() if header not in hopbyhop] - -URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") - -def parse_uri(uri): - """Parses a URI using the regex given in Appendix B of RFC 3986. - - (scheme, authority, path, query, fragment) = parse_uri(uri) - """ - groups = URI.match(uri).groups() - return (groups[1], groups[3], groups[4], groups[6], groups[8]) - -def urlnorm(uri): - (scheme, authority, path, query, fragment) = parse_uri(uri) - if not scheme or not authority: - raise RelativeURIError("Only absolute URIs are allowed. uri = %s" % uri) - authority = authority.lower() - scheme = scheme.lower() - if not path: - path = "/" - # Could do syntax based normalization of the URI before - # computing the digest. See Section 6.2.2 of Std 66. - request_uri = query and "?".join([path, query]) or path - scheme = scheme.lower() - defrag_uri = scheme + "://" + authority + request_uri - return scheme, authority, request_uri, defrag_uri - - -# Cache filename construction (original borrowed from Venus http://intertwingly.net/code/venus/) -re_url_scheme = re.compile(r'^\w+://') -re_slash = re.compile(r'[?/:|]+') - -def safename(filename): - """Return a filename suitable for the cache. - - Strips dangerous and common characters to create a filename we - can use to store the cache in. - """ - - try: - if re_url_scheme.match(filename): - if isinstance(filename,str): - filename = filename.decode('utf-8') - filename = filename.encode('idna') - else: - filename = filename.encode('idna') - except UnicodeError: - pass - if isinstance(filename,unicode): - filename=filename.encode('utf-8') - filemd5 = _md5(filename).hexdigest() - filename = re_url_scheme.sub("", filename) - filename = re_slash.sub(",", filename) - - # limit length of filename - if len(filename)>200: - filename=filename[:200] - return ",".join((filename, filemd5)) - -NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+') -def _normalize_headers(headers): - return dict([ (key.lower(), NORMALIZE_SPACE.sub(value, ' ').strip()) for (key, value) in headers.iteritems()]) - -def _parse_cache_control(headers): - retval = {} - if headers.has_key('cache-control'): - parts = headers['cache-control'].split(',') - parts_with_args = [tuple([x.strip().lower() for x in part.split("=", 1)]) for part in parts if -1 != part.find("=")] - parts_wo_args = [(name.strip().lower(), 1) for name in parts if -1 == name.find("=")] - retval = dict(parts_with_args + parts_wo_args) - return retval - -# Whether to use a strict mode to parse WWW-Authenticate headers -# Might lead to bad results in case of ill-formed header value, -# so disabled by default, falling back to relaxed parsing. -# Set to true to turn on, usefull for testing servers. -USE_WWW_AUTH_STRICT_PARSING = 0 - -# In regex below: -# [^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+ matches a "token" as defined by HTTP -# "(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?" matches a "quoted-string" as defined by HTTP, when LWS have already been replaced by a single space -# Actually, as an auth-param value can be either a token or a quoted-string, they are combined in a single pattern which matches both: -# \"?((?<=\")(?:[^\0-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x08\x0A-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"? -WWW_AUTH_STRICT = re.compile(r"^(?:\s*(?:,\s*)?([^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+)\s*=\s*\"?((?<=\")(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"?)(.*)$") -WWW_AUTH_RELAXED = re.compile(r"^(?:\s*(?:,\s*)?([^ \t\r\n=]+)\s*=\s*\"?((?<=\")(?:[^\\\"]|\\.)*?(?=\")|(?<!\")[^ \t\r\n,]+(?!\"))\"?)(.*)$") -UNQUOTE_PAIRS = re.compile(r'\\(.)') -def _parse_www_authenticate(headers, headername='www-authenticate'): - """Returns a dictionary of dictionaries, one dict - per auth_scheme.""" - retval = {} - if headers.has_key(headername): - try: - - authenticate = headers[headername].strip() - www_auth = USE_WWW_AUTH_STRICT_PARSING and WWW_AUTH_STRICT or WWW_AUTH_RELAXED - while authenticate: - # Break off the scheme at the beginning of the line - if headername == 'authentication-info': - (auth_scheme, the_rest) = ('digest', authenticate) - else: - (auth_scheme, the_rest) = authenticate.split(" ", 1) - # Now loop over all the key value pairs that come after the scheme, - # being careful not to roll into the next scheme - match = www_auth.search(the_rest) - auth_params = {} - while match: - if match and len(match.groups()) == 3: - (key, value, the_rest) = match.groups() - auth_params[key.lower()] = UNQUOTE_PAIRS.sub(r'\1', value) # '\\'.join([x.replace('\\', '') for x in value.split('\\\\')]) - match = www_auth.search(the_rest) - retval[auth_scheme.lower()] = auth_params - authenticate = the_rest.strip() - - except ValueError: - raise MalformedHeader("WWW-Authenticate") - return retval - - -def _entry_disposition(response_headers, request_headers): - """Determine freshness from the Date, Expires and Cache-Control headers. - - We don't handle the following: - - 1. Cache-Control: max-stale - 2. Age: headers are not used in the calculations. - - Not that this algorithm is simpler than you might think - because we are operating as a private (non-shared) cache. - This lets us ignore 's-maxage'. We can also ignore - 'proxy-invalidate' since we aren't a proxy. - We will never return a stale document as - fresh as a design decision, and thus the non-implementation - of 'max-stale'. This also lets us safely ignore 'must-revalidate' - since we operate as if every server has sent 'must-revalidate'. - Since we are private we get to ignore both 'public' and - 'private' parameters. We also ignore 'no-transform' since - we don't do any transformations. - The 'no-store' parameter is handled at a higher level. - So the only Cache-Control parameters we look at are: - - no-cache - only-if-cached - max-age - min-fresh - """ - - retval = "STALE" - cc = _parse_cache_control(request_headers) - cc_response = _parse_cache_control(response_headers) - - if request_headers.has_key('pragma') and request_headers['pragma'].lower().find('no-cache') != -1: - retval = "TRANSPARENT" - if 'cache-control' not in request_headers: - request_headers['cache-control'] = 'no-cache' - elif cc.has_key('no-cache'): - retval = "TRANSPARENT" - elif cc_response.has_key('no-cache'): - retval = "STALE" - elif cc.has_key('only-if-cached'): - retval = "FRESH" - elif response_headers.has_key('date'): - date = calendar.timegm(email.Utils.parsedate_tz(response_headers['date'])) - now = time.time() - current_age = max(0, now - date) - if cc_response.has_key('max-age'): - try: - freshness_lifetime = int(cc_response['max-age']) - except ValueError: - freshness_lifetime = 0 - elif response_headers.has_key('expires'): - expires = email.Utils.parsedate_tz(response_headers['expires']) - if None == expires: - freshness_lifetime = 0 - else: - freshness_lifetime = max(0, calendar.timegm(expires) - date) - else: - freshness_lifetime = 0 - if cc.has_key('max-age'): - try: - freshness_lifetime = int(cc['max-age']) - except ValueError: - freshness_lifetime = 0 - if cc.has_key('min-fresh'): - try: - min_fresh = int(cc['min-fresh']) - except ValueError: - min_fresh = 0 - current_age += min_fresh - if freshness_lifetime > current_age: - retval = "FRESH" - return retval - -def _decompressContent(response, new_content): - content = new_content - try: - encoding = response.get('content-encoding', None) - if encoding in ['gzip', 'deflate']: - if encoding == 'gzip': - content = gzip.GzipFile(fileobj=StringIO.StringIO(new_content)).read() - if encoding == 'deflate': - content = zlib.decompress(content) - response['content-length'] = str(len(content)) - # Record the historical presence of the encoding in a way the won't interfere. - response['-content-encoding'] = response['content-encoding'] - del response['content-encoding'] - except IOError: - content = "" - raise FailedToDecompressContent(_("Content purported to be compressed with %s but failed to decompress.") % response.get('content-encoding'), response, content) - return content - -def _updateCache(request_headers, response_headers, content, cache, cachekey): - if cachekey: - cc = _parse_cache_control(request_headers) - cc_response = _parse_cache_control(response_headers) - if cc.has_key('no-store') or cc_response.has_key('no-store'): - cache.delete(cachekey) - else: - info = email.Message.Message() - for key, value in response_headers.iteritems(): - if key not in ['status','content-encoding','transfer-encoding']: - info[key] = value - - # Add annotations to the cache to indicate what headers - # are variant for this request. - vary = response_headers.get('vary', None) - if vary: - vary_headers = vary.lower().replace(' ', '').split(',') - for header in vary_headers: - key = '-varied-%s' % header - try: - info[key] = request_headers[header] - except KeyError: - pass - - status = response_headers.status - if status == 304: - status = 200 - - status_header = 'status: %d\r\n' % status - - header_str = info.as_string() - - header_str = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", header_str) - text = "".join([status_header, header_str, content]) - - cache.set(cachekey, text) - -def _cnonce(): - dig = _md5("%s:%s" % (time.ctime(), ["0123456789"[random.randrange(0, 9)] for i in range(20)])).hexdigest() - return dig[:16] - -def _wsse_username_token(cnonce, iso_now, password): - return base64.b64encode(_sha("%s%s%s" % (cnonce, iso_now, password)).digest()).strip() - - -# For credentials we need two things, first -# a pool of credential to try (not necesarily tied to BAsic, Digest, etc.) -# Then we also need a list of URIs that have already demanded authentication -# That list is tricky since sub-URIs can take the same auth, or the -# auth scheme may change as you descend the tree. -# So we also need each Auth instance to be able to tell us -# how close to the 'top' it is. - -class Authentication(object): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - self.path = path - self.host = host - self.credentials = credentials - self.http = http - - def depth(self, request_uri): - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - return request_uri[len(self.path):].count("/") - - def inscope(self, host, request_uri): - # XXX Should we normalize the request_uri? - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - return (host == self.host) and path.startswith(self.path) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header. Over-ride this in sub-classes.""" - pass - - def response(self, response, content): - """Gives us a chance to update with new nonces - or such returned from the last authorized response. - Over-rise this in sub-classes if necessary. - - Return TRUE is the request is to be retried, for - example Digest may return stale=true. - """ - return False - - - -class BasicAuthentication(Authentication): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'Basic ' + base64.b64encode("%s:%s" % self.credentials).strip() - - -class DigestAuthentication(Authentication): - """Only do qop='auth' and MD5, since that - is all Apache currently implements""" - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - self.challenge = challenge['digest'] - qop = self.challenge.get('qop', 'auth') - self.challenge['qop'] = ('auth' in [x.strip() for x in qop.split()]) and 'auth' or None - if self.challenge['qop'] is None: - raise UnimplementedDigestAuthOptionError( _("Unsupported value for qop: %s." % qop)) - self.challenge['algorithm'] = self.challenge.get('algorithm', 'MD5').upper() - if self.challenge['algorithm'] != 'MD5': - raise UnimplementedDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm'])) - self.A1 = "".join([self.credentials[0], ":", self.challenge['realm'], ":", self.credentials[1]]) - self.challenge['nc'] = 1 - - def request(self, method, request_uri, headers, content, cnonce = None): - """Modify the request headers""" - H = lambda x: _md5(x).hexdigest() - KD = lambda s, d: H("%s:%s" % (s, d)) - A2 = "".join([method, ":", request_uri]) - self.challenge['cnonce'] = cnonce or _cnonce() - request_digest = '"%s"' % KD(H(self.A1), "%s:%s:%s:%s:%s" % ( - self.challenge['nonce'], - '%08x' % self.challenge['nc'], - self.challenge['cnonce'], - self.challenge['qop'], H(A2))) - headers['authorization'] = 'Digest username="%s", realm="%s", nonce="%s", uri="%s", algorithm=%s, response=%s, qop=%s, nc=%08x, cnonce="%s"' % ( - self.credentials[0], - self.challenge['realm'], - self.challenge['nonce'], - request_uri, - self.challenge['algorithm'], - request_digest, - self.challenge['qop'], - self.challenge['nc'], - self.challenge['cnonce']) - if self.challenge.get('opaque'): - headers['authorization'] += ', opaque="%s"' % self.challenge['opaque'] - self.challenge['nc'] += 1 - - def response(self, response, content): - if not response.has_key('authentication-info'): - challenge = _parse_www_authenticate(response, 'www-authenticate').get('digest', {}) - if 'true' == challenge.get('stale'): - self.challenge['nonce'] = challenge['nonce'] - self.challenge['nc'] = 1 - return True - else: - updated_challenge = _parse_www_authenticate(response, 'authentication-info').get('digest', {}) - - if updated_challenge.has_key('nextnonce'): - self.challenge['nonce'] = updated_challenge['nextnonce'] - self.challenge['nc'] = 1 - return False - - -class HmacDigestAuthentication(Authentication): - """Adapted from Robert Sayre's code and DigestAuthentication above.""" - __author__ = "Thomas Broyer (t.broyer@ltgt.net)" - - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - self.challenge = challenge['hmacdigest'] - # TODO: self.challenge['domain'] - self.challenge['reason'] = self.challenge.get('reason', 'unauthorized') - if self.challenge['reason'] not in ['unauthorized', 'integrity']: - self.challenge['reason'] = 'unauthorized' - self.challenge['salt'] = self.challenge.get('salt', '') - if not self.challenge.get('snonce'): - raise UnimplementedHmacDigestAuthOptionError( _("The challenge doesn't contain a server nonce, or this one is empty.")) - self.challenge['algorithm'] = self.challenge.get('algorithm', 'HMAC-SHA-1') - if self.challenge['algorithm'] not in ['HMAC-SHA-1', 'HMAC-MD5']: - raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm'])) - self.challenge['pw-algorithm'] = self.challenge.get('pw-algorithm', 'SHA-1') - if self.challenge['pw-algorithm'] not in ['SHA-1', 'MD5']: - raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for pw-algorithm: %s." % self.challenge['pw-algorithm'])) - if self.challenge['algorithm'] == 'HMAC-MD5': - self.hashmod = _md5 - else: - self.hashmod = _sha - if self.challenge['pw-algorithm'] == 'MD5': - self.pwhashmod = _md5 - else: - self.pwhashmod = _sha - self.key = "".join([self.credentials[0], ":", - self.pwhashmod.new("".join([self.credentials[1], self.challenge['salt']])).hexdigest().lower(), - ":", self.challenge['realm']]) - self.key = self.pwhashmod.new(self.key).hexdigest().lower() - - def request(self, method, request_uri, headers, content): - """Modify the request headers""" - keys = _get_end2end_headers(headers) - keylist = "".join(["%s " % k for k in keys]) - headers_val = "".join([headers[k] for k in keys]) - created = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()) - cnonce = _cnonce() - request_digest = "%s:%s:%s:%s:%s" % (method, request_uri, cnonce, self.challenge['snonce'], headers_val) - request_digest = hmac.new(self.key, request_digest, self.hashmod).hexdigest().lower() - headers['authorization'] = 'HMACDigest username="%s", realm="%s", snonce="%s", cnonce="%s", uri="%s", created="%s", response="%s", headers="%s"' % ( - self.credentials[0], - self.challenge['realm'], - self.challenge['snonce'], - cnonce, - request_uri, - created, - request_digest, - keylist) - - def response(self, response, content): - challenge = _parse_www_authenticate(response, 'www-authenticate').get('hmacdigest', {}) - if challenge.get('reason') in ['integrity', 'stale']: - return True - return False - - -class WsseAuthentication(Authentication): - """This is thinly tested and should not be relied upon. - At this time there isn't any third party server to test against. - Blogger and TypePad implemented this algorithm at one point - but Blogger has since switched to Basic over HTTPS and - TypePad has implemented it wrong, by never issuing a 401 - challenge but instead requiring your client to telepathically know that - their endpoint is expecting WSSE profile="UsernameToken".""" - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'WSSE profile="UsernameToken"' - iso_now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - cnonce = _cnonce() - password_digest = _wsse_username_token(cnonce, iso_now, self.credentials[1]) - headers['X-WSSE'] = 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"' % ( - self.credentials[0], - password_digest, - cnonce, - iso_now) - -class GoogleLoginAuthentication(Authentication): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - from urllib import urlencode - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - service = challenge['googlelogin'].get('service', 'xapi') - # Bloggger actually returns the service in the challenge - # For the rest we guess based on the URI - if service == 'xapi' and request_uri.find("calendar") > 0: - service = "cl" - # No point in guessing Base or Spreadsheet - #elif request_uri.find("spreadsheets") > 0: - # service = "wise" - - auth = dict(Email=credentials[0], Passwd=credentials[1], service=service, source=headers['user-agent']) - resp, content = self.http.request("https://www.google.com/accounts/ClientLogin", method="POST", body=urlencode(auth), headers={'Content-Type': 'application/x-www-form-urlencoded'}) - lines = content.split('\n') - d = dict([tuple(line.split("=", 1)) for line in lines if line]) - if resp.status == 403: - self.Auth = "" - else: - self.Auth = d['Auth'] - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'GoogleLogin Auth=' + self.Auth - - -AUTH_SCHEME_CLASSES = { - "basic": BasicAuthentication, - "wsse": WsseAuthentication, - "digest": DigestAuthentication, - "hmacdigest": HmacDigestAuthentication, - "googlelogin": GoogleLoginAuthentication -} - -AUTH_SCHEME_ORDER = ["hmacdigest", "googlelogin", "digest", "wsse", "basic"] - -class FileCache(object): - """Uses a local directory as a store for cached files. - Not really safe to use if multiple threads or processes are going to - be running on the same cache. - """ - def __init__(self, cache, safe=safename): # use safe=lambda x: md5.new(x).hexdigest() for the old behavior - self.cache = cache - self.safe = safe - if not os.path.exists(cache): - os.makedirs(self.cache) - - def get(self, key): - retval = None - cacheFullPath = os.path.join(self.cache, self.safe(key)) - try: - f = file(cacheFullPath, "rb") - retval = f.read() - f.close() - except IOError: - pass - return retval - - def set(self, key, value): - cacheFullPath = os.path.join(self.cache, self.safe(key)) - f = file(cacheFullPath, "wb") - f.write(value) - f.close() - - def delete(self, key): - cacheFullPath = os.path.join(self.cache, self.safe(key)) - if os.path.exists(cacheFullPath): - os.remove(cacheFullPath) - -class Credentials(object): - def __init__(self): - self.credentials = [] - - def add(self, name, password, domain=""): - self.credentials.append((domain.lower(), name, password)) - - def clear(self): - self.credentials = [] - - def iter(self, domain): - for (cdomain, name, password) in self.credentials: - if cdomain == "" or domain == cdomain: - yield (name, password) - -class KeyCerts(Credentials): - """Identical to Credentials except that - name/password are mapped to key/cert.""" - pass - -class AllHosts(object): - pass - -class ProxyInfo(object): - """Collect information required to use a proxy.""" - bypass_hosts = () - - def __init__(self, proxy_type, proxy_host, proxy_port, - proxy_rdns=None, proxy_user=None, proxy_pass=None): - """The parameter proxy_type must be set to one of socks.PROXY_TYPE_XXX - constants. For example: - - p = ProxyInfo(proxy_type=socks.PROXY_TYPE_HTTP, - proxy_host='localhost', proxy_port=8000) - """ - self.proxy_type = proxy_type - self.proxy_host = proxy_host - self.proxy_port = proxy_port - self.proxy_rdns = proxy_rdns - self.proxy_user = proxy_user - self.proxy_pass = proxy_pass - - def astuple(self): - return (self.proxy_type, self.proxy_host, self.proxy_port, - self.proxy_rdns, self.proxy_user, self.proxy_pass) - - def isgood(self): - return (self.proxy_host != None) and (self.proxy_port != None) - - def applies_to(self, hostname): - return not self.bypass_host(hostname) - - def bypass_host(self, hostname): - """Has this host been excluded from the proxy config""" - if self.bypass_hosts is AllHosts: - return True - - bypass = False - for domain in self.bypass_hosts: - if hostname.endswith(domain): - bypass = True - - return bypass - - -def proxy_info_from_environment(method='http'): - """ - Read proxy info from the environment variables. - """ - if method not in ['http', 'https']: - return - - env_var = method + '_proxy' - url = os.environ.get(env_var, os.environ.get(env_var.upper())) - if not url: - return - pi = proxy_info_from_url(url, method) - - no_proxy = os.environ.get('no_proxy', os.environ.get('NO_PROXY', '')) - bypass_hosts = [] - if no_proxy: - bypass_hosts = no_proxy.split(',') - # special case, no_proxy=* means all hosts bypassed - if no_proxy == '*': - bypass_hosts = AllHosts - - pi.bypass_hosts = bypass_hosts - return pi - -def proxy_info_from_url(url, method='http'): - """ - Construct a ProxyInfo from a URL (such as http_proxy env var) - """ - url = urlparse.urlparse(url) - username = None - password = None - port = None - if '@' in url[1]: - ident, host_port = url[1].split('@', 1) - if ':' in ident: - username, password = ident.split(':', 1) - else: - password = ident - else: - host_port = url[1] - if ':' in host_port: - host, port = host_port.split(':', 1) - else: - host = host_port - - if port: - port = int(port) - else: - port = dict(https=443, http=80)[method] - - proxy_type = 3 # socks.PROXY_TYPE_HTTP - return ProxyInfo( - proxy_type = proxy_type, - proxy_host = host, - proxy_port = port, - proxy_user = username or None, - proxy_pass = password or None, - ) - - -class HTTPConnectionWithTimeout(httplib.HTTPConnection): - """ - HTTPConnection subclass that supports timeouts - - All timeouts are in seconds. If None is passed for timeout then - Python's default timeout for sockets will be used. See for example - the docs of socket.setdefaulttimeout(): - http://docs.python.org/library/socket.html#socket.setdefaulttimeout - """ - - def __init__(self, host, port=None, strict=None, timeout=None, proxy_info=None): - httplib.HTTPConnection.__init__(self, host, port, strict) - self.timeout = timeout - self.proxy_info = proxy_info - - def connect(self): - """Connect to the host and port specified in __init__.""" - # Mostly verbatim from httplib.py. - if self.proxy_info and socks is None: - raise ProxiesUnavailableError( - 'Proxy support missing but proxy use was requested!') - msg = "getaddrinfo returns an empty list" - if self.proxy_info and self.proxy_info.isgood(): - use_proxy = True - proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass = self.proxy_info.astuple() - else: - use_proxy = False - if use_proxy and proxy_rdns: - host = proxy_host - port = proxy_port - else: - host = self.host - port = self.port - - for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - if use_proxy: - self.sock = socks.socksocket(af, socktype, proto) - self.sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass) - else: - self.sock = socket.socket(af, socktype, proto) - self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - # Different from httplib: support timeouts. - if has_timeout(self.timeout): - self.sock.settimeout(self.timeout) - # End of difference from httplib. - if self.debuglevel > 0: - print "connect: (%s, %s) ************" % (self.host, self.port) - if use_proxy: - print "proxy: %s ************" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - - self.sock.connect((self.host, self.port) + sa[2:]) - except socket.error, msg: - if self.debuglevel > 0: - print "connect fail: (%s, %s)" % (self.host, self.port) - if use_proxy: - print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg - -class HTTPSConnectionWithTimeout(httplib.HTTPSConnection): - """ - This class allows communication via SSL. - - All timeouts are in seconds. If None is passed for timeout then - Python's default timeout for sockets will be used. See for example - the docs of socket.setdefaulttimeout(): - http://docs.python.org/library/socket.html#socket.setdefaulttimeout - """ - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=None, proxy_info=None, - ca_certs=None, disable_ssl_certificate_validation=False): - httplib.HTTPSConnection.__init__(self, host, port=port, - key_file=key_file, - cert_file=cert_file, strict=strict) - self.timeout = timeout - self.proxy_info = proxy_info - if ca_certs is None: - ca_certs = CA_CERTS - self.ca_certs = ca_certs - self.disable_ssl_certificate_validation = \ - disable_ssl_certificate_validation - - # The following two methods were adapted from https_wrapper.py, released - # with the Google Appengine SDK at - # http://googleappengine.googlecode.com/svn-history/r136/trunk/python/google/appengine/tools/https_wrapper.py - # under the following license: - # - # Copyright 2007 Google Inc. - # - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. - # - - def _GetValidHostsForCert(self, cert): - """Returns a list of valid host globs for an SSL certificate. - - Args: - cert: A dictionary representing an SSL certificate. - Returns: - list: A list of valid host globs. - """ - if 'subjectAltName' in cert: - return [x[1] for x in cert['subjectAltName'] - if x[0].lower() == 'dns'] - else: - return [x[0][1] for x in cert['subject'] - if x[0][0].lower() == 'commonname'] - - def _ValidateCertificateHostname(self, cert, hostname): - """Validates that a given hostname is valid for an SSL certificate. - - Args: - cert: A dictionary representing an SSL certificate. - hostname: The hostname to test. - Returns: - bool: Whether or not the hostname is valid for this certificate. - """ - hosts = self._GetValidHostsForCert(cert) - for host in hosts: - host_re = host.replace('.', '\.').replace('*', '[^.]*') - if re.search('^%s$' % (host_re,), hostname, re.I): - return True - return False - - def connect(self): - "Connect to a host on a given (SSL) port." - - msg = "getaddrinfo returns an empty list" - if self.proxy_info and self.proxy_info.isgood(): - use_proxy = True - proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass = self.proxy_info.astuple() - else: - use_proxy = False - if use_proxy and proxy_rdns: - host = proxy_host - port = proxy_port - else: - host = self.host - port = self.port - - address_info = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM) - for family, socktype, proto, canonname, sockaddr in address_info: - try: - if use_proxy: - sock = socks.socksocket(family, socktype, proto) - - sock.setproxy(proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass) - else: - sock = socket.socket(family, socktype, proto) - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - - if has_timeout(self.timeout): - sock.settimeout(self.timeout) - sock.connect((self.host, self.port)) - self.sock =_ssl_wrap_socket( - sock, self.key_file, self.cert_file, - self.disable_ssl_certificate_validation, self.ca_certs) - if self.debuglevel > 0: - print "connect: (%s, %s)" % (self.host, self.port) - if use_proxy: - print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - if not self.disable_ssl_certificate_validation: - cert = self.sock.getpeercert() - hostname = self.host.split(':', 0)[0] - if not self._ValidateCertificateHostname(cert, hostname): - raise CertificateHostnameMismatch( - 'Server presented certificate that does not match ' - 'host %s: %s' % (hostname, cert), hostname, cert) - except ssl_SSLError, e: - if sock: - sock.close() - if self.sock: - self.sock.close() - self.sock = None - # Unfortunately the ssl module doesn't seem to provide any way - # to get at more detailed error information, in particular - # whether the error is due to certificate validation or - # something else (such as SSL protocol mismatch). - if e.errno == ssl.SSL_ERROR_SSL: - raise SSLHandshakeError(e) - else: - raise - except (socket.timeout, socket.gaierror): - raise - except socket.error, msg: - if self.debuglevel > 0: - print "connect fail: (%s, %s)" % (self.host, self.port) - if use_proxy: - print "proxy: %s" % str((proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass)) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg - -SCHEME_TO_CONNECTION = { - 'http': HTTPConnectionWithTimeout, - 'https': HTTPSConnectionWithTimeout -} - -# Use a different connection object for Google App Engine -try: - try: - from google.appengine.api import apiproxy_stub_map - if apiproxy_stub_map.apiproxy.GetStub('urlfetch') is None: - raise ImportError # Bail out; we're not actually running on App Engine. - from google.appengine.api.urlfetch import fetch - from google.appengine.api.urlfetch import InvalidURLError - except (ImportError, AttributeError): - from google3.apphosting.api import apiproxy_stub_map - if apiproxy_stub_map.apiproxy.GetStub('urlfetch') is None: - raise ImportError # Bail out; we're not actually running on App Engine. - from google3.apphosting.api.urlfetch import fetch - from google3.apphosting.api.urlfetch import InvalidURLError - - def _new_fixed_fetch(validate_certificate): - def fixed_fetch(url, payload=None, method="GET", headers={}, - allow_truncated=False, follow_redirects=True, - deadline=None): - if deadline is None: - deadline = socket.getdefaulttimeout() or 5 - return fetch(url, payload=payload, method=method, headers=headers, - allow_truncated=allow_truncated, - follow_redirects=follow_redirects, deadline=deadline, - validate_certificate=validate_certificate) - return fixed_fetch - - class AppEngineHttpConnection(httplib.HTTPConnection): - """Use httplib on App Engine, but compensate for its weirdness. - - The parameters key_file, cert_file, proxy_info, ca_certs, and - disable_ssl_certificate_validation are all dropped on the ground. - """ - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=None, proxy_info=None, ca_certs=None, - disable_ssl_certificate_validation=False): - httplib.HTTPConnection.__init__(self, host, port=port, - strict=strict, timeout=timeout) - - class AppEngineHttpsConnection(httplib.HTTPSConnection): - """Same as AppEngineHttpConnection, but for HTTPS URIs.""" - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=None, proxy_info=None, ca_certs=None, - disable_ssl_certificate_validation=False): - httplib.HTTPSConnection.__init__(self, host, port=port, - key_file=key_file, - cert_file=cert_file, strict=strict, - timeout=timeout) - self._fetch = _new_fixed_fetch( - not disable_ssl_certificate_validation) - - # Update the connection classes to use the Googel App Engine specific ones. - SCHEME_TO_CONNECTION = { - 'http': AppEngineHttpConnection, - 'https': AppEngineHttpsConnection - } -except (ImportError, AttributeError): - pass - - -class Http(object): - """An HTTP client that handles: - - - all methods - - caching - - ETags - - compression, - - HTTPS - - Basic - - Digest - - WSSE - - and more. - """ - def __init__(self, cache=None, timeout=None, - proxy_info=proxy_info_from_environment, - ca_certs=None, disable_ssl_certificate_validation=False): - """If 'cache' is a string then it is used as a directory name for - a disk cache. Otherwise it must be an object that supports the - same interface as FileCache. - - All timeouts are in seconds. If None is passed for timeout - then Python's default timeout for sockets will be used. See - for example the docs of socket.setdefaulttimeout(): - http://docs.python.org/library/socket.html#socket.setdefaulttimeout - - `proxy_info` may be: - - a callable that takes the http scheme ('http' or 'https') and - returns a ProxyInfo instance per request. By default, uses - proxy_nfo_from_environment. - - a ProxyInfo instance (static proxy config). - - None (proxy disabled). - - ca_certs is the path of a file containing root CA certificates for SSL - server certificate validation. By default, a CA cert file bundled with - httplib2 is used. - - If disable_ssl_certificate_validation is true, SSL cert validation will - not be performed. - """ - self.proxy_info = proxy_info - self.ca_certs = ca_certs - self.disable_ssl_certificate_validation = \ - disable_ssl_certificate_validation - - # Map domain name to an httplib connection - self.connections = {} - # The location of the cache, for now a directory - # where cached responses are held. - if cache and isinstance(cache, basestring): - self.cache = FileCache(cache) - else: - self.cache = cache - - # Name/password - self.credentials = Credentials() - - # Key/cert - self.certificates = KeyCerts() - - # authorization objects - self.authorizations = [] - - # If set to False then no redirects are followed, even safe ones. - self.follow_redirects = True - - # Which HTTP methods do we apply optimistic concurrency to, i.e. - # which methods get an "if-match:" etag header added to them. - self.optimistic_concurrency_methods = ["PUT", "PATCH"] - - # If 'follow_redirects' is True, and this is set to True then - # all redirecs are followed, including unsafe ones. - self.follow_all_redirects = False - - self.ignore_etag = False - - self.force_exception_to_status_code = False - - self.timeout = timeout - - # Keep Authorization: headers on a redirect. - self.forward_authorization_headers = False - - def __getstate__(self): - state_dict = copy.copy(self.__dict__) - # In case request is augmented by some foreign object such as - # credentials which handle auth - if 'request' in state_dict: - del state_dict['request'] - if 'connections' in state_dict: - del state_dict['connections'] - return state_dict - - def __setstate__(self, state): - self.__dict__.update(state) - self.connections = {} - - def _auth_from_challenge(self, host, request_uri, headers, response, content): - """A generator that creates Authorization objects - that can be applied to requests. - """ - challenges = _parse_www_authenticate(response, 'www-authenticate') - for cred in self.credentials.iter(host): - for scheme in AUTH_SCHEME_ORDER: - if challenges.has_key(scheme): - yield AUTH_SCHEME_CLASSES[scheme](cred, host, request_uri, headers, response, content, self) - - def add_credentials(self, name, password, domain=""): - """Add a name and password that will be used - any time a request requires authentication.""" - self.credentials.add(name, password, domain) - - def add_certificate(self, key, cert, domain): - """Add a key and cert that will be used - any time a request requires authentication.""" - self.certificates.add(key, cert, domain) - - def clear_credentials(self): - """Remove all the names and passwords - that are used for authentication""" - self.credentials.clear() - self.authorizations = [] - - def _conn_request(self, conn, request_uri, method, body, headers): - i = 0 - seen_bad_status_line = False - while i < RETRIES: - i += 1 - try: - if hasattr(conn, 'sock') and conn.sock is None: - conn.connect() - conn.request(method, request_uri, body, headers) - except socket.timeout: - raise - except socket.gaierror: - conn.close() - raise ServerNotFoundError("Unable to find the server at %s" % conn.host) - except ssl_SSLError: - conn.close() - raise - except socket.error, e: - err = 0 - if hasattr(e, 'args'): - err = getattr(e, 'args')[0] - else: - err = e.errno - if err == errno.ECONNREFUSED: # Connection refused - raise - except httplib.HTTPException: - # Just because the server closed the connection doesn't apparently mean - # that the server didn't send a response. - if hasattr(conn, 'sock') and conn.sock is None: - if i < RETRIES-1: - conn.close() - conn.connect() - continue - else: - conn.close() - raise - if i < RETRIES-1: - conn.close() - conn.connect() - continue - try: - response = conn.getresponse() - except httplib.BadStatusLine: - # If we get a BadStatusLine on the first try then that means - # the connection just went stale, so retry regardless of the - # number of RETRIES set. - if not seen_bad_status_line and i == 1: - i = 0 - seen_bad_status_line = True - conn.close() - conn.connect() - continue - else: - conn.close() - raise - except (socket.error, httplib.HTTPException): - if i < RETRIES-1: - conn.close() - conn.connect() - continue - else: - conn.close() - raise - else: - content = "" - if method == "HEAD": - conn.close() - else: - content = response.read() - response = Response(response) - if method != "HEAD": - content = _decompressContent(response, content) - break - return (response, content) - - - def _request(self, conn, host, absolute_uri, request_uri, method, body, headers, redirections, cachekey): - """Do the actual request using the connection object - and also follow one level of redirects if necessary""" - - auths = [(auth.depth(request_uri), auth) for auth in self.authorizations if auth.inscope(host, request_uri)] - auth = auths and sorted(auths)[0][1] or None - if auth: - auth.request(method, request_uri, headers, body) - - (response, content) = self._conn_request(conn, request_uri, method, body, headers) - - if auth: - if auth.response(response, body): - auth.request(method, request_uri, headers, body) - (response, content) = self._conn_request(conn, request_uri, method, body, headers ) - response._stale_digest = 1 - - if response.status == 401: - for authorization in self._auth_from_challenge(host, request_uri, headers, response, content): - authorization.request(method, request_uri, headers, body) - (response, content) = self._conn_request(conn, request_uri, method, body, headers, ) - if response.status != 401: - self.authorizations.append(authorization) - authorization.response(response, body) - break - - if (self.follow_all_redirects or (method in ["GET", "HEAD"]) or response.status == 303): - if self.follow_redirects and response.status in [300, 301, 302, 303, 307]: - # Pick out the location header and basically start from the beginning - # remembering first to strip the ETag header and decrement our 'depth' - if redirections: - if not response.has_key('location') and response.status != 300: - raise RedirectMissingLocation( _("Redirected but the response is missing a Location: header."), response, content) - # Fix-up relative redirects (which violate an RFC 2616 MUST) - if response.has_key('location'): - location = response['location'] - (scheme, authority, path, query, fragment) = parse_uri(location) - if authority == None: - response['location'] = urlparse.urljoin(absolute_uri, location) - if response.status == 301 and method in ["GET", "HEAD"]: - response['-x-permanent-redirect-url'] = response['location'] - if not response.has_key('content-location'): - response['content-location'] = absolute_uri - _updateCache(headers, response, content, self.cache, cachekey) - if headers.has_key('if-none-match'): - del headers['if-none-match'] - if headers.has_key('if-modified-since'): - del headers['if-modified-since'] - if 'authorization' in headers and not self.forward_authorization_headers: - del headers['authorization'] - if response.has_key('location'): - location = response['location'] - old_response = copy.deepcopy(response) - if not old_response.has_key('content-location'): - old_response['content-location'] = absolute_uri - redirect_method = method - if response.status in [302, 303]: - redirect_method = "GET" - body = None - (response, content) = self.request( - location, method=redirect_method, - body=body, headers=headers, - redirections=redirections - 1) - response.previous = old_response - else: - raise RedirectLimit("Redirected more times than rediection_limit allows.", response, content) - elif response.status in [200, 203] and method in ["GET", "HEAD"]: - # Don't cache 206's since we aren't going to handle byte range requests - if not response.has_key('content-location'): - response['content-location'] = absolute_uri - _updateCache(headers, response, content, self.cache, cachekey) - - return (response, content) - - def _normalize_headers(self, headers): - return _normalize_headers(headers) - -# Need to catch and rebrand some exceptions -# Then need to optionally turn all exceptions into status codes -# including all socket.* and httplib.* exceptions. - - - def request(self, uri, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None): - """ Performs a single HTTP request. - - The 'uri' is the URI of the HTTP resource and can begin with either - 'http' or 'https'. The value of 'uri' must be an absolute URI. - - The 'method' is the HTTP method to perform, such as GET, POST, DELETE, - etc. There is no restriction on the methods allowed. - - The 'body' is the entity body to be sent with the request. It is a - string object. - - Any extra headers that are to be sent with the request should be - provided in the 'headers' dictionary. - - The maximum number of redirect to follow before raising an - exception is 'redirections. The default is 5. - - The return value is a tuple of (response, content), the first - being and instance of the 'Response' class, the second being - a string that contains the response entity body. - """ - try: - if headers is None: - headers = {} - else: - headers = self._normalize_headers(headers) - - if not headers.has_key('user-agent'): - headers['user-agent'] = "Python-httplib2/%s (gzip)" % __version__ - - uri = iri2uri(uri) - - (scheme, authority, request_uri, defrag_uri) = urlnorm(uri) - domain_port = authority.split(":")[0:2] - if len(domain_port) == 2 and domain_port[1] == '443' and scheme == 'http': - scheme = 'https' - authority = domain_port[0] - - proxy_info = self._get_proxy_info(scheme, authority) - - conn_key = scheme+":"+authority - if conn_key in self.connections: - conn = self.connections[conn_key] - else: - if not connection_type: - connection_type = SCHEME_TO_CONNECTION[scheme] - certs = list(self.certificates.iter(authority)) - if scheme == 'https': - if certs: - conn = self.connections[conn_key] = connection_type( - authority, key_file=certs[0][0], - cert_file=certs[0][1], timeout=self.timeout, - proxy_info=proxy_info, - ca_certs=self.ca_certs, - disable_ssl_certificate_validation= - self.disable_ssl_certificate_validation) - else: - conn = self.connections[conn_key] = connection_type( - authority, timeout=self.timeout, - proxy_info=proxy_info, - ca_certs=self.ca_certs, - disable_ssl_certificate_validation= - self.disable_ssl_certificate_validation) - else: - conn = self.connections[conn_key] = connection_type( - authority, timeout=self.timeout, - proxy_info=proxy_info) - conn.set_debuglevel(debuglevel) - - if 'range' not in headers and 'accept-encoding' not in headers: - headers['accept-encoding'] = 'gzip, deflate' - - info = email.Message.Message() - cached_value = None - if self.cache: - cachekey = defrag_uri - cached_value = self.cache.get(cachekey) - if cached_value: - # info = email.message_from_string(cached_value) - # - # Need to replace the line above with the kludge below - # to fix the non-existent bug not fixed in this - # bug report: http://mail.python.org/pipermail/python-bugs-list/2005-September/030289.html - try: - info, content = cached_value.split('\r\n\r\n', 1) - feedparser = email.FeedParser.FeedParser() - feedparser.feed(info) - info = feedparser.close() - feedparser._parse = None - except (IndexError, ValueError): - self.cache.delete(cachekey) - cachekey = None - cached_value = None - else: - cachekey = None - - if method in self.optimistic_concurrency_methods and self.cache and info.has_key('etag') and not self.ignore_etag and 'if-match' not in headers: - # http://www.w3.org/1999/04/Editing/ - headers['if-match'] = info['etag'] - - if method not in ["GET", "HEAD"] and self.cache and cachekey: - # RFC 2616 Section 13.10 - self.cache.delete(cachekey) - - # Check the vary header in the cache to see if this request - # matches what varies in the cache. - if method in ['GET', 'HEAD'] and 'vary' in info: - vary = info['vary'] - vary_headers = vary.lower().replace(' ', '').split(',') - for header in vary_headers: - key = '-varied-%s' % header - value = info[key] - if headers.get(header, None) != value: - cached_value = None - break - - if cached_value and method in ["GET", "HEAD"] and self.cache and 'range' not in headers: - if info.has_key('-x-permanent-redirect-url'): - # Should cached permanent redirects be counted in our redirection count? For now, yes. - if redirections <= 0: - raise RedirectLimit("Redirected more times than rediection_limit allows.", {}, "") - (response, new_content) = self.request( - info['-x-permanent-redirect-url'], method='GET', - headers=headers, redirections=redirections - 1) - response.previous = Response(info) - response.previous.fromcache = True - else: - # Determine our course of action: - # Is the cached entry fresh or stale? - # Has the client requested a non-cached response? - # - # There seems to be three possible answers: - # 1. [FRESH] Return the cache entry w/o doing a GET - # 2. [STALE] Do the GET (but add in cache validators if available) - # 3. [TRANSPARENT] Do a GET w/o any cache validators (Cache-Control: no-cache) on the request - entry_disposition = _entry_disposition(info, headers) - - if entry_disposition == "FRESH": - if not cached_value: - info['status'] = '504' - content = "" - response = Response(info) - if cached_value: - response.fromcache = True - return (response, content) - - if entry_disposition == "STALE": - if info.has_key('etag') and not self.ignore_etag and not 'if-none-match' in headers: - headers['if-none-match'] = info['etag'] - if info.has_key('last-modified') and not 'last-modified' in headers: - headers['if-modified-since'] = info['last-modified'] - elif entry_disposition == "TRANSPARENT": - pass - - (response, new_content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) - - if response.status == 304 and method == "GET": - # Rewrite the cache entry with the new end-to-end headers - # Take all headers that are in response - # and overwrite their values in info. - # unless they are hop-by-hop, or are listed in the connection header. - - for key in _get_end2end_headers(response): - info[key] = response[key] - merged_response = Response(info) - if hasattr(response, "_stale_digest"): - merged_response._stale_digest = response._stale_digest - _updateCache(headers, merged_response, content, self.cache, cachekey) - response = merged_response - response.status = 200 - response.fromcache = True - - elif response.status == 200: - content = new_content - else: - self.cache.delete(cachekey) - content = new_content - else: - cc = _parse_cache_control(headers) - if cc.has_key('only-if-cached'): - info['status'] = '504' - response = Response(info) - content = "" - else: - (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) - except Exception, e: - if self.force_exception_to_status_code: - if isinstance(e, HttpLib2ErrorWithResponse): - response = e.response - content = e.content - response.status = 500 - response.reason = str(e) - elif isinstance(e, socket.timeout): - content = "Request Timeout" - response = Response({ - "content-type": "text/plain", - "status": "408", - "content-length": len(content) - }) - response.reason = "Request Timeout" - else: - content = str(e) - response = Response({ - "content-type": "text/plain", - "status": "400", - "content-length": len(content) - }) - response.reason = "Bad Request" - else: - raise - - - return (response, content) - - def _get_proxy_info(self, scheme, authority): - """Return a ProxyInfo instance (or None) based on the scheme - and authority. - """ - hostname, port = urllib.splitport(authority) - proxy_info = self.proxy_info - if callable(proxy_info): - proxy_info = proxy_info(scheme) - - if (hasattr(proxy_info, 'applies_to') - and not proxy_info.applies_to(hostname)): - proxy_info = None - return proxy_info - - -class Response(dict): - """An object more like email.Message than httplib.HTTPResponse.""" - - """Is this response from our local cache""" - fromcache = False - - """HTTP protocol version used by server. 10 for HTTP/1.0, 11 for HTTP/1.1. """ - version = 11 - - "Status code returned by server. " - status = 200 - - """Reason phrase returned by server.""" - reason = "Ok" - - previous = None - - def __init__(self, info): - # info is either an email.Message or - # an httplib.HTTPResponse object. - if isinstance(info, httplib.HTTPResponse): - for key, value in info.getheaders(): - self[key.lower()] = value - self.status = info.status - self['status'] = str(self.status) - self.reason = info.reason - self.version = info.version - elif isinstance(info, email.Message.Message): - for key, value in info.items(): - self[key.lower()] = value - self.status = int(self['status']) - else: - for key, value in info.iteritems(): - self[key.lower()] = value - self.status = int(self.get('status', self.status)) - self.reason = self.get('reason', self.reason) - - - def __getattr__(self, name): - if name == 'dict': - return self - else: - raise AttributeError, name diff --git a/awx/lib/site-packages/httplib2/cacerts.txt b/awx/lib/site-packages/httplib2/cacerts.txt deleted file mode 100644 index 70990f1f82..0000000000 --- a/awx/lib/site-packages/httplib2/cacerts.txt +++ /dev/null @@ -1,2183 +0,0 @@ -# Issuer: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. -# Subject: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc. -# Label: "GTE CyberTrust Global Root" -# Serial: 421 -# MD5 Fingerprint: ca:3d:d3:68:f1:03:5c:d0:32:fa:b8:2b:59:e8:5a:db -# SHA1 Fingerprint: 97:81:79:50:d8:1c:96:70:cc:34:d8:09:cf:79:44:31:36:7e:f4:74 -# SHA256 Fingerprint: a5:31:25:18:8d:21:10:aa:96:4b:02:c7:b7:c6:da:32:03:17:08:94:e5:fb:71:ff:fb:66:67:d5:e6:81:0a:36 ------BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv -bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv -b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU -cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds -b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH -iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS -r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 -04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r -GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 -3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P -lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ ------END CERTIFICATE----- - -# Issuer: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division -# Subject: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division -# Label: "Thawte Server CA" -# Serial: 1 -# MD5 Fingerprint: c5:70:c4:a2:ed:53:78:0c:c8:10:53:81:64:cb:d0:1d -# SHA1 Fingerprint: 23:e5:94:94:51:95:f2:41:48:03:b4:d5:64:d2:a3:a3:f5:d8:8b:8c -# SHA256 Fingerprint: b4:41:0b:73:e2:e6:ea:ca:47:fb:c4:2f:8f:a4:01:8a:f4:38:1d:c5:4c:fa:a8:44:50:46:1e:ed:09:45:4d:e9 ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm -MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx -MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 -dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl -cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 -DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD -gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 -yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX -L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj -EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG -7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e -QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ -qdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- - -# Issuer: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division -# Subject: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division -# Label: "Thawte Premium Server CA" -# Serial: 1 -# MD5 Fingerprint: 06:9f:69:79:16:66:90:02:1b:8c:8c:a2:c3:07:6f:3a -# SHA1 Fingerprint: 62:7f:8d:78:27:65:63:99:d2:7d:7f:90:44:c9:fe:b3:f3:3e:fa:9a -# SHA256 Fingerprint: ab:70:36:36:5c:71:54:aa:29:c2:c2:9f:5d:41:91:16:3b:16:2a:22:25:01:13:57:d5:6d:07:ff:a7:bc:1f:72 ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy -dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t -MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB -MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG -A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl -cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv -bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE -VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ -ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR -uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG -9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI -hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM -pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- - -# Issuer: O=Equifax OU=Equifax Secure Certificate Authority -# Subject: O=Equifax OU=Equifax Secure Certificate Authority -# Label: "Equifax Secure CA" -# Serial: 903804111 -# MD5 Fingerprint: 67:cb:9d:c0:13:24:8a:82:9b:b2:17:1e:d1:1b:ec:d4 -# SHA1 Fingerprint: d2:32:09:ad:23:d3:14:23:21:74:e4:0d:7f:9d:62:13:97:86:63:3a -# SHA256 Fingerprint: 08:29:7a:40:47:db:a2:36:80:c7:31:db:6e:31:76:53:ca:78:48:e1:be:bd:3a:0b:01:79:a7:07:f9:2c:f1:78 ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy -dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 -MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx -dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f -BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A -cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ -MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm -aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw -ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y -7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh -1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 ------END CERTIFICATE----- - -# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Label: "Verisign Class 3 Public Primary Certification Authority" -# Serial: 149843929435818692848040365716851702463 -# MD5 Fingerprint: 10:fc:63:5d:f6:26:3e:0d:f3:25:be:5f:79:cd:67:67 -# SHA1 Fingerprint: 74:2c:31:92:e6:07:e4:24:eb:45:49:54:2b:e1:bb:c5:3e:61:74:e2 -# SHA256 Fingerprint: e7:68:56:34:ef:ac:f6:9a:ce:93:9a:6b:25:5b:7b:4f:ab:ef:42:93:5b:50:a2:65:ac:b5:cb:60:27:e4:4e:70 ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do -lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc -AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k ------END CERTIFICATE----- - -# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network -# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network -# Label: "Verisign Class 3 Public Primary Certification Authority - G2" -# Serial: 167285380242319648451154478808036881606 -# MD5 Fingerprint: a2:33:9b:4c:74:78:73:d4:6c:e7:c1:f3:8d:cb:5c:e9 -# SHA1 Fingerprint: 85:37:1c:a6:e5:50:14:3d:ce:28:03:47:1b:de:3a:09:e8:f8:77:0f -# SHA256 Fingerprint: 83:ce:3c:12:29:68:8a:59:3d:48:5f:81:97:3c:0f:91:95:43:1e:da:37:cc:5e:36:43:0e:79:c7:a8:88:63:8b ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 -pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 -13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk -U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i -F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY -oJ2daZH9 ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA -# Label: "GlobalSign Root CA" -# Serial: 4835703278459707669005204 -# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a -# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c -# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 ------BEGIN CERTIFICATE----- -MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 -# Label: "GlobalSign Root CA - R2" -# Serial: 4835703278459682885658125 -# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 -# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe -# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- - -# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority -# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority -# Label: "ValiCert Class 1 VA" -# Serial: 1 -# MD5 Fingerprint: 65:58:ab:15:ad:57:6c:1e:a8:a7:b5:69:ac:bf:ff:eb -# SHA1 Fingerprint: e5:df:74:3c:b6:01:c4:9b:98:43:dc:ab:8c:e8:6a:81:10:9f:e4:8e -# SHA256 Fingerprint: f4:c1:49:55:1a:30:13:a3:5b:c7:bf:fe:17:a7:f3:44:9b:c1:ab:5b:5a:0a:e7:4b:06:c2:3b:90:00:4c:01:04 ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy -NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y -LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ -TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y -TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 -LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW -I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw -nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI ------END CERTIFICATE----- - -# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority -# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority -# Label: "ValiCert Class 2 VA" -# Serial: 1 -# MD5 Fingerprint: a9:23:75:9b:ba:49:36:6e:31:c2:db:f2:e7:66:ba:87 -# SHA1 Fingerprint: 31:7a:2a:d0:7f:2b:33:5e:f5:a1:c3:4e:4b:57:e8:b7:d8:f1:fc:a6 -# SHA256 Fingerprint: 58:d0:17:27:9c:d4:dc:63:ab:dd:b1:96:a6:c9:90:6c:30:c4:e0:87:83:ea:e8:c1:60:99:54:d6:93:55:59:6b ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy -NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY -dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 -WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS -v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v -UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu -IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC -W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd ------END CERTIFICATE----- - -# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority -# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority -# Label: "RSA Root Certificate 1" -# Serial: 1 -# MD5 Fingerprint: a2:6f:53:b7:ee:40:db:4a:68:e7:fa:18:d9:10:4b:72 -# SHA1 Fingerprint: 69:bd:8c:f4:9c:d3:00:fb:59:2e:17:93:ca:55:6a:f3:ec:aa:35:fb -# SHA256 Fingerprint: bc:23:f9:8a:31:3c:b9:2d:e3:bb:fc:3a:5a:9f:44:61:ac:39:49:4c:4a:e1:5a:9e:9d:f1:31:e9:9b:73:01:9a ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy -NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD -cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs -2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY -JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE -Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ -n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A -PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Label: "Verisign Class 3 Public Primary Certification Authority - G3" -# Serial: 206684696279472310254277870180966723415 -# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 -# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 -# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only -# Label: "Verisign Class 4 Public Primary Certification Authority - G3" -# Serial: 314531972711909413743075096039378935511 -# MD5 Fingerprint: db:c8:f2:27:2e:b1:ea:6a:29:23:5d:fe:56:3e:33:df -# SHA1 Fingerprint: c8:ec:8c:87:92:69:cb:4b:ab:39:e9:8d:7e:57:67:f3:14:95:73:9d -# SHA256 Fingerprint: e3:89:36:0d:0f:db:ae:b3:d2:50:58:4b:47:30:31:4e:22:2f:39:c1:56:a0:20:14:4e:8d:96:05:61:79:15:06 ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 -GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ -+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd -U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm -NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY -ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ -ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 -CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq -g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c -2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ -bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- - -# Issuer: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Subject: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Label: "Entrust.net Secure Server CA" -# Serial: 927650371 -# MD5 Fingerprint: df:f2:80:73:cc:f1:e6:61:73:fc:f5:42:e9:c5:7c:ee -# SHA1 Fingerprint: 99:a6:9b:e6:1a:fe:88:6b:4d:2b:82:00:7c:b8:54:fc:31:7e:15:39 -# SHA256 Fingerprint: 62:f2:40:27:8c:56:4c:4d:d8:bf:7d:9d:4f:6f:36:6e:a8:94:d2:2f:5f:34:d9:89:a9:83:ac:ec:2f:ff:ed:50 ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 -MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE -ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j -b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg -U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ -I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 -wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC -AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb -oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 -BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 -MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi -E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa -MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI -hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN -95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd -2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= ------END CERTIFICATE----- - -# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited -# Label: "Entrust.net Premium 2048 Secure Server CA" -# Serial: 946059622 -# MD5 Fingerprint: ba:21:ea:20:d6:dd:db:8f:c1:57:8b:40:ad:a1:fc:fc -# SHA1 Fingerprint: 80:1d:62:d0:7b:44:9d:5c:5c:03:5c:98:ea:61:fa:44:3c:2a:58:fe -# SHA256 Fingerprint: d1:c3:39:ea:27:84:eb:87:0f:93:4f:c5:63:4e:4a:a9:ad:55:05:01:64:01:f2:64:65:d3:7a:57:46:63:35:9f ------BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy -MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA -vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G -CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA -WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo -oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ -h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 -f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN -B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy -vUxFnmG6v4SBkgPR0ml8xQ== ------END CERTIFICATE----- - -# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust -# Label: "Baltimore CyberTrust Root" -# Serial: 33554617 -# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 -# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 -# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- - -# Issuer: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. -# Subject: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc. -# Label: "Equifax Secure Global eBusiness CA" -# Serial: 1 -# MD5 Fingerprint: 8f:5d:77:06:27:c4:98:3c:5b:93:78:e7:d7:7d:9b:cc -# SHA1 Fingerprint: 7e:78:4a:10:1c:82:65:cc:2d:e1:f1:6d:47:b4:40:ca:d9:0a:19:45 -# SHA256 Fingerprint: 5f:0b:62:ea:b5:e3:53:ea:65:21:65:16:58:fb:b6:53:59:f4:43:28:0a:4a:fb:d1:04:d7:7d:10:f9:f0:4c:07 ------BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT -ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw -MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj -dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l -c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC -UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc -58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ -o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr -aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA -A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA -Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv -8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV ------END CERTIFICATE----- - -# Issuer: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. -# Subject: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc. -# Label: "Equifax Secure eBusiness CA 1" -# Serial: 4 -# MD5 Fingerprint: 64:9c:ef:2e:44:fc:c6:8f:52:07:d0:51:73:8f:cb:3d -# SHA1 Fingerprint: da:40:18:8b:91:89:a3:ed:ee:ae:da:97:fe:2f:9d:f5:b7:d1:8a:41 -# SHA256 Fingerprint: cf:56:ff:46:a4:a1:86:10:9d:d9:65:84:b5:ee:b5:8a:51:0c:42:75:b0:e5:f9:4f:40:bb:ae:86:5e:19:f6:73 ------BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT -ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw -MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j -LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo -RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu -WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw -Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD -AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK -eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM -zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ -WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN -/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== ------END CERTIFICATE----- - -# Issuer: O=Equifax Secure OU=Equifax Secure eBusiness CA-2 -# Subject: O=Equifax Secure OU=Equifax Secure eBusiness CA-2 -# Label: "Equifax Secure eBusiness CA 2" -# Serial: 930140085 -# MD5 Fingerprint: aa:bf:bf:64:97:da:98:1d:6f:c6:08:3a:95:70:33:ca -# SHA1 Fingerprint: 39:4f:f6:85:0b:06:be:52:e5:18:56:cc:10:e1:80:e8:82:b3:85:cc -# SHA256 Fingerprint: 2f:27:4e:48:ab:a4:ac:7b:76:59:33:10:17:75:50:6d:c3:0e:e3:8e:f6:ac:d5:c0:49:32:cf:e0:41:23:42:20 ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj -dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 -NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD -VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G -vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ -BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl -IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw -NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq -y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy -0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 -E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN ------END CERTIFICATE----- - -# Issuer: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network -# Subject: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network -# Label: "AddTrust Low-Value Services Root" -# Serial: 1 -# MD5 Fingerprint: 1e:42:95:02:33:92:6b:b9:5f:c0:7f:da:d6:b2:4b:fc -# SHA1 Fingerprint: cc:ab:0e:a0:4c:23:01:d6:69:7b:dd:37:9f:cd:12:eb:24:e3:94:9d -# SHA256 Fingerprint: 8c:72:09:27:9a:c0:4e:27:5e:16:d0:7f:d3:b7:75:e8:01:54:b5:96:80:46:e3:1f:52:dd:25:76:63:24:e9:a7 ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw -MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD -VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA -A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul -CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n -tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl -dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch -PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC -+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O -BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E -BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl -MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk -ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB -IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X -7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz -43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl -pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA -WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= ------END CERTIFICATE----- - -# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network -# Label: "AddTrust External Root" -# Serial: 1 -# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f -# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 -# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- - -# Issuer: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network -# Subject: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network -# Label: "AddTrust Public Services Root" -# Serial: 1 -# MD5 Fingerprint: c1:62:3e:23:c5:82:73:9c:03:59:4b:2b:e9:77:49:7f -# SHA1 Fingerprint: 2a:b6:28:48:5e:78:fb:f3:ad:9e:79:10:dd:6b:df:99:72:2c:96:e5 -# SHA256 Fingerprint: 07:91:ca:07:49:b2:07:82:aa:d3:c7:d7:bd:0c:df:c9:48:58:35:84:3e:b2:d7:99:60:09:ce:43:ab:6c:69:27 ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx -MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB -ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV -BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV -6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX -GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP -dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH -1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF -62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW -BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL -MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU -cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv -b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 -IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ -iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh -4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm -XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= ------END CERTIFICATE----- - -# Issuer: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network -# Subject: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network -# Label: "AddTrust Qualified Certificates Root" -# Serial: 1 -# MD5 Fingerprint: 27:ec:39:47:cd:da:5a:af:e2:9a:01:65:21:a9:4c:bb -# SHA1 Fingerprint: 4d:23:78:ec:91:95:39:b5:00:7f:75:8f:03:3b:21:1e:c5:4d:8b:cf -# SHA256 Fingerprint: 80:95:21:08:05:db:4b:bc:35:5e:44:28:d8:fd:6e:c2:cd:e3:ab:5f:b9:7a:99:42:98:8e:b8:f4:dc:d0:60:16 ------BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 -b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 -MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK -EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh -BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq -xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G -87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i -2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U -WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 -0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G -A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr -pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL -ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm -aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv -hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm -hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 -P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y -iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no -xqE= ------END CERTIFICATE----- - -# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. -# Label: "Entrust Root Certification Authority" -# Serial: 1164660820 -# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 -# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 -# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c ------BEGIN CERTIFICATE----- -MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 -Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW -KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw -NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw -NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy -ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV -BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo -Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 -4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 -KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI -rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi -94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB -sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi -gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo -kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE -vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA -A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t -O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua -AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP -9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ -eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m -0vdXcDazv/wor3ElhVsT/h5/WrQ8 ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. -# Label: "GeoTrust Global CA" -# Serial: 144470 -# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 -# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 -# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Global CA 2 O=GeoTrust Inc. -# Subject: CN=GeoTrust Global CA 2 O=GeoTrust Inc. -# Label: "GeoTrust Global CA 2" -# Serial: 1 -# MD5 Fingerprint: 0e:40:a7:6c:de:03:5d:8f:d1:0f:e4:d1:8d:f9:6c:a9 -# SHA1 Fingerprint: a9:e9:78:08:14:37:58:88:f2:05:19:b0:6d:2b:0d:2b:60:16:90:7d -# SHA256 Fingerprint: ca:2d:82:a0:86:77:07:2f:8a:b6:76:4f:f0:35:67:6c:fe:3e:5e:32:5e:01:21:72:df:3f:92:09:6d:b7:9b:85 ------BEGIN CERTIFICATE----- -MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs -IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg -R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A -PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 -Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL -TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL -5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 -S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe -2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap -EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td -EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv -/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN -A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 -abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF -I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz -4iIprn2DQKi6bA== ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Label: "GeoTrust Universal CA" -# Serial: 1 -# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 -# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 -# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Label: "GeoTrust Universal CA 2" -# Serial: 1 -# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 -# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 -# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- - -# Issuer: CN=America Online Root Certification Authority 1 O=America Online Inc. -# Subject: CN=America Online Root Certification Authority 1 O=America Online Inc. -# Label: "America Online Root Certification Authority 1" -# Serial: 1 -# MD5 Fingerprint: 14:f1:08:ad:9d:fa:64:e2:89:e7:1c:cf:a8:ad:7d:5e -# SHA1 Fingerprint: 39:21:c1:15:c1:5d:0e:ca:5c:cb:5b:c4:f0:7d:21:d8:05:0b:56:6a -# SHA256 Fingerprint: 77:40:73:12:c6:3a:15:3d:5b:c0:0b:4e:51:75:9c:df:da:c2:37:dc:2a:33:b6:79:46:e9:8e:9b:fa:68:0a:e3 ------BEGIN CERTIFICATE----- -MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk -hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym -1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW -OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb -2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko -O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU -AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF -Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb -LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir -oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C -MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds -sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 ------END CERTIFICATE----- - -# Issuer: CN=America Online Root Certification Authority 2 O=America Online Inc. -# Subject: CN=America Online Root Certification Authority 2 O=America Online Inc. -# Label: "America Online Root Certification Authority 2" -# Serial: 1 -# MD5 Fingerprint: d6:ed:3c:ca:e2:66:0f:af:10:43:0d:77:9b:04:09:bf -# SHA1 Fingerprint: 85:b5:ff:67:9b:0c:79:96:1f:c8:6e:44:22:00:46:13:db:17:92:84 -# SHA256 Fingerprint: 7d:3b:46:5a:60:14:e5:26:c0:af:fc:ee:21:27:d2:31:17:27:ad:81:1c:26:84:2d:00:6a:f3:73:06:cc:80:bd ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP -bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 -MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft -ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC -206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci -KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 -JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 -BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e -Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B -PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 -Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq -Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ -o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 -+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj -FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn -xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 -LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc -obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 -CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe -IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA -DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F -AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX -Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb -AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl -Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw -RY8mkaKO/qk= ------END CERTIFICATE----- - -# Issuer: CN=AAA Certificate Services O=Comodo CA Limited -# Subject: CN=AAA Certificate Services O=Comodo CA Limited -# Label: "Comodo AAA Services root" -# Serial: 1 -# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 -# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 -# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 ------BEGIN CERTIFICATE----- -MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj -YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM -GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua -BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe -3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 -YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR -rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm -ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU -oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v -QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t -b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF -AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q -GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz -Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 -G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi -l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 -smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== ------END CERTIFICATE----- - -# Issuer: CN=Secure Certificate Services O=Comodo CA Limited -# Subject: CN=Secure Certificate Services O=Comodo CA Limited -# Label: "Comodo Secure Services root" -# Serial: 1 -# MD5 Fingerprint: d3:d9:bd:ae:9f:ac:67:24:b3:c8:1b:52:e1:b9:a9:bd -# SHA1 Fingerprint: 4a:65:d5:f4:1d:ef:39:b8:b8:90:4a:4a:d3:64:81:33:cf:c7:a1:d1 -# SHA256 Fingerprint: bd:81:ce:3b:4f:65:91:d1:1a:67:b5:fc:7a:47:fd:ef:25:52:1b:f9:aa:4e:18:b9:e3:df:2e:34:a7:80:3b:e8 ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp -ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow -fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV -BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM -cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S -HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 -CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk -3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz -6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV -HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud -EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv -Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw -Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww -DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 -5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI -gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ -aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl -izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= ------END CERTIFICATE----- - -# Issuer: CN=Trusted Certificate Services O=Comodo CA Limited -# Subject: CN=Trusted Certificate Services O=Comodo CA Limited -# Label: "Comodo Trusted Services root" -# Serial: 1 -# MD5 Fingerprint: 91:1b:3f:6e:cd:9e:ab:ee:07:fe:1f:71:d2:b3:61:27 -# SHA1 Fingerprint: e1:9f:e3:0e:8b:84:60:9e:80:9b:17:0d:72:a8:c5:ba:6e:14:09:bd -# SHA256 Fingerprint: 3f:06:e5:56:81:d4:96:f5:be:16:9e:b5:38:9f:9f:2b:8f:f6:1e:17:08:df:68:81:72:48:49:cd:5d:27:cb:69 ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb -MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow -GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 -aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla -MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO -BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD -VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW -fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt -TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL -fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW -1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 -kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G -A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v -ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo -dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu -Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ -HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS -jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ -xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn -dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- - -# Issuer: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com -# Subject: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com -# Label: "UTN DATACorp SGC Root CA" -# Serial: 91374294542884689855167577680241077609 -# MD5 Fingerprint: b3:a5:3e:77:21:6d:ac:4a:c0:c9:fb:d5:41:3d:ca:06 -# SHA1 Fingerprint: 58:11:9f:0e:12:82:87:ea:50:fd:d9:87:45:6f:4f:78:dc:fa:d6:d4 -# SHA256 Fingerprint: 85:fb:2f:91:dd:12:27:5a:01:45:b6:36:53:4f:84:02:4a:d6:8b:69:b8:ee:88:68:4f:f7:11:37:58:05:b3:48 ------BEGIN CERTIFICATE----- -MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB -kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw -IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG -EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD -VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu -dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 -E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ -D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK -4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq -lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW -bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB -o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT -MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js -LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr -BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB -AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft -Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj -j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH -KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv -2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 -mfnGV/TJVTl4uix5yaaIK/QI ------END CERTIFICATE----- - -# Issuer: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com -# Subject: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com -# Label: "UTN USERFirst Hardware Root CA" -# Serial: 91374294542884704022267039221184531197 -# MD5 Fingerprint: 4c:56:41:e5:0d:bb:2b:e8:ca:a3:ed:18:08:ad:43:39 -# SHA1 Fingerprint: 04:83:ed:33:99:ac:36:08:05:87:22:ed:bc:5e:46:00:e3:be:f9:d7 -# SHA256 Fingerprint: 6e:a5:47:41:d0:04:66:7e:ed:1b:48:16:63:4a:a3:a7:9e:6e:4b:96:95:0f:82:79:da:fc:8d:9b:d8:81:21:37 ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB -lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug -Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho -dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt -SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG -A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe -MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v -d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh -cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn -0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ -M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a -MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd -oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI -DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy -oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 -dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy -bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF -BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli -CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE -CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t -3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS -KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== ------END CERTIFICATE----- - -# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com -# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com -# Label: "XRamp Global CA Root" -# Serial: 107108908803651509692980124233745014957 -# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 -# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 -# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB -gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk -MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY -UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx -NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 -dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy -dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 -38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP -KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q -DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 -qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa -JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi -PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P -BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs -jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 -eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR -vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt -qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa -IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy -i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ -O+7ETPTsJ3xCwnR8gooJybQDJbw= ------END CERTIFICATE----- - -# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority -# Label: "Go Daddy Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 -# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 -# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 ------BEGIN CERTIFICATE----- -MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh -MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE -YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 -MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo -ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg -MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN -ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA -PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w -wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi -EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY -avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ -YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE -sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h -/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 -IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD -ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy -OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P -TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ -HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER -dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf -ReYNnyicsbkqWletNw+vHX/bvZ8= ------END CERTIFICATE----- - -# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority -# Label: "Starfield Class 2 CA" -# Serial: 0 -# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 -# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a -# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl -MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp -U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw -NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE -ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp -ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 -DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf -8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN -+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 -X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa -K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA -1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G -A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR -zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 -YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD -bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 -L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D -eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl -xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp -VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY -WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= ------END CERTIFICATE----- - -# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Label: "StartCom Certification Authority" -# Serial: 1 -# MD5 Fingerprint: 22:4d:8f:8a:fc:f7:35:c2:bb:57:34:90:7b:8b:22:16 -# SHA1 Fingerprint: 3e:2b:f7:f2:03:1b:96:f3:8c:e6:c4:d8:a8:5d:3e:2d:58:47:6a:0f -# SHA256 Fingerprint: c7:66:a9:be:f2:d4:07:1c:86:3a:31:aa:49:20:e8:13:b2:d1:98:60:8c:b7:b7:cf:e2:11:43:b8:36:df:09:ea ------BEGIN CERTIFICATE----- -MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root CA" -# Serial: 17154717934120587862167794914071425081 -# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 -# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 -# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root CA" -# Serial: 10944719598952040374951832963794454346 -# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e -# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 -# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 ------BEGIN CERTIFICATE----- -MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert High Assurance EV Root CA" -# Serial: 3553400076410547919724730734378100087 -# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a -# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 -# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Label: "GeoTrust Primary Certification Authority" -# Serial: 32798226551256963324313806436981982369 -# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf -# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 -# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA" -# Serial: 69529181992039203566298953787712940909 -# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 -# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 -# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" -# Serial: 33037644167568058970164719475676101450 -# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c -# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 -# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- - -# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO Certification Authority O=COMODO CA Limited -# Label: "COMODO Certification Authority" -# Serial: 104350513648249232941998508985834464573 -# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 -# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b -# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 ------BEGIN CERTIFICATE----- -MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB -gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV -BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw -MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl -YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P -RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 -UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI -2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 -Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp -+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ -DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O -nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW -/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g -PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u -QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY -SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv -IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ -RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 -zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd -BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB -ZQ== ------END CERTIFICATE----- - -# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. -# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. -# Label: "Network Solutions Certificate Authority" -# Serial: 116697915152937497490437556386812487904 -# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e -# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce -# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c ------BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi -MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV -UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO -ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz -c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP -OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl -mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF -BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 -qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw -gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu -bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp -dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 -6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ -h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH -/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN -pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- - -# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Label: "COMODO ECC Certification Authority" -# Serial: 41578283867086692638256921589707938090 -# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 -# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 -# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT -IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw -MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy -ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N -T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR -FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J -cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW -BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm -fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv -GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA -# Subject: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA -# Label: "TC TrustCenter Class 2 CA II" -# Serial: 941389028203453866782103406992443 -# MD5 Fingerprint: ce:78:33:5c:59:78:01:6e:18:ea:b9:36:a0:b9:2e:23 -# SHA1 Fingerprint: ae:50:83:ed:7c:f4:5c:bc:8f:61:c6:21:fe:68:5d:79:42:21:15:6e -# SHA256 Fingerprint: e6:b8:f8:76:64:85:f8:07:ae:7f:8d:ac:16:70:46:1f:07:c0:a1:3e:ef:3a:1f:f7:17:53:8d:7a:ba:d3:91:b4 ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf -tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg -uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J -XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK -8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 -5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 -kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS -GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt -ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 -au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV -hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI -dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA -# Subject: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA -# Label: "TC TrustCenter Class 3 CA II" -# Serial: 1506523511417715638772220530020799 -# MD5 Fingerprint: 56:5f:aa:80:61:12:17:f6:67:21:e6:2b:6d:61:56:8e -# SHA1 Fingerprint: 80:25:ef:f4:6e:70:c8:d4:72:24:65:84:fe:40:3b:8a:8d:6a:db:f5 -# SHA256 Fingerprint: 8d:a0:84:fc:f9:9c:e0:77:22:f8:9b:32:05:93:98:06:fa:5c:b8:11:e1:c8:13:f6:a1:08:c7:d3:36:b3:40:8e ------BEGIN CERTIFICATE----- -MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV -BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 -Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 -OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i -SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc -VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW -Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q -Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 -1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq -ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 -Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX -XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy -dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 -Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz -JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 -Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u -TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN -irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 -TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 -g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB -95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj -S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Subject: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Label: "TC TrustCenter Universal CA I" -# Serial: 601024842042189035295619584734726 -# MD5 Fingerprint: 45:e1:a5:72:c5:a9:36:64:40:9e:f5:e4:58:84:67:8c -# SHA1 Fingerprint: 6b:2f:34:ad:89:58:be:62:fd:b0:6b:5c:ce:bb:9d:d9:4f:4e:39:f3 -# SHA256 Fingerprint: eb:f3:c0:2a:87:89:b1:fb:7d:51:19:95:d6:63:b7:29:06:d9:13:ce:0d:5e:10:56:8a:8a:77:e2:58:61:67:e7 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx -MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg -R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD -VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR -JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T -fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu -jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z -wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ -fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD -VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G -CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 -7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn -8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs -ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT -ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ -2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY ------END CERTIFICATE----- - -# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc -# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc -# Label: "Cybertrust Global Root" -# Serial: 4835703278459682877484360 -# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 -# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 -# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 ------BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG -A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh -bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE -ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS -b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 -7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS -J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y -HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP -t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz -FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY -XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ -MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw -hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js -MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA -A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj -Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx -XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o -omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc -A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW -WL1WMRJOEcgh4LMRkWXbtKaIOM5V ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G3" -# Serial: 28809105769928564313984085209975885599 -# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 -# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd -# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB -mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT -MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ -BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 -BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz -+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm -hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn -5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W -JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL -DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC -huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB -AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB -zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN -kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH -SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G -spki4cErx5z481+oghLrGREt ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G2" -# Serial: 71758320672825410020661621085256472406 -# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f -# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 -# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp -IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi -BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw -MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig -YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v -dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ -BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 -papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K -DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 -KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox -XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G3" -# Serial: 127614157056681299805556476275995414779 -# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 -# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 -# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB -rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV -BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa -Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl -LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u -MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm -gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 -YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf -b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 -9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S -zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk -OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV -HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA -2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW -oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c -KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM -m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu -MdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G2" -# Serial: 80682863203381065782177908751794619243 -# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a -# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 -# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL -MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj -KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 -MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw -NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV -BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL -So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal -tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG -CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT -qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz -rD6ogRLQy7rQkgu2npaqBA+K ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Universal Root Certification Authority" -# Serial: 85209574734084581917763752644031726877 -# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 -# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 -# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB -vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W -ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 -IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y -IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh -bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF -9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH -H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H -LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN -/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT -rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw -WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs -exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 -sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ -seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz -4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ -BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR -lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 -7M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" -# Serial: 63143484348153506665311985501458640051 -# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 -# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a -# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp -U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg -SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln -biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm -GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve -fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ -aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj -aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW -kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC -4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga -FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- - -# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority -# Label: "Verisign Class 3 Public Primary Certification Authority" -# Serial: 80507572722862485515306429940691309246 -# MD5 Fingerprint: ef:5a:f1:33:ef:f1:cd:bb:51:02:ee:12:14:4b:96:c4 -# SHA1 Fingerprint: a1:db:63:93:91:6f:17:e4:18:55:09:40:04:15:c7:02:40:b0:ae:6b -# SHA256 Fingerprint: a4:b6:b3:99:6f:c2:f3:06:b3:fd:86:81:bd:63:41:3d:8c:50:09:cc:4f:a3:29:c2:cc:f0:e2:fa:1b:14:03:05 ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i -2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ -2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Label: "GlobalSign Root CA - R3" -# Serial: 4835703278459759426209954 -# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 -# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad -# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- - -# Issuer: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Subject: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA -# Label: "TC TrustCenter Universal CA III" -# Serial: 2010889993983507346460533407902964 -# MD5 Fingerprint: 9f:dd:db:ab:ff:8e:ff:45:21:5f:f0:6c:9d:8f:fe:2b -# SHA1 Fingerprint: 96:56:cd:7b:57:96:98:95:d0:e1:41:46:68:06:fb:b8:c6:11:06:87 -# SHA256 Fingerprint: 30:9b:4a:87:f6:ca:56:c9:31:69:aa:a9:9c:6d:98:88:54:d7:89:2b:d5:43:7e:2d:07:b2:9c:be:da:55:d3:5d ------BEGIN CERTIFICATE----- -MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL -MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV -BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1 -c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy -MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl -ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm -BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF -5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv -DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v -zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT -yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj -dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh -MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI -4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz -dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY -aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G -DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV -CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH -LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== ------END CERTIFICATE----- - -# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Label: "Go Daddy Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 -# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b -# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -4uJEvlz36hz1 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 -# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e -# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Services Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 -# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f -# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -sSi6 ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Commercial O=AffirmTrust -# Subject: CN=AffirmTrust Commercial O=AffirmTrust -# Label: "AffirmTrust Commercial" -# Serial: 8608355977964138876 -# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 -# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 -# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP -Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr -ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL -MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 -yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr -VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ -nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG -XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj -vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt -Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g -N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC -nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Networking O=AffirmTrust -# Subject: CN=AffirmTrust Networking O=AffirmTrust -# Label: "AffirmTrust Networking" -# Serial: 8957382827206547757 -# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f -# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f -# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz -dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL -MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp -cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y -YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua -kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL -QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp -6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG -yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i -QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ -KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO -tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu -QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ -Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u -olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 -x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium O=AffirmTrust -# Subject: CN=AffirmTrust Premium O=AffirmTrust -# Label: "AffirmTrust Premium" -# Serial: 7893706540734352110 -# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 -# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 -# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE -BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz -dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG -A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U -cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf -qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ -JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ -+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS -s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 -HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 -70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG -V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S -qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S -5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia -C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX -OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE -FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 -KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B -8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ -MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc -0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ -u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF -u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH -YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 -GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO -RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e -KeC2uAloGRwYQw== ------END CERTIFICATE----- - -# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust -# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust -# Label: "AffirmTrust Premium ECC" -# Serial: 8401224907861490260 -# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d -# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb -# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC -VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ -cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ -BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt -VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D -0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 -ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G -A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs -aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I -flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== ------END CERTIFICATE----- - -# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing -# Label: "StartCom Certification Authority" -# Serial: 45 -# MD5 Fingerprint: c9:3b:0d:84:41:fc:a4:76:79:23:08:57:de:10:19:16 -# SHA1 Fingerprint: a3:f1:33:3f:e2:42:bf:cf:c5:d1:4e:8f:39:42:98:40:68:10:d1:a0 -# SHA256 Fingerprint: e1:78:90:ee:09:a3:fb:f4:f4:8b:9c:41:4a:17:d6:37:b7:a5:06:47:e9:bc:75:23:22:72:7f:cc:17:42:a9:11 ------BEGIN CERTIFICATE----- -MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 -MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul -F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC -ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w -ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk -aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 -YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg -c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 -d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG -CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF -wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS -Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst -0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc -pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl -CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF -P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK -1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm -KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE -JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ -8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm -fyWl8kgAwKQB2j8= ------END CERTIFICATE----- - -# Issuer: CN=StartCom Certification Authority G2 O=StartCom Ltd. -# Subject: CN=StartCom Certification Authority G2 O=StartCom Ltd. -# Label: "StartCom Certification Authority G2" -# Serial: 59 -# MD5 Fingerprint: 78:4b:fb:9e:64:82:0a:d3:b8:4c:62:f3:64:f2:90:64 -# SHA1 Fingerprint: 31:f1:fd:68:22:63:20:ee:c6:3b:3f:9d:ea:4a:3e:53:7c:7c:39:17 -# SHA256 Fingerprint: c7:ba:65:67:de:93:a7:98:ae:1f:aa:79:1e:71:2d:37:8f:ae:1f:93:c4:39:7f:ea:44:1b:b7:cb:e6:fd:59:95 ------BEGIN CERTIFICATE----- -MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW -MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 -OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG -A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ -JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD -vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo -D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ -Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW -RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK -HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN -nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM -0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i -UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 -Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg -TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL -BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K -2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX -UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl -6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK -9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ -HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI -wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY -XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l -IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo -hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr -so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI ------END CERTIFICATE----- diff --git a/awx/lib/site-packages/httplib2/iri2uri.py b/awx/lib/site-packages/httplib2/iri2uri.py deleted file mode 100644 index d88c91fdfb..0000000000 --- a/awx/lib/site-packages/httplib2/iri2uri.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -iri2uri - -Converts an IRI to a URI. - -""" -__author__ = "Joe Gregorio (joe@bitworking.org)" -__copyright__ = "Copyright 2006, Joe Gregorio" -__contributors__ = [] -__version__ = "1.0.0" -__license__ = "MIT" -__history__ = """ -""" - -import urlparse - - -# Convert an IRI to a URI following the rules in RFC 3987 -# -# The characters we need to enocde and escape are defined in the spec: -# -# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD -# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF -# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD -# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD -# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD -# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD -# / %xD0000-DFFFD / %xE1000-EFFFD - -escape_range = [ - (0xA0, 0xD7FF), - (0xE000, 0xF8FF), - (0xF900, 0xFDCF), - (0xFDF0, 0xFFEF), - (0x10000, 0x1FFFD), - (0x20000, 0x2FFFD), - (0x30000, 0x3FFFD), - (0x40000, 0x4FFFD), - (0x50000, 0x5FFFD), - (0x60000, 0x6FFFD), - (0x70000, 0x7FFFD), - (0x80000, 0x8FFFD), - (0x90000, 0x9FFFD), - (0xA0000, 0xAFFFD), - (0xB0000, 0xBFFFD), - (0xC0000, 0xCFFFD), - (0xD0000, 0xDFFFD), - (0xE1000, 0xEFFFD), - (0xF0000, 0xFFFFD), - (0x100000, 0x10FFFD), -] - -def encode(c): - retval = c - i = ord(c) - for low, high in escape_range: - if i < low: - break - if i >= low and i <= high: - retval = "".join(["%%%2X" % ord(o) for o in c.encode('utf-8')]) - break - return retval - - -def iri2uri(uri): - """Convert an IRI to a URI. Note that IRIs must be - passed in a unicode strings. That is, do not utf-8 encode - the IRI before passing it into the function.""" - if isinstance(uri ,unicode): - (scheme, authority, path, query, fragment) = urlparse.urlsplit(uri) - authority = authority.encode('idna') - # For each character in 'ucschar' or 'iprivate' - # 1. encode as utf-8 - # 2. then %-encode each octet of that utf-8 - uri = urlparse.urlunsplit((scheme, authority, path, query, fragment)) - uri = "".join([encode(c) for c in uri]) - return uri - -if __name__ == "__main__": - import unittest - - class Test(unittest.TestCase): - - def test_uris(self): - """Test that URIs are invariant under the transformation.""" - invariant = [ - u"ftp://ftp.is.co.za/rfc/rfc1808.txt", - u"http://www.ietf.org/rfc/rfc2396.txt", - u"ldap://[2001:db8::7]/c=GB?objectClass?one", - u"mailto:John.Doe@example.com", - u"news:comp.infosystems.www.servers.unix", - u"tel:+1-816-555-1212", - u"telnet://192.0.2.16:80/", - u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ] - for uri in invariant: - self.assertEqual(uri, iri2uri(uri)) - - def test_iri(self): - """ Test that the right type of escaping is done for each part of the URI.""" - self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri(u"http://\N{COMET}.com/\N{COMET}")) - self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri(u"http://bitworking.org/?fred=\N{COMET}")) - self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri(u"http://bitworking.org/#\N{COMET}")) - self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))) - self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8'))) - - unittest.main() - - diff --git a/awx/lib/site-packages/httplib2/socks.py b/awx/lib/site-packages/httplib2/socks.py deleted file mode 100644 index 0991f4cf6e..0000000000 --- a/awx/lib/site-packages/httplib2/socks.py +++ /dev/null @@ -1,438 +0,0 @@ -"""SocksiPy - Python SOCKS module. -Version 1.00 - -Copyright 2006 Dan-Haim. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -3. Neither the name of Dan Haim nor the names of his contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE. - - -This module provides a standard socket-like interface for Python -for tunneling connections through SOCKS proxies. - -""" - -""" - -Minor modifications made by Christopher Gilbert (http://motomastyle.com/) -for use in PyLoris (http://pyloris.sourceforge.net/) - -Minor modifications made by Mario Vilas (http://breakingcode.wordpress.com/) -mainly to merge bug fixes found in Sourceforge - -""" - -import base64 -import socket -import struct -import sys - -if getattr(socket, 'socket', None) is None: - raise ImportError('socket.socket missing, proxy support unusable') - -PROXY_TYPE_SOCKS4 = 1 -PROXY_TYPE_SOCKS5 = 2 -PROXY_TYPE_HTTP = 3 -PROXY_TYPE_HTTP_NO_TUNNEL = 4 - -_defaultproxy = None -_orgsocket = socket.socket - -class ProxyError(Exception): pass -class GeneralProxyError(ProxyError): pass -class Socks5AuthError(ProxyError): pass -class Socks5Error(ProxyError): pass -class Socks4Error(ProxyError): pass -class HTTPError(ProxyError): pass - -_generalerrors = ("success", - "invalid data", - "not connected", - "not available", - "bad proxy type", - "bad input") - -_socks5errors = ("succeeded", - "general SOCKS server failure", - "connection not allowed by ruleset", - "Network unreachable", - "Host unreachable", - "Connection refused", - "TTL expired", - "Command not supported", - "Address type not supported", - "Unknown error") - -_socks5autherrors = ("succeeded", - "authentication is required", - "all offered authentication methods were rejected", - "unknown username or invalid password", - "unknown error") - -_socks4errors = ("request granted", - "request rejected or failed", - "request rejected because SOCKS server cannot connect to identd on the client", - "request rejected because the client program and identd report different user-ids", - "unknown error") - -def setdefaultproxy(proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): - """setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) - Sets a default proxy which all further socksocket objects will use, - unless explicitly changed. - """ - global _defaultproxy - _defaultproxy = (proxytype, addr, port, rdns, username, password) - -def wrapmodule(module): - """wrapmodule(module) - Attempts to replace a module's socket library with a SOCKS socket. Must set - a default proxy using setdefaultproxy(...) first. - This will only work on modules that import socket directly into the namespace; - most of the Python Standard Library falls into this category. - """ - if _defaultproxy != None: - module.socket.socket = socksocket - else: - raise GeneralProxyError((4, "no proxy specified")) - -class socksocket(socket.socket): - """socksocket([family[, type[, proto]]]) -> socket object - Open a SOCKS enabled socket. The parameters are the same as - those of the standard socket init. In order for SOCKS to work, - you must specify family=AF_INET, type=SOCK_STREAM and proto=0. - """ - - def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None): - _orgsocket.__init__(self, family, type, proto, _sock) - if _defaultproxy != None: - self.__proxy = _defaultproxy - else: - self.__proxy = (None, None, None, None, None, None) - self.__proxysockname = None - self.__proxypeername = None - self.__httptunnel = True - - def __recvall(self, count): - """__recvall(count) -> data - Receive EXACTLY the number of bytes requested from the socket. - Blocks until the required number of bytes have been received. - """ - data = self.recv(count) - while len(data) < count: - d = self.recv(count-len(data)) - if not d: raise GeneralProxyError((0, "connection closed unexpectedly")) - data = data + d - return data - - def sendall(self, content, *args): - """ override socket.socket.sendall method to rewrite the header - for non-tunneling proxies if needed - """ - if not self.__httptunnel: - content = self.__rewriteproxy(content) - return super(socksocket, self).sendall(content, *args) - - def __rewriteproxy(self, header): - """ rewrite HTTP request headers to support non-tunneling proxies - (i.e. those which do not support the CONNECT method). - This only works for HTTP (not HTTPS) since HTTPS requires tunneling. - """ - host, endpt = None, None - hdrs = header.split("\r\n") - for hdr in hdrs: - if hdr.lower().startswith("host:"): - host = hdr - elif hdr.lower().startswith("get") or hdr.lower().startswith("post"): - endpt = hdr - if host and endpt: - hdrs.remove(host) - hdrs.remove(endpt) - host = host.split(" ")[1] - endpt = endpt.split(" ") - if (self.__proxy[4] != None and self.__proxy[5] != None): - hdrs.insert(0, self.__getauthheader()) - hdrs.insert(0, "Host: %s" % host) - hdrs.insert(0, "%s http://%s%s %s" % (endpt[0], host, endpt[1], endpt[2])) - return "\r\n".join(hdrs) - - def __getauthheader(self): - auth = self.__proxy[4] + ":" + self.__proxy[5] - return "Proxy-Authorization: Basic " + base64.b64encode(auth) - - def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None): - """setproxy(proxytype, addr[, port[, rdns[, username[, password]]]]) - Sets the proxy to be used. - proxytype - The type of the proxy to be used. Three types - are supported: PROXY_TYPE_SOCKS4 (including socks4a), - PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP - addr - The address of the server (IP or DNS). - port - The port of the server. Defaults to 1080 for SOCKS - servers and 8080 for HTTP proxy servers. - rdns - Should DNS queries be preformed on the remote side - (rather than the local side). The default is True. - Note: This has no effect with SOCKS4 servers. - username - Username to authenticate with to the server. - The default is no authentication. - password - Password to authenticate with to the server. - Only relevant when username is also provided. - """ - self.__proxy = (proxytype, addr, port, rdns, username, password) - - def __negotiatesocks5(self, destaddr, destport): - """__negotiatesocks5(self,destaddr,destport) - Negotiates a connection through a SOCKS5 server. - """ - # First we'll send the authentication packages we support. - if (self.__proxy[4]!=None) and (self.__proxy[5]!=None): - # The username/password details were supplied to the - # setproxy method so we support the USERNAME/PASSWORD - # authentication (in addition to the standard none). - self.sendall(struct.pack('BBBB', 0x05, 0x02, 0x00, 0x02)) - else: - # No username/password were entered, therefore we - # only support connections with no authentication. - self.sendall(struct.pack('BBB', 0x05, 0x01, 0x00)) - # We'll receive the server's response to determine which - # method was selected - chosenauth = self.__recvall(2) - if chosenauth[0:1] != chr(0x05).encode(): - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - # Check the chosen authentication method - if chosenauth[1:2] == chr(0x00).encode(): - # No authentication is required - pass - elif chosenauth[1:2] == chr(0x02).encode(): - # Okay, we need to perform a basic username/password - # authentication. - self.sendall(chr(0x01).encode() + chr(len(self.__proxy[4])) + self.__proxy[4] + chr(len(self.__proxy[5])) + self.__proxy[5]) - authstat = self.__recvall(2) - if authstat[0:1] != chr(0x01).encode(): - # Bad response - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - if authstat[1:2] != chr(0x00).encode(): - # Authentication failed - self.close() - raise Socks5AuthError((3, _socks5autherrors[3])) - # Authentication succeeded - else: - # Reaching here is always bad - self.close() - if chosenauth[1] == chr(0xFF).encode(): - raise Socks5AuthError((2, _socks5autherrors[2])) - else: - raise GeneralProxyError((1, _generalerrors[1])) - # Now we can request the actual connection - req = struct.pack('BBB', 0x05, 0x01, 0x00) - # If the given destination address is an IP address, we'll - # use the IPv4 address request even if remote resolving was specified. - try: - ipaddr = socket.inet_aton(destaddr) - req = req + chr(0x01).encode() + ipaddr - except socket.error: - # Well it's not an IP number, so it's probably a DNS name. - if self.__proxy[3]: - # Resolve remotely - ipaddr = None - req = req + chr(0x03).encode() + chr(len(destaddr)).encode() + destaddr - else: - # Resolve locally - ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) - req = req + chr(0x01).encode() + ipaddr - req = req + struct.pack(">H", destport) - self.sendall(req) - # Get the response - resp = self.__recvall(4) - if resp[0:1] != chr(0x05).encode(): - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - elif resp[1:2] != chr(0x00).encode(): - # Connection failed - self.close() - if ord(resp[1:2])<=8: - raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])])) - else: - raise Socks5Error((9, _socks5errors[9])) - # Get the bound address/port - elif resp[3:4] == chr(0x01).encode(): - boundaddr = self.__recvall(4) - elif resp[3:4] == chr(0x03).encode(): - resp = resp + self.recv(1) - boundaddr = self.__recvall(ord(resp[4:5])) - else: - self.close() - raise GeneralProxyError((1,_generalerrors[1])) - boundport = struct.unpack(">H", self.__recvall(2))[0] - self.__proxysockname = (boundaddr, boundport) - if ipaddr != None: - self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) - else: - self.__proxypeername = (destaddr, destport) - - def getproxysockname(self): - """getsockname() -> address info - Returns the bound IP address and port number at the proxy. - """ - return self.__proxysockname - - def getproxypeername(self): - """getproxypeername() -> address info - Returns the IP and port number of the proxy. - """ - return _orgsocket.getpeername(self) - - def getpeername(self): - """getpeername() -> address info - Returns the IP address and port number of the destination - machine (note: getproxypeername returns the proxy) - """ - return self.__proxypeername - - def __negotiatesocks4(self,destaddr,destport): - """__negotiatesocks4(self,destaddr,destport) - Negotiates a connection through a SOCKS4 server. - """ - # Check if the destination address provided is an IP address - rmtrslv = False - try: - ipaddr = socket.inet_aton(destaddr) - except socket.error: - # It's a DNS name. Check where it should be resolved. - if self.__proxy[3]: - ipaddr = struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01) - rmtrslv = True - else: - ipaddr = socket.inet_aton(socket.gethostbyname(destaddr)) - # Construct the request packet - req = struct.pack(">BBH", 0x04, 0x01, destport) + ipaddr - # The username parameter is considered userid for SOCKS4 - if self.__proxy[4] != None: - req = req + self.__proxy[4] - req = req + chr(0x00).encode() - # DNS name if remote resolving is required - # NOTE: This is actually an extension to the SOCKS4 protocol - # called SOCKS4A and may not be supported in all cases. - if rmtrslv: - req = req + destaddr + chr(0x00).encode() - self.sendall(req) - # Get the response from the server - resp = self.__recvall(8) - if resp[0:1] != chr(0x00).encode(): - # Bad data - self.close() - raise GeneralProxyError((1,_generalerrors[1])) - if resp[1:2] != chr(0x5A).encode(): - # Server returned an error - self.close() - if ord(resp[1:2]) in (91, 92, 93): - self.close() - raise Socks4Error((ord(resp[1:2]), _socks4errors[ord(resp[1:2]) - 90])) - else: - raise Socks4Error((94, _socks4errors[4])) - # Get the bound address/port - self.__proxysockname = (socket.inet_ntoa(resp[4:]), struct.unpack(">H", resp[2:4])[0]) - if rmtrslv != None: - self.__proxypeername = (socket.inet_ntoa(ipaddr), destport) - else: - self.__proxypeername = (destaddr, destport) - - def __negotiatehttp(self, destaddr, destport): - """__negotiatehttp(self,destaddr,destport) - Negotiates a connection through an HTTP server. - """ - # If we need to resolve locally, we do this now - if not self.__proxy[3]: - addr = socket.gethostbyname(destaddr) - else: - addr = destaddr - headers = ["CONNECT ", addr, ":", str(destport), " HTTP/1.1\r\n"] - headers += ["Host: ", destaddr, "\r\n"] - if (self.__proxy[4] != None and self.__proxy[5] != None): - headers += [self.__getauthheader(), "\r\n"] - headers.append("\r\n") - self.sendall("".join(headers).encode()) - # We read the response until we get the string "\r\n\r\n" - resp = self.recv(1) - while resp.find("\r\n\r\n".encode()) == -1: - resp = resp + self.recv(1) - # We just need the first line to check if the connection - # was successful - statusline = resp.splitlines()[0].split(" ".encode(), 2) - if statusline[0] not in ("HTTP/1.0".encode(), "HTTP/1.1".encode()): - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - try: - statuscode = int(statusline[1]) - except ValueError: - self.close() - raise GeneralProxyError((1, _generalerrors[1])) - if statuscode != 200: - self.close() - raise HTTPError((statuscode, statusline[2])) - self.__proxysockname = ("0.0.0.0", 0) - self.__proxypeername = (addr, destport) - - def connect(self, destpair): - """connect(self, despair) - Connects to the specified destination through a proxy. - destpar - A tuple of the IP/DNS address and the port number. - (identical to socket's connect). - To select the proxy server use setproxy(). - """ - # Do a minimal input check first - if (not type(destpair) in (list,tuple)) or (len(destpair) < 2) or (not isinstance(destpair[0], basestring)) or (type(destpair[1]) != int): - raise GeneralProxyError((5, _generalerrors[5])) - if self.__proxy[0] == PROXY_TYPE_SOCKS5: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 1080 - _orgsocket.connect(self, (self.__proxy[1], portnum)) - self.__negotiatesocks5(destpair[0], destpair[1]) - elif self.__proxy[0] == PROXY_TYPE_SOCKS4: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 1080 - _orgsocket.connect(self,(self.__proxy[1], portnum)) - self.__negotiatesocks4(destpair[0], destpair[1]) - elif self.__proxy[0] == PROXY_TYPE_HTTP: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 8080 - _orgsocket.connect(self,(self.__proxy[1], portnum)) - self.__negotiatehttp(destpair[0], destpair[1]) - elif self.__proxy[0] == PROXY_TYPE_HTTP_NO_TUNNEL: - if self.__proxy[2] != None: - portnum = self.__proxy[2] - else: - portnum = 8080 - _orgsocket.connect(self,(self.__proxy[1],portnum)) - if destpair[1] == 443: - self.__negotiatehttp(destpair[0],destpair[1]) - else: - self.__httptunnel = False - elif self.__proxy[0] == None: - _orgsocket.connect(self, (destpair[0], destpair[1])) - else: - raise GeneralProxyError((4, _generalerrors[4])) diff --git a/awx/lib/site-packages/importlib/__init__.py b/awx/lib/site-packages/importlib/__init__.py deleted file mode 100644 index ad31a1ac47..0000000000 --- a/awx/lib/site-packages/importlib/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Backport of importlib.import_module from 3.x.""" -# While not critical (and in no way guaranteed!), it would be nice to keep this -# code compatible with Python 2.3. -import sys - -def _resolve_name(name, package, level): - """Return the absolute name of the module to be imported.""" - if not hasattr(package, 'rindex'): - raise ValueError("'package' not set to a string") - dot = len(package) - for x in xrange(level, 1, -1): - try: - dot = package.rindex('.', 0, dot) - except ValueError: - raise ValueError("attempted relative import beyond top-level " - "package") - return "%s.%s" % (package[:dot], name) - - -def import_module(name, package=None): - """Import a module. - - The 'package' argument is required when performing a relative import. It - specifies the package to use as the anchor point from which to resolve the - relative import to an absolute import. - - """ - if name.startswith('.'): - if not package: - raise TypeError("relative imports require the 'package' argument") - level = 0 - for character in name: - if character != '.': - break - level += 1 - name = _resolve_name(name[level:], package, level) - __import__(name) - return sys.modules[name] diff --git a/awx/lib/site-packages/ironicclient/__init__.py b/awx/lib/site-packages/ironicclient/__init__.py deleted file mode 100644 index e01624cf3b..0000000000 --- a/awx/lib/site-packages/ironicclient/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import pbr.version - -from ironicclient import client -from ironicclient import exc as exceptions - - -__version__ = pbr.version.VersionInfo('python-ironicclient').version_string() - -__all__ = [ - 'client', - 'exc', - 'exceptions', -] diff --git a/awx/lib/site-packages/ironicclient/client.py b/awx/lib/site-packages/ironicclient/client.py deleted file mode 100644 index 6075ca9a2b..0000000000 --- a/awx/lib/site-packages/ironicclient/client.py +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.v2_0 import client as ksclient - -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient import exc - - -def _get_ksclient(**kwargs): - """Get an endpoint and auth token from Keystone. - - :param kwargs: keyword args containing credentials: - * username: name of user - * password: user's password - * auth_url: endpoint to authenticate against - * insecure: allow insecure SSL (no cert verification) - * tenant_{name|id}: name or ID of tenant - """ - return ksclient.Client(username=kwargs.get('username'), - password=kwargs.get('password'), - tenant_id=kwargs.get('tenant_id'), - tenant_name=kwargs.get('tenant_name'), - auth_url=kwargs.get('auth_url'), - insecure=kwargs.get('insecure')) - - -def _get_endpoint(client, **kwargs): - """Get an endpoint using the provided keystone client.""" - attr = None - filter_value = None - if kwargs.get('region_name'): - attr = 'region' - filter_value = kwargs.get('region_name') - return client.service_catalog.url_for( - service_type=kwargs.get('service_type') or 'baremetal', - attr=attr, - filter_value=filter_value, - endpoint_type=kwargs.get('endpoint_type') or 'publicURL') - - -def get_client(api_version, **kwargs): - """Get an authenticated client, based on the credentials in args. - - :param api_version: the API version to use. Valid value: '1'. - :param kwargs: keyword args containing credentials, either: - * os_auth_token: pre-existing token to re-use - * ironic_url: ironic API endpoint - or: - * os_username: name of user - * os_password: user's password - * os_auth_url: endpoint to authenticate against - * insecure: allow insecure SSL (no cert verification) - * os_tenant_{name|id}: name or ID of tenant - """ - - if kwargs.get('os_auth_token') and kwargs.get('ironic_url'): - token = kwargs.get('os_auth_token') - endpoint = kwargs.get('ironic_url') - auth_ref = None - elif (kwargs.get('os_username') and - kwargs.get('os_password') and - kwargs.get('os_auth_url') and - (kwargs.get('os_tenant_id') or kwargs.get('os_tenant_name'))): - - ks_kwargs = { - 'username': kwargs.get('os_username'), - 'password': kwargs.get('os_password'), - 'tenant_id': kwargs.get('os_tenant_id'), - 'tenant_name': kwargs.get('os_tenant_name'), - 'auth_url': kwargs.get('os_auth_url'), - 'service_type': kwargs.get('os_service_type'), - 'endpoint_type': kwargs.get('os_endpoint_type'), - 'insecure': kwargs.get('insecure'), - } - _ksclient = _get_ksclient(**ks_kwargs) - token = (kwargs.get('os_auth_token') - if kwargs.get('os_auth_token') - else _ksclient.auth_token) - - ks_kwargs['region_name'] = kwargs.get('os_region_name') - endpoint = (kwargs.get('ironic_url') or - _get_endpoint(_ksclient, **ks_kwargs)) - - auth_ref = _ksclient.auth_ref - - else: - e = (_('Must provide Keystone credentials or user-defined endpoint ' - 'and token')) - raise exc.AmbiguousAuthSystem(e) - - cli_kwargs = { - 'token': token, - 'insecure': kwargs.get('insecure'), - 'timeout': kwargs.get('timeout'), - 'ca_file': kwargs.get('ca_file'), - 'cert_file': kwargs.get('cert_file'), - 'key_file': kwargs.get('key_file'), - 'auth_ref': auth_ref, - 'os_ironic_api_version': kwargs.get('os_ironic_api_version'), - } - - return Client(api_version, endpoint, **cli_kwargs) - - -def Client(version, *args, **kwargs): - module = utils.import_versioned_module(version, 'client') - client_class = getattr(module, 'Client') - return client_class(*args, **kwargs) diff --git a/awx/lib/site-packages/ironicclient/common/__init__.py b/awx/lib/site-packages/ironicclient/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/common/base.py b/awx/lib/site-packages/ironicclient/common/base.py deleted file mode 100644 index 7be6ff2bc2..0000000000 --- a/awx/lib/site-packages/ironicclient/common/base.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -import copy - -import six.moves.urllib.parse as urlparse - -from ironicclient.openstack.common.apiclient import base - - -def getid(obj): - """Wrapper to get object's ID. - - Abstracts the common pattern of allowing both an object or an - object's ID (UUID) as a parameter when dealing with relationships. - """ - try: - return obj.id - except AttributeError: - return obj - - -class Manager(object): - """Provides CRUD operations with a particular API.""" - resource_class = None - - def __init__(self, api): - self.api = api - - def _create(self, url, body): - resp, body = self.api.json_request('POST', url, body=body) - if body: - return self.resource_class(self, body) - - def _format_body_data(self, body, response_key): - if response_key: - try: - data = body[response_key] - except KeyError: - return [] - else: - data = body - - if not isinstance(data, list): - data = [data] - - return data - - def _list_pagination(self, url, response_key=None, obj_class=None, - limit=None): - """Retrieve a list of items. - - The Ironic API is configured to return a maximum number of - items per request, (see Ironic's api.max_limit option). This - iterates over the 'next' link (pagination) in the responses, - to get the number of items specified by 'limit'. If 'limit' - is None this function will continue pagination until there are - no more values to be returned. - - :param url: a partial URL, e.g. '/nodes' - :param response_key: the key to be looked up in response - dictionary, e.g. 'nodes' - :param obj_class: class for constructing the returned objects. - :param limit: maximum number of items to return. If None returns - everything. - - """ - if obj_class is None: - obj_class = self.resource_class - - if limit is not None: - limit = int(limit) - - object_list = [] - object_count = 0 - limit_reached = False - while url: - resp, body = self.api.json_request('GET', url) - data = self._format_body_data(body, response_key) - for obj in data: - object_list.append(obj_class(self, obj, loaded=True)) - object_count += 1 - if limit and object_count >= limit: - # break the for loop - limit_reached = True - break - - # break the while loop and return - if limit_reached: - break - - url = body.get('next') - if url: - # NOTE(lucasagomes): We need to edit the URL to remove - # the scheme and netloc - url_parts = list(urlparse.urlparse(url)) - url_parts[0] = url_parts[1] = '' - url = urlparse.urlunparse(url_parts) - - return object_list - - def _list(self, url, response_key=None, obj_class=None, body=None): - resp, body = self.api.json_request('GET', url) - - if obj_class is None: - obj_class = self.resource_class - - data = self._format_body_data(body, response_key) - return [obj_class(self, res, loaded=True) for res in data if res] - - def _update(self, url, body, method='PATCH', response_key=None): - resp, body = self.api.json_request(method, url, body=body) - # PATCH/PUT requests may not return a body - if body: - return self.resource_class(self, body) - - def _delete(self, url): - self.api.raw_request('DELETE', url) - - -class Resource(base.Resource): - """Represents a particular instance of an object (tenant, user, etc). - - This is pretty much just a bag for attributes. - """ - - def to_dict(self): - return copy.deepcopy(self._info) diff --git a/awx/lib/site-packages/ironicclient/common/http.py b/awx/lib/site-packages/ironicclient/common/http.py deleted file mode 100644 index c936d3405d..0000000000 --- a/awx/lib/site-packages/ironicclient/common/http.py +++ /dev/null @@ -1,392 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import json -import logging -import os -import socket -import ssl - -from keystoneclient import adapter -import six -import six.moves.urllib.parse as urlparse - -from ironicclient import exc - - -LOG = logging.getLogger(__name__) -USER_AGENT = 'python-ironicclient' -CHUNKSIZE = 1024 * 64 # 64kB - -API_VERSION = '/v1' - - -def _trim_endpoint_api_version(url): - """Trim API version and trailing slash from endpoint.""" - return url.rstrip('/').rstrip(API_VERSION) - - -def _extract_error_json(body): - """Return error_message from the HTTP response body.""" - error_json = {} - try: - body_json = json.loads(body) - if 'error_message' in body_json: - raw_msg = body_json['error_message'] - error_json = json.loads(raw_msg) - except ValueError: - pass - - return error_json - - -class HTTPClient(object): - - def __init__(self, endpoint, **kwargs): - self.endpoint = endpoint - self.endpoint_trimmed = _trim_endpoint_api_version(endpoint) - self.auth_token = kwargs.get('token') - self.auth_ref = kwargs.get('auth_ref') - self.os_ironic_api_version = kwargs.get('os_ironic_api_version') - self.connection_params = self.get_connection_params(endpoint, **kwargs) - - @staticmethod - def get_connection_params(endpoint, **kwargs): - parts = urlparse.urlparse(endpoint) - - path = _trim_endpoint_api_version(parts.path) - - _args = (parts.hostname, parts.port, path) - _kwargs = {'timeout': (float(kwargs.get('timeout')) - if kwargs.get('timeout') else 600)} - - if parts.scheme == 'https': - _class = VerifiedHTTPSConnection - _kwargs['ca_file'] = kwargs.get('ca_file', None) - _kwargs['cert_file'] = kwargs.get('cert_file', None) - _kwargs['key_file'] = kwargs.get('key_file', None) - _kwargs['insecure'] = kwargs.get('insecure', False) - elif parts.scheme == 'http': - _class = six.moves.http_client.HTTPConnection - else: - msg = 'Unsupported scheme: %s' % parts.scheme - raise exc.EndpointException(msg) - - return (_class, _args, _kwargs) - - def get_connection(self): - _class = self.connection_params[0] - try: - return _class(*self.connection_params[1][0:2], - **self.connection_params[2]) - except six.moves.http_client.InvalidURL: - raise exc.EndpointException() - - def log_curl_request(self, method, url, kwargs): - curl = ['curl -i -X %s' % method] - - for (key, value) in kwargs['headers'].items(): - header = '-H \'%s: %s\'' % (key, value) - curl.append(header) - - conn_params_fmt = [ - ('key_file', '--key %s'), - ('cert_file', '--cert %s'), - ('ca_file', '--cacert %s'), - ] - for (key, fmt) in conn_params_fmt: - value = self.connection_params[2].get(key) - if value: - curl.append(fmt % value) - - if self.connection_params[2].get('insecure'): - curl.append('-k') - - if 'body' in kwargs: - curl.append('-d \'%s\'' % kwargs['body']) - - curl.append(urlparse.urljoin(self.endpoint_trimmed, url)) - LOG.debug(' '.join(curl)) - - @staticmethod - def log_http_response(resp, body=None): - status = (resp.version / 10.0, resp.status, resp.reason) - dump = ['\nHTTP/%.1f %s %s' % status] - dump.extend(['%s: %s' % (k, v) for k, v in resp.getheaders()]) - dump.append('') - if body: - dump.extend([body, '']) - LOG.debug('\n'.join(dump)) - - def _make_connection_url(self, url): - (_class, _args, _kwargs) = self.connection_params - base_url = _args[2] - return '%s/%s' % (base_url, url.lstrip('/')) - - def _http_request(self, url, method, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around httplib.HTTP(S)Connection.request to handle tasks such - as setting headers and error handling. - """ - # Copy the kwargs so we can reuse the original in case of redirects - kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {})) - kwargs['headers'].setdefault('User-Agent', USER_AGENT) - if self.os_ironic_api_version: - kwargs['headers'].setdefault('X-OpenStack-Ironic-API-Version', - self.os_ironic_api_version) - if self.auth_token: - kwargs['headers'].setdefault('X-Auth-Token', self.auth_token) - - self.log_curl_request(method, url, kwargs) - conn = self.get_connection() - - try: - conn_url = self._make_connection_url(url) - conn.request(method, conn_url, **kwargs) - resp = conn.getresponse() - except socket.gaierror as e: - message = ("Error finding address for %(url)s: %(e)s" - % dict(url=url, e=e)) - raise exc.EndpointNotFound(message) - except (socket.error, socket.timeout) as e: - endpoint = self.endpoint - message = ("Error communicating with %(endpoint)s %(e)s" - % dict(endpoint=endpoint, e=e)) - raise exc.ConnectionRefused(message) - - body_iter = ResponseBodyIterator(resp) - - # Read body into string if it isn't obviously image data - body_str = None - if resp.getheader('content-type', None) != 'application/octet-stream': - body_str = ''.join([chunk for chunk in body_iter]) - self.log_http_response(resp, body_str) - body_iter = six.StringIO(body_str) - else: - self.log_http_response(resp) - - if 400 <= resp.status < 600: - LOG.warn("Request returned failure status.") - error_json = _extract_error_json(body_str) - raise exc.from_response( - resp, error_json.get('faultstring'), - error_json.get('debuginfo'), method, url) - elif resp.status in (301, 302, 305): - # Redirected. Reissue the request to the new location. - return self._http_request(resp['location'], method, **kwargs) - elif resp.status == 300: - raise exc.from_response(resp, method=method, url=url) - - return resp, body_iter - - def json_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', 'application/json') - kwargs['headers'].setdefault('Accept', 'application/json') - - if 'body' in kwargs: - kwargs['body'] = json.dumps(kwargs['body']) - - resp, body_iter = self._http_request(url, method, **kwargs) - content_type = resp.getheader('content-type', None) - - if resp.status == 204 or resp.status == 205 or content_type is None: - return resp, list() - - if 'application/json' in content_type: - body = ''.join([chunk for chunk in body_iter]) - try: - body = json.loads(body) - except ValueError: - LOG.error('Could not decode response body as JSON') - else: - body = None - - return resp, body - - def raw_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', - 'application/octet-stream') - return self._http_request(url, method, **kwargs) - - -class VerifiedHTTPSConnection(six.moves.http_client.HTTPSConnection): - """httplib-compatibile connection using client-side SSL authentication - - :see http://code.activestate.com/recipes/ - 577548-https-httplib-client-connection-with-certificate-v/ - """ - - def __init__(self, host, port, key_file=None, cert_file=None, - ca_file=None, timeout=None, insecure=False): - six.moves.http_client.HTTPSConnection.__init__(self, host, port, - key_file=key_file, - cert_file=cert_file) - self.key_file = key_file - self.cert_file = cert_file - if ca_file is not None: - self.ca_file = ca_file - else: - self.ca_file = self.get_system_ca_file() - self.timeout = timeout - self.insecure = insecure - - def connect(self): - """Connect to a host on a given (SSL) port. - - If ca_file is pointing somewhere, use it to check Server Certificate. - - Redefined/copied and extended from httplib.py:1105 (Python 2.6.x). - This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter to - ssl.wrap_socket(), which forces SSL to check server certificate against - our client certificate. - """ - sock = socket.create_connection((self.host, self.port), self.timeout) - - if self._tunnel_host: - self.sock = sock - self._tunnel() - - if self.insecure is True: - kwargs = {'cert_reqs': ssl.CERT_NONE} - else: - kwargs = {'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': self.ca_file} - - if self.cert_file: - kwargs['certfile'] = self.cert_file - if self.key_file: - kwargs['keyfile'] = self.key_file - - self.sock = ssl.wrap_socket(sock, **kwargs) - - @staticmethod - def get_system_ca_file(): - """Return path to system default CA file.""" - # Standard CA file locations for Debian/Ubuntu, RedHat/Fedora, - # Suse, FreeBSD/OpenBSD - ca_path = ['/etc/ssl/certs/ca-certificates.crt', - '/etc/pki/tls/certs/ca-bundle.crt', - '/etc/ssl/ca-bundle.pem', - '/etc/ssl/cert.pem'] - for ca in ca_path: - if os.path.exists(ca): - return ca - return None - - -class SessionClient(adapter.LegacyJsonAdapter): - """HTTP client based on Keystone client session.""" - - def _http_request(self, url, method, **kwargs): - kwargs.setdefault('user_agent', USER_AGENT) - kwargs.setdefault('auth', self.auth) - if getattr(self, 'os_ironic_api_version', None): - kwargs['headers'].setdefault('X-OpenStack-Ironic-API-Version', - self.os_ironic_api_version) - - endpoint_filter = kwargs.setdefault('endpoint_filter', {}) - endpoint_filter.setdefault('interface', self.interface) - endpoint_filter.setdefault('service_type', self.service_type) - endpoint_filter.setdefault('region_name', self.region_name) - - resp = self.session.request(url, method, - raise_exc=False, **kwargs) - if 400 <= resp.status_code < 600: - error_json = _extract_error_json(resp.content) - raise exc.from_response(resp, error_json.get('faultstring'), - error_json.get('debuginfo'), method, url) - elif resp.status_code in (301, 302, 305): - # Redirected. Reissue the request to the new location. - location = resp.headers.get('location') - resp = self._http_request(location, method, **kwargs) - elif resp.status_code == 300: - raise exc.from_response(resp, method=method, url=url) - return resp - - def json_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', 'application/json') - kwargs['headers'].setdefault('Accept', 'application/json') - - if 'body' in kwargs: - kwargs['data'] = json.dumps(kwargs.pop('body')) - - resp = self._http_request(url, method, **kwargs) - body = resp.content - content_type = resp.headers.get('content-type', None) - status = resp.status_code - if status == 204 or status == 205 or content_type is None: - return resp, list() - if 'application/json' in content_type: - try: - body = resp.json() - except ValueError: - LOG.error('Could not decode response body as JSON') - else: - body = None - - return resp, body - - def raw_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', - 'application/octet-stream') - return self._http_request(url, method, **kwargs) - - -class ResponseBodyIterator(object): - """A class that acts as an iterator over an HTTP response.""" - - def __init__(self, resp): - self.resp = resp - - def __iter__(self): - while True: - yield self.next() - - def next(self): - chunk = self.resp.read(CHUNKSIZE) - if chunk: - return chunk - else: - raise StopIteration() - - -def _construct_http_client(*args, **kwargs): - session = kwargs.pop('session', None) - auth = kwargs.pop('auth', None) - - if session: - service_type = kwargs.pop('service_type', 'baremetal') - interface = kwargs.pop('endpoint_type', None) - region_name = kwargs.pop('region_name', None) - os_ironic_api_version = kwargs.pop('os_ironic_api_version', None) - session_client = SessionClient(session=session, - auth=auth, - interface=interface, - service_type=service_type, - region_name=region_name, - service_name=None, - user_agent='python-ironicclient') - # Append an ironic specific variable to session - session_client.os_ironic_api_version = os_ironic_api_version - return session_client - else: - return HTTPClient(*args, **kwargs) diff --git a/awx/lib/site-packages/ironicclient/common/i18n.py b/awx/lib/site-packages/ironicclient/common/i18n.py deleted file mode 100644 index 35d33b4dfe..0000000000 --- a/awx/lib/site-packages/ironicclient/common/i18n.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import oslo_i18n - -_translators = oslo_i18n.TranslatorFactory(domain='ironicclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/ironicclient/common/utils.py b/awx/lib/site-packages/ironicclient/common/utils.py deleted file mode 100644 index 22fc624ee5..0000000000 --- a/awx/lib/site-packages/ironicclient/common/utils.py +++ /dev/null @@ -1,247 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import argparse -import base64 -import contextlib -import gzip -import json -import os -import shutil -import subprocess -import tempfile - -from oslo_utils import importutils - -from ironicclient.common.i18n import _ -from ironicclient import exc - - -class HelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(HelpFormatter, self).start_section(heading) - - -def define_command(subparsers, command, callback, cmd_mapper): - '''Define a command in the subparsers collection. - - :param subparsers: subparsers collection where the command will go - :param command: command name - :param callback: function that will be used to process the command - ''' - desc = callback.__doc__ or '' - help = desc.strip().split('\n')[0] - arguments = getattr(callback, 'arguments', []) - - subparser = subparsers.add_parser(command, help=help, - description=desc, - add_help=False, - formatter_class=HelpFormatter) - subparser.add_argument('-h', '--help', action='help', - help=argparse.SUPPRESS) - cmd_mapper[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - -def define_commands_from_module(subparsers, command_module, cmd_mapper): - """Add *do_* methods in a module and add as commands into a subparsers.""" - - for method_name in (a for a in dir(command_module) if a.startswith('do_')): - # Commands should be hypen-separated instead of underscores. - command = method_name[3:].replace('_', '-') - callback = getattr(command_module, method_name) - define_command(subparsers, command, callback, cmd_mapper) - - -def import_versioned_module(version, submodule=None): - module = 'ironicclient.v%s' % version - if submodule: - module = '.'.join((module, submodule)) - return importutils.import_module(module) - - -def split_and_deserialize(string): - """Split and try to JSON deserialize a string. - - Gets a string with the KEY=VALUE format, split it (using '=' as the - separator) and try to JSON deserialize the VALUE. - - :returns: A tuple of (key, value). - """ - try: - key, value = string.split("=", 1) - except ValueError: - raise exc.CommandError(_('Attributes must be a list of ' - 'PATH=VALUE not "%s"') % string) - try: - value = json.loads(value) - except ValueError: - pass - - return (key, value) - - -def args_array_to_dict(kwargs, key_to_convert): - values_to_convert = kwargs.get(key_to_convert) - if values_to_convert: - kwargs[key_to_convert] = dict(split_and_deserialize(v) - for v in values_to_convert) - return kwargs - - -def args_array_to_patch(op, attributes): - patch = [] - for attr in attributes: - # Sanitize - if not attr.startswith('/'): - attr = '/' + attr - - if op in ['add', 'replace']: - path, value = split_and_deserialize(attr) - patch.append({'op': op, 'path': path, 'value': value}) - - elif op == "remove": - # For remove only the key is needed - patch.append({'op': op, 'path': attr}) - else: - raise exc.CommandError(_('Unknown PATCH operation: %s') % op) - return patch - - -def common_params_for_list(args, fields, field_labels): - """Generate 'params' dict that is common for every 'list' command. - - :param args: arguments from command line. - :param fields: possible fields for sorting. - :param field_labels: possible field labels for sorting. - :returns: a dict with params to pass to the client method. - """ - params = {} - if args.marker is not None: - params['marker'] = args.marker - if args.limit is not None: - if args.limit < 0: - raise exc.CommandError( - _('Expected non-negative --limit, got %s') % args.limit) - params['limit'] = args.limit - - if args.sort_key is not None: - # Support using both heading and field name for sort_key - fields_map = dict(zip(field_labels, fields)) - fields_map.update(zip(fields, fields)) - try: - sort_key = fields_map[args.sort_key] - except KeyError: - raise exc.CommandError( - _("%(sort_key)s is an invalid field for sorting, " - "valid values for --sort-key are: %(valid)s") % - {'sort_key': args.sort_key, - 'valid': list(fields_map)}) - params['sort_key'] = sort_key - if args.sort_dir is not None: - if args.sort_dir not in ('asc', 'desc'): - raise exc.CommandError( - _("%s is an invalid value for sort direction, " - "valid values for --sort-dir are: 'asc', 'desc'") % - args.sort_dir) - params['sort_dir'] = args.sort_dir - - params['detail'] = args.detail - - return params - - -def common_filters(marker=None, limit=None, sort_key=None, sort_dir=None): - """Generate common filters for any list request. - - :param marker: entity ID from which to start returning entities. - :param limit: maximum number of entities to return. - :param sort_key: field to use for sorting. - :param sort_dir: direction of sorting: 'asc' or 'desc'. - :returns: list of string filters. - """ - filters = [] - if isinstance(limit, int) and limit > 0: - filters.append('limit=%s' % limit) - if marker is not None: - filters.append('marker=%s' % marker) - if sort_key is not None: - filters.append('sort_key=%s' % sort_key) - if sort_dir is not None: - filters.append('sort_dir=%s' % sort_dir) - return filters - - -@contextlib.contextmanager -def tempdir(*args, **kwargs): - dirname = tempfile.mkdtemp(*args, **kwargs) - try: - yield dirname - finally: - shutil.rmtree(dirname) - - -def make_configdrive(path): - """Make the config drive file. - - :param path: The directory containing the config drive files. - :returns: A gzipped and base64 encoded configdrive string. - - """ - # Make sure path it's readable - if not os.access(path, os.R_OK): - raise exc.CommandError(_('The directory "%s" is not readable') % path) - - with tempfile.NamedTemporaryFile() as tmpfile: - with tempfile.NamedTemporaryFile() as tmpzipfile: - publisher = 'ironicclient-configdrive 0.1' - try: - p = subprocess.Popen(['genisoimage', '-o', tmpfile.name, - '-ldots', '-allow-lowercase', - '-allow-multidot', '-l', - '-publisher', publisher, - '-quiet', '-J', - '-r', '-V', 'config-2', - path], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - except OSError as e: - raise exc.CommandError( - _('Error generating the config drive. Make sure the ' - '"genisoimage" tool is installed. Error: %s') % e) - - stdout, stderr = p.communicate() - if p.returncode != 0: - raise exc.CommandError( - _('Error generating the config drive.' - 'Stdout: "%(stdout)s". Stderr: %(stderr)s') % - {'stdout': stdout, 'stderr': stderr}) - - # Compress file - tmpfile.seek(0) - g = gzip.GzipFile(fileobj=tmpzipfile, mode='wb') - shutil.copyfileobj(tmpfile, g) - g.close() - - tmpzipfile.seek(0) - return base64.b64encode(tmpzipfile.read()) diff --git a/awx/lib/site-packages/ironicclient/exc.py b/awx/lib/site-packages/ironicclient/exc.py deleted file mode 100644 index a1d04176ea..0000000000 --- a/awx/lib/site-packages/ironicclient/exc.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.openstack.common.apiclient import exceptions -from ironicclient.openstack.common.apiclient.exceptions import * # noqa - - -# NOTE(akurilin): This alias is left here since v.0.1.3 to support backwards -# compatibility. -InvalidEndpoint = EndpointException -CommunicationError = ConnectionRefused -HTTPBadRequest = BadRequest -HTTPInternalServerError = InternalServerError -HTTPNotFound = NotFound -HTTPServiceUnavailable = ServiceUnavailable - - -class AmbiguousAuthSystem(ClientException): - """Could not obtain token and endpoint using provided credentials.""" - pass - -# Alias for backwards compatibility -AmbigiousAuthSystem = AmbiguousAuthSystem - - -class InvalidAttribute(ClientException): - pass - - -def from_response(response, message=None, traceback=None, method=None, - url=None): - """Return an HttpError instance based on response from httplib/requests.""" - - error_body = {} - if message: - error_body['message'] = message - if traceback: - error_body['details'] = traceback - - if hasattr(response, 'status') and not hasattr(response, 'status_code'): - # NOTE(akurilin): These modifications around response object give - # ability to get all necessary information in method `from_response` - # from common code, which expecting response object from `requests` - # library instead of object from `httplib/httplib2` library. - response.status_code = response.status - response.headers = { - 'Content-Type': response.getheader('content-type', "")} - - if hasattr(response, 'status_code'): - # NOTE(jiangfei): These modifications allow SessionClient - # to handle faultstring. - response.json = lambda: {'error': error_body} - - if (response.headers['Content-Type'].startswith('text/') and - not hasattr(response, 'text')): - # NOTE(clif_h): There seems to be a case in the - # openstack.common.apiclient.exceptions module where if the - # content-type of the response is text/* then it expects - # the response to have a 'text' attribute, but that - # doesn't always seem to necessarily be the case. - # This is to work around that problem. - response.text = '' - - return exceptions.from_response(response, message, url) diff --git a/awx/lib/site-packages/ironicclient/openstack/__init__.py b/awx/lib/site-packages/ironicclient/openstack/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/openstack/common/__init__.py b/awx/lib/site-packages/ironicclient/openstack/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/openstack/common/_i18n.py b/awx/lib/site-packages/ironicclient/openstack/common/_i18n.py deleted file mode 100644 index 29ffaac057..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/_i18n.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html - -""" - -import oslo.i18n - - -# NOTE(dhellmann): This reference to o-s-l-o will be replaced by the -# application name when this module is synced into the separate -# repository. It is OK to have more than one translation function -# using the same domain, since there will still only be one message -# catalog. -_translators = oslo.i18n.TranslatorFactory(domain='ironicclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/__init__.py b/awx/lib/site-packages/ironicclient/openstack/common/apiclient/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/auth.py b/awx/lib/site-packages/ironicclient/openstack/common/apiclient/auth.py deleted file mode 100644 index 88978b5800..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/auth.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 Spanish National Research Council. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import abc -import argparse -import os - -import six -from stevedore import extension - -from ironicclient.openstack.common.apiclient import exceptions - - -_discovered_plugins = {} - - -def discover_auth_systems(): - """Discover the available auth-systems. - - This won't take into account the old style auth-systems. - """ - global _discovered_plugins - _discovered_plugins = {} - - def add_plugin(ext): - _discovered_plugins[ext.name] = ext.plugin - - ep_namespace = "ironicclient.openstack.common.apiclient.auth" - mgr = extension.ExtensionManager(ep_namespace) - mgr.map(add_plugin) - - -def load_auth_system_opts(parser): - """Load options needed by the available auth-systems into a parser. - - This function will try to populate the parser with options from the - available plugins. - """ - group = parser.add_argument_group("Common auth options") - BaseAuthPlugin.add_common_opts(group) - for name, auth_plugin in six.iteritems(_discovered_plugins): - group = parser.add_argument_group( - "Auth-system '%s' options" % name, - conflict_handler="resolve") - auth_plugin.add_opts(group) - - -def load_plugin(auth_system): - try: - plugin_class = _discovered_plugins[auth_system] - except KeyError: - raise exceptions.AuthSystemNotFound(auth_system) - return plugin_class(auth_system=auth_system) - - -def load_plugin_from_args(args): - """Load required plugin and populate it with options. - - Try to guess auth system if it is not specified. Systems are tried in - alphabetical order. - - :type args: argparse.Namespace - :raises: AuthPluginOptionsMissing - """ - auth_system = args.os_auth_system - if auth_system: - plugin = load_plugin(auth_system) - plugin.parse_opts(args) - plugin.sufficient_options() - return plugin - - for plugin_auth_system in sorted(six.iterkeys(_discovered_plugins)): - plugin_class = _discovered_plugins[plugin_auth_system] - plugin = plugin_class() - plugin.parse_opts(args) - try: - plugin.sufficient_options() - except exceptions.AuthPluginOptionsMissing: - continue - return plugin - raise exceptions.AuthPluginOptionsMissing(["auth_system"]) - - -@six.add_metaclass(abc.ABCMeta) -class BaseAuthPlugin(object): - """Base class for authentication plugins. - - An authentication plugin needs to override at least the authenticate - method to be a valid plugin. - """ - - auth_system = None - opt_names = [] - common_opt_names = [ - "auth_system", - "username", - "password", - "tenant_name", - "token", - "auth_url", - ] - - def __init__(self, auth_system=None, **kwargs): - self.auth_system = auth_system or self.auth_system - self.opts = dict((name, kwargs.get(name)) - for name in self.opt_names) - - @staticmethod - def _parser_add_opt(parser, opt): - """Add an option to parser in two variants. - - :param opt: option name (with underscores) - """ - dashed_opt = opt.replace("_", "-") - env_var = "OS_%s" % opt.upper() - arg_default = os.environ.get(env_var, "") - arg_help = "Defaults to env[%s]." % env_var - parser.add_argument( - "--os-%s" % dashed_opt, - metavar="<%s>" % dashed_opt, - default=arg_default, - help=arg_help) - parser.add_argument( - "--os_%s" % opt, - metavar="<%s>" % dashed_opt, - help=argparse.SUPPRESS) - - @classmethod - def add_opts(cls, parser): - """Populate the parser with the options for this plugin. - """ - for opt in cls.opt_names: - # use `BaseAuthPlugin.common_opt_names` since it is never - # changed in child classes - if opt not in BaseAuthPlugin.common_opt_names: - cls._parser_add_opt(parser, opt) - - @classmethod - def add_common_opts(cls, parser): - """Add options that are common for several plugins. - """ - for opt in cls.common_opt_names: - cls._parser_add_opt(parser, opt) - - @staticmethod - def get_opt(opt_name, args): - """Return option name and value. - - :param opt_name: name of the option, e.g., "username" - :param args: parsed arguments - """ - return (opt_name, getattr(args, "os_%s" % opt_name, None)) - - def parse_opts(self, args): - """Parse the actual auth-system options if any. - - This method is expected to populate the attribute `self.opts` with a - dict containing the options and values needed to make authentication. - """ - self.opts.update(dict(self.get_opt(opt_name, args) - for opt_name in self.opt_names)) - - def authenticate(self, http_client): - """Authenticate using plugin defined method. - - The method usually analyses `self.opts` and performs - a request to authentication server. - - :param http_client: client object that needs authentication - :type http_client: HTTPClient - :raises: AuthorizationFailure - """ - self.sufficient_options() - self._do_authenticate(http_client) - - @abc.abstractmethod - def _do_authenticate(self, http_client): - """Protected method for authentication. - """ - - def sufficient_options(self): - """Check if all required options are present. - - :raises: AuthPluginOptionsMissing - """ - missing = [opt - for opt in self.opt_names - if not self.opts.get(opt)] - if missing: - raise exceptions.AuthPluginOptionsMissing(missing) - - @abc.abstractmethod - def token_and_endpoint(self, endpoint_type, service_type): - """Return token and endpoint. - - :param service_type: Service type of the endpoint - :type service_type: string - :param endpoint_type: Type of endpoint. - Possible values: public or publicURL, - internal or internalURL, - admin or adminURL - :type endpoint_type: string - :returns: tuple of token and endpoint strings - :raises: EndpointException - """ diff --git a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/base.py b/awx/lib/site-packages/ironicclient/openstack/common/apiclient/base.py deleted file mode 100644 index fc4a2ccb53..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/base.py +++ /dev/null @@ -1,518 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2012 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -# E1102: %s is not callable -# pylint: disable=E1102 - -import abc -import copy - -from oslo.utils import strutils -import six -from six.moves.urllib import parse - -from ironicclient.openstack.common._i18n import _ -from ironicclient.openstack.common.apiclient import exceptions - - -def getid(obj): - """Return id if argument is a Resource. - - Abstracts the common pattern of allowing both an object or an object's ID - (UUID) as a parameter when dealing with relationships. - """ - try: - if obj.uuid: - return obj.uuid - except AttributeError: - pass - try: - return obj.id - except AttributeError: - return obj - - -# TODO(aababilov): call run_hooks() in HookableMixin's child classes -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - """Add a new hook of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param hook_func: hook function - """ - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - """Run all hooks of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param args: args to be passed to every hook function - :param kwargs: kwargs to be passed to every hook function - """ - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - -class BaseManager(HookableMixin): - """Basic manager type providing common operations. - - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, client): - """Initializes BaseManager with `client`. - - :param client: instance of BaseClient descendant for HTTP requests - """ - super(BaseManager, self).__init__() - self.client = client - - def _list(self, url, response_key=None, obj_class=None, json=None): - """List the collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - :param obj_class: class for constructing the returned objects - (self.resource_class will be used by default) - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - """ - if json: - body = self.client.post(url, json=json).json() - else: - body = self.client.get(url).json() - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] if response_key is not None else body - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - try: - data = data['values'] - except (KeyError, TypeError): - pass - - return [obj_class(self, res, loaded=True) for res in data if res] - - def _get(self, url, response_key=None): - """Get an object from collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'server'. If response_key is None - all response body - will be used. - """ - body = self.client.get(url).json() - data = body[response_key] if response_key is not None else body - return self.resource_class(self, data, loaded=True) - - def _head(self, url): - """Retrieve request headers for an object. - - :param url: a partial URL, e.g., '/servers' - """ - resp = self.client.head(url) - return resp.status_code == 204 - - def _post(self, url, json, response_key=None, return_raw=False): - """Create an object. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'server'. If response_key is None - all response body - will be used. - :param return_raw: flag to force returning raw JSON instead of - Python object of self.resource_class - """ - body = self.client.post(url, json=json).json() - data = body[response_key] if response_key is not None else body - if return_raw: - return data - return self.resource_class(self, data) - - def _put(self, url, json=None, response_key=None): - """Update an object with PUT method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - """ - resp = self.client.put(url, json=json) - # PUT requests may not return a body - if resp.content: - body = resp.json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _patch(self, url, json=None, response_key=None): - """Update an object with PATCH method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - """ - body = self.client.patch(url, json=json).json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _delete(self, url): - """Delete an object. - - :param url: a partial URL, e.g., '/servers/my-server' - """ - return self.client.delete(url) - - -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(BaseManager): - """Manager with additional `find()`/`findall()` methods.""" - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - matches = self.findall(**kwargs) - num_matches = len(matches) - if num_matches == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(msg) - elif num_matches > 1: - raise exceptions.NoUniqueMatch() - else: - return matches[0] - - def findall(self, **kwargs): - """Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - found = [] - searches = kwargs.items() - - for obj in self.list(): - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - found.append(obj) - except AttributeError: - continue - - return found - - -class CrudManager(BaseManager): - """Base manager class for manipulating entities. - - Children of this class are expected to define a `collection_key` and `key`. - - - `collection_key`: Usually a plural noun by convention (e.g. `entities`); - used to refer collections in both URL's (e.g. `/v3/entities`) and JSON - objects containing a list of member resources (e.g. `{'entities': [{}, - {}, {}]}`). - - `key`: Usually a singular noun by convention (e.g. `entity`); used to - refer to an individual member of the collection. - - """ - collection_key = None - key = None - - def build_url(self, base_url=None, **kwargs): - """Builds a resource URL for the given kwargs. - - Given an example collection where `collection_key = 'entities'` and - `key = 'entity'`, the following URL's could be generated. - - By default, the URL will represent a collection of entities, e.g.:: - - /entities - - If kwargs contains an `entity_id`, then the URL will represent a - specific member, e.g.:: - - /entities/{entity_id} - - :param base_url: if provided, the generated URL will be appended to it - """ - url = base_url if base_url is not None else '' - - url += '/%s' % self.collection_key - - # do we have a specific entity? - entity_id = kwargs.get('%s_id' % self.key) - if entity_id is not None: - url += '/%s' % entity_id - - return url - - def _filter_kwargs(self, kwargs): - """Drop null values and handle ids.""" - for key, ref in six.iteritems(kwargs.copy()): - if ref is None: - kwargs.pop(key) - else: - if isinstance(ref, Resource): - kwargs.pop(key) - kwargs['%s_id' % key] = getid(ref) - return kwargs - - def create(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._post( - self.build_url(**kwargs), - {self.key: kwargs}, - self.key) - - def get(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._get( - self.build_url(**kwargs), - self.key) - - def head(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._head(self.build_url(**kwargs)) - - def list(self, base_url=None, **kwargs): - """List the collection. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - - def put(self, base_url=None, **kwargs): - """Update an element. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._put(self.build_url(base_url=base_url, **kwargs)) - - def update(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - params = kwargs.copy() - params.pop('%s_id' % self.key) - - return self._patch( - self.build_url(**kwargs), - {self.key: params}, - self.key) - - def delete(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - - return self._delete( - self.build_url(**kwargs)) - - def find(self, base_url=None, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - rl = self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - num = len(rl) - - if num == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(404, msg) - elif num > 1: - raise exceptions.NoUniqueMatch - else: - return rl[0] - - -class Extension(HookableMixin): - """Extension descriptor.""" - - SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') - manager_class = None - - def __init__(self, name, module): - super(Extension, self).__init__() - self.name = name - self.module = module - self._parse_extension_module() - - def _parse_extension_module(self): - self.manager_class = None - for attr_name, attr_value in self.module.__dict__.items(): - if attr_name in self.SUPPORTED_HOOKS: - self.add_hook(attr_name, attr_value) - else: - try: - if issubclass(attr_value, BaseManager): - self.manager_class = attr_value - except TypeError: - pass - - def __repr__(self): - return "<Extension '%s'>" % self.name - - -class Resource(object): - """Base class for OpenStack resources (tenant, user, etc.). - - This is pretty much just a bag for attributes. - """ - - HUMAN_ID = False - NAME_ATTR = 'name' - - def __init__(self, manager, info, loaded=False): - """Populate and bind to a manager. - - :param manager: BaseManager object - :param info: dictionary representing resource attributes - :param loaded: prevent lazy-loading if set to True - """ - self.manager = manager - self._info = info - self._add_details(info) - self._loaded = loaded - - def __repr__(self): - reprkeys = sorted(k - for k in self.__dict__.keys() - if k[0] != '_' and k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) - - @property - def human_id(self): - """Human-readable ID which can be used for bash completion. - """ - if self.HUMAN_ID: - name = getattr(self, self.NAME_ATTR, None) - if name is not None: - return strutils.to_slug(name) - return None - - def _add_details(self, info): - for (k, v) in six.iteritems(info): - try: - setattr(self, k, v) - self._info[k] = v - except AttributeError: - # In this case we already defined the attribute on the class - pass - - def __getattr__(self, k): - if k not in self.__dict__: - # NOTE(bcwaldon): disallow lazy-loading if already loaded once - if not self.is_loaded(): - self.get() - return self.__getattr__(k) - - raise AttributeError(k) - else: - return self.__dict__[k] - - def get(self): - """Support for lazy loading details. - - Some clients, such as novaclient have the option to lazy load the - details, details which can be loaded with this function. - """ - # set_loaded() first ... so if we have to bail, we know we tried. - self.set_loaded(True) - if not hasattr(self.manager, 'get'): - return - - new = self.manager.get(self.id) - if new: - self._add_details(new._info) - self._add_details( - {'x_request_id': self.manager.client.last_request_id}) - - def __eq__(self, other): - if not isinstance(other, Resource): - return NotImplemented - # two resources of different types are not equal - if not isinstance(other, self.__class__): - return False - if hasattr(self, 'id') and hasattr(other, 'id'): - return self.id == other.id - return self._info == other._info - - def is_loaded(self): - return self._loaded - - def set_loaded(self, val): - self._loaded = val - - def to_dict(self): - return copy.deepcopy(self._info) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/client.py b/awx/lib/site-packages/ironicclient/openstack/common/apiclient/client.py deleted file mode 100644 index d05e354bc5..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/client.py +++ /dev/null @@ -1,388 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Piston Cloud Computing, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import hashlib -import logging -import time - -try: - import simplejson as json -except ImportError: - import json - -from oslo.utils import encodeutils -from oslo.utils import importutils -import requests - -from ironicclient.openstack.common._i18n import _ -from ironicclient.openstack.common.apiclient import exceptions - -_logger = logging.getLogger(__name__) -SENSITIVE_HEADERS = ('X-Auth-Token', 'X-Subject-Token',) - - -class HTTPClient(object): - """This client handles sending HTTP requests to OpenStack servers. - - Features: - - - share authentication information between several clients to different - services (e.g., for compute and image clients); - - reissue authentication request for expired tokens; - - encode/decode JSON bodies; - - raise exceptions on HTTP errors; - - pluggable authentication; - - store authentication information in a keyring; - - store time spent for requests; - - register clients for particular services, so one can use - `http_client.identity` or `http_client.compute`; - - log requests and responses in a format that is easy to copy-and-paste - into terminal and send the same request with curl. - """ - - user_agent = "ironicclient.openstack.common.apiclient" - - def __init__(self, - auth_plugin, - region_name=None, - endpoint_type="publicURL", - original_ip=None, - verify=True, - cert=None, - timeout=None, - timings=False, - keyring_saver=None, - debug=False, - user_agent=None, - http=None): - self.auth_plugin = auth_plugin - - self.endpoint_type = endpoint_type - self.region_name = region_name - - self.original_ip = original_ip - self.timeout = timeout - self.verify = verify - self.cert = cert - - self.keyring_saver = keyring_saver - self.debug = debug - self.user_agent = user_agent or self.user_agent - - self.times = [] # [("item", starttime, endtime), ...] - self.timings = timings - - # requests within the same session can reuse TCP connections from pool - self.http = http or requests.Session() - - self.cached_token = None - self.last_request_id = None - - def _safe_header(self, name, value): - if name in SENSITIVE_HEADERS: - # because in python3 byte string handling is ... ug - v = value.encode('utf-8') - h = hashlib.sha1(v) - d = h.hexdigest() - return encodeutils.safe_decode(name), "{SHA1}%s" % d - else: - return (encodeutils.safe_decode(name), - encodeutils.safe_decode(value)) - - def _http_log_req(self, method, url, kwargs): - if not self.debug: - return - - string_parts = [ - "curl -i", - "-X '%s'" % method, - "'%s'" % url, - ] - - for element in kwargs['headers']: - header = ("-H '%s: %s'" % - self._safe_header(element, kwargs['headers'][element])) - string_parts.append(header) - - _logger.debug("REQ: %s" % " ".join(string_parts)) - if 'data' in kwargs: - _logger.debug("REQ BODY: %s\n" % (kwargs['data'])) - - def _http_log_resp(self, resp): - if not self.debug: - return - _logger.debug( - "RESP: [%s] %s\n", - resp.status_code, - resp.headers) - if resp._content_consumed: - _logger.debug( - "RESP BODY: %s\n", - resp.text) - - def serialize(self, kwargs): - if kwargs.get('json') is not None: - kwargs['headers']['Content-Type'] = 'application/json' - kwargs['data'] = json.dumps(kwargs['json']) - try: - del kwargs['json'] - except KeyError: - pass - - def get_timings(self): - return self.times - - def reset_timings(self): - self.times = [] - - def request(self, method, url, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around `requests.Session.request` to handle tasks such as - setting headers, JSON encoding/decoding, and error handling. - - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - requests.Session.request (such as `headers`) or `json` - that will be encoded as JSON and used as `data` argument - """ - kwargs.setdefault("headers", {}) - kwargs["headers"]["User-Agent"] = self.user_agent - if self.original_ip: - kwargs["headers"]["Forwarded"] = "for=%s;by=%s" % ( - self.original_ip, self.user_agent) - if self.timeout is not None: - kwargs.setdefault("timeout", self.timeout) - kwargs.setdefault("verify", self.verify) - if self.cert is not None: - kwargs.setdefault("cert", self.cert) - self.serialize(kwargs) - - self._http_log_req(method, url, kwargs) - if self.timings: - start_time = time.time() - resp = self.http.request(method, url, **kwargs) - if self.timings: - self.times.append(("%s %s" % (method, url), - start_time, time.time())) - self._http_log_resp(resp) - - self.last_request_id = resp.headers.get('x-openstack-request-id') - - if resp.status_code >= 400: - _logger.debug( - "Request returned failure status: %s", - resp.status_code) - raise exceptions.from_response(resp, method, url) - - return resp - - @staticmethod - def concat_url(endpoint, url): - """Concatenate endpoint and final URL. - - E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to - "http://keystone/v2.0/tokens". - - :param endpoint: the base URL - :param url: the final URL - """ - return "%s/%s" % (endpoint.rstrip("/"), url.strip("/")) - - def client_request(self, client, method, url, **kwargs): - """Send an http request using `client`'s endpoint and specified `url`. - - If request was rejected as unauthorized (possibly because the token is - expired), issue one authorization attempt and send the request once - again. - - :param client: instance of BaseClient descendant - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - `HTTPClient.request` - """ - - filter_args = { - "endpoint_type": client.endpoint_type or self.endpoint_type, - "service_type": client.service_type, - } - token, endpoint = (self.cached_token, client.cached_endpoint) - just_authenticated = False - if not (token and endpoint): - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - pass - if not (token and endpoint): - self.authenticate() - just_authenticated = True - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - if not (token and endpoint): - raise exceptions.AuthorizationFailure( - _("Cannot find endpoint or token for request")) - - old_token_endpoint = (token, endpoint) - kwargs.setdefault("headers", {})["X-Auth-Token"] = token - self.cached_token = token - client.cached_endpoint = endpoint - # Perform the request once. If we get Unauthorized, then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - except exceptions.Unauthorized as unauth_ex: - if just_authenticated: - raise - self.cached_token = None - client.cached_endpoint = None - if self.auth_plugin.opts.get('token'): - self.auth_plugin.opts['token'] = None - if self.auth_plugin.opts.get('endpoint'): - self.auth_plugin.opts['endpoint'] = None - self.authenticate() - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - raise unauth_ex - if (not (token and endpoint) or - old_token_endpoint == (token, endpoint)): - raise unauth_ex - self.cached_token = token - client.cached_endpoint = endpoint - kwargs["headers"]["X-Auth-Token"] = token - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - - def add_client(self, base_client_instance): - """Add a new instance of :class:`BaseClient` descendant. - - `self` will store a reference to `base_client_instance`. - - Example: - - >>> def test_clients(): - ... from keystoneclient.auth import keystone - ... from openstack.common.apiclient import client - ... auth = keystone.KeystoneAuthPlugin( - ... username="user", password="pass", tenant_name="tenant", - ... auth_url="http://auth:5000/v2.0") - ... openstack_client = client.HTTPClient(auth) - ... # create nova client - ... from novaclient.v1_1 import client - ... client.Client(openstack_client) - ... # create keystone client - ... from keystoneclient.v2_0 import client - ... client.Client(openstack_client) - ... # use them - ... openstack_client.identity.tenants.list() - ... openstack_client.compute.servers.list() - """ - service_type = base_client_instance.service_type - if service_type and not hasattr(self, service_type): - setattr(self, service_type, base_client_instance) - - def authenticate(self): - self.auth_plugin.authenticate(self) - # Store the authentication results in the keyring for later requests - if self.keyring_saver: - self.keyring_saver.save(self) - - -class BaseClient(object): - """Top-level object to access the OpenStack API. - - This client uses :class:`HTTPClient` to send requests. :class:`HTTPClient` - will handle a bunch of issues such as authentication. - """ - - service_type = None - endpoint_type = None # "publicURL" will be used - cached_endpoint = None - - def __init__(self, http_client, extensions=None): - self.http_client = http_client - http_client.add_client(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - def client_request(self, method, url, **kwargs): - return self.http_client.client_request( - self, method, url, **kwargs) - - @property - def last_request_id(self): - return self.http_client.last_request_id - - def head(self, url, **kwargs): - return self.client_request("HEAD", url, **kwargs) - - def get(self, url, **kwargs): - return self.client_request("GET", url, **kwargs) - - def post(self, url, **kwargs): - return self.client_request("POST", url, **kwargs) - - def put(self, url, **kwargs): - return self.client_request("PUT", url, **kwargs) - - def delete(self, url, **kwargs): - return self.client_request("DELETE", url, **kwargs) - - def patch(self, url, **kwargs): - return self.client_request("PATCH", url, **kwargs) - - @staticmethod - def get_class(api_name, version, version_map): - """Returns the client class for the requested API version - - :param api_name: the name of the API, e.g. 'compute', 'image', etc - :param version: the requested API version - :param version_map: a dict of client classes keyed by version - :rtype: a client class for the requested API version - """ - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = _("Invalid %(api_name)s client version '%(version)s'. " - "Must be one of: %(version_map)s") % { - 'api_name': api_name, - 'version': version, - 'version_map': ', '.join(version_map.keys())} - raise exceptions.UnsupportedVersion(msg) - - return importutils.import_class(client_path) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/exceptions.py b/awx/lib/site-packages/ironicclient/openstack/common/apiclient/exceptions.py deleted file mode 100644 index 2f3ea28991..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/exceptions.py +++ /dev/null @@ -1,458 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Nebula, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception definitions. -""" - -import inspect -import sys - -import six - -from ironicclient.openstack.common._i18n import _ - - -class ClientException(Exception): - """The base exception class for all exceptions this library raises. - """ - pass - - -class ValidationError(ClientException): - """Error in validation on API client side.""" - pass - - -class UnsupportedVersion(ClientException): - """User is trying to use an unsupported version of the API.""" - pass - - -class CommandError(ClientException): - """Error in CLI tool.""" - pass - - -class AuthorizationFailure(ClientException): - """Cannot authorize API client.""" - pass - - -class ConnectionRefused(ClientException): - """Cannot connect to API service.""" - pass - - -class AuthPluginOptionsMissing(AuthorizationFailure): - """Auth plugin misses some options.""" - def __init__(self, opt_names): - super(AuthPluginOptionsMissing, self).__init__( - _("Authentication failed. Missing options: %s") % - ", ".join(opt_names)) - self.opt_names = opt_names - - -class AuthSystemNotFound(AuthorizationFailure): - """User has specified an AuthSystem that is not installed.""" - def __init__(self, auth_system): - super(AuthSystemNotFound, self).__init__( - _("AuthSystemNotFound: %s") % repr(auth_system)) - self.auth_system = auth_system - - -class NoUniqueMatch(ClientException): - """Multiple entities found instead of one.""" - pass - - -class EndpointException(ClientException): - """Something is rotten in Service Catalog.""" - pass - - -class EndpointNotFound(EndpointException): - """Could not find requested endpoint in Service Catalog.""" - pass - - -class AmbiguousEndpoints(EndpointException): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - super(AmbiguousEndpoints, self).__init__( - _("AmbiguousEndpoints: %s") % repr(endpoints)) - self.endpoints = endpoints - - -class HttpError(ClientException): - """The base exception class for all HTTP exceptions. - """ - http_status = 0 - message = _("HTTP Error") - - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None): - self.http_status = http_status or self.http_status - self.message = message or self.message - self.details = details - self.request_id = request_id - self.response = response - self.url = url - self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) - if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HttpError, self).__init__(formatted_string) - - -class HTTPRedirection(HttpError): - """HTTP Redirection.""" - message = _("HTTP Redirection") - - -class HTTPClientError(HttpError): - """Client-side HTTP error. - - Exception for cases in which the client seems to have erred. - """ - message = _("HTTP Client Error") - - -class HttpServerError(HttpError): - """Server-side HTTP error. - - Exception for cases in which the server is aware that it has - erred or is incapable of performing the request. - """ - message = _("HTTP Server Error") - - -class MultipleChoices(HTTPRedirection): - """HTTP 300 - Multiple Choices. - - Indicates multiple options for the resource that the client may follow. - """ - - http_status = 300 - message = _("Multiple Choices") - - -class BadRequest(HTTPClientError): - """HTTP 400 - Bad Request. - - The request cannot be fulfilled due to bad syntax. - """ - http_status = 400 - message = _("Bad Request") - - -class Unauthorized(HTTPClientError): - """HTTP 401 - Unauthorized. - - Similar to 403 Forbidden, but specifically for use when authentication - is required and has failed or has not yet been provided. - """ - http_status = 401 - message = _("Unauthorized") - - -class PaymentRequired(HTTPClientError): - """HTTP 402 - Payment Required. - - Reserved for future use. - """ - http_status = 402 - message = _("Payment Required") - - -class Forbidden(HTTPClientError): - """HTTP 403 - Forbidden. - - The request was a valid request, but the server is refusing to respond - to it. - """ - http_status = 403 - message = _("Forbidden") - - -class NotFound(HTTPClientError): - """HTTP 404 - Not Found. - - The requested resource could not be found but may be available again - in the future. - """ - http_status = 404 - message = _("Not Found") - - -class MethodNotAllowed(HTTPClientError): - """HTTP 405 - Method Not Allowed. - - A request was made of a resource using a request method not supported - by that resource. - """ - http_status = 405 - message = _("Method Not Allowed") - - -class NotAcceptable(HTTPClientError): - """HTTP 406 - Not Acceptable. - - The requested resource is only capable of generating content not - acceptable according to the Accept headers sent in the request. - """ - http_status = 406 - message = _("Not Acceptable") - - -class ProxyAuthenticationRequired(HTTPClientError): - """HTTP 407 - Proxy Authentication Required. - - The client must first authenticate itself with the proxy. - """ - http_status = 407 - message = _("Proxy Authentication Required") - - -class RequestTimeout(HTTPClientError): - """HTTP 408 - Request Timeout. - - The server timed out waiting for the request. - """ - http_status = 408 - message = _("Request Timeout") - - -class Conflict(HTTPClientError): - """HTTP 409 - Conflict. - - Indicates that the request could not be processed because of conflict - in the request, such as an edit conflict. - """ - http_status = 409 - message = _("Conflict") - - -class Gone(HTTPClientError): - """HTTP 410 - Gone. - - Indicates that the resource requested is no longer available and will - not be available again. - """ - http_status = 410 - message = _("Gone") - - -class LengthRequired(HTTPClientError): - """HTTP 411 - Length Required. - - The request did not specify the length of its content, which is - required by the requested resource. - """ - http_status = 411 - message = _("Length Required") - - -class PreconditionFailed(HTTPClientError): - """HTTP 412 - Precondition Failed. - - The server does not meet one of the preconditions that the requester - put on the request. - """ - http_status = 412 - message = _("Precondition Failed") - - -class RequestEntityTooLarge(HTTPClientError): - """HTTP 413 - Request Entity Too Large. - - The request is larger than the server is willing or able to process. - """ - http_status = 413 - message = _("Request Entity Too Large") - - def __init__(self, *args, **kwargs): - try: - self.retry_after = int(kwargs.pop('retry_after')) - except (KeyError, ValueError): - self.retry_after = 0 - - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) - - -class RequestUriTooLong(HTTPClientError): - """HTTP 414 - Request-URI Too Long. - - The URI provided was too long for the server to process. - """ - http_status = 414 - message = _("Request-URI Too Long") - - -class UnsupportedMediaType(HTTPClientError): - """HTTP 415 - Unsupported Media Type. - - The request entity has a media type which the server or resource does - not support. - """ - http_status = 415 - message = _("Unsupported Media Type") - - -class RequestedRangeNotSatisfiable(HTTPClientError): - """HTTP 416 - Requested Range Not Satisfiable. - - The client has asked for a portion of the file, but the server cannot - supply that portion. - """ - http_status = 416 - message = _("Requested Range Not Satisfiable") - - -class ExpectationFailed(HTTPClientError): - """HTTP 417 - Expectation Failed. - - The server cannot meet the requirements of the Expect request-header field. - """ - http_status = 417 - message = _("Expectation Failed") - - -class UnprocessableEntity(HTTPClientError): - """HTTP 422 - Unprocessable Entity. - - The request was well-formed but was unable to be followed due to semantic - errors. - """ - http_status = 422 - message = _("Unprocessable Entity") - - -class InternalServerError(HttpServerError): - """HTTP 500 - Internal Server Error. - - A generic error message, given when no more specific message is suitable. - """ - http_status = 500 - message = _("Internal Server Error") - - -# NotImplemented is a python keyword. -class HttpNotImplemented(HttpServerError): - """HTTP 501 - Not Implemented. - - The server either does not recognize the request method, or it lacks - the ability to fulfill the request. - """ - http_status = 501 - message = _("Not Implemented") - - -class BadGateway(HttpServerError): - """HTTP 502 - Bad Gateway. - - The server was acting as a gateway or proxy and received an invalid - response from the upstream server. - """ - http_status = 502 - message = _("Bad Gateway") - - -class ServiceUnavailable(HttpServerError): - """HTTP 503 - Service Unavailable. - - The server is currently unavailable. - """ - http_status = 503 - message = _("Service Unavailable") - - -class GatewayTimeout(HttpServerError): - """HTTP 504 - Gateway Timeout. - - The server was acting as a gateway or proxy and did not receive a timely - response from the upstream server. - """ - http_status = 504 - message = _("Gateway Timeout") - - -class HttpVersionNotSupported(HttpServerError): - """HTTP 505 - HttpVersion Not Supported. - - The server does not support the HTTP protocol version used in the request. - """ - http_status = 505 - message = _("HTTP Version Not Supported") - - -# _code_map contains all the classes that have http_status attribute. -_code_map = dict( - (getattr(obj, 'http_status', None), obj) - for name, obj in six.iteritems(vars(sys.modules[__name__])) - if inspect.isclass(obj) and getattr(obj, 'http_status', False) -) - - -def from_response(response, method, url): - """Returns an instance of :class:`HttpError` or subclass based on response. - - :param response: instance of `requests.Response` class - :param method: HTTP method used for request - :param url: URL used for request - """ - - req_id = response.headers.get("x-openstack-request-id") - # NOTE(hdd) true for older versions of nova and cinder - if not req_id: - req_id = response.headers.get("x-compute-request-id") - kwargs = { - "http_status": response.status_code, - "response": response, - "method": method, - "url": url, - "request_id": req_id, - } - if "retry-after" in response.headers: - kwargs["retry_after"] = response.headers["retry-after"] - - content_type = response.headers.get("Content-Type", "") - if content_type.startswith("application/json"): - try: - body = response.json() - except ValueError: - pass - else: - if isinstance(body, dict) and isinstance(body.get("error"), dict): - error = body["error"] - kwargs["message"] = error.get("message") - kwargs["details"] = error.get("details") - elif content_type.startswith("text/"): - kwargs["details"] = response.text - - try: - cls = _code_map[response.status_code] - except KeyError: - if 500 <= response.status_code < 600: - cls = HttpServerError - elif 400 <= response.status_code < 500: - cls = HTTPClientError - else: - cls = HttpError - return cls(**kwargs) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/fake_client.py b/awx/lib/site-packages/ironicclient/openstack/common/apiclient/fake_client.py deleted file mode 100644 index c52501373e..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/fake_client.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -# W0102: Dangerous default value %s as argument -# pylint: disable=W0102 - -import json - -import requests -import six -from six.moves.urllib import parse - -from ironicclient.openstack.common.apiclient import client - - -def assert_has_keys(dct, required=None, optional=None): - required = required or [] - optional = optional or [] - for k in required: - try: - assert k in dct - except AssertionError: - extra_keys = set(dct.keys()).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class TestResponse(requests.Response): - """Wrap requests.Response and provide a convenient initialization. - """ - - def __init__(self, data): - super(TestResponse, self).__init__() - self._content_consumed = True - if isinstance(data, dict): - self.status_code = data.get('status_code', 200) - # Fake the text attribute to streamline Response creation - text = data.get('text', "") - if isinstance(text, (dict, list)): - self._content = json.dumps(text) - default_headers = { - "Content-Type": "application/json", - } - else: - self._content = text - default_headers = {} - if six.PY3 and isinstance(self._content, six.string_types): - self._content = self._content.encode('utf-8', 'strict') - self.headers = data.get('headers') or default_headers - else: - self.status_code = data - - def __eq__(self, other): - return (self.status_code == other.status_code and - self.headers == other.headers and - self._content == other._content) - - -class FakeHTTPClient(client.HTTPClient): - - def __init__(self, *args, **kwargs): - self.callstack = [] - self.fixtures = kwargs.pop("fixtures", None) or {} - if not args and "auth_plugin" not in kwargs: - args = (None, ) - super(FakeHTTPClient, self).__init__(*args, **kwargs) - - def assert_called(self, method, url, body=None, pos=-1): - """Assert than an API method was just called. - """ - expected = (method, url) - called = self.callstack[pos][0:2] - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - assert expected == called, 'Expected %s %s; got %s %s' % \ - (expected + called) - - if body is not None: - if self.callstack[pos][3] != body: - raise AssertionError('%r != %r' % - (self.callstack[pos][3], body)) - - def assert_called_anytime(self, method, url, body=None): - """Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - found = False - entry = None - for entry in self.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s %s; got %s' % \ - (method, url, self.callstack) - if body is not None: - assert entry[3] == body, "%s != %s" % (entry[3], body) - - self.callstack = [] - - def clear_callstack(self): - self.callstack = [] - - def authenticate(self): - pass - - def client_request(self, client, method, url, **kwargs): - # Check that certain things are called correctly - if method in ["GET", "DELETE"]: - assert "json" not in kwargs - - # Note the call - self.callstack.append( - (method, - url, - kwargs.get("headers") or {}, - kwargs.get("json") or kwargs.get("data"))) - try: - fixture = self.fixtures[url][method] - except KeyError: - pass - else: - return TestResponse({"headers": fixture[0], - "text": fixture[1]}) - - # Call the method - args = parse.parse_qsl(parse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - resp = getattr(self, callback)(**kwargs) - if len(resp) == 3: - status, headers, body = resp - else: - status, body = resp - headers = {} - self.last_request_id = headers.get('x-openstack-request-id', - 'req-test') - return TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/utils.py b/awx/lib/site-packages/ironicclient/openstack/common/apiclient/utils.py deleted file mode 100644 index 1e5c319467..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/apiclient/utils.py +++ /dev/null @@ -1,87 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.utils import encodeutils -import six - -from ironicclient.openstack.common._i18n import _ -from ironicclient.openstack.common.apiclient import exceptions -from ironicclient.openstack.common import uuidutils - - -def find_resource(manager, name_or_id, **find_args): - """Look for resource in a given manager. - - Used as a helper for the _find_* methods. - Example: - - .. code-block:: python - - def _find_hypervisor(cs, hypervisor): - #Get a hypervisor by name or ID. - return cliutils.find_resource(cs.hypervisors, hypervisor) - """ - # first try to get entity as integer id - try: - return manager.get(int(name_or_id)) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # now try to get entity as uuid - try: - if six.PY2: - tmp_id = encodeutils.safe_encode(name_or_id) - else: - tmp_id = encodeutils.safe_decode(name_or_id) - - if uuidutils.is_uuid_like(tmp_id): - return manager.get(tmp_id) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # for str id which is not uuid - if getattr(manager, 'is_alphanum_id_allowed', False): - try: - return manager.get(name_or_id) - except exceptions.NotFound: - pass - - try: - try: - return manager.find(human_id=name_or_id, **find_args) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - resource = getattr(manager, 'resource_class', None) - name_attr = resource.NAME_ATTR if resource else 'name' - kwargs = {name_attr: name_or_id} - kwargs.update(find_args) - return manager.find(**kwargs) - except exceptions.NotFound: - msg = _("No %(name)s with a name or " - "ID of '%(name_or_id)s' exists.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = _("Multiple %(name)s matches found for " - "'%(name_or_id)s', use an ID to be more specific.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/cliutils.py b/awx/lib/site-packages/ironicclient/openstack/common/cliutils.py deleted file mode 100644 index f81453aec3..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/cliutils.py +++ /dev/null @@ -1,325 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# W0603: Using the global statement -# W0621: Redefining name %s from outer scope -# pylint: disable=W0603,W0621 - -from __future__ import print_function - -import getpass -import inspect -import os -import sys -import textwrap - -import prettytable -import six -from six import moves - -from ironicclient.openstack.common.apiclient import exceptions -from ironicclient.openstack.common.gettextutils import _ -from ironicclient.openstack.common import strutils -from ironicclient.openstack.common import uuidutils - - -def validate_args(fn, *args, **kwargs): - """Check that the supplied args are sufficient for calling a function. - - >>> validate_args(lambda a: None) - Traceback (most recent call last): - ... - MissingArgs: Missing argument(s): a - >>> validate_args(lambda a, b, c, d: None, 0, c=1) - Traceback (most recent call last): - ... - MissingArgs: Missing argument(s): b, d - - :param fn: the function to check - :param arg: the positional arguments supplied - :param kwargs: the keyword arguments supplied - """ - argspec = inspect.getargspec(fn) - - num_defaults = len(argspec.defaults or []) - required_args = argspec.args[:len(argspec.args) - num_defaults] - - def isbound(method): - return getattr(method, '__self__', None) is not None - - if isbound(fn): - required_args.pop(0) - - missing = [arg for arg in required_args if arg not in kwargs] - missing = missing[len(args):] - if missing: - raise exceptions.MissingArgs(missing) - - -def arg(*args, **kwargs): - """Decorator for CLI args. - - Example: - - >>> @arg("name", help="Name of the new entity") - ... def entity_create(args): - ... pass - """ - def _decorator(func): - add_arg(func, *args, **kwargs) - return func - return _decorator - - -def env(*args, **kwargs): - """Returns the first environment variable set. - - If all are empty, defaults to '' or keyword arg `default`. - """ - for arg in args: - value = os.environ.get(arg) - if value: - return value - return kwargs.get('default', '') - - -def add_arg(func, *args, **kwargs): - """Bind CLI arguments to a shell.py `do_foo` function.""" - - if not hasattr(func, 'arguments'): - func.arguments = [] - - # NOTE(sirp): avoid dups that can occur when the module is shared across - # tests. - if (args, kwargs) not in func.arguments: - # Because of the semantics of decorator composition if we just append - # to the options list positional options will appear to be backwards. - func.arguments.insert(0, (args, kwargs)) - - -def unauthenticated(func): - """Adds 'unauthenticated' attribute to decorated function. - - Usage: - - >>> @unauthenticated - ... def mymethod(f): - ... pass - """ - func.unauthenticated = True - return func - - -def isunauthenticated(func): - """Checks if the function does not require authentication. - - Mark such functions with the `@unauthenticated` decorator. - - :returns: bool - """ - return getattr(func, 'unauthenticated', False) - - -def print_list(objs, fields, formatters=None, sortby_index=0, - mixed_case_fields=None, field_labels=None): - """Print a list or objects as a table, one row per object. - - :param objs: iterable of :class:`Resource` - :param fields: attributes that correspond to columns, in order - :param formatters: `dict` of callables for field formatting - :param sortby_index: index of the field for sorting table rows - :param mixed_case_fields: fields corresponding to object attributes that - have mixed case names (e.g., 'serverId') - :param field_labels: Labels to use in the heading of the table, default to - fields. - """ - formatters = formatters or {} - mixed_case_fields = mixed_case_fields or [] - field_labels = field_labels or fields - if len(field_labels) != len(fields): - raise ValueError(_("Field labels list %(labels)s has different number " - "of elements than fields list %(fields)s"), - {'labels': field_labels, 'fields': fields}) - - if sortby_index is None: - kwargs = {} - else: - kwargs = {'sortby': field_labels[sortby_index]} - pt = prettytable.PrettyTable(field_labels, caching=False) - pt.align = 'l' - - for o in objs: - row = [] - for field in fields: - if field in formatters: - row.append(formatters[field](o)) - else: - if field in mixed_case_fields: - field_name = field.replace(' ', '_') - else: - field_name = field.lower().replace(' ', '_') - data = getattr(o, field_name, '') - row.append(data) - pt.add_row(row) - - print(strutils.safe_encode(pt.get_string(**kwargs))) - - -def print_dict(dct, dict_property="Property", wrap=0): - """Print a `dict` as a table of two columns. - - :param dct: `dict` to print - :param dict_property: name of the first column - :param wrap: wrapping for the second column - """ - pt = prettytable.PrettyTable([dict_property, 'Value'], caching=False) - pt.align = 'l' - for k, v in six.iteritems(dct): - # convert dict to str to check length - if isinstance(v, dict): - v = six.text_type(v) - if wrap > 0: - v = textwrap.fill(six.text_type(v), wrap) - # if value has a newline, add in multiple rows - # e.g. fault with stacktrace - if v and isinstance(v, six.string_types) and r'\n' in v: - lines = v.strip().split(r'\n') - col1 = k - for line in lines: - pt.add_row([col1, line]) - col1 = '' - else: - pt.add_row([k, v]) - print(strutils.safe_encode(pt.get_string())) - - -def get_password(max_password_prompts=3): - """Read password from TTY.""" - verify = strutils.bool_from_string(env("OS_VERIFY_PASSWORD")) - pw = None - if hasattr(sys.stdin, "isatty") and sys.stdin.isatty(): - # Check for Ctrl-D - try: - for __ in moves.range(max_password_prompts): - pw1 = getpass.getpass("OS Password: ") - if verify: - pw2 = getpass.getpass("Please verify: ") - else: - pw2 = pw1 - if pw1 == pw2 and pw1: - pw = pw1 - break - except EOFError: - pass - return pw - - -def find_resource(manager, name_or_id, **find_args): - """Look for resource in a given manager. - - Used as a helper for the _find_* methods. - Example: - - .. code-block:: python - - def _find_hypervisor(cs, hypervisor): - #Get a hypervisor by name or ID. - return cliutils.find_resource(cs.hypervisors, hypervisor) - """ - # first try to get entity as integer id - try: - return manager.get(int(name_or_id)) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # now try to get entity as uuid - try: - if six.PY2: - tmp_id = strutils.safe_encode(name_or_id) - else: - tmp_id = strutils.safe_decode(name_or_id) - - if uuidutils.is_uuid_like(tmp_id): - return manager.get(tmp_id) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # for str id which is not uuid - if getattr(manager, 'is_alphanum_id_allowed', False): - try: - return manager.get(name_or_id) - except exceptions.NotFound: - pass - - try: - try: - return manager.find(human_id=name_or_id, **find_args) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - resource = getattr(manager, 'resource_class', None) - name_attr = resource.NAME_ATTR if resource else 'name' - kwargs = {name_attr: name_or_id} - kwargs.update(find_args) - return manager.find(**kwargs) - except exceptions.NotFound: - msg = _("No %(name)s with a name or " - "ID of '%(name_or_id)s' exists.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = _("Multiple %(name)s matches found for " - "'%(name_or_id)s', use an ID to be more specific.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - - -def service_type(stype): - """Adds 'service_type' attribute to decorated function. - - Usage: - - .. code-block:: python - - @service_type('volume') - def mymethod(f): - ... - """ - def inner(f): - f.service_type = stype - return f - return inner - - -def get_service_type(f): - """Retrieves service type from function.""" - return getattr(f, 'service_type', None) - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def exit(msg=''): - if msg: - print (msg, file=sys.stderr) - sys.exit(1) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/gettextutils.py b/awx/lib/site-packages/ironicclient/openstack/common/gettextutils.py deleted file mode 100644 index b1798ee048..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/gettextutils.py +++ /dev/null @@ -1,413 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -gettext for openstack-common modules. - -Usual usage in an openstack.common module: - - from ironicclient.openstack.common.gettextutils import _ -""" - -import copy -import gettext -import locale -from logging import handlers -import os -import re - -from babel import localedata -import six - -_localedir = os.environ.get('ironicclient'.upper() + '_LOCALEDIR') -_t = gettext.translation('ironicclient', localedir=_localedir, fallback=True) - -_AVAILABLE_LANGUAGES = {} -USE_LAZY = False - - -def enable_lazy(): - """Convenience function for configuring _() to use lazy gettext - - Call this at the start of execution to enable the gettextutils._ - function to use lazy gettext functionality. This is useful if - your project is importing _ directly instead of using the - gettextutils.install() way of importing the _ function. - """ - global USE_LAZY - USE_LAZY = True - - -def _(msg): - if USE_LAZY: - return Message(msg, domain='ironicclient') - else: - if six.PY3: - return _t.gettext(msg) - return _t.ugettext(msg) - - -def install(domain, lazy=False): - """Install a _() function using the given translation domain. - - Given a translation domain, install a _() function using gettext's - install() function. - - The main difference from gettext.install() is that we allow - overriding the default localedir (e.g. /usr/share/locale) using - a translation-domain-specific environment variable (e.g. - NOVA_LOCALEDIR). - - :param domain: the translation domain - :param lazy: indicates whether or not to install the lazy _() function. - The lazy _() introduces a way to do deferred translation - of messages by installing a _ that builds Message objects, - instead of strings, which can then be lazily translated into - any available locale. - """ - if lazy: - # NOTE(mrodden): Lazy gettext functionality. - # - # The following introduces a deferred way to do translations on - # messages in OpenStack. We override the standard _() function - # and % (format string) operation to build Message objects that can - # later be translated when we have more information. - def _lazy_gettext(msg): - """Create and return a Message object. - - Lazy gettext function for a given domain, it is a factory method - for a project/module to get a lazy gettext function for its own - translation domain (i.e. nova, glance, cinder, etc.) - - Message encapsulates a string so that we can translate - it later when needed. - """ - return Message(msg, domain=domain) - - from six import moves - moves.builtins.__dict__['_'] = _lazy_gettext - else: - localedir = '%s_LOCALEDIR' % domain.upper() - if six.PY3: - gettext.install(domain, - localedir=os.environ.get(localedir)) - else: - gettext.install(domain, - localedir=os.environ.get(localedir), - unicode=True) - - -class Message(six.text_type): - """A Message object is a unicode object that can be translated. - - Translation of Message is done explicitly using the translate() method. - For all non-translation intents and purposes, a Message is simply unicode, - and can be treated as such. - """ - - def __new__(cls, msgid, msgtext=None, params=None, domain='ironicclient', *args): - """Create a new Message object. - - In order for translation to work gettext requires a message ID, this - msgid will be used as the base unicode text. It is also possible - for the msgid and the base unicode text to be different by passing - the msgtext parameter. - """ - # If the base msgtext is not given, we use the default translation - # of the msgid (which is in English) just in case the system locale is - # not English, so that the base text will be in that locale by default. - if not msgtext: - msgtext = Message._translate_msgid(msgid, domain) - # We want to initialize the parent unicode with the actual object that - # would have been plain unicode if 'Message' was not enabled. - msg = super(Message, cls).__new__(cls, msgtext) - msg.msgid = msgid - msg.domain = domain - msg.params = params - return msg - - def translate(self, desired_locale=None): - """Translate this message to the desired locale. - - :param desired_locale: The desired locale to translate the message to, - if no locale is provided the message will be - translated to the system's default locale. - - :returns: the translated message in unicode - """ - - translated_message = Message._translate_msgid(self.msgid, - self.domain, - desired_locale) - if self.params is None: - # No need for more translation - return translated_message - - # This Message object may have been formatted with one or more - # Message objects as substitution arguments, given either as a single - # argument, part of a tuple, or as one or more values in a dictionary. - # When translating this Message we need to translate those Messages too - translated_params = _translate_args(self.params, desired_locale) - - translated_message = translated_message % translated_params - - return translated_message - - @staticmethod - def _translate_msgid(msgid, domain, desired_locale=None): - if not desired_locale: - system_locale = locale.getdefaultlocale() - # If the system locale is not available to the runtime use English - if not system_locale[0]: - desired_locale = 'en_US' - else: - desired_locale = system_locale[0] - - locale_dir = os.environ.get(domain.upper() + '_LOCALEDIR') - lang = gettext.translation(domain, - localedir=locale_dir, - languages=[desired_locale], - fallback=True) - if six.PY3: - translator = lang.gettext - else: - translator = lang.ugettext - - translated_message = translator(msgid) - return translated_message - - def __mod__(self, other): - # When we mod a Message we want the actual operation to be performed - # by the parent class (i.e. unicode()), the only thing we do here is - # save the original msgid and the parameters in case of a translation - unicode_mod = super(Message, self).__mod__(other) - modded = Message(self.msgid, - msgtext=unicode_mod, - params=self._sanitize_mod_params(other), - domain=self.domain) - return modded - - def _sanitize_mod_params(self, other): - """Sanitize the object being modded with this Message. - - - Add support for modding 'None' so translation supports it - - Trim the modded object, which can be a large dictionary, to only - those keys that would actually be used in a translation - - Snapshot the object being modded, in case the message is - translated, it will be used as it was when the Message was created - """ - if other is None: - params = (other,) - elif isinstance(other, dict): - params = self._trim_dictionary_parameters(other) - else: - params = self._copy_param(other) - return params - - def _trim_dictionary_parameters(self, dict_param): - """Return a dict that only has matching entries in the msgid.""" - # NOTE(luisg): Here we trim down the dictionary passed as parameters - # to avoid carrying a lot of unnecessary weight around in the message - # object, for example if someone passes in Message() % locals() but - # only some params are used, and additionally we prevent errors for - # non-deepcopyable objects by unicoding() them. - - # Look for %(param) keys in msgid; - # Skip %% and deal with the case where % is first character on the line - keys = re.findall('(?:[^%]|^)?%\((\w*)\)[a-z]', self.msgid) - - # If we don't find any %(param) keys but have a %s - if not keys and re.findall('(?:[^%]|^)%[a-z]', self.msgid): - # Apparently the full dictionary is the parameter - params = self._copy_param(dict_param) - else: - params = {} - for key in keys: - params[key] = self._copy_param(dict_param[key]) - - return params - - def _copy_param(self, param): - try: - return copy.deepcopy(param) - except TypeError: - # Fallback to casting to unicode this will handle the - # python code-like objects that can't be deep-copied - return six.text_type(param) - - def __add__(self, other): - msg = _('Message objects do not support addition.') - raise TypeError(msg) - - def __radd__(self, other): - return self.__add__(other) - - def __str__(self): - # NOTE(luisg): Logging in python 2.6 tries to str() log records, - # and it expects specifically a UnicodeError in order to proceed. - msg = _('Message objects do not support str() because they may ' - 'contain non-ascii characters. ' - 'Please use unicode() or translate() instead.') - raise UnicodeError(msg) - - -def get_available_languages(domain): - """Lists the available languages for the given translation domain. - - :param domain: the domain to get languages for - """ - if domain in _AVAILABLE_LANGUAGES: - return copy.copy(_AVAILABLE_LANGUAGES[domain]) - - localedir = '%s_LOCALEDIR' % domain.upper() - find = lambda x: gettext.find(domain, - localedir=os.environ.get(localedir), - languages=[x]) - - # NOTE(mrodden): en_US should always be available (and first in case - # order matters) since our in-line message strings are en_US - language_list = ['en_US'] - # NOTE(luisg): Babel <1.0 used a function called list(), which was - # renamed to locale_identifiers() in >=1.0, the requirements master list - # requires >=0.9.6, uncapped, so defensively work with both. We can remove - # this check when the master list updates to >=1.0, and update all projects - list_identifiers = (getattr(localedata, 'list', None) or - getattr(localedata, 'locale_identifiers')) - locale_identifiers = list_identifiers() - for i in locale_identifiers: - if find(i) is not None: - language_list.append(i) - _AVAILABLE_LANGUAGES[domain] = language_list - return copy.copy(language_list) - - -def translate(obj, desired_locale=None): - """Gets the translated unicode representation of the given object. - - If the object is not translatable it is returned as-is. - If the locale is None the object is translated to the system locale. - - :param obj: the object to translate - :param desired_locale: the locale to translate the message to, if None the - default system locale will be used - :returns: the translated object in unicode, or the original object if - it could not be translated - """ - message = obj - if not isinstance(message, Message): - # If the object to translate is not already translatable, - # let's first get its unicode representation - message = six.text_type(obj) - if isinstance(message, Message): - # Even after unicoding() we still need to check if we are - # running with translatable unicode before translating - return message.translate(desired_locale) - return obj - - -def _translate_args(args, desired_locale=None): - """Translates all the translatable elements of the given arguments object. - - This method is used for translating the translatable values in method - arguments which include values of tuples or dictionaries. - If the object is not a tuple or a dictionary the object itself is - translated if it is translatable. - - If the locale is None the object is translated to the system locale. - - :param args: the args to translate - :param desired_locale: the locale to translate the args to, if None the - default system locale will be used - :returns: a new args object with the translated contents of the original - """ - if isinstance(args, tuple): - return tuple(translate(v, desired_locale) for v in args) - if isinstance(args, dict): - translated_dict = {} - for (k, v) in six.iteritems(args): - translated_v = translate(v, desired_locale) - translated_dict[k] = translated_v - return translated_dict - return translate(args, desired_locale) - - -class TranslationHandler(handlers.MemoryHandler): - """Handler that translates records before logging them. - - The TranslationHandler takes a locale and a target logging.Handler object - to forward LogRecord objects to after translating them. This handler - depends on Message objects being logged, instead of regular strings. - - The handler can be configured declaratively in the logging.conf as follows: - - [handlers] - keys = translatedlog, translator - - [handler_translatedlog] - class = handlers.WatchedFileHandler - args = ('/var/log/api-localized.log',) - formatter = context - - [handler_translator] - class = openstack.common.log.TranslationHandler - target = translatedlog - args = ('zh_CN',) - - If the specified locale is not available in the system, the handler will - log in the default locale. - """ - - def __init__(self, locale=None, target=None): - """Initialize a TranslationHandler - - :param locale: locale to use for translating messages - :param target: logging.Handler object to forward - LogRecord objects to after translation - """ - # NOTE(luisg): In order to allow this handler to be a wrapper for - # other handlers, such as a FileHandler, and still be able to - # configure it using logging.conf, this handler has to extend - # MemoryHandler because only the MemoryHandlers' logging.conf - # parsing is implemented such that it accepts a target handler. - handlers.MemoryHandler.__init__(self, capacity=0, target=target) - self.locale = locale - - def setFormatter(self, fmt): - self.target.setFormatter(fmt) - - def emit(self, record): - # We save the message from the original record to restore it - # after translation, so other handlers are not affected by this - original_msg = record.msg - original_args = record.args - - try: - self._translate_and_log_record(record) - finally: - record.msg = original_msg - record.args = original_args - - def _translate_and_log_record(self, record): - record.msg = translate(record.msg, self.locale) - - # In addition to translating the message, we also need to translate - # arguments that were passed to the log method that were not part - # of the main message e.g., log.info(_('Some message %s'), this_one)) - record.args = _translate_args(record.args, self.locale) - - self.target.emit(record) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/importutils.py b/awx/lib/site-packages/ironicclient/openstack/common/importutils.py deleted file mode 100644 index e6bf556b8a..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/importutils.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class""" - mod_str, _sep, class_str = import_str.rpartition('.') - try: - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - except (ValueError, AttributeError): - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """ - Import a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/awx/lib/site-packages/ironicclient/openstack/common/strutils.py b/awx/lib/site-packages/ironicclient/openstack/common/strutils.py deleted file mode 100644 index c2870d38e9..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/strutils.py +++ /dev/null @@ -1,224 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -System-level utilities and helper functions. -""" - -import re -import sys -import unicodedata - -import six - -from ironicclient.openstack.common.gettextutils import _ - - -# Used for looking up extensions of text -# to their 'multiplied' byte amount -BYTE_MULTIPLIERS = { - '': 1, - 't': 1024 ** 4, - 'g': 1024 ** 3, - 'm': 1024 ** 2, - 'k': 1024, -} -BYTE_REGEX = re.compile(r'(^-?\d+)(\D*)') - -TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes') -FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no') - -SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]") -SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+") - - -def int_from_bool_as_string(subject): - """Interpret a string as a boolean and return either 1 or 0. - - Any string value in: - - ('True', 'true', 'On', 'on', '1') - - is interpreted as a boolean True. - - Useful for JSON-decoded stuff and config file parsing - """ - return bool_from_string(subject) and 1 or 0 - - -def bool_from_string(subject, strict=False, default=False): - """Interpret a string as a boolean. - - A case-insensitive match is performed such that strings matching 't', - 'true', 'on', 'y', 'yes', or '1' are considered True and, when - `strict=False`, anything else returns the value specified by 'default'. - - Useful for JSON-decoded stuff and config file parsing. - - If `strict=True`, unrecognized values, including None, will raise a - ValueError which is useful when parsing values passed in from an API call. - Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. - """ - if not isinstance(subject, six.string_types): - subject = str(subject) - - lowered = subject.strip().lower() - - if lowered in TRUE_STRINGS: - return True - elif lowered in FALSE_STRINGS: - return False - elif strict: - acceptable = ', '.join( - "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) - msg = _("Unrecognized value '%(val)s', acceptable values are:" - " %(acceptable)s") % {'val': subject, - 'acceptable': acceptable} - raise ValueError(msg) - else: - return default - - -def safe_decode(text, incoming=None, errors='strict'): - """Decodes incoming str using `incoming` if they're not already unicode. - - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a unicode `incoming` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, six.string_types): - raise TypeError("%s can't be decoded" % type(text)) - - if isinstance(text, six.text_type): - return text - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - try: - return text.decode(incoming, errors) - except UnicodeDecodeError: - # Note(flaper87) If we get here, it means that - # sys.stdin.encoding / sys.getdefaultencoding - # didn't return a suitable encoding to decode - # text. This happens mostly when global LANG - # var is not set correctly and there's no - # default encoding. In this case, most likely - # python will use ASCII or ANSI encoders as - # default encodings but they won't be capable - # of decoding non-ASCII characters. - # - # Also, UTF-8 is being used since it's an ASCII - # extension. - return text.decode('utf-8', errors) - - -def safe_encode(text, incoming=None, - encoding='utf-8', errors='strict'): - """Encodes incoming str/unicode using `encoding`. - - If incoming is not specified, text is expected to be encoded with - current python's default encoding. (`sys.getdefaultencoding`) - - :param incoming: Text's current encoding - :param encoding: Expected encoding for text (Default UTF-8) - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a bytestring `encoding` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, six.string_types): - raise TypeError("%s can't be encoded" % type(text)) - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - if isinstance(text, six.text_type): - if six.PY3: - return text.encode(encoding, errors).decode(incoming) - else: - return text.encode(encoding, errors) - elif text and encoding != incoming: - # Decode text before encoding it with `encoding` - text = safe_decode(text, incoming, errors) - if six.PY3: - return text.encode(encoding, errors).decode(incoming) - else: - return text.encode(encoding, errors) - - return text - - -def to_bytes(text, default=0): - """Converts a string into an integer of bytes. - - Looks at the last characters of the text to determine - what conversion is needed to turn the input text into a byte number. - Supports "B, K(B), M(B), G(B), and T(B)". (case insensitive) - - :param text: String input for bytes size conversion. - :param default: Default return value when text is blank. - - """ - match = BYTE_REGEX.search(text) - if match: - magnitude = int(match.group(1)) - mult_key_org = match.group(2) - if not mult_key_org: - return magnitude - elif text: - msg = _('Invalid string format: %s') % text - raise TypeError(msg) - else: - return default - mult_key = mult_key_org.lower().replace('b', '', 1) - multiplier = BYTE_MULTIPLIERS.get(mult_key) - if multiplier is None: - msg = _('Unknown byte multiplier: %s') % mult_key_org - raise TypeError(msg) - return magnitude * multiplier - - -def to_slug(value, incoming=None, errors="strict"): - """Normalize string. - - Convert to lowercase, remove non-word characters, and convert spaces - to hyphens. - - Inspired by Django's `slugify` filter. - - :param value: Text to slugify - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: slugified unicode representation of `value` - :raises TypeError: If text is not an instance of str - """ - value = safe_decode(value, incoming, errors) - # NOTE(aababilov): no need to use safe_(encode|decode) here: - # encodings are always "ascii", error handling is always "ignore" - # and types are always known (first: unicode; second: str) - value = unicodedata.normalize("NFKD", value).encode( - "ascii", "ignore").decode("ascii") - value = SLUGIFY_STRIP_RE.sub("", value).strip().lower() - return SLUGIFY_HYPHENATE_RE.sub("-", value) diff --git a/awx/lib/site-packages/ironicclient/openstack/common/uuidutils.py b/awx/lib/site-packages/ironicclient/openstack/common/uuidutils.py deleted file mode 100644 index 49c201aebf..0000000000 --- a/awx/lib/site-packages/ironicclient/openstack/common/uuidutils.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (c) 2012 Intel Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -UUID related utilities and helper functions. -""" - -import uuid - - -def generate_uuid(): - return str(uuid.uuid4()) - - -def is_uuid_like(val): - """Returns validation of a value as a UUID. - - For our purposes, a UUID is a canonical form string: - aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa - - """ - try: - return str(uuid.UUID(val)) == val - except (TypeError, ValueError, AttributeError): - return False diff --git a/awx/lib/site-packages/ironicclient/shell.py b/awx/lib/site-packages/ironicclient/shell.py deleted file mode 100644 index 9ff59a922d..0000000000 --- a/awx/lib/site-packages/ironicclient/shell.py +++ /dev/null @@ -1,544 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Command-line interface to the OpenStack Bare Metal Provisioning API. -""" - -from __future__ import print_function - -import argparse -import getpass -import logging -import sys - -import httplib2 -from keystoneclient.auth.identity import v2 as v2_auth -from keystoneclient.auth.identity import v3 as v3_auth -from keystoneclient import discover -from keystoneclient.openstack.common.apiclient import exceptions as ks_exc -from keystoneclient import session as kssession -import six.moves.urllib.parse as urlparse - - -import ironicclient -from ironicclient import client as iroclient -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient import exc -from ironicclient.openstack.common import cliutils - - -LATEST_API_VERSION = ('1', 'latest') - - -class IronicShell(object): - - def _append_global_identity_args(self, parser): - # FIXME(dhu): these are global identity (Keystone) arguments which - # should be consistent and shared by all service clients. Therefore, - # they should be provided by python-keystoneclient. We will need to - # refactor this code once this functionality is avaible in - # python-keystoneclient. - - # Register arguments needed for a Session - kssession.Session.register_cli_options(parser) - - parser.add_argument('--os-user-domain-id', - default=cliutils.env('OS_USER_DOMAIN_ID'), - help='Defaults to env[OS_USER_DOMAIN_ID].') - - parser.add_argument('--os-user-domain-name', - default=cliutils.env('OS_USER_DOMAIN_NAME'), - help='Defaults to env[OS_USER_DOMAIN_NAME].') - - parser.add_argument('--os-project-id', - default=cliutils.env('OS_PROJECT_ID'), - help='Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - ' --os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].') - - parser.add_argument('--os-project-name', - default=cliutils.env('OS_PROJECT_NAME'), - help='Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - ' --os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].') - - parser.add_argument('--os-project-domain-id', - default=cliutils.env('OS_PROJECT_DOMAIN_ID'), - help='Defaults to env[OS_PROJECT_DOMAIN_ID].') - - parser.add_argument('--os-project-domain-name', - default=cliutils.env('OS_PROJECT_DOMAIN_NAME'), - help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') - - def get_base_parser(self): - parser = argparse.ArgumentParser( - prog='ironic', - description=__doc__.strip(), - epilog='See "ironic help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=HelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS, - ) - - parser.add_argument('--version', - action='version', - version=ironicclient.__version__) - - parser.add_argument('--debug', - default=bool(cliutils.env('IRONICCLIENT_DEBUG')), - action='store_true', - help='Defaults to env[IRONICCLIENT_DEBUG]') - - parser.add_argument('-v', '--verbose', - default=False, action="store_true", - help="Print more verbose output") - - # for backward compatibility only - parser.add_argument('--cert-file', - dest='os_cert', - help='DEPRECATED! Use --os-cert.') - - # for backward compatibility only - parser.add_argument('--key-file', - dest='os_key', - help='DEPRECATED! Use --os-key.') - - # for backward compatibility only - parser.add_argument('--ca-file', - dest='os_cacert', - help='DEPRECATED! Use --os-cacert.') - - parser.add_argument('--os-username', - default=cliutils.env('OS_USERNAME'), - help='Defaults to env[OS_USERNAME]') - - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-password', - default=cliutils.env('OS_PASSWORD'), - help='Defaults to env[OS_PASSWORD]') - - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - default=cliutils.env('OS_TENANT_ID'), - help='Defaults to env[OS_TENANT_ID]') - - parser.add_argument('--os_tenant_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - default=cliutils.env('OS_TENANT_NAME'), - help='Defaults to env[OS_TENANT_NAME]') - - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-url', - default=cliutils.env('OS_AUTH_URL'), - help='Defaults to env[OS_AUTH_URL]') - - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-region-name', - default=cliutils.env('OS_REGION_NAME'), - help='Defaults to env[OS_REGION_NAME]') - - parser.add_argument('--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-token', - default=cliutils.env('OS_AUTH_TOKEN'), - help='Defaults to env[OS_AUTH_TOKEN]') - - parser.add_argument('--os_auth_token', - help=argparse.SUPPRESS) - - parser.add_argument('--ironic-url', - default=cliutils.env('IRONIC_URL'), - help='Defaults to env[IRONIC_URL]') - - parser.add_argument('--ironic_url', - help=argparse.SUPPRESS) - - parser.add_argument('--ironic-api-version', - default=cliutils.env( - 'IRONIC_API_VERSION', default='1'), - help='Accepts 1.x (where "x" is microversion) ' - 'or "latest", Defaults to ' - 'env[IRONIC_API_VERSION] or 1') - - parser.add_argument('--ironic_api_version', - help=argparse.SUPPRESS) - - parser.add_argument('--os-service-type', - default=cliutils.env('OS_SERVICE_TYPE'), - help='Defaults to env[OS_SERVICE_TYPE] or ' - '"baremetal"') - - parser.add_argument('--os_service_type', - help=argparse.SUPPRESS) - - parser.add_argument('--os-endpoint', - default=cliutils.env('OS_SERVICE_ENDPOINT'), - help='Specify an endpoint to use instead of ' - 'retrieving one from the service catalog ' - '(via authentication). ' - 'Defaults to env[OS_SERVICE_ENDPOINT].') - - parser.add_argument('--os_endpoint', - help=argparse.SUPPRESS) - - parser.add_argument('--os-endpoint-type', - default=cliutils.env('OS_ENDPOINT_TYPE'), - help='Defaults to env[OS_ENDPOINT_TYPE] or ' - '"publicURL"') - - parser.add_argument('--os_endpoint_type', - help=argparse.SUPPRESS) - - # FIXME(gyee): this method should come from python-keystoneclient. - # Will refactor this code once it is available. - # https://bugs.launchpad.net/python-keystoneclient/+bug/1332337 - - self._append_global_identity_args(parser) - - return parser - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='<subcommand>') - submodule = utils.import_versioned_module(version, 'shell') - submodule.enhance_parser(parser, subparsers, self.subcommands) - utils.define_commands_from_module(subparsers, self, self.subcommands) - return parser - - def _setup_debugging(self, debug): - if debug: - logging.basicConfig( - format="%(levelname)s (%(module)s:%(lineno)d) %(message)s", - level=logging.DEBUG) - - httplib2.debuglevel = 1 - else: - logging.basicConfig( - format="%(levelname)s %(message)s", - level=logging.CRITICAL) - - def do_bash_completion(self): - """Prints all of the commands and options for bash-completion.""" - commands = set() - options = set() - for sc_str, sc in self.subcommands.items(): - commands.add(sc_str) - for option in sc._optionals._option_string_actions.keys(): - options.add(option) - - commands.remove('bash-completion') - print(' '.join(commands | options)) - - def _discover_auth_versions(self, session, auth_url): - # discover the API versions the server is supporting base on the - # given URL - v2_auth_url = None - v3_auth_url = None - try: - ks_discover = discover.Discover(session=session, auth_url=auth_url) - v2_auth_url = ks_discover.url_for('2.0') - v3_auth_url = ks_discover.url_for('3.0') - except ks_exc.ClientException: - # Identity service may not support discover API version. - # Let's try to figure out the API version from the original URL. - url_parts = urlparse.urlparse(auth_url) - (scheme, netloc, path, params, query, fragment) = url_parts - path = path.lower() - if path.startswith('/v3'): - v3_auth_url = auth_url - elif path.startswith('/v2'): - v2_auth_url = auth_url - else: - # not enough information to determine the auth version - msg = _('Unable to determine the Keystone version ' - 'to authenticate with using the given ' - 'auth_url. Identity service may not support API ' - 'version discovery. Please provide a versioned ' - 'auth_url instead. %s') % auth_url - raise exc.CommandError(msg) - - return (v2_auth_url, v3_auth_url) - - def _get_keystone_v3_auth(self, v3_auth_url, **kwargs): - auth_token = kwargs.pop('auth_token', None) - if auth_token: - return v3_auth.Token(v3_auth_url, auth_token) - else: - return v3_auth.Password(v3_auth_url, **kwargs) - - def _get_keystone_v2_auth(self, v2_auth_url, **kwargs): - auth_token = kwargs.pop('auth_token', None) - if auth_token: - return v2_auth.Token(v2_auth_url, auth_token, - tenant_id=kwargs.pop('project_id', None), - tenant_name=kwargs.pop('project_name', None)) - else: - return v2_auth.Password( - v2_auth_url, - username=kwargs.pop('username', None), - password=kwargs.pop('password', None), - tenant_id=kwargs.pop('project_id', None), - tenant_name=kwargs.pop('project_name', None)) - - def _get_keystone_auth(self, session, auth_url, **kwargs): - # FIXME(dhu): this code should come from keystoneclient - - # discover the supported keystone versions using the given url - (v2_auth_url, v3_auth_url) = self._discover_auth_versions( - session=session, - auth_url=auth_url) - - # Determine which authentication plugin to use. First inspect the - # auth_url to see the supported version. If both v3 and v2 are - # supported, then use the highest version if possible. - auth = None - if v3_auth_url and v2_auth_url: - user_domain_name = kwargs.get('user_domain_name', None) - user_domain_id = kwargs.get('user_domain_id', None) - project_domain_name = kwargs.get('project_domain_name', None) - project_domain_id = kwargs.get('project_domain_id', None) - - # support both v2 and v3 auth. Use v3 if domain information is - # provided. - if (user_domain_name or user_domain_id or project_domain_name or - project_domain_id): - auth = self._get_keystone_v3_auth(v3_auth_url, **kwargs) - else: - auth = self._get_keystone_v2_auth(v2_auth_url, **kwargs) - elif v3_auth_url: - # support only v3 - auth = self._get_keystone_v3_auth(v3_auth_url, **kwargs) - elif v2_auth_url: - # support only v2 - auth = self._get_keystone_v2_auth(v2_auth_url, **kwargs) - else: - msg = _('Unable to determine the Keystone version ' - 'to authenticate with using the given ' - 'auth_url.') - raise exc.CommandError(msg) - - return auth - - def _check_version(self, api_version): - if api_version == 'latest': - return LATEST_API_VERSION - else: - try: - versions = tuple(int(i) for i in api_version.split('.')) - except ValueError: - versions = () - if len(versions) == 1: - # Default value of ironic_api_version is '1'. - # If user not specify the value of api version, not passing - # headers at all. - os_ironic_api_version = None - elif len(versions) == 2: - os_ironic_api_version = api_version - # In the case of '1.0' - if versions[1] == 0: - os_ironic_api_version = None - else: - msg = _("The requested API version %(ver)s is an unexpected " - "format. Acceptable formats are 'X', 'X.Y', or the " - "literal string '%(latest)s'." - ) % {'ver': api_version, 'latest': 'latest'} - raise exc.CommandError(msg) - - api_major_version = versions[0] - return (api_major_version, os_ironic_api_version) - - def main(self, argv): - # Parse args once to find version - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - self._setup_debugging(options.debug) - - # build available subcommands based on version - (api_major_version, os_ironic_api_version) = ( - self._check_version(options.ironic_api_version)) - - subcommand_parser = self.get_subcommand_parser(api_major_version) - self.parser = subcommand_parser - - # Handle top-level --help/-h before attempting to parse - # a command off the command line - if options.help or not argv: - self.do_help(options) - return 0 - - # Parse args again and call whatever callback was selected - args = subcommand_parser.parse_args(argv) - - # Short-circuit and deal with these commands right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion() - return 0 - - if not (args.os_auth_token and (args.ironic_url or args.os_endpoint)): - if not args.os_username: - raise exc.CommandError(_("You must provide a username via " - "either --os-username or via " - "env[OS_USERNAME]")) - - if not args.os_password: - # No password, If we've got a tty, try prompting for it - if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): - # Check for Ctl-D - try: - args.os_password = getpass.getpass( - 'OpenStack Password: ') - except EOFError: - pass - # No password because we didn't have a tty or the - # user Ctl-D when prompted. - if not args.os_password: - raise exc.CommandError(_("You must provide a password via " - "either --os-password, " - "env[OS_PASSWORD], " - "or prompted response")) - - if not (args.os_tenant_id or args.os_tenant_name or - args.os_project_id or args.os_project_name): - raise exc.CommandError( - _("You must provide a project name or" - " project id via --os-project-name, --os-project-id," - " env[OS_PROJECT_ID] or env[OS_PROJECT_NAME]. You may" - " use os-project and os-tenant interchangeably.")) - - if not args.os_auth_url: - raise exc.CommandError(_("You must provide an auth url via " - "either --os-auth-url or via " - "env[OS_AUTH_URL]")) - - endpoint = args.ironic_url or args.os_endpoint - service_type = args.os_service_type or 'baremetal' - project_id = args.os_project_id or args.os_tenant_id - project_name = args.os_project_name or args.os_tenant_name - - if (args.os_auth_token and (args.ironic_url or args.os_endpoint)): - kwargs = { - 'token': args.os_auth_token, - 'insecure': args.insecure, - 'timeout': args.timeout, - 'ca_file': args.os_cacert, - 'cert_file': args.os_cert, - 'key_file': args.os_key, - 'auth_ref': None, - } - elif (args.os_username and - args.os_password and - args.os_auth_url and - (project_id or project_name)): - - keystone_session = kssession.Session.load_from_cli_options(args) - - kwargs = { - 'username': args.os_username, - 'user_domain_id': args.os_user_domain_id, - 'user_domain_name': args.os_user_domain_name, - 'password': args.os_password, - 'auth_token': args.os_auth_token, - 'project_id': project_id, - 'project_name': project_name, - 'project_domain_id': args.os_project_domain_id, - 'project_domain_name': args.os_project_domain_name, - } - keystone_auth = self._get_keystone_auth(keystone_session, - args.os_auth_url, - **kwargs) - if not endpoint: - svc_type = args.os_service_type - region_name = args.os_region_name - endpoint = keystone_auth.get_endpoint(keystone_session, - service_type=svc_type, - region_name=region_name) - - endpoint_type = args.os_endpoint_type or 'publicURL' - kwargs = { - 'auth_url': args.os_auth_url, - 'session': keystone_session, - 'auth': keystone_auth, - 'service_type': service_type, - 'endpoint_type': endpoint_type, - 'region_name': args.os_region_name, - 'username': args.os_username, - 'password': args.os_password, - } - kwargs['os_ironic_api_version'] = os_ironic_api_version - client = iroclient.Client(api_major_version, endpoint, **kwargs) - - try: - args.func(client, args) - except exc.Unauthorized: - raise exc.CommandError(_("Invalid OpenStack Identity credentials")) - - @cliutils.arg('command', metavar='<subcommand>', nargs='?', - help='Display help for <subcommand>') - def do_help(self, args): - """Display help about this program or one of its subcommands.""" - if getattr(args, 'command', None): - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError(_("'%s' is not a valid subcommand") % - args.command) - else: - self.parser.print_help() - - -class HelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(HelpFormatter, self).start_section(heading) - - -def main(): - try: - IronicShell().main(sys.argv[1:]) - except KeyboardInterrupt: - print("... terminating ironic client", file=sys.stderr) - sys.exit(130) - except Exception as e: - print(str(e), file=sys.stderr) - sys.exit(1) - -if __name__ == "__main__": - main() diff --git a/awx/lib/site-packages/ironicclient/tests/__init__.py b/awx/lib/site-packages/ironicclient/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/tests/functional/__init__.py b/awx/lib/site-packages/ironicclient/tests/functional/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/tests/functional/test_ironicclient.py b/awx/lib/site-packages/ironicclient/tests/functional/test_ironicclient.py deleted file mode 100644 index e660d5db7b..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/functional/test_ironicclient.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import ConfigParser -import os - -import testtools - -import ironicclient -from ironicclient import exc - -DEFAULT_CONFIG = os.path.join(os.path.dirname(__file__), 'test.conf') - - -class TestIronicClient(testtools.TestCase): - def setUp(self): - super(TestIronicClient, self).setUp() - self.client = ironicclient.client.get_client(**self._get_config()) - - def _get_config(self): - config_file = os.environ.get('IRONICCLIENT_TEST_CONFIG', - DEFAULT_CONFIG) - config = ConfigParser.SafeConfigParser() - if not config.read(config_file): - self.skipTest('Skipping, no test config found @ %s' % config_file) - try: - auth_strategy = config.get('functional', 'auth_strategy') - except ConfigParser.NoOptionError: - auth_strategy = 'keystone' - if auth_strategy not in ['keystone', 'noauth']: - raise self.fail( - 'Invalid auth type specified in functional must be one of: ' - 'keystone, noauth') - out = {} - conf_settings = ['api_version'] - if auth_strategy == 'keystone': - conf_settings += ['os_auth_url', 'os_username', - 'os_password', 'os_tenant_name'] - - else: - conf_settings += ['os_auth_token', 'ironic_url'] - - for c in conf_settings: - try: - out[c] = config.get('functional', c) - except ConfigParser.NoOptionError: - out[c] = None - missing = [k for k, v in out.items() if not v] - if missing: - self.fail('Missing required setting in test.conf (%s) for ' - 'auth_strategy=%s: %s' % - (config_file, auth_strategy, ','.join(missing))) - return out - - def _try_delete_resource(self, resource, id): - mgr = getattr(self.client, resource) - try: - mgr.delete(id) - except exc.NotFound: - pass - - def _create_node(self, **kwargs): - if 'driver' not in kwargs: - kwargs['driver'] = 'fake' - node = self.client.node.create(**kwargs) - self.addCleanup(self._try_delete_resource, 'node', node.uuid) - return node - - def test_node_list(self): - self.assertTrue(isinstance(self.client.node.list(), list)) - - def test_node_create_get_delete(self): - node = self._create_node() - self.assertTrue(isinstance(node, ironicclient.v1.node.Node)) - got = self.client.node.get(node.uuid) - self.assertTrue(isinstance(got, ironicclient.v1.node.Node)) - self.client.node.delete(node.uuid) - self.assertRaises(exc.NotFound, self.client.node.get, node.uuid) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/__init__.py b/awx/lib/site-packages/ironicclient/tests/unit/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/tests/unit/keystone_client_fixtures.py b/awx/lib/site-packages/ironicclient/tests/unit/keystone_client_fixtures.py deleted file mode 100644 index 7c226aa7a4..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/keystone_client_fixtures.py +++ /dev/null @@ -1,81 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import uuid - -from keystoneclient.fixture import v2 as ks_v2_fixture -from keystoneclient.fixture import v3 as ks_v3_fixture - -# these are copied from python-keystoneclient tests -BASE_HOST = 'http://keystone.example.com' -BASE_URL = "%s:5000/" % BASE_HOST -UPDATED = '2013-03-06T00:00:00Z' - -V2_URL = "%sv2.0" % BASE_URL -V2_DESCRIBED_BY_HTML = {'href': 'http://docs.openstack.org/api/' - 'openstack-identity-service/2.0/content/', - 'rel': 'describedby', - 'type': 'text/html'} -V2_DESCRIBED_BY_PDF = {'href': 'http://docs.openstack.org/api/openstack-ident' - 'ity-service/2.0/identity-dev-guide-2.0.pdf', - 'rel': 'describedby', - 'type': 'application/pdf'} - -V2_VERSION = {'id': 'v2.0', - 'links': [{'href': V2_URL, 'rel': 'self'}, - V2_DESCRIBED_BY_HTML, V2_DESCRIBED_BY_PDF], - 'status': 'stable', - 'updated': UPDATED} - -V3_URL = "%sv3" % BASE_URL -V3_MEDIA_TYPES = [{'base': 'application/json', - 'type': 'application/vnd.openstack.identity-v3+json'}, - {'base': 'application/xml', - 'type': 'application/vnd.openstack.identity-v3+xml'}] - -V3_VERSION = {'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED} - -TOKENID = uuid.uuid4().hex - - -def _create_version_list(versions): - return json.dumps({'versions': {'values': versions}}) - - -def _create_single_version(version): - return json.dumps({'version': version}) - - -V3_VERSION_LIST = _create_version_list([V3_VERSION, V2_VERSION]) -V2_VERSION_LIST = _create_version_list([V2_VERSION]) - -V3_VERSION_ENTRY = _create_single_version(V3_VERSION) -V2_VERSION_ENTRY = _create_single_version(V2_VERSION) - - -def keystone_request_callback(request, uri, headers): - response_headers = {"content-type": "application/json"} - token_id = TOKENID - if uri == BASE_URL: - return (200, headers, V3_VERSION_LIST) - elif uri == BASE_URL + "/v2.0": - v2_token = ks_v2_fixture.Token(token_id) - return (200, response_headers, json.dumps(v2_token)) - elif uri == BASE_URL + "/v3": - v3_token = ks_v3_fixture.Token() - response_headers["X-Subject-Token"] = token_id - return (201, response_headers, json.dumps(v3_token)) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/test_client.py b/awx/lib/site-packages/ironicclient/tests/unit/test_client.py deleted file mode 100644 index 56e9ed74e9..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/test_client.py +++ /dev/null @@ -1,173 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures - -from ironicclient.client import get_client -from ironicclient import exc -from ironicclient.tests.unit import utils -from ironicclient.v1 import client as v1 - - -def fake_get_ksclient(**kwargs): - return utils.FakeKeystone('KSCLIENT_AUTH_TOKEN') - - -class ClientTest(utils.BaseTestCase): - - def test_get_client_with_auth_token_ironic_url(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'ironic_url': 'http://ironic.example.org:6385/', - 'os_auth_token': 'USER_AUTH_TOKEN', - } - client = get_client('1', **kwargs) - - self.assertEqual('USER_AUTH_TOKEN', client.http_client.auth_token) - self.assertEqual('http://ironic.example.org:6385/', - client.http_client.endpoint) - - def test_get_client_no_auth_token(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_auth_url': 'http://localhost:35357/v2.0', - 'os_auth_token': '', - } - client = get_client('1', **kwargs) - - self.assertEqual('KSCLIENT_AUTH_TOKEN', client.http_client.auth_token) - self.assertEqual('http://localhost:6385/v1/f14b41234', - client.http_client.endpoint) - self.assertEqual(fake_get_ksclient().auth_ref, - client.http_client.auth_ref) - - def test_get_client_with_region_no_auth_token(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_region_name': 'REGIONONE', - 'os_auth_url': 'http://localhost:35357/v2.0', - 'os_auth_token': '', - } - client = get_client('1', **kwargs) - - self.assertEqual('KSCLIENT_AUTH_TOKEN', client.http_client.auth_token) - self.assertEqual('http://regionhost:6385/v1/f14b41234', - client.http_client.endpoint) - self.assertEqual(fake_get_ksclient().auth_ref, - client.http_client.auth_ref) - - def test_get_client_with_auth_token(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_auth_url': 'http://localhost:35357/v2.0', - 'os_auth_token': 'USER_AUTH_TOKEN', - } - client = get_client('1', **kwargs) - - self.assertEqual('USER_AUTH_TOKEN', client.http_client.auth_token) - self.assertEqual('http://localhost:6385/v1/f14b41234', - client.http_client.endpoint) - self.assertEqual(fake_get_ksclient().auth_ref, - client.http_client.auth_ref) - - def test_get_client_with_region_name_auth_token(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_auth_url': 'http://localhost:35357/v2.0', - 'os_region_name': 'REGIONONE', - 'os_auth_token': 'USER_AUTH_TOKEN', - } - client = get_client('1', **kwargs) - - self.assertEqual('USER_AUTH_TOKEN', client.http_client.auth_token) - self.assertEqual('http://regionhost:6385/v1/f14b41234', - client.http_client.endpoint) - self.assertEqual(fake_get_ksclient().auth_ref, - client.http_client.auth_ref) - - def test_get_client_no_url_and_no_token(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_auth_url': '', - 'os_auth_token': '', - } - self.assertRaises(exc.AmbiguousAuthSystem, get_client, '1', **kwargs) - # test the alias as well to ensure backwards compatibility - self.assertRaises(exc.AmbigiousAuthSystem, get_client, '1', **kwargs) - - def test_ensure_auth_ref_propagated(self): - ksclient = fake_get_ksclient - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_auth_url': 'http://localhost:35357/v2.0', - 'os_auth_token': '', - } - client = get_client('1', **kwargs) - - self.assertEqual(ksclient().auth_ref, client.http_client.auth_ref) - - def test_get_client_with_api_version(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_auth_url': 'http://localhost:35357/v2.0', - 'os_auth_token': '', - 'os_ironic_api_version': 'latest', - } - client = get_client('1', **kwargs) - - self.assertEqual('latest', client.http_client.os_ironic_api_version) - - def test_get_client_default_version_set(self): - self.useFixture(fixtures.MonkeyPatch( - 'ironicclient.client._get_ksclient', fake_get_ksclient)) - kwargs = { - 'os_tenant_name': 'TENANT_NAME', - 'os_username': 'USERNAME', - 'os_password': 'PASSWORD', - 'os_auth_url': 'http://localhost:35357/v2.0', - 'os_auth_token': '', - } - client = get_client('1', **kwargs) - - self.assertEqual(v1.DEFAULT_VER, - client.http_client.os_ironic_api_version) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/test_http.py b/awx/lib/site-packages/ironicclient/tests/unit/test_http.py deleted file mode 100644 index 406c280750..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/test_http.py +++ /dev/null @@ -1,283 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json - -import six - -from ironicclient.common import http -from ironicclient import exc -from ironicclient.tests.unit import utils - - -HTTP_CLASS = six.moves.http_client.HTTPConnection -HTTPS_CLASS = http.VerifiedHTTPSConnection -DEFAULT_TIMEOUT = 600 - - -def _get_error_body(faultstring=None, debuginfo=None): - error_body = { - 'faultstring': faultstring, - 'debuginfo': debuginfo - } - raw_error_body = json.dumps(error_body) - body = {'error_message': raw_error_body} - raw_body = json.dumps(body) - return raw_body - - -class HttpClientTest(utils.BaseTestCase): - - def test_url_generation_trailing_slash_in_base(self): - client = http.HTTPClient('http://localhost/') - url = client._make_connection_url('/v1/resources') - self.assertEqual('/v1/resources', url) - - def test_url_generation_without_trailing_slash_in_base(self): - client = http.HTTPClient('http://localhost') - url = client._make_connection_url('/v1/resources') - self.assertEqual('/v1/resources', url) - - def test_url_generation_prefix_slash_in_path(self): - client = http.HTTPClient('http://localhost/') - url = client._make_connection_url('/v1/resources') - self.assertEqual('/v1/resources', url) - - def test_url_generation_without_prefix_slash_in_path(self): - client = http.HTTPClient('http://localhost') - url = client._make_connection_url('v1/resources') - self.assertEqual('/v1/resources', url) - - def test_server_exception_empty_body(self): - error_body = _get_error_body() - fake_resp = utils.FakeResponse({'content-type': 'application/json'}, - six.StringIO(error_body), - version=1, - status=500) - client = http.HTTPClient('http://localhost/') - client.get_connection = ( - lambda *a, **kw: utils.FakeConnection(fake_resp)) - - error = self.assertRaises(exc.InternalServerError, - client.json_request, - 'GET', '/v1/resources') - self.assertEqual('Internal Server Error (HTTP 500)', str(error)) - - def test_server_exception_msg_only(self): - error_msg = 'test error msg' - error_body = _get_error_body(error_msg) - fake_resp = utils.FakeResponse({'content-type': 'application/json'}, - six.StringIO(error_body), - version=1, - status=500) - client = http.HTTPClient('http://localhost/') - client.get_connection = ( - lambda *a, **kw: utils.FakeConnection(fake_resp)) - - error = self.assertRaises(exc.InternalServerError, - client.json_request, - 'GET', '/v1/resources') - self.assertEqual(error_msg + ' (HTTP 500)', str(error)) - - def test_server_exception_msg_and_traceback(self): - error_msg = 'another test error' - error_trace = ("\"Traceback (most recent call last):\\n\\n " - "File \\\"/usr/local/lib/python2.7/...") - error_body = _get_error_body(error_msg, error_trace) - fake_resp = utils.FakeResponse({'content-type': 'application/json'}, - six.StringIO(error_body), - version=1, - status=500) - client = http.HTTPClient('http://localhost/') - client.get_connection = ( - lambda *a, **kw: utils.FakeConnection(fake_resp)) - - error = self.assertRaises(exc.InternalServerError, - client.json_request, - 'GET', '/v1/resources') - - self.assertEqual( - '%(error)s (HTTP 500)\n%(trace)s' % {'error': error_msg, - 'trace': error_trace}, - "%(error)s\n%(details)s" % {'error': str(error), - 'details': str(error.details)}) - - def test_get_connection_params(self): - endpoint = 'http://ironic-host:6385' - expected = (HTTP_CLASS, - ('ironic-host', 6385, ''), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_trailing_slash(self): - endpoint = 'http://ironic-host:6385/' - expected = (HTTP_CLASS, - ('ironic-host', 6385, ''), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_ssl(self): - endpoint = 'https://ironic-host:6385' - expected = (HTTPS_CLASS, - ('ironic-host', 6385, ''), - { - 'timeout': DEFAULT_TIMEOUT, - 'ca_file': None, - 'cert_file': None, - 'key_file': None, - 'insecure': False, - }) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_ssl_params(self): - endpoint = 'https://ironic-host:6385' - ssl_args = { - 'ca_file': '/path/to/ca_file', - 'cert_file': '/path/to/cert_file', - 'key_file': '/path/to/key_file', - 'insecure': True, - } - - expected_kwargs = {'timeout': DEFAULT_TIMEOUT} - expected_kwargs.update(ssl_args) - expected = (HTTPS_CLASS, - ('ironic-host', 6385, ''), - expected_kwargs) - params = http.HTTPClient.get_connection_params(endpoint, **ssl_args) - self.assertEqual(expected, params) - - def test_get_connection_params_with_timeout(self): - endpoint = 'http://ironic-host:6385' - expected = (HTTP_CLASS, - ('ironic-host', 6385, ''), - {'timeout': 300.0}) - params = http.HTTPClient.get_connection_params(endpoint, timeout=300) - self.assertEqual(expected, params) - - def test_get_connection_params_with_version(self): - endpoint = 'http://ironic-host:6385/v1' - expected = (HTTP_CLASS, - ('ironic-host', 6385, ''), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_version_trailing_slash(self): - endpoint = 'http://ironic-host:6385/v1/' - expected = (HTTP_CLASS, - ('ironic-host', 6385, ''), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_subpath(self): - endpoint = 'http://ironic-host:6385/ironic' - expected = (HTTP_CLASS, - ('ironic-host', 6385, '/ironic'), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_subpath_trailing_slash(self): - endpoint = 'http://ironic-host:6385/ironic/' - expected = (HTTP_CLASS, - ('ironic-host', 6385, '/ironic'), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_subpath_version(self): - endpoint = 'http://ironic-host:6385/ironic/v1' - expected = (HTTP_CLASS, - ('ironic-host', 6385, '/ironic'), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_get_connection_params_with_subpath_version_trailing_slash(self): - endpoint = 'http://ironic-host:6385/ironic/v1/' - expected = (HTTP_CLASS, - ('ironic-host', 6385, '/ironic'), - {'timeout': DEFAULT_TIMEOUT}) - params = http.HTTPClient.get_connection_params(endpoint) - self.assertEqual(expected, params) - - def test_401_unauthorized_exception(self): - error_body = _get_error_body() - fake_resp = utils.FakeResponse({'content-type': 'text/plain'}, - six.StringIO(error_body), - version=1, - status=401) - client = http.HTTPClient('http://localhost/') - client.get_connection = ( - lambda *a, **kw: utils.FakeConnection(fake_resp)) - - self.assertRaises(exc.Unauthorized, client.json_request, - 'GET', '/v1/resources') - - -class SessionClientTest(utils.BaseTestCase): - - def test_server_exception_msg_and_traceback(self): - error_msg = 'another test error' - error_trace = ("\"Traceback (most recent call last):\\n\\n " - "File \\\"/usr/local/lib/python2.7/...") - error_body = _get_error_body(error_msg, error_trace) - - fake_session = utils.FakeSession({'Content-Type': 'application/json'}, - error_body, - 500) - - client = http.SessionClient(session=fake_session, - auth=None, - interface=None, - service_type='publicURL', - region_name='', - service_name=None) - - error = self.assertRaises(exc.InternalServerError, - client.json_request, - 'GET', '/v1/resources') - - self.assertEqual( - '%(error)s (HTTP 500)\n%(trace)s' % {'error': error_msg, - 'trace': error_trace}, - "%(error)s\n%(details)s" % {'error': str(error), - 'details': str(error.details)}) - - def test_server_exception_empty_body(self): - error_body = _get_error_body() - - fake_session = utils.FakeSession({'Content-Type': 'application/json'}, - error_body, - 500) - - client = http.SessionClient(session=fake_session, - auth=None, - interface=None, - service_type='publicURL', - region_name='', - service_name=None) - - error = self.assertRaises(exc.InternalServerError, - client.json_request, - 'GET', '/v1/resources') - - self.assertEqual('Internal Server Error (HTTP 500)', str(error)) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/test_import.py b/awx/lib/site-packages/ironicclient/tests/unit/test_import.py deleted file mode 100644 index 09d3c725c6..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/test_import.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.tests.unit import utils - -module_str = 'ironicclient' - - -class ImportTest(utils.BaseTestCase): - - def check_exported_symbols(self, exported_symbols): - self.assertIn('client', exported_symbols) - self.assertIn('exc', exported_symbols) - self.assertIn('exceptions', exported_symbols) - - def test_import_objects(self): - module = __import__(module_str) - exported_symbols = dir(module) - self.check_exported_symbols(exported_symbols) - - def test_default_import(self): - default_imports = __import__(module_str, globals(), locals(), ['*']) - exported_symbols = dir(default_imports) - self.check_exported_symbols(exported_symbols) - - def test_import__all__(self): - module = __import__(module_str) - self.check_exported_symbols(module.__all__) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/test_shell.py b/awx/lib/site-packages/ironicclient/tests/unit/test_shell.py deleted file mode 100644 index 8b229178f7..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/test_shell.py +++ /dev/null @@ -1,306 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import os -import re -import sys - -import fixtures -import httplib2 -import httpretty -from keystoneclient import exceptions as keystone_exc -from keystoneclient.fixture import v2 as ks_v2_fixture -from keystoneclient.fixture import v3 as ks_v3_fixture -import mock -import six -import testtools -from testtools import matchers - -from ironicclient import exc -from ironicclient import shell as ironic_shell -from ironicclient.tests.unit import keystone_client_fixtures -from ironicclient.tests.unit import utils - -FAKE_ENV = {'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': 'http://no.where/v2.0/'} - -FAKE_ENV_KEYSTONE_V2 = { - 'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': keystone_client_fixtures.BASE_URL, -} - -FAKE_ENV_KEYSTONE_V3 = { - 'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': keystone_client_fixtures.BASE_URL, - 'OS_USER_DOMAIN_ID': 'default', - 'OS_PROJECT_DOMAIN_ID': 'default', -} - - -class ShellTest(utils.BaseTestCase): - re_options = re.DOTALL | re.MULTILINE - - # Patch os.environ to avoid required auth info. - def make_env(self, exclude=None): - env = dict((k, v) for k, v in FAKE_ENV.items() if k != exclude) - self.useFixture(fixtures.MonkeyPatch('os.environ', env)) - - def setUp(self): - super(ShellTest, self).setUp() - - def shell(self, argstr): - orig = sys.stdout - try: - sys.stdout = six.StringIO() - _shell = ironic_shell.IronicShell() - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(0, exc_value.code) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - return out - - def test_help_unknown_command(self): - self.assertRaises(exc.CommandError, self.shell, 'help foofoo') - - def test_debug(self): - httplib2.debuglevel = 0 - self.shell('--debug help') - self.assertEqual(1, httplib2.debuglevel) - - def test_help(self): - required = [ - '.*?^usage: ironic', - '.*?^ +bash-completion', - '.*?^See "ironic help COMMAND" ' - 'for help on a specific command', - ] - for argstr in ['--help', 'help']: - help_text = self.shell(argstr) - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, - self.re_options)) - - def test_help_on_subcommand(self): - required = [ - '.*?^usage: ironic chassis-show', - ".*?^Show detailed information about a chassis", - ] - argstrings = [ - 'help chassis-show', - ] - for argstr in argstrings: - help_text = self.shell(argstr) - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, self.re_options)) - - def test_auth_param(self): - self.make_env(exclude='OS_USERNAME') - self.test_help() - - @mock.patch('sys.stdin', side_effect=mock.MagicMock) - @mock.patch('getpass.getpass', return_value='password') - def test_password_prompted(self, mock_getpass, mock_stdin): - self.make_env(exclude='OS_PASSWORD') - # We will get a Connection Refused because there is no keystone. - self.assertRaises(keystone_exc.ConnectionRefused, - self.shell, 'node-list') - # Make sure we are actually prompted. - mock_getpass.assert_called_with('OpenStack Password: ') - - @mock.patch('sys.stdin', side_effect=mock.MagicMock) - @mock.patch('getpass.getpass', side_effect=EOFError) - def test_password_prompted_ctrlD(self, mock_getpass, mock_stdin): - self.make_env(exclude='OS_PASSWORD') - # We should get Command Error because we mock Ctl-D. - self.assertRaises(exc.CommandError, - self.shell, 'node-list') - # Make sure we are actually prompted. - mock_getpass.assert_called_with('OpenStack Password: ') - - @mock.patch('sys.stdin') - def test_no_password_no_tty(self, mock_stdin): - # delete the isatty attribute so that we do not get - # prompted when manually running the tests - del mock_stdin.isatty - required = ('You must provide a password' - ' via either --os-password, env[OS_PASSWORD],' - ' or prompted response',) - self.make_env(exclude='OS_PASSWORD') - try: - self.shell('node-list') - except exc.CommandError as message: - self.assertEqual(required, message.args) - else: - self.fail('CommandError not raised') - - def test_bash_completion(self): - stdout = self.shell('bash-completion') - # just check we have some output - required = [ - '.*--driver_info', - '.*--chassis_uuid', - '.*help', - '.*node-create', - '.*chassis-create'] - for r in required: - self.assertThat(stdout, - matchers.MatchesRegex(r, self.re_options)) - - def test_ironic_api_version(self): - self.shell('--ironic-api-version 1.2 help') - self.shell('--ironic-api-version latest help') - self.assertRaises(exc.CommandError, - self.shell, '--ironic-api-version 1.2.1 help') - - -class TestCase(testtools.TestCase): - - tokenid = keystone_client_fixtures.TOKENID - - def set_fake_env(self, fake_env): - client_env = ('OS_USERNAME', 'OS_PASSWORD', 'OS_TENANT_ID', - 'OS_TENANT_NAME', 'OS_AUTH_URL', 'OS_REGION_NAME', - 'OS_AUTH_TOKEN', 'OS_NO_CLIENT_AUTH', 'OS_SERVICE_TYPE', - 'OS_ENDPOINT_TYPE') - - for key in client_env: - self.useFixture( - fixtures.EnvironmentVariable(key, fake_env.get(key))) - - # required for testing with Python 2.6 - def assertRegexpMatches(self, text, expected_regexp, msg=None): - """Fail the test unless the text matches the regular expression.""" - if isinstance(expected_regexp, six.string_types): - expected_regexp = re.compile(expected_regexp) - if not expected_regexp.search(text): - msg = msg or "Regexp didn't match" - msg = '%s: %r not found in %r' % ( - msg, expected_regexp.pattern, text) - raise self.failureException(msg) - - def register_keystone_v2_token_fixture(self): - v2_token = ks_v2_fixture.Token(token_id=self.tokenid) - service = v2_token.add_service('baremetal') - service.add_endpoint('http://ironic.example.com', region='RegionOne') - httpretty.register_uri( - httpretty.POST, - '%s/tokens' % (keystone_client_fixtures.V2_URL), - body=json.dumps(v2_token)) - - def register_keystone_v3_token_fixture(self): - v3_token = ks_v3_fixture.Token() - service = v3_token.add_service('baremetal') - service.add_standard_endpoints(public='http://ironic.example.com') - httpretty.register_uri( - httpretty.POST, - '%s/auth/tokens' % (keystone_client_fixtures.V3_URL), - body=json.dumps(v3_token), - adding_headers={'X-Subject-Token': self.tokenid}) - - def register_keystone_auth_fixture(self): - self.register_keystone_v2_token_fixture() - self.register_keystone_v3_token_fixture() - httpretty.register_uri( - httpretty.GET, - keystone_client_fixtures.BASE_URL, - body=keystone_client_fixtures.keystone_request_callback) - - -class ShellTestNoMox(TestCase): - def setUp(self): - super(ShellTestNoMox, self).setUp() - # httpretty doesn't work as expected if http proxy environment - # variable is set. - os.environ = dict((k, v) for (k, v) in os.environ.items() - if k.lower() not in ('http_proxy', 'https_proxy')) - self.set_fake_env(FAKE_ENV_KEYSTONE_V2) - - def shell(self, argstr): - orig = sys.stdout - try: - sys.stdout = six.StringIO() - _shell = ironic_shell.IronicShell() - _shell.main(argstr.split()) - self.subcommands = _shell.subcommands.keys() - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(0, exc_value.code) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - - return out - - @httpretty.activate - def test_node_list(self): - self.register_keystone_auth_fixture() - resp_dict = {"nodes": [ - {"instance_uuid": "null", - "uuid": "351a82d6-9f04-4c36-b79a-a38b9e98ff71", - "links": [{"href": "http://ironic.example.com:6385/" - "v1/nodes/foo", - "rel": "self"}, - {"href": "http://ironic.example.com:6385/" - "nodes/foo", - "rel": "bookmark"}], - "maintenance": "false", - "provision_state": "null", - "power_state": "power off"}, - {"instance_uuid": "null", - "uuid": "66fbba13-29e8-4b8a-9e80-c655096a40d3", - "links": [{"href": "http://ironic.example.com:6385/" - "v1/nodes/foo2", - "rel": "self"}, - {"href": "http://ironic.example.com:6385/" - "nodes/foo2", - "rel": "bookmark"}], - "maintenance": "false", - "provision_state": "null", - "power_state": "power off"}]} - httpretty.register_uri( - httpretty.GET, - 'http://ironic.example.com/v1/nodes', - status=200, - content_type='application/json; charset=UTF-8', - body=json.dumps(resp_dict)) - - event_list_text = self.shell('node-list') - - required = [ - '351a82d6-9f04-4c36-b79a-a38b9e98ff71', - '66fbba13-29e8-4b8a-9e80-c655096a40d3', - ] - - for r in required: - self.assertRegexpMatches(event_list_text, r) - - -class ShellTestNoMoxV3(ShellTestNoMox): - - def _set_fake_env(self): - self.set_fake_env(FAKE_ENV_KEYSTONE_V3) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/test_utils.py b/awx/lib/site-packages/ironicclient/tests/unit/test_utils.py deleted file mode 100644 index 2d8581c0e4..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/test_utils.py +++ /dev/null @@ -1,237 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import subprocess - -import mock - -from ironicclient.common import utils -from ironicclient import exc -from ironicclient.tests.unit import utils as test_utils - - -class UtilsTest(test_utils.BaseTestCase): - - def test_args_array_to_dict(self): - my_args = { - 'matching_metadata': ['str=foo', 'int=1', 'bool=true', - 'list=[1, 2, 3]', 'dict={"foo": "bar"}'], - 'other': 'value' - } - cleaned_dict = utils.args_array_to_dict(my_args, - "matching_metadata") - self.assertEqual({ - 'matching_metadata': {'str': 'foo', 'int': 1, 'bool': True, - 'list': [1, 2, 3], 'dict': {'foo': 'bar'}}, - 'other': 'value' - }, cleaned_dict) - - def test_args_array_to_patch(self): - my_args = { - 'attributes': ['str=foo', 'int=1', 'bool=true', - 'list=[1, 2, 3]', 'dict={"foo": "bar"}'], - 'op': 'add', - } - patch = utils.args_array_to_patch(my_args['op'], - my_args['attributes']) - self.assertEqual([{'op': 'add', 'value': 'foo', 'path': '/str'}, - {'op': 'add', 'value': 1, 'path': '/int'}, - {'op': 'add', 'value': True, 'path': '/bool'}, - {'op': 'add', 'value': [1, 2, 3], 'path': '/list'}, - {'op': 'add', 'value': {"foo": "bar"}, - 'path': '/dict'}], patch) - - def test_args_array_to_patch_format_error(self): - my_args = { - 'attributes': ['foobar'], - 'op': 'add', - } - self.assertRaises(exc.CommandError, utils.args_array_to_patch, - my_args['op'], my_args['attributes']) - - def test_args_array_to_patch_remove(self): - my_args = { - 'attributes': ['/foo', 'extra/bar'], - 'op': 'remove', - } - patch = utils.args_array_to_patch(my_args['op'], - my_args['attributes']) - self.assertEqual([{'op': 'remove', 'path': '/foo'}, - {'op': 'remove', 'path': '/extra/bar'}], patch) - - def test_split_and_deserialize(self): - ret = utils.split_and_deserialize('str=foo') - self.assertEqual(('str', 'foo'), ret) - - ret = utils.split_and_deserialize('int=1') - self.assertEqual(('int', 1), ret) - - ret = utils.split_and_deserialize('bool=false') - self.assertEqual(('bool', False), ret) - - ret = utils.split_and_deserialize('list=[1, "foo", 2]') - self.assertEqual(('list', [1, "foo", 2]), ret) - - ret = utils.split_and_deserialize('dict={"foo": 1}') - self.assertEqual(('dict', {"foo": 1}), ret) - - ret = utils.split_and_deserialize('str_int="1"') - self.assertEqual(('str_int', "1"), ret) - - def test_split_and_deserialize_fail(self): - self.assertRaises(exc.CommandError, - utils.split_and_deserialize, 'foo:bar') - - -class CommonParamsForListTest(test_utils.BaseTestCase): - def setUp(self): - super(CommonParamsForListTest, self).setUp() - self.args = mock.Mock(marker=None, limit=None, - sort_key=None, sort_dir=None) - self.args.detail = False - self.expected_params = {'detail': False} - - def test_nothing_set(self): - self.assertEqual(self.expected_params, - utils.common_params_for_list(self.args, [], [])) - - def test_marker_and_limit(self): - self.args.marker = 'foo' - self.args.limit = 42 - self.expected_params.update({'marker': 'foo', 'limit': 42}) - self.assertEqual(self.expected_params, - utils.common_params_for_list(self.args, [], [])) - - def test_invalid_limit(self): - self.args.limit = -42 - self.assertRaises(exc.CommandError, - utils.common_params_for_list, - self.args, [], []) - - def test_sort_key_and_sort_dir(self): - self.args.sort_key = 'field' - self.args.sort_dir = 'desc' - self.expected_params.update({'sort_key': 'field', 'sort_dir': 'desc'}) - self.assertEqual(self.expected_params, - utils.common_params_for_list(self.args, - ['field'], - [])) - - def test_sort_key_allows_label(self): - self.args.sort_key = 'Label' - self.expected_params.update({'sort_key': 'field'}) - self.assertEqual(self.expected_params, - utils.common_params_for_list(self.args, - ['field', 'field2'], - ['Label', 'Label2'])) - - def test_sort_key_invalid(self): - self.args.sort_key = 'something' - self.assertRaises(exc.CommandError, - utils.common_params_for_list, - self.args, - ['field', 'field2'], - []) - - def test_sort_dir_invalid(self): - self.args.sort_dir = 'something' - self.assertRaises(exc.CommandError, - utils.common_params_for_list, - self.args, - [], - []) - - def test_detail(self): - self.args.detail = True - self.expected_params['detail'] = True - self.assertEqual(self.expected_params, - utils.common_params_for_list(self.args, [], [])) - - -class CommonFiltersTest(test_utils.BaseTestCase): - def test_limit(self): - result = utils.common_filters(limit=42) - self.assertEqual(['limit=42'], result) - - def test_limit_0(self): - result = utils.common_filters(limit=0) - self.assertEqual([], result) - - def test_other(self): - for key in ('marker', 'sort_key', 'sort_dir'): - result = utils.common_filters(**{key: 'test'}) - self.assertEqual(['%s=test' % key], result) - - -@mock.patch.object(subprocess, 'Popen') -class MakeConfigDriveTest(test_utils.BaseTestCase): - - def setUp(self): - super(MakeConfigDriveTest, self).setUp() - # expected genisoimage cmd - self.genisoimage_cmd = ['genisoimage', '-o', mock.ANY, - '-ldots', '-allow-lowercase', - '-allow-multidot', '-l', - '-publisher', 'ironicclient-configdrive 0.1', - '-quiet', '-J', '-r', '-V', - 'config-2', mock.ANY] - - def test_make_configdrive(self, mock_popen): - fake_process = mock.Mock(returncode=0) - fake_process.communicate.return_value = ('', '') - mock_popen.return_value = fake_process - - with utils.tempdir() as dirname: - utils.make_configdrive(dirname) - - mock_popen.assert_called_once_with(self.genisoimage_cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE) - fake_process.communicate.assert_called_once_with() - - @mock.patch.object(os, 'access') - def test_make_configdrive_non_readable_dir(self, mock_access, mock_popen): - mock_access.return_value = False - self.assertRaises(exc.CommandError, utils.make_configdrive, 'fake-dir') - mock_access.assert_called_once_with('fake-dir', os.R_OK) - self.assertFalse(mock_popen.called) - - @mock.patch.object(os, 'access') - def test_make_configdrive_oserror(self, mock_access, mock_popen): - mock_access.return_value = True - mock_popen.side_effect = OSError('boom') - - self.assertRaises(exc.CommandError, utils.make_configdrive, 'fake-dir') - mock_access.assert_called_once_with('fake-dir', os.R_OK) - mock_popen.assert_called_once_with(self.genisoimage_cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE) - - @mock.patch.object(os, 'access') - def test_make_configdrive_non_zero_returncode(self, mock_access, - mock_popen): - fake_process = mock.Mock(returncode=123) - fake_process.communicate.return_value = ('', '') - mock_popen.return_value = fake_process - - self.assertRaises(exc.CommandError, utils.make_configdrive, 'fake-dir') - mock_access.assert_called_once_with('fake-dir', os.R_OK) - mock_popen.assert_called_once_with(self.genisoimage_cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE) - fake_process.communicate.assert_called_once_with() diff --git a/awx/lib/site-packages/ironicclient/tests/unit/utils.py b/awx/lib/site-packages/ironicclient/tests/unit/utils.py deleted file mode 100644 index 36286cd5b2..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/utils.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import datetime -import os - -import fixtures -from oslo_utils import strutils -import six -import testtools - -from ironicclient.common import http - - -class BaseTestCase(testtools.TestCase): - - def setUp(self): - super(BaseTestCase, self).setUp() - self.useFixture(fixtures.FakeLogger()) - - # If enabled, stdout and/or stderr is captured and will appear in - # test results if that test fails. - if strutils.bool_from_string(os.environ.get('OS_STDOUT_CAPTURE')): - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if strutils.bool_from_string(os.environ.get('OS_STDERR_CAPTURE')): - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - - -class FakeAPI(object): - def __init__(self, responses): - self.responses = responses - self.calls = [] - - def _request(self, method, url, headers=None, body=None): - call = (method, url, headers or {}, body) - self.calls.append(call) - return self.responses[url][method] - - def raw_request(self, *args, **kwargs): - response = self._request(*args, **kwargs) - body_iter = http.ResponseBodyIterator(six.StringIO(response[1])) - return FakeResponse(response[0]), body_iter - - def json_request(self, *args, **kwargs): - response = self._request(*args, **kwargs) - return FakeResponse(response[0]), response[1] - - -class FakeConnection(object): - def __init__(self, response=None): - self._response = response - self._last_request = None - - def request(self, method, conn_url, **kwargs): - self._last_request = (method, conn_url, kwargs) - - def setresponse(self, response): - self._response = response - - def getresponse(self): - return self._response - - -class FakeResponse(object): - def __init__(self, headers, body=None, version=None, status=None, - reason=None): - """Fake object to help testing. - - :param headers: dict representing HTTP response headers - :param body: file-like object - """ - self.headers = headers - self.body = body - self.version = version - self.status = status - self.reason = reason - - def getheaders(self): - return copy.deepcopy(self.headers).items() - - def getheader(self, key, default): - return self.headers.get(key, default) - - def read(self, amt): - return self.body.read(amt) - - -class FakeServiceCatalog(): - def url_for(self, endpoint_type, service_type, attr=None, - filter_value=None): - if attr == 'region' and filter_value: - return 'http://regionhost:6385/v1/f14b41234' - else: - return 'http://localhost:6385/v1/f14b41234' - - -class FakeKeystone(): - service_catalog = FakeServiceCatalog() - timestamp = datetime.datetime.utcnow() + datetime.timedelta(days=5) - - def __init__(self, auth_token): - self.auth_token = auth_token - self.auth_ref = { - 'token': {'expires': FakeKeystone.timestamp.strftime( - '%Y-%m-%dT%H:%M:%S.%f'), - 'id': 'd1a541311782870742235'} - } - - -class FakeSessionResponse(): - - def __init__(self, headers, content=None, status_code=None): - self.headers = headers - self.content = content - self.status_code = status_code - - -class FakeSession(): - - def __init__(self, headers, content=None, status_code=None): - self.headers = headers - self.content = content - self.status_code = status_code - - def request(self, url, method, **kwargs): - return FakeSessionResponse(self.headers, self.content, - self.status_code) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/__init__.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_chassis.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_chassis.py deleted file mode 100644 index 8e5d15ee09..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_chassis.py +++ /dev/null @@ -1,351 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -import testtools -from testtools.matchers import HasLength - -from ironicclient.tests.unit import utils -import ironicclient.v1.chassis - -CHASSIS = {'id': 42, - 'uuid': 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee', - 'extra': {}, - 'description': 'data-center-1-chassis'} - -CHASSIS2 = {'id': 43, - 'uuid': 'eeeeeeee-dddd-cccc-bbbb-aaaaaaaaaaaa', - 'extra': {}, - 'description': 'data-center-1-chassis'} - - -NODE = {'id': 123, - 'uuid': '66666666-7777-8888-9999-000000000000', - 'chassis_id': 42, - 'driver': 'fake', - 'driver_info': {'user': 'foo', 'password': 'bar'}, - 'properties': {'num_cpu': 4}, - 'extra': {}} - -CREATE_CHASSIS = copy.deepcopy(CHASSIS) -del CREATE_CHASSIS['id'] -del CREATE_CHASSIS['uuid'] - -UPDATED_CHASSIS = copy.deepcopy(CHASSIS) -NEW_DESCR = 'new-description' -UPDATED_CHASSIS['description'] = NEW_DESCR - -fake_responses = { - '/v1/chassis': - { - 'GET': ( - {}, - {"chassis": [CHASSIS]}, - ), - 'POST': ( - {}, - CREATE_CHASSIS, - ), - }, - '/v1/chassis/detail': - { - 'GET': ( - {}, - {"chassis": [CHASSIS]}, - ), - }, - '/v1/chassis/%s' % CHASSIS['uuid']: - { - 'GET': ( - {}, - CHASSIS, - ), - 'DELETE': ( - {}, - None, - ), - 'PATCH': ( - {}, - UPDATED_CHASSIS, - ), - }, - '/v1/chassis/%s/nodes' % CHASSIS['uuid']: - { - 'GET': ( - {}, - {"nodes": [NODE]}, - ), - }, - '/v1/chassis/%s/nodes/detail' % CHASSIS['uuid']: - { - 'GET': ( - {}, - {"nodes": [NODE]}, - ), - }, -} - -fake_responses_pagination = { - '/v1/chassis': - { - 'GET': ( - {}, - {"chassis": [CHASSIS], - "next": "http://127.0.0.1:6385/v1/chassis/?limit=1"} - ), - }, - '/v1/chassis/?limit=1': - { - 'GET': ( - {}, - {"chassis": [CHASSIS2]} - ), - }, - '/v1/chassis/?marker=%s' % CHASSIS['uuid']: - { - 'GET': ( - {}, - {"chassis": [CHASSIS2]} - ), - }, - '/v1/chassis/%s/nodes?limit=1' % CHASSIS['uuid']: - { - 'GET': ( - {}, - {"nodes": [NODE]}, - ), - }, - '/v1/chassis/%s/nodes?marker=%s' % (CHASSIS['uuid'], NODE['uuid']): - { - 'GET': ( - {}, - {"nodes": [NODE]}, - ), - }, -} - -fake_responses_sorting = { - '/v1/chassis/?sort_key=updated_at': - { - 'GET': ( - {}, - {"chassis": [CHASSIS2]} - ), - }, - '/v1/chassis/?sort_dir=desc': - { - 'GET': ( - {}, - {"chassis": [CHASSIS2]} - ), - }, - '/v1/chassis/%s/nodes?sort_key=updated_at' % CHASSIS['uuid']: - { - 'GET': ( - {}, - {"nodes": [NODE]}, - ), - }, - '/v1/chassis/%s/nodes?sort_dir=desc' % CHASSIS['uuid']: - { - 'GET': ( - {}, - {"nodes": [NODE]}, - ), - }, -} - - -class ChassisManagerTest(testtools.TestCase): - - def setUp(self): - super(ChassisManagerTest, self).setUp() - self.api = utils.FakeAPI(fake_responses) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - - def test_chassis_list(self): - chassis = self.mgr.list() - expect = [ - ('GET', '/v1/chassis', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(chassis)) - - def test_chassis_list_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - chassis = self.mgr.list(limit=1) - expect = [ - ('GET', '/v1/chassis/?limit=1', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(chassis, HasLength(1)) - - def test_chassis_list_marker(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - chassis = self.mgr.list(marker=CHASSIS['uuid']) - expect = [ - ('GET', '/v1/chassis/?marker=%s' % CHASSIS['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(chassis, HasLength(1)) - - def test_chassis_list_pagination_no_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - chassis = self.mgr.list(limit=0) - expect = [ - ('GET', '/v1/chassis', {}, None), - ('GET', '/v1/chassis/?limit=1', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(chassis, HasLength(2)) - - def test_chassis_list_sort_key(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - chassis = self.mgr.list(sort_key='updated_at') - expect = [ - ('GET', '/v1/chassis/?sort_key=updated_at', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(chassis, HasLength(1)) - - def test_chassis_list_sort_dir(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - chassis = self.mgr.list(sort_dir='desc') - expect = [ - ('GET', '/v1/chassis/?sort_dir=desc', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(chassis, HasLength(1)) - - def test_chassis_list_detail(self): - chassis = self.mgr.list(detail=True) - expect = [ - ('GET', '/v1/chassis/detail', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(chassis)) - - def test_chassis_show(self): - chassis = self.mgr.get(CHASSIS['uuid']) - expect = [ - ('GET', '/v1/chassis/%s' % CHASSIS['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(CHASSIS['uuid'], chassis.uuid) - self.assertEqual(CHASSIS['description'], chassis.description) - - def test_create(self): - chassis = self.mgr.create(**CREATE_CHASSIS) - expect = [ - ('POST', '/v1/chassis', {}, CREATE_CHASSIS), - ] - self.assertEqual(expect, self.api.calls) - self.assertTrue(chassis) - - def test_delete(self): - chassis = self.mgr.delete(chassis_id=CHASSIS['uuid']) - expect = [ - ('DELETE', '/v1/chassis/%s' % CHASSIS['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertIsNone(chassis) - - def test_update(self): - patch = {'op': 'replace', - 'value': NEW_DESCR, - 'path': '/description'} - chassis = self.mgr.update(chassis_id=CHASSIS['uuid'], patch=patch) - expect = [ - ('PATCH', '/v1/chassis/%s' % CHASSIS['uuid'], {}, patch), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(NEW_DESCR, chassis.description) - - def test_chassis_node_list(self): - nodes = self.mgr.list_nodes(CHASSIS['uuid']) - expect = [ - ('GET', '/v1/chassis/%s/nodes' % CHASSIS['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(nodes)) - self.assertEqual(NODE['uuid'], nodes[0].uuid) - - def test_chassis_node_list_detail(self): - nodes = self.mgr.list_nodes(CHASSIS['uuid'], detail=True) - expect = [ - ('GET', '/v1/chassis/%s/nodes/detail' % CHASSIS['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(nodes)) - self.assertEqual(NODE['uuid'], nodes[0].uuid) - - def test_chassis_node_list_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - nodes = self.mgr.list_nodes(CHASSIS['uuid'], limit=1) - expect = [ - ('GET', - '/v1/chassis/%s/nodes?limit=1' % CHASSIS['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE['uuid'], nodes[0].uuid) - - def test_chassis_node_list_sort_key(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - nodes = self.mgr.list_nodes(CHASSIS['uuid'], sort_key='updated_at') - expect = [ - ('GET', - '/v1/chassis/%s/nodes?sort_key=updated_at' % CHASSIS['uuid'], {}, - None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE['uuid'], nodes[0].uuid) - - def test_chassis_node_list_sort_dir(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - nodes = self.mgr.list_nodes(CHASSIS['uuid'], sort_dir='desc') - expect = [ - ('GET', - '/v1/chassis/%s/nodes?sort_dir=desc' % CHASSIS['uuid'], {}, - None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE['uuid'], nodes[0].uuid) - - def test_chassis_node_list_marker(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.chassis.ChassisManager(self.api) - nodes = self.mgr.list_nodes(CHASSIS['uuid'], marker=NODE['uuid']) - expect = [ - ('GET', - '/v1/chassis/%s/nodes?marker=%s' % (CHASSIS['uuid'], - NODE['uuid']), {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE['uuid'], nodes[0].uuid) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_chassis_shell.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_chassis_shell.py deleted file mode 100644 index 21d036647b..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_chassis_shell.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 IBM Corp -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ironicclient.openstack.common import cliutils -from ironicclient.tests.unit import utils -import ironicclient.v1.chassis_shell as c_shell - - -class ChassisShellTest(utils.BaseTestCase): - def test_chassis_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - chassis = object() - c_shell._print_chassis_show(chassis) - exp = ['created_at', 'description', 'extra', 'updated_at', 'uuid'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_driver.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_driver.py deleted file mode 100644 index 48f28c1af3..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_driver.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import testtools -from testtools import matchers - -from ironicclient import exc -from ironicclient.tests.unit import utils -from ironicclient.v1 import driver - - -DRIVER1 = {'name': 'fake', 'hosts': ['fake-host1', 'fake-host2']} -DRIVER2 = {'name': 'pxe_ipminative', 'hosts': ['fake-host1', 'fake-host2']} - -DRIVER2_PROPERTIES = { - "username": "username. Required.", - "password": "password. Optional.", - "address": "IP of the node. Required.", -} - -fake_responses = { - '/v1/drivers': - { - 'GET': ( - {}, - {'drivers': [DRIVER1]}, - ), - }, - '/v1/drivers/%s' % DRIVER1['name']: - { - 'GET': ( - {}, - DRIVER1 - ), - }, - '/v1/drivers/%s/properties' % DRIVER2['name']: - { - 'GET': ( - {}, - DRIVER2_PROPERTIES, - ), - } -} - - -class DriverManagerTest(testtools.TestCase): - - def setUp(self): - super(DriverManagerTest, self).setUp() - self.api = utils.FakeAPI(fake_responses) - self.mgr = driver.DriverManager(self.api) - - def test_driver_list(self): - drivers = self.mgr.list() - expect = [ - ('GET', '/v1/drivers', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(drivers, matchers.HasLength(1)) - - def test_driver_show(self): - driver_ = self.mgr.get(DRIVER1['name']) - expect = [ - ('GET', '/v1/drivers/%s' % DRIVER1['name'], {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(DRIVER1['name'], driver_.name) - self.assertEqual(DRIVER1['hosts'], driver_.hosts) - - def test_driver_properties(self): - properties = self.mgr.properties(DRIVER2['name']) - expect = [ - ('GET', '/v1/drivers/%s/properties' % DRIVER2['name'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(DRIVER2_PROPERTIES, properties) - - @mock.patch.object(driver.DriverManager, 'update') - def test_vendor_passthru_update(self, update_mock): - # For now just mock the tests because vendor-passthru doesn't return - # anything to verify. - vendor_passthru_args = {'arg1': 'val1'} - kwargs = { - 'driver_name': 'driver_name', - 'method': 'method', - 'args': vendor_passthru_args - } - - final_path = 'driver_name/vendor_passthru/method' - for http_method in ('POST', 'PUT', 'PATCH'): - kwargs['http_method'] = http_method - self.mgr.vendor_passthru(**kwargs) - update_mock.assert_called_once_with(final_path, - vendor_passthru_args, - http_method=http_method) - update_mock.reset_mock() - - @mock.patch.object(driver.DriverManager, 'get') - def test_vendor_passthru_get(self, get_mock): - kwargs = { - 'driver_name': 'driver_name', - 'method': 'method', - 'http_method': 'GET', - } - - final_path = 'driver_name/vendor_passthru/method' - self.mgr.vendor_passthru(**kwargs) - get_mock.assert_called_once_with(final_path) - - @mock.patch.object(driver.DriverManager, 'delete') - def test_vendor_passthru_delete(self, delete_mock): - kwargs = { - 'driver_name': 'driver_name', - 'method': 'method', - 'http_method': 'DELETE', - } - - final_path = 'driver_name/vendor_passthru/method' - self.mgr.vendor_passthru(**kwargs) - delete_mock.assert_called_once_with(final_path) - - @mock.patch.object(driver.DriverManager, 'delete') - def test_vendor_passthru_unknown_http_method(self, delete_mock): - kwargs = { - 'driver_name': 'driver_name', - 'method': 'method', - 'http_method': 'UNKNOWN', - } - self.assertRaises(exc.InvalidAttribute, self.mgr.vendor_passthru, - **kwargs) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_driver_shell.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_driver_shell.py deleted file mode 100644 index 12b076dd64..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_driver_shell.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ironicclient.openstack.common import cliutils -from ironicclient.tests.unit import utils -import ironicclient.v1.driver_shell as d_shell - - -class DriverShellTest(utils.BaseTestCase): - def test_driver_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - driver = object() - d_shell._print_driver_show(driver) - exp = ['hosts', 'name'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_driver_vendor_passthru_with_args(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [['arg1=val1', 'arg2=val2']] - - d_shell.do_driver_vendor_passthru(client_mock, args) - client_mock.driver.vendor_passthru.assert_called_once_with( - args.driver_name, args.method, http_method=args.http_method, - args={'arg1': 'val1', 'arg2': 'val2'}) - - def test_do_driver_vendor_passthru_without_args(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver_name = 'driver_name' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [[]] - - d_shell.do_driver_vendor_passthru(client_mock, args) - client_mock.driver.vendor_passthru.assert_called_once_with( - args.driver_name, args.method, args={}, - http_method=args.http_method) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_node.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_node.py deleted file mode 100644 index 3b2cf246f6..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_node.py +++ /dev/null @@ -1,819 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import tempfile - -import mock -import testtools -from testtools.matchers import HasLength - -from ironicclient.common import utils as common_utils -from ironicclient import exc -from ironicclient.tests.unit import utils -from ironicclient.v1 import node - -NODE1 = {'id': 123, - 'uuid': '66666666-7777-8888-9999-000000000000', - 'chassis_uuid': 'aaaaaaaa-1111-bbbb-2222-cccccccccccc', - 'maintenance': False, - 'driver': 'fake', - 'driver_info': {'user': 'foo', 'password': 'bar'}, - 'properties': {'num_cpu': 4}, - 'name': 'fake-node-1', - 'extra': {}} -NODE2 = {'id': 456, - 'uuid': '66666666-7777-8888-9999-111111111111', - 'instance_uuid': '66666666-7777-8888-9999-222222222222', - 'chassis_uuid': 'aaaaaaaa-1111-bbbb-2222-cccccccccccc', - 'maintenance': True, - 'driver': 'fake too', - 'driver_info': {'user': 'foo', 'password': 'bar'}, - 'properties': {'num_cpu': 4}, - 'extra': {}} -PORT = {'id': 456, - 'uuid': '11111111-2222-3333-4444-555555555555', - 'node_id': 123, - 'address': 'AA:AA:AA:AA:AA:AA', - 'extra': {}} - -POWER_STATE = {'power_state': 'power off', - 'target_power_state': 'power on'} - -DRIVER_IFACES = {'deploy': {'result': True}, - 'power': {'result': False, 'reason': 'Invalid IPMI username'}, - 'console': {'result': None, 'reason': 'not supported'}, - 'rescue': {'result': None, 'reason': 'not supported'}} - -NODE_STATES = {"last_error": None, - "power_state": "power on", - "provision_state": "active", - "target_power_state": None, - "target_provision_state": None} - -CONSOLE_DATA_ENABLED = {'console_enabled': True, - 'console_info': {'test-console': 'test-console-data'}} -CONSOLE_DATA_DISABLED = {'console_enabled': False, 'console_info': None} - -BOOT_DEVICE = {'boot_device': 'pxe', 'persistent': False} -SUPPORTED_BOOT_DEVICE = {'supported_boot_devices': ['pxe']} - -CREATE_NODE = copy.deepcopy(NODE1) -del CREATE_NODE['id'] -del CREATE_NODE['uuid'] -del CREATE_NODE['maintenance'] - -UPDATED_NODE = copy.deepcopy(NODE1) -NEW_DRIVER = 'new-driver' -UPDATED_NODE['driver'] = NEW_DRIVER - -CREATE_WITH_UUID = copy.deepcopy(NODE1) -del CREATE_WITH_UUID['id'] -del CREATE_WITH_UUID['maintenance'] - -fake_responses = { - '/v1/nodes': - { - 'GET': ( - {}, - {"nodes": [NODE1, NODE2]} - ), - 'POST': ( - {}, - CREATE_NODE, - ), - }, - '/v1/nodes/detail': - { - 'GET': ( - {}, - {"nodes": [NODE1, NODE2]} - ), - }, - '/v1/nodes/?associated=False': - { - 'GET': ( - {}, - {"nodes": [NODE1]}, - ) - }, - '/v1/nodes/?associated=True': - { - 'GET': ( - {}, - {"nodes": [NODE2]}, - ) - }, - '/v1/nodes/?maintenance=False': - { - 'GET': ( - {}, - {"nodes": [NODE1]}, - ) - }, - '/v1/nodes/?maintenance=True': - { - 'GET': ( - {}, - {"nodes": [NODE2]}, - ) - }, - '/v1/nodes/?associated=True&maintenance=True': - { - 'GET': ( - {}, - {"nodes": [NODE2]}, - ) - }, - '/v1/nodes/detail?instance_uuid=%s' % NODE2['instance_uuid']: - { - 'GET': ( - {}, - {"nodes": [NODE2]}, - ) - }, - '/v1/nodes/%s' % NODE1['uuid']: - { - 'GET': ( - {}, - NODE1, - ), - 'DELETE': ( - {}, - None, - ), - 'PATCH': ( - {}, - UPDATED_NODE, - ), - }, - '/v1/nodes/%s' % NODE2['uuid']: - { - 'GET': ( - {}, - NODE2, - ), - }, - '/v1/nodes/%s' % NODE1['name']: - { - 'GET': ( - {}, - NODE1, - ), - }, - '/v1/nodes/%s/ports' % NODE1['uuid']: - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, - '/v1/nodes/%s/ports/detail' % NODE1['uuid']: - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, - '/v1/nodes/%s/maintenance' % NODE1['uuid']: - { - 'PUT': ( - {}, - None, - ), - 'DELETE': ( - {}, - None, - ), - }, - '/v1/nodes/%s/states/power' % NODE1['uuid']: - { - 'PUT': ( - {}, - POWER_STATE, - ), - }, - '/v1/nodes/%s/validate' % NODE1['uuid']: - { - 'GET': ( - {}, - DRIVER_IFACES, - ), - }, - '/v1/nodes/%s/states/provision' % NODE1['uuid']: - { - 'PUT': ( - {}, - None, - ), - }, - '/v1/nodes/%s/states' % NODE1['uuid']: - { - 'GET': ( - {}, - NODE_STATES, - ), - }, - '/v1/nodes/%s/states/console' % NODE1['uuid']: - { - 'GET': ( - {}, - CONSOLE_DATA_ENABLED, - ), - 'PUT': ( - {'enabled': 'true'}, - None, - ), - }, - '/v1/nodes/%s/states/console' % NODE2['uuid']: - { - 'GET': ( - {}, - CONSOLE_DATA_DISABLED, - ), - }, - '/v1/nodes/%s/management/boot_device' % NODE1['uuid']: - { - 'GET': ( - {}, - BOOT_DEVICE, - ), - 'PUT': ( - {}, - None, - ), - }, - '/v1/nodes/%s/management/boot_device/supported' % NODE1['uuid']: - { - 'GET': ( - {}, - SUPPORTED_BOOT_DEVICE, - ), - }, -} - -fake_responses_pagination = { - '/v1/nodes': - { - 'GET': ( - {}, - {"nodes": [NODE1], - "next": "http://127.0.0.1:6385/v1/nodes/?limit=1"} - ), - }, - '/v1/nodes/?limit=1': - { - 'GET': ( - {}, - {"nodes": [NODE2]} - ), - }, - '/v1/nodes/?marker=%s' % NODE1['uuid']: - { - 'GET': ( - {}, - {"nodes": [NODE2]} - ), - }, - '/v1/nodes/%s/ports?limit=1' % NODE1['uuid']: - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, - '/v1/nodes/%s/ports?marker=%s' % (NODE1['uuid'], PORT['uuid']): - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, -} - -fake_responses_sorting = { - '/v1/nodes/?sort_key=updated_at': - { - 'GET': ( - {}, - {"nodes": [NODE2, NODE1]} - ), - }, - '/v1/nodes/?sort_dir=desc': - { - 'GET': ( - {}, - {"nodes": [NODE2, NODE1]} - ), - }, - '/v1/nodes/%s/ports?sort_key=updated_at' % NODE1['uuid']: - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, - '/v1/nodes/%s/ports?sort_dir=desc' % NODE1['uuid']: - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, -} - - -class NodeManagerTest(testtools.TestCase): - - def setUp(self): - super(NodeManagerTest, self).setUp() - self.api = utils.FakeAPI(fake_responses) - self.mgr = node.NodeManager(self.api) - - def test_node_list(self): - nodes = self.mgr.list() - expect = [ - ('GET', '/v1/nodes', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(2, len(nodes)) - - def test_node_list_shows_name(self): - nodes = self.mgr.list() - self.assertIsNotNone(getattr(nodes[0], 'name')) - - def test_node_list_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = node.NodeManager(self.api) - nodes = self.mgr.list(limit=1) - expect = [ - ('GET', '/v1/nodes/?limit=1', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - - def test_node_list_marker(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = node.NodeManager(self.api) - nodes = self.mgr.list(marker=NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/?marker=%s' % NODE1['uuid'], {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - - def test_node_list_pagination_no_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = node.NodeManager(self.api) - nodes = self.mgr.list(limit=0) - expect = [ - ('GET', '/v1/nodes', {}, None), - ('GET', '/v1/nodes/?limit=1', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(2, len(nodes)) - - def test_node_list_sort_key(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = node.NodeManager(self.api) - nodes = self.mgr.list(sort_key='updated_at') - expect = [ - ('GET', '/v1/nodes/?sort_key=updated_at', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(2, len(nodes)) - - def test_node_list_sort_dir(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = node.NodeManager(self.api) - nodes = self.mgr.list(sort_dir='desc') - expect = [ - ('GET', '/v1/nodes/?sort_dir=desc', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(2, len(nodes)) - - def test_node_list_associated(self): - nodes = self.mgr.list(associated=True) - expect = [ - ('GET', '/v1/nodes/?associated=True', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE2['uuid'], getattr(nodes[0], 'uuid')) - - def test_node_list_unassociated(self): - nodes = self.mgr.list(associated=False) - expect = [ - ('GET', '/v1/nodes/?associated=False', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE1['uuid'], getattr(nodes[0], 'uuid')) - - def test_node_list_maintenance(self): - nodes = self.mgr.list(maintenance=True) - expect = [ - ('GET', '/v1/nodes/?maintenance=True', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE2['uuid'], getattr(nodes[0], 'uuid')) - - def test_node_list_no_maintenance(self): - nodes = self.mgr.list(maintenance=False) - expect = [ - ('GET', '/v1/nodes/?maintenance=False', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE1['uuid'], getattr(nodes[0], 'uuid')) - - def test_node_list_associated_and_maintenance(self): - nodes = self.mgr.list(associated=True, maintenance=True) - expect = [ - ('GET', '/v1/nodes/?associated=True&maintenance=True', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(nodes, HasLength(1)) - self.assertEqual(NODE2['uuid'], getattr(nodes[0], 'uuid')) - - def test_node_list_detail(self): - nodes = self.mgr.list(detail=True) - expect = [ - ('GET', '/v1/nodes/detail', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(2, len(nodes)) - self.assertEqual(nodes[0].extra, {}) - - def test_node_show(self): - node = self.mgr.get(NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/%s' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(NODE1['uuid'], node.uuid) - - def test_node_show_by_instance(self): - node = self.mgr.get_by_instance_uuid(NODE2['instance_uuid']) - expect = [ - ('GET', '/v1/nodes/detail?instance_uuid=%s' % - NODE2['instance_uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(NODE2['uuid'], node.uuid) - - def test_node_show_by_name(self): - node = self.mgr.get(NODE1['name']) - expect = [ - ('GET', '/v1/nodes/%s' % NODE1['name'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(NODE1['uuid'], node.uuid) - - def test_create(self): - node = self.mgr.create(**CREATE_NODE) - expect = [ - ('POST', '/v1/nodes', {}, CREATE_NODE), - ] - self.assertEqual(expect, self.api.calls) - self.assertTrue(node) - - def test_create_with_uuid(self): - node = self.mgr.create(**CREATE_WITH_UUID) - expect = [ - ('POST', '/v1/nodes', {}, CREATE_WITH_UUID), - ] - self.assertEqual(expect, self.api.calls) - self.assertTrue(node) - - def test_delete(self): - node = self.mgr.delete(node_id=NODE1['uuid']) - expect = [ - ('DELETE', '/v1/nodes/%s' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertIsNone(node) - - def test_update(self): - patch = {'op': 'replace', - 'value': NEW_DRIVER, - 'path': '/driver'} - node = self.mgr.update(node_id=NODE1['uuid'], patch=patch) - expect = [ - ('PATCH', '/v1/nodes/%s' % NODE1['uuid'], {}, patch), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(NEW_DRIVER, node.driver) - - def test_node_port_list(self): - ports = self.mgr.list_ports(NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/ports' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(ports)) - self.assertEqual(PORT['uuid'], ports[0].uuid) - self.assertEqual(PORT['address'], ports[0].address) - - def test_node_port_list_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = node.NodeManager(self.api) - ports = self.mgr.list_ports(NODE1['uuid'], limit=1) - expect = [ - ('GET', '/v1/nodes/%s/ports?limit=1' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(ports, HasLength(1)) - self.assertEqual(PORT['uuid'], ports[0].uuid) - self.assertEqual(PORT['address'], ports[0].address) - - def test_node_port_list_marker(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = node.NodeManager(self.api) - ports = self.mgr.list_ports(NODE1['uuid'], marker=PORT['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/ports?marker=%s' % (NODE1['uuid'], - PORT['uuid']), {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(ports, HasLength(1)) - - def test_node_port_list_sort_key(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = node.NodeManager(self.api) - ports = self.mgr.list_ports(NODE1['uuid'], sort_key='updated_at') - expect = [ - ('GET', '/v1/nodes/%s/ports?sort_key=updated_at' % NODE1['uuid'], - {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(ports, HasLength(1)) - self.assertEqual(PORT['uuid'], ports[0].uuid) - self.assertEqual(PORT['address'], ports[0].address) - - def test_node_port_list_sort_dir(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = node.NodeManager(self.api) - ports = self.mgr.list_ports(NODE1['uuid'], sort_dir='desc') - expect = [ - ('GET', '/v1/nodes/%s/ports?sort_dir=desc' % NODE1['uuid'], - {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(ports, HasLength(1)) - self.assertEqual(PORT['uuid'], ports[0].uuid) - self.assertEqual(PORT['address'], ports[0].address) - - def test_node_port_list_detail(self): - ports = self.mgr.list_ports(NODE1['uuid'], detail=True) - expect = [ - ('GET', '/v1/nodes/%s/ports/detail' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(ports)) - - def test_node_set_maintenance_true(self): - maintenance = self.mgr.set_maintenance(NODE1['uuid'], 'true', - maint_reason='reason') - body = {'reason': 'reason'} - expect = [ - ('PUT', '/v1/nodes/%s/maintenance' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(None, maintenance) - - def test_node_set_maintenance_false(self): - maintenance = self.mgr.set_maintenance(NODE1['uuid'], 'false') - expect = [ - ('DELETE', '/v1/nodes/%s/maintenance' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(None, maintenance) - - def test_node_set_maintenance_on(self): - maintenance = self.mgr.set_maintenance(NODE1['uuid'], 'on', - maint_reason='reason') - body = {'reason': 'reason'} - expect = [ - ('PUT', '/v1/nodes/%s/maintenance' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(None, maintenance) - - def test_node_set_maintenance_off(self): - maintenance = self.mgr.set_maintenance(NODE1['uuid'], 'off') - expect = [ - ('DELETE', '/v1/nodes/%s/maintenance' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(None, maintenance) - - def test_node_set_power_state(self): - power_state = self.mgr.set_power_state(NODE1['uuid'], "on") - body = {'target': 'power on'} - expect = [ - ('PUT', '/v1/nodes/%s/states/power' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual('power on', power_state.target_power_state) - - def test_node_validate(self): - ifaces = self.mgr.validate(NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/validate' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(DRIVER_IFACES['power'], ifaces.power) - self.assertEqual(DRIVER_IFACES['deploy'], ifaces.deploy) - self.assertEqual(DRIVER_IFACES['rescue'], ifaces.rescue) - self.assertEqual(DRIVER_IFACES['console'], ifaces.console) - - def test_node_set_provision_state(self): - target_state = 'active' - self.mgr.set_provision_state(NODE1['uuid'], target_state) - body = {'target': target_state} - expect = [ - ('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - - def test_node_set_provision_state_with_configdrive(self): - target_state = 'active' - self.mgr.set_provision_state(NODE1['uuid'], target_state, - configdrive='foo') - body = {'target': target_state, 'configdrive': 'foo'} - expect = [ - ('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - - def test_node_set_provision_state_with_configdrive_file(self): - target_state = 'active' - file_content = b'foo bar cat meow dog bark' - - with tempfile.NamedTemporaryFile() as f: - f.write(file_content) - f.flush() - self.mgr.set_provision_state(NODE1['uuid'], target_state, - configdrive=f.name) - - body = {'target': target_state, 'configdrive': file_content} - expect = [ - ('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - - @mock.patch.object(common_utils, 'make_configdrive') - def test_node_set_provision_state_with_configdrive_dir(self, - mock_configdrive): - mock_configdrive.return_value = 'fake-configdrive' - target_state = 'active' - - with common_utils.tempdir() as dirname: - self.mgr.set_provision_state(NODE1['uuid'], target_state, - configdrive=dirname) - mock_configdrive.assert_called_once_with(dirname) - - body = {'target': target_state, 'configdrive': 'fake-configdrive'} - expect = [ - ('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - - def test_node_states(self): - states = self.mgr.states(NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/states' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - expected_fields = ['last_error', 'power_state', 'provision_state', - 'target_power_state', 'target_provision_state'] - self.assertEqual(sorted(expected_fields), - sorted(states.to_dict().keys())) - - def test_node_set_console_mode(self): - enabled = 'true' - self.mgr.set_console_mode(NODE1['uuid'], enabled) - body = {'enabled': enabled} - expect = [ - ('PUT', '/v1/nodes/%s/states/console' % NODE1['uuid'], {}, body), - ] - self.assertEqual(expect, self.api.calls) - - def test_node_get_console(self): - info = self.mgr.get_console(NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/states/console' % NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(CONSOLE_DATA_ENABLED, info) - - def test_node_get_console_disabled(self): - info = self.mgr.get_console(NODE2['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/states/console' % NODE2['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(CONSOLE_DATA_DISABLED, info) - - @mock.patch.object(node.NodeManager, 'update') - def test_vendor_passthru_update(self, update_mock): - # For now just mock the tests because vendor-passthru doesn't return - # anything to verify. - vendor_passthru_args = {'arg1': 'val1'} - kwargs = { - 'node_id': 'node_uuid', - 'method': 'method', - 'args': vendor_passthru_args - } - - final_path = 'node_uuid/vendor_passthru/method' - for http_method in ('POST', 'PUT', 'PATCH'): - kwargs['http_method'] = http_method - self.mgr.vendor_passthru(**kwargs) - update_mock.assert_called_once_with(final_path, - vendor_passthru_args, - http_method=http_method) - update_mock.reset_mock() - - @mock.patch.object(node.NodeManager, 'get') - def test_vendor_passthru_get(self, get_mock): - kwargs = { - 'node_id': 'node_uuid', - 'method': 'method', - 'http_method': 'GET', - } - - final_path = 'node_uuid/vendor_passthru/method' - self.mgr.vendor_passthru(**kwargs) - get_mock.assert_called_once_with(final_path) - - @mock.patch.object(node.NodeManager, 'delete') - def test_vendor_passthru_delete(self, delete_mock): - kwargs = { - 'node_id': 'node_uuid', - 'method': 'method', - 'http_method': 'DELETE', - } - - final_path = 'node_uuid/vendor_passthru/method' - self.mgr.vendor_passthru(**kwargs) - delete_mock.assert_called_once_with(final_path) - - @mock.patch.object(node.NodeManager, 'delete') - def test_vendor_passthru_unknown_http_method(self, delete_mock): - kwargs = { - 'node_id': 'node_uuid', - 'method': 'method', - 'http_method': 'UNKNOWN', - } - self.assertRaises(exc.InvalidAttribute, self.mgr.vendor_passthru, - **kwargs) - - def _test_node_set_boot_device(self, boot_device, persistent=False): - self.mgr.set_boot_device(NODE1['uuid'], boot_device, persistent) - body = {'boot_device': boot_device, 'persistent': persistent} - expect = [ - ('PUT', '/v1/nodes/%s/management/boot_device' % NODE1['uuid'], - {}, body), - ] - self.assertEqual(expect, self.api.calls) - - def test_node_set_boot_device(self): - self._test_node_set_boot_device('pxe') - - def test_node_set_boot_device_persistent(self): - self._test_node_set_boot_device('pxe', persistent=True) - - def test_node_get_boot_device(self): - boot_device = self.mgr.get_boot_device(NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/management/boot_device' % NODE1['uuid'], - {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(BOOT_DEVICE, boot_device) - - def test_node_get_supported_boot_devices(self): - boot_device = self.mgr.get_supported_boot_devices(NODE1['uuid']) - expect = [ - ('GET', '/v1/nodes/%s/management/boot_device/supported' % - NODE1['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(SUPPORTED_BOOT_DEVICE, boot_device) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_node_shell.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_node_shell.py deleted file mode 100644 index 86807b63a7..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_node_shell.py +++ /dev/null @@ -1,398 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 IBM Corp -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ironicclient.common import utils as commonutils -from ironicclient.openstack.common.apiclient import exceptions -from ironicclient.openstack.common import cliutils -from ironicclient.tests.unit import utils -import ironicclient.v1.node_shell as n_shell - - -class NodeShellTest(utils.BaseTestCase): - def test_node_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - node = object() - n_shell._print_node_show(node) - exp = ['chassis_uuid', - 'created_at', - 'console_enabled', - 'driver', - 'driver_info', - 'driver_internal_info', - 'extra', - 'instance_info', - 'instance_uuid', - 'last_error', - 'maintenance', - 'maintenance_reason', - 'name', - 'power_state', - 'properties', - 'provision_state', - 'reservation', - 'target_power_state', - 'target_provision_state', - 'updated_at', - 'inspection_finished_at', - 'inspection_started_at', - 'uuid'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_node_delete(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = ['node_uuid'] - - n_shell.do_node_delete(client_mock, args) - client_mock.node.delete.assert_called_once_with('node_uuid') - - def test_do_node_delete_multiple(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = ['node_uuid1', 'node_uuid2'] - - n_shell.do_node_delete(client_mock, args) - client_mock.node.delete.assert_has_calls( - [mock.call('node_uuid1'), mock.call('node_uuid2')]) - - def test_do_node_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - - n_shell.do_node_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.node.update.assert_called_once_with('node_uuid', patch) - - def test_do_node_create(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with() - - def test_do_node_create_with_driver(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver = 'driver' - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - driver='driver') - - def test_do_node_create_with_chassis_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.chassis_uuid = 'chassis_uuid' - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with( - chassis_uuid='chassis_uuid') - - def test_do_node_create_with_driver_info(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver_info = ['arg1=val1', 'arg2=val2'] - - n_shell.do_node_create(client_mock, args) - kwargs = {'driver_info': {'arg1': 'val1', 'arg2': 'val2'}} - client_mock.node.create.assert_called_once_with(**kwargs) - - def test_do_node_create_with_properties(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.properties = ['arg1=val1', 'arg2=val2'] - - n_shell.do_node_create(client_mock, args) - kwargs = {'properties': {'arg1': 'val1', 'arg2': 'val2'}} - client_mock.node.create.assert_called_once_with(**kwargs) - - def test_do_node_create_with_extra(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.driver = 'driver_name' - args.extra = ['arg1=val1', 'arg2=val2'] - - n_shell.do_node_create(client_mock, args) - kwargs = { - 'driver': 'driver_name', - 'extra': {'arg1': 'val1', 'arg2': 'val2'}, - } - client_mock.node.create.assert_called_once_with(**kwargs) - - def test_do_node_create_with_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.uuid = 'fef99cb8-a0d1-43df-b084-17b3b42b3cbd' - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with(uuid=args.uuid) - - def test_do_node_create_with_name(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.name = 'node_name' - - n_shell.do_node_create(client_mock, args) - client_mock.node.create.assert_called_once_with(name=args.name) - - def test_do_node_show(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.instance_uuid = False - - n_shell.do_node_show(client_mock, args) - client_mock.node.get.assert_called_once_with('node_uuid') - # assert get_by_instance_uuid() wasn't called - self.assertFalse(client_mock.node.get_by_instance_uuid.called) - - def test_do_node_show_by_instance_uuid(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'instance_uuid' - args.instance_uuid = True - - n_shell.do_node_show(client_mock, args) - client_mock.node.get_by_instance_uuid.assert_called_once_with( - 'instance_uuid') - # assert get() wasn't called - self.assertFalse(client_mock.node.get.called) - - def test_do_node_set_maintenance_true(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'true' - args.reason = 'reason' - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', 'true', maint_reason='reason') - - def test_do_node_set_maintenance_false(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'false' - # NOTE(jroll) None is the default. <3 mock. - args.reason = None - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', 'false', maint_reason=None) - - def test_do_node_set_maintenance_false_with_reason_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'false' - args.reason = 'reason' - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_maintenance, - client_mock, args) - - def test_do_node_set_maintenance_on(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'on' - args.reason = 'reason' - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', 'on', maint_reason='reason') - - def test_do_node_set_maintenance_off(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'off' - # NOTE(jroll) None is the default. <3 mock. - args.reason = None - - n_shell.do_node_set_maintenance(client_mock, args) - client_mock.node.set_maintenance.assert_called_once_with( - 'node_uuid', 'off', maint_reason=None) - - def test_do_node_set_maintenance_off_with_reason_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.maintenance_mode = 'off' - args.reason = 'reason' - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_maintenance, - client_mock, args) - - def _do_node_set_power_state_helper(self, power_state): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.power_state = power_state - - n_shell.do_node_set_power_state(client_mock, args) - client_mock.node.set_power_state.assert_called_once_with('node_uuid', - power_state) - - def test_do_node_set_power_state_on(self): - self._do_node_set_power_state_helper('on') - - def test_do_node_set_power_state_off(self): - self._do_node_set_power_state_helper('off') - - def test_do_node_set_power_state_reboot(self): - self._do_node_set_power_state_helper('reboot') - - def test_do_node_vendor_passthru_with_args(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [['arg1=val1', 'arg2=val2']] - - n_shell.do_node_vendor_passthru(client_mock, args) - client_mock.node.vendor_passthru.assert_called_once_with( - args.node, args.method, args={'arg1': 'val1', 'arg2': 'val2'}, - http_method=args.http_method) - - def test_do_node_vendor_passthru_without_args(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.http_method = 'POST' - args.method = 'method' - args.arguments = [[]] - - n_shell.do_node_vendor_passthru(client_mock, args) - client_mock.node.vendor_passthru.assert_called_once_with( - args.node, args.method, args={}, http_method=args.http_method) - - def test_do_node_set_provision_state_active(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'active' - args.config_drive = 'foo' - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'active', configdrive='foo') - - def test_do_node_set_provision_state_deleted(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'deleted' - args.config_drive = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'deleted', configdrive=None) - - def test_do_node_set_provision_state_rebuild(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'rebuild' - args.config_drive = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'rebuild', configdrive=None) - - def test_do_node_set_provision_state_not_active_fails(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'deleted' - args.config_drive = 'foo' - - self.assertRaises(exceptions.CommandError, - n_shell.do_node_set_provision_state, - client_mock, args) - self.assertFalse(client_mock.node.set_provision_state.called) - - def test_do_node_set_provision_state_inspect(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'inspect' - args.config_drive = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'inspect', configdrive=None) - - def test_do_node_set_provision_state_manage(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'manage' - args.config_drive = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'manage', configdrive=None) - - def test_do_node_set_provision_state_provide(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.provision_state = 'provide' - args.config_drive = None - - n_shell.do_node_set_provision_state(client_mock, args) - client_mock.node.set_provision_state.assert_called_once_with( - 'node_uuid', 'provide', configdrive=None) - - def test_do_node_set_boot_device(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - args.persistent = False - args.device = 'pxe' - - n_shell.do_node_set_boot_device(client_mock, args) - client_mock.node.set_boot_device.assert_called_once_with( - 'node_uuid', 'pxe', False) - - def test_do_node_get_boot_device(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - - n_shell.do_node_get_boot_device(client_mock, args) - client_mock.node.get_boot_device.assert_called_once_with('node_uuid') - - def test_do_node_get_supported_boot_devices(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.node = 'node_uuid' - - n_shell.do_node_get_supported_boot_devices(client_mock, args) - client_mock.node.get_supported_boot_devices.assert_called_once_with( - 'node_uuid') diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_port.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_port.py deleted file mode 100644 index eba6f78c22..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_port.py +++ /dev/null @@ -1,275 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -import testtools -from testtools.matchers import HasLength - -from ironicclient.tests.unit import utils -import ironicclient.v1.port - -PORT = {'id': 987, - 'uuid': '11111111-2222-3333-4444-555555555555', - 'node_uuid': '55555555-4444-3333-2222-111111111111', - 'address': 'AA:BB:CC:DD:EE:FF', - 'extra': {}} - -PORT2 = {'id': 988, - 'uuid': '55555555-4444-3333-2222-111111111111', - 'node_uuid': '55555555-4444-3333-2222-111111111111', - 'address': 'AA:AA:AA:BB:BB:BB', - 'extra': {}} - -CREATE_PORT = copy.deepcopy(PORT) -del CREATE_PORT['id'] -del CREATE_PORT['uuid'] - -UPDATED_PORT = copy.deepcopy(PORT) -NEW_ADDR = 'AA:AA:AA:AA:AA:AA' -UPDATED_PORT['address'] = NEW_ADDR - -fake_responses = { - '/v1/ports': - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - 'POST': ( - {}, - CREATE_PORT, - ), - }, - '/v1/ports/detail': - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, - '/v1/ports/%s' % PORT['uuid']: - { - 'GET': ( - {}, - PORT, - ), - 'DELETE': ( - {}, - None, - ), - 'PATCH': ( - {}, - UPDATED_PORT, - ), - }, - '/v1/ports/detail?address=%s' % PORT['address']: - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - }, - '/v1/ports/?address=%s' % PORT['address']: - { - 'GET': ( - {}, - {"ports": [PORT]}, - ), - } -} - -fake_responses_pagination = { - '/v1/ports': - { - 'GET': ( - {}, - {"ports": [PORT], - "next": "http://127.0.0.1:6385/v1/ports/?limit=1"} - ), - }, - '/v1/ports/?limit=1': - { - 'GET': ( - {}, - {"ports": [PORT2]} - ), - }, - '/v1/ports/?marker=%s' % PORT['uuid']: - { - 'GET': ( - {}, - {"ports": [PORT2]} - ), - }, -} - -fake_responses_sorting = { - '/v1/ports/?sort_key=updated_at': - { - 'GET': ( - {}, - {"ports": [PORT2, PORT]} - ), - }, - '/v1/ports/?sort_dir=desc': - { - 'GET': ( - {}, - {"ports": [PORT2, PORT]} - ), - }, -} - - -class PortManagerTest(testtools.TestCase): - - def setUp(self): - super(PortManagerTest, self).setUp() - self.api = utils.FakeAPI(fake_responses) - self.mgr = ironicclient.v1.port.PortManager(self.api) - - def test_ports_list(self): - ports = self.mgr.list() - expect = [ - ('GET', '/v1/ports', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(ports)) - - def test_ports_list_by_address(self): - ports = self.mgr.list(address=PORT['address']) - expect = [ - ('GET', '/v1/ports/?address=%s' % PORT['address'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(ports)) - - def test_ports_list_by_address_detail(self): - ports = self.mgr.list(address=PORT['address'], detail=True) - expect = [ - ('GET', '/v1/ports/detail?address=%s' % PORT['address'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(ports)) - - def test_ports_list_detail(self): - ports = self.mgr.list(detail=True) - expect = [ - ('GET', '/v1/ports/detail', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(1, len(ports)) - - def test_ports_list_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.port.PortManager(self.api) - ports = self.mgr.list(limit=1) - expect = [ - ('GET', '/v1/ports/?limit=1', {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(ports, HasLength(1)) - - def test_ports_list_marker(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.port.PortManager(self.api) - ports = self.mgr.list(marker=PORT['uuid']) - expect = [ - ('GET', '/v1/ports/?marker=%s' % PORT['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(ports, HasLength(1)) - - def test_ports_list_pagination_no_limit(self): - self.api = utils.FakeAPI(fake_responses_pagination) - self.mgr = ironicclient.v1.port.PortManager(self.api) - ports = self.mgr.list(limit=0) - expect = [ - ('GET', '/v1/ports', {}, None), - ('GET', '/v1/ports/?limit=1', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertThat(ports, HasLength(2)) - - def test_ports_list_sort_key(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = ironicclient.v1.port.PortManager(self.api) - ports = self.mgr.list(sort_key='updated_at') - expect = [ - ('GET', '/v1/ports/?sort_key=updated_at', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(2, len(ports)) - - def test_ports_list_sort_dir(self): - self.api = utils.FakeAPI(fake_responses_sorting) - self.mgr = ironicclient.v1.port.PortManager(self.api) - ports = self.mgr.list(sort_dir='desc') - expect = [ - ('GET', '/v1/ports/?sort_dir=desc', {}, None) - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(2, len(ports)) - - def test_ports_show(self): - port = self.mgr.get(PORT['uuid']) - expect = [ - ('GET', '/v1/ports/%s' % PORT['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(PORT['uuid'], port.uuid) - self.assertEqual(PORT['address'], port.address) - self.assertEqual(PORT['node_uuid'], port.node_uuid) - - def test_ports_show_by_address(self): - port = self.mgr.get_by_address(PORT['address']) - expect = [ - ('GET', '/v1/ports/detail?address=%s' % PORT['address'], - {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(PORT['uuid'], port.uuid) - self.assertEqual(PORT['address'], port.address) - self.assertEqual(PORT['node_uuid'], port.node_uuid) - - def test_create(self): - port = self.mgr.create(**CREATE_PORT) - expect = [ - ('POST', '/v1/ports', {}, CREATE_PORT), - ] - self.assertEqual(expect, self.api.calls) - self.assertTrue(port) - - def test_delete(self): - port = self.mgr.delete(port_id=PORT['uuid']) - expect = [ - ('DELETE', '/v1/ports/%s' % PORT['uuid'], {}, None), - ] - self.assertEqual(expect, self.api.calls) - self.assertIsNone(port) - - def test_update(self): - patch = {'op': 'replace', - 'value': NEW_ADDR, - 'path': '/address'} - port = self.mgr.update(port_id=PORT['uuid'], patch=patch) - expect = [ - ('PATCH', '/v1/ports/%s' % PORT['uuid'], {}, patch), - ] - self.assertEqual(expect, self.api.calls) - self.assertEqual(NEW_ADDR, port.address) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_port_shell.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_port_shell.py deleted file mode 100644 index 716f37d114..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_port_shell.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 IBM Corp -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ironicclient.common import utils as commonutils -from ironicclient.openstack.common import cliutils -from ironicclient.tests.unit import utils -import ironicclient.v1.port_shell as p_shell - - -class PortShellTest(utils.BaseTestCase): - - def test_port_show(self): - actual = {} - fake_print_dict = lambda data, *args, **kwargs: actual.update(data) - with mock.patch.object(cliutils, 'print_dict', fake_print_dict): - port = object() - p_shell._print_port_show(port) - exp = ['address', 'created_at', 'extra', 'node_uuid', 'updated_at', - 'uuid'] - act = actual.keys() - self.assertEqual(sorted(exp), sorted(act)) - - def test_do_port_show(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_uuid' - args.address = False - - p_shell.do_port_show(client_mock, args) - client_mock.port.get.assert_called_once_with('port_uuid') - # assert get_by_address() wasn't called - self.assertFalse(client_mock.port.get_by_address.called) - - def test_do_port_show_by_address(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_address' - args.address = True - - p_shell.do_port_show(client_mock, args) - client_mock.port.get_by_address.assert_called_once_with('port_address') - # assert get() wasn't called - self.assertFalse(client_mock.port.get.called) - - def test_do_port_update(self): - client_mock = mock.MagicMock() - args = mock.MagicMock() - args.port = 'port_uuid' - args.op = 'add' - args.attributes = [['arg1=val1', 'arg2=val2']] - - p_shell.do_port_update(client_mock, args) - patch = commonutils.args_array_to_patch(args.op, args.attributes[0]) - client_mock.port.update.assert_called_once_with('port_uuid', patch) diff --git a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_resource_fields.py b/awx/lib/site-packages/ironicclient/tests/unit/v1/test_resource_fields.py deleted file mode 100644 index 748a754211..0000000000 --- a/awx/lib/site-packages/ironicclient/tests/unit/v1/test_resource_fields.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import testtools - -from ironicclient.v1 import resource_fields - - -class ResourceFieldsTest(testtools.TestCase): - - def test_chassis_fields(self): - self.assertEqual( - len(resource_fields.CHASSIS_FIELDS), - len(resource_fields.CHASSIS_FIELD_LABELS)) - - def test_chassis_list_fields(self): - self.assertEqual( - len(resource_fields.CHASSIS_LIST_FIELDS), - len(resource_fields.CHASSIS_LIST_FIELD_LABELS)) - - def test_node_fields(self): - self.assertEqual( - len(resource_fields.NODE_FIELDS), - len(resource_fields.NODE_FIELD_LABELS)) - - def test_node_list_fields(self): - self.assertEqual( - len(resource_fields.NODE_LIST_FIELDS), - len(resource_fields.NODE_LIST_FIELD_LABELS)) - - def test_port_fields(self): - self.assertEqual( - len(resource_fields.PORT_FIELDS), - len(resource_fields.PORT_FIELD_LABELS)) - - def test_port_list_fields(self): - self.assertEqual( - len(resource_fields.PORT_LIST_FIELDS), - len(resource_fields.PORT_LIST_FIELD_LABELS)) diff --git a/awx/lib/site-packages/ironicclient/v1/__init__.py b/awx/lib/site-packages/ironicclient/v1/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/ironicclient/v1/chassis.py b/awx/lib/site-packages/ironicclient/v1/chassis.py deleted file mode 100644 index de6c7f29cf..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/chassis.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright © 2013 Red Hat, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common import base -from ironicclient.common import utils -from ironicclient import exc - - -CREATION_ATTRIBUTES = ['description', 'extra'] - - -class Chassis(base.Resource): - def __repr__(self): - return "<Chassis %s>" % self._info - - -class ChassisManager(base.Manager): - resource_class = Chassis - - @staticmethod - def _path(id=None): - return '/v1/chassis/%s' % id if id else '/v1/chassis' - - def list(self, marker=None, limit=None, sort_key=None, - sort_dir=None, detail=False): - """Retrieve a list of chassis. - - :param marker: Optional, the UUID of a chassis, eg the last - chassis from a previous result set. Return - the next result set. - :param limit: The maximum number of results to return per - request, if: - - 1) limit > 0, the maximum number of chassis to return. - 2) limit == 0, return the entire list of chassis. - 3) limit param is NOT specified (None), the number of items - returned respect the maximum imposed by the Ironic API - (see Ironic's api.max_limit option). - - :param sort_key: Optional, field used for sorting. - - :param sort_dir: Optional, direction of sorting, either 'asc' (the - default) or 'desc'. - - :param detail: Optional, boolean whether to return detailed information - about chassis. - - :returns: A list of chassis. - - """ - if limit is not None: - limit = int(limit) - - filters = utils.common_filters(marker, limit, sort_key, sort_dir) - - path = '' - if detail: - path += 'detail' - if filters: - path += '?' + '&'.join(filters) - - if limit is None: - return self._list(self._path(path), "chassis") - else: - return self._list_pagination(self._path(path), "chassis", - limit=limit) - - def list_nodes(self, chassis_id, marker=None, limit=None, - sort_key=None, sort_dir=None, detail=False): - """List all the nodes for a given chassis. - - :param chassis_id: The UUID of the chassis. - :param marker: Optional, the UUID of a node, eg the last - node from a previous result set. Return - the next result set. - :param limit: The maximum number of results to return per - request, if: - - 1) limit > 0, the maximum number of nodes to return. - 2) limit == 0, return the entire list of nodes. - 3) limit param is NOT specified (None), the number of items - returned respect the maximum imposed by the Ironic API - (see Ironic's api.max_limit option). - - :param sort_key: Optional, field used for sorting. - - :param sort_dir: Optional, direction of sorting, either 'asc' (the - default) or 'desc'. - - :param detail: Optional, boolean whether to return detailed information - about nodes. - - :returns: A list of nodes. - - """ - if limit is not None: - limit = int(limit) - - filters = utils.common_filters(marker, limit, sort_key, sort_dir) - - path = "%s/nodes" % chassis_id - if detail: - path += '/detail' - - if filters: - path += '?' + '&'.join(filters) - - if limit is None: - return self._list(self._path(path), "nodes") - else: - return self._list_pagination(self._path(path), "nodes", - limit=limit) - - def get(self, chassis_id): - try: - return self._list(self._path(chassis_id))[0] - except IndexError: - return None - - def create(self, **kwargs): - new = {} - for (key, value) in kwargs.items(): - if key in CREATION_ATTRIBUTES: - new[key] = value - else: - raise exc.InvalidAttribute() - return self._create(self._path(), new) - - def delete(self, chassis_id): - return self._delete(self._path(chassis_id)) - - def update(self, chassis_id, patch): - return self._update(self._path(chassis_id), patch) diff --git a/awx/lib/site-packages/ironicclient/v1/chassis_shell.py b/awx/lib/site-packages/ironicclient/v1/chassis_shell.py deleted file mode 100644 index acd75a9675..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/chassis_shell.py +++ /dev/null @@ -1,179 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common import utils -from ironicclient.openstack.common import cliutils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_chassis_show(chassis): - fields = ['uuid', 'description', 'created_at', 'updated_at', 'extra'] - data = dict([(f, getattr(chassis, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72) - - -@cliutils.arg('chassis', metavar='<chassis>', help="UUID of the chassis.") -def do_chassis_show(cc, args): - """Show detailed information about a chassis.""" - chassis = cc.chassis.get(args.chassis) - _print_chassis_show(chassis) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the chassis.") -@cliutils.arg( - '--limit', - metavar='<limit>', - type=int, - help='Maximum number of chassis to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='<chassis>', - help='Chassis UUID (for example, of the last chassis in the list ' - 'from a previous request). Returns the list of chassis ' - 'after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='<field>', - help='Chassis field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='<direction>', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -def do_chassis_list(cc, args): - """List the chassis.""" - if args.detail: - fields = res_fields.CHASSIS_FIELDS - field_labels = res_fields.CHASSIS_FIELD_LABELS - else: - fields = res_fields.CHASSIS_LIST_FIELDS - field_labels = res_fields.CHASSIS_LIST_FIELD_LABELS - - params = utils.common_params_for_list(args, fields, field_labels) - - chassis = cc.chassis.list(**params) - cliutils.print_list(chassis, fields, - field_labels=field_labels, - sortby_index=None) - - -@cliutils.arg( - '-d', '--description', - metavar='<description>', - help='Description of the chassis.') -@cliutils.arg( - '-e', '--extra', - metavar="<key=value>", - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times.") -def do_chassis_create(cc, args): - """Create a new chassis.""" - field_list = ['description', 'extra'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'extra') - chassis = cc.chassis.create(**fields) - - field_list.append('uuid') - data = dict([(f, getattr(chassis, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72) - - -@cliutils.arg( - 'chassis', - metavar='<chassis>', - nargs='+', - help="UUID of the chassis.") -def do_chassis_delete(cc, args): - """Delete a chassis.""" - for c in args.chassis: - cc.chassis.delete(c) - print('Deleted chassis %s' % c) - - -@cliutils.arg('chassis', metavar='<chassis>', help="UUID of the chassis.") -@cliutils.arg( - 'op', - metavar='<op>', - choices=['add', 'replace', 'remove'], - help="Operation: 'add', 'replace', or 'remove'.") -@cliutils.arg( - 'attributes', - metavar='<path=value>', - nargs='+', - action='append', - default=[], - help="Attribute to add, replace, or remove. Can be specified " - "multiple times. For 'remove', only <path> is necessary.") -def do_chassis_update(cc, args): - """Update information about a chassis.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - chassis = cc.chassis.update(args.chassis, patch) - _print_chassis_show(chassis) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the nodes.") -@cliutils.arg( - '--limit', - metavar='<limit>', - type=int, - help='Maximum number of nodes to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='<node>', - help='Node UUID (for example, of the last node in the list from ' - 'a previous request). Returns the list of nodes after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='<field>', - help='Node field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='<direction>', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg('chassis', metavar='<chassis>', help="UUID of the chassis.") -def do_chassis_node_list(cc, args): - """List the nodes contained in a chassis.""" - if args.detail: - fields = res_fields.NODE_FIELDS - field_labels = res_fields.NODE_FIELD_LABELS - else: - fields = res_fields.NODE_LIST_FIELDS - field_labels = res_fields.NODE_LIST_FIELD_LABELS - - params = utils.common_params_for_list(args, fields, field_labels) - - nodes = cc.chassis.list_nodes(args.chassis, **params) - cliutils.print_list(nodes, fields, - field_labels=field_labels, - sortby_index=None) diff --git a/awx/lib/site-packages/ironicclient/v1/client.py b/awx/lib/site-packages/ironicclient/v1/client.py deleted file mode 100644 index 86f2867411..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/client.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2012 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common import http -from ironicclient.v1 import chassis -from ironicclient.v1 import driver -from ironicclient.v1 import node -from ironicclient.v1 import port - - -# NOTE(deva): Record the latest version that this client was tested with. -# We still have a lot of work to do in the client to implement -# microversion support in the client properly! See -# http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa -# for full details. -DEFAULT_VER = '1.6' - - -class Client(object): - """Client for the Ironic v1 API. - - :param string endpoint: A user-supplied endpoint URL for the ironic - service. - :param function token: Provides token for authentication. - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - """ - - def __init__(self, *args, **kwargs): - """Initialize a new client for the Ironic v1 API.""" - # set the default API version header string, if none specified - if not kwargs.get('os_ironic_api_version'): - kwargs['os_ironic_api_version'] = DEFAULT_VER - self.http_client = http._construct_http_client(*args, **kwargs) - self.chassis = chassis.ChassisManager(self.http_client) - self.node = node.NodeManager(self.http_client) - self.port = port.PortManager(self.http_client) - self.driver = driver.DriverManager(self.http_client) diff --git a/awx/lib/site-packages/ironicclient/v1/driver.py b/awx/lib/site-packages/ironicclient/v1/driver.py deleted file mode 100644 index 761c5fd2a3..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/driver.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common import base -from ironicclient.common.i18n import _ -from ironicclient import exc - - -class Driver(base.Resource): - def __repr__(self): - return "<Driver %s>" % self._info - - -class DriverManager(base.Manager): - resource_class = Driver - - def list(self): - return self._list('/v1/drivers', "drivers") - - def get(self, driver_name): - try: - return self._list('/v1/drivers/%s' % driver_name)[0] - except IndexError: - return None - - def update(self, driver_name, patch, http_method='PATCH'): - path = '/v1/drivers/%s' % driver_name - return self._update(path, patch, method=http_method) - - def delete(self, driver_name): - return self._delete('/v1/drivers/%s' % driver_name) - - def properties(self, driver_name): - try: - info = self._list('/v1/drivers/%s/properties' % driver_name)[0] - if info: - return info.to_dict() - return {} - except IndexError: - return {} - - def vendor_passthru(self, driver_name, method, args=None, - http_method=None): - """Issue requests for vendor-specific actions on a given driver. - - :param driver_name: Name of the driver. - :param method: Name of the vendor method. - :param args: Optional. The arguments to be passed to the method. - :param http_method: The HTTP method to use on the request. - Defaults to POST. - """ - if args is None: - args = {} - - if http_method is None: - http_method = 'POST' - - http_method = http_method.upper() - - path = "%s/vendor_passthru/%s" % (driver_name, method) - if http_method in ('POST', 'PUT', 'PATCH'): - return self.update(path, args, http_method=http_method) - elif http_method == 'DELETE': - return self.delete(path) - elif http_method == 'GET': - return self.get(path) - else: - raise exc.InvalidAttribute( - _('Unknown HTTP method: %s') % http_method) diff --git a/awx/lib/site-packages/ironicclient/v1/driver_shell.py b/awx/lib/site-packages/ironicclient/v1/driver_shell.py deleted file mode 100644 index db14800ceb..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/driver_shell.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -from ironicclient.common import utils -from ironicclient.openstack.common import cliutils - - -def _print_driver_show(driver): - fields = ['name', 'hosts'] - data = dict([(f, getattr(driver, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72) - - -def do_driver_list(cc, args): - """List the enabled drivers.""" - drivers = cc.driver.list() - # NOTE(lucasagomes): Separate each host by a comma. - # It's easier to read. - for d in drivers: - d.hosts = ', '.join(d.hosts) - field_labels = ['Supported driver(s)', 'Active host(s)'] - fields = ['name', 'hosts'] - cliutils.print_list(drivers, fields, field_labels=field_labels) - - -@cliutils.arg('driver_name', metavar='<driver>', - help='Name of the driver.') -def do_driver_show(cc, args): - """Show information about a driver.""" - driver = cc.driver.get(args.driver_name) - _print_driver_show(driver) - - -@cliutils.arg('driver_name', metavar='<driver>', - help="Name of the driver.") -def do_driver_properties(cc, args): - """Get properties of a driver.""" - properties = cc.driver.properties(args.driver_name) - obj_list = [] - for key, value in properties.iteritems(): - data = {'Property': key, 'Description': value} - obj_list.append(type('iface', (object,), data)) - fields = ['Property', 'Description'] - cliutils.print_list(obj_list, fields, mixed_case_fields=fields) - - -@cliutils.arg('driver_name', - metavar='<driver>', - help='Name of the driver.') -@cliutils.arg('method', - metavar='<method>', - help="Vendor-passthru method to be called.") -@cliutils.arg('arguments', - metavar='<arg=value>', - nargs='*', - action='append', - default=[], - help="Argument to be passed to the vendor-passthru method. " - "Can be specified multiple times.") -@cliutils.arg('--http-method', - metavar='<http-method>', - choices=['POST', 'PUT', 'GET', 'DELETE', 'PATCH'], - help="The HTTP method to use in the request. Valid HTTP " - "methods are: 'POST', 'PUT', 'GET', 'DELETE', and 'PATCH'. " - "Defaults to 'POST'.") -@cliutils.arg('--http_method', - help=argparse.SUPPRESS) -def do_driver_vendor_passthru(cc, args): - """Call a vendor-passthru extension for a driver.""" - arguments = utils.args_array_to_dict({'args': args.arguments[0]}, - 'args')['args'] - - # If there were no arguments for the method, arguments will still - # be an empty list. So make it an empty dict. - if not arguments: - arguments = {} - - resp = cc.driver.vendor_passthru(args.driver_name, args.method, - http_method=args.http_method, - args=arguments) - if resp: - # Print the raw response we don't know how it should be formated - print(str(resp.to_dict())) diff --git a/awx/lib/site-packages/ironicclient/v1/node.py b/awx/lib/site-packages/ironicclient/v1/node.py deleted file mode 100644 index a8ca40c4f0..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/node.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -from ironicclient.common import base -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient import exc - -CREATION_ATTRIBUTES = ['chassis_uuid', 'driver', 'driver_info', 'extra', - 'uuid', 'properties', 'name'] - - -class Node(base.Resource): - def __repr__(self): - return "<Node %s>" % self._info - - -class NodeManager(base.Manager): - resource_class = Node - - @staticmethod - def _path(id=None): - return '/v1/nodes/%s' % id if id else '/v1/nodes' - - def list(self, associated=None, maintenance=None, marker=None, limit=None, - detail=False, sort_key=None, sort_dir=None): - """Retrieve a list of nodes. - - :param associated: Optional, boolean whether to return a list of - associated or unassociated nodes. - :param maintenance: Optional, boolean value that indicates whether - to get nodes in maintenance mode ("True"), or not - in maintenance mode ("False"). - :param marker: Optional, the UUID of a node, eg the last - node from a previous result set. Return - the next result set. - :param limit: The maximum number of results to return per - request, if: - - 1) limit > 0, the maximum number of nodes to return. - 2) limit == 0, return the entire list of nodes. - 3) limit param is NOT specified (None), the number of items - returned respect the maximum imposed by the Ironic API - (see Ironic's api.max_limit option). - - :param detail: Optional, boolean whether to return detailed information - about nodes. - - :param sort_key: Optional, field used for sorting. - - :param sort_dir: Optional, direction of sorting, either 'asc' (the - default) or 'desc'. - - :returns: A list of nodes. - - """ - if limit is not None: - limit = int(limit) - - filters = utils.common_filters(marker, limit, sort_key, sort_dir) - if associated is not None: - filters.append('associated=%s' % associated) - if maintenance is not None: - filters.append('maintenance=%s' % maintenance) - - path = '' - if detail: - path += 'detail' - if filters: - path += '?' + '&'.join(filters) - - if limit is None: - return self._list(self._path(path), "nodes") - else: - return self._list_pagination(self._path(path), "nodes", - limit=limit) - - def list_ports(self, node_id, marker=None, limit=None, sort_key=None, - sort_dir=None, detail=False): - """List all the ports for a given node. - - :param node_id: The UUID of the node. - :param marker: Optional, the UUID of a port, eg the last - port from a previous result set. Return - the next result set. - :param limit: The maximum number of results to return per - request, if: - - 1) limit > 0, the maximum number of ports to return. - 2) limit == 0, return the entire list of ports. - 3) limit param is NOT specified (None), the number of items - returned respect the maximum imposed by the Ironic API - (see Ironic's api.max_limit option). - - :param sort_key: Optional, field used for sorting. - - :param sort_dir: Optional, direction of sorting, either 'asc' (the - default) or 'desc'. - - :param detail: Optional, boolean whether to return detailed information - about ports. - - :returns: A list of ports. - - """ - if limit is not None: - limit = int(limit) - - filters = utils.common_filters(marker, limit, sort_key, sort_dir) - - path = "%s/ports" % node_id - if detail: - path += '/detail' - - if filters: - path += '?' + '&'.join(filters) - - if limit is None: - return self._list(self._path(path), "ports") - else: - return self._list_pagination(self._path(path), "ports", - limit=limit) - - def get(self, node_id): - try: - return self._list(self._path(node_id))[0] - except IndexError: - return None - - def get_by_instance_uuid(self, instance_uuid): - path = "detail?instance_uuid=%s" % instance_uuid - nodes = self._list(self._path(path), 'nodes') - # get all the details of the node assuming that - # filtering by instance_uuid returns a collection - # of one node if successful. - if len(nodes) == 1: - return nodes[0] - else: - raise exc.NotFound() - - def create(self, **kwargs): - new = {} - for (key, value) in kwargs.items(): - if key in CREATION_ATTRIBUTES: - new[key] = value - else: - raise exc.InvalidAttribute() - return self._create(self._path(), new) - - def delete(self, node_id): - return self._delete(self._path(node_id)) - - def update(self, node_id, patch, http_method='PATCH'): - return self._update(self._path(node_id), patch, method=http_method) - - def vendor_passthru(self, node_id, method, args=None, http_method=None): - """Issue requests for vendor-specific actions on a given node. - - :param node_id: The UUID of the node. - :param method: Name of the vendor method. - :param args: Optional. The arguments to be passed to the method. - :param http_method: The HTTP method to use on the request. - Defaults to POST. - - """ - if args is None: - args = {} - - if http_method is None: - http_method = 'POST' - - http_method = http_method.upper() - - path = "%s/vendor_passthru/%s" % (node_id, method) - if http_method in ('POST', 'PUT', 'PATCH'): - return self.update(path, args, http_method=http_method) - elif http_method == 'DELETE': - return self.delete(path) - elif http_method == 'GET': - return self.get(path) - else: - raise exc.InvalidAttribute( - _('Unknown HTTP method: %s') % http_method) - - def set_maintenance(self, node_id, state, maint_reason=None): - path = "%s/maintenance" % node_id - if state in ('true', 'on'): - reason = {'reason': maint_reason} - return self._update(self._path(path), reason, method='PUT') - if state in ('false', 'off'): - return self._delete(self._path(path)) - - def set_power_state(self, node_id, state): - path = "%s/states/power" % node_id - if state in ['on', 'off']: - state = "power %s" % state - if state in ['reboot']: - state = "rebooting" - target = {'target': state} - return self._update(self._path(path), target, method='PUT') - - def validate(self, node_uuid): - path = "%s/validate" % node_uuid - return self.get(path) - - def set_provision_state(self, node_uuid, state, configdrive=None): - path = "%s/states/provision" % node_uuid - body = {'target': state} - if configdrive: - if os.path.isfile(configdrive): - with open(configdrive, 'rb') as f: - configdrive = f.read() - if os.path.isdir(configdrive): - configdrive = utils.make_configdrive(configdrive) - - body['configdrive'] = configdrive - return self._update(self._path(path), body, method='PUT') - - def states(self, node_uuid): - path = "%s/states" % node_uuid - return self.get(path) - - def get_console(self, node_uuid): - path = "%s/states/console" % node_uuid - info = self.get(path) - if not info: - return {} - return info.to_dict() - - def set_console_mode(self, node_uuid, enabled): - path = "%s/states/console" % node_uuid - target = {'enabled': enabled} - return self._update(self._path(path), target, method='PUT') - - def set_boot_device(self, node_uuid, boot_device, persistent=False): - path = "%s/management/boot_device" % node_uuid - target = {'boot_device': boot_device, 'persistent': persistent} - return self._update(self._path(path), target, method='PUT') - - def get_boot_device(self, node_uuid): - path = "%s/management/boot_device" % node_uuid - return self.get(path).to_dict() - - def get_supported_boot_devices(self, node_uuid): - path = "%s/management/boot_device/supported" % node_uuid - return self.get(path).to_dict() diff --git a/awx/lib/site-packages/ironicclient/v1/node_shell.py b/awx/lib/site-packages/ironicclient/v1/node_shell.py deleted file mode 100644 index 761fdf72ad..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/node_shell.py +++ /dev/null @@ -1,412 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -import six - -from ironicclient.common.i18n import _ -from ironicclient.common import utils -from ironicclient.openstack.common.apiclient import exceptions -from ironicclient.openstack.common import cliutils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_node_show(node): - data = dict([(f, getattr(node, f, '')) for f in res_fields.NODE_FIELDS]) - cliutils.print_dict(data, wrap=72) - - -@cliutils.arg( - 'node', - metavar='<id>', - help="Name or UUID of the node " - "(or instance UUID if --instance is specified).") -@cliutils.arg( - '--instance', - dest='instance_uuid', - action='store_true', - default=False, - help='<id> is an instance UUID.') -def do_node_show(cc, args): - """Show detailed information about a node.""" - if args.instance_uuid: - node = cc.node.get_by_instance_uuid(args.node) - else: - node = cc.node.get(args.node) - _print_node_show(node) - - -@cliutils.arg( - '--limit', - metavar='<limit>', - type=int, - help='Maximum number of nodes to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='<node>', - help='Node UUID (for example, of the last node in the list from ' - 'a previous request). Returns the list of nodes after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='<field>', - help='Node field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='<direction>', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg( - '--maintenance', - metavar='<boolean>', - choices=['true', 'True', 'false', 'False'], - help="List nodes in maintenance mode: 'true' or 'false'.") -@cliutils.arg( - '--associated', - metavar='<boolean>', - choices=['true', 'True', 'false', 'False'], - help="List nodes by instance association: 'true' or 'false'.") -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the nodes.") -def do_node_list(cc, args): - """List the nodes which are registered with the Ironic service.""" - params = {} - if args.associated is not None: - params['associated'] = args.associated - if args.maintenance is not None: - params['maintenance'] = args.maintenance - params['detail'] = args.detail - - if args.detail: - fields = res_fields.NODE_FIELDS - field_labels = res_fields.NODE_FIELD_LABELS - else: - fields = res_fields.NODE_LIST_FIELDS - field_labels = res_fields.NODE_LIST_FIELD_LABELS - - params.update(utils.common_params_for_list(args, - fields, - field_labels)) - nodes = cc.node.list(**params) - cliutils.print_list(nodes, fields, - field_labels=field_labels, - sortby_index=None) - - -@cliutils.arg( - '-c', '--chassis', - dest='chassis_uuid', - metavar='<chassis>', - help='UUID of the chassis that this node belongs to.') -@cliutils.arg( - '--chassis_uuid', - help=argparse.SUPPRESS) -@cliutils.arg( - '-d', '--driver', - metavar='<driver>', - required=True, - help='Driver used to control the node [REQUIRED].') -@cliutils.arg( - '-i', '--driver-info', - metavar='<key=value>', - action='append', - help='Key/value pair used by the driver, such as out-of-band management ' - 'credentials. Can be specified multiple times.') -@cliutils.arg( - '--driver_info', - action='append', - help=argparse.SUPPRESS) -@cliutils.arg( - '-p', '--properties', - metavar='<key=value>', - action='append', - help='Key/value pair describing the physical characteristics of the ' - 'node. This is exported to Nova and used by the scheduler. ' - 'Can be specified multiple times.') -@cliutils.arg( - '-e', '--extra', - metavar='<key=value>', - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times.") -@cliutils.arg( - '-u', '--uuid', - metavar='<uuid>', - help="Unique UUID for the node.") -@cliutils.arg( - '-n', '--name', - metavar='<name>', - help="Unique name for the node.") -def do_node_create(cc, args): - """Register a new node with the Ironic service.""" - field_list = ['chassis_uuid', 'driver', 'driver_info', - 'properties', 'extra', 'uuid', 'name'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'driver_info') - fields = utils.args_array_to_dict(fields, 'extra') - fields = utils.args_array_to_dict(fields, 'properties') - node = cc.node.create(**fields) - - data = dict([(f, getattr(node, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72) - - -@cliutils.arg('node', - metavar='<node>', - nargs='+', - help="Name or UUID of the node.") -def do_node_delete(cc, args): - """Unregister a node from the Ironic service.""" - for n in args.node: - cc.node.delete(n) - print(_('Deleted node %s') % n) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -@cliutils.arg( - 'op', - metavar='<op>', - choices=['add', 'replace', 'remove'], - help="Operation: 'add', 'replace', or 'remove'.") -@cliutils.arg( - 'attributes', - metavar='<path=value>', - nargs='+', - action='append', - default=[], - help="Attribute to add, replace, or remove. Can be specified " - "multiple times. For 'remove', only <path> is necessary.") -def do_node_update(cc, args): - """Update information about a registered node.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - node = cc.node.update(args.node, patch) - _print_node_show(node) - - -@cliutils.arg('node', - metavar='<node>', - help="Name or UUID of the node.") -@cliutils.arg('method', - metavar='<method>', - help="Vendor-passthru method to be called.") -@cliutils.arg('arguments', - metavar='<arg=value>', - nargs='*', - action='append', - default=[], - help=("Argument to be passed to the vendor-passthru method. Can " - "be specified mutiple times.")) -@cliutils.arg('--http-method', - metavar='<http-method>', - choices=['POST', 'PUT', 'GET', 'DELETE', 'PATCH'], - help="The HTTP method to use in the request. Valid HTTP " - "methods are: 'POST', 'PUT', 'GET', 'DELETE', and 'PATCH'. " - "Defaults to 'POST'.") -@cliutils.arg('--http_method', - help=argparse.SUPPRESS) -def do_node_vendor_passthru(cc, args): - """Call a vendor-passthru extension for a node.""" - arguments = utils.args_array_to_dict({'args': args.arguments[0]}, - 'args')['args'] - - # If there were no arguments for the method, arguments will still - # be an empty list. So make it an empty dict. - if not arguments: - arguments = {} - - resp = cc.node.vendor_passthru(args.node, args.method, - http_method=args.http_method, - args=arguments) - if resp: - # Print the raw response we don't know how it should be formated - print(str(resp.to_dict())) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about the ports.") -@cliutils.arg( - '--limit', - metavar='<limit>', - type=int, - help='Maximum number of ports to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='<port>', - help='Port UUID (for example, of the last port in the list from a ' - 'previous request). Returns the list of ports after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='<field>', - help='Port field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='<direction>', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -@cliutils.arg('node', metavar='<node>', help="UUID of the node.") -def do_node_port_list(cc, args): - """List the ports associated with a node.""" - if args.detail: - fields = res_fields.PORT_FIELDS - field_labels = res_fields.PORT_FIELD_LABELS - else: - fields = res_fields.PORT_LIST_FIELDS - field_labels = res_fields.PORT_LIST_FIELD_LABELS - - params = utils.common_params_for_list(args, fields, field_labels) - - ports = cc.node.list_ports(args.node, **params) - cliutils.print_list(ports, fields, - field_labels=field_labels, - sortby_index=None) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -@cliutils.arg( - 'maintenance_mode', - metavar='<maintenance-mode>', - choices=['true', 'True', 'false', 'False', 'on', 'off'], - help="'true' or 'false'; 'on' or 'off'.") -@cliutils.arg( - '--reason', - metavar='<reason>', - default=None, - help=('Reason for setting maintenance mode to "true" or "on";' - ' not valid when setting to "false" or "off".')) -def do_node_set_maintenance(cc, args): - """Enable or disable maintenance mode for a node.""" - if args.reason and args.maintenance_mode.lower() in ('false', 'off'): - raise exceptions.CommandError(_('Cannot set "reason" when turning off ' - 'maintenance mode.')) - cc.node.set_maintenance(args.node, args.maintenance_mode.lower(), - maint_reason=args.reason) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -@cliutils.arg( - 'power_state', - metavar='<power-state>', - choices=['on', 'off', 'reboot'], - help="'on', 'off', or 'reboot'.") -def do_node_set_power_state(cc, args): - """Power a node on or off or reboot.""" - cc.node.set_power_state(args.node, args.power_state) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -@cliutils.arg( - 'provision_state', - metavar='<provision-state>', - choices=['active', 'deleted', 'rebuild', 'inspect', 'provide', - 'manage'], - help="Supported states: 'active', 'deleted', 'rebuild', " - "'inspect', 'provide' or 'manage'") -@cliutils.arg( - '--config-drive', - metavar='<config-drive>', - default=None, - help=("A gzipped, base64-encoded configuration drive string OR the path " - "to the configuration drive file OR the path to a directory " - "containing the config drive files. In case it's a directory, a " - "config drive will be generated from it. This parameter is only " - "valid when setting provision state to 'active'.")) -def do_node_set_provision_state(cc, args): - """Provision, rebuild, delete, inspect, provide or manage an instance.""" - if args.config_drive and args.provision_state != 'active': - raise exceptions.CommandError(_('--config-drive is only valid when ' - 'setting provision state to "active"')) - cc.node.set_provision_state(args.node, args.provision_state, - configdrive=args.config_drive) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -def do_node_validate(cc, args): - """Validate a node's driver interfaces.""" - ifaces = cc.node.validate(args.node) - obj_list = [] - for key, value in six.iteritems(ifaces.to_dict()): - data = {'interface': key} - data.update(value) - obj_list.append(type('iface', (object,), data)) - field_labels = ['Interface', 'Result', 'Reason'] - fields = ['interface', 'result', 'reason'] - cliutils.print_list(obj_list, fields, field_labels=field_labels) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -def do_node_get_console(cc, args): - """Get the connection information for a node's console, if enabled.""" - info = cc.node.get_console(args.node) - cliutils.print_dict(info, wrap=72) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -@cliutils.arg( - 'enabled', - metavar='<enabled>', - choices=['true', 'false'], - help="Enable or disable console access for a node. Supported options are: " - "'true' or 'false'.") -def do_node_set_console_mode(cc, args): - """Enable or disable serial console access for a node.""" - cc.node.set_console_mode(args.node, args.enabled) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -@cliutils.arg( - 'device', - metavar='<boot-device>', - choices=['pxe', 'disk', 'cdrom', 'bios', 'safe'], - help="'pxe', 'disk', 'cdrom', 'bios', or 'safe'.") -@cliutils.arg( - '--persistent', - dest='persistent', - action='store_true', - default=False, - help="Make changes persistent for all future boots.") -def do_node_set_boot_device(cc, args): - """Set the boot device for a node.""" - cc.node.set_boot_device(args.node, args.device, args.persistent) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -def do_node_get_boot_device(cc, args): - """Get the current boot device for a node.""" - boot_device = cc.node.get_boot_device(args.node) - cliutils.print_dict(boot_device, wrap=72) - - -@cliutils.arg('node', metavar='<node>', help="Name or UUID of the node.") -def do_node_get_supported_boot_devices(cc, args): - """Get the supported boot devices for a node.""" - boot_devices = cc.node.get_supported_boot_devices(args.node) - boot_device_list = boot_devices.get('supported_boot_devices', []) - boot_devices['supported_boot_devices'] = ', '.join(boot_device_list) - cliutils.print_dict(boot_devices, wrap=72) diff --git a/awx/lib/site-packages/ironicclient/v1/port.py b/awx/lib/site-packages/ironicclient/v1/port.py deleted file mode 100644 index c7371fcd9c..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/port.py +++ /dev/null @@ -1,113 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright © 2013 Red Hat, Inc -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ironicclient.common import base -from ironicclient.common import utils -from ironicclient import exc - -CREATION_ATTRIBUTES = ['address', 'extra', 'node_uuid'] - - -class Port(base.Resource): - def __repr__(self): - return "<Port %s>" % self._info - - -class PortManager(base.Manager): - resource_class = Port - - @staticmethod - def _path(id=None): - return '/v1/ports/%s' % id if id else '/v1/ports' - - def list(self, address=None, limit=None, marker=None, sort_key=None, - sort_dir=None, detail=False): - """Retrieve a list of port. - - :param address: Optional, MAC address of a port, to get - the port which has this MAC address - :param marker: Optional, the UUID of a port, eg the last - port from a previous result set. Return - the next result set. - :param limit: The maximum number of results to return per - request, if: - - 1) limit > 0, the maximum number of ports to return. - 2) limit == 0, return the entire list of ports. - 3) limit param is NOT specified (None), the number of items - returned respect the maximum imposed by the Ironic API - (see Ironic's api.max_limit option). - - :param sort_key: Optional, field used for sorting. - - :param sort_dir: Optional, direction of sorting, either 'asc' (the - default) or 'desc'. - - :param detail: Optional, boolean whether to return detailed information - about ports. - - :returns: A list of ports. - - """ - if limit is not None: - limit = int(limit) - - filters = utils.common_filters(marker, limit, sort_key, sort_dir) - if address is not None: - filters.append('address=%s' % address) - - path = '' - if detail: - path += 'detail' - if filters: - path += '?' + '&'.join(filters) - - if limit is None: - return self._list(self._path(path), "ports") - else: - return self._list_pagination(self._path(path), "ports", - limit=limit) - - def get(self, port_id): - try: - return self._list(self._path(port_id))[0] - except IndexError: - return None - - def get_by_address(self, address): - path = "detail?address=%s" % address - ports = self._list(self._path(path), 'ports') - # get all the details of the port assuming that filtering by - # address returns a collection of one port if successful. - if len(ports) == 1: - return ports[0] - else: - raise exc.NotFound() - - def create(self, **kwargs): - new = {} - for (key, value) in kwargs.items(): - if key in CREATION_ATTRIBUTES: - new[key] = value - else: - raise exc.InvalidAttribute() - return self._create(self._path(), new) - - def delete(self, port_id): - return self._delete(self._path(port_id)) - - def update(self, port_id, patch): - return self._update(self._path(port_id), patch) diff --git a/awx/lib/site-packages/ironicclient/v1/port_shell.py b/awx/lib/site-packages/ironicclient/v1/port_shell.py deleted file mode 100644 index f0f7be494a..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/port_shell.py +++ /dev/null @@ -1,164 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -from ironicclient.common import utils -from ironicclient.openstack.common import cliutils -from ironicclient.v1 import resource_fields as res_fields - - -def _print_port_show(port): - fields = ['address', 'created_at', 'extra', 'node_uuid', 'updated_at', - 'uuid'] - data = dict([(f, getattr(port, f, '')) for f in fields]) - cliutils.print_dict(data, wrap=72) - - -@cliutils.arg( - 'port', - metavar='<id>', - help="UUID of the port (or MAC address if --address is specified).") -@cliutils.arg( - '--address', - dest='address', - action='store_true', - default=False, - help='<id> is the MAC address (instead of the UUID) of the port.') -def do_port_show(cc, args): - """Show detailed information about a port.""" - if args.address: - port = cc.port.get_by_address(args.port) - else: - port = cc.port.get(args.port) - _print_port_show(port) - - -@cliutils.arg( - '--detail', - dest='detail', - action='store_true', - default=False, - help="Show detailed information about ports.") -@cliutils.arg( - '--address', - metavar='<mac-address>', - help='Only show information for the port with this MAC address.') -@cliutils.arg( - '--limit', - metavar='<limit>', - type=int, - help='Maximum number of ports to return per request, ' - '0 for no limit. Default is the maximum number used ' - 'by the Ironic API Service.') -@cliutils.arg( - '--marker', - metavar='<port>', - help='Port UUID (for example, of the last port in the list from a ' - 'previous request). Returns the list of ports after this UUID.') -@cliutils.arg( - '--sort-key', - metavar='<field>', - help='Port field that will be used for sorting.') -@cliutils.arg( - '--sort-dir', - metavar='<direction>', - choices=['asc', 'desc'], - help='Sort direction: "asc" (the default) or "desc".') -def do_port_list(cc, args): - """List the ports.""" - params = {} - - if args.address is not None: - params['address'] = args.address - if args.detail: - fields = res_fields.PORT_FIELDS - field_labels = res_fields.PORT_FIELD_LABELS - else: - fields = res_fields.PORT_LIST_FIELDS - field_labels = res_fields.PORT_LIST_FIELD_LABELS - - params.update(utils.common_params_for_list(args, - fields, - field_labels)) - - port = cc.port.list(**params) - cliutils.print_list(port, fields, - field_labels=field_labels, - sortby_index=None) - - -@cliutils.arg( - '-a', '--address', - metavar='<address>', - required=True, - help='MAC address for this port.') -@cliutils.arg( - '-n', '--node', - dest='node_uuid', - metavar='<node>', - required=True, - help='UUID of the node that this port belongs to.') -@cliutils.arg( - '--node_uuid', - help=argparse.SUPPRESS) -@cliutils.arg( - '-e', '--extra', - metavar="<key=value>", - action='append', - help="Record arbitrary key/value metadata. " - "Can be specified multiple times.") -def do_port_create(cc, args): - """Create a new port.""" - field_list = ['address', 'extra', 'node_uuid'] - fields = dict((k, v) for (k, v) in vars(args).items() - if k in field_list and not (v is None)) - fields = utils.args_array_to_dict(fields, 'extra') - port = cc.port.create(**fields) - - field_list.append('uuid') - data = dict([(f, getattr(port, f, '')) for f in field_list]) - cliutils.print_dict(data, wrap=72) - - -@cliutils.arg('port', metavar='<port>', nargs='+', help="UUID of the port.") -def do_port_delete(cc, args): - """Delete a port.""" - for p in args.port: - cc.port.delete(p) - print ('Deleted port %s' % p) - - -@cliutils.arg('port', metavar='<port>', help="UUID of the port.") -@cliutils.arg( - 'op', - metavar='<op>', - choices=['add', 'replace', 'remove'], - help="Operation: 'add', 'replace', or 'remove'.") -@cliutils.arg( - 'attributes', - metavar='<path=value>', - nargs='+', - action='append', - default=[], - help="Attribute to add, replace, or remove. Can be specified multiple " - "times. For 'remove', only <path> is necessary.") -def do_port_update(cc, args): - """Update information about a port.""" - patch = utils.args_array_to_patch(args.op, args.attributes[0]) - port = cc.port.update(args.port, patch) - _print_port_show(port) diff --git a/awx/lib/site-packages/ironicclient/v1/resource_fields.py b/awx/lib/site-packages/ironicclient/v1/resource_fields.py deleted file mode 100644 index 4c731014be..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/resource_fields.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -# Chassis - -CHASSIS_FIELDS = ['uuid', 'description', 'created_at', 'updated_at', 'extra'] - -CHASSIS_FIELD_LABELS = ['UUID', 'Description', 'Created At', 'Updated At', - 'Extra'] - -CHASSIS_LIST_FIELDS = ['uuid', 'description'] - -CHASSIS_LIST_FIELD_LABELS = ['UUID', 'Description'] - - -# Nodes - -NODE_FIELDS = ['chassis_uuid', 'created_at', 'console_enabled', 'driver', - 'driver_info', 'driver_internal_info', 'extra', - 'instance_info', 'instance_uuid', 'last_error', - 'maintenance', 'maintenance_reason', 'power_state', - 'properties', 'provision_state', 'reservation', - 'target_power_state', 'target_provision_state', - 'updated_at', 'inspection_finished_at', - 'inspection_started_at', 'uuid', 'name'] - -NODE_FIELD_LABELS = ['Chassis UUID', 'Created At', 'Console Enabled', 'Driver', - 'Driver Info', 'Driver Internal Info', 'Extra', - 'Instance Info', 'Instance UUID', 'Last Error', - 'Maintenance', 'Maintenance Reason', 'Power State', - 'Properties', 'Provision State', 'Reservation', - 'Target Power State', 'Target Provision State', - 'Updated At', 'Inspection Finished At', - 'Inspection Started At', 'UUID', 'Name'] - -NODE_LIST_FIELDS = ['uuid', 'name', 'instance_uuid', 'power_state', - 'provision_state', 'maintenance'] - -NODE_LIST_FIELD_LABELS = ['UUID', 'Name', 'Instance UUID', 'Power State', - 'Provisioning State', 'Maintenance'] - - -# Ports - -PORT_FIELDS = ['uuid', 'address', 'created_at', 'extra', 'node_uuid', - 'updated_at'] - -PORT_FIELD_LABELS = ['UUID', 'Address', 'Created At', 'Extra', 'Node UUID', - 'Updated At'] - -PORT_LIST_FIELDS = ['uuid', 'address'] - -PORT_LIST_FIELD_LABELS = ['UUID', 'Address'] diff --git a/awx/lib/site-packages/ironicclient/v1/shell.py b/awx/lib/site-packages/ironicclient/v1/shell.py deleted file mode 100644 index 40b48a6b12..0000000000 --- a/awx/lib/site-packages/ironicclient/v1/shell.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from ironicclient.common import utils -from ironicclient.v1 import chassis_shell -from ironicclient.v1 import driver_shell -from ironicclient.v1 import node_shell -from ironicclient.v1 import port_shell - -COMMAND_MODULES = [ - chassis_shell, - node_shell, - port_shell, - driver_shell, -] - - -def enhance_parser(parser, subparsers, cmd_mapper): - """Enhance parser with API version specific options. - - Take a basic (nonversioned) parser and enhance it with - commands and options specific for this version of API. - - :param parser: top level parser :param subparsers: top level - parser's subparsers collection where subcommands will go - """ - for command_module in COMMAND_MODULES: - utils.define_commands_from_module(subparsers, command_module, - cmd_mapper) diff --git a/awx/lib/site-packages/iso8601/__init__.py b/awx/lib/site-packages/iso8601/__init__.py deleted file mode 100644 index 11b1adcbc9..0000000000 --- a/awx/lib/site-packages/iso8601/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .iso8601 import * diff --git a/awx/lib/site-packages/iso8601/iso8601.py b/awx/lib/site-packages/iso8601/iso8601.py deleted file mode 100644 index becdd95812..0000000000 --- a/awx/lib/site-packages/iso8601/iso8601.py +++ /dev/null @@ -1,202 +0,0 @@ -"""ISO 8601 date time string parsing - -Basic usage: ->>> import iso8601 ->>> iso8601.parse_date("2007-01-25T12:00:00Z") -datetime.datetime(2007, 1, 25, 12, 0, tzinfo=<iso8601.iso8601.Utc ...>) ->>> - -""" - -from datetime import ( - datetime, - timedelta, - tzinfo -) -from decimal import Decimal -import logging -import sys -import re - -__all__ = ["parse_date", "ParseError"] - -LOG = logging.getLogger(__name__) - -if sys.version_info >= (3, 0, 0): - _basestring = str -else: - _basestring = basestring - - -# Adapted from http://delete.me.uk/2005/03/iso8601.html -ISO8601_REGEX = re.compile( - r""" - (?P<year>[0-9]{4}) - ( - ( - (-(?P<monthdash>[0-9]{1,2})) - | - (?P<month>[0-9]{2}) - (?!$) # Don't allow YYYYMM - ) - ( - ( - (-(?P<daydash>[0-9]{1,2})) - | - (?P<day>[0-9]{2}) - ) - ( - ( - (?P<separator>[ T]) - (?P<hour>[0-9]{2}) - (:{0,1}(?P<minute>[0-9]{2})){0,1} - ( - :{0,1}(?P<second>[0-9]{1,2}) - (\.(?P<second_fraction>[0-9]+)){0,1} - ){0,1} - (?P<timezone> - Z - | - ( - (?P<tz_sign>[-+]) - (?P<tz_hour>[0-9]{2}) - :{0,1} - (?P<tz_minute>[0-9]{2}){0,1} - ) - ){0,1} - ){0,1} - ) - ){0,1} # YYYY-MM - ){0,1} # YYYY only - $ - """, - re.VERBOSE -) - -class ParseError(Exception): - """Raised when there is a problem parsing a date string""" - -# Yoinked from python docs -ZERO = timedelta(0) -class Utc(tzinfo): - """UTC - - """ - def utcoffset(self, dt): - return ZERO - - def tzname(self, dt): - return "UTC" - - def dst(self, dt): - return ZERO - -UTC = Utc() - -class FixedOffset(tzinfo): - """Fixed offset in hours and minutes from UTC - - """ - def __init__(self, offset_hours, offset_minutes, name): - self.__offset_hours = offset_hours # Keep for later __getinitargs__ - self.__offset_minutes = offset_minutes # Keep for later __getinitargs__ - self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) - self.__name = name - - def __eq__(self, other): - if isinstance(other, FixedOffset): - return ( - (other.__offset == self.__offset) - and - (other.__name == self.__name) - ) - if isinstance(other, tzinfo): - return other == self - return False - - def __getinitargs__(self): - return (self.__offset_hours, self.__offset_minutes, self.__name) - - def utcoffset(self, dt): - return self.__offset - - def tzname(self, dt): - return self.__name - - def dst(self, dt): - return ZERO - - def __repr__(self): - return "<FixedOffset %r %r>" % (self.__name, self.__offset) - -def to_int(d, key, default_to_zero=False, default=None, required=True): - """Pull a value from the dict and convert to int - - :param default_to_zero: If the value is None or empty, treat it as zero - :param default: If the value is missing in the dict use this default - - """ - value = d.get(key) or default - LOG.debug("Got %r for %r with default %r", value, key, default) - if (value in ["", None]) and default_to_zero: - return 0 - if value is None: - if required: - raise ParseError("Unable to read %s from %s" % (key, d)) - else: - return int(value) - -def parse_timezone(matches, default_timezone=UTC): - """Parses ISO 8601 time zone specs into tzinfo offsets - - """ - - if matches["timezone"] == "Z": - return UTC - # This isn't strictly correct, but it's common to encounter dates without - # timezones so I'll assume the default (which defaults to UTC). - # Addresses issue 4. - if matches["timezone"] is None: - return default_timezone - sign = matches["tz_sign"] - hours = to_int(matches, "tz_hour") - minutes = to_int(matches, "tz_minute", default_to_zero=True) - description = "%s%02d:%02d" % (sign, hours, minutes) - if sign == "-": - hours = -hours - minutes = -minutes - return FixedOffset(hours, minutes, description) - -def parse_date(datestring, default_timezone=UTC): - """Parses ISO 8601 dates into datetime objects - - The timezone is parsed from the date string. However it is quite common to - have dates without a timezone (not strictly correct). In this case the - default timezone specified in default_timezone is used. This is UTC by - default. - """ - if not isinstance(datestring, _basestring): - raise ParseError("Expecting a string %r" % datestring) - m = ISO8601_REGEX.match(datestring) - if not m: - raise ParseError("Unable to parse date string %r" % datestring) - groups = m.groupdict() - LOG.debug("Parsed %s into %s with default timezone %s", datestring, groups, default_timezone) - - tz = parse_timezone(groups, default_timezone=default_timezone) - - groups["second_fraction"] = int(Decimal("0.%s" % (groups["second_fraction"] or 0)) * Decimal("1000000.0")) - - try: - return datetime( - year=to_int(groups, "year"), - month=to_int(groups, "month", default=to_int(groups, "monthdash", required=False, default=1)), - day=to_int(groups, "day", default=to_int(groups, "daydash", required=False, default=1)), - hour=to_int(groups, "hour", default_to_zero=True), - minute=to_int(groups, "minute", default_to_zero=True), - second=to_int(groups, "second", default_to_zero=True), - microsecond=groups["second_fraction"], - tzinfo=tz, - ) - except Exception as e: - raise ParseError(e) diff --git a/awx/lib/site-packages/iso8601/test_iso8601.py b/awx/lib/site-packages/iso8601/test_iso8601.py deleted file mode 100644 index ed2d45a0b5..0000000000 --- a/awx/lib/site-packages/iso8601/test_iso8601.py +++ /dev/null @@ -1,97 +0,0 @@ -# coding=UTF-8 -from __future__ import absolute_import - -import copy -import datetime -import pickle - -import pytest - -from iso8601 import iso8601 - -def test_iso8601_regex(): - assert iso8601.ISO8601_REGEX.match("2006-10-11T00:14:33Z") - -def test_parse_no_timezone_different_default(): - tz = iso8601.FixedOffset(2, 0, "test offset") - d = iso8601.parse_date("2007-01-01T08:00:00", default_timezone=tz) - assert d == datetime.datetime(2007, 1, 1, 8, 0, 0, 0, tz) - assert d.tzinfo == tz - -def test_parse_utc_different_default(): - """Z should mean 'UTC', not 'default'. - - """ - tz = iso8601.FixedOffset(2, 0, "test offset") - d = iso8601.parse_date("2007-01-01T08:00:00Z", default_timezone=tz) - assert d == datetime.datetime(2007, 1, 1, 8, 0, 0, 0, iso8601.UTC) - -@pytest.mark.parametrize("invalid_date, error_string", [ - ("2013-10-", "Unable to parse date string"), - ("2013-", "Unable to parse date string"), - ("", "Unable to parse date string"), - (None, "Expecting a string"), - ("wibble", "Unable to parse date string"), - ("23", "Unable to parse date string"), - ("131015T142533Z", "Unable to parse date string"), - ("131015", "Unable to parse date string"), - ("20141", "Unable to parse date string"), - ("201402", "Unable to parse date string"), - ("2007-06-23X06:40:34.00Z", "Unable to parse date string"), # https://code.google.com/p/pyiso8601/issues/detail?id=14 - ("2007-06-23 06:40:34.00Zrubbish", "Unable to parse date string"), # https://code.google.com/p/pyiso8601/issues/detail?id=14 - ("20114-01-03T01:45:49", "Unable to parse date string"), -]) -def test_parse_invalid_date(invalid_date, error_string): - assert isinstance(invalid_date, str) or invalid_date is None # Why? 'cos I've screwed up the parametrize before :) - with pytest.raises(iso8601.ParseError) as exc: - iso8601.parse_date(invalid_date) - assert exc.errisinstance(iso8601.ParseError) - assert str(exc.value).startswith(error_string) - -@pytest.mark.parametrize("valid_date,expected_datetime,isoformat", [ - ("2007-06-23 06:40:34.00Z", datetime.datetime(2007, 6, 23, 6, 40, 34, 0, iso8601.UTC), "2007-06-23T06:40:34+00:00"), # Handle a separator other than T - ("1997-07-16T19:20+01:00", datetime.datetime(1997, 7, 16, 19, 20, 0, 0, iso8601.FixedOffset(1, 0, "+01:00")), "1997-07-16T19:20:00+01:00"), # Parse with no seconds - ("2007-01-01T08:00:00", datetime.datetime(2007, 1, 1, 8, 0, 0, 0, iso8601.UTC), "2007-01-01T08:00:00+00:00"), # Handle timezone-less dates. Assumes UTC. http://code.google.com/p/pyiso8601/issues/detail?id=4 - ("2006-10-20T15:34:56.123+02:30", datetime.datetime(2006, 10, 20, 15, 34, 56, 123000, iso8601.FixedOffset(2, 30, "+02:30")), None), - ("2006-10-20T15:34:56Z", datetime.datetime(2006, 10, 20, 15, 34, 56, 0, iso8601.UTC), "2006-10-20T15:34:56+00:00"), - ("2007-5-7T11:43:55.328Z", datetime.datetime(2007, 5, 7, 11, 43, 55, 328000, iso8601.UTC), "2007-05-07T11:43:55.328000+00:00"), # http://code.google.com/p/pyiso8601/issues/detail?id=6 - ("2006-10-20T15:34:56.123Z", datetime.datetime(2006, 10, 20, 15, 34, 56, 123000, iso8601.UTC), "2006-10-20T15:34:56.123000+00:00"), - ("2013-10-15T18:30Z", datetime.datetime(2013, 10, 15, 18, 30, 0, 0, iso8601.UTC), "2013-10-15T18:30:00+00:00"), - ("2013-10-15T22:30+04", datetime.datetime(2013, 10, 15, 22, 30, 0, 0, iso8601.FixedOffset(4, 0, "+04:00")), "2013-10-15T22:30:00+04:00"), # <time>±hh:mm - ("2013-10-15T1130-0700", datetime.datetime(2013, 10, 15, 11, 30, 0, 0, iso8601.FixedOffset(-7, 0, "-07:00")), "2013-10-15T11:30:00-07:00"), # <time>±hhmm - ("2013-10-15T1130+0700", datetime.datetime(2013, 10, 15, 11, 30, 0, 0, iso8601.FixedOffset(+7, 0, "+07:00")), "2013-10-15T11:30:00+07:00"), # <time>±hhmm - ("2013-10-15T1130+07", datetime.datetime(2013, 10, 15, 11, 30, 0, 0, iso8601.FixedOffset(+7, 0, "+07:00")), "2013-10-15T11:30:00+07:00"), # <time>±hh - ("2013-10-15T1130-07", datetime.datetime(2013, 10, 15, 11, 30, 0, 0, iso8601.FixedOffset(-7, 0, "-07:00")), "2013-10-15T11:30:00-07:00"), # <time>±hh - ("2013-10-15T15:00-03:30", datetime.datetime(2013, 10, 15, 15, 0, 0, 0, iso8601.FixedOffset(-3, -30, "-03:30")), "2013-10-15T15:00:00-03:30"), - ("2013-10-15T183123Z", datetime.datetime(2013, 10, 15, 18, 31, 23, 0, iso8601.UTC), "2013-10-15T18:31:23+00:00"), # hhmmss - ("2013-10-15T1831Z", datetime.datetime(2013, 10, 15, 18, 31, 0, 0, iso8601.UTC), "2013-10-15T18:31:00+00:00"), # hhmm - ("2013-10-15T18Z", datetime.datetime(2013, 10, 15, 18, 0, 0, 0, iso8601.UTC), "2013-10-15T18:00:00+00:00"), # hh - ("2013-10-15", datetime.datetime(2013, 10, 15, 0, 0, 0, 0, iso8601.UTC), "2013-10-15T00:00:00+00:00"), # YYYY-MM-DD - ("20131015T18:30Z", datetime.datetime(2013, 10, 15, 18, 30, 0, 0, iso8601.UTC), "2013-10-15T18:30:00+00:00"), # YYYYMMDD - ("2012-12-19T23:21:28.512400+00:00", datetime.datetime(2012, 12, 19, 23, 21, 28, 512400, iso8601.FixedOffset(0, 0, "+00:00")), "2012-12-19T23:21:28.512400+00:00"), # https://code.google.com/p/pyiso8601/issues/detail?id=21 - ("2006-10-20T15:34:56.123+0230", datetime.datetime(2006, 10, 20, 15, 34, 56, 123000, iso8601.FixedOffset(2, 30, "+02:30")), "2006-10-20T15:34:56.123000+02:30"), # https://code.google.com/p/pyiso8601/issues/detail?id=18 - ("19950204", datetime.datetime(1995, 2, 4, tzinfo=iso8601.UTC), "1995-02-04T00:00:00+00:00"), # https://code.google.com/p/pyiso8601/issues/detail?id=1 - ("2010-07-20 15:25:52.520701+00:00", datetime.datetime(2010, 7, 20, 15, 25, 52, 520701, iso8601.FixedOffset(0, 0, "+00:00")), "2010-07-20T15:25:52.520701+00:00"), # https://code.google.com/p/pyiso8601/issues/detail?id=17 - ("2010-06-12", datetime.datetime(2010, 6, 12, tzinfo=iso8601.UTC), "2010-06-12T00:00:00+00:00"), # https://code.google.com/p/pyiso8601/issues/detail?id=16 - ("1985-04-12T23:20:50.52-05:30", datetime.datetime(1985, 4, 12, 23, 20, 50, 520000, iso8601.FixedOffset(-5, -30, "-05:30")), "1985-04-12T23:20:50.520000-05:30"), # https://bitbucket.org/micktwomey/pyiso8601/issue/8/015-parses-negative-timezones-incorrectly - ("1997-08-29T06:14:00.000123Z", datetime.datetime(1997, 8, 29, 6, 14, 0, 123, iso8601.UTC), "1997-08-29T06:14:00.000123+00:00"), # https://bitbucket.org/micktwomey/pyiso8601/issue/9/regression-parsing-microseconds - ("2014-02", datetime.datetime(2014, 2, 1, 0, 0, 0, 0, iso8601.UTC), "2014-02-01T00:00:00+00:00"), # https://bitbucket.org/micktwomey/pyiso8601/issue/14/regression-yyyy-mm-no-longer-parses - ("2014", datetime.datetime(2014, 1, 1, 0, 0, 0, 0, iso8601.UTC), "2014-01-01T00:00:00+00:00"), # YYYY -]) -def test_parse_valid_date(valid_date, expected_datetime, isoformat): - parsed = iso8601.parse_date(valid_date) - assert parsed.year == expected_datetime.year - assert parsed.month == expected_datetime.month - assert parsed.day == expected_datetime.day - assert parsed.hour == expected_datetime.hour - assert parsed.minute == expected_datetime.minute - assert parsed.second == expected_datetime.second - assert parsed.microsecond == expected_datetime.microsecond - assert parsed.tzinfo == expected_datetime.tzinfo - assert parsed == expected_datetime - assert parsed.isoformat() == expected_datetime.isoformat() - copy.deepcopy(parsed) # ensure it's deep copy-able - pickle.dumps(parsed) # ensure it pickles - if isoformat: - assert parsed.isoformat() == isoformat - assert iso8601.parse_date(parsed.isoformat()) == parsed # Test round trip diff --git a/awx/lib/site-packages/isodate/__init__.py b/awx/lib/site-packages/isodate/__init__.py deleted file mode 100644 index 091af0aeba..0000000000 --- a/awx/lib/site-packages/isodate/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Import all essential functions and constants to re-export them here for easy -access. - -This module contains also various pre-defined ISO 8601 format strings. -''' -from isodate.isodates import parse_date, date_isoformat -from isodate.isotime import parse_time, time_isoformat -from isodate.isodatetime import parse_datetime, datetime_isoformat -from isodate.isoduration import parse_duration, duration_isoformat, Duration -from isodate.isoerror import ISO8601Error -from isodate.isotzinfo import parse_tzinfo, tz_isoformat -from isodate.tzinfo import UTC, FixedOffset, LOCAL -from isodate.duration import Duration -from isodate.isostrf import strftime -from isodate.isostrf import DATE_BAS_COMPLETE, DATE_BAS_ORD_COMPLETE -from isodate.isostrf import DATE_BAS_WEEK, DATE_BAS_WEEK_COMPLETE -from isodate.isostrf import DATE_CENTURY, DATE_EXT_COMPLETE -from isodate.isostrf import DATE_EXT_ORD_COMPLETE, DATE_EXT_WEEK -from isodate.isostrf import DATE_EXT_WEEK_COMPLETE, DATE_MONTH, DATE_YEAR -from isodate.isostrf import TIME_BAS_COMPLETE, TIME_BAS_MINUTE -from isodate.isostrf import TIME_EXT_COMPLETE, TIME_EXT_MINUTE -from isodate.isostrf import TIME_HOUR -from isodate.isostrf import TZ_BAS, TZ_EXT, TZ_HOUR -from isodate.isostrf import DT_BAS_COMPLETE, DT_EXT_COMPLETE -from isodate.isostrf import DT_BAS_ORD_COMPLETE, DT_EXT_ORD_COMPLETE -from isodate.isostrf import DT_BAS_WEEK_COMPLETE, DT_EXT_WEEK_COMPLETE -from isodate.isostrf import D_DEFAULT, D_WEEK, D_ALT_EXT, D_ALT_BAS -from isodate.isostrf import D_ALT_BAS_ORD, D_ALT_EXT_ORD diff --git a/awx/lib/site-packages/isodate/duration.py b/awx/lib/site-packages/isodate/duration.py deleted file mode 100644 index 4484919773..0000000000 --- a/awx/lib/site-packages/isodate/duration.py +++ /dev/null @@ -1,280 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -This module defines a Duration class. - -The class Duration allows to define durations in years and months and can be -used as limited replacement for timedelta objects. -''' -from datetime import date, datetime, timedelta -from decimal import Decimal, ROUND_FLOOR - - -def fquotmod(val, low, high): - ''' - A divmod function with boundaries. - - ''' - # assumes that all the maths is done with Decimals. - # divmod for Decimal uses truncate instead of floor as builtin divmod, so we have - # to do it manually here. - a, b = val - low, high - low - div = (a / b).to_integral(ROUND_FLOOR) - mod = a - div * b - # if we were not usig Decimal, it would look like this. - #div, mod = divmod(val - low, high - low) - mod += low - return int(div), mod - - -def max_days_in_month(year, month): - ''' - Determines the number of days of a specific month in a specific year. - ''' - if month in (1, 3, 5, 7, 8, 10, 12): - return 31 - if month in (4, 6, 9, 11): - return 30 - if ((year % 400) == 0) or ((year % 100) != 0) and ((year % 4) == 0): - return 29 - return 28 - - -class Duration(object): - ''' - A class which represents a duration. - - The difference to datetime.timedelta is, that this class handles also - differences given in years and months. - A Duration treats differences given in year, months separately from all - other components. - - A Duration can be used almost like any timedelta object, however there - are some restrictions: - * It is not really possible to compare Durations, because it is unclear, - whether a duration of 1 year is bigger than 365 days or not. - * Equality is only tested between the two (year, month vs. timedelta) - basic components. - - A Duration can also be converted into a datetime object, but this requires - a start date or an end date. - - The algorithm to add a duration to a date is defined at - http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes - ''' - - def __init__(self, days=0, seconds=0, microseconds=0, milliseconds=0, - minutes=0, hours=0, weeks=0, months=0, years=0): - ''' - Initialise this Duration instance with the given parameters. - ''' - if not isinstance(months, Decimal): - months = Decimal(str(months)) - if not isinstance(years, Decimal): - years = Decimal(str(years)) - self.months = months - self.years = years - self.tdelta = timedelta(days, seconds, microseconds, milliseconds, - minutes, hours, weeks) - - def __getattr__(self, name): - ''' - Provide direct access to attributes of included timedelta instance. - ''' - return getattr(self.tdelta, name) - - def __str__(self): - ''' - Return a string representation of this duration similar to timedelta. - ''' - params = [] - if self.years: - params.append('%d years' % self.years) - if self.months: - params.append('%d months' % self.months) - params.append(str(self.tdelta)) - return ', '.join(params) - - def __repr__(self): - ''' - Return a string suitable for repr(x) calls. - ''' - return "%s.%s(%d, %d, %d, years=%d, months=%d)" % ( - self.__class__.__module__, self.__class__.__name__, - self.tdelta.days, self.tdelta.seconds, - self.tdelta.microseconds, self.years, self.months) - - def __neg__(self): - """ - A simple unary minus. - - Returns a new Duration instance with all it's negated. - """ - negduration = Duration(years=-self.years, months=-self.months) - negduration.tdelta = -self.tdelta - return negduration - - def __add__(self, other): - ''' - Durations can be added with Duration, timedelta, date and datetime - objects. - ''' - if isinstance(other, timedelta): - newduration = Duration(years=self.years, months=self.months) - newduration.tdelta = self.tdelta + other - return newduration - if isinstance(other, Duration): - newduration = Duration(years=self.years + other.years, - months=self.months + other.months) - newduration.tdelta = self.tdelta + other.tdelta - return newduration - if isinstance(other, (date, datetime)): - if (not( float(self.years).is_integer() and float(self.months).is_integer())): - raise ValueError('fractional years or months not supported for date calculations') - newmonth = other.month + self.months - carry, newmonth = fquotmod(newmonth, 1, 13) - newyear = other.year + self.years + carry - maxdays = max_days_in_month(newyear, newmonth) - if other.day > maxdays: - newday = maxdays - else: - newday = other.day - newdt = other.replace(year=newyear, month=newmonth, day=newday) - return self.tdelta + newdt - raise TypeError('unsupported operand type(s) for +: %s and %s' % - (self.__class__, other.__class__)) - - def __radd__(self, other): - ''' - Add durations to timedelta, date and datetime objects. - ''' - if isinstance(other, timedelta): - newduration = Duration(years=self.years, months=self.months) - newduration.tdelta = self.tdelta + other - return newduration - if isinstance(other, (date, datetime)): - if (not( float(self.years).is_integer() and float(self.months).is_integer())): - raise ValueError('fractional years or months not supported for date calculations') - newmonth = other.month + self.months - carry, newmonth = fquotmod(newmonth, 1, 13) - newyear = other.year + self.years + carry - maxdays = max_days_in_month(newyear, newmonth) - if other.day > maxdays: - newday = maxdays - else: - newday = other.day - newdt = other.replace(year=newyear, month=newmonth, day=newday) - return newdt + self.tdelta - raise TypeError('unsupported operand type(s) for +: %s and %s' % - (other.__class__, self.__class__)) - - def __sub__(self, other): - ''' - It is possible to subtract Duration and timedelta objects from Duration - objects. - ''' - if isinstance(other, Duration): - newduration = Duration(years=self.years - other.years, - months=self.months - other.months) - newduration.tdelta = self.tdelta - other.tdelta - return newduration - if isinstance(other, timedelta): - newduration = Duration(years=self.years, months=self.months) - newduration.tdelta = self.tdelta - other - return newduration - raise TypeError('unsupported operand type(s) for -: %s and %s' % - (self.__class__, other.__class__)) - - def __rsub__(self, other): - ''' - It is possible to subtract Duration objecs from date, datetime and - timedelta objects. - ''' - #print '__rsub__:', self, other - if isinstance(other, (date, datetime)): - if (not( float(self.years).is_integer() and float(self.months).is_integer())): - raise ValueError('fractional years or months not supported for date calculations') - newmonth = other.month - self.months - carry, newmonth = fquotmod(newmonth, 1, 13) - newyear = other.year - self.years + carry - maxdays = max_days_in_month(newyear, newmonth) - if other.day > maxdays: - newday = maxdays - else: - newday = other.day - newdt = other.replace(year=newyear, month=newmonth, day=newday) - return newdt - self.tdelta - if isinstance(other, timedelta): - tmpdur = Duration() - tmpdur.tdelta = other - return tmpdur - self - raise TypeError('unsupported operand type(s) for -: %s and %s' % - (other.__class__, self.__class__)) - - def __eq__(self, other): - ''' - If the years, month part and the timedelta part are both equal, then - the two Durations are considered equal. - ''' - if (isinstance(other, timedelta) and - self.years == 0 and self.months == 0): - return self.tdelta == other - if not isinstance(other, Duration): - return NotImplemented - if ((self.years * 12 + self.months) == - (other.years * 12 + other.months) and self.tdelta == other.tdelta): - return True - return False - - def __ne__(self, other): - ''' - If the years, month part or the timedelta part is not equal, then - the two Durations are considered not equal. - ''' - if isinstance(other, timedelta) and self.years == 0 and self.months == 0: - return self.tdelta != other - if not isinstance(other, Duration): - return NotImplemented - if ((self.years * 12 + self.months) != - (other.years * 12 + other.months) or self.tdelta != other.tdelta): - return True - return False - - def totimedelta(self, start=None, end=None): - ''' - Convert this duration into a timedelta object. - - This method requires a start datetime or end datetimem, but raises - an exception if both are given. - ''' - if start is None and end is None: - raise ValueError("start or end required") - if start is not None and end is not None: - raise ValueError("only start or end allowed") - if start is not None: - return (start + self) - start - return end - (end - self) diff --git a/awx/lib/site-packages/isodate/isodates.py b/awx/lib/site-packages/isodate/isodates.py deleted file mode 100644 index 8bafa207fc..0000000000 --- a/awx/lib/site-packages/isodate/isodates.py +++ /dev/null @@ -1,201 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -This modules provides a method to parse an ISO 8601:2004 date string to a -python datetime.date instance. - -It supports all basic, extended and expanded formats as described in the ISO -standard. The only limitations it has, are given by the Python datetime.date -implementation, which does not support dates before 0001-01-01. -''' -import re -from datetime import date, timedelta - -from isodate.isostrf import strftime, DATE_EXT_COMPLETE -from isodate.isoerror import ISO8601Error - -DATE_REGEX_CACHE = {} -# A dictionary to cache pre-compiled regular expressions. -# A set of regular expressions is identified, by number of year digits allowed -# and whether a plus/minus sign is required or not. (This option is changeable -# only for 4 digit years). - -def build_date_regexps(yeardigits=4, expanded=False): - ''' - Compile set of regular expressions to parse ISO dates. The expressions will - be created only if they are not already in REGEX_CACHE. - - It is necessary to fix the number of year digits, else it is not possible - to automatically distinguish between various ISO date formats. - - ISO 8601 allows more than 4 digit years, on prior agreement, but then a +/- - sign is required (expanded format). To support +/- sign for 4 digit years, - the expanded parameter needs to be set to True. - ''' - if yeardigits != 4: - expanded = True - if (yeardigits, expanded) not in DATE_REGEX_CACHE: - cache_entry = [] - # ISO 8601 expanded DATE formats allow an arbitrary number of year - # digits with a leading +/- sign. - if expanded: - sign = 1 - else: - sign = 0 - # 1. complete dates: - # YYYY-MM-DD or +- YYYYYY-MM-DD... extended date format - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - r"-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})" - % (sign, yeardigits))) - # YYYYMMDD or +- YYYYYYMMDD... basic date format - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - r"(?P<month>[0-9]{2})(?P<day>[0-9]{2})" - % (sign, yeardigits))) - # 2. complete week dates: - # YYYY-Www-D or +-YYYYYY-Www-D ... extended week date - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - r"-W(?P<week>[0-9]{2})-(?P<day>[0-9]{1})" - % (sign, yeardigits))) - # YYYYWwwD or +-YYYYYYWwwD ... basic week date - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})W" - r"(?P<week>[0-9]{2})(?P<day>[0-9]{1})" - % (sign, yeardigits))) - # 3. ordinal dates: - # YYYY-DDD or +-YYYYYY-DDD ... extended format - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - r"-(?P<day>[0-9]{3})" - % (sign, yeardigits))) - # YYYYDDD or +-YYYYYYDDD ... basic format - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - r"(?P<day>[0-9]{3})" - % (sign, yeardigits))) - # 4. week dates: - # YYYY-Www or +-YYYYYY-Www ... extended reduced accuracy week date - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - r"-W(?P<week>[0-9]{2})" - % (sign, yeardigits))) - # YYYYWww or +-YYYYYYWww ... basic reduced accuracy week date - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})W" - r"(?P<week>[0-9]{2})" - % (sign, yeardigits))) - # 5. month dates: - # YYY-MM or +-YYYYYY-MM ... reduced accuracy specific month - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - r"-(?P<month>[0-9]{2})" - % (sign, yeardigits))) - # 6. year dates: - # YYYY or +-YYYYYY ... reduced accuracy specific year - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}(?P<year>[0-9]{%d})" - % (sign, yeardigits))) - # 7. century dates: - # YY or +-YYYY ... reduced accuracy specific century - cache_entry.append(re.compile(r"(?P<sign>[+-]){%d}" - r"(?P<century>[0-9]{%d})" - % (sign, yeardigits - 2))) - - DATE_REGEX_CACHE[(yeardigits, expanded)] = cache_entry - return DATE_REGEX_CACHE[(yeardigits, expanded)] - -def parse_date(datestring, yeardigits=4, expanded=False): - ''' - Parse an ISO 8601 date string into a datetime.date object. - - As the datetime.date implementation is limited to dates starting from - 0001-01-01, negative dates (BC) and year 0 can not be parsed by this - method. - - For incomplete dates, this method chooses the first day for it. For - instance if only a century is given, this method returns the 1st of - January in year 1 of this century. - - supported formats: (expanded formats are shown with 6 digits for year) - YYYYMMDD +-YYYYYYMMDD basic complete date - YYYY-MM-DD +-YYYYYY-MM-DD extended complete date - YYYYWwwD +-YYYYYYWwwD basic complete week date - YYYY-Www-D +-YYYYYY-Www-D extended complete week date - YYYYDDD +-YYYYYYDDD basic ordinal date - YYYY-DDD +-YYYYYY-DDD extended ordinal date - YYYYWww +-YYYYYYWww basic incomplete week date - YYYY-Www +-YYYYYY-Www extended incomplete week date - YYY-MM +-YYYYYY-MM incomplete month date - YYYY +-YYYYYY incomplete year date - YY +-YYYY incomplete century date - - @param datestring: the ISO date string to parse - @param yeardigits: how many digits are used to represent a year - @param expanded: if True then +/- signs are allowed. This parameter - is forced to True, if yeardigits != 4 - - @return: a datetime.date instance represented by datestring - @raise ISO8601Error: if this function can not parse the datestring - @raise ValueError: if datestring can not be represented by datetime.date - ''' - if yeardigits != 4: - expanded = True - isodates = build_date_regexps(yeardigits, expanded) - for pattern in isodates: - match = pattern.match(datestring) - if match: - groups = match.groupdict() - # sign, century, year, month, week, day, - # FIXME: negative dates not possible with python standard types - sign = (groups['sign'] == '-' and -1) or 1 - if 'century' in groups: - return date(sign * (int(groups['century']) * 100 + 1), 1, 1) - if not 'month' in groups: # weekdate or ordinal date - ret = date(sign * int(groups['year']), 1, 1) - if 'week' in groups: - isotuple = ret.isocalendar() - if 'day' in groups: - days = int(groups['day'] or 1) - else: - days = 1 - # if first week in year, do weeks-1 - return ret + timedelta(weeks=int(groups['week']) - - (((isotuple[1] == 1) and 1) or 0), - days = -isotuple[2] + days) - elif 'day' in groups: # ordinal date - return ret + timedelta(days=int(groups['day'])-1) - else: # year date - return ret - # year-, month-, or complete date - if 'day' not in groups or groups['day'] is None: - day = 1 - else: - day = int(groups['day']) - return date(sign * int(groups['year']), - int(groups['month']) or 1, day) - raise ISO8601Error('Unrecognised ISO 8601 date format: %r' % datestring) - -def date_isoformat(tdate, format=DATE_EXT_COMPLETE, yeardigits=4): - ''' - Format date strings. - - This method is just a wrapper around isodate.isostrf.strftime and uses - Date-Extended-Complete as default format. - ''' - return strftime(tdate, format, yeardigits) diff --git a/awx/lib/site-packages/isodate/isodatetime.py b/awx/lib/site-packages/isodate/isodatetime.py deleted file mode 100644 index 7e4d570411..0000000000 --- a/awx/lib/site-packages/isodate/isodatetime.py +++ /dev/null @@ -1,61 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -This module defines a method to parse an ISO 8601:2004 date time string. - -For this job it uses the parse_date and parse_time methods defined in date -and time module. -''' -from datetime import datetime - -from isodate.isostrf import strftime -from isodate.isostrf import DATE_EXT_COMPLETE, TIME_EXT_COMPLETE, TZ_EXT -from isodate.isodates import parse_date -from isodate.isotime import parse_time - -def parse_datetime(datetimestring): - ''' - Parses ISO 8601 date-times into datetime.datetime objects. - - This function uses parse_date and parse_time to do the job, so it allows - more combinations of date and time representations, than the actual - ISO 8601:2004 standard allows. - ''' - datestring, timestring = datetimestring.split('T') - tmpdate = parse_date(datestring) - tmptime = parse_time(timestring) - return datetime.combine(tmpdate, tmptime) - -def datetime_isoformat(tdt, format=DATE_EXT_COMPLETE + 'T' + - TIME_EXT_COMPLETE + TZ_EXT): - ''' - Format datetime strings. - - This method is just a wrapper around isodate.isostrf.strftime and uses - Extended-Complete as default format. - ''' - return strftime(tdt, format) diff --git a/awx/lib/site-packages/isodate/isoduration.py b/awx/lib/site-packages/isodate/isoduration.py deleted file mode 100644 index 97affdc10c..0000000000 --- a/awx/lib/site-packages/isodate/isoduration.py +++ /dev/null @@ -1,145 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -This module provides an ISO 8601:2004 duration parser. - -It also provides a wrapper to strftime. This wrapper makes it easier to -format timedelta or Duration instances as ISO conforming strings. -''' -from datetime import timedelta -from decimal import Decimal -import re - -from isodate.duration import Duration -from isodate.isoerror import ISO8601Error -from isodate.isodatetime import parse_datetime -from isodate.isostrf import strftime, D_DEFAULT - -ISO8601_PERIOD_REGEX = re.compile(r"^(?P<sign>[+-])?" - r"P(?P<years>[0-9]+([,.][0-9]+)?Y)?" - r"(?P<months>[0-9]+([,.][0-9]+)?M)?" - r"(?P<weeks>[0-9]+([,.][0-9]+)?W)?" - r"(?P<days>[0-9]+([,.][0-9]+)?D)?" - r"((?P<separator>T)(?P<hours>[0-9]+([,.][0-9]+)?H)?" - r"(?P<minutes>[0-9]+([,.][0-9]+)?M)?" - r"(?P<seconds>[0-9]+([,.][0-9]+)?S)?)?$") -# regular expression to parse ISO duartion strings. - - -def parse_duration(datestring): - """ - Parses an ISO 8601 durations into datetime.timedelta or Duration objects. - - If the ISO date string does not contain years or months, a timedelta - instance is returned, else a Duration instance is returned. - - The following duration formats are supported: - -PnnW duration in weeks - -PnnYnnMnnDTnnHnnMnnS complete duration specification - -PYYYYMMDDThhmmss basic alternative complete date format - -PYYYY-MM-DDThh:mm:ss extended alternative complete date format - -PYYYYDDDThhmmss basic alternative ordinal date format - -PYYYY-DDDThh:mm:ss extended alternative ordinal date format - - The '-' is optional. - - Limitations: ISO standard defines some restrictions about where to use - fractional numbers and which component and format combinations are - allowed. This parser implementation ignores all those restrictions and - returns something when it is able to find all necessary components. - In detail: - it does not check, whether only the last component has fractions. - it allows weeks specified with all other combinations - - The alternative format does not support durations with years, months or - days set to 0. - """ - if not isinstance(datestring, basestring): - raise TypeError("Expecting a string %r" % datestring) - match = ISO8601_PERIOD_REGEX.match(datestring) - if not match: - # try alternative format: - if datestring.startswith("P"): - durdt = parse_datetime(datestring[1:]) - if durdt.year != 0 or durdt.month != 0: - # create Duration - ret = Duration(days=durdt.day, seconds=durdt.second, - microseconds=durdt.microsecond, - minutes=durdt.minute, hours=durdt.hour, - months=durdt.month, years=durdt.year) - else: # FIXME: currently not possible in alternative format - # create timedelta - ret = timedelta(days=durdt.day, seconds=durdt.second, - microseconds=durdt.microsecond, - minutes=durdt.minute, hours=durdt.hour) - return ret - raise ISO8601Error("Unable to parse duration string %r" % datestring) - groups = match.groupdict() - for key, val in groups.items(): - if key not in ('separator', 'sign'): - if val is None: - groups[key] = "0n" - #print groups[key] - if key in ('years', 'months'): - groups[key] = Decimal(groups[key][:-1].replace(',', '.')) - else: - # these values are passed into a timedelta object, which works with floats. - groups[key] = float(groups[key][:-1].replace(',', '.')) - if groups["years"] == 0 and groups["months"] == 0: - ret = timedelta(days=groups["days"], hours=groups["hours"], - minutes=groups["minutes"], seconds=groups["seconds"], - weeks=groups["weeks"]) - if groups["sign"] == '-': - ret = timedelta(0) - ret - else: - ret = Duration(years=groups["years"], months=groups["months"], - days=groups["days"], hours=groups["hours"], - minutes=groups["minutes"], seconds=groups["seconds"], - weeks=groups["weeks"]) - if groups["sign"] == '-': - ret = Duration(0) - ret - return ret - - -def duration_isoformat(tduration, format=D_DEFAULT): - ''' - Format duration strings. - - This method is just a wrapper around isodate.isostrf.strftime and uses - P%P (D_DEFAULT) as default format. - ''' - # TODO: implement better decision for negative Durations. - # should be done in Duration class in consistent way with timedelta. - if ((isinstance(tduration, Duration) and (tduration.years < 0 or - tduration.months < 0 or - tduration.tdelta < timedelta(0))) - or (isinstance(tduration, timedelta) and (tduration < timedelta(0)))): - ret = '-' - else: - ret = '' - ret += strftime(tduration, format) - return ret diff --git a/awx/lib/site-packages/isodate/isoerror.py b/awx/lib/site-packages/isodate/isoerror.py deleted file mode 100644 index edbc5aaa8f..0000000000 --- a/awx/lib/site-packages/isodate/isoerror.py +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -This module defines all exception classes in the whole package. -''' - -class ISO8601Error(ValueError): - '''Raised when the given ISO string can not be parsed.''' diff --git a/awx/lib/site-packages/isodate/isostrf.py b/awx/lib/site-packages/isodate/isostrf.py deleted file mode 100644 index 5f3169f4b4..0000000000 --- a/awx/lib/site-packages/isodate/isostrf.py +++ /dev/null @@ -1,207 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -""" -This module provides an alternative strftime method. - -The strftime method in this module allows only a subset of Python's strftime -format codes, plus a few additional. It supports the full range of date values -possible with standard Python date/time objects. Furthermore there are several -pr-defined format strings in this module to make ease producing of ISO 8601 -conforming strings. -""" -import re -from datetime import date, timedelta - -from isodate.duration import Duration -from isodate.isotzinfo import tz_isoformat - -# Date specific format strings -DATE_BAS_COMPLETE = '%Y%m%d' -DATE_EXT_COMPLETE = '%Y-%m-%d' -DATE_BAS_WEEK_COMPLETE = '%YW%W%w' -DATE_EXT_WEEK_COMPLETE = '%Y-W%W-%w' -DATE_BAS_ORD_COMPLETE = '%Y%j' -DATE_EXT_ORD_COMPLETE = '%Y-%j' -DATE_BAS_WEEK = '%YW%W' -DATE_EXT_WEEK = '%Y-W%W' -DATE_MONTH = '%Y-%m' -DATE_YEAR = '%Y' -DATE_CENTURY = '%C' - -# Time specific format strings -TIME_BAS_COMPLETE = '%H%M%S' -TIME_EXT_COMPLETE = '%H:%M:%S' -TIME_BAS_MINUTE = '%H%M' -TIME_EXT_MINUTE = '%H:%M' -TIME_HOUR = '%H' - -# Time zone formats -TZ_BAS = '%z' -TZ_EXT = '%Z' -TZ_HOUR = '%h' - -# DateTime formats -DT_EXT_COMPLETE = DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + TZ_EXT -DT_BAS_COMPLETE = DATE_BAS_COMPLETE + 'T' + TIME_BAS_COMPLETE + TZ_BAS -DT_EXT_ORD_COMPLETE = DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_COMPLETE + TZ_EXT -DT_BAS_ORD_COMPLETE = DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_COMPLETE + TZ_BAS -DT_EXT_WEEK_COMPLETE = DATE_EXT_WEEK_COMPLETE + 'T' + TIME_EXT_COMPLETE +\ - TZ_EXT -DT_BAS_WEEK_COMPLETE = DATE_BAS_WEEK_COMPLETE + 'T' + TIME_BAS_COMPLETE +\ - TZ_BAS - -# Duration formts -D_DEFAULT = 'P%P' -D_WEEK = 'P%p' -D_ALT_EXT = 'P' + DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE -D_ALT_BAS = 'P' + DATE_BAS_COMPLETE + 'T' + TIME_BAS_COMPLETE -D_ALT_EXT_ORD = 'P' + DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_COMPLETE -D_ALT_BAS_ORD = 'P' + DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_COMPLETE - -STRF_DT_MAP = {'%d': lambda tdt, yds: '%02d' % tdt.day, - '%f': lambda tdt, yds: '%06d' % tdt.microsecond, - '%H': lambda tdt, yds: '%02d' % tdt.hour, - '%j': lambda tdt, yds: '%03d' % (tdt.toordinal() - - date(tdt.year, 1, 1).toordinal() + - 1), - '%m': lambda tdt, yds: '%02d' % tdt.month, - '%M': lambda tdt, yds: '%02d' % tdt.minute, - '%S': lambda tdt, yds: '%02d' % tdt.second, - '%w': lambda tdt, yds: '%1d' % tdt.isoweekday(), - '%W': lambda tdt, yds: '%02d' % tdt.isocalendar()[1], - '%Y': lambda tdt, yds: (((yds != 4) and '+') or '') +\ - (('%%0%dd' % yds) % tdt.year), - '%C': lambda tdt, yds: (((yds != 4) and '+') or '') +\ - (('%%0%dd' % (yds - 2)) % (tdt.year / 100)), - '%h': lambda tdt, yds: tz_isoformat(tdt, '%h'), - '%Z': lambda tdt, yds: tz_isoformat(tdt, '%Z'), - '%z': lambda tdt, yds: tz_isoformat(tdt, '%z'), - '%%': lambda tdt, yds: '%'} - -STRF_D_MAP = {'%d': lambda tdt, yds: '%02d' % tdt.days, - '%f': lambda tdt, yds: '%06d' % tdt.microseconds, - '%H': lambda tdt, yds: '%02d' % (tdt.seconds / 60 / 60), - '%m': lambda tdt, yds: '%02d' % tdt.months, - '%M': lambda tdt, yds: '%02d' % ((tdt.seconds / 60) % 60), - '%S': lambda tdt, yds: '%02d' % (tdt.seconds % 60), - '%W': lambda tdt, yds: '%02d' % (abs(tdt.days / 7)), - '%Y': lambda tdt, yds: (((yds != 4) and '+') or '') +\ - (('%%0%dd' % yds) % tdt.years), - '%C': lambda tdt, yds: (((yds != 4) and '+') or '') +\ - (('%%0%dd' % (yds - 2)) % - (tdt.years / 100)), - '%%': lambda tdt, yds: '%'} - - -def _strfduration(tdt, format, yeardigits=4): - ''' - this is the work method for timedelta and Duration instances. - - see strftime for more details. - ''' - def repl(match): - ''' - lookup format command and return corresponding replacement. - ''' - if match.group(0) in STRF_D_MAP: - return STRF_D_MAP[match.group(0)](tdt, yeardigits) - elif match.group(0) == '%P': - ret = [] - if isinstance(tdt, Duration): - if tdt.years: - ret.append('%sY' % abs(tdt.years)) - if tdt.months: - ret.append('%sM' % abs(tdt.months)) - usecs = abs((tdt.days * 24 * 60 * 60 + tdt.seconds) * 1000000 + - tdt.microseconds) - seconds, usecs = divmod(usecs, 1000000) - minutes, seconds = divmod(seconds, 60) - hours, minutes = divmod(minutes, 60) - days, hours = divmod(hours, 24) - if days: - ret.append('%sD' % days) - if hours or minutes or seconds or usecs: - ret.append('T') - if hours: - ret.append('%sH' % hours) - if minutes: - ret.append('%sM' % minutes) - if seconds or usecs: - if usecs: - ret.append(("%d.%06d" % (seconds, usecs)).rstrip('0')) - else: - ret.append("%d" % seconds) - ret.append('S') - # at least one component has to be there. - return ret and ''.join(ret) or '0D' - elif match.group(0) == '%p': - return str(abs(tdt.days // 7)) + 'W' - return match.group(0) - return re.sub('%d|%f|%H|%m|%M|%S|%W|%Y|%C|%%|%P|%p', repl, - format) - - -def _strfdt(tdt, format, yeardigits=4): - ''' - this is the work method for time and date instances. - - see strftime for more details. - ''' - def repl(match): - ''' - lookup format command and return corresponding replacement. - ''' - if match.group(0) in STRF_DT_MAP: - return STRF_DT_MAP[match.group(0)](tdt, yeardigits) - return match.group(0) - return re.sub('%d|%f|%H|%j|%m|%M|%S|%w|%W|%Y|%C|%z|%Z|%h|%%', repl, - format) - - -def strftime(tdt, format, yeardigits=4): - ''' - Directive Meaning Notes - %d Day of the month as a decimal number [01,31]. - %f Microsecond as a decimal number [0,999999], zero-padded on the left (1) - %H Hour (24-hour clock) as a decimal number [00,23]. - %j Day of the year as a decimal number [001,366]. - %m Month as a decimal number [01,12]. - %M Minute as a decimal number [00,59]. - %S Second as a decimal number [00,61]. (3) - %w Weekday as a decimal number [0(Monday),6]. - %W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. (4) - %Y Year with century as a decimal number. [0000,9999] - %C Century as a decimal number. [00,99] - %z UTC offset in the form +HHMM or -HHMM (empty string if the the object is naive). (5) - %Z Time zone name (empty string if the object is naive). - %P ISO8601 duration format. - %p ISO8601 duration format in weeks. - %% A literal '%' character. - ''' - if isinstance(tdt, (timedelta, Duration)): - return _strfduration(tdt, format, yeardigits) - return _strfdt(tdt, format, yeardigits) diff --git a/awx/lib/site-packages/isodate/isotime.py b/awx/lib/site-packages/isodate/isotime.py deleted file mode 100644 index 7ded2d4878..0000000000 --- a/awx/lib/site-packages/isodate/isotime.py +++ /dev/null @@ -1,157 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -This modules provides a method to parse an ISO 8601:2004 time string to a -Python datetime.time instance. - -It supports all basic and extended formats including time zone specifications -as described in the ISO standard. -''' -import re -from decimal import Decimal -from datetime import time - -from isodate.isostrf import strftime, TIME_EXT_COMPLETE, TZ_EXT -from isodate.isoerror import ISO8601Error -from isodate.isotzinfo import TZ_REGEX, build_tzinfo - -TIME_REGEX_CACHE = [] -# used to cache regular expressions to parse ISO time strings. - - -def build_time_regexps(): - ''' - Build regular expressions to parse ISO time string. - - The regular expressions are compiled and stored in TIME_REGEX_CACHE - for later reuse. - ''' - if not TIME_REGEX_CACHE: - # ISO 8601 time representations allow decimal fractions on least - # significant time component. Command and Full Stop are both valid - # fraction separators. - # The letter 'T' is allowed as time designator in front of a time - # expression. - # Immediately after a time expression, a time zone definition is - # allowed. - # a TZ may be missing (local time), be a 'Z' for UTC or a string of - # +-hh:mm where the ':mm' part can be skipped. - # TZ information patterns: - # '' - # Z - # +-hh:mm - # +-hhmm - # +-hh => - # isotzinfo.TZ_REGEX - # 1. complete time: - # hh:mm:ss.ss ... extended format - TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}):" - r"(?P<minute>[0-9]{2}):" - r"(?P<second>[0-9]{2}([,.][0-9]+)?)" - + TZ_REGEX)) - # hhmmss.ss ... basic format - TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2})" - r"(?P<minute>[0-9]{2})" - r"(?P<second>[0-9]{2}([,.][0-9]+)?)" - + TZ_REGEX)) - # 2. reduced accuracy: - # hh:mm.mm ... extended format - TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}):" - r"(?P<minute>[0-9]{2}([,.][0-9]+)?)" - + TZ_REGEX)) - # hhmm.mm ... basic format - TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2})" - r"(?P<minute>[0-9]{2}([,.][0-9]+)?)" - + TZ_REGEX)) - # hh.hh ... basic format - TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}([,.][0-9]+)?)" - + TZ_REGEX)) - return TIME_REGEX_CACHE - - -def parse_time(timestring): - ''' - Parses ISO 8601 times into datetime.time objects. - - Following ISO 8601 formats are supported: - (as decimal separator a ',' or a '.' is allowed) - hhmmss.ssTZD basic complete time - hh:mm:ss.ssTZD extended compelte time - hhmm.mmTZD basic reduced accuracy time - hh:mm.mmTZD extended reduced accuracy time - hh.hhTZD basic reduced accuracy time - TZD is the time zone designator which can be in the following format: - no designator indicates local time zone - Z UTC - +-hhmm basic hours and minutes - +-hh:mm extended hours and minutes - +-hh hours - ''' - isotimes = build_time_regexps() - for pattern in isotimes: - match = pattern.match(timestring) - if match: - groups = match.groupdict() - for key, value in groups.items(): - if value is not None: - groups[key] = value.replace(',', '.') - tzinfo = build_tzinfo(groups['tzname'], groups['tzsign'], - int(groups['tzhour'] or 0), - int(groups['tzmin'] or 0)) - if 'second' in groups: - # round to microseconds if fractional seconds are more precise - second = Decimal(groups['second']).quantize(Decimal('.000001')) - microsecond = (second - int(second)) * long(1e6) - # int(...) ... no rounding - # to_integral() ... rounding - return time(int(groups['hour']), int(groups['minute']), - int(second), int(microsecond.to_integral()), tzinfo) - if 'minute' in groups: - minute = Decimal(groups['minute']) - second = (minute - int(minute)) * 60 - microsecond = (second - int(second)) * long(1e6) - return time(int(groups['hour']), int(minute), int(second), - int(microsecond.to_integral()), tzinfo) - else: - microsecond, second, minute = 0, 0, 0 - hour = Decimal(groups['hour']) - minute = (hour - int(hour)) * 60 - second = (minute - int(minute)) * 60 - microsecond = (second - int(second)) * long(1e6) - return time(int(hour), int(minute), int(second), - int(microsecond.to_integral()), tzinfo) - raise ISO8601Error('Unrecognised ISO 8601 time format: %r' % timestring) - - -def time_isoformat(ttime, format=TIME_EXT_COMPLETE + TZ_EXT): - ''' - Format time strings. - - This method is just a wrapper around isodate.isostrf.strftime and uses - Time-Extended-Complete with extended time zone as default format. - ''' - return strftime(ttime, format) diff --git a/awx/lib/site-packages/isodate/isotzinfo.py b/awx/lib/site-packages/isodate/isotzinfo.py deleted file mode 100644 index 97dbe8cace..0000000000 --- a/awx/lib/site-packages/isodate/isotzinfo.py +++ /dev/null @@ -1,109 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -This module provides an ISO 8601:2004 time zone info parser. - -It offers a function to parse the time zone offset as specified by ISO 8601. -''' -import re - -from isodate.isoerror import ISO8601Error -from isodate.tzinfo import UTC, FixedOffset, ZERO - -TZ_REGEX = r"(?P<tzname>(Z|(?P<tzsign>[+-])"\ - r"(?P<tzhour>[0-9]{2})(:(?P<tzmin>[0-9]{2}))?)?)" - -TZ_RE = re.compile(TZ_REGEX) - -def build_tzinfo(tzname, tzsign='+', tzhour=0, tzmin=0): - ''' - create a tzinfo instance according to given parameters. - - tzname: - 'Z' ... return UTC - '' | None ... return None - other ... return FixedOffset - ''' - if tzname is None or tzname == '': - return None - if tzname == 'Z': - return UTC - tzsign = ((tzsign == '-') and -1) or 1 - return FixedOffset(tzsign * tzhour, tzsign * tzmin, tzname) - -def parse_tzinfo(tzstring): - ''' - Parses ISO 8601 time zone designators to tzinfo objecs. - - A time zone designator can be in the following format: - no designator indicates local time zone - Z UTC - +-hhmm basic hours and minutes - +-hh:mm extended hours and minutes - +-hh hours - ''' - match = TZ_RE.match(tzstring) - if match: - groups = match.groupdict() - return build_tzinfo(groups['tzname'], groups['tzsign'], - int(groups['tzhour'] or 0), - int(groups['tzmin'] or 0)) - raise ISO8601Error('%s not a valid time zone info' % tzstring) - -def tz_isoformat(dt, format='%Z'): - ''' - return time zone offset ISO 8601 formatted. - The various ISO formats can be chosen with the format parameter. - - if tzinfo is None returns '' - if tzinfo is UTC returns 'Z' - else the offset is rendered to the given format. - format: - %h ... +-HH - %z ... +-HHMM - %Z ... +-HH:MM - ''' - tzinfo = dt.tzinfo - if (tzinfo is None) or (tzinfo.utcoffset(dt) is None): - return '' - if tzinfo.utcoffset(dt) == ZERO and tzinfo.dst(dt) == ZERO: - return 'Z' - tdelta = tzinfo.utcoffset(dt) - seconds = tdelta.days * 24 * 60 * 60 + tdelta.seconds - sign = ((seconds < 0) and '-') or '+' - seconds = abs(seconds) - minutes, seconds = divmod(seconds, 60) - hours, minutes = divmod(minutes, 60) - if hours > 99: - raise OverflowError('can not handle differences > 99 hours') - if format == '%Z': - return '%s%02d:%02d' % (sign, hours, minutes) - elif format == '%z': - return '%s%02d%02d' % (sign, hours, minutes) - elif format == '%h': - return '%s%02d' % (sign, hours) - raise ValueError('unknown format string "%s"' % format) diff --git a/awx/lib/site-packages/isodate/tests/__init__.py b/awx/lib/site-packages/isodate/tests/__init__.py deleted file mode 100644 index bc1867df94..0000000000 --- a/awx/lib/site-packages/isodate/tests/__init__.py +++ /dev/null @@ -1,49 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Collect all test suites into one TestSuite instance. -''' - -import unittest -from isodate.tests import (test_date, test_time, test_datetime, test_duration, - test_strf, test_pickle) - -def test_suite(): - ''' - Return a new TestSuite instance consisting of all available TestSuites. - ''' - return unittest.TestSuite([ - test_date.test_suite(), - test_time.test_suite(), - test_datetime.test_suite(), - test_duration.test_suite(), - test_strf.test_suite(), - test_pickle.test_suite(), - ]) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/awx/lib/site-packages/isodate/tests/test_date.py b/awx/lib/site-packages/isodate/tests/test_date.py deleted file mode 100644 index 3a1b4a60f1..0000000000 --- a/awx/lib/site-packages/isodate/tests/test_date.py +++ /dev/null @@ -1,126 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isodate module. -''' -import unittest -from datetime import date -from isodate import parse_date, ISO8601Error, date_isoformat -from isodate import DATE_CENTURY, DATE_YEAR, DATE_MONTH -from isodate import DATE_EXT_COMPLETE, DATE_BAS_COMPLETE -from isodate import DATE_BAS_ORD_COMPLETE, DATE_EXT_ORD_COMPLETE -from isodate import DATE_BAS_WEEK, DATE_BAS_WEEK_COMPLETE -from isodate import DATE_EXT_WEEK, DATE_EXT_WEEK_COMPLETE - -# the following list contains tuples of ISO date strings and the expected -# result from the parse_date method. A result of None means an ISO8601Error -# is expected. The test cases are grouped into dates with 4 digit years -# and 6 digit years. -TEST_CASES = {4: [('19', date(1901, 1, 1), DATE_CENTURY), - ('1985', date(1985, 1, 1), DATE_YEAR), - ('1985-04', date(1985, 4, 1), DATE_MONTH), - ('1985-04-12', date(1985, 4, 12), DATE_EXT_COMPLETE), - ('19850412', date(1985, 4, 12), DATE_BAS_COMPLETE), - ('1985102', date(1985, 4, 12), DATE_BAS_ORD_COMPLETE), - ('1985-102', date(1985, 4, 12), DATE_EXT_ORD_COMPLETE), - ('1985W155', date(1985, 4, 12), DATE_BAS_WEEK_COMPLETE), - ('1985-W15-5', date(1985, 4, 12), DATE_EXT_WEEK_COMPLETE), - ('1985W15', date(1985, 4, 8), DATE_BAS_WEEK), - ('1985-W15', date(1985, 4, 8), DATE_EXT_WEEK), - ('1989-W15', date(1989, 4, 10), DATE_EXT_WEEK), - ('1989-W15-5', date(1989, 4, 14), DATE_EXT_WEEK_COMPLETE), - ('1-W1-1', None, DATE_BAS_WEEK_COMPLETE)], - 6: [('+0019', date(1901, 1, 1), DATE_CENTURY), - ('+001985', date(1985, 1, 1), DATE_YEAR), - ('+001985-04', date(1985, 4, 1), DATE_MONTH), - ('+001985-04-12', date(1985, 4, 12), DATE_EXT_COMPLETE), - ('+0019850412', date(1985, 4, 12), DATE_BAS_COMPLETE), - ('+001985102', date(1985, 4, 12), DATE_BAS_ORD_COMPLETE), - ('+001985-102', date(1985, 4, 12), DATE_EXT_ORD_COMPLETE), - ('+001985W155', date(1985, 4, 12), DATE_BAS_WEEK_COMPLETE), - ('+001985-W15-5', date(1985, 4, 12), DATE_EXT_WEEK_COMPLETE), - ('+001985W15', date(1985, 4, 8), DATE_BAS_WEEK), - ('+001985-W15', date(1985, 4, 8), DATE_EXT_WEEK)]} - -def create_testcase(yeardigits, datestring, expectation, format): - ''' - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - TEST_CASES list, so that a failed test won't stop other tests. - ''' - - class TestDate(unittest.TestCase): - ''' - A test case template to parse an ISO date string into a date - object. - ''' - - def test_parse(self): - ''' - Parse an ISO date string and compare it to the expected value. - ''' - if expectation is None: - self.assertRaises(ISO8601Error, parse_date, datestring, - yeardigits) - else: - result = parse_date(datestring, yeardigits) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take date object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if expectation is None: - self.assertRaises(AttributeError, - date_isoformat, expectation, format, - yeardigits) - else: - self.assertEqual(date_isoformat(expectation, format, - yeardigits), - datestring) - - return unittest.TestLoader().loadTestsFromTestCase(TestDate) - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - for yeardigits, tests in TEST_CASES.items(): - for datestring, expectation, format in tests: - suite.addTest(create_testcase(yeardigits, datestring, - expectation, format)) - return suite - -# load_tests Protocol -def load_tests(loader, tests, pattern): - return test_suite() - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/awx/lib/site-packages/isodate/tests/test_datetime.py b/awx/lib/site-packages/isodate/tests/test_datetime.py deleted file mode 100644 index f6aaa51a67..0000000000 --- a/awx/lib/site-packages/isodate/tests/test_datetime.py +++ /dev/null @@ -1,138 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isodatetime module. -''' -import unittest -from datetime import datetime - -from isodate import parse_datetime, UTC, FixedOffset, datetime_isoformat -from isodate import DATE_BAS_COMPLETE, TIME_BAS_MINUTE, TIME_BAS_COMPLETE -from isodate import DATE_EXT_COMPLETE, TIME_EXT_MINUTE, TIME_EXT_COMPLETE -from isodate import TZ_BAS, TZ_EXT, TZ_HOUR -from isodate import DATE_BAS_ORD_COMPLETE, DATE_EXT_ORD_COMPLETE -from isodate import DATE_BAS_WEEK_COMPLETE, DATE_EXT_WEEK_COMPLETE - -# the following list contains tuples of ISO datetime strings and the expected -# result from the parse_datetime method. A result of None means an ISO8601Error -# is expected. -TEST_CASES = [('19850412T1015', datetime(1985, 4, 12, 10, 15), - DATE_BAS_COMPLETE + 'T' + TIME_BAS_MINUTE, - '19850412T1015'), - ('1985-04-12T10:15', datetime(1985, 4, 12, 10, 15), - DATE_EXT_COMPLETE + 'T' + TIME_EXT_MINUTE, - '1985-04-12T10:15'), - ('1985102T1015Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC), - DATE_BAS_ORD_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS, - '1985102T1015Z'), - ('1985-102T10:15Z', datetime(1985, 4, 12, 10, 15, tzinfo=UTC), - DATE_EXT_ORD_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_EXT, - '1985-102T10:15Z'), - ('1985W155T1015+0400', datetime(1985, 4, 12, 10, 15, - tzinfo=FixedOffset(4, 0, - '+0400')), - DATE_BAS_WEEK_COMPLETE + 'T' + TIME_BAS_MINUTE + TZ_BAS, - '1985W155T1015+0400'), - ('1985-W15-5T10:15+04', datetime(1985, 4, 12, 10, 15, - tzinfo=FixedOffset(4, 0, - '+0400'),), - DATE_EXT_WEEK_COMPLETE + 'T' + TIME_EXT_MINUTE + TZ_HOUR, - '1985-W15-5T10:15+04'), - ('20110410T101225.123000Z', - datetime(2011, 4, 10, 10, 12, 25, 123000, tzinfo=UTC), - DATE_BAS_COMPLETE + 'T' + TIME_BAS_COMPLETE + ".%f" + TZ_BAS, - '20110410T101225.123000Z'), - ('2012-10-12T08:29:46.069178Z', - datetime(2012, 10, 12, 8, 29, 46, 69178, tzinfo=UTC), - DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS, - '2012-10-12T08:29:46.069178Z'), - ('2012-10-12T08:29:46.691780Z', - datetime(2012, 10, 12, 8, 29, 46, 691780, tzinfo=UTC), - DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS, - '2012-10-12T08:29:46.691780Z'), - ('2012-10-30T08:55:22.1234567Z', - datetime(2012, 10, 30, 8, 55, 22, 123457, tzinfo=UTC), - DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS, - '2012-10-30T08:55:22.123457Z'), - ('2012-10-30T08:55:22.1234561Z', - datetime(2012, 10, 30, 8, 55, 22, 123456, tzinfo=UTC), - DATE_EXT_COMPLETE + 'T' + TIME_EXT_COMPLETE + '.%f' + TZ_BAS, - '2012-10-30T08:55:22.123456Z') - ] - - -def create_testcase(datetimestring, expectation, format, output): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestDateTime(unittest.TestCase): - ''' - A test case template to parse an ISO datetime string into a - datetime object. - ''' - - def test_parse(self): - ''' - Parse an ISO datetime string and compare it to the expected value. - ''' - result = parse_datetime(datetimestring) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take datetime object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if expectation is None: - self.assertRaises(AttributeError, - datetime_isoformat, expectation, format) - else: - self.assertEqual(datetime_isoformat(expectation, format), - output) - - return unittest.TestLoader().loadTestsFromTestCase(TestDateTime) - - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - for datetimestring, expectation, format, output in TEST_CASES: - suite.addTest(create_testcase(datetimestring, expectation, format, output)) - return suite - -# load_tests Protocol -def load_tests(loader, tests, pattern): - return test_suite() - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/awx/lib/site-packages/isodate/tests/test_duration.py b/awx/lib/site-packages/isodate/tests/test_duration.py deleted file mode 100644 index e69ae17d24..0000000000 --- a/awx/lib/site-packages/isodate/tests/test_duration.py +++ /dev/null @@ -1,519 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isoduration module. -''' -import unittest -import operator -from datetime import timedelta, date, datetime - -from isodate import Duration, parse_duration, ISO8601Error -from isodate import D_DEFAULT, D_WEEK, D_ALT_EXT, duration_isoformat - -# the following list contains tuples of ISO duration strings and the expected -# result from the parse_duration method. A result of None means an ISO8601Error -# is expected. -PARSE_TEST_CASES = {'P18Y9M4DT11H9M8S': (Duration(4, 8, 0, 0, 9, 11, 0, 9, 18), - D_DEFAULT, None), - 'P2W': (timedelta(weeks=2), D_WEEK, None), - 'P3Y6M4DT12H30M5S': (Duration(4, 5, 0, 0, 30, 12, 0, 6, 3), - D_DEFAULT, None), - 'P23DT23H': (timedelta(hours=23, days=23), - D_DEFAULT, None), - 'P4Y': (Duration(years=4), D_DEFAULT, None), - 'P1M': (Duration(months=1), D_DEFAULT, None), - 'PT1M': (timedelta(minutes=1), D_DEFAULT, None), - 'P0.5Y': (Duration(years=0.5), D_DEFAULT, None), - 'PT36H': (timedelta(hours=36), D_DEFAULT, 'P1DT12H'), - 'P1DT12H': (timedelta(days=1, hours=12), D_DEFAULT, None), - '+P11D': (timedelta(days=11), D_DEFAULT, 'P11D'), - '-P2W': (timedelta(weeks=-2), D_WEEK, None), - '-P2.2W': (timedelta(weeks=-2.2), D_DEFAULT, - '-P15DT9H36M'), - 'P1DT2H3M4S': (timedelta(days=1, hours=2, minutes=3, - seconds=4), D_DEFAULT, None), - 'P1DT2H3M': (timedelta(days=1, hours=2, minutes=3), - D_DEFAULT, None), - 'P1DT2H': (timedelta(days=1, hours=2), D_DEFAULT, None), - 'PT2H': (timedelta(hours=2), D_DEFAULT, None), - 'PT2.3H': (timedelta(hours=2.3), D_DEFAULT, 'PT2H18M'), - 'PT2H3M4S': (timedelta(hours=2, minutes=3, seconds=4), - D_DEFAULT, None), - 'PT3M4S': (timedelta(minutes=3, seconds=4), D_DEFAULT, - None), - 'PT22S': (timedelta(seconds=22), D_DEFAULT, None), - 'PT22.22S': (timedelta(seconds=22.22), 'PT%S.%fS', - 'PT22.220000S'), - '-P2Y': (Duration(years=-2), D_DEFAULT, None), - '-P3Y6M4DT12H30M5S': (Duration(-4, -5, 0, 0, -30, -12, 0, - -6, -3), D_DEFAULT, None), - '-P1DT2H3M4S': (timedelta(days=-1, hours=-2, minutes=-3, - seconds=-4), D_DEFAULT, None), - # alternative format - 'P0018-09-04T11:09:08': (Duration(4, 8, 0, 0, 9, 11, 0, 9, - 18), D_ALT_EXT, None), - #'PT000022.22': timedelta(seconds=22.22), - } - -# d1 d2 '+', '-', '>' -# A list of test cases to test addition and subtraction between datetime and -# Duration objects. -# each tuple contains 2 duration strings, and a result string for addition and -# one for subtraction. The last value says, if the first duration is greater -# than the second. -MATH_TEST_CASES = (('P5Y7M1DT9H45M16.72S', 'PT27M24.68S', - 'P5Y7M1DT10H12M41.4S', 'P5Y7M1DT9H17M52.04S', None), - ('PT28M12.73S', 'PT56M29.92S', - 'PT1H24M42.65S', '-PT28M17.19S', False), - ('P3Y7M23DT5H25M0.33S', 'PT1H1.95S', - 'P3Y7M23DT6H25M2.28S', 'P3Y7M23DT4H24M58.38S', None), - ('PT1H1.95S', 'P3Y7M23DT5H25M0.33S', - 'P3Y7M23DT6H25M2.28S', '-P3Y7M23DT4H24M58.38S', None), - ('P1332DT55M0.33S', 'PT1H1.95S', - 'P1332DT1H55M2.28S', 'P1331DT23H54M58.38S', True), - ('PT1H1.95S', 'P1332DT55M0.33S', - 'P1332DT1H55M2.28S', '-P1331DT23H54M58.38S', False)) - -# A list of test cases to test addition and subtraction of date/datetime -# and Duration objects. They are tested against the results of an -# equal long timedelta duration. -DATE_TEST_CASES = ( (date(2008, 2, 29), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (date(2008, 1, 31), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 2, 29), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 1, 31), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 4, 21), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2008, 5, 5), - timedelta(days=10, hours=12, minutes=20), - Duration(days=10, hours=12, minutes=20)), - (datetime(2000, 1, 1), - timedelta(hours=-33), - Duration(hours=-33)), - (datetime(2008, 5, 5), - Duration(years=1, months=1, days=10, hours=12, - minutes=20), - Duration(months=13, days=10, hours=12, minutes=20)), - (datetime(2000, 3, 30), - Duration(years=1, months=1, days=10, hours=12, - minutes=20), - Duration(months=13, days=10, hours=12, minutes=20)), - ) - -# A list of test cases of additon of date/datetime and Duration. The results -# are compared against a given expected result. -DATE_CALC_TEST_CASES = ( - (date(2000, 2, 1), - Duration(years=1, months=1), - date(2001, 3, 1)), - (date(2000, 2, 29), - Duration(years=1, months=1), - date(2001, 3, 29)), - (date(2000, 2, 29), - Duration(years=1), - date(2001, 2, 28)), - (date(1996, 2, 29), - Duration(years=4), - date(2000, 2, 29)), - (date(2096, 2, 29), - Duration(years=4), - date(2100, 2, 28)), - (date(2000, 2, 1), - Duration(years=-1, months=-1), - date(1999, 1, 1)), - (date(2000, 2, 29), - Duration(years=-1, months=-1), - date(1999, 1, 29)), - (date(2000, 2, 1), - Duration(years=1, months=1, days=1), - date(2001, 3, 2)), - (date(2000, 2, 29), - Duration(years=1, months=1, days=1), - date(2001, 3, 30)), - (date(2000, 2, 29), - Duration(years=1, days=1), - date(2001, 3, 1)), - (date(1996, 2, 29), - Duration(years=4, days=1), - date(2000, 3, 1)), - (date(2096, 2, 29), - Duration(years=4, days=1), - date(2100, 3, 1)), - (date(2000, 2, 1), - Duration(years=-1, months=-1, days=-1), - date(1998, 12, 31)), - (date(2000, 2, 29), - Duration(years=-1, months=-1, days=-1), - date(1999, 1, 28)), - (date(2001, 4, 1), - Duration(years=-1, months=-1, days=-1), - date(2000, 2, 29)), - (date(2000, 4, 1), - Duration(years=-1, months=-1, days=-1), - date(1999, 2, 28)), - (Duration(years=1, months=2), - Duration(years=0, months=0, days=1), - Duration(years=1, months=2, days=1)), - (Duration(years=-1, months=-1, days=-1), - date(2000, 4, 1), - date(1999, 2, 28)), - (Duration(years=1, months=1, weeks=5), - date(2000, 1, 30), - date(2001, 4, 4)), - (parse_duration("P1Y1M5W"), - date(2000, 1, 30), - date(2001, 4, 4)), - (parse_duration("P0.5Y"), - date(2000, 1, 30), - None), - (Duration(years=1, months=1, hours=3), - datetime(2000, 1, 30, 12, 15, 00), - datetime(2001, 2, 28, 15, 15, 00)), - (parse_duration("P1Y1MT3H"), - datetime(2000, 1, 30, 12, 15, 00), - datetime(2001, 2, 28, 15, 15, 00)), - (Duration(years=1, months=2), - timedelta(days=1), - Duration(years=1, months=2, days=1)), - (timedelta(days=1), - Duration(years=1, months=2), - Duration(years=1, months=2, days=1)), - (datetime(2008, 1, 1, 0, 2), - Duration(months=1), - datetime(2008, 2, 1, 0, 2)), - (datetime.strptime("200802", "%Y%M"), - parse_duration("P1M"), - datetime(2008, 2, 1, 0, 2)), - (datetime(2008, 2, 1), - Duration(months=1), - datetime(2008, 3, 1)), - (datetime.strptime("200802", "%Y%m"), - parse_duration("P1M"), - datetime(2008, 3, 1)), - # (date(2000, 1, 1), - # Duration(years=1.5), - # date(2001, 6, 1)), - # (date(2000, 1, 1), - # Duration(years=1, months=1.5), - # date(2001, 2, 14)), - ) - - -class DurationTest(unittest.TestCase): - ''' - This class tests various other aspects of the isoduration module, - which are not covered with the test cases listed above. - ''' - - def test_associative(self): - ''' - Adding 2 durations to a date is not associative. - ''' - days1 = Duration(days=1) - months1 = Duration(months=1) - start = date(2000, 3, 30) - res1 = start + days1 + months1 - res2 = start + months1 + days1 - self.assertNotEqual(res1, res2) - - def test_typeerror(self): - ''' - Test if TypError is raised with certain parameters. - ''' - self.assertRaises(TypeError, parse_duration, date(2000, 1, 1)) - self.assertRaises(TypeError, operator.sub, Duration(years=1), - date(2000, 1, 1)) - self.assertRaises(TypeError, operator.sub, 'raise exc', - Duration(years=1)) - self.assertRaises(TypeError, operator.add, - Duration(years=1, months=1, weeks=5), - 'raise exception') - self.assertRaises(TypeError, operator.add, 'raise exception', - Duration(years=1, months=1, weeks=5)) - - def test_parseerror(self): - ''' - Test for unparseable duration string. - ''' - self.assertRaises(ISO8601Error, parse_duration, 'T10:10:10') - - def test_repr(self): - ''' - Test __repr__ and __str__ for Duration obqects. - ''' - dur = Duration(10, 10, years=10, months=10) - self.assertEqual('10 years, 10 months, 10 days, 0:00:10', str(dur)) - self.assertEqual('isodate.duration.Duration(10, 10, 0,' - ' years=10, months=10)', repr(dur)) - - def test_neg(self): - ''' - Test __neg__ for Duration objects. - ''' - self.assertEqual(-Duration(0), Duration(0)) - self.assertEqual(-Duration(years=1, months=1), - Duration(years=-1, months=-1)) - self.assertEqual(-Duration(years=1, months=1), Duration(months=-13)) - self.assertNotEqual(-Duration(years=1), timedelta(days=-365)) - self.assertNotEqual(-timedelta(days=365), Duration(years=-1)) - # FIXME: this test fails in python 3... it seems like python3 - # treats a == b the same b == a - #self.assertNotEqual(-timedelta(days=10), -Duration(days=10)) - - def test_format(self): - ''' - Test various other strftime combinations. - ''' - self.assertEqual(duration_isoformat(Duration(0)), 'P0D') - self.assertEqual(duration_isoformat(-Duration(0)), 'P0D') - self.assertEqual(duration_isoformat(Duration(seconds=10)), 'PT10S') - self.assertEqual(duration_isoformat(Duration(years=-1, months=-1)), - '-P1Y1M') - self.assertEqual(duration_isoformat(-Duration(years=1, months=1)), - '-P1Y1M') - self.assertEqual(duration_isoformat(-Duration(years=-1, months=-1)), - 'P1Y1M') - self.assertEqual(duration_isoformat(-Duration(years=-1, months=-1)), - 'P1Y1M') - dur = Duration(years=3, months=7, days=23, hours=5, minutes=25, - milliseconds=330) - self.assertEqual(duration_isoformat(dur), 'P3Y7M23DT5H25M0.33S') - self.assertEqual(duration_isoformat(-dur), '-P3Y7M23DT5H25M0.33S') - - def test_equal(self): - ''' - Test __eq__ and __ne__ methods. - ''' - self.assertEqual(Duration(years=1, months=1), - Duration(years=1, months=1)) - self.assertEqual(Duration(years=1, months=1), Duration(months=13)) - self.assertNotEqual(Duration(years=1, months=2), - Duration(years=1, months=1)) - self.assertNotEqual(Duration(years=1, months=1), Duration(months=14)) - self.assertNotEqual(Duration(years=1), timedelta(days=365)) - self.assertFalse(Duration(years=1, months=1) != - Duration(years=1, months=1)) - self.assertFalse(Duration(years=1, months=1) != Duration(months=13)) - self.assertTrue(Duration(years=1, months=2) != - Duration(years=1, months=1)) - self.assertTrue(Duration(years=1, months=1) != Duration(months=14)) - self.assertTrue(Duration(years=1) != timedelta(days=365)) - self.assertEqual(Duration(days=1), timedelta(days=1)) - # FIXME: this test fails in python 3... it seems like python3 - # treats a != b the same b != a - #self.assertNotEqual(timedelta(days=1), Duration(days=1)) - - def test_totimedelta(self): - ''' - Test conversion form Duration to timedelta. - ''' - dur = Duration(years=1, months=2, days=10) - self.assertEqual(dur.totimedelta(datetime(1998, 2, 25)), timedelta(434)) - # leap year has one day more in february - self.assertEqual(dur.totimedelta(datetime(2000, 2, 25)), timedelta(435)) - dur = Duration(months=2) - # march is longer than february, but april is shorter than march (cause only one day difference compared to 2) - self.assertEqual(dur.totimedelta(datetime(2000, 2, 25)), timedelta(60)) - self.assertEqual(dur.totimedelta(datetime(2001, 2, 25)), timedelta(59)) - self.assertEqual(dur.totimedelta(datetime(2001, 3, 25)), timedelta(61)) - - -def create_parsetestcase(durationstring, expectation, format, altstr): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - PARSE_TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestParseDuration(unittest.TestCase): - ''' - A test case template to parse an ISO duration string into a - timedelta or Duration object. - ''' - - def test_parse(self): - ''' - Parse an ISO duration string and compare it to the expected value. - ''' - result = parse_duration(durationstring) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take duration/timedelta object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if altstr: - self.assertEqual(duration_isoformat(expectation, format), - altstr) - else: - # if durationstring == '-P2W': - # import pdb; pdb.set_trace() - self.assertEqual(duration_isoformat(expectation, format), - durationstring) - - return unittest.TestLoader().loadTestsFromTestCase(TestParseDuration) - - -def create_mathtestcase(dur1, dur2, resadd, ressub, resge): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - MATH_TEST_CASES list, so that a failed test won't stop other tests. - """ - - dur1 = parse_duration(dur1) - dur2 = parse_duration(dur2) - resadd = parse_duration(resadd) - ressub = parse_duration(ressub) - - class TestMathDuration(unittest.TestCase): - ''' - A test case template test addition, subtraction and > - operators for Duration objects. - ''' - - def test_add(self): - ''' - Test operator + (__add__, __radd__) - ''' - self.assertEqual(dur1 + dur2, resadd) - - def test_sub(self): - ''' - Test operator - (__sub__, __rsub__) - ''' - self.assertEqual(dur1 - dur2, ressub) - - def test_ge(self): - ''' - Test operator > and < - ''' - def dogetest(): - ''' Test greater than.''' - return dur1 > dur2 - - def doletest(): - ''' Test less than.''' - return dur1 < dur2 - if resge is None: - self.assertRaises(TypeError, dogetest) - self.assertRaises(TypeError, doletest) - else: - self.assertEqual(dogetest(), resge) - self.assertEqual(doletest(), not resge) - - return unittest.TestLoader().loadTestsFromTestCase(TestMathDuration) - - -def create_datetestcase(start, tdelta, duration): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - DATE_TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestDateCalc(unittest.TestCase): - ''' - A test case template test addition, subtraction - operators for Duration objects. - ''' - - def test_add(self): - ''' - Test operator +. - ''' - self.assertEqual(start + tdelta, start + duration) - - def test_sub(self): - ''' - Test operator -. - ''' - self.assertEqual(start - tdelta, start - duration) - - return unittest.TestLoader().loadTestsFromTestCase(TestDateCalc) - - -def create_datecalctestcase(start, duration, expectation): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - DATE_CALC_TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestDateCalc(unittest.TestCase): - ''' - A test case template test addition operators for Duration objects. - ''' - - def test_calc(self): - ''' - Test operator +. - ''' - if expectation is None: - self.assertRaises(ValueError, operator.add, start, duration) - else: - self.assertEqual(start + duration, expectation) - - return unittest.TestLoader().loadTestsFromTestCase(TestDateCalc) - - -def test_suite(): - ''' - Return a test suite containing all test defined above. - ''' - suite = unittest.TestSuite() - for durationstring, (expectation, format, altstr) in PARSE_TEST_CASES.items(): - suite.addTest(create_parsetestcase(durationstring, expectation, - format, altstr)) - for testdata in MATH_TEST_CASES: - suite.addTest(create_mathtestcase(*testdata)) - for testdata in DATE_TEST_CASES: - suite.addTest(create_datetestcase(*testdata)) - for testdata in DATE_CALC_TEST_CASES: - suite.addTest(create_datecalctestcase(*testdata)) - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(DurationTest)) - return suite - -# load_tests Protocol -def load_tests(loader, tests, pattern): - return test_suite() - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/awx/lib/site-packages/isodate/tests/test_pickle.py b/awx/lib/site-packages/isodate/tests/test_pickle.py deleted file mode 100644 index 952c238336..0000000000 --- a/awx/lib/site-packages/isodate/tests/test_pickle.py +++ /dev/null @@ -1,35 +0,0 @@ -import unittest -import cPickle as pickle -import isodate - - -class TestPickle(unittest.TestCase): - ''' - A test case template to parse an ISO datetime string into a - datetime object. - ''' - - def test_pickle(self): - ''' - Parse an ISO datetime string and compare it to the expected value. - ''' - dti = isodate.parse_datetime('2012-10-26T09:33+00:00') - pikl = pickle.dumps(dti, 2) - dto = pickle.loads(pikl) - self.assertEqual(dti, dto) - - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestPickle)) - return suite - -# load_tests Protocol -def load_tests(loader, tests, pattern): - return test_suite() - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/awx/lib/site-packages/isodate/tests/test_strf.py b/awx/lib/site-packages/isodate/tests/test_strf.py deleted file mode 100644 index c7f1c554b7..0000000000 --- a/awx/lib/site-packages/isodate/tests/test_strf.py +++ /dev/null @@ -1,130 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isodate module. -''' -import unittest -import time -from datetime import datetime, timedelta -from isodate import strftime -from isodate import LOCAL -from isodate import DT_EXT_COMPLETE -from isodate import tzinfo - - -TEST_CASES = ((datetime(2012, 12, 25, 13, 30, 0, 0, LOCAL), DT_EXT_COMPLETE, - "2012-12-25T13:30:00+10:00"), - # DST ON - (datetime(1999, 12, 25, 13, 30, 0, 0, LOCAL), DT_EXT_COMPLETE, - "1999-12-25T13:30:00+11:00"), - # microseconds - (datetime(2012, 10, 12, 8, 29, 46, 69178), "%Y-%m-%dT%H:%M:%S.%f", - "2012-10-12T08:29:46.069178"), - (datetime(2012, 10, 12, 8, 29, 46, 691780), "%Y-%m-%dT%H:%M:%S.%f", - "2012-10-12T08:29:46.691780"), - ) - - -def create_testcase(dt, format, expectation): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestDate(unittest.TestCase): - ''' - A test case template to test ISO date formatting. - ''' - - # local time zone mock function - def localtime_mock(self, secs): - """ - mock time.localtime so that it always returns a time_struct with tm_idst=1 - """ - tt = self.ORIG['localtime'](secs) - # befor 2000 everything is dst, after 2000 no dst. - if tt.tm_year < 2000: - dst = 1 - else: - dst = 0 - tt = (tt.tm_year, tt.tm_mon, tt.tm_mday, - tt.tm_hour, tt.tm_min, tt.tm_sec, - tt.tm_wday, tt.tm_yday, dst) - return time.struct_time(tt) - - def setUp(self): - self.ORIG = {} - self.ORIG['STDOFFSET'] = tzinfo.STDOFFSET - self.ORIG['DSTOFFSET'] = tzinfo.DSTOFFSET - self.ORIG['DSTDIFF'] = tzinfo.DSTDIFF - self.ORIG['localtime'] = time.localtime - # ovveride all saved values with fixtures. - # calculate LOCAL TZ offset, so that this test runs in every time zone - tzinfo.STDOFFSET = timedelta(seconds=36000) # assume we are in +10:00 - tzinfo.DSTOFFSET = timedelta(seconds=39600) # assume DST = +11:00 - tzinfo.DSTDIFF = tzinfo.DSTOFFSET - tzinfo.STDOFFSET - time.localtime = self.localtime_mock - - def tearDown(self): - # restore test fixtures - tzinfo.STDOFFSET = self.ORIG['STDOFFSET'] - tzinfo.DSTOFFSET = self.ORIG['DSTOFFSET'] - tzinfo.DSTDIFF = self.ORIG['DSTDIFF'] - time.localtime = self.ORIG['localtime'] - - def test_format(self): - ''' - Take date object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if expectation is None: - self.assertRaises(AttributeError, - strftime(dt, format)) - else: - self.assertEqual(strftime(dt, format), - expectation) - - return unittest.TestLoader().loadTestsFromTestCase(TestDate) - - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - for dt, format, expectation in TEST_CASES: - suite.addTest(create_testcase(dt, format, expectation)) - return suite - -# load_tests Protocol -def load_tests(loader, tests, pattern): - return test_suite() - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/awx/lib/site-packages/isodate/tests/test_time.py b/awx/lib/site-packages/isodate/tests/test_time.py deleted file mode 100644 index cdce704c33..0000000000 --- a/awx/lib/site-packages/isodate/tests/test_time.py +++ /dev/null @@ -1,143 +0,0 @@ -############################################################################## -# Copyright 2009, Gerhard Weis -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of the authors nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT -############################################################################## -''' -Test cases for the isotime module. -''' -import unittest -from datetime import time - -from isodate import parse_time, UTC, FixedOffset, ISO8601Error, time_isoformat -from isodate import TIME_BAS_COMPLETE, TIME_BAS_MINUTE -from isodate import TIME_EXT_COMPLETE, TIME_EXT_MINUTE -from isodate import TIME_HOUR -from isodate import TZ_BAS, TZ_EXT, TZ_HOUR - -# the following list contains tuples of ISO time strings and the expected -# result from the parse_time method. A result of None means an ISO8601Error -# is expected. -TEST_CASES = [('232050', time(23, 20, 50), TIME_BAS_COMPLETE + TZ_BAS), - ('23:20:50', time(23, 20, 50), TIME_EXT_COMPLETE + TZ_EXT), - ('2320', time(23, 20), TIME_BAS_MINUTE), - ('23:20', time(23, 20), TIME_EXT_MINUTE), - ('23', time(23), TIME_HOUR), - ('232050,5', time(23, 20, 50, 500000), None), - ('23:20:50.5', time(23, 20, 50, 500000), None), - # test precision - ('15:33:42.123456', time(15, 33, 42, 123456), None), - ('15:33:42.1234564', time(15, 33, 42, 123456), None), - ('15:33:42.1234557', time(15, 33, 42, 123456), None), - ('2320,8', time(23, 20, 48), None), - ('23:20,8', time(23, 20, 48), None), - ('23,3', time(23, 18), None), - ('232030Z', time(23, 20, 30, tzinfo=UTC), - TIME_BAS_COMPLETE + TZ_BAS), - ('2320Z', time(23, 20, tzinfo=UTC), TIME_BAS_MINUTE + TZ_BAS), - ('23Z', time(23, tzinfo=UTC), TIME_HOUR + TZ_BAS), - ('23:20:30Z', time(23, 20, 30, tzinfo=UTC), - TIME_EXT_COMPLETE + TZ_EXT), - ('23:20Z', time(23, 20, tzinfo=UTC), TIME_EXT_MINUTE + TZ_EXT), - ('152746+0100', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+0100')), - TIME_BAS_COMPLETE + TZ_BAS), - ('152746-0500', time(15, 27, 46, - tzinfo=FixedOffset(-5, 0, '-0500')), - TIME_BAS_COMPLETE + TZ_BAS), - ('152746+01', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+01:00')), - TIME_BAS_COMPLETE + TZ_HOUR), - ('152746-05', time(15, 27, 46, - tzinfo=FixedOffset(-5, -0, '-05:00')), - TIME_BAS_COMPLETE + TZ_HOUR), - ('15:27:46+01:00', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+01:00')), - TIME_EXT_COMPLETE + TZ_EXT), - ('15:27:46-05:00', time(15, 27, 46, - tzinfo=FixedOffset(-5, -0, '-05:00')), - TIME_EXT_COMPLETE + TZ_EXT), - ('15:27:46+01', time(15, 27, 46, - tzinfo=FixedOffset(1, 0, '+01:00')), - TIME_EXT_COMPLETE + TZ_HOUR), - ('15:27:46-05', time(15, 27, 46, - tzinfo=FixedOffset(-5, -0, '-05:00')), - TIME_EXT_COMPLETE + TZ_HOUR), - ('1:17:30', None, TIME_EXT_COMPLETE)] - - -def create_testcase(timestring, expectation, format): - """ - Create a TestCase class for a specific test. - - This allows having a separate TestCase for each test tuple from the - TEST_CASES list, so that a failed test won't stop other tests. - """ - - class TestTime(unittest.TestCase): - ''' - A test case template to parse an ISO time string into a time - object. - ''' - - def test_parse(self): - ''' - Parse an ISO time string and compare it to the expected value. - ''' - if expectation is None: - self.assertRaises(ISO8601Error, parse_time, timestring) - else: - result = parse_time(timestring) - self.assertEqual(result, expectation) - - def test_format(self): - ''' - Take time object and create ISO string from it. - This is the reverse test to test_parse. - ''' - if expectation is None: - self.assertRaises(AttributeError, - time_isoformat, expectation, format) - elif format is not None: - self.assertEqual(time_isoformat(expectation, format), - timestring) - - return unittest.TestLoader().loadTestsFromTestCase(TestTime) - - -def test_suite(): - ''' - Construct a TestSuite instance for all test cases. - ''' - suite = unittest.TestSuite() - for timestring, expectation, format in TEST_CASES: - suite.addTest(create_testcase(timestring, expectation, format)) - return suite - - # load_tests Protocol -def load_tests(loader, tests, pattern): - return test_suite() - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff --git a/awx/lib/site-packages/isodate/tzinfo.py b/awx/lib/site-packages/isodate/tzinfo.py deleted file mode 100644 index 820c88da62..0000000000 --- a/awx/lib/site-packages/isodate/tzinfo.py +++ /dev/null @@ -1,137 +0,0 @@ -''' -This module provides some datetime.tzinfo implementations. - -All those classes are taken from the Python documentation. -''' -from datetime import timedelta, tzinfo -import time - -ZERO = timedelta(0) -# constant for zero time offset. - -class Utc(tzinfo): - '''UTC - - Universal time coordinated time zone. - ''' - - def utcoffset(self, dt): - ''' - Return offset from UTC in minutes east of UTC, which is ZERO for UTC. - ''' - return ZERO - - def tzname(self, dt): - ''' - Return the time zone name corresponding to the datetime object dt, as a string. - ''' - return "UTC" - - def dst(self, dt): - ''' - Return the daylight saving time (DST) adjustment, in minutes east of UTC. - ''' - return ZERO - -UTC = Utc() -# the default instance for UTC. - -class FixedOffset(tzinfo): - ''' - A class building tzinfo objects for fixed-offset time zones. - - Note that FixedOffset(0, 0, "UTC") or FixedOffset() is a different way to - build a UTC tzinfo object. - ''' - - def __init__(self, offset_hours=0, offset_minutes=0, name="UTC"): - ''' - Initialise an instance with time offset and name. - The time offset should be positive for time zones east of UTC - and negate for time zones west of UTC. - ''' - self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) - self.__name = name - - def utcoffset(self, dt): - ''' - Return offset from UTC in minutes of UTC. - ''' - return self.__offset - - def tzname(self, dt): - ''' - Return the time zone name corresponding to the datetime object dt, as a - string. - ''' - return self.__name - - def dst(self, dt): - ''' - Return the daylight saving time (DST) adjustment, in minutes east of - UTC. - ''' - return ZERO - - def __repr__(self): - ''' - Return nicely formatted repr string. - ''' - return "<FixedOffset %r>" % self.__name - - -STDOFFSET = timedelta(seconds = -time.timezone) -# locale time zone offset - -# calculate local daylight saving offset if any. -if time.daylight: - DSTOFFSET = timedelta(seconds = -time.altzone) -else: - DSTOFFSET = STDOFFSET - -DSTDIFF = DSTOFFSET - STDOFFSET -# difference between local time zone and local DST time zone - -class LocalTimezone(tzinfo): - """ - A class capturing the platform's idea of local time. - """ - - def utcoffset(self, dt): - ''' - Return offset from UTC in minutes of UTC. - ''' - if self._isdst(dt): - return DSTOFFSET - else: - return STDOFFSET - - def dst(self, dt): - ''' - Return daylight saving offset. - ''' - if self._isdst(dt): - return DSTDIFF - else: - return ZERO - - def tzname(self, dt): - ''' - Return the time zone name corresponding to the datetime object dt, as a - string. - ''' - return time.tzname[self._isdst(dt)] - - def _isdst(self, dt): - ''' - Returns true if DST is active for given datetime object dt. - ''' - tt = (dt.year, dt.month, dt.day, - dt.hour, dt.minute, dt.second, - dt.weekday(), 0, -1) - stamp = time.mktime(tt) - tt = time.localtime(stamp) - return tt.tm_isdst > 0 - -LOCAL = LocalTimezone() -# the default instance for local time zone. diff --git a/awx/lib/site-packages/jsonfield/VERSION b/awx/lib/site-packages/jsonfield/VERSION deleted file mode 100644 index 583b27acca..0000000000 --- a/awx/lib/site-packages/jsonfield/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.9.12 diff --git a/awx/lib/site-packages/jsonfield/__init__.py b/awx/lib/site-packages/jsonfield/__init__.py deleted file mode 100644 index 0bf34dcac5..0000000000 --- a/awx/lib/site-packages/jsonfield/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -import os -__version__ = open(os.path.join(os.path.dirname(__file__),'VERSION')).read().strip() - -try: - from .fields import JSONField -except ImportError: - pass \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/fields.py b/awx/lib/site-packages/jsonfield/fields.py deleted file mode 100644 index 5c936b7ff7..0000000000 --- a/awx/lib/site-packages/jsonfield/fields.py +++ /dev/null @@ -1,181 +0,0 @@ -from __future__ import unicode_literals -import json - -from django.core.exceptions import ValidationError -from django.conf import settings -from django.db import models, DatabaseError, transaction -from django.utils.translation import ugettext_lazy as _ -from django.utils import six -from django.core.cache import cache - -from decimal import Decimal -import datetime - -from .utils import default -from .widgets import JSONWidget -from .forms import JSONFormField -from jsonfield import __version__ - -DB_TYPE_CACHE_KEY = ( - 'django-jsonfield:db-type:%s' % __version__ + - '%(ENGINE)s:%(HOST)s:%(PORT)s:%(NAME)s' -) - -class JSONField(six.with_metaclass(models.SubfieldBase, models.Field)): - """ - A field that will ensure the data entered into it is valid JSON. - """ - default_error_messages = { - 'invalid': _("'%s' is not a valid JSON string.") - } - description = "JSON object" - - def __init__(self, *args, **kwargs): - if not kwargs.get('null', False): - kwargs['default'] = kwargs.get('default', dict) - self.encoder_kwargs = { - 'indent': kwargs.get('indent', getattr(settings, 'JSONFIELD_INDENT', None)) - } - super(JSONField, self).__init__(*args, **kwargs) - self.validate(self.get_default(), None) - - def formfield(self, **kwargs): - defaults = { - 'form_class': JSONFormField, - 'widget': JSONWidget - } - defaults.update(**kwargs) - return super(JSONField, self).formfield(**defaults) - - def validate(self, value, model_instance): - if not self.null and value is None: - raise ValidationError(self.error_messages['null']) - try: - self.get_prep_value(value) - except: - raise ValidationError(self.error_messages['invalid'] % value) - - def get_default(self): - if self.has_default(): - default = self.default - if callable(default): - default = default() - if isinstance(default, six.string_types): - return json.loads(default) - return json.loads(json.dumps(default)) - return super(JSONField, self).get_default() - - def get_internal_type(self): - return 'TextField' - - def db_type(self, connection): - return 'text' # HACK: Fix for Ansible Tower to avoid generating errors - # in PostgreSQL log. - cache_key = DB_TYPE_CACHE_KEY % connection.settings_dict - db_type = cache.get(cache_key) - - if not db_type: - # Test to see if we support JSON querying. - cursor = connection.cursor() - try: - sid = transaction.savepoint(using=connection.alias) - cursor.execute('SELECT \'{}\'::json = \'{}\'::json;') - except DatabaseError: - transaction.savepoint_rollback(sid, using=connection.alias) - db_type = 'text' - else: - db_type = 'json' - cache.set(cache_key, db_type) - - return db_type - - def to_python(self, value): - if isinstance(value, six.string_types): - if value == "": - if self.null: - return None - if self.blank: - return "" - try: - value = json.loads(value) - except ValueError: - msg = self.error_messages['invalid'] % value - raise ValidationError(msg) - # TODO: Look for date/time/datetime objects within the structure? - return value - - def get_db_prep_value(self, value, connection=None, prepared=None): - return self.get_prep_value(value) - - def get_prep_value(self, value): - if value is None: - if not self.null and self.blank: - return "" - return None - return json.dumps(value, default=default, **self.encoder_kwargs) - - def get_prep_lookup(self, lookup_type, value): - if lookup_type in ["exact", "iexact"]: - return self.to_python(self.get_prep_value(value)) - if lookup_type == "in": - return [self.to_python(self.get_prep_value(v)) for v in value] - if lookup_type == "isnull": - return value - if lookup_type in ["contains", "icontains"]: - if isinstance(value, (list, tuple)): - raise TypeError("Lookup type %r not supported with argument of %s" % ( - lookup_type, type(value).__name__ - )) - # Need a way co combine the values with '%', but don't escape that. - return self.get_prep_value(value)[1:-1].replace(', ', r'%') - if isinstance(value, dict): - return self.get_prep_value(value)[1:-1] - return self.to_python(self.get_prep_value(value)) - raise TypeError('Lookup type %r not supported' % lookup_type) - - def value_to_string(self, obj): - return self._get_val_from_obj(obj) - -class TypedJSONField(JSONField): - """ - - """ - def __init__(self, *args, **kwargs): - self.json_required_fields = kwargs.pop('required_fields', {}) - self.json_validators = kwargs.pop('validators', []) - - super(TypedJSONField, self).__init__(*args, **kwargs) - - def cast_required_fields(self, obj): - if not obj: - return - for field_name, field_type in self.json_required_fields.items(): - obj[field_name] = field_type.to_python(obj[field_name]) - - def to_python(self, value): - value = super(TypedJSONField, self).to_python(value) - - if isinstance(value, list): - for item in value: - self.cast_required_fields(item) - else: - self.cast_required_fields(value) - - return value - - def validate(self, value, model_instance): - super(TypedJSONField, self).validate(value, model_instance) - - for v in self.json_validators: - if isinstance(value, list): - for item in value: - v(item) - else: - v(value) - -try: - from south.modelsinspector import add_introspection_rules - add_introspection_rules([], ['^jsonfield\.fields\.JSONField']) - add_introspection_rules([], ['^jsonfield\.fields\.TypedJSONField']) -except ImportError: - pass \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/forms.py b/awx/lib/site-packages/jsonfield/forms.py deleted file mode 100644 index 60d17fe49b..0000000000 --- a/awx/lib/site-packages/jsonfield/forms.py +++ /dev/null @@ -1,31 +0,0 @@ -import json - -from django import forms -from django.utils import six - -from .widgets import JSONWidget - - -class JSONFormField(forms.CharField): - empty_values = [None, ''] - - def __init__(self, *args, **kwargs): - if 'widget' not in kwargs: - kwargs['widget'] = JSONWidget - super(JSONFormField, self).__init__(*args, **kwargs) - - def to_python(self, value): - if isinstance(value, six.string_types) and value: - try: - return json.loads(value) - except Exception as exc: - raise forms.ValidationError( - 'JSON decode error: %s' % (unicode(exc),) - ) - else: - return value - - def validate(self, value): - # This is required in older django versions. - if value in self.empty_values and self.required: - raise forms.ValidationError(self.error_messages['required'], code='required') \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/models.py b/awx/lib/site-packages/jsonfield/models.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/jsonfield/templatetags/__init__.py b/awx/lib/site-packages/jsonfield/templatetags/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/jsonfield/templatetags/jsonify.py b/awx/lib/site-packages/jsonfield/templatetags/jsonify.py deleted file mode 100644 index da20e980f0..0000000000 --- a/awx/lib/site-packages/jsonfield/templatetags/jsonify.py +++ /dev/null @@ -1,14 +0,0 @@ -import json - -from django import template -from django.utils.safestring import mark_safe -from jsonfield.utils import TZAwareJSONEncoder - -register = template.Library() - -@register.filter -def jsonify(value): - # If we have a queryset, then convert it into a list. - if getattr(value, 'all', False): - value = list(value) - return mark_safe(json.dumps(value, cls=TZAwareJSONEncoder)) diff --git a/awx/lib/site-packages/jsonfield/tests/__init__.py b/awx/lib/site-packages/jsonfield/tests/__init__.py deleted file mode 100644 index d017229a9e..0000000000 --- a/awx/lib/site-packages/jsonfield/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .test_fields import * -from .test_forms import * \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/__init__.py b/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/forms.py b/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/forms.py deleted file mode 100644 index ec546d6965..0000000000 --- a/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/forms.py +++ /dev/null @@ -1,12 +0,0 @@ -from django import forms - -from jsonfield.forms import JSONFormField -from .models import JSONFieldTestModel - -class JSONTestForm(forms.Form): - json_data = JSONFormField() - optional_json_data = JSONFormField(required=False) - -class JSONTestModelForm(forms.ModelForm): - class Meta: - model = JSONFieldTestModel diff --git a/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/models.py b/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/models.py deleted file mode 100644 index f4545e1dff..0000000000 --- a/awx/lib/site-packages/jsonfield/tests/jsonfield_test_app/models.py +++ /dev/null @@ -1,25 +0,0 @@ -from django.db import models -from jsonfield.fields import JSONField - -class JSONFieldTestModel(models.Model): - json = JSONField("test", null=True, blank=True) - class Meta: - app_label = 'jsonfield' - -class JSONFieldWithDefaultTestModel(models.Model): - json = JSONField(default={"sukasuka": "YAAAAAZ"}) - class Meta: - app_label = 'jsonfield' - - -class BlankJSONFieldTestModel(models.Model): - null_json = JSONField(null=True) - blank_json = JSONField(blank=True) - class Meta: - app_label = 'jsonfield' - -class CallableDefaultModel(models.Model): - json = JSONField(default=lambda:{'x':2}) - - class Meta: - app_label = 'jsonfield' \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/tests/test_fields.py b/awx/lib/site-packages/jsonfield/tests/test_fields.py deleted file mode 100644 index 37b521ecbb..0000000000 --- a/awx/lib/site-packages/jsonfield/tests/test_fields.py +++ /dev/null @@ -1,153 +0,0 @@ -#:coding=utf-8: -from django.test import TestCase as DjangoTestCase -from django.utils import unittest -from django.utils.encoding import force_text -from django import forms - -from jsonfield.tests.jsonfield_test_app.models import * -from jsonfield.fields import JSONField - -class JSONFieldTest(DjangoTestCase): - def test_json_field(self): - obj = JSONFieldTestModel(json='''{ - "spam": "eggs" - }''') - self.assertEquals(obj.json, {'spam':'eggs'}) - - def test_json_field_empty(self): - obj = JSONFieldTestModel(json='') - self.assertEquals(obj.json, None) - - def test_json_field_save(self): - JSONFieldTestModel.objects.create( - id=10, - json='''{ - "spam": "eggs" - }''', - ) - obj2 = JSONFieldTestModel.objects.get(id=10) - self.assertEquals(obj2.json, {'spam':'eggs'}) - - def test_json_field_save_empty(self): - JSONFieldTestModel.objects.create(id=10, json='') - obj2 = JSONFieldTestModel.objects.get(id=10) - self.assertEquals(obj2.json, None) - - def test_db_prep_save(self): - field = JSONField("test") - field.set_attributes_from_name("json") - self.assertEquals(None, field.get_db_prep_save(None, connection=None)) - self.assertEquals('{"spam": "eggs"}', field.get_db_prep_save({"spam": "eggs"}, connection=None)) - - def test_formfield(self): - from jsonfield.forms import JSONFormField - from jsonfield.widgets import JSONWidget - field = JSONField("test") - field.set_attributes_from_name("json") - formfield = field.formfield() - self.assertEquals(type(formfield), JSONFormField) - self.assertEquals(type(formfield.widget), JSONWidget) - - def test_formfield_clean_blank(self): - field = JSONField("test") - formfield = field.formfield() - self.assertRaisesMessage(forms.ValidationError, force_text(formfield.error_messages['required']), formfield.clean, value='') - - def test_formfield_clean_none(self): - field = JSONField("test") - formfield = field.formfield() - self.assertRaisesMessage(forms.ValidationError, force_text(formfield.error_messages['required']), formfield.clean, value=None) - - def test_formfield_null_and_blank_clean_blank(self): - field = JSONField("test", null=True, blank=True) - formfield = field.formfield() - self.assertEquals(formfield.clean(value=''), '') - - def test_formfield_null_and_blank_clean_none(self): - field = JSONField("test", null=True, blank=True) - formfield = field.formfield() - self.assertEquals(formfield.clean(value=None), None) - - def test_formfield_blank_clean_blank(self): - field = JSONField("test", null=False, blank=True) - formfield = field.formfield() - self.assertEquals(formfield.clean(value=''), '') - - def test_formfield_blank_clean_none(self): - # Hmm, I'm not sure how to do this. What happens if we pass a - # None to a field that has null=False? - field = JSONField("test", null=False, blank=True) - formfield = field.formfield() - self.assertEquals(formfield.clean(value=None), None) - - def test_default_value(self): - obj = JSONFieldWithDefaultTestModel.objects.create() - obj = JSONFieldWithDefaultTestModel.objects.get(id=obj.id) - self.assertEquals(obj.json, {'sukasuka': 'YAAAAAZ'}) - - def test_query_object(self): - JSONFieldTestModel.objects.create(json={}) - JSONFieldTestModel.objects.create(json={'foo':'bar'}) - self.assertEquals(2, JSONFieldTestModel.objects.all().count()) - self.assertEquals(1, JSONFieldTestModel.objects.exclude(json={}).count()) - self.assertEquals(1, JSONFieldTestModel.objects.filter(json={}).count()) - self.assertEquals(1, JSONFieldTestModel.objects.filter(json={'foo':'bar'}).count()) - self.assertEquals(1, JSONFieldTestModel.objects.filter(json__contains={'foo':'bar'}).count()) - JSONFieldTestModel.objects.create(json={'foo':'bar', 'baz':'bing'}) - self.assertEquals(2, JSONFieldTestModel.objects.filter(json__contains={'foo':'bar'}).count()) - self.assertEquals(1, JSONFieldTestModel.objects.filter(json__contains={'baz':'bing', 'foo':'bar'}).count()) - self.assertEquals(2, JSONFieldTestModel.objects.filter(json__contains='foo').count()) - # This code needs to be implemented! - self.assertRaises(TypeError, lambda:JSONFieldTestModel.objects.filter(json__contains=['baz', 'foo'])) - - def test_query_isnull(self): - JSONFieldTestModel.objects.create(json=None) - JSONFieldTestModel.objects.create(json={}) - JSONFieldTestModel.objects.create(json={'foo':'bar'}) - - self.assertEquals(1, JSONFieldTestModel.objects.filter(json=None).count()) - self.assertEquals(None, JSONFieldTestModel.objects.get(json=None).json) - - def test_jsonfield_blank(self): - BlankJSONFieldTestModel.objects.create(blank_json='', null_json=None) - obj = BlankJSONFieldTestModel.objects.get() - self.assertEquals(None, obj.null_json) - self.assertEquals("", obj.blank_json) - obj.save() - obj = BlankJSONFieldTestModel.objects.get() - self.assertEquals(None, obj.null_json) - self.assertEquals("", obj.blank_json) - - def test_callable_default(self): - CallableDefaultModel.objects.create() - obj = CallableDefaultModel.objects.get() - self.assertEquals({'x':2}, obj.json) - - def test_callable_default_overridden(self): - CallableDefaultModel.objects.create(json={'x':3}) - obj = CallableDefaultModel.objects.get() - self.assertEquals({'x':3}, obj.json) - - def test_mutable_default_checking(self): - obj1 = JSONFieldWithDefaultTestModel() - obj2 = JSONFieldWithDefaultTestModel() - - obj1.json['foo'] = 'bar' - self.assertNotIn('foo', obj2.json) - - def test_invalid_json(self): - obj = JSONFieldTestModel() - obj.json = '{"foo": 2}' - self.assertIn('foo', obj.json) - with self.assertRaises(forms.ValidationError): - obj.json = '{"foo"}' - - def test_invalid_json_default(self): - with self.assertRaises(ValueError): - field = JSONField('test', default='{"foo"}') - -class SavingModelsTest(DjangoTestCase): - def test_saving_null(self): - obj = BlankJSONFieldTestModel.objects.create(blank_json='', null_json=None) - self.assertEquals('', obj.blank_json) - self.assertEquals(None, obj.null_json) \ No newline at end of file diff --git a/awx/lib/site-packages/jsonfield/tests/test_forms.py b/awx/lib/site-packages/jsonfield/tests/test_forms.py deleted file mode 100644 index 3e7d53b40b..0000000000 --- a/awx/lib/site-packages/jsonfield/tests/test_forms.py +++ /dev/null @@ -1,56 +0,0 @@ -from django.test import TestCase as DjangoTestCase -from django.utils import unittest -from django.forms import ValidationError - -from jsonfield.forms import JSONFormField -from jsonfield.tests.jsonfield_test_app.forms import JSONTestForm, JSONTestModelForm - -class JSONFormFieldTest(DjangoTestCase): - def test_form_field_clean_empty_object(self): - field = JSONFormField(required=False) - self.assertEquals({}, field.clean('{}')) - - def test_form_field_clean_object(self): - field = JSONFormField(required=False) - self.assertEquals( - {'foo':'bar', 'baz':2}, - field.clean('{"foo":"bar","baz":2}') - ) - - def test_form_field_clean_empty_array(self): - field = JSONFormField(required=False) - self.assertEquals([],field.clean('[]')) - - def test_required_form_field_array(self): - field = JSONFormField(required=True) - self.assertEquals([], field.clean('[]')) - - def test_required_form_field_object(self): - field = JSONFormField(required=True) - self.assertEquals({}, field.clean('{}')) - - def test_required_form_field_empty(self): - field = JSONFormField(required=True) - with self.assertRaises(ValidationError): - field.clean('') - - def test_invalid_json(self): - field = JSONFormField(required=True) - - with self.assertRaises(ValidationError): - field.clean('{"foo"}') - -class JSONFormTest(DjangoTestCase): - def test_form_clean(self): - form = JSONTestForm({}) - self.assertFalse(form.is_valid()) - - -class JSONFormMultipleSelectFieldTest(DjangoTestCase): - def test_multiple_select_data(self): - form = JSONTestForm({'json_data': [u'SA', u'WA']}) - assert form.is_valid() - - self.assertEquals([u'SA', u'WA'], form.cleaned_data['json_data']) - - diff --git a/awx/lib/site-packages/jsonfield/utils.py b/awx/lib/site-packages/jsonfield/utils.py deleted file mode 100644 index 3ffca827e3..0000000000 --- a/awx/lib/site-packages/jsonfield/utils.py +++ /dev/null @@ -1,28 +0,0 @@ -import datetime -from decimal import Decimal - -from django.core.serializers.json import DjangoJSONEncoder - -class TZAwareJSONEncoder(DjangoJSONEncoder): - def default(self, obj): - if isinstance(obj, datetime.datetime): - return obj.strftime("%Y-%m-%d %H:%M:%S%z") - return super(TZAwareJSONEncoder, self).default(obj) - -def default(o): - if hasattr(o, 'to_json'): - return o.to_json() - if isinstance(o, Decimal): - return str(o) - if isinstance(o, datetime.datetime): - if o.tzinfo: - return o.strftime('%Y-%m-%dT%H:%M:%S%z') - return o.strftime("%Y-%m-%dT%H:%M:%S") - if isinstance(o, datetime.date): - return o.strftime("%Y-%m-%d") - if isinstance(o, datetime.time): - if o.tzinfo: - return o.strftime('%H:%M:%S%z') - return o.strftime("%H:%M:%S") - - raise TypeError(repr(o) + " is not JSON serializable") diff --git a/awx/lib/site-packages/jsonfield/widgets.py b/awx/lib/site-packages/jsonfield/widgets.py deleted file mode 100644 index 52d6116632..0000000000 --- a/awx/lib/site-packages/jsonfield/widgets.py +++ /dev/null @@ -1,18 +0,0 @@ -import json - -from django import forms -from django.conf import settings - -from .utils import default - -class JSONWidget(forms.Textarea): - def render(self, name, value, attrs=None): - if value is None: - value = "" - if not isinstance(value, basestring): - value = json.dumps(value, indent=2, default=default) - return super(JSONWidget, self).render(name, value, attrs) - - -class JSONSelectWidget(forms.SelectMultiple): - pass diff --git a/awx/lib/site-packages/keyring/__init__.py b/awx/lib/site-packages/keyring/__init__.py deleted file mode 100644 index bbf968f649..0000000000 --- a/awx/lib/site-packages/keyring/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -""" -__init__.py - -Created by Kang Zhang on 2009-07-09 -""" - -from __future__ import absolute_import - -import logging -logger = logging.getLogger('keyring') - -from .core import (set_keyring, get_keyring, set_password, get_password, - delete_password) -from .getpassbackend import get_password as get_pass_get_password diff --git a/awx/lib/site-packages/keyring/backend.py b/awx/lib/site-packages/keyring/backend.py deleted file mode 100644 index 1161774eae..0000000000 --- a/awx/lib/site-packages/keyring/backend.py +++ /dev/null @@ -1,191 +0,0 @@ -""" -Keyring implementation support -""" - -from __future__ import absolute_import - -import abc -import logging - -try: - import importlib -except ImportError: - pass - -try: - import pkg_resources -except ImportError: - pass - -from . import errors, util -from . import backends -from .util import properties -from .py27compat import add_metaclass, filter - - -log = logging.getLogger(__name__) - - -class KeyringBackendMeta(abc.ABCMeta): - """ - A metaclass that's both an ABCMeta and a type that keeps a registry of - all (non-abstract) types. - """ - def __init__(cls, name, bases, dict): - super(KeyringBackendMeta, cls).__init__(name, bases, dict) - if not hasattr(cls, '_classes'): - cls._classes = set() - classes = cls._classes - if not cls.__abstractmethods__: - classes.add(cls) - - -@add_metaclass(KeyringBackendMeta) -class KeyringBackend(object): - """The abstract base class of the keyring, every backend must implement - this interface. - """ - - #@abc.abstractproperty - def priority(cls): - """ - Each backend class must supply a priority, a number (float or integer) - indicating the priority of the backend relative to all other backends. - The priority need not be static -- it may (and should) vary based - attributes of the environment in which is runs (platform, available - packages, etc.). - - A higher number indicates a higher priority. The priority should raise - a RuntimeError with a message indicating the underlying cause if the - backend is not suitable for the current environment. - - As a rule of thumb, a priority between zero but less than one is - suitable, but a priority of one or greater is recommended. - """ - - @properties.ClassProperty - @classmethod - def viable(cls): - with errors.ExceptionRaisedContext() as exc: - cls.priority - return not bool(exc) - - @abc.abstractmethod - def get_password(self, service, username): - """Get password of the username for the service - """ - return None - - @abc.abstractmethod - def set_password(self, service, username, password): - """Set password for the username of the service - """ - raise errors.PasswordSetError("reason") - - # for backward-compatibility, don't require a backend to implement - # delete_password - #@abc.abstractmethod - def delete_password(self, service, username): - """Delete the password for the username of the service. - """ - raise errors.PasswordDeleteError("reason") - -class Crypter(object): - """Base class providing encryption and decryption - """ - - @abc.abstractmethod - def encrypt(self, value): - """Encrypt the value. - """ - pass - - @abc.abstractmethod - def decrypt(self, value): - """Decrypt the value. - """ - pass - -class NullCrypter(Crypter): - """A crypter that does nothing - """ - - def encrypt(self, value): - return value - - def decrypt(self, value): - return value - - -def _load_backend(name): - "Load a backend by name" - if 'importlib' in globals(): - package = backends.__package__ or backends.__name__ - mod = importlib.import_module('.'+name, package) - else: - # Python 2.6 support - ns = {} - exec("from .backends import {name} as mod".format(name=name), - globals(), ns) - mod = ns['mod'] - # invoke __name__ on each module to ensure it's loaded in demand-import - # environments - mod.__name__ - -def _load_backends(): - "ensure that all keyring backends are loaded" - backends = ('file', 'Gnome', 'Google', 'keyczar', 'kwallet', 'multi', - 'OS_X', 'pyfs', 'SecretService', 'Windows') - list(map(_load_backend, backends)) - _load_plugins() - -def _load_plugins(): - """ - Locate all setuptools entry points by the name 'keyring backends' - and initialize them. - Any third-party library may register an entry point by adding the - following to their setup.py:: - - entry_points = { - 'keyring backends': [ - 'plugin_name = mylib.mymodule:initialize_func', - ], - }, - - `plugin_name` can be anything, and is only used to display the name - of the plugin at initialization time. - - `initialize_func` is optional, but will be invoked if callable. - """ - if 'pkg_resources' not in globals(): - return - group = 'keyring backends' - entry_points = pkg_resources.iter_entry_points(group=group) - for ep in entry_points: - try: - log.info('Loading %s', ep.name) - init_func = ep.load() - if callable(init_func): - init_func() - except Exception: - log.exception("Error initializing plugin %s." % ep) - -@util.once -def get_all_keyring(): - """ - Return a list of all implemented keyrings that can be constructed without - parameters. - """ - _load_backends() - - def is_class_viable(keyring_cls): - try: - keyring_cls.priority - except RuntimeError: - return False - return True - - all_classes = KeyringBackend._classes - viable_classes = filter(is_class_viable, all_classes) - return list(util.suppress_exceptions(viable_classes, - exceptions=TypeError)) diff --git a/awx/lib/site-packages/keyring/backends/Gnome.py b/awx/lib/site-packages/keyring/backends/Gnome.py deleted file mode 100644 index 7cce2454f8..0000000000 --- a/awx/lib/site-packages/keyring/backends/Gnome.py +++ /dev/null @@ -1,116 +0,0 @@ -import os - -try: - from gi import Repository - if Repository.get_default().enumerate_versions('GnomeKeyring'): - from gi.repository import GnomeKeyring -except ImportError: - pass - -from ..backend import KeyringBackend -from ..errors import PasswordSetError, PasswordDeleteError -from ..util import properties -from ..util import XDG -from ..py27compat import unicode_str - -class Keyring(KeyringBackend): - """Gnome Keyring""" - - # Name of the keyring to store the passwords in. - # Use None for the default keyring. - KEYRING_NAME = None - - requisite_vars = [ - 'DISPLAY', - 'DBUS_SESSION_BUS_ADDRESS', - ] - - @properties.ClassProperty - @classmethod - @XDG.Preference('Gnome') - def priority(cls): - if 'GnomeKeyring' not in globals(): - raise RuntimeError("GnomeKeyring module required") - if not cls.has_requisite_vars(): - raise RuntimeError("Requisite environment vars are not present") - return int(cls.has_requisite_vars()) - - @classmethod - def has_requisite_vars(cls): - """ - Return True if the requisite environment vars are present in the - environment. - """ - return set(cls.requisite_vars).issubset(os.environ) - - def _find_passwords(self, service, username, deleting=False): - """Get password of the username for the service - """ - passwords = [] - - service = self._safe_string(service) - username = self._safe_string(username) - for attrs_tuple in (('username', 'service'), ('user', 'domain')): - attrs = GnomeKeyring.Attribute.list_new() - GnomeKeyring.Attribute.list_append_string(attrs, attrs_tuple[0], username) - GnomeKeyring.Attribute.list_append_string(attrs, attrs_tuple[1], service) - result, items = GnomeKeyring.find_items_sync( - GnomeKeyring.ItemType.NETWORK_PASSWORD, attrs) - if result == GnomeKeyring.Result.OK: - passwords += items - elif deleting: - if result == GnomeKeyring.Result.CANCELLED: - raise PasswordDeleteError("Cancelled by user") - elif result != GnomeKeyring.Result.NO_MATCH: - raise PasswordDeleteError(result.value_name) - return passwords - - def get_password(self, service, username): - """Get password of the username for the service - """ - items = self._find_passwords(service, username) - if not items: - return None - - secret = items[0].secret - return secret if isinstance(secret, unicode_str) else secret.decode('utf-8') - - def set_password(self, service, username, password): - """Set password for the username of the service - """ - service = self._safe_string(service) - username = self._safe_string(username) - password = self._safe_string(password) - attrs = GnomeKeyring.Attribute.list_new() - GnomeKeyring.Attribute.list_append_string(attrs, 'username', username) - GnomeKeyring.Attribute.list_append_string(attrs, 'service', service) - GnomeKeyring.Attribute.list_append_string(attrs, 'application', 'python-keyring') - result = GnomeKeyring.item_create_sync( - self.KEYRING_NAME, GnomeKeyring.ItemType.NETWORK_PASSWORD, - "Password for '%s' on '%s'" % (username, service), - attrs, password, True)[0] - if result == GnomeKeyring.Result.CANCELLED: - # The user pressed "Cancel" when prompted to unlock their keyring. - raise PasswordSetError("Cancelled by user") - elif result != GnomeKeyring.Result.OK: - raise PasswordSetError(result.value_name) - - def delete_password(self, service, username): - """Delete the password for the username of the service. - """ - items = self._find_passwords(service, username, deleting=True) - if not items: - raise PasswordDeleteError("Password not found") - for current in items: - result = GnomeKeyring.item_delete_sync(current.keyring, - current.item_id) - if result == GnomeKeyring.Result.CANCELLED: - raise PasswordDeleteError("Cancelled by user") - elif result != GnomeKeyring.Result.OK: - raise PasswordDeleteError(result.value_name) - - def _safe_string(self, source, encoding='utf-8'): - """Convert unicode to string as gnomekeyring barfs on unicode""" - if not isinstance(source, str): - return source.encode(encoding) - return str(source) diff --git a/awx/lib/site-packages/keyring/backends/Google.py b/awx/lib/site-packages/keyring/backends/Google.py deleted file mode 100644 index 48fd478942..0000000000 --- a/awx/lib/site-packages/keyring/backends/Google.py +++ /dev/null @@ -1,321 +0,0 @@ -from __future__ import absolute_import - -import os -import sys -import copy -import codecs -import base64 -import io - -try: - import gdata.docs.service -except ImportError: - pass - -from . import keyczar -from .. import errors -from .. import credentials -from ..py27compat import input, pickle -from ..backend import KeyringBackend -from ..util import properties -from ..errors import ExceptionRaisedContext - -class EnvironCredential(credentials.EnvironCredential): - """Retrieve credentials from specifically named environment variables - """ - - def __init__(self): - super(EnvironCredential, self).__init__('GOOGLE_KEYRING_USER', - 'GOOGLE_KEYRING_PASSWORD') - -class DocsKeyring(KeyringBackend): - """Backend that stores keyring on Google Docs. - Note that login and any other initialisation is deferred until it is - actually required to allow this keyring class to be added to the - global _all_keyring list. - """ - - keyring_title = 'GoogleKeyring' - # status enums - OK = 1 - FAIL = 0 - CONFLICT = -1 - - def __init__(self, credential, source, crypter, - collection=None, client=None, - can_create=True, input_getter=input - ): - self.credential = credential - self.crypter = crypter - self.source = source - self._collection = collection - self.can_create = can_create - self.input_getter = input_getter - self._keyring_dict = None - - if not client: - self._client = gdata.docs.service.DocsService() - else: - self._client = client - - self._client.source = source - self._client.ssl = True - self._login_reqd = True - - @properties.ClassProperty - @classmethod - def priority(cls): - if not cls._has_gdata(): - raise RuntimeError("Requires gdata") - if not keyczar.has_keyczar(): - raise RuntimeError("Requires keyczar") - return 3 - - @classmethod - def _has_gdata(cls): - with ExceptionRaisedContext() as exc: - gdata.__name__ - return not bool(exc) - - def get_password(self, service, username): - """Get password of the username for the service - """ - result = self._get_entry(self._keyring, service, username) - if result: - result = self._decrypt(result) - return result - - def set_password(self, service, username, password): - """Set password for the username of the service - """ - password = self._encrypt(password or '') - keyring_working_copy = copy.deepcopy(self._keyring) - service_entries = keyring_working_copy.get(service) - if not service_entries: - service_entries = {} - keyring_working_copy[service] = service_entries - service_entries[username] = password - save_result = self._save_keyring(keyring_working_copy) - if save_result == self.OK: - self._keyring_dict = keyring_working_copy - return - elif save_result == self.CONFLICT: - # check if we can avoid updating - self.docs_entry, keyring_dict = self._read() - existing_pwd = self._get_entry(self._keyring, service, username) - conflicting_pwd = self._get_entry(keyring_dict, service, username) - if conflicting_pwd == password: - # if someone else updated it to the same value then we are done - self._keyring_dict = keyring_working_copy - return - elif conflicting_pwd is None or conflicting_pwd == existing_pwd: - # if doesn't already exist or is unchanged then update it - new_service_entries = keyring_dict.get(service, {}) - new_service_entries[username] = password - keyring_dict[service] = new_service_entries - save_result = self._save_keyring(keyring_dict) - if save_result == self.OK: - self._keyring_dict = keyring_dict - return - else: - raise errors.PasswordSetError( - 'Failed write after conflict detected') - else: - raise errors.PasswordSetError( - 'Conflict detected, service:%s and username:%s was '\ - 'set to a different value by someone else' %(service, - username)) - - raise errors.PasswordSetError('Could not save keyring') - - def delete_password(self, service, username): - return self._del_entry(self._keyring, service, username) - - @property - def client(self): - if not self._client.GetClientLoginToken(): - try: - self._client.ClientLogin(self.credential.username, - self.credential.password, - self._client.source) - except gdata.service.CaptchaRequired: - sys.stdout.write('Please visit ' + self._client.captcha_url) - answer = self.input_getter('Answer to the challenge? ') - self._client.email = self.credential.username - self._client.password = self.credential.password - self._client.ClientLogin( - self.credential.username, - self.credential.password, - self._client.source, - captcha_token=self._client.captcha_token, - captcha_response=answer) - except gdata.service.BadAuthentication: - raise errors.InitError('Users credential were unrecognized') - except gdata.service.Error: - raise errors.InitError('Login Error') - - return self._client - - @property - def collection(self): - return self._collection or self.credential.username.split('@')[0] - - @property - def _keyring(self): - if self._keyring_dict is None: - self.docs_entry, self._keyring_dict = self._read() - return self._keyring_dict - - def _get_entry(self, keyring_dict, service, username): - result = None - service_entries = keyring_dict.get(service) - if service_entries: - result = service_entries.get(username) - return result - - def _del_entry(self, keyring_dict, service, username): - service_entries = keyring_dict.get(service) - if not service_entries: - raise errors.PasswordDeleteError("No matching service") - try: - del service_entries[username] - except KeyError: - raise errors.PasswordDeleteError("Not found") - if not service_entries: - del keyring_dict[service] - - def _decrypt(self, value): - if not value: - return '' - return self.crypter.decrypt(value) - - def _encrypt(self, value): - if not value: - return '' - return self.crypter.encrypt(value) - - def _get_doc_title(self): - return '%s' %self.keyring_title - - def _read(self): - from gdata.docs.service import DocumentQuery - title_query = DocumentQuery(categories=[self.collection]) - title_query['title'] = self._get_doc_title() - title_query['title-exact'] = 'true' - docs = self.client.QueryDocumentListFeed(title_query.ToUri()) - - if not docs.entry: - if self.can_create: - docs_entry = None - keyring_dict = {} - else: - raise errors.InitError( - '%s not found in %s and create not permitted' - %(self._get_doc_title(), self.collection)) - else: - docs_entry = docs.entry[0] - file_contents = '' - try: - url = docs_entry.content.src - url += '&exportFormat=txt' - server_response = self.client.request('GET', url) - if server_response.status != 200: - raise errors.InitError( - 'Could not read existing Google Docs keyring') - file_contents = server_response.read() - if file_contents.startswith(codecs.BOM_UTF8): - file_contents = file_contents[len(codecs.BOM_UTF8):] - keyring_dict = pickle.loads(base64.urlsafe_b64decode( - file_contents.decode('string-escape'))) - except pickle.UnpicklingError as ex: - raise errors.InitError( - 'Could not unpickle existing Google Docs keyring', ex) - except TypeError as ex: - raise errors.InitError( - 'Could not decode existing Google Docs keyring', ex) - - return docs_entry, keyring_dict - - def _save_keyring(self, keyring_dict): - """Helper to actually write the keyring to Google""" - import gdata - result = self.OK - file_contents = base64.urlsafe_b64encode(pickle.dumps(keyring_dict)) - try: - if self.docs_entry: - extra_headers = {'Content-Type': 'text/plain', - 'Content-Length': len(file_contents)} - self.docs_entry = self.client.Put( - file_contents, - self.docs_entry.GetEditMediaLink().href, - extra_headers=extra_headers - ) - else: - from gdata.docs.service import DocumentQuery - # check for existence of folder, create if required - folder_query = DocumentQuery(categories=['folder']) - folder_query['title'] = self.collection - folder_query['title-exact'] = 'true' - docs = self.client.QueryDocumentListFeed(folder_query.ToUri()) - if docs.entry: - folder_entry = docs.entry[0] - else: - folder_entry = self.client.CreateFolder(self.collection) - file_handle = io.BytesIO(file_contents) - media_source = gdata.MediaSource( - file_handle=file_handle, - content_type='text/plain', - content_length=len(file_contents), - file_name='temp') - self.docs_entry = self.client.Upload( - media_source, - self._get_doc_title(), - folder_or_uri=folder_entry - ) - except gdata.service.RequestError as ex: - try: - if ex.message['reason'].lower().find('conflict') != -1: - result = self.CONFLICT - else: - # Google docs has a bug when updating a shared document - # using PUT from any account other that the owner. - # It returns an error 400 "Sorry, there was an error saving the file. Please try again" - # *despite* actually updating the document! - # Workaround by re-reading to see if it actually updated - if ex.message['body'].find( - 'Sorry, there was an error saving the file') != -1: - new_docs_entry, new_keyring_dict = self._read() - if new_keyring_dict == keyring_dict: - result = self.OK - else: - result = self.FAIL - else: - result = self.FAIL - except: - result = self.FAIL - - return result - -class KeyczarDocsKeyring(DocsKeyring): - """Google Docs keyring using keyczar initialized from environment - variables - """ - - def __init__(self): - crypter = keyczar.EnvironCrypter() - credential = EnvironCredential() - source = os.environ.get('GOOGLE_KEYRING_SOURCE') - super(KeyczarDocsKeyring, self).__init__( - credential, source, crypter) - - def supported(self): - """Return if this keyring supports current environment: - -1: not applicable - 0: suitable - 1: recommended - """ - try: - from keyczar import keyczar - return super(KeyczarDocsKeyring, self).supported() - except ImportError: - return -1 diff --git a/awx/lib/site-packages/keyring/backends/OS_X.py b/awx/lib/site-packages/keyring/backends/OS_X.py deleted file mode 100644 index 1f8d94084f..0000000000 --- a/awx/lib/site-packages/keyring/backends/OS_X.py +++ /dev/null @@ -1,123 +0,0 @@ -import platform -import subprocess -import re -import binascii - -from ..backend import KeyringBackend -from ..errors import PasswordSetError -from ..errors import PasswordDeleteError -from ..util import properties -from ..py27compat import unicode_str - - -class SecurityCommand(unicode_str): - """ - A string suitable for passing as the 'command' parameter to the - OS X 'security' command. - """ - def __new__(cls, cmd, store='generic'): - cmd = '%(cmd)s-%(store)s-password' % vars() - return super(SecurityCommand, cls).__new__(cls, cmd) - - -class Keyring(KeyringBackend): - """Mac OS X Keychain""" - - # regex for extracting password from security call - password_regex = re.compile("""password:\s*(?:0x(?P<hex>[0-9A-F]+)\s*)?""" - """(?:"(?P<pw>.*)")?""") - store = 'generic' - - @properties.ClassProperty - @classmethod - def priority(cls): - """ - Preferred for all OS X environments. - """ - if platform.system() != 'Darwin': - raise RuntimeError("OS X required") - return 5 - - def set_password(self, service, username, password): - if username is None: - username = '' - set_error = PasswordSetError("Can't store password in keychain") - try: - # set up the call for security. - cmd = [ - 'security', - SecurityCommand('add', self.store), - '-a', username, - '-s', service, - '-w', password, - '-U', - ] - call = subprocess.Popen(cmd, stderr=subprocess.PIPE, - stdout=subprocess.PIPE) - stdoutdata, stderrdata = call.communicate() - code = call.returncode - # check return code. - if code is not 0: - raise set_error - except: - raise set_error - - def get_password(self, service, username): - if username is None: - username = '' - try: - # set up the call to security. - cmd = [ - 'security', - SecurityCommand('find', self.store), - '-g', - '-a', username, - '-s', service, - ] - call = subprocess.Popen(cmd, stderr=subprocess.PIPE, - stdout=subprocess.PIPE) - stdoutdata, stderrdata = call.communicate() - code = call.returncode - if code is not 0: - raise OSError("Can't fetch password from system") - output = stderrdata.decode() - # check for empty password. - if output == 'password: \n': - return '' - # search for special password pattern. - matches = Keyring.password_regex.search(output) - if matches: - group_dict = matches.groupdict() - hex = group_dict.get('hex') - pw = group_dict.get('pw') - if hex: - # it's a weird hex password, decode it. - return unicode_str(binascii.unhexlify(hex), 'utf-8') - else: - # it's a normal password, send it back. - return pw - # nothing was found, it doesn't exist. - except: - pass - - def delete_password(self, service, username): - del_error = PasswordDeleteError("Can't delete password in keychain") - if username is None: - username = '' - try: - cmd = [ - 'security', - SecurityCommand('delete', self.store), - '-a', username, - '-s', service, - ] - # set up the call for security. - call = subprocess.Popen(cmd, stderr=subprocess.PIPE, - stdout=subprocess.PIPE) - stdoutdata, stderrdata = call.communicate() - code = call.returncode - # check return code. - if code is not 0: - raise del_error - except: - raise del_error diff --git a/awx/lib/site-packages/keyring/backends/SecretService.py b/awx/lib/site-packages/keyring/backends/SecretService.py deleted file mode 100644 index 7b77f0c21f..0000000000 --- a/awx/lib/site-packages/keyring/backends/SecretService.py +++ /dev/null @@ -1,79 +0,0 @@ -import logging - -from ..util import properties -from ..util import XDG -from ..backend import KeyringBackend -from ..errors import (InitError, PasswordDeleteError, - ExceptionRaisedContext) - -try: - import secretstorage - import secretstorage.exceptions as exceptions -except ImportError: - pass - -log = logging.getLogger(__name__) - -class Keyring(KeyringBackend): - """Secret Service Keyring""" - - @properties.ClassProperty - @classmethod - @XDG.Preference('Gnome') - def priority(cls): - with ExceptionRaisedContext() as exc: - secretstorage.__name__ - if exc: - raise RuntimeError("SecretStorage required") - if not hasattr(secretstorage, 'get_default_collection'): - raise RuntimeError("SecretStorage 1.0 or newer required") - try: - bus = secretstorage.dbus_init() - list(secretstorage.get_all_collections(bus)) - except exceptions.SecretServiceNotAvailableException as e: - raise RuntimeError( - "Unable to initialize SecretService: %s" % e) - return 5 - - def get_default_collection(self): - bus = secretstorage.dbus_init() - try: - collection = secretstorage.get_default_collection(bus) - except exceptions.SecretStorageException as e: - raise InitError("Failed to create the collection: %s." % e) - if collection.is_locked(): - collection.unlock() - if collection.is_locked(): # User dismissed the prompt - raise InitError("Failed to unlock the collection!") - return collection - - def get_password(self, service, username): - """Get password of the username for the service - """ - collection = self.get_default_collection() - items = collection.search_items( - {"username": username, "service": service}) - for item in items: - return item.get_secret().decode('utf-8') - - def set_password(self, service, username, password): - """Set password for the username of the service - """ - collection = self.get_default_collection() - attributes = { - "application": "python-keyring", - "service": service, - "username": username - } - label = "Password for '%s' on '%s'" % (username, service) - collection.create_item(label, attributes, password, replace=True) - - def delete_password(self, service, username): - """Delete the stored password (only the first one) - """ - collection = self.get_default_collection() - items = collection.search_items( - {"username": username, "service": service}) - for item in items: - return item.delete() - raise PasswordDeleteError("No such password!") diff --git a/awx/lib/site-packages/keyring/backends/Windows.py b/awx/lib/site-packages/keyring/backends/Windows.py deleted file mode 100644 index d2c74ffe90..0000000000 --- a/awx/lib/site-packages/keyring/backends/Windows.py +++ /dev/null @@ -1,287 +0,0 @@ -import sys -import base64 -import platform -import functools - -from ..py27compat import unicode_str -from ..util import escape, properties -from ..backend import KeyringBackend -from ..errors import PasswordDeleteError, ExceptionRaisedContext -from . import file - -try: - # prefer pywin32-ctypes - from win32ctypes import pywintypes - from win32ctypes import win32cred - # force demand import to raise ImportError - win32cred.__name__ -except ImportError: - # fallback to pywin32 - try: - import pywintypes - import win32cred - except ImportError: - pass - -try: - import winreg -except ImportError: - try: - # Python 2 compatibility - import _winreg as winreg - except ImportError: - pass - -try: - from . import _win_crypto -except ImportError: - pass - -def has_pywin32(): - """ - Does this environment have pywin32? - Should return False even when Mercurial's Demand Import allowed import of - win32cred. - """ - with ExceptionRaisedContext() as exc: - win32cred.__name__ - return not bool(exc) - -def has_wincrypto(): - """ - Does this environment have wincrypto? - Should return False even when Mercurial's Demand Import allowed import of - _win_crypto, so accesses an attribute of the module. - """ - with ExceptionRaisedContext() as exc: - _win_crypto.__name__ - return not bool(exc) - -class EncryptedKeyring(file.BaseKeyring): - """ - A File-based keyring secured by Windows Crypto API. - """ - - @properties.ClassProperty - @classmethod - def priority(self): - """ - Preferred over file.EncryptedKeyring but not other, more sophisticated - Windows backends. - """ - if not platform.system() == 'Windows': - raise RuntimeError("Requires Windows") - return .8 - - filename = 'wincrypto_pass.cfg' - - def encrypt(self, password): - """Encrypt the password using the CryptAPI. - """ - return _win_crypto.encrypt(password) - - def decrypt(self, password_encrypted): - """Decrypt the password using the CryptAPI. - """ - return _win_crypto.decrypt(password_encrypted) - - -class WinVaultKeyring(KeyringBackend): - """ - WinVaultKeyring stores encrypted passwords using the Windows Credential - Manager. - - Requires pywin32 - - This backend does some gymnastics to simulate multi-user support, - which WinVault doesn't support natively. See - https://bitbucket.org/kang/python-keyring-lib/issue/47/winvaultkeyring-only-ever-returns-last#comment-731977 - for details on the implementation, but here's the gist: - - Passwords are stored under the service name unless there is a collision - (another password with the same service name but different user name), - in which case the previous password is moved into a compound name: - {username}@{service} - """ - - @properties.ClassProperty - @classmethod - def priority(cls): - """ - If available, the preferred backend on Windows. - """ - if not has_pywin32(): - raise RuntimeError("Requires Windows and pywin32") - return 5 - - @staticmethod - def _compound_name(username, service): - return escape.u('%(username)s@%(service)s') % vars() - - def get_password(self, service, username): - # first attempt to get the password under the service name - res = self._get_password(service) - if not res or res['UserName'] != username: - # It wasn't found so attempt to get it with the compound name - res = self._get_password(self._compound_name(username, service)) - if not res: - return None - blob = res['CredentialBlob'] - return blob.decode('utf-16') - - def _get_password(self, target): - try: - res = win32cred.CredRead( - Type=win32cred.CRED_TYPE_GENERIC, - TargetName=target, - ) - except pywintypes.error as e: - e = OldPywinError.wrap(e) - if e.winerror == 1168 and e.funcname == 'CredRead': # not found - return None - raise - return res - - def set_password(self, service, username, password): - existing_pw = self._get_password(service) - if existing_pw: - # resave the existing password using a compound target - existing_username = existing_pw['UserName'] - target = self._compound_name(existing_username, service) - self._set_password(target, existing_username, - existing_pw['CredentialBlob'].decode('utf-16')) - self._set_password(service, username, unicode_str(password)) - - def _set_password(self, target, username, password): - credential = dict(Type=win32cred.CRED_TYPE_GENERIC, - TargetName=target, - UserName=username, - CredentialBlob=password, - Comment="Stored using python-keyring", - Persist=win32cred.CRED_PERSIST_ENTERPRISE) - win32cred.CredWrite(credential, 0) - - def delete_password(self, service, username): - compound = self._compound_name(username, service) - deleted = False - for target in service, compound: - existing_pw = self._get_password(target) - if existing_pw and existing_pw['UserName'] == username: - deleted = True - self._delete_password(target) - if not deleted: - raise PasswordDeleteError(service) - - def _delete_password(self, target): - win32cred.CredDelete( - Type=win32cred.CRED_TYPE_GENERIC, - TargetName=target, - ) - - -class RegistryKeyring(KeyringBackend): - """ - RegistryKeyring is a keyring which use Windows CryptAPI to encrypt - the user's passwords and store them under registry keys - """ - - @properties.ClassProperty - @classmethod - def priority(self): - """ - Preferred on Windows when pywin32 isn't installed - """ - if platform.system() != 'Windows': - raise RuntimeError("Requires Windows") - if not has_wincrypto(): - raise RuntimeError("Requires ctypes") - return 2 - - def get_password(self, service, username): - """Get password of the username for the service - """ - try: - # fetch the password - key = r'Software\%s\Keyring' % service - hkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key) - password_saved = winreg.QueryValueEx(hkey, username)[0] - password_base64 = password_saved.encode('ascii') - # decode with base64 - password_encrypted = base64.decodestring(password_base64) - # decrypted the password - password = _win_crypto.decrypt(password_encrypted).decode('utf-8') - except EnvironmentError: - password = None - return password - - def set_password(self, service, username, password): - """Write the password to the registry - """ - # encrypt the password - password_encrypted = _win_crypto.encrypt(password.encode('utf-8')) - # encode with base64 - password_base64 = base64.encodestring(password_encrypted) - # encode again to unicode - password_saved = password_base64.decode('ascii') - - # store the password - key_name = r'Software\%s\Keyring' % service - hkey = winreg.CreateKey(winreg.HKEY_CURRENT_USER, key_name) - winreg.SetValueEx(hkey, username, 0, winreg.REG_SZ, password_saved) - - def delete_password(self, service, username): - """Delete the password for the username of the service. - """ - try: - key_name = r'Software\%s\Keyring' % service - hkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_name, 0, - winreg.KEY_ALL_ACCESS) - winreg.DeleteValue(hkey, username) - winreg.CloseKey(hkey) - except WindowsError: - e = sys.exc_info()[1] - raise PasswordDeleteError(e) - self._delete_key_if_empty(service) - - def _delete_key_if_empty(self, service): - key_name = r'Software\%s\Keyring' % service - key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_name, 0, - winreg.KEY_ALL_ACCESS) - try: - winreg.EnumValue(key, 0) - return - except WindowsError: - pass - winreg.CloseKey(key) - - # it's empty; delete everything - while key_name != 'Software': - parent, sep, base = key_name.rpartition('\\') - key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, parent, 0, - winreg.KEY_ALL_ACCESS) - winreg.DeleteKey(key, base) - winreg.CloseKey(key) - key_name = parent - - -class OldPywinError(object): - """ - A compatibility wrapper for old PyWin32 errors, such as reported in - https://bitbucket.org/kang/python-keyring-lib/issue/140/ - """ - def __init__(self, orig): - self.orig = orig - - @property - def funcname(self): - return self.orig[1] - - @property - def winerror(self): - return self.orig[0] - - @classmethod - def wrap(cls, orig_err): - attr_check = functools.partial(hasattr, orig_err) - is_old = not all(map(attr_check, ['funcname', 'winerror'])) - return cls(orig_err) if is_old else orig_err diff --git a/awx/lib/site-packages/keyring/backends/__init__.py b/awx/lib/site-packages/keyring/backends/__init__.py deleted file mode 100644 index 792d600548..0000000000 --- a/awx/lib/site-packages/keyring/backends/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/awx/lib/site-packages/keyring/backends/_win_crypto.py b/awx/lib/site-packages/keyring/backends/_win_crypto.py deleted file mode 100644 index b23d636a34..0000000000 --- a/awx/lib/site-packages/keyring/backends/_win_crypto.py +++ /dev/null @@ -1,101 +0,0 @@ - -from ctypes import Structure, POINTER, c_void_p, cast, create_string_buffer, \ - c_char_p, byref, memmove -from ctypes import windll, WinDLL, WINFUNCTYPE -try: - from ctypes import wintypes -except ValueError: - # see http://bugs.python.org/issue16396 - raise ImportError("wintypes") - -from ..util.escape import u - -# Crypto API ctypes bindings - -class DATA_BLOB(Structure): - _fields_ = [('cbData', wintypes.DWORD), - ('pbData', POINTER(wintypes.BYTE))] - - -class CRYPTPROTECT_PROMPTSTRUCT(Structure): - _fields_ = [('cbSize', wintypes.DWORD), - ('dwPromptFlags', wintypes.DWORD), - ('hwndApp', wintypes.HWND), - ('szPrompt', POINTER(wintypes.WCHAR))] - -# Flags for CRYPTPROTECT_PROMPTSTRUCT - -CRYPTPROTECT_PROMPT_ON_UNPROTECT = 1 -CRYPTPROTECT_PROMPT_ON_PROTECT = 2 - -# Flags for CryptProtectData/CryptUnprotectData - -CRYPTPROTECT_UI_FORBIDDEN = 0x01 -CRYPTPROTECT_LOCAL_MACHINE = 0x04 -CRYPTPROTECT_CRED_SYNC = 0x08 -CRYPTPROTECT_AUDIT = 0x10 -CRYPTPROTECT_NO_RECOVERY = 0x20 -CRYPTPROTECT_VERIFY_PROTECTION = 0x40 -CRYPTPROTECT_CRED_REGENERATE = 0x80 - -# Crypto API Functions - -_dll = WinDLL('CRYPT32.DLL') - -CryptProtectData = WINFUNCTYPE(wintypes.BOOL, - POINTER(DATA_BLOB), - POINTER(wintypes.WCHAR), - POINTER(DATA_BLOB), - c_void_p, - POINTER(CRYPTPROTECT_PROMPTSTRUCT), - wintypes.DWORD, - POINTER(DATA_BLOB))(('CryptProtectData', _dll)) - -CryptUnprotectData = WINFUNCTYPE(wintypes.BOOL, - POINTER(DATA_BLOB), - POINTER(wintypes.WCHAR), - POINTER(DATA_BLOB), - c_void_p, - POINTER(CRYPTPROTECT_PROMPTSTRUCT), - wintypes.DWORD, POINTER(DATA_BLOB))( - ('CryptUnprotectData', _dll)) - -# Functions - - -def encrypt(data, non_interactive=0): - blobin = DATA_BLOB(cbData=len(data), - pbData=cast(c_char_p(data), - POINTER(wintypes.BYTE))) - blobout = DATA_BLOB() - - if not CryptProtectData(byref(blobin), - u('python-keyring-lib.win32crypto'), - None, None, None, - CRYPTPROTECT_UI_FORBIDDEN, - byref(blobout)): - raise OSError("Can't encrypt") - - encrypted = create_string_buffer(blobout.cbData) - memmove(encrypted, blobout.pbData, blobout.cbData) - windll.kernel32.LocalFree(blobout.pbData) - return encrypted.raw - - -def decrypt(encrypted, non_interactive=0): - blobin = DATA_BLOB(cbData=len(encrypted), - pbData=cast(c_char_p(encrypted), - POINTER(wintypes.BYTE))) - blobout = DATA_BLOB() - - if not CryptUnprotectData(byref(blobin), - u('python-keyring-lib.win32crypto'), - None, None, None, - CRYPTPROTECT_UI_FORBIDDEN, - byref(blobout)): - raise OSError("Can't decrypt") - - data = create_string_buffer(blobout.cbData) - memmove(data, blobout.pbData, blobout.cbData) - windll.kernel32.LocalFree(blobout.pbData) - return data.raw diff --git a/awx/lib/site-packages/keyring/backends/file.py b/awx/lib/site-packages/keyring/backends/file.py deleted file mode 100644 index f89988066f..0000000000 --- a/awx/lib/site-packages/keyring/backends/file.py +++ /dev/null @@ -1,295 +0,0 @@ -from __future__ import with_statement - -import os -import getpass -import base64 -import sys -import json -import abc - -from ..py27compat import configparser - -from ..errors import PasswordDeleteError -from ..backend import KeyringBackend -from ..util import platform_, properties -from ..util.escape import escape as escape_for_ini - - -class FileBacked(object): - @abc.abstractproperty - def filename(self): - """ - The filename used to store the passwords. - """ - - @properties.NonDataProperty - def file_path(self): - """ - The path to the file where passwords are stored. This property - may be overridden by the subclass or at the instance level. - """ - return os.path.join(platform_.data_root(), self.filename) - - -class BaseKeyring(FileBacked, KeyringBackend): - """ - BaseKeyring is a file-based implementation of keyring. - - This keyring stores the password directly in the file and provides methods - which may be overridden by subclasses to support - encryption and decryption. The encrypted payload is stored in base64 - format. - """ - - @abc.abstractmethod - def encrypt(self, password): - """ - Given a password (byte string), return an encrypted byte string. - """ - - @abc.abstractmethod - def decrypt(self, password_encrypted): - """ - Given a password encrypted by a previous call to `encrypt`, return - the original byte string. - """ - - def get_password(self, service, username): - """ - Read the password from the file. - """ - service = escape_for_ini(service) - username = escape_for_ini(username) - - # load the passwords from the file - config = configparser.RawConfigParser() - if os.path.exists(self.file_path): - config.read(self.file_path) - - # fetch the password - try: - password_base64 = config.get(service, username).encode() - # decode with base64 - password_encrypted = base64.decodestring(password_base64) - # decrypted the password - password = self.decrypt(password_encrypted).decode('utf-8') - except (configparser.NoOptionError, configparser.NoSectionError): - password = None - return password - - def set_password(self, service, username, password): - """Write the password in the file. - """ - service = escape_for_ini(service) - username = escape_for_ini(username) - - # encrypt the password - password_encrypted = self.encrypt(password.encode('utf-8')) - # encode with base64 - password_base64 = base64.encodestring(password_encrypted).decode() - - # ensure the file exists - self._ensure_file_path() - - # load the keyring from the disk - config = configparser.RawConfigParser() - config.read(self.file_path) - - # update the keyring with the password - if not config.has_section(service): - config.add_section(service) - config.set(service, username, password_base64) - - # save the keyring back to the file - with open(self.file_path, 'w') as config_file: - config.write(config_file) - - def _ensure_file_path(self): - """ - Ensure the storage path exists. - If it doesn't, create it with "go-rwx" permissions. - """ - storage_root = os.path.dirname(self.file_path) - if storage_root and not os.path.isdir(storage_root): - os.makedirs(storage_root) - if not os.path.isfile(self.file_path): - # create the file without group/world permissions - with open(self.file_path, 'w'): - pass - user_read_write = 0o600 - os.chmod(self.file_path, user_read_write) - - def delete_password(self, service, username): - """Delete the password for the username of the service. - """ - service = escape_for_ini(service) - username = escape_for_ini(username) - config = configparser.RawConfigParser() - if os.path.exists(self.file_path): - config.read(self.file_path) - try: - if not config.remove_option(service, username): - raise PasswordDeleteError("Password not found") - except configparser.NoSectionError: - raise PasswordDeleteError("Password not found") - # update the file - with open(self.file_path, 'w') as config_file: - config.write(config_file) - -class PlaintextKeyring(BaseKeyring): - """Simple File Keyring with no encryption""" - - priority = .5 - "Applicable for all platforms, but not recommended" - - filename = 'keyring_pass.cfg' - - def encrypt(self, password): - """Directly return the password itself. - """ - return password - - def decrypt(self, password_encrypted): - """Directly return encrypted password. - """ - return password_encrypted - -class Encrypted(object): - """ - PyCrypto-backed Encryption support - """ - - block_size = 32 - - def _create_cipher(self, password, salt, IV): - """ - Create the cipher object to encrypt or decrypt a payload. - """ - from Crypto.Protocol.KDF import PBKDF2 - from Crypto.Cipher import AES - pw = PBKDF2(password, salt, dkLen=self.block_size) - return AES.new(pw[:self.block_size], AES.MODE_CFB, IV) - - def _get_new_password(self): - while True: - password = getpass.getpass( - "Please set a password for your new keyring: ") - confirm = getpass.getpass('Please confirm the password: ') - if password != confirm: - sys.stderr.write("Error: Your passwords didn't match\n") - continue - if '' == password.strip(): - # forbid the blank password - sys.stderr.write("Error: blank passwords aren't allowed.\n") - continue - return password - - -class EncryptedKeyring(Encrypted, BaseKeyring): - """PyCrypto File Keyring""" - - filename = 'crypted_pass.cfg' - pw_prefix = 'pw:'.encode() - - @properties.ClassProperty - @classmethod - def priority(self): - "Applicable for all platforms, but not recommended." - try: - __import__('Crypto.Cipher.AES') - __import__('Crypto.Protocol.KDF') - __import__('Crypto.Random') - except ImportError: - raise RuntimeError("PyCrypto required") - if not json: - raise RuntimeError("JSON implementation such as simplejson " - "required.") - return .6 - - @properties.NonDataProperty - def keyring_key(self): - # _unlock or _init_file will set the key or raise an exception - if self._check_file(): - self._unlock() - else: - self._init_file() - return self.keyring_key - - def _init_file(self): - """ - Initialize a new password file and set the reference password. - """ - self.keyring_key = self._get_new_password() - # set a reference password, used to check that the password provided - # matches for subsequent checks. - self.set_password('keyring-setting', 'password reference', - 'password reference value') - - def _check_file(self): - """ - Check if the file exists and has the expected password reference. - """ - if not os.path.exists(self.file_path): - return False - self._migrate() - config = configparser.RawConfigParser() - config.read(self.file_path) - try: - config.get( - escape_for_ini('keyring-setting'), - escape_for_ini('password reference'), - ) - except (configparser.NoSectionError, configparser.NoOptionError): - return False - return True - - def _unlock(self): - """ - Unlock this keyring by getting the password for the keyring from the - user. - """ - self.keyring_key = getpass.getpass( - 'Please enter password for encrypted keyring: ') - try: - ref_pw = self.get_password('keyring-setting', 'password reference') - assert ref_pw == 'password reference value' - except AssertionError: - self._lock() - raise ValueError("Incorrect Password") - - def _lock(self): - """ - Remove the keyring key from this instance. - """ - del self.keyring_key - - def encrypt(self, password): - from Crypto.Random import get_random_bytes - salt = get_random_bytes(self.block_size) - from Crypto.Cipher import AES - IV = get_random_bytes(AES.block_size) - cipher = self._create_cipher(self.keyring_key, salt, IV) - password_encrypted = cipher.encrypt(self.pw_prefix + password) - # Serialize the salt, IV, and encrypted password in a secure format - data = dict( - salt=salt, IV=IV, password_encrypted=password_encrypted, - ) - for key in data: - data[key] = base64.encodestring(data[key]).decode() - return json.dumps(data).encode() - - def decrypt(self, password_encrypted): - # unpack the encrypted payload - data = json.loads(password_encrypted.decode()) - for key in data: - data[key] = base64.decodestring(data[key].encode()) - cipher = self._create_cipher(self.keyring_key, data['salt'], - data['IV']) - plaintext = cipher.decrypt(data['password_encrypted']) - assert plaintext.startswith(self.pw_prefix) - return plaintext[3:] - - def _migrate(self, keyring_password=None): - """ - Convert older keyrings to the current format. - """ diff --git a/awx/lib/site-packages/keyring/backends/keyczar.py b/awx/lib/site-packages/keyring/backends/keyczar.py deleted file mode 100644 index 7bf5fc0b63..0000000000 --- a/awx/lib/site-packages/keyring/backends/keyczar.py +++ /dev/null @@ -1,99 +0,0 @@ -from __future__ import absolute_import - -import os -import abc - -try: - from keyczar import keyczar -except ImportError: - pass - -from ..backend import Crypter -from .. import errors - -def has_keyczar(): - with errors.ExceptionRaisedContext() as exc: - keyczar.__name__ - return not bool(exc) - -class BaseCrypter(Crypter): - """Base Keyczar keyset encryption and decryption. - The keyset initialisation is deferred until required. - """ - - @abc.abstractproperty - def keyset_location(self): - """Location for the main keyset that may be encrypted or not""" - pass - - @abc.abstractproperty - def encrypting_keyset_location(self): - """Location for the encrypting keyset. - Use None to indicate that the main keyset is not encrypted - """ - pass - - @property - def crypter(self): - """The actual keyczar crypter""" - if not hasattr(self, '_crypter'): - # initialise the Keyczar keysets - if not self.keyset_location: - raise ValueError('No encrypted keyset location!') - reader = keyczar.readers.CreateReader(self.keyset_location) - if self.encrypting_keyset_location: - encrypting_keyczar = keyczar.Crypter.Read( - self.encrypting_keyset_location) - reader = keyczar.readers.EncryptedReader(reader, - encrypting_keyczar) - self._crypter = keyczar.Crypter(reader) - return self._crypter - - def encrypt(self, value): - """Encrypt the value. - """ - if not value: - return '' - return self.crypter.Encrypt(value) - - def decrypt(self, value): - """Decrypt the value. - """ - if not value: - return '' - return self.crypter.Decrypt(value) - -class Crypter(BaseCrypter): - """A Keyczar crypter using locations specified in the constructor - """ - - def __init__(self, keyset_location, encrypting_keyset_location=None): - self._keyset_location = keyset_location - self._encrypting_keyset_location = encrypting_keyset_location - - @property - def keyset_location(self): - return self._keyset_location - - @property - def encrypting_keyset_location(self): - return self._encrypting_keyset_location - -class EnvironCrypter(BaseCrypter): - """A Keyczar crypter using locations specified by environment vars - """ - - KEYSET_ENV_VAR = 'KEYRING_KEYCZAR_ENCRYPTED_LOCATION' - ENC_KEYSET_ENV_VAR = 'KEYRING_KEYCZAR_ENCRYPTING_LOCATION' - - @property - def keyset_location(self): - val = os.environ.get(self.KEYSET_ENV_VAR) - if not val: - raise ValueError('%s environment value not set' % - self.KEYSET_ENV_VAR) - return val - - @property - def encrypting_keyset_location(self): - return os.environ.get(self.ENC_KEYSET_ENV_VAR) diff --git a/awx/lib/site-packages/keyring/backends/kwallet.py b/awx/lib/site-packages/keyring/backends/kwallet.py deleted file mode 100644 index 209b75d818..0000000000 --- a/awx/lib/site-packages/keyring/backends/kwallet.py +++ /dev/null @@ -1,113 +0,0 @@ -from __future__ import absolute_import - -import os - -from ..py27compat import unicode_str -from ..backend import KeyringBackend -from ..errors import PasswordDeleteError -from ..errors import PasswordSetError, ExceptionRaisedContext -from ..util import properties -from ..util import XDG - -try: - from PyKDE4.kdeui import KWallet - from PyQt4 import QtGui -except ImportError: - pass - -kwallet = None - -def open_kwallet(kwallet_module=None, qt_module=None): - - # If we specified the kwallet_module and/or qt_module, surely we won't need - # the cached kwallet object... - if kwallet_module is None and qt_module is None: - global kwallet - if not kwallet is None: - return kwallet - - # Allow for the injection of module-like objects for testing purposes. - if kwallet_module is None: - kwallet_module = KWallet.Wallet - if qt_module is None: - qt_module = QtGui - - # KDE wants us to instantiate an application object. - app = None - if qt_module.qApp.instance() == None: - app = qt_module.QApplication([]) - try: - window = qt_module.QWidget() - kwallet = kwallet_module.openWallet( - kwallet_module.NetworkWallet(), - window.winId(), - kwallet_module.Synchronous) - if kwallet is not None: - if not kwallet.hasFolder('Python'): - kwallet.createFolder('Python') - kwallet.setFolder('Python') - return kwallet - finally: - if app: - app.exit() - -class Keyring(KeyringBackend): - """KDE KWallet""" - - @properties.ClassProperty - @classmethod - @XDG.Preference('KDE') - def priority(cls): - with ExceptionRaisedContext() as exc: - KWallet.__name__ - if exc: - raise RuntimeError("KDE libraries not available") - if "DISPLAY" not in os.environ: - raise RuntimeError("cannot connect to X server") - # Infer if KDE environment is active based on environment vars. - # TODO: Does PyKDE provide a better indicator? - kde_session_keys = ( - 'KDE_SESSION_ID', # most environments - 'KDE_FULL_SESSION', # openSUSE - ) - if not set(os.environ).intersection(kde_session_keys): - return 0 - return 5 - - def get_password(self, service, username): - """Get password of the username for the service - """ - key = username + '@' + service - network = KWallet.Wallet.NetworkWallet() - wallet = open_kwallet() - if wallet is None: - # the user pressed "cancel" when prompted to unlock their keyring. - return None - if wallet.keyDoesNotExist(network, 'Python', key): - return None - - result = wallet.readPassword(key)[1] - # The string will be a PyQt4.QtCore.QString, so turn it into a unicode - # object. - return unicode_str(result) - - def set_password(self, service, username, password): - """Set password for the username of the service - """ - wallet = open_kwallet() - if wallet is None: - # the user pressed "cancel" when prompted to unlock their keyring. - raise PasswordSetError("Cancelled by user") - wallet.writePassword(username+'@'+service, password) - - def delete_password(self, service, username): - """Delete the password for the username of the service. - """ - key = username + '@' + service - wallet = open_kwallet() - if wallet is None: - # the user pressed "cancel" when prompted to unlock their keyring. - raise PasswordDeleteError("Cancelled by user") - if wallet.keyDoesNotExist(wallet.walletName(), 'Python', key): - raise PasswordDeleteError("Password not found") - wallet.removeEntry(key) diff --git a/awx/lib/site-packages/keyring/backends/multi.py b/awx/lib/site-packages/keyring/backends/multi.py deleted file mode 100644 index 90d7c04c37..0000000000 --- a/awx/lib/site-packages/keyring/backends/multi.py +++ /dev/null @@ -1,63 +0,0 @@ -import itertools - -from ..util import properties -from ..backend import KeyringBackend -from .. import errors - -class MultipartKeyringWrapper(KeyringBackend): - - """A wrapper around an existing keyring that breaks the password into - smaller parts to handle implementations that have limits on the maximum - length of passwords i.e. Windows Vault - """ - - def __init__(self, keyring, max_password_size=512): - self._keyring = keyring - self._max_password_size = max_password_size - - @properties.ClassProperty - @classmethod - def priority(cls): - return 0 - - def get_password(self, service, username): - """Get password of the username for the service - """ - init_part = self._keyring.get_password(service, username) - if init_part: - parts = [init_part,] - i = 1 - while True: - next_part = self._keyring.get_password( - service, - '%s{{part_%d}}' %(username, i)) - if next_part: - parts.append(next_part) - i += 1 - else: - break - return ''.join(parts) - return None - - def set_password(self, service, username, password): - """Set password for the username of the service - """ - segments = range(0, len(password), self._max_password_size) - password_parts = [ - password[i:i + self._max_password_size] for i in segments] - for i, password_part in enumerate(password_parts): - curr_username = username - if i > 0: - curr_username += '{{part_%d}}' %i - self._keyring.set_password(service, curr_username, password_part) - - def delete_password(self, service, username): - self._keyring.delete_password(service, username) - count = itertools.count(1) - while True: - part_name = '%(username)s{{part_%(index)d}}' % dict( - index = next(count), **vars()) - try: - self._keyring.delete_password(service, part_name) - except errors.PasswordDeleteError: - break diff --git a/awx/lib/site-packages/keyring/backends/pyfs.py b/awx/lib/site-packages/keyring/backends/pyfs.py deleted file mode 100644 index ca82bd7418..0000000000 --- a/awx/lib/site-packages/keyring/backends/pyfs.py +++ /dev/null @@ -1,252 +0,0 @@ -import os -import base64 - -from ..py27compat import configparser - -from .. import errors -from ..util.escape import escape as escape_for_ini -from ..util import platform_, properties -from ..backend import KeyringBackend, NullCrypter -from . import keyczar - -try: - import fs.opener - import fs.osfs - import fs.errors - import fs.path - import fs.remote -except ImportError: - pass - -def has_pyfs(): - """ - Does this environment have pyfs installed? - Should return False even when Mercurial's Demand Import allowed import of - fs.*. - """ - with errors.ExceptionRaisedContext() as exc: - fs.__name__ - return not bool(exc) - -class BasicKeyring(KeyringBackend): - """BasicKeyring is a Pyfilesystem-based implementation of - keyring. - - It stores the password directly in the file, and supports - encryption and decryption. The encrypted password is stored in base64 - format. - Being based on Pyfilesystem the file can be local or network-based and - served by any of the filesystems supported by Pyfilesystem including Amazon - S3, FTP, WebDAV, memory and more. - """ - - _filename = 'keyring_pyf_pass.cfg' - - def __init__(self, crypter, filename=None, can_create=True, - cache_timeout=None): - super(BasicKeyring, self).__init__() - self._crypter = crypter - self._filename = (filename or - os.path.join(platform_.data_root(), - self.__class__._filename)) - self._can_create = can_create - self._cache_timeout = cache_timeout - - @properties.NonDataProperty - def file_path(self): - """ - The path to the file where passwords are stored. This property - may be overridden by the subclass or at the instance level. - """ - return os.path.join(platform_.data_root(), self.filename) - - @property - def filename(self): - """The filename used to store the passwords. - """ - return self._filename - - def encrypt(self, password): - """Encrypt the password. - """ - if not password or not self._crypter: - return password or '' - return self._crypter.encrypt(password) - - def decrypt(self, password_encrypted): - """Decrypt the password. - """ - if not password_encrypted or not self._crypter: - return password_encrypted or '' - return self._crypter.decrypt(password_encrypted) - - def _open(self, mode='rb'): - """Open the password file in the specified mode - """ - open_file = None - writeable = 'w' in mode or 'a' in mode or '+' in mode - try: - # NOTE: currently the MemOpener does not split off any filename - # which causes errors on close() - # so we add a dummy name and open it separately - if (self.filename.startswith('mem://') or - self.filename.startswith('ram://')): - open_file = fs.opener.fsopendir(self.filename).open('kr.cfg', - mode) - else: - if not hasattr(self, '_pyfs'): - # reuse the pyfilesystem and path - self._pyfs, self._path = fs.opener.opener.parse(self.filename, - writeable=writeable) - # cache if permitted - if self._cache_timeout is not None: - self._pyfs = fs.remote.CacheFS( - self._pyfs, cache_timeout=self._cache_timeout) - open_file = self._pyfs.open(self._path, mode) - except fs.errors.ResourceNotFoundError: - if self._can_create: - segments = fs.opener.opener.split_segments(self.filename) - if segments: - # this seems broken, but pyfilesystem uses it, so we must - fs_name, credentials, url1, url2, path = segments.groups() - assert fs_name, 'Should be a remote filesystem' - host = '' - # allow for domain:port - if ':' in url2: - split_url2 = url2.split('/', 1) - if len(split_url2) > 1: - url2 = split_url2[1] - else: - url2 = '' - host = split_url2[0] - pyfs = fs.opener.opener.opendir('%s://%s' %(fs_name, host)) - # cache if permitted - if self._cache_timeout is not None: - pyfs = fs.remote.CacheFS( - pyfs, cache_timeout=self._cache_timeout) - # NOTE: fs.path.split does not function in the same way os os.path.split... at least under windows - url2_path, url2_filename = os.path.split(url2) - if url2_path and not pyfs.exists(url2_path): - pyfs.makedir(url2_path, recursive=True) - else: - # assume local filesystem - full_url = fs.opener._expand_syspath(self.filename) - # NOTE: fs.path.split does not function in the same way os os.path.split... at least under windows - url2_path, url2 = os.path.split(full_url) - pyfs = fs.osfs.OSFS(url2_path) - - try: - # reuse the pyfilesystem and path - self._pyfs = pyfs - self._path = url2 - return pyfs.open(url2, mode) - except fs.errors.ResourceNotFoundError: - if writeable: - raise - else: - pass - # NOTE: ignore read errors as the underlying caller can fail safely - if writeable: - raise - else: - pass - return open_file - - @property - def config(self): - """load the passwords from the config file - """ - if not hasattr(self, '_config'): - raw_config = configparser.RawConfigParser() - f = self._open() - if f: - raw_config.readfp(f) - f.close() - self._config = raw_config - return self._config - - def get_password(self, service, username): - """Read the password from the file. - """ - service = escape_for_ini(service) - username = escape_for_ini(username) - - # fetch the password - try: - password_base64 = self.config.get(service, username).encode() - # decode with base64 - password_encrypted = base64.decodestring(password_base64) - # decrypted the password - password = self.decrypt(password_encrypted).decode('utf-8') - except (configparser.NoOptionError, configparser.NoSectionError): - password = None - return password - - def set_password(self, service, username, password): - """Write the password in the file. - """ - service = escape_for_ini(service) - username = escape_for_ini(username) - - # encrypt the password - password = password or '' - password_encrypted = self.encrypt(password.encode('utf-8')) - - # encode with base64 - password_base64 = base64.encodestring(password_encrypted).decode() - # write the modification - if not self.config.has_section(service): - self.config.add_section(service) - self.config.set(service, username, password_base64) - config_file = self._open('w') - self.config.write(config_file) - config_file.close() - - def delete_password(self, service, username): - service = escape_for_ini(service) - username = escape_for_ini(username) - - try: - self.config.remove_option(service, username) - except configparser.NoSectionError: - raise errors.PasswordDeleteError('Password not found') - config_file = self._open('w') - self.config.write(config_file) - config_file.close() - - @properties.ClassProperty - @classmethod - def priority(cls): - if not has_pyfs(): - raise RuntimeError("pyfs required") - return 2 - -class PlaintextKeyring(BasicKeyring): - """Unencrypted Pyfilesystem Keyring - """ - - def __init__(self, filename=None, can_create=True, cache_timeout=None): - super(PlaintextKeyring, self).__init__( - NullCrypter(), filename=filename, can_create=can_create, - cache_timeout=cache_timeout) - -class EncryptedKeyring(BasicKeyring): - """Encrypted Pyfilesystem Keyring - """ - - _filename = 'crypted_pyf_pass.cfg' - - def __init__(self, crypter, filename=None, can_create=True, - cache_timeout=None): - super(EncryptedKeyring, self).__init__( - crypter, filename=filename, can_create=can_create, - cache_timeout=cache_timeout) - -class KeyczarKeyring(EncryptedKeyring): - """Encrypted Pyfilesystem Keyring using Keyczar keysets specified in - environment vars - """ - - def __init__(self): - super(KeyczarKeyring, self).__init__( - keyczar.EnvironCrypter()) diff --git a/awx/lib/site-packages/keyring/cli.py b/awx/lib/site-packages/keyring/cli.py deleted file mode 100644 index 4fae8211a6..0000000000 --- a/awx/lib/site-packages/keyring/cli.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python -"""Simple command line interface to get/set password from a keyring""" - -from __future__ import print_function - -import getpass -from optparse import OptionParser -import sys - -from . import get_keyring, set_keyring, get_password, set_password, delete_password -from . import core - - -class CommandLineTool(object): - def __init__(self): - self.parser = OptionParser( - usage="%prog [get|set|del] SERVICE USERNAME") - self.parser.add_option("-p", "--keyring-path", - dest="keyring_path", default=None, - help="Path to the keyring backend") - self.parser.add_option("-b", "--keyring-backend", - dest="keyring_backend", default=None, - help="Name of the keyring backend") - - def run(self, argv): - opts, args = self.parser.parse_args(argv) - - try: - kind, service, username = args - except ValueError: - if len(args) == 0: - # Be nice with the user if he just tries to launch the tool - self.parser.print_help() - return 1 - else: - self.parser.error("Wrong number of arguments") - - if opts.keyring_backend is not None: - try: - if opts.keyring_path: - sys.path.insert(0, opts.keyring_path) - backend = core.load_keyring(opts.keyring_backend) - set_keyring(backend) - except (Exception,): - # Tons of things can go wrong here: - # ImportError when using "fjkljfljkl" - # AttributeError when using "os.path.bar" - # TypeError when using "__builtins__.str" - # So, we play on the safe side, and catch everything. - e = sys.exc_info()[1] - self.parser.error("Unable to load specified keyring: %s" % e) - - if kind == 'get': - password = get_password(service, username) - if password is None: - return 1 - - self.output_password(password) - return 0 - - elif kind == 'set': - password = self.input_password("Password for '%s' in '%s': " % - (username, service)) - set_password(service, username, password) - return 0 - - elif kind == 'del': - password = self.input_password("Deleting password for '%s' in '%s': " % - (username, service)) - delete_password(service, username) - return 0 - - else: - self.parser.error("You can only 'get', 'del' or 'set' a password.") - pass - - def input_password(self, prompt): - """Ask for a password to the user. - - This mostly exists to ease the testing process. - """ - - return getpass.getpass(prompt) - - def output_password(self, password): - """Output the password to the user. - - This mostly exists to ease the testing process. - """ - - print(password, file=sys.stdout) - - -def main(argv=None): - """Main command line interface.""" - - if argv is None: - argv = sys.argv[1:] - - cli = CommandLineTool() - return cli.run(argv) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/awx/lib/site-packages/keyring/core.py b/awx/lib/site-packages/keyring/core.py deleted file mode 100644 index 6d193c9050..0000000000 --- a/awx/lib/site-packages/keyring/core.py +++ /dev/null @@ -1,158 +0,0 @@ -""" -core.py - -Created by Kang Zhang on 2009-07-09 -""" -import os -import sys -import logging - -from .py27compat import configparser - -from . import logger -from . import backend -from .util import platform_ as platform - -log = logging.getLogger(__name__) - -_keyring_backend = None - -def set_keyring(keyring): - """Set current keyring backend. - """ - global _keyring_backend - if not isinstance(keyring, backend.KeyringBackend): - raise TypeError("The keyring must be a subclass of KeyringBackend") - _keyring_backend = keyring - - -def get_keyring(): - """Get current keyring backend. - """ - return _keyring_backend - - -def get_password(service_name, username): - """Get password from the specified service. - """ - return _keyring_backend.get_password(service_name, username) - - -def set_password(service_name, username, password): - """Set password for the user in the specified service. - """ - _keyring_backend.set_password(service_name, username, password) - - -def delete_password(service_name, username): - """Delete the password for the user in the specified service. - """ - _keyring_backend.delete_password(service_name, username) - - -def init_backend(): - """ - Load a keyring specified in the config file or infer the best available. - """ - _load_library_extensions() - set_keyring(load_config() or _get_best_keyring()) - - -def _get_best_keyring(): - """ - Return the best keyring backend for the given environment based on - priority. - """ - keyrings = backend.get_all_keyring() - # rank by priority - keyrings.sort(key = lambda x: -x.priority) - # get the most recommended one - return keyrings[0] - - -def load_keyring(keyring_name): - """ - Load the specified keyring by name (a fully-qualified name to the - keyring, such as 'keyring.backends.file.PlaintextKeyring') - """ - module_name, sep, class_name = keyring_name.rpartition('.') - __import__(module_name) - module = sys.modules[module_name] - class_ = getattr(module, class_name) - # invoke the priority to ensure it is viable, or raise a RuntimeError - class_.priority - return class_() - - -def load_config(): - """Load a keyring using the config file in the config root.""" - - filename = 'keyringrc.cfg' - - keyring_cfg = os.path.join(platform.config_root(), filename) - - if not os.path.exists(keyring_cfg): - return - - config = configparser.RawConfigParser() - config.read(keyring_cfg) - _load_keyring_path(config) - - # load the keyring class name, and then load this keyring - try: - if config.has_section("backend"): - keyring_name = config.get("backend", "default-keyring").strip() - else: - raise configparser.NoOptionError('backend', 'default-keyring') - - except (configparser.NoOptionError, ImportError): - logger.warning("Keyring config file contains incorrect values.\n" + - "Config file: %s" % keyring_cfg) - return - - return load_keyring(keyring_name) - -def _load_keyring_path(config): - "load the keyring-path option (if present)" - try: - path = config.get("backend", "keyring-path").strip() - sys.path.insert(0, path) - except (configparser.NoOptionError, configparser.NoSectionError): - pass - -def _load_library_extensions(): - """ - Locate all setuptools entry points by the name 'keyring backends' - and initialize them. - - Any third-party library may register an entry point by adding the - following to their setup.py:: - - entry_points = { - 'keyring backends': [ - 'plugin name = mylib.mymodule:initialize_func', - ], - }, - - `plugin name` can be anything. - `initialize_func` is optional and will be invoked by keyring on startup. - - Most plugins will simply provide or import a KeyringBackend in `mymodule`. - """ - group = 'keyring backends' - try: - pkg_resources = __import__('pkg_resources') - except ImportError: - return - entry_points = pkg_resources.iter_entry_points(group=group) - for ep in entry_points: - try: - log.info('Loading keyring backends from %s', ep.name) - init_func = ep.load() - if callable(init_func): - init_func() - except Exception as exc: - log.exception("Error initializing plugin %s (%s).", ep, exc) - -# init the _keyring_backend -init_backend() diff --git a/awx/lib/site-packages/keyring/credentials.py b/awx/lib/site-packages/keyring/credentials.py deleted file mode 100644 index 99470515f5..0000000000 --- a/awx/lib/site-packages/keyring/credentials.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -import abc - -from .py27compat import add_metaclass - -@add_metaclass(abc.ABCMeta) -class Credential(object): - """Abstract class to manage credentials - """ - - @abc.abstractproperty - def username(self): - return None - - @abc.abstractproperty - def password(self): - return None - -class SimpleCredential(Credential): - """Simple credentials implementation - """ - - def __init__(self, username, password): - self._username = username - self._password = password - - @property - def username(self): - return self._username - - @property - def password(self): - return self._password - -class EnvironCredential(Credential): - """Source credentials from environment variables. - Actual sourcing is deferred until requested. - """ - - def __init__(self, user_env_var, pwd_env_var): - self.user_env_var = user_env_var - self.pwd_env_var = pwd_env_var - - def _get_env(self, env_var): - """Helper to read an environment variable - """ - value = os.environ.get(env_var) - if not value: - raise ValueError('Missing environment variable:%s' %env_var) - return value - - @property - def username(self): - return self._get_env(self.user_env_var) - - @property - def password(self): - return self._get_env(self.pwd_env_var) diff --git a/awx/lib/site-packages/keyring/errors.py b/awx/lib/site-packages/keyring/errors.py deleted file mode 100644 index d32c260a32..0000000000 --- a/awx/lib/site-packages/keyring/errors.py +++ /dev/null @@ -1,45 +0,0 @@ -import sys - -class PasswordSetError(Exception): - """Raised when the password can't be set. - """ - -class PasswordDeleteError(Exception): - """Raised when the password can't be deleted. - """ - -class InitError(Exception): - """Raised when the keyring could not be initialised - """ - -class ExceptionRaisedContext(object): - """ - An exception-trapping context that indicates whether an exception was - raised. - """ - def __init__(self, ExpectedException=Exception): - self.ExpectedException = ExpectedException - self.exc_info = None - - def __enter__(self): - self.exc_info = object.__new__(ExceptionInfo) - return self.exc_info - - def __exit__(self, *exc_info): - self.exc_info.__init__(*exc_info) - return self.exc_info.type and issubclass( - self.exc_info.type, self.ExpectedException) - -class ExceptionInfo(object): - def __init__(self, *info): - if not info: - info = sys.exc_info() - self.type, self.value, self.traceback = info - - def __bool__(self): - """ - Return True if an exception occurred - """ - return bool(self.type) - - __nonzero__ = __bool__ diff --git a/awx/lib/site-packages/keyring/getpassbackend.py b/awx/lib/site-packages/keyring/getpassbackend.py deleted file mode 100644 index a2bce7e0e0..0000000000 --- a/awx/lib/site-packages/keyring/getpassbackend.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Specific support for getpass.""" -import getpass - -from . import core - - -def get_password(prompt='Password: ', stream=None, - service_name='Python', - username=None): - if username is None: - username = getpass.getuser() - return core.get_password(service_name, username) diff --git a/awx/lib/site-packages/keyring/http.py b/awx/lib/site-packages/keyring/http.py deleted file mode 100644 index 722b253aa0..0000000000 --- a/awx/lib/site-packages/keyring/http.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -urllib2.HTTPPasswordMgr object using the keyring, for use with the -urllib2.HTTPBasicAuthHandler. - -usage: - import urllib2 - handlers = [urllib2.HTTPBasicAuthHandler(PasswordMgr())] - urllib2.install_opener(handlers) - urllib2.urlopen(...) - -This will prompt for a password if one is required and isn't already -in the keyring. Then, it adds it to the keyring for subsequent use. -""" - -import getpass - -from . import get_password, delete_password, set_password - -class PasswordMgr(object): - def get_username(self, realm, authuri): - return getpass.getuser() - - def add_password(self, realm, authuri, password): - user = self.get_username(realm, authuri) - set_password(realm, user, password) - - def find_user_password(self, realm, authuri): - user = self.get_username(realm, authuri) - password = get_password(realm, user) - if password is None: - prompt = 'password for %(user)s@%(realm)s for '\ - '%(authuri)s: ' % vars() - password = getpass.getpass(prompt) - set_password(realm, user, password) - return user, password - - def clear_password(self, realm, authuri): - user = self.get_username(realm, authuri) - delete_password(realm, user) diff --git a/awx/lib/site-packages/keyring/py27compat.py b/awx/lib/site-packages/keyring/py27compat.py deleted file mode 100644 index dc868a7f00..0000000000 --- a/awx/lib/site-packages/keyring/py27compat.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Compatibility support for Python 2.7. Remove when Python 2.7 support is -no longer required. -""" -try: - import configparser -except ImportError: - import ConfigParser as configparser - -try: - input = raw_input -except NameError: - input = input - -try: - unicode_str = unicode -except NameError: - unicode_str = str - -try: - import cPickle as pickle -except ImportError: - import pickle - -try: - from itertools import ifilter as filter -except ImportError: - filter = filter - -# Taken from six.py -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - for slots_var in orig_vars.get('__slots__', ()): - orig_vars.pop(slots_var) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper diff --git a/awx/lib/site-packages/keyring/tests/__init__.py b/awx/lib/site-packages/keyring/tests/__init__.py deleted file mode 100644 index 14a394dce4..0000000000 --- a/awx/lib/site-packages/keyring/tests/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -import logging -import sys - -logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) diff --git a/awx/lib/site-packages/keyring/tests/backends/__init__.py b/awx/lib/site-packages/keyring/tests/backends/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keyring/tests/backends/test_Gnome.py b/awx/lib/site-packages/keyring/tests/backends/test_Gnome.py deleted file mode 100644 index e5a187d810..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_Gnome.py +++ /dev/null @@ -1,53 +0,0 @@ -import types -import sys - -from ..py30compat import unittest -from ..test_backend import BackendBasicTests -from ..util import Environ, NoNoneDictMutator -from keyring.backends import Gnome - - -def ImportBlesser(*names, **changes): - """A context manager to temporarily make it possible to import a module""" - for name in names: - changes[name] = types.ModuleType(name) - return NoNoneDictMutator(sys.modules, **changes) - - -@unittest.skipUnless(Gnome.Keyring.viable, "Need GnomeKeyring") -class GnomeKeyringTestCase(BackendBasicTests, unittest.TestCase): - - def environ(self): - return dict(DISPLAY='1', - DBUS_SESSION_BUS_ADDRESS='1') - - def init_keyring(self): - k = Gnome.Keyring() - - # Store passwords in the session (in-memory) keyring for the tests. This - # is going to be automatically cleared when the user logoff. - k.KEYRING_NAME = 'session' - - return k - - def test_supported(self): - with ImportBlesser('gi.repository'): - with Environ(**self.environ()): - self.assertTrue(Gnome.Keyring.viable) - - def test_supported_no_module(self): - with NoNoneDictMutator(Gnome.__dict__, GnomeKeyring=None): - with Environ(**self.environ()): - self.assertFalse(Gnome.Keyring.viable) - - def test_supported_no_display(self): - environ = self.environ() - environ['DISPLAY'] = None - with Environ(**environ): - self.assertFalse(Gnome.Keyring.viable) - - def test_supported_no_session(self): - environ = self.environ() - environ['DBUS_SESSION_BUS_ADDRESS'] = None - with Environ(**environ): - self.assertFalse(Gnome.Keyring.viable) diff --git a/awx/lib/site-packages/keyring/tests/backends/test_Google.py b/awx/lib/site-packages/keyring/tests/backends/test_Google.py deleted file mode 100644 index 955a18169d..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_Google.py +++ /dev/null @@ -1,331 +0,0 @@ -import codecs -import base64 - -from ..py30compat import unittest -from ..test_backend import BackendBasicTests -from keyring.backends import Google -from keyring.credentials import SimpleCredential -from keyring.backend import NullCrypter -from keyring import errors -from keyring.py27compat import input, pickle -from .. import mocks - -def is_gdata_supported(): - try: - __import__('gdata.service') - except ImportError: - return False - return True - -def init_google_docs_keyring(client, can_create=True, - input_getter=input): - credentials = SimpleCredential('foo', 'bar') - return Google.DocsKeyring(credentials, - 'test_src', - NullCrypter(), - client=client, - can_create=can_create, - input_getter=input_getter - ) - -@unittest.skipUnless(is_gdata_supported(), - "Need Google Docs (gdata)") -class GoogleDocsKeyringTestCase(BackendBasicTests, unittest.TestCase): - """Run all the standard tests on a new keyring""" - - def init_keyring(self): - client = mocks.MockDocumentService() - client.SetClientLoginToken('foo') - return init_google_docs_keyring(client) - -@unittest.skipUnless(is_gdata_supported(), - "Need Google Docs (gdata)") -class GoogleDocsKeyringInteractionTestCase(unittest.TestCase): - """Additional tests for Google Doc interactions""" - - def _init_client(self, set_token=True): - client = mocks.MockDocumentService() - if set_token: - client.SetClientLoginToken('interaction') - return client - - def _init_keyring(self, client): - self.keyring = init_google_docs_keyring(client) - - def _init_listfeed(self): - listfeed = mocks.MockListFeed() - listfeed._entry = [mocks.MockDocumentListEntry(), - mocks.MockDocumentListEntry() - ] - return listfeed - - def _encode_data(self, data): - return base64.urlsafe_b64encode(pickle.dumps(data)) - - def test_handles_auth_failure(self): - import gdata - client = self._init_client(set_token=False) - client._login_err = gdata.service.BadAuthentication - self._init_keyring(client) - with self.assertRaises(errors.InitError): - self.keyring.client - - def test_handles_auth_error(self): - import gdata - client = self._init_client(set_token=False) - client._login_err = gdata.service.Error - self._init_keyring(client) - with self.assertRaises(errors.InitError): - self.keyring.client - - def test_handles_login_captcha(self): - import gdata - client = self._init_client(set_token=False) - client._login_err = gdata.service.CaptchaRequired - client.captcha_url = 'a_captcha_url' - client.captcha_token = 'token' - self.get_input_called = False - def _get_input(prompt): - self.get_input_called = True - delattr(client, '_login_err') - return 'Foo' - self.keyring = init_google_docs_keyring(client, input_getter=_get_input) - self.keyring.client - self.assertTrue(self.get_input_called, 'Should have got input') - - def test_retrieves_existing_keyring_with_and_without_bom(self): - client = self._init_client() - dummy_entries = dict(section1=dict(user1='pwd1')) - no_utf8_bom_entries = self._encode_data(dummy_entries) - client._request_response = dict(status=200, data=no_utf8_bom_entries) - client._listfeed = self._init_listfeed() - self._init_keyring(client) - self.assertEqual(self.keyring.get_password('section1', 'user1'), 'pwd1') - - utf8_bom_entries = codecs.BOM_UTF8 + no_utf8_bom_entries - client._request_response = dict(status=200, data=utf8_bom_entries) - self._init_keyring(client) - self.assertEqual(self.keyring.get_password('section1', 'user1'), 'pwd1') - - def test_handles_retrieve_failure(self): - client = self._init_client() - client._listfeed = self._init_listfeed() - client._request_response = dict(status=400, - reason='Data centre explosion') - self._init_keyring(client) - self.assertRaises(errors.InitError, self.keyring.get_password, 'any', 'thing') - - def test_handles_corrupt_retrieve(self): - client = self._init_client() - dummy_entries = dict(section1=dict(user1='pwd1')) - client._request_response = dict(status=200, data='broken' + self._encode_data(dummy_entries)) - client._listfeed = self._init_listfeed() - self._init_keyring(client) - self.assertRaises(errors.InitError, self.keyring.get_password, 'any', 'thing') - - def test_no_create_if_requested(self): - client = self._init_client() - self.keyring = init_google_docs_keyring(client, can_create=False) - self.assertRaises(errors.InitError, self.keyring.get_password, 'any', 'thing') - - def test_no_set_if_create_folder_fails_on_new_keyring(self): - import gdata - client = self._init_client() - client._create_folder_err = gdata.service.RequestError - self._init_keyring(client) - self.assertEqual(self.keyring.get_password('service-a', 'user-A'), None, - 'No password should be set in new keyring') - self.assertRaises(errors.PasswordSetError, self.keyring.set_password, - 'service-a', 'user-A', 'password-A') - self.assertEqual(self.keyring.get_password('service-a', 'user-A'), None, - 'No password should be set after write fail') - - def test_no_set_if_write_fails_on_new_keyring(self): - import gdata - client = self._init_client() - client._upload_err = gdata.service.RequestError - self._init_keyring(client) - self.assertEqual(self.keyring.get_password('service-a', 'user-A'), None, - 'No password should be set in new keyring') - self.assertRaises(errors.PasswordSetError, self.keyring.set_password, - 'service-a', 'user-A', 'password-A') - self.assertEqual(self.keyring.get_password('service-a', 'user-A'), None, - 'No password should be set after write fail') - - def test_no_set_if_write_fails_on_existing_keyring(self): - import gdata - client = self._init_client() - dummy_entries = dict(sectionB=dict(user9='pwd9')) - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - client._put_err = gdata.service.RequestError - client._listfeed = self._init_listfeed() - self._init_keyring(client) - self.assertEqual(self.keyring.get_password('sectionB', 'user9'), 'pwd9', - 'Correct password should be set in existing keyring') - self.assertRaises(errors.PasswordSetError, self.keyring.set_password, - 'sectionB', 'user9', 'Not the same pwd') - self.assertEqual(self.keyring.get_password('sectionB', 'user9'), 'pwd9', - 'Password should be unchanged after write fail') - - def test_writes_correct_data_to_google_docs(self): - client = self._init_client() - dummy_entries = dict(sectionWriteChk=dict(userWriteChk='pwd')) - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - client._listfeed = self._init_listfeed() - self._init_keyring(client) - self.keyring.set_password('sectionWriteChk', - 'userWritechk', - 'new_pwd') - self.assertIsNotNone(client._put_data, 'Should have written data') - self.assertEquals( - 'new_pwd', - client._put_data.get('sectionWriteChk').get('userWritechk'), - 'Did not write updated password!') - - def test_handles_write_conflict_on_different_service(self): - import gdata - client = self._init_client() - dummy_entries = dict(sectionWriteConflictA=dict( - userwriteConflictA='pwdwriteConflictA')) - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - client._put_err = [(gdata.service.RequestError, - {'status': '406', - 'reason': 'Conflict'}),] - client._listfeed = self._init_listfeed() - self._init_keyring(client) - self.assertEqual( - self.keyring.get_password('sectionWriteConflictA', - 'userwriteConflictA'), - 'pwdwriteConflictA', - 'Correct password should be set in existing keyring') - dummy_entries['diffSection'] = dict(foo='bar') - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - new_pwd = 'Not the same pwd' - self.keyring.set_password('sectionWriteConflictA', - 'userwriteConflictA', - new_pwd) - - self.assertEquals(self.keyring.get_password('sectionWriteConflictA', - 'userwriteConflictA'), - new_pwd - ) - self.assertEqual(1, client._put_count, - 'Write not called after conflict resolution') - - def test_handles_write_conflict_on_same_service_and_username(self): - import gdata - client = self._init_client() - dummy_entries = dict(sectionWriteConflictB=dict( - userwriteConflictB='pwdwriteConflictB')) - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - client._put_err = (gdata.service.RequestError, - {'status': '406', - 'reason': 'Conflict'}) - client._listfeed = self._init_listfeed() - self._init_keyring(client) - self.assertEqual( - self.keyring.get_password('sectionWriteConflictB', - 'userwriteConflictB'), - 'pwdwriteConflictB', - 'Correct password should be set in existing keyring') - conflicting_dummy_entries = dict(sectionWriteConflictB=dict( - userwriteConflictB='pwdwriteConflictC')) - client._request_response = dict(status=200, data=self._encode_data(conflicting_dummy_entries)) - self.assertRaises(errors.PasswordSetError, self.keyring.set_password, - 'sectionWriteConflictB', 'userwriteConflictB', 'new_pwd') - - def test_handles_write_conflict_with_identical_change(self): - import gdata - client = self._init_client() - dummy_entries = dict(sectionWriteConflictC=dict( - userwriteConflictC='pwdwriteConflictC')) - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - client._put_err = [(gdata.service.RequestError, - {'status': '406', - 'reason': 'Conflict'}),] - client._listfeed = self._init_listfeed() - self._init_keyring(client) - self.assertEqual( - self.keyring.get_password('sectionWriteConflictC', - 'userwriteConflictC'), - 'pwdwriteConflictC', - 'Correct password should be set in existing keyring') - new_pwd = 'Not the same pwd' - conflicting_dummy_entries = dict(sectionWriteConflictC=dict( - userwriteConflictC=new_pwd)) - client._request_response = dict(status=200, data=self._encode_data(conflicting_dummy_entries)) - self.keyring.set_password('sectionWriteConflictC', - 'userwriteConflictC', - new_pwd) - self.assertEquals(self.keyring.get_password('sectionWriteConflictC', - 'userwriteConflictC'), - new_pwd - ) - - def test_handles_broken_google_put_when_non_owner_update_fails(self): - """Google Docs has a bug when putting to a non-owner - see GoogleDocsKeyring._save_keyring() - """ - import gdata - client = self._init_client() - dummy_entries = dict(sectionBrokenPut=dict( - userBrokenPut='pwdBrokenPut')) - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - client._put_err = [( - gdata.service.RequestError, - { 'status': '400', - 'body': 'Sorry, there was an error saving the file. Please try again.', - 'reason': 'Bad Request'}),] - client._listfeed = self._init_listfeed() - self._init_keyring(client) - new_pwd = 'newPwdBrokenPut' - correct_read_entries = dict(sectionBrokenPut=dict( - userBrokenPut='pwdBrokenPut')) - client._request_response = dict(status=200, - data=self._encode_data(correct_read_entries)) - self.assertRaises(errors.PasswordSetError, self.keyring.set_password, - 'sectionBrokenPut', 'userBrokenPut', new_pwd) - - def test_handles_broken_google_put_when_non_owner_update(self): - """Google Docs has a bug when putting to a non-owner - see GoogleDocsKeyring._save_keyring() - """ - import gdata - client = self._init_client() - dummy_entries = dict(sectionBrokenPut=dict( - userBrokenPut='pwdBrokenPut')) - client._request_response = dict(status=200, data=self._encode_data(dummy_entries)) - client._put_err = [( - gdata.service.RequestError, - { 'status': '400', - 'body': 'Sorry, there was an error saving the file. Please try again.', - 'reason': 'Bad Request'}),] - client._listfeed = self._init_listfeed() - self._init_keyring(client) - new_pwd = 'newPwdBrokenPut' - correct_read_entries = dict(sectionBrokenPut=dict( - userBrokenPut=new_pwd)) - client._request_response = dict(status=200, - data=self._encode_data(correct_read_entries)) - self.keyring.set_password('sectionBrokenPut', - 'userBrokenPut', - new_pwd) - self.assertEquals(self.keyring.get_password('sectionBrokenPut', - 'userBrokenPut'), - new_pwd) - - def test_uses_existing_folder(self): - import gdata - client = self._init_client() - # should not happen - client._create_folder_err = gdata.service.RequestError - - self._init_keyring(client) - self.assertEqual(self.keyring.get_password('service-a', 'user-A'), None, - 'No password should be set in new keyring') - client._listfeed = self._init_listfeed() - self.keyring.set_password('service-a', 'user-A', 'password-A') - self.assertIsNotNone(client._upload_data, 'Should have written data') - self.assertEqual(self.keyring.get_password('service-a', 'user-A'), - 'password-A', - 'Correct password should be set') diff --git a/awx/lib/site-packages/keyring/tests/backends/test_OS_X.py b/awx/lib/site-packages/keyring/tests/backends/test_OS_X.py deleted file mode 100644 index 28eccc7050..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_OS_X.py +++ /dev/null @@ -1,25 +0,0 @@ -import sys - -from ..test_backend import BackendBasicTests -from ..py30compat import unittest -from keyring.backends import OS_X - -def is_osx_keychain_supported(): - return sys.platform in ('mac','darwin') - -@unittest.skipUnless(is_osx_keychain_supported(), - "Need OS X") -class OSXKeychainTestCase(BackendBasicTests, unittest.TestCase): - - def init_keyring(self): - return OS_X.Keyring() - - @unittest.expectedFailure - def test_delete_present(self): - """Not implemented""" - super(OSXKeychainTestCase, self).test_delete_present() - -class SecurityCommandTestCase(unittest.TestCase): - def test_SecurityCommand(self): - self.assertEqual(OS_X.SecurityCommand('get'), 'get-generic-password') - self.assertEqual(OS_X.SecurityCommand('set', 'internet'), 'set-internet-password') diff --git a/awx/lib/site-packages/keyring/tests/backends/test_SecretService.py b/awx/lib/site-packages/keyring/tests/backends/test_SecretService.py deleted file mode 100644 index c4ae738d27..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_SecretService.py +++ /dev/null @@ -1,22 +0,0 @@ -from ..py30compat import unittest -from ..test_backend import BackendBasicTests -from keyring.backends import SecretService -from .. import util - -@unittest.skipUnless(SecretService.Keyring.viable, - "SecretStorage package is needed for SecretServiceKeyring") -class SecretServiceKeyringTestCase(BackendBasicTests, unittest.TestCase): - __test__ = True - - def init_keyring(self): - print("Testing SecretServiceKeyring; the following " - "password prompts are for this keyring") - return SecretService.Keyring() - -class SecretServiceKeyringUnitTests(unittest.TestCase): - def test_supported_no_secretstorage(self): - """ - SecretService Keyring is not viable if secretstorage can't be imported. - """ - with util.NoNoneDictMutator(SecretService.__dict__, secretstorage=None): - self.assertFalse(SecretService.Keyring.viable) diff --git a/awx/lib/site-packages/keyring/tests/backends/test_Windows.py b/awx/lib/site-packages/keyring/tests/backends/test_Windows.py deleted file mode 100644 index e2eec3a78a..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_Windows.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import print_function - -import sys - -from ..py30compat import unittest - -import keyring.backends.Windows -from ..test_backend import BackendBasicTests -from .test_file import FileKeyringTests - -def is_win32_crypto_supported(): - try: - __import__('keyring.backends._win_crypto') - except ImportError: - return False - return sys.platform in ['win32'] and sys.getwindowsversion()[-2] == 2 - -def is_winvault_supported(): - try: - __import__('win32cred') - has_pywin32 = True - except ImportError: - has_pywin32 = False - return ( - sys.platform in ['win32'] and sys.getwindowsversion().major >= 6 - and has_pywin32 - ) - - -@unittest.skipUnless(is_win32_crypto_supported(), - "Need Windows") -class Win32CryptoKeyringTestCase(FileKeyringTests, unittest.TestCase): - - def init_keyring(self): - return keyring.backends.Windows.EncryptedKeyring() - - -@unittest.skipUnless(is_winvault_supported(), - "Need WinVault") -class WinVaultKeyringTestCase(BackendBasicTests, unittest.TestCase): - def tearDown(self): - # clean up any credentials created - for cred in self.credentials_created: - try: - self.keyring.delete_password(*cred) - except Exception as e: - print(e, file=sys.stderr) - - def init_keyring(self): - return keyring.backends.Windows.WinVaultKeyring() - - -@unittest.skipUnless(keyring.backends.Windows.RegistryKeyring.viable - and sys.version_info > (3,), "RegistryKeyring not viable") -class RegistryKeyringTestCase(BackendBasicTests, unittest.TestCase): - def tearDown(self): - # clean up any credentials created - for cred in self.credentials_created: - try: - self.keyring.delete_password(*cred) - except Exception as e: - print(e, file=sys.stderr) - - def init_keyring(self): - return keyring.backends.Windows.RegistryKeyring() diff --git a/awx/lib/site-packages/keyring/tests/backends/test_crypto.py b/awx/lib/site-packages/keyring/tests/backends/test_crypto.py deleted file mode 100644 index ae7b581aca..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_crypto.py +++ /dev/null @@ -1,32 +0,0 @@ -import mock - -from ..py30compat import unittest -from .test_file import FileKeyringTests - -from keyring.backends import file - -def is_crypto_supported(): - try: - __import__('Crypto.Cipher.AES') - __import__('Crypto.Protocol.KDF') - __import__('Crypto.Random') - except ImportError: - return False - return True - - -@unittest.skipUnless(is_crypto_supported(), - "Need Crypto module") -class CryptedFileKeyringTestCase(FileKeyringTests, unittest.TestCase): - - def setUp(self): - super(self.__class__, self).setUp() - fake_getpass = mock.Mock(return_value='abcdef') - self.patcher = mock.patch('getpass.getpass', fake_getpass) - self.patcher.start() - - def tearDown(self): - self.patcher.stop() - - def init_keyring(self): - return file.EncryptedKeyring() diff --git a/awx/lib/site-packages/keyring/tests/backends/test_file.py b/awx/lib/site-packages/keyring/tests/backends/test_file.py deleted file mode 100644 index e27db941fe..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_file.py +++ /dev/null @@ -1,53 +0,0 @@ -import os -import tempfile -import sys -import errno - -from ..py30compat import unittest - -from ..test_backend import BackendBasicTests -from ..util import random_string - -from keyring.backends import file - -class FileKeyringTests(BackendBasicTests): - - def setUp(self): - super(FileKeyringTests, self).setUp() - self.keyring = self.init_keyring() - self.keyring.file_path = self.tmp_keyring_file = tempfile.mktemp() - - def tearDown(self): - try: - os.unlink(self.tmp_keyring_file) - except (OSError,): - e = sys.exc_info()[1] - if e.errno != errno.ENOENT: # No such file or directory - raise - - def test_encrypt_decrypt(self): - password = random_string(20) - # keyring.encrypt expects bytes - password = password.encode('utf-8') - encrypted = self.keyring.encrypt(password) - - self.assertEqual(password, self.keyring.decrypt(encrypted)) - - -class UncryptedFileKeyringTestCase(FileKeyringTests, unittest.TestCase): - - def init_keyring(self): - return file.PlaintextKeyring() - - @unittest.skipIf(sys.platform == 'win32', - "Group/World permissions aren't meaningful on Windows") - def test_keyring_not_created_world_writable(self): - """ - Ensure that when keyring creates the file that it's not overly- - permissive. - """ - self.keyring.set_password('system', 'user', 'password') - - self.assertTrue(os.path.exists(self.keyring.file_path)) - group_other_perms = os.stat(self.keyring.file_path).st_mode & 0o077 - self.assertEqual(group_other_perms, 0) diff --git a/awx/lib/site-packages/keyring/tests/backends/test_keyczar.py b/awx/lib/site-packages/keyring/tests/backends/test_keyczar.py deleted file mode 100644 index d83f20c41a..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_keyczar.py +++ /dev/null @@ -1,77 +0,0 @@ -import os - -from ..py30compat import unittest - -from keyring.backends import keyczar -from .. import mocks - -def is_keyczar_supported(): - return hasattr(keyczar, 'keyczar') - -@unittest.skipUnless(is_keyczar_supported(), - "Need Keyczar") -class KeyczarCrypterTestCase(unittest.TestCase): - - """Test the keyczar crypter""" - - def setUp(self): - self._orig_keyczar = keyczar.keyczar - keyczar.keyczar = mocks.MockKeyczar() - - def tearDown(self): - keyczar.keyczar = self._orig_keyczar - if keyczar.EnvironCrypter.KEYSET_ENV_VAR in os.environ: - del os.environ[keyczar.EnvironCrypter.KEYSET_ENV_VAR] - if keyczar.EnvironCrypter.ENC_KEYSET_ENV_VAR in os.environ: - del os.environ[keyczar.EnvironCrypter.ENC_KEYSET_ENV_VAR] - - def testKeyczarCrypterWithUnencryptedReader(self): - """ - """ - location = 'bar://baz' - kz_crypter = keyczar.Crypter(location) - self.assertEquals(location, kz_crypter.keyset_location) - self.assertIsNone(kz_crypter.encrypting_keyset_location) - self.assertIsInstance(kz_crypter.crypter, mocks.MockKeyczarCrypter) - self.assertIsInstance(kz_crypter.crypter.reader, mocks.MockKeyczarReader) - self.assertEquals(location, kz_crypter.crypter.reader.location) - - def testKeyczarCrypterWithEncryptedReader(self): - """ - """ - location = 'foo://baz' - encrypting_location = 'castle://aaargh' - kz_crypter = keyczar.Crypter(location, encrypting_location) - self.assertEquals(location, kz_crypter.keyset_location) - self.assertEquals(encrypting_location, - kz_crypter.encrypting_keyset_location) - self.assertIsInstance(kz_crypter.crypter, mocks.MockKeyczarCrypter) - self.assertIsInstance(kz_crypter.crypter.reader, - mocks.MockKeyczarEncryptedReader) - self.assertEquals(location, kz_crypter.crypter.reader._reader.location) - self.assertEquals(encrypting_location, - kz_crypter.crypter.reader._crypter.reader.location) - - def testKeyczarCrypterEncryptDecryptHandlesEmptyNone(self): - location = 'castle://aargh' - kz_crypter = keyczar.Crypter(location) - self.assertEquals('', kz_crypter.encrypt('')) - self.assertEquals('', kz_crypter.encrypt(None)) - self.assertEquals('', kz_crypter.decrypt('')) - self.assertEquals('', kz_crypter.decrypt(None)) - - def testEnvironCrypterReadsCorrectValues(self): - location = 'foo://baz' - encrypting_location = 'castle://aaargh' - kz_crypter = keyczar.EnvironCrypter() - os.environ[kz_crypter.KEYSET_ENV_VAR] = location - self.assertEqual(location, kz_crypter.keyset_location) - self.assertIsNone(kz_crypter.encrypting_keyset_location) - os.environ[kz_crypter.ENC_KEYSET_ENV_VAR] = encrypting_location - self.assertEqual(encrypting_location, kz_crypter.encrypting_keyset_location) - - def testEnvironCrypterThrowsExceptionOnMissingValues(self): - kz_crypter = keyczar.EnvironCrypter() - with self.assertRaises(ValueError): - kz_crypter.keyset_location - self.assertIsNone(kz_crypter.encrypting_keyset_location) diff --git a/awx/lib/site-packages/keyring/tests/backends/test_kwallet.py b/awx/lib/site-packages/keyring/tests/backends/test_kwallet.py deleted file mode 100644 index f55f93a763..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_kwallet.py +++ /dev/null @@ -1,81 +0,0 @@ -from ..py30compat import unittest - -from keyring.backends import kwallet -from ..test_backend import BackendBasicTests - -def is_qt4_supported(): - try: - __import__('PyQt4.QtGui') - except ImportError: - return False - return True - -@unittest.skipUnless(kwallet.Keyring.viable, "Need KWallet") -class KDEKWalletTestCase(BackendBasicTests, unittest.TestCase): - - def init_keyring(self): - return kwallet.Keyring() - - -class UnOpenableKWallet(object): - """A module-like object used to test KDE wallet fall-back.""" - - Synchronous = None - - def openWallet(self, *args): - return None - - def NetworkWallet(self): - return None - - -class FauxQtGui(object): - """A fake module-like object used in testing the open_kwallet function.""" - - class qApp: - @staticmethod - def instance(): - pass - - class QApplication(object): - def __init__(self, *args): - pass - - def exit(self): - pass - - class QWidget(object): - def __init__(self, *args): - pass - - def winId(self): - pass - -class KDEWalletCanceledTestCase(unittest.TestCase): - - def test_user_canceled(self): - # If the user cancels either the "enter your password to unlock the - # keyring" dialog or clicks "deny" on the "can this application access - # the wallet" dialog then openWallet() will return None. The - # open_wallet() function should handle that eventuality by returning - # None to signify that the KWallet backend is not available. - self.assertEqual( - kwallet.open_kwallet(UnOpenableKWallet(), FauxQtGui()), - None) - - -@unittest.skipUnless(kwallet.Keyring.viable and - is_qt4_supported(), - "Need KWallet and Qt4") -class KDEKWalletInQApplication(unittest.TestCase): - def test_QApplication(self): - try: - from PyKDE4.kdeui import KWallet - from PyQt4.QtGui import QApplication - except: - return - - app = QApplication([]) - wallet = kwallet.open_kwallet() - self.assertIsInstance(wallet, KWallet.Wallet) - app.exit() diff --git a/awx/lib/site-packages/keyring/tests/backends/test_multi.py b/awx/lib/site-packages/keyring/tests/backends/test_multi.py deleted file mode 100644 index 080a366b23..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_multi.py +++ /dev/null @@ -1,58 +0,0 @@ -from ..py30compat import unittest - -from keyring.backend import KeyringBackend -from keyring.backends import multi -import keyring.errors - -class MultipartKeyringWrapperTestCase(unittest.TestCase): - - """Test the wrapper that breaks passwords into smaller chunks""" - - class MockKeyring(KeyringBackend): - - priority = 1 - - def __init__(self): - self.passwords = {} - - def get_password(self, service, username): - return self.passwords.get(service+username) - - def set_password(self, service, username, password): - self.passwords[service+username] = password - - def delete_password(self, service, username): - try: - del self.passwords[service+username] - except KeyError: - raise keyring.errors.PasswordDeleteError('not found') - - def testViablePassThru(self): - kr = multi.MultipartKeyringWrapper(self.MockKeyring()) - self.assertTrue(kr.viable) - - def testMissingPassword(self): - wrapped_kr = self.MockKeyring() - kr = multi.MultipartKeyringWrapper(wrapped_kr) - self.assertIsNone(kr.get_password('s1', 'u1')) - - def testSmallPasswordSetInSinglePart(self): - wrapped_kr = self.MockKeyring() - kr = multi.MultipartKeyringWrapper(wrapped_kr) - kr.set_password('s1', 'u1', 'p1') - self.assertEquals(wrapped_kr.passwords, {'s1u1':'p1'}) - # should be able to read it back - self.assertEquals(kr.get_password('s1', 'u1'), 'p1') - - def testLargePasswordSetInMultipleParts(self): - wrapped_kr = self.MockKeyring() - kr = multi.MultipartKeyringWrapper(wrapped_kr, - max_password_size=2) - kr.set_password('s2', 'u2', '0123456') - self.assertEquals(wrapped_kr.passwords, {'s2u2':'01', - 's2u2{{part_1}}':'23', - 's2u2{{part_2}}':'45', - "s2u2{{part_3}}":'6'}) - - # should be able to read it back - self.assertEquals(kr.get_password('s2', 'u2'), '0123456') diff --git a/awx/lib/site-packages/keyring/tests/backends/test_pyfs.py b/awx/lib/site-packages/keyring/tests/backends/test_pyfs.py deleted file mode 100644 index 7ed0eb473d..0000000000 --- a/awx/lib/site-packages/keyring/tests/backends/test_pyfs.py +++ /dev/null @@ -1,130 +0,0 @@ -import os -import tempfile - -from ..py30compat import unittest - -import keyring.backend -from keyring.backends import pyfs -from ..test_backend import BackendBasicTests, random_string - - -class ReverseCrypter(keyring.backend.Crypter): - """Very silly crypter class""" - - def encrypt(self, value): - return value[::-1] - - def decrypt(self, value): - return value[::-1] - -class PyfilesystemKeyringTests(BackendBasicTests): - """Base class for Pyfilesystem tests""" - - def setUp(self): - super(PyfilesystemKeyringTests, self).setUp() - self.keyring = self.init_keyring() - - def tearDown(self): - del self.keyring - - def test_encrypt_decrypt(self): - password = random_string(20) - encrypted = self.keyring.encrypt(password) - - self.assertEqual(password, self.keyring.decrypt(encrypted)) - -@unittest.skipUnless(pyfs.BasicKeyring.viable, "Need Pyfilesystem") -class UnencryptedMemoryPyfilesystemKeyringNoSubDirTestCase( - PyfilesystemKeyringTests, unittest.TestCase): - """Test in memory with no encryption""" - - keyring_filename = 'mem://unencrypted' - - def init_keyring(self): - return keyring.backends.pyfs.PlaintextKeyring( - filename=self.keyring_filename) - -@unittest.skipUnless(pyfs.BasicKeyring.viable, "Need Pyfilesystem") -class UnencryptedMemoryPyfilesystemKeyringSubDirTestCase( - PyfilesystemKeyringTests, unittest.TestCase): - """Test in memory with no encryption""" - - keyring_filename = 'mem://some/sub/dir/unencrypted' - - def init_keyring(self): - return keyring.backends.pyfs.PlaintextKeyring( - filename=self.keyring_filename) - -@unittest.skipUnless(pyfs.BasicKeyring.viable, "Need Pyfilesystem") -class UnencryptedLocalPyfilesystemKeyringNoSubDirTestCase( - PyfilesystemKeyringTests, unittest.TestCase): - """Test using local temp files with no encryption""" - - keyring_filename = '%s/keyring.cfg' %tempfile.mkdtemp() - - def init_keyring(self): - return keyring.backends.pyfs.PlaintextKeyring( - filename=self.keyring_filename) - - def test_handles_preexisting_keyring(self): - from fs.opener import opener - fs, path = opener.parse(self.keyring_filename, writeable=True) - keyring_file = fs.open(path, 'wb') - keyring_file.write( - """[svc1] -user1 = cHdkMQ== - """) - keyring_file.close() - pyf_keyring = keyring.backends.pyfs.PlaintextKeyring( - filename=self.keyring_filename) - self.assertEquals('pwd1', pyf_keyring.get_password('svc1', 'user1')) - - def tearDown(self): - del self.keyring - if os.path.exists(self.keyring_filename): - os.remove(self.keyring_filename) - -@unittest.skipUnless(pyfs.BasicKeyring.viable, "Need Pyfilesystem") -class UnencryptedLocalPyfilesystemKeyringSubDirTestCase( - PyfilesystemKeyringTests, unittest.TestCase): - """Test using local temp files with no encryption""" - - keyring_dir = os.path.join(tempfile.mkdtemp(), 'more', 'sub', 'dirs') - keyring_filename = os.path.join(keyring_dir, 'keyring.cfg') - - def init_keyring(self): - - if not os.path.exists(self.keyring_dir): - os.makedirs(self.keyring_dir) - return keyring.backends.pyfs.PlaintextKeyring( - filename=self.keyring_filename) - -@unittest.skipUnless(pyfs.BasicKeyring.viable, "Need Pyfilesystem") -class EncryptedMemoryPyfilesystemKeyringTestCase(PyfilesystemKeyringTests, - unittest.TestCase): - """Test in memory with encryption""" - - def init_keyring(self): - return keyring.backends.pyfs.EncryptedKeyring( - ReverseCrypter(), - filename='mem://encrypted/keyring.cfg') - -@unittest.skipUnless(pyfs.BasicKeyring.viable, "Need Pyfilesystem") -class EncryptedLocalPyfilesystemKeyringNoSubDirTestCase( - PyfilesystemKeyringTests, unittest.TestCase): - """Test using local temp files with encryption""" - - def init_keyring(self): - return keyring.backends.pyfs.EncryptedKeyring( - ReverseCrypter(), - filename='temp://keyring.cfg') - -@unittest.skipUnless(pyfs.BasicKeyring.viable, "Need Pyfilesystem") -class EncryptedLocalPyfilesystemKeyringSubDirTestCase( - PyfilesystemKeyringTests, unittest.TestCase): - """Test using local temp files with encryption""" - - def init_keyring(self): - return keyring.backends.pyfs.EncryptedKeyring( - ReverseCrypter(), - filename='temp://a/sub/dir/hierarchy/keyring.cfg') diff --git a/awx/lib/site-packages/keyring/tests/mocks.py b/awx/lib/site-packages/keyring/tests/mocks.py deleted file mode 100644 index 0dd53372a2..0000000000 --- a/awx/lib/site-packages/keyring/tests/mocks.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -mocks.py - -Various mock objects for testing -""" - -import base64 -from keyring.py27compat import pickle, unicode_str -try: - from StringIO import StringIO -except ImportError: # For Python 3 - from io import StringIO - -class MockAtom(object): - """ Mocks an atom in the GData service. """ - def __init__(self, value): - self.text = value - -class MockEntry(object): - """ Mocks and entry returned from the GData service. """ - def __init__(self, title, ID): - self.title = MockAtom(title) - self.id = MockAtom('http://mock.example.com/%s' % ID) - self.ID = ID # simpler lookup for key value - - def GetEditMediaLink(self): - return MockLink() - - -class MockHTTPClient(object): - """ Mocks the functionality of an http client. """ - def request(*args, **kwargs): - pass - -class MockGDataService(object): - """ Provides the common functionality of a Google Service. """ - http_client = MockHTTPClient() - def __init__(self, email=None, password=None, - account_type='HOSTED_OR_GOOGLE', service=None, - auth_service_url=None, source=None, server=None, - additional_headers=None, handler=None, tokens=None, - http_client=None, token_store=None): - """ Create the Service with the default parameters. """ - self.email = email - self.password = password - self.account_type = account_type - self.service = service - self.auth_service_url = auth_service_url - self.server = server - self.login_token = None - - def GetClientLoginToken(self): - return self.login_token - - def SetClientLoginToken(self, token): - self.login_token = token - - def ClientLogin(self, username, password, account_type=None, service=None, - auth_service_url=None, source=None, captcha_token=None, - captcha_response=None): - - """ Client side login to the service. """ - if hasattr(self, '_login_err'): - raise self._login_err() - -class MockDocumentService(MockGDataService): - """ - Implements the minimum functionality of the Google Document service. - """ - - def Upload(self, media_source, title, folder_or_uri=None, label=None): - """ - Upload a document. - """ - if hasattr(self, '_upload_err'): - raise self._upload_err() - if not hasattr(self, '_upload_count'): - self._upload_count = 0 - # save the data for asserting against - self._upload_data = dict(media_source=media_source, title=title, - folder_or_uri=folder_or_uri, label=label) - self._upload_count += 1 - return MockEntry(title, 'mockentry%3A' + title) - - def QueryDocumentListFeed(self, uri): - if hasattr(self, '_listfeed'): - return self._listfeed - return MockListFeed() - - def CreateFolder(self, title, folder_or_uri=None): - if hasattr(self, '_create_folder_err'): - raise self._create_folder_err() - if hasattr(self, '_create_folder'): - return self._create_folder - return MockListEntry() - - def Put(self, data, uri, extra_headers=None, url_params=None, - escape_params=True, redirects_remaining=3, media_source=None, - converter=None): - self._put_data = None - if not hasattr(self, '_put_count'): - self._put_count = 0 - if hasattr(self, '_put_err'): - # allow for a list of errors - if type(self._put_err) == list: - put_err = self._put_err.pop(0) - if not len(self._put_err): - delattr(self, '_put_err') - else: - put_err = self._put_err - if type(put_err) == tuple: - raise put_err[0](put_err[1]) - else: - raise put_err() - # save the data for asserting against - assert isinstance(data, str) or isinstance(data, unicode_str), \ - 'Should be a string' - self._put_data = pickle.loads(base64.urlsafe_b64decode(data)) - self._put_count += 1 - return MockEntry('', 'mockentry%3A' + '') - - def Export(self, entry_or_id_or_url, file_path, gid=None, extra_params=None): - if hasattr(self, '_export_err'): - raise self._export_err() - if hasattr(self, '_export_data'): - export_file = open(file_path, 'wb') - export_file.write(self._export_data) - export_file.close() - - def request(self, data, uri): - if hasattr(self, '_request_err'): - if type(self._request_err) == tuple: - raise self._request_err[0](self._request_err[1]) - else: - raise self._request_err() - if hasattr(self, '_request_response'): - return MockHttpResponse(self._request_response) - -class MockHttpResponse(StringIO, object): - - def __init__(self, response_dict): - super(MockHttpResponse, self).__init__(response_dict.get('data', '')) - self.status = response_dict.get('status', 200) - self.reason = response_dict.get('reason', '') - -class MockListFeed(object): - - @property - def entry(self): - if hasattr(self, '_entry'): - return self._entry - return [] - -class MockListEntry(object): - - pass - -class MockLink(object): - - @property - def href(self): - return '' - -class MockContent(object): - - @property - def src(self): - return 'src' - -class MockDocumentListEntry(object): - - @property - def content(self): - return MockContent() - - def GetEditMediaLink(self): - return MockLink() - -class MockKeyczarReader(object): - - def __init__(self, location): - self.location = location - -class MockKeyczarEncryptedReader(object): - - def __init__(self, reader, crypter): - self._reader = reader - self._crypter = crypter - -class MockKeyczarReaders(object): - - @staticmethod - def CreateReader(location): - return MockKeyczarReader(location) - - @staticmethod - def EncryptedReader(reader, crypter): - return MockKeyczarEncryptedReader(reader, crypter) - -class MockKeyczarCrypter(object): - - def __init__(self, reader): - self.reader = reader - - @staticmethod - def Read(location): - return MockKeyczarCrypter(MockKeyczarReader(location)) - -class MockKeyczar(object): - - @property - def readers(self): - return MockKeyczarReaders - - @property - def Crypter(self): - return MockKeyczarCrypter diff --git a/awx/lib/site-packages/keyring/tests/py30compat.py b/awx/lib/site-packages/keyring/tests/py30compat.py deleted file mode 100644 index 4b24c7fe40..0000000000 --- a/awx/lib/site-packages/keyring/tests/py30compat.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -Compatibility support for Python 3.0. Remove when Python 3.0 support is -no longer required. -""" -import sys - -if sys.version_info < (2,7) or sys.version_info[:2] == (3,0): - import unittest2 as unittest -else: - import unittest diff --git a/awx/lib/site-packages/keyring/tests/test_XDG.py b/awx/lib/site-packages/keyring/tests/test_XDG.py deleted file mode 100644 index 2a8ae5f5bc..0000000000 --- a/awx/lib/site-packages/keyring/tests/test_XDG.py +++ /dev/null @@ -1,16 +0,0 @@ -from mock import patch - -from keyring.util import XDG - -class TestPreference: - @XDG.Preference('Unity') - def one(self): - return 1 - - @patch.dict('os.environ', XDG_CURRENT_DESKTOP='KDE') - def test_mismatch(self): - assert self.one() == 1 - - @patch.dict('os.environ', XDG_CURRENT_DESKTOP='Unity') - def test_match(self): - assert self.one() == 1.5 diff --git a/awx/lib/site-packages/keyring/tests/test_backend.py b/awx/lib/site-packages/keyring/tests/test_backend.py deleted file mode 100644 index ffed807261..0000000000 --- a/awx/lib/site-packages/keyring/tests/test_backend.py +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: utf-8 -*- -""" -test_backend.py - -Test case for keyring basic function - -created by Kang Zhang 2009-07-14 -""" -from __future__ import with_statement - -import string - -from keyring.util import escape -from .util import random_string -from keyring import errors - -DIFFICULT_CHARS = string.whitespace + string.punctuation -# unicode only characters -# Sourced from The Quick Brown Fox... Pangrams -# http://www.columbia.edu/~fdc/utf8/ -UNICODE_CHARS = escape.u( - """זהכיףסת×לשמוע×יךתנצחקרפדעץטובבגן""" - """ξεσκεπάζωτηνψυχοφθόÏαβδελυγμία""" - """СъешьжеещёÑтихмÑгкихфранцузÑкихбулокдавыпейчаю""" - """ЖълтатадюлÑбешещаÑтливачепухъткойтоцъфназамръзнакатогьон""" -) - -# ensure no-ascii chars slip by - watch your editor! -assert min(ord(char) for char in UNICODE_CHARS) > 127 - -class BackendBasicTests(object): - """Test for the keyring's basic functions. password_set and password_get - """ - - def setUp(self): - self.keyring = self.init_keyring() - self.credentials_created = set() - - def tearDown(self): - for item in self.credentials_created: - self.keyring.delete_password(*item) - - def set_password(self, service, username, password): - # set the password and save the result so the test runner can clean - # up after if necessary. - self.keyring.set_password(service, username, password) - self.credentials_created.add((service, username)) - - def check_set_get(self, service, username, password): - keyring = self.keyring - - # for the non-existent password - self.assertEqual(keyring.get_password(service, username), None) - - # common usage - self.set_password(service, username, password) - self.assertEqual(keyring.get_password(service, username), password) - - # for the empty password - self.set_password(service, username, "") - self.assertEqual(keyring.get_password(service, username), "") - - def test_password_set_get(self): - password = random_string(20) - username = random_string(20) - service = random_string(20) - self.check_set_get(service, username, password) - - def test_difficult_chars(self): - password = random_string(20, DIFFICULT_CHARS) - username = random_string(20, DIFFICULT_CHARS) - service = random_string(20, DIFFICULT_CHARS) - self.check_set_get(service, username, password) - - def test_delete_present(self): - password = random_string(20, DIFFICULT_CHARS) - username = random_string(20, DIFFICULT_CHARS) - service = random_string(20, DIFFICULT_CHARS) - self.keyring.set_password(service, username, password) - self.keyring.delete_password(service, username) - self.assertIsNone(self.keyring.get_password(service, username)) - - def test_delete_not_present(self): - username = random_string(20, DIFFICULT_CHARS) - service = random_string(20, DIFFICULT_CHARS) - self.assertRaises(errors.PasswordDeleteError, - self.keyring.delete_password, service, username) - - def test_delete_one_in_group(self): - username1 = random_string(20, DIFFICULT_CHARS) - username2 = random_string(20, DIFFICULT_CHARS) - password = random_string(20, DIFFICULT_CHARS) - service = random_string(20, DIFFICULT_CHARS) - self.keyring.set_password(service, username1, password) - self.set_password(service, username2, password) - self.keyring.delete_password(service, username1) - self.assertEqual(self.keyring.get_password( - service, username2), password) - - def test_unicode_chars(self): - password = random_string(20, UNICODE_CHARS) - username = random_string(20, UNICODE_CHARS) - service = random_string(20, UNICODE_CHARS) - self.check_set_get(service, username, password) - - def test_unicode_and_ascii_chars(self): - source = (random_string(10, UNICODE_CHARS) + random_string(10) + - random_string(10, DIFFICULT_CHARS)) - password = random_string(20, source) - username = random_string(20, source) - service = random_string(20, source) - self.check_set_get(service, username, password) - - def test_different_user(self): - """ - Issue #47 reports that WinVault isn't storing passwords for - multiple users. This test exercises that test for each of the - backends. - """ - - keyring = self.keyring - self.set_password('service1', 'user1', 'password1') - self.set_password('service1', 'user2', 'password2') - self.assertEqual(keyring.get_password('service1', 'user1'), - 'password1') - self.assertEqual(keyring.get_password('service1', 'user2'), - 'password2') - self.set_password('service2', 'user3', 'password3') - self.assertEqual(keyring.get_password('service1', 'user1'), - 'password1') diff --git a/awx/lib/site-packages/keyring/tests/test_cli.py b/awx/lib/site-packages/keyring/tests/test_cli.py deleted file mode 100644 index 74f035d71c..0000000000 --- a/awx/lib/site-packages/keyring/tests/test_cli.py +++ /dev/null @@ -1,150 +0,0 @@ -""" -Test case to access the keyring from the command line -""" - -import os.path - -from keyring.tests.py30compat import unittest - -import keyring.backend -from keyring import cli -from keyring import errors - - -class FakeKeyring(keyring.backend.KeyringBackend): - PASSWORD = "GABUZOMEUH" - - def supported(self): - return 1 - - def set_password(self, service, username, password): - pass - - def get_password(self, service, username): - return self.PASSWORD - - def delete_password(self, service, username): - pass - -class SimpleKeyring(keyring.backend.KeyringBackend): - """A very simple keyring""" - - def __init__(self): - self.pwd = {} - - def supported(self): - return 1 - - def set_password(self, service, username, password): - self.pwd[(service, username)] = password - - def get_password(self, service, username): - try: - return self.pwd[(service, username)] - except KeyError: - return None - - def delete_password(self, service, username): - try: - del self.pwd[(service, username)] - except KeyError: - raise errors.PasswordDeleteError("No key") - -class CommandLineTestCase(unittest.TestCase): - def setUp(self): - self.old_keyring = keyring.get_keyring() - - self.cli = cli.CommandLineTool() - self.cli.input_password = self.return_password - self.cli.output_password = self.save_password - self.cli.parser.error = self.mock_error - self.cli.parser.print_help = lambda: None - - keyring.set_keyring(SimpleKeyring()) - - self.password = "" - self.password_returned = None - self.last_error = None - - def tearDown(self): - keyring.set_keyring(self.old_keyring) - - def return_password(self, *args, **kwargs): - return self.password - - def save_password(self, password): - self.password_returned = password - - def mock_error(self, error): - self.last_error = error - raise SystemExit() - - def test_wrong_arguments(self): - self.assertEqual(1, self.cli.run([])) - - self.assertRaises(SystemExit, self.cli.run, ["get"]) - self.assertRaises(SystemExit, self.cli.run, ["get", "foo"]) - self.assertRaises(SystemExit, self.cli.run, - ["get", "foo", "bar", "baz"]) - - self.assertRaises(SystemExit, self.cli.run, ["set"]) - self.assertRaises(SystemExit, self.cli.run, ["set", "foo"]) - self.assertRaises(SystemExit, self.cli.run, - ["set", "foo", "bar", "baz"]) - - self.assertRaises(SystemExit, self.cli.run, ["foo", "bar", "baz"]) - - def test_get_unexistent_password(self): - self.assertEqual(1, self.cli.run(["get", "foo", "bar"])) - self.assertEqual(None, self.password_returned) - - def test_set_and_get_password(self): - self.password = "plop" - self.assertEqual(0, self.cli.run(["set", "foo", "bar"])) - self.assertEqual(0, self.cli.run(["get", "foo", "bar"])) - self.assertEqual("plop", self.password_returned) - - def test_load_builtin_backend(self): - self.assertEqual(1, self.cli.run([ - "get", - "-b", "keyring.backends.file.PlaintextKeyring", - "foo", "bar"])) - backend = keyring.get_keyring() - self.assertIsInstance(backend, - keyring.backends.file.PlaintextKeyring) - - def test_load_specific_backend_with_path(self): - keyring_path = os.path.join(os.path.dirname(keyring.__file__), 'tests') - self.assertEqual(0, self.cli.run(["get", - "-b", "test_cli.FakeKeyring", - "-p", keyring_path, - "foo", "bar"])) - - # Somehow, this doesn't work, because the full dotted name of the class - # is not the same as the one expected :( - #self.assertIsInstance(keyring.get_keyring(), FakeKeyring) - self.assertEqual(FakeKeyring.PASSWORD, self.password_returned) - - def test_load_wrong_keyrings(self): - self.assertRaises(SystemExit, self.cli.run, - ["get", "foo", "bar", - "-b", "blablabla" # ImportError - ]) - self.assertRaises(SystemExit, self.cli.run, - ["get", "foo", "bar", - "-b", "os.path.blabla" # AttributeError - ]) - self.assertRaises(SystemExit, self.cli.run, - ["get", "foo", "bar", - "-b", "__builtin__.str" # TypeError - ]) - - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(CommandLineTestCase)) - return suite - - -if __name__ == '__main__': - unittest.main(defaultTest="test_suite") diff --git a/awx/lib/site-packages/keyring/tests/test_core.py b/awx/lib/site-packages/keyring/tests/test_core.py deleted file mode 100644 index 3328ce02ce..0000000000 --- a/awx/lib/site-packages/keyring/tests/test_core.py +++ /dev/null @@ -1,130 +0,0 @@ -""" -test_core.py - -Created by Kang Zhang on 2009-08-09 -""" - -from __future__ import with_statement - -import os -import tempfile -import shutil - -import mock -import pytest - -import keyring.backend -import keyring.core -import keyring.util.platform_ -from keyring import errors - -PASSWORD_TEXT = "This is password" -PASSWORD_TEXT_2 = "This is password2" - - -@pytest.yield_fixture() -def config_filename(tmpdir): - filename = tmpdir / 'keyringrc.cfg' - with mock.patch('keyring.util.platform_.config_root', lambda: str(tmpdir)): - yield str(filename) - - -class TestKeyring(keyring.backend.KeyringBackend): - """A faked keyring for test. - """ - def __init__(self): - self.passwords = {} - - def supported(self): - return 0 - - def get_password(self, service, username): - return PASSWORD_TEXT - - def set_password(self, service, username, password): - self.passwords[(service, username)] = password - return 0 - - def delete_password(self, service, username): - try: - del self.passwords[(service, username)] - except KeyError: - raise errors.PasswordDeleteError("not set") - - -class TestKeyring2(TestKeyring): - """Another faked keyring for test. - """ - def get_password(self, service, username): - return PASSWORD_TEXT_2 - - -class TestCore: - mock_global_backend = mock.patch('keyring.core._keyring_backend') - - @mock_global_backend - def test_set_password(self, backend): - """ - set_password on the default keyring is called. - """ - keyring.core.set_password("test", "user", "passtest") - backend.set_password.assert_called_once_with('test', 'user', - 'passtest') - - @mock_global_backend - def test_get_password(self, backend): - """ - set_password on the default keyring is called. - """ - result = keyring.core.get_password("test", "user") - backend.get_password.assert_called_once_with('test', 'user') - assert result is not None - - @mock_global_backend - def test_delete_password(self, backend): - keyring.core.delete_password("test", "user") - backend.delete_password.assert_called_once_with('test', 'user') - - def test_set_keyring_in_runtime(self): - """Test the function of set keyring in runtime. - """ - keyring.core.set_keyring(TestKeyring()) - - keyring.core.set_password("test", "user", "password") - assert keyring.core.get_password("test", "user") == PASSWORD_TEXT - - def test_set_keyring_in_config(self, config_filename): - """Test setting the keyring by config file. - """ - # create the config file - with open(config_filename, 'w') as config_file: - config_file.writelines([ - "[backend]\n", - # the path for the user created keyring - "keyring-path= %s\n" % os.path.dirname(os.path.abspath(__file__)), - # the name of the keyring class - "default-keyring=test_core.TestKeyring2\n", - ]) - - # init the keyring lib, the lib will automaticlly load the - # config file and load the user defined module - keyring.core.init_backend() - - keyring.core.set_password("test", "user", "password") - assert keyring.core.get_password("test", "user") == PASSWORD_TEXT_2 - - def test_load_config_empty(self, config_filename): - "A non-existent or empty config should load" - assert keyring.core.load_config() is None - - def test_load_config_degenerate(self, config_filename): - "load_config should succeed in the absence of a backend section" - with open(config_filename, 'w') as config_file: - config_file.write('[keyring]') - assert keyring.core.load_config() is None - - def test_load_config_blank_backend(self, config_filename): - "load_config should succeed with an empty [backend] section" - with open(config_filename, 'w') as config_file: - config_file.write('[backend]') - assert keyring.core.load_config() is None diff --git a/awx/lib/site-packages/keyring/tests/test_util.py b/awx/lib/site-packages/keyring/tests/test_util.py deleted file mode 100644 index f433ad217a..0000000000 --- a/awx/lib/site-packages/keyring/tests/test_util.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -Test for simple escape/unescape routine -""" - - -from .py30compat import unittest - -from keyring.util import escape - - -class EscapeTestCase(unittest.TestCase): - - def check_escape_unescape(self, initial): - escaped = escape.escape(initial) - for c in escaped: - self.assertIn(c, escape.LEGAL_CHARS + '_') - unescaped = escape.unescape(escaped) - self.assertEqual(initial, unescaped) - - def test_escape_unescape(self): - self.check_escape_unescape("aaaa") - self.check_escape_unescape("aaaa bbbb cccc") - self.check_escape_unescape(escape.u("Zażółć gęślÄ… jaźń")) - self.check_escape_unescape("(((P{{{{'''---; ;; '\"|%^") - - def test_low_byte(self): - """ - Ensure that encoding low bytes (ordinal less than hex F) encode as - as three bytes to avoid ambiguity. For example '\n' (hex A) should - encode as '_0A' and not '_A', the latter of which - isn't matched by the inverse operation. - """ - self.check_escape_unescape('\n') - self.check_escape_unescape('\x000') - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(EscapeTestCase)) - return suite - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff --git a/awx/lib/site-packages/keyring/tests/util.py b/awx/lib/site-packages/keyring/tests/util.py deleted file mode 100644 index 1fcce03857..0000000000 --- a/awx/lib/site-packages/keyring/tests/util.py +++ /dev/null @@ -1,63 +0,0 @@ -import contextlib -import os -import sys -import random -import string - -class ImportKiller(object): - "Context manager to make an import of a given name or names fail." - def __init__(self, *names): - self.names = names - def find_module(self, fullname, path=None): - if fullname in self.names: - return self - def load_module(self, fullname): - assert fullname in self.names - raise ImportError(fullname) - def __enter__(self): - self.original = {} - for name in self.names: - self.original[name] = sys.modules.pop(name, None) - sys.meta_path.insert(0, self) - def __exit__(self, *args): - sys.meta_path.remove(self) - for key, value in self.original.items(): - if value is not None: - sys.modules[key] = value - -@contextlib.contextmanager -def NoNoneDictMutator(destination, **changes): - """Helper context manager to make and unmake changes to a dict. - - A None is not a valid value for the destination, and so means that the - associated name should be removed.""" - original = {} - for key, value in changes.items(): - original[key] = destination.get(key) - if value is None: - if key in destination: - del destination[key] - else: - destination[key] = value - yield - for key, value in original.items(): - if value is None: - if key in destination: - del destination[key] - else: - destination[key] = value - - -def Environ(**changes): - """A context manager to temporarily change the os.environ""" - return NoNoneDictMutator(os.environ, **changes) - -ALPHABET = string.ascii_letters + string.digits - -def random_string(k, source = ALPHABET): - """Generate a random string with length <i>k</i> - """ - result = '' - for i in range(0, k): - result += random.choice(source) - return result diff --git a/awx/lib/site-packages/keyring/util/XDG.py b/awx/lib/site-packages/keyring/util/XDG.py deleted file mode 100644 index 68304170b1..0000000000 --- a/awx/lib/site-packages/keyring/util/XDG.py +++ /dev/null @@ -1,25 +0,0 @@ -import os -import functools - -class Preference: - """ - A decorator wrapping a 'priority' classmethod - """ - def __init__(self, name): - """ - Create a decorator giving preference to XDG_CURRENT_DESKTOP of 'name' - """ - self.name = name - - def decorate(self, func): - self.func = func - @functools.wraps(func) - def wrapper(*args, **kwargs): - return func(*args, **kwargs) * self.multiplier - return wrapper - __call__ = decorate - - @property - def multiplier(self): - matches = os.environ.get('XDG_CURRENT_DESKTOP') == self.name - return 1.5 if matches else 1 diff --git a/awx/lib/site-packages/keyring/util/__init__.py b/awx/lib/site-packages/keyring/util/__init__.py deleted file mode 100644 index d67d8ab327..0000000000 --- a/awx/lib/site-packages/keyring/util/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -try: - import functools -except ImportError: - # functools not available until Python 2.5 - pass - -def once(func): - """ - Decorate func so it's only ever called the first time. - - This decorator can ensure that an expensive or non-idempotent function - will not be expensive on subsequent calls and is idempotent. - - >>> func = once(lambda a: a+3) - >>> func(3) - 6 - >>> func(9) - 6 - >>> func('12') - 6 - """ - def wrapper(*args, **kwargs): - if not hasattr(func, 'always_returns'): - func.always_returns = func(*args, **kwargs) - return func.always_returns - if 'functools' in globals(): - wrapper = functools.wraps(func)(wrapper) - return wrapper - -def suppress_exceptions(callables, exceptions=Exception): - """ - yield the results of calling each element of callables, suppressing - any indicated exceptions. - """ - for callable in callables: - try: - yield callable() - except exceptions: - pass diff --git a/awx/lib/site-packages/keyring/util/escape.py b/awx/lib/site-packages/keyring/util/escape.py deleted file mode 100644 index 41dd439597..0000000000 --- a/awx/lib/site-packages/keyring/util/escape.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -escape/unescape routines available for backends which need -alphanumeric usernames, services, or other values -""" - -import re -import string -import sys - -# True if we are running on Python 3. -# taken from six.py -PY3 = sys.version_info[0] == 3 - -# allow use of unicode literals -if PY3: - def u(s): - return s - def _unichr(c): - return chr(c) -else: - def u(s): - return unicode(s, "unicode_escape") - def _unichr(c): - return unichr(c) - -LEGAL_CHARS = ( - getattr(string, 'letters', None) # Python 2 - or getattr(string, 'ascii_letters') # Python 3 -) + string.digits - -ESCAPE_FMT = "_%02X" - -def _escape_char(c): - "Single char escape. Return the char, escaped if not already legal" - if isinstance(c, int): - c = _unichr(c) - return c if c in LEGAL_CHARS else ESCAPE_FMT % ord(c) - -def escape(value): - """ - Escapes given string so the result consists of alphanumeric chars and - underscore only. - """ - return "".join(_escape_char(c) for c in value.encode('utf-8')) - -def _unescape_code(regex_match): - ordinal = int(regex_match.group('code'), 16) - if sys.version_info >= (3,): - return bytes([ordinal]) - return chr(ordinal) - -def unescape(value): - """ - Inverse of escape. - """ - re_esc = re.compile( - # the pattern must be bytes to operate on bytes - ESCAPE_FMT.replace('%02X', '(?P<code>[0-9A-F]{2})').encode('ascii') - ) - return re_esc.sub(_unescape_code, value.encode('ascii')).decode('utf-8') diff --git a/awx/lib/site-packages/keyring/util/platform_.py b/awx/lib/site-packages/keyring/util/platform_.py deleted file mode 100644 index dcdffea666..0000000000 --- a/awx/lib/site-packages/keyring/util/platform_.py +++ /dev/null @@ -1,40 +0,0 @@ -from __future__ import absolute_import - -import os -import platform - -def _settings_root_XP(): - return os.path.join(os.environ['USERPROFILE'], 'Local Settings') - -def _settings_root_Vista(): - return os.environ.get('LOCALAPPDATA', os.environ.get('ProgramData', '.')) - -def _data_root_Windows(): - release, version, csd, ptype = platform.win32_ver() - root = _settings_root_XP() if release == 'XP' else _settings_root_Vista() - return os.path.join(root, 'Python Keyring') - -def _data_root_Linux(): - """ - Use freedesktop.org Base Dir Specfication to determine storage - location. - """ - fallback = os.path.expanduser('~/.local/share') - root = os.environ.get('XDG_DATA_HOME', None) or fallback - return os.path.join(root, 'python_keyring') - -_config_root_Windows = _data_root_Windows - -def _config_root_Linux(): - """ - Use freedesktop.org Base Dir Specfication to determine config - location. - """ - fallback = os.path.expanduser('~/.local/share') - key = 'XDG_DATA_HOME' # TODO: use XDG_CONFIG_HOME, ref #99. - root = os.environ.get(key, None) or fallback - return os.path.join(root, 'python_keyring') - -# by default, use Unix convention -data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux) -config_root = globals().get('_config_root' + platform.system(), _config_root_Linux) diff --git a/awx/lib/site-packages/keyring/util/properties.py b/awx/lib/site-packages/keyring/util/properties.py deleted file mode 100644 index 663204f7c3..0000000000 --- a/awx/lib/site-packages/keyring/util/properties.py +++ /dev/null @@ -1,52 +0,0 @@ -from collections import Callable - -class ClassProperty(property): - """ - An implementation of a property callable on a class. Used to decorate a - classmethod but to then treat it like a property. - - Example: - - >>> class MyClass: - ... @ClassProperty - ... @classmethod - ... def skillz(cls): - ... return cls.__name__.startswith('My') - >>> MyClass.skillz - True - >>> class YourClass(MyClass): pass - >>> YourClass.skillz - False - """ - def __get__(self, cls, owner): - return self.fget.__get__(None, owner)() - -# borrowed from jaraco.util.dictlib -class NonDataProperty(object): - """Much like the property builtin, but only implements __get__, - making it a non-data property, and can be subsequently reset. - - See http://users.rcn.com/python/download/Descriptor.htm for more - information. - - >>> class X(object): - ... @NonDataProperty - ... def foo(self): - ... return 3 - >>> x = X() - >>> x.foo - 3 - >>> x.foo = 4 - >>> x.foo - 4 - """ - - def __init__(self, fget): - assert fget is not None, "fget cannot be none" - assert isinstance(fget, Callable), "fget must be callable" - self.fget = fget - - def __get__(self, obj, objtype=None): - if obj is None: - return self - return self.fget(obj) diff --git a/awx/lib/site-packages/keystoneclient/__init__.py b/awx/lib/site-packages/keystoneclient/__init__.py deleted file mode 100644 index 2e2378b011..0000000000 --- a/awx/lib/site-packages/keystoneclient/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""The python bindings for the OpenStack Identity (Keystone) project. - -A Client object will allow you to communicate with the Identity server. The -recommended way to get a Client object is to use -:py:func:`keystoneclient.client.Client()`. :py:func:`~.Client()` uses version -discovery to create a V3 or V2 client depending on what versions the Identity -server supports and what version is requested. - -Identity V2 and V3 clients can also be created directly. See -:py:class:`keystoneclient.v3.client.Client` for the V3 client and -:py:class:`keystoneclient.v2_0.client.Client` for the V2 client. - -""" - - -import pbr.version - -__version__ = pbr.version.VersionInfo('python-keystoneclient').version_string() - diff --git a/awx/lib/site-packages/keystoneclient/_discover.py b/awx/lib/site-packages/keystoneclient/_discover.py deleted file mode 100644 index 07d0ae6c66..0000000000 --- a/awx/lib/site-packages/keystoneclient/_discover.py +++ /dev/null @@ -1,326 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""The passive components to version discovery. - -The Discover object in discover.py contains functions that can create objects -on your behalf. These functions are not usable from within the keystoneclient -library because you will get dependency resolution issues. - -The Discover object in this file provides the querying components of Discovery. -This includes functions like url_for which allow you to retrieve URLs and the -raw data specified in version discovery responses. -""" - -import logging -import re - -from keystoneclient import exceptions -from keystoneclient.i18n import _, _LI, _LW -from keystoneclient import utils - - -_LOGGER = logging.getLogger(__name__) - - -@utils.positional() -def get_version_data(session, url, authenticated=None): - """Retrieve raw version data from a url.""" - headers = {'Accept': 'application/json'} - - resp = session.get(url, headers=headers, authenticated=authenticated) - - try: - body_resp = resp.json() - except ValueError: - pass - else: - # In the event of querying a root URL we will get back a list of - # available versions. - try: - return body_resp['versions']['values'] - except (KeyError, TypeError): - pass - - # Most servers don't have a 'values' element so accept a simple - # versions dict if available. - try: - return body_resp['versions'] - except KeyError: - pass - - # Otherwise if we query an endpoint like /v2.0 then we will get back - # just the one available version. - try: - return [body_resp['version']] - except KeyError: - pass - - err_text = resp.text[:50] + '...' if len(resp.text) > 50 else resp.text - msg = _('Invalid Response - Bad version data returned: %s') % err_text - raise exceptions.DiscoveryFailure(msg) - - -def normalize_version_number(version): - """Turn a version representation into a tuple.""" - - # trim the v from a 'v2.0' or similar - try: - version = version.lstrip('v') - except AttributeError: - pass - - # if it's an integer or a numeric as a string then normalize it - # to a string, this ensures 1 decimal point - try: - num = float(version) - except Exception: - pass - else: - version = str(num) - - # if it's a string (or an integer) from above break it on . - try: - return tuple(map(int, version.split('.'))) - except Exception: - pass - - # last attempt, maybe it's a list or iterable. - try: - return tuple(map(int, version)) - except Exception: - pass - - raise TypeError(_('Invalid version specified: %s') % version) - - -def version_match(required, candidate): - """Test that an available version is a suitable match for a required - version. - - To be suitable a version must be of the same major version as required - and be at least a match in minor/patch level. - - eg. 3.3 is a match for a required 3.1 but 4.1 is not. - - :param tuple required: the version that must be met. - :param tuple candidate: the version to test against required. - - :returns: True if candidate is suitable False otherwise. - :rtype: bool - """ - # major versions must be the same (e.g. even though v2 is a lower - # version than v3 we can't use it if v2 was requested) - if candidate[0] != required[0]: - return False - - # prevent selecting a minor version less than what is required - if candidate < required: - return False - - return True - - -class Discover(object): - - CURRENT_STATUSES = ('stable', 'current', 'supported') - DEPRECATED_STATUSES = ('deprecated',) - EXPERIMENTAL_STATUSES = ('experimental',) - - @utils.positional() - def __init__(self, session, url, authenticated=None): - self._data = get_version_data(session, url, - authenticated=authenticated) - - def raw_version_data(self, allow_experimental=False, - allow_deprecated=True, allow_unknown=False): - """Get raw version information from URL. - - Raw data indicates that only minimal validation processing is performed - on the data, so what is returned here will be the data in the same - format it was received from the endpoint. - - :param bool allow_experimental: Allow experimental version endpoints. - :param bool allow_deprecated: Allow deprecated version endpoints. - :param bool allow_unknown: Allow endpoints with an unrecognised status. - - :returns: The endpoints returned from the server that match the - criteria. - :rtype: list - """ - versions = [] - for v in self._data: - try: - status = v['status'] - except KeyError: - _LOGGER.warning(_LW('Skipping over invalid version data. ' - 'No stability status in version.')) - continue - - status = status.lower() - - if status in self.CURRENT_STATUSES: - versions.append(v) - elif status in self.DEPRECATED_STATUSES: - if allow_deprecated: - versions.append(v) - elif status in self.EXPERIMENTAL_STATUSES: - if allow_experimental: - versions.append(v) - elif allow_unknown: - versions.append(v) - - return versions - - def version_data(self, **kwargs): - """Get normalized version data. - - Return version data in a structured way. - - :returns: A list of version data dictionaries sorted by version number. - Each data element in the returned list is a dictionary - consisting of at least: - - :version tuple: The normalized version of the endpoint. - :url str: The url for the endpoint. - :raw_status str: The status as provided by the server - :rtype: list(dict) - """ - data = self.raw_version_data(**kwargs) - versions = [] - - for v in data: - try: - version_str = v['id'] - except KeyError: - _LOGGER.info(_LI('Skipping invalid version data. Missing ID.')) - continue - - try: - links = v['links'] - except KeyError: - _LOGGER.info( - _LI('Skipping invalid version data. Missing links')) - continue - - version_number = normalize_version_number(version_str) - - for link in links: - try: - rel = link['rel'] - url = link['href'] - except (KeyError, TypeError): - _LOGGER.info(_LI('Skipping invalid version link. ' - 'Missing link URL or relationship.')) - continue - - if rel.lower() == 'self': - break - else: - _LOGGER.info(_LI('Skipping invalid version data. ' - 'Missing link to endpoint.')) - continue - - versions.append({'version': version_number, - 'url': url, - 'raw_status': v['status']}) - - versions.sort(key=lambda v: v['version']) - return versions - - def data_for(self, version, **kwargs): - """Return endpoint data for a version. - - :param tuple version: The version is always a minimum version in the - same major release as there should be no compatibility issues with - using a version newer than the one asked for. - - :returns: the endpoint data for a URL that matches the required version - (the format is described in version_data) or None if no - match. - :rtype: dict - """ - version = normalize_version_number(version) - version_data = self.version_data(**kwargs) - - for data in reversed(version_data): - if version_match(version, data['version']): - return data - - return None - - def url_for(self, version, **kwargs): - """Get the endpoint url for a version. - - :param tuple version: The version is always a minimum version in the - same major release as there should be no compatibility issues with - using a version newer than the one asked for. - - :returns: The url for the specified version or None if no match. - :rtype: str - """ - data = self.data_for(version, **kwargs) - return data['url'] if data else None - - -class _VersionHacks(object): - """A container to abstract the list of version hacks. - - This could be done as simply a dictionary but is abstracted like this to - make for easier testing. - """ - - def __init__(self): - self._discovery_data = {} - - def add_discover_hack(self, service_type, old, new=''): - """Add a new hack for a service type. - - :param str service_type: The service_type in the catalog. - :param re.RegexObject old: The pattern to use. - :param str new: What to replace the pattern with. - """ - hacks = self._discovery_data.setdefault(service_type, []) - hacks.append((old, new)) - - def get_discover_hack(self, service_type, url): - """Apply the catalog hacks and figure out an unversioned endpoint. - - :param str service_type: the service_type to look up. - :param str url: The original url that came from a service_catalog. - - :returns: Either the unversioned url or the one from the catalog - to try. - """ - for old, new in self._discovery_data.get(service_type, []): - new_string, number_of_subs_made = old.subn(new, url) - if number_of_subs_made > 0: - return new_string - - return url - - -_VERSION_HACKS = _VersionHacks() -_VERSION_HACKS.add_discover_hack('identity', re.compile('/v2.0/?$'), '/') - - -def get_catalog_discover_hack(service_type, url): - """Apply the catalog hacks and figure out an unversioned endpoint. - - This function is internal to keystoneclient. - - :param str service_type: the service_type to look up. - :param str url: The original url that came from a service_catalog. - - :returns: Either the unversioned url or the one from the catalog to try. - """ - return _VERSION_HACKS.get_discover_hack(service_type, url) diff --git a/awx/lib/site-packages/keystoneclient/access.py b/awx/lib/site-packages/keystoneclient/access.py deleted file mode 100644 index 8217de81bb..0000000000 --- a/awx/lib/site-packages/keystoneclient/access.py +++ /dev/null @@ -1,762 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import datetime - -from oslo_utils import timeutils - -from keystoneclient.i18n import _ -from keystoneclient import service_catalog - - -# gap, in seconds, to determine whether the given token is about to expire -STALE_TOKEN_DURATION = 30 - - -class AccessInfo(dict): - """Encapsulates a raw authentication token from keystone. - - Provides helper methods for extracting useful values from that token. - - """ - - @classmethod - def factory(cls, resp=None, body=None, region_name=None, auth_token=None, - **kwargs): - """Create AccessInfo object given a successful auth response & body - or a user-provided dict. - """ - # FIXME(jamielennox): Passing region_name is deprecated. Provide an - # appropriate warning. - auth_ref = None - - if body is not None or len(kwargs): - if AccessInfoV3.is_valid(body, **kwargs): - if resp and not auth_token: - auth_token = resp.headers['X-Subject-Token'] - # NOTE(jamielennox): these return AccessInfo because they - # already have auth_token installed on them. - if body: - if region_name: - body['token']['region_name'] = region_name - return AccessInfoV3(auth_token, **body['token']) - else: - return AccessInfoV3(auth_token, **kwargs) - elif AccessInfoV2.is_valid(body, **kwargs): - if body: - if region_name: - body['access']['region_name'] = region_name - auth_ref = AccessInfoV2(**body['access']) - else: - auth_ref = AccessInfoV2(**kwargs) - else: - raise NotImplementedError(_('Unrecognized auth response')) - else: - auth_ref = AccessInfoV2(**kwargs) - - if auth_token: - auth_ref.auth_token = auth_token - - return auth_ref - - def __init__(self, *args, **kwargs): - super(AccessInfo, self).__init__(*args, **kwargs) - self.service_catalog = service_catalog.ServiceCatalog.factory( - resource_dict=self, region_name=self._region_name) - - @property - def _region_name(self): - return self.get('region_name') - - def will_expire_soon(self, stale_duration=None): - """Determines if expiration is about to occur. - - :returns: true if expiration is within the given duration - :rtype: boolean - - """ - stale_duration = (STALE_TOKEN_DURATION if stale_duration is None - else stale_duration) - norm_expires = timeutils.normalize_time(self.expires) - # (gyee) should we move auth_token.will_expire_soon() to timeutils - # instead of duplicating code here? - soon = (timeutils.utcnow() + datetime.timedelta( - seconds=stale_duration)) - return norm_expires < soon - - @classmethod - def is_valid(cls, body, **kwargs): - """Determines if processing v2 or v3 token given a successful - auth body or a user-provided dict. - - :returns: true if auth body matches implementing class - :rtype: boolean - """ - raise NotImplementedError() - - def has_service_catalog(self): - """Returns true if the authorization token has a service catalog. - - :returns: boolean - """ - raise NotImplementedError() - - @property - def auth_token(self): - """Returns the token_id associated with the auth request, to be used - in headers for authenticating OpenStack API requests. - - :returns: str - """ - return self['auth_token'] - - @auth_token.setter - def auth_token(self, value): - self['auth_token'] = value - - @auth_token.deleter - def auth_token(self): - try: - del self['auth_token'] - except KeyError: - pass - - @property - def expires(self): - """Returns the token expiration (as datetime object) - - :returns: datetime - """ - raise NotImplementedError() - - @property - def issued(self): - """Returns the token issue time (as datetime object) - - :returns: datetime - """ - raise NotImplementedError() - - @property - def username(self): - """Returns the username associated with the authentication request. - Follows the pattern defined in the V2 API of first looking for 'name', - returning that if available, and falling back to 'username' if name - is unavailable. - - :returns: str - """ - raise NotImplementedError() - - @property - def user_id(self): - """Returns the user id associated with the authentication request. - - :returns: str - """ - raise NotImplementedError() - - @property - def user_domain_id(self): - """Returns the domain id of the user associated with the authentication - request. - - For v2, it always returns 'default' which may be different from the - Keystone configuration. - - :returns: str - """ - raise NotImplementedError() - - @property - def user_domain_name(self): - """Returns the domain name of the user associated with the - authentication request. - - For v2, it always returns 'Default' which may be different from the - Keystone configuration. - - :returns: str - """ - raise NotImplementedError() - - @property - def role_ids(self): - """Returns a list of role ids of the user associated with the - authentication request. - - :returns: a list of strings of role ids - """ - raise NotImplementedError() - - @property - def role_names(self): - """Returns a list of role names of the user associated with the - authentication request. - - :returns: a list of strings of role names - """ - raise NotImplementedError() - - @property - def domain_name(self): - """Returns the domain name associated with the authentication token. - - :returns: str or None (if no domain associated with the token) - """ - raise NotImplementedError() - - @property - def domain_id(self): - """Returns the domain id associated with the authentication token. - - :returns: str or None (if no domain associated with the token) - """ - raise NotImplementedError() - - @property - def project_name(self): - """Returns the project name associated with the authentication request. - - :returns: str or None (if no project associated with the token) - """ - raise NotImplementedError() - - @property - def tenant_name(self): - """Synonym for project_name.""" - return self.project_name - - @property - def scoped(self): - """Returns true if the authorization token was scoped to a tenant - (project), and contains a populated service catalog. - - This is deprecated, use project_scoped instead. - - :returns: bool - """ - raise NotImplementedError() - - @property - def project_scoped(self): - """Returns true if the authorization token was scoped to a tenant - (project). - - :returns: bool - """ - raise NotImplementedError() - - @property - def domain_scoped(self): - """Returns true if the authorization token was scoped to a domain. - - :returns: bool - """ - raise NotImplementedError() - - @property - def trust_id(self): - """Returns the trust id associated with the authentication token. - - :returns: str or None (if no trust associated with the token) - """ - raise NotImplementedError() - - @property - def trust_scoped(self): - """Returns true if the authorization token was scoped as delegated in a - trust, via the OS-TRUST v3 extension. - - :returns: bool - """ - raise NotImplementedError() - - @property - def trustee_user_id(self): - """Returns the trustee user id associated with a trust. - - :returns: str or None (if no trust associated with the token) - """ - raise NotImplementedError() - - @property - def trustor_user_id(self): - """Returns the trustor user id associated with a trust. - - :returns: str or None (if no trust associated with the token) - """ - raise NotImplementedError() - - @property - def project_id(self): - """Returns the project ID associated with the authentication - request, or None if the authentication request wasn't scoped to a - project. - - :returns: str or None (if no project associated with the token) - """ - raise NotImplementedError() - - @property - def tenant_id(self): - """Synonym for project_id.""" - return self.project_id - - @property - def project_domain_id(self): - """Returns the domain id of the project associated with the - authentication request. - - For v2, it returns 'default' if a project is scoped or None which may - be different from the keystone configuration. - - :returns: str - """ - raise NotImplementedError() - - @property - def project_domain_name(self): - """Returns the domain name of the project associated with the - authentication request. - - For v2, it returns 'Default' if a project is scoped or None which may - be different from the keystone configuration. - - :returns: str - """ - raise NotImplementedError() - - @property - def auth_url(self): - """Returns a tuple of URLs from publicURL and adminURL for the service - 'identity' from the service catalog associated with the authorization - request. If the authentication request wasn't scoped to a tenant - (project), this property will return None. - - DEPRECATED: this doesn't correctly handle region name. You should fetch - it from the service catalog yourself. - - :returns: tuple of urls - """ - raise NotImplementedError() - - @property - def management_url(self): - """Returns the first adminURL for 'identity' from the service catalog - associated with the authorization request, or None if the - authentication request wasn't scoped to a tenant (project). - - DEPRECATED: this doesn't correctly handle region name. You should fetch - it from the service catalog yourself. - - :returns: tuple of urls - """ - raise NotImplementedError() - - @property - def version(self): - """Returns the version of the auth token from identity service. - - :returns: str - """ - return self.get('version') - - @property - def oauth_access_token_id(self): - """Return the access token ID if OAuth authentication used. - - :returns: str or None. - """ - raise NotImplementedError() - - @property - def oauth_consumer_id(self): - """Return the consumer ID if OAuth authentication used. - - :returns: str or None. - """ - raise NotImplementedError() - - @property - def is_federated(self): - """Returns true if federation was used to get the token. - - :returns: boolean - """ - raise NotImplementedError() - - -class AccessInfoV2(AccessInfo): - """An object for encapsulating a raw v2 auth token from identity - service. - """ - - def __init__(self, *args, **kwargs): - super(AccessInfo, self).__init__(*args, **kwargs) - self.update(version='v2.0') - self.service_catalog = service_catalog.ServiceCatalog.factory( - resource_dict=self, - token=self['token']['id'], - region_name=self._region_name) - - @classmethod - def is_valid(cls, body, **kwargs): - if body: - return 'access' in body - elif kwargs: - return kwargs.get('version') == 'v2.0' - else: - return False - - def has_service_catalog(self): - return 'serviceCatalog' in self - - @AccessInfo.auth_token.getter - def auth_token(self): - try: - return super(AccessInfoV2, self).auth_token - except KeyError: - return self['token']['id'] - - @property - def expires(self): - return timeutils.parse_isotime(self['token']['expires']) - - @property - def issued(self): - return timeutils.parse_isotime(self['token']['issued_at']) - - @property - def username(self): - return self['user'].get('name', self['user'].get('username')) - - @property - def user_id(self): - return self['user']['id'] - - @property - def user_domain_id(self): - return 'default' - - @property - def user_domain_name(self): - return 'Default' - - @property - def role_ids(self): - return self.get('metadata', {}).get('roles', []) - - @property - def role_names(self): - return [r['name'] for r in self['user'].get('roles', [])] - - @property - def domain_name(self): - return None - - @property - def domain_id(self): - return None - - @property - def project_name(self): - try: - tenant_dict = self['token']['tenant'] - except KeyError: - pass - else: - return tenant_dict.get('name') - - # pre grizzly - try: - return self['user']['tenantName'] - except KeyError: - pass - - # pre diablo, keystone only provided a tenantId - try: - return self['token']['tenantId'] - except KeyError: - pass - - @property - def scoped(self): - if ('serviceCatalog' in self - and self['serviceCatalog'] - and 'tenant' in self['token']): - return True - return False - - @property - def project_scoped(self): - return 'tenant' in self['token'] - - @property - def domain_scoped(self): - return False - - @property - def trust_id(self): - return self.get('trust', {}).get('id') - - @property - def trust_scoped(self): - return 'trust' in self - - @property - def trustee_user_id(self): - return self.get('trust', {}).get('trustee_user_id') - - @property - def trustor_user_id(self): - # this information is not available in the v2 token bug: #1331882 - return None - - @property - def project_id(self): - try: - tenant_dict = self['token']['tenant'] - except KeyError: - pass - else: - return tenant_dict.get('id') - - # pre grizzly - try: - return self['user']['tenantId'] - except KeyError: - pass - - # pre diablo - try: - return self['token']['tenantId'] - except KeyError: - pass - - @property - def project_domain_id(self): - if self.project_id: - return 'default' - - @property - def project_domain_name(self): - if self.project_id: - return 'Default' - - @property - def auth_url(self): - # FIXME(jamielennox): this is deprecated in favour of retrieving it - # from the service catalog. Provide a warning. - if self.service_catalog: - return self.service_catalog.get_urls(service_type='identity', - endpoint_type='publicURL', - region_name=self._region_name) - else: - return None - - @property - def management_url(self): - # FIXME(jamielennox): this is deprecated in favour of retrieving it - # from the service catalog. Provide a warning. - if self.service_catalog: - return self.service_catalog.get_urls(service_type='identity', - endpoint_type='adminURL', - region_name=self._region_name) - else: - return None - - @property - def oauth_access_token_id(self): - return None - - @property - def oauth_consumer_id(self): - return None - - @property - def is_federated(self): - return False - - -class AccessInfoV3(AccessInfo): - """An object for encapsulating a raw v3 auth token from identity - service. - """ - - def __init__(self, token, *args, **kwargs): - super(AccessInfo, self).__init__(*args, **kwargs) - self.update(version='v3') - self.service_catalog = service_catalog.ServiceCatalog.factory( - resource_dict=self, - token=token, - region_name=self._region_name) - if token: - self.auth_token = token - - @classmethod - def is_valid(cls, body, **kwargs): - if body: - return 'token' in body - elif kwargs: - return kwargs.get('version') == 'v3' - else: - return False - - def has_service_catalog(self): - return 'catalog' in self - - @property - def is_federated(self): - return 'OS-FEDERATION' in self['user'] - - @property - def expires(self): - return timeutils.parse_isotime(self['expires_at']) - - @property - def issued(self): - return timeutils.parse_isotime(self['issued_at']) - - @property - def user_id(self): - return self['user']['id'] - - @property - def user_domain_id(self): - try: - return self['user']['domain']['id'] - except KeyError: - if self.is_federated: - return None - raise - - @property - def user_domain_name(self): - try: - return self['user']['domain']['name'] - except KeyError: - if self.is_federated: - return None - raise - - @property - def role_ids(self): - return [r['id'] for r in self.get('roles', [])] - - @property - def role_names(self): - return [r['name'] for r in self.get('roles', [])] - - @property - def username(self): - return self['user']['name'] - - @property - def domain_name(self): - domain = self.get('domain') - if domain: - return domain['name'] - - @property - def domain_id(self): - domain = self.get('domain') - if domain: - return domain['id'] - - @property - def project_id(self): - project = self.get('project') - if project: - return project['id'] - - @property - def project_domain_id(self): - project = self.get('project') - if project: - return project['domain']['id'] - - @property - def project_domain_name(self): - project = self.get('project') - if project: - return project['domain']['name'] - - @property - def project_name(self): - project = self.get('project') - if project: - return project['name'] - - @property - def scoped(self): - return ('catalog' in self and self['catalog'] and 'project' in self) - - @property - def project_scoped(self): - return 'project' in self - - @property - def domain_scoped(self): - return 'domain' in self - - @property - def trust_id(self): - return self.get('OS-TRUST:trust', {}).get('id') - - @property - def trust_scoped(self): - return 'OS-TRUST:trust' in self - - @property - def trustee_user_id(self): - return self.get('OS-TRUST:trust', {}).get('trustee_user', {}).get('id') - - @property - def trustor_user_id(self): - return self.get('OS-TRUST:trust', {}).get('trustor_user', {}).get('id') - - @property - def auth_url(self): - # FIXME(jamielennox): this is deprecated in favour of retrieving it - # from the service catalog. Provide a warning. - if self.service_catalog: - return self.service_catalog.get_urls(service_type='identity', - endpoint_type='public', - region_name=self._region_name) - else: - return None - - @property - def management_url(self): - # FIXME(jamielennox): this is deprecated in favour of retrieving it - # from the service catalog. Provide a warning. - if self.service_catalog: - return self.service_catalog.get_urls(service_type='identity', - endpoint_type='admin', - region_name=self._region_name) - - else: - return None - - @property - def oauth_access_token_id(self): - return self.get('OS-OAUTH1', {}).get('access_token_id') - - @property - def oauth_consumer_id(self): - return self.get('OS-OAUTH1', {}).get('consumer_id') diff --git a/awx/lib/site-packages/keystoneclient/adapter.py b/awx/lib/site-packages/keystoneclient/adapter.py deleted file mode 100644 index 74399da17a..0000000000 --- a/awx/lib/site-packages/keystoneclient/adapter.py +++ /dev/null @@ -1,215 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_serialization import jsonutils - -from keystoneclient import utils - - -class Adapter(object): - """An instance of a session with local variables. - - A session is a global object that is shared around amongst many clients. It - therefore contains state that is relevant to everyone. There is a lot of - state such as the service type and region_name that are only relevant to a - particular client that is using the session. An adapter provides a wrapper - of client local data around the global session object. - - :param session: The session object to wrap. - :type session: keystoneclient.session.Session - :param str service_type: The default service_type for URL discovery. - :param str service_name: The default service_name for URL discovery. - :param str interface: The default interface for URL discovery. - :param str region_name: The default region_name for URL discovery. - :param str endpoint_override: Always use this endpoint URL for requests - for this client. - :param tuple version: The version that this API targets. - :param auth: An auth plugin to use instead of the session one. - :type auth: keystoneclient.auth.base.BaseAuthPlugin - :param str user_agent: The User-Agent string to set. - :param int connect_retries: the maximum number of retries that should - be attempted for connection errors. - Default None - use session default which - is don't retry. - :param logger: A logging object to use for requests that pass through this - adapter. - :type logger: logging.Logger - """ - - @utils.positional() - def __init__(self, session, service_type=None, service_name=None, - interface=None, region_name=None, endpoint_override=None, - version=None, auth=None, user_agent=None, - connect_retries=None, logger=None): - # NOTE(jamielennox): when adding new parameters to adapter please also - # add them to the adapter call in httpclient.HTTPClient.__init__ - self.session = session - self.service_type = service_type - self.service_name = service_name - self.interface = interface - self.region_name = region_name - self.endpoint_override = endpoint_override - self.version = version - self.user_agent = user_agent - self.auth = auth - self.connect_retries = connect_retries - self.logger = logger - - def _set_endpoint_filter_kwargs(self, kwargs): - if self.service_type: - kwargs.setdefault('service_type', self.service_type) - if self.service_name: - kwargs.setdefault('service_name', self.service_name) - if self.interface: - kwargs.setdefault('interface', self.interface) - if self.region_name: - kwargs.setdefault('region_name', self.region_name) - if self.version: - kwargs.setdefault('version', self.version) - - def request(self, url, method, **kwargs): - endpoint_filter = kwargs.setdefault('endpoint_filter', {}) - self._set_endpoint_filter_kwargs(endpoint_filter) - - if self.endpoint_override: - kwargs.setdefault('endpoint_override', self.endpoint_override) - - if self.auth: - kwargs.setdefault('auth', self.auth) - if self.user_agent: - kwargs.setdefault('user_agent', self.user_agent) - if self.connect_retries is not None: - kwargs.setdefault('connect_retries', self.connect_retries) - if self.logger: - kwargs.setdefault('logger', self.logger) - - return self.session.request(url, method, **kwargs) - - def get_token(self, auth=None): - """Return a token as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin - on the session. (optional) - :type auth: :class:`keystoneclient.auth.base.BaseAuthPlugin` - - :raises keystoneclient.exceptions.AuthorizationFailure: if a new token - fetch fails. - - :returns: A valid token. - :rtype: string - """ - return self.session.get_token(auth or self.auth) - - def get_endpoint(self, auth=None, **kwargs): - """Get an endpoint as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin on - the session. (optional) - :type auth: :class:`keystoneclient.auth.base.BaseAuthPlugin` - - :raises keystoneclient.exceptions.MissingAuthPlugin: if a plugin is not - available. - - :returns: An endpoint if available or None. - :rtype: string - """ - if self.endpoint_override: - return self.endpoint_override - - self._set_endpoint_filter_kwargs(kwargs) - return self.session.get_endpoint(auth or self.auth, **kwargs) - - def invalidate(self, auth=None): - """Invalidate an authentication plugin.""" - return self.session.invalidate(auth or self.auth) - - def get_user_id(self, auth=None): - """Return the authenticated user_id as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin - on the session. (optional) - :type auth: keystoneclient.auth.base.BaseAuthPlugin - - :raises keystoneclient.exceptions.AuthorizationFailure: - if a new token fetch fails. - :raises keystoneclient.exceptions.MissingAuthPlugin: - if a plugin is not available. - - :returns: Current `user_id` or None if not supported by plugin. - :rtype: string - """ - return self.session.get_user_id(auth or self.auth) - - def get_project_id(self, auth=None): - """Return the authenticated project_id as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin - on the session. (optional) - :type auth: keystoneclient.auth.base.BaseAuthPlugin - - :raises keystoneclient.exceptions.AuthorizationFailure: - if a new token fetch fails. - :raises keystoneclient.exceptions.MissingAuthPlugin: - if a plugin is not available. - - :returns: Current `project_id` or None if not supported by plugin. - :rtype: string - """ - return self.session.get_project_id(auth or self.auth) - - def get(self, url, **kwargs): - return self.request(url, 'GET', **kwargs) - - def head(self, url, **kwargs): - return self.request(url, 'HEAD', **kwargs) - - def post(self, url, **kwargs): - return self.request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - return self.request(url, 'PUT', **kwargs) - - def patch(self, url, **kwargs): - return self.request(url, 'PATCH', **kwargs) - - def delete(self, url, **kwargs): - return self.request(url, 'DELETE', **kwargs) - - -class LegacyJsonAdapter(Adapter): - """Make something that looks like an old HTTPClient. - - A common case when using an adapter is that we want an interface similar to - the HTTPClients of old which returned the body as JSON as well. - - You probably don't want this if you are starting from scratch. - """ - - def request(self, *args, **kwargs): - headers = kwargs.setdefault('headers', {}) - headers.setdefault('Accept', 'application/json') - - try: - kwargs['json'] = kwargs.pop('body') - except KeyError: - pass - - resp = super(LegacyJsonAdapter, self).request(*args, **kwargs) - - body = None - if resp.text: - try: - body = jsonutils.loads(resp.text) - except ValueError: - pass - - return resp, body diff --git a/awx/lib/site-packages/keystoneclient/apiclient/__init__.py b/awx/lib/site-packages/keystoneclient/apiclient/__init__.py deleted file mode 100644 index 344b661690..0000000000 --- a/awx/lib/site-packages/keystoneclient/apiclient/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - -from keystoneclient import exceptions - -# NOTE(akurilin): Module 'keystoneclient.apiclient' contains only exceptions -# which are deprecated, so this module must also be deprecated which helps -# to report 'deprecated' status of exceptions for next kind of imports -# from keystoneclient.apiclient import exceptions - -warnings.warn("The 'keystoneclient.apiclient' module is deprecated since " - "v.0.7.1. Use 'keystoneclient.exceptions' instead of this " - "module.", DeprecationWarning) - -__all__ = [ - 'exceptions', -] diff --git a/awx/lib/site-packages/keystoneclient/apiclient/exceptions.py b/awx/lib/site-packages/keystoneclient/apiclient/exceptions.py deleted file mode 100644 index 982820830e..0000000000 --- a/awx/lib/site-packages/keystoneclient/apiclient/exceptions.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Nebula, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception definitions. - -Deprecated since v0.7.1. Use 'keystoneclient.exceptions' instead of -this module. -""" - -import warnings - -from keystoneclient.exceptions import * # noqa - - -warnings.warn("The 'keystoneclient.apiclient.exceptions' module is deprecated " - "since v.0.7.1. Use 'keystoneclient.exceptions' instead of this " - "module.", DeprecationWarning) diff --git a/awx/lib/site-packages/keystoneclient/auth/__init__.py b/awx/lib/site-packages/keystoneclient/auth/__init__.py deleted file mode 100644 index 463bcef4c6..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from keystoneclient.auth.base import * # noqa -from keystoneclient.auth.cli import * # noqa -from keystoneclient.auth.conf import * # noqa - - -__all__ = [ - # auth.base - 'AUTH_INTERFACE', - 'BaseAuthPlugin', - 'get_plugin_class', - 'IDENTITY_AUTH_HEADER_NAME', - 'PLUGIN_NAMESPACE', - - # auth.cli - 'load_from_argparse_arguments', - 'register_argparse_arguments', - - # auth.conf - 'get_common_conf_options', - 'get_plugin_options', - 'load_from_conf_options', - 'register_conf_options', -] diff --git a/awx/lib/site-packages/keystoneclient/auth/base.py b/awx/lib/site-packages/keystoneclient/auth/base.py deleted file mode 100644 index a6c54f19a2..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/base.py +++ /dev/null @@ -1,298 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -import six -import stevedore - -from keystoneclient import exceptions - - -# NOTE(jamielennox): The AUTH_INTERFACE is a special value that can be -# requested from get_endpoint. If a plugin receives this as the value of -# 'interface' it should return the initial URL that was passed to the plugin. -AUTH_INTERFACE = object() - -PLUGIN_NAMESPACE = 'keystoneclient.auth.plugin' -IDENTITY_AUTH_HEADER_NAME = 'X-Auth-Token' - - -def get_plugin_class(name): - """Retrieve a plugin class by its entrypoint name. - - :param str name: The name of the object to get. - - :returns: An auth plugin class. - :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin` - - :raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be - created. - """ - try: - mgr = stevedore.DriverManager(namespace=PLUGIN_NAMESPACE, - name=name, - invoke_on_load=False) - except RuntimeError: - raise exceptions.NoMatchingPlugin(name) - - return mgr.driver - - -class BaseAuthPlugin(object): - """The basic structure of an authentication plugin.""" - - def get_token(self, session, **kwargs): - """Obtain a token. - - How the token is obtained is up to the plugin. If it is still valid - it may be re-used, retrieved from cache or invoke an authentication - request against a server. - - There are no required kwargs. They are passed directly to the auth - plugin and they are implementation specific. - - Returning None will indicate that no token was able to be retrieved. - - This function is misplaced as it should only be required for auth - plugins that use the 'X-Auth-Token' header. However due to the way - plugins evolved this method is required and often called to trigger an - authentication request on a new plugin. - - When implementing a new plugin it is advised that you implement this - method, however if you don't require the 'X-Auth-Token' header override - the `get_headers` method instead. - - :param session: A session object so the plugin can make HTTP calls. - :type session: keystoneclient.session.Session - - :return: A token to use. - :rtype: string - """ - return None - - def get_headers(self, session, **kwargs): - """Fetch authentication headers for message. - - This is a more generalized replacement of the older get_token to allow - plugins to specify different or additional authentication headers to - the OpenStack standard 'X-Auth-Token' header. - - How the authentication headers are obtained is up to the plugin. If the - headers are still valid they may be re-used, retrieved from cache or - the plugin may invoke an authentication request against a server. - - The default implementation of get_headers calls the `get_token` method - to enable older style plugins to continue functioning unchanged. - Subclasses should feel free to completely override this function to - provide the headers that they want. - - There are no required kwargs. They are passed directly to the auth - plugin and they are implementation specific. - - Returning None will indicate that no token was able to be retrieved and - that authorization was a failure. Adding no authentication data can be - achieved by returning an empty dictionary. - - :param session: The session object that the auth_plugin belongs to. - :type session: keystoneclient.session.Session - - :returns: Headers that are set to authenticate a message or None for - failure. Note that when checking this value that the empty - dict is a valid, non-failure response. - :rtype: dict - """ - token = self.get_token(session) - - if not token: - return None - - return {IDENTITY_AUTH_HEADER_NAME: token} - - def get_endpoint(self, session, **kwargs): - """Return an endpoint for the client. - - There are no required keyword arguments to ``get_endpoint`` as a plugin - implementation should use best effort with the information available to - determine the endpoint. However there are certain standard options that - will be generated by the clients and should be used by plugins: - - - ``service_type``: what sort of service is required. - - ``service_name``: the name of the service in the catalog. - - ``interface``: what visibility the endpoint should have. - - ``region_name``: the region the endpoint exists in. - - :param session: The session object that the auth_plugin belongs to. - :type session: keystoneclient.session.Session - - :returns: The base URL that will be used to talk to the required - service or None if not available. - :rtype: string - """ - return None - - def invalidate(self): - """Invalidate the current authentication data. - - This should result in fetching a new token on next call. - - A plugin may be invalidated if an Unauthorized HTTP response is - returned to indicate that the token may have been revoked or is - otherwise now invalid. - - :returns: True if there was something that the plugin did to - invalidate. This means that it makes sense to try again. If - nothing happens returns False to indicate give up. - :rtype: bool - """ - return False - - def get_user_id(self, session, **kwargs): - """Return a unique user identifier of the plugin. - - Wherever possible the user id should be inferred from the token however - there are certain URLs and other places that require access to the - currently authenticated user id. - - :param session: A session object so the plugin can make HTTP calls. - :type session: keystoneclient.session.Session - - :returns: A user identifier or None if one is not available. - :rtype: str - """ - return None - - def get_project_id(self, session, **kwargs): - """Return the project id that we are authenticated to. - - Wherever possible the project id should be inferred from the token - however there are certain URLs and other places that require access to - the currently authenticated project id. - - :param session: A session object so the plugin can make HTTP calls. - :type session: keystoneclient.session.Session - - :returns: A project identifier or None if one is not available. - :rtype: str - """ - return None - - @classmethod - def get_options(cls): - """Return the list of parameters associated with the auth plugin. - - This list may be used to generate CLI or config arguments. - - :returns: A list of Param objects describing available plugin - parameters. - :rtype: list - """ - return [] - - @classmethod - def load_from_options(cls, **kwargs): - """Create a plugin from the arguments retrieved from get_options. - - A client can override this function to do argument validation or to - handle differences between the registered options and what is required - to create the plugin. - """ - return cls(**kwargs) - - @classmethod - def register_argparse_arguments(cls, parser): - """Register the CLI options provided by a specific plugin. - - Given a plugin class convert it's options into argparse arguments and - add them to a parser. - - :param parser: the parser to attach argparse options. - :type parser: argparse.ArgumentParser - """ - - # NOTE(jamielennox): ideally oslo_config would be smart enough to - # handle all the Opt manipulation that goes on in this file. However it - # is currently not. Options are handled in as similar a way as - # possible to oslo_config such that when available we should be able to - # transition. - - for opt in cls.get_options(): - args = [] - envs = [] - - for o in [opt] + opt.deprecated_opts: - args.append('--os-%s' % o.name) - envs.append('OS_%s' % o.name.replace('-', '_').upper()) - - # select the first ENV that is not false-y or return None - env_vars = (os.environ.get(e) for e in envs) - default = six.next(six.moves.filter(None, env_vars), None) - - parser.add_argument(*args, - default=default or opt.default, - metavar=opt.metavar, - help=opt.help, - dest='os_%s' % opt.dest) - - @classmethod - def load_from_argparse_arguments(cls, namespace, **kwargs): - """Load a specific plugin object from an argparse result. - - Convert the results of a parse into the specified plugin. - - :param namespace: The result from CLI parsing. - :type namespace: argparse.Namespace - - :returns: An auth plugin, or None if a name is not provided. - :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin` - """ - for opt in cls.get_options(): - val = getattr(namespace, 'os_%s' % opt.dest) - if val is not None: - val = opt.type(val) - kwargs.setdefault(opt.dest, val) - - return cls.load_from_options(**kwargs) - - @classmethod - def register_conf_options(cls, conf, group): - """Register the oslo_config options that are needed for a plugin. - - :param conf: A config object. - :type conf: oslo_config.cfg.ConfigOpts - :param string group: The group name that options should be read from. - """ - plugin_opts = cls.get_options() - conf.register_opts(plugin_opts, group=group) - - @classmethod - def load_from_conf_options(cls, conf, group, **kwargs): - """Load the plugin from a CONF object. - - Convert the options already registered into a real plugin. - - :param conf: A config object. - :type conf: oslo_config.cfg.ConfigOpts - :param string group: The group name that options should be read from. - - :returns: An authentication Plugin. - :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin` - """ - plugin_opts = cls.get_options() - - for opt in plugin_opts: - val = conf[group][opt.dest] - if val is not None: - val = opt.type(val) - kwargs.setdefault(opt.dest, val) - - return cls.load_from_options(**kwargs) diff --git a/awx/lib/site-packages/keystoneclient/auth/cli.py b/awx/lib/site-packages/keystoneclient/auth/cli.py deleted file mode 100644 index 40a81c1d42..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/cli.py +++ /dev/null @@ -1,85 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import os - -from keystoneclient.auth import base -from keystoneclient import utils - - -@utils.positional() -def register_argparse_arguments(parser, argv, default=None): - """Register CLI options needed to create a plugin. - - The function inspects the provided arguments so that it can also register - the options required for that specific plugin if available. - - :param argparse.ArgumentParser: the parser to attach argparse options to. - :param list argv: the arguments provided to the appliation. - :param str/class default: a default plugin name or a plugin object to use - if one isn't specified by the CLI. default: None. - - :returns: The plugin class that will be loaded or None if not provided. - :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin` - - :raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be - created. - """ - in_parser = argparse.ArgumentParser(add_help=False) - env_plugin = os.environ.get('OS_AUTH_PLUGIN', default) - for p in (in_parser, parser): - p.add_argument('--os-auth-plugin', - metavar='<name>', - default=env_plugin, - help='The auth plugin to load') - - options, _args = in_parser.parse_known_args(argv) - - if not options.os_auth_plugin: - return None - - if isinstance(options.os_auth_plugin, type): - msg = 'Default Authentication options' - plugin = options.os_auth_plugin - else: - msg = 'Options specific to the %s plugin.' % options.os_auth_plugin - plugin = base.get_plugin_class(options.os_auth_plugin) - - group = parser.add_argument_group('Authentication Options', msg) - plugin.register_argparse_arguments(group) - return plugin - - -def load_from_argparse_arguments(namespace, **kwargs): - """Retrieve the created plugin from the completed argparse results. - - Loads and creates the auth plugin from the information parsed from the - command line by argparse. - - :param Namespace namespace: The result from CLI parsing. - - :returns: An auth plugin, or None if a name is not provided. - :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin` - - :raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be - created. - """ - if not namespace.os_auth_plugin: - return None - - if isinstance(namespace.os_auth_plugin, type): - plugin = namespace.os_auth_plugin - else: - plugin = base.get_plugin_class(namespace.os_auth_plugin) - - return plugin.load_from_argparse_arguments(namespace, **kwargs) diff --git a/awx/lib/site-packages/keystoneclient/auth/conf.py b/awx/lib/site-packages/keystoneclient/auth/conf.py deleted file mode 100644 index b61c123c6d..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/conf.py +++ /dev/null @@ -1,111 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg - -from keystoneclient.auth import base - -_AUTH_PLUGIN_OPT = cfg.StrOpt('auth_plugin', help='Name of the plugin to load') - -_section_help = 'Config Section from which to load plugin specific options' -_AUTH_SECTION_OPT = cfg.StrOpt('auth_section', help=_section_help) - - -def get_common_conf_options(): - """Get the oslo_config options common for all auth plugins. - - These may be useful without being registered for config file generation - or to manipulate the options before registering them yourself. - - The options that are set are: - :auth_plugin: The name of the pluign to load. - :auth_section: The config file section to load options from. - - :returns: A list of oslo_config options. - """ - return [_AUTH_PLUGIN_OPT, _AUTH_SECTION_OPT] - - -def get_plugin_options(name): - """Get the oslo_config options for a specific plugin. - - This will be the list of config options that is registered and loaded by - the specified plugin. - - :returns: A list of oslo_config options. - """ - return base.get_plugin_class(name).get_options() - - -def register_conf_options(conf, group): - """Register the oslo_config options that are needed for a plugin. - - This only registers the basic options shared by all plugins. Options that - are specific to a plugin are loaded just before they are read. - - The defined options are: - - - auth_plugin: the name of the auth plugin that will be used for - authentication. - - auth_section: the group from which further auth plugin options should be - taken. If section is not provided then the auth plugin options will be - taken from the same group as provided in the parameters. - - :param conf: config object to register with. - :type conf: oslo_config.cfg.ConfigOpts - :param string group: The ini group to register options in. - """ - conf.register_opt(_AUTH_SECTION_OPT, group=group) - - # NOTE(jamielennox): plugins are allowed to specify a 'section' which is - # the group that auth options should be taken from. If not present they - # come from the same as the base options were registered in. If present - # then the auth_plugin option may be read from that section so add that - # option. - if conf[group].auth_section: - group = conf[group].auth_section - - conf.register_opt(_AUTH_PLUGIN_OPT, group=group) - - -def load_from_conf_options(conf, group, **kwargs): - """Load a plugin from an oslo_config CONF object. - - Each plugin will register their own required options and so there is no - standard list and the plugin should be consulted. - - The base options should have been registered with register_conf_options - before this function is called. - - :param conf: A conf object. - :type conf: oslo_config.cfg.ConfigOpts - :param string group: The group name that options should be read from. - - :returns: An authentication Plugin or None if a name is not provided - :rtype: :py:class:`keystoneclient.auth.BaseAuthPlugin` - - :raises keystoneclient.exceptions.NoMatchingPlugin: if a plugin cannot be - created. - """ - # NOTE(jamielennox): plugins are allowed to specify a 'section' which is - # the group that auth options should be taken from. If not present they - # come from the same as the base options were registered in. - if conf[group].auth_section: - group = conf[group].auth_section - - name = conf[group].auth_plugin - if not name: - return None - - plugin_class = base.get_plugin_class(name) - plugin_class.register_conf_options(conf, group) - return plugin_class.load_from_conf_options(conf, group, **kwargs) diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/__init__.py b/awx/lib/site-packages/keystoneclient/auth/identity/__init__.py deleted file mode 100644 index d2aca8f9d7..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.auth.identity import base -from keystoneclient.auth.identity import generic -from keystoneclient.auth.identity import v2 -from keystoneclient.auth.identity import v3 - - -BaseIdentityPlugin = base.BaseIdentityPlugin - -V2Password = v2.Password -V2Token = v2.Token - -V3Password = v3.Password -V3Token = v3.Token - -Password = generic.Password -Token = generic.Token - - -__all__ = ['BaseIdentityPlugin', - 'Password', - 'Token', - 'V2Password', - 'V2Token', - 'V3Password', - 'V3Token'] diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/access.py b/awx/lib/site-packages/keystoneclient/auth/identity/access.py deleted file mode 100644 index 46df3bfd1a..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/access.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.auth.identity import base -from keystoneclient import utils - - -class AccessInfoPlugin(base.BaseIdentityPlugin): - """A plugin that turns an existing AccessInfo object into a usable plugin. - - There are cases where reuse of an auth_ref or AccessInfo object is - warranted such as from a cache, from auth_token middleware, or another - source. - - Turn the existing access info object into an identity plugin. This plugin - cannot be refreshed as the AccessInfo object does not contain any - authorizing information. - - :param auth_ref: the existing AccessInfo object. - :type auth_ref: keystoneclient.access.AccessInfo - :param auth_url: the url where this AccessInfo was retrieved from. Required - if using the AUTH_INTERFACE with get_endpoint. (optional) - """ - - @utils.positional() - def __init__(self, auth_ref, auth_url=None): - super(AccessInfoPlugin, self).__init__(auth_url=auth_url, - reauthenticate=False) - self.auth_ref = auth_ref - - def get_auth_ref(self, session, **kwargs): - return self.auth_ref - - def invalidate(self): - # NOTE(jamielennox): Don't allow the default invalidation to occur - # because on next authentication request we will only get the same - # auth_ref object again. - return False diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/base.py b/awx/lib/site-packages/keystoneclient/auth/identity/base.py deleted file mode 100644 index d8cd2a6a0f..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/base.py +++ /dev/null @@ -1,309 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import logging - -from oslo_config import cfg -import six - -from keystoneclient import _discover -from keystoneclient.auth import base -from keystoneclient import exceptions -from keystoneclient.i18n import _LW -from keystoneclient import utils - -LOG = logging.getLogger(__name__) - - -def get_options(): - return [ - cfg.StrOpt('auth-url', help='Authentication URL'), - ] - - -@six.add_metaclass(abc.ABCMeta) -class BaseIdentityPlugin(base.BaseAuthPlugin): - - # we count a token as valid if it is valid for at least this many seconds - MIN_TOKEN_LIFE_SECONDS = 1 - - def __init__(self, - auth_url=None, - username=None, - password=None, - token=None, - trust_id=None, - reauthenticate=True): - - super(BaseIdentityPlugin, self).__init__() - - self.auth_url = auth_url - self.auth_ref = None - self.reauthenticate = reauthenticate - - self._endpoint_cache = {} - - # NOTE(jamielennox): DEPRECATED. The following should not really be set - # here but handled by the individual auth plugin. - self.username = username - self.password = password - self.token = token - self.trust_id = trust_id - - @abc.abstractmethod - def get_auth_ref(self, session, **kwargs): - """Obtain a token from an OpenStack Identity Service. - - This method is overridden by the various token version plugins. - - This function should not be called independently and is expected to be - invoked via the do_authenticate function. - - This function will be invoked if the AcessInfo object cached by the - plugin is not valid. Thus plugins should always fetch a new AccessInfo - when invoked. If you are looking to just retrieve the current auth - data then you should use get_access. - - :param session: A session object that can be used for communication. - :type session: keystoneclient.session.Session - - :raises keystoneclient.exceptions.InvalidResponse: The response - returned wasn't - appropriate. - :raises keystoneclient.exceptions.HttpError: An error from an invalid - HTTP response. - - :returns: Token access information. - :rtype: :py:class:`keystoneclient.access.AccessInfo` - """ - - def get_token(self, session, **kwargs): - """Return a valid auth token. - - If a valid token is not present then a new one will be fetched. - - :param session: A session object that can be used for communication. - :type session: keystoneclient.session.Session - - :raises keystoneclient.exceptions.HttpError: An error from an invalid - HTTP response. - - :return: A valid token. - :rtype: string - """ - return self.get_access(session).auth_token - - def _needs_reauthenticate(self): - """Return if the existing token needs to be re-authenticated. - - The token should be refreshed if it is about to expire. - - :returns: True if the plugin should fetch a new token. False otherwise. - """ - if not self.auth_ref: - # authentication was never fetched. - return True - - if not self.reauthenticate: - # don't re-authenticate if it has been disallowed. - return False - - if self.auth_ref.will_expire_soon(self.MIN_TOKEN_LIFE_SECONDS): - # if it's about to expire we should re-authenticate now. - return True - - # otherwise it's fine and use the existing one. - return False - - def get_access(self, session, **kwargs): - """Fetch or return a current AccessInfo object. - - If a valid AccessInfo is present then it is returned otherwise a new - one will be fetched. - - :param session: A session object that can be used for communication. - :type session: keystoneclient.session.Session - - :raises keystoneclient.exceptions.HttpError: An error from an invalid - HTTP response. - - :returns: Valid AccessInfo - :rtype: :py:class:`keystoneclient.access.AccessInfo` - """ - if self._needs_reauthenticate(): - self.auth_ref = self.get_auth_ref(session) - - return self.auth_ref - - def invalidate(self): - """Invalidate the current authentication data. - - This should result in fetching a new token on next call. - - A plugin may be invalidated if an Unauthorized HTTP response is - returned to indicate that the token may have been revoked or is - otherwise now invalid. - - :returns: True if there was something that the plugin did to - invalidate. This means that it makes sense to try again. If - nothing happens returns False to indicate give up. - :rtype: bool - """ - if self.auth_ref: - self.auth_ref = None - return True - - return False - - def get_endpoint(self, session, service_type=None, interface=None, - region_name=None, service_name=None, version=None, - **kwargs): - """Return a valid endpoint for a service. - - If a valid token is not present then a new one will be fetched using - the session and kwargs. - - :param session: A session object that can be used for communication. - :type session: keystoneclient.session.Session - :param string service_type: The type of service to lookup the endpoint - for. This plugin will return None (failure) - if service_type is not provided. - :param string interface: The exposure of the endpoint. Should be - `public`, `internal`, `admin`, or `auth`. - `auth` is special here to use the `auth_url` - rather than a URL extracted from the service - catalog. Defaults to `public`. - :param string region_name: The region the endpoint should exist in. - (optional) - :param string service_name: The name of the service in the catalog. - (optional) - :param tuple version: The minimum version number required for this - endpoint. (optional) - - :raises keystoneclient.exceptions.HttpError: An error from an invalid - HTTP response. - - :return: A valid endpoint URL or None if not available. - :rtype: string or None - """ - # NOTE(jamielennox): if you specifically ask for requests to be sent to - # the auth url then we can ignore the rest of the checks. Typically if - # you are asking for the auth endpoint it means that there is no - # catalog to query anyway. - if interface is base.AUTH_INTERFACE: - return self.auth_url - - if not service_type: - LOG.warn(_LW('Plugin cannot return an endpoint without knowing ' - 'the service type that is required. Add service_type ' - 'to endpoint filtering data.')) - return None - - if not interface: - interface = 'public' - - service_catalog = self.get_access(session).service_catalog - url = service_catalog.url_for(service_type=service_type, - endpoint_type=interface, - region_name=region_name, - service_name=service_name) - - if not version: - # NOTE(jamielennox): This may not be the best thing to default to - # but is here for backwards compatibility. It may be worth - # defaulting to the most recent version. - return url - - # NOTE(jamielennox): For backwards compatibility people might have a - # versioned endpoint in their catalog even though they want to use - # other endpoint versions. So we support a list of client defined - # situations where we can strip the version component from a URL before - # doing discovery. - hacked_url = _discover.get_catalog_discover_hack(service_type, url) - - try: - disc = self.get_discovery(session, hacked_url, authenticated=False) - except (exceptions.DiscoveryFailure, - exceptions.HTTPError, - exceptions.ConnectionError): - # NOTE(jamielennox): Again if we can't contact the server we fall - # back to just returning the URL from the catalog. This may not be - # the best default but we need it for now. - LOG.warn(_LW('Failed to contact the endpoint at %s for discovery. ' - 'Fallback to using that endpoint as the base url.'), - url) - else: - url = disc.url_for(version) - - return url - - def get_user_id(self, session, **kwargs): - return self.get_access(session).user_id - - def get_project_id(self, session, **kwargs): - return self.get_access(session).project_id - - @utils.positional() - def get_discovery(self, session, url, authenticated=None): - """Return the discovery object for a URL. - - Check the session and the plugin cache to see if we have already - performed discovery on the URL and if so return it, otherwise create - a new discovery object, cache it and return it. - - This function is expected to be used by subclasses and should not - be needed by users. - - :param session: A session object to discover with. - :type session: keystoneclient.session.Session - :param str url: The url to lookup. - :param bool authenticated: Include a token in the discovery call. - (optional) Defaults to None (use a token - if a plugin is installed). - - :raises keystoneclient.exceptions.DiscoveryFailure: if for some reason - the lookup fails. - :raises keystoneclient.exceptions.HttpError: An error from an invalid - HTTP response. - - :returns: A discovery object with the results of looking up that URL. - """ - # NOTE(jamielennox): we want to cache endpoints on the session as well - # so that they maintain sharing between auth plugins. Create a cache on - # the session if it doesn't exist already. - try: - session_endpoint_cache = session._identity_endpoint_cache - except AttributeError: - session_endpoint_cache = session._identity_endpoint_cache = {} - - # NOTE(jamielennox): There is a cache located on both the session - # object and the auth plugin object so that they can be shared and the - # cache is still usable - for cache in (self._endpoint_cache, session_endpoint_cache): - disc = cache.get(url) - - if disc: - break - else: - disc = _discover.Discover(session, url, - authenticated=authenticated) - self._endpoint_cache[url] = disc - session_endpoint_cache[url] = disc - - return disc - - @classmethod - def get_options(cls): - options = super(BaseIdentityPlugin, cls).get_options() - options.extend(get_options()) - return options diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/generic/__init__.py b/awx/lib/site-packages/keystoneclient/auth/identity/generic/__init__.py deleted file mode 100644 index b24c3d6429..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/generic/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.auth.identity.generic.base import BaseGenericPlugin # noqa -from keystoneclient.auth.identity.generic.password import Password # noqa -from keystoneclient.auth.identity.generic.token import Token # noqa - - -__all__ = ['BaseGenericPlugin', - 'Password', - 'Token', - ] diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/generic/base.py b/awx/lib/site-packages/keystoneclient/auth/identity/generic/base.py deleted file mode 100644 index 7e148d2cb3..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/generic/base.py +++ /dev/null @@ -1,182 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import logging - -from oslo_config import cfg -import six -import six.moves.urllib.parse as urlparse - -from keystoneclient import _discover -from keystoneclient.auth.identity import base -from keystoneclient import exceptions -from keystoneclient.i18n import _, _LW - - -LOG = logging.getLogger(__name__) - - -def get_options(): - return [ - cfg.StrOpt('domain-id', help='Domain ID to scope to'), - cfg.StrOpt('domain-name', help='Domain name to scope to'), - cfg.StrOpt('tenant-id', help='Tenant ID to scope to'), - cfg.StrOpt('tenant-name', help='Tenant name to scope to'), - cfg.StrOpt('project-id', help='Project ID to scope to'), - cfg.StrOpt('project-name', help='Project name to scope to'), - cfg.StrOpt('project-domain-id', - help='Domain ID containing project'), - cfg.StrOpt('project-domain-name', - help='Domain name containing project'), - cfg.StrOpt('trust-id', help='Trust ID'), - ] - - -@six.add_metaclass(abc.ABCMeta) -class BaseGenericPlugin(base.BaseIdentityPlugin): - """An identity plugin that is not version dependant. - - Internally we will construct a version dependant plugin with the resolved - URL and then proxy all calls from the base plugin to the versioned one. - """ - - def __init__(self, auth_url, - tenant_id=None, - tenant_name=None, - project_id=None, - project_name=None, - project_domain_id=None, - project_domain_name=None, - domain_id=None, - domain_name=None, - trust_id=None): - super(BaseGenericPlugin, self).__init__(auth_url=auth_url) - - self._project_id = project_id or tenant_id - self._project_name = project_name or tenant_name - self._project_domain_id = project_domain_id - self._project_domain_name = project_domain_name - self._domain_id = domain_id - self._domain_name = domain_name - self._trust_id = trust_id - - self._plugin = None - - @abc.abstractmethod - def create_plugin(self, session, version, url, raw_status=None): - """Create a plugin from the given paramters. - - This function will be called multiple times with the version and url - of a potential endpoint. If a plugin can be constructed that fits the - params then it should return it. If not return None and then another - call will be made with other available URLs. - - :param session: A session object. - :type session: keystoneclient.session.Session - :param tuple version: A tuple of the API version at the URL. - :param string url: The base URL for this version. - :param string raw_status: The status that was in the discovery field. - - :returns: A plugin that can match the parameters or None if nothing. - """ - return None - - @property - def _has_domain_scope(self): - """Are there domain parameters. - - Domain parameters are v3 only so returns if any are set. - - :returns: True if a domain parameter is set, false otherwise. - """ - return any([self._domain_id, self._domain_name, - self._project_domain_id, self._project_domain_name]) - - @property - def _v2_params(self): - """Parameters that are common to v2 plugins.""" - return {'trust_id': self._trust_id, - 'tenant_id': self._project_id, - 'tenant_name': self._project_name} - - @property - def _v3_params(self): - """Parameters that are common to v3 plugins.""" - return {'trust_id': self._trust_id, - 'project_id': self._project_id, - 'project_name': self._project_name, - 'project_domain_id': self._project_domain_id, - 'project_domain_name': self._project_domain_name, - 'domain_id': self._domain_id, - 'domain_name': self._domain_name} - - def _do_create_plugin(self, session): - plugin = None - - try: - disc = self.get_discovery(session, - self.auth_url, - authenticated=False) - except (exceptions.DiscoveryFailure, - exceptions.HTTPError, - exceptions.ConnectionError): - LOG.warn(_LW('Discovering versions from the identity service ' - 'failed when creating the password plugin. ' - 'Attempting to determine version from URL.')) - - url_parts = urlparse.urlparse(self.auth_url) - path = url_parts.path.lower() - - if path.startswith('/v2.0') and not self._has_domain_scope: - plugin = self.create_plugin(session, (2, 0), self.auth_url) - elif path.startswith('/v3'): - plugin = self.create_plugin(session, (3, 0), self.auth_url) - - else: - disc_data = disc.version_data() - - for data in disc_data: - version = data['version'] - - if (_discover.version_match((2,), version) and - self._has_domain_scope): - # NOTE(jamielennox): if there are domain parameters there - # is no point even trying against v2 APIs. - continue - - plugin = self.create_plugin(session, - version, - data['url'], - raw_status=data['raw_status']) - - if plugin: - break - - if plugin: - return plugin - - # so there were no URLs that i could use for auth of any version. - msg = _('Could not determine a suitable URL for the plugin') - raise exceptions.DiscoveryFailure(msg) - - def get_auth_ref(self, session, **kwargs): - if not self._plugin: - self._plugin = self._do_create_plugin(session) - - return self._plugin.get_auth_ref(session, **kwargs) - - @classmethod - def get_options(cls): - options = super(BaseGenericPlugin, cls).get_options() - options.extend(get_options()) - return options diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/generic/password.py b/awx/lib/site-packages/keystoneclient/auth/identity/generic/password.py deleted file mode 100644 index 6790fe22c3..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/generic/password.py +++ /dev/null @@ -1,84 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -from oslo_config import cfg - -from keystoneclient import _discover -from keystoneclient.auth.identity.generic import base -from keystoneclient.auth.identity import v2 -from keystoneclient.auth.identity import v3 -from keystoneclient import utils - -LOG = logging.getLogger(__name__) - - -def get_options(): - return [ - cfg.StrOpt('user-id', help='User id'), - cfg.StrOpt('user-name', dest='username', help='Username', - deprecated_name='username'), - cfg.StrOpt('user-domain-id', help="User's domain id"), - cfg.StrOpt('user-domain-name', help="User's domain name"), - cfg.StrOpt('password', help="User's password"), - ] - - -class Password(base.BaseGenericPlugin): - """A common user/password authentication plugin. - - :param string username: Username for authentication. - :param string user_id: User ID for authentication. - :param string password: Password for authentication. - :param string user_domain_id: User's domain ID for authentication. - :param string user_domain_name: User's domain name for authentication. - - """ - - @utils.positional() - def __init__(self, auth_url, username=None, user_id=None, password=None, - user_domain_id=None, user_domain_name=None, **kwargs): - super(Password, self).__init__(auth_url=auth_url, **kwargs) - - self._username = username - self._user_id = user_id - self._password = password - self._user_domain_id = user_domain_id - self._user_domain_name = user_domain_name - - def create_plugin(self, session, version, url, raw_status=None): - if _discover.version_match((2,), version): - if self._user_domain_id or self._user_domain_name: - # If you specify any domain parameters it won't work so quit. - return None - - return v2.Password(auth_url=url, - user_id=self._user_id, - username=self._username, - password=self._password, - **self._v2_params) - - elif _discover.version_match((3,), version): - return v3.Password(auth_url=url, - user_id=self._user_id, - username=self._username, - user_domain_id=self._user_domain_id, - user_domain_name=self._user_domain_name, - password=self._password, - **self._v3_params) - - @classmethod - def get_options(cls): - options = super(Password, cls).get_options() - options.extend(get_options()) - return options diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/generic/token.py b/awx/lib/site-packages/keystoneclient/auth/identity/generic/token.py deleted file mode 100644 index 0fbacf042d..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/generic/token.py +++ /dev/null @@ -1,52 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -from oslo_config import cfg - -from keystoneclient import _discover -from keystoneclient.auth.identity.generic import base -from keystoneclient.auth.identity import v2 -from keystoneclient.auth.identity import v3 - -LOG = logging.getLogger(__name__) - - -def get_options(): - return [ - cfg.StrOpt('token', help='Token to authenticate with'), - ] - - -class Token(base.BaseGenericPlugin): - """Generic token auth plugin. - - :param string token: Token for authentication. - """ - - def __init__(self, auth_url, token=None, **kwargs): - super(Token, self).__init__(auth_url, **kwargs) - self._token = token - - def create_plugin(self, session, version, url, raw_status=None): - if _discover.version_match((2,), version): - return v2.Token(url, self._token, **self._v2_params) - - elif _discover.version_match((3,), version): - return v3.Token(url, self._token, **self._v3_params) - - @classmethod - def get_options(cls): - options = super(Token, cls).get_options() - options.extend(get_options()) - return options diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/v2.py b/awx/lib/site-packages/keystoneclient/auth/identity/v2.py deleted file mode 100644 index 8eaa9c59c5..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/v2.py +++ /dev/null @@ -1,192 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import logging - -from oslo_config import cfg -import six - -from keystoneclient import access -from keystoneclient.auth.identity import base -from keystoneclient import exceptions -from keystoneclient import utils - -_logger = logging.getLogger(__name__) - - -@six.add_metaclass(abc.ABCMeta) -class Auth(base.BaseIdentityPlugin): - """Identity V2 Authentication Plugin. - - :param string auth_url: Identity service endpoint for authorization. - :param string trust_id: Trust ID for trust scoping. - :param string tenant_id: Tenant ID for project scoping. - :param string tenant_name: Tenant name for project scoping. - :param bool reauthenticate: Allow fetching a new token if the current one - is going to expire. (optional) default True - """ - - @classmethod - def get_options(cls): - options = super(Auth, cls).get_options() - - options.extend([ - cfg.StrOpt('tenant-id', help='Tenant ID'), - cfg.StrOpt('tenant-name', help='Tenant Name'), - cfg.StrOpt('trust-id', help='Trust ID'), - ]) - - return options - - @utils.positional() - def __init__(self, auth_url, - trust_id=None, - tenant_id=None, - tenant_name=None, - reauthenticate=True): - super(Auth, self).__init__(auth_url=auth_url, - reauthenticate=reauthenticate) - - self.trust_id = trust_id - self.tenant_id = tenant_id - self.tenant_name = tenant_name - - def get_auth_ref(self, session, **kwargs): - headers = {'Accept': 'application/json'} - url = self.auth_url.rstrip('/') + '/tokens' - params = {'auth': self.get_auth_data(headers)} - - if self.tenant_id: - params['auth']['tenantId'] = self.tenant_id - elif self.tenant_name: - params['auth']['tenantName'] = self.tenant_name - if self.trust_id: - params['auth']['trust_id'] = self.trust_id - - _logger.debug('Making authentication request to %s', url) - resp = session.post(url, json=params, headers=headers, - authenticated=False, log=False) - - try: - resp_data = resp.json()['access'] - except (KeyError, ValueError): - raise exceptions.InvalidResponse(response=resp) - - return access.AccessInfoV2(**resp_data) - - @abc.abstractmethod - def get_auth_data(self, headers=None): - """Return the authentication section of an auth plugin. - - :param dict headers: The headers that will be sent with the auth - request if a plugin needs to add to them. - :return: A dict of authentication data for the auth type. - :rtype: dict - """ - - -_NOT_PASSED = object() - - -class Password(Auth): - """A plugin for authenticating with a username and password. - - A username or user_id must be provided. - - :param string auth_url: Identity service endpoint for authorization. - :param string username: Username for authentication. - :param string password: Password for authentication. - :param string user_id: User ID for authentication. - :param string trust_id: Trust ID for trust scoping. - :param string tenant_id: Tenant ID for tenant scoping. - :param string tenant_name: Tenant name for tenant scoping. - :param bool reauthenticate: Allow fetching a new token if the current one - is going to expire. (optional) default True - - :raises TypeError: if a user_id or username is not provided. - """ - - @utils.positional(4) - def __init__(self, auth_url, username=_NOT_PASSED, password=None, - user_id=_NOT_PASSED, **kwargs): - super(Password, self).__init__(auth_url, **kwargs) - - if username is _NOT_PASSED and user_id is _NOT_PASSED: - msg = 'You need to specify either a username or user_id' - raise TypeError(msg) - - if username is _NOT_PASSED: - username = None - if user_id is _NOT_PASSED: - user_id = None - - self.user_id = user_id - self.username = username - self.password = password - - def get_auth_data(self, headers=None): - auth = {'password': self.password} - - if self.username: - auth['username'] = self.username - elif self.user_id: - auth['userId'] = self.user_id - - return {'passwordCredentials': auth} - - @classmethod - def get_options(cls): - options = super(Password, cls).get_options() - - options.extend([ - cfg.StrOpt('user-name', - dest='username', - deprecated_name='username', - help='Username to login with'), - cfg.StrOpt('user-id', help='User ID to longin with'), - cfg.StrOpt('password', secret=True, help='Password to use'), - ]) - - return options - - -class Token(Auth): - """A plugin for authenticating with an existing token. - - :param string auth_url: Identity service endpoint for authorization. - :param string token: Existing token for authentication. - :param string tenant_id: Tenant ID for tenant scoping. - :param string tenant_name: Tenant name for tenant scoping. - :param string trust_id: Trust ID for trust scoping. - :param bool reauthenticate: Allow fetching a new token if the current one - is going to expire. (optional) default True - """ - - def __init__(self, auth_url, token, **kwargs): - super(Token, self).__init__(auth_url, **kwargs) - self.token = token - - def get_auth_data(self, headers=None): - if headers is not None: - headers['X-Auth-Token'] = self.token - return {'token': {'id': self.token}} - - @classmethod - def get_options(cls): - options = super(Token, cls).get_options() - - options.extend([ - cfg.StrOpt('token', secret=True, help='Token'), - ]) - - return options diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/v3/__init__.py b/awx/lib/site-packages/keystoneclient/auth/identity/v3/__init__.py deleted file mode 100644 index a08f3eccc7..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/v3/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.auth.identity.v3.base import * # noqa -from keystoneclient.auth.identity.v3.federated import * # noqa -from keystoneclient.auth.identity.v3.password import * # noqa -from keystoneclient.auth.identity.v3.token import * # noqa - - -__all__ = ['Auth', - 'AuthConstructor', - 'AuthMethod', - 'BaseAuth', - - 'FederatedBaseAuth', - - 'Password', - 'PasswordMethod', - - 'Token', - 'TokenMethod'] diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/v3/base.py b/awx/lib/site-packages/keystoneclient/auth/identity/v3/base.py deleted file mode 100644 index add571e390..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/v3/base.py +++ /dev/null @@ -1,243 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import logging - -from oslo_config import cfg -import six - -from keystoneclient import access -from keystoneclient.auth.identity import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import utils - -_logger = logging.getLogger(__name__) - -__all__ = ['Auth', 'AuthMethod', 'AuthConstructor', 'BaseAuth'] - - -@six.add_metaclass(abc.ABCMeta) -class BaseAuth(base.BaseIdentityPlugin): - """Identity V3 Authentication Plugin. - - :param string auth_url: Identity service endpoint for authentication. - :param list auth_methods: A collection of methods to authenticate with. - :param string trust_id: Trust ID for trust scoping. - :param string domain_id: Domain ID for domain scoping. - :param string domain_name: Domain name for domain scoping. - :param string project_id: Project ID for project scoping. - :param string project_name: Project name for project scoping. - :param string project_domain_id: Project's domain ID for project. - :param string project_domain_name: Project's domain name for project. - :param bool reauthenticate: Allow fetching a new token if the current one - is going to expire. (optional) default True - :param bool include_catalog: Include the service catalog in the returned - token. (optional) default True. - """ - - @utils.positional() - def __init__(self, auth_url, - trust_id=None, - domain_id=None, - domain_name=None, - project_id=None, - project_name=None, - project_domain_id=None, - project_domain_name=None, - reauthenticate=True, - include_catalog=True): - super(BaseAuth, self).__init__(auth_url=auth_url, - reauthenticate=reauthenticate) - self.trust_id = trust_id - self.domain_id = domain_id - self.domain_name = domain_name - self.project_id = project_id - self.project_name = project_name - self.project_domain_id = project_domain_id - self.project_domain_name = project_domain_name - self.include_catalog = include_catalog - - @property - def token_url(self): - """The full URL where we will send authentication data.""" - return '%s/auth/tokens' % self.auth_url.rstrip('/') - - @abc.abstractmethod - def get_auth_ref(self, session, **kwargs): - return None - - @classmethod - def get_options(cls): - options = super(BaseAuth, cls).get_options() - - options.extend([ - cfg.StrOpt('domain-id', help='Domain ID to scope to'), - cfg.StrOpt('domain-name', help='Domain name to scope to'), - cfg.StrOpt('project-id', help='Project ID to scope to'), - cfg.StrOpt('project-name', help='Project name to scope to'), - cfg.StrOpt('project-domain-id', - help='Domain ID containing project'), - cfg.StrOpt('project-domain-name', - help='Domain name containing project'), - cfg.StrOpt('trust-id', help='Trust ID'), - ]) - - return options - - -class Auth(BaseAuth): - """Identity V3 Authentication Plugin. - - :param string auth_url: Identity service endpoint for authentication. - :param list auth_methods: A collection of methods to authenticate with. - :param string trust_id: Trust ID for trust scoping. - :param string domain_id: Domain ID for domain scoping. - :param string domain_name: Domain name for domain scoping. - :param string project_id: Project ID for project scoping. - :param string project_name: Project name for project scoping. - :param string project_domain_id: Project's domain ID for project. - :param string project_domain_name: Project's domain name for project. - :param bool reauthenticate: Allow fetching a new token if the current one - is going to expire. (optional) default True - :param bool include_catalog: Include the service catalog in the returned - token. (optional) default True. - """ - - def __init__(self, auth_url, auth_methods, **kwargs): - super(Auth, self).__init__(auth_url=auth_url, **kwargs) - self.auth_methods = auth_methods - - def get_auth_ref(self, session, **kwargs): - headers = {'Accept': 'application/json'} - body = {'auth': {'identity': {}}} - ident = body['auth']['identity'] - rkwargs = {} - - for method in self.auth_methods: - name, auth_data = method.get_auth_data(session, - self, - headers, - request_kwargs=rkwargs) - ident.setdefault('methods', []).append(name) - ident[name] = auth_data - - if not ident: - raise exceptions.AuthorizationFailure( - _('Authentication method required (e.g. password)')) - - mutual_exclusion = [bool(self.domain_id or self.domain_name), - bool(self.project_id or self.project_name), - bool(self.trust_id)] - - if sum(mutual_exclusion) > 1: - raise exceptions.AuthorizationFailure( - _('Authentication cannot be scoped to multiple targets. Pick ' - 'one of: project, domain or trust')) - - if self.domain_id: - body['auth']['scope'] = {'domain': {'id': self.domain_id}} - elif self.domain_name: - body['auth']['scope'] = {'domain': {'name': self.domain_name}} - elif self.project_id: - body['auth']['scope'] = {'project': {'id': self.project_id}} - elif self.project_name: - scope = body['auth']['scope'] = {'project': {}} - scope['project']['name'] = self.project_name - - if self.project_domain_id: - scope['project']['domain'] = {'id': self.project_domain_id} - elif self.project_domain_name: - scope['project']['domain'] = {'name': self.project_domain_name} - elif self.trust_id: - body['auth']['scope'] = {'OS-TRUST:trust': {'id': self.trust_id}} - - # NOTE(jamielennox): we add nocatalog here rather than in token_url - # directly as some federation plugins require the base token_url - token_url = self.token_url - if not self.include_catalog: - token_url += '?nocatalog' - - _logger.debug('Making authentication request to %s', token_url) - resp = session.post(token_url, json=body, headers=headers, - authenticated=False, log=False, **rkwargs) - - try: - resp_data = resp.json()['token'] - except (KeyError, ValueError): - raise exceptions.InvalidResponse(response=resp) - - return access.AccessInfoV3(resp.headers['X-Subject-Token'], - **resp_data) - - -@six.add_metaclass(abc.ABCMeta) -class AuthMethod(object): - """One part of a V3 Authentication strategy. - - V3 Tokens allow multiple methods to be presented when authentication - against the server. Each one of these methods is implemented by an - AuthMethod. - - Note: When implementing an AuthMethod use the method_parameters - and do not use positional arguments. Otherwise they can't be picked up by - the factory method and don't work as well with AuthConstructors. - """ - - _method_parameters = [] - - def __init__(self, **kwargs): - for param in self._method_parameters: - setattr(self, param, kwargs.pop(param, None)) - - if kwargs: - msg = _("Unexpected Attributes: %s") % ", ".join(kwargs.keys()) - raise AttributeError(msg) - - @classmethod - def _extract_kwargs(cls, kwargs): - """Remove parameters related to this method from other kwargs.""" - return dict([(p, kwargs.pop(p, None)) - for p in cls._method_parameters]) - - @abc.abstractmethod - def get_auth_data(self, session, auth, headers, **kwargs): - """Return the authentication section of an auth plugin. - - :param session: The communication session. - :type session: keystoneclient.session.Session - :param Auth auth: The auth plugin calling the method. - :param dict headers: The headers that will be sent with the auth - request if a plugin needs to add to them. - :return: The identifier of this plugin and a dict of authentication - data for the auth type. - :rtype: tuple(string, dict) - """ - - -@six.add_metaclass(abc.ABCMeta) -class AuthConstructor(Auth): - """AuthConstructor is a means of creating an Auth Plugin that contains - only one authentication method. This is generally the required usage. - - An AuthConstructor creates an AuthMethod based on the method's - arguments and the auth_method_class defined by the plugin. It then - creates the auth plugin with only that authentication method. - """ - - _auth_method_class = None - - def __init__(self, auth_url, *args, **kwargs): - method_kwargs = self._auth_method_class._extract_kwargs(kwargs) - method = self._auth_method_class(*args, **method_kwargs) - super(AuthConstructor, self).__init__(auth_url, [method], **kwargs) diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/v3/federated.py b/awx/lib/site-packages/keystoneclient/auth/identity/v3/federated.py deleted file mode 100644 index db7ad2b92a..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/v3/federated.py +++ /dev/null @@ -1,111 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc - -from oslo_config import cfg -import six - -from keystoneclient.auth.identity.v3 import base -from keystoneclient.auth.identity.v3 import token - -__all__ = ['FederatedBaseAuth'] - - -@six.add_metaclass(abc.ABCMeta) -class FederatedBaseAuth(base.BaseAuth): - - rescoping_plugin = token.Token - - def __init__(self, auth_url, identity_provider, protocol, **kwargs): - """Class constructor accepting following parameters: - - :param auth_url: URL of the Identity Service - :type auth_url: string - :param identity_provider: name of the Identity Provider the client - will authenticate against. This parameter - will be used to build a dynamic URL used to - obtain unscoped OpenStack token. - :type identity_provider: string - - """ - super(FederatedBaseAuth, self).__init__(auth_url=auth_url, **kwargs) - self.identity_provider = identity_provider - self.protocol = protocol - - @classmethod - def get_options(cls): - options = super(FederatedBaseAuth, cls).get_options() - - options.extend([ - cfg.StrOpt('identity-provider', - help="Identity Provider's name"), - cfg.StrOpt('protocol', - help='Protocol for federated plugin'), - ]) - - return options - - @property - def federated_token_url(self): - """Full URL where authorization data is sent.""" - values = { - 'host': self.auth_url.rstrip('/'), - 'identity_provider': self.identity_provider, - 'protocol': self.protocol - } - url = ("%(host)s/OS-FEDERATION/identity_providers/" - "%(identity_provider)s/protocols/%(protocol)s/auth") - url = url % values - - return url - - def _get_scoping_data(self): - return {'trust_id': self.trust_id, - 'domain_id': self.domain_id, - 'domain_name': self.domain_name, - 'project_id': self.project_id, - 'project_name': self.project_name, - 'project_domain_id': self.project_domain_id, - 'project_domain_name': self.project_domain_name} - - def get_auth_ref(self, session, **kwargs): - """Authenticate retrieve token information. - - This is a multi-step process where a client does federated authn - receives an unscoped token. - - If an unscoped token is successfully received and scoping information - is present then the token is rescoped to that target. - - :param session: a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - :returns: a token data representation - :rtype: :py:class:`keystoneclient.access.AccessInfo` - - """ - auth_ref = self.get_unscoped_auth_ref(session) - scoping = self._get_scoping_data() - - if any(scoping.values()): - token_plugin = self.rescoping_plugin(self.auth_url, - token=auth_ref.auth_token, - **scoping) - - auth_ref = token_plugin.get_auth_ref(session) - - return auth_ref - - @abc.abstractmethod - def get_unscoped_auth_ref(self, session, **kwargs): - """Fetch unscoped federated token.""" diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/v3/password.py b/awx/lib/site-packages/keystoneclient/auth/identity/v3/password.py deleted file mode 100644 index 7e432faafe..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/v3/password.py +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg - -from keystoneclient.auth.identity.v3 import base - - -__all__ = ['PasswordMethod', 'Password'] - - -class PasswordMethod(base.AuthMethod): - """Construct a User/Password based authentication method. - - :param string password: Password for authentication. - :param string username: Username for authentication. - :param string user_id: User ID for authentication. - :param string user_domain_id: User's domain ID for authentication. - :param string user_domain_name: User's domain name for authentication. - """ - - _method_parameters = ['user_id', - 'username', - 'user_domain_id', - 'user_domain_name', - 'password'] - - def get_auth_data(self, session, auth, headers, **kwargs): - user = {'password': self.password} - - if self.user_id: - user['id'] = self.user_id - elif self.username: - user['name'] = self.username - - if self.user_domain_id: - user['domain'] = {'id': self.user_domain_id} - elif self.user_domain_name: - user['domain'] = {'name': self.user_domain_name} - - return 'password', {'user': user} - - -class Password(base.AuthConstructor): - """A plugin for authenticating with a username and password. - - :param string auth_url: Identity service endpoint for authentication. - :param string password: Password for authentication. - :param string username: Username for authentication. - :param string user_id: User ID for authentication. - :param string user_domain_id: User's domain ID for authentication. - :param string user_domain_name: User's domain name for authentication. - :param string trust_id: Trust ID for trust scoping. - :param string domain_id: Domain ID for domain scoping. - :param string domain_name: Domain name for domain scoping. - :param string project_id: Project ID for project scoping. - :param string project_name: Project name for project scoping. - :param string project_domain_id: Project's domain ID for project. - :param string project_domain_name: Project's domain name for project. - :param bool reauthenticate: Allow fetching a new token if the current one - is going to expire. (optional) default True - """ - - _auth_method_class = PasswordMethod - - @classmethod - def get_options(cls): - options = super(Password, cls).get_options() - - options.extend([ - cfg.StrOpt('user-id', help='User ID'), - cfg.StrOpt('user-name', dest='username', help='Username', - deprecated_name='username'), - cfg.StrOpt('user-domain-id', help="User's domain id"), - cfg.StrOpt('user-domain-name', help="User's domain name"), - cfg.StrOpt('password', secret=True, help="User's password"), - ]) - - return options diff --git a/awx/lib/site-packages/keystoneclient/auth/identity/v3/token.py b/awx/lib/site-packages/keystoneclient/auth/identity/v3/token.py deleted file mode 100644 index d92d3fccec..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/identity/v3/token.py +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg - -from keystoneclient.auth.identity.v3 import base - - -__all__ = ['TokenMethod', 'Token'] - - -class TokenMethod(base.AuthMethod): - """Construct an Auth plugin to fetch a token from a token. - - :param string token: Token for authentication. - """ - - _method_parameters = ['token'] - - def get_auth_data(self, session, auth, headers, **kwargs): - headers['X-Auth-Token'] = self.token - return 'token', {'id': self.token} - - -class Token(base.AuthConstructor): - """A plugin for authenticating with an existing Token. - - :param string auth_url: Identity service endpoint for authentication. - :param string token: Token for authentication. - :param string trust_id: Trust ID for trust scoping. - :param string domain_id: Domain ID for domain scoping. - :param string domain_name: Domain name for domain scoping. - :param string project_id: Project ID for project scoping. - :param string project_name: Project name for project scoping. - :param string project_domain_id: Project's domain ID for project. - :param string project_domain_name: Project's domain name for project. - :param bool reauthenticate: Allow fetching a new token if the current one - is going to expire. (optional) default True - """ - - _auth_method_class = TokenMethod - - def __init__(self, auth_url, token, **kwargs): - super(Token, self).__init__(auth_url, token=token, **kwargs) - - @classmethod - def get_options(cls): - options = super(Token, cls).get_options() - - options.extend([ - cfg.StrOpt('token', - secret=True, - help='Token to authenticate with'), - ]) - - return options diff --git a/awx/lib/site-packages/keystoneclient/auth/token_endpoint.py b/awx/lib/site-packages/keystoneclient/auth/token_endpoint.py deleted file mode 100644 index 4055062906..0000000000 --- a/awx/lib/site-packages/keystoneclient/auth/token_endpoint.py +++ /dev/null @@ -1,54 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config import cfg - -from keystoneclient.auth import base - - -class Token(base.BaseAuthPlugin): - """A provider that will always use the given token and endpoint. - - This is really only useful for testing and in certain CLI cases where you - have a known endpoint and admin token that you want to use. - """ - - def __init__(self, endpoint, token): - # NOTE(jamielennox): endpoint is reserved for when plugins - # can be used to provide that information - self.endpoint = endpoint - self.token = token - - def get_token(self, session): - return self.token - - def get_endpoint(self, session, **kwargs): - """Return the supplied endpoint. - - Using this plugin the same endpoint is returned regardless of the - parameters passed to the plugin. - """ - return self.endpoint - - @classmethod - def get_options(cls): - options = super(Token, cls).get_options() - - options.extend([ - cfg.StrOpt('endpoint', - help='The endpoint that will always be used'), - cfg.StrOpt('token', - secret=True, - help='The token that will always be used'), - ]) - - return options diff --git a/awx/lib/site-packages/keystoneclient/base.py b/awx/lib/site-packages/keystoneclient/base.py deleted file mode 100644 index 2af38b9f42..0000000000 --- a/awx/lib/site-packages/keystoneclient/base.py +++ /dev/null @@ -1,423 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -import abc -import functools - -import six -from six.moves import urllib - -from keystoneclient import auth -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient.openstack.common.apiclient import base - - -def getid(obj): - """Return id if argument is a Resource. - - Abstracts the common pattern of allowing both an object or an object's ID - (UUID) as a parameter when dealing with relationships. - """ - try: - if obj.uuid: - return obj.uuid - except AttributeError: - pass - try: - return obj.id - except AttributeError: - return obj - - -def filter_none(**kwargs): - """Remove any entries from a dictionary where the value is None.""" - return dict((k, v) for k, v in six.iteritems(kwargs) if v is not None) - - -def filter_kwargs(f): - @functools.wraps(f) - def func(*args, **kwargs): - new_kwargs = {} - for key, ref in six.iteritems(kwargs): - if ref is None: - # drop null values - continue - - id_value = getid(ref) - if id_value != ref: - # If an object with an id was passed, then use the id, e.g.: - # user: user(id=1) becomes user_id: 1 - key = '%s_id' % key - - new_kwargs[key] = id_value - - return f(*args, **new_kwargs) - return func - - -class Manager(object): - """Basic manager type providing common operations. - - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - - :param client: instance of BaseClient descendant for HTTP requests - - """ - resource_class = None - - def __init__(self, client): - super(Manager, self).__init__() - self.client = client - - @property - def api(self): - """Deprecated. Use `client` instead. - """ - return self.client - - def _list(self, url, response_key, obj_class=None, body=None, **kwargs): - """List the collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param obj_class: class for constructing the returned objects - (self.resource_class will be used by default) - :param body: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param kwargs: Additional arguments will be passed to the request. - """ - if body: - resp, body = self.client.post(url, body=body, **kwargs) - else: - resp, body = self.client.get(url, **kwargs) - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - try: - data = data['values'] - except (KeyError, TypeError): - pass - - return [obj_class(self, res, loaded=True) for res in data if res] - - def _get(self, url, response_key, **kwargs): - """Get an object from collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'server' - :param kwargs: Additional arguments will be passed to the request. - """ - resp, body = self.client.get(url, **kwargs) - return self.resource_class(self, body[response_key], loaded=True) - - def _head(self, url, **kwargs): - """Retrieve request headers for an object. - - :param url: a partial URL, e.g., '/servers' - :param kwargs: Additional arguments will be passed to the request. - """ - resp, body = self.client.head(url, **kwargs) - return resp.status_code == 204 - - def _create(self, url, body, response_key, return_raw=False, **kwargs): - """Deprecated. Use `_post` instead. - """ - return self._post(url, body, response_key, return_raw, **kwargs) - - def _post(self, url, body, response_key, return_raw=False, **kwargs): - """Create an object. - - :param url: a partial URL, e.g., '/servers' - :param body: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param return_raw: flag to force returning raw JSON instead of - Python object of self.resource_class - :param kwargs: Additional arguments will be passed to the request. - """ - resp, body = self.client.post(url, body=body, **kwargs) - if return_raw: - return body[response_key] - return self.resource_class(self, body[response_key]) - - def _put(self, url, body=None, response_key=None, **kwargs): - """Update an object with PUT method. - - :param url: a partial URL, e.g., '/servers' - :param body: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param kwargs: Additional arguments will be passed to the request. - """ - resp, body = self.client.put(url, body=body, **kwargs) - # PUT requests may not return a body - if body is not None: - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _patch(self, url, body=None, response_key=None, **kwargs): - """Update an object with PATCH method. - - :param url: a partial URL, e.g., '/servers' - :param body: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param kwargs: Additional arguments will be passed to the request. - """ - resp, body = self.client.patch(url, body=body, **kwargs) - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _delete(self, url, **kwargs): - """Delete an object. - - :param url: a partial URL, e.g., '/servers/my-server' - :param kwargs: Additional arguments will be passed to the request. - """ - return self.client.delete(url, **kwargs) - - def _update(self, url, body=None, response_key=None, method="PUT", - **kwargs): - methods = {"PUT": self.client.put, - "POST": self.client.post, - "PATCH": self.client.patch} - try: - resp, body = methods[method](url, body=body, - **kwargs) - except KeyError: - raise exceptions.ClientException(_("Invalid update method: %s") - % method) - # PUT requests may not return a body - if body: - return self.resource_class(self, body[response_key]) - - -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(Manager): - """Manager with additional `find()`/`findall()` methods.""" - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - rl = self.findall(**kwargs) - num = len(rl) - - if num == 0: - msg = _("No %(name)s matching %(kwargs)s.") % { - 'name': self.resource_class.__name__, 'kwargs': kwargs} - raise exceptions.NotFound(404, msg) - elif num > 1: - raise exceptions.NoUniqueMatch - else: - return rl[0] - - def findall(self, **kwargs): - """Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - found = [] - searches = kwargs.items() - - for obj in self.list(): - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - found.append(obj) - except AttributeError: - continue - - return found - - -class CrudManager(Manager): - """Base manager class for manipulating Keystone entities. - - Children of this class are expected to define a `collection_key` and `key`. - - - `collection_key`: Usually a plural noun by convention (e.g. `entities`); - used to refer collections in both URL's (e.g. `/v3/entities`) and JSON - objects containing a list of member resources (e.g. `{'entities': [{}, - {}, {}]}`). - - `key`: Usually a singular noun by convention (e.g. `entity`); used to - refer to an individual member of the collection. - - """ - collection_key = None - key = None - base_url = None - - def build_url(self, dict_args_in_out=None): - """Builds a resource URL for the given kwargs. - - Given an example collection where `collection_key = 'entities'` and - `key = 'entity'`, the following URL's could be generated. - - By default, the URL will represent a collection of entities, e.g.:: - - /entities - - If kwargs contains an `entity_id`, then the URL will represent a - specific member, e.g.:: - - /entities/{entity_id} - - If a `base_url` is provided, the generated URL will be appended to it. - - """ - if dict_args_in_out is None: - dict_args_in_out = {} - - url = dict_args_in_out.pop('base_url', None) or self.base_url or '' - url += '/%s' % self.collection_key - - # do we have a specific entity? - entity_id = dict_args_in_out.pop('%s_id' % self.key, None) - if entity_id is not None: - url += '/%s' % entity_id - - return url - - @filter_kwargs - def create(self, **kwargs): - url = self.build_url(dict_args_in_out=kwargs) - return self._create( - url, - {self.key: kwargs}, - self.key) - - @filter_kwargs - def get(self, **kwargs): - return self._get( - self.build_url(dict_args_in_out=kwargs), - self.key) - - @filter_kwargs - def head(self, **kwargs): - return self._head(self.build_url(dict_args_in_out=kwargs)) - - def _build_query(self, params): - return '?%s' % urllib.parse.urlencode(params) if params else '' - - def build_key_only_query(self, params_list): - """Builds a query that does not include values, just keys. - - The Identity API has some calls that define queries without values, - this can not be accomplished by using urllib.parse.urlencode(). This - method builds a query using only the keys. - """ - return '?%s' % '&'.join(params_list) if params_list else '' - - @filter_kwargs - def list(self, fallback_to_auth=False, **kwargs): - url = self.build_url(dict_args_in_out=kwargs) - - try: - query = self._build_query(kwargs) - url_query = '%(url)s%(query)s' % {'url': url, 'query': query} - return self._list( - url_query, - self.collection_key) - except exceptions.EmptyCatalog: - if fallback_to_auth: - return self._list( - url_query, - self.collection_key, - endpoint_filter={'interface': auth.AUTH_INTERFACE}) - else: - raise - - @filter_kwargs - def put(self, **kwargs): - return self._update( - self.build_url(dict_args_in_out=kwargs), - method='PUT') - - @filter_kwargs - def update(self, **kwargs): - url = self.build_url(dict_args_in_out=kwargs) - - return self._update( - url, - {self.key: kwargs}, - self.key, - method='PATCH') - - @filter_kwargs - def delete(self, **kwargs): - return self._delete( - self.build_url(dict_args_in_out=kwargs)) - - @filter_kwargs - def find(self, **kwargs): - """Find a single item with attributes matching ``**kwargs``.""" - url = self.build_url(dict_args_in_out=kwargs) - - query = self._build_query(kwargs) - rl = self._list( - '%(url)s%(query)s' % { - 'url': url, - 'query': query, - }, - self.collection_key) - num = len(rl) - - if num == 0: - msg = _("No %(name)s matching %(kwargs)s.") % { - 'name': self.resource_class.__name__, 'kwargs': kwargs} - raise exceptions.NotFound(404, msg) - elif num > 1: - raise exceptions.NoUniqueMatch - else: - return rl[0] - - -class Resource(base.Resource): - """Base class for OpenStack resources (tenant, user, etc.). - - This is pretty much just a bag for attributes. - """ - - def delete(self): - return self.manager.delete(self) diff --git a/awx/lib/site-packages/keystoneclient/baseclient.py b/awx/lib/site-packages/keystoneclient/baseclient.py deleted file mode 100644 index 97943684d9..0000000000 --- a/awx/lib/site-packages/keystoneclient/baseclient.py +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class Client(object): - - def __init__(self, session): - self.session = session - - def request(self, url, method, **kwargs): - kwargs.setdefault('authenticated', True) - return self.session.request(url, method, **kwargs) - - def get(self, url, **kwargs): - return self.request(url, 'GET', **kwargs) - - def head(self, url, **kwargs): - return self.request(url, 'HEAD', **kwargs) - - def post(self, url, **kwargs): - return self.request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - return self.request(url, 'PUT', **kwargs) - - def patch(self, url, **kwargs): - return self.request(url, 'PATCH', **kwargs) - - def delete(self, url, **kwargs): - return self.request(url, 'DELETE', **kwargs) diff --git a/awx/lib/site-packages/keystoneclient/client.py b/awx/lib/site-packages/keystoneclient/client.py deleted file mode 100644 index f4b9f87fef..0000000000 --- a/awx/lib/site-packages/keystoneclient/client.py +++ /dev/null @@ -1,53 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import discover -from keystoneclient import httpclient -from keystoneclient import session as client_session - - -# Using client.HTTPClient is deprecated. Use httpclient.HTTPClient instead. -HTTPClient = httpclient.HTTPClient - - -def Client(version=None, unstable=False, session=None, **kwargs): - """Factory function to create a new identity service client. - - The returned client will be either a V3 or V2 client. Check the version - using the :py:attr:`~keystoneclient.v3.client.Client.version` property or - the instance's class (with instanceof). - - :param tuple version: The required version of the identity API. If - specified the client will be selected such that the - major version is equivalent and an endpoint provides - at least the specified minor version. For example to - specify the 3.1 API use ``(3, 1)``. - :param bool unstable: Accept endpoints not marked as 'stable'. (optional) - :param session: A session object to be used for communication. If one is - not provided it will be constructed from the provided - kwargs. (optional) - :type session: keystoneclient.session.Session - :param kwargs: Additional arguments are passed through to the client - that is being created. - :returns: New keystone client object. - :rtype: :py:class:`keystoneclient.v3.client.Client` or - :py:class:`keystoneclient.v2_0.client.Client` - :raises keystoneclient.exceptions.DiscoveryFailure: if the server's - response is invalid. - :raises keystoneclient.exceptions.VersionNotAvailable: if a suitable client - cannot be found. - """ - if not session: - session = client_session.Session.construct(kwargs) - - d = discover.Discover(session=session, **kwargs) - return d.create_client(version=version, unstable=unstable) diff --git a/awx/lib/site-packages/keystoneclient/common/__init__.py b/awx/lib/site-packages/keystoneclient/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/common/cms.py b/awx/lib/site-packages/keystoneclient/common/cms.py deleted file mode 100644 index 06cba735b8..0000000000 --- a/awx/lib/site-packages/keystoneclient/common/cms.py +++ /dev/null @@ -1,396 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Certificate signing functions. - -Call set_subprocess() with the subprocess module. Either Python's -subprocess or eventlet.green.subprocess can be used. - -If set_subprocess() is not called, this module will pick Python's subprocess -or eventlet.green.subprocess based on if os module is patched by eventlet. -""" - -import base64 -import errno -import hashlib -import logging -import textwrap -import zlib - -import six - -from keystoneclient import exceptions -from keystoneclient.i18n import _, _LE, _LW - - -subprocess = None -LOG = logging.getLogger(__name__) -PKI_ASN1_PREFIX = 'MII' -PKIZ_PREFIX = 'PKIZ_' -PKIZ_CMS_FORM = 'DER' -PKI_ASN1_FORM = 'PEM' -DEFAULT_TOKEN_DIGEST_ALGORITHM = 'sha256' - - -# The openssl cms command exits with these status codes. -# See https://www.openssl.org/docs/apps/cms.html#EXIT_CODES -class OpensslCmsExitStatus(object): - SUCCESS = 0 - INPUT_FILE_READ_ERROR = 2 - CREATE_CMS_READ_MIME_ERROR = 3 - - -def _ensure_subprocess(): - # NOTE(vish): late loading subprocess so we can - # use the green version if we are in - # eventlet. - global subprocess - if not subprocess: - try: - from eventlet import patcher - if patcher.already_patched: - from eventlet.green import subprocess - else: - import subprocess - except ImportError: - import subprocess # noqa - - -def set_subprocess(_subprocess=None): - """Set subprocess module to use. - The subprocess could be eventlet.green.subprocess if using eventlet, - or Python's subprocess otherwise. - """ - global subprocess - subprocess = _subprocess - - -def _check_files_accessible(files): - err = None - retcode = -1 - try: - for try_file in files: - with open(try_file, 'r'): - pass - except IOError as e: - # Catching IOError means there is an issue with - # the given file. - err = _('Hit OSError in _process_communicate_handle_oserror()\n' - 'Likely due to %(file)s: %(error)s') % {'file': try_file, - 'error': e.strerror} - # Emulate openssl behavior, which returns with code 2 when - # access to a file failed. - retcode = OpensslCmsExitStatus.INPUT_FILE_READ_ERROR - - return retcode, err - - -def _process_communicate_handle_oserror(process, data, files): - """Wrapper around process.communicate that checks for OSError.""" - - try: - output, err = process.communicate(data) - except OSError as e: - if e.errno != errno.EPIPE: - raise - # OSError with EPIPE only occurs with Python 2.6.x/old 2.7.x - # http://bugs.python.org/issue10963 - - # The quick exit is typically caused by the openssl command not being - # able to read an input file, so check ourselves if can't read a file. - retcode, err = _check_files_accessible(files) - if process.stderr: - msg = process.stderr.read() - err = err + msg.decode('utf-8') - output = '' - else: - retcode = process.poll() - if err is not None: - err = err.decode('utf-8') - - return output, err, retcode - - -def _encoding_for_form(inform): - if inform == PKI_ASN1_FORM: - encoding = 'UTF-8' - elif inform == PKIZ_CMS_FORM: - encoding = 'hex' - else: - raise ValueError( - _('"inform" must be one of: %s') % ','.join((PKI_ASN1_FORM, - PKIZ_CMS_FORM))) - - return encoding - - -def cms_verify(formatted, signing_cert_file_name, ca_file_name, - inform=PKI_ASN1_FORM): - """Verifies the signature of the contents IAW CMS syntax. - - :raises subprocess.CalledProcessError: - :raises keystoneclient.exceptions.CertificateConfigError: if certificate - is not configured - properly. - """ - _ensure_subprocess() - if isinstance(formatted, six.string_types): - data = bytearray(formatted, _encoding_for_form(inform)) - else: - data = formatted - process = subprocess.Popen(['openssl', 'cms', '-verify', - '-certfile', signing_cert_file_name, - '-CAfile', ca_file_name, - '-inform', 'PEM', - '-nosmimecap', '-nodetach', - '-nocerts', '-noattr'], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - close_fds=True) - output, err, retcode = _process_communicate_handle_oserror( - process, data, (signing_cert_file_name, ca_file_name)) - - # Do not log errors, as some happen in the positive thread - # instead, catch them in the calling code and log them there. - - # When invoke the openssl with not exist file, return code 2 - # and error msg will be returned. - # You can get more from - # http://www.openssl.org/docs/apps/cms.html#EXIT_CODES - # - # $ openssl cms -verify -certfile not_exist_file -CAfile \ - # not_exist_file -inform PEM -nosmimecap -nodetach \ - # -nocerts -noattr - # Error opening certificate file not_exist_file - # - if retcode == OpensslCmsExitStatus.INPUT_FILE_READ_ERROR: - if err.startswith('Error reading S/MIME message'): - raise exceptions.CMSError(err) - else: - raise exceptions.CertificateConfigError(err) - elif retcode != OpensslCmsExitStatus.SUCCESS: - # NOTE(dmllr): Python 2.6 compatibility: - # CalledProcessError did not have output keyword argument - e = subprocess.CalledProcessError(retcode, 'openssl') - e.output = err - raise e - return output - - -def is_pkiz(token_text): - """Determine if a token a cmsz token - - Checks if the string has the prefix that indicates it is a - Crypto Message Syntax, Z compressed token. - """ - return token_text.startswith(PKIZ_PREFIX) - - -def pkiz_sign(text, - signing_cert_file_name, - signing_key_file_name, - compression_level=6, - message_digest=DEFAULT_TOKEN_DIGEST_ALGORITHM): - signed = cms_sign_data(text, - signing_cert_file_name, - signing_key_file_name, - PKIZ_CMS_FORM, - message_digest=message_digest) - - compressed = zlib.compress(signed, compression_level) - encoded = PKIZ_PREFIX + base64.urlsafe_b64encode( - compressed).decode('utf-8') - return encoded - - -def pkiz_uncompress(signed_text): - text = signed_text[len(PKIZ_PREFIX):].encode('utf-8') - unencoded = base64.urlsafe_b64decode(text) - uncompressed = zlib.decompress(unencoded) - return uncompressed - - -def pkiz_verify(signed_text, signing_cert_file_name, ca_file_name): - uncompressed = pkiz_uncompress(signed_text) - return cms_verify(uncompressed, signing_cert_file_name, ca_file_name, - inform=PKIZ_CMS_FORM) - - -# This function is deprecated and will be removed once the ASN1 token format -# is no longer required. It is only here to be used for testing. -def token_to_cms(signed_text): - copy_of_text = signed_text.replace('-', '/') - - lines = ['-----BEGIN CMS-----'] - lines += textwrap.wrap(copy_of_text, 64) - lines.append('-----END CMS-----\n') - return '\n'.join(lines) - - -def verify_token(token, signing_cert_file_name, ca_file_name): - return cms_verify(token_to_cms(token), - signing_cert_file_name, - ca_file_name) - - -def is_asn1_token(token): - """Determine if a token appears to be PKI-based. - - thx to ayoung for sorting this out. - - base64 decoded hex representation of MII is 3082:: - - In [3]: binascii.hexlify(base64.b64decode('MII=')) - Out[3]: '3082' - - re: http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - - :: - - pg4: For tags from 0 to 30 the first octet is the identfier - pg10: Hex 30 means sequence, followed by the length of that sequence. - pg5: Second octet is the length octet - first bit indicates short or long form, next 7 bits encode the - number of subsequent octets that make up the content length octets - as an unsigned binary int - - 82 = 10000010 (first bit indicates long form) - 0000010 = 2 octets of content length - so read the next 2 octets to get the length of the content. - - In the case of a very large content length there could be a requirement to - have more than 2 octets to designate the content length, therefore - requiring us to check for MIM, MIQ, etc. - - :: - - In [4]: base64.b64encode(binascii.a2b_hex('3083')) - Out[4]: 'MIM=' - In [5]: base64.b64encode(binascii.a2b_hex('3084')) - Out[5]: 'MIQ=' - Checking for MI would become invalid at 16 octets of content length - 10010000 = 90 - In [6]: base64.b64encode(binascii.a2b_hex('3090')) - Out[6]: 'MJA=' - Checking for just M is insufficient - - But we will only check for MII: - Max length of the content using 2 octets is 3FFF or 16383. - - It's not practical to support a token of this length or greater in http - therefore, we will check for MII only and ignore the case of larger tokens - """ - return token[:3] == PKI_ASN1_PREFIX - - -def is_ans1_token(token): - """Deprecated. Use is_asn1_token() instead.""" - LOG.warning(_LW('The function is_ans1_token() is deprecated, ' - 'use is_asn1_token() instead.')) - return is_asn1_token(token) - - -def cms_sign_text(data_to_sign, signing_cert_file_name, signing_key_file_name, - message_digest=DEFAULT_TOKEN_DIGEST_ALGORITHM): - return cms_sign_data(data_to_sign, signing_cert_file_name, - signing_key_file_name, message_digest=message_digest) - - -def cms_sign_data(data_to_sign, signing_cert_file_name, signing_key_file_name, - outform=PKI_ASN1_FORM, - message_digest=DEFAULT_TOKEN_DIGEST_ALGORITHM): - """Uses OpenSSL to sign a document. - - Produces a Base64 encoding of a DER formatted CMS Document - http://en.wikipedia.org/wiki/Cryptographic_Message_Syntax - - :param data_to_sign: data to sign - :param signing_cert_file_name: path to the X509 certificate containing - the public key associated with the private key used to sign the data - :param signing_key_file_name: path to the private key used to sign - the data - :param outform: Format for the signed document PKIZ_CMS_FORM or - PKI_ASN1_FORM - :param message_digest: Digest algorithm to use when signing or resigning - - """ - _ensure_subprocess() - if isinstance(data_to_sign, six.string_types): - data = bytearray(data_to_sign, encoding='utf-8') - else: - data = data_to_sign - process = subprocess.Popen(['openssl', 'cms', '-sign', - '-signer', signing_cert_file_name, - '-inkey', signing_key_file_name, - '-outform', 'PEM', - '-nosmimecap', '-nodetach', - '-nocerts', '-noattr', - '-md', message_digest, ], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - close_fds=True) - - output, err, retcode = _process_communicate_handle_oserror( - process, data, (signing_cert_file_name, signing_key_file_name)) - - if retcode != OpensslCmsExitStatus.SUCCESS or ('Error' in err): - if retcode == OpensslCmsExitStatus.CREATE_CMS_READ_MIME_ERROR: - LOG.error(_LE('Signing error: Unable to load certificate - ' - 'ensure you have configured PKI with ' - '"keystone-manage pki_setup"')) - else: - LOG.error(_LE('Signing error: %s'), err) - raise subprocess.CalledProcessError(retcode, 'openssl') - if outform == PKI_ASN1_FORM: - return output.decode('utf-8') - else: - return output - - -def cms_sign_token(text, signing_cert_file_name, signing_key_file_name, - message_digest=DEFAULT_TOKEN_DIGEST_ALGORITHM): - output = cms_sign_data(text, signing_cert_file_name, signing_key_file_name, - message_digest=message_digest) - return cms_to_token(output) - - -def cms_to_token(cms_text): - - start_delim = '-----BEGIN CMS-----' - end_delim = '-----END CMS-----' - signed_text = cms_text - signed_text = signed_text.replace('/', '-') - signed_text = signed_text.replace(start_delim, '') - signed_text = signed_text.replace(end_delim, '') - signed_text = signed_text.replace('\n', '') - - return signed_text - - -def cms_hash_token(token_id, mode='md5'): - """Hash PKI tokens. - - return: for asn1 or pkiz tokens, returns the hash of the passed in token - otherwise, returns what it was passed in. - """ - if token_id is None: - return None - if is_asn1_token(token_id) or is_pkiz(token_id): - hasher = hashlib.new(mode) - if isinstance(token_id, six.text_type): - token_id = token_id.encode('utf-8') - hasher.update(token_id) - return hasher.hexdigest() - else: - return token_id diff --git a/awx/lib/site-packages/keystoneclient/contrib/__init__.py b/awx/lib/site-packages/keystoneclient/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/contrib/auth/__init__.py b/awx/lib/site-packages/keystoneclient/contrib/auth/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/contrib/auth/v3/__init__.py b/awx/lib/site-packages/keystoneclient/contrib/auth/v3/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/contrib/auth/v3/saml2.py b/awx/lib/site-packages/keystoneclient/contrib/auth/v3/saml2.py deleted file mode 100644 index f3bb1052cd..0000000000 --- a/awx/lib/site-packages/keystoneclient/contrib/auth/v3/saml2.py +++ /dev/null @@ -1,881 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime -import uuid - -from lxml import etree -from oslo_config import cfg -from six.moves import urllib - -from keystoneclient import access -from keystoneclient.auth.identity import v3 -from keystoneclient import exceptions -from keystoneclient.i18n import _ - - -class _BaseSAMLPlugin(v3.AuthConstructor): - - HTTP_MOVED_TEMPORARILY = 302 - PROTOCOL = 'saml2' - - @staticmethod - def _first(_list): - if len(_list) != 1: - raise IndexError(_("Only single element list is acceptable")) - return _list[0] - - @staticmethod - def str_to_xml(content, msg=None, include_exc=True): - try: - return etree.XML(content) - except etree.XMLSyntaxError as e: - if not msg: - msg = str(e) - else: - msg = msg % e if include_exc else msg - raise exceptions.AuthorizationFailure(msg) - - @staticmethod - def xml_to_str(content, **kwargs): - return etree.tostring(content, **kwargs) - - @property - def token_url(self): - """Return full URL where authorization data is sent.""" - values = { - 'host': self.auth_url.rstrip('/'), - 'identity_provider': self.identity_provider, - 'protocol': self.PROTOCOL - } - url = ("%(host)s/OS-FEDERATION/identity_providers/" - "%(identity_provider)s/protocols/%(protocol)s/auth") - url = url % values - - return url - - @classmethod - def get_options(cls): - options = super(_BaseSAMLPlugin, cls).get_options() - options.extend([ - cfg.StrOpt('identity-provider', help="Identity Provider's name"), - cfg.StrOpt('identity-provider-url', - help="Identity Provider's URL"), - cfg.StrOpt('user-name', dest='username', help='Username', - deprecated_name='username'), - cfg.StrOpt('password', help='Password') - ]) - return options - - -class Saml2UnscopedTokenAuthMethod(v3.AuthMethod): - _method_parameters = [] - - def get_auth_data(self, session, auth, headers, **kwargs): - raise exceptions.MethodNotImplemented(_('This method should never ' - 'be called')) - - -class Saml2UnscopedToken(_BaseSAMLPlugin): - """Implement authentication plugin for SAML2 protocol. - - ECP stands for `Enhanced Client or Proxy` and is a SAML2 extension - for federated authentication where a transportation layer consists of - HTTP protocol and XML SOAP messages. - - `Read for more information - <https://wiki.shibboleth.net/confluence/display/SHIB2/ECP>`_ on ECP. - - Reference the `SAML2 ECP specification <https://www.oasis-open.org/\ - committees/download.php/49979/saml-ecp-v2.0-wd09.pdf>`_. - - Currently only HTTPBasicAuth mechanism is available for the IdP - authenication. - - :param auth_url: URL of the Identity Service - :type auth_url: string - - :param identity_provider: name of the Identity Provider the client will - authenticate against. This parameter will be used - to build a dynamic URL used to obtain unscoped - OpenStack token. - :type identity_provider: string - - :param identity_provider_url: An Identity Provider URL, where the SAML2 - authn request will be sent. - :type identity_provider_url: string - - :param username: User's login - :type username: string - - :param password: User's password - :type password: string - - """ - - _auth_method_class = Saml2UnscopedTokenAuthMethod - - SAML2_HEADER_INDEX = 0 - ECP_SP_EMPTY_REQUEST_HEADERS = { - 'Accept': 'text/html; application/vnd.paos+xml', - 'PAOS': ('ver="urn:liberty:paos:2003-08";"urn:oasis:names:tc:' - 'SAML:2.0:profiles:SSO:ecp"') - } - - ECP_SP_SAML2_REQUEST_HEADERS = { - 'Content-Type': 'application/vnd.paos+xml' - } - - ECP_SAML2_NAMESPACES = { - 'ecp': 'urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp', - 'S': 'http://schemas.xmlsoap.org/soap/envelope/', - 'paos': 'urn:liberty:paos:2003-08' - } - - ECP_RELAY_STATE = '//ecp:RelayState' - - ECP_SERVICE_PROVIDER_CONSUMER_URL = ('/S:Envelope/S:Header/paos:Request/' - '@responseConsumerURL') - - ECP_IDP_CONSUMER_URL = ('/S:Envelope/S:Header/ecp:Response/' - '@AssertionConsumerServiceURL') - - SOAP_FAULT = """ - <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> - <S:Body> - <S:Fault> - <faultcode>S:Server</faultcode> - <faultstring>responseConsumerURL from SP and - assertionConsumerServiceURL from IdP do not match - </faultstring> - </S:Fault> - </S:Body> - </S:Envelope> - """ - - def __init__(self, auth_url, - identity_provider, - identity_provider_url, - username, password, - **kwargs): - super(Saml2UnscopedToken, self).__init__(auth_url=auth_url, **kwargs) - self.identity_provider = identity_provider - self.identity_provider_url = identity_provider_url - self.username, self.password = username, password - - def _handle_http_302_ecp_redirect(self, session, response, method, - **kwargs): - if response.status_code != self.HTTP_MOVED_TEMPORARILY: - return response - - location = response.headers['location'] - return session.request(location, method, authenticated=False, - **kwargs) - - def _prepare_idp_saml2_request(self, saml2_authn_request): - header = saml2_authn_request[self.SAML2_HEADER_INDEX] - saml2_authn_request.remove(header) - - def _check_consumer_urls(self, session, sp_response_consumer_url, - idp_sp_response_consumer_url): - """Check if consumer URLs issued by SP and IdP are equal. - - In the initial SAML2 authn Request issued by a Service Provider - there is a url called ``consumer url``. A trusted Identity Provider - should issue identical url. If the URLs are not equal the federated - authn process should be interrupted and the user should be warned. - - :param session: session object to send out HTTP requests. - :type session: keystoneclient.session.Session - :param sp_response_consumer_url: consumer URL issued by a SP - :type sp_response_consumer_url: string - :param idp_sp_response_consumer_url: consumer URL issued by an IdP - :type idp_sp_response_consumer_url: string - - """ - if sp_response_consumer_url != idp_sp_response_consumer_url: - # send fault message to the SP, discard the response - session.post(sp_response_consumer_url, data=self.SOAP_FAULT, - headers=self.ECP_SP_SAML2_REQUEST_HEADERS, - authenticated=False) - - # prepare error message and raise an exception. - msg = _("Consumer URLs from Service Provider %(service_provider)s " - "%(sp_consumer_url)s and Identity Provider " - "%(identity_provider)s %(idp_consumer_url)s are not equal") - msg = msg % { - 'service_provider': self.token_url, - 'sp_consumer_url': sp_response_consumer_url, - 'identity_provider': self.identity_provider, - 'idp_consumer_url': idp_sp_response_consumer_url - } - - raise exceptions.ValidationError(msg) - - def _send_service_provider_request(self, session): - """Initial HTTP GET request to the SAML2 protected endpoint. - - It's crucial to include HTTP headers indicating that the client is - willing to take advantage of the ECP SAML2 extension and receive data - as the SOAP. - Unlike standard authentication methods in the OpenStack Identity, - the client accesses:: - ``/v3/OS-FEDERATION/identity_providers/{identity_providers}/ - protocols/{protocol}/auth`` - - After a successful HTTP call the HTTP response should include SAML2 - authn request in the XML format. - - If a HTTP response contains ``X-Subject-Token`` in the headers and - the response body is a valid JSON assume the user was already - authenticated and Keystone returned a valid unscoped token. - Return True indicating the user was already authenticated. - - :param session: a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - """ - sp_response = session.get(self.token_url, - headers=self.ECP_SP_EMPTY_REQUEST_HEADERS, - authenticated=False) - - if 'X-Subject-Token' in sp_response.headers: - self.authenticated_response = sp_response - return True - - try: - self.saml2_authn_request = etree.XML(sp_response.content) - except etree.XMLSyntaxError as e: - msg = _("SAML2: Error parsing XML returned " - "from Service Provider, reason: %s") % e - raise exceptions.AuthorizationFailure(msg) - - relay_state = self.saml2_authn_request.xpath( - self.ECP_RELAY_STATE, namespaces=self.ECP_SAML2_NAMESPACES) - self.relay_state = self._first(relay_state) - - sp_response_consumer_url = self.saml2_authn_request.xpath( - self.ECP_SERVICE_PROVIDER_CONSUMER_URL, - namespaces=self.ECP_SAML2_NAMESPACES) - self.sp_response_consumer_url = self._first(sp_response_consumer_url) - return False - - def _send_idp_saml2_authn_request(self, session): - """Present modified SAML2 authn assertion from the Service Provider.""" - - self._prepare_idp_saml2_request(self.saml2_authn_request) - idp_saml2_authn_request = self.saml2_authn_request - - # Currently HTTPBasicAuth method is hardcoded into the plugin - idp_response = session.post( - self.identity_provider_url, - headers={'Content-type': 'text/xml'}, - data=etree.tostring(idp_saml2_authn_request), - requests_auth=(self.username, self.password), - authenticated=False, log=False) - - try: - self.saml2_idp_authn_response = etree.XML(idp_response.content) - except etree.XMLSyntaxError as e: - msg = _("SAML2: Error parsing XML returned " - "from Identity Provider, reason: %s") % e - raise exceptions.AuthorizationFailure(msg) - - idp_response_consumer_url = self.saml2_idp_authn_response.xpath( - self.ECP_IDP_CONSUMER_URL, - namespaces=self.ECP_SAML2_NAMESPACES) - - self.idp_response_consumer_url = self._first(idp_response_consumer_url) - - self._check_consumer_urls(session, self.idp_response_consumer_url, - self.sp_response_consumer_url) - - def _send_service_provider_saml2_authn_response(self, session): - """Present SAML2 assertion to the Service Provider. - - The assertion is issued by a trusted Identity Provider for the - authenticated user. This function directs the HTTP request to SP - managed URL, for instance: ``https://<host>:<port>/Shibboleth.sso/ - SAML2/ECP``. - Upon success the there's a session created and access to the protected - resource is granted. Many implementations of the SP return HTTP 302 - status code pointing to the protected URL (``https://<host>:<port>/v3/ - OS-FEDERATION/identity_providers/{identity_provider}/protocols/ - {protocol_id}/auth`` in this case). Saml2 plugin should point to that - URL again, with HTTP GET method, expecting an unscoped token. - - :param session: a session object to send out HTTP requests. - - """ - self.saml2_idp_authn_response[0][0] = self.relay_state - - response = session.post( - self.idp_response_consumer_url, - headers=self.ECP_SP_SAML2_REQUEST_HEADERS, - data=etree.tostring(self.saml2_idp_authn_response), - authenticated=False, redirect=False) - - # Don't follow HTTP specs - after the HTTP 302 response don't repeat - # the call directed to the Location URL. In this case, this is an - # indication that saml2 session is now active and protected resource - # can be accessed. - response = self._handle_http_302_ecp_redirect( - session, response, method='GET', - headers=self.ECP_SP_SAML2_REQUEST_HEADERS) - - self.authenticated_response = response - - def _get_unscoped_token(self, session): - """Get unscoped OpenStack token after federated authentication. - - This is a multi-step process including multiple HTTP requests. - - The federated authentication consists of:: - * HTTP GET request to the Identity Service (acting as a Service - Provider). Client utilizes URL:: - ``/v3/OS-FEDERATION/identity_providers/{identity_provider}/ - protocols/saml2/auth``. - It's crucial to include HTTP headers indicating we are expecting - SOAP message in return. - Service Provider should respond with such SOAP message. - This step is handed by a method - ``Saml2UnscopedToken_send_service_provider_request()`` - - * HTTP POST request to the external Identity Provider service with - ECP extension enabled. The content sent is a header removed SOAP - message returned from the Service Provider. It's also worth noting - that ECP extension to the SAML2 doesn't define authentication method. - The most popular is HttpBasicAuth with just user and password. - Other possibilities could be X509 certificates or Kerberos. - Upon successful authentication the user should receive a SAML2 - assertion. - This step is handed by a method - ``Saml2UnscopedToken_send_idp_saml2_authn_request(session)`` - - * HTTP POST request again to the Service Provider. The body of the - request includes SAML2 assertion issued by a trusted Identity - Provider. The request should be sent to the Service Provider - consumer url specified in the SAML2 assertion. - Providing the authentication was successful and both Service Provider - and Identity Providers are trusted to each other, the Service - Provider will issue an unscoped token with a list of groups the - federated user is a member of. - This step is handed by a method - ``Saml2UnscopedToken_send_service_provider_saml2_authn_response()`` - - Unscoped token example:: - - { - "token": { - "methods": [ - "saml2" - ], - "user": { - "id": "username%40example.com", - "name": "username@example.com", - "OS-FEDERATION": { - "identity_provider": "ACME", - "protocol": "saml2", - "groups": [ - {"id": "abc123"}, - {"id": "bcd234"} - ] - } - } - } - } - - - :param session : a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - :returns: (token, token_json) - - """ - saml_authenticated = self._send_service_provider_request(session) - if not saml_authenticated: - self._send_idp_saml2_authn_request(session) - self._send_service_provider_saml2_authn_response(session) - return (self.authenticated_response.headers['X-Subject-Token'], - self.authenticated_response.json()['token']) - - def get_auth_ref(self, session, **kwargs): - """Authenticate via SAML2 protocol and retrieve unscoped token. - - This is a multi-step process where a client does federated authn - receives an unscoped token. - - Federated authentication utilizing SAML2 Enhanced Client or Proxy - extension. See ``Saml2UnscopedToken_get_unscoped_token()`` - for more information on that step. - Upon successful authentication and assertion mapping an - unscoped token is returned and stored within the plugin object for - further use. - - :param session : a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - :return: an object with scoped token's id and unscoped token json - included. - :rtype: :py:class:`keystoneclient.access.AccessInfoV3` - - """ - token, token_json = self._get_unscoped_token(session) - return access.AccessInfoV3(token, - **token_json) - - -class ADFSUnscopedToken(_BaseSAMLPlugin): - """Authentication plugin for Microsoft ADFS2.0 IdPs. - - :param auth_url: URL of the Identity Service - :type auth_url: string - - :param identity_provider: name of the Identity Provider the client will - authenticate against. This parameter will be used - to build a dynamic URL used to obtain unscoped - OpenStack token. - :type identity_provider: string - - :param identity_provider_url: An Identity Provider URL, where the SAML2 - authentication request will be sent. - :type identity_provider_url: string - - :param service_provider_endpoint: Endpoint where an assertion is being - sent, for instance: ``https://host.domain/Shibboleth.sso/ADFS`` - :type service_provider_endpoint: string - - :param username: User's login - :type username: string - - :param password: User's password - :type password: string - - """ - - _auth_method_class = Saml2UnscopedTokenAuthMethod - - DEFAULT_ADFS_TOKEN_EXPIRATION = 120 - - HEADER_SOAP = {"Content-Type": "application/soap+xml; charset=utf-8"} - HEADER_X_FORM = {"Content-Type": "application/x-www-form-urlencoded"} - - NAMESPACES = { - 's': 'http://www.w3.org/2003/05/soap-envelope', - 'a': 'http://www.w3.org/2005/08/addressing', - 'u': ('http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd') - } - - ADFS_TOKEN_NAMESPACES = { - 's': 'http://www.w3.org/2003/05/soap-envelope', - 't': 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' - } - ADFS_ASSERTION_XPATH = ('/s:Envelope/s:Body' - '/t:RequestSecurityTokenResponseCollection' - '/t:RequestSecurityTokenResponse') - - def __init__(self, auth_url, identity_provider, identity_provider_url, - service_provider_endpoint, username, password, **kwargs): - super(ADFSUnscopedToken, self).__init__(auth_url=auth_url, **kwargs) - self.identity_provider = identity_provider - self.identity_provider_url = identity_provider_url - self.service_provider_endpoint = service_provider_endpoint - self.username, self.password = username, password - - @classmethod - def get_options(cls): - options = super(ADFSUnscopedToken, cls).get_options() - - options.extend([ - cfg.StrOpt('service-provider-endpoint', - help="Service Provider's Endpoint") - ]) - return options - - def _cookies(self, session): - """Check if cookie jar is not empty. - - keystoneclient.session.Session object doesn't have a cookies attribute. - We should then try fetching cookies from the underlying - requests.Session object. If that fails too, there is something wrong - and let Python raise the AttributeError. - - :param session - :returns: True if cookie jar is nonempty, False otherwise - :raises AttributeError: in case cookies are not find anywhere - - """ - try: - return bool(session.cookies) - except AttributeError: - pass - - return bool(session.session.cookies) - - def _token_dates(self, fmt='%Y-%m-%dT%H:%M:%S.%fZ'): - """Calculate created and expires datetime objects. - - The method is going to be used for building ADFS Request Security - Token message. Time interval between ``created`` and ``expires`` - dates is now static and equals to 120 seconds. ADFS security tokens - should not be live too long, as currently ``keystoneclient`` - doesn't have mechanisms for reusing such tokens (every time ADFS authn - method is called, keystoneclient will login with the ADFS instance). - - :param fmt: Datetime format for specifying string format of a date. - It should not be changed if the method is going to be used - for building the ADFS security token request. - :type fmt: string - - """ - - date_created = datetime.datetime.utcnow() - date_expires = date_created + datetime.timedelta( - seconds=self.DEFAULT_ADFS_TOKEN_EXPIRATION) - return [_time.strftime(fmt) for _time in (date_created, date_expires)] - - def _prepare_adfs_request(self): - """Build the ADFS Request Security Token SOAP message. - - Some values like username or password are inserted in the request. - - """ - - WSS_SECURITY_NAMESPACE = { - 'o': ('http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-secext-1.0.xsd') - } - - TRUST_NAMESPACE = { - 'trust': 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' - } - - WSP_NAMESPACE = { - 'wsp': 'http://schemas.xmlsoap.org/ws/2004/09/policy' - } - - WSA_NAMESPACE = { - 'wsa': 'http://www.w3.org/2005/08/addressing' - } - - root = etree.Element( - '{http://www.w3.org/2003/05/soap-envelope}Envelope', - nsmap=self.NAMESPACES) - - header = etree.SubElement( - root, '{http://www.w3.org/2003/05/soap-envelope}Header') - action = etree.SubElement( - header, "{http://www.w3.org/2005/08/addressing}Action") - action.set( - "{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1") - action.text = ('http://docs.oasis-open.org/ws-sx/ws-trust/200512' - '/RST/Issue') - - messageID = etree.SubElement( - header, '{http://www.w3.org/2005/08/addressing}MessageID') - messageID.text = 'urn:uuid:' + uuid.uuid4().hex - replyID = etree.SubElement( - header, '{http://www.w3.org/2005/08/addressing}ReplyTo') - address = etree.SubElement( - replyID, '{http://www.w3.org/2005/08/addressing}Address') - address.text = 'http://www.w3.org/2005/08/addressing/anonymous' - - to = etree.SubElement( - header, '{http://www.w3.org/2005/08/addressing}To') - to.set("{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1") - - security = etree.SubElement( - header, '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-secext-1.0.xsd}Security', - nsmap=WSS_SECURITY_NAMESPACE) - - security.set( - "{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1") - - timestamp = etree.SubElement( - security, ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Timestamp')) - timestamp.set( - ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Id'), '_0') - - created = etree.SubElement( - timestamp, ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Created')) - - expires = etree.SubElement( - timestamp, ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Expires')) - - created.text, expires.text = self._token_dates() - - usernametoken = etree.SubElement( - security, '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-secext-1.0.xsd}UsernameToken') - usernametoken.set( - ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-' - 'wssecurity-utility-1.0.xsd}u'), "uuid-%s-1" % uuid.uuid4().hex) - - username = etree.SubElement( - usernametoken, ('{http://docs.oasis-open.org/wss/2004/01/oasis-' - '200401-wss-wssecurity-secext-1.0.xsd}Username')) - password = etree.SubElement( - usernametoken, ('{http://docs.oasis-open.org/wss/2004/01/oasis-' - '200401-wss-wssecurity-secext-1.0.xsd}Password'), - Type=('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-' - 'username-token-profile-1.0#PasswordText')) - - body = etree.SubElement( - root, "{http://www.w3.org/2003/05/soap-envelope}Body") - - request_security_token = etree.SubElement( - body, ('{http://docs.oasis-open.org/ws-sx/ws-trust/200512}' - 'RequestSecurityToken'), nsmap=TRUST_NAMESPACE) - - applies_to = etree.SubElement( - request_security_token, - '{http://schemas.xmlsoap.org/ws/2004/09/policy}AppliesTo', - nsmap=WSP_NAMESPACE) - - endpoint_reference = etree.SubElement( - applies_to, - '{http://www.w3.org/2005/08/addressing}EndpointReference', - nsmap=WSA_NAMESPACE) - - wsa_address = etree.SubElement( - endpoint_reference, - '{http://www.w3.org/2005/08/addressing}Address') - - keytype = etree.SubElement( - request_security_token, - '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}KeyType') - keytype.text = ('http://docs.oasis-open.org/ws-sx/' - 'ws-trust/200512/Bearer') - - request_type = etree.SubElement( - request_security_token, - '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}RequestType') - request_type.text = ('http://docs.oasis-open.org/ws-sx/' - 'ws-trust/200512/Issue') - token_type = etree.SubElement( - request_security_token, - '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}TokenType') - token_type.text = 'urn:oasis:names:tc:SAML:1.0:assertion' - - # After constructing the request, let's plug in some values - username.text = self.username - password.text = self.password - to.text = self.identity_provider_url - wsa_address.text = self.service_provider_endpoint - - self.prepared_request = root - - def _get_adfs_security_token(self, session): - """Send ADFS Security token to the ADFS server. - - Store the result in the instance attribute and raise an exception in - case the response is not valid XML data. - - If a user cannot authenticate due to providing bad credentials, the - ADFS2.0 server will return a HTTP 500 response and a XML Fault message. - If ``exceptions.InternalServerError`` is caught, the method tries to - parse the XML response. - If parsing is unsuccessful, an ``exceptions.AuthorizationFailure`` is - raised with a reason from the XML fault. Otherwise an original - ``exceptions.InternalServerError`` is re-raised. - - :param session : a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - :raises keystoneclient.exceptions.AuthorizationFailure: when HTTP - response from the ADFS server is not a valid XML ADFS security - token. - :raises keystoneclient.exceptions.InternalServerError: If response - status code is HTTP 500 and the response XML cannot be - recognized. - - """ - def _get_failure(e): - xpath = '/s:Envelope/s:Body/s:Fault/s:Code/s:Subcode/s:Value' - content = e.response.content - try: - obj = self.str_to_xml(content).xpath( - xpath, namespaces=self.NAMESPACES) - obj = self._first(obj) - return obj.text - # NOTE(marek-denis): etree.Element.xpath() doesn't raise an - # exception, it just returns an empty list. In that case, _first() - # will raise IndexError and we should treat it as an indication XML - # is not valid. exceptions.AuthorizationFailure can be raised from - # str_to_xml(), however since server returned HTTP 500 we should - # re-raise exceptions.InternalServerError. - except (IndexError, exceptions.AuthorizationFailure): - raise e - - request_security_token = self.xml_to_str(self.prepared_request) - try: - response = session.post( - url=self.identity_provider_url, headers=self.HEADER_SOAP, - data=request_security_token, authenticated=False) - except exceptions.InternalServerError as e: - reason = _get_failure(e) - raise exceptions.AuthorizationFailure(reason) - msg = _("Error parsing XML returned from " - "the ADFS Identity Provider, reason: %s") - self.adfs_token = self.str_to_xml(response.content, msg) - - def _prepare_sp_request(self): - """Prepare ADFS Security Token to be sent to the Service Provider. - - The method works as follows: - * Extract SAML2 assertion from the ADFS Security Token. - * Replace namespaces - * urlencode assertion - * concatenate static string with the encoded assertion - - """ - assertion = self.adfs_token.xpath( - self.ADFS_ASSERTION_XPATH, namespaces=self.ADFS_TOKEN_NAMESPACES) - assertion = self._first(assertion) - assertion = self.xml_to_str(assertion) - # TODO(marek-denis): Ideally no string replacement should occur. - # Unfortunately lxml doesn't allow for namespaces changing in-place and - # probably the only solution good for now is to build the assertion - # from scratch and reuse values from the adfs security token. - assertion = assertion.replace( - b'http://docs.oasis-open.org/ws-sx/ws-trust/200512', - b'http://schemas.xmlsoap.org/ws/2005/02/trust') - - encoded_assertion = urllib.parse.quote(assertion) - self.encoded_assertion = 'wa=wsignin1.0&wresult=' + encoded_assertion - - def _send_assertion_to_service_provider(self, session): - """Send prepared assertion to a service provider. - - As the assertion doesn't contain a protected resource, the value from - the ``location`` header is not valid and we should not let the Session - object get redirected there. The aim of this call is to get a cookie in - the response which is required for entering a protected endpoint. - - :param session : a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - :raises: Corresponding HTTP error exception - - """ - session.post( - url=self.service_provider_endpoint, data=self.encoded_assertion, - headers=self.HEADER_X_FORM, redirect=False, authenticated=False) - - def _access_service_provider(self, session): - """Access protected endpoint and fetch unscoped token. - - After federated authentication workflow a protected endpoint should be - accessible with the session object. The access is granted basing on the - cookies stored within the session object. If, for some reason no - cookies are present (quantity test) it means something went wrong and - user will not be able to fetch an unscoped token. In that case an - ``exceptions.AuthorizationFailure` exception is raised and no HTTP call - is even made. - - :param session : a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - :raises keystoneclient.exceptions.AuthorizationFailure: in case session - object has empty cookie jar. - - """ - if self._cookies(session) is False: - raise exceptions.AuthorizationFailure( - _("Session object doesn't contain a cookie, therefore you are " - "not allowed to enter the Identity Provider's protected " - "area.")) - self.authenticated_response = session.get(self.token_url, - authenticated=False) - - def _get_unscoped_token(self, session, *kwargs): - """Retrieve unscoped token after authentcation with ADFS server. - - This is a multistep process:: - - * Prepare ADFS Request Securty Token - - build a etree.XML object filling certain attributes with proper user - credentials, created/expires dates (ticket is be valid for 120 seconds - as currently we don't handle reusing ADFS issued security tokens) . - Step handled by ``ADFSUnscopedToken._prepare_adfs_request()`` method. - - * Send ADFS Security token to the ADFS server. Step handled by - ``ADFSUnscopedToken._get_adfs_security_token()`` method. - - * Receive and parse security token, extract actual SAML assertion and - prepare a request addressed for the Service Provider endpoint. - This also includes changing namespaces in the XML document. Step - handled by ``ADFSUnscopedToken._prepare_sp_request()`` method. - - * Send prepared assertion to the Service Provider endpoint. Usually - the server will respond with HTTP 301 code which should be ignored as - the 'location' header doesn't contain protected area. The goal of this - operation is fetching the session cookie which later allows for - accessing protected URL endpoints. Step handed by - ``ADFSUnscopedToken._send_assertion_to_service_provider()`` method. - - * Once the session cookie is issued, the protected endpoint can be - accessed and an unscoped token can be retrieved. Step handled by - ``ADFSUnscopedToken._access_service_provider()`` method. - - :param session : a session object to send out HTTP requests. - :type session: keystoneclient.session.Session - - :returns: (Unscoped federated token, token JSON body) - - """ - self._prepare_adfs_request() - self._get_adfs_security_token(session) - self._prepare_sp_request() - self._send_assertion_to_service_provider(session) - self._access_service_provider(session) - - try: - return (self.authenticated_response.headers['X-Subject-Token'], - self.authenticated_response.json()['token']) - except (KeyError, ValueError): - raise exceptions.InvalidResponse( - response=self.authenticated_response) - - def get_auth_ref(self, session, **kwargs): - token, token_json = self._get_unscoped_token(session) - return access.AccessInfoV3(token, **token_json) - - -class Saml2ScopedTokenMethod(v3.TokenMethod): - _method_name = 'saml2' - - def get_auth_data(self, session, auth, headers, **kwargs): - """Build and return request body for token scoping step.""" - - t = super(Saml2ScopedTokenMethod, self).get_auth_data( - session, auth, headers, **kwargs) - _token_method, token = t - return self._method_name, token - - -class Saml2ScopedToken(v3.Token): - """Class for scoping unscoped saml2 token.""" - - _auth_method_class = Saml2ScopedTokenMethod - - def __init__(self, auth_url, token, **kwargs): - super(Saml2ScopedToken, self).__init__(auth_url, token, **kwargs) - if not (self.project_id or self.domain_id): - raise exceptions.ValidationError( - _('Neither project nor domain specified')) diff --git a/awx/lib/site-packages/keystoneclient/contrib/bootstrap/__init__.py b/awx/lib/site-packages/keystoneclient/contrib/bootstrap/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/contrib/bootstrap/shell.py b/awx/lib/site-packages/keystoneclient/contrib/bootstrap/shell.py deleted file mode 100644 index 9a4ed9fcf1..0000000000 --- a/awx/lib/site-packages/keystoneclient/contrib/bootstrap/shell.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import utils -from keystoneclient.v2_0 import client - - -@utils.arg('--user-name', metavar='<user-name>', default='admin', dest='user', - help='The name of the user to be created (default="admin").') -@utils.arg('--pass', metavar='<password>', required=True, dest='passwd', - help='The password for the new user.') -@utils.arg('--role-name', metavar='<role-name>', default='admin', dest='role', - help='The name of the role to be created and granted to the user ' - '(default="admin").') -@utils.arg('--tenant-name', metavar='<tenant-name>', default='admin', - dest='tenant', - help='The name of the tenant to be created (default="admin").') -def do_bootstrap(kc, args): - """Grants a new role to a new user on a new tenant, after creating each.""" - tenant = kc.tenants.create(tenant_name=args.tenant) - role = kc.roles.create(name=args.role) - user = kc.users.create(name=args.user, password=args.passwd, email=None) - kc.roles.add_user_role(user=user, role=role, tenant=tenant) - - # verify the result - user_client = client.Client( - username=args.user, - password=args.passwd, - tenant_name=args.tenant, - auth_url=kc.management_url) - user_client.authenticate() diff --git a/awx/lib/site-packages/keystoneclient/contrib/ec2/__init__.py b/awx/lib/site-packages/keystoneclient/contrib/ec2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/contrib/ec2/utils.py b/awx/lib/site-packages/keystoneclient/contrib/ec2/utils.py deleted file mode 100644 index 95e4bb188d..0000000000 --- a/awx/lib/site-packages/keystoneclient/contrib/ec2/utils.py +++ /dev/null @@ -1,280 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 - 2012 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import base64 -import hashlib -import hmac -import re - -import six -from six.moves import urllib - -from keystoneclient.i18n import _ - - -class Ec2Signer(object): - """Utility class which allows a request to be signed with an AWS style - signature, which can then be used for authentication via the keystone ec2 - authentication extension. - """ - - def __init__(self, secret_key): - self.secret_key = secret_key.encode() - self.hmac = hmac.new(self.secret_key, digestmod=hashlib.sha1) - if hashlib.sha256: - self.hmac_256 = hmac.new(self.secret_key, digestmod=hashlib.sha256) - - def _v4_creds(self, credentials): - """Detect if the credentials are for a v4 signed request, since AWS - removed the SignatureVersion field from the v4 request spec... - - This expects a dict of the request headers to be passed in the - credentials dict, since the recommended way to pass v4 creds is - via the 'Authorization' header - see http://docs.aws.amazon.com/general/latest/gr/ - sigv4-signed-request-examples.html - - Alternatively X-Amz-Algorithm can be specified as a query parameter, - and the authentication data can also passed as query parameters. - - Note a hash of the request body is also required in the credentials - for v4 auth to work in the body_hash key, calculated via: - hashlib.sha256(req.body).hexdigest() - """ - try: - auth_str = credentials['headers']['Authorization'] - if auth_str.startswith('AWS4-HMAC-SHA256'): - return True - except KeyError: - # Alternatively the Authorization data can be passed via - # the query params list, check X-Amz-Algorithm=AWS4-HMAC-SHA256 - try: - if (credentials['params']['X-Amz-Algorithm'] == - 'AWS4-HMAC-SHA256'): - return True - except KeyError: - pass - - return False - - def generate(self, credentials): - """Generate auth string according to what SignatureVersion is given.""" - signature_version = credentials['params'].get('SignatureVersion') - if signature_version == '0': - return self._calc_signature_0(credentials['params']) - if signature_version == '1': - return self._calc_signature_1(credentials['params']) - if signature_version == '2': - return self._calc_signature_2(credentials['params'], - credentials['verb'], - credentials['host'], - credentials['path']) - if self._v4_creds(credentials): - return self._calc_signature_4(credentials['params'], - credentials['verb'], - credentials['host'], - credentials['path'], - credentials['headers'], - credentials['body_hash']) - - if signature_version is not None: - raise Exception(_('Unknown signature version: %s') % - signature_version) - else: - raise Exception(_('Unexpected signature format')) - - @staticmethod - def _get_utf8_value(value): - """Get the UTF8-encoded version of a value.""" - if not isinstance(value, (six.binary_type, six.text_type)): - value = str(value) - if isinstance(value, six.text_type): - return value.encode('utf-8') - else: - return value - - def _calc_signature_0(self, params): - """Generate AWS signature version 0 string.""" - s = (params['Action'] + params['Timestamp']).encode('utf-8') - self.hmac.update(s) - return base64.b64encode(self.hmac.digest()).decode('utf-8') - - def _calc_signature_1(self, params): - """Generate AWS signature version 1 string.""" - keys = list(params) - keys.sort(key=six.text_type.lower) - for key in keys: - self.hmac.update(key.encode('utf-8')) - val = self._get_utf8_value(params[key]) - self.hmac.update(val) - return base64.b64encode(self.hmac.digest()).decode('utf-8') - - @staticmethod - def _canonical_qs(params): - """Construct a sorted, correctly encoded query string as required for - _calc_signature_2 and _calc_signature_4. - """ - keys = list(params) - keys.sort() - pairs = [] - for key in keys: - val = Ec2Signer._get_utf8_value(params[key]) - val = urllib.parse.quote(val, safe='-_~') - pairs.append(urllib.parse.quote(key, safe='') + '=' + val) - qs = '&'.join(pairs) - return qs - - def _calc_signature_2(self, params, verb, server_string, path): - """Generate AWS signature version 2 string.""" - string_to_sign = '%s\n%s\n%s\n' % (verb, server_string, path) - if self.hmac_256: - current_hmac = self.hmac_256 - params['SignatureMethod'] = 'HmacSHA256' - else: - current_hmac = self.hmac - params['SignatureMethod'] = 'HmacSHA1' - string_to_sign += self._canonical_qs(params) - current_hmac.update(string_to_sign.encode('utf-8')) - b64 = base64.b64encode(current_hmac.digest()).decode('utf-8') - return b64 - - def _calc_signature_4(self, params, verb, server_string, path, headers, - body_hash): - """Generate AWS signature version 4 string.""" - - def sign(key, msg): - return hmac.new(key, self._get_utf8_value(msg), - hashlib.sha256).digest() - - def signature_key(datestamp, region_name, service_name): - """Signature key derivation, see - http://docs.aws.amazon.com/general/latest/gr/ - signature-v4-examples.html#signature-v4-examples-python - """ - k_date = sign(self._get_utf8_value(b"AWS4" + self.secret_key), - datestamp) - k_region = sign(k_date, region_name) - k_service = sign(k_region, service_name) - k_signing = sign(k_service, "aws4_request") - return k_signing - - def auth_param(param_name): - """Get specified auth parameter. - - Provided via one of: - - the Authorization header - - the X-Amz-* query parameters - """ - try: - auth_str = headers['Authorization'] - param_str = auth_str.partition( - '%s=' % param_name)[2].split(',')[0] - except KeyError: - param_str = params.get('X-Amz-%s' % param_name) - return param_str - - def date_param(): - """Get the X-Amz-Date' value, which can be either a header - or parameter. - - Note AWS supports parsing the Date header also, but this is not - currently supported here as it will require some format mangling - So the X-Amz-Date value must be YYYYMMDDTHHMMSSZ format, then it - can be used to match against the YYYYMMDD format provided in the - credential scope. - see: - http://docs.aws.amazon.com/general/latest/gr/ - sigv4-date-handling.html - """ - try: - return headers['X-Amz-Date'] - except KeyError: - return params.get('X-Amz-Date') - - def canonical_header_str(): - # Get the list of headers to include, from either - # - the Authorization header (SignedHeaders key) - # - the X-Amz-SignedHeaders query parameter - headers_lower = dict((k.lower().strip(), v.strip()) - for (k, v) in six.iteritems(headers)) - - # Boto versions < 2.9.3 strip the port component of the host:port - # header, so detect the user-agent via the header and strip the - # port if we detect an old boto version. FIXME: remove when all - # distros package boto >= 2.9.3, this is a transitional workaround - user_agent = headers_lower.get('user-agent', '') - strip_port = re.match('Boto/2.[0-9].[0-2]', user_agent) - - header_list = [] - sh_str = auth_param('SignedHeaders') - for h in sh_str.split(';'): - if h not in headers_lower: - continue - - if h == 'host' and strip_port: - header_list.append('%s:%s' % - (h, headers_lower[h].split(':')[0])) - continue - - header_list.append('%s:%s' % (h, headers_lower[h])) - return '\n'.join(header_list) + '\n' - - def canonical_query_str(verb, params): - # POST requests pass parameters in through the request body - canonical_qs = '' - if verb.upper() != 'POST': - canonical_qs = self._canonical_qs(params) - return canonical_qs - - # Create canonical request: - # http://docs.aws.amazon.com/general/latest/gr/ - # sigv4-create-canonical-request.html - # Get parameters and headers in expected string format - cr = "\n".join((verb.upper(), path, - canonical_query_str(verb, params), - canonical_header_str(), - auth_param('SignedHeaders'), - body_hash)) - - # Check the date, reject any request where the X-Amz-Date doesn't - # match the credential scope - credential = auth_param('Credential') - credential_split = credential.split('/') - credential_scope = '/'.join(credential_split[1:]) - credential_date = credential_split[1] - param_date = date_param() - if not param_date.startswith(credential_date): - raise Exception(_('Request date mismatch error')) - - # Create the string to sign - # http://docs.aws.amazon.com/general/latest/gr/ - # sigv4-create-string-to-sign.html - cr = cr.encode('utf-8') - string_to_sign = '\n'.join(('AWS4-HMAC-SHA256', - param_date, - credential_scope, - hashlib.sha256(cr).hexdigest())) - - # Calculate the derived key, this requires a datestamp, region - # and service, which can be extracted from the credential scope - (req_region, req_service) = credential_split[2:4] - s_key = signature_key(credential_date, req_region, req_service) - # Finally calculate the signature! - signature = hmac.new(s_key, self._get_utf8_value(string_to_sign), - hashlib.sha256).hexdigest() - return signature diff --git a/awx/lib/site-packages/keystoneclient/contrib/revoke/__init__.py b/awx/lib/site-packages/keystoneclient/contrib/revoke/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/contrib/revoke/model.py b/awx/lib/site-packages/keystoneclient/contrib/revoke/model.py deleted file mode 100644 index bb62840c2e..0000000000 --- a/awx/lib/site-packages/keystoneclient/contrib/revoke/model.py +++ /dev/null @@ -1,314 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils import timeutils - -# The set of attributes common between the RevokeEvent -# and the dictionaries created from the token Data. -_NAMES = ['trust_id', - 'consumer_id', - 'access_token_id', - 'expires_at', - 'domain_id', - 'project_id', - 'user_id', - 'role_id'] - - -# Additional arguments for creating a RevokeEvent -_EVENT_ARGS = ['issued_before', 'revoked_at'] - -# Values that will be in the token data but not in the event. -# These will compared with event values that have different names. -# For example: both trustor_id and trustee_id are compared against user_id -_TOKEN_KEYS = ['identity_domain_id', - 'assignment_domain_id', - 'issued_at', - 'trustor_id', - 'trustee_id'] - - -REVOKE_KEYS = _NAMES + _EVENT_ARGS - - -def blank_token_data(issued_at): - token_data = dict() - for name in _NAMES: - token_data[name] = None - for name in _TOKEN_KEYS: - token_data[name] = None - # required field - token_data['issued_at'] = issued_at - return token_data - - -class RevokeEvent(object): - def __init__(self, **kwargs): - for k in REVOKE_KEYS: - v = kwargs.get(k, None) - setattr(self, k, v) - if self.revoked_at is None: - self.revoked_at = timeutils.utcnow() - if self.issued_before is None: - self.issued_before = self.revoked_at - - def to_dict(self): - keys = ['user_id', - 'role_id', - 'domain_id', - 'project_id'] - event = dict((key, self.__dict__[key]) for key in keys - if self.__dict__[key] is not None) - if self.trust_id is not None: - event['OS-TRUST:trust_id'] = self.trust_id - if self.consumer_id is not None: - event['OS-OAUTH1:consumer_id'] = self.consumer_id - if self.consumer_id is not None: - event['OS-OAUTH1:access_token_id'] = self.access_token_id - if self.expires_at is not None: - event['expires_at'] = timeutils.isotime(self.expires_at, - subsecond=True) - if self.issued_before is not None: - event['issued_before'] = timeutils.isotime(self.issued_before, - subsecond=True) - return event - - def key_for_name(self, name): - return "%s=%s" % (name, getattr(self, name) or '*') - - -def attr_keys(event): - return map(event.key_for_name, _NAMES) - - -class RevokeTree(object): - """Fast Revocation Checking Tree Structure - - The Tree is an index to quickly match tokens against events. - Each node is a hashtable of key=value combinations from revocation events. - The - - """ - - def __init__(self, revoke_events=None): - self.revoke_map = dict() - self.add_events(revoke_events) - - def add_event(self, event): - """Updates the tree based on a revocation event. - - Creates any necessary internal nodes in the tree corresponding to the - fields of the revocation event. The leaf node will always be set to - the latest 'issued_before' for events that are otherwise identical. - - :param: Event to add to the tree - - :returns: the event that was passed in. - - """ - revoke_map = self.revoke_map - for key in attr_keys(event): - revoke_map = revoke_map.setdefault(key, {}) - revoke_map['issued_before'] = max( - event.issued_before, revoke_map.get( - 'issued_before', event.issued_before)) - return event - - def remove_event(self, event): - """Update the tree based on the removal of a Revocation Event - - Removes empty nodes from the tree from the leaf back to the root. - - If multiple events trace the same path, but have different - 'issued_before' values, only the last is ever stored in the tree. - So only an exact match on 'issued_before' ever triggers a removal - - :param: Event to remove from the tree - - """ - stack = [] - revoke_map = self.revoke_map - for name in _NAMES: - key = event.key_for_name(name) - nxt = revoke_map.get(key) - if nxt is None: - break - stack.append((revoke_map, key, nxt)) - revoke_map = nxt - else: - if event.issued_before == revoke_map['issued_before']: - revoke_map.pop('issued_before') - for parent, key, child in reversed(stack): - if not any(child): - del parent[key] - - def add_events(self, revoke_events): - return map(self.add_event, revoke_events or []) - - def is_revoked(self, token_data): - """Check if a token matches the revocation event - - Compare the values for each level of the tree with the values from - the token, accounting for attributes that have alternative - keys, and for wildcard matches. - if there is a match, continue down the tree. - if there is no match, exit early. - - token_data is a map based on a flattened view of token. - The required fields are: - - 'expires_at','user_id', 'project_id', 'identity_domain_id', - 'assignment_domain_id', 'trust_id', 'trustor_id', 'trustee_id' - 'consumer_id', 'access_token_id' - - """ - # Alternative names to be checked in token for every field in - # revoke tree. - alternatives = { - 'user_id': ['user_id', 'trustor_id', 'trustee_id'], - 'domain_id': ['identity_domain_id', 'assignment_domain_id'], - } - # Contains current forest (collection of trees) to be checked. - partial_matches = [self.revoke_map] - # We iterate over every layer of our revoke tree (except the last one). - for name in _NAMES: - # bundle is the set of partial matches for the next level down - # the tree - bundle = [] - wildcard = '%s=*' % (name,) - # For every tree in current forest. - for tree in partial_matches: - # If there is wildcard node on current level we take it. - bundle.append(tree.get(wildcard)) - if name == 'role_id': - # Roles are very special since a token has a list of them. - # If the revocation event matches any one of them, - # revoke the token. - for role_id in token_data.get('roles', []): - bundle.append(tree.get('role_id=%s' % role_id)) - else: - # For other fields we try to get any branch that concur - # with any alternative field in the token. - for alt_name in alternatives.get(name, [name]): - bundle.append( - tree.get('%s=%s' % (name, token_data[alt_name]))) - # tree.get returns `None` if there is no match, so `bundle.append` - # adds a 'None' entry. This call remoes the `None` entries. - partial_matches = [x for x in bundle if x is not None] - if not partial_matches: - # If we end up with no branches to follow means that the token - # is definitely not in the revoke tree and all further - # iterations will be for nothing. - return False - - # The last (leaf) level is checked in a special way because we verify - # issued_at field differently. - for leaf in partial_matches: - try: - if leaf['issued_before'] > token_data['issued_at']: - return True - except KeyError: - pass - # If we made it out of the loop then no element in revocation tree - # corresponds to our token and it is good. - return False - - -def build_token_values_v2(access, default_domain_id): - token_data = access['token'] - token_values = { - 'expires_at': timeutils.normalize_time( - timeutils.parse_isotime(token_data['expires'])), - 'issued_at': timeutils.normalize_time( - timeutils.parse_isotime(token_data['issued_at']))} - - token_values['user_id'] = access.get('user', {}).get('id') - - project = token_data.get('tenant') - if project is not None: - token_values['project_id'] = project['id'] - else: - token_values['project_id'] = None - - token_values['identity_domain_id'] = default_domain_id - token_values['assignment_domain_id'] = default_domain_id - - trust = token_data.get('trust') - if trust is None: - token_values['trust_id'] = None - token_values['trustor_id'] = None - token_values['trustee_id'] = None - else: - token_values['trust_id'] = trust['id'] - token_values['trustor_id'] = trust['trustor_id'] - token_values['trustee_id'] = trust['trustee_id'] - - token_values['consumer_id'] = None - token_values['access_token_id'] = None - - role_list = [] - # Roles are by ID in metadata and by name in the user section - roles = access.get('metadata', {}).get('roles', []) - for role in roles: - role_list.append(role) - token_values['roles'] = role_list - return token_values - - -def build_token_values(token_data): - token_values = { - 'expires_at': timeutils.normalize_time( - timeutils.parse_isotime(token_data['expires_at'])), - 'issued_at': timeutils.normalize_time( - timeutils.parse_isotime(token_data['issued_at']))} - - user = token_data.get('user') - if user is not None: - token_values['user_id'] = user['id'] - token_values['identity_domain_id'] = user['domain']['id'] - else: - token_values['user_id'] = None - token_values['identity_domain_id'] = None - - project = token_data.get('project', token_data.get('tenant')) - if project is not None: - token_values['project_id'] = project['id'] - token_values['assignment_domain_id'] = project['domain']['id'] - else: - token_values['project_id'] = None - token_values['assignment_domain_id'] = None - - role_list = [] - roles = token_data.get('roles') - if roles is not None: - for role in roles: - role_list.append(role['id']) - token_values['roles'] = role_list - - trust = token_data.get('OS-TRUST:trust') - if trust is None: - token_values['trust_id'] = None - token_values['trustor_id'] = None - token_values['trustee_id'] = None - else: - token_values['trust_id'] = trust['id'] - token_values['trustor_id'] = trust['trustor_user']['id'] - token_values['trustee_id'] = trust['trustee_user']['id'] - - oauth1 = token_data.get('OS-OAUTH1') - if oauth1 is None: - token_values['consumer_id'] = None - token_values['access_token_id'] = None - else: - token_values['consumer_id'] = oauth1['consumer_id'] - token_values['access_token_id'] = oauth1['access_token_id'] - return token_values diff --git a/awx/lib/site-packages/keystoneclient/discover.py b/awx/lib/site-packages/keystoneclient/discover.py deleted file mode 100644 index 40fd85db3c..0000000000 --- a/awx/lib/site-packages/keystoneclient/discover.py +++ /dev/null @@ -1,338 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -import six - -from keystoneclient import _discover -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import session as client_session -from keystoneclient import utils -from keystoneclient.v2_0 import client as v2_client -from keystoneclient.v3 import client as v3_client - - -_logger = logging.getLogger(__name__) - - -_CLIENT_VERSIONS = {2: v2_client.Client, - 3: v3_client.Client} - - -# functions needed from the private file that can be made public - -def normalize_version_number(version): - """Turn a version representation into a tuple. - - Takes a string, tuple or float which represent version formats we can - handle and converts them into a (major, minor) version tuple that we can - actually use for discovery. - - e.g. 'v3.3' gives (3, 3) - 3.1 gives (3, 1) - - :param version: Inputted version number to try and convert. - - :returns: A usable version tuple - :rtype: tuple - - :raises TypeError: if the inputted version cannot be converted to tuple. - """ - return _discover.normalize_version_number(version) - - -def version_match(required, candidate): - """Test that an available version is a suitable match for a required - version. - - To be suitable a version must be of the same major version as required - and be at least a match in minor/patch level. - - eg. 3.3 is a match for a required 3.1 but 4.1 is not. - - :param tuple required: the version that must be met. - :param tuple candidate: the version to test against required. - - :returns: True if candidate is suitable False otherwise. - :rtype: bool - """ - return _discover.version_match(required, candidate) - - -def available_versions(url, session=None, **kwargs): - """Retrieve raw version data from a url.""" - if not session: - session = client_session.Session.construct(kwargs) - - return _discover.get_version_data(session, url) - - -class Discover(_discover.Discover): - """A means to discover and create clients depending on the supported API - versions on the server. - - Querying the server is done on object creation and every subsequent method - operates upon the data that was retrieved. - - The connection parameters associated with this method are the same format - and name as those used by a client (see - :py:class:`keystoneclient.v2_0.client.Client` and - :py:class:`keystoneclient.v3.client.Client`). If not overridden in - subsequent methods they will also be what is passed to the constructed - client. - - In the event that auth_url and endpoint is provided then auth_url will be - used in accordance with how the client operates. - - :param session: A session object that will be used for communication. - Clients will also be constructed with this session. - :type session: keystoneclient.session.Session - :param string auth_url: Identity service endpoint for authorization. - (optional) - :param string endpoint: A user-supplied endpoint URL for the identity - service. (optional) - :param string original_ip: The original IP of the requesting user which - will be sent to identity service in a - 'Forwarded' header. (optional) DEPRECATED: use - the session object. This is ignored if a session - is provided. - :param boolean debug: Enables debug logging of all request and responses to - the identity service. default False (optional) - DEPRECATED: use the session object. This is ignored - if a session is provided. - :param string cacert: Path to the Privacy Enhanced Mail (PEM) file which - contains the trusted authority X.509 certificates - needed to established SSL connection with the - identity service. (optional) DEPRECATED: use the - session object. This is ignored if a session is - provided. - :param string key: Path to the Privacy Enhanced Mail (PEM) file which - contains the unencrypted client private key needed to - established two-way SSL connection with the identity - service. (optional) DEPRECATED: use the session object. - This is ignored if a session is provided. - :param string cert: Path to the Privacy Enhanced Mail (PEM) file which - contains the corresponding X.509 client certificate - needed to established two-way SSL connection with the - identity service. (optional) DEPRECATED: use the - session object. This is ignored if a session is - provided. - :param boolean insecure: Does not perform X.509 certificate validation when - establishing SSL connection with identity service. - default: False (optional) DEPRECATED: use the - session object. This is ignored if a session is - provided. - :param bool authenticated: Should a token be used to perform the initial - discovery operations. default: None (attach a - token if an auth plugin is available). - - """ - - @utils.positional(2) - def __init__(self, session=None, authenticated=None, **kwargs): - if not session: - session = client_session.Session.construct(kwargs) - kwargs['session'] = session - - url = None - endpoint = kwargs.pop('endpoint', None) - auth_url = kwargs.pop('auth_url', None) - - if endpoint: - self._use_endpoint = True - url = endpoint - elif auth_url: - self._use_endpoint = False - url = auth_url - - if not url: - raise exceptions.DiscoveryFailure( - _('Not enough information to determine URL. Provide either ' - 'auth_url or endpoint')) - - self._client_kwargs = kwargs - super(Discover, self).__init__(session, url, - authenticated=authenticated) - - def available_versions(self, **kwargs): - """Return a list of identity APIs available on the server and the data - associated with them. - - DEPRECATED: use raw_version_data() - - :param bool unstable: Accept endpoints not marked 'stable'. (optional) - DEPRECTED. Equates to setting allow_experimental - and allow_unknown to True. - :param bool allow_experimental: Allow experimental version endpoints. - :param bool allow_deprecated: Allow deprecated version endpoints. - :param bool allow_unknown: Allow endpoints with an unrecognised status. - - :returns: A List of dictionaries as presented by the server. Each dict - will contain the version and the URL to use for the version. - It is a direct representation of the layout presented by the - identity API. - """ - return self.raw_version_data(**kwargs) - - def raw_version_data(self, unstable=False, **kwargs): - """Get raw version information from URL. - - Raw data indicates that only minimal validation processing is performed - on the data, so what is returned here will be the data in the same - format it was received from the endpoint. - - :param bool unstable: (deprecated) equates to setting - allow_experimental and allow_unknown. - :param bool allow_experimental: Allow experimental version endpoints. - :param bool allow_deprecated: Allow deprecated version endpoints. - :param bool allow_unknown: Allow endpoints with an unrecognised status. - - :returns: The endpoints returned from the server that match the - criteria. - :rtype: list - - Example:: - - >>> from keystoneclient import discover - >>> disc = discover.Discovery(auth_url='http://localhost:5000') - >>> disc.raw_version_data() - [{'id': 'v3.0', - 'links': [{'href': u'http://127.0.0.1:5000/v3/', - 'rel': u'self'}], - 'media-types': [ - {'base': 'application/json', - 'type': 'application/vnd.openstack.identity-v3+json'}, - {'base': 'application/xml', - 'type': 'application/vnd.openstack.identity-v3+xml'}], - 'status': 'stable', - 'updated': '2013-03-06T00:00:00Z'}, - {'id': 'v2.0', - 'links': [{'href': u'http://127.0.0.1:5000/v2.0/', - 'rel': u'self'}, - {'href': u'...', - 'rel': u'describedby', - 'type': u'application/pdf'}], - 'media-types': [ - {'base': 'application/json', - 'type': 'application/vnd.openstack.identity-v2.0+json'}, - {'base': 'application/xml', - 'type': 'application/vnd.openstack.identity-v2.0+xml'}], - 'status': 'stable', - 'updated': '2013-03-06T00:00:00Z'}] - """ - if unstable: - kwargs.setdefault('allow_experimental', True) - kwargs.setdefault('allow_unknown', True) - - return super(Discover, self).raw_version_data(**kwargs) - - def _calculate_version(self, version, unstable): - version_data = None - - if version: - version_data = self.data_for(version) - else: - # if no version specified pick the latest one - all_versions = self.version_data(unstable=unstable) - if all_versions: - version_data = all_versions[-1] - - if not version_data: - msg = _('Could not find a suitable endpoint') - - if version: - msg = _('Could not find a suitable endpoint for client ' - 'version: %s') % str(version) - - raise exceptions.VersionNotAvailable(msg) - - return version_data - - def _create_client(self, version_data, **kwargs): - # Get the client for the version requested that was returned - try: - client_class = _CLIENT_VERSIONS[version_data['version'][0]] - except KeyError: - version = '.'.join(str(v) for v in version_data['version']) - msg = _('No client available for version: %s') % version - raise exceptions.DiscoveryFailure(msg) - - # kwargs should take priority over stored kwargs. - for k, v in six.iteritems(self._client_kwargs): - kwargs.setdefault(k, v) - - # restore the url to either auth_url or endpoint depending on what - # was initially given - if self._use_endpoint: - kwargs['auth_url'] = None - kwargs['endpoint'] = version_data['url'] - else: - kwargs['auth_url'] = version_data['url'] - kwargs['endpoint'] = None - - return client_class(**kwargs) - - def create_client(self, version=None, unstable=False, **kwargs): - """Factory function to create a new identity service client. - - :param tuple version: The required version of the identity API. If - specified the client will be selected such that - the major version is equivalent and an endpoint - provides at least the specified minor version. - For example to specify the 3.1 API use (3, 1). - (optional) - :param bool unstable: Accept endpoints not marked 'stable'. (optional) - :param kwargs: Additional arguments will override those provided to - this object's constructor. - - :returns: An instantiated identity client object. - - :raises keystoneclient.exceptions.DiscoveryFailure: if the server - response is invalid - :raises keystoneclient.exceptions.VersionNotAvailable: if a suitable - client cannot be found. - """ - version_data = self._calculate_version(version, unstable) - return self._create_client(version_data, **kwargs) - - -def add_catalog_discover_hack(service_type, old, new): - """Adds a version removal rule for a particular service. - - Originally deployments of OpenStack would contain a versioned endpoint in - the catalog for different services. E.g. an identity service might look - like ``http://localhost:5000/v2.0``. This is a problem when we want to use - a different version like v3.0 as there is no way to tell where it is - located. We cannot simply change all service catalogs either so there must - be a way to handle the older style of catalog. - - This function adds a rule for a given service type that if part of the URL - matches a given regular expression in *old* then it will be replaced with - the *new* value. This will replace all instances of old with new. It should - therefore contain a regex anchor. - - For example the included rule states:: - - add_catalog_version_hack('identity', re.compile('/v2.0/?$'), '/') - - so if the catalog retrieves an *identity* URL that ends with /v2.0 or - /v2.0/ then it should replace it simply with / to fix the user's catalog. - - :param str service_type: The service type as defined in the catalog that - the rule will apply to. - :param re.RegexObject old: The regular expression to search for and replace - if found. - :param str new: The new string to replace the pattern with. - """ - _discover._VERSION_HACKS.add_discover_hack(service_type, old, new) diff --git a/awx/lib/site-packages/keystoneclient/exceptions.py b/awx/lib/site-packages/keystoneclient/exceptions.py deleted file mode 100644 index 0150bf528f..0000000000 --- a/awx/lib/site-packages/keystoneclient/exceptions.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -Exception definitions. - -.. py:exception:: AuthorizationFailure - -.. py:exception:: ClientException - -.. py:exception:: HttpError - -.. py:exception:: ValidationError - -.. py:exception:: Unauthorized - -""" - -from keystoneclient.i18n import _ -from keystoneclient.openstack.common.apiclient.exceptions import * # noqa - -# NOTE(akurilin): This alias should be left here to support backwards -# compatibility until we are sure that usage of these exceptions in -# projects is correct. -ConnectionError = ConnectionRefused -HTTPNotImplemented = HttpNotImplemented -Timeout = RequestTimeout -HTTPError = HttpError - - -class CertificateConfigError(Exception): - """Error reading the certificate.""" - def __init__(self, output): - self.output = output - msg = _('Unable to load certificate.') - super(CertificateConfigError, self).__init__(msg) - - -class CMSError(Exception): - """Error reading the certificate.""" - def __init__(self, output): - self.output = output - msg = _('Unable to sign or verify data.') - super(CMSError, self).__init__(msg) - - -class EmptyCatalog(EndpointNotFound): - """The service catalog is empty.""" - pass - - -class SSLError(ConnectionRefused): - """An SSL error occurred.""" - - -class DiscoveryFailure(ClientException): - """Discovery of client versions failed.""" - - -class VersionNotAvailable(DiscoveryFailure): - """Discovery failed as the version you requested is not available.""" - - -class MethodNotImplemented(ClientException): - """Method not implemented by the keystoneclient API.""" - - -class MissingAuthPlugin(ClientException): - """An authenticated request is required but no plugin available.""" - - -class NoMatchingPlugin(ClientException): - """There were no auth plugins that could be created from the parameters - provided. - - :param str name: The name of the plugin that was attempted to load. - - .. py:attribute:: name - - The name of the plugin that was attempted to load. - """ - - def __init__(self, name): - self.name = name - msg = _('The plugin %s could not be found') % name - super(NoMatchingPlugin, self).__init__(msg) - - -class InvalidResponse(ClientException): - """The response from the server is not valid for this request.""" - - def __init__(self, response): - super(InvalidResponse, self).__init__() - self.response = response diff --git a/awx/lib/site-packages/keystoneclient/fixture/__init__.py b/awx/lib/site-packages/keystoneclient/fixture/__init__.py deleted file mode 100644 index ad937040ca..0000000000 --- a/awx/lib/site-packages/keystoneclient/fixture/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -The generators in this directory produce keystone compliant structures for use -in testing. - -They should be considered part of the public API because they may be relied -upon to generate test tokens for other clients. However they should never be -imported into the main client (keystoneclient or other). Because of this there -may be dependencies from this module on libraries that are only available in -testing. -""" - -from keystoneclient.fixture.discovery import * # noqa -from keystoneclient.fixture.exception import FixtureValidationError # noqa -from keystoneclient.fixture.v2 import Token as V2Token # noqa -from keystoneclient.fixture.v3 import Token as V3Token # noqa -from keystoneclient.fixture.v3 import V3FederationToken # noqa - -__all__ = ['DiscoveryList', - 'FixtureValidationError', - 'V2Discovery', - 'V3Discovery', - 'V2Token', - 'V3Token', - 'V3FederationToken', - ] diff --git a/awx/lib/site-packages/keystoneclient/fixture/discovery.py b/awx/lib/site-packages/keystoneclient/fixture/discovery.py deleted file mode 100644 index eae0bcdc31..0000000000 --- a/awx/lib/site-packages/keystoneclient/fixture/discovery.py +++ /dev/null @@ -1,260 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -from oslo_utils import timeutils - -from keystoneclient import utils - -__all__ = ['DiscoveryList', - 'V2Discovery', - 'V3Discovery', - ] - -_DEFAULT_DAYS_AGO = 30 - - -class DiscoveryBase(dict): - """The basic version discovery structure. - - All version discovery elements should have access to these values. - - :param string id: The version id for this version entry. - :param string status: The status of this entry. - :param DateTime updated: When the API was last updated. - """ - - @utils.positional() - def __init__(self, id, status=None, updated=None): - super(DiscoveryBase, self).__init__() - - self.id = id - self.status = status or 'stable' - self.updated = updated or (timeutils.utcnow() - - datetime.timedelta(days=_DEFAULT_DAYS_AGO)) - - @property - def id(self): - return self.get('id') - - @id.setter - def id(self, value): - self['id'] = value - - @property - def status(self): - return self.get('status') - - @status.setter - def status(self, value): - self['status'] = value - - @property - def links(self): - return self.setdefault('links', []) - - @property - def updated_str(self): - return self.get('updated') - - @updated_str.setter - def updated_str(self, value): - self['updated'] = value - - @property - def updated(self): - return timeutils.parse_isotime(self.updated_str) - - @updated.setter - def updated(self, value): - self.updated_str = timeutils.isotime(value) - - @utils.positional() - def add_link(self, href, rel='self', type=None): - link = {'href': href, 'rel': rel} - if type: - link['type'] = type - self.links.append(link) - return link - - @property - def media_types(self): - return self.setdefault('media-types', []) - - @utils.positional(1) - def add_media_type(self, base, type): - mt = {'base': base, 'type': type} - self.media_types.append(mt) - return mt - - -class V2Discovery(DiscoveryBase): - """A Version element for a V2 identity service endpoint. - - Provides some default values and helper methods for creating a v2.0 - endpoint version structure. Clients should use this instead of creating - their own structures. - - :param string href: The url that this entry should point to. - :param string id: The version id that should be reported. (optional) - Defaults to 'v2.0'. - :param bool html: Add HTML describedby links to the structure. - :param bool pdf: Add PDF describedby links to the structure. - - """ - - _DESC_URL = 'http://docs.openstack.org/api/openstack-identity-service/2.0/' - - @utils.positional() - def __init__(self, href, id=None, html=True, pdf=True, **kwargs): - super(V2Discovery, self).__init__(id or 'v2.0', **kwargs) - - self.add_link(href) - - if html: - self.add_html_description() - if pdf: - self.add_pdf_description() - - def add_html_description(self): - """Add the HTML described by links. - - The standard structure includes a link to a HTML document with the - API specification. Add it to this entry. - """ - self.add_link(href=self._DESC_URL + 'content', - rel='describedby', - type='text/html') - - def add_pdf_description(self): - """Add the PDF described by links. - - The standard structure includes a link to a PDF document with the - API specification. Add it to this entry. - """ - self.add_link(href=self._DESC_URL + 'identity-dev-guide-2.0.pdf', - rel='describedby', - type='application/pdf') - - -class V3Discovery(DiscoveryBase): - """A Version element for a V3 identity service endpoint. - - Provides some default values and helper methods for creating a v3 - endpoint version structure. Clients should use this instead of creating - their own structures. - - :param href: The url that this entry should point to. - :param string id: The version id that should be reported. (optional) - Defaults to 'v3.0'. - :param bool json: Add JSON media-type elements to the structure. - :param bool xml: Add XML media-type elements to the structure. - """ - - @utils.positional() - def __init__(self, href, id=None, json=True, xml=True, **kwargs): - super(V3Discovery, self).__init__(id or 'v3.0', **kwargs) - - self.add_link(href) - - if json: - self.add_json_media_type() - if xml: - self.add_xml_media_type() - - def add_json_media_type(self): - """Add the JSON media-type links. - - The standard structure includes a list of media-types that the endpoint - supports. Add JSON to the list. - """ - self.add_media_type(base='application/json', - type='application/vnd.openstack.identity-v3+json') - - def add_xml_media_type(self): - """Add the XML media-type links. - - The standard structure includes a list of media-types that the endpoint - supports. Add XML to the list. - """ - self.add_media_type(base='application/xml', - type='application/vnd.openstack.identity-v3+xml') - - -class DiscoveryList(dict): - """A List of version elements. - - Creates a correctly structured list of identity service endpoints for - use in testing with discovery. - - :param string href: The url that this should be based at. - :param bool v2: Add a v2 element. - :param bool v3: Add a v3 element. - :param string v2_status: The status to use for the v2 element. - :param DateTime v2_updated: The update time to use for the v2 element. - :param bool v2_html: True to add a html link to the v2 element. - :param bool v2_pdf: True to add a pdf link to the v2 element. - :param string v3_status: The status to use for the v3 element. - :param DateTime v3_updated: The update time to use for the v3 element. - :param bool v3_json: True to add a html link to the v2 element. - :param bool v3_xml: True to add a pdf link to the v2 element. - """ - - TEST_URL = 'http://keystone.host:5000/' - - @utils.positional(2) - def __init__(self, href=None, v2=True, v3=True, v2_id=None, v3_id=None, - v2_status=None, v2_updated=None, v2_html=True, v2_pdf=True, - v3_status=None, v3_updated=None, v3_json=True, v3_xml=True): - super(DiscoveryList, self).__init__(versions={'values': []}) - - href = href or self.TEST_URL - - if v2: - v2_href = href.rstrip('/') + '/v2.0' - self.add_v2(v2_href, id=v2_id, status=v2_status, - updated=v2_updated, html=v2_html, pdf=v2_pdf) - - if v3: - v3_href = href.rstrip('/') + '/v3' - self.add_v3(v3_href, id=v3_id, status=v3_status, - updated=v3_updated, json=v3_json, xml=v3_xml) - - @property - def versions(self): - return self['versions']['values'] - - def add_version(self, version): - """Add a new version structure to the list. - - :param dict version: A new version structure to add to the list. - """ - self.versions.append(version) - - def add_v2(self, href, **kwargs): - """Add a v2 version to the list. - - The parameters are the same as V2Discovery. - """ - obj = V2Discovery(href, **kwargs) - self.add_version(obj) - return obj - - def add_v3(self, href, **kwargs): - """Add a v3 version to the list. - - The parameters are the same as V3Discovery. - """ - obj = V3Discovery(href, **kwargs) - self.add_version(obj) - return obj diff --git a/awx/lib/site-packages/keystoneclient/fixture/exception.py b/awx/lib/site-packages/keystoneclient/fixture/exception.py deleted file mode 100644 index 416a3cf45b..0000000000 --- a/awx/lib/site-packages/keystoneclient/fixture/exception.py +++ /dev/null @@ -1,20 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class FixtureValidationError(Exception): - """The token you created is not legitimate. - - The data contained in the token that was generated is not valid and would - not have been returned from a keystone server. You should not do testing - with this token. - """ diff --git a/awx/lib/site-packages/keystoneclient/fixture/v2.py b/awx/lib/site-packages/keystoneclient/fixture/v2.py deleted file mode 100644 index cd4207b5f5..0000000000 --- a/awx/lib/site-packages/keystoneclient/fixture/v2.py +++ /dev/null @@ -1,215 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime -import uuid - -from oslo_utils import timeutils - -from keystoneclient.fixture import exception - - -class _Service(dict): - - def add_endpoint(self, public, admin=None, internal=None, - tenant_id=None, region=None): - data = {'tenantId': tenant_id or uuid.uuid4().hex, - 'publicURL': public, - 'adminURL': admin or public, - 'internalURL': internal or public, - 'region': region} - - self.setdefault('endpoints', []).append(data) - return data - - -class Token(dict): - """A V2 Keystone token that can be used for testing. - - This object is designed to allow clients to generate a correct V2 token for - use in there test code. It should prevent clients from having to know the - correct token format and allow them to test the portions of token handling - that matter to them and not copy and paste sample. - """ - - def __init__(self, token_id=None, expires=None, issued=None, - tenant_id=None, tenant_name=None, user_id=None, - user_name=None, trust_id=None, trustee_user_id=None): - super(Token, self).__init__() - - self.token_id = token_id or uuid.uuid4().hex - self.user_id = user_id or uuid.uuid4().hex - self.user_name = user_name or uuid.uuid4().hex - - if not issued: - issued = timeutils.utcnow() - datetime.timedelta(minutes=2) - if not expires: - expires = issued + datetime.timedelta(hours=1) - - try: - self.issued = issued - except (TypeError, AttributeError): - # issued should be able to be passed as a string so ignore - self.issued_str = issued - - try: - self.expires = expires - except (TypeError, AttributeError): - # expires should be able to be passed as a string so ignore - self.expires_str = expires - - if tenant_id or tenant_name: - self.set_scope(tenant_id, tenant_name) - - if trust_id or trustee_user_id: - # the trustee_user_id will generally be the same as the user_id as - # the token is being issued to the trustee - self.set_trust(id=trust_id, - trustee_user_id=trustee_user_id or user_id) - - @property - def root(self): - return self.setdefault('access', {}) - - @property - def _token(self): - return self.root.setdefault('token', {}) - - @property - def token_id(self): - return self._token['id'] - - @token_id.setter - def token_id(self, value): - self._token['id'] = value - - @property - def expires_str(self): - return self._token['expires'] - - @expires_str.setter - def expires_str(self, value): - self._token['expires'] = value - - @property - def expires(self): - return timeutils.parse_isotime(self.expires_str) - - @expires.setter - def expires(self, value): - self.expires_str = timeutils.isotime(value) - - @property - def issued_str(self): - return self._token['issued_at'] - - @issued_str.setter - def issued_str(self, value): - self._token['issued_at'] = value - - @property - def issued(self): - return timeutils.parse_isotime(self.issued_str) - - @issued.setter - def issued(self, value): - self.issued_str = timeutils.isotime(value) - - @property - def _user(self): - return self.root.setdefault('user', {}) - - @property - def user_id(self): - return self._user['id'] - - @user_id.setter - def user_id(self, value): - self._user['id'] = value - - @property - def user_name(self): - return self._user['name'] - - @user_name.setter - def user_name(self, value): - self._user['name'] = value - - @property - def tenant_id(self): - return self._token.get('tenant', {}).get('id') - - @tenant_id.setter - def tenant_id(self, value): - self._token.setdefault('tenant', {})['id'] = value - - @property - def tenant_name(self): - return self._token.get('tenant', {}).get('name') - - @tenant_name.setter - def tenant_name(self, value): - self._token.setdefault('tenant', {})['name'] = value - - @property - def _metadata(self): - return self.root.setdefault('metadata', {}) - - @property - def trust_id(self): - return self.root.setdefault('trust', {})['id'] - - @trust_id.setter - def trust_id(self, value): - self.root.setdefault('trust', {})['id'] = value - - @property - def trustee_user_id(self): - return self.root.setdefault('trust', {}).get('trustee_user_id') - - @trustee_user_id.setter - def trustee_user_id(self, value): - self.root.setdefault('trust', {})['trustee_user_id'] = value - - def validate(self): - scoped = 'tenant' in self.token - catalog = self.root.get('serviceCatalog') - - if catalog and not scoped: - msg = 'You cannot have a service catalog on an unscoped token' - raise exception.FixtureValidationError(msg) - - if scoped and not self.user.get('roles'): - msg = 'You must have roles on a token to scope it' - raise exception.FixtureValidationError(msg) - - def add_role(self, name=None, id=None): - id = id or uuid.uuid4().hex - name = name or uuid.uuid4().hex - roles = self._user.setdefault('roles', []) - roles.append({'name': name}) - self._metadata.setdefault('roles', []).append(id) - return {'id': id, 'name': name} - - def add_service(self, type, name=None): - name = name or uuid.uuid4().hex - service = _Service(name=name, type=type) - self.root.setdefault('serviceCatalog', []).append(service) - return service - - def set_scope(self, id=None, name=None): - self.tenant_id = id or uuid.uuid4().hex - self.tenant_name = name or uuid.uuid4().hex - - def set_trust(self, id=None, trustee_user_id=None): - self.trust_id = id or uuid.uuid4().hex - self.trustee_user_id = trustee_user_id or uuid.uuid4().hex diff --git a/awx/lib/site-packages/keystoneclient/fixture/v3.py b/awx/lib/site-packages/keystoneclient/fixture/v3.py deleted file mode 100644 index 4f3d1f14bc..0000000000 --- a/awx/lib/site-packages/keystoneclient/fixture/v3.py +++ /dev/null @@ -1,384 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime -import uuid - -from oslo_utils import timeutils - -from keystoneclient.fixture import exception - - -class _Service(dict): - """One of the services that exist in the catalog. - - You use this by adding a service to a token which returns an instance of - this object and then you can add_endpoints to the service. - """ - - def add_endpoint(self, interface, url, region=None): - data = {'interface': interface, - 'url': url, - 'region': region, - 'region_id': region} - self.setdefault('endpoints', []).append(data) - return data - - def add_standard_endpoints(self, public=None, admin=None, internal=None, - region=None): - ret = [] - - if public: - ret.append(self.add_endpoint('public', public, region=region)) - if admin: - ret.append(self.add_endpoint('admin', admin, region=region)) - if internal: - ret.append(self.add_endpoint('internal', internal, region=region)) - - return ret - - -class Token(dict): - """A V3 Keystone token that can be used for testing. - - This object is designed to allow clients to generate a correct V3 token for - use in there test code. It should prevent clients from having to know the - correct token format and allow them to test the portions of token handling - that matter to them and not copy and paste sample. - """ - - def __init__(self, expires=None, issued=None, user_id=None, user_name=None, - user_domain_id=None, user_domain_name=None, methods=None, - project_id=None, project_name=None, project_domain_id=None, - project_domain_name=None, domain_id=None, domain_name=None, - trust_id=None, trust_impersonation=None, trustee_user_id=None, - trustor_user_id=None, oauth_access_token_id=None, - oauth_consumer_id=None): - super(Token, self).__init__() - - self.user_id = user_id or uuid.uuid4().hex - self.user_name = user_name or uuid.uuid4().hex - self.user_domain_id = user_domain_id or uuid.uuid4().hex - self.user_domain_name = user_domain_name or uuid.uuid4().hex - - if not methods: - methods = ['password'] - self.methods.extend(methods) - - if not issued: - issued = timeutils.utcnow() - datetime.timedelta(minutes=2) - - try: - self.issued = issued - except (TypeError, AttributeError): - # issued should be able to be passed as a string so ignore - self.issued_str = issued - - if not expires: - expires = self.issued + datetime.timedelta(hours=1) - - try: - self.expires = expires - except (TypeError, AttributeError): - # expires should be able to be passed as a string so ignore - self.expires_str = expires - - if (project_id or project_name or - project_domain_id or project_domain_name): - self.set_project_scope(id=project_id, - name=project_name, - domain_id=project_domain_id, - domain_name=project_domain_name) - - if domain_id or domain_name: - self.set_domain_scope(id=domain_id, name=domain_name) - - if (trust_id or (trust_impersonation is not None) or - trustee_user_id or trustor_user_id): - self.set_trust_scope(id=trust_id, - impersonation=trust_impersonation, - trustee_user_id=trustee_user_id, - trustor_user_id=trustor_user_id) - - if oauth_access_token_id or oauth_consumer_id: - self.set_oauth(access_token_id=oauth_access_token_id, - consumer_id=oauth_consumer_id) - - @property - def root(self): - return self.setdefault('token', {}) - - @property - def expires_str(self): - return self.root.get('expires_at') - - @expires_str.setter - def expires_str(self, value): - self.root['expires_at'] = value - - @property - def expires(self): - return timeutils.parse_isotime(self.expires_str) - - @expires.setter - def expires(self, value): - self.expires_str = timeutils.isotime(value, subsecond=True) - - @property - def issued_str(self): - return self.root.get('issued_at') - - @issued_str.setter - def issued_str(self, value): - self.root['issued_at'] = value - - @property - def issued(self): - return timeutils.parse_isotime(self.issued_str) - - @issued.setter - def issued(self, value): - self.issued_str = timeutils.isotime(value, subsecond=True) - - @property - def _user(self): - return self.root.setdefault('user', {}) - - @property - def user_id(self): - return self._user.get('id') - - @user_id.setter - def user_id(self, value): - self._user['id'] = value - - @property - def user_name(self): - return self._user.get('name') - - @user_name.setter - def user_name(self, value): - self._user['name'] = value - - @property - def _user_domain(self): - return self._user.setdefault('domain', {}) - - @property - def user_domain_id(self): - return self._user_domain.get('id') - - @user_domain_id.setter - def user_domain_id(self, value): - self._user_domain['id'] = value - - @property - def user_domain_name(self): - return self._user_domain.get('name') - - @user_domain_name.setter - def user_domain_name(self, value): - self._user_domain['name'] = value - - @property - def methods(self): - return self.root.setdefault('methods', []) - - @property - def project_id(self): - return self.root.get('project', {}).get('id') - - @project_id.setter - def project_id(self, value): - self.root.setdefault('project', {})['id'] = value - - @property - def project_name(self): - return self.root.get('project', {}).get('name') - - @project_name.setter - def project_name(self, value): - self.root.setdefault('project', {})['name'] = value - - @property - def project_domain_id(self): - return self.root.get('project', {}).get('domain', {}).get('id') - - @project_domain_id.setter - def project_domain_id(self, value): - project = self.root.setdefault('project', {}) - project.setdefault('domain', {})['id'] = value - - @property - def project_domain_name(self): - return self.root.get('project', {}).get('domain', {}).get('name') - - @project_domain_name.setter - def project_domain_name(self, value): - project = self.root.setdefault('project', {}) - project.setdefault('domain', {})['name'] = value - - @property - def domain_id(self): - return self.root.get('domain', {}).get('id') - - @domain_id.setter - def domain_id(self, value): - self.root.setdefault('domain', {})['id'] = value - - @property - def domain_name(self): - return self.root.get('domain', {}).get('name') - - @domain_name.setter - def domain_name(self, value): - self.root.setdefault('domain', {})['name'] = value - - @property - def trust_id(self): - return self.root.get('OS-TRUST:trust', {}).get('id') - - @trust_id.setter - def trust_id(self, value): - self.root.setdefault('OS-TRUST:trust', {})['id'] = value - - @property - def trust_impersonation(self): - return self.root.get('OS-TRUST:trust', {}).get('impersonation') - - @trust_impersonation.setter - def trust_impersonation(self, value): - self.root.setdefault('OS-TRUST:trust', {})['impersonation'] = value - - @property - def trustee_user_id(self): - trust = self.root.get('OS-TRUST:trust', {}) - return trust.get('trustee_user', {}).get('id') - - @trustee_user_id.setter - def trustee_user_id(self, value): - trust = self.root.setdefault('OS-TRUST:trust', {}) - trust.setdefault('trustee_user', {})['id'] = value - - @property - def trustor_user_id(self): - trust = self.root.get('OS-TRUST:trust', {}) - return trust.get('trustor_user', {}).get('id') - - @trustor_user_id.setter - def trustor_user_id(self, value): - trust = self.root.setdefault('OS-TRUST:trust', {}) - trust.setdefault('trustor_user', {})['id'] = value - - @property - def oauth_access_token_id(self): - return self.root.get('OS-OAUTH1', {}).get('access_token_id') - - @oauth_access_token_id.setter - def oauth_access_token_id(self, value): - self.root.setdefault('OS-OAUTH1', {})['access_token_id'] = value - - @property - def oauth_consumer_id(self): - return self.root.get('OS-OAUTH1', {}).get('consumer_id') - - @oauth_consumer_id.setter - def oauth_consumer_id(self, value): - self.root.setdefault('OS-OAUTH1', {})['consumer_id'] = value - - def validate(self): - project = self.root.get('project') - domain = self.root.get('domain') - trust = self.root.get('OS-TRUST:trust') - catalog = self.root.get('catalog') - roles = self.root.get('roles') - scoped = project or domain or trust - - if sum((bool(project), bool(domain), bool(trust))) > 1: - msg = 'You cannot scope to multiple targets' - raise exception.FixtureValidationError(msg) - - if catalog and not scoped: - msg = 'You cannot have a service catalog on an unscoped token' - raise exception.FixtureValidationError(msg) - - if scoped and not self.user.get('roles'): - msg = 'You must have roles on a token to scope it' - raise exception.FixtureValidationError(msg) - - if bool(scoped) != bool(roles): - msg = 'You must be scoped to have roles and vice-versa' - raise exception.FixtureValidationError(msg) - - def add_role(self, name=None, id=None): - roles = self.root.setdefault('roles', []) - data = {'id': id or uuid.uuid4().hex, - 'name': name or uuid.uuid4().hex} - roles.append(data) - return data - - def add_service(self, type, name=None): - service = _Service(type=type) - if name: - service['name'] = name - self.root.setdefault('catalog', []).append(service) - return service - - def set_project_scope(self, id=None, name=None, domain_id=None, - domain_name=None): - self.project_id = id or uuid.uuid4().hex - self.project_name = name or uuid.uuid4().hex - self.project_domain_id = domain_id or uuid.uuid4().hex - self.project_domain_name = domain_name or uuid.uuid4().hex - - def set_domain_scope(self, id=None, name=None): - self.domain_id = id or uuid.uuid4().hex - self.domain_name = name or uuid.uuid4().hex - - def set_trust_scope(self, id=None, impersonation=False, - trustee_user_id=None, trustor_user_id=None): - self.trust_id = id or uuid.uuid4().hex - self.trust_impersonation = impersonation - self.trustee_user_id = trustee_user_id or uuid.uuid4().hex - self.trustor_user_id = trustor_user_id or uuid.uuid4().hex - - def set_oauth(self, access_token_id=None, consumer_id=None): - self.oauth_access_token_id = access_token_id or uuid.uuid4().hex - self.oauth_consumer_id = consumer_id or uuid.uuid4().hex - - -class V3FederationToken(Token): - """A V3 Keystone Federation token that can be used for testing. - - Similar to V3Token, this object is designed to allow clients to generate - a correct V3 federation token for use in test code. - """ - - def __init__(self, methods=None, identity_provider=None, protocol=None, - groups=None): - methods = methods or ['saml2'] - super(V3FederationToken, self).__init__(methods=methods) - # NOTE(stevemar): Federated tokens do not have a domain for the user - del self._user['domain'] - self.add_federation_info_to_user(identity_provider, protocol, groups) - - def add_federation_info_to_user(self, identity_provider=None, - protocol=None, groups=None): - data = { - "OS-FEDERATION": { - "identity_provider": identity_provider or uuid.uuid4().hex, - "protocol": protocol or uuid.uuid4().hex, - "groups": groups or [{"id": uuid.uuid4().hex}] - } - } - self._user.update(data) - return data diff --git a/awx/lib/site-packages/keystoneclient/generic/__init__.py b/awx/lib/site-packages/keystoneclient/generic/__init__.py deleted file mode 100644 index ed59d727c1..0000000000 --- a/awx/lib/site-packages/keystoneclient/generic/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ - -__all__ = [ - 'client', -] diff --git a/awx/lib/site-packages/keystoneclient/generic/client.py b/awx/lib/site-packages/keystoneclient/generic/client.py deleted file mode 100644 index 7ca39fbced..0000000000 --- a/awx/lib/site-packages/keystoneclient/generic/client.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright 2010 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -from six.moves.urllib import parse as urlparse - -from keystoneclient import exceptions -from keystoneclient import httpclient -from keystoneclient.i18n import _, _LE - - -_logger = logging.getLogger(__name__) - - -class Client(httpclient.HTTPClient): - """Client for the OpenStack Keystone pre-version calls API. - - :param string endpoint: A user-supplied endpoint URL for the keystone - service. - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - - Example:: - - >>> from keystoneclient.generic import client - >>> root = client.Client(auth_url=KEYSTONE_URL) - >>> versions = root.discover() - ... - >>> from keystoneclient.v2_0 import client as v2client - >>> keystone = v2client.Client(auth_url=versions['v2.0']['url']) - ... - >>> user = keystone.users.get(USER_ID) - >>> user.delete() - - """ - - def __init__(self, endpoint=None, **kwargs): - """Initialize a new client for the Keystone v2.0 API.""" - super(Client, self).__init__(endpoint=endpoint, **kwargs) - self.endpoint = endpoint - - def discover(self, url=None): - """Discover Keystone servers and return API versions supported. - - :param url: optional url to test (without version) - - Returns:: - - { - 'message': 'Keystone found at http://127.0.0.1:5000/', - 'v2.0': { - 'status': 'beta', - 'url': 'http://127.0.0.1:5000/v2.0/', - 'id': 'v2.0' - }, - } - - """ - if url: - return self._check_keystone_versions(url) - else: - return self._local_keystone_exists() - - def _local_keystone_exists(self): - """Checks if Keystone is available on default local port 35357.""" - results = self._check_keystone_versions("http://localhost:35357") - if results is None: - results = self._check_keystone_versions("https://localhost:35357") - return results - - def _check_keystone_versions(self, url): - """Calls Keystone URL and detects the available API versions.""" - try: - resp, body = self.request(url, "GET", - headers={'Accept': - 'application/json'}) - # Multiple Choices status code is returned by the root - # identity endpoint, with references to one or more - # Identity API versions -- v3 spec - # some cases we get No Content - if resp.status_code in (200, 204, 300): - try: - results = {} - if 'version' in body: - results['message'] = _("Keystone found at %s") % url - version = body['version'] - # Stable/diablo incorrect format - id, status, version_url = ( - self._get_version_info(version, url)) - results[str(id)] = {"id": id, - "status": status, - "url": version_url} - return results - elif 'versions' in body: - # Correct format - results['message'] = _("Keystone found at %s") % url - for version in body['versions']['values']: - id, status, version_url = ( - self._get_version_info(version, url)) - results[str(id)] = {"id": id, - "status": status, - "url": version_url} - return results - else: - results['message'] = ( - _("Unrecognized response from %s") % url) - return results - except KeyError: - raise exceptions.AuthorizationFailure() - elif resp.status_code == 305: - return self._check_keystone_versions(resp['location']) - else: - raise exceptions.from_response(resp, "GET", url) - except Exception: - _logger.exception(_LE('Failed to detect available versions.')) - - def discover_extensions(self, url=None): - """Discover Keystone extensions supported. - - :param url: optional url to test (should have a version in it) - - Returns:: - - { - 'message': 'Keystone extensions at http://127.0.0.1:35357/v2', - 'OS-KSEC2': 'OpenStack EC2 Credentials Extension', - } - - """ - if url: - return self._check_keystone_extensions(url) - - def _check_keystone_extensions(self, url): - """Calls Keystone URL and detects the available extensions.""" - try: - if not url.endswith("/"): - url += '/' - resp, body = self.request("%sextensions" % url, "GET", - headers={'Accept': - 'application/json'}) - if resp.status_code in (200, 204): # some cases we get No Content - if 'extensions' in body and 'values' in body['extensions']: - # Parse correct format (per contract) - extensions = body['extensions']['values'] - elif 'extensions' in body: - # Support incorrect, but prevalent format - extensions = body['extensions'] - else: - return dict(message=( - _('Unrecognized extensions response from %s') % url)) - - return dict(self._get_extension_info(e) for e in extensions) - elif resp.status_code == 305: - return self._check_keystone_extensions(resp['location']) - else: - raise exceptions.from_response( - resp, "GET", "%sextensions" % url) - except Exception: - _logger.exception(_LE('Failed to check keystone extensions.')) - - @staticmethod - def _get_version_info(version, root_url): - """Parses version information. - - :param version: a dict of a Keystone version response - :param root_url: string url used to construct - the version if no URL is provided. - :returns: tuple - (verionId, versionStatus, versionUrl) - """ - id = version['id'] - status = version['status'] - ref = urlparse.urljoin(root_url, id) - if 'links' in version: - for link in version['links']: - if link['rel'] == 'self': - ref = link['href'] - break - return (id, status, ref) - - @staticmethod - def _get_extension_info(extension): - """Parses extension information. - - :param extension: a dict of a Keystone extension response - :returns: tuple - (alias, name) - """ - alias = extension['alias'] - name = extension['name'] - return (alias, name) diff --git a/awx/lib/site-packages/keystoneclient/generic/shell.py b/awx/lib/site-packages/keystoneclient/generic/shell.py deleted file mode 100644 index e5330a5667..0000000000 --- a/awx/lib/site-packages/keystoneclient/generic/shell.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2010 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from keystoneclient.generic import client -from keystoneclient.i18n import _ -from keystoneclient import utils - - -CLIENT_CLASS = client.Client - - -@utils.unauthenticated -def do_discover(cs, args): - """Discover Keystone servers, supported API versions and extensions. - """ - if cs.endpoint: - versions = cs.discover(cs.endpoint) - elif cs.auth_url: - versions = cs.discover(cs.auth_url) - else: - versions = cs.discover() - if versions: - if 'message' in versions: - print(versions['message']) - for key, version in six.iteritems(versions): - if key != 'message': - print(_(" - supports version %(id)s (%(status)s) here " - "%(url)s") % - version) - extensions = cs.discover_extensions(version['url']) - if extensions: - for key, extension in six.iteritems(extensions): - if key != 'message': - print(_(" - and %(key)s: %(extension)s") % - {'key': key, 'extension': extension}) - else: - print(_("No Keystone-compatible endpoint found")) diff --git a/awx/lib/site-packages/keystoneclient/hacking/__init__.py b/awx/lib/site-packages/keystoneclient/hacking/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/hacking/checks.py b/awx/lib/site-packages/keystoneclient/hacking/checks.py deleted file mode 100644 index 42826982a8..0000000000 --- a/awx/lib/site-packages/keystoneclient/hacking/checks.py +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""python-keystoneclient's pep8 extensions. - -In order to make the review process faster and easier for core devs we are -adding some python-keystoneclient specific pep8 checks. This will catch common -errors so that core devs don't have to. - -""" - - -import re - - -def check_oslo_namespace_imports(logical_line, blank_before, filename): - oslo_namespace_imports = re.compile( - r"(((from)|(import))\s+oslo\.)|(from\s+oslo\s+import\s+)") - - if re.match(oslo_namespace_imports, logical_line): - msg = ("K333: '%s' must be used instead of '%s'.") % ( - logical_line.replace('oslo.', 'oslo_'), - logical_line) - yield(0, msg) - - -def factory(register): - register(check_oslo_namespace_imports) diff --git a/awx/lib/site-packages/keystoneclient/httpclient.py b/awx/lib/site-packages/keystoneclient/httpclient.py deleted file mode 100644 index 3270295224..0000000000 --- a/awx/lib/site-packages/keystoneclient/httpclient.py +++ /dev/null @@ -1,798 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Piston Cloud Computing, Inc. -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -import logging - -from oslo_serialization import jsonutils -import pkg_resources -import requests -from six.moves.urllib import parse as urlparse - -try: - import pickle - - # NOTE(sdague): The conditional keyring import needs to only - # trigger if it's a version of keyring that's supported in global - # requirements. Update _min and _bad when that changes. - keyring_v = pkg_resources.parse_version( - pkg_resources.get_distribution("keyring").version) - keyring_min = pkg_resources.parse_version('2.1') - keyring_bad = (pkg_resources.parse_version('3.3'),) - - if keyring_v >= keyring_min and keyring_v not in keyring_bad: - import keyring - else: - keyring = None -except (ImportError, pkg_resources.DistributionNotFound): - keyring = None - pickle = None - -# Python 2.5 compat fix -if not hasattr(urlparse, 'parse_qsl'): - import cgi - urlparse.parse_qsl = cgi.parse_qsl - - -from keystoneclient import access -from keystoneclient import adapter -from keystoneclient.auth import base -from keystoneclient import baseclient -from keystoneclient import exceptions -from keystoneclient.i18n import _, _LW -from keystoneclient import session as client_session -from keystoneclient import utils - - -_logger = logging.getLogger(__name__) - -# These variables are moved and using them via httpclient is deprecated. -# Maintain here for compatibility. -USER_AGENT = client_session.USER_AGENT -request = client_session.request - - -class _FakeRequestSession(object): - """This object is a temporary hack that should be removed later. - - Keystoneclient has a cyclical dependency with its managers which is - preventing it from being cleaned up correctly. This is always bad but when - we switched to doing connection pooling this object wasn't getting cleaned - either and so we had left over TCP connections hanging around. - - Until we can fix the client cleanup we rollback the use of a requests - session and do individual connections like we used to. - """ - - def request(self, *args, **kwargs): - return requests.request(*args, **kwargs) - - -class _KeystoneAdapter(adapter.LegacyJsonAdapter): - """A wrapper layer to interface keystoneclient with a session. - - An adapter provides a generic interface between a client and the session to - provide client specific defaults. This object is passed to the managers. - Keystoneclient managers have some additional requirements of variables that - they expect to be present on the passed object. - - Subclass the existing adapter to provide those values that keystoneclient - managers expect. - """ - - @property - def user_id(self): - """Best effort to retrieve the user_id from the plugin. - - Some managers rely on being able to get the currently authenticated - user id. This is a problem when we are trying to abstract away the - details of an auth plugin. - - For example changing a user's password can require access to the - currently authenticated user_id. - - Perform a best attempt to fetch this data. It will work in the legacy - case and with identity plugins and be None otherwise which is the same - as the historical behavior. - """ - # the identity plugin case - try: - return self.session.auth.get_access(self.session).user_id - except AttributeError: - pass - - # there is a case that we explicity allow (tested by our unit tests) - # that says you should be able to set the user_id on a legacy client - # and it should overwrite the one retrieved via authentication. If it's - # a legacy then self.session.auth is a client and we retrieve user_id. - try: - return self.session.auth.user_id - except AttributeError: - pass - - return None - - -class HTTPClient(baseclient.Client, base.BaseAuthPlugin): - """HTTP client - - :param string user_id: User ID for authentication. (optional) - :param string username: Username for authentication. (optional) - :param string user_domain_id: User's domain ID for authentication. - (optional) - :param string user_domain_name: User's domain name for authentication. - (optional) - :param string password: Password for authentication. (optional) - :param string domain_id: Domain ID for domain scoping. (optional) - :param string domain_name: Domain name for domain scoping. (optional) - :param string project_id: Project ID for project scoping. (optional) - :param string project_name: Project name for project scoping. (optional) - :param string project_domain_id: Project's domain ID for project scoping. - (optional) - :param string project_domain_name: Project's domain name for project - scoping. (optional) - :param string auth_url: Identity service endpoint for authorization. - :param string region_name: Name of a region to select when choosing an - endpoint from the service catalog. - :param integer timeout: DEPRECATED: use session. (optional) - :param string endpoint: A user-supplied endpoint URL for the identity - service. Lazy-authentication is possible for API - service calls if endpoint is set at instantiation. - (optional) - :param string token: Token for authentication. (optional) - :param string cacert: DEPRECATED: use session. (optional) - :param string key: DEPRECATED: use session. (optional) - :param string cert: DEPRECATED: use session. (optional) - :param boolean insecure: DEPRECATED: use session. (optional) - :param string original_ip: DEPRECATED: use session. (optional) - :param boolean debug: DEPRECATED: use logging configuration. (optional) - :param dict auth_ref: To allow for consumers of the client to manage their - own caching strategy, you may initialize a client - with a previously captured auth_reference (token). If - there are keyword arguments passed that also exist in - auth_ref, the value from the argument will take - precedence. - :param boolean use_keyring: Enables caching auth_ref into keyring. - default: False (optional) - :param boolean force_new_token: Keyring related parameter, forces request - for new token. default: False (optional) - :param integer stale_duration: Gap in seconds to determine if token from - keyring is about to expire. default: 30 - (optional) - :param string tenant_name: Tenant name. (optional) The tenant_name keyword - argument is deprecated, use project_name - instead. - :param string tenant_id: Tenant id. (optional) The tenant_id keyword - argument is deprecated, use project_id instead. - :param string trust_id: Trust ID for trust scoping. (optional) - :param object session: A Session object to be used for - communicating with the identity service. - :type session: keystoneclient.session.Session - :param string service_name: The default service_name for URL discovery. - default: None (optional) - :param string interface: The default interface for URL discovery. - default: admin (optional) - :param string endpoint_override: Always use this endpoint URL for requests - for this client. (optional) - :param auth: An auth plugin to use instead of the session one. (optional) - :type auth: keystoneclient.auth.base.BaseAuthPlugin - :param string user_agent: The User-Agent string to set. - default: python-keystoneclient (optional) - :param int connect_retries: the maximum number of retries that should - be attempted for connection errors. - Default None - use session default which - is don't retry. (optional) - """ - - version = None - - @utils.positional(enforcement=utils.positional.WARN) - def __init__(self, username=None, tenant_id=None, tenant_name=None, - password=None, auth_url=None, region_name=None, endpoint=None, - token=None, debug=False, auth_ref=None, use_keyring=False, - force_new_token=False, stale_duration=None, user_id=None, - user_domain_id=None, user_domain_name=None, domain_id=None, - domain_name=None, project_id=None, project_name=None, - project_domain_id=None, project_domain_name=None, - trust_id=None, session=None, service_name=None, - interface='admin', endpoint_override=None, auth=None, - user_agent=USER_AGENT, connect_retries=None, **kwargs): - # set baseline defaults - self.user_id = None - self.username = None - self.user_domain_id = None - self.user_domain_name = None - - self.domain_id = None - self.domain_name = None - - self.project_id = None - self.project_name = None - self.project_domain_id = None - self.project_domain_name = None - - self.auth_url = None - self._endpoint = None - self._management_url = None - - self.trust_id = None - - # if loading from a dictionary passed in via auth_ref, - # load values from AccessInfo parsing that dictionary - if auth_ref: - self.auth_ref = access.AccessInfo.factory(**auth_ref) - self.version = self.auth_ref.version - self.user_id = self.auth_ref.user_id - self.username = self.auth_ref.username - self.user_domain_id = self.auth_ref.user_domain_id - self.domain_id = self.auth_ref.domain_id - self.domain_name = self.auth_ref.domain_name - self.project_id = self.auth_ref.project_id - self.project_name = self.auth_ref.project_name - self.project_domain_id = self.auth_ref.project_domain_id - self.auth_url = self.auth_ref.auth_url[0] - self._management_url = self.auth_ref.management_url[0] - self.auth_token_from_user = self.auth_ref.auth_token - self.trust_id = self.auth_ref.trust_id - if self.auth_ref.has_service_catalog() and not region_name: - region_name = self.auth_ref.service_catalog.region_name - else: - self.auth_ref = None - - # allow override of the auth_ref defaults from explicit - # values provided to the client - - # apply deprecated variables first, so modern variables override them - if tenant_id: - self.project_id = tenant_id - if tenant_name: - self.project_name = tenant_name - - # user-related attributes - self.password = password - if user_id: - self.user_id = user_id - if username: - self.username = username - if user_domain_id: - self.user_domain_id = user_domain_id - elif not (user_id or user_domain_name): - self.user_domain_id = 'default' - if user_domain_name: - self.user_domain_name = user_domain_name - - # domain-related attributes - if domain_id: - self.domain_id = domain_id - if domain_name: - self.domain_name = domain_name - - # project-related attributes - if project_id: - self.project_id = project_id - if project_name: - self.project_name = project_name - if project_domain_id: - self.project_domain_id = project_domain_id - elif not (project_id or project_domain_name): - self.project_domain_id = 'default' - if project_domain_name: - self.project_domain_name = project_domain_name - - # trust-related attributes - if trust_id: - self.trust_id = trust_id - - # endpoint selection - if auth_url: - self.auth_url = auth_url.rstrip('/') - if token: - self.auth_token_from_user = token - else: - self.auth_token_from_user = None - if endpoint: - self._endpoint = endpoint.rstrip('/') - self._auth_token = None - - if not session: - kwargs['session'] = _FakeRequestSession() - session = client_session.Session.construct(kwargs) - session.auth = self - - super(HTTPClient, self).__init__(session=session) - self.domain = '' - self.debug_log = debug - - # NOTE(jamielennox): unfortunately we can't just use **kwargs here as - # it would incompatibly limit the kwargs that can be passed to __init__ - # try and keep this list in sync with adapter.Adapter.__init__ - self._adapter = _KeystoneAdapter(session, - service_type='identity', - service_name=service_name, - interface=interface, - region_name=region_name, - endpoint_override=endpoint_override, - version=self.version, - auth=auth, - user_agent=user_agent, - connect_retries=connect_retries) - - # keyring setup - if use_keyring and keyring is None: - _logger.warning(_LW('Failed to load keyring modules.')) - self.use_keyring = use_keyring and keyring is not None - self.force_new_token = force_new_token - self.stale_duration = stale_duration or access.STALE_TOKEN_DURATION - self.stale_duration = int(self.stale_duration) - - def get_token(self, session, **kwargs): - return self.auth_token - - @property - def auth_token(self): - if self._auth_token: - return self._auth_token - if self.auth_ref: - if self.auth_ref.will_expire_soon(self.stale_duration): - self.authenticate() - return self.auth_ref.auth_token - if self.auth_token_from_user: - return self.auth_token_from_user - - def get_endpoint(self, session, interface=None, **kwargs): - if interface == 'public' or interface is base.AUTH_INTERFACE: - return self.auth_url - else: - return self.management_url - - def get_user_id(self, session, **kwargs): - return self.auth_ref.user_id - - def get_project_id(self, session, **kwargs): - return self.auth_ref.project_id - - @auth_token.setter - def auth_token(self, value): - """Override the auth_token. - - If an application sets auth_token explicitly then it will always be - used and override any past or future retrieved token. - """ - self._auth_token = value - - @auth_token.deleter - def auth_token(self): - self._auth_token = None - self.auth_token_from_user = None - - @property - def service_catalog(self): - """Returns this client's service catalog.""" - return self.auth_ref.service_catalog - - def has_service_catalog(self): - """Returns True if this client provides a service catalog.""" - return self.auth_ref and self.auth_ref.has_service_catalog() - - @property - def tenant_id(self): - """Provide read-only backwards compatibility for tenant_id. - This is deprecated, use project_id instead. - """ - return self.project_id - - @property - def tenant_name(self): - """Provide read-only backwards compatibility for tenant_name. - This is deprecated, use project_name instead. - """ - return self.project_name - - @utils.positional(enforcement=utils.positional.WARN) - def authenticate(self, username=None, password=None, tenant_name=None, - tenant_id=None, auth_url=None, token=None, - user_id=None, domain_name=None, domain_id=None, - project_name=None, project_id=None, user_domain_id=None, - user_domain_name=None, project_domain_id=None, - project_domain_name=None, trust_id=None, - region_name=None): - """Authenticate user. - - Uses the data provided at instantiation to authenticate against - the Identity server. This may use either a username and password - or token for authentication. If a tenant name or id was provided - then the resulting authenticated client will be scoped to that - tenant and contain a service catalog of available endpoints. - - With the v2.0 API, if a tenant name or ID is not provided, the - authentication token returned will be 'unscoped' and limited in - capabilities until a fully-scoped token is acquired. - - With the v3 API, if a domain name or id was provided then the resulting - authenticated client will be scoped to that domain. If a project name - or ID is not provided, and the authenticating user has a default - project configured, the authentication token returned will be 'scoped' - to the default project. Otherwise, the authentication token returned - will be 'unscoped' and limited in capabilities until a fully-scoped - token is acquired. - - With the v3 API, with the OS-TRUST extension enabled, the trust_id can - be provided to allow project-specific role delegation between users - - If successful, sets the self.auth_ref and self.auth_token with - the returned token. If not already set, will also set - self.management_url from the details provided in the token. - - :returns: ``True`` if authentication was successful. - :raises keystoneclient.exceptions.AuthorizationFailure: if unable to - authenticate or validate the existing authorization token - :raises keystoneclient.exceptions.ValueError: if insufficient - parameters are used. - - If keyring is used, token is retrieved from keyring instead. - Authentication will only be necessary if any of the following - conditions are met: - - * keyring is not used - * if token is not found in keyring - * if token retrieved from keyring is expired or about to - expired (as determined by stale_duration) - * if force_new_token is true - - """ - auth_url = auth_url or self.auth_url - user_id = user_id or self.user_id - username = username or self.username - password = password or self.password - - user_domain_id = user_domain_id or self.user_domain_id - user_domain_name = user_domain_name or self.user_domain_name - domain_id = domain_id or self.domain_id - domain_name = domain_name or self.domain_name - project_id = project_id or tenant_id or self.project_id - project_name = project_name or tenant_name or self.project_name - project_domain_id = project_domain_id or self.project_domain_id - project_domain_name = project_domain_name or self.project_domain_name - - trust_id = trust_id or self.trust_id - region_name = region_name or self._adapter.region_name - - if not token: - token = self.auth_token_from_user - if (not token and self.auth_ref and not - self.auth_ref.will_expire_soon(self.stale_duration)): - token = self.auth_ref.auth_token - - kwargs = { - 'auth_url': auth_url, - 'user_id': user_id, - 'username': username, - 'user_domain_id': user_domain_id, - 'user_domain_name': user_domain_name, - 'domain_id': domain_id, - 'domain_name': domain_name, - 'project_id': project_id, - 'project_name': project_name, - 'project_domain_id': project_domain_id, - 'project_domain_name': project_domain_name, - 'token': token, - 'trust_id': trust_id, - } - (keyring_key, auth_ref) = self.get_auth_ref_from_keyring(**kwargs) - new_token_needed = False - if auth_ref is None or self.force_new_token: - new_token_needed = True - kwargs['password'] = password - resp = self.get_raw_token_from_identity_service(**kwargs) - - if isinstance(resp, access.AccessInfo): - self.auth_ref = resp - else: - self.auth_ref = access.AccessInfo.factory(*resp) - - # NOTE(jamielennox): The original client relies on being able to - # push the region name into the service catalog but new auth - # it in. - if region_name: - self.auth_ref.service_catalog._region_name = region_name - else: - self.auth_ref = auth_ref - - self.process_token(region_name=region_name) - if new_token_needed: - self.store_auth_ref_into_keyring(keyring_key) - return True - - def _build_keyring_key(self, **kwargs): - """Create a unique key for keyring. - - Used to store and retrieve auth_ref from keyring. - - Returns a slash-separated string of values ordered by key name. - - """ - return '/'.join([kwargs[k] or '?' for k in sorted(kwargs.keys())]) - - def get_auth_ref_from_keyring(self, **kwargs): - """Retrieve auth_ref from keyring. - - If auth_ref is found in keyring, (keyring_key, auth_ref) is returned. - Otherwise, (keyring_key, None) is returned. - - :returns: (keyring_key, auth_ref) or (keyring_key, None) - :returns: or (None, None) if use_keyring is not set in the object - - """ - keyring_key = None - auth_ref = None - if self.use_keyring: - keyring_key = self._build_keyring_key(**kwargs) - try: - auth_ref = keyring.get_password("keystoneclient_auth", - keyring_key) - if auth_ref: - auth_ref = pickle.loads(auth_ref) - if auth_ref.will_expire_soon(self.stale_duration): - # token has expired, don't use it - auth_ref = None - except Exception as e: - auth_ref = None - _logger.warning( - _LW('Unable to retrieve token from keyring %s'), e) - return (keyring_key, auth_ref) - - def store_auth_ref_into_keyring(self, keyring_key): - """Store auth_ref into keyring. - - """ - if self.use_keyring: - try: - keyring.set_password("keystoneclient_auth", - keyring_key, - pickle.dumps(self.auth_ref)) - except Exception as e: - _logger.warning( - _LW("Failed to store token into keyring %s"), e) - - def _process_management_url(self, region_name): - try: - self._management_url = self.auth_ref.service_catalog.url_for( - service_type='identity', - endpoint_type='admin', - region_name=region_name) - except exceptions.EndpointNotFound: - pass - - def process_token(self, region_name=None): - """Extract and process information from the new auth_ref. - - And set the relevant authentication information. - """ - # if we got a response without a service catalog, set the local - # list of tenants for introspection, and leave to client user - # to determine what to do. Otherwise, load up the service catalog - if self.auth_ref.project_scoped: - if not self.auth_ref.tenant_id: - raise exceptions.AuthorizationFailure( - _("Token didn't provide tenant_id")) - self._process_management_url(region_name) - self.project_name = self.auth_ref.tenant_name - self.project_id = self.auth_ref.tenant_id - - if not self.auth_ref.user_id: - raise exceptions.AuthorizationFailure( - _("Token didn't provide user_id")) - - self.user_id = self.auth_ref.user_id - - self.auth_domain_id = self.auth_ref.domain_id - self.auth_tenant_id = self.auth_ref.tenant_id - self.auth_user_id = self.auth_ref.user_id - - @property - def management_url(self): - return self._endpoint or self._management_url - - @management_url.setter - def management_url(self, value): - # NOTE(jamielennox): it's debatable here whether we should set - # _endpoint or _management_url. As historically management_url was set - # permanently setting _endpoint would better match that behaviour. - self._endpoint = value - - @utils.positional(enforcement=utils.positional.WARN) - def get_raw_token_from_identity_service(self, auth_url, username=None, - password=None, tenant_name=None, - tenant_id=None, token=None, - user_id=None, user_domain_id=None, - user_domain_name=None, - domain_id=None, domain_name=None, - project_id=None, project_name=None, - project_domain_id=None, - project_domain_name=None, - trust_id=None): - """Authenticate against the Identity API and get a token. - - Not implemented here because auth protocols should be API - version-specific. - - Expected to authenticate or validate an existing authentication - reference already associated with the client. Invoking this call - *always* makes a call to the Identity service. - - :returns: (``resp``, ``body``) - - """ - raise NotImplementedError - - def serialize(self, entity): - return jsonutils.dumps(entity) - - def request(self, *args, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around requests.request to handle tasks such as - setting headers, JSON encoding/decoding, and error handling. - - .. warning:: - *DEPRECATED*: This function is no longer used. It was designed to - be used only by the managers and the managers now receive an - adapter so this function is no longer on the standard request path. - """ - kwargs.setdefault('authenticated', False) - return self._adapter.request(*args, **kwargs) - - def _cs_request(self, url, method, management=True, **kwargs): - """Makes an authenticated request to keystone endpoint by - concatenating self.management_url and url and passing in method and - any associated kwargs. - """ - # NOTE(jamielennox): This is deprecated and is no longer a part of the - # standard client request path. It now goes via the adapter instead. - if not management: - endpoint_filter = kwargs.setdefault('endpoint_filter', {}) - endpoint_filter.setdefault('interface', 'public') - - kwargs.setdefault('authenticated', None) - return self.request(url, method, **kwargs) - - def get(self, url, **kwargs): - """Perform an authenticated GET request. - - This calls :py:meth:`.request()` with ``method`` set to ``GET`` and an - authentication token if one is available. - - .. warning:: - *DEPRECATED*: This function is no longer used. It was designed to - be used by the managers and the managers now receive an adapter so - this function is no longer on the standard request path. - """ - return self._cs_request(url, 'GET', **kwargs) - - def head(self, url, **kwargs): - """Perform an authenticated HEAD request. - - This calls :py:meth:`.request()` with ``method`` set to ``HEAD`` and an - authentication token if one is available. - - .. warning:: - *DEPRECATED*: This function is no longer used. It was designed to - be used by the managers and the managers now receive an adapter so - this function is no longer on the standard request path. - """ - return self._cs_request(url, 'HEAD', **kwargs) - - def post(self, url, **kwargs): - """Perform an authenticate POST request. - - This calls :py:meth:`.request()` with ``method`` set to ``POST`` and an - authentication token if one is available. - - .. warning:: - *DEPRECATED*: This function is no longer used. It was designed to - be used by the managers and the managers now receive an adapter so - this function is no longer on the standard request path. - """ - return self._cs_request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - """Perform an authenticate PUT request. - - This calls :py:meth:`.request()` with ``method`` set to ``PUT`` and an - authentication token if one is available. - - .. warning:: - *DEPRECATED*: This function is no longer used. It was designed to - be used by the managers and the managers now receive an adapter so - this function is no longer on the standard request path. - """ - return self._cs_request(url, 'PUT', **kwargs) - - def patch(self, url, **kwargs): - """Perform an authenticate PATCH request. - - This calls :py:meth:`.request()` with ``method`` set to ``PATCH`` and - an authentication token if one is available. - - .. warning:: - *DEPRECATED*: This function is no longer used. It was designed to - be used by the managers and the managers now receive an adapter so - this function is no longer on the standard request path. - """ - return self._cs_request(url, 'PATCH', **kwargs) - - def delete(self, url, **kwargs): - """Perform an authenticate DELETE request. - - This calls :py:meth:`.request()` with ``method`` set to ``DELETE`` and - an authentication token if one is available. - - .. warning:: - *DEPRECATED*: This function is no longer used. It was designed to - be used by the managers and the managers now receive an adapter so - this function is no longer on the standard request path. - """ - return self._cs_request(url, 'DELETE', **kwargs) - - # DEPRECATIONS: The following methods are no longer directly supported - # but maintained for compatibility purposes. - - deprecated_session_variables = {'original_ip': None, - 'cert': None, - 'timeout': None, - 'verify_cert': 'verify'} - - deprecated_adapter_variables = {'region_name': None} - - def __getattr__(self, name): - # FIXME(jamielennox): provide a proper deprecated warning - try: - var_name = self.deprecated_session_variables[name] - except KeyError: - pass - else: - return getattr(self.session, var_name or name) - - try: - var_name = self.deprecated_adapter_variables[name] - except KeyError: - pass - else: - return getattr(self._adapter, var_name or name) - - raise AttributeError(_("Unknown Attribute: %s") % name) - - def __setattr__(self, name, val): - # FIXME(jamielennox): provide a proper deprecated warning - try: - var_name = self.deprecated_session_variables[name] - except KeyError: - pass - else: - return setattr(self.session, var_name or name) - - try: - var_name = self.deprecated_adapter_variables[name] - except KeyError: - pass - else: - return setattr(self._adapter, var_name or name) - - super(HTTPClient, self).__setattr__(name, val) diff --git a/awx/lib/site-packages/keystoneclient/i18n.py b/awx/lib/site-packages/keystoneclient/i18n.py deleted file mode 100644 index fc9a52b3d0..0000000000 --- a/awx/lib/site-packages/keystoneclient/i18n.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2014 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html . - -""" - -import oslo_i18n - - -_translators = oslo_i18n.TranslatorFactory(domain='keystoneclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/keystoneclient/locale/keystoneclient.pot b/awx/lib/site-packages/keystoneclient/locale/keystoneclient.pot deleted file mode 100644 index a966864842..0000000000 --- a/awx/lib/site-packages/keystoneclient/locale/keystoneclient.pot +++ /dev/null @@ -1,20 +0,0 @@ -# Translations template for python-keystoneclient. -# Copyright (C) 2012 ORGANIZATION -# This file is distributed under the same license as the -# python-keystoneclient project. -# FIRST AUTHOR <EMAIL@ADDRESS>, 2012. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: python-keystoneclient 0.1.3.12\n" -"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2012-09-29 16:02-0700\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 0.9.6\n" - diff --git a/awx/lib/site-packages/keystoneclient/middleware/__init__.py b/awx/lib/site-packages/keystoneclient/middleware/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/middleware/auth_token.py b/awx/lib/site-packages/keystoneclient/middleware/auth_token.py deleted file mode 100644 index c6a08a4f31..0000000000 --- a/awx/lib/site-packages/keystoneclient/middleware/auth_token.py +++ /dev/null @@ -1,1622 +0,0 @@ -# Copyright 2010-2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -TOKEN-BASED AUTH MIDDLEWARE - -.. warning:: - - This module is DEPRECATED. The auth_token middleware has been moved to the - `keystonemiddleware repository - <http://docs.openstack.org/developer/keystonemiddleware/>`_. - -This WSGI component: - -* Verifies that incoming client requests have valid tokens by validating - tokens with the auth service. -* Rejects unauthenticated requests UNLESS it is in 'delay_auth_decision' - mode, which means the final decision is delegated to the downstream WSGI - component (usually the OpenStack service) -* Collects and forwards identity information based on a valid token - such as user name, tenant, etc - -HEADERS -------- - -* Headers starting with HTTP\_ is a standard http header -* Headers starting with HTTP_X is an extended http header - -Coming in from initial call from client or customer -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -HTTP_X_AUTH_TOKEN - The client token being passed in. - -HTTP_X_STORAGE_TOKEN - The client token being passed in (legacy Rackspace use) to support - swift/cloud files - -Used for communication between components -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -WWW-Authenticate - HTTP header returned to a user indicating which endpoint to use - to retrieve a new token - -What we add to the request for use by the OpenStack service -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -HTTP_X_IDENTITY_STATUS - 'Confirmed' or 'Invalid' - The underlying service will only see a value of 'Invalid' if the Middleware - is configured to run in 'delay_auth_decision' mode - -HTTP_X_DOMAIN_ID - Identity service managed unique identifier, string. Only present if - this is a domain-scoped v3 token. - -HTTP_X_DOMAIN_NAME - Unique domain name, string. Only present if this is a domain-scoped - v3 token. - -HTTP_X_PROJECT_ID - Identity service managed unique identifier, string. Only present if - this is a project-scoped v3 token, or a tenant-scoped v2 token. - -HTTP_X_PROJECT_NAME - Project name, unique within owning domain, string. Only present if - this is a project-scoped v3 token, or a tenant-scoped v2 token. - -HTTP_X_PROJECT_DOMAIN_ID - Identity service managed unique identifier of owning domain of - project, string. Only present if this is a project-scoped v3 token. If - this variable is set, this indicates that the PROJECT_NAME can only - be assumed to be unique within this domain. - -HTTP_X_PROJECT_DOMAIN_NAME - Name of owning domain of project, string. Only present if this is a - project-scoped v3 token. If this variable is set, this indicates that - the PROJECT_NAME can only be assumed to be unique within this domain. - -HTTP_X_USER_ID - Identity-service managed unique identifier, string - -HTTP_X_USER_NAME - User identifier, unique within owning domain, string - -HTTP_X_USER_DOMAIN_ID - Identity service managed unique identifier of owning domain of - user, string. If this variable is set, this indicates that the USER_NAME - can only be assumed to be unique within this domain. - -HTTP_X_USER_DOMAIN_NAME - Name of owning domain of user, string. If this variable is set, this - indicates that the USER_NAME can only be assumed to be unique within - this domain. - -HTTP_X_ROLES - Comma delimited list of case-sensitive role names - -HTTP_X_SERVICE_CATALOG - json encoded keystone service catalog (optional). - For compatibility reasons this catalog will always be in the V2 catalog - format even if it is a v3 token. - -HTTP_X_TENANT_ID - *Deprecated* in favor of HTTP_X_PROJECT_ID - Identity service managed unique identifier, string. For v3 tokens, this - will be set to the same value as HTTP_X_PROJECT_ID - -HTTP_X_TENANT_NAME - *Deprecated* in favor of HTTP_X_PROJECT_NAME - Project identifier, unique within owning domain, string. For v3 tokens, - this will be set to the same value as HTTP_X_PROJECT_NAME - -HTTP_X_TENANT - *Deprecated* in favor of HTTP_X_TENANT_ID and HTTP_X_TENANT_NAME - Keystone-assigned unique identifier, string. For v3 tokens, this - will be set to the same value as HTTP_X_PROJECT_ID - -HTTP_X_USER - *Deprecated* in favor of HTTP_X_USER_ID and HTTP_X_USER_NAME - User name, unique within owning domain, string - -HTTP_X_ROLE - *Deprecated* in favor of HTTP_X_ROLES - Will contain the same values as HTTP_X_ROLES. - -OTHER ENVIRONMENT VARIABLES ---------------------------- - -keystone.token_info - Information about the token discovered in the process of - validation. This may include extended information returned by the - Keystone token validation call, as well as basic information about - the tenant and user. - -""" - -import contextlib -import datetime -import logging -import os -import stat -import tempfile -import time - -import netaddr -from oslo_config import cfg -from oslo_serialization import jsonutils -from oslo_utils import timeutils -import requests -import six -from six.moves import urllib - -from keystoneclient import access -from keystoneclient.common import cms -from keystoneclient import exceptions -from keystoneclient.middleware import memcache_crypt -from keystoneclient.openstack.common import memorycache - - -# alternative middleware configuration in the main application's -# configuration file e.g. in nova.conf -# [keystone_authtoken] -# auth_host = 127.0.0.1 -# auth_port = 35357 -# auth_protocol = http -# admin_tenant_name = admin -# admin_user = admin -# admin_password = badpassword - -# when deploy Keystone auth_token middleware with Swift, user may elect -# to use Swift memcache instead of the local Keystone memcache. Swift memcache -# is passed in from the request environment and its identified by the -# 'swift.cache' key. However it could be different, depending on deployment. -# To use Swift memcache, you must set the 'cache' option to the environment -# key where the Swift cache object is stored. - - -# NOTE(jamielennox): A number of options below are deprecated however are left -# in the list and only mentioned as deprecated in the help string. This is -# because we have to provide the same deprecation functionality for arguments -# passed in via the conf in __init__ (from paste) and there is no way to test -# that the default value was set or not in CONF. -# Also if we were to remove the options from the CONF list (as typical CONF -# deprecation works) then other projects will not be able to override the -# options via CONF. - -opts = [ - cfg.StrOpt('auth_admin_prefix', - default='', - help='Prefix to prepend at the beginning of the path. ' - 'Deprecated, use identity_uri.'), - cfg.StrOpt('auth_host', - default='127.0.0.1', - help='Host providing the admin Identity API endpoint. ' - 'Deprecated, use identity_uri.'), - cfg.IntOpt('auth_port', - default=35357, - help='Port of the admin Identity API endpoint. ' - 'Deprecated, use identity_uri.'), - cfg.StrOpt('auth_protocol', - default='https', - help='Protocol of the admin Identity API endpoint ' - '(http or https). Deprecated, use identity_uri.'), - cfg.StrOpt('auth_uri', - default=None, - # FIXME(dolph): should be default='http://127.0.0.1:5000/v2.0/', - # or (depending on client support) an unversioned, publicly - # accessible identity endpoint (see bug 1207517) - help='Complete public Identity API endpoint'), - cfg.StrOpt('identity_uri', - default=None, - help='Complete admin Identity API endpoint. This should ' - 'specify the unversioned root endpoint ' - 'e.g. https://localhost:35357/'), - cfg.StrOpt('auth_version', - default=None, - help='API version of the admin Identity API endpoint'), - cfg.BoolOpt('delay_auth_decision', - default=False, - help='Do not handle authorization requests within the' - ' middleware, but delegate the authorization decision to' - ' downstream WSGI components'), - cfg.BoolOpt('http_connect_timeout', - default=None, - help='Request timeout value for communicating with Identity' - ' API server.'), - cfg.IntOpt('http_request_max_retries', - default=3, - help='How many times are we trying to reconnect when' - ' communicating with Identity API Server.'), - cfg.StrOpt('admin_token', - secret=True, - help='This option is deprecated and may be removed in a future' - ' release. Single shared secret with the Keystone configuration' - ' used for bootstrapping a Keystone installation, or otherwise' - ' bypassing the normal authentication process. This option' - ' should not be used, use `admin_user` and `admin_password`' - ' instead.'), - cfg.StrOpt('admin_user', - help='Keystone account username'), - cfg.StrOpt('admin_password', - secret=True, - help='Keystone account password'), - cfg.StrOpt('admin_tenant_name', - default='admin', - help='Keystone service account tenant name to validate' - ' user tokens'), - cfg.StrOpt('cache', - default=None, - help='Env key for the swift cache'), - cfg.StrOpt('certfile', - help='Required if Keystone server requires client certificate'), - cfg.StrOpt('keyfile', - help='Required if Keystone server requires client certificate'), - cfg.StrOpt('cafile', default=None, - help='A PEM encoded Certificate Authority to use when ' - 'verifying HTTPs connections. Defaults to system CAs.'), - cfg.BoolOpt('insecure', default=False, help='Verify HTTPS connections.'), - cfg.StrOpt('signing_dir', - help='Directory used to cache files related to PKI tokens'), - cfg.ListOpt('memcached_servers', - deprecated_name='memcache_servers', - help='Optionally specify a list of memcached server(s) to' - ' use for caching. If left undefined, tokens will instead be' - ' cached in-process.'), - cfg.IntOpt('token_cache_time', - default=300, - help='In order to prevent excessive effort spent validating' - ' tokens, the middleware caches previously-seen tokens for a' - ' configurable duration (in seconds). Set to -1 to disable' - ' caching completely.'), - cfg.IntOpt('revocation_cache_time', - default=10, - help='Determines the frequency at which the list of revoked' - ' tokens is retrieved from the Identity service (in seconds). A' - ' high number of revocation events combined with a low cache' - ' duration may significantly reduce performance.'), - cfg.StrOpt('memcache_security_strategy', - default=None, - help='(optional) if defined, indicate whether token data' - ' should be authenticated or authenticated and encrypted.' - ' Acceptable values are MAC or ENCRYPT. If MAC, token data is' - ' authenticated (with HMAC) in the cache. If ENCRYPT, token' - ' data is encrypted and authenticated in the cache. If the' - ' value is not one of these options or empty, auth_token will' - ' raise an exception on initialization.'), - cfg.StrOpt('memcache_secret_key', - default=None, - secret=True, - help='(optional, mandatory if memcache_security_strategy is' - ' defined) this string is used for key derivation.'), - cfg.BoolOpt('include_service_catalog', - default=True, - help='(optional) indicate whether to set the X-Service-Catalog' - ' header. If False, middleware will not ask for service' - ' catalog on token validation and will not set the' - ' X-Service-Catalog header.'), - cfg.StrOpt('enforce_token_bind', - default='permissive', - help='Used to control the use and type of token binding. Can' - ' be set to: "disabled" to not check token binding.' - ' "permissive" (default) to validate binding information if the' - ' bind type is of a form known to the server and ignore it if' - ' not. "strict" like "permissive" but if the bind type is' - ' unknown the token will be rejected. "required" any form of' - ' token binding is needed to be allowed. Finally the name of a' - ' binding method that must be present in tokens.'), - cfg.BoolOpt('check_revocations_for_cached', default=False, - help='If true, the revocation list will be checked for cached' - ' tokens. This requires that PKI tokens are configured on the' - ' Keystone server.'), - cfg.ListOpt('hash_algorithms', default=['md5'], - help='Hash algorithms to use for hashing PKI tokens. This may' - ' be a single algorithm or multiple. The algorithms are those' - ' supported by Python standard hashlib.new(). The hashes will' - ' be tried in the order given, so put the preferred one first' - ' for performance. The result of the first hash will be stored' - ' in the cache. This will typically be set to multiple values' - ' only while migrating from a less secure algorithm to a more' - ' secure one. Once all the old tokens are expired this option' - ' should be set to a single value for better performance.'), -] - -CONF = cfg.CONF -CONF.register_opts(opts, group='keystone_authtoken') - -LIST_OF_VERSIONS_TO_ATTEMPT = ['v2.0', 'v3.0'] -CACHE_KEY_TEMPLATE = 'tokens/%s' - - -class BIND_MODE(object): - DISABLED = 'disabled' - PERMISSIVE = 'permissive' - STRICT = 'strict' - REQUIRED = 'required' - KERBEROS = 'kerberos' - - -def will_expire_soon(expiry): - """Determines if expiration is about to occur. - - :param expiry: a datetime of the expected expiration - :returns: boolean : true if expiration is within 30 seconds - """ - soon = (timeutils.utcnow() + datetime.timedelta(seconds=30)) - return expiry < soon - - -def _token_is_v2(token_info): - return ('access' in token_info) - - -def _token_is_v3(token_info): - return ('token' in token_info) - - -def confirm_token_not_expired(data): - if not data: - raise InvalidUserToken('Token authorization failed') - if _token_is_v2(data): - timestamp = data['access']['token']['expires'] - elif _token_is_v3(data): - timestamp = data['token']['expires_at'] - else: - raise InvalidUserToken('Token authorization failed') - expires = timeutils.parse_isotime(timestamp) - expires = timeutils.normalize_time(expires) - utcnow = timeutils.utcnow() - if utcnow >= expires: - raise InvalidUserToken('Token authorization failed') - return timeutils.isotime(at=expires, subsecond=True) - - -def _v3_to_v2_catalog(catalog): - """Convert a catalog to v2 format. - - X_SERVICE_CATALOG must be specified in v2 format. If you get a token - that is in v3 convert it. - """ - v2_services = [] - for v3_service in catalog: - # first copy over the entries we allow for the service - v2_service = {'type': v3_service['type']} - try: - v2_service['name'] = v3_service['name'] - except KeyError: - pass - - # now convert the endpoints. Because in v3 we specify region per - # URL not per group we have to collect all the entries of the same - # region together before adding it to the new service. - regions = {} - for v3_endpoint in v3_service.get('endpoints', []): - region_name = v3_endpoint.get('region') - try: - region = regions[region_name] - except KeyError: - region = {'region': region_name} if region_name else {} - regions[region_name] = region - - interface_name = v3_endpoint['interface'].lower() + 'URL' - region[interface_name] = v3_endpoint['url'] - - v2_service['endpoints'] = list(regions.values()) - v2_services.append(v2_service) - - return v2_services - - -def safe_quote(s): - """URL-encode strings that are not already URL-encoded.""" - return urllib.parse.quote(s) if s == urllib.parse.unquote(s) else s - - -def _conf_values_type_convert(conf): - """Convert conf values into correct type.""" - if not conf: - return {} - _opts = {} - opt_types = dict((o.dest, getattr(o, 'type', str)) for o in opts) - for k, v in six.iteritems(conf): - try: - if v is None: - _opts[k] = v - else: - _opts[k] = opt_types[k](v) - except KeyError: - _opts[k] = v - except ValueError as e: - raise ConfigurationError( - 'Unable to convert the value of %s option into correct ' - 'type: %s' % (k, e)) - return _opts - - -class InvalidUserToken(Exception): - pass - - -class ServiceError(Exception): - pass - - -class ConfigurationError(Exception): - pass - - -class NetworkError(Exception): - pass - - -class MiniResp(object): - def __init__(self, error_message, env, headers=[]): - # The HEAD method is unique: it must never return a body, even if - # it reports an error (RFC-2616 clause 9.4). We relieve callers - # from varying the error responses depending on the method. - if env['REQUEST_METHOD'] == 'HEAD': - self.body = [''] - else: - self.body = [error_message] - self.headers = list(headers) - self.headers.append(('Content-type', 'text/plain')) - - -class AuthProtocol(object): - """Auth Middleware that handles authenticating client calls.""" - - def __init__(self, app, conf): - self.LOG = logging.getLogger(conf.get('log_name', __name__)) - self.LOG.info('Starting keystone auth_token middleware') - self.LOG.warning( - 'This middleware module is deprecated as of v0.10.0 in favor of ' - 'keystonemiddleware.auth_token - please update your WSGI pipeline ' - 'to reference the new middleware package.') - # NOTE(wanghong): If options are set in paste file, all the option - # values passed into conf are string type. So, we should convert the - # conf value into correct type. - self.conf = _conf_values_type_convert(conf) - self.app = app - - # delay_auth_decision means we still allow unauthenticated requests - # through and we let the downstream service make the final decision - self.delay_auth_decision = (self._conf_get('delay_auth_decision') in - (True, 'true', 't', '1', 'on', 'yes', 'y')) - - # where to find the auth service (we use this to validate tokens) - self.identity_uri = self._conf_get('identity_uri') - self.auth_uri = self._conf_get('auth_uri') - - # NOTE(jamielennox): it does appear here that our defaults arguments - # are backwards. We need to do it this way so that we can handle the - # same deprecation strategy for CONF and the conf variable. - if not self.identity_uri: - self.LOG.warning('Configuring admin URI using auth fragments. ' - 'This is deprecated, use \'identity_uri\'' - ' instead.') - - auth_host = self._conf_get('auth_host') - auth_port = int(self._conf_get('auth_port')) - auth_protocol = self._conf_get('auth_protocol') - auth_admin_prefix = self._conf_get('auth_admin_prefix') - - if netaddr.valid_ipv6(auth_host): - # Note(dzyu) it is an IPv6 address, so it needs to be wrapped - # with '[]' to generate a valid IPv6 URL, based on - # http://www.ietf.org/rfc/rfc2732.txt - auth_host = '[%s]' % auth_host - - self.identity_uri = '%s://%s:%s' % (auth_protocol, auth_host, - auth_port) - if auth_admin_prefix: - self.identity_uri = '%s/%s' % (self.identity_uri, - auth_admin_prefix.strip('/')) - else: - self.identity_uri = self.identity_uri.rstrip('/') - - if self.auth_uri is None: - self.LOG.warning( - 'Configuring auth_uri to point to the public identity ' - 'endpoint is required; clients may not be able to ' - 'authenticate against an admin endpoint') - - # FIXME(dolph): drop support for this fallback behavior as - # documented in bug 1207517. - # NOTE(jamielennox): we urljoin '/' to get just the base URI as - # this is the original behaviour. - self.auth_uri = urllib.parse.urljoin(self.identity_uri, '/') - self.auth_uri = self.auth_uri.rstrip('/') - - # SSL - self.cert_file = self._conf_get('certfile') - self.key_file = self._conf_get('keyfile') - self.ssl_ca_file = self._conf_get('cafile') - self.ssl_insecure = self._conf_get('insecure') - - # signing - self.signing_dirname = self._conf_get('signing_dir') - if self.signing_dirname is None: - self.signing_dirname = tempfile.mkdtemp(prefix='keystone-signing-') - self.LOG.info('Using %s as cache directory for signing certificate', - self.signing_dirname) - self.verify_signing_dir() - - val = '%s/signing_cert.pem' % self.signing_dirname - self.signing_cert_file_name = val - val = '%s/cacert.pem' % self.signing_dirname - self.signing_ca_file_name = val - val = '%s/revoked.pem' % self.signing_dirname - self.revoked_file_name = val - - # Credentials used to verify this component with the Auth service since - # validating tokens is a privileged call - self.admin_token = self._conf_get('admin_token') - if self.admin_token: - self.LOG.warning( - "The admin_token option in the auth_token middleware is " - "deprecated and should not be used. The admin_user and " - "admin_password options should be used instead. The " - "admin_token option may be removed in a future release.") - self.admin_token_expiry = None - self.admin_user = self._conf_get('admin_user') - self.admin_password = self._conf_get('admin_password') - self.admin_tenant_name = self._conf_get('admin_tenant_name') - - memcache_security_strategy = ( - self._conf_get('memcache_security_strategy')) - - self._token_cache = TokenCache( - self.LOG, - cache_time=int(self._conf_get('token_cache_time')), - hash_algorithms=self._conf_get('hash_algorithms'), - env_cache_name=self._conf_get('cache'), - memcached_servers=self._conf_get('memcached_servers'), - memcache_security_strategy=memcache_security_strategy, - memcache_secret_key=self._conf_get('memcache_secret_key')) - - self._token_revocation_list = None - self._token_revocation_list_fetched_time = None - self.token_revocation_list_cache_timeout = datetime.timedelta( - seconds=self._conf_get('revocation_cache_time')) - http_connect_timeout_cfg = self._conf_get('http_connect_timeout') - self.http_connect_timeout = (http_connect_timeout_cfg and - int(http_connect_timeout_cfg)) - self.auth_version = None - self.http_request_max_retries = ( - self._conf_get('http_request_max_retries')) - - self.include_service_catalog = self._conf_get( - 'include_service_catalog') - - self.check_revocations_for_cached = self._conf_get( - 'check_revocations_for_cached') - - def _conf_get(self, name): - # try config from paste-deploy first - if name in self.conf: - return self.conf[name] - else: - return CONF.keystone_authtoken[name] - - def _choose_api_version(self): - """Determine the api version that we should use.""" - - # If the configuration specifies an auth_version we will just - # assume that is correct and use it. We could, of course, check - # that this version is supported by the server, but in case - # there are some problems in the field, we want as little code - # as possible in the way of letting auth_token talk to the - # server. - if self._conf_get('auth_version'): - version_to_use = self._conf_get('auth_version') - self.LOG.info('Auth Token proceeding with requested %s apis', - version_to_use) - else: - version_to_use = None - versions_supported_by_server = self._get_supported_versions() - if versions_supported_by_server: - for version in LIST_OF_VERSIONS_TO_ATTEMPT: - if version in versions_supported_by_server: - version_to_use = version - break - if version_to_use: - self.LOG.info('Auth Token confirmed use of %s apis', - version_to_use) - else: - self.LOG.error( - 'Attempted versions [%s] not in list supported by ' - 'server [%s]', - ', '.join(LIST_OF_VERSIONS_TO_ATTEMPT), - ', '.join(versions_supported_by_server)) - raise ServiceError('No compatible apis supported by server') - return version_to_use - - def _get_supported_versions(self): - versions = [] - response, data = self._json_request('GET', '/') - if response.status_code == 501: - self.LOG.warning('Old keystone installation found...assuming v2.0') - versions.append('v2.0') - elif response.status_code != 300: - self.LOG.error('Unable to get version info from keystone: %s', - response.status_code) - raise ServiceError('Unable to get version info from keystone') - else: - try: - for version in data['versions']['values']: - versions.append(version['id']) - except KeyError: - self.LOG.error( - 'Invalid version response format from server') - raise ServiceError('Unable to parse version response ' - 'from keystone') - - self.LOG.debug('Server reports support for api versions: %s', - ', '.join(versions)) - return versions - - def __call__(self, env, start_response): - """Handle incoming request. - - Authenticate send downstream on success. Reject request if - we can't authenticate. - - """ - self.LOG.debug('Authenticating user token') - - self._token_cache.initialize(env) - - try: - self._remove_auth_headers(env) - user_token = self._get_user_token_from_header(env) - token_info = self._validate_user_token(user_token, env) - env['keystone.token_info'] = token_info - user_headers = self._build_user_headers(token_info) - self._add_headers(env, user_headers) - return self.app(env, start_response) - - except InvalidUserToken: - if self.delay_auth_decision: - self.LOG.info( - 'Invalid user token - deferring reject downstream') - self._add_headers(env, {'X-Identity-Status': 'Invalid'}) - return self.app(env, start_response) - else: - self.LOG.info('Invalid user token - rejecting request') - return self._reject_request(env, start_response) - - except ServiceError as e: - self.LOG.critical('Unable to obtain admin token: %s', e) - resp = MiniResp('Service unavailable', env) - start_response('503 Service Unavailable', resp.headers) - return resp.body - - def _remove_auth_headers(self, env): - """Remove headers so a user can't fake authentication. - - :param env: wsgi request environment - - """ - auth_headers = ( - 'X-Identity-Status', - 'X-Domain-Id', - 'X-Domain-Name', - 'X-Project-Id', - 'X-Project-Name', - 'X-Project-Domain-Id', - 'X-Project-Domain-Name', - 'X-User-Id', - 'X-User-Name', - 'X-User-Domain-Id', - 'X-User-Domain-Name', - 'X-Roles', - 'X-Service-Catalog', - # Deprecated - 'X-User', - 'X-Tenant-Id', - 'X-Tenant-Name', - 'X-Tenant', - 'X-Role', - ) - self.LOG.debug('Removing headers from request environment: %s', - ','.join(auth_headers)) - self._remove_headers(env, auth_headers) - - def _get_user_token_from_header(self, env): - """Get token id from request. - - :param env: wsgi request environment - :return token id - :raises InvalidUserToken if no token is provided in request - - """ - token = self._get_header(env, 'X-Auth-Token', - self._get_header(env, 'X-Storage-Token')) - if token: - return token - else: - if not self.delay_auth_decision: - self.LOG.warn('Unable to find authentication token' - ' in headers') - self.LOG.debug('Headers: %s', env) - raise InvalidUserToken('Unable to find token in headers') - - def _reject_request(self, env, start_response): - """Redirect client to auth server. - - :param env: wsgi request environment - :param start_response: wsgi response callback - :returns HTTPUnauthorized http response - - """ - headers = [('WWW-Authenticate', 'Keystone uri=\'%s\'' % self.auth_uri)] - resp = MiniResp('Authentication required', env, headers) - start_response('401 Unauthorized', resp.headers) - return resp.body - - def get_admin_token(self): - """Return admin token, possibly fetching a new one. - - if self.admin_token_expiry is set from fetching an admin token, check - it for expiration, and request a new token is the existing token - is about to expire. - - :return admin token id - :raise ServiceError when unable to retrieve token from keystone - - """ - if self.admin_token_expiry: - if will_expire_soon(self.admin_token_expiry): - self.admin_token = None - - if not self.admin_token: - (self.admin_token, - self.admin_token_expiry) = self._request_admin_token() - - return self.admin_token - - def _http_request(self, method, path, **kwargs): - """HTTP request helper used to make unspecified content type requests. - - :param method: http method - :param path: relative request url - :return (http response object, response body) - :raise ServerError when unable to communicate with keystone - - """ - url = '%s/%s' % (self.identity_uri, path.lstrip('/')) - - kwargs.setdefault('timeout', self.http_connect_timeout) - if self.cert_file and self.key_file: - kwargs['cert'] = (self.cert_file, self.key_file) - elif self.cert_file or self.key_file: - self.LOG.warn('Cannot use only a cert or key file. ' - 'Please provide both. Ignoring.') - - kwargs['verify'] = self.ssl_ca_file or True - if self.ssl_insecure: - kwargs['verify'] = False - - RETRIES = self.http_request_max_retries - retry = 0 - while True: - try: - response = requests.request(method, url, **kwargs) - break - except Exception as e: - if retry >= RETRIES: - self.LOG.error('HTTP connection exception: %s', e) - raise NetworkError('Unable to communicate with keystone') - # NOTE(vish): sleep 0.5, 1, 2 - self.LOG.warn('Retrying on HTTP connection exception: %s', e) - time.sleep(2.0 ** retry / 2) - retry += 1 - - return response - - def _json_request(self, method, path, body=None, additional_headers=None): - """HTTP request helper used to make json requests. - - :param method: http method - :param path: relative request url - :param body: dict to encode to json as request body. Optional. - :param additional_headers: dict of additional headers to send with - http request. Optional. - :return (http response object, response body parsed as json) - :raise ServerError when unable to communicate with keystone - - """ - kwargs = { - 'headers': { - 'Content-type': 'application/json', - 'Accept': 'application/json', - }, - } - - if additional_headers: - kwargs['headers'].update(additional_headers) - - if body: - kwargs['data'] = jsonutils.dumps(body) - - response = self._http_request(method, path, **kwargs) - - try: - data = jsonutils.loads(response.text) - except ValueError: - self.LOG.debug('Keystone did not return json-encoded body') - data = {} - - return response, data - - def _request_admin_token(self): - """Retrieve new token as admin user from keystone. - - :return token id upon success - :raises ServerError when unable to communicate with keystone - - Irrespective of the auth version we are going to use for the - user token, for simplicity we always use a v2 admin token to - validate the user token. - - """ - params = { - 'auth': { - 'passwordCredentials': { - 'username': self.admin_user, - 'password': self.admin_password, - }, - 'tenantName': self.admin_tenant_name, - } - } - - response, data = self._json_request('POST', - '/v2.0/tokens', - body=params) - - try: - token = data['access']['token']['id'] - expiry = data['access']['token']['expires'] - if not (token and expiry): - raise AssertionError('invalid token or expire') - datetime_expiry = timeutils.parse_isotime(expiry) - return (token, timeutils.normalize_time(datetime_expiry)) - except (AssertionError, KeyError): - self.LOG.warn( - 'Unexpected response from keystone service: %s', data) - raise ServiceError('invalid json response') - except (ValueError): - data['access']['token']['id'] = '<SANITIZED>' - self.LOG.warn( - 'Unable to parse expiration time from token: %s', data) - raise ServiceError('invalid json response') - - def _validate_user_token(self, user_token, env, retry=True): - """Authenticate user token - - :param user_token: user's token id - :param retry: Ignored, as it is not longer relevant - :return uncrypted body of the token if the token is valid - :raise InvalidUserToken if token is rejected - :no longer raises ServiceError since it no longer makes RPC - - """ - token_id = None - - try: - token_ids, cached = self._token_cache.get(user_token) - token_id = token_ids[0] - if cached: - data = cached - - if self.check_revocations_for_cached: - # A token stored in Memcached might have been revoked - # regardless of initial mechanism used to validate it, - # and needs to be checked. - for tid in token_ids: - is_revoked = self._is_token_id_in_revoked_list(tid) - if is_revoked: - self.LOG.debug( - 'Token is marked as having been revoked') - raise InvalidUserToken( - 'Token authorization failed') - elif cms.is_pkiz(user_token): - verified = self.verify_pkiz_token(user_token, token_ids) - data = jsonutils.loads(verified) - elif cms.is_asn1_token(user_token): - verified = self.verify_signed_token(user_token, token_ids) - data = jsonutils.loads(verified) - else: - data = self.verify_uuid_token(user_token, retry) - expires = confirm_token_not_expired(data) - self._confirm_token_bind(data, env) - self._token_cache.store(token_id, data, expires) - return data - except NetworkError: - self.LOG.debug('Token validation failure.', exc_info=True) - self.LOG.warn('Authorization failed for token') - raise InvalidUserToken('Token authorization failed') - except Exception: - self.LOG.debug('Token validation failure.', exc_info=True) - if token_id: - self._token_cache.store_invalid(token_id) - self.LOG.warn('Authorization failed for token') - raise InvalidUserToken('Token authorization failed') - - def _build_user_headers(self, token_info): - """Convert token object into headers. - - Build headers that represent authenticated user - see main - doc info at start of file for details of headers to be defined. - - :param token_info: token object returned by keystone on authentication - :raise InvalidUserToken when unable to parse token object - - """ - auth_ref = access.AccessInfo.factory(body=token_info) - roles = ','.join(auth_ref.role_names) - - if _token_is_v2(token_info) and not auth_ref.project_id: - raise InvalidUserToken('Unable to determine tenancy.') - - rval = { - 'X-Identity-Status': 'Confirmed', - 'X-Domain-Id': auth_ref.domain_id, - 'X-Domain-Name': auth_ref.domain_name, - 'X-Project-Id': auth_ref.project_id, - 'X-Project-Name': auth_ref.project_name, - 'X-Project-Domain-Id': auth_ref.project_domain_id, - 'X-Project-Domain-Name': auth_ref.project_domain_name, - 'X-User-Id': auth_ref.user_id, - 'X-User-Name': auth_ref.username, - 'X-User-Domain-Id': auth_ref.user_domain_id, - 'X-User-Domain-Name': auth_ref.user_domain_name, - 'X-Roles': roles, - # Deprecated - 'X-User': auth_ref.username, - 'X-Tenant-Id': auth_ref.project_id, - 'X-Tenant-Name': auth_ref.project_name, - 'X-Tenant': auth_ref.project_name, - 'X-Role': roles, - } - - self.LOG.debug('Received request from user: %s with project_id : %s' - ' and roles: %s ', - auth_ref.user_id, auth_ref.project_id, roles) - - if self.include_service_catalog and auth_ref.has_service_catalog(): - catalog = auth_ref.service_catalog.get_data() - if _token_is_v3(token_info): - catalog = _v3_to_v2_catalog(catalog) - rval['X-Service-Catalog'] = jsonutils.dumps(catalog) - - return rval - - def _header_to_env_var(self, key): - """Convert header to wsgi env variable. - - :param key: http header name (ex. 'X-Auth-Token') - :return wsgi env variable name (ex. 'HTTP_X_AUTH_TOKEN') - - """ - return 'HTTP_%s' % key.replace('-', '_').upper() - - def _add_headers(self, env, headers): - """Add http headers to environment.""" - for (k, v) in six.iteritems(headers): - env_key = self._header_to_env_var(k) - env[env_key] = v - - def _remove_headers(self, env, keys): - """Remove http headers from environment.""" - for k in keys: - env_key = self._header_to_env_var(k) - try: - del env[env_key] - except KeyError: - pass - - def _get_header(self, env, key, default=None): - """Get http header from environment.""" - env_key = self._header_to_env_var(key) - return env.get(env_key, default) - - def _invalid_user_token(self, msg=False): - # NOTE(jamielennox): use False as the default so that None is valid - if msg is False: - msg = 'Token authorization failed' - - raise InvalidUserToken(msg) - - def _confirm_token_bind(self, data, env): - bind_mode = self._conf_get('enforce_token_bind') - - if bind_mode == BIND_MODE.DISABLED: - return - - try: - if _token_is_v2(data): - bind = data['access']['token']['bind'] - elif _token_is_v3(data): - bind = data['token']['bind'] - else: - self._invalid_user_token() - except KeyError: - bind = {} - - # permissive and strict modes don't require there to be a bind - permissive = bind_mode in (BIND_MODE.PERMISSIVE, BIND_MODE.STRICT) - - if not bind: - if permissive: - # no bind provided and none required - return - else: - self.LOG.info('No bind information present in token.') - self._invalid_user_token() - - # get the named mode if bind_mode is not one of the predefined - if permissive or bind_mode == BIND_MODE.REQUIRED: - name = None - else: - name = bind_mode - - if name and name not in bind: - self.LOG.info('Named bind mode %s not in bind information', name) - self._invalid_user_token() - - for bind_type, identifier in six.iteritems(bind): - if bind_type == BIND_MODE.KERBEROS: - if not env.get('AUTH_TYPE', '').lower() == 'negotiate': - self.LOG.info('Kerberos credentials required and ' - 'not present.') - self._invalid_user_token() - - if not env.get('REMOTE_USER') == identifier: - self.LOG.info('Kerberos credentials do not match ' - 'those in bind.') - self._invalid_user_token() - - self.LOG.debug('Kerberos bind authentication successful.') - - elif bind_mode == BIND_MODE.PERMISSIVE: - self.LOG.debug('Ignoring Unknown bind for permissive mode: ' - '%(bind_type)s: %(identifier)s.', - {'bind_type': bind_type, - 'identifier': identifier}) - - else: - self.LOG.info('Couldn`t verify unknown bind: %(bind_type)s: ' - '%(identifier)s.', - {'bind_type': bind_type, - 'identifier': identifier}) - self._invalid_user_token() - - def verify_uuid_token(self, user_token, retry=True): - """Authenticate user token with keystone. - - :param user_token: user's token id - :param retry: flag that forces the middleware to retry - user authentication when an indeterminate - response is received. Optional. - :returns: token object received from keystone on success - :raise InvalidUserToken: if token is rejected - :raise ServiceError: if unable to authenticate token - - """ - # Determine the highest api version we can use. - if not self.auth_version: - self.auth_version = self._choose_api_version() - - if self.auth_version == 'v3.0': - headers = {'X-Auth-Token': self.get_admin_token(), - 'X-Subject-Token': safe_quote(user_token)} - path = '/v3/auth/tokens' - if not self.include_service_catalog: - # NOTE(gyee): only v3 API support this option - path = path + '?nocatalog' - response, data = self._json_request( - 'GET', - path, - additional_headers=headers) - else: - headers = {'X-Auth-Token': self.get_admin_token()} - response, data = self._json_request( - 'GET', - '/v2.0/tokens/%s' % safe_quote(user_token), - additional_headers=headers) - - if response.status_code == 200: - return data - if response.status_code == 404: - self.LOG.warn('Authorization failed for token') - raise InvalidUserToken('Token authorization failed') - if response.status_code == 401: - self.LOG.info( - 'Keystone rejected admin token, resetting') - self.admin_token = None - else: - self.LOG.error('Bad response code while validating token: %s', - response.status_code) - if retry: - self.LOG.info('Retrying validation') - return self.verify_uuid_token(user_token, False) - else: - self.LOG.warn('Invalid user token. Keystone response: %s', data) - - raise InvalidUserToken() - - def is_signed_token_revoked(self, token_ids): - """Indicate whether the token appears in the revocation list.""" - for token_id in token_ids: - if self._is_token_id_in_revoked_list(token_id): - self.LOG.debug('Token is marked as having been revoked') - return True - return False - - def _is_token_id_in_revoked_list(self, token_id): - """Indicate whether the token_id appears in the revocation list.""" - revocation_list = self.token_revocation_list - revoked_tokens = revocation_list.get('revoked', None) - if not revoked_tokens: - return False - - revoked_ids = (x['id'] for x in revoked_tokens) - return token_id in revoked_ids - - def cms_verify(self, data, inform=cms.PKI_ASN1_FORM): - """Verifies the signature of the provided data's IAW CMS syntax. - - If either of the certificate files might be missing, fetch them and - retry. - """ - def verify(): - try: - return cms.cms_verify(data, self.signing_cert_file_name, - self.signing_ca_file_name, - inform=inform).decode('utf-8') - except cms.subprocess.CalledProcessError as err: - self.LOG.warning('Verify error: %s', err) - raise - - try: - return verify() - except exceptions.CertificateConfigError: - # the certs might be missing; unconditionally fetch to avoid racing - self.fetch_signing_cert() - self.fetch_ca_cert() - - try: - # retry with certs in place - return verify() - except exceptions.CertificateConfigError as err: - # if this is still occurring, something else is wrong and we - # need err.output to identify the problem - self.LOG.error('CMS Verify output: %s', err.output) - raise - - def verify_signed_token(self, signed_text, token_ids): - """Check that the token is unrevoked and has a valid signature.""" - if self.is_signed_token_revoked(token_ids): - raise InvalidUserToken('Token has been revoked') - - formatted = cms.token_to_cms(signed_text) - verified = self.cms_verify(formatted) - return verified - - def verify_pkiz_token(self, signed_text, token_ids): - if self.is_signed_token_revoked(token_ids): - raise InvalidUserToken('Token has been revoked') - try: - uncompressed = cms.pkiz_uncompress(signed_text) - verified = self.cms_verify(uncompressed, inform=cms.PKIZ_CMS_FORM) - return verified - # TypeError If the signed_text is not zlib compressed - except TypeError: - raise InvalidUserToken(signed_text) - - def verify_signing_dir(self): - if os.path.exists(self.signing_dirname): - if not os.access(self.signing_dirname, os.W_OK): - raise ConfigurationError( - 'unable to access signing_dir %s' % self.signing_dirname) - uid = os.getuid() - if os.stat(self.signing_dirname).st_uid != uid: - self.LOG.warning( - 'signing_dir is not owned by %s', uid) - current_mode = stat.S_IMODE(os.stat(self.signing_dirname).st_mode) - if current_mode != stat.S_IRWXU: - self.LOG.warning( - 'signing_dir mode is %s instead of %s', - oct(current_mode), oct(stat.S_IRWXU)) - else: - os.makedirs(self.signing_dirname, stat.S_IRWXU) - - @property - def token_revocation_list_fetched_time(self): - if not self._token_revocation_list_fetched_time: - # If the fetched list has been written to disk, use its - # modification time. - if os.path.exists(self.revoked_file_name): - mtime = os.path.getmtime(self.revoked_file_name) - fetched_time = datetime.datetime.utcfromtimestamp(mtime) - # Otherwise the list will need to be fetched. - else: - fetched_time = datetime.datetime.min - self._token_revocation_list_fetched_time = fetched_time - return self._token_revocation_list_fetched_time - - @token_revocation_list_fetched_time.setter - def token_revocation_list_fetched_time(self, value): - self._token_revocation_list_fetched_time = value - - @property - def token_revocation_list(self): - timeout = (self.token_revocation_list_fetched_time + - self.token_revocation_list_cache_timeout) - list_is_current = timeutils.utcnow() < timeout - - if list_is_current: - # Load the list from disk if required - if not self._token_revocation_list: - open_kwargs = {'encoding': 'utf-8'} if six.PY3 else {} - with open(self.revoked_file_name, 'r', **open_kwargs) as f: - self._token_revocation_list = jsonutils.loads(f.read()) - else: - self.token_revocation_list = self.fetch_revocation_list() - return self._token_revocation_list - - def _atomic_write_to_signing_dir(self, file_name, value): - # In Python2, encoding is slow so the following check avoids it if it - # is not absolutely necessary. - if isinstance(value, six.text_type): - value = value.encode('utf-8') - - def _atomic_write(destination, data): - with tempfile.NamedTemporaryFile(dir=self.signing_dirname, - delete=False) as f: - f.write(data) - os.rename(f.name, destination) - - try: - _atomic_write(file_name, value) - except (OSError, IOError): - self.verify_signing_dir() - _atomic_write(file_name, value) - - @token_revocation_list.setter - def token_revocation_list(self, value): - """Save a revocation list to memory and to disk. - - :param value: A json-encoded revocation list - - """ - self._token_revocation_list = jsonutils.loads(value) - self.token_revocation_list_fetched_time = timeutils.utcnow() - self._atomic_write_to_signing_dir(self.revoked_file_name, value) - - def fetch_revocation_list(self, retry=True): - headers = {'X-Auth-Token': self.get_admin_token()} - response, data = self._json_request('GET', '/v2.0/tokens/revoked', - additional_headers=headers) - if response.status_code == 401: - if retry: - self.LOG.info( - 'Keystone rejected admin token, resetting admin token') - self.admin_token = None - return self.fetch_revocation_list(retry=False) - if response.status_code != 200: - raise ServiceError('Unable to fetch token revocation list.') - if 'signed' not in data: - raise ServiceError('Revocation list improperly formatted.') - return self.cms_verify(data['signed']) - - def _fetch_cert_file(self, cert_file_name, cert_type): - if not self.auth_version: - self.auth_version = self._choose_api_version() - - if self.auth_version == 'v3.0': - if cert_type == 'signing': - cert_type = 'certificates' - path = '/v3/OS-SIMPLE-CERT/' + cert_type - else: - path = '/v2.0/certificates/' + cert_type - response = self._http_request('GET', path) - if response.status_code != 200: - raise exceptions.CertificateConfigError(response.text) - self._atomic_write_to_signing_dir(cert_file_name, response.text) - - def fetch_signing_cert(self): - self._fetch_cert_file(self.signing_cert_file_name, 'signing') - - def fetch_ca_cert(self): - self._fetch_cert_file(self.signing_ca_file_name, 'ca') - - -class CachePool(list): - """A lazy pool of cache references.""" - - def __init__(self, cache, memcached_servers): - self._environment_cache = cache - self._memcached_servers = memcached_servers - - @contextlib.contextmanager - def reserve(self): - """Context manager to manage a pooled cache reference.""" - if self._environment_cache is not None: - # skip pooling and just use the cache from the upstream filter - yield self._environment_cache - return # otherwise the context manager will continue! - - try: - c = self.pop() - except IndexError: - # the pool is empty, so we need to create a new client - c = memorycache.get_client(self._memcached_servers) - - try: - yield c - finally: - self.append(c) - - -class TokenCache(object): - """Encapsulates the auth_token token cache functionality. - - auth_token caches tokens that it's seen so that when a token is re-used the - middleware doesn't have to do a more expensive operation (like going to the - identity server) to validate the token. - - initialize() must be called before calling the other methods. - - Store a valid token in the cache using store(); mark a token as invalid in - the cache using store_invalid(). - - Check if a token is in the cache and retrieve it using get(). - - """ - - _INVALID_INDICATOR = 'invalid' - - def __init__(self, log, cache_time=None, hash_algorithms=None, - env_cache_name=None, memcached_servers=None, - memcache_security_strategy=None, memcache_secret_key=None): - self.LOG = log - self._cache_time = cache_time - self._hash_algorithms = hash_algorithms - self._env_cache_name = env_cache_name - self._memcached_servers = memcached_servers - - # memcache value treatment, ENCRYPT or MAC - self._memcache_security_strategy = memcache_security_strategy - if self._memcache_security_strategy is not None: - self._memcache_security_strategy = ( - self._memcache_security_strategy.upper()) - self._memcache_secret_key = memcache_secret_key - - self._cache_pool = None - self._initialized = False - - self._assert_valid_memcache_protection_config() - - def initialize(self, env): - if self._initialized: - return - - self._cache_pool = CachePool(env.get(self._env_cache_name), - self._memcached_servers) - self._initialized = True - - def get(self, user_token): - """Check if the token is cached already. - - Returns a tuple. The first element is a list of token IDs, where the - first one is the preferred hash. - - The second element is the token data from the cache if the token was - cached, otherwise ``None``. - - :raises InvalidUserToken: if the token is invalid - - """ - - if cms.is_asn1_token(user_token) or cms.is_pkiz(user_token): - # user_token is a PKI token that's not hashed. - - token_hashes = list(cms.cms_hash_token(user_token, mode=algo) - for algo in self._hash_algorithms) - - for token_hash in token_hashes: - cached = self._cache_get(token_hash) - if cached: - return (token_hashes, cached) - - # The token wasn't found using any hash algorithm. - return (token_hashes, None) - - # user_token is either a UUID token or a hashed PKI token. - token_id = user_token - cached = self._cache_get(token_id) - return ([token_id], cached) - - def store(self, token_id, data, expires): - """Put token data into the cache. - - Stores the parsed expire date in cache allowing - quick check of token freshness on retrieval. - - """ - self.LOG.debug('Storing token in cache') - self._cache_store(token_id, (data, expires)) - - def store_invalid(self, token_id): - """Store invalid token in cache.""" - self.LOG.debug('Marking token as unauthorized in cache') - self._cache_store(token_id, self._INVALID_INDICATOR) - - def _assert_valid_memcache_protection_config(self): - if self._memcache_security_strategy: - if self._memcache_security_strategy not in ('MAC', 'ENCRYPT'): - raise ConfigurationError('memcache_security_strategy must be ' - 'ENCRYPT or MAC') - if not self._memcache_secret_key: - raise ConfigurationError('memcache_secret_key must be defined ' - 'when a memcache_security_strategy ' - 'is defined') - - def _cache_get(self, token_id): - """Return token information from cache. - - If token is invalid raise InvalidUserToken - return token only if fresh (not expired). - """ - - if not token_id: - # Nothing to do - return - - if self._memcache_security_strategy is None: - key = CACHE_KEY_TEMPLATE % token_id - with self._cache_pool.reserve() as cache: - serialized = cache.get(key) - else: - secret_key = self._memcache_secret_key - if isinstance(secret_key, six.string_types): - secret_key = secret_key.encode('utf-8') - security_strategy = self._memcache_security_strategy - if isinstance(security_strategy, six.string_types): - security_strategy = security_strategy.encode('utf-8') - keys = memcache_crypt.derive_keys( - token_id, - secret_key, - security_strategy) - cache_key = CACHE_KEY_TEMPLATE % ( - memcache_crypt.get_cache_key(keys)) - with self._cache_pool.reserve() as cache: - raw_cached = cache.get(cache_key) - try: - # unprotect_data will return None if raw_cached is None - serialized = memcache_crypt.unprotect_data(keys, - raw_cached) - except Exception: - msg = 'Failed to decrypt/verify cache data' - self.LOG.exception(msg) - # this should have the same effect as data not - # found in cache - serialized = None - - if serialized is None: - return None - - # Note that _INVALID_INDICATOR and (data, expires) are the only - # valid types of serialized cache entries, so there is not - # a collision with jsonutils.loads(serialized) == None. - if not isinstance(serialized, six.string_types): - serialized = serialized.decode('utf-8') - cached = jsonutils.loads(serialized) - if cached == self._INVALID_INDICATOR: - self.LOG.debug('Cached Token is marked unauthorized') - raise InvalidUserToken('Token authorization failed') - - data, expires = cached - - try: - expires = timeutils.parse_isotime(expires) - except ValueError: - # Gracefully handle upgrade of expiration times from *nix - # timestamps to ISO 8601 formatted dates by ignoring old cached - # values. - return - - expires = timeutils.normalize_time(expires) - utcnow = timeutils.utcnow() - if utcnow < expires: - self.LOG.debug('Returning cached token') - return data - else: - self.LOG.debug('Cached Token seems expired') - raise InvalidUserToken('Token authorization failed') - - def _cache_store(self, token_id, data): - """Store value into memcache. - - data may be _INVALID_INDICATOR or a tuple like (data, expires) - - """ - serialized_data = jsonutils.dumps(data) - if isinstance(serialized_data, six.text_type): - serialized_data = serialized_data.encode('utf-8') - if self._memcache_security_strategy is None: - cache_key = CACHE_KEY_TEMPLATE % token_id - data_to_store = serialized_data - else: - secret_key = self._memcache_secret_key - if isinstance(secret_key, six.string_types): - secret_key = secret_key.encode('utf-8') - security_strategy = self._memcache_security_strategy - if isinstance(security_strategy, six.string_types): - security_strategy = security_strategy.encode('utf-8') - keys = memcache_crypt.derive_keys( - token_id, secret_key, security_strategy) - cache_key = CACHE_KEY_TEMPLATE % memcache_crypt.get_cache_key(keys) - data_to_store = memcache_crypt.protect_data(keys, serialized_data) - - with self._cache_pool.reserve() as cache: - cache.set(cache_key, data_to_store, time=self._cache_time) - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def auth_filter(app): - return AuthProtocol(app, conf) - return auth_filter - - -def app_factory(global_conf, **local_conf): - conf = global_conf.copy() - conf.update(local_conf) - return AuthProtocol(None, conf) - - -if __name__ == '__main__': - """Run this module directly to start a protected echo service:: - - $ python -m keystoneclient.middleware.auth_token - - When the ``auth_token`` module authenticates a request, the echo service - will respond with all the environment variables presented to it by this - module. - - """ - def echo_app(environ, start_response): - """A WSGI application that echoes the CGI environment to the user.""" - start_response('200 OK', [('Content-Type', 'application/json')]) - environment = dict((k, v) for k, v in six.iteritems(environ) - if k.startswith('HTTP_X_')) - yield jsonutils.dumps(environment) - - from wsgiref import simple_server - - # hardcode any non-default configuration here - conf = {'auth_protocol': 'http', 'admin_token': 'ADMIN'} - app = AuthProtocol(echo_app, conf) - server = simple_server.make_server('', 8000, app) - print('Serving on port 8000 (Ctrl+C to end)...') - server.serve_forever() diff --git a/awx/lib/site-packages/keystoneclient/middleware/memcache_crypt.py b/awx/lib/site-packages/keystoneclient/middleware/memcache_crypt.py deleted file mode 100644 index 40e2051320..0000000000 --- a/awx/lib/site-packages/keystoneclient/middleware/memcache_crypt.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2010-2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Utilities for memcache encryption and integrity check. - -Data should be serialized before entering these functions. Encryption -has a dependency on the pycrypto. If pycrypto is not available, -CryptoUnavailableError will be raised. - -This module will not be called unless signing or encryption is enabled -in the config. It will always validate signatures, and will decrypt -data if encryption is enabled. It is not valid to mix protection -modes. - -""" - -import base64 -import functools -import hashlib -import hmac -import math -import os -import sys - -import six - -# make sure pycrypto is available -try: - from Crypto.Cipher import AES -except ImportError: - AES = None - -HASH_FUNCTION = hashlib.sha384 -DIGEST_LENGTH = HASH_FUNCTION().digest_size -DIGEST_SPLIT = DIGEST_LENGTH // 3 -DIGEST_LENGTH_B64 = 4 * int(math.ceil(DIGEST_LENGTH / 3.0)) - - -class InvalidMacError(Exception): - """raise when unable to verify MACed data. - - This usually indicates that data had been expectedly modified in memcache. - - """ - pass - - -class DecryptError(Exception): - """raise when unable to decrypt encrypted data. - - """ - pass - - -class CryptoUnavailableError(Exception): - """raise when Python Crypto module is not available. - - """ - pass - - -def assert_crypto_availability(f): - """Ensure Crypto module is available.""" - - @functools.wraps(f) - def wrapper(*args, **kwds): - if AES is None: - raise CryptoUnavailableError() - return f(*args, **kwds) - return wrapper - - -if sys.version_info >= (3, 3): - constant_time_compare = hmac.compare_digest -else: - def constant_time_compare(first, second): - """Returns True if both string inputs are equal, otherwise False. - - This function should take a constant amount of time regardless of - how many characters in the strings match. - - """ - if len(first) != len(second): - return False - result = 0 - if six.PY3 and isinstance(first, bytes) and isinstance(second, bytes): - for x, y in zip(first, second): - result |= x ^ y - else: - for x, y in zip(first, second): - result |= ord(x) ^ ord(y) - return result == 0 - - -def derive_keys(token, secret, strategy): - """Derives keys for MAC and ENCRYPTION from the user-provided - secret. The resulting keys should be passed to the protect and - unprotect functions. - - As suggested by NIST Special Publication 800-108, this uses the - first 128 bits from the sha384 KDF for the obscured cache key - value, the second 128 bits for the message authentication key and - the remaining 128 bits for the encryption key. - - This approach is faster than computing a separate hmac as the KDF - for each desired key. - """ - digest = hmac.new(secret, token + strategy, HASH_FUNCTION).digest() - return {'CACHE_KEY': digest[:DIGEST_SPLIT], - 'MAC': digest[DIGEST_SPLIT: 2 * DIGEST_SPLIT], - 'ENCRYPTION': digest[2 * DIGEST_SPLIT:], - 'strategy': strategy} - - -def sign_data(key, data): - """Sign the data using the defined function and the derived key.""" - mac = hmac.new(key, data, HASH_FUNCTION).digest() - return base64.b64encode(mac) - - -@assert_crypto_availability -def encrypt_data(key, data): - """Encrypt the data with the given secret key. - - Padding is n bytes of the value n, where 1 <= n <= blocksize. - """ - iv = os.urandom(16) - cipher = AES.new(key, AES.MODE_CBC, iv) - padding = 16 - len(data) % 16 - return iv + cipher.encrypt(data + six.int2byte(padding) * padding) - - -@assert_crypto_availability -def decrypt_data(key, data): - """Decrypt the data with the given secret key.""" - iv = data[:16] - cipher = AES.new(key, AES.MODE_CBC, iv) - try: - result = cipher.decrypt(data[16:]) - except Exception: - raise DecryptError('Encrypted data appears to be corrupted.') - - # Strip the last n padding bytes where n is the last value in - # the plaintext - return result[:-1 * six.byte2int([result[-1]])] - - -def protect_data(keys, data): - """Given keys and serialized data, returns an appropriately - protected string suitable for storage in the cache. - - """ - if keys['strategy'] == b'ENCRYPT': - data = encrypt_data(keys['ENCRYPTION'], data) - - encoded_data = base64.b64encode(data) - - signature = sign_data(keys['MAC'], encoded_data) - return signature + encoded_data - - -def unprotect_data(keys, signed_data): - """Given keys and cached string data, verifies the signature, - decrypts if necessary, and returns the original serialized data. - - """ - # cache backends return None when no data is found. We don't mind - # that this particular special value is unsigned. - if signed_data is None: - return None - - # First we calculate the signature - provided_mac = signed_data[:DIGEST_LENGTH_B64] - calculated_mac = sign_data( - keys['MAC'], - signed_data[DIGEST_LENGTH_B64:]) - - # Then verify that it matches the provided value - if not constant_time_compare(provided_mac, calculated_mac): - raise InvalidMacError('Invalid MAC; data appears to be corrupted.') - - data = base64.b64decode(signed_data[DIGEST_LENGTH_B64:]) - - # then if necessary decrypt the data - if keys['strategy'] == b'ENCRYPT': - data = decrypt_data(keys['ENCRYPTION'], data) - - return data - - -def get_cache_key(keys): - """Given keys generated by derive_keys(), returns a base64 - encoded value suitable for use as a cache key in memcached. - - """ - return base64.b64encode(keys['CACHE_KEY']) diff --git a/awx/lib/site-packages/keystoneclient/middleware/s3_token.py b/awx/lib/site-packages/keystoneclient/middleware/s3_token.py deleted file mode 100644 index 755289347a..0000000000 --- a/awx/lib/site-packages/keystoneclient/middleware/s3_token.py +++ /dev/null @@ -1,267 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011,2012 Akira YOSHIYAMA <akirayoshiyama@gmail.com> -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# This source code is based ./auth_token.py and ./ec2_token.py. -# See them for their copyright. - -""" -S3 TOKEN MIDDLEWARE - -This WSGI component: - -* Get a request from the swift3 middleware with an S3 Authorization - access key. -* Validate s3 token in Keystone. -* Transform the account name to AUTH_%(tenant_name). - -""" - -import logging - -from oslo_serialization import jsonutils -import requests -import six -from six.moves import urllib -import webob - - -PROTOCOL_NAME = 'S3 Token Authentication' - - -# TODO(kun): remove it after oslo merge this. -def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False): - """Validate and split the given HTTP request path. - - **Examples**:: - - ['a'] = split_path('/a') - ['a', None] = split_path('/a', 1, 2) - ['a', 'c'] = split_path('/a/c', 1, 2) - ['a', 'c', 'o/r'] = split_path('/a/c/o/r', 1, 3, True) - - :param path: HTTP Request path to be split - :param minsegs: Minimum number of segments to be extracted - :param maxsegs: Maximum number of segments to be extracted - :param rest_with_last: If True, trailing data will be returned as part - of last segment. If False, and there is - trailing data, raises ValueError. - :returns: list of segments with a length of maxsegs (non-existent - segments will return as None) - :raises: ValueError if given an invalid path - """ - if not maxsegs: - maxsegs = minsegs - if minsegs > maxsegs: - raise ValueError('minsegs > maxsegs: %d > %d' % (minsegs, maxsegs)) - if rest_with_last: - segs = path.split('/', maxsegs) - minsegs += 1 - maxsegs += 1 - count = len(segs) - if (segs[0] or count < minsegs or count > maxsegs or - '' in segs[1:minsegs]): - raise ValueError('Invalid path: %s' % urllib.parse.quote(path)) - else: - minsegs += 1 - maxsegs += 1 - segs = path.split('/', maxsegs) - count = len(segs) - if (segs[0] or count < minsegs or count > maxsegs + 1 or - '' in segs[1:minsegs] or - (count == maxsegs + 1 and segs[maxsegs])): - raise ValueError('Invalid path: %s' % urllib.parse.quote(path)) - segs = segs[1:maxsegs] - segs.extend([None] * (maxsegs - 1 - len(segs))) - return segs - - -class ServiceError(Exception): - pass - - -class S3Token(object): - """Auth Middleware that handles S3 authenticating client calls.""" - - def __init__(self, app, conf): - """Common initialization code.""" - self.app = app - self.logger = logging.getLogger(conf.get('log_name', __name__)) - self.logger.debug('Starting the %s component', PROTOCOL_NAME) - self.logger.warning( - 'This middleware module is deprecated as of v0.11.0 in favor of ' - 'keystonemiddleware.s3_token - please update your WSGI pipeline ' - 'to reference the new middleware package.') - self.reseller_prefix = conf.get('reseller_prefix', 'AUTH_') - # where to find the auth service (we use this to validate tokens) - - auth_host = conf.get('auth_host') - auth_port = int(conf.get('auth_port', 35357)) - auth_protocol = conf.get('auth_protocol', 'https') - - self.request_uri = '%s://%s:%s' % (auth_protocol, auth_host, auth_port) - - # SSL - insecure = conf.get('insecure', False) - cert_file = conf.get('certfile') - key_file = conf.get('keyfile') - - if insecure: - self.verify = False - elif cert_file and key_file: - self.verify = (cert_file, key_file) - elif cert_file: - self.verify = cert_file - else: - self.verify = None - - def deny_request(self, code): - error_table = { - 'AccessDenied': (401, 'Access denied'), - 'InvalidURI': (400, 'Could not parse the specified URI'), - } - resp = webob.Response(content_type='text/xml') - resp.status = error_table[code][0] - error_msg = ('<?xml version="1.0" encoding="UTF-8"?>\r\n' - '<Error>\r\n <Code>%s</Code>\r\n ' - '<Message>%s</Message>\r\n</Error>\r\n' % - (code, error_table[code][1])) - if six.PY3: - error_msg = error_msg.encode() - resp.body = error_msg - return resp - - def _json_request(self, creds_json): - headers = {'Content-Type': 'application/json'} - try: - response = requests.post('%s/v2.0/s3tokens' % self.request_uri, - headers=headers, data=creds_json, - verify=self.verify) - except requests.exceptions.RequestException as e: - self.logger.info('HTTP connection exception: %s', e) - resp = self.deny_request('InvalidURI') - raise ServiceError(resp) - - if response.status_code < 200 or response.status_code >= 300: - self.logger.debug('Keystone reply error: status=%s reason=%s', - response.status_code, response.reason) - resp = self.deny_request('AccessDenied') - raise ServiceError(resp) - - return response - - def __call__(self, environ, start_response): - """Handle incoming request. authenticate and send downstream.""" - req = webob.Request(environ) - self.logger.debug('Calling S3Token middleware.') - - try: - parts = split_path(req.path, 1, 4, True) - version, account, container, obj = parts - except ValueError: - msg = 'Not a path query, skipping.' - self.logger.debug(msg) - return self.app(environ, start_response) - - # Read request signature and access id. - if 'Authorization' not in req.headers: - msg = 'No Authorization header. skipping.' - self.logger.debug(msg) - return self.app(environ, start_response) - - token = req.headers.get('X-Auth-Token', - req.headers.get('X-Storage-Token')) - if not token: - msg = 'You did not specify an auth or a storage token. skipping.' - self.logger.debug(msg) - return self.app(environ, start_response) - - auth_header = req.headers['Authorization'] - try: - access, signature = auth_header.split(' ')[-1].rsplit(':', 1) - except ValueError: - msg = 'You have an invalid Authorization header: %s' - self.logger.debug(msg, auth_header) - return self.deny_request('InvalidURI')(environ, start_response) - - # NOTE(chmou): This is to handle the special case with nova - # when we have the option s3_affix_tenant. We will force it to - # connect to another account than the one - # authenticated. Before people start getting worried about - # security, I should point that we are connecting with - # username/token specified by the user but instead of - # connecting to its own account we will force it to go to an - # another account. In a normal scenario if that user don't - # have the reseller right it will just fail but since the - # reseller account can connect to every account it is allowed - # by the swift_auth middleware. - force_tenant = None - if ':' in access: - access, force_tenant = access.split(':') - - # Authenticate request. - creds = {'credentials': {'access': access, - 'token': token, - 'signature': signature}} - creds_json = jsonutils.dumps(creds) - self.logger.debug('Connecting to Keystone sending this JSON: %s', - creds_json) - # NOTE(vish): We could save a call to keystone by having - # keystone return token, tenant, user, and roles - # from this call. - # - # NOTE(chmou): We still have the same problem we would need to - # change token_auth to detect if we already - # identified and not doing a second query and just - # pass it through to swiftauth in this case. - try: - resp = self._json_request(creds_json) - except ServiceError as e: - resp = e.args[0] - msg = 'Received error, exiting middleware with error: %s' - self.logger.debug(msg, resp.status_code) - return resp(environ, start_response) - - self.logger.debug('Keystone Reply: Status: %d, Output: %s', - resp.status_code, resp.content) - - try: - identity_info = resp.json() - token_id = str(identity_info['access']['token']['id']) - tenant = identity_info['access']['token']['tenant'] - except (ValueError, KeyError): - error = 'Error on keystone reply: %d %s' - self.logger.debug(error, resp.status_code, resp.content) - return self.deny_request('InvalidURI')(environ, start_response) - - req.headers['X-Auth-Token'] = token_id - tenant_to_connect = force_tenant or tenant['id'] - self.logger.debug('Connecting with tenant: %s', tenant_to_connect) - new_tenant_name = '%s%s' % (self.reseller_prefix, tenant_to_connect) - environ['PATH_INFO'] = environ['PATH_INFO'].replace(account, - new_tenant_name) - return self.app(environ, start_response) - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def auth_filter(app): - return S3Token(app, conf) - return auth_filter diff --git a/awx/lib/site-packages/keystoneclient/openstack/__init__.py b/awx/lib/site-packages/keystoneclient/openstack/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/__init__.py b/awx/lib/site-packages/keystoneclient/openstack/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/_i18n.py b/awx/lib/site-packages/keystoneclient/openstack/common/_i18n.py deleted file mode 100644 index 52a5e84784..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/_i18n.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html - -""" - -import oslo.i18n - - -# NOTE(dhellmann): This reference to o-s-l-o will be replaced by the -# application name when this module is synced into the separate -# repository. It is OK to have more than one translation function -# using the same domain, since there will still only be one message -# catalog. -_translators = oslo.i18n.TranslatorFactory(domain='keystoneclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/__init__.py b/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/auth.py b/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/auth.py deleted file mode 100644 index e68990d57c..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/auth.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 Spanish National Research Council. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import abc -import argparse -import os - -import six -from stevedore import extension - -from keystoneclient.openstack.common.apiclient import exceptions - - -_discovered_plugins = {} - - -def discover_auth_systems(): - """Discover the available auth-systems. - - This won't take into account the old style auth-systems. - """ - global _discovered_plugins - _discovered_plugins = {} - - def add_plugin(ext): - _discovered_plugins[ext.name] = ext.plugin - - ep_namespace = "keystoneclient.openstack.common.apiclient.auth" - mgr = extension.ExtensionManager(ep_namespace) - mgr.map(add_plugin) - - -def load_auth_system_opts(parser): - """Load options needed by the available auth-systems into a parser. - - This function will try to populate the parser with options from the - available plugins. - """ - group = parser.add_argument_group("Common auth options") - BaseAuthPlugin.add_common_opts(group) - for name, auth_plugin in six.iteritems(_discovered_plugins): - group = parser.add_argument_group( - "Auth-system '%s' options" % name, - conflict_handler="resolve") - auth_plugin.add_opts(group) - - -def load_plugin(auth_system): - try: - plugin_class = _discovered_plugins[auth_system] - except KeyError: - raise exceptions.AuthSystemNotFound(auth_system) - return plugin_class(auth_system=auth_system) - - -def load_plugin_from_args(args): - """Load required plugin and populate it with options. - - Try to guess auth system if it is not specified. Systems are tried in - alphabetical order. - - :type args: argparse.Namespace - :raises: AuthPluginOptionsMissing - """ - auth_system = args.os_auth_system - if auth_system: - plugin = load_plugin(auth_system) - plugin.parse_opts(args) - plugin.sufficient_options() - return plugin - - for plugin_auth_system in sorted(six.iterkeys(_discovered_plugins)): - plugin_class = _discovered_plugins[plugin_auth_system] - plugin = plugin_class() - plugin.parse_opts(args) - try: - plugin.sufficient_options() - except exceptions.AuthPluginOptionsMissing: - continue - return plugin - raise exceptions.AuthPluginOptionsMissing(["auth_system"]) - - -@six.add_metaclass(abc.ABCMeta) -class BaseAuthPlugin(object): - """Base class for authentication plugins. - - An authentication plugin needs to override at least the authenticate - method to be a valid plugin. - """ - - auth_system = None - opt_names = [] - common_opt_names = [ - "auth_system", - "username", - "password", - "tenant_name", - "token", - "auth_url", - ] - - def __init__(self, auth_system=None, **kwargs): - self.auth_system = auth_system or self.auth_system - self.opts = dict((name, kwargs.get(name)) - for name in self.opt_names) - - @staticmethod - def _parser_add_opt(parser, opt): - """Add an option to parser in two variants. - - :param opt: option name (with underscores) - """ - dashed_opt = opt.replace("_", "-") - env_var = "OS_%s" % opt.upper() - arg_default = os.environ.get(env_var, "") - arg_help = "Defaults to env[%s]." % env_var - parser.add_argument( - "--os-%s" % dashed_opt, - metavar="<%s>" % dashed_opt, - default=arg_default, - help=arg_help) - parser.add_argument( - "--os_%s" % opt, - metavar="<%s>" % dashed_opt, - help=argparse.SUPPRESS) - - @classmethod - def add_opts(cls, parser): - """Populate the parser with the options for this plugin. - """ - for opt in cls.opt_names: - # use `BaseAuthPlugin.common_opt_names` since it is never - # changed in child classes - if opt not in BaseAuthPlugin.common_opt_names: - cls._parser_add_opt(parser, opt) - - @classmethod - def add_common_opts(cls, parser): - """Add options that are common for several plugins. - """ - for opt in cls.common_opt_names: - cls._parser_add_opt(parser, opt) - - @staticmethod - def get_opt(opt_name, args): - """Return option name and value. - - :param opt_name: name of the option, e.g., "username" - :param args: parsed arguments - """ - return (opt_name, getattr(args, "os_%s" % opt_name, None)) - - def parse_opts(self, args): - """Parse the actual auth-system options if any. - - This method is expected to populate the attribute `self.opts` with a - dict containing the options and values needed to make authentication. - """ - self.opts.update(dict(self.get_opt(opt_name, args) - for opt_name in self.opt_names)) - - def authenticate(self, http_client): - """Authenticate using plugin defined method. - - The method usually analyses `self.opts` and performs - a request to authentication server. - - :param http_client: client object that needs authentication - :type http_client: HTTPClient - :raises: AuthorizationFailure - """ - self.sufficient_options() - self._do_authenticate(http_client) - - @abc.abstractmethod - def _do_authenticate(self, http_client): - """Protected method for authentication. - """ - - def sufficient_options(self): - """Check if all required options are present. - - :raises: AuthPluginOptionsMissing - """ - missing = [opt - for opt in self.opt_names - if not self.opts.get(opt)] - if missing: - raise exceptions.AuthPluginOptionsMissing(missing) - - @abc.abstractmethod - def token_and_endpoint(self, endpoint_type, service_type): - """Return token and endpoint. - - :param service_type: Service type of the endpoint - :type service_type: string - :param endpoint_type: Type of endpoint. - Possible values: public or publicURL, - internal or internalURL, - admin or adminURL - :type endpoint_type: string - :returns: tuple of token and endpoint strings - :raises: EndpointException - """ diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/base.py b/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/base.py deleted file mode 100644 index 72d7999d11..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/base.py +++ /dev/null @@ -1,518 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2012 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -# E1102: %s is not callable -# pylint: disable=E1102 - -import abc -import copy - -from oslo.utils import strutils -import six -from six.moves.urllib import parse - -from keystoneclient.openstack.common._i18n import _ -from keystoneclient.openstack.common.apiclient import exceptions - - -def getid(obj): - """Return id if argument is a Resource. - - Abstracts the common pattern of allowing both an object or an object's ID - (UUID) as a parameter when dealing with relationships. - """ - try: - if obj.uuid: - return obj.uuid - except AttributeError: - pass - try: - return obj.id - except AttributeError: - return obj - - -# TODO(aababilov): call run_hooks() in HookableMixin's child classes -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - """Add a new hook of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param hook_func: hook function - """ - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - """Run all hooks of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param args: args to be passed to every hook function - :param kwargs: kwargs to be passed to every hook function - """ - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - -class BaseManager(HookableMixin): - """Basic manager type providing common operations. - - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, client): - """Initializes BaseManager with `client`. - - :param client: instance of BaseClient descendant for HTTP requests - """ - super(BaseManager, self).__init__() - self.client = client - - def _list(self, url, response_key=None, obj_class=None, json=None): - """List the collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - :param obj_class: class for constructing the returned objects - (self.resource_class will be used by default) - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - """ - if json: - body = self.client.post(url, json=json).json() - else: - body = self.client.get(url).json() - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] if response_key is not None else body - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - try: - data = data['values'] - except (KeyError, TypeError): - pass - - return [obj_class(self, res, loaded=True) for res in data if res] - - def _get(self, url, response_key=None): - """Get an object from collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'server'. If response_key is None - all response body - will be used. - """ - body = self.client.get(url).json() - data = body[response_key] if response_key is not None else body - return self.resource_class(self, data, loaded=True) - - def _head(self, url): - """Retrieve request headers for an object. - - :param url: a partial URL, e.g., '/servers' - """ - resp = self.client.head(url) - return resp.status_code == 204 - - def _post(self, url, json, response_key=None, return_raw=False): - """Create an object. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'server'. If response_key is None - all response body - will be used. - :param return_raw: flag to force returning raw JSON instead of - Python object of self.resource_class - """ - body = self.client.post(url, json=json).json() - data = body[response_key] if response_key is not None else body - if return_raw: - return data - return self.resource_class(self, data) - - def _put(self, url, json=None, response_key=None): - """Update an object with PUT method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - """ - resp = self.client.put(url, json=json) - # PUT requests may not return a body - if resp.content: - body = resp.json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _patch(self, url, json=None, response_key=None): - """Update an object with PATCH method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers'. If response_key is None - all response body - will be used. - """ - body = self.client.patch(url, json=json).json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _delete(self, url): - """Delete an object. - - :param url: a partial URL, e.g., '/servers/my-server' - """ - return self.client.delete(url) - - -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(BaseManager): - """Manager with additional `find()`/`findall()` methods.""" - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - matches = self.findall(**kwargs) - num_matches = len(matches) - if num_matches == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(msg) - elif num_matches > 1: - raise exceptions.NoUniqueMatch() - else: - return matches[0] - - def findall(self, **kwargs): - """Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - found = [] - searches = kwargs.items() - - for obj in self.list(): - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - found.append(obj) - except AttributeError: - continue - - return found - - -class CrudManager(BaseManager): - """Base manager class for manipulating entities. - - Children of this class are expected to define a `collection_key` and `key`. - - - `collection_key`: Usually a plural noun by convention (e.g. `entities`); - used to refer collections in both URL's (e.g. `/v3/entities`) and JSON - objects containing a list of member resources (e.g. `{'entities': [{}, - {}, {}]}`). - - `key`: Usually a singular noun by convention (e.g. `entity`); used to - refer to an individual member of the collection. - - """ - collection_key = None - key = None - - def build_url(self, base_url=None, **kwargs): - """Builds a resource URL for the given kwargs. - - Given an example collection where `collection_key = 'entities'` and - `key = 'entity'`, the following URL's could be generated. - - By default, the URL will represent a collection of entities, e.g.:: - - /entities - - If kwargs contains an `entity_id`, then the URL will represent a - specific member, e.g.:: - - /entities/{entity_id} - - :param base_url: if provided, the generated URL will be appended to it - """ - url = base_url if base_url is not None else '' - - url += '/%s' % self.collection_key - - # do we have a specific entity? - entity_id = kwargs.get('%s_id' % self.key) - if entity_id is not None: - url += '/%s' % entity_id - - return url - - def _filter_kwargs(self, kwargs): - """Drop null values and handle ids.""" - for key, ref in six.iteritems(kwargs.copy()): - if ref is None: - kwargs.pop(key) - else: - if isinstance(ref, Resource): - kwargs.pop(key) - kwargs['%s_id' % key] = getid(ref) - return kwargs - - def create(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._post( - self.build_url(**kwargs), - {self.key: kwargs}, - self.key) - - def get(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._get( - self.build_url(**kwargs), - self.key) - - def head(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._head(self.build_url(**kwargs)) - - def list(self, base_url=None, **kwargs): - """List the collection. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - - def put(self, base_url=None, **kwargs): - """Update an element. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._put(self.build_url(base_url=base_url, **kwargs)) - - def update(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - params = kwargs.copy() - params.pop('%s_id' % self.key) - - return self._patch( - self.build_url(**kwargs), - {self.key: params}, - self.key) - - def delete(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - - return self._delete( - self.build_url(**kwargs)) - - def find(self, base_url=None, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - rl = self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - num = len(rl) - - if num == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(404, msg) - elif num > 1: - raise exceptions.NoUniqueMatch - else: - return rl[0] - - -class Extension(HookableMixin): - """Extension descriptor.""" - - SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') - manager_class = None - - def __init__(self, name, module): - super(Extension, self).__init__() - self.name = name - self.module = module - self._parse_extension_module() - - def _parse_extension_module(self): - self.manager_class = None - for attr_name, attr_value in self.module.__dict__.items(): - if attr_name in self.SUPPORTED_HOOKS: - self.add_hook(attr_name, attr_value) - else: - try: - if issubclass(attr_value, BaseManager): - self.manager_class = attr_value - except TypeError: - pass - - def __repr__(self): - return "<Extension '%s'>" % self.name - - -class Resource(object): - """Base class for OpenStack resources (tenant, user, etc.). - - This is pretty much just a bag for attributes. - """ - - HUMAN_ID = False - NAME_ATTR = 'name' - - def __init__(self, manager, info, loaded=False): - """Populate and bind to a manager. - - :param manager: BaseManager object - :param info: dictionary representing resource attributes - :param loaded: prevent lazy-loading if set to True - """ - self.manager = manager - self._info = info - self._add_details(info) - self._loaded = loaded - - def __repr__(self): - reprkeys = sorted(k - for k in self.__dict__.keys() - if k[0] != '_' and k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) - - @property - def human_id(self): - """Human-readable ID which can be used for bash completion. - """ - if self.HUMAN_ID: - name = getattr(self, self.NAME_ATTR, None) - if name is not None: - return strutils.to_slug(name) - return None - - def _add_details(self, info): - for (k, v) in six.iteritems(info): - try: - setattr(self, k, v) - self._info[k] = v - except AttributeError: - # In this case we already defined the attribute on the class - pass - - def __getattr__(self, k): - if k not in self.__dict__: - # NOTE(bcwaldon): disallow lazy-loading if already loaded once - if not self.is_loaded(): - self.get() - return self.__getattr__(k) - - raise AttributeError(k) - else: - return self.__dict__[k] - - def get(self): - """Support for lazy loading details. - - Some clients, such as novaclient have the option to lazy load the - details, details which can be loaded with this function. - """ - # set_loaded() first ... so if we have to bail, we know we tried. - self.set_loaded(True) - if not hasattr(self.manager, 'get'): - return - - new = self.manager.get(self.id) - if new: - self._add_details(new._info) - self._add_details( - {'x_request_id': self.manager.client.last_request_id}) - - def __eq__(self, other): - if not isinstance(other, Resource): - return NotImplemented - # two resources of different types are not equal - if not isinstance(other, self.__class__): - return False - if hasattr(self, 'id') and hasattr(other, 'id'): - return self.id == other.id - return self._info == other._info - - def is_loaded(self): - return self._loaded - - def set_loaded(self, val): - self._loaded = val - - def to_dict(self): - return copy.deepcopy(self._info) diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/client.py b/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/client.py deleted file mode 100644 index dd560aba53..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/client.py +++ /dev/null @@ -1,388 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Piston Cloud Computing, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import hashlib -import logging -import time - -try: - import simplejson as json -except ImportError: - import json - -from oslo.utils import encodeutils -from oslo.utils import importutils -import requests - -from keystoneclient.openstack.common._i18n import _ -from keystoneclient.openstack.common.apiclient import exceptions - -_logger = logging.getLogger(__name__) -SENSITIVE_HEADERS = ('X-Auth-Token', 'X-Subject-Token',) - - -class HTTPClient(object): - """This client handles sending HTTP requests to OpenStack servers. - - Features: - - - share authentication information between several clients to different - services (e.g., for compute and image clients); - - reissue authentication request for expired tokens; - - encode/decode JSON bodies; - - raise exceptions on HTTP errors; - - pluggable authentication; - - store authentication information in a keyring; - - store time spent for requests; - - register clients for particular services, so one can use - `http_client.identity` or `http_client.compute`; - - log requests and responses in a format that is easy to copy-and-paste - into terminal and send the same request with curl. - """ - - user_agent = "keystoneclient.openstack.common.apiclient" - - def __init__(self, - auth_plugin, - region_name=None, - endpoint_type="publicURL", - original_ip=None, - verify=True, - cert=None, - timeout=None, - timings=False, - keyring_saver=None, - debug=False, - user_agent=None, - http=None): - self.auth_plugin = auth_plugin - - self.endpoint_type = endpoint_type - self.region_name = region_name - - self.original_ip = original_ip - self.timeout = timeout - self.verify = verify - self.cert = cert - - self.keyring_saver = keyring_saver - self.debug = debug - self.user_agent = user_agent or self.user_agent - - self.times = [] # [("item", starttime, endtime), ...] - self.timings = timings - - # requests within the same session can reuse TCP connections from pool - self.http = http or requests.Session() - - self.cached_token = None - self.last_request_id = None - - def _safe_header(self, name, value): - if name in SENSITIVE_HEADERS: - # because in python3 byte string handling is ... ug - v = value.encode('utf-8') - h = hashlib.sha1(v) - d = h.hexdigest() - return encodeutils.safe_decode(name), "{SHA1}%s" % d - else: - return (encodeutils.safe_decode(name), - encodeutils.safe_decode(value)) - - def _http_log_req(self, method, url, kwargs): - if not self.debug: - return - - string_parts = [ - "curl -i", - "-X '%s'" % method, - "'%s'" % url, - ] - - for element in kwargs['headers']: - header = ("-H '%s: %s'" % - self._safe_header(element, kwargs['headers'][element])) - string_parts.append(header) - - _logger.debug("REQ: %s" % " ".join(string_parts)) - if 'data' in kwargs: - _logger.debug("REQ BODY: %s\n" % (kwargs['data'])) - - def _http_log_resp(self, resp): - if not self.debug: - return - _logger.debug( - "RESP: [%s] %s\n", - resp.status_code, - resp.headers) - if resp._content_consumed: - _logger.debug( - "RESP BODY: %s\n", - resp.text) - - def serialize(self, kwargs): - if kwargs.get('json') is not None: - kwargs['headers']['Content-Type'] = 'application/json' - kwargs['data'] = json.dumps(kwargs['json']) - try: - del kwargs['json'] - except KeyError: - pass - - def get_timings(self): - return self.times - - def reset_timings(self): - self.times = [] - - def request(self, method, url, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around `requests.Session.request` to handle tasks such as - setting headers, JSON encoding/decoding, and error handling. - - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - requests.Session.request (such as `headers`) or `json` - that will be encoded as JSON and used as `data` argument - """ - kwargs.setdefault("headers", {}) - kwargs["headers"]["User-Agent"] = self.user_agent - if self.original_ip: - kwargs["headers"]["Forwarded"] = "for=%s;by=%s" % ( - self.original_ip, self.user_agent) - if self.timeout is not None: - kwargs.setdefault("timeout", self.timeout) - kwargs.setdefault("verify", self.verify) - if self.cert is not None: - kwargs.setdefault("cert", self.cert) - self.serialize(kwargs) - - self._http_log_req(method, url, kwargs) - if self.timings: - start_time = time.time() - resp = self.http.request(method, url, **kwargs) - if self.timings: - self.times.append(("%s %s" % (method, url), - start_time, time.time())) - self._http_log_resp(resp) - - self.last_request_id = resp.headers.get('x-openstack-request-id') - - if resp.status_code >= 400: - _logger.debug( - "Request returned failure status: %s", - resp.status_code) - raise exceptions.from_response(resp, method, url) - - return resp - - @staticmethod - def concat_url(endpoint, url): - """Concatenate endpoint and final URL. - - E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to - "http://keystone/v2.0/tokens". - - :param endpoint: the base URL - :param url: the final URL - """ - return "%s/%s" % (endpoint.rstrip("/"), url.strip("/")) - - def client_request(self, client, method, url, **kwargs): - """Send an http request using `client`'s endpoint and specified `url`. - - If request was rejected as unauthorized (possibly because the token is - expired), issue one authorization attempt and send the request once - again. - - :param client: instance of BaseClient descendant - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - `HTTPClient.request` - """ - - filter_args = { - "endpoint_type": client.endpoint_type or self.endpoint_type, - "service_type": client.service_type, - } - token, endpoint = (self.cached_token, client.cached_endpoint) - just_authenticated = False - if not (token and endpoint): - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - pass - if not (token and endpoint): - self.authenticate() - just_authenticated = True - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - if not (token and endpoint): - raise exceptions.AuthorizationFailure( - _("Cannot find endpoint or token for request")) - - old_token_endpoint = (token, endpoint) - kwargs.setdefault("headers", {})["X-Auth-Token"] = token - self.cached_token = token - client.cached_endpoint = endpoint - # Perform the request once. If we get Unauthorized, then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - except exceptions.Unauthorized as unauth_ex: - if just_authenticated: - raise - self.cached_token = None - client.cached_endpoint = None - if self.auth_plugin.opts.get('token'): - self.auth_plugin.opts['token'] = None - if self.auth_plugin.opts.get('endpoint'): - self.auth_plugin.opts['endpoint'] = None - self.authenticate() - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - raise unauth_ex - if (not (token and endpoint) or - old_token_endpoint == (token, endpoint)): - raise unauth_ex - self.cached_token = token - client.cached_endpoint = endpoint - kwargs["headers"]["X-Auth-Token"] = token - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - - def add_client(self, base_client_instance): - """Add a new instance of :class:`BaseClient` descendant. - - `self` will store a reference to `base_client_instance`. - - Example: - - >>> def test_clients(): - ... from keystoneclient.auth import keystone - ... from openstack.common.apiclient import client - ... auth = keystone.KeystoneAuthPlugin( - ... username="user", password="pass", tenant_name="tenant", - ... auth_url="http://auth:5000/v2.0") - ... openstack_client = client.HTTPClient(auth) - ... # create nova client - ... from novaclient.v1_1 import client - ... client.Client(openstack_client) - ... # create keystone client - ... from keystoneclient.v2_0 import client - ... client.Client(openstack_client) - ... # use them - ... openstack_client.identity.tenants.list() - ... openstack_client.compute.servers.list() - """ - service_type = base_client_instance.service_type - if service_type and not hasattr(self, service_type): - setattr(self, service_type, base_client_instance) - - def authenticate(self): - self.auth_plugin.authenticate(self) - # Store the authentication results in the keyring for later requests - if self.keyring_saver: - self.keyring_saver.save(self) - - -class BaseClient(object): - """Top-level object to access the OpenStack API. - - This client uses :class:`HTTPClient` to send requests. :class:`HTTPClient` - will handle a bunch of issues such as authentication. - """ - - service_type = None - endpoint_type = None # "publicURL" will be used - cached_endpoint = None - - def __init__(self, http_client, extensions=None): - self.http_client = http_client - http_client.add_client(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - def client_request(self, method, url, **kwargs): - return self.http_client.client_request( - self, method, url, **kwargs) - - @property - def last_request_id(self): - return self.http_client.last_request_id - - def head(self, url, **kwargs): - return self.client_request("HEAD", url, **kwargs) - - def get(self, url, **kwargs): - return self.client_request("GET", url, **kwargs) - - def post(self, url, **kwargs): - return self.client_request("POST", url, **kwargs) - - def put(self, url, **kwargs): - return self.client_request("PUT", url, **kwargs) - - def delete(self, url, **kwargs): - return self.client_request("DELETE", url, **kwargs) - - def patch(self, url, **kwargs): - return self.client_request("PATCH", url, **kwargs) - - @staticmethod - def get_class(api_name, version, version_map): - """Returns the client class for the requested API version - - :param api_name: the name of the API, e.g. 'compute', 'image', etc - :param version: the requested API version - :param version_map: a dict of client classes keyed by version - :rtype: a client class for the requested API version - """ - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = _("Invalid %(api_name)s client version '%(version)s'. " - "Must be one of: %(version_map)s") % { - 'api_name': api_name, - 'version': version, - 'version_map': ', '.join(version_map.keys())} - raise exceptions.UnsupportedVersion(msg) - - return importutils.import_class(client_path) diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/exceptions.py b/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/exceptions.py deleted file mode 100644 index a4ff25add8..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/exceptions.py +++ /dev/null @@ -1,458 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Nebula, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception definitions. -""" - -import inspect -import sys - -import six - -from keystoneclient.openstack.common._i18n import _ - - -class ClientException(Exception): - """The base exception class for all exceptions this library raises. - """ - pass - - -class ValidationError(ClientException): - """Error in validation on API client side.""" - pass - - -class UnsupportedVersion(ClientException): - """User is trying to use an unsupported version of the API.""" - pass - - -class CommandError(ClientException): - """Error in CLI tool.""" - pass - - -class AuthorizationFailure(ClientException): - """Cannot authorize API client.""" - pass - - -class ConnectionRefused(ClientException): - """Cannot connect to API service.""" - pass - - -class AuthPluginOptionsMissing(AuthorizationFailure): - """Auth plugin misses some options.""" - def __init__(self, opt_names): - super(AuthPluginOptionsMissing, self).__init__( - _("Authentication failed. Missing options: %s") % - ", ".join(opt_names)) - self.opt_names = opt_names - - -class AuthSystemNotFound(AuthorizationFailure): - """User has specified an AuthSystem that is not installed.""" - def __init__(self, auth_system): - super(AuthSystemNotFound, self).__init__( - _("AuthSystemNotFound: %s") % repr(auth_system)) - self.auth_system = auth_system - - -class NoUniqueMatch(ClientException): - """Multiple entities found instead of one.""" - pass - - -class EndpointException(ClientException): - """Something is rotten in Service Catalog.""" - pass - - -class EndpointNotFound(EndpointException): - """Could not find requested endpoint in Service Catalog.""" - pass - - -class AmbiguousEndpoints(EndpointException): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - super(AmbiguousEndpoints, self).__init__( - _("AmbiguousEndpoints: %s") % repr(endpoints)) - self.endpoints = endpoints - - -class HttpError(ClientException): - """The base exception class for all HTTP exceptions. - """ - http_status = 0 - message = _("HTTP Error") - - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None): - self.http_status = http_status or self.http_status - self.message = message or self.message - self.details = details - self.request_id = request_id - self.response = response - self.url = url - self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) - if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HttpError, self).__init__(formatted_string) - - -class HTTPRedirection(HttpError): - """HTTP Redirection.""" - message = _("HTTP Redirection") - - -class HTTPClientError(HttpError): - """Client-side HTTP error. - - Exception for cases in which the client seems to have erred. - """ - message = _("HTTP Client Error") - - -class HttpServerError(HttpError): - """Server-side HTTP error. - - Exception for cases in which the server is aware that it has - erred or is incapable of performing the request. - """ - message = _("HTTP Server Error") - - -class MultipleChoices(HTTPRedirection): - """HTTP 300 - Multiple Choices. - - Indicates multiple options for the resource that the client may follow. - """ - - http_status = 300 - message = _("Multiple Choices") - - -class BadRequest(HTTPClientError): - """HTTP 400 - Bad Request. - - The request cannot be fulfilled due to bad syntax. - """ - http_status = 400 - message = _("Bad Request") - - -class Unauthorized(HTTPClientError): - """HTTP 401 - Unauthorized. - - Similar to 403 Forbidden, but specifically for use when authentication - is required and has failed or has not yet been provided. - """ - http_status = 401 - message = _("Unauthorized") - - -class PaymentRequired(HTTPClientError): - """HTTP 402 - Payment Required. - - Reserved for future use. - """ - http_status = 402 - message = _("Payment Required") - - -class Forbidden(HTTPClientError): - """HTTP 403 - Forbidden. - - The request was a valid request, but the server is refusing to respond - to it. - """ - http_status = 403 - message = _("Forbidden") - - -class NotFound(HTTPClientError): - """HTTP 404 - Not Found. - - The requested resource could not be found but may be available again - in the future. - """ - http_status = 404 - message = _("Not Found") - - -class MethodNotAllowed(HTTPClientError): - """HTTP 405 - Method Not Allowed. - - A request was made of a resource using a request method not supported - by that resource. - """ - http_status = 405 - message = _("Method Not Allowed") - - -class NotAcceptable(HTTPClientError): - """HTTP 406 - Not Acceptable. - - The requested resource is only capable of generating content not - acceptable according to the Accept headers sent in the request. - """ - http_status = 406 - message = _("Not Acceptable") - - -class ProxyAuthenticationRequired(HTTPClientError): - """HTTP 407 - Proxy Authentication Required. - - The client must first authenticate itself with the proxy. - """ - http_status = 407 - message = _("Proxy Authentication Required") - - -class RequestTimeout(HTTPClientError): - """HTTP 408 - Request Timeout. - - The server timed out waiting for the request. - """ - http_status = 408 - message = _("Request Timeout") - - -class Conflict(HTTPClientError): - """HTTP 409 - Conflict. - - Indicates that the request could not be processed because of conflict - in the request, such as an edit conflict. - """ - http_status = 409 - message = _("Conflict") - - -class Gone(HTTPClientError): - """HTTP 410 - Gone. - - Indicates that the resource requested is no longer available and will - not be available again. - """ - http_status = 410 - message = _("Gone") - - -class LengthRequired(HTTPClientError): - """HTTP 411 - Length Required. - - The request did not specify the length of its content, which is - required by the requested resource. - """ - http_status = 411 - message = _("Length Required") - - -class PreconditionFailed(HTTPClientError): - """HTTP 412 - Precondition Failed. - - The server does not meet one of the preconditions that the requester - put on the request. - """ - http_status = 412 - message = _("Precondition Failed") - - -class RequestEntityTooLarge(HTTPClientError): - """HTTP 413 - Request Entity Too Large. - - The request is larger than the server is willing or able to process. - """ - http_status = 413 - message = _("Request Entity Too Large") - - def __init__(self, *args, **kwargs): - try: - self.retry_after = int(kwargs.pop('retry_after')) - except (KeyError, ValueError): - self.retry_after = 0 - - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) - - -class RequestUriTooLong(HTTPClientError): - """HTTP 414 - Request-URI Too Long. - - The URI provided was too long for the server to process. - """ - http_status = 414 - message = _("Request-URI Too Long") - - -class UnsupportedMediaType(HTTPClientError): - """HTTP 415 - Unsupported Media Type. - - The request entity has a media type which the server or resource does - not support. - """ - http_status = 415 - message = _("Unsupported Media Type") - - -class RequestedRangeNotSatisfiable(HTTPClientError): - """HTTP 416 - Requested Range Not Satisfiable. - - The client has asked for a portion of the file, but the server cannot - supply that portion. - """ - http_status = 416 - message = _("Requested Range Not Satisfiable") - - -class ExpectationFailed(HTTPClientError): - """HTTP 417 - Expectation Failed. - - The server cannot meet the requirements of the Expect request-header field. - """ - http_status = 417 - message = _("Expectation Failed") - - -class UnprocessableEntity(HTTPClientError): - """HTTP 422 - Unprocessable Entity. - - The request was well-formed but was unable to be followed due to semantic - errors. - """ - http_status = 422 - message = _("Unprocessable Entity") - - -class InternalServerError(HttpServerError): - """HTTP 500 - Internal Server Error. - - A generic error message, given when no more specific message is suitable. - """ - http_status = 500 - message = _("Internal Server Error") - - -# NotImplemented is a python keyword. -class HttpNotImplemented(HttpServerError): - """HTTP 501 - Not Implemented. - - The server either does not recognize the request method, or it lacks - the ability to fulfill the request. - """ - http_status = 501 - message = _("Not Implemented") - - -class BadGateway(HttpServerError): - """HTTP 502 - Bad Gateway. - - The server was acting as a gateway or proxy and received an invalid - response from the upstream server. - """ - http_status = 502 - message = _("Bad Gateway") - - -class ServiceUnavailable(HttpServerError): - """HTTP 503 - Service Unavailable. - - The server is currently unavailable. - """ - http_status = 503 - message = _("Service Unavailable") - - -class GatewayTimeout(HttpServerError): - """HTTP 504 - Gateway Timeout. - - The server was acting as a gateway or proxy and did not receive a timely - response from the upstream server. - """ - http_status = 504 - message = _("Gateway Timeout") - - -class HttpVersionNotSupported(HttpServerError): - """HTTP 505 - HttpVersion Not Supported. - - The server does not support the HTTP protocol version used in the request. - """ - http_status = 505 - message = _("HTTP Version Not Supported") - - -# _code_map contains all the classes that have http_status attribute. -_code_map = dict( - (getattr(obj, 'http_status', None), obj) - for name, obj in six.iteritems(vars(sys.modules[__name__])) - if inspect.isclass(obj) and getattr(obj, 'http_status', False) -) - - -def from_response(response, method, url): - """Returns an instance of :class:`HttpError` or subclass based on response. - - :param response: instance of `requests.Response` class - :param method: HTTP method used for request - :param url: URL used for request - """ - - req_id = response.headers.get("x-openstack-request-id") - # NOTE(hdd) true for older versions of nova and cinder - if not req_id: - req_id = response.headers.get("x-compute-request-id") - kwargs = { - "http_status": response.status_code, - "response": response, - "method": method, - "url": url, - "request_id": req_id, - } - if "retry-after" in response.headers: - kwargs["retry_after"] = response.headers["retry-after"] - - content_type = response.headers.get("Content-Type", "") - if content_type.startswith("application/json"): - try: - body = response.json() - except ValueError: - pass - else: - if isinstance(body, dict) and isinstance(body.get("error"), dict): - error = body["error"] - kwargs["message"] = error.get("message") - kwargs["details"] = error.get("details") - elif content_type.startswith("text/"): - kwargs["details"] = response.text - - try: - cls = _code_map[response.status_code] - except KeyError: - if 500 <= response.status_code < 600: - cls = HttpServerError - elif 400 <= response.status_code < 500: - cls = HTTPClientError - else: - cls = HttpError - return cls(**kwargs) diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/fake_client.py b/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/fake_client.py deleted file mode 100644 index 46fc5368c8..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/fake_client.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -# W0102: Dangerous default value %s as argument -# pylint: disable=W0102 - -import json - -import requests -import six -from six.moves.urllib import parse - -from keystoneclient.openstack.common.apiclient import client - - -def assert_has_keys(dct, required=None, optional=None): - required = required or [] - optional = optional or [] - for k in required: - try: - assert k in dct - except AssertionError: - extra_keys = set(dct.keys()).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class TestResponse(requests.Response): - """Wrap requests.Response and provide a convenient initialization. - """ - - def __init__(self, data): - super(TestResponse, self).__init__() - self._content_consumed = True - if isinstance(data, dict): - self.status_code = data.get('status_code', 200) - # Fake the text attribute to streamline Response creation - text = data.get('text', "") - if isinstance(text, (dict, list)): - self._content = json.dumps(text) - default_headers = { - "Content-Type": "application/json", - } - else: - self._content = text - default_headers = {} - if six.PY3 and isinstance(self._content, six.string_types): - self._content = self._content.encode('utf-8', 'strict') - self.headers = data.get('headers') or default_headers - else: - self.status_code = data - - def __eq__(self, other): - return (self.status_code == other.status_code and - self.headers == other.headers and - self._content == other._content) - - -class FakeHTTPClient(client.HTTPClient): - - def __init__(self, *args, **kwargs): - self.callstack = [] - self.fixtures = kwargs.pop("fixtures", None) or {} - if not args and "auth_plugin" not in kwargs: - args = (None, ) - super(FakeHTTPClient, self).__init__(*args, **kwargs) - - def assert_called(self, method, url, body=None, pos=-1): - """Assert than an API method was just called. - """ - expected = (method, url) - called = self.callstack[pos][0:2] - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - assert expected == called, 'Expected %s %s; got %s %s' % \ - (expected + called) - - if body is not None: - if self.callstack[pos][3] != body: - raise AssertionError('%r != %r' % - (self.callstack[pos][3], body)) - - def assert_called_anytime(self, method, url, body=None): - """Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - found = False - entry = None - for entry in self.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s %s; got %s' % \ - (method, url, self.callstack) - if body is not None: - assert entry[3] == body, "%s != %s" % (entry[3], body) - - self.callstack = [] - - def clear_callstack(self): - self.callstack = [] - - def authenticate(self): - pass - - def client_request(self, client, method, url, **kwargs): - # Check that certain things are called correctly - if method in ["GET", "DELETE"]: - assert "json" not in kwargs - - # Note the call - self.callstack.append( - (method, - url, - kwargs.get("headers") or {}, - kwargs.get("json") or kwargs.get("data"))) - try: - fixture = self.fixtures[url][method] - except KeyError: - pass - else: - return TestResponse({"headers": fixture[0], - "text": fixture[1]}) - - # Call the method - args = parse.parse_qsl(parse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - resp = getattr(self, callback)(**kwargs) - if len(resp) == 3: - status, headers, body = resp - else: - status, body = resp - headers = {} - self.last_request_id = headers.get('x-openstack-request-id', - 'req-test') - return TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/utils.py b/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/utils.py deleted file mode 100644 index 6aa2975aa5..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/apiclient/utils.py +++ /dev/null @@ -1,87 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.utils import encodeutils -import six - -from keystoneclient.openstack.common._i18n import _ -from keystoneclient.openstack.common.apiclient import exceptions -from keystoneclient.openstack.common import uuidutils - - -def find_resource(manager, name_or_id, **find_args): - """Look for resource in a given manager. - - Used as a helper for the _find_* methods. - Example: - - .. code-block:: python - - def _find_hypervisor(cs, hypervisor): - #Get a hypervisor by name or ID. - return cliutils.find_resource(cs.hypervisors, hypervisor) - """ - # first try to get entity as integer id - try: - return manager.get(int(name_or_id)) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # now try to get entity as uuid - try: - if six.PY2: - tmp_id = encodeutils.safe_encode(name_or_id) - else: - tmp_id = encodeutils.safe_decode(name_or_id) - - if uuidutils.is_uuid_like(tmp_id): - return manager.get(tmp_id) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # for str id which is not uuid - if getattr(manager, 'is_alphanum_id_allowed', False): - try: - return manager.get(name_or_id) - except exceptions.NotFound: - pass - - try: - try: - return manager.find(human_id=name_or_id, **find_args) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - resource = getattr(manager, 'resource_class', None) - name_attr = resource.NAME_ATTR if resource else 'name' - kwargs = {name_attr: name_or_id} - kwargs.update(find_args) - return manager.find(**kwargs) - except exceptions.NotFound: - msg = _("No %(name)s with a name or " - "ID of '%(name_or_id)s' exists.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = _("Multiple %(name)s matches found for " - "'%(name_or_id)s', use an ID to be more specific.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/memorycache.py b/awx/lib/site-packages/keystoneclient/openstack/common/memorycache.py deleted file mode 100644 index 4826865a20..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/memorycache.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Super simple fake memcache client.""" - -from oslo.config import cfg -from oslo.utils import timeutils - -memcache_opts = [ - cfg.ListOpt('memcached_servers', - help='Memcached servers or None for in process cache.'), -] - -CONF = cfg.CONF -CONF.register_opts(memcache_opts) - - -def get_client(memcached_servers=None): - client_cls = Client - - if not memcached_servers: - memcached_servers = CONF.memcached_servers - if memcached_servers: - import memcache - client_cls = memcache.Client - - return client_cls(memcached_servers, debug=0) - - -class Client(object): - """Replicates a tiny subset of memcached client interface.""" - - def __init__(self, *args, **kwargs): - """Ignores the passed in args.""" - self.cache = {} - - def get(self, key): - """Retrieves the value for a key or None. - - This expunges expired keys during each get. - """ - - now = timeutils.utcnow_ts() - for k in list(self.cache): - (timeout, _value) = self.cache[k] - if timeout and now >= timeout: - del self.cache[k] - - return self.cache.get(key, (0, None))[1] - - def set(self, key, value, time=0, min_compress_len=0): - """Sets the value for a key.""" - timeout = 0 - if time != 0: - timeout = timeutils.utcnow_ts() + time - self.cache[key] = (timeout, value) - return True - - def add(self, key, value, time=0, min_compress_len=0): - """Sets the value for a key if it doesn't exist.""" - if self.get(key) is not None: - return False - return self.set(key, value, time, min_compress_len) - - def incr(self, key, delta=1): - """Increments the value for a key.""" - value = self.get(key) - if value is None: - return None - new_value = int(value) + delta - self.cache[key] = (self.cache[key][0], str(new_value)) - return new_value - - def delete(self, key, time=0): - """Deletes the value associated with a key.""" - if key in self.cache: - del self.cache[key] diff --git a/awx/lib/site-packages/keystoneclient/openstack/common/uuidutils.py b/awx/lib/site-packages/keystoneclient/openstack/common/uuidutils.py deleted file mode 100644 index 234b880c99..0000000000 --- a/awx/lib/site-packages/keystoneclient/openstack/common/uuidutils.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2012 Intel Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -UUID related utilities and helper functions. -""" - -import uuid - - -def generate_uuid(): - return str(uuid.uuid4()) - - -def is_uuid_like(val): - """Returns validation of a value as a UUID. - - For our purposes, a UUID is a canonical form string: - aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa - - """ - try: - return str(uuid.UUID(val)) == val - except (TypeError, ValueError, AttributeError): - return False diff --git a/awx/lib/site-packages/keystoneclient/service_catalog.py b/awx/lib/site-packages/keystoneclient/service_catalog.py deleted file mode 100644 index 143a6b7c6e..0000000000 --- a/awx/lib/site-packages/keystoneclient/service_catalog.py +++ /dev/null @@ -1,387 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011, Piston Cloud Computing, Inc. -# Copyright 2011 Nebula, Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import abc - -import six - -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import utils - - -@six.add_metaclass(abc.ABCMeta) -class ServiceCatalog(object): - """Helper methods for dealing with a Keystone Service Catalog.""" - - @classmethod - def factory(cls, resource_dict, token=None, region_name=None): - """Create ServiceCatalog object given an auth token.""" - if ServiceCatalogV3.is_valid(resource_dict): - return ServiceCatalogV3(token, resource_dict, region_name) - elif ServiceCatalogV2.is_valid(resource_dict): - return ServiceCatalogV2(resource_dict, region_name) - else: - raise NotImplementedError(_('Unrecognized auth response')) - - def __init__(self, region_name=None): - self._region_name = region_name - - @property - def region_name(self): - # FIXME(jamielennox): Having region_name set on the service catalog - # directly is deprecated. It should instead be provided as a parameter - # to calls made to the service_catalog. Provide appropriate warning. - return self._region_name - - def _get_endpoint_region(self, endpoint): - return endpoint.get('region_id') or endpoint.get('region') - - @abc.abstractmethod - def get_token(self): - """Fetch token details from service catalog. - - Returns a dictionary containing the following:: - - - `id`: Token's ID - - `expires`: Token's expiration - - `user_id`: Authenticated user's ID - - `tenant_id`: Authorized project's ID - - `domain_id`: Authorized domain's ID - - """ - raise NotImplementedError() - - @abc.abstractmethod - def _is_endpoint_type_match(self, endpoint, endpoint_type): - """Helper function to normalize endpoint matching across v2 and v3. - - :returns: True if the provided endpoint matches the required - endpoint_type otherwise False. - """ - - @abc.abstractmethod - def _normalize_endpoint_type(self, endpoint_type): - """Handle differences in the way v2 and v3 catalogs specify endpoint. - - Both v2 and v3 must be able to handle the endpoint style of the other. - For example v2 must be able to handle a 'public' endpoint_type and - v3 must be able to handle a 'publicURL' endpoint_type. - - :returns: the endpoint string in the format appropriate for this - service catalog. - """ - - def get_endpoints(self, service_type=None, endpoint_type=None, - region_name=None, service_name=None): - """Fetch and filter endpoints for the specified service(s). - - Returns endpoints for the specified service (or all) containing - the specified type (or all) and region (or all) and service name. - - If there is no name in the service catalog the service_name check will - be skipped. This allows compatibility with services that existed - before the name was available in the catalog. - """ - endpoint_type = self._normalize_endpoint_type(endpoint_type) - region_name = region_name or self._region_name - - sc = {} - - for service in (self.get_data() or []): - try: - st = service['type'] - except KeyError: - continue - - if service_type and service_type != st: - continue - - # NOTE(jamielennox): service_name is different. It is not available - # in API < v3.3. If it is in the catalog then we enforce it, if it - # is not then we don't because the name could be correct we just - # don't have that information to check against. - if service_name: - try: - sn = service['name'] - except KeyError: - # assume that we're in v3.0-v3.2 and don't have the name in - # the catalog. Skip the check. - pass - else: - if service_name != sn: - continue - - endpoints = sc.setdefault(st, []) - - for endpoint in service.get('endpoints', []): - if (endpoint_type and not - self._is_endpoint_type_match(endpoint, endpoint_type)): - continue - if (region_name and - region_name != self._get_endpoint_region(endpoint)): - continue - endpoints.append(endpoint) - - return sc - - def _get_service_endpoints(self, attr, filter_value, service_type, - endpoint_type, region_name, service_name): - """Fetch the endpoints of a particular service_type and handle - the filtering. - """ - sc_endpoints = self.get_endpoints(service_type=service_type, - endpoint_type=endpoint_type, - region_name=region_name, - service_name=service_name) - - try: - endpoints = sc_endpoints[service_type] - except KeyError: - return - - # TODO(jamielennox): at least swiftclient is known to set attr and not - # filter_value and expects that to mean that filtering is ignored, so - # we can't check for the presence of attr. This behaviour should be - # deprecated and an appropriate warning provided. - if filter_value: - return [endpoint for endpoint in endpoints - if endpoint.get(attr) == filter_value] - - return endpoints - - @abc.abstractmethod - @utils.positional(enforcement=utils.positional.WARN) - def get_urls(self, attr=None, filter_value=None, - service_type='identity', endpoint_type='publicURL', - region_name=None, service_name=None): - """Fetch endpoint urls from the service catalog. - - Fetch the endpoints from the service catalog for a particular - endpoint attribute. If no attribute is given, return the first - endpoint of the specified type. - - :param string attr: Endpoint attribute name. - :param string filter_value: Endpoint attribute value. - :param string service_type: Service type of the endpoint. - :param string endpoint_type: Type of endpoint. - Possible values: public or publicURL, - internal or internalURL, admin or - adminURL - :param string region_name: Region of the endpoint. - :param string service_name: The assigned name of the service. - - :returns: tuple of urls or None (if no match found) - """ - raise NotImplementedError() - - @utils.positional(3, enforcement=utils.positional.WARN) - def url_for(self, attr=None, filter_value=None, - service_type='identity', endpoint_type='publicURL', - region_name=None, service_name=None): - """Fetch an endpoint from the service catalog. - - Fetch the specified endpoint from the service catalog for - a particular endpoint attribute. If no attribute is given, return - the first endpoint of the specified type. - - Valid endpoint types: `public` or `publicURL`, - `internal` or `internalURL`, - `admin` or 'adminURL` - - :param string attr: Endpoint attribute name. - :param string filter_value: Endpoint attribute value. - :param string service_type: Service type of the endpoint. - :param string endpoint_type: Type of endpoint. - :param string region_name: Region of the endpoint. - :param string service_name: The assigned name of the service. - - """ - if not self.get_data(): - raise exceptions.EmptyCatalog(_('The service catalog is empty.')) - - urls = self.get_urls(attr=attr, - filter_value=filter_value, - service_type=service_type, - endpoint_type=endpoint_type, - region_name=region_name, - service_name=service_name) - - try: - return urls[0] - except Exception: - pass - - if service_name and region_name: - msg = (_('%(endpoint_type)s endpoint for %(service_type)s service ' - 'named %(service_name)s in %(region_name)s region not ' - 'found') % - {'endpoint_type': endpoint_type, - 'service_type': service_type, 'service_name': service_name, - 'region_name': region_name}) - elif service_name: - msg = (_('%(endpoint_type)s endpoint for %(service_type)s service ' - 'named %(service_name)s not found') % - {'endpoint_type': endpoint_type, - 'service_type': service_type, - 'service_name': service_name}) - elif region_name: - msg = (_('%(endpoint_type)s endpoint for %(service_type)s service ' - 'in %(region_name)s region not found') % - {'endpoint_type': endpoint_type, - 'service_type': service_type, 'region_name': region_name}) - else: - msg = (_('%(endpoint_type)s endpoint for %(service_type)s service ' - 'not found') % - {'endpoint_type': endpoint_type, - 'service_type': service_type}) - - raise exceptions.EndpointNotFound(msg) - - @abc.abstractmethod - def get_data(self): - """Get the raw catalog structure. - - Get the version dependent catalog structure as it is presented within - the resource. - - :returns: list containing raw catalog data entries or None - """ - raise NotImplementedError() - - -class ServiceCatalogV2(ServiceCatalog): - """An object for encapsulating the service catalog using raw v2 auth token - from Keystone. - """ - - def __init__(self, resource_dict, region_name=None): - self.catalog = resource_dict - super(ServiceCatalogV2, self).__init__(region_name=region_name) - - @classmethod - def is_valid(cls, resource_dict): - # This class is also used for reading token info of an unscoped token. - # Unscoped token does not have 'serviceCatalog' in V2, checking this - # will not work. Use 'token' attribute instead. - return 'token' in resource_dict - - def _normalize_endpoint_type(self, endpoint_type): - if endpoint_type and 'URL' not in endpoint_type: - endpoint_type = endpoint_type + 'URL' - - return endpoint_type - - def _is_endpoint_type_match(self, endpoint, endpoint_type): - return endpoint_type in endpoint - - def get_data(self): - return self.catalog.get('serviceCatalog') - - def get_token(self): - token = {'id': self.catalog['token']['id'], - 'expires': self.catalog['token']['expires']} - try: - token['user_id'] = self.catalog['user']['id'] - token['tenant_id'] = self.catalog['token']['tenant']['id'] - except Exception: - # just leave the tenant and user out if it doesn't exist - pass - return token - - @utils.positional(enforcement=utils.positional.WARN) - def get_urls(self, attr=None, filter_value=None, - service_type='identity', endpoint_type='publicURL', - region_name=None, service_name=None): - endpoint_type = self._normalize_endpoint_type(endpoint_type) - endpoints = self._get_service_endpoints(attr=attr, - filter_value=filter_value, - service_type=service_type, - endpoint_type=endpoint_type, - region_name=region_name, - service_name=service_name) - - if endpoints: - return tuple([endpoint[endpoint_type] for endpoint in endpoints]) - else: - return None - - -class ServiceCatalogV3(ServiceCatalog): - """An object for encapsulating the service catalog using raw v3 auth token - from Keystone. - """ - - def __init__(self, token, resource_dict, region_name=None): - super(ServiceCatalogV3, self).__init__(region_name=region_name) - self._auth_token = token - self.catalog = resource_dict - - @classmethod - def is_valid(cls, resource_dict): - # This class is also used for reading token info of an unscoped token. - # Unscoped token does not have 'catalog', checking this - # will not work. Use 'methods' attribute instead. - return 'methods' in resource_dict - - def _normalize_endpoint_type(self, endpoint_type): - if endpoint_type: - endpoint_type = endpoint_type.rstrip('URL') - - return endpoint_type - - def _is_endpoint_type_match(self, endpoint, endpoint_type): - try: - return endpoint_type == endpoint['interface'] - except KeyError: - return False - - def get_data(self): - return self.catalog.get('catalog') - - def get_token(self): - token = {'id': self._auth_token, - 'expires': self.catalog['expires_at']} - try: - token['user_id'] = self.catalog['user']['id'] - domain = self.catalog.get('domain') - if domain: - token['domain_id'] = domain['id'] - project = self.catalog.get('project') - if project: - token['tenant_id'] = project['id'] - except Exception: - # just leave the domain, project and user out if it doesn't exist - pass - return token - - @utils.positional(enforcement=utils.positional.WARN) - def get_urls(self, attr=None, filter_value=None, - service_type='identity', endpoint_type='public', - region_name=None, service_name=None): - endpoints = self._get_service_endpoints(attr=attr, - filter_value=filter_value, - service_type=service_type, - endpoint_type=endpoint_type, - region_name=region_name, - service_name=service_name) - - if endpoints: - return tuple([endpoint['url'] for endpoint in endpoints]) - else: - return None diff --git a/awx/lib/site-packages/keystoneclient/session.py b/awx/lib/site-packages/keystoneclient/session.py deleted file mode 100644 index f9da97d968..0000000000 --- a/awx/lib/site-packages/keystoneclient/session.py +++ /dev/null @@ -1,854 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import functools -import hashlib -import logging -import os -import socket -import time - -from oslo_config import cfg -from oslo_serialization import jsonutils -from oslo_utils import importutils -import requests -import six -from six.moves import urllib - -from keystoneclient import exceptions -from keystoneclient.i18n import _, _LI, _LW -from keystoneclient import utils - -osprofiler_web = importutils.try_import("osprofiler.web") - -USER_AGENT = 'python-keystoneclient' - -_logger = logging.getLogger(__name__) - - -def _positive_non_zero_float(argument_value): - if argument_value is None: - return None - try: - value = float(argument_value) - except ValueError: - msg = _("%s must be a float") % argument_value - raise argparse.ArgumentTypeError(msg) - if value <= 0: - msg = _("%s must be greater than 0") % argument_value - raise argparse.ArgumentTypeError(msg) - return value - - -def request(url, method='GET', **kwargs): - return Session().request(url, method=method, **kwargs) - - -def _remove_service_catalog(body): - try: - data = jsonutils.loads(body) - - # V3 token - if 'token' in data and 'catalog' in data['token']: - data['token']['catalog'] = '<removed>' - return jsonutils.dumps(data) - - # V2 token - if 'serviceCatalog' in data['access']: - data['access']['serviceCatalog'] = '<removed>' - return jsonutils.dumps(data) - - except Exception: - # Don't fail trying to clean up the request body. - pass - return body - - -class Session(object): - """Maintains client communication state and common functionality. - - As much as possible the parameters to this class reflect and are passed - directly to the requests library. - - :param auth: An authentication plugin to authenticate the session with. - (optional, defaults to None) - :type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin` - :param requests.Session session: A requests session object that can be used - for issuing requests. (optional) - :param string original_ip: The original IP of the requesting user which - will be sent to identity service in a - 'Forwarded' header. (optional) - :param verify: The verification arguments to pass to requests. These are of - the same form as requests expects, so True or False to - verify (or not) against system certificates or a path to a - bundle or CA certs to check against or None for requests to - attempt to locate and use certificates. (optional, defaults - to True) - :param cert: A client certificate to pass to requests. These are of the - same form as requests expects. Either a single filename - containing both the certificate and key or a tuple containing - the path to the certificate then a path to the key. (optional) - :param float timeout: A timeout to pass to requests. This should be a - numerical value indicating some amount (or fraction) - of seconds or 0 for no timeout. (optional, defaults - to 0) - :param string user_agent: A User-Agent header string to use for the - request. If not provided a default is used. - (optional, defaults to 'python-keystoneclient') - :param int/bool redirect: Controls the maximum number of redirections that - can be followed by a request. Either an integer - for a specific count or True/False for - forever/never. (optional, default to 30) - """ - - user_agent = None - - _REDIRECT_STATUSES = (301, 302, 303, 305, 307) - - REDIRECT_STATUSES = _REDIRECT_STATUSES - """This property is deprecated.""" - - _DEFAULT_REDIRECT_LIMIT = 30 - - DEFAULT_REDIRECT_LIMIT = _DEFAULT_REDIRECT_LIMIT - """This property is deprecated.""" - - @utils.positional(2, enforcement=utils.positional.WARN) - def __init__(self, auth=None, session=None, original_ip=None, verify=True, - cert=None, timeout=None, user_agent=None, - redirect=_DEFAULT_REDIRECT_LIMIT): - if not session: - session = requests.Session() - # Use TCPKeepAliveAdapter to fix bug 1323862 - for scheme in session.adapters.keys(): - session.mount(scheme, TCPKeepAliveAdapter()) - - self.auth = auth - self.session = session - self.original_ip = original_ip - self.verify = verify - self.cert = cert - self.timeout = None - self.redirect = redirect - - if timeout is not None: - self.timeout = float(timeout) - - # don't override the class variable if none provided - if user_agent is not None: - self.user_agent = user_agent - - @classmethod - def process_header(cls, header): - """Redacts the secure headers to be logged.""" - secure_headers = ('authorization', 'x-auth-token', - 'x-subject-token',) - if header[0].lower() in secure_headers: - token_hasher = hashlib.sha1() - token_hasher.update(header[1].encode('utf-8')) - token_hash = token_hasher.hexdigest() - return (header[0], '{SHA1}%s' % token_hash) - return header - - @utils.positional() - def _http_log_request(self, url, method=None, data=None, - json=None, headers=None, logger=_logger): - if not logger.isEnabledFor(logging.DEBUG): - # NOTE(morganfainberg): This whole debug section is expensive, - # there is no need to do the work if we're not going to emit a - # debug log. - return - - string_parts = ['REQ: curl -g -i'] - - # NOTE(jamielennox): None means let requests do its default validation - # so we need to actually check that this is False. - if self.verify is False: - string_parts.append('--insecure') - elif isinstance(self.verify, six.string_types): - string_parts.append('--cacert "%s"' % self.verify) - - if method: - string_parts.extend(['-X', method]) - - string_parts.append(url) - - if headers: - for header in six.iteritems(headers): - string_parts.append('-H "%s: %s"' - % Session.process_header(header)) - if json: - data = jsonutils.dumps(json) - if data: - string_parts.append("-d '%s'" % data) - - logger.debug(' '.join(string_parts)) - - @utils.positional() - def _http_log_response(self, response=None, json=None, - status_code=None, headers=None, text=None, - logger=_logger): - if not logger.isEnabledFor(logging.DEBUG): - return - - if response: - if not status_code: - status_code = response.status_code - if not headers: - headers = response.headers - if not text: - text = _remove_service_catalog(response.text) - if json: - text = jsonutils.dumps(json) - - string_parts = ['RESP:'] - - if status_code: - string_parts.append('[%s]' % status_code) - if headers: - for header in six.iteritems(headers): - string_parts.append('%s: %s' % Session.process_header(header)) - if text: - string_parts.append('\nRESP BODY: %s\n' % text) - - logger.debug(' '.join(string_parts)) - - @utils.positional(enforcement=utils.positional.WARN) - def request(self, url, method, json=None, original_ip=None, - user_agent=None, redirect=None, authenticated=None, - endpoint_filter=None, auth=None, requests_auth=None, - raise_exc=True, allow_reauth=True, log=True, - endpoint_override=None, connect_retries=0, logger=_logger, - **kwargs): - """Send an HTTP request with the specified characteristics. - - Wrapper around `requests.Session.request` to handle tasks such as - setting headers, JSON encoding/decoding, and error handling. - - Arguments that are not handled are passed through to the requests - library. - - :param string url: Path or fully qualified URL of HTTP request. If only - a path is provided then endpoint_filter must also be - provided such that the base URL can be determined. - If a fully qualified URL is provided then - endpoint_filter will be ignored. - :param string method: The http method to use. (e.g. 'GET', 'POST') - :param string original_ip: Mark this request as forwarded for this ip. - (optional) - :param dict headers: Headers to be included in the request. (optional) - :param json: Some data to be represented as JSON. (optional) - :param string user_agent: A user_agent to use for the request. If - present will override one present in headers. - (optional) - :param int/bool redirect: the maximum number of redirections that - can be followed by a request. Either an - integer for a specific count or True/False - for forever/never. (optional) - :param int connect_retries: the maximum number of retries that should - be attempted for connection errors. - (optional, defaults to 0 - never retry). - :param bool authenticated: True if a token should be attached to this - request, False if not or None for attach if - an auth_plugin is available. - (optional, defaults to None) - :param dict endpoint_filter: Data to be provided to an auth plugin with - which it should be able to determine an - endpoint to use for this request. If not - provided then URL is expected to be a - fully qualified URL. (optional) - :param str endpoint_override: The URL to use instead of looking up the - endpoint in the auth plugin. This will be - ignored if a fully qualified URL is - provided but take priority over an - endpoint_filter. (optional) - :param auth: The auth plugin to use when authenticating this request. - This will override the plugin that is attached to the - session (if any). (optional) - :type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin` - :param requests_auth: A requests library auth plugin that cannot be - passed via kwarg because the `auth` kwarg - collides with our own auth plugins. (optional) - :type requests_auth: :py:class:`requests.auth.AuthBase` - :param bool raise_exc: If True then raise an appropriate exception for - failed HTTP requests. If False then return the - request object. (optional, default True) - :param bool allow_reauth: Allow fetching a new token and retrying the - request on receiving a 401 Unauthorized - response. (optional, default True) - :param bool log: If True then log the request and response data to the - debug log. (optional, default True) - :param logger: The logger object to use to log request and responses. - If not provided the keystoneclient.session default - logger will be used. - :type logger: logging.Logger - :param kwargs: any other parameter that can be passed to - requests.Session.request (such as `headers`). Except: - 'data' will be overwritten by the data in 'json' param. - 'allow_redirects' is ignored as redirects are handled - by the session. - - :raises keystoneclient.exceptions.ClientException: For connection - failure, or to indicate an error response code. - - :returns: The response to the request. - """ - - headers = kwargs.setdefault('headers', dict()) - - if authenticated is None: - authenticated = bool(auth or self.auth) - - if authenticated: - auth_headers = self.get_auth_headers(auth) - - if auth_headers is None: - msg = _('No valid authentication is available') - raise exceptions.AuthorizationFailure(msg) - - headers.update(auth_headers) - - if osprofiler_web: - headers.update(osprofiler_web.get_trace_id_headers()) - - # if we are passed a fully qualified URL and an endpoint_filter we - # should ignore the filter. This will make it easier for clients who - # want to overrule the default endpoint_filter data added to all client - # requests. We check fully qualified here by the presence of a host. - if not urllib.parse.urlparse(url).netloc: - base_url = None - - if endpoint_override: - base_url = endpoint_override - elif endpoint_filter: - base_url = self.get_endpoint(auth, **endpoint_filter) - - if not base_url: - raise exceptions.EndpointNotFound() - - url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/')) - - if self.cert: - kwargs.setdefault('cert', self.cert) - - if self.timeout is not None: - kwargs.setdefault('timeout', self.timeout) - - if user_agent: - headers['User-Agent'] = user_agent - elif self.user_agent: - user_agent = headers.setdefault('User-Agent', self.user_agent) - else: - user_agent = headers.setdefault('User-Agent', USER_AGENT) - - if self.original_ip: - headers.setdefault('Forwarded', - 'for=%s;by=%s' % (self.original_ip, user_agent)) - - if json is not None: - headers['Content-Type'] = 'application/json' - kwargs['data'] = jsonutils.dumps(json) - - kwargs.setdefault('verify', self.verify) - - if requests_auth: - kwargs['auth'] = requests_auth - - if log: - self._http_log_request(url, method=method, - data=kwargs.get('data'), - headers=headers, - logger=logger) - - # Force disable requests redirect handling. We will manage this below. - kwargs['allow_redirects'] = False - - if redirect is None: - redirect = self.redirect - - send = functools.partial(self._send_request, - url, method, redirect, log, logger, - connect_retries) - resp = send(**kwargs) - - # handle getting a 401 Unauthorized response by invalidating the plugin - # and then retrying the request. This is only tried once. - if resp.status_code == 401 and authenticated and allow_reauth: - if self.invalidate(auth): - auth_headers = self.get_auth_headers(auth) - - if auth_headers is not None: - headers.update(auth_headers) - resp = send(**kwargs) - - if raise_exc and resp.status_code >= 400: - logger.debug('Request returned failure status: %s', - resp.status_code) - raise exceptions.from_response(resp, method, url) - - return resp - - def _send_request(self, url, method, redirect, log, logger, - connect_retries, connect_retry_delay=0.5, **kwargs): - # NOTE(jamielennox): We handle redirection manually because the - # requests lib follows some browser patterns where it will redirect - # POSTs as GETs for certain statuses which is not want we want for an - # API. See: https://en.wikipedia.org/wiki/Post/Redirect/Get - - # NOTE(jamielennox): The interaction between retries and redirects are - # handled naively. We will attempt only a maximum number of retries and - # redirects rather than per request limits. Otherwise the extreme case - # could be redirects * retries requests. This will be sufficient in - # most cases and can be fixed properly if there's ever a need. - - try: - try: - resp = self.session.request(method, url, **kwargs) - except requests.exceptions.SSLError as e: - msg = _('SSL exception connecting to %(url)s: ' - '%(error)s') % {'url': url, 'error': e} - raise exceptions.SSLError(msg) - except requests.exceptions.Timeout: - msg = _('Request to %s timed out') % url - raise exceptions.RequestTimeout(msg) - except requests.exceptions.ConnectionError: - msg = _('Unable to establish connection to %s') % url - raise exceptions.ConnectionRefused(msg) - except (exceptions.RequestTimeout, exceptions.ConnectionRefused) as e: - if connect_retries <= 0: - raise - - logger.info(_LI('Failure: %(e)s. Retrying in %(delay).1fs.'), - {'e': e, 'delay': connect_retry_delay}) - time.sleep(connect_retry_delay) - - return self._send_request( - url, method, redirect, log, logger, - connect_retries=connect_retries - 1, - connect_retry_delay=connect_retry_delay * 2, - **kwargs) - - if log: - self._http_log_response(response=resp, logger=logger) - - if resp.status_code in self._REDIRECT_STATUSES: - # be careful here in python True == 1 and False == 0 - if isinstance(redirect, bool): - redirect_allowed = redirect - else: - redirect -= 1 - redirect_allowed = redirect >= 0 - - if not redirect_allowed: - return resp - - try: - location = resp.headers['location'] - except KeyError: - logger.warn(_LW("Failed to redirect request to %s as new " - "location was not provided."), resp.url) - else: - # NOTE(jamielennox): We don't pass through connect_retry_delay. - # This request actually worked so we can reset the delay count. - new_resp = self._send_request( - location, method, redirect, log, logger, - connect_retries=connect_retries, - **kwargs) - - if not isinstance(new_resp.history, list): - new_resp.history = list(new_resp.history) - new_resp.history.insert(0, resp) - resp = new_resp - - return resp - - def head(self, url, **kwargs): - """Perform a HEAD request. - - This calls :py:meth:`.request()` with ``method`` set to ``HEAD``. - - """ - return self.request(url, 'HEAD', **kwargs) - - def get(self, url, **kwargs): - """Perform a GET request. - - This calls :py:meth:`.request()` with ``method`` set to ``GET``. - - """ - return self.request(url, 'GET', **kwargs) - - def post(self, url, **kwargs): - """Perform a POST request. - - This calls :py:meth:`.request()` with ``method`` set to ``POST``. - - """ - return self.request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - """Perform a PUT request. - - This calls :py:meth:`.request()` with ``method`` set to ``PUT``. - - """ - return self.request(url, 'PUT', **kwargs) - - def delete(self, url, **kwargs): - """Perform a DELETE request. - - This calls :py:meth:`.request()` with ``method`` set to ``DELETE``. - - """ - return self.request(url, 'DELETE', **kwargs) - - def patch(self, url, **kwargs): - """Perform a PATCH request. - - This calls :py:meth:`.request()` with ``method`` set to ``PATCH``. - - """ - return self.request(url, 'PATCH', **kwargs) - - @classmethod - def construct(cls, kwargs): - """Handles constructing a session from the older - :py:class:`~keystoneclient.httpclient.HTTPClient` args as well as the - new request-style arguments. - - .. warning:: - *DEPRECATED*: This function is purely for bridging the gap between - older client arguments and the session arguments that they relate - to. It is not intended to be used as a generic Session Factory. - - This function purposefully modifies the input kwargs dictionary so that - the remaining kwargs dict can be reused and passed on to other - functions without session arguments. - - """ - params = {} - - for attr in ('verify', 'cacert', 'cert', 'key', 'insecure', - 'timeout', 'session', 'original_ip', 'user_agent'): - try: - params[attr] = kwargs.pop(attr) - except KeyError: - pass - - return cls._make(**params) - - @classmethod - def _make(cls, insecure=False, verify=None, cacert=None, cert=None, - key=None, **kwargs): - """Create a session with individual certificate parameters. - - Some parameters used to create a session don't lend themselves to be - loaded from config/CLI etc. Create a session by converting those - parameters into session __init__ parameters. - """ - if verify is None: - if insecure: - verify = False - else: - verify = cacert or True - - if cert and key: - # passing cert and key together is deprecated in favour of the - # requests lib form of having the cert and key as a tuple - cert = (cert, key) - - return cls(verify=verify, cert=cert, **kwargs) - - def _auth_required(self, auth, msg): - if not auth: - auth = self.auth - - if not auth: - msg_fmt = _('An auth plugin is required to %s') - raise exceptions.MissingAuthPlugin(msg_fmt % msg) - - return auth - - def get_auth_headers(self, auth=None, **kwargs): - """Return auth headers as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin - on the session. (optional) - :type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin` - - :raises keystoneclient.exceptions.AuthorizationFailure: if a new token - fetch fails. - :raises keystoneclient.exceptions.MissingAuthPlugin: if a plugin is not - available. - - :returns: Authentication headers or None for failure. - :rtype: dict - """ - auth = self._auth_required(auth, 'fetch a token') - return auth.get_headers(self, **kwargs) - - def get_token(self, auth=None): - """Return a token as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin - on the session. (optional) - :type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin` - - :raises keystoneclient.exceptions.AuthorizationFailure: if a new token - fetch fails. - :raises keystoneclient.exceptions.MissingAuthPlugin: if a plugin is not - available. - - *DEPRECATED*: This assumes that the only header that is used to - authenticate a message is 'X-Auth-Token'. This may not be - correct. Use get_auth_headers instead. - - :returns: A valid token. - :rtype: string - """ - return (self.get_auth_headers(auth) or {}).get('X-Auth-Token') - - def get_endpoint(self, auth=None, **kwargs): - """Get an endpoint as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin on - the session. (optional) - :type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin` - - :raises keystoneclient.exceptions.MissingAuthPlugin: if a plugin is not - available. - - :returns: An endpoint if available or None. - :rtype: string - """ - auth = self._auth_required(auth, 'determine endpoint URL') - return auth.get_endpoint(self, **kwargs) - - def invalidate(self, auth=None): - """Invalidate an authentication plugin. - - :param auth: The auth plugin to invalidate. Overrides the plugin on the - session. (optional) - :type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin` - - """ - auth = self._auth_required(auth, 'validate') - return auth.invalidate() - - def get_user_id(self, auth=None): - """Return the authenticated user_id as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin - on the session. (optional) - :type auth: keystoneclient.auth.base.BaseAuthPlugin - - :raises keystoneclient.exceptions.AuthorizationFailure: - if a new token fetch fails. - :raises keystoneclient.exceptions.MissingAuthPlugin: - if a plugin is not available. - - :returns string: Current user_id or None if not supported by plugin. - """ - auth = self._auth_required(auth, 'get user_id') - return auth.get_user_id(self) - - def get_project_id(self, auth=None): - """Return the authenticated project_id as provided by the auth plugin. - - :param auth: The auth plugin to use for token. Overrides the plugin - on the session. (optional) - :type auth: keystoneclient.auth.base.BaseAuthPlugin - - :raises keystoneclient.exceptions.AuthorizationFailure: - if a new token fetch fails. - :raises keystoneclient.exceptions.MissingAuthPlugin: - if a plugin is not available. - - :returns string: Current project_id or None if not supported by plugin. - """ - auth = self._auth_required(auth, 'get project_id') - return auth.get_project_id(self) - - @utils.positional.classmethod() - def get_conf_options(cls, deprecated_opts=None): - """Get the oslo_config options that are needed for a - :py:class:`.Session`. - - These may be useful without being registered for config file generation - or to manipulate the options before registering them yourself. - - The options that are set are: - :cafile: The certificate authority filename. - :certfile: The client certificate file to present. - :keyfile: The key for the client certificate. - :insecure: Whether to ignore SSL verification. - :timeout: The max time to wait for HTTP connections. - - :param dict deprecated_opts: Deprecated options that should be included - in the definition of new options. This should be a dict from the - name of the new option to a list of oslo.DeprecatedOpts that - correspond to the new option. (optional) - - For example, to support the ``ca_file`` option pointing to the new - ``cafile`` option name:: - - old_opt = oslo.cfg.DeprecatedOpt('ca_file', 'old_group') - deprecated_opts={'cafile': [old_opt]} - - :returns: A list of oslo_config options. - """ - if deprecated_opts is None: - deprecated_opts = {} - - return [cfg.StrOpt('cafile', - deprecated_opts=deprecated_opts.get('cafile'), - help='PEM encoded Certificate Authority to use ' - 'when verifying HTTPs connections.'), - cfg.StrOpt('certfile', - deprecated_opts=deprecated_opts.get('certfile'), - help='PEM encoded client certificate cert file'), - cfg.StrOpt('keyfile', - deprecated_opts=deprecated_opts.get('keyfile'), - help='PEM encoded client certificate key file'), - cfg.BoolOpt('insecure', - default=False, - deprecated_opts=deprecated_opts.get('insecure'), - help='Verify HTTPS connections.'), - cfg.IntOpt('timeout', - deprecated_opts=deprecated_opts.get('timeout'), - help='Timeout value for http requests'), - ] - - @utils.positional.classmethod() - def register_conf_options(cls, conf, group, deprecated_opts=None): - """Register the oslo_config options that are needed for a session. - - The options that are set are: - :cafile: The certificate authority filename. - :certfile: The client certificate file to present. - :keyfile: The key for the client certificate. - :insecure: Whether to ignore SSL verification. - :timeout: The max time to wait for HTTP connections. - - :param oslo_config.Cfg conf: config object to register with. - :param string group: The ini group to register options in. - :param dict deprecated_opts: Deprecated options that should be included - in the definition of new options. This should be a dict from the - name of the new option to a list of oslo.DeprecatedOpts that - correspond to the new option. (optional) - - For example, to support the ``ca_file`` option pointing to the new - ``cafile`` option name:: - - old_opt = oslo.cfg.DeprecatedOpt('ca_file', 'old_group') - deprecated_opts={'cafile': [old_opt]} - - :returns: The list of options that was registered. - """ - opts = cls.get_conf_options(deprecated_opts=deprecated_opts) - conf.register_group(cfg.OptGroup(group)) - conf.register_opts(opts, group=group) - return opts - - @classmethod - def load_from_conf_options(cls, conf, group, **kwargs): - """Create a session object from an oslo_config object. - - The options must have been previously registered with - register_conf_options. - - :param oslo_config.Cfg conf: config object to register with. - :param string group: The ini group to register options in. - :param dict kwargs: Additional parameters to pass to session - construction. - :returns: A new session object. - :rtype: :py:class:`.Session` - """ - c = conf[group] - - kwargs['insecure'] = c.insecure - kwargs['cacert'] = c.cafile - kwargs['cert'] = c.certfile - kwargs['key'] = c.keyfile - kwargs['timeout'] = c.timeout - - return cls._make(**kwargs) - - @staticmethod - def register_cli_options(parser): - """Register the argparse arguments that are needed for a session. - - :param argparse.ArgumentParser parser: parser to add to. - """ - parser.add_argument('--insecure', - default=False, - action='store_true', - help='Explicitly allow client to perform ' - '"insecure" TLS (https) requests. The ' - 'server\'s certificate will not be verified ' - 'against any certificate authorities. This ' - 'option should be used with caution.') - - parser.add_argument('--os-cacert', - metavar='<ca-certificate>', - default=os.environ.get('OS_CACERT'), - help='Specify a CA bundle file to use in ' - 'verifying a TLS (https) server certificate. ' - 'Defaults to env[OS_CACERT].') - - parser.add_argument('--os-cert', - metavar='<certificate>', - default=os.environ.get('OS_CERT'), - help='Defaults to env[OS_CERT].') - - parser.add_argument('--os-key', - metavar='<key>', - default=os.environ.get('OS_KEY'), - help='Defaults to env[OS_KEY].') - - parser.add_argument('--timeout', - default=600, - type=_positive_non_zero_float, - metavar='<seconds>', - help='Set request timeout (in seconds).') - - @classmethod - def load_from_cli_options(cls, args, **kwargs): - """Create a :py:class:`.Session` object from CLI arguments. - - The CLI arguments must have been registered with - :py:meth:`.register_cli_options`. - - :param Namespace args: result of parsed arguments. - - :returns: A new session object. - :rtype: :py:class:`.Session` - """ - kwargs['insecure'] = args.insecure - kwargs['cacert'] = args.os_cacert - kwargs['cert'] = args.os_cert - kwargs['key'] = args.os_key - kwargs['timeout'] = args.timeout - - return cls._make(**kwargs) - - -class TCPKeepAliveAdapter(requests.adapters.HTTPAdapter): - """The custom adapter used to set TCP Keep-Alive on all connections.""" - def init_poolmanager(self, *args, **kwargs): - if requests.__version__ >= '2.4.1': - kwargs.setdefault('socket_options', [ - (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1), - (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), - ]) - super(TCPKeepAliveAdapter, self).init_poolmanager(*args, **kwargs) diff --git a/awx/lib/site-packages/keystoneclient/shell.py b/awx/lib/site-packages/keystoneclient/shell.py deleted file mode 100644 index 1221e57a04..0000000000 --- a/awx/lib/site-packages/keystoneclient/shell.py +++ /dev/null @@ -1,478 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Command-line interface to the OpenStack Identity API.""" - -from __future__ import print_function - -import argparse -import getpass -import logging -import os -import sys -import warnings - -from oslo_utils import encodeutils -import six - -import keystoneclient -from keystoneclient import access -from keystoneclient.contrib.bootstrap import shell as shell_bootstrap -from keystoneclient import exceptions as exc -from keystoneclient.generic import shell as shell_generic -from keystoneclient import session -from keystoneclient import utils -from keystoneclient.v2_0 import shell as shell_v2_0 - - -def env(*vars, **kwargs): - """Search for the first defined of possibly many env vars - - Returns the first environment variable defined in vars, or - returns the default defined in kwargs. - - """ - for v in vars: - value = os.environ.get(v) - if value: - return value - return kwargs.get('default', '') - - -class OpenStackIdentityShell(object): - - def __init__(self, parser_class=argparse.ArgumentParser): - - # Since Python 2.7, DeprecationWarning is ignored by default, enable - # it so that the deprecation message is displayed. - warnings.simplefilter('once', category=DeprecationWarning) - warnings.warn( - 'The keystone CLI is deprecated in favor of ' - 'python-openstackclient. For a Python library, continue using ' - 'python-keystoneclient.', DeprecationWarning) - # And back to normal! - warnings.resetwarnings() - self.parser_class = parser_class - - def get_base_parser(self): - parser = self.parser_class( - prog='keystone', - description=__doc__.strip(), - epilog='See "keystone help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=OpenStackHelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', - '--help', - action='store_true', - help=argparse.SUPPRESS) - - parser.add_argument('--version', - action='version', - version=keystoneclient.__version__, - help="Shows the client version and exits.") - - parser.add_argument('--debug', - default=False, - action='store_true', - help="Prints debugging output onto the console, " - "this includes the curl request and response " - "calls. Helpful for debugging and " - "understanding the API calls.") - - parser.add_argument('--os-username', - metavar='<auth-user-name>', - default=env('OS_USERNAME'), - help='Name used for authentication with the ' - 'OpenStack Identity service. ' - 'Defaults to env[OS_USERNAME].') - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-password', - metavar='<auth-password>', - default=env('OS_PASSWORD'), - help='Password used for authentication with the ' - 'OpenStack Identity service. ' - 'Defaults to env[OS_PASSWORD].') - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - metavar='<auth-tenant-name>', - default=env('OS_TENANT_NAME'), - help='Tenant to request authorization on. ' - 'Defaults to env[OS_TENANT_NAME].') - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - metavar='<tenant-id>', - default=env('OS_TENANT_ID'), - help='Tenant to request authorization on. ' - 'Defaults to env[OS_TENANT_ID].') - parser.add_argument('--os_tenant_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-url', - metavar='<auth-url>', - default=env('OS_AUTH_URL'), - help='Specify the Identity endpoint to use for ' - 'authentication. ' - 'Defaults to env[OS_AUTH_URL].') - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-region-name', - metavar='<region-name>', - default=env('OS_REGION_NAME'), - help='Specify the region to use. ' - 'Defaults to env[OS_REGION_NAME].') - parser.add_argument('--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-identity-api-version', - metavar='<identity-api-version>', - default=env('OS_IDENTITY_API_VERSION', - 'KEYSTONE_VERSION'), - help='Specify Identity API version to use. ' - 'Defaults to env[OS_IDENTITY_API_VERSION]' - ' or 2.0.') - parser.add_argument('--os_identity_api_version', - help=argparse.SUPPRESS) - - parser.add_argument('--os-token', - metavar='<service-token>', - default=env('OS_SERVICE_TOKEN'), - help='Specify an existing token to use instead of ' - 'retrieving one via authentication (e.g. ' - 'with username & password). ' - 'Defaults to env[OS_SERVICE_TOKEN].') - - parser.add_argument('--os-endpoint', - metavar='<service-endpoint>', - default=env('OS_SERVICE_ENDPOINT'), - help='Specify an endpoint to use instead of ' - 'retrieving one from the service catalog ' - '(via authentication). ' - 'Defaults to env[OS_SERVICE_ENDPOINT].') - - parser.add_argument('--os-cache', - default=env('OS_CACHE', default=False), - action='store_true', - help='Use the auth token cache. ' - 'Defaults to env[OS_CACHE].') - parser.add_argument('--os_cache', - help=argparse.SUPPRESS) - - parser.add_argument('--force-new-token', - default=False, - action="store_true", - dest='force_new_token', - help="If the keyring is available and in use, " - "token will always be stored and fetched " - "from the keyring until the token has " - "expired. Use this option to request a " - "new token and replace the existing one " - "in the keyring.") - - parser.add_argument('--stale-duration', - metavar='<seconds>', - default=access.STALE_TOKEN_DURATION, - dest='stale_duration', - help="Stale duration (in seconds) used to " - "determine whether a token has expired " - "when retrieving it from keyring. This " - "is useful in mitigating process or " - "network delays. Default is %s seconds." % - access.STALE_TOKEN_DURATION) - - session.Session.register_cli_options(parser) - - parser.add_argument('--os_cacert', help=argparse.SUPPRESS) - parser.add_argument('--os_key', help=argparse.SUPPRESS) - parser.add_argument('--os_cert', help=argparse.SUPPRESS) - - return parser - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='<subcommand>') - - try: - actions_module = { - '2.0': shell_v2_0, - }[version] - except KeyError: - actions_module = shell_v2_0 - - self._find_actions(subparsers, actions_module) - self._find_actions(subparsers, shell_generic) - self._find_actions(subparsers, shell_bootstrap) - self._find_actions(subparsers, self) - self._add_bash_completion_subparser(subparsers) - - return parser - - def _add_bash_completion_subparser(self, subparsers): - subparser = subparsers.add_parser( - 'bash_completion', - add_help=False, - formatter_class=OpenStackHelpFormatter - ) - self.subcommands['bash_completion'] = subparser - subparser.set_defaults(func=self.do_bash_completion) - - def _find_actions(self, subparsers, actions_module): - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hyphen-separated instead of underscores. - command = attr[3:].replace('_', '-') - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - help = desc.strip().split('\n')[0] - arguments = getattr(callback, 'arguments', []) - - subparser = subparsers.add_parser( - command, - help=help, - description=desc, - add_help=False, - formatter_class=OpenStackHelpFormatter) - subparser.add_argument('-h', '--help', action='help', - help=argparse.SUPPRESS) - self.subcommands[command] = subparser - group = subparser.add_argument_group(title='Arguments') - for (args, kwargs) in arguments: - group.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - def auth_check(self, args): - if args.os_token or args.os_endpoint: - if not args.os_token: - raise exc.CommandError( - 'Expecting a token provided via either --os-token or ' - 'env[OS_SERVICE_TOKEN]') - - if not args.os_endpoint: - raise exc.CommandError( - 'Expecting an endpoint provided via either ' - '--os-endpoint or env[OS_SERVICE_ENDPOINT]') - - # user supplied a token and endpoint and at least one other cred - if args.os_username or args.os_password or args.os_auth_url: - msg = ('WARNING: Bypassing authentication using a token & ' - 'endpoint (authentication credentials are being ' - 'ignored).') - print(msg) - - else: - if not args.os_auth_url: - raise exc.CommandError( - 'Expecting an auth URL via either --os-auth-url or ' - 'env[OS_AUTH_URL]') - - if args.os_username or args.os_password: - if not args.os_username: - raise exc.CommandError( - 'Expecting a username provided via either ' - '--os-username or env[OS_USERNAME]') - - if not args.os_password: - # No password, If we've got a tty, try prompting for it - if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): - # Check for Ctl-D - try: - args.os_password = getpass.getpass('OS Password: ') - except EOFError: - pass - # No password because we didn't have a tty or the - # user Ctl-D when prompted? - if not args.os_password: - raise exc.CommandError( - 'Expecting a password provided via either ' - '--os-password, env[OS_PASSWORD], or ' - 'prompted response') - - else: - raise exc.CommandError('Expecting authentication method via' - '\n either a service token, ' - '--os-token or env[OS_SERVICE_TOKEN], ' - '\n credentials, ' - '--os-username or env[OS_USERNAME]') - - def main(self, argv): - # Parse args once to find version - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - - # build available subcommands based on version - api_version = options.os_identity_api_version - subcommand_parser = self.get_subcommand_parser(api_version) - self.parser = subcommand_parser - - # Handle top-level --help/-h before attempting to parse - # a command off the command line - if not argv or options.help: - self.do_help(options) - return 0 - - # Parse args again and call whatever callback was selected - args = subcommand_parser.parse_args(argv) - - # Short-circuit and deal with help command right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion(args) - return 0 - - if args.debug: - logging_level = logging.DEBUG - iso_logger = logging.getLogger('iso8601') - iso_logger.setLevel('WARN') - else: - logging_level = logging.WARNING - - logging.basicConfig(level=logging_level) - - # TODO(heckj): supporting backwards compatibility with environment - # variables. To be removed after DEVSTACK is updated, ideally in - # the Grizzly release cycle. - args.os_token = args.os_token or env('SERVICE_TOKEN') - args.os_endpoint = args.os_endpoint or env('SERVICE_ENDPOINT') - - if utils.isunauthenticated(args.func): - self.cs = shell_generic.CLIENT_CLASS(endpoint=args.os_auth_url, - cacert=args.os_cacert, - key=args.os_key, - cert=args.os_cert, - insecure=args.insecure, - timeout=args.timeout) - else: - self.auth_check(args) - token = None - if args.os_token and args.os_endpoint: - token = args.os_token - api_version = options.os_identity_api_version - self.cs = self.get_api_class(api_version)( - username=args.os_username, - tenant_name=args.os_tenant_name, - tenant_id=args.os_tenant_id, - token=token, - endpoint=args.os_endpoint, - password=args.os_password, - auth_url=args.os_auth_url, - region_name=args.os_region_name, - cacert=args.os_cacert, - key=args.os_key, - cert=args.os_cert, - insecure=args.insecure, - debug=args.debug, - use_keyring=args.os_cache, - force_new_token=args.force_new_token, - stale_duration=args.stale_duration, - timeout=args.timeout) - - try: - args.func(self.cs, args) - except exc.Unauthorized: - raise exc.CommandError("Invalid OpenStack Identity credentials.") - except exc.AuthorizationFailure: - raise exc.CommandError("Unable to authorize user") - - def get_api_class(self, version): - try: - return { - "2.0": shell_v2_0.CLIENT_CLASS, - }[version] - except KeyError: - if version: - msg = ('WARNING: unsupported identity-api-version %s, ' - 'falling back to 2.0' % version) - print(msg) - return shell_v2_0.CLIENT_CLASS - - def do_bash_completion(self, args): - """Prints all of the commands and options to stdout. - - The keystone.bash_completion script doesn't have to hard code them. - """ - commands = set() - options = set() - for sc_str, sc in self.subcommands.items(): - commands.add(sc_str) - for option in list(sc._optionals._option_string_actions): - options.add(option) - - commands.remove('bash-completion') - commands.remove('bash_completion') - print(' '.join(commands | options)) - - @utils.arg('command', metavar='<subcommand>', nargs='?', - help='Display help for <subcommand>.') - def do_help(self, args): - """Display help about this program or one of its subcommands.""" - if getattr(args, 'command', None): - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError("'%s' is not a valid subcommand" % - args.command) - else: - self.parser.print_help() - - -# I'm picky about my shell help. -class OpenStackHelpFormatter(argparse.HelpFormatter): - INDENT_BEFORE_ARGUMENTS = 6 - MAX_WIDTH_ARGUMENTS = 32 - - def add_arguments(self, actions): - for action in filter(lambda x: not x.option_strings, actions): - if not action.choices: - continue - for choice in action.choices: - length = len(choice) + self.INDENT_BEFORE_ARGUMENTS - if(length > self._max_help_position and - length <= self.MAX_WIDTH_ARGUMENTS): - self._max_help_position = length - super(OpenStackHelpFormatter, self).add_arguments(actions) - - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(OpenStackHelpFormatter, self).start_section(heading) - - -def main(): - try: - OpenStackIdentityShell().main(sys.argv[1:]) - except KeyboardInterrupt: - print("... terminating keystone client", file=sys.stderr) - sys.exit(130) - except Exception as e: - print(encodeutils.safe_encode(six.text_type(e)), file=sys.stderr) - sys.exit(1) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/awx/lib/site-packages/keystoneclient/tests/__init__.py b/awx/lib/site-packages/keystoneclient/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/functional/__init__.py b/awx/lib/site-packages/keystoneclient/tests/functional/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/functional/hooks/post_test_hook.sh b/awx/lib/site-packages/keystoneclient/tests/functional/hooks/post_test_hook.sh deleted file mode 100755 index 0a07aa77dd..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/functional/hooks/post_test_hook.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -xe - -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# This script is executed inside post_test_hook function in devstack gate. - -function generate_testr_results { - if [ -f .testrepository/0 ]; then - sudo .tox/functional/bin/testr last --subunit > $WORKSPACE/testrepository.subunit - sudo mv $WORKSPACE/testrepository.subunit $BASE/logs/testrepository.subunit - sudo .tox/functional/bin/python /usr/local/jenkins/slave_scripts/subunit2html.py $BASE/logs/testrepository.subunit $BASE/logs/testr_results.html - sudo gzip -9 $BASE/logs/testrepository.subunit - sudo gzip -9 $BASE/logs/testr_results.html - sudo chown jenkins:jenkins $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz - sudo chmod a+r $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz - fi -} - -export KEYSTONECLIENT_DIR="$BASE/new/python-keystoneclient" - -# Get admin credentials -cd $BASE/new/devstack -source openrc admin admin - -# Go to the keystoneclient dir -cd $KEYSTONECLIENT_DIR - -sudo chown -R jenkins:stack $KEYSTONECLIENT_DIR - -# Run tests -echo "Running keystoneclient functional test suite" -set +e -# Preserve env for OS_ credentials -sudo -E -H -u jenkins tox -efunctional -EXIT_CODE=$? -set -e - -# Collect and parse result -generate_testr_results -exit $EXIT_CODE diff --git a/awx/lib/site-packages/keystoneclient/tests/functional/test_cli.py b/awx/lib/site-packages/keystoneclient/tests/functional/test_cli.py deleted file mode 100644 index 8400e7ce0b..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/functional/test_cli.py +++ /dev/null @@ -1,143 +0,0 @@ - -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import re - -from tempest_lib.cli import base -from tempest_lib import exceptions - - -class SimpleReadOnlyKeystoneClientTest(base.ClientTestBase): - """Basic, read-only tests for Keystone CLI client. - - Checks return values and output of read-only commands. - These tests do not presume any content, nor do they create - their own. They only verify the structure of output if present. - """ - - def _get_clients(self): - path = os.path.join(os.path.abspath('.'), '.tox/functional/bin') - cli_dir = os.environ.get('OS_KEYSTONECLIENT_EXEC_DIR', path) - - return base.CLIClient( - username=os.environ.get('OS_USERNAME'), - password=os.environ.get('OS_PASSWORD'), - tenant_name=os.environ.get('OS_TENANT_NAME'), - uri=os.environ.get('OS_AUTH_URL'), - cli_dir=cli_dir) - - def keystone(self, *args, **kwargs): - return self.clients.keystone(*args, **kwargs) - - def test_admin_fake_action(self): - self.assertRaises(exceptions.CommandFailed, - self.keystone, - 'this-does-not-exist') - - def test_admin_catalog_list(self): - out = self.keystone('catalog') - catalog = self.parser.details_multiple(out, with_label=True) - for svc in catalog: - if svc.get('__label'): - self.assertTrue(svc['__label'].startswith('Service:'), - msg=('Invalid beginning of service block: ' - '%s' % svc['__label'])) - # check that region and publicURL exists. One might also - # check for adminURL and internalURL. id seems to be optional - # and is missing in the catalog backend - self.assertIn('publicURL', svc.keys()) - self.assertIn('region', svc.keys()) - - def test_admin_endpoint_list(self): - out = self.keystone('endpoint-list') - endpoints = self.parser.listing(out) - self.assertTableStruct(endpoints, [ - 'id', 'region', 'publicurl', 'internalurl', - 'adminurl', 'service_id']) - - def test_admin_endpoint_service_match(self): - endpoints = self.parser.listing(self.keystone('endpoint-list')) - services = self.parser.listing(self.keystone('service-list')) - svc_by_id = {} - for svc in services: - svc_by_id[svc['id']] = svc - for endpoint in endpoints: - self.assertIn(endpoint['service_id'], svc_by_id) - - def test_admin_role_list(self): - roles = self.parser.listing(self.keystone('role-list')) - self.assertTableStruct(roles, ['id', 'name']) - - def test_admin_service_list(self): - services = self.parser.listing(self.keystone('service-list')) - self.assertTableStruct(services, ['id', 'name', 'type', 'description']) - - def test_admin_tenant_list(self): - tenants = self.parser.listing(self.keystone('tenant-list')) - self.assertTableStruct(tenants, ['id', 'name', 'enabled']) - - def test_admin_user_list(self): - users = self.parser.listing(self.keystone('user-list')) - self.assertTableStruct(users, [ - 'id', 'name', 'enabled', 'email']) - - def test_admin_user_role_list(self): - user_roles = self.parser.listing(self.keystone('user-role-list')) - self.assertTableStruct(user_roles, [ - 'id', 'name', 'user_id', 'tenant_id']) - - def test_admin_discover(self): - discovered = self.keystone('discover') - self.assertIn('Keystone found at http', discovered) - self.assertIn('supports version', discovered) - - def test_admin_help(self): - help_text = self.keystone('help') - lines = help_text.split('\n') - self.assertFirstLineStartsWith(lines, 'usage: keystone') - - commands = [] - cmds_start = lines.index('Positional arguments:') - cmds_end = lines.index('Optional arguments:') - command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)') - for line in lines[cmds_start:cmds_end]: - match = command_pattern.match(line) - if match: - commands.append(match.group(1)) - commands = set(commands) - wanted_commands = set(('catalog', 'endpoint-list', 'help', - 'token-get', 'discover', 'bootstrap')) - self.assertFalse(wanted_commands - commands) - - def test_admin_bashcompletion(self): - self.keystone('bash-completion') - - def test_admin_ec2_credentials_list(self): - creds = self.keystone('ec2-credentials-list') - creds = self.parser.listing(creds) - self.assertTableStruct(creds, ['tenant', 'access', 'secret']) - - # Optional arguments: - - def test_admin_version(self): - self.keystone('', flags='--version') - - def test_admin_debug_list(self): - self.keystone('catalog', flags='--debug') - - def test_admin_timeout(self): - self.keystone('catalog', flags='--timeout %d' % 15) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/__init__.py b/awx/lib/site-packages/keystoneclient/tests/unit/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/apiclient/__init__.py b/awx/lib/site-packages/keystoneclient/tests/unit/apiclient/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/apiclient/test_exceptions.py b/awx/lib/site-packages/keystoneclient/tests/unit/apiclient/test_exceptions.py deleted file mode 100644 index 4a803c7e71..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/apiclient/test_exceptions.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from keystoneclient import exceptions -from keystoneclient.tests.unit import utils - - -class FakeResponse(object): - json_data = {} - - def __init__(self, **kwargs): - for key, value in six.iteritems(kwargs): - setattr(self, key, value) - - def json(self): - return self.json_data - - -class ExceptionsArgsTest(utils.TestCase): - - def assert_exception(self, ex_cls, method, url, status_code, json_data): - ex = exceptions.from_response( - FakeResponse(status_code=status_code, - headers={"Content-Type": "application/json"}, - json_data=json_data), - method, - url) - self.assertIsInstance(ex, ex_cls) - self.assertEqual(ex.message, json_data["error"]["message"]) - self.assertEqual(ex.details, json_data["error"]["details"]) - self.assertEqual(ex.method, method) - self.assertEqual(ex.url, url) - self.assertEqual(ex.http_status, status_code) - - def test_from_response_known(self): - method = "GET" - url = "/fake" - status_code = 400 - json_data = {"error": {"message": "fake message", - "details": "fake details"}} - self.assert_exception( - exceptions.BadRequest, method, url, status_code, json_data) - - def test_from_response_unknown(self): - method = "POST" - url = "/fake-unknown" - status_code = 499 - json_data = {"error": {"message": "fake unknown message", - "details": "fake unknown details"}} - self.assert_exception( - exceptions.HTTPClientError, method, url, status_code, json_data) - status_code = 600 - self.assert_exception( - exceptions.HTTPError, method, url, status_code, json_data) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/__init__.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_access.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_access.py deleted file mode 100644 index 405fb8befd..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_access.py +++ /dev/null @@ -1,61 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import access -from keystoneclient import auth -from keystoneclient.auth.identity import access as access_plugin -from keystoneclient import fixture -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -class AccessInfoPluginTests(utils.TestCase): - - def setUp(self): - super(AccessInfoPluginTests, self).setUp() - self.session = session.Session() - self.auth_token = uuid.uuid4().hex - - def _plugin(self, **kwargs): - token = fixture.V3Token() - s = token.add_service('identity') - s.add_standard_endpoints(public=self.TEST_ROOT_URL) - - auth_ref = access.AccessInfo.factory(body=token, - auth_token=self.auth_token) - return access_plugin.AccessInfoPlugin(auth_ref, **kwargs) - - def test_auth_ref(self): - plugin = self._plugin() - self.assertEqual(self.TEST_ROOT_URL, - plugin.get_endpoint(self.session, - service_type='identity', - interface='public')) - self.assertEqual(self.auth_token, plugin.get_token(session)) - - def test_auth_url(self): - auth_url = 'http://keystone.test.url' - plugin = self._plugin(auth_url=auth_url) - - self.assertEqual(auth_url, - plugin.get_endpoint(self.session, - interface=auth.AUTH_INTERFACE)) - - def test_invalidate(self): - plugin = self._plugin() - auth_ref = plugin.auth_ref - - self.assertIsInstance(auth_ref, access.AccessInfo) - self.assertFalse(plugin.invalidate()) - self.assertIs(auth_ref, plugin.auth_ref) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_cli.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_cli.py deleted file mode 100644 index d65de731f7..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_cli.py +++ /dev/null @@ -1,196 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import uuid - -import fixtures -import mock -from oslo_config import cfg - -from keystoneclient.auth import base -from keystoneclient.auth import cli -from keystoneclient.tests.unit.auth import utils - - -class TesterPlugin(base.BaseAuthPlugin): - - def get_token(self, *args, **kwargs): - return None - - @classmethod - def get_options(cls): - # NOTE(jamielennox): this is kind of horrible. If you specify this as - # a deprecated_name= value it will convert - to _ which is not what we - # want for a CLI option. - deprecated = [cfg.DeprecatedOpt('test-other')] - return [ - cfg.StrOpt('test-opt', help='tester', deprecated_opts=deprecated) - ] - - -class CliTests(utils.TestCase): - - def setUp(self): - super(CliTests, self).setUp() - self.p = argparse.ArgumentParser() - - def env(self, name, value=None): - if value is not None: - # environment variables are always strings - value = str(value) - - return self.useFixture(fixtures.EnvironmentVariable(name, value)) - - def test_creating_with_no_args(self): - ret = cli.register_argparse_arguments(self.p, []) - self.assertIsNone(ret) - self.assertIn('--os-auth-plugin', self.p.format_usage()) - - def test_load_with_nothing(self): - cli.register_argparse_arguments(self.p, []) - opts = self.p.parse_args([]) - self.assertIsNone(cli.load_from_argparse_arguments(opts)) - - @utils.mock_plugin - def test_basic_params_added(self, m): - name = uuid.uuid4().hex - argv = ['--os-auth-plugin', name] - ret = cli.register_argparse_arguments(self.p, argv) - self.assertIs(utils.MockPlugin, ret) - - for n in ('--os-a-int', '--os-a-bool', '--os-a-float'): - self.assertIn(n, self.p.format_usage()) - - m.assert_called_once_with(name) - - @utils.mock_plugin - def test_param_loading(self, m): - name = uuid.uuid4().hex - argv = ['--os-auth-plugin', name, - '--os-a-int', str(self.a_int), - '--os-a-float', str(self.a_float), - '--os-a-bool', str(self.a_bool)] - - klass = cli.register_argparse_arguments(self.p, argv) - self.assertIs(utils.MockPlugin, klass) - - opts = self.p.parse_args(argv) - self.assertEqual(name, opts.os_auth_plugin) - - a = cli.load_from_argparse_arguments(opts) - self.assertTestVals(a) - - self.assertEqual(name, opts.os_auth_plugin) - self.assertEqual(str(self.a_int), opts.os_a_int) - self.assertEqual(str(self.a_float), opts.os_a_float) - self.assertEqual(str(self.a_bool), opts.os_a_bool) - - @utils.mock_plugin - def test_default_options(self, m): - name = uuid.uuid4().hex - argv = ['--os-auth-plugin', name, - '--os-a-float', str(self.a_float)] - - klass = cli.register_argparse_arguments(self.p, argv) - self.assertIs(utils.MockPlugin, klass) - - opts = self.p.parse_args(argv) - self.assertEqual(name, opts.os_auth_plugin) - - a = cli.load_from_argparse_arguments(opts) - - self.assertEqual(self.a_float, a['a_float']) - self.assertEqual(3, a['a_int']) - - @utils.mock_plugin - def test_with_default_string_value(self, m): - name = uuid.uuid4().hex - klass = cli.register_argparse_arguments(self.p, [], default=name) - self.assertIs(utils.MockPlugin, klass) - m.assert_called_once_with(name) - - @utils.mock_plugin - def test_overrides_default_string_value(self, m): - name = uuid.uuid4().hex - default = uuid.uuid4().hex - argv = ['--os-auth-plugin', name] - klass = cli.register_argparse_arguments(self.p, argv, default=default) - self.assertIs(utils.MockPlugin, klass) - m.assert_called_once_with(name) - - @utils.mock_plugin - def test_with_default_type_value(self, m): - klass = cli.register_argparse_arguments(self.p, [], - default=utils.MockPlugin) - self.assertIs(utils.MockPlugin, klass) - self.assertEqual(0, m.call_count) - - @utils.mock_plugin - def test_overrides_default_type_value(self, m): - # using this test plugin would fail if called because there - # is no get_options() function - class TestPlugin(object): - pass - name = uuid.uuid4().hex - argv = ['--os-auth-plugin', name] - klass = cli.register_argparse_arguments(self.p, argv, - default=TestPlugin) - self.assertIs(utils.MockPlugin, klass) - m.assert_called_once_with(name) - - @utils.mock_plugin - def test_env_overrides_default_opt(self, m): - name = uuid.uuid4().hex - val = uuid.uuid4().hex - self.env('OS_A_STR', val) - - klass = cli.register_argparse_arguments(self.p, [], default=name) - opts = self.p.parse_args([]) - a = klass.load_from_argparse_arguments(opts) - - self.assertEqual(val, a['a_str']) - - def test_deprecated_cli_options(self): - TesterPlugin.register_argparse_arguments(self.p) - val = uuid.uuid4().hex - opts = self.p.parse_args(['--os-test-other', val]) - self.assertEqual(val, opts.os_test_opt) - - def test_deprecated_multi_cli_options(self): - TesterPlugin.register_argparse_arguments(self.p) - val1 = uuid.uuid4().hex - val2 = uuid.uuid4().hex - # argarse rules say that the last specified wins. - opts = self.p.parse_args(['--os-test-other', val2, - '--os-test-opt', val1]) - self.assertEqual(val1, opts.os_test_opt) - - def test_deprecated_env_options(self): - val = uuid.uuid4().hex - - with mock.patch.dict('os.environ', {'OS_TEST_OTHER': val}): - TesterPlugin.register_argparse_arguments(self.p) - - opts = self.p.parse_args([]) - self.assertEqual(val, opts.os_test_opt) - - def test_deprecated_env_multi_options(self): - val1 = uuid.uuid4().hex - val2 = uuid.uuid4().hex - - with mock.patch.dict('os.environ', {'OS_TEST_OPT': val1, - 'OS_TEST_OTHER': val2}): - TesterPlugin.register_argparse_arguments(self.p) - - opts = self.p.parse_args([]) - self.assertEqual(val1, opts.os_test_opt) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_conf.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_conf.py deleted file mode 100644 index c3ce8eb69f..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_conf.py +++ /dev/null @@ -1,177 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -import mock -from oslo_config import cfg -from oslo_config import fixture as config -import stevedore - -from keystoneclient.auth import base -from keystoneclient.auth import conf -from keystoneclient.auth.identity import v2 as v2_auth -from keystoneclient.auth.identity import v3 as v3_auth -from keystoneclient import exceptions -from keystoneclient.tests.unit.auth import utils - - -class ConfTests(utils.TestCase): - - def setUp(self): - super(ConfTests, self).setUp() - self.conf_fixture = self.useFixture(config.Config()) - - # NOTE(jamielennox): we register the basic config options first because - # we need them in place before we can stub them. We will need to run - # the register again after we stub the auth section and auth plugin so - # it can load the plugin specific options. - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - - def test_loading_v2(self): - section = uuid.uuid4().hex - username = uuid.uuid4().hex - password = uuid.uuid4().hex - trust_id = uuid.uuid4().hex - tenant_id = uuid.uuid4().hex - - self.conf_fixture.config(auth_section=section, group=self.GROUP) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - - self.conf_fixture.register_opts(v2_auth.Password.get_options(), - group=section) - - self.conf_fixture.config(auth_plugin=self.V2PASS, - username=username, - password=password, - trust_id=trust_id, - tenant_id=tenant_id, - group=section) - - a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP) - - self.assertEqual(username, a.username) - self.assertEqual(password, a.password) - self.assertEqual(trust_id, a.trust_id) - self.assertEqual(tenant_id, a.tenant_id) - - def test_loading_v3(self): - section = uuid.uuid4().hex - token = uuid.uuid4().hex - trust_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - project_domain_name = uuid.uuid4().hex - - self.conf_fixture.config(auth_section=section, group=self.GROUP) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - - self.conf_fixture.register_opts(v3_auth.Token.get_options(), - group=section) - - self.conf_fixture.config(auth_plugin=self.V3TOKEN, - token=token, - trust_id=trust_id, - project_id=project_id, - project_domain_name=project_domain_name, - group=section) - - a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP) - - self.assertEqual(token, a.auth_methods[0].token) - self.assertEqual(trust_id, a.trust_id) - self.assertEqual(project_id, a.project_id) - self.assertEqual(project_domain_name, a.project_domain_name) - - def test_loading_invalid_plugin(self): - auth_plugin = uuid.uuid4().hex - self.conf_fixture.config(auth_plugin=auth_plugin, - group=self.GROUP) - - e = self.assertRaises(exceptions.NoMatchingPlugin, - conf.load_from_conf_options, - self.conf_fixture.conf, - self.GROUP) - - self.assertEqual(auth_plugin, e.name) - - def test_loading_with_no_data(self): - self.assertIsNone(conf.load_from_conf_options(self.conf_fixture.conf, - self.GROUP)) - - @mock.patch('stevedore.DriverManager') - def test_other_params(self, m): - m.return_value = utils.MockManager(utils.MockPlugin) - driver_name = uuid.uuid4().hex - - self.conf_fixture.register_opts(utils.MockPlugin.get_options(), - group=self.GROUP) - self.conf_fixture.config(auth_plugin=driver_name, - group=self.GROUP, - **self.TEST_VALS) - - a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP) - self.assertTestVals(a) - - m.assert_called_once_with(namespace=base.PLUGIN_NAMESPACE, - name=driver_name, - invoke_on_load=False) - - @utils.mock_plugin - def test_same_section(self, m): - self.conf_fixture.register_opts(utils.MockPlugin.get_options(), - group=self.GROUP) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - self.conf_fixture.config(auth_plugin=uuid.uuid4().hex, - group=self.GROUP, - **self.TEST_VALS) - - a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP) - self.assertTestVals(a) - - @utils.mock_plugin - def test_diff_section(self, m): - section = uuid.uuid4().hex - - self.conf_fixture.config(auth_section=section, group=self.GROUP) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - - self.conf_fixture.register_opts(utils.MockPlugin.get_options(), - group=section) - self.conf_fixture.config(group=section, - auth_plugin=uuid.uuid4().hex, - **self.TEST_VALS) - - a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP) - self.assertTestVals(a) - - def test_plugins_are_all_opts(self): - manager = stevedore.ExtensionManager(base.PLUGIN_NAMESPACE, - invoke_on_load=False, - propagate_map_exceptions=True) - - def inner(driver): - for p in driver.plugin.get_options(): - self.assertIsInstance(p, cfg.Opt) - - manager.map(inner) - - def test_get_common(self): - opts = conf.get_common_conf_options() - for opt in opts: - self.assertIsInstance(opt, cfg.Opt) - self.assertEqual(2, len(opts)) - - def test_get_named(self): - loaded_opts = conf.get_plugin_options('v2password') - plugin_opts = v2_auth.Password.get_options() - - self.assertEqual(plugin_opts, loaded_opts) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_common.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_common.py deleted file mode 100644 index 3bf04c79d8..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_common.py +++ /dev/null @@ -1,423 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc -import datetime -import uuid - -from oslo_utils import timeutils -import six - -from keystoneclient import access -from keystoneclient.auth import base -from keystoneclient.auth import identity -from keystoneclient import fixture -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -@six.add_metaclass(abc.ABCMeta) -class CommonIdentityTests(object): - - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' - - TEST_COMPUTE_PUBLIC = 'http://nova/novapi/public' - TEST_COMPUTE_INTERNAL = 'http://nova/novapi/internal' - TEST_COMPUTE_ADMIN = 'http://nova/novapi/admin' - - TEST_PASS = uuid.uuid4().hex - - def setUp(self): - super(CommonIdentityTests, self).setUp() - - self.TEST_URL = '%s%s' % (self.TEST_ROOT_URL, self.version) - self.TEST_ADMIN_URL = '%s%s' % (self.TEST_ROOT_ADMIN_URL, self.version) - self.TEST_DISCOVERY = fixture.DiscoveryList(href=self.TEST_ROOT_URL) - - self.stub_auth_data() - - @abc.abstractmethod - def create_auth_plugin(self, **kwargs): - """Create an auth plugin that makes sense for the auth data. - - It doesn't really matter what auth mechanism is used but it should be - appropriate to the API version. - """ - - @abc.abstractmethod - def get_auth_data(self, **kwargs): - """Return fake authentication data. - - This should register a valid token response and ensure that the compute - endpoints are set to TEST_COMPUTE_PUBLIC, _INTERNAL and _ADMIN. - """ - - def stub_auth_data(self, **kwargs): - token = self.get_auth_data(**kwargs) - self.user_id = token.user_id - - try: - self.project_id = token.project_id - except AttributeError: - self.project_id = token.tenant_id - - self.stub_auth(json=token) - - @abc.abstractproperty - def version(self): - """The API version being tested.""" - - def test_discovering(self): - self.stub_url('GET', [], - base_url=self.TEST_COMPUTE_ADMIN, - json=self.TEST_DISCOVERY) - - body = 'SUCCESS' - - # which gives our sample values - self.stub_url('GET', ['path'], text=body) - - a = self.create_auth_plugin() - s = session.Session(auth=a) - - resp = s.get('/path', endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': self.version}) - - self.assertEqual(200, resp.status_code) - self.assertEqual(body, resp.text) - - new_body = 'SC SUCCESS' - # if we don't specify a version, we use the URL from the SC - self.stub_url('GET', ['path'], - base_url=self.TEST_COMPUTE_ADMIN, - text=new_body) - - resp = s.get('/path', endpoint_filter={'service_type': 'compute', - 'interface': 'admin'}) - - self.assertEqual(200, resp.status_code) - self.assertEqual(new_body, resp.text) - - def test_discovery_uses_session_cache(self): - # register responses such that if the discovery URL is hit more than - # once then the response will be invalid and not point to COMPUTE_ADMIN - resps = [{'json': self.TEST_DISCOVERY}, {'status_code': 500}] - self.requests_mock.get(self.TEST_COMPUTE_ADMIN, resps) - - body = 'SUCCESS' - self.stub_url('GET', ['path'], text=body) - - # now either of the two plugins I use, it should not cause a second - # request to the discovery url. - s = session.Session() - a = self.create_auth_plugin() - b = self.create_auth_plugin() - - for auth in (a, b): - resp = s.get('/path', - auth=auth, - endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': self.version}) - - self.assertEqual(200, resp.status_code) - self.assertEqual(body, resp.text) - - def test_discovery_uses_plugin_cache(self): - # register responses such that if the discovery URL is hit more than - # once then the response will be invalid and not point to COMPUTE_ADMIN - resps = [{'json': self.TEST_DISCOVERY}, {'status_code': 500}] - self.requests_mock.get(self.TEST_COMPUTE_ADMIN, resps) - - body = 'SUCCESS' - self.stub_url('GET', ['path'], text=body) - - # now either of the two sessions I use, it should not cause a second - # request to the discovery url. - sa = session.Session() - sb = session.Session() - auth = self.create_auth_plugin() - - for sess in (sa, sb): - resp = sess.get('/path', - auth=auth, - endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': self.version}) - - self.assertEqual(200, resp.status_code) - self.assertEqual(body, resp.text) - - def test_discovering_with_no_data(self): - # which returns discovery information pointing to TEST_URL but there is - # no data there. - self.stub_url('GET', [], - base_url=self.TEST_COMPUTE_ADMIN, - status_code=400) - - # so the url that will be used is the same TEST_COMPUTE_ADMIN - body = 'SUCCESS' - self.stub_url('GET', ['path'], base_url=self.TEST_COMPUTE_ADMIN, - text=body, status_code=200) - - a = self.create_auth_plugin() - s = session.Session(auth=a) - - resp = s.get('/path', endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': self.version}) - - self.assertEqual(200, resp.status_code) - self.assertEqual(body, resp.text) - - def test_asking_for_auth_endpoint_ignores_checks(self): - a = self.create_auth_plugin() - s = session.Session(auth=a) - - auth_url = s.get_endpoint(service_type='compute', - interface=base.AUTH_INTERFACE) - - self.assertEqual(self.TEST_URL, auth_url) - - def _create_expired_auth_plugin(self, **kwargs): - expires = timeutils.utcnow() - datetime.timedelta(minutes=20) - expired_token = self.get_auth_data(expires=expires) - expired_auth_ref = access.AccessInfo.factory(body=expired_token) - - body = 'SUCCESS' - self.stub_url('GET', ['path'], - base_url=self.TEST_COMPUTE_ADMIN, text=body) - - a = self.create_auth_plugin(**kwargs) - a.auth_ref = expired_auth_ref - return a - - def test_reauthenticate(self): - a = self._create_expired_auth_plugin() - expired_auth_ref = a.auth_ref - s = session.Session(auth=a) - self.assertIsNot(expired_auth_ref, a.get_access(s)) - - def test_no_reauthenticate(self): - a = self._create_expired_auth_plugin(reauthenticate=False) - expired_auth_ref = a.auth_ref - s = session.Session(auth=a) - self.assertIs(expired_auth_ref, a.get_access(s)) - - def test_invalidate(self): - a = self.create_auth_plugin() - s = session.Session(auth=a) - - # trigger token fetching - s.get_auth_headers() - - self.assertTrue(a.auth_ref) - self.assertTrue(a.invalidate()) - self.assertIsNone(a.auth_ref) - self.assertFalse(a.invalidate()) - - def test_get_auth_properties(self): - a = self.create_auth_plugin() - s = session.Session() - - self.assertEqual(self.user_id, a.get_user_id(s)) - self.assertEqual(self.project_id, a.get_project_id(s)) - - -class V3(CommonIdentityTests, utils.TestCase): - - @property - def version(self): - return 'v3' - - def get_auth_data(self, **kwargs): - token = fixture.V3Token(**kwargs) - region = 'RegionOne' - - svc = token.add_service('identity') - svc.add_standard_endpoints(admin=self.TEST_ADMIN_URL, region=region) - - svc = token.add_service('compute') - svc.add_standard_endpoints(admin=self.TEST_COMPUTE_ADMIN, - public=self.TEST_COMPUTE_PUBLIC, - internal=self.TEST_COMPUTE_INTERNAL, - region=region) - - return token - - def stub_auth(self, subject_token=None, **kwargs): - if not subject_token: - subject_token = self.TEST_TOKEN - - kwargs.setdefault('headers', {})['X-Subject-Token'] = subject_token - self.stub_url('POST', ['auth', 'tokens'], **kwargs) - - def create_auth_plugin(self, **kwargs): - kwargs.setdefault('auth_url', self.TEST_URL) - kwargs.setdefault('username', self.TEST_USER) - kwargs.setdefault('password', self.TEST_PASS) - return identity.V3Password(**kwargs) - - -class V2(CommonIdentityTests, utils.TestCase): - - @property - def version(self): - return 'v2.0' - - def create_auth_plugin(self, **kwargs): - kwargs.setdefault('auth_url', self.TEST_URL) - kwargs.setdefault('username', self.TEST_USER) - kwargs.setdefault('password', self.TEST_PASS) - return identity.V2Password(**kwargs) - - def get_auth_data(self, **kwargs): - token = fixture.V2Token(**kwargs) - region = 'RegionOne' - - svc = token.add_service('identity') - svc.add_endpoint(self.TEST_ADMIN_URL, region=region) - - svc = token.add_service('compute') - svc.add_endpoint(public=self.TEST_COMPUTE_PUBLIC, - internal=self.TEST_COMPUTE_INTERNAL, - admin=self.TEST_COMPUTE_ADMIN, - region=region) - - return token - - def stub_auth(self, **kwargs): - self.stub_url('POST', ['tokens'], **kwargs) - - -class CatalogHackTests(utils.TestCase): - - TEST_URL = 'http://keystone.server:5000/v2.0' - OTHER_URL = 'http://other.server:5000/path' - - IDENTITY = 'identity' - - BASE_URL = 'http://keystone.server:5000/' - V2_URL = BASE_URL + 'v2.0' - V3_URL = BASE_URL + 'v3' - - def test_getting_endpoints(self): - disc = fixture.DiscoveryList(href=self.BASE_URL) - self.stub_url('GET', - ['/'], - base_url=self.BASE_URL, - json=disc) - - token = fixture.V2Token() - service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) - - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) - - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) - - sess = session.Session(auth=v2_auth) - - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - interface='public', - version=(3, 0)) - - self.assertEqual(self.V3_URL, endpoint) - - def test_returns_original_when_discover_fails(self): - token = fixture.V2Token() - service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) - - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) - - self.stub_url('GET', [], base_url=self.BASE_URL, status_code=404) - - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) - - sess = session.Session(auth=v2_auth) - - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - interface='public', - version=(3, 0)) - - self.assertEqual(self.V2_URL, endpoint) - - -class GenericPlugin(base.BaseAuthPlugin): - - BAD_TOKEN = uuid.uuid4().hex - - def __init__(self): - super(GenericPlugin, self).__init__() - - self.endpoint = 'http://keystone.host:5000' - - self.headers = {'headerA': 'valueA', - 'headerB': 'valueB'} - - def url(self, prefix): - return '%s/%s' % (self.endpoint, prefix) - - def get_token(self, session, **kwargs): - # NOTE(jamielennox): by specifying get_headers this should not be used - return self.BAD_TOKEN - - def get_headers(self, session, **kwargs): - return self.headers - - def get_endpoint(self, session, **kwargs): - return self.endpoint - - -class GenericAuthPluginTests(utils.TestCase): - - # filter doesn't matter to GenericPlugin, but we have to specify one - ENDPOINT_FILTER = {uuid.uuid4().hex: uuid.uuid4().hex} - - def setUp(self): - super(GenericAuthPluginTests, self).setUp() - self.auth = GenericPlugin() - self.session = session.Session(auth=self.auth) - - def test_setting_headers(self): - text = uuid.uuid4().hex - self.stub_url('GET', base_url=self.auth.url('prefix'), text=text) - - resp = self.session.get('prefix', endpoint_filter=self.ENDPOINT_FILTER) - - self.assertEqual(text, resp.text) - - for k, v in six.iteritems(self.auth.headers): - self.assertRequestHeaderEqual(k, v) - - self.assertIsNone(self.session.get_token()) - self.assertEqual(self.auth.headers, - self.session.get_auth_headers()) - self.assertNotIn('X-Auth-Token', - self.requests_mock.last_request.headers) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v2.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v2.py deleted file mode 100644 index 4c05ee2343..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v2.py +++ /dev/null @@ -1,296 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import uuid - -from keystoneclient.auth.identity import v2 -from keystoneclient import exceptions -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -class V2IdentityPlugin(utils.TestCase): - - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0') - TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' - TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v2.0') - - TEST_PASS = 'password' - - TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "adminURL": "http://cdn.admin-nets.local:8774/v1.0", - "region": "RegionOne", - "internalURL": "http://127.0.0.1:8774/v1.0", - "publicURL": "http://cdn.admin-nets.local:8774/v1.0/" - }], - "type": "nova_compat", - "name": "nova_compat" - }, { - "endpoints": [{ - "adminURL": "http://nova/novapi/admin", - "region": "RegionOne", - "internalURL": "http://nova/novapi/internal", - "publicURL": "http://nova/novapi/public" - }], - "type": "compute", - "name": "nova" - }, { - "endpoints": [{ - "adminURL": "http://glance/glanceapi/admin", - "region": "RegionOne", - "internalURL": "http://glance/glanceapi/internal", - "publicURL": "http://glance/glanceapi/public" - }], - "type": "image", - "name": "glance" - }, { - "endpoints": [{ - "adminURL": TEST_ADMIN_URL, - "region": "RegionOne", - "internalURL": "http://127.0.0.1:5000/v2.0", - "publicURL": "http://127.0.0.1:5000/v2.0" - }], - "type": "identity", - "name": "keystone" - }, { - "endpoints": [{ - "adminURL": "http://swift/swiftapi/admin", - "region": "RegionOne", - "internalURL": "http://swift/swiftapi/internal", - "publicURL": "http://swift/swiftapi/public" - }], - "type": "object-store", - "name": "swift" - }] - - def setUp(self): - super(V2IdentityPlugin, self).setUp() - self.TEST_RESPONSE_DICT = { - "access": { - "token": { - "expires": "2020-01-01T00:00:10.000123Z", - "id": self.TEST_TOKEN, - "tenant": { - "id": self.TEST_TENANT_ID - }, - }, - "user": { - "id": self.TEST_USER - }, - "serviceCatalog": self.TEST_SERVICE_CATALOG, - }, - } - - def stub_auth(self, **kwargs): - self.stub_url('POST', ['tokens'], **kwargs) - - def test_authenticate_with_username_password(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - self.assertIsNone(a.user_id) - s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'username': self.TEST_USER, - 'password': self.TEST_PASS}}} - self.assertRequestBodyIs(json=req) - self.assertRequestHeaderEqual('Content-Type', 'application/json') - self.assertRequestHeaderEqual('Accept', 'application/json') - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_authenticate_with_user_id_password(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, user_id=self.TEST_USER, - password=self.TEST_PASS) - self.assertIsNone(a.username) - s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'userId': self.TEST_USER, - 'password': self.TEST_PASS}}} - self.assertRequestBodyIs(json=req) - self.assertRequestHeaderEqual('Content-Type', 'application/json') - self.assertRequestHeaderEqual('Accept', 'application/json') - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_authenticate_with_username_password_scoped(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, tenant_id=self.TEST_TENANT_ID) - self.assertIsNone(a.user_id) - s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'username': self.TEST_USER, - 'password': self.TEST_PASS}, - 'tenantId': self.TEST_TENANT_ID}} - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_authenticate_with_user_id_password_scoped(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, user_id=self.TEST_USER, - password=self.TEST_PASS, tenant_id=self.TEST_TENANT_ID) - self.assertIsNone(a.username) - s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'userId': self.TEST_USER, - 'password': self.TEST_PASS}, - 'tenantId': self.TEST_TENANT_ID}} - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_authenticate_with_token(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Token(self.TEST_URL, 'foo') - s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'token': {'id': 'foo'}}} - self.assertRequestBodyIs(json=req) - self.assertRequestHeaderEqual('x-Auth-Token', 'foo') - self.assertRequestHeaderEqual('Content-Type', 'application/json') - self.assertRequestHeaderEqual('Accept', 'application/json') - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_with_trust_id(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, trust_id='trust') - s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'username': self.TEST_USER, - 'password': self.TEST_PASS}, - 'trust_id': 'trust'}} - - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def _do_service_url_test(self, base_url, endpoint_filter): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', ['path'], - base_url=base_url, - text='SUCCESS', status_code=200) - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - resp = s.get('/path', endpoint_filter=endpoint_filter) - - self.assertEqual(resp.status_code, 200) - self.assertEqual(self.requests_mock.last_request.url, - base_url + '/path') - - def test_service_url(self): - endpoint_filter = {'service_type': 'compute', - 'interface': 'admin', - 'service_name': 'nova'} - self._do_service_url_test('http://nova/novapi/admin', endpoint_filter) - - def test_service_url_defaults_to_public(self): - endpoint_filter = {'service_type': 'compute'} - self._do_service_url_test('http://nova/novapi/public', endpoint_filter) - - def test_endpoint_filter_without_service_type_fails(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertRaises(exceptions.EndpointNotFound, s.get, '/path', - endpoint_filter={'interface': 'admin'}) - - def test_full_url_overrides_endpoint_filter(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [], - base_url='http://testurl/', - text='SUCCESS', status_code=200) - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - resp = s.get('http://testurl/', - endpoint_filter={'service_type': 'compute'}) - self.assertEqual(resp.status_code, 200) - self.assertEqual(resp.text, 'SUCCESS') - - def test_invalid_auth_response_dict(self): - self.stub_auth(json={'hello': 'world'}) - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) - - def test_invalid_auth_response_type(self): - self.stub_url('POST', ['tokens'], text='testdata') - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) - - def test_invalidate_response(self): - resp_data1 = copy.deepcopy(self.TEST_RESPONSE_DICT) - resp_data2 = copy.deepcopy(self.TEST_RESPONSE_DICT) - - resp_data1['access']['token']['id'] = 'token1' - resp_data2['access']['token']['id'] = 'token2' - - auth_responses = [{'json': resp_data1}, {'json': resp_data2}] - self.stub_auth(response_list=auth_responses) - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertEqual('token1', s.get_token()) - self.assertEqual({'X-Auth-Token': 'token1'}, s.get_auth_headers()) - - a.invalidate() - self.assertEqual('token2', s.get_token()) - self.assertEqual({'X-Auth-Token': 'token2'}, s.get_auth_headers()) - - def test_doesnt_log_password(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - password = uuid.uuid4().hex - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=password) - s = session.Session(auth=a) - self.assertEqual(self.TEST_TOKEN, s.get_token()) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - self.assertNotIn(password, self.logger.output) - - def test_password_with_no_user_id_or_name(self): - self.assertRaises(TypeError, - v2.Password, self.TEST_URL, password=self.TEST_PASS) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v3.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v3.py deleted file mode 100644 index c01b39f1cc..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v3.py +++ /dev/null @@ -1,498 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import uuid - -from keystoneclient import access -from keystoneclient.auth.identity import v3 -from keystoneclient.auth.identity.v3 import base as v3_base -from keystoneclient import client -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -class V3IdentityPlugin(utils.TestCase): - - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') - TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' - TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3') - - TEST_PASS = 'password' - - TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "url": "http://cdn.admin-nets.local:8774/v1.0/", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://127.0.0.1:8774/v1.0", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://cdn.admin-nets.local:8774/v1.0", - "region": "RegionOne", - "interface": "admin" - }], - "type": "nova_compat" - }, { - "endpoints": [{ - "url": "http://nova/novapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://nova/novapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://nova/novapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "compute", - "name": "nova", - }, { - "endpoints": [{ - "url": "http://glance/glanceapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://glance/glanceapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://glance/glanceapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "image", - "name": "glance" - }, { - "endpoints": [{ - "url": "http://127.0.0.1:5000/v3", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://127.0.0.1:5000/v3", - "region": "RegionOne", - "interface": "internal" - }, { - "url": TEST_ADMIN_URL, - "region": "RegionOne", - "interface": "admin" - }], - "type": "identity" - }, { - "endpoints": [{ - "url": "http://swift/swiftapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://swift/swiftapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://swift/swiftapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "object-store" - }] - - def setUp(self): - super(V3IdentityPlugin, self).setUp() - - V3_URL = "%sv3" % self.TEST_URL - self.TEST_DISCOVERY_RESPONSE = { - 'versions': {'values': [fixture.V3Discovery(V3_URL)]}} - - self.TEST_RESPONSE_DICT = { - "token": { - "methods": [ - "token", - "password" - ], - - "expires_at": "2020-01-01T00:00:10.000123Z", - "project": { - "domain": { - "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME - }, - "id": self.TEST_TENANT_ID, - "name": self.TEST_TENANT_NAME - }, - "user": { - "domain": { - "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME - }, - "id": self.TEST_USER, - "name": self.TEST_USER - }, - "issued_at": "2013-05-29T16:55:21.468960Z", - "catalog": self.TEST_SERVICE_CATALOG - }, - } - self.TEST_PROJECTS_RESPONSE = { - "projects": [ - { - "domain_id": "1789d1", - "enabled": "True", - "id": "263fd9", - "links": { - "self": "https://identity:5000/v3/projects/263fd9" - }, - "name": "Dev Group A" - }, - { - "domain_id": "1789d1", - "enabled": "True", - "id": "e56ad3", - "links": { - "self": "https://identity:5000/v3/projects/e56ad3" - }, - "name": "Dev Group B" - } - ], - "links": { - "self": "https://identity:5000/v3/projects", - } - } - - def stub_auth(self, subject_token=None, **kwargs): - if not subject_token: - subject_token = self.TEST_TOKEN - - self.stub_url('POST', ['auth', 'tokens'], - headers={'X-Subject-Token': subject_token}, **kwargs) - - def test_authenticate_with_username_password(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}}} - - self.assertRequestBodyIs(json=req) - self.assertRequestHeaderEqual('Content-Type', 'application/json') - self.assertRequestHeaderEqual('Accept', 'application/json') - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_authenticate_with_username_password_unscoped(self): - del self.TEST_RESPONSE_DICT['token']['catalog'] - del self.TEST_RESPONSE_DICT['token']['project'] - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url(method="GET", json=self.TEST_DISCOVERY_RESPONSE) - test_user_id = self.TEST_RESPONSE_DICT['token']['user']['id'] - self.stub_url(method="GET", - json=self.TEST_PROJECTS_RESPONSE, - parts=['users', test_user_id, 'projects']) - - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - cs = client.Client(session=s, auth_url=self.TEST_URL) - - # As a sanity check on the auth_ref, make sure client has the - # proper user id, that it fetches the right project response - self.assertEqual(test_user_id, a.auth_ref.user_id) - t = cs.projects.list(user=a.auth_ref.user_id) - self.assertEqual(2, len(t)) - - def test_authenticate_with_username_password_domain_scoped(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, domain_id=self.TEST_DOMAIN_ID) - s = session.Session(a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}, - 'scope': {'domain': {'id': self.TEST_DOMAIN_ID}}}} - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_authenticate_with_username_password_project_scoped(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, - project_id=self.TEST_DOMAIN_ID) - s = session.Session(a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}, - 'scope': {'project': {'id': self.TEST_DOMAIN_ID}}}} - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - self.assertEqual(s.auth.auth_ref.project_id, self.TEST_DOMAIN_ID) - - def test_authenticate_with_token(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Token(self.TEST_URL, self.TEST_TOKEN) - s = session.Session(auth=a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'identity': - {'methods': ['token'], - 'token': {'id': self.TEST_TOKEN}}}} - - self.assertRequestBodyIs(json=req) - - self.assertRequestHeaderEqual('Content-Type', 'application/json') - self.assertRequestHeaderEqual('Accept', 'application/json') - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_with_expired(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - d = copy.deepcopy(self.TEST_RESPONSE_DICT) - d['token']['expires_at'] = '2000-01-01T00:00:10.000123Z' - - a = v3.Password(self.TEST_URL, username='username', - password='password') - a.auth_ref = access.AccessInfo.factory(body=d) - s = session.Session(auth=a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - self.assertEqual(a.auth_ref['expires_at'], - self.TEST_RESPONSE_DICT['token']['expires_at']) - - def test_with_domain_and_project_scoping(self): - a = v3.Password(self.TEST_URL, username='username', - password='password', project_id='project', - domain_id='domain') - - self.assertRaises(exceptions.AuthorizationFailure, - a.get_token, None) - self.assertRaises(exceptions.AuthorizationFailure, - a.get_headers, None) - - def test_with_trust_id(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, trust_id='trust') - s = session.Session(a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}, - 'scope': {'OS-TRUST:trust': {'id': 'trust'}}}} - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_with_multiple_mechanisms_factory(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - p = v3.PasswordMethod(username=self.TEST_USER, password=self.TEST_PASS) - t = v3.TokenMethod(token='foo') - a = v3.Auth(self.TEST_URL, [p, t], trust_id='trust') - s = session.Session(a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'identity': - {'methods': ['password', 'token'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}, - 'token': {'id': 'foo'}}, - 'scope': {'OS-TRUST:trust': {'id': 'trust'}}}} - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_with_multiple_mechanisms(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - p = v3.PasswordMethod(username=self.TEST_USER, - password=self.TEST_PASS) - t = v3.TokenMethod(token='foo') - a = v3.Auth(self.TEST_URL, [p, t], trust_id='trust') - s = session.Session(auth=a) - - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'identity': - {'methods': ['password', 'token'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}, - 'token': {'id': 'foo'}}, - 'scope': {'OS-TRUST:trust': {'id': 'trust'}}}} - self.assertRequestBodyIs(json=req) - self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) - - def test_with_multiple_scopes(self): - s = session.Session() - - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, password=self.TEST_PASS, - domain_id='x', project_id='x') - self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s) - - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, password=self.TEST_PASS, - domain_id='x', trust_id='x') - self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s) - - def _do_service_url_test(self, base_url, endpoint_filter): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', ['path'], - base_url=base_url, - text='SUCCESS', status_code=200) - - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - resp = s.get('/path', endpoint_filter=endpoint_filter) - - self.assertEqual(resp.status_code, 200) - self.assertEqual(self.requests_mock.last_request.url, - base_url + '/path') - - def test_service_url(self): - endpoint_filter = {'service_type': 'compute', - 'interface': 'admin', - 'service_name': 'nova'} - self._do_service_url_test('http://nova/novapi/admin', endpoint_filter) - - def test_service_url_defaults_to_public(self): - endpoint_filter = {'service_type': 'compute'} - self._do_service_url_test('http://nova/novapi/public', endpoint_filter) - - def test_endpoint_filter_without_service_type_fails(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertRaises(exceptions.EndpointNotFound, s.get, '/path', - endpoint_filter={'interface': 'admin'}) - - def test_full_url_overrides_endpoint_filter(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [], - base_url='http://testurl/', - text='SUCCESS', status_code=200) - - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - resp = s.get('http://testurl/', - endpoint_filter={'service_type': 'compute'}) - self.assertEqual(resp.status_code, 200) - self.assertEqual(resp.text, 'SUCCESS') - - def test_invalid_auth_response_dict(self): - self.stub_auth(json={'hello': 'world'}) - - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) - - def test_invalid_auth_response_type(self): - self.stub_url('POST', ['auth', 'tokens'], text='testdata') - - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) - - def test_invalidate_response(self): - auth_responses = [{'status_code': 200, 'json': self.TEST_RESPONSE_DICT, - 'headers': {'X-Subject-Token': 'token1'}}, - {'status_code': 200, 'json': self.TEST_RESPONSE_DICT, - 'headers': {'X-Subject-Token': 'token2'}}] - - self.requests_mock.post('%s/auth/tokens' % self.TEST_URL, - auth_responses) - - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) - s = session.Session(auth=a) - - self.assertEqual('token1', s.get_token()) - self.assertEqual({'X-Auth-Token': 'token1'}, s.get_auth_headers()) - a.invalidate() - self.assertEqual('token2', s.get_token()) - self.assertEqual({'X-Auth-Token': 'token2'}, s.get_auth_headers()) - - def test_doesnt_log_password(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - password = uuid.uuid4().hex - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=password) - s = session.Session(a) - self.assertEqual(self.TEST_TOKEN, s.get_token()) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - self.assertNotIn(password, self.logger.output) - - def test_sends_nocatalog(self): - del self.TEST_RESPONSE_DICT['token']['catalog'] - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - include_catalog=False) - s = session.Session(auth=a) - - s.get_token() - - auth_url = self.TEST_URL + '/auth/tokens' - self.assertEqual(auth_url, a.token_url) - self.assertEqual(auth_url + '?nocatalog', - self.requests_mock.last_request.url) - - def test_symbols(self): - self.assertIs(v3.AuthMethod, v3_base.AuthMethod) - self.assertIs(v3.AuthConstructor, v3_base.AuthConstructor) - self.assertIs(v3.Auth, v3_base.Auth) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v3_federated.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v3_federated.py deleted file mode 100644 index b0fa119b3c..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_identity_v3_federated.py +++ /dev/null @@ -1,96 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import uuid - -from keystoneclient import access -from keystoneclient.auth.identity import v3 -from keystoneclient import fixture -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -class TesterFederationPlugin(v3.FederatedBaseAuth): - - def get_unscoped_auth_ref(self, sess, **kwargs): - # This would go and talk to an idp or something - resp = sess.post(self.federated_token_url, authenticated=False) - return access.AccessInfo.factory(resp=resp, body=resp.json()) - - -class V3FederatedPlugin(utils.TestCase): - - AUTH_URL = 'http://keystone/v3' - - def setUp(self): - super(V3FederatedPlugin, self).setUp() - - self.unscoped_token = fixture.V3Token() - self.unscoped_token_id = uuid.uuid4().hex - self.scoped_token = copy.deepcopy(self.unscoped_token) - self.scoped_token.set_project_scope() - self.scoped_token.methods.append('token') - self.scoped_token_id = uuid.uuid4().hex - - s = self.scoped_token.add_service('compute', name='nova') - s.add_standard_endpoints(public='http://nova/public', - admin='http://nova/admin', - internal='http://nova/internal') - - self.idp = uuid.uuid4().hex - self.protocol = uuid.uuid4().hex - - self.token_url = ('%s/OS-FEDERATION/identity_providers/%s/protocols/%s' - '/auth' % (self.AUTH_URL, self.idp, self.protocol)) - - headers = {'X-Subject-Token': self.unscoped_token_id} - self.unscoped_mock = self.requests_mock.post(self.token_url, - json=self.unscoped_token, - headers=headers) - - headers = {'X-Subject-Token': self.scoped_token_id} - auth_url = self.AUTH_URL + '/auth/tokens' - self.scoped_mock = self.requests_mock.post(auth_url, - json=self.scoped_token, - headers=headers) - - def get_plugin(self, **kwargs): - kwargs.setdefault('auth_url', self.AUTH_URL) - kwargs.setdefault('protocol', self.protocol) - kwargs.setdefault('identity_provider', self.idp) - return TesterFederationPlugin(**kwargs) - - def test_federated_url(self): - plugin = self.get_plugin() - self.assertEqual(self.token_url, plugin.federated_token_url) - - def test_unscoped_behaviour(self): - sess = session.Session(auth=self.get_plugin()) - self.assertEqual(self.unscoped_token_id, sess.get_token()) - - self.assertTrue(self.unscoped_mock.called) - self.assertFalse(self.scoped_mock.called) - - def test_scoped_behaviour(self): - auth = self.get_plugin(project_id=self.scoped_token.project_id) - sess = session.Session(auth=auth) - self.assertEqual(self.scoped_token_id, sess.get_token()) - - self.assertTrue(self.unscoped_mock.called) - self.assertTrue(self.scoped_mock.called) - - def test_options(self): - opts = [o.name for o in v3.FederatedBaseAuth.get_options()] - - self.assertIn('protocol', opts) - self.assertIn('identity-provider', opts) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_password.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_password.py deleted file mode 100644 index 2891d8f6b0..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_password.py +++ /dev/null @@ -1,68 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.auth.identity.generic import password -from keystoneclient.auth.identity import v2 -from keystoneclient.auth.identity import v3 -from keystoneclient.auth.identity.v3 import password as v3_password -from keystoneclient.tests.unit.auth import utils - - -class PasswordTests(utils.GenericPluginTestCase): - - PLUGIN_CLASS = password.Password - V2_PLUGIN_CLASS = v2.Password - V3_PLUGIN_CLASS = v3.Password - - def new_plugin(self, **kwargs): - kwargs.setdefault('username', uuid.uuid4().hex) - kwargs.setdefault('password', uuid.uuid4().hex) - return super(PasswordTests, self).new_plugin(**kwargs) - - def test_with_user_domain_params(self): - self.stub_discovery() - - self.assertCreateV3(domain_id=uuid.uuid4().hex, - user_domain_id=uuid.uuid4().hex) - - def test_v3_user_params_v2_url(self): - self.stub_discovery(v3=False) - self.assertDiscoveryFailure(user_domain_id=uuid.uuid4().hex) - - def test_options(self): - opts = [o.name for o in self.PLUGIN_CLASS.get_options()] - - allowed_opts = ['user-name', - 'user-domain-id', - 'user-domain-name', - 'user-id', - 'password', - - 'domain-id', - 'domain-name', - 'tenant-id', - 'tenant-name', - 'project-id', - 'project-name', - 'project-domain-id', - 'project-domain-name', - 'trust-id', - 'auth-url'] - - self.assertEqual(set(allowed_opts), set(opts)) - self.assertEqual(len(allowed_opts), len(opts)) - - def test_symbols(self): - self.assertIs(v3.Password, v3_password.Password) - self.assertIs(v3.PasswordMethod, v3_password.PasswordMethod) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_token.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_token.py deleted file mode 100644 index ce4c1cdc65..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_token.py +++ /dev/null @@ -1,52 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.auth.identity.generic import token -from keystoneclient.auth.identity import v2 -from keystoneclient.auth.identity import v3 -from keystoneclient.auth.identity.v3 import token as v3_token -from keystoneclient.tests.unit.auth import utils - - -class TokenTests(utils.GenericPluginTestCase): - - PLUGIN_CLASS = token.Token - V2_PLUGIN_CLASS = v2.Token - V3_PLUGIN_CLASS = v3.Token - - def new_plugin(self, **kwargs): - kwargs.setdefault('token', uuid.uuid4().hex) - return super(TokenTests, self).new_plugin(**kwargs) - - def test_options(self): - opts = [o.name for o in self.PLUGIN_CLASS.get_options()] - - allowed_opts = ['token', - 'domain-id', - 'domain-name', - 'tenant-id', - 'tenant-name', - 'project-id', - 'project-name', - 'project-domain-id', - 'project-domain-name', - 'trust-id', - 'auth-url'] - - self.assertEqual(set(allowed_opts), set(opts)) - self.assertEqual(len(allowed_opts), len(opts)) - - def test_symbols(self): - self.assertIs(v3.Token, v3_token.Token) - self.assertIs(v3.TokenMethod, v3_token.TokenMethod) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_token_endpoint.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_token_endpoint.py deleted file mode 100644 index b0be8f16be..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/test_token_endpoint.py +++ /dev/null @@ -1,63 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from testtools import matchers - -from keystoneclient.auth import token_endpoint -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -class TokenEndpointTest(utils.TestCase): - - TEST_TOKEN = 'aToken' - TEST_URL = 'http://server/prefix' - - def test_basic_case(self): - self.requests_mock.get(self.TEST_URL, text='body') - - a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN) - s = session.Session(auth=a) - - data = s.get(self.TEST_URL, authenticated=True) - - self.assertEqual(data.text, 'body') - self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN) - - def test_basic_endpoint_case(self): - self.stub_url('GET', ['p'], text='body') - a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN) - s = session.Session(auth=a) - - data = s.get('/p', - authenticated=True, - endpoint_filter={'service': 'identity'}) - - self.assertEqual(self.TEST_URL, a.get_endpoint(s)) - self.assertEqual('body', data.text) - self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN) - - def test_token_endpoint_options(self): - opt_names = [opt.name for opt in token_endpoint.Token.get_options()] - - self.assertThat(opt_names, matchers.HasLength(2)) - - self.assertIn('token', opt_names) - self.assertIn('endpoint', opt_names) - - def test_token_endpoint_user_id(self): - a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN) - s = session.Session() - - # we can't know this information about this sort of plugin - self.assertIsNone(a.get_user_id(s)) - self.assertIsNone(a.get_project_id(s)) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/auth/utils.py b/awx/lib/site-packages/keystoneclient/tests/unit/auth/utils.py deleted file mode 100644 index 87c2b62ffd..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/auth/utils.py +++ /dev/null @@ -1,200 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import functools -import uuid - -import mock -from oslo_config import cfg -import six - -from keystoneclient import access -from keystoneclient.auth import base -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -class MockPlugin(base.BaseAuthPlugin): - - INT_DESC = 'test int' - FLOAT_DESC = 'test float' - BOOL_DESC = 'test bool' - STR_DESC = 'test str' - STR_DEFAULT = uuid.uuid4().hex - - def __init__(self, **kwargs): - self._data = kwargs - - def __getitem__(self, key): - return self._data[key] - - def get_token(self, *args, **kwargs): - return 'aToken' - - def get_endpoint(self, *args, **kwargs): - return 'http://test' - - @classmethod - def get_options(cls): - return [ - cfg.IntOpt('a-int', default='3', help=cls.INT_DESC), - cfg.BoolOpt('a-bool', help=cls.BOOL_DESC), - cfg.FloatOpt('a-float', help=cls.FLOAT_DESC), - cfg.StrOpt('a-str', help=cls.STR_DESC, default=cls.STR_DEFAULT), - ] - - -class MockManager(object): - - def __init__(self, driver): - self.driver = driver - - -def mock_plugin(f): - @functools.wraps(f) - def inner(*args, **kwargs): - with mock.patch.object(base, 'get_plugin_class') as m: - m.return_value = MockPlugin - args = list(args) + [m] - return f(*args, **kwargs) - - return inner - - -class TestCase(utils.TestCase): - - GROUP = 'auth' - V2PASS = 'v2password' - V3TOKEN = 'v3token' - - a_int = 88 - a_float = 88.8 - a_bool = False - - TEST_VALS = {'a_int': a_int, - 'a_float': a_float, - 'a_bool': a_bool} - - def assertTestVals(self, plugin, vals=TEST_VALS): - for k, v in six.iteritems(vals): - self.assertEqual(v, plugin[k]) - - -class GenericPluginTestCase(utils.TestCase): - - TEST_URL = 'http://keystone.host:5000/' - - # OVERRIDE THESE IN SUB CLASSES - PLUGIN_CLASS = None - V2_PLUGIN_CLASS = None - V3_PLUGIN_CLASS = None - - def setUp(self): - super(GenericPluginTestCase, self).setUp() - - self.token_v2 = fixture.V2Token() - self.token_v3 = fixture.V3Token() - self.token_v3_id = uuid.uuid4().hex - self.session = session.Session() - - self.stub_url('POST', ['v2.0', 'tokens'], json=self.token_v2) - self.stub_url('POST', ['v3', 'auth', 'tokens'], - headers={'X-Subject-Token': self.token_v3_id}, - json=self.token_v3) - - def new_plugin(self, **kwargs): - kwargs.setdefault('auth_url', self.TEST_URL) - return self.PLUGIN_CLASS(**kwargs) - - def stub_discovery(self, base_url=None, **kwargs): - kwargs.setdefault('href', self.TEST_URL) - disc = fixture.DiscoveryList(**kwargs) - self.stub_url('GET', json=disc, base_url=base_url, status_code=300) - return disc - - def assertCreateV3(self, **kwargs): - auth = self.new_plugin(**kwargs) - auth_ref = auth.get_auth_ref(self.session) - self.assertIsInstance(auth_ref, access.AccessInfoV3) - self.assertEqual(self.TEST_URL + 'v3/auth/tokens', - self.requests_mock.last_request.url) - self.assertIsInstance(auth._plugin, self.V3_PLUGIN_CLASS) - return auth - - def assertCreateV2(self, **kwargs): - auth = self.new_plugin(**kwargs) - auth_ref = auth.get_auth_ref(self.session) - self.assertIsInstance(auth_ref, access.AccessInfoV2) - self.assertEqual(self.TEST_URL + 'v2.0/tokens', - self.requests_mock.last_request.url) - self.assertIsInstance(auth._plugin, self.V2_PLUGIN_CLASS) - return auth - - def assertDiscoveryFailure(self, **kwargs): - plugin = self.new_plugin(**kwargs) - self.assertRaises(exceptions.DiscoveryFailure, - plugin.get_auth_ref, - self.session) - - def test_create_v3_if_domain_params(self): - self.stub_discovery() - - self.assertCreateV3(domain_id=uuid.uuid4().hex) - self.assertCreateV3(domain_name=uuid.uuid4().hex) - self.assertCreateV3(project_name=uuid.uuid4().hex, - project_domain_name=uuid.uuid4().hex) - self.assertCreateV3(project_name=uuid.uuid4().hex, - project_domain_id=uuid.uuid4().hex) - - def test_create_v2_if_no_domain_params(self): - self.stub_discovery() - self.assertCreateV2() - self.assertCreateV2(project_id=uuid.uuid4().hex) - self.assertCreateV2(project_name=uuid.uuid4().hex) - self.assertCreateV2(tenant_id=uuid.uuid4().hex) - self.assertCreateV2(tenant_name=uuid.uuid4().hex) - - def test_v3_params_v2_url(self): - self.stub_discovery(v3=False) - self.assertDiscoveryFailure(domain_name=uuid.uuid4().hex) - - def test_v2_params_v3_url(self): - self.stub_discovery(v2=False) - self.assertCreateV3() - - def test_no_urls(self): - self.stub_discovery(v2=False, v3=False) - self.assertDiscoveryFailure() - - def test_path_based_url_v2(self): - self.stub_url('GET', ['v2.0'], status_code=403) - self.assertCreateV2(auth_url=self.TEST_URL + 'v2.0') - - def test_path_based_url_v3(self): - self.stub_url('GET', ['v3'], status_code=403) - self.assertCreateV3(auth_url=self.TEST_URL + 'v3') - - def test_disc_error_for_failure(self): - self.stub_url('GET', [], status_code=403) - self.assertDiscoveryFailure() - - def test_v3_plugin_from_failure(self): - url = self.TEST_URL + 'v3' - self.stub_url('GET', [], base_url=url, status_code=403) - self.assertCreateV3(auth_url=url) - - def test_unknown_discovery_version(self): - # make a v4 entry that's mostly the same as a v3 - self.stub_discovery(v2=False, v3_id='v4.0') - self.assertDiscoveryFailure() diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/client_fixtures.py b/awx/lib/site-packages/keystoneclient/tests/unit/client_fixtures.py deleted file mode 100644 index b226e32bb6..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/client_fixtures.py +++ /dev/null @@ -1,597 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -import fixtures -from oslo_serialization import jsonutils -from oslo_utils import timeutils -import six -import testresources - -from keystoneclient.common import cms -from keystoneclient import utils - - -TESTDIR = os.path.dirname(os.path.abspath(__file__)) -ROOTDIR = os.path.normpath(os.path.join(TESTDIR, '..', '..', '..')) -CERTDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'certs') -CMSDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'cms') -KEYDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'private') - - -def _hash_signed_token_safe(signed_text, **kwargs): - if isinstance(signed_text, six.text_type): - signed_text = signed_text.encode('utf-8') - return utils.hash_signed_token(signed_text, **kwargs) - - -class Examples(fixtures.Fixture): - """Example tokens and certs loaded from the examples directory. - - To use this class correctly, the module needs to override the test suite - class to use testresources.OptimisingTestSuite (otherwise the files will - be read on every test). This is done by defining a load_tests function - in the module, like this: - - def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) - - (see http://docs.python.org/2/library/unittest.html#load-tests-protocol ) - - """ - - def setUp(self): - super(Examples, self).setUp() - - # The data for several tests are signed using openssl and are stored in - # files in the signing subdirectory. In order to keep the values - # consistent between the tests and the signed documents, we read them - # in for use in the tests. - with open(os.path.join(CMSDIR, 'auth_token_scoped.json')) as f: - self.TOKEN_SCOPED_DATA = cms.cms_to_token(f.read()) - - with open(os.path.join(CMSDIR, 'auth_token_scoped.pem')) as f: - self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read()) - self.SIGNED_TOKEN_SCOPED_HASH = _hash_signed_token_safe( - self.SIGNED_TOKEN_SCOPED) - self.SIGNED_TOKEN_SCOPED_HASH_SHA256 = _hash_signed_token_safe( - self.SIGNED_TOKEN_SCOPED, mode='sha256') - with open(os.path.join(CMSDIR, 'auth_token_unscoped.pem')) as f: - self.SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_scoped.pem')) as f: - self.SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read()) - self.SIGNED_v3_TOKEN_SCOPED_HASH = _hash_signed_token_safe( - self.SIGNED_v3_TOKEN_SCOPED) - self.SIGNED_v3_TOKEN_SCOPED_HASH_SHA256 = _hash_signed_token_safe( - self.SIGNED_v3_TOKEN_SCOPED, mode='sha256') - with open(os.path.join(CMSDIR, 'auth_token_revoked.pem')) as f: - self.REVOKED_TOKEN = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_scoped_expired.pem')) as f: - self.SIGNED_TOKEN_SCOPED_EXPIRED = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_revoked.pem')) as f: - self.REVOKED_v3_TOKEN = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_scoped.pkiz')) as f: - self.SIGNED_TOKEN_SCOPED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_unscoped.pkiz')) as f: - self.SIGNED_TOKEN_UNSCOPED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_scoped.pkiz')) as f: - self.SIGNED_v3_TOKEN_SCOPED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_token_revoked.pkiz')) as f: - self.REVOKED_TOKEN_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, - 'auth_token_scoped_expired.pkiz')) as f: - self.SIGNED_TOKEN_SCOPED_EXPIRED_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'auth_v3_token_revoked.pkiz')) as f: - self.REVOKED_v3_TOKEN_PKIZ = cms.cms_to_token(f.read()) - with open(os.path.join(CMSDIR, 'revocation_list.json')) as f: - self.REVOCATION_LIST = jsonutils.loads(f.read()) - with open(os.path.join(CMSDIR, 'revocation_list.pem')) as f: - self.SIGNED_REVOCATION_LIST = jsonutils.dumps({'signed': f.read()}) - - self.SIGNING_CERT_FILE = os.path.join(CERTDIR, 'signing_cert.pem') - with open(self.SIGNING_CERT_FILE) as f: - self.SIGNING_CERT = f.read() - - self.KERBEROS_BIND = 'USER@REALM' - - self.SIGNING_KEY_FILE = os.path.join(KEYDIR, 'signing_key.pem') - with open(self.SIGNING_KEY_FILE) as f: - self.SIGNING_KEY = f.read() - - self.SIGNING_CA_FILE = os.path.join(CERTDIR, 'cacert.pem') - with open(self.SIGNING_CA_FILE) as f: - self.SIGNING_CA = f.read() - - self.UUID_TOKEN_DEFAULT = "ec6c0710ec2f471498484c1b53ab4f9d" - self.UUID_TOKEN_NO_SERVICE_CATALOG = '8286720fbe4941e69fa8241723bb02df' - self.UUID_TOKEN_UNSCOPED = '731f903721c14827be7b2dc912af7776' - self.UUID_TOKEN_BIND = '3fc54048ad64405c98225ce0897af7c5' - self.UUID_TOKEN_UNKNOWN_BIND = '8885fdf4d42e4fb9879e6379fa1eaf48' - self.VALID_DIABLO_TOKEN = 'b0cf19b55dbb4f20a6ee18e6c6cf1726' - self.v3_UUID_TOKEN_DEFAULT = '5603457654b346fdbb93437bfe76f2f1' - self.v3_UUID_TOKEN_UNSCOPED = 'd34835fdaec447e695a0a024d84f8d79' - self.v3_UUID_TOKEN_DOMAIN_SCOPED = 'e8a7b63aaa4449f38f0c5c05c3581792' - self.v3_UUID_TOKEN_BIND = '2f61f73e1c854cbb9534c487f9bd63c2' - self.v3_UUID_TOKEN_UNKNOWN_BIND = '7ed9781b62cd4880b8d8c6788ab1d1e2' - - revoked_token = self.REVOKED_TOKEN - if isinstance(revoked_token, six.text_type): - revoked_token = revoked_token.encode('utf-8') - self.REVOKED_TOKEN_HASH = utils.hash_signed_token(revoked_token) - self.REVOKED_TOKEN_HASH_SHA256 = utils.hash_signed_token(revoked_token, - mode='sha256') - self.REVOKED_TOKEN_LIST = ( - {'revoked': [{'id': self.REVOKED_TOKEN_HASH, - 'expires': timeutils.utcnow()}]}) - self.REVOKED_TOKEN_LIST_JSON = jsonutils.dumps(self.REVOKED_TOKEN_LIST) - - revoked_v3_token = self.REVOKED_v3_TOKEN - if isinstance(revoked_v3_token, six.text_type): - revoked_v3_token = revoked_v3_token.encode('utf-8') - self.REVOKED_v3_TOKEN_HASH = utils.hash_signed_token(revoked_v3_token) - hash = utils.hash_signed_token(revoked_v3_token, mode='sha256') - self.REVOKED_v3_TOKEN_HASH_SHA256 = hash - self.REVOKED_v3_TOKEN_LIST = ( - {'revoked': [{'id': self.REVOKED_v3_TOKEN_HASH, - 'expires': timeutils.utcnow()}]}) - self.REVOKED_v3_TOKEN_LIST_JSON = jsonutils.dumps( - self.REVOKED_v3_TOKEN_LIST) - - revoked_token_pkiz = self.REVOKED_TOKEN_PKIZ - if isinstance(revoked_token_pkiz, six.text_type): - revoked_token_pkiz = revoked_token_pkiz.encode('utf-8') - self.REVOKED_TOKEN_PKIZ_HASH = utils.hash_signed_token( - revoked_token_pkiz) - revoked_v3_token_pkiz = self.REVOKED_v3_TOKEN_PKIZ - if isinstance(revoked_v3_token_pkiz, six.text_type): - revoked_v3_token_pkiz = revoked_v3_token_pkiz.encode('utf-8') - self.REVOKED_v3_PKIZ_TOKEN_HASH = utils.hash_signed_token( - revoked_v3_token_pkiz) - - self.REVOKED_TOKEN_PKIZ_LIST = ( - {'revoked': [{'id': self.REVOKED_TOKEN_PKIZ_HASH, - 'expires': timeutils.utcnow()}, - {'id': self.REVOKED_v3_PKIZ_TOKEN_HASH, - 'expires': timeutils.utcnow()}, - ]}) - self.REVOKED_TOKEN_PKIZ_LIST_JSON = jsonutils.dumps( - self.REVOKED_TOKEN_PKIZ_LIST) - - self.SIGNED_TOKEN_SCOPED_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_SCOPED) - self.SIGNED_TOKEN_UNSCOPED_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_UNSCOPED) - self.SIGNED_v3_TOKEN_SCOPED_KEY = cms.cms_hash_token( - self.SIGNED_v3_TOKEN_SCOPED) - - self.SIGNED_TOKEN_SCOPED_PKIZ_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_SCOPED_PKIZ) - self.SIGNED_TOKEN_UNSCOPED_PKIZ_KEY = cms.cms_hash_token( - self.SIGNED_TOKEN_UNSCOPED_PKIZ) - self.SIGNED_v3_TOKEN_SCOPED_PKIZ_KEY = cms.cms_hash_token( - self.SIGNED_v3_TOKEN_SCOPED_PKIZ) - - self.INVALID_SIGNED_TOKEN = ( - "MIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" - "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" - "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "0000000000000000000000000000000000000000000000000000000000000000" - "1111111111111111111111111111111111111111111111111111111111111111" - "2222222222222222222222222222222222222222222222222222222222222222" - "3333333333333333333333333333333333333333333333333333333333333333" - "4444444444444444444444444444444444444444444444444444444444444444" - "5555555555555555555555555555555555555555555555555555555555555555" - "6666666666666666666666666666666666666666666666666666666666666666" - "7777777777777777777777777777777777777777777777777777777777777777" - "8888888888888888888888888888888888888888888888888888888888888888" - "9999999999999999999999999999999999999999999999999999999999999999" - "0000000000000000000000000000000000000000000000000000000000000000") - - self.INVALID_SIGNED_PKIZ_TOKEN = ( - "PKIZ_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" - "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" - "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" - "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "0000000000000000000000000000000000000000000000000000000000000000" - "1111111111111111111111111111111111111111111111111111111111111111" - "2222222222222222222222222222222222222222222222222222222222222222" - "3333333333333333333333333333333333333333333333333333333333333333" - "4444444444444444444444444444444444444444444444444444444444444444" - "5555555555555555555555555555555555555555555555555555555555555555" - "6666666666666666666666666666666666666666666666666666666666666666" - "7777777777777777777777777777777777777777777777777777777777777777" - "8888888888888888888888888888888888888888888888888888888888888888" - "9999999999999999999999999999999999999999999999999999999999999999" - "0000000000000000000000000000000000000000000000000000000000000000") - - # JSON responses keyed by token ID - self.TOKEN_RESPONSES = { - self.UUID_TOKEN_DEFAULT: { - 'access': { - 'token': { - 'id': self.UUID_TOKEN_DEFAULT, - 'expires': '2020-01-01T00:00:10.000123Z', - 'tenant': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - }, - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - 'serviceCatalog': {} - }, - }, - self.VALID_DIABLO_TOKEN: { - 'access': { - 'token': { - 'id': self.VALID_DIABLO_TOKEN, - 'expires': '2020-01-01T00:00:10.000123Z', - 'tenantId': 'tenant_id1', - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - }, - }, - self.UUID_TOKEN_UNSCOPED: { - 'access': { - 'token': { - 'id': self.UUID_TOKEN_UNSCOPED, - 'expires': '2020-01-01T00:00:10.000123Z', - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - }, - }, - self.UUID_TOKEN_NO_SERVICE_CATALOG: { - 'access': { - 'token': { - 'id': 'valid-token', - 'expires': '2020-01-01T00:00:10.000123Z', - 'tenant': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - }, - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - } - }, - }, - self.UUID_TOKEN_BIND: { - 'access': { - 'token': { - 'bind': {'kerberos': self.KERBEROS_BIND}, - 'id': self.UUID_TOKEN_BIND, - 'expires': '2020-01-01T00:00:10.000123Z', - 'tenant': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - }, - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - 'serviceCatalog': {} - }, - }, - self.UUID_TOKEN_UNKNOWN_BIND: { - 'access': { - 'token': { - 'bind': {'FOO': 'BAR'}, - 'id': self.UUID_TOKEN_UNKNOWN_BIND, - 'expires': '2020-01-01T00:00:10.000123Z', - 'tenant': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - }, - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - 'serviceCatalog': {} - }, - }, - self.v3_UUID_TOKEN_DEFAULT: { - 'token': { - 'expires_at': '2020-01-01T00:00:10.000123Z', - 'methods': ['password'], - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'project': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'roles': [ - {'name': 'role1', 'id': 'Role1'}, - {'name': 'role2', 'id': 'Role2'}, - ], - 'catalog': {} - } - }, - self.v3_UUID_TOKEN_UNSCOPED: { - 'token': { - 'expires_at': '2020-01-01T00:00:10.000123Z', - 'methods': ['password'], - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - } - } - }, - self.v3_UUID_TOKEN_DOMAIN_SCOPED: { - 'token': { - 'expires_at': '2020-01-01T00:00:10.000123Z', - 'methods': ['password'], - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1', - }, - 'roles': [ - {'name': 'role1', 'id': 'Role1'}, - {'name': 'role2', 'id': 'Role2'}, - ], - 'catalog': {} - } - }, - self.SIGNED_TOKEN_SCOPED_KEY: { - 'access': { - 'token': { - 'id': self.SIGNED_TOKEN_SCOPED_KEY, - 'expires': '2020-01-01T00:00:10.000123Z', - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'tenantId': 'tenant_id1', - 'tenantName': 'tenant_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - }, - }, - self.SIGNED_TOKEN_UNSCOPED_KEY: { - 'access': { - 'token': { - 'id': self.SIGNED_TOKEN_UNSCOPED_KEY, - 'expires': '2020-01-01T00:00:10.000123Z', - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - }, - }, - self.SIGNED_v3_TOKEN_SCOPED_KEY: { - 'token': { - 'expires_at': '2020-01-01T00:00:10.000123Z', - 'methods': ['password'], - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'project': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'} - ], - 'catalog': {} - } - }, - self.v3_UUID_TOKEN_BIND: { - 'token': { - 'bind': {'kerberos': self.KERBEROS_BIND}, - 'methods': ['password'], - 'expires_at': '2020-01-01T00:00:10.000123Z', - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'project': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'roles': [ - {'name': 'role1', 'id': 'Role1'}, - {'name': 'role2', 'id': 'Role2'}, - ], - 'catalog': {} - } - }, - self.v3_UUID_TOKEN_UNKNOWN_BIND: { - 'token': { - 'bind': {'FOO': 'BAR'}, - 'expires_at': '2020-01-01T00:00:10.000123Z', - 'methods': ['password'], - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'project': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'roles': [ - {'name': 'role1', 'id': 'Role1'}, - {'name': 'role2', 'id': 'Role2'}, - ], - 'catalog': {} - } - }, - } - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_PKIZ_KEY] = ( - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED_KEY]) - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED_PKIZ_KEY] = ( - self.TOKEN_RESPONSES[self.SIGNED_TOKEN_UNSCOPED_KEY]) - self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_PKIZ_KEY] = ( - self.TOKEN_RESPONSES[self.SIGNED_v3_TOKEN_SCOPED_KEY]) - - self.JSON_TOKEN_RESPONSES = dict([(k, jsonutils.dumps(v)) for k, v in - six.iteritems(self.TOKEN_RESPONSES)]) - - -EXAMPLES_RESOURCE = testresources.FixtureResource(Examples()) - - -class HackingCode(fixtures.Fixture): - """A fixture to house the various code examples for the keystoneclient - hacking style checks. - """ - - oslo_namespace_imports = { - 'code': """ - import oslo.utils - import oslo_utils - import oslo.utils.encodeutils - import oslo_utils.encodeutils - from oslo import utils - from oslo.utils import encodeutils - from oslo_utils import encodeutils - - import oslo.serialization - import oslo_serialization - import oslo.serialization.jsonutils - import oslo_serialization.jsonutils - from oslo import serialization - from oslo.serialization import jsonutils - from oslo_serialization import jsonutils - - import oslo.config - import oslo_config - import oslo.config.cfg - import oslo_config.cfg - from oslo import config - from oslo.config import cfg - from oslo_config import cfg - - import oslo.i18n - import oslo_i18n - import oslo.i18n.log - import oslo_i18n.log - from oslo import i18n - from oslo.i18n import log - from oslo_i18n import log - """, - 'expected_errors': [ - (1, 0, 'K333'), - (3, 0, 'K333'), - (5, 0, 'K333'), - (6, 0, 'K333'), - (9, 0, 'K333'), - (11, 0, 'K333'), - (13, 0, 'K333'), - (14, 0, 'K333'), - (17, 0, 'K333'), - (19, 0, 'K333'), - (21, 0, 'K333'), - (22, 0, 'K333'), - (25, 0, 'K333'), - (27, 0, 'K333'), - (29, 0, 'K333'), - (30, 0, 'K333'), - ], - } diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/generic/__init__.py b/awx/lib/site-packages/keystoneclient/tests/unit/generic/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/generic/test_client.py b/awx/lib/site-packages/keystoneclient/tests/unit/generic/test_client.py deleted file mode 100644 index 6eb6836e52..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/generic/test_client.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_serialization import jsonutils - -from keystoneclient.generic import client -from keystoneclient.tests.unit import utils - -BASE_HOST = 'http://keystone.example.com' -BASE_URL = "%s:5000/" % BASE_HOST -V2_URL = "%sv2.0" % BASE_URL - -EXTENSION_NAMESPACE = "http://docs.openstack.org/identity/api/ext/OS-FAKE/v1.0" -EXTENSION_DESCRIBED = {"href": "https://github.com/openstack/identity-api", - "rel": "describedby", - "type": "text/html"} - -EXTENSION_ALIAS_FOO = "OS-FAKE-FOO" -EXTENSION_NAME_FOO = "OpenStack Keystone Fake Extension Foo" -EXTENSION_FOO = {"alias": EXTENSION_ALIAS_FOO, - "description": "Fake Foo extension to V2.0 API.", - "links": [EXTENSION_DESCRIBED], - "name": EXTENSION_NAME_FOO, - "namespace": EXTENSION_NAMESPACE, - "updated": '2014-01-08T00:00:00Z'} - -EXTENSION_ALIAS_BAR = "OS-FAKE-BAR" -EXTENSION_NAME_BAR = "OpenStack Keystone Fake Extension Bar" -EXTENSION_BAR = {"alias": EXTENSION_ALIAS_BAR, - "description": "Fake Bar extension to V2.0 API.", - "links": [EXTENSION_DESCRIBED], - "name": EXTENSION_NAME_BAR, - "namespace": EXTENSION_NAMESPACE, - "updated": '2014-01-08T00:00:00Z'} - - -def _create_extension_list(extensions): - return jsonutils.dumps({'extensions': {'values': extensions}}) - - -EXTENSION_LIST = _create_extension_list([EXTENSION_FOO, EXTENSION_BAR]) - - -class ClientDiscoveryTests(utils.TestCase): - - def test_discover_extensions_v2(self): - self.requests_mock.get("%s/extensions" % V2_URL, text=EXTENSION_LIST) - extensions = client.Client().discover_extensions(url=V2_URL) - self.assertIn(EXTENSION_ALIAS_FOO, extensions) - self.assertEqual(extensions[EXTENSION_ALIAS_FOO], EXTENSION_NAME_FOO) - self.assertIn(EXTENSION_ALIAS_BAR, extensions) - self.assertEqual(extensions[EXTENSION_ALIAS_BAR], EXTENSION_NAME_BAR) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/generic/test_shell.py b/awx/lib/site-packages/keystoneclient/tests/unit/generic/test_shell.py deleted file mode 100644 index ad457aad3d..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/generic/test_shell.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from six import moves - -from keystoneclient.generic import shell -from keystoneclient.tests.unit import utils - - -class DoDiscoverTest(utils.TestCase): - """Unit tests for do_discover function.""" - foo_version = { - 'id': 'foo_id', - 'status': 'foo_status', - 'url': 'http://foo/url', - } - bar_version = { - 'id': 'bar_id', - 'status': 'bar_status', - 'url': 'http://bar/url', - } - foo_extension = { - 'foo': 'foo_extension', - 'message': 'extension_message', - 'bar': 'bar_extension', - } - stub_message = 'This is a stub message' - - def setUp(self): - super(DoDiscoverTest, self).setUp() - - self.client_mock = mock.Mock() - self.client_mock.discover.return_value = {} - - def _execute_discover(self): - """Call do_discover function and capture output - - :returns: captured output is returned - """ - with mock.patch('sys.stdout', - new_callable=moves.StringIO) as mock_stdout: - shell.do_discover(self.client_mock, args=None) - output = mock_stdout.getvalue() - return output - - def _check_version_print(self, output, version): - """Checks all api version's parameters are present in output.""" - self.assertIn(version['id'], output) - self.assertIn(version['status'], output) - self.assertIn(version['url'], output) - - def test_no_keystones(self): - # No servers configured for client, - # corresponding message should be printed - output = self._execute_discover() - self.assertIn('No Keystone-compatible endpoint found', output) - - def test_endpoint(self): - # Endpoint is configured for client, - # client's discover method should be called with that value - self.client_mock.endpoint = 'Some non-empty value' - shell.do_discover(self.client_mock, args=None) - self.client_mock.discover.assert_called_with(self.client_mock.endpoint) - - def test_auth_url(self): - # No endpoint provided for client, but there is an auth_url - # client's discover method should be called with auth_url value - self.client_mock.endpoint = False - self.client_mock.auth_url = 'Some non-empty value' - shell.do_discover(self.client_mock, args=None) - self.client_mock.discover.assert_called_with(self.client_mock.auth_url) - - def test_empty(self): - # No endpoint or auth_url is configured for client. - # client.discover() should be called without parameters - self.client_mock.endpoint = False - self.client_mock.auth_url = False - shell.do_discover(self.client_mock, args=None) - self.client_mock.discover.assert_called_with() - - def test_message(self): - # If client.discover() result contains message - it should be printed - self.client_mock.discover.return_value = {'message': self.stub_message} - output = self._execute_discover() - self.assertIn(self.stub_message, output) - - def test_versions(self): - # Every version in client.discover() result should be printed - # and client.discover_extension() should be called on its url - self.client_mock.discover.return_value = { - 'foo': self.foo_version, - 'bar': self.bar_version, - } - self.client_mock.discover_extensions.return_value = {} - output = self._execute_discover() - self._check_version_print(output, self.foo_version) - self._check_version_print(output, self.bar_version) - - discover_extension_calls = [ - mock.call(self.foo_version['url']), - mock.call(self.bar_version['url']), - ] - - self.client_mock.discover_extensions.assert_has_calls( - discover_extension_calls, - any_order=True) - - def test_extensions(self): - # Every extension's parameters should be printed - # Extension's message should be omitted - self.client_mock.discover.return_value = {'foo': self.foo_version} - self.client_mock.discover_extensions.return_value = self.foo_extension - output = self._execute_discover() - self.assertIn(self.foo_extension['foo'], output) - self.assertIn(self.foo_extension['bar'], output) - self.assertNotIn(self.foo_extension['message'], output) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_auth_token_middleware.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_auth_token_middleware.py deleted file mode 100644 index 32a322d6ae..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_auth_token_middleware.py +++ /dev/null @@ -1,1945 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import calendar -import datetime -import json -import os -import shutil -import stat -import tempfile -import time -import uuid - -import fixtures -import iso8601 -import mock -from oslo_serialization import jsonutils -from oslo_utils import timeutils -from requests_mock.contrib import fixture as mock_fixture -import six -from six.moves.urllib import parse as urlparse -import testresources -import testtools -from testtools import matchers -import webob - -from keystoneclient import access -from keystoneclient.common import cms -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient.middleware import auth_token -from keystoneclient.openstack.common import memorycache -from keystoneclient.tests.unit import client_fixtures -from keystoneclient.tests.unit import utils - - -EXPECTED_V2_DEFAULT_ENV_RESPONSE = { - 'HTTP_X_IDENTITY_STATUS': 'Confirmed', - 'HTTP_X_TENANT_ID': 'tenant_id1', - 'HTTP_X_TENANT_NAME': 'tenant_name1', - 'HTTP_X_USER_ID': 'user_id1', - 'HTTP_X_USER_NAME': 'user_name1', - 'HTTP_X_ROLES': 'role1,role2', - 'HTTP_X_USER': 'user_name1', # deprecated (diablo-compat) - 'HTTP_X_TENANT': 'tenant_name1', # deprecated (diablo-compat) - 'HTTP_X_ROLE': 'role1,role2', # deprecated (diablo-compat) -} - - -BASE_HOST = 'https://keystone.example.com:1234' -BASE_URI = '%s/testadmin' % BASE_HOST -FAKE_ADMIN_TOKEN_ID = 'admin_token2' -FAKE_ADMIN_TOKEN = jsonutils.dumps( - {'access': {'token': {'id': FAKE_ADMIN_TOKEN_ID, - 'expires': '2022-10-03T16:58:01Z'}}}) - - -VERSION_LIST_v2 = jsonutils.dumps(fixture.DiscoveryList(href=BASE_URI, - v3=False)) -VERSION_LIST_v3 = jsonutils.dumps(fixture.DiscoveryList(href=BASE_URI)) - -ERROR_TOKEN = '7ae290c2a06244c4b41692eb4e9225f2' -MEMCACHED_SERVERS = ['localhost:11211'] -MEMCACHED_AVAILABLE = None - - -def memcached_available(): - """Do a sanity check against memcached. - - Returns ``True`` if the following conditions are met (otherwise, returns - ``False``): - - - ``python-memcached`` is installed - - a usable ``memcached`` instance is available via ``MEMCACHED_SERVERS`` - - the client is able to set and get a key/value pair - - """ - global MEMCACHED_AVAILABLE - - if MEMCACHED_AVAILABLE is None: - try: - import memcache - c = memcache.Client(MEMCACHED_SERVERS) - c.set('ping', 'pong', time=1) - MEMCACHED_AVAILABLE = c.get('ping') == 'pong' - except ImportError: - MEMCACHED_AVAILABLE = False - - return MEMCACHED_AVAILABLE - - -def cleanup_revoked_file(filename): - try: - os.remove(filename) - except OSError: - pass - - -class TimezoneFixture(fixtures.Fixture): - @staticmethod - def supported(): - # tzset is only supported on Unix. - return hasattr(time, 'tzset') - - def __init__(self, new_tz): - super(TimezoneFixture, self).__init__() - self.tz = new_tz - self.old_tz = os.environ.get('TZ') - - def setUp(self): - super(TimezoneFixture, self).setUp() - if not self.supported(): - raise NotImplementedError('timezone override is not supported.') - os.environ['TZ'] = self.tz - time.tzset() - self.addCleanup(self.cleanup) - - def cleanup(self): - if self.old_tz is not None: - os.environ['TZ'] = self.old_tz - elif 'TZ' in os.environ: - del os.environ['TZ'] - time.tzset() - - -class TimeFixture(fixtures.Fixture): - - def __init__(self, new_time, normalize=True): - super(TimeFixture, self).__init__() - if isinstance(new_time, six.string_types): - new_time = timeutils.parse_isotime(new_time) - if normalize: - new_time = timeutils.normalize_time(new_time) - self.new_time = new_time - - def setUp(self): - super(TimeFixture, self).setUp() - timeutils.set_time_override(self.new_time) - self.addCleanup(timeutils.clear_time_override) - - -class FakeApp(object): - """This represents a WSGI app protected by the auth_token middleware.""" - - SUCCESS = b'SUCCESS' - - def __init__(self, expected_env=None): - self.expected_env = dict(EXPECTED_V2_DEFAULT_ENV_RESPONSE) - - if expected_env: - self.expected_env.update(expected_env) - - def __call__(self, env, start_response): - for k, v in self.expected_env.items(): - assert env[k] == v, '%s != %s' % (env[k], v) - - resp = webob.Response() - resp.body = FakeApp.SUCCESS - return resp(env, start_response) - - -class v3FakeApp(FakeApp): - """This represents a v3 WSGI app protected by the auth_token middleware.""" - - def __init__(self, expected_env=None): - - # with v3 additions, these are for the DEFAULT TOKEN - v3_default_env_additions = { - 'HTTP_X_PROJECT_ID': 'tenant_id1', - 'HTTP_X_PROJECT_NAME': 'tenant_name1', - 'HTTP_X_PROJECT_DOMAIN_ID': 'domain_id1', - 'HTTP_X_PROJECT_DOMAIN_NAME': 'domain_name1', - 'HTTP_X_USER_DOMAIN_ID': 'domain_id1', - 'HTTP_X_USER_DOMAIN_NAME': 'domain_name1' - } - - if expected_env: - v3_default_env_additions.update(expected_env) - - super(v3FakeApp, self).__init__(v3_default_env_additions) - - -class BaseAuthTokenMiddlewareTest(testtools.TestCase): - """Base test class for auth_token middleware. - - All the tests allow for running with auth_token - configured for receiving v2 or v3 tokens, with the - choice being made by passing configuration data into - setUp(). - - The base class will, by default, run all the tests - expecting v2 token formats. Child classes can override - this to specify, for instance, v3 format. - - """ - def setUp(self, expected_env=None, auth_version=None, fake_app=None): - testtools.TestCase.setUp(self) - - self.expected_env = expected_env or dict() - self.fake_app = fake_app or FakeApp - self.middleware = None - - self.conf = { - 'identity_uri': 'https://keystone.example.com:1234/testadmin/', - 'signing_dir': client_fixtures.CERTDIR, - 'auth_version': auth_version, - 'auth_uri': 'https://keystone.example.com:1234', - } - - self.auth_version = auth_version - self.response_status = None - self.response_headers = None - - self.requests_mock = self.useFixture(mock_fixture.Fixture()) - - def set_middleware(self, expected_env=None, conf=None): - """Configure the class ready to call the auth_token middleware. - - Set up the various fake items needed to run the middleware. - Individual tests that need to further refine these can call this - function to override the class defaults. - - """ - if conf: - self.conf.update(conf) - - if expected_env: - self.expected_env.update(expected_env) - - self.middleware = auth_token.AuthProtocol( - self.fake_app(self.expected_env), self.conf) - self.middleware._iso8601 = iso8601 - - with tempfile.NamedTemporaryFile(dir=self.middleware.signing_dirname, - delete=False) as f: - pass - self.middleware.revoked_file_name = f.name - - self.addCleanup(cleanup_revoked_file, - self.middleware.revoked_file_name) - - self.middleware.token_revocation_list = jsonutils.dumps( - {"revoked": [], "extra": "success"}) - - def start_fake_response(self, status, headers): - self.response_status = int(status.split(' ', 1)[0]) - self.response_headers = dict(headers) - - def assertLastPath(self, path): - if path: - parts = urlparse.urlparse(self.requests_mock.last_request.url) - self.assertEqual(path, parts.path) - else: - self.assertIsNone(self.requests_mock.last_request) - - -class MultiStepAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_fetch_revocation_list_with_expire(self): - self.set_middleware() - - # Get a token, then try to retrieve revocation list and get a 401. - # Get a new token, try to retrieve revocation list and return 200. - self.requests_mock.post("%s/v2.0/tokens" % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - text = self.examples.SIGNED_REVOCATION_LIST - self.requests_mock.get("%s/v2.0/tokens/revoked" % BASE_URI, - response_list=[{'status_code': 401}, - {'text': text}]) - - fetched_list = jsonutils.loads(self.middleware.fetch_revocation_list()) - self.assertEqual(fetched_list, self.examples.REVOCATION_LIST) - - # Check that 4 requests have been made - self.assertEqual(len(self.requests_mock.request_history), 4) - - -class DiabloAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - """Auth Token middleware should understand Diablo keystone responses.""" - def setUp(self): - # pre-diablo only had Tenant ID, which was also the Name - expected_env = { - 'HTTP_X_TENANT_ID': 'tenant_id1', - 'HTTP_X_TENANT_NAME': 'tenant_id1', - # now deprecated (diablo-compat) - 'HTTP_X_TENANT': 'tenant_id1', - } - - super(DiabloAuthTokenMiddlewareTest, self).setUp( - expected_env=expected_env) - - self.requests_mock.get("%s/" % BASE_URI, - text=VERSION_LIST_v2, - status_code=300) - - self.requests_mock.post("%s/v2.0/tokens" % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - self.token_id = self.examples.VALID_DIABLO_TOKEN - token_response = self.examples.JSON_TOKEN_RESPONSES[self.token_id] - - url = '%s/v2.0/tokens/%s' % (BASE_URI, self.token_id) - self.requests_mock.get(url, text=token_response) - - self.set_middleware() - - def test_valid_diablo_response(self): - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.token_id - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - self.assertIn('keystone.token_info', req.environ) - - -class NoMemcacheAuthToken(BaseAuthTokenMiddlewareTest): - """These tests will not have the memcache module available.""" - - def setUp(self): - super(NoMemcacheAuthToken, self).setUp() - self.useFixture(utils.DisableModuleFixture('memcache')) - - def test_nomemcache(self): - conf = { - 'admin_token': 'admin_token1', - 'auth_host': 'keystone.example.com', - 'auth_port': 1234, - 'memcached_servers': MEMCACHED_SERVERS, - 'auth_uri': 'https://keystone.example.com:1234', - } - - auth_token.AuthProtocol(FakeApp(), conf) - - -class CachePoolTest(BaseAuthTokenMiddlewareTest): - def test_use_cache_from_env(self): - """If `swift.cache` is set in the environment and `cache` is set in the - config then the env cache is used. - """ - env = {'swift.cache': 'CACHE_TEST'} - conf = { - 'cache': 'swift.cache' - } - self.set_middleware(conf=conf) - self.middleware._token_cache.initialize(env) - with self.middleware._token_cache._cache_pool.reserve() as cache: - self.assertEqual(cache, 'CACHE_TEST') - - def test_not_use_cache_from_env(self): - """If `swift.cache` is set in the environment but `cache` isn't set in - the config then the env cache isn't used. - """ - self.set_middleware() - env = {'swift.cache': 'CACHE_TEST'} - self.middleware._token_cache.initialize(env) - with self.middleware._token_cache._cache_pool.reserve() as cache: - self.assertNotEqual(cache, 'CACHE_TEST') - - def test_multiple_context_managers_share_single_client(self): - self.set_middleware() - token_cache = self.middleware._token_cache - env = {} - token_cache.initialize(env) - - caches = [] - - with token_cache._cache_pool.reserve() as cache: - caches.append(cache) - - with token_cache._cache_pool.reserve() as cache: - caches.append(cache) - - self.assertIs(caches[0], caches[1]) - self.assertEqual(set(caches), set(token_cache._cache_pool)) - - def test_nested_context_managers_create_multiple_clients(self): - self.set_middleware() - env = {} - self.middleware._token_cache.initialize(env) - token_cache = self.middleware._token_cache - - with token_cache._cache_pool.reserve() as outer_cache: - with token_cache._cache_pool.reserve() as inner_cache: - self.assertNotEqual(outer_cache, inner_cache) - - self.assertEqual( - set([inner_cache, outer_cache]), - set(token_cache._cache_pool)) - - -class GeneralAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - """These tests are not affected by the token format - (see CommonAuthTokenMiddlewareTest). - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_will_expire_soon(self): - tenseconds = datetime.datetime.utcnow() + datetime.timedelta( - seconds=10) - self.assertTrue(auth_token.will_expire_soon(tenseconds)) - fortyseconds = datetime.datetime.utcnow() + datetime.timedelta( - seconds=40) - self.assertFalse(auth_token.will_expire_soon(fortyseconds)) - - def test_token_is_v2_accepts_v2(self): - token = self.examples.UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertTrue(auth_token._token_is_v2(token_response)) - - def test_token_is_v2_rejects_v3(self): - token = self.examples.v3_UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertFalse(auth_token._token_is_v2(token_response)) - - def test_token_is_v3_rejects_v2(self): - token = self.examples.UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertFalse(auth_token._token_is_v3(token_response)) - - def test_token_is_v3_accepts_v3(self): - token = self.examples.v3_UUID_TOKEN_DEFAULT - token_response = self.examples.TOKEN_RESPONSES[token] - self.assertTrue(auth_token._token_is_v3(token_response)) - - @testtools.skipUnless(memcached_available(), 'memcached not available') - def test_encrypt_cache_data(self): - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_security_strategy': 'encrypt', - 'memcache_secret_key': 'mysecret' - } - self.set_middleware(conf=conf) - token = b'my_token' - some_time_later = timeutils.utcnow() + datetime.timedelta(hours=4) - expires = timeutils.strtime(some_time_later) - data = ('this_data', expires) - token_cache = self.middleware._token_cache - token_cache.initialize({}) - token_cache._cache_store(token, data) - self.assertEqual(token_cache._cache_get(token), data[0]) - - @testtools.skipUnless(memcached_available(), 'memcached not available') - def test_sign_cache_data(self): - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_security_strategy': 'mac', - 'memcache_secret_key': 'mysecret' - } - self.set_middleware(conf=conf) - token = b'my_token' - some_time_later = timeutils.utcnow() + datetime.timedelta(hours=4) - expires = timeutils.strtime(some_time_later) - data = ('this_data', expires) - token_cache = self.middleware._token_cache - token_cache.initialize({}) - token_cache._cache_store(token, data) - self.assertEqual(token_cache._cache_get(token), data[0]) - - @testtools.skipUnless(memcached_available(), 'memcached not available') - def test_no_memcache_protection(self): - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_secret_key': 'mysecret' - } - self.set_middleware(conf=conf) - token = 'my_token' - some_time_later = timeutils.utcnow() + datetime.timedelta(hours=4) - expires = timeutils.strtime(some_time_later) - data = ('this_data', expires) - token_cache = self.middleware._token_cache - token_cache.initialize({}) - token_cache._cache_store(token, data) - self.assertEqual(token_cache._cache_get(token), data[0]) - - def test_assert_valid_memcache_protection_config(self): - # test missing memcache_secret_key - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_security_strategy': 'Encrypt' - } - self.assertRaises(auth_token.ConfigurationError, self.set_middleware, - conf=conf) - # test invalue memcache_security_strategy - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_security_strategy': 'whatever' - } - self.assertRaises(auth_token.ConfigurationError, self.set_middleware, - conf=conf) - # test missing memcache_secret_key - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_security_strategy': 'mac' - } - self.assertRaises(auth_token.ConfigurationError, self.set_middleware, - conf=conf) - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_security_strategy': 'Encrypt', - 'memcache_secret_key': '' - } - self.assertRaises(auth_token.ConfigurationError, self.set_middleware, - conf=conf) - conf = { - 'memcached_servers': MEMCACHED_SERVERS, - 'memcache_security_strategy': 'mAc', - 'memcache_secret_key': '' - } - self.assertRaises(auth_token.ConfigurationError, self.set_middleware, - conf=conf) - - def test_config_revocation_cache_timeout(self): - conf = { - 'revocation_cache_time': 24, - 'auth_uri': 'https://keystone.example.com:1234', - } - middleware = auth_token.AuthProtocol(self.fake_app, conf) - self.assertEqual(middleware.token_revocation_list_cache_timeout, - datetime.timedelta(seconds=24)) - - def test_conf_values_type_convert(self): - conf = { - 'revocation_cache_time': '24', - 'identity_uri': 'https://keystone.example.com:1234', - 'include_service_catalog': '0', - 'nonexsit_option': '0', - } - - middleware = auth_token.AuthProtocol(self.fake_app, conf) - self.assertEqual(datetime.timedelta(seconds=24), - middleware.token_revocation_list_cache_timeout) - self.assertEqual(False, middleware.include_service_catalog) - self.assertEqual('https://keystone.example.com:1234', - middleware.identity_uri) - self.assertEqual('0', middleware.conf['nonexsit_option']) - - def test_conf_values_type_convert_with_wrong_value(self): - conf = { - 'include_service_catalog': '123', - } - self.assertRaises(auth_token.ConfigurationError, - auth_token.AuthProtocol, self.fake_app, conf) - - -class CommonAuthTokenMiddlewareTest(object): - """These tests are run once using v2 tokens and again using v3 tokens.""" - - def test_init_does_not_call_http(self): - conf = { - 'revocation_cache_time': 1 - } - self.set_middleware(conf=conf) - self.assertLastPath(None) - - def test_init_by_ipv6Addr_auth_host(self): - del self.conf['identity_uri'] - conf = { - 'auth_host': '2001:2013:1:f101::1', - 'auth_port': 1234, - 'auth_protocol': 'http', - 'auth_uri': None, - } - self.set_middleware(conf=conf) - expected_auth_uri = 'http://[2001:2013:1:f101::1]:1234' - self.assertEqual(expected_auth_uri, self.middleware.auth_uri) - - def assert_valid_request_200(self, token, with_catalog=True): - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token - body = self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - if with_catalog: - self.assertTrue(req.headers.get('X-Service-Catalog')) - else: - self.assertNotIn('X-Service-Catalog', req.headers) - self.assertEqual(body, [FakeApp.SUCCESS]) - self.assertIn('keystone.token_info', req.environ) - return req - - def test_valid_uuid_request(self): - for _ in range(2): # Do it twice because first result was cached. - token = self.token_dict['uuid_token_default'] - self.assert_valid_request_200(token) - self.assert_valid_last_url(token) - - def test_valid_uuid_request_with_auth_fragments(self): - del self.conf['identity_uri'] - self.conf['auth_protocol'] = 'https' - self.conf['auth_host'] = 'keystone.example.com' - self.conf['auth_port'] = 1234 - self.conf['auth_admin_prefix'] = '/testadmin' - self.set_middleware() - self.assert_valid_request_200(self.token_dict['uuid_token_default']) - self.assert_valid_last_url(self.token_dict['uuid_token_default']) - - def _test_cache_revoked(self, token, revoked_form=None): - # When the token is cached and revoked, 401 is returned. - self.middleware.check_revocations_for_cached = True - - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token - - # Token should be cached as ok after this. - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(200, self.response_status) - - # Put it in revocation list. - self.middleware.token_revocation_list = self.get_revocation_list_json( - token_ids=[revoked_form or token]) - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(401, self.response_status) - - def test_cached_revoked_uuid(self): - # When the UUID token is cached and revoked, 401 is returned. - self._test_cache_revoked(self.token_dict['uuid_token_default']) - - def test_valid_signed_request(self): - for _ in range(2): # Do it twice because first result was cached. - self.assert_valid_request_200( - self.token_dict['signed_token_scoped']) - # ensure that signed requests do not generate HTTP traffic - self.assertLastPath(None) - - def test_valid_signed_compressed_request(self): - self.assert_valid_request_200( - self.token_dict['signed_token_scoped_pkiz']) - # ensure that signed requests do not generate HTTP traffic - self.assertLastPath(None) - - def test_revoked_token_receives_401(self): - self.middleware.token_revocation_list = self.get_revocation_list_json() - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.token_dict['revoked_token'] - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - - def test_revoked_token_receives_401_sha256(self): - self.conf['hash_algorithms'] = ['sha256', 'md5'] - self.set_middleware() - self.middleware.token_revocation_list = ( - self.get_revocation_list_json(mode='sha256')) - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.token_dict['revoked_token'] - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - - def test_cached_revoked_pki(self): - # When the PKI token is cached and revoked, 401 is returned. - token = self.token_dict['signed_token_scoped'] - revoked_form = cms.cms_hash_token(token) - self._test_cache_revoked(token, revoked_form) - - def test_cached_revoked_pkiz(self): - # When the PKI token is cached and revoked, 401 is returned. - token = self.token_dict['signed_token_scoped_pkiz'] - revoked_form = cms.cms_hash_token(token) - self._test_cache_revoked(token, revoked_form) - - def test_revoked_token_receives_401_md5_secondary(self): - # When hash_algorithms has 'md5' as the secondary hash and the - # revocation list contains the md5 hash for a token, that token is - # considered revoked so returns 401. - self.conf['hash_algorithms'] = ['sha256', 'md5'] - self.set_middleware() - self.middleware.token_revocation_list = self.get_revocation_list_json() - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.token_dict['revoked_token'] - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - - def _test_revoked_hashed_token(self, token_key): - # If hash_algorithms is set as ['sha256', 'md5'], - # and check_revocations_for_cached is True, - # and a token is in the cache because it was successfully validated - # using the md5 hash, then - # if the token is in the revocation list by md5 hash, it'll be - # rejected and auth_token returns 401. - self.conf['hash_algorithms'] = ['sha256', 'md5'] - self.conf['check_revocations_for_cached'] = True - self.set_middleware() - - token = self.token_dict[token_key] - - # Put the token in the revocation list. - token_hashed = cms.cms_hash_token(token) - self.middleware.token_revocation_list = self.get_revocation_list_json( - token_ids=[token_hashed]) - - # request is using the hashed token, is valid so goes in - # cache using the given hash. - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token_hashed - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(200, self.response_status) - - # This time use the PKI(Z) token - req.headers['X-Auth-Token'] = token - self.middleware(req.environ, self.start_fake_response) - - # Should find the token in the cache and revocation list. - self.assertEqual(401, self.response_status) - - def test_revoked_hashed_pki_token(self): - self._test_revoked_hashed_token('signed_token_scoped') - - def test_revoked_hashed_pkiz_token(self): - self._test_revoked_hashed_token('signed_token_scoped_pkiz') - - def get_revocation_list_json(self, token_ids=None, mode=None): - if token_ids is None: - key = 'revoked_token_hash' + (('_' + mode) if mode else '') - token_ids = [self.token_dict[key]] - revocation_list = {'revoked': [{'id': x, 'expires': timeutils.utcnow()} - for x in token_ids]} - return jsonutils.dumps(revocation_list) - - def test_is_signed_token_revoked_returns_false(self): - # explicitly setting an empty revocation list here to document intent - self.middleware.token_revocation_list = jsonutils.dumps( - {"revoked": [], "extra": "success"}) - result = self.middleware.is_signed_token_revoked( - [self.token_dict['revoked_token_hash']]) - self.assertFalse(result) - - def test_is_signed_token_revoked_returns_true(self): - self.middleware.token_revocation_list = self.get_revocation_list_json() - result = self.middleware.is_signed_token_revoked( - [self.token_dict['revoked_token_hash']]) - self.assertTrue(result) - - def test_is_signed_token_revoked_returns_true_sha256(self): - self.conf['hash_algorithms'] = ['sha256', 'md5'] - self.set_middleware() - self.middleware.token_revocation_list = ( - self.get_revocation_list_json(mode='sha256')) - result = self.middleware.is_signed_token_revoked( - [self.token_dict['revoked_token_hash_sha256']]) - self.assertTrue(result) - - def test_verify_signed_token_raises_exception_for_revoked_token(self): - self.middleware.token_revocation_list = self.get_revocation_list_json() - self.assertRaises(auth_token.InvalidUserToken, - self.middleware.verify_signed_token, - self.token_dict['revoked_token'], - [self.token_dict['revoked_token_hash']]) - - def test_verify_signed_token_raises_exception_for_revoked_token_s256(self): - self.conf['hash_algorithms'] = ['sha256', 'md5'] - self.set_middleware() - self.middleware.token_revocation_list = ( - self.get_revocation_list_json(mode='sha256')) - self.assertRaises(auth_token.InvalidUserToken, - self.middleware.verify_signed_token, - self.token_dict['revoked_token'], - [self.token_dict['revoked_token_hash_sha256'], - self.token_dict['revoked_token_hash']]) - - def test_verify_signed_token_raises_exception_for_revoked_pkiz_token(self): - self.middleware.token_revocation_list = ( - self.examples.REVOKED_TOKEN_PKIZ_LIST_JSON) - self.assertRaises(auth_token.InvalidUserToken, - self.middleware.verify_pkiz_token, - self.token_dict['revoked_token_pkiz'], - [self.token_dict['revoked_token_pkiz_hash']]) - - def assertIsValidJSON(self, text): - json.loads(text) - - def test_verify_signed_token_succeeds_for_unrevoked_token(self): - self.middleware.token_revocation_list = self.get_revocation_list_json() - text = self.middleware.verify_signed_token( - self.token_dict['signed_token_scoped'], - [self.token_dict['signed_token_scoped_hash']]) - self.assertIsValidJSON(text) - - def test_verify_signed_compressed_token_succeeds_for_unrevoked_token(self): - self.middleware.token_revocation_list = self.get_revocation_list_json() - text = self.middleware.verify_pkiz_token( - self.token_dict['signed_token_scoped_pkiz'], - [self.token_dict['signed_token_scoped_hash']]) - self.assertIsValidJSON(text) - - def test_verify_signed_token_succeeds_for_unrevoked_token_sha256(self): - self.conf['hash_algorithms'] = ['sha256', 'md5'] - self.set_middleware() - self.middleware.token_revocation_list = ( - self.get_revocation_list_json(mode='sha256')) - text = self.middleware.verify_signed_token( - self.token_dict['signed_token_scoped'], - [self.token_dict['signed_token_scoped_hash_sha256'], - self.token_dict['signed_token_scoped_hash']]) - self.assertIsValidJSON(text) - - def test_verify_signing_dir_create_while_missing(self): - tmp_name = uuid.uuid4().hex - test_parent_signing_dir = "/tmp/%s" % tmp_name - self.middleware.signing_dirname = "/tmp/%s/%s" % ((tmp_name,) * 2) - self.middleware.signing_cert_file_name = ( - "%s/test.pem" % self.middleware.signing_dirname) - self.middleware.verify_signing_dir() - # NOTE(wu_wenxiang): Verify if the signing dir was created as expected. - self.assertTrue(os.path.isdir(self.middleware.signing_dirname)) - self.assertTrue(os.access(self.middleware.signing_dirname, os.W_OK)) - self.assertEqual(os.stat(self.middleware.signing_dirname).st_uid, - os.getuid()) - self.assertEqual( - stat.S_IMODE(os.stat(self.middleware.signing_dirname).st_mode), - stat.S_IRWXU) - shutil.rmtree(test_parent_signing_dir) - - def test_get_token_revocation_list_fetched_time_returns_min(self): - self.middleware.token_revocation_list_fetched_time = None - self.middleware.revoked_file_name = '' - self.assertEqual(self.middleware.token_revocation_list_fetched_time, - datetime.datetime.min) - - def test_get_token_revocation_list_fetched_time_returns_mtime(self): - self.middleware.token_revocation_list_fetched_time = None - mtime = os.path.getmtime(self.middleware.revoked_file_name) - fetched_time = datetime.datetime.utcfromtimestamp(mtime) - self.assertEqual(fetched_time, - self.middleware.token_revocation_list_fetched_time) - - @testtools.skipUnless(TimezoneFixture.supported(), - 'TimezoneFixture not supported') - def test_get_token_revocation_list_fetched_time_returns_utc(self): - with TimezoneFixture('UTC-1'): - self.middleware.token_revocation_list = jsonutils.dumps( - self.examples.REVOCATION_LIST) - self.middleware.token_revocation_list_fetched_time = None - fetched_time = self.middleware.token_revocation_list_fetched_time - self.assertTrue(timeutils.is_soon(fetched_time, 1)) - - def test_get_token_revocation_list_fetched_time_returns_value(self): - expected = self.middleware._token_revocation_list_fetched_time - self.assertEqual(self.middleware.token_revocation_list_fetched_time, - expected) - - def test_get_revocation_list_returns_fetched_list(self): - # auth_token uses v2 to fetch this, so don't allow the v3 - # tests to override the fake http connection - self.middleware.token_revocation_list_fetched_time = None - os.remove(self.middleware.revoked_file_name) - self.assertEqual(self.middleware.token_revocation_list, - self.examples.REVOCATION_LIST) - - def test_get_revocation_list_returns_current_list_from_memory(self): - self.assertEqual(self.middleware.token_revocation_list, - self.middleware._token_revocation_list) - - def test_get_revocation_list_returns_current_list_from_disk(self): - in_memory_list = self.middleware.token_revocation_list - self.middleware._token_revocation_list = None - self.assertEqual(self.middleware.token_revocation_list, in_memory_list) - - def test_invalid_revocation_list_raises_service_error(self): - self.requests_mock.get('%s/v2.0/tokens/revoked' % BASE_URI, text='{}') - - self.assertRaises(auth_token.ServiceError, - self.middleware.fetch_revocation_list) - - def test_fetch_revocation_list(self): - # auth_token uses v2 to fetch this, so don't allow the v3 - # tests to override the fake http connection - fetched_list = jsonutils.loads(self.middleware.fetch_revocation_list()) - self.assertEqual(fetched_list, self.examples.REVOCATION_LIST) - - def test_request_invalid_uuid_token(self): - # remember because we are testing the middleware we stub the connection - # to the keystone server, but this is not what gets returned - invalid_uri = "%s/v2.0/tokens/invalid-token" % BASE_URI - self.requests_mock.get(invalid_uri, text="", status_code=404) - - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = 'invalid-token' - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - self.assertEqual(self.response_headers['WWW-Authenticate'], - "Keystone uri='https://keystone.example.com:1234'") - - def test_request_invalid_signed_token(self): - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.examples.INVALID_SIGNED_TOKEN - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(401, self.response_status) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - self.response_headers['WWW-Authenticate']) - - def test_request_invalid_signed_pkiz_token(self): - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.examples.INVALID_SIGNED_PKIZ_TOKEN - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(401, self.response_status) - self.assertEqual("Keystone uri='https://keystone.example.com:1234'", - self.response_headers['WWW-Authenticate']) - - def test_request_no_token(self): - req = webob.Request.blank('/') - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - self.assertEqual(self.response_headers['WWW-Authenticate'], - "Keystone uri='https://keystone.example.com:1234'") - - def test_request_no_token_log_message(self): - class FakeLog(object): - def __init__(self): - self.msg = None - self.debugmsg = None - - def warn(self, msg=None, *args, **kwargs): - self.msg = msg - - def debug(self, msg=None, *args, **kwargs): - self.debugmsg = msg - - self.middleware.LOG = FakeLog() - self.middleware.delay_auth_decision = False - self.assertRaises(auth_token.InvalidUserToken, - self.middleware._get_user_token_from_header, {}) - self.assertIsNotNone(self.middleware.LOG.msg) - self.assertIsNotNone(self.middleware.LOG.debugmsg) - - def test_request_no_token_http(self): - req = webob.Request.blank('/', environ={'REQUEST_METHOD': 'HEAD'}) - self.set_middleware() - body = self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - self.assertEqual(self.response_headers['WWW-Authenticate'], - "Keystone uri='https://keystone.example.com:1234'") - self.assertEqual(body, ['']) - - def test_request_blank_token(self): - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = '' - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - self.assertEqual(self.response_headers['WWW-Authenticate'], - "Keystone uri='https://keystone.example.com:1234'") - - def _get_cached_token(self, token, mode='md5'): - token_id = cms.cms_hash_token(token, mode=mode) - return self.middleware._token_cache._cache_get(token_id) - - def test_memcache(self): - req = webob.Request.blank('/') - token = self.token_dict['signed_token_scoped'] - req.headers['X-Auth-Token'] = token - self.middleware(req.environ, self.start_fake_response) - self.assertIsNotNone(self._get_cached_token(token)) - - def test_expired(self): - req = webob.Request.blank('/') - token = self.token_dict['signed_token_scoped_expired'] - req.headers['X-Auth-Token'] = token - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - - def test_memcache_set_invalid_uuid(self): - invalid_uri = "%s/v2.0/tokens/invalid-token" % BASE_URI - self.requests_mock.get(invalid_uri, status_code=404) - - req = webob.Request.blank('/') - token = 'invalid-token' - req.headers['X-Auth-Token'] = token - self.middleware(req.environ, self.start_fake_response) - self.assertRaises(auth_token.InvalidUserToken, - self._get_cached_token, token) - - def _test_memcache_set_invalid_signed(self, hash_algorithms=None, - exp_mode='md5'): - req = webob.Request.blank('/') - token = self.token_dict['signed_token_scoped_expired'] - req.headers['X-Auth-Token'] = token - if hash_algorithms: - self.conf['hash_algorithms'] = hash_algorithms - self.set_middleware() - self.middleware(req.environ, self.start_fake_response) - self.assertRaises(auth_token.InvalidUserToken, - self._get_cached_token, token, mode=exp_mode) - - def test_memcache_set_invalid_signed(self): - self._test_memcache_set_invalid_signed() - - def test_memcache_set_invalid_signed_sha256_md5(self): - hash_algorithms = ['sha256', 'md5'] - self._test_memcache_set_invalid_signed(hash_algorithms=hash_algorithms, - exp_mode='sha256') - - def test_memcache_set_invalid_signed_sha256(self): - hash_algorithms = ['sha256'] - self._test_memcache_set_invalid_signed(hash_algorithms=hash_algorithms, - exp_mode='sha256') - - def test_memcache_set_expired(self, extra_conf={}, extra_environ={}): - token_cache_time = 10 - conf = { - 'token_cache_time': token_cache_time, - 'signing_dir': client_fixtures.CERTDIR, - } - conf.update(extra_conf) - self.set_middleware(conf=conf) - req = webob.Request.blank('/') - token = self.token_dict['signed_token_scoped'] - req.headers['X-Auth-Token'] = token - req.environ.update(extra_environ) - - now = datetime.datetime.utcnow() - self.useFixture(TimeFixture(now)) - - self.middleware(req.environ, self.start_fake_response) - self.assertIsNotNone(self._get_cached_token(token)) - - timeutils.advance_time_seconds(token_cache_time) - self.assertIsNone(self._get_cached_token(token)) - - def test_swift_memcache_set_expired(self): - extra_conf = {'cache': 'swift.cache'} - extra_environ = {'swift.cache': memorycache.Client()} - self.test_memcache_set_expired(extra_conf, extra_environ) - - def test_http_error_not_cached_token(self): - """Test to don't cache token as invalid on network errors. - - We use UUID tokens since they are the easiest one to reach - get_http_connection. - """ - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = ERROR_TOKEN - self.middleware.http_request_max_retries = 0 - self.middleware(req.environ, self.start_fake_response) - self.assertIsNone(self._get_cached_token(ERROR_TOKEN)) - self.assert_valid_last_url(ERROR_TOKEN) - - def test_http_request_max_retries(self): - times_retry = 10 - - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = ERROR_TOKEN - - conf = {'http_request_max_retries': times_retry} - self.set_middleware(conf=conf) - - with mock.patch('time.sleep') as mock_obj: - self.middleware(req.environ, self.start_fake_response) - - self.assertEqual(mock_obj.call_count, times_retry) - - def test_nocatalog(self): - conf = { - 'include_service_catalog': False - } - self.set_middleware(conf=conf) - self.assert_valid_request_200(self.token_dict['uuid_token_default'], - with_catalog=False) - - def assert_kerberos_bind(self, token, bind_level, - use_kerberos=True, success=True): - conf = { - 'enforce_token_bind': bind_level, - 'auth_version': self.auth_version, - } - self.set_middleware(conf=conf) - - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token - - if use_kerberos: - if use_kerberos is True: - req.environ['REMOTE_USER'] = self.examples.KERBEROS_BIND - else: - req.environ['REMOTE_USER'] = use_kerberos - - req.environ['AUTH_TYPE'] = 'Negotiate' - - body = self.middleware(req.environ, self.start_fake_response) - - if success: - self.assertEqual(self.response_status, 200) - self.assertEqual(body, [FakeApp.SUCCESS]) - self.assertIn('keystone.token_info', req.environ) - self.assert_valid_last_url(token) - else: - self.assertEqual(self.response_status, 401) - self.assertEqual(self.response_headers['WWW-Authenticate'], - "Keystone uri='https://keystone.example.com:1234'" - ) - - def test_uuid_bind_token_disabled_with_kerb_user(self): - for use_kerberos in [True, False]: - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='disabled', - use_kerberos=use_kerberos, - success=True) - - def test_uuid_bind_token_disabled_with_incorrect_ticket(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos='ronald@MCDONALDS.COM', - success=False) - - def test_uuid_bind_token_permissive_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='permissive', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_permissive_without_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='permissive', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_permissive_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='permissive', - use_kerberos=use_kerberos, - success=True) - - def test_uuid_bind_token_permissive_with_incorrect_ticket(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos='ronald@MCDONALDS.COM', - success=False) - - def test_uuid_bind_token_strict_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='strict', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_strict_with_kerbout_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='strict', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_strict_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='strict', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_required_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='required', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_required_without_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='required', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_required_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='required', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_required_without_bind(self): - for use_kerberos in [True, False]: - self.assert_kerberos_bind(self.token_dict['uuid_token_default'], - bind_level='required', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_named_kerberos_with_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos=True, - success=True) - - def test_uuid_bind_token_named_kerberos_without_kerb_user(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos=False, - success=False) - - def test_uuid_bind_token_named_kerberos_with_unknown_bind(self): - token = self.token_dict['uuid_token_unknown_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='kerberos', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_named_kerberos_without_bind(self): - for use_kerberos in [True, False]: - self.assert_kerberos_bind(self.token_dict['uuid_token_default'], - bind_level='kerberos', - use_kerberos=use_kerberos, - success=False) - - def test_uuid_bind_token_named_kerberos_with_incorrect_ticket(self): - self.assert_kerberos_bind(self.token_dict['uuid_token_bind'], - bind_level='kerberos', - use_kerberos='ronald@MCDONALDS.COM', - success=False) - - def test_uuid_bind_token_with_unknown_named_FOO(self): - token = self.token_dict['uuid_token_bind'] - - for use_kerberos in [True, False]: - self.assert_kerberos_bind(token, - bind_level='FOO', - use_kerberos=use_kerberos, - success=False) - - -class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def __init__(self, *args, **kwargs): - super(V2CertDownloadMiddlewareTest, self).__init__(*args, **kwargs) - self.auth_version = 'v2.0' - self.fake_app = None - self.ca_path = '/v2.0/certificates/ca' - self.signing_path = '/v2.0/certificates/signing' - - def setUp(self): - super(V2CertDownloadMiddlewareTest, self).setUp( - auth_version=self.auth_version, - fake_app=self.fake_app) - self.base_dir = tempfile.mkdtemp() - self.addCleanup(shutil.rmtree, self.base_dir) - self.cert_dir = os.path.join(self.base_dir, 'certs') - os.makedirs(self.cert_dir, stat.S_IRWXU) - conf = { - 'signing_dir': self.cert_dir, - 'auth_version': self.auth_version, - } - self.set_middleware(conf=conf) - - # Usually we supply a signed_dir with pre-installed certificates, - # so invocation of /usr/bin/openssl succeeds. This time we give it - # an empty directory, so it fails. - def test_request_no_token_dummy(self): - cms._ensure_subprocess() - - self.requests_mock.get("%s%s" % (BASE_URI, self.ca_path), - status_code=404) - url = "%s%s" % (BASE_URI, self.signing_path) - self.requests_mock.get(url, status_code=404) - self.assertRaises(exceptions.CertificateConfigError, - self.middleware.verify_signed_token, - self.examples.SIGNED_TOKEN_SCOPED, - [self.examples.SIGNED_TOKEN_SCOPED_HASH]) - - def test_fetch_signing_cert(self): - data = 'FAKE CERT' - url = '%s%s' % (BASE_URI, self.signing_path) - self.requests_mock.get(url, text=data) - self.middleware.fetch_signing_cert() - - with open(self.middleware.signing_cert_file_name, 'r') as f: - self.assertEqual(f.read(), data) - - self.assertLastPath("/testadmin%s" % self.signing_path) - - def test_fetch_signing_ca(self): - data = 'FAKE CA' - self.requests_mock.get("%s%s" % (BASE_URI, self.ca_path), text=data) - self.middleware.fetch_ca_cert() - - with open(self.middleware.signing_ca_file_name, 'r') as f: - self.assertEqual(f.read(), data) - - self.assertLastPath("/testadmin%s" % self.ca_path) - - def test_prefix_trailing_slash(self): - del self.conf['identity_uri'] - self.conf['auth_protocol'] = 'https' - self.conf['auth_host'] = 'keystone.example.com' - self.conf['auth_port'] = 1234 - self.conf['auth_admin_prefix'] = '/newadmin/' - - self.requests_mock.get("%s/newadmin%s" % (BASE_HOST, self.ca_path), - text='FAKECA') - url = "%s/newadmin%s" % (BASE_HOST, self.signing_path) - self.requests_mock.get(url, text='FAKECERT') - - self.set_middleware(conf=self.conf) - - self.middleware.fetch_ca_cert() - - self.assertLastPath('/newadmin%s' % self.ca_path) - - self.middleware.fetch_signing_cert() - - self.assertLastPath('/newadmin%s' % self.signing_path) - - def test_without_prefix(self): - del self.conf['identity_uri'] - self.conf['auth_protocol'] = 'https' - self.conf['auth_host'] = 'keystone.example.com' - self.conf['auth_port'] = 1234 - self.conf['auth_admin_prefix'] = '' - - self.requests_mock.get("%s%s" % (BASE_HOST, self.ca_path), - text='FAKECA') - self.requests_mock.get("%s%s" % (BASE_HOST, self.signing_path), - text='FAKECERT') - - self.set_middleware(conf=self.conf) - - self.middleware.fetch_ca_cert() - - self.assertLastPath(self.ca_path) - - self.middleware.fetch_signing_cert() - - self.assertLastPath(self.signing_path) - - -class V3CertDownloadMiddlewareTest(V2CertDownloadMiddlewareTest): - - def __init__(self, *args, **kwargs): - super(V3CertDownloadMiddlewareTest, self).__init__(*args, **kwargs) - self.auth_version = 'v3.0' - self.fake_app = v3FakeApp - self.ca_path = '/v3/OS-SIMPLE-CERT/ca' - self.signing_path = '/v3/OS-SIMPLE-CERT/certificates' - - -def network_error_response(method, uri, headers): - raise auth_token.NetworkError("Network connection error.") - - -class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - CommonAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - """v2 token specific tests. - - There are some differences between how the auth-token middleware handles - v2 and v3 tokens over and above the token formats, namely: - - - A v3 keystone server will auto scope a token to a user's default project - if no scope is specified. A v2 server assumes that the auth-token - middleware will do that. - - A v2 keystone server may issue a token without a catalog, even with a - tenant - - The tests below were originally part of the generic AuthTokenMiddlewareTest - class, but now, since they really are v2 specific, they are included here. - - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def setUp(self): - super(v2AuthTokenMiddlewareTest, self).setUp() - - self.token_dict = { - 'uuid_token_default': self.examples.UUID_TOKEN_DEFAULT, - 'uuid_token_unscoped': self.examples.UUID_TOKEN_UNSCOPED, - 'uuid_token_bind': self.examples.UUID_TOKEN_BIND, - 'uuid_token_unknown_bind': self.examples.UUID_TOKEN_UNKNOWN_BIND, - 'signed_token_scoped': self.examples.SIGNED_TOKEN_SCOPED, - 'signed_token_scoped_pkiz': self.examples.SIGNED_TOKEN_SCOPED_PKIZ, - 'signed_token_scoped_hash': self.examples.SIGNED_TOKEN_SCOPED_HASH, - 'signed_token_scoped_hash_sha256': - self.examples.SIGNED_TOKEN_SCOPED_HASH_SHA256, - 'signed_token_scoped_expired': - self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, - 'revoked_token': self.examples.REVOKED_TOKEN, - 'revoked_token_pkiz': self.examples.REVOKED_TOKEN_PKIZ, - 'revoked_token_pkiz_hash': - self.examples.REVOKED_TOKEN_PKIZ_HASH, - 'revoked_token_hash': self.examples.REVOKED_TOKEN_HASH, - 'revoked_token_hash_sha256': - self.examples.REVOKED_TOKEN_HASH_SHA256, - } - - self.requests_mock.get("%s/" % BASE_URI, - text=VERSION_LIST_v2, - status_code=300) - - self.requests_mock.post("%s/v2.0/tokens" % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - self.requests_mock.get("%s/v2.0/tokens/revoked" % BASE_URI, - text=self.examples.SIGNED_REVOCATION_LIST) - - for token in (self.examples.UUID_TOKEN_DEFAULT, - self.examples.UUID_TOKEN_UNSCOPED, - self.examples.UUID_TOKEN_BIND, - self.examples.UUID_TOKEN_UNKNOWN_BIND, - self.examples.UUID_TOKEN_NO_SERVICE_CATALOG, - self.examples.SIGNED_TOKEN_SCOPED_KEY, - self.examples.SIGNED_TOKEN_SCOPED_PKIZ_KEY,): - text = self.examples.JSON_TOKEN_RESPONSES[token] - self.requests_mock.get('%s/v2.0/tokens/%s' % (BASE_URI, token), - text=text) - - self.requests_mock.get('%s/v2.0/tokens/%s' % (BASE_URI, ERROR_TOKEN), - text=network_error_response) - - self.set_middleware() - - def assert_unscoped_default_tenant_auto_scopes(self, token): - """Unscoped v2 requests with a default tenant should "auto-scope." - - The implied scope is the user's tenant ID. - - """ - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token - body = self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - self.assertEqual(body, [FakeApp.SUCCESS]) - self.assertIn('keystone.token_info', req.environ) - - def assert_valid_last_url(self, token_id): - self.assertLastPath("/testadmin/v2.0/tokens/%s" % token_id) - - def test_default_tenant_uuid_token(self): - self.assert_unscoped_default_tenant_auto_scopes( - self.examples.UUID_TOKEN_DEFAULT) - - def test_default_tenant_signed_token(self): - self.assert_unscoped_default_tenant_auto_scopes( - self.examples.SIGNED_TOKEN_SCOPED) - - def assert_unscoped_token_receives_401(self, token): - """Unscoped requests with no default tenant ID should be rejected.""" - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = token - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 401) - self.assertEqual(self.response_headers['WWW-Authenticate'], - "Keystone uri='https://keystone.example.com:1234'") - - def test_unscoped_uuid_token_receives_401(self): - self.assert_unscoped_token_receives_401( - self.examples.UUID_TOKEN_UNSCOPED) - - def test_unscoped_pki_token_receives_401(self): - self.assert_unscoped_token_receives_401( - self.examples.SIGNED_TOKEN_UNSCOPED) - - def test_request_prevent_service_catalog_injection(self): - req = webob.Request.blank('/') - req.headers['X-Service-Catalog'] = '[]' - req.headers['X-Auth-Token'] = ( - self.examples.UUID_TOKEN_NO_SERVICE_CATALOG) - body = self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - self.assertFalse(req.headers.get('X-Service-Catalog')) - self.assertEqual(body, [FakeApp.SUCCESS]) - - -class CrossVersionAuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_valid_uuid_request_forced_to_2_0(self): - """Test forcing auth_token to use lower api version. - - By installing the v3 http hander, auth_token will be get - a version list that looks like a v3 server - from which it - would normally chose v3.0 as the auth version. However, here - we specify v2.0 in the configuration - which should force - auth_token to use that version instead. - - """ - conf = { - 'signing_dir': client_fixtures.CERTDIR, - 'auth_version': 'v2.0' - } - - self.requests_mock.get('%s/' % BASE_URI, - text=VERSION_LIST_v3, - status_code=300) - - self.requests_mock.post('%s/v2.0/tokens' % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - token = self.examples.UUID_TOKEN_DEFAULT - url = '%s/v2.0/tokens/%s' % (BASE_URI, token) - response_body = self.examples.JSON_TOKEN_RESPONSES[token] - self.requests_mock.get(url, text=response_body) - - self.set_middleware(conf=conf) - - # This tests will only work is auth_token has chosen to use the - # lower, v2, api version - req = webob.Request.blank('/') - req.headers['X-Auth-Token'] = self.examples.UUID_TOKEN_DEFAULT - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - self.assertLastPath("/testadmin/v2.0/tokens/%s" % - self.examples.UUID_TOKEN_DEFAULT) - - -class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest, - CommonAuthTokenMiddlewareTest, - testresources.ResourcedTestCase): - """Test auth_token middleware with v3 tokens. - - Re-execute the AuthTokenMiddlewareTest class tests, but with the - auth_token middleware configured to expect v3 tokens back from - a keystone server. - - This is done by configuring the AuthTokenMiddlewareTest class via - its Setup(), passing in v3 style data that will then be used by - the tests themselves. This approach has been used to ensure we - really are running the same tests for both v2 and v3 tokens. - - There a few additional specific test for v3 only: - - - We allow an unscoped token to be validated (as unscoped), where - as for v2 tokens, the auth_token middleware is expected to try and - auto-scope it (and fail if there is no default tenant) - - Domain scoped tokens - - Since we don't specify an auth version for auth_token to use, by - definition we are thefore implicitely testing that it will use - the highest available auth version, i.e. v3.0 - - """ - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def setUp(self): - super(v3AuthTokenMiddlewareTest, self).setUp( - auth_version='v3.0', - fake_app=v3FakeApp) - - self.token_dict = { - 'uuid_token_default': self.examples.v3_UUID_TOKEN_DEFAULT, - 'uuid_token_unscoped': self.examples.v3_UUID_TOKEN_UNSCOPED, - 'uuid_token_bind': self.examples.v3_UUID_TOKEN_BIND, - 'uuid_token_unknown_bind': - self.examples.v3_UUID_TOKEN_UNKNOWN_BIND, - 'signed_token_scoped': self.examples.SIGNED_v3_TOKEN_SCOPED, - 'signed_token_scoped_pkiz': - self.examples.SIGNED_v3_TOKEN_SCOPED_PKIZ, - 'signed_token_scoped_hash': - self.examples.SIGNED_v3_TOKEN_SCOPED_HASH, - 'signed_token_scoped_hash_sha256': - self.examples.SIGNED_v3_TOKEN_SCOPED_HASH_SHA256, - 'signed_token_scoped_expired': - self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, - 'revoked_token': self.examples.REVOKED_v3_TOKEN, - 'revoked_token_pkiz': self.examples.REVOKED_v3_TOKEN_PKIZ, - 'revoked_token_hash': self.examples.REVOKED_v3_TOKEN_HASH, - 'revoked_token_hash_sha256': - self.examples.REVOKED_v3_TOKEN_HASH_SHA256, - 'revoked_token_pkiz_hash': - self.examples.REVOKED_v3_PKIZ_TOKEN_HASH, - } - - self.requests_mock.get(BASE_URI, text=VERSION_LIST_v3, status_code=300) - - # TODO(jamielennox): auth_token middleware uses a v2 admin token - # regardless of the auth_version that is set. - self.requests_mock.post('%s/v2.0/tokens' % BASE_URI, - text=FAKE_ADMIN_TOKEN) - - # TODO(jamielennox): there is no v3 revocation url yet, it uses v2 - self.requests_mock.get('%s/v2.0/tokens/revoked' % BASE_URI, - text=self.examples.SIGNED_REVOCATION_LIST) - - self.requests_mock.get('%s/v3/auth/tokens' % BASE_URI, - text=self.token_response) - - self.set_middleware() - - def token_response(self, request, context): - auth_id = request.headers.get('X-Auth-Token') - token_id = request.headers.get('X-Subject-Token') - self.assertEqual(auth_id, FAKE_ADMIN_TOKEN_ID) - - response = "" - - if token_id == ERROR_TOKEN: - raise auth_token.NetworkError("Network connection error.") - - try: - response = self.examples.JSON_TOKEN_RESPONSES[token_id] - except KeyError: - context.status_code = 404 - - return response - - def assert_valid_last_url(self, token_id): - self.assertLastPath('/testadmin/v3/auth/tokens') - - def test_valid_unscoped_uuid_request(self): - # Remove items that won't be in an unscoped token - delta_expected_env = { - 'HTTP_X_PROJECT_ID': None, - 'HTTP_X_PROJECT_NAME': None, - 'HTTP_X_PROJECT_DOMAIN_ID': None, - 'HTTP_X_PROJECT_DOMAIN_NAME': None, - 'HTTP_X_TENANT_ID': None, - 'HTTP_X_TENANT_NAME': None, - 'HTTP_X_ROLES': '', - 'HTTP_X_TENANT': None, - 'HTTP_X_ROLE': '', - } - self.set_middleware(expected_env=delta_expected_env) - self.assert_valid_request_200(self.examples.v3_UUID_TOKEN_UNSCOPED, - with_catalog=False) - self.assertLastPath('/testadmin/v3/auth/tokens') - - def test_domain_scoped_uuid_request(self): - # Modify items compared to default token for a domain scope - delta_expected_env = { - 'HTTP_X_DOMAIN_ID': 'domain_id1', - 'HTTP_X_DOMAIN_NAME': 'domain_name1', - 'HTTP_X_PROJECT_ID': None, - 'HTTP_X_PROJECT_NAME': None, - 'HTTP_X_PROJECT_DOMAIN_ID': None, - 'HTTP_X_PROJECT_DOMAIN_NAME': None, - 'HTTP_X_TENANT_ID': None, - 'HTTP_X_TENANT_NAME': None, - 'HTTP_X_TENANT': None - } - self.set_middleware(expected_env=delta_expected_env) - self.assert_valid_request_200( - self.examples.v3_UUID_TOKEN_DOMAIN_SCOPED) - self.assertLastPath('/testadmin/v3/auth/tokens') - - def test_gives_v2_catalog(self): - self.set_middleware() - req = self.assert_valid_request_200( - self.examples.SIGNED_v3_TOKEN_SCOPED) - - catalog = jsonutils.loads(req.headers['X-Service-Catalog']) - - for service in catalog: - for endpoint in service['endpoints']: - # no point checking everything, just that it's in v2 format - self.assertIn('adminURL', endpoint) - self.assertIn('publicURL', endpoint) - self.assertIn('adminURL', endpoint) - - -class TokenEncodingTest(testtools.TestCase): - def test_unquoted_token(self): - self.assertEqual('foo%20bar', auth_token.safe_quote('foo bar')) - - def test_quoted_token(self): - self.assertEqual('foo%20bar', auth_token.safe_quote('foo%20bar')) - - -class TokenExpirationTest(BaseAuthTokenMiddlewareTest): - def setUp(self): - super(TokenExpirationTest, self).setUp() - self.now = timeutils.utcnow() - self.delta = datetime.timedelta(hours=1) - self.one_hour_ago = timeutils.isotime(self.now - self.delta, - subsecond=True) - self.one_hour_earlier = timeutils.isotime(self.now + self.delta, - subsecond=True) - - def create_v2_token_fixture(self, expires=None): - v2_fixture = { - 'access': { - 'token': { - 'id': 'blah', - 'expires': expires or self.one_hour_earlier, - 'tenant': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - }, - }, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], - }, - 'serviceCatalog': {} - }, - } - - return v2_fixture - - def create_v3_token_fixture(self, expires=None): - - v3_fixture = { - 'token': { - 'expires_at': expires or self.one_hour_earlier, - 'user': { - 'id': 'user_id1', - 'name': 'user_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'project': { - 'id': 'tenant_id1', - 'name': 'tenant_name1', - 'domain': { - 'id': 'domain_id1', - 'name': 'domain_name1' - } - }, - 'roles': [ - {'name': 'role1', 'id': 'Role1'}, - {'name': 'role2', 'id': 'Role2'}, - ], - 'catalog': {} - } - } - - return v3_fixture - - def test_no_data(self): - data = {} - self.assertRaises(auth_token.InvalidUserToken, - auth_token.confirm_token_not_expired, - data) - - def test_bad_data(self): - data = {'my_happy_token_dict': 'woo'} - self.assertRaises(auth_token.InvalidUserToken, - auth_token.confirm_token_not_expired, - data) - - def test_v2_token_not_expired(self): - data = self.create_v2_token_fixture() - expected_expires = data['access']['token']['expires'] - actual_expires = auth_token.confirm_token_not_expired(data) - self.assertEqual(actual_expires, expected_expires) - - def test_v2_token_expired(self): - data = self.create_v2_token_fixture(expires=self.one_hour_ago) - self.assertRaises(auth_token.InvalidUserToken, - auth_token.confirm_token_not_expired, - data) - - def test_v2_token_with_timezone_offset_not_expired(self): - self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z')) - data = self.create_v2_token_fixture( - expires='2000-01-01T00:05:10.000123-05:00') - expected_expires = '2000-01-01T05:05:10.000123Z' - actual_expires = auth_token.confirm_token_not_expired(data) - self.assertEqual(actual_expires, expected_expires) - - def test_v2_token_with_timezone_offset_expired(self): - self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z')) - data = self.create_v2_token_fixture( - expires='2000-01-01T00:05:10.000123+05:00') - data['access']['token']['expires'] = '2000-01-01T00:05:10.000123+05:00' - self.assertRaises(auth_token.InvalidUserToken, - auth_token.confirm_token_not_expired, - data) - - def test_v3_token_not_expired(self): - data = self.create_v3_token_fixture() - expected_expires = data['token']['expires_at'] - actual_expires = auth_token.confirm_token_not_expired(data) - self.assertEqual(actual_expires, expected_expires) - - def test_v3_token_expired(self): - data = self.create_v3_token_fixture(expires=self.one_hour_ago) - self.assertRaises(auth_token.InvalidUserToken, - auth_token.confirm_token_not_expired, - data) - - def test_v3_token_with_timezone_offset_not_expired(self): - self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z')) - data = self.create_v3_token_fixture( - expires='2000-01-01T00:05:10.000123-05:00') - expected_expires = '2000-01-01T05:05:10.000123Z' - - actual_expires = auth_token.confirm_token_not_expired(data) - self.assertEqual(actual_expires, expected_expires) - - def test_v3_token_with_timezone_offset_expired(self): - self.useFixture(TimeFixture('2000-01-01T00:01:10.000123Z')) - data = self.create_v3_token_fixture( - expires='2000-01-01T00:05:10.000123+05:00') - self.assertRaises(auth_token.InvalidUserToken, - auth_token.confirm_token_not_expired, - data) - - def test_cached_token_not_expired(self): - token = 'mytoken' - data = 'this_data' - self.set_middleware() - self.middleware._token_cache.initialize({}) - some_time_later = timeutils.strtime(at=(self.now + self.delta)) - expires = some_time_later - self.middleware._token_cache.store(token, data, expires) - self.assertEqual(self.middleware._token_cache._cache_get(token), data) - - def test_cached_token_not_expired_with_old_style_nix_timestamp(self): - """Ensure we cannot retrieve a token from the cache. - - Getting a token from the cache should return None when the token data - in the cache stores the expires time as a \*nix style timestamp. - - """ - token = 'mytoken' - data = 'this_data' - self.set_middleware() - token_cache = self.middleware._token_cache - token_cache.initialize({}) - some_time_later = self.now + self.delta - # Store a unix timestamp in the cache. - expires = calendar.timegm(some_time_later.timetuple()) - token_cache.store(token, data, expires) - self.assertIsNone(token_cache._cache_get(token)) - - def test_cached_token_expired(self): - token = 'mytoken' - data = 'this_data' - self.set_middleware() - self.middleware._token_cache.initialize({}) - some_time_earlier = timeutils.strtime(at=(self.now - self.delta)) - expires = some_time_earlier - self.middleware._token_cache.store(token, data, expires) - self.assertThat(lambda: self.middleware._token_cache._cache_get(token), - matchers.raises(auth_token.InvalidUserToken)) - - def test_cached_token_with_timezone_offset_not_expired(self): - token = 'mytoken' - data = 'this_data' - self.set_middleware() - self.middleware._token_cache.initialize({}) - timezone_offset = datetime.timedelta(hours=2) - some_time_later = self.now - timezone_offset + self.delta - expires = timeutils.strtime(some_time_later) + '-02:00' - self.middleware._token_cache.store(token, data, expires) - self.assertEqual(self.middleware._token_cache._cache_get(token), data) - - def test_cached_token_with_timezone_offset_expired(self): - token = 'mytoken' - data = 'this_data' - self.set_middleware() - self.middleware._token_cache.initialize({}) - timezone_offset = datetime.timedelta(hours=2) - some_time_earlier = self.now - timezone_offset - self.delta - expires = timeutils.strtime(some_time_earlier) + '-02:00' - self.middleware._token_cache.store(token, data, expires) - self.assertThat(lambda: self.middleware._token_cache._cache_get(token), - matchers.raises(auth_token.InvalidUserToken)) - - -class CatalogConversionTests(BaseAuthTokenMiddlewareTest): - - PUBLIC_URL = 'http://server:5000/v2.0' - ADMIN_URL = 'http://admin:35357/v2.0' - INTERNAL_URL = 'http://internal:5000/v2.0' - - REGION_ONE = 'RegionOne' - REGION_TWO = 'RegionTwo' - REGION_THREE = 'RegionThree' - - def test_basic_convert(self): - token = fixture.V3Token() - s = token.add_service(type='identity') - s.add_standard_endpoints(public=self.PUBLIC_URL, - admin=self.ADMIN_URL, - internal=self.INTERNAL_URL, - region=self.REGION_ONE) - - auth_ref = access.AccessInfo.factory(body=token) - catalog_data = auth_ref.service_catalog.get_data() - catalog = auth_token._v3_to_v2_catalog(catalog_data) - - self.assertEqual(1, len(catalog)) - service = catalog[0] - self.assertEqual(1, len(service['endpoints'])) - endpoints = service['endpoints'][0] - - self.assertEqual('identity', service['type']) - self.assertEqual(4, len(endpoints)) - self.assertEqual(self.PUBLIC_URL, endpoints['publicURL']) - self.assertEqual(self.ADMIN_URL, endpoints['adminURL']) - self.assertEqual(self.INTERNAL_URL, endpoints['internalURL']) - self.assertEqual(self.REGION_ONE, endpoints['region']) - - def test_multi_region(self): - token = fixture.V3Token() - s = token.add_service(type='identity') - - s.add_endpoint('internal', self.INTERNAL_URL, region=self.REGION_ONE) - s.add_endpoint('public', self.PUBLIC_URL, region=self.REGION_TWO) - s.add_endpoint('admin', self.ADMIN_URL, region=self.REGION_THREE) - - auth_ref = access.AccessInfo.factory(body=token) - catalog_data = auth_ref.service_catalog.get_data() - catalog = auth_token._v3_to_v2_catalog(catalog_data) - - self.assertEqual(1, len(catalog)) - service = catalog[0] - - # the 3 regions will come through as 3 separate endpoints - expected = [{'internalURL': self.INTERNAL_URL, - 'region': self.REGION_ONE}, - {'publicURL': self.PUBLIC_URL, - 'region': self.REGION_TWO}, - {'adminURL': self.ADMIN_URL, - 'region': self.REGION_THREE}] - - self.assertEqual('identity', service['type']) - self.assertEqual(3, len(service['endpoints'])) - for e in expected: - self.assertIn(e, expected) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_base.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_base.py deleted file mode 100644 index 2e7fc5e28c..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_base.py +++ /dev/null @@ -1,161 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient.tests.unit import utils -from keystoneclient.v2_0 import client -from keystoneclient.v2_0 import roles - - -class HumanReadable(base.Resource): - HUMAN_ID = True - - -class BaseTest(utils.TestCase): - - def test_resource_repr(self): - r = base.Resource(None, dict(foo="bar", baz="spam")) - self.assertEqual(repr(r), "<Resource baz=spam, foo=bar>") - - def test_getid(self): - self.assertEqual(base.getid(4), 4) - - class TmpObject(object): - id = 4 - self.assertEqual(base.getid(TmpObject), 4) - - def test_resource_lazy_getattr(self): - self.client = client.Client(username=self.TEST_USER, - token=self.TEST_TOKEN, - tenant_name=self.TEST_TENANT_NAME, - auth_url='http://127.0.0.1:5000', - endpoint='http://127.0.0.1:5000') - - self.client._adapter.get = self.mox.CreateMockAnything() - self.client._adapter.get('/OS-KSADM/roles/1').AndRaise(AttributeError) - self.mox.ReplayAll() - - f = roles.Role(self.client.roles, {'id': 1, 'name': 'Member'}) - self.assertEqual(f.name, 'Member') - - # Missing stuff still fails after a second get - self.assertRaises(AttributeError, getattr, f, 'blahblah') - - def test_eq(self): - # Two resources of the same type with the same id: equal - r1 = base.Resource(None, {'id': 1, 'name': 'hi'}) - r2 = base.Resource(None, {'id': 1, 'name': 'hello'}) - self.assertEqual(r1, r2) - - # Two resoruces of different types: never equal - r1 = base.Resource(None, {'id': 1}) - r2 = roles.Role(None, {'id': 1}) - self.assertNotEqual(r1, r2) - - # Two resources with no ID: equal if their info is equal - r1 = base.Resource(None, {'name': 'joe', 'age': 12}) - r2 = base.Resource(None, {'name': 'joe', 'age': 12}) - self.assertEqual(r1, r2) - - r1 = base.Resource(None, {'id': 1}) - self.assertNotEqual(r1, object()) - self.assertNotEqual(r1, {'id': 1}) - - def test_human_id(self): - r = base.Resource(None, {"name": "1 of !"}) - self.assertIsNone(r.human_id) - r = HumanReadable(None, {"name": "1 of !"}) - self.assertEqual(r.human_id, "1-of") - - -class ManagerTest(utils.TestCase): - body = {"hello": {"hi": 1}} - url = "/test-url" - - def setUp(self): - super(ManagerTest, self).setUp() - self.client = client.Client(username=self.TEST_USER, - token=self.TEST_TOKEN, - tenant_name=self.TEST_TENANT_NAME, - auth_url='http://127.0.0.1:5000', - endpoint='http://127.0.0.1:5000') - self.mgr = base.Manager(self.client) - self.mgr.resource_class = base.Resource - - def test_api(self): - self.assertEqual(self.mgr.api, self.client) - - def test_get(self): - self.client.get = self.mox.CreateMockAnything() - self.client.get(self.url).AndReturn((None, self.body)) - self.mox.ReplayAll() - - rsrc = self.mgr._get(self.url, "hello") - self.assertEqual(rsrc.hi, 1) - - def test_post(self): - self.client.post = self.mox.CreateMockAnything() - self.client.post(self.url, body=self.body).AndReturn((None, self.body)) - self.client.post(self.url, body=self.body).AndReturn((None, self.body)) - self.mox.ReplayAll() - - rsrc = self.mgr._post(self.url, self.body, "hello") - self.assertEqual(rsrc.hi, 1) - - rsrc = self.mgr._post(self.url, self.body, "hello", return_raw=True) - self.assertEqual(rsrc["hi"], 1) - - def test_put(self): - self.client.put = self.mox.CreateMockAnything() - self.client.put(self.url, body=self.body).AndReturn((None, self.body)) - self.client.put(self.url, body=self.body).AndReturn((None, self.body)) - self.mox.ReplayAll() - - rsrc = self.mgr._put(self.url, self.body, "hello") - self.assertEqual(rsrc.hi, 1) - - rsrc = self.mgr._put(self.url, self.body) - self.assertEqual(rsrc.hello["hi"], 1) - - def test_patch(self): - self.client.patch = self.mox.CreateMockAnything() - self.client.patch(self.url, body=self.body).AndReturn( - (None, self.body)) - self.client.patch(self.url, body=self.body).AndReturn( - (None, self.body)) - self.mox.ReplayAll() - - rsrc = self.mgr._patch(self.url, self.body, "hello") - self.assertEqual(rsrc.hi, 1) - - rsrc = self.mgr._patch(self.url, self.body) - self.assertEqual(rsrc.hello["hi"], 1) - - def test_update(self): - self.client.patch = self.mox.CreateMockAnything() - self.client.put = self.mox.CreateMockAnything() - self.client.patch( - self.url, body=self.body, management=False).AndReturn((None, - self.body)) - self.client.put(self.url, body=None, management=True).AndReturn( - (None, self.body)) - self.mox.ReplayAll() - - rsrc = self.mgr._update( - self.url, body=self.body, response_key="hello", method="PATCH", - management=False) - self.assertEqual(rsrc.hi, 1) - - rsrc = self.mgr._update( - self.url, body=None, response_key="hello", method="PUT", - management=True) - self.assertEqual(rsrc.hi, 1) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_cms.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_cms.py deleted file mode 100644 index 019730d6be..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_cms.py +++ /dev/null @@ -1,160 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import errno -import os -import subprocess - -import mock -import testresources -from testtools import matchers - -from keystoneclient.common import cms -from keystoneclient import exceptions -from keystoneclient.tests.unit import client_fixtures -from keystoneclient.tests.unit import utils - - -class CMSTest(utils.TestCase, testresources.ResourcedTestCase): - - """Unit tests for the keystoneclient.common.cms module.""" - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def __init__(self, *args, **kwargs): - super(CMSTest, self).__init__(*args, **kwargs) - process = subprocess.Popen(['openssl', 'version'], - stdout=subprocess.PIPE) - out, err = process.communicate() - # Example output: 'OpenSSL 0.9.8za 5 Jun 2014' - openssl_version = out.split()[1] - - if err or openssl_version.startswith(b'0'): - raise Exception('Your version of OpenSSL is not supported. ' - 'You will need to update it to 1.0 or later.') - - def test_cms_verify(self): - self.assertRaises(exceptions.CertificateConfigError, - cms.cms_verify, - 'data', - 'no_exist_cert_file', - 'no_exist_ca_file') - - def test_token_tocms_to_token(self): - with open(os.path.join(client_fixtures.CMSDIR, - 'auth_token_scoped.pem')) as f: - AUTH_TOKEN_SCOPED_CMS = f.read() - - self.assertEqual(cms.token_to_cms(self.examples.SIGNED_TOKEN_SCOPED), - AUTH_TOKEN_SCOPED_CMS) - - tok = cms.cms_to_token(cms.token_to_cms( - self.examples.SIGNED_TOKEN_SCOPED)) - self.assertEqual(tok, self.examples.SIGNED_TOKEN_SCOPED) - - def test_asn1_token(self): - self.assertTrue(cms.is_asn1_token(self.examples.SIGNED_TOKEN_SCOPED)) - self.assertFalse(cms.is_asn1_token('FOOBAR')) - - def test_cms_sign_token_no_files(self): - self.assertRaises(subprocess.CalledProcessError, - cms.cms_sign_token, - self.examples.TOKEN_SCOPED_DATA, - '/no/such/file', '/no/such/key') - - def test_cms_sign_token_no_files_pkiz(self): - self.assertRaises(subprocess.CalledProcessError, - cms.pkiz_sign, - self.examples.TOKEN_SCOPED_DATA, - '/no/such/file', '/no/such/key') - - def test_cms_sign_token_success(self): - self.assertTrue( - cms.pkiz_sign(self.examples.TOKEN_SCOPED_DATA, - self.examples.SIGNING_CERT_FILE, - self.examples.SIGNING_KEY_FILE)) - - def test_cms_verify_token_no_files(self): - self.assertRaises(exceptions.CertificateConfigError, - cms.cms_verify, - self.examples.SIGNED_TOKEN_SCOPED, - '/no/such/file', '/no/such/key') - - def test_cms_verify_token_no_oserror(self): - def raise_OSError(*args): - e = OSError() - e.errno = errno.EPIPE - raise e - - with mock.patch('subprocess.Popen.communicate', new=raise_OSError): - try: - cms.cms_verify("x", '/no/such/file', '/no/such/key') - except exceptions.CertificateConfigError as e: - self.assertIn('/no/such/file', e.output) - self.assertIn('Hit OSError ', e.output) - else: - self.fail('Expected exceptions.CertificateConfigError') - - def test_cms_verify_token_scoped(self): - cms_content = cms.token_to_cms(self.examples.SIGNED_TOKEN_SCOPED) - self.assertTrue(cms.cms_verify(cms_content, - self.examples.SIGNING_CERT_FILE, - self.examples.SIGNING_CA_FILE)) - - def test_cms_verify_token_scoped_expired(self): - cms_content = cms.token_to_cms( - self.examples.SIGNED_TOKEN_SCOPED_EXPIRED) - self.assertTrue(cms.cms_verify(cms_content, - self.examples.SIGNING_CERT_FILE, - self.examples.SIGNING_CA_FILE)) - - def test_cms_verify_token_unscoped(self): - cms_content = cms.token_to_cms(self.examples.SIGNED_TOKEN_UNSCOPED) - self.assertTrue(cms.cms_verify(cms_content, - self.examples.SIGNING_CERT_FILE, - self.examples.SIGNING_CA_FILE)) - - def test_cms_verify_token_v3_scoped(self): - cms_content = cms.token_to_cms(self.examples.SIGNED_v3_TOKEN_SCOPED) - self.assertTrue(cms.cms_verify(cms_content, - self.examples.SIGNING_CERT_FILE, - self.examples.SIGNING_CA_FILE)) - - def test_cms_hash_token_no_token_id(self): - token_id = None - self.assertThat(cms.cms_hash_token(token_id), matchers.Is(None)) - - def test_cms_hash_token_not_pki(self): - """If the token_id is not a PKI token then it returns the token_id.""" - token = 'something' - self.assertFalse(cms.is_asn1_token(token)) - self.assertThat(cms.cms_hash_token(token), matchers.Is(token)) - - def test_cms_hash_token_default_md5(self): - """The default hash method is md5.""" - token = self.examples.SIGNED_TOKEN_SCOPED - token_id_default = cms.cms_hash_token(token) - token_id_md5 = cms.cms_hash_token(token, mode='md5') - self.assertThat(token_id_default, matchers.Equals(token_id_md5)) - # md5 hash is 32 chars. - self.assertThat(token_id_default, matchers.HasLength(32)) - - def test_cms_hash_token_sha256(self): - """Can also hash with sha256.""" - token = self.examples.SIGNED_TOKEN_SCOPED - token_id = cms.cms_hash_token(token, mode='sha256') - # sha256 hash is 64 chars. - self.assertThat(token_id, matchers.HasLength(64)) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_discovery.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_discovery.py deleted file mode 100644 index 76aaf03775..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_discovery.py +++ /dev/null @@ -1,805 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import uuid - -from oslo_serialization import jsonutils -import six -from testtools import matchers - -from keystoneclient import _discover -from keystoneclient.auth import token_endpoint -from keystoneclient import client -from keystoneclient import discover -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient import session -from keystoneclient.tests.unit import utils -from keystoneclient.v2_0 import client as v2_client -from keystoneclient.v3 import client as v3_client - - -BASE_HOST = 'http://keystone.example.com' -BASE_URL = "%s:5000/" % BASE_HOST -UPDATED = '2013-03-06T00:00:00Z' - -TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "adminURL": "%s:8774/v1.0" % BASE_HOST, - "region": "RegionOne", - "internalURL": "%s://127.0.0.1:8774/v1.0" % BASE_HOST, - "publicURL": "%s:8774/v1.0/" % BASE_HOST - }], - "type": "nova_compat", - "name": "nova_compat" -}, { - "endpoints": [{ - "adminURL": "http://nova/novapi/admin", - "region": "RegionOne", - "internalURL": "http://nova/novapi/internal", - "publicURL": "http://nova/novapi/public" - }], - "type": "compute", - "name": "nova" -}, { - "endpoints": [{ - "adminURL": "http://glance/glanceapi/admin", - "region": "RegionOne", - "internalURL": "http://glance/glanceapi/internal", - "publicURL": "http://glance/glanceapi/public" - }], - "type": "image", - "name": "glance" -}, { - "endpoints": [{ - "adminURL": "%s:35357/v2.0" % BASE_HOST, - "region": "RegionOne", - "internalURL": "%s:5000/v2.0" % BASE_HOST, - "publicURL": "%s:5000/v2.0" % BASE_HOST - }], - "type": "identity", - "name": "keystone" -}, { - "endpoints": [{ - "adminURL": "http://swift/swiftapi/admin", - "region": "RegionOne", - "internalURL": "http://swift/swiftapi/internal", - "publicURL": "http://swift/swiftapi/public" - }], - "type": "object-store", - "name": "swift" -}] - -V2_URL = "%sv2.0" % BASE_URL -V2_VERSION = fixture.V2Discovery(V2_URL) -V2_VERSION.updated_str = UPDATED - -V2_AUTH_RESPONSE = jsonutils.dumps({ - "access": { - "token": { - "expires": "2020-01-01T00:00:10.000123Z", - "id": 'fakeToken', - "tenant": { - "id": '1' - }, - }, - "user": { - "id": 'test' - }, - "serviceCatalog": TEST_SERVICE_CATALOG, - }, -}) - -V3_URL = "%sv3" % BASE_URL -V3_VERSION = fixture.V3Discovery(V3_URL) -V3_MEDIA_TYPES = V3_VERSION.media_types -V3_VERSION.updated_str = UPDATED - -V3_TOKEN = six.u('3e2813b7ba0b4006840c3825860b86ed'), -V3_AUTH_RESPONSE = jsonutils.dumps({ - "token": { - "methods": [ - "token", - "password" - ], - - "expires_at": "2020-01-01T00:00:10.000123Z", - "project": { - "domain": { - "id": '1', - "name": 'test-domain' - }, - "id": '1', - "name": 'test-project' - }, - "user": { - "domain": { - "id": '1', - "name": 'test-domain' - }, - "id": '1', - "name": 'test-user' - }, - "issued_at": "2013-05-29T16:55:21.468960Z", - }, -}) - -CINDER_EXAMPLES = { - "versions": [ - { - "status": "CURRENT", - "updated": "2012-01-04T11:33:21Z", - "id": "v1.0", - "links": [ - { - "href": "%sv1/" % BASE_URL, - "rel": "self" - } - ] - }, - { - "status": "CURRENT", - "updated": "2012-11-21T11:33:21Z", - "id": "v2.0", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] - } - ] -} - -GLANCE_EXAMPLES = { - "versions": [ - { - "status": "CURRENT", - "id": "v2.2", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] - }, - { - "status": "SUPPORTED", - "id": "v2.1", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] - }, - { - "status": "SUPPORTED", - "id": "v2.0", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] - }, - { - "status": "CURRENT", - "id": "v1.1", - "links": [ - { - "href": "%sv1/" % BASE_URL, - "rel": "self" - } - ] - }, - { - "status": "SUPPORTED", - "id": "v1.0", - "links": [ - { - "href": "%sv1/" % BASE_URL, - "rel": "self" - } - ] - } - ] -} - - -def _create_version_list(versions): - return jsonutils.dumps({'versions': {'values': versions}}) - - -def _create_single_version(version): - return jsonutils.dumps({'version': version}) - - -V3_VERSION_LIST = _create_version_list([V3_VERSION, V2_VERSION]) -V2_VERSION_LIST = _create_version_list([V2_VERSION]) - -V3_VERSION_ENTRY = _create_single_version(V3_VERSION) -V2_VERSION_ENTRY = _create_single_version(V2_VERSION) - - -class AvailableVersionsTests(utils.TestCase): - - def test_available_versions_basics(self): - examples = {'keystone': V3_VERSION_LIST, - 'cinder': jsonutils.dumps(CINDER_EXAMPLES), - 'glance': jsonutils.dumps(GLANCE_EXAMPLES)} - - for path, text in six.iteritems(examples): - url = "%s%s" % (BASE_URL, path) - - self.requests_mock.get(url, status_code=300, text=text) - versions = discover.available_versions(url) - - for v in versions: - for n in ('id', 'status', 'links'): - msg = '%s missing from %s version data' % (n, path) - self.assertThat(v, matchers.Annotate(msg, - matchers.Contains(n))) - - def test_available_versions_individual(self): - self.requests_mock.get(V3_URL, status_code=200, text=V3_VERSION_ENTRY) - - versions = discover.available_versions(V3_URL) - - for v in versions: - self.assertEqual(v['id'], 'v3.0') - self.assertEqual(v['status'], 'stable') - self.assertIn('media-types', v) - self.assertIn('links', v) - - def test_available_keystone_data(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - versions = discover.available_versions(BASE_URL) - self.assertEqual(2, len(versions)) - - for v in versions: - self.assertIn(v['id'], ('v2.0', 'v3.0')) - self.assertEqual(v['updated'], UPDATED) - self.assertEqual(v['status'], 'stable') - - if v['id'] == 'v3.0': - self.assertEqual(v['media-types'], V3_MEDIA_TYPES) - - def test_available_cinder_data(self): - text = jsonutils.dumps(CINDER_EXAMPLES) - self.requests_mock.get(BASE_URL, status_code=300, text=text) - - versions = discover.available_versions(BASE_URL) - self.assertEqual(2, len(versions)) - - for v in versions: - self.assertEqual(v['status'], 'CURRENT') - if v['id'] == 'v1.0': - self.assertEqual(v['updated'], '2012-01-04T11:33:21Z') - elif v['id'] == 'v2.0': - self.assertEqual(v['updated'], '2012-11-21T11:33:21Z') - else: - self.fail("Invalid version found") - - def test_available_glance_data(self): - text = jsonutils.dumps(GLANCE_EXAMPLES) - self.requests_mock.get(BASE_URL, status_code=200, text=text) - - versions = discover.available_versions(BASE_URL) - self.assertEqual(5, len(versions)) - - for v in versions: - if v['id'] in ('v2.2', 'v1.1'): - self.assertEqual(v['status'], 'CURRENT') - elif v['id'] in ('v2.1', 'v2.0', 'v1.0'): - self.assertEqual(v['status'], 'SUPPORTED') - else: - self.fail("Invalid version found") - - -class ClientDiscoveryTests(utils.TestCase): - - def assertCreatesV3(self, **kwargs): - self.requests_mock.post('%s/auth/tokens' % V3_URL, - text=V3_AUTH_RESPONSE, - headers={'X-Subject-Token': V3_TOKEN}) - - kwargs.setdefault('username', 'foo') - kwargs.setdefault('password', 'bar') - keystone = client.Client(**kwargs) - self.assertIsInstance(keystone, v3_client.Client) - return keystone - - def assertCreatesV2(self, **kwargs): - self.requests_mock.post("%s/tokens" % V2_URL, text=V2_AUTH_RESPONSE) - - kwargs.setdefault('username', 'foo') - kwargs.setdefault('password', 'bar') - keystone = client.Client(**kwargs) - self.assertIsInstance(keystone, v2_client.Client) - return keystone - - def assertVersionNotAvailable(self, **kwargs): - kwargs.setdefault('username', 'foo') - kwargs.setdefault('password', 'bar') - - self.assertRaises(exceptions.VersionNotAvailable, - client.Client, **kwargs) - - def assertDiscoveryFailure(self, **kwargs): - kwargs.setdefault('username', 'foo') - kwargs.setdefault('password', 'bar') - - self.assertRaises(exceptions.DiscoveryFailure, - client.Client, **kwargs) - - def test_discover_v3(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - self.assertCreatesV3(auth_url=BASE_URL) - - def test_discover_v2(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V2_VERSION_LIST) - self.requests_mock.post("%s/tokens" % V2_URL, text=V2_AUTH_RESPONSE) - - self.assertCreatesV2(auth_url=BASE_URL) - - def test_discover_endpoint_v2(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V2_VERSION_LIST) - self.assertCreatesV2(endpoint=BASE_URL, token='fake-token') - - def test_discover_endpoint_v3(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - self.assertCreatesV3(endpoint=BASE_URL, token='fake-token') - - def test_discover_invalid_major_version(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - self.assertVersionNotAvailable(auth_url=BASE_URL, version=5) - - def test_discover_200_response_fails(self): - self.requests_mock.get(BASE_URL, text='ok') - self.assertDiscoveryFailure(auth_url=BASE_URL) - - def test_discover_minor_greater_than_available_fails(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - self.assertVersionNotAvailable(endpoint=BASE_URL, version=3.4) - - def test_discover_individual_version_v2(self): - self.requests_mock.get(V2_URL, text=V2_VERSION_ENTRY) - - self.assertCreatesV2(auth_url=V2_URL) - - def test_discover_individual_version_v3(self): - self.requests_mock.get(V3_URL, text=V3_VERSION_ENTRY) - - self.assertCreatesV3(auth_url=V3_URL) - - def test_discover_individual_endpoint_v2(self): - self.requests_mock.get(V2_URL, text=V2_VERSION_ENTRY) - self.assertCreatesV2(endpoint=V2_URL, token='fake-token') - - def test_discover_individual_endpoint_v3(self): - self.requests_mock.get(V3_URL, text=V3_VERSION_ENTRY) - self.assertCreatesV3(endpoint=V3_URL, token='fake-token') - - def test_discover_fail_to_create_bad_individual_version(self): - self.requests_mock.get(V2_URL, text=V2_VERSION_ENTRY) - self.requests_mock.get(V3_URL, text=V3_VERSION_ENTRY) - - self.assertVersionNotAvailable(auth_url=V2_URL, version=3) - self.assertVersionNotAvailable(auth_url=V3_URL, version=2) - - def test_discover_unstable_versions(self): - version_list = fixture.DiscoveryList(BASE_URL, v3_status='beta') - self.requests_mock.get(BASE_URL, status_code=300, json=version_list) - - self.assertCreatesV2(auth_url=BASE_URL) - self.assertVersionNotAvailable(auth_url=BASE_URL, version=3) - self.assertCreatesV3(auth_url=BASE_URL, unstable=True) - - def test_discover_forwards_original_ip(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - ip = '192.168.1.1' - self.assertCreatesV3(auth_url=BASE_URL, original_ip=ip) - - self.assertThat(self.requests_mock.last_request.headers['forwarded'], - matchers.Contains(ip)) - - def test_discover_bad_args(self): - self.assertRaises(exceptions.DiscoveryFailure, - client.Client) - - def test_discover_bad_response(self): - self.requests_mock.get(BASE_URL, status_code=300, json={'FOO': 'BAR'}) - self.assertDiscoveryFailure(auth_url=BASE_URL) - - def test_discovery_ignore_invalid(self): - resp = [{'id': 'v3.0', - 'links': [1, 2, 3, 4], # invalid links - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED}] - self.requests_mock.get(BASE_URL, status_code=300, - text=_create_version_list(resp)) - self.assertDiscoveryFailure(auth_url=BASE_URL) - - def test_ignore_entry_without_links(self): - v3 = V3_VERSION.copy() - v3['links'] = [] - self.requests_mock.get(BASE_URL, status_code=300, - text=_create_version_list([v3, V2_VERSION])) - self.assertCreatesV2(auth_url=BASE_URL) - - def test_ignore_entry_without_status(self): - v3 = V3_VERSION.copy() - del v3['status'] - self.requests_mock.get(BASE_URL, status_code=300, - text=_create_version_list([v3, V2_VERSION])) - self.assertCreatesV2(auth_url=BASE_URL) - - def test_greater_version_than_required(self): - versions = fixture.DiscoveryList(BASE_URL, v3_id='v3.6') - self.requests_mock.get(BASE_URL, json=versions) - self.assertCreatesV3(auth_url=BASE_URL, version=(3, 4)) - - def test_lesser_version_than_required(self): - versions = fixture.DiscoveryList(BASE_URL, v3_id='v3.4') - self.requests_mock.get(BASE_URL, json=versions) - self.assertVersionNotAvailable(auth_url=BASE_URL, version=(3, 6)) - - def test_bad_response(self): - self.requests_mock.get(BASE_URL, status_code=300, text="Ugly Duckling") - self.assertDiscoveryFailure(auth_url=BASE_URL) - - def test_pass_client_arguments(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V2_VERSION_LIST) - kwargs = {'original_ip': '100', 'use_keyring': False, - 'stale_duration': 15} - - cl = self.assertCreatesV2(auth_url=BASE_URL, **kwargs) - - self.assertEqual(cl.original_ip, '100') - self.assertEqual(cl.stale_duration, 15) - self.assertFalse(cl.use_keyring) - - def test_overriding_stored_kwargs(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - self.requests_mock.post("%s/auth/tokens" % V3_URL, - text=V3_AUTH_RESPONSE, - headers={'X-Subject-Token': V3_TOKEN}) - - disc = discover.Discover(auth_url=BASE_URL, debug=False, - username='foo') - client = disc.create_client(debug=True, password='bar') - - self.assertIsInstance(client, v3_client.Client) - self.assertTrue(client.debug_log) - self.assertFalse(disc._client_kwargs['debug']) - self.assertEqual(client.username, 'foo') - self.assertEqual(client.password, 'bar') - - def test_available_versions(self): - self.requests_mock.get(BASE_URL, - status_code=300, - text=V3_VERSION_ENTRY) - disc = discover.Discover(auth_url=BASE_URL) - - versions = disc.available_versions() - self.assertEqual(1, len(versions)) - self.assertEqual(V3_VERSION, versions[0]) - - def test_unknown_client_version(self): - V4_VERSION = {'id': 'v4.0', - 'links': [{'href': 'http://url', 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED} - versions = fixture.DiscoveryList() - versions.add_version(V4_VERSION) - self.requests_mock.get(BASE_URL, status_code=300, json=versions) - - disc = discover.Discover(auth_url=BASE_URL) - self.assertRaises(exceptions.DiscoveryFailure, - disc.create_client, version=4) - - def test_discovery_fail_for_missing_v3(self): - versions = fixture.DiscoveryList(v2=True, v3=False) - self.requests_mock.get(BASE_URL, status_code=300, json=versions) - - disc = discover.Discover(auth_url=BASE_URL) - self.assertRaises(exceptions.DiscoveryFailure, - disc.create_client, version=(3, 0)) - - def _do_discovery_call(self, token=None, **kwargs): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - if not token: - token = uuid.uuid4().hex - - url = 'http://testurl' - a = token_endpoint.Token(url, token) - s = session.Session(auth=a) - - # will default to true as there is a plugin on the session - discover.Discover(s, auth_url=BASE_URL, **kwargs) - - self.assertEqual(BASE_URL, self.requests_mock.last_request.url) - - def test_setting_authenticated_true(self): - token = uuid.uuid4().hex - self._do_discovery_call(token) - self.assertRequestHeaderEqual('X-Auth-Token', token) - - def test_setting_authenticated_false(self): - self._do_discovery_call(authenticated=False) - self.assertNotIn('X-Auth-Token', - self.requests_mock.last_request.headers) - - -class DiscoverQueryTests(utils.TestCase): - - def test_available_keystone_data(self): - self.requests_mock.get(BASE_URL, status_code=300, text=V3_VERSION_LIST) - - disc = discover.Discover(auth_url=BASE_URL) - versions = disc.version_data() - - self.assertEqual((2, 0), versions[0]['version']) - self.assertEqual('stable', versions[0]['raw_status']) - self.assertEqual(V2_URL, versions[0]['url']) - self.assertEqual((3, 0), versions[1]['version']) - self.assertEqual('stable', versions[1]['raw_status']) - self.assertEqual(V3_URL, versions[1]['url']) - - version = disc.data_for('v3.0') - self.assertEqual((3, 0), version['version']) - self.assertEqual('stable', version['raw_status']) - self.assertEqual(V3_URL, version['url']) - - version = disc.data_for(2) - self.assertEqual((2, 0), version['version']) - self.assertEqual('stable', version['raw_status']) - self.assertEqual(V2_URL, version['url']) - - self.assertIsNone(disc.url_for('v4')) - self.assertEqual(V3_URL, disc.url_for('v3')) - self.assertEqual(V2_URL, disc.url_for('v2')) - - def test_available_cinder_data(self): - text = jsonutils.dumps(CINDER_EXAMPLES) - self.requests_mock.get(BASE_URL, status_code=300, text=text) - - v1_url = "%sv1/" % BASE_URL - v2_url = "%sv2/" % BASE_URL - - disc = discover.Discover(auth_url=BASE_URL) - versions = disc.version_data() - - self.assertEqual((1, 0), versions[0]['version']) - self.assertEqual('CURRENT', versions[0]['raw_status']) - self.assertEqual(v1_url, versions[0]['url']) - self.assertEqual((2, 0), versions[1]['version']) - self.assertEqual('CURRENT', versions[1]['raw_status']) - self.assertEqual(v2_url, versions[1]['url']) - - version = disc.data_for('v2.0') - self.assertEqual((2, 0), version['version']) - self.assertEqual('CURRENT', version['raw_status']) - self.assertEqual(v2_url, version['url']) - - version = disc.data_for(1) - self.assertEqual((1, 0), version['version']) - self.assertEqual('CURRENT', version['raw_status']) - self.assertEqual(v1_url, version['url']) - - self.assertIsNone(disc.url_for('v3')) - self.assertEqual(v2_url, disc.url_for('v2')) - self.assertEqual(v1_url, disc.url_for('v1')) - - def test_available_glance_data(self): - text = jsonutils.dumps(GLANCE_EXAMPLES) - self.requests_mock.get(BASE_URL, text=text) - - v1_url = "%sv1/" % BASE_URL - v2_url = "%sv2/" % BASE_URL - - disc = discover.Discover(auth_url=BASE_URL) - versions = disc.version_data() - - self.assertEqual((1, 0), versions[0]['version']) - self.assertEqual('SUPPORTED', versions[0]['raw_status']) - self.assertEqual(v1_url, versions[0]['url']) - self.assertEqual((1, 1), versions[1]['version']) - self.assertEqual('CURRENT', versions[1]['raw_status']) - self.assertEqual(v1_url, versions[1]['url']) - self.assertEqual((2, 0), versions[2]['version']) - self.assertEqual('SUPPORTED', versions[2]['raw_status']) - self.assertEqual(v2_url, versions[2]['url']) - self.assertEqual((2, 1), versions[3]['version']) - self.assertEqual('SUPPORTED', versions[3]['raw_status']) - self.assertEqual(v2_url, versions[3]['url']) - self.assertEqual((2, 2), versions[4]['version']) - self.assertEqual('CURRENT', versions[4]['raw_status']) - self.assertEqual(v2_url, versions[4]['url']) - - for ver in (2, 2.1, 2.2): - version = disc.data_for(ver) - self.assertEqual((2, 2), version['version']) - self.assertEqual('CURRENT', version['raw_status']) - self.assertEqual(v2_url, version['url']) - self.assertEqual(v2_url, disc.url_for(ver)) - - for ver in (1, 1.1): - version = disc.data_for(ver) - self.assertEqual((1, 1), version['version']) - self.assertEqual('CURRENT', version['raw_status']) - self.assertEqual(v1_url, version['url']) - self.assertEqual(v1_url, disc.url_for(ver)) - - self.assertIsNone(disc.url_for('v3')) - self.assertIsNone(disc.url_for('v2.3')) - - def test_allow_deprecated(self): - status = 'deprecated' - version_list = [{'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': status, - 'updated': UPDATED}] - text = jsonutils.dumps({'versions': version_list}) - self.requests_mock.get(BASE_URL, text=text) - - disc = discover.Discover(auth_url=BASE_URL) - - # deprecated is allowed by default - versions = disc.version_data(allow_deprecated=False) - self.assertEqual(0, len(versions)) - - versions = disc.version_data(allow_deprecated=True) - self.assertEqual(1, len(versions)) - self.assertEqual(status, versions[0]['raw_status']) - self.assertEqual(V3_URL, versions[0]['url']) - self.assertEqual((3, 0), versions[0]['version']) - - def test_allow_experimental(self): - status = 'experimental' - version_list = [{'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': status, - 'updated': UPDATED}] - text = jsonutils.dumps({'versions': version_list}) - self.requests_mock.get(BASE_URL, text=text) - - disc = discover.Discover(auth_url=BASE_URL) - - versions = disc.version_data() - self.assertEqual(0, len(versions)) - - versions = disc.version_data(allow_experimental=True) - self.assertEqual(1, len(versions)) - self.assertEqual(status, versions[0]['raw_status']) - self.assertEqual(V3_URL, versions[0]['url']) - self.assertEqual((3, 0), versions[0]['version']) - - def test_allow_unknown(self): - status = 'abcdef' - version_list = fixture.DiscoveryList(BASE_URL, v2=False, - v3_status=status) - self.requests_mock.get(BASE_URL, json=version_list) - disc = discover.Discover(auth_url=BASE_URL) - - versions = disc.version_data() - self.assertEqual(0, len(versions)) - - versions = disc.version_data(allow_unknown=True) - self.assertEqual(1, len(versions)) - self.assertEqual(status, versions[0]['raw_status']) - self.assertEqual(V3_URL, versions[0]['url']) - self.assertEqual((3, 0), versions[0]['version']) - - def test_ignoring_invalid_lnks(self): - version_list = [{'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED}, - {'id': 'v3.1', - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED}, - {'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED, - 'links': [{'href': V3_URL, 'rel': 'self'}], - }] - - text = jsonutils.dumps({'versions': version_list}) - self.requests_mock.get(BASE_URL, text=text) - - disc = discover.Discover(auth_url=BASE_URL) - - # raw_version_data will return all choices, even invalid ones - versions = disc.raw_version_data() - self.assertEqual(3, len(versions)) - - # only the version with both id and links will be actually returned - versions = disc.version_data() - self.assertEqual(1, len(versions)) - - -class CatalogHackTests(utils.TestCase): - - TEST_URL = 'http://keystone.server:5000/v2.0' - OTHER_URL = 'http://other.server:5000/path' - - IDENTITY = 'identity' - - BASE_URL = 'http://keystone.server:5000/' - V2_URL = BASE_URL + 'v2.0' - V3_URL = BASE_URL + 'v3' - - def setUp(self): - super(CatalogHackTests, self).setUp() - self.hacks = _discover._VersionHacks() - self.hacks.add_discover_hack(self.IDENTITY, - re.compile('/v2.0/?$'), - '/') - - def test_version_hacks(self): - self.assertEqual(self.BASE_URL, - self.hacks.get_discover_hack(self.IDENTITY, - self.V2_URL)) - - self.assertEqual(self.BASE_URL, - self.hacks.get_discover_hack(self.IDENTITY, - self.V2_URL + '/')) - - self.assertEqual(self.OTHER_URL, - self.hacks.get_discover_hack(self.IDENTITY, - self.OTHER_URL)) - - def test_ignored_non_service_type(self): - self.assertEqual(self.V2_URL, - self.hacks.get_discover_hack('other', self.V2_URL)) - - -class DiscoverUtils(utils.TestCase): - - def test_version_number(self): - def assertVersion(inp, out): - self.assertEqual(out, _discover.normalize_version_number(inp)) - - def versionRaises(inp): - self.assertRaises(TypeError, - _discover.normalize_version_number, - inp) - - assertVersion('v1.2', (1, 2)) - assertVersion('v11', (11, 0)) - assertVersion('1.2', (1, 2)) - assertVersion('1.5.1', (1, 5, 1)) - assertVersion('1', (1, 0)) - assertVersion(1, (1, 0)) - assertVersion(5.2, (5, 2)) - assertVersion((6, 1), (6, 1)) - assertVersion([1, 4], (1, 4)) - - versionRaises('hello') - versionRaises('1.a') - versionRaises('vacuum') diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_ec2utils.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_ec2utils.py deleted file mode 100644 index 71fc176b51..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_ec2utils.py +++ /dev/null @@ -1,262 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import unicode_literals - -import testtools - -from keystoneclient.contrib.ec2 import utils - - -class Ec2SignerTest(testtools.TestCase): - - def setUp(self): - super(Ec2SignerTest, self).setUp() - self.access = '966afbde20b84200ae4e62e09acf46b2' - self.secret = '89cdf9e94e2643cab35b8b8ac5a51f83' - self.signer = utils.Ec2Signer(self.secret) - - def test_v4_creds_header(self): - auth_str = 'AWS4-HMAC-SHA256 blah' - credentials = {'host': '127.0.0.1', - 'verb': 'GET', - 'path': '/v1/', - 'params': {}, - 'headers': {'Authorization': auth_str}} - self.assertTrue(self.signer._v4_creds(credentials)) - - def test_v4_creds_param(self): - credentials = {'host': '127.0.0.1', - 'verb': 'GET', - 'path': '/v1/', - 'params': {'X-Amz-Algorithm': 'AWS4-HMAC-SHA256'}, - 'headers': {}} - self.assertTrue(self.signer._v4_creds(credentials)) - - def test_v4_creds_false(self): - credentials = {'host': '127.0.0.1', - 'verb': 'GET', - 'path': '/v1/', - 'params': {'SignatureVersion': '0', - 'AWSAccessKeyId': self.access, - 'Timestamp': '2012-11-27T11:47:02Z', - 'Action': 'Foo'}} - self.assertFalse(self.signer._v4_creds(credentials)) - - def test_generate_0(self): - """Test generate function for v0 signature.""" - credentials = {'host': '127.0.0.1', - 'verb': 'GET', - 'path': '/v1/', - 'params': {'SignatureVersion': '0', - 'AWSAccessKeyId': self.access, - 'Timestamp': '2012-11-27T11:47:02Z', - 'Action': 'Foo'}} - signature = self.signer.generate(credentials) - expected = 'SmXQEZAUdQw5glv5mX8mmixBtas=' - self.assertEqual(signature, expected) - - def test_generate_1(self): - """Test generate function for v1 signature.""" - credentials = {'host': '127.0.0.1', - 'verb': 'GET', - 'path': '/v1/', - 'params': {'SignatureVersion': '1', - 'AWSAccessKeyId': self.access}} - signature = self.signer.generate(credentials) - expected = 'VRnoQH/EhVTTLhwRLfuL7jmFW9c=' - self.assertEqual(signature, expected) - - def test_generate_v2_SHA256(self): - """Test generate function for v2 signature, SHA256.""" - credentials = {'host': '127.0.0.1', - 'verb': 'GET', - 'path': '/v1/', - 'params': {'SignatureVersion': '2', - 'AWSAccessKeyId': self.access}} - signature = self.signer.generate(credentials) - expected = 'odsGmT811GffUO0Eu13Pq+xTzKNIjJ6NhgZU74tYX/w=' - self.assertEqual(signature, expected) - - def test_generate_v2_SHA1(self): - """Test generate function for v2 signature, SHA1.""" - credentials = {'host': '127.0.0.1', - 'verb': 'GET', - 'path': '/v1/', - 'params': {'SignatureVersion': '2', - 'AWSAccessKeyId': self.access}} - self.signer.hmac_256 = None - signature = self.signer.generate(credentials) - expected = 'ZqCxMI4ZtTXWI175743mJ0hy/Gc=' - self.assertEqual(signature, expected) - - def test_generate_v4(self): - """Test v4 generator with data from AWS docs example. - - see: - http://docs.aws.amazon.com/general/latest/gr/ - sigv4-create-canonical-request.html - and - http://docs.aws.amazon.com/general/latest/gr/ - sigv4-signed-request-examples.html - """ - # Create a new signer object with the AWS example key - secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY' - signer = utils.Ec2Signer(secret) - - body_hash = ('b6359072c78d70ebee1e81adcbab4f0' - '1bf2c23245fa365ef83fe8f1f955085e2') - auth_str = ('AWS4-HMAC-SHA256 ' - 'Credential=AKIAIOSFODNN7EXAMPLE/20110909/' - 'us-east-1/iam/aws4_request,' - 'SignedHeaders=content-type;host;x-amz-date,') - headers = {'Content-type': - 'application/x-www-form-urlencoded; charset=utf-8', - 'X-Amz-Date': '20110909T233600Z', - 'Host': 'iam.amazonaws.com', - 'Authorization': auth_str} - # Note the example in the AWS docs is inconsistent, previous - # examples specify no query string, but the final POST example - # does, apparently incorrectly since an empty parameter list - # aligns all steps and the final signature with the examples - params = {'Action': 'CreateUser', - 'UserName': 'NewUser', - 'Version': '2010-05-08', - 'X-Amz-Algorithm': 'AWS4-HMAC-SHA256', - 'X-Amz-Credential': 'AKIAEXAMPLE/20140611/' - 'us-east-1/iam/aws4_request', - 'X-Amz-Date': '20140611T231318Z', - 'X-Amz-Expires': '30', - 'X-Amz-SignedHeaders': 'host', - 'X-Amz-Signature': 'ced6826de92d2bdeed8f846f0bf508e8' - '559e98e4b0199114b84c54174deb456c'} - credentials = {'host': 'iam.amazonaws.com', - 'verb': 'POST', - 'path': '/', - 'params': params, - 'headers': headers, - 'body_hash': body_hash} - signature = signer.generate(credentials) - expected = ('ced6826de92d2bdeed8f846f0bf508e8' - '559e98e4b0199114b84c54174deb456c') - self.assertEqual(signature, expected) - - def test_generate_v4_port(self): - """Test v4 generator with host:port format.""" - # Create a new signer object with the AWS example key - secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY' - signer = utils.Ec2Signer(secret) - - body_hash = ('b6359072c78d70ebee1e81adcbab4f0' - '1bf2c23245fa365ef83fe8f1f955085e2') - auth_str = ('AWS4-HMAC-SHA256 ' - 'Credential=AKIAIOSFODNN7EXAMPLE/20110909/' - 'us-east-1/iam/aws4_request,' - 'SignedHeaders=content-type;host;x-amz-date,') - headers = {'Content-type': - 'application/x-www-form-urlencoded; charset=utf-8', - 'X-Amz-Date': '20110909T233600Z', - 'Host': 'foo:8000', - 'Authorization': auth_str} - # Note the example in the AWS docs is inconsistent, previous - # examples specify no query string, but the final POST example - # does, apparently incorrectly since an empty parameter list - # aligns all steps and the final signature with the examples - params = {} - credentials = {'host': 'foo:8000', - 'verb': 'POST', - 'path': '/', - 'params': params, - 'headers': headers, - 'body_hash': body_hash} - signature = signer.generate(credentials) - - expected = ('26dd92ea79aaa49f533d13b1055acdc' - 'd7d7321460d64621f96cc79c4f4d4ab2b') - self.assertEqual(signature, expected) - - def test_generate_v4_port_strip(self): - """Test v4 generator with host:port format, but for an old - (<2.9.3) version of boto, where the port should be stripped - to match boto behavior. - """ - # Create a new signer object with the AWS example key - secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY' - signer = utils.Ec2Signer(secret) - - body_hash = ('b6359072c78d70ebee1e81adcbab4f0' - '1bf2c23245fa365ef83fe8f1f955085e2') - auth_str = ('AWS4-HMAC-SHA256 ' - 'Credential=AKIAIOSFODNN7EXAMPLE/20110909/' - 'us-east-1/iam/aws4_request,' - 'SignedHeaders=content-type;host;x-amz-date,') - headers = {'Content-type': - 'application/x-www-form-urlencoded; charset=utf-8', - 'X-Amz-Date': '20110909T233600Z', - 'Host': 'foo:8000', - 'Authorization': auth_str, - 'User-Agent': 'Boto/2.9.2 (linux2)'} - # Note the example in the AWS docs is inconsistent, previous - # examples specify no query string, but the final POST example - # does, apparently incorrectly since an empty parameter list - # aligns all steps and the final signature with the examples - params = {} - credentials = {'host': 'foo:8000', - 'verb': 'POST', - 'path': '/', - 'params': params, - 'headers': headers, - 'body_hash': body_hash} - signature = signer.generate(credentials) - - expected = ('9a4b2276a5039ada3b90f72ea8ec1745' - '14b92b909fb106b22ad910c5d75a54f4') - self.assertEqual(expected, signature) - - def test_generate_v4_port_nostrip(self): - """Test v4 generator with host:port format, but for an new - (>=2.9.3) version of boto, where the port should not be stripped. - """ - # Create a new signer object with the AWS example key - secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY' - signer = utils.Ec2Signer(secret) - - body_hash = ('b6359072c78d70ebee1e81adcbab4f0' - '1bf2c23245fa365ef83fe8f1f955085e2') - auth_str = ('AWS4-HMAC-SHA256 ' - 'Credential=AKIAIOSFODNN7EXAMPLE/20110909/' - 'us-east-1/iam/aws4_request,' - 'SignedHeaders=content-type;host;x-amz-date,') - headers = {'Content-type': - 'application/x-www-form-urlencoded; charset=utf-8', - 'X-Amz-Date': '20110909T233600Z', - 'Host': 'foo:8000', - 'Authorization': auth_str, - 'User-Agent': 'Boto/2.9.3 (linux2)'} - # Note the example in the AWS docs is inconsistent, previous - # examples specify no query string, but the final POST example - # does, apparently incorrectly since an empty parameter list - # aligns all steps and the final signature with the examples - params = {} - credentials = {'host': 'foo:8000', - 'verb': 'POST', - 'path': '/', - 'params': params, - 'headers': headers, - 'body_hash': body_hash} - signature = signer.generate(credentials) - - expected = ('26dd92ea79aaa49f533d13b1055acdc' - 'd7d7321460d64621f96cc79c4f4d4ab2b') - self.assertEqual(expected, signature) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_fixtures.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_fixtures.py deleted file mode 100644 index f136e7020e..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_fixtures.py +++ /dev/null @@ -1,238 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -import six - -from keystoneclient import fixture -from keystoneclient.tests.unit import utils - - -class V2TokenTests(utils.TestCase): - - def test_unscoped(self): - token_id = uuid.uuid4().hex - user_id = uuid.uuid4().hex - user_name = uuid.uuid4().hex - - token = fixture.V2Token(token_id=token_id, - user_id=user_id, - user_name=user_name) - - self.assertEqual(token_id, token.token_id) - self.assertEqual(token_id, token['access']['token']['id']) - self.assertEqual(user_id, token.user_id) - self.assertEqual(user_id, token['access']['user']['id']) - self.assertEqual(user_name, token.user_name) - self.assertEqual(user_name, token['access']['user']['name']) - - def test_tenant_scoped(self): - tenant_id = uuid.uuid4().hex - tenant_name = uuid.uuid4().hex - - token = fixture.V2Token(tenant_id=tenant_id, - tenant_name=tenant_name) - - self.assertEqual(tenant_id, token.tenant_id) - self.assertEqual(tenant_id, token['access']['token']['tenant']['id']) - self.assertEqual(tenant_name, token.tenant_name) - tn = token['access']['token']['tenant']['name'] - self.assertEqual(tenant_name, tn) - - def test_trust_scoped(self): - trust_id = uuid.uuid4().hex - trustee_user_id = uuid.uuid4().hex - - token = fixture.V2Token(trust_id=trust_id, - trustee_user_id=trustee_user_id) - trust = token['access']['trust'] - - self.assertEqual(trust_id, token.trust_id) - self.assertEqual(trust_id, trust['id']) - self.assertEqual(trustee_user_id, token.trustee_user_id) - self.assertEqual(trustee_user_id, trust['trustee_user_id']) - - def test_roles(self): - role_id1 = uuid.uuid4().hex - role_name1 = uuid.uuid4().hex - role_id2 = uuid.uuid4().hex - role_name2 = uuid.uuid4().hex - - token = fixture.V2Token() - token.add_role(id=role_id1, name=role_name1) - token.add_role(id=role_id2, name=role_name2) - - role_names = token['access']['user']['roles'] - role_ids = token['access']['metadata']['roles'] - - self.assertEqual(set([role_id1, role_id2]), set(role_ids)) - for r in (role_name1, role_name2): - self.assertIn({'name': r}, role_names) - - def test_services(self): - service_type = uuid.uuid4().hex - service_name = uuid.uuid4().hex - region = uuid.uuid4().hex - - public = uuid.uuid4().hex - admin = uuid.uuid4().hex - internal = uuid.uuid4().hex - - token = fixture.V2Token() - svc = token.add_service(type=service_type, name=service_name) - - svc.add_endpoint(public=public, - admin=admin, - internal=internal, - region=region) - - self.assertEqual(1, len(token['access']['serviceCatalog'])) - service = token['access']['serviceCatalog'][0]['endpoints'][0] - - self.assertEqual(public, service['publicURL']) - self.assertEqual(internal, service['internalURL']) - self.assertEqual(admin, service['adminURL']) - self.assertEqual(region, service['region']) - - -class V3TokenTests(utils.TestCase): - - def test_unscoped(self): - user_id = uuid.uuid4().hex - user_name = uuid.uuid4().hex - user_domain_id = uuid.uuid4().hex - user_domain_name = uuid.uuid4().hex - - token = fixture.V3Token(user_id=user_id, - user_name=user_name, - user_domain_id=user_domain_id, - user_domain_name=user_domain_name) - - self.assertEqual(user_id, token.user_id) - self.assertEqual(user_id, token['token']['user']['id']) - self.assertEqual(user_name, token.user_name) - self.assertEqual(user_name, token['token']['user']['name']) - - user_domain = token['token']['user']['domain'] - - self.assertEqual(user_domain_id, token.user_domain_id) - self.assertEqual(user_domain_id, user_domain['id']) - self.assertEqual(user_domain_name, token.user_domain_name) - self.assertEqual(user_domain_name, user_domain['name']) - - def test_project_scoped(self): - project_id = uuid.uuid4().hex - project_name = uuid.uuid4().hex - project_domain_id = uuid.uuid4().hex - project_domain_name = uuid.uuid4().hex - - token = fixture.V3Token(project_id=project_id, - project_name=project_name, - project_domain_id=project_domain_id, - project_domain_name=project_domain_name) - - self.assertEqual(project_id, token.project_id) - self.assertEqual(project_id, token['token']['project']['id']) - self.assertEqual(project_name, token.project_name) - self.assertEqual(project_name, token['token']['project']['name']) - - project_domain = token['token']['project']['domain'] - - self.assertEqual(project_domain_id, token.project_domain_id) - self.assertEqual(project_domain_id, project_domain['id']) - self.assertEqual(project_domain_name, token.project_domain_name) - self.assertEqual(project_domain_name, project_domain['name']) - - def test_domain_scoped(self): - domain_id = uuid.uuid4().hex - domain_name = uuid.uuid4().hex - - token = fixture.V3Token(domain_id=domain_id, - domain_name=domain_name) - - self.assertEqual(domain_id, token.domain_id) - self.assertEqual(domain_id, token['token']['domain']['id']) - self.assertEqual(domain_name, token.domain_name) - self.assertEqual(domain_name, token['token']['domain']['name']) - - def test_roles(self): - role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} - role2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} - - token = fixture.V3Token() - token.add_role(**role1) - token.add_role(**role2) - - self.assertEqual(2, len(token['token']['roles'])) - - self.assertIn(role1, token['token']['roles']) - self.assertIn(role2, token['token']['roles']) - - def test_trust_scoped(self): - trust_id = uuid.uuid4().hex - trustee_user_id = uuid.uuid4().hex - trustor_user_id = uuid.uuid4().hex - impersonation = True - - token = fixture.V3Token(trust_id=trust_id, - trustee_user_id=trustee_user_id, - trustor_user_id=trustor_user_id, - trust_impersonation=impersonation) - - trust = token['token']['OS-TRUST:trust'] - self.assertEqual(trust_id, token.trust_id) - self.assertEqual(trust_id, trust['id']) - self.assertEqual(trustee_user_id, token.trustee_user_id) - self.assertEqual(trustee_user_id, trust['trustee_user']['id']) - self.assertEqual(trustor_user_id, token.trustor_user_id) - self.assertEqual(trustor_user_id, trust['trustor_user']['id']) - self.assertEqual(impersonation, token.trust_impersonation) - self.assertEqual(impersonation, trust['impersonation']) - - def test_oauth_scoped(self): - access_id = uuid.uuid4().hex - consumer_id = uuid.uuid4().hex - - token = fixture.V3Token(oauth_access_token_id=access_id, - oauth_consumer_id=consumer_id) - - oauth = token['token']['OS-OAUTH1'] - - self.assertEqual(access_id, token.oauth_access_token_id) - self.assertEqual(access_id, oauth['access_token_id']) - self.assertEqual(consumer_id, token.oauth_consumer_id) - self.assertEqual(consumer_id, oauth['consumer_id']) - - def test_catalog(self): - service_type = uuid.uuid4().hex - service_name = uuid.uuid4().hex - region = uuid.uuid4().hex - endpoints = {'public': uuid.uuid4().hex, - 'internal': uuid.uuid4().hex, - 'admin': uuid.uuid4().hex} - - token = fixture.V3Token() - svc = token.add_service(type=service_type, name=service_name) - svc.add_standard_endpoints(region=region, **endpoints) - - self.assertEqual(1, len(token['token']['catalog'])) - service = token['token']['catalog'][0] - self.assertEqual(3, len(service['endpoints'])) - - self.assertEqual(service_name, service['name']) - self.assertEqual(service_type, service['type']) - - for interface, url in six.iteritems(endpoints): - endpoint = {'interface': interface, 'url': url, - 'region': region, 'region_id': region} - self.assertIn(endpoint, service['endpoints']) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_hacking_checks.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_hacking_checks.py deleted file mode 100644 index 220d258cc2..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_hacking_checks.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import textwrap - -import mock -import pep8 -import testtools - -from keystoneclient.hacking import checks -from keystoneclient.tests.unit import client_fixtures - - -class TestCheckOsloNamespaceImports(testtools.TestCase): - - # We are patching pep8 so that only the check under test is actually - # installed. - @mock.patch('pep8._checks', - {'physical_line': {}, 'logical_line': {}, 'tree': {}}) - def run_check(self, code): - pep8.register_check(checks.check_oslo_namespace_imports) - - lines = textwrap.dedent(code).strip().splitlines(True) - - checker = pep8.Checker(lines=lines) - checker.check_all() - checker.report._deferred_print.sort() - return checker.report._deferred_print - - def assert_has_errors(self, code, expected_errors=None): - actual_errors = [e[:3] for e in self.run_check(code)] - self.assertEqual(expected_errors or [], actual_errors) - - def test(self): - code_ex = self.useFixture(client_fixtures.HackingCode()) - code = code_ex.oslo_namespace_imports['code'] - errors = code_ex.oslo_namespace_imports['expected_errors'] - self.assert_has_errors(code, expected_errors=errors) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_http.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_http.py deleted file mode 100644 index 436c374b76..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_http.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -import six -from testtools import matchers - -from keystoneclient import exceptions -from keystoneclient import httpclient -from keystoneclient import session -from keystoneclient.tests.unit import utils - - -RESPONSE_BODY = '{"hi": "there"}' - - -def get_client(): - cl = httpclient.HTTPClient(username="username", password="password", - tenant_id="tenant", auth_url="auth_test") - return cl - - -def get_authed_client(): - cl = get_client() - cl.management_url = "http://127.0.0.1:5000" - cl.auth_token = "token" - return cl - - -class FakeLog(object): - def __init__(self): - self.warn_log = str() - self.debug_log = str() - - def warn(self, msg=None, *args, **kwargs): - self.warn_log = "%s\n%s" % (self.warn_log, (msg % args)) - - def debug(self, msg=None, *args, **kwargs): - self.debug_log = "%s\n%s" % (self.debug_log, (msg % args)) - - -class ClientTest(utils.TestCase): - - TEST_URL = 'http://127.0.0.1:5000/hi' - - def test_unauthorized_client_requests(self): - cl = get_client() - self.assertRaises(exceptions.AuthorizationFailure, cl.get, '/hi') - self.assertRaises(exceptions.AuthorizationFailure, cl.post, '/hi') - self.assertRaises(exceptions.AuthorizationFailure, cl.put, '/hi') - self.assertRaises(exceptions.AuthorizationFailure, cl.delete, '/hi') - - def test_get(self): - cl = get_authed_client() - - self.stub_url('GET', text=RESPONSE_BODY) - - resp, body = cl.get("/hi") - self.assertEqual(self.requests_mock.last_request.method, 'GET') - self.assertEqual(self.requests_mock.last_request.url, self.TEST_URL) - - self.assertRequestHeaderEqual('X-Auth-Token', 'token') - self.assertRequestHeaderEqual('User-Agent', httpclient.USER_AGENT) - - # Automatic JSON parsing - self.assertEqual(body, {"hi": "there"}) - - def test_get_error_with_plaintext_resp(self): - cl = get_authed_client() - self.stub_url('GET', status_code=400, - text='Some evil plaintext string') - - self.assertRaises(exceptions.BadRequest, cl.get, '/hi') - - def test_get_error_with_json_resp(self): - cl = get_authed_client() - err_response = { - "error": { - "code": 400, - "title": "Error title", - "message": "Error message string" - } - } - self.stub_url('GET', status_code=400, json=err_response) - exc_raised = False - try: - cl.get('/hi') - except exceptions.BadRequest as exc: - exc_raised = True - self.assertEqual(exc.message, "Error message string") - self.assertTrue(exc_raised, 'Exception not raised.') - - def test_post(self): - cl = get_authed_client() - - self.stub_url('POST') - cl.post("/hi", body=[1, 2, 3]) - - self.assertEqual(self.requests_mock.last_request.method, 'POST') - self.assertEqual(self.requests_mock.last_request.body, '[1, 2, 3]') - - self.assertRequestHeaderEqual('X-Auth-Token', 'token') - self.assertRequestHeaderEqual('Content-Type', 'application/json') - self.assertRequestHeaderEqual('User-Agent', httpclient.USER_AGENT) - - def test_forwarded_for(self): - ORIGINAL_IP = "10.100.100.1" - cl = httpclient.HTTPClient(username="username", password="password", - tenant_id="tenant", auth_url="auth_test", - original_ip=ORIGINAL_IP) - - self.stub_url('GET') - - cl.request(self.TEST_URL, 'GET') - forwarded = "for=%s;by=%s" % (ORIGINAL_IP, httpclient.USER_AGENT) - self.assertRequestHeaderEqual('Forwarded', forwarded) - - def test_client_deprecated(self): - # Can resolve symbols from the keystoneclient.client module. - # keystoneclient.client was deprecated and renamed to - # keystoneclient.httpclient. This tests that keystoneclient.client - # can still be used. - - from keystoneclient import client - - # These statements will raise an AttributeError if the symbol isn't - # defined in the module. - - client.HTTPClient - - -class BasicRequestTests(utils.TestCase): - - url = 'http://keystone.test.com/' - - def setUp(self): - super(BasicRequestTests, self).setUp() - self.logger_message = six.moves.cStringIO() - handler = logging.StreamHandler(self.logger_message) - handler.setLevel(logging.DEBUG) - - self.logger = logging.getLogger(session.__name__) - level = self.logger.getEffectiveLevel() - self.logger.setLevel(logging.DEBUG) - self.logger.addHandler(handler) - - self.addCleanup(self.logger.removeHandler, handler) - self.addCleanup(self.logger.setLevel, level) - - def request(self, method='GET', response='Test Response', status_code=200, - url=None, **kwargs): - if not url: - url = self.url - - self.requests_mock.register_uri(method, url, text=response, - status_code=status_code) - - return httpclient.request(url, method, **kwargs) - - def test_basic_params(self): - method = 'GET' - response = 'Test Response' - status = 200 - - self.request(method=method, status_code=status, response=response) - - self.assertEqual(self.requests_mock.last_request.method, method) - - logger_message = self.logger_message.getvalue() - - self.assertThat(logger_message, matchers.Contains('curl')) - self.assertThat(logger_message, matchers.Contains('-X %s' % - method)) - self.assertThat(logger_message, matchers.Contains(self.url)) - - self.assertThat(logger_message, matchers.Contains(str(status))) - self.assertThat(logger_message, matchers.Contains(response)) - - def test_headers(self): - headers = {'key': 'val', 'test': 'other'} - - self.request(headers=headers) - - for k, v in six.iteritems(headers): - self.assertRequestHeaderEqual(k, v) - - for header in six.iteritems(headers): - self.assertThat(self.logger_message.getvalue(), - matchers.Contains('-H "%s: %s"' % header)) - - def test_body(self): - data = "BODY DATA" - self.request(response=data) - logger_message = self.logger_message.getvalue() - self.assertThat(logger_message, matchers.Contains('BODY:')) - self.assertThat(logger_message, matchers.Contains(data)) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_https.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_https.py deleted file mode 100644 index e574d37505..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_https.py +++ /dev/null @@ -1,107 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import requests - -from keystoneclient import httpclient -from keystoneclient.tests.unit import utils - - -FAKE_RESPONSE = utils.TestResponse({ - "status_code": 200, - "text": '{"hi": "there"}', -}) - -REQUEST_URL = 'https://127.0.0.1:5000/hi' -RESPONSE_BODY = '{"hi": "there"}' - - -def get_client(): - cl = httpclient.HTTPClient(username="username", password="password", - tenant_id="tenant", auth_url="auth_test", - cacert="ca.pem", key="key.pem", cert="cert.pem") - return cl - - -def get_authed_client(): - cl = get_client() - cl.management_url = "https://127.0.0.1:5000" - cl.auth_token = "token" - return cl - - -class ClientTest(utils.TestCase): - - def setUp(self): - super(ClientTest, self).setUp() - self.request_patcher = mock.patch.object(requests, 'request', - self.mox.CreateMockAnything()) - self.request_patcher.start() - self.addCleanup(self.request_patcher.stop) - - @mock.patch.object(requests, 'request') - def test_get(self, MOCK_REQUEST): - MOCK_REQUEST.return_value = FAKE_RESPONSE - cl = get_authed_client() - - resp, body = cl.get("/hi") - - # this may become too tightly couple later - mock_args, mock_kwargs = MOCK_REQUEST.call_args - - self.assertEqual(mock_args[0], 'GET') - self.assertEqual(mock_args[1], REQUEST_URL) - self.assertEqual(mock_kwargs['headers']['X-Auth-Token'], 'token') - self.assertEqual(mock_kwargs['cert'], ('cert.pem', 'key.pem')) - self.assertEqual(mock_kwargs['verify'], 'ca.pem') - - # Automatic JSON parsing - self.assertEqual(body, {"hi": "there"}) - - @mock.patch.object(requests, 'request') - def test_post(self, MOCK_REQUEST): - MOCK_REQUEST.return_value = FAKE_RESPONSE - cl = get_authed_client() - - cl.post("/hi", body=[1, 2, 3]) - - # this may become too tightly couple later - mock_args, mock_kwargs = MOCK_REQUEST.call_args - - self.assertEqual(mock_args[0], 'POST') - self.assertEqual(mock_args[1], REQUEST_URL) - self.assertEqual(mock_kwargs['data'], '[1, 2, 3]') - self.assertEqual(mock_kwargs['headers']['X-Auth-Token'], 'token') - self.assertEqual(mock_kwargs['cert'], ('cert.pem', 'key.pem')) - self.assertEqual(mock_kwargs['verify'], 'ca.pem') - - @mock.patch.object(requests, 'request') - def test_post_auth(self, MOCK_REQUEST): - MOCK_REQUEST.return_value = FAKE_RESPONSE - cl = httpclient.HTTPClient( - username="username", password="password", tenant_id="tenant", - auth_url="auth_test", cacert="ca.pem", key="key.pem", - cert="cert.pem") - cl.management_url = "https://127.0.0.1:5000" - cl.auth_token = "token" - cl.post("/hi", body=[1, 2, 3]) - - # this may become too tightly couple later - mock_args, mock_kwargs = MOCK_REQUEST.call_args - - self.assertEqual(mock_args[0], 'POST') - self.assertEqual(mock_args[1], REQUEST_URL) - self.assertEqual(mock_kwargs['data'], '[1, 2, 3]') - self.assertEqual(mock_kwargs['headers']['X-Auth-Token'], 'token') - self.assertEqual(mock_kwargs['cert'], ('cert.pem', 'key.pem')) - self.assertEqual(mock_kwargs['verify'], 'ca.pem') diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_keyring.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_keyring.py deleted file mode 100644 index a54009e9c2..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_keyring.py +++ /dev/null @@ -1,187 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -import mock -from oslo_utils import timeutils - -from keystoneclient import access -from keystoneclient import httpclient -from keystoneclient.tests.unit import utils -from keystoneclient.tests.unit.v2_0 import client_fixtures - -try: - import keyring # noqa - import pickle # noqa -except ImportError: - keyring = None - - -PROJECT_SCOPED_TOKEN = client_fixtures.project_scoped_token() - -# These mirror values from PROJECT_SCOPED_TOKEN -USERNAME = 'exampleuser' -AUTH_URL = 'http://public.com:5000/v2.0' -TOKEN = '04c7d5ffaeef485f9dc69c06db285bdb' - -PASSWORD = 'password' -TENANT = 'tenant' -TENANT_ID = 'tenant_id' - - -class KeyringTest(utils.TestCase): - - def setUp(self): - if keyring is None: - self.skipTest( - 'optional package keyring or pickle is not installed') - - class MemoryKeyring(keyring.backend.KeyringBackend): - """A Simple testing keyring. - - This class supports stubbing an initial password to be returned by - setting password, and allows easy password and key retrieval. Also - records if a password was retrieved. - """ - def __init__(self): - self.key = None - self.password = None - self.fetched = False - self.get_password_called = False - self.set_password_called = False - - def supported(self): - return 1 - - def get_password(self, service, username): - self.get_password_called = True - key = username + '@' + service - # make sure we don't get passwords crossed if one is enforced. - if self.key and self.key != key: - return None - if self.password: - self.fetched = True - return self.password - - def set_password(self, service, username, password): - self.set_password_called = True - self.key = username + '@' + service - self.password = password - - super(KeyringTest, self).setUp() - self.memory_keyring = MemoryKeyring() - keyring.set_keyring(self.memory_keyring) - - def test_no_keyring_key(self): - """Ensure that if we don't have use_keyring set in the client that - the keyring is never accessed. - """ - cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD, - tenant_id=TENANT_ID, auth_url=AUTH_URL) - - # stub and check that a new token is received - method = 'get_raw_token_from_identity_service' - with mock.patch.object(cl, method) as meth: - meth.return_value = (True, PROJECT_SCOPED_TOKEN) - - self.assertTrue(cl.authenticate()) - - self.assertEqual(1, meth.call_count) - - # make sure that we never touched the keyring - self.assertFalse(self.memory_keyring.get_password_called) - self.assertFalse(self.memory_keyring.set_password_called) - - def test_build_keyring_key(self): - cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD, - tenant_id=TENANT_ID, auth_url=AUTH_URL) - - keyring_key = cl._build_keyring_key(auth_url=AUTH_URL, - username=USERNAME, - tenant_name=TENANT, - tenant_id=TENANT_ID, - token=TOKEN) - - self.assertEqual(keyring_key, - '%s/%s/%s/%s/%s' % - (AUTH_URL, TENANT_ID, TENANT, TOKEN, USERNAME)) - - def test_set_and_get_keyring_expired(self): - cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD, - tenant_id=TENANT_ID, auth_url=AUTH_URL, - use_keyring=True) - - # set an expired token into the keyring - auth_ref = access.AccessInfo.factory(body=PROJECT_SCOPED_TOKEN) - expired = timeutils.utcnow() - datetime.timedelta(minutes=30) - auth_ref['token']['expires'] = timeutils.isotime(expired) - self.memory_keyring.password = pickle.dumps(auth_ref) - - # stub and check that a new token is received, so not using expired - method = 'get_raw_token_from_identity_service' - with mock.patch.object(cl, method) as meth: - meth.return_value = (True, PROJECT_SCOPED_TOKEN) - - self.assertTrue(cl.authenticate()) - - self.assertEqual(1, meth.call_count) - - # check that a value was returned from the keyring - self.assertTrue(self.memory_keyring.fetched) - - # check that the new token has been loaded into the keyring - new_auth_ref = pickle.loads(self.memory_keyring.password) - self.assertEqual(new_auth_ref['token']['expires'], - PROJECT_SCOPED_TOKEN['access']['token']['expires']) - - def test_get_keyring(self): - cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD, - tenant_id=TENANT_ID, auth_url=AUTH_URL, - use_keyring=True) - - # set an token into the keyring - auth_ref = access.AccessInfo.factory(body=PROJECT_SCOPED_TOKEN) - future = timeutils.utcnow() + datetime.timedelta(minutes=30) - auth_ref['token']['expires'] = timeutils.isotime(future) - self.memory_keyring.password = pickle.dumps(auth_ref) - - # don't stub get_raw_token so will fail if authenticate happens - - self.assertTrue(cl.authenticate()) - self.assertTrue(self.memory_keyring.fetched) - - def test_set_keyring(self): - cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD, - tenant_id=TENANT_ID, auth_url=AUTH_URL, - use_keyring=True) - - # stub and check that a new token is received - method = 'get_raw_token_from_identity_service' - with mock.patch.object(cl, method) as meth: - meth.return_value = (True, PROJECT_SCOPED_TOKEN) - - self.assertTrue(cl.authenticate()) - - self.assertEqual(1, meth.call_count) - - # we checked the keyring, but we didn't find anything - self.assertTrue(self.memory_keyring.get_password_called) - self.assertFalse(self.memory_keyring.fetched) - - # check that the new token has been loaded into the keyring - self.assertTrue(self.memory_keyring.set_password_called) - new_auth_ref = pickle.loads(self.memory_keyring.password) - self.assertEqual(new_auth_ref.auth_token, TOKEN) - self.assertEqual(new_auth_ref['token'], - PROJECT_SCOPED_TOKEN['access']['token']) - self.assertEqual(new_auth_ref.username, USERNAME) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_memcache_crypt.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_memcache_crypt.py deleted file mode 100644 index be07b24ead..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_memcache_crypt.py +++ /dev/null @@ -1,97 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six -import testtools - -from keystoneclient.middleware import memcache_crypt - - -class MemcacheCryptPositiveTests(testtools.TestCase): - def _setup_keys(self, strategy): - return memcache_crypt.derive_keys(b'token', b'secret', strategy) - - def test_constant_time_compare(self): - # make sure it works as a compare, the "constant time" aspect - # isn't appropriate to test in unittests - ctc = memcache_crypt.constant_time_compare - self.assertTrue(ctc('abcd', 'abcd')) - self.assertTrue(ctc('', '')) - self.assertFalse(ctc('abcd', 'efgh')) - self.assertFalse(ctc('abc', 'abcd')) - self.assertFalse(ctc('abc', 'abc\x00')) - self.assertFalse(ctc('', 'abc')) - - # For Python 3, we want to test these functions with both str and bytes - # as input. - if six.PY3: - self.assertTrue(ctc(b'abcd', b'abcd')) - self.assertTrue(ctc(b'', b'')) - self.assertFalse(ctc(b'abcd', b'efgh')) - self.assertFalse(ctc(b'abc', b'abcd')) - self.assertFalse(ctc(b'abc', b'abc\x00')) - self.assertFalse(ctc(b'', b'abc')) - - def test_derive_keys(self): - keys = self._setup_keys(b'strategy') - self.assertEqual(len(keys['ENCRYPTION']), - len(keys['CACHE_KEY'])) - self.assertEqual(len(keys['CACHE_KEY']), - len(keys['MAC'])) - self.assertNotEqual(keys['ENCRYPTION'], - keys['MAC']) - self.assertIn('strategy', keys.keys()) - - def test_key_strategy_diff(self): - k1 = self._setup_keys(b'MAC') - k2 = self._setup_keys(b'ENCRYPT') - self.assertNotEqual(k1, k2) - - def test_sign_data(self): - keys = self._setup_keys(b'MAC') - sig = memcache_crypt.sign_data(keys['MAC'], b'data') - self.assertEqual(len(sig), memcache_crypt.DIGEST_LENGTH_B64) - - def test_encryption(self): - keys = self._setup_keys(b'ENCRYPT') - # what you put in is what you get out - for data in [b'data', b'1234567890123456', b'\x00\xFF' * 13 - ] + [six.int2byte(x % 256) * x for x in range(768)]: - crypt = memcache_crypt.encrypt_data(keys['ENCRYPTION'], data) - decrypt = memcache_crypt.decrypt_data(keys['ENCRYPTION'], crypt) - self.assertEqual(data, decrypt) - self.assertRaises(memcache_crypt.DecryptError, - memcache_crypt.decrypt_data, - keys['ENCRYPTION'], crypt[:-1]) - - def test_protect_wrappers(self): - data = b'My Pretty Little Data' - for strategy in [b'MAC', b'ENCRYPT']: - keys = self._setup_keys(strategy) - protected = memcache_crypt.protect_data(keys, data) - self.assertNotEqual(protected, data) - if strategy == b'ENCRYPT': - self.assertNotIn(data, protected) - unprotected = memcache_crypt.unprotect_data(keys, protected) - self.assertEqual(data, unprotected) - self.assertRaises(memcache_crypt.InvalidMacError, - memcache_crypt.unprotect_data, - keys, protected[:-1]) - self.assertIsNone(memcache_crypt.unprotect_data(keys, None)) - - def test_no_pycrypt(self): - aes = memcache_crypt.AES - memcache_crypt.AES = None - self.assertRaises(memcache_crypt.CryptoUnavailableError, - memcache_crypt.encrypt_data, 'token', 'secret', - 'data') - memcache_crypt.AES = aes diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_s3_token_middleware.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_s3_token_middleware.py deleted file mode 100644 index d5a62e8f43..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_s3_token_middleware.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslo_serialization import jsonutils -import requests -import six -import testtools -import webob - -from keystoneclient.middleware import s3_token -from keystoneclient.tests.unit import utils - - -GOOD_RESPONSE = {'access': {'token': {'id': 'TOKEN_ID', - 'tenant': {'id': 'TENANT_ID'}}}} - - -class FakeApp(object): - """This represents a WSGI app protected by the auth_token middleware.""" - def __call__(self, env, start_response): - resp = webob.Response() - resp.environ = env - return resp(env, start_response) - - -class S3TokenMiddlewareTestBase(utils.TestCase): - - TEST_PROTOCOL = 'https' - TEST_HOST = 'fakehost' - TEST_PORT = 35357 - TEST_URL = '%s://%s:%d/v2.0/s3tokens' % (TEST_PROTOCOL, - TEST_HOST, - TEST_PORT) - - def setUp(self): - super(S3TokenMiddlewareTestBase, self).setUp() - - self.conf = { - 'auth_host': self.TEST_HOST, - 'auth_port': self.TEST_PORT, - 'auth_protocol': self.TEST_PROTOCOL, - } - - def start_fake_response(self, status, headers): - self.response_status = int(status.split(' ', 1)[0]) - self.response_headers = dict(headers) - - -class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase): - - def setUp(self): - super(S3TokenMiddlewareTestGood, self).setUp() - self.middleware = s3_token.S3Token(FakeApp(), self.conf) - - self.requests_mock.post(self.TEST_URL, - status_code=201, - json=GOOD_RESPONSE) - - # Ignore the request and pass to the next middleware in the - # pipeline if no path has been specified. - def test_no_path_request(self): - req = webob.Request.blank('/') - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - - # Ignore the request and pass to the next middleware in the - # pipeline if no Authorization header has been specified - def test_without_authorization(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - - def test_without_auth_storage_token(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'badboy' - self.middleware(req.environ, self.start_fake_response) - self.assertEqual(self.response_status, 200) - - def test_authorized(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - self.assertTrue(req.path.startswith('/v1/AUTH_TENANT_ID')) - self.assertEqual(req.headers['X-Auth-Token'], 'TOKEN_ID') - - def test_authorized_http(self): - TEST_URL = 'http://%s:%d/v2.0/s3tokens' % (self.TEST_HOST, - self.TEST_PORT) - - self.requests_mock.post(TEST_URL, status_code=201, json=GOOD_RESPONSE) - - self.middleware = ( - s3_token.filter_factory({'auth_protocol': 'http', - 'auth_host': self.TEST_HOST, - 'auth_port': self.TEST_PORT})(FakeApp())) - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - self.assertTrue(req.path.startswith('/v1/AUTH_TENANT_ID')) - self.assertEqual(req.headers['X-Auth-Token'], 'TOKEN_ID') - - def test_authorization_nova_toconnect(self): - req = webob.Request.blank('/v1/AUTH_swiftint/c/o') - req.headers['Authorization'] = 'access:FORCED_TENANT_ID:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - path = req.environ['PATH_INFO'] - self.assertTrue(path.startswith('/v1/AUTH_FORCED_TENANT_ID')) - - @mock.patch.object(requests, 'post') - def test_insecure(self, MOCK_REQUEST): - self.middleware = ( - s3_token.filter_factory({'insecure': True})(FakeApp())) - - text_return_value = jsonutils.dumps(GOOD_RESPONSE) - if six.PY3: - text_return_value = text_return_value.encode() - MOCK_REQUEST.return_value = utils.TestResponse({ - 'status_code': 201, - 'text': text_return_value}) - - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - req.get_response(self.middleware) - - self.assertTrue(MOCK_REQUEST.called) - mock_args, mock_kwargs = MOCK_REQUEST.call_args - self.assertIs(mock_kwargs['verify'], False) - - -class S3TokenMiddlewareTestBad(S3TokenMiddlewareTestBase): - def setUp(self): - super(S3TokenMiddlewareTestBad, self).setUp() - self.middleware = s3_token.S3Token(FakeApp(), self.conf) - - def test_unauthorized_token(self): - ret = {"error": - {"message": "EC2 access key not found.", - "code": 401, - "title": "Unauthorized"}} - self.requests_mock.post(self.TEST_URL, status_code=403, json=ret) - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - s3_denied_req = self.middleware.deny_request('AccessDenied') - self.assertEqual(resp.body, s3_denied_req.body) - self.assertEqual(resp.status_int, s3_denied_req.status_int) - - def test_bogus_authorization(self): - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'badboy' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - self.assertEqual(resp.status_int, 400) - s3_invalid_req = self.middleware.deny_request('InvalidURI') - self.assertEqual(resp.body, s3_invalid_req.body) - self.assertEqual(resp.status_int, s3_invalid_req.status_int) - - def test_fail_to_connect_to_keystone(self): - with mock.patch.object(self.middleware, '_json_request') as o: - s3_invalid_req = self.middleware.deny_request('InvalidURI') - o.side_effect = s3_token.ServiceError(s3_invalid_req) - - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - self.assertEqual(resp.body, s3_invalid_req.body) - self.assertEqual(resp.status_int, s3_invalid_req.status_int) - - def test_bad_reply(self): - self.requests_mock.post(self.TEST_URL, - status_code=201, - text="<badreply>") - - req = webob.Request.blank('/v1/AUTH_cfa/c/o') - req.headers['Authorization'] = 'access:signature' - req.headers['X-Storage-Token'] = 'token' - resp = req.get_response(self.middleware) - s3_invalid_req = self.middleware.deny_request('InvalidURI') - self.assertEqual(resp.body, s3_invalid_req.body) - self.assertEqual(resp.status_int, s3_invalid_req.status_int) - - -class S3TokenMiddlewareTestUtil(testtools.TestCase): - def test_split_path_failed(self): - self.assertRaises(ValueError, s3_token.split_path, '') - self.assertRaises(ValueError, s3_token.split_path, '/') - self.assertRaises(ValueError, s3_token.split_path, '//') - self.assertRaises(ValueError, s3_token.split_path, '//a') - self.assertRaises(ValueError, s3_token.split_path, '/a/c') - self.assertRaises(ValueError, s3_token.split_path, '//c') - self.assertRaises(ValueError, s3_token.split_path, '/a/c/') - self.assertRaises(ValueError, s3_token.split_path, '/a//') - self.assertRaises(ValueError, s3_token.split_path, '/a', 2) - self.assertRaises(ValueError, s3_token.split_path, '/a', 2, 3) - self.assertRaises(ValueError, s3_token.split_path, '/a', 2, 3, True) - self.assertRaises(ValueError, s3_token.split_path, '/a/c/o/r', 3, 3) - self.assertRaises(ValueError, s3_token.split_path, '/a', 5, 4) - - def test_split_path_success(self): - self.assertEqual(s3_token.split_path('/a'), ['a']) - self.assertEqual(s3_token.split_path('/a/'), ['a']) - self.assertEqual(s3_token.split_path('/a/c', 2), ['a', 'c']) - self.assertEqual(s3_token.split_path('/a/c/o', 3), ['a', 'c', 'o']) - self.assertEqual(s3_token.split_path('/a/c/o/r', 3, 3, True), - ['a', 'c', 'o/r']) - self.assertEqual(s3_token.split_path('/a/c', 2, 3, True), - ['a', 'c', None]) - self.assertEqual(s3_token.split_path('/a/c/', 2), ['a', 'c']) - self.assertEqual(s3_token.split_path('/a/c/', 2, 3), ['a', 'c', '']) - - def test_split_path_invalid_path(self): - try: - s3_token.split_path('o\nn e', 2) - except ValueError as err: - self.assertEqual(str(err), 'Invalid path: o%0An%20e') - try: - s3_token.split_path('o\nn e', 2, 3, True) - except ValueError as err: - self.assertEqual(str(err), 'Invalid path: o%0An%20e') diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_session.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_session.py deleted file mode 100644 index 646cba8c3b..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_session.py +++ /dev/null @@ -1,942 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import itertools -import logging -import uuid - -import mock -from oslo_config import cfg -from oslo_config import fixture as config -from oslo_serialization import jsonutils -import requests -import six -from testtools import matchers - -from keystoneclient import adapter -from keystoneclient.auth import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import session as client_session -from keystoneclient.tests.unit import utils - - -class SessionTests(utils.TestCase): - - TEST_URL = 'http://127.0.0.1:5000/' - - def test_get(self): - session = client_session.Session() - self.stub_url('GET', text='response') - resp = session.get(self.TEST_URL) - - self.assertEqual('GET', self.requests_mock.last_request.method) - self.assertEqual(resp.text, 'response') - self.assertTrue(resp.ok) - - def test_post(self): - session = client_session.Session() - self.stub_url('POST', text='response') - resp = session.post(self.TEST_URL, json={'hello': 'world'}) - - self.assertEqual('POST', self.requests_mock.last_request.method) - self.assertEqual(resp.text, 'response') - self.assertTrue(resp.ok) - self.assertRequestBodyIs(json={'hello': 'world'}) - - def test_head(self): - session = client_session.Session() - self.stub_url('HEAD') - resp = session.head(self.TEST_URL) - - self.assertEqual('HEAD', self.requests_mock.last_request.method) - self.assertTrue(resp.ok) - self.assertRequestBodyIs('') - - def test_put(self): - session = client_session.Session() - self.stub_url('PUT', text='response') - resp = session.put(self.TEST_URL, json={'hello': 'world'}) - - self.assertEqual('PUT', self.requests_mock.last_request.method) - self.assertEqual(resp.text, 'response') - self.assertTrue(resp.ok) - self.assertRequestBodyIs(json={'hello': 'world'}) - - def test_delete(self): - session = client_session.Session() - self.stub_url('DELETE', text='response') - resp = session.delete(self.TEST_URL) - - self.assertEqual('DELETE', self.requests_mock.last_request.method) - self.assertTrue(resp.ok) - self.assertEqual(resp.text, 'response') - - def test_patch(self): - session = client_session.Session() - self.stub_url('PATCH', text='response') - resp = session.patch(self.TEST_URL, json={'hello': 'world'}) - - self.assertEqual('PATCH', self.requests_mock.last_request.method) - self.assertTrue(resp.ok) - self.assertEqual(resp.text, 'response') - self.assertRequestBodyIs(json={'hello': 'world'}) - - def test_user_agent(self): - session = client_session.Session(user_agent='test-agent') - self.stub_url('GET', text='response') - resp = session.get(self.TEST_URL) - - self.assertTrue(resp.ok) - self.assertRequestHeaderEqual('User-Agent', 'test-agent') - - resp = session.get(self.TEST_URL, headers={'User-Agent': 'new-agent'}) - self.assertTrue(resp.ok) - self.assertRequestHeaderEqual('User-Agent', 'new-agent') - - resp = session.get(self.TEST_URL, headers={'User-Agent': 'new-agent'}, - user_agent='overrides-agent') - self.assertTrue(resp.ok) - self.assertRequestHeaderEqual('User-Agent', 'overrides-agent') - - def test_http_session_opts(self): - session = client_session.Session(cert='cert.pem', timeout=5, - verify='certs') - - FAKE_RESP = utils.TestResponse({'status_code': 200, 'text': 'resp'}) - RESP = mock.Mock(return_value=FAKE_RESP) - - with mock.patch.object(session.session, 'request', RESP) as mocked: - session.post(self.TEST_URL, data='value') - - mock_args, mock_kwargs = mocked.call_args - - self.assertEqual(mock_args[0], 'POST') - self.assertEqual(mock_args[1], self.TEST_URL) - self.assertEqual(mock_kwargs['data'], 'value') - self.assertEqual(mock_kwargs['cert'], 'cert.pem') - self.assertEqual(mock_kwargs['verify'], 'certs') - self.assertEqual(mock_kwargs['timeout'], 5) - - def test_not_found(self): - session = client_session.Session() - self.stub_url('GET', status_code=404) - self.assertRaises(exceptions.NotFound, session.get, self.TEST_URL) - - def test_server_error(self): - session = client_session.Session() - self.stub_url('GET', status_code=500) - self.assertRaises(exceptions.InternalServerError, - session.get, self.TEST_URL) - - def test_session_debug_output(self): - """Test request and response headers in debug logs - - in order to redact secure headers while debug is true. - """ - session = client_session.Session(verify=False) - headers = {'HEADERA': 'HEADERVALB'} - security_headers = {'Authorization': uuid.uuid4().hex, - 'X-Auth-Token': uuid.uuid4().hex, - 'X-Subject-Token': uuid.uuid4().hex, } - body = 'BODYRESPONSE' - data = 'BODYDATA' - all_headers = dict( - itertools.chain(headers.items(), security_headers.items())) - self.stub_url('POST', text=body, headers=all_headers) - resp = session.post(self.TEST_URL, headers=all_headers, data=data) - self.assertEqual(resp.status_code, 200) - - self.assertIn('curl', self.logger.output) - self.assertIn('POST', self.logger.output) - self.assertIn('--insecure', self.logger.output) - self.assertIn(body, self.logger.output) - self.assertIn("'%s'" % data, self.logger.output) - - for k, v in six.iteritems(headers): - self.assertIn(k, self.logger.output) - self.assertIn(v, self.logger.output) - - # Assert that response headers contains actual values and - # only debug logs has been masked - for k, v in six.iteritems(security_headers): - self.assertIn('%s: {SHA1}' % k, self.logger.output) - self.assertEqual(v, resp.headers[k]) - self.assertNotIn(v, self.logger.output) - - def test_logging_cacerts(self): - path_to_certs = '/path/to/certs' - session = client_session.Session(verify=path_to_certs) - - self.stub_url('GET', text='text') - session.get(self.TEST_URL) - - self.assertIn('--cacert', self.logger.output) - self.assertIn(path_to_certs, self.logger.output) - - def test_connect_retries(self): - - def _timeout_error(request, context): - raise requests.exceptions.Timeout() - - self.stub_url('GET', text=_timeout_error) - - session = client_session.Session() - retries = 3 - - with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.RequestTimeout, - session.get, - self.TEST_URL, connect_retries=retries) - - self.assertEqual(retries, m.call_count) - # 3 retries finishing with 2.0 means 0.5, 1.0 and 2.0 - m.assert_called_with(2.0) - - # we count retries so there will be one initial request + 3 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) - - def test_uses_tcp_keepalive_by_default(self): - session = client_session.Session() - requests_session = session.session - self.assertIsInstance(requests_session.adapters['http://'], - client_session.TCPKeepAliveAdapter) - self.assertIsInstance(requests_session.adapters['https://'], - client_session.TCPKeepAliveAdapter) - - def test_does_not_set_tcp_keepalive_on_custom_sessions(self): - mock_session = mock.Mock() - client_session.Session(session=mock_session) - self.assertFalse(mock_session.mount.called) - - def test_ssl_error_message(self): - error = uuid.uuid4().hex - - def _ssl_error(request, context): - raise requests.exceptions.SSLError(error) - - self.stub_url('GET', text=_ssl_error) - session = client_session.Session() - - # The exception should contain the URL and details about the SSL error - msg = _('SSL exception connecting to %(url)s: %(error)s') % { - 'url': self.TEST_URL, 'error': error} - self.assertRaisesRegexp(exceptions.SSLError, - msg, - session.get, - self.TEST_URL) - - -class RedirectTests(utils.TestCase): - - REDIRECT_CHAIN = ['http://myhost:3445/', - 'http://anotherhost:6555/', - 'http://thirdhost/', - 'http://finaldestination:55/'] - - DEFAULT_REDIRECT_BODY = 'Redirect' - DEFAULT_RESP_BODY = 'Found' - - def setup_redirects(self, method='GET', status_code=305, - redirect_kwargs={}, final_kwargs={}): - redirect_kwargs.setdefault('text', self.DEFAULT_REDIRECT_BODY) - - for s, d in zip(self.REDIRECT_CHAIN, self.REDIRECT_CHAIN[1:]): - self.requests_mock.register_uri(method, s, status_code=status_code, - headers={'Location': d}, - **redirect_kwargs) - - final_kwargs.setdefault('status_code', 200) - final_kwargs.setdefault('text', self.DEFAULT_RESP_BODY) - self.requests_mock.register_uri(method, self.REDIRECT_CHAIN[-1], - **final_kwargs) - - def assertResponse(self, resp): - self.assertEqual(resp.status_code, 200) - self.assertEqual(resp.text, self.DEFAULT_RESP_BODY) - - def test_basic_get(self): - session = client_session.Session() - self.setup_redirects() - resp = session.get(self.REDIRECT_CHAIN[-2]) - self.assertResponse(resp) - - def test_basic_post_keeps_correct_method(self): - session = client_session.Session() - self.setup_redirects(method='POST', status_code=301) - resp = session.post(self.REDIRECT_CHAIN[-2]) - self.assertResponse(resp) - - def test_redirect_forever(self): - session = client_session.Session(redirect=True) - self.setup_redirects() - resp = session.get(self.REDIRECT_CHAIN[0]) - self.assertResponse(resp) - self.assertTrue(len(resp.history), len(self.REDIRECT_CHAIN)) - - def test_no_redirect(self): - session = client_session.Session(redirect=False) - self.setup_redirects() - resp = session.get(self.REDIRECT_CHAIN[0]) - self.assertEqual(resp.status_code, 305) - self.assertEqual(resp.url, self.REDIRECT_CHAIN[0]) - - def test_redirect_limit(self): - self.setup_redirects() - for i in (1, 2): - session = client_session.Session(redirect=i) - resp = session.get(self.REDIRECT_CHAIN[0]) - self.assertEqual(resp.status_code, 305) - self.assertEqual(resp.url, self.REDIRECT_CHAIN[i]) - self.assertEqual(resp.text, self.DEFAULT_REDIRECT_BODY) - - def test_history_matches_requests(self): - self.setup_redirects(status_code=301) - session = client_session.Session(redirect=True) - req_resp = requests.get(self.REDIRECT_CHAIN[0], - allow_redirects=True) - - ses_resp = session.get(self.REDIRECT_CHAIN[0]) - - self.assertEqual(len(req_resp.history), len(ses_resp.history)) - - for r, s in zip(req_resp.history, ses_resp.history): - self.assertEqual(r.url, s.url) - self.assertEqual(r.status_code, s.status_code) - - -class ConstructSessionFromArgsTests(utils.TestCase): - - KEY = 'keyfile' - CERT = 'certfile' - CACERT = 'cacert-path' - - def _s(self, k=None, **kwargs): - k = k or kwargs - return client_session.Session.construct(k) - - def test_verify(self): - self.assertFalse(self._s(insecure=True).verify) - self.assertTrue(self._s(verify=True, insecure=True).verify) - self.assertFalse(self._s(verify=False, insecure=True).verify) - self.assertEqual(self._s(cacert=self.CACERT).verify, self.CACERT) - - def test_cert(self): - tup = (self.CERT, self.KEY) - self.assertEqual(self._s(cert=tup).cert, tup) - self.assertEqual(self._s(cert=self.CERT, key=self.KEY).cert, tup) - self.assertIsNone(self._s(key=self.KEY).cert) - - def test_pass_through(self): - value = 42 # only a number because timeout needs to be - for key in ['timeout', 'session', 'original_ip', 'user_agent']: - args = {key: value} - self.assertEqual(getattr(self._s(args), key), value) - self.assertNotIn(key, args) - - -class AuthPlugin(base.BaseAuthPlugin): - """Very simple debug authentication plugin. - - Takes Parameters such that it can throw exceptions at the right times. - """ - - TEST_TOKEN = 'aToken' - TEST_USER_ID = 'aUser' - TEST_PROJECT_ID = 'aProject' - - SERVICE_URLS = { - 'identity': {'public': 'http://identity-public:1111/v2.0', - 'admin': 'http://identity-admin:1111/v2.0'}, - 'compute': {'public': 'http://compute-public:2222/v1.0', - 'admin': 'http://compute-admin:2222/v1.0'}, - 'image': {'public': 'http://image-public:3333/v2.0', - 'admin': 'http://image-admin:3333/v2.0'} - } - - def __init__(self, token=TEST_TOKEN, invalidate=True): - self.token = token - self._invalidate = invalidate - - def get_token(self, session): - return self.token - - def get_endpoint(self, session, service_type=None, interface=None, - **kwargs): - try: - return self.SERVICE_URLS[service_type][interface] - except (KeyError, AttributeError): - return None - - def invalidate(self): - return self._invalidate - - def get_user_id(self, session): - return self.TEST_USER_ID - - def get_project_id(self, session): - return self.TEST_PROJECT_ID - - -class CalledAuthPlugin(base.BaseAuthPlugin): - - ENDPOINT = 'http://fakeendpoint/' - - def __init__(self, invalidate=True): - self.get_token_called = False - self.get_endpoint_called = False - self.endpoint_arguments = {} - self.invalidate_called = False - self._invalidate = invalidate - - def get_token(self, session): - self.get_token_called = True - return 'aToken' - - def get_endpoint(self, session, **kwargs): - self.get_endpoint_called = True - self.endpoint_arguments = kwargs - return self.ENDPOINT - - def invalidate(self): - self.invalidate_called = True - return self._invalidate - - -class SessionAuthTests(utils.TestCase): - - TEST_URL = 'http://127.0.0.1:5000/' - TEST_JSON = {'hello': 'world'} - - def stub_service_url(self, service_type, interface, path, - method='GET', **kwargs): - base_url = AuthPlugin.SERVICE_URLS[service_type][interface] - uri = "%s/%s" % (base_url.rstrip('/'), path.lstrip('/')) - - self.requests_mock.register_uri(method, uri, **kwargs) - - def test_auth_plugin_default_with_plugin(self): - self.stub_url('GET', base_url=self.TEST_URL, json=self.TEST_JSON) - - # if there is an auth_plugin then it should default to authenticated - auth = AuthPlugin() - sess = client_session.Session(auth=auth) - resp = sess.get(self.TEST_URL) - self.assertDictEqual(resp.json(), self.TEST_JSON) - - self.assertRequestHeaderEqual('X-Auth-Token', AuthPlugin.TEST_TOKEN) - - def test_auth_plugin_disable(self): - self.stub_url('GET', base_url=self.TEST_URL, json=self.TEST_JSON) - - auth = AuthPlugin() - sess = client_session.Session(auth=auth) - resp = sess.get(self.TEST_URL, authenticated=False) - self.assertDictEqual(resp.json(), self.TEST_JSON) - - self.assertRequestHeaderEqual('X-Auth-Token', None) - - def test_service_type_urls(self): - service_type = 'compute' - interface = 'public' - path = '/instances' - status = 200 - body = 'SUCCESS' - - self.stub_service_url(service_type=service_type, - interface=interface, - path=path, - status_code=status, - text=body) - - sess = client_session.Session(auth=AuthPlugin()) - resp = sess.get(path, - endpoint_filter={'service_type': service_type, - 'interface': interface}) - - self.assertEqual(self.requests_mock.last_request.url, - AuthPlugin.SERVICE_URLS['compute']['public'] + path) - self.assertEqual(resp.text, body) - self.assertEqual(resp.status_code, status) - - def test_service_url_raises_if_no_auth_plugin(self): - sess = client_session.Session() - self.assertRaises(exceptions.MissingAuthPlugin, - sess.get, '/path', - endpoint_filter={'service_type': 'compute', - 'interface': 'public'}) - - def test_service_url_raises_if_no_url_returned(self): - sess = client_session.Session(auth=AuthPlugin()) - self.assertRaises(exceptions.EndpointNotFound, - sess.get, '/path', - endpoint_filter={'service_type': 'unknown', - 'interface': 'public'}) - - def test_raises_exc_only_when_asked(self): - # A request that returns a HTTP error should by default raise an - # exception by default, if you specify raise_exc=False then it will not - self.requests_mock.get(self.TEST_URL, status_code=401) - - sess = client_session.Session() - self.assertRaises(exceptions.Unauthorized, sess.get, self.TEST_URL) - - resp = sess.get(self.TEST_URL, raise_exc=False) - self.assertEqual(401, resp.status_code) - - def test_passed_auth_plugin(self): - passed = CalledAuthPlugin() - sess = client_session.Session() - - self.requests_mock.get(CalledAuthPlugin.ENDPOINT + 'path', - status_code=200) - endpoint_filter = {'service_type': 'identity'} - - # no plugin with authenticated won't work - self.assertRaises(exceptions.MissingAuthPlugin, sess.get, 'path', - authenticated=True) - - # no plugin with an endpoint filter won't work - self.assertRaises(exceptions.MissingAuthPlugin, sess.get, 'path', - authenticated=False, endpoint_filter=endpoint_filter) - - resp = sess.get('path', auth=passed, endpoint_filter=endpoint_filter) - - self.assertEqual(200, resp.status_code) - self.assertTrue(passed.get_endpoint_called) - self.assertTrue(passed.get_token_called) - - def test_passed_auth_plugin_overrides(self): - fixed = CalledAuthPlugin() - passed = CalledAuthPlugin() - - sess = client_session.Session(fixed) - - self.requests_mock.get(CalledAuthPlugin.ENDPOINT + 'path', - status_code=200) - - resp = sess.get('path', auth=passed, - endpoint_filter={'service_type': 'identity'}) - - self.assertEqual(200, resp.status_code) - self.assertTrue(passed.get_endpoint_called) - self.assertTrue(passed.get_token_called) - self.assertFalse(fixed.get_endpoint_called) - self.assertFalse(fixed.get_token_called) - - def test_requests_auth_plugin(self): - sess = client_session.Session() - - requests_auth = object() - - FAKE_RESP = utils.TestResponse({'status_code': 200, 'text': 'resp'}) - RESP = mock.Mock(return_value=FAKE_RESP) - - with mock.patch.object(sess.session, 'request', RESP) as mocked: - sess.get(self.TEST_URL, requests_auth=requests_auth) - - mocked.assert_called_once_with('GET', self.TEST_URL, - headers=mock.ANY, - allow_redirects=mock.ANY, - auth=requests_auth, - verify=mock.ANY) - - def test_reauth_called(self): - auth = CalledAuthPlugin(invalidate=True) - sess = client_session.Session(auth=auth) - - self.requests_mock.get(self.TEST_URL, - [{'text': 'Failed', 'status_code': 401}, - {'text': 'Hello', 'status_code': 200}]) - - # allow_reauth=True is the default - resp = sess.get(self.TEST_URL, authenticated=True) - - self.assertEqual(200, resp.status_code) - self.assertEqual('Hello', resp.text) - self.assertTrue(auth.invalidate_called) - - def test_reauth_not_called(self): - auth = CalledAuthPlugin(invalidate=True) - sess = client_session.Session(auth=auth) - - self.requests_mock.get(self.TEST_URL, - [{'text': 'Failed', 'status_code': 401}, - {'text': 'Hello', 'status_code': 200}]) - - self.assertRaises(exceptions.Unauthorized, sess.get, self.TEST_URL, - authenticated=True, allow_reauth=False) - self.assertFalse(auth.invalidate_called) - - def test_endpoint_override_overrides_filter(self): - auth = CalledAuthPlugin() - sess = client_session.Session(auth=auth) - - override_base = 'http://mytest/' - path = 'path' - override_url = override_base + path - resp_text = uuid.uuid4().hex - - self.requests_mock.get(override_url, text=resp_text) - - resp = sess.get(path, - endpoint_override=override_base, - endpoint_filter={'service_type': 'identity'}) - - self.assertEqual(resp_text, resp.text) - self.assertEqual(override_url, self.requests_mock.last_request.url) - - self.assertTrue(auth.get_token_called) - self.assertFalse(auth.get_endpoint_called) - - def test_endpoint_override_ignore_full_url(self): - auth = CalledAuthPlugin() - sess = client_session.Session(auth=auth) - - path = 'path' - url = self.TEST_URL + path - - resp_text = uuid.uuid4().hex - self.requests_mock.get(url, text=resp_text) - - resp = sess.get(url, - endpoint_override='http://someother.url', - endpoint_filter={'service_type': 'identity'}) - - self.assertEqual(resp_text, resp.text) - self.assertEqual(url, self.requests_mock.last_request.url) - - self.assertTrue(auth.get_token_called) - self.assertFalse(auth.get_endpoint_called) - - def test_user_and_project_id(self): - auth = AuthPlugin() - sess = client_session.Session(auth=auth) - - self.assertEqual(auth.TEST_USER_ID, sess.get_user_id()) - self.assertEqual(auth.TEST_PROJECT_ID, sess.get_project_id()) - - def test_logger_object_passed(self): - logger = logging.getLogger(uuid.uuid4().hex) - logger.setLevel(logging.DEBUG) - logger.propagate = False - - io = six.StringIO() - handler = logging.StreamHandler(io) - logger.addHandler(handler) - - auth = AuthPlugin() - sess = client_session.Session(auth=auth) - response = uuid.uuid4().hex - - self.stub_url('GET', - text=response, - headers={'Content-Type': 'text/html'}) - - resp = sess.get(self.TEST_URL, logger=logger) - - self.assertEqual(response, resp.text) - output = io.getvalue() - - self.assertIn(self.TEST_URL, output) - self.assertIn(response, output) - - self.assertNotIn(self.TEST_URL, self.logger.output) - self.assertNotIn(response, self.logger.output) - - -class AdapterTest(utils.TestCase): - - SERVICE_TYPE = uuid.uuid4().hex - SERVICE_NAME = uuid.uuid4().hex - INTERFACE = uuid.uuid4().hex - REGION_NAME = uuid.uuid4().hex - USER_AGENT = uuid.uuid4().hex - VERSION = uuid.uuid4().hex - - TEST_URL = CalledAuthPlugin.ENDPOINT - - def _create_loaded_adapter(self): - auth = CalledAuthPlugin() - sess = client_session.Session() - return adapter.Adapter(sess, - auth=auth, - service_type=self.SERVICE_TYPE, - service_name=self.SERVICE_NAME, - interface=self.INTERFACE, - region_name=self.REGION_NAME, - user_agent=self.USER_AGENT, - version=self.VERSION) - - def _verify_endpoint_called(self, adpt): - self.assertEqual(self.SERVICE_TYPE, - adpt.auth.endpoint_arguments['service_type']) - self.assertEqual(self.SERVICE_NAME, - adpt.auth.endpoint_arguments['service_name']) - self.assertEqual(self.INTERFACE, - adpt.auth.endpoint_arguments['interface']) - self.assertEqual(self.REGION_NAME, - adpt.auth.endpoint_arguments['region_name']) - self.assertEqual(self.VERSION, - adpt.auth.endpoint_arguments['version']) - - def test_setting_variables_on_request(self): - response = uuid.uuid4().hex - self.stub_url('GET', text=response) - adpt = self._create_loaded_adapter() - resp = adpt.get('/') - self.assertEqual(resp.text, response) - - self._verify_endpoint_called(adpt) - self.assertTrue(adpt.auth.get_token_called) - self.assertRequestHeaderEqual('User-Agent', self.USER_AGENT) - - def test_setting_variables_on_get_endpoint(self): - adpt = self._create_loaded_adapter() - url = adpt.get_endpoint() - - self.assertEqual(self.TEST_URL, url) - self._verify_endpoint_called(adpt) - - def test_legacy_binding(self): - key = uuid.uuid4().hex - val = uuid.uuid4().hex - response = jsonutils.dumps({key: val}) - - self.stub_url('GET', text=response) - - auth = CalledAuthPlugin() - sess = client_session.Session(auth=auth) - adpt = adapter.LegacyJsonAdapter(sess, - service_type=self.SERVICE_TYPE, - user_agent=self.USER_AGENT) - - resp, body = adpt.get('/') - self.assertEqual(self.SERVICE_TYPE, - auth.endpoint_arguments['service_type']) - self.assertEqual(resp.text, response) - self.assertEqual(val, body[key]) - - def test_legacy_binding_non_json_resp(self): - response = uuid.uuid4().hex - self.stub_url('GET', text=response, - headers={'Content-Type': 'text/html'}) - - auth = CalledAuthPlugin() - sess = client_session.Session(auth=auth) - adpt = adapter.LegacyJsonAdapter(sess, - service_type=self.SERVICE_TYPE, - user_agent=self.USER_AGENT) - - resp, body = adpt.get('/') - self.assertEqual(self.SERVICE_TYPE, - auth.endpoint_arguments['service_type']) - self.assertEqual(resp.text, response) - self.assertIsNone(body) - - def test_methods(self): - sess = client_session.Session() - adpt = adapter.Adapter(sess) - url = 'http://url' - - for method in ['get', 'head', 'post', 'put', 'patch', 'delete']: - with mock.patch.object(adpt, 'request') as m: - getattr(adpt, method)(url) - m.assert_called_once_with(url, method.upper()) - - def test_setting_endpoint_override(self): - endpoint_override = 'http://overrideurl' - path = '/path' - endpoint_url = endpoint_override + path - - auth = CalledAuthPlugin() - sess = client_session.Session(auth=auth) - adpt = adapter.Adapter(sess, endpoint_override=endpoint_override) - - response = uuid.uuid4().hex - self.requests_mock.get(endpoint_url, text=response) - - resp = adpt.get(path) - - self.assertEqual(response, resp.text) - self.assertEqual(endpoint_url, self.requests_mock.last_request.url) - - self.assertEqual(endpoint_override, adpt.get_endpoint()) - - def test_adapter_invalidate(self): - auth = CalledAuthPlugin() - sess = client_session.Session() - adpt = adapter.Adapter(sess, auth=auth) - - adpt.invalidate() - - self.assertTrue(auth.invalidate_called) - - def test_adapter_get_token(self): - auth = CalledAuthPlugin() - sess = client_session.Session() - adpt = adapter.Adapter(sess, auth=auth) - - self.assertEqual(self.TEST_TOKEN, adpt.get_token()) - self.assertTrue(auth.get_token_called) - - def test_adapter_connect_retries(self): - retries = 2 - sess = client_session.Session() - adpt = adapter.Adapter(sess, connect_retries=retries) - - def _refused_error(request, context): - raise requests.exceptions.ConnectionError() - - self.stub_url('GET', text=_refused_error) - - with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.ConnectionRefused, - adpt.get, self.TEST_URL) - self.assertEqual(retries, m.call_count) - - # we count retries so there will be one initial request + 2 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) - - def test_user_and_project_id(self): - auth = AuthPlugin() - sess = client_session.Session() - adpt = adapter.Adapter(sess, auth=auth) - - self.assertEqual(auth.TEST_USER_ID, adpt.get_user_id()) - self.assertEqual(auth.TEST_PROJECT_ID, adpt.get_project_id()) - - def test_logger_object_passed(self): - logger = logging.getLogger(uuid.uuid4().hex) - logger.setLevel(logging.DEBUG) - logger.propagate = False - - io = six.StringIO() - handler = logging.StreamHandler(io) - logger.addHandler(handler) - - auth = AuthPlugin() - sess = client_session.Session(auth=auth) - adpt = adapter.Adapter(sess, auth=auth, logger=logger) - - response = uuid.uuid4().hex - - self.stub_url('GET', text=response, - headers={'Content-Type': 'text/html'}) - - resp = adpt.get(self.TEST_URL, logger=logger) - - self.assertEqual(response, resp.text) - output = io.getvalue() - - self.assertIn(self.TEST_URL, output) - self.assertIn(response, output) - - self.assertNotIn(self.TEST_URL, self.logger.output) - self.assertNotIn(response, self.logger.output) - - -class ConfLoadingTests(utils.TestCase): - - GROUP = 'sessiongroup' - - def setUp(self): - super(ConfLoadingTests, self).setUp() - - self.conf_fixture = self.useFixture(config.Config()) - client_session.Session.register_conf_options(self.conf_fixture.conf, - self.GROUP) - - def config(self, **kwargs): - kwargs['group'] = self.GROUP - self.conf_fixture.config(**kwargs) - - def get_session(self, **kwargs): - return client_session.Session.load_from_conf_options( - self.conf_fixture.conf, - self.GROUP, - **kwargs) - - def test_insecure_timeout(self): - self.config(insecure=True, timeout=5) - s = self.get_session() - - self.assertFalse(s.verify) - self.assertEqual(5, s.timeout) - - def test_client_certs(self): - cert = '/path/to/certfile' - key = '/path/to/keyfile' - - self.config(certfile=cert, keyfile=key) - s = self.get_session() - - self.assertTrue(s.verify) - self.assertEqual((cert, key), s.cert) - - def test_cacert(self): - cafile = '/path/to/cacert' - - self.config(cafile=cafile) - s = self.get_session() - - self.assertEqual(cafile, s.verify) - - def test_deprecated(self): - def new_deprecated(): - return cfg.DeprecatedOpt(uuid.uuid4().hex, group=uuid.uuid4().hex) - - opt_names = ['cafile', 'certfile', 'keyfile', 'insecure', 'timeout'] - depr = dict([(n, [new_deprecated()]) for n in opt_names]) - opts = client_session.Session.get_conf_options(deprecated_opts=depr) - - self.assertThat(opt_names, matchers.HasLength(len(opts))) - for opt in opts: - self.assertIn(depr[opt.name][0], opt.deprecated_opts) - - -class CliLoadingTests(utils.TestCase): - - def setUp(self): - super(CliLoadingTests, self).setUp() - - self.parser = argparse.ArgumentParser() - client_session.Session.register_cli_options(self.parser) - - def get_session(self, val, **kwargs): - args = self.parser.parse_args(val.split()) - return client_session.Session.load_from_cli_options(args, **kwargs) - - def test_insecure_timeout(self): - s = self.get_session('--insecure --timeout 5.5') - - self.assertFalse(s.verify) - self.assertEqual(5.5, s.timeout) - - def test_client_certs(self): - cert = '/path/to/certfile' - key = '/path/to/keyfile' - - s = self.get_session('--os-cert %s --os-key %s' % (cert, key)) - - self.assertTrue(s.verify) - self.assertEqual((cert, key), s.cert) - - def test_cacert(self): - cacert = '/path/to/cacert' - - s = self.get_session('--os-cacert %s' % cacert) - - self.assertEqual(cacert, s.verify) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_shell.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_shell.py deleted file mode 100644 index 452f9e7931..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_shell.py +++ /dev/null @@ -1,532 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import json -import logging -import os -import sys -import uuid - -import fixtures -import mock -import six -import testtools -from testtools import matchers - -from keystoneclient import exceptions -from keystoneclient import session -from keystoneclient import shell as openstack_shell -from keystoneclient.tests.unit import utils -from keystoneclient.v2_0 import shell as shell_v2_0 - - -DEFAULT_USERNAME = 'username' -DEFAULT_PASSWORD = 'password' -DEFAULT_TENANT_ID = 'tenant_id' -DEFAULT_TENANT_NAME = 'tenant_name' -DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/' - - -# Make a fake shell object, a helping wrapper to call it -def shell(cmd): - openstack_shell.OpenStackIdentityShell().main(cmd.split()) - - -class NoExitArgumentParser(argparse.ArgumentParser): - def error(self, message): - raise exceptions.CommandError(message) - - -class ShellTest(utils.TestCase): - - FAKE_ENV = { - 'OS_USERNAME': DEFAULT_USERNAME, - 'OS_PASSWORD': DEFAULT_PASSWORD, - 'OS_TENANT_ID': DEFAULT_TENANT_ID, - 'OS_TENANT_NAME': DEFAULT_TENANT_NAME, - 'OS_AUTH_URL': DEFAULT_AUTH_URL, - } - - def _tolerant_shell(self, cmd): - t_shell = openstack_shell.OpenStackIdentityShell(NoExitArgumentParser) - t_shell.main(cmd.split()) - - # Patch os.environ to avoid required auth info. - def setUp(self): - - super(ShellTest, self).setUp() - for var in os.environ: - if var.startswith("OS_"): - self.useFixture(fixtures.EnvironmentVariable(var, "")) - - for var in self.FAKE_ENV: - self.useFixture(fixtures.EnvironmentVariable(var, - self.FAKE_ENV[var])) - - def test_help_unknown_command(self): - self.assertRaises(exceptions.CommandError, shell, 'help %s' - % uuid.uuid4().hex) - - def shell(self, argstr): - orig = sys.stdout - clean_env = {} - _old_env, os.environ = os.environ, clean_env.copy() - try: - sys.stdout = six.StringIO() - _shell = openstack_shell.OpenStackIdentityShell() - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(exc_value.code, 0) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - os.environ = _old_env - return out - - def test_help_no_args(self): - do_tenant_mock = mock.MagicMock() - with mock.patch('keystoneclient.shell.OpenStackIdentityShell.do_help', - do_tenant_mock): - self.shell('') - assert do_tenant_mock.called - - def test_help(self): - required = 'usage:' - help_text = self.shell('help') - self.assertThat(help_text, - matchers.MatchesRegex(required)) - - def test_help_command(self): - required = 'usage: keystone user-create' - help_text = self.shell('help user-create') - self.assertThat(help_text, - matchers.MatchesRegex(required)) - - def test_help_command_with_no_action_choices(self): - required = 'usage: keystone user-update' - help_text = self.shell('help user-update') - self.assertThat(help_text, - matchers.MatchesRegex(required)) - - def test_auth_no_credentials(self): - with testtools.ExpectedException( - exceptions.CommandError, 'Expecting'): - self.shell('user-list') - - def test_debug(self): - logging_mock = mock.MagicMock() - with mock.patch('logging.basicConfig', logging_mock): - self.assertRaises(exceptions.CommandError, - self.shell, '--debug user-list') - self.assertTrue(logging_mock.called) - self.assertEqual([(), {'level': logging.DEBUG}], - list(logging_mock.call_args)) - - def test_auth_password_authurl_no_username(self): - with testtools.ExpectedException( - exceptions.CommandError, - 'Expecting a username provided via either'): - self.shell('--os-password=%s --os-auth-url=%s user-list' - % (uuid.uuid4().hex, uuid.uuid4().hex)) - - def test_auth_username_password_no_authurl(self): - with testtools.ExpectedException( - exceptions.CommandError, 'Expecting an auth URL via either'): - self.shell('--os-password=%s --os-username=%s user-list' - % (uuid.uuid4().hex, uuid.uuid4().hex)) - - def test_token_no_endpoint(self): - with testtools.ExpectedException( - exceptions.CommandError, 'Expecting an endpoint provided'): - self.shell('--os-token=%s user-list' % uuid.uuid4().hex) - - def test_endpoint_no_token(self): - with testtools.ExpectedException( - exceptions.CommandError, 'Expecting a token provided'): - self.shell('--os-endpoint=http://10.0.0.1:5000/v2.0/ user-list') - - def test_shell_args(self): - do_tenant_mock = mock.MagicMock() - with mock.patch('keystoneclient.v2_0.shell.do_user_list', - do_tenant_mock): - shell('user-list') - assert do_tenant_mock.called - ((a, b), c) = do_tenant_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # Old_style options - shell('--os_auth_url http://0.0.0.0:5000/ --os_password xyzpdq ' - '--os_tenant_id 1234 --os_tenant_name fred ' - '--os_username barney ' - '--os_identity_api_version 2.0 user-list') - assert do_tenant_mock.called - ((a, b), c) = do_tenant_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = ('http://0.0.0.0:5000/', 'xyzpdq', '1234', - 'fred', 'barney', '2.0') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - shell('--os-auth-url http://1.1.1.1:5000/ --os-password xyzpdq ' - '--os-tenant-id 4321 --os-tenant-name wilma ' - '--os-username betty ' - '--os-identity-api-version 2.0 user-list') - assert do_tenant_mock.called - ((a, b), c) = do_tenant_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = ('http://1.1.1.1:5000/', 'xyzpdq', '4321', - 'wilma', 'betty', '2.0') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # Test keyring options - shell('--os-auth-url http://1.1.1.1:5000/ --os-password xyzpdq ' - '--os-tenant-id 4321 --os-tenant-name wilma ' - '--os-username betty ' - '--os-identity-api-version 2.0 ' - '--os-cache ' - '--stale-duration 500 ' - '--force-new-token user-list') - assert do_tenant_mock.called - ((a, b), c) = do_tenant_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version, b.os_cache, - b.stale_duration, b.force_new_token) - expect = ('http://1.1.1.1:5000/', 'xyzpdq', '4321', - 'wilma', 'betty', '2.0', True, '500', True) - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # Test os-identity-api-version fall back to 2.0 - shell('--os-identity-api-version 3.0 user-list') - assert do_tenant_mock.called - self.assertTrue(b.os_identity_api_version, '2.0') - - def test_shell_user_create_args(self): - """Test user-create args.""" - do_uc_mock = mock.MagicMock() - # grab the decorators for do_user_create - uc_func = getattr(shell_v2_0, 'do_user_create') - do_uc_mock.arguments = getattr(uc_func, 'arguments', []) - with mock.patch('keystoneclient.v2_0.shell.do_user_create', - do_uc_mock): - - # Old_style options - # Test case with one --tenant_id args present: ec2 creds - shell('user-create --name=FOO ' - '--pass=secret --tenant_id=barrr --enabled=true') - assert do_uc_mock.called - ((a, b), c) = do_uc_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant_id, b.name, b.passwd, b.enabled) - expect = ('barrr', 'FOO', 'secret', 'true') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - # Test case with one --tenant args present: ec2 creds - shell('user-create --name=foo ' - '--pass=secret --tenant=BARRR --enabled=true') - assert do_uc_mock.called - ((a, b), c) = do_uc_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant, b.name, b.passwd, b.enabled) - expect = ('BARRR', 'foo', 'secret', 'true') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - # Test case with one --tenant-id args present: ec2 creds - shell('user-create --name=foo ' - '--pass=secret --tenant-id=BARRR --enabled=true') - assert do_uc_mock.called - ((a, b), c) = do_uc_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant, b.name, b.passwd, b.enabled) - expect = ('BARRR', 'foo', 'secret', 'true') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # Old_style options - # Test case with --os_tenant_id and --tenant_id args present - shell('--os_tenant_id=os-tenant user-create --name=FOO ' - '--pass=secret --tenant_id=barrr --enabled=true') - assert do_uc_mock.called - ((a, b), c) = do_uc_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'os-tenant', - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant_id, b.name, b.passwd, b.enabled) - expect = ('barrr', 'FOO', 'secret', 'true') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - # Test case with --os-tenant-id and --tenant-id args present - shell('--os-tenant-id=ostenant user-create --name=foo ' - '--pass=secret --tenant-id=BARRR --enabled=true') - assert do_uc_mock.called - ((a, b), c) = do_uc_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'ostenant', - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant, b.name, b.passwd, b.enabled) - expect = ('BARRR', 'foo', 'secret', 'true') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - def test_do_tenant_create(self): - do_tenant_mock = mock.MagicMock() - with mock.patch('keystoneclient.v2_0.shell.do_tenant_create', - do_tenant_mock): - shell('tenant-create') - assert do_tenant_mock.called - # FIXME(dtroyer): how do you test the decorators? - # shell('tenant-create --tenant-name wilma ' - # '--description "fred\'s wife"') - # assert do_tenant_mock.called - - def test_do_tenant_list(self): - do_tenant_mock = mock.MagicMock() - with mock.patch('keystoneclient.v2_0.shell.do_tenant_list', - do_tenant_mock): - shell('tenant-list') - assert do_tenant_mock.called - - def test_shell_tenant_id_args(self): - """Test a corner case where --tenant_id appears on the - command-line twice. - """ - do_ec2_mock = mock.MagicMock() - # grab the decorators for do_ec2_create_credentials - ec2_func = getattr(shell_v2_0, 'do_ec2_credentials_create') - do_ec2_mock.arguments = getattr(ec2_func, 'arguments', []) - with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_create', - do_ec2_mock): - - # Old_style options - # Test case with one --tenant_id args present: ec2 creds - shell('ec2-credentials-create ' - '--tenant_id=ec2-tenant --user_id=ec2-user') - assert do_ec2_mock.called - ((a, b), c) = do_ec2_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant_id, b.user_id) - expect = ('ec2-tenant', 'ec2-user') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - # Test case with one --tenant-id args present: ec2 creds - shell('ec2-credentials-create ' - '--tenant-id=dash-tenant --user-id=dash-user') - assert do_ec2_mock.called - ((a, b), c) = do_ec2_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant_id, b.user_id) - expect = ('dash-tenant', 'dash-user') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # Old_style options - # Test case with two --tenant_id args present - shell('--os_tenant_id=os-tenant ec2-credentials-create ' - '--tenant_id=ec2-tenant --user_id=ec2-user') - assert do_ec2_mock.called - ((a, b), c) = do_ec2_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'os-tenant', - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant_id, b.user_id) - expect = ('ec2-tenant', 'ec2-user') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - # Test case with two --tenant-id args present - shell('--os-tenant-id=ostenant ec2-credentials-create ' - '--tenant-id=dash-tenant --user-id=dash-user') - assert do_ec2_mock.called - ((a, b), c) = do_ec2_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'ostenant', - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.tenant_id, b.user_id) - expect = ('dash-tenant', 'dash-user') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - def test_do_ec2_get(self): - do_shell_mock = mock.MagicMock() - - with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_create', - do_shell_mock): - shell('ec2-credentials-create') - assert do_shell_mock.called - - with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_get', - do_shell_mock): - shell('ec2-credentials-get') - assert do_shell_mock.called - - with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_list', - do_shell_mock): - shell('ec2-credentials-list') - assert do_shell_mock.called - - with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_delete', - do_shell_mock): - shell('ec2-credentials-delete') - assert do_shell_mock.called - - def test_timeout_parse_invalid_type(self): - for f in ['foobar', 'xyz']: - cmd = '--timeout %s endpoint-create' % (f) - self.assertRaises(exceptions.CommandError, - self._tolerant_shell, cmd) - - def test_timeout_parse_invalid_number(self): - for f in [-1, 0]: - cmd = '--timeout %s endpoint-create' % (f) - self.assertRaises(exceptions.CommandError, - self._tolerant_shell, cmd) - - def test_do_timeout(self): - response_mock = mock.MagicMock() - response_mock.status_code = 200 - response_mock.text = json.dumps({ - 'endpoints': [], - }) - request_mock = mock.MagicMock(return_value=response_mock) - with mock.patch.object(session.requests, 'request', - request_mock): - shell(('--timeout 2 --os-token=blah --os-endpoint=blah' - ' --os-auth-url=blah.com endpoint-list')) - request_mock.assert_called_with(mock.ANY, mock.ANY, - timeout=2, - allow_redirects=False, - headers=mock.ANY, - verify=mock.ANY) - - def test_do_endpoints(self): - do_shell_mock = mock.MagicMock() - # grab the decorators for do_endpoint_create - shell_func = getattr(shell_v2_0, 'do_endpoint_create') - do_shell_mock.arguments = getattr(shell_func, 'arguments', []) - with mock.patch('keystoneclient.v2_0.shell.do_endpoint_create', - do_shell_mock): - - # Old_style options - # Test create args - shell('endpoint-create ' - '--service_id=2 --publicurl=http://example.com:1234/go ' - '--adminurl=http://example.com:9876/adm') - assert do_shell_mock.called - ((a, b), c) = do_shell_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.service, b.publicurl, b.adminurl) - expect = ('2', - 'http://example.com:1234/go', - 'http://example.com:9876/adm') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - # Test create args - shell('endpoint-create ' - '--service-id=3 --publicurl=http://example.com:4321/go ' - '--adminurl=http://example.com:9876/adm') - assert do_shell_mock.called - ((a, b), c) = do_shell_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.service, b.publicurl, b.adminurl) - expect = ('3', - 'http://example.com:4321/go', - 'http://example.com:9876/adm') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - # New-style options - # Test create args - shell('endpoint-create ' - '--service=3 --publicurl=http://example.com:4321/go ' - '--adminurl=http://example.com:9876/adm') - assert do_shell_mock.called - ((a, b), c) = do_shell_mock.call_args - actual = (b.os_auth_url, b.os_password, b.os_tenant_id, - b.os_tenant_name, b.os_username, - b.os_identity_api_version) - expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID, - DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - actual = (b.service, b.publicurl, b.adminurl) - expect = ('3', - 'http://example.com:4321/go', - 'http://example.com:9876/adm') - self.assertTrue(all([x == y for x, y in zip(actual, expect)])) - - def test_shell_keyboard_interrupt(self): - shell_mock = mock.MagicMock() - with mock.patch('keystoneclient.shell.OpenStackIdentityShell.main', - shell_mock): - try: - shell_mock.side_effect = KeyboardInterrupt() - openstack_shell.main() - except SystemExit as ex: - self.assertEqual(130, ex.code) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/test_utils.py b/awx/lib/site-packages/keystoneclient/tests/unit/test_utils.py deleted file mode 100644 index 8f0de9b0f1..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/test_utils.py +++ /dev/null @@ -1,240 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import sys - -import six -import testresources -from testtools import matchers - -from keystoneclient import exceptions -from keystoneclient.tests.unit import client_fixtures -from keystoneclient.tests.unit import utils as test_utils -from keystoneclient import utils - - -class FakeResource(object): - pass - - -class FakeManager(object): - - resource_class = FakeResource - - resources = { - '1234': {'name': 'entity_one'}, - '8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0': {'name': 'entity_two'}, - '\xe3\x82\xbdtest': {'name': u'\u30bdtest'}, - '5678': {'name': '9876'} - } - - def get(self, resource_id): - try: - return self.resources[str(resource_id)] - except KeyError: - raise exceptions.NotFound(resource_id) - - def find(self, name=None): - if name == '9999': - # NOTE(morganfainberg): special case that raises NoUniqueMatch. - raise exceptions.NoUniqueMatch() - for resource_id, resource in self.resources.items(): - if resource['name'] == str(name): - return resource - raise exceptions.NotFound(name) - - -class FindResourceTestCase(test_utils.TestCase): - - def setUp(self): - super(FindResourceTestCase, self).setUp() - self.manager = FakeManager() - - def test_find_none(self): - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - 'asdf') - - def test_find_by_integer_id(self): - output = utils.find_resource(self.manager, 1234) - self.assertEqual(output, self.manager.resources['1234']) - - def test_find_by_str_id(self): - output = utils.find_resource(self.manager, '1234') - self.assertEqual(output, self.manager.resources['1234']) - - def test_find_by_uuid(self): - uuid = '8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0' - output = utils.find_resource(self.manager, uuid) - self.assertEqual(output, self.manager.resources[uuid]) - - def test_find_by_unicode(self): - name = '\xe3\x82\xbdtest' - output = utils.find_resource(self.manager, name) - self.assertEqual(output, self.manager.resources[name]) - - def test_find_by_str_name(self): - output = utils.find_resource(self.manager, 'entity_one') - self.assertEqual(output, self.manager.resources['1234']) - - def test_find_by_int_name(self): - output = utils.find_resource(self.manager, 9876) - self.assertEqual(output, self.manager.resources['5678']) - - def test_find_no_unique_match(self): - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - 9999) - - -class FakeObject(object): - def __init__(self, name): - self.name = name - - -class PrintTestCase(test_utils.TestCase): - def setUp(self): - super(PrintTestCase, self).setUp() - self.old_stdout = sys.stdout - self.stdout = six.moves.cStringIO() - self.addCleanup(setattr, self, 'stdout', None) - sys.stdout = self.stdout - self.addCleanup(setattr, sys, 'stdout', self.old_stdout) - - def test_print_list_unicode(self): - name = six.u('\u540d\u5b57') - objs = [FakeObject(name)] - # NOTE(Jeffrey4l) If the text's encode is proper, this method will not - # raise UnicodeEncodeError exceptions - utils.print_list(objs, ['name']) - output = self.stdout.getvalue() - # In Python 2, output will be bytes, while in Python 3, it will not. - # Let's decode the value if needed. - if isinstance(output, six.binary_type): - output = output.decode('utf-8') - self.assertIn(name, output) - - def test_print_dict_unicode(self): - name = six.u('\u540d\u5b57') - utils.print_dict({'name': name}) - output = self.stdout.getvalue() - # In Python 2, output will be bytes, while in Python 3, it will not. - # Let's decode the value if needed. - if isinstance(output, six.binary_type): - output = output.decode('utf-8') - self.assertIn(name, output) - - -class TestPositional(test_utils.TestCase): - - @utils.positional(1) - def no_vars(self): - # positional doesn't enforce anything here - return True - - @utils.positional(3, utils.positional.EXCEPT) - def mixed_except(self, arg, kwarg1=None, kwarg2=None): - # self, arg, and kwarg1 may be passed positionally - return (arg, kwarg1, kwarg2) - - @utils.positional(3, utils.positional.WARN) - def mixed_warn(self, arg, kwarg1=None, kwarg2=None): - # self, arg, and kwarg1 may be passed positionally, only a warning - # is emitted - return (arg, kwarg1, kwarg2) - - def test_nothing(self): - self.assertTrue(self.no_vars()) - - def test_mixed_except(self): - self.assertEqual((1, 2, 3), self.mixed_except(1, 2, kwarg2=3)) - self.assertEqual((1, 2, 3), self.mixed_except(1, kwarg1=2, kwarg2=3)) - self.assertEqual((1, None, None), self.mixed_except(1)) - self.assertRaises(TypeError, self.mixed_except, 1, 2, 3) - - def test_mixed_warn(self): - logger_message = six.moves.cStringIO() - handler = logging.StreamHandler(logger_message) - handler.setLevel(logging.DEBUG) - - logger = logging.getLogger(utils.__name__) - level = logger.getEffectiveLevel() - logger.setLevel(logging.DEBUG) - logger.addHandler(handler) - - self.addCleanup(logger.removeHandler, handler) - self.addCleanup(logger.setLevel, level) - - self.mixed_warn(1, 2, 3) - - self.assertIn('takes at most 3 positional', logger_message.getvalue()) - - @utils.positional(enforcement=utils.positional.EXCEPT) - def inspect_func(self, arg, kwarg=None): - return (arg, kwarg) - - def test_inspect_positions(self): - self.assertEqual((1, None), self.inspect_func(1)) - self.assertEqual((1, 2), self.inspect_func(1, kwarg=2)) - self.assertRaises(TypeError, self.inspect_func) - self.assertRaises(TypeError, self.inspect_func, 1, 2) - - @utils.positional.classmethod(1) - def class_method(cls, a, b): - return (cls, a, b) - - @utils.positional.method(1) - def normal_method(self, a, b): - self.assertIsInstance(self, TestPositional) - return (self, a, b) - - def test_class_method(self): - self.assertEqual((TestPositional, 1, 2), self.class_method(1, b=2)) - self.assertRaises(TypeError, self.class_method, 1, 2) - - def test_normal_method(self): - self.assertEqual((self, 1, 2), self.normal_method(1, b=2)) - self.assertRaises(TypeError, self.normal_method, 1, 2) - - -class HashSignedTokenTestCase(test_utils.TestCase, - testresources.ResourcedTestCase): - """Unit tests for utils.hash_signed_token().""" - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_default_md5(self): - """The default hash method is md5.""" - token = self.examples.SIGNED_TOKEN_SCOPED - if six.PY3: - token = token.encode('utf-8') - token_id_default = utils.hash_signed_token(token) - token_id_md5 = utils.hash_signed_token(token, mode='md5') - self.assertThat(token_id_default, matchers.Equals(token_id_md5)) - # md5 hash is 32 chars. - self.assertThat(token_id_default, matchers.HasLength(32)) - - def test_sha256(self): - """Can also hash with sha256.""" - token = self.examples.SIGNED_TOKEN_SCOPED - if six.PY3: - token = token.encode('utf-8') - token_id = utils.hash_signed_token(token, mode='sha256') - # sha256 hash is 64 chars. - self.assertThat(token_id, matchers.HasLength(64)) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/utils.py b/awx/lib/site-packages/keystoneclient/tests/unit/utils.py deleted file mode 100644 index b3405fbcbe..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/utils.py +++ /dev/null @@ -1,209 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import sys -import time -import uuid - -import fixtures -import mock -from mox3 import mox -from oslo_serialization import jsonutils -import requests -from requests_mock.contrib import fixture -import six -from six.moves.urllib import parse as urlparse -import testtools - - -class TestCase(testtools.TestCase): - - TEST_DOMAIN_ID = '1' - TEST_DOMAIN_NAME = 'aDomain' - TEST_GROUP_ID = uuid.uuid4().hex - TEST_ROLE_ID = uuid.uuid4().hex - TEST_TENANT_ID = '1' - TEST_TENANT_NAME = 'aTenant' - TEST_TOKEN = 'aToken' - TEST_TRUST_ID = 'aTrust' - TEST_USER = 'test' - TEST_USER_ID = uuid.uuid4().hex - - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - - def setUp(self): - super(TestCase, self).setUp() - self.mox = mox.Mox() - self.logger = self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) - self.time_patcher = mock.patch.object(time, 'time', lambda: 1234) - self.time_patcher.start() - - self.requests_mock = self.useFixture(fixture.Fixture()) - - def tearDown(self): - self.time_patcher.stop() - self.mox.UnsetStubs() - self.mox.VerifyAll() - super(TestCase, self).tearDown() - - def stub_url(self, method, parts=None, base_url=None, json=None, **kwargs): - if not base_url: - base_url = self.TEST_URL - - if json: - kwargs['text'] = jsonutils.dumps(json) - headers = kwargs.setdefault('headers', {}) - headers['Content-Type'] = 'application/json' - - if parts: - url = '/'.join([p.strip('/') for p in [base_url] + parts]) - else: - url = base_url - - url = url.replace("/?", "?") - self.requests_mock.register_uri(method, url, **kwargs) - - def assertRequestBodyIs(self, body=None, json=None): - last_request_body = self.requests_mock.last_request.body - if json: - val = jsonutils.loads(last_request_body) - self.assertEqual(json, val) - elif body: - self.assertEqual(body, last_request_body) - - def assertQueryStringIs(self, qs=''): - """Verify the QueryString matches what is expected. - - The qs parameter should be of the format \'foo=bar&abc=xyz\' - """ - expected = urlparse.parse_qs(qs, keep_blank_values=True) - parts = urlparse.urlparse(self.requests_mock.last_request.url) - querystring = urlparse.parse_qs(parts.query, keep_blank_values=True) - self.assertEqual(expected, querystring) - - def assertQueryStringContains(self, **kwargs): - """Verify the query string contains the expected parameters. - - This method is used to verify that the query string for the most recent - request made contains all the parameters provided as ``kwargs``, and - that the value of each parameter contains the value for the kwarg. If - the value for the kwarg is an empty string (''), then all that's - verified is that the parameter is present. - - """ - parts = urlparse.urlparse(self.requests_mock.last_request.url) - qs = urlparse.parse_qs(parts.query, keep_blank_values=True) - - for k, v in six.iteritems(kwargs): - self.assertIn(k, qs) - self.assertIn(v, qs[k]) - - def assertRequestHeaderEqual(self, name, val): - """Verify that the last request made contains a header and its value - - The request must have already been made. - """ - headers = self.requests_mock.last_request.headers - self.assertEqual(headers.get(name), val) - - -if tuple(sys.version_info)[0:2] < (2, 7): - - def assertDictEqual(self, d1, d2, msg=None): - # Simple version taken from 2.7 - self.assertIsInstance(d1, dict, - 'First argument is not a dictionary') - self.assertIsInstance(d2, dict, - 'Second argument is not a dictionary') - if d1 != d2: - if msg: - self.fail(msg) - else: - standardMsg = '%r != %r' % (d1, d2) - self.fail(standardMsg) - - TestCase.assertDictEqual = assertDictEqual - - -class TestResponse(requests.Response): - """Class used to wrap requests.Response and provide some - convenience to initialize with a dict. - """ - - def __init__(self, data): - self._text = None - super(TestResponse, self).__init__() - if isinstance(data, dict): - self.status_code = data.get('status_code', 200) - headers = data.get('headers') - if headers: - self.headers.update(headers) - # Fake the text attribute to streamline Response creation - # _content is defined by requests.Response - self._content = data.get('text') - else: - self.status_code = data - - def __eq__(self, other): - return self.__dict__ == other.__dict__ - - @property - def text(self): - return self.content - - -class DisableModuleFixture(fixtures.Fixture): - """A fixture to provide support for unloading/disabling modules.""" - - def __init__(self, module, *args, **kw): - super(DisableModuleFixture, self).__init__(*args, **kw) - self.module = module - self._finders = [] - self._cleared_modules = {} - - def tearDown(self): - super(DisableModuleFixture, self).tearDown() - for finder in self._finders: - sys.meta_path.remove(finder) - sys.modules.update(self._cleared_modules) - - def clear_module(self): - cleared_modules = {} - for fullname in sys.modules.keys(): - if (fullname == self.module or - fullname.startswith(self.module + '.')): - cleared_modules[fullname] = sys.modules.pop(fullname) - return cleared_modules - - def setUp(self): - """Ensure ImportError for the specified module.""" - - super(DisableModuleFixture, self).setUp() - - # Clear 'module' references in sys.modules - self._cleared_modules.update(self.clear_module()) - - finder = NoModuleFinder(self.module) - self._finders.append(finder) - sys.meta_path.insert(0, finder) - - -class NoModuleFinder(object): - """Disallow further imports of 'module'.""" - - def __init__(self, module): - self.module = module - - def find_module(self, fullname, path): - if fullname == self.module or fullname.startswith(self.module + '.'): - raise ImportError diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/__init__.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/client_fixtures.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/client_fixtures.py deleted file mode 100644 index 39d808eb14..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/client_fixtures.py +++ /dev/null @@ -1,124 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import unicode_literals - -from keystoneclient import fixture - - -def unscoped_token(): - return fixture.V2Token(token_id='3e2813b7ba0b4006840c3825860b86ed', - expires='2012-10-03T16:58:01Z', - user_id='c4da488862bd435c9e6c0275a0d0e49a', - user_name='exampleuser') - - -def project_scoped_token(): - _TENANT_ID = '225da22d3ce34b15877ea70b2a575f58' - - f = fixture.V2Token(token_id='04c7d5ffaeef485f9dc69c06db285bdb', - expires='2012-10-03T16:53:36Z', - tenant_id='225da22d3ce34b15877ea70b2a575f58', - tenant_name='exampleproject', - user_id='c4da488862bd435c9e6c0275a0d0e49a', - user_name='exampleuser') - - f.add_role(id='member_id', name='Member') - - s = f.add_service('volume', 'Volume Service') - s.add_endpoint(public='http://public.com:8776/v1/%s' % _TENANT_ID, - admin='http://admin:8776/v1/%s' % _TENANT_ID, - internal='http://internal:8776/v1/%s' % _TENANT_ID, - region='RegionOne') - - s = f.add_service('image', 'Image Service') - s.add_endpoint(public='http://public.com:9292/v1', - admin='http://admin:9292/v1', - internal='http://internal:9292/v1', - region='RegionOne') - - s = f.add_service('compute', 'Compute Service') - s.add_endpoint(public='http://public.com:8774/v2/%s' % _TENANT_ID, - admin='http://admin:8774/v2/%s' % _TENANT_ID, - internal='http://internal:8774/v2/%s' % _TENANT_ID, - region='RegionOne') - - s = f.add_service('ec2', 'EC2 Service') - s.add_endpoint(public='http://public.com:8773/services/Cloud', - admin='http://admin:8773/services/Admin', - internal='http://internal:8773/services/Cloud', - region='RegionOne') - - s = f.add_service('identity', 'Identity Service') - s.add_endpoint(public='http://public.com:5000/v2.0', - admin='http://admin:35357/v2.0', - internal='http://internal:5000/v2.0', - region='RegionOne') - - return f - - -def auth_response_body(): - f = fixture.V2Token(token_id='ab48a9efdfedb23ty3494', - expires='2010-11-01T03:32:15-05:00', - tenant_id='345', - tenant_name='My Project', - user_id='123', - user_name='jqsmith') - - f.add_role(id='234', name='compute:admin') - role = f.add_role(id='235', name='object-store:admin') - role['tenantId'] = '1' - - s = f.add_service('compute', 'Cloud Servers') - endpoint = s.add_endpoint(public='https://compute.north.host/v1/1234', - internal='https://compute.north.host/v1/1234', - region='North') - endpoint['tenantId'] = '1' - endpoint['versionId'] = '1.0' - endpoint['versionInfo'] = 'https://compute.north.host/v1.0/' - endpoint['versionList'] = 'https://compute.north.host/' - - endpoint = s.add_endpoint(public='https://compute.north.host/v1.1/3456', - internal='https://compute.north.host/v1.1/3456', - region='North') - endpoint['tenantId'] = '2' - endpoint['versionId'] = '1.1' - endpoint['versionInfo'] = 'https://compute.north.host/v1.1/' - endpoint['versionList'] = 'https://compute.north.host/' - - s = f.add_service('object-store', 'Cloud Files') - endpoint = s.add_endpoint(public='https://swift.north.host/v1/blah', - internal='https://swift.north.host/v1/blah', - region='South') - endpoint['tenantId'] = '11' - endpoint['versionId'] = '1.0' - endpoint['versionInfo'] = 'uri' - endpoint['versionList'] = 'uri' - - endpoint = s.add_endpoint(public='https://swift.north.host/v1.1/blah', - internal='https://compute.north.host/v1.1/blah', - region='South') - endpoint['tenantId'] = '2' - endpoint['versionId'] = '1.1' - endpoint['versionInfo'] = 'https://swift.north.host/v1.1/' - endpoint['versionList'] = 'https://swift.north.host/' - - s = f.add_service('image', 'Image Servers') - s.add_endpoint(public='https://image.north.host/v1/', - internal='https://image-internal.north.host/v1/', - region='North') - s.add_endpoint(public='https://image.south.host/v1/', - internal='https://image-internal.south.host/v1/', - region='South') - - return f diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_access.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_access.py deleted file mode 100644 index f05f138d8a..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_access.py +++ /dev/null @@ -1,201 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime -import uuid - -from oslo_utils import timeutils -import testresources - -from keystoneclient import access -from keystoneclient import fixture -from keystoneclient.tests.unit import client_fixtures as token_data -from keystoneclient.tests.unit.v2_0 import client_fixtures -from keystoneclient.tests.unit.v2_0 import utils - - -class AccessInfoTest(utils.TestCase, testresources.ResourcedTestCase): - - resources = [('examples', token_data.EXAMPLES_RESOURCE)] - - def test_building_unscoped_accessinfo(self): - token = client_fixtures.unscoped_token() - auth_ref = access.AccessInfo.factory(body=token) - - self.assertTrue(auth_ref) - self.assertIn('token', auth_ref) - - self.assertEqual(auth_ref.auth_token, - '3e2813b7ba0b4006840c3825860b86ed') - self.assertEqual(auth_ref.username, 'exampleuser') - self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a') - - self.assertEqual(auth_ref.role_ids, []) - self.assertEqual(auth_ref.role_names, []) - - self.assertIsNone(auth_ref.tenant_name) - self.assertIsNone(auth_ref.tenant_id) - - self.assertIsNone(auth_ref.auth_url) - self.assertIsNone(auth_ref.management_url) - - self.assertFalse(auth_ref.scoped) - self.assertFalse(auth_ref.domain_scoped) - self.assertFalse(auth_ref.project_scoped) - self.assertFalse(auth_ref.trust_scoped) - - self.assertIsNone(auth_ref.project_domain_id) - self.assertIsNone(auth_ref.project_domain_name) - self.assertEqual(auth_ref.user_domain_id, 'default') - self.assertEqual(auth_ref.user_domain_name, 'Default') - - self.assertEqual(auth_ref.expires, token.expires) - self.assertEqual(auth_ref.issued, token.issued) - - def test_will_expire_soon(self): - token = client_fixtures.unscoped_token() - expires = timeutils.utcnow() + datetime.timedelta(minutes=5) - token.expires = expires - auth_ref = access.AccessInfo.factory(body=token) - self.assertFalse(auth_ref.will_expire_soon(stale_duration=120)) - self.assertTrue(auth_ref.will_expire_soon(stale_duration=300)) - self.assertFalse(auth_ref.will_expire_soon()) - - def test_building_scoped_accessinfo(self): - token = client_fixtures.project_scoped_token() - auth_ref = access.AccessInfo.factory(body=token) - - self.assertTrue(auth_ref) - self.assertIn('token', auth_ref) - self.assertIn('serviceCatalog', auth_ref) - self.assertTrue(auth_ref['serviceCatalog']) - - self.assertEqual(auth_ref.auth_token, - '04c7d5ffaeef485f9dc69c06db285bdb') - self.assertEqual(auth_ref.username, 'exampleuser') - self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a') - - self.assertEqual(auth_ref.role_ids, ['member_id']) - self.assertEqual(auth_ref.role_names, ['Member']) - - self.assertEqual(auth_ref.tenant_name, 'exampleproject') - self.assertEqual(auth_ref.tenant_id, - '225da22d3ce34b15877ea70b2a575f58') - - self.assertEqual(auth_ref.tenant_name, auth_ref.project_name) - self.assertEqual(auth_ref.tenant_id, auth_ref.project_id) - - self.assertEqual(auth_ref.auth_url, ('http://public.com:5000/v2.0',)) - self.assertEqual(auth_ref.management_url, ('http://admin:35357/v2.0',)) - - self.assertEqual(auth_ref.project_domain_id, 'default') - self.assertEqual(auth_ref.project_domain_name, 'Default') - self.assertEqual(auth_ref.user_domain_id, 'default') - self.assertEqual(auth_ref.user_domain_name, 'Default') - - self.assertTrue(auth_ref.scoped) - self.assertTrue(auth_ref.project_scoped) - self.assertFalse(auth_ref.domain_scoped) - - def test_diablo_token(self): - diablo_token = self.examples.TOKEN_RESPONSES[ - self.examples.VALID_DIABLO_TOKEN] - auth_ref = access.AccessInfo.factory(body=diablo_token) - - self.assertTrue(auth_ref) - self.assertEqual(auth_ref.username, 'user_name1') - self.assertEqual(auth_ref.project_id, 'tenant_id1') - self.assertEqual(auth_ref.project_name, 'tenant_id1') - self.assertEqual(auth_ref.project_domain_id, 'default') - self.assertEqual(auth_ref.project_domain_name, 'Default') - self.assertEqual(auth_ref.user_domain_id, 'default') - self.assertEqual(auth_ref.user_domain_name, 'Default') - self.assertEqual(auth_ref.role_names, ['role1', 'role2']) - self.assertFalse(auth_ref.scoped) - - def test_grizzly_token(self): - grizzly_token = self.examples.TOKEN_RESPONSES[ - self.examples.SIGNED_TOKEN_SCOPED_KEY] - auth_ref = access.AccessInfo.factory(body=grizzly_token) - - self.assertEqual(auth_ref.project_id, 'tenant_id1') - self.assertEqual(auth_ref.project_name, 'tenant_name1') - self.assertEqual(auth_ref.project_domain_id, 'default') - self.assertEqual(auth_ref.project_domain_name, 'Default') - self.assertEqual(auth_ref.user_domain_id, 'default') - self.assertEqual(auth_ref.user_domain_name, 'Default') - self.assertEqual(auth_ref.role_names, ['role1', 'role2']) - - def test_v2_roles(self): - role_id = 'a' - role_name = 'b' - - token = fixture.V2Token() - token.set_scope() - token.add_role(id=role_id, name=role_name) - - auth_ref = access.AccessInfo.factory(body=token) - - self.assertEqual([role_id], auth_ref.role_ids) - self.assertEqual([role_id], auth_ref['metadata']['roles']) - self.assertEqual([role_name], auth_ref.role_names) - self.assertEqual([{'name': role_name}], auth_ref['user']['roles']) - - def test_trusts(self): - user_id = uuid.uuid4().hex - trust_id = uuid.uuid4().hex - - token = fixture.V2Token(user_id=user_id, trust_id=trust_id) - token.set_scope() - token.add_role() - - auth_ref = access.AccessInfo.factory(body=token) - - self.assertEqual(trust_id, auth_ref.trust_id) - self.assertEqual(user_id, auth_ref.trustee_user_id) - - self.assertEqual(trust_id, token['access']['trust']['id']) - - def test_override_auth_token(self): - token = fixture.V2Token() - token.set_scope() - token.add_role() - - new_auth_token = uuid.uuid4().hex - - auth_ref = access.AccessInfo.factory(body=token) - - self.assertEqual(token.token_id, auth_ref.auth_token) - - auth_ref.auth_token = new_auth_token - self.assertEqual(new_auth_token, auth_ref.auth_token) - - del auth_ref.auth_token - self.assertEqual(token.token_id, auth_ref.auth_token) - - def test_override_auth_token_in_factory(self): - token = fixture.V2Token() - token.set_scope() - token.add_role() - - new_auth_token = uuid.uuid4().hex - - auth_ref = access.AccessInfo.factory(body=token, - auth_token=new_auth_token) - - self.assertEqual(new_auth_token, auth_ref.auth_token) - del auth_ref.auth_token - self.assertEqual(token.token_id, auth_ref.auth_token) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_auth.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_auth.py deleted file mode 100644 index 2c69dc3d19..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_auth.py +++ /dev/null @@ -1,258 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import datetime - -from oslo_serialization import jsonutils -from oslo_utils import timeutils - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import client - - -class AuthenticateAgainstKeystoneTests(utils.TestCase): - def setUp(self): - super(AuthenticateAgainstKeystoneTests, self).setUp() - self.TEST_RESPONSE_DICT = { - "access": { - "token": { - "expires": "2020-01-01T00:00:10.000123Z", - "id": self.TEST_TOKEN, - "tenant": { - "id": self.TEST_TENANT_ID - }, - }, - "user": { - "id": self.TEST_USER - }, - "serviceCatalog": self.TEST_SERVICE_CATALOG, - }, - } - self.TEST_REQUEST_BODY = { - "auth": { - "passwordCredentials": { - "username": self.TEST_USER, - "password": self.TEST_TOKEN, - }, - "tenantId": self.TEST_TENANT_ID, - }, - } - - def test_authenticate_success_expired(self): - resp_a = copy.deepcopy(self.TEST_RESPONSE_DICT) - resp_b = copy.deepcopy(self.TEST_RESPONSE_DICT) - headers = {'Content-Type': 'application/json'} - - # Build an expired token - resp_a['access']['token']['expires'] = ( - (timeutils.utcnow() - datetime.timedelta(1)).isoformat()) - - # Build a new response - TEST_TOKEN = "abcdef" - resp_b['access']['token']['expires'] = '2020-01-01T00:00:10.000123Z' - resp_b['access']['token']['id'] = TEST_TOKEN - - # return expired first, and then the new response - self.stub_auth(response_list=[{'json': resp_a, 'headers': headers}, - {'json': resp_b, 'headers': headers}]) - - cs = client.Client(tenant_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_TOKEN) - - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3] - ['endpoints'][0]["adminURL"]) - - self.assertEqual(cs.auth_token, TEST_TOKEN) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_failure(self): - _auth = 'auth' - _cred = 'passwordCredentials' - _pass = 'password' - self.TEST_REQUEST_BODY[_auth][_cred][_pass] = 'bad_key' - error = {"unauthorized": {"message": "Unauthorized", - "code": "401"}} - - self.stub_auth(status_code=401, json=error) - - # Workaround for issue with assertRaises on python2.6 - # where with assertRaises(exceptions.Unauthorized): doesn't work - # right - def client_create_wrapper(): - client.Client(username=self.TEST_USER, - password="bad_key", - tenant_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - - self.assertRaises(exceptions.Unauthorized, client_create_wrapper) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_auth_redirect(self): - self.stub_auth(status_code=305, text='Use Proxy', - headers={'Location': self.TEST_ADMIN_URL + "/tokens"}) - - self.stub_auth(base_url=self.TEST_ADMIN_URL, - json=self.TEST_RESPONSE_DICT) - - cs = client.Client(username=self.TEST_USER, - password=self.TEST_TOKEN, - tenant_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3] - ['endpoints'][0]["adminURL"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_DICT["access"]["token"]["id"]) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_password_scoped(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(username=self.TEST_USER, - password=self.TEST_TOKEN, - tenant_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3] - ['endpoints'][0]["adminURL"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_DICT["access"]["token"]["id"]) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_password_unscoped(self): - del self.TEST_RESPONSE_DICT['access']['serviceCatalog'] - del self.TEST_REQUEST_BODY['auth']['tenantId'] - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(username=self.TEST_USER, - password=self.TEST_TOKEN, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_DICT["access"]["token"]["id"]) - self.assertFalse('serviceCatalog' in cs.service_catalog.catalog) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_auth_url_token_authentication(self): - fake_token = 'fake_token' - fake_url = '/fake-url' - fake_resp = {'result': True} - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [fake_url], json=fake_resp, - base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT) - - cl = client.Client(auth_url=self.TEST_URL, - token=fake_token) - json_body = jsonutils.loads(self.requests_mock.last_request.body) - self.assertEqual(json_body['auth']['token']['id'], fake_token) - - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(self.TEST_TOKEN, token) - - def test_authenticate_success_token_scoped(self): - del self.TEST_REQUEST_BODY['auth']['passwordCredentials'] - self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN} - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(token=self.TEST_TOKEN, - tenant_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3] - ['endpoints'][0]["adminURL"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_DICT["access"]["token"]["id"]) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_token_scoped_trust(self): - del self.TEST_REQUEST_BODY['auth']['passwordCredentials'] - self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN} - self.TEST_REQUEST_BODY['auth']['trust_id'] = self.TEST_TRUST_ID - response = self.TEST_RESPONSE_DICT.copy() - response['access']['trust'] = {"trustee_user_id": self.TEST_USER, - "id": self.TEST_TRUST_ID} - self.stub_auth(json=response) - - cs = client.Client(token=self.TEST_TOKEN, - tenant_id=self.TEST_TENANT_ID, - trust_id=self.TEST_TRUST_ID, - auth_url=self.TEST_URL) - self.assertTrue(cs.auth_ref.trust_scoped) - self.assertEqual(cs.auth_ref.trust_id, self.TEST_TRUST_ID) - self.assertEqual(cs.auth_ref.trustee_user_id, self.TEST_USER) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_token_unscoped(self): - del self.TEST_REQUEST_BODY['auth']['passwordCredentials'] - del self.TEST_REQUEST_BODY['auth']['tenantId'] - del self.TEST_RESPONSE_DICT['access']['serviceCatalog'] - self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN} - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(token=self.TEST_TOKEN, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_DICT["access"]["token"]["id"]) - self.assertFalse('serviceCatalog' in cs.service_catalog.catalog) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_allow_override_of_auth_token(self): - fake_url = '/fake-url' - fake_token = 'fake_token' - fake_resp = {'result': True} - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [fake_url], json=fake_resp, - base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT) - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL) - - self.assertEqual(cl.auth_token, self.TEST_TOKEN) - - # the token returned from the authentication will be used - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(self.TEST_TOKEN, token) - - # then override that token and the new token shall be used - cl.auth_token = fake_token - - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(fake_token, token) - - # if we clear that overridden token then we fall back to the original - del cl.auth_token - - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(self.TEST_TOKEN, token) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_certificates.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_certificates.py deleted file mode 100644 index fc19d8119c..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_certificates.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2014 IBM Corp. -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import testresources - -from keystoneclient.tests.unit import client_fixtures -from keystoneclient.tests.unit.v2_0 import utils - - -class CertificateTests(utils.TestCase, testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_get_ca_certificate(self): - self.stub_url('GET', ['certificates', 'ca'], - headers={'Content-Type': 'text/html; charset=UTF-8'}, - text=self.examples.SIGNING_CA) - res = self.client.certificates.get_ca_certificate() - self.assertEqual(self.examples.SIGNING_CA, res) - - def test_get_signing_certificate(self): - self.stub_url('GET', ['certificates', 'signing'], - headers={'Content-Type': 'text/html; charset=UTF-8'}, - text=self.examples.SIGNING_CERT) - res = self.client.certificates.get_signing_certificate() - self.assertEqual(self.examples.SIGNING_CERT, res) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_client.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_client.py deleted file mode 100644 index 2700b31820..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_client.py +++ /dev/null @@ -1,184 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import uuid - -import six - -from keystoneclient.auth import token_endpoint -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient import session -from keystoneclient.tests.unit.v2_0 import client_fixtures -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import client - - -class KeystoneClientTest(utils.TestCase): - - def test_unscoped_init(self): - token = client_fixtures.unscoped_token() - self.stub_auth(json=token) - - c = client.Client(username='exampleuser', - password='password', - auth_url=self.TEST_URL) - self.assertIsNotNone(c.auth_ref) - self.assertFalse(c.auth_ref.scoped) - self.assertFalse(c.auth_ref.domain_scoped) - self.assertFalse(c.auth_ref.project_scoped) - self.assertIsNone(c.auth_ref.trust_id) - self.assertFalse(c.auth_ref.trust_scoped) - self.assertIsNone(c.get_project_id(session=None)) - self.assertEqual(token.user_id, c.get_user_id(session=None)) - - def test_scoped_init(self): - token = client_fixtures.project_scoped_token() - self.stub_auth(json=token) - - c = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL) - self.assertIsNotNone(c.auth_ref) - self.assertTrue(c.auth_ref.scoped) - self.assertTrue(c.auth_ref.project_scoped) - self.assertFalse(c.auth_ref.domain_scoped) - self.assertIsNone(c.auth_ref.trust_id) - self.assertFalse(c.auth_ref.trust_scoped) - - self.assertEqual(token.tenant_id, c.get_project_id(session=None)) - self.assertEqual(token.user_id, c.get_user_id(session=None)) - - def test_auth_ref_load(self): - self.stub_auth(json=client_fixtures.project_scoped_token()) - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL) - cache = json.dumps(cl.auth_ref) - new_client = client.Client(auth_ref=json.loads(cache)) - self.assertIsNotNone(new_client.auth_ref) - self.assertTrue(new_client.auth_ref.scoped) - self.assertTrue(new_client.auth_ref.project_scoped) - self.assertFalse(new_client.auth_ref.domain_scoped) - self.assertIsNone(new_client.auth_ref.trust_id) - self.assertFalse(new_client.auth_ref.trust_scoped) - self.assertEqual(new_client.username, 'exampleuser') - self.assertIsNone(new_client.password) - self.assertEqual(new_client.management_url, - 'http://admin:35357/v2.0') - - def test_auth_ref_load_with_overridden_arguments(self): - self.stub_auth(json=client_fixtures.project_scoped_token()) - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL) - cache = json.dumps(cl.auth_ref) - new_auth_url = "http://new-public:5000/v2.0" - new_client = client.Client(auth_ref=json.loads(cache), - auth_url=new_auth_url) - self.assertIsNotNone(new_client.auth_ref) - self.assertTrue(new_client.auth_ref.scoped) - self.assertTrue(new_client.auth_ref.scoped) - self.assertTrue(new_client.auth_ref.project_scoped) - self.assertFalse(new_client.auth_ref.domain_scoped) - self.assertIsNone(new_client.auth_ref.trust_id) - self.assertFalse(new_client.auth_ref.trust_scoped) - self.assertEqual(new_client.auth_url, new_auth_url) - self.assertEqual(new_client.username, 'exampleuser') - self.assertIsNone(new_client.password) - self.assertEqual(new_client.management_url, - 'http://admin:35357/v2.0') - - def test_init_err_no_auth_url(self): - self.assertRaises(exceptions.AuthorizationFailure, - client.Client, - username='exampleuser', - password='password') - - def test_management_url_is_updated(self): - first = fixture.V2Token() - first.set_scope() - admin_url = 'http://admin:35357/v2.0' - second_url = 'http://secondurl:35357/v2.0' - - s = first.add_service('identity') - s.add_endpoint(public='http://public.com:5000/v2.0', - admin=admin_url) - - second = fixture.V2Token() - second.set_scope() - s = second.add_service('identity') - s.add_endpoint(public='http://secondurl:5000/v2.0', - admin=second_url) - - self.stub_auth(response_list=[{'json': first}, {'json': second}]) - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL) - self.assertEqual(cl.management_url, admin_url) - - cl.authenticate() - self.assertEqual(cl.management_url, second_url) - - def test_client_with_region_name_passes_to_service_catalog(self): - # NOTE(jamielennox): this is deprecated behaviour that should be - # removed ASAP, however must remain compatible. - self.stub_auth(json=client_fixtures.auth_response_body()) - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL, - region_name='North') - self.assertEqual(cl.service_catalog.url_for(service_type='image'), - 'https://image.north.host/v1/') - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL, - region_name='South') - self.assertEqual(cl.service_catalog.url_for(service_type='image'), - 'https://image.south.host/v1/') - - def test_client_without_auth_params(self): - self.assertRaises(exceptions.AuthorizationFailure, - client.Client, - tenant_name='exampleproject', - auth_url=self.TEST_URL) - - def test_client_params(self): - opts = {'auth': token_endpoint.Token('a', 'b'), - 'connect_retries': 50, - 'endpoint_override': uuid.uuid4().hex, - 'interface': uuid.uuid4().hex, - 'region_name': uuid.uuid4().hex, - 'service_name': uuid.uuid4().hex, - 'user_agent': uuid.uuid4().hex, - } - - sess = session.Session() - cl = client.Client(session=sess, **opts) - - for k, v in six.iteritems(opts): - self.assertEqual(v, getattr(cl._adapter, k)) - - self.assertEqual('identity', cl._adapter.service_type) - self.assertEqual('v2.0', cl._adapter.version) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_discovery.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_discovery.py deleted file mode 100644 index 348038a43f..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_discovery.py +++ /dev/null @@ -1,80 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from keystoneclient.generic import client -from keystoneclient.tests.unit.v2_0 import utils - - -class DiscoverKeystoneTests(utils.UnauthenticatedTestCase): - def setUp(self): - super(DiscoverKeystoneTests, self).setUp() - self.TEST_RESPONSE_DICT = { - "versions": { - "values": [{ - "id": "v2.0", - "status": "beta", - "updated": "2011-11-19T00:00:00Z", - "links": [ - {"rel": "self", - "href": "http://127.0.0.1:5000/v2.0/", }, - {"rel": "describedby", - "type": "text/html", - "href": "http://docs.openstack.org/api/" - "openstack-identity-service/2.0/content/", }, - {"rel": "describedby", - "type": "application/pdf", - "href": "http://docs.openstack.org/api/" - "openstack-identity-service/2.0/" - "identity-dev-guide-2.0.pdf", }, - {"rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://127.0.0.1:5000/v2.0/identity.wadl", } - ], - "media-types": [{ - "base": "application/xml", - "type": "application/vnd.openstack.identity-v2.0+xml", - }, { - "base": "application/json", - "type": "application/vnd.openstack.identity-v2.0+json", - }], - }], - }, - } - - def test_get_versions(self): - self.stub_url('GET', base_url=self.TEST_ROOT_URL, - json=self.TEST_RESPONSE_DICT) - - cs = client.Client() - versions = cs.discover(self.TEST_ROOT_URL) - self.assertIsInstance(versions, dict) - self.assertIn('message', versions) - self.assertIn('v2.0', versions) - self.assertEqual( - versions['v2.0']['url'], - self.TEST_RESPONSE_DICT['versions']['values'][0]['links'][0] - ['href']) - - def test_get_version_local(self): - self.stub_url('GET', base_url="http://localhost:35357/", - json=self.TEST_RESPONSE_DICT) - - cs = client.Client() - versions = cs.discover() - self.assertIsInstance(versions, dict) - self.assertIn('message', versions) - self.assertIn('v2.0', versions) - self.assertEqual( - versions['v2.0']['url'], - self.TEST_RESPONSE_DICT['versions']['values'][0]['links'][0] - ['href']) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_ec2.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_ec2.py deleted file mode 100644 index e08d228f2c..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_ec2.py +++ /dev/null @@ -1,107 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import ec2 - - -class EC2Tests(utils.TestCase): - - def test_create(self): - user_id = 'usr' - tenant_id = 'tnt' - req_body = { - "tenant_id": tenant_id, - } - resp_body = { - "credential": { - "access": "access", - "secret": "secret", - "tenant_id": tenant_id, - "created": "12/12/12", - "enabled": True, - } - } - self.stub_url('POST', ['users', user_id, 'credentials', - 'OS-EC2'], json=resp_body) - - cred = self.client.ec2.create(user_id, tenant_id) - self.assertIsInstance(cred, ec2.EC2) - self.assertEqual(cred.tenant_id, tenant_id) - self.assertEqual(cred.enabled, True) - self.assertEqual(cred.access, 'access') - self.assertEqual(cred.secret, 'secret') - self.assertRequestBodyIs(json=req_body) - - def test_get(self): - user_id = 'usr' - tenant_id = 'tnt' - resp_body = { - "credential": { - "access": "access", - "secret": "secret", - "tenant_id": tenant_id, - "created": "12/12/12", - "enabled": True, - } - } - self.stub_url('GET', ['users', user_id, 'credentials', - 'OS-EC2', 'access'], json=resp_body) - - cred = self.client.ec2.get(user_id, 'access') - self.assertIsInstance(cred, ec2.EC2) - self.assertEqual(cred.tenant_id, tenant_id) - self.assertEqual(cred.enabled, True) - self.assertEqual(cred.access, 'access') - self.assertEqual(cred.secret, 'secret') - - def test_list(self): - user_id = 'usr' - tenant_id = 'tnt' - resp_body = { - "credentials": { - "values": [ - { - "access": "access", - "secret": "secret", - "tenant_id": tenant_id, - "created": "12/12/12", - "enabled": True, - }, - { - "access": "another", - "secret": "key", - "tenant_id": tenant_id, - "created": "12/12/31", - "enabled": True, - } - ] - } - } - self.stub_url('GET', ['users', user_id, 'credentials', - 'OS-EC2'], json=resp_body) - - creds = self.client.ec2.list(user_id) - self.assertEqual(len(creds), 2) - cred = creds[0] - self.assertIsInstance(cred, ec2.EC2) - self.assertEqual(cred.tenant_id, tenant_id) - self.assertEqual(cred.enabled, True) - self.assertEqual(cred.access, 'access') - self.assertEqual(cred.secret, 'secret') - - def test_delete(self): - user_id = 'usr' - access = 'access' - self.stub_url('DELETE', ['users', user_id, 'credentials', - 'OS-EC2', access], status_code=204) - self.client.ec2.delete(user_id, access) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_endpoints.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_endpoints.py deleted file mode 100644 index ffc1c65d1d..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_endpoints.py +++ /dev/null @@ -1,147 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import endpoints - - -class EndpointTests(utils.TestCase): - def setUp(self): - super(EndpointTests, self).setUp() - self.TEST_ENDPOINTS = { - 'endpoints': [ - { - 'adminurl': 'http://host-1:8774/v1.1/$(tenant_id)s', - 'id': '8f9531231e044e218824b0e58688d262', - 'internalurl': 'http://host-1:8774/v1.1/$(tenant_id)s', - 'publicurl': 'http://host-1:8774/v1.1/$(tenant_id)s', - 'region': 'RegionOne', - }, - { - 'adminurl': 'http://host-1:8774/v1.1/$(tenant_id)s', - 'id': '8f9531231e044e218824b0e58688d263', - 'internalurl': 'http://host-1:8774/v1.1/$(tenant_id)s', - 'publicurl': 'http://host-1:8774/v1.1/$(tenant_id)s', - 'region': 'RegionOne', - } - ] - } - - def test_create_with_optional_params(self): - req_body = { - "endpoint": { - "region": "RegionOne", - "publicurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "internalurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "adminurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "service_id": uuid.uuid4().hex, - } - } - - resp_body = { - "endpoint": { - "adminurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "region": "RegionOne", - "id": uuid.uuid4().hex, - "internalurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "publicurl": "http://host-3:8774/v1.1/$(tenant_id)s", - } - } - - self.stub_url('POST', ['endpoints'], json=resp_body) - - endpoint = self.client.endpoints.create( - region=req_body['endpoint']['region'], - publicurl=req_body['endpoint']['publicurl'], - adminurl=req_body['endpoint']['adminurl'], - internalurl=req_body['endpoint']['internalurl'], - service_id=req_body['endpoint']['service_id'] - ) - self.assertIsInstance(endpoint, endpoints.Endpoint) - self.assertRequestBodyIs(json=req_body) - - def test_create_with_optional_params_as_none(self): - req_body_without_defaults = { - "endpoint": { - "region": "RegionOne", - "service_id": uuid.uuid4().hex, - "publicurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "adminurl": None, - "internalurl": None, - } - } - - resp_body = { - "endpoint": { - "region": "RegionOne", - "id": uuid.uuid4().hex, - "publicurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "adminurl": None, - "internalurl": None, - } - } - - self.stub_url('POST', ['endpoints'], json=resp_body) - - endpoint_without_defaults = self.client.endpoints.create( - region=req_body_without_defaults['endpoint']['region'], - publicurl=req_body_without_defaults['endpoint']['publicurl'], - service_id=req_body_without_defaults['endpoint']['service_id'], - adminurl=None, - internalurl=None - ) - self.assertIsInstance(endpoint_without_defaults, endpoints.Endpoint) - self.assertRequestBodyIs(json=req_body_without_defaults) - - def test_create_without_optional_params(self): - req_body_without_defaults = { - "endpoint": { - "region": "RegionOne", - "service_id": uuid.uuid4().hex, - "publicurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "adminurl": None, - "internalurl": None, - } - } - - resp_body = { - "endpoint": { - "region": "RegionOne", - "id": uuid.uuid4().hex, - "publicurl": "http://host-3:8774/v1.1/$(tenant_id)s", - "adminurl": None, - "internalurl": None, - } - } - - self.stub_url('POST', ['endpoints'], json=resp_body) - - endpoint_without_defaults = self.client.endpoints.create( - region=req_body_without_defaults['endpoint']['region'], - publicurl=req_body_without_defaults['endpoint']['publicurl'], - service_id=req_body_without_defaults['endpoint']['service_id'] - ) - self.assertIsInstance(endpoint_without_defaults, endpoints.Endpoint) - self.assertRequestBodyIs(json=req_body_without_defaults) - - def test_delete(self): - self.stub_url('DELETE', ['endpoints', '8f953'], status_code=204) - self.client.endpoints.delete('8f953') - - def test_list(self): - self.stub_url('GET', ['endpoints'], json=self.TEST_ENDPOINTS) - - endpoint_list = self.client.endpoints.list() - [self.assertIsInstance(r, endpoints.Endpoint) - for r in endpoint_list] diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_extensions.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_extensions.py deleted file mode 100644 index d09943f4ba..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_extensions.py +++ /dev/null @@ -1,63 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import extensions - - -class ExtensionTests(utils.TestCase): - def setUp(self): - super(ExtensionTests, self).setUp() - self.TEST_EXTENSIONS = { - 'extensions': { - "values": [ - { - 'name': 'OpenStack Keystone User CRUD', - 'namespace': 'http://docs.openstack.org/' - 'identity/api/ext/OS-KSCRUD/v1.0', - 'updated': '2013-07-07T12:00:0-00:00', - 'alias': 'OS-KSCRUD', - 'description': - 'OpenStack extensions to Keystone v2.0 API' - ' enabling User Operations.', - 'links': - '[{"href":' - '"https://github.com/openstack/identity-api", "type":' - ' "text/html", "rel": "describedby"}]', - }, - { - 'name': 'OpenStack EC2 API', - 'namespace': 'http://docs.openstack.org/' - 'identity/api/ext/OS-EC2/v1.0', - 'updated': '2013-09-07T12:00:0-00:00', - 'alias': 'OS-EC2', - 'description': 'OpenStack EC2 Credentials backend.', - 'links': '[{"href":' - '"https://github.com/openstack/identity-api", "type":' - ' "text/html", "rel": "describedby"}]', - } - ] - } - } - - def test_list(self): - self.stub_url('GET', ['extensions'], json=self.TEST_EXTENSIONS) - extensions_list = self.client.extensions.list() - self.assertEqual(2, len(extensions_list)) - for extension in extensions_list: - self.assertIsInstance(extension, extensions.Extension) - self.assertIsNotNone(extension.alias) - self.assertIsNotNone(extension.description) - self.assertIsNotNone(extension.links) - self.assertIsNotNone(extension.name) - self.assertIsNotNone(extension.namespace) - self.assertIsNotNone(extension.updated) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_roles.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_roles.py deleted file mode 100644 index 74ad1ed548..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_roles.py +++ /dev/null @@ -1,121 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import roles - - -class RoleTests(utils.TestCase): - def setUp(self): - super(RoleTests, self).setUp() - - self.ADMIN_ROLE_ID = uuid.uuid4().hex - self.MEMBER_ROLE_ID = uuid.uuid4().hex - - self.TEST_ROLES = { - "roles": { - "values": [ - { - "name": "admin", - "id": self.ADMIN_ROLE_ID, - }, - { - "name": "member", - "id": self.MEMBER_ROLE_ID, - } - ], - }, - } - - def test_create(self): - req_body = { - "role": { - "name": "sysadmin", - } - } - role_id = uuid.uuid4().hex - resp_body = { - "role": { - "name": "sysadmin", - "id": role_id, - } - } - self.stub_url('POST', ['OS-KSADM', 'roles'], json=resp_body) - - role = self.client.roles.create(req_body['role']['name']) - self.assertRequestBodyIs(json=req_body) - self.assertIsInstance(role, roles.Role) - self.assertEqual(role.id, role_id) - self.assertEqual(role.name, req_body['role']['name']) - - def test_delete(self): - self.stub_url('DELETE', - ['OS-KSADM', 'roles', self.ADMIN_ROLE_ID], - status_code=204) - self.client.roles.delete(self.ADMIN_ROLE_ID) - - def test_get(self): - self.stub_url('GET', ['OS-KSADM', 'roles', self.ADMIN_ROLE_ID], - json={'role': self.TEST_ROLES['roles']['values'][0]}) - - role = self.client.roles.get(self.ADMIN_ROLE_ID) - self.assertIsInstance(role, roles.Role) - self.assertEqual(role.id, self.ADMIN_ROLE_ID) - self.assertEqual(role.name, 'admin') - - def test_list(self): - self.stub_url('GET', ['OS-KSADM', 'roles'], - json=self.TEST_ROLES) - - role_list = self.client.roles.list() - [self.assertIsInstance(r, roles.Role) for r in role_list] - - def test_roles_for_user(self): - self.stub_url('GET', ['users', 'foo', 'roles'], - json=self.TEST_ROLES) - - role_list = self.client.roles.roles_for_user('foo') - [self.assertIsInstance(r, roles.Role) for r in role_list] - - def test_roles_for_user_tenant(self): - self.stub_url('GET', ['tenants', 'barrr', 'users', 'foo', - 'roles'], json=self.TEST_ROLES) - - role_list = self.client.roles.roles_for_user('foo', 'barrr') - [self.assertIsInstance(r, roles.Role) for r in role_list] - - def test_add_user_role(self): - self.stub_url('PUT', ['users', 'foo', 'roles', 'OS-KSADM', - 'barrr'], status_code=204) - - self.client.roles.add_user_role('foo', 'barrr') - - def test_add_user_role_tenant(self): - id_ = uuid.uuid4().hex - self.stub_url('PUT', ['tenants', id_, 'users', 'foo', 'roles', - 'OS-KSADM', 'barrr'], status_code=204) - - self.client.roles.add_user_role('foo', 'barrr', id_) - - def test_remove_user_role(self): - self.stub_url('DELETE', ['users', 'foo', 'roles', 'OS-KSADM', - 'barrr'], status_code=204) - self.client.roles.remove_user_role('foo', 'barrr') - - def test_remove_user_role_tenant(self): - id_ = uuid.uuid4().hex - self.stub_url('DELETE', ['tenants', id_, 'users', 'foo', - 'roles', 'OS-KSADM', 'barrr'], - status_code=204) - self.client.roles.remove_user_role('foo', 'barrr', id_) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_service_catalog.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_service_catalog.py deleted file mode 100644 index fddda6de77..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_service_catalog.py +++ /dev/null @@ -1,200 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import access -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient.tests.unit.v2_0 import client_fixtures -from keystoneclient.tests.unit.v2_0 import utils - - -class ServiceCatalogTest(utils.TestCase): - def setUp(self): - super(ServiceCatalogTest, self).setUp() - self.AUTH_RESPONSE_BODY = client_fixtures.auth_response_body() - - def test_building_a_service_catalog(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - self.assertEqual(sc.url_for(service_type='compute'), - "https://compute.north.host/v1/1234") - self.assertEqual(sc.url_for('tenantId', '1', service_type='compute'), - "https://compute.north.host/v1/1234") - self.assertEqual(sc.url_for('tenantId', '2', service_type='compute'), - "https://compute.north.host/v1.1/3456") - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, "region", - "South", service_type='compute') - - def test_service_catalog_endpoints(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - public_ep = sc.get_endpoints(service_type='compute', - endpoint_type='publicURL') - self.assertEqual(public_ep['compute'][1]['tenantId'], '2') - self.assertEqual(public_ep['compute'][1]['versionId'], '1.1') - self.assertEqual(public_ep['compute'][1]['internalURL'], - "https://compute.north.host/v1.1/3456") - - def test_service_catalog_regions(self): - self.AUTH_RESPONSE_BODY['access']['region_name'] = "North" - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_type='image', endpoint_type='publicURL') - self.assertEqual(url, "https://image.north.host/v1/") - - self.AUTH_RESPONSE_BODY['access']['region_name'] = "South" - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_type='image', endpoint_type='internalURL') - self.assertEqual(url, "https://image-internal.south.host/v1/") - - def test_service_catalog_empty(self): - self.AUTH_RESPONSE_BODY['access']['serviceCatalog'] = [] - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - self.assertRaises(exceptions.EmptyCatalog, - auth_ref.service_catalog.url_for, - service_type='image', - endpoint_type='internalURL') - - def test_service_catalog_get_endpoints_region_names(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - endpoints = sc.get_endpoints(service_type='image', region_name='North') - self.assertEqual(len(endpoints), 1) - self.assertEqual(endpoints['image'][0]['publicURL'], - 'https://image.north.host/v1/') - - endpoints = sc.get_endpoints(service_type='image', region_name='South') - self.assertEqual(len(endpoints), 1) - self.assertEqual(endpoints['image'][0]['publicURL'], - 'https://image.south.host/v1/') - - endpoints = sc.get_endpoints(service_type='compute') - self.assertEqual(len(endpoints['compute']), 2) - - endpoints = sc.get_endpoints(service_type='compute', - region_name='North') - self.assertEqual(len(endpoints['compute']), 2) - - endpoints = sc.get_endpoints(service_type='compute', - region_name='West') - self.assertEqual(len(endpoints['compute']), 0) - - def test_service_catalog_url_for_region_names(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_type='image', region_name='North') - self.assertEqual(url, 'https://image.north.host/v1/') - - url = sc.url_for(service_type='image', region_name='South') - self.assertEqual(url, 'https://image.south.host/v1/') - - url = sc.url_for(service_type='compute', - region_name='North', - attr='versionId', - filter_value='1.1') - self.assertEqual(url, 'https://compute.north.host/v1.1/3456') - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_type='image', region_name='West') - - def test_servcie_catalog_get_url_region_names(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - urls = sc.get_urls(service_type='image') - self.assertEqual(len(urls), 2) - - urls = sc.get_urls(service_type='image', region_name='North') - self.assertEqual(len(urls), 1) - self.assertEqual(urls[0], 'https://image.north.host/v1/') - - urls = sc.get_urls(service_type='image', region_name='South') - self.assertEqual(len(urls), 1) - self.assertEqual(urls[0], 'https://image.south.host/v1/') - - urls = sc.get_urls(service_type='image', region_name='West') - self.assertIsNone(urls) - - def test_service_catalog_param_overrides_body_region(self): - self.AUTH_RESPONSE_BODY['access']['region_name'] = "North" - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_type='image') - self.assertEqual(url, 'https://image.north.host/v1/') - - url = sc.url_for(service_type='image', region_name='South') - self.assertEqual(url, 'https://image.south.host/v1/') - - endpoints = sc.get_endpoints(service_type='image') - self.assertEqual(len(endpoints['image']), 1) - self.assertEqual(endpoints['image'][0]['publicURL'], - 'https://image.north.host/v1/') - - endpoints = sc.get_endpoints(service_type='image', region_name='South') - self.assertEqual(len(endpoints['image']), 1) - self.assertEqual(endpoints['image'][0]['publicURL'], - 'https://image.south.host/v1/') - - def test_service_catalog_service_name(self): - auth_ref = access.AccessInfo.factory(resp=None, - body=self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_name='Image Servers', endpoint_type='public', - service_type='image', region_name='North') - self.assertEqual('https://image.north.host/v1/', url) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_name='Image Servers', service_type='compute') - - urls = sc.get_urls(service_type='image', service_name='Image Servers', - endpoint_type='public') - - self.assertIn('https://image.north.host/v1/', urls) - self.assertIn('https://image.south.host/v1/', urls) - - urls = sc.get_urls(service_type='image', service_name='Servers', - endpoint_type='public') - - self.assertIsNone(urls) - - def test_service_catalog_multiple_service_types(self): - token = fixture.V2Token() - token.set_scope() - - for i in range(3): - s = token.add_service('compute') - s.add_endpoint(public='public-%d' % i, - admin='admin-%d' % i, - internal='internal-%d' % i, - region='region-%d' % i) - - auth_ref = access.AccessInfo.factory(resp=None, body=token) - - urls = auth_ref.service_catalog.get_urls(service_type='compute', - endpoint_type='publicURL') - - self.assertEqual(set(['public-0', 'public-1', 'public-2']), set(urls)) - - urls = auth_ref.service_catalog.get_urls(service_type='compute', - endpoint_type='publicURL', - region_name='region-1') - - self.assertEqual(('public-1', ), urls) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_services.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_services.py deleted file mode 100644 index 21727453ec..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_services.py +++ /dev/null @@ -1,98 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import services - - -class ServiceTests(utils.TestCase): - def setUp(self): - super(ServiceTests, self).setUp() - - self.NOVA_SERVICE_ID = uuid.uuid4().hex - self.KEYSTONE_SERVICE_ID = uuid.uuid4().hex - - self.TEST_SERVICES = { - "OS-KSADM:services": { - "values": [ - { - "name": "nova", - "type": "compute", - "description": "Nova-compatible service.", - "id": self.NOVA_SERVICE_ID - }, - { - "name": "keystone", - "type": "identity", - "description": "Keystone-compatible service.", - "id": self.KEYSTONE_SERVICE_ID - }, - ], - }, - } - - def test_create(self): - req_body = { - "OS-KSADM:service": { - "name": "swift", - "type": "object-store", - "description": "Swift-compatible service.", - } - } - service_id = uuid.uuid4().hex - resp_body = { - "OS-KSADM:service": { - "name": "swift", - "type": "object-store", - "description": "Swift-compatible service.", - "id": service_id, - } - } - self.stub_url('POST', ['OS-KSADM', 'services'], json=resp_body) - - service = self.client.services.create( - req_body['OS-KSADM:service']['name'], - req_body['OS-KSADM:service']['type'], - req_body['OS-KSADM:service']['description']) - self.assertIsInstance(service, services.Service) - self.assertEqual(service.id, service_id) - self.assertEqual(service.name, req_body['OS-KSADM:service']['name']) - self.assertRequestBodyIs(json=req_body) - - def test_delete(self): - self.stub_url('DELETE', - ['OS-KSADM', 'services', self.NOVA_SERVICE_ID], - status_code=204) - - self.client.services.delete(self.NOVA_SERVICE_ID) - - def test_get(self): - test_services = self.TEST_SERVICES['OS-KSADM:services']['values'][0] - - self.stub_url('GET', ['OS-KSADM', 'services', self.NOVA_SERVICE_ID], - json={'OS-KSADM:service': test_services}) - - service = self.client.services.get(self.NOVA_SERVICE_ID) - self.assertIsInstance(service, services.Service) - self.assertEqual(service.id, self.NOVA_SERVICE_ID) - self.assertEqual(service.name, 'nova') - self.assertEqual(service.type, 'compute') - - def test_list(self): - self.stub_url('GET', ['OS-KSADM', 'services'], - json=self.TEST_SERVICES) - - service_list = self.client.services.list() - [self.assertIsInstance(r, services.Service) - for r in service_list] diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_shell.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_shell.py deleted file mode 100644 index 85bbca5f09..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_shell.py +++ /dev/null @@ -1,464 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import sys - -import mock -from oslo_serialization import jsonutils -import six -from testtools import matchers - -from keystoneclient import fixture -from keystoneclient.tests.unit.v2_0 import utils - - -DEFAULT_USERNAME = 'username' -DEFAULT_PASSWORD = 'password' -DEFAULT_TENANT_ID = 'tenant_id' -DEFAULT_TENANT_NAME = 'tenant_name' -DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/' -DEFAULT_ADMIN_URL = 'http://127.0.0.1:35357/v2.0/' - - -class ShellTests(utils.TestCase): - - TEST_URL = DEFAULT_ADMIN_URL - - def setUp(self): - """Patch os.environ to avoid required auth info.""" - - super(ShellTests, self).setUp() - - self.old_environment = os.environ.copy() - os.environ = { - 'OS_USERNAME': DEFAULT_USERNAME, - 'OS_PASSWORD': DEFAULT_PASSWORD, - 'OS_TENANT_ID': DEFAULT_TENANT_ID, - 'OS_TENANT_NAME': DEFAULT_TENANT_NAME, - 'OS_AUTH_URL': DEFAULT_AUTH_URL, - } - import keystoneclient.shell - self.shell = keystoneclient.shell.OpenStackIdentityShell() - - self.token = fixture.V2Token() - self.token.set_scope() - svc = self.token.add_service('identity') - svc.add_endpoint(public=DEFAULT_AUTH_URL, - admin=DEFAULT_ADMIN_URL) - - self.stub_auth(json=self.token, base_url=DEFAULT_AUTH_URL) - - def tearDown(self): - os.environ = self.old_environment - super(ShellTests, self).tearDown() - - def run_command(self, cmd): - orig = sys.stdout - try: - sys.stdout = six.StringIO() - if isinstance(cmd, list): - self.shell.main(cmd) - else: - self.shell.main(cmd.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(exc_value.code, 0) - finally: - out = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - return out - - def assert_called(self, method, path, base_url=TEST_URL): - self.assertEqual(method, self.requests_mock.last_request.method) - self.assertEqual(base_url + path.lstrip('/'), - self.requests_mock.last_request.url) - - def test_user_list(self): - self.stub_url('GET', ['users'], json={'users': []}) - self.run_command('user-list') - self.assert_called('GET', '/users') - - def test_user_create(self): - self.stub_url('POST', ['users'], json={'user': {}}) - self.run_command('user-create --name new-user') - - self.assert_called('POST', '/users') - self.assertRequestBodyIs(json={'user': {'email': None, - 'password': None, - 'enabled': True, - 'name': 'new-user', - 'tenantId': None}}) - - @mock.patch('sys.stdin', autospec=True) - def test_user_create_password_prompt(self, mock_stdin): - self.stub_url('POST', ['users'], json={'user': {}}) - - with mock.patch('getpass.getpass') as mock_getpass: - del(os.environ['OS_PASSWORD']) - mock_stdin.isatty = lambda: True - mock_getpass.return_value = 'newpass' - self.run_command('user-create --name new-user --pass') - - self.assert_called('POST', '/users') - self.assertRequestBodyIs(json={'user': {'email': None, - 'password': 'newpass', - 'enabled': True, - 'name': 'new-user', - 'tenantId': None}}) - - def test_user_get(self): - self.stub_url('GET', ['users', '1'], - json={'user': {'id': '1'}}) - self.run_command('user-get 1') - self.assert_called('GET', '/users/1') - - def test_user_delete(self): - self.stub_url('GET', ['users', '1'], - json={'user': {'id': '1'}}) - self.stub_url('DELETE', ['users', '1']) - self.run_command('user-delete 1') - self.assert_called('DELETE', '/users/1') - - def test_user_password_update(self): - self.stub_url('GET', ['users', '1'], - json={'user': {'id': '1'}}) - self.stub_url('PUT', ['users', '1', 'OS-KSADM', 'password']) - self.run_command('user-password-update --pass newpass 1') - self.assert_called('PUT', '/users/1/OS-KSADM/password') - - def test_user_update(self): - self.stub_url('PUT', ['users', '1']) - self.stub_url('GET', ['users', '1'], - json={"user": {"tenantId": "1", - "enabled": "true", - "id": "1", - "name": "username"}}) - - self.run_command('user-update --name new-user1' - ' --email user@email.com --enabled true 1') - self.assert_called('PUT', '/users/1') - body = {'user': {'id': '1', 'email': 'user@email.com', - 'enabled': True, 'name': 'new-user1'}} - self.assertRequestBodyIs(json=body) - - required = 'User not updated, no arguments present.' - out = self.run_command('user-update 1') - self.assertThat(out, matchers.MatchesRegex(required)) - - self.run_command(['user-update', '--email', '', '1']) - self.assert_called('PUT', '/users/1') - self.assertRequestBodyIs(json={'user': {'id': '1', 'email': ''}}) - - def test_role_create(self): - self.stub_url('POST', ['OS-KSADM', 'roles'], json={'role': {}}) - self.run_command('role-create --name new-role') - self.assert_called('POST', '/OS-KSADM/roles') - self.assertRequestBodyIs(json={"role": {"name": "new-role"}}) - - def test_role_get(self): - self.stub_url('GET', ['OS-KSADM', 'roles', '1'], - json={'role': {'id': '1'}}) - self.run_command('role-get 1') - self.assert_called('GET', '/OS-KSADM/roles/1') - - def test_role_list(self): - self.stub_url('GET', ['OS-KSADM', 'roles'], json={'roles': []}) - self.run_command('role-list') - self.assert_called('GET', '/OS-KSADM/roles') - - def test_role_delete(self): - self.stub_url('GET', ['OS-KSADM', 'roles', '1'], - json={'role': {'id': '1'}}) - self.stub_url('DELETE', ['OS-KSADM', 'roles', '1']) - self.run_command('role-delete 1') - self.assert_called('DELETE', '/OS-KSADM/roles/1') - - def test_user_role_add(self): - self.stub_url('GET', ['users', '1'], - json={'user': {'id': '1'}}) - self.stub_url('GET', ['OS-KSADM', 'roles', '1'], - json={'role': {'id': '1'}}) - - self.stub_url('PUT', ['users', '1', 'roles', 'OS-KSADM', '1']) - self.run_command('user-role-add --user_id 1 --role_id 1') - self.assert_called('PUT', '/users/1/roles/OS-KSADM/1') - - def test_user_role_list(self): - self.stub_url('GET', ['tenants', self.token.tenant_id], - json={'tenant': {'id': self.token.tenant_id}}) - self.stub_url('GET', ['tenants', self.token.tenant_id, - 'users', self.token.user_id, 'roles'], - json={'roles': []}) - - url = '/tenants/%s/users/%s/roles' % (self.token.tenant_id, - self.token.user_id) - - self.run_command('user-role-list --user_id %s --tenant-id %s' % - (self.token.user_id, self.token.tenant_id)) - self.assert_called('GET', url) - - self.run_command('user-role-list --user_id %s' % self.token.user_id) - self.assert_called('GET', url) - - self.run_command('user-role-list') - self.assert_called('GET', url) - - def test_user_role_remove(self): - self.stub_url('GET', ['users', '1'], - json={'user': {'id': 1}}) - self.stub_url('GET', ['OS-KSADM', 'roles', '1'], - json={'role': {'id': 1}}) - self.stub_url('DELETE', - ['users', '1', 'roles', 'OS-KSADM', '1']) - - self.run_command('user-role-remove --user_id 1 --role_id 1') - self.assert_called('DELETE', '/users/1/roles/OS-KSADM/1') - - def test_tenant_create(self): - self.stub_url('POST', ['tenants'], json={'tenant': {}}) - self.run_command('tenant-create --name new-tenant') - self.assertRequestBodyIs(json={"tenant": {"enabled": True, - "name": "new-tenant", - "description": None}}) - - def test_tenant_get(self): - self.stub_url('GET', ['tenants', '2'], json={'tenant': {}}) - self.run_command('tenant-get 2') - self.assert_called('GET', '/tenants/2') - - def test_tenant_list(self): - self.stub_url('GET', ['tenants'], json={'tenants': []}) - self.run_command('tenant-list') - self.assert_called('GET', '/tenants') - - def test_tenant_update(self): - self.stub_url('GET', ['tenants', '1'], - json={'tenant': {'id': '1'}}) - self.stub_url('GET', ['tenants', '2'], - json={'tenant': {'id': '2'}}) - self.stub_url('POST', ['tenants', '2'], - json={'tenant': {'id': '2'}}) - self.run_command('tenant-update' - ' --name new-tenant1 --enabled false' - ' --description desc 2') - self.assert_called('POST', '/tenants/2') - self.assertRequestBodyIs(json={"tenant": {"enabled": False, - "id": "2", - "description": "desc", - "name": "new-tenant1"}}) - - required = 'Tenant not updated, no arguments present.' - out = self.run_command('tenant-update 1') - self.assertThat(out, matchers.MatchesRegex(required)) - - def test_tenant_delete(self): - self.stub_url('GET', ['tenants', '2'], - json={'tenant': {'id': '2'}}) - self.stub_url('DELETE', ['tenants', '2']) - self.run_command('tenant-delete 2') - self.assert_called('DELETE', '/tenants/2') - - def test_service_create_with_required_arguments_only(self): - self.stub_url('POST', ['OS-KSADM', 'services'], - json={'OS-KSADM:service': {}}) - self.run_command('service-create --type compute') - self.assert_called('POST', '/OS-KSADM/services') - json = {"OS-KSADM:service": {"type": "compute", - "name": None, - "description": None}} - self.assertRequestBodyIs(json=json) - - def test_service_create_with_all_arguments(self): - self.stub_url('POST', ['OS-KSADM', 'services'], - json={'OS-KSADM:service': {}}) - self.run_command('service-create --type compute ' - '--name service1 --description desc1') - self.assert_called('POST', '/OS-KSADM/services') - json = {"OS-KSADM:service": {"type": "compute", - "name": "service1", - "description": "desc1"}} - self.assertRequestBodyIs(json=json) - - def test_service_get(self): - self.stub_url('GET', ['OS-KSADM', 'services', '1'], - json={'OS-KSADM:service': {'id': '1'}}) - self.run_command('service-get 1') - self.assert_called('GET', '/OS-KSADM/services/1') - - def test_service_list(self): - self.stub_url('GET', ['OS-KSADM', 'services'], - json={'OS-KSADM:services': []}) - self.run_command('service-list') - self.assert_called('GET', '/OS-KSADM/services') - - def test_service_delete(self): - self.stub_url('GET', ['OS-KSADM', 'services', '1'], - json={'OS-KSADM:service': {'id': 1}}) - self.stub_url('DELETE', ['OS-KSADM', 'services', '1']) - self.run_command('service-delete 1') - self.assert_called('DELETE', '/OS-KSADM/services/1') - - def test_catalog(self): - self.run_command('catalog') - self.run_command('catalog --service compute') - - def test_ec2_credentials_create(self): - self.stub_url('POST', - ['users', self.token.user_id, 'credentials', 'OS-EC2'], - json={'credential': {}}) - - url = '/users/%s/credentials/OS-EC2' % self.token.user_id - self.run_command('ec2-credentials-create --tenant-id 1 ' - '--user-id %s' % self.token.user_id) - self.assert_called('POST', url) - self.assertRequestBodyIs(json={'tenant_id': '1'}) - - self.run_command('ec2-credentials-create --tenant-id 1') - self.assert_called('POST', url) - self.assertRequestBodyIs(json={'tenant_id': '1'}) - - self.run_command('ec2-credentials-create') - self.assert_called('POST', url) - self.assertRequestBodyIs(json={'tenant_id': self.token.tenant_id}) - - def test_ec2_credentials_delete(self): - self.stub_url('DELETE', - ['users', self.token.user_id, - 'credentials', 'OS-EC2', '2']) - self.run_command('ec2-credentials-delete --access 2 --user-id %s' % - self.token.user_id) - - url = '/users/%s/credentials/OS-EC2/2' % self.token.user_id - self.assert_called('DELETE', url) - - self.run_command('ec2-credentials-delete --access 2') - self.assert_called('DELETE', url) - - def test_ec2_credentials_list(self): - self.stub_url('GET', - ['users', self.token.user_id, 'credentials', 'OS-EC2'], - json={'credentials': []}) - self.run_command('ec2-credentials-list --user-id %s' - % self.token.user_id) - - url = '/users/%s/credentials/OS-EC2' % self.token.user_id - self.assert_called('GET', url) - - self.run_command('ec2-credentials-list') - self.assert_called('GET', url) - - def test_ec2_credentials_get(self): - self.stub_url('GET', - ['users', '1', 'credentials', 'OS-EC2', '2'], - json={'credential': {}}) - self.run_command('ec2-credentials-get --access 2 --user-id 1') - self.assert_called('GET', '/users/1/credentials/OS-EC2/2') - - def test_bootstrap(self): - user = {'user': {'id': '1'}} - role = {'role': {'id': '1'}} - tenant = {'tenant': {'id': '1'}} - - token = fixture.V2Token(user_id=1, tenant_id=1) - token.add_role(id=1) - svc = token.add_service('identity') - svc.add_endpoint(public=DEFAULT_AUTH_URL, - admin=DEFAULT_ADMIN_URL) - - self.stub_auth(json=token) - - self.stub_url('POST', ['OS-KSADM', 'roles'], json=role) - self.stub_url('GET', ['OS-KSADM', 'roles', '1'], json=role) - self.stub_url('POST', ['tenants'], json=tenant) - self.stub_url('GET', ['tenants', '1'], json=tenant) - self.stub_url('POST', ['users'], json=user) - self.stub_url('GET', ['users', '1'], json=user) - self.stub_url('PUT', - ['tenants', '1', 'users', '1', 'roles', 'OS-KSADM', '1'], - json=role) - - self.run_command('bootstrap --user-name new-user' - ' --pass 1 --role-name admin' - ' --tenant-name new-tenant') - - def called_anytime(method, path, json=None): - test_url = self.TEST_URL.strip('/') - for r in self.requests_mock.request_history: - if not r.method == method: - continue - if not r.url == test_url + path: - continue - - if json: - json_body = jsonutils.loads(r.body) - if not json_body == json: - continue - - return True - - raise AssertionError('URL never called') - - called_anytime('POST', '/users', {'user': {'email': None, - 'password': '1', - 'enabled': True, - 'name': 'new-user', - 'tenantId': None}}) - - called_anytime('POST', '/tenants', {"tenant": {"enabled": True, - "name": "new-tenant", - "description": None}}) - - called_anytime('POST', '/OS-KSADM/roles', - {"role": {"name": "admin"}}) - - called_anytime('PUT', '/tenants/1/users/1/roles/OS-KSADM/1') - - def test_bash_completion(self): - self.run_command('bash-completion') - - def test_help(self): - out = self.run_command('help') - required = 'usage: keystone' - self.assertThat(out, matchers.MatchesRegex(required)) - - def test_password_update(self): - self.stub_url('PATCH', - ['OS-KSCRUD', 'users', self.token.user_id], - base_url=DEFAULT_AUTH_URL) - self.run_command('password-update --current-password oldpass' - ' --new-password newpass') - self.assert_called('PATCH', - '/OS-KSCRUD/users/%s' % self.token.user_id, - base_url=DEFAULT_AUTH_URL) - self.assertRequestBodyIs(json={'user': {'original_password': 'oldpass', - 'password': 'newpass'}}) - - def test_endpoint_create(self): - self.stub_url('GET', ['OS-KSADM', 'services', '1'], - json={'OS-KSADM:service': {'id': '1'}}) - self.stub_url('POST', ['endpoints'], json={'endpoint': {}}) - self.run_command('endpoint-create --service-id 1 ' - '--publicurl=http://example.com:1234/go') - self.assert_called('POST', '/endpoints') - json = {'endpoint': {'adminurl': None, - 'service_id': '1', - 'region': 'regionOne', - 'internalurl': None, - 'publicurl': "http://example.com:1234/go"}} - self.assertRequestBodyIs(json=json) - - def test_endpoint_list(self): - self.stub_url('GET', ['endpoints'], json={'endpoints': []}) - self.run_command('endpoint-list') - self.assert_called('GET', '/endpoints') diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_tenants.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_tenants.py deleted file mode 100644 index 62ca398991..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_tenants.py +++ /dev/null @@ -1,363 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import client -from keystoneclient.v2_0 import tenants -from keystoneclient.v2_0 import users - - -class TenantTests(utils.TestCase): - def setUp(self): - super(TenantTests, self).setUp() - - self.INVIS_ID = uuid.uuid4().hex - self.DEMO_ID = uuid.uuid4().hex - self.ADMIN_ID = uuid.uuid4().hex - self.EXTRAS_ID = uuid.uuid4().hex - - self.TEST_TENANTS = { - "tenants": { - "values": [ - { - "enabled": True, - "description": "A description change!", - "name": "invisible_to_admin", - "id": self.INVIS_ID, - }, - { - "enabled": True, - "description": "None", - "name": "demo", - "id": self.DEMO_ID, - }, - { - "enabled": True, - "description": "None", - "name": "admin", - "id": self.ADMIN_ID, - }, - { - "extravalue01": "metadata01", - "enabled": True, - "description": "For testing extras", - "name": "test_extras", - "id": self.EXTRAS_ID, - } - ], - "links": [], - }, - } - - def test_create(self): - req_body = { - "tenant": { - "name": "tenantX", - "description": "Like tenant 9, but better.", - "enabled": True, - "extravalue01": "metadata01", - }, - } - id_ = uuid.uuid4().hex - resp_body = { - "tenant": { - "name": "tenantX", - "enabled": True, - "id": id_, - "description": "Like tenant 9, but better.", - "extravalue01": "metadata01", - } - } - self.stub_url('POST', ['tenants'], json=resp_body) - - tenant = self.client.tenants.create( - req_body['tenant']['name'], - req_body['tenant']['description'], - req_body['tenant']['enabled'], - extravalue01=req_body['tenant']['extravalue01'], - name="don't overwrite priors") - self.assertIsInstance(tenant, tenants.Tenant) - self.assertEqual(tenant.id, id_) - self.assertEqual(tenant.name, "tenantX") - self.assertEqual(tenant.description, "Like tenant 9, but better.") - self.assertEqual(tenant.extravalue01, "metadata01") - self.assertRequestBodyIs(json=req_body) - - def test_duplicate_create(self): - req_body = { - "tenant": { - "name": "tenantX", - "description": "The duplicate tenant.", - "enabled": True - }, - } - resp_body = { - "error": { - "message": "Conflict occurred attempting to store project.", - "code": 409, - "title": "Conflict", - } - } - self.stub_url('POST', ['tenants'], status_code=409, json=resp_body) - - def create_duplicate_tenant(): - self.client.tenants.create(req_body['tenant']['name'], - req_body['tenant']['description'], - req_body['tenant']['enabled']) - - self.assertRaises(exceptions.Conflict, create_duplicate_tenant) - - def test_delete(self): - self.stub_url('DELETE', ['tenants', self.ADMIN_ID], status_code=204) - self.client.tenants.delete(self.ADMIN_ID) - - def test_get(self): - resp = {'tenant': self.TEST_TENANTS['tenants']['values'][2]} - self.stub_url('GET', ['tenants', self.ADMIN_ID], json=resp) - - t = self.client.tenants.get(self.ADMIN_ID) - self.assertIsInstance(t, tenants.Tenant) - self.assertEqual(t.id, self.ADMIN_ID) - self.assertEqual(t.name, 'admin') - - def test_list(self): - self.stub_url('GET', ['tenants'], json=self.TEST_TENANTS) - - tenant_list = self.client.tenants.list() - [self.assertIsInstance(t, tenants.Tenant) for t in tenant_list] - - def test_list_limit(self): - self.stub_url('GET', ['tenants'], json=self.TEST_TENANTS) - - tenant_list = self.client.tenants.list(limit=1) - self.assertQueryStringIs('limit=1') - [self.assertIsInstance(t, tenants.Tenant) for t in tenant_list] - - def test_list_marker(self): - self.stub_url('GET', ['tenants'], json=self.TEST_TENANTS) - - tenant_list = self.client.tenants.list(marker=1) - self.assertQueryStringIs('marker=1') - [self.assertIsInstance(t, tenants.Tenant) for t in tenant_list] - - def test_list_limit_marker(self): - self.stub_url('GET', ['tenants'], json=self.TEST_TENANTS) - - tenant_list = self.client.tenants.list(limit=1, marker=1) - self.assertQueryStringIs('marker=1&limit=1') - [self.assertIsInstance(t, tenants.Tenant) for t in tenant_list] - - def test_update(self): - req_body = { - "tenant": { - "id": self.EXTRAS_ID, - "name": "tenantX", - "description": "I changed you!", - "enabled": False, - "extravalue01": "metadataChanged", - # "extraname": "dontoverwrite!", - }, - } - resp_body = { - "tenant": { - "name": "tenantX", - "enabled": False, - "id": self.EXTRAS_ID, - "description": "I changed you!", - "extravalue01": "metadataChanged", - }, - } - - self.stub_url('POST', ['tenants', self.EXTRAS_ID], json=resp_body) - - tenant = self.client.tenants.update( - req_body['tenant']['id'], - req_body['tenant']['name'], - req_body['tenant']['description'], - req_body['tenant']['enabled'], - extravalue01=req_body['tenant']['extravalue01'], - name="don't overwrite priors") - self.assertIsInstance(tenant, tenants.Tenant) - self.assertRequestBodyIs(json=req_body) - self.assertEqual(tenant.id, self.EXTRAS_ID) - self.assertEqual(tenant.name, "tenantX") - self.assertEqual(tenant.description, "I changed you!") - self.assertFalse(tenant.enabled) - self.assertEqual(tenant.extravalue01, "metadataChanged") - - def test_update_empty_description(self): - req_body = { - "tenant": { - "id": self.EXTRAS_ID, - "name": "tenantX", - "description": "", - "enabled": False, - }, - } - resp_body = { - "tenant": { - "name": "tenantX", - "enabled": False, - "id": self.EXTRAS_ID, - "description": "", - }, - } - self.stub_url('POST', ['tenants', self.EXTRAS_ID], json=resp_body) - - tenant = self.client.tenants.update(req_body['tenant']['id'], - req_body['tenant']['name'], - req_body['tenant']['description'], - req_body['tenant']['enabled']) - self.assertIsInstance(tenant, tenants.Tenant) - self.assertRequestBodyIs(json=req_body) - self.assertEqual(tenant.id, self.EXTRAS_ID) - self.assertEqual(tenant.name, "tenantX") - self.assertEqual(tenant.description, "") - self.assertFalse(tenant.enabled) - - def test_add_user(self): - self.stub_url('PUT', - ['tenants', self.EXTRAS_ID, 'users', 'foo', 'roles', - 'OS-KSADM', 'barrr'], - status_code=204) - - self.client.tenants.add_user(self.EXTRAS_ID, 'foo', 'barrr') - - def test_remove_user(self): - self.stub_url('DELETE', ['tenants', self.EXTRAS_ID, 'users', - 'foo', 'roles', 'OS-KSADM', 'barrr'], - status_code=204) - - self.client.tenants.remove_user(self.EXTRAS_ID, 'foo', 'barrr') - - def test_tenant_add_user(self): - self.stub_url('PUT', ['tenants', self.EXTRAS_ID, 'users', - 'foo', 'roles', 'OS-KSADM', 'barrr'], - status_code=204) - - req_body = { - "tenant": { - "id": self.EXTRAS_ID, - "name": "tenantX", - "description": "I changed you!", - "enabled": False, - }, - } - # make tenant object with manager - tenant = self.client.tenants.resource_class(self.client.tenants, - req_body['tenant']) - tenant.add_user('foo', 'barrr') - self.assertIsInstance(tenant, tenants.Tenant) - - def test_tenant_remove_user(self): - self.stub_url('DELETE', ['tenants', self.EXTRAS_ID, 'users', - 'foo', 'roles', 'OS-KSADM', 'barrr'], - status_code=204) - - req_body = { - "tenant": { - "id": self.EXTRAS_ID, - "name": "tenantX", - "description": "I changed you!", - "enabled": False, - }, - } - - # make tenant object with manager - tenant = self.client.tenants.resource_class(self.client.tenants, - req_body['tenant']) - tenant.remove_user('foo', 'barrr') - self.assertIsInstance(tenant, tenants.Tenant) - - def test_tenant_list_users(self): - tenant_id = uuid.uuid4().hex - user_id1 = uuid.uuid4().hex - user_id2 = uuid.uuid4().hex - - tenant_resp = { - 'tenant': { - 'name': uuid.uuid4().hex, - 'enabled': True, - 'id': tenant_id, - 'description': 'test tenant', - } - } - - users_resp = { - 'users': { - 'values': [ - { - 'email': uuid.uuid4().hex, - 'enabled': True, - 'id': user_id1, - 'name': uuid.uuid4().hex, - }, - { - 'email': uuid.uuid4().hex, - 'enabled': True, - 'id': user_id2, - 'name': uuid.uuid4().hex, - }, - ] - } - } - - self.stub_url('GET', ['tenants', tenant_id], json=tenant_resp) - self.stub_url('GET', - ['tenants', tenant_id, 'users'], - json=users_resp) - - tenant = self.client.tenants.get(tenant_id) - user_objs = tenant.list_users() - - for u in user_objs: - self.assertIsInstance(u, users.User) - - self.assertEqual(set([user_id1, user_id2]), - set([u.id for u in user_objs])) - - def test_list_tenants_use_admin_url(self): - self.stub_url('GET', ['tenants'], json=self.TEST_TENANTS) - - self.assertEqual(self.TEST_URL, self.client.management_url) - - tenant_list = self.client.tenants.list() - [self.assertIsInstance(t, tenants.Tenant) for t in tenant_list] - - self.assertEqual(len(self.TEST_TENANTS['tenants']['values']), - len(tenant_list)) - - def test_list_tenants_fallback_to_auth_url(self): - new_auth_url = 'http://keystone.test:5000/v2.0' - - token = fixture.V2Token(token_id=self.TEST_TOKEN, - user_name=self.TEST_USER, - user_id=self.TEST_USER_ID) - - self.stub_auth(base_url=new_auth_url, json=token) - self.stub_url('GET', ['tenants'], base_url=new_auth_url, - json=self.TEST_TENANTS) - - c = client.Client(username=self.TEST_USER, - auth_url=new_auth_url, - password=uuid.uuid4().hex) - - self.assertIsNone(c.management_url) - tenant_list = c.tenants.list() - [self.assertIsInstance(t, tenants.Tenant) for t in tenant_list] - - self.assertEqual(len(self.TEST_TENANTS['tenants']['values']), - len(tenant_list)) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_tokens.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_tokens.py deleted file mode 100644 index 8a40f82953..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_tokens.py +++ /dev/null @@ -1,208 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import access -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import client -from keystoneclient.v2_0 import tokens - - -class TokenTests(utils.TestCase): - - def test_delete(self): - id_ = uuid.uuid4().hex - self.stub_url('DELETE', ['tokens', id_], status_code=204) - self.client.tokens.delete(id_) - - def test_user_password(self): - token_fixture = fixture.V2Token(user_name=self.TEST_USER) - self.stub_auth(json=token_fixture) - - password = uuid.uuid4().hex - token_ref = self.client.tokens.authenticate(username=self.TEST_USER, - password=password) - - self.assertIsInstance(token_ref, tokens.Token) - self.assertEqual(token_fixture.token_id, token_ref.id) - self.assertEqual(token_fixture.expires_str, token_ref.expires) - - req_body = { - 'auth': { - 'passwordCredentials': { - 'username': self.TEST_USER, - 'password': password, - } - } - } - - self.assertRequestBodyIs(json=req_body) - - def test_with_token_id(self): - token_fixture = fixture.V2Token() - self.stub_auth(json=token_fixture) - - token_id = uuid.uuid4().hex - token_ref = self.client.tokens.authenticate(token=token_id) - - self.assertIsInstance(token_ref, tokens.Token) - self.assertEqual(token_fixture.token_id, token_ref.id) - self.assertEqual(token_fixture.expires_str, token_ref.expires) - - req_body = { - 'auth': { - 'token': { - 'id': token_id, - } - } - } - - self.assertRequestBodyIs(json=req_body) - - def test_without_auth_params(self): - self.assertRaises(ValueError, self.client.tokens.authenticate) - self.assertRaises(ValueError, self.client.tokens.authenticate, - tenant_id=uuid.uuid4().hex) - - def test_with_tenant_id(self): - token_fixture = fixture.V2Token() - token_fixture.set_scope() - self.stub_auth(json=token_fixture) - - token_id = uuid.uuid4().hex - tenant_id = uuid.uuid4().hex - token_ref = self.client.tokens.authenticate(token=token_id, - tenant_id=tenant_id) - - self.assertIsInstance(token_ref, tokens.Token) - self.assertEqual(token_fixture.token_id, token_ref.id) - self.assertEqual(token_fixture.expires_str, token_ref.expires) - - tenant_data = {'id': token_fixture.tenant_id, - 'name': token_fixture.tenant_name} - self.assertEqual(tenant_data, token_ref.tenant) - - req_body = { - 'auth': { - 'token': { - 'id': token_id, - }, - 'tenantId': tenant_id - } - } - - self.assertRequestBodyIs(json=req_body) - - def test_with_tenant_name(self): - token_fixture = fixture.V2Token() - token_fixture.set_scope() - self.stub_auth(json=token_fixture) - - token_id = uuid.uuid4().hex - tenant_name = uuid.uuid4().hex - token_ref = self.client.tokens.authenticate(token=token_id, - tenant_name=tenant_name) - - self.assertIsInstance(token_ref, tokens.Token) - self.assertEqual(token_fixture.token_id, token_ref.id) - self.assertEqual(token_fixture.expires_str, token_ref.expires) - - tenant_data = {'id': token_fixture.tenant_id, - 'name': token_fixture.tenant_name} - self.assertEqual(tenant_data, token_ref.tenant) - - req_body = { - 'auth': { - 'token': { - 'id': token_id, - }, - 'tenantName': tenant_name - } - } - - self.assertRequestBodyIs(json=req_body) - - def test_authenticate_use_admin_url(self): - token_fixture = fixture.V2Token() - token_fixture.set_scope() - self.stub_auth(json=token_fixture) - - self.assertEqual(self.TEST_URL, self.client.management_url) - - token_ref = self.client.tokens.authenticate(token=uuid.uuid4().hex) - self.assertIsInstance(token_ref, tokens.Token) - self.assertEqual(token_fixture.token_id, token_ref.id) - self.assertEqual(token_fixture.expires_str, token_ref.expires) - - def test_authenticate_fallback_to_auth_url(self): - new_auth_url = 'http://keystone.test:5000/v2.0' - - token_fixture = fixture.V2Token() - self.stub_auth(base_url=new_auth_url, json=token_fixture) - - c = client.Client(username=self.TEST_USER, - auth_url=new_auth_url, - password=uuid.uuid4().hex) - - self.assertIsNone(c.management_url) - - token_ref = c.tokens.authenticate(token=uuid.uuid4().hex) - self.assertIsInstance(token_ref, tokens.Token) - self.assertEqual(token_fixture.token_id, token_ref.id) - self.assertEqual(token_fixture.expires_str, token_ref.expires) - - def test_validate_token(self): - id_ = uuid.uuid4().hex - token_fixture = fixture.V2Token(token_id=id_) - self.stub_url('GET', ['tokens', id_], json=token_fixture) - - token_ref = self.client.tokens.validate(id_) - self.assertIsInstance(token_ref, tokens.Token) - self.assertEqual(id_, token_ref.id) - - def test_validate_token_invalid_token(self): - # If the token is invalid, typically a NotFound is raised. - - id_ = uuid.uuid4().hex - # The server is expected to return 404 if the token is invalid. - self.stub_url('GET', ['tokens', id_], status_code=404) - self.assertRaises(exceptions.NotFound, - self.client.tokens.validate, id_) - - def test_validate_token_access_info_with_token_id(self): - # Can validate a token passing a string token ID. - token_id = uuid.uuid4().hex - token_fixture = fixture.V2Token(token_id=token_id) - self.stub_url('GET', ['tokens', token_id], json=token_fixture) - access_info = self.client.tokens.validate_access_info(token_id) - self.assertIsInstance(access_info, access.AccessInfoV2) - self.assertEqual(token_id, access_info.auth_token) - - def test_validate_token_access_info_with_access_info(self): - # Can validate a token passing an access info. - token_id = uuid.uuid4().hex - token_fixture = fixture.V2Token(token_id=token_id) - self.stub_url('GET', ['tokens', token_id], json=token_fixture) - token = access.AccessInfo.factory(body=token_fixture) - access_info = self.client.tokens.validate_access_info(token) - self.assertIsInstance(access_info, access.AccessInfoV2) - self.assertEqual(token_id, access_info.auth_token) - - def test_get_revoked(self): - sample_revoked_response = {'signed': '-----BEGIN CMS-----\nMIIB...'} - self.stub_url('GET', ['tokens', 'revoked'], - json=sample_revoked_response) - resp = self.client.tokens.get_revoked() - self.assertEqual(sample_revoked_response, resp) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_users.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_users.py deleted file mode 100644 index 455ca3cf55..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/test_users.py +++ /dev/null @@ -1,305 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v2_0 import utils -from keystoneclient.v2_0 import roles -from keystoneclient.v2_0 import users - - -class UserTests(utils.TestCase): - def setUp(self): - super(UserTests, self).setUp() - self.ADMIN_USER_ID = uuid.uuid4().hex - self.DEMO_USER_ID = uuid.uuid4().hex - self.TEST_USERS = { - "users": { - "values": [ - { - "email": "None", - "enabled": True, - "id": self.ADMIN_USER_ID, - "name": "admin", - }, - { - "email": "None", - "enabled": True, - "id": self.DEMO_USER_ID, - "name": "demo", - }, - ] - } - } - - def test_create(self): - tenant_id = uuid.uuid4().hex - user_id = uuid.uuid4().hex - password = uuid.uuid4().hex - req_body = { - "user": { - "name": "gabriel", - "password": password, - "tenantId": tenant_id, - "email": "test@example.com", - "enabled": True, - } - } - - resp_body = { - "user": { - "name": "gabriel", - "enabled": True, - "tenantId": tenant_id, - "id": user_id, - "password": password, - "email": "test@example.com", - } - } - - self.stub_url('POST', ['users'], json=resp_body) - - user = self.client.users.create(req_body['user']['name'], - req_body['user']['password'], - req_body['user']['email'], - tenant_id=req_body['user']['tenantId'], - enabled=req_body['user']['enabled']) - self.assertIsInstance(user, users.User) - self.assertEqual(user.id, user_id) - self.assertEqual(user.name, "gabriel") - self.assertEqual(user.email, "test@example.com") - self.assertRequestBodyIs(json=req_body) - self.assertNotIn(password, self.logger.output) - - def test_create_user_without_email(self): - tenant_id = uuid.uuid4().hex - req_body = { - "user": { - "name": "gabriel", - "password": "test", - "tenantId": tenant_id, - "enabled": True, - "email": None, - } - } - - user_id = uuid.uuid4().hex - resp_body = { - "user": { - "name": "gabriel", - "enabled": True, - "tenantId": tenant_id, - "id": user_id, - "password": "test", - } - } - - self.stub_url('POST', ['users'], json=resp_body) - - user = self.client.users.create( - req_body['user']['name'], - req_body['user']['password'], - tenant_id=req_body['user']['tenantId'], - enabled=req_body['user']['enabled']) - self.assertIsInstance(user, users.User) - self.assertEqual(user.id, user_id) - self.assertEqual(user.name, "gabriel") - self.assertRequestBodyIs(json=req_body) - - def test_create_user_without_password(self): - user_name = 'test' - user_id = uuid.uuid4().hex - tenant_id = uuid.uuid4().hex - user_enabled = True - req_body = { - 'user': { - 'name': user_name, - 'password': None, - 'tenantId': tenant_id, - 'enabled': user_enabled, - 'email': None, - } - } - resp_body = { - 'user': { - 'name': user_name, - 'enabled': user_enabled, - 'tenantId': tenant_id, - 'id': user_id, - } - } - - self.stub_url('POST', ['users'], json=resp_body) - - user = self.client.users.create(user_name, tenant_id=tenant_id, - enabled=user_enabled) - self.assertIsInstance(user, users.User) - self.assertEqual(user_id, user.id) - self.assertEqual(user_name, user.name) - self.assertRequestBodyIs(json=req_body) - - def test_delete(self): - self.stub_url('DELETE', ['users', self.ADMIN_USER_ID], status_code=204) - self.client.users.delete(self.ADMIN_USER_ID) - - def test_get(self): - self.stub_url('GET', ['users', self.ADMIN_USER_ID], - json={'user': self.TEST_USERS['users']['values'][0]}) - - u = self.client.users.get(self.ADMIN_USER_ID) - self.assertIsInstance(u, users.User) - self.assertEqual(u.id, self.ADMIN_USER_ID) - self.assertEqual(u.name, 'admin') - - def test_list(self): - self.stub_url('GET', ['users'], json=self.TEST_USERS) - - user_list = self.client.users.list() - [self.assertIsInstance(u, users.User) for u in user_list] - - def test_list_limit(self): - self.stub_url('GET', ['users'], json=self.TEST_USERS) - - user_list = self.client.users.list(limit=1) - self.assertQueryStringIs('limit=1') - [self.assertIsInstance(u, users.User) for u in user_list] - - def test_list_marker(self): - self.stub_url('GET', ['users'], json=self.TEST_USERS) - - user_list = self.client.users.list(marker='foo') - self.assertQueryStringIs('marker=foo') - [self.assertIsInstance(u, users.User) for u in user_list] - - def test_list_limit_marker(self): - self.stub_url('GET', ['users'], json=self.TEST_USERS) - - user_list = self.client.users.list(limit=1, marker='foo') - - self.assertQueryStringIs('marker=foo&limit=1') - [self.assertIsInstance(u, users.User) for u in user_list] - - def test_update(self): - req_1 = { - "user": { - "id": self.DEMO_USER_ID, - "email": "gabriel@example.com", - "name": "gabriel", - } - } - password = uuid.uuid4().hex - req_2 = { - "user": { - "id": self.DEMO_USER_ID, - "password": password, - } - } - tenant_id = uuid.uuid4().hex - req_3 = { - "user": { - "id": self.DEMO_USER_ID, - "tenantId": tenant_id, - } - } - req_4 = { - "user": { - "id": self.DEMO_USER_ID, - "enabled": False, - } - } - - self.stub_url('PUT', ['users', self.DEMO_USER_ID], json=req_1) - self.stub_url('PUT', - ['users', self.DEMO_USER_ID, 'OS-KSADM', 'password'], - json=req_2) - self.stub_url('PUT', - ['users', self.DEMO_USER_ID, 'OS-KSADM', 'tenant'], - json=req_3) - self.stub_url('PUT', - ['users', self.DEMO_USER_ID, 'OS-KSADM', 'enabled'], - json=req_4) - - self.client.users.update(self.DEMO_USER_ID, - name='gabriel', - email='gabriel@example.com') - self.assertRequestBodyIs(json=req_1) - self.client.users.update_password(self.DEMO_USER_ID, password) - self.assertRequestBodyIs(json=req_2) - self.client.users.update_tenant(self.DEMO_USER_ID, tenant_id) - self.assertRequestBodyIs(json=req_3) - self.client.users.update_enabled(self.DEMO_USER_ID, False) - self.assertRequestBodyIs(json=req_4) - self.assertNotIn(password, self.logger.output) - - def test_update_own_password(self): - old_password = uuid.uuid4().hex - new_password = uuid.uuid4().hex - req_body = { - 'user': { - 'password': new_password, - 'original_password': old_password - } - } - resp_body = { - 'access': {} - } - user_id = uuid.uuid4().hex - self.stub_url('PATCH', ['OS-KSCRUD', 'users', user_id], json=resp_body) - - self.client.user_id = user_id - self.client.users.update_own_password(old_password, new_password) - self.assertRequestBodyIs(json=req_body) - self.assertNotIn(old_password, self.logger.output) - self.assertNotIn(new_password, self.logger.output) - - def test_user_role_listing(self): - user_id = uuid.uuid4().hex - role_id1 = uuid.uuid4().hex - role_id2 = uuid.uuid4().hex - tenant_id = uuid.uuid4().hex - - user_resp = { - 'user': { - 'id': user_id, - 'email': uuid.uuid4().hex, - 'name': uuid.uuid4().hex, - } - } - - roles_resp = { - 'roles': { - 'values': [ - { - 'name': uuid.uuid4().hex, - 'id': role_id1, - }, - { - 'name': uuid.uuid4().hex, - 'id': role_id2, - } - ] - } - } - - self.stub_url('GET', ['users', user_id], json=user_resp) - self.stub_url('GET', - ['tenants', tenant_id, 'users', user_id, 'roles'], - json=roles_resp) - - user = self.client.users.get(user_id) - role_objs = user.list_roles(tenant_id) - - for r in role_objs: - self.assertIsInstance(r, roles.Role) - - self.assertEqual(set([role_id1, role_id2]), - set([r.id for r in role_objs])) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/utils.py b/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/utils.py deleted file mode 100644 index 475181f6f9..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v2_0/utils.py +++ /dev/null @@ -1,88 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.tests.unit import utils -from keystoneclient.v2_0 import client - -TestResponse = utils.TestResponse - - -class UnauthenticatedTestCase(utils.TestCase): - """Class used as base for unauthenticated calls.""" - - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0') - TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' - TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v2.0') - - -class TestCase(UnauthenticatedTestCase): - - TEST_ADMIN_IDENTITY_ENDPOINT = "http://127.0.0.1:35357/v2.0" - - TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "adminURL": "http://cdn.admin-nets.local:8774/v1.0", - "region": "RegionOne", - "internalURL": "http://127.0.0.1:8774/v1.0", - "publicURL": "http://cdn.admin-nets.local:8774/v1.0/" - }], - "type": "nova_compat", - "name": "nova_compat" - }, { - "endpoints": [{ - "adminURL": "http://nova/novapi/admin", - "region": "RegionOne", - "internalURL": "http://nova/novapi/internal", - "publicURL": "http://nova/novapi/public" - }], - "type": "compute", - "name": "nova" - }, { - "endpoints": [{ - "adminURL": "http://glance/glanceapi/admin", - "region": "RegionOne", - "internalURL": "http://glance/glanceapi/internal", - "publicURL": "http://glance/glanceapi/public" - }], - "type": "image", - "name": "glance" - }, { - "endpoints": [{ - "adminURL": TEST_ADMIN_IDENTITY_ENDPOINT, - "region": "RegionOne", - "internalURL": "http://127.0.0.1:5000/v2.0", - "publicURL": "http://127.0.0.1:5000/v2.0" - }], - "type": "identity", - "name": "keystone" - }, { - "endpoints": [{ - "adminURL": "http://swift/swiftapi/admin", - "region": "RegionOne", - "internalURL": "http://swift/swiftapi/internal", - "publicURL": "http://swift/swiftapi/public" - }], - "type": "object-store", - "name": "swift" - }] - - def setUp(self): - super(TestCase, self).setUp() - self.client = client.Client(username=self.TEST_USER, - token=self.TEST_TOKEN, - tenant_name=self.TEST_TENANT_NAME, - auth_url=self.TEST_URL, - endpoint=self.TEST_URL) - - def stub_auth(self, **kwargs): - self.stub_url('POST', ['tokens'], **kwargs) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/__init__.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/client_fixtures.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/client_fixtures.py deleted file mode 100644 index 517f9ae071..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/client_fixtures.py +++ /dev/null @@ -1,182 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import unicode_literals - -from keystoneclient import fixture - - -def unscoped_token(): - return fixture.V3Token(user_id='c4da488862bd435c9e6c0275a0d0e49a', - user_name='exampleuser', - user_domain_id='4e6893b7ba0b4006840c3845660b86ed', - user_domain_name='exampledomain', - expires='2010-11-01T03:32:15-05:00') - - -def domain_scoped_token(): - f = fixture.V3Token(user_id='c4da488862bd435c9e6c0275a0d0e49a', - user_name='exampleuser', - user_domain_id='4e6893b7ba0b4006840c3845660b86ed', - user_domain_name='exampledomain', - expires='2010-11-01T03:32:15-05:00', - domain_id='8e9283b7ba0b1038840c3842058b86ab', - domain_name='anotherdomain') - - f.add_role(id='76e72a', name='admin') - f.add_role(id='f4f392', name='member') - region = 'RegionOne' - - s = f.add_service('volume') - s.add_standard_endpoints(public='http://public.com:8776/v1/None', - internal='http://internal.com:8776/v1/None', - admin='http://admin.com:8776/v1/None', - region=region) - - s = f.add_service('image') - s.add_standard_endpoints(public='http://public.com:9292/v1', - internal='http://internal:9292/v1', - admin='http://admin:9292/v1', - region=region) - - s = f.add_service('compute') - s.add_standard_endpoints(public='http://public.com:8774/v1.1/None', - internal='http://internal:8774/v1.1/None', - admin='http://admin:8774/v1.1/None', - region=region) - - s = f.add_service('ec2') - s.add_standard_endpoints(public='http://public.com:8773/services/Cloud', - internal='http://internal:8773/services/Cloud', - admin='http://admin:8773/services/Admin', - region=region) - - s = f.add_service('identity') - s.add_standard_endpoints(public='http://public.com:5000/v3', - internal='http://internal:5000/v3', - admin='http://admin:35357/v3', - region=region) - - return f - - -def project_scoped_token(): - f = fixture.V3Token(user_id='c4da488862bd435c9e6c0275a0d0e49a', - user_name='exampleuser', - user_domain_id='4e6893b7ba0b4006840c3845660b86ed', - user_domain_name='exampledomain', - expires='2010-11-01T03:32:15-05:00', - project_id='225da22d3ce34b15877ea70b2a575f58', - project_name='exampleproject', - project_domain_id='4e6893b7ba0b4006840c3845660b86ed', - project_domain_name='exampledomain') - - f.add_role(id='76e72a', name='admin') - f.add_role(id='f4f392', name='member') - - region = 'RegionOne' - tenant = '225da22d3ce34b15877ea70b2a575f58' - - s = f.add_service('volume') - s.add_standard_endpoints(public='http://public.com:8776/v1/%s' % tenant, - internal='http://internal:8776/v1/%s' % tenant, - admin='http://admin:8776/v1/%s' % tenant, - region=region) - - s = f.add_service('image') - s.add_standard_endpoints(public='http://public.com:9292/v1', - internal='http://internal:9292/v1', - admin='http://admin:9292/v1', - region=region) - - s = f.add_service('compute') - s.add_standard_endpoints(public='http://public.com:8774/v2/%s' % tenant, - internal='http://internal:8774/v2/%s' % tenant, - admin='http://admin:8774/v2/%s' % tenant, - region=region) - - s = f.add_service('ec2') - s.add_standard_endpoints(public='http://public.com:8773/services/Cloud', - internal='http://internal:8773/services/Cloud', - admin='http://admin:8773/services/Admin', - region=region) - - s = f.add_service('identity') - s.add_standard_endpoints(public='http://public.com:5000/v3', - internal='http://internal:5000/v3', - admin='http://admin:35357/v3', - region=region) - - return f - - -AUTH_SUBJECT_TOKEN = '3e2813b7ba0b4006840c3825860b86ed' - -AUTH_RESPONSE_HEADERS = { - 'X-Subject-Token': AUTH_SUBJECT_TOKEN, -} - - -def auth_response_body(): - f = fixture.V3Token(user_id='567', - user_name='test', - user_domain_id='1', - user_domain_name='aDomain', - expires='2010-11-01T03:32:15-05:00', - project_domain_id='123', - project_domain_name='aDomain', - project_id='345', - project_name='aTenant') - - f.add_role(id='76e72a', name='admin') - f.add_role(id='f4f392', name='member') - - s = f.add_service('compute', name='nova') - s.add_standard_endpoints( - public='https://compute.north.host/novapi/public', - internal='https://compute.north.host/novapi/internal', - admin='https://compute.north.host/novapi/admin', - region='North') - - s = f.add_service('object-store', name='swift') - s.add_standard_endpoints( - public='http://swift.north.host/swiftapi/public', - internal='http://swift.north.host/swiftapi/internal', - admin='http://swift.north.host/swiftapi/admin', - region='South') - - s = f.add_service('image', name='glance') - s.add_standard_endpoints( - public='http://glance.north.host/glanceapi/public', - internal='http://glance.north.host/glanceapi/internal', - admin='http://glance.north.host/glanceapi/admin', - region='North') - - s.add_standard_endpoints( - public='http://glance.south.host/glanceapi/public', - internal='http://glance.south.host/glanceapi/internal', - admin='http://glance.south.host/glanceapi/admin', - region='South') - - return f - - -def trust_token(): - return fixture.V3Token(user_id='0ca8f6', - user_name='exampleuser', - user_domain_id='4e6893b7ba0b4006840c3845660b86ed', - user_domain_name='exampledomain', - expires='2010-11-01T03:32:15-05:00', - trust_id='fe0aef', - trust_impersonation=False, - trustee_user_id='0ca8f6', - trustor_user_id='bd263c') diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/examples/xml/ADFS_RequestSecurityTokenResponse.xml b/awx/lib/site-packages/keystoneclient/tests/unit/v3/examples/xml/ADFS_RequestSecurityTokenResponse.xml deleted file mode 100644 index 487bcac592..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/examples/xml/ADFS_RequestSecurityTokenResponse.xml +++ /dev/null @@ -1,132 +0,0 @@ -<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> - <s:Header> - <a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTRC/IssueFinal</a:Action> - <a:RelatesTo>urn:uuid:487c064b-b7c6-4654-b4d4-715f9961170e</a:RelatesTo> - <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> - <u:Timestamp u:Id="_0"> - <u:Created>2014-08-05T18:36:14.235Z</u:Created> - <u:Expires>2014-08-05T18:41:14.235Z</u:Expires> - </u:Timestamp> - </o:Security> - </s:Header> - <s:Body> - <trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512"> - <trust:RequestSecurityTokenResponse> - <trust:Lifetime> - <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-08-05T18:36:14.063Z</wsu:Created> - <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-08-05T19:36:14.063Z</wsu:Expires> - </trust:Lifetime> - <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> - <wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing"> - <wsa:Address>https://ltartari2.cern.ch:5000/Shibboleth.sso/ADFS</wsa:Address> - </wsa:EndpointReference> - </wsp:AppliesTo> - <trust:RequestedSecurityToken> - <saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="_c9e77bc4-a81b-4da7-88c2-72a6ba376d3f" Issuer="https://cern.ch/login" IssueInstant="2014-08-05T18:36:14.235Z" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"> - <saml:Conditions NotBefore="2014-08-05T18:36:14.063Z" NotOnOrAfter="2014-08-05T19:36:14.063Z"> - <saml:AudienceRestrictionCondition> - <saml:Audience>https://ltartari2.cern.ch:5000/Shibboleth.sso/ADFS</saml:Audience> - </saml:AudienceRestrictionCondition> - </saml:Conditions> - <saml:AttributeStatement> - <saml:Subject> - <saml:NameIdentifier Format="http://schemas.xmlsoap.org/claims/UPN">marek.denis@cern.ch</saml:NameIdentifier> - <saml:SubjectConfirmation> - <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod> - </saml:SubjectConfirmation> - </saml:Subject> - <saml:Attribute AttributeName="UPN" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>marek.denis@cern.ch</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="EmailAddress" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>marek.denis@cern.ch</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="CommonName" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>madenis</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="role" AttributeNamespace="http://schemas.microsoft.com/ws/2008/06/identity/claims"> - <saml:AttributeValue>CERN Users</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="Group" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>Domain Users</saml:AttributeValue> - <saml:AttributeValue>occupants-bldg-31</saml:AttributeValue> - <saml:AttributeValue>CERN-Direct-Employees</saml:AttributeValue> - <saml:AttributeValue>ca-dev-allowed</saml:AttributeValue> - <saml:AttributeValue>cernts-cerntstest-users</saml:AttributeValue> - <saml:AttributeValue>staf-fell-pjas-at-cern</saml:AttributeValue> - <saml:AttributeValue>ELG-CERN</saml:AttributeValue> - <saml:AttributeValue>student-club-new-members</saml:AttributeValue> - <saml:AttributeValue>pawel-dynamic-test-82</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="DisplayName" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>Marek Kamil Denis</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="MobileNumber" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>+5555555</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="Building" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>31S-013</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="Firstname" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>Marek Kamil</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="Lastname" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>Denis</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="IdentityClass" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>CERN Registered</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="Federation" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>CERN</saml:AttributeValue> - </saml:Attribute> - <saml:Attribute AttributeName="AuthLevel" AttributeNamespace="http://schemas.xmlsoap.org/claims"> - <saml:AttributeValue>Normal</saml:AttributeValue> - </saml:Attribute> - </saml:AttributeStatement> - <saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password" AuthenticationInstant="2014-08-05T18:36:14.032Z"> - <saml:Subject> - <saml:NameIdentifier Format="http://schemas.xmlsoap.org/claims/UPN">marek.denis@cern.ch</saml:NameIdentifier> - <saml:SubjectConfirmation> - <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod> - </saml:SubjectConfirmation> - </saml:Subject> - </saml:AuthenticationStatement> - <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> - <SignedInfo> - <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> - <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> - <Reference URI="#_c9e77bc4-a81b-4da7-88c2-72a6ba376d3f"> - <Transforms> - <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> - <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> - </Transforms> - <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> - <DigestValue>EaZ/2d0KAY5un9akV3++Npyk6hBc8JuTYs2S3lSxUeQ=</DigestValue> - </Reference> - </SignedInfo> - <SignatureValue>CxYiYvNsbedhHdmDbb9YQCBy6Ppus3bNJdw2g2HLq0VU2yRhv23mUW05I89Hs4yG4OcCo0uOZ3zaeNFbSNXMW+Mr996tAXtujKjgyrCXNJAToE+gwltvGxwY1EluSbe3IzoSM3Ao87mKhxGOSzlDhuN7dQ9Rv6l/J4gUjbOO5SIX4pdZ6mVF7cHEfe9x+H8Lg15YjnElQUEaPi+NSW5jYTdtIpsB4ORxJvALuSt6+4doDYc9wuwBiWkEdnBHAQBINoKpAV2oy0/C85SBX3IdRhxUznmL5yEUmf8JvPccXecMPqJow0L43mnCdu74xPwU0as3MNfYQ10kLvHXHfIExg==</SignatureValue> - <KeyInfo> - <X509Data> - <X509Certificate>MIIIEjCCBfqgAwIBAgIKLYgjvQAAAAAAMDANBgkqhkiG9w0BAQsFADBRMRIwEAYKCZImiZPyLGQBGRYCY2gxFDASBgoJkiaJk/IsZAEZFgRjZXJuMSUwIwYDVQQDExxDRVJOIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMTEwODA4Mzg1NVoXDTIzMDcyOTA5MTkzOFowVjESMBAGCgmSJomT8ixkARkWAmNoMRQwEgYKCZImiZPyLGQBGRYEY2VybjESMBAGA1UECxMJY29tcHV0ZXJzMRYwFAYDVQQDEw1sb2dpbi5jZXJuLmNoMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp6t1C0SGlLddL2M+ltffGioTnDT3eztOxlA9bAGuvB8/Rjym8en6+ET9boM02CyoR5Vpn8iElXVWccAExPIQEq70D6LPe86vb+tYhuKPeLfuICN9Z0SMQ4f+57vk61Co1/uw/8kPvXlyd+Ai8Dsn/G0hpH67bBI9VOQKfpJqclcSJuSlUB5PJffvMUpr29B0eRx8LKFnIHbDILSu6nVbFLcadtWIjbYvoKorXg3J6urtkz+zEDeYMTvA6ZGOFf/Xy5eGtroSq9csSC976tx+umKEPhXBA9AcpiCV9Cj5axN03Aaa+iTE36jpnjcd9d02dy5Q9jE2nUN6KXnB6qF6eQIDAQABo4ID5TCCA+EwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIg73QCYLtjQ2G7Ysrgd71N4WA0GIehd2yb4Wu9TkCAWQCARkwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA4GA1UdDwEB/wQEAwIFoDBoBgNVHSAEYTBfMF0GCisGAQQBYAoEAQEwTzBNBggrBgEFBQcCARZBaHR0cDovL2NhLWRvY3MuY2Vybi5jaC9jYS1kb2NzL2NwLWNwcy9jZXJuLXRydXN0ZWQtY2EyLWNwLWNwcy5wZGYwJwYJKwYBBAGCNxUKBBowGDAKBggrBgEFBQcDAjAKBggrBgEFBQcDATAdBgNVHQ4EFgQUqtJcwUXasyM6sRaO5nCMFoFDenMwGAYDVR0RBBEwD4INbG9naW4uY2Vybi5jaDAfBgNVHSMEGDAWgBQdkBnqyM7MPI0UsUzZ7BTiYUADYTCCASoGA1UdHwSCASEwggEdMIIBGaCCARWgggERhkdodHRwOi8vY2FmaWxlcy5jZXJuLmNoL2NhZmlsZXMvY3JsL0NFUk4lMjBDZXJ0aWZpY2F0aW9uJTIwQXV0aG9yaXR5LmNybIaBxWxkYXA6Ly8vQ049Q0VSTiUyMENlcnRpZmljYXRpb24lMjBBdXRob3JpdHksQ049Q0VSTlBLSTA3LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWNlcm4sREM9Y2g/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MIIBVAYIKwYBBQUHAQEEggFGMIIBQjBcBggrBgEFBQcwAoZQaHR0cDovL2NhZmlsZXMuY2Vybi5jaC9jYWZpbGVzL2NlcnRpZmljYXRlcy9DRVJOJTIwQ2VydGlmaWNhdGlvbiUyMEF1dGhvcml0eS5jcnQwgbsGCCsGAQUFBzAChoGubGRhcDovLy9DTj1DRVJOJTIwQ2VydGlmaWNhdGlvbiUyMEF1dGhvcml0eSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1jZXJuLERDPWNoP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jZXJuLmNoL29jc3AwDQYJKoZIhvcNAQELBQADggIBAGKZ3bknTCfNuh4TMaL3PuvBFjU8LQ5NKY9GLZvY2ibYMRk5Is6eWRgyUsy1UJRQdaQQPnnysqrGq8VRw/NIFotBBsA978/+jj7v4e5Kr4o8HvwAQNLBxNmF6XkDytpLL701FcNEGRqIsoIhNzihi2VBADLC9HxljEyPT52IR767TMk/+xTOqClceq3sq6WRD4m+xaWRUJyOhn+Pqr+wbhXIw4wzHC6X0hcLj8P9Povtm6VmKkN9JPuymMo/0+zSrUt2+TYfmbbEKYJSP0+sceQ76IKxxmSdKAr1qDNE8v+c3DvPM2PKmfivwaV2l44FdP8ulzqTgphkYcN1daa9Oc+qJeyu/eL7xWzk6Zq5R+jVrMlM0p1y2XczI7Hoc96TMOcbVnwgMcVqRM9p57VItn6XubYPR0C33i1yUZjkWbIfqEjq6Vev6lVgngOyzu+hqC/8SDyORA3dlF9aZOD13kPZdF/JRphHREQtaRydAiYRlE/WHTvOcY52jujDftUR6oY0eWaWkwSHbX+kDFx8IlR8UtQCUgkGHBGwnOYLIGu7SRDGSfOBOiVhxKoHWVk/pL6eKY2SkmyOmmgO4JnQGg95qeAOMG/EQZt/2x8GAavUqGvYy9dPFwFf08678hQqkjNSuex7UD0ku8OP1QKvpP44l6vZhFc6A5XqjdU9lus1</X509Certificate> - </X509Data> - </KeyInfo> - </Signature> - </saml:Assertion> - </trust:RequestedSecurityToken> - <trust:RequestedAttachedReference> - <o:SecurityTokenReference k:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:k="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"> - <o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_c9e77bc4-a81b-4da7-88c2-72a6ba376d3f</o:KeyIdentifier> - </o:SecurityTokenReference> - </trust:RequestedAttachedReference> - <trust:RequestedUnattachedReference> - <o:SecurityTokenReference k:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:k="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"> - <o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_c9e77bc4-a81b-4da7-88c2-72a6ba376d3f</o:KeyIdentifier> - </o:SecurityTokenReference> - </trust:RequestedUnattachedReference> - <trust:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</trust:TokenType> - <trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType> - <trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType> - </trust:RequestSecurityTokenResponse> - </trust:RequestSecurityTokenResponseCollection> - </s:Body> -</s:Envelope> \ No newline at end of file diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/examples/xml/ADFS_fault.xml b/awx/lib/site-packages/keystoneclient/tests/unit/v3/examples/xml/ADFS_fault.xml deleted file mode 100644 index 913252e7f1..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/examples/xml/ADFS_fault.xml +++ /dev/null @@ -1,19 +0,0 @@ -<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"> - <s:Header> - <a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action> - <a:RelatesTo>urn:uuid:89c47849-2622-4cdc-bb06-1d46c89ed12d</a:RelatesTo> - </s:Header> - <s:Body> - <s:Fault> - <s:Code> - <s:Value>s:Sender</s:Value> - <s:Subcode> - <s:Value xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:FailedAuthentication</s:Value> - </s:Subcode> - </s:Code> - <s:Reason> - <s:Text xml:lang="en-US">At least one security token in the message could not be validated.</s:Text> - </s:Reason> - </s:Fault> - </s:Body> -</s:Envelope> \ No newline at end of file diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/saml2_fixtures.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/saml2_fixtures.py deleted file mode 100644 index 2ecae6ad8d..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/saml2_fixtures.py +++ /dev/null @@ -1,171 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -SP_SOAP_RESPONSE = six.b("""<S:Envelope -xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> -<S:Header> -<paos:Request xmlns:paos="urn:liberty:paos:2003-08" -S:actor="http://schemas.xmlsoap.org/soap/actor/next" -S:mustUnderstand="1" -responseConsumerURL="https://openstack4.local/Shibboleth.sso/SAML2/ECP" -service="urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"/> -<ecp:Request xmlns:ecp="urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp" -IsPassive="0" S:actor="http://schemas.xmlsoap.org/soap/actor/next" -S:mustUnderstand="1"> -<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> -https://openstack4.local/shibboleth -</saml:Issuer> -<samlp:IDPList xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> -<samlp:IDPEntry ProviderID="https://idp.testshib.org/idp/shibboleth"/> -</samlp:IDPList></ecp:Request> -<ecp:RelayState xmlns:ecp="urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp" -S:actor="http://schemas.xmlsoap.org/soap/actor/next" S:mustUnderstand="1"> -ss:mem:6f1f20fafbb38433467e9d477df67615</ecp:RelayState> -</S:Header><S:Body><samlp:AuthnRequest -xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" -AssertionConsumerServiceURL="https://openstack4.local/Shibboleth.sso/SAML2/ECP" - ID="_a07186e3992e70e92c17b9d249495643" IssueInstant="2014-06-09T09:48:57Z" - ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Version="2.0"> - <saml:Issuer - xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> - https://openstack4.local/shibboleth - </saml:Issuer><samlp:NameIDPolicy AllowCreate="1"/><samlp:Scoping> - <samlp:IDPList> - <samlp:IDPEntry ProviderID="https://idp.testshib.org/idp/shibboleth"/> - </samlp:IDPList></samlp:Scoping></samlp:AuthnRequest></S:Body></S:Envelope> -""") - - -SAML2_ASSERTION = six.b("""<?xml version="1.0" encoding="UTF-8"?> -<soap11:Envelope xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/"> -<soap11:Header> -<ecp:Response xmlns:ecp="urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp" -AssertionConsumerServiceURL="https://openstack4.local/Shibboleth.sso/SAML2/ECP" - soap11:actor="http://schemas.xmlsoap.org/soap/actor/next" - soap11:mustUnderstand="1"/> - <samlec:GeneratedKey xmlns:samlec="urn:ietf:params:xml:ns:samlec" - soap11:actor="http://schemas.xmlsoap.org/soap/actor/next"> - x= - </samlec:GeneratedKey> - </soap11:Header> - <soap11:Body> - <saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" -Destination="https://openstack4.local/Shibboleth.sso/SAML2/ECP" -ID="_bbbe6298d7ee586c915d952013875440" -InResponseTo="_a07186e3992e70e92c17b9d249495643" -IssueInstant="2014-06-09T09:48:58.945Z" Version="2.0"> -<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" -Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"> -https://idp.testshib.org/idp/shibboleth -</saml2:Issuer><saml2p:Status> -<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> -</saml2p:Status> -<saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> -<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" -Id="_e5215ac77a6028a8da8caa8be89bad44" -Type="http://www.w3.org/2001/04/xmlenc#Element"> -<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" -xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/> -<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> -<xenc:EncryptedKey Id="_204349856f6e73c9480afc949d1b4643" -xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> -<xenc:EncryptionMethod -Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" -xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> -<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" -xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/> -</xenc:EncryptionMethod><ds:KeyInfo><ds:X509Data><ds:X509Certificate> -</ds:X509Certificate> -</ds:X509Data></ds:KeyInfo> -<xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> -<xenc:CipherValue>VALUE==</xenc:CipherValue></xenc:CipherData> -</xenc:EncryptedKey></ds:KeyInfo> -<xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> -<xenc:CipherValue>VALUE=</xenc:CipherValue></xenc:CipherData> -</xenc:EncryptedData></saml2:EncryptedAssertion></saml2p:Response> -</soap11:Body></soap11:Envelope> -""") - -UNSCOPED_TOKEN_HEADER = 'UNSCOPED_TOKEN' - -UNSCOPED_TOKEN = { - "token": { - "issued_at": "2014-06-09T09:48:59.643406Z", - "extras": {}, - "methods": ["saml2"], - "expires_at": "2014-06-09T10:48:59.643375Z", - "user": { - "OS-FEDERATION": { - "identity_provider": { - "id": "testshib" - }, - "protocol": { - "id": "saml2" - }, - "groups": [ - {"id": "1764fa5cf69a49a4918131de5ce4af9a"} - ] - }, - "id": "testhib%20user", - "name": "testhib user" - } - } -} - -PROJECTS = { - "projects": [ - { - "domain_id": "37ef61", - "enabled": 'true', - "id": "12d706", - "links": { - "self": "http://identity:35357/v3/projects/12d706" - }, - "name": "a project name" - }, - { - "domain_id": "37ef61", - "enabled": 'true', - "id": "9ca0eb", - "links": { - "self": "http://identity:35357/v3/projects/9ca0eb" - }, - "name": "another project" - } - ], - "links": { - "self": "http://identity:35357/v3/OS-FEDERATION/projects", - "previous": 'null', - "next": 'null' - } -} - -DOMAINS = { - "domains": [ - { - "description": "desc of domain", - "enabled": 'true', - "id": "37ef61", - "links": { - "self": "http://identity:35357/v3/domains/37ef61" - }, - "name": "my domain" - } - ], - "links": { - "self": "http://identity:35357/v3/OS-FEDERATION/domains", - "previous": 'null', - "next": 'null' - } -} diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_access.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_access.py deleted file mode 100644 index 5e4a9493d7..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_access.py +++ /dev/null @@ -1,191 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime -import uuid - -from oslo_utils import timeutils - -from keystoneclient import access -from keystoneclient import fixture -from keystoneclient.tests.unit.v3 import client_fixtures -from keystoneclient.tests.unit.v3 import utils - - -TOKEN_RESPONSE = utils.TestResponse({ - "headers": client_fixtures.AUTH_RESPONSE_HEADERS -}) -UNSCOPED_TOKEN = client_fixtures.unscoped_token() -DOMAIN_SCOPED_TOKEN = client_fixtures.domain_scoped_token() -PROJECT_SCOPED_TOKEN = client_fixtures.project_scoped_token() - - -class AccessInfoTest(utils.TestCase): - def test_building_unscoped_accessinfo(self): - auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE, - body=UNSCOPED_TOKEN) - - self.assertTrue(auth_ref) - self.assertIn('methods', auth_ref) - self.assertNotIn('catalog', auth_ref) - - self.assertEqual(auth_ref.auth_token, - '3e2813b7ba0b4006840c3825860b86ed') - self.assertEqual(auth_ref.username, 'exampleuser') - self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a') - - self.assertEqual(auth_ref.role_ids, []) - self.assertEqual(auth_ref.role_names, []) - - self.assertIsNone(auth_ref.project_name) - self.assertIsNone(auth_ref.project_id) - - self.assertIsNone(auth_ref.auth_url) - self.assertIsNone(auth_ref.management_url) - - self.assertFalse(auth_ref.domain_scoped) - self.assertFalse(auth_ref.project_scoped) - - self.assertEqual(auth_ref.user_domain_id, - '4e6893b7ba0b4006840c3845660b86ed') - self.assertEqual(auth_ref.user_domain_name, 'exampledomain') - - self.assertIsNone(auth_ref.project_domain_id) - self.assertIsNone(auth_ref.project_domain_name) - - self.assertEqual(auth_ref.expires, timeutils.parse_isotime( - UNSCOPED_TOKEN['token']['expires_at'])) - self.assertEqual(auth_ref.issued, timeutils.parse_isotime( - UNSCOPED_TOKEN['token']['issued_at'])) - - self.assertEqual(auth_ref.expires, UNSCOPED_TOKEN.expires) - self.assertEqual(auth_ref.issued, UNSCOPED_TOKEN.issued) - - def test_will_expire_soon(self): - expires = timeutils.utcnow() + datetime.timedelta(minutes=5) - UNSCOPED_TOKEN['token']['expires_at'] = expires.isoformat() - auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE, - body=UNSCOPED_TOKEN) - self.assertFalse(auth_ref.will_expire_soon(stale_duration=120)) - self.assertTrue(auth_ref.will_expire_soon(stale_duration=301)) - self.assertFalse(auth_ref.will_expire_soon()) - - def test_building_domain_scoped_accessinfo(self): - auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE, - body=DOMAIN_SCOPED_TOKEN) - - self.assertTrue(auth_ref) - self.assertIn('methods', auth_ref) - self.assertIn('catalog', auth_ref) - self.assertTrue(auth_ref['catalog']) - - self.assertEqual(auth_ref.auth_token, - '3e2813b7ba0b4006840c3825860b86ed') - self.assertEqual(auth_ref.username, 'exampleuser') - self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a') - - self.assertEqual(auth_ref.role_ids, ['76e72a', 'f4f392']) - self.assertEqual(auth_ref.role_names, ['admin', 'member']) - - self.assertEqual(auth_ref.domain_name, 'anotherdomain') - self.assertEqual(auth_ref.domain_id, - '8e9283b7ba0b1038840c3842058b86ab') - - self.assertIsNone(auth_ref.project_name) - self.assertIsNone(auth_ref.project_id) - - self.assertEqual(auth_ref.user_domain_id, - '4e6893b7ba0b4006840c3845660b86ed') - self.assertEqual(auth_ref.user_domain_name, 'exampledomain') - - self.assertIsNone(auth_ref.project_domain_id) - self.assertIsNone(auth_ref.project_domain_name) - - self.assertTrue(auth_ref.domain_scoped) - self.assertFalse(auth_ref.project_scoped) - - def test_building_project_scoped_accessinfo(self): - auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE, - body=PROJECT_SCOPED_TOKEN) - - self.assertTrue(auth_ref) - self.assertIn('methods', auth_ref) - self.assertIn('catalog', auth_ref) - self.assertTrue(auth_ref['catalog']) - - self.assertEqual(auth_ref.auth_token, - '3e2813b7ba0b4006840c3825860b86ed') - self.assertEqual(auth_ref.username, 'exampleuser') - self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a') - - self.assertEqual(auth_ref.role_ids, ['76e72a', 'f4f392']) - self.assertEqual(auth_ref.role_names, ['admin', 'member']) - - self.assertIsNone(auth_ref.domain_name) - self.assertIsNone(auth_ref.domain_id) - - self.assertEqual(auth_ref.project_name, 'exampleproject') - self.assertEqual(auth_ref.project_id, - '225da22d3ce34b15877ea70b2a575f58') - - self.assertEqual(auth_ref.tenant_name, auth_ref.project_name) - self.assertEqual(auth_ref.tenant_id, auth_ref.project_id) - - self.assertEqual(auth_ref.auth_url, - ('http://public.com:5000/v3',)) - self.assertEqual(auth_ref.management_url, - ('http://admin:35357/v3',)) - - self.assertEqual(auth_ref.project_domain_id, - '4e6893b7ba0b4006840c3845660b86ed') - self.assertEqual(auth_ref.project_domain_name, 'exampledomain') - - self.assertEqual(auth_ref.user_domain_id, - '4e6893b7ba0b4006840c3845660b86ed') - self.assertEqual(auth_ref.user_domain_name, 'exampledomain') - - self.assertFalse(auth_ref.domain_scoped) - self.assertTrue(auth_ref.project_scoped) - - def test_oauth_access(self): - consumer_id = uuid.uuid4().hex - access_token_id = uuid.uuid4().hex - - token = fixture.V3Token() - token.set_project_scope() - token.set_oauth(access_token_id=access_token_id, - consumer_id=consumer_id) - - auth_ref = access.AccessInfo.factory(body=token) - - self.assertEqual(consumer_id, auth_ref.oauth_consumer_id) - self.assertEqual(access_token_id, auth_ref.oauth_access_token_id) - - self.assertEqual(consumer_id, auth_ref['OS-OAUTH1']['consumer_id']) - self.assertEqual(access_token_id, - auth_ref['OS-OAUTH1']['access_token_id']) - - def test_override_auth_token(self): - token = fixture.V3Token() - token.set_project_scope() - - new_auth_token = uuid.uuid4().hex - auth_ref = access.AccessInfo.factory(body=token, - auth_token=new_auth_token) - self.assertEqual(new_auth_token, auth_ref.auth_token) - - def test_federated_property_standard_token(self): - """Check if is_federated property returns expected value.""" - token = fixture.V3Token() - token.set_project_scope() - auth_ref = access.AccessInfo.factory(body=token) - self.assertFalse(auth_ref.is_federated) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_auth.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_auth.py deleted file mode 100644 index b3f29d66fa..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_auth.py +++ /dev/null @@ -1,352 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_serialization import jsonutils - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import client - - -class AuthenticateAgainstKeystoneTests(utils.TestCase): - def setUp(self): - super(AuthenticateAgainstKeystoneTests, self).setUp() - self.TEST_RESPONSE_DICT = { - "token": { - "methods": [ - "token", - "password" - ], - - "expires_at": "2020-01-01T00:00:10.000123Z", - "project": { - "domain": { - "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME - }, - "id": self.TEST_TENANT_ID, - "name": self.TEST_TENANT_NAME - }, - "user": { - "domain": { - "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME - }, - "id": self.TEST_USER, - "name": self.TEST_USER - }, - "issued_at": "2013-05-29T16:55:21.468960Z", - "catalog": self.TEST_SERVICE_CATALOG - }, - } - self.TEST_REQUEST_BODY = { - "auth": { - "identity": { - "methods": ["password"], - "password": { - "user": { - "domain": { - "name": self.TEST_DOMAIN_NAME - }, - "name": self.TEST_USER, - "password": self.TEST_TOKEN - } - } - }, - "scope": { - "project": { - "id": self.TEST_TENANT_ID - }, - } - } - } - self.TEST_REQUEST_HEADERS = { - 'Content-Type': 'application/json', - 'User-Agent': 'python-keystoneclient' - } - self.TEST_RESPONSE_HEADERS = { - 'X-Subject-Token': self.TEST_TOKEN - } - - def test_authenticate_success(self): - TEST_TOKEN = "abcdef" - ident = self.TEST_REQUEST_BODY['auth']['identity'] - del ident['password']['user']['domain'] - del ident['password']['user']['name'] - ident['password']['user']['id'] = self.TEST_USER - - self.stub_auth(json=self.TEST_RESPONSE_DICT, subject_token=TEST_TOKEN) - - cs = client.Client(user_id=self.TEST_USER, - password=self.TEST_TOKEN, - project_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_token, TEST_TOKEN) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_failure(self): - ident = self.TEST_REQUEST_BODY['auth']['identity'] - ident['password']['user']['password'] = 'bad_key' - error = {"unauthorized": {"message": "Unauthorized", - "code": "401"}} - - self.stub_auth(status_code=401, json=error) - - # Workaround for issue with assertRaises on python2.6 - # where with assertRaises(exceptions.Unauthorized): doesn't work - # right - def client_create_wrapper(): - client.Client(user_domain_name=self.TEST_DOMAIN_NAME, - username=self.TEST_USER, - password="bad_key", - project_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - - self.assertRaises(exceptions.Unauthorized, client_create_wrapper) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_auth_redirect(self): - headers = {'Location': self.TEST_ADMIN_URL + '/auth/tokens'} - self.stub_auth(status_code=305, text='Use proxy', headers=headers) - - self.stub_auth(json=self.TEST_RESPONSE_DICT, - base_url=self.TEST_ADMIN_URL) - - cs = client.Client(user_domain_name=self.TEST_DOMAIN_NAME, - username=self.TEST_USER, - password=self.TEST_TOKEN, - project_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["token"]["catalog"][3] - ['endpoints'][2]["url"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - - def test_authenticate_success_domain_username_password_scoped(self): - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(user_domain_name=self.TEST_DOMAIN_NAME, - username=self.TEST_USER, - password=self.TEST_TOKEN, - project_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["token"]["catalog"][3] - ['endpoints'][2]["url"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - - def test_authenticate_success_userid_password_domain_scoped(self): - ident = self.TEST_REQUEST_BODY['auth']['identity'] - del ident['password']['user']['domain'] - del ident['password']['user']['name'] - ident['password']['user']['id'] = self.TEST_USER - - scope = self.TEST_REQUEST_BODY['auth']['scope'] - del scope['project'] - scope['domain'] = {} - scope['domain']['id'] = self.TEST_DOMAIN_ID - - token = self.TEST_RESPONSE_DICT['token'] - del token['project'] - token['domain'] = {} - token['domain']['id'] = self.TEST_DOMAIN_ID - token['domain']['name'] = self.TEST_DOMAIN_NAME - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(user_id=self.TEST_USER, - password=self.TEST_TOKEN, - domain_id=self.TEST_DOMAIN_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_domain_id, - self.TEST_DOMAIN_ID) - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["token"]["catalog"][3] - ['endpoints'][2]["url"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_userid_password_project_scoped(self): - ident = self.TEST_REQUEST_BODY['auth']['identity'] - del ident['password']['user']['domain'] - del ident['password']['user']['name'] - ident['password']['user']['id'] = self.TEST_USER - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(user_id=self.TEST_USER, - password=self.TEST_TOKEN, - project_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_tenant_id, - self.TEST_TENANT_ID) - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["token"]["catalog"][3] - ['endpoints'][2]["url"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_password_unscoped(self): - del self.TEST_RESPONSE_DICT['token']['catalog'] - del self.TEST_REQUEST_BODY['auth']['scope'] - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(user_domain_name=self.TEST_DOMAIN_NAME, - username=self.TEST_USER, - password=self.TEST_TOKEN, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - self.assertFalse('catalog' in cs.service_catalog.catalog) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_auth_url_token_authentication(self): - fake_token = 'fake_token' - fake_url = '/fake-url' - fake_resp = {'result': True} - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [fake_url], json=fake_resp, - base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT) - - cl = client.Client(auth_url=self.TEST_URL, - token=fake_token) - body = jsonutils.loads(self.requests_mock.last_request.body) - self.assertEqual(body['auth']['identity']['token']['id'], fake_token) - - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(self.TEST_TOKEN, token) - - def test_authenticate_success_token_domain_scoped(self): - ident = self.TEST_REQUEST_BODY['auth']['identity'] - del ident['password'] - ident['methods'] = ['token'] - ident['token'] = {} - ident['token']['id'] = self.TEST_TOKEN - - scope = self.TEST_REQUEST_BODY['auth']['scope'] - del scope['project'] - scope['domain'] = {} - scope['domain']['id'] = self.TEST_DOMAIN_ID - - token = self.TEST_RESPONSE_DICT['token'] - del token['project'] - token['domain'] = {} - token['domain']['id'] = self.TEST_DOMAIN_ID - token['domain']['name'] = self.TEST_DOMAIN_NAME - - self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(token=self.TEST_TOKEN, - domain_id=self.TEST_DOMAIN_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_domain_id, - self.TEST_DOMAIN_ID) - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["token"]["catalog"][3] - ['endpoints'][2]["url"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_token_project_scoped(self): - ident = self.TEST_REQUEST_BODY['auth']['identity'] - del ident['password'] - ident['methods'] = ['token'] - ident['token'] = {} - ident['token']['id'] = self.TEST_TOKEN - self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(token=self.TEST_TOKEN, - project_id=self.TEST_TENANT_ID, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_tenant_id, - self.TEST_TENANT_ID) - self.assertEqual(cs.management_url, - self.TEST_RESPONSE_DICT["token"]["catalog"][3] - ['endpoints'][2]["url"]) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_authenticate_success_token_unscoped(self): - ident = self.TEST_REQUEST_BODY['auth']['identity'] - del ident['password'] - ident['methods'] = ['token'] - ident['token'] = {} - ident['token']['id'] = self.TEST_TOKEN - del self.TEST_REQUEST_BODY['auth']['scope'] - del self.TEST_RESPONSE_DICT['token']['catalog'] - self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - - cs = client.Client(token=self.TEST_TOKEN, - auth_url=self.TEST_URL) - self.assertEqual(cs.auth_token, - self.TEST_RESPONSE_HEADERS["X-Subject-Token"]) - self.assertFalse('catalog' in cs.service_catalog.catalog) - self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY) - - def test_allow_override_of_auth_token(self): - fake_url = '/fake-url' - fake_token = 'fake_token' - fake_resp = {'result': True} - - self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [fake_url], json=fake_resp, - base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT) - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL) - - self.assertEqual(cl.auth_token, self.TEST_TOKEN) - - # the token returned from the authentication will be used - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(self.TEST_TOKEN, token) - - # then override that token and the new token shall be used - cl.auth_token = fake_token - - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(fake_token, token) - - # if we clear that overridden token then we fall back to the original - del cl.auth_token - - resp, body = cl.get(fake_url) - self.assertEqual(fake_resp, body) - - token = self.requests_mock.last_request.headers.get('X-Auth-Token') - self.assertEqual(self.TEST_TOKEN, token) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_auth_saml2.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_auth_saml2.py deleted file mode 100644 index 33bfdac2d3..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_auth_saml2.py +++ /dev/null @@ -1,623 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import uuid - -from lxml import etree -from oslo_config import fixture as config -import requests -from six.moves import urllib - -from keystoneclient.auth import conf -from keystoneclient.contrib.auth.v3 import saml2 -from keystoneclient import exceptions -from keystoneclient import session -from keystoneclient.tests.unit.v3 import client_fixtures -from keystoneclient.tests.unit.v3 import saml2_fixtures -from keystoneclient.tests.unit.v3 import utils - -ROOTDIR = os.path.dirname(os.path.abspath(__file__)) -XMLDIR = os.path.join(ROOTDIR, 'examples', 'xml/') - - -def make_oneline(s): - return etree.tostring(etree.XML(s)).replace(b'\n', b'') - - -def _load_xml(filename): - with open(XMLDIR + filename, 'rb') as f: - return make_oneline(f.read()) - - -class AuthenticateviaSAML2Tests(utils.TestCase): - - GROUP = 'auth' - - class _AuthenticatedResponse(object): - headers = { - 'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER - } - - def json(self): - return saml2_fixtures.UNSCOPED_TOKEN - - class _AuthenticatedResponseInvalidJson(_AuthenticatedResponse): - - def json(self): - raise ValueError() - - class _AuthentiatedResponseMissingTokenID(_AuthenticatedResponse): - headers = {} - - def setUp(self): - super(AuthenticateviaSAML2Tests, self).setUp() - - self.conf_fixture = self.useFixture(config.Config()) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - - self.session = session.Session() - - self.ECP_SP_EMPTY_REQUEST_HEADERS = { - 'Accept': 'text/html; application/vnd.paos+xml', - 'PAOS': ('ver="urn:liberty:paos:2003-08";' - '"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"') - } - - self.ECP_SP_SAML2_REQUEST_HEADERS = { - 'Content-Type': 'application/vnd.paos+xml' - } - - self.ECP_SAML2_NAMESPACES = { - 'ecp': 'urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp', - 'S': 'http://schemas.xmlsoap.org/soap/envelope/', - 'paos': 'urn:liberty:paos:2003-08' - } - self.ECP_RELAY_STATE = '//ecp:RelayState' - self.ECP_SERVICE_PROVIDER_CONSUMER_URL = ('/S:Envelope/S:Header/paos:' - 'Request/' - '@responseConsumerURL') - self.ECP_IDP_CONSUMER_URL = ('/S:Envelope/S:Header/ecp:Response/' - '@AssertionConsumerServiceURL') - self.IDENTITY_PROVIDER = 'testidp' - self.IDENTITY_PROVIDER_URL = 'http://local.url' - self.PROTOCOL = 'saml2' - self.FEDERATION_AUTH_URL = '%s/%s' % ( - self.TEST_URL, - 'OS-FEDERATION/identity_providers/testidp/protocols/saml2/auth') - self.SHIB_CONSUMER_URL = ('https://openstack4.local/' - 'Shibboleth.sso/SAML2/ECP') - - self.saml2plugin = saml2.Saml2UnscopedToken( - self.TEST_URL, - self.IDENTITY_PROVIDER, self.IDENTITY_PROVIDER_URL, - self.TEST_USER, self.TEST_TOKEN) - - def test_conf_params(self): - section = uuid.uuid4().hex - identity_provider = uuid.uuid4().hex - identity_provider_url = uuid.uuid4().hex - username = uuid.uuid4().hex - password = uuid.uuid4().hex - self.conf_fixture.config(auth_section=section, group=self.GROUP) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - - self.conf_fixture.register_opts(saml2.Saml2UnscopedToken.get_options(), - group=section) - self.conf_fixture.config(auth_plugin='v3unscopedsaml', - identity_provider=identity_provider, - identity_provider_url=identity_provider_url, - username=username, - password=password, - group=section) - - a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP) - self.assertEqual(identity_provider, a.identity_provider) - self.assertEqual(identity_provider_url, a.identity_provider_url) - self.assertEqual(username, a.username) - self.assertEqual(password, a.password) - - def test_initial_sp_call(self): - """Test initial call, expect SOAP message.""" - self.requests_mock.get( - self.FEDERATION_AUTH_URL, - content=make_oneline(saml2_fixtures.SP_SOAP_RESPONSE)) - a = self.saml2plugin._send_service_provider_request(self.session) - - self.assertFalse(a) - - fixture_soap_response = make_oneline( - saml2_fixtures.SP_SOAP_RESPONSE) - - sp_soap_response = make_oneline( - etree.tostring(self.saml2plugin.saml2_authn_request)) - - error_msg = "Expected %s instead of %s" % (fixture_soap_response, - sp_soap_response) - - self.assertEqual(fixture_soap_response, sp_soap_response, error_msg) - - self.assertEqual( - self.saml2plugin.sp_response_consumer_url, self.SHIB_CONSUMER_URL, - "Expected consumer_url set to %s instead of %s" % ( - self.SHIB_CONSUMER_URL, - str(self.saml2plugin.sp_response_consumer_url))) - - def test_initial_sp_call_when_saml_authenticated(self): - self.requests_mock.get( - self.FEDERATION_AUTH_URL, - json=saml2_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER}) - - a = self.saml2plugin._send_service_provider_request(self.session) - self.assertTrue(a) - self.assertEqual( - saml2_fixtures.UNSCOPED_TOKEN['token'], - self.saml2plugin.authenticated_response.json()['token']) - self.assertEqual( - saml2_fixtures.UNSCOPED_TOKEN_HEADER, - self.saml2plugin.authenticated_response.headers['X-Subject-Token']) - - def test_get_unscoped_token_when_authenticated(self): - self.requests_mock.get( - self.FEDERATION_AUTH_URL, - json=saml2_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER, - 'Content-Type': 'application/json'}) - - token, token_body = self.saml2plugin._get_unscoped_token(self.session) - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN['token'], token_body) - - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN_HEADER, token) - - def test_initial_sp_call_invalid_response(self): - """Send initial SP HTTP request and receive wrong server response.""" - self.requests_mock.get(self.FEDERATION_AUTH_URL, - text='NON XML RESPONSE') - - self.assertRaises( - exceptions.AuthorizationFailure, - self.saml2plugin._send_service_provider_request, - self.session) - - def test_send_authn_req_to_idp(self): - self.requests_mock.post(self.IDENTITY_PROVIDER_URL, - content=saml2_fixtures.SAML2_ASSERTION) - - self.saml2plugin.sp_response_consumer_url = self.SHIB_CONSUMER_URL - self.saml2plugin.saml2_authn_request = etree.XML( - saml2_fixtures.SP_SOAP_RESPONSE) - self.saml2plugin._send_idp_saml2_authn_request(self.session) - - idp_response = make_oneline(etree.tostring( - self.saml2plugin.saml2_idp_authn_response)) - - saml2_assertion_oneline = make_oneline( - saml2_fixtures.SAML2_ASSERTION) - error = "Expected %s instead of %s" % (saml2_fixtures.SAML2_ASSERTION, - idp_response) - self.assertEqual(idp_response, saml2_assertion_oneline, error) - - def test_fail_basicauth_idp_authentication(self): - self.requests_mock.post(self.IDENTITY_PROVIDER_URL, status_code=401) - - self.saml2plugin.sp_response_consumer_url = self.SHIB_CONSUMER_URL - self.saml2plugin.saml2_authn_request = etree.XML( - saml2_fixtures.SP_SOAP_RESPONSE) - self.assertRaises( - exceptions.Unauthorized, - self.saml2plugin._send_idp_saml2_authn_request, - self.session) - - def test_mising_username_password_in_plugin(self): - self.assertRaises(TypeError, - saml2.Saml2UnscopedToken, - self.TEST_URL, self.IDENTITY_PROVIDER, - self.IDENTITY_PROVIDER_URL) - - def test_send_authn_response_to_sp(self): - self.requests_mock.post( - self.SHIB_CONSUMER_URL, - json=saml2_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER}) - - self.saml2plugin.relay_state = etree.XML( - saml2_fixtures.SP_SOAP_RESPONSE).xpath( - self.ECP_RELAY_STATE, namespaces=self.ECP_SAML2_NAMESPACES)[0] - - self.saml2plugin.saml2_idp_authn_response = etree.XML( - saml2_fixtures.SAML2_ASSERTION) - - self.saml2plugin.idp_response_consumer_url = self.SHIB_CONSUMER_URL - self.saml2plugin._send_service_provider_saml2_authn_response( - self.session) - token_json = self.saml2plugin.authenticated_response.json()['token'] - token = self.saml2plugin.authenticated_response.headers[ - 'X-Subject-Token'] - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN['token'], - token_json) - - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN_HEADER, - token) - - def test_consumer_url_mismatch_success(self): - self.saml2plugin._check_consumer_urls( - self.session, self.SHIB_CONSUMER_URL, - self.SHIB_CONSUMER_URL) - - def test_consumer_url_mismatch(self): - self.requests_mock.post(self.SHIB_CONSUMER_URL) - invalid_consumer_url = uuid.uuid4().hex - self.assertRaises( - exceptions.ValidationError, - self.saml2plugin._check_consumer_urls, - self.session, self.SHIB_CONSUMER_URL, - invalid_consumer_url) - - def test_custom_302_redirection(self): - self.requests_mock.post( - self.SHIB_CONSUMER_URL, - text='BODY', - headers={'location': self.FEDERATION_AUTH_URL}, - status_code=302) - - self.requests_mock.get( - self.FEDERATION_AUTH_URL, - json=saml2_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER}) - - self.session.redirect = False - response = self.session.post( - self.SHIB_CONSUMER_URL, data='CLIENT BODY') - self.assertEqual(302, response.status_code) - self.assertEqual(self.FEDERATION_AUTH_URL, - response.headers['location']) - - response = self.saml2plugin._handle_http_302_ecp_redirect( - self.session, response, 'GET') - - self.assertEqual(self.FEDERATION_AUTH_URL, response.request.url) - self.assertEqual('GET', response.request.method) - - def test_end_to_end_workflow(self): - self.requests_mock.get( - self.FEDERATION_AUTH_URL, - content=make_oneline(saml2_fixtures.SP_SOAP_RESPONSE)) - - self.requests_mock.post(self.IDENTITY_PROVIDER_URL, - content=saml2_fixtures.SAML2_ASSERTION) - - self.requests_mock.post( - self.SHIB_CONSUMER_URL, - json=saml2_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': saml2_fixtures.UNSCOPED_TOKEN_HEADER, - 'Content-Type': 'application/json'}) - - self.session.redirect = False - response = self.saml2plugin.get_auth_ref(self.session) - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN_HEADER, - response.auth_token) - - -class ScopeFederationTokenTests(AuthenticateviaSAML2Tests): - - TEST_TOKEN = client_fixtures.AUTH_SUBJECT_TOKEN - - def setUp(self): - super(ScopeFederationTokenTests, self).setUp() - - self.PROJECT_SCOPED_TOKEN_JSON = client_fixtures.project_scoped_token() - self.PROJECT_SCOPED_TOKEN_JSON['methods'] = ['saml2'] - - # for better readability - self.TEST_TENANT_ID = self.PROJECT_SCOPED_TOKEN_JSON.project_id - self.TEST_TENANT_NAME = self.PROJECT_SCOPED_TOKEN_JSON.project_name - - self.DOMAIN_SCOPED_TOKEN_JSON = client_fixtures.domain_scoped_token() - self.DOMAIN_SCOPED_TOKEN_JSON['methods'] = ['saml2'] - - # for better readability - self.TEST_DOMAIN_ID = self.DOMAIN_SCOPED_TOKEN_JSON.domain_id - self.TEST_DOMAIN_NAME = self.DOMAIN_SCOPED_TOKEN_JSON.domain_name - - self.saml2_scope_plugin = saml2.Saml2ScopedToken( - self.TEST_URL, saml2_fixtures.UNSCOPED_TOKEN_HEADER, - project_id=self.TEST_TENANT_ID) - - def test_scope_saml2_token_to_project(self): - self.stub_auth(json=self.PROJECT_SCOPED_TOKEN_JSON) - - token = self.saml2_scope_plugin.get_auth_ref(self.session) - self.assertTrue(token.project_scoped, "Received token is not scoped") - self.assertEqual(client_fixtures.AUTH_SUBJECT_TOKEN, token.auth_token) - self.assertEqual(self.TEST_TENANT_ID, token.project_id) - self.assertEqual(self.TEST_TENANT_NAME, token.project_name) - - def test_scope_saml2_token_to_invalid_project(self): - self.stub_auth(status_code=401) - self.saml2_scope_plugin.project_id = uuid.uuid4().hex - self.saml2_scope_plugin.project_name = None - self.assertRaises(exceptions.Unauthorized, - self.saml2_scope_plugin.get_auth_ref, - self.session) - - def test_scope_saml2_token_to_invalid_domain(self): - self.stub_auth(status_code=401) - self.saml2_scope_plugin.project_id = None - self.saml2_scope_plugin.project_name = None - self.saml2_scope_plugin.domain_id = uuid.uuid4().hex - self.saml2_scope_plugin.domain_name = None - self.assertRaises(exceptions.Unauthorized, - self.saml2_scope_plugin.get_auth_ref, - self.session) - - def test_scope_saml2_token_to_domain(self): - self.stub_auth(json=self.DOMAIN_SCOPED_TOKEN_JSON) - token = self.saml2_scope_plugin.get_auth_ref(self.session) - self.assertTrue(token.domain_scoped, "Received token is not scoped") - self.assertEqual(client_fixtures.AUTH_SUBJECT_TOKEN, token.auth_token) - self.assertEqual(self.TEST_DOMAIN_ID, token.domain_id) - self.assertEqual(self.TEST_DOMAIN_NAME, token.domain_name) - - def test_dont_set_project_nor_domain(self): - self.saml2_scope_plugin.project_id = None - self.saml2_scope_plugin.domain_id = None - self.assertRaises(exceptions.ValidationError, - saml2.Saml2ScopedToken, - self.TEST_URL, client_fixtures.AUTH_SUBJECT_TOKEN) - - -class AuthenticateviaADFSTests(utils.TestCase): - - GROUP = 'auth' - - NAMESPACES = { - 's': 'http://www.w3.org/2003/05/soap-envelope', - 'trust': 'http://docs.oasis-open.org/ws-sx/ws-trust/200512', - 'wsa': 'http://www.w3.org/2005/08/addressing', - 'wsp': 'http://schemas.xmlsoap.org/ws/2004/09/policy', - 'a': 'http://www.w3.org/2005/08/addressing', - 'o': ('http://docs.oasis-open.org/wss/2004/01/oasis' - '-200401-wss-wssecurity-secext-1.0.xsd') - } - - USER_XPATH = ('/s:Envelope/s:Header' - '/o:Security' - '/o:UsernameToken' - '/o:Username') - PASSWORD_XPATH = ('/s:Envelope/s:Header' - '/o:Security' - '/o:UsernameToken' - '/o:Password') - ADDRESS_XPATH = ('/s:Envelope/s:Body' - '/trust:RequestSecurityToken' - '/wsp:AppliesTo/wsa:EndpointReference' - '/wsa:Address') - TO_XPATH = ('/s:Envelope/s:Header' - '/a:To') - - @property - def _uuid4(self): - return '4b911420-4982-4009-8afc-5c596cd487f5' - - def setUp(self): - super(AuthenticateviaADFSTests, self).setUp() - - self.conf_fixture = self.useFixture(config.Config()) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - self.session = session.Session(session=requests.Session()) - - self.IDENTITY_PROVIDER = 'adfs' - self.IDENTITY_PROVIDER_URL = ('http://adfs.local/adfs/service/trust/13' - '/usernamemixed') - self.FEDERATION_AUTH_URL = '%s/%s' % ( - self.TEST_URL, - 'OS-FEDERATION/identity_providers/adfs/protocols/saml2/auth') - self.SP_ENDPOINT = 'https://openstack4.local/Shibboleth.sso/ADFS' - - self.adfsplugin = saml2.ADFSUnscopedToken( - self.TEST_URL, self.IDENTITY_PROVIDER, - self.IDENTITY_PROVIDER_URL, self.SP_ENDPOINT, - self.TEST_USER, self.TEST_TOKEN) - - self.ADFS_SECURITY_TOKEN_RESPONSE = _load_xml( - 'ADFS_RequestSecurityTokenResponse.xml') - self.ADFS_FAULT = _load_xml('ADFS_fault.xml') - - def test_conf_params(self): - section = uuid.uuid4().hex - identity_provider = uuid.uuid4().hex - identity_provider_url = uuid.uuid4().hex - sp_endpoint = uuid.uuid4().hex - username = uuid.uuid4().hex - password = uuid.uuid4().hex - self.conf_fixture.config(auth_section=section, group=self.GROUP) - conf.register_conf_options(self.conf_fixture.conf, group=self.GROUP) - - self.conf_fixture.register_opts(saml2.ADFSUnscopedToken.get_options(), - group=section) - self.conf_fixture.config(auth_plugin='v3unscopedadfs', - identity_provider=identity_provider, - identity_provider_url=identity_provider_url, - service_provider_endpoint=sp_endpoint, - username=username, - password=password, - group=section) - - a = conf.load_from_conf_options(self.conf_fixture.conf, self.GROUP) - self.assertEqual(identity_provider, a.identity_provider) - self.assertEqual(identity_provider_url, a.identity_provider_url) - self.assertEqual(sp_endpoint, a.service_provider_endpoint) - self.assertEqual(username, a.username) - self.assertEqual(password, a.password) - - def test_get_adfs_security_token(self): - """Test ADFSUnscopedToken._get_adfs_security_token().""" - - self.requests_mock.post( - self.IDENTITY_PROVIDER_URL, - content=make_oneline(self.ADFS_SECURITY_TOKEN_RESPONSE), - status_code=200) - - self.adfsplugin._prepare_adfs_request() - self.adfsplugin._get_adfs_security_token(self.session) - - adfs_response = etree.tostring(self.adfsplugin.adfs_token) - fixture_response = self.ADFS_SECURITY_TOKEN_RESPONSE - - self.assertEqual(fixture_response, adfs_response) - - def test_adfs_request_user(self): - self.adfsplugin._prepare_adfs_request() - user = self.adfsplugin.prepared_request.xpath( - self.USER_XPATH, namespaces=self.NAMESPACES)[0] - self.assertEqual(self.TEST_USER, user.text) - - def test_adfs_request_password(self): - self.adfsplugin._prepare_adfs_request() - password = self.adfsplugin.prepared_request.xpath( - self.PASSWORD_XPATH, namespaces=self.NAMESPACES)[0] - self.assertEqual(self.TEST_TOKEN, password.text) - - def test_adfs_request_to(self): - self.adfsplugin._prepare_adfs_request() - to = self.adfsplugin.prepared_request.xpath( - self.TO_XPATH, namespaces=self.NAMESPACES)[0] - self.assertEqual(self.IDENTITY_PROVIDER_URL, to.text) - - def test_prepare_adfs_request_address(self): - self.adfsplugin._prepare_adfs_request() - address = self.adfsplugin.prepared_request.xpath( - self.ADDRESS_XPATH, namespaces=self.NAMESPACES)[0] - self.assertEqual(self.SP_ENDPOINT, address.text) - - def test_prepare_sp_request(self): - assertion = etree.XML(self.ADFS_SECURITY_TOKEN_RESPONSE) - assertion = assertion.xpath( - saml2.ADFSUnscopedToken.ADFS_ASSERTION_XPATH, - namespaces=saml2.ADFSUnscopedToken.ADFS_TOKEN_NAMESPACES) - assertion = assertion[0] - assertion = etree.tostring(assertion) - - assertion = assertion.replace( - b'http://docs.oasis-open.org/ws-sx/ws-trust/200512', - b'http://schemas.xmlsoap.org/ws/2005/02/trust') - assertion = urllib.parse.quote(assertion) - assertion = 'wa=wsignin1.0&wresult=' + assertion - - self.adfsplugin.adfs_token = etree.XML( - self.ADFS_SECURITY_TOKEN_RESPONSE) - self.adfsplugin._prepare_sp_request() - - self.assertEqual(assertion, self.adfsplugin.encoded_assertion) - - def test_get_adfs_security_token_authn_fail(self): - """Test proper parsing XML fault after bad authentication. - - An exceptions.AuthorizationFailure should be raised including - error message from the XML message indicating where was the problem. - """ - self.requests_mock.post(self.IDENTITY_PROVIDER_URL, - content=make_oneline(self.ADFS_FAULT), - status_code=500) - - self.adfsplugin._prepare_adfs_request() - self.assertRaises(exceptions.AuthorizationFailure, - self.adfsplugin._get_adfs_security_token, - self.session) - # TODO(marek-denis): Python3 tests complain about missing 'message' - # attributes - # self.assertEqual('a:FailedAuthentication', e.message) - - def test_get_adfs_security_token_bad_response(self): - """Test proper handling HTTP 500 and mangled (non XML) response. - - This should never happen yet, keystoneclient should be prepared - and correctly raise exceptions.InternalServerError once it cannot - parse XML fault message - """ - self.requests_mock.post(self.IDENTITY_PROVIDER_URL, - content=b'NOT XML', - status_code=500) - self.adfsplugin._prepare_adfs_request() - self.assertRaises(exceptions.InternalServerError, - self.adfsplugin._get_adfs_security_token, - self.session) - - # TODO(marek-denis): Need to figure out how to properly send cookies - # from the request_uri() method. - def _send_assertion_to_service_provider(self): - """Test whether SP issues a cookie.""" - cookie = uuid.uuid4().hex - - self.requests_mock.post(self.SP_ENDPOINT, - headers={"set-cookie": cookie}, - status_code=302) - - self.adfsplugin.adfs_token = self._build_adfs_request() - self.adfsplugin._prepare_sp_request() - self.adfsplugin._send_assertion_to_service_provider(self.session) - - self.assertEqual(1, len(self.session.session.cookies)) - - def test_send_assertion_to_service_provider_bad_status(self): - self.requests_mock.post(self.SP_ENDPOINT, status_code=500) - - self.adfsplugin.adfs_token = etree.XML( - self.ADFS_SECURITY_TOKEN_RESPONSE) - self.adfsplugin._prepare_sp_request() - - self.assertRaises( - exceptions.InternalServerError, - self.adfsplugin._send_assertion_to_service_provider, - self.session) - - def test_access_sp_no_cookies_fail(self): - # clean cookie jar - self.session.session.cookies = [] - - self.assertRaises(exceptions.AuthorizationFailure, - self.adfsplugin._access_service_provider, - self.session) - - def test_check_valid_token_when_authenticated(self): - self.requests_mock.get(self.FEDERATION_AUTH_URL, - json=saml2_fixtures.UNSCOPED_TOKEN, - headers=client_fixtures.AUTH_RESPONSE_HEADERS) - - self.session.session.cookies = [object()] - self.adfsplugin._access_service_provider(self.session) - response = self.adfsplugin.authenticated_response - - self.assertEqual(client_fixtures.AUTH_RESPONSE_HEADERS, - response.headers) - - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN['token'], - response.json()['token']) - - def test_end_to_end_workflow(self): - self.requests_mock.post(self.IDENTITY_PROVIDER_URL, - content=self.ADFS_SECURITY_TOKEN_RESPONSE, - status_code=200) - self.requests_mock.post(self.SP_ENDPOINT, - headers={"set-cookie": 'x'}, - status_code=302) - self.requests_mock.get(self.FEDERATION_AUTH_URL, - json=saml2_fixtures.UNSCOPED_TOKEN, - headers=client_fixtures.AUTH_RESPONSE_HEADERS) - - # NOTE(marek-denis): We need to mimic this until self.requests_mock can - # issue cookies properly. - self.session.session.cookies = [object()] - token, token_json = self.adfsplugin._get_unscoped_token(self.session) - self.assertEqual(token, client_fixtures.AUTH_SUBJECT_TOKEN) - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN['token'], token_json) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_client.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_client.py deleted file mode 100644 index 6be09c117c..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_client.py +++ /dev/null @@ -1,230 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import json -import uuid - -import six - -from keystoneclient.auth import token_endpoint -from keystoneclient import exceptions -from keystoneclient import session -from keystoneclient.tests.unit.v3 import client_fixtures -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import client - - -class KeystoneClientTest(utils.TestCase): - - def test_unscoped_init(self): - self.stub_auth(json=client_fixtures.unscoped_token()) - - c = client.Client(user_domain_name='exampledomain', - username='exampleuser', - password='password', - auth_url=self.TEST_URL) - self.assertIsNotNone(c.auth_ref) - self.assertFalse(c.auth_ref.domain_scoped) - self.assertFalse(c.auth_ref.project_scoped) - self.assertEqual(c.auth_user_id, - 'c4da488862bd435c9e6c0275a0d0e49a') - self.assertFalse(c.has_service_catalog()) - - self.assertEqual('c4da488862bd435c9e6c0275a0d0e49a', - c.get_user_id(session=None)) - self.assertIsNone(c.get_project_id(session=None)) - - def test_domain_scoped_init(self): - self.stub_auth(json=client_fixtures.domain_scoped_token()) - - c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a', - password='password', - domain_name='exampledomain', - auth_url=self.TEST_URL) - self.assertIsNotNone(c.auth_ref) - self.assertTrue(c.auth_ref.domain_scoped) - self.assertFalse(c.auth_ref.project_scoped) - self.assertEqual(c.auth_user_id, - 'c4da488862bd435c9e6c0275a0d0e49a') - self.assertEqual(c.auth_domain_id, - '8e9283b7ba0b1038840c3842058b86ab') - - def test_project_scoped_init(self): - self.stub_auth(json=client_fixtures.project_scoped_token()), - - c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a', - password='password', - user_domain_name='exampledomain', - project_name='exampleproject', - auth_url=self.TEST_URL) - self.assertIsNotNone(c.auth_ref) - self.assertFalse(c.auth_ref.domain_scoped) - self.assertTrue(c.auth_ref.project_scoped) - self.assertEqual(c.auth_user_id, - 'c4da488862bd435c9e6c0275a0d0e49a') - self.assertEqual(c.auth_tenant_id, - '225da22d3ce34b15877ea70b2a575f58') - self.assertEqual('c4da488862bd435c9e6c0275a0d0e49a', - c.get_user_id(session=None)) - self.assertEqual('225da22d3ce34b15877ea70b2a575f58', - c.get_project_id(session=None)) - - def test_auth_ref_load(self): - self.stub_auth(json=client_fixtures.project_scoped_token()) - - c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a', - password='password', - project_id='225da22d3ce34b15877ea70b2a575f58', - auth_url=self.TEST_URL) - cache = json.dumps(c.auth_ref) - new_client = client.Client(auth_ref=json.loads(cache)) - self.assertIsNotNone(new_client.auth_ref) - self.assertFalse(new_client.auth_ref.domain_scoped) - self.assertTrue(new_client.auth_ref.project_scoped) - self.assertEqual(new_client.username, 'exampleuser') - self.assertIsNone(new_client.password) - self.assertEqual(new_client.management_url, - 'http://admin:35357/v3') - - def test_auth_ref_load_with_overridden_arguments(self): - new_auth_url = 'https://newkeystone.com/v3' - - self.stub_auth(json=client_fixtures.project_scoped_token()) - self.stub_auth(json=client_fixtures.project_scoped_token(), - base_url=new_auth_url) - - c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a', - password='password', - project_id='225da22d3ce34b15877ea70b2a575f58', - auth_url=self.TEST_URL) - cache = json.dumps(c.auth_ref) - new_client = client.Client(auth_ref=json.loads(cache), - auth_url=new_auth_url) - self.assertIsNotNone(new_client.auth_ref) - self.assertFalse(new_client.auth_ref.domain_scoped) - self.assertTrue(new_client.auth_ref.project_scoped) - self.assertEqual(new_client.auth_url, new_auth_url) - self.assertEqual(new_client.username, 'exampleuser') - self.assertIsNone(new_client.password) - self.assertEqual(new_client.management_url, - 'http://admin:35357/v3') - - def test_trust_init(self): - self.stub_auth(json=client_fixtures.trust_token()) - - c = client.Client(user_domain_name='exampledomain', - username='exampleuser', - password='password', - auth_url=self.TEST_URL, - trust_id='fe0aef') - self.assertIsNotNone(c.auth_ref) - self.assertFalse(c.auth_ref.domain_scoped) - self.assertFalse(c.auth_ref.project_scoped) - self.assertEqual(c.auth_ref.trust_id, 'fe0aef') - self.assertEqual(c.auth_ref.trustee_user_id, '0ca8f6') - self.assertEqual(c.auth_ref.trustor_user_id, 'bd263c') - self.assertTrue(c.auth_ref.trust_scoped) - self.assertEqual(c.auth_user_id, '0ca8f6') - - def test_init_err_no_auth_url(self): - self.assertRaises(exceptions.AuthorizationFailure, - client.Client, - username='exampleuser', - password='password') - - def _management_url_is_updated(self, fixture, **kwargs): - second = copy.deepcopy(fixture) - first_url = 'http://admin:35357/v3' - second_url = "http://secondurl:%d/v3'" - - for entry in second['token']['catalog']: - if entry['type'] == 'identity': - entry['endpoints'] = [{ - 'url': second_url % 5000, - 'region': 'RegionOne', - 'interface': 'public' - }, { - 'url': second_url % 5000, - 'region': 'RegionOne', - 'interface': 'internal' - }, { - 'url': second_url % 35357, - 'region': 'RegionOne', - 'interface': 'admin' - }] - - self.stub_auth(response_list=[{'json': fixture}, {'json': second}]) - - cl = client.Client(username='exampleuser', - password='password', - auth_url=self.TEST_URL, - **kwargs) - self.assertEqual(cl.management_url, first_url) - - cl.authenticate() - self.assertEqual(cl.management_url, second_url % 35357) - - def test_management_url_is_updated_with_project(self): - self._management_url_is_updated(client_fixtures.project_scoped_token(), - project_name='exampleproject') - - def test_management_url_is_updated_with_domain(self): - self._management_url_is_updated(client_fixtures.domain_scoped_token(), - domain_name='exampledomain') - - def test_client_with_region_name_passes_to_service_catalog(self): - # NOTE(jamielennox): this is deprecated behaviour that should be - # removed ASAP, however must remain compatible. - - self.stub_auth(json=client_fixtures.auth_response_body()) - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL, - region_name='North') - self.assertEqual(cl.service_catalog.url_for(service_type='image'), - 'http://glance.north.host/glanceapi/public') - - cl = client.Client(username='exampleuser', - password='password', - tenant_name='exampleproject', - auth_url=self.TEST_URL, - region_name='South') - self.assertEqual(cl.service_catalog.url_for(service_type='image'), - 'http://glance.south.host/glanceapi/public') - - def test_client_without_auth_params(self): - self.assertRaises(exceptions.AuthorizationFailure, - client.Client, - project_name='exampleproject', - auth_url=self.TEST_URL) - - def test_client_params(self): - opts = {'auth': token_endpoint.Token('a', 'b'), - 'connect_retries': 50, - 'endpoint_override': uuid.uuid4().hex, - 'interface': uuid.uuid4().hex, - 'region_name': uuid.uuid4().hex, - 'service_name': uuid.uuid4().hex, - 'user_agent': uuid.uuid4().hex, - } - - sess = session.Session() - cl = client.Client(session=sess, **opts) - - for k, v in six.iteritems(opts): - self.assertEqual(v, getattr(cl._adapter, k)) - - self.assertEqual('identity', cl._adapter.service_type) - self.assertEqual('v3', cl._adapter.version) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_credentials.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_credentials.py deleted file mode 100644 index 752f25ac52..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_credentials.py +++ /dev/null @@ -1,54 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import credentials - - -class CredentialTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(CredentialTests, self).setUp() - self.key = 'credential' - self.collection_key = 'credentials' - self.model = credentials.Credential - self.manager = self.client.credentials - - def new_ref(self, **kwargs): - kwargs = super(CredentialTests, self).new_ref(**kwargs) - kwargs.setdefault('blob', uuid.uuid4().hex) - kwargs.setdefault('project_id', uuid.uuid4().hex) - kwargs.setdefault('type', uuid.uuid4().hex) - kwargs.setdefault('user_id', uuid.uuid4().hex) - return kwargs - - @staticmethod - def _ref_data_not_blob(ref): - ret_ref = ref.copy() - ret_ref['data'] = ref['blob'] - del ret_ref['blob'] - return ret_ref - - def test_create_data_not_blob(self): - # Test create operation with previous, deprecated "data" argument, - # which should be translated into "blob" at the API call level - req_ref = self.new_ref() - api_ref = self._ref_data_not_blob(req_ref) - req_ref.pop('id') - self.test_create(api_ref, req_ref) - - def test_update_data_not_blob(self): - # Likewise test update operation with data instead of blob argument - req_ref = self.new_ref() - api_ref = self._ref_data_not_blob(req_ref) - self.test_update(api_ref, req_ref) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_discover.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_discover.py deleted file mode 100644 index ae88bb4572..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_discover.py +++ /dev/null @@ -1,80 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.generic import client -from keystoneclient.tests.unit.v3 import utils - - -class DiscoverKeystoneTests(utils.UnauthenticatedTestCase): - def setUp(self): - super(DiscoverKeystoneTests, self).setUp() - self.TEST_RESPONSE_DICT = { - "versions": { - "values": [{"id": "v3.0", - "status": "beta", - "updated": "2013-03-06T00:00:00Z", - "links": [ - {"rel": "self", - "href": "http://127.0.0.1:5000/v3.0/", }, - {"rel": "describedby", - "type": "text/html", - "href": "http://docs.openstack.org/api/" - "openstack-identity-service/3/" - "content/", }, - {"rel": "describedby", - "type": "application/pdf", - "href": "http://docs.openstack.org/api/" - "openstack-identity-service/3/" - "identity-dev-guide-3.pdf", }, - ]}, - {"id": "v2.0", - "status": "beta", - "updated": "2013-03-06T00:00:00Z", - "links": [ - {"rel": "self", - "href": "http://127.0.0.1:5000/v2.0/", }, - {"rel": "describedby", - "type": "text/html", - "href": "http://docs.openstack.org/api/" - "openstack-identity-service/2.0/" - "content/", }, - {"rel": "describedby", - "type": "application/pdf", - "href": "http://docs.openstack.org/api/" - "openstack-identity-service/2.0/" - "identity-dev-guide-2.0.pdf", } - ]}], - }, - } - self.TEST_REQUEST_HEADERS = { - 'User-Agent': 'python-keystoneclient', - 'Accept': 'application/json', - } - - def test_get_version_local(self): - self.requests_mock.get("http://localhost:35357/", - status_code=300, - json=self.TEST_RESPONSE_DICT) - - cs = client.Client() - versions = cs.discover() - self.assertIsInstance(versions, dict) - self.assertIn('message', versions) - self.assertIn('v3.0', versions) - self.assertEqual( - versions['v3.0']['url'], - self.TEST_RESPONSE_DICT['versions']['values'][0]['links'][0] - ['href']) - self.assertEqual( - versions['v2.0']['url'], - self.TEST_RESPONSE_DICT['versions']['values'][1]['links'][0] - ['href']) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_domains.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_domains.py deleted file mode 100644 index 9cc23e7eb1..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_domains.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import domains - - -class DomainTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(DomainTests, self).setUp() - self.key = 'domain' - self.collection_key = 'domains' - self.model = domains.Domain - self.manager = self.client.domains - - def new_ref(self, **kwargs): - kwargs = super(DomainTests, self).new_ref(**kwargs) - kwargs.setdefault('enabled', True) - kwargs.setdefault('name', uuid.uuid4().hex) - return kwargs - - def test_list_filter_name(self): - super(DomainTests, self).test_list(name='adomain123') - - def test_list_filter_enabled(self): - super(DomainTests, self).test_list(enabled=True) - - def test_list_filter_disabled(self): - # False is converted to '0' ref bug #1267530 - expected_query = {'enabled': '0'} - super(DomainTests, self).test_list(expected_query=expected_query, - enabled=False) - - def test_update_enabled_defaults_to_none(self): - super(DomainTests, self).test_update( - req_ref={'name': uuid.uuid4().hex}) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoint_filter.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoint_filter.py deleted file mode 100644 index eaca264c70..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoint_filter.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v3 import utils - - -class EndpointTestUtils(object): - """Mixin class with shared methods between Endpoint Filter & Policy.""" - - def new_ref(self, **kwargs): - # copied from CrudTests as we need to create endpoint and project - # refs for our tests. EndpointFilter is not exactly CRUD API. - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - return kwargs - - def new_endpoint_ref(self, **kwargs): - # copied from EndpointTests as we need endpoint refs for our tests - kwargs = self.new_ref(**kwargs) - kwargs.setdefault('interface', 'public') - kwargs.setdefault('region', uuid.uuid4().hex) - kwargs.setdefault('service_id', uuid.uuid4().hex) - kwargs.setdefault('url', uuid.uuid4().hex) - return kwargs - - -class EndpointFilterTests(utils.TestCase, EndpointTestUtils): - """Test project-endpoint associations (a.k.a. EndpointFilter Extension). - - Endpoint filter provides associations between service endpoints and - projects. These assciations are then used to create ad-hoc catalogs for - each project-scoped token request. - - """ - - def setUp(self): - super(EndpointFilterTests, self).setUp() - self.manager = self.client.endpoint_filter - - def new_project_ref(self, **kwargs): - # copied from ProjectTests as we need project refs for our tests - kwargs = self.new_ref(**kwargs) - kwargs.setdefault('domain_id', uuid.uuid4().hex) - kwargs.setdefault('name', uuid.uuid4().hex) - return kwargs - - def test_add_endpoint_to_project_via_id(self): - endpoint_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - - self.stub_url('PUT', - [self.manager.OS_EP_FILTER_EXT, 'projects', project_id, - 'endpoints', endpoint_id], - status_code=201) - - self.manager.add_endpoint_to_project(project=project_id, - endpoint=endpoint_id) - - def test_add_endpoint_to_project_via_obj(self): - project_ref = self.new_project_ref() - endpoint_ref = self.new_endpoint_ref() - project = self.client.projects.resource_class(self.client.projects, - project_ref, - loaded=True) - endpoint = self.client.endpoints.resource_class(self.client.endpoints, - endpoint_ref, - loaded=True) - - self.stub_url('PUT', - [self.manager.OS_EP_FILTER_EXT, - 'projects', project_ref['id'], - 'endpoints', endpoint_ref['id']], - status_code=201) - - self.manager.add_endpoint_to_project(project=project, - endpoint=endpoint) - - def test_delete_endpoint_from_project(self): - endpoint_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - - self.stub_url('DELETE', - [self.manager.OS_EP_FILTER_EXT, 'projects', project_id, - 'endpoints', endpoint_id], - status_code=201) - - self.manager.delete_endpoint_from_project(project=project_id, - endpoint=endpoint_id) - - def test_check_endpoint_in_project(self): - endpoint_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - - self.stub_url('HEAD', - [self.manager.OS_EP_FILTER_EXT, 'projects', project_id, - 'endpoints', endpoint_id], - status_code=201) - - self.manager.check_endpoint_in_project(project=project_id, - endpoint=endpoint_id) - - def test_list_endpoints_for_project(self): - project_id = uuid.uuid4().hex - endpoints = {'endpoints': [self.new_endpoint_ref(), - self.new_endpoint_ref()]} - self.stub_url('GET', - [self.manager.OS_EP_FILTER_EXT, 'projects', project_id, - 'endpoints'], - json=endpoints, - status_code=200) - - endpoints_resp = self.manager.list_endpoints_for_project( - project=project_id) - - expected_endpoint_ids = [ - endpoint['id'] for endpoint in endpoints['endpoints']] - actual_endpoint_ids = [endpoint.id for endpoint in endpoints_resp] - self.assertEqual(expected_endpoint_ids, actual_endpoint_ids) - - def test_list_projects_for_endpoint(self): - endpoint_id = uuid.uuid4().hex - projects = {'projects': [self.new_project_ref(), - self.new_project_ref()]} - self.stub_url('GET', - [self.manager.OS_EP_FILTER_EXT, 'endpoints', endpoint_id, - 'projects'], - json=projects, - status_code=200) - - projects_resp = self.manager.list_projects_for_endpoint( - endpoint=endpoint_id) - - expected_project_ids = [ - project['id'] for project in projects['projects']] - actual_project_ids = [project.id for project in projects_resp] - self.assertEqual(expected_project_ids, actual_project_ids) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoint_policy.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoint_policy.py deleted file mode 100644 index ce9efb4c60..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoint_policy.py +++ /dev/null @@ -1,242 +0,0 @@ -# Copyright 2014 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v3 import test_endpoint_filter -from keystoneclient.tests.unit.v3 import utils - - -class EndpointPolicyTests(utils.TestCase, - test_endpoint_filter.EndpointTestUtils): - """Test policy-endpoint associations (a.k.a. EndpointPolicy Extension).""" - - def setUp(self): - super(EndpointPolicyTests, self).setUp() - self.manager = self.client.endpoint_policy - - def new_policy_ref(self, **kwargs): - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault('type', uuid.uuid4().hex) - kwargs.setdefault('blob', uuid.uuid4().hex) - return kwargs - - def new_region_ref(self, **kwargs): - kwargs = self.new_ref(**kwargs) - return kwargs - - def new_service_ref(self, **kwargs): - kwargs = self.new_ref(**kwargs) - kwargs.setdefault('name', uuid.uuid4().hex) - kwargs.setdefault('type', uuid.uuid4().hex) - return kwargs - - def _crud_policy_association_for_endpoint_via_id( - self, http_action, manager_action): - policy_id = uuid.uuid4().hex - endpoint_id = uuid.uuid4().hex - - self.stub_url(http_action, - ['policies', policy_id, self.manager.OS_EP_POLICY_EXT, - 'endpoints', endpoint_id], - status_code=204) - manager_action(policy=policy_id, endpoint=endpoint_id) - - def _crud_policy_association_for_endpoint_via_obj( - self, http_action, manager_action): - policy_ref = self.new_policy_ref() - endpoint_ref = self.new_endpoint_ref() - policy = self.client.policies.resource_class( - self.client.policies, policy_ref, loaded=True) - endpoint = self.client.endpoints.resource_class( - self.client.endpoints, endpoint_ref, loaded=True) - - self.stub_url(http_action, - ['policies', policy_ref['id'], - self.manager.OS_EP_POLICY_EXT, - 'endpoints', endpoint_ref['id']], - status_code=204) - manager_action(policy=policy, endpoint=endpoint) - - def test_create_policy_association_for_endpoint_via_id(self): - self._crud_policy_association_for_endpoint_via_id( - 'PUT', self.manager.create_policy_association_for_endpoint) - - def test_create_policy_association_for_endpoint_via_obj(self): - self._crud_policy_association_for_endpoint_via_obj( - 'PUT', self.manager.create_policy_association_for_endpoint) - - def test_check_policy_association_for_endpoint_via_id(self): - self._crud_policy_association_for_endpoint_via_id( - 'HEAD', self.manager.check_policy_association_for_endpoint) - - def test_check_policy_association_for_endpoint_via_obj(self): - self._crud_policy_association_for_endpoint_via_obj( - 'HEAD', self.manager.check_policy_association_for_endpoint) - - def test_delete_policy_association_for_endpoint_via_id(self): - self._crud_policy_association_for_endpoint_via_id( - 'DELETE', self.manager.delete_policy_association_for_endpoint) - - def test_delete_policy_association_for_endpoint_via_obj(self): - self._crud_policy_association_for_endpoint_via_obj( - 'DELETE', self.manager.delete_policy_association_for_endpoint) - - def _crud_policy_association_for_service_via_id( - self, http_action, manager_action): - policy_id = uuid.uuid4().hex - service_id = uuid.uuid4().hex - - self.stub_url(http_action, - ['policies', policy_id, self.manager.OS_EP_POLICY_EXT, - 'services', service_id], - status_code=204) - manager_action(policy=policy_id, service=service_id) - - def _crud_policy_association_for_service_via_obj( - self, http_action, manager_action): - policy_ref = self.new_policy_ref() - service_ref = self.new_service_ref() - policy = self.client.policies.resource_class( - self.client.policies, policy_ref, loaded=True) - service = self.client.services.resource_class( - self.client.services, service_ref, loaded=True) - - self.stub_url(http_action, - ['policies', policy_ref['id'], - self.manager.OS_EP_POLICY_EXT, - 'services', service_ref['id']], - status_code=204) - manager_action(policy=policy, service=service) - - def test_create_policy_association_for_service_via_id(self): - self._crud_policy_association_for_service_via_id( - 'PUT', self.manager.create_policy_association_for_service) - - def test_create_policy_association_for_service_via_obj(self): - self._crud_policy_association_for_service_via_obj( - 'PUT', self.manager.create_policy_association_for_service) - - def test_check_policy_association_for_service_via_id(self): - self._crud_policy_association_for_service_via_id( - 'HEAD', self.manager.check_policy_association_for_service) - - def test_check_policy_association_for_service_via_obj(self): - self._crud_policy_association_for_service_via_obj( - 'HEAD', self.manager.check_policy_association_for_service) - - def test_delete_policy_association_for_service_via_id(self): - self._crud_policy_association_for_service_via_id( - 'DELETE', self.manager.delete_policy_association_for_service) - - def test_delete_policy_association_for_service_via_obj(self): - self._crud_policy_association_for_service_via_obj( - 'DELETE', self.manager.delete_policy_association_for_service) - - def _crud_policy_association_for_region_and_service_via_id( - self, http_action, manager_action): - policy_id = uuid.uuid4().hex - region_id = uuid.uuid4().hex - service_id = uuid.uuid4().hex - - self.stub_url(http_action, - ['policies', policy_id, self.manager.OS_EP_POLICY_EXT, - 'services', service_id, 'regions', region_id], - status_code=204) - manager_action(policy=policy_id, region=region_id, service=service_id) - - def _crud_policy_association_for_region_and_service_via_obj( - self, http_action, manager_action): - policy_ref = self.new_policy_ref() - region_ref = self.new_region_ref() - service_ref = self.new_service_ref() - policy = self.client.policies.resource_class( - self.client.policies, policy_ref, loaded=True) - region = self.client.regions.resource_class( - self.client.regions, region_ref, loaded=True) - service = self.client.services.resource_class( - self.client.services, service_ref, loaded=True) - - self.stub_url(http_action, - ['policies', policy_ref['id'], - self.manager.OS_EP_POLICY_EXT, - 'services', service_ref['id'], - 'regions', region_ref['id']], - status_code=204) - manager_action(policy=policy, region=region, service=service) - - def test_create_policy_association_for_region_and_service_via_id(self): - self._crud_policy_association_for_region_and_service_via_id( - 'PUT', - self.manager.create_policy_association_for_region_and_service) - - def test_create_policy_association_for_region_and_service_via_obj(self): - self._crud_policy_association_for_region_and_service_via_obj( - 'PUT', - self.manager.create_policy_association_for_region_and_service) - - def test_check_policy_association_for_region_and_service_via_id(self): - self._crud_policy_association_for_region_and_service_via_id( - 'HEAD', - self.manager.check_policy_association_for_region_and_service) - - def test_check_policy_association_for_region_and_service_via_obj(self): - self._crud_policy_association_for_region_and_service_via_obj( - 'HEAD', - self.manager.check_policy_association_for_region_and_service) - - def test_delete_policy_association_for_region_and_service_via_id(self): - self._crud_policy_association_for_region_and_service_via_id( - 'DELETE', - self.manager.delete_policy_association_for_region_and_service) - - def test_delete_policy_association_for_region_and_service_via_obj(self): - self._crud_policy_association_for_region_and_service_via_obj( - 'DELETE', - self.manager.delete_policy_association_for_region_and_service) - - def test_get_policy_for_endpoint(self): - endpoint_id = uuid.uuid4().hex - expected_policy = self.new_policy_ref() - - self.stub_url('GET', - ['endpoints', endpoint_id, self.manager.OS_EP_POLICY_EXT, - 'policy'], - json={'policy': expected_policy}, - status_code=200) - - policy_resp = self.manager.get_policy_for_endpoint( - endpoint=endpoint_id) - - self.assertEqual(expected_policy['id'], policy_resp.id) - self.assertEqual(expected_policy['blob'], policy_resp.blob) - self.assertEqual(expected_policy['type'], policy_resp.type) - - def test_list_endpoints_for_policy(self): - policy_id = uuid.uuid4().hex - endpoints = {'endpoints': [self.new_endpoint_ref(), - self.new_endpoint_ref()]} - self.stub_url('GET', - ['policies', policy_id, self.manager.OS_EP_POLICY_EXT, - 'endpoints'], - json=endpoints, - status_code=200) - - endpoints_resp = self.manager.list_endpoints_for_policy( - policy=policy_id) - - expected_endpoint_ids = [ - endpoint['id'] for endpoint in endpoints['endpoints']] - actual_endpoint_ids = [endpoint.id for endpoint in endpoints_resp] - self.assertEqual(expected_endpoint_ids, actual_endpoint_ids) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoints.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoints.py deleted file mode 100644 index 000718a686..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_endpoints.py +++ /dev/null @@ -1,91 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import endpoints - - -class EndpointTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(EndpointTests, self).setUp() - self.key = 'endpoint' - self.collection_key = 'endpoints' - self.model = endpoints.Endpoint - self.manager = self.client.endpoints - - def new_ref(self, **kwargs): - kwargs = super(EndpointTests, self).new_ref(**kwargs) - kwargs.setdefault('interface', 'public') - kwargs.setdefault('region', uuid.uuid4().hex) - kwargs.setdefault('service_id', uuid.uuid4().hex) - kwargs.setdefault('url', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - return kwargs - - def test_create_public_interface(self): - ref = self.new_ref(interface='public') - self.test_create(ref) - - def test_create_admin_interface(self): - ref = self.new_ref(interface='admin') - self.test_create(ref) - - def test_create_internal_interface(self): - ref = self.new_ref(interface='internal') - self.test_create(ref) - - def test_create_invalid_interface(self): - ref = self.new_ref(interface=uuid.uuid4().hex) - self.assertRaises(exceptions.ValidationError, self.manager.create, - **utils.parameterize(ref)) - - def test_update_public_interface(self): - ref = self.new_ref(interface='public') - self.test_update(ref) - - def test_update_admin_interface(self): - ref = self.new_ref(interface='admin') - self.test_update(ref) - - def test_update_internal_interface(self): - ref = self.new_ref(interface='internal') - self.test_update(ref) - - def test_update_invalid_interface(self): - ref = self.new_ref(interface=uuid.uuid4().hex) - ref['endpoint'] = "fake_endpoint" - self.assertRaises(exceptions.ValidationError, self.manager.update, - **utils.parameterize(ref)) - - def test_list_public_interface(self): - interface = 'public' - expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) - self.test_list(expected_path=expected_path, interface=interface) - - def test_list_admin_interface(self): - interface = 'admin' - expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) - self.test_list(expected_path=expected_path, interface=interface) - - def test_list_internal_interface(self): - interface = 'admin' - expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) - self.test_list(expected_path=expected_path, interface=interface) - - def test_list_invalid_interface(self): - interface = uuid.uuid4().hex - expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) - self.assertRaises(exceptions.ValidationError, self.manager.list, - expected_path=expected_path, interface=interface) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_federation.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_federation.py deleted file mode 100644 index ff219cc080..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_federation.py +++ /dev/null @@ -1,469 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import uuid - -from keystoneclient import access -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3.contrib.federation import base -from keystoneclient.v3.contrib.federation import identity_providers -from keystoneclient.v3.contrib.federation import mappings -from keystoneclient.v3.contrib.federation import protocols -from keystoneclient.v3.contrib.federation import service_providers -from keystoneclient.v3 import domains -from keystoneclient.v3 import projects - - -class IdentityProviderTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(IdentityProviderTests, self).setUp() - self.key = 'identity_provider' - self.collection_key = 'identity_providers' - self.model = identity_providers.IdentityProvider - self.manager = self.client.federation.identity_providers - self.path_prefix = 'OS-FEDERATION' - - def new_ref(self, **kwargs): - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault('description', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - return kwargs - - def test_positional_parameters_expect_fail(self): - """Ensure CrudManager raises TypeError exceptions. - - After passing wrong number of positional arguments - an exception should be raised. - - Operations to be tested: - * create() - * get() - * list() - * delete() - * update() - - """ - POS_PARAM_1 = uuid.uuid4().hex - POS_PARAM_2 = uuid.uuid4().hex - POS_PARAM_3 = uuid.uuid4().hex - - PARAMETERS = { - 'create': (POS_PARAM_1, POS_PARAM_2), - 'get': (POS_PARAM_1, POS_PARAM_2), - 'list': (POS_PARAM_1, POS_PARAM_2), - 'update': (POS_PARAM_1, POS_PARAM_2, POS_PARAM_3), - 'delete': (POS_PARAM_1, POS_PARAM_2) - } - - for f_name, args in PARAMETERS.items(): - self.assertRaises(TypeError, getattr(self.manager, f_name), - *args) - - def test_create(self): - ref = self.new_ref() - req_ref = ref.copy() - req_ref.pop('id') - - self.stub_entity('PUT', entity=ref, id=ref['id'], status_code=201) - - returned = self.manager.create(**ref) - self.assertIsInstance(returned, self.model) - for attr in req_ref: - self.assertEqual( - getattr(returned, attr), - req_ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) - - -class MappingTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(MappingTests, self).setUp() - self.key = 'mapping' - self.collection_key = 'mappings' - self.model = mappings.Mapping - self.manager = self.client.federation.mappings - self.path_prefix = 'OS-FEDERATION' - - def new_ref(self, **kwargs): - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault('rules', [uuid.uuid4().hex, - uuid.uuid4().hex]) - return kwargs - - def test_create(self): - ref = self.new_ref() - manager_ref = ref.copy() - mapping_id = manager_ref.pop('id') - req_ref = ref.copy() - - self.stub_entity('PUT', entity=req_ref, id=mapping_id, - status_code=201) - - returned = self.manager.create(mapping_id=mapping_id, **manager_ref) - self.assertIsInstance(returned, self.model) - for attr in req_ref: - self.assertEqual( - getattr(returned, attr), - req_ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(manager_ref) - - -class ProtocolTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(ProtocolTests, self).setUp() - self.key = 'protocol' - self.collection_key = 'protocols' - self.model = protocols.Protocol - self.manager = self.client.federation.protocols - self.path_prefix = 'OS-FEDERATION/identity_providers' - - def _transform_to_response(self, ref): - """Rebuild dictionary so it can be used as a - reference response body. - - """ - response = copy.deepcopy(ref) - response['id'] = response.pop('protocol_id') - del response['identity_provider'] - return response - - def new_ref(self, **kwargs): - kwargs.setdefault('mapping', uuid.uuid4().hex) - kwargs.setdefault('identity_provider', uuid.uuid4().hex) - kwargs.setdefault('protocol_id', uuid.uuid4().hex) - return kwargs - - def build_parts(self, identity_provider, protocol_id=None): - """Build array used to construct mocking URL. - - Construct and return array with URL parts later used - by methods like utils.TestCase.stub_entity(). - Example of URL: - ``OS-FEDERATION/identity_providers/{idp_id}/ - protocols/{protocol_id}`` - - """ - parts = ['OS-FEDERATION', 'identity_providers', - identity_provider, 'protocols'] - if protocol_id: - parts.append(protocol_id) - return parts - - def test_build_url_provide_base_url(self): - base_url = uuid.uuid4().hex - parameters = {'base_url': base_url} - url = self.manager.build_url(dict_args_in_out=parameters) - self.assertEqual('/'.join([base_url, self.collection_key]), url) - - def test_build_url_w_idp_id(self): - """Test whether kwargs ``base_url`` discards object's base_url - - This test shows, that when ``base_url`` is specified in the - dict_args_in_out dictionary, values like ``identity_provider_id`` - are not taken into consideration while building the url. - - """ - base_url, identity_provider_id = uuid.uuid4().hex, uuid.uuid4().hex - parameters = { - 'base_url': base_url, - 'identity_provider_id': identity_provider_id - } - url = self.manager.build_url(dict_args_in_out=parameters) - self.assertEqual('/'.join([base_url, self.collection_key]), url) - - def test_build_url_default_base_url(self): - identity_provider_id = uuid.uuid4().hex - parameters = { - 'identity_provider_id': identity_provider_id - } - - url = self.manager.build_url(dict_args_in_out=parameters) - self.assertEqual( - '/'.join([self.manager.base_url, identity_provider_id, - self.manager.collection_key]), url) - - def test_create(self): - """Test creating federation protocol tied to an Identity Provider. - - URL to be tested: PUT /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - """ - request_args = self.new_ref() - expected = self._transform_to_response(request_args) - parts = self.build_parts(request_args['identity_provider'], - request_args['protocol_id']) - self.stub_entity('PUT', entity=expected, - parts=parts, status_code=201) - returned = self.manager.create(**request_args) - self.assertEqual(expected, returned.to_dict()) - request_body = {'mapping_id': request_args['mapping']} - self.assertEntityRequestBodyIs(request_body) - - def test_get(self): - """Fetch federation protocol object. - - URL to be tested: GET /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - """ - request_args = self.new_ref() - expected = self._transform_to_response(request_args) - - parts = self.build_parts(request_args['identity_provider'], - request_args['protocol_id']) - self.stub_entity('GET', entity=expected, - parts=parts, status_code=201) - - returned = self.manager.get(request_args['identity_provider'], - request_args['protocol_id']) - self.assertIsInstance(returned, self.model) - self.assertEqual(expected, returned.to_dict()) - - def test_delete(self): - """Delete federation protocol object. - - URL to be tested: DELETE /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - """ - request_args = self.new_ref() - parts = self.build_parts(request_args['identity_provider'], - request_args['protocol_id']) - - self.stub_entity('DELETE', parts=parts, status_code=204) - - self.manager.delete(request_args['identity_provider'], - request_args['protocol_id']) - - def test_list(self): - """Test listing all federation protocols tied to the Identity Provider. - - URL to be tested: GET /OS-FEDERATION/identity_providers/ - $identity_provider/protocols - - """ - def _ref_protocols(): - return { - 'id': uuid.uuid4().hex, - 'mapping_id': uuid.uuid4().hex - } - - request_args = self.new_ref() - expected = [_ref_protocols() for _ in range(3)] - parts = self.build_parts(request_args['identity_provider']) - self.stub_entity('GET', parts=parts, - entity=expected, status_code=200) - - returned = self.manager.list(request_args['identity_provider']) - for obj, ref_obj in zip(returned, expected): - self.assertEqual(obj.to_dict(), ref_obj) - - def test_list_params(self): - request_args = self.new_ref() - filter_kwargs = {uuid.uuid4().hex: uuid.uuid4().hex} - parts = self.build_parts(request_args['identity_provider']) - - # Return HTTP 401 as we don't accept such requests. - self.stub_entity('GET', parts=parts, status_code=401) - self.assertRaises(exceptions.Unauthorized, - self.manager.list, - request_args['identity_provider'], - **filter_kwargs) - self.assertQueryStringContains(**filter_kwargs) - - def test_update(self): - """Test updating federation protocol - - URL to be tested: PATCH /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - """ - request_args = self.new_ref() - expected = self._transform_to_response(request_args) - - parts = self.build_parts(request_args['identity_provider'], - request_args['protocol_id']) - - self.stub_entity('PATCH', parts=parts, - entity=expected, status_code=200) - - returned = self.manager.update(request_args['identity_provider'], - request_args['protocol_id'], - mapping=request_args['mapping']) - self.assertIsInstance(returned, self.model) - self.assertEqual(expected, returned.to_dict()) - request_body = {'mapping_id': request_args['mapping']} - self.assertEntityRequestBodyIs(request_body) - - -class EntityManagerTests(utils.TestCase): - def test_create_object_expect_fail(self): - self.assertRaises(TypeError, - base.EntityManager, - self.client) - - -class FederationProjectTests(utils.TestCase): - - def setUp(self): - super(FederationProjectTests, self).setUp() - self.key = 'project' - self.collection_key = 'projects' - self.model = projects.Project - self.manager = self.client.federation.projects - self.URL = "%s%s" % (self.TEST_URL, '/OS-FEDERATION/projects') - - def new_ref(self, **kwargs): - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault('domain_id', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - kwargs.setdefault('name', uuid.uuid4().hex) - return kwargs - - def test_list_accessible_projects(self): - projects_ref = [self.new_ref(), self.new_ref()] - projects_json = { - self.collection_key: [self.new_ref(), self.new_ref()] - } - self.requests_mock.get(self.URL, json=projects_json) - returned_list = self.manager.list() - - self.assertEqual(len(projects_ref), len(returned_list)) - for project in returned_list: - self.assertIsInstance(project, self.model) - - -class FederationDomainTests(utils.TestCase): - - def setUp(self): - super(FederationDomainTests, self).setUp() - self.key = 'domain' - self.collection_key = 'domains' - self.model = domains.Domain - self.manager = self.client.federation.domains - - self.URL = "%s%s" % (self.TEST_URL, '/OS-FEDERATION/domains') - - def new_ref(self, **kwargs): - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - kwargs.setdefault('name', uuid.uuid4().hex) - kwargs.setdefault('description', uuid.uuid4().hex) - return kwargs - - def test_list_accessible_domains(self): - domains_ref = [self.new_ref(), self.new_ref()] - domains_json = { - self.collection_key: domains_ref - } - self.requests_mock.get(self.URL, json=domains_json) - returned_list = self.manager.list() - self.assertEqual(len(domains_ref), len(returned_list)) - for domain in returned_list: - self.assertIsInstance(domain, self.model) - - -class FederatedTokenTests(utils.TestCase): - - def setUp(self): - super(FederatedTokenTests, self).setUp() - token = fixture.V3FederationToken() - token.set_project_scope() - token.add_role() - self.federated_token = access.AccessInfo.factory(body=token) - - def test_federated_property_federated_token(self): - """Check if is_federated property returns expected value.""" - self.assertTrue(self.federated_token.is_federated) - - def test_get_user_domain_name(self): - """Ensure a federated user's domain name does not exist.""" - self.assertIsNone(self.federated_token.user_domain_name) - - def test_get_user_domain_id(self): - """Ensure a federated user's domain ID does not exist.""" - self.assertIsNone(self.federated_token.user_domain_id) - - -class ServiceProviderTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(ServiceProviderTests, self).setUp() - self.key = 'service_provider' - self.collection_key = 'service_providers' - self.model = service_providers.ServiceProvider - self.manager = self.client.federation.service_providers - self.path_prefix = 'OS-FEDERATION' - - def new_ref(self, **kwargs): - kwargs.setdefault('auth_url', uuid.uuid4().hex) - kwargs.setdefault('description', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault('sp_url', uuid.uuid4().hex) - return kwargs - - def test_positional_parameters_expect_fail(self): - """Ensure CrudManager raises TypeError exceptions. - - After passing wrong number of positional arguments - an exception should be raised. - - Operations to be tested: - * create() - * get() - * list() - * delete() - * update() - - """ - POS_PARAM_1 = uuid.uuid4().hex - POS_PARAM_2 = uuid.uuid4().hex - POS_PARAM_3 = uuid.uuid4().hex - - PARAMETERS = { - 'create': (POS_PARAM_1, POS_PARAM_2), - 'get': (POS_PARAM_1, POS_PARAM_2), - 'list': (POS_PARAM_1, POS_PARAM_2), - 'update': (POS_PARAM_1, POS_PARAM_2, POS_PARAM_3), - 'delete': (POS_PARAM_1, POS_PARAM_2) - } - - for f_name, args in PARAMETERS.items(): - self.assertRaises(TypeError, getattr(self.manager, f_name), - *args) - - def test_create(self): - ref = self.new_ref() - - # req_ref argument allows you to specify a different - # signature for the request when the manager does some - # conversion before doing the request (e.g. converting - # from datetime object to timestamp string) - req_ref = ref.copy() - req_ref.pop('id') - - self.stub_entity('PUT', entity=ref, id=ref['id'], status_code=201) - - returned = self.manager.create(**ref) - self.assertIsInstance(returned, self.model) - for attr in req_ref: - self.assertEqual( - getattr(returned, attr), - req_ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_groups.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_groups.py deleted file mode 100644 index 6ed140cef2..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_groups.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import groups - - -class GroupTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(GroupTests, self).setUp() - self.key = 'group' - self.collection_key = 'groups' - self.model = groups.Group - self.manager = self.client.groups - - def new_ref(self, **kwargs): - kwargs = super(GroupTests, self).new_ref(**kwargs) - kwargs.setdefault('name', uuid.uuid4().hex) - return kwargs - - def test_list_groups_for_user(self): - user_id = uuid.uuid4().hex - ref_list = [self.new_ref(), self.new_ref()] - - self.stub_entity('GET', - ['users', user_id, self.collection_key], - status_code=200, entity=ref_list) - - returned_list = self.manager.list(user=user_id) - self.assertEqual(len(ref_list), len(returned_list)) - [self.assertIsInstance(r, self.model) for r in returned_list] - - def test_list_groups_for_domain(self): - ref_list = [self.new_ref(), self.new_ref()] - domain_id = uuid.uuid4().hex - - self.stub_entity('GET', - [self.collection_key], - status_code=200, entity=ref_list) - - returned_list = self.manager.list(domain=domain_id) - self.assertTrue(len(ref_list), len(returned_list)) - [self.assertIsInstance(r, self.model) for r in returned_list] - - self.assertQueryStringIs('domain_id=%s' % domain_id) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_oauth1.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_oauth1.py deleted file mode 100644 index b52a75981c..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_oauth1.py +++ /dev/null @@ -1,298 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import uuid - -import mock -from oslo_utils import timeutils -import six -from six.moves.urllib import parse as urlparse -from testtools import matchers - -from keystoneclient import session -from keystoneclient.tests.unit.v3 import client_fixtures -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3.contrib.oauth1 import access_tokens -from keystoneclient.v3.contrib.oauth1 import auth -from keystoneclient.v3.contrib.oauth1 import consumers -from keystoneclient.v3.contrib.oauth1 import request_tokens - -try: - import oauthlib - from oauthlib import oauth1 -except ImportError: - oauth1 = None - - -class BaseTest(utils.TestCase): - def setUp(self): - super(BaseTest, self).setUp() - if oauth1 is None: - self.skipTest('oauthlib package not available') - - -class ConsumerTests(BaseTest, utils.CrudTests): - def setUp(self): - super(ConsumerTests, self).setUp() - self.key = 'consumer' - self.collection_key = 'consumers' - self.model = consumers.Consumer - self.manager = self.client.oauth1.consumers - self.path_prefix = 'OS-OAUTH1' - - def new_ref(self, **kwargs): - kwargs = super(ConsumerTests, self).new_ref(**kwargs) - kwargs.setdefault('description', uuid.uuid4().hex) - return kwargs - - def test_description_is_optional(self): - consumer_id = uuid.uuid4().hex - resp_ref = {'consumer': {'description': None, - 'id': consumer_id}} - - self.stub_url('POST', - [self.path_prefix, self.collection_key], - status_code=201, json=resp_ref) - - consumer = self.manager.create() - self.assertEqual(consumer_id, consumer.id) - self.assertIsNone(consumer.description) - - def test_description_not_included(self): - consumer_id = uuid.uuid4().hex - resp_ref = {'consumer': {'id': consumer_id}} - - self.stub_url('POST', - [self.path_prefix, self.collection_key], - status_code=201, json=resp_ref) - - consumer = self.manager.create() - self.assertEqual(consumer_id, consumer.id) - - -class TokenTests(BaseTest): - def _new_oauth_token(self): - key = uuid.uuid4().hex - secret = uuid.uuid4().hex - params = {'oauth_token': key, 'oauth_token_secret': secret} - token = urlparse.urlencode(params) - return (key, secret, token) - - def _new_oauth_token_with_expires_at(self): - key, secret, token = self._new_oauth_token() - expires_at = timeutils.strtime() - params = {'oauth_token': key, - 'oauth_token_secret': secret, - 'oauth_expires_at': expires_at} - token = urlparse.urlencode(params) - return (key, secret, expires_at, token) - - def _validate_oauth_headers(self, auth_header, oauth_client): - """Assert that the data in the headers matches the data - that is produced from oauthlib. - """ - - self.assertThat(auth_header, matchers.StartsWith('OAuth ')) - auth_header = auth_header[len('OAuth '):] - # NOTE(stevemar): In newer versions of oauthlib there is - # an additional argument for getting oauth parameters. - # Adding a conditional here to revert back to no arguments - # if an earlier version is detected. - if tuple(oauthlib.__version__.split('.')) > ('0', '6', '1'): - header_params = oauth_client.get_oauth_params(None) - else: - header_params = oauth_client.get_oauth_params() - parameters = dict(header_params) - - self.assertEqual('HMAC-SHA1', parameters['oauth_signature_method']) - self.assertEqual('1.0', parameters['oauth_version']) - self.assertIsInstance(parameters['oauth_nonce'], six.string_types) - self.assertEqual(oauth_client.client_key, - parameters['oauth_consumer_key']) - if oauth_client.resource_owner_key: - self.assertEqual(oauth_client.resource_owner_key, - parameters['oauth_token'],) - if oauth_client.verifier: - self.assertEqual(oauth_client.verifier, - parameters['oauth_verifier']) - if oauth_client.callback_uri: - self.assertEqual(oauth_client.callback_uri, - parameters['oauth_callback']) - if oauth_client.timestamp: - self.assertEqual(oauth_client.timestamp, - parameters['oauth_timestamp']) - return parameters - - -class RequestTokenTests(TokenTests): - def setUp(self): - super(RequestTokenTests, self).setUp() - self.model = request_tokens.RequestToken - self.manager = self.client.oauth1.request_tokens - self.path_prefix = 'OS-OAUTH1' - - def test_authorize_request_token(self): - request_key = uuid.uuid4().hex - info = {'id': request_key, - 'key': request_key, - 'secret': uuid.uuid4().hex} - request_token = request_tokens.RequestToken(self.manager, info) - - verifier = uuid.uuid4().hex - resp_ref = {'token': {'oauth_verifier': verifier}} - self.stub_url('PUT', - [self.path_prefix, 'authorize', request_key], - status_code=200, json=resp_ref) - - # Assert the manager is returning the expected data - role_id = uuid.uuid4().hex - token = request_token.authorize([role_id]) - self.assertEqual(verifier, token.oauth_verifier) - - # Assert that the request was sent in the expected structure - exp_body = {'roles': [{'id': role_id}]} - self.assertRequestBodyIs(json=exp_body) - - def test_create_request_token(self): - project_id = uuid.uuid4().hex - consumer_key = uuid.uuid4().hex - consumer_secret = uuid.uuid4().hex - - request_key, request_secret, resp_ref = self._new_oauth_token() - - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - self.stub_url('POST', [self.path_prefix, 'request_token'], - status_code=201, text=resp_ref, headers=headers) - - # Assert the manager is returning request token object - request_token = self.manager.create(consumer_key, consumer_secret, - project_id) - self.assertIsInstance(request_token, self.model) - self.assertEqual(request_key, request_token.key) - self.assertEqual(request_secret, request_token.secret) - - # Assert that the project id is in the header - self.assertRequestHeaderEqual('requested-project-id', project_id) - req_headers = self.requests_mock.last_request.headers - - oauth_client = oauth1.Client(consumer_key, - client_secret=consumer_secret, - signature_method=oauth1.SIGNATURE_HMAC, - callback_uri="oob") - self._validate_oauth_headers(req_headers['Authorization'], - oauth_client) - - -class AccessTokenTests(TokenTests): - def setUp(self): - super(AccessTokenTests, self).setUp() - self.manager = self.client.oauth1.access_tokens - self.model = access_tokens.AccessToken - self.path_prefix = 'OS-OAUTH1' - - def test_create_access_token_expires_at(self): - verifier = uuid.uuid4().hex - consumer_key = uuid.uuid4().hex - consumer_secret = uuid.uuid4().hex - request_key = uuid.uuid4().hex - request_secret = uuid.uuid4().hex - - t = self._new_oauth_token_with_expires_at() - access_key, access_secret, expires_at, resp_ref = t - - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - self.stub_url('POST', [self.path_prefix, 'access_token'], - status_code=201, text=resp_ref, headers=headers) - - # Assert that the manager creates an access token object - access_token = self.manager.create(consumer_key, consumer_secret, - request_key, request_secret, - verifier) - self.assertIsInstance(access_token, self.model) - self.assertEqual(access_key, access_token.key) - self.assertEqual(access_secret, access_token.secret) - self.assertEqual(expires_at, access_token.expires) - - req_headers = self.requests_mock.last_request.headers - oauth_client = oauth1.Client(consumer_key, - client_secret=consumer_secret, - resource_owner_key=request_key, - resource_owner_secret=request_secret, - signature_method=oauth1.SIGNATURE_HMAC, - verifier=verifier, - timestamp=expires_at) - self._validate_oauth_headers(req_headers['Authorization'], - oauth_client) - - -class AuthenticateWithOAuthTests(TokenTests): - def setUp(self): - super(AuthenticateWithOAuthTests, self).setUp() - if oauth1 is None: - self.skipTest('optional package oauthlib is not installed') - - def test_oauth_authenticate_success(self): - consumer_key = uuid.uuid4().hex - consumer_secret = uuid.uuid4().hex - access_key = uuid.uuid4().hex - access_secret = uuid.uuid4().hex - - # Just use an existing project scoped token and change - # the methods to oauth1, and add an OS-OAUTH1 section. - oauth_token = client_fixtures.project_scoped_token() - oauth_token['methods'] = ["oauth1"] - oauth_token['OS-OAUTH1'] = {"consumer_id": consumer_key, - "access_token_id": access_key} - self.stub_auth(json=oauth_token) - - a = auth.OAuth(self.TEST_URL, consumer_key=consumer_key, - consumer_secret=consumer_secret, - access_key=access_key, - access_secret=access_secret) - s = session.Session(auth=a) - t = s.get_token() - self.assertEqual(self.TEST_TOKEN, t) - - OAUTH_REQUEST_BODY = { - "auth": { - "identity": { - "methods": ["oauth1"], - "oauth1": {} - } - } - } - - self.assertRequestBodyIs(json=OAUTH_REQUEST_BODY) - - # Assert that the headers have the same oauthlib data - req_headers = self.requests_mock.last_request.headers - oauth_client = oauth1.Client(consumer_key, - client_secret=consumer_secret, - resource_owner_key=access_key, - resource_owner_secret=access_secret, - signature_method=oauth1.SIGNATURE_HMAC) - self._validate_oauth_headers(req_headers['Authorization'], - oauth_client) - - -class TestOAuthLibModule(utils.TestCase): - - def test_no_oauthlib_installed(self): - with mock.patch.object(auth, 'oauth1', None): - self.assertRaises(NotImplementedError, - auth.OAuth, - self.TEST_URL, - consumer_key=uuid.uuid4().hex, - consumer_secret=uuid.uuid4().hex, - access_key=uuid.uuid4().hex, - access_secret=uuid.uuid4().hex) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_policies.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_policies.py deleted file mode 100644 index a7f8d8afdc..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_policies.py +++ /dev/null @@ -1,31 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import policies - - -class PolicyTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(PolicyTests, self).setUp() - self.key = 'policy' - self.collection_key = 'policies' - self.model = policies.Policy - self.manager = self.client.policies - - def new_ref(self, **kwargs): - kwargs = super(PolicyTests, self).new_ref(**kwargs) - kwargs.setdefault('type', uuid.uuid4().hex) - kwargs.setdefault('blob', uuid.uuid4().hex) - return kwargs diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_projects.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_projects.py deleted file mode 100644 index 61a5ef17be..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_projects.py +++ /dev/null @@ -1,313 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import projects - - -class ProjectTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(ProjectTests, self).setUp() - self.key = 'project' - self.collection_key = 'projects' - self.model = projects.Project - self.manager = self.client.projects - - def new_ref(self, **kwargs): - kwargs = super(ProjectTests, self).new_ref(**kwargs) - return self._new_project_ref(ref=kwargs) - - def _new_project_ref(self, ref=None): - ref = ref or {} - ref.setdefault('domain_id', uuid.uuid4().hex) - ref.setdefault('enabled', True) - ref.setdefault('name', uuid.uuid4().hex) - return ref - - def test_list_projects_for_user(self): - ref_list = [self.new_ref(), self.new_ref()] - user_id = uuid.uuid4().hex - - self.stub_entity('GET', - ['users', user_id, self.collection_key], - entity=ref_list) - - returned_list = self.manager.list(user=user_id) - self.assertEqual(len(ref_list), len(returned_list)) - [self.assertIsInstance(r, self.model) for r in returned_list] - - def test_list_projects_for_domain(self): - ref_list = [self.new_ref(), self.new_ref()] - domain_id = uuid.uuid4().hex - - self.stub_entity('GET', [self.collection_key], - entity=ref_list) - - returned_list = self.manager.list(domain=domain_id) - self.assertEqual(len(ref_list), len(returned_list)) - [self.assertIsInstance(r, self.model) for r in returned_list] - - self.assertQueryStringIs('domain_id=%s' % domain_id) - - def test_create_with_parent(self): - parent_ref = self.new_ref() - parent_ref['parent_id'] = uuid.uuid4().hex - parent = self.test_create(ref=parent_ref) - parent.id = parent_ref['id'] - - # Create another project under 'parent' in the hierarchy - ref = self.new_ref() - ref['parent_id'] = parent.id - - child_ref = ref.copy() - del child_ref['parent_id'] - child_ref['parent'] = parent - - # test_create() pops the 'id' of the mocked response - del ref['id'] - - # Resource objects may peform lazy-loading. The create() method of - # ProjectManager will try to access the 'uuid' attribute of the parent - # object, which will trigger a call to fetch the Resource attributes. - self.stub_entity('GET', id=parent_ref['id'], entity=parent_ref) - self.test_create(ref=child_ref, req_ref=ref) - - def test_create_with_parent_id(self): - ref = self._new_project_ref() - ref['parent_id'] = uuid.uuid4().hex - - self.stub_entity('POST', entity=ref, status_code=201) - - returned = self.manager.create(name=ref['name'], - domain=ref['domain_id'], - parent_id=ref['parent_id']) - - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(ref) - - def test_create_with_parent_and_parent_id(self): - ref = self._new_project_ref() - ref['parent_id'] = uuid.uuid4().hex - - self.stub_entity('POST', entity=ref, status_code=201) - - # Should ignore the 'parent_id' argument since we are also passing - # 'parent' - returned = self.manager.create(name=ref['name'], - domain=ref['domain_id'], - parent=ref['parent_id'], - parent_id=uuid.uuid4().hex) - - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(ref) - - def _create_projects_hierarchy(self, hierarchy_size=3): - """Creates a project hierarchy with specified size. - - :param hierarchy_size: the desired hierarchy size, default is 3. - - :returns: a list of the projects in the created hierarchy. - - """ - - ref = self.new_ref() - project_id = ref['id'] - projects = [ref] - - for i in range(1, hierarchy_size): - new_ref = self.new_ref() - new_ref['parent_id'] = project_id - projects.append(new_ref) - project_id = new_ref['id'] - - return projects - - def test_get_with_subtree_as_ids(self): - projects = self._create_projects_hierarchy() - ref = projects[0] - - # We will query for projects[0] subtree, it should include projects[1] - # and projects[2] structured like the following: - # { - # projects[1]: { - # projects[2]: None - # } - # } - ref['subtree'] = { - projects[1]['id']: { - projects[2]['id']: None - } - } - - self.stub_entity('GET', id=ref['id'], entity=ref) - - returned = self.manager.get(ref['id'], subtree_as_ids=True) - self.assertQueryStringIs('subtree_as_ids') - self.assertDictEqual(ref['subtree'], returned.subtree) - - def test_get_with_parents_as_ids(self): - projects = self._create_projects_hierarchy() - ref = projects[2] - - # We will query for projects[2] parents, it should include projects[1] - # and projects[0] structured like the following: - # { - # projects[1]: { - # projects[0]: None - # } - # } - ref['parents'] = { - projects[1]['id']: { - projects[0]['id']: None - } - } - - self.stub_entity('GET', id=ref['id'], entity=ref) - - returned = self.manager.get(ref['id'], parents_as_ids=True) - self.assertQueryStringIs('parents_as_ids') - self.assertDictEqual(ref['parents'], returned.parents) - - def test_get_with_parents_as_ids_and_subtree_as_ids(self): - ref = self.new_ref() - projects = self._create_projects_hierarchy() - ref = projects[1] - - # We will query for projects[1] subtree and parents. The subtree should - # include projects[2] and the parents should include projects[2]. - ref['parents'] = { - projects[0]['id']: None - } - ref['subtree'] = { - projects[2]['id']: None - } - - self.stub_entity('GET', id=ref['id'], entity=ref) - - returned = self.manager.get(ref['id'], - parents_as_ids=True, - subtree_as_ids=True) - self.assertQueryStringIs('subtree_as_ids&parents_as_ids') - self.assertDictEqual(ref['parents'], returned.parents) - self.assertDictEqual(ref['subtree'], returned.subtree) - - def test_get_with_subtree_as_list(self): - projects = self._create_projects_hierarchy() - ref = projects[0] - - ref['subtree_as_list'] = [] - for i in range(1, len(projects)): - ref['subtree_as_list'].append(projects[i]) - - self.stub_entity('GET', id=ref['id'], entity=ref) - - returned = self.manager.get(ref['id'], subtree_as_list=True) - self.assertQueryStringIs('subtree_as_list') - for i in range(1, len(projects)): - for attr in projects[i]: - child = getattr(returned, 'subtree_as_list')[i - 1] - self.assertEqual( - child[attr], - projects[i][attr], - 'Expected different %s' % attr) - - def test_get_with_parents_as_list(self): - projects = self._create_projects_hierarchy() - ref = projects[2] - - ref['parents_as_list'] = [] - for i in range(0, len(projects) - 1): - ref['parents_as_list'].append(projects[i]) - - self.stub_entity('GET', id=ref['id'], entity=ref) - - returned = self.manager.get(ref['id'], parents_as_list=True) - self.assertQueryStringIs('parents_as_list') - for i in range(0, len(projects) - 1): - for attr in projects[i]: - parent = getattr(returned, 'parents_as_list')[i] - self.assertEqual( - parent[attr], - projects[i][attr], - 'Expected different %s' % attr) - - def test_get_with_parents_as_list_and_subtree_as_list(self): - ref = self.new_ref() - projects = self._create_projects_hierarchy() - ref = projects[1] - - ref['parents_as_list'] = [projects[0]] - ref['subtree_as_list'] = [projects[2]] - - self.stub_entity('GET', id=ref['id'], entity=ref) - - returned = self.manager.get(ref['id'], - parents_as_list=True, - subtree_as_list=True) - self.assertQueryStringIs('subtree_as_list&parents_as_list') - - for attr in projects[0]: - parent = getattr(returned, 'parents_as_list')[0] - self.assertEqual( - parent[attr], - projects[0][attr], - 'Expected different %s' % attr) - - for attr in projects[2]: - child = getattr(returned, 'subtree_as_list')[0] - self.assertEqual( - child[attr], - projects[2][attr], - 'Expected different %s' % attr) - - def test_get_with_invalid_parameters_combination(self): - # subtree_as_list and subtree_as_ids can not be included at the - # same time in the call. - self.assertRaises(exceptions.ValidationError, - self.manager.get, - project=uuid.uuid4().hex, - subtree_as_list=True, - subtree_as_ids=True) - - # parents_as_list and parents_as_ids can not be included at the - # same time in the call. - self.assertRaises(exceptions.ValidationError, - self.manager.get, - project=uuid.uuid4().hex, - parents_as_list=True, - parents_as_ids=True) - - def test_update_with_parent_project(self): - ref = self.new_ref() - ref['parent_id'] = uuid.uuid4().hex - - self.stub_entity('PATCH', id=ref['id'], entity=ref, status_code=403) - req_ref = ref.copy() - req_ref.pop('id') - - # NOTE(rodrigods): this is the expected behaviour of the Identity - # server, a different implementation might not fail this request. - self.assertRaises(exceptions.Forbidden, self.manager.update, - ref['id'], **utils.parameterize(req_ref)) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_regions.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_regions.py deleted file mode 100644 index 392f79f97b..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_regions.py +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import uuid - - -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import regions - - -class RegionTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(RegionTests, self).setUp() - self.key = 'region' - self.collection_key = 'regions' - self.model = regions.Region - self.manager = self.client.regions - - def new_ref(self, **kwargs): - kwargs = super(RegionTests, self).new_ref(**kwargs) - kwargs.setdefault('enabled', True) - kwargs.setdefault('id', uuid.uuid4().hex) - return kwargs - - def test_update_enabled_defaults_to_none(self): - super(RegionTests, self).test_update( - req_ref={'description': uuid.uuid4().hex}) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_role_assignments.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_role_assignments.py deleted file mode 100644 index 79d2585dfa..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_role_assignments.py +++ /dev/null @@ -1,225 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import role_assignments - - -class RoleAssignmentsTests(utils.TestCase, utils.CrudTests): - - def setUp(self): - super(RoleAssignmentsTests, self).setUp() - self.key = 'role_assignment' - self.collection_key = 'role_assignments' - self.model = role_assignments.RoleAssignment - self.manager = self.client.role_assignments - self.TEST_USER_DOMAIN_LIST = [{ - 'role': { - 'id': self.TEST_ROLE_ID - }, - 'scope': { - 'domain': { - 'id': self.TEST_DOMAIN_ID - } - }, - 'user': { - 'id': self.TEST_USER_ID - } - }] - self.TEST_GROUP_PROJECT_LIST = [{ - 'group': { - 'id': self.TEST_GROUP_ID - }, - 'role': { - 'id': self.TEST_ROLE_ID - }, - 'scope': { - 'project': { - 'id': self.TEST_TENANT_ID - } - } - }] - self.TEST_USER_PROJECT_LIST = [{ - 'user': { - 'id': self.TEST_USER_ID - }, - 'role': { - 'id': self.TEST_ROLE_ID - }, - 'scope': { - 'project': { - 'id': self.TEST_TENANT_ID - } - } - }] - - self.TEST_ALL_RESPONSE_LIST = (self.TEST_USER_PROJECT_LIST + - self.TEST_GROUP_PROJECT_LIST + - self.TEST_USER_DOMAIN_LIST) - - def _assert_returned_list(self, ref_list, returned_list): - self.assertEqual(len(ref_list), len(returned_list)) - [self.assertIsInstance(r, self.model) for r in returned_list] - - def test_list_params(self): - ref_list = self.TEST_USER_PROJECT_LIST - self.stub_entity('GET', - [self.collection_key, - '?scope.project.id=%s&user.id=%s' % - (self.TEST_TENANT_ID, self.TEST_USER_ID)], - entity=ref_list) - - returned_list = self.manager.list(user=self.TEST_USER_ID, - project=self.TEST_TENANT_ID) - self._assert_returned_list(ref_list, returned_list) - - kwargs = {'scope.project.id': self.TEST_TENANT_ID, - 'user.id': self.TEST_USER_ID} - self.assertQueryStringContains(**kwargs) - - def test_all_assignments_list(self): - ref_list = self.TEST_ALL_RESPONSE_LIST - self.stub_entity('GET', - [self.collection_key], - entity=ref_list) - - returned_list = self.manager.list() - self._assert_returned_list(ref_list, returned_list) - - kwargs = {} - self.assertQueryStringContains(**kwargs) - - def test_project_assignments_list(self): - ref_list = self.TEST_GROUP_PROJECT_LIST + self.TEST_USER_PROJECT_LIST - self.stub_entity('GET', - [self.collection_key, - '?scope.project.id=%s' % self.TEST_TENANT_ID], - entity=ref_list) - - returned_list = self.manager.list(project=self.TEST_TENANT_ID) - self._assert_returned_list(ref_list, returned_list) - - kwargs = {'scope.project.id': self.TEST_TENANT_ID} - self.assertQueryStringContains(**kwargs) - - def test_domain_assignments_list(self): - ref_list = self.TEST_USER_DOMAIN_LIST - self.stub_entity('GET', - [self.collection_key, - '?scope.domain.id=%s' % self.TEST_DOMAIN_ID], - entity=ref_list) - - returned_list = self.manager.list(domain=self.TEST_DOMAIN_ID) - self._assert_returned_list(ref_list, returned_list) - - kwargs = {'scope.domain.id': self.TEST_DOMAIN_ID} - self.assertQueryStringContains(**kwargs) - - def test_group_assignments_list(self): - ref_list = self.TEST_GROUP_PROJECT_LIST - self.stub_entity('GET', - [self.collection_key, - '?group.id=%s' % self.TEST_GROUP_ID], - entity=ref_list) - - returned_list = self.manager.list(group=self.TEST_GROUP_ID) - self._assert_returned_list(ref_list, returned_list) - - kwargs = {'group.id': self.TEST_GROUP_ID} - self.assertQueryStringContains(**kwargs) - - def test_user_assignments_list(self): - ref_list = self.TEST_USER_DOMAIN_LIST + self.TEST_USER_PROJECT_LIST - self.stub_entity('GET', - [self.collection_key, - '?user.id=%s' % self.TEST_USER_ID], - entity=ref_list) - - returned_list = self.manager.list(user=self.TEST_USER_ID) - self._assert_returned_list(ref_list, returned_list) - - kwargs = {'user.id': self.TEST_USER_ID} - self.assertQueryStringContains(**kwargs) - - def test_effective_assignments_list(self): - ref_list = self.TEST_USER_PROJECT_LIST + self.TEST_USER_DOMAIN_LIST - self.stub_entity('GET', - [self.collection_key, - '?effective=True'], - entity=ref_list) - - returned_list = self.manager.list(effective=True) - self._assert_returned_list(ref_list, returned_list) - - kwargs = {'effective': 'True'} - self.assertQueryStringContains(**kwargs) - - def test_role_assignments_list(self): - ref_list = self.TEST_ALL_RESPONSE_LIST - self.stub_entity('GET', - [self.collection_key, - '?role.id=' + self.TEST_ROLE_ID], - entity=ref_list) - - returned_list = self.manager.list(role=self.TEST_ROLE_ID) - self._assert_returned_list(ref_list, returned_list) - - kwargs = {'role.id': self.TEST_ROLE_ID} - self.assertQueryStringContains(**kwargs) - - def test_role_assignments_inherited_list(self): - ref_list = self.TEST_ALL_RESPONSE_LIST - self.stub_entity('GET', - [self.collection_key, - '?scope.OS-INHERIT:inherited_to=projects'], - entity=ref_list - ) - - returned_list = self.manager.list( - os_inherit_extension_inherited_to='projects') - self._assert_returned_list(ref_list, returned_list) - - query_string = 'scope.OS-INHERIT:inherited_to=projects' - self.assertQueryStringIs(query_string) - - def test_domain_and_project_list(self): - # Should only accept either domain or project, never both - self.assertRaises(exceptions.ValidationError, - self.manager.list, - domain=self.TEST_DOMAIN_ID, - project=self.TEST_TENANT_ID) - - def test_user_and_group_list(self): - # Should only accept either user or group, never both - self.assertRaises(exceptions.ValidationError, self.manager.list, - user=self.TEST_USER_ID, group=self.TEST_GROUP_ID) - - def test_create(self): - # Create not supported for role assignments - self.assertRaises(exceptions.MethodNotImplemented, self.manager.create) - - def test_update(self): - # Update not supported for role assignments - self.assertRaises(exceptions.MethodNotImplemented, self.manager.update) - - def test_delete(self): - # Delete not supported for role assignments - self.assertRaises(exceptions.MethodNotImplemented, self.manager.delete) - - def test_get(self): - # Get not supported for role assignments - self.assertRaises(exceptions.MethodNotImplemented, self.manager.get) - - def test_find(self): - # Find not supported for role assignments - self.assertRaises(exceptions.MethodNotImplemented, self.manager.find) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_roles.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_roles.py deleted file mode 100644 index 2a71bf32ed..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_roles.py +++ /dev/null @@ -1,331 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import roles - - -class RoleTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(RoleTests, self).setUp() - self.key = 'role' - self.collection_key = 'roles' - self.model = roles.Role - self.manager = self.client.roles - - def new_ref(self, **kwargs): - kwargs = super(RoleTests, self).new_ref(**kwargs) - kwargs.setdefault('name', uuid.uuid4().hex) - return kwargs - - def test_domain_role_grant(self): - user_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('PUT', - ['domains', domain_id, 'users', user_id, - self.collection_key, ref['id']], - status_code=201) - - self.manager.grant(role=ref['id'], domain=domain_id, user=user_id) - - def test_domain_group_role_grant(self): - group_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('PUT', - ['domains', domain_id, 'groups', group_id, - self.collection_key, ref['id']], - status_code=201) - - self.manager.grant(role=ref['id'], domain=domain_id, group=group_id) - - def test_domain_role_list(self): - user_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref_list = [self.new_ref(), self.new_ref()] - - self.stub_entity('GET', - ['domains', domain_id, 'users', user_id, - self.collection_key], entity=ref_list) - - self.manager.list(domain=domain_id, user=user_id) - - def test_domain_group_role_list(self): - group_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref_list = [self.new_ref(), self.new_ref()] - - self.stub_entity('GET', - ['domains', domain_id, 'groups', group_id, - self.collection_key], entity=ref_list) - - self.manager.list(domain=domain_id, group=group_id) - - def test_domain_role_check(self): - user_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('HEAD', - ['domains', domain_id, 'users', user_id, - self.collection_key, ref['id']], - status_code=204) - - self.manager.check(role=ref['id'], domain=domain_id, - user=user_id) - - def test_domain_group_role_check(self): - return - group_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('HEAD', - ['domains', domain_id, 'groups', group_id, - self.collection_key, ref['id']], - status_code=204) - - self.manager.check(role=ref['id'], domain=domain_id, group=group_id) - - def test_domain_role_revoke(self): - user_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('DELETE', - ['domains', domain_id, 'users', user_id, - self.collection_key, ref['id']], - status_code=204) - - self.manager.revoke(role=ref['id'], domain=domain_id, user=user_id) - - def test_domain_group_role_revoke(self): - group_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('DELETE', - ['domains', domain_id, 'groups', group_id, - self.collection_key, ref['id']], - status_code=204) - - self.manager.revoke(role=ref['id'], domain=domain_id, group=group_id) - - def test_project_role_grant(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('PUT', - ['projects', project_id, 'users', user_id, - self.collection_key, ref['id']], - status_code=201) - - self.manager.grant(role=ref['id'], project=project_id, user=user_id) - - def test_project_group_role_grant(self): - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('PUT', - ['projects', project_id, 'groups', group_id, - self.collection_key, ref['id']], - status_code=201) - - self.manager.grant(role=ref['id'], project=project_id, group=group_id) - - def test_project_role_list(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref_list = [self.new_ref(), self.new_ref()] - - self.stub_entity('GET', - ['projects', project_id, 'users', user_id, - self.collection_key], entity=ref_list) - - self.manager.list(project=project_id, user=user_id) - - def test_project_group_role_list(self): - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref_list = [self.new_ref(), self.new_ref()] - - self.stub_entity('GET', - ['projects', project_id, 'groups', group_id, - self.collection_key], entity=ref_list) - - self.manager.list(project=project_id, group=group_id) - - def test_project_role_check(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('HEAD', - ['projects', project_id, 'users', user_id, - self.collection_key, ref['id']], - status_code=200) - - self.manager.check(role=ref['id'], project=project_id, user=user_id) - - def test_project_group_role_check(self): - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('HEAD', - ['projects', project_id, 'groups', group_id, - self.collection_key, ref['id']], - status_code=200) - - self.manager.check(role=ref['id'], project=project_id, group=group_id) - - def test_project_role_revoke(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('DELETE', - ['projects', project_id, 'users', user_id, - self.collection_key, ref['id']], - status_code=204) - - self.manager.revoke(role=ref['id'], project=project_id, user=user_id) - - def test_project_group_role_revoke(self): - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('DELETE', - ['projects', project_id, 'groups', group_id, - self.collection_key, ref['id']], - status_code=204) - - self.manager.revoke(role=ref['id'], project=project_id, group=group_id) - - def test_domain_project_role_grant_fails(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.assertRaises( - exceptions.ValidationError, - self.manager.grant, - role=ref['id'], - domain=domain_id, - project=project_id, - user=user_id) - - def test_domain_project_role_list_fails(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - - self.assertRaises( - exceptions.ValidationError, - self.manager.list, - domain=domain_id, - project=project_id, - user=user_id) - - def test_domain_project_role_check_fails(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.assertRaises( - exceptions.ValidationError, - self.manager.check, - role=ref['id'], - domain=domain_id, - project=project_id, - user=user_id) - - def test_domain_project_role_revoke_fails(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - domain_id = uuid.uuid4().hex - ref = self.new_ref() - - self.assertRaises( - exceptions.ValidationError, - self.manager.revoke, - role=ref['id'], - domain=domain_id, - project=project_id, - user=user_id) - - def test_user_group_role_grant_fails(self): - user_id = uuid.uuid4().hex - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.assertRaises( - exceptions.ValidationError, - self.manager.grant, - role=ref['id'], - project=project_id, - group=group_id, - user=user_id) - - def test_user_group_role_list_fails(self): - user_id = uuid.uuid4().hex - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - - self.assertRaises( - exceptions.ValidationError, - self.manager.list, - project=project_id, - group=group_id, - user=user_id) - - def test_user_group_role_check_fails(self): - user_id = uuid.uuid4().hex - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.assertRaises( - exceptions.ValidationError, - self.manager.check, - role=ref['id'], - project=project_id, - group=group_id, - user=user_id) - - def test_user_group_role_revoke_fails(self): - user_id = uuid.uuid4().hex - group_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - ref = self.new_ref() - - self.assertRaises( - exceptions.ValidationError, - self.manager.revoke, - role=ref['id'], - project=project_id, - group=group_id, - user=user_id) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_service_catalog.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_service_catalog.py deleted file mode 100644 index 054ad56b39..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_service_catalog.py +++ /dev/null @@ -1,271 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import access -from keystoneclient import exceptions -from keystoneclient import fixture -from keystoneclient.tests.unit.v3 import client_fixtures -from keystoneclient.tests.unit.v3 import utils - - -class ServiceCatalogTest(utils.TestCase): - def setUp(self): - super(ServiceCatalogTest, self).setUp() - self.AUTH_RESPONSE_BODY = client_fixtures.auth_response_body() - self.RESPONSE = utils.TestResponse({ - "headers": client_fixtures.AUTH_RESPONSE_HEADERS - }) - - self.north_endpoints = {'public': - 'http://glance.north.host/glanceapi/public', - 'internal': - 'http://glance.north.host/glanceapi/internal', - 'admin': - 'http://glance.north.host/glanceapi/admin'} - - self.south_endpoints = {'public': - 'http://glance.south.host/glanceapi/public', - 'internal': - 'http://glance.south.host/glanceapi/internal', - 'admin': - 'http://glance.south.host/glanceapi/admin'} - - def test_building_a_service_catalog(self): - auth_ref = access.AccessInfo.factory(self.RESPONSE, - self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - self.assertEqual(sc.url_for(service_type='compute'), - "https://compute.north.host/novapi/public") - self.assertEqual(sc.url_for(service_type='compute', - endpoint_type='internal'), - "https://compute.north.host/novapi/internal") - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, "region", - "South", service_type='compute') - - def test_service_catalog_endpoints(self): - auth_ref = access.AccessInfo.factory(self.RESPONSE, - self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - public_ep = sc.get_endpoints(service_type='compute', - endpoint_type='public') - self.assertEqual(public_ep['compute'][0]['region'], 'North') - self.assertEqual(public_ep['compute'][0]['url'], - "https://compute.north.host/novapi/public") - - def test_service_catalog_regions(self): - self.AUTH_RESPONSE_BODY['token']['region_name'] = "North" - auth_ref = access.AccessInfo.factory(self.RESPONSE, - self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_type='image', endpoint_type='public') - self.assertEqual(url, "http://glance.north.host/glanceapi/public") - - self.AUTH_RESPONSE_BODY['token']['region_name'] = "South" - auth_ref = access.AccessInfo.factory(self.RESPONSE, - self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - url = sc.url_for(service_type='image', endpoint_type='internal') - self.assertEqual(url, "http://glance.south.host/glanceapi/internal") - - def test_service_catalog_empty(self): - self.AUTH_RESPONSE_BODY['token']['catalog'] = [] - auth_ref = access.AccessInfo.factory(self.RESPONSE, - self.AUTH_RESPONSE_BODY) - self.assertRaises(exceptions.EmptyCatalog, - auth_ref.service_catalog.url_for, - service_type='image', - endpoint_type='internalURL') - - def test_service_catalog_get_endpoints_region_names(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - endpoints = sc.get_endpoints(service_type='image', region_name='North') - self.assertEqual(len(endpoints), 1) - for endpoint in endpoints['image']: - self.assertEqual(endpoint['url'], - self.north_endpoints[endpoint['interface']]) - - endpoints = sc.get_endpoints(service_type='image', region_name='South') - self.assertEqual(len(endpoints), 1) - for endpoint in endpoints['image']: - self.assertEqual(endpoint['url'], - self.south_endpoints[endpoint['interface']]) - - endpoints = sc.get_endpoints(service_type='compute') - self.assertEqual(len(endpoints['compute']), 3) - - endpoints = sc.get_endpoints(service_type='compute', - region_name='North') - self.assertEqual(len(endpoints['compute']), 3) - - endpoints = sc.get_endpoints(service_type='compute', - region_name='West') - self.assertEqual(len(endpoints['compute']), 0) - - def test_service_catalog_url_for_region_names(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_type='image', region_name='North') - self.assertEqual(url, self.north_endpoints['public']) - - url = sc.url_for(service_type='image', region_name='South') - self.assertEqual(url, self.south_endpoints['public']) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_type='image', region_name='West') - - def test_servcie_catalog_get_url_region_names(self): - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - urls = sc.get_urls(service_type='image') - self.assertEqual(len(urls), 2) - - urls = sc.get_urls(service_type='image', region_name='North') - self.assertEqual(len(urls), 1) - self.assertEqual(urls[0], self.north_endpoints['public']) - - urls = sc.get_urls(service_type='image', region_name='South') - self.assertEqual(len(urls), 1) - self.assertEqual(urls[0], self.south_endpoints['public']) - - urls = sc.get_urls(service_type='image', region_name='West') - self.assertIsNone(urls) - - def test_service_catalog_param_overrides_body_region(self): - self.AUTH_RESPONSE_BODY['token']['region_name'] = "North" - auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_type='image') - self.assertEqual(url, self.north_endpoints['public']) - - url = sc.url_for(service_type='image', region_name='South') - self.assertEqual(url, self.south_endpoints['public']) - - endpoints = sc.get_endpoints(service_type='image') - self.assertEqual(len(endpoints['image']), 3) - for endpoint in endpoints['image']: - self.assertEqual(endpoint['url'], - self.north_endpoints[endpoint['interface']]) - - endpoints = sc.get_endpoints(service_type='image', region_name='South') - self.assertEqual(len(endpoints['image']), 3) - for endpoint in endpoints['image']: - self.assertEqual(endpoint['url'], - self.south_endpoints[endpoint['interface']]) - - def test_service_catalog_service_name(self): - auth_ref = access.AccessInfo.factory(resp=None, - body=self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - url = sc.url_for(service_name='glance', endpoint_type='public', - service_type='image', region_name='North') - self.assertEqual('http://glance.north.host/glanceapi/public', url) - - url = sc.url_for(service_name='glance', endpoint_type='public', - service_type='image', region_name='South') - self.assertEqual('http://glance.south.host/glanceapi/public', url) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_name='glance', service_type='compute') - - urls = sc.get_urls(service_type='image', service_name='glance', - endpoint_type='public') - - self.assertIn('http://glance.north.host/glanceapi/public', urls) - self.assertIn('http://glance.south.host/glanceapi/public', urls) - - urls = sc.get_urls(service_type='image', service_name='Servers', - endpoint_type='public') - - self.assertIsNone(urls) - - def test_service_catalog_without_name(self): - pr_auth_ref = access.AccessInfo.factory( - resp=None, - body=client_fixtures.project_scoped_token()) - pr_sc = pr_auth_ref.service_catalog - - # this will work because there are no service names on that token - url_ref = 'http://public.com:8774/v2/225da22d3ce34b15877ea70b2a575f58' - url = pr_sc.url_for(service_type='compute', service_name='NotExist', - endpoint_type='public') - self.assertEqual(url_ref, url) - - ab_auth_ref = access.AccessInfo.factory(resp=None, - body=self.AUTH_RESPONSE_BODY) - ab_sc = ab_auth_ref.service_catalog - - # this won't work because there is a name and it's not this one - self.assertRaises(exceptions.EndpointNotFound, ab_sc.url_for, - service_type='compute', service_name='NotExist', - endpoint_type='public') - - -class ServiceCatalogV3Test(ServiceCatalogTest): - - def test_building_a_service_catalog(self): - auth_ref = access.AccessInfo.factory(self.RESPONSE, - self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - self.assertEqual(sc.url_for(service_type='compute'), - 'https://compute.north.host/novapi/public') - self.assertEqual(sc.url_for(service_type='compute', - endpoint_type='internal'), - 'https://compute.north.host/novapi/internal') - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, 'region_id', - 'South', service_type='compute') - - def test_service_catalog_endpoints(self): - auth_ref = access.AccessInfo.factory(self.RESPONSE, - self.AUTH_RESPONSE_BODY) - sc = auth_ref.service_catalog - - public_ep = sc.get_endpoints(service_type='compute', - endpoint_type='public') - self.assertEqual(public_ep['compute'][0]['region_id'], 'North') - self.assertEqual(public_ep['compute'][0]['url'], - 'https://compute.north.host/novapi/public') - - def test_service_catalog_multiple_service_types(self): - token = fixture.V3Token() - token.set_project_scope() - - for i in range(3): - s = token.add_service('compute') - s.add_standard_endpoints(public='public-%d' % i, - admin='admin-%d' % i, - internal='internal-%d' % i, - region='region-%d' % i) - - auth_ref = access.AccessInfo.factory(resp=None, body=token) - - urls = auth_ref.service_catalog.get_urls(service_type='compute', - endpoint_type='public') - - self.assertEqual(set(['public-0', 'public-1', 'public-2']), set(urls)) - - urls = auth_ref.service_catalog.get_urls(service_type='compute', - endpoint_type='public', - region_name='region-1') - - self.assertEqual(('public-1', ), urls) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_services.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_services.py deleted file mode 100644 index 40dde475bd..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_services.py +++ /dev/null @@ -1,44 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import services - - -class ServiceTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(ServiceTests, self).setUp() - self.key = 'service' - self.collection_key = 'services' - self.model = services.Service - self.manager = self.client.services - - def new_ref(self, **kwargs): - kwargs = super(ServiceTests, self).new_ref(**kwargs) - kwargs.setdefault('name', uuid.uuid4().hex) - kwargs.setdefault('type', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - return kwargs - - def test_list_filter_name(self): - filter_name = uuid.uuid4().hex - expected_query = {'name': filter_name} - super(ServiceTests, self).test_list(expected_query=expected_query, - name=filter_name) - - def test_list_filter_type(self): - filter_type = uuid.uuid4().hex - expected_query = {'type': filter_type} - super(ServiceTests, self).test_list(expected_query=expected_query, - type=filter_type) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_simple_cert.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_simple_cert.py deleted file mode 100644 index 067083a44c..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_simple_cert.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2014 IBM Corp. -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import testresources - -from keystoneclient.tests.unit import client_fixtures -from keystoneclient.tests.unit.v3 import utils - - -class SimpleCertTests(utils.TestCase, testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_get_ca_certificate(self): - self.stub_url('GET', ['OS-SIMPLE-CERT', 'ca'], - headers={'Content-Type': 'application/x-pem-file'}, - text=self.examples.SIGNING_CA) - res = self.client.simple_cert.get_ca_certificates() - self.assertEqual(self.examples.SIGNING_CA, res) - - def test_get_certificates(self): - self.stub_url('GET', ['OS-SIMPLE-CERT', 'certificates'], - headers={'Content-Type': 'application/x-pem-file'}, - text=self.examples.SIGNING_CERT) - res = self.client.simple_cert.get_certificates() - self.assertEqual(self.examples.SIGNING_CERT, res) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_tokens.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_tokens.py deleted file mode 100644 index 2c27fd0979..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_tokens.py +++ /dev/null @@ -1,110 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -import testresources - -from keystoneclient import access -from keystoneclient import exceptions -from keystoneclient.tests.unit import client_fixtures -from keystoneclient.tests.unit.v3 import utils - - -class TokenTests(utils.TestCase, testresources.ResourcedTestCase): - - resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)] - - def test_revoke_token_with_token_id(self): - token_id = uuid.uuid4().hex - self.stub_url('DELETE', ['/auth/tokens'], status_code=204) - self.client.tokens.revoke_token(token_id) - self.assertRequestHeaderEqual('X-Subject-Token', token_id) - - def test_revoke_token_with_access_info_instance(self): - token_id = uuid.uuid4().hex - token_ref = self.examples.TOKEN_RESPONSES[ - self.examples.v3_UUID_TOKEN_DEFAULT] - token = access.AccessInfoV3(token_id, token_ref['token']) - self.stub_url('DELETE', ['/auth/tokens'], status_code=204) - self.client.tokens.revoke_token(token) - self.assertRequestHeaderEqual('X-Subject-Token', token_id) - - def test_get_revoked(self): - sample_revoked_response = {'signed': '-----BEGIN CMS-----\nMIIB...'} - self.stub_url('GET', ['auth', 'tokens', 'OS-PKI', 'revoked'], - json=sample_revoked_response) - resp = self.client.tokens.get_revoked() - self.assertEqual(sample_revoked_response, resp) - - def test_validate_token_with_token_id(self): - # Can validate a token passing a string token ID. - token_id = uuid.uuid4().hex - token_ref = self.examples.TOKEN_RESPONSES[ - self.examples.v3_UUID_TOKEN_DEFAULT] - self.stub_url('GET', ['auth', 'tokens'], - headers={'X-Subject-Token': token_id, }, json=token_ref) - access_info = self.client.tokens.validate(token_id) - - self.assertRequestHeaderEqual('X-Subject-Token', token_id) - self.assertIsInstance(access_info, access.AccessInfoV3) - self.assertEqual(token_id, access_info.auth_token) - - def test_validate_token_with_access_info(self): - # Can validate a token passing an access info. - token_id = uuid.uuid4().hex - token_ref = self.examples.TOKEN_RESPONSES[ - self.examples.v3_UUID_TOKEN_DEFAULT] - token = access.AccessInfoV3(token_id, token_ref['token']) - self.stub_url('GET', ['auth', 'tokens'], - headers={'X-Subject-Token': token_id, }, json=token_ref) - access_info = self.client.tokens.validate(token) - - self.assertRequestHeaderEqual('X-Subject-Token', token_id) - self.assertIsInstance(access_info, access.AccessInfoV3) - self.assertEqual(token_id, access_info.auth_token) - - def test_validate_token_invalid(self): - # When the token is invalid the server typically returns a 404. - token_id = uuid.uuid4().hex - self.stub_url('GET', ['auth', 'tokens'], status_code=404) - self.assertRaises(exceptions.NotFound, - self.client.tokens.validate, token_id) - - def test_validate_token_catalog(self): - # Can validate a token and a catalog is requested by default. - token_id = uuid.uuid4().hex - token_ref = self.examples.TOKEN_RESPONSES[ - self.examples.v3_UUID_TOKEN_DEFAULT] - self.stub_url('GET', ['auth', 'tokens'], - headers={'X-Subject-Token': token_id, }, json=token_ref) - access_info = self.client.tokens.validate(token_id) - - self.assertQueryStringIs() - self.assertTrue(access_info.has_service_catalog()) - - def test_validate_token_nocatalog(self): - # Can validate a token and request no catalog. - token_id = uuid.uuid4().hex - token_ref = self.examples.TOKEN_RESPONSES[ - self.examples.v3_UUID_TOKEN_UNSCOPED] - self.stub_url('GET', ['auth', 'tokens'], - headers={'X-Subject-Token': token_id, }, json=token_ref) - access_info = self.client.tokens.validate(token_id, - include_catalog=False) - - self.assertQueryStringIs('nocatalog') - self.assertFalse(access_info.has_service_catalog()) - - -def load_tests(loader, tests, pattern): - return testresources.OptimisingTestSuite(tests) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_trusts.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_trusts.py deleted file mode 100644 index fbd8fdeada..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_trusts.py +++ /dev/null @@ -1,112 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import uuid - -from oslo_utils import timeutils - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3.contrib import trusts - - -class TrustTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(TrustTests, self).setUp() - self.key = 'trust' - self.collection_key = 'trusts' - self.model = trusts.Trust - self.manager = self.client.trusts - self.path_prefix = 'OS-TRUST' - - def new_ref(self, **kwargs): - kwargs = super(TrustTests, self).new_ref(**kwargs) - kwargs.setdefault('project_id', uuid.uuid4().hex) - return kwargs - - def test_create(self): - ref = self.new_ref() - ref['trustor_user_id'] = uuid.uuid4().hex - ref['trustee_user_id'] = uuid.uuid4().hex - ref['impersonation'] = False - super(TrustTests, self).test_create(ref=ref) - - def test_create_limited_uses(self): - ref = self.new_ref() - ref['trustor_user_id'] = uuid.uuid4().hex - ref['trustee_user_id'] = uuid.uuid4().hex - ref['impersonation'] = False - ref['remaining_uses'] = 5 - super(TrustTests, self).test_create(ref=ref) - - def test_create_roles(self): - ref = self.new_ref() - ref['trustor_user_id'] = uuid.uuid4().hex - ref['trustee_user_id'] = uuid.uuid4().hex - ref['impersonation'] = False - req_ref = ref.copy() - req_ref.pop('id') - - # Note the TrustManager takes a list of role_names, and converts - # internally to the slightly odd list-of-dict API format, so we - # have to pass the expected request data to allow correct stubbing - ref['role_names'] = ['atestrole'] - req_ref['roles'] = [{'name': 'atestrole'}] - super(TrustTests, self).test_create(ref=ref, req_ref=req_ref) - - def test_create_expires(self): - ref = self.new_ref() - ref['trustor_user_id'] = uuid.uuid4().hex - ref['trustee_user_id'] = uuid.uuid4().hex - ref['impersonation'] = False - ref['expires_at'] = timeutils.parse_isotime( - '2013-03-04T12:00:01.000000Z') - req_ref = ref.copy() - req_ref.pop('id') - - # Note the TrustManager takes a datetime.datetime object for - # expires_at, and converts it internally into an iso format datestamp - req_ref['expires_at'] = '2013-03-04T12:00:01.000000Z' - super(TrustTests, self).test_create(ref=ref, req_ref=req_ref) - - def test_create_imp(self): - ref = self.new_ref() - ref['trustor_user_id'] = uuid.uuid4().hex - ref['trustee_user_id'] = uuid.uuid4().hex - ref['impersonation'] = True - super(TrustTests, self).test_create(ref=ref) - - def test_create_roles_imp(self): - ref = self.new_ref() - ref['trustor_user_id'] = uuid.uuid4().hex - ref['trustee_user_id'] = uuid.uuid4().hex - ref['impersonation'] = True - req_ref = ref.copy() - req_ref.pop('id') - ref['role_names'] = ['atestrole'] - req_ref['roles'] = [{'name': 'atestrole'}] - super(TrustTests, self).test_create(ref=ref, req_ref=req_ref) - - def test_list_filter_trustor(self): - expected_query = {'trustor_user_id': '12345'} - super(TrustTests, self).test_list(expected_query=expected_query, - trustor_user='12345') - - def test_list_filter_trustee(self): - expected_query = {'trustee_user_id': '12345'} - super(TrustTests, self).test_list(expected_query=expected_query, - trustee_user='12345') - - def test_update(self): - # Update not supported for the OS-TRUST API - self.assertRaises(exceptions.MethodNotImplemented, self.manager.update) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_users.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_users.py deleted file mode 100644 index 4619b66ab8..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/test_users.py +++ /dev/null @@ -1,279 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import exceptions -from keystoneclient.tests.unit.v3 import utils -from keystoneclient.v3 import users - - -class UserTests(utils.TestCase, utils.CrudTests): - def setUp(self): - super(UserTests, self).setUp() - self.key = 'user' - self.collection_key = 'users' - self.model = users.User - self.manager = self.client.users - - def new_ref(self, **kwargs): - kwargs = super(UserTests, self).new_ref(**kwargs) - kwargs.setdefault('description', uuid.uuid4().hex) - kwargs.setdefault('domain_id', uuid.uuid4().hex) - kwargs.setdefault('enabled', True) - kwargs.setdefault('name', uuid.uuid4().hex) - kwargs.setdefault('default_project_id', uuid.uuid4().hex) - return kwargs - - def test_add_user_to_group(self): - group_id = uuid.uuid4().hex - ref = self.new_ref() - self.stub_url('PUT', - ['groups', group_id, self.collection_key, ref['id']], - status_code=204) - - self.manager.add_to_group(user=ref['id'], group=group_id) - self.assertRaises(exceptions.ValidationError, - self.manager.remove_from_group, - user=ref['id'], - group=None) - - def test_list_users_in_group(self): - group_id = uuid.uuid4().hex - ref_list = [self.new_ref(), self.new_ref()] - - self.stub_entity('GET', - ['groups', group_id, self.collection_key], - entity=ref_list) - - returned_list = self.manager.list(group=group_id) - self.assertEqual(len(ref_list), len(returned_list)) - [self.assertIsInstance(r, self.model) for r in returned_list] - - def test_check_user_in_group(self): - group_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('HEAD', - ['groups', group_id, self.collection_key, ref['id']], - status_code=204) - - self.manager.check_in_group(user=ref['id'], group=group_id) - - self.assertRaises(exceptions.ValidationError, - self.manager.check_in_group, - user=ref['id'], - group=None) - - def test_remove_user_from_group(self): - group_id = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_url('DELETE', - ['groups', group_id, self.collection_key, ref['id']], - status_code=204) - - self.manager.remove_from_group(user=ref['id'], group=group_id) - self.assertRaises(exceptions.ValidationError, - self.manager.remove_from_group, - user=ref['id'], - group=None) - - def test_create_doesnt_log_password(self): - password = uuid.uuid4().hex - ref = self.new_ref() - - self.stub_entity('POST', [self.collection_key], - status_code=201, entity=ref) - - req_ref = ref.copy() - req_ref.pop('id') - param_ref = req_ref.copy() - - param_ref['password'] = password - params = utils.parameterize(param_ref) - - self.manager.create(**params) - - self.assertNotIn(password, self.logger.output) - - def test_create_with_project(self): - # Can create a user with the deprecated project option rather than - # default_project_id. - ref = self.new_ref() - - self.stub_entity('POST', [self.collection_key], - status_code=201, entity=ref) - - req_ref = ref.copy() - req_ref.pop('id') - param_ref = req_ref.copy() - # Use deprecated project_id rather than new default_project_id. - param_ref['project_id'] = param_ref.pop('default_project_id') - params = utils.parameterize(param_ref) - - returned = self.manager.create(**params) - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) - - def test_create_with_project_and_default_project(self): - # Can create a user with the deprecated project and default_project_id. - # The backend call should only pass the default_project_id. - ref = self.new_ref() - - self.stub_entity('POST', - [self.collection_key], - status_code=201, entity=ref) - - req_ref = ref.copy() - req_ref.pop('id') - param_ref = req_ref.copy() - - # Add the deprecated project_id in the call, the value will be ignored. - param_ref['project_id'] = 'project' - params = utils.parameterize(param_ref) - - returned = self.manager.create(**params) - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) - - def test_update_doesnt_log_password(self): - password = uuid.uuid4().hex - ref = self.new_ref() - - req_ref = ref.copy() - req_ref.pop('id') - param_ref = req_ref.copy() - - self.stub_entity('PATCH', - [self.collection_key, ref['id']], - status_code=200, entity=ref) - - param_ref['password'] = password - params = utils.parameterize(param_ref) - - self.manager.update(ref['id'], **params) - - self.assertNotIn(password, self.logger.output) - - def test_update_with_project(self): - # Can update a user with the deprecated project option rather than - # default_project_id. - ref = self.new_ref() - req_ref = ref.copy() - req_ref.pop('id') - param_ref = req_ref.copy() - - self.stub_entity('PATCH', - [self.collection_key, ref['id']], - status_code=200, entity=ref) - - # Use deprecated project_id rather than new default_project_id. - param_ref['project_id'] = param_ref.pop('default_project_id') - params = utils.parameterize(param_ref) - - returned = self.manager.update(ref['id'], **params) - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) - - def test_update_with_project_and_default_project(self, ref=None): - ref = self.new_ref() - req_ref = ref.copy() - req_ref.pop('id') - param_ref = req_ref.copy() - - self.stub_entity('PATCH', - [self.collection_key, ref['id']], - status_code=200, entity=ref) - - # Add the deprecated project_id in the call, the value will be ignored. - param_ref['project_id'] = 'project' - params = utils.parameterize(param_ref) - - returned = self.manager.update(ref['id'], **params) - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) - - def test_update_password(self): - old_password = uuid.uuid4().hex - new_password = uuid.uuid4().hex - - self.stub_url('POST', - [self.collection_key, self.TEST_USER, 'password']) - self.client.user_id = self.TEST_USER - self.manager.update_password(old_password, new_password) - - exp_req_body = { - 'user': { - 'password': new_password, 'original_password': old_password - } - } - - self.assertEqual(self.TEST_URL + '/users/test/password', - self.requests_mock.last_request.url) - self.assertRequestBodyIs(json=exp_req_body) - self.assertNotIn(old_password, self.logger.output) - self.assertNotIn(new_password, self.logger.output) - - def test_update_password_with_bad_inputs(self): - old_password = uuid.uuid4().hex - new_password = uuid.uuid4().hex - - # users can't unset their password - self.assertRaises(exceptions.ValidationError, - self.manager.update_password, - old_password, None) - self.assertRaises(exceptions.ValidationError, - self.manager.update_password, - old_password, '') - - # users can't start with empty passwords - self.assertRaises(exceptions.ValidationError, - self.manager.update_password, - None, new_password) - self.assertRaises(exceptions.ValidationError, - self.manager.update_password, - '', new_password) - - # this wouldn't result in any change anyway - self.assertRaises(exceptions.ValidationError, - self.manager.update_password, - None, None) - self.assertRaises(exceptions.ValidationError, - self.manager.update_password, - '', '') - password = uuid.uuid4().hex - self.assertRaises(exceptions.ValidationError, - self.manager.update_password, - password, password) diff --git a/awx/lib/site-packages/keystoneclient/tests/unit/v3/utils.py b/awx/lib/site-packages/keystoneclient/tests/unit/v3/utils.py deleted file mode 100644 index 7f2d633d7e..0000000000 --- a/awx/lib/site-packages/keystoneclient/tests/unit/v3/utils.py +++ /dev/null @@ -1,332 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -import six -from six.moves.urllib import parse as urlparse - -from keystoneclient.tests.unit import utils -from keystoneclient.v3 import client - - -TestResponse = utils.TestResponse - - -def parameterize(ref): - """Rewrites attributes to match the kwarg naming convention in client. - - >>> parameterize({'project_id': 0}) - {'project': 0} - - """ - params = ref.copy() - for key in ref: - if key[-3:] == '_id': - params.setdefault(key[:-3], params.pop(key)) - return params - - -class UnauthenticatedTestCase(utils.TestCase): - """Class used as base for unauthenticated calls.""" - - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') - TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' - TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3') - - -class TestCase(UnauthenticatedTestCase): - - TEST_ADMIN_IDENTITY_ENDPOINT = "http://127.0.0.1:35357/v3" - - TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "url": "http://cdn.admin-nets.local:8774/v1.0/", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://127.0.0.1:8774/v1.0", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://cdn.admin-nets.local:8774/v1.0", - "region": "RegionOne", - "interface": "admin" - }], - "type": "nova_compat" - }, { - "endpoints": [{ - "url": "http://nova/novapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://nova/novapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://nova/novapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "compute" - }, { - "endpoints": [{ - "url": "http://glance/glanceapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://glance/glanceapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://glance/glanceapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "image", - "name": "glance" - }, { - "endpoints": [{ - "url": "http://127.0.0.1:5000/v3", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://127.0.0.1:5000/v3", - "region": "RegionOne", - "interface": "internal" - }, { - "url": TEST_ADMIN_IDENTITY_ENDPOINT, - "region": "RegionOne", - "interface": "admin" - }], - "type": "identity" - }, { - "endpoints": [{ - "url": "http://swift/swiftapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://swift/swiftapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://swift/swiftapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "object-store" - }] - - def setUp(self): - super(TestCase, self).setUp() - self.client = client.Client(username=self.TEST_USER, - token=self.TEST_TOKEN, - tenant_name=self.TEST_TENANT_NAME, - auth_url=self.TEST_URL, - endpoint=self.TEST_URL) - - def stub_auth(self, subject_token=None, **kwargs): - if not subject_token: - subject_token = self.TEST_TOKEN - - try: - response_list = kwargs['response_list'] - except KeyError: - headers = kwargs.setdefault('headers', {}) - headers['X-Subject-Token'] = subject_token - else: - for resp in response_list: - headers = resp.setdefault('headers', {}) - headers['X-Subject-Token'] = subject_token - - self.stub_url('POST', ['auth', 'tokens'], **kwargs) - - -class CrudTests(object): - key = None - collection_key = None - model = None - manager = None - path_prefix = None - - def new_ref(self, **kwargs): - kwargs.setdefault('id', uuid.uuid4().hex) - kwargs.setdefault(uuid.uuid4().hex, uuid.uuid4().hex) - return kwargs - - def encode(self, entity): - if isinstance(entity, dict): - return {self.key: entity} - if isinstance(entity, list): - return {self.collection_key: entity} - raise NotImplementedError('Are you sure you want to encode that?') - - def stub_entity(self, method, parts=None, entity=None, id=None, **kwargs): - if entity: - entity = self.encode(entity) - kwargs['json'] = entity - - if not parts: - parts = [self.collection_key] - - if self.path_prefix: - parts.insert(0, self.path_prefix) - - if id: - if not parts: - parts = [] - - parts.append(id) - - self.stub_url(method, parts=parts, **kwargs) - - def assertEntityRequestBodyIs(self, entity): - self.assertRequestBodyIs(json=self.encode(entity)) - - def test_create(self, ref=None, req_ref=None): - ref = ref or self.new_ref() - manager_ref = ref.copy() - manager_ref.pop('id') - - # req_ref argument allows you to specify a different - # signature for the request when the manager does some - # conversion before doing the request (e.g. converting - # from datetime object to timestamp string) - if req_ref: - req_ref = req_ref.copy() - else: - req_ref = ref.copy() - req_ref.pop('id') - - self.stub_entity('POST', entity=req_ref, status_code=201) - - returned = self.manager.create(**parameterize(manager_ref)) - self.assertIsInstance(returned, self.model) - for attr in req_ref: - self.assertEqual( - getattr(returned, attr), - req_ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) - - # The entity created here may be used in other test cases - return returned - - def test_get(self, ref=None): - ref = ref or self.new_ref() - - self.stub_entity('GET', id=ref['id'], entity=ref) - - returned = self.manager.get(ref['id']) - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - - def _get_expected_path(self, expected_path=None): - if not expected_path: - if self.path_prefix: - expected_path = 'v3/%s/%s' % (self.path_prefix, - self.collection_key) - else: - expected_path = 'v3/%s' % self.collection_key - - return expected_path - - def test_list(self, ref_list=None, expected_path=None, - expected_query=None, **filter_kwargs): - ref_list = ref_list or [self.new_ref(), self.new_ref()] - expected_path = self._get_expected_path(expected_path) - - self.requests_mock.get(urlparse.urljoin(self.TEST_URL, expected_path), - json=self.encode(ref_list)) - - returned_list = self.manager.list(**filter_kwargs) - self.assertEqual(len(ref_list), len(returned_list)) - [self.assertIsInstance(r, self.model) for r in returned_list] - - qs_args = self.requests_mock.last_request.qs - qs_args_expected = expected_query or filter_kwargs - for key, value in six.iteritems(qs_args_expected): - self.assertIn(key, qs_args) - # The querystring value is a list. Note we convert the value to a - # string and lower, as the query string is always a string and the - # filter_kwargs may contain non-string values, for example a - # boolean, causing the comaprison to fail. - self.assertIn(str(value).lower(), qs_args[key]) - - # Also check that no query string args exist which are not expected - for key in qs_args: - self.assertIn(key, qs_args_expected) - - def test_list_params(self): - ref_list = [self.new_ref()] - filter_kwargs = {uuid.uuid4().hex: uuid.uuid4().hex} - expected_path = self._get_expected_path() - - self.requests_mock.get(urlparse.urljoin(self.TEST_URL, expected_path), - json=self.encode(ref_list)) - - self.manager.list(**filter_kwargs) - self.assertQueryStringContains(**filter_kwargs) - - def test_find(self, ref=None): - ref = ref or self.new_ref() - ref_list = [ref] - - self.stub_entity('GET', entity=ref_list) - - returned = self.manager.find(name=getattr(ref, 'name', None)) - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - - if hasattr(ref, 'name'): - self.assertQueryStringIs('name=%s' % ref['name']) - else: - self.assertQueryStringIs('') - - def test_update(self, ref=None, req_ref=None): - ref = ref or self.new_ref() - - self.stub_entity('PATCH', id=ref['id'], entity=ref) - - # req_ref argument allows you to specify a different - # signature for the request when the manager does some - # conversion before doing the request (e.g. converting - # from datetime object to timestamp string) - if req_ref: - req_ref = req_ref.copy() - else: - req_ref = ref.copy() - req_ref.pop('id') - - returned = self.manager.update(ref['id'], **parameterize(req_ref)) - self.assertIsInstance(returned, self.model) - for attr in ref: - self.assertEqual( - getattr(returned, attr), - ref[attr], - 'Expected different %s' % attr) - self.assertEntityRequestBodyIs(req_ref) - - def test_delete(self, ref=None): - ref = ref or self.new_ref() - - self.stub_entity('DELETE', id=ref['id'], status_code=204) - self.manager.delete(ref['id']) diff --git a/awx/lib/site-packages/keystoneclient/utils.py b/awx/lib/site-packages/keystoneclient/utils.py deleted file mode 100644 index 7a2739f5b2..0000000000 --- a/awx/lib/site-packages/keystoneclient/utils.py +++ /dev/null @@ -1,320 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import functools -import getpass -import hashlib -import inspect -import logging -import sys - -from oslo_utils import encodeutils -import prettytable -import six - -from keystoneclient import exceptions - - -logger = logging.getLogger(__name__) - - -# Decorator for cli-args -def arg(*args, **kwargs): - def _decorator(func): - # Because of the semantics of decorator composition if we just append - # to the options list positional options will appear to be backwards. - func.__dict__.setdefault('arguments', []).insert(0, (args, kwargs)) - return func - return _decorator - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def print_list(objs, fields, formatters={}, order_by=None): - pt = prettytable.PrettyTable([f for f in fields], - caching=False, print_empty=False) - pt.aligns = ['l' for f in fields] - - for o in objs: - row = [] - for field in fields: - if field in formatters: - row.append(formatters[field](o)) - else: - field_name = field.lower().replace(' ', '_') - data = getattr(o, field_name, '') - if data is None: - data = '' - row.append(data) - pt.add_row(row) - - if order_by is None: - order_by = fields[0] - encoded = encodeutils.safe_encode(pt.get_string(sortby=order_by)) - if six.PY3: - encoded = encoded.decode() - print(encoded) - - -def _word_wrap(string, max_length=0): - """wrap long strings to be no longer than max_length.""" - if max_length <= 0: - return string - return '\n'.join([string[i:i + max_length] for i in - range(0, len(string), max_length)]) - - -def print_dict(d, wrap=0): - """pretty table prints dictionaries. - - Wrap values to max_length wrap if wrap>0 - """ - pt = prettytable.PrettyTable(['Property', 'Value'], - caching=False, print_empty=False) - pt.aligns = ['l', 'l'] - for (prop, value) in six.iteritems(d): - if value is None: - value = '' - value = _word_wrap(value, max_length=wrap) - pt.add_row([prop, value]) - encoded = encodeutils.safe_encode(pt.get_string(sortby='Property')) - if six.PY3: - encoded = encoded.decode() - print(encoded) - - -def find_resource(manager, name_or_id): - """Helper for the _find_* methods.""" - - # first try the entity as a string - try: - return manager.get(name_or_id) - except (exceptions.NotFound): - pass - - # finally try to find entity by name - try: - if isinstance(name_or_id, six.binary_type): - name_or_id = name_or_id.decode('utf-8', 'strict') - return manager.find(name=name_or_id) - except exceptions.NotFound: - msg = ("No %s with a name or ID of '%s' exists." % - (manager.resource_class.__name__.lower(), name_or_id)) - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = ("Multiple %s matches found for '%s', use an ID to be more" - " specific." % (manager.resource_class.__name__.lower(), - name_or_id)) - raise exceptions.CommandError(msg) - - -def unauthenticated(f): - """Adds 'unauthenticated' attribute to decorated function. - - Usage:: - - @unauthenticated - def mymethod(f): - ... - """ - f.unauthenticated = True - return f - - -def isunauthenticated(f): - """Checks to see if the function is marked as not requiring authentication - with the @unauthenticated decorator. - - Returns True if decorator is set to True, False otherwise. - """ - return getattr(f, 'unauthenticated', False) - - -def hash_signed_token(signed_text, mode='md5'): - hash_ = hashlib.new(mode) - hash_.update(signed_text) - return hash_.hexdigest() - - -def prompt_for_password(): - """Prompt user for password if not provided so the password - doesn't show up in the bash history. - """ - if not (hasattr(sys.stdin, 'isatty') and sys.stdin.isatty()): - # nothing to do - return - - while True: - try: - new_passwd = getpass.getpass('New Password: ') - rep_passwd = getpass.getpass('Repeat New Password: ') - if new_passwd == rep_passwd: - return new_passwd - except EOFError: - return - - -class positional(object): - """A decorator which enforces only some args may be passed positionally. - - This idea and some of the code was taken from the oauth2 client of the - google-api client. - - This decorator makes it easy to support Python 3 style key-word only - parameters. For example, in Python 3 it is possible to write:: - - def fn(pos1, *, kwonly1, kwonly2=None): - ... - - All named parameters after * must be a keyword:: - - fn(10, 'kw1', 'kw2') # Raises exception. - fn(10, kwonly1='kw1', kwonly2='kw2') # Ok. - - To replicate this behaviour with the positional decorator you simply - specify how many arguments may be passed positionally. To replicate the - example above:: - - @positional(1) - def fn(pos1, kwonly1=None, kwonly2=None): - ... - - If no default value is provided to a keyword argument, it becomes a - required keyword argument:: - - @positional(0) - def fn(required_kw): - ... - - This must be called with the keyword parameter:: - - fn() # Raises exception. - fn(10) # Raises exception. - fn(required_kw=10) # Ok. - - When defining instance or class methods always remember that in python the - first positional argument passed is always the instance so you will need to - account for `self` and `cls`:: - - class MyClass(object): - - @positional(2) - def my_method(self, pos1, kwonly1=None): - ... - - @classmethod - @positional(2) - def my_method(cls, pos1, kwonly1=None): - ... - - If you would prefer not to account for `self` and `cls` you can use the - `method` and `classmethod` helpers which do not consider the initial - positional argument. So the following class is exactly the same as the one - above:: - - class MyClass(object): - - @positional.method(1) - def my_method(self, pos1, kwonly1=None): - ... - - @positional.classmethod(1) - def my_method(cls, pos1, kwonly1=None): - ... - - If a value isn't provided to the decorator then it will enforce that - every variable without a default value will be required to be a kwarg:: - - @positional() - def fn(pos1, kwonly1=None): - ... - - fn(10) # Ok. - fn(10, 20) # Raises exception. - fn(10, kwonly1=20) # Ok. - - This behaviour will work with the `positional.method` and - `positional.classmethod` helper functions as well:: - - class MyClass(object): - - @positional.classmethod() - def my_method(cls, pos1, kwonly1=None): - ... - - MyClass.my_method(10) # Ok. - MyClass.my_method(10, 20) # Raises exception. - MyClass.my_method(10, kwonly1=20) # Ok. - - For compatibility reasons you may wish to not always raise an exception so - a WARN mode is available. Rather than raise an exception a warning message - will be logged:: - - @positional(1, enforcement=positional.WARN): - def fn(pos1, kwonly=1): - ... - - Available modes are: - - - positional.EXCEPT - the default, raise an exception. - - positional.WARN - log a warning on mistake. - """ - - EXCEPT = 'except' - WARN = 'warn' - - def __init__(self, max_positional_args=None, enforcement=EXCEPT): - self._max_positional_args = max_positional_args - self._enforcement = enforcement - - @classmethod - def method(cls, max_positional_args=None, enforcement=EXCEPT): - if max_positional_args is not None: - max_positional_args += 1 - - def f(func): - return cls(max_positional_args, enforcement)(func) - return f - - @classmethod - def classmethod(cls, *args, **kwargs): - def f(func): - return classmethod(cls.method(*args, **kwargs)(func)) - return f - - def __call__(self, func): - if self._max_positional_args is None: - spec = inspect.getargspec(func) - self._max_positional_args = len(spec.args) - len(spec.defaults) - - plural = '' if self._max_positional_args == 1 else 's' - - @functools.wraps(func) - def inner(*args, **kwargs): - if len(args) > self._max_positional_args: - message = ('%(name)s takes at most %(max)d positional ' - 'argument%(plural)s (%(given)d given)' % - {'name': func.__name__, - 'max': self._max_positional_args, - 'given': len(args), - 'plural': plural}) - - if self._enforcement == self.EXCEPT: - raise TypeError(message) - elif self._enforcement == self.WARN: - logger.warn(message) - - return func(*args, **kwargs) - - return inner diff --git a/awx/lib/site-packages/keystoneclient/v2_0/__init__.py b/awx/lib/site-packages/keystoneclient/v2_0/__init__.py deleted file mode 100644 index 30407e0c63..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from keystoneclient.v2_0.client import Client # noqa - - -__all__ = [ - 'client', -] diff --git a/awx/lib/site-packages/keystoneclient/v2_0/certificates.py b/awx/lib/site-packages/keystoneclient/v2_0/certificates.py deleted file mode 100644 index b8d2573f0e..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/certificates.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2014 IBM Corp. -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class CertificatesManager(object): - """Manager for certificates.""" - - def __init__(self, client): - self._client = client - - def get_ca_certificate(self): - """Get CA certificate. - - :returns: PEM-formatted string. - :rtype: str - - """ - - resp, body = self._client.get('/certificates/ca', authenticated=False) - return resp.text - - def get_signing_certificate(self): - """Get signing certificate. - - :returns: PEM-formatted string. - :rtype: str - - """ - - resp, body = self._client.get('/certificates/signing', - authenticated=False) - return resp.text diff --git a/awx/lib/site-packages/keystoneclient/v2_0/client.py b/awx/lib/site-packages/keystoneclient/v2_0/client.py deleted file mode 100644 index bba556e837..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/client.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -from keystoneclient.auth.identity import v2 as v2_auth -from keystoneclient import exceptions -from keystoneclient import httpclient -from keystoneclient.i18n import _ -from keystoneclient.v2_0 import certificates -from keystoneclient.v2_0 import ec2 -from keystoneclient.v2_0 import endpoints -from keystoneclient.v2_0 import extensions -from keystoneclient.v2_0 import roles -from keystoneclient.v2_0 import services -from keystoneclient.v2_0 import tenants -from keystoneclient.v2_0 import tokens -from keystoneclient.v2_0 import users - - -_logger = logging.getLogger(__name__) - - -class Client(httpclient.HTTPClient): - """Client for the OpenStack Keystone v2.0 API. - - :param string username: Username for authentication. (optional) - :param string password: Password for authentication. (optional) - :param string token: Token for authentication. (optional) - :param string tenant_id: Tenant id. (optional) - :param string tenant_name: Tenant name. (optional) - :param string auth_url: Keystone service endpoint for authorization. - :param string region_name: Name of a region to select when choosing an - endpoint from the service catalog. - :param string endpoint: A user-supplied endpoint URL for the keystone - service. Lazy-authentication is possible for API - service calls if endpoint is set at - instantiation.(optional) - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - :param string original_ip: The original IP of the requesting user - which will be sent to Keystone in a - 'Forwarded' header. (optional) - :param string cert: Path to the Privacy Enhanced Mail (PEM) file which - contains the corresponding X.509 client certificate - needed to established two-way SSL connection with - the identity service. (optional) - :param string key: Path to the Privacy Enhanced Mail (PEM) file which - contains the unencrypted client private key needed - to established two-way SSL connection with the - identity service. (optional) - :param string cacert: Path to the Privacy Enhanced Mail (PEM) file which - contains the trusted authority X.509 certificates - needed to established SSL connection with the - identity service. (optional) - :param boolean insecure: Does not perform X.509 certificate validation - when establishing SSL connection with identity - service. default: False (optional) - :param dict auth_ref: To allow for consumers of the client to manage their - own caching strategy, you may initialize a client - with a previously captured auth_reference (token) - :param boolean debug: Enables debug logging of all request and responses - to keystone. default False (option) - - .. warning:: - - If debug is enabled, it may show passwords in plain text as a part of - its output. - - - The client can be created and used like a user or in a strictly - bootstrap mode. Normal operation expects a username, password, auth_url, - and tenant_name or id to be provided. Other values will be lazily loaded - as needed from the service catalog. - - Example:: - - >>> from keystoneclient.v2_0 import client - >>> keystone = client.Client(username=USER, - ... password=PASS, - ... tenant_name=TENANT_NAME, - ... auth_url=KEYSTONE_URL) - >>> keystone.tenants.list() - ... - >>> user = keystone.users.get(USER_ID) - >>> user.delete() - - Once authenticated, you can store and attempt to re-use the - authenticated token. the auth_ref property on the client - returns as a dictionary-like-object so that you can export and - cache it, re-using it when initiating another client:: - - >>> from keystoneclient.v2_0 import client - >>> keystone = client.Client(username=USER, - ... password=PASS, - ... tenant_name=TENANT_NAME, - ... auth_url=KEYSTONE_URL) - >>> auth_ref = keystone.auth_ref - >>> # pickle or whatever you like here - >>> new_client = client.Client(auth_ref=auth_ref) - - Alternatively, you can provide the administrative token configured in - keystone and an endpoint to communicate with directly. See - (``admin_token`` in ``keystone.conf``) In this case, authenticate() - is not needed, and no service catalog will be loaded. - - Example:: - - >>> from keystoneclient.v2_0 import client - >>> admin_client = client.Client( - ... token='12345secret7890', - ... endpoint='http://localhost:35357/v2.0') - >>> admin_client.tenants.list() - - """ - - version = 'v2.0' - - def __init__(self, **kwargs): - """Initialize a new client for the Keystone v2.0 API.""" - super(Client, self).__init__(**kwargs) - - self.certificates = certificates.CertificatesManager(self._adapter) - self.endpoints = endpoints.EndpointManager(self._adapter) - self.extensions = extensions.ExtensionManager(self._adapter) - self.roles = roles.RoleManager(self._adapter) - self.services = services.ServiceManager(self._adapter) - self.tokens = tokens.TokenManager(self._adapter) - self.users = users.UserManager(self._adapter, self.roles) - - self.tenants = tenants.TenantManager(self._adapter, - self.roles, self.users) - - # extensions - self.ec2 = ec2.CredentialsManager(self._adapter) - - # DEPRECATED: if session is passed then we go to the new behaviour of - # authenticating on the first required call. - if not kwargs.get('session') and self.management_url is None: - self.authenticate() - - def get_raw_token_from_identity_service(self, auth_url, username=None, - password=None, tenant_name=None, - tenant_id=None, token=None, - project_name=None, project_id=None, - trust_id=None, - **kwargs): - """Authenticate against the v2 Identity API. - - If a token is provided it will be used in preference over username and - password. - - :returns: access.AccessInfo if authentication was successful. - :raises keystoneclient.exceptions.AuthorizationFailure: if unable to - authenticate or validate the existing authorization token - """ - try: - if auth_url is None: - raise ValueError(_("Cannot authenticate without an auth_url")) - - new_kwargs = {'trust_id': trust_id, - 'tenant_id': project_id or tenant_id, - 'tenant_name': project_name or tenant_name} - - if token: - plugin = v2_auth.Token(auth_url, token, **new_kwargs) - elif username and password: - plugin = v2_auth.Password(auth_url, username, password, - **new_kwargs) - else: - msg = _('A username and password or token is required.') - raise exceptions.AuthorizationFailure(msg) - - return plugin.get_auth_ref(self.session) - except (exceptions.AuthorizationFailure, exceptions.Unauthorized): - _logger.debug("Authorization Failed.") - raise - except exceptions.EndpointNotFound: - msg = ( - _('There was no suitable authentication url for this request')) - raise exceptions.AuthorizationFailure(msg) - except Exception as e: - raise exceptions.AuthorizationFailure( - _("Authorization Failed: %s") % e) diff --git a/awx/lib/site-packages/keystoneclient/v2_0/ec2.py b/awx/lib/site-packages/keystoneclient/v2_0/ec2.py deleted file mode 100644 index 0baf224f91..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/ec2.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base - - -class EC2(base.Resource): - def __repr__(self): - return "<EC2 %s>" % self._info - - def delete(self): - return self.manager.delete(self) - - -class CredentialsManager(base.ManagerWithFind): - resource_class = EC2 - - def create(self, user_id, tenant_id): - """Create a new access/secret pair for the user/tenant pair. - - :rtype: object of type :class:`EC2` - """ - - params = {'tenant_id': tenant_id} - - return self._create('/users/%s/credentials/OS-EC2' % user_id, - params, "credential") - - def list(self, user_id): - """Get a list of access/secret pairs for a user_id. - - :rtype: list of :class:`EC2` - """ - return self._list("/users/%s/credentials/OS-EC2" % user_id, - "credentials") - - def get(self, user_id, access): - """Get the access/secret pair for a given access key. - - :rtype: object of type :class:`EC2` - """ - return self._get("/users/%s/credentials/OS-EC2/%s" % - (user_id, base.getid(access)), "credential") - - def delete(self, user_id, access): - """Delete an access/secret pair for a user.""" - return self._delete("/users/%s/credentials/OS-EC2/%s" % - (user_id, base.getid(access))) diff --git a/awx/lib/site-packages/keystoneclient/v2_0/endpoints.py b/awx/lib/site-packages/keystoneclient/v2_0/endpoints.py deleted file mode 100644 index 35bda258ff..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/endpoints.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2012 Canonical Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base - - -class Endpoint(base.Resource): - """Represents a Keystone endpoint.""" - def __repr__(self): - return "<Endpoint %s>" % self._info - - -class EndpointManager(base.ManagerWithFind): - """Manager class for manipulating Keystone endpoints.""" - - resource_class = Endpoint - - def list(self): - """List all available endpoints.""" - return self._list('/endpoints', 'endpoints') - - def create(self, region, service_id, publicurl, adminurl=None, - internalurl=None): - """Create a new endpoint.""" - body = {'endpoint': {'region': region, - 'service_id': service_id, - 'publicurl': publicurl, - 'adminurl': adminurl, - 'internalurl': internalurl}} - return self._create('/endpoints', body, 'endpoint') - - def delete(self, id): - """Delete an endpoint.""" - return self._delete('/endpoints/%s' % id) diff --git a/awx/lib/site-packages/keystoneclient/v2_0/extensions.py b/awx/lib/site-packages/keystoneclient/v2_0/extensions.py deleted file mode 100644 index b805d31de3..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/extensions.py +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base - - -class Extension(base.Resource): - """Represents an Identity API extension.""" - def __repr__(self): - return "<Extension %s>" % self._info - - -class ExtensionManager(base.ManagerWithFind): - """Manager class for listing Identity API extensions.""" - - resource_class = Extension - - def list(self): - """List all available extensions.""" - return self._list('/extensions', 'extensions') diff --git a/awx/lib/site-packages/keystoneclient/v2_0/roles.py b/awx/lib/site-packages/keystoneclient/v2_0/roles.py deleted file mode 100644 index 3fc47e96f2..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/roles.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base - - -class Role(base.Resource): - """Represents a Keystone role.""" - def __repr__(self): - return "<Role %s>" % self._info - - def delete(self): - return self.manager.delete(self) - - -class RoleManager(base.ManagerWithFind): - """Manager class for manipulating Keystone roles.""" - resource_class = Role - - def get(self, role): - return self._get("/OS-KSADM/roles/%s" % base.getid(role), "role") - - def create(self, name): - """Create a role.""" - params = {"role": {"name": name}} - return self._create('/OS-KSADM/roles', params, "role") - - def delete(self, role): - """Delete a role.""" - return self._delete("/OS-KSADM/roles/%s" % base.getid(role)) - - def list(self): - """List all available roles.""" - return self._list("/OS-KSADM/roles", "roles") - - def roles_for_user(self, user, tenant=None): - user_id = base.getid(user) - if tenant: - tenant_id = base.getid(tenant) - route = "/tenants/%s/users/%s/roles" - return self._list(route % (tenant_id, user_id), "roles") - else: - return self._list("/users/%s/roles" % user_id, "roles") - - def add_user_role(self, user, role, tenant=None): - """Adds a role to a user. - - If tenant is specified, the role is added just for that tenant, - otherwise the role is added globally. - """ - user_id = base.getid(user) - role_id = base.getid(role) - if tenant: - route = "/tenants/%s/users/%s/roles/OS-KSADM/%s" - params = (base.getid(tenant), user_id, role_id) - return self._update(route % params, None, "role") - else: - route = "/users/%s/roles/OS-KSADM/%s" - return self._update(route % (user_id, role_id), None, "roles") - - def remove_user_role(self, user, role, tenant=None): - """Removes a role from a user. - - If tenant is specified, the role is removed just for that tenant, - otherwise the role is removed from the user's global roles. - """ - user_id = base.getid(user) - role_id = base.getid(role) - if tenant: - route = "/tenants/%s/users/%s/roles/OS-KSADM/%s" - params = (base.getid(tenant), user_id, role_id) - return self._delete(route % params) - else: - route = "/users/%s/roles/OS-KSADM/%s" - return self._delete(route % (user_id, role_id)) diff --git a/awx/lib/site-packages/keystoneclient/v2_0/services.py b/awx/lib/site-packages/keystoneclient/v2_0/services.py deleted file mode 100644 index adb740d575..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/services.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base - - -class Service(base.Resource): - """Represents a Keystone service.""" - def __repr__(self): - return "<Service %s>" % self._info - - -class ServiceManager(base.ManagerWithFind): - """Manager class for manipulating Keystone services.""" - resource_class = Service - - def list(self): - """List available services.""" - return self._list("/OS-KSADM/services", "OS-KSADM:services") - - def get(self, id): - """Retrieve a service by id.""" - return self._get("/OS-KSADM/services/%s" % id, "OS-KSADM:service") - - def create(self, name, service_type, description): - """Create a new service.""" - body = {"OS-KSADM:service": {'name': name, - 'type': service_type, - 'description': description}} - return self._create("/OS-KSADM/services", body, "OS-KSADM:service") - - def delete(self, id): - """Delete a service.""" - return self._delete("/OS-KSADM/services/%s" % id) diff --git a/awx/lib/site-packages/keystoneclient/v2_0/shell.py b/awx/lib/site-packages/keystoneclient/v2_0/shell.py deleted file mode 100644 index 9d7d7ce6d2..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/shell.py +++ /dev/null @@ -1,546 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -This module is pending deprecation in favor of python-openstackclient. - -Bug fixes are welcome, but new features should be exposed to the CLI by -python-openstackclient after being added to the python-keystoneclient library. - -""" - -import argparse -import getpass -import sys - -from oslo_utils import strutils -import six - -from keystoneclient.i18n import _ -from keystoneclient import utils -from keystoneclient.v2_0 import client - - -CLIENT_CLASS = client.Client -ASK_FOR_PASSWORD = object() - - -def require_service_catalog(f): - msg = _('Configuration error: Client configured to run without a service ' - 'catalog. Run the client using --os-auth-url or OS_AUTH_URL, ' - 'instead of --os-endpoint or OS_SERVICE_ENDPOINT, for example.') - - def wrapped(kc, args): - if not kc.has_service_catalog(): - raise Exception(msg) - return f(kc, args) - - # Change __doc__ attribute back to origin function's __doc__ - wrapped.__doc__ = f.__doc__ - - return wrapped - - -@utils.arg('--tenant', '--tenant-id', metavar='<tenant>', - help='Tenant; lists all users if not specified.') -@utils.arg('--tenant_id', help=argparse.SUPPRESS) -def do_user_list(kc, args): - """List users.""" - if args.tenant: - tenant_id = utils.find_resource(kc.tenants, args.tenant).id - else: - tenant_id = None - users = kc.users.list(tenant_id=tenant_id) - utils.print_list(users, ['id', 'name', 'enabled', 'email'], - order_by='name') - - -@utils.arg('user', metavar='<user>', help='Name or ID of user to display.') -def do_user_get(kc, args): - """Display user details.""" - user = utils.find_resource(kc.users, args.user) - utils.print_dict(user._info) - - -@utils.arg('--name', metavar='<user-name>', required=True, - help='New user name (must be unique).') -@utils.arg('--tenant', '--tenant-id', metavar='<tenant>', - help='New user default tenant.') -@utils.arg('--tenant_id', help=argparse.SUPPRESS) -@utils.arg('--pass', metavar='<pass>', dest='passwd', nargs='?', - const=ASK_FOR_PASSWORD, help='New user password; ' - 'required for some auth backends.') -@utils.arg('--email', metavar='<email>', - help='New user email address.') -@utils.arg('--enabled', metavar='<true|false>', default=True, - help='Initial user enabled status. Default is true.') -def do_user_create(kc, args): - """Create new user.""" - if args.tenant: - tenant_id = utils.find_resource(kc.tenants, args.tenant).id - elif args.tenant_id: - tenant_id = args.tenant_id - else: - tenant_id = None - new_passwd = args.passwd - if args.passwd is ASK_FOR_PASSWORD: - new_passwd = utils.prompt_for_password() - user = kc.users.create(args.name, new_passwd, args.email, - tenant_id=tenant_id, - enabled=strutils.bool_from_string(args.enabled)) - utils.print_dict(user._info) - - -@utils.arg('--name', metavar='<user-name>', - help='Desired new user name.') -@utils.arg('--email', metavar='<email>', - help='Desired new email address.') -@utils.arg('--enabled', metavar='<true|false>', - help='Enable or disable user.') -@utils.arg('user', metavar='<user>', help='Name or ID of user to update.') -def do_user_update(kc, args): - """Update user's name, email, and enabled status.""" - kwargs = {} - if args.name: - kwargs['name'] = args.name - if args.email is not None: - kwargs['email'] = args.email - if args.enabled: - kwargs['enabled'] = strutils.bool_from_string(args.enabled) - - if not len(kwargs): - print(_("User not updated, no arguments present.")) - return - - user = utils.find_resource(kc.users, args.user) - try: - kc.users.update(user, **kwargs) - print(_('User has been updated.')) - except Exception as e: - print(_('Unable to update user: %s') % e) - - -@utils.arg('--pass', metavar='<password>', dest='passwd', required=False, - help='Desired new password.') -@utils.arg('user', metavar='<user>', - help='Name or ID of user to update password.') -def do_user_password_update(kc, args): - """Update user password.""" - user = utils.find_resource(kc.users, args.user) - new_passwd = args.passwd or utils.prompt_for_password() - if new_passwd is None: - msg = (_("\nPlease specify password using the --pass option " - "or using the prompt")) - sys.exit(msg) - kc.users.update_password(user, new_passwd) - - -@utils.arg('--current-password', metavar='<current-password>', - dest='currentpasswd', required=False, help='Current password, ' - 'Defaults to the password as set by --os-password or ' - 'env[OS_PASSWORD].') -@utils.arg('--new-password ', metavar='<new-password>', dest='newpasswd', - required=False, help='Desired new password.') -def do_password_update(kc, args): - """Update own password.""" - - # we are prompting for these passwords if they are not passed in - # this gives users the option not to have their password - # appear in bash history etc.. - currentpasswd = args.os_password - if args.currentpasswd is not None: - currentpasswd = args.currentpasswd - if currentpasswd is None: - currentpasswd = getpass.getpass(_('Current Password: ')) - - newpasswd = args.newpasswd - while newpasswd is None: - passwd1 = getpass.getpass(_('New Password: ')) - passwd2 = getpass.getpass(_('Repeat New Password: ')) - if passwd1 == passwd2: - newpasswd = passwd1 - - kc.users.update_own_password(currentpasswd, newpasswd) - - if args.os_password != newpasswd: - print(_("You should update the password you are using to authenticate " - "to match your new password")) - - -@utils.arg('user', metavar='<user>', help='Name or ID of user to delete.') -def do_user_delete(kc, args): - """Delete user.""" - user = utils.find_resource(kc.users, args.user) - kc.users.delete(user) - - -def do_tenant_list(kc, args): - """List all tenants.""" - tenants = kc.tenants.list() - utils.print_list(tenants, ['id', 'name', 'enabled'], order_by='name') - - -@utils.arg('tenant', metavar='<tenant>', - help='Name or ID of tenant to display.') -def do_tenant_get(kc, args): - """Display tenant details.""" - tenant = utils.find_resource(kc.tenants, args.tenant) - utils.print_dict(tenant._info) - - -@utils.arg('--name', metavar='<tenant-name>', required=True, - help='New tenant name (must be unique).') -@utils.arg('--description', metavar='<tenant-description>', default=None, - help='Description of new tenant. Default is none.') -@utils.arg('--enabled', metavar='<true|false>', default=True, - help='Initial tenant enabled status. Default is true.') -def do_tenant_create(kc, args): - """Create new tenant.""" - tenant = kc.tenants.create(args.name, - description=args.description, - enabled=strutils.bool_from_string(args.enabled)) - utils.print_dict(tenant._info) - - -@utils.arg('--name', metavar='<tenant_name>', - help='Desired new name of tenant.') -@utils.arg('--description', metavar='<tenant-description>', default=None, - help='Desired new description of tenant.') -@utils.arg('--enabled', metavar='<true|false>', - help='Enable or disable tenant.') -@utils.arg('tenant', metavar='<tenant>', - help='Name or ID of tenant to update.') -def do_tenant_update(kc, args): - """Update tenant name, description, enabled status.""" - tenant = utils.find_resource(kc.tenants, args.tenant) - kwargs = {} - if args.name: - kwargs.update({'name': args.name}) - if args.description is not None: - kwargs.update({'description': args.description}) - if args.enabled: - kwargs.update({'enabled': strutils.bool_from_string(args.enabled)}) - - if kwargs == {}: - print(_("Tenant not updated, no arguments present.")) - return - tenant.update(**kwargs) - - -@utils.arg('tenant', metavar='<tenant>', - help='Name or ID of tenant to delete.') -def do_tenant_delete(kc, args): - """Delete tenant.""" - tenant = utils.find_resource(kc.tenants, args.tenant) - kc.tenants.delete(tenant) - - -@utils.arg('--type', metavar='<type>', required=True, - help='Service type (one of: identity, compute, network, ' - 'image, object-store, or other service identifier string).') -@utils.arg('--name', metavar='<name>', - help='Name of new service (must be unique).') -@utils.arg('--description', metavar='<service-description>', - help='Description of service.') -def do_service_create(kc, args): - """Add service to Service Catalog.""" - service = kc.services.create(args.name, - args.type, - args.description) - utils.print_dict(service._info) - - -def do_service_list(kc, args): - """List all services in Service Catalog.""" - services = kc.services.list() - utils.print_list(services, ['id', 'name', 'type', 'description'], - order_by='name') - - -@utils.arg('service', metavar='<service>', - help='Name or ID of service to display.') -def do_service_get(kc, args): - """Display service from Service Catalog.""" - service = utils.find_resource(kc.services, args.service) - utils.print_dict(service._info) - - -@utils.arg('service', metavar='<service>', - help='Name or ID of service to delete.') -def do_service_delete(kc, args): - """Delete service from Service Catalog.""" - service = utils.find_resource(kc.services, args.service) - kc.services.delete(service.id) - - -def do_role_list(kc, args): - """List all roles.""" - roles = kc.roles.list() - utils.print_list(roles, ['id', 'name'], order_by='name') - - -@utils.arg('role', metavar='<role>', help='Name or ID of role to display.') -def do_role_get(kc, args): - """Display role details.""" - role = utils.find_resource(kc.roles, args.role) - utils.print_dict(role._info) - - -@utils.arg('--name', metavar='<role-name>', required=True, - help='Name of new role.') -def do_role_create(kc, args): - """Create new role.""" - role = kc.roles.create(args.name) - utils.print_dict(role._info) - - -@utils.arg('role', metavar='<role>', help='Name or ID of role to delete.') -def do_role_delete(kc, args): - """Delete role.""" - role = utils.find_resource(kc.roles, args.role) - kc.roles.delete(role) - - -@utils.arg('--user', '--user-id', '--user_id', metavar='<user>', - required=True, help='Name or ID of user.') -@utils.arg('--role', '--role-id', '--role_id', metavar='<role>', - required=True, help='Name or ID of role.') -@utils.arg('--tenant', '--tenant-id', metavar='<tenant>', - help='Name or ID of tenant.') -@utils.arg('--tenant_id', help=argparse.SUPPRESS) -def do_user_role_add(kc, args): - """Add role to user.""" - user = utils.find_resource(kc.users, args.user) - role = utils.find_resource(kc.roles, args.role) - if args.tenant: - tenant = utils.find_resource(kc.tenants, args.tenant) - elif args.tenant_id: - tenant = args.tenant_id - else: - tenant = None - kc.roles.add_user_role(user, role, tenant) - - -@utils.arg('--user', '--user-id', '--user_id', metavar='<user>', - required=True, help='Name or ID of user.') -@utils.arg('--role', '--role-id', '--role_id', metavar='<role>', - required=True, help='Name or ID of role.') -@utils.arg('--tenant', '--tenant-id', metavar='<tenant>', - help='Name or ID of tenant.') -@utils.arg('--tenant_id', help=argparse.SUPPRESS) -def do_user_role_remove(kc, args): - """Remove role from user.""" - user = utils.find_resource(kc.users, args.user) - role = utils.find_resource(kc.roles, args.role) - if args.tenant: - tenant = utils.find_resource(kc.tenants, args.tenant) - elif args.tenant_id: - tenant = args.tenant_id - else: - tenant = None - kc.roles.remove_user_role(user, role, tenant) - - -@utils.arg('--user', '--user-id', metavar='<user>', - help='List roles granted to specified user.') -@utils.arg('--user_id', help=argparse.SUPPRESS) -@utils.arg('--tenant', '--tenant-id', metavar='<tenant>', - help='List only roles granted on specified tenant.') -@utils.arg('--tenant_id', help=argparse.SUPPRESS) -def do_user_role_list(kc, args): - """List roles granted to a user.""" - if args.tenant: - tenant_id = utils.find_resource(kc.tenants, args.tenant).id - elif args.tenant_id: - tenant_id = args.tenant_id - else: - # use the authenticated tenant id as a default - tenant_id = kc.auth_tenant_id - - if args.user: - user_id = utils.find_resource(kc.users, args.user).id - elif args.user_id: - user_id = args.user_id - else: - # use the authenticated user id as a default - user_id = kc.auth_user_id - roles = kc.roles.roles_for_user(user=user_id, tenant=tenant_id) - - # this makes the command output a bit more intuitive - for role in roles: - role.user_id = user_id - role.tenant_id = tenant_id - - utils.print_list(roles, ['id', 'name', 'user_id', 'tenant_id'], - order_by='name') - - -@utils.arg('--user-id', metavar='<user-id>', - help='User ID for which to create credentials. If not specified, ' - 'the authenticated user will be used.') -@utils.arg('--user_id', help=argparse.SUPPRESS) -@utils.arg('--tenant-id', metavar='<tenant-id>', - help='Tenant ID for which to create credentials. If not ' - 'specified, the authenticated tenant ID will be used.') -@utils.arg('--tenant_id', help=argparse.SUPPRESS) -def do_ec2_credentials_create(kc, args): - """Create EC2-compatible credentials for user per tenant.""" - if not args.tenant_id: - # use the authenticated tenant id as a default - args.tenant_id = kc.auth_tenant_id - if not args.user_id: - # use the authenticated user id as a default - args.user_id = kc.auth_user_id - credentials = kc.ec2.create(args.user_id, args.tenant_id) - utils.print_dict(credentials._info) - - -@utils.arg('--user-id', metavar='<user-id>', help='User ID.') -@utils.arg('--user_id', help=argparse.SUPPRESS) -@utils.arg('--access', metavar='<access-key>', required=True, - help='Access Key.') -def do_ec2_credentials_get(kc, args): - """Display EC2-compatible credentials.""" - if not args.user_id: - # use the authenticated user id as a default - args.user_id = kc.auth_user_id - cred = kc.ec2.get(args.user_id, args.access) - if cred: - utils.print_dict(cred._info) - - -@utils.arg('--user-id', metavar='<user-id>', help='User ID.') -@utils.arg('--user_id', help=argparse.SUPPRESS) -def do_ec2_credentials_list(kc, args): - """List EC2-compatible credentials for a user.""" - if not args.user_id: - # use the authenticated user id as a default - args.user_id = kc.auth_user_id - credentials = kc.ec2.list(args.user_id) - for cred in credentials: - try: - cred.tenant = getattr(kc.tenants.get(cred.tenant_id), 'name') - except Exception: - # FIXME(dtroyer): Retrieving the tenant name fails for normal - # users; stuff in the tenant_id instead. - cred.tenant = cred.tenant_id - utils.print_list(credentials, ['tenant', 'access', 'secret']) - - -@utils.arg('--user-id', metavar='<user-id>', help='User ID.') -@utils.arg('--user_id', help=argparse.SUPPRESS) -@utils.arg('--access', metavar='<access-key>', required=True, - help='Access Key.') -def do_ec2_credentials_delete(kc, args): - """Delete EC2-compatible credentials.""" - if not args.user_id: - # use the authenticated user id as a default - args.user_id = kc.auth_user_id - try: - kc.ec2.delete(args.user_id, args.access) - print(_('Credential has been deleted.')) - except Exception as e: - print(_('Unable to delete credential: %s') % e) - - -@utils.arg('--service', metavar='<service-type>', default=None, - help='Service type to return.') -@require_service_catalog -def do_catalog(kc, args): - """List service catalog, possibly filtered by service.""" - endpoints = kc.service_catalog.get_endpoints(service_type=args.service) - for (service, service_endpoints) in six.iteritems(endpoints): - if len(service_endpoints) > 0: - print(_("Service: %s") % service) - for ep in service_endpoints: - utils.print_dict(ep) - - -@utils.arg('--service', metavar='<service-type>', required=True, - help='Service type to select.') -@utils.arg('--endpoint-type', metavar='<endpoint-type>', default='publicURL', - help='Endpoint type to select.') -@utils.arg('--endpoint_type', default='publicURL', - help=argparse.SUPPRESS) -@utils.arg('--attr', metavar='<service-attribute>', - help='Service attribute to match for selection.') -@utils.arg('--value', metavar='<value>', - help='Value of attribute to match.') -@require_service_catalog -def do_endpoint_get(kc, args): - """Find endpoint filtered by a specific attribute or service type.""" - kwargs = { - 'service_type': args.service, - 'endpoint_type': args.endpoint_type, - } - - if args.attr and args.value: - kwargs.update({'attr': args.attr, 'filter_value': args.value}) - elif args.attr or args.value: - print(_('Both --attr and --value required.')) - return - - url = kc.service_catalog.url_for(**kwargs) - utils.print_dict({'%s.%s' % (args.service, args.endpoint_type): url}) - - -def do_endpoint_list(kc, args): - """List configured service endpoints.""" - endpoints = kc.endpoints.list() - utils.print_list(endpoints, - ['id', 'region', 'publicurl', - 'internalurl', 'adminurl', 'service_id']) - - -@utils.arg('--region', metavar='<endpoint-region>', - help='Endpoint region.', default='regionOne') -@utils.arg('--service', '--service-id', '--service_id', - metavar='<service>', required=True, - help='Name or ID of service associated with endpoint.') -@utils.arg('--publicurl', metavar='<public-url>', required=True, - help='Public URL endpoint.') -@utils.arg('--adminurl', metavar='<admin-url>', - help='Admin URL endpoint.') -@utils.arg('--internalurl', metavar='<internal-url>', - help='Internal URL endpoint.') -def do_endpoint_create(kc, args): - """Create a new endpoint associated with a service.""" - service_id = utils.find_resource(kc.services, args.service).id - endpoint = kc.endpoints.create(args.region, - service_id, - args.publicurl, - args.adminurl, - args.internalurl) - utils.print_dict(endpoint._info) - - -@utils.arg('id', metavar='<endpoint-id>', help='ID of endpoint to delete.') -def do_endpoint_delete(kc, args): - """Delete a service endpoint.""" - try: - kc.endpoints.delete(args.id) - print(_('Endpoint has been deleted.')) - except Exception: - print(_('Unable to delete endpoint.')) - - -@utils.arg('--wrap', metavar='<integer>', default=0, - help='Wrap PKI tokens to a specified length, or 0 to disable.') -@require_service_catalog -def do_token_get(kc, args): - """Display the current user token.""" - utils.print_dict(kc.service_catalog.get_token(), - wrap=int(args.wrap)) diff --git a/awx/lib/site-packages/keystoneclient/v2_0/tenants.py b/awx/lib/site-packages/keystoneclient/v2_0/tenants.py deleted file mode 100644 index 79d98d559c..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/tenants.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six -from six.moves import urllib - -from keystoneclient import auth -from keystoneclient import base -from keystoneclient import exceptions - - -class Tenant(base.Resource): - """Represents a Keystone tenant - - Attributes: - * id: a uuid that identifies the tenant - * name: tenant name - * description: tenant description - * enabled: boolean to indicate if tenant is enabled - - """ - def __repr__(self): - return "<Tenant %s>" % self._info - - def delete(self): - return self.manager.delete(self) - - def update(self, name=None, description=None, enabled=None): - # Preserve the existing settings; keystone legacy resets these? - new_name = name if name else self.name - if description is not None: - new_description = description - else: - new_description = self.description - new_enabled = enabled if enabled is not None else self.enabled - - try: - retval = self.manager.update(self.id, tenant_name=new_name, - description=new_description, - enabled=new_enabled) - self = retval - except Exception: - retval = None - return retval - - def add_user(self, user, role): - return self.manager.role_manager.add_user_role(base.getid(user), - base.getid(role), - self.id) - - def remove_user(self, user, role): - return self.manager.role_manager.remove_user_role(base.getid(user), - base.getid(role), - self.id) - - def list_users(self): - return self.manager.list_users(self.id) - - -class TenantManager(base.ManagerWithFind): - """Manager class for manipulating Keystone tenants.""" - resource_class = Tenant - - def __init__(self, client, role_manager, user_manager): - super(TenantManager, self).__init__(client) - self.role_manager = role_manager - self.user_manager = user_manager - - def get(self, tenant_id): - return self._get("/tenants/%s" % tenant_id, "tenant") - - def create(self, tenant_name, description=None, enabled=True, **kwargs): - """Create a new tenant.""" - params = {"tenant": {"name": tenant_name, - "description": description, - "enabled": enabled}} - - # Allow Extras Passthru and ensure we don't clobber primary arguments. - for k, v in six.iteritems(kwargs): - if k not in params['tenant']: - params['tenant'][k] = v - - return self._create('/tenants', params, "tenant") - - def list(self, limit=None, marker=None): - """Get a list of tenants. - - :param integer limit: maximum number to return. (optional) - :param string marker: use when specifying a limit and making - multiple calls for querying. (optional) - - :rtype: list of :class:`Tenant` - - """ - - params = {} - if limit: - params['limit'] = limit - if marker: - params['marker'] = marker - - query = "" - if params: - query = "?" + urllib.parse.urlencode(params) - - # NOTE(jamielennox): try doing a regular admin query first. If there is - # no endpoint that can satisfy the request (eg an unscoped token) then - # issue it against the auth_url. - try: - tenant_list = self._list('/tenants%s' % query, 'tenants') - except exceptions.EndpointNotFound: - endpoint_filter = {'interface': auth.AUTH_INTERFACE} - tenant_list = self._list('/tenants%s' % query, 'tenants', - endpoint_filter=endpoint_filter) - - return tenant_list - - def update(self, tenant_id, tenant_name=None, description=None, - enabled=None, **kwargs): - """Update a tenant with a new name and description.""" - body = {"tenant": {'id': tenant_id}} - if tenant_name is not None: - body['tenant']['name'] = tenant_name - if enabled is not None: - body['tenant']['enabled'] = enabled - if description is not None: - body['tenant']['description'] = description - - # Allow Extras Passthru and ensure we don't clobber primary arguments. - for k, v in six.iteritems(kwargs): - if k not in body['tenant']: - body['tenant'][k] = v - - # Keystone's API uses a POST rather than a PUT here. - return self._create("/tenants/%s" % tenant_id, body, "tenant") - - def delete(self, tenant): - """Delete a tenant.""" - return self._delete("/tenants/%s" % (base.getid(tenant))) - - def list_users(self, tenant): - """List users for a tenant.""" - return self.user_manager.list(base.getid(tenant)) - - def add_user(self, tenant, user, role): - """Add a user to a tenant with the given role.""" - return self.role_manager.add_user_role(base.getid(user), - base.getid(role), - base.getid(tenant)) - - def remove_user(self, tenant, user, role): - """Remove the specified role from the user on the tenant.""" - return self.role_manager.remove_user_role(base.getid(user), - base.getid(role), - base.getid(tenant)) diff --git a/awx/lib/site-packages/keystoneclient/v2_0/tokens.py b/awx/lib/site-packages/keystoneclient/v2_0/tokens.py deleted file mode 100644 index 670d65b1ce..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/tokens.py +++ /dev/null @@ -1,116 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import access -from keystoneclient import auth -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import utils - - -class Token(base.Resource): - def __repr__(self): - return "<Token %s>" % self._info - - @property - def id(self): - return self._info['token']['id'] - - @property - def expires(self): - return self._info['token']['expires'] - - @property - def tenant(self): - return self._info['token'].get('tenant') - - -class TokenManager(base.Manager): - resource_class = Token - - @utils.positional(enforcement=utils.positional.WARN) - def authenticate(self, username=None, tenant_id=None, tenant_name=None, - password=None, token=None, return_raw=False): - if token: - params = {"auth": {"token": {"id": token}}} - elif username and password: - params = {"auth": {"passwordCredentials": {"username": username, - "password": password}}} - else: - raise ValueError( - _('A username and password or token is required.')) - if tenant_id: - params['auth']['tenantId'] = tenant_id - elif tenant_name: - params['auth']['tenantName'] = tenant_name - - args = ['/tokens', params, 'access'] - kwargs = {'return_raw': return_raw, 'log': False} - - # NOTE(jamielennox): try doing a regular admin query first. If there is - # no endpoint that can satisfy the request (eg an unscoped token) then - # issue it against the auth_url. - try: - token_ref = self._create(*args, **kwargs) - except exceptions.EndpointNotFound: - kwargs['endpoint_filter'] = {'interface': auth.AUTH_INTERFACE} - token_ref = self._create(*args, **kwargs) - - return token_ref - - def delete(self, token): - return self._delete("/tokens/%s" % base.getid(token)) - - def endpoints(self, token): - return self._get("/tokens/%s/endpoints" % base.getid(token), "token") - - def validate(self, token): - """Validate a token. - - :param token: Token to be validated. - - :rtype: :py:class:`.Token` - - """ - return self._get('/tokens/%s' % base.getid(token), 'access') - - def validate_access_info(self, token): - """Validate a token. - - :param token: Token to be validated. This can be an instance of - :py:class:`keystoneclient.access.AccessInfo` or a string - token_id. - - :rtype: :py:class:`keystoneclient.access.AccessInfoV2` - - """ - - def calc_id(token): - if isinstance(token, access.AccessInfo): - return token.auth_token - return base.getid(token) - - url = '/tokens/%s' % calc_id(token) - resp, body = self.client.get(url) - access_info = access.AccessInfo.factory(resp=resp, body=body) - return access_info - - def get_revoked(self): - """Returns the revoked tokens response. - - The response will be a dict containing 'signed' which is a CMS-encoded - document. - - """ - resp, body = self.client.get('/tokens/revoked') - return body diff --git a/awx/lib/site-packages/keystoneclient/v2_0/users.py b/awx/lib/site-packages/keystoneclient/v2_0/users.py deleted file mode 100644 index 11e06f3efd..0000000000 --- a/awx/lib/site-packages/keystoneclient/v2_0/users.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from six.moves import urllib - -from keystoneclient import base - - -class User(base.Resource): - """Represents a Keystone user.""" - def __repr__(self): - return "<User %s>" % self._info - - def delete(self): - return self.manager.delete(self) - - def list_roles(self, tenant=None): - return self.manager.list_roles(self.id, base.getid(tenant)) - - -class UserManager(base.ManagerWithFind): - """Manager class for manipulating Keystone users.""" - resource_class = User - - def __init__(self, client, role_manager): - super(UserManager, self).__init__(client) - self.role_manager = role_manager - - def get(self, user): - return self._get("/users/%s" % base.getid(user), "user") - - def update(self, user, **kwargs): - """Update user data. - - Supported arguments include ``name``, ``email``, and ``enabled``. - """ - # FIXME(gabriel): "tenantId" seems to be accepted by the API but - # fails to actually update the default tenant. - params = {"user": kwargs} - params['user']['id'] = base.getid(user) - url = "/users/%s" % base.getid(user) - return self._update(url, params, "user") - - def update_enabled(self, user, enabled): - """Update enabled-ness.""" - params = {"user": {"id": base.getid(user), - "enabled": enabled}} - - self._update("/users/%s/OS-KSADM/enabled" % base.getid(user), params, - "user") - - def update_password(self, user, password): - """Update password.""" - params = {"user": {"id": base.getid(user), - "password": password}} - - return self._update("/users/%s/OS-KSADM/password" % base.getid(user), - params, "user", log=False) - - def update_own_password(self, origpasswd, passwd): - """Update password.""" - params = {"user": {"password": passwd, - "original_password": origpasswd}} - - return self._update("/OS-KSCRUD/users/%s" % self.api.user_id, params, - response_key="access", - method="PATCH", - endpoint_filter={'interface': 'public'}, - log=False) - - def update_tenant(self, user, tenant): - """Update default tenant.""" - params = {"user": {"id": base.getid(user), - "tenantId": base.getid(tenant)}} - - # FIXME(ja): seems like a bad url - default tenant is an attribute - # not a subresource!??? - return self._update("/users/%s/OS-KSADM/tenant" % base.getid(user), - params, "user") - - def create(self, name, password=None, email=None, - tenant_id=None, enabled=True): - """Create a user.""" - params = {"user": {"name": name, - "password": password, - "tenantId": tenant_id, - "email": email, - "enabled": enabled}} - return self._create('/users', params, "user", log=not bool(password)) - - def delete(self, user): - """Delete a user.""" - return self._delete("/users/%s" % base.getid(user)) - - def list(self, tenant_id=None, limit=None, marker=None): - """Get a list of users (optionally limited to a tenant). - - :rtype: list of :class:`User` - """ - - params = {} - if limit: - params['limit'] = int(limit) - if marker: - params['marker'] = marker - - query = "" - if params: - query = "?" + urllib.parse.urlencode(params) - - if not tenant_id: - return self._list("/users%s" % query, "users") - else: - return self._list("/tenants/%s/users%s" % (tenant_id, query), - "users") - - def list_roles(self, user, tenant=None): - return self.role_manager.roles_for_user(base.getid(user), - base.getid(tenant)) diff --git a/awx/lib/site-packages/keystoneclient/v3/__init__.py b/awx/lib/site-packages/keystoneclient/v3/__init__.py deleted file mode 100644 index 56b26d3b44..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ - -from keystoneclient.v3.client import Client # noqa - - -__all__ = [ - 'client', -] diff --git a/awx/lib/site-packages/keystoneclient/v3/client.py b/awx/lib/site-packages/keystoneclient/v3/client.py deleted file mode 100644 index f7becbbcdc..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/client.py +++ /dev/null @@ -1,287 +0,0 @@ -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -from oslo_serialization import jsonutils - -from keystoneclient.auth.identity import v3 as v3_auth -from keystoneclient import exceptions -from keystoneclient import httpclient -from keystoneclient.i18n import _ -from keystoneclient.v3.contrib import endpoint_filter -from keystoneclient.v3.contrib import endpoint_policy -from keystoneclient.v3.contrib import federation -from keystoneclient.v3.contrib import oauth1 -from keystoneclient.v3.contrib import simple_cert -from keystoneclient.v3.contrib import trusts -from keystoneclient.v3 import credentials -from keystoneclient.v3 import domains -from keystoneclient.v3 import endpoints -from keystoneclient.v3 import groups -from keystoneclient.v3 import policies -from keystoneclient.v3 import projects -from keystoneclient.v3 import regions -from keystoneclient.v3 import role_assignments -from keystoneclient.v3 import roles -from keystoneclient.v3 import services -from keystoneclient.v3 import tokens -from keystoneclient.v3 import users - - -_logger = logging.getLogger(__name__) - - -class Client(httpclient.HTTPClient): - """Client for the OpenStack Identity API v3. - - :param string user_id: User ID for authentication. (optional) - :param string username: Username for authentication. (optional) - :param string user_domain_id: User's domain ID for authentication. - (optional) - :param string user_domain_name: User's domain name for authentication. - (optional) - :param string password: Password for authentication. (optional) - :param string token: Token for authentication. (optional) - :param string domain_id: Domain ID for domain scoping. (optional) - :param string domain_name: Domain name for domain scoping. (optional) - :param string project_id: Project ID for project scoping. (optional) - :param string project_name: Project name for project scoping. (optional) - :param string project_domain_id: Project's domain ID for project - scoping. (optional) - :param string project_domain_name: Project's domain name for project - scoping. (optional) - :param string tenant_name: Tenant name. (optional) - The tenant_name keyword argument is deprecated, - use project_name instead. - :param string tenant_id: Tenant id. (optional) - The tenant_id keyword argument is deprecated, - use project_id instead. - :param string auth_url: Identity service endpoint for authorization. - :param string region_name: Name of a region to select when choosing an - endpoint from the service catalog. - :param string endpoint: A user-supplied endpoint URL for the identity - service. Lazy-authentication is possible for API - service calls if endpoint is set at - instantiation. (optional) - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - - Example:: - - >>> from keystoneclient.v3 import client - >>> keystone = client.Client(user_domain_name=DOMAIN_NAME, - ... username=USER, - ... password=PASS, - ... project_domain_name=PROJECT_DOMAIN_NAME, - ... project_name=PROJECT_NAME, - ... auth_url=KEYSTONE_URL) - ... - >>> keystone.projects.list() - ... - >>> user = keystone.users.get(USER_ID) - >>> user.delete() - - Instances of this class have the following managers: - - .. py:attribute:: credentials - - :py:class:`keystoneclient.v3.credentials.CredentialManager` - - .. py:attribute:: endpoint_filter - - :py:class:`keystoneclient.v3.contrib.endpoint_filter.\ -EndpointFilterManager` - - .. py:attribute:: endpoint_policy - - :py:class:`keystoneclient.v3.contrib.endpoint_policy.\ -EndpointPolicyManager` - - .. py:attribute:: endpoints - - :py:class:`keystoneclient.v3.endpoints.EndpointManager` - - .. py:attribute:: domains - - :py:class:`keystoneclient.v3.domains.DomainManager` - - .. py:attribute:: federation - - :py:class:`keystoneclient.v3.contrib.federation.core.FederationManager` - - .. py:attribute:: groups - - :py:class:`keystoneclient.v3.groups.GroupManager` - - .. py:attribute:: oauth1 - - :py:class:`keystoneclient.v3.contrib.oauth1.core.OAuthManager` - - .. py:attribute:: policies - - :py:class:`keystoneclient.v3.policies.PolicyManager` - - .. py:attribute:: regions - - :py:class:`keystoneclient.v3.regions.RegionManager` - - .. py:attribute:: role_assignments - - :py:class:`keystoneclient.v3.role_assignments.RoleAssignmentManager` - - .. py:attribute:: roles - - :py:class:`keystoneclient.v3.roles.RoleManager` - - .. py:attribute:: simple_cert - - :py:class:`keystoneclient.v3.contrib.simple_cert.SimpleCertManager` - - .. py:attribute:: services - - :py:class:`keystoneclient.v3.services.ServiceManager` - - .. py:attribute:: tokens - - :py:class:`keystoneclient.v3.tokens.TokenManager` - - .. py:attribute:: trusts - - :py:class:`keystoneclient.v3.contrib.trusts.TrustManager` - - .. py:attribute:: users - - :py:class:`keystoneclient.v3.users.UserManager` - - """ - - version = 'v3' - - def __init__(self, **kwargs): - """Initialize a new client for the Keystone v3 API.""" - super(Client, self).__init__(**kwargs) - - self.credentials = credentials.CredentialManager(self._adapter) - self.endpoint_filter = endpoint_filter.EndpointFilterManager( - self._adapter) - self.endpoint_policy = endpoint_policy.EndpointPolicyManager( - self._adapter) - self.endpoints = endpoints.EndpointManager(self._adapter) - self.domains = domains.DomainManager(self._adapter) - self.federation = federation.FederationManager(self._adapter) - self.groups = groups.GroupManager(self._adapter) - self.oauth1 = oauth1.create_oauth_manager(self._adapter) - self.policies = policies.PolicyManager(self._adapter) - self.projects = projects.ProjectManager(self._adapter) - self.regions = regions.RegionManager(self._adapter) - self.role_assignments = ( - role_assignments.RoleAssignmentManager(self._adapter)) - self.roles = roles.RoleManager(self._adapter) - self.services = services.ServiceManager(self._adapter) - self.simple_cert = simple_cert.SimpleCertManager(self._adapter) - self.tokens = tokens.TokenManager(self._adapter) - self.trusts = trusts.TrustManager(self._adapter) - self.users = users.UserManager(self._adapter) - - # DEPRECATED: if session is passed then we go to the new behaviour of - # authenticating on the first required call. - if 'session' not in kwargs and self.management_url is None: - self.authenticate() - - def serialize(self, entity): - return jsonutils.dumps(entity, sort_keys=True) - - def process_token(self, **kwargs): - """Extract and process information from the new auth_ref. - - And set the relevant authentication information. - """ - super(Client, self).process_token(**kwargs) - if self.auth_ref.domain_scoped: - if not self.auth_ref.domain_id: - raise exceptions.AuthorizationFailure( - _("Token didn't provide domain_id")) - self._process_management_url(kwargs.get('region_name')) - self.domain_name = self.auth_ref.domain_name - self.domain_id = self.auth_ref.domain_id - if self._management_url: - self._management_url = self._management_url.replace('/v2.0', '/v3') - - def get_raw_token_from_identity_service(self, auth_url, user_id=None, - username=None, - user_domain_id=None, - user_domain_name=None, - password=None, - domain_id=None, domain_name=None, - project_id=None, project_name=None, - project_domain_id=None, - project_domain_name=None, - token=None, - trust_id=None, - **kwargs): - """Authenticate against the v3 Identity API. - - If password and token methods are both provided then both methods will - be used in the request. - - :returns: access.AccessInfo if authentication was successful. - :raises keystoneclient.exceptions.AuthorizationFailure: if unable to - authenticate or validate the existing authorization token. - :raises keystoneclient.exceptions.Unauthorized: if authentication fails - due to invalid token. - - """ - try: - if auth_url is None: - raise ValueError(_("Cannot authenticate without an auth_url")) - - auth_methods = [] - - if token: - auth_methods.append(v3_auth.TokenMethod(token=token)) - - if password: - m = v3_auth.PasswordMethod(user_id=user_id, - username=username, - user_domain_id=user_domain_id, - user_domain_name=user_domain_name, - password=password) - auth_methods.append(m) - - if not auth_methods: - msg = _('A user and password or token is required.') - raise exceptions.AuthorizationFailure(msg) - - plugin = v3_auth.Auth(auth_url, auth_methods, - trust_id=trust_id, - domain_id=domain_id, - domain_name=domain_name, - project_id=project_id, - project_name=project_name, - project_domain_id=project_domain_id, - project_domain_name=project_domain_name) - - return plugin.get_auth_ref(self.session) - except (exceptions.AuthorizationFailure, exceptions.Unauthorized): - _logger.debug('Authorization failed.') - raise - except exceptions.EndpointNotFound: - msg = _('There was no suitable authentication url for this' - ' request') - raise exceptions.AuthorizationFailure(msg) - except Exception as e: - raise exceptions.AuthorizationFailure( - _('Authorization failed: %s') % e) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/__init__.py b/awx/lib/site-packages/keystoneclient/v3/contrib/__init__.py deleted file mode 100644 index 79b89d1a09..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ - -__all__ = [ -] diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/endpoint_filter.py b/awx/lib/site-packages/keystoneclient/v3/contrib/endpoint_filter.py deleted file mode 100644 index 0da79b81b7..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/endpoint_filter.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient.v3 import endpoints -from keystoneclient.v3 import projects - - -class EndpointFilterManager(base.Manager): - """Manager class for manipulating project-endpoint associations.""" - OS_EP_FILTER_EXT = '/OS-EP-FILTER' - - def _build_base_url(self, project=None, endpoint=None): - project_id = base.getid(project) - endpoint_id = base.getid(endpoint) - - if project_id and endpoint_id: - api_path = '/projects/%s/endpoints/%s' % (project_id, endpoint_id) - elif project_id: - api_path = '/projects/%s/endpoints' % (project_id) - elif endpoint_id: - api_path = '/endpoints/%s/projects' % (endpoint_id) - else: - msg = _('Must specify a project, an endpoint, or both') - raise exceptions.ValidationError(msg) - - return self.OS_EP_FILTER_EXT + api_path - - def add_endpoint_to_project(self, project, endpoint): - """Create a project-endpoint association.""" - if not (project and endpoint): - raise ValueError(_('project and endpoint are required')) - - base_url = self._build_base_url(project=project, - endpoint=endpoint) - return super(EndpointFilterManager, self)._put(url=base_url) - - def delete_endpoint_from_project(self, project, endpoint): - """Remove a project-endpoint association.""" - if not (project and endpoint): - raise ValueError(_('project and endpoint are required')) - - base_url = self._build_base_url(project=project, - endpoint=endpoint) - return super(EndpointFilterManager, self)._delete(url=base_url) - - def check_endpoint_in_project(self, project, endpoint): - """Checks if project-endpoint association exist.""" - if not (project and endpoint): - raise ValueError(_('project and endpoint are required')) - - base_url = self._build_base_url(project=project, - endpoint=endpoint) - return super(EndpointFilterManager, self)._head(url=base_url) - - def list_endpoints_for_project(self, project): - """List all endpoints for a given project.""" - if not project: - raise ValueError(_('project is required')) - - base_url = self._build_base_url(project=project) - return super(EndpointFilterManager, self)._list( - base_url, - endpoints.EndpointManager.collection_key, - obj_class=endpoints.EndpointManager.resource_class) - - def list_projects_for_endpoint(self, endpoint): - """List all projects for a given endpoint.""" - if not endpoint: - raise ValueError(_('endpoint is required')) - - base_url = self._build_base_url(endpoint=endpoint) - return super(EndpointFilterManager, self)._list( - base_url, - projects.ProjectManager.collection_key, - obj_class=projects.ProjectManager.resource_class) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/endpoint_policy.py b/awx/lib/site-packages/keystoneclient/v3/contrib/endpoint_policy.py deleted file mode 100644 index 24148c1ac4..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/endpoint_policy.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2014 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient.i18n import _ -from keystoneclient.v3 import endpoints -from keystoneclient.v3 import policies - - -class EndpointPolicyManager(base.Manager): - """Manager class for manipulating endpoint-policy associations.""" - - OS_EP_POLICY_EXT = 'OS-ENDPOINT-POLICY' - - def _act_on_policy_association_for_endpoint( - self, policy, endpoint, action): - if not (policy and endpoint): - raise ValueError(_('policy and endpoint are required')) - - policy_id = base.getid(policy) - endpoint_id = base.getid(endpoint) - url = ('/policies/%(policy_id)s/%(ext_name)s' - '/endpoints/%(endpoint_id)s') % { - 'policy_id': policy_id, - 'ext_name': self.OS_EP_POLICY_EXT, - 'endpoint_id': endpoint_id} - return action(url=url) - - def create_policy_association_for_endpoint(self, policy, endpoint): - """Create an association between a policy and an endpoint.""" - self._act_on_policy_association_for_endpoint( - policy, endpoint, self._put) - - def check_policy_association_for_endpoint(self, policy, endpoint): - """Check an association between a policy and an endpoint.""" - self._act_on_policy_association_for_endpoint( - policy, endpoint, self._head) - - def delete_policy_association_for_endpoint(self, policy, endpoint): - """Delete an association between a policy and an endpoint.""" - self._act_on_policy_association_for_endpoint( - policy, endpoint, self._delete) - - def _act_on_policy_association_for_service(self, policy, service, action): - if not (policy and service): - raise ValueError(_('policy and service are required')) - - policy_id = base.getid(policy) - service_id = base.getid(service) - url = ('/policies/%(policy_id)s/%(ext_name)s' - '/services/%(service_id)s') % { - 'policy_id': policy_id, - 'ext_name': self.OS_EP_POLICY_EXT, - 'service_id': service_id} - return action(url=url) - - def create_policy_association_for_service(self, policy, service): - """Create an association between a policy and a service.""" - self._act_on_policy_association_for_service( - policy, service, self._put) - - def check_policy_association_for_service(self, policy, service): - """Check an association between a policy and a service.""" - self._act_on_policy_association_for_service( - policy, service, self._head) - - def delete_policy_association_for_service(self, policy, service): - """Delete an association between a policy and a service.""" - self._act_on_policy_association_for_service( - policy, service, self._delete) - - def _act_on_policy_association_for_region_and_service( - self, policy, region, service, action): - if not (policy and region and service): - raise ValueError(_('policy, region and service are required')) - - policy_id = base.getid(policy) - region_id = base.getid(region) - service_id = base.getid(service) - url = ('/policies/%(policy_id)s/%(ext_name)s' - '/services/%(service_id)s/regions/%(region_id)s') % { - 'policy_id': policy_id, - 'ext_name': self.OS_EP_POLICY_EXT, - 'service_id': service_id, - 'region_id': region_id} - return action(url=url) - - def create_policy_association_for_region_and_service( - self, policy, region, service): - """Create an association between a policy and a service in a region.""" - self._act_on_policy_association_for_region_and_service( - policy, region, service, self._put) - - def check_policy_association_for_region_and_service( - self, policy, region, service): - """Check an association between a policy and a service in a region.""" - self._act_on_policy_association_for_region_and_service( - policy, region, service, self._head) - - def delete_policy_association_for_region_and_service( - self, policy, region, service): - """Delete an association between a policy and a service in a region.""" - self._act_on_policy_association_for_region_and_service( - policy, region, service, self._delete) - - def get_policy_for_endpoint(self, endpoint): - """Get the effective policy for an endpoint. - - :param endpoint: endpoint object or ID - - :returns: policies.Policy object - - """ - if not endpoint: - raise ValueError(_('endpoint is required')) - - endpoint_id = base.getid(endpoint) - url = ('/endpoints/%(endpoint_id)s/%(ext_name)s/policy') % { - 'endpoint_id': endpoint_id, - 'ext_name': self.OS_EP_POLICY_EXT} - - _resp, body = self.client.get(url) - return policies.Policy( - self, body[policies.PolicyManager.key], loaded=True) - - def list_endpoints_for_policy(self, policy): - """List endpoints with the effective association to a policy. - - :param policy: policy object or ID - - :returns: list of endpoints that are associated with the policy - - """ - if not policy: - raise ValueError(_('policy is required')) - - policy_id = base.getid(policy) - url = ('/policies/%(policy_id)s/%(ext_name)s/endpoints') % { - 'policy_id': policy_id, - 'ext_name': self.OS_EP_POLICY_EXT} - return self._list( - url, - endpoints.EndpointManager.collection_key, - obj_class=endpoints.EndpointManager.resource_class) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/__init__.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/__init__.py deleted file mode 100644 index ee9bcef98a..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.v3.contrib.federation.core import * # noqa diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/base.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/base.py deleted file mode 100644 index 0160170ea1..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/base.py +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc - -import six - -from keystoneclient.auth import base as base_auth -from keystoneclient import base -from keystoneclient import exceptions - - -@six.add_metaclass(abc.ABCMeta) -class EntityManager(base.Manager): - """Manager class for listing federated accessible objects.""" - resource_class = None - - @abc.abstractproperty - def object_type(self): - raise exceptions.MethodNotImplemented - - def list(self): - url = '/OS-FEDERATION/%s' % self.object_type - try: - tenant_list = self._list(url, self.object_type) - except exceptions.EndpointNotFound: - endpoint_filter = {'interface': base_auth.AUTH_INTERFACE} - tenant_list = self._list(url, self.object_type, - endpoint_filter=endpoint_filter) - return tenant_list diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/core.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/core.py deleted file mode 100644 index b8074606be..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/core.py +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.v3.contrib.federation import domains -from keystoneclient.v3.contrib.federation import identity_providers -from keystoneclient.v3.contrib.federation import mappings -from keystoneclient.v3.contrib.federation import projects -from keystoneclient.v3.contrib.federation import protocols -from keystoneclient.v3.contrib.federation import service_providers - - -class FederationManager(object): - def __init__(self, api): - self.identity_providers = identity_providers.IdentityProviderManager( - api) - self.mappings = mappings.MappingManager(api) - self.protocols = protocols.ProtocolManager(api) - self.projects = projects.ProjectManager(api) - self.domains = domains.DomainManager(api) - self.service_providers = service_providers.ServiceProviderManager(api) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/domains.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/domains.py deleted file mode 100644 index 4d5e1353d1..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/domains.py +++ /dev/null @@ -1,19 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.v3.contrib.federation import base as federation_base -from keystoneclient.v3 import domains - - -class DomainManager(federation_base.EntityManager): - object_type = 'domains' - resource_class = domains.Domain diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/identity_providers.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/identity_providers.py deleted file mode 100644 index 242d5d9621..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/identity_providers.py +++ /dev/null @@ -1,100 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class IdentityProvider(base.Resource): - """Object representing Identity Provider container - - Attributes: - * id: user-defined unique string identifying Identity Provider. - - """ - pass - - -class IdentityProviderManager(base.CrudManager): - """Manager class for manipulating Identity Providers.""" - - resource_class = IdentityProvider - collection_key = 'identity_providers' - key = 'identity_provider' - base_url = 'OS-FEDERATION' - - def _build_url_and_put(self, **kwargs): - url = self.build_url(dict_args_in_out=kwargs) - body = {self.key: kwargs} - return self._update(url, body=body, response_key=self.key, - method='PUT') - - @utils.positional.method(0) - def create(self, id, **kwargs): - """Create Identity Provider object. - - Utilize Keystone URI: - PUT /OS-FEDERATION/identity_providers/$identity_provider - - :param id: unique id of the identity provider. - - """ - return self._build_url_and_put(identity_provider_id=id, - **kwargs) - - def get(self, identity_provider): - """Fetch Identity Provider object - - Utilize Keystone URI: - GET /OS-FEDERATION/identity_providers/$identity_provider - - :param identity_provider: an object with identity_provider_id - stored inside. - - """ - return super(IdentityProviderManager, self).get( - identity_provider_id=base.getid(identity_provider)) - - def list(self, **kwargs): - """List all Identity Providers. - - Utilize Keystone URI: - GET /OS-FEDERATION/identity_providers - - """ - return super(IdentityProviderManager, self).list(**kwargs) - - def update(self, identity_provider, **kwargs): - """Update Identity Provider object. - - Utilize Keystone URI: - PATCH /OS-FEDERATION/identity_providers/$identity_provider - - :param identity_provider: an object with identity_provider_id - stored inside. - - """ - return super(IdentityProviderManager, self).update( - identity_provider_id=base.getid(identity_provider), **kwargs) - - def delete(self, identity_provider): - """Delete Identity Provider object. - - Utilize Keystone URI: - DELETE /OS-FEDERATION/identity_providers/$identity_provider - - :param identity_provider: an object with identity_provider_id - stored inside. - - """ - return super(IdentityProviderManager, self).delete( - identity_provider_id=base.getid(identity_provider)) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/mappings.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/mappings.py deleted file mode 100644 index 1cdb879345..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/mappings.py +++ /dev/null @@ -1,151 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class Mapping(base.Resource): - """An object representing mapping container - - Attributes: - * id: user defined unique string identifying mapping. - - """ - pass - - -class MappingManager(base.CrudManager): - """Manager class for manipulating federation mappings.""" - - resource_class = Mapping - collection_key = 'mappings' - key = 'mapping' - base_url = 'OS-FEDERATION' - - def _build_url_and_put(self, **kwargs): - url = self.build_url(dict_args_in_out=kwargs) - body = {self.key: kwargs} - return self._update(url, body=body, - response_key=self.key, - method='PUT') - - @utils.positional.method(0) - def create(self, mapping_id, **kwargs): - """Create federation mapping. - - Utilize Identity API operation: - PUT /OS-FEDERATION/mappings/$mapping_id - - :param mapping_id: user defined string identifier of the federation - mapping. - :param rules: a list of mapping rules. - - Example of the ``rules`` parameter:: - - [ - { - "local": [ - { - "group": { - "id": "0cd5e9" - } - } - ], - "remote": [ - { - "type": "orgPersonType", - "not_any_of": [ - "Contractor", - "Guest" - ] - } - ] - } - ] - - """ - return self._build_url_and_put( - mapping_id=mapping_id, **kwargs) - - def get(self, mapping): - """Fetch federation mapping identified by mapping id. - - Utilize Identity API operation: - GET /OS-FEDERATION/mappings/$mapping_id - - :param mapping: a Mapping type object with mapping id - stored inside. - - """ - return super(MappingManager, self).get( - mapping_id=base.getid(mapping)) - - def list(self, **kwargs): - """List all federation mappings. - - Utilize Identity API operation: - GET /OS-FEDERATION/mappings/$mapping_id - - """ - return super(MappingManager, self).list(**kwargs) - - def update(self, mapping, **kwargs): - """Update federation mapping identified by mapping id. - - Utilize Identity API operation: - PATCH /OS-FEDERATION/mappings/$mapping_id - - :param mapping: a Mapping type object with mapping id - stored inside. - :param rules: a list of mapping rules. - - Example of the ``rules`` parameter:: - - - [ - { - "local": [ - { - "group": { - "id": "0cd5e9" - } - } - ], - "remote": [ - { - "type": "orgPersonType", - "not_any_of": [ - "Contractor", - "Guest" - ] - } - ] - } - ] - - """ - return super(MappingManager, self).update( - mapping_id=base.getid(mapping), **kwargs) - - def delete(self, mapping): - """Delete federation mapping identified by mapping id. - - Utilize Identity API operation: - DELETE /OS-FEDERATION/mappings/$mapping_id - - :param mapping: a Mapping type object with mapping id - stored inside. - - """ - return super(MappingManager, self).delete( - mapping_id=base.getid(mapping)) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/projects.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/projects.py deleted file mode 100644 index 8e657b4540..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/projects.py +++ /dev/null @@ -1,19 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.v3.contrib.federation import base as federation_base -from keystoneclient.v3 import projects - - -class ProjectManager(federation_base.EntityManager): - object_type = 'projects' - resource_class = projects.Project diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/protocols.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/protocols.py deleted file mode 100644 index 97d88297ba..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/protocols.py +++ /dev/null @@ -1,145 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class Protocol(base.Resource): - """An object representing federation protocol container. - - Attributes: - * id: user-defined unique per Identity Provider string identifying - federation protocol. - - """ - pass - - -class ProtocolManager(base.CrudManager): - """Manager class for manipulating federation protocols.""" - - resource_class = Protocol - collection_key = 'protocols' - key = 'protocol' - base_url = 'OS-FEDERATION/identity_providers' - - def build_url(self, dict_args_in_out=None): - """Build URL for federation protocols.""" - - if dict_args_in_out is None: - dict_args_in_out = {} - - identity_provider_id = dict_args_in_out.pop('identity_provider_id', - None) - if identity_provider_id: - base_url = '/'.join([self.base_url, identity_provider_id]) - else: - base_url = self.base_url - - dict_args_in_out.setdefault('base_url', base_url) - return super(ProtocolManager, self).build_url(dict_args_in_out) - - def _build_url_and_put(self, request_body=None, **kwargs): - url = self.build_url(dict_args_in_out=kwargs) - body = {self.key: request_body} - return self._update(url, body=body, - response_key=self.key, - method='PUT') - - @utils.positional.method(3) - def create(self, protocol_id, identity_provider, mapping, **kwargs): - """Create federation protocol object and tie to the Identity Provider. - - Utilize Identity API operation: - PUT /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - :param protocol_id: a string type parameter identifying a federation - protocol - :param identity_provider: a string type parameter identifying an - Identity Provider - :param mapping: a base.Resource object with federation mapping id - - """ - return self._build_url_and_put( - request_body={'mapping_id': base.getid(mapping)}, - identity_provider_id=base.getid(identity_provider), - protocol_id=protocol_id, **kwargs) - - def get(self, identity_provider, protocol, **kwargs): - """Fetch federation protocol object tied to the Identity Provider. - - Utilize Identity API operation: - GET /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - :param identity_provider: a base.Resource type object with Identity - Provider id stored inside - :param protocol: a base.Resource type object with federation protocol - id stored inside - - """ - return super(ProtocolManager, self).get( - identity_provider_id=base.getid(identity_provider), - protocol_id=base.getid(protocol), **kwargs) - - def list(self, identity_provider, **kwargs): - """List all federation protocol objects tied to the Identity Provider. - - Utilize Identity API operation: - GET /OS-FEDERATION/identity_providers/ - $identity_provider/protocols - - :param identity_provider: a base.Resource type object with Identity - Provider id stored inside - - """ - return super(ProtocolManager, self).list( - identity_provider_id=base.getid(identity_provider), **kwargs) - - def update(self, identity_provider, protocol, mapping, **kwargs): - """Update Protocol object tied to the Identity Provider. - - Utilize Identity API operation: - PATCH /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - :param identity_provider: a base.Resource type object with Identity - Provider id stored inside - :param protocol: a base.Resource type object with federation protocol - id stored inside - :param mapping: a base.Resource object with federation mapping id - - - """ - return super(ProtocolManager, self).update( - identity_provider_id=base.getid(identity_provider), - protocol_id=base.getid(protocol), mapping_id=base.getid(mapping), - **kwargs) - - def delete(self, identity_provider, protocol): - """Delete Protocol object tied to the Identity Provider. - - Utilize Identity API operation: - DELETE /OS-FEDERATION/identity_providers/ - $identity_provider/protocols/$protocol - - :param identity_provider: a base.Resource type object with - Identity Provider id stored inside - :param protocol: a base.Resource type object with federation - protocol id stored inside - - """ - return super(ProtocolManager, self).delete( - identity_provider_id=base.getid(identity_provider), - protocol_id=base.getid(protocol)) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/service_providers.py b/awx/lib/site-packages/keystoneclient/v3/contrib/federation/service_providers.py deleted file mode 100644 index a4192956b9..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/federation/service_providers.py +++ /dev/null @@ -1,104 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class ServiceProvider(base.Resource): - """Object representing Service Provider container - - Attributes: - * id: user-defined unique string identifying Service Provider. - * sp_url: the shibboleth endpoint of a Service Provider. - * auth_url: the authentication url of Service Provider. - - """ - pass - - -class ServiceProviderManager(base.CrudManager): - """Manager class for manipulating Service Providers.""" - - resource_class = ServiceProvider - collection_key = 'service_providers' - key = 'service_provider' - base_url = 'OS-FEDERATION' - - def _build_url_and_put(self, **kwargs): - url = self.build_url(dict_args_in_out=kwargs) - body = {self.key: kwargs} - return self._update(url, body=body, response_key=self.key, - method='PUT') - - @utils.positional.method(0) - def create(self, id, **kwargs): - """Create Service Provider object. - - Utilize Keystone URI: - ``PUT /OS-FEDERATION/service_providers/{id}`` - - :param id: unique id of the service provider. - - """ - return self._build_url_and_put(service_provider_id=id, - **kwargs) - - def get(self, service_provider): - """Fetch Service Provider object - - Utilize Keystone URI: - ``GET /OS-FEDERATION/service_providers/{id}`` - - :param service_provider: an object with service_provider_id - stored inside. - - """ - return super(ServiceProviderManager, self).get( - service_provider_id=base.getid(service_provider)) - - def list(self, **kwargs): - """List all Service Providers. - - Utilize Keystone URI: - ``GET /OS-FEDERATION/service_providers`` - - """ - return super(ServiceProviderManager, self).list(**kwargs) - - def update(self, service_provider, **kwargs): - """Update the existing Service Provider object on the server. - - Only properties provided to the function are being updated. - - Utilize Keystone URI: - ``PATCH /OS-FEDERATION/service_providers/{id}`` - - :param service_provider: an object with service_provider_id - stored inside. - - """ - return super(ServiceProviderManager, self).update( - service_provider_id=base.getid(service_provider), **kwargs) - - def delete(self, service_provider): - """Delete Service Provider object. - - Utilize Keystone URI: - ``DELETE /OS-FEDERATION/service_providers/{id}`` - - :param service_provider: an object with service_provider_id - stored inside. - - """ - return super(ServiceProviderManager, self).delete( - service_provider_id=base.getid(service_provider)) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/__init__.py b/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/__init__.py deleted file mode 100644 index e1fb8b7975..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient.v3.contrib.oauth1.core import * # noqa diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/access_tokens.py b/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/access_tokens.py deleted file mode 100644 index 12b0c6bc66..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/access_tokens.py +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import unicode_literals - -from keystoneclient import auth -from keystoneclient import base -from keystoneclient.v3.contrib.oauth1 import utils - -try: - from oauthlib import oauth1 -except ImportError: - oauth1 = None - - -class AccessToken(base.Resource): - pass - - -class AccessTokenManager(base.CrudManager): - """Manager class for manipulating identity OAuth access tokens.""" - resource_class = AccessToken - - def create(self, consumer_key, consumer_secret, request_key, - request_secret, verifier): - endpoint = utils.OAUTH_PATH + '/access_token' - oauth_client = oauth1.Client(consumer_key, - client_secret=consumer_secret, - resource_owner_key=request_key, - resource_owner_secret=request_secret, - signature_method=oauth1.SIGNATURE_HMAC, - verifier=verifier) - url = self.api.get_endpoint(interface=auth.AUTH_INTERFACE).rstrip('/') - url, headers, body = oauth_client.sign(url + endpoint, - http_method='POST') - resp, body = self.client.post(endpoint, headers=headers) - token = utils.get_oauth_token_from_body(resp.content) - return self.resource_class(self, token) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/auth.py b/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/auth.py deleted file mode 100644 index bd4a152e2d..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/auth.py +++ /dev/null @@ -1,55 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from keystoneclient.auth.identity import v3 - -try: - from oauthlib import oauth1 -except ImportError: - oauth1 = None - - -class OAuthMethod(v3.AuthMethod): - """OAuth based authentication method. - - :param string consumer_key: Consumer key. - :param string consumer_secret: Consumer secret. - :param string access_key: Access token key. - :param string access_secret: Access token secret. - """ - - _method_parameters = ['consumer_key', 'consumer_secret', - 'access_key', 'access_secret'] - - def __init__(self, **kwargs): - super(OAuthMethod, self).__init__(**kwargs) - if oauth1 is None: - raise NotImplementedError('optional package oauthlib' - ' is not installed') - - def get_auth_data(self, session, auth, headers, **kwargs): - # Add the oauth specific content into the headers - oauth_client = oauth1.Client(self.consumer_key, - client_secret=self.consumer_secret, - resource_owner_key=self.access_key, - resource_owner_secret=self.access_secret, - signature_method=oauth1.SIGNATURE_HMAC) - o_url, o_headers, o_body = oauth_client.sign(auth.token_url, - http_method='POST') - - headers.update(o_headers) - return 'oauth1', {} - - -class OAuth(v3.AuthConstructor): - _auth_method_class = OAuthMethod diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/consumers.py b/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/consumers.py deleted file mode 100644 index 25e8ca1910..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/consumers.py +++ /dev/null @@ -1,52 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from keystoneclient import base -from keystoneclient.v3.contrib.oauth1 import utils - - -class Consumer(base.Resource): - """Represents an OAuth consumer. - - Attributes: - * id: a uuid that identifies the consumer - * description: a short description of the consumer - """ - pass - - -class ConsumerManager(base.CrudManager): - """Manager class for manipulating identity consumers.""" - resource_class = Consumer - collection_key = 'consumers' - key = 'consumer' - base_url = utils.OAUTH_PATH - - def create(self, description=None, **kwargs): - return super(ConsumerManager, self).create( - description=description, - **kwargs) - - def get(self, consumer): - return super(ConsumerManager, self).get( - consumer_id=base.getid(consumer)) - - def update(self, consumer, description=None, **kwargs): - return super(ConsumerManager, self).update( - consumer_id=base.getid(consumer), - description=description, - **kwargs) - - def delete(self, consumer): - return super(ConsumerManager, self).delete( - consumer_id=base.getid(consumer)) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/core.py b/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/core.py deleted file mode 100644 index 8d10325772..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/core.py +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from keystoneclient.i18n import _ -from keystoneclient.v3.contrib.oauth1 import access_tokens -from keystoneclient.v3.contrib.oauth1 import consumers -from keystoneclient.v3.contrib.oauth1 import request_tokens - - -def create_oauth_manager(self): - # NOTE(stevemar): Attempt to import the oauthlib package at this point. - try: - import oauthlib # noqa - # NOTE(stevemar): Return an object instead of raising an exception here, - # this will allow users to see an exception only when trying to access the - # oauth portions of client. Otherwise an exception would be raised - # when the client is created. - except ImportError: - return OAuthManagerOptionalImportProxy() - else: - return OAuthManager(self) - - -class OAuthManager(object): - def __init__(self, api): - self.access_tokens = access_tokens.AccessTokenManager(api) - self.consumers = consumers.ConsumerManager(api) - self.request_tokens = request_tokens.RequestTokenManager(api) - - -class OAuthManagerOptionalImportProxy(object): - """Act as a proxy manager in case oauthlib is no installed. - - This class will only be created if oauthlib is not in the system, - trying to access any of the attributes in name (access_tokens, - consumers, request_tokens), will result in a NotImplementedError, - and a message. - - >>> manager.access_tokens.blah - NotImplementedError: To use 'access_tokens' oauthlib must be installed - - Otherwise, if trying to access an attribute other than the ones in name, - the manager will state that the attribute does not exist. - - >>> manager.dne.blah - AttributeError: 'OAuthManagerOptionalImportProxy' object has no - attribute 'dne' - """ - - def __getattribute__(self, name): - if name in ('access_tokens', 'consumers', 'request_tokens'): - raise NotImplementedError( - _('To use %r oauthlib must be installed') % name) - return super(OAuthManagerOptionalImportProxy, - self).__getattribute__(name) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/request_tokens.py b/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/request_tokens.py deleted file mode 100644 index 33ecc3ad72..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/request_tokens.py +++ /dev/null @@ -1,72 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import unicode_literals - -from six.moves.urllib import parse as urlparse - -from keystoneclient import auth -from keystoneclient import base -from keystoneclient.v3.contrib.oauth1 import utils - -try: - from oauthlib import oauth1 -except ImportError: - oauth1 = None - - -class RequestToken(base.Resource): - def authorize(self, roles): - try: - retval = self.manager.authorize(self.id, roles) - self = retval - except Exception: - retval = None - - return retval - - -class RequestTokenManager(base.CrudManager): - """Manager class for manipulating identity OAuth request tokens.""" - resource_class = RequestToken - - def authorize(self, request_token, roles): - """Authorize a request token with specific roles. - - Utilize Identity API operation: - PUT /OS-OAUTH1/authorize/$request_token_id - - :param request_token: a request token that will be authorized, and - can be exchanged for an access token. - :param roles: a list of roles, that will be delegated to the user. - """ - - request_id = urlparse.quote(base.getid(request_token)) - endpoint = utils.OAUTH_PATH + '/authorize/%s' % (request_id) - body = {'roles': [{'id': base.getid(r_id)} for r_id in roles]} - return self._put(endpoint, body, "token") - - def create(self, consumer_key, consumer_secret, project): - endpoint = utils.OAUTH_PATH + '/request_token' - headers = {'requested-project-id': base.getid(project)} - oauth_client = oauth1.Client(consumer_key, - client_secret=consumer_secret, - signature_method=oauth1.SIGNATURE_HMAC, - callback_uri="oob") - url = self.api.get_endpoint(interface=auth.AUTH_INTERFACE).rstrip("/") - url, headers, body = oauth_client.sign(url + endpoint, - http_method='POST', - headers=headers) - resp, body = self.client.post(endpoint, headers=headers) - token = utils.get_oauth_token_from_body(resp.content) - return self.resource_class(self, token) diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/utils.py b/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/utils.py deleted file mode 100644 index bf741ab4ef..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/oauth1/utils.py +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import six -from six.moves.urllib import parse as urlparse - - -OAUTH_PATH = '/OS-OAUTH1' - - -def get_oauth_token_from_body(body): - """Parse the URL response body to retrieve the oauth token key and secret - - The response body will look like: - 'oauth_token=12345&oauth_token_secret=67890' with - 'oauth_expires_at=2013-03-30T05:27:19.463201' possibly there, too. - """ - - if six.PY3: - body = body.decode('utf-8') - - credentials = urlparse.parse_qs(body) - key = credentials['oauth_token'][0] - secret = credentials['oauth_token_secret'][0] - token = {'key': key, 'id': key, 'secret': secret} - expires_at = credentials.get('oauth_expires_at') - if expires_at: - token['expires'] = expires_at[0] - return token diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/simple_cert.py b/awx/lib/site-packages/keystoneclient/v3/contrib/simple_cert.py deleted file mode 100644 index c76234a3d6..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/simple_cert.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2014 IBM Corp. -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class SimpleCertManager(object): - """Manager for the OS-SIMPLE-CERT extension.""" - - def __init__(self, client): - self._client = client - - def get_ca_certificates(self): - """Get CA certificates. - - :returns: PEM-formatted string. - :rtype: str - - """ - - resp, body = self._client.get('/OS-SIMPLE-CERT/ca', - authenticated=False) - return resp.text - - def get_certificates(self): - """Get signing certificates. - - :returns: PEM-formatted string. - :rtype: str - - """ - - resp, body = self._client.get('/OS-SIMPLE-CERT/certificates', - authenticated=False) - return resp.text diff --git a/awx/lib/site-packages/keystoneclient/v3/contrib/trusts.py b/awx/lib/site-packages/keystoneclient/v3/contrib/trusts.py deleted file mode 100644 index 5fe88f8c94..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/contrib/trusts.py +++ /dev/null @@ -1,96 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils import timeutils - -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ - - -class Trust(base.Resource): - """Represents a Trust. - - Attributes: - * id: a uuid that identifies the trust - * impersonation: allow explicit impersonation - * project_id: project ID - * trustee_user_id: a uuid that identifies the trustee - * trustor_user_id: a uuid that identifies the trustor - """ - pass - - -class TrustManager(base.CrudManager): - """Manager class for manipulating Trusts.""" - resource_class = Trust - collection_key = 'trusts' - key = 'trust' - base_url = '/OS-TRUST' - - def create(self, trustee_user, trustor_user, role_names=None, - project=None, impersonation=False, expires_at=None, - remaining_uses=None, **kwargs): - """Create a Trust. - - :param string trustee_user: user who is capable of consuming the trust - :param string trustor_user: user who's authorization is being delegated - :param string role_names: subset of trustor's roles to be granted - :param string project: project which the trustor is delegating - :param boolean impersonation: enable explicit impersonation - :param datetime.datetime expires_at: expiry time - :param integer remaining_uses: how many times this trust can be used - to generate a token. None means - unlimited tokens. - - """ - # Convert role_names list into list-of-dict API format - if role_names: - roles = [{'name': n} for n in role_names] - else: - roles = None - - # Convert datetime.datetime expires_at to iso format string - if expires_at: - expires_str = timeutils.isotime(at=expires_at, subsecond=True) - else: - expires_str = None - - return super(TrustManager, self).create( - expires_at=expires_str, - impersonation=impersonation, - project_id=base.getid(project), - remaining_uses=remaining_uses, - roles=roles, - trustee_user_id=base.getid(trustee_user), - trustor_user_id=base.getid(trustor_user), - **kwargs) - - def update(self): - raise exceptions.MethodNotImplemented( - _('Update not supported for trusts')) - - def list(self, trustee_user=None, trustor_user=None, **kwargs): - """List Trusts.""" - trustee_user_id = base.getid(trustee_user) - trustor_user_id = base.getid(trustor_user) - return super(TrustManager, self).list(trustee_user_id=trustee_user_id, - trustor_user_id=trustor_user_id, - **kwargs) - - def get(self, trust): - """Get a specific trust.""" - return super(TrustManager, self).get(trust_id=base.getid(trust)) - - def delete(self, trust): - """Delete a trust.""" - return super(TrustManager, self).delete(trust_id=base.getid(trust)) diff --git a/awx/lib/site-packages/keystoneclient/v3/credentials.py b/awx/lib/site-packages/keystoneclient/v3/credentials.py deleted file mode 100644 index 8ef7ce4283..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/credentials.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient.i18n import _ -from keystoneclient import utils - - -class Credential(base.Resource): - """Represents an Identity credential. - - Attributes: - * id: a uuid that identifies the credential - * user_id: user ID - * type: credential type - * blob: credential data - * project_id: project ID (optional) - - """ - pass - - -class CredentialManager(base.CrudManager): - """Manager class for manipulating Identity credentials.""" - resource_class = Credential - collection_key = 'credentials' - key = 'credential' - - def _get_data_blob(self, blob, data): - # Ref bug #1259461, the <= 0.4.1 keystoneclient calling convention was - # to pass "data", but the underlying API expects "blob", so - # support both in the python API for backwards compatibility - if blob is not None: - return blob - elif data is not None: - # FIXME(shardy): Passing data is deprecated. Provide an - # appropriate warning. - return data - else: - raise ValueError( - _("Credential requires blob to be specified")) - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, user, type, blob=None, data=None, project=None, **kwargs): - """Create a credential - - :param user: User - :type user: :class:`keystoneclient.v3.users.User` or str - :param str type: credential type, should be either ``ec2`` or ``cert`` - :param JSON blob: Credential data - :param JSON data: Deprecated, use blob instead. - :param project: Project, optional - :type project: :class:`keystoneclient.v3.projects.Project` or str - :param kwargs: Extra attributes passed to create. - - :raises ValueError: if one of ``blob`` or ``data`` is not specified. - - """ - return super(CredentialManager, self).create( - user_id=base.getid(user), - type=type, - blob=self._get_data_blob(blob, data), - project_id=base.getid(project), - **kwargs) - - def get(self, credential): - """Get a credential - - :param credential: Credential - :type credential: :class:`Credential` or str - - """ - return super(CredentialManager, self).get( - credential_id=base.getid(credential)) - - def list(self, **kwargs): - """List credentials. - - If ``**kwargs`` are provided, then filter credentials with - attributes matching ``**kwargs``. - """ - return super(CredentialManager, self).list(**kwargs) - - @utils.positional(2, enforcement=utils.positional.WARN) - def update(self, credential, user, type=None, blob=None, data=None, - project=None, **kwargs): - """Update a credential - - :param credential: Credential to update - :type credential: :class:`Credential` or str - :param user: User - :type user: :class:`keystoneclient.v3.users.User` or str - :param str type: credential type, should be either ``ec2`` or ``cert`` - :param JSON blob: Credential data - :param JSON data: Deprecated, use blob instead. - :param project: Project - :type project: :class:`keystoneclient.v3.projects.Project` or str - :param kwargs: Extra attributes passed to create. - - :raises ValueError: if one of ``blob`` or ``data`` is not specified. - - """ - return super(CredentialManager, self).update( - credential_id=base.getid(credential), - user_id=base.getid(user), - type=type, - blob=self._get_data_blob(blob, data), - project_id=base.getid(project), - **kwargs) - - def delete(self, credential): - """Delete a credential - - :param credential: Credential - :type credential: :class:`Credential` or str - - """ - - return super(CredentialManager, self).delete( - credential_id=base.getid(credential)) diff --git a/awx/lib/site-packages/keystoneclient/v3/domains.py b/awx/lib/site-packages/keystoneclient/v3/domains.py deleted file mode 100644 index 4439f41256..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/domains.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class Domain(base.Resource): - """Represents an Identity domain. - - Attributes: - * id: a uuid that identifies the domain - - """ - pass - - -class DomainManager(base.CrudManager): - """Manager class for manipulating Identity domains.""" - resource_class = Domain - collection_key = 'domains' - key = 'domain' - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, name, description=None, enabled=True, **kwargs): - return super(DomainManager, self).create( - name=name, - description=description, - enabled=enabled, - **kwargs) - - def get(self, domain): - return super(DomainManager, self).get( - domain_id=base.getid(domain)) - - def list(self, **kwargs): - """List domains. - - ``**kwargs`` allows filter criteria to be passed where - supported by the server. - """ - # Ref bug #1267530 we have to pass 0 for False to get the expected - # results on all keystone versions - if kwargs.get('enabled') is False: - kwargs['enabled'] = 0 - return super(DomainManager, self).list(**kwargs) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, domain, name=None, - description=None, enabled=None, **kwargs): - return super(DomainManager, self).update( - domain_id=base.getid(domain), - name=name, - description=description, - enabled=enabled, - **kwargs) - - def delete(self, domain): - return super(DomainManager, self).delete( - domain_id=base.getid(domain)) diff --git a/awx/lib/site-packages/keystoneclient/v3/endpoints.py b/awx/lib/site-packages/keystoneclient/v3/endpoints.py deleted file mode 100644 index eeddc4cd36..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/endpoints.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import utils - - -VALID_INTERFACES = ['public', 'admin', 'internal'] - - -class Endpoint(base.Resource): - """Represents an Identity endpoint. - - Attributes: - * id: a uuid that identifies the endpoint - * interface: 'public', 'admin' or 'internal' network interface - * region: geographic location of the endpoint - * service_id: service to which the endpoint belongs - * url: fully qualified service endpoint - * enabled: determines whether the endpoint appears in the catalog - - """ - pass - - -class EndpointManager(base.CrudManager): - """Manager class for manipulating Identity endpoints.""" - resource_class = Endpoint - collection_key = 'endpoints' - key = 'endpoint' - - def _validate_interface(self, interface): - if interface is not None and interface not in VALID_INTERFACES: - msg = _('"interface" must be one of: %s') - msg = msg % ', '.join(VALID_INTERFACES) - raise exceptions.ValidationError(msg) - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, service, url, interface=None, region=None, enabled=True, - **kwargs): - self._validate_interface(interface) - return super(EndpointManager, self).create( - service_id=base.getid(service), - interface=interface, - url=url, - region=region, - enabled=enabled, - **kwargs) - - def get(self, endpoint): - return super(EndpointManager, self).get( - endpoint_id=base.getid(endpoint)) - - @utils.positional(enforcement=utils.positional.WARN) - def list(self, service=None, interface=None, region=None, enabled=None, - **kwargs): - """List endpoints. - - If ``**kwargs`` are provided, then filter endpoints with - attributes matching ``**kwargs``. - """ - self._validate_interface(interface) - return super(EndpointManager, self).list( - service_id=base.getid(service), - interface=interface, - region=region, - enabled=enabled, - **kwargs) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, endpoint, service=None, url=None, interface=None, - region=None, enabled=None, **kwargs): - self._validate_interface(interface) - return super(EndpointManager, self).update( - endpoint_id=base.getid(endpoint), - service_id=base.getid(service), - interface=interface, - url=url, - region=region, - enabled=enabled, - **kwargs) - - def delete(self, endpoint): - return super(EndpointManager, self).delete( - endpoint_id=base.getid(endpoint)) diff --git a/awx/lib/site-packages/keystoneclient/v3/groups.py b/awx/lib/site-packages/keystoneclient/v3/groups.py deleted file mode 100644 index a998323fa8..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/groups.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class Group(base.Resource): - """Represents an Identity user group. - - Attributes: - * id: a uuid that identifies the group - * name: group name - * description: group description - - """ - @utils.positional(enforcement=utils.positional.WARN) - def update(self, name=None, description=None): - kwargs = { - 'name': name if name is not None else self.name, - 'description': (description - if description is not None - else self.description), - } - - try: - retval = self.manager.update(self.id, **kwargs) - self = retval - except Exception: - retval = None - - return retval - - -class GroupManager(base.CrudManager): - """Manager class for manipulating Identity groups.""" - resource_class = Group - collection_key = 'groups' - key = 'group' - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, name, domain=None, description=None, **kwargs): - return super(GroupManager, self).create( - name=name, - domain_id=base.getid(domain), - description=description, - **kwargs) - - @utils.positional(enforcement=utils.positional.WARN) - def list(self, user=None, domain=None, **kwargs): - """List groups. - - If domain or user is provided, then filter groups with - that attribute. - - If ``**kwargs`` are provided, then filter groups with - attributes matching ``**kwargs``. - """ - if user: - base_url = '/users/%s' % base.getid(user) - else: - base_url = None - return super(GroupManager, self).list( - base_url=base_url, - domain_id=base.getid(domain), - **kwargs) - - def get(self, group): - return super(GroupManager, self).get( - group_id=base.getid(group)) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, group, name=None, description=None, **kwargs): - return super(GroupManager, self).update( - group_id=base.getid(group), - name=name, - description=description, - **kwargs) - - def delete(self, group): - return super(GroupManager, self).delete( - group_id=base.getid(group)) diff --git a/awx/lib/site-packages/keystoneclient/v3/policies.py b/awx/lib/site-packages/keystoneclient/v3/policies.py deleted file mode 100644 index 78cad9376a..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/policies.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class Policy(base.Resource): - """Represents an Identity policy. - - Attributes: - * id: a uuid that identifies the policy - * blob: a policy document (blob) - * type: the mime type of the policy blob - - """ - @utils.positional(enforcement=utils.positional.WARN) - def update(self, blob=None, type=None): - kwargs = { - 'blob': blob if blob is not None else self.blob, - 'type': type if type is not None else self.type, - } - - try: - retval = self.manager.update(self.id, **kwargs) - self = retval - except Exception: - retval = None - - return retval - - -class PolicyManager(base.CrudManager): - """Manager class for manipulating Identity policies.""" - resource_class = Policy - collection_key = 'policies' - key = 'policy' - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, blob, type='application/json', **kwargs): - return super(PolicyManager, self).create( - blob=blob, - type=type, - **kwargs) - - def get(self, policy): - return super(PolicyManager, self).get( - policy_id=base.getid(policy)) - - def list(self, **kwargs): - """List policies. - - ``**kwargs`` allows filter criteria to be passed where - supported by the server. - """ - return super(PolicyManager, self).list(**kwargs) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, entity, blob=None, type=None, **kwargs): - return super(PolicyManager, self).update( - policy_id=base.getid(entity), - blob=blob, - type=type, - **kwargs) - - def delete(self, policy): - return super(PolicyManager, self).delete( - policy_id=base.getid(policy)) diff --git a/awx/lib/site-packages/keystoneclient/v3/projects.py b/awx/lib/site-packages/keystoneclient/v3/projects.py deleted file mode 100644 index 5daaee55cf..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/projects.py +++ /dev/null @@ -1,180 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import utils - - -class Project(base.Resource): - """Represents an Identity project. - - Attributes: - * id: a uuid that identifies the project - * name: project name - * description: project description - * enabled: boolean to indicate if project is enabled - * parent_id: a uuid representing this project's parent in hierarchy - * parents: a list or a structured dict containing the parents of this - project in the hierarchy - * subtree: a list or a structured dict containing the subtree of this - project in the hierarchy - - """ - @utils.positional(enforcement=utils.positional.WARN) - def update(self, name=None, description=None, enabled=None): - kwargs = { - 'name': name if name is not None else self.name, - 'description': (description - if description is not None - else self.description), - 'enabled': enabled if enabled is not None else self.enabled, - } - - try: - retval = self.manager.update(self.id, **kwargs) - self = retval - except Exception: - retval = None - - return retval - - -class ProjectManager(base.CrudManager): - """Manager class for manipulating Identity projects.""" - resource_class = Project - collection_key = 'projects' - key = 'project' - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, name, domain, description=None, - enabled=True, parent=None, **kwargs): - """Create a project. - - :param str name: project name. - :param domain: the project domain. - :type domain: :py:class:`keystoneclient.v3.domains.Domain` or str - :param str description: the project description. (optional) - :param boolean enabled: if the project is enabled. (optional) - :param parent: the project's parent in the hierarchy. (optional) - :type parent: :py:class:`keystoneclient.v3.projects.Project` or str - """ - - # NOTE(rodrigods): the API must be backwards compatible, so if an - # application was passing a 'parent_id' before as kwargs, the call - # should not fail. If both 'parent' and 'parent_id' are provided, - # 'parent' will be preferred. - if parent: - kwargs['parent_id'] = base.getid(parent) - - return super(ProjectManager, self).create( - domain_id=base.getid(domain), - name=name, - description=description, - enabled=enabled, - **kwargs) - - @utils.positional(enforcement=utils.positional.WARN) - def list(self, domain=None, user=None, **kwargs): - """List projects. - - If domain or user are provided, then filter projects with - those attributes. - - If ``**kwargs`` are provided, then filter projects with - attributes matching ``**kwargs``. - """ - base_url = '/users/%s' % base.getid(user) if user else None - return super(ProjectManager, self).list( - base_url=base_url, - domain_id=base.getid(domain), - fallback_to_auth=True, - **kwargs) - - def _check_not_parents_as_ids_and_parents_as_list(self, parents_as_ids, - parents_as_list): - if parents_as_ids and parents_as_list: - msg = _('Specify either parents_as_ids or parents_as_list ' - 'parameters, not both') - raise exceptions.ValidationError(msg) - - def _check_not_subtree_as_ids_and_subtree_as_list(self, subtree_as_ids, - subtree_as_list): - if subtree_as_ids and subtree_as_list: - msg = _('Specify either subtree_as_ids or subtree_as_list ' - 'parameters, not both') - raise exceptions.ValidationError(msg) - - @utils.positional() - def get(self, project, subtree_as_list=False, parents_as_list=False, - subtree_as_ids=False, parents_as_ids=False): - """Get a project. - - :param project: project to be retrieved. - :type project: :py:class:`keystoneclient.v3.projects.Project` or str - :param boolean subtree_as_list: retrieve projects below this project - in the hierarchy as a flat list. - (optional) - :param boolean parents_as_list: retrieve projects above this project - in the hierarchy as a flat list. - (optional) - :param boolean subtree_as_ids: retrieve the IDs from the projects below - this project in the hierarchy as a - structured dictionary. (optional) - :param boolean parents_as_ids: retrieve the IDs from the projects above - this project in the hierarchy as a - structured dictionary. (optional) - - :raises keystoneclient.exceptions.ValidationError: if subtree_as_list - and subtree_as_ids or parents_as_list and parents_as_ids are - included at the same time in the call. - """ - self._check_not_parents_as_ids_and_parents_as_list( - parents_as_ids, parents_as_list) - self._check_not_subtree_as_ids_and_subtree_as_list( - subtree_as_ids, subtree_as_list) - - # According to the API spec, the query params are key only - query_params = [] - if subtree_as_list: - query_params.append('subtree_as_list') - if subtree_as_ids: - query_params.append('subtree_as_ids') - if parents_as_list: - query_params.append('parents_as_list') - if parents_as_ids: - query_params.append('parents_as_ids') - - query = self.build_key_only_query(query_params) - dict_args = {'project_id': base.getid(project)} - url = self.build_url(dict_args_in_out=dict_args) - return self._get(url + query, self.key) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, project, name=None, domain=None, description=None, - enabled=None, **kwargs): - return super(ProjectManager, self).update( - project_id=base.getid(project), - domain_id=base.getid(domain), - name=name, - description=description, - enabled=enabled, - **kwargs) - - def delete(self, project): - return super(ProjectManager, self).delete( - project_id=base.getid(project)) diff --git a/awx/lib/site-packages/keystoneclient/v3/regions.py b/awx/lib/site-packages/keystoneclient/v3/regions.py deleted file mode 100644 index 65cc6abc52..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/regions.py +++ /dev/null @@ -1,90 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base - - -class Region(base.Resource): - """Represents a Catalog region. - - Attributes: - * id: a string that identifies the region. - * description: a string that describes the region. Optional. - * parent_region_id: string that is the id field for an pre-existing - region in the backend. Allows for hierarchical region - organization - * enabled: determines whether the endpoint appears in the catalog. - Defaults to True - """ - pass - - -class RegionManager(base.CrudManager): - """Manager class for manipulating Identity endpoints.""" - resource_class = Region - collection_key = 'regions' - key = 'region' - - def create(self, id=None, description=None, enabled=True, - parent_region=None, **kwargs): - """Create a Catalog region. - - :param id: a string that identifies the region. If not specified - a unique identifier will be assigned to the region. - :param description: a string that describes the region. - :param parent_region: string that is the id field for a - pre-existing region in the backend. Allows for hierarchical - region organization. - :param enabled: determines whether the endpoint appears in the - catalog. - - """ - return super(RegionManager, self).create( - id=id, description=description, enabled=enabled, - parent_region_id=base.getid(parent_region), **kwargs) - - def get(self, region): - return super(RegionManager, self).get( - region_id=base.getid(region)) - - def list(self, **kwargs): - """List regions. - - If ``**kwargs`` are provided, then filter regions with - attributes matching ``**kwargs``. - """ - return super(RegionManager, self).list( - **kwargs) - - def update(self, region, description=None, enabled=None, - parent_region=None, **kwargs): - """Update a Catalog region. - - :param region: a string that identifies the region. - :param description: a string that describes the region. - :param parent_region: string that is the id field for a - pre-existing region in the backend. Allows for hierarchical - region organization. - :param enabled: determines whether the endpoint appears in the - catalog. - - """ - return super(RegionManager, self).update( - region_id=base.getid(region), - description=description, - enabled=enabled, - parent_region_id=base.getid(parent_region), - **kwargs) - - def delete(self, region): - return super(RegionManager, self).delete( - region_id=base.getid(region)) diff --git a/awx/lib/site-packages/keystoneclient/v3/role_assignments.py b/awx/lib/site-packages/keystoneclient/v3/role_assignments.py deleted file mode 100644 index d71f9eb110..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/role_assignments.py +++ /dev/null @@ -1,118 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ - - -class RoleAssignment(base.Resource): - - """Represents an Identity role assignment. - - Attributes: - * role: an object which contains a role uuid - * user or group: an object which contains either a user or - group uuid - * scope: an object which has either a project or domain object - containing an uuid - """ - pass - - -class RoleAssignmentManager(base.CrudManager): - - """Manager class for manipulating Identity roles assignments.""" - resource_class = RoleAssignment - collection_key = 'role_assignments' - key = 'role_assignment' - - def _check_not_user_and_group(self, user, group): - if user and group: - msg = _('Specify either a user or group, not both') - raise exceptions.ValidationError(msg) - - def _check_not_domain_and_project(self, domain, project): - if domain and project: - msg = _('Specify either a domain or project, not both') - raise exceptions.ValidationError(msg) - - def list(self, user=None, group=None, project=None, domain=None, role=None, - effective=False, os_inherit_extension_inherited_to=None): - """Lists role assignments. - - If no arguments are provided, all role assignments in the - system will be listed. - - If both user and group are provided, a ValidationError will be - raised. If both domain and project are provided, it will also - raise a ValidationError. - - :param user: User to be used as query filter. (optional) - :param group: Group to be used as query filter. (optional) - :param project: Project to be used as query filter. - (optional) - :param domain: Domain to be used as query - filter. (optional) - :param role: Role to be used as query filter. (optional) - :param boolean effective: return effective role - assignments. (optional) - :param string os_inherit_extension_inherited_to: - return inherited role assignments for either 'projects' or - 'domains'. (optional) - """ - - self._check_not_user_and_group(user, group) - self._check_not_domain_and_project(domain, project) - - query_params = {} - if user: - query_params['user.id'] = base.getid(user) - if group: - query_params['group.id'] = base.getid(group) - if project: - query_params['scope.project.id'] = base.getid(project) - if domain: - query_params['scope.domain.id'] = base.getid(domain) - if role: - query_params['role.id'] = base.getid(role) - if effective: - query_params['effective'] = effective - if os_inherit_extension_inherited_to: - query_params['scope.OS-INHERIT:inherited_to'] = ( - os_inherit_extension_inherited_to) - - return super(RoleAssignmentManager, self).list(**query_params) - - def create(self, **kwargs): - raise exceptions.MethodNotImplemented( - _('Create not supported for role assignments')) - - def update(self, **kwargs): - raise exceptions.MethodNotImplemented( - _('Update not supported for role assignments')) - - def get(self, **kwargs): - raise exceptions.MethodNotImplemented( - _('Get not supported for role assignments')) - - def find(self, **kwargs): - raise exceptions.MethodNotImplemented( - _('Find not supported for role assignments')) - - def put(self, **kwargs): - raise exceptions.MethodNotImplemented( - _('Put not supported for role assignments')) - - def delete(self, **kwargs): - raise exceptions.MethodNotImplemented( - _('Delete not supported for role assignments')) diff --git a/awx/lib/site-packages/keystoneclient/v3/roles.py b/awx/lib/site-packages/keystoneclient/v3/roles.py deleted file mode 100644 index 3eb68d1746..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/roles.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _ -from keystoneclient import utils - - -class Role(base.Resource): - """Represents an Identity role. - - Attributes: - * id: a uuid that identifies the role - * name: user-facing identifier - - """ - pass - - -class RoleManager(base.CrudManager): - """Manager class for manipulating Identity roles.""" - resource_class = Role - collection_key = 'roles' - key = 'role' - - def _role_grants_base_url(self, user, group, domain, project): - # When called, we have already checked that only one of user & group - # and one of domain & project have been specified - params = {} - - if project: - params['project_id'] = base.getid(project) - base_url = '/projects/%(project_id)s' - elif domain: - params['domain_id'] = base.getid(domain) - base_url = '/domains/%(domain_id)s' - - if user: - params['user_id'] = base.getid(user) - base_url += '/users/%(user_id)s' - elif group: - params['group_id'] = base.getid(group) - base_url += '/groups/%(group_id)s' - - return base_url % params - - def _require_domain_xor_project(self, domain, project): - if domain and project: - msg = _('Specify either a domain or project, not both') - raise exceptions.ValidationError(msg) - elif not (domain or project): - msg = _('Must specify either a domain or project') - raise exceptions.ValidationError(msg) - - def _require_user_xor_group(self, user, group): - if user and group: - msg = _('Specify either a user or group, not both') - raise exceptions.ValidationError(msg) - elif not (user or group): - msg = _('Must specify either a user or group') - raise exceptions.ValidationError(msg) - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, name, **kwargs): - return super(RoleManager, self).create( - name=name, - **kwargs) - - def get(self, role): - return super(RoleManager, self).get( - role_id=base.getid(role)) - - @utils.positional(enforcement=utils.positional.WARN) - def list(self, user=None, group=None, domain=None, project=None, **kwargs): - """Lists roles and role grants. - - If no arguments are provided, all roles in the system will be - listed. - - If a user or group is specified, you must also specify either a - domain or project to list role grants on that pair. And if - ``**kwargs`` are provided, then also filter roles with - attributes matching ``**kwargs``. - """ - - if user or group: - self._require_user_xor_group(user, group) - self._require_domain_xor_project(domain, project) - - return super(RoleManager, self).list( - base_url=self._role_grants_base_url(user, group, - domain, project), - **kwargs) - - return super(RoleManager, self).list(**kwargs) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, role, name=None, **kwargs): - return super(RoleManager, self).update( - role_id=base.getid(role), - name=name, - **kwargs) - - def delete(self, role): - return super(RoleManager, self).delete( - role_id=base.getid(role)) - - @utils.positional(enforcement=utils.positional.WARN) - def grant(self, role, user=None, group=None, domain=None, project=None): - """Grants a role to a user or group on a domain or project.""" - self._require_domain_xor_project(domain, project) - self._require_user_xor_group(user, group) - - return super(RoleManager, self).put( - base_url=self._role_grants_base_url(user, group, domain, project), - role_id=base.getid(role)) - - @utils.positional(enforcement=utils.positional.WARN) - def check(self, role, user=None, group=None, domain=None, project=None): - """Checks if a user or group has a role on a domain or project.""" - self._require_domain_xor_project(domain, project) - self._require_user_xor_group(user, group) - - return super(RoleManager, self).head( - base_url=self._role_grants_base_url(user, group, domain, project), - role_id=base.getid(role)) - - @utils.positional(enforcement=utils.positional.WARN) - def revoke(self, role, user=None, group=None, domain=None, project=None): - """Revokes a role from a user or group on a domain or project.""" - self._require_domain_xor_project(domain, project) - self._require_user_xor_group(user, group) - - return super(RoleManager, self).delete( - base_url=self._role_grants_base_url(user, group, domain, project), - role_id=base.getid(role)) diff --git a/awx/lib/site-packages/keystoneclient/v3/services.py b/awx/lib/site-packages/keystoneclient/v3/services.py deleted file mode 100644 index d6d4c80db4..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/services.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import base -from keystoneclient import utils - - -class Service(base.Resource): - """Represents an Identity service. - - Attributes: - * id: a uuid that identifies the service - * name: user-facing name of the service (e.g. Keystone) - * type: 'compute', 'identity', etc - * enabled: determines whether the service appears in the catalog - - """ - pass - - -class ServiceManager(base.CrudManager): - """Manager class for manipulating Identity services.""" - resource_class = Service - collection_key = 'services' - key = 'service' - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, name, type, enabled=True, description=None, **kwargs): - return super(ServiceManager, self).create( - name=name, - type=type, - description=description, - enabled=enabled, - **kwargs) - - def get(self, service): - return super(ServiceManager, self).get( - service_id=base.getid(service)) - - @utils.positional(enforcement=utils.positional.WARN) - def list(self, name=None, type=None, **kwargs): - return super(ServiceManager, self).list( - name=name, - type=type, - **kwargs) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, service, name=None, type=None, enabled=None, - description=None, **kwargs): - return super(ServiceManager, self).update( - service_id=base.getid(service), - name=name, - type=type, - description=description, - enabled=enabled, - **kwargs) - - def delete(self, service): - return super(ServiceManager, self).delete( - service_id=base.getid(service)) diff --git a/awx/lib/site-packages/keystoneclient/v3/tokens.py b/awx/lib/site-packages/keystoneclient/v3/tokens.py deleted file mode 100644 index 77edbc073a..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/tokens.py +++ /dev/null @@ -1,78 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import access -from keystoneclient import base -from keystoneclient import utils - - -def _calc_id(token): - if isinstance(token, access.AccessInfo): - return token.auth_token - - return base.getid(token) - - -class TokenManager(object): - """Manager class for manipulating Identity tokens.""" - - def __init__(self, client): - self._client = client - - def revoke_token(self, token): - """Revoke a token. - - :param token: Token to be revoked. This can be an instance of - :py:class:`keystoneclient.access.AccessInfo` or a string - token_id. - """ - - token_id = _calc_id(token) - headers = {'X-Subject-Token': token_id} - return self._client.delete('/auth/tokens', headers=headers) - - def get_revoked(self): - """Get revoked tokens list. - - :returns: A dict containing "signed" which is a CMS formatted string. - :rtype: dict - - """ - - resp, body = self._client.get('/auth/tokens/OS-PKI/revoked') - return body - - @utils.positional.method(1) - def validate(self, token, include_catalog=True): - """Validate a token. - - :param token: Token to be validated. This can be an instance of - :py:class:`keystoneclient.access.AccessInfo` or a string - token_id. - :param include_catalog: If False, the response is requested to not - include the catalog. - - :rtype: :py:class:`keystoneclient.access.AccessInfoV3` - - """ - - token_id = _calc_id(token) - headers = {'X-Subject-Token': token_id} - - url = '/auth/tokens' - if not include_catalog: - url += '?nocatalog' - - resp, body = self._client.get(url, headers=headers) - - access_info = access.AccessInfo.factory(resp=resp, body=body) - return access_info diff --git a/awx/lib/site-packages/keystoneclient/v3/users.py b/awx/lib/site-packages/keystoneclient/v3/users.py deleted file mode 100644 index 2e20ede3c1..0000000000 --- a/awx/lib/site-packages/keystoneclient/v3/users.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -from keystoneclient import base -from keystoneclient import exceptions -from keystoneclient.i18n import _, _LW -from keystoneclient import utils - -LOG = logging.getLogger(__name__) - - -class User(base.Resource): - """Represents an Identity user. - - Attributes: - * id: a uuid that identifies the user - - """ - pass - - -class UserManager(base.CrudManager): - """Manager class for manipulating Identity users.""" - resource_class = User - collection_key = 'users' - key = 'user' - - def _require_user_and_group(self, user, group): - if not (user and group): - msg = _('Specify both a user and a group') - raise exceptions.ValidationError(msg) - - @utils.positional(1, enforcement=utils.positional.WARN) - def create(self, name, domain=None, project=None, password=None, - email=None, description=None, enabled=True, - default_project=None, **kwargs): - """Create a user. - - .. warning:: - - The project argument is deprecated, use default_project instead. - - If both default_project and project is provided, the default_project - will be used. - """ - if project: - LOG.warning(_LW("The project argument is deprecated, " - "use default_project instead.")) - default_project_id = base.getid(default_project) or base.getid(project) - user_data = base.filter_none(name=name, - domain_id=base.getid(domain), - default_project_id=default_project_id, - password=password, - email=email, - description=description, - enabled=enabled, - **kwargs) - - return self._create('/users', {'user': user_data}, 'user', - log=not bool(password)) - - @utils.positional(enforcement=utils.positional.WARN) - def list(self, project=None, domain=None, group=None, default_project=None, - **kwargs): - """List users. - - If project, domain or group are provided, then filter - users with those attributes. - - If ``**kwargs`` are provided, then filter users with - attributes matching ``**kwargs``. - - .. warning:: - - The project argument is deprecated, use default_project instead. - - If both default_project and project is provided, the default_project - will be used. - """ - if project: - LOG.warning(_LW("The project argument is deprecated, " - "use default_project instead.")) - default_project_id = base.getid(default_project) or base.getid(project) - if group: - base_url = '/groups/%s' % base.getid(group) - else: - base_url = None - - return super(UserManager, self).list( - base_url=base_url, - domain_id=base.getid(domain), - default_project_id=default_project_id, - **kwargs) - - def get(self, user): - return super(UserManager, self).get( - user_id=base.getid(user)) - - @utils.positional(enforcement=utils.positional.WARN) - def update(self, user, name=None, domain=None, project=None, password=None, - email=None, description=None, enabled=None, - default_project=None, **kwargs): - """Update a user. - - .. warning:: - - The project argument is deprecated, use default_project instead. - - If both default_project and project is provided, the default_project - will be used. - """ - if project: - LOG.warning(_LW("The project argument is deprecated, " - "use default_project instead.")) - default_project_id = base.getid(default_project) or base.getid(project) - user_data = base.filter_none(name=name, - domain_id=base.getid(domain), - default_project_id=default_project_id, - password=password, - email=email, - description=description, - enabled=enabled, - **kwargs) - - return self._update('/users/%s' % base.getid(user), - {'user': user_data}, - 'user', - method='PATCH', - log=False) - - def update_password(self, old_password, new_password): - """Update the password for the user the token belongs to.""" - if not (old_password and new_password): - msg = _('Specify both the current password and a new password') - raise exceptions.ValidationError(msg) - - if old_password == new_password: - msg = _('Old password and new password must be different.') - raise exceptions.ValidationError(msg) - - params = {'user': {'password': new_password, - 'original_password': old_password}} - - base_url = '/users/%s/password' % self.api.user_id - - return self._update(base_url, params, method='POST', log=False, - endpoint_filter={'interface': 'public'}) - - def add_to_group(self, user, group): - self._require_user_and_group(user, group) - - base_url = '/groups/%s' % base.getid(group) - return super(UserManager, self).put( - base_url=base_url, - user_id=base.getid(user)) - - def check_in_group(self, user, group): - self._require_user_and_group(user, group) - - base_url = '/groups/%s' % base.getid(group) - return super(UserManager, self).head( - base_url=base_url, - user_id=base.getid(user)) - - def remove_from_group(self, user, group): - self._require_user_and_group(user, group) - - base_url = '/groups/%s' % base.getid(group) - return super(UserManager, self).delete( - base_url=base_url, - user_id=base.getid(user)) - - def delete(self, user): - return super(UserManager, self).delete( - user_id=base.getid(user)) diff --git a/awx/lib/site-packages/kombu/__init__.py b/awx/lib/site-packages/kombu/__init__.py deleted file mode 100644 index 9825e32606..0000000000 --- a/awx/lib/site-packages/kombu/__init__.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Messaging library for Python""" -from __future__ import absolute_import - -from collections import namedtuple - -version_info_t = namedtuple( - 'version_info_t', ('major', 'minor', 'micro', 'releaselevel', 'serial'), -) - -VERSION = version_info_t(3, 0, 21, '', '') -__version__ = '{0.major}.{0.minor}.{0.micro}{0.releaselevel}'.format(VERSION) -__author__ = 'Ask Solem' -__contact__ = 'ask@celeryproject.org' -__homepage__ = 'http://kombu.readthedocs.org' -__docformat__ = 'restructuredtext en' - -# -eof meta- - -import os -import sys - -if sys.version_info < (2, 6): # pragma: no cover - raise Exception('Kombu 3.1 requires Python versions 2.6 or later.') - -STATICA_HACK = True -globals()['kcah_acitats'[::-1].upper()] = False -if STATICA_HACK: # pragma: no cover - # This is never executed, but tricks static analyzers (PyDev, PyCharm, - # pylint, etc.) into knowing the types of these symbols, and what - # they contain. - from kombu.connection import Connection, BrokerConnection # noqa - from kombu.entity import Exchange, Queue, binding # noqa - from kombu.messaging import Consumer, Producer # noqa - from kombu.pools import connections, producers # noqa - from kombu.utils.url import parse_url # noqa - from kombu.common import eventloop, uuid # noqa - from kombu.serialization import ( # noqa - enable_insecure_serializers, - disable_insecure_serializers, - ) - -# Lazy loading. -# - See werkzeug/__init__.py for the rationale behind this. -from types import ModuleType - -all_by_module = { - 'kombu.connection': ['Connection', 'BrokerConnection'], - 'kombu.entity': ['Exchange', 'Queue', 'binding'], - 'kombu.messaging': ['Consumer', 'Producer'], - 'kombu.pools': ['connections', 'producers'], - 'kombu.utils.url': ['parse_url'], - 'kombu.common': ['eventloop', 'uuid'], - 'kombu.serialization': ['enable_insecure_serializers', - 'disable_insecure_serializers'], -} - -object_origins = {} -for module, items in all_by_module.items(): - for item in items: - object_origins[item] = module - - -class module(ModuleType): - - def __getattr__(self, name): - if name in object_origins: - module = __import__(object_origins[name], None, None, [name]) - for extra_name in all_by_module[module.__name__]: - setattr(self, extra_name, getattr(module, extra_name)) - return getattr(module, name) - return ModuleType.__getattribute__(self, name) - - def __dir__(self): - result = list(new_module.__all__) - result.extend(('__file__', '__path__', '__doc__', '__all__', - '__docformat__', '__name__', '__path__', 'VERSION', - '__package__', '__version__', '__author__', - '__contact__', '__homepage__', '__docformat__')) - return result - -# 2.5 does not define __package__ -try: - package = __package__ -except NameError: # pragma: no cover - package = 'kombu' - -# keep a reference to this module so that it's not garbage collected -old_module = sys.modules[__name__] - -new_module = sys.modules[__name__] = module(__name__) -new_module.__dict__.update({ - '__file__': __file__, - '__path__': __path__, - '__doc__': __doc__, - '__all__': tuple(object_origins), - '__version__': __version__, - '__author__': __author__, - '__contact__': __contact__, - '__homepage__': __homepage__, - '__docformat__': __docformat__, - '__package__': package, - 'version_info_t': version_info_t, - 'VERSION': VERSION}) - -if os.environ.get('KOMBU_LOG_DEBUG'): # pragma: no cover - os.environ.update(KOMBU_LOG_CHANNEL='1', KOMBU_LOG_CONNECTION='1') - from .utils import debug - debug.setup_logging() diff --git a/awx/lib/site-packages/kombu/abstract.py b/awx/lib/site-packages/kombu/abstract.py deleted file mode 100644 index 6dff8486f5..0000000000 --- a/awx/lib/site-packages/kombu/abstract.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -kombu.abstract -============== - -Object utilities. - -""" -from __future__ import absolute_import - -from copy import copy - -from .connection import maybe_channel -from .exceptions import NotBoundError -from .utils import ChannelPromise - -__all__ = ['Object', 'MaybeChannelBound'] - - -def unpickle_dict(cls, kwargs): - return cls(**kwargs) - - -class Object(object): - """Common base class supporting automatic kwargs->attributes handling, - and cloning.""" - attrs = () - - def __init__(self, *args, **kwargs): - any = lambda v: v - for name, type_ in self.attrs: - value = kwargs.get(name) - if value is not None: - setattr(self, name, (type_ or any)(value)) - else: - try: - getattr(self, name) - except AttributeError: - setattr(self, name, None) - - def as_dict(self, recurse=False): - def f(obj, type): - if recurse and isinstance(obj, Object): - return obj.as_dict(recurse=True) - return type(obj) if type else obj - return dict( - (attr, f(getattr(self, attr), type)) for attr, type in self.attrs - ) - - def __reduce__(self): - return unpickle_dict, (self.__class__, self.as_dict()) - - def __copy__(self): - return self.__class__(**self.as_dict()) - - -class MaybeChannelBound(Object): - """Mixin for classes that can be bound to an AMQP channel.""" - _channel = None - _is_bound = False - - #: Defines whether maybe_declare can skip declaring this entity twice. - can_cache_declaration = False - - def __call__(self, channel): - """`self(channel) -> self.bind(channel)`""" - return self.bind(channel) - - def bind(self, channel): - """Create copy of the instance that is bound to a channel.""" - return copy(self).maybe_bind(channel) - - def maybe_bind(self, channel): - """Bind instance to channel if not already bound.""" - if not self.is_bound and channel: - self._channel = maybe_channel(channel) - self.when_bound() - self._is_bound = True - return self - - def revive(self, channel): - """Revive channel after the connection has been re-established. - - Used by :meth:`~kombu.Connection.ensure`. - - """ - if self.is_bound: - self._channel = channel - self.when_bound() - - def when_bound(self): - """Callback called when the class is bound.""" - pass - - def __repr__(self, item=''): - item = item or type(self).__name__ - if self.is_bound: - return '<{0} bound to chan:{1}>'.format( - item or type(self).__name__, self.channel.channel_id) - return '<unbound {0}>'.format(item) - - @property - def is_bound(self): - """Flag set if the channel is bound.""" - return self._is_bound and self._channel is not None - - @property - def channel(self): - """Current channel if the object is bound.""" - channel = self._channel - if channel is None: - raise NotBoundError( - "Can't call method on {0} not bound to a channel".format( - type(self).__name__)) - if isinstance(channel, ChannelPromise): - channel = self._channel = channel() - return channel diff --git a/awx/lib/site-packages/kombu/async/__init__.py b/awx/lib/site-packages/kombu/async/__init__.py deleted file mode 100644 index c6e8e8e1d6..0000000000 --- a/awx/lib/site-packages/kombu/async/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -""" -kombu.async -=========== - -Event loop implementation. - -""" -from __future__ import absolute_import - -from .hub import Hub, get_event_loop, set_event_loop - -from kombu.utils.eventio import READ, WRITE, ERR - -__all__ = ['READ', 'WRITE', 'ERR', 'Hub', 'get_event_loop', 'set_event_loop'] diff --git a/awx/lib/site-packages/kombu/async/debug.py b/awx/lib/site-packages/kombu/async/debug.py deleted file mode 100644 index 80cdcb78f1..0000000000 --- a/awx/lib/site-packages/kombu/async/debug.py +++ /dev/null @@ -1,60 +0,0 @@ -from __future__ import absolute_import - -from kombu.five import items -from kombu.utils import reprcall -from kombu.utils.eventio import READ, WRITE, ERR - - -def repr_flag(flag): - return '{0}{1}{2}'.format('R' if flag & READ else '', - 'W' if flag & WRITE else '', - '!' if flag & ERR else '') - - -def _rcb(obj): - if obj is None: - return '<missing>' - if isinstance(obj, str): - return obj - if isinstance(obj, tuple): - cb, args = obj - return reprcall(cb.__name__, args=args) - return obj.__name__ - - -def repr_active(h): - return ', '.join(repr_readers(h) + repr_writers(h)) - - -def repr_events(h, events): - return ', '.join( - '{0}({1})->{2}'.format( - _rcb(callback_for(h, fd, fl, '(GONE)')), fd, - repr_flag(fl), - ) - for fd, fl in events - ) - - -def repr_readers(h): - return ['({0}){1}->{2}'.format(fd, _rcb(cb), repr_flag(READ | ERR)) - for fd, cb in items(h.readers)] - - -def repr_writers(h): - return ['({0}){1}->{2}'.format(fd, _rcb(cb), repr_flag(WRITE)) - for fd, cb in items(h.writers)] - - -def callback_for(h, fd, flag, *default): - try: - if flag & READ: - return h.readers[fd] - if flag & WRITE: - if fd in h.consolidate: - return h.consolidate_callback - return h.writers[fd] - except KeyError: - if default: - return default[0] - raise diff --git a/awx/lib/site-packages/kombu/async/hub.py b/awx/lib/site-packages/kombu/async/hub.py deleted file mode 100644 index cea77ddbf4..0000000000 --- a/awx/lib/site-packages/kombu/async/hub.py +++ /dev/null @@ -1,350 +0,0 @@ -# -*- coding: utf-8 -*- -""" -kombu.async.hub -=============== - -Event loop implementation. - -""" -from __future__ import absolute_import - -import errno - -from collections import deque -from contextlib import contextmanager -from time import sleep -from types import GeneratorType as generator - -from amqp import promise - -from kombu.five import Empty, range -from kombu.log import get_logger -from kombu.utils import cached_property, fileno -from kombu.utils.compat import get_errno -from kombu.utils.eventio import READ, WRITE, ERR, poll - -from .timer import Timer - -__all__ = ['Hub', 'get_event_loop', 'set_event_loop'] -logger = get_logger(__name__) - -_current_loop = None - - -class Stop(BaseException): - """Stops the event loop.""" - - -def _raise_stop_error(): - raise Stop() - - -@contextmanager -def _dummy_context(*args, **kwargs): - yield - - -def get_event_loop(): - return _current_loop - - -def set_event_loop(loop): - global _current_loop - _current_loop = loop - return loop - - -class Hub(object): - """Event loop object. - - :keyword timer: Specify timer object. - - """ - #: Flag set if reading from an fd will not block. - READ = READ - - #: Flag set if writing to an fd will not block. - WRITE = WRITE - - #: Flag set on error, and the fd should be read from asap. - ERR = ERR - - #: List of callbacks to be called when the loop is exiting, - #: applied with the hub instance as sole argument. - on_close = None - - def __init__(self, timer=None): - self.timer = timer if timer is not None else Timer() - - self.readers = {} - self.writers = {} - self.on_tick = set() - self.on_close = set() - self._ready = deque() - - self._running = False - self._loop = None - - # The eventloop (in celery.worker.loops) - # will merge fds in this set and then instead of calling - # the callback for each ready fd it will call the - # :attr:`consolidate_callback` with the list of ready_fds - # as an argument. This API is internal and is only - # used by the multiprocessing pool to find inqueues - # that are ready to write. - self.consolidate = set() - self.consolidate_callback = None - - self.propagate_errors = () - - self._create_poller() - - def reset(self): - self.close() - self._create_poller() - - def _create_poller(self): - self.poller = poll() - self._register_fd = self.poller.register - self._unregister_fd = self.poller.unregister - - def _close_poller(self): - if self.poller is not None: - self.poller.close() - self.poller = None - self._register_fd = None - self._unregister_fd = None - - def stop(self): - self.call_soon(_raise_stop_error) - - def __repr__(self): - return '<Hub@{0:#x}: R:{1} W:{2}>'.format( - id(self), len(self.readers), len(self.writers), - ) - - def fire_timers(self, min_delay=1, max_delay=10, max_timers=10, - propagate=()): - timer = self.timer - delay = None - if timer and timer._queue: - for i in range(max_timers): - delay, entry = next(self.scheduler) - if entry is None: - break - try: - entry() - except propagate: - raise - except (MemoryError, AssertionError): - raise - except OSError as exc: - if get_errno(exc) == errno.ENOMEM: - raise - logger.error('Error in timer: %r', exc, exc_info=1) - except Exception as exc: - logger.error('Error in timer: %r', exc, exc_info=1) - return min(max(delay or 0, min_delay), max_delay) - - def add(self, fd, callback, flags, args=(), consolidate=False): - fd = fileno(fd) - try: - self.poller.register(fd, flags) - except ValueError: - self._discard(fd) - raise - else: - dest = self.readers if flags & READ else self.writers - if consolidate: - self.consolidate.add(fd) - dest[fd] = None - else: - dest[fd] = callback, args - - def remove(self, fd): - fd = fileno(fd) - self._unregister(fd) - self._discard(fd) - - def run_forever(self): - self._running = True - try: - while 1: - try: - self.run_once() - except Stop: - break - finally: - self._running = False - - def run_once(self): - try: - next(self.loop) - except StopIteration: - self._loop = None - - def call_soon(self, callback, *args): - handle = promise(callback, args) - self._ready.append(handle) - return handle - - def call_later(self, delay, callback, *args): - return self.timer.call_after(delay, callback, args) - - def call_at(self, when, callback, *args): - return self.timer.call_at(when, callback, args) - - def call_repeatedly(self, delay, callback, *args): - return self.timer.call_repeatedly(delay, callback, args) - - def add_reader(self, fds, callback, *args): - return self.add(fds, callback, READ | ERR, args) - - def add_writer(self, fds, callback, *args): - return self.add(fds, callback, WRITE, args) - - def remove_reader(self, fd): - writable = fd in self.writers - on_write = self.writers.get(fd) - try: - self._unregister(fd) - self._discard(fd) - finally: - if writable: - cb, args = on_write - self.add(fd, cb, WRITE, args) - - def remove_writer(self, fd): - readable = fd in self.readers - on_read = self.readers.get(fd) - try: - self._unregister(fd) - self._discard(fd) - finally: - if readable: - cb, args = on_read - self.add(fd, cb, READ | ERR, args) - - def _unregister(self, fd): - try: - self.poller.unregister(fd) - except (AttributeError, KeyError, OSError): - pass - - def close(self, *args): - [self._unregister(fd) for fd in self.readers] - self.readers.clear() - [self._unregister(fd) for fd in self.writers] - self.writers.clear() - self.consolidate.clear() - self._close_poller() - for callback in self.on_close: - callback(self) - - def _discard(self, fd): - fd = fileno(fd) - self.readers.pop(fd, None) - self.writers.pop(fd, None) - self.consolidate.discard(fd) - - def create_loop(self, - generator=generator, sleep=sleep, min=min, next=next, - Empty=Empty, StopIteration=StopIteration, - KeyError=KeyError, READ=READ, WRITE=WRITE, ERR=ERR): - readers, writers = self.readers, self.writers - poll = self.poller.poll - fire_timers = self.fire_timers - hub_remove = self.remove - scheduled = self.timer._queue - consolidate = self.consolidate - consolidate_callback = self.consolidate_callback - on_tick = self.on_tick - todo = self._ready - propagate = self.propagate_errors - - while 1: - for tick_callback in on_tick: - tick_callback() - - while todo: - item = todo.popleft() - if item: - item() - - poll_timeout = fire_timers(propagate=propagate) if scheduled else 1 - if readers or writers: - to_consolidate = [] - try: - events = poll(poll_timeout) - except ValueError: # Issue 882 - raise StopIteration() - - for fd, event in events or (): - if fd in consolidate and \ - writers.get(fd) is None: - to_consolidate.append(fd) - continue - cb = cbargs = None - - if event & READ: - try: - cb, cbargs = readers[fd] - except KeyError: - self.remove_reader(fd) - continue - elif event & WRITE: - try: - cb, cbargs = writers[fd] - except KeyError: - self.remove_writer(fd) - continue - elif event & ERR: - try: - cb, cbargs = (readers.get(fd) or - writers.get(fd)) - except TypeError: - pass - - if cb is None: - continue - if isinstance(cb, generator): - try: - next(cb) - except OSError as exc: - if get_errno(exc) != errno.EBADF: - raise - hub_remove(fd) - except StopIteration: - pass - except Exception: - hub_remove(fd) - raise - else: - try: - cb(*cbargs) - except Empty: - pass - if to_consolidate: - consolidate_callback(to_consolidate) - else: - # no sockets yet, startup is probably not done. - sleep(min(poll_timeout, 0.1)) - yield - - def repr_active(self): - from .debug import repr_active - return repr_active(self) - - def repr_events(self, events): - from .debug import repr_events - return repr_events(self, events) - - @cached_property - def scheduler(self): - return iter(self.timer) - - @property - def loop(self): - if self._loop is None: - self._loop = self.create_loop() - return self._loop diff --git a/awx/lib/site-packages/kombu/async/semaphore.py b/awx/lib/site-packages/kombu/async/semaphore.py deleted file mode 100644 index b446441095..0000000000 --- a/awx/lib/site-packages/kombu/async/semaphore.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- -""" -kombu.async.semaphore -===================== - -Semaphores and concurrency primitives. - -""" -from __future__ import absolute_import - -from collections import deque - -__all__ = ['DummyLock', 'LaxBoundedSemaphore'] - - -class LaxBoundedSemaphore(object): - """Asynchronous Bounded Semaphore. - - Lax means that the value will stay within the specified - range even if released more times than it was acquired. - - Example: - - >>> from future import print_statement as printf - # ^ ignore: just fooling stupid pyflakes - - >>> x = LaxBoundedSemaphore(2) - - >>> x.acquire(printf, 'HELLO 1') - HELLO 1 - - >>> x.acquire(printf, 'HELLO 2') - HELLO 2 - - >>> x.acquire(printf, 'HELLO 3') - >>> x._waiters # private, do not access directly - [print, ('HELLO 3', )] - - >>> x.release() - HELLO 3 - - """ - - def __init__(self, value): - self.initial_value = self.value = value - self._waiting = deque() - self._add_waiter = self._waiting.append - self._pop_waiter = self._waiting.popleft - - def acquire(self, callback, *partial_args): - """Acquire semaphore, applying ``callback`` if - the resource is available. - - :param callback: The callback to apply. - :param \*partial_args: partial arguments to callback. - - """ - value = self.value - if value <= 0: - self._add_waiter((callback, partial_args)) - return False - else: - self.value = max(value - 1, 0) - callback(*partial_args) - return True - - def release(self): - """Release semaphore. - - If there are any waiters this will apply the first waiter - that is waiting for the resource (FIFO order). - - """ - try: - waiter, args = self._pop_waiter() - except IndexError: - self.value = min(self.value + 1, self.initial_value) - else: - waiter(*args) - - def grow(self, n=1): - """Change the size of the semaphore to accept more users.""" - self.initial_value += n - self.value += n - [self.release() for _ in range(n)] - - def shrink(self, n=1): - """Change the size of the semaphore to accept less users.""" - self.initial_value = max(self.initial_value - n, 0) - self.value = max(self.value - n, 0) - - def clear(self): - """Reset the semaphore, which also wipes out any waiting callbacks.""" - self._waiting.clear() - self.value = self.initial_value - - def __repr__(self): - return '<{0} at {1:#x} value:{2} waiting:{3}>'.format( - self.__class__.__name__, id(self), self.value, len(self._waiting), - ) - - -class DummyLock(object): - """Pretending to be a lock.""" - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - pass diff --git a/awx/lib/site-packages/kombu/async/timer.py b/awx/lib/site-packages/kombu/async/timer.py deleted file mode 100644 index 00f54123a7..0000000000 --- a/awx/lib/site-packages/kombu/async/timer.py +++ /dev/null @@ -1,232 +0,0 @@ -# -*- coding: utf-8 -*- -""" -kombu.async.timer -================= - -Timer scheduling Python callbacks. - -""" -from __future__ import absolute_import - -import heapq -import sys - -from collections import namedtuple -from datetime import datetime -from functools import wraps -from time import time -from weakref import proxy as weakrefproxy - -from kombu.five import monotonic -from kombu.log import get_logger -from kombu.utils.compat import timedelta_seconds - -try: - from pytz import utc -except ImportError: - utc = None - -DEFAULT_MAX_INTERVAL = 2 -EPOCH = datetime.utcfromtimestamp(0).replace(tzinfo=utc) -IS_PYPY = hasattr(sys, 'pypy_version_info') - -logger = get_logger(__name__) - -__all__ = ['Entry', 'Timer', 'to_timestamp'] - -scheduled = namedtuple('scheduled', ('eta', 'priority', 'entry')) - - -def to_timestamp(d, default_timezone=utc): - if isinstance(d, datetime): - if d.tzinfo is None: - d = d.replace(tzinfo=default_timezone) - return timedelta_seconds(d - EPOCH) - return d - - -class Entry(object): - if not IS_PYPY: # pragma: no cover - __slots__ = ( - 'fun', 'args', 'kwargs', 'tref', 'cancelled', - '_last_run', '__weakref__', - ) - - def __init__(self, fun, args=None, kwargs=None): - self.fun = fun - self.args = args or [] - self.kwargs = kwargs or {} - self.tref = weakrefproxy(self) - self._last_run = None - self.cancelled = False - - def __call__(self): - return self.fun(*self.args, **self.kwargs) - - def cancel(self): - try: - self.tref.cancelled = True - except ReferenceError: # pragma: no cover - pass - - def __repr__(self): - return '<TimerEntry: {0}(*{1!r}, **{2!r})'.format( - self.fun.__name__, self.args, self.kwargs) - - def __hash__(self): - return hash((self.fun, repr(self.args), repr(self.kwargs))) - - # must not use hash() to order entries - def __lt__(self, other): - return id(self) < id(other) - - def __gt__(self, other): - return id(self) > id(other) - - def __le__(self, other): - return id(self) <= id(other) - - def __ge__(self, other): - return id(self) >= id(other) - - def __eq__(self, other): - return hash(self) == hash(other) - - def __ne__(self, other): - return not self.__eq__(other) - - -class Timer(object): - """ETA scheduler.""" - Entry = Entry - - on_error = None - - def __init__(self, max_interval=None, on_error=None, **kwargs): - self.max_interval = float(max_interval or DEFAULT_MAX_INTERVAL) - self.on_error = on_error or self.on_error - self._queue = [] - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.stop() - - def call_at(self, eta, fun, args=(), kwargs={}, priority=0): - return self.enter_at(self.Entry(fun, args, kwargs), eta, priority) - - def call_after(self, secs, fun, args=(), kwargs={}, priority=0): - return self.enter_after(secs, self.Entry(fun, args, kwargs), priority) - - def call_repeatedly(self, secs, fun, args=(), kwargs={}, priority=0): - tref = self.Entry(fun, args, kwargs) - - @wraps(fun) - def _reschedules(*args, **kwargs): - last, now = tref._last_run, monotonic() - lsince = (now - tref._last_run) if last else secs - try: - if lsince and lsince >= secs: - tref._last_run = now - return fun(*args, **kwargs) - finally: - if not tref.cancelled: - last = tref._last_run - next = secs - (now - last) if last else secs - self.enter_after(next, tref, priority) - - tref.fun = _reschedules - tref._last_run = None - return self.enter_after(secs, tref, priority) - - def enter_at(self, entry, eta=None, priority=0, time=time): - """Enter function into the scheduler. - - :param entry: Item to enter. - :keyword eta: Scheduled time as a :class:`datetime.datetime` object. - :keyword priority: Unused. - - """ - if eta is None: - eta = time() - if isinstance(eta, datetime): - try: - eta = to_timestamp(eta) - except Exception as exc: - if not self.handle_error(exc): - raise - return - return self._enter(eta, priority, entry) - - def enter_after(self, secs, entry, priority=0, time=time): - return self.enter_at(entry, time() + secs, priority) - - def _enter(self, eta, priority, entry, push=heapq.heappush): - push(self._queue, scheduled(eta, priority, entry)) - return entry - - def apply_entry(self, entry): - try: - entry() - except Exception as exc: - if not self.handle_error(exc): - logger.error('Error in timer: %r', exc, exc_info=True) - - def handle_error(self, exc_info): - if self.on_error: - self.on_error(exc_info) - return True - - def stop(self): - pass - - def __iter__(self, min=min, nowfun=time, - pop=heapq.heappop, push=heapq.heappush): - """This iterator yields a tuple of ``(entry, wait_seconds)``, - where if entry is :const:`None` the caller should wait - for ``wait_seconds`` until it polls the schedule again.""" - max_interval = self.max_interval - queue = self._queue - - while 1: - if queue: - eventA = queue[0] - now, eta = nowfun(), eventA[0] - - if now < eta: - yield min(eta - now, max_interval), None - else: - eventB = pop(queue) - - if eventB is eventA: - entry = eventA[2] - if not entry.cancelled: - yield None, entry - continue - else: - push(queue, eventB) - else: - yield None, None - - def clear(self): - self._queue[:] = [] # atomic, without creating a new list. - - def cancel(self, tref): - tref.cancel() - - def __len__(self): - return len(self._queue) - - def __nonzero__(self): - return True - - @property - def queue(self, _pop=heapq.heappop): - """Snapshot of underlying datastructure.""" - events = list(self._queue) - return [_pop(v) for v in [events] * len(events)] - - @property - def schedule(self): - return self diff --git a/awx/lib/site-packages/kombu/clocks.py b/awx/lib/site-packages/kombu/clocks.py deleted file mode 100644 index a9862382df..0000000000 --- a/awx/lib/site-packages/kombu/clocks.py +++ /dev/null @@ -1,148 +0,0 @@ -""" -kombu.clocks -============ - -Logical Clocks and Synchronization. - -""" -from __future__ import absolute_import - -from threading import Lock -from itertools import islice -from operator import itemgetter - -from .five import zip - -__all__ = ['LamportClock', 'timetuple'] - -R_CLOCK = '_lamport(clock={0}, timestamp={1}, id={2} {3!r})' - - -class timetuple(tuple): - """Tuple of event clock information. - - Can be used as part of a heap to keep events ordered. - - :param clock: Event clock value. - :param timestamp: Event UNIX timestamp value. - :param id: Event host id (e.g. ``hostname:pid``). - :param obj: Optional obj to associate with this event. - - """ - __slots__ = () - - def __new__(cls, clock, timestamp, id, obj=None): - return tuple.__new__(cls, (clock, timestamp, id, obj)) - - def __repr__(self): - return R_CLOCK.format(*self) - - def __getnewargs__(self): - return tuple(self) - - def __lt__(self, other): - # 0: clock 1: timestamp 3: process id - try: - A, B = self[0], other[0] - # uses logical clock value first - if A and B: # use logical clock if available - if A == B: # equal clocks use lower process id - return self[2] < other[2] - return A < B - return self[1] < other[1] # ... or use timestamp - except IndexError: - return NotImplemented - __gt__ = lambda self, other: other < self - __le__ = lambda self, other: not other < self - __ge__ = lambda self, other: not self < other - - clock = property(itemgetter(0)) - timestamp = property(itemgetter(1)) - id = property(itemgetter(2)) - obj = property(itemgetter(3)) - - -class LamportClock(object): - """Lamport's logical clock. - - From Wikipedia: - - A Lamport logical clock is a monotonically incrementing software counter - maintained in each process. It follows some simple rules: - - * A process increments its counter before each event in that process; - * When a process sends a message, it includes its counter value with - the message; - * On receiving a message, the receiver process sets its counter to be - greater than the maximum of its own value and the received value - before it considers the message received. - - Conceptually, this logical clock can be thought of as a clock that only - has meaning in relation to messages moving between processes. When a - process receives a message, it resynchronizes its logical clock with - the sender. - - .. seealso:: - - * `Lamport timestamps`_ - - * `Lamports distributed mutex`_ - - .. _`Lamport Timestamps`: http://en.wikipedia.org/wiki/Lamport_timestamps - .. _`Lamports distributed mutex`: http://bit.ly/p99ybE - - *Usage* - - When sending a message use :meth:`forward` to increment the clock, - when receiving a message use :meth:`adjust` to sync with - the time stamp of the incoming message. - - """ - #: The clocks current value. - value = 0 - - def __init__(self, initial_value=0, Lock=Lock): - self.value = initial_value - self.mutex = Lock() - - def adjust(self, other): - with self.mutex: - value = self.value = max(self.value, other) + 1 - return value - - def forward(self): - with self.mutex: - self.value += 1 - return self.value - - def sort_heap(self, h): - """List of tuples containing at least two elements, representing - an event, where the first element is the event's scalar clock value, - and the second element is the id of the process (usually - ``"hostname:pid"``): ``sh([(clock, processid, ...?), (...)])`` - - The list must already be sorted, which is why we refer to it as a - heap. - - The tuple will not be unpacked, so more than two elements can be - present. - - Will return the latest event. - - """ - if h[0][0] == h[1][0]: - same = [] - for PN in zip(h, islice(h, 1, None)): - if PN[0][0] != PN[1][0]: - break # Prev and Next's clocks differ - same.append(PN[0]) - # return first item sorted by process id - return sorted(same, key=lambda event: event[1])[0] - # clock values unique, return first item - return h[0] - - def __str__(self): - return str(self.value) - - def __repr__(self): - return '<LamportClock: {0.value}>'.format(self) diff --git a/awx/lib/site-packages/kombu/common.py b/awx/lib/site-packages/kombu/common.py deleted file mode 100644 index 99f4f6f943..0000000000 --- a/awx/lib/site-packages/kombu/common.py +++ /dev/null @@ -1,398 +0,0 @@ -""" -kombu.common -============ - -Common Utilities. - -""" -from __future__ import absolute_import - -import os -import socket -import threading - -from collections import deque -from contextlib import contextmanager -from functools import partial -from itertools import count -from uuid import getnode as _getnode, uuid4, uuid3, NAMESPACE_OID - -from amqp import RecoverableConnectionError - -from .entity import Exchange, Queue -from .five import range -from .log import get_logger -from .serialization import registry as serializers -from .utils import uuid - -try: - from _thread import get_ident -except ImportError: # pragma: no cover - try: # noqa - from thread import get_ident # noqa - except ImportError: # pragma: no cover - from dummy_thread import get_ident # noqa - -__all__ = ['Broadcast', 'maybe_declare', 'uuid', - 'itermessages', 'send_reply', - 'collect_replies', 'insured', 'drain_consumer', - 'eventloop'] - -#: Prefetch count can't exceed short. -PREFETCH_COUNT_MAX = 0xFFFF - -logger = get_logger(__name__) - -_node_id = None - - -def get_node_id(): - global _node_id - if _node_id is None: - _node_id = uuid4().int - return _node_id - - -def generate_oid(node_id, process_id, thread_id, instance): - ent = '%x-%x-%x-%x' % (get_node_id(), process_id, thread_id, id(instance)) - return str(uuid3(NAMESPACE_OID, ent)) - - -def oid_from(instance): - return generate_oid(_getnode(), os.getpid(), get_ident(), instance) - - -class Broadcast(Queue): - """Convenience class used to define broadcast queues. - - Every queue instance will have a unique name, - and both the queue and exchange is configured with auto deletion. - - :keyword name: This is used as the name of the exchange. - :keyword queue: By default a unique id is used for the queue - name for every consumer. You can specify a custom queue - name here. - :keyword \*\*kwargs: See :class:`~kombu.Queue` for a list - of additional keyword arguments supported. - - """ - - def __init__(self, name=None, queue=None, **kwargs): - return super(Broadcast, self).__init__( - name=queue or 'bcast.%s' % (uuid(), ), - **dict({'alias': name, - 'auto_delete': True, - 'exchange': Exchange(name, type='fanout')}, **kwargs)) - - -def declaration_cached(entity, channel): - return entity in channel.connection.client.declared_entities - - -def maybe_declare(entity, channel=None, retry=False, **retry_policy): - is_bound = entity.is_bound - - if not is_bound: - assert channel - entity = entity.bind(channel) - - if channel is None: - assert is_bound - channel = entity.channel - - declared = ident = None - if channel.connection and entity.can_cache_declaration: - declared = channel.connection.client.declared_entities - ident = hash(entity) - if ident in declared: - return False - - if retry: - return _imaybe_declare(entity, declared, ident, - channel, **retry_policy) - return _maybe_declare(entity, declared, ident, channel) - - -def _maybe_declare(entity, declared, ident, channel): - channel = channel or entity.channel - if not channel.connection: - raise RecoverableConnectionError('channel disconnected') - entity.declare() - if declared is not None and ident: - declared.add(ident) - return True - - -def _imaybe_declare(entity, declared, ident, channel, **retry_policy): - return entity.channel.connection.client.ensure( - entity, _maybe_declare, **retry_policy)( - entity, declared, ident, channel) - - -def drain_consumer(consumer, limit=1, timeout=None, callbacks=None): - acc = deque() - - def on_message(body, message): - acc.append((body, message)) - - consumer.callbacks = [on_message] + (callbacks or []) - - with consumer: - for _ in eventloop(consumer.channel.connection.client, - limit=limit, timeout=timeout, ignore_timeouts=True): - try: - yield acc.popleft() - except IndexError: - pass - - -def itermessages(conn, channel, queue, limit=1, timeout=None, - callbacks=None, **kwargs): - return drain_consumer(conn.Consumer(channel, queues=[queue], **kwargs), - limit=limit, timeout=timeout, callbacks=callbacks) - - -def eventloop(conn, limit=None, timeout=None, ignore_timeouts=False): - """Best practice generator wrapper around ``Connection.drain_events``. - - Able to drain events forever, with a limit, and optionally ignoring - timeout errors (a timeout of 1 is often used in environments where - the socket can get "stuck", and is a best practice for Kombu consumers). - - **Examples** - - ``eventloop`` is a generator:: - - from kombu.common import eventloop - - def run(connection): - it = eventloop(connection, timeout=1, ignore_timeouts=True) - next(it) # one event consumed, or timed out. - - for _ in eventloop(connection, timeout=1, ignore_timeouts=True): - pass # loop forever. - - It also takes an optional limit parameter, and timeout errors - are propagated by default:: - - for _ in eventloop(connection, limit=1, timeout=1): - pass - - .. seealso:: - - :func:`itermessages`, which is an event loop bound to one or more - consumers, that yields any messages received. - - """ - for i in limit and range(limit) or count(): - try: - yield conn.drain_events(timeout=timeout) - except socket.timeout: - if timeout and not ignore_timeouts: # pragma: no cover - raise - - -def send_reply(exchange, req, msg, - producer=None, retry=False, retry_policy=None, **props): - """Send reply for request. - - :param exchange: Reply exchange - :param req: Original request, a message with a ``reply_to`` property. - :param producer: Producer instance - :param retry: If true must retry according to ``reply_policy`` argument. - :param retry_policy: Retry settings. - :param props: Extra properties - - """ - - producer.publish( - msg, exchange=exchange, - retry=retry, retry_policy=retry_policy, - **dict({'routing_key': req.properties['reply_to'], - 'correlation_id': req.properties.get('correlation_id'), - 'serializer': serializers.type_to_name[req.content_type], - 'content_encoding': req.content_encoding}, **props) - ) - - -def collect_replies(conn, channel, queue, *args, **kwargs): - """Generator collecting replies from ``queue``""" - no_ack = kwargs.setdefault('no_ack', True) - received = False - try: - for body, message in itermessages(conn, channel, queue, - *args, **kwargs): - if not no_ack: - message.ack() - received = True - yield body - finally: - if received: - channel.after_reply_message_received(queue.name) - - -def _ensure_errback(exc, interval): - logger.error( - 'Connection error: %r. Retry in %ss\n', exc, interval, - exc_info=True, - ) - - -@contextmanager -def _ignore_errors(conn): - try: - yield - except conn.connection_errors + conn.channel_errors: - pass - - -def ignore_errors(conn, fun=None, *args, **kwargs): - """Ignore connection and channel errors. - - The first argument must be a connection object, or any other object - with ``connection_error`` and ``channel_error`` attributes. - - Can be used as a function: - - .. code-block:: python - - def example(connection): - ignore_errors(connection, consumer.channel.close) - - or as a context manager: - - .. code-block:: python - - def example(connection): - with ignore_errors(connection): - consumer.channel.close() - - - .. note:: - - Connection and channel errors should be properly handled, - and not ignored. Using this function is only acceptable in a cleanup - phase, like when a connection is lost or at shutdown. - - """ - if fun: - with _ignore_errors(conn): - return fun(*args, **kwargs) - return _ignore_errors(conn) - - -def revive_connection(connection, channel, on_revive=None): - if on_revive: - on_revive(channel) - - -def insured(pool, fun, args, kwargs, errback=None, on_revive=None, **opts): - """Ensures function performing broker commands completes - despite intermittent connection failures.""" - errback = errback or _ensure_errback - - with pool.acquire(block=True) as conn: - conn.ensure_connection(errback=errback) - # we cache the channel for subsequent calls, this has to be - # reset on revival. - channel = conn.default_channel - revive = partial(revive_connection, conn, on_revive=on_revive) - insured = conn.autoretry(fun, channel, errback=errback, - on_revive=revive, **opts) - retval, _ = insured(*args, **dict(kwargs, connection=conn)) - return retval - - -class QoS(object): - """Thread safe increment/decrement of a channels prefetch_count. - - :param callback: Function used to set new prefetch count, - e.g. ``consumer.qos`` or ``channel.basic_qos``. Will be called - with a single ``prefetch_count`` keyword argument. - :param initial_value: Initial prefetch count value. - - **Example usage** - - .. code-block:: python - - >>> from kombu import Consumer, Connection - >>> connection = Connection('amqp://') - >>> consumer = Consumer(connection) - >>> qos = QoS(consumer.qos, initial_prefetch_count=2) - >>> qos.update() # set initial - - >>> qos.value - 2 - - >>> def in_some_thread(): - ... qos.increment_eventually() - - >>> def in_some_other_thread(): - ... qos.decrement_eventually() - - >>> while 1: - ... if qos.prev != qos.value: - ... qos.update() # prefetch changed so update. - - It can be used with any function supporting a ``prefetch_count`` keyword - argument:: - - >>> channel = connection.channel() - >>> QoS(channel.basic_qos, 10) - - - >>> def set_qos(prefetch_count): - ... print('prefetch count now: %r' % (prefetch_count, )) - >>> QoS(set_qos, 10) - - """ - prev = None - - def __init__(self, callback, initial_value): - self.callback = callback - self._mutex = threading.RLock() - self.value = initial_value or 0 - - def increment_eventually(self, n=1): - """Increment the value, but do not update the channels QoS. - - The MainThread will be responsible for calling :meth:`update` - when necessary. - - """ - with self._mutex: - if self.value: - self.value = self.value + max(n, 0) - return self.value - - def decrement_eventually(self, n=1): - """Decrement the value, but do not update the channels QoS. - - The MainThread will be responsible for calling :meth:`update` - when necessary. - - """ - with self._mutex: - if self.value: - self.value -= n - if self.value < 1: - self.value = 1 - return self.value - - def set(self, pcount): - """Set channel prefetch_count setting.""" - if pcount != self.prev: - new_value = pcount - if pcount > PREFETCH_COUNT_MAX: - logger.warn('QoS: Disabled: prefetch_count exceeds %r', - PREFETCH_COUNT_MAX) - new_value = 0 - logger.debug('basic.qos: prefetch_count->%s', new_value) - self.callback(prefetch_count=new_value) - self.prev = pcount - return pcount - - def update(self): - """Update prefetch count with current value.""" - with self._mutex: - return self.set(self.value) diff --git a/awx/lib/site-packages/kombu/compat.py b/awx/lib/site-packages/kombu/compat.py deleted file mode 100644 index 7347e9bc9e..0000000000 --- a/awx/lib/site-packages/kombu/compat.py +++ /dev/null @@ -1,215 +0,0 @@ -""" -kombu.compat -============ - -Carrot compatible interface for :class:`Publisher` and :class:`Producer`. - -See http://packages.python.org/pypi/carrot for documentation. - -""" -from __future__ import absolute_import - -from itertools import count - -from . import messaging -from .entity import Exchange, Queue -from .five import items - -__all__ = ['Publisher', 'Consumer'] - -# XXX compat attribute -entry_to_queue = Queue.from_dict - - -def _iterconsume(connection, consumer, no_ack=False, limit=None): - consumer.consume(no_ack=no_ack) - for iteration in count(0): # for infinity - if limit and iteration >= limit: - raise StopIteration - yield connection.drain_events() - - -class Publisher(messaging.Producer): - exchange = '' - exchange_type = 'direct' - routing_key = '' - durable = True - auto_delete = False - _closed = False - - def __init__(self, connection, exchange=None, routing_key=None, - exchange_type=None, durable=None, auto_delete=None, - channel=None, **kwargs): - if channel: - connection = channel - - self.exchange = exchange or self.exchange - self.exchange_type = exchange_type or self.exchange_type - self.routing_key = routing_key or self.routing_key - - if auto_delete is not None: - self.auto_delete = auto_delete - if durable is not None: - self.durable = durable - - if not isinstance(self.exchange, Exchange): - self.exchange = Exchange(name=self.exchange, - type=self.exchange_type, - routing_key=self.routing_key, - auto_delete=self.auto_delete, - durable=self.durable) - super(Publisher, self).__init__(connection, self.exchange, **kwargs) - - def send(self, *args, **kwargs): - return self.publish(*args, **kwargs) - - def close(self): - super(Publisher, self).close() - self._closed = True - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - @property - def backend(self): - return self.channel - - -class Consumer(messaging.Consumer): - queue = '' - exchange = '' - routing_key = '' - exchange_type = 'direct' - durable = True - exclusive = False - auto_delete = False - exchange_type = 'direct' - _closed = False - - def __init__(self, connection, queue=None, exchange=None, - routing_key=None, exchange_type=None, durable=None, - exclusive=None, auto_delete=None, **kwargs): - self.backend = connection.channel() - - if durable is not None: - self.durable = durable - if exclusive is not None: - self.exclusive = exclusive - if auto_delete is not None: - self.auto_delete = auto_delete - - self.queue = queue or self.queue - self.exchange = exchange or self.exchange - self.exchange_type = exchange_type or self.exchange_type - self.routing_key = routing_key or self.routing_key - - exchange = Exchange(self.exchange, - type=self.exchange_type, - routing_key=self.routing_key, - auto_delete=self.auto_delete, - durable=self.durable) - queue = Queue(self.queue, - exchange=exchange, - routing_key=self.routing_key, - durable=self.durable, - exclusive=self.exclusive, - auto_delete=self.auto_delete) - super(Consumer, self).__init__(self.backend, queue, **kwargs) - - def revive(self, channel): - self.backend = channel - super(Consumer, self).revive(channel) - - def close(self): - self.cancel() - self.backend.close() - self._closed = True - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - def __iter__(self): - return self.iterqueue(infinite=True) - - def fetch(self, no_ack=None, enable_callbacks=False): - if no_ack is None: - no_ack = self.no_ack - message = self.queues[0].get(no_ack) - if message: - if enable_callbacks: - self.receive(message.payload, message) - return message - - def process_next(self): - raise NotImplementedError('Use fetch(enable_callbacks=True)') - - def discard_all(self, filterfunc=None): - if filterfunc is not None: - raise NotImplementedError( - 'discard_all does not implement filters') - return self.purge() - - def iterconsume(self, limit=None, no_ack=None): - return _iterconsume(self.connection, self, no_ack, limit) - - def wait(self, limit=None): - it = self.iterconsume(limit) - return list(it) - - def iterqueue(self, limit=None, infinite=False): - for items_since_start in count(): # for infinity - item = self.fetch() - if (not infinite and item is None) or \ - (limit and items_since_start >= limit): - raise StopIteration - yield item - - -class ConsumerSet(messaging.Consumer): - - def __init__(self, connection, from_dict=None, consumers=None, - channel=None, **kwargs): - if channel: - self._provided_channel = True - self.backend = channel - else: - self._provided_channel = False - self.backend = connection.channel() - - queues = [] - if consumers: - for consumer in consumers: - queues.extend(consumer.queues) - if from_dict: - for queue_name, queue_options in items(from_dict): - queues.append(Queue.from_dict(queue_name, **queue_options)) - - super(ConsumerSet, self).__init__(self.backend, queues, **kwargs) - - def iterconsume(self, limit=None, no_ack=False): - return _iterconsume(self.connection, self, no_ack, limit) - - def discard_all(self): - return self.purge() - - def add_consumer_from_dict(self, queue, **options): - return self.add_queue_from_dict(queue, **options) - - def add_consumer(self, consumer): - for queue in consumer.queues: - self.add_queue(queue) - - def revive(self, channel): - self.backend = channel - super(ConsumerSet, self).revive(channel) - - def close(self): - self.cancel() - if not self._provided_channel: - self.channel.close() diff --git a/awx/lib/site-packages/kombu/compression.py b/awx/lib/site-packages/kombu/compression.py deleted file mode 100644 index 866433d8e5..0000000000 --- a/awx/lib/site-packages/kombu/compression.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -kombu.compression -================= - -Compression utilities. - -""" -from __future__ import absolute_import - -from kombu.utils.encoding import ensure_bytes - -import zlib - -_aliases = {} -_encoders = {} -_decoders = {} - -__all__ = ['register', 'encoders', 'get_encoder', - 'get_decoder', 'compress', 'decompress'] - - -def register(encoder, decoder, content_type, aliases=[]): - """Register new compression method. - - :param encoder: Function used to compress text. - :param decoder: Function used to decompress previously compressed text. - :param content_type: The mime type this compression method identifies as. - :param aliases: A list of names to associate with this compression method. - - """ - _encoders[content_type] = encoder - _decoders[content_type] = decoder - _aliases.update((alias, content_type) for alias in aliases) - - -def encoders(): - """Return a list of available compression methods.""" - return list(_encoders) - - -def get_encoder(t): - """Get encoder by alias name.""" - t = _aliases.get(t, t) - return _encoders[t], t - - -def get_decoder(t): - """Get decoder by alias name.""" - return _decoders[_aliases.get(t, t)] - - -def compress(body, content_type): - """Compress text. - - :param body: The text to compress. - :param content_type: mime-type of compression method to use. - - """ - encoder, content_type = get_encoder(content_type) - return encoder(ensure_bytes(body)), content_type - - -def decompress(body, content_type): - """Decompress compressed text. - - :param body: Previously compressed text to uncompress. - :param content_type: mime-type of compression method used. - - """ - return get_decoder(content_type)(body) - - -register(zlib.compress, - zlib.decompress, - 'application/x-gzip', aliases=['gzip', 'zlib']) -try: - import bz2 -except ImportError: - pass # Jython? -else: - register(bz2.compress, - bz2.decompress, - 'application/x-bz2', aliases=['bzip2', 'bzip']) diff --git a/awx/lib/site-packages/kombu/connection.py b/awx/lib/site-packages/kombu/connection.py deleted file mode 100644 index 291d680ad7..0000000000 --- a/awx/lib/site-packages/kombu/connection.py +++ /dev/null @@ -1,1059 +0,0 @@ -""" -kombu.connection -================ - -Broker connection and pools. - -""" -from __future__ import absolute_import - -import os -import socket - -from contextlib import contextmanager -from itertools import count, cycle -from operator import itemgetter - -# jython breaks on relative import for .exceptions for some reason -# (Issue #112) -from kombu import exceptions -from .five import Empty, range, string_t, text_t, LifoQueue as _LifoQueue -from .log import get_logger -from .transport import get_transport_cls, supports_librabbitmq -from .utils import cached_property, retry_over_time, shufflecycle, HashedSeq -from .utils.compat import OrderedDict -from .utils.functional import lazy -from .utils.url import as_url, parse_url, quote, urlparse - -__all__ = ['Connection', 'ConnectionPool', 'ChannelPool'] - -RESOLVE_ALIASES = {'pyamqp': 'amqp', - 'librabbitmq': 'amqp'} - -_LOG_CONNECTION = os.environ.get('KOMBU_LOG_CONNECTION', False) -_LOG_CHANNEL = os.environ.get('KOMBU_LOG_CHANNEL', False) - -logger = get_logger(__name__) -roundrobin_failover = cycle - -failover_strategies = { - 'round-robin': roundrobin_failover, - 'shuffle': shufflecycle, -} - - -class Connection(object): - """A connection to the broker. - - :param URL: Broker URL, or a list of URLs, e.g. - - .. code-block:: python - - Connection('amqp://guest:guest@localhost:5672//') - Connection('amqp://foo;amqp://bar', failover_strategy='round-robin') - Connection('redis://', transport_options={ - 'visibility_timeout': 3000, - }) - - import ssl - Connection('amqp://', login_method='EXTERNAL', ssl={ - 'ca_certs': '/etc/pki/tls/certs/something.crt', - 'keyfile': '/etc/something/system.key', - 'certfile': '/etc/something/system.cert', - 'cert_reqs': ssl.CERT_REQUIRED, - }) - - .. admonition:: SSL compatibility - - SSL currently only works with the py-amqp & amqplib transports. - For other transports you can use stunnel. - - :keyword hostname: Default host name/address if not provided in the URL. - :keyword userid: Default user name if not provided in the URL. - :keyword password: Default password if not provided in the URL. - :keyword virtual_host: Default virtual host if not provided in the URL. - :keyword port: Default port if not provided in the URL. - :keyword ssl: Use SSL to connect to the server. Default is ``False``. - May not be supported by the specified transport. - :keyword transport: Default transport if not specified in the URL. - :keyword connect_timeout: Timeout in seconds for connecting to the - server. May not be supported by the specified transport. - :keyword transport_options: A dict of additional connection arguments to - pass to alternate kombu channel implementations. Consult the transport - documentation for available options. - :keyword heartbeat: Heartbeat interval in int/float seconds. - Note that if heartbeats are enabled then the :meth:`heartbeat_check` - method must be called regularly, around once per second. - - .. note:: - - The connection is established lazily when needed. If you need the - connection to be established, then force it by calling - :meth:`connect`:: - - >>> conn = Connection('amqp://') - >>> conn.connect() - - and always remember to close the connection:: - - >>> conn.release() - - """ - port = None - virtual_host = '/' - connect_timeout = 5 - - _closed = None - _connection = None - _default_channel = None - _transport = None - _logger = False - uri_prefix = None - - #: The cache of declared entities is per connection, - #: in case the server loses data. - declared_entities = None - - #: Iterator returning the next broker URL to try in the event - #: of connection failure (initialized by :attr:`failover_strategy`). - cycle = None - - #: Additional transport specific options, - #: passed on to the transport instance. - transport_options = None - - #: Strategy used to select new hosts when reconnecting after connection - #: failure. One of "round-robin", "shuffle" or any custom iterator - #: constantly yielding new URLs to try. - failover_strategy = 'round-robin' - - #: Heartbeat value, currently only supported by the py-amqp transport. - heartbeat = None - - hostname = userid = password = ssl = login_method = None - - def __init__(self, hostname='localhost', userid=None, - password=None, virtual_host=None, port=None, insist=False, - ssl=False, transport=None, connect_timeout=5, - transport_options=None, login_method=None, uri_prefix=None, - heartbeat=0, failover_strategy='round-robin', - alternates=None, **kwargs): - alt = [] if alternates is None else alternates - # have to spell the args out, just to get nice docstrings :( - params = self._initial_params = { - 'hostname': hostname, 'userid': userid, - 'password': password, 'virtual_host': virtual_host, - 'port': port, 'insist': insist, 'ssl': ssl, - 'transport': transport, 'connect_timeout': connect_timeout, - 'login_method': login_method, 'heartbeat': heartbeat - } - - if hostname and not isinstance(hostname, string_t): - alt.extend(hostname) - hostname = alt[0] - if hostname and '://' in hostname: - if ';' in hostname: - alt.extend(hostname.split(';')) - hostname = alt[0] - if '+' in hostname[:hostname.index('://')]: - # e.g. sqla+mysql://root:masterkey@localhost/ - params['transport'], params['hostname'] = \ - hostname.split('+', 1) - transport = self.uri_prefix = params['transport'] - else: - transport = transport or urlparse(hostname).scheme - if get_transport_cls(transport).can_parse_url: - # set the transport so that the default is not used. - params['transport'] = transport - else: - # we must parse the URL - params.update(parse_url(hostname)) - self._init_params(**params) - - # fallback hosts - self.alt = alt - self.failover_strategy = failover_strategies.get( - failover_strategy or 'round-robin') or failover_strategy - if self.alt: - self.cycle = self.failover_strategy(self.alt) - next(self.cycle) # skip first entry - - if transport_options is None: - transport_options = {} - self.transport_options = transport_options - - if _LOG_CONNECTION: # pragma: no cover - self._logger = True - - if uri_prefix: - self.uri_prefix = uri_prefix - - self.declared_entities = set() - - def switch(self, url): - """Switch connection parameters to use a new URL (does not - reconnect)""" - self.close() - self.declared_entities.clear() - self._closed = False - self._init_params(**dict(self._initial_params, **parse_url(url))) - - def maybe_switch_next(self): - """Switch to next URL given by the current failover strategy (if - any).""" - if self.cycle: - self.switch(next(self.cycle)) - - def _init_params(self, hostname, userid, password, virtual_host, port, - insist, ssl, transport, connect_timeout, - login_method, heartbeat): - transport = transport or 'amqp' - if transport == 'amqp' and supports_librabbitmq(): - transport = 'librabbitmq' - self.hostname = hostname - self.userid = userid - self.password = password - self.login_method = login_method - self.virtual_host = virtual_host or self.virtual_host - self.port = port or self.port - self.insist = insist - self.connect_timeout = connect_timeout - self.ssl = ssl - self.transport_cls = transport - self.heartbeat = heartbeat and float(heartbeat) - - def register_with_event_loop(self, loop): - self.transport.register_with_event_loop(self.connection, loop) - - def _debug(self, msg, *args, **kwargs): - if self._logger: # pragma: no cover - fmt = '[Kombu connection:0x{id:x}] {msg}' - logger.debug(fmt.format(id=id(self), msg=text_t(msg)), - *args, **kwargs) - - def connect(self): - """Establish connection to server immediately.""" - self._closed = False - return self.connection - - def channel(self): - """Create and return a new channel.""" - self._debug('create channel') - chan = self.transport.create_channel(self.connection) - if _LOG_CHANNEL: # pragma: no cover - from .utils.debug import Logwrapped - return Logwrapped(chan, 'kombu.channel', - '[Kombu channel:{0.channel_id}] ') - return chan - - def heartbeat_check(self, rate=2): - """Allow the transport to perform any periodic tasks - required to make heartbeats work. This should be called - approximately every second. - - If the current transport does not support heartbeats then - this is a noop operation. - - :keyword rate: Rate is how often the tick is called - compared to the actual heartbeat value. E.g. if - the heartbeat is set to 3 seconds, and the tick - is called every 3 / 2 seconds, then the rate is 2. - This value is currently unused by any transports. - - """ - return self.transport.heartbeat_check(self.connection, rate=rate) - - def drain_events(self, **kwargs): - """Wait for a single event from the server. - - :keyword timeout: Timeout in seconds before we give up. - - - :raises :exc:`socket.timeout`: if the timeout is exceeded. - - """ - return self.transport.drain_events(self.connection, **kwargs) - - def maybe_close_channel(self, channel): - """Close given channel, but ignore connection and channel errors.""" - try: - channel.close() - except (self.connection_errors + self.channel_errors): - pass - - def _do_close_self(self): - # Close only connection and channel(s), but not transport. - self.declared_entities.clear() - if self._default_channel: - self.maybe_close_channel(self._default_channel) - if self._connection: - try: - self.transport.close_connection(self._connection) - except self.connection_errors + (AttributeError, socket.error): - pass - self._connection = None - - def _close(self): - """Really close connection, even if part of a connection pool.""" - self._do_close_self() - if self._transport: - self._transport.client = None - self._transport = None - self._debug('closed') - self._closed = True - - def collect(self, socket_timeout=None): - # amqp requires communication to close, we don't need that just - # to clear out references, Transport._collect can also be implemented - # by other transports that want fast after fork - try: - gc_transport = self._transport._collect - except AttributeError: - _timeo = socket.getdefaulttimeout() - socket.setdefaulttimeout(socket_timeout) - try: - self._close() - except socket.timeout: - pass - finally: - socket.setdefaulttimeout(_timeo) - else: - gc_transport(self._connection) - if self._transport: - self._transport.client = None - self._transport = None - self.declared_entities.clear() - self._connection = None - - def release(self): - """Close the connection (if open).""" - self._close() - close = release - - def ensure_connection(self, errback=None, max_retries=None, - interval_start=2, interval_step=2, interval_max=30, - callback=None): - """Ensure we have a connection to the server. - - If not retry establishing the connection with the settings - specified. - - :keyword errback: Optional callback called each time the connection - can't be established. Arguments provided are the exception - raised and the interval that will be slept ``(exc, interval)``. - - :keyword max_retries: Maximum number of times to retry. - If this limit is exceeded the connection error will be re-raised. - - :keyword interval_start: The number of seconds we start sleeping for. - :keyword interval_step: How many seconds added to the interval - for each retry. - :keyword interval_max: Maximum number of seconds to sleep between - each retry. - :keyword callback: Optional callback that is called for every - internal iteration (1 s) - - """ - def on_error(exc, intervals, retries, interval=0): - round = self.completes_cycle(retries) - if round: - interval = next(intervals) - if errback: - errback(exc, interval) - self.maybe_switch_next() # select next host - - return interval if round else 0 - - retry_over_time(self.connect, self.recoverable_connection_errors, - (), {}, on_error, max_retries, - interval_start, interval_step, interval_max, callback) - return self - - def completes_cycle(self, retries): - """Return true if the cycle is complete after number of `retries`.""" - return not (retries + 1) % len(self.alt) if self.alt else True - - def revive(self, new_channel): - """Revive connection after connection re-established.""" - if self._default_channel: - self.maybe_close_channel(self._default_channel) - self._default_channel = None - - def _default_ensure_callback(self, exc, interval): - logger.error("Ensure: Operation error: %r. Retry in %ss", - exc, interval, exc_info=True) - - def ensure(self, obj, fun, errback=None, max_retries=None, - interval_start=1, interval_step=1, interval_max=1, - on_revive=None): - """Ensure operation completes, regardless of any channel/connection - errors occurring. - - Will retry by establishing the connection, and reapplying - the function. - - :param fun: Method to apply. - - :keyword errback: Optional callback called each time the connection - can't be established. Arguments provided are the exception - raised and the interval that will be slept ``(exc, interval)``. - - :keyword max_retries: Maximum number of times to retry. - If this limit is exceeded the connection error will be re-raised. - - :keyword interval_start: The number of seconds we start sleeping for. - :keyword interval_step: How many seconds added to the interval - for each retry. - :keyword interval_max: Maximum number of seconds to sleep between - each retry. - - **Example** - - This is an example ensuring a publish operation:: - - >>> from kombu import Connection, Producer - >>> conn = Connection('amqp://') - >>> producer = Producer(conn) - - >>> def errback(exc, interval): - ... logger.error('Error: %r', exc, exc_info=1) - ... logger.info('Retry in %s seconds.', interval) - - >>> publish = conn.ensure(producer, producer.publish, - ... errback=errback, max_retries=3) - >>> publish({'hello': 'world'}, routing_key='dest') - - """ - def _ensured(*args, **kwargs): - got_connection = 0 - conn_errors = self.recoverable_connection_errors - chan_errors = self.recoverable_channel_errors - has_modern_errors = hasattr( - self.transport, 'recoverable_connection_errors', - ) - for retries in count(0): # for infinity - try: - return fun(*args, **kwargs) - except conn_errors as exc: - if got_connection and not has_modern_errors: - # transport can not distinguish between - # recoverable/irrecoverable errors, so we propagate - # the error if it persists after a new connection was - # successfully established. - raise - if max_retries is not None and retries > max_retries: - raise - self._debug('ensure connection error: %r', exc, exc_info=1) - self._connection = None - self._do_close_self() - errback and errback(exc, 0) - remaining_retries = None - if max_retries is not None: - remaining_retries = max(max_retries - retries, 1) - self.ensure_connection(errback, - remaining_retries, - interval_start, - interval_step, - interval_max) - new_channel = self.channel() - self.revive(new_channel) - obj.revive(new_channel) - if on_revive: - on_revive(new_channel) - got_connection += 1 - except chan_errors as exc: - if max_retries is not None and retries > max_retries: - raise - self._debug('ensure channel error: %r', exc, exc_info=1) - errback and errback(exc, 0) - _ensured.__name__ = "%s(ensured)" % fun.__name__ - _ensured.__doc__ = fun.__doc__ - _ensured.__module__ = fun.__module__ - return _ensured - - def autoretry(self, fun, channel=None, **ensure_options): - """Decorator for functions supporting a ``channel`` keyword argument. - - The resulting callable will retry calling the function if - it raises connection or channel related errors. - The return value will be a tuple of ``(retval, last_created_channel)``. - - If a ``channel`` is not provided, then one will be automatically - acquired (remember to close it afterwards). - - See :meth:`ensure` for the full list of supported keyword arguments. - - Example usage:: - - channel = connection.channel() - try: - ret, channel = connection.autoretry(publish_messages, channel) - finally: - channel.close() - """ - channels = [channel] - create_channel = self.channel - - class Revival(object): - __name__ = fun.__name__ - __module__ = fun.__module__ - __doc__ = fun.__doc__ - - def revive(self, channel): - channels[0] = channel - - def __call__(self, *args, **kwargs): - if channels[0] is None: - self.revive(create_channel()) - return fun(*args, channel=channels[0], **kwargs), channels[0] - - revive = Revival() - return self.ensure(revive, revive, **ensure_options) - - def create_transport(self): - return self.get_transport_cls()(client=self) - - def get_transport_cls(self): - """Get the currently used transport class.""" - transport_cls = self.transport_cls - if not transport_cls or isinstance(transport_cls, string_t): - transport_cls = get_transport_cls(transport_cls) - return transport_cls - - def clone(self, **kwargs): - """Create a copy of the connection with the same connection - settings.""" - return self.__class__(**dict(self._info(resolve=False), **kwargs)) - - def get_heartbeat_interval(self): - return self.transport.get_heartbeat_interval(self.connection) - - def _info(self, resolve=True): - transport_cls = self.transport_cls - if resolve: - transport_cls = RESOLVE_ALIASES.get(transport_cls, transport_cls) - D = self.transport.default_connection_params - - hostname = self.hostname or D.get('hostname') - if self.uri_prefix: - hostname = '%s+%s' % (self.uri_prefix, hostname) - - info = ( - ('hostname', hostname), - ('userid', self.userid or D.get('userid')), - ('password', self.password or D.get('password')), - ('virtual_host', self.virtual_host or D.get('virtual_host')), - ('port', self.port or D.get('port')), - ('insist', self.insist), - ('ssl', self.ssl), - ('transport', transport_cls), - ('connect_timeout', self.connect_timeout), - ('transport_options', self.transport_options), - ('login_method', self.login_method or D.get('login_method')), - ('uri_prefix', self.uri_prefix), - ('heartbeat', self.heartbeat), - ('alternates', self.alt), - ) - return info - - def info(self): - """Get connection info.""" - return OrderedDict(self._info()) - - def __eqhash__(self): - return HashedSeq(self.transport_cls, self.hostname, self.userid, - self.password, self.virtual_host, self.port, - repr(self.transport_options)) - - def as_uri(self, include_password=False, mask='**', - getfields=itemgetter('port', 'userid', 'password', - 'virtual_host', 'transport')): - """Convert connection parameters to URL form.""" - hostname = self.hostname or 'localhost' - if self.transport.can_parse_url: - if self.uri_prefix: - return '%s+%s' % (self.uri_prefix, hostname) - return self.hostname - fields = self.info() - port, userid, password, vhost, transport = getfields(fields) - scheme = ('{0}+{1}'.format(self.uri_prefix, transport) - if self.uri_prefix else transport) - return as_url( - scheme, hostname, port, userid, password, quote(vhost), - sanitize=not include_password, mask=mask, - ) - - def Pool(self, limit=None, preload=None): - """Pool of connections. - - See :class:`ConnectionPool`. - - :keyword limit: Maximum number of active connections. - Default is no limit. - :keyword preload: Number of connections to preload - when the pool is created. Default is 0. - - *Example usage*:: - - >>> connection = Connection('amqp://') - >>> pool = connection.Pool(2) - >>> c1 = pool.acquire() - >>> c2 = pool.acquire() - >>> c3 = pool.acquire() - Traceback (most recent call last): - File "<stdin>", line 1, in <module> - File "kombu/connection.py", line 354, in acquire - raise ConnectionLimitExceeded(self.limit) - kombu.exceptions.ConnectionLimitExceeded: 2 - >>> c1.release() - >>> c3 = pool.acquire() - - """ - return ConnectionPool(self, limit, preload) - - def ChannelPool(self, limit=None, preload=None): - """Pool of channels. - - See :class:`ChannelPool`. - - :keyword limit: Maximum number of active channels. - Default is no limit. - :keyword preload: Number of channels to preload - when the pool is created. Default is 0. - - *Example usage*:: - - >>> connection = Connection('amqp://') - >>> pool = connection.ChannelPool(2) - >>> c1 = pool.acquire() - >>> c2 = pool.acquire() - >>> c3 = pool.acquire() - Traceback (most recent call last): - File "<stdin>", line 1, in <module> - File "kombu/connection.py", line 354, in acquire - raise ChannelLimitExceeded(self.limit) - kombu.connection.ChannelLimitExceeded: 2 - >>> c1.release() - >>> c3 = pool.acquire() - - """ - return ChannelPool(self, limit, preload) - - def Producer(self, channel=None, *args, **kwargs): - """Create new :class:`kombu.Producer` instance using this - connection.""" - from .messaging import Producer - return Producer(channel or self, *args, **kwargs) - - def Consumer(self, queues=None, channel=None, *args, **kwargs): - """Create new :class:`kombu.Consumer` instance using this - connection.""" - from .messaging import Consumer - return Consumer(channel or self, queues, *args, **kwargs) - - def SimpleQueue(self, name, no_ack=None, queue_opts=None, - exchange_opts=None, channel=None, **kwargs): - """Create new :class:`~kombu.simple.SimpleQueue`, using a channel - from this connection. - - If ``name`` is a string, a queue and exchange will be automatically - created using that name as the name of the queue and exchange, - also it will be used as the default routing key. - - :param name: Name of the queue/or a :class:`~kombu.Queue`. - :keyword no_ack: Disable acknowledgements. Default is false. - :keyword queue_opts: Additional keyword arguments passed to the - constructor of the automatically created - :class:`~kombu.Queue`. - :keyword exchange_opts: Additional keyword arguments passed to the - constructor of the automatically created - :class:`~kombu.Exchange`. - :keyword channel: Custom channel to use. If not specified the - connection default channel is used. - - """ - from .simple import SimpleQueue - return SimpleQueue(channel or self, name, no_ack, queue_opts, - exchange_opts, **kwargs) - - def SimpleBuffer(self, name, no_ack=None, queue_opts=None, - exchange_opts=None, channel=None, **kwargs): - """Create new :class:`~kombu.simple.SimpleQueue` using a channel - from this connection. - - Same as :meth:`SimpleQueue`, but configured with buffering - semantics. The resulting queue and exchange will not be durable, also - auto delete is enabled. Messages will be transient (not persistent), - and acknowledgements are disabled (``no_ack``). - - """ - from .simple import SimpleBuffer - return SimpleBuffer(channel or self, name, no_ack, queue_opts, - exchange_opts, **kwargs) - - def _establish_connection(self): - self._debug('establishing connection...') - conn = self.transport.establish_connection() - self._debug('connection established: %r', conn) - return conn - - def __repr__(self): - """``x.__repr__() <==> repr(x)``""" - return '<Connection: {0} at 0x{1:x}>'.format(self.as_uri(), id(self)) - - def __copy__(self): - """``x.__copy__() <==> copy(x)``""" - return self.clone() - - def __reduce__(self): - return self.__class__, tuple(self.info().values()), None - - def __enter__(self): - return self - - def __exit__(self, *args): - self.release() - - @property - def qos_semantics_matches_spec(self): - return self.transport.qos_semantics_matches_spec(self.connection) - - @property - def connected(self): - """Return true if the connection has been established.""" - return (not self._closed and - self._connection is not None and - self.transport.verify_connection(self._connection)) - - @property - def connection(self): - """The underlying connection object. - - .. warning:: - This instance is transport specific, so do not - depend on the interface of this object. - - """ - if not self._closed: - if not self.connected: - self.declared_entities.clear() - self._default_channel = None - self._connection = self._establish_connection() - self._closed = False - return self._connection - - @property - def default_channel(self): - """Default channel, created upon access and closed when the connection - is closed. - - Can be used for automatic channel handling when you only need one - channel, and also it is the channel implicitly used if a connection - is passed instead of a channel, to functions that require a channel. - - """ - # make sure we're still connected, and if not refresh. - self.connection - if self._default_channel is None: - self._default_channel = self.channel() - return self._default_channel - - @property - def host(self): - """The host as a host name/port pair separated by colon.""" - return ':'.join([self.hostname, str(self.port)]) - - @property - def transport(self): - if self._transport is None: - self._transport = self.create_transport() - return self._transport - - @cached_property - def manager(self): - """Experimental manager that can be used to manage/monitor the broker - instance. Not available for all transports.""" - return self.transport.manager - - def get_manager(self, *args, **kwargs): - return self.transport.get_manager(*args, **kwargs) - - @cached_property - def recoverable_connection_errors(self): - """List of connection related exceptions that can be recovered from, - but where the connection must be closed and re-established first.""" - try: - return self.transport.recoverable_connection_errors - except AttributeError: - # There were no such classification before, - # and all errors were assumed to be recoverable, - # so this is a fallback for transports that do - # not support the new recoverable/irrecoverable classes. - return self.connection_errors + self.channel_errors - - @cached_property - def recoverable_channel_errors(self): - """List of channel related exceptions that can be automatically - recovered from without re-establishing the connection.""" - try: - return self.transport.recoverable_channel_errors - except AttributeError: - return () - - @cached_property - def connection_errors(self): - """List of exceptions that may be raised by the connection.""" - return self.transport.connection_errors - - @cached_property - def channel_errors(self): - """List of exceptions that may be raised by the channel.""" - return self.transport.channel_errors - - @property - def supports_heartbeats(self): - return self.transport.supports_heartbeats - - @property - def is_evented(self): - return self.transport.supports_ev -BrokerConnection = Connection - - -class Resource(object): - LimitExceeded = exceptions.LimitExceeded - - def __init__(self, limit=None, preload=None): - self.limit = limit - self.preload = preload or 0 - self._closed = False - - self._resource = _LifoQueue() - self._dirty = set() - self.setup() - - def setup(self): - raise NotImplementedError('subclass responsibility') - - def _add_when_empty(self): - if self.limit and len(self._dirty) >= self.limit: - raise self.LimitExceeded(self.limit) - # All taken, put new on the queue and - # try get again, this way the first in line - # will get the resource. - self._resource.put_nowait(self.new()) - - def acquire(self, block=False, timeout=None): - """Acquire resource. - - :keyword block: If the limit is exceeded, - block until there is an available item. - :keyword timeout: Timeout to wait - if ``block`` is true. Default is :const:`None` (forever). - - :raises LimitExceeded: if block is false - and the limit has been exceeded. - - """ - if self._closed: - raise RuntimeError('Acquire on closed pool') - if self.limit: - while 1: - try: - R = self._resource.get(block=block, timeout=timeout) - except Empty: - self._add_when_empty() - else: - try: - R = self.prepare(R) - except BaseException: - if isinstance(R, lazy): - # no evaluated yet, just put it back - self._resource.put_nowait(R) - else: - # evaluted so must try to release/close first. - self.release(R) - raise - self._dirty.add(R) - break - else: - R = self.prepare(self.new()) - - def release(): - """Release resource so it can be used by another thread. - - The caller is responsible for discarding the object, - and to never use the resource again. A new resource must - be acquired if so needed. - - """ - self.release(R) - R.release = release - - return R - - def prepare(self, resource): - return resource - - def close_resource(self, resource): - resource.close() - - def release_resource(self, resource): - pass - - def replace(self, resource): - """Replace resource with a new instance. This can be used in case - of defective resources.""" - if self.limit: - self._dirty.discard(resource) - self.close_resource(resource) - - def release(self, resource): - if self.limit: - self._dirty.discard(resource) - self._resource.put_nowait(resource) - self.release_resource(resource) - else: - self.close_resource(resource) - - def collect_resource(self, resource): - pass - - def force_close_all(self): - """Close and remove all resources in the pool (also those in use). - - Can be used to close resources from parent processes - after fork (e.g. sockets/connections). - - """ - self._closed = True - dirty = self._dirty - resource = self._resource - while 1: # - acquired - try: - dres = dirty.pop() - except KeyError: - break - try: - self.collect_resource(dres) - except AttributeError: # Issue #78 - pass - while 1: # - available - # deque supports '.clear', but lists do not, so for that - # reason we use pop here, so that the underlying object can - # be any object supporting '.pop' and '.append'. - try: - res = resource.queue.pop() - except IndexError: - break - try: - self.collect_resource(res) - except AttributeError: - pass # Issue #78 - - if os.environ.get('KOMBU_DEBUG_POOL'): # pragma: no cover - _orig_acquire = acquire - _orig_release = release - - _next_resource_id = 0 - - def acquire(self, *args, **kwargs): # noqa - import traceback - id = self._next_resource_id = self._next_resource_id + 1 - print('+{0} ACQUIRE {1}'.format(id, self.__class__.__name__)) - r = self._orig_acquire(*args, **kwargs) - r._resource_id = id - print('-{0} ACQUIRE {1}'.format(id, self.__class__.__name__)) - if not hasattr(r, 'acquired_by'): - r.acquired_by = [] - r.acquired_by.append(traceback.format_stack()) - return r - - def release(self, resource): # noqa - id = resource._resource_id - print('+{0} RELEASE {1}'.format(id, self.__class__.__name__)) - r = self._orig_release(resource) - print('-{0} RELEASE {1}'.format(id, self.__class__.__name__)) - self._next_resource_id -= 1 - return r - - -class ConnectionPool(Resource): - LimitExceeded = exceptions.ConnectionLimitExceeded - - def __init__(self, connection, limit=None, preload=None): - self.connection = connection - super(ConnectionPool, self).__init__(limit=limit, - preload=preload) - - def new(self): - return self.connection.clone() - - def release_resource(self, resource): - try: - resource._debug('released') - except AttributeError: - pass - - def close_resource(self, resource): - resource._close() - - def collect_resource(self, resource, socket_timeout=0.1): - return resource.collect(socket_timeout) - - @contextmanager - def acquire_channel(self, block=False): - with self.acquire(block=block) as connection: - yield connection, connection.default_channel - - def setup(self): - if self.limit: - for i in range(self.limit): - if i < self.preload: - conn = self.new() - conn.connect() - else: - conn = lazy(self.new) - self._resource.put_nowait(conn) - - def prepare(self, resource): - if callable(resource): - resource = resource() - resource._debug('acquired') - return resource - - -class ChannelPool(Resource): - LimitExceeded = exceptions.ChannelLimitExceeded - - def __init__(self, connection, limit=None, preload=None): - self.connection = connection - super(ChannelPool, self).__init__(limit=limit, - preload=preload) - - def new(self): - return lazy(self.connection.channel) - - def setup(self): - channel = self.new() - if self.limit: - for i in range(self.limit): - self._resource.put_nowait( - i < self.preload and channel() or lazy(channel)) - - def prepare(self, channel): - if callable(channel): - channel = channel() - return channel - - -def maybe_channel(channel): - """Return the default channel if argument is a connection instance, - otherwise just return the channel given.""" - if isinstance(channel, Connection): - return channel.default_channel - return channel - - -def is_connection(obj): - return isinstance(obj, Connection) diff --git a/awx/lib/site-packages/kombu/entity.py b/awx/lib/site-packages/kombu/entity.py deleted file mode 100644 index c27316c770..0000000000 --- a/awx/lib/site-packages/kombu/entity.py +++ /dev/null @@ -1,718 +0,0 @@ -""" -kombu.entity -================ - -Exchange and Queue declarations. - -""" -from __future__ import absolute_import - -from .abstract import MaybeChannelBound -from .exceptions import ContentDisallowed -from .serialization import prepare_accept_content - -TRANSIENT_DELIVERY_MODE = 1 -PERSISTENT_DELIVERY_MODE = 2 -DELIVERY_MODES = {'transient': TRANSIENT_DELIVERY_MODE, - 'persistent': PERSISTENT_DELIVERY_MODE} - -__all__ = ['Exchange', 'Queue', 'binding'] - - -def pretty_bindings(bindings): - return '[%s]' % (', '.join(map(str, bindings))) - - -class Exchange(MaybeChannelBound): - """An Exchange declaration. - - :keyword name: See :attr:`name`. - :keyword type: See :attr:`type`. - :keyword channel: See :attr:`channel`. - :keyword durable: See :attr:`durable`. - :keyword auto_delete: See :attr:`auto_delete`. - :keyword delivery_mode: See :attr:`delivery_mode`. - :keyword arguments: See :attr:`arguments`. - - .. attribute:: name - - Name of the exchange. Default is no name (the default exchange). - - .. attribute:: type - - *This description of AMQP exchange types was shamelessly stolen - from the blog post `AMQP in 10 minutes: Part 4`_ by - Rajith Attapattu. Reading this article is recommended if you're - new to amqp.* - - "AMQP defines four default exchange types (routing algorithms) that - covers most of the common messaging use cases. An AMQP broker can - also define additional exchange types, so see your broker - manual for more information about available exchange types. - - * `direct` (*default*) - - Direct match between the routing key in the message, and the - routing criteria used when a queue is bound to this exchange. - - * `topic` - - Wildcard match between the routing key and the routing pattern - specified in the exchange/queue binding. The routing key is - treated as zero or more words delimited by `"."` and - supports special wildcard characters. `"*"` matches a - single word and `"#"` matches zero or more words. - - * `fanout` - - Queues are bound to this exchange with no arguments. Hence any - message sent to this exchange will be forwarded to all queues - bound to this exchange. - - * `headers` - - Queues are bound to this exchange with a table of arguments - containing headers and values (optional). A special argument - named "x-match" determines the matching algorithm, where - `"all"` implies an `AND` (all pairs must match) and - `"any"` implies `OR` (at least one pair must match). - - :attr:`arguments` is used to specify the arguments. - - - .. _`AMQP in 10 minutes: Part 4`: - http://bit.ly/amqp-exchange-types - - .. attribute:: channel - - The channel the exchange is bound to (if bound). - - .. attribute:: durable - - Durable exchanges remain active when a server restarts. Non-durable - exchanges (transient exchanges) are purged when a server restarts. - Default is :const:`True`. - - .. attribute:: auto_delete - - If set, the exchange is deleted when all queues have finished - using it. Default is :const:`False`. - - .. attribute:: delivery_mode - - The default delivery mode used for messages. The value is an integer, - or alias string. - - * 1 or `"transient"` - - The message is transient. Which means it is stored in - memory only, and is lost if the server dies or restarts. - - * 2 or "persistent" (*default*) - The message is persistent. Which means the message is - stored both in-memory, and on disk, and therefore - preserved if the server dies or restarts. - - The default value is 2 (persistent). - - .. attribute:: arguments - - Additional arguments to specify when the exchange is declared. - - """ - TRANSIENT_DELIVERY_MODE = TRANSIENT_DELIVERY_MODE - PERSISTENT_DELIVERY_MODE = PERSISTENT_DELIVERY_MODE - - name = '' - type = 'direct' - durable = True - auto_delete = False - passive = False - delivery_mode = PERSISTENT_DELIVERY_MODE - - attrs = ( - ('name', None), - ('type', None), - ('arguments', None), - ('durable', bool), - ('passive', bool), - ('auto_delete', bool), - ('delivery_mode', lambda m: DELIVERY_MODES.get(m) or m), - ) - - def __init__(self, name='', type='', channel=None, **kwargs): - super(Exchange, self).__init__(**kwargs) - self.name = name or self.name - self.type = type or self.type - self.maybe_bind(channel) - - def __hash__(self): - return hash('E|%s' % (self.name, )) - - def declare(self, nowait=False, passive=None): - """Declare the exchange. - - Creates the exchange on the broker. - - :keyword nowait: If set the server will not respond, and a - response will not be waited for. Default is :const:`False`. - - """ - passive = self.passive if passive is None else passive - if self.name: - return self.channel.exchange_declare( - exchange=self.name, type=self.type, durable=self.durable, - auto_delete=self.auto_delete, arguments=self.arguments, - nowait=nowait, passive=passive, - ) - - def bind_to(self, exchange='', routing_key='', - arguments=None, nowait=False, **kwargs): - """Binds the exchange to another exchange. - - :keyword nowait: If set the server will not respond, and the call - will not block waiting for a response. Default is :const:`False`. - - """ - if isinstance(exchange, Exchange): - exchange = exchange.name - return self.channel.exchange_bind(destination=self.name, - source=exchange, - routing_key=routing_key, - nowait=nowait, - arguments=arguments) - - def unbind_from(self, source='', routing_key='', - nowait=False, arguments=None): - """Delete previously created exchange binding from the server.""" - if isinstance(source, Exchange): - source = source.name - return self.channel.exchange_unbind(destination=self.name, - source=source, - routing_key=routing_key, - nowait=nowait, - arguments=arguments) - - def Message(self, body, delivery_mode=None, priority=None, - content_type=None, content_encoding=None, - properties=None, headers=None): - """Create message instance to be sent with :meth:`publish`. - - :param body: Message body. - - :keyword delivery_mode: Set custom delivery mode. Defaults - to :attr:`delivery_mode`. - - :keyword priority: Message priority, 0 to 9. (currently not - supported by RabbitMQ). - - :keyword content_type: The messages content_type. If content_type - is set, no serialization occurs as it is assumed this is either - a binary object, or you've done your own serialization. - Leave blank if using built-in serialization as our library - properly sets content_type. - - :keyword content_encoding: The character set in which this object - is encoded. Use "binary" if sending in raw binary objects. - Leave blank if using built-in serialization as our library - properly sets content_encoding. - - :keyword properties: Message properties. - - :keyword headers: Message headers. - - """ - properties = {} if properties is None else properties - dm = delivery_mode or self.delivery_mode - properties['delivery_mode'] = \ - DELIVERY_MODES[dm] if (dm != 2 and dm != 1) else dm - return self.channel.prepare_message(body, - properties=properties, - priority=priority, - content_type=content_type, - content_encoding=content_encoding, - headers=headers) - - def publish(self, message, routing_key=None, mandatory=False, - immediate=False, exchange=None): - """Publish message. - - :param message: :meth:`Message` instance to publish. - :param routing_key: Routing key. - :param mandatory: Currently not supported. - :param immediate: Currently not supported. - - """ - exchange = exchange or self.name - return self.channel.basic_publish(message, - exchange=exchange, - routing_key=routing_key, - mandatory=mandatory, - immediate=immediate) - - def delete(self, if_unused=False, nowait=False): - """Delete the exchange declaration on server. - - :keyword if_unused: Delete only if the exchange has no bindings. - Default is :const:`False`. - - :keyword nowait: If set the server will not respond, and a - response will not be waited for. Default is :const:`False`. - - """ - return self.channel.exchange_delete(exchange=self.name, - if_unused=if_unused, - nowait=nowait) - - def binding(self, routing_key='', arguments=None, unbind_arguments=None): - return binding(self, routing_key, arguments, unbind_arguments) - - def __eq__(self, other): - if isinstance(other, Exchange): - return (self.name == other.name and - self.type == other.type and - self.arguments == other.arguments and - self.durable == other.durable and - self.auto_delete == other.auto_delete and - self.delivery_mode == other.delivery_mode) - return NotImplemented - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - return super(Exchange, self).__repr__(str(self)) - - def __str__(self): - return 'Exchange %s(%s)' % (self.name or repr(''), self.type) - - @property - def can_cache_declaration(self): - return not self.auto_delete - - -class binding(object): - """Represents a queue or exchange binding. - - :keyword exchange: Exchange to bind to. - :keyword routing_key: Routing key used as binding key. - :keyword arguments: Arguments for bind operation. - :keyword unbind_arguments: Arguments for unbind operation. - - """ - - def __init__(self, exchange=None, routing_key='', - arguments=None, unbind_arguments=None): - self.exchange = exchange - self.routing_key = routing_key - self.arguments = arguments - self.unbind_arguments = unbind_arguments - - def declare(self, channel, nowait=False): - """Declare destination exchange.""" - if self.exchange and self.exchange.name: - ex = self.exchange(channel) - ex.declare(nowait=nowait) - - def bind(self, entity, nowait=False): - """Bind entity to this binding.""" - entity.bind_to(exchange=self.exchange, - routing_key=self.routing_key, - arguments=self.arguments, - nowait=nowait) - - def unbind(self, entity, nowait=False): - """Unbind entity from this binding.""" - entity.unbind_from(self.exchange, - routing_key=self.routing_key, - arguments=self.unbind_arguments, - nowait=nowait) - - def __repr__(self): - return '<binding: %s>' % (self, ) - - def __str__(self): - return '%s->%s' % (self.exchange.name, self.routing_key) - - -class Queue(MaybeChannelBound): - """A Queue declaration. - - :keyword name: See :attr:`name`. - :keyword exchange: See :attr:`exchange`. - :keyword routing_key: See :attr:`routing_key`. - :keyword channel: See :attr:`channel`. - :keyword durable: See :attr:`durable`. - :keyword exclusive: See :attr:`exclusive`. - :keyword auto_delete: See :attr:`auto_delete`. - :keyword queue_arguments: See :attr:`queue_arguments`. - :keyword binding_arguments: See :attr:`binding_arguments`. - :keyword on_declared: See :attr:`on_declared` - - .. attribute:: name - - Name of the queue. Default is no name (default queue destination). - - .. attribute:: exchange - - The :class:`Exchange` the queue binds to. - - .. attribute:: routing_key - - The routing key (if any), also called *binding key*. - - The interpretation of the routing key depends on - the :attr:`Exchange.type`. - - * direct exchange - - Matches if the routing key property of the message and - the :attr:`routing_key` attribute are identical. - - * fanout exchange - - Always matches, even if the binding does not have a key. - - * topic exchange - - Matches the routing key property of the message by a primitive - pattern matching scheme. The message routing key then consists - of words separated by dots (`"."`, like domain names), and - two special characters are available; star (`"*"`) and hash - (`"#"`). The star matches any word, and the hash matches - zero or more words. For example `"*.stock.#"` matches the - routing keys `"usd.stock"` and `"eur.stock.db"` but not - `"stock.nasdaq"`. - - .. attribute:: channel - - The channel the Queue is bound to (if bound). - - .. attribute:: durable - - Durable queues remain active when a server restarts. - Non-durable queues (transient queues) are purged if/when - a server restarts. - Note that durable queues do not necessarily hold persistent - messages, although it does not make sense to send - persistent messages to a transient queue. - - Default is :const:`True`. - - .. attribute:: exclusive - - Exclusive queues may only be consumed from by the - current connection. Setting the 'exclusive' flag - always implies 'auto-delete'. - - Default is :const:`False`. - - .. attribute:: auto_delete - - If set, the queue is deleted when all consumers have - finished using it. Last consumer can be cancelled - either explicitly or because its channel is closed. If - there was no consumer ever on the queue, it won't be - deleted. - - .. attribute:: queue_arguments - - Additional arguments used when declaring the queue. - - .. attribute:: binding_arguments - - Additional arguments used when binding the queue. - - .. attribute:: alias - - Unused in Kombu, but applications can take advantage of this. - For example to give alternate names to queues with automatically - generated queue names. - - .. attribute:: on_declared - - Optional callback to be applied when the queue has been - declared (the ``queue_declare`` operation is complete). - This must be a function with a signature that accepts at least 3 - positional arguments: ``(name, messages, consumers)``. - - """ - ContentDisallowed = ContentDisallowed - - name = '' - exchange = Exchange('') - routing_key = '' - - durable = True - exclusive = False - auto_delete = False - no_ack = False - - attrs = ( - ('name', None), - ('exchange', None), - ('routing_key', None), - ('queue_arguments', None), - ('binding_arguments', None), - ('durable', bool), - ('exclusive', bool), - ('auto_delete', bool), - ('no_ack', None), - ('alias', None), - ('bindings', list), - ) - - def __init__(self, name='', exchange=None, routing_key='', - channel=None, bindings=None, on_declared=None, - **kwargs): - super(Queue, self).__init__(**kwargs) - self.name = name or self.name - self.exchange = exchange or self.exchange - self.routing_key = routing_key or self.routing_key - self.bindings = set(bindings or []) - self.on_declared = on_declared - - # allows Queue('name', [binding(...), binding(...), ...]) - if isinstance(exchange, (list, tuple, set)): - self.bindings |= set(exchange) - if self.bindings: - self.exchange = None - - # exclusive implies auto-delete. - if self.exclusive: - self.auto_delete = True - self.maybe_bind(channel) - - def bind(self, channel): - on_declared = self.on_declared - bound = super(Queue, self).bind(channel) - bound.on_declared = on_declared - return bound - - def __hash__(self): - return hash('Q|%s' % (self.name, )) - - def when_bound(self): - if self.exchange: - self.exchange = self.exchange(self.channel) - - def declare(self, nowait=False): - """Declares the queue, the exchange and binds the queue to - the exchange.""" - # - declare main binding. - if self.exchange: - self.exchange.declare(nowait) - self.queue_declare(nowait, passive=False) - - if self.exchange and self.exchange.name: - self.queue_bind(nowait) - - # - declare extra/multi-bindings. - for B in self.bindings: - B.declare(self.channel) - B.bind(self, nowait=nowait) - return self.name - - def queue_declare(self, nowait=False, passive=False): - """Declare queue on the server. - - :keyword nowait: Do not wait for a reply. - :keyword passive: If set, the server will not create the queue. - The client can use this to check whether a queue exists - without modifying the server state. - - """ - ret = self.channel.queue_declare(queue=self.name, - passive=passive, - durable=self.durable, - exclusive=self.exclusive, - auto_delete=self.auto_delete, - arguments=self.queue_arguments, - nowait=nowait) - if not self.name: - self.name = ret[0] - if self.on_declared: - self.on_declared(*ret) - return ret - - def queue_bind(self, nowait=False): - """Create the queue binding on the server.""" - return self.bind_to(self.exchange, self.routing_key, - self.binding_arguments, nowait=nowait) - - def bind_to(self, exchange='', routing_key='', - arguments=None, nowait=False): - if isinstance(exchange, Exchange): - exchange = exchange.name - return self.channel.queue_bind(queue=self.name, - exchange=exchange, - routing_key=routing_key, - arguments=arguments, - nowait=nowait) - - def get(self, no_ack=None, accept=None): - """Poll the server for a new message. - - Must return the message if a message was available, - or :const:`None` otherwise. - - :keyword no_ack: If enabled the broker will automatically - ack messages. - :keyword accept: Custom list of accepted content types. - - This method provides direct access to the messages in a - queue using a synchronous dialogue, designed for - specific types of applications where synchronous functionality - is more important than performance. - - """ - no_ack = self.no_ack if no_ack is None else no_ack - message = self.channel.basic_get(queue=self.name, no_ack=no_ack) - if message is not None: - m2p = getattr(self.channel, 'message_to_python', None) - if m2p: - message = m2p(message) - if message.errors: - message._reraise_error() - message.accept = prepare_accept_content(accept) - return message - - def purge(self, nowait=False): - """Remove all ready messages from the queue.""" - return self.channel.queue_purge(queue=self.name, - nowait=nowait) or 0 - - def consume(self, consumer_tag='', callback=None, - no_ack=None, nowait=False): - """Start a queue consumer. - - Consumers last as long as the channel they were created on, or - until the client cancels them. - - :keyword consumer_tag: Unique identifier for the consumer. The - consumer tag is local to a connection, so two clients - can use the same consumer tags. If this field is empty - the server will generate a unique tag. - - :keyword no_ack: If enabled the broker will automatically ack - messages. - - :keyword nowait: Do not wait for a reply. - - :keyword callback: callback called for each delivered message - - """ - if no_ack is None: - no_ack = self.no_ack - return self.channel.basic_consume(queue=self.name, - no_ack=no_ack, - consumer_tag=consumer_tag or '', - callback=callback, - nowait=nowait) - - def cancel(self, consumer_tag): - """Cancel a consumer by consumer tag.""" - return self.channel.basic_cancel(consumer_tag) - - def delete(self, if_unused=False, if_empty=False, nowait=False): - """Delete the queue. - - :keyword if_unused: If set, the server will only delete the queue - if it has no consumers. A channel error will be raised - if the queue has consumers. - - :keyword if_empty: If set, the server will only delete the queue - if it is empty. If it is not empty a channel error will be raised. - - :keyword nowait: Do not wait for a reply. - - """ - return self.channel.queue_delete(queue=self.name, - if_unused=if_unused, - if_empty=if_empty, - nowait=nowait) - - def queue_unbind(self, arguments=None, nowait=False): - return self.unbind_from(self.exchange, self.routing_key, - arguments, nowait) - - def unbind_from(self, exchange='', routing_key='', - arguments=None, nowait=False): - """Unbind queue by deleting the binding from the server.""" - return self.channel.queue_unbind(queue=self.name, - exchange=exchange.name, - routing_key=routing_key, - arguments=arguments, - nowait=nowait) - - def __eq__(self, other): - if isinstance(other, Queue): - return (self.name == other.name and - self.exchange == other.exchange and - self.routing_key == other.routing_key and - self.queue_arguments == other.queue_arguments and - self.binding_arguments == other.binding_arguments and - self.durable == other.durable and - self.exclusive == other.exclusive and - self.auto_delete == other.auto_delete) - return NotImplemented - - def __ne__(self, other): - return not self.__eq__(other) - - def __repr__(self): - s = super(Queue, self).__repr__ - if self.bindings: - return s('Queue {0.name} -> {bindings}'.format( - self, bindings=pretty_bindings(self.bindings), - )) - return s( - 'Queue {0.name} -> {0.exchange!r} -> {0.routing_key}'.format( - self)) - - @property - def can_cache_declaration(self): - return not self.auto_delete - - @classmethod - def from_dict(self, queue, **options): - binding_key = options.get('binding_key') or options.get('routing_key') - - e_durable = options.get('exchange_durable') - if e_durable is None: - e_durable = options.get('durable') - - e_auto_delete = options.get('exchange_auto_delete') - if e_auto_delete is None: - e_auto_delete = options.get('auto_delete') - - q_durable = options.get('queue_durable') - if q_durable is None: - q_durable = options.get('durable') - - q_auto_delete = options.get('queue_auto_delete') - if q_auto_delete is None: - q_auto_delete = options.get('auto_delete') - - e_arguments = options.get('exchange_arguments') - q_arguments = options.get('queue_arguments') - b_arguments = options.get('binding_arguments') - bindings = options.get('bindings') - - exchange = Exchange(options.get('exchange'), - type=options.get('exchange_type'), - delivery_mode=options.get('delivery_mode'), - routing_key=options.get('routing_key'), - durable=e_durable, - auto_delete=e_auto_delete, - arguments=e_arguments) - return Queue(queue, - exchange=exchange, - routing_key=binding_key, - durable=q_durable, - exclusive=options.get('exclusive'), - auto_delete=q_auto_delete, - no_ack=options.get('no_ack'), - queue_arguments=q_arguments, - binding_arguments=b_arguments, - bindings=bindings) diff --git a/awx/lib/site-packages/kombu/exceptions.py b/awx/lib/site-packages/kombu/exceptions.py deleted file mode 100644 index 716bc693b0..0000000000 --- a/awx/lib/site-packages/kombu/exceptions.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -kombu.exceptions -================ - -Exceptions. - -""" -from __future__ import absolute_import - -import socket - -from amqp import ChannelError, ConnectionError, ResourceError - -__all__ = ['NotBoundError', 'MessageStateError', 'TimeoutError', - 'LimitExceeded', 'ConnectionLimitExceeded', - 'ChannelLimitExceeded', 'ConnectionError', 'ChannelError', - 'VersionMismatch', 'SerializerNotInstalled', 'ResourceError', - 'SerializationError', 'EncodeError', 'DecodeError'] - -TimeoutError = socket.timeout - - -class KombuError(Exception): - """Common subclass for all Kombu exceptions.""" - pass - - -class SerializationError(KombuError): - """Failed to serialize/deserialize content.""" - - -class EncodeError(SerializationError): - """Cannot encode object.""" - pass - - -class DecodeError(SerializationError): - """Cannot decode object.""" - - -class NotBoundError(KombuError): - """Trying to call channel dependent method on unbound entity.""" - pass - - -class MessageStateError(KombuError): - """The message has already been acknowledged.""" - pass - - -class LimitExceeded(KombuError): - """Limit exceeded.""" - pass - - -class ConnectionLimitExceeded(LimitExceeded): - """Maximum number of simultaneous connections exceeded.""" - pass - - -class ChannelLimitExceeded(LimitExceeded): - """Maximum number of simultaneous channels exceeded.""" - pass - - -class VersionMismatch(KombuError): - pass - - -class SerializerNotInstalled(KombuError): - """Support for the requested serialization type is not installed""" - pass - - -class ContentDisallowed(SerializerNotInstalled): - """Consumer does not allow this content-type.""" - pass - - -class InconsistencyError(ConnectionError): - """Data or environment has been found to be inconsistent, - depending on the cause it may be possible to retry the operation.""" - pass diff --git a/awx/lib/site-packages/kombu/five.py b/awx/lib/site-packages/kombu/five.py deleted file mode 100644 index 87abc09ca9..0000000000 --- a/awx/lib/site-packages/kombu/five.py +++ /dev/null @@ -1,203 +0,0 @@ -# -*- coding: utf-8 -*- -""" - celery.five - ~~~~~~~~~~~ - - Compatibility implementations of features - only available in newer Python versions. - - -""" -from __future__ import absolute_import - -# ############# py3k ######################################################### -import sys -PY3 = sys.version_info[0] == 3 - -try: - reload = reload # noqa -except NameError: # pragma: no cover - from imp import reload # noqa - -try: - from collections import UserList # noqa -except ImportError: # pragma: no cover - from UserList import UserList # noqa - -try: - from collections import UserDict # noqa -except ImportError: # pragma: no cover - from UserDict import UserDict # noqa - -try: - bytes_t = bytes -except NameError: # pragma: no cover - bytes_t = str # noqa - -# ############# time.monotonic ############################################### - -if sys.version_info < (3, 3): - - import platform - SYSTEM = platform.system() - - if SYSTEM == 'Darwin': - import ctypes - from ctypes.util import find_library - libSystem = ctypes.CDLL('libSystem.dylib') - CoreServices = ctypes.CDLL(find_library('CoreServices'), - use_errno=True) - mach_absolute_time = libSystem.mach_absolute_time - mach_absolute_time.restype = ctypes.c_uint64 - absolute_to_nanoseconds = CoreServices.AbsoluteToNanoseconds - absolute_to_nanoseconds.restype = ctypes.c_uint64 - absolute_to_nanoseconds.argtypes = [ctypes.c_uint64] - - def _monotonic(): - return absolute_to_nanoseconds(mach_absolute_time()) * 1e-9 - - elif SYSTEM == 'Linux': - # from stackoverflow: - # questions/1205722/how-do-i-get-monotonic-time-durations-in-python - import ctypes - import os - - CLOCK_MONOTONIC = 1 # see <linux/time.h> - - class timespec(ctypes.Structure): - _fields_ = [ - ('tv_sec', ctypes.c_long), - ('tv_nsec', ctypes.c_long), - ] - - librt = ctypes.CDLL('librt.so.1', use_errno=True) - clock_gettime = librt.clock_gettime - clock_gettime.argtypes = [ - ctypes.c_int, ctypes.POINTER(timespec), - ] - - def _monotonic(): # noqa - t = timespec() - if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0: - errno_ = ctypes.get_errno() - raise OSError(errno_, os.strerror(errno_)) - return t.tv_sec + t.tv_nsec * 1e-9 - else: - from time import time as _monotonic -try: - from time import monotonic -except ImportError: - monotonic = _monotonic # noqa - -# ############# Py3 <-> Py2 ################################################## - -if PY3: # pragma: no cover - import builtins - - from queue import Queue, Empty, Full, LifoQueue - from itertools import zip_longest - from io import StringIO, BytesIO - - map = map - zip = zip - string = str - string_t = str - long_t = int - text_t = str - range = range - module_name_t = str - - open_fqdn = 'builtins.open' - - def items(d): - return d.items() - - def keys(d): - return d.keys() - - def values(d): - return d.values() - - def nextfun(it): - return it.__next__ - - exec_ = getattr(builtins, 'exec') - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - class WhateverIO(StringIO): - - def write(self, data): - if isinstance(data, bytes): - data = data.encode() - StringIO.write(self, data) - -else: - import __builtin__ as builtins # noqa - from Queue import Queue, Empty, Full, LifoQueue # noqa - from itertools import ( # noqa - imap as map, - izip as zip, - izip_longest as zip_longest, - ) - try: - from cStringIO import StringIO # noqa - except ImportError: # pragma: no cover - from StringIO import StringIO # noqa - - string = unicode # noqa - string_t = basestring # noqa - text_t = unicode - long_t = long # noqa - range = xrange - module_name_t = str - - open_fqdn = '__builtin__.open' - - def items(d): # noqa - return d.iteritems() - - def keys(d): # noqa - return d.iterkeys() - - def values(d): # noqa - return d.itervalues() - - def nextfun(it): # noqa - return it.next - - def exec_(code, globs=None, locs=None): # pragma: no cover - """Execute code in a namespace.""" - if globs is None: - frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals - del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - - exec_("""def reraise(tp, value, tb=None): raise tp, value, tb""") - - BytesIO = WhateverIO = StringIO # noqa - - -def with_metaclass(Type, skip_attrs=set(['__dict__', '__weakref__'])): - """Class decorator to set metaclass. - - Works with both Python 3 and Python 3 and it does not add - an extra class in the lookup order like ``six.with_metaclass`` does - (that is -- it copies the original class instead of using inheritance). - - """ - - def _clone_with_metaclass(Class): - attrs = dict((key, value) for key, value in items(vars(Class)) - if key not in skip_attrs) - return Type(Class.__name__, Class.__bases__, attrs) - - return _clone_with_metaclass diff --git a/awx/lib/site-packages/kombu/log.py b/awx/lib/site-packages/kombu/log.py deleted file mode 100644 index 2a7db9bf50..0000000000 --- a/awx/lib/site-packages/kombu/log.py +++ /dev/null @@ -1,147 +0,0 @@ -from __future__ import absolute_import - -import logging -import numbers -import os -import sys - -from logging.handlers import WatchedFileHandler - -from .five import string_t -from .utils import cached_property -from .utils.encoding import safe_repr, safe_str -from .utils.functional import maybe_evaluate - -__all__ = ['LogMixin', 'LOG_LEVELS', 'get_loglevel', 'setup_logging'] - -try: - LOG_LEVELS = dict(logging._nameToLevel) - LOG_LEVELS.update(logging._levelToName) -except AttributeError: - LOG_LEVELS = dict(logging._levelNames) -LOG_LEVELS.setdefault('FATAL', logging.FATAL) -LOG_LEVELS.setdefault(logging.FATAL, 'FATAL') -DISABLE_TRACEBACKS = os.environ.get('DISABLE_TRACEBACKS') - - -class NullHandler(logging.Handler): - - def emit(self, record): - pass - - -def get_logger(logger): - if isinstance(logger, string_t): - logger = logging.getLogger(logger) - if not logger.handlers: - logger.addHandler(NullHandler()) - return logger - - -def get_loglevel(level): - if isinstance(level, string_t): - return LOG_LEVELS[level] - return level - - -def naive_format_parts(fmt): - parts = fmt.split('%') - for i, e in enumerate(parts[1:]): - yield None if not e or not parts[i - 1] else e[0] - - -def safeify_format(fmt, args, - filters={'s': safe_str, - 'r': safe_repr}): - for index, type in enumerate(naive_format_parts(fmt)): - filt = filters.get(type) - yield filt(args[index]) if filt else args[index] - - -class LogMixin(object): - - def debug(self, *args, **kwargs): - return self.log(logging.DEBUG, *args, **kwargs) - - def info(self, *args, **kwargs): - return self.log(logging.INFO, *args, **kwargs) - - def warn(self, *args, **kwargs): - return self.log(logging.WARN, *args, **kwargs) - - def error(self, *args, **kwargs): - return self._error(logging.ERROR, *args, **kwargs) - - def critical(self, *args, **kwargs): - return self._error(logging.CRITICAL, *args, **kwargs) - - def _error(self, severity, *args, **kwargs): - kwargs.setdefault('exc_info', True) - if DISABLE_TRACEBACKS: - kwargs.pop('exc_info', None) - return self.log(severity, *args, **kwargs) - - def annotate(self, text): - return '%s - %s' % (self.logger_name, text) - - def log(self, severity, *args, **kwargs): - if self.logger.isEnabledFor(severity): - log = self.logger.log - if len(args) > 1 and isinstance(args[0], string_t): - expand = [maybe_evaluate(arg) for arg in args[1:]] - return log(severity, - self.annotate(args[0].replace('%r', '%s')), - *list(safeify_format(args[0], expand)), **kwargs) - else: - return self.logger.log( - severity, self.annotate(' '.join(map(safe_str, args))), - **kwargs) - - def get_logger(self): - return get_logger(self.logger_name) - - def is_enabled_for(self, level): - return self.logger.isEnabledFor(self.get_loglevel(level)) - - def get_loglevel(self, level): - if not isinstance(level, numbers.Integral): - return LOG_LEVELS[level] - return level - - @cached_property - def logger(self): - return self.get_logger() - - @property - def logger_name(self): - return self.__class__.__name__ - - -class Log(LogMixin): - - def __init__(self, name, logger=None): - self._logger_name = name - self._logger = logger - - def get_logger(self): - if self._logger: - return self._logger - return LogMixin.get_logger(self) - - @property - def logger_name(self): - return self._logger_name - - -def setup_logging(loglevel=None, logfile=None): - logger = logging.getLogger() - loglevel = get_loglevel(loglevel or 'ERROR') - logfile = logfile if logfile else sys.__stderr__ - if not logger.handlers: - if hasattr(logfile, 'write'): - handler = logging.StreamHandler(logfile) - else: - handler = WatchedFileHandler(logfile) - logger.addHandler(handler) - logger.setLevel(loglevel) - return logger diff --git a/awx/lib/site-packages/kombu/message.py b/awx/lib/site-packages/kombu/message.py deleted file mode 100644 index 5f7ae52514..0000000000 --- a/awx/lib/site-packages/kombu/message.py +++ /dev/null @@ -1,154 +0,0 @@ -""" -kombu.transport.message -======================= - -Message class. - -""" -from __future__ import absolute_import - -import sys - -from .compression import decompress -from .exceptions import MessageStateError -from .five import reraise, text_t -from .serialization import loads - -ACK_STATES = frozenset(['ACK', 'REJECTED', 'REQUEUED']) - - -class Message(object): - """Base class for received messages.""" - __slots__ = ('_state', 'channel', 'delivery_tag', - 'content_type', 'content_encoding', - 'delivery_info', 'headers', 'properties', - 'body', '_decoded_cache', 'accept', '__dict__') - MessageStateError = MessageStateError - - errors = None - - def __init__(self, channel, body=None, delivery_tag=None, - content_type=None, content_encoding=None, delivery_info={}, - properties=None, headers=None, postencode=None, - accept=None, **kwargs): - self.errors = [] if self.errors is None else self.errors - self.channel = channel - self.delivery_tag = delivery_tag - self.content_type = content_type - self.content_encoding = content_encoding - self.delivery_info = delivery_info - self.headers = headers or {} - self.properties = properties or {} - self._decoded_cache = None - self._state = 'RECEIVED' - self.accept = accept - - compression = self.headers.get('compression') - if not self.errors and compression: - try: - body = decompress(body, compression) - except Exception: - self.errors.append(sys.exc_info()) - - if not self.errors and postencode and isinstance(body, text_t): - try: - body = body.encode(postencode) - except Exception: - self.errors.append(sys.exc_info()) - self.body = body - - def _reraise_error(self, callback=None): - try: - reraise(*self.errors[0]) - except Exception as exc: - if not callback: - raise - callback(self, exc) - - def ack(self): - """Acknowledge this message as being processed., - This will remove the message from the queue. - - :raises MessageStateError: If the message has already been - acknowledged/requeued/rejected. - - """ - if self.channel.no_ack_consumers is not None: - try: - consumer_tag = self.delivery_info['consumer_tag'] - except KeyError: - pass - else: - if consumer_tag in self.channel.no_ack_consumers: - return - if self.acknowledged: - raise self.MessageStateError( - 'Message already acknowledged with state: {0._state}'.format( - self)) - self.channel.basic_ack(self.delivery_tag) - self._state = 'ACK' - - def ack_log_error(self, logger, errors): - try: - self.ack() - except errors as exc: - logger.critical("Couldn't ack %r, reason:%r", - self.delivery_tag, exc, exc_info=True) - - def reject_log_error(self, logger, errors, requeue=False): - try: - self.reject(requeue=requeue) - except errors as exc: - logger.critical("Couldn't reject %r, reason: %r", - self.delivery_tag, exc, exc_info=True) - - def reject(self, requeue=False): - """Reject this message. - - The message will be discarded by the server. - - :raises MessageStateError: If the message has already been - acknowledged/requeued/rejected. - - """ - if self.acknowledged: - raise self.MessageStateError( - 'Message already acknowledged with state: {0._state}'.format( - self)) - self.channel.basic_reject(self.delivery_tag, requeue=requeue) - self._state = 'REJECTED' - - def requeue(self): - """Reject this message and put it back on the queue. - - You must not use this method as a means of selecting messages - to process. - - :raises MessageStateError: If the message has already been - acknowledged/requeued/rejected. - - """ - if self.acknowledged: - raise self.MessageStateError( - 'Message already acknowledged with state: {0._state}'.format( - self)) - self.channel.basic_reject(self.delivery_tag, requeue=True) - self._state = 'REQUEUED' - - def decode(self): - """Deserialize the message body, returning the original - python structure sent by the publisher.""" - return loads(self.body, self.content_type, - self.content_encoding, accept=self.accept) - - @property - def acknowledged(self): - """Set to true if the message has been acknowledged.""" - return self._state in ACK_STATES - - @property - def payload(self): - """The decoded message body.""" - if not self._decoded_cache: - self._decoded_cache = self.decode() - return self._decoded_cache diff --git a/awx/lib/site-packages/kombu/messaging.py b/awx/lib/site-packages/kombu/messaging.py deleted file mode 100644 index 8b92395088..0000000000 --- a/awx/lib/site-packages/kombu/messaging.py +++ /dev/null @@ -1,602 +0,0 @@ -""" -kombu.messaging -=============== - -Sending and receiving messages. - -""" -from __future__ import absolute_import - -import numbers - -from itertools import count - -from .common import maybe_declare -from .compression import compress -from .connection import maybe_channel, is_connection -from .entity import Exchange, Queue, DELIVERY_MODES -from .exceptions import ContentDisallowed -from .five import text_t, values -from .serialization import dumps, prepare_accept_content -from .utils import ChannelPromise, maybe_list - -__all__ = ['Exchange', 'Queue', 'Producer', 'Consumer'] - - -class Producer(object): - """Message Producer. - - :param channel: Connection or channel. - :keyword exchange: Optional default exchange. - :keyword routing_key: Optional default routing key. - :keyword serializer: Default serializer. Default is `"json"`. - :keyword compression: Default compression method. Default is no - compression. - :keyword auto_declare: Automatically declare the default exchange - at instantiation. Default is :const:`True`. - :keyword on_return: Callback to call for undeliverable messages, - when the `mandatory` or `immediate` arguments to - :meth:`publish` is used. This callback needs the following - signature: `(exception, exchange, routing_key, message)`. - Note that the producer needs to drain events to use this feature. - - """ - - #: Default exchange - exchange = None - - #: Default routing key. - routing_key = '' - - #: Default serializer to use. Default is JSON. - serializer = None - - #: Default compression method. Disabled by default. - compression = None - - #: By default the exchange is declared at instantiation. - #: If you want to declare manually then you can set this - #: to :const:`False`. - auto_declare = True - - #: Basic return callback. - on_return = None - - #: Set if channel argument was a Connection instance (using - #: default_channel). - __connection__ = None - - def __init__(self, channel, exchange=None, routing_key=None, - serializer=None, auto_declare=None, compression=None, - on_return=None): - self._channel = channel - self.exchange = exchange - self.routing_key = routing_key or self.routing_key - self.serializer = serializer or self.serializer - self.compression = compression or self.compression - self.on_return = on_return or self.on_return - self._channel_promise = None - if self.exchange is None: - self.exchange = Exchange('') - if auto_declare is not None: - self.auto_declare = auto_declare - - if self._channel: - self.revive(self._channel) - - def __repr__(self): - return '<Producer: {0._channel}>'.format(self) - - def __reduce__(self): - return self.__class__, self.__reduce_args__() - - def __reduce_args__(self): - return (None, self.exchange, self.routing_key, self.serializer, - self.auto_declare, self.compression) - - def declare(self): - """Declare the exchange. - - This happens automatically at instantiation if - :attr:`auto_declare` is enabled. - - """ - if self.exchange.name: - self.exchange.declare() - - def maybe_declare(self, entity, retry=False, **retry_policy): - """Declare the exchange if it hasn't already been declared - during this session.""" - if entity: - return maybe_declare(entity, self.channel, retry, **retry_policy) - - def publish(self, body, routing_key=None, delivery_mode=None, - mandatory=False, immediate=False, priority=0, - content_type=None, content_encoding=None, serializer=None, - headers=None, compression=None, exchange=None, retry=False, - retry_policy=None, declare=[], **properties): - """Publish message to the specified exchange. - - :param body: Message body. - :keyword routing_key: Message routing key. - :keyword delivery_mode: See :attr:`delivery_mode`. - :keyword mandatory: Currently not supported. - :keyword immediate: Currently not supported. - :keyword priority: Message priority. A number between 0 and 9. - :keyword content_type: Content type. Default is auto-detect. - :keyword content_encoding: Content encoding. Default is auto-detect. - :keyword serializer: Serializer to use. Default is auto-detect. - :keyword compression: Compression method to use. Default is none. - :keyword headers: Mapping of arbitrary headers to pass along - with the message body. - :keyword exchange: Override the exchange. Note that this exchange - must have been declared. - :keyword declare: Optional list of required entities that must - have been declared before publishing the message. The entities - will be declared using :func:`~kombu.common.maybe_declare`. - :keyword retry: Retry publishing, or declaring entities if the - connection is lost. - :keyword retry_policy: Retry configuration, this is the keywords - supported by :meth:`~kombu.Connection.ensure`. - :keyword \*\*properties: Additional message properties, see AMQP spec. - - """ - headers = {} if headers is None else headers - retry_policy = {} if retry_policy is None else retry_policy - routing_key = self.routing_key if routing_key is None else routing_key - compression = self.compression if compression is None else compression - exchange = exchange or self.exchange - - if isinstance(exchange, Exchange): - delivery_mode = delivery_mode or exchange.delivery_mode - exchange = exchange.name - else: - delivery_mode = delivery_mode or self.exchange.delivery_mode - if not isinstance(delivery_mode, numbers.Integral): - delivery_mode = DELIVERY_MODES[delivery_mode] - properties['delivery_mode'] = delivery_mode - - body, content_type, content_encoding = self._prepare( - body, serializer, content_type, content_encoding, - compression, headers) - - publish = self._publish - if retry: - publish = self.connection.ensure(self, publish, **retry_policy) - return publish(body, priority, content_type, - content_encoding, headers, properties, - routing_key, mandatory, immediate, exchange, declare) - - def _publish(self, body, priority, content_type, content_encoding, - headers, properties, routing_key, mandatory, - immediate, exchange, declare): - channel = self.channel - message = channel.prepare_message( - body, priority, content_type, - content_encoding, headers, properties, - ) - if declare: - maybe_declare = self.maybe_declare - [maybe_declare(entity) for entity in declare] - return channel.basic_publish( - message, - exchange=exchange, routing_key=routing_key, - mandatory=mandatory, immediate=immediate, - ) - - def _get_channel(self): - channel = self._channel - if isinstance(channel, ChannelPromise): - channel = self._channel = channel() - self.exchange.revive(channel) - if self.on_return: - channel.events['basic_return'].add(self.on_return) - return channel - - def _set_channel(self, channel): - self._channel = channel - channel = property(_get_channel, _set_channel) - - def revive(self, channel): - """Revive the producer after connection loss.""" - if is_connection(channel): - connection = channel - self.__connection__ = connection - channel = ChannelPromise(lambda: connection.default_channel) - if isinstance(channel, ChannelPromise): - self._channel = channel - self.exchange = self.exchange(channel) - else: - # Channel already concrete - self._channel = channel - if self.on_return: - self._channel.events['basic_return'].add(self.on_return) - self.exchange = self.exchange(channel) - if self.auto_declare: - # auto_decare is not recommended as this will force - # evaluation of the channel. - self.declare() - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.release() - - def release(self): - pass - close = release - - def _prepare(self, body, serializer=None, content_type=None, - content_encoding=None, compression=None, headers=None): - - # No content_type? Then we're serializing the data internally. - if not content_type: - serializer = serializer or self.serializer - (content_type, content_encoding, - body) = dumps(body, serializer=serializer) - else: - # If the programmer doesn't want us to serialize, - # make sure content_encoding is set. - if isinstance(body, text_t): - if not content_encoding: - content_encoding = 'utf-8' - body = body.encode(content_encoding) - - # If they passed in a string, we can't know anything - # about it. So assume it's binary data. - elif not content_encoding: - content_encoding = 'binary' - - if compression: - body, headers['compression'] = compress(body, compression) - - return body, content_type, content_encoding - - @property - def connection(self): - try: - return self.__connection__ or self.channel.connection.client - except AttributeError: - pass - - -class Consumer(object): - """Message consumer. - - :param channel: see :attr:`channel`. - :param queues: see :attr:`queues`. - :keyword no_ack: see :attr:`no_ack`. - :keyword auto_declare: see :attr:`auto_declare` - :keyword callbacks: see :attr:`callbacks`. - :keyword on_message: See :attr:`on_message` - :keyword on_decode_error: see :attr:`on_decode_error`. - - """ - ContentDisallowed = ContentDisallowed - - #: The connection/channel to use for this consumer. - channel = None - - #: A single :class:`~kombu.Queue`, or a list of queues to - #: consume from. - queues = None - - #: Flag for automatic message acknowledgment. - #: If enabled the messages are automatically acknowledged by the - #: broker. This can increase performance but means that you - #: have no control of when the message is removed. - #: - #: Disabled by default. - no_ack = None - - #: By default all entities will be declared at instantiation, if you - #: want to handle this manually you can set this to :const:`False`. - auto_declare = True - - #: List of callbacks called in order when a message is received. - #: - #: The signature of the callbacks must take two arguments: - #: `(body, message)`, which is the decoded message body and - #: the `Message` instance (a subclass of - #: :class:`~kombu.transport.base.Message`). - callbacks = None - - #: Optional function called whenever a message is received. - #: - #: When defined this function will be called instead of the - #: :meth:`receive` method, and :attr:`callbacks` will be disabled. - #: - #: So this can be used as an alternative to :attr:`callbacks` when - #: you don't want the body to be automatically decoded. - #: Note that the message will still be decompressed if the message - #: has the ``compression`` header set. - #: - #: The signature of the callback must take a single argument, - #: which is the raw message object (a subclass of - #: :class:`~kombu.transport.base.Message`). - #: - #: Also note that the ``message.body`` attribute, which is the raw - #: contents of the message body, may in some cases be a read-only - #: :class:`buffer` object. - on_message = None - - #: Callback called when a message can't be decoded. - #: - #: The signature of the callback must take two arguments: `(message, - #: exc)`, which is the message that can't be decoded and the exception - #: that occurred while trying to decode it. - on_decode_error = None - - #: List of accepted content-types. - #: - #: An exception will be raised if the consumer receives - #: a message with an untrusted content type. - #: By default all content-types are accepted, but not if - #: :func:`kombu.disable_untrusted_serializers` was called, - #: in which case only json is allowed. - accept = None - - _tags = count(1) # global - - def __init__(self, channel, queues=None, no_ack=None, auto_declare=None, - callbacks=None, on_decode_error=None, on_message=None, - accept=None): - self.channel = channel - self.queues = self.queues or [] if queues is None else queues - self.no_ack = self.no_ack if no_ack is None else no_ack - self.callbacks = (self.callbacks or [] if callbacks is None - else callbacks) - self.on_message = on_message - self._active_tags = {} - if auto_declare is not None: - self.auto_declare = auto_declare - if on_decode_error is not None: - self.on_decode_error = on_decode_error - self.accept = prepare_accept_content(accept) - - if self.channel: - self.revive(self.channel) - - def revive(self, channel): - """Revive consumer after connection loss.""" - self._active_tags.clear() - channel = self.channel = maybe_channel(channel) - self.queues = [queue(self.channel) - for queue in maybe_list(self.queues)] - for queue in self.queues: - queue.revive(channel) - - if self.auto_declare: - self.declare() - - def declare(self): - """Declare queues, exchanges and bindings. - - This is done automatically at instantiation if :attr:`auto_declare` - is set. - - """ - for queue in self.queues: - queue.declare() - - def register_callback(self, callback): - """Register a new callback to be called when a message - is received. - - The signature of the callback needs to accept two arguments: - `(body, message)`, which is the decoded message body - and the `Message` instance (a subclass of - :class:`~kombu.transport.base.Message`. - - """ - self.callbacks.append(callback) - - def __enter__(self): - self.consume() - return self - - def __exit__(self, *exc_info): - try: - self.cancel() - except Exception: - pass - - def add_queue(self, queue): - """Add a queue to the list of queues to consume from. - - This will not start consuming from the queue, - for that you will have to call :meth:`consume` after. - - """ - queue = queue(self.channel) - if self.auto_declare: - queue.declare() - self.queues.append(queue) - return queue - - def add_queue_from_dict(self, queue, **options): - """This method is deprecated. - - Instead please use:: - - consumer.add_queue(Queue.from_dict(d)) - - """ - return self.add_queue(Queue.from_dict(queue, **options)) - - def consume(self, no_ack=None): - """Start consuming messages. - - Can be called multiple times, but note that while it - will consume from new queues added since the last call, - it will not cancel consuming from removed queues ( - use :meth:`cancel_by_queue`). - - :param no_ack: See :attr:`no_ack`. - - """ - if self.queues: - no_ack = self.no_ack if no_ack is None else no_ack - - H, T = self.queues[:-1], self.queues[-1] - for queue in H: - self._basic_consume(queue, no_ack=no_ack, nowait=True) - self._basic_consume(T, no_ack=no_ack, nowait=False) - - def cancel(self): - """End all active queue consumers. - - This does not affect already delivered messages, but it does - mean the server will not send any more messages for this consumer. - - """ - cancel = self.channel.basic_cancel - for tag in values(self._active_tags): - cancel(tag) - self._active_tags.clear() - close = cancel - - def cancel_by_queue(self, queue): - """Cancel consumer by queue name.""" - try: - tag = self._active_tags.pop(queue) - except KeyError: - pass - else: - self.queues[:] = [q for q in self.queues if q.name != queue] - self.channel.basic_cancel(tag) - - def consuming_from(self, queue): - """Return :const:`True` if the consumer is currently - consuming from queue'.""" - name = queue - if isinstance(queue, Queue): - name = queue.name - return name in self._active_tags - - def purge(self): - """Purge messages from all queues. - - .. warning:: - This will *delete all ready messages*, there is no - undo operation. - - """ - return sum(queue.purge() for queue in self.queues) - - def flow(self, active): - """Enable/disable flow from peer. - - This is a simple flow-control mechanism that a peer can use - to avoid overflowing its queues or otherwise finding itself - receiving more messages than it can process. - - The peer that receives a request to stop sending content - will finish sending the current content (if any), and then wait - until flow is reactivated. - - """ - self.channel.flow(active) - - def qos(self, prefetch_size=0, prefetch_count=0, apply_global=False): - """Specify quality of service. - - The client can request that messages should be sent in - advance so that when the client finishes processing a message, - the following message is already held locally, rather than needing - to be sent down the channel. Prefetching gives a performance - improvement. - - The prefetch window is Ignored if the :attr:`no_ack` option is set. - - :param prefetch_size: Specify the prefetch window in octets. - The server will send a message in advance if it is equal to - or smaller in size than the available prefetch size (and - also falls within other prefetch limits). May be set to zero, - meaning "no specific limit", although other prefetch limits - may still apply. - - :param prefetch_count: Specify the prefetch window in terms of - whole messages. - - :param apply_global: Apply new settings globally on all channels. - - """ - return self.channel.basic_qos(prefetch_size, - prefetch_count, - apply_global) - - def recover(self, requeue=False): - """Redeliver unacknowledged messages. - - Asks the broker to redeliver all unacknowledged messages - on the specified channel. - - :keyword requeue: By default the messages will be redelivered - to the original recipient. With `requeue` set to true, the - server will attempt to requeue the message, potentially then - delivering it to an alternative subscriber. - - """ - return self.channel.basic_recover(requeue=requeue) - - def receive(self, body, message): - """Method called when a message is received. - - This dispatches to the registered :attr:`callbacks`. - - :param body: The decoded message body. - :param message: The `Message` instance. - - :raises NotImplementedError: If no consumer callbacks have been - registered. - - """ - callbacks = self.callbacks - if not callbacks: - raise NotImplementedError('Consumer does not have any callbacks') - [callback(body, message) for callback in callbacks] - - def _basic_consume(self, queue, consumer_tag=None, - no_ack=no_ack, nowait=True): - tag = self._active_tags.get(queue.name) - if tag is None: - tag = self._add_tag(queue, consumer_tag) - queue.consume(tag, self._receive_callback, - no_ack=no_ack, nowait=nowait) - return tag - - def _add_tag(self, queue, consumer_tag=None): - tag = consumer_tag or str(next(self._tags)) - self._active_tags[queue.name] = tag - return tag - - def _receive_callback(self, message): - accept = self.accept - on_m, channel, decoded = self.on_message, self.channel, None - try: - m2p = getattr(channel, 'message_to_python', None) - if m2p: - message = m2p(message) - if accept is not None: - message.accept = accept - if message.errors: - return message._reraise_error(self.on_decode_error) - decoded = None if on_m else message.decode() - except Exception as exc: - if not self.on_decode_error: - raise - self.on_decode_error(message, exc) - else: - return on_m(message) if on_m else self.receive(decoded, message) - - def __repr__(self): - return '<Consumer: {0.queues}>'.format(self) - - @property - def connection(self): - try: - return self.channel.connection.client - except AttributeError: - pass diff --git a/awx/lib/site-packages/kombu/mixins.py b/awx/lib/site-packages/kombu/mixins.py deleted file mode 100644 index 081ae5801e..0000000000 --- a/awx/lib/site-packages/kombu/mixins.py +++ /dev/null @@ -1,251 +0,0 @@ -# -*- coding: utf-8 -*- -""" -kombu.mixins -============ - -Useful mixin classes. - -""" -from __future__ import absolute_import - -import socket - -from contextlib import contextmanager -from functools import partial -from itertools import count -from time import sleep - -from .common import ignore_errors -from .five import range -from .messaging import Consumer -from .log import get_logger -from .utils import cached_property, nested -from .utils.encoding import safe_repr -from .utils.limits import TokenBucket - -__all__ = ['ConsumerMixin'] - -logger = get_logger(__name__) -debug, info, warn, error = logger.debug, logger.info, logger.warn, logger.error - - -class ConsumerMixin(object): - """Convenience mixin for implementing consumer programs. - - It can be used outside of threads, with threads, or greenthreads - (eventlet/gevent) too. - - The basic class would need a :attr:`connection` attribute - which must be a :class:`~kombu.Connection` instance, - and define a :meth:`get_consumers` method that returns a list - of :class:`kombu.Consumer` instances to use. - Supporting multiple consumers is important so that multiple - channels can be used for different QoS requirements. - - **Example**: - - .. code-block:: python - - - class Worker(ConsumerMixin): - task_queue = Queue('tasks', Exchange('tasks'), 'tasks')) - - def __init__(self, connection): - self.connection = None - - def get_consumers(self, Consumer, channel): - return [Consumer(queues=[self.task_queue], - callback=[self.on_task])] - - def on_task(self, body, message): - print('Got task: {0!r}'.format(body)) - message.ack() - - **Additional handler methods**: - - * :meth:`extra_context` - - Optional extra context manager that will be entered - after the connection and consumers have been set up. - - Takes arguments ``(connection, channel)``. - - * :meth:`on_connection_error` - - Handler called if the connection is lost/ or - is unavailable. - - Takes arguments ``(exc, interval)``, where interval - is the time in seconds when the connection will be retried. - - The default handler will log the exception. - - * :meth:`on_connection_revived` - - Handler called as soon as the connection is re-established - after connection failure. - - Takes no arguments. - - * :meth:`on_consume_ready` - - Handler called when the consumer is ready to accept - messages. - - Takes arguments ``(connection, channel, consumers)``. - Also keyword arguments to ``consume`` are forwarded - to this handler. - - * :meth:`on_consume_end` - - Handler called after the consumers are cancelled. - Takes arguments ``(connection, channel)``. - - * :meth:`on_iteration` - - Handler called for every iteration while draining - events. - - Takes no arguments. - - * :meth:`on_decode_error` - - Handler called if a consumer was unable to decode - the body of a message. - - Takes arguments ``(message, exc)`` where message is the - original message object. - - The default handler will log the error and - acknowledge the message, so if you override make - sure to call super, or perform these steps yourself. - - """ - - #: maximum number of retries trying to re-establish the connection, - #: if the connection is lost/unavailable. - connect_max_retries = None - - #: When this is set to true the consumer should stop consuming - #: and return, so that it can be joined if it is the implementation - #: of a thread. - should_stop = False - - def get_consumers(self, Consumer, channel): - raise NotImplementedError('Subclass responsibility') - - def on_connection_revived(self): - pass - - def on_consume_ready(self, connection, channel, consumers, **kwargs): - pass - - def on_consume_end(self, connection, channel): - pass - - def on_iteration(self): - pass - - def on_decode_error(self, message, exc): - error("Can't decode message body: %r (type:%r encoding:%r raw:%r')", - exc, message.content_type, message.content_encoding, - safe_repr(message.body)) - message.ack() - - def on_connection_error(self, exc, interval): - warn('Broker connection error: %r. ' - 'Trying again in %s seconds.', exc, interval) - - @contextmanager - def extra_context(self, connection, channel): - yield - - def run(self, _tokens=1): - restart_limit = self.restart_limit - errors = (self.connection.connection_errors + - self.connection.channel_errors) - while not self.should_stop: - try: - if restart_limit.can_consume(_tokens): - for _ in self.consume(limit=None): # pragma: no cover - pass - else: - sleep(restart_limit.expected_time(_tokens)) - except errors: - warn('Connection to broker lost. ' - 'Trying to re-establish the connection...') - - @contextmanager - def consumer_context(self, **kwargs): - with self.Consumer() as (connection, channel, consumers): - with self.extra_context(connection, channel): - self.on_consume_ready(connection, channel, consumers, **kwargs) - yield connection, channel, consumers - - def consume(self, limit=None, timeout=None, safety_interval=1, **kwargs): - elapsed = 0 - with self.consumer_context(**kwargs) as (conn, channel, consumers): - for i in limit and range(limit) or count(): - if self.should_stop: - break - self.on_iteration() - try: - conn.drain_events(timeout=safety_interval) - except socket.timeout: - conn.heartbeat_check() - elapsed += safety_interval - if timeout and elapsed >= timeout: - raise - except socket.error: - if not self.should_stop: - raise - else: - yield - elapsed = 0 - debug('consume exiting') - - def maybe_conn_error(self, fun): - """Use :func:`kombu.common.ignore_errors` instead.""" - return ignore_errors(self, fun) - - def create_connection(self): - return self.connection.clone() - - @contextmanager - def establish_connection(self): - with self.create_connection() as conn: - conn.ensure_connection(self.on_connection_error, - self.connect_max_retries) - yield conn - - @contextmanager - def Consumer(self): - with self.establish_connection() as conn: - self.on_connection_revived() - info('Connected to %s', conn.as_uri()) - channel = conn.default_channel - cls = partial(Consumer, channel, - on_decode_error=self.on_decode_error) - with self._consume_from(*self.get_consumers(cls, channel)) as c: - yield conn, channel, c - debug('Consumers cancelled') - self.on_consume_end(conn, channel) - debug('Connection closed') - - def _consume_from(self, *consumers): - return nested(*consumers) - - @cached_property - def restart_limit(self): - # the AttributeError that can be catched from amqplib - # poses problems for the too often restarts protection - # in Connection.ensure_connection - return TokenBucket(1) - - @cached_property - def connection_errors(self): - return self.connection.connection_errors - - @cached_property - def channel_errors(self): - return self.connection.channel_errors diff --git a/awx/lib/site-packages/kombu/pidbox.py b/awx/lib/site-packages/kombu/pidbox.py deleted file mode 100644 index 3a3131154f..0000000000 --- a/awx/lib/site-packages/kombu/pidbox.py +++ /dev/null @@ -1,364 +0,0 @@ -""" -kombu.pidbox -=============== - -Generic process mailbox. - -""" -from __future__ import absolute_import - -import socket -import warnings - -from collections import defaultdict, deque -from copy import copy -from itertools import count -from threading import local -from time import time - -from . import Exchange, Queue, Consumer, Producer -from .clocks import LamportClock -from .common import maybe_declare, oid_from -from .exceptions import InconsistencyError -from .five import range -from .log import get_logger -from .utils import cached_property, kwdict, uuid, reprcall - -REPLY_QUEUE_EXPIRES = 10 - -W_PIDBOX_IN_USE = """\ -A node named {node.hostname} is already using this process mailbox! - -Maybe you forgot to shutdown the other node or did not do so properly? -Or if you meant to start multiple nodes on the same host please make sure -you give each node a unique node name! -""" - -__all__ = ['Node', 'Mailbox'] -logger = get_logger(__name__) -debug, error = logger.debug, logger.error - - -class Node(object): - - #: hostname of the node. - hostname = None - - #: the :class:`Mailbox` this is a node for. - mailbox = None - - #: map of method name/handlers. - handlers = None - - #: current context (passed on to handlers) - state = None - - #: current channel. - channel = None - - def __init__(self, hostname, state=None, channel=None, - handlers=None, mailbox=None): - self.channel = channel - self.mailbox = mailbox - self.hostname = hostname - self.state = state - self.adjust_clock = self.mailbox.clock.adjust - if handlers is None: - handlers = {} - self.handlers = handlers - - def Consumer(self, channel=None, no_ack=True, accept=None, **options): - queue = self.mailbox.get_queue(self.hostname) - - def verify_exclusive(name, messages, consumers): - if consumers: - warnings.warn(W_PIDBOX_IN_USE.format(node=self)) - queue.on_declared = verify_exclusive - - return Consumer( - channel or self.channel, [queue], no_ack=no_ack, - accept=self.mailbox.accept if accept is None else accept, - **options - ) - - def handler(self, fun): - self.handlers[fun.__name__] = fun - return fun - - def on_decode_error(self, message, exc): - error('Cannot decode message: %r', exc, exc_info=1) - - def listen(self, channel=None, callback=None): - consumer = self.Consumer(channel=channel, - callbacks=[callback or self.handle_message], - on_decode_error=self.on_decode_error) - consumer.consume() - return consumer - - def dispatch(self, method, arguments=None, - reply_to=None, ticket=None, **kwargs): - arguments = arguments or {} - debug('pidbox received method %s [reply_to:%s ticket:%s]', - reprcall(method, (), kwargs=arguments), reply_to, ticket) - handle = reply_to and self.handle_call or self.handle_cast - try: - reply = handle(method, kwdict(arguments)) - except SystemExit: - raise - except Exception as exc: - error('pidbox command error: %r', exc, exc_info=1) - reply = {'error': repr(exc)} - - if reply_to: - self.reply({self.hostname: reply}, - exchange=reply_to['exchange'], - routing_key=reply_to['routing_key'], - ticket=ticket) - return reply - - def handle(self, method, arguments={}): - return self.handlers[method](self.state, **arguments) - - def handle_call(self, method, arguments): - return self.handle(method, arguments) - - def handle_cast(self, method, arguments): - return self.handle(method, arguments) - - def handle_message(self, body, message=None): - destination = body.get('destination') - if message: - self.adjust_clock(message.headers.get('clock') or 0) - if not destination or self.hostname in destination: - return self.dispatch(**kwdict(body)) - dispatch_from_message = handle_message - - def reply(self, data, exchange, routing_key, ticket, **kwargs): - self.mailbox._publish_reply(data, exchange, routing_key, ticket, - channel=self.channel, - serializer=self.mailbox.serializer) - - -class Mailbox(object): - node_cls = Node - exchange_fmt = '%s.pidbox' - reply_exchange_fmt = 'reply.%s.pidbox' - - #: Name of application. - namespace = None - - #: Connection (if bound). - connection = None - - #: Exchange type (usually direct, or fanout for broadcast). - type = 'direct' - - #: mailbox exchange (init by constructor). - exchange = None - - #: exchange to send replies to. - reply_exchange = None - - #: Only accepts json messages by default. - accept = ['json'] - - #: Message serializer - serializer = None - - def __init__(self, namespace, - type='direct', connection=None, clock=None, - accept=None, serializer=None): - self.namespace = namespace - self.connection = connection - self.type = type - self.clock = LamportClock() if clock is None else clock - self.exchange = self._get_exchange(self.namespace, self.type) - self.reply_exchange = self._get_reply_exchange(self.namespace) - self._tls = local() - self.unclaimed = defaultdict(deque) - self.accept = self.accept if accept is None else accept - self.serializer = self.serializer if serializer is None else serializer - - def __call__(self, connection): - bound = copy(self) - bound.connection = connection - return bound - - def Node(self, hostname=None, state=None, channel=None, handlers=None): - hostname = hostname or socket.gethostname() - return self.node_cls(hostname, state, channel, handlers, mailbox=self) - - def call(self, destination, command, kwargs={}, - timeout=None, callback=None, channel=None): - return self._broadcast(command, kwargs, destination, - reply=True, timeout=timeout, - callback=callback, - channel=channel) - - def cast(self, destination, command, kwargs={}): - return self._broadcast(command, kwargs, destination, reply=False) - - def abcast(self, command, kwargs={}): - return self._broadcast(command, kwargs, reply=False) - - def multi_call(self, command, kwargs={}, timeout=1, - limit=None, callback=None, channel=None): - return self._broadcast(command, kwargs, reply=True, - timeout=timeout, limit=limit, - callback=callback, - channel=channel) - - def get_reply_queue(self): - oid = self.oid - return Queue( - '%s.%s' % (oid, self.reply_exchange.name), - exchange=self.reply_exchange, - routing_key=oid, - durable=False, - auto_delete=True, - queue_arguments={'x-expires': int(REPLY_QUEUE_EXPIRES * 1000)}, - ) - - @cached_property - def reply_queue(self): - return self.get_reply_queue() - - def get_queue(self, hostname): - return Queue('%s.%s.pidbox' % (hostname, self.namespace), - exchange=self.exchange, - durable=False, - auto_delete=True) - - def _publish_reply(self, reply, exchange, routing_key, ticket, - channel=None, **opts): - chan = channel or self.connection.default_channel - exchange = Exchange(exchange, exchange_type='direct', - delivery_mode='transient', - durable=False) - producer = Producer(chan, auto_declare=False) - try: - producer.publish( - reply, exchange=exchange, routing_key=routing_key, - declare=[exchange], headers={ - 'ticket': ticket, 'clock': self.clock.forward(), - }, - **opts - ) - except InconsistencyError: - pass # queue probably deleted and no one is expecting a reply. - - def _publish(self, type, arguments, destination=None, - reply_ticket=None, channel=None, timeout=None, - serializer=None): - message = {'method': type, - 'arguments': arguments, - 'destination': destination} - chan = channel or self.connection.default_channel - exchange = self.exchange - if reply_ticket: - maybe_declare(self.reply_queue(channel)) - message.update(ticket=reply_ticket, - reply_to={'exchange': self.reply_exchange.name, - 'routing_key': self.oid}) - serializer = serializer or self.serializer - producer = Producer(chan, auto_declare=False) - producer.publish( - message, exchange=exchange.name, declare=[exchange], - headers={'clock': self.clock.forward(), - 'expires': time() + timeout if timeout else 0}, - serializer=serializer, - ) - - def _broadcast(self, command, arguments=None, destination=None, - reply=False, timeout=1, limit=None, - callback=None, channel=None, serializer=None): - if destination is not None and \ - not isinstance(destination, (list, tuple)): - raise ValueError( - 'destination must be a list/tuple not {0}'.format( - type(destination))) - - arguments = arguments or {} - reply_ticket = reply and uuid() or None - chan = channel or self.connection.default_channel - - # Set reply limit to number of destinations (if specified) - if limit is None and destination: - limit = destination and len(destination) or None - - serializer = serializer or self.serializer - self._publish(command, arguments, destination=destination, - reply_ticket=reply_ticket, - channel=chan, - timeout=timeout, - serializer=serializer) - - if reply_ticket: - return self._collect(reply_ticket, limit=limit, - timeout=timeout, - callback=callback, - channel=chan) - - def _collect(self, ticket, - limit=None, timeout=1, callback=None, - channel=None, accept=None): - if accept is None: - accept = self.accept - chan = channel or self.connection.default_channel - queue = self.reply_queue - consumer = Consumer(channel, [queue], accept=accept, no_ack=True) - responses = [] - unclaimed = self.unclaimed - adjust_clock = self.clock.adjust - - try: - return unclaimed.pop(ticket) - except KeyError: - pass - - def on_message(body, message): - # ticket header added in kombu 2.5 - header = message.headers.get - adjust_clock(header('clock') or 0) - expires = header('expires') - if expires and time() > expires: - return - this_id = header('ticket', ticket) - if this_id == ticket: - if callback: - callback(body) - responses.append(body) - else: - unclaimed[this_id].append(body) - - consumer.register_callback(on_message) - try: - with consumer: - for i in limit and range(limit) or count(): - try: - self.connection.drain_events(timeout=timeout) - except socket.timeout: - break - return responses - finally: - chan.after_reply_message_received(queue.name) - - def _get_exchange(self, namespace, type): - return Exchange(self.exchange_fmt % namespace, - type=type, - durable=False, - delivery_mode='transient') - - def _get_reply_exchange(self, namespace): - return Exchange(self.reply_exchange_fmt % namespace, - type='direct', - durable=False, - delivery_mode='transient') - - @cached_property - def oid(self): - try: - return self._tls.OID - except AttributeError: - oid = self._tls.OID = oid_from(self) - return oid diff --git a/awx/lib/site-packages/kombu/pools.py b/awx/lib/site-packages/kombu/pools.py deleted file mode 100644 index 4d075e6243..0000000000 --- a/awx/lib/site-packages/kombu/pools.py +++ /dev/null @@ -1,153 +0,0 @@ -""" -kombu.pools -=========== - -Public resource pools. - -""" -from __future__ import absolute_import - -import os - -from itertools import chain - -from .connection import Resource -from .five import range, values -from .messaging import Producer -from .utils import EqualityDict -from .utils.functional import lazy - -__all__ = ['ProducerPool', 'PoolGroup', 'register_group', - 'connections', 'producers', 'get_limit', 'set_limit', 'reset'] -_limit = [200] -_used = [False] -_groups = [] -use_global_limit = object() -disable_limit_protection = os.environ.get('KOMBU_DISABLE_LIMIT_PROTECTION') - - -class ProducerPool(Resource): - Producer = Producer - - def __init__(self, connections, *args, **kwargs): - self.connections = connections - self.Producer = kwargs.pop('Producer', None) or self.Producer - super(ProducerPool, self).__init__(*args, **kwargs) - - def _acquire_connection(self): - return self.connections.acquire(block=True) - - def create_producer(self): - conn = self._acquire_connection() - try: - return self.Producer(conn) - except BaseException: - conn.release() - raise - - def new(self): - return lazy(self.create_producer) - - def setup(self): - if self.limit: - for _ in range(self.limit): - self._resource.put_nowait(self.new()) - - def close_resource(self, resource): - pass - - def prepare(self, p): - if callable(p): - p = p() - if p._channel is None: - conn = self._acquire_connection() - try: - p.revive(conn) - except BaseException: - conn.release() - raise - return p - - def release(self, resource): - if resource.__connection__: - resource.__connection__.release() - resource.channel = None - super(ProducerPool, self).release(resource) - - -class PoolGroup(EqualityDict): - - def __init__(self, limit=None): - self.limit = limit - - def create(self, resource, limit): - raise NotImplementedError('PoolGroups must define ``create``') - - def __missing__(self, resource): - limit = self.limit - if limit is use_global_limit: - limit = get_limit() - if not _used[0]: - _used[0] = True - k = self[resource] = self.create(resource, limit) - return k - - -def register_group(group): - _groups.append(group) - return group - - -class Connections(PoolGroup): - - def create(self, connection, limit): - return connection.Pool(limit=limit) -connections = register_group(Connections(limit=use_global_limit)) - - -class Producers(PoolGroup): - - def create(self, connection, limit): - return ProducerPool(connections[connection], limit=limit) -producers = register_group(Producers(limit=use_global_limit)) - - -def _all_pools(): - return chain(*[(values(g) if g else iter([])) for g in _groups]) - - -def get_limit(): - return _limit[0] - - -def set_limit(limit, force=False, reset_after=False): - limit = limit or 0 - glimit = _limit[0] or 0 - if limit < glimit: - if not disable_limit_protection and (_used[0] and not force): - raise RuntimeError("Can't lower limit after pool in use.") - reset_after = True - if limit != glimit: - _limit[0] = limit - for pool in _all_pools(): - pool.limit = limit - if reset_after: - reset() - return limit - - -def reset(*args, **kwargs): - for pool in _all_pools(): - try: - pool.force_close_all() - except Exception: - pass - for group in _groups: - group.clear() - _used[0] = False - -try: - from multiprocessing.util import register_after_fork - register_after_fork(connections, reset) -except ImportError: # pragma: no cover - pass diff --git a/awx/lib/site-packages/kombu/serialization.py b/awx/lib/site-packages/kombu/serialization.py deleted file mode 100644 index 47b8f91b6c..0000000000 --- a/awx/lib/site-packages/kombu/serialization.py +++ /dev/null @@ -1,455 +0,0 @@ -""" -kombu.serialization -=================== - -Serialization utilities. - -""" -from __future__ import absolute_import - -import codecs -import os -import sys - -import pickle as pypickle -try: - import cPickle as cpickle -except ImportError: # pragma: no cover - cpickle = None # noqa - -from collections import namedtuple -from contextlib import contextmanager - -from .exceptions import ( - ContentDisallowed, DecodeError, EncodeError, SerializerNotInstalled -) -from .five import BytesIO, reraise, text_t -from .utils import entrypoints -from .utils.encoding import str_to_bytes, bytes_t - -__all__ = ['pickle', 'loads', 'dumps', 'register', 'unregister'] -SKIP_DECODE = frozenset(['binary', 'ascii-8bit']) -TRUSTED_CONTENT = frozenset(['application/data', 'application/text']) - -if sys.platform.startswith('java'): # pragma: no cover - - def _decode(t, coding): - return codecs.getdecoder(coding)(t)[0] -else: - _decode = codecs.decode - -pickle = cpickle or pypickle -pickle_load = pickle.load - -#: Kombu requires Python 2.5 or later so we use protocol 2 by default. -#: There's a new protocol (3) but this is only supported by Python 3. -pickle_protocol = int(os.environ.get('PICKLE_PROTOCOL', 2)) - -codec = namedtuple('codec', ('content_type', 'content_encoding', 'encoder')) - - -@contextmanager -def _reraise_errors(wrapper, - include=(Exception, ), exclude=(SerializerNotInstalled, )): - try: - yield - except exclude: - raise - except include as exc: - reraise(wrapper, wrapper(exc), sys.exc_info()[2]) - - -def pickle_loads(s, load=pickle_load): - # used to support buffer objects - return load(BytesIO(s)) - - -def parenthesize_alias(first, second): - return '%s (%s)' % (first, second) if first else second - - -class SerializerRegistry(object): - """The registry keeps track of serialization methods.""" - - def __init__(self): - self._encoders = {} - self._decoders = {} - self._default_encode = None - self._default_content_type = None - self._default_content_encoding = None - self._disabled_content_types = set() - self.type_to_name = {} - self.name_to_type = {} - - def register(self, name, encoder, decoder, content_type, - content_encoding='utf-8'): - if encoder: - self._encoders[name] = codec( - content_type, content_encoding, encoder, - ) - if decoder: - self._decoders[content_type] = decoder - self.type_to_name[content_type] = name - self.name_to_type[name] = content_type - - def enable(self, name): - if '/' not in name: - name = self.name_to_type[name] - self._disabled_content_types.discard(name) - - def disable(self, name): - if '/' not in name: - name = self.name_to_type[name] - self._disabled_content_types.add(name) - - def unregister(self, name): - try: - content_type = self.name_to_type[name] - self._decoders.pop(content_type, None) - self._encoders.pop(name, None) - self.type_to_name.pop(content_type, None) - self.name_to_type.pop(name, None) - except KeyError: - raise SerializerNotInstalled( - 'No encoder/decoder installed for {0}'.format(name)) - - def _set_default_serializer(self, name): - """ - Set the default serialization method used by this library. - - :param name: The name of the registered serialization method. - For example, `json` (default), `pickle`, `yaml`, `msgpack`, - or any custom methods registered using :meth:`register`. - - :raises SerializerNotInstalled: If the serialization method - requested is not available. - """ - try: - (self._default_content_type, self._default_content_encoding, - self._default_encode) = self._encoders[name] - except KeyError: - raise SerializerNotInstalled( - 'No encoder installed for {0}'.format(name)) - - def dumps(self, data, serializer=None): - if serializer == 'raw': - return raw_encode(data) - if serializer and not self._encoders.get(serializer): - raise SerializerNotInstalled( - 'No encoder installed for {0}'.format(serializer)) - - # If a raw string was sent, assume binary encoding - # (it's likely either ASCII or a raw binary file, and a character - # set of 'binary' will encompass both, even if not ideal. - if not serializer and isinstance(data, bytes_t): - # In Python 3+, this would be "bytes"; allow binary data to be - # sent as a message without getting encoder errors - return 'application/data', 'binary', data - - # For Unicode objects, force it into a string - if not serializer and isinstance(data, text_t): - with _reraise_errors(EncodeError, exclude=()): - payload = data.encode('utf-8') - return 'text/plain', 'utf-8', payload - - if serializer: - content_type, content_encoding, encoder = \ - self._encoders[serializer] - else: - encoder = self._default_encode - content_type = self._default_content_type - content_encoding = self._default_content_encoding - - with _reraise_errors(EncodeError): - payload = encoder(data) - return content_type, content_encoding, payload - encode = dumps # XXX compat - - def loads(self, data, content_type, content_encoding, - accept=None, force=False, _trusted_content=TRUSTED_CONTENT): - content_type = content_type or 'application/data' - if accept is not None: - if content_type not in _trusted_content \ - and content_type not in accept: - raise self._for_untrusted_content(content_type, 'untrusted') - else: - if content_type in self._disabled_content_types and not force: - raise self._for_untrusted_content(content_type, 'disabled') - content_encoding = (content_encoding or 'utf-8').lower() - - if data: - decode = self._decoders.get(content_type) - if decode: - with _reraise_errors(DecodeError): - return decode(data) - if content_encoding not in SKIP_DECODE and \ - not isinstance(data, text_t): - with _reraise_errors(DecodeError): - return _decode(data, content_encoding) - return data - decode = loads # XXX compat - - def _for_untrusted_content(self, ctype, why): - return ContentDisallowed( - 'Refusing to deserialize {0} content of type {1}'.format( - why, - parenthesize_alias(self.type_to_name.get(ctype, ctype), ctype), - ), - ) - - -#: Global registry of serializers/deserializers. -registry = SerializerRegistry() - - -""" -.. function:: dumps(data, serializer=default_serializer) - - Serialize a data structure into a string suitable for sending - as an AMQP message body. - - :param data: The message data to send. Can be a list, - dictionary or a string. - - :keyword serializer: An optional string representing - the serialization method you want the data marshalled - into. (For example, `json`, `raw`, or `pickle`). - - If :const:`None` (default), then json will be used, unless - `data` is a :class:`str` or :class:`unicode` object. In this - latter case, no serialization occurs as it would be - unnecessary. - - Note that if `serializer` is specified, then that - serialization method will be used even if a :class:`str` - or :class:`unicode` object is passed in. - - :returns: A three-item tuple containing the content type - (e.g., `application/json`), content encoding, (e.g., - `utf-8`) and a string containing the serialized - data. - - :raises SerializerNotInstalled: If the serialization method - requested is not available. -""" -dumps = encode = registry.encode # XXX encode is a compat alias - -""" -.. function:: loads(data, content_type, content_encoding): - - Deserialize a data stream as serialized using `dumps` - based on `content_type`. - - :param data: The message data to deserialize. - - :param content_type: The content-type of the data. - (e.g., `application/json`). - - :param content_encoding: The content-encoding of the data. - (e.g., `utf-8`, `binary`, or `us-ascii`). - - :returns: The unserialized data. - -""" -loads = decode = registry.decode # XXX decode is a compat alias - - -""" -.. function:: register(name, encoder, decoder, content_type, - content_encoding='utf-8'): - Register a new encoder/decoder. - - :param name: A convenience name for the serialization method. - - :param encoder: A method that will be passed a python data structure - and should return a string representing the serialized data. - If :const:`None`, then only a decoder will be registered. Encoding - will not be possible. - - :param decoder: A method that will be passed a string representing - serialized data and should return a python data structure. - If :const:`None`, then only an encoder will be registered. - Decoding will not be possible. - - :param content_type: The mime-type describing the serialized - structure. - - :param content_encoding: The content encoding (character set) that - the `decoder` method will be returning. Will usually be - `utf-8`, `us-ascii`, or `binary`. - -""" -register = registry.register - - -""" -.. function:: unregister(name): - Unregister registered encoder/decoder. - - :param name: Registered serialization method name. - -""" -unregister = registry.unregister - - -def raw_encode(data): - """Special case serializer.""" - content_type = 'application/data' - payload = data - if isinstance(payload, text_t): - content_encoding = 'utf-8' - with _reraise_errors(EncodeError, exclude=()): - payload = payload.encode(content_encoding) - else: - content_encoding = 'binary' - return content_type, content_encoding, payload - - -def register_json(): - """Register a encoder/decoder for JSON serialization.""" - from anyjson import loads as json_loads, dumps as json_dumps - - def _loads(obj): - if isinstance(obj, bytes_t): - obj = obj.decode() - return json_loads(obj) - - registry.register('json', json_dumps, _loads, - content_type='application/json', - content_encoding='utf-8') - - -def register_yaml(): - """Register a encoder/decoder for YAML serialization. - - It is slower than JSON, but allows for more data types - to be serialized. Useful if you need to send data such as dates""" - try: - import yaml - registry.register('yaml', yaml.safe_dump, yaml.safe_load, - content_type='application/x-yaml', - content_encoding='utf-8') - except ImportError: - - def not_available(*args, **kwargs): - """In case a client receives a yaml message, but yaml - isn't installed.""" - raise SerializerNotInstalled( - 'No decoder installed for YAML. Install the PyYAML library') - registry.register('yaml', None, not_available, 'application/x-yaml') - - -if sys.version_info[0] == 3: # pragma: no cover - - def unpickle(s): - return pickle_loads(str_to_bytes(s)) - -else: - unpickle = pickle_loads # noqa - - -def register_pickle(): - """The fastest serialization method, but restricts - you to python clients.""" - - def pickle_dumps(obj, dumper=pickle.dumps): - return dumper(obj, protocol=pickle_protocol) - - registry.register('pickle', pickle_dumps, unpickle, - content_type='application/x-python-serialize', - content_encoding='binary') - - -def register_msgpack(): - """See http://msgpack.sourceforge.net/""" - try: - try: - from msgpack import packb as pack, unpackb - unpack = lambda s: unpackb(s, encoding='utf-8') - except ImportError: - # msgpack < 0.2.0 and Python 2.5 - from msgpack import packs as pack, unpacks as unpack # noqa - registry.register( - 'msgpack', pack, unpack, - content_type='application/x-msgpack', - content_encoding='binary') - except (ImportError, ValueError): - - def not_available(*args, **kwargs): - """In case a client receives a msgpack message, but yaml - isn't installed.""" - raise SerializerNotInstalled( - 'No decoder installed for msgpack. ' - 'Please install the msgpack library') - registry.register('msgpack', None, not_available, - 'application/x-msgpack') - -# Register the base serialization methods. -register_json() -register_pickle() -register_yaml() -register_msgpack() - -# Default serializer is 'json' -registry._set_default_serializer('json') - - -_setupfuns = { - 'json': register_json, - 'pickle': register_pickle, - 'yaml': register_yaml, - 'msgpack': register_msgpack, - 'application/json': register_json, - 'application/x-yaml': register_yaml, - 'application/x-python-serialize': register_pickle, - 'application/x-msgpack': register_msgpack, -} - - -def enable_insecure_serializers(choices=['pickle', 'yaml', 'msgpack']): - """Enable serializers that are considered to be unsafe. - - Will enable ``pickle``, ``yaml`` and ``msgpack`` by default, - but you can also specify a list of serializers (by name or content type) - to enable. - - """ - for choice in choices: - try: - registry.enable(choice) - except KeyError: - pass - - -def disable_insecure_serializers(allowed=['json']): - """Disable untrusted serializers. - - Will disable all serializers except ``json`` - or you can specify a list of deserializers to allow. - - .. note:: - - Producers will still be able to serialize data - in these formats, but consumers will not accept - incoming data using the untrusted content types. - - """ - for name in registry._decoders: - registry.disable(name) - if allowed is not None: - for name in allowed: - registry.enable(name) - - -# Insecure serializers are disabled by default since v3.0 -disable_insecure_serializers() - -# Load entrypoints from installed extensions -for ep, args in entrypoints('kombu.serializers'): # pragma: no cover - register(ep.name, *args) - - -def prepare_accept_content(l, name_to_type=registry.name_to_type): - if l is not None: - return set(n if '/' in n else name_to_type[n] for n in l) - return l diff --git a/awx/lib/site-packages/kombu/simple.py b/awx/lib/site-packages/kombu/simple.py deleted file mode 100644 index 1b1d8e7652..0000000000 --- a/awx/lib/site-packages/kombu/simple.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -kombu.simple -============ - -Simple interface. - -""" -from __future__ import absolute_import - -import socket - -from collections import deque - -from . import entity -from . import messaging -from .connection import maybe_channel -from .five import Empty, monotonic - -__all__ = ['SimpleQueue', 'SimpleBuffer'] - - -class SimpleBase(object): - Empty = Empty - _consuming = False - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - def __init__(self, channel, producer, consumer, no_ack=False): - self.channel = maybe_channel(channel) - self.producer = producer - self.consumer = consumer - self.no_ack = no_ack - self.queue = self.consumer.queues[0] - self.buffer = deque() - self.consumer.register_callback(self._receive) - - def get(self, block=True, timeout=None): - if not block: - return self.get_nowait() - self._consume() - elapsed = 0.0 - remaining = timeout - while True: - time_start = monotonic() - if self.buffer: - return self.buffer.pop() - try: - self.channel.connection.client.drain_events( - timeout=timeout and remaining) - except socket.timeout: - raise self.Empty() - elapsed += monotonic() - time_start - remaining = timeout and timeout - elapsed or None - - def get_nowait(self): - m = self.queue.get(no_ack=self.no_ack) - if not m: - raise self.Empty() - return m - - def put(self, message, serializer=None, headers=None, compression=None, - routing_key=None, **kwargs): - self.producer.publish(message, - serializer=serializer, - routing_key=routing_key, - headers=headers, - compression=compression, - **kwargs) - - def clear(self): - return self.consumer.purge() - - def qsize(self): - _, size, _ = self.queue.queue_declare(passive=True) - return size - - def close(self): - self.consumer.cancel() - - def _receive(self, message_data, message): - self.buffer.append(message) - - def _consume(self): - if not self._consuming: - self.consumer.consume(no_ack=self.no_ack) - self._consuming = True - - def __len__(self): - """`len(self) -> self.qsize()`""" - return self.qsize() - - def __bool__(self): - return True - __nonzero__ = __bool__ - - -class SimpleQueue(SimpleBase): - no_ack = False - queue_opts = {} - exchange_opts = {'type': 'direct'} - - def __init__(self, channel, name, no_ack=None, queue_opts=None, - exchange_opts=None, serializer=None, - compression=None, **kwargs): - queue = name - queue_opts = dict(self.queue_opts, **queue_opts or {}) - exchange_opts = dict(self.exchange_opts, **exchange_opts or {}) - if no_ack is None: - no_ack = self.no_ack - if not isinstance(queue, entity.Queue): - exchange = entity.Exchange(name, **exchange_opts) - queue = entity.Queue(name, exchange, name, **queue_opts) - routing_key = name - else: - name = queue.name - exchange = queue.exchange - routing_key = queue.routing_key - producer = messaging.Producer(channel, exchange, - serializer=serializer, - routing_key=routing_key, - compression=compression) - consumer = messaging.Consumer(channel, queue) - super(SimpleQueue, self).__init__(channel, producer, - consumer, no_ack, **kwargs) - - -class SimpleBuffer(SimpleQueue): - no_ack = True - queue_opts = dict(durable=False, - auto_delete=True) - exchange_opts = dict(durable=False, - delivery_mode='transient', - auto_delete=True) diff --git a/awx/lib/site-packages/kombu/syn.py b/awx/lib/site-packages/kombu/syn.py deleted file mode 100644 index 01b4d479cc..0000000000 --- a/awx/lib/site-packages/kombu/syn.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -kombu.syn -========= - -""" -from __future__ import absolute_import - -import sys - -__all__ = ['detect_environment'] - -_environment = None - - -def blocking(fun, *args, **kwargs): - return fun(*args, **kwargs) - - -def select_blocking_method(type): - pass - - -def _detect_environment(): - # ## -eventlet- - if 'eventlet' in sys.modules: - try: - from eventlet.patcher import is_monkey_patched as is_eventlet - import socket - - if is_eventlet(socket): - return 'eventlet' - except ImportError: - pass - - # ## -gevent- - if 'gevent' in sys.modules: - try: - from gevent import socket as _gsocket - import socket - - if socket.socket is _gsocket.socket: - return 'gevent' - except ImportError: - pass - - return 'default' - - -def detect_environment(): - global _environment - if _environment is None: - _environment = _detect_environment() - return _environment diff --git a/awx/lib/site-packages/kombu/tests/__init__.py b/awx/lib/site-packages/kombu/tests/__init__.py deleted file mode 100644 index fb9f21a210..0000000000 --- a/awx/lib/site-packages/kombu/tests/__init__.py +++ /dev/null @@ -1,91 +0,0 @@ -from __future__ import absolute_import - -import anyjson -import atexit -import os -import sys - -from kombu.exceptions import VersionMismatch - -# avoid json implementation inconsistencies. -try: - import json # noqa - anyjson.force_implementation('json') -except ImportError: - anyjson.force_implementation('simplejson') - - -def teardown(): - # Workaround for multiprocessing bug where logging - # is attempted after global already collected at shutdown. - cancelled = set() - try: - import multiprocessing.util - cancelled.add(multiprocessing.util._exit_function) - except (AttributeError, ImportError): - pass - - try: - atexit._exithandlers[:] = [ - e for e in atexit._exithandlers if e[0] not in cancelled - ] - except AttributeError: # pragma: no cover - pass # Py3 missing _exithandlers - - -def find_distribution_modules(name=__name__, file=__file__): - current_dist_depth = len(name.split('.')) - 1 - current_dist = os.path.join(os.path.dirname(file), - *([os.pardir] * current_dist_depth)) - abs = os.path.abspath(current_dist) - dist_name = os.path.basename(abs) - - for dirpath, dirnames, filenames in os.walk(abs): - package = (dist_name + dirpath[len(abs):]).replace('/', '.') - if '__init__.py' in filenames: - yield package - for filename in filenames: - if filename.endswith('.py') and filename != '__init__.py': - yield '.'.join([package, filename])[:-3] - - -def import_all_modules(name=__name__, file=__file__, skip=[]): - for module in find_distribution_modules(name, file): - if module not in skip: - print('preimporting %r for coverage...' % (module, )) - try: - __import__(module) - except (ImportError, VersionMismatch, AttributeError): - pass - - -def is_in_coverage(): - return (os.environ.get('COVER_ALL_MODULES') or - '--with-coverage3' in sys.argv) - - -def setup_django_env(): - try: - from django.conf import settings - except ImportError: - return - - if not settings.configured: - settings.configure( - DATABASES={ - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': ':memory:', - }, - }, - DATABASE_ENGINE='sqlite3', - DATABASE_NAME=':memory:', - INSTALLED_APPS=('kombu.transport.django', ), - ) - - -def setup(): - # so coverage sees all our modules. - setup_django_env() - if is_in_coverage(): - import_all_modules() diff --git a/awx/lib/site-packages/kombu/tests/async/__init__.py b/awx/lib/site-packages/kombu/tests/async/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/kombu/tests/async/test_hub.py b/awx/lib/site-packages/kombu/tests/async/test_hub.py deleted file mode 100644 index 7d5d81cd43..0000000000 --- a/awx/lib/site-packages/kombu/tests/async/test_hub.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import absolute_import - -from kombu.async import hub as _hub -from kombu.async.hub import Hub, get_event_loop, set_event_loop - -from kombu.tests.case import Case - - -class test_Utils(Case): - - def setUp(self): - self._prev_loop = get_event_loop() - - def tearDown(self): - set_event_loop(self._prev_loop) - - def test_get_set_event_loop(self): - set_event_loop(None) - self.assertIsNone(_hub._current_loop) - self.assertIsNone(get_event_loop()) - hub = Hub() - set_event_loop(hub) - self.assertIs(_hub._current_loop, hub) - self.assertIs(get_event_loop(), hub) - - -class test_Hub(Case): - - def setUp(self): - self.hub = Hub() - - def tearDown(self): - self.hub.close() diff --git a/awx/lib/site-packages/kombu/tests/async/test_semaphore.py b/awx/lib/site-packages/kombu/tests/async/test_semaphore.py deleted file mode 100644 index 5ca48de708..0000000000 --- a/awx/lib/site-packages/kombu/tests/async/test_semaphore.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import absolute_import - -from kombu.async.semaphore import LaxBoundedSemaphore - -from kombu.tests.case import Case - - -class test_LaxBoundedSemaphore(Case): - - def test_over_release(self): - x = LaxBoundedSemaphore(2) - calls = [] - for i in range(1, 21): - x.acquire(calls.append, i) - x.release() - x.acquire(calls.append, 'x') - x.release() - x.acquire(calls.append, 'y') - - self.assertEqual(calls, [1, 2, 3, 4]) - - for i in range(30): - x.release() - self.assertEqual(calls, list(range(1, 21)) + ['x', 'y']) - self.assertEqual(x.value, x.initial_value) - - calls[:] = [] - for i in range(1, 11): - x.acquire(calls.append, i) - for i in range(1, 11): - x.release() - self.assertEqual(calls, list(range(1, 11))) - - calls[:] = [] - self.assertEqual(x.value, x.initial_value) - x.acquire(calls.append, 'x') - self.assertEqual(x.value, 1) - x.acquire(calls.append, 'y') - self.assertEqual(x.value, 0) - x.release() - self.assertEqual(x.value, 1) - x.release() - self.assertEqual(x.value, 2) - x.release() - self.assertEqual(x.value, 2) diff --git a/awx/lib/site-packages/kombu/tests/case.py b/awx/lib/site-packages/kombu/tests/case.py deleted file mode 100644 index e8b6d32b86..0000000000 --- a/awx/lib/site-packages/kombu/tests/case.py +++ /dev/null @@ -1,191 +0,0 @@ -from __future__ import absolute_import - -import os -import sys -import types - -from functools import wraps - -import mock - -from nose import SkipTest - -from kombu.five import builtins, string_t, StringIO -from kombu.utils.encoding import ensure_bytes - -try: - import unittest - unittest.skip -except AttributeError: - import unittest2 as unittest # noqa - -PY3 = sys.version_info[0] == 3 - -patch = mock.patch -call = mock.call - - -class Case(unittest.TestCase): - - def assertItemsEqual(self, a, b, *args, **kwargs): - return self.assertEqual(sorted(a), sorted(b), *args, **kwargs) - assertSameElements = assertItemsEqual - - -class Mock(mock.Mock): - - def __init__(self, *args, **kwargs): - attrs = kwargs.pop('attrs', None) or {} - super(Mock, self).__init__(*args, **kwargs) - for attr_name, attr_value in attrs.items(): - setattr(self, attr_name, attr_value) - - -class _ContextMock(Mock): - """Dummy class implementing __enter__ and __exit__ - as the with statement requires these to be implemented - in the class, not just the instance.""" - - def __enter__(self): - pass - - def __exit__(self, *exc_info): - pass - - -def ContextMock(*args, **kwargs): - obj = _ContextMock(*args, **kwargs) - obj.attach_mock(Mock(), '__enter__') - obj.attach_mock(Mock(), '__exit__') - obj.__enter__.return_value = obj - # if __exit__ return a value the exception is ignored, - # so it must return None here. - obj.__exit__.return_value = None - return obj - - -class MockPool(object): - - def __init__(self, value=None): - self.value = value or ContextMock() - - def acquire(self, **kwargs): - return self.value - - -def redirect_stdouts(fun): - - @wraps(fun) - def _inner(*args, **kwargs): - sys.stdout = StringIO() - sys.stderr = StringIO() - try: - return fun(*args, **dict(kwargs, - stdout=sys.stdout, stderr=sys.stderr)) - finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - - return _inner - - -def module_exists(*modules): - - def _inner(fun): - - @wraps(fun) - def __inner(*args, **kwargs): - gen = [] - for module in modules: - if isinstance(module, string_t): - if not PY3: - module = ensure_bytes(module) - module = types.ModuleType(module) - gen.append(module) - sys.modules[module.__name__] = module - name = module.__name__ - if '.' in name: - parent, _, attr = name.rpartition('.') - setattr(sys.modules[parent], attr, module) - try: - return fun(*args, **kwargs) - finally: - for module in gen: - sys.modules.pop(module.__name__, None) - - return __inner - return _inner - - -# Taken from -# http://bitbucket.org/runeh/snippets/src/tip/missing_modules.py -def mask_modules(*modnames): - def _inner(fun): - - @wraps(fun) - def __inner(*args, **kwargs): - realimport = builtins.__import__ - - def myimp(name, *args, **kwargs): - if name in modnames: - raise ImportError('No module named %s' % name) - else: - return realimport(name, *args, **kwargs) - - builtins.__import__ = myimp - try: - return fun(*args, **kwargs) - finally: - builtins.__import__ = realimport - - return __inner - return _inner - - -def skip_if_environ(env_var_name): - - def _wrap_test(fun): - - @wraps(fun) - def _skips_if_environ(*args, **kwargs): - if os.environ.get(env_var_name): - raise SkipTest('SKIP %s: %s set\n' % ( - fun.__name__, env_var_name)) - return fun(*args, **kwargs) - - return _skips_if_environ - - return _wrap_test - - -def skip_if_module(module): - def _wrap_test(fun): - @wraps(fun) - def _skip_if_module(*args, **kwargs): - try: - __import__(module) - raise SkipTest('SKIP %s: %s available\n' % ( - fun.__name__, module)) - except ImportError: - pass - return fun(*args, **kwargs) - return _skip_if_module - return _wrap_test - - -def skip_if_not_module(module, import_errors=(ImportError, )): - def _wrap_test(fun): - @wraps(fun) - def _skip_if_not_module(*args, **kwargs): - try: - __import__(module) - except import_errors: - raise SkipTest('SKIP %s: %s available\n' % ( - fun.__name__, module)) - return fun(*args, **kwargs) - return _skip_if_not_module - return _wrap_test - - -def skip_if_quick(fun): - return skip_if_environ('QUICKTEST')(fun) diff --git a/awx/lib/site-packages/kombu/tests/mocks.py b/awx/lib/site-packages/kombu/tests/mocks.py deleted file mode 100644 index 836457ebdd..0000000000 --- a/awx/lib/site-packages/kombu/tests/mocks.py +++ /dev/null @@ -1,148 +0,0 @@ -from __future__ import absolute_import - -from itertools import count - -import anyjson - -from kombu.transport import base - - -class Message(base.Message): - - def __init__(self, *args, **kwargs): - self.throw_decode_error = kwargs.get('throw_decode_error', False) - super(Message, self).__init__(*args, **kwargs) - - def decode(self): - if self.throw_decode_error: - raise ValueError("can't decode message") - return super(Message, self).decode() - - -class Channel(base.StdChannel): - open = True - throw_decode_error = False - _ids = count(1) - - def __init__(self, connection): - self.connection = connection - self.called = [] - self.deliveries = count(1) - self.to_deliver = [] - self.events = {'basic_return': set()} - self.channel_id = next(self._ids) - - def _called(self, name): - self.called.append(name) - - def __contains__(self, key): - return key in self.called - - def exchange_declare(self, *args, **kwargs): - self._called('exchange_declare') - - def prepare_message(self, body, priority=0, content_type=None, - content_encoding=None, headers=None, properties={}): - self._called('prepare_message') - return dict(body=body, - headers=headers, - properties=properties, - priority=priority, - content_type=content_type, - content_encoding=content_encoding) - - def basic_publish(self, message, exchange='', routing_key='', - mandatory=False, immediate=False, **kwargs): - self._called('basic_publish') - return message, exchange, routing_key - - def exchange_delete(self, *args, **kwargs): - self._called('exchange_delete') - - def queue_declare(self, *args, **kwargs): - self._called('queue_declare') - - def queue_bind(self, *args, **kwargs): - self._called('queue_bind') - - def queue_unbind(self, *args, **kwargs): - self._called('queue_unbind') - - def queue_delete(self, queue, if_unused=False, if_empty=False, **kwargs): - self._called('queue_delete') - - def basic_get(self, *args, **kwargs): - self._called('basic_get') - try: - return self.to_deliver.pop() - except IndexError: - pass - - def queue_purge(self, *args, **kwargs): - self._called('queue_purge') - - def basic_consume(self, *args, **kwargs): - self._called('basic_consume') - - def basic_cancel(self, *args, **kwargs): - self._called('basic_cancel') - - def basic_ack(self, *args, **kwargs): - self._called('basic_ack') - - def basic_recover(self, requeue=False): - self._called('basic_recover') - - def exchange_bind(self, *args, **kwargs): - self._called('exchange_bind') - - def exchange_unbind(self, *args, **kwargs): - self._called('exchange_unbind') - - def close(self): - self._called('close') - - def message_to_python(self, message, *args, **kwargs): - self._called('message_to_python') - return Message(self, body=anyjson.dumps(message), - delivery_tag=next(self.deliveries), - throw_decode_error=self.throw_decode_error, - content_type='application/json', - content_encoding='utf-8') - - def flow(self, active): - self._called('flow') - - def basic_reject(self, delivery_tag, requeue=False): - if requeue: - return self._called('basic_reject:requeue') - return self._called('basic_reject') - - def basic_qos(self, prefetch_size=0, prefetch_count=0, - apply_global=False): - self._called('basic_qos') - - -class Connection(object): - connected = True - - def __init__(self, client): - self.client = client - - def channel(self): - return Channel(self) - - -class Transport(base.Transport): - - def establish_connection(self): - return Connection(self.client) - - def create_channel(self, connection): - return connection.channel() - - def drain_events(self, connection, **kwargs): - return 'event' - - def close_connection(self, connection): - connection.connected = False diff --git a/awx/lib/site-packages/kombu/tests/test_clocks.py b/awx/lib/site-packages/kombu/tests/test_clocks.py deleted file mode 100644 index fa39b6d1a7..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_clocks.py +++ /dev/null @@ -1,104 +0,0 @@ -from __future__ import absolute_import - -import pickle - -from heapq import heappush -from time import time - -from kombu.clocks import LamportClock, timetuple - -from .case import Mock, Case - - -class test_LamportClock(Case): - - def test_clocks(self): - c1 = LamportClock() - c2 = LamportClock() - - c1.forward() - c2.forward() - c1.forward() - c1.forward() - c2.adjust(c1.value) - self.assertEqual(c2.value, c1.value + 1) - self.assertTrue(repr(c1)) - - c2_val = c2.value - c2.forward() - c2.forward() - c2.adjust(c1.value) - self.assertEqual(c2.value, c2_val + 2 + 1) - - c1.adjust(c2.value) - self.assertEqual(c1.value, c2.value + 1) - - def test_sort(self): - c = LamportClock() - pid1 = 'a.example.com:312' - pid2 = 'b.example.com:311' - - events = [] - - m1 = (c.forward(), pid1) - heappush(events, m1) - m2 = (c.forward(), pid2) - heappush(events, m2) - m3 = (c.forward(), pid1) - heappush(events, m3) - m4 = (30, pid1) - heappush(events, m4) - m5 = (30, pid2) - heappush(events, m5) - - self.assertEqual(str(c), str(c.value)) - - self.assertEqual(c.sort_heap(events), m1) - self.assertEqual(c.sort_heap([m4, m5]), m4) - self.assertEqual(c.sort_heap([m4, m5, m1]), m4) - - -class test_timetuple(Case): - - def test_repr(self): - x = timetuple(133, time(), 'id', Mock()) - self.assertTrue(repr(x)) - - def test_pickleable(self): - x = timetuple(133, time(), 'id', 'obj') - self.assertEqual(pickle.loads(pickle.dumps(x)), tuple(x)) - - def test_order(self): - t1 = time() - t2 = time() + 300 # windows clock not reliable - a = timetuple(133, t1, 'A', 'obj') - b = timetuple(140, t1, 'A', 'obj') - self.assertTrue(a.__getnewargs__()) - self.assertEqual(a.clock, 133) - self.assertEqual(a.timestamp, t1) - self.assertEqual(a.id, 'A') - self.assertEqual(a.obj, 'obj') - self.assertTrue( - a <= b, - ) - self.assertTrue( - b >= a, - ) - - self.assertEqual( - timetuple(134, time(), 'A', 'obj').__lt__(tuple()), - NotImplemented, - ) - self.assertGreater( - timetuple(134, t2, 'A', 'obj'), - timetuple(133, t1, 'A', 'obj'), - ) - self.assertGreater( - timetuple(134, t1, 'B', 'obj'), - timetuple(134, t1, 'A', 'obj'), - ) - - self.assertGreater( - timetuple(None, t2, 'B', 'obj'), - timetuple(None, t1, 'A', 'obj'), - ) diff --git a/awx/lib/site-packages/kombu/tests/test_common.py b/awx/lib/site-packages/kombu/tests/test_common.py deleted file mode 100644 index c4eebb71c2..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_common.py +++ /dev/null @@ -1,416 +0,0 @@ -from __future__ import absolute_import - -import socket - -from amqp import RecoverableConnectionError - -from kombu import common -from kombu.common import ( - Broadcast, maybe_declare, - send_reply, collect_replies, - declaration_cached, ignore_errors, - QoS, PREFETCH_COUNT_MAX, -) - -from .case import Case, ContextMock, Mock, MockPool, patch - - -class test_ignore_errors(Case): - - def test_ignored(self): - connection = Mock() - connection.channel_errors = (KeyError, ) - connection.connection_errors = (KeyError, ) - - with ignore_errors(connection): - raise KeyError() - - def raising(): - raise KeyError() - - ignore_errors(connection, raising) - - connection.channel_errors = connection.connection_errors = \ - () - - with self.assertRaises(KeyError): - with ignore_errors(connection): - raise KeyError() - - -class test_declaration_cached(Case): - - def test_when_cached(self): - chan = Mock() - chan.connection.client.declared_entities = ['foo'] - self.assertTrue(declaration_cached('foo', chan)) - - def test_when_not_cached(self): - chan = Mock() - chan.connection.client.declared_entities = ['bar'] - self.assertFalse(declaration_cached('foo', chan)) - - -class test_Broadcast(Case): - - def test_arguments(self): - q = Broadcast(name='test_Broadcast') - self.assertTrue(q.name.startswith('bcast.')) - self.assertEqual(q.alias, 'test_Broadcast') - self.assertTrue(q.auto_delete) - self.assertEqual(q.exchange.name, 'test_Broadcast') - self.assertEqual(q.exchange.type, 'fanout') - - q = Broadcast('test_Broadcast', 'explicit_queue_name') - self.assertEqual(q.name, 'explicit_queue_name') - self.assertEqual(q.exchange.name, 'test_Broadcast') - - -class test_maybe_declare(Case): - - def test_cacheable(self): - channel = Mock() - client = channel.connection.client = Mock() - client.declared_entities = set() - entity = Mock() - entity.can_cache_declaration = True - entity.auto_delete = False - entity.is_bound = True - entity.channel = channel - - maybe_declare(entity, channel) - self.assertEqual(entity.declare.call_count, 1) - self.assertIn( - hash(entity), channel.connection.client.declared_entities, - ) - - maybe_declare(entity, channel) - self.assertEqual(entity.declare.call_count, 1) - - entity.channel.connection = None - with self.assertRaises(RecoverableConnectionError): - maybe_declare(entity) - - def test_binds_entities(self): - channel = Mock() - channel.connection.client.declared_entities = set() - entity = Mock() - entity.can_cache_declaration = True - entity.is_bound = False - entity.bind.return_value = entity - entity.bind.return_value.channel = channel - - maybe_declare(entity, channel) - entity.bind.assert_called_with(channel) - - def test_with_retry(self): - channel = Mock() - client = channel.connection.client = Mock() - client.declared_entities = set() - entity = Mock() - entity.can_cache_declaration = True - entity.is_bound = True - entity.channel = channel - - maybe_declare(entity, channel, retry=True) - self.assertTrue(channel.connection.client.ensure.call_count) - - -class test_replies(Case): - - def test_send_reply(self): - req = Mock() - req.content_type = 'application/json' - req.content_encoding = 'binary' - req.properties = {'reply_to': 'hello', - 'correlation_id': 'world'} - channel = Mock() - exchange = Mock() - exchange.is_bound = True - exchange.channel = channel - producer = Mock() - producer.channel = channel - producer.channel.connection.client.declared_entities = set() - send_reply(exchange, req, {'hello': 'world'}, producer) - - self.assertTrue(producer.publish.call_count) - args = producer.publish.call_args - self.assertDictEqual(args[0][0], {'hello': 'world'}) - self.assertDictEqual(args[1], {'exchange': exchange, - 'routing_key': 'hello', - 'correlation_id': 'world', - 'serializer': 'json', - 'retry': False, - 'retry_policy': None, - 'content_encoding': 'binary'}) - - @patch('kombu.common.itermessages') - def test_collect_replies_with_ack(self, itermessages): - conn, channel, queue = Mock(), Mock(), Mock() - body, message = Mock(), Mock() - itermessages.return_value = [(body, message)] - it = collect_replies(conn, channel, queue, no_ack=False) - m = next(it) - self.assertIs(m, body) - itermessages.assert_called_with(conn, channel, queue, no_ack=False) - message.ack.assert_called_with() - - with self.assertRaises(StopIteration): - next(it) - - channel.after_reply_message_received.assert_called_with(queue.name) - - @patch('kombu.common.itermessages') - def test_collect_replies_no_ack(self, itermessages): - conn, channel, queue = Mock(), Mock(), Mock() - body, message = Mock(), Mock() - itermessages.return_value = [(body, message)] - it = collect_replies(conn, channel, queue) - m = next(it) - self.assertIs(m, body) - itermessages.assert_called_with(conn, channel, queue, no_ack=True) - self.assertFalse(message.ack.called) - - @patch('kombu.common.itermessages') - def test_collect_replies_no_replies(self, itermessages): - conn, channel, queue = Mock(), Mock(), Mock() - itermessages.return_value = [] - it = collect_replies(conn, channel, queue) - with self.assertRaises(StopIteration): - next(it) - - self.assertFalse(channel.after_reply_message_received.called) - - -class test_insured(Case): - - @patch('kombu.common.logger') - def test_ensure_errback(self, logger): - common._ensure_errback('foo', 30) - self.assertTrue(logger.error.called) - - def test_revive_connection(self): - on_revive = Mock() - channel = Mock() - common.revive_connection(Mock(), channel, on_revive) - on_revive.assert_called_with(channel) - - common.revive_connection(Mock(), channel, None) - - def get_insured_mocks(self, insured_returns=('works', 'ignored')): - conn = ContextMock() - pool = MockPool(conn) - fun = Mock() - insured = conn.autoretry.return_value = Mock() - insured.return_value = insured_returns - return conn, pool, fun, insured - - def test_insured(self): - conn, pool, fun, insured = self.get_insured_mocks() - - ret = common.insured(pool, fun, (2, 2), {'foo': 'bar'}) - self.assertEqual(ret, 'works') - conn.ensure_connection.assert_called_with( - errback=common._ensure_errback, - ) - - self.assertTrue(insured.called) - i_args, i_kwargs = insured.call_args - self.assertTupleEqual(i_args, (2, 2)) - self.assertDictEqual(i_kwargs, {'foo': 'bar', - 'connection': conn}) - - self.assertTrue(conn.autoretry.called) - ar_args, ar_kwargs = conn.autoretry.call_args - self.assertTupleEqual(ar_args, (fun, conn.default_channel)) - self.assertTrue(ar_kwargs.get('on_revive')) - self.assertTrue(ar_kwargs.get('errback')) - - def test_insured_custom_errback(self): - conn, pool, fun, insured = self.get_insured_mocks() - - custom_errback = Mock() - common.insured(pool, fun, (2, 2), {'foo': 'bar'}, - errback=custom_errback) - conn.ensure_connection.assert_called_with(errback=custom_errback) - - -class MockConsumer(object): - consumers = set() - - def __init__(self, channel, queues=None, callbacks=None, **kwargs): - self.channel = channel - self.queues = queues - self.callbacks = callbacks - - def __enter__(self): - self.consumers.add(self) - return self - - def __exit__(self, *exc_info): - self.consumers.discard(self) - - -class test_itermessages(Case): - - class MockConnection(object): - should_raise_timeout = False - - def drain_events(self, **kwargs): - if self.should_raise_timeout: - raise socket.timeout() - for consumer in MockConsumer.consumers: - for callback in consumer.callbacks: - callback('body', 'message') - - def test_default(self): - conn = self.MockConnection() - channel = Mock() - channel.connection.client = conn - conn.Consumer = MockConsumer - it = common.itermessages(conn, channel, 'q', limit=1) - - ret = next(it) - self.assertTupleEqual(ret, ('body', 'message')) - - with self.assertRaises(StopIteration): - next(it) - - def test_when_raises_socket_timeout(self): - conn = self.MockConnection() - conn.should_raise_timeout = True - channel = Mock() - channel.connection.client = conn - conn.Consumer = MockConsumer - it = common.itermessages(conn, channel, 'q', limit=1) - - with self.assertRaises(StopIteration): - next(it) - - @patch('kombu.common.deque') - def test_when_raises_IndexError(self, deque): - deque_instance = deque.return_value = Mock() - deque_instance.popleft.side_effect = IndexError() - conn = self.MockConnection() - channel = Mock() - conn.Consumer = MockConsumer - it = common.itermessages(conn, channel, 'q', limit=1) - - with self.assertRaises(StopIteration): - next(it) - - -class test_QoS(Case): - - class _QoS(QoS): - def __init__(self, value): - self.value = value - QoS.__init__(self, None, value) - - def set(self, value): - return value - - def test_qos_exceeds_16bit(self): - with patch('kombu.common.logger') as logger: - callback = Mock() - qos = QoS(callback, 10) - qos.prev = 100 - # cannot use 2 ** 32 because of a bug on OSX Py2.5: - # https://jira.mongodb.org/browse/PYTHON-389 - qos.set(4294967296) - self.assertTrue(logger.warn.called) - callback.assert_called_with(prefetch_count=0) - - def test_qos_increment_decrement(self): - qos = self._QoS(10) - self.assertEqual(qos.increment_eventually(), 11) - self.assertEqual(qos.increment_eventually(3), 14) - self.assertEqual(qos.increment_eventually(-30), 14) - self.assertEqual(qos.decrement_eventually(7), 7) - self.assertEqual(qos.decrement_eventually(), 6) - - def test_qos_disabled_increment_decrement(self): - qos = self._QoS(0) - self.assertEqual(qos.increment_eventually(), 0) - self.assertEqual(qos.increment_eventually(3), 0) - self.assertEqual(qos.increment_eventually(-30), 0) - self.assertEqual(qos.decrement_eventually(7), 0) - self.assertEqual(qos.decrement_eventually(), 0) - self.assertEqual(qos.decrement_eventually(10), 0) - - def test_qos_thread_safe(self): - qos = self._QoS(10) - - def add(): - for i in range(1000): - qos.increment_eventually() - - def sub(): - for i in range(1000): - qos.decrement_eventually() - - def threaded(funs): - from threading import Thread - threads = [Thread(target=fun) for fun in funs] - for thread in threads: - thread.start() - for thread in threads: - thread.join() - - threaded([add, add]) - self.assertEqual(qos.value, 2010) - - qos.value = 1000 - threaded([add, sub]) # n = 2 - self.assertEqual(qos.value, 1000) - - def test_exceeds_short(self): - qos = QoS(Mock(), PREFETCH_COUNT_MAX - 1) - qos.update() - self.assertEqual(qos.value, PREFETCH_COUNT_MAX - 1) - qos.increment_eventually() - self.assertEqual(qos.value, PREFETCH_COUNT_MAX) - qos.increment_eventually() - self.assertEqual(qos.value, PREFETCH_COUNT_MAX + 1) - qos.decrement_eventually() - self.assertEqual(qos.value, PREFETCH_COUNT_MAX) - qos.decrement_eventually() - self.assertEqual(qos.value, PREFETCH_COUNT_MAX - 1) - - def test_consumer_increment_decrement(self): - mconsumer = Mock() - qos = QoS(mconsumer.qos, 10) - qos.update() - self.assertEqual(qos.value, 10) - mconsumer.qos.assert_called_with(prefetch_count=10) - qos.decrement_eventually() - qos.update() - self.assertEqual(qos.value, 9) - mconsumer.qos.assert_called_with(prefetch_count=9) - qos.decrement_eventually() - self.assertEqual(qos.value, 8) - mconsumer.qos.assert_called_with(prefetch_count=9) - self.assertIn({'prefetch_count': 9}, mconsumer.qos.call_args) - - # Does not decrement 0 value - qos.value = 0 - qos.decrement_eventually() - self.assertEqual(qos.value, 0) - qos.increment_eventually() - self.assertEqual(qos.value, 0) - - def test_consumer_decrement_eventually(self): - mconsumer = Mock() - qos = QoS(mconsumer.qos, 10) - qos.decrement_eventually() - self.assertEqual(qos.value, 9) - qos.value = 0 - qos.decrement_eventually() - self.assertEqual(qos.value, 0) - - def test_set(self): - mconsumer = Mock() - qos = QoS(mconsumer.qos, 10) - qos.set(12) - self.assertEqual(qos.prev, 12) - qos.set(qos.prev) diff --git a/awx/lib/site-packages/kombu/tests/test_compat.py b/awx/lib/site-packages/kombu/tests/test_compat.py deleted file mode 100644 index b081cf0c22..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_compat.py +++ /dev/null @@ -1,331 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection, Exchange, Queue -from kombu import compat - -from .case import Case, Mock, patch -from .mocks import Transport, Channel - - -class test_misc(Case): - - def test_iterconsume(self): - - class MyConnection(object): - drained = 0 - - def drain_events(self, *args, **kwargs): - self.drained += 1 - return self.drained - - class Consumer(object): - active = False - - def consume(self, *args, **kwargs): - self.active = True - - conn = MyConnection() - consumer = Consumer() - it = compat._iterconsume(conn, consumer) - self.assertEqual(next(it), 1) - self.assertTrue(consumer.active) - - it2 = compat._iterconsume(conn, consumer, limit=10) - self.assertEqual(list(it2), [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) - - def test_Queue_from_dict(self): - defs = {'binding_key': 'foo.#', - 'exchange': 'fooex', - 'exchange_type': 'topic', - 'durable': True, - 'auto_delete': False} - - q1 = Queue.from_dict('foo', **dict(defs)) - self.assertEqual(q1.name, 'foo') - self.assertEqual(q1.routing_key, 'foo.#') - self.assertEqual(q1.exchange.name, 'fooex') - self.assertEqual(q1.exchange.type, 'topic') - self.assertTrue(q1.durable) - self.assertTrue(q1.exchange.durable) - self.assertFalse(q1.auto_delete) - self.assertFalse(q1.exchange.auto_delete) - - q2 = Queue.from_dict('foo', **dict(defs, - exchange_durable=False)) - self.assertTrue(q2.durable) - self.assertFalse(q2.exchange.durable) - - q3 = Queue.from_dict('foo', **dict(defs, - exchange_auto_delete=True)) - self.assertFalse(q3.auto_delete) - self.assertTrue(q3.exchange.auto_delete) - - q4 = Queue.from_dict('foo', **dict(defs, - queue_durable=False)) - self.assertFalse(q4.durable) - self.assertTrue(q4.exchange.durable) - - q5 = Queue.from_dict('foo', **dict(defs, - queue_auto_delete=True)) - self.assertTrue(q5.auto_delete) - self.assertFalse(q5.exchange.auto_delete) - - self.assertEqual(Queue.from_dict('foo', **dict(defs)), - Queue.from_dict('foo', **dict(defs))) - - -class test_Publisher(Case): - - def setUp(self): - self.connection = Connection(transport=Transport) - - def test_constructor(self): - pub = compat.Publisher(self.connection, - exchange='test_Publisher_constructor', - routing_key='rkey') - self.assertIsInstance(pub.backend, Channel) - self.assertEqual(pub.exchange.name, 'test_Publisher_constructor') - self.assertTrue(pub.exchange.durable) - self.assertFalse(pub.exchange.auto_delete) - self.assertEqual(pub.exchange.type, 'direct') - - pub2 = compat.Publisher(self.connection, - exchange='test_Publisher_constructor2', - routing_key='rkey', - auto_delete=True, - durable=False) - self.assertTrue(pub2.exchange.auto_delete) - self.assertFalse(pub2.exchange.durable) - - explicit = Exchange('test_Publisher_constructor_explicit', - type='topic') - pub3 = compat.Publisher(self.connection, - exchange=explicit) - self.assertEqual(pub3.exchange, explicit) - - compat.Publisher(self.connection, - exchange='test_Publisher_constructor3', - channel=self.connection.default_channel) - - def test_send(self): - pub = compat.Publisher(self.connection, - exchange='test_Publisher_send', - routing_key='rkey') - pub.send({'foo': 'bar'}) - self.assertIn('basic_publish', pub.backend) - pub.close() - - def test__enter__exit__(self): - pub = compat.Publisher(self.connection, - exchange='test_Publisher_send', - routing_key='rkey') - x = pub.__enter__() - self.assertIs(x, pub) - x.__exit__() - self.assertTrue(pub._closed) - - -class test_Consumer(Case): - - def setUp(self): - self.connection = Connection(transport=Transport) - - @patch('kombu.compat._iterconsume') - def test_iterconsume_calls__iterconsume(self, it, n='test_iterconsume'): - c = compat.Consumer(self.connection, queue=n, exchange=n) - c.iterconsume(limit=10, no_ack=True) - it.assert_called_with(c.connection, c, True, 10) - - def test_constructor(self, n='test_Consumer_constructor'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - self.assertIsInstance(c.backend, Channel) - q = c.queues[0] - self.assertTrue(q.durable) - self.assertTrue(q.exchange.durable) - self.assertFalse(q.auto_delete) - self.assertFalse(q.exchange.auto_delete) - self.assertEqual(q.name, n) - self.assertEqual(q.exchange.name, n) - - c2 = compat.Consumer(self.connection, queue=n + '2', - exchange=n + '2', - routing_key='rkey', durable=False, - auto_delete=True, exclusive=True) - q2 = c2.queues[0] - self.assertFalse(q2.durable) - self.assertFalse(q2.exchange.durable) - self.assertTrue(q2.auto_delete) - self.assertTrue(q2.exchange.auto_delete) - - def test__enter__exit__(self, n='test__enter__exit__'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - x = c.__enter__() - self.assertIs(x, c) - x.__exit__() - self.assertTrue(c._closed) - - def test_revive(self, n='test_revive'): - c = compat.Consumer(self.connection, queue=n, exchange=n) - - with self.connection.channel() as c2: - c.revive(c2) - self.assertIs(c.backend, c2) - - def test__iter__(self, n='test__iter__'): - c = compat.Consumer(self.connection, queue=n, exchange=n) - c.iterqueue = Mock() - - c.__iter__() - c.iterqueue.assert_called_with(infinite=True) - - def test_iter(self, n='test_iterqueue'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - c.close() - - def test_process_next(self, n='test_process_next'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - with self.assertRaises(NotImplementedError): - c.process_next() - c.close() - - def test_iterconsume(self, n='test_iterconsume'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - c.close() - - def test_discard_all(self, n='test_discard_all'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - c.discard_all() - self.assertIn('queue_purge', c.backend) - - def test_fetch(self, n='test_fetch'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - self.assertIsNone(c.fetch()) - self.assertIsNone(c.fetch(no_ack=True)) - self.assertIn('basic_get', c.backend) - - callback_called = [False] - - def receive(payload, message): - callback_called[0] = True - - c.backend.to_deliver.append('42') - payload = c.fetch().payload - self.assertEqual(payload, '42') - c.backend.to_deliver.append('46') - c.register_callback(receive) - self.assertEqual(c.fetch(enable_callbacks=True).payload, '46') - self.assertTrue(callback_called[0]) - - def test_discard_all_filterfunc_not_supported(self, n='xjf21j21'): - c = compat.Consumer(self.connection, queue=n, exchange=n, - routing_key='rkey') - with self.assertRaises(NotImplementedError): - c.discard_all(filterfunc=lambda x: x) - c.close() - - def test_wait(self, n='test_wait'): - - class C(compat.Consumer): - - def iterconsume(self, limit=None): - for i in range(limit): - yield i - - c = C(self.connection, - queue=n, exchange=n, routing_key='rkey') - self.assertEqual(c.wait(10), list(range(10))) - c.close() - - def test_iterqueue(self, n='test_iterqueue'): - i = [0] - - class C(compat.Consumer): - - def fetch(self, limit=None): - z = i[0] - i[0] += 1 - return z - - c = C(self.connection, - queue=n, exchange=n, routing_key='rkey') - self.assertEqual(list(c.iterqueue(limit=10)), list(range(10))) - c.close() - - -class test_ConsumerSet(Case): - - def setUp(self): - self.connection = Connection(transport=Transport) - - def test_providing_channel(self): - chan = Mock(name='channel') - cs = compat.ConsumerSet(self.connection, channel=chan) - self.assertTrue(cs._provided_channel) - self.assertIs(cs.backend, chan) - - cs.cancel = Mock(name='cancel') - cs.close() - self.assertFalse(chan.close.called) - - @patch('kombu.compat._iterconsume') - def test_iterconsume(self, _iterconsume, n='test_iterconsume'): - c = compat.Consumer(self.connection, queue=n, exchange=n) - cs = compat.ConsumerSet(self.connection, consumers=[c]) - cs.iterconsume(limit=10, no_ack=True) - _iterconsume.assert_called_with(c.connection, cs, True, 10) - - def test_revive(self, n='test_revive'): - c = compat.Consumer(self.connection, queue=n, exchange=n) - cs = compat.ConsumerSet(self.connection, consumers=[c]) - - with self.connection.channel() as c2: - cs.revive(c2) - self.assertIs(cs.backend, c2) - - def test_constructor(self, prefix='0daf8h21'): - dcon = {'%s.xyx' % prefix: {'exchange': '%s.xyx' % prefix, - 'routing_key': 'xyx'}, - '%s.xyz' % prefix: {'exchange': '%s.xyz' % prefix, - 'routing_key': 'xyz'}} - consumers = [compat.Consumer(self.connection, queue=prefix + str(i), - exchange=prefix + str(i)) - for i in range(3)] - c = compat.ConsumerSet(self.connection, consumers=consumers) - c2 = compat.ConsumerSet(self.connection, from_dict=dcon) - - self.assertEqual(len(c.queues), 3) - self.assertEqual(len(c2.queues), 2) - - c.add_consumer(compat.Consumer(self.connection, - queue=prefix + 'xaxxxa', - exchange=prefix + 'xaxxxa')) - self.assertEqual(len(c.queues), 4) - for cq in c.queues: - self.assertIs(cq.channel, c.channel) - - c2.add_consumer_from_dict({ - '%s.xxx' % prefix: { - 'exchange': '%s.xxx' % prefix, - 'routing_key': 'xxx', - }, - }) - self.assertEqual(len(c2.queues), 3) - for c2q in c2.queues: - self.assertIs(c2q.channel, c2.channel) - - c.discard_all() - self.assertEqual(c.channel.called.count('queue_purge'), 4) - c.consume() - - c.close() - c2.close() - self.assertIn('basic_cancel', c.channel) - self.assertIn('close', c.channel) - self.assertIn('close', c2.channel) diff --git a/awx/lib/site-packages/kombu/tests/test_compression.py b/awx/lib/site-packages/kombu/tests/test_compression.py deleted file mode 100644 index 7d651ee25d..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_compression.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import absolute_import - -import sys - -from kombu import compression - -from .case import Case, SkipTest, mask_modules - - -class test_compression(Case): - - def setUp(self): - try: - import bz2 # noqa - except ImportError: - self.has_bzip2 = False - else: - self.has_bzip2 = True - - @mask_modules('bz2') - def test_no_bz2(self): - c = sys.modules.pop('kombu.compression') - try: - import kombu.compression - self.assertFalse(hasattr(kombu.compression, 'bz2')) - finally: - if c is not None: - sys.modules['kombu.compression'] = c - - def test_encoders(self): - encoders = compression.encoders() - self.assertIn('application/x-gzip', encoders) - if self.has_bzip2: - self.assertIn('application/x-bz2', encoders) - - def test_compress__decompress__zlib(self): - text = b'The Quick Brown Fox Jumps Over The Lazy Dog' - c, ctype = compression.compress(text, 'zlib') - self.assertNotEqual(text, c) - d = compression.decompress(c, ctype) - self.assertEqual(d, text) - - def test_compress__decompress__bzip2(self): - if not self.has_bzip2: - raise SkipTest('bzip2 not available') - text = b'The Brown Quick Fox Over The Lazy Dog Jumps' - c, ctype = compression.compress(text, 'bzip2') - self.assertNotEqual(text, c) - d = compression.decompress(c, ctype) - self.assertEqual(d, text) diff --git a/awx/lib/site-packages/kombu/tests/test_connection.py b/awx/lib/site-packages/kombu/tests/test_connection.py deleted file mode 100644 index 6bd3303fc9..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_connection.py +++ /dev/null @@ -1,688 +0,0 @@ -from __future__ import absolute_import - -import pickle -import socket - -from copy import copy - -from kombu import Connection, Consumer, Producer, parse_url -from kombu.connection import Resource -from kombu.five import items, range - -from .case import Case, Mock, SkipTest, patch, skip_if_not_module -from .mocks import Transport - - -class test_connection_utils(Case): - - def setUp(self): - self.url = 'amqp://user:pass@localhost:5672/my/vhost' - self.nopass = 'amqp://user:**@localhost:5672/my/vhost' - self.expected = { - 'transport': 'amqp', - 'userid': 'user', - 'password': 'pass', - 'hostname': 'localhost', - 'port': 5672, - 'virtual_host': 'my/vhost', - } - - def test_parse_url(self): - result = parse_url(self.url) - self.assertDictEqual(result, self.expected) - - def test_parse_generated_as_uri(self): - conn = Connection(self.url) - info = conn.info() - for k, v in self.expected.items(): - self.assertEqual(info[k], v) - # by default almost the same- no password - self.assertEqual(conn.as_uri(), self.nopass) - self.assertEqual(conn.as_uri(include_password=True), self.url) - - def test_as_uri_when_prefix(self): - conn = Connection('memory://') - conn.uri_prefix = 'foo' - self.assertTrue(conn.as_uri().startswith('foo+memory://')) - - @skip_if_not_module('pymongo') - def test_as_uri_when_mongodb(self): - x = Connection('mongodb://localhost') - self.assertTrue(x.as_uri()) - - def test_bogus_scheme(self): - with self.assertRaises(KeyError): - Connection('bogus://localhost:7421').transport - - def assert_info(self, conn, **fields): - info = conn.info() - for field, expected in items(fields): - self.assertEqual(info[field], expected) - - def test_rabbitmq_example_urls(self): - # see Appendix A of http://www.rabbitmq.com/uri-spec.html - - self.assert_info( - Connection('amqp://user:pass@host:10000/vhost'), - userid='user', password='pass', hostname='host', - port=10000, virtual_host='vhost', - ) - - self.assert_info( - Connection('amqp://user%61:%61pass@ho%61st:10000/v%2fhost'), - userid='usera', password='apass', hostname='hoast', - port=10000, virtual_host='v/host', - ) - - self.assert_info( - Connection('amqp://'), - userid='guest', password='guest', hostname='localhost', - port=5672, virtual_host='/', - ) - - self.assert_info( - Connection('amqp://:@/'), - userid='guest', password='guest', hostname='localhost', - port=5672, virtual_host='/', - ) - - self.assert_info( - Connection('amqp://user@/'), - userid='user', password='guest', hostname='localhost', - port=5672, virtual_host='/', - ) - - self.assert_info( - Connection('amqp://user:pass@/'), - userid='user', password='pass', hostname='localhost', - port=5672, virtual_host='/', - ) - - self.assert_info( - Connection('amqp://host'), - userid='guest', password='guest', hostname='host', - port=5672, virtual_host='/', - ) - - self.assert_info( - Connection('amqp://:10000'), - userid='guest', password='guest', hostname='localhost', - port=10000, virtual_host='/', - ) - - self.assert_info( - Connection('amqp:///vhost'), - userid='guest', password='guest', hostname='localhost', - port=5672, virtual_host='vhost', - ) - - self.assert_info( - Connection('amqp://host/'), - userid='guest', password='guest', hostname='host', - port=5672, virtual_host='/', - ) - - self.assert_info( - Connection('amqp://host/%2f'), - userid='guest', password='guest', hostname='host', - port=5672, virtual_host='/', - ) - - def test_url_IPV6(self): - raise SkipTest("urllib can't parse ipv6 urls") - - self.assert_info( - Connection('amqp://[::1]'), - userid='guest', password='guest', hostname='[::1]', - port=5672, virtual_host='/', - ) - - -class test_Connection(Case): - - def setUp(self): - self.conn = Connection(port=5672, transport=Transport) - - def test_establish_connection(self): - conn = self.conn - conn.connect() - self.assertTrue(conn.connection.connected) - self.assertEqual(conn.host, 'localhost:5672') - channel = conn.channel() - self.assertTrue(channel.open) - self.assertEqual(conn.drain_events(), 'event') - _connection = conn.connection - conn.close() - self.assertFalse(_connection.connected) - self.assertIsInstance(conn.transport, Transport) - - def test_multiple_urls(self): - conn1 = Connection('amqp://foo;amqp://bar') - self.assertEqual(conn1.hostname, 'foo') - self.assertListEqual(conn1.alt, ['amqp://foo', 'amqp://bar']) - - conn2 = Connection(['amqp://foo', 'amqp://bar']) - self.assertEqual(conn2.hostname, 'foo') - self.assertListEqual(conn2.alt, ['amqp://foo', 'amqp://bar']) - - def test_collect(self): - connection = Connection('memory://') - trans = connection._transport = Mock(name='transport') - _collect = trans._collect = Mock(name='transport._collect') - _close = connection._close = Mock(name='connection._close') - connection.declared_entities = Mock(name='decl_entities') - uconn = connection._connection = Mock(name='_connection') - connection.collect() - - self.assertFalse(_close.called) - _collect.assert_called_with(uconn) - connection.declared_entities.clear.assert_called_with() - self.assertIsNone(trans.client) - self.assertIsNone(connection._transport) - self.assertIsNone(connection._connection) - - def test_collect_no_transport(self): - connection = Connection('memory://') - connection._transport = None - connection._close = Mock() - connection.collect() - connection._close.assert_called_with() - - connection._close.side_effect = socket.timeout() - connection.collect() - - def test_collect_transport_gone(self): - connection = Connection('memory://') - uconn = connection._connection = Mock(name='conn._conn') - trans = connection._transport = Mock(name='transport') - collect = trans._collect = Mock(name='transport._collect') - - def se(conn): - connection._transport = None - collect.side_effect = se - - connection.collect() - collect.assert_called_with(uconn) - self.assertIsNone(connection._transport) - - def test_uri_passthrough(self): - transport = Mock(name='transport') - with patch('kombu.connection.get_transport_cls') as gtc: - gtc.return_value = transport - transport.can_parse_url = True - with patch('kombu.connection.parse_url') as parse_url: - c = Connection('foo+mysql://some_host') - self.assertEqual(c.transport_cls, 'foo') - self.assertFalse(parse_url.called) - self.assertEqual(c.hostname, 'mysql://some_host') - self.assertTrue(c.as_uri().startswith('foo+')) - with patch('kombu.connection.parse_url') as parse_url: - c = Connection('mysql://some_host', transport='foo') - self.assertEqual(c.transport_cls, 'foo') - self.assertFalse(parse_url.called) - self.assertEqual(c.hostname, 'mysql://some_host') - c = Connection('pyamqp+sqlite://some_host') - self.assertTrue(c.as_uri().startswith('pyamqp+')) - - def test_default_ensure_callback(self): - with patch('kombu.connection.logger') as logger: - c = Connection(transport=Mock) - c._default_ensure_callback(KeyError(), 3) - self.assertTrue(logger.error.called) - - def test_ensure_connection_on_error(self): - c = Connection('amqp://A;amqp://B') - with patch('kombu.connection.retry_over_time') as rot: - c.ensure_connection() - self.assertTrue(rot.called) - - args = rot.call_args[0] - cb = args[4] - intervals = iter([1, 2, 3, 4, 5]) - self.assertEqual(cb(KeyError(), intervals, 0), 0) - self.assertEqual(cb(KeyError(), intervals, 1), 1) - self.assertEqual(cb(KeyError(), intervals, 2), 0) - self.assertEqual(cb(KeyError(), intervals, 3), 2) - self.assertEqual(cb(KeyError(), intervals, 4), 0) - self.assertEqual(cb(KeyError(), intervals, 5), 3) - self.assertEqual(cb(KeyError(), intervals, 6), 0) - self.assertEqual(cb(KeyError(), intervals, 7), 4) - - errback = Mock() - c.ensure_connection(errback=errback) - args = rot.call_args[0] - cb = args[4] - self.assertEqual(cb(KeyError(), intervals, 0), 0) - self.assertTrue(errback.called) - - def test_supports_heartbeats(self): - c = Connection(transport=Mock) - c.transport.supports_heartbeats = False - self.assertFalse(c.supports_heartbeats) - - def test_is_evented(self): - c = Connection(transport=Mock) - c.transport.supports_ev = False - self.assertFalse(c.is_evented) - - def test_register_with_event_loop(self): - c = Connection(transport=Mock) - loop = Mock(name='loop') - c.register_with_event_loop(loop) - c.transport.register_with_event_loop.assert_called_with( - c.connection, loop, - ) - - def test_manager(self): - c = Connection(transport=Mock) - self.assertIs(c.manager, c.transport.manager) - - def test_copy(self): - c = Connection('amqp://example.com') - self.assertEqual(copy(c).info(), c.info()) - - def test_copy_multiples(self): - c = Connection('amqp://A.example.com;amqp://B.example.com') - self.assertTrue(c.alt) - d = copy(c) - self.assertEqual(d.alt, c.alt) - - def test_switch(self): - c = Connection('amqp://foo') - c._closed = True - c.switch('redis://example.com//3') - self.assertFalse(c._closed) - self.assertEqual(c.hostname, 'example.com') - self.assertEqual(c.transport_cls, 'redis') - self.assertEqual(c.virtual_host, '/3') - - def test_maybe_switch_next(self): - c = Connection('amqp://foo;redis://example.com//3') - c.maybe_switch_next() - self.assertFalse(c._closed) - self.assertEqual(c.hostname, 'example.com') - self.assertEqual(c.transport_cls, 'redis') - self.assertEqual(c.virtual_host, '/3') - - def test_maybe_switch_next_no_cycle(self): - c = Connection('amqp://foo') - c.maybe_switch_next() - self.assertFalse(c._closed) - self.assertEqual(c.hostname, 'foo') - self.assertIn(c.transport_cls, ('librabbitmq', 'pyamqp', 'amqp')) - - def test_heartbeat_check(self): - c = Connection(transport=Transport) - c.transport.heartbeat_check = Mock() - c.heartbeat_check(3) - c.transport.heartbeat_check.assert_called_with(c.connection, rate=3) - - def test_completes_cycle_no_cycle(self): - c = Connection('amqp://') - self.assertTrue(c.completes_cycle(0)) - self.assertTrue(c.completes_cycle(1)) - - def test_completes_cycle(self): - c = Connection('amqp://a;amqp://b;amqp://c') - self.assertFalse(c.completes_cycle(0)) - self.assertFalse(c.completes_cycle(1)) - self.assertTrue(c.completes_cycle(2)) - - def test__enter____exit__(self): - conn = self.conn - context = conn.__enter__() - self.assertIs(context, conn) - conn.connect() - self.assertTrue(conn.connection.connected) - conn.__exit__() - self.assertIsNone(conn.connection) - conn.close() # again - - def test_close_survives_connerror(self): - - class _CustomError(Exception): - pass - - class MyTransport(Transport): - connection_errors = (_CustomError, ) - - def close_connection(self, connection): - raise _CustomError('foo') - - conn = Connection(transport=MyTransport) - conn.connect() - conn.close() - self.assertTrue(conn._closed) - - def test_close_when_default_channel(self): - conn = self.conn - conn._default_channel = Mock() - conn._close() - conn._default_channel.close.assert_called_with() - - def test_close_when_default_channel_close_raises(self): - - class Conn(Connection): - - @property - def connection_errors(self): - return (KeyError, ) - - conn = Conn('memory://') - conn._default_channel = Mock() - conn._default_channel.close.side_effect = KeyError() - - conn._close() - conn._default_channel.close.assert_called_with() - - def test_revive_when_default_channel(self): - conn = self.conn - defchan = conn._default_channel = Mock() - conn.revive(Mock()) - - defchan.close.assert_called_with() - self.assertIsNone(conn._default_channel) - - def test_ensure_connection(self): - self.assertTrue(self.conn.ensure_connection()) - - def test_ensure_success(self): - def publish(): - return 'foobar' - - ensured = self.conn.ensure(None, publish) - self.assertEqual(ensured(), 'foobar') - - def test_ensure_failure(self): - class _CustomError(Exception): - pass - - def publish(): - raise _CustomError('bar') - - ensured = self.conn.ensure(None, publish) - with self.assertRaises(_CustomError): - ensured() - - def test_ensure_connection_failure(self): - class _ConnectionError(Exception): - pass - - def publish(): - raise _ConnectionError('failed connection') - - self.conn.transport.connection_errors = (_ConnectionError,) - ensured = self.conn.ensure(self.conn, publish) - with self.assertRaises(_ConnectionError): - ensured() - - def test_autoretry(self): - myfun = Mock() - myfun.__name__ = 'test_autoretry' - - self.conn.transport.connection_errors = (KeyError, ) - - def on_call(*args, **kwargs): - myfun.side_effect = None - raise KeyError('foo') - - myfun.side_effect = on_call - insured = self.conn.autoretry(myfun) - insured() - - self.assertTrue(myfun.called) - - def test_SimpleQueue(self): - conn = self.conn - q = conn.SimpleQueue('foo') - self.assertIs(q.channel, conn.default_channel) - chan = conn.channel() - q2 = conn.SimpleQueue('foo', channel=chan) - self.assertIs(q2.channel, chan) - - def test_SimpleBuffer(self): - conn = self.conn - q = conn.SimpleBuffer('foo') - self.assertIs(q.channel, conn.default_channel) - chan = conn.channel() - q2 = conn.SimpleBuffer('foo', channel=chan) - self.assertIs(q2.channel, chan) - - def test_Producer(self): - conn = self.conn - self.assertIsInstance(conn.Producer(), Producer) - self.assertIsInstance(conn.Producer(conn.default_channel), Producer) - - def test_Consumer(self): - conn = self.conn - self.assertIsInstance(conn.Consumer(queues=[]), Consumer) - self.assertIsInstance(conn.Consumer(queues=[], - channel=conn.default_channel), Consumer) - - def test__repr__(self): - self.assertTrue(repr(self.conn)) - - def test__reduce__(self): - x = pickle.loads(pickle.dumps(self.conn)) - self.assertDictEqual(x.info(), self.conn.info()) - - def test_channel_errors(self): - - class MyTransport(Transport): - channel_errors = (KeyError, ValueError) - - conn = Connection(transport=MyTransport) - self.assertTupleEqual(conn.channel_errors, (KeyError, ValueError)) - - def test_connection_errors(self): - - class MyTransport(Transport): - connection_errors = (KeyError, ValueError) - - conn = Connection(transport=MyTransport) - self.assertTupleEqual(conn.connection_errors, (KeyError, ValueError)) - - -class test_Connection_with_transport_options(Case): - - transport_options = {'pool_recycler': 3600, 'echo': True} - - def setUp(self): - self.conn = Connection(port=5672, transport=Transport, - transport_options=self.transport_options) - - def test_establish_connection(self): - conn = self.conn - self.assertEqual(conn.transport_options, self.transport_options) - - -class xResource(Resource): - - def setup(self): - pass - - -class ResourceCase(Case): - abstract = True - - def create_resource(self, limit, preload): - raise NotImplementedError('subclass responsibility') - - def assertState(self, P, avail, dirty): - self.assertEqual(P._resource.qsize(), avail) - self.assertEqual(len(P._dirty), dirty) - - def test_setup(self): - if self.abstract: - with self.assertRaises(NotImplementedError): - Resource() - - def test_acquire__release(self): - if self.abstract: - return - P = self.create_resource(10, 0) - self.assertState(P, 10, 0) - chans = [P.acquire() for _ in range(10)] - self.assertState(P, 0, 10) - with self.assertRaises(P.LimitExceeded): - P.acquire() - chans.pop().release() - self.assertState(P, 1, 9) - [chan.release() for chan in chans] - self.assertState(P, 10, 0) - - def test_acquire_prepare_raises(self): - if self.abstract: - return - P = self.create_resource(10, 0) - - self.assertEqual(len(P._resource.queue), 10) - P.prepare = Mock() - P.prepare.side_effect = IOError() - with self.assertRaises(IOError): - P.acquire(block=True) - self.assertEqual(len(P._resource.queue), 10) - - def test_acquire_no_limit(self): - if self.abstract: - return - P = self.create_resource(None, 0) - P.acquire().release() - - def test_replace_when_limit(self): - if self.abstract: - return - P = self.create_resource(10, 0) - r = P.acquire() - P._dirty = Mock() - P.close_resource = Mock() - - P.replace(r) - P._dirty.discard.assert_called_with(r) - P.close_resource.assert_called_with(r) - - def test_replace_no_limit(self): - if self.abstract: - return - P = self.create_resource(None, 0) - r = P.acquire() - P._dirty = Mock() - P.close_resource = Mock() - - P.replace(r) - self.assertFalse(P._dirty.discard.called) - P.close_resource.assert_called_with(r) - - def test_interface_prepare(self): - if not self.abstract: - return - x = xResource() - self.assertEqual(x.prepare(10), 10) - - def test_force_close_all_handles_AttributeError(self): - if self.abstract: - return - P = self.create_resource(10, 10) - cr = P.collect_resource = Mock() - cr.side_effect = AttributeError('x') - - P.acquire() - self.assertTrue(P._dirty) - - P.force_close_all() - - def test_force_close_all_no_mutex(self): - if self.abstract: - return - P = self.create_resource(10, 10) - P.close_resource = Mock() - - m = P._resource = Mock() - m.mutex = None - m.queue.pop.side_effect = IndexError - - P.force_close_all() - - def test_add_when_empty(self): - if self.abstract: - return - P = self.create_resource(None, None) - P._resource.queue[:] = [] - self.assertFalse(P._resource.queue) - P._add_when_empty() - self.assertTrue(P._resource.queue) - - -class test_ConnectionPool(ResourceCase): - abstract = False - - def create_resource(self, limit, preload): - return Connection(port=5672, transport=Transport).Pool(limit, preload) - - def test_setup(self): - P = self.create_resource(10, 2) - q = P._resource.queue - self.assertIsNotNone(q[0]._connection) - self.assertIsNotNone(q[1]._connection) - self.assertIsNone(q[2]()._connection) - - def test_acquire_raises_evaluated(self): - P = self.create_resource(1, 0) - # evaluate the connection first - r = P.acquire() - r.release() - P.prepare = Mock() - P.prepare.side_effect = MemoryError() - P.release = Mock() - with self.assertRaises(MemoryError): - with P.acquire(): - assert False - P.release.assert_called_with(r) - - def test_release_no__debug(self): - P = self.create_resource(10, 2) - R = Mock() - R._debug.side_effect = AttributeError() - P.release_resource(R) - - def test_setup_no_limit(self): - P = self.create_resource(None, None) - self.assertFalse(P._resource.queue) - self.assertIsNone(P.limit) - - def test_prepare_not_callable(self): - P = self.create_resource(None, None) - conn = Connection('memory://') - self.assertIs(P.prepare(conn), conn) - - def test_acquire_channel(self): - P = self.create_resource(10, 0) - with P.acquire_channel() as (conn, channel): - self.assertIs(channel, conn.default_channel) - - -class test_ChannelPool(ResourceCase): - abstract = False - - def create_resource(self, limit, preload): - return Connection(port=5672, transport=Transport) \ - .ChannelPool(limit, preload) - - def test_setup(self): - P = self.create_resource(10, 2) - q = P._resource.queue - self.assertTrue(q[0].basic_consume) - self.assertTrue(q[1].basic_consume) - with self.assertRaises(AttributeError): - getattr(q[2], 'basic_consume') - - def test_setup_no_limit(self): - P = self.create_resource(None, None) - self.assertFalse(P._resource.queue) - self.assertIsNone(P.limit) - - def test_prepare_not_callable(self): - P = self.create_resource(10, 0) - conn = Connection('memory://') - chan = conn.default_channel - self.assertIs(P.prepare(chan), chan) diff --git a/awx/lib/site-packages/kombu/tests/test_entities.py b/awx/lib/site-packages/kombu/tests/test_entities.py deleted file mode 100644 index ef7591a7b7..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_entities.py +++ /dev/null @@ -1,366 +0,0 @@ -from __future__ import absolute_import - -import pickle - -from kombu import Connection, Exchange, Producer, Queue, binding -from kombu.exceptions import NotBoundError - -from .case import Case, Mock, call -from .mocks import Transport - - -def get_conn(): - return Connection(transport=Transport) - - -class test_binding(Case): - - def test_constructor(self): - x = binding( - Exchange('foo'), 'rkey', - arguments={'barg': 'bval'}, - unbind_arguments={'uarg': 'uval'}, - ) - self.assertEqual(x.exchange, Exchange('foo')) - self.assertEqual(x.routing_key, 'rkey') - self.assertDictEqual(x.arguments, {'barg': 'bval'}) - self.assertDictEqual(x.unbind_arguments, {'uarg': 'uval'}) - - def test_declare(self): - chan = get_conn().channel() - x = binding(Exchange('foo'), 'rkey') - x.declare(chan) - self.assertIn('exchange_declare', chan) - - def test_declare_no_exchange(self): - chan = get_conn().channel() - x = binding() - x.declare(chan) - self.assertNotIn('exchange_declare', chan) - - def test_bind(self): - chan = get_conn().channel() - x = binding(Exchange('foo')) - x.bind(Exchange('bar')(chan)) - self.assertIn('exchange_bind', chan) - - def test_unbind(self): - chan = get_conn().channel() - x = binding(Exchange('foo')) - x.unbind(Exchange('bar')(chan)) - self.assertIn('exchange_unbind', chan) - - def test_repr(self): - b = binding(Exchange('foo'), 'rkey') - self.assertIn('foo', repr(b)) - self.assertIn('rkey', repr(b)) - - -class test_Exchange(Case): - - def test_bound(self): - exchange = Exchange('foo', 'direct') - self.assertFalse(exchange.is_bound) - self.assertIn('<unbound', repr(exchange)) - - chan = get_conn().channel() - bound = exchange.bind(chan) - self.assertTrue(bound.is_bound) - self.assertIs(bound.channel, chan) - self.assertIn('bound to chan:%r' % (chan.channel_id, ), - repr(bound)) - - def test_hash(self): - self.assertEqual(hash(Exchange('a')), hash(Exchange('a'))) - self.assertNotEqual(hash(Exchange('a')), hash(Exchange('b'))) - - def test_can_cache_declaration(self): - self.assertTrue(Exchange('a', durable=True).can_cache_declaration) - self.assertTrue(Exchange('a', durable=False).can_cache_declaration) - - def test_pickle(self): - e1 = Exchange('foo', 'direct') - e2 = pickle.loads(pickle.dumps(e1)) - self.assertEqual(e1, e2) - - def test_eq(self): - e1 = Exchange('foo', 'direct') - e2 = Exchange('foo', 'direct') - self.assertEqual(e1, e2) - - e3 = Exchange('foo', 'topic') - self.assertNotEqual(e1, e3) - - self.assertEqual(e1.__eq__(True), NotImplemented) - - def test_revive(self): - exchange = Exchange('foo', 'direct') - conn = get_conn() - chan = conn.channel() - - # reviving unbound channel is a noop. - exchange.revive(chan) - self.assertFalse(exchange.is_bound) - self.assertIsNone(exchange._channel) - - bound = exchange.bind(chan) - self.assertTrue(bound.is_bound) - self.assertIs(bound.channel, chan) - - chan2 = conn.channel() - bound.revive(chan2) - self.assertTrue(bound.is_bound) - self.assertIs(bound._channel, chan2) - - def test_assert_is_bound(self): - exchange = Exchange('foo', 'direct') - with self.assertRaises(NotBoundError): - exchange.declare() - conn = get_conn() - - chan = conn.channel() - exchange.bind(chan).declare() - self.assertIn('exchange_declare', chan) - - def test_set_transient_delivery_mode(self): - exc = Exchange('foo', 'direct', delivery_mode='transient') - self.assertEqual(exc.delivery_mode, Exchange.TRANSIENT_DELIVERY_MODE) - - def test_set_passive_mode(self): - exc = Exchange('foo', 'direct', passive=True) - self.assertTrue(exc.passive) - - def test_set_persistent_delivery_mode(self): - exc = Exchange('foo', 'direct', delivery_mode='persistent') - self.assertEqual(exc.delivery_mode, Exchange.PERSISTENT_DELIVERY_MODE) - - def test_bind_at_instantiation(self): - self.assertTrue(Exchange('foo', channel=get_conn().channel()).is_bound) - - def test_create_message(self): - chan = get_conn().channel() - Exchange('foo', channel=chan).Message({'foo': 'bar'}) - self.assertIn('prepare_message', chan) - - def test_publish(self): - chan = get_conn().channel() - Exchange('foo', channel=chan).publish('the quick brown fox') - self.assertIn('basic_publish', chan) - - def test_delete(self): - chan = get_conn().channel() - Exchange('foo', channel=chan).delete() - self.assertIn('exchange_delete', chan) - - def test__repr__(self): - b = Exchange('foo', 'topic') - self.assertIn('foo(topic)', repr(b)) - self.assertIn('Exchange', repr(b)) - - def test_bind_to(self): - chan = get_conn().channel() - foo = Exchange('foo', 'topic') - bar = Exchange('bar', 'topic') - foo(chan).bind_to(bar) - self.assertIn('exchange_bind', chan) - - def test_bind_to_by_name(self): - chan = get_conn().channel() - foo = Exchange('foo', 'topic') - foo(chan).bind_to('bar') - self.assertIn('exchange_bind', chan) - - def test_unbind_from(self): - chan = get_conn().channel() - foo = Exchange('foo', 'topic') - bar = Exchange('bar', 'topic') - foo(chan).unbind_from(bar) - self.assertIn('exchange_unbind', chan) - - def test_unbind_from_by_name(self): - chan = get_conn().channel() - foo = Exchange('foo', 'topic') - foo(chan).unbind_from('bar') - self.assertIn('exchange_unbind', chan) - - -class test_Queue(Case): - - def setUp(self): - self.exchange = Exchange('foo', 'direct') - - def test_hash(self): - self.assertEqual(hash(Queue('a')), hash(Queue('a'))) - self.assertNotEqual(hash(Queue('a')), hash(Queue('b'))) - - def test_repr_with_bindings(self): - ex = Exchange('foo') - x = Queue('foo', bindings=[ex.binding('A'), ex.binding('B')]) - self.assertTrue(repr(x)) - - def test_anonymous(self): - chan = Mock() - x = Queue(bindings=[binding(Exchange('foo'), 'rkey')]) - chan.queue_declare.return_value = 'generated', 0, 0 - xx = x(chan) - xx.declare() - self.assertEqual(xx.name, 'generated') - - def test_basic_get__accept_disallowed(self): - conn = Connection('memory://') - q = Queue('foo', exchange=self.exchange) - p = Producer(conn) - p.publish( - {'complex': object()}, - declare=[q], exchange=self.exchange, serializer='pickle', - ) - - message = q(conn).get(no_ack=True) - self.assertIsNotNone(message) - - with self.assertRaises(q.ContentDisallowed): - message.decode() - - def test_basic_get__accept_allowed(self): - conn = Connection('memory://') - q = Queue('foo', exchange=self.exchange) - p = Producer(conn) - p.publish( - {'complex': object()}, - declare=[q], exchange=self.exchange, serializer='pickle', - ) - - message = q(conn).get(accept=['pickle'], no_ack=True) - self.assertIsNotNone(message) - - payload = message.decode() - self.assertTrue(payload['complex']) - - def test_when_bound_but_no_exchange(self): - q = Queue('a') - q.exchange = None - self.assertIsNone(q.when_bound()) - - def test_declare_but_no_exchange(self): - q = Queue('a') - q.queue_declare = Mock() - q.queue_bind = Mock() - q.exchange = None - - q.declare() - q.queue_declare.assert_called_with(False, passive=False) - - def test_bind_to_when_name(self): - chan = Mock() - q = Queue('a') - q(chan).bind_to('ex') - self.assertTrue(chan.queue_bind.called) - - def test_get_when_no_m2p(self): - chan = Mock() - q = Queue('a')(chan) - chan.message_to_python = None - self.assertTrue(q.get()) - - def test_multiple_bindings(self): - chan = Mock() - q = Queue('mul', [ - binding(Exchange('mul1'), 'rkey1'), - binding(Exchange('mul2'), 'rkey2'), - binding(Exchange('mul3'), 'rkey3'), - ]) - q(chan).declare() - self.assertIn( - call( - nowait=False, - exchange='mul1', - auto_delete=False, - passive=False, - arguments=None, - type='direct', - durable=True, - ), - chan.exchange_declare.call_args_list, - ) - - def test_can_cache_declaration(self): - self.assertTrue(Queue('a', durable=True).can_cache_declaration) - self.assertTrue(Queue('a', durable=False).can_cache_declaration) - - def test_eq(self): - q1 = Queue('xxx', Exchange('xxx', 'direct'), 'xxx') - q2 = Queue('xxx', Exchange('xxx', 'direct'), 'xxx') - self.assertEqual(q1, q2) - self.assertEqual(q1.__eq__(True), NotImplemented) - - q3 = Queue('yyy', Exchange('xxx', 'direct'), 'xxx') - self.assertNotEqual(q1, q3) - - def test_exclusive_implies_auto_delete(self): - self.assertTrue( - Queue('foo', self.exchange, exclusive=True).auto_delete, - ) - - def test_binds_at_instantiation(self): - self.assertTrue(Queue('foo', self.exchange, - channel=get_conn().channel()).is_bound) - - def test_also_binds_exchange(self): - chan = get_conn().channel() - b = Queue('foo', self.exchange) - self.assertFalse(b.is_bound) - self.assertFalse(b.exchange.is_bound) - b = b.bind(chan) - self.assertTrue(b.is_bound) - self.assertTrue(b.exchange.is_bound) - self.assertIs(b.channel, b.exchange.channel) - self.assertIsNot(b.exchange, self.exchange) - - def test_declare(self): - chan = get_conn().channel() - b = Queue('foo', self.exchange, 'foo', channel=chan) - self.assertTrue(b.is_bound) - b.declare() - self.assertIn('exchange_declare', chan) - self.assertIn('queue_declare', chan) - self.assertIn('queue_bind', chan) - - def test_get(self): - b = Queue('foo', self.exchange, 'foo', channel=get_conn().channel()) - b.get() - self.assertIn('basic_get', b.channel) - - def test_purge(self): - b = Queue('foo', self.exchange, 'foo', channel=get_conn().channel()) - b.purge() - self.assertIn('queue_purge', b.channel) - - def test_consume(self): - b = Queue('foo', self.exchange, 'foo', channel=get_conn().channel()) - b.consume('fifafo', None) - self.assertIn('basic_consume', b.channel) - - def test_cancel(self): - b = Queue('foo', self.exchange, 'foo', channel=get_conn().channel()) - b.cancel('fifafo') - self.assertIn('basic_cancel', b.channel) - - def test_delete(self): - b = Queue('foo', self.exchange, 'foo', channel=get_conn().channel()) - b.delete() - self.assertIn('queue_delete', b.channel) - - def test_queue_unbind(self): - b = Queue('foo', self.exchange, 'foo', channel=get_conn().channel()) - b.queue_unbind() - self.assertIn('queue_unbind', b.channel) - - def test_as_dict(self): - q = Queue('foo', self.exchange, 'rk') - d = q.as_dict(recurse=True) - self.assertEqual(d['exchange']['name'], self.exchange.name) - - def test__repr__(self): - b = Queue('foo', self.exchange, 'foo') - self.assertIn('foo', repr(b)) - self.assertIn('Queue', repr(b)) diff --git a/awx/lib/site-packages/kombu/tests/test_log.py b/awx/lib/site-packages/kombu/tests/test_log.py deleted file mode 100644 index bd1242c0be..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_log.py +++ /dev/null @@ -1,165 +0,0 @@ -from __future__ import absolute_import - -import logging -import sys - -from kombu.log import ( - NullHandler, - get_logger, - get_loglevel, - safeify_format, - Log, - LogMixin, - setup_logging, -) - -from .case import Case, Mock, patch - - -class test_NullHandler(Case): - - def test_emit(self): - h = NullHandler() - h.emit('record') - - -class test_get_logger(Case): - - def test_when_string(self): - l = get_logger('foo') - - self.assertIs(l, logging.getLogger('foo')) - h1 = l.handlers[0] - self.assertIsInstance(h1, NullHandler) - - def test_when_logger(self): - l = get_logger(logging.getLogger('foo')) - h1 = l.handlers[0] - self.assertIsInstance(h1, NullHandler) - - def test_with_custom_handler(self): - l = logging.getLogger('bar') - handler = NullHandler() - l.addHandler(handler) - - l = get_logger('bar') - self.assertIs(l.handlers[0], handler) - - def test_get_loglevel(self): - self.assertEqual(get_loglevel('DEBUG'), logging.DEBUG) - self.assertEqual(get_loglevel('ERROR'), logging.ERROR) - self.assertEqual(get_loglevel(logging.INFO), logging.INFO) - - -class test_safe_format(Case): - - def test_formatting(self): - fmt = 'The %r jumped %x over the %s' - args = ['frog', 'foo', 'elephant'] - - res = list(safeify_format(fmt, args)) - self.assertListEqual(res, ["'frog'", 'foo', 'elephant']) - - -class test_LogMixin(Case): - - def setUp(self): - self.log = Log('Log', Mock()) - self.logger = self.log.logger - - def test_debug(self): - self.log.debug('debug') - self.logger.log.assert_called_with(logging.DEBUG, 'Log - debug') - - def test_info(self): - self.log.info('info') - self.logger.log.assert_called_with(logging.INFO, 'Log - info') - - def test_warning(self): - self.log.warn('warning') - self.logger.log.assert_called_with(logging.WARN, 'Log - warning') - - def test_error(self): - self.log.error('error', exc_info='exc') - self.logger.log.assert_called_with( - logging.ERROR, 'Log - error', exc_info='exc', - ) - - def test_critical(self): - self.log.critical('crit', exc_info='exc') - self.logger.log.assert_called_with( - logging.CRITICAL, 'Log - crit', exc_info='exc', - ) - - def test_error_when_DISABLE_TRACEBACKS(self): - from kombu import log - log.DISABLE_TRACEBACKS = True - try: - self.log.error('error') - self.logger.log.assert_called_with(logging.ERROR, 'Log - error') - finally: - log.DISABLE_TRACEBACKS = False - - def test_get_loglevel(self): - self.assertEqual(self.log.get_loglevel('DEBUG'), logging.DEBUG) - self.assertEqual(self.log.get_loglevel('ERROR'), logging.ERROR) - self.assertEqual(self.log.get_loglevel(logging.INFO), logging.INFO) - - def test_is_enabled_for(self): - self.logger.isEnabledFor.return_value = True - self.assertTrue(self.log.is_enabled_for('DEBUG')) - self.logger.isEnabledFor.assert_called_with(logging.DEBUG) - - def test_LogMixin_get_logger(self): - self.assertIs(LogMixin().get_logger(), - logging.getLogger('LogMixin')) - - def test_Log_get_logger(self): - self.assertIs(Log('test_Log').get_logger(), - logging.getLogger('test_Log')) - - def test_log_when_not_enabled(self): - self.logger.isEnabledFor.return_value = False - self.log.debug('debug') - self.assertFalse(self.logger.log.called) - - def test_log_with_format(self): - self.log.debug('Host %r removed', 'example.com') - self.logger.log.assert_called_with( - logging.DEBUG, 'Log - Host %s removed', "'example.com'", - ) - - -class test_setup_logging(Case): - - @patch('logging.getLogger') - def test_set_up_default_values(self, getLogger): - logger = logging.getLogger.return_value = Mock() - logger.handlers = [] - setup_logging() - - logger.setLevel.assert_called_with(logging.ERROR) - self.assertTrue(logger.addHandler.called) - ah_args, _ = logger.addHandler.call_args - handler = ah_args[0] - self.assertIsInstance(handler, logging.StreamHandler) - self.assertIs(handler.stream, sys.__stderr__) - - @patch('logging.getLogger') - @patch('kombu.log.WatchedFileHandler') - def test_setup_custom_values(self, getLogger, WatchedFileHandler): - logger = logging.getLogger.return_value = Mock() - logger.handlers = [] - setup_logging(loglevel=logging.DEBUG, logfile='/var/logfile') - - logger.setLevel.assert_called_with(logging.DEBUG) - self.assertTrue(logger.addHandler.called) - self.assertTrue(WatchedFileHandler.called) - - @patch('logging.getLogger') - def test_logger_already_setup(self, getLogger): - logger = logging.getLogger.return_value = Mock() - logger.handlers = [Mock()] - setup_logging() - - self.assertFalse(logger.setLevel.called) diff --git a/awx/lib/site-packages/kombu/tests/test_messaging.py b/awx/lib/site-packages/kombu/tests/test_messaging.py deleted file mode 100644 index a64ebd53a0..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_messaging.py +++ /dev/null @@ -1,611 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import anyjson -import pickle - -from collections import defaultdict - -from kombu import Connection, Consumer, Producer, Exchange, Queue -from kombu.exceptions import MessageStateError -from kombu.utils import ChannelPromise - -from .case import Case, Mock, patch -from .mocks import Transport - - -class test_Producer(Case): - - def setUp(self): - self.exchange = Exchange('foo', 'direct') - self.connection = Connection(transport=Transport) - self.connection.connect() - self.assertTrue(self.connection.connection.connected) - self.assertFalse(self.exchange.is_bound) - - def test_repr(self): - p = Producer(self.connection) - self.assertTrue(repr(p)) - - def test_pickle(self): - chan = Mock() - producer = Producer(chan, serializer='pickle') - p2 = pickle.loads(pickle.dumps(producer)) - self.assertEqual(p2.serializer, producer.serializer) - - def test_no_channel(self): - p = Producer(None) - self.assertFalse(p._channel) - - @patch('kombu.messaging.maybe_declare') - def test_maybe_declare(self, maybe_declare): - p = self.connection.Producer() - q = Queue('foo') - p.maybe_declare(q) - maybe_declare.assert_called_with(q, p.channel, False) - - @patch('kombu.common.maybe_declare') - def test_maybe_declare_when_entity_false(self, maybe_declare): - p = self.connection.Producer() - p.maybe_declare(None) - self.assertFalse(maybe_declare.called) - - def test_auto_declare(self): - channel = self.connection.channel() - p = Producer(channel, self.exchange, auto_declare=True) - self.assertIsNot(p.exchange, self.exchange, - 'creates Exchange clone at bind') - self.assertTrue(p.exchange.is_bound) - self.assertIn('exchange_declare', channel, - 'auto_declare declares exchange') - - def test_manual_declare(self): - channel = self.connection.channel() - p = Producer(channel, self.exchange, auto_declare=False) - self.assertTrue(p.exchange.is_bound) - self.assertNotIn('exchange_declare', channel, - 'auto_declare=False does not declare exchange') - p.declare() - self.assertIn('exchange_declare', channel, - 'p.declare() declares exchange') - - def test_prepare(self): - message = {'the quick brown fox': 'jumps over the lazy dog'} - channel = self.connection.channel() - p = Producer(channel, self.exchange, serializer='json') - m, ctype, cencoding = p._prepare(message, headers={}) - self.assertDictEqual(message, anyjson.loads(m)) - self.assertEqual(ctype, 'application/json') - self.assertEqual(cencoding, 'utf-8') - - def test_prepare_compression(self): - message = {'the quick brown fox': 'jumps over the lazy dog'} - channel = self.connection.channel() - p = Producer(channel, self.exchange, serializer='json') - headers = {} - m, ctype, cencoding = p._prepare(message, compression='zlib', - headers=headers) - self.assertEqual(ctype, 'application/json') - self.assertEqual(cencoding, 'utf-8') - self.assertEqual(headers['compression'], 'application/x-gzip') - import zlib - self.assertEqual( - anyjson.loads(zlib.decompress(m).decode('utf-8')), - message, - ) - - def test_prepare_custom_content_type(self): - message = 'the quick brown fox'.encode('utf-8') - channel = self.connection.channel() - p = Producer(channel, self.exchange, serializer='json') - m, ctype, cencoding = p._prepare(message, content_type='custom') - self.assertEqual(m, message) - self.assertEqual(ctype, 'custom') - self.assertEqual(cencoding, 'binary') - m, ctype, cencoding = p._prepare(message, content_type='custom', - content_encoding='alien') - self.assertEqual(m, message) - self.assertEqual(ctype, 'custom') - self.assertEqual(cencoding, 'alien') - - def test_prepare_is_already_unicode(self): - message = 'the quick brown fox' - channel = self.connection.channel() - p = Producer(channel, self.exchange, serializer='json') - m, ctype, cencoding = p._prepare(message, content_type='text/plain') - self.assertEqual(m, message.encode('utf-8')) - self.assertEqual(ctype, 'text/plain') - self.assertEqual(cencoding, 'utf-8') - m, ctype, cencoding = p._prepare(message, content_type='text/plain', - content_encoding='utf-8') - self.assertEqual(m, message.encode('utf-8')) - self.assertEqual(ctype, 'text/plain') - self.assertEqual(cencoding, 'utf-8') - - def test_publish_with_Exchange_instance(self): - p = self.connection.Producer() - p.channel = Mock() - p.publish('hello', exchange=Exchange('foo'), delivery_mode='transient') - self.assertEqual( - p._channel.basic_publish.call_args[1]['exchange'], 'foo', - ) - - def test_set_on_return(self): - chan = Mock() - chan.events = defaultdict(Mock) - p = Producer(ChannelPromise(lambda: chan), on_return='on_return') - p.channel - chan.events['basic_return'].add.assert_called_with('on_return') - - def test_publish_retry_calls_ensure(self): - p = Producer(Mock()) - p._connection = Mock() - ensure = p.connection.ensure = Mock() - p.publish('foo', exchange='foo', retry=True) - self.assertTrue(ensure.called) - - def test_publish_retry_with_declare(self): - p = self.connection.Producer() - p.maybe_declare = Mock() - p.connection.ensure = Mock() - ex = Exchange('foo') - p._publish('hello', 0, '', '', {}, {}, 'rk', 0, 0, ex, declare=[ex]) - p.maybe_declare.assert_called_with(ex) - - def test_revive_when_channel_is_connection(self): - p = self.connection.Producer() - p.exchange = Mock() - new_conn = Connection('memory://') - defchan = new_conn.default_channel - p.revive(new_conn) - - self.assertIs(p.channel, defchan) - p.exchange.revive.assert_called_with(defchan) - - def test_enter_exit(self): - p = self.connection.Producer() - p.release = Mock() - - self.assertIs(p.__enter__(), p) - p.__exit__() - p.release.assert_called_with() - - def test_connection_property_handles_AttributeError(self): - p = self.connection.Producer() - p.channel = object() - p.__connection__ = None - self.assertIsNone(p.connection) - - def test_publish(self): - channel = self.connection.channel() - p = Producer(channel, self.exchange, serializer='json') - message = {'the quick brown fox': 'jumps over the lazy dog'} - ret = p.publish(message, routing_key='process') - self.assertIn('prepare_message', channel) - self.assertIn('basic_publish', channel) - - m, exc, rkey = ret - self.assertDictEqual(message, anyjson.loads(m['body'])) - self.assertDictContainsSubset({'content_type': 'application/json', - 'content_encoding': 'utf-8', - 'priority': 0}, m) - self.assertDictContainsSubset({'delivery_mode': 2}, m['properties']) - self.assertEqual(exc, p.exchange.name) - self.assertEqual(rkey, 'process') - - def test_no_exchange(self): - chan = self.connection.channel() - p = Producer(chan) - self.assertFalse(p.exchange.name) - - def test_revive(self): - chan = self.connection.channel() - p = Producer(chan) - chan2 = self.connection.channel() - p.revive(chan2) - self.assertIs(p.channel, chan2) - self.assertIs(p.exchange.channel, chan2) - - def test_on_return(self): - chan = self.connection.channel() - - def on_return(exception, exchange, routing_key, message): - pass - - p = Producer(chan, on_return=on_return) - self.assertTrue(on_return in chan.events['basic_return']) - self.assertTrue(p.on_return) - - -class test_Consumer(Case): - - def setUp(self): - self.connection = Connection(transport=Transport) - self.connection.connect() - self.assertTrue(self.connection.connection.connected) - self.exchange = Exchange('foo', 'direct') - - def test_accept(self): - a = Consumer(self.connection) - self.assertIsNone(a.accept) - b = Consumer(self.connection, accept=['json', 'pickle']) - self.assertSetEqual( - b.accept, - set(['application/json', 'application/x-python-serialize']), - ) - c = Consumer(self.connection, accept=b.accept) - self.assertSetEqual(b.accept, c.accept) - - def test_enter_exit_cancel_raises(self): - c = Consumer(self.connection) - c.cancel = Mock(name='Consumer.cancel') - c.cancel.side_effect = KeyError('foo') - with c: - pass - c.cancel.assert_called_with() - - def test_receive_callback_accept(self): - message = Mock(name='Message') - message.errors = [] - callback = Mock(name='on_message') - c = Consumer(self.connection, accept=['json'], on_message=callback) - c.on_decode_error = None - c.channel = Mock(name='channel') - c.channel.message_to_python = None - - c._receive_callback(message) - callback.assert_called_with(message) - self.assertSetEqual(message.accept, c.accept) - - def test_accept__content_disallowed(self): - conn = Connection('memory://') - q = Queue('foo', exchange=self.exchange) - p = conn.Producer() - p.publish( - {'complex': object()}, - declare=[q], exchange=self.exchange, serializer='pickle', - ) - - callback = Mock(name='callback') - with conn.Consumer(queues=[q], callbacks=[callback]) as consumer: - with self.assertRaises(consumer.ContentDisallowed): - conn.drain_events(timeout=1) - self.assertFalse(callback.called) - - def test_accept__content_allowed(self): - conn = Connection('memory://') - q = Queue('foo', exchange=self.exchange) - p = conn.Producer() - p.publish( - {'complex': object()}, - declare=[q], exchange=self.exchange, serializer='pickle', - ) - - callback = Mock(name='callback') - with conn.Consumer(queues=[q], accept=['pickle'], - callbacks=[callback]): - conn.drain_events(timeout=1) - self.assertTrue(callback.called) - body, message = callback.call_args[0] - self.assertTrue(body['complex']) - - def test_set_no_channel(self): - c = Consumer(None) - self.assertIsNone(c.channel) - c.revive(Mock()) - self.assertTrue(c.channel) - - def test_set_no_ack(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - consumer = Consumer(channel, queue, auto_declare=True, no_ack=True) - self.assertTrue(consumer.no_ack) - - def test_add_queue_when_auto_declare(self): - consumer = self.connection.Consumer(auto_declare=True) - q = Mock() - q.return_value = q - consumer.add_queue(q) - self.assertIn(q, consumer.queues) - q.declare.assert_called_with() - - def test_add_queue_when_not_auto_declare(self): - consumer = self.connection.Consumer(auto_declare=False) - q = Mock() - q.return_value = q - consumer.add_queue(q) - self.assertIn(q, consumer.queues) - self.assertFalse(q.declare.call_count) - - def test_consume_without_queues_returns(self): - consumer = self.connection.Consumer() - consumer.queues[:] = [] - self.assertIsNone(consumer.consume()) - - def test_consuming_from(self): - consumer = self.connection.Consumer() - consumer.queues[:] = [Queue('a'), Queue('b'), Queue('d')] - consumer._active_tags = {'a': 1, 'b': 2} - - self.assertFalse(consumer.consuming_from(Queue('c'))) - self.assertFalse(consumer.consuming_from('c')) - self.assertFalse(consumer.consuming_from(Queue('d'))) - self.assertFalse(consumer.consuming_from('d')) - self.assertTrue(consumer.consuming_from(Queue('a'))) - self.assertTrue(consumer.consuming_from(Queue('b'))) - self.assertTrue(consumer.consuming_from('b')) - - def test_receive_callback_without_m2p(self): - channel = self.connection.channel() - c = channel.Consumer() - m2p = getattr(channel, 'message_to_python') - channel.message_to_python = None - try: - message = Mock() - message.errors = [] - message.decode.return_value = 'Hello' - recv = c.receive = Mock() - c._receive_callback(message) - recv.assert_called_with('Hello', message) - finally: - channel.message_to_python = m2p - - def test_set_callbacks(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - callbacks = [lambda x, y: x, - lambda x, y: x] - consumer = Consumer(channel, queue, auto_declare=True, - callbacks=callbacks) - self.assertEqual(consumer.callbacks, callbacks) - - def test_auto_declare(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - consumer = Consumer(channel, queue, auto_declare=True) - consumer.consume() - consumer.consume() # twice is a noop - self.assertIsNot(consumer.queues[0], queue) - self.assertTrue(consumer.queues[0].is_bound) - self.assertTrue(consumer.queues[0].exchange.is_bound) - self.assertIsNot(consumer.queues[0].exchange, self.exchange) - - for meth in ('exchange_declare', - 'queue_declare', - 'queue_bind', - 'basic_consume'): - self.assertIn(meth, channel) - self.assertEqual(channel.called.count('basic_consume'), 1) - self.assertTrue(consumer._active_tags) - - consumer.cancel_by_queue(queue.name) - consumer.cancel_by_queue(queue.name) - self.assertFalse(consumer._active_tags) - - def test_manual_declare(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - consumer = Consumer(channel, queue, auto_declare=False) - self.assertIsNot(consumer.queues[0], queue) - self.assertTrue(consumer.queues[0].is_bound) - self.assertTrue(consumer.queues[0].exchange.is_bound) - self.assertIsNot(consumer.queues[0].exchange, self.exchange) - - for meth in ('exchange_declare', - 'queue_declare', - 'basic_consume'): - self.assertNotIn(meth, channel) - - consumer.declare() - for meth in ('exchange_declare', - 'queue_declare', - 'queue_bind'): - self.assertIn(meth, channel) - self.assertNotIn('basic_consume', channel) - - consumer.consume() - self.assertIn('basic_consume', channel) - - def test_consume__cancel(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - consumer = Consumer(channel, queue, auto_declare=True) - consumer.consume() - consumer.cancel() - self.assertIn('basic_cancel', channel) - self.assertFalse(consumer._active_tags) - - def test___enter____exit__(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - consumer = Consumer(channel, queue, auto_declare=True) - context = consumer.__enter__() - self.assertIs(context, consumer) - self.assertTrue(consumer._active_tags) - res = consumer.__exit__(None, None, None) - self.assertFalse(res) - self.assertIn('basic_cancel', channel) - self.assertFalse(consumer._active_tags) - - def test_flow(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - consumer = Consumer(channel, queue, auto_declare=True) - consumer.flow(False) - self.assertIn('flow', channel) - - def test_qos(self): - channel = self.connection.channel() - queue = Queue('qname', self.exchange, 'rkey') - consumer = Consumer(channel, queue, auto_declare=True) - consumer.qos(30, 10, False) - self.assertIn('basic_qos', channel) - - def test_purge(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - b2 = Queue('qname2', self.exchange, 'rkey') - b3 = Queue('qname3', self.exchange, 'rkey') - b4 = Queue('qname4', self.exchange, 'rkey') - consumer = Consumer(channel, [b1, b2, b3, b4], auto_declare=True) - consumer.purge() - self.assertEqual(channel.called.count('queue_purge'), 4) - - def test_multiple_queues(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - b2 = Queue('qname2', self.exchange, 'rkey') - b3 = Queue('qname3', self.exchange, 'rkey') - b4 = Queue('qname4', self.exchange, 'rkey') - consumer = Consumer(channel, [b1, b2, b3, b4]) - consumer.consume() - self.assertEqual(channel.called.count('exchange_declare'), 4) - self.assertEqual(channel.called.count('queue_declare'), 4) - self.assertEqual(channel.called.count('queue_bind'), 4) - self.assertEqual(channel.called.count('basic_consume'), 4) - self.assertEqual(len(consumer._active_tags), 4) - consumer.cancel() - self.assertEqual(channel.called.count('basic_cancel'), 4) - self.assertFalse(len(consumer._active_tags)) - - def test_receive_callback(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - received = [] - - def callback(message_data, message): - received.append(message_data) - message.ack() - message.payload # trigger cache - - consumer.register_callback(callback) - consumer._receive_callback({'foo': 'bar'}) - - self.assertIn('basic_ack', channel) - self.assertIn('message_to_python', channel) - self.assertEqual(received[0], {'foo': 'bar'}) - - def test_basic_ack_twice(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - - def callback(message_data, message): - message.ack() - message.ack() - - consumer.register_callback(callback) - with self.assertRaises(MessageStateError): - consumer._receive_callback({'foo': 'bar'}) - - def test_basic_reject(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - - def callback(message_data, message): - message.reject() - - consumer.register_callback(callback) - consumer._receive_callback({'foo': 'bar'}) - self.assertIn('basic_reject', channel) - - def test_basic_reject_twice(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - - def callback(message_data, message): - message.reject() - message.reject() - - consumer.register_callback(callback) - with self.assertRaises(MessageStateError): - consumer._receive_callback({'foo': 'bar'}) - self.assertIn('basic_reject', channel) - - def test_basic_reject__requeue(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - - def callback(message_data, message): - message.requeue() - - consumer.register_callback(callback) - consumer._receive_callback({'foo': 'bar'}) - self.assertIn('basic_reject:requeue', channel) - - def test_basic_reject__requeue_twice(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - - def callback(message_data, message): - message.requeue() - message.requeue() - - consumer.register_callback(callback) - with self.assertRaises(MessageStateError): - consumer._receive_callback({'foo': 'bar'}) - self.assertIn('basic_reject:requeue', channel) - - def test_receive_without_callbacks_raises(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - with self.assertRaises(NotImplementedError): - consumer.receive(1, 2) - - def test_decode_error(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - consumer.channel.throw_decode_error = True - - with self.assertRaises(ValueError): - consumer._receive_callback({'foo': 'bar'}) - - def test_on_decode_error_callback(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - thrown = [] - - def on_decode_error(msg, exc): - thrown.append((msg.body, exc)) - - consumer = Consumer(channel, [b1], on_decode_error=on_decode_error) - consumer.channel.throw_decode_error = True - consumer._receive_callback({'foo': 'bar'}) - - self.assertTrue(thrown) - m, exc = thrown[0] - self.assertEqual(anyjson.loads(m), {'foo': 'bar'}) - self.assertIsInstance(exc, ValueError) - - def test_recover(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - consumer.recover() - self.assertIn('basic_recover', channel) - - def test_revive(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - consumer = Consumer(channel, [b1]) - channel2 = self.connection.channel() - consumer.revive(channel2) - self.assertIs(consumer.channel, channel2) - self.assertIs(consumer.queues[0].channel, channel2) - self.assertIs(consumer.queues[0].exchange.channel, channel2) - - def test__repr__(self): - channel = self.connection.channel() - b1 = Queue('qname1', self.exchange, 'rkey') - self.assertTrue(repr(Consumer(channel, [b1]))) - - def test_connection_property_handles_AttributeError(self): - p = self.connection.Consumer() - p.channel = object() - self.assertIsNone(p.connection) diff --git a/awx/lib/site-packages/kombu/tests/test_mixins.py b/awx/lib/site-packages/kombu/tests/test_mixins.py deleted file mode 100644 index 53c423df9b..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_mixins.py +++ /dev/null @@ -1,239 +0,0 @@ -from __future__ import absolute_import, unicode_literals - -import socket - -from kombu.mixins import ConsumerMixin - -from .case import Case, Mock, ContextMock, patch - - -def Message(body, content_type='text/plain', content_encoding='utf-8'): - m = Mock(name='Message') - m.body = body - m.content_type = content_type - m.content_encoding = content_encoding - return m - - -class Cons(ConsumerMixin): - - def __init__(self, consumers): - self.calls = Mock(name='ConsumerMixin') - self.calls.get_consumers.return_value = consumers - self.get_consumers = self.calls.get_consumers - self.on_connection_revived = self.calls.on_connection_revived - self.on_consume_ready = self.calls.on_consume_ready - self.on_consume_end = self.calls.on_consume_end - self.on_iteration = self.calls.on_iteration - self.on_decode_error = self.calls.on_decode_error - self.on_connection_error = self.calls.on_connection_error - self.extra_context = ContextMock(name='extra_context') - self.extra_context.return_value = self.extra_context - - -class test_ConsumerMixin(Case): - - def _context(self): - Acons = ContextMock(name='consumerA') - Bcons = ContextMock(name='consumerB') - c = Cons([Acons, Bcons]) - _conn = c.connection = ContextMock(name='connection') - est = c.establish_connection = Mock(name='est_connection') - est.return_value = _conn - return c, Acons, Bcons - - def test_consume(self): - c, Acons, Bcons = self._context() - c.should_stop = False - it = c.consume(no_ack=True) - next(it) - Acons.__enter__.assert_called_with() - Bcons.__enter__.assert_called_with() - c.extra_context.__enter__.assert_called_with() - self.assertTrue(c.on_consume_ready.called) - c.on_iteration.assert_called_with() - c.connection.drain_events.assert_called_with(timeout=1) - next(it) - next(it) - next(it) - c.should_stop = True - with self.assertRaises(StopIteration): - next(it) - - def test_consume_drain_raises_socket_error(self): - c, Acons, Bcons = self._context() - c.should_stop = False - it = c.consume(no_ack=True) - c.connection.drain_events.side_effect = socket.error - with self.assertRaises(socket.error): - next(it) - - def se2(*args, **kwargs): - c.should_stop = True - raise socket.error() - c.connection.drain_events.side_effect = se2 - it = c.consume(no_ack=True) - with self.assertRaises(StopIteration): - next(it) - - def test_consume_drain_raises_socket_timeout(self): - c, Acons, Bcons = self._context() - c.should_stop = False - it = c.consume(no_ack=True, timeout=1) - - def se(*args, **kwargs): - c.should_stop = True - raise socket.timeout() - c.connection.drain_events.side_effect = se - with self.assertRaises(socket.error): - next(it) - - def test_Consumer_context(self): - c, Acons, Bcons = self._context() - - with c.Consumer() as (conn, channel, consumer): - self.assertIs(conn, c.connection) - self.assertIs(channel, conn.default_channel) - c.on_connection_revived.assert_called_with() - self.assertTrue(c.get_consumers.called) - cls = c.get_consumers.call_args[0][0] - - subcons = cls() - self.assertIs(subcons.on_decode_error, c.on_decode_error) - self.assertIs(subcons.channel, conn.default_channel) - Acons.__enter__.assert_called_with() - Bcons.__enter__.assert_called_with() - c.on_consume_end.assert_called_with(conn, channel) - - -class test_ConsumerMixin_interface(Case): - - def setUp(self): - self.c = ConsumerMixin() - - def test_get_consumers(self): - with self.assertRaises(NotImplementedError): - self.c.get_consumers(Mock(), Mock()) - - def test_on_connection_revived(self): - self.assertIsNone(self.c.on_connection_revived()) - - def test_on_consume_ready(self): - self.assertIsNone(self.c.on_consume_ready( - Mock(), Mock(), [], - )) - - def test_on_consume_end(self): - self.assertIsNone(self.c.on_consume_end(Mock(), Mock())) - - def test_on_iteration(self): - self.assertIsNone(self.c.on_iteration()) - - def test_on_decode_error(self): - message = Message('foo') - with patch('kombu.mixins.error') as error: - self.c.on_decode_error(message, KeyError('foo')) - self.assertTrue(error.called) - message.ack.assert_called_with() - - def test_on_connection_error(self): - with patch('kombu.mixins.warn') as warn: - self.c.on_connection_error(KeyError('foo'), 3) - self.assertTrue(warn.called) - - def test_extra_context(self): - with self.c.extra_context(Mock(), Mock()): - pass - - def test_restart_limit(self): - self.assertTrue(self.c.restart_limit) - - def test_connection_errors(self): - conn = Mock(name='connection') - self.c.connection = conn - conn.connection_errors = (KeyError, ) - self.assertTupleEqual(self.c.connection_errors, conn.connection_errors) - conn.channel_errors = (ValueError, ) - self.assertTupleEqual(self.c.channel_errors, conn.channel_errors) - - def test__consume_from(self): - a = ContextMock(name='A') - b = ContextMock(name='B') - a.__enter__ = Mock(name='A.__enter__') - b.__enter__ = Mock(name='B.__enter__') - with self.c._consume_from(a, b): - pass - a.__enter__.assert_called_with() - b.__enter__.assert_called_with() - - def test_establish_connection(self): - conn = ContextMock(name='connection') - conn.clone.return_value = conn - self.c.connection = conn - self.c.connect_max_retries = 3 - - with self.c.establish_connection() as conn: - self.assertTrue(conn) - conn.ensure_connection.assert_called_with( - self.c.on_connection_error, 3, - ) - - def test_maybe_conn_error(self): - conn = ContextMock(name='connection') - conn.connection_errors = (KeyError, ) - conn.channel_errors = () - - self.c.connection = conn - - def raises(): - raise KeyError('foo') - self.c.maybe_conn_error(raises) - - def test_run(self): - conn = ContextMock(name='connection') - self.c.connection = conn - conn.connection_errors = (KeyError, ) - conn.channel_errors = () - consume = self.c.consume = Mock(name='c.consume') - - def se(*args, **kwargs): - self.c.should_stop = True - return [1] - self.c.should_stop = False - consume.side_effect = se - self.c.run() - - def test_run_restart_rate_limited(self): - conn = ContextMock(name='connection') - self.c.connection = conn - conn.connection_errors = (KeyError, ) - conn.channel_errors = () - consume = self.c.consume = Mock(name='c.consume') - with patch('kombu.mixins.sleep') as sleep: - counter = [0] - - def se(*args, **kwargs): - if counter[0] >= 1: - self.c.should_stop = True - counter[0] += 1 - return counter - self.c.should_stop = False - consume.side_effect = se - self.c.run() - self.assertTrue(sleep.called) - - def test_run_raises(self): - conn = ContextMock(name='connection') - self.c.connection = conn - conn.connection_errors = (KeyError, ) - conn.channel_errors = () - consume = self.c.consume = Mock(name='c.consume') - - with patch('kombu.mixins.warn') as warn: - def se_raises(*args, **kwargs): - self.c.should_stop = True - raise KeyError('foo') - self.c.should_stop = False - consume.side_effect = se_raises - self.c.run() - self.assertTrue(warn.called) diff --git a/awx/lib/site-packages/kombu/tests/test_pidbox.py b/awx/lib/site-packages/kombu/tests/test_pidbox.py deleted file mode 100644 index 357de656fb..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_pidbox.py +++ /dev/null @@ -1,287 +0,0 @@ -from __future__ import absolute_import - -import socket -import warnings - -from kombu import Connection -from kombu import pidbox -from kombu.exceptions import ContentDisallowed, InconsistencyError -from kombu.utils import uuid - -from .case import Case, Mock, patch - - -class test_Mailbox(Case): - - def _handler(self, state): - return self.stats['var'] - - def setUp(self): - - class Mailbox(pidbox.Mailbox): - - def _collect(self, *args, **kwargs): - return 'COLLECTED' - - self.mailbox = Mailbox('test_pidbox') - self.connection = Connection(transport='memory') - self.state = {'var': 1} - self.handlers = {'mymethod': self._handler} - self.bound = self.mailbox(self.connection) - self.default_chan = self.connection.channel() - self.node = self.bound.Node( - 'test_pidbox', - state=self.state, handlers=self.handlers, - channel=self.default_chan, - ) - - def test_publish_reply_ignores_InconsistencyError(self): - mailbox = pidbox.Mailbox('test_reply__collect')(self.connection) - with patch('kombu.pidbox.Producer') as Producer: - producer = Producer.return_value = Mock(name='producer') - producer.publish.side_effect = InconsistencyError() - mailbox._publish_reply( - {'foo': 'bar'}, mailbox.reply_exchange, mailbox.oid, 'foo', - ) - self.assertTrue(producer.publish.called) - - def test_reply__collect(self): - mailbox = pidbox.Mailbox('test_reply__collect')(self.connection) - exchange = mailbox.reply_exchange.name - channel = self.connection.channel() - mailbox.reply_queue(channel).declare() - - ticket = uuid() - mailbox._publish_reply({'foo': 'bar'}, exchange, mailbox.oid, ticket) - _callback_called = [False] - - def callback(body): - _callback_called[0] = True - - reply = mailbox._collect(ticket, limit=1, - callback=callback, channel=channel) - self.assertEqual(reply, [{'foo': 'bar'}]) - self.assertTrue(_callback_called[0]) - - ticket = uuid() - mailbox._publish_reply({'biz': 'boz'}, exchange, mailbox.oid, ticket) - reply = mailbox._collect(ticket, limit=1, channel=channel) - self.assertEqual(reply, [{'biz': 'boz'}]) - - mailbox._publish_reply({'foo': 'BAM'}, exchange, mailbox.oid, 'doom', - serializer='pickle') - with self.assertRaises(ContentDisallowed): - reply = mailbox._collect('doom', limit=1, channel=channel) - mailbox._publish_reply( - {'foo': 'BAMBAM'}, exchange, mailbox.oid, 'doom', - serializer='pickle', - ) - reply = mailbox._collect('doom', limit=1, channel=channel, - accept=['pickle']) - self.assertEqual(reply[0]['foo'], 'BAMBAM') - - de = mailbox.connection.drain_events = Mock() - de.side_effect = socket.timeout - mailbox._collect(ticket, limit=1, channel=channel) - - def test_constructor(self): - self.assertIsNone(self.mailbox.connection) - self.assertTrue(self.mailbox.exchange.name) - self.assertTrue(self.mailbox.reply_exchange.name) - - def test_bound(self): - bound = self.mailbox(self.connection) - self.assertIs(bound.connection, self.connection) - - def test_Node(self): - self.assertTrue(self.node.hostname) - self.assertTrue(self.node.state) - self.assertIs(self.node.mailbox, self.bound) - self.assertTrue(self.handlers) - - # No initial handlers - node2 = self.bound.Node('test_pidbox2', state=self.state) - self.assertDictEqual(node2.handlers, {}) - - def test_Node_consumer(self): - consumer1 = self.node.Consumer() - self.assertIs(consumer1.channel, self.default_chan) - self.assertTrue(consumer1.no_ack) - - chan2 = self.connection.channel() - consumer2 = self.node.Consumer(channel=chan2, no_ack=False) - self.assertIs(consumer2.channel, chan2) - self.assertFalse(consumer2.no_ack) - - def test_Node_consumer_multiple_listeners(self): - warnings.resetwarnings() - consumer = self.node.Consumer() - q = consumer.queues[0] - with warnings.catch_warnings(record=True) as log: - q.on_declared('foo', 1, 1) - self.assertTrue(log) - self.assertIn('already using this', log[0].message.args[0]) - - with warnings.catch_warnings(record=True) as log: - q.on_declared('foo', 1, 0) - self.assertFalse(log) - - def test_handler(self): - node = self.bound.Node('test_handler', state=self.state) - - @node.handler - def my_handler_name(state): - return 42 - - self.assertIn('my_handler_name', node.handlers) - - def test_dispatch(self): - node = self.bound.Node('test_dispatch', state=self.state) - - @node.handler - def my_handler_name(state, x=None, y=None): - return x + y - - self.assertEqual(node.dispatch('my_handler_name', - arguments={'x': 10, 'y': 10}), 20) - - def test_dispatch_raising_SystemExit(self): - node = self.bound.Node('test_dispatch_raising_SystemExit', - state=self.state) - - @node.handler - def my_handler_name(state): - raise SystemExit - - with self.assertRaises(SystemExit): - node.dispatch('my_handler_name') - - def test_dispatch_raising(self): - node = self.bound.Node('test_dispatch_raising', state=self.state) - - @node.handler - def my_handler_name(state): - raise KeyError('foo') - - res = node.dispatch('my_handler_name') - self.assertIn('error', res) - self.assertIn('KeyError', res['error']) - - def test_dispatch_replies(self): - _replied = [False] - - def reply(data, **options): - _replied[0] = True - - node = self.bound.Node('test_dispatch', state=self.state) - node.reply = reply - - @node.handler - def my_handler_name(state, x=None, y=None): - return x + y - - node.dispatch('my_handler_name', - arguments={'x': 10, 'y': 10}, - reply_to={'exchange': 'foo', 'routing_key': 'bar'}) - self.assertTrue(_replied[0]) - - def test_reply(self): - _replied = [(None, None, None)] - - def publish_reply(data, exchange, routing_key, ticket, **kwargs): - _replied[0] = (data, exchange, routing_key, ticket) - - mailbox = self.mailbox(self.connection) - mailbox._publish_reply = publish_reply - node = mailbox.Node('test_reply') - - @node.handler - def my_handler_name(state): - return 42 - - node.dispatch('my_handler_name', - reply_to={'exchange': 'exchange', - 'routing_key': 'rkey'}, - ticket='TICKET') - data, exchange, routing_key, ticket = _replied[0] - self.assertEqual(data, {'test_reply': 42}) - self.assertEqual(exchange, 'exchange') - self.assertEqual(routing_key, 'rkey') - self.assertEqual(ticket, 'TICKET') - - def test_handle_message(self): - node = self.bound.Node('test_dispatch_from_message') - - @node.handler - def my_handler_name(state, x=None, y=None): - return x * y - - body = {'method': 'my_handler_name', - 'arguments': {'x': 64, 'y': 64}} - - self.assertEqual(node.handle_message(body, None), 64 * 64) - - # message not for me should not be processed. - body['destination'] = ['some_other_node'] - self.assertIsNone(node.handle_message(body, None)) - - def test_handle_message_adjusts_clock(self): - node = self.bound.Node('test_adjusts_clock') - - @node.handler - def my_handler_name(state): - return 10 - - body = {'method': 'my_handler_name', - 'arguments': {}} - message = Mock(name='message') - message.headers = {'clock': 313} - node.adjust_clock = Mock(name='adjust_clock') - res = node.handle_message(body, message) - node.adjust_clock.assert_called_with(313) - self.assertEqual(res, 10) - - def test_listen(self): - consumer = self.node.listen() - self.assertEqual(consumer.callbacks[0], - self.node.handle_message) - self.assertEqual(consumer.channel, self.default_chan) - - def test_cast(self): - self.bound.cast(['somenode'], 'mymethod') - consumer = self.node.Consumer() - self.assertIsCast(self.get_next(consumer)) - - def test_abcast(self): - self.bound.abcast('mymethod') - consumer = self.node.Consumer() - self.assertIsCast(self.get_next(consumer)) - - def test_call_destination_must_be_sequence(self): - with self.assertRaises(ValueError): - self.bound.call('some_node', 'mymethod') - - def test_call(self): - self.assertEqual( - self.bound.call(['some_node'], 'mymethod'), - 'COLLECTED', - ) - consumer = self.node.Consumer() - self.assertIsCall(self.get_next(consumer)) - - def test_multi_call(self): - self.assertEqual(self.bound.multi_call('mymethod'), 'COLLECTED') - consumer = self.node.Consumer() - self.assertIsCall(self.get_next(consumer)) - - def get_next(self, consumer): - m = consumer.queues[0].get() - if m: - return m.payload - - def assertIsCast(self, message): - self.assertTrue(message['method']) - - def assertIsCall(self, message): - self.assertTrue(message['method']) - self.assertTrue(message['reply_to']) diff --git a/awx/lib/site-packages/kombu/tests/test_pools.py b/awx/lib/site-packages/kombu/tests/test_pools.py deleted file mode 100644 index 920c65a7fb..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_pools.py +++ /dev/null @@ -1,239 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection, Producer -from kombu import pools -from kombu.connection import ConnectionPool -from kombu.utils import eqhash - -from .case import Case, Mock - - -class test_ProducerPool(Case): - Pool = pools.ProducerPool - - class MyPool(pools.ProducerPool): - - def __init__(self, *args, **kwargs): - self.instance = Mock() - pools.ProducerPool.__init__(self, *args, **kwargs) - - def Producer(self, connection): - return self.instance - - def setUp(self): - self.connections = Mock() - self.pool = self.Pool(self.connections, limit=10) - - def test_close_resource(self): - self.pool.close_resource(Mock(name='resource')) - - def test_releases_connection_when_Producer_raises(self): - self.pool.Producer = Mock() - self.pool.Producer.side_effect = IOError() - acq = self.pool._acquire_connection = Mock() - conn = acq.return_value = Mock() - with self.assertRaises(IOError): - self.pool.create_producer() - conn.release.assert_called_with() - - def test_prepare_release_connection_on_error(self): - pp = Mock() - p = pp.return_value = Mock() - p.revive.side_effect = IOError() - acq = self.pool._acquire_connection = Mock() - conn = acq.return_value = Mock() - p._channel = None - with self.assertRaises(IOError): - self.pool.prepare(pp) - conn.release.assert_called_with() - - def test_release_releases_connection(self): - p = Mock() - p.__connection__ = Mock() - self.pool.release(p) - p.__connection__.release.assert_called_with() - p.__connection__ = None - self.pool.release(p) - - def test_init(self): - self.assertIs(self.pool.connections, self.connections) - - def test_Producer(self): - self.assertIsInstance(self.pool.Producer(Mock()), Producer) - - def test_acquire_connection(self): - self.pool._acquire_connection() - self.connections.acquire.assert_called_with(block=True) - - def test_new(self): - promise = self.pool.new() - producer = promise() - self.assertIsInstance(producer, Producer) - self.connections.acquire.assert_called_with(block=True) - - def test_setup_unlimited(self): - pool = self.Pool(self.connections, limit=None) - pool.setup() - self.assertFalse(pool._resource.queue) - - def test_setup(self): - self.assertEqual(len(self.pool._resource.queue), self.pool.limit) - - first = self.pool._resource.get_nowait() - producer = first() - self.assertIsInstance(producer, Producer) - - def test_prepare(self): - connection = self.connections.acquire.return_value = Mock() - pool = self.MyPool(self.connections, limit=10) - pool.instance._channel = None - first = pool._resource.get_nowait() - producer = pool.prepare(first) - self.assertTrue(self.connections.acquire.called) - producer.revive.assert_called_with(connection) - - def test_prepare_channel_already_created(self): - self.connections.acquire.return_value = Mock() - pool = self.MyPool(self.connections, limit=10) - pool.instance._channel = Mock() - first = pool._resource.get_nowait() - self.connections.acquire.reset() - producer = pool.prepare(first) - self.assertFalse(producer.revive.called) - - def test_prepare_not_callable(self): - x = Producer(Mock) - self.pool.prepare(x) - - def test_release(self): - p = Mock() - p.channel = Mock() - p.__connection__ = Mock() - self.pool.release(p) - p.__connection__.release.assert_called_with() - self.assertIsNone(p.channel) - - -class test_PoolGroup(Case): - Group = pools.PoolGroup - - class MyGroup(pools.PoolGroup): - - def create(self, resource, limit): - return resource, limit - - def test_interface_create(self): - g = self.Group() - with self.assertRaises(NotImplementedError): - g.create(Mock(), 10) - - def test_getitem_using_global_limit(self): - pools._used[0] = False - g = self.MyGroup(limit=pools.use_global_limit) - res = g['foo'] - self.assertTupleEqual(res, ('foo', pools.get_limit())) - self.assertTrue(pools._used[0]) - - def test_getitem_using_custom_limit(self): - pools._used[0] = True - g = self.MyGroup(limit=102456) - res = g['foo'] - self.assertTupleEqual(res, ('foo', 102456)) - - def test_delitem(self): - g = self.MyGroup() - g['foo'] - del(g['foo']) - self.assertNotIn('foo', g) - - def test_Connections(self): - conn = Connection('memory://') - p = pools.connections[conn] - self.assertTrue(p) - self.assertIsInstance(p, ConnectionPool) - self.assertIs(p.connection, conn) - self.assertEqual(p.limit, pools.get_limit()) - - def test_Producers(self): - conn = Connection('memory://') - p = pools.producers[conn] - self.assertTrue(p) - self.assertIsInstance(p, pools.ProducerPool) - self.assertIs(p.connections, pools.connections[conn]) - self.assertEqual(p.limit, p.connections.limit) - self.assertEqual(p.limit, pools.get_limit()) - - def test_all_groups(self): - conn = Connection('memory://') - pools.connections[conn] - - self.assertTrue(list(pools._all_pools())) - - def test_reset(self): - pools.reset() - - class MyGroup(dict): - clear_called = False - - def clear(self): - self.clear_called = True - - p1 = pools.connections['foo'] = Mock() - g1 = MyGroup() - pools._groups.append(g1) - - pools.reset() - p1.force_close_all.assert_called_with() - self.assertTrue(g1.clear_called) - - p1 = pools.connections['foo'] = Mock() - p1.force_close_all.side_effect = KeyError() - pools.reset() - - def test_set_limit(self): - pools.reset() - pools.set_limit(34576) - limit = pools.get_limit() - self.assertEqual(limit, 34576) - - pools.connections[Connection('memory://')] - pools.set_limit(limit + 1) - self.assertEqual(pools.get_limit(), limit + 1) - limit = pools.get_limit() - with self.assertRaises(RuntimeError): - pools.set_limit(limit - 1) - pools.set_limit(limit - 1, force=True) - self.assertEqual(pools.get_limit(), limit - 1) - - pools.set_limit(pools.get_limit()) - - -class test_fun_PoolGroup(Case): - - def test_connections_behavior(self): - c1u = 'memory://localhost:123' - c2u = 'memory://localhost:124' - c1 = Connection(c1u) - c2 = Connection(c2u) - c3 = Connection(c1u) - - assert eqhash(c1) != eqhash(c2) - assert eqhash(c1) == eqhash(c3) - - c4 = Connection(c1u, transport_options={'confirm_publish': True}) - self.assertNotEqual(eqhash(c3), eqhash(c4)) - - p1 = pools.connections[c1] - p2 = pools.connections[c2] - p3 = pools.connections[c3] - - self.assertIsNot(p1, p2) - self.assertIs(p1, p3) - - r1 = p1.acquire() - self.assertTrue(p1._dirty) - self.assertTrue(p3._dirty) - self.assertFalse(p2._dirty) - r1.release() - self.assertFalse(p1._dirty) - self.assertFalse(p3._dirty) diff --git a/awx/lib/site-packages/kombu/tests/test_serialization.py b/awx/lib/site-packages/kombu/tests/test_serialization.py deleted file mode 100644 index 231207114c..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_serialization.py +++ /dev/null @@ -1,348 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import unicode_literals - -import sys - -from base64 import b64decode - -from kombu.exceptions import ContentDisallowed, EncodeError, DecodeError -from kombu.five import text_t, bytes_t -from kombu.serialization import ( - registry, register, SerializerNotInstalled, - raw_encode, register_yaml, register_msgpack, - dumps, loads, pickle, pickle_protocol, - unregister, register_pickle, enable_insecure_serializers, - disable_insecure_serializers, -) -from kombu.utils.encoding import str_to_bytes - -from .case import Case, call, mask_modules, patch, skip_if_not_module - -# For content_encoding tests -unicode_string = 'abcdé\u8463' -unicode_string_as_utf8 = unicode_string.encode('utf-8') -latin_string = 'abcdé' -latin_string_as_latin1 = latin_string.encode('latin-1') -latin_string_as_utf8 = latin_string.encode('utf-8') - - -# For serialization tests -py_data = { - 'string': 'The quick brown fox jumps over the lazy dog', - 'int': 10, - 'float': 3.14159265, - 'unicode': 'Thé quick brown fox jumps over thé lazy dog', - 'list': ['george', 'jerry', 'elaine', 'cosmo'], -} - -# JSON serialization tests -json_data = """\ -{"int": 10, "float": 3.1415926500000002, \ -"list": ["george", "jerry", "elaine", "cosmo"], \ -"string": "The quick brown fox jumps over the lazy \ -dog", "unicode": "Th\\u00e9 quick brown fox jumps over \ -th\\u00e9 lazy dog"}\ -""" - -# Pickle serialization tests -pickle_data = pickle.dumps(py_data, protocol=pickle_protocol) - -# YAML serialization tests -yaml_data = """\ -float: 3.1415926500000002 -int: 10 -list: [george, jerry, elaine, cosmo] -string: The quick brown fox jumps over the lazy dog -unicode: "Th\\xE9 quick brown fox jumps over th\\xE9 lazy dog" -""" - - -msgpack_py_data = dict(py_data) -# Unicode chars are lost in transmit :( -msgpack_py_data['unicode'] = 'Th quick brown fox jumps over th lazy dog' -msgpack_data = b64decode(str_to_bytes("""\ -haNpbnQKpWZsb2F0y0AJIftTyNTxpGxpc3SUpmdlb3JnZaVqZXJyeaZlbGFpbmWlY29zbW+mc3Rya\ -W5n2gArVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZ6d1bmljb2Rl2g\ -ApVGggcXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgdGggbGF6eSBkb2c=\ -""")) - - -def say(m): - sys.stderr.write('%s\n' % (m, )) - - -registry.register('testS', lambda s: s, lambda s: 'decoded', - 'application/testS', 'utf-8') - - -class test_Serialization(Case): - - def test_disable(self): - disabled = registry._disabled_content_types - try: - registry.disable('testS') - self.assertIn('application/testS', disabled) - disabled.clear() - - registry.disable('application/testS') - self.assertIn('application/testS', disabled) - finally: - disabled.clear() - - def test_enable(self): - registry._disabled_content_types.add('application/json') - registry.enable('json') - self.assertNotIn('application/json', registry._disabled_content_types) - registry._disabled_content_types.add('application/json') - registry.enable('application/json') - self.assertNotIn('application/json', registry._disabled_content_types) - - def test_loads_when_disabled(self): - disabled = registry._disabled_content_types - try: - registry.disable('testS') - - with self.assertRaises(SerializerNotInstalled): - loads('xxd', 'application/testS', 'utf-8', force=False) - - ret = loads('xxd', 'application/testS', 'utf-8', force=True) - self.assertEqual(ret, 'decoded') - finally: - disabled.clear() - - def test_loads_when_data_is_None(self): - loads(None, 'application/testS', 'utf-8') - - def test_content_type_decoding(self): - self.assertEqual( - unicode_string, - loads(unicode_string_as_utf8, - content_type='plain/text', content_encoding='utf-8'), - ) - self.assertEqual( - latin_string, - loads(latin_string_as_latin1, - content_type='application/data', content_encoding='latin-1'), - ) - - def test_content_type_binary(self): - self.assertIsInstance( - loads(unicode_string_as_utf8, - content_type='application/data', content_encoding='binary'), - bytes_t, - ) - - self.assertEqual( - unicode_string_as_utf8, - loads(unicode_string_as_utf8, - content_type='application/data', content_encoding='binary'), - ) - - def test_content_type_encoding(self): - # Using the 'raw' serializer - self.assertEqual( - unicode_string_as_utf8, - dumps(unicode_string, serializer='raw')[-1], - ) - self.assertEqual( - latin_string_as_utf8, - dumps(latin_string, serializer='raw')[-1], - ) - # And again w/o a specific serializer to check the - # code where we force unicode objects into a string. - self.assertEqual( - unicode_string_as_utf8, - dumps(unicode_string)[-1], - ) - self.assertEqual( - latin_string_as_utf8, - dumps(latin_string)[-1], - ) - - def test_enable_insecure_serializers(self): - with patch('kombu.serialization.registry') as registry: - enable_insecure_serializers() - registry.assert_has_calls([ - call.enable('pickle'), call.enable('yaml'), - call.enable('msgpack'), - ]) - registry.enable.side_effect = KeyError() - enable_insecure_serializers() - - with patch('kombu.serialization.registry') as registry: - enable_insecure_serializers(['msgpack']) - registry.assert_has_calls([call.enable('msgpack')]) - - def test_disable_insecure_serializers(self): - with patch('kombu.serialization.registry') as registry: - registry._decoders = ['pickle', 'yaml', 'doomsday'] - disable_insecure_serializers(allowed=['doomsday']) - registry.disable.assert_has_calls([call('pickle'), call('yaml')]) - registry.enable.assert_has_calls([call('doomsday')]) - disable_insecure_serializers(allowed=None) - registry.disable.assert_has_calls([ - call('pickle'), call('yaml'), call('doomsday') - ]) - - def test_reraises_EncodeError(self): - with self.assertRaises(EncodeError): - dumps([object()], serializer='json') - - def test_reraises_DecodeError(self): - with self.assertRaises(DecodeError): - loads(object(), content_type='application/json', - content_encoding='utf-8') - - def test_json_loads(self): - self.assertEqual( - py_data, - loads(json_data, - content_type='application/json', content_encoding='utf-8'), - ) - - def test_json_dumps(self): - self.assertEqual( - loads( - dumps(py_data, serializer='json')[-1], - content_type='application/json', - content_encoding='utf-8', - ), - loads( - json_data, - content_type='application/json', - content_encoding='utf-8', - ), - ) - - @skip_if_not_module('msgpack', (ImportError, ValueError)) - def test_msgpack_loads(self): - register_msgpack() - res = loads(msgpack_data, - content_type='application/x-msgpack', - content_encoding='binary') - if sys.version_info[0] < 3: - for k, v in res.items(): - if isinstance(v, text_t): - res[k] = v.encode() - if isinstance(v, (list, tuple)): - res[k] = [i.encode() for i in v] - self.assertEqual( - msgpack_py_data, - res, - ) - - @skip_if_not_module('msgpack', (ImportError, ValueError)) - def test_msgpack_dumps(self): - register_msgpack() - self.assertEqual( - loads( - dumps(msgpack_py_data, serializer='msgpack')[-1], - content_type='application/x-msgpack', - content_encoding='binary', - ), - loads( - msgpack_data, - content_type='application/x-msgpack', - content_encoding='binary', - ), - ) - - @skip_if_not_module('yaml') - def test_yaml_loads(self): - register_yaml() - self.assertEqual( - py_data, - loads(yaml_data, - content_type='application/x-yaml', - content_encoding='utf-8'), - ) - - @skip_if_not_module('yaml') - def test_yaml_dumps(self): - register_yaml() - self.assertEqual( - loads( - dumps(py_data, serializer='yaml')[-1], - content_type='application/x-yaml', - content_encoding='utf-8', - ), - loads( - yaml_data, - content_type='application/x-yaml', - content_encoding='utf-8', - ), - ) - - def test_pickle_loads(self): - self.assertEqual( - py_data, - loads(pickle_data, - content_type='application/x-python-serialize', - content_encoding='binary'), - ) - - def test_pickle_dumps(self): - self.assertEqual( - pickle.loads(pickle_data), - pickle.loads(dumps(py_data, serializer='pickle')[-1]), - ) - - def test_register(self): - register(None, None, None, None) - - def test_unregister(self): - with self.assertRaises(SerializerNotInstalled): - unregister('nonexisting') - dumps('foo', serializer='pickle') - unregister('pickle') - with self.assertRaises(SerializerNotInstalled): - dumps('foo', serializer='pickle') - register_pickle() - - def test_set_default_serializer_missing(self): - with self.assertRaises(SerializerNotInstalled): - registry._set_default_serializer('nonexisting') - - def test_dumps_missing(self): - with self.assertRaises(SerializerNotInstalled): - dumps('foo', serializer='nonexisting') - - def test_dumps__no_serializer(self): - ctyp, cenc, data = dumps(str_to_bytes('foo')) - self.assertEqual(ctyp, 'application/data') - self.assertEqual(cenc, 'binary') - - def test_loads__trusted_content(self): - loads('tainted', 'application/data', 'binary', accept=[]) - loads('tainted', 'application/text', 'utf-8', accept=[]) - - def test_loads__not_accepted(self): - with self.assertRaises(ContentDisallowed): - loads('tainted', 'application/x-evil', 'binary', accept=[]) - with self.assertRaises(ContentDisallowed): - loads('tainted', 'application/x-evil', 'binary', - accept=['application/x-json']) - self.assertTrue( - loads('tainted', 'application/x-doomsday', 'binary', - accept=['application/x-doomsday']) - ) - - def test_raw_encode(self): - self.assertTupleEqual( - raw_encode('foo'.encode('utf-8')), - ('application/data', 'binary', 'foo'.encode('utf-8')), - ) - - @mask_modules('yaml') - def test_register_yaml__no_yaml(self): - register_yaml() - with self.assertRaises(SerializerNotInstalled): - loads('foo', 'application/x-yaml', 'utf-8') - - @mask_modules('msgpack') - def test_register_msgpack__no_msgpack(self): - register_msgpack() - with self.assertRaises(SerializerNotInstalled): - loads('foo', 'application/x-msgpack', 'utf-8') diff --git a/awx/lib/site-packages/kombu/tests/test_simple.py b/awx/lib/site-packages/kombu/tests/test_simple.py deleted file mode 100644 index 53a4ac3893..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_simple.py +++ /dev/null @@ -1,136 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection, Exchange, Queue - -from .case import Case, Mock - - -class SimpleBase(Case): - abstract = True - - def Queue(self, name, *args, **kwargs): - q = name - if not isinstance(q, Queue): - q = self.__class__.__name__ - if name: - q = '%s.%s' % (q, name) - return self._Queue(q, *args, **kwargs) - - def _Queue(self, *args, **kwargs): - raise NotImplementedError() - - def setUp(self): - if not self.abstract: - self.connection = Connection(transport='memory') - with self.connection.channel() as channel: - channel.exchange_declare('amq.direct') - self.q = self.Queue(None, no_ack=True) - - def tearDown(self): - if not self.abstract: - self.q.close() - self.connection.close() - - def test_produce__consume(self): - if self.abstract: - return - q = self.Queue('test_produce__consume', no_ack=True) - - q.put({'hello': 'Simple'}) - - self.assertEqual(q.get(timeout=1).payload, {'hello': 'Simple'}) - with self.assertRaises(q.Empty): - q.get(timeout=0.1) - - def test_produce__basic_get(self): - if self.abstract: - return - q = self.Queue('test_produce__basic_get', no_ack=True) - q.put({'hello': 'SimpleSync'}) - self.assertEqual(q.get_nowait().payload, {'hello': 'SimpleSync'}) - with self.assertRaises(q.Empty): - q.get_nowait() - - q.put({'hello': 'SimpleSync'}) - self.assertEqual(q.get(block=False).payload, {'hello': 'SimpleSync'}) - with self.assertRaises(q.Empty): - q.get(block=False) - - def test_clear(self): - if self.abstract: - return - q = self.Queue('test_clear', no_ack=True) - - for i in range(10): - q.put({'hello': 'SimplePurge%d' % (i, )}) - - self.assertEqual(q.clear(), 10) - - def test_enter_exit(self): - if self.abstract: - return - q = self.Queue('test_enter_exit') - q.close = Mock() - - self.assertIs(q.__enter__(), q) - q.__exit__() - q.close.assert_called_with() - - def test_qsize(self): - if self.abstract: - return - q = self.Queue('test_clear', no_ack=True) - - for i in range(10): - q.put({'hello': 'SimplePurge%d' % (i, )}) - - self.assertEqual(q.qsize(), 10) - self.assertEqual(len(q), 10) - - def test_autoclose(self): - if self.abstract: - return - channel = self.connection.channel() - q = self.Queue('test_autoclose', no_ack=True, channel=channel) - q.close() - - def test_custom_Queue(self): - if self.abstract: - return - n = self.__class__.__name__ - exchange = Exchange('%s-test.custom.Queue' % (n, )) - queue = Queue('%s-test.custom.Queue' % (n, ), - exchange, - 'my.routing.key') - - q = self.Queue(queue) - self.assertEqual(q.consumer.queues[0], queue) - q.close() - - def test_bool(self): - if self.abstract: - return - q = self.Queue('test_nonzero') - self.assertTrue(q) - - -class test_SimpleQueue(SimpleBase): - abstract = False - - def _Queue(self, *args, **kwargs): - return self.connection.SimpleQueue(*args, **kwargs) - - def test_is_ack(self): - q = self.Queue('test_is_no_ack') - self.assertFalse(q.no_ack) - - -class test_SimpleBuffer(SimpleBase): - abstract = False - - def Queue(self, *args, **kwargs): - return self.connection.SimpleBuffer(*args, **kwargs) - - def test_is_no_ack(self): - q = self.Queue('test_is_no_ack') - self.assertTrue(q.no_ack) diff --git a/awx/lib/site-packages/kombu/tests/test_syn.py b/awx/lib/site-packages/kombu/tests/test_syn.py deleted file mode 100644 index 34e58035a1..0000000000 --- a/awx/lib/site-packages/kombu/tests/test_syn.py +++ /dev/null @@ -1,61 +0,0 @@ -from __future__ import absolute_import - -import socket -import sys -import types - -from kombu import syn - -from kombu.tests.case import Case, patch, module_exists - - -class test_syn(Case): - - def test_compat(self): - self.assertEqual(syn.blocking(lambda: 10), 10) - syn.select_blocking_method('foo') - - def test_detect_environment(self): - try: - syn._environment = None - X = syn.detect_environment() - self.assertEqual(syn._environment, X) - Y = syn.detect_environment() - self.assertEqual(Y, X) - finally: - syn._environment = None - - @module_exists('eventlet', 'eventlet.patcher') - def test_detect_environment_eventlet(self): - with patch('eventlet.patcher.is_monkey_patched', create=True) as m: - self.assertTrue(sys.modules['eventlet']) - m.return_value = True - env = syn._detect_environment() - m.assert_called_with(socket) - self.assertEqual(env, 'eventlet') - - @module_exists('gevent') - def test_detect_environment_gevent(self): - with patch('gevent.socket', create=True) as m: - prev, socket.socket = socket.socket, m.socket - try: - self.assertTrue(sys.modules['gevent']) - env = syn._detect_environment() - self.assertEqual(env, 'gevent') - finally: - socket.socket = prev - - def test_detect_environment_no_eventlet_or_gevent(self): - try: - sys.modules['eventlet'] = types.ModuleType('eventlet') - sys.modules['eventlet.patcher'] = types.ModuleType('eventlet') - self.assertEqual(syn._detect_environment(), 'default') - finally: - sys.modules.pop('eventlet', None) - syn._detect_environment() - try: - sys.modules['gevent'] = types.ModuleType('gevent') - self.assertEqual(syn._detect_environment(), 'default') - finally: - sys.modules.pop('gevent', None) - syn._detect_environment() diff --git a/awx/lib/site-packages/kombu/tests/transport/__init__.py b/awx/lib/site-packages/kombu/tests/transport/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/kombu/tests/transport/test_SQS.py b/awx/lib/site-packages/kombu/tests/transport/test_SQS.py deleted file mode 100644 index e4efb53f26..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_SQS.py +++ /dev/null @@ -1,296 +0,0 @@ -"""Testing module for the kombu.transport.SQS package. - -NOTE: The SQSQueueMock and SQSConnectionMock classes originally come from -http://github.com/pcsforeducation/sqs-mock-python. They have been patched -slightly. -""" - -from __future__ import absolute_import - -from kombu import Connection -from kombu import messaging -from kombu import five -from kombu.tests.case import Case, SkipTest -import kombu - -try: - from kombu.transport import SQS -except ImportError: - # Boto must not be installed if the SQS transport fails to import, - # so we skip all unit tests. Set SQS to None here, and it will be - # checked during the setUp() phase later. - SQS = None - - -class SQSQueueMock(object): - - def __init__(self, name): - self.name = name - self.messages = [] - self._get_message_calls = 0 - - def clear(self, page_size=10, vtimeout=10): - empty, self.messages[:] = not self.messages, [] - return not empty - - def count(self, page_size=10, vtimeout=10): - return len(self.messages) - count_slow = count - - def delete(self): - self.messages[:] = [] - return True - - def delete_message(self, message): - try: - self.messages.remove(message) - except ValueError: - return False - return True - - def get_messages(self, num_messages=1, visibility_timeout=None, - attributes=None, *args, **kwargs): - self._get_message_calls += 1 - return self.messages[:num_messages] - - def read(self, visibility_timeout=None): - return self.messages.pop(0) - - def write(self, message): - self.messages.append(message) - return True - - -class SQSConnectionMock(object): - - def __init__(self): - self.queues = {} - - def get_queue(self, queue): - return self.queues.get(queue) - - def get_all_queues(self, prefix=""): - return self.queues.values() - - def delete_queue(self, queue, force_deletion=False): - q = self.get_queue(queue) - if q: - if q.count(): - return False - q.clear() - self.queues.pop(queue, None) - - def delete_message(self, queue, message): - return queue.delete_message(message) - - def create_queue(self, name, *args, **kwargs): - q = self.queues[name] = SQSQueueMock(name) - return q - - -class test_Channel(Case): - - def handleMessageCallback(self, message): - self.callback_message = message - - def setUp(self): - """Mock the back-end SQS classes""" - # Sanity check... if SQS is None, then it did not import and we - # cannot execute our tests. - if SQS is None: - raise SkipTest('Boto is not installed') - - SQS.Channel._queue_cache.clear() - - # Common variables used in the unit tests - self.queue_name = 'unittest' - - # Mock the sqs() method that returns an SQSConnection object and - # instead return an SQSConnectionMock() object. - self.sqs_conn_mock = SQSConnectionMock() - - def mock_sqs(): - return self.sqs_conn_mock - SQS.Channel.sqs = mock_sqs() - - # Set up a task exchange for passing tasks through the queue - self.exchange = kombu.Exchange('test_SQS', type='direct') - self.queue = kombu.Queue(self.queue_name, - self.exchange, - self.queue_name) - - # Mock up a test SQS Queue with the SQSQueueMock class (and always - # make sure its a clean empty queue) - self.sqs_queue_mock = SQSQueueMock(self.queue_name) - - # Now, create our Connection object with the SQS Transport and store - # the connection/channel objects as references for use in these tests. - self.connection = Connection(transport=SQS.Transport) - self.channel = self.connection.channel() - - self.queue(self.channel).declare() - self.producer = messaging.Producer(self.channel, - self.exchange, - routing_key=self.queue_name) - - # Lastly, make sure that we're set up to 'consume' this queue. - self.channel.basic_consume(self.queue_name, - no_ack=True, - callback=self.handleMessageCallback, - consumer_tag='unittest') - - def test_init(self): - """kombu.SQS.Channel instantiates correctly with mocked queues""" - self.assertIn(self.queue_name, self.channel._queue_cache) - - def test_new_queue(self): - queue_name = 'new_unittest_queue' - self.channel._new_queue(queue_name) - self.assertIn(queue_name, self.sqs_conn_mock.queues) - # For cleanup purposes, delete the queue and the queue file - self.channel._delete(queue_name) - - def test_delete(self): - queue_name = 'new_unittest_queue' - self.channel._new_queue(queue_name) - self.channel._delete(queue_name) - self.assertNotIn(queue_name, self.channel._queue_cache) - - def test_get_from_sqs(self): - # Test getting a single message - message = 'my test message' - self.producer.publish(message) - results = self.channel._get_from_sqs(self.queue_name) - self.assertEquals(len(results), 1) - - # Now test getting many messages - for i in xrange(3): - message = 'message: {0}'.format(i) - self.producer.publish(message) - - results = self.channel._get_from_sqs(self.queue_name, count=3) - self.assertEquals(len(results), 3) - - def test_get_with_empty_list(self): - with self.assertRaises(five.Empty): - self.channel._get(self.queue_name) - - def test_get_bulk_raises_empty(self): - with self.assertRaises(five.Empty): - self.channel._get_bulk(self.queue_name) - - def test_messages_to_python(self): - message_count = 3 - # Create several test messages and publish them - for i in range(message_count): - message = 'message: %s' % i - self.producer.publish(message) - - # Get the messages now - messages = self.channel._get_from_sqs( - self.queue_name, count=message_count, - ) - - # Now convert them to payloads - payloads = self.channel._messages_to_python( - messages, self.queue_name, - ) - - # We got the same number of payloads back, right? - self.assertEquals(len(payloads), message_count) - - # Make sure they're payload-style objects - for p in payloads: - self.assertTrue('properties' in p) - - def test_put_and_get(self): - message = 'my test message' - self.producer.publish(message) - results = self.queue(self.channel).get().payload - self.assertEquals(message, results) - - def test_puts_and_gets(self): - for i in xrange(3): - message = 'message: %s' % i - self.producer.publish(message) - - for i in xrange(3): - self.assertEquals('message: %s' % i, - self.queue(self.channel).get().payload) - - def test_put_and_get_bulk(self): - # With QoS.prefetch_count = 0 - message = 'my test message' - self.producer.publish(message) - results = self.channel._get_bulk(self.queue_name) - self.assertEquals(1, len(results)) - - def test_puts_and_get_bulk(self): - # Generate 8 messages - message_count = 8 - - # Set the prefetch_count to 5 - self.channel.qos.prefetch_count = 5 - - # Now, generate all the messages - for i in xrange(message_count): - message = 'message: %s' % i - self.producer.publish(message) - - # Count how many messages are retrieved the first time. Should - # be 5 (message_count). - results = self.channel._get_bulk(self.queue_name) - self.assertEquals(5, len(results)) - - # Now, do the get again, the number of messages returned should be 3. - results = self.channel._get_bulk(self.queue_name) - self.assertEquals(3, len(results)) - - def test_drain_events_with_empty_list(self): - def mock_can_consume(): - return False - self.channel.qos.can_consume = mock_can_consume - with self.assertRaises(five.Empty): - self.channel.drain_events() - - def test_drain_events_with_prefetch_5(self): - # Generate 20 messages - message_count = 20 - expected_get_message_count = 4 - - # Set the prefetch_count to 5 - self.channel.qos.prefetch_count = 5 - - # Now, generate all the messages - for i in xrange(message_count): - self.producer.publish('message: %s' % i) - - # Now drain all the events - for i in xrange(message_count): - self.channel.drain_events() - - # How many times was the SQSConnectionMock get_message method called? - self.assertEquals( - expected_get_message_count, - self.channel._queue_cache[self.queue_name]._get_message_calls) - - def test_drain_events_with_prefetch_none(self): - # Generate 20 messages - message_count = 20 - expected_get_message_count = 2 - - # Set the prefetch_count to None - self.channel.qos.prefetch_count = None - - # Now, generate all the messages - for i in xrange(message_count): - self.producer.publish('message: %s' % i) - - # Now drain all the events - for i in xrange(message_count): - self.channel.drain_events() - - # How many times was the SQSConnectionMock get_message method called? - self.assertEquals( - expected_get_message_count, - self.channel._queue_cache[self.queue_name]._get_message_calls) diff --git a/awx/lib/site-packages/kombu/tests/transport/test_amqplib.py b/awx/lib/site-packages/kombu/tests/transport/test_amqplib.py deleted file mode 100644 index cf7d6150da..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_amqplib.py +++ /dev/null @@ -1,162 +0,0 @@ -from __future__ import absolute_import - -import sys - -from kombu import Connection - -from kombu.tests.case import Case, SkipTest, Mock, mask_modules - - -class MockConnection(dict): - - def __setattr__(self, key, value): - self[key] = value - -try: - __import__('amqplib') -except ImportError: - amqplib = Channel = None -else: - from kombu.transport import amqplib - - class Channel(amqplib.Channel): - wait_returns = [] - - def _x_open(self, *args, **kwargs): - pass - - def wait(self, *args, **kwargs): - return self.wait_returns - - def _send_method(self, *args, **kwargs): - pass - - -class amqplibCase(Case): - - def setUp(self): - if amqplib is None: - raise SkipTest('amqplib not installed') - self.setup() - - def setup(self): - pass - - -class test_Channel(amqplibCase): - - def setup(self): - self.conn = Mock() - self.conn.channels = {} - self.channel = Channel(self.conn, 0) - - def test_init(self): - self.assertFalse(self.channel.no_ack_consumers) - - def test_prepare_message(self): - self.assertTrue(self.channel.prepare_message( - 'foobar', 10, 'application/data', 'utf-8', - properties={}, - )) - - def test_message_to_python(self): - message = Mock() - message.headers = {} - message.properties = {} - self.assertTrue(self.channel.message_to_python(message)) - - def test_close_resolves_connection_cycle(self): - self.assertIsNotNone(self.channel.connection) - self.channel.close() - self.assertIsNone(self.channel.connection) - - def test_basic_consume_registers_ack_status(self): - self.channel.wait_returns = 'my-consumer-tag' - self.channel.basic_consume('foo', no_ack=True) - self.assertIn('my-consumer-tag', self.channel.no_ack_consumers) - - self.channel.wait_returns = 'other-consumer-tag' - self.channel.basic_consume('bar', no_ack=False) - self.assertNotIn('other-consumer-tag', self.channel.no_ack_consumers) - - self.channel.basic_cancel('my-consumer-tag') - self.assertNotIn('my-consumer-tag', self.channel.no_ack_consumers) - - -class test_Transport(amqplibCase): - - def setup(self): - self.connection = Connection('amqplib://') - self.transport = self.connection.transport - - def test_create_channel(self): - connection = Mock() - self.transport.create_channel(connection) - connection.channel.assert_called_with() - - def test_drain_events(self): - connection = Mock() - self.transport.drain_events(connection, timeout=10.0) - connection.drain_events.assert_called_with(timeout=10.0) - - def test_dnspython_localhost_resolve_bug(self): - - class Conn(object): - - def __init__(self, **kwargs): - vars(self).update(kwargs) - - self.transport.Connection = Conn - self.transport.client.hostname = 'localhost' - conn1 = self.transport.establish_connection() - self.assertEqual(conn1.host, '127.0.0.1:5672') - - self.transport.client.hostname = 'example.com' - conn2 = self.transport.establish_connection() - self.assertEqual(conn2.host, 'example.com:5672') - - def test_close_connection(self): - connection = Mock() - connection.client = Mock() - self.transport.close_connection(connection) - - self.assertIsNone(connection.client) - connection.close.assert_called_with() - - def test_verify_connection(self): - connection = Mock() - connection.channels = None - self.assertFalse(self.transport.verify_connection(connection)) - - connection.channels = {1: 1, 2: 2} - self.assertTrue(self.transport.verify_connection(connection)) - - @mask_modules('ssl') - def test_import_no_ssl(self): - pm = sys.modules.pop('kombu.transport.amqplib') - try: - from kombu.transport.amqplib import SSLError - self.assertEqual(SSLError.__module__, 'kombu.transport.amqplib') - finally: - if pm is not None: - sys.modules['kombu.transport.amqplib'] = pm - - -class test_amqplib(amqplibCase): - - def test_default_port(self): - - class Transport(amqplib.Transport): - Connection = MockConnection - - c = Connection(port=None, transport=Transport).connect() - self.assertEqual(c['host'], - '127.0.0.1:%s' % (Transport.default_port, )) - - def test_custom_port(self): - - class Transport(amqplib.Transport): - Connection = MockConnection - - c = Connection(port=1337, transport=Transport).connect() - self.assertEqual(c['host'], '127.0.0.1:1337') diff --git a/awx/lib/site-packages/kombu/tests/transport/test_base.py b/awx/lib/site-packages/kombu/tests/transport/test_base.py deleted file mode 100644 index 5c4a50d552..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_base.py +++ /dev/null @@ -1,148 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection, Consumer, Exchange, Producer, Queue -from kombu.five import text_t -from kombu.message import Message -from kombu.transport.base import StdChannel, Transport, Management - -from kombu.tests.case import Case, Mock - - -class test_StdChannel(Case): - - def setUp(self): - self.conn = Connection('memory://') - self.channel = self.conn.channel() - self.channel.queues.clear() - self.conn.connection.state.clear() - - def test_Consumer(self): - q = Queue('foo', Exchange('foo')) - print(self.channel.queues) - cons = self.channel.Consumer(q) - self.assertIsInstance(cons, Consumer) - self.assertIs(cons.channel, self.channel) - - def test_Producer(self): - prod = self.channel.Producer() - self.assertIsInstance(prod, Producer) - self.assertIs(prod.channel, self.channel) - - def test_interface_get_bindings(self): - with self.assertRaises(NotImplementedError): - StdChannel().get_bindings() - - def test_interface_after_reply_message_received(self): - self.assertIsNone( - StdChannel().after_reply_message_received(Queue('foo')), - ) - - -class test_Message(Case): - - def setUp(self): - self.conn = Connection('memory://') - self.channel = self.conn.channel() - self.message = Message(self.channel, delivery_tag=313) - - def test_postencode(self): - m = Message(self.channel, text_t('FOO'), postencode='ccyzz') - with self.assertRaises(LookupError): - m._reraise_error() - m.ack() - - def test_ack_respects_no_ack_consumers(self): - self.channel.no_ack_consumers = set(['abc']) - self.message.delivery_info['consumer_tag'] = 'abc' - ack = self.channel.basic_ack = Mock() - - self.message.ack() - self.assertNotEqual(self.message._state, 'ACK') - self.assertFalse(ack.called) - - def test_ack_missing_consumer_tag(self): - self.channel.no_ack_consumers = set(['abc']) - self.message.delivery_info = {} - ack = self.channel.basic_ack = Mock() - - self.message.ack() - ack.assert_called_with(self.message.delivery_tag) - - def test_ack_not_no_ack(self): - self.channel.no_ack_consumers = set() - self.message.delivery_info['consumer_tag'] = 'abc' - ack = self.channel.basic_ack = Mock() - - self.message.ack() - ack.assert_called_with(self.message.delivery_tag) - - def test_ack_log_error_when_no_error(self): - ack = self.message.ack = Mock() - self.message.ack_log_error(Mock(), KeyError) - ack.assert_called_with() - - def test_ack_log_error_when_error(self): - ack = self.message.ack = Mock() - ack.side_effect = KeyError('foo') - logger = Mock() - self.message.ack_log_error(logger, KeyError) - ack.assert_called_with() - self.assertTrue(logger.critical.called) - self.assertIn("Couldn't ack", logger.critical.call_args[0][0]) - - def test_reject_log_error_when_no_error(self): - reject = self.message.reject = Mock() - self.message.reject_log_error(Mock(), KeyError, requeue=True) - reject.assert_called_with(requeue=True) - - def test_reject_log_error_when_error(self): - reject = self.message.reject = Mock() - reject.side_effect = KeyError('foo') - logger = Mock() - self.message.reject_log_error(logger, KeyError) - reject.assert_called_with(requeue=False) - self.assertTrue(logger.critical.called) - self.assertIn("Couldn't reject", logger.critical.call_args[0][0]) - - -class test_interface(Case): - - def test_establish_connection(self): - with self.assertRaises(NotImplementedError): - Transport(None).establish_connection() - - def test_close_connection(self): - with self.assertRaises(NotImplementedError): - Transport(None).close_connection(None) - - def test_create_channel(self): - with self.assertRaises(NotImplementedError): - Transport(None).create_channel(None) - - def test_close_channel(self): - with self.assertRaises(NotImplementedError): - Transport(None).close_channel(None) - - def test_drain_events(self): - with self.assertRaises(NotImplementedError): - Transport(None).drain_events(None) - - def test_heartbeat_check(self): - Transport(None).heartbeat_check(Mock(name='connection')) - - def test_driver_version(self): - self.assertTrue(Transport(None).driver_version()) - - def test_register_with_event_loop(self): - Transport(None).register_with_event_loop(Mock(name='loop')) - - def test_manager(self): - self.assertTrue(Transport(None).manager) - - -class test_Management(Case): - - def test_get_bindings(self): - m = Management(Mock(name='transport')) - with self.assertRaises(NotImplementedError): - m.get_bindings() diff --git a/awx/lib/site-packages/kombu/tests/transport/test_filesystem.py b/awx/lib/site-packages/kombu/tests/transport/test_filesystem.py deleted file mode 100644 index 0649a8d000..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_filesystem.py +++ /dev/null @@ -1,123 +0,0 @@ -from __future__ import absolute_import - -import sys -import tempfile - -from kombu import Connection, Exchange, Queue, Consumer, Producer - -from kombu.tests.case import Case, SkipTest - - -class test_FilesystemTransport(Case): - - def setUp(self): - if sys.platform == 'win32': - raise SkipTest('Needs win32con module') - try: - data_folder_in = tempfile.mkdtemp() - data_folder_out = tempfile.mkdtemp() - except Exception: - raise SkipTest('filesystem transport: cannot create tempfiles') - self.c = Connection(transport='filesystem', - transport_options={ - 'data_folder_in': data_folder_in, - 'data_folder_out': data_folder_out, - }) - self.p = Connection(transport='filesystem', - transport_options={ - 'data_folder_in': data_folder_out, - 'data_folder_out': data_folder_in, - }) - self.e = Exchange('test_transport_filesystem') - self.q = Queue('test_transport_filesystem', - exchange=self.e, - routing_key='test_transport_filesystem') - self.q2 = Queue('test_transport_filesystem2', - exchange=self.e, - routing_key='test_transport_filesystem2') - - def test_produce_consume_noack(self): - producer = Producer(self.p.channel(), self.e) - consumer = Consumer(self.c.channel(), self.q, no_ack=True) - - for i in range(10): - producer.publish({'foo': i}, - routing_key='test_transport_filesystem') - - _received = [] - - def callback(message_data, message): - _received.append(message) - - consumer.register_callback(callback) - consumer.consume() - - while 1: - if len(_received) == 10: - break - self.c.drain_events() - - self.assertEqual(len(_received), 10) - - def test_produce_consume(self): - producer_channel = self.p.channel() - consumer_channel = self.c.channel() - producer = Producer(producer_channel, self.e) - consumer1 = Consumer(consumer_channel, self.q) - consumer2 = Consumer(consumer_channel, self.q2) - self.q2(consumer_channel).declare() - - for i in range(10): - producer.publish({'foo': i}, - routing_key='test_transport_filesystem') - for i in range(10): - producer.publish({'foo': i}, - routing_key='test_transport_filesystem2') - - _received1 = [] - _received2 = [] - - def callback1(message_data, message): - _received1.append(message) - message.ack() - - def callback2(message_data, message): - _received2.append(message) - message.ack() - - consumer1.register_callback(callback1) - consumer2.register_callback(callback2) - - consumer1.consume() - consumer2.consume() - - while 1: - if len(_received1) + len(_received2) == 20: - break - self.c.drain_events() - - self.assertEqual(len(_received1) + len(_received2), 20) - - # compression - producer.publish({'compressed': True}, - routing_key='test_transport_filesystem', - compression='zlib') - m = self.q(consumer_channel).get() - self.assertDictEqual(m.payload, {'compressed': True}) - - # queue.delete - for i in range(10): - producer.publish({'foo': i}, - routing_key='test_transport_filesystem') - self.assertTrue(self.q(consumer_channel).get()) - self.q(consumer_channel).delete() - self.q(consumer_channel).declare() - self.assertIsNone(self.q(consumer_channel).get()) - - # queue.purge - for i in range(10): - producer.publish({'foo': i}, - routing_key='test_transport_filesystem2') - self.assertTrue(self.q2(consumer_channel).get()) - self.q2(consumer_channel).purge() - self.assertIsNone(self.q2(consumer_channel).get()) diff --git a/awx/lib/site-packages/kombu/tests/transport/test_librabbitmq.py b/awx/lib/site-packages/kombu/tests/transport/test_librabbitmq.py deleted file mode 100644 index a50b26241a..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_librabbitmq.py +++ /dev/null @@ -1,150 +0,0 @@ -from __future__ import absolute_import - -try: - import librabbitmq -except ImportError: - librabbitmq = None # noqa -else: - from kombu.transport import librabbitmq # noqa - -from kombu.tests.case import Case, Mock, SkipTest, patch - - -class lrmqCase(Case): - - def setUp(self): - if librabbitmq is None: - raise SkipTest('librabbitmq is not installed') - - -class test_Message(lrmqCase): - - def test_init(self): - chan = Mock(name='channel') - message = librabbitmq.Message( - chan, {'prop': 42}, {'delivery_tag': 337}, 'body', - ) - self.assertEqual(message.body, 'body') - self.assertEqual(message.delivery_tag, 337) - self.assertEqual(message.properties['prop'], 42) - - -class test_Channel(lrmqCase): - - def test_prepare_message(self): - conn = Mock(name='connection') - chan = librabbitmq.Channel(conn, 1) - self.assertTrue(chan) - - body = 'the quick brown fox...' - properties = {'name': 'Elaine M.'} - - body2, props2 = chan.prepare_message( - body, properties=properties, - priority=999, - content_type='ctype', - content_encoding='cenc', - headers={'H': 2}, - ) - - self.assertEqual(props2['name'], 'Elaine M.') - self.assertEqual(props2['priority'], 999) - self.assertEqual(props2['content_type'], 'ctype') - self.assertEqual(props2['content_encoding'], 'cenc') - self.assertEqual(props2['headers'], {'H': 2}) - self.assertEqual(body2, body) - - body3, props3 = chan.prepare_message(body, priority=777) - self.assertEqual(props3['priority'], 777) - self.assertEqual(body3, body) - - -class test_Transport(lrmqCase): - - def setUp(self): - super(test_Transport, self).setUp() - self.client = Mock(name='client') - self.T = librabbitmq.Transport(self.client) - - def test_driver_version(self): - self.assertTrue(self.T.driver_version()) - - def test_create_channel(self): - conn = Mock(name='connection') - chan = self.T.create_channel(conn) - self.assertTrue(chan) - conn.channel.assert_called_with() - - def test_drain_events(self): - conn = Mock(name='connection') - self.T.drain_events(conn, timeout=1.33) - conn.drain_events.assert_called_with(timeout=1.33) - - def test_establish_connection_SSL_not_supported(self): - self.client.ssl = True - with self.assertRaises(NotImplementedError): - self.T.establish_connection() - - def test_establish_connection(self): - self.T.Connection = Mock(name='Connection') - self.T.client.ssl = False - self.T.client.port = None - self.T.client.transport_options = {} - - conn = self.T.establish_connection() - self.assertEqual( - self.T.client.port, - self.T.default_connection_params['port'], - ) - self.assertEqual(conn.client, self.T.client) - self.assertEqual(self.T.client.drain_events, conn.drain_events) - - def test_collect__no_conn(self): - self.T.client.drain_events = 1234 - self.T._collect(None) - self.assertIsNone(self.client.drain_events) - self.assertIsNone(self.T.client) - - def test_collect__with_conn(self): - self.T.client.drain_events = 1234 - conn = Mock(name='connection') - chans = conn.channels = {1: Mock(name='chan1'), 2: Mock(name='chan2')} - conn.callbacks = {'foo': Mock(name='cb1'), 'bar': Mock(name='cb2')} - for i, chan in enumerate(conn.channels.values()): - chan.connection = i - - with patch('os.close') as close: - self.T._collect(conn) - close.assert_called_with(conn.fileno()) - self.assertFalse(conn.channels) - self.assertFalse(conn.callbacks) - for chan in chans.values(): - self.assertIsNone(chan.connection) - self.assertIsNone(self.client.drain_events) - self.assertIsNone(self.T.client) - - with patch('os.close') as close: - self.T.client = self.client - close.side_effect = OSError() - self.T._collect(conn) - close.assert_called_with(conn.fileno()) - - def test_register_with_event_loop(self): - conn = Mock(name='conn') - loop = Mock(name='loop') - self.T.register_with_event_loop(conn, loop) - loop.add_reader.assert_called_with( - conn.fileno(), self.T.on_readable, conn, loop, - ) - - def test_verify_connection(self): - conn = Mock(name='connection') - conn.connected = True - self.assertTrue(self.T.verify_connection(conn)) - - def test_close_connection(self): - conn = Mock(name='connection') - self.client.drain_events = 1234 - self.T.close_connection(conn) - self.assertIsNone(self.client.drain_events) - conn.close.assert_called_with() diff --git a/awx/lib/site-packages/kombu/tests/transport/test_memory.py b/awx/lib/site-packages/kombu/tests/transport/test_memory.py deleted file mode 100644 index 605527f401..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_memory.py +++ /dev/null @@ -1,157 +0,0 @@ -from __future__ import absolute_import - -import socket - -from kombu import Connection, Exchange, Queue, Consumer, Producer - -from kombu.tests.case import Case - - -class test_MemoryTransport(Case): - - def setUp(self): - self.c = Connection(transport='memory') - self.e = Exchange('test_transport_memory') - self.q = Queue('test_transport_memory', - exchange=self.e, - routing_key='test_transport_memory') - self.q2 = Queue('test_transport_memory2', - exchange=self.e, - routing_key='test_transport_memory2') - self.fanout = Exchange('test_transport_memory_fanout', type='fanout') - self.q3 = Queue('test_transport_memory_fanout1', - exchange=self.fanout) - self.q4 = Queue('test_transport_memory_fanout2', - exchange=self.fanout) - - def test_driver_version(self): - self.assertTrue(self.c.transport.driver_version()) - - def test_produce_consume_noack(self): - channel = self.c.channel() - producer = Producer(channel, self.e) - consumer = Consumer(channel, self.q, no_ack=True) - - for i in range(10): - producer.publish({'foo': i}, routing_key='test_transport_memory') - - _received = [] - - def callback(message_data, message): - _received.append(message) - - consumer.register_callback(callback) - consumer.consume() - - while 1: - if len(_received) == 10: - break - self.c.drain_events() - - self.assertEqual(len(_received), 10) - - def test_produce_consume_fanout(self): - producer = self.c.Producer() - consumer = self.c.Consumer([self.q3, self.q4]) - - producer.publish( - {'hello': 'world'}, - declare=consumer.queues, - exchange=self.fanout, - ) - - self.assertEqual(self.q3(self.c).get().payload, {'hello': 'world'}) - self.assertEqual(self.q4(self.c).get().payload, {'hello': 'world'}) - self.assertIsNone(self.q3(self.c).get()) - self.assertIsNone(self.q4(self.c).get()) - - def test_produce_consume(self): - channel = self.c.channel() - producer = Producer(channel, self.e) - consumer1 = Consumer(channel, self.q) - consumer2 = Consumer(channel, self.q2) - self.q2(channel).declare() - - for i in range(10): - producer.publish({'foo': i}, routing_key='test_transport_memory') - for i in range(10): - producer.publish({'foo': i}, routing_key='test_transport_memory2') - - _received1 = [] - _received2 = [] - - def callback1(message_data, message): - _received1.append(message) - message.ack() - - def callback2(message_data, message): - _received2.append(message) - message.ack() - - consumer1.register_callback(callback1) - consumer2.register_callback(callback2) - - consumer1.consume() - consumer2.consume() - - while 1: - if len(_received1) + len(_received2) == 20: - break - self.c.drain_events() - - self.assertEqual(len(_received1) + len(_received2), 20) - - # compression - producer.publish({'compressed': True}, - routing_key='test_transport_memory', - compression='zlib') - m = self.q(channel).get() - self.assertDictEqual(m.payload, {'compressed': True}) - - # queue.delete - for i in range(10): - producer.publish({'foo': i}, routing_key='test_transport_memory') - self.assertTrue(self.q(channel).get()) - self.q(channel).delete() - self.q(channel).declare() - self.assertIsNone(self.q(channel).get()) - - # queue.purge - for i in range(10): - producer.publish({'foo': i}, routing_key='test_transport_memory2') - self.assertTrue(self.q2(channel).get()) - self.q2(channel).purge() - self.assertIsNone(self.q2(channel).get()) - - def test_drain_events(self): - with self.assertRaises(socket.timeout): - self.c.drain_events(timeout=0.1) - - c1 = self.c.channel() - c2 = self.c.channel() - - with self.assertRaises(socket.timeout): - self.c.drain_events(timeout=0.1) - - del(c1) # so pyflakes doesn't complain. - del(c2) - - def test_drain_events_unregistered_queue(self): - c1 = self.c.channel() - - class Cycle(object): - - def get(self, timeout=None): - return ('foo', 'foo'), c1 - - self.c.transport.cycle = Cycle() - with self.assertRaises(KeyError): - self.c.drain_events() - - def test_queue_for(self): - chan = self.c.channel() - chan.queues.clear() - - x = chan._queue_for('foo') - self.assertTrue(x) - self.assertIs(chan._queue_for('foo'), x) diff --git a/awx/lib/site-packages/kombu/tests/transport/test_mongodb.py b/awx/lib/site-packages/kombu/tests/transport/test_mongodb.py deleted file mode 100644 index b4d10fc5c2..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_mongodb.py +++ /dev/null @@ -1,120 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection - -from kombu.tests.case import Case, SkipTest, Mock, skip_if_not_module - - -class MockConnection(dict): - - def __setattr__(self, key, value): - self[key] = value - - -class test_mongodb(Case): - - def _get_connection(self, url, **kwargs): - from kombu.transport import mongodb - - class _Channel(mongodb.Channel): - - def _create_client(self): - self._client = Mock(name='client') - - class Transport(mongodb.Transport): - Connection = MockConnection - Channel = _Channel - - return Connection(url, transport=Transport, **kwargs).connect() - - @skip_if_not_module('pymongo') - def test_defaults(self): - url = 'mongodb://' - - c = self._get_connection(url) - hostname, dbname, options = c.channels[0]._parse_uri() - - self.assertEquals(dbname, 'kombu_default') - self.assertEquals(hostname, 'mongodb://127.0.0.1') - - @skip_if_not_module('pymongo') - def test_custom_host(self): - url = 'mongodb://localhost' - c = self._get_connection(url) - hostname, dbname, options = c.channels[0]._parse_uri() - - self.assertEquals(dbname, 'kombu_default') - - @skip_if_not_module('pymongo') - def test_custom_database(self): - url = 'mongodb://localhost/dbname' - c = self._get_connection(url) - hostname, dbname, options = c.channels[0]._parse_uri() - - self.assertEquals(dbname, 'dbname') - - @skip_if_not_module('pymongo') - def test_custom_credentials(self): - url = 'mongodb://localhost/dbname' - c = self._get_connection(url, userid='foo', password='bar') - hostname, dbname, options = c.channels[0]._parse_uri() - - self.assertEquals(hostname, 'mongodb://foo:bar@localhost/dbname') - self.assertEquals(dbname, 'dbname') - - @skip_if_not_module('pymongo') - def test_options(self): - url = 'mongodb://localhost,localhost2:29017/dbname?safe=true' - c = self._get_connection(url) - - hostname, dbname, options = c.channels[0]._parse_uri() - - self.assertEqual(options['safe'], True) - - @skip_if_not_module('pymongo') - def test_real_connections(self): - from pymongo.errors import ConfigurationError - - raise SkipTest( - 'Test is functional: it actually connects to mongod') - - url = 'mongodb://localhost,localhost:29017/dbname' - c = self._get_connection(url) - client = c.channels[0].client - - nodes = client.connection.nodes - # If there's just 1 node it is because we're connecting to a single - # server instead of a repl / mongoss. - if len(nodes) == 2: - self.assertTrue(('localhost', 29017) in nodes) - self.assertEquals(client.name, 'dbname') - - url = 'mongodb://localhost:27017,localhost2:29017/dbname' - c = self._get_connection(url) - client = c.channels[0].client - - # Login to admin db since there's no db specified - url = 'mongodb://adminusername:adminpassword@localhost' - c = self._get_connection() - client = c.channels[0].client - self.assertEquals(client.name, 'kombu_default') - - # Lets make sure that using admin db doesn't break anything - # when no user is specified - url = 'mongodb://localhost' - c = self._get_connection(url) - client = c.channels[0].client - - # Assuming there's user 'username' with password 'password' - # configured in mongodb - url = 'mongodb://username:password@localhost/dbname' - c = self._get_connection(url) - client = c.channels[0].client - - # Assuming there's no user 'nousername' with password 'nopassword' - # configured in mongodb - url = 'mongodb://nousername:nopassword@localhost/dbname' - c = self._get_connection(url) - - with self.assertRaises(ConfigurationError): - c.channels[0].client diff --git a/awx/lib/site-packages/kombu/tests/transport/test_pyamqp.py b/awx/lib/site-packages/kombu/tests/transport/test_pyamqp.py deleted file mode 100644 index d6a910b46e..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_pyamqp.py +++ /dev/null @@ -1,179 +0,0 @@ -from __future__ import absolute_import - -import sys - -from itertools import count - -try: - import amqp # noqa -except ImportError: - pyamqp = None # noqa -else: - from kombu.transport import pyamqp -from kombu import Connection -from kombu.five import nextfun - -from kombu.tests.case import Case, Mock, SkipTest, mask_modules, patch - - -class MockConnection(dict): - - def __setattr__(self, key, value): - self[key] = value - - -class test_Channel(Case): - - def setUp(self): - if pyamqp is None: - raise SkipTest('py-amqp not installed') - - class Channel(pyamqp.Channel): - wait_returns = [] - - def _x_open(self, *args, **kwargs): - pass - - def wait(self, *args, **kwargs): - return self.wait_returns - - def _send_method(self, *args, **kwargs): - pass - - self.conn = Mock() - self.conn._get_free_channel_id.side_effect = nextfun(count(0)) - self.conn.channels = {} - self.channel = Channel(self.conn, 0) - - def test_init(self): - self.assertFalse(self.channel.no_ack_consumers) - - def test_prepare_message(self): - self.assertTrue(self.channel.prepare_message( - 'foobar', 10, 'application/data', 'utf-8', - properties={}, - )) - - def test_message_to_python(self): - message = Mock() - message.headers = {} - message.properties = {} - self.assertTrue(self.channel.message_to_python(message)) - - def test_close_resolves_connection_cycle(self): - self.assertIsNotNone(self.channel.connection) - self.channel.close() - self.assertIsNone(self.channel.connection) - - def test_basic_consume_registers_ack_status(self): - self.channel.wait_returns = 'my-consumer-tag' - self.channel.basic_consume('foo', no_ack=True) - self.assertIn('my-consumer-tag', self.channel.no_ack_consumers) - - self.channel.wait_returns = 'other-consumer-tag' - self.channel.basic_consume('bar', no_ack=False) - self.assertNotIn('other-consumer-tag', self.channel.no_ack_consumers) - - self.channel.basic_cancel('my-consumer-tag') - self.assertNotIn('my-consumer-tag', self.channel.no_ack_consumers) - - -class test_Transport(Case): - - def setUp(self): - if pyamqp is None: - raise SkipTest('py-amqp not installed') - self.connection = Connection('pyamqp://') - self.transport = self.connection.transport - - def test_create_channel(self): - connection = Mock() - self.transport.create_channel(connection) - connection.channel.assert_called_with() - - def test_driver_version(self): - self.assertTrue(self.transport.driver_version()) - - def test_drain_events(self): - connection = Mock() - self.transport.drain_events(connection, timeout=10.0) - connection.drain_events.assert_called_with(timeout=10.0) - - def test_dnspython_localhost_resolve_bug(self): - - class Conn(object): - - def __init__(self, **kwargs): - vars(self).update(kwargs) - - self.transport.Connection = Conn - self.transport.client.hostname = 'localhost' - conn1 = self.transport.establish_connection() - self.assertEqual(conn1.host, '127.0.0.1:5672') - - self.transport.client.hostname = 'example.com' - conn2 = self.transport.establish_connection() - self.assertEqual(conn2.host, 'example.com:5672') - - def test_close_connection(self): - connection = Mock() - connection.client = Mock() - self.transport.close_connection(connection) - - self.assertIsNone(connection.client) - connection.close.assert_called_with() - - @mask_modules('ssl') - def test_import_no_ssl(self): - pm = sys.modules.pop('amqp.connection') - try: - from amqp.connection import SSLError - self.assertEqual(SSLError.__module__, 'amqp.connection') - finally: - if pm is not None: - sys.modules['amqp.connection'] = pm - - -class test_pyamqp(Case): - - def setUp(self): - if pyamqp is None: - raise SkipTest('py-amqp not installed') - - def test_default_port(self): - - class Transport(pyamqp.Transport): - Connection = MockConnection - - c = Connection(port=None, transport=Transport).connect() - self.assertEqual(c['host'], - '127.0.0.1:%s' % (Transport.default_port, )) - - def test_custom_port(self): - - class Transport(pyamqp.Transport): - Connection = MockConnection - - c = Connection(port=1337, transport=Transport).connect() - self.assertEqual(c['host'], '127.0.0.1:1337') - - def test_register_with_event_loop(self): - t = pyamqp.Transport(Mock()) - conn = Mock(name='conn') - loop = Mock(name='loop') - t.register_with_event_loop(conn, loop) - loop.add_reader.assert_called_with( - conn.sock, t.on_readable, conn, loop, - ) - - def test_heartbeat_check(self): - t = pyamqp.Transport(Mock()) - conn = Mock() - t.heartbeat_check(conn, rate=4.331) - conn.heartbeat_tick.assert_called_with(rate=4.331) - - def test_get_manager(self): - with patch('kombu.transport.pyamqp.get_manager') as get_manager: - t = pyamqp.Transport(Mock()) - t.get_manager(1, kw=2) - get_manager.assert_called_with(t.client, 1, kw=2) diff --git a/awx/lib/site-packages/kombu/tests/transport/test_redis.py b/awx/lib/site-packages/kombu/tests/transport/test_redis.py deleted file mode 100644 index 17f2dcc4ac..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_redis.py +++ /dev/null @@ -1,1237 +0,0 @@ -from __future__ import absolute_import - -import socket -import types - -from anyjson import dumps, loads -from collections import defaultdict -from itertools import count - -from kombu import Connection, Exchange, Queue, Consumer, Producer -from kombu.exceptions import InconsistencyError, VersionMismatch -from kombu.five import Empty, Queue as _Queue -from kombu.transport import virtual -from kombu.utils import eventio # patch poll - -from kombu.tests.case import ( - Case, Mock, call, module_exists, skip_if_not_module, patch, -) - - -class _poll(eventio._select): - - def register(self, fd, flags): - if flags & eventio.READ: - self._rfd.add(fd) - - def poll(self, timeout): - events = [] - for fd in self._rfd: - if fd.data: - events.append((fd.fileno(), eventio.READ)) - return events - - -eventio.poll = _poll -from kombu.transport import redis # must import after poller patch - - -class ResponseError(Exception): - pass - - -class Client(object): - queues = {} - sets = defaultdict(set) - hashes = defaultdict(dict) - shard_hint = None - - def __init__(self, db=None, port=None, connection_pool=None, **kwargs): - self._called = [] - self._connection = None - self.bgsave_raises_ResponseError = False - self.connection = self._sconnection(self) - - def bgsave(self): - self._called.append('BGSAVE') - if self.bgsave_raises_ResponseError: - raise ResponseError() - - def delete(self, key): - self.queues.pop(key, None) - - def exists(self, key): - return key in self.queues or key in self.sets - - def hset(self, key, k, v): - self.hashes[key][k] = v - - def hget(self, key, k): - return self.hashes[key].get(k) - - def hdel(self, key, k): - self.hashes[key].pop(k, None) - - def sadd(self, key, member, *args): - self.sets[key].add(member) - zadd = sadd - - def smembers(self, key): - return self.sets.get(key, set()) - - def srem(self, key, *args): - self.sets.pop(key, None) - zrem = srem - - def llen(self, key): - try: - return self.queues[key].qsize() - except KeyError: - return 0 - - def lpush(self, key, value): - self.queues[key].put_nowait(value) - - def parse_response(self, connection, type, **options): - cmd, queues = self.connection._sock.data.pop() - assert cmd == type - self.connection._sock.data = [] - if type == 'BRPOP': - item = self.brpop(queues, 0.001) - if item: - return item - raise Empty() - - def brpop(self, keys, timeout=None): - key = keys[0] - try: - item = self.queues[key].get(timeout=timeout) - except Empty: - pass - else: - return key, item - - def rpop(self, key): - try: - return self.queues[key].get_nowait() - except KeyError: - pass - - def __contains__(self, k): - return k in self._called - - def pipeline(self): - return Pipeline(self) - - def encode(self, value): - return str(value) - - def _new_queue(self, key): - self.queues[key] = _Queue() - - class _sconnection(object): - disconnected = False - - class _socket(object): - blocking = True - filenos = count(30) - - def __init__(self, *args): - self._fileno = next(self.filenos) - self.data = [] - - def fileno(self): - return self._fileno - - def setblocking(self, blocking): - self.blocking = blocking - - def __init__(self, client): - self.client = client - self._sock = self._socket() - - def disconnect(self): - self.disconnected = True - - def send_command(self, cmd, *args): - self._sock.data.append((cmd, args)) - - def info(self): - return {'foo': 1} - - def pubsub(self, *args, **kwargs): - connection = self.connection - - class ConnectionPool(object): - - def get_connection(self, *args, **kwargs): - return connection - self.connection_pool = ConnectionPool() - - return self - - -class Pipeline(object): - - def __init__(self, client): - self.client = client - self.stack = [] - - def __getattr__(self, key): - if key not in self.__dict__: - - def _add(*args, **kwargs): - self.stack.append((getattr(self.client, key), args, kwargs)) - return self - - return _add - return self.__dict__[key] - - def execute(self): - stack = list(self.stack) - self.stack[:] = [] - return [fun(*args, **kwargs) for fun, args, kwargs in stack] - - -class Channel(redis.Channel): - - def _get_client(self): - return Client - - def _get_pool(self): - return Mock() - - def _get_response_error(self): - return ResponseError - - def _new_queue(self, queue, **kwargs): - self.client._new_queue(queue) - - def pipeline(self): - return Pipeline(Client()) - - -class Transport(redis.Transport): - Channel = Channel - - def _get_errors(self): - return ((KeyError, ), (IndexError, )) - - -class test_Channel(Case): - - @skip_if_not_module('redis') - def setUp(self): - self.connection = self.create_connection() - self.channel = self.connection.default_channel - - def create_connection(self, **kwargs): - kwargs.setdefault('transport_options', {'fanout_patterns': True}) - return Connection(transport=Transport, **kwargs) - - def _get_one_delivery_tag(self, n='test_uniq_tag'): - with self.create_connection() as conn1: - chan = conn1.default_channel - chan.exchange_declare(n) - chan.queue_declare(n) - chan.queue_bind(n, n, n) - msg = chan.prepare_message('quick brown fox') - chan.basic_publish(msg, n, n) - q, payload = chan.client.brpop([n]) - self.assertEqual(q, n) - self.assertTrue(payload) - pymsg = chan.message_to_python(loads(payload)) - return pymsg.delivery_tag - - def test_delivery_tag_is_uuid(self): - seen = set() - for i in range(100): - tag = self._get_one_delivery_tag() - self.assertNotIn(tag, seen) - seen.add(tag) - with self.assertRaises(ValueError): - int(tag) - self.assertEqual(len(tag), 36) - - def test_disable_ack_emulation(self): - conn = Connection(transport=Transport, transport_options={ - 'ack_emulation': False, - }) - - chan = conn.channel() - self.assertFalse(chan.ack_emulation) - self.assertEqual(chan.QoS, virtual.QoS) - - def test_redis_info_raises(self): - pool = Mock(name='pool') - pool_at_init = [pool] - client = Mock(name='client') - - class XChannel(Channel): - - def __init__(self, *args, **kwargs): - self._pool = pool_at_init[0] - super(XChannel, self).__init__(*args, **kwargs) - - def _get_client(self): - return lambda *_, **__: client - - class XTransport(Transport): - Channel = XChannel - - conn = Connection(transport=XTransport) - client.info.side_effect = RuntimeError() - with self.assertRaises(RuntimeError): - conn.channel() - pool.disconnect.assert_called_with() - pool.disconnect.reset_mock() - - pool_at_init = [None] - with self.assertRaises(RuntimeError): - conn.channel() - self.assertFalse(pool.disconnect.called) - - def test_after_fork(self): - self.channel._pool = None - self.channel._after_fork() - - self.channel._pool = Mock(name='pool') - self.channel._after_fork() - self.channel._pool.disconnect.assert_called_with() - - def test_next_delivery_tag(self): - self.assertNotEqual( - self.channel._next_delivery_tag(), - self.channel._next_delivery_tag(), - ) - - def test_do_restore_message(self): - client = Mock(name='client') - pl1 = {'body': 'BODY'} - spl1 = dumps(pl1) - lookup = self.channel._lookup = Mock(name='_lookup') - lookup.return_value = ['george', 'elaine'] - self.channel._do_restore_message( - pl1, 'ex', 'rkey', client, - ) - client.rpush.assert_has_calls([ - call('george', spl1), call('elaine', spl1), - ]) - - pl2 = {'body': 'BODY2', 'headers': {'x-funny': 1}} - headers_after = dict(pl2['headers'], redelivered=True) - spl2 = dumps(dict(pl2, headers=headers_after)) - self.channel._do_restore_message( - pl2, 'ex', 'rkey', client, - ) - client.rpush.assert_has_calls([ - call('george', spl2), call('elaine', spl2), - ]) - - client.rpush.side_effect = KeyError() - with patch('kombu.transport.redis.crit') as crit: - self.channel._do_restore_message( - pl2, 'ex', 'rkey', client, - ) - self.assertTrue(crit.called) - - def test_restore(self): - message = Mock(name='message') - with patch('kombu.transport.redis.loads') as loads: - loads.return_value = 'M', 'EX', 'RK' - client = self.channel.client = Mock(name='client') - restore = self.channel._do_restore_message = Mock( - name='_do_restore_message', - ) - pipe = Mock(name='pipe') - client.pipeline.return_value = pipe - pipe_hget = Mock(name='pipe.hget') - pipe.hget.return_value = pipe_hget - pipe_hget_hdel = Mock(name='pipe.hget.hdel') - pipe_hget.hdel.return_value = pipe_hget_hdel - result = Mock(name='result') - pipe_hget_hdel.execute.return_value = None, None - - self.channel._restore(message) - client.pipeline.assert_called_with() - unacked_key = self.channel.unacked_key - self.assertFalse(loads.called) - - tag = message.delivery_tag - pipe.hget.assert_called_with(unacked_key, tag) - pipe_hget.hdel.assert_called_with(unacked_key, tag) - pipe_hget_hdel.execute.assert_called_with() - - pipe_hget_hdel.execute.return_value = result, None - self.channel._restore(message) - loads.assert_called_with(result) - restore.assert_called_with('M', 'EX', 'RK', client, False) - - def test_qos_restore_visible(self): - client = self.channel.client = Mock(name='client') - client.zrevrangebyscore.return_value = [ - (1, 10), - (2, 20), - (3, 30), - ] - qos = redis.QoS(self.channel) - restore = qos.restore_by_tag = Mock(name='restore_by_tag') - qos._vrestore_count = 1 - qos.restore_visible() - self.assertFalse(client.zrevrangebyscore.called) - self.assertEqual(qos._vrestore_count, 2) - - qos._vrestore_count = 0 - qos.restore_visible() - restore.assert_has_calls([ - call(1, client), call(2, client), call(3, client), - ]) - self.assertEqual(qos._vrestore_count, 1) - - qos._vrestore_count = 0 - restore.reset_mock() - client.zrevrangebyscore.return_value = [] - qos.restore_visible() - self.assertFalse(restore.called) - self.assertEqual(qos._vrestore_count, 1) - - qos._vrestore_count = 0 - client.setnx.side_effect = redis.MutexHeld() - qos.restore_visible() - - def test_basic_consume_when_fanout_queue(self): - self.channel.exchange_declare(exchange='txconfan', type='fanout') - self.channel.queue_declare(queue='txconfanq') - self.channel.queue_bind(queue='txconfanq', exchange='txconfan') - - self.assertIn('txconfanq', self.channel._fanout_queues) - self.channel.basic_consume('txconfanq', False, None, 1) - self.assertIn('txconfanq', self.channel.active_fanout_queues) - self.assertEqual(self.channel._fanout_to_queue.get('txconfan'), - 'txconfanq') - - def test_basic_cancel_unknown_delivery_tag(self): - self.assertIsNone(self.channel.basic_cancel('txaseqwewq')) - - def test_subscribe_no_queues(self): - self.channel.subclient = Mock() - self.channel.active_fanout_queues.clear() - self.channel._subscribe() - - self.assertFalse(self.channel.subclient.subscribe.called) - - def test_subscribe(self): - self.channel.subclient = Mock() - self.channel.active_fanout_queues.add('a') - self.channel.active_fanout_queues.add('b') - self.channel._fanout_queues.update(a=('a', ''), b=('b', '')) - - self.channel._subscribe() - self.assertTrue(self.channel.subclient.psubscribe.called) - s_args, _ = self.channel.subclient.psubscribe.call_args - self.assertItemsEqual(s_args[0], ['a', 'b']) - - self.channel.subclient.connection._sock = None - self.channel._subscribe() - self.channel.subclient.connection.connect.assert_called_with() - - def test_handle_unsubscribe_message(self): - s = self.channel.subclient - s.subscribed = True - self.channel._handle_message(s, ['unsubscribe', 'a', 0]) - self.assertFalse(s.subscribed) - - def test_handle_pmessage_message(self): - self.assertDictEqual( - self.channel._handle_message( - self.channel.subclient, - ['pmessage', 'pattern', 'channel', 'data'], - ), - { - 'type': 'pmessage', - 'pattern': 'pattern', - 'channel': 'channel', - 'data': 'data', - }, - ) - - def test_handle_message(self): - self.assertDictEqual( - self.channel._handle_message( - self.channel.subclient, - ['type', 'channel', 'data'], - ), - { - 'type': 'type', - 'pattern': None, - 'channel': 'channel', - 'data': 'data', - }, - ) - - def test_brpop_start_but_no_queues(self): - self.assertIsNone(self.channel._brpop_start()) - - def test_receive(self): - s = self.channel.subclient = Mock() - self.channel._fanout_to_queue['a'] = 'b' - s.parse_response.return_value = ['message', 'a', - dumps({'hello': 'world'})] - payload, queue = self.channel._receive() - self.assertDictEqual(payload, {'hello': 'world'}) - self.assertEqual(queue, 'b') - - def test_receive_raises(self): - self.channel._in_listen = True - s = self.channel.subclient = Mock() - s.parse_response.side_effect = KeyError('foo') - - with self.assertRaises(redis.Empty): - self.channel._receive() - self.assertFalse(self.channel._in_listen) - - def test_receive_empty(self): - s = self.channel.subclient = Mock() - s.parse_response.return_value = None - - with self.assertRaises(redis.Empty): - self.channel._receive() - - def test_receive_different_message_Type(self): - s = self.channel.subclient = Mock() - s.parse_response.return_value = ['message', '/foo/', 0, 'data'] - - with self.assertRaises(redis.Empty): - self.channel._receive() - - def test_brpop_read_raises(self): - c = self.channel.client = Mock() - c.parse_response.side_effect = KeyError('foo') - - with self.assertRaises(redis.Empty): - self.channel._brpop_read() - - c.connection.disconnect.assert_called_with() - - def test_brpop_read_gives_None(self): - c = self.channel.client = Mock() - c.parse_response.return_value = None - - with self.assertRaises(redis.Empty): - self.channel._brpop_read() - - def test_poll_error(self): - c = self.channel.client = Mock() - c.parse_response = Mock() - self.channel._poll_error('BRPOP') - - c.parse_response.assert_called_with(c.connection, 'BRPOP') - - c.parse_response.side_effect = KeyError('foo') - with self.assertRaises(KeyError): - self.channel._poll_error('BRPOP') - - def test_poll_error_on_type_LISTEN(self): - c = self.channel.subclient = Mock() - c.parse_response = Mock() - self.channel._poll_error('LISTEN') - - c.parse_response.assert_called_with() - - c.parse_response.side_effect = KeyError('foo') - with self.assertRaises(KeyError): - self.channel._poll_error('LISTEN') - - def test_put_fanout(self): - self.channel._in_poll = False - c = self.channel.client = Mock() - - body = {'hello': 'world'} - self.channel._put_fanout('exchange', body, '') - c.publish.assert_called_with('exchange', dumps(body)) - - def test_put_priority(self): - client = self.channel.client = Mock(name='client') - msg1 = {'properties': {'delivery_info': {'priority': 3}}} - - self.channel._put('george', msg1) - client.lpush.assert_called_with( - self.channel._q_for_pri('george', 3), dumps(msg1), - ) - - msg2 = {'properties': {'delivery_info': {'priority': 313}}} - self.channel._put('george', msg2) - client.lpush.assert_called_with( - self.channel._q_for_pri('george', 9), dumps(msg2), - ) - - msg3 = {'properties': {'delivery_info': {}}} - self.channel._put('george', msg3) - client.lpush.assert_called_with( - self.channel._q_for_pri('george', 0), dumps(msg3), - ) - - def test_delete(self): - x = self.channel - self.channel._in_poll = False - delete = x.client.delete = Mock() - srem = x.client.srem = Mock() - - x._delete('queue', 'exchange', 'routing_key', None) - delete.assert_has_call('queue') - srem.assert_has_call(x.keyprefix_queue % ('exchange', ), - x.sep.join(['routing_key', '', 'queue'])) - - def test_has_queue(self): - self.channel._in_poll = False - exists = self.channel.client.exists = Mock() - exists.return_value = True - self.assertTrue(self.channel._has_queue('foo')) - exists.assert_has_call('foo') - - exists.return_value = False - self.assertFalse(self.channel._has_queue('foo')) - - def test_close_when_closed(self): - self.channel.closed = True - self.channel.close() - - def test_close_deletes_autodelete_fanout_queues(self): - self.channel._fanout_queues = {'foo': ('foo', ''), 'bar': ('bar', '')} - self.channel.auto_delete_queues = ['foo'] - self.channel.queue_delete = Mock(name='queue_delete') - - self.channel.close() - self.channel.queue_delete.assert_has_calls([call('foo')]) - - def test_close_client_close_raises(self): - c = self.channel.client = Mock() - c.connection.disconnect.side_effect = self.channel.ResponseError() - - self.channel.close() - c.connection.disconnect.assert_called_with() - - def test_invalid_database_raises_ValueError(self): - - with self.assertRaises(ValueError): - self.channel.connection.client.virtual_host = 'dwqeq' - self.channel._connparams() - - @skip_if_not_module('redis') - def test_connparams_allows_slash_in_db(self): - self.channel.connection.client.virtual_host = '/123' - self.assertEqual(self.channel._connparams()['db'], 123) - - @skip_if_not_module('redis') - def test_connparams_db_can_be_int(self): - self.channel.connection.client.virtual_host = 124 - self.assertEqual(self.channel._connparams()['db'], 124) - - def test_new_queue_with_auto_delete(self): - redis.Channel._new_queue(self.channel, 'george', auto_delete=False) - self.assertNotIn('george', self.channel.auto_delete_queues) - redis.Channel._new_queue(self.channel, 'elaine', auto_delete=True) - self.assertIn('elaine', self.channel.auto_delete_queues) - - @skip_if_not_module('redis') - def test_connparams_regular_hostname(self): - self.channel.connection.client.hostname = 'george.vandelay.com' - self.assertEqual( - self.channel._connparams()['host'], - 'george.vandelay.com', - ) - - def test_rotate_cycle_ValueError(self): - cycle = self.channel._queue_cycle = ['kramer', 'jerry'] - self.channel._rotate_cycle('kramer') - self.assertEqual(cycle, ['jerry', 'kramer']) - self.channel._rotate_cycle('elaine') - - @skip_if_not_module('redis') - def test_get_client(self): - import redis as R - KombuRedis = redis.Channel._get_client(self.channel) - self.assertTrue(KombuRedis) - - Rv = getattr(R, 'VERSION', None) - try: - R.VERSION = (2, 4, 0) - with self.assertRaises(VersionMismatch): - redis.Channel._get_client(self.channel) - finally: - if Rv is not None: - R.VERSION = Rv - - @skip_if_not_module('redis') - def test_get_response_error(self): - from redis.exceptions import ResponseError - self.assertIs(redis.Channel._get_response_error(self.channel), - ResponseError) - - def test_avail_client_when_not_in_poll(self): - self.channel._in_poll = False - c = self.channel.client = Mock() - - with self.channel.conn_or_acquire() as client: - self.assertIs(client, c) - - def test_avail_client_when_in_poll(self): - self.channel._in_poll = True - self.channel._pool = Mock() - cc = self.channel._create_client = Mock() - client = cc.return_value = Mock() - - with self.channel.conn_or_acquire(): - pass - self.channel.pool.release.assert_called_with(client.connection) - cc.assert_called_with() - - def test_register_with_event_loop(self): - transport = self.connection.transport - transport.cycle = Mock(name='cycle') - transport.cycle.fds = {12: 'LISTEN', 13: 'BRPOP'} - conn = Mock(name='conn') - loop = Mock(name='loop') - redis.Transport.register_with_event_loop(transport, conn, loop) - transport.cycle.on_poll_init.assert_called_with(loop.poller) - loop.call_repeatedly.assert_called_with( - 10, transport.cycle.maybe_restore_messages, - ) - self.assertTrue(loop.on_tick.add.called) - on_poll_start = loop.on_tick.add.call_args[0][0] - - on_poll_start() - transport.cycle.on_poll_start.assert_called_with() - loop.add_reader.assert_has_calls([ - call(12, transport.on_readable, 12), - call(13, transport.on_readable, 13), - ]) - - def test_transport_on_readable(self): - transport = self.connection.transport - cycle = transport.cycle = Mock(name='cyle') - cycle.on_readable.return_value = None - - redis.Transport.on_readable(transport, 13) - cycle.on_readable.assert_called_with(13) - cycle.on_readable.reset_mock() - - queue = Mock(name='queue') - ret = (Mock(name='message'), queue) - cycle.on_readable.return_value = ret - with self.assertRaises(KeyError): - redis.Transport.on_readable(transport, 14) - - cb = transport._callbacks[queue] = Mock(name='callback') - redis.Transport.on_readable(transport, 14) - cb.assert_called_with(ret[0]) - - @skip_if_not_module('redis') - def test_transport_get_errors(self): - self.assertTrue(redis.Transport._get_errors(self.connection.transport)) - - @skip_if_not_module('redis') - def test_transport_driver_version(self): - self.assertTrue( - redis.Transport.driver_version(self.connection.transport), - ) - - @skip_if_not_module('redis') - def test_transport_get_errors_when_InvalidData_used(self): - from redis import exceptions - - class ID(Exception): - pass - - DataError = getattr(exceptions, 'DataError', None) - InvalidData = getattr(exceptions, 'InvalidData', None) - exceptions.InvalidData = ID - exceptions.DataError = None - try: - errors = redis.Transport._get_errors(self.connection.transport) - self.assertTrue(errors) - self.assertIn(ID, errors[1]) - finally: - if DataError is not None: - exceptions.DataError = DataError - if InvalidData is not None: - exceptions.InvalidData = InvalidData - - def test_empty_queues_key(self): - channel = self.channel - channel._in_poll = False - key = channel.keyprefix_queue % 'celery' - - # Everything is fine, there is a list of queues. - channel.client.sadd(key, 'celery\x06\x16\x06\x16celery') - self.assertListEqual(channel.get_table('celery'), - [('celery', '', 'celery')]) - - # ... then for some reason, the _kombu.binding.celery key gets lost - channel.client.srem(key) - - # which raises a channel error so that the consumer/publisher - # can recover by redeclaring the required entities. - with self.assertRaises(InconsistencyError): - self.channel.get_table('celery') - - @skip_if_not_module('redis') - def test_socket_connection(self): - with patch('kombu.transport.redis.Channel._create_client'): - with Connection('redis+socket:///tmp/redis.sock') as conn: - connparams = conn.default_channel._connparams() - self.assertTrue(issubclass( - connparams['connection_class'], - redis.redis.UnixDomainSocketConnection, - )) - self.assertEqual(connparams['path'], '/tmp/redis.sock') - - -class test_Redis(Case): - - @skip_if_not_module('redis') - def setUp(self): - self.connection = Connection(transport=Transport) - self.exchange = Exchange('test_Redis', type='direct') - self.queue = Queue('test_Redis', self.exchange, 'test_Redis') - - def tearDown(self): - self.connection.close() - - def test_publish__get(self): - channel = self.connection.channel() - producer = Producer(channel, self.exchange, routing_key='test_Redis') - self.queue(channel).declare() - - producer.publish({'hello': 'world'}) - - self.assertDictEqual(self.queue(channel).get().payload, - {'hello': 'world'}) - self.assertIsNone(self.queue(channel).get()) - self.assertIsNone(self.queue(channel).get()) - self.assertIsNone(self.queue(channel).get()) - - def test_publish__consume(self): - connection = Connection(transport=Transport) - channel = connection.channel() - producer = Producer(channel, self.exchange, routing_key='test_Redis') - consumer = Consumer(channel, queues=[self.queue]) - - producer.publish({'hello2': 'world2'}) - _received = [] - - def callback(message_data, message): - _received.append(message_data) - message.ack() - - consumer.register_callback(callback) - consumer.consume() - - self.assertIn(channel, channel.connection.cycle._channels) - try: - connection.drain_events(timeout=1) - self.assertTrue(_received) - with self.assertRaises(socket.timeout): - connection.drain_events(timeout=0.01) - finally: - channel.close() - - def test_purge(self): - channel = self.connection.channel() - producer = Producer(channel, self.exchange, routing_key='test_Redis') - self.queue(channel).declare() - - for i in range(10): - producer.publish({'hello': 'world-%s' % (i, )}) - - self.assertEqual(channel._size('test_Redis'), 10) - self.assertEqual(self.queue(channel).purge(), 10) - channel.close() - - def test_db_values(self): - Connection(virtual_host=1, - transport=Transport).channel() - - Connection(virtual_host='1', - transport=Transport).channel() - - Connection(virtual_host='/1', - transport=Transport).channel() - - with self.assertRaises(Exception): - Connection('redis:///foo').channel() - - def test_db_port(self): - c1 = Connection(port=None, transport=Transport).channel() - c1.close() - - c2 = Connection(port=9999, transport=Transport).channel() - c2.close() - - def test_close_poller_not_active(self): - c = Connection(transport=Transport).channel() - cycle = c.connection.cycle - c.client.connection - c.close() - self.assertNotIn(c, cycle._channels) - - def test_close_ResponseError(self): - c = Connection(transport=Transport).channel() - c.client.bgsave_raises_ResponseError = True - c.close() - - def test_close_disconnects(self): - c = Connection(transport=Transport).channel() - conn1 = c.client.connection - conn2 = c.subclient.connection - c.close() - self.assertTrue(conn1.disconnected) - self.assertTrue(conn2.disconnected) - - def test_get__Empty(self): - channel = self.connection.channel() - with self.assertRaises(Empty): - channel._get('does-not-exist') - channel.close() - - def test_get_client(self): - - myredis, exceptions = _redis_modules() - - @module_exists(myredis, exceptions) - def _do_test(): - conn = Connection(transport=Transport) - chan = conn.channel() - self.assertTrue(chan.Client) - self.assertTrue(chan.ResponseError) - self.assertTrue(conn.transport.connection_errors) - self.assertTrue(conn.transport.channel_errors) - - _do_test() - - -def _redis_modules(): - - class ConnectionError(Exception): - pass - - class AuthenticationError(Exception): - pass - - class InvalidData(Exception): - pass - - class InvalidResponse(Exception): - pass - - class ResponseError(Exception): - pass - - exceptions = types.ModuleType('redis.exceptions') - exceptions.ConnectionError = ConnectionError - exceptions.AuthenticationError = AuthenticationError - exceptions.InvalidData = InvalidData - exceptions.InvalidResponse = InvalidResponse - exceptions.ResponseError = ResponseError - - class Redis(object): - pass - - myredis = types.ModuleType('redis') - myredis.exceptions = exceptions - myredis.Redis = Redis - - return myredis, exceptions - - -class test_MultiChannelPoller(Case): - - @skip_if_not_module('redis') - def setUp(self): - self.Poller = redis.MultiChannelPoller - - def test_on_poll_start(self): - p = self.Poller() - p._channels = [] - p.on_poll_start() - p._register_BRPOP = Mock(name='_register_BRPOP') - p._register_LISTEN = Mock(name='_register_LISTEN') - - chan1 = Mock(name='chan1') - p._channels = [chan1] - chan1.active_queues = [] - chan1.active_fanout_queues = [] - p.on_poll_start() - - chan1.active_queues = ['q1'] - chan1.active_fanout_queues = ['q2'] - chan1.qos.can_consume.return_value = False - - p.on_poll_start() - p._register_LISTEN.assert_called_with(chan1) - self.assertFalse(p._register_BRPOP.called) - - chan1.qos.can_consume.return_value = True - p._register_LISTEN.reset_mock() - p.on_poll_start() - - p._register_BRPOP.assert_called_with(chan1) - p._register_LISTEN.assert_called_with(chan1) - - def test_on_poll_init(self): - p = self.Poller() - chan1 = Mock(name='chan1') - p._channels = [] - poller = Mock(name='poller') - p.on_poll_init(poller) - self.assertIs(p.poller, poller) - - p._channels = [chan1] - p.on_poll_init(poller) - chan1.qos.restore_visible.assert_called_with( - num=chan1.unacked_restore_limit, - ) - - def test_handle_event(self): - p = self.Poller() - chan = Mock(name='chan') - p._fd_to_chan[13] = chan, 'BRPOP' - chan.handlers = {'BRPOP': Mock(name='BRPOP')} - - chan.qos.can_consume.return_value = False - p.handle_event(13, redis.READ) - self.assertFalse(chan.handlers['BRPOP'].called) - - chan.qos.can_consume.return_value = True - p.handle_event(13, redis.READ) - chan.handlers['BRPOP'].assert_called_with() - - p.handle_event(13, redis.ERR) - chan._poll_error.assert_called_with('BRPOP') - - p.handle_event(13, ~(redis.READ | redis.ERR)) - - def test_fds(self): - p = self.Poller() - p._fd_to_chan = {1: 2} - self.assertDictEqual(p.fds, p._fd_to_chan) - - def test_close_unregisters_fds(self): - p = self.Poller() - poller = p.poller = Mock() - p._chan_to_sock.update({1: 1, 2: 2, 3: 3}) - - p.close() - - self.assertEqual(poller.unregister.call_count, 3) - u_args = poller.unregister.call_args_list - - self.assertItemsEqual(u_args, [((1, ), {}), - ((2, ), {}), - ((3, ), {})]) - - def test_close_when_unregister_raises_KeyError(self): - p = self.Poller() - p.poller = Mock() - p._chan_to_sock.update({1: 1}) - p.poller.unregister.side_effect = KeyError(1) - p.close() - - def test_close_resets_state(self): - p = self.Poller() - p.poller = Mock() - p._channels = Mock() - p._fd_to_chan = Mock() - p._chan_to_sock = Mock() - - p._chan_to_sock.itervalues.return_value = [] - p._chan_to_sock.values.return_value = [] # py3k - - p.close() - p._channels.clear.assert_called_with() - p._fd_to_chan.clear.assert_called_with() - p._chan_to_sock.clear.assert_called_with() - - def test_register_when_registered_reregisters(self): - p = self.Poller() - p.poller = Mock() - channel, client, type = Mock(), Mock(), Mock() - sock = client.connection._sock = Mock() - sock.fileno.return_value = 10 - - p._chan_to_sock = {(channel, client, type): 6} - p._register(channel, client, type) - p.poller.unregister.assert_called_with(6) - self.assertTupleEqual(p._fd_to_chan[10], (channel, type)) - self.assertEqual(p._chan_to_sock[(channel, client, type)], sock) - p.poller.register.assert_called_with(sock, p.eventflags) - - # when client not connected yet - client.connection._sock = None - - def after_connected(): - client.connection._sock = Mock() - client.connection.connect.side_effect = after_connected - - p._register(channel, client, type) - client.connection.connect.assert_called_with() - - def test_register_BRPOP(self): - p = self.Poller() - channel = Mock() - channel.client.connection._sock = None - p._register = Mock() - - channel._in_poll = False - p._register_BRPOP(channel) - self.assertEqual(channel._brpop_start.call_count, 1) - self.assertEqual(p._register.call_count, 1) - - channel.client.connection._sock = Mock() - p._chan_to_sock[(channel, channel.client, 'BRPOP')] = True - channel._in_poll = True - p._register_BRPOP(channel) - self.assertEqual(channel._brpop_start.call_count, 1) - self.assertEqual(p._register.call_count, 1) - - def test_register_LISTEN(self): - p = self.Poller() - channel = Mock() - channel.subclient.connection._sock = None - channel._in_listen = False - p._register = Mock() - - p._register_LISTEN(channel) - p._register.assert_called_with(channel, channel.subclient, 'LISTEN') - self.assertEqual(p._register.call_count, 1) - self.assertEqual(channel._subscribe.call_count, 1) - - channel._in_listen = True - channel.subclient.connection._sock = Mock() - p._register_LISTEN(channel) - self.assertEqual(p._register.call_count, 1) - self.assertEqual(channel._subscribe.call_count, 1) - - def create_get(self, events=None, queues=None, fanouts=None): - _pr = [] if events is None else events - _aq = [] if queues is None else queues - _af = [] if fanouts is None else fanouts - p = self.Poller() - p.poller = Mock() - p.poller.poll.return_value = _pr - - p._register_BRPOP = Mock() - p._register_LISTEN = Mock() - - channel = Mock() - p._channels = [channel] - channel.active_queues = _aq - channel.active_fanout_queues = _af - - return p, channel - - def test_get_no_actions(self): - p, channel = self.create_get() - - with self.assertRaises(redis.Empty): - p.get() - - def test_qos_reject(self): - p, channel = self.create_get() - qos = redis.QoS(channel) - qos.ack = Mock(name='Qos.ack') - qos.reject(1234) - qos.ack.assert_called_with(1234) - - def test_get_brpop_qos_allow(self): - p, channel = self.create_get(queues=['a_queue']) - channel.qos.can_consume.return_value = True - - with self.assertRaises(redis.Empty): - p.get() - - p._register_BRPOP.assert_called_with(channel) - - def test_get_brpop_qos_disallow(self): - p, channel = self.create_get(queues=['a_queue']) - channel.qos.can_consume.return_value = False - - with self.assertRaises(redis.Empty): - p.get() - - self.assertFalse(p._register_BRPOP.called) - - def test_get_listen(self): - p, channel = self.create_get(fanouts=['f_queue']) - - with self.assertRaises(redis.Empty): - p.get() - - p._register_LISTEN.assert_called_with(channel) - - def test_get_receives_ERR(self): - p, channel = self.create_get(events=[(1, eventio.ERR)]) - p._fd_to_chan[1] = (channel, 'BRPOP') - - with self.assertRaises(redis.Empty): - p.get() - - channel._poll_error.assert_called_with('BRPOP') - - def test_get_receives_multiple(self): - p, channel = self.create_get(events=[(1, eventio.ERR), - (1, eventio.ERR)]) - p._fd_to_chan[1] = (channel, 'BRPOP') - - with self.assertRaises(redis.Empty): - p.get() - - channel._poll_error.assert_called_with('BRPOP') - - -class test_Mutex(Case): - - @skip_if_not_module('redis') - def test_mutex(self, lock_id='xxx'): - client = Mock(name='client') - with patch('kombu.transport.redis.uuid') as uuid: - # Won - uuid.return_value = lock_id - client.setnx.return_value = True - pipe = client.pipeline.return_value = Mock(name='pipe') - pipe.get.return_value = lock_id - held = False - with redis.Mutex(client, 'foo1', 100): - held = True - self.assertTrue(held) - client.setnx.assert_called_with('foo1', lock_id) - pipe.get.return_value = 'yyy' - held = False - with redis.Mutex(client, 'foo1', 100): - held = True - self.assertTrue(held) - - # Did not win - client.expire.reset_mock() - pipe.get.return_value = lock_id - client.setnx.return_value = False - with self.assertRaises(redis.MutexHeld): - held = False - with redis.Mutex(client, 'foo1', '100'): - held = True - self.assertFalse(held) - client.ttl.return_value = 0 - with self.assertRaises(redis.MutexHeld): - held = False - with redis.Mutex(client, 'foo1', '100'): - held = True - self.assertFalse(held) - self.assertTrue(client.expire.called) - - # Wins but raises WatchError (and that is ignored) - client.setnx.return_value = True - pipe.watch.side_effect = redis.redis.WatchError() - held = False - with redis.Mutex(client, 'foo1', 100): - held = True - self.assertTrue(held) diff --git a/awx/lib/site-packages/kombu/tests/transport/test_sqlalchemy.py b/awx/lib/site-packages/kombu/tests/transport/test_sqlalchemy.py deleted file mode 100644 index 07055999e1..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_sqlalchemy.py +++ /dev/null @@ -1,69 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection -from kombu.tests.case import Case, SkipTest, patch - - -class test_sqlalchemy(Case): - - def setUp(self): - try: - import sqlalchemy # noqa - except ImportError: - raise SkipTest('sqlalchemy not installed') - - def test_url_parser(self): - with patch('kombu.transport.sqlalchemy.Channel._open'): - url = 'sqlalchemy+sqlite:///celerydb.sqlite' - Connection(url).connect() - - url = 'sqla+sqlite:///celerydb.sqlite' - Connection(url).connect() - - # Should prevent regression fixed by f187ccd - url = 'sqlb+sqlite:///celerydb.sqlite' - with self.assertRaises(KeyError): - Connection(url).connect() - - def test_simple_queueing(self): - conn = Connection('sqlalchemy+sqlite:///:memory:') - conn.connect() - channel = conn.channel() - self.assertEqual( - channel.queue_cls.__table__.name, - 'kombu_queue' - ) - self.assertEqual( - channel.message_cls.__table__.name, - 'kombu_message' - ) - channel._put('celery', 'DATA') - assert channel._get('celery') == 'DATA' - - def test_custom_table_names(self): - raise SkipTest('causes global side effect') - conn = Connection('sqlalchemy+sqlite:///:memory:', transport_options={ - 'queue_tablename': 'my_custom_queue', - 'message_tablename': 'my_custom_message' - }) - conn.connect() - channel = conn.channel() - self.assertEqual( - channel.queue_cls.__table__.name, - 'my_custom_queue' - ) - self.assertEqual( - channel.message_cls.__table__.name, - 'my_custom_message' - ) - channel._put('celery', 'DATA') - assert channel._get('celery') == 'DATA' - - def test_clone(self): - hostname = 'sqlite:///celerydb.sqlite' - x = Connection('+'.join(['sqla', hostname])) - self.assertEqual(x.uri_prefix, 'sqla') - self.assertEqual(x.hostname, hostname) - clone = x.clone() - self.assertEqual(clone.hostname, hostname) - self.assertEqual(clone.uri_prefix, 'sqla') diff --git a/awx/lib/site-packages/kombu/tests/transport/test_transport.py b/awx/lib/site-packages/kombu/tests/transport/test_transport.py deleted file mode 100644 index e10943ba31..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/test_transport.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import absolute_import - -from kombu import transport - -from kombu.tests.case import Case, Mock, patch - - -class test_supports_librabbitmq(Case): - - def test_eventlet(self): - with patch('kombu.transport._detect_environment') as de: - de.return_value = 'eventlet' - self.assertFalse(transport.supports_librabbitmq()) - - -class test_transport(Case): - - def test_resolve_transport(self): - from kombu.transport.memory import Transport - self.assertIs(transport.resolve_transport( - 'kombu.transport.memory:Transport'), - Transport) - self.assertIs(transport.resolve_transport(Transport), Transport) - - def test_resolve_transport_alias_callable(self): - m = transport.TRANSPORT_ALIASES['George'] = Mock(name='lazyalias') - try: - transport.resolve_transport('George') - m.assert_called_with() - finally: - transport.TRANSPORT_ALIASES.pop('George') - - def test_resolve_transport_alias(self): - self.assertTrue(transport.resolve_transport('pyamqp')) - - -class test_transport_ghettoq(Case): - - @patch('warnings.warn') - def test_compat(self, warn): - x = transport._ghettoq('Redis', 'redis', 'redis') - - self.assertEqual(x(), 'kombu.transport.redis.Transport') - self.assertTrue(warn.called) diff --git a/awx/lib/site-packages/kombu/tests/transport/virtual/__init__.py b/awx/lib/site-packages/kombu/tests/transport/virtual/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/kombu/tests/transport/virtual/test_base.py b/awx/lib/site-packages/kombu/tests/transport/virtual/test_base.py deleted file mode 100644 index f872356f46..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/virtual/test_base.py +++ /dev/null @@ -1,540 +0,0 @@ -from __future__ import absolute_import - -import warnings - -from kombu import Connection -from kombu.exceptions import ResourceError, ChannelError -from kombu.transport import virtual -from kombu.utils import uuid -from kombu.compression import compress - -from kombu.tests.case import Case, Mock, patch, redirect_stdouts - - -def client(**kwargs): - return Connection(transport='kombu.transport.virtual:Transport', **kwargs) - - -def memory_client(): - return Connection(transport='memory') - - -class test_BrokerState(Case): - - def test_constructor(self): - s = virtual.BrokerState() - self.assertTrue(hasattr(s, 'exchanges')) - self.assertTrue(hasattr(s, 'bindings')) - - t = virtual.BrokerState(exchanges=16, bindings=32) - self.assertEqual(t.exchanges, 16) - self.assertEqual(t.bindings, 32) - - -class test_QoS(Case): - - def setUp(self): - self.q = virtual.QoS(client().channel(), prefetch_count=10) - - def tearDown(self): - self.q._on_collect.cancel() - - def test_constructor(self): - self.assertTrue(self.q.channel) - self.assertTrue(self.q.prefetch_count) - self.assertFalse(self.q._delivered.restored) - self.assertTrue(self.q._on_collect) - - @redirect_stdouts - def test_can_consume(self, stdout, stderr): - _restored = [] - - class RestoreChannel(virtual.Channel): - do_restore = True - - def _restore(self, message): - _restored.append(message) - - self.assertTrue(self.q.can_consume()) - for i in range(self.q.prefetch_count - 1): - self.q.append(i, uuid()) - self.assertTrue(self.q.can_consume()) - self.q.append(i + 1, uuid()) - self.assertFalse(self.q.can_consume()) - - tag1 = next(iter(self.q._delivered)) - self.q.ack(tag1) - self.assertTrue(self.q.can_consume()) - - tag2 = uuid() - self.q.append(i + 2, tag2) - self.assertFalse(self.q.can_consume()) - self.q.reject(tag2) - self.assertTrue(self.q.can_consume()) - - self.q.channel = RestoreChannel(self.q.channel.connection) - tag3 = uuid() - self.q.append(i + 3, tag3) - self.q.reject(tag3, requeue=True) - self.q._flush() - self.q.restore_unacked_once() - self.assertListEqual(_restored, [11, 9, 8, 7, 6, 5, 4, 3, 2, 1]) - self.assertTrue(self.q._delivered.restored) - self.assertFalse(self.q._delivered) - - self.q.restore_unacked_once() - self.q._delivered.restored = False - self.q.restore_unacked_once() - - self.assertTrue(stderr.getvalue()) - self.assertFalse(stdout.getvalue()) - - self.q.restore_at_shutdown = False - self.q.restore_unacked_once() - - def test_get(self): - self.q._delivered['foo'] = 1 - self.assertEqual(self.q.get('foo'), 1) - - -class test_Message(Case): - - def test_create(self): - c = client().channel() - data = c.prepare_message('the quick brown fox...') - tag = data['properties']['delivery_tag'] = uuid() - message = c.message_to_python(data) - self.assertIsInstance(message, virtual.Message) - self.assertIs(message, c.message_to_python(message)) - if message.errors: - message._reraise_error() - - self.assertEqual(message.body, - 'the quick brown fox...'.encode('utf-8')) - self.assertTrue(message.delivery_tag, tag) - - def test_create_no_body(self): - virtual.Message(Mock(), { - 'body': None, - 'properties': {'delivery_tag': 1}}) - - def test_serializable(self): - c = client().channel() - body, content_type = compress('the quick brown fox...', 'gzip') - data = c.prepare_message(body, headers={'compression': content_type}) - tag = data['properties']['delivery_tag'] = uuid() - message = c.message_to_python(data) - dict_ = message.serializable() - self.assertEqual(dict_['body'], - 'the quick brown fox...'.encode('utf-8')) - self.assertEqual(dict_['properties']['delivery_tag'], tag) - self.assertFalse('compression' in dict_['headers']) - - -class test_AbstractChannel(Case): - - def test_get(self): - with self.assertRaises(NotImplementedError): - virtual.AbstractChannel()._get('queue') - - def test_put(self): - with self.assertRaises(NotImplementedError): - virtual.AbstractChannel()._put('queue', 'm') - - def test_size(self): - self.assertEqual(virtual.AbstractChannel()._size('queue'), 0) - - def test_purge(self): - with self.assertRaises(NotImplementedError): - virtual.AbstractChannel()._purge('queue') - - def test_delete(self): - with self.assertRaises(NotImplementedError): - virtual.AbstractChannel()._delete('queue') - - def test_new_queue(self): - self.assertIsNone(virtual.AbstractChannel()._new_queue('queue')) - - def test_has_queue(self): - self.assertTrue(virtual.AbstractChannel()._has_queue('queue')) - - def test_poll(self): - - class Cycle(object): - called = False - - def get(self): - self.called = True - return True - - cycle = Cycle() - self.assertTrue(virtual.AbstractChannel()._poll(cycle)) - self.assertTrue(cycle.called) - - -class test_Channel(Case): - - def setUp(self): - self.channel = client().channel() - - def tearDown(self): - if self.channel._qos is not None: - self.channel._qos._on_collect.cancel() - - def test_exceeds_channel_max(self): - c = client() - t = c.transport - avail = t._avail_channel_ids = Mock(name='_avail_channel_ids') - avail.pop.side_effect = IndexError() - with self.assertRaises(ResourceError): - virtual.Channel(t) - - def test_exchange_bind_interface(self): - with self.assertRaises(NotImplementedError): - self.channel.exchange_bind('dest', 'src', 'key') - - def test_exchange_unbind_interface(self): - with self.assertRaises(NotImplementedError): - self.channel.exchange_unbind('dest', 'src', 'key') - - def test_queue_unbind_interface(self): - with self.assertRaises(NotImplementedError): - self.channel.queue_unbind('dest', 'ex', 'key') - - def test_management(self): - m = self.channel.connection.client.get_manager() - self.assertTrue(m) - m.get_bindings() - m.close() - - def test_exchange_declare(self): - c = self.channel - - with self.assertRaises(ChannelError): - c.exchange_declare('test_exchange_declare', 'direct', - durable=True, auto_delete=True, passive=True) - c.exchange_declare('test_exchange_declare', 'direct', - durable=True, auto_delete=True) - c.exchange_declare('test_exchange_declare', 'direct', - durable=True, auto_delete=True, passive=True) - self.assertIn('test_exchange_declare', c.state.exchanges) - # can declare again with same values - c.exchange_declare('test_exchange_declare', 'direct', - durable=True, auto_delete=True) - self.assertIn('test_exchange_declare', c.state.exchanges) - - # using different values raises NotEquivalentError - with self.assertRaises(virtual.NotEquivalentError): - c.exchange_declare('test_exchange_declare', 'direct', - durable=False, auto_delete=True) - - def test_exchange_delete(self, ex='test_exchange_delete'): - - class PurgeChannel(virtual.Channel): - purged = [] - - def _purge(self, queue): - self.purged.append(queue) - - c = PurgeChannel(self.channel.connection) - - c.exchange_declare(ex, 'direct', durable=True, auto_delete=True) - self.assertIn(ex, c.state.exchanges) - self.assertNotIn(ex, c.state.bindings) # no bindings yet - c.exchange_delete(ex) - self.assertNotIn(ex, c.state.exchanges) - - c.exchange_declare(ex, 'direct', durable=True, auto_delete=True) - c.queue_declare(ex) - c.queue_bind(ex, ex, ex) - self.assertTrue(c.state.bindings[ex]) - c.exchange_delete(ex) - self.assertNotIn(ex, c.state.bindings) - self.assertIn(ex, c.purged) - - def test_queue_delete__if_empty(self, n='test_queue_delete__if_empty'): - class PurgeChannel(virtual.Channel): - purged = [] - size = 30 - - def _purge(self, queue): - self.purged.append(queue) - - def _size(self, queue): - return self.size - - c = PurgeChannel(self.channel.connection) - c.exchange_declare(n) - c.queue_declare(n) - c.queue_bind(n, n, n) - # tests code path that returns if queue already bound. - c.queue_bind(n, n, n) - - c.queue_delete(n, if_empty=True) - self.assertIn(n, c.state.bindings) - - c.size = 0 - c.queue_delete(n, if_empty=True) - self.assertNotIn(n, c.state.bindings) - self.assertIn(n, c.purged) - - def test_queue_purge(self, n='test_queue_purge'): - - class PurgeChannel(virtual.Channel): - purged = [] - - def _purge(self, queue): - self.purged.append(queue) - - c = PurgeChannel(self.channel.connection) - c.exchange_declare(n) - c.queue_declare(n) - c.queue_bind(n, n, n) - c.queue_purge(n) - self.assertIn(n, c.purged) - - def test_basic_publish_unique_delivery_tags(self, n='test_uniq_tag'): - c1 = memory_client().channel() - c2 = memory_client().channel() - - for c in (c1, c2): - c.exchange_declare(n) - c.queue_declare(n) - c.queue_bind(n, n, n) - m1 = c1.prepare_message('George Costanza') - m2 = c2.prepare_message('Elaine Marie Benes') - c1.basic_publish(m1, n, n) - c2.basic_publish(m2, n, n) - - r1 = c1.message_to_python(c1.basic_get(n)) - r2 = c2.message_to_python(c2.basic_get(n)) - - self.assertNotEqual(r1.delivery_tag, r2.delivery_tag) - with self.assertRaises(ValueError): - int(r1.delivery_tag) - with self.assertRaises(ValueError): - int(r2.delivery_tag) - - def test_basic_publish__get__consume__restore(self, - n='test_basic_publish'): - c = memory_client().channel() - - c.exchange_declare(n) - c.queue_declare(n) - c.queue_bind(n, n, n) - c.queue_declare(n + '2') - c.queue_bind(n + '2', n, n) - - m = c.prepare_message('nthex quick brown fox...') - c.basic_publish(m, n, n) - - r1 = c.message_to_python(c.basic_get(n)) - self.assertTrue(r1) - self.assertEqual(r1.body, - 'nthex quick brown fox...'.encode('utf-8')) - self.assertIsNone(c.basic_get(n)) - - consumer_tag = uuid() - - c.basic_consume(n + '2', False, - consumer_tag=consumer_tag, callback=lambda *a: None) - self.assertIn(n + '2', c._active_queues) - r2, _ = c.drain_events() - r2 = c.message_to_python(r2) - self.assertEqual(r2.body, - 'nthex quick brown fox...'.encode('utf-8')) - self.assertEqual(r2.delivery_info['exchange'], n) - self.assertEqual(r2.delivery_info['routing_key'], n) - with self.assertRaises(virtual.Empty): - c.drain_events() - c.basic_cancel(consumer_tag) - - c._restore(r2) - r3 = c.message_to_python(c.basic_get(n)) - self.assertTrue(r3) - self.assertEqual(r3.body, 'nthex quick brown fox...'.encode('utf-8')) - self.assertIsNone(c.basic_get(n)) - - def test_basic_ack(self): - - class MockQoS(virtual.QoS): - was_acked = False - - def ack(self, delivery_tag): - self.was_acked = True - - self.channel._qos = MockQoS(self.channel) - self.channel.basic_ack('foo') - self.assertTrue(self.channel._qos.was_acked) - - def test_basic_recover__requeue(self): - - class MockQoS(virtual.QoS): - was_restored = False - - def restore_unacked(self): - self.was_restored = True - - self.channel._qos = MockQoS(self.channel) - self.channel.basic_recover(requeue=True) - self.assertTrue(self.channel._qos.was_restored) - - def test_restore_unacked_raises_BaseException(self): - q = self.channel.qos - q._flush = Mock() - q._delivered = {1: 1} - - q.channel._restore = Mock() - q.channel._restore.side_effect = SystemExit - - errors = q.restore_unacked() - self.assertIsInstance(errors[0][0], SystemExit) - self.assertEqual(errors[0][1], 1) - self.assertFalse(q._delivered) - - @patch('kombu.transport.virtual.emergency_dump_state') - @patch('kombu.transport.virtual.say') - def test_restore_unacked_once_when_unrestored(self, say, - emergency_dump_state): - q = self.channel.qos - q._flush = Mock() - - class State(dict): - restored = False - - q._delivered = State({1: 1}) - ru = q.restore_unacked = Mock() - exc = None - try: - raise KeyError() - except KeyError as exc_: - exc = exc_ - ru.return_value = [(exc, 1)] - - self.channel.do_restore = True - q.restore_unacked_once() - self.assertTrue(say.called) - self.assertTrue(emergency_dump_state.called) - - def test_basic_recover(self): - with self.assertRaises(NotImplementedError): - self.channel.basic_recover(requeue=False) - - def test_basic_reject(self): - - class MockQoS(virtual.QoS): - was_rejected = False - - def reject(self, delivery_tag, requeue=False): - self.was_rejected = True - - self.channel._qos = MockQoS(self.channel) - self.channel.basic_reject('foo') - self.assertTrue(self.channel._qos.was_rejected) - - def test_basic_qos(self): - self.channel.basic_qos(prefetch_count=128) - self.assertEqual(self.channel._qos.prefetch_count, 128) - - def test_lookup__undeliverable(self, n='test_lookup__undeliverable'): - warnings.resetwarnings() - with warnings.catch_warnings(record=True) as log: - self.assertListEqual( - self.channel._lookup(n, n, 'ae.undeliver'), - ['ae.undeliver'], - ) - self.assertTrue(log) - self.assertIn('could not be delivered', log[0].message.args[0]) - - def test_context(self): - x = self.channel.__enter__() - self.assertIs(x, self.channel) - x.__exit__() - self.assertTrue(x.closed) - - def test_cycle_property(self): - self.assertTrue(self.channel.cycle) - - def test_flow(self): - with self.assertRaises(NotImplementedError): - self.channel.flow(False) - - def test_close_when_no_connection(self): - self.channel.connection = None - self.channel.close() - self.assertTrue(self.channel.closed) - - def test_drain_events_has_get_many(self): - c = self.channel - c._get_many = Mock() - c._poll = Mock() - c._consumers = [1] - c._qos = Mock() - c._qos.can_consume.return_value = True - - c.drain_events(timeout=10.0) - c._get_many.assert_called_with(c._active_queues, timeout=10.0) - - def test_get_exchanges(self): - self.channel.exchange_declare(exchange='foo') - self.assertTrue(self.channel.get_exchanges()) - - def test_basic_cancel_not_in_active_queues(self): - c = self.channel - c._consumers.add('x') - c._tag_to_queue['x'] = 'foo' - c._active_queues = Mock() - c._active_queues.remove.side_effect = ValueError() - - c.basic_cancel('x') - c._active_queues.remove.assert_called_with('foo') - - def test_basic_cancel_unknown_ctag(self): - self.assertIsNone(self.channel.basic_cancel('unknown-tag')) - - def test_list_bindings(self): - c = self.channel - c.exchange_declare(exchange='foo') - c.queue_declare(queue='q') - c.queue_bind(queue='q', exchange='foo', routing_key='rk') - - self.assertIn(('q', 'foo', 'rk'), list(c.list_bindings())) - - def test_after_reply_message_received(self): - c = self.channel - c.queue_delete = Mock() - c.after_reply_message_received('foo') - c.queue_delete.assert_called_with('foo') - - def test_queue_delete_unknown_queue(self): - self.assertIsNone(self.channel.queue_delete('xiwjqjwel')) - - def test_queue_declare_passive(self): - has_queue = self.channel._has_queue = Mock() - has_queue.return_value = False - with self.assertRaises(ChannelError): - self.channel.queue_declare(queue='21wisdjwqe', passive=True) - - -class test_Transport(Case): - - def setUp(self): - self.transport = client().transport - - def test_custom_polling_interval(self): - x = client(transport_options=dict(polling_interval=32.3)) - self.assertEqual(x.transport.polling_interval, 32.3) - - def test_close_connection(self): - c1 = self.transport.create_channel(self.transport) - c2 = self.transport.create_channel(self.transport) - self.assertEqual(len(self.transport.channels), 2) - self.transport.close_connection(self.transport) - self.assertFalse(self.transport.channels) - del(c1) # so pyflakes doesn't complain - del(c2) - - def test_drain_channel(self): - channel = self.transport.create_channel(self.transport) - with self.assertRaises(virtual.Empty): - self.transport._drain_channel(channel) diff --git a/awx/lib/site-packages/kombu/tests/transport/virtual/test_exchange.py b/awx/lib/site-packages/kombu/tests/transport/virtual/test_exchange.py deleted file mode 100644 index ad590afc0a..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/virtual/test_exchange.py +++ /dev/null @@ -1,161 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection -from kombu.transport.virtual import exchange - -from kombu.tests.case import Case, Mock -from kombu.tests.mocks import Transport - - -class ExchangeCase(Case): - type = None - - def setUp(self): - if self.type: - self.e = self.type(Connection(transport=Transport).channel()) - - -class test_Direct(ExchangeCase): - type = exchange.DirectExchange - table = [('rFoo', None, 'qFoo'), - ('rFoo', None, 'qFox'), - ('rBar', None, 'qBar'), - ('rBaz', None, 'qBaz')] - - def test_lookup(self): - self.assertListEqual( - self.e.lookup(self.table, 'eFoo', 'rFoo', None), - ['qFoo', 'qFox'], - ) - self.assertListEqual( - self.e.lookup(self.table, 'eMoz', 'rMoz', 'DEFAULT'), - [], - ) - self.assertListEqual( - self.e.lookup(self.table, 'eBar', 'rBar', None), - ['qBar'], - ) - - -class test_Fanout(ExchangeCase): - type = exchange.FanoutExchange - table = [(None, None, 'qFoo'), - (None, None, 'qFox'), - (None, None, 'qBar')] - - def test_lookup(self): - self.assertListEqual( - self.e.lookup(self.table, 'eFoo', 'rFoo', None), - ['qFoo', 'qFox', 'qBar'], - ) - - def test_deliver_when_fanout_supported(self): - self.e.channel = Mock() - self.e.channel.supports_fanout = True - message = Mock() - - self.e.deliver(message, 'exchange', 'rkey') - self.e.channel._put_fanout.assert_called_with( - 'exchange', message, 'rkey', - ) - - def test_deliver_when_fanout_unsupported(self): - self.e.channel = Mock() - self.e.channel.supports_fanout = False - - self.e.deliver(Mock(), 'exchange', None) - self.assertFalse(self.e.channel._put_fanout.called) - - -class test_Topic(ExchangeCase): - type = exchange.TopicExchange - table = [ - ('stock.#', None, 'rFoo'), - ('stock.us.*', None, 'rBar'), - ] - - def setUp(self): - super(test_Topic, self).setUp() - self.table = [(rkey, self.e.key_to_pattern(rkey), queue) - for rkey, _, queue in self.table] - - def test_prepare_bind(self): - x = self.e.prepare_bind('qFoo', 'eFoo', 'stock.#', {}) - self.assertTupleEqual(x, ('stock.#', r'^stock\..*?$', 'qFoo')) - - def test_lookup(self): - self.assertListEqual( - self.e.lookup(self.table, 'eFoo', 'stock.us.nasdaq', None), - ['rFoo', 'rBar'], - ) - self.assertTrue(self.e._compiled) - self.assertListEqual( - self.e.lookup(self.table, 'eFoo', 'stock.europe.OSE', None), - ['rFoo'], - ) - self.assertListEqual( - self.e.lookup(self.table, 'eFoo', 'stockxeuropexOSE', None), - [], - ) - self.assertListEqual( - self.e.lookup(self.table, 'eFoo', - 'candy.schleckpulver.snap_crackle', None), - [], - ) - - def test_deliver(self): - self.e.channel = Mock() - self.e.channel._lookup.return_value = ('a', 'b') - message = Mock() - self.e.deliver(message, 'exchange', 'rkey') - - expected = [(('a', message), {}), - (('b', message), {})] - self.assertListEqual(self.e.channel._put.call_args_list, expected) - - -class test_ExchangeType(ExchangeCase): - type = exchange.ExchangeType - - def test_lookup(self): - with self.assertRaises(NotImplementedError): - self.e.lookup([], 'eFoo', 'rFoo', None) - - def test_prepare_bind(self): - self.assertTupleEqual( - self.e.prepare_bind('qFoo', 'eFoo', 'rFoo', {}), - ('rFoo', None, 'qFoo'), - ) - - def test_equivalent(self): - e1 = dict( - type='direct', - durable=True, - auto_delete=True, - arguments={}, - ) - self.assertTrue( - self.e.equivalent(e1, 'eFoo', 'direct', True, True, {}), - ) - self.assertFalse( - self.e.equivalent(e1, 'eFoo', 'topic', True, True, {}), - ) - self.assertFalse( - self.e.equivalent(e1, 'eFoo', 'direct', False, True, {}), - ) - self.assertFalse( - self.e.equivalent(e1, 'eFoo', 'direct', True, False, {}), - ) - self.assertFalse( - self.e.equivalent(e1, 'eFoo', 'direct', True, True, - {'expires': 3000}), - ) - e2 = dict(e1, arguments={'expires': 3000}) - self.assertTrue( - self.e.equivalent(e2, 'eFoo', 'direct', True, True, - {'expires': 3000}), - ) - self.assertFalse( - self.e.equivalent(e2, 'eFoo', 'direct', True, True, - {'expires': 6000}), - ) diff --git a/awx/lib/site-packages/kombu/tests/transport/virtual/test_scheduling.py b/awx/lib/site-packages/kombu/tests/transport/virtual/test_scheduling.py deleted file mode 100644 index ccd7d4eeaa..0000000000 --- a/awx/lib/site-packages/kombu/tests/transport/virtual/test_scheduling.py +++ /dev/null @@ -1,67 +0,0 @@ -from __future__ import absolute_import - -from kombu.transport.virtual.scheduling import FairCycle - -from kombu.tests.case import Case - - -class MyEmpty(Exception): - pass - - -def consume(fun, n): - r = [] - for i in range(n): - r.append(fun()) - return r - - -class test_FairCycle(Case): - - def test_cycle(self): - resources = ['a', 'b', 'c', 'd', 'e'] - - def echo(r, timeout=None): - return r - - # cycle should be ['a', 'b', 'c', 'd', 'e', ... repeat] - cycle = FairCycle(echo, resources, MyEmpty) - for i in range(len(resources)): - self.assertEqual(cycle.get(), (resources[i], - resources[i])) - for i in range(len(resources)): - self.assertEqual(cycle.get(), (resources[i], - resources[i])) - - def test_cycle_breaks(self): - resources = ['a', 'b', 'c', 'd', 'e'] - - def echo(r): - if r == 'c': - raise MyEmpty(r) - return r - - cycle = FairCycle(echo, resources, MyEmpty) - self.assertEqual( - consume(cycle.get, len(resources)), - [('a', 'a'), ('b', 'b'), ('d', 'd'), - ('e', 'e'), ('a', 'a')], - ) - self.assertEqual( - consume(cycle.get, len(resources)), - [('b', 'b'), ('d', 'd'), ('e', 'e'), - ('a', 'a'), ('b', 'b')], - ) - cycle2 = FairCycle(echo, ['c', 'c'], MyEmpty) - with self.assertRaises(MyEmpty): - consume(cycle2.get, 3) - - def test_cycle_no_resources(self): - cycle = FairCycle(None, [], MyEmpty) - cycle.pos = 10 - - with self.assertRaises(MyEmpty): - cycle._next() - - def test__repr__(self): - self.assertTrue(repr(FairCycle(lambda x: x, [1, 2, 3], MyEmpty))) diff --git a/awx/lib/site-packages/kombu/tests/utils/__init__.py b/awx/lib/site-packages/kombu/tests/utils/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/kombu/tests/utils/test_amq_manager.py b/awx/lib/site-packages/kombu/tests/utils/test_amq_manager.py deleted file mode 100644 index b34b52e8ad..0000000000 --- a/awx/lib/site-packages/kombu/tests/utils/test_amq_manager.py +++ /dev/null @@ -1,36 +0,0 @@ -from __future__ import absolute_import - -from kombu import Connection - -from kombu.tests.case import Case, mask_modules, module_exists, patch - - -class test_get_manager(Case): - - @mask_modules('pyrabbit') - def test_without_pyrabbit(self): - with self.assertRaises(ImportError): - Connection('amqp://').get_manager() - - @module_exists('pyrabbit') - def test_with_pyrabbit(self): - with patch('pyrabbit.Client', create=True) as Client: - manager = Connection('amqp://').get_manager() - self.assertIsNotNone(manager) - Client.assert_called_with( - 'localhost:15672', 'guest', 'guest', - ) - - @module_exists('pyrabbit') - def test_transport_options(self): - with patch('pyrabbit.Client', create=True) as Client: - manager = Connection('amqp://', transport_options={ - 'manager_hostname': 'admin.mq.vandelay.com', - 'manager_port': 808, - 'manager_userid': 'george', - 'manager_password': 'bosco', - }).get_manager() - self.assertIsNotNone(manager) - Client.assert_called_with( - 'admin.mq.vandelay.com:808', 'george', 'bosco', - ) diff --git a/awx/lib/site-packages/kombu/tests/utils/test_debug.py b/awx/lib/site-packages/kombu/tests/utils/test_debug.py deleted file mode 100644 index ea25cb77f3..0000000000 --- a/awx/lib/site-packages/kombu/tests/utils/test_debug.py +++ /dev/null @@ -1,56 +0,0 @@ -from __future__ import absolute_import - -import logging - -from kombu.utils.debug import ( - setup_logging, - Logwrapped, -) -from kombu.tests.case import Case, Mock, patch - - -class test_setup_logging(Case): - - def test_adds_handlers_sets_level(self): - with patch('kombu.utils.debug.get_logger') as get_logger: - logger = get_logger.return_value = Mock() - setup_logging(loggers=['kombu.test']) - - get_logger.assert_called_with('kombu.test') - - self.assertTrue(logger.addHandler.called) - logger.setLevel.assert_called_with(logging.DEBUG) - - -class test_Logwrapped(Case): - - def test_wraps(self): - with patch('kombu.utils.debug.get_logger') as get_logger: - logger = get_logger.return_value = Mock() - - W = Logwrapped(Mock(), 'kombu.test') - get_logger.assert_called_with('kombu.test') - self.assertIsNotNone(W.instance) - self.assertIs(W.logger, logger) - - W.instance.__repr__ = lambda s: 'foo' - self.assertEqual(repr(W), 'foo') - W.instance.some_attr = 303 - self.assertEqual(W.some_attr, 303) - - W.instance.some_method.__name__ = 'some_method' - W.some_method(1, 2, kw=1) - W.instance.some_method.assert_called_with(1, 2, kw=1) - - W.some_method() - W.instance.some_method.assert_called_with() - - W.some_method(kw=1) - W.instance.some_method.assert_called_with(kw=1) - - W.ident = 'ident' - W.some_method(kw=1) - self.assertTrue(logger.debug.called) - self.assertIn('ident', logger.debug.call_args[0][0]) - - self.assertEqual(dir(W), dir(W.instance)) diff --git a/awx/lib/site-packages/kombu/tests/utils/test_encoding.py b/awx/lib/site-packages/kombu/tests/utils/test_encoding.py deleted file mode 100644 index fd710c30f8..0000000000 --- a/awx/lib/site-packages/kombu/tests/utils/test_encoding.py +++ /dev/null @@ -1,102 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import unicode_literals - -import sys - -from contextlib import contextmanager - -from kombu.five import bytes_t, string_t -from kombu.utils.encoding import safe_str, default_encoding - -from kombu.tests.case import Case, SkipTest, patch - - -@contextmanager -def clean_encoding(): - old_encoding = sys.modules.pop('kombu.utils.encoding', None) - import kombu.utils.encoding - try: - yield kombu.utils.encoding - finally: - if old_encoding: - sys.modules['kombu.utils.encoding'] = old_encoding - - -class test_default_encoding(Case): - - @patch('sys.getfilesystemencoding') - def test_default(self, getdefaultencoding): - getdefaultencoding.return_value = 'ascii' - with clean_encoding() as encoding: - enc = encoding.default_encoding() - if sys.platform.startswith('java'): - self.assertEqual(enc, 'utf-8') - else: - self.assertEqual(enc, 'ascii') - getdefaultencoding.assert_called_with() - - -class test_encoding_utils(Case): - - def setUp(self): - if sys.version_info >= (3, 0): - raise SkipTest('not relevant on py3k') - - def test_str_to_bytes(self): - with clean_encoding() as e: - self.assertIsInstance(e.str_to_bytes('foobar'), bytes_t) - - def test_from_utf8(self): - with clean_encoding() as e: - self.assertIsInstance(e.from_utf8('foobar'), bytes_t) - - def test_default_encode(self): - with clean_encoding() as e: - self.assertTrue(e.default_encode(b'foo')) - - -class test_safe_str(Case): - - def setUp(self): - self._cencoding = patch('sys.getfilesystemencoding') - self._encoding = self._cencoding.__enter__() - self._encoding.return_value = 'ascii' - - def tearDown(self): - self._cencoding.__exit__() - - def test_when_bytes(self): - self.assertEqual(safe_str('foo'), 'foo') - - def test_when_unicode(self): - self.assertIsInstance(safe_str('foo'), string_t) - - def test_when_encoding_utf8(self): - with patch('sys.getfilesystemencoding') as encoding: - encoding.return_value = 'utf-8' - self.assertEqual(default_encoding(), 'utf-8') - s = 'The quiæk fåx jømps øver the lazy dåg' - res = safe_str(s) - self.assertIsInstance(res, str) - - def test_when_containing_high_chars(self): - with patch('sys.getfilesystemencoding') as encoding: - encoding.return_value = 'ascii' - s = 'The quiæk fåx jømps øver the lazy dåg' - res = safe_str(s) - self.assertIsInstance(res, str) - self.assertEqual(len(s), len(res)) - - def test_when_not_string(self): - o = object() - self.assertEqual(safe_str(o), repr(o)) - - def test_when_unrepresentable(self): - - class O(object): - - def __repr__(self): - raise KeyError('foo') - - self.assertIn('<Unrepresentable', safe_str(O())) diff --git a/awx/lib/site-packages/kombu/tests/utils/test_functional.py b/awx/lib/site-packages/kombu/tests/utils/test_functional.py deleted file mode 100644 index f215dea5ed..0000000000 --- a/awx/lib/site-packages/kombu/tests/utils/test_functional.py +++ /dev/null @@ -1,63 +0,0 @@ -from __future__ import absolute_import - -import pickle -import sys - -from kombu.utils.functional import lazy, maybe_evaluate - -from kombu.tests.case import Case, SkipTest - - -def double(x): - return x * 2 - - -class test_lazy(Case): - - def test__str__(self): - self.assertEqual( - str(lazy(lambda: 'the quick brown fox')), - 'the quick brown fox', - ) - - def test__repr__(self): - self.assertEqual( - repr(lazy(lambda: 'fi fa fo')), - "'fi fa fo'", - ) - - def test__cmp__(self): - if sys.version_info[0] == 3: - raise SkipTest('irrelevant on py3') - - self.assertEqual(lazy(lambda: 10).__cmp__(lazy(lambda: 20)), -1) - self.assertEqual(lazy(lambda: 10).__cmp__(5), 1) - - def test_evaluate(self): - self.assertEqual(lazy(lambda: 2 + 2)(), 4) - self.assertEqual(lazy(lambda x: x * 4, 2), 8) - self.assertEqual(lazy(lambda x: x * 8, 2)(), 16) - - def test_cmp(self): - self.assertEqual(lazy(lambda: 10), lazy(lambda: 10)) - self.assertNotEqual(lazy(lambda: 10), lazy(lambda: 20)) - - def test__reduce__(self): - x = lazy(double, 4) - y = pickle.loads(pickle.dumps(x)) - self.assertEqual(x(), y()) - - def test__deepcopy__(self): - from copy import deepcopy - x = lazy(double, 4) - y = deepcopy(x) - self.assertEqual(x._fun, y._fun) - self.assertEqual(x._args, y._args) - self.assertEqual(x(), y()) - - -class test_maybe_evaluate(Case): - - def test_evaluates(self): - self.assertEqual(maybe_evaluate(lazy(lambda: 10)), 10) - self.assertEqual(maybe_evaluate(20), 20) diff --git a/awx/lib/site-packages/kombu/tests/utils/test_utils.py b/awx/lib/site-packages/kombu/tests/utils/test_utils.py deleted file mode 100644 index 0248a3039d..0000000000 --- a/awx/lib/site-packages/kombu/tests/utils/test_utils.py +++ /dev/null @@ -1,412 +0,0 @@ -from __future__ import absolute_import -from __future__ import unicode_literals - -import pickle -import sys - -from functools import wraps - -if sys.version_info >= (3, 0): - from io import StringIO, BytesIO -else: - from StringIO import StringIO, StringIO as BytesIO # noqa - -from kombu import version_info_t -from kombu import utils -from kombu.utils.text import version_string_as_tuple -from kombu.five import string_t - -from kombu.tests.case import ( - Case, Mock, patch, - redirect_stdouts, mask_modules, module_exists, skip_if_module, -) - - -class OldString(object): - - def __init__(self, value): - self.value = value - - def __str__(self): - return self.value - - def split(self, *args, **kwargs): - return self.value.split(*args, **kwargs) - - def rsplit(self, *args, **kwargs): - return self.value.rsplit(*args, **kwargs) - - -class test_kombu_module(Case): - - def test_dir(self): - import kombu - self.assertTrue(dir(kombu)) - - -class test_utils(Case): - - def test_maybe_list(self): - self.assertEqual(utils.maybe_list(None), []) - self.assertEqual(utils.maybe_list(1), [1]) - self.assertEqual(utils.maybe_list([1, 2, 3]), [1, 2, 3]) - - def test_fxrange_no_repeatlast(self): - self.assertEqual(list(utils.fxrange(1.0, 3.0, 1.0)), - [1.0, 2.0, 3.0]) - - def test_fxrangemax(self): - self.assertEqual(list(utils.fxrangemax(1.0, 3.0, 1.0, 30.0)), - [1.0, 2.0, 3.0, 3.0, 3.0, 3.0, - 3.0, 3.0, 3.0, 3.0, 3.0]) - self.assertEqual(list(utils.fxrangemax(1.0, None, 1.0, 30.0)), - [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]) - - def test_reprkwargs(self): - self.assertTrue(utils.reprkwargs({'foo': 'bar', 1: 2, 'k': 'v'})) - - def test_reprcall(self): - self.assertTrue( - utils.reprcall('add', (2, 2), {'copy': True}), - ) - - -class test_UUID(Case): - - def test_uuid4(self): - self.assertNotEqual(utils.uuid4(), - utils.uuid4()) - - def test_uuid(self): - i1 = utils.uuid() - i2 = utils.uuid() - self.assertIsInstance(i1, str) - self.assertNotEqual(i1, i2) - - @skip_if_module('__pypy__') - def test_uuid_without_ctypes(self): - old_utils = sys.modules.pop('kombu.utils') - - @mask_modules('ctypes') - def with_ctypes_masked(): - from kombu.utils import ctypes, uuid - - self.assertIsNone(ctypes) - tid = uuid() - self.assertTrue(tid) - self.assertIsInstance(tid, string_t) - - try: - with_ctypes_masked() - finally: - sys.modules['celery.utils'] = old_utils - - -class test_Misc(Case): - - def test_kwdict(self): - - def f(**kwargs): - return kwargs - - kw = {'foo': 'foo', - 'bar': 'bar'} - self.assertTrue(f(**utils.kwdict(kw))) - - -class MyStringIO(StringIO): - - def close(self): - pass - - -class MyBytesIO(BytesIO): - - def close(self): - pass - - -class test_emergency_dump_state(Case): - - @redirect_stdouts - def test_dump(self, stdout, stderr): - fh = MyBytesIO() - - utils.emergency_dump_state({'foo': 'bar'}, open_file=lambda n, m: fh) - self.assertDictEqual(pickle.loads(fh.getvalue()), {'foo': 'bar'}) - self.assertTrue(stderr.getvalue()) - self.assertFalse(stdout.getvalue()) - - @redirect_stdouts - def test_dump_second_strategy(self, stdout, stderr): - fh = MyStringIO() - - def raise_something(*args, **kwargs): - raise KeyError('foo') - - utils.emergency_dump_state( - {'foo': 'bar'}, - open_file=lambda n, m: fh, dump=raise_something - ) - self.assertIn('foo', fh.getvalue()) - self.assertIn('bar', fh.getvalue()) - self.assertTrue(stderr.getvalue()) - self.assertFalse(stdout.getvalue()) - - -def insomnia(fun): - - @wraps(fun) - def _inner(*args, **kwargs): - def mysleep(i): - pass - - prev_sleep = utils.sleep - utils.sleep = mysleep - try: - return fun(*args, **kwargs) - finally: - utils.sleep = prev_sleep - - return _inner - - -class test_retry_over_time(Case): - - def setUp(self): - self.index = 0 - - class Predicate(Exception): - pass - - def myfun(self): - if self.index < 9: - raise self.Predicate() - return 42 - - def errback(self, exc, intervals, retries): - interval = next(intervals) - sleepvals = (None, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 16.0) - self.index += 1 - self.assertEqual(interval, sleepvals[self.index]) - return interval - - @insomnia - def test_simple(self): - prev_count, utils.count = utils.count, Mock() - try: - utils.count.return_value = list(range(1)) - x = utils.retry_over_time(self.myfun, self.Predicate, - errback=None, interval_max=14) - self.assertIsNone(x) - utils.count.return_value = list(range(10)) - cb = Mock() - x = utils.retry_over_time(self.myfun, self.Predicate, - errback=self.errback, callback=cb, - interval_max=14) - self.assertEqual(x, 42) - self.assertEqual(self.index, 9) - cb.assert_called_with() - finally: - utils.count = prev_count - - @insomnia - def test_retry_once(self): - with self.assertRaises(self.Predicate): - utils.retry_over_time( - self.myfun, self.Predicate, - max_retries=1, errback=self.errback, interval_max=14, - ) - self.assertEqual(self.index, 1) - # no errback - with self.assertRaises(self.Predicate): - utils.retry_over_time( - self.myfun, self.Predicate, - max_retries=1, errback=None, interval_max=14, - ) - - @insomnia - def test_retry_always(self): - Predicate = self.Predicate - - class Fun(object): - - def __init__(self): - self.calls = 0 - - def __call__(self, *args, **kwargs): - try: - if self.calls >= 10: - return 42 - raise Predicate() - finally: - self.calls += 1 - fun = Fun() - - self.assertEqual( - utils.retry_over_time( - fun, self.Predicate, - max_retries=0, errback=None, interval_max=14, - ), - 42, - ) - self.assertEqual(fun.calls, 11) - - -class test_cached_property(Case): - - def test_deleting(self): - - class X(object): - xx = False - - @utils.cached_property - def foo(self): - return 42 - - @foo.deleter # noqa - def foo(self, value): - self.xx = value - - x = X() - del(x.foo) - self.assertFalse(x.xx) - x.__dict__['foo'] = 'here' - del(x.foo) - self.assertEqual(x.xx, 'here') - - def test_when_access_from_class(self): - - class X(object): - xx = None - - @utils.cached_property - def foo(self): - return 42 - - @foo.setter # noqa - def foo(self, value): - self.xx = 10 - - desc = X.__dict__['foo'] - self.assertIs(X.foo, desc) - - self.assertIs(desc.__get__(None), desc) - self.assertIs(desc.__set__(None, 1), desc) - self.assertIs(desc.__delete__(None), desc) - self.assertTrue(desc.setter(1)) - - x = X() - x.foo = 30 - self.assertEqual(x.xx, 10) - - del(x.foo) - - -class test_symbol_by_name(Case): - - def test_instance_returns_instance(self): - instance = object() - self.assertIs(utils.symbol_by_name(instance), instance) - - def test_returns_default(self): - default = object() - self.assertIs( - utils.symbol_by_name('xyz.ryx.qedoa.weq:foz', default=default), - default, - ) - - def test_no_default(self): - with self.assertRaises(ImportError): - utils.symbol_by_name('xyz.ryx.qedoa.weq:foz') - - def test_imp_reraises_ValueError(self): - imp = Mock() - imp.side_effect = ValueError() - with self.assertRaises(ValueError): - utils.symbol_by_name('kombu.Connection', imp=imp) - - def test_package(self): - from kombu.entity import Exchange - self.assertIs( - utils.symbol_by_name('.entity:Exchange', package='kombu'), - Exchange, - ) - self.assertTrue(utils.symbol_by_name(':Consumer', package='kombu')) - - -class test_ChannelPromise(Case): - - def test_repr(self): - obj = Mock(name='cb') - self.assertIn( - 'promise', - repr(utils.ChannelPromise(obj)), - ) - self.assertFalse(obj.called) - - -class test_entrypoints(Case): - - @mask_modules('pkg_resources') - def test_without_pkg_resources(self): - self.assertListEqual(list(utils.entrypoints('kombu.test')), []) - - @module_exists('pkg_resources') - def test_with_pkg_resources(self): - with patch('pkg_resources.iter_entry_points', create=True) as iterep: - eps = iterep.return_value = [Mock(), Mock()] - - self.assertTrue(list(utils.entrypoints('kombu.test'))) - iterep.assert_called_with('kombu.test') - eps[0].load.assert_called_with() - eps[1].load.assert_called_with() - - -class test_shufflecycle(Case): - - def test_shuffles(self): - prev_repeat, utils.repeat = utils.repeat, Mock() - try: - utils.repeat.return_value = list(range(10)) - values = set(['A', 'B', 'C']) - cycle = utils.shufflecycle(values) - seen = set() - for i in range(10): - next(cycle) - utils.repeat.assert_called_with(None) - self.assertTrue(seen.issubset(values)) - with self.assertRaises(StopIteration): - next(cycle) - next(cycle) - finally: - utils.repeat = prev_repeat - - -class test_version_string_as_tuple(Case): - - def test_versions(self): - self.assertTupleEqual( - version_string_as_tuple('3'), - version_info_t(3, 0, 0, '', ''), - ) - self.assertTupleEqual( - version_string_as_tuple('3.3'), - version_info_t(3, 3, 0, '', ''), - ) - self.assertTupleEqual( - version_string_as_tuple('3.3.1'), - version_info_t(3, 3, 1, '', ''), - ) - self.assertTupleEqual( - version_string_as_tuple('3.3.1a3'), - version_info_t(3, 3, 1, 'a3', ''), - ) - self.assertTupleEqual( - version_string_as_tuple('3.3.1a3-40c32'), - version_info_t(3, 3, 1, 'a3', '40c32'), - ) - self.assertEqual( - version_string_as_tuple('3.3.1.a3.40c32'), - version_info_t(3, 3, 1, 'a3', '40c32'), - ) diff --git a/awx/lib/site-packages/kombu/transport/SLMQ.py b/awx/lib/site-packages/kombu/transport/SLMQ.py deleted file mode 100644 index 449bc2fb81..0000000000 --- a/awx/lib/site-packages/kombu/transport/SLMQ.py +++ /dev/null @@ -1,186 +0,0 @@ -""" -kombu.transport.SLMQ -==================== - -SoftLayer Message Queue transport. - -""" -from __future__ import absolute_import - -import socket -import string - -from anyjson import loads, dumps - -import os - -from kombu.five import Empty, text_t -from kombu.utils import cached_property # , uuid -from kombu.utils.encoding import bytes_to_str, safe_str - -from . import virtual - -try: - from softlayer_messaging import get_client - from softlayer_messaging.errors import ResponseError -except ImportError: # pragma: no cover - get_client = ResponseError = None # noqa - -# dots are replaced by dash, all other punctuation replaced by underscore. -CHARS_REPLACE_TABLE = dict( - (ord(c), 0x5f) for c in string.punctuation if c not in '_') - - -class Channel(virtual.Channel): - default_visibility_timeout = 1800 # 30 minutes. - domain_format = 'kombu%(vhost)s' - _slmq = None - _queue_cache = {} - _noack_queues = set() - - def __init__(self, *args, **kwargs): - if get_client is None: - raise ImportError( - 'SLMQ transport requires the softlayer_messaging library', - ) - super(Channel, self).__init__(*args, **kwargs) - queues = self.slmq.queues() - for queue in queues: - self._queue_cache[queue] = queue - - def basic_consume(self, queue, no_ack, *args, **kwargs): - if no_ack: - self._noack_queues.add(queue) - return super(Channel, self).basic_consume(queue, no_ack, - *args, **kwargs) - - def basic_cancel(self, consumer_tag): - if consumer_tag in self._consumers: - queue = self._tag_to_queue[consumer_tag] - self._noack_queues.discard(queue) - return super(Channel, self).basic_cancel(consumer_tag) - - def entity_name(self, name, table=CHARS_REPLACE_TABLE): - """Format AMQP queue name into a valid SLQS queue name.""" - return text_t(safe_str(name)).translate(table) - - def _new_queue(self, queue, **kwargs): - """Ensures a queue exists in SLQS.""" - queue = self.entity_name(self.queue_name_prefix + queue) - try: - return self._queue_cache[queue] - except KeyError: - try: - self.slmq.create_queue( - queue, visibility_timeout=self.visibility_timeout) - except ResponseError: - pass - q = self._queue_cache[queue] = self.slmq.queue(queue) - return q - - def _delete(self, queue, *args): - """delete queue by name.""" - queue_name = self.entity_name(queue) - self._queue_cache.pop(queue_name, None) - self.slmq.queue(queue_name).delete(force=True) - super(Channel, self)._delete(queue_name) - - def _put(self, queue, message, **kwargs): - """Put message onto queue.""" - q = self._new_queue(queue) - q.push(dumps(message)) - - def _get(self, queue): - """Try to retrieve a single message off ``queue``.""" - q = self._new_queue(queue) - rs = q.pop(1) - if rs['items']: - m = rs['items'][0] - payload = loads(bytes_to_str(m['body'])) - if queue in self._noack_queues: - q.message(m['id']).delete() - else: - payload['properties']['delivery_info'].update({ - 'slmq_message_id': m['id'], 'slmq_queue_name': q.name}) - return payload - raise Empty() - - def basic_ack(self, delivery_tag): - delivery_info = self.qos.get(delivery_tag).delivery_info - try: - queue = delivery_info['slmq_queue_name'] - except KeyError: - pass - else: - self.delete_message(queue, delivery_info['slmq_message_id']) - super(Channel, self).basic_ack(delivery_tag) - - def _size(self, queue): - """Return the number of messages in a queue.""" - return self._new_queue(queue).detail()['message_count'] - - def _purge(self, queue): - """Delete all current messages in a queue.""" - q = self._new_queue(queue) - n = 0 - l = q.pop(10) - while l['items']: - for m in l['items']: - self.delete_message(queue, m['id']) - n += 1 - l = q.pop(10) - return n - - def delete_message(self, queue, message_id): - q = self.slmq.queue(self.entity_name(queue)) - return q.message(message_id).delete() - - @property - def slmq(self): - if self._slmq is None: - conninfo = self.conninfo - account = os.environ.get('SLMQ_ACCOUNT', conninfo.virtual_host) - user = os.environ.get('SL_USERNAME', conninfo.userid) - api_key = os.environ.get('SL_API_KEY', conninfo.password) - host = os.environ.get('SLMQ_HOST', conninfo.hostname) - port = os.environ.get('SLMQ_PORT', conninfo.port) - secure = bool(os.environ.get( - 'SLMQ_SECURE', self.transport_options.get('secure')) or True, - ) - endpoint = '{0}://{1}{2}'.format( - 'https' if secure else 'http', host, - ':{0}'.format(port) if port else '', - ) - - self._slmq = get_client(account, endpoint=endpoint) - self._slmq.authenticate(user, api_key) - return self._slmq - - @property - def conninfo(self): - return self.connection.client - - @property - def transport_options(self): - return self.connection.client.transport_options - - @cached_property - def visibility_timeout(self): - return (self.transport_options.get('visibility_timeout') or - self.default_visibility_timeout) - - @cached_property - def queue_name_prefix(self): - return self.transport_options.get('queue_name_prefix', '') - - -class Transport(virtual.Transport): - Channel = Channel - - polling_interval = 1 - default_port = None - connection_errors = ( - virtual.Transport.connection_errors + ( - ResponseError, socket.error - ) - ) diff --git a/awx/lib/site-packages/kombu/transport/SQS.py b/awx/lib/site-packages/kombu/transport/SQS.py deleted file mode 100644 index 68cb053c2c..0000000000 --- a/awx/lib/site-packages/kombu/transport/SQS.py +++ /dev/null @@ -1,539 +0,0 @@ -""" -kombu.transport.SQS -=================== - -Amazon SQS transport module for Kombu. This package implements an AMQP-like -interface on top of Amazons SQS service, with the goal of being optimized for -high performance and reliability. - -The default settings for this module are focused now on high performance in -task queue situations where tasks are small, idempotent and run very fast. - -SQS Features supported by this transport: - Long Polling: - http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/ - sqs-long-polling.html - - Long polling is enabled by setting the `wait_time_seconds` transport - option to a number > 1. Amazon supports up to 20 seconds. This is - disabled for now, but will be enabled by default in the near future. - - Batch API Actions: - http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/ - sqs-batch-api.html - - The default behavior of the SQS Channel.drain_events() method is to - request up to the 'prefetch_count' messages on every request to SQS. - These messages are stored locally in a deque object and passed back - to the Transport until the deque is empty, before triggering a new - API call to Amazon. - - This behavior dramatically speeds up the rate that you can pull tasks - from SQS when you have short-running tasks (or a large number of workers). - - When a Celery worker has multiple queues to monitor, it will pull down - up to 'prefetch_count' messages from queueA and work on them all before - moving on to queueB. If queueB is empty, it will wait up until - 'polling_interval' expires before moving back and checking on queueA. -""" - -from __future__ import absolute_import - -import collections -import socket -import string - -from anyjson import loads, dumps - -import boto -from boto import exception -from boto import sdb as _sdb -from boto import sqs as _sqs -from boto.sdb.domain import Domain -from boto.sdb.connection import SDBConnection -from boto.sqs.connection import SQSConnection -from boto.sqs.message import Message - -from kombu.five import Empty, range, text_t -from kombu.log import get_logger -from kombu.utils import cached_property, uuid -from kombu.utils.encoding import bytes_to_str, safe_str -from kombu.transport.virtual import scheduling - -from . import virtual - -logger = get_logger(__name__) - -# dots are replaced by dash, all other punctuation -# replaced by underscore. -CHARS_REPLACE_TABLE = dict((ord(c), 0x5f) - for c in string.punctuation if c not in '-_.') -CHARS_REPLACE_TABLE[0x2e] = 0x2d # '.' -> '-' - - -def maybe_int(x): - try: - return int(x) - except ValueError: - return x -BOTO_VERSION = tuple(maybe_int(part) for part in boto.__version__.split('.')) -W_LONG_POLLING = BOTO_VERSION >= (2, 8) - -#: SQS bulk get supports a maximum of 10 messages at a time. -SQS_MAX_MESSAGES = 10 - - -class Table(Domain): - """Amazon SimpleDB domain describing the message routing table.""" - # caches queues already bound, so we don't have to declare them again. - _already_bound = set() - - def routes_for(self, exchange): - """Iterator giving all routes for an exchange.""" - return self.select("""WHERE exchange = '%s'""" % exchange) - - def get_queue(self, queue): - """Get binding for queue.""" - qid = self._get_queue_id(queue) - if qid: - return self.get_item(qid) - - def create_binding(self, queue): - """Get binding item for queue. - - Creates the item if it doesn't exist. - - """ - item = self.get_queue(queue) - if item: - return item, item['id'] - id = uuid() - return self.new_item(id), id - - def queue_bind(self, exchange, routing_key, pattern, queue): - if queue not in self._already_bound: - binding, id = self.create_binding(queue) - binding.update(exchange=exchange, - routing_key=routing_key or '', - pattern=pattern or '', - queue=queue or '', - id=id) - binding.save() - self._already_bound.add(queue) - - def queue_delete(self, queue): - """delete queue by name.""" - self._already_bound.discard(queue) - item = self._get_queue_item(queue) - if item: - self.delete_item(item) - - def exchange_delete(self, exchange): - """Delete all routes for `exchange`.""" - for item in self.routes_for(exchange): - self.delete_item(item['id']) - - def get_item(self, item_name): - """Uses `consistent_read` by default.""" - # Domain is an old-style class, can't use super(). - for consistent_read in (False, True): - item = Domain.get_item(self, item_name, consistent_read) - if item: - return item - - def select(self, query='', next_token=None, - consistent_read=True, max_items=None): - """Uses `consistent_read` by default.""" - query = """SELECT * FROM `%s` %s""" % (self.name, query) - return Domain.select(self, query, next_token, - consistent_read, max_items) - - def _try_first(self, query='', **kwargs): - for c in (False, True): - for item in self.select(query, consistent_read=c, **kwargs): - return item - - def get_exchanges(self): - return list(set(i['exchange'] for i in self.select())) - - def _get_queue_item(self, queue): - return self._try_first("""WHERE queue = '%s' limit 1""" % queue) - - def _get_queue_id(self, queue): - item = self._get_queue_item(queue) - if item: - return item['id'] - - -class Channel(virtual.Channel): - Table = Table - - default_region = 'us-east-1' - default_visibility_timeout = 1800 # 30 minutes. - default_wait_time_seconds = 0 # disabled see #198 - domain_format = 'kombu%(vhost)s' - _sdb = None - _sqs = None - _queue_cache = {} - _noack_queues = set() - - def __init__(self, *args, **kwargs): - super(Channel, self).__init__(*args, **kwargs) - - # SQS blows up when you try to create a new queue if one already - # exists with a different visibility_timeout, so this prepopulates - # the queue_cache to protect us from recreating - # queues that are known to already exist. - queues = self.sqs.get_all_queues(prefix=self.queue_name_prefix) - for queue in queues: - self._queue_cache[queue.name] = queue - self._fanout_queues = set() - - # The drain_events() method stores extra messages in a local - # Deque object. This allows multiple messages to be requested from - # SQS at once for performance, but maintains the same external API - # to the caller of the drain_events() method. - self._queue_message_cache = collections.deque() - - def basic_consume(self, queue, no_ack, *args, **kwargs): - if no_ack: - self._noack_queues.add(queue) - return super(Channel, self).basic_consume( - queue, no_ack, *args, **kwargs - ) - - def basic_cancel(self, consumer_tag): - if consumer_tag in self._consumers: - queue = self._tag_to_queue[consumer_tag] - self._noack_queues.discard(queue) - return super(Channel, self).basic_cancel(consumer_tag) - - def drain_events(self, timeout=None): - """Return a single payload message from one of our queues. - - :raises Empty: if no messages available. - - """ - # If we're not allowed to consume or have no consumers, raise Empty - if not self._consumers or not self.qos.can_consume(): - raise Empty() - message_cache = self._queue_message_cache - - # Check if there are any items in our buffer. If there are any, pop - # off that queue first. - try: - return message_cache.popleft() - except IndexError: - pass - - # At this point, go and get more messages from SQS - res, queue = self._poll(self.cycle, timeout=timeout) - message_cache.extend((r, queue) for r in res) - - # Now try to pop off the queue again. - try: - return message_cache.popleft() - except IndexError: - raise Empty() - - def _reset_cycle(self): - """Reset the consume cycle. - - :returns: a FairCycle object that points to our _get_bulk() method - rather than the standard _get() method. This allows for multiple - messages to be returned at once from SQS (based on the prefetch - limit). - - """ - self._cycle = scheduling.FairCycle( - self._get_bulk, self._active_queues, Empty, - ) - - def entity_name(self, name, table=CHARS_REPLACE_TABLE): - """Format AMQP queue name into a legal SQS queue name.""" - return text_t(safe_str(name)).translate(table) - - def _new_queue(self, queue, **kwargs): - """Ensure a queue with given name exists in SQS.""" - # Translate to SQS name for consistency with initial - # _queue_cache population. - queue = self.entity_name(self.queue_name_prefix + queue) - try: - return self._queue_cache[queue] - except KeyError: - q = self._queue_cache[queue] = self.sqs.create_queue( - queue, self.visibility_timeout, - ) - return q - - def queue_bind(self, queue, exchange=None, routing_key='', - arguments=None, **kwargs): - super(Channel, self).queue_bind(queue, exchange, routing_key, - arguments, **kwargs) - if self.typeof(exchange).type == 'fanout': - self._fanout_queues.add(queue) - - def _queue_bind(self, *args): - """Bind ``queue`` to ``exchange`` with routing key. - - Route will be stored in SDB if so enabled. - - """ - if self.supports_fanout: - self.table.queue_bind(*args) - - def get_table(self, exchange): - """Get routing table. - - Retrieved from SDB if :attr:`supports_fanout`. - - """ - if self.supports_fanout: - return [(r['routing_key'], r['pattern'], r['queue']) - for r in self.table.routes_for(exchange)] - return super(Channel, self).get_table(exchange) - - def get_exchanges(self): - if self.supports_fanout: - return self.table.get_exchanges() - return super(Channel, self).get_exchanges() - - def _delete(self, queue, *args): - """delete queue by name.""" - if self.supports_fanout: - self.table.queue_delete(queue) - super(Channel, self)._delete(queue) - self._queue_cache.pop(queue, None) - - def exchange_delete(self, exchange, **kwargs): - """Delete exchange by name.""" - if self.supports_fanout: - self.table.exchange_delete(exchange) - super(Channel, self).exchange_delete(exchange, **kwargs) - - def _has_queue(self, queue, **kwargs): - """Return True if ``queue`` was previously declared.""" - if self.supports_fanout: - return bool(self.table.get_queue(queue)) - return super(Channel, self)._has_queue(queue) - - def _put(self, queue, message, **kwargs): - """Put message onto queue.""" - q = self._new_queue(queue) - m = Message() - m.set_body(dumps(message)) - q.write(m) - - def _put_fanout(self, exchange, message, routing_key, **kwargs): - """Deliver fanout message to all queues in ``exchange``.""" - for route in self.table.routes_for(exchange): - self._put(route['queue'], message, **kwargs) - - def _get_from_sqs(self, queue, count=1): - """Retrieve messages from SQS and returns the raw SQS message objects. - - :returns: List of SQS message objects - - """ - q = self._new_queue(queue) - if W_LONG_POLLING and queue not in self._fanout_queues: - return q.get_messages( - count, wait_time_seconds=self.wait_time_seconds, - ) - else: # boto < 2.8 - return q.get_messages(count) - - def _message_to_python(self, message, queue_name, queue): - payload = loads(bytes_to_str(message.get_body())) - if queue_name in self._noack_queues: - queue.delete_message(message) - else: - payload['properties']['delivery_info'].update({ - 'sqs_message': message, 'sqs_queue': queue, - }) - return payload - - def _messages_to_python(self, messages, queue): - """Convert a list of SQS Message objects into Payloads. - - This method handles converting SQS Message objects into - Payloads, and appropriately updating the queue depending on - the 'ack' settings for that queue. - - :param messages: A list of SQS Message objects. - :param queue: String name representing the queue they came from - - :returns: A list of Payload objects - - """ - q = self._new_queue(queue) - return [self._message_to_python(m, queue, q) for m in messages] - - def _get_bulk(self, queue, max_if_unlimited=SQS_MAX_MESSAGES): - """Try to retrieve multiple messages off ``queue``. - - Where _get() returns a single Payload object, this method returns a - list of Payload objects. The number of objects returned is determined - by the total number of messages available in the queue and the - number of messages that the QoS object allows (based on the - prefetch_count). - - .. note:: - Ignores QoS limits so caller is responsible for checking - that we are allowed to consume at least one message from the - queue. get_bulk will then ask QoS for an estimate of - the number of extra messages that we can consume. - - args: - queue: The queue name (string) to pull from - - returns: - payloads: A list of payload objects returned - """ - # drain_events calls `can_consume` first, consuming - # a token, so we know that we are allowed to consume at least - # one message. - maxcount = self.qos.can_consume_max_estimate() - maxcount = max_if_unlimited if maxcount is None else max(maxcount, 1) - if maxcount: - messages = self._get_from_sqs( - queue, count=min(maxcount, SQS_MAX_MESSAGES), - ) - - if messages: - return self._messages_to_python(messages, queue) - raise Empty() - - def _get(self, queue): - """Try to retrieve a single message off ``queue``.""" - messages = self._get_from_sqs(queue, count=1) - - if messages: - return self._messages_to_python(messages, queue)[0] - raise Empty() - - def _restore(self, message, - unwanted_delivery_info=('sqs_message', 'sqs_queue')): - for unwanted_key in unwanted_delivery_info: - # Remove objects that aren't JSON serializable (Issue #1108). - message.delivery_info.pop(unwanted_key, None) - return super(Channel, self)._restore(message) - - def basic_ack(self, delivery_tag): - delivery_info = self.qos.get(delivery_tag).delivery_info - try: - queue = delivery_info['sqs_queue'] - except KeyError: - pass - else: - queue.delete_message(delivery_info['sqs_message']) - super(Channel, self).basic_ack(delivery_tag) - - def _size(self, queue): - """Return the number of messages in a queue.""" - return self._new_queue(queue).count() - - def _purge(self, queue): - """Delete all current messages in a queue.""" - q = self._new_queue(queue) - # SQS is slow at registering messages, so run for a few - # iterations to ensure messages are deleted. - size = 0 - for i in range(10): - size += q.count() - if not size: - break - q.clear() - return size - - def close(self): - super(Channel, self).close() - for conn in (self._sqs, self._sdb): - if conn: - try: - conn.close() - except AttributeError as exc: # FIXME ??? - if "can't set attribute" not in str(exc): - raise - - def _get_regioninfo(self, regions): - if self.region: - for _r in regions: - if _r.name == self.region: - return _r - - def _aws_connect_to(self, fun, regions): - conninfo = self.conninfo - region = self._get_regioninfo(regions) - return fun(region=region, - aws_access_key_id=conninfo.userid, - aws_secret_access_key=conninfo.password, - port=conninfo.port) - - @property - def sqs(self): - if self._sqs is None: - self._sqs = self._aws_connect_to(SQSConnection, _sqs.regions()) - return self._sqs - - @property - def sdb(self): - if self._sdb is None: - self._sdb = self._aws_connect_to(SDBConnection, _sdb.regions()) - return self._sdb - - @property - def table(self): - name = self.entity_name( - self.domain_format % {'vhost': self.conninfo.virtual_host}) - d = self.sdb.get_object( - 'CreateDomain', {'DomainName': name}, self.Table) - d.name = name - return d - - @property - def conninfo(self): - return self.connection.client - - @property - def transport_options(self): - return self.connection.client.transport_options - - @cached_property - def visibility_timeout(self): - return (self.transport_options.get('visibility_timeout') or - self.default_visibility_timeout) - - @cached_property - def queue_name_prefix(self): - return self.transport_options.get('queue_name_prefix', '') - - @cached_property - def supports_fanout(self): - return self.transport_options.get('sdb_persistence', False) - - @cached_property - def region(self): - return self.transport_options.get('region') or self.default_region - - @cached_property - def wait_time_seconds(self): - return self.transport_options.get('wait_time_seconds', - self.default_wait_time_seconds) - - -class Transport(virtual.Transport): - Channel = Channel - - polling_interval = 1 - wait_time_seconds = 0 - default_port = None - connection_errors = ( - virtual.Transport.connection_errors + - (exception.SQSError, socket.error) - ) - channel_errors = ( - virtual.Transport.channel_errors + (exception.SQSDecodeError, ) - ) - driver_type = 'sqs' - driver_name = 'sqs' diff --git a/awx/lib/site-packages/kombu/transport/__init__.py b/awx/lib/site-packages/kombu/transport/__init__.py deleted file mode 100644 index 10d62e9506..0000000000 --- a/awx/lib/site-packages/kombu/transport/__init__.py +++ /dev/null @@ -1,109 +0,0 @@ -""" -kombu.transport -=============== - -Built-in transports. - -""" -from __future__ import absolute_import - -from kombu.five import string_t -from kombu.syn import _detect_environment -from kombu.utils import symbol_by_name - - -def supports_librabbitmq(): - if _detect_environment() == 'default': - try: - import librabbitmq # noqa - except ImportError: # pragma: no cover - pass - else: # pragma: no cover - return True - - -def _ghettoq(name, new, alias=None): - xxx = new # stupid enclosing - - def __inner(): - import warnings - _new = callable(xxx) and xxx() or xxx - gtransport = 'ghettoq.taproot.{0}'.format(name) - ktransport = 'kombu.transport.{0}.Transport'.format(_new) - this = alias or name - warnings.warn(""" - Ghettoq does not work with Kombu, but there is now a built-in version - of the {0} transport. - - You should replace {1!r} with: {2!r} - """.format(name, gtransport, this)) - return ktransport - - return __inner - - -TRANSPORT_ALIASES = { - 'amqp': 'kombu.transport.pyamqp:Transport', - 'pyamqp': 'kombu.transport.pyamqp:Transport', - 'librabbitmq': 'kombu.transport.librabbitmq:Transport', - 'memory': 'kombu.transport.memory:Transport', - 'redis': 'kombu.transport.redis:Transport', - 'SQS': 'kombu.transport.SQS:Transport', - 'sqs': 'kombu.transport.SQS:Transport', - 'beanstalk': 'kombu.transport.beanstalk:Transport', - 'mongodb': 'kombu.transport.mongodb:Transport', - 'couchdb': 'kombu.transport.couchdb:Transport', - 'zookeeper': 'kombu.transport.zookeeper:Transport', - 'django': 'kombu.transport.django:Transport', - 'sqlalchemy': 'kombu.transport.sqlalchemy:Transport', - 'sqla': 'kombu.transport.sqlalchemy:Transport', - 'SLMQ': 'kombu.transport.SLMQ.Transport', - 'slmq': 'kombu.transport.SLMQ.Transport', - 'ghettoq.taproot.Redis': _ghettoq('Redis', 'redis', 'redis'), - 'ghettoq.taproot.Database': _ghettoq('Database', 'django', 'django'), - 'ghettoq.taproot.MongoDB': _ghettoq('MongoDB', 'mongodb'), - 'ghettoq.taproot.Beanstalk': _ghettoq('Beanstalk', 'beanstalk'), - 'ghettoq.taproot.CouchDB': _ghettoq('CouchDB', 'couchdb'), - 'filesystem': 'kombu.transport.filesystem:Transport', - 'zeromq': 'kombu.transport.zmq:Transport', - 'zmq': 'kombu.transport.zmq:Transport', - 'amqplib': 'kombu.transport.amqplib:Transport', -} - -_transport_cache = {} - - -def resolve_transport(transport=None): - if isinstance(transport, string_t): - try: - transport = TRANSPORT_ALIASES[transport] - except KeyError: - if '.' not in transport and ':' not in transport: - from kombu.utils.text import fmatch_best - alt = fmatch_best(transport, TRANSPORT_ALIASES) - if alt: - raise KeyError( - 'No such transport: {0}. Did you mean {1}?'.format( - transport, alt)) - raise KeyError('No such transport: {0}'.format(transport)) - else: - if callable(transport): - transport = transport() - return symbol_by_name(transport) - return transport - - -def get_transport_cls(transport=None): - """Get transport class by name. - - The transport string is the full path to a transport class, e.g.:: - - "kombu.transport.pyamqp:Transport" - - If the name does not include `"."` (is not fully qualified), - the alias table will be consulted. - - """ - if transport not in _transport_cache: - _transport_cache[transport] = resolve_transport(transport) - return _transport_cache[transport] diff --git a/awx/lib/site-packages/kombu/transport/amqplib.py b/awx/lib/site-packages/kombu/transport/amqplib.py deleted file mode 100644 index 5f4dbacbeb..0000000000 --- a/awx/lib/site-packages/kombu/transport/amqplib.py +++ /dev/null @@ -1,402 +0,0 @@ -""" -kombu.transport.amqplib -======================= - -amqplib transport. - -""" -from __future__ import absolute_import - -import errno -import socket - -try: - from ssl import SSLError -except ImportError: - class SSLError(Exception): # noqa - pass -from struct import unpack - - -class NA(object): - pass - -try: - from amqplib import client_0_8 as amqp - from amqplib.client_0_8 import transport - from amqplib.client_0_8.channel import Channel as _Channel - from amqplib.client_0_8.exceptions import AMQPConnectionException - from amqplib.client_0_8.exceptions import AMQPChannelException -except ImportError: # pragma: no cover - - class NAx(object): - pass - amqp = NA - amqp.Connection = NA - transport = _Channel = NA # noqa - # Sphinx crashes if this is NA, must be different class - transport.TCPTransport = transport.SSLTransport = NAx - AMQPConnectionException = AMQPChannelException = NA # noqa - - -from kombu.five import items -from kombu.utils.encoding import str_to_bytes -from kombu.utils.amq_manager import get_manager - -from . import base - -DEFAULT_PORT = 5672 -HAS_MSG_PEEK = hasattr(socket, 'MSG_PEEK') - -# amqplib's handshake mistakenly identifies as protocol version 1191, -# this breaks in RabbitMQ tip, which no longer falls back to -# 0-8 for unknown ids. -transport.AMQP_PROTOCOL_HEADER = str_to_bytes('AMQP\x01\x01\x08\x00') - - -# - fixes warnings when socket is not connected. -class TCPTransport(transport.TCPTransport): - - def read_frame(self): - frame_type, channel, size = unpack('>BHI', self._read(7, True)) - payload = self._read(size) - ch = ord(self._read(1)) - if ch == 206: # '\xce' - return frame_type, channel, payload - else: - raise Exception( - 'Framing Error, received 0x%02x while expecting 0xce' % ch) - - def _read(self, n, initial=False): - read_buffer = self._read_buffer - while len(read_buffer) < n: - try: - s = self.sock.recv(n - len(read_buffer)) - except socket.error as exc: - if not initial and exc.errno in (errno.EAGAIN, errno.EINTR): - continue - raise - if not s: - raise IOError('Socket closed') - read_buffer += s - - result = read_buffer[:n] - self._read_buffer = read_buffer[n:] - - return result - - def __del__(self): - try: - self.close() - except Exception: - pass - finally: - self.sock = None - -transport.TCPTransport = TCPTransport - - -class SSLTransport(transport.SSLTransport): - - def __init__(self, host, connect_timeout, ssl): - if isinstance(ssl, dict): - self.sslopts = ssl - self.sslobj = None - - transport._AbstractTransport.__init__(self, host, connect_timeout) - - def read_frame(self): - frame_type, channel, size = unpack('>BHI', self._read(7, True)) - payload = self._read(size) - ch = ord(self._read(1)) - if ch == 206: # '\xce' - return frame_type, channel, payload - else: - raise Exception( - 'Framing Error, received 0x%02x while expecting 0xce' % ch) - - def _read(self, n, initial=False): - result = '' - - while len(result) < n: - try: - s = self.sslobj.read(n - len(result)) - except socket.error as exc: - if not initial and exc.errno in (errno.EAGAIN, errno.EINTR): - continue - raise - if not s: - raise IOError('Socket closed') - result += s - - return result - - def __del__(self): - try: - self.close() - except Exception: - pass - finally: - self.sock = None -transport.SSLTransport = SSLTransport - - -class Connection(amqp.Connection): # pragma: no cover - connected = True - - def _do_close(self, *args, **kwargs): - # amqplib does not ignore socket errors when connection - # is closed on the remote end. - try: - super(Connection, self)._do_close(*args, **kwargs) - except socket.error: - pass - - def _dispatch_basic_return(self, channel, args, msg): - reply_code = args.read_short() - reply_text = args.read_shortstr() - exchange = args.read_shortstr() - routing_key = args.read_shortstr() - - exc = AMQPChannelException(reply_code, reply_text, (50, 60)) - if channel.events['basic_return']: - for callback in channel.events['basic_return']: - callback(exc, exchange, routing_key, msg) - else: - raise exc - - def __init__(self, *args, **kwargs): - super(Connection, self).__init__(*args, **kwargs) - self._method_override = {(60, 50): self._dispatch_basic_return} - - def drain_events(self, timeout=None): - """Wait for an event on a channel.""" - chanmap = self.channels - chanid, method_sig, args, content = self._wait_multiple( - chanmap, None, timeout=timeout) - - channel = chanmap[chanid] - - if (content - and channel.auto_decode - and hasattr(content, 'content_encoding')): - try: - content.body = content.body.decode(content.content_encoding) - except Exception: - pass - - amqp_method = self._method_override.get(method_sig) or \ - channel._METHOD_MAP.get(method_sig, None) - - if amqp_method is None: - raise Exception('Unknown AMQP method (%d, %d)' % method_sig) - - if content is None: - return amqp_method(channel, args) - else: - return amqp_method(channel, args, content) - - def read_timeout(self, timeout=None): - if timeout is None: - return self.method_reader.read_method() - sock = self.transport.sock - prev = sock.gettimeout() - if prev != timeout: - sock.settimeout(timeout) - try: - try: - return self.method_reader.read_method() - except SSLError as exc: - # http://bugs.python.org/issue10272 - if 'timed out' in str(exc): - raise socket.timeout() - # Non-blocking SSL sockets can throw SSLError - if 'The operation did not complete' in str(exc): - raise socket.timeout() - raise - finally: - if prev != timeout: - sock.settimeout(prev) - - def _wait_multiple(self, channels, allowed_methods, timeout=None): - for channel_id, channel in items(channels): - method_queue = channel.method_queue - for queued_method in method_queue: - method_sig = queued_method[0] - if (allowed_methods is None - or method_sig in allowed_methods - or method_sig == (20, 40)): - method_queue.remove(queued_method) - method_sig, args, content = queued_method - return channel_id, method_sig, args, content - - # Nothing queued, need to wait for a method from the peer - read_timeout = self.read_timeout - wait = self.wait - while 1: - channel, method_sig, args, content = read_timeout(timeout) - - if (channel in channels - and allowed_methods is None - or method_sig in allowed_methods - or method_sig == (20, 40)): - return channel, method_sig, args, content - - # Not the channel and/or method we were looking for. Queue - # this method for later - channels[channel].method_queue.append((method_sig, args, content)) - - # - # If we just queued up a method for channel 0 (the Connection - # itself) it's probably a close method in reaction to some - # error, so deal with it right away. - # - if channel == 0: - wait() - - def channel(self, channel_id=None): - try: - return self.channels[channel_id] - except KeyError: - return Channel(self, channel_id) - - -class Message(base.Message): - - def __init__(self, channel, msg, **kwargs): - props = msg.properties - super(Message, self).__init__( - channel, - body=msg.body, - delivery_tag=msg.delivery_tag, - content_type=props.get('content_type'), - content_encoding=props.get('content_encoding'), - delivery_info=msg.delivery_info, - properties=msg.properties, - headers=props.get('application_headers') or {}, - **kwargs) - - -class Channel(_Channel, base.StdChannel): - Message = Message - events = {'basic_return': set()} - - def __init__(self, *args, **kwargs): - self.no_ack_consumers = set() - super(Channel, self).__init__(*args, **kwargs) - - def prepare_message(self, body, priority=None, content_type=None, - content_encoding=None, headers=None, properties=None): - """Encapsulate data into a AMQP message.""" - return amqp.Message(body, priority=priority, - content_type=content_type, - content_encoding=content_encoding, - application_headers=headers, - **properties) - - def message_to_python(self, raw_message): - """Convert encoded message body back to a Python value.""" - return self.Message(self, raw_message) - - def close(self): - try: - super(Channel, self).close() - finally: - self.connection = None - - def basic_consume(self, *args, **kwargs): - consumer_tag = super(Channel, self).basic_consume(*args, **kwargs) - if kwargs['no_ack']: - self.no_ack_consumers.add(consumer_tag) - return consumer_tag - - def basic_cancel(self, consumer_tag, **kwargs): - self.no_ack_consumers.discard(consumer_tag) - return super(Channel, self).basic_cancel(consumer_tag, **kwargs) - - -class Transport(base.Transport): - Connection = Connection - - default_port = DEFAULT_PORT - - # it's very annoying that amqplib sometimes raises AttributeError - # if the connection is lost, but nothing we can do about that here. - connection_errors = ( - base.Transport.connection_errors + ( - AMQPConnectionException, - socket.error, IOError, OSError, AttributeError) - ) - channel_errors = base.Transport.channel_errors + (AMQPChannelException, ) - - driver_name = 'amqplib' - driver_type = 'amqp' - supports_ev = True - - def __init__(self, client, **kwargs): - self.client = client - self.default_port = kwargs.get('default_port') or self.default_port - - if amqp is NA: - raise ImportError('Missing amqplib library (pip install amqplib)') - - def create_channel(self, connection): - return connection.channel() - - def drain_events(self, connection, **kwargs): - return connection.drain_events(**kwargs) - - def establish_connection(self): - """Establish connection to the AMQP broker.""" - conninfo = self.client - for name, default_value in items(self.default_connection_params): - if not getattr(conninfo, name, None): - setattr(conninfo, name, default_value) - if conninfo.hostname == 'localhost': - conninfo.hostname = '127.0.0.1' - conn = self.Connection(host=conninfo.host, - userid=conninfo.userid, - password=conninfo.password, - login_method=conninfo.login_method, - virtual_host=conninfo.virtual_host, - insist=conninfo.insist, - ssl=conninfo.ssl, - connect_timeout=conninfo.connect_timeout) - conn.client = self.client - return conn - - def close_connection(self, connection): - """Close the AMQP broker connection.""" - connection.client = None - connection.close() - - def is_alive(self, connection): - if HAS_MSG_PEEK: - sock = connection.transport.sock - prev = sock.gettimeout() - sock.settimeout(0.0001) - try: - sock.recv(1, socket.MSG_PEEK) - except socket.timeout: - pass - except socket.error: - return False - finally: - sock.settimeout(prev) - return True - - def verify_connection(self, connection): - return connection.channels is not None and self.is_alive(connection) - - def register_with_event_loop(self, connection, loop): - loop.add_reader(connection.method_reader.source.sock, - self.on_readable, connection, loop) - - @property - def default_connection_params(self): - return {'userid': 'guest', 'password': 'guest', - 'port': self.default_port, - 'hostname': 'localhost', 'login_method': 'AMQPLAIN'} - - def get_manager(self, *args, **kwargs): - return get_manager(self.client, *args, **kwargs) diff --git a/awx/lib/site-packages/kombu/transport/base.py b/awx/lib/site-packages/kombu/transport/base.py deleted file mode 100644 index c226307eed..0000000000 --- a/awx/lib/site-packages/kombu/transport/base.py +++ /dev/null @@ -1,173 +0,0 @@ -""" -kombu.transport.base -==================== - -Base transport interface. - -""" -from __future__ import absolute_import - -import errno -import socket - -from kombu.exceptions import ChannelError, ConnectionError -from kombu.message import Message -from kombu.utils import cached_property -from kombu.utils.compat import get_errno - -__all__ = ['Message', 'StdChannel', 'Management', 'Transport'] - - -def _LeftBlank(obj, method): - return NotImplementedError( - 'Transport {0.__module__}.{0.__name__} does not implement {1}'.format( - obj.__class__, method)) - - -class StdChannel(object): - no_ack_consumers = None - - def Consumer(self, *args, **kwargs): - from kombu.messaging import Consumer - return Consumer(self, *args, **kwargs) - - def Producer(self, *args, **kwargs): - from kombu.messaging import Producer - return Producer(self, *args, **kwargs) - - def get_bindings(self): - raise _LeftBlank(self, 'get_bindings') - - def after_reply_message_received(self, queue): - """reply queue semantics: can be used to delete the queue - after transient reply message received.""" - pass - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - -class Management(object): - - def __init__(self, transport): - self.transport = transport - - def get_bindings(self): - raise _LeftBlank(self, 'get_bindings') - - -class Transport(object): - """Base class for transports.""" - Management = Management - - #: The :class:`~kombu.Connection` owning this instance. - client = None - - #: Set to True if :class:`~kombu.Connection` should pass the URL - #: unmodified. - can_parse_url = False - - #: Default port used when no port has been specified. - default_port = None - - #: Tuple of errors that can happen due to connection failure. - connection_errors = (ConnectionError, ) - - #: Tuple of errors that can happen due to channel/method failure. - channel_errors = (ChannelError, ) - - #: Type of driver, can be used to separate transports - #: using the AMQP protocol (driver_type: 'amqp'), - #: Redis (driver_type: 'redis'), etc... - driver_type = 'N/A' - - #: Name of driver library (e.g. 'py-amqp', 'redis', 'beanstalkc'). - driver_name = 'N/A' - - #: Whether this transports support heartbeats, - #: and that the :meth:`heartbeat_check` method has any effect. - supports_heartbeats = False - - #: Set to true if the transport supports the AIO interface. - supports_ev = False - - __reader = None - - def __init__(self, client, **kwargs): - self.client = client - - def establish_connection(self): - raise _LeftBlank(self, 'establish_connection') - - def close_connection(self, connection): - raise _LeftBlank(self, 'close_connection') - - def create_channel(self, connection): - raise _LeftBlank(self, 'create_channel') - - def close_channel(self, connection): - raise _LeftBlank(self, 'close_channel') - - def drain_events(self, connection, **kwargs): - raise _LeftBlank(self, 'drain_events') - - def heartbeat_check(self, connection, rate=2): - pass - - def driver_version(self): - return 'N/A' - - def get_heartbeat_interval(self, connection): - return 0 - - def register_with_event_loop(self, loop): - pass - - def unregister_from_event_loop(self, loop): - pass - - def verify_connection(self, connection): - return True - - def _make_reader(self, connection, timeout=socket.timeout, - error=socket.error, get_errno=get_errno, - _unavail=(errno.EAGAIN, errno.EINTR)): - drain_events = connection.drain_events - - def _read(loop): - if not connection.connected: - raise ConnectionError('Socket was disconnected') - try: - drain_events(timeout=0) - except timeout: - return - except error as exc: - if get_errno(exc) in _unavail: - return - raise - loop.call_soon(_read, loop) - - return _read - - def qos_semantics_matches_spec(self, connection): - return True - - def on_readable(self, connection, loop): - reader = self.__reader - if reader is None: - reader = self.__reader = self._make_reader(connection) - reader(loop) - - @property - def default_connection_params(self): - return {} - - def get_manager(self, *args, **kwargs): - return self.Management(self) - - @cached_property - def manager(self): - return self.get_manager() diff --git a/awx/lib/site-packages/kombu/transport/beanstalk.py b/awx/lib/site-packages/kombu/transport/beanstalk.py deleted file mode 100644 index 4e73bbca4e..0000000000 --- a/awx/lib/site-packages/kombu/transport/beanstalk.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -kombu.transport.beanstalk -========================= - -Beanstalk transport. - -:copyright: (c) 2010 - 2013 by David Ziegler. -:license: BSD, see LICENSE for more details. - -""" -from __future__ import absolute_import - -import socket - -from anyjson import loads, dumps - -from kombu.five import Empty -from kombu.utils.encoding import bytes_to_str - -from . import virtual - -try: - import beanstalkc -except ImportError: # pragma: no cover - beanstalkc = None # noqa - -DEFAULT_PORT = 11300 - -__author__ = 'David Ziegler <david.ziegler@gmail.com>' - - -class Channel(virtual.Channel): - _client = None - - def _parse_job(self, job): - item, dest = None, None - if job: - try: - item = loads(bytes_to_str(job.body)) - dest = job.stats()['tube'] - except Exception: - job.bury() - else: - job.delete() - else: - raise Empty() - return item, dest - - def _put(self, queue, message, **kwargs): - extra = {} - priority = message['properties']['delivery_info']['priority'] - ttr = message['properties'].get('ttr') - if ttr is not None: - extra['ttr'] = ttr - - self.client.use(queue) - self.client.put(dumps(message), priority=priority, **extra) - - def _get(self, queue): - if queue not in self.client.watching(): - self.client.watch(queue) - - [self.client.ignore(active) for active in self.client.watching() - if active != queue] - - job = self.client.reserve(timeout=1) - item, dest = self._parse_job(job) - return item - - def _get_many(self, queues, timeout=1): - # timeout of None will cause beanstalk to timeout waiting - # for a new request - if timeout is None: - timeout = 1 - - watching = self.client.watching() - - [self.client.watch(active) for active in queues - if active not in watching] - - [self.client.ignore(active) for active in watching - if active not in queues] - - job = self.client.reserve(timeout=timeout) - return self._parse_job(job) - - def _purge(self, queue): - if queue not in self.client.watching(): - self.client.watch(queue) - - [self.client.ignore(active) - for active in self.client.watching() - if active != queue] - count = 0 - while 1: - job = self.client.reserve(timeout=1) - if job: - job.delete() - count += 1 - else: - break - return count - - def _size(self, queue): - return 0 - - def _open(self): - conninfo = self.connection.client - host = conninfo.hostname or 'localhost' - port = conninfo.port or DEFAULT_PORT - conn = beanstalkc.Connection(host=host, port=port) - conn.connect() - return conn - - def close(self): - if self._client is not None: - return self._client.close() - super(Channel, self).close() - - @property - def client(self): - if self._client is None: - self._client = self._open() - return self._client - - -class Transport(virtual.Transport): - Channel = Channel - - polling_interval = 1 - default_port = DEFAULT_PORT - connection_errors = ( - virtual.Transport.connection_errors + ( - socket.error, IOError, - getattr(beanstalkc, 'SocketError', None), - ) - ) - channel_errors = ( - virtual.Transport.channel_errors + ( - socket.error, IOError, - getattr(beanstalkc, 'SocketError', None), - getattr(beanstalkc, 'BeanstalkcException', None), - ) - ) - driver_type = 'beanstalk' - driver_name = 'beanstalkc' - - def __init__(self, *args, **kwargs): - if beanstalkc is None: - raise ImportError( - 'Missing beanstalkc library (pip install beanstalkc)') - super(Transport, self).__init__(*args, **kwargs) - - def driver_version(self): - return beanstalkc.__version__ diff --git a/awx/lib/site-packages/kombu/transport/couchdb.py b/awx/lib/site-packages/kombu/transport/couchdb.py deleted file mode 100644 index 99d1362ede..0000000000 --- a/awx/lib/site-packages/kombu/transport/couchdb.py +++ /dev/null @@ -1,142 +0,0 @@ -""" -kombu.transport.couchdb -======================= - -CouchDB transport. - -:copyright: (c) 2010 - 2013 by David Clymer. -:license: BSD, see LICENSE for more details. - -""" -from __future__ import absolute_import - -import socket - -from anyjson import loads, dumps - -from kombu.five import Empty -from kombu.utils import uuid4 -from kombu.utils.encoding import bytes_to_str - -from . import virtual - -try: - import couchdb -except ImportError: # pragma: no cover - couchdb = None # noqa - -DEFAULT_PORT = 5984 -DEFAULT_DATABASE = 'kombu_default' - -__author__ = 'David Clymer <david@zettazebra.com>' - - -def create_message_view(db): - from couchdb import design - - view = design.ViewDefinition('kombu', 'messages', """ - function (doc) { - if (doc.queue && doc.payload) - emit(doc.queue, doc); - } - """) - if not view.get_doc(db): - view.sync(db) - - -class Channel(virtual.Channel): - _client = None - - view_created = False - - def _put(self, queue, message, **kwargs): - self.client.save({'_id': uuid4().hex, - 'queue': queue, - 'payload': dumps(message)}) - - def _get(self, queue): - result = self._query(queue, limit=1) - if not result: - raise Empty() - - item = result.rows[0].value - self.client.delete(item) - return loads(bytes_to_str(item['payload'])) - - def _purge(self, queue): - result = self._query(queue) - for item in result: - self.client.delete(item.value) - return len(result) - - def _size(self, queue): - return len(self._query(queue)) - - def _open(self): - conninfo = self.connection.client - dbname = conninfo.virtual_host - proto = conninfo.ssl and 'https' or 'http' - if not dbname or dbname == '/': - dbname = DEFAULT_DATABASE - port = conninfo.port or DEFAULT_PORT - server = couchdb.Server('%s://%s:%s/' % (proto, - conninfo.hostname, - port)) - # Use username and password if avaliable - try: - if conninfo.userid: - server.resource.credentials = (conninfo.userid, - conninfo.password) - except AttributeError: - pass - try: - return server[dbname] - except couchdb.http.ResourceNotFound: - return server.create(dbname) - - def _query(self, queue, **kwargs): - if not self.view_created: - # if the message view is not yet set up, we'll need it now. - create_message_view(self.client) - self.view_created = True - return self.client.view('kombu/messages', key=queue, **kwargs) - - @property - def client(self): - if self._client is None: - self._client = self._open() - return self._client - - -class Transport(virtual.Transport): - Channel = Channel - - polling_interval = 1 - default_port = DEFAULT_PORT - connection_errors = ( - virtual.Transport.connection_errors + ( - socket.error, - getattr(couchdb, 'HTTPError', None), - getattr(couchdb, 'ServerError', None), - getattr(couchdb, 'Unauthorized', None), - ) - ) - channel_errors = ( - virtual.Transport.channel_errors + ( - getattr(couchdb, 'HTTPError', None), - getattr(couchdb, 'ServerError', None), - getattr(couchdb, 'PreconditionFailed', None), - getattr(couchdb, 'ResourceConflict', None), - getattr(couchdb, 'ResourceNotFound', None), - ) - ) - driver_type = 'couchdb' - driver_name = 'couchdb' - - def __init__(self, *args, **kwargs): - if couchdb is None: - raise ImportError('Missing couchdb library (pip install couchdb)') - super(Transport, self).__init__(*args, **kwargs) - - def driver_version(self): - return couchdb.__version__ diff --git a/awx/lib/site-packages/kombu/transport/django/__init__.py b/awx/lib/site-packages/kombu/transport/django/__init__.py deleted file mode 100644 index e859f3fd71..0000000000 --- a/awx/lib/site-packages/kombu/transport/django/__init__.py +++ /dev/null @@ -1,68 +0,0 @@ -"""Kombu transport using the Django database as a message store.""" -from __future__ import absolute_import - -from anyjson import loads, dumps - -from django.conf import settings -from django.core import exceptions as errors - -from kombu.five import Empty -from kombu.transport import virtual -from kombu.utils.encoding import bytes_to_str - -from .models import Queue - -VERSION = (1, 0, 0) -__version__ = '.'.join(map(str, VERSION)) - -POLLING_INTERVAL = getattr(settings, 'KOMBU_POLLING_INTERVAL', - getattr(settings, 'DJKOMBU_POLLING_INTERVAL', 5.0)) - - -class Channel(virtual.Channel): - - def _new_queue(self, queue, **kwargs): - Queue.objects.get_or_create(name=queue) - - def _put(self, queue, message, **kwargs): - Queue.objects.publish(queue, dumps(message)) - - def basic_consume(self, queue, *args, **kwargs): - qinfo = self.state.bindings[queue] - exchange = qinfo[0] - if self.typeof(exchange).type == 'fanout': - return - super(Channel, self).basic_consume(queue, *args, **kwargs) - - def _get(self, queue): - m = Queue.objects.fetch(queue) - if m: - return loads(bytes_to_str(m)) - raise Empty() - - def _size(self, queue): - return Queue.objects.size(queue) - - def _purge(self, queue): - return Queue.objects.purge(queue) - - def refresh_connection(self): - from django import db - db.close_connection() - - -class Transport(virtual.Transport): - Channel = Channel - - default_port = 0 - polling_interval = POLLING_INTERVAL - channel_errors = ( - virtual.Transport.channel_errors + ( - errors.ObjectDoesNotExist, errors.MultipleObjectsReturned) - ) - driver_type = 'sql' - driver_name = 'django' - - def driver_version(self): - import django - return '.'.join(map(str, django.VERSION)) diff --git a/awx/lib/site-packages/kombu/transport/django/management/__init__.py b/awx/lib/site-packages/kombu/transport/django/management/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/kombu/transport/django/management/commands/__init__.py b/awx/lib/site-packages/kombu/transport/django/management/commands/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/kombu/transport/django/management/commands/clean_kombu_messages.py b/awx/lib/site-packages/kombu/transport/django/management/commands/clean_kombu_messages.py deleted file mode 100644 index c82ba9f7d5..0000000000 --- a/awx/lib/site-packages/kombu/transport/django/management/commands/clean_kombu_messages.py +++ /dev/null @@ -1,22 +0,0 @@ -from __future__ import absolute_import - -from django.core.management.base import BaseCommand - - -def pluralize(desc, value): - if value > 1: - return desc + 's' - return desc - - -class Command(BaseCommand): - requires_model_validation = True - - def handle(self, *args, **options): - from kombu.transport.django.models import Message - - count = Message.objects.filter(visible=False).count() - - print('Removing {0} invisible {1} from database... '.format( - count, pluralize('message', count))) - Message.objects.cleanup() diff --git a/awx/lib/site-packages/kombu/transport/django/managers.py b/awx/lib/site-packages/kombu/transport/django/managers.py deleted file mode 100644 index 6b3f378857..0000000000 --- a/awx/lib/site-packages/kombu/transport/django/managers.py +++ /dev/null @@ -1,86 +0,0 @@ -from __future__ import absolute_import - -from django.db import transaction, connection, models -try: - from django.db import connections, router -except ImportError: # pre-Django 1.2 - connections = router = None # noqa - - -class QueueManager(models.Manager): - - def publish(self, queue_name, payload): - queue, created = self.get_or_create(name=queue_name) - queue.messages.create(payload=payload) - - def fetch(self, queue_name): - try: - queue = self.get(name=queue_name) - except self.model.DoesNotExist: - return - - return queue.messages.pop() - - def size(self, queue_name): - return self.get(name=queue_name).messages.count() - - def purge(self, queue_name): - try: - queue = self.get(name=queue_name) - except self.model.DoesNotExist: - return - - messages = queue.messages.all() - count = messages.count() - messages.delete() - return count - - -def select_for_update(qs): - try: - return qs.select_for_update() - except AttributeError: - return qs - - -class MessageManager(models.Manager): - _messages_received = [0] - cleanup_every = 10 - - @transaction.commit_manually - def pop(self): - try: - resultset = select_for_update( - self.filter(visible=True).order_by('sent_at', 'id') - ) - result = resultset[0:1].get() - result.visible = False - result.save() - recv = self.__class__._messages_received - recv[0] += 1 - if not recv[0] % self.cleanup_every: - self.cleanup() - transaction.commit() - return result.payload - except self.model.DoesNotExist: - transaction.commit() - except: - transaction.rollback() - - def cleanup(self): - cursor = self.connection_for_write().cursor() - try: - cursor.execute( - 'DELETE FROM %s WHERE visible=%%s' % ( - self.model._meta.db_table, ), - (False, ) - ) - except: - transaction.rollback_unless_managed() - else: - transaction.commit_unless_managed() - - def connection_for_write(self): - if connections: - return connections[router.db_for_write(self.model)] - return connection diff --git a/awx/lib/site-packages/kombu/transport/django/migrations/0001_initial.py b/awx/lib/site-packages/kombu/transport/django/migrations/0001_initial.py deleted file mode 100644 index ea1edb0e7d..0000000000 --- a/awx/lib/site-packages/kombu/transport/django/migrations/0001_initial.py +++ /dev/null @@ -1,57 +0,0 @@ -# encoding: utf-8 -from __future__ import absolute_import - -# flake8: noqa -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Adding model 'Queue' - db.create_table('djkombu_queue', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=200)), - )) - db.send_create_signal('django', ['Queue']) - - # Adding model 'Message' - db.create_table('djkombu_message', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('visible', self.gf('django.db.models.fields.BooleanField')(default=True, db_index=True)), - ('sent_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, null=True, db_index=True, blank=True)), - ('payload', self.gf('django.db.models.fields.TextField')()), - ('queue', self.gf('django.db.models.fields.related.ForeignKey')(related_name='messages', to=orm['django.Queue'])), - )) - db.send_create_signal('django', ['Message']) - - - def backwards(self, orm): - - # Deleting model 'Queue' - db.delete_table('djkombu_queue') - - # Deleting model 'Message' - db.delete_table('djkombu_message') - - - models = { - 'django.message': { - 'Meta': {'object_name': 'Message', 'db_table': "'djkombu_message'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'payload': ('django.db.models.fields.TextField', [], {}), - 'queue': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django.Queue']"}), - 'sent_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), - 'visible': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}) - }, - 'django.queue': { - 'Meta': {'object_name': 'Queue', 'db_table': "'djkombu_queue'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}) - } - } - - complete_apps = ['django'] diff --git a/awx/lib/site-packages/kombu/transport/django/migrations/__init__.py b/awx/lib/site-packages/kombu/transport/django/migrations/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/kombu/transport/django/models.py b/awx/lib/site-packages/kombu/transport/django/models.py deleted file mode 100644 index df6a462d20..0000000000 --- a/awx/lib/site-packages/kombu/transport/django/models.py +++ /dev/null @@ -1,32 +0,0 @@ -from __future__ import absolute_import - -from django.db import models -from django.utils.translation import ugettext_lazy as _ - -from .managers import QueueManager, MessageManager - - -class Queue(models.Model): - name = models.CharField(_('name'), max_length=200, unique=True) - - objects = QueueManager() - - class Meta: - db_table = 'djkombu_queue' - verbose_name = _('queue') - verbose_name_plural = _('queues') - - -class Message(models.Model): - visible = models.BooleanField(default=True, db_index=True) - sent_at = models.DateTimeField(null=True, blank=True, db_index=True, - auto_now_add=True) - payload = models.TextField(_('payload'), null=False) - queue = models.ForeignKey(Queue, related_name='messages') - - objects = MessageManager() - - class Meta: - db_table = 'djkombu_message' - verbose_name = _('message') - verbose_name_plural = _('messages') diff --git a/awx/lib/site-packages/kombu/transport/filesystem.py b/awx/lib/site-packages/kombu/transport/filesystem.py deleted file mode 100644 index c83dcdc3ab..0000000000 --- a/awx/lib/site-packages/kombu/transport/filesystem.py +++ /dev/null @@ -1,193 +0,0 @@ -""" -kombu.transport.filesystem -========================== - -Transport using the file system as the message store. - -""" -from __future__ import absolute_import - -from anyjson import loads, dumps - -import os -import shutil -import uuid -import tempfile - -from . import virtual -from kombu.exceptions import ChannelError -from kombu.five import Empty, monotonic -from kombu.utils import cached_property -from kombu.utils.encoding import bytes_to_str, str_to_bytes - -VERSION = (1, 0, 0) -__version__ = '.'.join(map(str, VERSION)) - -# needs win32all to work on Windows -if os.name == 'nt': - - import win32con - import win32file - import pywintypes - - LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK - # 0 is the default - LOCK_SH = 0 # noqa - LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY # noqa - __overlapped = pywintypes.OVERLAPPED() - - def lock(file, flags): - hfile = win32file._get_osfhandle(file.fileno()) - win32file.LockFileEx(hfile, flags, 0, 0xffff0000, __overlapped) - - def unlock(file): - hfile = win32file._get_osfhandle(file.fileno()) - win32file.UnlockFileEx(hfile, 0, 0xffff0000, __overlapped) - -elif os.name == 'posix': - - import fcntl - from fcntl import LOCK_EX, LOCK_SH, LOCK_NB # noqa - - def lock(file, flags): # noqa - fcntl.flock(file.fileno(), flags) - - def unlock(file): # noqa - fcntl.flock(file.fileno(), fcntl.LOCK_UN) -else: - raise RuntimeError( - 'Filesystem plugin only defined for NT and POSIX platforms') - - -class Channel(virtual.Channel): - - def _put(self, queue, payload, **kwargs): - """Put `message` onto `queue`.""" - - filename = '%s_%s.%s.msg' % (int(round(monotonic() * 1000)), - uuid.uuid4(), queue) - filename = os.path.join(self.data_folder_out, filename) - - try: - f = open(filename, 'wb') - lock(f, LOCK_EX) - f.write(str_to_bytes(dumps(payload))) - except (IOError, OSError): - raise ChannelError( - 'Cannot add file {0!r} to directory'.format(filename)) - finally: - unlock(f) - f.close() - - def _get(self, queue): - """Get next message from `queue`.""" - - queue_find = '.' + queue + '.msg' - folder = os.listdir(self.data_folder_in) - folder = sorted(folder) - while len(folder) > 0: - filename = folder.pop(0) - - # only handle message for the requested queue - if filename.find(queue_find) < 0: - continue - - if self.store_processed: - processed_folder = self.processed_folder - else: - processed_folder = tempfile.gettempdir() - - try: - # move the file to the tmp/processed folder - shutil.move(os.path.join(self.data_folder_in, filename), - processed_folder) - except IOError: - pass # file could be locked, or removed in meantime so ignore - - filename = os.path.join(processed_folder, filename) - try: - f = open(filename, 'rb') - payload = f.read() - f.close() - if not self.store_processed: - os.remove(filename) - except (IOError, OSError): - raise ChannelError( - 'Cannot read file {0!r} from queue.'.format(filename)) - - return loads(bytes_to_str(payload)) - - raise Empty() - - def _purge(self, queue): - """Remove all messages from `queue`.""" - count = 0 - queue_find = '.' + queue + '.msg' - - folder = os.listdir(self.data_folder_in) - while len(folder) > 0: - filename = folder.pop() - try: - # only purge messages for the requested queue - if filename.find(queue_find) < 0: - continue - - filename = os.path.join(self.data_folder_in, filename) - os.remove(filename) - - count += 1 - - except OSError: - # we simply ignore its existence, as it was probably - # processed by another worker - pass - - return count - - def _size(self, queue): - """Return the number of messages in `queue` as an :class:`int`.""" - count = 0 - - queue_find = '.{0}.msg'.format(queue) - folder = os.listdir(self.data_folder_in) - while len(folder) > 0: - filename = folder.pop() - - # only handle message for the requested queue - if filename.find(queue_find) < 0: - continue - - count += 1 - - return count - - @property - def transport_options(self): - return self.connection.client.transport_options - - @cached_property - def data_folder_in(self): - return self.transport_options.get('data_folder_in', 'data_in') - - @cached_property - def data_folder_out(self): - return self.transport_options.get('data_folder_out', 'data_out') - - @cached_property - def store_processed(self): - return self.transport_options.get('store_processed', False) - - @cached_property - def processed_folder(self): - return self.transport_options.get('processed_folder', 'processed') - - -class Transport(virtual.Transport): - Channel = Channel - - default_port = 0 - driver_type = 'filesystem' - driver_name = 'filesystem' - - def driver_version(self): - return 'N/A' diff --git a/awx/lib/site-packages/kombu/transport/librabbitmq.py b/awx/lib/site-packages/kombu/transport/librabbitmq.py deleted file mode 100644 index 286bd78e22..0000000000 --- a/awx/lib/site-packages/kombu/transport/librabbitmq.py +++ /dev/null @@ -1,173 +0,0 @@ -""" -kombu.transport.librabbitmq -=========================== - -`librabbitmq`_ transport. - -.. _`librabbitmq`: http://pypi.python.org/librabbitmq/ - -""" -from __future__ import absolute_import - -import os -import socket -import warnings - -try: - import librabbitmq as amqp - from librabbitmq import ChannelError, ConnectionError -except ImportError: # pragma: no cover - try: - import pylibrabbitmq as amqp # noqa - from pylibrabbitmq import ChannelError, ConnectionError # noqa - except ImportError: - raise ImportError('No module named librabbitmq') - -from kombu.five import items, values -from kombu.utils.amq_manager import get_manager -from kombu.utils.text import version_string_as_tuple - -from . import base - -W_VERSION = """ - librabbitmq version too old to detect RabbitMQ version information - so make sure you are using librabbitmq 1.5 when using rabbitmq > 3.3 -""" -DEFAULT_PORT = 5672 - -NO_SSL_ERROR = """\ -ssl not supported by librabbitmq, please use pyamqp:// or stunnel\ -""" - - -class Message(base.Message): - - def __init__(self, channel, props, info, body): - super(Message, self).__init__( - channel, - body=body, - delivery_info=info, - properties=props, - delivery_tag=info.get('delivery_tag'), - content_type=props.get('content_type'), - content_encoding=props.get('content_encoding'), - headers=props.get('headers')) - - -class Channel(amqp.Channel, base.StdChannel): - Message = Message - - def prepare_message(self, body, priority=None, - content_type=None, content_encoding=None, - headers=None, properties=None): - """Encapsulate data into a AMQP message.""" - properties = properties if properties is not None else {} - properties.update({'content_type': content_type, - 'content_encoding': content_encoding, - 'headers': headers, - 'priority': priority}) - return body, properties - - -class Connection(amqp.Connection): - Channel = Channel - Message = Message - - -class Transport(base.Transport): - Connection = Connection - - default_port = DEFAULT_PORT - connection_errors = ( - base.Transport.connection_errors + ( - ConnectionError, socket.error, IOError, OSError) - ) - channel_errors = ( - base.Transport.channel_errors + (ChannelError, ) - ) - driver_type = 'amqp' - driver_name = 'librabbitmq' - - supports_ev = True - - def __init__(self, client, **kwargs): - self.client = client - self.default_port = kwargs.get('default_port') or self.default_port - self.__reader = None - - def driver_version(self): - return amqp.__version__ - - def create_channel(self, connection): - return connection.channel() - - def drain_events(self, connection, **kwargs): - return connection.drain_events(**kwargs) - - def establish_connection(self): - """Establish connection to the AMQP broker.""" - conninfo = self.client - for name, default_value in items(self.default_connection_params): - if not getattr(conninfo, name, None): - setattr(conninfo, name, default_value) - if conninfo.ssl: - raise NotImplementedError(NO_SSL_ERROR) - opts = dict({ - 'host': conninfo.host, - 'userid': conninfo.userid, - 'password': conninfo.password, - 'virtual_host': conninfo.virtual_host, - 'login_method': conninfo.login_method, - 'insist': conninfo.insist, - 'ssl': conninfo.ssl, - 'connect_timeout': conninfo.connect_timeout, - }, **conninfo.transport_options or {}) - conn = self.Connection(**opts) - conn.client = self.client - self.client.drain_events = conn.drain_events - return conn - - def close_connection(self, connection): - """Close the AMQP broker connection.""" - self.client.drain_events = None - connection.close() - - def _collect(self, connection): - if connection is not None: - for channel in values(connection.channels): - channel.connection = None - try: - os.close(connection.fileno()) - except OSError: - pass - connection.channels.clear() - connection.callbacks.clear() - self.client.drain_events = None - self.client = None - - def verify_connection(self, connection): - return connection.connected - - def register_with_event_loop(self, connection, loop): - loop.add_reader( - connection.fileno(), self.on_readable, connection, loop, - ) - - def get_manager(self, *args, **kwargs): - return get_manager(self.client, *args, **kwargs) - - def qos_semantics_matches_spec(self, connection): - try: - props = connection.server_properties - except AttributeError: - warnings.warn(UserWarning(W_VERSION)) - else: - if props.get('product') == 'RabbitMQ': - return version_string_as_tuple(props['version']) < (3, 3) - return True - - @property - def default_connection_params(self): - return {'userid': 'guest', 'password': 'guest', - 'port': self.default_port, - 'hostname': 'localhost', 'login_method': 'AMQPLAIN'} diff --git a/awx/lib/site-packages/kombu/transport/memory.py b/awx/lib/site-packages/kombu/transport/memory.py deleted file mode 100644 index b1ba70f8d7..0000000000 --- a/awx/lib/site-packages/kombu/transport/memory.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -kombu.transport.memory -====================== - -In-memory transport. - -""" -from __future__ import absolute_import - -from kombu.five import Queue, values - -from . import virtual - - -class Channel(virtual.Channel): - queues = {} - do_restore = False - supports_fanout = True - - def _has_queue(self, queue, **kwargs): - return queue in self.queues - - def _new_queue(self, queue, **kwargs): - if queue not in self.queues: - self.queues[queue] = Queue() - - def _get(self, queue, timeout=None): - return self._queue_for(queue).get(block=False) - - def _queue_for(self, queue): - if queue not in self.queues: - self.queues[queue] = Queue() - return self.queues[queue] - - def _queue_bind(self, *args): - pass - - def _put_fanout(self, exchange, message, routing_key=None, **kwargs): - for queue in self._lookup(exchange, routing_key): - self._queue_for(queue).put(message) - - def _put(self, queue, message, **kwargs): - self._queue_for(queue).put(message) - - def _size(self, queue): - return self._queue_for(queue).qsize() - - def _delete(self, queue, *args): - self.queues.pop(queue, None) - - def _purge(self, queue): - q = self._queue_for(queue) - size = q.qsize() - q.queue.clear() - return size - - def close(self): - super(Channel, self).close() - for queue in values(self.queues): - queue.empty() - self.queues = {} - - def after_reply_message_received(self, queue): - pass - - -class Transport(virtual.Transport): - Channel = Channel - - #: memory backend state is global. - state = virtual.BrokerState() - - driver_type = 'memory' - driver_name = 'memory' - - def driver_version(self): - return 'N/A' diff --git a/awx/lib/site-packages/kombu/transport/mongodb.py b/awx/lib/site-packages/kombu/transport/mongodb.py deleted file mode 100644 index 2e1f9deed2..0000000000 --- a/awx/lib/site-packages/kombu/transport/mongodb.py +++ /dev/null @@ -1,314 +0,0 @@ -""" -kombu.transport.mongodb -======================= - -MongoDB transport. - -:copyright: (c) 2010 - 2013 by Flavio Percoco Premoli. -:license: BSD, see LICENSE for more details. - -""" -from __future__ import absolute_import - -import pymongo - -from pymongo import errors -from anyjson import loads, dumps -from pymongo import MongoClient, uri_parser - -from kombu.five import Empty -from kombu.syn import _detect_environment -from kombu.utils.encoding import bytes_to_str - -from . import virtual - -DEFAULT_HOST = '127.0.0.1' -DEFAULT_PORT = 27017 - -DEFAULT_MESSAGES_COLLECTION = 'messages' -DEFAULT_ROUTING_COLLECTION = 'messages.routing' -DEFAULT_BROADCAST_COLLECTION = 'messages.broadcast' - - -class BroadcastCursor(object): - """Cursor for broadcast queues.""" - - def __init__(self, cursor): - self._cursor = cursor - - self.purge(rewind=False) - - def get_size(self): - return self._cursor.count() - self._offset - - def close(self): - self._cursor.close() - - def purge(self, rewind=True): - if rewind: - self._cursor.rewind() - - # Fast forward the cursor past old events - self._offset = self._cursor.count() - self._cursor = self._cursor.skip(self._offset) - - def __iter__(self): - return self - - def __next__(self): - while True: - try: - msg = next(self._cursor) - except pymongo.errors.OperationFailure as exc: - # In some cases tailed cursor can become invalid - # and have to be reinitalized - if 'not valid at server' in exc.message: - self.purge() - - continue - - raise - else: - break - - self._offset += 1 - - return msg - next = __next__ - - -class Channel(virtual.Channel): - _client = None - supports_fanout = True - _fanout_queues = {} - - def __init__(self, *vargs, **kwargs): - super(Channel, self).__init__(*vargs, **kwargs) - - self._broadcast_cursors = {} - - # Evaluate connection - self._create_client() - - def _new_queue(self, queue, **kwargs): - pass - - def _get(self, queue): - if queue in self._fanout_queues: - try: - msg = next(self.get_broadcast_cursor(queue)) - except StopIteration: - msg = None - else: - msg = self.get_messages().find_and_modify( - query={'queue': queue}, - sort={'_id': pymongo.ASCENDING}, - remove=True, - ) - - if msg is None: - raise Empty() - - return loads(bytes_to_str(msg['payload'])) - - def _size(self, queue): - if queue in self._fanout_queues: - return self.get_broadcast_cursor(queue).get_size() - - return self.get_messages().find({'queue': queue}).count() - - def _put(self, queue, message, **kwargs): - self.get_messages().insert({'payload': dumps(message), - 'queue': queue}) - - def _purge(self, queue): - size = self._size(queue) - - if queue in self._fanout_queues: - self.get_broadcaset_cursor(queue).purge() - else: - self.get_messages().remove({'queue': queue}) - - return size - - def _parse_uri(self, scheme='mongodb://'): - # See mongodb uri documentation: - # http://docs.mongodb.org/manual/reference/connection-string/ - client = self.connection.client - hostname = client.hostname - - if not hostname.startswith(scheme): - hostname = scheme + hostname - - if not hostname[len(scheme):]: - hostname += DEFAULT_HOST - - if client.userid and '@' not in hostname: - head, tail = hostname.split('://') - - credentials = client.userid - if client.password: - credentials += ':' + client.password - - hostname = head + '://' + credentials + '@' + tail - - port = client.port if client.port is not None else DEFAULT_PORT - - parsed = uri_parser.parse_uri(hostname, port) - - dbname = parsed['database'] or client.virtual_host - - if dbname in ('/', None): - dbname = 'kombu_default' - - options = { - 'auto_start_request': True, - 'ssl': client.ssl, - 'connectTimeoutMS': (int(client.connect_timeout * 1000) - if client.connect_timeout else None), - } - options.update(client.transport_options) - options.update(parsed['options']) - - return hostname, dbname, options - - def _open(self, scheme='mongodb://'): - hostname, dbname, options = self._parse_uri(scheme=scheme) - - mongoconn = MongoClient( - host=hostname, ssl=options['ssl'], - auto_start_request=options['auto_start_request'], - connectTimeoutMS=options['connectTimeoutMS'], - use_greenlets=_detect_environment() != 'default', - ) - database = mongoconn[dbname] - - version = mongoconn.server_info()['version'] - if tuple(map(int, version.split('.')[:2])) < (1, 3): - raise NotImplementedError( - 'Kombu requires MongoDB version 1.3+ (server is {0})'.format( - version)) - - self._create_broadcast(database, options) - - self._client = database - - def _create_broadcast(self, database, options): - '''Create capped collection for broadcast messages.''' - if DEFAULT_BROADCAST_COLLECTION in database.collection_names(): - return - - capsize = options.get('capped_queue_size') or 100000 - database.create_collection(DEFAULT_BROADCAST_COLLECTION, - size=capsize, capped=True) - - def _ensure_indexes(self): - '''Ensure indexes on collections.''' - self.get_messages().ensure_index( - [('queue', 1), ('_id', 1)], background=True, - ) - self.get_broadcast().ensure_index([('queue', 1)]) - self.get_routing().ensure_index([('queue', 1), ('exchange', 1)]) - - # TODO Store a more complete exchange metatable in the routing collection - def get_table(self, exchange): - """Get table of bindings for ``exchange``.""" - localRoutes = frozenset(self.state.exchanges[exchange]['table']) - brokerRoutes = self.get_messages().routing.find( - {'exchange': exchange} - ) - - return localRoutes | frozenset((r['routing_key'], - r['pattern'], - r['queue']) for r in brokerRoutes) - - def _put_fanout(self, exchange, message, routing_key, **kwargs): - """Deliver fanout message.""" - self.get_broadcast().insert({'payload': dumps(message), - 'queue': exchange}) - - def _queue_bind(self, exchange, routing_key, pattern, queue): - if self.typeof(exchange).type == 'fanout': - self.create_broadcast_cursor(exchange, routing_key, pattern, queue) - self._fanout_queues[queue] = exchange - - meta = {'exchange': exchange, - 'queue': queue, - 'routing_key': routing_key, - 'pattern': pattern} - self.get_routing().update(meta, meta, upsert=True) - - def queue_delete(self, queue, **kwargs): - self.get_routing().remove({'queue': queue}) - - super(Channel, self).queue_delete(queue, **kwargs) - - if queue in self._fanout_queues: - try: - cursor = self._broadcast_cursors.pop(queue) - except KeyError: - pass - else: - cursor.close() - - self._fanout_queues.pop(queue) - - def _create_client(self): - self._open() - self._ensure_indexes() - - @property - def client(self): - if self._client is None: - self._create_client() - return self._client - - def get_messages(self): - return self.client[DEFAULT_MESSAGES_COLLECTION] - - def get_routing(self): - return self.client[DEFAULT_ROUTING_COLLECTION] - - def get_broadcast(self): - return self.client[DEFAULT_BROADCAST_COLLECTION] - - def get_broadcast_cursor(self, queue): - try: - return self._broadcast_cursors[queue] - except KeyError: - # Cursor may be absent when Channel created more than once. - # _fanout_queues is a class-level mutable attribute so it's - # shared over all Channel instances. - return self.create_broadcast_cursor( - self._fanout_queues[queue], None, None, queue, - ) - - def create_broadcast_cursor(self, exchange, routing_key, pattern, queue): - cursor = self.get_broadcast().find( - query={'queue': exchange}, - sort=[('$natural', 1)], - tailable=True, - ) - ret = self._broadcast_cursors[queue] = BroadcastCursor(cursor) - return ret - - -class Transport(virtual.Transport): - Channel = Channel - - can_parse_url = True - polling_interval = 1 - default_port = DEFAULT_PORT - connection_errors = ( - virtual.Transport.connection_errors + (errors.ConnectionFailure, ) - ) - channel_errors = ( - virtual.Transport.channel_errors + ( - errors.ConnectionFailure, - errors.OperationFailure) - ) - driver_type = 'mongodb' - driver_name = 'pymongo' - - def driver_version(self): - return pymongo.version diff --git a/awx/lib/site-packages/kombu/transport/pyamqp.py b/awx/lib/site-packages/kombu/transport/pyamqp.py deleted file mode 100644 index 0184430522..0000000000 --- a/awx/lib/site-packages/kombu/transport/pyamqp.py +++ /dev/null @@ -1,146 +0,0 @@ -""" -kombu.transport.pyamqp -====================== - -pure python amqp transport. - -""" -from __future__ import absolute_import - -import amqp - -from kombu.five import items -from kombu.utils.amq_manager import get_manager -from kombu.utils.text import version_string_as_tuple - -from . import base - -DEFAULT_PORT = 5672 - - -class Message(base.Message): - - def __init__(self, channel, msg, **kwargs): - props = msg.properties - super(Message, self).__init__( - channel, - body=msg.body, - delivery_tag=msg.delivery_tag, - content_type=props.get('content_type'), - content_encoding=props.get('content_encoding'), - delivery_info=msg.delivery_info, - properties=msg.properties, - headers=props.get('application_headers') or {}, - **kwargs) - - -class Channel(amqp.Channel, base.StdChannel): - Message = Message - - def prepare_message(self, body, priority=None, - content_type=None, content_encoding=None, - headers=None, properties=None, _Message=amqp.Message): - """Prepares message so that it can be sent using this transport.""" - return _Message( - body, - priority=priority, - content_type=content_type, - content_encoding=content_encoding, - application_headers=headers, - **properties or {} - ) - - def message_to_python(self, raw_message): - """Convert encoded message body back to a Python value.""" - return self.Message(self, raw_message) - - -class Connection(amqp.Connection): - Channel = Channel - - -class Transport(base.Transport): - Connection = Connection - - default_port = DEFAULT_PORT - - # it's very annoying that pyamqp sometimes raises AttributeError - # if the connection is lost, but nothing we can do about that here. - connection_errors = amqp.Connection.connection_errors - channel_errors = amqp.Connection.channel_errors - recoverable_connection_errors = \ - amqp.Connection.recoverable_connection_errors - recoverable_channel_errors = amqp.Connection.recoverable_channel_errors - - driver_name = 'py-amqp' - driver_type = 'amqp' - supports_heartbeats = True - supports_ev = True - - def __init__(self, client, default_port=None, **kwargs): - self.client = client - self.default_port = default_port or self.default_port - - def driver_version(self): - return amqp.__version__ - - def create_channel(self, connection): - return connection.channel() - - def drain_events(self, connection, **kwargs): - return connection.drain_events(**kwargs) - - def establish_connection(self): - """Establish connection to the AMQP broker.""" - conninfo = self.client - for name, default_value in items(self.default_connection_params): - if not getattr(conninfo, name, None): - setattr(conninfo, name, default_value) - if conninfo.hostname == 'localhost': - conninfo.hostname = '127.0.0.1' - opts = dict({ - 'host': conninfo.host, - 'userid': conninfo.userid, - 'password': conninfo.password, - 'login_method': conninfo.login_method, - 'virtual_host': conninfo.virtual_host, - 'insist': conninfo.insist, - 'ssl': conninfo.ssl, - 'connect_timeout': conninfo.connect_timeout, - 'heartbeat': conninfo.heartbeat, - }, **conninfo.transport_options or {}) - conn = self.Connection(**opts) - conn.client = self.client - return conn - - def verify_connection(self, connection): - return connection.connected - - def close_connection(self, connection): - """Close the AMQP broker connection.""" - connection.client = None - connection.close() - - def get_heartbeat_interval(self, connection): - return connection.heartbeat - - def register_with_event_loop(self, connection, loop): - loop.add_reader(connection.sock, self.on_readable, connection, loop) - - def heartbeat_check(self, connection, rate=2): - return connection.heartbeat_tick(rate=rate) - - def qos_semantics_matches_spec(self, connection): - props = connection.server_properties - if props.get('product') == 'RabbitMQ': - return version_string_as_tuple(props['version']) < (3, 3) - return True - - @property - def default_connection_params(self): - return {'userid': 'guest', 'password': 'guest', - 'port': self.default_port, - 'hostname': 'localhost', 'login_method': 'AMQPLAIN'} - - def get_manager(self, *args, **kwargs): - return get_manager(self.client, *args, **kwargs) diff --git a/awx/lib/site-packages/kombu/transport/pyro.py b/awx/lib/site-packages/kombu/transport/pyro.py deleted file mode 100644 index b87a5fbb9f..0000000000 --- a/awx/lib/site-packages/kombu/transport/pyro.py +++ /dev/null @@ -1,99 +0,0 @@ -""" -kombu.transport.pyro -====================== - -Pyro transport. - -Requires the :mod:`Pyro4` library to be installed. - -""" -from __future__ import absolute_import - -import sys - -from kombu.five import reraise -from kombu.utils import cached_property - -from . import virtual - -try: - import Pyro4 as pyro - from Pyro4.errors import NamingError -except ImportError: # pragma: no cover - pyro = NamingError = None # noqa - -DEFAULT_PORT = 9090 -E_LOOKUP = """\ -Unable to locate pyro nameserver {0.virtual_host} on host {0.hostname}\ -""" - - -class Channel(virtual.Channel): - - def queues(self): - return self.shared_queues.get_queue_names() - - def _new_queue(self, queue, **kwargs): - if queue not in self.queues(): - self.shared_queues.new_queue(queue) - - def _get(self, queue, timeout=None): - queue = self._queue_for(queue) - msg = self.shared_queues._get(queue) - return msg - - def _queue_for(self, queue): - if queue not in self.queues(): - self.shared_queues.new_queue(queue) - return queue - - def _put(self, queue, message, **kwargs): - queue = self._queue_for(queue) - self.shared_queues._put(queue, message) - - def _size(self, queue): - return self.shared_queues._size(queue) - - def _delete(self, queue, *args): - self.shared_queues._delete(queue) - - def _purge(self, queue): - return self.shared_queues._purge(queue) - - def after_reply_message_received(self, queue): - pass - - @cached_property - def shared_queues(self): - return self.connection.shared_queues - - -class Transport(virtual.Transport): - Channel = Channel - - #: memory backend state is global. - state = virtual.BrokerState() - - default_port = DEFAULT_PORT - - driver_type = driver_name = 'pyro' - - def _open(self): - conninfo = self.client - pyro.config.HMAC_KEY = conninfo.virtual_host - try: - nameserver = pyro.locateNS(host=conninfo.hostname, - port=self.default_port) - # name of registered pyro object - uri = nameserver.lookup(conninfo.virtual_host) - return pyro.Proxy(uri) - except NamingError: - reraise(NamingError, NamingError(E_LOOKUP.format(conninfo)), - sys.exc_info()[2]) - - def driver_version(self): - return pyro.__version__ - - @cached_property - def shared_queues(self): - return self._open() diff --git a/awx/lib/site-packages/kombu/transport/redis.py b/awx/lib/site-packages/kombu/transport/redis.py deleted file mode 100644 index 683f396d37..0000000000 --- a/awx/lib/site-packages/kombu/transport/redis.py +++ /dev/null @@ -1,957 +0,0 @@ -""" -kombu.transport.redis -===================== - -Redis transport. - -""" -from __future__ import absolute_import - -import numbers -import socket - -from bisect import bisect -from collections import namedtuple -from contextlib import contextmanager -from time import time - -from amqp import promise -from anyjson import loads, dumps - -from kombu.exceptions import InconsistencyError, VersionMismatch -from kombu.five import Empty, values, string_t -from kombu.log import get_logger -from kombu.utils import cached_property, uuid -from kombu.utils.eventio import poll, READ, ERR -from kombu.utils.encoding import bytes_to_str -from kombu.utils.url import _parse_url - -NO_ROUTE_ERROR = """ -Cannot route message for exchange {0!r}: Table empty or key no longer exists. -Probably the key ({1!r}) has been removed from the Redis database. -""" - -try: - from billiard.util import register_after_fork -except ImportError: # pragma: no cover - try: - from multiprocessing.util import register_after_fork # noqa - except ImportError: - def register_after_fork(*args, **kwargs): # noqa - pass - -try: - import redis -except ImportError: # pragma: no cover - redis = None # noqa - -from . import virtual - -logger = get_logger('kombu.transport.redis') -crit, warn = logger.critical, logger.warn - -DEFAULT_PORT = 6379 -DEFAULT_DB = 0 - -PRIORITY_STEPS = [0, 3, 6, 9] - -error_classes_t = namedtuple('error_classes_t', ( - 'connection_errors', 'channel_errors', -)) - -# This implementation may seem overly complex, but I assure you there is -# a good reason for doing it this way. -# -# Consuming from several connections enables us to emulate channels, -# which means we can have different service guarantees for individual -# channels. -# -# So we need to consume messages from multiple connections simultaneously, -# and using epoll means we don't have to do so using multiple threads. -# -# Also it means we can easily use PUBLISH/SUBSCRIBE to do fanout -# exchanges (broadcast), as an alternative to pushing messages to fanout-bound -# queues manually. - - -def get_redis_error_classes(): - from redis import exceptions - # This exception suddenly changed name between redis-py versions - if hasattr(exceptions, 'InvalidData'): - DataError = exceptions.InvalidData - else: - DataError = exceptions.DataError - return error_classes_t( - (virtual.Transport.connection_errors + ( - InconsistencyError, - socket.error, - IOError, - OSError, - exceptions.ConnectionError, - exceptions.AuthenticationError)), - (virtual.Transport.channel_errors + ( - DataError, - exceptions.InvalidResponse, - exceptions.ResponseError)), - ) - - -class MutexHeld(Exception): - pass - - -@contextmanager -def Mutex(client, name, expire): - lock_id = uuid() - i_won = client.setnx(name, lock_id) - try: - if i_won: - client.expire(name, expire) - yield - else: - if not client.ttl(name): - client.expire(name, expire) - raise MutexHeld() - finally: - if i_won: - pipe = client.pipeline(True) - try: - pipe.watch(name) - if pipe.get(name) == lock_id: - pipe.multi() - pipe.delete(name) - pipe.execute() - pipe.unwatch() - except redis.WatchError: - pass - - -class QoS(virtual.QoS): - restore_at_shutdown = True - - def __init__(self, *args, **kwargs): - super(QoS, self).__init__(*args, **kwargs) - self._vrestore_count = 0 - - def append(self, message, delivery_tag): - delivery = message.delivery_info - EX, RK = delivery['exchange'], delivery['routing_key'] - with self.pipe_or_acquire() as pipe: - pipe.zadd(self.unacked_index_key, delivery_tag, time()) \ - .hset(self.unacked_key, delivery_tag, - dumps([message._raw, EX, RK])) \ - .execute() - super(QoS, self).append(message, delivery_tag) - - def restore_unacked(self): - for tag in self._delivered: - self.restore_by_tag(tag) - self._delivered.clear() - - def ack(self, delivery_tag): - self._remove_from_indices(delivery_tag).execute() - super(QoS, self).ack(delivery_tag) - - def reject(self, delivery_tag, requeue=False): - if requeue: - self.restore_by_tag(delivery_tag, leftmost=True) - self.ack(delivery_tag) - - @contextmanager - def pipe_or_acquire(self, pipe=None): - if pipe: - yield pipe - else: - with self.channel.conn_or_acquire() as client: - yield client.pipeline() - - def _remove_from_indices(self, delivery_tag, pipe=None): - with self.pipe_or_acquire(pipe) as pipe: - return pipe.zrem(self.unacked_index_key, delivery_tag) \ - .hdel(self.unacked_key, delivery_tag) - - def restore_visible(self, start=0, num=10, interval=10): - self._vrestore_count += 1 - if (self._vrestore_count - 1) % interval: - return - with self.channel.conn_or_acquire() as client: - ceil = time() - self.visibility_timeout - try: - with Mutex(client, self.unacked_mutex_key, - self.unacked_mutex_expire): - visible = client.zrevrangebyscore( - self.unacked_index_key, ceil, 0, - start=num and start, num=num, withscores=True) - for tag, score in visible or []: - self.restore_by_tag(tag, client) - except MutexHeld: - pass - - def restore_by_tag(self, tag, client=None, leftmost=False): - with self.channel.conn_or_acquire(client) as client: - p, _, _ = self._remove_from_indices( - tag, client.pipeline().hget(self.unacked_key, tag)).execute() - if p: - M, EX, RK = loads(bytes_to_str(p)) # json is unicode - self.channel._do_restore_message(M, EX, RK, client, leftmost) - - @cached_property - def unacked_key(self): - return self.channel.unacked_key - - @cached_property - def unacked_index_key(self): - return self.channel.unacked_index_key - - @cached_property - def unacked_mutex_key(self): - return self.channel.unacked_mutex_key - - @cached_property - def unacked_mutex_expire(self): - return self.channel.unacked_mutex_expire - - @cached_property - def visibility_timeout(self): - return self.channel.visibility_timeout - - -class MultiChannelPoller(object): - eventflags = READ | ERR - - #: Set by :meth:`get` while reading from the socket. - _in_protected_read = False - - #: Set of one-shot callbacks to call after reading from socket. - after_read = None - - def __init__(self): - # active channels - self._channels = set() - # file descriptor -> channel map. - self._fd_to_chan = {} - # channel -> socket map - self._chan_to_sock = {} - # poll implementation (epoll/kqueue/select) - self.poller = poll() - # one-shot callbacks called after reading from socket. - self.after_read = set() - - def close(self): - for fd in values(self._chan_to_sock): - try: - self.poller.unregister(fd) - except (KeyError, ValueError): - pass - self._channels.clear() - self._fd_to_chan.clear() - self._chan_to_sock.clear() - - def add(self, channel): - self._channels.add(channel) - - def discard(self, channel): - self._channels.discard(channel) - - def _on_connection_disconnect(self, connection): - sock = getattr(connection, '_sock', None) - if sock is not None: - self.poller.unregister(sock) - - def _register(self, channel, client, type): - if (channel, client, type) in self._chan_to_sock: - self._unregister(channel, client, type) - if client.connection._sock is None: # not connected yet. - client.connection.connect() - sock = client.connection._sock - self._fd_to_chan[sock.fileno()] = (channel, type) - self._chan_to_sock[(channel, client, type)] = sock - self.poller.register(sock, self.eventflags) - - def _unregister(self, channel, client, type): - self.poller.unregister(self._chan_to_sock[(channel, client, type)]) - - def _register_BRPOP(self, channel): - """enable BRPOP mode for channel.""" - ident = channel, channel.client, 'BRPOP' - if channel.client.connection._sock is None or \ - ident not in self._chan_to_sock: - channel._in_poll = False - self._register(*ident) - - if not channel._in_poll: # send BRPOP - channel._brpop_start() - - def _register_LISTEN(self, channel): - """enable LISTEN mode for channel.""" - if channel.subclient.connection._sock is None: - channel._in_listen = False - self._register(channel, channel.subclient, 'LISTEN') - if not channel._in_listen: - channel._subscribe() # send SUBSCRIBE - - def on_poll_start(self): - for channel in self._channels: - if channel.active_queues: # BRPOP mode? - if channel.qos.can_consume(): - self._register_BRPOP(channel) - if channel.active_fanout_queues: # LISTEN mode? - self._register_LISTEN(channel) - - def on_poll_init(self, poller): - self.poller = poller - for channel in self._channels: - return channel.qos.restore_visible( - num=channel.unacked_restore_limit, - ) - - def maybe_restore_messages(self): - for channel in self._channels: - if channel.active_queues: - # only need to do this once, as they are not local to channel. - return channel.qos.restore_visible( - num=channel.unacked_restore_limit, - ) - - def on_readable(self, fileno): - chan, type = self._fd_to_chan[fileno] - if chan.qos.can_consume(): - return chan.handlers[type]() - - def handle_event(self, fileno, event): - if event & READ: - return self.on_readable(fileno), self - elif event & ERR: - chan, type = self._fd_to_chan[fileno] - chan._poll_error(type) - - def get(self, timeout=None): - self._in_protected_read = True - try: - for channel in self._channels: - if channel.active_queues: # BRPOP mode? - if channel.qos.can_consume(): - self._register_BRPOP(channel) - if channel.active_fanout_queues: # LISTEN mode? - self._register_LISTEN(channel) - - events = self.poller.poll(timeout) - for fileno, event in events or []: - ret = self.handle_event(fileno, event) - if ret: - return ret - - # - no new data, so try to restore messages. - # - reset active redis commands. - self.maybe_restore_messages() - - raise Empty() - finally: - self._in_protected_read = False - while self.after_read: - try: - fun = self.after_read.pop() - except KeyError: - break - else: - fun() - - @property - def fds(self): - return self._fd_to_chan - - -class Channel(virtual.Channel): - QoS = QoS - - _client = None - _subclient = None - supports_fanout = True - keyprefix_queue = '_kombu.binding.%s' - keyprefix_fanout = '/{db}.' - sep = '\x06\x16' - _in_poll = False - _in_listen = False - _fanout_queues = {} - ack_emulation = True - unacked_key = 'unacked' - unacked_index_key = 'unacked_index' - unacked_mutex_key = 'unacked_mutex' - unacked_mutex_expire = 300 # 5 minutes - unacked_restore_limit = None - visibility_timeout = 3600 # 1 hour - priority_steps = PRIORITY_STEPS - socket_timeout = None - max_connections = 10 - #: Transport option to enable disable fanout keyprefix. - #: Should be enabled by default, but that is not - #: backwards compatible. Can also be string, in which - #: case it changes the default prefix ('/{db}.') into to something - #: else. The prefix must include a leading slash and a trailing dot. - fanout_prefix = False - - #: If enabled the fanout exchange will support patterns in routing - #: and binding keys (like a topic exchange but using PUB/SUB). - #: This will be enabled by default in a future version. - fanout_patterns = False - _pool = None - - from_transport_options = ( - virtual.Channel.from_transport_options + - ('ack_emulation', - 'unacked_key', - 'unacked_index_key', - 'unacked_mutex_key', - 'unacked_mutex_expire', - 'visibility_timeout', - 'unacked_restore_limit', - 'fanout_prefix', - 'fanout_patterns', - 'socket_timeout', - 'max_connections', - 'priority_steps') # <-- do not add comma here! - ) - - def __init__(self, *args, **kwargs): - super_ = super(Channel, self) - super_.__init__(*args, **kwargs) - - if not self.ack_emulation: # disable visibility timeout - self.QoS = virtual.QoS - - self._queue_cycle = [] - self.Client = self._get_client() - self.ResponseError = self._get_response_error() - self.active_fanout_queues = set() - self.auto_delete_queues = set() - self._fanout_to_queue = {} - self.handlers = {'BRPOP': self._brpop_read, 'LISTEN': self._receive} - - if self.fanout_prefix: - if isinstance(self.fanout_prefix, string_t): - self.keyprefix_fanout = self.fanout_prefix - else: - # previous versions did not set a fanout, so cannot enable - # by default. - self.keyprefix_fanout = '' - - # Evaluate connection. - try: - self.client.info() - except Exception: - if self._pool: - self._pool.disconnect() - raise - - self.connection.cycle.add(self) # add to channel poller. - # copy errors, in case channel closed but threads still - # are still waiting for data. - self.connection_errors = self.connection.connection_errors - - register_after_fork(self, self._after_fork) - - def _after_fork(self): - if self._pool is not None: - self._pool.disconnect() - - def _on_connection_disconnect(self, connection): - if self.connection and self.connection.cycle: - self.connection.cycle._on_connection_disconnect(connection) - - def _do_restore_message(self, payload, exchange, routing_key, - client=None, leftmost=False): - with self.conn_or_acquire(client) as client: - try: - try: - payload['headers']['redelivered'] = True - except KeyError: - pass - for queue in self._lookup(exchange, routing_key): - (client.lpush if leftmost else client.rpush)( - queue, dumps(payload), - ) - except Exception: - crit('Could not restore message: %r', payload, exc_info=True) - - def _restore(self, message, leftmost=False): - if not self.ack_emulation: - return super(Channel, self)._restore(message) - tag = message.delivery_tag - with self.conn_or_acquire() as client: - P, _ = client.pipeline() \ - .hget(self.unacked_key, tag) \ - .hdel(self.unacked_key, tag) \ - .execute() - if P: - M, EX, RK = loads(bytes_to_str(P)) # json is unicode - self._do_restore_message(M, EX, RK, client, leftmost) - - def _restore_at_beginning(self, message): - return self._restore(message, leftmost=True) - - def basic_consume(self, queue, *args, **kwargs): - if queue in self._fanout_queues: - exchange, _ = self._fanout_queues[queue] - self.active_fanout_queues.add(queue) - self._fanout_to_queue[exchange] = queue - ret = super(Channel, self).basic_consume(queue, *args, **kwargs) - self._update_cycle() - return ret - - def basic_cancel(self, consumer_tag): - # If we are busy reading messages we may experience - # a race condition where a message is consumed after - # cancelling, so we must delay this operation until reading - # is complete (Issue celery/celery#1773). - connection = self.connection - if connection: - if connection.cycle._in_protected_read: - return connection.cycle.after_read.add( - promise(self._basic_cancel, (consumer_tag, )), - ) - return self._basic_cancel(consumer_tag) - - def _basic_cancel(self, consumer_tag): - try: - queue = self._tag_to_queue[consumer_tag] - except KeyError: - return - try: - self.active_fanout_queues.remove(queue) - except KeyError: - pass - else: - self._unsubscribe_from(queue) - try: - exchange, _ = self._fanout_queues[queue] - self._fanout_to_queue.pop(exchange) - except KeyError: - pass - ret = super(Channel, self).basic_cancel(consumer_tag) - self._update_cycle() - return ret - - def _get_publish_topic(self, exchange, routing_key): - if routing_key and self.fanout_patterns: - return ''.join([self.keyprefix_fanout, exchange, '/', routing_key]) - return ''.join([self.keyprefix_fanout, exchange]) - - def _get_subscribe_topic(self, queue): - exchange, routing_key = self._fanout_queues[queue] - return self._get_publish_topic(exchange, routing_key) - - def _subscribe(self): - keys = [self._get_subscribe_topic(queue) - for queue in self.active_fanout_queues] - if not keys: - return - c = self.subclient - if c.connection._sock is None: - c.connection.connect() - self._in_listen = True - c.psubscribe(keys) - - def _unsubscribe_from(self, queue): - topic = self._get_subscribe_topic(queue) - c = self.subclient - should_disconnect = False - if c.connection._sock is None: - c.connection.connect() - should_disconnect = True - try: - c.unsubscribe([topic]) - finally: - if should_disconnect and c.connection: - c.connection.disconnect() - - def _handle_message(self, client, r): - if bytes_to_str(r[0]) == 'unsubscribe' and r[2] == 0: - client.subscribed = False - elif bytes_to_str(r[0]) == 'pmessage': - return {'type': r[0], 'pattern': r[1], - 'channel': r[2], 'data': r[3]} - else: - return {'type': r[0], 'pattern': None, - 'channel': r[1], 'data': r[2]} - - def _receive(self): - c = self.subclient - response = None - try: - response = c.parse_response() - except self.connection_errors: - self._in_listen = False - raise Empty() - if response is not None: - payload = self._handle_message(c, response) - if bytes_to_str(payload['type']).endswith('message'): - channel = bytes_to_str(payload['channel']) - if payload['data']: - if channel[0] == '/': - _, _, channel = channel.partition('.') - try: - message = loads(bytes_to_str(payload['data'])) - except (TypeError, ValueError): - warn('Cannot process event on channel %r: %s', - channel, repr(payload)[:4096], exc_info=1) - raise Empty() - exchange = channel.split('/', 1)[0] - return message, self._fanout_to_queue[exchange] - raise Empty() - - def _brpop_start(self, timeout=1): - queues = self._consume_cycle() - if not queues: - return - keys = [self._q_for_pri(queue, pri) for pri in PRIORITY_STEPS - for queue in queues] + [timeout or 0] - self._in_poll = True - self.client.connection.send_command('BRPOP', *keys) - - def _brpop_read(self, **options): - try: - try: - dest__item = self.client.parse_response(self.client.connection, - 'BRPOP', - **options) - except self.connection_errors: - # if there's a ConnectionError, disconnect so the next - # iteration will reconnect automatically. - self.client.connection.disconnect() - raise Empty() - if dest__item: - dest, item = dest__item - dest = bytes_to_str(dest).rsplit(self.sep, 1)[0] - self._rotate_cycle(dest) - return loads(bytes_to_str(item)), dest - else: - raise Empty() - finally: - self._in_poll = False - - def _poll_error(self, type, **options): - if type == 'LISTEN': - self.subclient.parse_response() - else: - self.client.parse_response(self.client.connection, type) - - def _get(self, queue): - with self.conn_or_acquire() as client: - for pri in PRIORITY_STEPS: - item = client.rpop(self._q_for_pri(queue, pri)) - if item: - return loads(bytes_to_str(item)) - raise Empty() - - def _size(self, queue): - with self.conn_or_acquire() as client: - cmds = client.pipeline() - for pri in PRIORITY_STEPS: - cmds = cmds.llen(self._q_for_pri(queue, pri)) - sizes = cmds.execute() - return sum(size for size in sizes - if isinstance(size, numbers.Integral)) - - def _q_for_pri(self, queue, pri): - pri = self.priority(pri) - return '%s%s%s' % ((queue, self.sep, pri) if pri else (queue, '', '')) - - def priority(self, n): - steps = self.priority_steps - return steps[bisect(steps, n) - 1] - - def _put(self, queue, message, **kwargs): - """Deliver message.""" - try: - pri = max(min(int( - message['properties']['delivery_info']['priority']), 9), 0) - except (TypeError, ValueError, KeyError): - pri = 0 - with self.conn_or_acquire() as client: - client.lpush(self._q_for_pri(queue, pri), dumps(message)) - - def _put_fanout(self, exchange, message, routing_key, **kwargs): - """Deliver fanout message.""" - with self.conn_or_acquire() as client: - client.publish( - self._get_publish_topic(exchange, routing_key), - dumps(message), - ) - - def _new_queue(self, queue, auto_delete=False, **kwargs): - if auto_delete: - self.auto_delete_queues.add(queue) - - def _queue_bind(self, exchange, routing_key, pattern, queue): - if self.typeof(exchange).type == 'fanout': - # Mark exchange as fanout. - self._fanout_queues[queue] = ( - exchange, routing_key.replace('#', '*'), - ) - with self.conn_or_acquire() as client: - client.sadd(self.keyprefix_queue % (exchange, ), - self.sep.join([routing_key or '', - pattern or '', - queue or ''])) - - def _delete(self, queue, exchange, routing_key, pattern, *args): - self.auto_delete_queues.discard(queue) - with self.conn_or_acquire() as client: - client.srem(self.keyprefix_queue % (exchange, ), - self.sep.join([routing_key or '', - pattern or '', - queue or ''])) - cmds = client.pipeline() - for pri in PRIORITY_STEPS: - cmds = cmds.delete(self._q_for_pri(queue, pri)) - cmds.execute() - - def _has_queue(self, queue, **kwargs): - with self.conn_or_acquire() as client: - cmds = client.pipeline() - for pri in PRIORITY_STEPS: - cmds = cmds.exists(self._q_for_pri(queue, pri)) - return any(cmds.execute()) - - def get_table(self, exchange): - key = self.keyprefix_queue % exchange - with self.conn_or_acquire() as client: - values = client.smembers(key) - if not values: - raise InconsistencyError(NO_ROUTE_ERROR.format(exchange, key)) - return [tuple(bytes_to_str(val).split(self.sep)) for val in values] - - def _purge(self, queue): - with self.conn_or_acquire() as client: - cmds = client.pipeline() - for pri in PRIORITY_STEPS: - priq = self._q_for_pri(queue, pri) - cmds = cmds.llen(priq).delete(priq) - sizes = cmds.execute() - return sum(sizes[::2]) - - def close(self): - if self._pool: - self._pool.disconnect() - if not self.closed: - # remove from channel poller. - self.connection.cycle.discard(self) - - # delete fanout bindings - for queue in self._fanout_queues: - if queue in self.auto_delete_queues: - self.queue_delete(queue) - - self._close_clients() - - super(Channel, self).close() - - def _close_clients(self): - # Close connections - for attr in 'client', 'subclient': - try: - self.__dict__[attr].connection.disconnect() - except (KeyError, AttributeError, self.ResponseError): - pass - - def _prepare_virtual_host(self, vhost): - if not isinstance(vhost, numbers.Integral): - if not vhost or vhost == '/': - vhost = DEFAULT_DB - elif vhost.startswith('/'): - vhost = vhost[1:] - try: - vhost = int(vhost) - except ValueError: - raise ValueError( - 'Database is int between 0 and limit - 1, not {0}'.format( - vhost, - )) - return vhost - - def _connparams(self): - conninfo = self.connection.client - connparams = {'host': conninfo.hostname or '127.0.0.1', - 'port': conninfo.port or DEFAULT_PORT, - 'virtual_host': conninfo.virtual_host, - 'password': conninfo.password, - 'max_connections': self.max_connections, - 'socket_timeout': self.socket_timeout} - host = connparams['host'] - if '://' in host: - scheme, _, _, _, _, path, query = _parse_url(host) - if scheme == 'socket': - connparams.update({ - 'connection_class': redis.UnixDomainSocketConnection, - 'path': '/' + path}, **query) - connparams.pop('host', None) - connparams.pop('port', None) - connparams['db'] = self._prepare_virtual_host( - connparams.pop('virtual_host', None)) - - channel = self - connection_cls = ( - connparams.get('connection_class') or - redis.Connection - ) - - class Connection(connection_cls): - def disconnect(self): - channel._on_connection_disconnect(self) - super(Connection, self).disconnect() - connparams['connection_class'] = Connection - - return connparams - - def _create_client(self): - return self.Client(connection_pool=self.pool) - - def _get_pool(self): - params = self._connparams() - self.keyprefix_fanout = self.keyprefix_fanout.format(db=params['db']) - return redis.ConnectionPool(**params) - - def _get_client(self): - if redis.VERSION < (2, 4, 4): - raise VersionMismatch( - 'Redis transport requires redis-py versions 2.4.4 or later. ' - 'You have {0.__version__}'.format(redis)) - - # KombuRedis maintains a connection attribute on it's instance and - # uses that when executing commands - # This was added after redis-py was changed. - class KombuRedis(redis.Redis): # pragma: no cover - - def __init__(self, *args, **kwargs): - super(KombuRedis, self).__init__(*args, **kwargs) - self.connection = self.connection_pool.get_connection('_') - - return KombuRedis - - @contextmanager - def conn_or_acquire(self, client=None): - if client: - yield client - else: - if self._in_poll: - client = self._create_client() - try: - yield client - finally: - self.pool.release(client.connection) - else: - yield self.client - - @property - def pool(self): - if self._pool is None: - self._pool = self._get_pool() - return self._pool - - @cached_property - def client(self): - """Client used to publish messages, BRPOP etc.""" - return self._create_client() - - @cached_property - def subclient(self): - """Pub/Sub connection used to consume fanout queues.""" - client = self._create_client() - pubsub = client.pubsub() - pool = pubsub.connection_pool - pubsub.connection = pool.get_connection('pubsub', pubsub.shard_hint) - return pubsub - - def _update_cycle(self): - """Update fair cycle between queues. - - We cycle between queues fairly to make sure that - each queue is equally likely to be consumed from, - so that a very busy queue will not block others. - - This works by using Redis's `BRPOP` command and - by rotating the most recently used queue to the - and of the list. See Kombu github issue #166 for - more discussion of this method. - - """ - self._queue_cycle = list(self.active_queues) - - def _consume_cycle(self): - """Get a fresh list of queues from the queue cycle.""" - active = len(self.active_queues) - return self._queue_cycle[0:active] - - def _rotate_cycle(self, used): - """Move most recently used queue to end of list.""" - cycle = self._queue_cycle - try: - cycle.append(cycle.pop(cycle.index(used))) - except ValueError: - pass - - def _get_response_error(self): - from redis import exceptions - return exceptions.ResponseError - - @property - def active_queues(self): - """Set of queues being consumed from (excluding fanout queues).""" - return set(queue for queue in self._active_queues - if queue not in self.active_fanout_queues) - - -class Transport(virtual.Transport): - Channel = Channel - - polling_interval = None # disable sleep between unsuccessful polls. - default_port = DEFAULT_PORT - supports_ev = True - driver_type = 'redis' - driver_name = 'redis' - - def __init__(self, *args, **kwargs): - if redis is None: - raise ImportError('Missing redis library (pip install redis)') - super(Transport, self).__init__(*args, **kwargs) - - # Get redis-py exceptions. - self.connection_errors, self.channel_errors = self._get_errors() - # All channels share the same poller. - self.cycle = MultiChannelPoller() - - def driver_version(self): - return redis.__version__ - - def register_with_event_loop(self, connection, loop): - cycle = self.cycle - cycle.on_poll_init(loop.poller) - cycle_poll_start = cycle.on_poll_start - add_reader = loop.add_reader - on_readable = self.on_readable - - def _on_disconnect(connection): - if connection._sock: - loop.remove(connection._sock) - cycle._on_connection_disconnect = _on_disconnect - - def on_poll_start(): - cycle_poll_start() - [add_reader(fd, on_readable, fd) for fd in cycle.fds] - loop.on_tick.add(on_poll_start) - loop.call_repeatedly(10, cycle.maybe_restore_messages) - - def on_readable(self, fileno): - """Handle AIO event for one of our file descriptors.""" - item = self.cycle.on_readable(fileno) - if item: - message, queue = item - if not queue or queue not in self._callbacks: - raise KeyError( - 'Message for queue {0!r} without consumers: {1}'.format( - queue, message)) - self._callbacks[queue](message) - - def _get_errors(self): - """Utility to import redis-py's exceptions at runtime.""" - return get_redis_error_classes() diff --git a/awx/lib/site-packages/kombu/transport/sqlalchemy/__init__.py b/awx/lib/site-packages/kombu/transport/sqlalchemy/__init__.py deleted file mode 100644 index 3aab155729..0000000000 --- a/awx/lib/site-packages/kombu/transport/sqlalchemy/__init__.py +++ /dev/null @@ -1,160 +0,0 @@ -"""Kombu transport using SQLAlchemy as the message store.""" -# SQLAlchemy overrides != False to have special meaning and pep8 complains -# flake8: noqa - -from __future__ import absolute_import - -from anyjson import loads, dumps -from sqlalchemy import create_engine -from sqlalchemy.exc import OperationalError -from sqlalchemy.orm import sessionmaker - -from kombu.five import Empty -from kombu.transport import virtual -from kombu.utils import cached_property -from kombu.utils.encoding import bytes_to_str - -from .models import (ModelBase, Queue as QueueBase, Message as MessageBase, - class_registry, metadata) - - -VERSION = (1, 1, 0) -__version__ = '.'.join(map(str, VERSION)) - - -class Channel(virtual.Channel): - _session = None - _engines = {} # engine cache - - def __init__(self, connection, **kwargs): - self._configure_entity_tablenames(connection.client.transport_options) - super(Channel, self).__init__(connection, **kwargs) - - def _configure_entity_tablenames(self, opts): - self.queue_tablename = opts.get('queue_tablename', 'kombu_queue') - self.message_tablename = opts.get('message_tablename', 'kombu_message') - - # - # Define the model definitions. This registers the declarative - # classes with the active SQLAlchemy metadata object. This *must* be - # done prior to the ``create_engine`` call. - # - self.queue_cls and self.message_cls - - def _engine_from_config(self): - conninfo = self.connection.client - transport_options = conninfo.transport_options.copy() - transport_options.pop('queue_tablename', None) - transport_options.pop('message_tablename', None) - return create_engine(conninfo.hostname, **transport_options) - - def _open(self): - conninfo = self.connection.client - if conninfo.hostname not in self._engines: - engine = self._engine_from_config() - Session = sessionmaker(bind=engine) - metadata.create_all(engine) - self._engines[conninfo.hostname] = engine, Session - return self._engines[conninfo.hostname] - - @property - def session(self): - if self._session is None: - _, Session = self._open() - self._session = Session() - return self._session - - def _get_or_create(self, queue): - obj = self.session.query(self.queue_cls) \ - .filter(self.queue_cls.name == queue).first() - if not obj: - obj = self.queue_cls(queue) - self.session.add(obj) - try: - self.session.commit() - except OperationalError: - self.session.rollback() - return obj - - def _new_queue(self, queue, **kwargs): - self._get_or_create(queue) - - def _put(self, queue, payload, **kwargs): - obj = self._get_or_create(queue) - message = self.message_cls(dumps(payload), obj) - self.session.add(message) - try: - self.session.commit() - except OperationalError: - self.session.rollback() - - def _get(self, queue): - obj = self._get_or_create(queue) - if self.session.bind.name == 'sqlite': - self.session.execute('BEGIN IMMEDIATE TRANSACTION') - try: - msg = self.session.query(self.message_cls) \ - .with_lockmode('update') \ - .filter(self.message_cls.queue_id == obj.id) \ - .filter(self.message_cls.visible != False) \ - .order_by(self.message_cls.sent_at) \ - .order_by(self.message_cls.id) \ - .limit(1) \ - .first() - if msg: - msg.visible = False - return loads(bytes_to_str(msg.payload)) - raise Empty() - finally: - self.session.commit() - - def _query_all(self, queue): - obj = self._get_or_create(queue) - return self.session.query(self.message_cls) \ - .filter(self.message_cls.queue_id == obj.id) - - def _purge(self, queue): - count = self._query_all(queue).delete(synchronize_session=False) - try: - self.session.commit() - except OperationalError: - self.session.rollback() - return count - - def _size(self, queue): - return self._query_all(queue).count() - - def _declarative_cls(self, name, base, ns): - if name in class_registry: - return class_registry[name] - return type(name, (base, ModelBase), ns) - - @cached_property - def queue_cls(self): - return self._declarative_cls( - 'Queue', - QueueBase, - {'__tablename__': self.queue_tablename} - ) - - @cached_property - def message_cls(self): - return self._declarative_cls( - 'Message', - MessageBase, - {'__tablename__': self.message_tablename} - ) - - -class Transport(virtual.Transport): - Channel = Channel - - can_parse_url = True - default_port = 0 - driver_type = 'sql' - driver_name = 'sqlalchemy' - connection_errors = (OperationalError, ) - - def driver_version(self): - import sqlalchemy - return sqlalchemy.__version__ diff --git a/awx/lib/site-packages/kombu/transport/sqlalchemy/models.py b/awx/lib/site-packages/kombu/transport/sqlalchemy/models.py deleted file mode 100644 index 4fa2bfefb9..0000000000 --- a/awx/lib/site-packages/kombu/transport/sqlalchemy/models.py +++ /dev/null @@ -1,62 +0,0 @@ -from __future__ import absolute_import - -import datetime - -from sqlalchemy import (Column, Integer, String, Text, DateTime, - Sequence, Boolean, ForeignKey, SmallInteger) -from sqlalchemy.orm import relation -from sqlalchemy.ext.declarative import declarative_base, declared_attr -from sqlalchemy.schema import MetaData - -class_registry = {} -metadata = MetaData() -ModelBase = declarative_base(metadata=metadata, class_registry=class_registry) - - -class Queue(object): - __table_args__ = {'sqlite_autoincrement': True, 'mysql_engine': 'InnoDB'} - - id = Column(Integer, Sequence('queue_id_sequence'), primary_key=True, - autoincrement=True) - name = Column(String(200), unique=True) - - def __init__(self, name): - self.name = name - - def __str__(self): - return '<Queue({self.name})>'.format(self=self) - - @declared_attr - def messages(cls): - return relation('Message', backref='queue', lazy='noload') - - -class Message(object): - __table_args__ = {'sqlite_autoincrement': True, 'mysql_engine': 'InnoDB'} - - id = Column(Integer, Sequence('message_id_sequence'), - primary_key=True, autoincrement=True) - visible = Column(Boolean, default=True, index=True) - sent_at = Column('timestamp', DateTime, nullable=True, index=True, - onupdate=datetime.datetime.now) - payload = Column(Text, nullable=False) - version = Column(SmallInteger, nullable=False, default=1) - - __mapper_args__ = {'version_id_col': version} - - def __init__(self, payload, queue): - self.payload = payload - self.queue = queue - - def __str__(self): - return '<Message: {0.sent_at} {0.payload} {0.queue_id}>'.format(self) - - @declared_attr - def queue_id(self): - return Column( - Integer, - ForeignKey( - '%s.id' % class_registry['Queue'].__tablename__, - name='FK_kombu_message_queue' - ) - ) diff --git a/awx/lib/site-packages/kombu/transport/virtual/__init__.py b/awx/lib/site-packages/kombu/transport/virtual/__init__.py deleted file mode 100644 index ddcca47160..0000000000 --- a/awx/lib/site-packages/kombu/transport/virtual/__init__.py +++ /dev/null @@ -1,854 +0,0 @@ -""" -kombu.transport.virtual -======================= - -Virtual transport implementation. - -Emulates the AMQ API for non-AMQ transports. - -""" -from __future__ import absolute_import, unicode_literals - -import base64 -import socket -import sys -import warnings - -from array import array -from itertools import count -from multiprocessing.util import Finalize -from time import sleep - -from amqp.protocol import queue_declare_ok_t - -from kombu.exceptions import ResourceError, ChannelError -from kombu.five import Empty, items, monotonic -from kombu.utils import emergency_dump_state, kwdict, say, uuid -from kombu.utils.compat import OrderedDict -from kombu.utils.encoding import str_to_bytes, bytes_to_str - -from kombu.transport import base - -from .scheduling import FairCycle -from .exchange import STANDARD_EXCHANGE_TYPES - -ARRAY_TYPE_H = 'H' if sys.version_info[0] == 3 else b'H' - -UNDELIVERABLE_FMT = """\ -Message could not be delivered: No queues bound to exchange {exchange!r} \ -using binding key {routing_key!r}. -""" - -NOT_EQUIVALENT_FMT = """\ -Cannot redeclare exchange {0!r} in vhost {1!r} with \ -different type, durable, autodelete or arguments value.\ -""" - - -class Base64(object): - - def encode(self, s): - return bytes_to_str(base64.b64encode(str_to_bytes(s))) - - def decode(self, s): - return base64.b64decode(str_to_bytes(s)) - - -class NotEquivalentError(Exception): - """Entity declaration is not equivalent to the previous declaration.""" - pass - - -class UndeliverableWarning(UserWarning): - """The message could not be delivered to a queue.""" - pass - - -class BrokerState(object): - - #: exchange declarations. - exchanges = None - - #: active bindings. - bindings = None - - def __init__(self, exchanges=None, bindings=None): - self.exchanges = {} if exchanges is None else exchanges - self.bindings = {} if bindings is None else bindings - - def clear(self): - self.exchanges.clear() - self.bindings.clear() - - -class QoS(object): - """Quality of Service guarantees. - - Only supports `prefetch_count` at this point. - - :param channel: AMQ Channel. - :keyword prefetch_count: Initial prefetch count (defaults to 0). - - """ - - #: current prefetch count value - prefetch_count = 0 - - #: :class:`~collections.OrderedDict` of active messages. - #: *NOTE*: Can only be modified by the consuming thread. - _delivered = None - - #: acks can be done by other threads than the consuming thread. - #: Instead of a mutex, which doesn't perform well here, we mark - #: the delivery tags as dirty, so subsequent calls to append() can remove - #: them. - _dirty = None - - #: If disabled, unacked messages won't be restored at shutdown. - restore_at_shutdown = True - - def __init__(self, channel, prefetch_count=0): - self.channel = channel - self.prefetch_count = prefetch_count or 0 - - self._delivered = OrderedDict() - self._delivered.restored = False - self._dirty = set() - self._quick_ack = self._dirty.add - self._quick_append = self._delivered.__setitem__ - self._on_collect = Finalize( - self, self.restore_unacked_once, exitpriority=1, - ) - - def can_consume(self): - """Return true if the channel can be consumed from. - - Used to ensure the client adhers to currently active - prefetch limits. - - """ - pcount = self.prefetch_count - return not pcount or len(self._delivered) - len(self._dirty) < pcount - - def can_consume_max_estimate(self): - """Returns the maximum number of messages allowed to be returned. - - Returns an estimated number of messages that a consumer may be allowed - to consume at once from the broker. This is used for services where - bulk 'get message' calls are preferred to many individual 'get message' - calls - like SQS. - - returns: - An integer > 0 - """ - pcount = self.prefetch_count - if pcount: - return max(pcount - (len(self._delivered) - len(self._dirty)), 0) - - def append(self, message, delivery_tag): - """Append message to transactional state.""" - if self._dirty: - self._flush() - self._quick_append(delivery_tag, message) - - def get(self, delivery_tag): - return self._delivered[delivery_tag] - - def _flush(self): - """Flush dirty (acked/rejected) tags from.""" - dirty = self._dirty - delivered = self._delivered - while 1: - try: - dirty_tag = dirty.pop() - except KeyError: - break - delivered.pop(dirty_tag, None) - - def ack(self, delivery_tag): - """Acknowledge message and remove from transactional state.""" - self._quick_ack(delivery_tag) - - def reject(self, delivery_tag, requeue=False): - """Remove from transactional state and requeue message.""" - if requeue: - self.channel._restore_at_beginning(self._delivered[delivery_tag]) - self._quick_ack(delivery_tag) - - def restore_unacked(self): - """Restore all unacknowledged messages.""" - self._flush() - delivered = self._delivered - errors = [] - restore = self.channel._restore - pop_message = delivered.popitem - - while delivered: - try: - _, message = pop_message() - except KeyError: # pragma: no cover - break - - try: - restore(message) - except BaseException as exc: - errors.append((exc, message)) - delivered.clear() - return errors - - def restore_unacked_once(self): - """Restores all unacknowledged messages at shutdown/gc collect. - - Will only be done once for each instance. - - """ - self._on_collect.cancel() - self._flush() - state = self._delivered - - if not self.restore_at_shutdown or not self.channel.do_restore: - return - if getattr(state, 'restored', None): - assert not state - return - try: - if state: - say('Restoring {0!r} unacknowledged message(s).', - len(self._delivered)) - unrestored = self.restore_unacked() - - if unrestored: - errors, messages = list(zip(*unrestored)) - say('UNABLE TO RESTORE {0} MESSAGES: {1}', - len(errors), errors) - emergency_dump_state(messages) - finally: - state.restored = True - - def restore_visible(self, *args, **kwargs): - """Restore any pending unackwnowledged messages for visibility_timeout - style implementations. - - Optional: Currently only used by the Redis transport. - - """ - pass - - -class Message(base.Message): - - def __init__(self, channel, payload, **kwargs): - self._raw = payload - properties = payload['properties'] - body = payload.get('body') - if body: - body = channel.decode_body(body, properties.get('body_encoding')) - kwargs.update({ - 'body': body, - 'delivery_tag': properties['delivery_tag'], - 'content_type': payload.get('content-type'), - 'content_encoding': payload.get('content-encoding'), - 'headers': payload.get('headers'), - 'properties': properties, - 'delivery_info': properties.get('delivery_info'), - 'postencode': 'utf-8', - }) - super(Message, self).__init__(channel, **kwdict(kwargs)) - - def serializable(self): - props = self.properties - body, _ = self.channel.encode_body(self.body, - props.get('body_encoding')) - headers = dict(self.headers) - # remove compression header - headers.pop('compression', None) - return { - 'body': body, - 'properties': props, - 'content-type': self.content_type, - 'content-encoding': self.content_encoding, - 'headers': headers, - } - - -class AbstractChannel(object): - """This is an abstract class defining the channel methods - you'd usually want to implement in a virtual channel. - - Do not subclass directly, but rather inherit from :class:`Channel` - instead. - - """ - - def _get(self, queue, timeout=None): - """Get next message from `queue`.""" - raise NotImplementedError('Virtual channels must implement _get') - - def _put(self, queue, message): - """Put `message` onto `queue`.""" - raise NotImplementedError('Virtual channels must implement _put') - - def _purge(self, queue): - """Remove all messages from `queue`.""" - raise NotImplementedError('Virtual channels must implement _purge') - - def _size(self, queue): - """Return the number of messages in `queue` as an :class:`int`.""" - return 0 - - def _delete(self, queue, *args, **kwargs): - """Delete `queue`. - - This just purges the queue, if you need to do more you can - override this method. - - """ - self._purge(queue) - - def _new_queue(self, queue, **kwargs): - """Create new queue. - - Your transport can override this method if it needs - to do something whenever a new queue is declared. - - """ - pass - - def _has_queue(self, queue, **kwargs): - """Verify that queue exists. - - Should return :const:`True` if the queue exists or :const:`False` - otherwise. - - """ - return True - - def _poll(self, cycle, timeout=None): - """Poll a list of queues for available messages.""" - return cycle.get() - - -class Channel(AbstractChannel, base.StdChannel): - """Virtual channel. - - :param connection: The transport instance this channel is part of. - - """ - #: message class used. - Message = Message - - #: QoS class used. - QoS = QoS - - #: flag to restore unacked messages when channel - #: goes out of scope. - do_restore = True - - #: mapping of exchange types and corresponding classes. - exchange_types = dict(STANDARD_EXCHANGE_TYPES) - - #: flag set if the channel supports fanout exchanges. - supports_fanout = False - - #: Binary <-> ASCII codecs. - codecs = {'base64': Base64()} - - #: Default body encoding. - #: NOTE: ``transport_options['body_encoding']`` will override this value. - body_encoding = 'base64' - - #: counter used to generate delivery tags for this channel. - _delivery_tags = count(1) - - #: Optional queue where messages with no route is delivered. - #: Set by ``transport_options['deadletter_queue']``. - deadletter_queue = None - - # List of options to transfer from :attr:`transport_options`. - from_transport_options = ('body_encoding', 'deadletter_queue') - - def __init__(self, connection, **kwargs): - self.connection = connection - self._consumers = set() - self._cycle = None - self._tag_to_queue = {} - self._active_queues = [] - self._qos = None - self.closed = False - - # instantiate exchange types - self.exchange_types = dict( - (typ, cls(self)) for typ, cls in items(self.exchange_types) - ) - - try: - self.channel_id = self.connection._avail_channel_ids.pop() - except IndexError: - raise ResourceError( - 'No free channel ids, current={0}, channel_max={1}'.format( - len(self.connection.channels), - self.connection.channel_max), (20, 10), - ) - - topts = self.connection.client.transport_options - for opt_name in self.from_transport_options: - try: - setattr(self, opt_name, topts[opt_name]) - except KeyError: - pass - - def exchange_declare(self, exchange=None, type='direct', durable=False, - auto_delete=False, arguments=None, - nowait=False, passive=False): - """Declare exchange.""" - type = type or 'direct' - exchange = exchange or 'amq.%s' % type - if passive: - if exchange not in self.state.exchanges: - raise ChannelError( - 'NOT_FOUND - no exchange {0!r} in vhost {1!r}'.format( - exchange, self.connection.client.virtual_host or '/'), - (50, 10), 'Channel.exchange_declare', '404', - ) - return - try: - prev = self.state.exchanges[exchange] - if not self.typeof(exchange).equivalent(prev, exchange, type, - durable, auto_delete, - arguments): - raise NotEquivalentError(NOT_EQUIVALENT_FMT.format( - exchange, self.connection.client.virtual_host or '/')) - except KeyError: - self.state.exchanges[exchange] = { - 'type': type, - 'durable': durable, - 'auto_delete': auto_delete, - 'arguments': arguments or {}, - 'table': [], - } - - def exchange_delete(self, exchange, if_unused=False, nowait=False): - """Delete `exchange` and all its bindings.""" - for rkey, _, queue in self.get_table(exchange): - self.queue_delete(queue, if_unused=True, if_empty=True) - self.state.exchanges.pop(exchange, None) - - def queue_declare(self, queue=None, passive=False, **kwargs): - """Declare queue.""" - queue = queue or 'amq.gen-%s' % uuid() - if passive and not self._has_queue(queue, **kwargs): - raise ChannelError( - 'NOT_FOUND - no queue {0!r} in vhost {1!r}'.format( - queue, self.connection.client.virtual_host or '/'), - (50, 10), 'Channel.queue_declare', '404', - ) - else: - self._new_queue(queue, **kwargs) - return queue_declare_ok_t(queue, self._size(queue), 0) - - def queue_delete(self, queue, if_unused=False, if_empty=False, **kwargs): - """Delete queue.""" - if if_empty and self._size(queue): - return - try: - exchange, routing_key, arguments = self.state.bindings[queue] - except KeyError: - return - meta = self.typeof(exchange).prepare_bind( - queue, exchange, routing_key, arguments, - ) - self._delete(queue, exchange, *meta) - self.state.bindings.pop(queue, None) - - def after_reply_message_received(self, queue): - self.queue_delete(queue) - - def exchange_bind(self, destination, source='', routing_key='', - nowait=False, arguments=None): - raise NotImplementedError('transport does not support exchange_bind') - - def exchange_unbind(self, destination, source='', routing_key='', - nowait=False, arguments=None): - raise NotImplementedError('transport does not support exchange_unbind') - - def queue_bind(self, queue, exchange=None, routing_key='', - arguments=None, **kwargs): - """Bind `queue` to `exchange` with `routing key`.""" - if queue in self.state.bindings: - return - exchange = exchange or 'amq.direct' - table = self.state.exchanges[exchange].setdefault('table', []) - self.state.bindings[queue] = exchange, routing_key, arguments - meta = self.typeof(exchange).prepare_bind( - queue, exchange, routing_key, arguments, - ) - table.append(meta) - if self.supports_fanout: - self._queue_bind(exchange, *meta) - - def queue_unbind(self, queue, exchange=None, routing_key='', - arguments=None, **kwargs): - raise NotImplementedError('transport does not support queue_unbind') - - def list_bindings(self): - return ((queue, exchange, rkey) - for exchange in self.state.exchanges - for rkey, pattern, queue in self.get_table(exchange)) - - def queue_purge(self, queue, **kwargs): - """Remove all ready messages from queue.""" - return self._purge(queue) - - def _next_delivery_tag(self): - return uuid() - - def basic_publish(self, message, exchange, routing_key, **kwargs): - """Publish message.""" - message['body'], body_encoding = self.encode_body( - message['body'], self.body_encoding, - ) - props = message['properties'] - props.update( - body_encoding=body_encoding, - delivery_tag=self._next_delivery_tag(), - ) - props['delivery_info'].update( - exchange=exchange, - routing_key=routing_key, - ) - if exchange: - return self.typeof(exchange).deliver( - message, exchange, routing_key, **kwargs - ) - # anon exchange: routing_key is the destination queue - return self._put(routing_key, message, **kwargs) - - def basic_consume(self, queue, no_ack, callback, consumer_tag, **kwargs): - """Consume from `queue`""" - self._tag_to_queue[consumer_tag] = queue - self._active_queues.append(queue) - - def _callback(raw_message): - message = self.Message(self, raw_message) - if not no_ack: - self.qos.append(message, message.delivery_tag) - return callback(message) - - self.connection._callbacks[queue] = _callback - self._consumers.add(consumer_tag) - - self._reset_cycle() - - def basic_cancel(self, consumer_tag): - """Cancel consumer by consumer tag.""" - if consumer_tag in self._consumers: - self._consumers.remove(consumer_tag) - self._reset_cycle() - queue = self._tag_to_queue.pop(consumer_tag, None) - try: - self._active_queues.remove(queue) - except ValueError: - pass - self.connection._callbacks.pop(queue, None) - - def basic_get(self, queue, no_ack=False, **kwargs): - """Get message by direct access (synchronous).""" - try: - message = self.Message(self, self._get(queue)) - if not no_ack: - self.qos.append(message, message.delivery_tag) - return message - except Empty: - pass - - def basic_ack(self, delivery_tag): - """Acknowledge message.""" - self.qos.ack(delivery_tag) - - def basic_recover(self, requeue=False): - """Recover unacked messages.""" - if requeue: - return self.qos.restore_unacked() - raise NotImplementedError('Does not support recover(requeue=False)') - - def basic_reject(self, delivery_tag, requeue=False): - """Reject message.""" - self.qos.reject(delivery_tag, requeue=requeue) - - def basic_qos(self, prefetch_size=0, prefetch_count=0, - apply_global=False): - """Change QoS settings for this channel. - - Only `prefetch_count` is supported. - - """ - self.qos.prefetch_count = prefetch_count - - def get_exchanges(self): - return list(self.state.exchanges) - - def get_table(self, exchange): - """Get table of bindings for `exchange`.""" - return self.state.exchanges[exchange]['table'] - - def typeof(self, exchange, default='direct'): - """Get the exchange type instance for `exchange`.""" - try: - type = self.state.exchanges[exchange]['type'] - except KeyError: - type = default - return self.exchange_types[type] - - def _lookup(self, exchange, routing_key, default=None): - """Find all queues matching `routing_key` for the given `exchange`. - - Must return the string `default` if no queues matched. - - """ - if default is None: - default = self.deadletter_queue - try: - R = self.typeof(exchange).lookup( - self.get_table(exchange), - exchange, routing_key, default, - ) - except KeyError: - R = [] - - if not R and default is not None: - warnings.warn(UndeliverableWarning(UNDELIVERABLE_FMT.format( - exchange=exchange, routing_key=routing_key)), - ) - self._new_queue(default) - R = [default] - return R - - def _restore(self, message): - """Redeliver message to its original destination.""" - delivery_info = message.delivery_info - message = message.serializable() - message['redelivered'] = True - for queue in self._lookup( - delivery_info['exchange'], delivery_info['routing_key']): - self._put(queue, message) - - def _restore_at_beginning(self, message): - return self._restore(message) - - def drain_events(self, timeout=None): - if self._consumers and self.qos.can_consume(): - if hasattr(self, '_get_many'): - return self._get_many(self._active_queues, timeout=timeout) - return self._poll(self.cycle, timeout=timeout) - raise Empty() - - def message_to_python(self, raw_message): - """Convert raw message to :class:`Message` instance.""" - if not isinstance(raw_message, self.Message): - return self.Message(self, payload=raw_message) - return raw_message - - def prepare_message(self, body, priority=None, content_type=None, - content_encoding=None, headers=None, properties=None): - """Prepare message data.""" - properties = properties or {} - info = properties.setdefault('delivery_info', {}) - info['priority'] = priority or 0 - - return {'body': body, - 'content-encoding': content_encoding, - 'content-type': content_type, - 'headers': headers or {}, - 'properties': properties or {}} - - def flow(self, active=True): - """Enable/disable message flow. - - :raises NotImplementedError: as flow - is not implemented by the base virtual implementation. - - """ - raise NotImplementedError('virtual channels do not support flow.') - - def close(self): - """Close channel, cancel all consumers, and requeue unacked - messages.""" - if not self.closed: - self.closed = True - for consumer in list(self._consumers): - self.basic_cancel(consumer) - if self._qos: - self._qos.restore_unacked_once() - if self._cycle is not None: - self._cycle.close() - self._cycle = None - if self.connection is not None: - self.connection.close_channel(self) - self.exchange_types = None - - def encode_body(self, body, encoding=None): - if encoding: - return self.codecs.get(encoding).encode(body), encoding - return body, encoding - - def decode_body(self, body, encoding=None): - if encoding: - return self.codecs.get(encoding).decode(body) - return body - - def _reset_cycle(self): - self._cycle = FairCycle(self._get, self._active_queues, Empty) - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - - @property - def state(self): - """Broker state containing exchanges and bindings.""" - return self.connection.state - - @property - def qos(self): - """:class:`QoS` manager for this channel.""" - if self._qos is None: - self._qos = self.QoS(self) - return self._qos - - @property - def cycle(self): - if self._cycle is None: - self._reset_cycle() - return self._cycle - - -class Management(base.Management): - - def __init__(self, transport): - super(Management, self).__init__(transport) - self.channel = transport.client.channel() - - def get_bindings(self): - return [dict(destination=q, source=e, routing_key=r) - for q, e, r in self.channel.list_bindings()] - - def close(self): - self.channel.close() - - -class Transport(base.Transport): - """Virtual transport. - - :param client: :class:`~kombu.Connection` instance - - """ - Channel = Channel - Cycle = FairCycle - Management = Management - - #: :class:`BrokerState` containing declared exchanges and - #: bindings (set by constructor). - state = BrokerState() - - #: :class:`~kombu.transport.virtual.scheduling.FairCycle` instance - #: used to fairly drain events from channels (set by constructor). - cycle = None - - #: port number used when no port is specified. - default_port = None - - #: active channels. - channels = None - - #: queue/callback map. - _callbacks = None - - #: Time to sleep between unsuccessful polls. - polling_interval = 1.0 - - #: Max number of channels - channel_max = 65535 - - def __init__(self, client, **kwargs): - self.client = client - self.channels = [] - self._avail_channels = [] - self._callbacks = {} - self.cycle = self.Cycle(self._drain_channel, self.channels, Empty) - polling_interval = client.transport_options.get('polling_interval') - if polling_interval is not None: - self.polling_interval = polling_interval - self._avail_channel_ids = array( - ARRAY_TYPE_H, range(self.channel_max, 0, -1), - ) - - def create_channel(self, connection): - try: - return self._avail_channels.pop() - except IndexError: - channel = self.Channel(connection) - self.channels.append(channel) - return channel - - def close_channel(self, channel): - try: - self._avail_channel_ids.append(channel.channel_id) - try: - self.channels.remove(channel) - except ValueError: - pass - finally: - channel.connection = None - - def establish_connection(self): - # creates channel to verify connection. - # this channel is then used as the next requested channel. - # (returned by ``create_channel``). - self._avail_channels.append(self.create_channel(self)) - return self # for drain events - - def close_connection(self, connection): - self.cycle.close() - for l in self._avail_channels, self.channels: - while l: - try: - channel = l.pop() - except (IndexError, KeyError): # pragma: no cover - pass - else: - channel.close() - - def drain_events(self, connection, timeout=None): - loop = 0 - time_start = monotonic() - get = self.cycle.get - polling_interval = self.polling_interval - while 1: - try: - item, channel = get(timeout=timeout) - except Empty: - if timeout and monotonic() - time_start >= timeout: - raise socket.timeout() - loop += 1 - if polling_interval is not None: - sleep(polling_interval) - else: - break - - message, queue = item - - if not queue or queue not in self._callbacks: - raise KeyError( - 'Message for queue {0!r} without consumers: {1}'.format( - queue, message)) - - self._callbacks[queue](message) - - def _drain_channel(self, channel, timeout=None): - return channel.drain_events(timeout=timeout) - - @property - def default_connection_params(self): - return {'port': self.default_port, 'hostname': 'localhost'} diff --git a/awx/lib/site-packages/kombu/transport/virtual/exchange.py b/awx/lib/site-packages/kombu/transport/virtual/exchange.py deleted file mode 100644 index c788a26e7d..0000000000 --- a/awx/lib/site-packages/kombu/transport/virtual/exchange.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -kombu.transport.virtual.exchange -================================ - -Implementations of the standard exchanges defined -by the AMQ protocol (excluding the `headers` exchange). - -""" -from __future__ import absolute_import - -from kombu.utils import escape_regex - -import re - - -class ExchangeType(object): - """Implements the specifics for an exchange type. - - :param channel: AMQ Channel - - """ - type = None - - def __init__(self, channel): - self.channel = channel - - def lookup(self, table, exchange, routing_key, default): - """Lookup all queues matching `routing_key` in `exchange`. - - :returns: `default` if no queues matched. - - """ - raise NotImplementedError('subclass responsibility') - - def prepare_bind(self, queue, exchange, routing_key, arguments): - """Return tuple of `(routing_key, regex, queue)` to be stored - for bindings to this exchange.""" - return routing_key, None, queue - - def equivalent(self, prev, exchange, type, - durable, auto_delete, arguments): - """Return true if `prev` and `exchange` is equivalent.""" - return (type == prev['type'] and - durable == prev['durable'] and - auto_delete == prev['auto_delete'] and - (arguments or {}) == (prev['arguments'] or {})) - - -class DirectExchange(ExchangeType): - """The `direct` exchange routes based on exact routing keys.""" - type = 'direct' - - def lookup(self, table, exchange, routing_key, default): - return [queue for rkey, _, queue in table - if rkey == routing_key] - - def deliver(self, message, exchange, routing_key, **kwargs): - _lookup = self.channel._lookup - _put = self.channel._put - for queue in _lookup(exchange, routing_key): - _put(queue, message, **kwargs) - - -class TopicExchange(ExchangeType): - """The `topic` exchange routes messages based on words separated by - dots, using wildcard characters ``*`` (any single word), and ``#`` - (one or more words).""" - type = 'topic' - - #: map of wildcard to regex conversions - wildcards = {'*': r'.*?[^\.]', - '#': r'.*?'} - - #: compiled regex cache - _compiled = {} - - def lookup(self, table, exchange, routing_key, default): - return [queue for rkey, pattern, queue in table - if self._match(pattern, routing_key)] - - def deliver(self, message, exchange, routing_key, **kwargs): - _lookup = self.channel._lookup - _put = self.channel._put - deadletter = self.channel.deadletter_queue - for queue in [q for q in _lookup(exchange, routing_key) - if q and q != deadletter]: - _put(queue, message, **kwargs) - - def prepare_bind(self, queue, exchange, routing_key, arguments): - return routing_key, self.key_to_pattern(routing_key), queue - - def key_to_pattern(self, rkey): - """Get the corresponding regex for any routing key.""" - return '^%s$' % ('\.'.join( - self.wildcards.get(word, word) - for word in escape_regex(rkey, '.#*').split('.') - )) - - def _match(self, pattern, string): - """Same as :func:`re.match`, except the regex is compiled and cached, - then reused on subsequent matches with the same pattern.""" - try: - compiled = self._compiled[pattern] - except KeyError: - compiled = self._compiled[pattern] = re.compile(pattern, re.U) - return compiled.match(string) - - -class FanoutExchange(ExchangeType): - """The `fanout` exchange implements broadcast messaging by delivering - copies of all messages to all queues bound to the exchange. - - To support fanout the virtual channel needs to store the table - as shared state. This requires that the `Channel.supports_fanout` - attribute is set to true, and the `Channel._queue_bind` and - `Channel.get_table` methods are implemented. See the redis backend - for an example implementation of these methods. - - """ - type = 'fanout' - - def lookup(self, table, exchange, routing_key, default): - return [queue for _, _, queue in table] - - def deliver(self, message, exchange, routing_key, **kwargs): - if self.channel.supports_fanout: - self.channel._put_fanout( - exchange, message, routing_key, **kwargs) - - -#: Map of standard exchange types and corresponding classes. -STANDARD_EXCHANGE_TYPES = {'direct': DirectExchange, - 'topic': TopicExchange, - 'fanout': FanoutExchange} diff --git a/awx/lib/site-packages/kombu/transport/virtual/scheduling.py b/awx/lib/site-packages/kombu/transport/virtual/scheduling.py deleted file mode 100644 index bf92a3a808..0000000000 --- a/awx/lib/site-packages/kombu/transport/virtual/scheduling.py +++ /dev/null @@ -1,49 +0,0 @@ -""" - kombu.transport.virtual.scheduling - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Consumer utilities. - -""" -from __future__ import absolute_import - -from itertools import count - - -class FairCycle(object): - """Consume from a set of resources, where each resource gets - an equal chance to be consumed from.""" - - def __init__(self, fun, resources, predicate=Exception): - self.fun = fun - self.resources = resources - self.predicate = predicate - self.pos = 0 - - def _next(self): - while 1: - try: - resource = self.resources[self.pos] - self.pos += 1 - return resource - except IndexError: - self.pos = 0 - if not self.resources: - raise self.predicate() - - def get(self, **kwargs): - for tried in count(0): # for infinity - resource = self._next() - - try: - return self.fun(resource, **kwargs), resource - except self.predicate: - if tried >= len(self.resources) - 1: - raise - - def close(self): - pass - - def __repr__(self): - return '<FairCycle: {self.pos}/{size} {self.resources}>'.format( - self=self, size=len(self.resources)) diff --git a/awx/lib/site-packages/kombu/transport/zmq.py b/awx/lib/site-packages/kombu/transport/zmq.py deleted file mode 100644 index e6b8a48b7f..0000000000 --- a/awx/lib/site-packages/kombu/transport/zmq.py +++ /dev/null @@ -1,314 +0,0 @@ -""" -kombu.transport.zmq -=================== - -ZeroMQ transport. - -""" -from __future__ import absolute_import - -import errno -import os -import socket - -try: - import zmq - from zmq import ZMQError -except ImportError: - zmq = ZMQError = None # noqa - -from kombu.five import Empty -from kombu.log import get_logger -from kombu.serialization import pickle -from kombu.utils import cached_property -from kombu.utils.eventio import poll, READ - -from . import virtual - -logger = get_logger('kombu.transport.zmq') - -DEFAULT_PORT = 5555 -DEFAULT_HWM = 128 -DEFAULT_INCR = 1 - -dumps, loads = pickle.dumps, pickle.loads - - -class MultiChannelPoller(object): - eventflags = READ - - def __init__(self): - # active channels - self._channels = set() - # file descriptor -> channel map - self._fd_to_chan = {} - # poll implementation (epoll/kqueue/select) - self.poller = poll() - - def close(self): - for fd in self._fd_to_chan: - try: - self.poller.unregister(fd) - except KeyError: - pass - self._channels.clear() - self._fd_to_chan.clear() - self.poller = None - - def add(self, channel): - self._channels.add(channel) - - def discard(self, channel): - self._channels.discard(channel) - self._fd_to_chan.pop(channel.client.connection.fd, None) - - def _register(self, channel): - conn = channel.client.connection - self._fd_to_chan[conn.fd] = channel - self.poller.register(conn.fd, self.eventflags) - - def on_poll_start(self): - for channel in self._channels: - self._register(channel) - - def on_readable(self, fileno): - chan = self._fd_to_chan[fileno] - return chan.drain_events(), chan - - def get(self, timeout=None): - self.on_poll_start() - - events = self.poller.poll(timeout) - for fileno, _ in events or []: - return self.on_readable(fileno) - - raise Empty() - - @property - def fds(self): - return self._fd_to_chan - - -class Client(object): - - def __init__(self, uri='tcp://127.0.0.1', port=DEFAULT_PORT, - hwm=DEFAULT_HWM, swap_size=None, enable_sink=True, - context=None): - try: - scheme, parts = uri.split('://') - except ValueError: - scheme = 'tcp' - parts = uri - endpoints = parts.split(';') - self.port = port - - if scheme != 'tcp': - raise NotImplementedError('Currently only TCP can be used') - - self.context = context or zmq.Context.instance() - - if enable_sink: - self.sink = self.context.socket(zmq.PULL) - self.sink.bind('tcp://*:{0.port}'.format(self)) - else: - self.sink = None - - self.vent = self.context.socket(zmq.PUSH) - - if hasattr(zmq, 'SNDHWM'): - self.vent.setsockopt(zmq.SNDHWM, hwm) - else: - self.vent.setsockopt(zmq.HWM, hwm) - - if swap_size: - self.vent.setsockopt(zmq.SWAP, swap_size) - - for endpoint in endpoints: - if scheme == 'tcp' and ':' not in endpoint: - endpoint += ':' + str(DEFAULT_PORT) - - endpoint = ''.join([scheme, '://', endpoint]) - - self.connect(endpoint) - - def connect(self, endpoint): - self.vent.connect(endpoint) - - def get(self, queue=None, timeout=None): - sink = self.sink - try: - if timeout is not None: - prev_timeout, sink.RCVTIMEO = sink.RCVTIMEO, timeout - try: - return sink.recv() - finally: - sink.RCVTIMEO = prev_timeout - else: - return sink.recv() - except ZMQError as exc: - if exc.errno == zmq.EAGAIN: - raise socket.error(errno.EAGAIN, exc.strerror) - else: - raise - - def put(self, queue, message, **kwargs): - return self.vent.send(message) - - def close(self): - if self.sink and not self.sink.closed: - self.sink.close() - if not self.vent.closed: - self.vent.close() - - @property - def connection(self): - if self.sink: - return self.sink - return self.vent - - -class Channel(virtual.Channel): - Client = Client - - hwm = DEFAULT_HWM - swap_size = None - enable_sink = True - port_incr = DEFAULT_INCR - - from_transport_options = ( - virtual.Channel.from_transport_options + - ('hwm', 'swap_size', 'enable_sink', 'port_incr') - ) - - def __init__(self, *args, **kwargs): - super_ = super(Channel, self) - super_.__init__(*args, **kwargs) - - # Evaluate socket - self.client.connection.closed - - self.connection.cycle.add(self) - self.connection_errors = self.connection.connection_errors - - def _get(self, queue, timeout=None): - try: - return loads(self.client.get(queue, timeout)) - except socket.error as exc: - if exc.errno == errno.EAGAIN and timeout != 0: - raise Empty() - else: - raise - - def _put(self, queue, message, **kwargs): - self.client.put(queue, dumps(message, -1), **kwargs) - - def _purge(self, queue): - return 0 - - def _poll(self, cycle, timeout=None): - return cycle.get(timeout=timeout) - - def close(self): - if not self.closed: - self.connection.cycle.discard(self) - try: - self.__dict__['client'].close() - except KeyError: - pass - super(Channel, self).close() - - def _prepare_port(self, port): - return (port + self.channel_id - 1) * self.port_incr - - def _create_client(self): - conninfo = self.connection.client - port = self._prepare_port(conninfo.port or DEFAULT_PORT) - return self.Client(uri=conninfo.hostname or 'tcp://127.0.0.1', - port=port, - hwm=self.hwm, - swap_size=self.swap_size, - enable_sink=self.enable_sink, - context=self.connection.context) - - @cached_property - def client(self): - return self._create_client() - - -class Transport(virtual.Transport): - Channel = Channel - - can_parse_url = True - default_port = DEFAULT_PORT - driver_type = 'zeromq' - driver_name = 'zmq' - - connection_errors = virtual.Transport.connection_errors + (ZMQError, ) - - supports_ev = True - polling_interval = None - - def __init__(self, *args, **kwargs): - if zmq is None: - raise ImportError('The zmq library is not installed') - super(Transport, self).__init__(*args, **kwargs) - self.cycle = MultiChannelPoller() - - def driver_version(self): - return zmq.__version__ - - def register_with_event_loop(self, connection, loop): - cycle = self.cycle - cycle.poller = loop.poller - add_reader = loop.add_reader - on_readable = self.on_readable - - cycle_poll_start = cycle.on_poll_start - - def on_poll_start(): - cycle_poll_start() - [add_reader(fd, on_readable, fd) for fd in cycle.fds] - - loop.on_tick.add(on_poll_start) - - def on_readable(self, fileno): - self._handle_event(self.cycle.on_readable(fileno)) - - def drain_events(self, connection, timeout=None): - more_to_read = False - for channel in connection.channels: - try: - evt = channel.cycle.get(timeout=timeout) - except socket.error as exc: - if exc.errno == errno.EAGAIN: - continue - raise - else: - connection._handle_event((evt, channel)) - more_to_read = True - if not more_to_read: - raise socket.error(errno.EAGAIN, os.strerror(errno.EAGAIN)) - - def _handle_event(self, evt): - item, channel = evt - message, queue = item - if not queue or queue not in self._callbacks: - raise KeyError( - 'Message for queue {0!r} without consumers: {1}'.format( - queue, message)) - self._callbacks[queue](message) - - def establish_connection(self): - self.context.closed - return super(Transport, self).establish_connection() - - def close_connection(self, connection): - super(Transport, self).close_connection(connection) - try: - connection.__dict__['context'].term() - except KeyError: - pass - - @cached_property - def context(self): - return zmq.Context(1) diff --git a/awx/lib/site-packages/kombu/transport/zookeeper.py b/awx/lib/site-packages/kombu/transport/zookeeper.py deleted file mode 100644 index 2d1c8abcea..0000000000 --- a/awx/lib/site-packages/kombu/transport/zookeeper.py +++ /dev/null @@ -1,188 +0,0 @@ -""" -kombu.transport.zookeeper -========================= - -Zookeeper transport. - -:copyright: (c) 2010 - 2013 by Mahendra M. -:license: BSD, see LICENSE for more details. - -**Synopsis** - -Connects to a zookeeper node as <server>:<port>/<vhost> -The <vhost> becomes the base for all the other znodes. So we can use -it like a vhost. - -This uses the built-in kazoo recipe for queues - -**References** - -- https://zookeeper.apache.org/doc/trunk/recipes.html#sc_recipes_Queues -- https://kazoo.readthedocs.org/en/latest/api/recipe/queue.html - -**Limitations** -This queue does not offer reliable consumption. An entry is removed from -the queue prior to being processed. So if an error occurs, the consumer -has to re-queue the item or it will be lost. -""" -from __future__ import absolute_import - -import os -import socket - -from anyjson import loads, dumps - -from kombu.five import Empty -from kombu.utils.encoding import bytes_to_str - -from . import virtual - -MAX_PRIORITY = 9 - -try: - import kazoo - from kazoo.client import KazooClient - from kazoo.recipe.queue import Queue - - KZ_CONNECTION_ERRORS = ( - kazoo.exceptions.SystemErrorException, - kazoo.exceptions.ConnectionLossException, - kazoo.exceptions.MarshallingErrorException, - kazoo.exceptions.UnimplementedException, - kazoo.exceptions.OperationTimeoutException, - kazoo.exceptions.NoAuthException, - kazoo.exceptions.InvalidACLException, - kazoo.exceptions.AuthFailedException, - kazoo.exceptions.SessionExpiredException, - ) - - KZ_CHANNEL_ERRORS = ( - kazoo.exceptions.RuntimeInconsistencyException, - kazoo.exceptions.DataInconsistencyException, - kazoo.exceptions.BadArgumentsException, - kazoo.exceptions.MarshallingErrorException, - kazoo.exceptions.UnimplementedException, - kazoo.exceptions.OperationTimeoutException, - kazoo.exceptions.ApiErrorException, - kazoo.exceptions.NoNodeException, - kazoo.exceptions.NoAuthException, - kazoo.exceptions.NodeExistsException, - kazoo.exceptions.NoChildrenForEphemeralsException, - kazoo.exceptions.NotEmptyException, - kazoo.exceptions.SessionExpiredException, - kazoo.exceptions.InvalidCallbackException, - socket.error, - ) -except ImportError: - kazoo = None # noqa - KZ_CONNECTION_ERRORS = KZ_CHANNEL_ERRORS = () # noqa - -DEFAULT_PORT = 2181 - -__author__ = 'Mahendra M <mahendra.m@gmail.com>' - - -class Channel(virtual.Channel): - - _client = None - _queues = {} - - def _get_path(self, queue_name): - return os.path.join(self.vhost, queue_name) - - def _get_queue(self, queue_name): - queue = self._queues.get(queue_name, None) - - if queue is None: - queue = Queue(self.client, self._get_path(queue_name)) - self._queues[queue_name] = queue - - # Ensure that the queue is created - len(queue) - - return queue - - def _put(self, queue, message, **kwargs): - try: - priority = message['properties']['delivery_info']['priority'] - except KeyError: - priority = 0 - - queue = self._get_queue(queue) - queue.put(dumps(message), priority=(MAX_PRIORITY - priority)) - - def _get(self, queue): - queue = self._get_queue(queue) - msg = queue.get() - - if msg is None: - raise Empty() - - return loads(bytes_to_str(msg)) - - def _purge(self, queue): - count = 0 - queue = self._get_queue(queue) - - while True: - msg = queue.get() - if msg is None: - break - count += 1 - - return count - - def _delete(self, queue, *args, **kwargs): - if self._has_queue(queue): - self._purge(queue) - self.client.delete(self._get_path(queue)) - - def _size(self, queue): - queue = self._get_queue(queue) - return len(queue) - - def _new_queue(self, queue, **kwargs): - if not self._has_queue(queue): - queue = self._get_queue(queue) - - def _has_queue(self, queue): - return self.client.exists(self._get_path(queue)) is not None - - def _open(self): - conninfo = self.connection.client - port = conninfo.port or DEFAULT_PORT - conn_str = '%s:%s' % (conninfo.hostname, port) - self.vhost = os.path.join('/', conninfo.virtual_host[0:-1]) - - conn = KazooClient(conn_str) - conn.start() - return conn - - @property - def client(self): - if self._client is None: - self._client = self._open() - return self._client - - -class Transport(virtual.Transport): - Channel = Channel - polling_interval = 1 - default_port = DEFAULT_PORT - connection_errors = ( - virtual.Transport.connection_errors + KZ_CONNECTION_ERRORS - ) - channel_errors = ( - virtual.Transport.channel_errors + KZ_CHANNEL_ERRORS - ) - driver_type = 'zookeeper' - driver_name = 'kazoo' - - def __init__(self, *args, **kwargs): - if kazoo is None: - raise ImportError('The kazoo library is not installed') - - super(Transport, self).__init__(*args, **kwargs) - - def driver_version(self): - return kazoo.__version__ diff --git a/awx/lib/site-packages/kombu/utils/__init__.py b/awx/lib/site-packages/kombu/utils/__init__.py deleted file mode 100644 index 0745ddfef7..0000000000 --- a/awx/lib/site-packages/kombu/utils/__init__.py +++ /dev/null @@ -1,450 +0,0 @@ -""" -kombu.utils -=========== - -Internal utilities. - -""" -from __future__ import absolute_import, print_function - -import importlib -import numbers -import random -import sys - -from contextlib import contextmanager -from itertools import count, repeat -from functools import wraps -from time import sleep -from uuid import UUID, uuid4 as _uuid4, _uuid_generate_random - -from kombu.five import items, reraise, string_t - -from .encoding import default_encode, safe_repr as _safe_repr - -try: - import ctypes -except: - ctypes = None # noqa - -try: - from io import UnsupportedOperation - FILENO_ERRORS = (AttributeError, ValueError, UnsupportedOperation) -except ImportError: # pragma: no cover - # Py2 - FILENO_ERRORS = (AttributeError, ValueError) # noqa - - -__all__ = ['EqualityDict', 'say', 'uuid', 'kwdict', 'maybe_list', - 'fxrange', 'fxrangemax', 'retry_over_time', - 'emergency_dump_state', 'cached_property', - 'reprkwargs', 'reprcall', 'nested', 'fileno', 'maybe_fileno'] - - -def symbol_by_name(name, aliases={}, imp=None, package=None, - sep='.', default=None, **kwargs): - """Get symbol by qualified name. - - The name should be the full dot-separated path to the class:: - - modulename.ClassName - - Example:: - - celery.concurrency.processes.TaskPool - ^- class name - - or using ':' to separate module and symbol:: - - celery.concurrency.processes:TaskPool - - If `aliases` is provided, a dict containing short name/long name - mappings, the name is looked up in the aliases first. - - Examples: - - >>> symbol_by_name('celery.concurrency.processes.TaskPool') - <class 'celery.concurrency.processes.TaskPool'> - - >>> symbol_by_name('default', { - ... 'default': 'celery.concurrency.processes.TaskPool'}) - <class 'celery.concurrency.processes.TaskPool'> - - # Does not try to look up non-string names. - >>> from celery.concurrency.processes import TaskPool - >>> symbol_by_name(TaskPool) is TaskPool - True - - """ - if imp is None: - imp = importlib.import_module - - if not isinstance(name, string_t): - return name # already a class - - name = aliases.get(name) or name - sep = ':' if ':' in name else sep - module_name, _, cls_name = name.rpartition(sep) - if not module_name: - cls_name, module_name = None, package if package else cls_name - try: - try: - module = imp(module_name, package=package, **kwargs) - except ValueError as exc: - reraise(ValueError, - ValueError("Couldn't import {0!r}: {1}".format(name, exc)), - sys.exc_info()[2]) - return getattr(module, cls_name) if cls_name else module - except (ImportError, AttributeError): - if default is None: - raise - return default - - -class HashedSeq(list): - """type used for hash() to make sure the hash is not generated - multiple times.""" - __slots__ = 'hashvalue' - - def __init__(self, *seq): - self[:] = seq - self.hashvalue = hash(seq) - - def __hash__(self): - return self.hashvalue - - -def eqhash(o): - try: - return o.__eqhash__() - except AttributeError: - return hash(o) - - -class EqualityDict(dict): - - def __getitem__(self, key): - h = eqhash(key) - if h not in self: - return self.__missing__(key) - return dict.__getitem__(self, h) - - def __setitem__(self, key, value): - return dict.__setitem__(self, eqhash(key), value) - - def __delitem__(self, key): - return dict.__delitem__(self, eqhash(key)) - - -def say(m, *fargs, **fkwargs): - print(str(m).format(*fargs, **fkwargs), file=sys.stderr) - - -def uuid4(): - # Workaround for http://bugs.python.org/issue4607 - if ctypes and _uuid_generate_random: # pragma: no cover - buffer = ctypes.create_string_buffer(16) - _uuid_generate_random(buffer) - return UUID(bytes=buffer.raw) - return _uuid4() - - -def uuid(): - """Generate a unique id, having - hopefully - a very small chance of - collision. - - For now this is provided by :func:`uuid.uuid4`. - """ - return str(uuid4()) -gen_unique_id = uuid - - -if sys.version_info >= (2, 6, 5): - - def kwdict(kwargs): - return kwargs -else: - def kwdict(kwargs): # pragma: no cover # noqa - """Make sure keyword arguments are not in Unicode. - - This should be fixed in newer Python versions, - see: http://bugs.python.org/issue4978. - - """ - return dict((key.encode('utf-8'), value) - for key, value in items(kwargs)) - - -def maybe_list(v): - if v is None: - return [] - if hasattr(v, '__iter__'): - return v - return [v] - - -def fxrange(start=1.0, stop=None, step=1.0, repeatlast=False): - cur = start * 1.0 - while 1: - if not stop or cur <= stop: - yield cur - cur += step - else: - if not repeatlast: - break - yield cur - step - - -def fxrangemax(start=1.0, stop=None, step=1.0, max=100.0): - sum_, cur = 0, start * 1.0 - while 1: - if sum_ >= max: - break - yield cur - if stop: - cur = min(cur + step, stop) - else: - cur += step - sum_ += cur - - -def retry_over_time(fun, catch, args=[], kwargs={}, errback=None, - max_retries=None, interval_start=2, interval_step=2, - interval_max=30, callback=None): - """Retry the function over and over until max retries is exceeded. - - For each retry we sleep a for a while before we try again, this interval - is increased for every retry until the max seconds is reached. - - :param fun: The function to try - :param catch: Exceptions to catch, can be either tuple or a single - exception class. - :keyword args: Positional arguments passed on to the function. - :keyword kwargs: Keyword arguments passed on to the function. - :keyword errback: Callback for when an exception in ``catch`` is raised. - The callback must take two arguments: ``exc`` and ``interval``, where - ``exc`` is the exception instance, and ``interval`` is the time in - seconds to sleep next.. - :keyword max_retries: Maximum number of retries before we give up. - If this is not set, we will retry forever. - :keyword interval_start: How long (in seconds) we start sleeping between - retries. - :keyword interval_step: By how much the interval is increased for each - retry. - :keyword interval_max: Maximum number of seconds to sleep between retries. - - """ - retries = 0 - interval_range = fxrange(interval_start, - interval_max + interval_start, - interval_step, repeatlast=True) - for retries in count(): - try: - return fun(*args, **kwargs) - except catch as exc: - if max_retries and retries >= max_retries: - raise - if callback: - callback() - tts = float(errback(exc, interval_range, retries) if errback - else next(interval_range)) - if tts: - for _ in range(int(tts)): - if callback: - callback() - sleep(1.0) - # sleep remainder after int truncation above. - sleep(abs(int(tts) - tts)) - - -def emergency_dump_state(state, open_file=open, dump=None): - from pprint import pformat - from tempfile import mktemp - - if dump is None: - import pickle - dump = pickle.dump - persist = mktemp() - say('EMERGENCY DUMP STATE TO FILE -> {0} <-', persist) - fh = open_file(persist, 'w') - try: - try: - dump(state, fh, protocol=0) - except Exception as exc: - say('Cannot pickle state: {0!r}. Fallback to pformat.', exc) - fh.write(default_encode(pformat(state))) - finally: - fh.flush() - fh.close() - return persist - - -class cached_property(object): - """Property descriptor that caches the return value - of the get function. - - *Examples* - - .. code-block:: python - - @cached_property - def connection(self): - return Connection() - - @connection.setter # Prepares stored value - def connection(self, value): - if value is None: - raise TypeError('Connection must be a connection') - return value - - @connection.deleter - def connection(self, value): - # Additional action to do at del(self.attr) - if value is not None: - print('Connection {0!r} deleted'.format(value) - - """ - - def __init__(self, fget=None, fset=None, fdel=None, doc=None): - self.__get = fget - self.__set = fset - self.__del = fdel - self.__doc__ = doc or fget.__doc__ - self.__name__ = fget.__name__ - self.__module__ = fget.__module__ - - def __get__(self, obj, type=None): - if obj is None: - return self - try: - return obj.__dict__[self.__name__] - except KeyError: - value = obj.__dict__[self.__name__] = self.__get(obj) - return value - - def __set__(self, obj, value): - if obj is None: - return self - if self.__set is not None: - value = self.__set(obj, value) - obj.__dict__[self.__name__] = value - - def __delete__(self, obj): - if obj is None: - return self - try: - value = obj.__dict__.pop(self.__name__) - except KeyError: - pass - else: - if self.__del is not None: - self.__del(obj, value) - - def setter(self, fset): - return self.__class__(self.__get, fset, self.__del) - - def deleter(self, fdel): - return self.__class__(self.__get, self.__set, fdel) - - -def reprkwargs(kwargs, sep=', ', fmt='{0}={1}'): - return sep.join(fmt.format(k, _safe_repr(v)) for k, v in items(kwargs)) - - -def reprcall(name, args=(), kwargs={}, sep=', '): - return '{0}({1}{2}{3})'.format( - name, sep.join(map(_safe_repr, args or ())), - (args and kwargs) and sep or '', - reprkwargs(kwargs, sep), - ) - - -@contextmanager -def nested(*managers): # pragma: no cover - # flake8: noqa - """Combine multiple context managers into a single nested - context manager.""" - exits = [] - vars = [] - exc = (None, None, None) - try: - try: - for mgr in managers: - exit = mgr.__exit__ - enter = mgr.__enter__ - vars.append(enter()) - exits.append(exit) - yield vars - except: - exc = sys.exc_info() - finally: - while exits: - exit = exits.pop() - try: - if exit(*exc): - exc = (None, None, None) - except: - exc = sys.exc_info() - if exc != (None, None, None): - # Don't rely on sys.exc_info() still containing - # the right information. Another exception may - # have been raised and caught by an exit method - reraise(exc[0], exc[1], exc[2]) - finally: - del(exc) - - -def shufflecycle(it): - it = list(it) # don't modify callers list - shuffle = random.shuffle - for _ in repeat(None): - shuffle(it) - yield it[0] - - -def entrypoints(namespace): - try: - from pkg_resources import iter_entry_points - except ImportError: - return iter([]) - return ((ep, ep.load()) for ep in iter_entry_points(namespace)) - - -class ChannelPromise(object): - - def __init__(self, contract): - self.__contract__ = contract - - def __call__(self): - try: - return self.__value__ - except AttributeError: - value = self.__value__ = self.__contract__() - return value - - def __repr__(self): - try: - return repr(self.__value__) - except AttributeError: - return '<promise: 0x{0:x}>'.format(id(self.__contract__)) - - -def escape_regex(p, white=''): - # what's up with re.escape? that code must be neglected or someting - return ''.join(c if c.isalnum() or c in white - else ('\\000' if c == '\000' else '\\' + c) - for c in p) - - -def fileno(f): - if isinstance(f, numbers.Integral): - return f - return f.fileno() - - -def maybe_fileno(f): - """Get object fileno, or :const:`None` if not defined.""" - try: - return fileno(f) - except FILENO_ERRORS: - pass diff --git a/awx/lib/site-packages/kombu/utils/amq_manager.py b/awx/lib/site-packages/kombu/utils/amq_manager.py deleted file mode 100644 index 7da5490631..0000000000 --- a/awx/lib/site-packages/kombu/utils/amq_manager.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import absolute_import - - -def get_manager(client, hostname=None, port=None, userid=None, - password=None): - import pyrabbit - opt = client.transport_options.get - - def get(name, val, default): - return (val if val is not None - else opt('manager_%s' % name) - or getattr(client, name, None) or default) - - host = get('hostname', hostname, 'localhost') - port = port if port is not None else opt('manager_port', 15672) - userid = get('userid', userid, 'guest') - password = get('password', password, 'guest') - return pyrabbit.Client('%s:%s' % (host, port), userid, password) diff --git a/awx/lib/site-packages/kombu/utils/compat.py b/awx/lib/site-packages/kombu/utils/compat.py deleted file mode 100644 index d0c3e6766f..0000000000 --- a/awx/lib/site-packages/kombu/utils/compat.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -kombu.utils.compat -================== - -Helps compatibility with older Python versions. - -""" -from __future__ import absolute_import - - -# ############# timedelta_seconds() -> delta.total_seconds ################### -from datetime import timedelta - -HAVE_TIMEDELTA_TOTAL_SECONDS = hasattr(timedelta, 'total_seconds') - - -if HAVE_TIMEDELTA_TOTAL_SECONDS: # pragma: no cover - - def timedelta_seconds(delta): - """Convert :class:`datetime.timedelta` to seconds. - - Doesn't account for negative values. - - """ - return max(delta.total_seconds(), 0) - -else: # pragma: no cover - - def timedelta_seconds(delta): # noqa - """Convert :class:`datetime.timedelta` to seconds. - - Doesn't account for negative values. - - """ - if delta.days < 0: - return 0 - return delta.days * 86400 + delta.seconds + (delta.microseconds / 10e5) - -# ############# socket.error.errno ########################################### - - -def get_errno(exc): - """:exc:`socket.error` and :exc:`IOError` first got - the ``.errno`` attribute in Py2.7""" - try: - return exc.errno - except AttributeError: - try: - # e.args = (errno, reason) - if isinstance(exc.args, tuple) and len(exc.args) == 2: - return exc.args[0] - except AttributeError: - pass - return 0 - -# ############# collections.OrderedDict ###################################### -try: - from collections import OrderedDict -except ImportError: - from ordereddict import OrderedDict # noqa diff --git a/awx/lib/site-packages/kombu/utils/debug.py b/awx/lib/site-packages/kombu/utils/debug.py deleted file mode 100644 index 8d08115b06..0000000000 --- a/awx/lib/site-packages/kombu/utils/debug.py +++ /dev/null @@ -1,65 +0,0 @@ -""" -kombu.utils.debug -================= - -Debugging support. - -""" -from __future__ import absolute_import - -import logging - -from functools import wraps - -from kombu.five import items -from kombu.log import get_logger - -__all__ = ['setup_logging', 'Logwrapped'] - - -def setup_logging(loglevel=logging.DEBUG, loggers=['kombu.connection', - 'kombu.channel']): - for logger in loggers: - l = get_logger(logger) - l.addHandler(logging.StreamHandler()) - l.setLevel(loglevel) - - -class Logwrapped(object): - __ignore = ('__enter__', '__exit__') - - def __init__(self, instance, logger=None, ident=None): - self.instance = instance - self.logger = get_logger(logger) - self.ident = ident - - def __getattr__(self, key): - meth = getattr(self.instance, key) - - if not callable(meth) or key in self.__ignore: - return meth - - @wraps(meth) - def __wrapped(*args, **kwargs): - info = '' - if self.ident: - info += self.ident.format(self.instance) - info += '{0.__name__}('.format(meth) - if args: - info += ', '.join(map(repr, args)) - if kwargs: - if args: - info += ', ' - info += ', '.join('{k}={v!r}'.format(k=key, v=value) - for key, value in items(kwargs)) - info += ')' - self.logger.debug(info) - return meth(*args, **kwargs) - - return __wrapped - - def __repr__(self): - return repr(self.instance) - - def __dir__(self): - return dir(self.instance) diff --git a/awx/lib/site-packages/kombu/utils/encoding.py b/awx/lib/site-packages/kombu/utils/encoding.py deleted file mode 100644 index d054257a3f..0000000000 --- a/awx/lib/site-packages/kombu/utils/encoding.py +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: utf-8 -*- -""" -kombu.utils.encoding -~~~~~~~~~~~~~~~~~~~~~ - -Utilities to encode text, and to safely emit text from running -applications without crashing with the infamous :exc:`UnicodeDecodeError` -exception. - -""" -from __future__ import absolute_import - -import sys -import traceback - -from kombu.five import text_t - -is_py3k = sys.version_info >= (3, 0) - -#: safe_str takes encoding from this file by default. -#: :func:`set_default_encoding_file` can used to set the -#: default output file. -default_encoding_file = None - - -def set_default_encoding_file(file): - global default_encoding_file - default_encoding_file = file - - -def get_default_encoding_file(): - return default_encoding_file - - -if sys.platform.startswith('java'): # pragma: no cover - - def default_encoding(file=None): - return 'utf-8' -else: - - def default_encoding(file=None): # noqa - file = file or get_default_encoding_file() - return getattr(file, 'encoding', None) or sys.getfilesystemencoding() - -if is_py3k: # pragma: no cover - - def str_to_bytes(s): - if isinstance(s, str): - return s.encode() - return s - - def bytes_to_str(s): - if isinstance(s, bytes): - return s.decode() - return s - - def from_utf8(s, *args, **kwargs): - return s - - def ensure_bytes(s): - if not isinstance(s, bytes): - return str_to_bytes(s) - return s - - def default_encode(obj): - return obj - - str_t = str - -else: - - def str_to_bytes(s): # noqa - if isinstance(s, unicode): - return s.encode() - return s - - def bytes_to_str(s): # noqa - return s - - def from_utf8(s, *args, **kwargs): # noqa - return s.encode('utf-8', *args, **kwargs) - - def default_encode(obj, file=None): # noqa - return unicode(obj, default_encoding(file)) - - str_t = unicode - ensure_bytes = str_to_bytes - - -try: - bytes_t = bytes -except NameError: # pragma: no cover - bytes_t = str # noqa - - -def safe_str(s, errors='replace'): - s = bytes_to_str(s) - if not isinstance(s, (text_t, bytes)): - return safe_repr(s, errors) - return _safe_str(s, errors) - - -if is_py3k: - - def _safe_str(s, errors='replace', file=None): - if isinstance(s, str): - return s - try: - return str(s) - except Exception as exc: - return '<Unrepresentable {0!r}: {1!r} {2!r}>'.format( - type(s), exc, '\n'.join(traceback.format_stack())) -else: - def _safe_str(s, errors='replace', file=None): # noqa - encoding = default_encoding(file) - try: - if isinstance(s, unicode): - return s.encode(encoding, errors) - return unicode(s, encoding, errors) - except Exception as exc: - return '<Unrepresentable {0!r}: {1!r} {2!r}>'.format( - type(s), exc, '\n'.join(traceback.format_stack())) - - -def safe_repr(o, errors='replace'): - try: - return repr(o) - except Exception: - return _safe_str(o, errors) diff --git a/awx/lib/site-packages/kombu/utils/eventio.py b/awx/lib/site-packages/kombu/utils/eventio.py deleted file mode 100644 index e4961cdc31..0000000000 --- a/awx/lib/site-packages/kombu/utils/eventio.py +++ /dev/null @@ -1,265 +0,0 @@ -""" -kombu.utils.eventio -=================== - -Evented IO support for multiple platforms. - -""" -from __future__ import absolute_import - -import errno -import select as __select__ -import socket - -from numbers import Integral - -_selectf = __select__.select -_selecterr = __select__.error -epoll = getattr(__select__, 'epoll', None) -kqueue = getattr(__select__, 'kqueue', None) -kevent = getattr(__select__, 'kevent', None) -KQ_EV_ADD = getattr(__select__, 'KQ_EV_ADD', 1) -KQ_EV_DELETE = getattr(__select__, 'KQ_EV_DELETE', 2) -KQ_EV_ENABLE = getattr(__select__, 'KQ_EV_ENABLE', 4) -KQ_EV_CLEAR = getattr(__select__, 'KQ_EV_CLEAR', 32) -KQ_EV_ERROR = getattr(__select__, 'KQ_EV_ERROR', 16384) -KQ_EV_EOF = getattr(__select__, 'KQ_EV_EOF', 32768) -KQ_FILTER_READ = getattr(__select__, 'KQ_FILTER_READ', -1) -KQ_FILTER_WRITE = getattr(__select__, 'KQ_FILTER_WRITE', -2) -KQ_FILTER_AIO = getattr(__select__, 'KQ_FILTER_AIO', -3) -KQ_FILTER_VNODE = getattr(__select__, 'KQ_FILTER_VNODE', -4) -KQ_FILTER_PROC = getattr(__select__, 'KQ_FILTER_PROC', -5) -KQ_FILTER_SIGNAL = getattr(__select__, 'KQ_FILTER_SIGNAL', -6) -KQ_FILTER_TIMER = getattr(__select__, 'KQ_FILTER_TIMER', -7) -KQ_NOTE_LOWAT = getattr(__select__, 'KQ_NOTE_LOWAT', 1) -KQ_NOTE_DELETE = getattr(__select__, 'KQ_NOTE_DELETE', 1) -KQ_NOTE_WRITE = getattr(__select__, 'KQ_NOTE_WRITE', 2) -KQ_NOTE_EXTEND = getattr(__select__, 'KQ_NOTE_EXTEND', 4) -KQ_NOTE_ATTRIB = getattr(__select__, 'KQ_NOTE_ATTRIB', 8) -KQ_NOTE_LINK = getattr(__select__, 'KQ_NOTE_LINK', 16) -KQ_NOTE_RENAME = getattr(__select__, 'KQ_NOTE_RENAME', 32) -KQ_NOTE_REVOKE = getattr(__select__, 'kQ_NOTE_REVOKE', 64) - - -from kombu.syn import detect_environment - -from . import fileno -from .compat import get_errno - -__all__ = ['poll'] - -READ = POLL_READ = 0x001 -WRITE = POLL_WRITE = 0x004 -ERR = POLL_ERR = 0x008 | 0x010 - -try: - SELECT_BAD_FD = set((errno.EBADF, errno.WSAENOTSOCK)) -except AttributeError: - SELECT_BAD_FD = set((errno.EBADF,)) - - -class Poller(object): - - def poll(self, timeout): - try: - return self._poll(timeout) - except Exception as exc: - if get_errno(exc) != errno.EINTR: - raise - - -class _epoll(Poller): - - def __init__(self): - self._epoll = epoll() - - def register(self, fd, events): - try: - self._epoll.register(fd, events) - except Exception as exc: - if get_errno(exc) != errno.EEXIST: - raise - - def unregister(self, fd): - try: - self._epoll.unregister(fd) - except (socket.error, ValueError, KeyError, TypeError): - pass - except (IOError, OSError) as exc: - if get_errno(exc) != errno.ENOENT: - raise - - def _poll(self, timeout): - return self._epoll.poll(timeout if timeout is not None else -1) - - def close(self): - self._epoll.close() - - -class _kqueue(Poller): - w_fflags = (KQ_NOTE_WRITE | KQ_NOTE_EXTEND | - KQ_NOTE_ATTRIB | KQ_NOTE_DELETE) - - def __init__(self): - self._kqueue = kqueue() - self._active = {} - self.on_file_change = None - self._kcontrol = self._kqueue.control - - def register(self, fd, events): - self._control(fd, events, KQ_EV_ADD) - self._active[fd] = events - - def unregister(self, fd): - events = self._active.pop(fd, None) - if events: - try: - self._control(fd, events, KQ_EV_DELETE) - except socket.error: - pass - - def watch_file(self, fd): - ev = kevent(fd, - filter=KQ_FILTER_VNODE, - flags=KQ_EV_ADD | KQ_EV_ENABLE | KQ_EV_CLEAR, - fflags=self.w_fflags) - self._kcontrol([ev], 0) - - def unwatch_file(self, fd): - ev = kevent(fd, - filter=KQ_FILTER_VNODE, - flags=KQ_EV_DELETE, - fflags=self.w_fflags) - self._kcontrol([ev], 0) - - def _control(self, fd, events, flags): - if not events: - return - kevents = [] - if events & WRITE: - kevents.append(kevent(fd, - filter=KQ_FILTER_WRITE, - flags=flags)) - if not kevents or events & READ: - kevents.append( - kevent(fd, filter=KQ_FILTER_READ, flags=flags), - ) - control = self._kcontrol - for e in kevents: - try: - control([e], 0) - except ValueError: - pass - - def _poll(self, timeout): - kevents = self._kcontrol(None, 1000, timeout) - events, file_changes = {}, [] - for k in kevents: - fd = k.ident - if k.filter == KQ_FILTER_READ: - events[fd] = events.get(fd, 0) | READ - elif k.filter == KQ_FILTER_WRITE: - if k.flags & KQ_EV_EOF: - events[fd] = ERR - else: - events[fd] = events.get(fd, 0) | WRITE - elif k.filter == KQ_EV_ERROR: - events[fd] = events.get(fd, 0) | ERR - elif k.filter == KQ_FILTER_VNODE: - if k.fflags & KQ_NOTE_DELETE: - self.unregister(fd) - file_changes.append(k) - if file_changes: - self.on_file_change(file_changes) - return list(events.items()) - - def close(self): - self._kqueue.close() - - -class _select(Poller): - - def __init__(self): - self._all = (self._rfd, - self._wfd, - self._efd) = set(), set(), set() - - def register(self, fd, events): - fd = fileno(fd) - if events & ERR: - self._efd.add(fd) - if events & WRITE: - self._wfd.add(fd) - if events & READ: - self._rfd.add(fd) - - def _remove_bad(self): - for fd in self._rfd | self._wfd | self._efd: - try: - _selectf([fd], [], [], 0) - except (_selecterr, socket.error) as exc: - if get_errno(exc) in SELECT_BAD_FD: - self.unregister(fd) - - def unregister(self, fd): - try: - fd = fileno(fd) - except socket.error as exc: - # we don't know the previous fd of this object - # but it will be removed by the next poll iteration. - if get_errno(exc) in SELECT_BAD_FD: - return - raise - self._rfd.discard(fd) - self._wfd.discard(fd) - self._efd.discard(fd) - - def _poll(self, timeout): - try: - read, write, error = _selectf( - self._rfd, self._wfd, self._efd, timeout, - ) - except (_selecterr, socket.error) as exc: - if get_errno(exc) == errno.EINTR: - return - elif get_errno(exc) in SELECT_BAD_FD: - return self._remove_bad() - raise - - events = {} - for fd in read: - if not isinstance(fd, Integral): - fd = fd.fileno() - events[fd] = events.get(fd, 0) | READ - for fd in write: - if not isinstance(fd, Integral): - fd = fd.fileno() - events[fd] = events.get(fd, 0) | WRITE - for fd in error: - if not isinstance(fd, Integral): - fd = fd.fileno() - events[fd] = events.get(fd, 0) | ERR - return list(events.items()) - - def close(self): - self._rfd.clear() - self._wfd.clear() - self._efd.clear() - - -def _get_poller(): - if detect_environment() != 'default': - # greenlet - return _select - elif epoll: - # Py2.6+ Linux - return _epoll - elif kqueue: - # Py2.6+ on BSD / Darwin - return _select # was: _kqueue - else: - return _select - - -def poll(*args, **kwargs): - return _get_poller()(*args, **kwargs) diff --git a/awx/lib/site-packages/kombu/utils/functional.py b/awx/lib/site-packages/kombu/utils/functional.py deleted file mode 100644 index 746f42faf0..0000000000 --- a/awx/lib/site-packages/kombu/utils/functional.py +++ /dev/null @@ -1,82 +0,0 @@ -from __future__ import absolute_import - -import sys - -from collections import Iterable, Mapping - -from kombu.five import string_t - -__all__ = ['lazy', 'maybe_evaluate', 'is_list', 'maybe_list'] - - -class lazy(object): - """Holds lazy evaluation. - - Evaluated when called or if the :meth:`evaluate` method is called. - The function is re-evaluated on every call. - - Overloaded operations that will evaluate the promise: - :meth:`__str__`, :meth:`__repr__`, :meth:`__cmp__`. - - """ - - def __init__(self, fun, *args, **kwargs): - self._fun = fun - self._args = args - self._kwargs = kwargs - - def __call__(self): - return self.evaluate() - - def evaluate(self): - return self._fun(*self._args, **self._kwargs) - - def __str__(self): - return str(self()) - - def __repr__(self): - return repr(self()) - - def __eq__(self, rhs): - return self() == rhs - - def __ne__(self, rhs): - return self() != rhs - - def __deepcopy__(self, memo): - memo[id(self)] = self - return self - - def __reduce__(self): - return (self.__class__, (self._fun, ), {'_args': self._args, - '_kwargs': self._kwargs}) - - if sys.version_info[0] < 3: - - def __cmp__(self, rhs): - if isinstance(rhs, self.__class__): - return -cmp(rhs, self()) - return cmp(self(), rhs) - - -def maybe_evaluate(value): - """Evaluates if the value is a :class:`lazy` instance.""" - if isinstance(value, lazy): - return value.evaluate() - return value - - -def is_list(l, scalars=(Mapping, string_t), iters=(Iterable, )): - """Return true if the object is iterable (but not - if object is a mapping or string).""" - return isinstance(l, iters) and not isinstance(l, scalars or ()) - - -def maybe_list(l, scalars=(Mapping, string_t)): - """Return list of one element if ``l`` is a scalar.""" - return l if l is None or is_list(l, scalars) else [l] - - -# Compat names (before kombu 3.0) -promise = lazy -maybe_promise = maybe_evaluate diff --git a/awx/lib/site-packages/kombu/utils/limits.py b/awx/lib/site-packages/kombu/utils/limits.py deleted file mode 100644 index 48eb536809..0000000000 --- a/awx/lib/site-packages/kombu/utils/limits.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -kombu.utils.limits -================== - -Token bucket implementation for rate limiting. - -""" -from __future__ import absolute_import - -from kombu.five import monotonic - -__all__ = ['TokenBucket'] - - -class TokenBucket(object): - """Token Bucket Algorithm. - - See http://en.wikipedia.org/wiki/Token_Bucket - Most of this code was stolen from an entry in the ASPN Python Cookbook: - http://code.activestate.com/recipes/511490/ - - .. admonition:: Thread safety - - This implementation may not be thread safe. - - """ - - #: The rate in tokens/second that the bucket will be refilled. - fill_rate = None - - #: Maximum number of tokens in the bucket. - capacity = 1 - - #: Timestamp of the last time a token was taken out of the bucket. - timestamp = None - - def __init__(self, fill_rate, capacity=1): - self.capacity = float(capacity) - self._tokens = capacity - self.fill_rate = float(fill_rate) - self.timestamp = monotonic() - - def can_consume(self, tokens=1): - """Return :const:`True` if the number of tokens can be consumed - from the bucket.""" - if tokens <= self._get_tokens(): - self._tokens -= tokens - return True - return False - - def expected_time(self, tokens=1): - """Return the time (in seconds) when a new token is expected - to be available. - - This will also consume a token from the bucket. - - """ - _tokens = self._get_tokens() - tokens = max(tokens, _tokens) - return (tokens - _tokens) / self.fill_rate - - def _get_tokens(self): - if self._tokens < self.capacity: - now = monotonic() - delta = self.fill_rate * (now - self.timestamp) - self._tokens = min(self.capacity, self._tokens + delta) - self.timestamp = now - return self._tokens diff --git a/awx/lib/site-packages/kombu/utils/text.py b/awx/lib/site-packages/kombu/utils/text.py deleted file mode 100644 index 066b28affb..0000000000 --- a/awx/lib/site-packages/kombu/utils/text.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import - -from difflib import SequenceMatcher - -from kombu import version_info_t -from kombu.five import string_t - - -def fmatch_iter(needle, haystack, min_ratio=0.6): - for key in haystack: - ratio = SequenceMatcher(None, needle, key).ratio() - if ratio >= min_ratio: - yield ratio, key - - -def fmatch_best(needle, haystack, min_ratio=0.6): - try: - return sorted( - fmatch_iter(needle, haystack, min_ratio), reverse=True, - )[0][1] - except IndexError: - pass - - -def version_string_as_tuple(s): - v = _unpack_version(*s.split('.')) - # X.Y.3a1 -> (X, Y, 3, 'a1') - if isinstance(v.micro, string_t): - v = version_info_t(v.major, v.minor, *_splitmicro(*v[2:])) - # X.Y.3a1-40 -> (X, Y, 3, 'a1', '40') - if not v.serial and v.releaselevel and '-' in v.releaselevel: - v = version_info_t(*list(v[0:3]) + v.releaselevel.split('-')) - return v - - -def _unpack_version(major, minor=0, micro=0, releaselevel='', serial=''): - return version_info_t(int(major), int(minor), micro, releaselevel, serial) - - -def _splitmicro(micro, releaselevel='', serial=''): - for index, char in enumerate(micro): - if not char.isdigit(): - break - else: - return int(micro or 0), releaselevel, serial - return int(micro[:index]), micro[index:], serial diff --git a/awx/lib/site-packages/kombu/utils/url.py b/awx/lib/site-packages/kombu/utils/url.py deleted file mode 100644 index f93282d3a9..0000000000 --- a/awx/lib/site-packages/kombu/utils/url.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import absolute_import - -from functools import partial - -try: - from urllib.parse import parse_qsl, quote, unquote, urlparse -except ImportError: - from urllib import quote, unquote # noqa - from urlparse import urlparse, parse_qsl # noqa - -from . import kwdict -from kombu.five import string_t - -safequote = partial(quote, safe='') - - -def _parse_url(url): - scheme = urlparse(url).scheme - schemeless = url[len(scheme) + 3:] - # parse with HTTP URL semantics - parts = urlparse('http://' + schemeless) - path = parts.path or '' - path = path[1:] if path and path[0] == '/' else path - return (scheme, unquote(parts.hostname or '') or None, parts.port, - unquote(parts.username or '') or None, - unquote(parts.password or '') or None, - unquote(path or '') or None, - kwdict(dict(parse_qsl(parts.query)))) - - -def parse_url(url): - scheme, host, port, user, password, path, query = _parse_url(url) - return dict(transport=scheme, hostname=host, - port=port, userid=user, - password=password, virtual_host=path, **query) - - -def as_url(scheme, host=None, port=None, user=None, password=None, - path=None, query=None, sanitize=False, mask='**'): - parts = ['{0}://'.format(scheme)] - if user or password: - if user: - parts.append(safequote(user)) - if password: - if sanitize: - parts.extend([':', mask] if mask else [':']) - else: - parts.extend([':', safequote(password)]) - parts.append('@') - parts.append(safequote(host) if host else '') - if port: - parts.extend([':', port]) - parts.extend(['/', path]) - return ''.join(str(part) for part in parts if part) - - -def sanitize_url(url, mask='**'): - return as_url(*_parse_url(url), sanitize=True, mask=mask) - - -def maybe_sanitize_url(url, mask='**'): - if isinstance(url, string_t) and '://' in url: - return sanitize_url(url, mask) - return url diff --git a/awx/lib/site-packages/libcloud/__init__.py b/awx/lib/site-packages/libcloud/__init__.py deleted file mode 100644 index 3ce79f0b20..0000000000 --- a/awx/lib/site-packages/libcloud/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -libcloud provides a unified interface to the cloud computing resources. - -:var __version__: Current version of libcloud -""" - -__all__ = ['__version__', 'enable_debug'] -__version__ = '0.15.1' - -import os - -try: - import paramiko - have_paramiko = True -except ImportError: - have_paramiko = False - - -def enable_debug(fo): - """ - Enable library wide debugging to a file-like object. - - :param fo: Where to append debugging information - :type fo: File like object, only write operations are used. - """ - from libcloud.common.base import (Connection, - LoggingHTTPConnection, - LoggingHTTPSConnection) - LoggingHTTPSConnection.log = fo - LoggingHTTPConnection.log = fo - Connection.conn_classes = (LoggingHTTPConnection, - LoggingHTTPSConnection) - - -def _init_once(): - """ - Utility function that is ran once on Library import. - - This checks for the LIBCLOUD_DEBUG environment variable, which if it exists - is where we will log debug information about the provider transports. - """ - path = os.getenv('LIBCLOUD_DEBUG') - if path: - fo = open(path, 'a') - enable_debug(fo) - - if have_paramiko: - paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG) - -_init_once() diff --git a/awx/lib/site-packages/libcloud/common/__init__.py b/awx/lib/site-packages/libcloud/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/common/abiquo.py b/awx/lib/site-packages/libcloud/common/abiquo.py deleted file mode 100644 index f621b2aa5c..0000000000 --- a/awx/lib/site-packages/libcloud/common/abiquo.py +++ /dev/null @@ -1,260 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Abiquo Utilities Module for the Abiquo Driver. - -Common utilities needed by the :class:`AbiquoNodeDriver`. -""" -import base64 - -from libcloud.common.base import ConnectionUserAndKey, PollingConnection -from libcloud.common.base import XmlResponse -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import b -from libcloud.compute.base import NodeState - - -def get_href(element, rel): - """ - Search a RESTLink element in the :class:`AbiquoResponse`. - - Abiquo, as a REST API, it offers self-discovering functionality. - That means that you could walk through the whole API only - navigating from the links offered by the entities. - - This is a basic method to find the 'relations' of an entity searching into - its links. - - For instance, a Rack entity serialized as XML as the following:: - - <?xml version="1.0" encoding="UTF-8" standalone="yes"?> - <rack> - <link href="http://host/api/admin/datacenters/1" - type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://host/api/admin/datacenters/1/racks/1" - type="application/vnd.abiquo.rack+xml" rel="edit"/> - <link href="http://host/api/admin/datacenters/1/racks/1/machines" - type="application/vnd.abiquo.machines+xml" rel="machines"/> - <haEnabled>false</haEnabled> - <id>1</id> - <longDescription></longDescription> - <name>racacaca</name> - <nrsq>10</nrsq> - <shortDescription></shortDescription> - <vlanIdMax>4094</vlanIdMax> - <vlanIdMin>2</vlanIdMin> - <vlanPerVdcReserved>1</vlanPerVdcReserved> - <vlansIdAvoided></vlansIdAvoided> - </rack> - - offers link to datacenters (rel='datacenter'), to itself (rel='edit') and - to the machines defined in it (rel='machines') - - A call to this method with the 'rack' element using 'datacenter' as 'rel' - will return: - - 'http://10.60.12.7:80/api/admin/datacenters/1' - - :type element: :class:`xml.etree.ElementTree` - :param element: Xml Entity returned by Abiquo API (required) - :type rel: ``str`` - :param rel: relation link name - :rtype: ``str`` - :return: the 'href' value according to the 'rel' input parameter - """ - links = element.findall('link') - for link in links: - if link.attrib['rel'] == rel: - href = link.attrib['href'] - # href is something like: - # - # 'http://localhost:80/api/admin/enterprises' - # - # we are only interested in '/admin/enterprises/' part - needle = '/api/' - url_path = urlparse.urlparse(href).path - index = url_path.find(needle) - result = url_path[index + len(needle) - 1:] - return result - - -class AbiquoResponse(XmlResponse): - """ - Abiquo XML Response. - - Wraps the response in XML bodies or extract the error data in - case of error. - """ - - # Map between abiquo state and Libcloud State - NODE_STATE_MAP = { - 'NOT_ALLOCATED': NodeState.TERMINATED, - 'ALLOCATED': NodeState.PENDING, - 'CONFIGURED': NodeState.PENDING, - 'ON': NodeState.RUNNING, - 'PAUSED': NodeState.PENDING, - 'OFF': NodeState.PENDING, - 'LOCKED': NodeState.PENDING, - 'UNKNOWN': NodeState.UNKNOWN - } - - def parse_error(self): - """ - Parse the error messages. - - Response body can easily be handled by this class parent - :class:`XmlResponse`, but there are use cases which Abiquo API - does not respond an XML but an HTML. So we need to - handle these special cases. - """ - if self.status == httplib.UNAUTHORIZED: - raise InvalidCredsError(driver=self.connection.driver) - elif self.status == httplib.FORBIDDEN: - raise ForbiddenError(self.connection.driver) - else: - errors = self.parse_body().findall('error') - # Most of the exceptions only have one error - raise LibcloudError(errors[0].findtext('message')) - - def success(self): - """ - Determine if the request was successful. - - Any of the 2XX HTTP response codes are accepted as successfull requests - - :rtype: ``bool`` - :return: successful request or not. - """ - return self.status in [httplib.OK, httplib.CREATED, httplib.NO_CONTENT, - httplib.ACCEPTED] - - def async_success(self): - """ - Determinate if async request was successful. - - An async_request retrieves for a task object that can be successfully - retrieved (self.status == OK), but the asyncronous task (the body of - the HTTP response) which we are asking for has finished with an error. - So this method checks if the status code is 'OK' and if the task - has finished successfully. - - :rtype: ``bool`` - :return: successful asynchronous request or not - """ - if self.success(): - # So we have a 'task' object in the body - task = self.parse_body() - return task.findtext('state') == 'FINISHED_SUCCESSFULLY' - else: - return False - - -class AbiquoConnection(ConnectionUserAndKey, PollingConnection): - """ - A Connection to Abiquo API. - - Basic :class:`ConnectionUserAndKey` connection with - :class:`PollingConnection` features for asynchronous tasks. - """ - - responseCls = AbiquoResponse - - def __init__(self, user_id, key, secure=True, host=None, port=None, - url=None, timeout=None): - super(AbiquoConnection, self).__init__(user_id=user_id, key=key, - secure=secure, - host=host, port=port, - url=url, timeout=timeout) - - # This attribute stores data cached across multiple request - self.cache = {} - - def add_default_headers(self, headers): - """ - Add Basic Authentication header to all the requests. - - It injects the 'Authorization: Basic Base64String===' header - in each request - - :type headers: ``dict`` - :param headers: Default input headers - :rtype ``dict`` - :return: Default input headers with the 'Authorization' - header - """ - b64string = b('%s:%s' % (self.user_id, self.key)) - encoded = base64.b64encode(b64string).decode('utf-8') - - authorization = 'Basic ' + encoded - - headers['Authorization'] = authorization - return headers - - def get_poll_request_kwargs(self, response, context, request_kwargs): - """ - Manage polling request arguments. - - Return keyword arguments which are passed to the - :class:`NodeDriver.request` method when polling for the job status. The - Abiquo Asynchronous Response returns and 'acceptedrequest' XmlElement - as the following:: - - <acceptedrequest> - <link href="http://uri/to/task" rel="status"/> - <message>You can follow the progress in the link</message> - </acceptedrequest> - - We need to extract the href URI to poll. - - :type response: :class:`xml.etree.ElementTree` - :keyword response: Object returned by poll request. - :type request_kwargs: ``dict`` - :keyword request_kwargs: Default request arguments and headers - :rtype: ``dict`` - :return: Modified keyword arguments - """ - accepted_request_obj = response.object - link_poll = get_href(accepted_request_obj, 'status') - - # Override just the 'action' and 'method' keys of the previous dict - request_kwargs['action'] = link_poll - request_kwargs['method'] = 'GET' - return request_kwargs - - def has_completed(self, response): - """ - Decide if the asynchronous job has ended. - - :type response: :class:`xml.etree.ElementTree` - :param response: Response object returned by poll request - :rtype: ``bool`` - :return: Whether the job has completed - """ - task = response.object - task_state = task.findtext('state') - return task_state in ['FINISHED_SUCCESSFULLY', 'ABORTED', - 'FINISHED_UNSUCCESSFULLY'] - - -class ForbiddenError(LibcloudError): - """ - Exception used when credentials are ok but user has not permissions. - """ - - def __init__(self, driver): - message = 'User has not permission to perform this task.' - super(LibcloudError, self).__init__(message, driver) diff --git a/awx/lib/site-packages/libcloud/common/aws.py b/awx/lib/site-packages/libcloud/common/aws.py deleted file mode 100644 index 1d3dfb45fb..0000000000 --- a/awx/lib/site-packages/libcloud/common/aws.py +++ /dev/null @@ -1,193 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import hmac -import time -from hashlib import sha256 - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.common.base import ConnectionUserAndKey, XmlResponse, BaseDriver -from libcloud.common.types import InvalidCredsError, MalformedResponseError -from libcloud.utils.py3 import b, httplib, urlquote -from libcloud.utils.xml import findtext, findall - - -class AWSBaseResponse(XmlResponse): - namespace = None - - def _parse_error_details(self, element): - """ - Parse code and message from the provided error element. - - :return: ``tuple`` with two elements: (code, message) - :rtype: ``tuple`` - """ - code = findtext(element=element, xpath='Code', - namespace=self.namespace) - message = findtext(element=element, xpath='Message', - namespace=self.namespace) - - return code, message - - -class AWSGenericResponse(AWSBaseResponse): - # There are multiple error messages in AWS, but they all have an Error node - # with Code and Message child nodes. Xpath to select them - # None if the root node *is* the Error node - xpath = None - - # This dict maps <Error><Code>CodeName</Code></Error> to a specific - # exception class that is raised immediately. - # If a custom exception class is not defined, errors are accumulated and - # returned from the parse_error method. - expections = {} - - def success(self): - return self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] - - def parse_error(self): - context = self.connection.context - status = int(self.status) - - # FIXME: Probably ditch this as the forbidden message will have - # corresponding XML. - if status == httplib.FORBIDDEN: - if not self.body: - raise InvalidCredsError(str(self.status) + ': ' + self.error) - else: - raise InvalidCredsError(self.body) - - try: - body = ET.XML(self.body) - except Exception: - raise MalformedResponseError('Failed to parse XML', - body=self.body, - driver=self.connection.driver) - - if self.xpath: - errs = findall(element=body, xpath=self.xpath, - namespace=self.namespace) - else: - errs = [body] - - msgs = [] - for err in errs: - code, message = self._parse_error_details(element=err) - exceptionCls = self.exceptions.get(code, None) - - if exceptionCls is None: - msgs.append('%s: %s' % (code, message)) - continue - - # Custom exception class is defined, immediately throw an exception - params = {} - if hasattr(exceptionCls, 'kwargs'): - for key in exceptionCls.kwargs: - if key in context: - params[key] = context[key] - - raise exceptionCls(value=message, driver=self.connection.driver, - **params) - - return "\n".join(msgs) - - -class AWSTokenConnection(ConnectionUserAndKey): - def __init__(self, user_id, key, secure=True, - host=None, port=None, url=None, timeout=None, token=None): - self.token = token - super(AWSTokenConnection, self).__init__(user_id, key, secure=secure, - host=host, port=port, url=url, - timeout=timeout) - - def add_default_params(self, params): - # Even though we are adding it to the headers, we need it here too - # so that the token is added to the signature. - if self.token: - params['x-amz-security-token'] = self.token - return super(AWSTokenConnection, self).add_default_params(params) - - def add_default_headers(self, headers): - if self.token: - headers['x-amz-security-token'] = self.token - return super(AWSTokenConnection, self).add_default_headers(headers) - - -class SignedAWSConnection(AWSTokenConnection): - - def add_default_params(self, params): - params['SignatureVersion'] = '2' - params['SignatureMethod'] = 'HmacSHA256' - params['AWSAccessKeyId'] = self.user_id - params['Version'] = self.version - params['Timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', - time.gmtime()) - params['Signature'] = self._get_aws_auth_param(params, self.key, - self.action) - return params - - def _get_aws_auth_param(self, params, secret_key, path='/'): - """ - Creates the signature required for AWS, per - http://bit.ly/aR7GaQ [docs.amazonwebservices.com]: - - StringToSign = HTTPVerb + "\n" + - ValueOfHostHeaderInLowercase + "\n" + - HTTPRequestURI + "\n" + - CanonicalizedQueryString <from the preceding step> - """ - keys = list(params.keys()) - keys.sort() - pairs = [] - for key in keys: - value = str(params[key]) - pairs.append(urlquote(key, safe='') + '=' + - urlquote(value, safe='-_~')) - - qs = '&'.join(pairs) - - hostname = self.host - if (self.secure and self.port != 443) or \ - (not self.secure and self.port != 80): - hostname += ":" + str(self.port) - - string_to_sign = '\n'.join(('GET', hostname, path, qs)) - - b64_hmac = base64.b64encode( - hmac.new(b(secret_key), b(string_to_sign), - digestmod=sha256).digest() - ) - - return b64_hmac.decode('utf-8') - - -class AWSDriver(BaseDriver): - def __init__(self, key, secret=None, secure=True, host=None, port=None, - api_version=None, region=None, token=None, **kwargs): - self.token = token - super(AWSDriver, self).__init__(key, secret=secret, secure=secure, - host=host, port=port, - api_version=api_version, region=region, - token=token, **kwargs) - - def _ex_connection_class_kwargs(self): - kwargs = super(AWSDriver, self)._ex_connection_class_kwargs() - kwargs['token'] = self.token - return kwargs diff --git a/awx/lib/site-packages/libcloud/common/azure.py b/awx/lib/site-packages/libcloud/common/azure.py deleted file mode 100644 index 104cca817b..0000000000 --- a/awx/lib/site-packages/libcloud/common/azure.py +++ /dev/null @@ -1,189 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -import time -import base64 -import hmac - -from hashlib import sha256 - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b -from libcloud.utils.xml import fixxpath - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.common.types import InvalidCredsError -from libcloud.common.types import LibcloudError, MalformedResponseError -from libcloud.common.base import ConnectionUserAndKey, RawResponse -from libcloud.common.base import XmlResponse - -# Azure API version -API_VERSION = '2012-02-12' - -# The time format for headers in Azure requests -AZURE_TIME_FORMAT = '%a, %d %b %Y %H:%M:%S GMT' - - -class AzureResponse(XmlResponse): - - valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT, - httplib.BAD_REQUEST] - - def success(self): - i = int(self.status) - return i >= 200 and i <= 299 or i in self.valid_response_codes - - def parse_error(self, msg=None): - error_msg = 'Unknown error' - - try: - # Azure does give some meaningful errors, but is inconsistent - # Some APIs respond with an XML error. Others just dump HTML - body = self.parse_body() - - if type(body) == ET.Element: - code = body.findtext(fixxpath(xpath='Code')) - message = body.findtext(fixxpath(xpath='Message')) - message = message.split('\n')[0] - error_msg = '%s: %s' % (code, message) - - except MalformedResponseError: - pass - - if msg: - error_msg = '%s - %s' % (msg, error_msg) - - if self.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]: - raise InvalidCredsError(error_msg) - - raise LibcloudError('%s Status code: %d.' % (error_msg, self.status), - driver=self) - - -class AzureRawResponse(RawResponse): - pass - - -class AzureConnection(ConnectionUserAndKey): - """ - Represents a single connection to Azure - """ - - responseCls = AzureResponse - rawResponseCls = AzureRawResponse - - def add_default_params(self, params): - return params - - def pre_connect_hook(self, params, headers): - headers = copy.deepcopy(headers) - - # We have to add a date header in GMT - headers['x-ms-date'] = time.strftime(AZURE_TIME_FORMAT, time.gmtime()) - headers['x-ms-version'] = API_VERSION - - # Add the authorization header - headers['Authorization'] = self._get_azure_auth_signature( - method=self.method, headers=headers, params=params, - account=self.user_id, secret_key=self.key, path=self.action) - - # Azure cribs about this in 'raw' connections - headers.pop('Host', None) - - return params, headers - - def _get_azure_auth_signature(self, method, headers, params, - account, secret_key, path='/'): - """ - Signature = Base64( HMAC-SHA1( YourSecretAccessKeyID, - UTF-8-Encoding-Of( StringToSign ) ) ) ); - - StringToSign = HTTP-VERB + "\n" + - Content-Encoding + "\n" + - Content-Language + "\n" + - Content-Length + "\n" + - Content-MD5 + "\n" + - Content-Type + "\n" + - Date + "\n" + - If-Modified-Since + "\n" + - If-Match + "\n" + - If-None-Match + "\n" + - If-Unmodified-Since + "\n" + - Range + "\n" + - CanonicalizedHeaders + - CanonicalizedResource; - """ - special_header_values = [] - xms_header_values = [] - param_list = [] - special_header_keys = ['content-encoding', 'content-language', - 'content-length', 'content-md5', - 'content-type', 'date', 'if-modified-since', - 'if-match', 'if-none-match', - 'if-unmodified-since', 'range'] - - # Split the x-ms headers and normal headers and make everything - # lower case - headers_copy = {} - for header, value in headers.items(): - header = header.lower() - value = str(value).strip() - if header.startswith('x-ms-'): - xms_header_values.append((header, value)) - else: - headers_copy[header] = value - - # Get the values for the headers in the specific order - for header in special_header_keys: - header = header.lower() # Just for safety - if header in headers_copy: - special_header_values.append(headers_copy[header]) - else: - special_header_values.append('') - - # Prepare the first section of the string to be signed - values_to_sign = [method] + special_header_values - # string_to_sign = '\n'.join([method] + special_header_values) - - # The x-ms-* headers have to be in lower case and sorted - xms_header_values.sort() - - for header, value in xms_header_values: - values_to_sign.append('%s:%s' % (header, value)) - - # Add the canonicalized path - values_to_sign.append('/%s%s' % (account, path)) - - # URL query parameters (sorted and lower case) - for key, value in params.items(): - param_list.append((key.lower(), str(value).strip())) - - param_list.sort() - - for key, value in param_list: - values_to_sign.append('%s:%s' % (key, value)) - - string_to_sign = b('\n'.join(values_to_sign)) - secret_key = b(secret_key) - b64_hmac = base64.b64encode( - hmac.new(secret_key, string_to_sign, digestmod=sha256).digest() - ) - - return 'SharedKey %s:%s' % (self.user_id, b64_hmac.decode('utf-8')) diff --git a/awx/lib/site-packages/libcloud/common/base.py b/awx/lib/site-packages/libcloud/common/base.py deleted file mode 100644 index a42f228243..0000000000 --- a/awx/lib/site-packages/libcloud/common/base.py +++ /dev/null @@ -1,968 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys -import ssl -import copy -import binascii -import time - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from pipes import quote as pquote - -try: - import simplejson as json -except: - import json - -import libcloud - -from libcloud.utils.py3 import PY3, PY25 -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import urlencode -from libcloud.utils.py3 import StringIO -from libcloud.utils.py3 import u -from libcloud.utils.py3 import b - -from libcloud.utils.misc import lowercase_keys -from libcloud.utils.compression import decompress_data -from libcloud.common.types import LibcloudError, MalformedResponseError - -from libcloud.httplib_ssl import LibcloudHTTPSConnection - -LibcloudHTTPConnection = httplib.HTTPConnection - - -class HTTPResponse(httplib.HTTPResponse): - # On python 2.6 some calls can hang because HEAD isn't quite properly - # supported. - # In particular this happens on S3 when calls are made to get_object to - # objects that don't exist. - # This applies the behaviour from 2.7, fixing the hangs. - def read(self, amt=None): - if self.fp is None: - return '' - - if self._method == 'HEAD': - self.close() - return '' - - return httplib.HTTPResponse.read(self, amt) - - -class Response(object): - """ - A base Response class to derive from. - """ - - status = httplib.OK # Response status code - headers = {} # Response headers - body = None # Raw response body - object = None # Parsed response body - - error = None # Reason returned by the server. - connection = None # Parent connection class - parse_zero_length_body = False - - def __init__(self, response, connection): - """ - :param response: HTTP response object. (optional) - :type response: :class:`httplib.HTTPResponse` - - :param connection: Parent connection object. - :type connection: :class:`.Connection` - """ - self.connection = connection - - # http.client In Python 3 doesn't automatically lowercase the header - # names - self.headers = lowercase_keys(dict(response.getheaders())) - self.error = response.reason - self.status = response.status - - # This attribute is set when using LoggingConnection. - original_data = getattr(response, '_original_data', None) - - if original_data: - # LoggingConnection already decompresses data so it can log it - # which means we don't need to decompress it here. - self.body = response._original_data - else: - self.body = self._decompress_response(body=response.read(), - headers=self.headers) - - if PY3: - self.body = b(self.body).decode('utf-8') - - if not self.success(): - raise Exception(self.parse_error()) - - self.object = self.parse_body() - - def parse_body(self): - """ - Parse response body. - - Override in a provider's subclass. - - :return: Parsed body. - :rtype: ``str`` - """ - return self.body - - def parse_error(self): - """ - Parse the error messages. - - Override in a provider's subclass. - - :return: Parsed error. - :rtype: ``str`` - """ - return self.body - - def success(self): - """ - Determine if our request was successful. - - The meaning of this can be arbitrary; did we receive OK status? Did - the node get created? Were we authenticated? - - :rtype: ``bool`` - :return: ``True`` or ``False`` - """ - return self.status in [httplib.OK, httplib.CREATED] - - def _decompress_response(self, body, headers): - """ - Decompress a response body if it is using deflate or gzip encoding. - - :param body: Response body. - :type body: ``str`` - - :param headers: Response headers. - :type headers: ``dict`` - - :return: Decompressed response - :rtype: ``str`` - """ - encoding = headers.get('content-encoding', None) - - if encoding in ['zlib', 'deflate']: - body = decompress_data('zlib', body) - elif encoding in ['gzip', 'x-gzip']: - body = decompress_data('gzip', body) - else: - body = body.strip() - - return body - - -class JsonResponse(Response): - """ - A Base JSON Response class to derive from. - """ - - def parse_body(self): - if len(self.body) == 0 and not self.parse_zero_length_body: - return self.body - - try: - body = json.loads(self.body) - except: - raise MalformedResponseError( - 'Failed to parse JSON', - body=self.body, - driver=self.connection.driver) - return body - - parse_error = parse_body - - -class XmlResponse(Response): - """ - A Base XML Response class to derive from. - """ - - def parse_body(self): - if len(self.body) == 0 and not self.parse_zero_length_body: - return self.body - - try: - body = ET.XML(self.body) - except: - raise MalformedResponseError('Failed to parse XML', - body=self.body, - driver=self.connection.driver) - return body - - parse_error = parse_body - - -class RawResponse(Response): - - def __init__(self, connection): - """ - :param connection: Parent connection object. - :type connection: :class:`.Connection` - """ - self._status = None - self._response = None - self._headers = {} - self._error = None - self._reason = None - self.connection = connection - - @property - def response(self): - if not self._response: - response = self.connection.connection.getresponse() - self._response, self.body = response, response - if not self.success(): - self.parse_error() - return self._response - - @property - def status(self): - if not self._status: - self._status = self.response.status - return self._status - - @property - def headers(self): - if not self._headers: - self._headers = lowercase_keys(dict(self.response.getheaders())) - return self._headers - - @property - def reason(self): - if not self._reason: - self._reason = self.response.reason - return self._reason - - -# TODO: Move this to a better location/package -class LoggingConnection(): - """ - Debug class to log all HTTP(s) requests as they could be made - with the curl command. - - :cvar log: file-like object that logs entries are written to. - """ - log = None - - def _log_response(self, r): - rv = "# -------- begin %d:%d response ----------\n" % (id(self), id(r)) - ht = "" - v = r.version - if r.version == 10: - v = "HTTP/1.0" - if r.version == 11: - v = "HTTP/1.1" - ht += "%s %s %s\r\n" % (v, r.status, r.reason) - body = r.read() - for h in r.getheaders(): - ht += "%s: %s\r\n" % (h[0].title(), h[1]) - ht += "\r\n" - - # this is evil. laugh with me. ha arharhrhahahaha - class fakesock: - def __init__(self, s): - self.s = s - - def makefile(self, *args, **kwargs): - if PY3: - from io import BytesIO - cls = BytesIO - else: - cls = StringIO - - return cls(b(self.s)) - rr = r - headers = lowercase_keys(dict(r.getheaders())) - - encoding = headers.get('content-encoding', None) - - if encoding in ['zlib', 'deflate']: - body = decompress_data('zlib', body) - elif encoding in ['gzip', 'x-gzip']: - body = decompress_data('gzip', body) - - if r.chunked: - ht += "%x\r\n" % (len(body)) - ht += u(body) - ht += "\r\n0\r\n" - else: - ht += u(body) - - if sys.version_info >= (2, 6) and sys.version_info < (2, 7): - cls = HTTPResponse - else: - cls = httplib.HTTPResponse - - rr = cls(sock=fakesock(ht), method=r._method, - debuglevel=r.debuglevel) - rr.begin() - rv += ht - rv += ("\n# -------- end %d:%d response ----------\n" - % (id(self), id(r))) - - rr._original_data = body - return (rr, rv) - - def _log_curl(self, method, url, body, headers): - cmd = ["curl", "-i"] - - if method.lower() == 'head': - # HEAD method need special handling - cmd.extend(["--head"]) - else: - cmd.extend(["-X", pquote(method)]) - - for h in headers: - cmd.extend(["-H", pquote("%s: %s" % (h, headers[h]))]) - - # TODO: in python 2.6, body can be a file-like object. - if body is not None and len(body) > 0: - cmd.extend(["--data-binary", pquote(body)]) - - cmd.extend(["--compress"]) - cmd.extend([pquote("%s://%s:%d%s" % (self.protocol, self.host, - self.port, url))]) - return " ".join(cmd) - - -class LoggingHTTPSConnection(LoggingConnection, LibcloudHTTPSConnection): - """ - Utility Class for logging HTTPS connections - """ - - protocol = 'https' - - def getresponse(self): - r = LibcloudHTTPSConnection.getresponse(self) - if self.log is not None: - r, rv = self._log_response(r) - self.log.write(rv + "\n") - self.log.flush() - return r - - def request(self, method, url, body=None, headers=None): - headers.update({'X-LC-Request-ID': str(id(self))}) - if self.log is not None: - pre = "# -------- begin %d request ----------\n" % id(self) - self.log.write(pre + - self._log_curl(method, url, body, headers) + "\n") - self.log.flush() - return LibcloudHTTPSConnection.request(self, method, url, body, - headers) - - -class LoggingHTTPConnection(LoggingConnection, LibcloudHTTPConnection): - """ - Utility Class for logging HTTP connections - """ - - protocol = 'http' - - def getresponse(self): - r = LibcloudHTTPConnection.getresponse(self) - if self.log is not None: - r, rv = self._log_response(r) - self.log.write(rv + "\n") - self.log.flush() - return r - - def request(self, method, url, body=None, headers=None): - headers.update({'X-LC-Request-ID': str(id(self))}) - if self.log is not None: - pre = '# -------- begin %d request ----------\n' % id(self) - self.log.write(pre + - self._log_curl(method, url, body, headers) + "\n") - self.log.flush() - return LibcloudHTTPConnection.request(self, method, url, - body, headers) - - -class Connection(object): - """ - A Base Connection class to derive from. - """ - # conn_classes = (LoggingHTTPSConnection) - conn_classes = (LibcloudHTTPConnection, LibcloudHTTPSConnection) - - responseCls = Response - rawResponseCls = RawResponse - connection = None - host = '127.0.0.1' - port = 443 - timeout = None - secure = 1 - driver = None - action = None - cache_busting = False - - allow_insecure = True - - def __init__(self, secure=True, host=None, port=None, url=None, - timeout=None): - self.secure = secure and 1 or 0 - self.ua = [] - self.context = {} - - if not self.allow_insecure and not secure: - # TODO: We should eventually switch to whitelist instead of - # blacklist approach - raise ValueError('Non https connections are not allowed (use ' - 'secure=True)') - - self.request_path = '' - - if host: - self.host = host - - if port is not None: - self.port = port - else: - if self.secure == 1: - self.port = 443 - else: - self.port = 80 - - if url: - (self.host, self.port, self.secure, - self.request_path) = self._tuple_from_url(url) - - if timeout: - self.timeout = timeout - - def set_context(self, context): - if not isinstance(context, dict): - raise TypeError('context needs to be a dictionary') - - self.context = context - - def reset_context(self): - self.context = {} - - def _tuple_from_url(self, url): - secure = 1 - port = None - (scheme, netloc, request_path, param, - query, fragment) = urlparse.urlparse(url) - - if scheme not in ['http', 'https']: - raise LibcloudError('Invalid scheme: %s in url %s' % (scheme, url)) - - if scheme == "http": - secure = 0 - - if ":" in netloc: - netloc, port = netloc.rsplit(":") - port = port - - if not port: - if scheme == "http": - port = 80 - else: - port = 443 - - host = netloc - - return (host, port, secure, request_path) - - def connect(self, host=None, port=None, base_url=None): - """ - Establish a connection with the API server. - - :type host: ``str`` - :param host: Optional host to override our default - - :type port: ``int`` - :param port: Optional port to override our default - - :returns: A connection - """ - # prefer the attribute base_url if its set or sent - connection = None - secure = self.secure - - if getattr(self, 'base_url', None) and base_url is None: - (host, port, - secure, request_path) = self._tuple_from_url(self.base_url) - elif base_url is not None: - (host, port, - secure, request_path) = self._tuple_from_url(base_url) - else: - host = host or self.host - port = port or self.port - - kwargs = {'host': host, 'port': int(port)} - - # Timeout is only supported in Python 2.6 and later - # http://docs.python.org/library/httplib.html#httplib.HTTPConnection - if self.timeout and not PY25: - kwargs.update({'timeout': self.timeout}) - - connection = self.conn_classes[secure](**kwargs) - # You can uncoment this line, if you setup a reverse proxy server - # which proxies to your endpoint, and lets you easily capture - # connections in cleartext when you setup the proxy to do SSL - # for you - # connection = self.conn_classes[False]("127.0.0.1", 8080) - - self.connection = connection - - def _user_agent(self): - user_agent_suffix = ' '.join(['(%s)' % x for x in self.ua]) - - if self.driver: - user_agent = 'libcloud/%s (%s) %s' % ( - libcloud.__version__, - self.driver.name, user_agent_suffix) - else: - user_agent = 'libcloud/%s %s' % ( - libcloud.__version__, user_agent_suffix) - - return user_agent - - def user_agent_append(self, token): - """ - Append a token to a user agent string. - - Users of the library should call this to uniquely identify their - requests to a provider. - - :type token: ``str`` - :param token: Token to add to the user agent. - """ - self.ua.append(token) - - def request(self, action, params=None, data=None, headers=None, - method='GET', raw=False): - """ - Request a given `action`. - - Basically a wrapper around the connection - object's `request` that does some helpful pre-processing. - - :type action: ``str`` - :param action: A path. This can include arguments. If included, - any extra parameters are appended to the existing ones. - - :type params: ``dict`` - :param params: Optional mapping of additional parameters to send. If - None, leave as an empty ``dict``. - - :type data: ``unicode`` - :param data: A body of data to send with the request. - - :type headers: ``dict`` - :param headers: Extra headers to add to the request - None, leave as an empty ``dict``. - - :type method: ``str`` - :param method: An HTTP method such as "GET" or "POST". - - :type raw: ``bool`` - :param raw: True to perform a "raw" request aka only send the headers - and use the rawResponseCls class. This is used with - storage API when uploading a file. - - :return: An :class:`Response` instance. - :rtype: :class:`Response` instance - - """ - if params is None: - params = {} - else: - params = copy.copy(params) - - if headers is None: - headers = {} - else: - headers = copy.copy(headers) - - action = self.morph_action_hook(action) - self.action = action - self.method = method - - # Extend default parameters - params = self.add_default_params(params) - - # Add cache busting parameters (if enabled) - if self.cache_busting and method == 'GET': - params = self._add_cache_busting_to_params(params=params) - - # Extend default headers - headers = self.add_default_headers(headers) - - # We always send a user-agent header - headers.update({'User-Agent': self._user_agent()}) - - # Indicate that we support gzip and deflate compression - headers.update({'Accept-Encoding': 'gzip,deflate'}) - - port = int(self.port) - - if port not in (80, 443): - headers.update({'Host': "%s:%d" % (self.host, port)}) - else: - headers.update({'Host': self.host}) - - if data: - data = self.encode_data(data) - headers['Content-Length'] = str(len(data)) - elif method.upper() in ['POST', 'PUT'] and not raw: - # Only send Content-Length 0 with POST and PUT request. - # - # Note: Content-Length is not added when using "raw" mode means - # means that headers are upfront and the body is sent at some point - # later on. With raw mode user can specify Content-Length with - # "data" not being set. - headers['Content-Length'] = '0' - - params, headers = self.pre_connect_hook(params, headers) - - if params: - if '?' in action: - url = '&'.join((action, urlencode(params, doseq=True))) - else: - url = '?'.join((action, urlencode(params, doseq=True))) - else: - url = action - - # Removed terrible hack...this a less-bad hack that doesn't execute a - # request twice, but it's still a hack. - self.connect() - try: - # @TODO: Should we just pass File object as body to request method - # instead of dealing with splitting and sending the file ourselves? - if raw: - self.connection.putrequest(method, url) - - for key, value in list(headers.items()): - self.connection.putheader(key, str(value)) - - self.connection.endheaders() - else: - self.connection.request(method=method, url=url, body=data, - headers=headers) - except ssl.SSLError: - e = sys.exc_info()[1] - self.reset_context() - raise ssl.SSLError(str(e)) - - if raw: - responseCls = self.rawResponseCls - kwargs = {'connection': self} - else: - responseCls = self.responseCls - kwargs = {'connection': self, - 'response': self.connection.getresponse()} - - try: - response = responseCls(**kwargs) - finally: - # Always reset the context after the request has completed - self.reset_context() - - return response - - def morph_action_hook(self, action): - return self.request_path + action - - def add_default_params(self, params): - """ - Adds default parameters (such as API key, version, etc.) - to the passed `params` - - Should return a dictionary. - """ - return params - - def add_default_headers(self, headers): - """ - Adds default headers (such as Authorization, X-Foo-Bar) - to the passed `headers` - - Should return a dictionary. - """ - return headers - - def pre_connect_hook(self, params, headers): - """ - A hook which is called before connecting to the remote server. - This hook can perform a final manipulation on the params, headers and - url parameters. - - :type params: ``dict`` - :param params: Request parameters. - - :type headers: ``dict`` - :param headers: Request headers. - """ - return params, headers - - def encode_data(self, data): - """ - Encode body data. - - Override in a provider's subclass. - """ - return data - - def _add_cache_busting_to_params(self, params): - """ - Add cache busting parameter to the query parameters of a GET request. - - Parameters are only added if "cache_busting" class attribute is set to - True. - - Note: This should only be used with *naughty* providers which use - excessive caching of responses. - """ - cache_busting_value = binascii.hexlify(os.urandom(8)).decode('ascii') - - if isinstance(params, dict): - params['cache-busting'] = cache_busting_value - else: - params.append(('cache-busting', cache_busting_value)) - - return params - - -class PollingConnection(Connection): - """ - Connection class which can also work with the async APIs. - - After initial requests, this class periodically polls for jobs status and - waits until the job has finished. - If job doesn't finish in timeout seconds, an Exception thrown. - """ - poll_interval = 0.5 - timeout = 200 - request_method = 'request' - - def async_request(self, action, params=None, data=None, headers=None, - method='GET', context=None): - """ - Perform an 'async' request to the specified path. Keep in mind that - this function is *blocking* and 'async' in this case means that the - hit URL only returns a job ID which is the periodically polled until - the job has completed. - - This function works like this: - - - Perform a request to the specified path. Response should contain a - 'job_id'. - - - Returned 'job_id' is then used to construct a URL which is used for - retrieving job status. Constructed URL is then periodically polled - until the response indicates that the job has completed or the - timeout of 'self.timeout' seconds has been reached. - - :type action: ``str`` - :param action: A path - - :type params: ``dict`` - :param params: Optional mapping of additional parameters to send. If - None, leave as an empty ``dict``. - - :type data: ``unicode`` - :param data: A body of data to send with the request. - - :type headers: ``dict`` - :param headers: Extra headers to add to the request - None, leave as an empty ``dict``. - - :type method: ``str`` - :param method: An HTTP method such as "GET" or "POST". - - :type context: ``dict`` - :param context: Context dictionary which is passed to the functions - which construct initial and poll URL. - - :return: An :class:`Response` instance. - :rtype: :class:`Response` instance - """ - - request = getattr(self, self.request_method) - kwargs = self.get_request_kwargs(action=action, params=params, - data=data, headers=headers, - method=method, - context=context) - response = request(**kwargs) - kwargs = self.get_poll_request_kwargs(response=response, - context=context, - request_kwargs=kwargs) - - end = time.time() + self.timeout - completed = False - while time.time() < end and not completed: - response = request(**kwargs) - completed = self.has_completed(response=response) - if not completed: - time.sleep(self.poll_interval) - - if not completed: - raise LibcloudError('Job did not complete in %s seconds' % - (self.timeout)) - - return response - - def get_request_kwargs(self, action, params=None, data=None, headers=None, - method='GET', context=None): - """ - Arguments which are passed to the initial request() call inside - async_request. - """ - kwargs = {'action': action, 'params': params, 'data': data, - 'headers': headers, 'method': method} - return kwargs - - def get_poll_request_kwargs(self, response, context, request_kwargs): - """ - Return keyword arguments which are passed to the request() method when - polling for the job status. - - :param response: Response object returned by poll request. - :type response: :class:`HTTPResponse` - - :param request_kwargs: Kwargs previously used to initiate the - poll request. - :type response: ``dict`` - - :return ``dict`` Keyword arguments - """ - raise NotImplementedError('get_poll_request_kwargs not implemented') - - def has_completed(self, response): - """ - Return job completion status. - - :param response: Response object returned by poll request. - :type response: :class:`HTTPResponse` - - :return ``bool`` True if the job has completed, False otherwise. - """ - raise NotImplementedError('has_completed not implemented') - - -class ConnectionKey(Connection): - """ - Base connection class which accepts a single ``key`` argument. - """ - def __init__(self, key, secure=True, host=None, port=None, url=None, - timeout=None): - """ - Initialize `user_id` and `key`; set `secure` to an ``int`` based on - passed value. - """ - super(ConnectionKey, self).__init__(secure=secure, host=host, - port=port, url=url, - timeout=timeout) - self.key = key - - -class ConnectionUserAndKey(ConnectionKey): - """ - Base connection class which accepts a ``user_id`` and ``key`` argument. - """ - - user_id = None - - def __init__(self, user_id, key, secure=True, - host=None, port=None, url=None, timeout=None): - super(ConnectionUserAndKey, self).__init__(key, secure=secure, - host=host, port=port, - url=url, timeout=timeout) - self.user_id = user_id - - -class BaseDriver(object): - """ - Base driver class from which other classes can inherit from. - """ - - connectionCls = ConnectionKey - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - api_version=None, region=None, **kwargs): - """ - :param key: API key or username to be used (required) - :type key: ``str`` - - :param secret: Secret password to be used (required) - :type secret: ``str`` - - :param secure: Weither to use HTTPS or HTTP. Note: Some providers - only support HTTPS, and it is on by default. - :type secure: ``bool`` - - :param host: Override hostname used for connections. - :type host: ``str`` - - :param port: Override port used for connections. - :type port: ``int`` - - :param api_version: Optional API version. Only used by drivers - which support multiple API versions. - :type api_version: ``str`` - - :param region: Optional driver region. Only used by drivers which - support multiple regions. - :type region: ``str`` - - :rtype: ``None`` - """ - - self.key = key - self.secret = secret - self.secure = secure - args = [self.key] - - if self.secret is not None: - args.append(self.secret) - - args.append(secure) - - if host is not None: - args.append(host) - - if port is not None: - args.append(port) - - self.api_version = api_version - self.region = region - - conn_kwargs = self._ex_connection_class_kwargs() - self.connection = self.connectionCls(*args, **conn_kwargs) - - self.connection.driver = self - self.connection.connect() - - def _ex_connection_class_kwargs(self): - """ - Return extra connection keyword arguments which are passed to the - Connection class constructor. - """ - return {} diff --git a/awx/lib/site-packages/libcloud/common/brightbox.py b/awx/lib/site-packages/libcloud/common/brightbox.py deleted file mode 100644 index 1943dda0d2..0000000000 --- a/awx/lib/site-packages/libcloud/common/brightbox.py +++ /dev/null @@ -1,101 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 - -from libcloud.common.base import ConnectionUserAndKey, JsonResponse -from libcloud.compute.types import InvalidCredsError - -from libcloud.utils.py3 import b -from libcloud.utils.py3 import httplib - -try: - import simplejson as json -except ImportError: - import json - - -class BrightboxResponse(JsonResponse): - def success(self): - return self.status >= httplib.OK and self.status < httplib.BAD_REQUEST - - def parse_body(self): - if self.headers['content-type'].split(';')[0] == 'application/json': - return super(BrightboxResponse, self).parse_body() - else: - return self.body - - def parse_error(self): - response = super(BrightboxResponse, self).parse_body() - - if 'error' in response: - if response['error'] in ['invalid_client', 'unauthorized_client']: - raise InvalidCredsError(response['error']) - - return response['error'] - elif 'error_name' in response: - return '%s: %s' % (response['error_name'], response['errors'][0]) - - return self.body - - -class BrightboxConnection(ConnectionUserAndKey): - """ - Connection class for the Brightbox driver - """ - - host = 'api.gb1.brightbox.com' - responseCls = BrightboxResponse - - def _fetch_oauth_token(self): - body = json.dumps({'client_id': self.user_id, 'grant_type': 'none'}) - - authorization = 'Basic ' + str(base64.encodestring(b('%s:%s' % - (self.user_id, self.key)))).rstrip() - - self.connect() - - headers = { - 'Host': self.host, - 'User-Agent': self._user_agent(), - 'Authorization': authorization, - 'Content-Type': 'application/json', - 'Content-Length': str(len(body)) - } - - response = self.connection.request(method='POST', url='/token', - body=body, headers=headers) - - response = self.connection.getresponse() - - if response.status == httplib.OK: - return json.loads(response.read())['access_token'] - else: - responseCls = BrightboxResponse(response=response, connection=self) - message = responseCls.parse_error() - raise InvalidCredsError(message) - - def add_default_headers(self, headers): - try: - headers['Authorization'] = 'OAuth ' + self.token - except AttributeError: - self.token = self._fetch_oauth_token() - - headers['Authorization'] = 'OAuth ' + self.token - - return headers - - def encode_data(self, data): - return json.dumps(data) diff --git a/awx/lib/site-packages/libcloud/common/cloudsigma.py b/awx/lib/site-packages/libcloud/common/cloudsigma.py deleted file mode 100644 index c65535cfde..0000000000 --- a/awx/lib/site-packages/libcloud/common/cloudsigma.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'API_ENDPOINTS_1_0', - 'API_ENDPOINTS_2_0', - 'API_VERSIONS', - 'INSTANCE_TYPES' -] - -# API end-points -API_ENDPOINTS_1_0 = { - 'zrh': { - 'name': 'Zurich', - 'country': 'Switzerland', - 'host': 'api.zrh.cloudsigma.com' - }, - 'lvs': { - 'name': 'Las Vegas', - 'country': 'United States', - 'host': 'api.lvs.cloudsigma.com' - } -} - -API_ENDPOINTS_2_0 = { - 'zrh': { - 'name': 'Zurich', - 'country': 'Switzerland', - 'host': 'zrh.cloudsigma.com' - }, - 'lvs': { - 'name': 'Las Vegas', - 'country': 'United States', - 'host': 'lvs.cloudsigma.com' - }, - 'wdc': { - 'name': 'Washington DC', - 'country': 'United States', - 'host': 'wdc.cloudsigma.com' - } - -} - -DEFAULT_REGION = 'zrh' - -# Supported API versions. -API_VERSIONS = [ - '1.0' # old and deprecated - '2.0' -] - -DEFAULT_API_VERSION = '2.0' - -# CloudSigma doesn't specify special instance types. -# Basically for CPU any value between 0.5 GHz and 20.0 GHz should work, -# 500 MB to 32000 MB for ram -# and 1 GB to 1024 GB for hard drive size. -# Plans in this file are based on examples listed on http://www.cloudsigma -# .com/en/pricing/price-schedules -INSTANCE_TYPES = [ - { - 'id': 'micro-regular', - 'name': 'Micro/Regular instance', - 'cpu': 1100, - 'memory': 640, - 'disk': 10 + 3, - 'bandwidth': None, - }, - { - 'id': 'micro-high-cpu', - 'name': 'Micro/High CPU instance', - 'cpu': 2200, - 'memory': 640, - 'disk': 80, - 'bandwidth': None, - }, - { - 'id': 'standard-small', - 'name': 'Standard/Small instance', - 'cpu': 1100, - 'memory': 1741, - 'disk': 50, - 'bandwidth': None, - }, - { - 'id': 'standard-large', - 'name': 'Standard/Large instance', - 'cpu': 4400, - 'memory': 7680, - 'disk': 250, - 'bandwidth': None, - }, - { - 'id': 'standard-extra-large', - 'name': 'Standard/Extra Large instance', - 'cpu': 8800, - 'memory': 15360, - 'disk': 500, - 'bandwidth': None, - }, - { - 'id': 'high-memory-extra-large', - 'name': 'High Memory/Extra Large instance', - 'cpu': 7150, - 'memory': 17510, - 'disk': 250, - 'bandwidth': None, - }, - { - 'id': 'high-memory-double-extra-large', - 'name': 'High Memory/Double Extra Large instance', - 'cpu': 14300, - 'memory': 32768, - 'disk': 500, - 'bandwidth': None, - }, - { - 'id': 'high-cpu-medium', - 'name': 'High CPU/Medium instance', - 'cpu': 5500, - 'memory': 1741, - 'disk': 150, - 'bandwidth': None, - }, - { - 'id': 'high-cpu-extra-large', - 'name': 'High CPU/Extra Large instance', - 'cpu': 20000, - 'memory': 7168, - 'disk': 500, - 'bandwidth': None, - } -] diff --git a/awx/lib/site-packages/libcloud/common/cloudstack.py b/awx/lib/site-packages/libcloud/common/cloudstack.py deleted file mode 100644 index b23d4539ee..0000000000 --- a/awx/lib/site-packages/libcloud/common/cloudstack.py +++ /dev/null @@ -1,195 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import hashlib -import copy -import hmac - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlencode -from libcloud.utils.py3 import urlquote -from libcloud.utils.py3 import b - -from libcloud.common.types import ProviderError -from libcloud.common.base import ConnectionUserAndKey, PollingConnection -from libcloud.common.base import JsonResponse -from libcloud.common.types import MalformedResponseError -from libcloud.compute.types import InvalidCredsError - - -class CloudStackResponse(JsonResponse): - def parse_error(self): - if self.status == httplib.UNAUTHORIZED: - raise InvalidCredsError('Invalid provider credentials') - - body = self.parse_body() - values = list(body.values())[0] - - if 'errortext' in values: - value = values['errortext'] - else: - value = self.body - - error = ProviderError(value=value, http_code=self.status, - driver=self.connection.driver) - raise error - - -class CloudStackConnection(ConnectionUserAndKey, PollingConnection): - responseCls = CloudStackResponse - poll_interval = 1 - request_method = '_sync_request' - timeout = 600 - - ASYNC_PENDING = 0 - ASYNC_SUCCESS = 1 - ASYNC_FAILURE = 2 - - def encode_data(self, data): - """ - Must of the data is sent as part of query params (eeww), - but in newer versions, userdata argument can be sent as a - urlencoded data in the request body. - """ - if data: - data = urlencode(data) - - return data - - def _make_signature(self, params): - signature = [(k.lower(), v) for k, v in list(params.items())] - signature.sort(key=lambda x: x[0]) - - pairs = [] - for pair in signature: - key = urlquote(str(pair[0]), safe='[]') - value = urlquote(str(pair[1]), safe='[]') - item = '%s=%s' % (key, value) - pairs .append(item) - - signature = '&'.join(pairs) - - signature = signature.lower().replace('+', '%20') - signature = hmac.new(b(self.key), msg=b(signature), - digestmod=hashlib.sha1) - return base64.b64encode(b(signature.digest())) - - def add_default_params(self, params): - params['apiKey'] = self.user_id - params['response'] = 'json' - - return params - - def pre_connect_hook(self, params, headers): - params['signature'] = self._make_signature(params) - - return params, headers - - def _async_request(self, command, action=None, params=None, data=None, - headers=None, method='GET', context=None): - if params: - context = copy.deepcopy(params) - else: - context = {} - - # Command is specified as part of GET call - context['command'] = command - result = super(CloudStackConnection, self).async_request( - action=action, params=params, data=data, headers=headers, - method=method, context=context) - return result['jobresult'] - - def get_request_kwargs(self, action, params=None, data='', headers=None, - method='GET', context=None): - command = context['command'] - request_kwargs = {'command': command, 'action': action, - 'params': params, 'data': data, - 'headers': headers, 'method': method} - return request_kwargs - - def get_poll_request_kwargs(self, response, context, request_kwargs): - job_id = response['jobid'] - params = {'jobid': job_id} - kwargs = {'command': 'queryAsyncJobResult', 'params': params} - return kwargs - - def has_completed(self, response): - status = response.get('jobstatus', self.ASYNC_PENDING) - - if status == self.ASYNC_FAILURE: - msg = response.get('jobresult', {}).get('errortext', status) - raise Exception(msg) - - return status == self.ASYNC_SUCCESS - - def _sync_request(self, command, action=None, params=None, data=None, - headers=None, method='GET'): - """ - This method handles synchronous calls which are generally fast - information retrieval requests and thus return 'quickly'. - """ - # command is always sent as part of "command" query parameter - if params: - params = copy.deepcopy(params) - else: - params = {} - - params['command'] = command - result = self.request(action=self.driver.path, params=params, - data=data, headers=headers, method=method) - - command = command.lower() - - # Work around for older verions which don't return "response" suffix - # in delete ingress rule response command name - if (command == 'revokesecuritygroupingress' and - 'revokesecuritygroupingressresponse' not in result.object): - command = command - else: - command = command + 'response' - - if command not in result.object: - raise MalformedResponseError( - "Unknown response format", - body=result.body, - driver=self.driver) - result = result.object[command] - return result - - -class CloudStackDriverMixIn(object): - host = None - path = None - - connectionCls = CloudStackConnection - - def __init__(self, key, secret=None, secure=True, host=None, port=None): - host = host or self.host - super(CloudStackDriverMixIn, self).__init__(key, secret, secure, host, - port) - - def _sync_request(self, command, action=None, params=None, data=None, - headers=None, method='GET'): - return self.connection._sync_request(command=command, action=action, - params=params, data=data, - headers=headers, method=method) - - def _async_request(self, command, action=None, params=None, data=None, - headers=None, method='GET', context=None): - return self.connection._async_request(command=command, action=action, - params=params, data=data, - headers=headers, method=method, - context=context) diff --git a/awx/lib/site-packages/libcloud/common/gandi.py b/awx/lib/site-packages/libcloud/common/gandi.py deleted file mode 100644 index 11e96221b8..0000000000 --- a/awx/lib/site-packages/libcloud/common/gandi.py +++ /dev/null @@ -1,189 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Gandi driver base classes -""" - -import time -import hashlib -import sys - -from libcloud.utils.py3 import b - -from libcloud.common.base import ConnectionKey -from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection - -# Global constants - -DEFAULT_TIMEOUT = 600 # operation pooling max seconds -DEFAULT_INTERVAL = 20 # seconds between 2 operation.info - - -class GandiException(Exception): - """ - Exception class for Gandi driver - """ - def __str__(self): - return '(%u) %s' % (self.args[0], self.args[1]) - - def __repr__(self): - return '<GandiException code %u "%s">' % (self.args[0], self.args[1]) - - -class GandiResponse(XMLRPCResponse): - """ - A Base Gandi Response class to derive from. - """ - - -class GandiConnection(XMLRPCConnection, ConnectionKey): - """ - Connection class for the Gandi driver - """ - - responseCls = GandiResponse - host = 'rpc.gandi.net' - endpoint = '/xmlrpc/' - - def __init__(self, key, secure=True): - # Note: Method resolution order in this case is - # XMLRPCConnection -> Connection and Connection doesn't take key as the - # first argument so we specify a keyword argument instead. - # Previously it was GandiConnection -> ConnectionKey so it worked fine. - super(GandiConnection, self).__init__(key=key, secure=secure) - self.driver = BaseGandiDriver - - def request(self, method, *args): - args = (self.key, ) + args - return super(GandiConnection, self).request(method, *args) - - -class BaseGandiDriver(object): - """ - Gandi base driver - - """ - connectionCls = GandiConnection - name = 'Gandi' - - # Specific methods for gandi - def _wait_operation(self, id, timeout=DEFAULT_TIMEOUT, - check_interval=DEFAULT_INTERVAL): - """ Wait for an operation to succeed""" - - for i in range(0, timeout, check_interval): - try: - op = self.connection.request('operation.info', int(id)).object - - if op['step'] == 'DONE': - return True - if op['step'] in ['ERROR', 'CANCEL']: - return False - except (KeyError, IndexError): - pass - except Exception: - e = sys.exc_info()[1] - raise GandiException(1002, e) - - time.sleep(check_interval) - return False - - -class BaseObject(object): - """Base class for objects not conventional""" - - uuid_prefix = '' - - def __init__(self, id, state, driver): - self.id = str(id) if id else None - self.state = state - self.driver = driver - self.uuid = self.get_uuid() - - def get_uuid(self): - """Unique hash for this object - - :return: ``str`` - - The hash is a function of an SHA1 hash of prefix, the object's ID and - its driver which means that it should be unique between all - interfaces. - TODO : to review - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> vif = driver.create_interface() - >>> vif.get_uuid() - 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f' - - Note, for example, that this example will always produce the - same UUID! - """ - hashstring = '%s:%s:%s' % \ - (self.uuid_prefix, self.id, self.driver.type) - return hashlib.sha1(b(hashstring)).hexdigest() - - -class IPAddress(BaseObject): - """ - Provide a common interface for ip addresses - """ - - uuid_prefix = 'inet:' - - def __init__(self, id, state, inet, driver, version=4, extra=None): - super(IPAddress, self).__init__(id, state, driver) - self.inet = inet - self.version = version - self.extra = extra or {} - - def __repr__(self): - return (('<IPAddress: id=%s, address=%s, state=%s, driver=%s ...>') - % (self.id, self.inet, self.state, self.driver.name)) - - -class NetworkInterface(BaseObject): - """ - Provide a common interface for network interfaces - """ - - uuid_prefix = 'if:' - - def __init__(self, id, state, mac_address, driver, - ips=None, node_id=None, extra=None): - super(NetworkInterface, self).__init__(id, state, driver) - self.mac = mac_address - self.ips = ips or {} - self.node_id = node_id - self.extra = extra or {} - - def __repr__(self): - return (('<Interface: id=%s, mac=%s, state=%s, driver=%s ...>') - % (self.id, self.mac, self.state, self.driver.name)) - - -class Disk(BaseObject): - """ - Gandi disk component - """ - def __init__(self, id, state, name, driver, size, extra=None): - super(Disk, self).__init__(id, state, driver) - self.name = name - self.size = size - self.extra = extra or {} - - def __repr__(self): - return ( - ('<Disk: id=%s, name=%s, state=%s, size=%s, driver=%s ...>') - % (self.id, self.name, self.state, self.size, self.driver.name)) diff --git a/awx/lib/site-packages/libcloud/common/gogrid.py b/awx/lib/site-packages/libcloud/common/gogrid.py deleted file mode 100644 index e2448debdd..0000000000 --- a/awx/lib/site-packages/libcloud/common/gogrid.py +++ /dev/null @@ -1,183 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import hashlib -import time - -from libcloud.utils.py3 import b - -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.common.types import MalformedResponseError -from libcloud.common.base import ConnectionUserAndKey, JsonResponse -from libcloud.compute.base import NodeLocation - -HOST = 'api.gogrid.com' -PORTS_BY_SECURITY = {True: 443, False: 80} -API_VERSION = '1.8' - -__all__ = [ - "GoGridResponse", - "GoGridConnection", - "GoGridIpAddress", - "BaseGoGridDriver", -] - - -class GoGridResponse(JsonResponse): - - def __init__(self, *args, **kwargs): - self.driver = BaseGoGridDriver - super(GoGridResponse, self).__init__(*args, **kwargs) - - def success(self): - if self.status == 403: - raise InvalidCredsError('Invalid credentials', self.driver) - if self.status == 401: - raise InvalidCredsError('API Key has insufficient rights', - self.driver) - if not self.body: - return None - try: - return self.parse_body()['status'] == 'success' - except ValueError: - raise MalformedResponseError('Malformed reply', - body=self.body, - driver=self.driver) - - def parse_error(self): - try: - return self.parse_body()["list"][0]["message"] - except (ValueError, KeyError): - return None - - -class GoGridConnection(ConnectionUserAndKey): - """ - Connection class for the GoGrid driver - """ - - host = HOST - responseCls = GoGridResponse - - def add_default_params(self, params): - params["api_key"] = self.user_id - params["v"] = API_VERSION - params["format"] = 'json' - params["sig"] = self.get_signature(self.user_id, self.key) - - return params - - def get_signature(self, key, secret): - """ create sig from md5 of key + secret + time """ - m = hashlib.md5(b(key + secret + str(int(time.time())))) - return m.hexdigest() - - def request(self, action, params=None, data='', headers=None, method='GET', - raw=False): - return super(GoGridConnection, self).request(action, params, data, - headers, method, raw) - - -class GoGridIpAddress(object): - """ - IP Address - """ - - def __init__(self, id, ip, public, state, subnet): - self.id = id - self.ip = ip - self.public = public - self.state = state - self.subnet = subnet - - -class BaseGoGridDriver(object): - """GoGrid has common object model for services they - provide, like locations and IP, so keep handling of - these things in a single place.""" - - name = "GoGrid" - - def _get_ip(self, element): - return element.get('ip').get('ip') - - def _to_ip(self, element): - ip = GoGridIpAddress(id=element['id'], - ip=element['ip'], - public=element['public'], - subnet=element['subnet'], - state=element["state"]["name"]) - ip.location = self._to_location(element['datacenter']) - return ip - - def _to_ips(self, object): - return [self._to_ip(el) - for el in object['list']] - - def _to_location(self, element): - location = NodeLocation(id=element['id'], - name=element['name'], - country="US", - driver=self.connection.driver) - return location - - def _to_locations(self, object): - return [self._to_location(el) - for el in object['list']] - - def ex_list_ips(self, **kwargs): - """Return list of IP addresses assigned to - the account. - - :keyword public: set to True to list only - public IPs or False to list only - private IPs. Set to None or not specify - at all not to filter by type - :type public: ``bool`` - - :keyword assigned: set to True to list only addresses - assigned to servers, False to list unassigned - addresses and set to None or don't set at all - not no filter by state - :type assigned: ``bool`` - - :keyword location: filter IP addresses by location - :type location: :class:`NodeLocation` - - :rtype: ``list`` of :class:`GoGridIpAddress` - """ - - params = {} - - if "public" in kwargs and kwargs["public"] is not None: - params["ip.type"] = {True: "Public", - False: "Private"}[kwargs["public"]] - if "assigned" in kwargs and kwargs["assigned"] is not None: - params["ip.state"] = {True: "Assigned", - False: "Unassigned"}[kwargs["assigned"]] - if "location" in kwargs and kwargs['location'] is not None: - params['datacenter'] = kwargs['location'].id - - response = self.connection.request('/api/grid/ip/list', params=params) - ips = self._to_ips(response.object) - return ips - - def _get_first_ip(self, location=None): - ips = self.ex_list_ips(public=True, assigned=False, location=location) - try: - return ips[0].ip - except IndexError: - raise LibcloudError('No public unassigned IPs left', - self.driver) diff --git a/awx/lib/site-packages/libcloud/common/google.py b/awx/lib/site-packages/libcloud/common/google.py deleted file mode 100644 index 725c3832aa..0000000000 --- a/awx/lib/site-packages/libcloud/common/google.py +++ /dev/null @@ -1,671 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Module for Google Connection and Authentication classes. - -Information about setting up your Google OAUTH2 credentials: - -For libcloud, there are two basic methods for authenticating to Google using -OAUTH2: Service Accounts and Client IDs for Installed Applications. - -Both are initially set up from the Cloud Console_ -_Console: https://cloud.google.com/console - -Setting up Service Account authentication (note that you need the PyCrypto -package installed to use this): - - Go to the Console - - Go to your project and then to "APIs & auth" on the left - - Click on "Credentials" - - Click on "Create New Client ID..." - - Select "Service account" and click on "Create Client ID" - - Download the Private Key (should happen automatically). - - The key that you download is a PKCS12 key. It needs to be converted to - the PEM format. - - Convert the key using OpenSSL (the default password is 'notasecret'): - ``openssl pkcs12 -in YOURPRIVKEY.p12 -nodes -nocerts - -passin pass:notasecret | openssl rsa -out PRIV.pem`` - - Move the .pem file to a safe location. - - To Authenticate, you will need to pass the Service Account's "Email - address" in as the user_id and the path to the .pem file as the key. - -Setting up Installed Application authentication: - - Go to the Console - - Go to your project and then to "APIs & auth" on the left - - Click on "Credentials" - - Select "Installed application" and "Other" then click on - "Create Client ID" - - To Authenticate, pass in the "Client ID" as the user_id and the "Client - secret" as the key - - The first time that you do this, the libcloud will give you a URL to - visit. Copy and paste the URL into a browser. - - When you go to the URL it will ask you to log in (if you aren't already) - and ask you if you want to allow the project access to your account. - - Click on Accept and you will be given a code. - - Paste that code at the prompt given to you by the Google libcloud - connection. - - At that point, a token & refresh token will be stored in your home - directory and will be used for authentication. - -Please remember to secure your keys and access tokens. -""" -from __future__ import with_statement - -try: - import simplejson as json -except ImportError: - import json - -import base64 -import errno -import time -import datetime -import os -import socket -import sys - -from libcloud.utils.py3 import httplib, urlencode, urlparse, PY3 -from libcloud.common.base import (ConnectionUserAndKey, JsonResponse, - PollingConnection) -from libcloud.common.types import (ProviderError, - LibcloudError) - -try: - from Crypto.Hash import SHA256 - from Crypto.PublicKey import RSA - from Crypto.Signature import PKCS1_v1_5 - import Crypto.Random - Crypto.Random.atfork() -except ImportError: - # The pycrypto library is unavailable - SHA256 = None - RSA = None - PKCS1_v1_5 = None - -TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%SZ' - - -class GoogleAuthError(LibcloudError): - """Generic Error class for various authentication errors.""" - def __init__(self, value): - self.value = value - - def __repr__(self): - return repr(self.value) - - -class GoogleBaseError(ProviderError): - def __init__(self, value, http_code, code, driver=None): - self.code = code - super(GoogleBaseError, self).__init__(value, http_code, driver) - - -class InvalidRequestError(GoogleBaseError): - pass - - -class JsonParseError(GoogleBaseError): - pass - - -class ResourceNotFoundError(GoogleBaseError): - pass - - -class QuotaExceededError(GoogleBaseError): - pass - - -class ResourceExistsError(GoogleBaseError): - pass - - -class ResourceInUseError(GoogleBaseError): - pass - - -class GoogleResponse(JsonResponse): - """ - Google Base Response class. - """ - def success(self): - """ - Determine if the request was successful. - - For the Google response class, tag all responses as successful and - raise appropriate Exceptions from parse_body. - - :return: C{True} - """ - return True - - def _get_error(self, body): - """ - Get the error code and message from a JSON response. - - Return just the first error if there are multiple errors. - - :param body: The body of the JSON response dictionary - :type body: ``dict`` - - :return: Tuple containing error code and message - :rtype: ``tuple`` of ``str`` or ``int`` - """ - if 'errors' in body['error']: - err = body['error']['errors'][0] - else: - err = body['error'] - - if 'code' in err: - code = err.get('code') - message = err.get('message') - else: - code = None - message = body.get('error_description', err) - - return (code, message) - - def parse_body(self): - """ - Parse the JSON response body, or raise exceptions as appropriate. - - :return: JSON dictionary - :rtype: ``dict`` - """ - if len(self.body) == 0 and not self.parse_zero_length_body: - return self.body - - json_error = False - try: - body = json.loads(self.body) - except: - # If there is both a JSON parsing error and an unsuccessful http - # response (like a 404), we want to raise the http error and not - # the JSON one, so don't raise JsonParseError here. - body = self.body - json_error = True - - if self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED]: - if json_error: - raise JsonParseError(body, self.status, None) - elif 'error' in body: - (code, message) = self._get_error(body) - if code == 'QUOTA_EXCEEDED': - raise QuotaExceededError(message, self.status, code) - elif code == 'RESOURCE_ALREADY_EXISTS': - raise ResourceExistsError(message, self.status, code) - elif code.startswith('RESOURCE_IN_USE'): - raise ResourceInUseError(message, self.status, code) - else: - raise GoogleBaseError(message, self.status, code) - else: - return body - - elif self.status == httplib.NOT_FOUND: - if (not json_error) and ('error' in body): - (code, message) = self._get_error(body) - else: - message = body - code = None - raise ResourceNotFoundError(message, self.status, code) - - elif self.status == httplib.BAD_REQUEST: - if (not json_error) and ('error' in body): - (code, message) = self._get_error(body) - else: - message = body - code = None - raise InvalidRequestError(message, self.status, code) - - else: - if (not json_error) and ('error' in body): - (code, message) = self._get_error(body) - else: - message = body - code = None - raise GoogleBaseError(message, self.status, code) - - -class GoogleBaseDriver(object): - name = "Google API" - - -class GoogleBaseAuthConnection(ConnectionUserAndKey): - """ - Base class for Google Authentication. Should be subclassed for specific - types of authentication. - """ - driver = GoogleBaseDriver - responseCls = GoogleResponse - name = 'Google Auth' - host = 'accounts.google.com' - auth_path = '/o/oauth2/auth' - - def __init__(self, user_id, key, scopes=None, - redirect_uri='urn:ietf:wg:oauth:2.0:oob', - login_hint=None, **kwargs): - """ - :param user_id: The email address (for service accounts) or Client ID - (for installed apps) to be used for authentication. - :type user_id: ``str`` - - :param key: The RSA Key (for service accounts) or file path containing - key or Client Secret (for installed apps) to be used for - authentication. - :type key: ``str`` - - :param scopes: A list of urls defining the scope of authentication - to grant. - :type scopes: ``list`` - - :keyword redirect_uri: The Redirect URI for the authentication - request. See Google OAUTH2 documentation for - more info. - :type redirect_uri: ``str`` - - :keyword login_hint: Login hint for authentication request. Useful - for Installed Application authentication. - :type login_hint: ``str`` - """ - scopes = scopes or [] - - self.scopes = " ".join(scopes) - self.redirect_uri = redirect_uri - self.login_hint = login_hint - - super(GoogleBaseAuthConnection, self).__init__(user_id, key, **kwargs) - - def _now(self): - return datetime.datetime.utcnow() - - def add_default_headers(self, headers): - headers['Content-Type'] = "application/x-www-form-urlencoded" - headers['Host'] = self.host - return headers - - def _token_request(self, request_body): - """ - Return an updated token from a token request body. - - :param request_body: A dictionary of values to send in the body of the - token request. - :type request_body: ``dict`` - - :return: A dictionary with updated token information - :rtype: ``dict`` - """ - data = urlencode(request_body) - now = self._now() - response = self.request('/o/oauth2/token', method='POST', data=data) - token_info = response.object - if 'expires_in' in token_info: - expire_time = now + datetime.timedelta( - seconds=token_info['expires_in']) - token_info['expire_time'] = expire_time.strftime(TIMESTAMP_FORMAT) - return token_info - - -class GoogleInstalledAppAuthConnection(GoogleBaseAuthConnection): - """Authentication connection for "Installed Application" authentication.""" - def get_code(self): - """ - Give the user a URL that they can visit to authenticate and obtain a - code. This method will ask for that code that the user can paste in. - - :return: Code supplied by the user after authenticating - :rtype: ``str`` - """ - auth_params = {'response_type': 'code', - 'client_id': self.user_id, - 'redirect_uri': self.redirect_uri, - 'scope': self.scopes, - 'state': 'Libcloud Request'} - if self.login_hint: - auth_params['login_hint'] = self.login_hint - - data = urlencode(auth_params) - - url = 'https://%s%s?%s' % (self.host, self.auth_path, data) - print('Please Go to the following URL and sign in:') - print(url) - if PY3: - code = input('Enter Code:') - else: - code = raw_input('Enter Code:') - return code - - def get_new_token(self): - """ - Get a new token. Generally used when no previous token exists or there - is no refresh token - - :return: Dictionary containing token information - :rtype: ``dict`` - """ - # Ask the user for a code - code = self.get_code() - - token_request = {'code': code, - 'client_id': self.user_id, - 'client_secret': self.key, - 'redirect_uri': self.redirect_uri, - 'grant_type': 'authorization_code'} - - return self._token_request(token_request) - - def refresh_token(self, token_info): - """ - Use the refresh token supplied in the token info to get a new token. - - :param token_info: Dictionary containing current token information - :type token_info: ``dict`` - - :return: A dictionary containing updated token information. - :rtype: ``dict`` - """ - if 'refresh_token' not in token_info: - return self.get_new_token() - refresh_request = {'refresh_token': token_info['refresh_token'], - 'client_id': self.user_id, - 'client_secret': self.key, - 'grant_type': 'refresh_token'} - - new_token = self._token_request(refresh_request) - if 'refresh_token' not in new_token: - new_token['refresh_token'] = token_info['refresh_token'] - return new_token - - -class GoogleServiceAcctAuthConnection(GoogleBaseAuthConnection): - """Authentication class for "Service Account" authentication.""" - def __init__(self, user_id, key, *args, **kwargs): - """ - Check to see if PyCrypto is available, and convert key file path into a - key string if the key is in a file. - - :param user_id: Email address to be used for Service Account - authentication. - :type user_id: ``str`` - - :param key: The RSA Key or path to file containing the key. - :type key: ``str`` - """ - if SHA256 is None: - raise GoogleAuthError('PyCrypto library required for ' - 'Service Account Authentication.') - # Check to see if 'key' is a file and read the file if it is. - keypath = os.path.expanduser(key) - is_file_path = os.path.exists(keypath) and os.path.isfile(keypath) - if is_file_path: - with open(keypath, 'r') as f: - key = f.read() - super(GoogleServiceAcctAuthConnection, self).__init__( - user_id, key, *args, **kwargs) - - def get_new_token(self): - """ - Get a new token using the email address and RSA Key. - - :return: Dictionary containing token information - :rtype: ``dict`` - """ - # The header is always the same - header = {'alg': 'RS256', 'typ': 'JWT'} - header_enc = base64.urlsafe_b64encode(json.dumps(header)) - - # Construct a claim set - claim_set = {'iss': self.user_id, - 'scope': self.scopes, - 'aud': 'https://accounts.google.com/o/oauth2/token', - 'exp': int(time.time()) + 3600, - 'iat': int(time.time())} - claim_set_enc = base64.urlsafe_b64encode(json.dumps(claim_set)) - - # The message contains both the header and claim set - message = '%s.%s' % (header_enc, claim_set_enc) - # Then the message is signed using the key supplied - key = RSA.importKey(self.key) - hash_func = SHA256.new(message) - signer = PKCS1_v1_5.new(key) - signature = base64.urlsafe_b64encode(signer.sign(hash_func)) - - # Finally the message and signature are sent to get a token - jwt = '%s.%s' % (message, signature) - request = {'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', - 'assertion': jwt} - - return self._token_request(request) - - def refresh_token(self, token_info): - """ - Refresh the current token. - - Service Account authentication doesn't supply a "refresh token" so - this simply gets a new token using the email address/key. - - :param token_info: Dictionary containing token information. - (Not used, but here for compatibility) - :type token_info: ``dict`` - - :return: A dictionary containing updated token information. - :rtype: ``dict`` - """ - return self.get_new_token() - - -class GoogleBaseConnection(ConnectionUserAndKey, PollingConnection): - """Base connection class for interacting with Google APIs.""" - driver = GoogleBaseDriver - responseCls = GoogleResponse - host = 'www.googleapis.com' - poll_interval = 2.0 - timeout = 180 - - def __init__(self, user_id, key, auth_type=None, - credential_file=None, scopes=None, **kwargs): - """ - Determine authentication type, set up appropriate authentication - connection and get initial authentication information. - - :param user_id: The email address (for service accounts) or Client ID - (for installed apps) to be used for authentication. - :type user_id: ``str`` - - :param key: The RSA Key (for service accounts) or file path containing - key or Client Secret (for installed apps) to be used for - authentication. - :type key: ``str`` - - :keyword auth_type: Accepted values are "SA" or "IA" - ("Service Account" or "Installed Application"). - If not supplied, auth_type will be guessed based - on value of user_id. - :type auth_type: ``str`` - - :keyword credential_file: Path to file for caching authentication - information. - :type credential_file: ``str`` - - :keyword scopes: List of OAuth2 scope URLs. The empty default sets - read/write access to Compute, Storage, and DNS. - :type scopes: ``list`` - """ - self.credential_file = credential_file or '~/.gce_libcloud_auth' - - if auth_type is None: - # Try to guess. Service accounts use an email address - # as the user id. - if '@' in user_id: - auth_type = 'SA' - else: - auth_type = 'IA' - - # Default scopes to read/write for compute, storage, and dns. Can - # override this when calling get_driver() or setting in secrets.py - self.scopes = scopes - if not self.scopes: - self.scopes = [ - 'https://www.googleapis.com/auth/compute', - 'https://www.googleapis.com/auth/devstorage.full_control', - 'https://www.googleapis.com/auth/ndev.clouddns.readwrite', - ] - self.token_info = self._get_token_info_from_file() - - if auth_type == 'SA': - self.auth_conn = GoogleServiceAcctAuthConnection( - user_id, key, self.scopes, **kwargs) - elif auth_type == 'IA': - self.auth_conn = GoogleInstalledAppAuthConnection( - user_id, key, self.scopes, **kwargs) - else: - raise GoogleAuthError('auth_type should be \'SA\' or \'IA\'') - - if self.token_info is None: - self.token_info = self.auth_conn.get_new_token() - self._write_token_info_to_file() - - self.token_expire_time = datetime.datetime.strptime( - self.token_info['expire_time'], TIMESTAMP_FORMAT) - - super(GoogleBaseConnection, self).__init__(user_id, key, **kwargs) - - python_ver = '%s.%s.%s' % (sys.version_info[0], sys.version_info[1], - sys.version_info[2]) - ver_platform = 'Python %s/%s' % (python_ver, sys.platform) - self.user_agent_append(ver_platform) - - def _now(self): - return datetime.datetime.utcnow() - - def add_default_headers(self, headers): - """ - @inherits: :class:`Connection.add_default_headers` - """ - headers['Content-Type'] = "application/json" - headers['Host'] = self.host - return headers - - def pre_connect_hook(self, params, headers): - """ - Check to make sure that token hasn't expired. If it has, get an - updated token. Also, add the token to the headers. - - @inherits: :class:`Connection.pre_connect_hook` - """ - now = self._now() - if self.token_expire_time < now: - self.token_info = self.auth_conn.refresh_token(self.token_info) - self.token_expire_time = datetime.datetime.strptime( - self.token_info['expire_time'], TIMESTAMP_FORMAT) - self._write_token_info_to_file() - headers['Authorization'] = 'Bearer %s' % ( - self.token_info['access_token']) - - return params, headers - - def encode_data(self, data): - """Encode data to JSON""" - return json.dumps(data) - - def request(self, *args, **kwargs): - """ - @inherits: :class:`Connection.request` - """ - # Adds some retry logic for the occasional - # "Connection Reset by peer" error. - retries = 4 - tries = 0 - while tries < (retries - 1): - try: - return super(GoogleBaseConnection, self).request( - *args, **kwargs) - except socket.error: - e = sys.exc_info()[1] - if e.errno == errno.ECONNRESET: - tries = tries + 1 - else: - raise e - # One more time, then give up. - return super(GoogleBaseConnection, self).request(*args, **kwargs) - - def _get_token_info_from_file(self): - """ - Read credential file and return token information. - - :return: Token information dictionary, or None - :rtype: ``dict`` or ``None`` - """ - token_info = None - filename = os.path.realpath(os.path.expanduser(self.credential_file)) - - try: - with open(filename, 'r') as f: - data = f.read() - token_info = json.loads(data) - except IOError: - pass - return token_info - - def _write_token_info_to_file(self): - """ - Write token_info to credential file. - """ - filename = os.path.realpath(os.path.expanduser(self.credential_file)) - data = json.dumps(self.token_info) - with open(filename, 'w') as f: - f.write(data) - - def has_completed(self, response): - """ - Determine if operation has completed based on response. - - :param response: JSON response - :type response: I{responseCls} - - :return: True if complete, False otherwise - :rtype: ``bool`` - """ - if response.object['status'] == 'DONE': - return True - else: - return False - - def get_poll_request_kwargs(self, response, context, request_kwargs): - """ - @inherits: :class:`PollingConnection.get_poll_request_kwargs` - """ - return {'action': response.object['selfLink']} - - def morph_action_hook(self, action): - """ - Update action to correct request path. - - In many places, the Google API returns a full URL to a resource. - This will strip the scheme and host off of the path and just return - the request. Otherwise, it will append the base request_path to - the action. - - :param action: The action to be called in the http request - :type action: ``str`` - - :return: The modified request based on the action - :rtype: ``str`` - """ - if action.startswith('https://'): - u = urlparse.urlsplit(action) - request = urlparse.urlunsplit(('', '', u[2], u[3], u[4])) - else: - request = self.request_path + action - return request diff --git a/awx/lib/site-packages/libcloud/common/hostvirtual.py b/awx/lib/site-packages/libcloud/common/hostvirtual.py deleted file mode 100644 index e7ce14daba..0000000000 --- a/awx/lib/site-packages/libcloud/common/hostvirtual.py +++ /dev/null @@ -1,77 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import httplib -from libcloud.common.base import ConnectionKey, JsonResponse -from libcloud.compute.types import InvalidCredsError -from libcloud.common.types import LibcloudError - -API_HOST = 'vapi.vr.org' - - -class HostVirtualException(LibcloudError): - def __init__(self, code, message): - self.code = code - self.message = message - self.args = (code, message) - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return '<HostVirtualException in %d: %s>' % (self.code, self.message) - - -class HostVirtualConnection(ConnectionKey): - host = API_HOST - - allow_insecure = False - - def add_default_params(self, params): - params['key'] = self.key - return params - - -class HostVirtualResponse(JsonResponse): - valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, - httplib.NO_CONTENT] - - def parse_body(self): - if not self.body: - return None - - data = json.loads(self.body) - return data - - def parse_error(self): - data = self.parse_body() - - if self.status == httplib.UNAUTHORIZED: - raise InvalidCredsError('%(code)s:%(message)s' % (data['error'])) - elif self.status == httplib.PRECONDITION_FAILED: - raise HostVirtualException( - data['error']['code'], data['error']['message']) - elif self.status == httplib.NOT_FOUND: - raise HostVirtualException( - data['error']['code'], data['error']['message']) - - return self.body - - def success(self): - return self.status in self.valid_response_codes diff --git a/awx/lib/site-packages/libcloud/common/linode.py b/awx/lib/site-packages/libcloud/common/linode.py deleted file mode 100644 index f7ee22bdd2..0000000000 --- a/awx/lib/site-packages/libcloud/common/linode.py +++ /dev/null @@ -1,176 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.common.base import ConnectionKey, JsonResponse -from libcloud.common.types import InvalidCredsError - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import b - -__all__ = [ - 'API_HOST', - 'API_ROOT', - 'LinodeException', - 'LinodeResponse', - 'LinodeConnection' -] - -# Endpoint for the Linode API -API_HOST = 'api.linode.com' -API_ROOT = '/' - -# Constants that map a RAM figure to a PlanID (updated 4/25/14) -LINODE_PLAN_IDS = {2048: '1', - 4096: '3', - 8192: '5', - 16384: '6', - 32768: '7', - 49152: '8', - 65536: '9', - 98304: '11'} - - -class LinodeException(Exception): - """Error originating from the Linode API - - This class wraps a Linode API error, a list of which is available in the - API documentation. All Linode API errors are a numeric code and a - human-readable description. - """ - def __init__(self, code, message): - self.code = code - self.message = message - self.args = (code, message) - - def __str__(self): - return "(%u) %s" % (self.code, self.message) - - def __repr__(self): - return "<LinodeException code %u '%s'>" % (self.code, self.message) - - -class LinodeResponse(JsonResponse): - """Linode API response - - Wraps the HTTP response returned by the Linode API, which should be JSON in - this structure: - - { - "ERRORARRAY": [ ... ], - "DATA": [ ... ], - "ACTION": " ... " - } - - libcloud does not take advantage of batching, so a response will always - reflect the above format. A few weird quirks are caught here as well.""" - def __init__(self, response, connection): - """Instantiate a LinodeResponse from the HTTP response - - :keyword response: The raw response returned by urllib - :return: parsed :class:`LinodeResponse`""" - - self.connection = connection - - self.headers = dict(response.getheaders()) - self.error = response.reason - self.status = response.status - - self.body = self._decompress_response(body=response.read(), - headers=self.headers) - - if PY3: - self.body = b(self.body).decode('utf-8') - - self.invalid = LinodeException(0xFF, - "Invalid JSON received from server") - - # Move parse_body() to here; we can't be sure of failure until we've - # parsed the body into JSON. - self.objects, self.errors = self.parse_body() - - if not self.success(): - # Raise the first error, as there will usually only be one - raise self.errors[0] - - def parse_body(self): - """Parse the body of the response into JSON objects - - If the response chokes the parser, action and data will be returned as - None and errorarray will indicate an invalid JSON exception. - - :return: ``list`` of objects and ``list`` of errors""" - js = super(LinodeResponse, self).parse_body() - - try: - if isinstance(js, dict): - # solitary response - promote to list - js = [js] - ret = [] - errs = [] - for obj in js: - if ("DATA" not in obj or "ERRORARRAY" not in obj - or "ACTION" not in obj): - ret.append(None) - errs.append(self.invalid) - continue - ret.append(obj["DATA"]) - errs.extend(self._make_excp(e) for e in obj["ERRORARRAY"]) - return (ret, errs) - except: - return (None, [self.invalid]) - - def success(self): - """Check the response for success - - The way we determine success is by the presence of an error in - ERRORARRAY. If one is there, we assume the whole request failed. - - :return: ``bool`` indicating a successful request""" - return len(self.errors) == 0 - - def _make_excp(self, error): - """Convert an API error to a LinodeException instance - - :keyword error: JSON object containing ``ERRORCODE`` and - ``ERRORMESSAGE`` - :type error: dict""" - if "ERRORCODE" not in error or "ERRORMESSAGE" not in error: - return None - if error["ERRORCODE"] == 4: - return InvalidCredsError(error["ERRORMESSAGE"]) - return LinodeException(error["ERRORCODE"], error["ERRORMESSAGE"]) - - -class LinodeConnection(ConnectionKey): - """ - A connection to the Linode API - - Wraps SSL connections to the Linode API, automagically injecting the - parameters that the API needs for each request. - """ - host = API_HOST - responseCls = LinodeResponse - - def add_default_params(self, params): - """ - Add parameters that are necessary for every request - - This method adds ``api_key`` and ``api_responseFormat`` to - the request. - """ - params["api_key"] = self.key - # Be explicit about this in case the default changes. - params["api_responseFormat"] = "json" - return params diff --git a/awx/lib/site-packages/libcloud/common/openstack.py b/awx/lib/site-packages/libcloud/common/openstack.py deleted file mode 100644 index 26bf6920b5..0000000000 --- a/awx/lib/site-packages/libcloud/common/openstack.py +++ /dev/null @@ -1,652 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Common utilities for OpenStack -""" -import sys -import datetime - -from libcloud.utils.py3 import httplib -from libcloud.utils.iso8601 import parse_date - -from libcloud.common.base import ConnectionUserAndKey, Response -from libcloud.compute.types import (LibcloudError, InvalidCredsError, - MalformedResponseError) - -try: - import simplejson as json -except ImportError: - import json - -AUTH_API_VERSION = '1.1' - -# Auth versions which contain token expiration information. -AUTH_VERSIONS_WITH_EXPIRES = [ - '1.1', - '2.0', - '2.0_apikey', - '2.0_password' -] - -# How many seconds to substract from the auth token expiration time before -# testing if the token is still valid. -# The time is subtracted to account for the HTTP request latency and prevent -# user from getting "InvalidCredsError" if token is about to expire. -AUTH_TOKEN_EXPIRES_GRACE_SECONDS = 5 - -__all__ = [ - 'OpenStackBaseConnection', - 'OpenStackAuthConnection', - 'OpenStackServiceCatalog', - 'OpenStackDriverMixin', - - 'AUTH_TOKEN_EXPIRES_GRACE_SECONDS' -] - - -# @TODO: Refactor for re-use by other openstack drivers -class OpenStackAuthResponse(Response): - def success(self): - return True - - def parse_body(self): - if not self.body: - return None - - if 'content-type' in self.headers: - key = 'content-type' - elif 'Content-Type' in self.headers: - key = 'Content-Type' - else: - raise LibcloudError('Missing content-type header', - driver=OpenStackAuthConnection) - - content_type = self.headers[key] - if content_type.find(';') != -1: - content_type = content_type.split(';')[0] - - if content_type == 'application/json': - try: - data = json.loads(self.body) - except: - raise MalformedResponseError('Failed to parse JSON', - body=self.body, - driver=OpenStackAuthConnection) - elif content_type == 'text/plain': - data = self.body - else: - data = self.body - - return data - - -class OpenStackAuthConnection(ConnectionUserAndKey): - - responseCls = OpenStackAuthResponse - name = 'OpenStack Auth' - timeout = None - - def __init__(self, parent_conn, auth_url, auth_version, user_id, key, - tenant_name=None, timeout=None): - self.parent_conn = parent_conn - # enable tests to use the same mock connection classes. - self.conn_classes = parent_conn.conn_classes - - super(OpenStackAuthConnection, self).__init__( - user_id, key, url=auth_url, timeout=timeout) - - self.auth_version = auth_version - self.auth_url = auth_url - self.driver = self.parent_conn.driver - self.tenant_name = tenant_name - self.timeout = timeout - - self.urls = {} - self.auth_token = None - self.auth_token_expires = None - self.auth_user_info = None - - def morph_action_hook(self, action): - (_, _, _, request_path) = self._tuple_from_url(self.auth_url) - - if request_path == '': - # No path is provided in the auth_url, use action passed to this - # method. - return action - - return request_path - - def add_default_headers(self, headers): - headers['Accept'] = 'application/json' - headers['Content-Type'] = 'application/json; charset=UTF-8' - return headers - - def authenticate(self, force=False): - """ - Authenticate against the keystone api. - - :param force: Forcefully update the token even if it's already cached - and still valid. - :type force: ``bool`` - """ - if not force and self.auth_version in AUTH_VERSIONS_WITH_EXPIRES \ - and self.is_token_valid(): - # If token is still valid, there is no need to re-authenticate - return self - - if self.auth_version == "1.0": - return self.authenticate_1_0() - elif self.auth_version == "1.1": - return self.authenticate_1_1() - elif self.auth_version == "2.0" or self.auth_version == "2.0_apikey": - return self.authenticate_2_0_with_apikey() - elif self.auth_version == "2.0_password": - return self.authenticate_2_0_with_password() - else: - raise LibcloudError('Unsupported Auth Version requested') - - def authenticate_1_0(self): - headers = { - 'X-Auth-User': self.user_id, - 'X-Auth-Key': self.key, - } - - resp = self.request('/v1.0', headers=headers, method='GET') - - if resp.status == httplib.UNAUTHORIZED: - # HTTP UNAUTHORIZED (401): auth failed - raise InvalidCredsError() - elif resp.status not in [httplib.NO_CONTENT, httplib.OK]: - body = 'code: %s body:%s headers:%s' % (resp.status, - resp.body, - resp.headers) - raise MalformedResponseError('Malformed response', body=body, - driver=self.driver) - else: - headers = resp.headers - # emulate the auth 1.1 URL list - self.urls = {} - self.urls['cloudServers'] = \ - [{'publicURL': headers.get('x-server-management-url', None)}] - self.urls['cloudFilesCDN'] = \ - [{'publicURL': headers.get('x-cdn-management-url', None)}] - self.urls['cloudFiles'] = \ - [{'publicURL': headers.get('x-storage-url', None)}] - self.auth_token = headers.get('x-auth-token', None) - self.auth_user_info = None - - if not self.auth_token: - raise MalformedResponseError('Missing X-Auth-Token in \ - response headers') - - return self - - def authenticate_1_1(self): - reqbody = json.dumps({'credentials': {'username': self.user_id, - 'key': self.key}}) - resp = self.request('/v1.1/auth', data=reqbody, headers={}, - method='POST') - - if resp.status == httplib.UNAUTHORIZED: - # HTTP UNAUTHORIZED (401): auth failed - raise InvalidCredsError() - elif resp.status != httplib.OK: - body = 'code: %s body:%s' % (resp.status, resp.body) - raise MalformedResponseError('Malformed response', body=body, - driver=self.driver) - else: - try: - body = json.loads(resp.body) - except Exception: - e = sys.exc_info()[1] - raise MalformedResponseError('Failed to parse JSON', e) - - try: - expires = body['auth']['token']['expires'] - - self.auth_token = body['auth']['token']['id'] - self.auth_token_expires = parse_date(expires) - self.urls = body['auth']['serviceCatalog'] - self.auth_user_info = None - except KeyError: - e = sys.exc_info()[1] - raise MalformedResponseError('Auth JSON response is \ - missing required elements', e) - - return self - - def authenticate_2_0_with_apikey(self): - # API Key based authentication uses the RAX-KSKEY extension. - # http://s.apache.org/oAi - data = {'auth': - {'RAX-KSKEY:apiKeyCredentials': - {'username': self.user_id, 'apiKey': self.key}}} - if self.tenant_name: - data['auth']['tenantName'] = self.tenant_name - reqbody = json.dumps(data) - return self.authenticate_2_0_with_body(reqbody) - - def authenticate_2_0_with_password(self): - # Password based authentication is the only 'core' authentication - # method in Keystone at this time. - # 'keystone' - http://s.apache.org/e8h - data = {'auth': - {'passwordCredentials': - {'username': self.user_id, 'password': self.key}}} - if self.tenant_name: - data['auth']['tenantName'] = self.tenant_name - reqbody = json.dumps(data) - return self.authenticate_2_0_with_body(reqbody) - - def authenticate_2_0_with_body(self, reqbody): - resp = self.request('/v2.0/tokens', data=reqbody, - headers={'Content-Type': 'application/json'}, - method='POST') - if resp.status == httplib.UNAUTHORIZED: - raise InvalidCredsError() - elif resp.status not in [httplib.OK, - httplib.NON_AUTHORITATIVE_INFORMATION]: - body = 'code: %s body: %s' % (resp.status, resp.body) - raise MalformedResponseError('Malformed response', body=body, - driver=self.driver) - else: - try: - body = json.loads(resp.body) - except Exception: - e = sys.exc_info()[1] - raise MalformedResponseError('Failed to parse JSON', e) - - try: - access = body['access'] - expires = access['token']['expires'] - - self.auth_token = access['token']['id'] - self.auth_token_expires = parse_date(expires) - self.urls = access['serviceCatalog'] - self.auth_user_info = access.get('user', {}) - except KeyError: - e = sys.exc_info()[1] - raise MalformedResponseError('Auth JSON response is \ - missing required elements', e) - - return self - - def is_token_valid(self): - """ - Return True if the current auth token is already cached and hasn't - expired yet. - - :return: ``True`` if the token is still valid, ``False`` otherwise. - :rtype: ``bool`` - """ - if not self.auth_token: - return False - - if not self.auth_token_expires: - return False - - expires = self.auth_token_expires - \ - datetime.timedelta(seconds=AUTH_TOKEN_EXPIRES_GRACE_SECONDS) - - time_tuple_expires = expires.utctimetuple() - time_tuple_now = datetime.datetime.utcnow().utctimetuple() - - if time_tuple_now < time_tuple_expires: - return True - - return False - - -class OpenStackServiceCatalog(object): - """ - http://docs.openstack.org/api/openstack-identity-service/2.0/content/ - - This class should be instanciated with the contents of the - 'serviceCatalog' in the auth response. This will do the work of figuring - out which services actually exist in the catalog as well as split them up - by type, name, and region if available - """ - - _auth_version = None - _service_catalog = None - - def __init__(self, service_catalog, ex_force_auth_version=None): - self._auth_version = ex_force_auth_version or AUTH_API_VERSION - self._service_catalog = {} - - # Check this way because there are a couple of different 2.0_* - # auth types. - if '2.0' in self._auth_version: - self._parse_auth_v2(service_catalog) - elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version): - self._parse_auth_v1(service_catalog) - else: - raise LibcloudError('auth version "%s" not supported' - % (self._auth_version)) - - def get_catalog(self): - return self._service_catalog - - def get_public_urls(self, service_type=None, name=None): - endpoints = self.get_endpoints(service_type=service_type, - name=name) - - result = [] - for endpoint in endpoints: - if 'publicURL' in endpoint: - result.append(endpoint['publicURL']) - - return result - - def get_endpoints(self, service_type=None, name=None): - eps = [] - - if '2.0' in self._auth_version: - endpoints = self._service_catalog.get(service_type, {}) \ - .get(name, {}) - elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version): - endpoints = self._service_catalog.get(name, {}) - - for regionName, values in endpoints.items(): - eps.append(values[0]) - - return eps - - def get_endpoint(self, service_type=None, name=None, region=None): - if '2.0' in self._auth_version: - endpoint = self._service_catalog.get(service_type, {}) \ - .get(name, {}).get(region, []) - elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version): - endpoint = self._service_catalog.get(name, {}).get(region, []) - - # ideally an endpoint either isn't found or only one match is found. - if len(endpoint) == 1: - return endpoint[0] - else: - return {} - - def _parse_auth_v1(self, service_catalog): - for service, endpoints in service_catalog.items(): - - self._service_catalog[service] = {} - - for endpoint in endpoints: - region = endpoint.get('region') - - if region not in self._service_catalog[service]: - self._service_catalog[service][region] = [] - - self._service_catalog[service][region].append(endpoint) - - def _parse_auth_v2(self, service_catalog): - for service in service_catalog: - service_type = service['type'] - service_name = service.get('name', None) - - if service_type not in self._service_catalog: - self._service_catalog[service_type] = {} - - if service_name not in self._service_catalog[service_type]: - self._service_catalog[service_type][service_name] = {} - - for endpoint in service.get('endpoints', []): - region = endpoint.get('region', None) - - catalog = self._service_catalog[service_type][service_name] - if region not in catalog: - catalog[region] = [] - - catalog[region].append(endpoint) - - -class OpenStackBaseConnection(ConnectionUserAndKey): - - """ - Base class for OpenStack connections. - - :param user_id: User name to use when authenticating - :type user_id: ``str`` - - :param key: Secret to use when authenticating. - :type key: ``str`` - - :param secure: Use HTTPS? (True by default.) - :type secure: ``bool`` - - :param ex_force_base_url: Base URL for connection requests. If - not specified, this will be determined by authenticating. - :type ex_force_base_url: ``str`` - - :param ex_force_auth_url: Base URL for authentication requests. - :type ex_force_auth_url: ``str`` - - :param ex_force_auth_version: Authentication version to use. If - not specified, defaults to AUTH_API_VERSION. - :type ex_force_auth_version: ``str`` - - :param ex_force_auth_token: Authentication token to use for - connection requests. If specified, the connection will not attempt - to authenticate, and the value of ex_force_base_url will be used to - determine the base request URL. If ex_force_auth_token is passed in, - ex_force_base_url must also be provided. - :type ex_force_auth_token: ``str`` - - :param ex_tenant_name: When authenticating, provide this tenant - name to the identity service. A scoped token will be returned. - Some cloud providers require the tenant name to be provided at - authentication time. Others will use a default tenant if none - is provided. - :type ex_tenant_name: ``str`` - - :param ex_force_service_type: Service type to use when selecting an - service. If not specified, a provider specific default will be used. - :type ex_force_service_type: ``str`` - - :param ex_force_service_name: Service name to use when selecting an - service. If not specified, a provider specific default will be used. - :type ex_force_service_name: ``str`` - - :param ex_force_service_region: Region to use when selecting an - service. If not specified, a provider specific default will be used. - :type ex_force_service_region: ``str`` - """ - - auth_url = None - auth_token = None - auth_token_expires = None - auth_user_info = None - service_catalog = None - service_type = None - service_name = None - service_region = None - _auth_version = None - - def __init__(self, user_id, key, secure=True, - host=None, port=None, timeout=None, - ex_force_base_url=None, - ex_force_auth_url=None, - ex_force_auth_version=None, - ex_force_auth_token=None, - ex_tenant_name=None, - ex_force_service_type=None, - ex_force_service_name=None, - ex_force_service_region=None): - super(OpenStackBaseConnection, self).__init__( - user_id, key, secure=secure, timeout=timeout) - - if ex_force_auth_version: - self._auth_version = ex_force_auth_version - - self._ex_force_base_url = ex_force_base_url - self._ex_force_auth_url = ex_force_auth_url - self._ex_force_auth_token = ex_force_auth_token - self._ex_tenant_name = ex_tenant_name - self._ex_force_service_type = ex_force_service_type - self._ex_force_service_name = ex_force_service_name - self._ex_force_service_region = ex_force_service_region - - if ex_force_auth_token and not ex_force_base_url: - raise LibcloudError( - 'Must also provide ex_force_base_url when specifying ' - 'ex_force_auth_token.') - - if ex_force_auth_token: - self.auth_token = ex_force_auth_token - - if not self._auth_version: - self._auth_version = AUTH_API_VERSION - - auth_url = self._get_auth_url() - - if not auth_url: - raise LibcloudError('OpenStack instance must ' + - 'have auth_url set') - - osa = OpenStackAuthConnection(self, auth_url, self._auth_version, - self.user_id, self.key, - tenant_name=self._ex_tenant_name, - timeout=self.timeout) - self._osa = osa - - def _get_auth_url(self): - """ - Retrieve auth url for this instance using either "ex_force_auth_url" - constructor kwarg of "auth_url" class variable. - """ - auth_url = self.auth_url - - if self._ex_force_auth_url is not None: - auth_url = self._ex_force_auth_url - - return auth_url - - def get_service_catalog(self): - if self.service_catalog is None: - self._populate_hosts_and_request_paths() - - return self.service_catalog - - def get_endpoint(self): - """ - Selects the endpoint to use based on provider specific values, - or overrides passed in by the user when setting up the driver. - - :returns: url of the relevant endpoint for the driver - """ - service_type = self.service_type - service_name = self.service_name - service_region = self.service_region - if self._ex_force_service_type: - service_type = self._ex_force_service_type - if self._ex_force_service_name: - service_name = self._ex_force_service_name - if self._ex_force_service_region: - service_region = self._ex_force_service_region - - ep = self.service_catalog.get_endpoint(service_type=service_type, - name=service_name, - region=service_region) - if 'publicURL' in ep: - return ep['publicURL'] - - raise LibcloudError('Could not find specified endpoint') - - def add_default_headers(self, headers): - headers['X-Auth-Token'] = self.auth_token - headers['Accept'] = self.accept_format - return headers - - def morph_action_hook(self, action): - self._populate_hosts_and_request_paths() - return super(OpenStackBaseConnection, self).morph_action_hook(action) - - def request(self, **kwargs): - return super(OpenStackBaseConnection, self).request(**kwargs) - - def _set_up_connection_info(self, url): - result = self._tuple_from_url(url) - (self.host, self.port, self.secure, self.request_path) = result - - def _populate_hosts_and_request_paths(self): - """ - OpenStack uses a separate host for API calls which is only provided - after an initial authentication request. - """ - osa = self._osa - - if self._ex_force_auth_token: - # If ex_force_auth_token is provided we always hit the api directly - # and never try to authenticate. - # - # Note: When ex_force_auth_token is provided, ex_force_base_url - # must be provided as well. - self._set_up_connection_info(url=self._ex_force_base_url) - return - - if not osa.is_token_valid(): - # Token is not available or it has expired. Need to retrieve a - # new one. - osa.authenticate() # may throw InvalidCreds - - self.auth_token = osa.auth_token - self.auth_token_expires = osa.auth_token_expires - self.auth_user_info = osa.auth_user_info - - # Pull out and parse the service catalog - osc = OpenStackServiceCatalog( - osa.urls, ex_force_auth_version=self._auth_version) - self.service_catalog = osc - - url = self._ex_force_base_url or self.get_endpoint() - self._set_up_connection_info(url=url) - - -class OpenStackDriverMixin(object): - - def __init__(self, *args, **kwargs): - self._ex_force_base_url = kwargs.get('ex_force_base_url', None) - self._ex_force_auth_url = kwargs.get('ex_force_auth_url', None) - self._ex_force_auth_version = kwargs.get('ex_force_auth_version', None) - self._ex_force_auth_token = kwargs.get('ex_force_auth_token', None) - self._ex_tenant_name = kwargs.get('ex_tenant_name', None) - self._ex_force_service_type = kwargs.get('ex_force_service_type', None) - self._ex_force_service_name = kwargs.get('ex_force_service_name', None) - self._ex_force_service_region = kwargs.get('ex_force_service_region', - None) - - def openstack_connection_kwargs(self): - """ - - :rtype: ``dict`` - """ - rv = {} - if self._ex_force_base_url: - rv['ex_force_base_url'] = self._ex_force_base_url - if self._ex_force_auth_token: - rv['ex_force_auth_token'] = self._ex_force_auth_token - if self._ex_force_auth_url: - rv['ex_force_auth_url'] = self._ex_force_auth_url - if self._ex_force_auth_version: - rv['ex_force_auth_version'] = self._ex_force_auth_version - if self._ex_tenant_name: - rv['ex_tenant_name'] = self._ex_tenant_name - if self._ex_force_service_type: - rv['ex_force_service_type'] = self._ex_force_service_type - if self._ex_force_service_name: - rv['ex_force_service_name'] = self._ex_force_service_name - if self._ex_force_service_region: - rv['ex_force_service_region'] = self._ex_force_service_region - return rv diff --git a/awx/lib/site-packages/libcloud/common/rackspace.py b/awx/lib/site-packages/libcloud/common/rackspace.py deleted file mode 100644 index 3826ba6f62..0000000000 --- a/awx/lib/site-packages/libcloud/common/rackspace.py +++ /dev/null @@ -1,24 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Common settings for Rackspace Cloud Servers and Cloud Files -""" - -__all__ = [ - 'AUTH_URL' -] - -AUTH_URL = 'https://auth.api.rackspacecloud.com' diff --git a/awx/lib/site-packages/libcloud/common/types.py b/awx/lib/site-packages/libcloud/common/types.py deleted file mode 100644 index 98250c1ba2..0000000000 --- a/awx/lib/site-packages/libcloud/common/types.py +++ /dev/null @@ -1,144 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.utils.py3 import httplib - -__all__ = [ - "LibcloudError", - "MalformedResponseError", - "ProviderError", - "InvalidCredsError", - "InvalidCredsException", - "LazyList" -] - - -class LibcloudError(Exception): - """The base class for other libcloud exceptions""" - - def __init__(self, value, driver=None): - self.value = value - self.driver = driver - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return ("<LibcloudError in " - + repr(self.driver) - + " " - + repr(self.value) + ">") - - -class MalformedResponseError(LibcloudError): - """Exception for the cases when a provider returns a malformed - response, e.g. you request JSON and provider returns - '<h3>something</h3>' due to some error on their side.""" - - def __init__(self, value, body=None, driver=None): - self.value = value - self.driver = driver - self.body = body - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return ("<MalformedResponseException in " - + repr(self.driver) - + " " - + repr(self.value) - + ">: " - + repr(self.body)) - - -class ProviderError(LibcloudError): - """ - Exception used when provider gives back - error response (HTTP 4xx, 5xx) for a request. - - Specific sub types can be derieved for errors like - HTTP 401 : InvalidCredsError - HTTP 404 : NodeNotFoundError, ContainerDoesNotExistError - """ - - def __init__(self, value, http_code, - driver=None): - self.value = value - self.http_code = http_code - self.driver = driver - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return repr(self.value) - - -class InvalidCredsError(ProviderError): - """Exception used when invalid credentials are used on a provider.""" - - def __init__(self, value='Invalid credentials with the provider', - driver=None): - super(InvalidCredsError, self).__init__(value, - http_code=httplib.UNAUTHORIZED, - driver=driver) - - -# Deprecated alias of :class:`InvalidCredsError` -InvalidCredsException = InvalidCredsError - - -class LazyList(object): - - def __init__(self, get_more, value_dict=None): - self._data = [] - self._last_key = None - self._exhausted = False - self._all_loaded = False - self._get_more = get_more - self._value_dict = value_dict or {} - - def __iter__(self): - if not self._all_loaded: - self._load_all() - - data = self._data - for i in data: - yield i - - def __getitem__(self, index): - if index >= len(self._data) and not self._all_loaded: - self._load_all() - - return self._data[index] - - def __len__(self): - self._load_all() - return len(self._data) - - def __repr__(self): - self._load_all() - repr_string = ', ' .join([repr(item) for item in self._data]) - repr_string = '[%s]' % (repr_string) - return repr_string - - def _load_all(self): - while not self._exhausted: - newdata, self._last_key, self._exhausted = \ - self._get_more(last_key=self._last_key, - value_dict=self._value_dict) - self._data.extend(newdata) - self._all_loaded = True diff --git a/awx/lib/site-packages/libcloud/common/xmlrpc.py b/awx/lib/site-packages/libcloud/common/xmlrpc.py deleted file mode 100644 index 2502ea6093..0000000000 --- a/awx/lib/site-packages/libcloud/common/xmlrpc.py +++ /dev/null @@ -1,108 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Base classes for working with xmlrpc APIs -""" - -import sys - -from libcloud.utils.py3 import xmlrpclib -from libcloud.utils.py3 import httplib -from libcloud.common.base import Response, Connection - - -class ProtocolError(Exception): - pass - - -class ErrorCodeMixin(object): - """ - This is a helper for API's that have a well defined collection of error - codes that are easily parsed out of error messages. It acts as a factory: - it finds the right exception for the error code, fetches any parameters it - needs from the context and raises it. - """ - - exceptions = {} - - def raise_exception_for_error(self, error_code, message): - exceptionCls = self.exceptions.get(error_code, None) - if exceptionCls is None: - return - context = self.connection.context - driver = self.connection.driver - params = {} - if hasattr(exceptionCls, 'kwargs'): - for key in exceptionCls.kwargs: - if key in context: - params[key] = context[key] - raise exceptionCls(value=message, driver=driver, **params) - - -class XMLRPCResponse(ErrorCodeMixin, Response): - - defaultExceptionCls = Exception - - def success(self): - return self.status == httplib.OK - - def parse_body(self): - try: - params, methodname = xmlrpclib.loads(self.body) - if len(params) == 1: - params = params[0] - return params - except xmlrpclib.Fault: - e = sys.exc_info()[1] - self.raise_exception_for_error(e.faultCode, e.faultString) - error_string = '%s: %s' % (e.faultCode, e.faultString) - raise self.defaultExceptionCls(error_string) - - def parse_error(self): - msg = 'Server returned an invalid xmlrpc response (%d)' % (self.status) - raise ProtocolError(msg) - - -class XMLRPCConnection(Connection): - """ - Connection class which can call XMLRPC based API's. - - This class uses the xmlrpclib marshalling and demarshalling code but uses - the http transports provided by libcloud giving it better certificate - validation and debugging helpers than the core client library. - """ - - responseCls = XMLRPCResponse - - def add_default_headers(self, headers): - headers['Content-Type'] = 'text/xml' - return headers - - def request(self, method_name, *args, **kwargs): - """ - Call a given `method_name`. - - :type method_name: ``str`` - :param method_name: A method exposed by the xmlrpc endpoint that you - are connecting to. - - :type args: ``tuple`` - :param args: Arguments to invoke with method with. - """ - endpoint = kwargs.get('endpoint', self.endpoint) - data = xmlrpclib.dumps(args, methodname=method_name, allow_none=True) - return super(XMLRPCConnection, self).request(endpoint, - data=data, - method='POST') diff --git a/awx/lib/site-packages/libcloud/compute/__init__.py b/awx/lib/site-packages/libcloud/compute/__init__.py deleted file mode 100644 index 6d0970a00c..0000000000 --- a/awx/lib/site-packages/libcloud/compute/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Module for working with Cloud Servers -""" diff --git a/awx/lib/site-packages/libcloud/compute/base.py b/awx/lib/site-packages/libcloud/compute/base.py deleted file mode 100644 index f9a9e31d60..0000000000 --- a/awx/lib/site-packages/libcloud/compute/base.py +++ /dev/null @@ -1,1477 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Provides base classes for working with drivers -""" - -from __future__ import with_statement - -import sys -import time -import hashlib -import os -import socket -import binascii - -from libcloud.utils.py3 import b - -import libcloud.compute.ssh -from libcloud.pricing import get_size_price -from libcloud.compute.types import NodeState, DeploymentError -from libcloud.compute.ssh import SSHClient -from libcloud.common.base import ConnectionKey -from libcloud.common.base import BaseDriver -from libcloud.common.types import LibcloudError -from libcloud.compute.ssh import have_paramiko - -from libcloud.utils.networking import is_private_subnet -from libcloud.utils.networking import is_valid_ip_address - -if have_paramiko: - from paramiko.ssh_exception import SSHException - SSH_TIMEOUT_EXCEPTION_CLASSES = (SSHException, IOError, socket.gaierror, - socket.error) -else: - SSH_TIMEOUT_EXCEPTION_CLASSES = (IOError, socket.gaierror, socket.error) - -# How long to wait for the node to come online after creating it -NODE_ONLINE_WAIT_TIMEOUT = 10 * 60 - -# How long to try connecting to a remote SSH server when running a deployment -# script. -SSH_CONNECT_TIMEOUT = 5 * 60 - - -__all__ = [ - 'Node', - 'NodeState', - 'NodeSize', - 'NodeImage', - 'NodeLocation', - 'NodeAuthSSHKey', - 'NodeAuthPassword', - 'NodeDriver', - - 'StorageVolume', - 'VolumeSnapshot', - - # Deprecated, moved to libcloud.utils.networking - 'is_private_subnet', - 'is_valid_ip_address' -] - - -class UuidMixin(object): - """ - Mixin class for get_uuid function. - """ - - def __init__(self): - self._uuid = None - - def get_uuid(self): - """ - Unique hash for a node, node image, or node size - - The hash is a function of an SHA1 hash of the node, node image, - or node size's ID and its driver which means that it should be - unique between all objects of its type. - In some subclasses (e.g. GoGridNode) there is no ID - available so the public IP address is used. This means that, - unlike a properly done system UUID, the same UUID may mean a - different system install at a different time - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node() - >>> node.get_uuid() - 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f' - - Note, for example, that this example will always produce the - same UUID! - - :rtype: ``str`` - """ - if not self._uuid: - self._uuid = hashlib.sha1(b('%s:%s' % - (self.id, self.driver.type))).hexdigest() - - return self._uuid - - @property - def uuid(self): - return self.get_uuid() - - -class Node(UuidMixin): - """ - Provide a common interface for handling nodes of all types. - - The Node object provides the interface in libcloud through which - we can manipulate nodes in different cloud providers in the same - way. Node objects don't actually do much directly themselves, - instead the node driver handles the connection to the node. - - You don't normally create a node object yourself; instead you use - a driver and then have that create the node for you. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node() - >>> node.public_ips[0] - '127.0.0.3' - >>> node.name - 'dummy-3' - - You can also get nodes from the driver's list_node function. - - >>> node = driver.list_nodes()[0] - >>> node.name - 'dummy-1' - - The node keeps a reference to its own driver which means that we - can work on nodes from different providers without having to know - which is which. - - >>> driver = DummyNodeDriver(72) - >>> node2 = driver.create_node() - >>> node.driver.creds - 0 - >>> node2.driver.creds - 72 - - Although Node objects can be subclassed, this isn't normally - done. Instead, any driver specific information is stored in the - "extra" attribute of the node. - - >>> node.extra - {'foo': 'bar'} - """ - - def __init__(self, id, name, state, public_ips, private_ips, - driver, size=None, image=None, extra=None): - """ - :param id: Node ID. - :type id: ``str`` - - :param name: Node name. - :type name: ``str`` - - :param state: Node state. - :type state: :class:`libcloud.compute.types.NodeState` - - :param public_ips: Public IP addresses associated with this node. - :type public_ips: ``list`` - - :param private_ips: Private IP addresses associated with this node. - :type private_ips: ``list`` - - :param driver: Driver this node belongs to. - :type driver: :class:`.NodeDriver` - - :param size: Size of this node. (optional) - :type size: :class:`.NodeSize` - - :param image: Image of this node. (optional) - :type size: :class:`.NodeImage` - - :param extra: Optional provider specific attributes associated with - this node. - :type extra: ``dict`` - - """ - self.id = str(id) if id else None - self.name = name - self.state = state - self.public_ips = public_ips if public_ips else [] - self.private_ips = private_ips if private_ips else [] - self.driver = driver - self.size = size - self.image = image - self.extra = extra or {} - UuidMixin.__init__(self) - - def reboot(self): - """ - Reboot this node - - :return: ``bool`` - - This calls the node's driver and reboots the node - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node() - >>> node.state == NodeState.RUNNING - True - >>> node.state == NodeState.REBOOTING - False - >>> node.reboot() - True - >>> node.state == NodeState.REBOOTING - True - """ - return self.driver.reboot_node(self) - - def destroy(self): - """ - Destroy this node - - :return: ``bool`` - - This calls the node's driver and destroys the node - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> from libcloud.compute.types import NodeState - >>> node = driver.create_node() - >>> node.state == NodeState.RUNNING - True - >>> node.destroy() - True - >>> node.state == NodeState.RUNNING - False - - """ - return self.driver.destroy_node(self) - - def __repr__(self): - return (('<Node: uuid=%s, name=%s, state=%s, public_ips=%s, ' - 'private_ips=%s, provider=%s ...>') - % (self.uuid, self.name, self.state, self.public_ips, - self.private_ips, self.driver.name)) - - -class NodeSize(UuidMixin): - """ - A Base NodeSize class to derive from. - - NodeSizes are objects which are typically returned a driver's - list_sizes function. They contain a number of different - parameters which define how big an image is. - - The exact parameters available depends on the provider. - - N.B. Where a parameter is "unlimited" (for example bandwidth in - Amazon) this will be given as 0. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> size = driver.list_sizes()[0] - >>> size.ram - 128 - >>> size.bandwidth - 500 - >>> size.price - 4 - """ - - def __init__(self, id, name, ram, disk, bandwidth, price, - driver, extra=None): - """ - :param id: Size ID. - :type id: ``str`` - - :param name: Size name. - :type name: ``str`` - - :param ram: Amount of memory (in MB) provided by this size. - :type ram: ``int`` - - :param disk: Amount of disk storage (in GB) provided by this image. - :type disk: ``int`` - - :param bandwidth: Amount of bandiwdth included with this size. - :type bandwidth: ``int`` - - :param price: Price (in US dollars) of running this node for an hour. - :type price: ``float`` - - :param driver: Driver this size belongs to. - :type driver: :class:`.NodeDriver` - - :param extra: Optional provider specific attributes associated with - this size. - :type extra: ``dict`` - """ - self.id = str(id) - self.name = name - self.ram = ram - self.disk = disk - self.bandwidth = bandwidth - self.price = price - self.driver = driver - self.extra = extra or {} - UuidMixin.__init__(self) - - def __repr__(self): - return (('<NodeSize: id=%s, name=%s, ram=%s disk=%s bandwidth=%s ' - 'price=%s driver=%s ...>') - % (self.id, self.name, self.ram, self.disk, self.bandwidth, - self.price, self.driver.name)) - - -class NodeImage(UuidMixin): - """ - An operating system image. - - NodeImage objects are typically returned by the driver for the - cloud provider in response to the list_images function - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> image = driver.list_images()[0] - >>> image.name - 'Ubuntu 9.10' - - Apart from name and id, there is no further standard information; - other parameters are stored in a driver specific "extra" variable - - When creating a node, a node image should be given as an argument - to the create_node function to decide which OS image to use. - - >>> node = driver.create_node(image=image) - """ - - def __init__(self, id, name, driver, extra=None): - """ - :param id: Image ID. - :type id: ``str`` - - :param name: Image name. - :type name: ``str`` - - :param driver: Driver this image belongs to. - :type driver: :class:`.NodeDriver` - - :param extra: Optional provided specific attributes associated with - this image. - :type extra: ``dict`` - """ - self.id = str(id) - self.name = name - self.driver = driver - self.extra = extra or {} - UuidMixin.__init__(self) - - def __repr__(self): - return (('<NodeImage: id=%s, name=%s, driver=%s ...>') - % (self.id, self.name, self.driver.name)) - - -class NodeLocation(object): - """ - A physical location where nodes can be. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> location = driver.list_locations()[0] - >>> location.country - 'US' - """ - - def __init__(self, id, name, country, driver): - """ - :param id: Location ID. - :type id: ``str`` - - :param name: Location name. - :type name: ``str`` - - :param country: Location country. - :type country: ``str`` - - :param driver: Driver this location belongs to. - :type driver: :class:`.NodeDriver` - """ - self.id = str(id) - self.name = name - self.country = country - self.driver = driver - - def __repr__(self): - return (('<NodeLocation: id=%s, name=%s, country=%s, driver=%s>') - % (self.id, self.name, self.country, self.driver.name)) - - -class NodeAuthSSHKey(object): - """ - An SSH key to be installed for authentication to a node. - - This is the actual contents of the users ssh public key which will - normally be installed as root's public key on the node. - - >>> pubkey = '...' # read from file - >>> from libcloud.compute.base import NodeAuthSSHKey - >>> k = NodeAuthSSHKey(pubkey) - >>> k - <NodeAuthSSHKey> - """ - - def __init__(self, pubkey): - """ - :param pubkey: Public key matetiral. - :type pubkey: ``str`` - """ - self.pubkey = pubkey - - def __repr__(self): - return '<NodeAuthSSHKey>' - - -class NodeAuthPassword(object): - """ - A password to be used for authentication to a node. - """ - def __init__(self, password, generated=False): - """ - :param password: Password. - :type password: ``str`` - - :type generated: ``True`` if this password was automatically generated, - ``False`` otherwise. - """ - self.password = password - self.generated = generated - - def __repr__(self): - return '<NodeAuthPassword>' - - -class StorageVolume(UuidMixin): - """ - A base StorageVolume class to derive from. - """ - - def __init__(self, id, name, size, driver, extra=None): - """ - :param id: Storage volume ID. - :type id: ``str`` - - :param name: Storage volume name. - :type name: ``str`` - - :param size: Size of this volume (in GB). - :type size: ``int`` - - :param driver: Driver this image belongs to. - :type driver: :class:`.NodeDriver` - - :param extra: Optional provider specific attributes. - :type extra: ``dict`` - """ - self.id = id - self.name = name - self.size = size - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def list_snapshots(self): - """ - :rtype: ``list`` of ``VolumeSnapshot`` - """ - return self.driver.list_volume_snapshots(volume=self) - - def attach(self, node, device=None): - """ - Attach this volume to a node. - - :param node: Node to attach volume to - :type node: :class:`.Node` - - :param device: Where the device is exposed, - e.g. '/dev/sdb (optional) - :type device: ``str`` - - :return: ``True`` if attach was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - return self.driver.attach_volume(node=node, volume=self, device=device) - - def detach(self): - """ - Detach this volume from its node - - :return: ``True`` if detach was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - return self.driver.detach_volume(volume=self) - - def snapshot(self, name): - """ - Creates a snapshot of this volume. - - :return: Created snapshot. - :rtype: ``VolumeSnapshot`` - """ - return self.driver.create_volume_snapshot(volume=self, name=name) - - def destroy(self): - """ - Destroy this storage volume. - - :return: ``True`` if destroy was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - return self.driver.destroy_volume(volume=self) - - def __repr__(self): - return '<StorageVolume id=%s size=%s driver=%s>' % ( - self.id, self.size, self.driver.name) - - -class VolumeSnapshot(object): - """ - A base VolumeSnapshot class to derive from. - """ - def __init__(self, id, driver, size=None, extra=None): - """ - VolumeSnapshot constructor. - - :param id: Snapshot ID. - :type id: ``str`` - - :param size: A snapshot size in GB. - :type size: ``int`` - - :param extra: Provider depends parameters for snapshot. - :type extra: ``dict`` - """ - self.id = id - self.driver = driver - self.size = size - self.extra = extra or {} - - def destroy(self): - """ - Destroys this snapshot. - - :rtype: ``bool`` - """ - return self.driver.destroy_volume_snapshot(snapshot=self) - - def __repr__(self): - return ('<VolumeSnapshot id=%s size=%s driver=%s>' % - (self.id, self.size, self.driver.name)) - - -class KeyPair(object): - """ - Represents a SSH key pair. - """ - - def __init__(self, name, public_key, fingerprint, driver, private_key=None, - extra=None): - """ - Constructor. - - :keyword name: Name of the key pair object. - :type name: ``str`` - - :keyword fingerprint: Key fingerprint. - :type fingerprint: ``str`` - - :keyword public_key: Public key in OpenSSH format. - :type public_key: ``str`` - - :keyword private_key: Private key in PEM format. - :type private_key: ``str`` - - :keyword extra: Provider specific attributes associated with this - key pair. (optional) - :type extra: ``dict`` - """ - self.name = name - self.fingerprint = fingerprint - self.public_key = public_key - self.private_key = private_key - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return ('<KeyPair name=%s fingerprint=%s driver=%s>' % - (self.name, self.fingerprint, self.driver.name)) - - -class NodeDriver(BaseDriver): - """ - A base NodeDriver class to derive from - - This class is always subclassed by a specific driver. For - examples of base behavior of most functions (except deploy node) - see the dummy driver. - - """ - - connectionCls = ConnectionKey - name = None - type = None - port = None - features = {'create_node': []} - - """ - List of available features for a driver. - - :meth:`libcloud.compute.base.NodeDriver.create_node` - - ssh_key: Supports :class:`.NodeAuthSSHKey` as an authentication - method for nodes. - - password: Supports :class:`.NodeAuthPassword` as an - authentication - method for nodes. - - generates_password: Returns a password attribute on the Node - object returned from creation. - """ - - NODE_STATE_MAP = {} - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - api_version=None, **kwargs): - super(NodeDriver, self).__init__(key=key, secret=secret, secure=secure, - host=host, port=port, - api_version=api_version, **kwargs) - - def list_nodes(self): - """ - List all nodes. - - :return: list of node objects - :rtype: ``list`` of :class:`.Node` - """ - raise NotImplementedError( - 'list_nodes not implemented for this driver') - - def list_sizes(self, location=None): - """ - List sizes on a provider - - :param location: The location at which to list sizes - :type location: :class:`.NodeLocation` - - :return: list of node size objects - :rtype: ``list`` of :class:`.NodeSize` - """ - raise NotImplementedError( - 'list_sizes not implemented for this driver') - - def list_locations(self): - """ - List data centers for a provider - - :return: list of node location objects - :rtype: ``list`` of :class:`.NodeLocation` - """ - raise NotImplementedError( - 'list_locations not implemented for this driver') - - def create_node(self, **kwargs): - """ - Create a new node instance. This instance will be started - automatically. - - Not all hosting API's are created equal and to allow libcloud to - support as many as possible there are some standard supported - variations of ``create_node``. These are declared using a - ``features`` API. - You can inspect ``driver.features['create_node']`` to see what - variation of the API you are dealing with: - - ``ssh_key`` - You can inject a public key into a new node allows key based SSH - authentication. - ``password`` - You can inject a password into a new node for SSH authentication. - If no password is provided libcloud will generated a password. - The password will be available as - ``return_value.extra['password']``. - ``generates_password`` - The hosting provider will generate a password. It will be returned - to you via ``return_value.extra['password']``. - - Some drivers allow you to set how you will authenticate with the - instance that is created. You can inject this initial authentication - information via the ``auth`` parameter. - - If a driver supports the ``ssh_key`` feature flag for ``created_node`` - you can upload a public key into the new instance:: - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> auth = NodeAuthSSHKey('pubkey data here') - >>> node = driver.create_node("test_node", auth=auth) - - If a driver supports the ``password`` feature flag for ``create_node`` - you can set a password:: - - >>> driver = DummyNodeDriver(0) - >>> auth = NodeAuthPassword('mysecretpassword') - >>> node = driver.create_node("test_node", auth=auth) - - If a driver supports the ``password`` feature and you don't provide the - ``auth`` argument libcloud will assign a password:: - - >>> driver = DummyNodeDriver(0) - >>> node = driver.create_node("test_node") - >>> password = node.extra['password'] - - A password will also be returned in this way for drivers that declare - the ``generates_password`` feature, though in that case the password is - actually provided to the driver API by the hosting provider rather than - generated by libcloud. - - You can only pass a :class:`.NodeAuthPassword` or - :class:`.NodeAuthSSHKey` to ``create_node`` via the auth parameter if - has the corresponding feature flag. - - :param name: String with a name for this new node (required) - :type name: ``str`` - - :param size: The size of resources allocated to this node. - (required) - :type size: :class:`.NodeSize` - - :param image: OS Image to boot on node. (required) - :type image: :class:`.NodeImage` - - :param location: Which data center to create a node in. If empty, - undefined behavior will be selected. (optional) - :type location: :class:`.NodeLocation` - - :param auth: Initial authentication information for the node - (optional) - :type auth: :class:`.NodeAuthSSHKey` or :class:`NodeAuthPassword` - - :return: The newly created node. - :rtype: :class:`.Node` - """ - raise NotImplementedError( - 'create_node not implemented for this driver') - - def deploy_node(self, **kwargs): - """ - Create a new node, and start deployment. - - In order to be able to SSH into a created node access credentials are - required. - - A user can pass either a :class:`.NodeAuthPassword` or - :class:`.NodeAuthSSHKey` to the ``auth`` argument. If the - ``create_node`` implementation supports that kind if credential (as - declared in ``self.features['create_node']``) then it is passed on to - ``create_node``. Otherwise it is not passed on to ``create_node`` and - it is only used for authentication. - - If the ``auth`` parameter is not supplied but the driver declares it - supports ``generates_password`` then the password returned by - ``create_node`` will be used to SSH into the server. - - Finally, if the ``ssh_key_file`` is supplied that key will be used to - SSH into the server. - - This function may raise a :class:`DeploymentException`, if a - create_node call was successful, but there is a later error (like SSH - failing or timing out). This exception includes a Node object which - you may want to destroy if incomplete deployments are not desirable. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> from libcloud.compute.deployment import ScriptDeployment - >>> from libcloud.compute.deployment import MultiStepDeployment - >>> from libcloud.compute.base import NodeAuthSSHKey - >>> driver = DummyNodeDriver(0) - >>> key = NodeAuthSSHKey('...') # read from file - >>> script = ScriptDeployment("yum -y install emacs strace tcpdump") - >>> msd = MultiStepDeployment([key, script]) - >>> def d(): - ... try: - ... driver.deploy_node(deploy=msd) - ... except NotImplementedError: - ... print ("not implemented for dummy driver") - >>> d() - not implemented for dummy driver - - Deploy node is typically not overridden in subclasses. The - existing implementation should be able to handle most such. - - :param deploy: Deployment to run once machine is online and - available to SSH. - :type deploy: :class:`Deployment` - - :param ssh_username: Optional name of the account which is used - when connecting to - SSH server (default is root) - :type ssh_username: ``str`` - - :param ssh_alternate_usernames: Optional list of ssh usernames to - try to connect with if using the - default one fails - :type ssh_alternate_usernames: ``list`` - - :param ssh_port: Optional SSH server port (default is 22) - :type ssh_port: ``int`` - - :param ssh_timeout: Optional SSH connection timeout in seconds - (default is 10) - :type ssh_timeout: ``float`` - - :param auth: Initial authentication information for the node - (optional) - :type auth: :class:`.NodeAuthSSHKey` or :class:`NodeAuthPassword` - - :param ssh_key: A path (or paths) to an SSH private key with which - to attempt to authenticate. (optional) - :type ssh_key: ``str`` or ``list`` of ``str`` - - :param timeout: How many seconds to wait before timing out. - (default is 600) - :type timeout: ``int`` - - :param max_tries: How many times to retry if a deployment fails - before giving up (default is 3) - :type max_tries: ``int`` - - :param ssh_interface: The interface to wait for. Default is - 'public_ips', other option is 'private_ips'. - :type ssh_interface: ``str`` - """ - if not libcloud.compute.ssh.have_paramiko: - raise RuntimeError('paramiko is not installed. You can install ' + - 'it using pip: pip install paramiko') - - if 'auth' in kwargs: - auth = kwargs['auth'] - if not isinstance(auth, (NodeAuthSSHKey, NodeAuthPassword)): - raise NotImplementedError( - 'If providing auth, only NodeAuthSSHKey or' - 'NodeAuthPassword is supported') - elif 'ssh_key' in kwargs: - # If an ssh_key is provided we can try deploy_node - pass - elif 'create_node' in self.features: - f = self.features['create_node'] - if 'generates_password' not in f and "password" not in f: - raise NotImplementedError( - 'deploy_node not implemented for this driver') - else: - raise NotImplementedError( - 'deploy_node not implemented for this driver') - - node = self.create_node(**kwargs) - max_tries = kwargs.get('max_tries', 3) - - password = None - if 'auth' in kwargs: - if isinstance(kwargs['auth'], NodeAuthPassword): - password = kwargs['auth'].password - elif 'password' in node.extra: - password = node.extra['password'] - - ssh_interface = kwargs.get('ssh_interface', 'public_ips') - - # Wait until node is up and running and has IP assigned - try: - node, ip_addresses = self.wait_until_running( - nodes=[node], - wait_period=3, - timeout=kwargs.get('timeout', NODE_ONLINE_WAIT_TIMEOUT), - ssh_interface=ssh_interface)[0] - except Exception: - e = sys.exc_info()[1] - raise DeploymentError(node=node, original_exception=e, driver=self) - - ssh_username = kwargs.get('ssh_username', 'root') - ssh_alternate_usernames = kwargs.get('ssh_alternate_usernames', []) - ssh_port = kwargs.get('ssh_port', 22) - ssh_timeout = kwargs.get('ssh_timeout', 10) - ssh_key_file = kwargs.get('ssh_key', None) - timeout = kwargs.get('timeout', SSH_CONNECT_TIMEOUT) - - deploy_error = None - - for username in ([ssh_username] + ssh_alternate_usernames): - try: - self._connect_and_run_deployment_script( - task=kwargs['deploy'], node=node, - ssh_hostname=ip_addresses[0], ssh_port=ssh_port, - ssh_username=username, ssh_password=password, - ssh_key_file=ssh_key_file, ssh_timeout=ssh_timeout, - timeout=timeout, max_tries=max_tries) - except Exception: - # Try alternate username - # Todo: Need to fix paramiko so we can catch a more specific - # exception - e = sys.exc_info()[1] - deploy_error = e - else: - # Script successfully executed, don't try alternate username - deploy_error = None - break - - if deploy_error is not None: - raise DeploymentError(node=node, original_exception=deploy_error, - driver=self) - - return node - - def reboot_node(self, node): - """ - Reboot a node. - - :param node: The node to be rebooted - :type node: :class:`.Node` - - :return: True if the reboot was successful, otherwise False - :rtype: ``bool`` - """ - raise NotImplementedError( - 'reboot_node not implemented for this driver') - - def destroy_node(self, node): - """ - Destroy a node. - - Depending upon the provider, this may destroy all data associated with - the node, including backups. - - :param node: The node to be destroyed - :type node: :class:`.Node` - - :return: True if the destroy was successful, False otherwise. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'destroy_node not implemented for this driver') - - ## - # Volume and snapshot management methods - ## - - def list_volumes(self): - """ - List storage volumes. - - :rtype: ``list`` of :class:`.StorageVolume` - """ - raise NotImplementedError( - 'list_volumes not implemented for this driver') - - def list_volume_snapshots(self, volume): - """ - List snapshots for a storage volume. - - :rtype: ``list`` of :class:`VolumeSnapshot` - """ - raise NotImplementedError( - 'list_volume_snapshots not implemented for this driver') - - def create_volume(self, size, name, location=None, snapshot=None): - """ - Create a new volume. - - :param size: Size of volume in gigabytes (required) - :type size: ``int`` - - :param name: Name of the volume to be created - :type name: ``str`` - - :param location: Which data center to create a volume in. If - empty, undefined behavior will be selected. - (optional) - :type location: :class:`.NodeLocation` - - :param snapshot: Name of snapshot from which to create the new - volume. (optional) - :type snapshot: ``str`` - - :return: The newly created volume. - :rtype: :class:`StorageVolume` - """ - raise NotImplementedError( - 'create_volume not implemented for this driver') - - def create_volume_snapshot(self, volume, name): - """ - Creates a snapshot of the storage volume. - - :rtype: :class:`VolumeSnapshot` - """ - raise NotImplementedError( - 'create_volume_snapshot not implemented for this driver') - - def attach_volume(self, node, volume, device=None): - """ - Attaches volume to node. - - :param node: Node to attach volume to. - :type node: :class:`.Node` - - :param volume: Volume to attach. - :type volume: :class:`.StorageVolume` - - :param device: Where the device is exposed, e.g. '/dev/sdb' - :type device: ``str`` - - :rytpe: ``bool`` - """ - raise NotImplementedError('attach not implemented for this driver') - - def detach_volume(self, volume): - """ - Detaches a volume from a node. - - :param volume: Volume to be detached - :type volume: :class:`.StorageVolume` - - :rtype: ``bool`` - """ - - raise NotImplementedError('detach not implemented for this driver') - - def destroy_volume(self, volume): - """ - Destroys a storage volume. - - :param volume: Volume to be destroyed - :type volume: :class:`StorageVolume` - - :rtype: ``bool`` - """ - - raise NotImplementedError( - 'destroy_volume not implemented for this driver') - - def destroy_volume_snapshot(self, snapshot): - """ - Destroys a snapshot. - - :rtype: :class:`bool` - """ - raise NotImplementedError( - 'destroy_volume_snapshot not implemented for this driver') - - ## - # Image management methods - ## - - def list_images(self, location=None): - """ - List images on a provider. - - :param location: The location at which to list images. - :type location: :class:`.NodeLocation` - - :return: list of node image objects. - :rtype: ``list`` of :class:`.NodeImage` - """ - raise NotImplementedError( - 'list_images not implemented for this driver') - - def create_image(self, node, name, description=None): - """ - Creates an image from a node object. - - :param node: Node to run the task on. - :type node: :class:`.Node` - - :param name: name for new image. - :type name: ``str`` - - :param description: description for new image. - :type name: ``description`` - - :rtype: :class:`.NodeImage`: - :return: NodeImage instance on success. - - """ - raise NotImplementedError( - 'create_image not implemented for this driver') - - def delete_image(self, node_image): - """ - Deletes a node image from a provider. - - :param node_image: Node image object. - :type node_image: :class:`.NodeImage` - - :return: ``True`` if delete_image was successful, ``False`` otherwise. - :rtype: ``bool`` - """ - - raise NotImplementedError( - 'delete_image not implemented for this driver') - - def get_image(self, image_id): - """ - Returns a single node image from a provider. - - :param image_id: Node to run the task on. - :type image_id: ``str`` - - :rtype :class:`.NodeImage`: - :return: NodeImage instance on success. - """ - raise NotImplementedError( - 'get_image not implemented for this driver') - - def copy_image(self, source_region, node_image, name, description=None): - """ - Copies an image from a source region to the current region. - - :param source_region: Region to copy the node from. - :type source_region: ``str`` - - :param node_image: NodeImage to copy. - :type node_image: :class`.NodeImage`: - - :param name: name for new image. - :type name: ``str`` - - :param description: description for new image. - :type name: ``str`` - - :rtype: :class:`.NodeImage`: - :return: NodeImage instance on success. - """ - raise NotImplementedError( - 'copy_image not implemented for this driver') - - ## - # SSH key pair management methods - ## - - def list_key_pairs(self): - """ - List all the available key pair objects. - - :rtype: ``list`` of :class:`.KeyPair` objects - """ - raise NotImplementedError( - 'list_key_pairs not implemented for this driver') - - def get_key_pair(self, name): - """ - Retrieve a single key pair. - - :param name: Name of the key pair to retrieve. - :type name: ``str`` - - :rtype: :class:`.KeyPair` - """ - raise NotImplementedError( - 'get_key_pair not implemented for this driver') - - def create_key_pair(self, name): - """ - Create a new key pair object. - - :param name: Key pair name. - :type name: ``str`` - """ - raise NotImplementedError( - 'create_key_pair not implemented for this driver') - - def import_key_pair_from_string(self, name, key_material): - """ - Import a new public key from string. - - :param name: Key pair name. - :type name: ``str`` - - :param key_material: Public key material. - :type key_material: ``str`` - - :rtype: :class:`.KeyPair` object - """ - raise NotImplementedError( - 'import_key_pair_from_string not implemented for this driver') - - def import_key_pair_from_file(self, name, key_file_path): - """ - Import a new public key from string. - - :param name: Key pair name. - :type name: ``str`` - - :param key_file_path: Path to the public key file. - :type key_file_path: ``str`` - - :rtype: :class:`.KeyPair` object - """ - key_file_path = os.path.expanduser(key_file_path) - - with open(key_file_path, 'r') as fp: - key_material = fp.read() - - return self.import_key_pair_from_string(name=name, - key_material=key_material) - - def delete_key_pair(self, key_pair): - """ - Delete an existing key pair. - - :param key_pair: Key pair object. - :type key_pair: :class`.KeyPair` - """ - raise NotImplementedError( - 'delete_key_pair not implemented for this driver') - - def wait_until_running(self, nodes, wait_period=3, timeout=600, - ssh_interface='public_ips', force_ipv4=True): - """ - Block until the provided nodes are considered running. - - Node is considered running when it's state is "running" and when it has - at least one IP address assigned. - - :param nodes: List of nodes to wait for. - :type nodes: ``list`` of :class:`.Node` - - :param wait_period: How many seconds to wait between each loop - iteration. (default is 3) - :type wait_period: ``int`` - - :param timeout: How many seconds to wait before giving up. - (default is 600) - :type timeout: ``int`` - - :param ssh_interface: Which attribute on the node to use to obtain - an IP address. Valid options: public_ips, - private_ips. Default is public_ips. - :type ssh_interface: ``str`` - - :param force_ipv4: Ignore IPv6 addresses (default is True). - :type force_ipv4: ``bool`` - - :return: ``[(Node, ip_addresses)]`` list of tuple of Node instance and - list of ip_address on success. - :rtype: ``list`` of ``tuple`` - """ - def is_supported(address): - """ - Return True for supported address. - """ - if force_ipv4 and not is_valid_ip_address(address=address, - family=socket.AF_INET): - return False - return True - - def filter_addresses(addresses): - """ - Return list of supported addresses. - """ - return [address for address in addresses if is_supported(address)] - - if ssh_interface not in ['public_ips', 'private_ips']: - raise ValueError('ssh_interface argument must either be' + - 'public_ips or private_ips') - - start = time.time() - end = start + timeout - - uuids = set([node.uuid for node in nodes]) - - while time.time() < end: - all_nodes = self.list_nodes() - matching_nodes = list([node for node in all_nodes - if node.uuid in uuids]) - - if len(matching_nodes) > len(uuids): - found_uuids = [node.uuid for node in matching_nodes] - msg = ('Unable to match specified uuids ' + - '(%s) with existing nodes. Found ' % (uuids) + - 'multiple nodes with same uuid: (%s)' % (found_uuids)) - raise LibcloudError(value=msg, driver=self) - - running_nodes = [node for node in matching_nodes - if node.state == NodeState.RUNNING] - addresses = [filter_addresses(getattr(node, ssh_interface)) - for node in running_nodes] - - if len(running_nodes) == len(uuids) == len(addresses): - return list(zip(running_nodes, addresses)) - else: - time.sleep(wait_period) - continue - - raise LibcloudError(value='Timed out after %s seconds' % (timeout), - driver=self) - - def _get_and_check_auth(self, auth): - """ - Helper function for providers supporting :class:`.NodeAuthPassword` or - :class:`.NodeAuthSSHKey` - - Validates that only a supported object type is passed to the auth - parameter and raises an exception if it is not. - - If no :class:`.NodeAuthPassword` object is provided but one is expected - then a password is automatically generated. - """ - - if isinstance(auth, NodeAuthPassword): - if 'password' in self.features['create_node']: - return auth - raise LibcloudError( - 'Password provided as authentication information, but password' - 'not supported', driver=self) - - if isinstance(auth, NodeAuthSSHKey): - if 'ssh_key' in self.features['create_node']: - return auth - raise LibcloudError( - 'SSH Key provided as authentication information, but SSH Key' - 'not supported', driver=self) - - if 'password' in self.features['create_node']: - value = os.urandom(16) - value = binascii.hexlify(value).decode('ascii') - return NodeAuthPassword(value, generated=True) - - if auth: - raise LibcloudError( - '"auth" argument provided, but it was not a NodeAuthPassword' - 'or NodeAuthSSHKey object', driver=self) - - def _wait_until_running(self, node, wait_period=3, timeout=600, - ssh_interface='public_ips', force_ipv4=True): - # This is here for backward compatibility and will be removed in the - # next major release - return self.wait_until_running(nodes=[node], wait_period=wait_period, - timeout=timeout, - ssh_interface=ssh_interface, - force_ipv4=force_ipv4) - - def _ssh_client_connect(self, ssh_client, wait_period=1.5, timeout=300): - """ - Try to connect to the remote SSH server. If a connection times out or - is refused it is retried up to timeout number of seconds. - - :param ssh_client: A configured SSHClient instance - :type ssh_client: ``SSHClient`` - - :param wait_period: How many seconds to wait between each loop - iteration. (default is 1.5) - :type wait_period: ``int`` - - :param timeout: How many seconds to wait before giving up. - (default is 300) - :type timeout: ``int`` - - :return: ``SSHClient`` on success - """ - start = time.time() - end = start + timeout - - while time.time() < end: - try: - ssh_client.connect() - except SSH_TIMEOUT_EXCEPTION_CLASSES: - e = sys.exc_info()[1] - message = str(e).lower() - expected_msg = 'no such file or directory' - - if isinstance(e, IOError) and expected_msg in message: - # Propagate (key) file doesn't exist errors - raise e - - # Retry if a connection is refused, timeout occurred, - # or the connection fails due to failed authentication. - ssh_client.close() - time.sleep(wait_period) - continue - else: - return ssh_client - - raise LibcloudError(value='Could not connect to the remote SSH ' + - 'server. Giving up.', driver=self) - - def _connect_and_run_deployment_script(self, task, node, ssh_hostname, - ssh_port, ssh_username, - ssh_password, ssh_key_file, - ssh_timeout, timeout, max_tries): - """ - Establish an SSH connection to the node and run the provided deployment - task. - - :rtype: :class:`.Node`: - :return: Node instance on success. - """ - ssh_client = SSHClient(hostname=ssh_hostname, - port=ssh_port, username=ssh_username, - password=ssh_password, - key_files=ssh_key_file, - timeout=ssh_timeout) - - ssh_client = self._ssh_client_connect(ssh_client=ssh_client, - timeout=timeout) - - # Execute the deployment task - node = self._run_deployment_script(task=task, node=node, - ssh_client=ssh_client, - max_tries=max_tries) - return node - - def _run_deployment_script(self, task, node, ssh_client, max_tries=3): - """ - Run the deployment script on the provided node. At this point it is - assumed that SSH connection has already been established. - - :param task: Deployment task to run. - :type task: :class:`Deployment` - - :param node: Node to run the task on. - :type node: ``Node`` - - :param ssh_client: A configured and connected SSHClient instance. - :type ssh_client: :class:`SSHClient` - - :param max_tries: How many times to retry if a deployment fails - before giving up. (default is 3) - :type max_tries: ``int`` - - :rtype: :class:`.Node` - :return: ``Node`` Node instance on success. - """ - tries = 0 - - while tries < max_tries: - try: - node = task.run(node, ssh_client) - except Exception: - tries += 1 - - if tries >= max_tries: - e = sys.exc_info()[1] - raise LibcloudError(value='Failed after %d tries: %s' - % (max_tries, str(e)), driver=self) - else: - # Deployment succeeded - ssh_client.close() - return node - - def _get_size_price(self, size_id): - """ - Return pricing information for the provided size id. - """ - return get_size_price(driver_type='compute', - driver_name=self.api_name, - size_id=size_id) - - -if __name__ == '__main__': - import doctest - doctest.testmod() diff --git a/awx/lib/site-packages/libcloud/compute/deployment.py b/awx/lib/site-packages/libcloud/compute/deployment.py deleted file mode 100644 index 018c5f86dc..0000000000 --- a/awx/lib/site-packages/libcloud/compute/deployment.py +++ /dev/null @@ -1,263 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Provides generic deployment steps for machines post boot. -""" - -from __future__ import with_statement - -import os -import binascii - -from libcloud.utils.py3 import basestring, PY3 - - -class Deployment(object): - """ - Base class for deployment tasks. - """ - - def run(self, node, client): - """ - Runs this deployment task on node using the client provided. - - :type node: :class:`Node` - :keyword node: Node to operate one - - :type client: :class:`BaseSSHClient` - :keyword client: Connected SSH client to use. - - :return: :class:`Node` - """ - raise NotImplementedError( - 'run not implemented for this deployment') - - def _get_string_value(self, argument_name, argument_value): - if not isinstance(argument_value, basestring) and \ - not hasattr(argument_value, 'read'): - raise TypeError('%s argument must be a string or a file-like ' - 'object' % (argument_name)) - - if hasattr(argument_value, 'read'): - argument_value = argument_value.read() - - return argument_value - - -class SSHKeyDeployment(Deployment): - """ - Installs a public SSH Key onto a server. - """ - - def __init__(self, key): - """ - :type key: ``str`` or :class:`File` object - :keyword key: Contents of the public key write or a file object which - can be read. - """ - self.key = self._get_string_value(argument_name='key', - argument_value=key) - - def run(self, node, client): - """ - Installs SSH key into ``.ssh/authorized_keys`` - - See also :class:`Deployment.run` - """ - client.put(".ssh/authorized_keys", contents=self.key, mode='a') - return node - - -class FileDeployment(Deployment): - """ - Installs a file on the server. - """ - - def __init__(self, source, target): - """ - :type source: ``str`` - :keyword source: Local path of file to be installed - - :type target: ``str`` - :keyword target: Path to install file on node - """ - self.source = source - self.target = target - - def run(self, node, client): - """ - Upload the file, retaining permissions. - - See also :class:`Deployment.run` - """ - perms = int(oct(os.stat(self.source).st_mode)[4:], 8) - - with open(self.source, 'rb') as fp: - content = fp.read() - - client.put(path=self.target, chmod=perms, - contents=content) - return node - - -class ScriptDeployment(Deployment): - """ - Runs an arbitrary shell script on the server. - - This step works by first writing the content of the shell script (script - argument) in a \*.sh file on a remote server and then running that file. - - If you are running a non-shell script, make sure to put the appropriate - shebang to the top of the script. You are also advised to do that even if - you are running a plan shell script. - """ - - def __init__(self, script, args=None, name=None, delete=False): - """ - :type script: ``str`` - :keyword script: Contents of the script to run. - - :type args: ``list`` - :keyword args: Optional command line arguments which get passed to the - deployment script file. - - :type name: ``str`` - :keyword name: Name of the script to upload it as, if not specified, - a random name will be chosen. - - :type delete: ``bool`` - :keyword delete: Whether to delete the script on completion. - """ - script = self._get_string_value(argument_name='script', - argument_value=script) - - self.script = script - self.args = args or [] - self.stdout = None - self.stderr = None - self.exit_status = None - self.delete = delete - self.name = name - - if self.name is None: - # File is put under user's home directory - # (~/libcloud_deployment_<random_string>.sh) - random_string = binascii.hexlify(os.urandom(4)) - random_string = random_string.decode('ascii') - self.name = 'libcloud_deployment_%s.sh' % (random_string) - - def run(self, node, client): - """ - Uploads the shell script and then executes it. - - See also :class:`Deployment.run` - """ - file_path = client.put(path=self.name, chmod=int('755', 8), - contents=self.script) - - # Pre-pend cwd if user specified a relative path - if self.name[0] != '/': - base_path = os.path.dirname(file_path) - name = os.path.join(base_path, self.name) - else: - name = self.name - - cmd = name - - if self.args: - # Append arguments to the command - cmd = '%s %s' % (name, ' '.join(self.args)) - else: - cmd = name - - self.stdout, self.stderr, self.exit_status = client.run(cmd) - - if self.delete: - client.delete(self.name) - - return node - - -class ScriptFileDeployment(ScriptDeployment): - """ - Runs an arbitrary shell script from a local file on the server. Same as - ScriptDeployment, except that you can pass in a path to the file instead of - the script content. - """ - - def __init__(self, script_file, args=None, name=None, delete=False): - """ - :type script_file: ``str`` - :keyword script_file: Path to a file containing the script to run. - - :type args: ``list`` - :keyword args: Optional command line arguments which get passed to the - deployment script file. - - - :type name: ``str`` - :keyword name: Name of the script to upload it as, if not specified, - a random name will be chosen. - - :type delete: ``bool`` - :keyword delete: Whether to delete the script on completion. - """ - with open(script_file, 'rb') as fp: - content = fp.read() - - if PY3: - content = content.decode('utf-8') - - super(ScriptFileDeployment, self).__init__(script=content, - args=args, - name=name, - delete=delete) - - -class MultiStepDeployment(Deployment): - """ - Runs a chain of Deployment steps. - """ - def __init__(self, add=None): - """ - :type add: ``list`` - :keyword add: Deployment steps to add. - """ - self.steps = [] - self.add(add) - - def add(self, add): - """ - Add a deployment to this chain. - - :type add: Single :class:`Deployment` or a ``list`` of - :class:`Deployment` - :keyword add: Adds this deployment to the others already in this - object. - """ - if add is not None: - add = add if isinstance(add, (list, tuple)) else [add] - self.steps.extend(add) - - def run(self, node, client): - """ - Run each deployment that has been added. - - See also :class:`Deployment.run` - """ - for s in self.steps: - node = s.run(node, client) - return node diff --git a/awx/lib/site-packages/libcloud/compute/drivers/__init__.py b/awx/lib/site-packages/libcloud/compute/drivers/__init__.py deleted file mode 100644 index ab02a6b186..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Drivers for working with different providers -""" - -__all__ = [ - 'abiquo', - 'brightbox', - 'bluebox', - 'dummy', - 'ec2', - 'ecp', - 'elasticstack', - 'elastichosts', - 'cloudsigma', - 'gce', - 'gogrid', - 'hostvirtual', - 'ibm_sce', - 'linode', - 'opennebula', - 'rackspace', - 'rimuhosting', - 'softlayer', - 'vcloud', - 'voxel', - 'vpsnet', -] diff --git a/awx/lib/site-packages/libcloud/compute/drivers/abiquo.py b/awx/lib/site-packages/libcloud/compute/drivers/abiquo.py deleted file mode 100644 index cccd5cfa68..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/abiquo.py +++ /dev/null @@ -1,759 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Abiquo Compute Driver - -The driver implements the compute Abiquo functionality for the Abiquo API. -This version is compatible with the following versions of Abiquo: - - * Abiquo 2.0 (http://wiki.abiquo.com/display/ABI20/The+Abiquo+API) - * Abiquo 2.2 (http://wiki.abiquo.com/display/ABI22/The+Abiquo+API) -""" -import xml.etree.ElementTree as ET - -from libcloud.compute.base import NodeDriver, NodeSize -from libcloud.compute.types import Provider, LibcloudError -from libcloud.common.abiquo import (AbiquoConnection, get_href, - AbiquoResponse) -from libcloud.compute.base import NodeLocation, NodeImage, Node -from libcloud.utils.py3 import tostring - - -class AbiquoNodeDriver(NodeDriver): - """ - Implements the :class:`NodeDriver`'s for the Abiquo Compute Provider - """ - - type = Provider.ABIQUO - name = 'Abiquo' - website = 'http://www.abiquo.com/' - connectionCls = AbiquoConnection - timeout = 2000 # some images take a lot of time! - - # Media Types - NODES_MIME_TYPE = 'application/vnd.abiquo.virtualmachineswithnode+xml' - NODE_MIME_TYPE = 'application/vnd.abiquo.virtualmachinewithnode+xml' - VAPP_MIME_TYPE = 'application/vnd.abiquo.virtualappliance+xml' - VM_TASK_MIME_TYPE = 'application/vnd.abiquo.virtualmachinetask+xml' - - # Others constants - GIGABYTE = 1073741824 - - def __init__(self, user_id, secret, endpoint, **kwargs): - """ - Initializes Abiquo Driver - - Initializes the :class:`NodeDriver` object and populate the cache. - - :param user_id: identifier of Abiquo user (required) - :type user_id: ``str`` - :param secret: password of the Abiquo user (required) - :type secret: ``str`` - :param endpoint: Abiquo API endpoint (required) - :type endpoint: ``str`` that can be parsed as URL - """ - self.endpoint = endpoint - super(AbiquoNodeDriver, self).__init__(key=user_id, secret=secret, - secure=False, host=None, - port=None, **kwargs) - self.ex_populate_cache() - - def create_node(self, **kwargs): - """ - Create a new node instance in Abiquo - - All the :class:`Node`s need to be defined inside a VirtualAppliance - (called :class:`NodeGroup` here). If there is no group name defined, - 'libcloud' name will be used instead. - - This method wraps these Abiquo actions: - - 1. Create a group if it does not exist. - 2. Register a new node in the group. - 3. Deploy the node and boot it. - 4. Retrieves it again to get schedule-time attributes (such as ips - and vnc ports). - - The rest of the driver methods has been created in a way that, if any - of these actions fail, the user can not reach an inconsistent state - - :keyword name: The name for this new node (required) - :type name: ``str`` - - :keyword size: The size of resources allocated to this node. - :type size: :class:`NodeSize` - - :keyword image: OS Image to boot on node. (required) - :type image: :class:`NodeImage` - - :keyword location: Which data center to create a node in. If empty, - undefined behavior will be selected. (optional) - :type location: :class:`NodeLocation` - - :keyword group_name: Which group this node belongs to. If empty, - it will be created into 'libcloud' group. If - it does not found any group in the target - location (random location if you have not set - the parameter), then it will create a new - group with this name. - :type group_name: c{str} - - :return: The newly created node. - :rtype: :class:`Node` - """ - # Define the location - # To be clear: - # 'xml_loc' is the xml element we navigate into (we need links) - # 'loc' is the :class:`NodeLocation` entity - xml_loc, loc = self._define_create_node_location(**kwargs) - - # Define the Group - group = self._define_create_node_group(xml_loc, loc, **kwargs) - - # Register the Node - vm = self._define_create_node_node(group, **kwargs) - - # Execute the 'create' in hypervisor action - self._deploy_remote(vm) - - # Retrieve it again, to get some schedule-time defined values - edit_vm = get_href(vm, 'edit') - headers = {'Accept': self.NODE_MIME_TYPE} - vm = self.connection.request(edit_vm, headers=headers).object - return self._to_node(vm, self) - - def destroy_node(self, node): - """ - Destroy a node - - Depending on the provider, this may destroy all data associated with - the node, including backups. - - :param node: The node to be destroyed - :type node: :class:`Node` - - :return: True if the destroy was successful, otherwise False - :rtype: ``bool`` - """ - - # Refresh node state - e_vm = self.connection.request(node.extra['uri_id']).object - state = e_vm.findtext('state') - - if state in ['ALLOCATED', 'CONFIGURED', 'LOCKED', 'UNKNOWN']: - raise LibcloudError('Invalid Node state', self) - - if state != 'NOT_ALLOCATED': - # prepare the element that forces the undeploy - vm_task = ET.Element('virtualmachinetask') - force_undeploy = ET.SubElement(vm_task, 'forceUndeploy') - force_undeploy.text = 'True' - # Set the URI - destroy_uri = node.extra['uri_id'] + '/action/undeploy' - # Prepare the headers - headers = {'Content-type': self.VM_TASK_MIME_TYPE} - res = self.connection.async_request(action=destroy_uri, - method='POST', - data=tostring(vm_task), - headers=headers) - - if state == 'NOT_ALLOCATED' or res.async_success(): - self.connection.request(action=node.extra['uri_id'], - method='DELETE') - return True - else: - return False - - def ex_run_node(self, node): - """ - Runs a node - - Here there is a bit difference between Abiquo states and libcloud - states, so this method is created to have better compatibility. In - libcloud, if the node is not running, then it does not exist (avoiding - UNKNOWN and temporal states). In Abiquo, you can define a node, and - then deploy it. - - If the node is in :class:`NodeState.TERMINATED` libcloud's state and in - 'NOT_DEPLOYED' Abiquo state, there is a way to run and recover it - for libcloud using this method. There is no way to reach this state - if you are using only libcloud, but you may have used another Abiquo - client and now you want to recover your node to be used by libcloud. - - :param node: The node to run - :type node: :class:`Node` - - :return: The node itself, but with the new state - :rtype: :class:`Node` - """ - # Refresh node state - e_vm = self.connection.request(node.extra['uri_id']).object - state = e_vm.findtext('state') - - if state != 'NOT_ALLOCATED': - raise LibcloudError('Invalid Node state', self) - - # -------------------------------------------------------- - # Deploy the Node - # -------------------------------------------------------- - self._deploy_remote(e_vm) - - # -------------------------------------------------------- - # Retrieve it again, to get some schedule-defined - # values. - # -------------------------------------------------------- - edit_vm = get_href(e_vm, 'edit') - headers = {'Accept': self.NODE_MIME_TYPE} - e_vm = self.connection.request(edit_vm, headers=headers).object - return self._to_node(e_vm, self) - - def ex_populate_cache(self): - """ - Populate the cache. - - For each connection, it is good to store some objects that will be - useful for further requests, such as the 'user' and the 'enterprise' - objects. - - Executes the 'login' resource after setting the connection parameters - and, if the execution is successful, it sets the 'user' object into - cache. After that, it also requests for the 'enterprise' and - 'locations' data. - - List of locations should remain the same for a single libcloud - connection. However, this method is public and you are able to - refresh the list of locations any time. - """ - user = self.connection.request('/login').object - self.connection.cache['user'] = user - e_ent = get_href(self.connection.cache['user'], - 'enterprise') - ent = self.connection.request(e_ent).object - self.connection.cache['enterprise'] = ent - - uri_vdcs = '/cloud/virtualdatacenters' - e_vdcs = self.connection.request(uri_vdcs).object - - # Set a dict for the datacenter and its href for a further search - params = {"idEnterprise": self._get_enterprise_id()} - e_dcs = self.connection.request('/admin/datacenters', - params=params).object - dc_dict = {} - for dc in e_dcs.findall('datacenter'): - key = get_href(dc, 'edit') - dc_dict[key] = dc - - # Populate locations cache - self.connection.cache['locations'] = {} - for e_vdc in e_vdcs.findall('virtualDatacenter'): - dc_link = get_href(e_vdc, 'datacenter') - loc = self._to_location(e_vdc, dc_dict[dc_link], self) - - # Save into cache the link to the itself because we will need - # it in the future, but we save here to don't extend the class - # :class:`NodeLocation`. - # So here we have the dict: :class:`NodeLocation` -> - # link_datacenter - self.connection.cache['locations'][loc] = get_href(e_vdc, 'edit') - - def ex_create_group(self, name, location=None): - """ - Create an empty group. - - You can specify the location as well. - - :param group: name of the group (required) - :type group: ``str`` - - :param location: location were to create the group - :type location: :class:`NodeLocation` - - :returns: the created group - :rtype: :class:`NodeGroup` - """ - # prepare the element - vapp = ET.Element('virtualAppliance') - vapp_name = ET.SubElement(vapp, 'name') - vapp_name.text = name - - if location is None: - location = self.list_locations()[0] - elif location not in self.list_locations(): - raise LibcloudError('Location does not exist') - - link_vdc = self.connection.cache['locations'][location] - e_vdc = self.connection.request(link_vdc).object - - creation_link = get_href(e_vdc, 'virtualappliances') - headers = {'Content-type': self.VAPP_MIME_TYPE} - vapp = self.connection.request(creation_link, data=tostring(vapp), - headers=headers, method='POST').object - - uri_vapp = get_href(vapp, 'edit') - - return NodeGroup(self, vapp.findtext('name'), - uri=uri_vapp) - - def ex_destroy_group(self, group): - """ - Destroy a group. - - Be careful! Destroying a group means destroying all the :class:`Node`s - there and the group itself! - - If there is currently any action over any :class:`Node` of the - :class:`NodeGroup`, then the method will raise an exception. - - :param name: The group (required) - :type name: :class:`NodeGroup` - - :return: If the group was destroyed successfully - :rtype: ``bool`` - """ - # Refresh group state - e_group = self.connection.request(group.uri).object - state = e_group.findtext('state') - - if state not in ['NOT_DEPLOYED', 'DEPLOYED']: - error = 'Can not destroy group because of current state' - raise LibcloudError(error, self) - - if state == 'DEPLOYED': - # prepare the element that forces the undeploy - vm_task = ET.Element('virtualmachinetask') - force_undeploy = ET.SubElement(vm_task, 'forceUndeploy') - force_undeploy.text = 'True' - - # Set the URI - undeploy_uri = group.uri + '/action/undeploy' - - # Prepare the headers - headers = {'Content-type': self.VM_TASK_MIME_TYPE} - res = self.connection.async_request(action=undeploy_uri, - method='POST', - data=tostring(vm_task), - headers=headers) - - if state == 'NOT_DEPLOYED' or res.async_success(): - # The node is no longer deployed. Unregister it. - self.connection.request(action=group.uri, - method='DELETE') - return True - else: - return False - - def ex_list_groups(self, location=None): - """ - List all groups. - - :param location: filter the groups by location (optional) - :type location: a :class:`NodeLocation` instance. - - :return: the list of :class:`NodeGroup` - """ - groups = [] - for vdc in self._get_locations(location): - link_vdc = self.connection.cache['locations'][vdc] - e_vdc = self.connection.request(link_vdc).object - apps_link = get_href(e_vdc, 'virtualappliances') - vapps = self.connection.request(apps_link).object - for vapp in vapps.findall('virtualAppliance'): - nodes = [] - vms_link = get_href(vapp, 'virtualmachines') - headers = {'Accept': self.NODES_MIME_TYPE} - vms = self.connection.request(vms_link, headers=headers).object - for vm in vms.findall('virtualmachinewithnode'): - nodes.append(self._to_node(vm, self)) - - group = NodeGroup(self, vapp.findtext('name'), - nodes, get_href(vapp, 'edit')) - groups.append(group) - - return groups - - def list_images(self, location=None): - """ - List images on Abiquo Repositories - - :keyword location: The location to list images for. - :type location: :class:`NodeLocation` - - :return: list of node image objects - :rtype: ``list`` of :class:`NodeImage` - """ - enterprise_id = self._get_enterprise_id() - uri = '/admin/enterprises/%s/datacenterrepositories/' % (enterprise_id) - repos = self.connection.request(uri).object - - images = [] - for repo in repos.findall('datacenterRepository'): - # filter by location. Skips when the name of the location - # is different from the 'datacenterRepository' element - for vdc in self._get_locations(location): - # Check if the virtual datacenter belongs to this repo - link_vdc = self.connection.cache['locations'][vdc] - e_vdc = self.connection.request(link_vdc).object - dc_link_vdc = get_href(e_vdc, 'datacenter') - dc_link_repo = get_href(repo, 'datacenter') - - if dc_link_vdc == dc_link_repo: - # Filter the template in case we don't have it yet - url_templates = get_href(repo, 'virtualmachinetemplates') - hypervisor_type = e_vdc.findtext('hypervisorType') - params = {'hypervisorTypeName': hypervisor_type} - templates = self.connection.request(url_templates, - params).object - for templ in templates.findall('virtualMachineTemplate'): - # Avoid duplicated templates - id_template = templ.findtext('id') - ids = [image.id for image in images] - if id_template not in ids: - images.append(self._to_nodeimage(templ, self, - get_href(repo, - 'edit'))) - - return images - - def list_locations(self): - """ - Return list of locations where the user has access to. - - :return: the list of :class:`NodeLocation` available for the current - user - :rtype: ``list`` of :class:`NodeLocation` - """ - return list(self.connection.cache['locations'].keys()) - - def list_nodes(self, location=None): - """ - List all nodes. - - :param location: Filter the groups by location (optional) - :type location: a :class:`NodeLocation` instance. - - :return: List of node objects - :rtype: ``list`` of :class:`Node` - """ - nodes = [] - - for group in self.ex_list_groups(location): - nodes.extend(group.nodes) - - return nodes - - def list_sizes(self, location=None): - """ - List sizes on a provider. - - Abiquo does not work with sizes. However, this method - returns a list of predefined ones (copied from :class:`DummyNodeDriver` - but without price neither bandwidth) to help the users to create their - own. - - If you call the method :class:`AbiquoNodeDriver.create_node` with the - size informed, it will just override the 'ram' value of the 'image' - template. So it is no too much usefull work with sizes... - - :return: The list of sizes - :rtype: ``list`` of :class:`NodeSizes` - """ - return [ - NodeSize(id=1, - name='Small', - ram=128, - disk=4, - bandwidth=None, - price=None, - driver=self), - NodeSize(id=2, - name='Medium', - ram=512, - disk=16, - bandwidth=None, - price=None, - driver=self), - NodeSize(id=3, - name='Big', - ram=4096, - disk=32, - bandwidth=None, - price=None, - driver=self), - NodeSize(id=4, - name="XXL Big", - ram=4096 * 2, - disk=32 * 4, - bandwidth=None, - price=None, - driver=self) - ] - - def reboot_node(self, node): - """ - Reboot a node. - - :param node: The node to be rebooted - :type node: :class:`Node` - - :return: True if the reboot was successful, otherwise False - :rtype: ``bool`` - """ - reboot_uri = node.extra['uri_id'] + '/action/reset' - res = self.connection.async_request(action=reboot_uri, method='POST') - return res.async_success() - - # ------------------------- - # Extenstion methods - # ------------------------- - - def _ex_connection_class_kwargs(self): - """ - Set the endpoint as an extra :class:`AbiquoConnection` argument. - - According to Connection code, the "url" argument should be - parsed properly to connection. - - :return: ``dict`` of :class:`AbiquoConnection` input arguments - """ - - return {'url': self.endpoint} - - def _deploy_remote(self, e_vm): - """ - Asynchronous call to create the node. - """ - # -------------------------------------------------------- - # Deploy the Node - # -------------------------------------------------------- - # prepare the element that forces the deploy - vm_task = ET.Element('virtualmachinetask') - force_deploy = ET.SubElement(vm_task, 'forceEnterpriseSoftLimits') - force_deploy.text = 'True' - - # Prepare the headers - headers = {'Content-type': self.VM_TASK_MIME_TYPE} - link_deploy = get_href(e_vm, 'deploy') - res = self.connection.async_request(action=link_deploy, method='POST', - data=tostring(vm_task), - headers=headers) - if not res.async_success(): - raise LibcloudError('Could not run the node', self) - - def _to_location(self, vdc, dc, driver): - """ - Generates the :class:`NodeLocation` class. - """ - identifier = vdc.findtext('id') - name = vdc.findtext('name') - country = dc.findtext('name') - return NodeLocation(identifier, name, country, driver) - - def _to_node(self, vm, driver): - """ - Generates the :class:`Node` class. - """ - identifier = vm.findtext('id') - name = vm.findtext('nodeName') - state = AbiquoResponse.NODE_STATE_MAP[vm.findtext('state')] - - link_image = get_href(vm, 'virtualmachinetemplate') - image_element = self.connection.request(link_image).object - repo_link = get_href(image_element, 'datacenterrepository') - image = self._to_nodeimage(image_element, self, repo_link) - - # Fill the 'ips' data - private_ips = [] - public_ips = [] - nics_element = self.connection.request(get_href(vm, 'nics')).object - for nic in nics_element.findall('nic'): - ip = nic.findtext('ip') - for link in nic.findall('link'): - rel = link.attrib['rel'] - if rel == 'privatenetwork': - private_ips.append(ip) - elif rel in ['publicnetwork', 'externalnetwork', - 'unmanagednetwork']: - public_ips.append(ip) - - extra = {'uri_id': get_href(vm, 'edit')} - - if vm.find('vdrpIp') is not None: - extra['vdrp_ip'] = vm.findtext('vdrpIP') - extra['vdrp_port'] = vm.findtext('vdrpPort') - - return Node(identifier, name, state, public_ips, private_ips, - driver, image=image, extra=extra) - - def _to_nodeimage(self, template, driver, repo): - """ - Generates the :class:`NodeImage` class. - """ - identifier = template.findtext('id') - name = template.findtext('name') - url = get_href(template, 'edit') - extra = {'repo': repo, 'url': url} - return NodeImage(identifier, name, driver, extra) - - def _get_locations(self, location=None): - """ - Returns the locations as a generator. - """ - if location is not None: - yield location - else: - for loc in self.list_locations(): - yield loc - - def _get_enterprise_id(self): - """ - Returns the identifier of the logged user's enterprise. - """ - return self.connection.cache['enterprise'].findtext('id') - - def _define_create_node_location(self, **kwargs): - """ - Search for a location where to create the node. - - Based on 'create_node' **kwargs argument, decide in which - location will be created. - """ - # First, get image location - if 'image' not in kwargs: - error = "'image' parameter is mandatory" - raise LibcloudError(error, self) - - image = kwargs['image'] - - # Get the location argument - location = None - if 'location' in kwargs: - location = kwargs['location'] - if location not in self.list_locations(): - raise LibcloudError('Location does not exist') - - # Check if the image is compatible with any of the locations or - # the input location - loc = None - target_loc = None - for candidate_loc in self._get_locations(location): - link_vdc = self.connection.cache['locations'][candidate_loc] - e_vdc = self.connection.request(link_vdc).object - # url_location = get_href(e_vdc, 'datacenter') - for img in self.list_images(candidate_loc): - if img.id == image.id: - loc = e_vdc - target_loc = candidate_loc - break - - if loc is None: - error = 'The image can not be used in any location' - raise LibcloudError(error, self) - - return loc, target_loc - - def _define_create_node_group(self, xml_loc, loc, **kwargs): - """ - Search for a group where to create the node. - - If we can not find any group, create it into argument 'location' - """ - if 'group_name' not in kwargs: - group_name = NodeGroup.DEFAULT_GROUP_NAME - else: - group_name = kwargs['group_name'] - - # We search if the group is already defined into the location - groups_link = get_href(xml_loc, 'virtualappliances') - vapps_element = self.connection.request(groups_link).object - target_group = None - for vapp in vapps_element.findall('virtualAppliance'): - if vapp.findtext('name') == group_name: - uri_vapp = get_href(vapp, 'edit') - return NodeGroup(self, vapp.findtext('name'), uri=uri_vapp) - - # target group not found: create it. Since it is an extension of - # the basic 'libcloud' functionality, we try to be as flexible as - # possible. - if target_group is None: - return self.ex_create_group(group_name, loc) - - def _define_create_node_node(self, group, **kwargs): - """ - Defines the node before to create. - - In Abiquo, you first need to 'register' or 'define' the node in - the API before to create it into the target hypervisor. - """ - vm = ET.Element('virtualmachinewithnode') - if 'name' in kwargs: - vmname = ET.SubElement(vm, 'nodeName') - vmname.text = kwargs['name'] - attrib = {'type': 'application/vnd.abiquo/virtualmachinetemplate+xml', - 'rel': 'virtualmachinetemplate', - 'href': kwargs['image'].extra['url']} - ET.SubElement(vm, 'link', attrib=attrib) - headers = {'Content-type': self.NODE_MIME_TYPE} - - if 'size' in kwargs: - # Override the 'NodeSize' data - ram = ET.SubElement(vm, 'ram') - ram.text = str(kwargs['size'].ram) - hd = ET.SubElement(vm, 'hdInBytes') - hd.text = str(int(kwargs['size'].disk) * self.GIGABYTE) - - # Create the virtual machine - nodes_link = group.uri + '/virtualmachines' - vm = self.connection.request(nodes_link, data=tostring(vm), - headers=headers, method='POST').object - edit_vm = get_href(vm, 'edit') - headers = {'Accept': self.NODE_MIME_TYPE} - - return self.connection.request(edit_vm, headers=headers).object - - -class NodeGroup(object): - """ - Group of virtual machines that can be managed together - - All :class:`Node`s in Abiquo must be defined inside a Virtual Appliance. - We offer a way to handle virtual appliances (called NodeGroup to - maintain some kind of name conventions here) inside the - :class:`AbiquoNodeDriver` without breaking compatibility of the rest of - libcloud API. - - If the user does not want to handle groups, all the virtual machines - will be created inside a group named 'libcloud' - """ - DEFAULT_GROUP_NAME = 'libcloud' - - def __init__(self, driver, name=DEFAULT_GROUP_NAME, nodes=[], uri=''): - """ - Initialize a new group object. - """ - self.driver = driver - self.name = name - self.nodes = nodes - self.uri = uri - - def __repr__(self): - return (('<NodeGroup: name=%s, nodes=[%s] >') - % (self.name, ",".join(map(str, self.nodes)))) - - def destroy(self): - """ - Destroys the group delegating the execution to - :class:`AbiquoNodeDriver`. - """ - return self.driver.ex_destroy_group(self) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/bluebox.py b/awx/lib/site-packages/libcloud/compute/drivers/bluebox.py deleted file mode 100644 index 204e0de6bf..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/bluebox.py +++ /dev/null @@ -1,235 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -libcloud driver for the Blue Box Blocks API - -This driver implements all libcloud functionality for the Blue Box Blocks API. - -Blue Box home page http://bluebox.net -Blue Box API documentation https://boxpanel.bluebox -.net/public/the_vault/index.php/Blocks_API -""" - -import copy -import base64 - -from libcloud.utils.py3 import urlencode -from libcloud.utils.py3 import b - -from libcloud.common.base import JsonResponse, ConnectionUserAndKey -from libcloud.compute.providers import Provider -from libcloud.compute.types import NodeState, InvalidCredsError -from libcloud.compute.base import Node, NodeDriver -from libcloud.compute.base import NodeSize, NodeImage, NodeLocation -from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey - -# Current end point for Blue Box API. -BLUEBOX_API_HOST = "boxpanel.bluebox.net" - -# The API doesn't currently expose all of the required values for libcloud, -# so we simply list what's available right now, along with all of the various -# attributes that are needed by libcloud. -BLUEBOX_INSTANCE_TYPES = { - '1gb': { - 'id': '94fd37a7-2606-47f7-84d5-9000deda52ae', - 'name': 'Block 1GB Virtual Server', - 'ram': 1024, - 'disk': 20, - 'cpu': 0.5 - }, - '2gb': { - 'id': 'b412f354-5056-4bf0-a42f-6ddd998aa092', - 'name': 'Block 2GB Virtual Server', - 'ram': 2048, - 'disk': 25, - 'cpu': 1 - }, - '4gb': { - 'id': '0cd183d3-0287-4b1a-8288-b3ea8302ed58', - 'name': 'Block 4GB Virtual Server', - 'ram': 4096, - 'disk': 50, - 'cpu': 2 - }, - '8gb': { - 'id': 'b9b87a5b-2885-4a2e-b434-44a163ca6251', - 'name': 'Block 8GB Virtual Server', - 'ram': 8192, - 'disk': 100, - 'cpu': 4 - } -} - -RAM_PER_CPU = 2048 - -NODE_STATE_MAP = {'queued': NodeState.PENDING, - 'building': NodeState.PENDING, - 'running': NodeState.RUNNING, - 'error': NodeState.TERMINATED, - 'unknown': NodeState.UNKNOWN} - - -class BlueboxResponse(JsonResponse): - def parse_error(self): - if int(self.status) == 401: - if not self.body: - raise InvalidCredsError(str(self.status) + ': ' + self.error) - else: - raise InvalidCredsError(self.body) - return self.body - - -class BlueboxNodeSize(NodeSize): - def __init__(self, id, name, cpu, ram, disk, price, driver): - self.id = id - self.name = name - self.cpu = cpu - self.ram = ram - self.disk = disk - self.price = price - self.driver = driver - - def __repr__(self): - return (( - '<NodeSize: id=%s, name=%s, cpu=%s, ram=%s, disk=%s, ' - 'price=%s, driver=%s ...>') - % (self.id, self.name, self.cpu, self.ram, self.disk, - self.price, self.driver.name)) - - -class BlueboxConnection(ConnectionUserAndKey): - """ - Connection class for the Bluebox driver - """ - - host = BLUEBOX_API_HOST - secure = True - responseCls = BlueboxResponse - - allow_insecure = False - - def add_default_headers(self, headers): - user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) - headers['Authorization'] = 'Basic %s' % (user_b64) - return headers - - -class BlueboxNodeDriver(NodeDriver): - """ - Bluebox Blocks node driver - """ - - connectionCls = BlueboxConnection - type = Provider.BLUEBOX - api_name = 'bluebox' - name = 'Bluebox Blocks' - website = 'http://bluebox.net' - features = {'create_node': ['ssh_key', 'password']} - - def list_nodes(self): - result = self.connection.request('/api/blocks.json') - return [self._to_node(i) for i in result.object] - - def list_sizes(self, location=None): - sizes = [] - for key, values in list(BLUEBOX_INSTANCE_TYPES.items()): - attributes = copy.deepcopy(values) - attributes.update({'price': self._get_size_price(size_id=key)}) - sizes.append(BlueboxNodeSize(driver=self.connection.driver, - **attributes)) - - return sizes - - def list_images(self, location=None): - result = self.connection.request('/api/block_templates.json') - images = [] - for image in result.object: - images.extend([self._to_image(image)]) - - return images - - def create_node(self, **kwargs): - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - size = kwargs["size"] - - name = kwargs['name'] - image = kwargs['image'] - size = kwargs['size'] - - auth = self._get_and_check_auth(kwargs.get('auth')) - - data = { - 'hostname': name, - 'product': size.id, - 'template': image.id - } - - ssh = None - password = None - - if isinstance(auth, NodeAuthSSHKey): - ssh = auth.pubkey - data.update(ssh_public_key=ssh) - elif isinstance(auth, NodeAuthPassword): - password = auth.password - data.update(password=password) - - if "ex_username" in kwargs: - data.update(username=kwargs["ex_username"]) - - if not ssh and not password: - raise Exception("SSH public key or password required.") - - params = urlencode(data) - result = self.connection.request('/api/blocks.json', headers=headers, - data=params, method='POST') - node = self._to_node(result.object) - - if getattr(auth, "generated", False): - node.extra['password'] = auth.password - - return node - - def destroy_node(self, node): - url = '/api/blocks/%s.json' % (node.id) - result = self.connection.request(url, method='DELETE') - - return result.status == 200 - - def list_locations(self): - return [NodeLocation(0, "Blue Box Seattle US", 'US', self)] - - def reboot_node(self, node): - url = '/api/blocks/%s/reboot.json' % (node.id) - result = self.connection.request(url, method="PUT") - return result.status == 200 - - def _to_node(self, vm): - state = NODE_STATE_MAP[vm.get('status', NodeState.UNKNOWN)] - n = Node(id=vm['id'], - name=vm['hostname'], - state=state, - public_ips=[ip['address'] for ip in vm['ips']], - private_ips=[], - extra={'storage': vm['storage'], 'cpu': vm['cpu']}, - driver=self.connection.driver) - return n - - def _to_image(self, image): - image = NodeImage(id=image['id'], - name=image['description'], - driver=self.connection.driver) - return image diff --git a/awx/lib/site-packages/libcloud/compute/drivers/brightbox.py b/awx/lib/site-packages/libcloud/compute/drivers/brightbox.py deleted file mode 100644 index 8798332ff0..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/brightbox.py +++ /dev/null @@ -1,306 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Brightbox Driver -""" - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -from libcloud.common.brightbox import BrightboxConnection -from libcloud.compute.types import Provider, NodeState -from libcloud.compute.base import NodeDriver -from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation - -import base64 - - -API_VERSION = '1.0' - - -def _extract(d, keys): - return dict((k, d[k]) for k in keys if k in d and d[k] is not None) - - -class BrightboxNodeDriver(NodeDriver): - """ - Brightbox node driver - """ - - connectionCls = BrightboxConnection - - type = Provider.BRIGHTBOX - name = 'Brightbox' - website = 'http://www.brightbox.co.uk/' - - NODE_STATE_MAP = {'creating': NodeState.PENDING, - 'active': NodeState.RUNNING, - 'inactive': NodeState.UNKNOWN, - 'deleting': NodeState.UNKNOWN, - 'deleted': NodeState.TERMINATED, - 'failed': NodeState.UNKNOWN, - 'unavailable': NodeState.UNKNOWN} - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - api_version=API_VERSION, **kwargs): - super(BrightboxNodeDriver, self).__init__(key=key, secret=secret, - secure=secure, - host=host, port=port, - api_version=api_version, - **kwargs) - - def _to_node(self, data): - extra_data = _extract(data, ['fqdn', 'user_data', 'status', - 'interfaces', 'snapshots', - 'server_groups', 'hostname', - 'started_at', 'created_at', - 'deleted_at']) - extra_data['zone'] = self._to_location(data['zone']) - - ipv6_addresses = [interface['ipv6_address'] for interface - in data['interfaces'] if 'ipv6_address' in interface] - - private_ips = [interface['ipv4_address'] - for interface in data['interfaces'] - if 'ipv4_address' in interface] - - public_ips = [cloud_ip['public_ip'] for cloud_ip in data['cloud_ips']] - public_ips += ipv6_addresses - - return Node( - id=data['id'], - name=data['name'], - state=self.NODE_STATE_MAP[data['status']], - private_ips=private_ips, - public_ips=public_ips, - driver=self.connection.driver, - size=self._to_size(data['server_type']), - image=self._to_image(data['image']), - extra=extra_data - ) - - def _to_image(self, data): - extra_data = _extract(data, ['arch', 'compatibility_mode', - 'created_at', 'description', - 'disk_size', 'min_ram', 'official', - 'owner', 'public', 'source', - 'source_type', 'status', 'username', - 'virtual_size', 'licence_name']) - - if data.get('ancestor', None): - extra_data['ancestor'] = self._to_image(data['ancestor']) - - return NodeImage( - id=data['id'], - name=data['name'], - driver=self, - extra=extra_data - ) - - def _to_size(self, data): - return NodeSize( - id=data['id'], - name=data['name'], - ram=data['ram'], - disk=data['disk_size'], - bandwidth=0, - price=0, - driver=self - ) - - def _to_location(self, data): - if data: - return NodeLocation( - id=data['id'], - name=data['handle'], - country='GB', - driver=self - ) - else: - return None - - def _post(self, path, data={}): - headers = {'Content-Type': 'application/json'} - return self.connection.request(path, data=data, headers=headers, - method='POST') - - def _put(self, path, data={}): - headers = {'Content-Type': 'application/json'} - return self.connection.request(path, data=data, headers=headers, - method='PUT') - - def create_node(self, **kwargs): - """Create a new Brightbox node - - Reference: https://api.gb1.brightbox.com/1.0/#server_create_server - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_userdata: User data - :type ex_userdata: ``str`` - - :keyword ex_servergroup: Name or list of server group ids to - add server to - :type ex_servergroup: ``str`` or ``list`` of ``str`` - """ - data = { - 'name': kwargs['name'], - 'server_type': kwargs['size'].id, - 'image': kwargs['image'].id, - } - - if 'ex_userdata' in kwargs: - data['user_data'] = base64.b64encode(b(kwargs['ex_userdata'])) \ - .decode('ascii') - - if 'location' in kwargs: - data['zone'] = kwargs['location'].id - - if 'ex_servergroup' in kwargs: - if not isinstance(kwargs['ex_servergroup'], list): - kwargs['ex_servergroup'] = [kwargs['ex_servergroup']] - data['server_groups'] = kwargs['ex_servergroup'] - - data = self._post('/%s/servers' % self.api_version, data).object - return self._to_node(data) - - def destroy_node(self, node): - response = self.connection.request( - '/%s/servers/%s' % (self.api_version, node.id), - method='DELETE') - return response.status == httplib.ACCEPTED - - def list_nodes(self): - data = self.connection.request('/%s/servers' % self.api_version).object - return list(map(self._to_node, data)) - - def list_images(self, location=None): - data = self.connection.request('/%s/images' % self.api_version).object - return list(map(self._to_image, data)) - - def list_sizes(self): - data = self.connection.request('/%s/server_types' % self.api_version) \ - .object - return list(map(self._to_size, data)) - - def list_locations(self): - data = self.connection.request('/%s/zones' % self.api_version).object - return list(map(self._to_location, data)) - - def ex_list_cloud_ips(self): - """ - List Cloud IPs - - @note: This is an API extension for use on Brightbox - - :rtype: ``list`` of ``dict`` - """ - return self.connection.request('/%s/cloud_ips' % self.api_version) \ - .object - - def ex_create_cloud_ip(self, reverse_dns=None): - """ - Requests a new cloud IP address for the account - - @note: This is an API extension for use on Brightbox - - :param reverse_dns: Reverse DNS hostname - :type reverse_dns: ``str`` - - :rtype: ``dict`` - """ - params = {} - - if reverse_dns: - params['reverse_dns'] = reverse_dns - - return self._post('/%s/cloud_ips' % self.api_version, params).object - - def ex_update_cloud_ip(self, cloud_ip_id, reverse_dns): - """ - Update some details of the cloud IP address - - @note: This is an API extension for use on Brightbox - - :param cloud_ip_id: The id of the cloud ip. - :type cloud_ip_id: ``str`` - - :param reverse_dns: Reverse DNS hostname - :type reverse_dns: ``str`` - - :rtype: ``dict`` - """ - response = self._put('/%s/cloud_ips/%s' % (self.api_version, - cloud_ip_id), - {'reverse_dns': reverse_dns}) - return response.status == httplib.OK - - def ex_map_cloud_ip(self, cloud_ip_id, interface_id): - """ - Maps (or points) a cloud IP address at a server's interface - or a load balancer to allow them to respond to public requests - - @note: This is an API extension for use on Brightbox - - :param cloud_ip_id: The id of the cloud ip. - :type cloud_ip_id: ``str`` - - :param interface_id: The Interface ID or LoadBalancer ID to - which this Cloud IP should be mapped to - :type interface_id: ``str`` - - :return: True if the mapping was successful. - :rtype: ``bool`` - """ - response = self._post('/%s/cloud_ips/%s/map' % (self.api_version, - cloud_ip_id), - {'destination': interface_id}) - return response.status == httplib.ACCEPTED - - def ex_unmap_cloud_ip(self, cloud_ip_id): - """ - Unmaps a cloud IP address from its current destination making - it available to remap. This remains in the account's pool - of addresses - - @note: This is an API extension for use on Brightbox - - :param cloud_ip_id: The id of the cloud ip. - :type cloud_ip_id: ``str`` - - :return: True if the unmap was successful. - :rtype: ``bool`` - """ - response = self._post('/%s/cloud_ips/%s/unmap' % (self.api_version, - cloud_ip_id)) - return response.status == httplib.ACCEPTED - - def ex_destroy_cloud_ip(self, cloud_ip_id): - """ - Release the cloud IP address from the account's ownership - - @note: This is an API extension for use on Brightbox - - :param cloud_ip_id: The id of the cloud ip. - :type cloud_ip_id: ``str`` - - :return: True if the unmap was successful. - :rtype: ``bool`` - """ - response = self.connection.request( - '/%s/cloud_ips/%s' % (self.api_version, - cloud_ip_id), - method='DELETE') - return response.status == httplib.OK diff --git a/awx/lib/site-packages/libcloud/compute/drivers/cloudframes.py b/awx/lib/site-packages/libcloud/compute/drivers/cloudframes.py deleted file mode 100644 index 9902f5dbb9..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/cloudframes.py +++ /dev/null @@ -1,431 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -CloudFrames Driver - -""" - -# (name, ram, disk, bandwidth, price, vcpus) -SIZES = [ - ('512mb_1core_10gb', 512, 10, 512, 0.025, 1), - ('1024mb_1core_20gb', 1024, 20, 512, 0.05, 1), - ('2048mb_2core_50gb', 2048, 50, 1024, 0.10, 2), - ('4096mb_2core_100gb', 4096, 100, 2048, 0.20, 2), - ('8192mb_4core_200gb', 8192, 200, 2048, 0.40, 4), - ('16384mb_4core_400gb', 16384, 400, 4096, 0.80, 4), -] - -import base64 -import random - -from libcloud.utils.py3 import urlparse, b -from libcloud.common.base import ConnectionKey -from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection -from libcloud.common.types import ProviderError -from libcloud.compute.base import NodeImage, NodeSize, Node, NodeLocation -from libcloud.compute.base import NodeDriver -from libcloud.compute.types import Provider, NodeState - - -class CloudFramesException(ProviderError): - pass - - -class CloudFramesComponent(object): - """ - Represents a node in the cloudapi path. - """ - - def __init__(self, cloudFramesConnection, name): - self.cloudFramesConnection = cloudFramesConnection - self.name = name - - def __getattr__(self, key): - return self.method(key) - - def method(self, methodname): - def foo(*args, **kwargs): - async = kwargs.get('async', False) - args = list(args) - args.append('') # jobguid - args.append({'wait': False} if async else {}) # executionparams - response = self.cloudFramesConnection.request( - 'cloud_api_%s.%s' % (self.name, methodname), *args) - if not response.success(): - response.parse_error() - if async: - return response.parse_body()['jobguid'] - else: - return response.parse_body()['result'] - return foo - - -class CloudFramesNodeSize(NodeSize): - - def __init__(self, id, name, ram, disk, bandwidth, price, driver, - vcpus=None): - super(CloudFramesNodeSize, self).__init__( - id, name, ram, disk, bandwidth, price, driver) - self.vcpus = vcpus - - -class CloudFramesNode(Node): - - def list_snapshots(self): - return self.driver.ex_list_snapshots(self) - - def snapshot(self, label='', description=''): - return self.driver.ex_snapshot_node(self, label, description) - - def rollback(self, snapshot): - return self.driver.ex_rollback_node(self, snapshot) - - -class CloudFramesSnapshot(object): - - def __init__(self, id, timestamp, label, description, driver): - self.id = id - self.timestamp = timestamp - self.label = label - self.description = description - self.driver = driver - - def destroy(self): - self.driver.ex_destroy_snapshot(self) - - -class CloudFramesConnection(XMLRPCConnection, ConnectionKey): - """ - Cloudapi connection class - """ - - repsonseCls = XMLRPCResponse - base_url = None - - def __init__(self, key=None, secret=None, secure=True, - host=None, port=None, url=None, timeout=None): - """ - :param key: The username to connect with to the cloudapi - :type key: ``str`` - - :param secret: The password to connect with to the cloudapi - :type secret: ``str`` - - :param secure: Should always be false at the moment - :type secure: ``bool`` - - :param host: The hostname of the cloudapi - :type host: ``str`` - - :param port: The port on which to connect to the cloudapi - :type port: ``int`` - - :param url: Url to the cloudapi (can replace all above) - :type url: ``str`` - """ - - super(CloudFramesConnection, self).__init__(key=key, secure=secure, - host=host, port=port, - url=url, timeout=timeout) - self._auth = base64.b64encode( - b('%s:%s' % (key, secret))).decode('utf-8') - self.endpoint = url - - def __getattr__(self, key): - return CloudFramesComponent(self, key) - - def add_default_headers(self, headers): - headers['Authorization'] = 'Basic %s' % self._auth - return headers - - -class CloudFramesNodeDriver(NodeDriver): - """ - CloudFrames node driver - """ - - connectionCls = CloudFramesConnection - - name = 'CloudFrames' - api_name = 'cloudframes' - website = 'http://www.cloudframes.net/' - type = Provider.CLOUDFRAMES - - NODE_STATE_MAP = { - 'CONFIGURED': NodeState.PENDING, - 'CREATED': NodeState.PENDING, - 'DELETING': NodeState.PENDING, - 'HALTED': NodeState.TERMINATED, - 'IMAGEONLY': NodeState.UNKNOWN, - 'ISCSIEXPOSED': NodeState.PENDING, - 'MOVING': NodeState.PENDING, - 'OVERLOADED': NodeState.UNKNOWN, - 'PAUSED': NodeState.TERMINATED, - 'RUNNING': NodeState.RUNNING, - 'STARTING': NodeState.PENDING, - 'STOPPING': NodeState.PENDING, - 'SYNCING': NodeState.PENDING, - 'TODELETE': NodeState.PENDING, - } - - # subclassed internal methods - def __init__(self, key=None, secret=None, secure=True, - host=None, port=None, url=None, **kwargs): - if not port: - port = 443 if secure else 80 - if url: - if not url.endswith('/'): - url += '/' - scheme, netloc, _, _, _, _ = urlparse.urlparse(url) - secure = (scheme == 'https') - if '@' in netloc: - auth, hostport = netloc.rsplit('@', 1) - if ':' in auth: - key, secret = auth.split(':', 1) - else: - key = auth - else: - hostport = netloc - if ':' in hostport: - host, port = hostport.split(':') - else: - host = hostport - hostport = '%s:%s' % (host, port) - url = url.replace(netloc, hostport) - else: - url = '%s://%s:%s/appserver/xmlrpc/' % ( - 'https' if secure else 'http', host, port) - - if secure: - raise NotImplementedError( - 'The cloudapi only supports unsecure connections') - - if key is None or secret is None: - raise NotImplementedError( - 'Unauthenticated support to the cloudapi is not supported') - - # connection url - self._url = url - - # cached attributes - self.__cloudspaceguid = None - self.__languid = None - self.__locations = [] - - super(CloudFramesNodeDriver, self).__init__( - key, secret, secure, host, port, **kwargs) - - def _ex_connection_class_kwargs(self): - return {'url': self._url} - - # internal methods - @property - def _cloudspaceguid(self): - if not self.__cloudspaceguid: - self.__cloudspaceguid = self.connection.cloudspace.find( - '', '', 'cloud', '')[0] - return self.__cloudspaceguid - - @property - def _languid(self): - if not self.__languid: - self.__languid = self.connection.lan.find( - '', '', 'public_virtual', '', '', '', '', '', '', '', '', '', - '', '', '', '', '')[0] - return self.__languid - - def _get_machine_data(self, guid): - """ - Looks up some basic data related to the given machine guid. - """ - try: - d = self.connection.machine.list('', '', '', guid, '')[0] - except IndexError: - raise CloudFramesException('VM no longer exists', 404, self) - d['public_ips'] = [] - d['private_ips'] = [] - d['size'] = None - d['image'] = None - return d - - def _machine_find(self, template=False, machinetype=None, - machinerole=None): - # the cloudframes xmlrpc api requires you to pass all args and kwargs - # as positional arguments, you can't use keywords arguments - if not machinetype: - guids = [] - for machinetype in ['VIRTUALSERVER', 'VIRTUALDESKTOP']: - guids += self.connection.machine.find( - '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', - '', '', machinetype, template, '', '', '', '', '', '', '', - '', '', '', '', '', '', '') - else: - guids = self.connection.machine.find( - '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', - '', '', machinetype, '', '', '', '', '', '', '', '', - machinerole, '', '', '', '', '', '') - return guids - - def _to_image(self, image_dict): - return NodeImage(id=image_dict['guid'], - name=image_dict['name'], - driver=self.connection.driver) - - def _to_size(self, id, name, ram, disk, bandwidth, price, vcpus): - return CloudFramesNodeSize( - id, name, ram, disk, bandwidth, price, self, vcpus) - - def _to_location(self, location_dict): - return NodeLocation(id=location_dict['guid'], - name=location_dict['name'], - country=None, - driver=self) - - def _to_node(self, node_dict): - # only return nodes which can be worked with - # (ignore cloudframes internal autotests and deleted nodes) - if node_dict['status'] == 'CONFIGURED': - return None - return CloudFramesNode(id=node_dict['guid'], - name=node_dict['name'], - state=self.NODE_STATE_MAP.get( - node_dict['status'], NodeState.UNKNOWN), - public_ips=node_dict['public_ips'], - private_ips=node_dict['private_ips'], - driver=self.connection.driver, - size=node_dict['size'], - image=node_dict['image'], - extra={}) - - def _to_snapshot(self, snapshot_dict): - return CloudFramesSnapshot(id=snapshot_dict['guid'], - timestamp=snapshot_dict['timestamp'], - label=snapshot_dict['backuplabel'], - description=snapshot_dict['description'], - driver=self) - - # subclassed public methods, and provider specific public methods - def list_images(self, location=None): - image_ids = self._machine_find(template=True) - image_list = [] - for image_id in image_ids: - image_list.append(self._to_image(self._get_machine_data(image_id))) - return image_list - - def list_sizes(self, location=None): - sizes = [] - for id in range(len(SIZES)): - sizes.append(self._to_size(id, *SIZES[id])) - return sizes - - def list_locations(self, ex_use_cached=True): - if not self.__locations or not ex_use_cached: - self.__locations = [] - for location_id in self._machine_find(machinetype='PHYSICAL', - machinerole='COMPUTENODE'): - self.__locations.append( - self._to_location(self._get_machine_data(location_id))) - return self.__locations - - def list_nodes(self): - node_ids = self._machine_find() - node_list = [] - for node_id in node_ids: - node = self._to_node(self._get_machine_data(node_id)) - if node: - node_list.append(node) - return node_list - - def create_node(self, **kwargs): - """ - Creates a new node, by cloning the template provided. - - If no location object is passed, a random location will be used. - - - :param image: The template to be cloned (required) - :type image: ``list`` of :class:`NodeImage` - - :param name: The name for the new node (required) - :type name: ``str`` - - :param size: The size of the new node (required) - :type size: ``list`` of :class:`NodeSize` - - :param location: The location to create the new node - :type location: ``list`` of :class:`NodeLocation` - - :param default_gateway: The default gateway to be used - :type default_gateway: ``str`` - - :param extra: Additional requirements (extra disks fi.) - :type extra: ``dict`` - - - :returns: ``list`` of :class:`Node` -- The newly created Node object - - :raises: CloudFramesException - """ - - additionalinfo = kwargs.get('extra', {}) - additionalinfo.update({ - 'memory': kwargs['size'].ram, - 'cpu': kwargs['size'].vcpus, - }) - guid = self.connection.machine.createFromTemplate( - self._cloudspaceguid, kwargs['image'].id, kwargs['name'], - [{'languid': self._languid}], kwargs['name'], - kwargs.get('location', random.choice(self.list_locations())).id, - kwargs.get('default_gateway', ''), None, additionalinfo) - if not self.connection.machine.start(guid): - raise CloudFramesException( - 'failed to start machine after creation', 500, self) - return self._to_node(self._get_machine_data(guid)) - - def destroy_node(self, node): - return self.connection.machine.delete(node.id, False) - - def reboot_node(self, node, ex_clean=True): - return self.connection.machine.reboot(node.id, ex_clean) - - def ex_snapshot_node(self, node, label='', description=''): - guid = self.connection.machine.snapshot( - node.id, label, description, False, False, 'PAUSED') - for snapshot in self.ex_list_snapshots(node): - if snapshot.id == guid: - return snapshot - else: - raise CloudFramesException('Snapshot creation failed', 500, self) - - def ex_rollback_node(self, node, snapshot): - if not node.state == NodeState.TERMINATED: - self.connection.machine.stop(node.id, False, 930) - success = self.connection.machine.rollback(node.id, snapshot.id) - self.connection.machine.start(node.id) - return success - - def ex_list_snapshots(self, node): - return [self._to_snapshot(snapshot_dict) for snapshot_dict in - self.connection.machine.listSnapshots(node.id, False, '', '')] - - def ex_destroy_snapshot(self, node, snapshot): - return self.connection.machine.delete(snapshot.id, False) - - -if __name__ == "__main__": - import doctest - - doctest.testmod() diff --git a/awx/lib/site-packages/libcloud/compute/drivers/cloudsigma.py b/awx/lib/site-packages/libcloud/compute/drivers/cloudsigma.py deleted file mode 100644 index 29b65cb21b..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/cloudsigma.py +++ /dev/null @@ -1,2093 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Drivers for CloudSigma API v1.0 and v2.0. -""" - -import re -import time -import copy -import base64 - -try: - import simplejson as json -except: - import json - -from libcloud.utils.py3 import b -from libcloud.utils.py3 import httplib - -from libcloud.utils.misc import str2dicts, str2list, dict2str -from libcloud.common.base import ConnectionUserAndKey, JsonResponse, Response -from libcloud.common.types import InvalidCredsError, ProviderError -from libcloud.common.cloudsigma import INSTANCE_TYPES -from libcloud.common.cloudsigma import API_ENDPOINTS_1_0 -from libcloud.common.cloudsigma import API_ENDPOINTS_2_0 -from libcloud.common.cloudsigma import DEFAULT_API_VERSION, DEFAULT_REGION -from libcloud.compute.types import NodeState, Provider -from libcloud.compute.base import NodeDriver, NodeSize, Node -from libcloud.compute.base import NodeImage -from libcloud.compute.base import is_private_subnet -from libcloud.utils.iso8601 import parse_date -from libcloud.utils.misc import get_secure_random_string - -__all__ = [ - 'CloudSigmaNodeDriver', - 'CloudSigma_1_0_NodeDriver', - 'CloudSigma_2_0_NodeDriver', - 'CloudSigmaError', - - 'CloudSigmaNodeSize', - 'CloudSigmaDrive', - 'CloudSigmaTag', - 'CloudSigmaSubscription', - 'CloudSigmaFirewallPolicy', - 'CloudSigmaFirewallPolicyRule' -] - - -class CloudSigmaNodeDriver(NodeDriver): - name = 'CloudSigma' - website = 'http://www.cloudsigma.com/' - - def __new__(cls, key, secret=None, secure=True, host=None, port=None, - api_version=DEFAULT_API_VERSION, **kwargs): - if cls is CloudSigmaNodeDriver: - if api_version == '1.0': - cls = CloudSigma_1_0_NodeDriver - elif api_version == '2.0': - cls = CloudSigma_2_0_NodeDriver - else: - raise NotImplementedError('Unsupported API version: %s' % - (api_version)) - return super(CloudSigmaNodeDriver, cls).__new__(cls) - - -class CloudSigmaException(Exception): - def __str__(self): - return self.args[0] - - def __repr__(self): - return "<CloudSigmaException '%s'>" % (self.args[0]) - - -class CloudSigmaInsufficientFundsException(Exception): - def __repr__(self): - return "<CloudSigmaInsufficientFundsException '%s'>" % (self.args[0]) - - -class CloudSigmaNodeSize(NodeSize): - def __init__(self, id, name, cpu, ram, disk, bandwidth, price, driver): - self.id = id - self.name = name - self.cpu = cpu - self.ram = ram - self.disk = disk - self.bandwidth = bandwidth - self.price = price - self.driver = driver - - def __repr__(self): - return (('<NodeSize: id=%s, name=%s, cpu=%s, ram=%s disk=%s ' - 'bandwidth=%s price=%s driver=%s ...>') - % (self.id, self.name, self.cpu, self.ram, self.disk, - self.bandwidth, self.price, self.driver.name)) - - -class CloudSigma_1_0_Response(Response): - def success(self): - if self.status == httplib.UNAUTHORIZED: - raise InvalidCredsError() - - return self.status >= 200 and self.status <= 299 - - def parse_body(self): - if not self.body: - return self.body - - return str2dicts(self.body) - - def parse_error(self): - return 'Error: %s' % (self.body.replace('errors:', '').strip()) - - -class CloudSigma_1_0_Connection(ConnectionUserAndKey): - host = API_ENDPOINTS_1_0[DEFAULT_REGION]['host'] - responseCls = CloudSigma_1_0_Response - - def add_default_headers(self, headers): - headers['Accept'] = 'application/json' - headers['Content-Type'] = 'application/json' - - headers['Authorization'] = 'Basic %s' % (base64.b64encode( - b('%s:%s' % (self.user_id, self.key))).decode('utf-8')) - return headers - - -class CloudSigma_1_0_NodeDriver(CloudSigmaNodeDriver): - type = Provider.CLOUDSIGMA - name = 'CloudSigma (API v1.0)' - website = 'http://www.cloudsigma.com/' - connectionCls = CloudSigma_1_0_Connection - - IMAGING_TIMEOUT = 20 * 60 # Default timeout (in seconds) for the drive - # imaging process - - NODE_STATE_MAP = { - 'active': NodeState.RUNNING, - 'stopped': NodeState.TERMINATED, - 'dead': NodeState.TERMINATED, - 'dumped': NodeState.TERMINATED, - } - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region=DEFAULT_REGION, **kwargs): - if region not in API_ENDPOINTS_1_0: - raise ValueError('Invalid region: %s' % (region)) - - self._host_argument_set = host is not None - self.api_name = 'cloudsigma_%s' % (region) - super(CloudSigma_1_0_NodeDriver, self).__init__(key=key, secret=secret, - secure=secure, - host=host, - port=port, - region=region, - **kwargs) - - def reboot_node(self, node): - """ - Reboot a node. - - Because Cloudsigma API does not provide native reboot call, - it's emulated using stop and start. - - @inherits: :class:`NodeDriver.reboot_node` - """ - node = self._get_node(node.id) - state = node.state - - if state == NodeState.RUNNING: - stopped = self.ex_stop_node(node) - else: - stopped = True - - if not stopped: - raise CloudSigmaException( - 'Could not stop node with id %s' % (node.id)) - - success = self.ex_start_node(node) - - return success - - def destroy_node(self, node): - """ - Destroy a node (all the drives associated with it are NOT destroyed). - - If a node is still running, it's stopped before it's destroyed. - - @inherits: :class:`NodeDriver.destroy_node` - """ - node = self._get_node(node.id) - state = node.state - - # Node cannot be destroyed while running so it must be stopped first - if state == NodeState.RUNNING: - stopped = self.ex_stop_node(node) - else: - stopped = True - - if not stopped: - raise CloudSigmaException( - 'Could not stop node with id %s' % (node.id)) - - response = self.connection.request( - action='/servers/%s/destroy' % (node.id), - method='POST') - return response.status == 204 - - def list_images(self, location=None): - """ - Return a list of available standard images (this call might take up - to 15 seconds to return). - - @inherits: :class:`NodeDriver.list_images` - """ - response = self.connection.request( - action='/drives/standard/info').object - - images = [] - for value in response: - if value.get('type'): - if value['type'] == 'disk': - image = NodeImage(id=value['drive'], name=value['name'], - driver=self.connection.driver, - extra={'size': value['size']}) - images.append(image) - - return images - - def list_sizes(self, location=None): - sizes = [] - for value in INSTANCE_TYPES: - key = value['id'] - size = CloudSigmaNodeSize(id=value['id'], name=value['name'], - cpu=value['cpu'], ram=value['memory'], - disk=value['disk'], - bandwidth=value['bandwidth'], - price=self._get_size_price(size_id=key), - driver=self.connection.driver) - sizes.append(size) - - return sizes - - def list_nodes(self): - response = self.connection.request(action='/servers/info').object - - nodes = [] - for data in response: - node = self._to_node(data) - if node: - nodes.append(node) - return nodes - - def create_node(self, **kwargs): - """ - Creates a CloudSigma instance - - @inherits: :class:`NodeDriver.create_node` - - :keyword name: String with a name for this new node (required) - :type name: ``str`` - - :keyword smp: Number of virtual processors or None to calculate - based on the cpu speed - :type smp: ``int`` - - :keyword nic_model: e1000, rtl8139 or virtio (is not specified, - e1000 is used) - :type nic_model: ``str`` - - :keyword vnc_password: If not set, VNC access is disabled. - :type vnc_password: ``bool`` - - :keyword drive_type: Drive type (ssd|hdd). Defaults to hdd. - :type drive_type: ``str`` - """ - size = kwargs['size'] - image = kwargs['image'] - smp = kwargs.get('smp', 'auto') - nic_model = kwargs.get('nic_model', 'e1000') - vnc_password = kwargs.get('vnc_password', None) - drive_type = kwargs.get('drive_type', 'hdd') - - if nic_model not in ['e1000', 'rtl8139', 'virtio']: - raise CloudSigmaException('Invalid NIC model specified') - - if drive_type not in ['hdd', 'ssd']: - raise CloudSigmaException('Invalid drive type "%s". Valid types' - ' are: hdd, ssd' % (drive_type)) - - drive_data = {} - drive_data.update({'name': kwargs['name'], - 'size': '%sG' % (kwargs['size'].disk), - 'driveType': drive_type}) - - response = self.connection.request( - action='/drives/%s/clone' % image.id, - data=dict2str(drive_data), - method='POST').object - - if not response: - raise CloudSigmaException('Drive creation failed') - - drive_uuid = response[0]['drive'] - - response = self.connection.request( - action='/drives/%s/info' % (drive_uuid)).object - imaging_start = time.time() - while 'imaging' in response[0]: - response = self.connection.request( - action='/drives/%s/info' % (drive_uuid)).object - elapsed_time = time.time() - imaging_start - timed_out = elapsed_time >= self.IMAGING_TIMEOUT - if 'imaging' in response[0] and timed_out: - raise CloudSigmaException('Drive imaging timed out') - time.sleep(1) - - node_data = {} - node_data.update( - {'name': kwargs['name'], 'cpu': size.cpu, 'mem': size.ram, - 'ide:0:0': drive_uuid, 'boot': 'ide:0:0', 'smp': smp}) - node_data.update({'nic:0:model': nic_model, 'nic:0:dhcp': 'auto'}) - - if vnc_password: - node_data.update({'vnc:ip': 'auto', 'vnc:password': vnc_password}) - - response = self.connection.request(action='/servers/create', - data=dict2str(node_data), - method='POST').object - - if not isinstance(response, list): - response = [response] - - node = self._to_node(response[0]) - if node is None: - # Insufficient funds, destroy created drive - self.ex_drive_destroy(drive_uuid) - raise CloudSigmaInsufficientFundsException( - 'Insufficient funds, node creation failed') - - # Start the node after it has been created - started = self.ex_start_node(node) - - if started: - node.state = NodeState.RUNNING - - return node - - def ex_destroy_node_and_drives(self, node): - """ - Destroy a node and all the drives associated with it. - - :param node: Node which should be used - :type node: :class:`libcloud.compute.base.Node` - - :rtype: ``bool`` - """ - node = self._get_node_info(node) - - drive_uuids = [] - for key, value in node.items(): - if (key.startswith('ide:') or key.startswith( - 'scsi') or key.startswith('block')) and\ - not (key.endswith(':bytes') or - key.endswith(':requests') or key.endswith('media')): - drive_uuids.append(value) - - node_destroyed = self.destroy_node(self._to_node(node)) - - if not node_destroyed: - return False - - for drive_uuid in drive_uuids: - self.ex_drive_destroy(drive_uuid) - - return True - - def ex_static_ip_list(self): - """ - Return a list of available static IP addresses. - - :rtype: ``list`` of ``str`` - """ - response = self.connection.request(action='/resources/ip/list', - method='GET') - - if response.status != 200: - raise CloudSigmaException('Could not retrieve IP list') - - ips = str2list(response.body) - return ips - - def ex_drives_list(self): - """ - Return a list of all the available drives. - - :rtype: ``list`` of ``dict`` - """ - response = self.connection.request(action='/drives/info', method='GET') - - result = str2dicts(response.body) - return result - - def ex_static_ip_create(self): - """ - Create a new static IP address.p - - :rtype: ``list`` of ``dict`` - """ - response = self.connection.request(action='/resources/ip/create', - method='GET') - - result = str2dicts(response.body) - return result - - def ex_static_ip_destroy(self, ip_address): - """ - Destroy a static IP address. - - :param ip_address: IP address which should be used - :type ip_address: ``str`` - - :rtype: ``bool`` - """ - response = self.connection.request( - action='/resources/ip/%s/destroy' % (ip_address), method='GET') - - return response.status == 204 - - def ex_drive_destroy(self, drive_uuid): - """ - Destroy a drive with a specified uuid. - If the drive is currently mounted an exception is thrown. - - :param drive_uuid: Drive uuid which should be used - :type drive_uuid: ``str`` - - :rtype: ``bool`` - """ - response = self.connection.request( - action='/drives/%s/destroy' % (drive_uuid), method='POST') - - return response.status == 204 - - def ex_set_node_configuration(self, node, **kwargs): - """ - Update a node configuration. - Changing most of the parameters requires node to be stopped. - - :param node: Node which should be used - :type node: :class:`libcloud.compute.base.Node` - - :param kwargs: keyword arguments - :type kwargs: ``dict`` - - :rtype: ``bool`` - """ - valid_keys = ('^name$', '^parent$', '^cpu$', '^smp$', '^mem$', - '^boot$', '^nic:0:model$', '^nic:0:dhcp', - '^nic:1:model$', '^nic:1:vlan$', '^nic:1:mac$', - '^vnc:ip$', '^vnc:password$', '^vnc:tls', - '^ide:[0-1]:[0-1](:media)?$', '^scsi:0:[0-7](:media)?$', - '^block:[0-7](:media)?$') - - invalid_keys = [] - keys = list(kwargs.keys()) - for key in keys: - matches = False - for regex in valid_keys: - if re.match(regex, key): - matches = True - break - if not matches: - invalid_keys.append(key) - - if invalid_keys: - raise CloudSigmaException( - 'Invalid configuration key specified: %s' % - (',' .join(invalid_keys))) - - response = self.connection.request( - action='/servers/%s/set' % (node.id), - data=dict2str(kwargs), - method='POST') - - return (response.status == 200 and response.body != '') - - def ex_start_node(self, node): - """ - Start a node. - - :param node: Node which should be used - :type node: :class:`libcloud.compute.base.Node` - - :rtype: ``bool`` - """ - response = self.connection.request( - action='/servers/%s/start' % (node.id), - method='POST') - - return response.status == 200 - - def ex_stop_node(self, node): - """ - Stop (shutdown) a node. - - :param node: Node which should be used - :type node: :class:`libcloud.compute.base.Node` - - :rtype: ``bool`` - """ - response = self.connection.request( - action='/servers/%s/stop' % (node.id), - method='POST') - return response.status == 204 - - def ex_shutdown_node(self, node): - """ - Stop (shutdown) a node. - - @inherits: :class:`CloudSigmaBaseNodeDriver.ex_stop_node` - """ - return self.ex_stop_node(node) - - def ex_destroy_drive(self, drive_uuid): - """ - Destroy a drive. - - :param drive_uuid: Drive uuid which should be used - :type drive_uuid: ``str`` - - :rtype: ``bool`` - """ - response = self.connection.request( - action='/drives/%s/destroy' % (drive_uuid), - method='POST') - return response.status == 204 - - def _ex_connection_class_kwargs(self): - """ - Return the host value based on the user supplied region. - """ - kwargs = {} - if not self._host_argument_set: - kwargs['host'] = API_ENDPOINTS_1_0[self.region]['host'] - - return kwargs - - def _to_node(self, data): - if data: - try: - state = self.NODE_STATE_MAP[data['status']] - except KeyError: - state = NodeState.UNKNOWN - - if 'server' not in data: - # Response does not contain server UUID if the server - # creation failed because of insufficient funds. - return None - - public_ips = [] - if 'nic:0:dhcp' in data: - if isinstance(data['nic:0:dhcp'], list): - public_ips = data['nic:0:dhcp'] - else: - public_ips = [data['nic:0:dhcp']] - - extra = {} - extra_keys = [('cpu', 'int'), ('smp', 'auto'), ('mem', 'int'), - ('status', 'str')] - for key, value_type in extra_keys: - if key in data: - value = data[key] - - if value_type == 'int': - value = int(value) - elif value_type == 'auto': - try: - value = int(value) - except ValueError: - pass - - extra.update({key: value}) - - if 'vnc:ip' in data and 'vnc:password' in data: - extra.update({'vnc_ip': data['vnc:ip'], - 'vnc_password': data['vnc:password']}) - - node = Node(id=data['server'], name=data['name'], state=state, - public_ips=public_ips, private_ips=None, - driver=self.connection.driver, - extra=extra) - - return node - return None - - def _get_node(self, node_id): - nodes = self.list_nodes() - node = [node for node in nodes if node.id == node.id] - - if not node: - raise CloudSigmaException( - 'Node with id %s does not exist' % (node_id)) - - return node[0] - - def _get_node_info(self, node): - response = self.connection.request( - action='/servers/%s/info' % (node.id)) - - result = str2dicts(response.body) - return result[0] - - -class CloudSigmaZrhConnection(CloudSigma_1_0_Connection): - """ - Connection class for the CloudSigma driver for the Zurich end-point - """ - host = API_ENDPOINTS_1_0['zrh']['host'] - - -class CloudSigmaZrhNodeDriver(CloudSigma_1_0_NodeDriver): - """ - CloudSigma node driver for the Zurich end-point - """ - connectionCls = CloudSigmaZrhConnection - api_name = 'cloudsigma_zrh' - - -class CloudSigmaLvsConnection(CloudSigma_1_0_Connection): - """ - Connection class for the CloudSigma driver for the Las Vegas end-point - """ - host = API_ENDPOINTS_1_0['lvs']['host'] - - -class CloudSigmaLvsNodeDriver(CloudSigma_1_0_NodeDriver): - """ - CloudSigma node driver for the Las Vegas end-point - """ - connectionCls = CloudSigmaLvsConnection - api_name = 'cloudsigma_lvs' - - -class CloudSigmaError(ProviderError): - """ - Represents CloudSigma API error. - """ - - def __init__(self, http_code, error_type, error_msg, error_point, driver): - """ - :param http_code: HTTP status code. - :type http_code: ``int`` - - :param error_type: Type of error (validation / notexist / backend / - permissions database / concurrency / billing / - payment) - :type error_type: ``str`` - - :param error_msg: A description of the error that occurred. - :type error_msg: ``str`` - - :param error_point: Point at which the error occurred. Can be None. - :type error_point: ``str`` or ``None`` - """ - super(CloudSigmaError, self).__init__(http_code=http_code, - value=error_msg, driver=driver) - self.error_type = error_type - self.error_msg = error_msg - self.error_point = error_point - - -class CloudSigmaSubscription(object): - """ - Represents CloudSigma subscription. - """ - - def __init__(self, id, resource, amount, period, status, price, start_time, - end_time, auto_renew, subscribed_object=None): - """ - :param id: Subscription ID. - :type id: ``str`` - - :param resource: Resource (e.g vlan, ip, etc.). - :type resource: ``str`` - - :param period: Subscription period. - :type period: ``str`` - - :param status: Subscription status (active / inactive). - :type status: ``str`` - - :param price: Subscription price. - :type price: ``str`` - - :param start_time: Start time for this subscription. - :type start_time: ``datetime.datetime`` - - :param end_time: End time for this subscription. - :type end_time: ``datetime.datetime`` - - :param auto_renew: True if the subscription is auto renewed. - :type auto_renew: ``bool`` - - :param subscribed_object: Optional UUID of the subscribed object. - :type subscribed_object: ``str`` - """ - self.id = id - self.resource = resource - self.amount = amount - self.period = period - self.status = status - self.price = price - self.start_time = start_time - self.end_time = end_time - self.auto_renew = auto_renew - self.subscribed_object = subscribed_object - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return ('<CloudSigmaSubscription id=%s, resource=%s, amount=%s, ' - 'period=%s, object_uuid=%s>' % - (self.id, self.resource, self.amount, self.period, - self.subscribed_object)) - - -class CloudSigmaTag(object): - """ - Represents a CloudSigma tag object. - """ - - def __init__(self, id, name, resources=None): - """ - :param id: Tag ID. - :type id: ``str`` - - :param name: Tag name. - :type name: ``str`` - - :param resource: IDs of resources which are associated with this tag. - :type resources: ``list`` of ``str`` - """ - self.id = id - self.name = name - self.resources = resources if resources else [] - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return ('<CloudSigmaTag id=%s, name=%s, resources=%s>' % - (self.id, self.name, repr(self.resources))) - - -class CloudSigmaDrive(NodeImage): - """ - Represents a CloudSigma drive. - """ - - def __init__(self, id, name, size, media, status, driver, extra=None): - """ - :param id: Drive ID. - :type id: ``str`` - - :param name: Drive name. - :type name: ``str`` - - :param size: Drive size (in bytes). - :type size: ``int`` - - :param media: Drive media (cdrom / disk). - :type media: ``str`` - - :param status: Drive status (unmounted / mounted). - :type status: ``str`` - """ - super(CloudSigmaDrive, self).__init__(id=id, name=name, driver=driver, - extra=extra) - self.size = size - self.media = media - self.status = status - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return (('<CloudSigmaSize id=%s, name=%s size=%s, media=%s, ' - 'status=%s>') % - (self.id, self.name, self.size, self.media, self.status)) - - -class CloudSigmaFirewallPolicy(object): - """ - Represents a CloudSigma firewall policy. - """ - - def __init__(self, id, name, rules): - """ - :param id: Policy ID. - :type id: ``str`` - - :param name: Policy name. - :type name: ``str`` - - :param rules: Rules associated with this policy. - :type rules: ``list`` of :class:`.CloudSigmaFirewallPolicyRule` objects - """ - self.id = id - self.name = name - self.rules = rules if rules else [] - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return (('<CloudSigmaFirewallPolicy id=%s, name=%s rules=%s>') % - (self.id, self.name, repr(self.rules))) - - -class CloudSigmaFirewallPolicyRule(object): - """ - Represents a CloudSigma firewall policy rule. - """ - - def __init__(self, action, direction, ip_proto=None, src_ip=None, - src_port=None, dst_ip=None, dst_port=None, comment=None): - """ - :param action: Action (drop / accept). - :type action: ``str`` - - :param direction: Rule direction (in / out / both)> - :type direction: ``str`` - - :param ip_proto: IP protocol (tcp / udp). - :type ip_proto: ``str``. - - :param src_ip: Source IP in CIDR notation. - :type src_ip: ``str`` - - :param src_port: Source port or a port range. - :type src_port: ``str`` - - :param dst_ip: Destination IP in CIDR notation. - :type dst_ip: ``str`` - - :param src_port: Destination port or a port range. - :type src_port: ``str`` - - :param comment: Comment associated with the policy. - :type comment: ``str`` - """ - self.action = action - self.direction = direction - self.ip_proto = ip_proto - self.src_ip = src_ip - self.src_port = src_port - self.dst_ip = dst_ip - self.dst_port = dst_port - self.comment = comment - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return (('<CloudSigmaFirewallPolicyRule action=%s, direction=%s>') % - (self.action, self.direction)) - - -class CloudSigma_2_0_Response(JsonResponse): - success_status_codes = [ - httplib.OK, - httplib.ACCEPTED, - httplib.NO_CONTENT, - httplib.CREATED - ] - - def success(self): - return self.status in self.success_status_codes - - def parse_error(self): - if int(self.status) == httplib.UNAUTHORIZED: - raise InvalidCredsError('Invalid credentials') - - body = self.parse_body() - errors = self._parse_errors_from_body(body=body) - - if errors: - # Throw first error - raise errors[0] - - return body - - def _parse_errors_from_body(self, body): - """ - Parse errors from the response body. - - :return: List of error objects. - :rtype: ``list`` of :class:`.CloudSigmaError` objects - """ - errors = [] - - if not isinstance(body, list): - return None - - for item in body: - if 'error_type' not in item: - # Unrecognized error - continue - - error = CloudSigmaError(http_code=self.status, - error_type=item['error_type'], - error_msg=item['error_message'], - error_point=item['error_point'], - driver=self.connection.driver) - errors.append(error) - - return errors - - -class CloudSigma_2_0_Connection(ConnectionUserAndKey): - host = API_ENDPOINTS_2_0[DEFAULT_REGION]['host'] - responseCls = CloudSigma_2_0_Response - api_prefix = '/api/2.0' - - def add_default_headers(self, headers): - headers['Accept'] = 'application/json' - headers['Content-Type'] = 'application/json' - - headers['Authorization'] = 'Basic %s' % (base64.b64encode( - b('%s:%s' % (self.user_id, self.key))).decode('utf-8')) - return headers - - def encode_data(self, data): - data = json.dumps(data) - return data - - def request(self, action, params=None, data=None, headers=None, - method='GET', raw=False): - params = params or {} - action = self.api_prefix + action - - if method == 'GET': - params['limit'] = 0 # we want all the items back - - return super(CloudSigma_2_0_Connection, self).request(action=action, - params=params, - data=data, - headers=headers, - method=method, - raw=raw) - - -class CloudSigma_2_0_NodeDriver(CloudSigmaNodeDriver): - """ - Driver for CloudSigma API v2.0. - """ - name = 'CloudSigma (API v2.0)' - api_name = 'cloudsigma_zrh' - website = 'http://www.cloudsigma.com/' - connectionCls = CloudSigma_2_0_Connection - - # Default drive transition timeout in seconds - DRIVE_TRANSITION_TIMEOUT = 500 - - # How long to sleep between different polling periods while waiting for - # drive transition - DRIVE_TRANSITION_SLEEP_INTERVAL = 5 - - NODE_STATE_MAP = { - 'starting': NodeState.PENDING, - 'stopping': NodeState.PENDING, - 'unavailable': NodeState.PENDING, - 'running': NodeState.RUNNING, - 'stopped': NodeState.STOPPED, - 'paused': NodeState.STOPPED - } - - def __init__(self, key, secret, secure=True, host=None, port=None, - region=DEFAULT_REGION, **kwargs): - if region not in API_ENDPOINTS_2_0: - raise ValueError('Invalid region: %s' % (region)) - - if not secure: - # CloudSigma drive uses Basic Auth authentication and we don't want - # to allow user to accidentally send credentials over the wire in - # plain-text - raise ValueError('CloudSigma driver only supports a ' - 'secure connection') - - self._host_argument_set = host is not None - super(CloudSigma_2_0_NodeDriver, self).__init__(key=key, secret=secret, - secure=secure, - host=host, port=port, - region=region, - **kwargs) - - def list_nodes(self, ex_tag=None): - """ - List available nodes. - - :param ex_tag: If specified, only return servers tagged with the - provided tag. - :type ex_tag: :class:`CloudSigmaTag` - """ - if ex_tag: - action = '/tags/%s/servers/detail/' % (ex_tag.id) - else: - action = '/servers/detail/' - - response = self.connection.request(action=action, method='GET').object - nodes = [self._to_node(data=item) for item in response['objects']] - return nodes - - def list_sizes(self): - """ - List available sizes. - """ - sizes = [] - for value in INSTANCE_TYPES: - key = value['id'] - size = CloudSigmaNodeSize(id=value['id'], name=value['name'], - cpu=value['cpu'], ram=value['memory'], - disk=value['disk'], - bandwidth=value['bandwidth'], - price=self._get_size_price(size_id=key), - driver=self.connection.driver) - sizes.append(size) - - return sizes - - def list_images(self): - """ - Return a list of available pre-installed library drives. - - Note: If you want to list all the available library drives (both - pre-installed and installation CDs), use :meth:`ex_list_library_drives` - method. - """ - response = self.connection.request(action='/libdrives/').object - images = [self._to_image(data=item) for item in response['objects']] - - # We filter out non pre-installed library drives by default because - # they can't be used directly following a default Libcloud server - # creation flow. - images = [image for image in images if - image.extra['image_type'] == 'preinst'] - return images - - def create_node(self, name, size, image, ex_metadata=None, - ex_vnc_password=None, ex_avoid=None, ex_vlan=None): - """ - Create a new server. - - Server creation consists multiple steps depending on the type of the - image used. - - 1. Installation CD: - - 1. Create a server and attach installation cd - 2. Start a server - - 2. Pre-installed image: - - 1. Clone provided library drive so we can use it - 2. Resize cloned drive to the desired size - 3. Create a server and attach cloned drive - 4. Start a server - - :param ex_metadata: Key / value pairs to associate with the - created node. (optional) - :type ex_metadata: ``dict`` - - :param ex_vnc_password: Password to use for VNC access. If not - provided, random password is generated. - :type ex_vnc_password: ``str`` - - :param ex_avoid: A list of server UUIDs to avoid when starting this - node. (optional) - :type ex_avoid: ``list`` - - :param ex_vlan: Optional UUID of a VLAN network to use. If specified, - server will have two nics assigned - 1 with a public ip - and 1 with the provided VLAN. - :type ex_vlan: ``str`` - """ - is_installation_cd = self._is_installation_cd(image=image) - - if ex_vnc_password: - vnc_password = ex_vnc_password - else: - # VNC password is not provided, generate a random one. - vnc_password = get_secure_random_string(size=12) - - drive_name = '%s-drive' % (name) - - # size is specified in GB - drive_size = (size.disk * 1024 * 1024 * 1024) - - if not is_installation_cd: - # 1. Clone library drive so we can use it - drive = self.ex_clone_drive(drive=image, name=drive_name) - - # Wait for drive clone to finish - drive = self._wait_for_drive_state_transition(drive=drive, - state='unmounted') - - # 2. Resize drive to the desired disk size if the desired disk size - # is larger than the cloned drive size. - if drive_size > drive.size: - drive = self.ex_resize_drive(drive=drive, size=drive_size) - - # Wait for drive resize to finish - drive = self._wait_for_drive_state_transition(drive=drive, - state='unmounted') - else: - # No need to clone installation CDs - drive = image - - # 3. Create server and attach cloned drive - # ide 0:0 - data = {} - data['name'] = name - data['cpu'] = size.cpu - data['mem'] = (size.ram * 1024 * 1024) - data['vnc_password'] = vnc_password - - if ex_metadata: - data['meta'] = ex_metadata - - # Assign 1 public interface (DHCP) to the node - nic = { - 'boot_order': None, - 'ip_v4_conf': { - 'conf': 'dhcp', - }, - 'ip_v6_conf': None - } - - nics = [nic] - - if ex_vlan: - # Assign another interface for VLAN - nic = { - 'boot_order': None, - 'ip_v4_conf': None, - 'ip_v6_conf': None, - 'vlan': ex_vlan - } - nics.append(nic) - - # Need to use IDE for installation CDs - if is_installation_cd: - device_type = 'ide' - else: - device_type = 'virtio' - - drive = { - 'boot_order': 1, - 'dev_channel': '0:0', - 'device': device_type, - 'drive': drive.id - } - - drives = [drive] - - data['nics'] = nics - data['drives'] = drives - - action = '/servers/' - response = self.connection.request(action=action, method='POST', - data=data) - node = self._to_node(response.object['objects'][0]) - - # 4. Start server - self.ex_start_node(node=node, ex_avoid=ex_avoid) - - return node - - def destroy_node(self, node): - """ - Destroy the node and all the associated drives. - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - action = '/servers/%s/' % (node.id) - params = {'recurse': 'all_drives'} - response = self.connection.request(action=action, method='DELETE', - params=params) - return response.status == httplib.NO_CONTENT - - # Server extension methods - - def ex_edit_node(self, node, params): - """ - Edit a node. - - :param node: Node to edit. - :type node: :class:`libcloud.compute.base.Node` - - :param params: Node parameters to update. - :type params: ``dict`` - - :return Edited node. - :rtype: :class:`libcloud.compute.base.Node` - """ - data = {} - - # name, cpu, mem and vnc_password attributes must always be present so - # we just copy them from the to-be-edited node - data['name'] = node.name - data['cpu'] = node.extra['cpu'] - data['mem'] = node.extra['mem'] - data['vnc_password'] = node.extra['vnc_password'] - - nics = copy.deepcopy(node.extra.get('nics', [])) - - data['nics'] = nics - - data.update(params) - - action = '/servers/%s/' % (node.id) - response = self.connection.request(action=action, method='PUT', - data=data).object - node = self._to_node(data=response) - return node - - def ex_start_node(self, node, ex_avoid=None): - """ - Start a node. - - :param node: Node to start. - :type node: :class:`libcloud.compute.base.Node` - - :param ex_avoid: A list of other server uuids to avoid when - starting this node. If provided, node will - attempt to be started on a different - physical infrastructure from other servers - specified using this argument. (optional) - :type ex_avoid: ``list`` - """ - params = {} - - if ex_avoid: - params['avoid'] = ','.join(ex_avoid) - - path = '/servers/%s/action/' % (node.id) - response = self._perform_action(path=path, action='start', - params=params, - method='POST') - return response.status == httplib.ACCEPTED - - def ex_stop_node(self, node): - """ - Stop a node. - """ - path = '/servers/%s/action/' % (node.id) - response = self._perform_action(path=path, action='stop', - method='POST') - return response.status == httplib.ACCEPTED - - def ex_clone_node(self, node, name=None, random_vnc_password=None): - """ - Clone the provided node. - - :param name: Optional name for the cloned node. - :type name: ``str`` - :param random_vnc_password: If True, a new random VNC password will be - generated for the cloned node. Otherwise - password from the cloned node will be - reused. - :type random_vnc_password: ``bool`` - - :return: Cloned node. - :rtype: :class:`libcloud.compute.base.Node` - """ - data = {} - - data['name'] = name - data['random_vnc_password'] = random_vnc_password - - path = '/servers/%s/action/' % (node.id) - response = self._perform_action(path=path, action='clone', - method='POST', data=data).object - node = self._to_node(data=response) - return node - - def ex_open_vnc_tunnel(self, node): - """ - Open a VNC tunnel to the provided node and return the VNC url. - - :param node: Node to open the VNC tunnel to. - :type node: :class:`libcloud.compute.base.Node` - - :return: URL of the opened VNC tunnel. - :rtype: ``str`` - """ - path = '/servers/%s/action/' % (node.id) - response = self._perform_action(path=path, action='open_vnc', - method='POST').object - vnc_url = response['vnc_url'] - return vnc_url - - def ex_close_vnc_tunnel(self, node): - """ - Close a VNC server to the provided node. - - :param node: Node to close the VNC tunnel to. - :type node: :class:`libcloud.compute.base.Node` - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - path = '/servers/%s/action/' % (node.id) - response = self._perform_action(path=path, action='close_vnc', - method='POST') - return response.status == httplib.ACCEPTED - - # Drive extension methods - - def ex_list_library_drives(self): - """ - Return a list of all the available library drives (pre-installed and - installation CDs). - - :rtype: ``list`` of :class:`.CloudSigmaDrive` objects - """ - response = self.connection.request(action='/libdrives/').object - drives = [self._to_drive(data=item) for item in response['objects']] - return drives - - def ex_list_user_drives(self): - """ - Return a list of all the available user's drives. - - :rtype: ``list`` of :class:`.CloudSigmaDrive` objects - """ - response = self.connection.request(action='/drives/detail/').object - drives = [self._to_drive(data=item) for item in response['objects']] - return drives - - def ex_create_drive(self, name, size, media='disk', ex_avoid=None): - """ - Create a new drive. - - :param name: Drive name. - :type name: ``str`` - - :param size: Drive size in bytes. - :type size: ``int`` - - :param media: Drive media type (cdrom, disk). - :type media: ``str`` - - :param ex_avoid: A list of other drive uuids to avoid when - creating this drive. If provided, drive will - attempt to be created on a different - physical infrastructure from other drives - specified using this argument. (optional) - :type ex_avoid: ``list`` - - :return: Created drive object. - :rtype: :class:`.CloudSigmaDrive` - """ - params = {} - data = { - 'name': name, - 'size': size, - 'media': media - } - - if ex_avoid: - params['avoid'] = ','.join(ex_avoid) - - action = '/drives/' - response = self.connection.request(action=action, method='POST', - params=params, data=data).object - drive = self._to_drive(data=response['objects'][0]) - return drive - - def ex_clone_drive(self, drive, name=None, ex_avoid=None): - """ - Clone a library or a standard drive. - - :param drive: Drive to clone. - :type drive: :class:`libcloud.compute.base.NodeImage` or - :class:`.CloudSigmaDrive` - - :param name: Optional name for the cloned drive. - :type name: ``str`` - - :param ex_avoid: A list of other drive uuids to avoid when - creating this drive. If provided, drive will - attempt to be created on a different - physical infrastructure from other drives - specified using this argument. (optional) - :type ex_avoid: ``list`` - - :return: New cloned drive. - :rtype: :class:`.CloudSigmaDrive` - """ - params = {} - data = {} - - if ex_avoid: - params['avoid'] = ','.join(ex_avoid) - - if name: - data['name'] = name - - path = '/drives/%s/action/' % (drive.id) - response = self._perform_action(path=path, action='clone', - params=params, data=data, - method='POST') - drive = self._to_drive(data=response.object['objects'][0]) - return drive - - def ex_resize_drive(self, drive, size): - """ - Resize a drive. - - :param drive: Drive to resize. - - :param size: New drive size in bytes. - :type size: ``int`` - - :return: Drive object which is being resized. - :rtype: :class:`.CloudSigmaDrive` - """ - path = '/drives/%s/action/' % (drive.id) - data = {'name': drive.name, 'size': size, 'media': 'disk'} - response = self._perform_action(path=path, action='resize', - method='POST', data=data) - - drive = self._to_drive(data=response.object['objects'][0]) - return drive - - def ex_attach_drive(self, node): - """ - Attach a drive to the provided node. - """ - # TODO - pass - - def ex_get_drive(self, drive_id): - """ - Retrieve information about a single drive. - - :param drive_id: ID of the drive to retrieve. - :type drive_id: ``str`` - - :return: Drive object. - :rtype: :class:`.CloudSigmaDrive` - """ - action = '/drives/%s/' % (drive_id) - response = self.connection.request(action=action).object - drive = self._to_drive(data=response) - return drive - - # Firewall policies extension methods - - def ex_list_firewall_policies(self): - """ - List firewall policies. - - :rtype: ``list`` of :class:`.CloudSigmaFirewallPolicy` - """ - action = '/fwpolicies/detail/' - response = self.connection.request(action=action, method='GET').object - policies = [self._to_firewall_policy(data=item) for item - in response['objects']] - return policies - - def ex_create_firewall_policy(self, name, rules=None): - """ - Create a firewall policy. - - :param name: Policy name. - :type name: ``str`` - - :param rules: List of firewall policy rules to associate with this - policy. (optional) - :type rules: ``list`` of ``dict`` - - :return: Created firewall policy object. - :rtype: :class:`.CloudSigmaFirewallPolicy` - """ - data = {} - obj = {} - obj['name'] = name - - if rules: - obj['rules'] = rules - - data['objects'] = [obj] - - action = '/fwpolicies/' - response = self.connection.request(action=action, method='POST', - data=data).object - policy = self._to_firewall_policy(data=response['objects'][0]) - return policy - - def ex_attach_firewall_policy(self, policy, node, nic_mac=None): - """ - Attach firewall policy to a public NIC interface on the server. - - :param policy: Firewall policy to attach. - :type policy: :class:`.CloudSigmaFirewallPolicy` - - :param node: Node to attach policy to. - :type node: :class:`libcloud.compute.base.Node` - - :param nic_mac: Optional MAC address of the NIC to add the policy to. - If not specified, first public interface is used - instead. - :type nic_mac: ``str`` - - :return: Node object to which the policy was attached to. - :rtype: :class:`libcloud.compute.base.Node` - """ - nics = copy.deepcopy(node.extra.get('nics', [])) - - if nic_mac: - nic = [n for n in nics if n['mac'] == nic_mac] - else: - nic = nics - - if len(nic) == 0: - raise ValueError('Cannot find the NIC interface to attach ' - 'a policy to') - - nic = nic[0] - nic['firewall_policy'] = policy.id - - params = {'nics': nics} - node = self.ex_edit_node(node=node, params=params) - return node - - def ex_delete_firewall_policy(self, policy): - """ - Delete a firewall policy. - - :param policy: Policy to delete to. - :type policy: :class:`.CloudSigmaFirewallPolicy` - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - action = '/fwpolicies/%s/' % (policy.id) - response = self.connection.request(action=action, method='DELETE') - return response.status == httplib.NO_CONTENT - - # Availability groups extension methods - - def ex_list_servers_availability_groups(self): - """ - Return which running servers share the same physical compute host. - - :return: A list of server UUIDs which share the same physical compute - host. Servers which share the same host will be stored under - the same list index. - :rtype: ``list`` of ``list`` - """ - action = '/servers/availability_groups/' - response = self.connection.request(action=action, method='GET') - return response.object - - def ex_list_drives_availability_groups(self): - """ - Return which drives share the same physical storage host. - - :return: A list of drive UUIDs which share the same physical storage - host. Drives which share the same host will be stored under - the same list index. - :rtype: ``list`` of ``list`` - """ - action = '/drives/availability_groups/' - response = self.connection.request(action=action, method='GET') - return response.object - - # Tag extension methods - - def ex_list_tags(self): - """ - List all the available tags. - - :rtype: ``list`` of :class:`.CloudSigmaTag` objects - """ - action = '/tags/detail/' - response = self.connection.request(action=action, method='GET').object - tags = [self._to_tag(data=item) for item in response['objects']] - - return tags - - def ex_get_tag(self, tag_id): - """ - Retrieve a single tag. - - :param tag_id: ID of the tag to retrieve. - :type tag_id: ``str`` - - :rtype: ``list`` of :class:`.CloudSigmaTag` objects - """ - action = '/tags/%s/' % (tag_id) - response = self.connection.request(action=action, method='GET').object - tag = self._to_tag(data=response) - return tag - - def ex_create_tag(self, name, resource_uuids=None): - """ - Create a tag. - - :param name: Tag name. - :type name: ``str`` - - :param resource_uuids: Optional list of resource UUIDs to assign this - tag go. - :type resource_uuids: ``list`` of ``str`` - - :return: Created tag object. - :rtype: :class:`.CloudSigmaTag` - """ - data = {} - data['objects'] = [ - { - 'name': name - } - ] - - if resource_uuids: - data['resources'] = resource_uuids - - action = '/tags/' - response = self.connection.request(action=action, method='POST', - data=data).object - tag = self._to_tag(data=response['objects'][0]) - return tag - - def ex_tag_resource(self, resource, tag): - """ - Associate tag with the provided resource. - - :param resource: Resource to associate a tag with. - :type resource: :class:`libcloud.compute.base.Node` or - :class:`.CloudSigmaDrive` - - :param tag: Tag to associate with the resources. - :type tag: :class:`.CloudSigmaTag` - - :return: Updated tag object. - :rtype: :class:`.CloudSigmaTag` - """ - if not hasattr(resource, 'id'): - raise ValueError('Resource doesn\'t have id attribute') - - return self.ex_tag_resources(resources=[resource], tag=tag) - - def ex_tag_resources(self, resources, tag): - """ - Associate tag with the provided resources. - - :param resources: Resources to associate a tag with. - :type resources: ``list`` of :class:`libcloud.compute.base.Node` or - :class:`.CloudSigmaDrive` - - :param tag: Tag to associate with the resources. - :type tag: :class:`.CloudSigmaTag` - - :return: Updated tag object. - :rtype: :class:`.CloudSigmaTag` - """ - - resources = tag.resources[:] - - for resource in resources: - if not hasattr(resource, 'id'): - raise ValueError('Resource doesn\'t have id attribute') - - resources.append(resource.id) - - resources = list(set(resources)) - - data = { - 'name': tag.name, - 'resources': resources - } - - action = '/tags/%s/' % (tag.id) - response = self.connection.request(action=action, method='PUT', - data=data).object - tag = self._to_tag(data=response) - return tag - - def ex_delete_tag(self, tag): - """ - Delete a tag. - - :param tag: Tag to delete. - :type tag: :class:`.CloudSigmaTag` - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - action = '/tags/%s/' % (tag.id) - response = self.connection.request(action=action, method='DELETE') - return response.status == httplib.NO_CONTENT - - # Account extension methods - - def ex_get_balance(self): - """ - Retrueve account balance information. - - :return: Dictionary with two items ("balance" and "currency"). - :rtype: ``dict`` - """ - action = '/balance/' - response = self.connection.request(action=action, method='GET') - return response.object - - def ex_get_pricing(self): - """ - Retrive pricing information that are applicable to the cloud. - - :return: Dictionary with pricing information. - :rtype: ``dict`` - """ - action = '/pricing/' - response = self.connection.request(action=action, method='GET') - return response.object - - def ex_get_usage(self): - """ - Retrieve account current usage information. - - :return: Dictionary with two items ("balance" and "usage"). - :rtype: ``dict`` - """ - action = '/currentusage/' - response = self.connection.request(action=action, method='GET') - return response.object - - def ex_list_subscriptions(self, status='all', resources=None): - """ - List subscriptions for this account. - - :param status: Only return subscriptions with the provided status - (optional). - :type status: ``str`` - :param resources: Only return subscriptions for the provided resources - (optional). - :type resources: ``list`` - - :rtype: ``list`` - """ - params = {} - - if status: - params['status'] = status - - if resources: - params['resource'] = ','.join(resources) - - response = self.connection.request(action='/subscriptions/', - params=params).object - subscriptions = self._to_subscriptions(data=response) - return subscriptions - - def ex_toggle_subscription_auto_renew(self, subscription): - """ - Toggle subscription auto renew status. - - :param subscription: Subscription to toggle the auto renew flag for. - :type subscription: :class:`.CloudSigmaSubscription` - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - path = '/subscriptions/%s/action/' % (subscription.id) - response = self._perform_action(path=path, action='auto_renew', - method='POST') - return response.status == httplib.OK - - def ex_create_subscription(self, amount, period, resource, - auto_renew=False): - """ - Create a new subscription. - - :param amount: Subscription amount. For example, in dssd case this - would be disk size in gigabytes. - :type amount: ``int`` - - :param period: Subscription period. For example: 30 days, 1 week, 1 - month, ... - :type period: ``str`` - - :param resource: Resource the purchase the subscription for. - :type resource: ``str`` - - :param auto_renew: True to automatically renew the subscription. - :type auto_renew: ``bool`` - """ - data = [ - { - 'amount': amount, - 'period': period, - 'auto_renew': auto_renew, - 'resource': resource - } - ] - - response = self.connection.request(action='/subscriptions/', - data=data, method='POST') - data = response.object['objects'][0] - subscription = self._to_subscription(data=data) - return subscription - - # Misc extension methods - - def ex_list_capabilities(self): - """ - Retrieve all the basic and sensible limits of the API. - - :rtype: ``dict`` - """ - action = '/capabilities/' - response = self.connection.request(action=action, - method='GET') - capabilities = response.object - return capabilities - - def _parse_ips_from_nic(self, nic): - """ - Parse private and public IP addresses from the provided network - interface object. - - :param nic: NIC object. - :type nic: ``dict`` - - :return: (public_ips, private_ips) tuple. - :rtype: ``tuple`` - """ - public_ips, private_ips = [], [] - - ipv4_conf = nic['ip_v4_conf'] - ipv6_conf = nic['ip_v6_conf'] - - ipv4 = ipv4_conf['ip'] if ipv4_conf else None - ipv6 = ipv6_conf['ip'] if ipv6_conf else None - - ips = [] - - if ipv4: - ips.append(ipv4) - - if ipv6: - ips.append(ipv6) - - runtime = nic['runtime'] - - ip_v4 = runtime['ip_v4'] if nic['runtime'] else None - ip_v6 = runtime['ip_v6'] if nic['runtime'] else None - - ipv4 = ip_v4['uuid'] if ip_v4 else None - ipv6 = ip_v4['uuid'] if ip_v6 else None - - if ipv4: - ips.append(ipv4) - - if ipv6: - ips.append(ipv6) - - ips = set(ips) - - for ip in ips: - if is_private_subnet(ip): - private_ips.append(ip) - else: - public_ips.append(ip) - - return public_ips, private_ips - - def _to_node(self, data): - extra_keys = ['cpu', 'mem', 'nics', 'vnc_password', 'meta'] - - id = data['uuid'] - name = data['name'] - state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN) - - public_ips = [] - private_ips = [] - extra = self._extract_values(obj=data, keys=extra_keys) - - for nic in data['nics']: - _public_ips, _private_ips = self._parse_ips_from_nic(nic=nic) - - public_ips.extend(_public_ips) - private_ips.extend(_private_ips) - - node = Node(id=id, name=name, state=state, public_ips=public_ips, - private_ips=private_ips, driver=self, extra=extra) - return node - - def _to_image(self, data): - extra_keys = ['description', 'arch', 'image_type', 'os', 'licenses', - 'media', 'meta'] - - id = data['uuid'] - name = data['name'] - extra = self._extract_values(obj=data, keys=extra_keys) - - image = NodeImage(id=id, name=name, driver=self, extra=extra) - return image - - def _to_drive(self, data): - id = data['uuid'] - name = data['name'] - size = data['size'] - media = data['media'] - status = data['status'] - extra = {} - - drive = CloudSigmaDrive(id=id, name=name, size=size, media=media, - status=status, driver=self, extra=extra) - - return drive - - def _to_tag(self, data): - resources = data['resources'] - resources = [resource['uuid'] for resource in resources] - - tag = CloudSigmaTag(id=data['uuid'], name=data['name'], - resources=resources) - return tag - - def _to_subscriptions(self, data): - subscriptions = [] - - for item in data['objects']: - subscription = self._to_subscription(data=item) - subscriptions.append(subscription) - - return subscriptions - - def _to_subscription(self, data): - start_time = parse_date(data['start_time']) - end_time = parse_date(data['end_time']) - obj_uuid = data['subscribed_object'] - - subscription = CloudSigmaSubscription(id=data['id'], - resource=data['resource'], - amount=int(data['amount']), - period=data['period'], - status=data['status'], - price=data['price'], - start_time=start_time, - end_time=end_time, - auto_renew=data['auto_renew'], - subscribed_object=obj_uuid) - return subscription - - def _to_firewall_policy(self, data): - rules = [] - - for item in data.get('rules', []): - rule = CloudSigmaFirewallPolicyRule(action=item['action'], - direction=item['direction'], - ip_proto=item['ip_proto'], - src_ip=item['src_ip'], - src_port=item['src_port'], - dst_ip=item['dst_ip'], - dst_port=item['dst_port'], - comment=item['comment']) - rules.append(rule) - - policy = CloudSigmaFirewallPolicy(id=data['uuid'], name=data['name'], - rules=rules) - return policy - - def _perform_action(self, path, action, method='POST', params=None, - data=None): - """ - Perform API action and return response object. - """ - if params: - params = params.copy() - else: - params = {} - - params['do'] = action - response = self.connection.request(action=path, method=method, - params=params, data=data) - return response - - def _is_installation_cd(self, image): - """ - Detect if the provided image is an installation CD. - - :rtype: ``bool`` - """ - if isinstance(image, CloudSigmaDrive) and image.media == 'cdrom': - return True - - return False - - def _extract_values(self, obj, keys): - """ - Extract values from a dictionary and return a new dictionary with - extracted values. - - :param obj: Dictionary to extract values from. - :type obj: ``dict`` - - :param keys: Keys to extract. - :type keys: ``list`` - - :return: Dictionary with extracted values. - :rtype: ``dict`` - """ - result = {} - - for key in keys: - result[key] = obj[key] - - return result - - def _wait_for_drive_state_transition(self, drive, state, - timeout=DRIVE_TRANSITION_TIMEOUT): - """ - Wait for a drive to transition to the provided state. - - Note: This function blocks and periodically calls "GET drive" endpoint - to check if the drive has already transitioned to the desired state. - - :param drive: Drive to wait for. - :type drive: :class:`.CloudSigmaDrive` - - :param state: Desired drive state. - :type state: ``str`` - - :param timeout: How long to wait for the transition (in seconds) before - timing out. - :type timeout: ``int`` - - :return: Drive object. - :rtype: :class:`.CloudSigmaDrive` - """ - - start_time = time.time() - - while drive.status != state: - drive = self.ex_get_drive(drive_id=drive.id) - - if drive.status == state: - break - - current_time = time.time() - delta = (current_time - start_time) - - if delta >= timeout: - msg = ('Timed out while waiting for drive transition ' - '(timeout=%s seconds)' % (timeout)) - raise Exception(msg) - - time.sleep(self.DRIVE_TRANSITION_SLEEP_INTERVAL) - - return drive - - def _ex_connection_class_kwargs(self): - """ - Return the host value based on the user supplied region. - """ - kwargs = {} - - if not self._host_argument_set: - kwargs['host'] = API_ENDPOINTS_2_0[self.region]['host'] - - return kwargs diff --git a/awx/lib/site-packages/libcloud/compute/drivers/cloudstack.py b/awx/lib/site-packages/libcloud/compute/drivers/cloudstack.py deleted file mode 100644 index 089e3f08b3..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/cloudstack.py +++ /dev/null @@ -1,2208 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import base64 -import warnings - -from libcloud.utils.py3 import b -from libcloud.utils.py3 import urlparse - -from libcloud.compute.providers import Provider -from libcloud.common.cloudstack import CloudStackDriverMixIn -from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation -from libcloud.compute.base import NodeSize, StorageVolume -from libcloud.compute.base import KeyPair -from libcloud.compute.types import NodeState, LibcloudError -from libcloud.compute.types import KeyPairDoesNotExistError -from libcloud.utils.networking import is_private_subnet - - -""" -Define the extra dictionary for specific resources -""" -RESOURCE_EXTRA_ATTRIBUTES_MAP = { - 'network': { - 'broadcast_domain_type': { - 'key_name': 'broadcastdomaintype', - 'transform_func': str - }, - 'traffic_type': { - 'key_name': 'traffictype', - 'transform_func': str - }, - 'zone_name': { - 'key_name': 'zonename', - 'transform_func': str - }, - 'network_offering_name': { - 'key_name': 'networkofferingname', - 'transform_func': str - }, - 'network_offeringdisplay_text': { - 'key_name': 'networkofferingdisplaytext', - 'transform_func': str - }, - 'network_offering_availability': { - 'key_name': 'networkofferingavailability', - 'transform_func': str - }, - 'is_system': { - 'key_name': 'issystem', - 'transform_func': str - }, - 'state': { - 'key_name': 'state', - 'transform_func': str - }, - 'dns1': { - 'key_name': 'dns1', - 'transform_func': str - }, - 'dns2': { - 'key_name': 'dns2', - 'transform_func': str - }, - 'type': { - 'key_name': 'type', - 'transform_func': str - }, - 'acl_type': { - 'key_name': 'acltype', - 'transform_func': str - }, - 'subdomain_access': { - 'key_name': 'subdomainaccess', - 'transform_func': str - }, - 'network_domain': { - 'key_name': 'networkdomain', - 'transform_func': str - }, - 'physical_network_id': { - 'key_name': 'physicalnetworkid', - 'transform_func': str - }, - 'can_use_for_deploy': { - 'key_name': 'canusefordeploy', - 'transform_func': str - }, - 'gateway': { - 'key_name': 'gateway', - 'transform_func': str - }, - 'netmask': { - 'key_name': 'netmask', - 'transform_func': str - }, - 'vpc_id': { - 'key_name': 'vpcid', - 'transform_func': str - }, - 'project_id': { - 'key_name': 'projectid', - 'transform_func': str - } - }, - 'node': { - 'haenable': { - 'key_name': 'haenable', - 'transform_func': str - }, - 'zone_id': { - 'key_name': 'zoneid', - 'transform_func': str - }, - 'zone_name': { - 'key_name': 'zonename', - 'transform_func': str - }, - 'key_name': { - 'key_name': 'keypair', - 'transform_func': str - }, - 'password': { - 'key_name': 'password', - 'transform_func': str - }, - 'image_id': { - 'key_name': 'templateid', - 'transform_func': str - }, - 'image_name': { - 'key_name': 'templatename', - 'transform_func': str - }, - 'template_display_text': { - 'key_name': 'templatdisplaytext', - 'transform_func': str - }, - 'password_enabled': { - 'key_name': 'passwordenabled', - 'transform_func': str - }, - 'size_id': { - 'key_name': 'serviceofferingid', - 'transform_func': str - }, - 'size_name': { - 'key_name': 'serviceofferingname', - 'transform_func': str - }, - 'root_device_id': { - 'key_name': 'rootdeviceid', - 'transform_func': str - }, - 'root_device_type': { - 'key_name': 'rootdevicetype', - 'transform_func': str - }, - 'hypervisor': { - 'key_name': 'hypervisor', - 'transform_func': str - }, - 'project': { - 'key_name': 'project', - 'transform_func': str - }, - 'project_id': { - 'key_name': 'projectid', - 'transform_func': str - } - }, - 'volume': { - 'created': { - 'key_name': 'created', - 'transform_func': str - }, - 'device_id': { - 'key_name': 'deviceid', - 'transform_func': int - }, - 'instance_id': { - 'key_name': 'serviceofferingid', - 'transform_func': str - }, - 'state': { - 'key_name': 'state', - 'transform_func': str - }, - 'volume_type': { - 'key_name': 'type', - 'transform_func': str - }, - 'zone_id': { - 'key_name': 'zoneid', - 'transform_func': str - }, - 'zone_name': { - 'key_name': 'zonename', - 'transform_func': str - } - }, - 'project': { - 'account': {'key_name': 'account', 'transform_func': str}, - 'cpuavailable': {'key_name': 'cpuavailable', 'transform_func': int}, - 'cpulimit': {'key_name': 'cpulimit', 'transform_func': int}, - 'cputotal': {'key_name': 'cputotal', 'transform_func': int}, - 'domain': {'key_name': 'domain', 'transform_func': str}, - 'domainid': {'key_name': 'domainid', 'transform_func': str}, - 'ipavailable': {'key_name': 'ipavailable', 'transform_func': int}, - 'iplimit': {'key_name': 'iplimit', 'transform_func': int}, - 'iptotal': {'key_name': 'iptotal', 'transform_func': int}, - 'memoryavailable': {'key_name': 'memoryavailable', - 'transform_func': int}, - 'memorylimit': {'key_name': 'memorylimit', 'transform_func': int}, - 'memorytotal': {'key_name': 'memorytotal', 'transform_func': int}, - 'networkavailable': {'key_name': 'networkavailable', - 'transform_func': int}, - 'networklimit': {'key_name': 'networklimit', 'transform_func': int}, - 'networktotal': {'key_name': 'networktotal', 'transform_func': int}, - 'primarystorageavailable': {'key_name': 'primarystorageavailable', - 'transform_func': int}, - 'primarystoragelimit': {'key_name': 'primarystoragelimit', - 'transform_func': int}, - 'primarystoragetotal': {'key_name': 'primarystoragetotal', - 'transform_func': int}, - 'secondarystorageavailable': {'key_name': 'secondarystorageavailable', - 'transform_func': int}, - 'secondarystoragelimit': {'key_name': 'secondarystoragelimit', - 'transform_func': int}, - 'secondarystoragetotal': {'key_name': 'secondarystoragetotal', - 'transform_func': int}, - 'snapshotavailable': {'key_name': 'snapshotavailable', - 'transform_func': int}, - 'snapshotlimit': {'key_name': 'snapshotlimit', 'transform_func': int}, - 'snapshottotal': {'key_name': 'snapshottotal', 'transform_func': int}, - 'state': {'key_name': 'state', 'transform_func': str}, - 'tags': {'key_name': 'tags', 'transform_func': str}, - 'templateavailable': {'key_name': 'templateavailable', - 'transform_func': int}, - 'templatelimit': {'key_name': 'templatelimit', 'transform_func': int}, - 'templatetotal': {'key_name': 'templatetotal', 'transform_func': int}, - 'vmavailable': {'key_name': 'vmavailable', 'transform_func': int}, - 'vmlimit': {'key_name': 'vmlimit', 'transform_func': int}, - 'vmrunning': {'key_name': 'vmrunning', 'transform_func': int}, - 'vmtotal': {'key_name': 'vmtotal', 'transform_func': int}, - 'volumeavailable': {'key_name': 'volumeavailable', - 'transform_func': int}, - 'volumelimit': {'key_name': 'volumelimit', 'transform_func': int}, - 'volumetotal': {'key_name': 'volumetotal', 'transform_func': int}, - 'vpcavailable': {'key_name': 'vpcavailable', 'transform_func': int}, - 'vpclimit': {'key_name': 'vpclimit', 'transform_func': int}, - 'vpctotal': {'key_name': 'vpctotal', 'transform_func': int} - } -} - - -class CloudStackNode(Node): - """ - Subclass of Node so we can expose our extension methods. - """ - - def ex_allocate_public_ip(self): - """ - Allocate a public IP and bind it to this node. - """ - return self.driver.ex_allocate_public_ip(self) - - def ex_release_public_ip(self, address): - """ - Release a public IP that this node holds. - """ - return self.driver.ex_release_public_ip(self, address) - - def ex_create_ip_forwarding_rule(self, address, protocol, - start_port, end_port=None): - """ - Add a NAT/firewall forwarding rule for a port or ports. - """ - return self.driver.ex_create_ip_forwarding_rule(node=self, - address=address, - protocol=protocol, - start_port=start_port, - end_port=end_port) - - def ex_create_port_forwarding_rule(self, address, - private_port, public_port, - protocol, - public_end_port=None, - private_end_port=None, - openfirewall=True): - """ - Add a port forwarding rule for port or ports. - """ - return self.driver.ex_create_port_forwarding_rule( - node=self, address=address, private_port=private_port, - public_port=public_port, protocol=protocol, - public_end_port=public_end_port, private_end_port=private_end_port, - openfirewall=openfirewall) - - def ex_delete_ip_forwarding_rule(self, rule): - """ - Delete a port forwarding rule. - """ - return self.driver.ex_delete_ip_forwarding_rule(node=self, rule=rule) - - def ex_delete_port_forwarding_rule(self, rule): - """ - Delete a NAT/firewall rule. - """ - return self.driver.ex_delete_port_forwarding_rule(node=self, rule=rule) - - def ex_start(self): - """ - Starts a stopped virtual machine. - """ - return self.driver.ex_start(node=self) - - def ex_stop(self): - """ - Stops a running virtual machine. - """ - return self.driver.ex_stop(node=self) - - -class CloudStackAddress(object): - """ - A public IP address. - - :param id: UUID of the Public IP - :type id: ``str`` - - :param address: The public IP address - :type address: ``str`` - - :param associated_network_id: The ID of the network where this address - has been associated with - :type associated_network_id: ``str`` - """ - - def __init__(self, id, address, driver, associated_network_id=None): - self.id = id - self.address = address - self.driver = driver - self.associated_network_id = associated_network_id - - def release(self): - self.driver.ex_release_public_ip(address=self) - - def __str__(self): - return self.address - - def __eq__(self, other): - return self.__class__ is other.__class__ and self.id == other.id - - -class CloudStackIPForwardingRule(object): - """ - A NAT/firewall forwarding rule. - """ - - def __init__(self, node, id, address, protocol, start_port, end_port=None): - self.node = node - self.id = id - self.address = address - self.protocol = protocol - self.start_port = start_port - self.end_port = end_port - - def delete(self): - self.node.ex_delete_ip_forwarding_rule(rule=self) - - def __eq__(self, other): - return self.__class__ is other.__class__ and self.id == other.id - - -class CloudStackPortForwardingRule(object): - """ - A Port forwarding rule for Source NAT. - """ - - def __init__(self, node, rule_id, address, protocol, public_port, - private_port, public_end_port=None, private_end_port=None): - """ - A Port forwarding rule for Source NAT. - - @note: This is a non-standard extension API, and only works for EC2. - - :param node: Node for rule - :type node: :class:`Node` - - :param rule_id: Rule ID - :type rule_id: ``int`` - - :param address: External IP address - :type address: :class:`CloudStackAddress` - - :param protocol: TCP/IP Protocol (TCP, UDP) - :type protocol: ``str`` - - :param public_port: External port for rule (or start port if - public_end_port is also provided) - :type public_port: ``int`` - - :param private_port: Internal node port for rule (or start port if - public_end_port is also provided) - :type private_port: ``int`` - - :param public_end_port: End of external port range - :type public_end_port: ``int`` - - :param private_end_port: End of internal port range - :type private_end_port: ``int`` - - :rtype: :class:`CloudStackPortForwardingRule` - """ - self.node = node - self.id = rule_id - self.address = address - self.protocol = protocol - self.public_port = public_port - self.public_end_port = public_end_port - self.private_port = private_port - self.private_end_port = private_end_port - - def delete(self): - self.node.ex_delete_port_forwarding_rule(rule=self) - - def __eq__(self, other): - return self.__class__ is other.__class__ and self.id == other.id - - -class CloudStackDiskOffering(object): - """ - A disk offering within CloudStack. - """ - - def __init__(self, id, name, size, customizable): - self.id = id - self.name = name - self.size = size - self.customizable = customizable - - def __eq__(self, other): - return self.__class__ is other.__class__ and self.id == other.id - - -class CloudStackNetwork(object): - """ - Class representing a CloudStack Network. - """ - - def __init__(self, displaytext, name, networkofferingid, id, zoneid, - driver, extra=None): - self.displaytext = displaytext - self.name = name - self.networkofferingid = networkofferingid - self.id = id - self.zoneid = zoneid - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return (('<CloudStackNetwork: id=%s, displaytext=%s, name=%s, ' - 'networkofferingid=%s, zoneid=%s, driver%s>') - % (self.id, self.displaytext, self.name, - self.networkofferingid, self.zoneid, self.driver.name)) - - -class CloudStackNetworkOffering(object): - """ - Class representing a CloudStack Network Offering. - """ - - def __init__(self, name, display_text, guest_ip_type, id, - service_offering_id, for_vpc, driver, extra=None): - self.display_text = display_text - self.name = name - self.guest_ip_type = guest_ip_type - self.id = id - self.service_offering_id = service_offering_id - self.for_vpc = for_vpc - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return (('<CloudStackNetworkOffering: id=%s, name=%s, ' - 'display_text=%s, guest_ip_type=%s, service_offering_id=%s, ' - 'for_vpc=%s, driver%s>') - % (self.id, self.name, self.display_text, - self.guest_ip_type, self.service_offering_id, self.for_vpc, - self.driver.name)) - - -class CloudStackProject(object): - """ - Class representing a CloudStack Project. - """ - - def __init__(self, id, name, display_text, driver, extra=None): - self.id = id - self.name = name - self.display_text = display_text - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return (('<CloudStackProject: id=%s, display_text=%s, name=%s, ' - 'driver=%s>') - % (self.id, self.display_text, self.name, - self.driver.name)) - - -class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver): - """ - Driver for the CloudStack API. - - :cvar host: The host where the API can be reached. - :cvar path: The path where the API can be reached. - :cvar async_poll_frequency: How often (in seconds) to poll for async - job completion. - :type async_poll_frequency: ``int``""" - - name = 'CloudStack' - api_name = 'cloudstack' - website = 'http://cloudstack.org/' - type = Provider.CLOUDSTACK - - features = {'create_node': ['generates_password']} - - NODE_STATE_MAP = { - 'Running': NodeState.RUNNING, - 'Starting': NodeState.REBOOTING, - 'Stopped': NodeState.STOPPED, - 'Stopping': NodeState.PENDING, - 'Destroyed': NodeState.TERMINATED, - 'Expunging': NodeState.PENDING, - 'Error': NodeState.TERMINATED - } - - def __init__(self, key, secret=None, secure=True, host=None, - path=None, port=None, url=None, *args, **kwargs): - """ - :inherits: :class:`NodeDriver.__init__` - - :param host: The host where the API can be reached. (required) - :type host: ``str`` - - :param path: The path where the API can be reached. (required) - :type path: ``str`` - - :param url: Full URL to the API endpoint. Mutually exclusive with host - and path argument. - :type url: ``str`` - """ - if url: - parsed = urlparse.urlparse(url) - - path = parsed.path - - scheme = parsed.scheme - split = parsed.netloc.split(':') - - if len(split) == 1: - # No port provided, use the default one - host = parsed.netloc - port = 443 if scheme == 'https' else 80 - else: - host = split[0] - port = int(split[1]) - else: - host = host if host else self.host - path = path if path else self.path - - if path is not None: - self.path = path - - if host is not None: - self.host = host - - if (self.type == Provider.CLOUDSTACK) and (not host or not path): - raise Exception('When instantiating CloudStack driver directly ' - 'you also need to provide url or host and path ' - 'argument') - - super(CloudStackNodeDriver, self).__init__(key=key, - secret=secret, - secure=secure, - host=host, - port=port) - - def list_images(self, location=None): - args = { - 'templatefilter': 'executable' - } - if location is not None: - args['zoneid'] = location.id - imgs = self._sync_request(command='listTemplates', - params=args, - method='GET') - images = [] - for img in imgs.get('template', []): - images.append(NodeImage( - id=img['id'], - name=img['name'], - driver=self.connection.driver, - extra={ - 'hypervisor': img['hypervisor'], - 'format': img['format'], - 'os': img['ostypename'], - 'displaytext': img['displaytext']})) - return images - - def list_locations(self): - """ - :rtype ``list`` of :class:`NodeLocation` - """ - locs = self._sync_request('listZones') - - locations = [] - for loc in locs['zone']: - location = NodeLocation(str(loc['id']), loc['name'], 'Unknown', - self) - locations.append(location) - - return locations - - def list_nodes(self, project=None): - """ - @inherits: :class:`NodeDriver.list_nodes` - - :keyword project: Limit nodes returned to those configured under - the defined project. - :type project: :class:`.CloudStackProject` - - :rtype: ``list`` of :class:`CloudStackNode` - """ - - args = {} - if project: - args['projectid'] = project.id - vms = self._sync_request('listVirtualMachines', params=args) - addrs = self._sync_request('listPublicIpAddresses', params=args) - - public_ips_map = {} - for addr in addrs.get('publicipaddress', []): - if 'virtualmachineid' not in addr: - continue - vm_id = str(addr['virtualmachineid']) - if vm_id not in public_ips_map: - public_ips_map[vm_id] = {} - public_ips_map[vm_id][addr['ipaddress']] = addr['id'] - - nodes = [] - - for vm in vms.get('virtualmachine', []): - public_ips = public_ips_map.get(str(vm['id']), {}).keys() - public_ips = list(public_ips) - node = self._to_node(data=vm, public_ips=public_ips) - - addresses = public_ips_map.get(vm['id'], {}).items() - addresses = [CloudStackAddress(node, v, k) for k, v in addresses] - node.extra['ip_addresses'] = addresses - - rules = [] - for addr in addresses: - result = self._sync_request('listIpForwardingRules') - for r in result.get('ipforwardingrule', []): - if str(r['virtualmachineid']) == node.id: - rule = CloudStackIPForwardingRule(node, r['id'], - addr, - r['protocol'] - .upper(), - r['startport'], - r['endport']) - rules.append(rule) - node.extra['ip_forwarding_rules'] = rules - - rules = [] - public_ips = self.ex_list_public_ips() - result = self._sync_request('listPortForwardingRules') - for r in result.get('portforwardingrule', []): - if str(r['virtualmachineid']) == node.id: - addr = [a for a in public_ips if - a.address == r['ipaddress']] - rule = CloudStackPortForwardingRule(node, r['id'], - addr[0], - r['protocol'].upper(), - r['publicport'], - r['privateport'], - r['publicendport'], - r['privateendport']) - if not addr[0].address in node.public_ips: - node.public_ips.append(addr[0].address) - rules.append(rule) - node.extra['port_forwarding_rules'] = rules - - nodes.append(node) - - return nodes - - def list_sizes(self, location=None): - """ - :rtype ``list`` of :class:`NodeSize` - """ - szs = self._sync_request(command='listServiceOfferings', - method='GET') - sizes = [] - for sz in szs['serviceoffering']: - extra = {'cpu': sz['cpunumber']} - sizes.append(NodeSize(sz['id'], sz['name'], sz['memory'], 0, 0, - 0, self, extra=extra)) - return sizes - - def create_node(self, **kwargs): - """ - Create a new node - - @inherits: :class:`NodeDriver.create_node` - - :keyword networks: Optional list of networks to launch the server - into. - :type networks: ``list`` of :class:`.CloudStackNetwork` - - :keyword project: Optional project to create the new node under. - :type project: :class:`.CloudStackProject` - - :keyword diskoffering: Optional disk offering to add to the new - node. - :type diskoffering: :class:`.CloudStackDiskOffering` - - :keyword ex_keyname: Name of existing keypair - :type ex_keyname: ``str`` - - :keyword ex_userdata: String containing user data - :type ex_userdata: ``str`` - - :keyword ex_security_groups: List of security groups to assign to - the node - :type ex_security_groups: ``list`` of ``str`` - - :keyword ex_displayname: String containing instance display name - :type ex_displayname: ``str`` - - :rtype: :class:`.CloudStackNode` - """ - - server_params = self._create_args_to_params(None, **kwargs) - - data = self._async_request(command='deployVirtualMachine', - params=server_params, - method='GET')['virtualmachine'] - node = self._to_node(data=data) - return node - - def _create_args_to_params(self, node, **kwargs): - server_params = {} - - # TODO: Refactor and use "kwarg_to_server_params" map - name = kwargs.get('name', None) - size = kwargs.get('size', None) - image = kwargs.get('image', None) - location = kwargs.get('location', None) - networks = kwargs.get('networks', None) - project = kwargs.get('project', None) - diskoffering = kwargs.get('diskoffering', None) - ex_key_name = kwargs.get('ex_keyname', None) - ex_user_data = kwargs.get('ex_userdata', None) - ex_security_groups = kwargs.get('ex_security_groups', None) - ex_displayname = kwargs.get('ex_displayname', None) - - if name: - server_params['name'] = name - - if ex_displayname: - server_params['displayname'] = ex_displayname - - if size: - server_params['serviceofferingid'] = size.id - - if image: - server_params['templateid'] = image.id - - if location: - server_params['zoneid'] = location.id - else: - # Use a default location - server_params['zoneid'] = self.list_locations()[0].id - - if networks: - networks = ','.join([network.id for network in networks]) - server_params['networkids'] = networks - - if project: - server_params['projectid'] = project.id - - if diskoffering: - server_params['diskofferingid'] = diskoffering.id - - if ex_key_name: - server_params['keypair'] = ex_key_name - - if ex_user_data: - ex_user_data = base64.b64encode(b(ex_user_data).decode('ascii')) - server_params['userdata'] = ex_user_data - - if ex_security_groups: - ex_security_groups = ','.join(ex_security_groups) - server_params['securitygroupnames'] = ex_security_groups - - return server_params - - def destroy_node(self, node): - """ - @inherits: :class:`NodeDriver.reboot_node` - :type node: :class:`CloudStackNode` - - :rtype: ``bool`` - """ - self._async_request(command='destroyVirtualMachine', - params={'id': node.id}, - method='GET') - return True - - def reboot_node(self, node): - """ - @inherits: :class:`NodeDriver.reboot_node` - :type node: :class:`CloudStackNode` - - :rtype: ``bool`` - """ - self._async_request(command='rebootVirtualMachine', - params={'id': node.id}, - method='GET') - return True - - def ex_start(self, node): - """ - Starts/Resumes a stopped virtual machine - - :type node: :class:`CloudStackNode` - - :param id: The ID of the virtual machine (required) - :type id: ``str`` - - :param hostid: destination Host ID to deploy the VM to - parameter available for root admin only - :type hostid: ``str`` - - :rtype ``str`` - """ - res = self._async_request(command='startVirtualMachine', - params={'id': node.id}, - method='GET') - return res['virtualmachine']['state'] - - def ex_stop(self, node): - """ - Stops/Suspends a running virtual machine - - :param node: Node to stop. - :type node: :class:`CloudStackNode` - - :rtype: ``str`` - """ - res = self._async_request(command='stopVirtualMachine', - params={'id': node.id}, - method='GET') - return res['virtualmachine']['state'] - - def ex_list_disk_offerings(self): - """ - Fetch a list of all available disk offerings. - - :rtype: ``list`` of :class:`CloudStackDiskOffering` - """ - - diskOfferings = [] - - diskOfferResponse = self._sync_request(command='listDiskOfferings', - method='GET') - for diskOfferDict in diskOfferResponse.get('diskoffering', ()): - diskOfferings.append( - CloudStackDiskOffering( - id=diskOfferDict['id'], - name=diskOfferDict['name'], - size=diskOfferDict['disksize'], - customizable=diskOfferDict['iscustomized'])) - - return diskOfferings - - def ex_list_networks(self): - """ - List the available networks - - :rtype ``list`` of :class:`CloudStackNetwork` - """ - - res = self._sync_request(command='listNetworks', - method='GET') - nets = res.get('network', []) - - networks = [] - extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['network'] - for net in nets: - extra = self._get_extra_dict(net, extra_map) - - if 'tags' in net: - extra['tags'] = self._get_resource_tags(net['tags']) - - networks.append(CloudStackNetwork( - net['displaytext'], - net['name'], - net['networkofferingid'], - net['id'], - net['zoneid'], - self, - extra=extra)) - - return networks - - def ex_list_network_offerings(self): - """ - List the available network offerings - - :rtype ``list`` of :class:`CloudStackNetworkOffering` - """ - res = self._sync_request(command='listNetworkOfferings', - method='GET') - netoffers = res.get('networkoffering', []) - - networkofferings = [] - - for netoffer in netoffers: - networkofferings.append(CloudStackNetworkOffering( - netoffer['name'], - netoffer['displaytext'], - netoffer['guestiptype'], - netoffer['id'], - netoffer['serviceofferingid'], - netoffer['forvpc'], - self)) - - return networkofferings - - def ex_create_network(self, display_text, name, network_offering, - location, gateway=None, netmask=None, - network_domain=None, vpc_id=None, project_id=None): - """ - - Creates a Network, only available in advanced zones. - - :param display_text: the display text of the network - :type display_text: ``str`` - - :param name: the name of the network - :type name: ``str`` - - :param network_offering: the network offering id - :type network_offering: :class:'CloudStackNetworkOffering` - - :param location: Zone - :type location: :class:`NodeLocation` - - :param gateway: Optional, the Gateway of this network - :type gateway: ``str`` - - :param netmask: Optional, the netmask of this network - :type netmask: ``str`` - - :param network_domain: Optional, the DNS domain of the network - :type network_domain: ``str`` - - :param vpc_id: Optional, the VPC id the network belongs to - :type vpc_id: ``str`` - - :param project_id: Optional, the project id the networks belongs to - :type project_id: ``str`` - - :rtype: :class:`CloudStackNetwork` - - """ - - extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['network'] - - args = { - 'displaytext': display_text, - 'name': name, - 'networkofferingid': network_offering.id, - 'zoneid': location.id, - } - - if gateway is not None: - args['gateway'] = gateway - - if netmask is not None: - args['netmask'] = netmask - - if network_domain is not None: - args['networkdomain'] = network_domain - - if vpc_id is not None: - args['vpcid'] = vpc_id - - if project_id is not None: - args['projectid'] = project_id - - """ Cloudstack allows for duplicate network names, - this should be handled in the code leveraging libcloud - As there could be use cases for duplicate names. - e.g. management from ROOT level""" - - # for net in self.ex_list_networks(): - # if name == net.name: - # raise LibcloudError('This network name already exists') - - result = self._sync_request(command='createNetwork', - params=args, - method='GET') - - result = result['network'] - extra = self._get_extra_dict(result, extra_map) - - network = CloudStackNetwork(display_text, - name, - network_offering.id, - result['id'], - location.id, - self, - extra=extra) - - return network - - def ex_delete_network(self, network, force=None): - """ - - Deletes a Network, only available in advanced zones. - - :param network: The network - :type network: :class: 'CloudStackNetwork' - - :param force: Force deletion of the network? - :type force: ``bool`` - - :rtype: ``bool`` - - """ - - args = {'id': network.id, 'forced': force} - - self._async_request(command='deleteNetwork', - params=args, - method='GET') - return True - - def ex_list_projects(self): - """ - List the available projects - - :rtype ``list`` of :class:`CloudStackProject` - """ - - res = self._sync_request(command='listProjects', - method='GET') - projs = res.get('project', []) - - projects = [] - extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['project'] - for proj in projs: - extra = self._get_extra_dict(proj, extra_map) - - if 'tags' in proj: - extra['tags'] = self._get_resource_tags(proj['tags']) - - projects.append(CloudStackProject( - id=proj['id'], - name=proj['name'], - display_text=proj['displaytext'], - driver=self, - extra=extra)) - - return projects - - def create_volume(self, size, name, location=None, snapshot=None): - """ - Creates a data volume - Defaults to the first location - """ - for diskOffering in self.ex_list_disk_offerings(): - if diskOffering.size == size or diskOffering.customizable: - break - else: - raise LibcloudError( - 'Disk offering with size=%s not found' % size) - - if location is None: - location = self.list_locations()[0] - - params = {'name': name, - 'diskOfferingId': diskOffering.id, - 'zoneId': location.id} - - if diskOffering.customizable: - params['size'] = size - - requestResult = self._async_request(command='createVolume', - params=params, - method='GET') - - volumeResponse = requestResult['volume'] - - return StorageVolume(id=volumeResponse['id'], - name=name, - size=size, - driver=self, - extra=dict(name=volumeResponse['name'])) - - def destroy_volume(self, volume): - """ - :rtype: ``bool`` - """ - self._sync_request(command='deleteVolume', - params={'id': volume.id}, - method='GET') - return True - - def attach_volume(self, node, volume, device=None): - """ - @inherits: :class:`NodeDriver.attach_volume` - :type node: :class:`CloudStackNode` - - :rtype: ``bool`` - """ - # TODO Add handling for device name - self._async_request(command='attachVolume', - params={'id': volume.id, - 'virtualMachineId': node.id}, - method='GET') - return True - - def detach_volume(self, volume): - """ - :rtype: ``bool`` - """ - self._async_request(command='detachVolume', - params={'id': volume.id}, - method='GET') - return True - - def list_volumes(self, node=None): - """ - List all volumes - - :param node: Only return volumes for the provided node. - :type node: :class:`CloudStackNode` - - :rtype: ``list`` of :class:`StorageVolume` - """ - if node: - volumes = self._sync_request(command='listVolumes', - params={'virtualmachineid': node.id}, - method='GET') - else: - volumes = self._sync_request(command='listVolumes', - method='GET') - - list_volumes = [] - extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['volume'] - for vol in volumes['volume']: - extra = self._get_extra_dict(vol, extra_map) - - if 'tags' in vol: - extra['tags'] = self._get_resource_tags(vol['tags']) - - list_volumes.append(StorageVolume(id=vol['id'], - name=vol['name'], - size=vol['size'], - driver=self, - extra=extra)) - return list_volumes - - def list_key_pairs(self, **kwargs): - """ - List registered key pairs. - - :param projectid: list objects by project - :type projectid: ``str`` - - :param page: The page to list the keypairs from - :type page: ``int`` - - :param keyword: List by keyword - :type keyword: ``str`` - - :param listall: If set to false, list only resources - belonging to the command's caller; - if set to true - list resources that - the caller is authorized to see. - Default value is false - - :type listall: ``bool`` - - :param pagesize: The number of results per page - :type pagesize: ``int`` - - :param account: List resources by account. - Must be used with the domainId parameter - :type account: ``str`` - - :param isrecursive: Defaults to false, but if true, - lists all resources from - the parent specified by the - domainId till leaves. - :type isrecursive: ``bool`` - - :param fingerprint: A public key fingerprint to look for - :type fingerprint: ``str`` - - :param name: A key pair name to look for - :type name: ``str`` - - :param domainid: List only resources belonging to - the domain specified - :type domainid: ``str`` - - :return: A list of key par objects. - :rtype: ``list`` of :class:`libcloud.compute.base.KeyPair` - """ - extra_args = kwargs.copy() - res = self._sync_request(command='listSSHKeyPairs', - params=extra_args, - method='GET') - key_pairs = res.get('sshkeypair', []) - key_pairs = self._to_key_pairs(data=key_pairs) - return key_pairs - - def get_key_pair(self, name): - params = {'name': name} - res = self._sync_request(command='listSSHKeyPairs', - params=params, - method='GET') - key_pairs = res.get('sshkeypair', []) - - if len(key_pairs) == 0: - raise KeyPairDoesNotExistError(name=name, driver=self) - - key_pair = self._to_key_pair(data=key_pairs[0]) - return key_pair - - def create_key_pair(self, name, **kwargs): - """ - Create a new key pair object. - - :param name: Key pair name. - :type name: ``str`` - - :param name: Name of the keypair (required) - :type name: ``str`` - - :param projectid: An optional project for the ssh key - :type projectid: ``str`` - - :param domainid: An optional domainId for the ssh key. - If the account parameter is used, - domainId must also be used. - :type domainid: ``str`` - - :param account: An optional account for the ssh key. - Must be used with domainId. - :type account: ``str`` - - :return: Created key pair object. - :rtype: :class:`libcloud.compute.base.KeyPair` - """ - extra_args = kwargs.copy() - - params = {'name': name} - params.update(extra_args) - - res = self._sync_request(command='createSSHKeyPair', - params=params, - method='GET') - key_pair = self._to_key_pair(data=res['keypair']) - return key_pair - - def import_key_pair_from_string(self, name, key_material): - """ - Import a new public key from string. - - :param name: Key pair name. - :type name: ``str`` - - :param key_material: Public key material. - :type key_material: ``str`` - - :return: Imported key pair object. - :rtype: :class:`libcloud.compute.base.KeyPair` - """ - res = self._sync_request(command='registerSSHKeyPair', - params={'name': name, - 'publickey': key_material}, - method='GET') - key_pair = self._to_key_pair(data=res['keypair']) - return key_pair - - def delete_key_pair(self, key_pair, **kwargs): - """ - Delete an existing key pair. - - :param key_pair: Key pair object. - :type key_pair: :class`libcloud.compute.base.KeyPair` - - :param projectid: The project associated with keypair - :type projectid: ``str`` - - :param domainid: The domain ID associated with the keypair - :type domainid: ``str`` - - :param account: The account associated with the keypair. - Must be used with the domainId parameter. - :type account: ``str`` - - :return: True of False based on success of Keypair deletion - :rtype: ``bool`` - """ - - extra_args = kwargs.copy() - params = {'name': key_pair.name} - params.update(extra_args) - - res = self._sync_request(command='deleteSSHKeyPair', - params=params, - method='GET') - return res['success'] == 'true' - - def ex_list_public_ips(self): - """ - Lists all Public IP Addresses. - - :rtype: ``list`` of :class:`CloudStackAddress` - """ - ips = [] - - res = self._sync_request(command='listPublicIpAddresses', - method='GET') - - # Workaround for basic zones - if not res: - return ips - - for ip in res['publicipaddress']: - ips.append(CloudStackAddress(ip['id'], - ip['ipaddress'], - self, - ip['associatednetworkid'])) - return ips - - def ex_allocate_public_ip(self, location=None): - """ - Allocate a public IP. - - :param location: Zone - :type location: :class:`NodeLocation` - - :rtype: :class:`CloudStackAddress` - """ - if location is None: - location = self.list_locations()[0] - - addr = self._async_request(command='associateIpAddress', - params={'zoneid': location.id}, - method='GET') - addr = addr['ipaddress'] - addr = CloudStackAddress(addr['id'], addr['ipaddress'], self) - return addr - - def ex_release_public_ip(self, address): - """ - Release a public IP. - - :param address: CloudStackAddress which should be used - :type address: :class:`CloudStackAddress` - - :rtype: ``bool`` - """ - res = self._async_request(command='disassociateIpAddress', - params={'id': address.id}, - method='GET') - return res['success'] - - def ex_list_port_forwarding_rules(self): - """ - Lists all Port Forwarding Rules - - :rtype: ``list`` of :class:`CloudStackPortForwardingRule` - """ - rules = [] - result = self._sync_request(command='listPortForwardingRules', - method='GET') - if result != {}: - public_ips = self.ex_list_public_ips() - nodes = self.list_nodes() - for rule in result['portforwardingrule']: - node = [n for n in nodes - if n.id == str(rule['virtualmachineid'])] - addr = [a for a in public_ips if - a.address == rule['ipaddress']] - rules.append(CloudStackPortForwardingRule - (node[0], - rule['id'], - addr[0], - rule['protocol'], - rule['publicport'], - rule['privateport'], - rule['publicendport'], - rule['privateendport'])) - - return rules - - def ex_create_port_forwarding_rule(self, node, address, - private_port, public_port, - protocol, - public_end_port=None, - private_end_port=None, - openfirewall=True): - """ - Creates a Port Forwarding Rule, used for Source NAT - - :param address: IP address of the Source NAT - :type address: :class:`CloudStackAddress` - - :param private_port: Port of the virtual machine - :type private_port: ``int`` - - :param protocol: Protocol of the rule - :type protocol: ``str`` - - :param public_port: Public port on the Source NAT address - :type public_port: ``int`` - - :param node: The virtual machine - :type node: :class:`CloudStackNode` - - :rtype: :class:`CloudStackPortForwardingRule` - """ - args = { - 'ipaddressid': address.id, - 'protocol': protocol, - 'privateport': int(private_port), - 'publicport': int(public_port), - 'virtualmachineid': node.id, - 'openfirewall': openfirewall - } - if public_end_port: - args['publicendport'] = int(public_end_port) - if private_end_port: - args['privateendport'] = int(private_end_port) - - result = self._async_request(command='createPortForwardingRule', - params=args, - method='GET') - rule = CloudStackPortForwardingRule(node, - result['portforwardingrule'] - ['id'], - address, - protocol, - public_port, - private_port, - public_end_port, - private_end_port) - node.extra['port_forwarding_rules'].append(rule) - node.public_ips.append(address.address) - return rule - - def ex_delete_port_forwarding_rule(self, node, rule): - """ - Remove a Port forwarding rule. - - :param node: Node used in the rule - :type node: :class:`CloudStackNode` - - :param rule: Forwarding rule which should be used - :type rule: :class:`CloudStackPortForwardingRule` - - :rtype: ``bool`` - """ - - node.extra['port_forwarding_rules'].remove(rule) - node.public_ips.remove(rule.address.address) - res = self._async_request(command='deletePortForwardingRule', - params={'id': rule.id}, - method='GET') - return res['success'] - - def ex_create_ip_forwarding_rule(self, node, address, protocol, - start_port, end_port=None): - """ - "Add a NAT/firewall forwarding rule. - - :param node: Node which should be used - :type node: :class:`CloudStackNode` - - :param address: CloudStackAddress which should be used - :type address: :class:`CloudStackAddress` - - :param protocol: Protocol which should be used (TCP or UDP) - :type protocol: ``str`` - - :param start_port: Start port which should be used - :type start_port: ``int`` - - :param end_port: End port which should be used - :type end_port: ``int`` - - :rtype: :class:`CloudStackForwardingRule` - """ - - protocol = protocol.upper() - if protocol not in ('TCP', 'UDP'): - return None - - args = { - 'ipaddressid': address.id, - 'protocol': protocol, - 'startport': int(start_port) - } - if end_port is not None: - args['endport'] = int(end_port) - - result = self._async_request(command='createIpForwardingRule', - params=args, - method='GET') - result = result['ipforwardingrule'] - rule = CloudStackIPForwardingRule(node, result['id'], address, - protocol, start_port, end_port) - node.extra['ip_forwarding_rules'].append(rule) - return rule - - def ex_delete_ip_forwarding_rule(self, node, rule): - """ - Remove a NAT/firewall forwarding rule. - - :param node: Node which should be used - :type node: :class:`CloudStackNode` - - :param rule: Forwarding rule which should be used - :type rule: :class:`CloudStackForwardingRule` - - :rtype: ``bool`` - """ - - node.extra['ip_forwarding_rules'].remove(rule) - self._async_request(command='deleteIpForwardingRule', - params={'id': rule.id}, - method='GET') - return True - - def ex_list_keypairs(self, **kwargs): - """ - List Registered SSH Key Pairs - - :param projectid: list objects by project - :type projectid: ``str`` - - :param page: The page to list the keypairs from - :type page: ``int`` - - :param keyword: List by keyword - :type keyword: ``str`` - - :param listall: If set to false, list only resources - belonging to the command's caller; - if set to true - list resources that - the caller is authorized to see. - Default value is false - - :type listall: ``bool`` - - :param pagesize: The number of results per page - :type pagesize: ``int`` - - :param account: List resources by account. - Must be used with the domainId parameter - :type account: ``str`` - - :param isrecursive: Defaults to false, but if true, - lists all resources from - the parent specified by the - domainId till leaves. - :type isrecursive: ``bool`` - - :param fingerprint: A public key fingerprint to look for - :type fingerprint: ``str`` - - :param name: A key pair name to look for - :type name: ``str`` - - :param domainid: List only resources belonging to - the domain specified - :type domainid: ``str`` - - :return: A list of keypair dictionaries - :rtype: ``list`` of ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'list_key_pairs method') - - key_pairs = self.list_key_pairs(**kwargs) - - result = [] - - for key_pair in key_pairs: - item = { - 'name': key_pair.name, - 'fingerprint': key_pair.fingerprint, - 'privateKey': key_pair.private_key - } - result.append(item) - - return result - - def ex_create_keypair(self, name, **kwargs): - """ - Creates a SSH KeyPair, returns fingerprint and private key - - :param name: Name of the keypair (required) - :type name: ``str`` - - :param projectid: An optional project for the ssh key - :type projectid: ``str`` - - :param domainid: An optional domainId for the ssh key. - If the account parameter is used, - domainId must also be used. - :type domainid: ``str`` - - :param account: An optional account for the ssh key. - Must be used with domainId. - :type account: ``str`` - - :return: A keypair dictionary - :rtype: ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'create_key_pair method') - - key_pair = self.create_key_pair(name=name, **kwargs) - - result = { - 'name': key_pair.name, - 'fingerprint': key_pair.fingerprint, - 'privateKey': key_pair.private_key - } - - return result - - def ex_import_keypair_from_string(self, name, key_material): - """ - Imports a new public key where the public key is passed in as a string - - :param name: The name of the public key to import. - :type name: ``str`` - - :param key_material: The contents of a public key file. - :type key_material: ``str`` - - :rtype: ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'import_key_pair_from_string method') - - key_pair = self.import_key_pair_from_string(name=name, - key_material=key_material) - result = { - 'keyName': key_pair.name, - 'keyFingerprint': key_pair.fingerprint - } - - return result - - def ex_import_keypair(self, name, keyfile): - """ - Imports a new public key where the public key is passed via a filename - - :param name: The name of the public key to import. - :type name: ``str`` - - :param keyfile: The filename with path of the public key to import. - :type keyfile: ``str`` - - :rtype: ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'import_key_pair_from_file method') - - key_pair = self.import_key_pair_from_file(name=name, - key_file_path=keyfile) - result = { - 'keyName': key_pair.name, - 'keyFingerprint': key_pair.fingerprint - } - - return result - - def ex_delete_keypair(self, keypair, **kwargs): - """ - Deletes an existing SSH KeyPair - - :param keypair: Name of the keypair (required) - :type keypair: ``str`` - - :param projectid: The project associated with keypair - :type projectid: ``str`` - - :param domainid: The domain ID associated with the keypair - :type domainid: ``str`` - - :param account: The account associated with the keypair. - Must be used with the domainId parameter. - :type account: ``str`` - - :return: True of False based on success of Keypair deletion - :rtype: ``bool`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'delete_key_pair method') - - key_pair = KeyPair(name=keypair, public_key=None, fingerprint=None, - driver=self) - - return self.delete_key_pair(key_pair=key_pair) - - def ex_list_security_groups(self, **kwargs): - """ - Lists Security Groups - - :param domainid: List only resources belonging to the domain specified - :type domainid: ``str`` - - :param account: List resources by account. Must be used with - the domainId parameter. - :type account: ``str`` - - :param listall: If set to false, list only resources belonging to - the command's caller; if set to true - list resources that the caller is - authorized to see. - Default value is false - :type listall: ``bool`` - - :param pagesize: Number of entries per page - :type pagesize: ``int`` - - :param keyword: List by keyword - :type keyword: ``str`` - - :param tags: List resources by tags (key/value pairs) - :type tags: ``dict`` - - :param id: list the security group by the id provided - :type id: ``str`` - - :param securitygroupname: lists security groups by name - :type securitygroupname: ``str`` - - :param virtualmachineid: lists security groups by virtual machine id - :type virtualmachineid: ``str`` - - :param projectid: list objects by project - :type projectid: ``str`` - - :param isrecursive: (boolean) defaults to false, but if true, - lists all resources from the parent - specified by the domainId till leaves. - :type isrecursive: ``bool`` - - :param page: (integer) - :type page: ``int`` - - :rtype ``list`` - """ - extra_args = kwargs.copy() - res = self._sync_request(command='listSecurityGroups', - params=extra_args, - method='GET') - - security_groups = res.get('securitygroup', []) - return security_groups - - def ex_create_security_group(self, name, **kwargs): - """ - Creates a new Security Group - - :param name: name of the security group (required) - :type name: ``str`` - - :param account: An optional account for the security group. - Must be used with domainId. - :type account: ``str`` - - :param domainid: An optional domainId for the security group. - If the account parameter is used, - domainId must also be used. - :type domainid: ``str`` - - :param description: The description of the security group - :type description: ``str`` - - :param projectid: Deploy vm for the project - :type projectid: ``str`` - - :rtype: ``dict`` - """ - - extra_args = kwargs.copy() - - for sg in self.ex_list_security_groups(): - if name in sg['name']: - raise LibcloudError('This Security Group name already exists') - - params = {'name': name} - params.update(extra_args) - - return self._sync_request(command='createSecurityGroup', - params=params, - method='GET')['securitygroup'] - - def ex_delete_security_group(self, name): - """ - Deletes a given Security Group - - :param domainid: The domain ID of account owning - the security group - :type domainid: ``str`` - - :param id: The ID of the security group. - Mutually exclusive with name parameter - :type id: ``str`` - - :param name: The ID of the security group. - Mutually exclusive with id parameter - :type name: ``str`` - - :param account: The account of the security group. - Must be specified with domain ID - :type account: ``str`` - - :param projectid: The project of the security group - :type projectid: ``str`` - - :rtype: ``bool`` - """ - - return self._sync_request(command='deleteSecurityGroup', - params={'name': name}, - method='GET')['success'] - - def ex_authorize_security_group_ingress(self, securitygroupname, - protocol, cidrlist, startport, - endport=None): - """ - Creates a new Security Group Ingress rule - - :param domainid: An optional domainId for the security group. - If the account parameter is used, - domainId must also be used. - :type domainid: ``str`` - - :param startport: Start port for this ingress rule - :type startport: ``int`` - - :param securitygroupid: The ID of the security group. - Mutually exclusive with securityGroupName - parameter - :type securitygroupid: ``str`` - - :param cidrlist: The cidr list associated - :type cidrlist: ``list`` - - :param usersecuritygrouplist: user to security group mapping - :type usersecuritygrouplist: ``dict`` - - :param securitygroupname: The name of the security group. - Mutually exclusive with - securityGroupName parameter - :type securitygroupname: ``str`` - - :param account: An optional account for the security group. - Must be used with domainId. - :type account: ``str`` - - :param icmpcode: Error code for this icmp message - :type icmpcode: ``int`` - - :param protocol: TCP is default. UDP is the other supported protocol - :type protocol: ``str`` - - :param icmptype: type of the icmp message being sent - :type icmptype: ``int`` - - :param projectid: An optional project of the security group - :type projectid: ``str`` - - :param endport: end port for this ingress rule - :type endport: ``int`` - - :rtype: ``list`` - """ - - protocol = protocol.upper() - if protocol not in ('TCP', 'ICMP'): - raise LibcloudError('Only TCP and ICMP are allowed') - - args = { - 'securitygroupname': securitygroupname, - 'protocol': protocol, - 'startport': int(startport), - 'cidrlist': cidrlist - } - if endport is None: - args['endport'] = int(startport) - - return self._async_request(command='authorizeSecurityGroupIngress', - params=args, - method='GET')['securitygroup'] - - def ex_revoke_security_group_ingress(self, rule_id): - """ - Revoke/delete an ingress security rule - - :param id: The ID of the ingress security rule - :type id: ``str`` - - :rtype: ``bool`` - """ - - self._async_request(command='revokeSecurityGroupIngress', - params={'id': rule_id}, - method='GET') - return True - - def ex_register_iso(self, name, url, location=None, **kwargs): - """ - Registers an existing ISO by URL. - - :param name: Name which should be used - :type name: ``str`` - - :param url: Url should be used - :type url: ``str`` - - :param location: Location which should be used - :type location: :class:`NodeLocation` - - :rtype: ``str`` - """ - if location is None: - location = self.list_locations()[0] - - params = {'name': name, - 'displaytext': name, - 'url': url, - 'zoneid': location.id} - params['bootable'] = kwargs.pop('bootable', False) - if params['bootable']: - os_type_id = kwargs.pop('ostypeid', None) - - if not os_type_id: - raise LibcloudError('If bootable=True, ostypeid is required!') - - params['ostypeid'] = os_type_id - - return self._sync_request(command='registerIso', - name=name, - displaytext=name, - url=url, - zoneid=location.id, - params=params) - - def ex_limits(self): - """ - Extra call to get account's resource limits, such as - the amount of instances, volumes, snapshots and networks. - - CloudStack uses integers as the resource type so we will convert - them to a more human readable string using the resource map - - A list of the resource type mappings can be found at - http://goo.gl/17C6Gk - - :return: dict - :rtype: ``dict`` - """ - - result = self._sync_request(command='listResourceLimits', - method='GET') - - limits = {} - resource_map = { - 0: 'max_instances', - 1: 'max_public_ips', - 2: 'max_volumes', - 3: 'max_snapshots', - 4: 'max_images', - 5: 'max_projects', - 6: 'max_networks', - 7: 'max_vpc', - 8: 'max_cpu', - 9: 'max_memory', - 10: 'max_primary_storage', - 11: 'max_secondary_storage' - } - - for limit in result.get('resourcelimit', []): - # We will ignore unknown types - resource = resource_map.get(int(limit['resourcetype']), None) - if not resource: - continue - limits[resource] = int(limit['max']) - - return limits - - def ex_create_tags(self, resource_ids, resource_type, tags): - """ - Create tags for a resource (Node/StorageVolume/etc). - A list of resource types can be found at http://goo.gl/6OKphH - - :param resource_ids: Resource IDs to be tagged. The resource IDs must - all be associated with the resource_type. - For example, for virtual machines (UserVm) you - can only specify a list of virtual machine IDs. - :type resource_ids: ``list`` of resource IDs - - :param resource_type: Resource type (eg: UserVm) - :type resource_type: ``str`` - - :param tags: A dictionary or other mapping of strings to strings, - associating tag names with tag values. - :type tags: ``dict`` - - :rtype: ``bool`` - """ - params = {'resourcetype': resource_type, - 'resourceids': ','.join(resource_ids)} - - for i, key in enumerate(tags): - params['tags[%d].key' % i] = key - params['tags[%d].value' % i] = tags[key] - - self._async_request(command='createTags', - params=params, - method='GET') - return True - - def ex_delete_tags(self, resource_ids, resource_type, tag_keys): - """ - Delete tags from a resource. - - :param resource_ids: Resource IDs to be tagged. The resource IDs must - all be associated with the resource_type. - For example, for virtual machines (UserVm) you - can only specify a list of virtual machine IDs. - :type resource_ids: ``list`` of resource IDs - - :param resource_type: Resource type (eg: UserVm) - :type resource_type: ``str`` - - :param tag_keys: A list of keys to delete. CloudStack only requires - the keys from the key/value pair. - :type tag_keys: ``list`` - - :rtype: ``bool`` - """ - params = {'resourcetype': resource_type, - 'resourceids': ','.join(resource_ids)} - - for i, key in enumerate(tag_keys): - params['tags[%s].key' % i] = key - - self._async_request(command='deleteTags', - params=params, - method='GET') - - return True - - def _to_node(self, data, public_ips=None): - """ - :param data: Node data object. - :type data: ``dict`` - - :param public_ips: A list of additional IP addresses belonging to - this node. (optional) - :type public_ips: ``list`` or ``None`` - """ - id = data['id'] - - if 'name' in data: - name = data['name'] - elif 'displayname' in data: - name = data['displayname'] - else: - name = None - - state = self.NODE_STATE_MAP[data['state']] - - public_ips = public_ips if public_ips else [] - private_ips = [] - - for nic in data['nic']: - if is_private_subnet(nic['ipaddress']): - private_ips.append(nic['ipaddress']) - else: - public_ips.append(nic['ipaddress']) - - security_groups = data.get('securitygroup', []) - - if security_groups: - security_groups = [sg['name'] for sg in security_groups] - - created = data.get('created', False) - - extra = self._get_extra_dict(data, - RESOURCE_EXTRA_ATTRIBUTES_MAP['node']) - - # Add additional parameters to extra - extra['security_group'] = security_groups - extra['ip_addresses'] = [] - extra['ip_forwarding_rules'] = [] - extra['port_forwarding_rules'] = [] - extra['created'] = created - - if 'tags' in data: - extra['tags'] = self._get_resource_tags(data['tags']) - - node = CloudStackNode(id=id, name=name, state=state, - public_ips=public_ips, private_ips=private_ips, - driver=self, extra=extra) - return node - - def _to_key_pairs(self, data): - key_pairs = [self._to_key_pair(data=item) for item in data] - return key_pairs - - def _to_key_pair(self, data): - key_pair = KeyPair(name=data['name'], - fingerprint=data['fingerprint'], - public_key=data.get('publickey', None), - private_key=data.get('privatekey', None), - driver=self) - return key_pair - - def _get_resource_tags(self, tag_set): - """ - Parse tags from the provided element and return a dictionary with - key/value pairs. - - :param tag_set: A list of key/value tag pairs - :type tag_set: ``list``` - - :rtype: ``dict`` - """ - tags = {} - - for tag in tag_set: - for key, value in tag.iteritems(): - key = tag['key'] - value = tag['value'] - tags[key] = value - - return tags - - def _get_extra_dict(self, response, mapping): - """ - Extract attributes from the element based on rules provided in the - mapping dictionary. - - :param response: The JSON response to parse the values from. - :type response: ``dict`` - - :param mapping: Dictionary with the extra layout - :type mapping: ``dict`` - - :rtype: ``dict`` - """ - extra = {} - for attribute, values in mapping.items(): - transform_func = values['transform_func'] - value = response.get(values['key_name'], None) - - if value is not None: - extra[attribute] = transform_func(value) - else: - extra[attribute] = None - - return extra diff --git a/awx/lib/site-packages/libcloud/compute/drivers/digitalocean.py b/awx/lib/site-packages/libcloud/compute/drivers/digitalocean.py deleted file mode 100644 index 7dbed418c0..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/digitalocean.py +++ /dev/null @@ -1,224 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Digital Ocean Driver -""" - -from libcloud.utils.py3 import httplib - -from libcloud.common.base import ConnectionUserAndKey, JsonResponse -from libcloud.compute.types import Provider, NodeState, InvalidCredsError -from libcloud.compute.base import NodeDriver -from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation - - -class DigitalOceanResponse(JsonResponse): - def parse_error(self): - if self.status == httplib.FOUND and '/api/error' in self.body: - # Hacky, but DigitalOcean error responses are awful - raise InvalidCredsError(self.body) - elif self.status == httplib.UNAUTHORIZED: - body = self.parse_body() - raise InvalidCredsError(body['message']) - else: - body = self.parse_body() - - if 'error_message' in body: - error = '%s (code: %s)' % (body['error_message'], self.status) - else: - error = body - return error - - -class SSHKey(object): - def __init__(self, id, name, pub_key): - self.id = id - self.name = name - self.pub_key = pub_key - - def __repr__(self): - return (('<SSHKey: id=%s, name=%s, pub_key=%s>') % - (self.id, self.name, self.pub_key)) - - -class DigitalOceanConnection(ConnectionUserAndKey): - """ - Connection class for the DigitalOcean driver. - """ - - host = 'api.digitalocean.com' - responseCls = DigitalOceanResponse - - def add_default_params(self, params): - """ - Add parameters that are necessary for every request - - This method adds ``client_id`` and ``api_key`` to - the request. - """ - params['client_id'] = self.user_id - params['api_key'] = self.key - return params - - -class DigitalOceanNodeDriver(NodeDriver): - """ - DigitalOceanNode node driver. - """ - - connectionCls = DigitalOceanConnection - - type = Provider.DIGITAL_OCEAN - name = 'Digital Ocean' - website = 'https://www.digitalocean.com' - - NODE_STATE_MAP = {'new': NodeState.PENDING, - 'off': NodeState.REBOOTING, - 'active': NodeState.RUNNING} - - def list_nodes(self): - data = self.connection.request('/droplets').object['droplets'] - return list(map(self._to_node, data)) - - def list_locations(self): - data = self.connection.request('/regions').object['regions'] - return list(map(self._to_location, data)) - - def list_images(self): - data = self.connection.request('/images').object['images'] - return list(map(self._to_image, data)) - - def list_sizes(self): - data = self.connection.request('/sizes').object['sizes'] - return list(map(self._to_size, data)) - - def create_node(self, name, size, image, location, ex_ssh_key_ids=None, - **kwargs): - """ - Create a node. - - :keyword ex_ssh_key_ids: A list of ssh key ids which will be added - to the server. (optional) - :type ex_ssh_key_ids: ``list`` of ``str`` - - :return: The newly created node. - :rtype: :class:`Node` - """ - params = {'name': name, 'size_id': size.id, 'image_id': image.id, - 'region_id': location.id} - - if ex_ssh_key_ids: - params['ssh_key_ids'] = ','.join(ex_ssh_key_ids) - - data = self.connection.request('/droplets/new', params=params).object - return self._to_node(data=data['droplet']) - - def reboot_node(self, node): - res = self.connection.request('/droplets/%s/reboot/' % (node.id)) - return res.status == httplib.OK - - def destroy_node(self, node): - params = {'scrub_data': '1'} - res = self.connection.request('/droplets/%s/destroy/' % (node.id), - params=params) - return res.status == httplib.OK - - def ex_rename_node(self, node, name): - params = {'name': name} - res = self.connection.request('/droplets/%s/rename/' % (node.id), - params=params) - return res.status == httplib.OK - - def ex_list_ssh_keys(self): - """ - List all the available SSH keys. - - :return: Available SSH keys. - :rtype: ``list`` of :class:`SSHKey` - """ - data = self.connection.request('/ssh_keys').object['ssh_keys'] - return list(map(self._to_ssh_key, data)) - - def ex_create_ssh_key(self, name, ssh_key_pub): - """ - Create a new SSH key. - - :param name: Key name (required) - :type name: ``str`` - - :param name: Valid public key string (required) - :type name: ``str`` - """ - params = {'name': name, 'ssh_pub_key': ssh_key_pub} - data = self.connection.request('/ssh_keys/new/', method='GET', - params=params).object - assert 'ssh_key' in data - return self._to_ssh_key(data=data['ssh_key']) - - def ex_destroy_ssh_key(self, key_id): - """ - Delete an existing SSH key. - - :param key_id: SSH key id (required) - :type key_id: ``str`` - """ - res = self.connection.request('/ssh_keys/%s/destroy/' % (key_id)) - return res.status == httplib.OK - - def _to_node(self, data): - extra_keys = ['backups_active', 'region_id'] - if 'status' in data: - state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN) - else: - state = NodeState.UNKNOWN - - if 'ip_address' in data and data['ip_address'] is not None: - public_ips = [data['ip_address']] - else: - public_ips = [] - - extra = {} - for key in extra_keys: - if key in data: - extra[key] = data[key] - - node = Node(id=data['id'], name=data['name'], state=state, - public_ips=public_ips, private_ips=None, extra=extra, - driver=self) - return node - - def _to_image(self, data): - extra = {'distribution': data['distribution']} - return NodeImage(id=data['id'], name=data['name'], extra=extra, - driver=self) - - def _to_location(self, data): - return NodeLocation(id=data['id'], name=data['name'], country=None, - driver=self) - - def _to_size(self, data): - ram = data['name'].lower() - - if 'mb' in ram: - ram = int(ram.replace('mb', '')) - elif 'gb' in ram: - ram = int(ram.replace('gb', '')) * 1024 - - return NodeSize(id=data['id'], name=data['name'], ram=ram, disk=0, - bandwidth=0, price=0, driver=self) - - def _to_ssh_key(self, data): - return SSHKey(id=data['id'], name=data['name'], - pub_key=data.get('ssh_pub_key', None)) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/dreamhost.py b/awx/lib/site-packages/libcloud/compute/drivers/dreamhost.py deleted file mode 100644 index cba445c39f..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/dreamhost.py +++ /dev/null @@ -1,242 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -DreamHost Driver -""" - -import copy - -from libcloud.common.base import ConnectionKey, JsonResponse -from libcloud.common.types import InvalidCredsError -from libcloud.compute.base import Node, NodeDriver, NodeSize -from libcloud.compute.base import NodeImage -from libcloud.compute.types import Provider, NodeState - -# DreamHost Private Servers can be resized on the fly, but Libcloud doesn't -# currently support extensions to its interface, so we'll put some basic sizes -# in for node creation. - -DH_PS_SIZES = { - 'minimum': { - 'id': 'minimum', - 'name': 'Minimum DH PS size', - 'ram': 300, - 'disk': None, - 'bandwidth': None - }, - 'maximum': { - 'id': 'maximum', - 'name': 'Maximum DH PS size', - 'ram': 4000, - 'disk': None, - 'bandwidth': None - }, - 'default': { - 'id': 'default', - 'name': 'Default DH PS size', - 'ram': 2300, - 'disk': None, - 'bandwidth': None - }, - 'low': { - 'id': 'low', - 'name': 'DH PS with 1GB RAM', - 'ram': 1000, - 'disk': None, - 'bandwidth': None - }, - 'high': { - 'id': 'high', - 'name': 'DH PS with 3GB RAM', - 'ram': 3000, - 'disk': None, - 'bandwidth': None - }, -} - - -class DreamhostAPIException(Exception): - def __str__(self): - return self.args[0] - - def __repr__(self): - return "<DreamhostException '%s'>" % (self.args[0]) - - -class DreamhostResponse(JsonResponse): - """ - Response class for DreamHost PS - """ - - def parse_body(self): - resp = super(DreamhostResponse, self).parse_body() - if resp['result'] != 'success': - raise Exception(self._api_parse_error(resp)) - return resp['data'] - - def parse_error(self): - raise Exception - - def _api_parse_error(self, response): - if 'data' in response: - if response['data'] == 'invalid_api_key': - raise InvalidCredsError( - "Oops! You've entered an invalid API key") - else: - raise DreamhostAPIException(response['data']) - else: - raise DreamhostAPIException("Unknown problem: %s" % (self.body)) - - -class DreamhostConnection(ConnectionKey): - """ - Connection class to connect to DreamHost's API servers - """ - - host = 'api.dreamhost.com' - responseCls = DreamhostResponse - format = 'json' - - def add_default_params(self, params): - """ - Add key and format parameters to the request. Eventually should add - unique_id to prevent re-execution of a single request. - """ - params['key'] = self.key - params['format'] = self.format - # params['unique_id'] = generate_unique_id() - return params - - -class DreamhostNodeDriver(NodeDriver): - """ - Node Driver for DreamHost PS - """ - type = Provider.DREAMHOST - api_name = 'dreamhost' - name = "Dreamhost" - website = 'http://dreamhost.com/' - connectionCls = DreamhostConnection - - _sizes = DH_PS_SIZES - - def create_node(self, **kwargs): - """Create a new Dreamhost node - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_movedata: Copy all your existing users to this new PS - :type ex_movedata: ``str`` - """ - size = kwargs['size'].ram - params = { - 'cmd': 'dreamhost_ps-add_ps', - 'movedata': kwargs.get('movedata', 'no'), - 'type': kwargs['image'].name, - 'size': size - } - data = self.connection.request('/', params).object - return Node( - id=data['added_web'], - name=data['added_web'], - state=NodeState.PENDING, - public_ips=[], - private_ips=[], - driver=self.connection.driver, - extra={ - 'type': kwargs['image'].name - } - ) - - def destroy_node(self, node): - params = { - 'cmd': 'dreamhost_ps-remove_ps', - 'ps': node.id - } - try: - return self.connection.request('/', params).success() - except DreamhostAPIException: - return False - - def reboot_node(self, node): - params = { - 'cmd': 'dreamhost_ps-reboot', - 'ps': node.id - } - try: - return self.connection.request('/', params).success() - except DreamhostAPIException: - return False - - def list_nodes(self, **kwargs): - data = self.connection.request( - '/', {'cmd': 'dreamhost_ps-list_ps'}).object - return [self._to_node(n) for n in data] - - def list_images(self, **kwargs): - data = self.connection.request( - '/', {'cmd': 'dreamhost_ps-list_images'}).object - images = [] - for img in data: - images.append(NodeImage( - id=img['image'], - name=img['image'], - driver=self.connection.driver - )) - return images - - def list_sizes(self, **kwargs): - sizes = [] - for key, values in self._sizes.items(): - attributes = copy.deepcopy(values) - attributes.update({'price': self._get_size_price(size_id=key)}) - sizes.append(NodeSize(driver=self.connection.driver, **attributes)) - - return sizes - - def list_locations(self, **kwargs): - raise NotImplementedError( - 'You cannot select a location for ' - 'DreamHost Private Servers at this time.') - - def _resize_node(self, node, size): - if (size < 300 or size > 4000): - return False - - params = { - 'cmd': 'dreamhost_ps-set_size', - 'ps': node.id, - 'size': size - } - try: - return self.connection.request('/', params).success() - except DreamhostAPIException: - return False - - def _to_node(self, data): - """ - Convert the data from a DreamhostResponse object into a Node - """ - return Node( - id=data['ps'], - name=data['ps'], - state=NodeState.UNKNOWN, - public_ips=[data['ip']], - private_ips=[], - driver=self.connection.driver, - extra={ - 'current_size': data['memory_mb'], - 'account_id': data['account_id'], - 'type': data['type']}) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/dummy.py b/awx/lib/site-packages/libcloud/compute/drivers/dummy.py deleted file mode 100644 index 982433525b..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/dummy.py +++ /dev/null @@ -1,349 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Dummy Driver - -@note: This driver is out of date -""" -import uuid -import socket -import struct - -from libcloud.common.base import ConnectionKey -from libcloud.compute.base import NodeImage, NodeSize, Node -from libcloud.compute.base import NodeDriver, NodeLocation -from libcloud.compute.base import KeyPair -from libcloud.compute.types import Provider, NodeState - - -class DummyConnection(ConnectionKey): - """ - Dummy connection class - """ - - def connect(self, host=None, port=None): - pass - - -class DummyNodeDriver(NodeDriver): - """ - Dummy node driver - - This is a fake driver which appears to always create or destroy - nodes successfully. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node=driver.create_node() - >>> node.public_ips[0] - '127.0.0.3' - >>> node.name - 'dummy-3' - - If the credentials you give convert to an integer then the next - node to be created will be one higher. - - Each time you create a node you will get a different IP address. - - >>> driver = DummyNodeDriver(22) - >>> node=driver.create_node() - >>> node.name - 'dummy-23' - - """ - - name = "Dummy Node Provider" - website = 'http://example.com' - type = Provider.DUMMY - - def __init__(self, creds): - """ - :param creds: Credentials - :type creds: ``str`` - - :rtype: ``None`` - """ - self.creds = creds - try: - num = int(creds) - except ValueError: - num = None - if num: - self.nl = [] - startip = _ip_to_int('127.0.0.1') - for i in range(num): - ip = _int_to_ip(startip + i) - self.nl.append( - Node(id=i, - name='dummy-%d' % (i), - state=NodeState.RUNNING, - public_ips=[ip], - private_ips=[], - driver=self, - extra={'foo': 'bar'}) - ) - else: - self.nl = [ - Node(id=1, - name='dummy-1', - state=NodeState.RUNNING, - public_ips=['127.0.0.1'], - private_ips=[], - driver=self, - extra={'foo': 'bar'}), - Node(id=2, - name='dummy-2', - state=NodeState.RUNNING, - public_ips=['127.0.0.1'], - private_ips=[], - driver=self, - extra={'foo': 'bar'}), - ] - self.connection = DummyConnection(self.creds) - - def get_uuid(self, unique_field=None): - """ - - :param unique_field: Unique field - :type unique_field: ``bool`` - :rtype: :class:`UUID` - """ - return str(uuid.uuid4()) - - def list_nodes(self): - """ - List the nodes known to a particular driver; - There are two default nodes created at the beginning - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node_list=driver.list_nodes() - >>> sorted([node.name for node in node_list ]) - ['dummy-1', 'dummy-2'] - - each item in the list returned is a node object from which you - can carry out any node actions you wish - - >>> node_list[0].reboot() - True - - As more nodes are added, list_nodes will return them - - >>> node=driver.create_node() - >>> node.size.id - 's1' - >>> node.image.id - 'i2' - >>> sorted([n.name for n in driver.list_nodes()]) - ['dummy-1', 'dummy-2', 'dummy-3'] - - @inherits: :class:`NodeDriver.list_nodes` - """ - return self.nl - - def reboot_node(self, node): - """ - Sets the node state to rebooting; in this dummy driver always - returns True as if the reboot had been successful. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> node=driver.create_node() - >>> from libcloud.compute.types import NodeState - >>> node.state == NodeState.RUNNING - True - >>> node.state == NodeState.REBOOTING - False - >>> driver.reboot_node(node) - True - >>> node.state == NodeState.REBOOTING - True - - Please note, dummy nodes never recover from the reboot. - - @inherits: :class:`NodeDriver.reboot_node` - """ - - node.state = NodeState.REBOOTING - return True - - def destroy_node(self, node): - """ - Sets the node state to terminated and removes it from the node list - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> from libcloud.compute.types import NodeState - >>> node = [node for node in driver.list_nodes() if - ... node.name == 'dummy-1'][0] - >>> node.state == NodeState.RUNNING - True - >>> driver.destroy_node(node) - True - >>> node.state == NodeState.RUNNING - False - >>> [n for n in driver.list_nodes() if n.name == 'dummy-1'] - [] - - @inherits: :class:`NodeDriver.destroy_node` - """ - - node.state = NodeState.TERMINATED - self.nl.remove(node) - return True - - def list_images(self, location=None): - """ - Returns a list of images as a cloud provider might have - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> sorted([image.name for image in driver.list_images()]) - ['Slackware 4', 'Ubuntu 9.04', 'Ubuntu 9.10'] - - @inherits: :class:`NodeDriver.list_images` - """ - return [ - NodeImage(id=1, name="Ubuntu 9.10", driver=self), - NodeImage(id=2, name="Ubuntu 9.04", driver=self), - NodeImage(id=3, name="Slackware 4", driver=self), - ] - - def list_sizes(self, location=None): - """ - Returns a list of node sizes as a cloud provider might have - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> sorted([size.ram for size in driver.list_sizes()]) - [128, 512, 4096, 8192] - - @inherits: :class:`NodeDriver.list_images` - """ - - return [ - NodeSize(id=1, - name="Small", - ram=128, - disk=4, - bandwidth=500, - price=4, - driver=self), - NodeSize(id=2, - name="Medium", - ram=512, - disk=16, - bandwidth=1500, - price=8, - driver=self), - NodeSize(id=3, - name="Big", - ram=4096, - disk=32, - bandwidth=2500, - price=32, - driver=self), - NodeSize(id=4, - name="XXL Big", - ram=4096 * 2, - disk=32 * 4, - bandwidth=2500 * 3, - price=32 * 2, - driver=self), - ] - - def list_locations(self): - """ - Returns a list of locations of nodes - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> sorted([loc.name + " in " + loc.country for loc in - ... driver.list_locations()]) - ['Island Datacenter in FJ', 'London Loft in GB', "Paul's Room in US"] - - @inherits: :class:`NodeDriver.list_locations` - """ - return [ - NodeLocation(id=1, - name="Paul's Room", - country='US', - driver=self), - NodeLocation(id=2, - name="London Loft", - country='GB', - driver=self), - NodeLocation(id=3, - name="Island Datacenter", - country='FJ', - driver=self), - ] - - def create_node(self, **kwargs): - """ - Creates a dummy node; the node id is equal to the number of - nodes in the node list - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver(0) - >>> sorted([node.name for node in driver.list_nodes()]) - ['dummy-1', 'dummy-2'] - >>> nodeA = driver.create_node() - >>> sorted([node.name for node in driver.list_nodes()]) - ['dummy-1', 'dummy-2', 'dummy-3'] - >>> driver.create_node().name - 'dummy-4' - >>> driver.destroy_node(nodeA) - True - >>> sorted([node.name for node in driver.list_nodes()]) - ['dummy-1', 'dummy-2', 'dummy-4'] - - @inherits: :class:`NodeDriver.create_node` - """ - l = len(self.nl) + 1 - n = Node(id=l, - name='dummy-%d' % l, - state=NodeState.RUNNING, - public_ips=['127.0.0.%d' % l], - private_ips=[], - driver=self, - size=NodeSize(id='s1', name='foo', ram=2048, - disk=160, bandwidth=None, price=0.0, - driver=self), - image=NodeImage(id='i2', name='image', driver=self), - extra={'foo': 'bar'}) - self.nl.append(n) - return n - - def import_key_pair_from_string(self, name, key_material): - key_pair = KeyPair(name=name, - public_key=key_material, - fingerprint='fingerprint', - private_key='private_key', - driver=self) - return key_pair - - -def _ip_to_int(ip): - return socket.htonl(struct.unpack('I', socket.inet_aton(ip))[0]) - - -def _int_to_ip(ip): - return socket.inet_ntoa(struct.pack('I', socket.ntohl(ip))) - -if __name__ == "__main__": - import doctest - - doctest.testmod() diff --git a/awx/lib/site-packages/libcloud/compute/drivers/ec2.py b/awx/lib/site-packages/libcloud/compute/drivers/ec2.py deleted file mode 100644 index c17f072a8c..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/ec2.py +++ /dev/null @@ -1,5770 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Amazon EC2, Eucalyptus, Nimbus and Outscale drivers. -""" - -import re -import sys -import base64 -import copy -import warnings - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.utils.py3 import b, basestring, ensure_string - -from libcloud.utils.xml import fixxpath, findtext, findattr, findall -from libcloud.utils.publickey import get_pubkey_ssh2_fingerprint -from libcloud.utils.publickey import get_pubkey_comment -from libcloud.utils.iso8601 import parse_date -from libcloud.common.aws import AWSBaseResponse, SignedAWSConnection -from libcloud.common.types import (InvalidCredsError, MalformedResponseError, - LibcloudError) -from libcloud.compute.providers import Provider -from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize -from libcloud.compute.base import NodeImage, StorageVolume, VolumeSnapshot -from libcloud.compute.base import KeyPair -from libcloud.compute.types import NodeState, KeyPairDoesNotExistError - -__all__ = [ - 'API_VERSION', - 'NAMESPACE', - 'INSTANCE_TYPES', - 'OUTSCALE_INSTANCE_TYPES', - 'OUTSCALE_SAS_REGION_DETAILS', - 'OUTSCALE_INC_REGION_DETAILS', - 'DEFAULT_EUCA_API_VERSION', - 'EUCA_NAMESPACE', - - 'EC2NodeDriver', - 'BaseEC2NodeDriver', - - 'NimbusNodeDriver', - 'EucNodeDriver', - - 'OutscaleSASNodeDriver', - 'OutscaleINCNodeDriver', - - 'EC2NodeLocation', - 'EC2ReservedNode', - 'EC2SecurityGroup', - 'EC2Network', - 'EC2NetworkSubnet', - 'EC2NetworkInterface', - 'EC2RouteTable', - 'EC2Route', - 'EC2SubnetAssociation', - 'ExEC2AvailabilityZone', - - 'IdempotentParamError' -] - -API_VERSION = '2013-10-15' -NAMESPACE = 'http://ec2.amazonaws.com/doc/%s/' % (API_VERSION) - -# Eucalyptus Constants -DEFAULT_EUCA_API_VERSION = '3.3.0' -EUCA_NAMESPACE = 'http://msgs.eucalyptus.com/%s' % (DEFAULT_EUCA_API_VERSION) - -""" -Sizes must be hardcoded, because Amazon doesn't provide an API to fetch them. -From http://aws.amazon.com/ec2/instance-types/ -""" -INSTANCE_TYPES = { - 't1.micro': { - 'id': 't1.micro', - 'name': 'Micro Instance', - 'ram': 613, - 'disk': 15, - 'bandwidth': None - }, - 'm1.small': { - 'id': 'm1.small', - 'name': 'Small Instance', - 'ram': 1740, - 'disk': 160, - 'bandwidth': None - }, - 'm1.medium': { - 'id': 'm1.medium', - 'name': 'Medium Instance', - 'ram': 3700, - 'disk': 410, - 'bandwidth': None - }, - 'm1.large': { - 'id': 'm1.large', - 'name': 'Large Instance', - 'ram': 7680, - 'disk': 850, - 'bandwidth': None - }, - 'm1.xlarge': { - 'id': 'm1.xlarge', - 'name': 'Extra Large Instance', - 'ram': 15360, - 'disk': 1690, - 'bandwidth': None - }, - 'c1.medium': { - 'id': 'c1.medium', - 'name': 'High-CPU Medium Instance', - 'ram': 1740, - 'disk': 350, - 'bandwidth': None - }, - 'c1.xlarge': { - 'id': 'c1.xlarge', - 'name': 'High-CPU Extra Large Instance', - 'ram': 7680, - 'disk': 1690, - 'bandwidth': None - }, - 'm2.xlarge': { - 'id': 'm2.xlarge', - 'name': 'High-Memory Extra Large Instance', - 'ram': 17510, - 'disk': 420, - 'bandwidth': None - }, - 'm2.2xlarge': { - 'id': 'm2.2xlarge', - 'name': 'High-Memory Double Extra Large Instance', - 'ram': 35021, - 'disk': 850, - 'bandwidth': None - }, - 'm2.4xlarge': { - 'id': 'm2.4xlarge', - 'name': 'High-Memory Quadruple Extra Large Instance', - 'ram': 70042, - 'disk': 1690, - 'bandwidth': None - }, - 'm3.medium': { - 'id': 'm3.medium', - 'name': 'Medium Instance', - 'ram': 3840, - 'disk': 4000, - 'bandwidth': None - }, - 'm3.large': { - 'id': 'm3.large', - 'name': 'Large Instance', - 'ram': 7168, - 'disk': 32000, - 'bandwidth': None - }, - 'm3.xlarge': { - 'id': 'm3.xlarge', - 'name': 'Extra Large Instance', - 'ram': 15360, - 'disk': 80000, - 'bandwidth': None - }, - 'm3.2xlarge': { - 'id': 'm3.2xlarge', - 'name': 'Double Extra Large Instance', - 'ram': 30720, - 'disk': 160000, - 'bandwidth': None - }, - 'cg1.4xlarge': { - 'id': 'cg1.4xlarge', - 'name': 'Cluster GPU Quadruple Extra Large Instance', - 'ram': 22528, - 'disk': 1690, - 'bandwidth': None - }, - 'g2.2xlarge': { - 'id': 'g2.2xlarge', - 'name': 'Cluster GPU G2 Double Extra Large Instance', - 'ram': 15000, - 'disk': 60, - 'bandwidth': None, - }, - 'cc1.4xlarge': { - 'id': 'cc1.4xlarge', - 'name': 'Cluster Compute Quadruple Extra Large Instance', - 'ram': 23552, - 'disk': 1690, - 'bandwidth': None - }, - 'cc2.8xlarge': { - 'id': 'cc2.8xlarge', - 'name': 'Cluster Compute Eight Extra Large Instance', - 'ram': 63488, - 'disk': 3370, - 'bandwidth': None - }, - # c3 instances have 2 SSDs of the specified disk size - 'c3.large': { - 'id': 'c3.large', - 'name': 'Compute Optimized Large Instance', - 'ram': 3750, - 'disk': 16, - 'bandwidth': None - }, - 'c3.xlarge': { - 'id': 'c3.xlarge', - 'name': 'Compute Optimized Extra Large Instance', - 'ram': 7000, - 'disk': 40, - 'bandwidth': None - }, - 'c3.2xlarge': { - 'id': 'c3.2xlarge', - 'name': 'Compute Optimized Double Extra Large Instance', - 'ram': 15000, - 'disk': 80, - 'bandwidth': None - }, - 'c3.4xlarge': { - 'id': 'c3.4xlarge', - 'name': 'Compute Optimized Quadruple Extra Large Instance', - 'ram': 30000, - 'disk': 160, - 'bandwidth': None - }, - 'c3.8xlarge': { - 'id': 'c3.8xlarge', - 'name': 'Compute Optimized Eight Extra Large Instance', - 'ram': 60000, - 'disk': 320, - 'bandwidth': None - }, - 'cr1.8xlarge': { - 'id': 'cr1.8xlarge', - 'name': 'High Memory Cluster Eight Extra Large', - 'ram': 244000, - 'disk': 240, - 'bandwidth': None - }, - 'hs1.4xlarge': { - 'id': 'hs1.4xlarge', - 'name': 'High Storage Quadruple Extra Large Instance', - 'ram': 61952, - 'disk': 2048, - 'bandwidth': None - }, - 'hs1.8xlarge': { - 'id': 'hs1.8xlarge', - 'name': 'High Storage Eight Extra Large Instance', - 'ram': 119808, - 'disk': 48000, - 'bandwidth': None - }, - # i2 instances have up to eight SSD drives - 'i2.xlarge': { - 'id': 'i2.xlarge', - 'name': 'High Storage Optimized Extra Large Instance', - 'ram': 31232, - 'disk': 800, - 'bandwidth': None - }, - 'i2.2xlarge': { - 'id': 'i2.2xlarge', - 'name': 'High Storage Optimized Double Extra Large Instance', - 'ram': 62464, - 'disk': 1600, - 'bandwidth': None - }, - 'i2.4xlarge': { - 'id': 'i2.4xlarge', - 'name': 'High Storage Optimized Quadruple Large Instance', - 'ram': 124928, - 'disk': 3200, - 'bandwidth': None - }, - 'i2.8xlarge': { - 'id': 'i2.8xlarge', - 'name': 'High Storage Optimized Eight Extra Large Instance', - 'ram': 249856, - 'disk': 6400, - 'bandwidth': None - }, - # 1x SSD - 'r3.large': { - 'id': 'r3.large', - 'name': 'Memory Optimized Large instance', - 'ram': 15000, - 'disk': 32, - 'bandwidth': None - }, - 'r3.xlarge': { - 'id': 'r3.xlarge', - 'name': 'Memory Optimized Extra Large instance', - 'ram': 30500, - 'disk': 80, - 'bandwidth': None - }, - 'r3.2xlarge': { - 'id': 'r3.2xlarge', - 'name': 'Memory Optimized Double Extra Large instance', - 'ram': 61000, - 'disk': 160, - 'bandwidth': None - }, - 'r3.4xlarge': { - 'id': 'r3.4xlarge', - 'name': 'Memory Optimized Quadruple Extra Large instance', - 'ram': 122000, - 'disk': 320, - 'bandwidth': None - }, - 'r3.8xlarge': { - 'id': 'r3.8xlarge', - 'name': 'Memory Optimized Eight Extra Large instance', - 'ram': 244000, - 'disk': 320, # x2 - 'bandwidth': None - } -} - -REGION_DETAILS = { - # US East (Northern Virginia) Region - 'us-east-1': { - 'endpoint': 'ec2.us-east-1.amazonaws.com', - 'api_name': 'ec2_us_east', - 'country': 'USA', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'c1.xlarge', - 'cc2.8xlarge', - 'c3.large', - 'c3.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'cg1.4xlarge', - 'g2.2xlarge', - 'cr1.8xlarge', - 'hs1.8xlarge', - 'i2.xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - 'r3.large', - 'r3.xlarge', - 'r3.2xlarge', - 'r3.4xlarge', - 'r3.8xlarge' - ] - }, - # US West (Northern California) Region - 'us-west-1': { - 'endpoint': 'ec2.us-west-1.amazonaws.com', - 'api_name': 'ec2_us_west', - 'country': 'USA', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'c1.xlarge', - 'g2.2xlarge', - 'c3.large', - 'c3.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'i2.xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - 'r3.large', - 'r3.xlarge', - 'r3.2xlarge', - 'r3.4xlarge', - 'r3.8xlarge' - ] - }, - # US West (Oregon) Region - 'us-west-2': { - 'endpoint': 'ec2.us-west-2.amazonaws.com', - 'api_name': 'ec2_us_west_oregon', - 'country': 'US', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'c1.xlarge', - 'g2.2xlarge', - 'c3.large', - 'c3.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'hs1.8xlarge', - 'cc2.8xlarge', - 'i2.xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - 'r3.large', - 'r3.xlarge', - 'r3.2xlarge', - 'r3.4xlarge', - 'r3.8xlarge' - ] - }, - # EU (Ireland) Region - 'eu-west-1': { - 'endpoint': 'ec2.eu-west-1.amazonaws.com', - 'api_name': 'ec2_eu_west', - 'country': 'Ireland', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'c1.xlarge', - 'g2.2xlarge', - 'c3.large', - 'c3.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'hs1.8xlarge', - 'cc2.8xlarge', - 'i2.xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - 'r3.large', - 'r3.xlarge', - 'r3.2xlarge', - 'r3.4xlarge', - 'r3.8xlarge' - ] - }, - # Asia Pacific (Singapore) Region - 'ap-southeast-1': { - 'endpoint': 'ec2.ap-southeast-1.amazonaws.com', - 'api_name': 'ec2_ap_southeast', - 'country': 'Singapore', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'c1.xlarge', - 'c3.large', - 'c3.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'hs1.8xlarge', - 'i2.xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - ] - }, - # Asia Pacific (Tokyo) Region - 'ap-northeast-1': { - 'endpoint': 'ec2.ap-northeast-1.amazonaws.com', - 'api_name': 'ec2_ap_northeast', - 'country': 'Japan', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'g2.2xlarge', - 'c1.xlarge', - 'c3.large', - 'c3.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'hs1.8xlarge', - 'i2.xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - 'r3.large', - 'r3.xlarge', - 'r3.2xlarge', - 'r3.4xlarge', - 'r3.8xlarge' - ] - }, - # South America (Sao Paulo) Region - 'sa-east-1': { - 'endpoint': 'ec2.sa-east-1.amazonaws.com', - 'api_name': 'ec2_sa_east', - 'country': 'Brazil', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'c1.xlarge' - ] - }, - # Asia Pacific (Sydney) Region - 'ap-southeast-2': { - 'endpoint': 'ec2.ap-southeast-2.amazonaws.com', - 'api_name': 'ec2_ap_southeast_2', - 'country': 'Australia', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'm3.medium', - 'm3.large', - 'm3.xlarge', - 'm3.2xlarge', - 'c1.medium', - 'c1.xlarge', - 'c3.large', - 'c3.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'hs1.8xlarge', - 'i2.xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - 'r3.large', - 'r3.xlarge', - 'r3.2xlarge', - 'r3.4xlarge', - 'r3.8xlarge' - ] - }, - 'nimbus': { - # Nimbus clouds have 3 EC2-style instance types but their particular - # RAM allocations are configured by the admin - 'country': 'custom', - 'instance_types': [ - 'm1.small', - 'm1.large', - 'm1.xlarge' - ] - } -} - - -""" -Sizes must be hardcoded because Outscale doesn't provide an API to fetch them. -Outscale cloud instances share some names with EC2 but have differents -specifications so declare them in another constant. -""" -OUTSCALE_INSTANCE_TYPES = { - 't1.micro': { - 'id': 't1.micro', - 'name': 'Micro Instance', - 'ram': 615, - 'disk': 0, - 'bandwidth': None - }, - 'm1.small': { - 'id': 'm1.small', - 'name': 'Standard Small Instance', - 'ram': 1740, - 'disk': 150, - 'bandwidth': None - }, - 'm1.medium': { - 'id': 'm1.medium', - 'name': 'Standard Medium Instance', - 'ram': 3840, - 'disk': 420, - 'bandwidth': None - }, - 'm1.large': { - 'id': 'm1.large', - 'name': 'Standard Large Instance', - 'ram': 7680, - 'disk': 840, - 'bandwidth': None - }, - 'm1.xlarge': { - 'id': 'm1.xlarge', - 'name': 'Standard Extra Large Instance', - 'ram': 15360, - 'disk': 1680, - 'bandwidth': None - }, - 'c1.medium': { - 'id': 'c1.medium', - 'name': 'Compute Optimized Medium Instance', - 'ram': 1740, - 'disk': 340, - 'bandwidth': None - }, - 'c1.xlarge': { - 'id': 'c1.xlarge', - 'name': 'Compute Optimized Extra Large Instance', - 'ram': 7168, - 'disk': 1680, - 'bandwidth': None - }, - 'c3.large': { - 'id': 'c3.large', - 'name': 'Compute Optimized Large Instance', - 'ram': 3840, - 'disk': 32, - 'bandwidth': None - }, - 'c3.xlarge': { - 'id': 'c3.xlarge', - 'name': 'Compute Optimized Extra Large Instance', - 'ram': 7168, - 'disk': 80, - 'bandwidth': None - }, - 'c3.2xlarge': { - 'id': 'c3.2xlarge', - 'name': 'Compute Optimized Double Extra Large Instance', - 'ram': 15359, - 'disk': 160, - 'bandwidth': None - }, - 'c3.4xlarge': { - 'id': 'c3.4xlarge', - 'name': 'Compute Optimized Quadruple Extra Large Instance', - 'ram': 30720, - 'disk': 320, - 'bandwidth': None - }, - 'c3.8xlarge': { - 'id': 'c3.8xlarge', - 'name': 'Compute Optimized Eight Extra Large Instance', - 'ram': 61440, - 'disk': 640, - 'bandwidth': None - }, - 'm2.xlarge': { - 'id': 'm2.xlarge', - 'name': 'High Memory Extra Large Instance', - 'ram': 17510, - 'disk': 420, - 'bandwidth': None - }, - 'm2.2xlarge': { - 'id': 'm2.2xlarge', - 'name': 'High Memory Double Extra Large Instance', - 'ram': 35020, - 'disk': 840, - 'bandwidth': None - }, - 'm2.4xlarge': { - 'id': 'm2.4xlarge', - 'name': 'High Memory Quadruple Extra Large Instance', - 'ram': 70042, - 'disk': 1680, - 'bandwidth': None - }, - 'nv1.small': { - 'id': 'nv1.small', - 'name': 'GPU Small Instance', - 'ram': 1739, - 'disk': 150, - 'bandwidth': None - }, - 'nv1.medium': { - 'id': 'nv1.medium', - 'name': 'GPU Medium Instance', - 'ram': 3839, - 'disk': 420, - 'bandwidth': None - }, - 'nv1.large': { - 'id': 'nv1.large', - 'name': 'GPU Large Instance', - 'ram': 7679, - 'disk': 840, - 'bandwidth': None - }, - 'nv1.xlarge': { - 'id': 'nv1.xlarge', - 'name': 'GPU Extra Large Instance', - 'ram': 15358, - 'disk': 1680, - 'bandwidth': None - }, - 'g2.2xlarge': { - 'id': 'g2.2xlarge', - 'name': 'GPU Double Extra Large Instance', - 'ram': 15360, - 'disk': 60, - 'bandwidth': None - }, - 'cc1.4xlarge': { - 'id': 'cc1.4xlarge', - 'name': 'Cluster Compute Quadruple Extra Large Instance', - 'ram': 24576, - 'disk': 1680, - 'bandwidth': None - }, - 'cc2.8xlarge': { - 'id': 'cc2.8xlarge', - 'name': 'Cluster Compute Eight Extra Large Instance', - 'ram': 65536, - 'disk': 3360, - 'bandwidth': None - }, - 'hi1.xlarge': { - 'id': 'hi1.xlarge', - 'name': 'High Storage Extra Large Instance', - 'ram': 15361, - 'disk': 1680, - 'bandwidth': None - }, - 'm3.xlarge': { - 'id': 'm3.xlarge', - 'name': 'High Storage Optimized Extra Large Instance', - 'ram': 15357, - 'disk': 0, - 'bandwidth': None - }, - 'm3.2xlarge': { - 'id': 'm3.2xlarge', - 'name': 'High Storage Optimized Double Extra Large Instance', - 'ram': 30720, - 'disk': 0, - 'bandwidth': None - }, - 'm3s.xlarge': { - 'id': 'm3s.xlarge', - 'name': 'High Storage Optimized Extra Large Instance', - 'ram': 15359, - 'disk': 0, - 'bandwidth': None - }, - 'm3s.2xlarge': { - 'id': 'm3s.2xlarge', - 'name': 'High Storage Optimized Double Extra Large Instance', - 'ram': 30719, - 'disk': 0, - 'bandwidth': None - }, - 'cr1.8xlarge': { - 'id': 'cr1.8xlarge', - 'name': 'Memory Optimized Eight Extra Large Instance', - 'ram': 249855, - 'disk': 240, - 'bandwidth': None - }, - 'os1.2xlarge': { - 'id': 'os1.2xlarge', - 'name': 'Memory Optimized, High Storage, Passthrough NIC Double Extra ' - 'Large Instance', - 'ram': 65536, - 'disk': 60, - 'bandwidth': None - }, - 'os1.4xlarge': { - 'id': 'os1.4xlarge', - 'name': 'Memory Optimized, High Storage, Passthrough NIC Quadruple Ext' - 'ra Large Instance', - 'ram': 131072, - 'disk': 120, - 'bandwidth': None - }, - 'os1.8xlarge': { - 'id': 'os1.8xlarge', - 'name': 'Memory Optimized, High Storage, Passthrough NIC Eight Extra L' - 'arge Instance', - 'ram': 249856, - 'disk': 500, - 'bandwidth': None - }, - 'oc1.4xlarge': { - 'id': 'oc1.4xlarge', - 'name': 'Outscale Quadruple Extra Large Instance', - 'ram': 24575, - 'disk': 1680, - 'bandwidth': None - }, - 'oc2.8xlarge': { - 'id': 'oc2.8xlarge', - 'name': 'Outscale Eight Extra Large Instance', - 'ram': 65535, - 'disk': 3360, - 'bandwidth': None - } -} - - -""" -The function manipulating Outscale cloud regions will be overriden because -Outscale instances types are in a separate dict so also declare Outscale cloud -regions in some other constants. -""" -OUTSCALE_SAS_REGION_DETAILS = { - 'eu-west-3': { - 'endpoint': 'api-ppd.outscale.com', - 'api_name': 'osc_sas_eu_west_3', - 'country': 'FRANCE', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'c1.medium', - 'c1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'nv1.small', - 'nv1.medium', - 'nv1.large', - 'nv1.xlarge', - 'cc1.4xlarge', - 'cc2.8xlarge', - 'm3.xlarge', - 'm3.2xlarge', - 'cr1.8xlarge', - 'os1.8xlarge' - ] - }, - 'eu-west-1': { - 'endpoint': 'api.eu-west-1.outscale.com', - 'api_name': 'osc_sas_eu_west_1', - 'country': 'FRANCE', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'c1.medium', - 'c1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'nv1.small', - 'nv1.medium', - 'nv1.large', - 'nv1.xlarge', - 'cc1.4xlarge', - 'cc2.8xlarge', - 'm3.xlarge', - 'm3.2xlarge', - 'cr1.8xlarge', - 'os1.8xlarge' - ] - }, - 'us-east-1': { - 'endpoint': 'api.us-east-1.outscale.com', - 'api_name': 'osc_sas_us_east_1', - 'country': 'USA', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'c1.medium', - 'c1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'nv1.small', - 'nv1.medium', - 'nv1.large', - 'nv1.xlarge', - 'cc1.4xlarge', - 'cc2.8xlarge', - 'm3.xlarge', - 'm3.2xlarge', - 'cr1.8xlarge', - 'os1.8xlarge' - ] - } -} - - -OUTSCALE_INC_REGION_DETAILS = { - 'eu-west-1': { - 'endpoint': 'api.eu-west-1.outscale.com', - 'api_name': 'osc_inc_eu_west_1', - 'country': 'FRANCE', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'c1.medium', - 'c1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'nv1.small', - 'nv1.medium', - 'nv1.large', - 'nv1.xlarge', - 'cc1.4xlarge', - 'cc2.8xlarge', - 'm3.xlarge', - 'm3.2xlarge', - 'cr1.8xlarge', - 'os1.8xlarge' - ] - }, - 'eu-west-3': { - 'endpoint': 'api-ppd.outscale.com', - 'api_name': 'osc_inc_eu_west_3', - 'country': 'FRANCE', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'c1.medium', - 'c1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'nv1.small', - 'nv1.medium', - 'nv1.large', - 'nv1.xlarge', - 'cc1.4xlarge', - 'cc2.8xlarge', - 'm3.xlarge', - 'm3.2xlarge', - 'cr1.8xlarge', - 'os1.8xlarge' - ] - }, - 'us-east-1': { - 'endpoint': 'api.us-east-1.outscale.com', - 'api_name': 'osc_inc_us_east_1', - 'country': 'USA', - 'instance_types': [ - 't1.micro', - 'm1.small', - 'm1.medium', - 'm1.large', - 'm1.xlarge', - 'c1.medium', - 'c1.xlarge', - 'm2.xlarge', - 'm2.2xlarge', - 'm2.4xlarge', - 'nv1.small', - 'nv1.medium', - 'nv1.large', - 'nv1.xlarge', - 'cc1.4xlarge', - 'cc2.8xlarge', - 'm3.xlarge', - 'm3.2xlarge', - 'cr1.8xlarge', - 'os1.8xlarge' - ] - } -} - - -""" -Define the extra dictionary for specific resources -""" -RESOURCE_EXTRA_ATTRIBUTES_MAP = { - 'ebs_volume': { - 'snapshot_id': { - 'xpath': 'ebs/snapshotId', - 'transform_func': str - }, - 'volume_id': { - 'xpath': 'ebs/volumeId', - 'transform_func': str - }, - 'volume_size': { - 'xpath': 'ebs/volumeSize', - 'transform_func': int - }, - 'delete': { - 'xpath': 'ebs/deleteOnTermination', - 'transform_func': str - }, - 'volume_type': { - 'xpath': 'ebs/volumeType', - 'transform_func': str - }, - 'iops': { - 'xpath': 'ebs/iops', - 'transform_func': int - } - }, - 'elastic_ip': { - 'allocation_id': { - 'xpath': 'allocationId', - 'transform_func': str, - }, - 'association_id': { - 'xpath': 'associationId', - 'transform_func': str, - }, - 'interface_id': { - 'xpath': 'networkInterfaceId', - 'transform_func': str, - }, - 'owner_id': { - 'xpath': 'networkInterfaceOwnerId', - 'transform_func': str, - }, - 'private_ip': { - 'xpath': 'privateIp', - 'transform_func': str, - } - }, - 'image': { - 'state': { - 'xpath': 'imageState', - 'transform_func': str - }, - 'owner_id': { - 'xpath': 'imageOwnerId', - 'transform_func': str - }, - 'owner_alias': { - 'xpath': 'imageOwnerAlias', - 'transform_func': str - }, - 'is_public': { - 'xpath': 'isPublic', - 'transform_func': str - }, - 'architecture': { - 'xpath': 'architecture', - 'transform_func': str - }, - 'image_type': { - 'xpath': 'imageType', - 'transform_func': str - }, - 'image_location': { - 'xpath': 'imageLocation', - 'transform_func': str - }, - 'platform': { - 'xpath': 'platform', - 'transform_func': str - }, - 'description': { - 'xpath': 'description', - 'transform_func': str - }, - 'root_device_type': { - 'xpath': 'rootDeviceType', - 'transform_func': str - }, - 'virtualization_type': { - 'xpath': 'virtualizationType', - 'transform_func': str - }, - 'hypervisor': { - 'xpath': 'hypervisor', - 'transform_func': str - }, - 'kernel_id': { - 'xpath': 'kernelId', - 'transform_func': str - }, - 'ramdisk_id': { - 'xpath': 'ramdiskId', - 'transform_func': str - } - }, - 'network': { - 'state': { - 'xpath': 'state', - 'transform_func': str - }, - 'dhcp_options_id': { - 'xpath': 'dhcpOptionsId', - 'transform_func': str - }, - 'instance_tenancy': { - 'xpath': 'instanceTenancy', - 'transform_func': str - }, - 'is_default': { - 'xpath': 'isDefault', - 'transform_func': str - } - }, - 'network_interface': { - 'subnet_id': { - 'xpath': 'subnetId', - 'transform_func': str - }, - 'vpc_id': { - 'xpath': 'vpcId', - 'transform_func': str - }, - 'zone': { - 'xpath': 'availabilityZone', - 'transform_func': str - }, - 'description': { - 'xpath': 'description', - 'transform_func': str - }, - 'owner_id': { - 'xpath': 'ownerId', - 'transform_func': str - }, - 'mac_address': { - 'xpath': 'macAddress', - 'transform_func': str - }, - 'private_dns_name': { - 'xpath': 'privateIpAddressesSet/privateDnsName', - 'transform_func': str - }, - 'source_dest_check': { - 'xpath': 'sourceDestCheck', - 'transform_func': str - } - }, - 'network_interface_attachment': { - 'attachment_id': { - 'xpath': 'attachment/attachmentId', - 'transform_func': str - }, - 'instance_id': { - 'xpath': 'attachment/instanceId', - 'transform_func': str - }, - 'owner_id': { - 'xpath': 'attachment/instanceOwnerId', - 'transform_func': str - }, - 'device_index': { - 'xpath': 'attachment/deviceIndex', - 'transform_func': int - }, - 'status': { - 'xpath': 'attachment/status', - 'transform_func': str - }, - 'attach_time': { - 'xpath': 'attachment/attachTime', - 'transform_func': parse_date - }, - 'delete': { - 'xpath': 'attachment/deleteOnTermination', - 'transform_func': str - } - }, - 'node': { - 'availability': { - 'xpath': 'placement/availabilityZone', - 'transform_func': str - }, - 'architecture': { - 'xpath': 'architecture', - 'transform_func': str - }, - 'client_token': { - 'xpath': 'clientToken', - 'transform_func': str - }, - 'dns_name': { - 'xpath': 'dnsName', - 'transform_func': str - }, - 'hypervisor': { - 'xpath': 'hypervisor', - 'transform_func': str - }, - 'iam_profile': { - 'xpath': 'iamInstanceProfile/id', - 'transform_func': str - }, - 'image_id': { - 'xpath': 'imageId', - 'transform_func': str - }, - 'instance_id': { - 'xpath': 'instanceId', - 'transform_func': str - }, - 'instance_lifecycle': { - 'xpath': 'instanceLifecycle', - 'transform_func': str - }, - 'instance_tenancy': { - 'xpath': 'placement/tenancy', - 'transform_func': str - }, - 'instance_type': { - 'xpath': 'instanceType', - 'transform_func': str - }, - 'key_name': { - 'xpath': 'keyName', - 'transform_func': str - }, - 'launch_index': { - 'xpath': 'amiLaunchIndex', - 'transform_func': int - }, - 'launch_time': { - 'xpath': 'launchTime', - 'transform_func': str - }, - 'kernel_id': { - 'xpath': 'kernelId', - 'transform_func': str - }, - 'monitoring': { - 'xpath': 'monitoring/state', - 'transform_func': str - }, - 'platform': { - 'xpath': 'platform', - 'transform_func': str - }, - 'private_dns': { - 'xpath': 'privateDnsName', - 'transform_func': str - }, - 'ramdisk_id': { - 'xpath': 'ramdiskId', - 'transform_func': str - }, - 'root_device_type': { - 'xpath': 'rootDeviceType', - 'transform_func': str - }, - 'root_device_name': { - 'xpath': 'rootDeviceName', - 'transform_func': str - }, - 'reason': { - 'xpath': 'reason', - 'transform_func': str - }, - 'source_dest_check': { - 'xpath': 'sourceDestCheck', - 'transform_func': str - }, - 'status': { - 'xpath': 'instanceState/name', - 'transform_func': str - }, - 'subnet_id': { - 'xpath': 'subnetId', - 'transform_func': str - }, - 'virtualization_type': { - 'xpath': 'virtualizationType', - 'transform_func': str - }, - 'ebs_optimized': { - 'xpath': 'ebsOptimized', - 'transform_func': str - }, - 'vpc_id': { - 'xpath': 'vpcId', - 'transform_func': str - } - }, - 'reserved_node': { - 'instance_type': { - 'xpath': 'instanceType', - 'transform_func': str - }, - 'availability': { - 'xpath': 'availabilityZone', - 'transform_func': str - }, - 'start': { - 'xpath': 'start', - 'transform_func': str - }, - 'duration': { - 'xpath': 'duration', - 'transform_func': int - }, - 'usage_price': { - 'xpath': 'usagePrice', - 'transform_func': float - }, - 'fixed_price': { - 'xpath': 'fixedPrice', - 'transform_func': float - }, - 'instance_count': { - 'xpath': 'instanceCount', - 'transform_func': int - }, - 'description': { - 'xpath': 'productDescription', - 'transform_func': str - }, - 'instance_tenancy': { - 'xpath': 'instanceTenancy', - 'transform_func': str - }, - 'currency_code': { - 'xpath': 'currencyCode', - 'transform_func': str - }, - 'offering_type': { - 'xpath': 'offeringType', - 'transform_func': str - } - }, - 'security_group': { - 'vpc_id': { - 'xpath': 'vpcId', - 'transform_func': str - }, - 'description': { - 'xpath': 'groupDescription', - 'transform_func': str - }, - 'owner_id': { - 'xpath': 'ownerId', - 'transform_func': str - } - }, - 'snapshot': { - 'volume_id': { - 'xpath': 'volumeId', - 'transform_func': str - }, - 'state': { - 'xpath': 'status', - 'transform_func': str - }, - 'description': { - 'xpath': 'description', - 'transform_func': str - }, - 'progress': { - 'xpath': 'progress', - 'transform_func': str - }, - 'start_time': { - 'xpath': 'startTime', - 'transform_func': parse_date - } - }, - 'subnet': { - 'cidr_block': { - 'xpath': 'cidrBlock', - 'transform_func': str - }, - 'available_ips': { - 'xpath': 'availableIpAddressCount', - 'transform_func': int - }, - 'zone': { - 'xpath': 'availabilityZone', - 'transform_func': str - }, - 'vpc_id': { - 'xpath': 'vpcId', - 'transform_func': str - } - }, - 'volume': { - 'device': { - 'xpath': 'attachmentSet/item/device', - 'transform_func': str - }, - 'iops': { - 'xpath': 'iops', - 'transform_func': int - }, - 'zone': { - 'xpath': 'availabilityZone', - 'transform_func': str - }, - 'create_time': { - 'xpath': 'createTime', - 'transform_func': parse_date - }, - 'state': { - 'xpath': 'status', - 'transform_func': str - }, - 'attach_time': { - 'xpath': 'attachmentSet/item/attachTime', - 'transform_func': parse_date - }, - 'attachment_status': { - 'xpath': 'attachmentSet/item/status', - 'transform_func': str - }, - 'instance_id': { - 'xpath': 'attachmentSet/item/instanceId', - 'transform_func': str - }, - 'delete': { - 'xpath': 'attachmentSet/item/deleteOnTermination', - 'transform_func': str - } - }, - 'route_table': { - 'vpc_id': { - 'xpath': 'vpcId', - 'transform_func': str - } - } -} - -VALID_EC2_REGIONS = REGION_DETAILS.keys() -VALID_EC2_REGIONS = [r for r in VALID_EC2_REGIONS if r != 'nimbus'] - - -class EC2NodeLocation(NodeLocation): - def __init__(self, id, name, country, driver, availability_zone): - super(EC2NodeLocation, self).__init__(id, name, country, driver) - self.availability_zone = availability_zone - - def __repr__(self): - return (('<EC2NodeLocation: id=%s, name=%s, country=%s, ' - 'availability_zone=%s driver=%s>') - % (self.id, self.name, self.country, - self.availability_zone, self.driver.name)) - - -class EC2Response(AWSBaseResponse): - """ - EC2 specific response parsing and error handling. - """ - - def parse_error(self): - err_list = [] - # Okay, so for Eucalyptus, you can get a 403, with no body, - # if you are using the wrong user/password. - msg = "Failure: 403 Forbidden" - if self.status == 403 and self.body[:len(msg)] == msg: - raise InvalidCredsError(msg) - - try: - body = ET.XML(self.body) - except: - raise MalformedResponseError("Failed to parse XML", - body=self.body, driver=EC2NodeDriver) - - for err in body.findall('Errors/Error'): - code, message = err.getchildren() - err_list.append('%s: %s' % (code.text, message.text)) - if code.text == 'InvalidClientTokenId': - raise InvalidCredsError(err_list[-1]) - if code.text == 'SignatureDoesNotMatch': - raise InvalidCredsError(err_list[-1]) - if code.text == 'AuthFailure': - raise InvalidCredsError(err_list[-1]) - if code.text == 'OptInRequired': - raise InvalidCredsError(err_list[-1]) - if code.text == 'IdempotentParameterMismatch': - raise IdempotentParamError(err_list[-1]) - if code.text == 'InvalidKeyPair.NotFound': - # TODO: Use connection context instead - match = re.match(r'.*\'(.+?)\'.*', message.text) - - if match: - name = match.groups()[0] - else: - name = None - - raise KeyPairDoesNotExistError(name=name, - driver=self.connection.driver) - return '\n'.join(err_list) - - -class EC2Connection(SignedAWSConnection): - """ - Represents a single connection to the EC2 Endpoint. - """ - - version = API_VERSION - host = REGION_DETAILS['us-east-1']['endpoint'] - responseCls = EC2Response - - -class ExEC2AvailabilityZone(object): - """ - Extension class which stores information about an EC2 availability zone. - - Note: This class is EC2 specific. - """ - - def __init__(self, name, zone_state, region_name): - self.name = name - self.zone_state = zone_state - self.region_name = region_name - - def __repr__(self): - return (('<ExEC2AvailabilityZone: name=%s, zone_state=%s, ' - 'region_name=%s>') - % (self.name, self.zone_state, self.region_name)) - - -class EC2ReservedNode(Node): - """ - Class which stores information about EC2 reserved instances/nodes - Inherits from Node and passes in None for name and private/public IPs - - Note: This class is EC2 specific. - """ - - def __init__(self, id, state, driver, size=None, image=None, extra=None): - super(EC2ReservedNode, self).__init__(id=id, name=None, state=state, - public_ips=None, - private_ips=None, - driver=driver, extra=extra) - - def __repr__(self): - return (('<EC2ReservedNode: id=%s>') % (self.id)) - - -class EC2SecurityGroup(object): - """ - Represents information about a Security group - - Note: This class is EC2 specific. - """ - - def __init__(self, id, name, ingress_rules, egress_rules, extra=None): - self.id = id - self.name = name - self.ingress_rules = ingress_rules - self.egress_rules = egress_rules - self.extra = extra or {} - - def __repr__(self): - return (('<EC2SecurityGroup: id=%s, name=%s') - % (self.id, self.name)) - - -class EC2Network(object): - """ - Represents information about a VPC (Virtual Private Cloud) network - - Note: This class is EC2 specific. - """ - - def __init__(self, id, name, cidr_block, extra=None): - self.id = id - self.name = name - self.cidr_block = cidr_block - self.extra = extra or {} - - def __repr__(self): - return (('<EC2Network: id=%s, name=%s') - % (self.id, self.name)) - - -class EC2NetworkSubnet(object): - """ - Represents information about a VPC (Virtual Private Cloud) subnet - - Note: This class is EC2 specific. - """ - - def __init__(self, id, name, state, extra=None): - self.id = id - self.name = name - self.state = state - self.extra = extra or {} - - def __repr__(self): - return (('<EC2NetworkSubnet: id=%s, name=%s') % (self.id, self.name)) - - -class EC2NetworkInterface(object): - """ - Represents information about a VPC network interface - - Note: This class is EC2 specific. The state parameter denotes the current - status of the interface. Valid values for state are attaching, attached, - detaching and detached. - """ - - def __init__(self, id, name, state, extra=None): - self.id = id - self.name = name - self.state = state - self.extra = extra or {} - - def __repr__(self): - return (('<EC2NetworkInterface: id=%s, name=%s') - % (self.id, self.name)) - - -class ElasticIP(object): - """ - Represents information about an elastic IP address - - :param ip: The elastic IP address - :type ip: ``str`` - - :param domain: The domain that the IP resides in (EC2-Classic/VPC). - EC2 classic is represented with standard and VPC - is represented with vpc. - :type domain: ``str`` - - :param instance_id: The identifier of the instance which currently - has the IP associated. - :type instance_id: ``str`` - - Note: This class is used to support both EC2 and VPC IPs. - For VPC specific attributes are stored in the extra - dict to make promotion to the base API easier. - """ - - def __init__(self, ip, domain, instance_id, extra=None): - self.ip = ip - self.domain = domain - self.instance_id = instance_id - self.extra = extra or {} - - def __repr__(self): - return (('<ElasticIP: ip=%s, domain=%s, instance_id=%s>') - % (self.ip, self.domain, self.instance_id)) - - -class VPCInternetGateway(object): - """ - Class which stores information about VPC Internet Gateways. - - Note: This class is VPC specific. - """ - - def __init__(self, id, name, vpc_id, state, driver, extra=None): - self.id = id - self.name = name - self.vpc_id = vpc_id - self.state = state - self.extra = extra or {} - - def __repr__(self): - return (('<VPCInternetGateway: id=%s>') % (self.id)) - - -class EC2RouteTable(object): - """ - Class which stores information about VPC Route Tables. - - Note: This class is VPC specific. - """ - - def __init__(self, id, name, routes, subnet_associations, - propagating_gateway_ids, extra=None): - """ - :param id: The ID of the route table. - :type id: ``str`` - - :param name: The name of the route table. - :type name: ``str`` - - :param routes: A list of routes in the route table. - :type routes: ``list`` of :class:`EC2Route` - - :param subnet_associations: A list of associations between the - route table and one or more subnets. - :type subnet_associations: ``list`` of - :class:`EC2SubnetAssociation` - - :param propagating_gateway_ids: The list of IDs of any virtual - private gateways propagating the - routes. - :type propagating_gateway_ids: ``list`` - """ - - self.id = id - self.name = name - self.routes = routes - self.subnet_associations = subnet_associations - self.propagating_gateway_ids = propagating_gateway_ids - self.extra = extra or {} - - def __repr__(self): - return (('<EC2RouteTable: id=%s>') % (self.id)) - - -class EC2Route(object): - """ - Class which stores information about a Route. - - Note: This class is VPC specific. - """ - - def __init__(self, cidr, gateway_id, instance_id, owner_id, - interface_id, state, origin, vpc_peering_connection_id): - """ - :param cidr: The CIDR block used for the destination match. - :type cidr: ``str`` - - :param gateway_id: The ID of a gateway attached to the VPC. - :type gateway_id: ``str`` - - :param instance_id: The ID of a NAT instance in the VPC. - :type instance_id: ``str`` - - :param owner_id: The AWS account ID of the owner of the instance. - :type owner_id: ``str`` - - :param interface_id: The ID of the network interface. - :type interface_id: ``str`` - - :param state: The state of the route (active | blackhole). - :type state: ``str`` - - :param origin: Describes how the route was created. - :type origin: ``str`` - - :param vpc_peering_connection_id: The ID of the VPC - peering connection. - :type vpc_peering_connection_id: ``str`` - """ - - self.cidr = cidr - self.gateway_id = gateway_id - self.instance_id = instance_id - self.owner_id = owner_id - self.interface_id = interface_id - self.state = state - self.origin = origin - self.vpc_peering_connection_id = vpc_peering_connection_id - - def __repr__(self): - return (('<EC2Route: cidr=%s>') % (self.cidr)) - - -class EC2SubnetAssociation(object): - """ - Class which stores information about Route Table associated with - a given Subnet in a VPC - - Note: This class is VPC specific. - """ - - def __init__(self, id, route_table_id, subnet_id, main=False): - """ - :param id: The ID of the subent association in the VPC. - :type id: ``str`` - - :param route_table_id: The ID of a route table in the VPC. - :type route_table_id: ``str`` - - :param subnet_id: The ID of a subnet in the VPC. - :type subnet_id: ``str`` - - :param main: If true, means this is a main VPC route table. - :type main: ``bool`` - """ - - self.id = id - self.route_table_id = route_table_id - self.subnet_id = subnet_id - self.main = main - - def __repr__(self): - return (('<EC2SubnetAssociation: id=%s>') % (self.id)) - - -class BaseEC2NodeDriver(NodeDriver): - """ - Base Amazon EC2 node driver. - - Used for main EC2 and other derivate driver classes to inherit from it. - """ - - connectionCls = EC2Connection - features = {'create_node': ['ssh_key']} - path = '/' - - NODE_STATE_MAP = { - 'pending': NodeState.PENDING, - 'running': NodeState.RUNNING, - 'shutting-down': NodeState.UNKNOWN, - 'terminated': NodeState.TERMINATED - } - - def list_nodes(self, ex_node_ids=None, ex_filters=None): - """ - List all nodes - - Ex_node_ids parameter is used to filter the list of - nodes that should be returned. Only the nodes - with the corresponding node ids will be returned. - - :param ex_node_ids: List of ``node.id`` - :type ex_node_ids: ``list`` of ``str`` - - :param ex_filters: The filters so that the response includes - information for only certain nodes. - :type ex_filters: ``dict`` - - :rtype: ``list`` of :class:`Node` - """ - - params = {'Action': 'DescribeInstances'} - - if ex_node_ids: - params.update(self._pathlist('InstanceId', ex_node_ids)) - - if ex_filters: - params.update(self._build_filters(ex_filters)) - - elem = self.connection.request(self.path, params=params).object - - nodes = [] - for rs in findall(element=elem, xpath='reservationSet/item', - namespace=NAMESPACE): - nodes += self._to_nodes(rs, 'instancesSet/item') - - nodes_elastic_ips_mappings = self.ex_describe_addresses(nodes) - - for node in nodes: - ips = nodes_elastic_ips_mappings[node.id] - node.public_ips.extend(ips) - - return nodes - - def list_sizes(self, location=None): - available_types = REGION_DETAILS[self.region_name]['instance_types'] - sizes = [] - - for instance_type in available_types: - attributes = INSTANCE_TYPES[instance_type] - attributes = copy.deepcopy(attributes) - price = self._get_size_price(size_id=instance_type) - attributes.update({'price': price}) - sizes.append(NodeSize(driver=self, **attributes)) - return sizes - - def list_images(self, location=None, ex_image_ids=None, ex_owner=None, - ex_executableby=None): - """ - List all images - @inherits: :class:`NodeDriver.list_images` - - Ex_image_ids parameter is used to filter the list of - images that should be returned. Only the images - with the corresponding image ids will be returned. - - Ex_owner parameter is used to filter the list of - images that should be returned. Only the images - with the corresponding owner will be returned. - Valid values: amazon|aws-marketplace|self|all|aws id - - Ex_executableby parameter describes images for which - the specified user has explicit launch permissions. - The user can be an AWS account ID, self to return - images for which the sender of the request has - explicit launch permissions, or all to return - images with public launch permissions. - Valid values: all|self|aws id - - :param ex_image_ids: List of ``NodeImage.id`` - :type ex_image_ids: ``list`` of ``str`` - - :param ex_owner: Owner name - :type ex_owner: ``str`` - - :param ex_executableby: Executable by - :type ex_executableby: ``str`` - - :rtype: ``list`` of :class:`NodeImage` - """ - params = {'Action': 'DescribeImages'} - - if ex_owner: - params.update({'Owner.1': ex_owner}) - - if ex_executableby: - params.update({'ExecutableBy.1': ex_executableby}) - - if ex_image_ids: - for index, image_id in enumerate(ex_image_ids): - index += 1 - params.update({'ImageId.%s' % (index): image_id}) - - images = self._to_images( - self.connection.request(self.path, params=params).object - ) - return images - - def get_image(self, image_id): - """ - Get an image based on a image_id - - :param image_id: Image identifier - :type image_id: ``str`` - - :return: A NodeImage object - :rtype: :class:`NodeImage` - - """ - images = self.list_images(ex_image_ids=[image_id]) - image = images[0] - - return image - - def list_locations(self): - locations = [] - for index, availability_zone in \ - enumerate(self.ex_list_availability_zones()): - locations.append(EC2NodeLocation( - index, availability_zone.name, self.country, self, - availability_zone) - ) - return locations - - def list_volumes(self, node=None): - params = { - 'Action': 'DescribeVolumes', - } - if node: - filters = {'attachment.instance-id': node.id} - params.update(self._build_filters(filters)) - - response = self.connection.request(self.path, params=params).object - volumes = [self._to_volume(el) for el in response.findall( - fixxpath(xpath='volumeSet/item', namespace=NAMESPACE)) - ] - return volumes - - def create_node(self, **kwargs): - """ - Create a new EC2 node. - - Reference: http://bit.ly/8ZyPSy [docs.amazonwebservices.com] - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_keyname: The name of the key pair - :type ex_keyname: ``str`` - - :keyword ex_userdata: User data - :type ex_userdata: ``str`` - - :keyword ex_security_groups: A list of names of security groups to - assign to the node. - :type ex_security_groups: ``list`` - - :keyword ex_metadata: Key/Value metadata to associate with a node - :type ex_metadata: ``dict`` - - :keyword ex_mincount: Minimum number of instances to launch - :type ex_mincount: ``int`` - - :keyword ex_maxcount: Maximum number of instances to launch - :type ex_maxcount: ``int`` - - :keyword ex_clienttoken: Unique identifier to ensure idempotency - :type ex_clienttoken: ``str`` - - :keyword ex_blockdevicemappings: ``list`` of ``dict`` block device - mappings. - :type ex_blockdevicemappings: ``list`` of ``dict`` - - :keyword ex_iamprofile: Name or ARN of IAM profile - :type ex_iamprofile: ``str`` - - :keyword ex_ebs_optimized: EBS-Optimized if True - :type ex_ebs_optimized: ``bool`` - - :keyword ex_subnet: The subnet to launch the instance into. - :type ex_subnet: :class:`.EC2Subnet` - """ - image = kwargs["image"] - size = kwargs["size"] - params = { - 'Action': 'RunInstances', - 'ImageId': image.id, - 'MinCount': str(kwargs.get('ex_mincount', '1')), - 'MaxCount': str(kwargs.get('ex_maxcount', '1')), - 'InstanceType': size.id - } - - if 'ex_security_groups' in kwargs and 'ex_securitygroup' in kwargs: - raise ValueError('You can only supply ex_security_groups or' - ' ex_securitygroup') - - # ex_securitygroup is here for backward compatibility - ex_security_groups = kwargs.get('ex_security_groups', None) - ex_securitygroup = kwargs.get('ex_securitygroup', None) - security_groups = ex_security_groups or ex_securitygroup - - if security_groups: - if not isinstance(security_groups, (tuple, list)): - security_groups = [security_groups] - - for sig in range(len(security_groups)): - params['SecurityGroup.%d' % (sig + 1,)] =\ - security_groups[sig] - - if 'location' in kwargs: - availability_zone = getattr(kwargs['location'], - 'availability_zone', None) - if availability_zone: - if availability_zone.region_name != self.region_name: - raise AttributeError('Invalid availability zone: %s' - % (availability_zone.name)) - params['Placement.AvailabilityZone'] = availability_zone.name - - if 'auth' in kwargs and 'ex_keyname' in kwargs: - raise AttributeError('Cannot specify auth and ex_keyname together') - - if 'auth' in kwargs: - auth = self._get_and_check_auth(kwargs['auth']) - key = self.ex_find_or_import_keypair_by_key_material(auth.pubkey) - params['KeyName'] = key['keyName'] - - if 'ex_keyname' in kwargs: - params['KeyName'] = kwargs['ex_keyname'] - - if 'ex_userdata' in kwargs: - params['UserData'] = base64.b64encode(b(kwargs['ex_userdata']))\ - .decode('utf-8') - - if 'ex_clienttoken' in kwargs: - params['ClientToken'] = kwargs['ex_clienttoken'] - - if 'ex_blockdevicemappings' in kwargs: - params.update(self._get_block_device_mapping_params( - kwargs['ex_blockdevicemappings'])) - - if 'ex_iamprofile' in kwargs: - if not isinstance(kwargs['ex_iamprofile'], basestring): - raise AttributeError('ex_iamprofile not string') - - if kwargs['ex_iamprofile'].startswith('arn:aws:iam:'): - params['IamInstanceProfile.Arn'] = kwargs['ex_iamprofile'] - else: - params['IamInstanceProfile.Name'] = kwargs['ex_iamprofile'] - - if 'ex_ebs_optimized' in kwargs: - params['EbsOptimized'] = kwargs['ex_ebs_optimized'] - - if 'ex_subnet' in kwargs: - params['SubnetId'] = kwargs['ex_subnet'].id - - object = self.connection.request(self.path, params=params).object - nodes = self._to_nodes(object, 'instancesSet/item') - - for node in nodes: - tags = {'Name': kwargs['name']} - if 'ex_metadata' in kwargs: - tags.update(kwargs['ex_metadata']) - - try: - self.ex_create_tags(resource=node, tags=tags) - except Exception: - continue - - node.name = kwargs['name'] - node.extra.update({'tags': tags}) - - if len(nodes) == 1: - return nodes[0] - else: - return nodes - - def reboot_node(self, node): - params = {'Action': 'RebootInstances'} - params.update(self._pathlist('InstanceId', [node.id])) - res = self.connection.request(self.path, params=params).object - return self._get_boolean(res) - - def destroy_node(self, node): - params = {'Action': 'TerminateInstances'} - params.update(self._pathlist('InstanceId', [node.id])) - res = self.connection.request(self.path, params=params).object - return self._get_terminate_boolean(res) - - def create_volume(self, size, name, location=None, snapshot=None, - ex_volume_type='standard', ex_iops=None): - """ - :param location: Datacenter in which to create a volume in. - :type location: :class:`.ExEC2AvailabilityZone` - - :param ex_volume_type: Type of volume to create. - :type ex_volume_type: ``str`` - - :param iops: The number of I/O operations per second (IOPS) - that the volume supports. Only used if ex_volume_type - is io1. - :type iops: ``int`` - """ - valid_volume_types = ['standard', 'io1', 'g2'] - - params = { - 'Action': 'CreateVolume', - 'Size': str(size)} - - if ex_volume_type and ex_volume_type not in valid_volume_types: - raise ValueError('Invalid volume type specified: %s' % - (ex_volume_type)) - - if location is not None: - params['AvailabilityZone'] = location.availability_zone.name - - if ex_volume_type: - params['VolumeType'] = ex_volume_type - - if ex_volume_type == 'io1' and ex_iops: - params['Iops'] = ex_iops - - volume = self._to_volume( - self.connection.request(self.path, params=params).object, - name=name) - - if self.ex_create_tags(volume, {'Name': name}): - volume.extra['tags']['Name'] = name - - return volume - - def attach_volume(self, node, volume, device): - params = { - 'Action': 'AttachVolume', - 'VolumeId': volume.id, - 'InstanceId': node.id, - 'Device': device} - - self.connection.request(self.path, params=params) - return True - - def detach_volume(self, volume): - params = { - 'Action': 'DetachVolume', - 'VolumeId': volume.id} - - self.connection.request(self.path, params=params) - return True - - def destroy_volume(self, volume): - params = { - 'Action': 'DeleteVolume', - 'VolumeId': volume.id} - response = self.connection.request(self.path, params=params).object - return self._get_boolean(response) - - def create_volume_snapshot(self, volume, name=None): - """ - Create snapshot from volume - - :param volume: Instance of ``StorageVolume`` - :type volume: ``StorageVolume`` - - :param name: Name of snapshot - :type name: ``str`` - - :rtype: :class:`VolumeSnapshot` - """ - params = { - 'Action': 'CreateSnapshot', - 'VolumeId': volume.id, - } - - if name: - params.update({ - 'Description': name, - }) - response = self.connection.request(self.path, params=params).object - snapshot = self._to_snapshot(response, name) - - if name and self.ex_create_tags(snapshot, {'Name': name}): - snapshot.extra['tags']['Name'] = name - - return snapshot - - def list_volume_snapshots(self, snapshot): - return self.list_snapshots(snapshot) - - def list_snapshots(self, snapshot=None, owner=None): - """ - Describe all snapshots. - - :param snapshot: If provided, only return snapshot information for the - provided snapshot. - - :param owner: Owner for snapshot: self|amazon|ID - :type owner: ``str`` - - :rtype: ``list`` of :class:`VolumeSnapshot` - """ - params = { - 'Action': 'DescribeSnapshots', - } - if snapshot: - params.update({ - 'SnapshotId.1': snapshot.id, - }) - if owner: - params.update({ - 'Owner.1': owner, - }) - response = self.connection.request(self.path, params=params).object - snapshots = self._to_snapshots(response) - return snapshots - - def destroy_volume_snapshot(self, snapshot): - params = { - 'Action': 'DeleteSnapshot', - 'SnapshotId': snapshot.id - } - response = self.connection.request(self.path, params=params).object - return self._get_boolean(response) - - # Key pair management methods - - def list_key_pairs(self): - params = { - 'Action': 'DescribeKeyPairs' - } - - response = self.connection.request(self.path, params=params) - elems = findall(element=response.object, xpath='keySet/item', - namespace=NAMESPACE) - - key_pairs = self._to_key_pairs(elems=elems) - return key_pairs - - def get_key_pair(self, name): - params = { - 'Action': 'DescribeKeyPairs', - 'KeyName': name - } - - response = self.connection.request(self.path, params=params) - elems = findall(element=response.object, xpath='keySet/item', - namespace=NAMESPACE) - - key_pair = self._to_key_pairs(elems=elems)[0] - return key_pair - - def create_key_pair(self, name): - params = { - 'Action': 'CreateKeyPair', - 'KeyName': name - } - - response = self.connection.request(self.path, params=params) - elem = response.object - key_pair = self._to_key_pair(elem=elem) - return key_pair - - def import_key_pair_from_string(self, name, key_material): - base64key = ensure_string(base64.b64encode(b(key_material))) - - params = { - 'Action': 'ImportKeyPair', - 'KeyName': name, - 'PublicKeyMaterial': base64key - } - - response = self.connection.request(self.path, params=params) - elem = response.object - key_pair = self._to_key_pair(elem=elem) - return key_pair - - def delete_key_pair(self, key_pair): - params = { - 'Action': 'DeleteKeyPair', - 'KeyName': key_pair.name - } - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def copy_image(self, image, source_region, name=None, description=None): - """ - Copy an Amazon Machine Image from the specified source region - to the current region. - - @inherits: :class:`NodeDriver.copy_image` - - :param source_region: The region where the image resides - :type source_region: ``str`` - - :param image: Instance of class NodeImage - :type image: :class:`NodeImage` - - :param name: The name of the new image - :type name: ``str`` - - :param description: The description of the new image - :type description: ``str`` - - :return: Instance of class ``NodeImage`` - :rtype: :class:`NodeImage` - """ - params = {'Action': 'CopyImage', - 'SourceRegion': source_region, - 'SourceImageId': image.id} - - if name is not None: - params['Name'] = name - - if description is not None: - params['Description'] = description - - image = self._to_image( - self.connection.request(self.path, params=params).object) - - return image - - def create_image(self, node, name, description=None, reboot=False, - block_device_mapping=None): - """ - Create an Amazon Machine Image based off of an EBS-backed instance. - - @inherits: :class:`NodeDriver.create_image` - - :param node: Instance of ``Node`` - :type node: :class: `Node` - - :param name: The name for the new image - :type name: ``str`` - - :param block_device_mapping: A dictionary of the disk layout - An example of this dict is included - below. - :type block_device_mapping: ``list`` of ``dict`` - - :param reboot: Whether or not to shutdown the instance before - creation. Amazon calls this NoReboot and - sets it to false by default to ensure a - clean image. - :type reboot: ``bool`` - - :param description: An optional description for the new image - :type description: ``str`` - - An example block device mapping dictionary is included: - - mapping = [{'VirtualName': None, - 'Ebs': {'VolumeSize': 10, - 'VolumeType': 'standard', - 'DeleteOnTermination': 'true'}, - 'DeviceName': '/dev/sda1'}] - - :return: Instance of class ``NodeImage`` - :rtype: :class:`NodeImage` - """ - params = {'Action': 'CreateImage', - 'InstanceId': node.id, - 'Name': name, - 'NoReboot': not reboot} - - if description is not None: - params['Description'] = description - - if block_device_mapping is not None: - params.update(self._get_block_device_mapping_params( - block_device_mapping)) - - image = self._to_image( - self.connection.request(self.path, params=params).object) - - return image - - def delete_image(self, image): - """ - Deletes an image at Amazon given a NodeImage object - - @inherits: :class:`NodeDriver.delete_image` - - :param image: Instance of ``NodeImage`` - :type image: :class: `NodeImage` - - :rtype: ``bool`` - """ - params = {'Action': 'DeregisterImage', - 'ImageId': image.id} - - response = self.connection.request(self.path, params=params).object - return self._get_boolean(response) - - def ex_register_image(self, name, description=None, architecture=None, - image_location=None, root_device_name=None, - block_device_mapping=None, kernel_id=None, - ramdisk_id=None): - """ - Registers an Amazon Machine Image based off of an EBS-backed instance. - Can also be used to create images from snapshots. More information - can be found at http://goo.gl/hqZq0a. - - :param name: The name for the AMI being registered - :type name: ``str`` - - :param description: The description of the AMI (optional) - :type description: ``str`` - - :param architecture: The architecture of the AMI (i386/x86_64) - (optional) - :type architecture: ``str`` - - :param image_location: The location of the AMI within Amazon S3 - Required if registering an instance - store-backed AMI - :type image_location: ``str`` - - :param root_device_name: The device name for the root device - Required if registering a EBS-backed AMI - :type root_device_name: ``str`` - - :param block_device_mapping: A dictionary of the disk layout - (optional) - :type block_device_mapping: ``dict`` - - :param kernel_id: Kernel id for AMI (optional) - :type kernel_id: ``str`` - - :param ramdisk_id: RAM disk for AMI (optional) - :type ramdisk_id: ``str`` - - :rtype: :class:`NodeImage` - """ - - params = {'Action': 'RegisterImage', - 'Name': name} - - if description is not None: - params['Description'] = description - - if architecture is not None: - params['Architecture'] = architecture - - if image_location is not None: - params['ImageLocation'] = image_location - - if root_device_name is not None: - params['RootDeviceName'] = root_device_name - - if block_device_mapping is not None: - params.update(self._get_block_device_mapping_params( - block_device_mapping)) - - if kernel_id is not None: - params['KernelId'] = kernel_id - - if ramdisk_id is not None: - params['RamDiskId'] = ramdisk_id - - image = self._to_image( - self.connection.request(self.path, params=params).object - ) - return image - - def ex_list_networks(self, network_ids=None, filters=None): - """ - Return a list of :class:`EC2Network` objects for the - current region. - - :param network_ids: Return only networks matching the provided - network IDs. If not specified, a list of all - the networks in the corresponding region - is returned. - :type network_ids: ``list`` - - :param filters: The filters so that the response includes - information for only certain networks. - :type filters: ``dict`` - - :rtype: ``list`` of :class:`EC2Network` - """ - params = {'Action': 'DescribeVpcs'} - - if network_ids: - params.update(self._pathlist('VpcId', network_ids)) - - if filters: - params.update(self._build_filters(filters)) - - return self._to_networks( - self.connection.request(self.path, params=params).object - ) - - def ex_create_network(self, cidr_block, name=None, - instance_tenancy='default'): - """ - Create a network/VPC - - :param cidr_block: The CIDR block assigned to the network - :type cidr_block: ``str`` - - :param name: An optional name for the network - :type name: ``str`` - - :param instance_tenancy: The allowed tenancy of instances launched - into the VPC. - Valid values: default/dedicated - :type instance_tenancy: ``str`` - - :return: Dictionary of network properties - :rtype: ``dict`` - """ - params = {'Action': 'CreateVpc', - 'CidrBlock': cidr_block, - 'InstanceTenancy': instance_tenancy} - - response = self.connection.request(self.path, params=params).object - element = response.findall(fixxpath(xpath='vpc', - namespace=NAMESPACE))[0] - - network = self._to_network(element, name) - - if name and self.ex_create_tags(network, {'Name': name}): - network.extra['tags']['Name'] = name - - return network - - def ex_delete_network(self, vpc): - """ - Deletes a network/VPC. - - :param vpc: VPC to delete. - :type vpc: :class:`.EC2Network` - - :rtype: ``bool`` - """ - params = {'Action': 'DeleteVpc', 'VpcId': vpc.id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_list_subnets(self, subnet_ids=None, filters=None): - """ - Return a list of :class:`EC2NetworkSubnet` objects for the - current region. - - :param subnet_ids: Return only subnets matching the provided - subnet IDs. If not specified, a list of all - the subnets in the corresponding region - is returned. - :type subnet_ids: ``list`` - - :param filters: The filters so that the response includes - information for only certain subnets. - :type filters: ``dict`` - - :rtype: ``list`` of :class:`EC2NetworkSubnet` - """ - params = {'Action': 'DescribeSubnets'} - - if subnet_ids: - params.update(self._pathlist('SubnetId', subnet_ids)) - - if filters: - params.update(self._build_filters(filters)) - - return self._to_subnets( - self.connection.request(self.path, params=params).object - ) - - def ex_create_subnet(self, vpc_id, cidr_block, - availability_zone, name=None): - """ - Create a network subnet within a VPC - - :param vpc_id: The ID of the VPC that the subnet should be - associated with - :type vpc_id: ``str`` - - :param cidr_block: The CIDR block assigned to the subnet - :type cidr_block: ``str`` - - :param availability_zone: The availability zone where the subnet - should reside - :type availability_zone: ``str`` - - :param name: An optional name for the network - :type name: ``str`` - - :rtype: :class: `EC2NetworkSubnet` - """ - params = {'Action': 'CreateSubnet', - 'VpcId': vpc_id, - 'CidrBlock': cidr_block, - 'AvailabilityZone': availability_zone} - - response = self.connection.request(self.path, params=params).object - element = response.findall(fixxpath(xpath='subnet', - namespace=NAMESPACE))[0] - - subnet = self._to_subnet(element, name) - - if name and self.ex_create_tags(subnet, {'Name': name}): - subnet.extra['tags']['Name'] = name - - return subnet - - def ex_delete_subnet(self, subnet): - """ - Deletes a VPC subnet. - - :param subnet: The subnet to delete - :type subnet: :class:`.EC2NetworkSubnet` - - :rtype: ``bool`` - """ - params = {'Action': 'DeleteSubnet', 'SubnetId': subnet.id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_list_security_groups(self): - """ - List existing Security Groups. - - @note: This is a non-standard extension API, and only works for EC2. - - :rtype: ``list`` of ``str`` - """ - params = {'Action': 'DescribeSecurityGroups'} - response = self.connection.request(self.path, params=params).object - - groups = [] - for group in findall(element=response, xpath='securityGroupInfo/item', - namespace=NAMESPACE): - name = findtext(element=group, xpath='groupName', - namespace=NAMESPACE) - groups.append(name) - - return groups - - def ex_get_security_groups(self, group_ids=None, - group_names=None, filters=None): - """ - Return a list of :class:`EC2SecurityGroup` objects for the - current region. - - :param group_ids: Return only groups matching the provided - group IDs. - :type group_ids: ``list`` - - :param group_names: Return only groups matching the provided - group names. - :type group_ids: ``list`` - - :param filters: The filters so that the response includes - information for only specific security groups. - :type filters: ``dict`` - - :rtype: ``list`` of :class:`EC2SecurityGroup` - """ - - params = {'Action': 'DescribeSecurityGroups'} - - if group_ids: - params.update(self._pathlist('GroupId', group_ids)) - - if group_names: - for name_idx, group_name in enumerate(group_names): - name_idx += 1 # We want 1-based indexes - name_key = 'GroupName.%s' % (name_idx) - params[name_key] = group_name - - if filters: - params.update(self._build_filters(filters)) - - response = self.connection.request(self.path, params=params) - return self._to_security_groups(response.object) - - def ex_create_security_group(self, name, description, vpc_id=None): - """ - Creates a new Security Group in EC2-Classic or a targeted VPC. - - :param name: The name of the security group to Create. - This must be unique. - :type name: ``str`` - - :param description: Human readable description of a Security - Group. - :type description: ``str`` - - :param vpc_id: Optional identifier for VPC networks - :type vpc_id: ``str`` - - :rtype: ``dict`` - """ - params = {'Action': 'CreateSecurityGroup', - 'GroupName': name, - 'GroupDescription': description} - - if vpc_id is not None: - params['VpcId'] = vpc_id - - response = self.connection.request(self.path, params=params).object - group_id = findattr(element=response, xpath='groupId', - namespace=NAMESPACE) - return { - 'group_id': group_id - } - - def ex_delete_security_group_by_id(self, group_id): - """ - Deletes a new Security Group using the group id. - - :param group_id: The ID of the security group - :type group_id: ``str`` - - :rtype: ``bool`` - """ - params = {'Action': 'DeleteSecurityGroup', 'GroupId': group_id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_delete_security_group_by_name(self, group_name): - """ - Deletes a new Security Group using the group name. - - :param group_name: The name of the security group - :type group_name: ``str`` - - :rtype: ``bool`` - """ - params = {'Action': 'DeleteSecurityGroup', 'GroupName': group_name} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_delete_security_group(self, name): - """ - Wrapper method which calls ex_delete_security_group_by_name. - - :param name: The name of the security group - :type name: ``str`` - - :rtype: ``bool`` - """ - return self.ex_delete_security_group_by_name(name) - - def ex_authorize_security_group(self, name, from_port, to_port, cidr_ip, - protocol='tcp'): - """ - Edit a Security Group to allow specific traffic. - - @note: This is a non-standard extension API, and only works for EC2. - - :param name: The name of the security group to edit - :type name: ``str`` - - :param from_port: The beginning of the port range to open - :type from_port: ``str`` - - :param to_port: The end of the port range to open - :type to_port: ``str`` - - :param cidr_ip: The ip to allow traffic for. - :type cidr_ip: ``str`` - - :param protocol: tcp/udp/icmp - :type protocol: ``str`` - - :rtype: ``bool`` - """ - - params = {'Action': 'AuthorizeSecurityGroupIngress', - 'GroupName': name, - 'IpProtocol': protocol, - 'FromPort': str(from_port), - 'ToPort': str(to_port), - 'CidrIp': cidr_ip} - try: - res = self.connection.request( - self.path, params=params.copy()).object - return self._get_boolean(res) - except Exception: - e = sys.exc_info()[1] - if e.args[0].find('InvalidPermission.Duplicate') == -1: - raise e - - def ex_authorize_security_group_ingress(self, id, from_port, to_port, - cidr_ips=None, group_pairs=None, - protocol='tcp'): - """ - Edit a Security Group to allow specific ingress traffic using - CIDR blocks or either a group ID, group name or user ID (account). - - :param id: The id of the security group to edit - :type id: ``str`` - - :param from_port: The beginning of the port range to open - :type from_port: ``int`` - - :param to_port: The end of the port range to open - :type to_port: ``int`` - - :param cidr_ips: The list of ip ranges to allow traffic for. - :type cidr_ips: ``list`` - - :param group_pairs: Source user/group pairs to allow traffic for. - More info can be found at http://goo.gl/stBHJF - - EC2 Classic Example: To allow access from any system - associated with the default group on account 1234567890 - - [{'group_name': 'default', 'user_id': '1234567890'}] - - VPC Example: Allow access from any system associated with - security group sg-47ad482e on your own account - - [{'group_id': ' sg-47ad482e'}] - :type group_pairs: ``list`` of ``dict`` - - :param protocol: tcp/udp/icmp - :type protocol: ``str`` - - :rtype: ``bool`` - """ - - params = self._get_common_security_group_params(id, - protocol, - from_port, - to_port, - cidr_ips, - group_pairs) - - params["Action"] = 'AuthorizeSecurityGroupIngress' - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_authorize_security_group_egress(self, id, from_port, to_port, - cidr_ips, group_pairs=None, - protocol='tcp'): - """ - Edit a Security Group to allow specific egress traffic using - CIDR blocks or either a group ID, group name or user ID (account). - This call is not supported for EC2 classic and only works for VPC - groups. - - :param id: The id of the security group to edit - :type id: ``str`` - - :param from_port: The beginning of the port range to open - :type from_port: ``int`` - - :param to_port: The end of the port range to open - :type to_port: ``int`` - - :param cidr_ips: The list of ip ranges to allow traffic for. - :type cidr_ips: ``list`` - - :param group_pairs: Source user/group pairs to allow traffic for. - More info can be found at http://goo.gl/stBHJF - - EC2 Classic Example: To allow access from any system - associated with the default group on account 1234567890 - - [{'group_name': 'default', 'user_id': '1234567890'}] - - VPC Example: Allow access from any system associated with - security group sg-47ad482e on your own account - - [{'group_id': ' sg-47ad482e'}] - :type group_pairs: ``list`` of ``dict`` - - :param protocol: tcp/udp/icmp - :type protocol: ``str`` - - :rtype: ``bool`` - """ - - params = self._get_common_security_group_params(id, - protocol, - from_port, - to_port, - cidr_ips, - group_pairs) - - params["Action"] = 'AuthorizeSecurityGroupEgress' - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_revoke_security_group_ingress(self, id, from_port, to_port, - cidr_ips=None, group_pairs=None, - protocol='tcp'): - """ - Edit a Security Group to revoke specific ingress traffic using - CIDR blocks or either a group ID, group name or user ID (account). - - :param id: The id of the security group to edit - :type id: ``str`` - - :param from_port: The beginning of the port range to open - :type from_port: ``int`` - - :param to_port: The end of the port range to open - :type to_port: ``int`` - - :param cidr_ips: The list of ip ranges to allow traffic for. - :type cidr_ips: ``list`` - - :param group_pairs: Source user/group pairs to allow traffic for. - More info can be found at http://goo.gl/stBHJF - - EC2 Classic Example: To allow access from any system - associated with the default group on account 1234567890 - - [{'group_name': 'default', 'user_id': '1234567890'}] - - VPC Example: Allow access from any system associated with - security group sg-47ad482e on your own account - - [{'group_id': ' sg-47ad482e'}] - :type group_pairs: ``list`` of ``dict`` - - :param protocol: tcp/udp/icmp - :type protocol: ``str`` - - :rtype: ``bool`` - """ - - params = self._get_common_security_group_params(id, - protocol, - from_port, - to_port, - cidr_ips, - group_pairs) - - params["Action"] = 'RevokeSecurityGroupIngress' - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_revoke_security_group_egress(self, id, from_port, to_port, - cidr_ips=None, group_pairs=None, - protocol='tcp'): - """ - Edit a Security Group to revoke specific egress traffic using - CIDR blocks or either a group ID, group name or user ID (account). - This call is not supported for EC2 classic and only works for - VPC groups. - - :param id: The id of the security group to edit - :type id: ``str`` - - :param from_port: The beginning of the port range to open - :type from_port: ``int`` - - :param to_port: The end of the port range to open - :type to_port: ``int`` - - :param cidr_ips: The list of ip ranges to allow traffic for. - :type cidr_ips: ``list`` - - :param group_pairs: Source user/group pairs to allow traffic for. - More info can be found at http://goo.gl/stBHJF - - EC2 Classic Example: To allow access from any system - associated with the default group on account 1234567890 - - [{'group_name': 'default', 'user_id': '1234567890'}] - - VPC Example: Allow access from any system associated with - security group sg-47ad482e on your own account - - [{'group_id': ' sg-47ad482e'}] - :type group_pairs: ``list`` of ``dict`` - - :param protocol: tcp/udp/icmp - :type protocol: ``str`` - - :rtype: ``bool`` - """ - - params = self._get_common_security_group_params(id, - protocol, - from_port, - to_port, - cidr_ips, - group_pairs) - - params['Action'] = 'RevokeSecurityGroupEgress' - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_authorize_security_group_permissive(self, name): - """ - Edit a Security Group to allow all traffic. - - @note: This is a non-standard extension API, and only works for EC2. - - :param name: The name of the security group to edit - :type name: ``str`` - - :rtype: ``list`` of ``str`` - """ - - results = [] - params = {'Action': 'AuthorizeSecurityGroupIngress', - 'GroupName': name, - 'IpProtocol': 'tcp', - 'FromPort': '0', - 'ToPort': '65535', - 'CidrIp': '0.0.0.0/0'} - try: - results.append( - self.connection.request(self.path, params=params.copy()).object - ) - except Exception: - e = sys.exc_info()[1] - if e.args[0].find("InvalidPermission.Duplicate") == -1: - raise e - params['IpProtocol'] = 'udp' - - try: - results.append( - self.connection.request(self.path, params=params.copy()).object - ) - except Exception: - e = sys.exc_info()[1] - if e.args[0].find("InvalidPermission.Duplicate") == -1: - raise e - - params.update({'IpProtocol': 'icmp', 'FromPort': '-1', 'ToPort': '-1'}) - - try: - results.append( - self.connection.request(self.path, params=params.copy()).object - ) - except Exception: - e = sys.exc_info()[1] - - if e.args[0].find("InvalidPermission.Duplicate") == -1: - raise e - return results - - def ex_list_availability_zones(self, only_available=True): - """ - Return a list of :class:`ExEC2AvailabilityZone` objects for the - current region. - - Note: This is an extension method and is only available for EC2 - driver. - - :keyword only_available: If true, return only availability zones - with state 'available' - :type only_available: ``str`` - - :rtype: ``list`` of :class:`ExEC2AvailabilityZone` - """ - params = {'Action': 'DescribeAvailabilityZones'} - - filters = {'region-name': self.region_name} - if only_available: - filters['state'] = 'available' - - params.update(self._build_filters(filters)) - - result = self.connection.request(self.path, - params=params.copy()).object - - availability_zones = [] - for element in findall(element=result, - xpath='availabilityZoneInfo/item', - namespace=NAMESPACE): - name = findtext(element=element, xpath='zoneName', - namespace=NAMESPACE) - zone_state = findtext(element=element, xpath='zoneState', - namespace=NAMESPACE) - region_name = findtext(element=element, xpath='regionName', - namespace=NAMESPACE) - - availability_zone = ExEC2AvailabilityZone( - name=name, - zone_state=zone_state, - region_name=region_name - ) - availability_zones.append(availability_zone) - - return availability_zones - - def ex_describe_tags(self, resource): - """ - Return a dictionary of tags for a resource (Node or StorageVolume). - - :param resource: resource which should be used - :type resource: :class:`Node` or :class:`StorageVolume` - - :return: dict Node tags - :rtype: ``dict`` - """ - params = {'Action': 'DescribeTags'} - - filters = { - 'resource-id': resource.id, - 'resource-type': 'instance' - } - - params.update(self._build_filters(filters)) - - result = self.connection.request(self.path, params=params).object - - return self._get_resource_tags(result) - - def ex_create_tags(self, resource, tags): - """ - Create tags for a resource (Node or StorageVolume). - - :param resource: Resource to be tagged - :type resource: :class:`Node` or :class:`StorageVolume` - - :param tags: A dictionary or other mapping of strings to strings, - associating tag names with tag values. - :type tags: ``dict`` - - :rtype: ``bool`` - """ - if not tags: - return - - params = {'Action': 'CreateTags', - 'ResourceId.0': resource.id} - for i, key in enumerate(tags): - params['Tag.%d.Key' % i] = key - params['Tag.%d.Value' % i] = tags[key] - - res = self.connection.request(self.path, - params=params.copy()).object - - return self._get_boolean(res) - - def ex_delete_tags(self, resource, tags): - """ - Delete tags from a resource. - - :param resource: Resource to be tagged - :type resource: :class:`Node` or :class:`StorageVolume` - - :param tags: A dictionary or other mapping of strings to strings, - specifying the tag names and tag values to be deleted. - :type tags: ``dict`` - - :rtype: ``bool`` - """ - if not tags: - return - - params = {'Action': 'DeleteTags', - 'ResourceId.0': resource.id} - for i, key in enumerate(tags): - params['Tag.%d.Key' % i] = key - params['Tag.%d.Value' % i] = tags[key] - - res = self.connection.request(self.path, - params=params.copy()).object - - return self._get_boolean(res) - - def ex_get_metadata_for_node(self, node): - """ - Return the metadata associated with the node. - - :param node: Node instance - :type node: :class:`Node` - - :return: A dictionary or other mapping of strings to strings, - associating tag names with tag values. - :rtype tags: ``dict`` - """ - return node.extra['tags'] - - def ex_allocate_address(self, domain='standard'): - """ - Allocate a new Elastic IP address for EC2 classic or VPC - - :param domain: The domain to allocate the new address in - (standard/vpc) - :type domain: ``str`` - - :return: Instance of ElasticIP - :rtype: :class:`ElasticIP` - """ - params = {'Action': 'AllocateAddress'} - - if domain == 'vpc': - params['Domain'] = domain - - response = self.connection.request(self.path, params=params).object - - return self._to_address(response, only_associated=False) - - def ex_release_address(self, elastic_ip, domain=None): - """ - Release an Elastic IP address using the IP (EC2-Classic) or - using the allocation ID (VPC) - - :param elastic_ip: Elastic IP instance - :type elastic_ip: :class:`ElasticIP` - - :param domain: The domain where the IP resides (vpc only) - :type domain: ``str`` - - :return: True on success, False otherwise. - :rtype: ``bool`` - """ - params = {'Action': 'ReleaseAddress'} - - if domain is not None and domain != 'vpc': - raise AttributeError('Domain can only be set to vpc') - - if domain is None: - params['PublicIp'] = elastic_ip.ip - else: - params['AllocationId'] = elastic_ip.extra['allocation_id'] - - response = self.connection.request(self.path, params=params).object - return self._get_boolean(response) - - def ex_describe_all_addresses(self, only_associated=False): - """ - Return all the Elastic IP addresses for this account - optionally, return only addresses associated with nodes - - :param only_associated: If true, return only those addresses - that are associated with an instance. - :type only_associated: ``bool`` - - :return: List of ElasticIP instances. - :rtype: ``list`` of :class:`ElasticIP` - """ - params = {'Action': 'DescribeAddresses'} - - response = self.connection.request(self.path, params=params).object - - # We will send our only_associated boolean over to - # shape how the return data is sent back - return self._to_addresses(response, only_associated) - - def ex_associate_address_with_node(self, node, elastic_ip, domain=None): - """ - Associate an Elastic IP address with a particular node. - - :param node: Node instance - :type node: :class:`Node` - - :param elastic_ip: Elastic IP instance - :type elastic_ip: :class:`ElasticIP` - - :param domain: The domain where the IP resides (vpc only) - :type domain: ``str`` - - :return: A string representation of the association ID which is - required for VPC disassociation. EC2/standard - addresses return None - :rtype: ``None`` or ``str`` - """ - params = {'Action': 'AssociateAddress', 'InstanceId': node.id} - - if domain is not None and domain != 'vpc': - raise AttributeError('Domain can only be set to vpc') - - if domain is None: - params.update({'PublicIp': elastic_ip.ip}) - else: - params.update({'AllocationId': elastic_ip.extra['allocation_id']}) - - response = self.connection.request(self.path, params=params).object - association_id = findtext(element=response, - xpath='associationId', - namespace=NAMESPACE) - return association_id - - def ex_associate_addresses(self, node, elastic_ip, domain=None): - """ - Note: This method has been deprecated in favor of - the ex_associate_address_with_node method. - """ - - return self.ex_associate_address_with_node(node=node, - elastic_ip=elastic_ip, - domain=domain) - - def ex_disassociate_address(self, elastic_ip, domain=None): - """ - Disassociate an Elastic IP address using the IP (EC2-Classic) - or the association ID (VPC) - - :param elastic_ip: ElasticIP instance - :type elastic_ip: :class:`ElasticIP` - - :param domain: The domain where the IP resides (vpc only) - :type domain: ``str`` - - :return: True on success, False otherwise. - :rtype: ``bool`` - """ - params = {'Action': 'DisassociateAddress'} - - if domain is not None and domain != 'vpc': - raise AttributeError('Domain can only be set to vpc') - - if domain is None: - params['PublicIp'] = elastic_ip.ip - - else: - params['AssociationId'] = elastic_ip.extra['association_id'] - - res = self.connection.request(self.path, params=params).object - return self._get_boolean(res) - - def ex_describe_addresses(self, nodes): - """ - Return Elastic IP addresses for all the nodes in the provided list. - - :param nodes: List of :class:`Node` instances - :type nodes: ``list`` of :class:`Node` - - :return: Dictionary where a key is a node ID and the value is a - list with the Elastic IP addresses associated with - this node. - :rtype: ``dict`` - """ - if not nodes: - return {} - - params = {'Action': 'DescribeAddresses'} - - if len(nodes) == 1: - self._add_instance_filter(params, nodes[0]) - - result = self.connection.request(self.path, params=params).object - - node_instance_ids = [node.id for node in nodes] - nodes_elastic_ip_mappings = {} - - # We will set only_associated to True so that we only get back - # IPs which are associated with instances - only_associated = True - - for node_id in node_instance_ids: - nodes_elastic_ip_mappings.setdefault(node_id, []) - for addr in self._to_addresses(result, - only_associated): - - instance_id = addr.instance_id - - if node_id == instance_id: - nodes_elastic_ip_mappings[instance_id].append( - addr.ip) - - return nodes_elastic_ip_mappings - - def ex_describe_addresses_for_node(self, node): - """ - Return a list of Elastic IP addresses associated with this node. - - :param node: Node instance - :type node: :class:`Node` - - :return: list Elastic IP addresses attached to this node. - :rtype: ``list`` of ``str`` - """ - node_elastic_ips = self.ex_describe_addresses([node]) - return node_elastic_ips[node.id] - - # Network interface management methods - - def ex_list_network_interfaces(self): - """ - Return all network interfaces - - :return: List of EC2NetworkInterface instances - :rtype: ``list`` of :class `EC2NetworkInterface` - """ - params = {'Action': 'DescribeNetworkInterfaces'} - - return self._to_interfaces( - self.connection.request(self.path, params=params).object - ) - - def ex_create_network_interface(self, subnet, name=None, - description=None, - private_ip_address=None): - """ - Create a network interface within a VPC subnet. - - :param subnet: EC2NetworkSubnet instance - :type subnet: :class:`EC2NetworkSubnet` - - :param name: Optional name of the interface - :type name: ``str`` - - :param description: Optional description of the network interface - :type description: ``str`` - - :param private_ip_address: Optional address to assign as the - primary private IP address of the - interface. If one is not provided then - Amazon will automatically auto-assign - an available IP. EC2 allows assignment - of multiple IPs, but this will be - the primary. - :type private_ip_address: ``str`` - - :return: EC2NetworkInterface instance - :rtype: :class `EC2NetworkInterface` - """ - params = {'Action': 'CreateNetworkInterface', - 'SubnetId': subnet.id} - - if description: - params['Description'] = description - - if private_ip_address: - params['PrivateIpAddress'] = private_ip_address - - response = self.connection.request(self.path, params=params).object - - element = response.findall(fixxpath(xpath='networkInterface', - namespace=NAMESPACE))[0] - - interface = self._to_interface(element, name) - - if name and self.ex_create_tags(interface, {'Name': name}): - interface.extra['tags']['Name'] = name - - return interface - - def ex_delete_network_interface(self, network_interface): - """ - Deletes a network interface. - - :param network_interface: EC2NetworkInterface instance - :type network_interface: :class:`EC2NetworkInterface` - - :rtype: ``bool`` - """ - params = {'Action': 'DeleteNetworkInterface', - 'NetworkInterfaceId': network_interface.id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_attach_network_interface_to_node(self, network_interface, - node, device_index): - """ - Attatch a network interface to an instance. - - :param network_interface: EC2NetworkInterface instance - :type network_interface: :class:`EC2NetworkInterface` - - :param node: Node instance - :type node: :class:`Node` - - :param device_index: The interface device index - :type device_index: ``int`` - - :return: String representation of the attachment id. - This is required to detach the interface. - :rtype: ``str`` - """ - params = {'Action': 'AttachNetworkInterface', - 'NetworkInterfaceId': network_interface.id, - 'InstanceId': node.id, - 'DeviceIndex': device_index} - - response = self.connection.request(self.path, params=params).object - attachment_id = findattr(element=response, xpath='attachmentId', - namespace=NAMESPACE) - - return attachment_id - - def ex_detach_network_interface(self, attachment_id, force=False): - """ - Detatch a network interface from an instance. - - :param attachment_id: The attachment ID associated with the - interface - :type attachment_id: ``str`` - - :param force: Forces the detachment. - :type force: ``bool`` - - :return: ``True`` on successful detachment, ``False`` otherwise. - :rtype: ``bool`` - """ - params = {'Action': 'DetachNetworkInterface', - 'AttachmentId': attachment_id} - - if force: - params['Force'] = True - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_modify_instance_attribute(self, node, attributes): - """ - Modify node attributes. - A list of valid attributes can be found at http://goo.gl/gxcj8 - - :param node: Node instance - :type node: :class:`Node` - - :param attributes: Dictionary with node attributes - :type attributes: ``dict`` - - :return: True on success, False otherwise. - :rtype: ``bool`` - """ - attributes = attributes or {} - attributes.update({'InstanceId': node.id}) - - params = {'Action': 'ModifyInstanceAttribute'} - params.update(attributes) - - res = self.connection.request(self.path, - params=params.copy()).object - - return self._get_boolean(res) - - def ex_modify_image_attribute(self, image, attributes): - """ - Modify image attributes. - - :param image: NodeImage instance - :type image: :class:`NodeImage` - - :param attributes: Dictionary with node attributes - :type attributes: ``dict`` - - :return: True on success, False otherwise. - :rtype: ``bool`` - """ - attributes = attributes or {} - attributes.update({'ImageId': image.id}) - - params = {'Action': 'ModifyImageAttribute'} - params.update(attributes) - - res = self.connection.request(self.path, - params=params.copy()).object - - return self._get_boolean(res) - - def ex_change_node_size(self, node, new_size): - """ - Change the node size. - Note: Node must be turned of before changing the size. - - :param node: Node instance - :type node: :class:`Node` - - :param new_size: NodeSize intance - :type new_size: :class:`NodeSize` - - :return: True on success, False otherwise. - :rtype: ``bool`` - """ - if 'instancetype' in node.extra: - current_instance_type = node.extra['instancetype'] - - if current_instance_type == new_size.id: - raise ValueError('New instance size is the same as' + - 'the current one') - - attributes = {'InstanceType.Value': new_size.id} - return self.ex_modify_instance_attribute(node, attributes) - - def ex_start_node(self, node): - """ - Start the node by passing in the node object, does not work with - instance store backed instances - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - params = {'Action': 'StartInstances'} - params.update(self._pathlist('InstanceId', [node.id])) - res = self.connection.request(self.path, params=params).object - return self._get_state_boolean(res) - - def ex_stop_node(self, node): - """ - Stop the node by passing in the node object, does not work with - instance store backed instances - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - params = {'Action': 'StopInstances'} - params.update(self._pathlist('InstanceId', [node.id])) - res = self.connection.request(self.path, params=params).object - return self._get_state_boolean(res) - - def ex_get_console_output(self, node): - """ - Get console output for the node. - - :param node: Node which should be used - :type node: :class:`Node` - - :return: Dictionary with the following keys: - - instance_id (``str``) - - timestamp (``datetime.datetime``) - ts of the last output - - output (``str``) - console output - :rtype: ``dict`` - """ - params = { - 'Action': 'GetConsoleOutput', - 'InstanceId': node.id - } - - response = self.connection.request(self.path, params=params).object - - timestamp = findattr(element=response, - xpath='timestamp', - namespace=NAMESPACE) - - encoded_string = findattr(element=response, - xpath='output', - namespace=NAMESPACE) - - timestamp = parse_date(timestamp) - output = base64.b64decode(b(encoded_string)).decode('utf-8') - - return {'instance_id': node.id, - 'timestamp': timestamp, - 'output': output} - - def ex_list_reserved_nodes(self): - """ - List all reserved instances/nodes which can be purchased from Amazon - for one or three year terms. Reservations are made at a region level - and reduce the hourly charge for instances. - - More information can be found at http://goo.gl/ulXCC7. - - :rtype: ``list`` of :class:`.EC2ReservedNode` - """ - params = {'Action': 'DescribeReservedInstances'} - - response = self.connection.request(self.path, params=params).object - - return self._to_reserved_nodes(response, 'reservedInstancesSet/item') - - # Account specific methods - - def ex_get_limits(self): - """ - Retrieve account resource limits. - - :rtype: ``dict`` - """ - attributes = ['max-instances', 'max-elastic-ips', - 'vpc-max-elastic-ips'] - params = {} - params['Action'] = 'DescribeAccountAttributes' - - for index, attribute in enumerate(attributes): - params['AttributeName.%s' % (index)] = attribute - - response = self.connection.request(self.path, params=params) - data = response.object - - elems = data.findall(fixxpath(xpath='accountAttributeSet/item', - namespace=NAMESPACE)) - - result = {'resource': {}} - - for elem in elems: - name = findtext(element=elem, xpath='attributeName', - namespace=NAMESPACE) - value = findtext(element=elem, - xpath='attributeValueSet/item/attributeValue', - namespace=NAMESPACE) - - result['resource'][name] = int(value) - - return result - - # Deprecated extension methods - - def ex_list_keypairs(self): - """ - Lists all the keypair names and fingerprints. - - :rtype: ``list`` of ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'list_key_pairs method') - - key_pairs = self.list_key_pairs() - - result = [] - - for key_pair in key_pairs: - item = { - 'keyName': key_pair.name, - 'keyFingerprint': key_pair.fingerprint, - } - result.append(item) - - return result - - def ex_describe_all_keypairs(self): - """ - Return names for all the available key pairs. - - @note: This is a non-standard extension API, and only works for EC2. - - :rtype: ``list`` of ``str`` - """ - names = [key_pair.name for key_pair in self.list_key_pairs()] - return names - - def ex_describe_keypairs(self, name): - """ - Here for backward compatibility. - """ - return self.ex_describe_keypair(name=name) - - def ex_describe_keypair(self, name): - """ - Describes a keypair by name. - - @note: This is a non-standard extension API, and only works for EC2. - - :param name: The name of the keypair to describe. - :type name: ``str`` - - :rtype: ``dict`` - """ - - params = { - 'Action': 'DescribeKeyPairs', - 'KeyName.1': name - } - - response = self.connection.request(self.path, params=params).object - key_name = findattr(element=response, xpath='keySet/item/keyName', - namespace=NAMESPACE) - fingerprint = findattr(element=response, - xpath='keySet/item/keyFingerprint', - namespace=NAMESPACE).strip() - return { - 'keyName': key_name, - 'keyFingerprint': fingerprint - } - - def ex_create_keypair(self, name): - """ - Creates a new keypair - - @note: This is a non-standard extension API, and only works for EC2. - - :param name: The name of the keypair to Create. This must be - unique, otherwise an InvalidKeyPair.Duplicate exception is raised. - :type name: ``str`` - - :rtype: ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'create_key_pair method') - - key_pair = self.create_key_pair(name=name) - - result = { - 'keyMaterial': key_pair.private_key, - 'keyFingerprint': key_pair.fingerprint - } - - return result - - def ex_delete_keypair(self, keypair): - """ - Delete a key pair by name. - - @note: This is a non-standard extension API, and only works with EC2. - - :param keypair: The name of the keypair to delete. - :type keypair: ``str`` - - :rtype: ``bool`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'delete_key_pair method') - - keypair = KeyPair(name=keypair, public_key=None, fingerprint=None, - driver=self) - - return self.delete_key_pair(keypair) - - def ex_import_keypair_from_string(self, name, key_material): - """ - imports a new public key where the public key is passed in as a string - - @note: This is a non-standard extension API, and only works for EC2. - - :param name: The name of the public key to import. This must be - unique, otherwise an InvalidKeyPair.Duplicate exception is raised. - :type name: ``str`` - - :param key_material: The contents of a public key file. - :type key_material: ``str`` - - :rtype: ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'import_key_pair_from_string method') - - key_pair = self.import_key_pair_from_string(name=name, - key_material=key_material) - - result = { - 'keyName': key_pair.name, - 'keyFingerprint': key_pair.fingerprint - } - return result - - def ex_import_keypair(self, name, keyfile): - """ - imports a new public key where the public key is passed via a filename - - @note: This is a non-standard extension API, and only works for EC2. - - :param name: The name of the public key to import. This must be - unique, otherwise an InvalidKeyPair.Duplicate exception is raised. - :type name: ``str`` - - :param keyfile: The filename with path of the public key to import. - :type keyfile: ``str`` - - :rtype: ``dict`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'import_key_pair_from_file method') - - key_pair = self.import_key_pair_from_file(name=name, - key_file_path=keyfile) - - result = { - 'keyName': key_pair.name, - 'keyFingerprint': key_pair.fingerprint - } - return result - - def ex_find_or_import_keypair_by_key_material(self, pubkey): - """ - Given a public key, look it up in the EC2 KeyPair database. If it - exists, return any information we have about it. Otherwise, create it. - - Keys that are created are named based on their comment and fingerprint. - - :rtype: ``dict`` - """ - key_fingerprint = get_pubkey_ssh2_fingerprint(pubkey) - key_comment = get_pubkey_comment(pubkey, default='unnamed') - key_name = '%s-%s' % (key_comment, key_fingerprint) - - key_pairs = self.list_key_pairs() - key_pairs = [key_pair for key_pair in key_pairs if - key_pair.fingerprint == key_fingerprint] - - if len(key_pairs) >= 1: - key_pair = key_pairs[0] - result = { - 'keyName': key_pair.name, - 'keyFingerprint': key_pair.fingerprint - } - else: - result = self.ex_import_keypair_from_string(key_name, pubkey) - - return result - - def ex_list_internet_gateways(self, gateway_ids=None, filters=None): - """ - Describes available Internet gateways and whether or not they are - attached to a VPC. These are required for VPC nodes to communicate - over the Internet. - - :param gateway_ids: Return only intenet gateways matching the - provided internet gateway IDs. If not - specified, a list of all the internet - gateways in the corresponding region is - returned. - :type gateway_ids: ``list`` - - :param filters: The filters so that the response includes - information for only certain gateways. - :type filters: ``dict`` - - :rtype: ``list`` of :class:`.VPCInternetGateway` - """ - params = {'Action': 'DescribeInternetGateways'} - - if gateway_ids: - params.update(self._pathlist('InternetGatewayId', gateway_ids)) - - if filters: - params.update(self._build_filters(filters)) - - response = self.connection.request(self.path, params=params).object - - return self._to_internet_gateways(response, 'internetGatewaySet/item') - - def ex_create_internet_gateway(self, name=None): - """ - Delete a VPC Internet gateway - - :rtype: ``bool`` - """ - params = {'Action': 'CreateInternetGateway'} - - resp = self.connection.request(self.path, params=params).object - - element = resp.findall(fixxpath(xpath='internetGateway', - namespace=NAMESPACE)) - - gateway = self._to_internet_gateway(element[0], name) - - if name and self.ex_create_tags(gateway, {'Name': name}): - gateway.extra['tags']['Name'] = name - - return gateway - - def ex_delete_internet_gateway(self, gateway): - """ - Delete a VPC Internet gateway - - :param gateway: The gateway to delete - :type gateway: :class:`.VPCInternetGateway` - - :rtype: ``bool`` - """ - params = {'Action': 'DeleteInternetGateway', - 'InternetGatewayId': gateway.id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_attach_internet_gateway(self, gateway, network): - """ - Attach a Internet gateway to a VPC - - :param gateway: The gateway to attach - :type gateway: :class:`.VPCInternetGateway` - - :param network: The VPC network to attach to - :type network: :class:`.EC2Network` - - :rtype: ``bool`` - """ - params = {'Action': 'AttachInternetGateway', - 'InternetGatewayId': gateway.id, - 'VpcId': network.id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_detach_internet_gateway(self, gateway, network): - """ - Detach a Internet gateway from a VPC - - :param gateway: The gateway to detach - :type gateway: :class:`.VPCInternetGateway` - - :param network: The VPC network to detach from - :type network: :class:`.EC2Network` - - :rtype: ``bool`` - """ - params = {'Action': 'DetachInternetGateway', - 'InternetGatewayId': gateway.id, - 'VpcId': network.id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_list_route_tables(self, route_table_ids=None, filters=None): - """ - Describes one or more of a VPC's route tables. - These are are used to determine where network traffic is directed. - - :param route_table_ids: Return only route tables matching the - provided route table IDs. If not specified, - a list of all the route tables in the - corresponding region is returned. - :type route_table_ids: ``list`` - - :param filters: The filters so that the response includes - information for only certain route tables. - :type filters: ``dict`` - - :rtype: ``list`` of :class:`.EC2RouteTable` - """ - params = {'Action': 'DescribeRouteTables'} - - if route_table_ids: - params.update(self._pathlist('RouteTableId', route_table_ids)) - - if filters: - params.update(self._build_filters(filters)) - - response = self.connection.request(self.path, params=params) - - return self._to_route_tables(response.object) - - def ex_create_route_table(self, network, name=None): - """ - Create a route table within a VPC. - - :param vpc_id: The VPC that the subnet should be created in. - :type vpc_id: :class:`.EC2Network` - - :rtype: :class: `.EC2RouteTable` - """ - params = {'Action': 'CreateRouteTable', - 'VpcId': network.id} - - response = self.connection.request(self.path, params=params).object - element = response.findall(fixxpath(xpath='routeTable', - namespace=NAMESPACE))[0] - - route_table = self._to_route_table(element, name=name) - - if name and self.ex_create_tags(route_table, {'Name': name}): - route_table.extra['tags']['Name'] = name - - return route_table - - def ex_delete_route_table(self, route_table): - """ - Deletes a VPC route table. - - :param route_table: The route table to delete. - :type route_table: :class:`.EC2RouteTable` - - :rtype: ``bool`` - """ - - params = {'Action': 'DeleteRouteTable', - 'RouteTableId': route_table.id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_associate_route_table(self, route_table, subnet): - """ - Associates a route table with a subnet within a VPC. - - Note: A route table can be associated with multiple subnets. - - :param route_table: The route table to associate. - :type route_table: :class:`.EC2RouteTable` - - :param subnet: The subnet to associate with. - :type subnet: :class:`.EC2Subnet` - - :return: Route table association ID. - :rtype: ``str`` - """ - - params = {'Action': 'AssociateRouteTable', - 'RouteTableId': route_table.id, - 'SubnetId': subnet.id} - - result = self.connection.request(self.path, params=params).object - association_id = findtext(element=result, - xpath='associationId', - namespace=NAMESPACE) - - return association_id - - def ex_dissociate_route_table(self, subnet_association): - """ - Dissociates a subnet from a route table. - - :param subnet_association: The subnet association object or - subnet association ID. - :type subnet_association: :class:`.EC2SubnetAssociation` or - ``str`` - - :rtype: ``bool`` - """ - - if isinstance(subnet_association, EC2SubnetAssociation): - subnet_association_id = subnet_association.id - else: - subnet_association_id = subnet_association - - params = {'Action': 'DisassociateRouteTable', - 'AssociationId': subnet_association_id} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_replace_route_table_association(self, subnet_association, - route_table): - """ - Changes the route table associated with a given subnet in a VPC. - - Note: This method can be used to change which table is the main route - table in the VPC (Specify the main route table's association ID - and the route table to be the new main route table). - - :param subnet_association: The subnet association object or - subnet association ID. - :type subnet_association: :class:`.EC2SubnetAssociation` or - ``str`` - - :param route_table: The new route table to associate. - :type route_table: :class:`.EC2RouteTable` - - :return: New route table association ID. - :rtype: ``str`` - """ - - if isinstance(subnet_association, EC2SubnetAssociation): - subnet_association_id = subnet_association.id - else: - subnet_association_id = subnet_association - - params = {'Action': 'ReplaceRouteTableAssociation', - 'AssociationId': subnet_association_id, - 'RouteTableId': route_table.id} - - result = self.connection.request(self.path, params=params).object - new_association_id = findtext(element=result, - xpath='newAssociationId', - namespace=NAMESPACE) - - return new_association_id - - def ex_create_route(self, route_table, cidr, - internet_gateway=None, node=None, - network_interface=None, vpc_peering_connection=None): - """ - Creates a route entry in the route table. - - :param route_table: The route table to create the route in. - :type route_table: :class:`.EC2RouteTable` - - :param cidr: The CIDR block used for the destination match. - :type cidr: ``str`` - - :param internet_gateway: The internet gateway to route - traffic through. - :type internet_gateway: :class:`.VPCInternetGateway` - - :param node: The NAT instance to route traffic through. - :type node: :class:`Node` - - :param network_interface: The network interface of the node - to route traffic through. - :type network_interface: :class:`.EC2NetworkInterface` - - :param vpc_peering_connection: The VPC peering connection. - :type vpc_peering_connection: :class:`.VPCPeeringConnection` - - :rtype: ``bool`` - - Note: You must specify one of the following: internet_gateway, - node, network_interface, vpc_peering_connection. - """ - - params = {'Action': 'CreateRoute', - 'RouteTableId': route_table.id, - 'DestinationCidrBlock': cidr} - - if internet_gateway: - params['GatewayId'] = internet_gateway.id - - if node: - params['InstanceId'] = node.id - - if network_interface: - params['NetworkInterfaceId'] = network_interface.id - - if vpc_peering_connection: - params['VpcPeeringConnectionId'] = vpc_peering_connection.id - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_delete_route(self, route_table, cidr): - """ - Deletes a route entry from the route table. - - :param route_table: The route table to delete the route from. - :type route_table: :class:`.EC2RouteTable` - - :param cidr: The CIDR block used for the destination match. - :type cidr: ``str`` - - :rtype: ``bool`` - """ - - params = {'Action': 'DeleteRoute', - 'RouteTableId': route_table.id, - 'DestinationCidrBlock': cidr} - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def ex_replace_route(self, route_table, cidr, - internet_gateway=None, node=None, - network_interface=None, vpc_peering_connection=None): - """ - Replaces an existing route entry within a route table in a VPC. - - :param route_table: The route table to replace the route in. - :type route_table: :class:`.EC2RouteTable` - - :param cidr: The CIDR block used for the destination match. - :type cidr: ``str`` - - :param internet_gateway: The new internet gateway to route - traffic through. - :type internet_gateway: :class:`.VPCInternetGateway` - - :param node: The new NAT instance to route traffic through. - :type node: :class:`Node` - - :param network_interface: The new network interface of the node - to route traffic through. - :type network_interface: :class:`.EC2NetworkInterface` - - :param vpc_peering_connection: The new VPC peering connection. - :type vpc_peering_connection: :class:`.VPCPeeringConnection` - - :rtype: ``bool`` - - Note: You must specify one of the following: internet_gateway, - node, network_interface, vpc_peering_connection. - """ - - params = {'Action': 'ReplaceRoute', - 'RouteTableId': route_table.id, - 'DestinationCidrBlock': cidr} - - if internet_gateway: - params['GatewayId'] = internet_gateway.id - - if node: - params['InstanceId'] = node.id - - if network_interface: - params['NetworkInterfaceId'] = network_interface.id - - if vpc_peering_connection: - params['VpcPeeringConnectionId'] = vpc_peering_connection.id - - res = self.connection.request(self.path, params=params).object - - return self._get_boolean(res) - - def _to_nodes(self, object, xpath): - return [self._to_node(el) - for el in object.findall(fixxpath(xpath=xpath, - namespace=NAMESPACE))] - - def _to_node(self, element): - try: - state = self.NODE_STATE_MAP[findattr(element=element, - xpath="instanceState/name", - namespace=NAMESPACE) - ] - except KeyError: - state = NodeState.UNKNOWN - - instance_id = findtext(element=element, xpath='instanceId', - namespace=NAMESPACE) - public_ip = findtext(element=element, xpath='ipAddress', - namespace=NAMESPACE) - public_ips = [public_ip] if public_ip else [] - private_ip = findtext(element=element, xpath='privateIpAddress', - namespace=NAMESPACE) - private_ips = [private_ip] if private_ip else [] - product_codes = [] - for p in findall(element=element, - xpath="productCodesSet/item/productCode", - namespace=NAMESPACE): - product_codes.append(p) - - # Get our tags - tags = self._get_resource_tags(element) - name = tags.get('Name', instance_id) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['node']) - - # Add additional properties to our extra dictionary - extra['block_device_mapping'] = self._to_device_mappings(element) - extra['groups'] = self._get_security_groups(element) - extra['network_interfaces'] = self._to_interfaces(element) - extra['product_codes'] = product_codes - extra['tags'] = tags - - return Node(id=instance_id, name=name, state=state, - public_ips=public_ips, private_ips=private_ips, - driver=self.connection.driver, extra=extra) - - def _to_images(self, object): - return [self._to_image(el) for el in object.findall( - fixxpath(xpath='imagesSet/item', namespace=NAMESPACE)) - ] - - def _to_image(self, element): - - id = findtext(element=element, xpath='imageId', namespace=NAMESPACE) - name = findtext(element=element, xpath='name', namespace=NAMESPACE) - - # Build block device mapping - block_device_mapping = self._to_device_mappings(element) - - # Get our tags - tags = self._get_resource_tags(element) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['image']) - - # Add our tags and block device mapping - extra['tags'] = tags - extra['block_device_mapping'] = block_device_mapping - - return NodeImage(id=id, name=name, driver=self, extra=extra) - - def _to_volume(self, element, name=None): - """ - Parse the XML element and return a StorageVolume object. - - :param name: An optional name for the volume. If not provided - then either tag with a key "Name" or volume ID - will be used (which ever is available first in that - order). - :type name: ``str`` - - :rtype: :class:`StorageVolume` - """ - volId = findtext(element=element, xpath='volumeId', - namespace=NAMESPACE) - size = findtext(element=element, xpath='size', namespace=NAMESPACE) - - # Get our tags - tags = self._get_resource_tags(element) - - # If name was not passed into the method then - # fall back then use the volume id - name = name if name else tags.get('Name', volId) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['volume']) - - extra['tags'] = tags - - return StorageVolume(id=volId, - name=name, - size=int(size), - driver=self, - extra=extra) - - def _to_snapshots(self, response): - return [self._to_snapshot(el) for el in response.findall( - fixxpath(xpath='snapshotSet/item', namespace=NAMESPACE)) - ] - - def _to_snapshot(self, element, name=None): - snapId = findtext(element=element, xpath='snapshotId', - namespace=NAMESPACE) - size = findtext(element=element, xpath='volumeSize', - namespace=NAMESPACE) - - # Get our tags - tags = self._get_resource_tags(element) - - # If name was not passed into the method then - # fall back then use the snapshot id - name = name if name else tags.get('Name', snapId) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['snapshot']) - - # Add tags and name to the extra dict - extra['tags'] = tags - extra['name'] = name - - return VolumeSnapshot(snapId, size=int(size), - driver=self, extra=extra) - - def _to_key_pairs(self, elems): - key_pairs = [self._to_key_pair(elem=elem) for elem in elems] - return key_pairs - - def _to_key_pair(self, elem): - name = findtext(element=elem, xpath='keyName', namespace=NAMESPACE) - fingerprint = findtext(element=elem, xpath='keyFingerprint', - namespace=NAMESPACE).strip() - private_key = findtext(element=elem, xpath='keyMaterial', - namespace=NAMESPACE) - - key_pair = KeyPair(name=name, - public_key=None, - fingerprint=fingerprint, - private_key=private_key, - driver=self) - return key_pair - - def _to_security_groups(self, response): - return [self._to_security_group(el) for el in response.findall( - fixxpath(xpath='securityGroupInfo/item', namespace=NAMESPACE)) - ] - - def _to_security_group(self, element): - # security group id - sg_id = findtext(element=element, - xpath='groupId', - namespace=NAMESPACE) - - # security group name - name = findtext(element=element, - xpath='groupName', - namespace=NAMESPACE) - - # Get our tags - tags = self._get_resource_tags(element) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['security_group']) - - # Add tags to the extra dict - extra['tags'] = tags - - # Get ingress rules - ingress_rules = self._to_security_group_rules( - element, 'ipPermissions/item' - ) - - # Get egress rules - egress_rules = self._to_security_group_rules( - element, 'ipPermissionsEgress/item' - ) - - return EC2SecurityGroup(sg_id, name, ingress_rules, - egress_rules, extra=extra) - - def _to_security_group_rules(self, element, xpath): - return [self._to_security_group_rule(el) for el in element.findall( - fixxpath(xpath=xpath, namespace=NAMESPACE)) - ] - - def _to_security_group_rule(self, element): - """ - Parse the XML element and return a SecurityGroup object. - - :rtype: :class:`EC2SecurityGroup` - """ - - rule = {} - rule['protocol'] = findtext(element=element, - xpath='ipProtocol', - namespace=NAMESPACE) - - rule['from_port'] = findtext(element=element, - xpath='fromPort', - namespace=NAMESPACE) - - rule['to_port'] = findtext(element=element, - xpath='toPort', - namespace=NAMESPACE) - - # get security groups - elements = element.findall(fixxpath( - xpath='groups/item', - namespace=NAMESPACE - )) - - rule['group_pairs'] = [] - - for element in elements: - item = { - 'user_id': findtext( - element=element, - xpath='userId', - namespace=NAMESPACE), - 'group_id': findtext( - element=element, - xpath='groupId', - namespace=NAMESPACE), - 'group_name': findtext( - element=element, - xpath='groupName', - namespace=NAMESPACE) - } - rule['group_pairs'].append(item) - - # get ip ranges - elements = element.findall(fixxpath( - xpath='ipRanges/item', - namespace=NAMESPACE - )) - - rule['cidr_ips'] = [ - findtext( - element=element, - xpath='cidrIp', - namespace=NAMESPACE - ) for element in elements] - - return rule - - def _to_networks(self, response): - return [self._to_network(el) for el in response.findall( - fixxpath(xpath='vpcSet/item', namespace=NAMESPACE)) - ] - - def _to_network(self, element, name=None): - # Get the network id - vpc_id = findtext(element=element, - xpath='vpcId', - namespace=NAMESPACE) - - # Get our tags - tags = self._get_resource_tags(element) - - # Set our name if the Name key/value if available - # If we don't get anything back then use the vpc_id - name = name if name else tags.get('Name', vpc_id) - - cidr_block = findtext(element=element, - xpath='cidrBlock', - namespace=NAMESPACE) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['network']) - - # Add tags to the extra dict - extra['tags'] = tags - - return EC2Network(vpc_id, name, cidr_block, extra=extra) - - def _to_addresses(self, response, only_associated): - """ - Builds a list of dictionaries containing elastic IP properties. - - :param only_associated: If true, return only those addresses - that are associated with an instance. - If false, return all addresses. - :type only_associated: ``bool`` - - :rtype: ``list`` of :class:`ElasticIP` - """ - addresses = [] - for el in response.findall(fixxpath(xpath='addressesSet/item', - namespace=NAMESPACE)): - addr = self._to_address(el, only_associated) - if addr is not None: - addresses.append(addr) - - return addresses - - def _to_address(self, element, only_associated): - instance_id = findtext(element=element, xpath='instanceId', - namespace=NAMESPACE) - - public_ip = findtext(element=element, - xpath='publicIp', - namespace=NAMESPACE) - - domain = findtext(element=element, - xpath='domain', - namespace=NAMESPACE) - - # Build our extra dict - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['elastic_ip']) - - # Return NoneType if only associated IPs are requested - if only_associated and not instance_id: - return None - - return ElasticIP(public_ip, domain, instance_id, extra=extra) - - def _to_subnets(self, response): - return [self._to_subnet(el) for el in response.findall( - fixxpath(xpath='subnetSet/item', namespace=NAMESPACE)) - ] - - def _to_subnet(self, element, name=None): - # Get the subnet ID - subnet_id = findtext(element=element, - xpath='subnetId', - namespace=NAMESPACE) - - # Get our tags - tags = self._get_resource_tags(element) - - # If we don't get anything back then use the subnet_id - name = name if name else tags.get('Name', subnet_id) - - state = findtext(element=element, - xpath='state', - namespace=NAMESPACE) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['subnet']) - - # Also include our tags - extra['tags'] = tags - - return EC2NetworkSubnet(subnet_id, name, state, extra=extra) - - def _to_interfaces(self, response): - return [self._to_interface(el) for el in response.findall( - fixxpath(xpath='networkInterfaceSet/item', namespace=NAMESPACE)) - ] - - def _to_interface(self, element, name=None): - """ - Parse the XML element and return a EC2NetworkInterface object. - - :param name: An optional name for the interface. If not provided - then either tag with a key "Name" or the interface ID - will be used (whichever is available first in that - order). - :type name: ``str`` - - :rtype: :class: `EC2NetworkInterface` - """ - - interface_id = findtext(element=element, - xpath='networkInterfaceId', - namespace=NAMESPACE) - - state = findtext(element=element, - xpath='status', - namespace=NAMESPACE) - - # Get tags - tags = self._get_resource_tags(element) - - name = name if name else tags.get('Name', interface_id) - - # Build security groups - groups = self._get_security_groups(element) - - # Build private IPs - priv_ips = [] - for item in findall(element=element, - xpath='privateIpAddressesSet/item', - namespace=NAMESPACE): - - priv_ips.append({'private_ip': findtext(element=item, - xpath='privateIpAddress', - namespace=NAMESPACE), - 'private_dns': findtext(element=item, - xpath='privateDnsName', - namespace=NAMESPACE), - 'primary': findtext(element=item, - xpath='primary', - namespace=NAMESPACE)}) - - # Build our attachment dictionary which we will add into extra later - attributes_map = \ - RESOURCE_EXTRA_ATTRIBUTES_MAP['network_interface_attachment'] - attachment = self._get_extra_dict(element, attributes_map) - - # Build our extra dict - attributes_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['network_interface'] - extra = self._get_extra_dict(element, attributes_map) - - # Include our previously built items as well - extra['tags'] = tags - extra['attachment'] = attachment - extra['private_ips'] = priv_ips - extra['groups'] = groups - - return EC2NetworkInterface(interface_id, name, state, extra=extra) - - def _to_reserved_nodes(self, object, xpath): - return [self._to_reserved_node(el) - for el in object.findall(fixxpath(xpath=xpath, - namespace=NAMESPACE))] - - def _to_reserved_node(self, element): - """ - Build an EC2ReservedNode object using the reserved instance properties. - Information on these properties can be found at http://goo.gl/ulXCC7. - """ - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['reserved_node']) - - try: - size = [size for size in self.list_sizes() if - size.id == extra['instance_type']][0] - except IndexError: - size = None - - return EC2ReservedNode(id=findtext(element=element, - xpath='reservedInstancesId', - namespace=NAMESPACE), - state=findattr(element=element, - xpath='state', - namespace=NAMESPACE), - driver=self, - size=size, - extra=extra) - - def _to_device_mappings(self, object): - return [self._to_device_mapping(el) for el in object.findall( - fixxpath(xpath='blockDeviceMapping/item', namespace=NAMESPACE)) - ] - - def _to_device_mapping(self, element): - """ - Parse the XML element and return a dictionary of device properties. - Additional information can be found at http://goo.gl/GjWYBf. - - @note: EBS volumes do not have a virtual name. Only ephemeral - disks use this property. - :rtype: ``dict`` - """ - mapping = {} - - mapping['device_name'] = findattr(element=element, - xpath='deviceName', - namespace=NAMESPACE) - - mapping['virtual_name'] = findattr(element=element, - xpath='virtualName', - namespace=NAMESPACE) - - # If virtual name does not exist then this is an EBS volume. - # Build the EBS dictionary leveraging the _get_extra_dict method. - if mapping['virtual_name'] is None: - mapping['ebs'] = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['ebs_volume']) - - return mapping - - def _to_internet_gateways(self, object, xpath): - return [self._to_internet_gateway(el) - for el in object.findall(fixxpath(xpath=xpath, - namespace=NAMESPACE))] - - def _to_internet_gateway(self, element, name=None): - id = findtext(element=element, - xpath='internetGatewayId', - namespace=NAMESPACE) - - vpc_id = findtext(element=element, - xpath='attachmentSet/item/vpcId', - namespace=NAMESPACE) - - state = findtext(element=element, - xpath='attachmentSet/item/state', - namespace=NAMESPACE) - - # If there's no attachment state, let's - # set it to available - if not state: - state = 'available' - - # Get our tags - tags = self._get_resource_tags(element) - - # If name was not passed into the method then - # fall back then use the gateway id - name = name if name else tags.get('Name', id) - - return VPCInternetGateway(id=id, name=name, vpc_id=vpc_id, - state=state, driver=self.connection.driver, - extra={'tags': tags}) - - def _to_route_tables(self, response): - return [self._to_route_table(el) for el in response.findall( - fixxpath(xpath='routeTableSet/item', namespace=NAMESPACE)) - ] - - def _to_route_table(self, element, name=None): - # route table id - route_table_id = findtext(element=element, - xpath='routeTableId', - namespace=NAMESPACE) - - # Get our tags - tags = self._get_resource_tags(element) - - # Get our extra dictionary - extra = self._get_extra_dict( - element, RESOURCE_EXTRA_ATTRIBUTES_MAP['route_table']) - - # Add tags to the extra dict - extra['tags'] = tags - - # Get routes - routes = self._to_routes(element, 'routeSet/item') - - # Get subnet associations - subnet_associations = self._to_subnet_associations( - element, 'associationSet/item') - - # Get propagating routes virtual private gateways (VGW) IDs - propagating_gateway_ids = [] - for el in element.findall(fixxpath(xpath='propagatingVgwSet/item', - namespace=NAMESPACE)): - propagating_gateway_ids.append(findtext(element=el, - xpath='gatewayId', - namespace=NAMESPACE)) - - name = name if name else tags.get('Name', id) - - return EC2RouteTable(route_table_id, name, routes, subnet_associations, - propagating_gateway_ids, extra=extra) - - def _to_routes(self, element, xpath): - return [self._to_route(el) for el in element.findall( - fixxpath(xpath=xpath, namespace=NAMESPACE)) - ] - - def _to_route(self, element): - """ - Parse the XML element and return a route object - - :rtype: :class: `EC2Route` - """ - - destination_cidr = findtext(element=element, - xpath='destinationCidrBlock', - namespace=NAMESPACE) - - gateway_id = findtext(element=element, - xpath='gatewayId', - namespace=NAMESPACE) - - instance_id = findtext(element=element, - xpath='instanceId', - namespace=NAMESPACE) - - owner_id = findtext(element=element, - xpath='instanceOwnerId', - namespace=NAMESPACE) - - interface_id = findtext(element=element, - xpath='networkInterfaceId', - namespace=NAMESPACE) - - state = findtext(element=element, - xpath='state', - namespace=NAMESPACE) - - origin = findtext(element=element, - xpath='origin', - namespace=NAMESPACE) - - vpc_peering_connection_id = findtext(element=element, - xpath='vpcPeeringConnectionId', - namespace=NAMESPACE) - - return EC2Route(destination_cidr, gateway_id, instance_id, owner_id, - interface_id, state, origin, vpc_peering_connection_id) - - def _to_subnet_associations(self, element, xpath): - return [self._to_subnet_association(el) for el in element.findall( - fixxpath(xpath=xpath, namespace=NAMESPACE)) - ] - - def _to_subnet_association(self, element): - """ - Parse the XML element and return a route table association object - - :rtype: :class: `EC2SubnetAssociation` - """ - - association_id = findtext(element=element, - xpath='routeTableAssociationId', - namespace=NAMESPACE) - - route_table_id = findtext(element=element, - xpath='routeTableId', - namespace=NAMESPACE) - - subnet_id = findtext(element=element, - xpath='subnetId', - namespace=NAMESPACE) - - main = findtext(element=element, - xpath='main', - namespace=NAMESPACE) - - main = True if main else False - - return EC2SubnetAssociation(association_id, route_table_id, - subnet_id, main) - - def _pathlist(self, key, arr): - """ - Converts a key and an array of values into AWS query param format. - """ - params = {} - i = 0 - - for value in arr: - i += 1 - params['%s.%s' % (key, i)] = value - - return params - - def _get_boolean(self, element): - tag = '{%s}%s' % (NAMESPACE, 'return') - return element.findtext(tag) == 'true' - - def _get_terminate_boolean(self, element): - status = element.findtext(".//{%s}%s" % (NAMESPACE, 'name')) - return any([term_status == status - for term_status - in ('shutting-down', 'terminated')]) - - def _add_instance_filter(self, params, node): - """ - Add instance filter to the provided params dictionary. - """ - filters = {'instance-id': node.id} - params.update(self._build_filters(filters)) - - return params - - def _get_state_boolean(self, element): - """ - Checks for the instances's state - """ - state = findall(element=element, - xpath='instancesSet/item/currentState/name', - namespace=NAMESPACE)[0].text - - return state in ('stopping', 'pending', 'starting') - - def _get_extra_dict(self, element, mapping): - """ - Extract attributes from the element based on rules provided in the - mapping dictionary. - - :param element: Element to parse the values from. - :type element: xml.etree.ElementTree.Element. - - :param mapping: Dictionary with the extra layout - :type node: :class:`Node` - - :rtype: ``dict`` - """ - extra = {} - for attribute, values in mapping.items(): - transform_func = values['transform_func'] - value = findattr(element=element, - xpath=values['xpath'], - namespace=NAMESPACE) - if value is not None: - extra[attribute] = transform_func(value) - else: - extra[attribute] = None - - return extra - - def _get_resource_tags(self, element): - """ - Parse tags from the provided element and return a dictionary with - key/value pairs. - - :rtype: ``dict`` - """ - tags = {} - - # Get our tag set by parsing the element - tag_set = findall(element=element, - xpath='tagSet/item', - namespace=NAMESPACE) - - for tag in tag_set: - key = findtext(element=tag, - xpath='key', - namespace=NAMESPACE) - - value = findtext(element=tag, - xpath='value', - namespace=NAMESPACE) - - tags[key] = value - - return tags - - def _get_block_device_mapping_params(self, block_device_mapping): - """ - Return a list of dictionaries with query parameters for - a valid block device mapping. - - :param mapping: List of dictionaries with the drive layout - :type mapping: ``list`` or ``dict`` - - :return: Dictionary representation of the drive mapping - :rtype: ``dict`` - """ - - if not isinstance(block_device_mapping, (list, tuple)): - raise AttributeError( - 'block_device_mapping not list or tuple') - - params = {} - - for idx, mapping in enumerate(block_device_mapping): - idx += 1 # We want 1-based indexes - if not isinstance(mapping, dict): - raise AttributeError( - 'mapping %s in block_device_mapping ' - 'not a dict' % mapping) - for k, v in mapping.items(): - if not isinstance(v, dict): - params['BlockDeviceMapping.%d.%s' % (idx, k)] = str(v) - else: - for key, value in v.items(): - params['BlockDeviceMapping.%d.%s.%s' - % (idx, k, key)] = str(value) - return params - - def _get_common_security_group_params(self, group_id, protocol, - from_port, to_port, cidr_ips, - group_pairs): - """ - Return a dictionary with common query parameters which are used when - operating on security groups. - - :rtype: ``dict`` - """ - params = {'GroupId': group_id, - 'IpPermissions.1.IpProtocol': protocol, - 'IpPermissions.1.FromPort': from_port, - 'IpPermissions.1.ToPort': to_port} - - if cidr_ips is not None: - ip_ranges = {} - for index, cidr_ip in enumerate(cidr_ips): - index += 1 - - ip_ranges['IpPermissions.1.IpRanges.%s.CidrIp' - % (index)] = cidr_ip - - params.update(ip_ranges) - - if group_pairs is not None: - user_groups = {} - for index, group_pair in enumerate(group_pairs): - index += 1 - - if 'group_id' in group_pair.keys(): - user_groups['IpPermissions.1.Groups.%s.GroupId' - % (index)] = group_pair['group_id'] - - if 'group_name' in group_pair.keys(): - user_groups['IpPermissions.1.Groups.%s.GroupName' - % (index)] = group_pair['group_name'] - - if 'user_id' in group_pair.keys(): - user_groups['IpPermissions.1.Groups.%s.UserId' - % (index)] = group_pair['user_id'] - - params.update(user_groups) - - return params - - def _get_security_groups(self, element): - """ - Parse security groups from the provided element and return a - list of security groups with the id ane name key/value pairs. - - :rtype: ``list`` of ``dict`` - """ - groups = [] - - for item in findall(element=element, - xpath='groupSet/item', - namespace=NAMESPACE): - groups.append({ - 'group_id': findtext(element=item, - xpath='groupId', - namespace=NAMESPACE), - 'group_name': findtext(element=item, - xpath='groupName', - namespace=NAMESPACE) - }) - - return groups - - def _build_filters(self, filters): - """ - Return a dictionary with filter query parameters which are used when - listing networks, security groups, etc. - - :param filters: Dict of filter names and filter values - :type filters: ``dict`` - - :rtype: ``dict`` - """ - - filter_entries = {} - - for filter_idx, filter_data in enumerate(filters.items()): - filter_idx += 1 # We want 1-based indexes - filter_name, filter_values = filter_data - filter_key = 'Filter.%s.Name' % (filter_idx) - filter_entries[filter_key] = filter_name - - if isinstance(filter_values, list): - for value_idx, value in enumerate(filter_values): - value_idx += 1 # We want 1-based indexes - value_key = 'Filter.%s.Value.%s' % (filter_idx, - value_idx) - filter_entries[value_key] = value - else: - value_key = 'Filter.%s.Value.1' % (filter_idx) - filter_entries[value_key] = filter_values - - return filter_entries - - -class EC2NodeDriver(BaseEC2NodeDriver): - """ - Amazon EC2 node driver. - """ - - connectionCls = EC2Connection - type = Provider.EC2 - name = 'Amazon EC2' - website = 'http://aws.amazon.com/ec2/' - path = '/' - - NODE_STATE_MAP = { - 'pending': NodeState.PENDING, - 'running': NodeState.RUNNING, - 'shutting-down': NodeState.UNKNOWN, - 'terminated': NodeState.TERMINATED, - 'stopped': NodeState.STOPPED - } - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='us-east-1', **kwargs): - if hasattr(self, '_region'): - region = self._region - - if region not in VALID_EC2_REGIONS: - raise ValueError('Invalid region: %s' % (region)) - - details = REGION_DETAILS[region] - self.region_name = region - self.api_name = details['api_name'] - self.country = details['country'] - - self.connectionCls.host = details['endpoint'] - - super(EC2NodeDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, **kwargs) - - -class IdempotentParamError(LibcloudError): - """ - Request used the same client token as a previous, - but non-identical request. - """ - - def __str__(self): - return repr(self.value) - - -class EC2EUNodeDriver(EC2NodeDriver): - """ - Driver class for EC2 in the Western Europe Region. - """ - name = 'Amazon EC2 (eu-west-1)' - _region = 'eu-west-1' - - -class EC2USWestNodeDriver(EC2NodeDriver): - """ - Driver class for EC2 in the Western US Region - """ - name = 'Amazon EC2 (us-west-1)' - _region = 'us-west-1' - - -class EC2USWestOregonNodeDriver(EC2NodeDriver): - """ - Driver class for EC2 in the US West Oregon region. - """ - name = 'Amazon EC2 (us-west-2)' - _region = 'us-west-2' - - -class EC2APSENodeDriver(EC2NodeDriver): - """ - Driver class for EC2 in the Southeast Asia Pacific Region. - """ - name = 'Amazon EC2 (ap-southeast-1)' - _region = 'ap-southeast-1' - - -class EC2APNENodeDriver(EC2NodeDriver): - """ - Driver class for EC2 in the Northeast Asia Pacific Region. - """ - name = 'Amazon EC2 (ap-northeast-1)' - _region = 'ap-northeast-1' - - -class EC2SAEastNodeDriver(EC2NodeDriver): - """ - Driver class for EC2 in the South America (Sao Paulo) Region. - """ - name = 'Amazon EC2 (sa-east-1)' - _region = 'sa-east-1' - - -class EC2APSESydneyNodeDriver(EC2NodeDriver): - """ - Driver class for EC2 in the Southeast Asia Pacific (Sydney) Region. - """ - name = 'Amazon EC2 (ap-southeast-2)' - _region = 'ap-southeast-2' - - -class EucConnection(EC2Connection): - """ - Connection class for Eucalyptus - """ - - host = None - - -class EucNodeDriver(BaseEC2NodeDriver): - """ - Driver class for Eucalyptus - """ - - name = 'Eucalyptus' - website = 'http://www.eucalyptus.com/' - api_name = 'ec2_us_east' - region_name = 'us-east-1' - connectionCls = EucConnection - - def __init__(self, key, secret=None, secure=True, host=None, - path=None, port=None, api_version=DEFAULT_EUCA_API_VERSION): - """ - @inherits: :class:`EC2NodeDriver.__init__` - - :param path: The host where the API can be reached. - :type path: ``str`` - - :param api_version: The API version to extend support for - Eucalyptus proprietary API calls - :type api_version: ``str`` - """ - super(EucNodeDriver, self).__init__(key, secret, secure, host, port) - - if path is None: - path = '/services/Eucalyptus' - - self.path = path - self.EUCA_NAMESPACE = 'http://msgs.eucalyptus.com/%s' % (api_version) - - def list_locations(self): - raise NotImplementedError( - 'list_locations not implemented for this driver') - - def _to_sizes(self, response): - return [self._to_size(el) for el in response.findall( - fixxpath(xpath='instanceTypeDetails/item', - namespace=self.EUCA_NAMESPACE))] - - def _to_size(self, el): - name = findtext(element=el, - xpath='name', - namespace=self.EUCA_NAMESPACE) - cpu = findtext(element=el, - xpath='cpu', - namespace=self.EUCA_NAMESPACE) - disk = findtext(element=el, - xpath='disk', - namespace=self.EUCA_NAMESPACE) - memory = findtext(element=el, - xpath='memory', - namespace=self.EUCA_NAMESPACE) - - return NodeSize(id=name, - name=name, - ram=int(memory), - disk=int(disk), - bandwidth=None, - price=None, - driver=EucNodeDriver, - extra={ - 'cpu': int(cpu) - }) - - def list_sizes(self): - """ - List available instance flavors/sizes - - :rtype: ``list`` of :class:`NodeSize` - """ - params = {'Action': 'DescribeInstanceTypes'} - response = self.connection.request(self.path, params=params).object - - return self._to_sizes(response) - - def _add_instance_filter(self, params, node): - """ - Eucalyptus driver doesn't support filtering on instance id so this is a - no-op. - """ - pass - - -class NimbusConnection(EC2Connection): - """ - Connection class for Nimbus - """ - - host = None - - -class NimbusNodeDriver(BaseEC2NodeDriver): - """ - Driver class for Nimbus - """ - - type = Provider.NIMBUS - name = 'Nimbus' - website = 'http://www.nimbusproject.org/' - country = 'Private' - api_name = 'nimbus' - region_name = 'nimbus' - friendly_name = 'Nimbus Private Cloud' - connectionCls = NimbusConnection - - def ex_describe_addresses(self, nodes): - """ - Nimbus doesn't support elastic IPs, so this is a pass-through. - - @inherits: :class:`EC2NodeDriver.ex_describe_addresses` - """ - nodes_elastic_ip_mappings = {} - for node in nodes: - # empty list per node - nodes_elastic_ip_mappings[node.id] = [] - return nodes_elastic_ip_mappings - - def ex_create_tags(self, resource, tags): - """ - Nimbus doesn't support creating tags, so this is a pass-through. - - @inherits: :class:`EC2NodeDriver.ex_create_tags` - """ - pass - - -class OutscaleConnection(EC2Connection): - """ - Connection class for Outscale - """ - - host = None - - -class OutscaleNodeDriver(BaseEC2NodeDriver): - """ - Base Outscale FCU node driver. - - Outscale per provider driver classes inherit from it. - """ - - connectionCls = OutscaleConnection - name = 'Outscale' - website = 'http://www.outscale.com' - path = '/' - - NODE_STATE_MAP = { - 'pending': NodeState.PENDING, - 'running': NodeState.RUNNING, - 'shutting-down': NodeState.UNKNOWN, - 'terminated': NodeState.TERMINATED, - 'stopped': NodeState.STOPPED - } - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='us-east-1', region_details=None, **kwargs): - if hasattr(self, '_region'): - region = self._region - - if region_details is None: - raise ValueError('Invalid region_details argument') - - if region not in region_details.keys(): - raise ValueError('Invalid region: %s' % (region)) - - self.region_name = region - self.region_details = region_details - details = self.region_details[region] - self.api_name = details['api_name'] - self.country = details['country'] - - self.connectionCls.host = details['endpoint'] - - self._not_implemented_msg =\ - 'This method is not supported in the Outscale driver' - - super(BaseEC2NodeDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, **kwargs) - - def create_node(self, **kwargs): - """ - Create a new Outscale node. The ex_iamprofile keyword is not supported. - - @inherits: :class:`BaseEC2NodeDriver.create_node` - - :keyword ex_keyname: The name of the key pair - :type ex_keyname: ``str`` - - :keyword ex_userdata: User data - :type ex_userdata: ``str`` - - :keyword ex_security_groups: A list of names of security groups to - assign to the node. - :type ex_security_groups: ``list`` - - :keyword ex_metadata: Key/Value metadata to associate with a node - :type ex_metadata: ``dict`` - - :keyword ex_mincount: Minimum number of instances to launch - :type ex_mincount: ``int`` - - :keyword ex_maxcount: Maximum number of instances to launch - :type ex_maxcount: ``int`` - - :keyword ex_clienttoken: Unique identifier to ensure idempotency - :type ex_clienttoken: ``str`` - - :keyword ex_blockdevicemappings: ``list`` of ``dict`` block device - mappings. - :type ex_blockdevicemappings: ``list`` of ``dict`` - - :keyword ex_ebs_optimized: EBS-Optimized if True - :type ex_ebs_optimized: ``bool`` - """ - if 'ex_iamprofile' in kwargs: - raise NotImplementedError("ex_iamprofile not implemented") - return super(OutscaleNodeDriver, self).create_node(**kwargs) - - def ex_create_network(self, cidr_block, name=None): - """ - Create a network/VPC. Outscale does not support instance_tenancy. - - :param cidr_block: The CIDR block assigned to the network - :type cidr_block: ``str`` - - :param name: An optional name for the network - :type name: ``str`` - - :return: Dictionary of network properties - :rtype: ``dict`` - """ - return super(OutscaleNodeDriver, self).ex_create_network(cidr_block, - name=name) - - def ex_modify_instance_attribute(self, node, disable_api_termination=None, - ebs_optimized=None, group_id=None, - source_dest_check=None, user_data=None, - instance_type=None): - """ - Modify node attributes. - Ouscale support the following attributes: - 'DisableApiTermination.Value', 'EbsOptimized', 'GroupId.n', - 'SourceDestCheck.Value', 'UserData.Value', - 'InstanceType.Value' - - :param node: Node instance - :type node: :class:`Node` - - :param attributes: Dictionary with node attributes - :type attributes: ``dict`` - - :return: True on success, False otherwise. - :rtype: ``bool`` - """ - attributes = {} - - if disable_api_termination is not None: - attributes['DisableApiTermination.Value'] = disable_api_termination - if ebs_optimized is not None: - attributes['EbsOptimized'] = ebs_optimized - if group_id is not None: - attributes['GroupId.n'] = group_id - if source_dest_check is not None: - attributes['SourceDestCheck.Value'] = source_dest_check - if user_data is not None: - attributes['UserData.Value'] = user_data - if instance_type is not None: - attributes['InstanceType.Value'] = instance_type - - return super(OutscaleNodeDriver, self).ex_modify_instance_attribute( - node, attributes) - - def ex_register_image(self, name, description=None, architecture=None, - root_device_name=None, block_device_mapping=None): - """ - Registers a Machine Image based off of an EBS-backed instance. - Can also be used to create images from snapshots. - - Outscale does not support image_location, kernel_id and ramdisk_id. - - :param name: The name for the AMI being registered - :type name: ``str`` - - :param description: The description of the AMI (optional) - :type description: ``str`` - - :param architecture: The architecture of the AMI (i386/x86_64) - (optional) - :type architecture: ``str`` - - :param root_device_name: The device name for the root device - Required if registering a EBS-backed AMI - :type root_device_name: ``str`` - - :param block_device_mapping: A dictionary of the disk layout - (optional) - :type block_device_mapping: ``dict`` - - :rtype: :class:`NodeImage` - """ - return super(OutscaleNodeDriver, self).ex_register_image( - name, description=description, architecture=architecture, - root_device_name=root_device_name, - block_device_mapping=block_device_mapping) - - def ex_copy_image(self, source_region, image, name=None, description=None): - """ - Outscale does not support copying images. - - @inherits: :class:`EC2NodeDriver.ex_copy_image` - """ - raise NotImplementedError(self._not_implemented_msg) - - def ex_get_limits(self): - """ - Outscale does not support getting limits. - - @inherits: :class:`EC2NodeDriver.ex_get_limits` - """ - raise NotImplementedError(self._not_implemented_msg) - - def ex_create_network_interface(self, subnet, name=None, - description=None, - private_ip_address=None): - """ - Outscale does not support creating a network interface within a VPC. - - @inherits: :class:`EC2NodeDriver.ex_create_network_interface` - """ - raise NotImplementedError(self._not_implemented_msg) - - def ex_delete_network_interface(self, network_interface): - """ - Outscale does not support deleting a network interface within a VPC. - - @inherits: :class:`EC2NodeDriver.ex_delete_network_interface` - """ - raise NotImplementedError(self._not_implemented_msg) - - def ex_attach_network_interface_to_node(self, network_interface, - node, device_index): - """ - Outscale does not support attaching a network interface. - - @inherits: :class:`EC2NodeDriver.ex_attach_network_interface_to_node` - """ - raise NotImplementedError(self._not_implemented_msg) - - def ex_detach_network_interface(self, attachment_id, force=False): - """ - Outscale does not support detaching a network interface - - @inherits: :class:`EC2NodeDriver.ex_detach_network_interface` - """ - raise NotImplementedError(self._not_implemented_msg) - - def list_sizes(self, location=None): - """ - List available instance flavors/sizes - - This override the EC2 default method in order to use Outscale infos. - - :rtype: ``list`` of :class:`NodeSize` - """ - available_types =\ - self.region_details[self.region_name]['instance_types'] - sizes = [] - - for instance_type in available_types: - attributes = OUTSCALE_INSTANCE_TYPES[instance_type] - attributes = copy.deepcopy(attributes) - price = self._get_size_price(size_id=instance_type) - attributes.update({'price': price}) - sizes.append(NodeSize(driver=self, **attributes)) - return sizes - - -class OutscaleSASNodeDriver(OutscaleNodeDriver): - """ - Outscale SAS node driver - """ - name = 'Outscale SAS' - type = Provider.OUTSCALE_SAS - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='us-east-1', region_details=None, **kwargs): - super(OutscaleSASNodeDriver, self).__init__( - key=key, secret=secret, secure=secure, host=host, port=port, - region=region, region_details=OUTSCALE_SAS_REGION_DETAILS, - **kwargs) - - -class OutscaleINCNodeDriver(OutscaleNodeDriver): - """ - Outscale INC node driver - """ - name = 'Outscale INC' - type = Provider.OUTSCALE_INC - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='us-east-1', region_details=None, **kwargs): - super(OutscaleINCNodeDriver, self).__init__( - key=key, secret=secret, secure=secure, host=host, port=port, - region=region, region_details=OUTSCALE_INC_REGION_DETAILS, - **kwargs) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/ecp.py b/awx/lib/site-packages/libcloud/compute/drivers/ecp.py deleted file mode 100644 index 79b57fa5b2..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/ecp.py +++ /dev/null @@ -1,385 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Enomaly ECP driver -""" -import time -import base64 -import os -import socket -import binascii - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -# JSON is included in the standard library starting with Python 2.6. For 2.5 -# and 2.4, there's a simplejson egg at: http://pypi.python.org/pypi/simplejson -try: - import simplejson as json -except ImportError: - import json - -from libcloud.common.base import Response, ConnectionUserAndKey -from libcloud.compute.base import NodeDriver, NodeSize, NodeLocation -from libcloud.compute.base import NodeImage, Node -from libcloud.compute.types import Provider, NodeState, InvalidCredsError -from libcloud.utils.networking import is_private_subnet - -# Defaults -API_HOST = '' -API_PORT = (80, 443) - - -class ECPResponse(Response): - def success(self): - if self.status == httplib.OK or self.status == httplib.CREATED: - try: - j_body = json.loads(self.body) - except ValueError: - self.error = "JSON response cannot be decoded." - return False - if j_body['errno'] == 0: - return True - else: - self.error = "ECP error: %s" % j_body['message'] - return False - elif self.status == httplib.UNAUTHORIZED: - raise InvalidCredsError() - else: - self.error = "HTTP Error Code: %s" % self.status - return False - - def parse_error(self): - return self.error - - # Interpret the json responses - no error checking required - def parse_body(self): - return json.loads(self.body) - - def getheaders(self): - return self.headers - - -class ECPConnection(ConnectionUserAndKey): - """ - Connection class for the Enomaly ECP driver - """ - - responseCls = ECPResponse - host = API_HOST - port = API_PORT - - def add_default_headers(self, headers): - # Authentication - username = self.user_id - password = self.key - base64string = base64.encodestring( - b('%s:%s' % (username, password)))[:-1] - authheader = "Basic %s" % base64string - headers['Authorization'] = authheader - - return headers - - def _encode_multipart_formdata(self, fields): - """ - Based on Wade Leftwich's function: - http://code.activestate.com/recipes/146306/ - """ - # use a random boundary that does not appear in the fields - boundary = '' - while boundary in ''.join(fields): - boundary = binascii.hexlify(os.urandom(16)).decode('utf-8') - L = [] - for i in fields: - L.append('--' + boundary) - L.append('Content-Disposition: form-data; name="%s"' % i) - L.append('') - L.append(fields[i]) - L.append('--' + boundary + '--') - L.append('') - body = '\r\n'.join(L) - content_type = 'multipart/form-data; boundary=%s' % boundary - header = {'Content-Type': content_type} - return header, body - - -class ECPNodeDriver(NodeDriver): - """ - Enomaly ECP node driver - """ - - name = "Enomaly Elastic Computing Platform" - website = 'http://www.enomaly.com/' - type = Provider.ECP - connectionCls = ECPConnection - - def list_nodes(self): - """ - Returns a list of all running Nodes - - :rtype: ``list`` of :class:`Node` - """ - - # Make the call - res = self.connection.request('/rest/hosting/vm/list').parse_body() - - # Put together a list of node objects - nodes = [] - for vm in res['vms']: - node = self._to_node(vm) - if node is not None: - nodes.append(node) - - # And return it - return nodes - - def _to_node(self, vm): - """ - Turns a (json) dictionary into a Node object. - This returns only running VMs. - """ - - # Check state - if not vm['state'] == "running": - return None - - # IPs - iplist = [interface['ip'] for interface in vm['interfaces'] if - interface['ip'] != '127.0.0.1'] - - public_ips = [] - private_ips = [] - for ip in iplist: - try: - socket.inet_aton(ip) - except socket.error: - # not a valid ip - continue - if is_private_subnet(ip): - private_ips.append(ip) - else: - public_ips.append(ip) - - # Create the node object - n = Node( - id=vm['uuid'], - name=vm['name'], - state=NodeState.RUNNING, - public_ips=public_ips, - private_ips=private_ips, - driver=self, - ) - - return n - - def reboot_node(self, node): - """ - Shuts down a VM and then starts it again. - - @inherits: :class:`NodeDriver.reboot_node` - """ - - # Turn the VM off - # Black magic to make the POST requests work - d = self.connection._encode_multipart_formdata({'action': 'stop'}) - self.connection.request( - '/rest/hosting/vm/%s' % node.id, - method='POST', - headers=d[0], - data=d[1] - ).parse_body() - - node.state = NodeState.REBOOTING - # Wait for it to turn off and then continue (to turn it on again) - while node.state == NodeState.REBOOTING: - # Check if it's off. - response = self.connection.request( - '/rest/hosting/vm/%s' % node.id - ).parse_body() - if response['vm']['state'] == 'off': - node.state = NodeState.TERMINATED - else: - time.sleep(5) - - # Turn the VM back on. - # Black magic to make the POST requests work - d = self.connection._encode_multipart_formdata({'action': 'start'}) - self.connection.request( - '/rest/hosting/vm/%s' % node.id, - method='POST', - headers=d[0], - data=d[1] - ).parse_body() - - node.state = NodeState.RUNNING - return True - - def destroy_node(self, node): - """ - Shuts down and deletes a VM. - - @inherits: :class:`NodeDriver.destroy_node` - """ - - # Shut down first - # Black magic to make the POST requests work - d = self.connection._encode_multipart_formdata({'action': 'stop'}) - self.connection.request( - '/rest/hosting/vm/%s' % node.id, - method='POST', - headers=d[0], - data=d[1] - ).parse_body() - - # Ensure there was no applicationl level error - node.state = NodeState.PENDING - # Wait for the VM to turn off before continuing - while node.state == NodeState.PENDING: - # Check if it's off. - response = self.connection.request( - '/rest/hosting/vm/%s' % node.id - ).parse_body() - if response['vm']['state'] == 'off': - node.state = NodeState.TERMINATED - else: - time.sleep(5) - - # Delete the VM - # Black magic to make the POST requests work - d = self.connection._encode_multipart_formdata({'action': 'delete'}) - self.connection.request( - '/rest/hosting/vm/%s' % (node.id), - method='POST', - headers=d[0], - data=d[1] - ).parse_body() - - return True - - def list_images(self, location=None): - """ - Returns a list of all package templates aka appiances aka images. - - @inherits: :class:`NodeDriver.list_images` - """ - - # Make the call - response = self.connection.request( - '/rest/hosting/ptemplate/list').parse_body() - - # Turn the response into an array of NodeImage objects - images = [] - for ptemplate in response['packages']: - images.append(NodeImage( - id=ptemplate['uuid'], - name='%s: %s' % (ptemplate['name'], ptemplate['description']), - driver=self,) - ) - - return images - - def list_sizes(self, location=None): - """ - Returns a list of all hardware templates - - @inherits: :class:`NodeDriver.list_sizes` - """ - - # Make the call - response = self.connection.request( - '/rest/hosting/htemplate/list').parse_body() - - # Turn the response into an array of NodeSize objects - sizes = [] - for htemplate in response['templates']: - sizes.append(NodeSize( - id=htemplate['uuid'], - name=htemplate['name'], - ram=htemplate['memory'], - disk=0, # Disk is independent of hardware template. - bandwidth=0, # There is no way to keep track of bandwidth. - price=0, # The billing system is external. - driver=self,) - ) - - return sizes - - def list_locations(self): - """ - This feature does not exist in ECP. Returns hard coded dummy location. - - :rtype: ``list`` of :class:`NodeLocation` - """ - return [NodeLocation(id=1, - name="Cloud", - country='', - driver=self), - ] - - def create_node(self, **kwargs): - """ - Creates a virtual machine. - - :keyword name: String with a name for this new node (required) - :type name: ``str`` - - :keyword size: The size of resources allocated to this node . - (required) - :type size: :class:`NodeSize` - - :keyword image: OS Image to boot on node. (required) - :type image: :class:`NodeImage` - - :rtype: :class:`Node` - """ - - # Find out what network to put the VM on. - res = self.connection.request( - '/rest/hosting/network/list').parse_body() - - # Use the first / default network because there is no way to specific - # which one - network = res['networks'][0]['uuid'] - - # Prepare to make the VM - data = { - 'name': str(kwargs['name']), - 'package': str(kwargs['image'].id), - 'hardware': str(kwargs['size'].id), - 'network_uuid': str(network), - 'disk': '' - } - - # Black magic to make the POST requests work - d = self.connection._encode_multipart_formdata(data) - response = self.connection.request( - '/rest/hosting/vm/', - method='PUT', - headers=d[0], - data=d[1] - ).parse_body() - - # Create a node object and return it. - n = Node( - id=response['machine_id'], - name=data['name'], - state=NodeState.PENDING, - public_ips=[], - private_ips=[], - driver=self, - ) - - return n diff --git a/awx/lib/site-packages/libcloud/compute/drivers/elastichosts.py b/awx/lib/site-packages/libcloud/compute/drivers/elastichosts.py deleted file mode 100644 index 736ac7f0b7..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/elastichosts.py +++ /dev/null @@ -1,236 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -ElasticHosts Driver -""" - -from libcloud.compute.types import Provider -from libcloud.compute.drivers.elasticstack import ElasticStackBaseNodeDriver - - -# API end-points -API_ENDPOINTS = { - 'lon-p': { - 'name': 'London Peer 1', - 'country': 'United Kingdom', - 'host': 'api-lon-p.elastichosts.com' - }, - 'lon-b': { - 'name': 'London BlueSquare', - 'country': 'United Kingdom', - 'host': 'api-lon-b.elastichosts.com' - }, - 'sat-p': { - 'name': 'San Antonio Peer 1', - 'country': 'United States', - 'host': 'api-sat-p.elastichosts.com' - }, - 'lax-p': { - 'name': 'Los Angeles Peer 1', - 'country': 'United States', - 'host': 'api-lax-p.elastichosts.com' - }, - 'sjc-c': { - 'name': 'San Jose (Silicon Valley)', - 'country': 'United States', - 'host': 'api-sjc-c.elastichosts.com' - }, - 'tor-p': { - 'name': 'Toronto Peer 1', - 'country': 'Canada', - 'host': 'api-tor-p.elastichosts.com' - }, - 'syd-y': { - 'name': 'Sydney', - 'country': 'Australia', - 'host': 'api-syd-v.elastichosts.com' - }, - 'cn-1': { - 'name': 'Hong Kong', - 'country': 'China', - 'host': 'api-hkg-e.elastichosts.com' - } -} - -# Default API end-point for the base connection class. -DEFAULT_REGION = 'sat-p' - -# Retrieved from http://www.elastichosts.com/cloud-hosting/api -STANDARD_DRIVES = { - '38df0986-4d85-4b76-b502-3878ffc80161': { - 'uuid': '38df0986-4d85-4b76-b502-3878ffc80161', - 'description': 'CentOS Linux 5.5', - 'size_gunzipped': '3GB', - 'supports_deployment': True, - }, - '980cf63c-f21e-4382-997b-6541d5809629': { - 'uuid': '980cf63c-f21e-4382-997b-6541d5809629', - 'description': 'Debian Linux 5.0', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - 'aee5589a-88c3-43ef-bb0a-9cab6e64192d': { - 'uuid': 'aee5589a-88c3-43ef-bb0a-9cab6e64192d', - 'description': 'Ubuntu Linux 10.04', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - '62f512cd-82c7-498e-88d8-a09ac2ef20e7': { - 'uuid': '62f512cd-82c7-498e-88d8-a09ac2ef20e7', - 'description': 'Ubuntu Linux 12.04', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - 'b9d0eb72-d273-43f1-98e3-0d4b87d372c0': { - 'uuid': 'b9d0eb72-d273-43f1-98e3-0d4b87d372c0', - 'description': 'Windows Web Server 2008', - 'size_gunzipped': '13GB', - 'supports_deployment': False, - }, - '30824e97-05a4-410c-946e-2ba5a92b07cb': { - 'uuid': '30824e97-05a4-410c-946e-2ba5a92b07cb', - 'description': 'Windows Web Server 2008 R2', - 'size_gunzipped': '13GB', - 'supports_deployment': False, - }, - '9ecf810e-6ad1-40ef-b360-d606f0444671': { - 'uuid': '9ecf810e-6ad1-40ef-b360-d606f0444671', - 'description': 'Windows Web Server 2008 R2 + SQL Server', - 'size_gunzipped': '13GB', - 'supports_deployment': False, - }, - '10a88d1c-6575-46e3-8d2c-7744065ea530': { - 'uuid': '10a88d1c-6575-46e3-8d2c-7744065ea530', - 'description': 'Windows Server 2008 Standard R2', - 'size_gunzipped': '13GB', - 'supports_deployment': False, - }, - '2567f25c-8fb8-45c7-95fc-bfe3c3d84c47': { - 'uuid': '2567f25c-8fb8-45c7-95fc-bfe3c3d84c47', - 'description': 'Windows Server 2008 Standard R2 + SQL Server', - 'size_gunzipped': '13GB', - 'supports_deployment': False, - }, -} - - -class ElasticHostsException(Exception): - def __str__(self): - return self.args[0] - - def __repr__(self): - return "<ElasticHostsException '%s'>" % (self.args[0]) - - -class ElasticHostsNodeDriver(ElasticStackBaseNodeDriver): - """ - Node Driver class for ElasticHosts - """ - type = Provider.ELASTICHOSTS - api_name = 'elastichosts' - name = 'ElasticHosts' - website = 'http://www.elastichosts.com/' - features = {"create_node": ["generates_password"]} - _standard_drives = STANDARD_DRIVES - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region=DEFAULT_REGION, **kwargs): - - if hasattr(self, '_region'): - region = self._region - - if region not in API_ENDPOINTS: - raise ValueError('Invalid region: %s' % (region)) - - self._host_argument_set = host is not None - super(ElasticHostsNodeDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, - region=region, **kwargs) - - def _ex_connection_class_kwargs(self): - """ - Return the host value based on the user supplied region. - """ - kwargs = {} - if not self._host_argument_set: - kwargs['host'] = API_ENDPOINTS[self.region]['host'] - - return kwargs - - -class ElasticHostsUK1NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the London Peer 1 end-point - """ - name = 'ElasticHosts (lon-p)' - _region = 'lon-p' - - -class ElasticHostsUK2NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the London Bluesquare end-point - """ - name = 'ElasticHosts (lon-b)' - _region = 'lon-b' - - -class ElasticHostsUS1NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the San Antonio Peer 1 end-point - """ - name = 'ElasticHosts (sat-p)' - _region = 'sat-p' - - -class ElasticHostsUS2NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the Los Angeles Peer 1 end-point - """ - name = 'ElasticHosts (lax-p)' - _region = 'lax-p' - - -class ElasticHostsUS3NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the San Jose (Silicon Valley) end-point - """ - name = 'ElasticHosts (sjc-c)' - _region = 'sjc-c' - - -class ElasticHostsCA1NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the Toronto Peer 1 end-point - """ - name = 'ElasticHosts (tor-p)' - _region = 'tor-p' - - -class ElasticHostsAU1NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the Sydney end-point - """ - name = 'ElasticHosts (syd-y)' - _region = 'syd-y' - - -class ElasticHostsCN1NodeDriver(ElasticHostsNodeDriver): - """ - ElasticHosts node driver for the Hong Kong end-point - """ - name = 'ElasticHosts (cn-1)' - _region = 'cn-1' diff --git a/awx/lib/site-packages/libcloud/compute/drivers/elasticstack.py b/awx/lib/site-packages/libcloud/compute/drivers/elasticstack.py deleted file mode 100644 index da3863a3ef..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/elasticstack.py +++ /dev/null @@ -1,488 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Base driver for the providers based on the ElasticStack platform - -http://www.elasticstack.com. -""" - -import re -import time -import base64 - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.common.base import ConnectionUserAndKey, JsonResponse -from libcloud.common.types import InvalidCredsError -from libcloud.compute.types import NodeState -from libcloud.compute.base import NodeDriver, NodeSize, Node -from libcloud.compute.base import NodeImage -from libcloud.compute.deployment import ScriptDeployment, SSHKeyDeployment -from libcloud.compute.deployment import MultiStepDeployment - - -NODE_STATE_MAP = { - 'active': NodeState.RUNNING, - 'dead': NodeState.TERMINATED, - 'dumped': NodeState.TERMINATED, -} - -# Default timeout (in seconds) for the drive imaging process -IMAGING_TIMEOUT = 10 * 60 - -# ElasticStack doesn't specify special instance types, so I just specified -# some plans based on the other provider offerings. -# -# Basically for CPU any value between 500Mhz and 20000Mhz should work, -# 256MB to 8192MB for ram and 1GB to 2TB for disk. -INSTANCE_TYPES = { - 'small': { - 'id': 'small', - 'name': 'Small instance', - 'cpu': 2000, - 'memory': 1700, - 'disk': 160, - 'bandwidth': None, - }, - 'medium': { - 'id': 'medium', - 'name': 'Medium instance', - 'cpu': 3000, - 'memory': 4096, - 'disk': 500, - 'bandwidth': None, - }, - 'large': { - 'id': 'large', - 'name': 'Large instance', - 'cpu': 4000, - 'memory': 7680, - 'disk': 850, - 'bandwidth': None, - }, - 'extra-large': { - 'id': 'extra-large', - 'name': 'Extra Large instance', - 'cpu': 8000, - 'memory': 8192, - 'disk': 1690, - 'bandwidth': None, - }, - 'high-cpu-medium': { - 'id': 'high-cpu-medium', - 'name': 'High-CPU Medium instance', - 'cpu': 5000, - 'memory': 1700, - 'disk': 350, - 'bandwidth': None, - }, - 'high-cpu-extra-large': { - 'id': 'high-cpu-extra-large', - 'name': 'High-CPU Extra Large instance', - 'cpu': 20000, - 'memory': 7168, - 'disk': 1690, - 'bandwidth': None, - }, -} - - -class ElasticStackException(Exception): - def __str__(self): - return self.args[0] - - def __repr__(self): - return "<ElasticStackException '%s'>" % (self.args[0]) - - -class ElasticStackResponse(JsonResponse): - def success(self): - if self.status == 401: - raise InvalidCredsError() - - return self.status >= 200 and self.status <= 299 - - def parse_error(self): - error_header = self.headers.get('x-elastic-error', '') - return 'X-Elastic-Error: %s (%s)' % (error_header, self.body.strip()) - - -class ElasticStackNodeSize(NodeSize): - def __init__(self, id, name, cpu, ram, disk, bandwidth, price, driver): - self.id = id - self.name = name - self.cpu = cpu - self.ram = ram - self.disk = disk - self.bandwidth = bandwidth - self.price = price - self.driver = driver - - def __repr__(self): - return (('<NodeSize: id=%s, name=%s, cpu=%s, ram=%s ' - 'disk=%s bandwidth=%s price=%s driver=%s ...>') - % (self.id, self.name, self.cpu, self.ram, - self.disk, self.bandwidth, self.price, self.driver.name)) - - -class ElasticStackBaseConnection(ConnectionUserAndKey): - """ - Base connection class for the ElasticStack driver - """ - - host = None - responseCls = ElasticStackResponse - - def add_default_headers(self, headers): - headers['Accept'] = 'application/json' - headers['Content-Type'] = 'application/json' - headers['Authorization'] = \ - ('Basic %s' % (base64.b64encode(b('%s:%s' % (self.user_id, - self.key)))) - .decode('utf-8')) - return headers - - -class ElasticStackBaseNodeDriver(NodeDriver): - website = 'http://www.elasticstack.com' - connectionCls = ElasticStackBaseConnection - features = {"create_node": ["generates_password"]} - - def reboot_node(self, node): - # Reboots the node - response = self.connection.request( - action='/servers/%s/reset' % (node.id), - method='POST' - ) - return response.status == 204 - - def destroy_node(self, node): - # Kills the server immediately - response = self.connection.request( - action='/servers/%s/destroy' % (node.id), - method='POST' - ) - return response.status == 204 - - def list_images(self, location=None): - # Returns a list of available pre-installed system drive images - images = [] - for key, value in self._standard_drives.items(): - image = NodeImage( - id=value['uuid'], - name=value['description'], - driver=self.connection.driver, - extra={ - 'size_gunzipped': value['size_gunzipped'] - } - ) - images.append(image) - - return images - - def list_sizes(self, location=None): - sizes = [] - for key, value in INSTANCE_TYPES.items(): - size = ElasticStackNodeSize( - id=value['id'], - name=value['name'], cpu=value['cpu'], ram=value['memory'], - disk=value['disk'], bandwidth=value['bandwidth'], - price=self._get_size_price(size_id=value['id']), - driver=self.connection.driver - ) - sizes.append(size) - - return sizes - - def list_nodes(self): - # Returns a list of active (running) nodes - response = self.connection.request(action='/servers/info').object - - nodes = [] - for data in response: - node = self._to_node(data) - nodes.append(node) - - return nodes - - def create_node(self, **kwargs): - """Creates a ElasticStack instance - - @inherits: :class:`NodeDriver.create_node` - - :keyword name: String with a name for this new node (required) - :type name: ``str`` - - :keyword smp: Number of virtual processors or None to calculate - based on the cpu speed - :type smp: ``int`` - - :keyword nic_model: e1000, rtl8139 or virtio - (if not specified, e1000 is used) - :type nic_model: ``str`` - - :keyword vnc_password: If set, the same password is also used for - SSH access with user toor, - otherwise VNC access is disabled and - no SSH login is possible. - :type vnc_password: ``str`` - """ - size = kwargs['size'] - image = kwargs['image'] - smp = kwargs.get('smp', 'auto') - nic_model = kwargs.get('nic_model', 'e1000') - vnc_password = ssh_password = kwargs.get('vnc_password', None) - - if nic_model not in ('e1000', 'rtl8139', 'virtio'): - raise ElasticStackException('Invalid NIC model specified') - - # check that drive size is not smaller than pre installed image size - - # First we create a drive with the specified size - drive_data = {} - drive_data.update({'name': kwargs['name'], - 'size': '%sG' % (kwargs['size'].disk)}) - - response = self.connection.request(action='/drives/create', - data=json.dumps(drive_data), - method='POST').object - - if not response: - raise ElasticStackException('Drive creation failed') - - drive_uuid = response['drive'] - - # Then we image the selected pre-installed system drive onto it - response = self.connection.request( - action='/drives/%s/image/%s/gunzip' % (drive_uuid, image.id), - method='POST' - ) - - if response.status not in (200, 204): - raise ElasticStackException('Drive imaging failed') - - # We wait until the drive is imaged and then boot up the node - # (in most cases, the imaging process shouldn't take longer - # than a few minutes) - response = self.connection.request( - action='/drives/%s/info' % (drive_uuid) - ).object - - imaging_start = time.time() - while 'imaging' in response: - response = self.connection.request( - action='/drives/%s/info' % (drive_uuid) - ).object - - elapsed_time = time.time() - imaging_start - if ('imaging' in response and elapsed_time >= IMAGING_TIMEOUT): - raise ElasticStackException('Drive imaging timed out') - - time.sleep(1) - - node_data = {} - node_data.update({'name': kwargs['name'], - 'cpu': size.cpu, - 'mem': size.ram, - 'ide:0:0': drive_uuid, - 'boot': 'ide:0:0', - 'smp': smp}) - node_data.update({'nic:0:model': nic_model, 'nic:0:dhcp': 'auto'}) - - if vnc_password: - node_data.update({'vnc': 'auto', 'vnc:password': vnc_password}) - - response = self.connection.request( - action='/servers/create', data=json.dumps(node_data), - method='POST' - ).object - - if isinstance(response, list): - nodes = [self._to_node(node, ssh_password) for node in response] - else: - nodes = self._to_node(response, ssh_password) - - return nodes - - # Extension methods - def ex_set_node_configuration(self, node, **kwargs): - """ - Changes the configuration of the running server - - :param node: Node which should be used - :type node: :class:`Node` - - :param kwargs: keyword arguments - :type kwargs: ``dict`` - - :rtype: ``bool`` - """ - valid_keys = ('^name$', '^parent$', '^cpu$', '^smp$', '^mem$', - '^boot$', '^nic:0:model$', '^nic:0:dhcp', - '^nic:1:model$', '^nic:1:vlan$', '^nic:1:mac$', - '^vnc:ip$', '^vnc:password$', '^vnc:tls', - '^ide:[0-1]:[0-1](:media)?$', - '^scsi:0:[0-7](:media)?$', '^block:[0-7](:media)?$') - - invalid_keys = [] - keys = list(kwargs.keys()) - for key in keys: - matches = False - for regex in valid_keys: - if re.match(regex, key): - matches = True - break - if not matches: - invalid_keys.append(key) - - if invalid_keys: - raise ElasticStackException( - 'Invalid configuration key specified: %s' - % (',' .join(invalid_keys)) - ) - - response = self.connection.request( - action='/servers/%s/set' % (node.id), data=json.dumps(kwargs), - method='POST' - ) - - return (response.status == httplib.OK and response.body != '') - - def deploy_node(self, **kwargs): - """ - Create a new node, and start deployment. - - @inherits: :class:`NodeDriver.deploy_node` - - :keyword enable_root: If true, root password will be set to - vnc_password (this will enable SSH access) - and default 'toor' account will be deleted. - :type enable_root: ``bool`` - """ - image = kwargs['image'] - vnc_password = kwargs.get('vnc_password', None) - enable_root = kwargs.get('enable_root', False) - - if not vnc_password: - raise ValueError('You need to provide vnc_password argument ' - 'if you want to use deployment') - - if (image in self._standard_drives and - not self._standard_drives[image]['supports_deployment']): - raise ValueError('Image %s does not support deployment' - % (image.id)) - - if enable_root: - script = ("unset HISTFILE;" - "echo root:%s | chpasswd;" - "sed -i '/^toor.*$/d' /etc/passwd /etc/shadow;" - "history -c") % vnc_password - root_enable_script = ScriptDeployment(script=script, - delete=True) - deploy = kwargs.get('deploy', None) - if deploy: - if (isinstance(deploy, ScriptDeployment) or - isinstance(deploy, SSHKeyDeployment)): - deployment = MultiStepDeployment([deploy, - root_enable_script]) - elif isinstance(deploy, MultiStepDeployment): - deployment = deploy - deployment.add(root_enable_script) - else: - deployment = root_enable_script - - kwargs['deploy'] = deployment - - if not kwargs.get('ssh_username', None): - kwargs['ssh_username'] = 'toor' - - return super(ElasticStackBaseNodeDriver, self).deploy_node(**kwargs) - - def ex_shutdown_node(self, node): - """ - Sends the ACPI power-down event - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - response = self.connection.request( - action='/servers/%s/shutdown' % (node.id), - method='POST' - ) - return response.status == 204 - - def ex_destroy_drive(self, drive_uuid): - """ - Deletes a drive - - :param drive_uuid: Drive uuid which should be used - :type drive_uuid: ``str`` - - :rtype: ``bool`` - """ - response = self.connection.request( - action='/drives/%s/destroy' % (drive_uuid), - method='POST' - ) - return response.status == 204 - - # Helper methods - def _to_node(self, data, ssh_password=None): - try: - state = NODE_STATE_MAP[data['status']] - except KeyError: - state = NodeState.UNKNOWN - - if isinstance(data['nic:0:dhcp'], list): - public_ip = data['nic:0:dhcp'] - else: - public_ip = [data['nic:0:dhcp']] - - extra = {'cpu': data['cpu'], - 'smp': data['smp'], - 'mem': data['mem'], - 'started': data['started']} - - if 'vnc:ip' in data: - extra['vnc:ip'] = data['vnc:ip'] - - if 'vnc:password' in data: - extra['vnc:password'] = data['vnc:password'] - - boot_device = data['boot'] - - if isinstance(boot_device, list): - for device in boot_device: - extra[device] = data[device] - else: - extra[boot_device] = data[boot_device] - - if ssh_password: - extra.update({'password': ssh_password}) - - node = Node(id=data['server'], name=data['name'], state=state, - public_ips=public_ip, private_ips=None, - driver=self.connection.driver, - extra=extra) - - return node diff --git a/awx/lib/site-packages/libcloud/compute/drivers/exoscale.py b/awx/lib/site-packages/libcloud/compute/drivers/exoscale.py deleted file mode 100644 index 9f883e0b5f..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/exoscale.py +++ /dev/null @@ -1,31 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.compute.providers import Provider -from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver - -__all__ = [ - 'ExoscaleNodeDriver' -] - - -class ExoscaleNodeDriver(CloudStackNodeDriver): - type = Provider.EXOSCALE - name = 'Exoscale' - website = 'https://www.exoscale.ch/' - - # API endpoint info - host = 'api.exoscale.ch' - path = '/compute' diff --git a/awx/lib/site-packages/libcloud/compute/drivers/gandi.py b/awx/lib/site-packages/libcloud/compute/drivers/gandi.py deleted file mode 100644 index e5593b4684..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/gandi.py +++ /dev/null @@ -1,619 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Gandi driver for compute -""" -import sys -from datetime import datetime - -from libcloud.common.gandi import BaseGandiDriver, GandiException,\ - NetworkInterface, IPAddress, Disk -from libcloud.compute.base import StorageVolume -from libcloud.compute.types import NodeState, Provider -from libcloud.compute.base import Node, NodeDriver -from libcloud.compute.base import NodeSize, NodeImage, NodeLocation - - -NODE_STATE_MAP = { - 'running': NodeState.RUNNING, - 'halted': NodeState.TERMINATED, - 'paused': NodeState.TERMINATED, - 'locked': NodeState.TERMINATED, - 'being_created': NodeState.PENDING, - 'invalid': NodeState.UNKNOWN, - 'legally_locked': NodeState.PENDING, - 'deleted': NodeState.TERMINATED -} - -NODE_PRICE_HOURLY_USD = 0.02 - -INSTANCE_TYPES = { - 'small': { - 'id': 'small', - 'name': 'Small instance', - 'cpu': 1, - 'memory': 256, - 'disk': 3, - 'bandwidth': 10240, - }, - 'medium': { - 'id': 'medium', - 'name': 'Medium instance', - 'cpu': 1, - 'memory': 1024, - 'disk': 20, - 'bandwidth': 10240, - }, - 'large': { - 'id': 'large', - 'name': 'Large instance', - 'cpu': 2, - 'memory': 2048, - 'disk': 50, - 'bandwidth': 10240, - }, - 'x-large': { - 'id': 'x-large', - 'name': 'Extra Large instance', - 'cpu': 4, - 'memory': 4096, - 'disk': 100, - 'bandwidth': 10240, - }, -} - - -class GandiNodeDriver(BaseGandiDriver, NodeDriver): - """ - Gandi node driver - - """ - api_name = 'gandi' - friendly_name = 'Gandi.net' - website = 'http://www.gandi.net/' - country = 'FR' - type = Provider.GANDI - # TODO : which features to enable ? - features = {} - - def __init__(self, *args, **kwargs): - """ - @inherits: :class:`NodeDriver.__init__` - """ - super(BaseGandiDriver, self).__init__(*args, **kwargs) - - def _resource_info(self, type, id): - try: - obj = self.connection.request('hosting.%s.info' % type, int(id)) - return obj.object - except Exception: - e = sys.exc_info()[1] - raise GandiException(1003, e) - return None - - def _node_info(self, id): - return self._resource_info('vm', id) - - def _volume_info(self, id): - return self._resource_info('disk', id) - - # Generic methods for driver - def _to_node(self, vm): - return Node( - id=vm['id'], - name=vm['hostname'], - state=NODE_STATE_MAP.get( - vm['state'], - NodeState.UNKNOWN - ), - public_ips=vm.get('ips', []), - private_ips=[], - driver=self, - extra={ - 'ai_active': vm.get('ai_active'), - 'datacenter_id': vm.get('datacenter_id'), - 'description': vm.get('description') - } - ) - - def _to_nodes(self, vms): - return [self._to_node(v) for v in vms] - - def _to_volume(self, disk): - extra = {'can_snapshot': disk['can_snapshot']} - return StorageVolume( - id=disk['id'], - name=disk['name'], - size=int(disk['size']), - driver=self, - extra=extra) - - def _to_volumes(self, disks): - return [self._to_volume(d) for d in disks] - - def list_nodes(self): - vms = self.connection.request('hosting.vm.list').object - ips = self.connection.request('hosting.ip.list').object - for vm in vms: - vm['ips'] = [] - for ip in ips: - if vm['ifaces_id'][0] == ip['iface_id']: - ip = ip.get('ip', None) - if ip: - vm['ips'].append(ip) - - nodes = self._to_nodes(vms) - return nodes - - def reboot_node(self, node): - op = self.connection.request('hosting.vm.reboot', int(node.id)) - self._wait_operation(op.object['id']) - vm = self._node_info(int(node.id)) - if vm['state'] == 'running': - return True - return False - - def destroy_node(self, node): - vm = self._node_info(node.id) - if vm['state'] == 'running': - # Send vm_stop and wait for accomplish - op_stop = self.connection.request('hosting.vm.stop', int(node.id)) - if not self._wait_operation(op_stop.object['id']): - raise GandiException(1010, 'vm.stop failed') - # Delete - op = self.connection.request('hosting.vm.delete', int(node.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def deploy_node(self, **kwargs): - """ - deploy_node is not implemented for gandi driver - - :rtype: ``bool`` - """ - raise NotImplementedError( - 'deploy_node not implemented for gandi driver') - - def create_node(self, **kwargs): - """ - Create a new Gandi node - - :keyword name: String with a name for this new node (required) - :type name: ``str`` - - :keyword image: OS Image to boot on node. (required) - :type image: :class:`NodeImage` - - :keyword location: Which data center to create a node in. If empty, - undefined behavior will be selected. (optional) - :type location: :class:`NodeLocation` - - :keyword size: The size of resources allocated to this node. - (required) - :type size: :class:`NodeSize` - - :keyword login: user name to create for login on machine (required) - :type login: ``str`` - - :keyword password: password for user that'll be created (required) - :type password: ``str`` - - :keyword inet_family: version of ip to use, default 4 (optional) - :type inet_family: ``int`` - - :rtype: :class:`Node` - """ - - if kwargs.get('login') is None or kwargs.get('password') is None: - raise GandiException( - 1020, 'login and password must be defined for node creation') - - location = kwargs.get('location') - if location and isinstance(location, NodeLocation): - dc_id = int(location.id) - else: - raise GandiException( - 1021, 'location must be a subclass of NodeLocation') - - size = kwargs.get('size') - if not size and not isinstance(size, NodeSize): - raise GandiException( - 1022, 'size must be a subclass of NodeSize') - - # If size name is in INSTANCE_TYPE we use new rating model - instance = INSTANCE_TYPES.get(size.id) - cores = instance['cpu'] if instance else int(size.id) - - src_disk_id = int(kwargs['image'].id) - - disk_spec = { - 'datacenter_id': dc_id, - 'name': 'disk_%s' % kwargs['name'] - } - - vm_spec = { - 'datacenter_id': dc_id, - 'hostname': kwargs['name'], - 'login': kwargs['login'], - 'password': kwargs['password'], # TODO : use NodeAuthPassword - 'memory': int(size.ram), - 'cores': cores, - 'bandwidth': int(size.bandwidth), - 'ip_version': kwargs.get('inet_family', 4), - } - - # Call create_from helper api. Return 3 operations : disk_create, - # iface_create,vm_create - (op_disk, op_iface, op_vm) = self.connection.request( - 'hosting.vm.create_from', - vm_spec, disk_spec, src_disk_id - ).object - - # We wait for vm_create to finish - if self._wait_operation(op_vm['id']): - # after successful operation, get ip information - # thru first interface - node = self._node_info(op_vm['vm_id']) - ifaces = node.get('ifaces') - if len(ifaces) > 0: - ips = ifaces[0].get('ips') - if len(ips) > 0: - node['ip'] = ips[0]['ip'] - return self._to_node(node) - - return None - - def _to_image(self, img): - return NodeImage( - id=img['disk_id'], - name=img['label'], - driver=self.connection.driver - ) - - def list_images(self, location=None): - try: - if location: - filtering = {'datacenter_id': int(location.id)} - else: - filtering = {} - images = self.connection.request('hosting.image.list', filtering) - return [self._to_image(i) for i in images.object] - except Exception: - e = sys.exc_info()[1] - raise GandiException(1011, e) - - def _to_size(self, id, size): - return NodeSize( - id=id, - name='%s cores' % id, - ram=size['memory'], - disk=size['disk'], - bandwidth=size['bandwidth'], - price=(self._get_size_price(size_id='1') * id), - driver=self.connection.driver, - ) - - def _instance_type_to_size(self, instance): - return NodeSize( - id=instance['id'], - name=instance['name'], - ram=instance['memory'], - disk=instance['disk'], - bandwidth=instance['bandwidth'], - price=self._get_size_price(size_id=instance['id']), - driver=self.connection.driver, - ) - - def list_instance_type(self, location=None): - return [self._instance_type_to_size(instance) - for name, instance in INSTANCE_TYPES.items()] - - def list_sizes(self, location=None): - account = self.connection.request('hosting.account.info').object - if account.get('rating_enabled'): - # This account use new rating model - return self.list_instance_type(location) - # Look for available shares, and return a list of share_definition - available_res = account['resources']['available'] - - if available_res['shares'] == 0: - return None - else: - share_def = account['share_definition'] - available_cores = available_res['cores'] - # 0.75 core given when creating a server - max_core = int(available_cores + 0.75) - shares = [] - if available_res['servers'] < 1: - # No server quota, no way - return shares - for i in range(1, max_core + 1): - share = {id: i} - share_is_available = True - for k in ['memory', 'disk', 'bandwidth']: - if share_def[k] * i > available_res[k]: - # We run out for at least one resource inside - share_is_available = False - else: - share[k] = share_def[k] * i - if share_is_available: - nb_core = i - shares.append(self._to_size(nb_core, share)) - return shares - - def _to_loc(self, loc): - return NodeLocation( - id=loc['id'], - name=loc['name'], - country=loc['country'], - driver=self - ) - - def list_locations(self): - res = self.connection.request('hosting.datacenter.list') - return [self._to_loc(l) for l in res.object] - - def list_volumes(self): - """ - - :rtype: ``list`` of :class:`StorageVolume` - """ - res = self.connection.request('hosting.disk.list', {}) - return self._to_volumes(res.object) - - def create_volume(self, size, name, location=None, snapshot=None): - disk_param = { - 'name': name, - 'size': int(size), - 'datacenter_id': int(location.id) - } - if snapshot: - op = self.connection.request('hosting.disk.create_from', - disk_param, int(snapshot.id)) - else: - op = self.connection.request('hosting.disk.create', disk_param) - if self._wait_operation(op.object['id']): - disk = self._volume_info(op.object['disk_id']) - return self._to_volume(disk) - return None - - def attach_volume(self, node, volume, device=None): - op = self.connection.request('hosting.vm.disk_attach', - int(node.id), int(volume.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def detach_volume(self, node, volume): - """ - Detaches a volume from a node. - - :param node: Node which should be used - :type node: :class:`Node` - - :param volume: Volume to be detached - :type volume: :class:`StorageVolume` - - :rtype: ``bool`` - """ - op = self.connection.request('hosting.vm.disk_detach', - int(node.id), int(volume.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def destroy_volume(self, volume): - op = self.connection.request('hosting.disk.delete', int(volume.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def _to_iface(self, iface): - ips = [] - for ip in iface.get('ips', []): - new_ip = IPAddress( - ip['id'], - NODE_STATE_MAP.get( - ip['state'], - NodeState.UNKNOWN - ), - ip['ip'], - self.connection.driver, - version=ip.get('version'), - extra={'reverse': ip['reverse']} - ) - ips.append(new_ip) - return NetworkInterface( - iface['id'], - NODE_STATE_MAP.get( - iface['state'], - NodeState.UNKNOWN - ), - mac_address=None, - driver=self.connection.driver, - ips=ips, - node_id=iface.get('vm_id'), - extra={'bandwidth': iface['bandwidth']}, - ) - - def _to_ifaces(self, ifaces): - return [self._to_iface(i) for i in ifaces] - - def ex_list_interfaces(self): - """ - Specific method to list network interfaces - - :rtype: ``list`` of :class:`GandiNetworkInterface` - """ - ifaces = self.connection.request('hosting.iface.list').object - ips = self.connection.request('hosting.ip.list').object - for iface in ifaces: - iface['ips'] = list( - filter(lambda i: i['iface_id'] == iface['id'], ips)) - return self._to_ifaces(ifaces) - - def _to_disk(self, element): - disk = Disk( - id=element['id'], - state=NODE_STATE_MAP.get( - element['state'], - NodeState.UNKNOWN - ), - name=element['name'], - driver=self.connection.driver, - size=element['size'], - extra={'can_snapshot': element['can_snapshot']} - ) - return disk - - def _to_disks(self, elements): - return [self._to_disk(el) for el in elements] - - def ex_list_disks(self): - """ - Specific method to list all disk - - :rtype: ``list`` of :class:`GandiDisk` - """ - res = self.connection.request('hosting.disk.list', {}) - return self._to_disks(res.object) - - def ex_node_attach_disk(self, node, disk): - """ - Specific method to attach a disk to a node - - :param node: Node which should be used - :type node: :class:`Node` - - :param disk: Disk which should be used - :type disk: :class:`GandiDisk` - - :rtype: ``bool`` - """ - op = self.connection.request('hosting.vm.disk_attach', - int(node.id), int(disk.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def ex_node_detach_disk(self, node, disk): - """ - Specific method to detach a disk from a node - - :param node: Node which should be used - :type node: :class:`Node` - - :param disk: Disk which should be used - :type disk: :class:`GandiDisk` - - :rtype: ``bool`` - """ - op = self.connection.request('hosting.vm.disk_detach', - int(node.id), int(disk.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def ex_node_attach_interface(self, node, iface): - """ - Specific method to attach an interface to a node - - :param node: Node which should be used - :type node: :class:`Node` - - - :param iface: Network interface which should be used - :type iface: :class:`GandiNetworkInterface` - - :rtype: ``bool`` - """ - op = self.connection.request('hosting.vm.iface_attach', - int(node.id), int(iface.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def ex_node_detach_interface(self, node, iface): - """ - Specific method to detach an interface from a node - - :param node: Node which should be used - :type node: :class:`Node` - - - :param iface: Network interface which should be used - :type iface: :class:`GandiNetworkInterface` - - :rtype: ``bool`` - """ - op = self.connection.request('hosting.vm.iface_detach', - int(node.id), int(iface.id)) - if self._wait_operation(op.object['id']): - return True - return False - - def ex_snapshot_disk(self, disk, name=None): - """ - Specific method to make a snapshot of a disk - - :param disk: Disk which should be used - :type disk: :class:`GandiDisk` - - :param name: Name which should be used - :type name: ``str`` - - :rtype: ``bool`` - """ - if not disk.extra.get('can_snapshot'): - raise GandiException(1021, 'Disk %s can\'t snapshot' % disk.id) - if not name: - suffix = datetime.today().strftime('%Y%m%d') - name = 'snap_%s' % (suffix) - op = self.connection.request( - 'hosting.disk.create_from', - {'name': name, 'type': 'snapshot', }, - int(disk.id), - ) - if self._wait_operation(op.object['id']): - return True - return False - - def ex_update_disk(self, disk, new_size=None, new_name=None): - """Specific method to update size or name of a disk - WARNING: if a server is attached it'll be rebooted - - :param disk: Disk which should be used - :type disk: :class:`GandiDisk` - - :param new_size: New size - :type new_size: ``int`` - - :param new_name: New name - :type new_name: ``str`` - - :rtype: ``bool`` - """ - params = {} - if new_size: - params.update({'size': new_size}) - if new_name: - params.update({'name': new_name}) - op = self.connection.request('hosting.disk.update', - int(disk.id), - params) - if self._wait_operation(op.object['id']): - return True - return False diff --git a/awx/lib/site-packages/libcloud/compute/drivers/gce.py b/awx/lib/site-packages/libcloud/compute/drivers/gce.py deleted file mode 100644 index a1cf75e16b..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/gce.py +++ /dev/null @@ -1,3346 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Module for Google Compute Engine Driver. -""" -from __future__ import with_statement - -import datetime -import time -import sys - -from libcloud.common.google import GoogleResponse -from libcloud.common.google import GoogleBaseConnection -from libcloud.common.google import GoogleBaseError -from libcloud.common.google import ResourceNotFoundError -from libcloud.common.google import ResourceExistsError - -from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation -from libcloud.compute.base import NodeSize, StorageVolume, VolumeSnapshot -from libcloud.compute.base import UuidMixin -from libcloud.compute.providers import Provider -from libcloud.compute.types import NodeState - -API_VERSION = 'v1' -DEFAULT_TASK_COMPLETION_TIMEOUT = 180 - - -def timestamp_to_datetime(timestamp): - """ - Return a datetime object that corresponds to the time in an RFC3339 - timestamp. - - :param timestamp: RFC3339 timestamp string - :type timestamp: ``str`` - - :return: Datetime object corresponding to timestamp - :rtype: :class:`datetime.datetime` - """ - # We remove timezone offset and microseconds (Python 2.5 strptime doesn't - # support %f) - ts = datetime.datetime.strptime(timestamp[:-10], '%Y-%m-%dT%H:%M:%S') - tz_hours = int(timestamp[-5:-3]) - tz_mins = int(timestamp[-2:]) * int(timestamp[-6:-5] + '1') - tz_delta = datetime.timedelta(hours=tz_hours, minutes=tz_mins) - return ts + tz_delta - - -class GCEResponse(GoogleResponse): - pass - - -class GCEConnection(GoogleBaseConnection): - """Connection class for the GCE driver.""" - host = 'www.googleapis.com' - responseCls = GCEResponse - - def __init__(self, user_id, key, secure, auth_type=None, - credential_file=None, project=None, **kwargs): - super(GCEConnection, self).__init__(user_id, key, secure=secure, - auth_type=auth_type, - credential_file=credential_file, - **kwargs) - self.request_path = '/compute/%s/projects/%s' % (API_VERSION, - project) - - -class GCEAddress(UuidMixin): - """A GCE Static address.""" - def __init__(self, id, name, address, region, driver, extra=None): - self.id = str(id) - self.name = name - self.address = address - self.region = region - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def destroy(self): - """ - Destroy this address. - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_destroy_address(address=self) - - def __repr__(self): - return '<GCEAddress id="%s" name="%s" address="%s">' % ( - self.id, self.name, self.address) - - -class GCEFailedDisk(object): - """Dummy Node object for disks that are not created.""" - def __init__(self, name, error, code): - self.name = name - self.error = error - self.code = code - - def __repr__(self): - return '<GCEFailedDisk name="%s" error_code="%s">' % ( - self.name, self.code) - - -class GCEFailedNode(object): - """Dummy Node object for nodes that are not created.""" - def __init__(self, name, error, code): - self.name = name - self.error = error - self.code = code - - def __repr__(self): - return '<GCEFailedNode name="%s" error_code="%s">' % ( - self.name, self.code) - - -class GCEHealthCheck(UuidMixin): - """A GCE Http Health Check class.""" - def __init__(self, id, name, path, port, interval, timeout, - unhealthy_threshold, healthy_threshold, driver, extra=None): - self.id = str(id) - self.name = name - self.path = path - self.port = port - self.interval = interval - self.timeout = timeout - self.unhealthy_threshold = unhealthy_threshold - self.healthy_threshold = healthy_threshold - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def destroy(self): - """ - Destroy this Health Check. - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_destroy_healthcheck(healthcheck=self) - - def update(self): - """ - Commit updated healthcheck values. - - :return: Updated Healthcheck object - :rtype: :class:`GCEHealthcheck` - """ - return self.driver.ex_update_healthcheck(healthcheck=self) - - def __repr__(self): - return '<GCEHealthCheck id="%s" name="%s" path="%s" port="%s">' % ( - self.id, self.name, self.path, self.port) - - -class GCEFirewall(UuidMixin): - """A GCE Firewall rule class.""" - def __init__(self, id, name, allowed, network, source_ranges, source_tags, - target_tags, driver, extra=None): - self.id = str(id) - self.name = name - self.network = network - self.allowed = allowed - self.source_ranges = source_ranges - self.source_tags = source_tags - self.target_tags = target_tags - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def destroy(self): - """ - Destroy this firewall. - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_destroy_firewall(firewall=self) - - def update(self): - """ - Commit updated firewall values. - - :return: Updated Firewall object - :rtype: :class:`GCEFirewall` - """ - return self.driver.ex_update_firewall(firewall=self) - - def __repr__(self): - return '<GCEFirewall id="%s" name="%s" network="%s">' % ( - self.id, self.name, self.network.name) - - -class GCEForwardingRule(UuidMixin): - def __init__(self, id, name, region, address, protocol, targetpool, driver, - extra=None): - self.id = str(id) - self.name = name - self.region = region - self.address = address - self.protocol = protocol - self.targetpool = targetpool - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def destroy(self): - """ - Destroy this Forwarding Rule - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_destroy_forwarding_rule(forwarding_rule=self) - - def __repr__(self): - return '<GCEForwardingRule id="%s" name="%s" address="%s">' % ( - self.id, self.name, self.address) - - -class GCENodeImage(NodeImage): - """A GCE Node Image class.""" - def __init__(self, id, name, driver, extra=None): - super(GCENodeImage, self).__init__(id, name, driver, extra=extra) - - def delete(self): - """ - Delete this image - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_delete_image(image=self) - - def deprecate(self, replacement, state): - """ - Deprecate this image - - :param replacement: Image to use as a replacement - :type replacement: ``str`` or :class: `GCENodeImage` - - :param state: Deprecation state of this image. Possible values include - \'DELETED\', \'DEPRECATED\' or \'OBSOLETE\'. - :type state: ``str`` - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_deprecate_image(self, replacement, state) - - -class GCENetwork(UuidMixin): - """A GCE Network object class.""" - def __init__(self, id, name, cidr, driver, extra=None): - self.id = str(id) - self.name = name - self.cidr = cidr - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def destroy(self): - """ - Destroy this network - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_destroy_network(network=self) - - def __repr__(self): - return '<GCENetwork id="%s" name="%s" cidr="%s">' % ( - self.id, self.name, self.cidr) - - -class GCENodeSize(NodeSize): - """A GCE Node Size (MachineType) class.""" - def __init__(self, id, name, ram, disk, bandwidth, price, driver, - extra=None): - self.extra = extra - super(GCENodeSize, self).__init__(id, name, ram, disk, bandwidth, - price, driver, extra=extra) - - -class GCEProject(UuidMixin): - """GCE Project information.""" - def __init__(self, id, name, metadata, quotas, driver, extra=None): - self.id = str(id) - self.name = name - self.metadata = metadata - self.quotas = quotas - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def __repr__(self): - return '<GCEProject id="%s" name="%s">' % (self.id, self.name) - - -class GCERegion(UuidMixin): - def __init__(self, id, name, status, zones, quotas, deprecated, driver, - extra=None): - self.id = str(id) - self.name = name - self.status = status - self.zones = zones - self.quotas = quotas - self.deprecated = deprecated - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def __repr__(self): - return '<GCERegion id="%s" name="%s", status="%s">' % ( - self.id, self.name, self.status) - - -class GCESnapshot(VolumeSnapshot): - def __init__(self, id, name, size, status, driver, extra=None): - self.name = name - self.status = status - super(GCESnapshot, self).__init__(id, driver, size, extra) - - -class GCETargetPool(UuidMixin): - def __init__(self, id, name, region, healthchecks, nodes, driver, - extra=None): - self.id = str(id) - self.name = name - self.region = region - self.healthchecks = healthchecks - self.nodes = nodes - self.driver = driver - self.extra = extra - UuidMixin.__init__(self) - - def add_node(self, node): - """ - Add a node to this target pool. - - :param node: Node to add - :type node: ``str`` or :class:`Node` - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_targetpool_add_node(targetpool=self, node=node) - - def remove_node(self, node): - """ - Remove a node from this target pool. - - :param node: Node to remove - :type node: ``str`` or :class:`Node` - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_targetpool_remove_node(targetpool=self, - node=node) - - def add_healthcheck(self, healthcheck): - """ - Add a healthcheck to this target pool. - - :param healthcheck: Healthcheck to add - :type healthcheck: ``str`` or :class:`GCEHealthCheck` - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_targetpool_add_healthcheck( - targetpool=self, healthcheck=healthcheck) - - def remove_healthcheck(self, healthcheck): - """ - Remove a healthcheck from this target pool. - - :param healthcheck: Healthcheck to remove - :type healthcheck: ``str`` or :class:`GCEHealthCheck` - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_targetpool_remove_healthcheck( - targetpool=self, healthcheck=healthcheck) - - def destroy(self): - """ - Destroy this Target Pool - - :return: True if successful - :rtype: ``bool`` - """ - return self.driver.ex_destroy_targetpool(targetpool=self) - - def __repr__(self): - return '<GCETargetPool id="%s" name="%s" region="%s">' % ( - self.id, self.name, self.region.name) - - -class GCEZone(NodeLocation): - """Subclass of NodeLocation to provide additional information.""" - def __init__(self, id, name, status, maintenance_windows, deprecated, - driver, extra=None): - self.status = status - self.maintenance_windows = maintenance_windows - self.deprecated = deprecated - self.extra = extra - country = name.split('-')[0] - super(GCEZone, self).__init__(id=str(id), name=name, country=country, - driver=driver) - - @property - def time_until_mw(self): - """ - Returns the time until the next Maintenance Window as a - datetime.timedelta object. - """ - return self._get_time_until_mw() - - @property - def next_mw_duration(self): - """ - Returns the duration of the next Maintenance Window as a - datetime.timedelta object. - """ - return self._get_next_mw_duration() - - def _now(self): - """ - Returns current UTC time. - - Can be overridden in unittests. - """ - return datetime.datetime.utcnow() - - def _get_next_maint(self): - """ - Returns the next Maintenance Window. - - :return: A dictionary containing maintenance window info (or None if - no maintenance windows are scheduled) - The dictionary contains 4 keys with values of type ``str`` - - name: The name of the maintenance window - - description: Description of the maintenance window - - beginTime: RFC3339 Timestamp - - endTime: RFC3339 Timestamp - :rtype: ``dict`` or ``None`` - """ - begin = None - next_window = None - if not self.maintenance_windows: - return None - if len(self.maintenance_windows) == 1: - return self.maintenance_windows[0] - for mw in self.maintenance_windows: - begin_next = timestamp_to_datetime(mw['beginTime']) - if (not begin) or (begin_next < begin): - begin = begin_next - next_window = mw - return next_window - - def _get_time_until_mw(self): - """ - Returns time until next maintenance window. - - :return: Time until next maintenance window (or None if no - maintenance windows are scheduled) - :rtype: :class:`datetime.timedelta` or ``None`` - """ - next_window = self._get_next_maint() - if not next_window: - return None - now = self._now() - next_begin = timestamp_to_datetime(next_window['beginTime']) - return next_begin - now - - def _get_next_mw_duration(self): - """ - Returns the duration of the next maintenance window. - - :return: Duration of next maintenance window (or None if no - maintenance windows are scheduled) - :rtype: :class:`datetime.timedelta` or ``None`` - """ - next_window = self._get_next_maint() - if not next_window: - return None - next_begin = timestamp_to_datetime(next_window['beginTime']) - next_end = timestamp_to_datetime(next_window['endTime']) - return next_end - next_begin - - def __repr__(self): - return '<GCEZone id="%s" name="%s" status="%s">' % (self.id, self.name, - self.status) - - -class GCENodeDriver(NodeDriver): - """ - GCE Node Driver class. - - This is the primary driver for interacting with Google Compute Engine. It - contains all of the standard libcloud methods, plus additional ex_* methods - for more features. - - Note that many methods allow either objects or strings (or lists of - objects/strings). In most cases, passing strings instead of objects will - result in additional GCE API calls. - """ - connectionCls = GCEConnection - api_name = 'googleapis' - name = "Google Compute Engine" - type = Provider.GCE - website = 'https://cloud.google.com/' - - NODE_STATE_MAP = { - "PROVISIONING": NodeState.PENDING, - "STAGING": NodeState.PENDING, - "RUNNING": NodeState.RUNNING, - "STOPPED": NodeState.TERMINATED, - "STOPPING": NodeState.TERMINATED, - "TERMINATED": NodeState.TERMINATED - } - - def __init__(self, user_id, key, datacenter=None, project=None, - auth_type=None, scopes=None, **kwargs): - """ - :param user_id: The email address (for service accounts) or Client ID - (for installed apps) to be used for authentication. - :type user_id: ``str`` - - :param key: The RSA Key (for service accounts) or file path containing - key or Client Secret (for installed apps) to be used for - authentication. - :type key: ``str`` - - :keyword datacenter: The name of the datacenter (zone) used for - operations. - :type datacenter: ``str`` - - :keyword project: Your GCE project name. (required) - :type project: ``str`` - - :keyword auth_type: Accepted values are "SA" or "IA" - ("Service Account" or "Installed Application"). - If not supplied, auth_type will be guessed based - on value of user_id. - :type auth_type: ``str`` - - :keyword scopes: List of authorization URLs. Default is empty and - grants read/write to Compute, Storage, DNS. - :type scopes: ``list`` - """ - self.auth_type = auth_type - self.project = project - self.scopes = scopes - if not self.project: - raise ValueError('Project name must be specified using ' - '"project" keyword.') - super(GCENodeDriver, self).__init__(user_id, key, **kwargs) - - # Cache Zone and Region information to reduce API calls and - # increase speed - self.base_path = '/compute/%s/projects/%s' % (API_VERSION, - self.project) - self.zone_list = self.ex_list_zones() - self.zone_dict = {} - for zone in self.zone_list: - self.zone_dict[zone.name] = zone - if datacenter: - self.zone = self.ex_get_zone(datacenter) - else: - self.zone = None - - self.region_list = self.ex_list_regions() - self.region_dict = {} - for region in self.region_list: - self.region_dict[region.name] = region - - if self.zone: - self.region = self._get_region_from_zone(self.zone) - else: - self.region = None - - def ex_list_addresses(self, region=None): - """ - Return a list of static addresses for a region or all. - - :keyword region: The region to return addresses from. For example: - 'us-central1'. If None, will return addresses from - region of self.zone. If 'all', will return all - addresses. - :type region: ``str`` or ``None`` - - :return: A list of static address objects. - :rtype: ``list`` of :class:`GCEAddress` - """ - list_addresses = [] - region = self._set_region(region) - if region is None: - request = '/aggregated/addresses' - else: - request = '/regions/%s/addresses' % (region.name) - response = self.connection.request(request, method='GET').object - - if 'items' in response: - # The aggregated result returns dictionaries for each region - if region is None: - for v in response['items'].values(): - region_addresses = [self._to_address(a) for a in - v.get('addresses', [])] - list_addresses.extend(region_addresses) - else: - list_addresses = [self._to_address(a) for a in - response['items']] - return list_addresses - - def ex_list_healthchecks(self): - """ - Return the list of health checks. - - :return: A list of health check objects. - :rtype: ``list`` of :class:`GCEHealthCheck` - """ - list_healthchecks = [] - request = '/global/httpHealthChecks' - response = self.connection.request(request, method='GET').object - list_healthchecks = [self._to_healthcheck(h) for h in - response.get('items', [])] - return list_healthchecks - - def ex_list_firewalls(self): - """ - Return the list of firewalls. - - :return: A list of firewall objects. - :rtype: ``list`` of :class:`GCEFirewall` - """ - list_firewalls = [] - request = '/global/firewalls' - response = self.connection.request(request, method='GET').object - list_firewalls = [self._to_firewall(f) for f in - response.get('items', [])] - return list_firewalls - - def ex_list_forwarding_rules(self, region=None): - """ - Return the list of forwarding rules for a region or all. - - :keyword region: The region to return forwarding rules from. For - example: 'us-central1'. If None, will return - forwarding rules from the region of self.region - (which is based on self.zone). If 'all', will - return all forwarding rules. - :type region: ``str`` or :class:`GCERegion` or ``None`` - - :return: A list of forwarding rule objects. - :rtype: ``list`` of :class:`GCEForwardingRule` - """ - list_forwarding_rules = [] - region = self._set_region(region) - if region is None: - request = '/aggregated/forwardingRules' - else: - request = '/regions/%s/forwardingRules' % (region.name) - response = self.connection.request(request, method='GET').object - - if 'items' in response: - # The aggregated result returns dictionaries for each region - if region is None: - for v in response['items'].values(): - region_forwarding_rules = [self._to_forwarding_rule(f) for - f in v.get('forwardingRules', - [])] - list_forwarding_rules.extend(region_forwarding_rules) - else: - list_forwarding_rules = [self._to_forwarding_rule(f) for f in - response['items']] - return list_forwarding_rules - - def list_images(self, ex_project=None): - """ - Return a list of image objects for a project. - - :keyword ex_project: Optional alternate project name. - :type ex_project: ``str`` or ``None`` - - :return: List of GCENodeImage objects - :rtype: ``list`` of :class:`GCENodeImage` - """ - request = '/global/images' - if ex_project is None: - response = self.connection.request(request, method='GET').object - else: - # Save the connection request_path - save_request_path = self.connection.request_path - # Override the connection request path - new_request_path = save_request_path.replace(self.project, - ex_project) - self.connection.request_path = new_request_path - response = self.connection.request(request, method='GET').object - # Restore the connection request_path - self.connection.request_path = save_request_path - list_images = [self._to_node_image(i) for i in - response.get('items', [])] - return list_images - - def list_locations(self): - """ - Return a list of locations (zones). - - The :class:`ex_list_zones` method returns more comprehensive results, - but this is here for compatibility. - - :return: List of NodeLocation objects - :rtype: ``list`` of :class:`NodeLocation` - """ - list_locations = [] - request = '/zones' - response = self.connection.request(request, method='GET').object - list_locations = [self._to_node_location(l) for l in response['items']] - return list_locations - - def ex_list_networks(self): - """ - Return the list of networks. - - :return: A list of network objects. - :rtype: ``list`` of :class:`GCENetwork` - """ - list_networks = [] - request = '/global/networks' - response = self.connection.request(request, method='GET').object - list_networks = [self._to_network(n) for n in - response.get('items', [])] - return list_networks - - def list_nodes(self, ex_zone=None): - """ - Return a list of nodes in the current zone or all zones. - - :keyword ex_zone: Optional zone name or 'all' - :type ex_zone: ``str`` or :class:`GCEZone` or - :class:`NodeLocation` or ``None`` - - :return: List of Node objects - :rtype: ``list`` of :class:`Node` - """ - list_nodes = [] - zone = self._set_zone(ex_zone) - if zone is None: - request = '/aggregated/instances' - else: - request = '/zones/%s/instances' % (zone.name) - - response = self.connection.request(request, method='GET').object - - if 'items' in response: - # The aggregated response returns a dict for each zone - if zone is None: - for v in response['items'].values(): - zone_nodes = [self._to_node(i) for i in - v.get('instances', [])] - list_nodes.extend(zone_nodes) - else: - list_nodes = [self._to_node(i) for i in response['items']] - return list_nodes - - def ex_list_regions(self): - """ - Return the list of regions. - - :return: A list of region objects. - :rtype: ``list`` of :class:`GCERegion` - """ - list_regions = [] - request = '/regions' - response = self.connection.request(request, method='GET').object - list_regions = [self._to_region(r) for r in response['items']] - return list_regions - - def list_sizes(self, location=None): - """ - Return a list of sizes (machineTypes) in a zone. - - :keyword location: Location or Zone for sizes - :type location: ``str`` or :class:`GCEZone` or - :class:`NodeLocation` or ``None`` - - :return: List of GCENodeSize objects - :rtype: ``list`` of :class:`GCENodeSize` - """ - list_sizes = [] - zone = self._set_zone(location) - if zone is None: - request = '/aggregated/machineTypes' - else: - request = '/zones/%s/machineTypes' % (zone.name) - - response = self.connection.request(request, method='GET').object - - if 'items' in response: - # The aggregated response returns a dict for each zone - if zone is None: - for v in response['items'].values(): - zone_sizes = [self._to_node_size(s) for s in - v.get('machineTypes', [])] - list_sizes.extend(zone_sizes) - else: - list_sizes = [self._to_node_size(s) for s in response['items']] - return list_sizes - - def ex_list_snapshots(self): - """ - Return the list of disk snapshots in the project. - - :return: A list of snapshot objects - :rtype: ``list`` of :class:`GCESnapshot` - """ - list_snapshots = [] - request = '/global/snapshots' - response = self.connection.request(request, method='GET').object - list_snapshots = [self._to_snapshot(s) for s in - response.get('items', [])] - return list_snapshots - - def ex_list_targetpools(self, region=None): - """ - Return the list of target pools. - - :return: A list of target pool objects - :rtype: ``list`` of :class:`GCETargetPool` - """ - list_targetpools = [] - region = self._set_region(region) - if region is None: - request = '/aggregated/targetPools' - else: - request = '/regions/%s/targetPools' % (region.name) - response = self.connection.request(request, method='GET').object - - if 'items' in response: - # The aggregated result returns dictionaries for each region - if region is None: - for v in response['items'].values(): - region_targetpools = [self._to_targetpool(t) for t in - v.get('targetPools', [])] - list_targetpools.extend(region_targetpools) - else: - list_targetpools = [self._to_targetpool(t) for t in - response['items']] - return list_targetpools - - def list_volumes(self, ex_zone=None): - """ - Return a list of volumes for a zone or all. - - Will return list from provided zone, or from the default zone unless - given the value of 'all'. - - :keyword ex_zone: The zone to return volumes from. - :type ex_zone: ``str`` or :class:`GCEZone` or - :class:`NodeLocation` or ``None`` - - :return: A list of volume objects. - :rtype: ``list`` of :class:`StorageVolume` - """ - list_volumes = [] - zone = self._set_zone(ex_zone) - if zone is None: - request = '/aggregated/disks' - else: - request = '/zones/%s/disks' % (zone.name) - - response = self.connection.request(request, method='GET').object - if 'items' in response: - # The aggregated response returns a dict for each zone - if zone is None: - for v in response['items'].values(): - zone_volumes = [self._to_storage_volume(d) for d in - v.get('disks', [])] - list_volumes.extend(zone_volumes) - else: - list_volumes = [self._to_storage_volume(d) for d in - response['items']] - return list_volumes - - def ex_list_zones(self): - """ - Return the list of zones. - - :return: A list of zone objects. - :rtype: ``list`` of :class:`GCEZone` - """ - list_zones = [] - request = '/zones' - response = self.connection.request(request, method='GET').object - list_zones = [self._to_zone(z) for z in response['items']] - return list_zones - - def ex_create_address(self, name, region=None): - """ - Create a static address in a region. - - :param name: Name of static address - :type name: ``str`` - - :keyword region: Name of region for the address (e.g. 'us-central1') - :type region: ``str`` or :class:`GCERegion` - - :return: Static Address object - :rtype: :class:`GCEAddress` - """ - region = region or self.region - if not hasattr(region, 'name'): - region = self.ex_get_region(region) - elif region is None: - raise ValueError('REGION_NOT_SPECIFIED', - 'Region must be provided for an address') - address_data = {'name': name} - request = '/regions/%s/addresses' % (region.name) - self.connection.async_request(request, method='POST', - data=address_data) - return self.ex_get_address(name, region=region) - - def ex_create_healthcheck(self, name, host=None, path=None, port=None, - interval=None, timeout=None, - unhealthy_threshold=None, - healthy_threshold=None): - """ - Create an Http Health Check. - - :param name: Name of health check - :type name: ``str`` - - :keyword host: Hostname of health check request. Defaults to empty - and public IP is used instead. - :type host: ``str`` - - :keyword path: The request path for the check. Defaults to /. - :type path: ``str`` - - :keyword port: The TCP port number for the check. Defaults to 80. - :type port: ``int`` - - :keyword interval: How often (in seconds) to check. Defaults to 5. - :type interval: ``int`` - - :keyword timeout: How long to wait before failing. Defaults to 5. - :type timeout: ``int`` - - :keyword unhealthy_threshold: How many failures before marking - unhealthy. Defaults to 2. - :type unhealthy_threshold: ``int`` - - :keyword healthy_threshold: How many successes before marking as - healthy. Defaults to 2. - :type healthy_threshold: ``int`` - - :return: Health Check object - :rtype: :class:`GCEHealthCheck` - """ - hc_data = {} - hc_data['name'] = name - if host: - hc_data['host'] = host - # As of right now, the 'default' values aren't getting set when called - # through the API, so set them explicitly - hc_data['requestPath'] = path or '/' - hc_data['port'] = port or 80 - hc_data['checkIntervalSec'] = interval or 5 - hc_data['timeoutSec'] = timeout or 5 - hc_data['unhealthyThreshold'] = unhealthy_threshold or 2 - hc_data['healthyThreshold'] = healthy_threshold or 2 - - request = '/global/httpHealthChecks' - - self.connection.async_request(request, method='POST', data=hc_data) - return self.ex_get_healthcheck(name) - - def ex_create_firewall(self, name, allowed, network='default', - source_ranges=None, source_tags=None, - target_tags=None): - """ - Create a firewall on a network. - - Firewall rules should be supplied in the "allowed" field. This is a - list of dictionaries formated like so ("ports" is optional):: - - [{"IPProtocol": "<protocol string or number>", - "ports": "<port_numbers or ranges>"}] - - For example, to allow tcp on port 8080 and udp on all ports, 'allowed' - would be:: - - [{"IPProtocol": "tcp", - "ports": ["8080"]}, - {"IPProtocol": "udp"}] - - See `Firewall Reference <https://developers.google.com/compute/docs/ - reference/latest/firewalls/insert>`_ for more information. - - :param name: Name of the firewall to be created - :type name: ``str`` - - :param allowed: List of dictionaries with rules - :type allowed: ``list`` of ``dict`` - - :keyword network: The network that the firewall applies to. - :type network: ``str`` or :class:`GCENetwork` - - :keyword source_ranges: A list of IP ranges in CIDR format that the - firewall should apply to. Defaults to - ['0.0.0.0/0'] - :type source_ranges: ``list`` of ``str`` - - :keyword source_tags: A list of source instance tags the rules apply - to. - :type source_tags: ``list`` of ``str`` - - :keyword target_tags: A list of target instance tags the rules apply - to. - :type target_tags: ``list`` of ``str`` - - :return: Firewall object - :rtype: :class:`GCEFirewall` - """ - firewall_data = {} - if not hasattr(network, 'name'): - nw = self.ex_get_network(network) - else: - nw = network - - firewall_data['name'] = name - firewall_data['allowed'] = allowed - firewall_data['network'] = nw.extra['selfLink'] - firewall_data['sourceRanges'] = source_ranges or ['0.0.0.0/0'] - if source_tags is not None: - firewall_data['sourceTags'] = source_tags - if target_tags is not None: - firewall_data['targetTags'] = target_tags - - request = '/global/firewalls' - - self.connection.async_request(request, method='POST', - data=firewall_data) - return self.ex_get_firewall(name) - - def ex_create_forwarding_rule(self, name, targetpool, region=None, - protocol='tcp', port_range=None, - address=None): - """ - Create a forwarding rule. - - :param name: Name of forwarding rule to be created - :type name: ``str`` - - :param targetpool: Target pool to apply the rule to - :param targetpool: ``str`` or :class:`GCETargetPool` - - :keyword region: Region to create the forwarding rule in. Defaults to - self.region - :type region: ``str`` or :class:`GCERegion` - - :keyword protocol: Should be 'tcp' or 'udp' - :type protocol: ``str`` - - :keyword port_range: Optional single port number or range separated - by a dash. Examples: '80', '5000-5999'. - :type port_range: ``str`` - - :keyword address: Optional static address for forwarding rule. Must be - in same region. - :type address: ``str`` or :class:`GCEAddress` - - :return: Forwarding Rule object - :rtype: :class:`GCEForwardingRule` - """ - forwarding_rule_data = {} - region = region or self.region - if not hasattr(region, 'name'): - region = self.ex_get_region(region) - if not hasattr(targetpool, 'name'): - targetpool = self.ex_get_targetpool(targetpool, region) - - forwarding_rule_data['name'] = name - forwarding_rule_data['region'] = region.extra['selfLink'] - forwarding_rule_data['target'] = targetpool.extra['selfLink'] - forwarding_rule_data['protocol'] = protocol.upper() - if address: - if not hasattr(address, 'name'): - address = self.ex_get_address(address, region) - forwarding_rule_data['IPAddress'] = address.extra['selfLink'] - if port_range: - forwarding_rule_data['portRange'] = port_range - - request = '/regions/%s/forwardingRules' % (region.name) - - self.connection.async_request(request, method='POST', - data=forwarding_rule_data) - - return self.ex_get_forwarding_rule(name) - - def ex_create_network(self, name, cidr): - """ - Create a network. - - :param name: Name of network to be created - :type name: ``str`` - - :param cidr: Address range of network in CIDR format. - :type cidr: ``str`` - - :return: Network object - :rtype: :class:`GCENetwork` - """ - network_data = {} - network_data['name'] = name - network_data['IPv4Range'] = cidr - - request = '/global/networks' - - self.connection.async_request(request, method='POST', - data=network_data) - - return self.ex_get_network(name) - - def create_node(self, name, size, image, location=None, - ex_network='default', ex_tags=None, ex_metadata=None, - ex_boot_disk=None, use_existing_disk=True, - external_ip='ephemeral'): - """ - Create a new node and return a node object for the node. - - :param name: The name of the node to create. - :type name: ``str`` - - :param size: The machine type to use. - :type size: ``str`` or :class:`GCENodeSize` - - :param image: The image to use to create the node (or, if attaching - a persistent disk, the image used to create the disk) - :type image: ``str`` or :class:`GCENodeImage` - - :keyword location: The location (zone) to create the node in. - :type location: ``str`` or :class:`NodeLocation` or - :class:`GCEZone` or ``None`` - - :keyword ex_network: The network to associate with the node. - :type ex_network: ``str`` or :class:`GCENetwork` - - :keyword ex_tags: A list of tags to associate with the node. - :type ex_tags: ``list`` of ``str`` or ``None`` - - :keyword ex_metadata: Metadata dictionary for instance. - :type ex_metadata: ``dict`` or ``None`` - - :keyword ex_boot_disk: The boot disk to attach to the instance. - :type ex_boot_disk: :class:`StorageVolume` or ``str`` - - :keyword use_existing_disk: If True and if an existing disk with the - same name/location is found, use that - disk instead of creating a new one. - :type use_existing_disk: ``bool`` - - :keyword external_ip: The external IP address to use. If 'ephemeral' - (default), a new non-static address will be - used. If 'None', then no external address will - be used. To use an existing static IP address, - a GCEAddress object should be passed in. - :type external_ip: :class:`GCEAddress` or ``str`` or None - - :return: A Node object for the new node. - :rtype: :class:`Node` - """ - location = location or self.zone - if not hasattr(location, 'name'): - location = self.ex_get_zone(location) - if not hasattr(size, 'name'): - size = self.ex_get_size(size, location) - if not hasattr(ex_network, 'name'): - ex_network = self.ex_get_network(ex_network) - if not hasattr(image, 'name'): - image = self.ex_get_image(image) - - if not ex_boot_disk: - ex_boot_disk = self.create_volume(None, name, location=location, - image=image, - use_existing=use_existing_disk) - - if ex_metadata is not None: - ex_metadata = {"items": [{"key": k, "value": v} - for k, v in ex_metadata.items()]} - - request, node_data = self._create_node_req(name, size, image, - location, ex_network, - ex_tags, ex_metadata, - ex_boot_disk, external_ip) - self.connection.async_request(request, method='POST', data=node_data) - - return self.ex_get_node(name, location.name) - - def ex_create_multiple_nodes(self, base_name, size, image, number, - location=None, ex_network='default', - ex_tags=None, ex_metadata=None, - ignore_errors=True, use_existing_disk=True, - poll_interval=2, external_ip='ephemeral', - timeout=DEFAULT_TASK_COMPLETION_TIMEOUT): - """ - Create multiple nodes and return a list of Node objects. - - Nodes will be named with the base name and a number. For example, if - the base name is 'libcloud' and you create 3 nodes, they will be - named:: - - libcloud-000 - libcloud-001 - libcloud-002 - - :param base_name: The base name of the nodes to create. - :type base_name: ``str`` - - :param size: The machine type to use. - :type size: ``str`` or :class:`GCENodeSize` - - :param image: The image to use to create the nodes. - :type image: ``str`` or :class:`GCENodeImage` - - :param number: The number of nodes to create. - :type number: ``int`` - - :keyword location: The location (zone) to create the nodes in. - :type location: ``str`` or :class:`NodeLocation` or - :class:`GCEZone` or ``None`` - - :keyword ex_network: The network to associate with the nodes. - :type ex_network: ``str`` or :class:`GCENetwork` - - :keyword ex_tags: A list of tags to assiciate with the nodes. - :type ex_tags: ``list`` of ``str`` or ``None`` - - :keyword ex_metadata: Metadata dictionary for instances. - :type ex_metadata: ``dict`` or ``None`` - - :keyword ignore_errors: If True, don't raise Exceptions if one or - more nodes fails. - :type ignore_errors: ``bool`` - - :keyword use_existing_disk: If True and if an existing disk with the - same name/location is found, use that - disk instead of creating a new one. - :type use_existing_disk: ``bool`` - - :keyword poll_interval: Number of seconds between status checks. - :type poll_interval: ``int`` - - :keyword external_ip: The external IP address to use. If 'ephemeral' - (default), a new non-static address will be - used. If 'None', then no external address will - be used. (Static addresses are not supported for - multiple node creation.) - :type external_ip: ``str`` or None - - :keyword timeout: The number of seconds to wait for all nodes to be - created before timing out. - :type timeout: ``int`` - - :return: A list of Node objects for the new nodes. - :rtype: ``list`` of :class:`Node` - """ - location = location or self.zone - if not hasattr(location, 'name'): - location = self.ex_get_zone(location) - if not hasattr(size, 'name'): - size = self.ex_get_size(size, location) - if not hasattr(ex_network, 'name'): - ex_network = self.ex_get_network(ex_network) - if not hasattr(image, 'name'): - image = self.ex_get_image(image) - - node_attrs = {'size': size, - 'image': image, - 'location': location, - 'network': ex_network, - 'tags': ex_tags, - 'metadata': ex_metadata, - 'ignore_errors': ignore_errors, - 'use_existing_disk': use_existing_disk, - 'external_ip': external_ip} - - # List for holding the status information for disk/node creation. - status_list = [] - - for i in range(number): - name = '%s-%03d' % (base_name, i) - - status = {'name': name, - 'node_response': None, - 'node': None, - 'disk_response': None, - 'disk': None} - - status_list.append(status) - - # Create disks for nodes - for status in status_list: - self._multi_create_disk(status, node_attrs) - - start_time = time.time() - complete = False - while not complete: - if (time.time() - start_time >= timeout): - raise Exception("Timeout (%s sec) while waiting for multiple " - "instances") - complete = True - time.sleep(poll_interval) - for status in status_list: - # If disk does not yet exist, check on its status - if not status['disk']: - self._multi_check_disk(status, node_attrs) - - # If disk exists, but node does not, create the node or check - # on its status if already in progress. - if status['disk'] and not status['node']: - if not status['node_response']: - self._multi_create_node(status, node_attrs) - else: - self._multi_check_node(status, node_attrs) - # If any of the nodes have not been created (or failed) we are - # not done yet. - if not status['node']: - complete = False - - # Return list of nodes - node_list = [] - for status in status_list: - node_list.append(status['node']) - return node_list - - def ex_create_targetpool(self, name, region=None, healthchecks=None, - nodes=None): - """ - Create a target pool. - - :param name: Name of target pool - :type name: ``str`` - - :keyword region: Region to create the target pool in. Defaults to - self.region - :type region: ``str`` or :class:`GCERegion` or ``None`` - - :keyword healthchecks: Optional list of health checks to attach - :type healthchecks: ``list`` of ``str`` or :class:`GCEHealthCheck` - - :keyword nodes: Optional list of nodes to attach to the pool - :type nodes: ``list`` of ``str`` or :class:`Node` - - :return: Target Pool object - :rtype: :class:`GCETargetPool` - """ - region = region or self.region - targetpool_data = {} - targetpool_data['name'] = name - if not hasattr(region, 'name'): - region = self.ex_get_region(region) - targetpool_data['region'] = region.extra['selfLink'] - - if healthchecks: - if not hasattr(healthchecks[0], 'name'): - hc_list = [self.ex_get_healthcheck(h).extra['selfLink'] for h - in healthchecks] - else: - hc_list = [h.extra['selfLink'] for h in healthchecks] - targetpool_data['healthChecks'] = hc_list - if nodes: - if not hasattr(nodes[0], 'name'): - node_list = [self.ex_get_node(n, 'all').extra['selfLink'] for n - in nodes] - else: - node_list = [n.extra['selfLink'] for n in nodes] - targetpool_data['instances'] = node_list - - request = '/regions/%s/targetPools' % (region.name) - - self.connection.async_request(request, method='POST', - data=targetpool_data) - - return self.ex_get_targetpool(name, region) - - def create_volume(self, size, name, location=None, snapshot=None, - image=None, use_existing=True): - """ - Create a volume (disk). - - :param size: Size of volume to create (in GB). Can be None if image - or snapshot is supplied. - :type size: ``int`` or ``str`` or ``None`` - - :param name: Name of volume to create - :type name: ``str`` - - :keyword location: Location (zone) to create the volume in - :type location: ``str`` or :class:`GCEZone` or - :class:`NodeLocation` or ``None`` - - :keyword snapshot: Snapshot to create image from - :type snapshot: :class:`GCESnapshot` or ``str`` or ``None`` - - :keyword image: Image to create disk from. - :type image: :class:`GCENodeImage` or ``str`` or ``None`` - - :keyword use_existing: If True and a disk with the given name already - exists, return an object for that disk instead - of attempting to create a new disk. - :type use_existing: ``bool`` - - :return: Storage Volume object - :rtype: :class:`StorageVolume` - """ - request, volume_data, params = self._create_vol_req( - size, name, location, snapshot, image) - try: - self.connection.async_request(request, method='POST', - data=volume_data, params=params) - except ResourceExistsError: - e = sys.exc_info()[1] - if not use_existing: - raise e - - return self.ex_get_volume(name, location) - - def create_volume_snapshot(self, volume, name): - """ - Create a snapshot of the provided Volume. - - :param volume: A StorageVolume object - :type volume: :class:`StorageVolume` - - :return: A GCE Snapshot object - :rtype: :class:`GCESnapshot` - """ - snapshot_data = {} - snapshot_data['name'] = name - request = '/zones/%s/disks/%s/createSnapshot' % ( - volume.extra['zone'].name, volume.name) - self.connection.async_request(request, method='POST', - data=snapshot_data) - - return self.ex_get_snapshot(name) - - def list_volume_snapshots(self, volume): - """ - List snapshots created from the provided volume. - - For GCE, snapshots are global, but while the volume they were - created from still exists, the source disk for the snapshot is - tracked. - - :param volume: A StorageVolume object - :type volume: :class:`StorageVolume` - - :return: A list of Snapshot objects - :rtype: ``list`` of :class:`GCESnapshot` - """ - volume_snapshots = [] - volume_link = volume.extra['selfLink'] - all_snapshots = self.ex_list_snapshots() - for snapshot in all_snapshots: - if snapshot.extra['sourceDisk'] == volume_link: - volume_snapshots.append(snapshot) - return volume_snapshots - - def ex_update_healthcheck(self, healthcheck): - """ - Update a health check with new values. - - To update, change the attributes of the health check object and pass - the updated object to the method. - - :param healthcheck: A healthcheck object with updated values. - :type healthcheck: :class:`GCEHealthCheck` - - :return: An object representing the new state of the health check. - :rtype: :class:`GCEHealthCheck` - """ - hc_data = {} - hc_data['name'] = healthcheck.name - hc_data['requestPath'] = healthcheck.path - hc_data['port'] = healthcheck.port - hc_data['checkIntervalSec'] = healthcheck.interval - hc_data['timeoutSec'] = healthcheck.timeout - hc_data['unhealthyThreshold'] = healthcheck.unhealthy_threshold - hc_data['healthyThreshold'] = healthcheck.healthy_threshold - if healthcheck.extra['host']: - hc_data['host'] = healthcheck.extra['host'] - if healthcheck.extra['description']: - hc_data['description'] = healthcheck.extra['description'] - - request = '/global/httpHealthChecks/%s' % (healthcheck.name) - - self.connection.async_request(request, method='PUT', - data=hc_data) - - return self.ex_get_healthcheck(healthcheck.name) - - def ex_update_firewall(self, firewall): - """ - Update a firewall with new values. - - To update, change the attributes of the firewall object and pass the - updated object to the method. - - :param firewall: A firewall object with updated values. - :type firewall: :class:`GCEFirewall` - - :return: An object representing the new state of the firewall. - :rtype: :class:`GCEFirewall` - """ - firewall_data = {} - firewall_data['name'] = firewall.name - firewall_data['allowed'] = firewall.allowed - firewall_data['network'] = firewall.network.extra['selfLink'] - if firewall.source_ranges: - firewall_data['sourceRanges'] = firewall.source_ranges - if firewall.source_tags: - firewall_data['sourceTags'] = firewall.source_tags - if firewall.target_tags: - firewall_data['targetTags'] = firewall.target_tags - if firewall.extra['description']: - firewall_data['description'] = firewall.extra['description'] - - request = '/global/firewalls/%s' % (firewall.name) - - self.connection.async_request(request, method='PUT', - data=firewall_data) - - return self.ex_get_firewall(firewall.name) - - def ex_targetpool_add_node(self, targetpool, node): - """ - Add a node to a target pool. - - :param targetpool: The targetpool to add node to - :type targetpool: ``str`` or :class:`GCETargetPool` - - :param node: The node to add - :type node: ``str`` or :class:`Node` - - :returns: True if successful - :rtype: ``bool`` - """ - if not hasattr(targetpool, 'name'): - targetpool = self.ex_get_targetpool(targetpool) - if not hasattr(node, 'name'): - node = self.ex_get_node(node, 'all') - - targetpool_data = {'instances': [{'instance': node.extra['selfLink']}]} - - request = '/regions/%s/targetPools/%s/addInstance' % ( - targetpool.region.name, targetpool.name) - self.connection.async_request(request, method='POST', - data=targetpool_data) - targetpool.nodes.append(node) - return True - - def ex_targetpool_add_healthcheck(self, targetpool, healthcheck): - """ - Add a health check to a target pool. - - :param targetpool: The targetpool to add health check to - :type targetpool: ``str`` or :class:`GCETargetPool` - - :param healthcheck: The healthcheck to add - :type healthcheck: ``str`` or :class:`GCEHealthCheck` - - :returns: True if successful - :rtype: ``bool`` - """ - if not hasattr(targetpool, 'name'): - targetpool = self.ex_get_targetpool(targetpool) - if not hasattr(healthcheck, 'name'): - healthcheck = self.ex_get_healthcheck(healthcheck) - - targetpool_data = {'healthCheck': healthcheck.extra['selfLink']} - - request = '/regions/%s/targetPools/%s/addHealthCheck' % ( - targetpool.region.name, targetpool.name) - self.connection.async_request(request, method='POST', - data=targetpool_data) - targetpool.healthchecks.append(healthcheck) - return True - - def ex_targetpool_remove_node(self, targetpool, node): - """ - Remove a node from a target pool. - - :param targetpool: The targetpool to remove node from - :type targetpool: ``str`` or :class:`GCETargetPool` - - :param node: The node to remove - :type node: ``str`` or :class:`Node` - - :returns: True if successful - :rtype: ``bool`` - """ - if not hasattr(targetpool, 'name'): - targetpool = self.ex_get_targetpool(targetpool) - if not hasattr(node, 'name'): - node = self.ex_get_node(node, 'all') - - targetpool_data = {'instances': [{'instance': node.extra['selfLink']}]} - - request = '/regions/%s/targetPools/%s/removeInstance' % ( - targetpool.region.name, targetpool.name) - self.connection.async_request(request, method='POST', - data=targetpool_data) - # Remove node object from node list - index = None - for i, nd in enumerate(targetpool.nodes): - if nd.name == node.name: - index = i - break - if index is not None: - targetpool.nodes.pop(index) - return True - - def ex_targetpool_remove_healthcheck(self, targetpool, healthcheck): - """ - Remove a health check from a target pool. - - :param targetpool: The targetpool to remove health check from - :type targetpool: ``str`` or :class:`GCETargetPool` - - :param healthcheck: The healthcheck to remove - :type healthcheck: ``str`` or :class:`GCEHealthCheck` - - :returns: True if successful - :rtype: ``bool`` - """ - if not hasattr(targetpool, 'name'): - targetpool = self.ex_get_targetpool(targetpool) - if not hasattr(healthcheck, 'name'): - healthcheck = self.ex_get_healthcheck(healthcheck) - - targetpool_data = {'healthCheck': healthcheck.extra['selfLink']} - - request = '/regions/%s/targetPools/%s/removeHealthCheck' % ( - targetpool.region.name, targetpool.name) - self.connection.async_request(request, method='POST', - data=targetpool_data) - # Remove healthcheck object from healthchecks list - index = None - for i, hc in enumerate(targetpool.healthchecks): - if hc.name == healthcheck.name: - index = i - if index is not None: - targetpool.healthchecks.pop(index) - return True - - def reboot_node(self, node): - """ - Reboot a node. - - :param node: Node to be rebooted - :type node: :class:`Node` - - :return: True if successful, False if not - :rtype: ``bool`` - """ - request = '/zones/%s/instances/%s/reset' % (node.extra['zone'].name, - node.name) - self.connection.async_request(request, method='POST', - data='ignored') - return True - - def ex_set_node_tags(self, node, tags): - """ - Set the tags on a Node instance. - - Note that this updates the node object directly. - - :param node: Node object - :type node: :class:`Node` - - :param tags: List of tags to apply to the object - :type tags: ``list`` of ``str`` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/zones/%s/instances/%s/setTags' % (node.extra['zone'].name, - node.name) - - tags_data = {} - tags_data['items'] = tags - tags_data['fingerprint'] = node.extra['tags_fingerprint'] - - self.connection.async_request(request, method='POST', - data=tags_data) - new_node = self.ex_get_node(node.name, node.extra['zone']) - node.extra['tags'] = new_node.extra['tags'] - node.extra['tags_fingerprint'] = new_node.extra['tags_fingerprint'] - return True - - def ex_set_node_scheduling(self, node, on_host_maintenance=None, - automatic_restart=None): - """Set the maintenance behavior for the node. - - See `Scheduling <https://developers.google.com/compute/ - docs/instances#onhostmaintenance>`_ documentation for more info. - - :param node: Node object - :type node: :class:`Node` - - :keyword on_host_maintenance: Defines whether node should be - terminated or migrated when host machine - goes down. Acceptable values are: - 'MIGRATE' or 'TERMINATE' (If not - supplied, value will be reset to GCE - default value for the instance type.) - :type on_host_maintenance: ``str`` - - :keyword automatic_restart: Defines whether the instance should be - automatically restarted when it is - terminated by Compute Engine. (If not - supplied, value will be set to the GCE - default value for the instance type.) - :type automatic_restart: ``bool`` - - :return: True if successful. - :rtype: ``bool`` - """ - if not hasattr(node, 'name'): - node = self.ex_get_node(node, 'all') - if on_host_maintenance is not None: - on_host_maintenance = on_host_maintenance.upper() - ohm_values = ['MIGRATE', 'TERMINATE'] - if on_host_maintenance not in ohm_values: - raise ValueError('on_host_maintenance must be one of %s' % - ','.join(ohm_values)) - - request = '/zones/%s/instances/%s/setScheduling' % ( - node.extra['zone'].name, node.name) - - scheduling_data = {} - if on_host_maintenance is not None: - scheduling_data['onHostMaintenance'] = on_host_maintenance - if automatic_restart is not None: - scheduling_data['automaticRestart'] = automatic_restart - - self.connection.async_request(request, method='POST', - data=scheduling_data) - - new_node = self.ex_get_node(node.name, node.extra['zone']) - node.extra['scheduling'] = new_node.extra['scheduling'] - - ohm = node.extra['scheduling'].get('onHostMaintenance') - ar = node.extra['scheduling'].get('automaticRestart') - - success = True - if on_host_maintenance not in [None, ohm]: - success = False - if automatic_restart not in [None, ar]: - success = False - - return success - - def deploy_node(self, name, size, image, script, location=None, - ex_network='default', ex_tags=None): - """ - Create a new node and run a script on start-up. - - :param name: The name of the node to create. - :type name: ``str`` - - :param size: The machine type to use. - :type size: ``str`` or :class:`GCENodeSize` - - :param image: The image to use to create the node. - :type image: ``str`` or :class:`GCENodeImage` - - :param script: File path to start-up script - :type script: ``str`` - - :keyword location: The location (zone) to create the node in. - :type location: ``str`` or :class:`NodeLocation` or - :class:`GCEZone` or ``None`` - - :keyword ex_network: The network to associate with the node. - :type ex_network: ``str`` or :class:`GCENetwork` - - :keyword ex_tags: A list of tags to associate with the node. - :type ex_tags: ``list`` of ``str`` or ``None`` - - :return: A Node object for the new node. - :rtype: :class:`Node` - """ - with open(script, 'r') as f: - script_data = f.read() - metadata = {'items': [{'key': 'startup-script', - 'value': script_data}]} - - return self.create_node(name, size, image, location=location, - ex_network=ex_network, ex_tags=ex_tags, - ex_metadata=metadata) - - def attach_volume(self, node, volume, device=None, ex_mode=None, - ex_boot=False): - """ - Attach a volume to a node. - - If volume is None, a scratch disk will be created and attached. - - :param node: The node to attach the volume to - :type node: :class:`Node` - - :param volume: The volume to attach. If none, a scratch disk will be - attached. - :type volume: :class:`StorageVolume` or ``None`` - - :keyword device: The device name to attach the volume as. Defaults to - volume name. - :type device: ``str`` - - :keyword ex_mode: Either 'READ_WRITE' or 'READ_ONLY' - :type ex_mode: ``str`` - - :keyword ex_boot: If true, disk will be attached as a boot disk - :type ex_boot: ``bool`` - - :return: True if successful - :rtype: ``bool`` - """ - volume_data = {} - if volume is None: - volume_data['type'] = 'SCRATCH' - else: - volume_data['type'] = 'PERSISTENT' - volume_data['source'] = volume.extra['selfLink'] - volume_data['kind'] = 'compute#attachedDisk' - volume_data['mode'] = ex_mode or 'READ_WRITE' - - if device: - volume_data['deviceName'] = device - else: - volume_data['deviceName'] = volume.name - - volume_data['boot'] = ex_boot - - request = '/zones/%s/instances/%s/attachDisk' % ( - node.extra['zone'].name, node.name) - self.connection.async_request(request, method='POST', - data=volume_data) - return True - - def detach_volume(self, volume, ex_node=None): - """ - Detach a volume from a node. - - :param volume: Volume object to detach - :type volume: :class:`StorageVolume` - - :keyword ex_node: Node object to detach volume from (required) - :type ex_node: :class:`Node` - - :return: True if successful - :rtype: ``bool`` - """ - if not ex_node: - return False - request = '/zones/%s/instances/%s/detachDisk?deviceName=%s' % ( - ex_node.extra['zone'].name, ex_node.name, volume.name) - - self.connection.async_request(request, method='POST', - data='ignored') - return True - - def ex_set_volume_auto_delete(self, volume, node, auto_delete=True): - """ - Sets the auto-delete flag for a volume attached to a node. - - :param volume: Volume object to auto-delete - :type volume: :class:`StorageVolume` - - :param ex_node: Node object to auto-delete volume from - :type ex_node: :class:`Node` - - :keyword auto_delete: Flag to set for the auto-delete value - :type auto_delete: ``bool`` (default True) - - :return: True if successfull - :rtype: ``bool`` - """ - request = '/zones/%s/instances/%s/setDiskAutoDelete' % ( - node.extra['zone'].name, node.name - ) - delete_params = { - 'deviceName': volume, - 'autoDelete': auto_delete, - } - self.connection.async_request(request, method='POST', - params=delete_params) - return True - - def ex_destroy_address(self, address): - """ - Destroy a static address. - - :param address: Address object to destroy - :type address: :class:`GCEAddress` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/regions/%s/addresses/%s' % (address.region.name, - address.name) - - self.connection.async_request(request, method='DELETE') - return True - - def ex_delete_image(self, image): - """ - Delete a specific image resource. - - :param image: Image object to delete - :type image: ``str`` or :class:`GCENodeImage` - - :return: True if successfull - :rtype: ``bool`` - """ - if not hasattr(image, 'name'): - image = self.ex_get_image(image) - - request = '/global/images/%s' % (image.name) - self.connection.async_request(request, method='DELETE') - return True - - def ex_deprecate_image(self, image, replacement, state=None): - """ - Deprecate a specific image resource. - - :param image: Image object to deprecate - :type image: ``str`` or :class: `GCENodeImage` - - :param replacement: Image object to use as a replacement - :type replacement: ``str`` or :class: `GCENodeImage` - - :param state: State of the image - :type state: ``str`` - - :return: True if successfull - :rtype: ``bool`` - """ - if not hasattr(image, 'name'): - image = self.ex_get_image(image) - - if not hasattr(replacement, 'name'): - replacement = self.ex_get_image(replacement) - - if state is None: - state = 'DEPRECATED' - - possible_states = ['DELETED', 'DEPRECATED', 'OBSOLETE'] - - if state not in possible_states: - raise ValueError('state must be one of %s' - % ','.join(possible_states)) - - image_data = { - 'state': state, - 'replacement': replacement.extra['selfLink'], - } - - request = '/global/images/%s/deprecate' % (image.name) - - self.connection.request( - request, method='POST', data=image_data).object - - return True - - def ex_destroy_healthcheck(self, healthcheck): - """ - Destroy a healthcheck. - - :param healthcheck: Health check object to destroy - :type healthcheck: :class:`GCEHealthCheck` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/global/httpHealthChecks/%s' % (healthcheck.name) - self.connection.async_request(request, method='DELETE') - return True - - def ex_destroy_firewall(self, firewall): - """ - Destroy a firewall. - - :param firewall: Firewall object to destroy - :type firewall: :class:`GCEFirewall` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/global/firewalls/%s' % (firewall.name) - self.connection.async_request(request, method='DELETE') - return True - - def ex_destroy_forwarding_rule(self, forwarding_rule): - """ - Destroy a forwarding rule. - - :param forwarding_rule: Forwarding Rule object to destroy - :type forwarding_rule: :class:`GCEForwardingRule` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/regions/%s/forwardingRules/%s' % ( - forwarding_rule.region.name, forwarding_rule.name) - self.connection.async_request(request, method='DELETE') - return True - - def ex_destroy_network(self, network): - """ - Destroy a network. - - :param network: Network object to destroy - :type network: :class:`GCENetwork` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/global/networks/%s' % (network.name) - self.connection.async_request(request, method='DELETE') - return True - - def destroy_node(self, node, destroy_boot_disk=False): - """ - Destroy a node. - - :param node: Node object to destroy - :type node: :class:`Node` - - :keyword destroy_boot_disk: If true, also destroy the node's - boot disk. (Note that this keyword is not - accessible from the node's .destroy() - method.) - :type destroy_boot_disk: ``bool`` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/zones/%s/instances/%s' % (node.extra['zone'].name, - node.name) - self.connection.async_request(request, method='DELETE') - if destroy_boot_disk and node.extra['boot_disk']: - node.extra['boot_disk'].destroy() - return True - - def ex_destroy_multiple_nodes(self, node_list, ignore_errors=True, - destroy_boot_disk=False, poll_interval=2, - timeout=DEFAULT_TASK_COMPLETION_TIMEOUT): - """ - Destroy multiple nodes at once. - - :param node_list: List of nodes to destroy - :type node_list: ``list`` of :class:`Node` - - :keyword ignore_errors: If true, don't raise an exception if one or - more nodes fails to be destroyed. - :type ignore_errors: ``bool`` - - :keyword destroy_boot_disk: If true, also destroy the nodes' boot - disks. - :type destroy_boot_disk: ``bool`` - - :keyword poll_interval: Number of seconds between status checks. - :type poll_interval: ``int`` - - :keyword timeout: Number of seconds to wait for all nodes to be - destroyed. - :type timeout: ``int`` - - :return: A list of boolean values. One for each node. True means - that the node was successfully destroyed. - :rtype: ``list`` of ``bool`` - """ - status_list = [] - complete = False - start_time = time.time() - for node in node_list: - request = '/zones/%s/instances/%s' % (node.extra['zone'].name, - node.name) - try: - response = self.connection.request(request, - method='DELETE').object - except GoogleBaseError: - self._catch_error(ignore_errors=ignore_errors) - response = None - - status = {'node': node, - 'node_success': False, - 'node_response': response, - 'disk_success': not destroy_boot_disk, - 'disk_response': None} - - status_list.append(status) - - while not complete: - if (time.time() - start_time >= timeout): - raise Exception("Timeout (%s sec) while waiting to delete " - "multiple instances") - complete = True - for status in status_list: - # If one of the operations is running, check the status - operation = status['node_response'] or status['disk_response'] - delete_disk = False - if operation: - no_errors = True - try: - response = self.connection.request( - operation['selfLink']).object - except GoogleBaseError: - self._catch_error(ignore_errors=ignore_errors) - no_errors = False - response = {'status': 'DONE'} - if response['status'] == 'DONE': - # If a node was deleted, update status and indicate - # that the disk is ready to be deleted. - if status['node_response']: - status['node_response'] = None - status['node_success'] = no_errors - delete_disk = True - else: - status['disk_response'] = None - status['disk_success'] = no_errors - # If we are destroying disks, and the node has been deleted, - # destroy the disk. - if delete_disk and destroy_boot_disk: - boot_disk = status['node'].extra['boot_disk'] - if boot_disk: - request = '/zones/%s/disks/%s' % ( - boot_disk.extra['zone'].name, boot_disk.name) - try: - response = self.connection.request( - request, method='DELETE').object - except GoogleBaseError: - self._catch_error(ignore_errors=ignore_errors) - no_errors = False - response = None - status['disk_response'] = response - else: # If there is no boot disk, ignore - status['disk_success'] = True - operation = status['node_response'] or status['disk_response'] - if operation: - time.sleep(poll_interval) - complete = False - - success = [] - for status in status_list: - s = status['node_success'] and status['disk_success'] - success.append(s) - return success - - def ex_destroy_targetpool(self, targetpool): - """ - Destroy a target pool. - - :param targetpool: TargetPool object to destroy - :type targetpool: :class:`GCETargetPool` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/regions/%s/targetPools/%s' % (targetpool.region.name, - targetpool.name) - - self.connection.async_request(request, method='DELETE') - return True - - def destroy_volume(self, volume): - """ - Destroy a volume. - - :param volume: Volume object to destroy - :type volume: :class:`StorageVolume` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/zones/%s/disks/%s' % (volume.extra['zone'].name, - volume.name) - self.connection.async_request(request, method='DELETE') - return True - - def destroy_volume_snapshot(self, snapshot): - """ - Destroy a snapshot. - - :param snapshot: Snapshot object to destroy - :type snapshot: :class:`GCESnapshot` - - :return: True if successful - :rtype: ``bool`` - """ - request = '/global/snapshots/%s' % (snapshot.name) - self.connection.async_request(request, method='DELETE') - return True - - def ex_get_address(self, name, region=None): - """ - Return an Address object based on an address name and optional region. - - :param name: The name of the address - :type name: ``str`` - - :keyword region: The region to search for the address in (set to - 'all' to search all regions) - :type region: ``str`` :class:`GCERegion` or ``None`` - - :return: An Address object for the address - :rtype: :class:`GCEAddress` - """ - region = self._set_region(region) or self._find_zone_or_region( - name, 'addresses', region=True, res_name='Address') - request = '/regions/%s/addresses/%s' % (region.name, name) - response = self.connection.request(request, method='GET').object - return self._to_address(response) - - def ex_get_healthcheck(self, name): - """ - Return a HealthCheck object based on the healthcheck name. - - :param name: The name of the healthcheck - :type name: ``str`` - - :return: A GCEHealthCheck object - :rtype: :class:`GCEHealthCheck` - """ - request = '/global/httpHealthChecks/%s' % (name) - response = self.connection.request(request, method='GET').object - return self._to_healthcheck(response) - - def ex_get_firewall(self, name): - """ - Return a Firewall object based on the firewall name. - - :param name: The name of the firewall - :type name: ``str`` - - :return: A GCEFirewall object - :rtype: :class:`GCEFirewall` - """ - request = '/global/firewalls/%s' % (name) - response = self.connection.request(request, method='GET').object - return self._to_firewall(response) - - def ex_get_forwarding_rule(self, name, region=None): - """ - Return a Forwarding Rule object based on the forwarding rule name. - - :param name: The name of the forwarding rule - :type name: ``str`` - - :keyword region: The region to search for the rule in (set to 'all' - to search all regions). - :type region: ``str`` or ``None`` - - :return: A GCEForwardingRule object - :rtype: :class:`GCEForwardingRule` - """ - region = self._set_region(region) or self._find_zone_or_region( - name, 'forwardingRules', region=True, res_name='ForwardingRule') - request = '/regions/%s/forwardingRules/%s' % (region.name, name) - response = self.connection.request(request, method='GET').object - return self._to_forwarding_rule(response) - - def ex_get_image(self, partial_name): - """ - Return an GCENodeImage object based on the name or link provided. - - :param partial_name: The name, partial name, or full path of a GCE - image. - :type partial_name: ``str`` - - :return: GCENodeImage object based on provided information or None if - an image with that name is not found. - :rtype: :class:`GCENodeImage` or ``None`` - """ - if partial_name.startswith('https://'): - response = self.connection.request(partial_name, method='GET') - return self._to_node_image(response.object) - image = self._match_images(None, partial_name) - if not image: - if partial_name.startswith('debian'): - image = self._match_images('debian-cloud', partial_name) - elif partial_name.startswith('centos'): - image = self._match_images('centos-cloud', partial_name) - elif partial_name.startswith('container-vm'): - image = self._match_images('google-containers', partial_name) - - return image - - def ex_get_network(self, name): - """ - Return a Network object based on a network name. - - :param name: The name of the network - :type name: ``str`` - - :return: A Network object for the network - :rtype: :class:`GCENetwork` - """ - request = '/global/networks/%s' % (name) - response = self.connection.request(request, method='GET').object - return self._to_network(response) - - def ex_get_node(self, name, zone=None): - """ - Return a Node object based on a node name and optional zone. - - :param name: The name of the node - :type name: ``str`` - - :keyword zone: The zone to search for the node in. If set to 'all', - search all zones for the instance. - :type zone: ``str`` or :class:`GCEZone` or - :class:`NodeLocation` or ``None`` - - :return: A Node object for the node - :rtype: :class:`Node` - """ - zone = self._set_zone(zone) or self._find_zone_or_region( - name, 'instances', res_name='Node') - request = '/zones/%s/instances/%s' % (zone.name, name) - response = self.connection.request(request, method='GET').object - return self._to_node(response) - - def ex_get_project(self): - """ - Return a Project object with project-wide information. - - :return: A GCEProject object - :rtype: :class:`GCEProject` - """ - response = self.connection.request('', method='GET').object - return self._to_project(response) - - def ex_get_size(self, name, zone=None): - """ - Return a size object based on a machine type name and zone. - - :param name: The name of the node - :type name: ``str`` - - :keyword zone: The zone to search for the machine type in - :type zone: ``str`` or :class:`GCEZone` or - :class:`NodeLocation` or ``None`` - - :return: A GCENodeSize object for the machine type - :rtype: :class:`GCENodeSize` - """ - zone = zone or self.zone - if not hasattr(zone, 'name'): - zone = self.ex_get_zone(zone) - request = '/zones/%s/machineTypes/%s' % (zone.name, name) - response = self.connection.request(request, method='GET').object - return self._to_node_size(response) - - def ex_get_snapshot(self, name): - """ - Return a Snapshot object based on snapshot name. - - :param name: The name of the snapshot - :type name: ``str`` - - :return: A GCESnapshot object for the snapshot - :rtype: :class:`GCESnapshot` - """ - request = '/global/snapshots/%s' % (name) - response = self.connection.request(request, method='GET').object - return self._to_snapshot(response) - - def ex_get_volume(self, name, zone=None): - """ - Return a Volume object based on a volume name and optional zone. - - :param name: The name of the volume - :type name: ``str`` - - :keyword zone: The zone to search for the volume in (set to 'all' to - search all zones) - :type zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` - or ``None`` - - :return: A StorageVolume object for the volume - :rtype: :class:`StorageVolume` - """ - zone = self._set_zone(zone) or self._find_zone_or_region( - name, 'disks', res_name='Volume') - request = '/zones/%s/disks/%s' % (zone.name, name) - response = self.connection.request(request, method='GET').object - return self._to_storage_volume(response) - - def ex_get_region(self, name): - """ - Return a Region object based on the region name. - - :param name: The name of the region. - :type name: ``str`` - - :return: A GCERegion object for the region - :rtype: :class:`GCERegion` - """ - if name.startswith('https://'): - short_name = self._get_components_from_path(name)['name'] - request = name - else: - short_name = name - request = '/regions/%s' % (name) - # Check region cache first - if short_name in self.region_dict: - return self.region_dict[short_name] - # Otherwise, look up region information - response = self.connection.request(request, method='GET').object - return self._to_region(response) - - def ex_get_targetpool(self, name, region=None): - """ - Return a TargetPool object based on a name and optional region. - - :param name: The name of the target pool - :type name: ``str`` - - :keyword region: The region to search for the target pool in (set to - 'all' to search all regions). - :type region: ``str`` or :class:`GCERegion` or ``None`` - - :return: A TargetPool object for the pool - :rtype: :class:`GCETargetPool` - """ - region = self._set_region(region) or self._find_zone_or_region( - name, 'targetPools', region=True, res_name='TargetPool') - request = '/regions/%s/targetPools/%s' % (region.name, name) - response = self.connection.request(request, method='GET').object - return self._to_targetpool(response) - - def ex_get_zone(self, name): - """ - Return a Zone object based on the zone name. - - :param name: The name of the zone. - :type name: ``str`` - - :return: A GCEZone object for the zone or None if not found - :rtype: :class:`GCEZone` or ``None`` - """ - if name.startswith('https://'): - short_name = self._get_components_from_path(name)['name'] - request = name - else: - short_name = name - request = '/zones/%s' % (name) - # Check zone cache first - if short_name in self.zone_dict: - return self.zone_dict[short_name] - # Otherwise, look up zone information - try: - response = self.connection.request(request, method='GET').object - except ResourceNotFoundError: - return None - return self._to_zone(response) - - def ex_copy_image(self, name, url, description=None): - """ - Copy an image to your image collection. - - :param name: The name of the image - :type name: ``str`` - - :param url: The URL to the image. The URL can start with `gs://` - :param url: ``str`` - - :param description: The description of the image - :type description: ``str`` - - :return: NodeImage object based on provided information or None if an - image with that name is not found. - :rtype: :class:`NodeImage` or ``None`` - """ - - # the URL for an image can start with gs:// - if url.startswith('gs://'): - url = url.replace('gs://', 'https://storage.googleapis.com/', 1) - - image_data = { - 'name': name, - 'description': description, - 'sourceType': 'RAW', - 'rawDisk': { - 'source': url, - }, - } - - request = '/global/images' - self.connection.async_request(request, method='POST', - data=image_data) - return self.ex_get_image(name) - - def _ex_connection_class_kwargs(self): - return {'auth_type': self.auth_type, - 'project': self.project, - 'scopes': self.scopes} - - def _catch_error(self, ignore_errors=False): - """ - Catch an exception and raise it unless asked to ignore it. - - :keyword ignore_errors: If true, just return the error. Otherwise, - raise the error. - :type ignore_errors: ``bool`` - - :return: The exception that was raised. - :rtype: :class:`Exception` - """ - e = sys.exc_info()[1] - if ignore_errors: - return e - else: - raise e - - def _get_components_from_path(self, path): - """ - Return a dictionary containing name & zone/region from a request path. - - :param path: HTTP request path (e.g. - '/project/pjt-name/zones/us-central1-a/instances/mynode') - :type path: ``str`` - - :return: Dictionary containing name and zone/region of resource - :rtype ``dict`` - """ - region = None - zone = None - glob = False - components = path.split('/') - name = components[-1] - if components[-4] == 'regions': - region = components[-3] - elif components[-4] == 'zones': - zone = components[-3] - elif components[-3] == 'global': - glob = True - - return {'name': name, 'region': region, 'zone': zone, 'global': glob} - - def _get_region_from_zone(self, zone): - """ - Return the Region object that contains the given Zone object. - - :param zone: Zone object - :type zone: :class:`GCEZone` - - :return: Region object that contains the zone - :rtype: :class:`GCERegion` - """ - for region in self.region_list: - zones = [z.name for z in region.zones] - if zone.name in zones: - return region - - def _find_zone_or_region(self, name, res_type, region=False, - res_name=None): - """ - Find the zone or region for a named resource. - - :param name: Name of resource to find - :type name: ``str`` - - :param res_type: Type of resource to find. - Examples include: 'disks', 'instances' or 'addresses' - :type res_type: ``str`` - - :keyword region: If True, search regions instead of zones - :type region: ``bool`` - - :keyword res_name: The name of the resource type for error messages. - Examples: 'Volume', 'Node', 'Address' - :keyword res_name: ``str`` - - :return: Zone/Region object for the zone/region for the resource. - :rtype: :class:`GCEZone` or :class:`GCERegion` - """ - if region: - rz = 'region' - else: - rz = 'zone' - rz_name = None - res_name = res_name or res_type - request = '/aggregated/%s' % (res_type) - res_list = self.connection.request(request).object - for k, v in res_list['items'].items(): - for res in v.get(res_type, []): - if res['name'] == name: - rz_name = k.replace('%ss/' % (rz), '') - break - if not rz_name: - raise ResourceNotFoundError( - '%s \'%s\' not found in any %s.' % (res_name, name, rz), - None, None) - else: - getrz = getattr(self, 'ex_get_%s' % (rz)) - return getrz(rz_name) - - def _match_images(self, project, partial_name): - """ - Find the latest image, given a partial name. - - For example, providing 'debian-7' will return the image object for the - most recent image with a name that starts with 'debian-7' in the - supplied project. If no project is given, it will search your own - project. - - :param project: The name of the project to search for images. - Examples include: 'debian-cloud' and 'centos-cloud'. - :type project: ``str`` or ``None`` - - :param partial_name: The full name or beginning of a name for an - image. - :type partial_name: ``str`` - - :return: The latest image object that matches the partial name or None - if no matching image is found. - :rtype: :class:`GCENodeImage` or ``None`` - """ - project_images = self.list_images(project) - partial_match = [] - for image in project_images: - if image.name == partial_name: - return image - if image.name.startswith(partial_name): - ts = timestamp_to_datetime(image.extra['creationTimestamp']) - if not partial_match or partial_match[0] < ts: - partial_match = [ts, image] - - if partial_match: - return partial_match[1] - - def _set_region(self, region): - """ - Return the region to use for listing resources. - - :param region: A name, region object, None, or 'all' - :type region: ``str`` or :class:`GCERegion` or ``None`` - - :return: A region object or None if all regions should be considered - :rtype: :class:`GCERegion` or ``None`` - """ - region = region or self.region - - if region == 'all' or region is None: - return None - - if not hasattr(region, 'name'): - region = self.ex_get_region(region) - return region - - def _set_zone(self, zone): - """ - Return the zone to use for listing resources. - - :param zone: A name, zone object, None, or 'all' - :type region: ``str`` or :class:`GCEZone` or ``None`` - - :return: A zone object or None if all zones should be considered - :rtype: :class:`GCEZone` or ``None`` - """ - zone = zone or self.zone - - if zone == 'all' or zone is None: - return None - - if not hasattr(zone, 'name'): - zone = self.ex_get_zone(zone) - return zone - - def _create_node_req(self, name, size, image, location, network, - tags=None, metadata=None, boot_disk=None, - external_ip='ephemeral'): - """ - Returns a request and body to create a new node. This is a helper - method to support both :class:`create_node` and - :class:`ex_create_multiple_nodes`. - - :param name: The name of the node to create. - :type name: ``str`` - - :param size: The machine type to use. - :type size: :class:`GCENodeSize` - - :param image: The image to use to create the node (or, if using a - persistent disk, the image the disk was created from). - :type image: :class:`GCENodeImage` - - :param location: The location (zone) to create the node in. - :type location: :class:`NodeLocation` or :class:`GCEZone` - - :param network: The network to associate with the node. - :type network: :class:`GCENetwork` - - :keyword tags: A list of tags to associate with the node. - :type tags: ``list`` of ``str`` - - :keyword metadata: Metadata dictionary for instance. - :type metadata: ``dict`` - - :keyword boot_disk: Persistent boot disk to attach. - :type :class:`StorageVolume` - - :keyword external_ip: The external IP address to use. If 'ephemeral' - (default), a new non-static address will be - used. If 'None', then no external address will - be used. To use an existing static IP address, - a GCEAddress object should be passed in. - :type external_ip: :class:`GCEAddress` or ``str`` or None - - :return: A tuple containing a request string and a node_data dict. - :rtype: ``tuple`` of ``str`` and ``dict`` - """ - node_data = {} - node_data['machineType'] = size.extra['selfLink'] - node_data['name'] = name - if tags: - node_data['tags'] = {'items': tags} - if metadata: - node_data['metadata'] = metadata - - if boot_disk: - disks = [{'kind': 'compute#attachedDisk', - 'boot': True, - 'type': 'PERSISTENT', - 'mode': 'READ_WRITE', - 'deviceName': boot_disk.name, - 'zone': boot_disk.extra['zone'].extra['selfLink'], - 'source': boot_disk.extra['selfLink']}] - node_data['disks'] = disks - else: - node_data['image'] = image.extra['selfLink'] - - ni = [{'kind': 'compute#instanceNetworkInterface', - 'network': network.extra['selfLink']}] - if external_ip: - access_configs = [{'name': 'External NAT', - 'type': 'ONE_TO_ONE_NAT'}] - if hasattr(external_ip, 'address'): - access_configs[0]['natIP'] = external_ip.address - ni[0]['accessConfigs'] = access_configs - node_data['networkInterfaces'] = ni - - request = '/zones/%s/instances' % (location.name) - - return request, node_data - - def _multi_create_disk(self, status, node_attrs): - """Create disk for ex_create_multiple_nodes. - - :param status: Dictionary for holding node/disk creation status. - (This dictionary is modified by this method) - :type status: ``dict`` - - :param node_attrs: Dictionary for holding node attribute information. - (size, image, location, etc.) - :type node_attrs: ``dict`` - """ - disk = None - # Check for existing disk - if node_attrs['use_existing_disk']: - try: - disk = self.ex_get_volume(status['name'], - node_attrs['location']) - except ResourceNotFoundError: - pass - - if disk: - status['disk'] = disk - else: - # Create disk and return response object back in the status dict. - # Or, if there is an error, mark as failed. - disk_req, disk_data, disk_params = self._create_vol_req( - None, status['name'], location=node_attrs['location'], - image=node_attrs['image']) - try: - disk_res = self.connection.request( - disk_req, method='POST', data=disk_data, - params=disk_params).object - except GoogleBaseError: - e = self._catch_error( - ignore_errors=node_attrs['ignore_errors']) - error = e.value - code = e.code - disk_res = None - status['disk'] = GCEFailedDisk(status['name'], - error, code) - status['disk_response'] = disk_res - - def _multi_check_disk(self, status, node_attrs): - """Check disk status for ex_create_multiple_nodes. - - :param status: Dictionary for holding node/disk creation status. - (This dictionary is modified by this method) - :type status: ``dict`` - - :param node_attrs: Dictionary for holding node attribute information. - (size, image, location, etc.) - :type node_attrs: ``dict`` - """ - error = None - try: - response = self.connection.request( - status['disk_response']['selfLink']).object - except GoogleBaseError: - e = self._catch_error(ignore_errors=node_attrs['ignore_errors']) - error = e.value - code = e.code - response = {'status': 'DONE'} - if response['status'] == 'DONE': - status['disk_response'] = None - if error: - status['disk'] = GCEFailedDisk(status['name'], error, code) - else: - status['disk'] = self.ex_get_volume(status['name'], - node_attrs['location']) - - def _multi_create_node(self, status, node_attrs): - """Create node for ex_create_multiple_nodes. - - :param status: Dictionary for holding node/disk creation status. - (This dictionary is modified by this method) - :type status: ``dict`` - - :param node_attrs: Dictionary for holding node attribute information. - (size, image, location, etc.) - :type node_attrs: ``dict`` - """ - # If disk has an error, set the node as failed and return - if hasattr(status['disk'], 'error'): - status['node'] = status['disk'] - return - - # Create node and return response object in status dictionary. - # Or, if there is an error, mark as failed. - request, node_data = self._create_node_req( - status['name'], node_attrs['size'], node_attrs['image'], - node_attrs['location'], node_attrs['network'], node_attrs['tags'], - node_attrs['metadata'], boot_disk=status['disk'], - external_ip=node_attrs['external_ip']) - try: - node_res = self.connection.request( - request, method='POST', data=node_data).object - except GoogleBaseError: - e = self._catch_error(ignore_errors=node_attrs['ignore_errors']) - error = e.value - code = e.code - node_res = None - status['node'] = GCEFailedNode(status['name'], - error, code) - status['node_response'] = node_res - - def _multi_check_node(self, status, node_attrs): - """Check node status for ex_create_multiple_nodes. - - :param status: Dictionary for holding node/disk creation status. - (This dictionary is modified by this method) - :type status: ``dict`` - - :param node_attrs: Dictionary for holding node attribute information. - (size, image, location, etc.) - :type node_attrs: ``dict`` - """ - error = None - try: - response = self.connection.request( - status['node_response']['selfLink']).object - except GoogleBaseError: - e = self._catch_error(ignore_errors=node_attrs['ignore_errors']) - error = e.value - code = e.code - response = {'status': 'DONE'} - if response['status'] == 'DONE': - status['node_response'] = None - if error: - status['node'] = GCEFailedNode(status['name'], - error, code) - else: - status['node'] = self.ex_get_node(status['name'], - node_attrs['location']) - - def _create_vol_req(self, size, name, location=None, snapshot=None, - image=None): - """ - Assemble the request/data for creating a volume. - - Used by create_volume and ex_create_multiple_nodes - - :param size: Size of volume to create (in GB). Can be None if image - or snapshot is supplied. - :type size: ``int`` or ``str`` or ``None`` - - :param name: Name of volume to create - :type name: ``str`` - - :keyword location: Location (zone) to create the volume in - :type location: ``str`` or :class:`GCEZone` or - :class:`NodeLocation` or ``None`` - - :keyword snapshot: Snapshot to create image from - :type snapshot: :class:`GCESnapshot` or ``str`` or ``None`` - - :keyword image: Image to create disk from. - :type image: :class:`GCENodeImage` or ``str`` or ``None`` - - :return: Tuple containing the request string, the data dictionary and - the URL parameters - :rtype: ``tuple`` - """ - volume_data = {} - params = None - volume_data['name'] = name - if size: - volume_data['sizeGb'] = str(size) - if image: - if not hasattr(image, 'name'): - image = self.ex_get_image(image) - params = {'sourceImage': image.extra['selfLink']} - volume_data['description'] = 'Image: %s' % ( - image.extra['selfLink']) - if snapshot: - if not hasattr(snapshot, 'name'): - # Check for full URI to not break backward-compatibility - if snapshot.startswith('https'): - snapshot = self._get_components_from_path(snapshot)['name'] - snapshot = self.ex_get_snapshot(snapshot) - snapshot_link = snapshot.extra['selfLink'] - volume_data['sourceSnapshot'] = snapshot_link - volume_data['description'] = 'Snapshot: %s' % (snapshot_link) - location = location or self.zone - if not hasattr(location, 'name'): - location = self.ex_get_zone(location) - request = '/zones/%s/disks' % (location.name) - - return request, volume_data, params - - def _to_address(self, address): - """ - Return an Address object from the json-response dictionary. - - :param address: The dictionary describing the address. - :type address: ``dict`` - - :return: Address object - :rtype: :class:`GCEAddress` - """ - extra = {} - - region = self.ex_get_region(address['region']) - - extra['selfLink'] = address.get('selfLink') - extra['status'] = address.get('status') - extra['creationTimestamp'] = address.get('creationTimestamp') - - return GCEAddress(id=address['id'], name=address['name'], - address=address['address'], - region=region, driver=self, extra=extra) - - def _to_healthcheck(self, healthcheck): - """ - Return a HealthCheck object from the json-response dictionary. - - :param healthcheck: The dictionary describing the healthcheck. - :type healthcheck: ``dict`` - - :return: HealthCheck object - :rtype: :class:`GCEHealthCheck` - """ - extra = {} - extra['selfLink'] = healthcheck.get('selfLink') - extra['creationTimestamp'] = healthcheck.get('creationTimestamp') - extra['description'] = healthcheck.get('description') - extra['host'] = healthcheck.get('host') - - return GCEHealthCheck( - id=healthcheck['id'], name=healthcheck['name'], - path=healthcheck.get('requestPath'), port=healthcheck.get('port'), - interval=healthcheck.get('checkIntervalSec'), - timeout=healthcheck.get('timeoutSec'), - unhealthy_threshold=healthcheck.get('unhealthyThreshold'), - healthy_threshold=healthcheck.get('healthyThreshold'), - driver=self, extra=extra) - - def _to_firewall(self, firewall): - """ - Return a Firewall object from the json-response dictionary. - - :param firewall: The dictionary describing the firewall. - :type firewall: ``dict`` - - :return: Firewall object - :rtype: :class:`GCEFirewall` - """ - extra = {} - extra['selfLink'] = firewall.get('selfLink') - extra['creationTimestamp'] = firewall.get('creationTimestamp') - extra['description'] = firewall.get('description') - extra['network_name'] = self._get_components_from_path( - firewall['network'])['name'] - - network = self.ex_get_network(extra['network_name']) - source_ranges = firewall.get('sourceRanges') - source_tags = firewall.get('sourceTags') - target_tags = firewall.get('targetTags') - - return GCEFirewall(id=firewall['id'], name=firewall['name'], - allowed=firewall.get('allowed'), network=network, - source_ranges=source_ranges, - source_tags=source_tags, - target_tags=target_tags, - driver=self, extra=extra) - - def _to_forwarding_rule(self, forwarding_rule): - """ - Return a Forwarding Rule object from the json-response dictionary. - - :param forwarding_rule: The dictionary describing the rule. - :type forwarding_rule: ``dict`` - - :return: ForwardingRule object - :rtype: :class:`GCEForwardingRule` - """ - extra = {} - extra['selfLink'] = forwarding_rule.get('selfLink') - extra['portRange'] = forwarding_rule.get('portRange') - extra['creationTimestamp'] = forwarding_rule.get('creationTimestamp') - extra['description'] = forwarding_rule.get('description') - - region = self.ex_get_region(forwarding_rule['region']) - targetpool = self.ex_get_targetpool( - self._get_components_from_path(forwarding_rule['target'])['name']) - - return GCEForwardingRule(id=forwarding_rule['id'], - name=forwarding_rule['name'], region=region, - address=forwarding_rule.get('IPAddress'), - protocol=forwarding_rule.get('IPProtocol'), - targetpool=targetpool, - driver=self, extra=extra) - - def _to_network(self, network): - """ - Return a Network object from the json-response dictionary. - - :param network: The dictionary describing the network. - :type network: ``dict`` - - :return: Network object - :rtype: :class:`GCENetwork` - """ - extra = {} - - extra['selfLink'] = network.get('selfLink') - extra['gatewayIPv4'] = network.get('gatewayIPv4') - extra['description'] = network.get('description') - extra['creationTimestamp'] = network.get('creationTimestamp') - - return GCENetwork(id=network['id'], name=network['name'], - cidr=network.get('IPv4Range'), - driver=self, extra=extra) - - def _to_node_image(self, image): - """ - Return an Image object from the json-response dictionary. - - :param image: The dictionary describing the image. - :type image: ``dict`` - - :return: Image object - :rtype: :class:`GCENodeImage` - """ - extra = {} - extra['preferredKernel'] = image.get('preferredKernel', None) - extra['description'] = image.get('description', None) - extra['creationTimestamp'] = image.get('creationTimestamp') - extra['selfLink'] = image.get('selfLink') - extra['deprecated'] = image.get('deprecated', None) - - return GCENodeImage(id=image['id'], name=image['name'], driver=self, - extra=extra) - - def _to_node_location(self, location): - """ - Return a Location object from the json-response dictionary. - - :param location: The dictionary describing the location. - :type location: ``dict`` - - :return: Location object - :rtype: :class:`NodeLocation` - """ - return NodeLocation(id=location['id'], name=location['name'], - country=location['name'].split('-')[0], - driver=self) - - def _to_node(self, node): - """ - Return a Node object from the json-response dictionary. - - :param node: The dictionary describing the node. - :type node: ``dict`` - - :return: Node object - :rtype: :class:`Node` - """ - public_ips = [] - private_ips = [] - extra = {} - - extra['status'] = node.get('status') - extra['description'] = node.get('description') - extra['zone'] = self.ex_get_zone(node['zone']) - extra['image'] = node.get('image') - extra['machineType'] = node.get('machineType') - extra['disks'] = node.get('disks', []) - extra['networkInterfaces'] = node.get('networkInterfaces') - extra['id'] = node['id'] - extra['selfLink'] = node.get('selfLink') - extra['name'] = node['name'] - extra['metadata'] = node.get('metadata', {}) - extra['tags_fingerprint'] = node['tags']['fingerprint'] - extra['scheduling'] = node.get('scheduling', {}) - extra['deprecated'] = True if node.get('deprecated', None) else False - - for disk in extra['disks']: - if disk.get('boot') and disk.get('type') == 'PERSISTENT': - bd = self._get_components_from_path(disk['source']) - extra['boot_disk'] = self.ex_get_volume(bd['name'], bd['zone']) - - if 'items' in node['tags']: - tags = node['tags']['items'] - else: - tags = [] - extra['tags'] = tags - - for network_interface in node.get('networkInterfaces', []): - private_ips.append(network_interface.get('networkIP')) - for access_config in network_interface.get('accessConfigs', []): - public_ips.append(access_config.get('natIP')) - - # For the node attributes, use just machine and image names, not full - # paths. Full paths are available in the "extra" dict. - if extra['image']: - image = self._get_components_from_path(extra['image'])['name'] - else: - image = None - size = self._get_components_from_path(node['machineType'])['name'] - - return Node(id=node['id'], name=node['name'], - state=self.NODE_STATE_MAP[node['status']], - public_ips=public_ips, private_ips=private_ips, - driver=self, size=size, image=image, extra=extra) - - def _to_node_size(self, machine_type): - """ - Return a Size object from the json-response dictionary. - - :param machine_type: The dictionary describing the machine. - :type machine_type: ``dict`` - - :return: Size object - :rtype: :class:`GCENodeSize` - """ - extra = {} - extra['selfLink'] = machine_type.get('selfLink') - extra['zone'] = self.ex_get_zone(machine_type['zone']) - extra['description'] = machine_type.get('description') - extra['guestCpus'] = machine_type.get('guestCpus') - extra['creationTimestamp'] = machine_type.get('creationTimestamp') - try: - price = self._get_size_price(size_id=machine_type['name']) - except KeyError: - price = None - - return GCENodeSize(id=machine_type['id'], name=machine_type['name'], - ram=machine_type.get('memoryMb'), - disk=machine_type.get('imageSpaceGb'), - bandwidth=0, price=price, driver=self, extra=extra) - - def _to_project(self, project): - """ - Return a Project object from the json-response dictionary. - - :param project: The dictionary describing the project. - :type project: ``dict`` - - :return: Project object - :rtype: :class:`GCEProject` - """ - extra = {} - extra['selfLink'] = project.get('selfLink') - extra['creationTimestamp'] = project.get('creationTimestamp') - extra['description'] = project.get('description') - metadata = project['commonInstanceMetadata'].get('items') - - return GCEProject(id=project['id'], name=project['name'], - metadata=metadata, quotas=project.get('quotas'), - driver=self, extra=extra) - - def _to_region(self, region): - """ - Return a Region object from the json-response dictionary. - - :param region: The dictionary describing the region. - :type region: ``dict`` - - :return: Region object - :rtype: :class:`GCERegion` - """ - extra = {} - extra['selfLink'] = region.get('selfLink') - extra['creationTimestamp'] = region.get('creationTimestamp') - extra['description'] = region.get('description') - - quotas = region.get('quotas') - zones = [self.ex_get_zone(z) for z in region.get('zones', [])] - # Work around a bug that will occasionally list missing zones in the - # region output - zones = [z for z in zones if z is not None] - deprecated = region.get('deprecated') - - return GCERegion(id=region['id'], name=region['name'], - status=region.get('status'), zones=zones, - quotas=quotas, deprecated=deprecated, - driver=self, extra=extra) - - def _to_snapshot(self, snapshot): - """ - Return a Snapshot object from the json-response dictionary. - - :param snapshot: The dictionary describing the snapshot - :type snapshot: ``dict`` - - :return: Snapshot object - :rtype: :class:`VolumeSnapshot` - """ - extra = {} - extra['selfLink'] = snapshot.get('selfLink') - extra['creationTimestamp'] = snapshot.get('creationTimestamp') - extra['sourceDisk'] = snapshot.get('sourceDisk') - - return GCESnapshot(id=snapshot['id'], name=snapshot['name'], - size=snapshot['diskSizeGb'], - status=snapshot.get('status'), driver=self, - extra=extra) - - def _to_storage_volume(self, volume): - """ - Return a Volume object from the json-response dictionary. - - :param volume: The dictionary describing the volume. - :type volume: ``dict`` - - :return: Volume object - :rtype: :class:`StorageVolume` - """ - extra = {} - extra['selfLink'] = volume.get('selfLink') - extra['zone'] = self.ex_get_zone(volume['zone']) - extra['status'] = volume.get('status') - extra['creationTimestamp'] = volume.get('creationTimestamp') - extra['description'] = volume.get('description') - - return StorageVolume(id=volume['id'], name=volume['name'], - size=volume['sizeGb'], driver=self, extra=extra) - - def _to_targetpool(self, targetpool): - """ - Return a Target Pool object from the json-response dictionary. - - :param targetpool: The dictionary describing the volume. - :type targetpool: ``dict`` - - :return: Target Pool object - :rtype: :class:`GCETargetPool` - """ - extra = {} - extra['selfLink'] = targetpool.get('selfLink') - extra['description'] = targetpool.get('description') - region = self.ex_get_region(targetpool['region']) - healthcheck_list = [self.ex_get_healthcheck(h.split('/')[-1]) for h - in targetpool.get('healthChecks', [])] - node_list = [] - for n in targetpool.get('instances', []): - # Nodes that do not exist can be part of a target pool. If the - # node does not exist, use the URL of the node instead of the node - # object. - comp = self._get_components_from_path(n) - try: - node = self.ex_get_node(comp['name'], comp['zone']) - except ResourceNotFoundError: - node = n - node_list.append(node) - - return GCETargetPool(id=targetpool['id'], name=targetpool['name'], - region=region, healthchecks=healthcheck_list, - nodes=node_list, driver=self, extra=extra) - - def _to_zone(self, zone): - """ - Return a Zone object from the json-response dictionary. - - :param zone: The dictionary describing the zone. - :type zone: ``dict`` - - :return: Zone object - :rtype: :class:`GCEZone` - """ - extra = {} - extra['selfLink'] = zone.get('selfLink') - extra['creationTimestamp'] = zone.get('creationTimestamp') - extra['description'] = zone.get('description') - - deprecated = zone.get('deprecated') - - return GCEZone(id=zone['id'], name=zone['name'], status=zone['status'], - maintenance_windows=zone.get('maintenanceWindows'), - deprecated=deprecated, driver=self, extra=extra) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/gogrid.py b/awx/lib/site-packages/libcloud/compute/drivers/gogrid.py deleted file mode 100644 index 6c73e46eb9..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/gogrid.py +++ /dev/null @@ -1,464 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -GoGrid driver -""" -import time -import hashlib -import copy - -from libcloud.utils.py3 import b - -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.common.gogrid import GoGridConnection, BaseGoGridDriver -from libcloud.compute.providers import Provider -from libcloud.compute.types import NodeState -from libcloud.compute.base import Node, NodeDriver -from libcloud.compute.base import NodeSize, NodeImage, NodeLocation - -STATE = { - "Starting": NodeState.PENDING, - "On": NodeState.RUNNING, - "On/Saving": NodeState.RUNNING, - "Off": NodeState.PENDING, - "Restarting": NodeState.REBOOTING, - "Saving": NodeState.PENDING, - "Restoring": NodeState.PENDING, -} - -GOGRID_INSTANCE_TYPES = { - '512MB': {'id': '512MB', - 'name': '512MB', - 'ram': 512, - 'disk': 30, - 'bandwidth': None}, - '1GB': {'id': '1GB', - 'name': '1GB', - 'ram': 1024, - 'disk': 60, - 'bandwidth': None}, - '2GB': {'id': '2GB', - 'name': '2GB', - 'ram': 2048, - 'disk': 120, - 'bandwidth': None}, - '4GB': {'id': '4GB', - 'name': '4GB', - 'ram': 4096, - 'disk': 240, - 'bandwidth': None}, - '8GB': {'id': '8GB', - 'name': '8GB', - 'ram': 8192, - 'disk': 480, - 'bandwidth': None}, - '16GB': {'id': '16GB', - 'name': '16GB', - 'ram': 16384, - 'disk': 960, - 'bandwidth': None}, - '24GB': {'id': '24GB', - 'name': '24GB', - 'ram': 24576, - 'disk': 960, - 'bandwidth': None}, -} - - -class GoGridNode(Node): - # Generating uuid based on public ip to get around missing id on - # create_node in gogrid api - # - # Used public ip since it is not mutable and specified at create time, - # so uuid of node should not change after add is completed - def get_uuid(self): - return hashlib.sha1( - b("%s:%s" % (self.public_ips, self.driver.type)) - ).hexdigest() - - -class GoGridNodeDriver(BaseGoGridDriver, NodeDriver): - """ - GoGrid node driver - """ - - connectionCls = GoGridConnection - type = Provider.GOGRID - api_name = 'gogrid' - name = 'GoGrid' - website = 'http://www.gogrid.com/' - features = {"create_node": ["generates_password"]} - - _instance_types = GOGRID_INSTANCE_TYPES - - def __init__(self, *args, **kwargs): - """ - @inherits: :class:`NodeDriver.__init__` - """ - super(GoGridNodeDriver, self).__init__(*args, **kwargs) - - def _get_state(self, element): - try: - return STATE[element['state']['name']] - except: - pass - return NodeState.UNKNOWN - - def _get_ip(self, element): - return element.get('ip').get('ip') - - def _get_id(self, element): - return element.get('id') - - def _to_node(self, element, password=None): - state = self._get_state(element) - ip = self._get_ip(element) - id = self._get_id(element) - n = GoGridNode(id=id, - name=element['name'], - state=state, - public_ips=[ip], - private_ips=[], - extra={'ram': element.get('ram').get('name'), - 'description': element.get('description', '')}, - driver=self.connection.driver) - if password: - n.extra['password'] = password - - return n - - def _to_image(self, element): - n = NodeImage(id=element['id'], - name=element['friendlyName'], - driver=self.connection.driver) - return n - - def _to_images(self, object): - return [self._to_image(el) - for el in object['list']] - - def _to_location(self, element): - location = NodeLocation(id=element['id'], - name=element['name'], - country="US", - driver=self.connection.driver) - return location - - def _to_locations(self, object): - return [self._to_location(el) - for el in object['list']] - - def list_images(self, location=None): - params = {} - if location is not None: - params["datacenter"] = location.id - images = self._to_images( - self.connection.request('/api/grid/image/list', params).object) - return images - - def list_nodes(self): - """ - @inherits: :class:`NodeDriver.list_nodes` - :rtype: ``list`` of :class:`GoGridNode` - """ - passwords_map = {} - - res = self._server_list() - try: - for password in self._password_list()['list']: - try: - passwords_map[password['server']['id']] = \ - password['password'] - except KeyError: - pass - except InvalidCredsError: - # some gogrid API keys don't have permission to access the - # password list. - pass - - return [self._to_node(el, passwords_map.get(el.get('id'))) - for el in res['list']] - - def reboot_node(self, node): - """ - @inherits: :class:`NodeDriver.reboot_node` - :type node: :class:`GoGridNode` - """ - id = node.id - power = 'restart' - res = self._server_power(id, power) - if not res.success(): - raise Exception(res.parse_error()) - return True - - def destroy_node(self, node): - """ - @inherits: :class:`NodeDriver.reboot_node` - :type node: :class:`GoGridNode` - """ - id = node.id - res = self._server_delete(id) - if not res.success(): - raise Exception(res.parse_error()) - return True - - def _server_list(self): - return self.connection.request('/api/grid/server/list').object - - def _password_list(self): - return self.connection.request('/api/support/password/list').object - - def _server_power(self, id, power): - # power in ['start', 'stop', 'restart'] - params = {'id': id, 'power': power} - return self.connection.request("/api/grid/server/power", params, - method='POST') - - def _server_delete(self, id): - params = {'id': id} - return self.connection.request("/api/grid/server/delete", params, - method='POST') - - def _get_first_ip(self, location=None): - ips = self.ex_list_ips(public=True, assigned=False, location=location) - try: - return ips[0].ip - except IndexError: - raise LibcloudError('No public unassigned IPs left', - GoGridNodeDriver) - - def list_sizes(self, location=None): - sizes = [] - for key, values in self._instance_types.items(): - attributes = copy.deepcopy(values) - attributes.update({'price': self._get_size_price(size_id=key)}) - sizes.append(NodeSize(driver=self.connection.driver, **attributes)) - - return sizes - - def list_locations(self): - locations = self._to_locations( - self.connection.request('/api/common/lookup/list', - params={'lookup': 'ip.datacenter'}).object) - return locations - - def ex_create_node_nowait(self, **kwargs): - """Don't block until GoGrid allocates id for a node - but return right away with id == None. - - The existence of this method is explained by the fact - that GoGrid assigns id to a node only few minutes after - creation. - - - :keyword name: String with a name for this new node (required) - :type name: ``str`` - - :keyword size: The size of resources allocated to this node . - (required) - :type size: :class:`NodeSize` - - :keyword image: OS Image to boot on node. (required) - :type image: :class:`NodeImage` - - :keyword ex_description: Description of a Node - :type ex_description: ``str`` - - :keyword ex_ip: Public IP address to use for a Node. If not - specified, first available IP address will be picked - :type ex_ip: ``str`` - - :rtype: :class:`GoGridNode` - """ - name = kwargs['name'] - image = kwargs['image'] - size = kwargs['size'] - try: - ip = kwargs['ex_ip'] - except KeyError: - ip = self._get_first_ip(kwargs.get('location')) - - params = {'name': name, - 'image': image.id, - 'description': kwargs.get('ex_description', ''), - 'server.ram': size.id, - 'ip': ip} - - object = self.connection.request('/api/grid/server/add', - params=params, method='POST').object - node = self._to_node(object['list'][0]) - - return node - - def create_node(self, **kwargs): - """Create a new GoGird node - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_description: Description of a Node - :type ex_description: ``str`` - - :keyword ex_ip: Public IP address to use for a Node. If not - specified, first available IP address will be picked - :type ex_ip: ``str`` - - :rtype: :class:`GoGridNode` - """ - node = self.ex_create_node_nowait(**kwargs) - - timeout = 60 * 20 - waittime = 0 - interval = 2 * 60 - - while node.id is None and waittime < timeout: - nodes = self.list_nodes() - - for i in nodes: - if i.public_ips[0] == node.public_ips[0] and i.id is not None: - return i - - waittime += interval - time.sleep(interval) - - if id is None: - raise Exception( - "Wasn't able to wait for id allocation for the node %s" - % str(node)) - - return node - - def ex_save_image(self, node, name): - """Create an image for node. - - Please refer to GoGrid documentation to get info - how prepare a node for image creation: - - http://wiki.gogrid.com/wiki/index.php/MyGSI - - :keyword node: node to use as a base for image - :type node: :class:`GoGridNode` - - :keyword name: name for new image - :type name: ``str`` - - :rtype: :class:`NodeImage` - """ - params = {'server': node.id, - 'friendlyName': name} - object = self.connection.request('/api/grid/image/save', params=params, - method='POST').object - - return self._to_images(object)[0] - - def ex_edit_node(self, **kwargs): - """Change attributes of a node. - - :keyword node: node to be edited (required) - :type node: :class:`GoGridNode` - - :keyword size: new size of a node (required) - :type size: :class:`NodeSize` - - :keyword ex_description: new description of a node - :type ex_description: ``str`` - - :rtype: :class:`Node` - """ - node = kwargs['node'] - size = kwargs['size'] - - params = {'id': node.id, - 'server.ram': size.id} - - if 'ex_description' in kwargs: - params['description'] = kwargs['ex_description'] - - object = self.connection.request('/api/grid/server/edit', - params=params).object - - return self._to_node(object['list'][0]) - - def ex_edit_image(self, **kwargs): - """Edit metadata of a server image. - - :keyword image: image to be edited (required) - :type image: :class:`NodeImage` - - :keyword public: should be the image public (required) - :type public: ``bool`` - - :keyword ex_description: description of the image (optional) - :type ex_description: ``str`` - - :keyword name: name of the image - :type name: ``str`` - - :rtype: :class:`NodeImage` - """ - - image = kwargs['image'] - public = kwargs['public'] - - params = {'id': image.id, - 'isPublic': str(public).lower()} - - if 'ex_description' in kwargs: - params['description'] = kwargs['ex_description'] - - if 'name' in kwargs: - params['friendlyName'] = kwargs['name'] - - object = self.connection.request('/api/grid/image/edit', - params=params).object - - return self._to_image(object['list'][0]) - - def ex_list_ips(self, **kwargs): - """Return list of IP addresses assigned to - the account. - - :keyword public: set to True to list only - public IPs or False to list only - private IPs. Set to None or not specify - at all not to filter by type - :type public: ``bool`` - - :keyword assigned: set to True to list only addresses - assigned to servers, False to list unassigned - addresses and set to None or don't set at all - not no filter by state - :type assigned: ``bool`` - - :keyword location: filter IP addresses by location - :type location: :class:`NodeLocation` - - :rtype: ``list`` of :class:`GoGridIpAddress` - """ - - params = {} - - if "public" in kwargs and kwargs["public"] is not None: - params["ip.type"] = {True: "Public", - False: "Private"}[kwargs["public"]] - if "assigned" in kwargs and kwargs["assigned"] is not None: - params["ip.state"] = {True: "Assigned", - False: "Unassigned"}[kwargs["assigned"]] - if "location" in kwargs and kwargs['location'] is not None: - params['datacenter'] = kwargs['location'].id - - ips = self._to_ips( - self.connection.request('/api/grid/ip/list', - params=params).object) - return ips diff --git a/awx/lib/site-packages/libcloud/compute/drivers/gridspot.py b/awx/lib/site-packages/libcloud/compute/drivers/gridspot.py deleted file mode 100644 index 856b0688f2..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/gridspot.py +++ /dev/null @@ -1,127 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.compute.base import NodeDriver, Node -from libcloud.compute.base import NodeState -from libcloud.common.base import ConnectionKey, JsonResponse -from libcloud.compute.types import Provider -from libcloud.common.types import InvalidCredsError - - -class GridspotAPIException(Exception): - def __str__(self): - return self.args[0] - - def __repr__(self): - return "<GridspotAPIException '%s'>" % (self.args[0]) - - -class GridspotResponse(JsonResponse): - """ - Response class for Gridspot - """ - def parse_body(self): - body = super(GridspotResponse, self).parse_body() - - if 'exception_name' in body and body['exception_name']: - raise GridspotAPIException(body['exception_name']) - - return body - - def parse_error(self): - # Gridspot 404s on invalid api key or instance_id - raise InvalidCredsError("Invalid api key/instance_id") - - -class GridspotConnection(ConnectionKey): - """ - Connection class to connect to Gridspot's API servers - """ - - host = 'gridspot.com' - responseCls = GridspotResponse - - def add_default_params(self, params): - params['api_key'] = self.key - return params - - -class GridspotNodeDriver(NodeDriver): - """ - Gridspot (http://www.gridspot.com/) node driver. - """ - - type = Provider.GRIDSPOT - name = 'Gridspot' - website = 'http://www.gridspot.com/' - connectionCls = GridspotConnection - NODE_STATE_MAP = { - 'Running': NodeState.RUNNING, - 'Starting': NodeState.PENDING - } - - def list_nodes(self): - data = self.connection.request( - '/compute_api/v1/list_instances').object - return [self._to_node(n) for n in data['instances']] - - def destroy_node(self, node): - data = {'instance_id': node.id} - self.connection.request('/compute_api/v1/stop_instance', data).object - return True - - def _get_node_state(self, state): - result = self.NODE_STATE_MAP.get(state, NodeState.UNKNOWN) - return result - - def _add_int_param(self, params, data, field): - if data[field]: - try: - params[field] = int(data[field]) - except: - pass - - def _to_node(self, data): - port = None - ip = None - - state = self._get_node_state(data['current_state']) - - if data['vm_ssh_wan_ip_endpoint'] != 'null': - parts = data['vm_ssh_wan_ip_endpoint'].split(':') - ip = parts[0] - port = int(parts[1]) - - extra_params = { - 'winning_bid_id': data['winning_bid_id'], - 'port': port - } - - # Spec is vague and doesn't indicate if these will always be present - self._add_int_param(extra_params, data, 'vm_num_logical_cores') - self._add_int_param(extra_params, data, 'vm_num_physical_cores') - self._add_int_param(extra_params, data, 'vm_ram') - self._add_int_param(extra_params, data, 'start_state_time') - self._add_int_param(extra_params, data, 'ended_state_time') - self._add_int_param(extra_params, data, 'running_state_time') - - return Node( - id=data['instance_id'], - name=data['instance_id'], - state=state, - public_ips=[ip], - private_ips=[], - driver=self.connection.driver, - extra=extra_params) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/hostvirtual.py b/awx/lib/site-packages/libcloud/compute/drivers/hostvirtual.py deleted file mode 100644 index e9fa6c80a5..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/hostvirtual.py +++ /dev/null @@ -1,341 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -libcloud driver for the Host Virtual Inc. (VR) API -Home page http://www.vr.org/ -""" - -import time - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.common.hostvirtual import HostVirtualResponse -from libcloud.common.hostvirtual import HostVirtualConnection -from libcloud.common.hostvirtual import HostVirtualException -from libcloud.compute.providers import Provider -from libcloud.compute.types import NodeState -from libcloud.compute.base import Node, NodeDriver -from libcloud.compute.base import NodeImage, NodeSize, NodeLocation -from libcloud.compute.base import NodeAuthSSHKey, NodeAuthPassword - -API_ROOT = '' - -NODE_STATE_MAP = { - 'BUILDING': NodeState.PENDING, - 'PENDING': NodeState.PENDING, - 'RUNNING': NodeState.RUNNING, # server is powered up - 'STOPPING': NodeState.REBOOTING, - 'REBOOTING': NodeState.REBOOTING, - 'STARTING': NodeState.REBOOTING, - 'TERMINATED': NodeState.TERMINATED, # server is powered down - 'STOPPED': NodeState.STOPPED -} - -DEFAULT_NODE_LOCATION_ID = 4 - - -class HostVirtualComputeResponse(HostVirtualResponse): - pass - - -class HostVirtualComputeConnection(HostVirtualConnection): - responseCls = HostVirtualComputeResponse - - -class HostVirtualNodeDriver(NodeDriver): - type = Provider.HOSTVIRTUAL - name = 'HostVirtual' - website = 'http://www.vr.org' - connectionCls = HostVirtualComputeConnection - features = {'create_node': ['ssh_key', 'password']} - - def __init__(self, key, secure=True, host=None, port=None): - self.location = None - super(HostVirtualNodeDriver, self).__init__(key=key, secure=secure, - host=host, port=port) - - def _to_node(self, data): - state = NODE_STATE_MAP[data['status']] - public_ips = [] - private_ips = [] - extra = {} - - if 'plan_id' in data: - extra['size'] = data['plan_id'] - if 'os_id' in data: - extra['image'] = data['os_id'] - if 'location_id' in data: - extra['location'] = data['location_id'] - if 'ip' in data: - public_ips.append(data['ip']) - - node = Node(id=data['mbpkgid'], name=data['fqdn'], state=state, - public_ips=public_ips, private_ips=private_ips, - driver=self.connection.driver, extra=extra) - return node - - def list_locations(self): - result = self.connection.request(API_ROOT + '/cloud/locations/').object - locations = [] - for dc in result: - locations.append(NodeLocation( - dc["id"], - dc["name"], - dc["name"].split(',')[1].replace(" ", ""), # country - self)) - return locations - - def list_sizes(self, location=None): - params = {} - if location: - params = {'location': location.id} - result = self.connection.request( - API_ROOT + '/cloud/sizes/', - data=json.dumps(params)).object - sizes = [] - for size in result: - n = NodeSize(id=size['plan_id'], - name=size['plan'], - ram=size['ram'], - disk=size['disk'], - bandwidth=size['transfer'], - price=size['price'], - driver=self.connection.driver) - sizes.append(n) - return sizes - - def list_images(self): - result = self.connection.request(API_ROOT + '/cloud/images/').object - images = [] - for image in result: - i = NodeImage(id=image["id"], - name=image["os"], - driver=self.connection.driver, - extra=image) - del i.extra['id'] - del i.extra['os'] - images.append(i) - return images - - def list_nodes(self): - result = self.connection.request(API_ROOT + '/cloud/servers/').object - nodes = [] - for value in result: - node = self._to_node(value) - nodes.append(node) - return nodes - - def _wait_for_node(self, node_id, timeout=30, interval=5.0): - """ - :param node_id: ID of the node to wait for. - :type node_id: ``int`` - - :param timeout: Timeout (in seconds). - :type timeout: ``int`` - - :param interval: How long to wait (in seconds) between each attempt. - :type interval: ``float`` - """ - # poll until we get a node - for i in range(0, timeout, int(interval)): - try: - node = self.ex_get_node(node_id) - return node - except HostVirtualException: - time.sleep(interval) - - raise HostVirtualException(412, 'Timedout on getting node details') - - def create_node(self, **kwargs): - dc = None - - size = kwargs['size'] - image = kwargs['image'] - - auth = self._get_and_check_auth(kwargs.get('auth')) - - params = {'plan': size.name} - - dc = DEFAULT_NODE_LOCATION_ID - if 'location' in kwargs: - dc = kwargs['location'].id - - # simply order a package first - result = self.connection.request(API_ROOT + '/cloud/buy/', - data=json.dumps(params), - method='POST').object - - # create a stub node - stub_node = self._to_node({ - 'mbpkgid': result['id'], - 'status': 'PENDING', - 'fqdn': kwargs['name'], - 'plan_id': size.id, - 'os_id': image.id, - 'location_id': dc - }) - - # provisioning a server using the stub node - self.ex_provision_node(node=stub_node, auth=auth) - node = self._wait_for_node(stub_node.id) - - if getattr(auth, 'generated', False): - node.extra['password'] = auth.password - - return node - - def reboot_node(self, node): - params = {'force': 0, 'mbpkgid': node.id} - result = self.connection.request( - API_ROOT + '/cloud/server/reboot', - data=json.dumps(params), - method='POST').object - - return bool(result) - - def destroy_node(self, node): - params = { - 'mbpkgid': node.id, - # 'reason': 'Submitted through Libcloud API' - } - - result = self.connection.request( - API_ROOT + '/cloud/cancel', data=json.dumps(params), - method='POST').object - - return bool(result) - - def ex_get_node(self, node_id): - """ - Get a single node. - - :param node_id: id of the node that we need the node object for - :type node_id: ``str`` - - :rtype: :class:`Node` - """ - - params = {'mbpkgid': node_id} - result = self.connection.request( - API_ROOT + '/cloud/server', params=params).object - node = self._to_node(result) - return node - - def ex_stop_node(self, node): - """ - Stop a node. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - params = {'force': 0, 'mbpkgid': node.id} - result = self.connection.request( - API_ROOT + '/cloud/server/shutdown', - data=json.dumps(params), - method='POST').object - - return bool(result) - - def ex_start_node(self, node): - """ - Start a node. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - params = {'mbpkgid': node.id} - result = self.connection.request( - API_ROOT + '/cloud/server/start', - data=json.dumps(params), - method='POST').object - - return bool(result) - - def ex_provision_node(self, **kwargs): - """ - Provision a server on a VR package and get it booted - - :keyword node: node which should be used - :type node: :class:`Node` - - :keyword image: The distribution to deploy on your server (mandatory) - :type image: :class:`NodeImage` - - :keyword auth: an SSH key or root password (mandatory) - :type auth: :class:`NodeAuthSSHKey` or :class:`NodeAuthPassword` - - :keyword location: which datacenter to create the server in - :type location: :class:`NodeLocation` - - :return: Node representing the newly built server - :rtype: :class:`Node` - """ - - node = kwargs['node'] - - if 'image' in kwargs: - image = kwargs['image'] - else: - image = node.extra['image'] - - params = { - 'mbpkgid': node.id, - 'image': image, - 'fqdn': node.name, - 'location': node.extra['location'], - } - - auth = kwargs['auth'] - - ssh_key = None - password = None - if isinstance(auth, NodeAuthSSHKey): - ssh_key = auth.pubkey - params['ssh_key'] = ssh_key - elif isinstance(auth, NodeAuthPassword): - password = auth.password - params['password'] = password - - if not ssh_key and not password: - raise HostVirtualException(500, "Need SSH key or Root password") - - result = self.connection.request(API_ROOT + '/cloud/server/build', - data=json.dumps(params), - method='POST').object - return bool(result) - - def ex_delete_node(self, node): - """ - Delete a node. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - - params = {'mbpkgid': node.id} - result = self.connection.request( - API_ROOT + '/cloud/server/delete', data=json.dumps(params), - method='POST').object - - return bool(result) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/hpcloud.py b/awx/lib/site-packages/libcloud/compute/drivers/hpcloud.py deleted file mode 100644 index 97de03e925..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/hpcloud.py +++ /dev/null @@ -1,99 +0,0 @@ -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -HP Public cloud driver which is esentially just a small wrapper around -OpenStack driver. -""" - -from libcloud.compute.types import Provider, LibcloudError -from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection -from libcloud.compute.drivers.openstack import OpenStack_1_1_NodeDriver - - -__all__ = [ - 'HPCloudNodeDriver' -] - -ENDPOINT_ARGS_MAP = { - 'region-a.geo-1': { - 'service_type': 'compute', - 'name': 'Compute', - 'region': 'region-a.geo-1' - }, - 'region-b.geo-1': { - 'service_type': 'compute', - 'name': 'Compute', - 'region': 'region-b.geo-1' - }, -} - -AUTH_URL_TEMPLATE = 'https://%s.identity.hpcloudsvc.com:35357/v2.0/tokens' - - -class HPCloudConnection(OpenStack_1_1_Connection): - _auth_version = '2.0_password' - - def __init__(self, *args, **kwargs): - self.region = kwargs.pop('region', None) - self.get_endpoint_args = kwargs.pop('get_endpoint_args', None) - super(HPCloudConnection, self).__init__(*args, **kwargs) - - def get_endpoint(self): - if not self.get_endpoint_args: - raise LibcloudError( - 'HPCloudConnection must have get_endpoint_args set') - - if '2.0_password' in self._auth_version: - ep = self.service_catalog.get_endpoint(**self.get_endpoint_args) - else: - raise LibcloudError( - 'Auth version "%s" not supported' % (self._auth_version)) - - public_url = ep.get('publicURL', None) - - if not public_url: - raise LibcloudError('Could not find specified endpoint') - - return public_url - - -class HPCloudNodeDriver(OpenStack_1_1_NodeDriver): - name = 'HP Public Cloud (Helion)' - website = 'http://www.hpcloud.com/' - connectionCls = HPCloudConnection - type = Provider.HPCLOUD - - def __init__(self, key, secret, tenant_name, secure=True, - host=None, port=None, region='region-b.geo-1', **kwargs): - """ - Note: tenant_name argument is required for HP cloud. - """ - self.tenant_name = tenant_name - super(HPCloudNodeDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, - region=region, - **kwargs) - - def _ex_connection_class_kwargs(self): - endpoint_args = ENDPOINT_ARGS_MAP[self.region] - - kwargs = self.openstack_connection_kwargs() - kwargs['region'] = self.region - kwargs['get_endpoint_args'] = endpoint_args - kwargs['ex_force_auth_url'] = AUTH_URL_TEMPLATE % (self.region) - kwargs['ex_tenant_name'] = self.tenant_name - - return kwargs diff --git a/awx/lib/site-packages/libcloud/compute/drivers/ibm_sce.py b/awx/lib/site-packages/libcloud/compute/drivers/ibm_sce.py deleted file mode 100644 index bcf73b9a8d..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/ibm_sce.py +++ /dev/null @@ -1,753 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Driver for IBM SmartCloud Enterprise - -Formerly known as: -- IBM Developer Cloud -- IBM Smart Business Development and Test on the IBM Cloud -- IBM SmartBusiness Cloud -""" - -import base64 -import time - -from libcloud.utils.py3 import urlencode -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -from libcloud.common.base import XmlResponse, ConnectionUserAndKey -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.compute.types import NodeState, Provider -from libcloud.compute.base import NodeDriver, Node, NodeImage, \ - NodeSize, NodeLocation, NodeAuthSSHKey, StorageVolume - -HOST = 'www-147.ibm.com' -REST_BASE = '/computecloud/enterprise/api/rest/20100331' - - -class IBMResponse(XmlResponse): - def success(self): - return int(self.status) == 200 - - def parse_error(self): - if int(self.status) == 401: - if not self.body: - raise InvalidCredsError(str(self.status) + ': ' + self.error) - else: - raise InvalidCredsError(self.body) - return self.body - - -class IBMConnection(ConnectionUserAndKey): - """ - Connection class for the IBM SmartCloud Enterprise driver - """ - - host = HOST - responseCls = IBMResponse - - def add_default_headers(self, headers): - headers['Accept'] = 'text/xml' - headers['Authorization'] = ('Basic %s' % (base64.b64encode( - b('%s:%s' % (self.user_id, self.key))).decode('utf-8'))) - if 'Content-Type' not in headers: - headers['Content-Type'] = 'text/xml' - return headers - - def encode_data(self, data): - return urlencode(data) - - -class IBMNodeLocation(NodeLocation): - """ - Extends the base LibCloud NodeLocation to contain additional attributes - """ - def __init__(self, id, name, country, driver, extra=None): - self.id = str(id) - self.name = name - self.country = country - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return ('<IBMNodeLocation: id=%s, name=%s, country=%s, ' - 'driver=%s, extra=%s>' % - (self.id, self.name, self.country, self.driver.name, - self.extra)) - - -class VolumeState(object): - """ - The SCE specific states for a storage volume - """ - NEW = '0' - CREATING = '1' - DELETING = '2' - DELETED = '3' - DETACHED = '4' - ATTACHED = '5' - FAILED = '6' - DELETE_PENDING = '7' - BEING_CLONED = '8' - CLONING = '9' - ATTACHING = '10' - DETACHING = '11' - ATTACHIED = '12' - IMPORTING = '13' - TRANSFER_RETRYING = '14' - - -class VolumeOffering(object): - """ - An SCE specific storage volume offering class. - The volume offering ID is needed to create a volume. - Volume offering IDs are different for each data center. - """ - def __init__(self, id, name, location, extra=None): - self.id = id - self.location = location - self.name = name - self.extra = extra or {} - - def __repr__(self): - return ('<VolumeOffering: id=%s, location=%s, name=%s, extra=%s>' % - (self.id, self.location, self.name, self.extra)) - - -class Address(object): - """ - A reserved IP address that can be attached to an instance. - Properties: id, ip, state, options(location, type, created_time, state, - hostname, instance_ids, vlan, owner, - mode, offering_id) - """ - def __init__(self, id, ip, state, options): - self.id = id - self.ip = ip - self.state = state - self.options = options - - def __repr__(self): - return ('<Address: id=%s, ip=%s, state=%s, options=%s>' % - (self.id, self.ip, self.state, self.options)) - - -class IBMNodeDriver(NodeDriver): - """ - Node driver for IBM SmartCloud Enterprise - """ - connectionCls = IBMConnection - type = Provider.IBM - name = "IBM SmartCloud Enterprise" - website = 'http://ibm.com/services/us/en/cloud-enterprise/' - - NODE_STATE_MAP = { - 0: NodeState.PENDING, # New - 1: NodeState.PENDING, # Provisioning - 2: NodeState.TERMINATED, # Failed - 3: NodeState.TERMINATED, # Removed - 4: NodeState.TERMINATED, # Rejected - 5: NodeState.RUNNING, # Active - 6: NodeState.UNKNOWN, # Unknown - 7: NodeState.PENDING, # Deprovisioning - 8: NodeState.REBOOTING, # Restarting - 9: NodeState.PENDING, # Starting - 10: NodeState.PENDING, # Stopping - 11: NodeState.TERMINATED, # Stopped - 12: NodeState.PENDING, # Deprovision Pending - 13: NodeState.PENDING, # Restart Pending - 14: NodeState.PENDING, # Attaching - 15: NodeState.PENDING, # Detaching - } - - def create_node(self, **kwargs): - """ - Creates a node in the IBM SmartCloud Enterprise. - - See :class:`NodeDriver.create_node` for more keyword args. - - @inherits: :class:`NodeDriver.create_node` - - :keyword auth: Name of the pubkey to use. When constructing - :class:`NodeAuthSSHKey` instance, 'pubkey' argument must be the - name of the public key to use. You chose this name when creating - a new public key on the IBM server. - :type auth: :class:`NodeAuthSSHKey` - - :keyword ex_configurationData: Image-specific configuration - parameters. Configuration parameters are defined in the parameters - .xml file. The URL to this file is defined in the NodeImage at - extra[parametersURL]. - Note: This argument must be specified when launching a Windows - instance. It must contain 'UserName' and 'Password' keys. - :type ex_configurationData: ``dict`` - """ - - # Compose headers for message body - data = {} - data.update({'name': kwargs['name']}) - data.update({'imageID': kwargs['image'].id}) - data.update({'instanceType': kwargs['size'].id}) - if 'location' in kwargs: - data.update({'location': kwargs['location'].id}) - else: - data.update({'location': '1'}) - if 'auth' in kwargs and isinstance(kwargs['auth'], NodeAuthSSHKey): - data.update({'publicKey': kwargs['auth'].pubkey}) - if 'ex_configurationData' in kwargs: - configurationData = kwargs['ex_configurationData'] - if configurationData: - for key in configurationData.keys(): - data.update({key: configurationData.get(key)}) - - # Send request! - resp = self.connection.request( - action=REST_BASE + '/instances', - headers={'Content-Type': 'application/x-www-form-urlencoded'}, - method='POST', - data=data).object - return self._to_nodes(resp)[0] - - def create_volume(self, size, name, location, **kwargs): - """ - Create a new block storage volume (virtual disk) - - :param size: Size of volume in gigabytes (required). - Find out the possible sizes from the - offerings/storage REST interface - :type size: ``int`` - - :keyword name: Name of the volume to be created (required) - :type name: ``str`` - - :keyword location: Which data center to create a volume in. If - empty, it will fail for IBM SmartCloud Enterprise - (required) - :type location: :class:`NodeLocation` - - :keyword snapshot: Not supported for IBM SmartCloud Enterprise - :type snapshot: ``str`` - - :keyword kwargs.format: Either RAW or EXT3 for IBM SmartCloud - Enterprise (optional) - :type kwargs.format: ``str`` - - :keyword kwargs.offering_id: The storage offering ID for IBM - SmartCloud Enterprise - Find this from the REST interface - storage/offerings. (optional) - :type kwargs.offering_id: ``str`` - - :keyword kwargs.source_disk_id: If cloning a volume, the storage - disk to make a copy from (optional) - :type kwargs.source_disk_id: ``str`` - - :keyword kwargs.storage_area_id: The id of the storage availability - area to create the volume in - (optional) - :type kwargs.storage_area_id: ``str`` - - :keyword kwargs.target_location_id: If cloning a volume, the - storage disk to make a copy - from (optional) - :type kwargs.target_location_id: ``str`` - - :return: The newly created :class:`StorageVolume`. - :rtype: :class:`StorageVolume` - """ - data = {} - data.update({'name': name}) - data.update({'size': size}) - data.update({'location': location}) - if (('format' in kwargs) and (kwargs['format'] is not None)): - data.update({'format': kwargs['format']}) - if (('offering_id' in kwargs) and (kwargs['offering_id'] is not None)): - data.update({'offeringID': kwargs['offering_id']}) - if (('storage_area_id' in kwargs) and - (kwargs['storage_area_id'] is not None)): - data.update({'storageAreaID': kwargs['storage_area_id']}) - if 'source_disk_id' in kwargs: - data.update({'sourceDiskID': kwargs['source_disk_id']}) - data.update({'type': 'clone'}) - if 'target_location_id' in kwargs: - data.update({'targetLocationID': kwargs['target_location_id']}) - resp = self.connection.request( - action=REST_BASE + '/storage', - headers={'Content-Type': 'application/x-www-form-urlencoded'}, - method='POST', - data=data).object - return self._to_volumes(resp)[0] - - def create_image(self, name, description=None, **kwargs): - """ - Create a new node image from an existing volume or image. - - :param name: Name of the image to be created (required) - :type name: ``str`` - - :param description: Description of the image to be created - :type description: ``str`` - - :keyword image_id: The ID of the source image if cloning the image - :type image_id: ``str`` - - :keyword volume_id: The ID of the storage volume if - importing the image - :type volume_id: ``str`` - - :return: The newly created :class:`NodeImage`. - :rtype: :class:`NodeImage` - """ - data = {} - data.update({'name': name}) - if description is not None: - data.update({'description': description}) - if (('image_id' in kwargs) and (kwargs['image_id'] is not None)): - data.update({'imageId': kwargs['image_id']}) - if (('volume_id' in kwargs) and (kwargs['volume_id'] is not None)): - data.update({'volumeId': kwargs['volume_id']}) - resp = self.connection.request( - action=REST_BASE + '/offerings/image', - headers={'Content-Type': 'application/x-www-form-urlencoded'}, - method='POST', - data=data).object - return self._to_images(resp)[0] - - def destroy_node(self, node): - url = REST_BASE + '/instances/%s' % (node.id) - status = int(self.connection.request(action=url, - method='DELETE').status) - return status == httplib.OK - - def destroy_volume(self, volume): - """ - Destroys a storage volume. - - :param volume: Volume to be destroyed - :type volume: :class:`StorageVolume` - - :rtype: ``bool`` - """ - url = REST_BASE + '/storage/%s' % (volume.id) - status = int(self.connection.request(action=url, - method='DELETE').status) - return status == httplib.OK - - def ex_destroy_image(self, image): - """ - Destroys an image. - - :param image: Image to be destroyed - :type image: :class:`NodeImage` - - :return: ``bool`` - """ - - url = REST_BASE + '/offerings/image/%s' % (image.id) - status = int(self.connection.request(action=url, - method='DELETE').status) - return status == 200 - - def attach_volume(self, node, volume): - """ - Attaches volume to node. - - :param node: Node to attach volume to - :type node: :class:`Node` - - :param volume: Volume to attach - :type volume: :class:`StorageVolume` - - :rtype: ``bool`` - """ - url = REST_BASE + '/instances/%s' % (node.id) - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - data = {'storageID': volume.id, 'type': 'attach'} - resp = self.connection.request(action=url, - method='PUT', - headers=headers, - data=data) - return int(resp.status) == 200 - - def detach_volume(self, node, volume): - """ - Detaches a volume from a node. - - :param node: Node which should be used - :type node: :class:`Node` - - :param volume: Volume to be detached - :type volume: :class:`StorageVolume` - - :rtype: ``bool`` - """ - url = REST_BASE + '/instances/%s' % (node.id) - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - data = {'storageID': volume.id, 'type': 'detach'} - resp = self.connection.request(action=url, - method='PUT', - headers=headers, - data=data) - return int(resp.status) == 200 - - def reboot_node(self, node): - url = REST_BASE + '/instances/%s' % (node.id) - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - data = {'state': 'restart'} - - resp = self.connection.request(action=url, - method='PUT', - headers=headers, - data=data) - return int(resp.status) == 200 - - def list_nodes(self): - return self._to_nodes( - self.connection.request(REST_BASE + '/instances').object) - - def list_images(self, location=None): - return self._to_images( - self.connection.request(REST_BASE + '/offerings/image').object) - - def list_volumes(self): - """ - List storage volumes. - - :rtype: ``list`` of :class:`StorageVolume` - """ - return self._to_volumes( - self.connection.request(REST_BASE + '/storage').object) - - def list_sizes(self, location=None): - """ - Returns a generic list of sizes. See list_images() for a list of - supported sizes for specific images. In particular, you need to have - a size that matches the architecture (32-bit vs 64-bit) of the virtual - machine image operating system. - - @inherits: :class:`NodeDriver.list_sizes` - """ - return [ - NodeSize('BRZ32.1/2048/60*175', 'Bronze 32 bit', None, None, None, - None, self.connection.driver), - NodeSize('BRZ64.2/4096/60*500*350', 'Bronze 64 bit', None, None, - None, None, self.connection.driver), - NodeSize('COP32.1/2048/60', 'Copper 32 bit', None, None, None, - None, self.connection.driver), - NodeSize('COP64.2/4096/60', 'Copper 64 bit', None, None, None, - None, self.connection.driver), - NodeSize('SLV32.2/4096/60*350', 'Silver 32 bit', None, None, None, - None, self.connection.driver), - NodeSize('SLV64.4/8192/60*500*500', 'Silver 64 bit', None, None, - None, None, self.connection.driver), - NodeSize('GLD32.4/4096/60*350', 'Gold 32 bit', None, None, None, - None, self.connection.driver), - NodeSize('GLD64.8/16384/60*500*500', 'Gold 64 bit', None, None, - None, None, self.connection.driver), - NodeSize('PLT64.16/16384/60*500*500*500*500', 'Platinum 64 bit', - None, None, None, None, self.connection.driver)] - - def list_locations(self): - return self._to_locations( - self.connection.request(REST_BASE + '/locations').object) - - def ex_list_storage_offerings(self): - """ - List the storage center offerings - - :rtype: ``list`` of :class:`VolumeOffering` - """ - return self._to_volume_offerings( - self.connection.request(REST_BASE + '/offerings/storage').object) - - def ex_allocate_address(self, location_id, offering_id, vlan_id=None): - """ - Allocate a new reserved IP address - - :param location_id: Target data center - :type location_id: ``str`` - - :param offering_id: Offering ID for address to create - :type offering_id: ``str`` - - :param vlan_id: ID of target VLAN - :type vlan_id: ``str`` - - :return: :class:`Address` object - :rtype: :class:`Address` - """ - url = REST_BASE + '/addresses' - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - data = {'location': location_id, 'offeringID': offering_id} - if vlan_id is not None: - data.update({'vlanID': vlan_id}) - resp = self.connection.request(action=url, - method='POST', - headers=headers, - data=data).object - return self._to_addresses(resp)[0] - - def ex_list_addresses(self, resource_id=None): - """ - List the reserved IP addresses - - :param resource_id: If this is supplied only a single address will - be returned (optional) - :type resource_id: ``str`` - - :rtype: ``list`` of :class:`Address` - """ - url = REST_BASE + '/addresses' - if resource_id: - url += '/' + resource_id - return self._to_addresses(self.connection.request(url).object) - - def ex_copy_to(self, image, volume): - """ - Copies a node image to a storage volume - - :param image: source image to copy - :type image: :class:`NodeImage` - - :param volume: Target storage volume to copy to - :type volume: :class:`StorageVolume` - - :return: ``bool`` The success of the operation - :rtype: ``bool`` - """ - url = REST_BASE + '/storage/%s' % (volume.id) - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - data = {'imageId': image.id} - resp = self.connection.request(action=url, - method='PUT', - headers=headers, - data=data) - return int(resp.status) == 200 - - def ex_delete_address(self, resource_id): - """ - Delete a reserved IP address - - :param resource_id: The address to delete (required) - :type resource_id: ``str`` - - :rtype: ``bool`` - """ - url = REST_BASE + '/addresses/' + resource_id - status = int(self.connection.request(action=url, - method='DELETE').status) - return status == 200 - - def ex_wait_storage_state(self, volume, state=VolumeState.DETACHED, - wait_period=60, timeout=1200): - """ - Block until storage volume state changes to the given value - - :param volume: Storage volume. - :type volume: :class:`StorageVolume` - - :param state: The target state to wait for - :type state: ``int`` - - :param wait_period: How many seconds to between each loop - iteration (default is 3) - :type wait_period: ``int`` - - :param timeout: How many seconds to wait before timing out - (default is 1200) - :type timeout: ``int`` - - :rtype: :class:`StorageVolume` - """ - start = time.time() - end = start + timeout - - while time.time() < end: - volumes = self.list_volumes() - volumes = list([v for v in volumes if v.uuid == volume.uuid]) - - if (len(volumes) == 1 and volumes[0].extra['state'] == state): - return volumes[0] - else: - time.sleep(wait_period) - continue - - raise LibcloudError(value='Timed out after %d seconds' % (timeout), - driver=self) - - def _to_nodes(self, object): - return [self._to_node(instance) for instance in - object.findall('Instance')] - - def _to_node(self, instance): - public_ips = [] - - ip = instance.findtext('IP') - if ip: - public_ips.append(ip) - - return Node( - id=instance.findtext('ID'), - name=instance.findtext('Name'), - state=self.NODE_STATE_MAP[int(instance.findtext('Status'))], - public_ips=public_ips, - private_ips=[], - driver=self.connection.driver - ) - - def _to_images(self, object): - # Converts data retrieved from SCE /offerings/image REST call to - # a NodeImage - return [self._to_image(image) for image in object.findall('Image')] - - def _to_image(self, image): - # Converts an SCE Image object to a NodeImage - imageID = image.findtext('ID') - imageName = image.findtext('Name') - parametersURL = image.findtext('Manifest') - location = image.findtext('Location') - state = image.findtext('State') - owner = image.findtext('Owner') - visibility = image.findtext('Visibility') - platform = image.findtext('Platform') - description = image.findtext('Description') - documentation = image.findtext('Documentation') - instanceTypes = image.findall('SupportedInstanceTypes') - nodeSizes = self._to_node_sizes(image.find('SupportedInstanceTypes')) - return NodeImage(id=imageID, - name=imageName, - driver=self.connection.driver, - extra={ - 'parametersURL': parametersURL, - 'location': location, - 'state': state, - 'owner': owner, - 'visibility': visibility, - 'platform': platform, - 'description': description, - 'documentation': documentation, - 'instanceTypes': instanceTypes, - 'node_sizes': nodeSizes - } - ) - - def _to_locations(self, object): - return [self._to_location(location) for location in - object.findall('Location')] - - def _to_location(self, location): - # Converts an SCE Location object to a Libcloud NodeLocation object - name_text = location.findtext('Name') - description = location.findtext('Description') - state = location.findtext('State') - (nameVal, separator, countryVal) = name_text.partition(',') - capabiltyElements = location.findall('Capabilities/Capability') - capabilities = {} - for elem in capabiltyElements: - capabilityID = elem.attrib['id'] - entryElements = elem.findall('Entry') - entries = [] - for entryElem in entryElements: - key = entryElem.attrib['key'] - valueElements = elem.findall('Value') - values = [] - for valueElem in valueElements: - values.append(valueElem.text) - entry = {'key': key, 'values': values} - entries.append(entry) - capabilities[capabilityID] = entries - extra = {'description': description, 'state': state, - 'capabilities': capabilities} - return IBMNodeLocation(id=location.findtext('ID'), - name=nameVal, - country=countryVal.strip(), - driver=self.connection.driver, - extra=extra) - - def _to_node_sizes(self, object): - # Converts SCE SupportedInstanceTypes object to - # a list of Libcloud NodeSize objects - return [self._to_node_size(iType) for iType in - object.findall('InstanceType')] - - def _to_node_size(self, object): - # Converts to an SCE InstanceType to a Libcloud NodeSize - return NodeSize(object.findtext('ID'), - object.findtext('Label'), - None, - None, - None, - object.findtext('Price/Rate'), - self.connection.driver) - - def _to_volumes(self, object): - return [self._to_volume(iType) for iType in - object.findall('Volume')] - - def _to_volume(self, object): - # Converts an SCE Volume to a Libcloud StorageVolume - extra = {'state': object.findtext('State'), - 'location': object.findtext('Location'), - 'instanceID': object.findtext('instanceID'), - 'owner': object.findtext('Owner'), - 'format': object.findtext('Format'), - 'createdTime': object.findtext('CreatedTime'), - 'storageAreaID': object.findtext('StorageArea/ID')} - return StorageVolume(object.findtext('ID'), - object.findtext('Name'), - object.findtext('Size'), - self.connection.driver, - extra) - - def _to_volume_offerings(self, object): - return [self._to_volume_offering(iType) for iType in - object.findall('Offerings')] - - def _to_volume_offering(self, object): - # Converts an SCE DescribeVolumeOfferingsResponse/Offerings XML object - # to an SCE VolumeOffering - extra = {'label': object.findtext('Label'), - 'supported_sizes': object.findtext('SupportedSizes'), - 'formats': object.findall('SupportedFormats/Format/ID'), - 'price': object.findall('Price')} - return VolumeOffering(object.findtext('ID'), - object.findtext('Name'), - object.findtext('Location'), - extra) - - def _to_addresses(self, object): - # Converts an SCE DescribeAddressesResponse XML object to a list of - # Address objects - return [self._to_address(iType) for iType in - object.findall('Address')] - - def _to_address(self, object): - # Converts an SCE DescribeAddressesResponse/Address XML object to - # an Address object - extra = {'location': object.findtext('Location'), - 'type': object.findtext('Label'), - 'created_time': object.findtext('SupportedSizes'), - 'hostname': object.findtext('Hostname'), - 'instance_ids': object.findtext('InstanceID'), - 'vlan': object.findtext('VLAN'), - 'owner': object.findtext('owner'), - 'mode': object.findtext('Mode'), - 'offering_id': object.findtext('OfferingID')} - return Address(object.findtext('ID'), - object.findtext('IP'), - object.findtext('State'), - extra) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/ikoula.py b/awx/lib/site-packages/libcloud/compute/drivers/ikoula.py deleted file mode 100644 index 554c647b95..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/ikoula.py +++ /dev/null @@ -1,31 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.compute.providers import Provider -from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver - -__all__ = [ - 'IkoulaNodeDriver' -] - - -class IkoulaNodeDriver(CloudStackNodeDriver): - type = Provider.IKOULA - name = 'Ikoula' - website = 'http://express.ikoula.co.uk/cloudstack' - - # API endpoint info - host = 'cloudstack.ikoula.com' - path = '/client/api' diff --git a/awx/lib/site-packages/libcloud/compute/drivers/joyent.py b/awx/lib/site-packages/libcloud/compute/drivers/joyent.py deleted file mode 100644 index 6d8142e8f8..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/joyent.py +++ /dev/null @@ -1,222 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Joyent Cloud (http://www.joyentcloud.com) driver. -""" - -import base64 - -try: - import simplejson as json -except: - import json - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -from libcloud.common.types import LibcloudError -from libcloud.compute.providers import Provider -from libcloud.common.base import JsonResponse, ConnectionUserAndKey -from libcloud.compute.types import NodeState, InvalidCredsError -from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeSize -from libcloud.utils.networking import is_private_subnet - -API_HOST_SUFFIX = '.api.joyentcloud.com' -API_VERSION = '~6.5' - - -NODE_STATE_MAP = { - 'provisioning': NodeState.PENDING, - 'running': NodeState.RUNNING, - 'stopping': NodeState.TERMINATED, - 'stopped': NodeState.TERMINATED, - 'deleted': NodeState.TERMINATED -} - -VALID_REGIONS = ['us-east-1', 'us-west-1', 'us-sw-1', 'eu-ams-1'] -DEFAULT_REGION = 'us-east-1' - - -class JoyentResponse(JsonResponse): - """ - Joyent response class. - """ - - valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, - httplib.NO_CONTENT] - - def parse_error(self): - if self.status == httplib.UNAUTHORIZED: - data = self.parse_body() - raise InvalidCredsError(data['code'] + ': ' + data['message']) - return self.body - - def success(self): - return self.status in self.valid_response_codes - - -class JoyentConnection(ConnectionUserAndKey): - """ - Joyent connection class. - """ - - responseCls = JoyentResponse - - allow_insecure = False - - def add_default_headers(self, headers): - headers['Accept'] = 'application/json' - headers['Content-Type'] = 'application/json; charset=UTF-8' - headers['X-Api-Version'] = API_VERSION - - user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) - headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) - return headers - - -class JoyentNodeDriver(NodeDriver): - """ - Joyent node driver class. - """ - - type = Provider.JOYENT - name = 'Joyent' - website = 'http://www.joyentcloud.com' - connectionCls = JoyentConnection - features = {'create_node': ['generates_password']} - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region=DEFAULT_REGION, **kwargs): - # Location is here for backward compatibility reasons - if 'location' in kwargs: - region = kwargs['location'] - - if region not in VALID_REGIONS: - msg = 'Invalid region: "%s". Valid region: %s' - raise LibcloudError(msg % (region, - ', '.join(VALID_REGIONS)), driver=self) - - super(JoyentNodeDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, region=region, - **kwargs) - self.connection.host = region + API_HOST_SUFFIX - - def list_images(self): - result = self.connection.request('/my/datasets').object - - images = [] - for value in result: - extra = {'type': value['type'], 'urn': value['urn'], - 'os': value['os'], 'default': value['default']} - image = NodeImage(id=value['id'], name=value['name'], - driver=self.connection.driver, extra=extra) - images.append(image) - - return images - - def list_sizes(self): - result = self.connection.request('/my/packages').object - - sizes = [] - for value in result: - size = NodeSize(id=value['name'], name=value['name'], - ram=value['memory'], disk=value['disk'], - bandwidth=None, price=0.0, - driver=self.connection.driver) - sizes.append(size) - - return sizes - - def list_nodes(self): - result = self.connection.request('/my/machines').object - - nodes = [] - for value in result: - node = self._to_node(value) - nodes.append(node) - - return nodes - - def reboot_node(self, node): - data = json.dumps({'action': 'reboot'}) - result = self.connection.request('/my/machines/%s' % (node.id), - data=data, method='POST') - return result.status == httplib.ACCEPTED - - def destroy_node(self, node): - result = self.connection.request('/my/machines/%s' % (node.id), - method='DELETE') - return result.status == httplib.NO_CONTENT - - def create_node(self, **kwargs): - name = kwargs['name'] - size = kwargs['size'] - image = kwargs['image'] - - data = json.dumps({'name': name, 'package': size.id, - 'dataset': image.id}) - result = self.connection.request('/my/machines', data=data, - method='POST') - return self._to_node(result.object) - - def ex_stop_node(self, node): - """ - Stop node - - :param node: The node to be stopped - :type node: :class:`Node` - - :rtype: ``bool`` - """ - data = json.dumps({'action': 'stop'}) - result = self.connection.request('/my/machines/%s' % (node.id), - data=data, method='POST') - return result.status == httplib.ACCEPTED - - def ex_start_node(self, node): - """ - Start node - - :param node: The node to be stopped - :type node: :class:`Node` - - :rtype: ``bool`` - """ - data = json.dumps({'action': 'start'}) - result = self.connection.request('/my/machines/%s' % (node.id), - data=data, method='POST') - return result.status == httplib.ACCEPTED - - def _to_node(self, data): - state = NODE_STATE_MAP[data['state']] - public_ips = [] - private_ips = [] - extra = {} - - for ip in data['ips']: - if is_private_subnet(ip): - private_ips.append(ip) - else: - public_ips.append(ip) - - if 'credentials' in data['metadata']: - extra['password'] = data['metadata']['credentials']['root'] - - node = Node(id=data['id'], name=data['name'], state=state, - public_ips=public_ips, private_ips=private_ips, - driver=self.connection.driver, extra=extra) - return node diff --git a/awx/lib/site-packages/libcloud/compute/drivers/kili.py b/awx/lib/site-packages/libcloud/compute/drivers/kili.py deleted file mode 100644 index de610676e6..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/kili.py +++ /dev/null @@ -1,87 +0,0 @@ -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -HP Public cloud driver which is esentially just a small wrapper around -OpenStack driver. -""" - -from libcloud.compute.types import Provider, LibcloudError -from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection -from libcloud.compute.drivers.openstack import OpenStack_1_1_NodeDriver - -__all__ = [ - 'KiliCloudNodeDriver' -] - -ENDPOINT_ARGS = { - 'service_type': 'compute', - 'name': 'nova', - 'region': 'RegionOne' -} - -AUTH_URL = 'https://api.kili.io/keystone/v2.0/tokens' - - -class KiliCloudConnection(OpenStack_1_1_Connection): - _auth_version = '2.0_password' - - def __init__(self, *args, **kwargs): - self.region = kwargs.pop('region', None) - self.get_endpoint_args = kwargs.pop('get_endpoint_args', None) - super(KiliCloudConnection, self).__init__(*args, **kwargs) - - def get_endpoint(self): - if not self.get_endpoint_args: - raise LibcloudError( - 'KiliCloudConnection must have get_endpoint_args set') - - if '2.0_password' in self._auth_version: - ep = self.service_catalog.get_endpoint(**self.get_endpoint_args) - else: - raise LibcloudError( - 'Auth version "%s" not supported' % (self._auth_version)) - - public_url = ep.get('publicURL', None) - - if not public_url: - raise LibcloudError('Could not find specified endpoint') - - return public_url - - -class KiliCloudNodeDriver(OpenStack_1_1_NodeDriver): - name = 'Kili Public Cloud' - website = 'http://kili.io/' - connectionCls = KiliCloudConnection - type = Provider.HPCLOUD - - def __init__(self, key, secret, tenant_name, secure=True, - host=None, port=None, **kwargs): - """ - Note: tenant_name argument is required for Kili cloud. - """ - self.tenant_name = tenant_name - super(KiliCloudNodeDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, - **kwargs) - - def _ex_connection_class_kwargs(self): - kwargs = self.openstack_connection_kwargs() - kwargs['get_endpoint_args'] = ENDPOINT_ARGS - kwargs['ex_force_auth_url'] = AUTH_URL - kwargs['ex_tenant_name'] = self.tenant_name - - return kwargs diff --git a/awx/lib/site-packages/libcloud/compute/drivers/ktucloud.py b/awx/lib/site-packages/libcloud/compute/drivers/ktucloud.py deleted file mode 100644 index 1bc8544563..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/ktucloud.py +++ /dev/null @@ -1,103 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.compute.providers import Provider -from libcloud.compute.base import Node, NodeImage, NodeSize -from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver - - -class KTUCloudNodeDriver(CloudStackNodeDriver): - "Driver for KTUCloud Compute platform." - - EMPTY_DISKOFFERINGID = '0' - type = Provider.KTUCLOUD - name = 'KTUCloud' - website = 'https://ucloudbiz.olleh.com/' - - def list_images(self, location=None): - args = { - 'templatefilter': 'executable' - } - if location is not None: - args['zoneid'] = location.id - - imgs = self._sync_request(command='listAvailableProductTypes', - method='GET') - images = [] - - for img in imgs['producttypes']: - images.append( - NodeImage( - img['serviceofferingid'], - img['serviceofferingdesc'], - self, - {'hypervisor': '', - 'format': '', - 'os': img['templatedesc'], - 'templateid': img['templateid'], - 'zoneid': img['zoneid']} - ) - ) - - return images - - def list_sizes(self, location=None): - szs = self._sync_request('listAvailableProductTypes') - sizes = [] - for sz in szs['producttypes']: - diskofferingid = sz.get('diskofferingid', - self.EMPTY_DISKOFFERINGID) - sizes.append(NodeSize( - diskofferingid, - sz['diskofferingdesc'], - 0, 0, 0, 0, self) - ) - return sizes - - def create_node(self, name, size, image, location=None, **kwargs): - params = {'displayname': name, - 'serviceofferingid': image.id, - 'templateid': str(image.extra['templateid']), - 'zoneid': str(image.extra['zoneid'])} - - usageplantype = kwargs.pop('usageplantype', None) - if usageplantype is None: - params['usageplantype'] = 'hourly' - else: - params['usageplantype'] = usageplantype - - if size.id != self.EMPTY_DISKOFFERINGID: - params['diskofferingid'] = size.id - - result = self._async_request( - command='deployVirtualMachine', - params=params, - method='GET') - - node = result['virtualmachine'] - - return Node( - id=node['id'], - name=node['displayname'], - state=self.NODE_STATE_MAP[node['state']], - public_ips=[], - private_ips=[], - driver=self, - extra={ - 'zoneid': image.extra['zoneid'], - 'ip_addresses': [], - 'forwarding_rules': [], - } - ) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/libvirt_driver.py b/awx/lib/site-packages/libcloud/compute/drivers/libvirt_driver.py deleted file mode 100644 index 3618ac4368..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/libvirt_driver.py +++ /dev/null @@ -1,335 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import with_statement - -import re -import os -import time -import platform -import subprocess -import mimetypes - -from os.path import join as pjoin -from collections import defaultdict - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.compute.base import NodeDriver, Node -from libcloud.compute.base import NodeState -from libcloud.compute.types import Provider -from libcloud.utils.networking import is_public_subnet - -try: - import libvirt - have_libvirt = True -except ImportError: - have_libvirt = False - - -class LibvirtNodeDriver(NodeDriver): - """ - Libvirt (http://libvirt.org/) node driver. - - To enable debug mode, set LIBVIR_DEBUG environment variable. - """ - - type = Provider.LIBVIRT - name = 'Libvirt' - website = 'http://libvirt.org/' - - NODE_STATE_MAP = { - 0: NodeState.TERMINATED, # no state - 1: NodeState.RUNNING, # domain is running - 2: NodeState.PENDING, # domain is blocked on resource - 3: NodeState.TERMINATED, # domain is paused by user - 4: NodeState.TERMINATED, # domain is being shut down - 5: NodeState.TERMINATED, # domain is shut off - 6: NodeState.UNKNOWN, # domain is crashed - 7: NodeState.UNKNOWN, # domain is suspended by guest power management - } - - def __init__(self, uri): - """ - :param uri: Hypervisor URI (e.g. vbox:///session, qemu:///system, - etc.). - :type uri: ``str`` - """ - if not have_libvirt: - raise RuntimeError('Libvirt driver requires \'libvirt\' Python ' + - 'package') - - self._uri = uri - self.connection = libvirt.open(uri) - - def list_nodes(self): - domains = self.connection.listAllDomains() - nodes = self._to_nodes(domains=domains) - return nodes - - def reboot_node(self, node): - domain = self._get_domain_for_node(node=node) - return domain.reboot(flags=0) == 0 - - def destroy_node(self, node): - domain = self._get_domain_for_node(node=node) - return domain.destroy() == 0 - - def ex_start_node(self, node): - """ - Start a stopped node. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - domain = self._get_domain_for_node(node=node) - return domain.create() == 0 - - def ex_shutdown_node(self, node): - """ - Shutdown a running node. - - Note: Usually this will result in sending an ACPI event to the node. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - domain = self._get_domain_for_node(node=node) - return domain.shutdown() == 0 - - def ex_suspend_node(self, node): - """ - Suspend a running node. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - domain = self._get_domain_for_node(node=node) - return domain.suspend() == 0 - - def ex_resume_node(self, node): - """ - Resume a suspended node. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - domain = self._get_domain_for_node(node=node) - return domain.resume() == 0 - - def ex_take_node_screenshot(self, node, directory, screen=0): - """ - Take a screenshot of a monitoring of a running instance. - - :param node: Node to take the screenshot of. - :type node: :class:`libcloud.compute.base.Node` - - :param directory: Path where the screenshot will be saved. - :type directory: ``str`` - - :param screen: ID of the monitor to take the screenshot of. - :type screen: ``int`` - - :return: Full path where the screenshot has been saved. - :rtype: ``str`` - """ - if not os.path.exists(directory) or not os.path.isdir(directory): - raise ValueError('Invalid value for directory argument') - - domain = self._get_domain_for_node(node=node) - stream = self.connection.newStream() - mime_type = domain.screenshot(stream=stream, screen=0) - extensions = mimetypes.guess_all_extensions(type=mime_type) - - if extensions: - extension = extensions[0] - else: - extension = '.png' - - name = 'screenshot-%s%s' % (int(time.time()), extension) - file_path = pjoin(directory, name) - - with open(file_path, 'wb') as fp: - def write(stream, buf, opaque): - fp.write(buf) - - stream.recvAll(write, None) - - try: - stream.finish() - except Exception: - # Finish is not supported by all backends - pass - - return file_path - - def ex_get_hypervisor_hostname(self): - """ - Return a system hostname on which the hypervisor is running. - """ - hostname = self.connection.getHostname() - return hostname - - def ex_get_hypervisor_sysinfo(self): - """ - Retrieve hypervisor system information. - - :rtype: ``dict`` - """ - xml = self.connection.getSysinfo() - etree = ET.XML(xml) - - attributes = ['bios', 'system', 'processor', 'memory_device'] - - sysinfo = {} - for attribute in attributes: - element = etree.find(attribute) - entries = self._get_entries(element=element) - sysinfo[attribute] = entries - - return sysinfo - - def _to_nodes(self, domains): - nodes = [self._to_node(domain=domain) for domain in domains] - return nodes - - def _to_node(self, domain): - state, max_mem, memory, vcpu_count, used_cpu_time = domain.info() - state = self.NODE_STATE_MAP.get(state, NodeState.UNKNOWN) - - public_ips, private_ips = [], [] - - ip_addresses = self._get_ip_addresses_for_domain(domain) - - for ip_address in ip_addresses: - if is_public_subnet(ip_address): - public_ips.append(ip_address) - else: - private_ips.append(ip_address) - - extra = {'uuid': domain.UUIDString(), 'os_type': domain.OSType(), - 'types': self.connection.getType(), - 'used_memory': memory / 1024, 'vcpu_count': vcpu_count, - 'used_cpu_time': used_cpu_time} - - node = Node(id=domain.ID(), name=domain.name(), state=state, - public_ips=public_ips, private_ips=private_ips, - driver=self, extra=extra) - node._uuid = domain.UUIDString() # we want to use a custom UUID - return node - - def _get_ip_addresses_for_domain(self, domain): - """ - Retrieve IP addresses for the provided domain. - - Note: This functionality is currently only supported on Linux and - only works if this code is run on the same machine as the VMs run - on. - - :return: IP addresses for the provided domain. - :rtype: ``list`` - """ - result = [] - - if platform.system() != 'Linux': - # Only Linux is supported atm - return result - - mac_addresses = self._get_mac_addresses_for_domain(domain=domain) - - cmd = ['arp', '-an'] - child = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, _ = child.communicate() - arp_table = self._parse_arp_table(arp_output=stdout) - - for mac_address in mac_addresses: - if mac_address in arp_table: - ip_addresses = arp_table[mac_address] - result.extend(ip_addresses) - - return result - - def _get_mac_addresses_for_domain(self, domain): - """ - Parses network interface MAC addresses from the provided domain. - """ - xml = domain.XMLDesc() - etree = ET.XML(xml) - elems = etree.findall("devices/interface[@type='network']/mac") - - result = [] - for elem in elems: - mac_address = elem.get('address') - result.append(mac_address) - - return result - - def _get_domain_for_node(self, node): - """ - Return libvirt domain object for the provided node. - """ - domain = self.connection.lookupByUUIDString(node.uuid) - return domain - - def _get_entries(self, element): - """ - Parse entries dictionary. - - :rtype: ``dict`` - """ - elements = element.findall('entry') - - result = {} - for element in elements: - name = element.get('name') - value = element.text - result[name] = value - - return result - - def _parse_arp_table(self, arp_output): - """ - Parse arp command output and return a dictionary which maps mac address - to an IP address. - - :return: Dictionary which maps mac address to IP address. - :rtype: ``dict`` - """ - lines = arp_output.split('\n') - - arp_table = defaultdict(list) - for line in lines: - match = re.match('.*?\((.*?)\) at (.*?)\s+', line) - - if not match: - continue - - groups = match.groups() - ip_address = groups[0] - mac_address = groups[1] - arp_table[mac_address].append(ip_address) - - return arp_table diff --git a/awx/lib/site-packages/libcloud/compute/drivers/linode.py b/awx/lib/site-packages/libcloud/compute/drivers/linode.py deleted file mode 100644 index 4960f29472..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/linode.py +++ /dev/null @@ -1,548 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""libcloud driver for the Linode(R) API - -This driver implements all libcloud functionality for the Linode API. -Since the API is a bit more fine-grained, create_node abstracts a significant -amount of work (and may take a while to run). - -Linode home page http://www.linode.com/ -Linode API documentation http://www.linode.com/api/ -Alternate bindings for reference http://github.com/tjfontaine/linode-python - -Linode(R) is a registered trademark of Linode, LLC. - -""" - -import os - -try: - import simplejson as json -except ImportError: - import json - -import itertools -import binascii - -from copy import copy - -from libcloud.utils.py3 import PY3 - -from libcloud.common.linode import (API_ROOT, LinodeException, - LinodeConnection, LINODE_PLAN_IDS) -from libcloud.compute.types import Provider, NodeState -from libcloud.compute.base import NodeDriver, NodeSize, Node, NodeLocation -from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey -from libcloud.compute.base import NodeImage - - -class LinodeNodeDriver(NodeDriver): - """libcloud driver for the Linode API - - Rough mapping of which is which: - - list_nodes linode.list - reboot_node linode.reboot - destroy_node linode.delete - create_node linode.create, linode.update, - linode.disk.createfromdistribution, - linode.disk.create, linode.config.create, - linode.ip.addprivate, linode.boot - list_sizes avail.linodeplans - list_images avail.distributions - list_locations avail.datacenters - - For more information on the Linode API, be sure to read the reference: - - http://www.linode.com/api/ - """ - type = Provider.LINODE - name = "Linode" - website = 'http://www.linode.com/' - connectionCls = LinodeConnection - _linode_plan_ids = LINODE_PLAN_IDS - features = {'create_node': ['ssh_key', 'password']} - - def __init__(self, key): - """Instantiate the driver with the given API key - - :param key: the API key to use (required) - :type key: ``str`` - - :rtype: ``None`` - """ - self.datacenter = None - NodeDriver.__init__(self, key) - - # Converts Linode's state from DB to a NodeState constant. - LINODE_STATES = { - (-2): NodeState.UNKNOWN, # Boot Failed - (-1): NodeState.PENDING, # Being Created - 0: NodeState.PENDING, # Brand New - 1: NodeState.RUNNING, # Running - 2: NodeState.TERMINATED, # Powered Off - 3: NodeState.REBOOTING, # Shutting Down - 4: NodeState.UNKNOWN # Reserved - } - - def list_nodes(self): - """ - List all Linodes that the API key can access - - This call will return all Linodes that the API key in use has access - to. - If a node is in this list, rebooting will work; however, creation and - destruction are a separate grant. - - :return: List of node objects that the API key can access - :rtype: ``list`` of :class:`Node` - """ - params = {"api_action": "linode.list"} - data = self.connection.request(API_ROOT, params=params).objects[0] - return self._to_nodes(data) - - def reboot_node(self, node): - """ - Reboot the given Linode - - Will issue a shutdown job followed by a boot job, using the last booted - configuration. In most cases, this will be the only configuration. - - :param node: the Linode to reboot - :type node: :class:`Node` - - :rtype: ``bool`` - """ - params = {"api_action": "linode.reboot", "LinodeID": node.id} - self.connection.request(API_ROOT, params=params) - return True - - def destroy_node(self, node): - """Destroy the given Linode - - Will remove the Linode from the account and issue a prorated credit. A - grant for removing Linodes from the account is required, otherwise this - method will fail. - - In most cases, all disk images must be removed from a Linode before the - Linode can be removed; however, this call explicitly skips those - safeguards. There is no going back from this method. - - :param node: the Linode to destroy - :type node: :class:`Node` - - :rtype: ``bool`` - """ - params = {"api_action": "linode.delete", "LinodeID": node.id, - "skipChecks": True} - self.connection.request(API_ROOT, params=params) - return True - - def create_node(self, **kwargs): - """Create a new Linode, deploy a Linux distribution, and boot - - This call abstracts much of the functionality of provisioning a Linode - and getting it booted. A global grant to add Linodes to the account is - required, as this call will result in a billing charge. - - Note that there is a safety valve of 5 Linodes per hour, in order to - prevent a runaway script from ruining your day. - - :keyword name: the name to assign the Linode (mandatory) - :type name: ``str`` - - :keyword image: which distribution to deploy on the Linode (mandatory) - :type image: :class:`NodeImage` - - :keyword size: the plan size to create (mandatory) - :type size: :class:`NodeSize` - - :keyword auth: an SSH key or root password (mandatory) - :type auth: :class:`NodeAuthSSHKey` or :class:`NodeAuthPassword` - - :keyword location: which datacenter to create the Linode in - :type location: :class:`NodeLocation` - - :keyword ex_swap: size of the swap partition in MB (128) - :type ex_swap: ``int`` - - :keyword ex_rsize: size of the root partition in MB (plan size - swap). - :type ex_rsize: ``int`` - - :keyword ex_kernel: a kernel ID from avail.kernels (Latest 2.6 Stable). - :type ex_kernel: ``str`` - - :keyword ex_payment: one of 1, 12, or 24; subscription length (1) - :type ex_payment: ``int`` - - :keyword ex_comment: a small comment for the configuration (libcloud) - :type ex_comment: ``str`` - - :keyword ex_private: whether or not to request a private IP (False) - :type ex_private: ``bool`` - - :keyword lconfig: what to call the configuration (generated) - :type lconfig: ``str`` - - :keyword lroot: what to call the root image (generated) - :type lroot: ``str`` - - :keyword lswap: what to call the swap space (generated) - :type lswap: ``str`` - - :return: Node representing the newly-created Linode - :rtype: :class:`Node` - """ - name = kwargs["name"] - image = kwargs["image"] - size = kwargs["size"] - auth = self._get_and_check_auth(kwargs["auth"]) - - # Pick a location (resolves LIBCLOUD-41 in JIRA) - if "location" in kwargs: - chosen = kwargs["location"].id - elif self.datacenter: - chosen = self.datacenter - else: - raise LinodeException(0xFB, "Need to select a datacenter first") - - # Step 0: Parameter validation before we purchase - # We're especially careful here so we don't fail after purchase, rather - # than getting halfway through the process and having the API fail. - - # Plan ID - plans = self.list_sizes() - if size.id not in [p.id for p in plans]: - raise LinodeException(0xFB, "Invalid plan ID -- avail.plans") - - # Payment schedule - payment = "1" if "ex_payment" not in kwargs else \ - str(kwargs["ex_payment"]) - if payment not in ["1", "12", "24"]: - raise LinodeException(0xFB, "Invalid subscription (1, 12, 24)") - - ssh = None - root = None - # SSH key and/or root password - if isinstance(auth, NodeAuthSSHKey): - ssh = auth.pubkey - elif isinstance(auth, NodeAuthPassword): - root = auth.password - - if not ssh and not root: - raise LinodeException(0xFB, "Need SSH key or root password") - if root is not None and len(root) < 6: - raise LinodeException(0xFB, "Root password is too short") - - # Swap size - try: - swap = 128 if "ex_swap" not in kwargs else int(kwargs["ex_swap"]) - except: - raise LinodeException(0xFB, "Need an integer swap size") - - # Root partition size - imagesize = (size.disk - swap) if "ex_rsize" not in kwargs else\ - int(kwargs["ex_rsize"]) - if (imagesize + swap) > size.disk: - raise LinodeException(0xFB, "Total disk images are too big") - - # Distribution ID - distros = self.list_images() - if image.id not in [d.id for d in distros]: - raise LinodeException(0xFB, - "Invalid distro -- avail.distributions") - - # Kernel - if "ex_kernel" in kwargs: - kernel = kwargs["ex_kernel"] - else: - if image.extra['64bit']: - # For a list of available kernel ids, see - # https://www.linode.com/kernels/ - kernel = 138 - else: - kernel = 137 - params = {"api_action": "avail.kernels"} - kernels = self.connection.request(API_ROOT, params=params).objects[0] - if kernel not in [z["KERNELID"] for z in kernels]: - raise LinodeException(0xFB, "Invalid kernel -- avail.kernels") - - # Comments - comments = "Created by Apache libcloud <http://www.libcloud.org>" if\ - "ex_comment" not in kwargs else kwargs["ex_comment"] - - # Step 1: linode.create - params = { - "api_action": "linode.create", - "DatacenterID": chosen, - "PlanID": size.id, - "PaymentTerm": payment - } - data = self.connection.request(API_ROOT, params=params).objects[0] - linode = {"id": data["LinodeID"]} - - # Step 1b. linode.update to rename the Linode - params = { - "api_action": "linode.update", - "LinodeID": linode["id"], - "Label": name - } - self.connection.request(API_ROOT, params=params) - - # Step 1c. linode.ip.addprivate if it was requested - if "ex_private" in kwargs and kwargs["ex_private"]: - params = { - "api_action": "linode.ip.addprivate", - "LinodeID": linode["id"] - } - self.connection.request(API_ROOT, params=params) - - # Step 1d. Labels - # use the linode id as the name can be up to 63 chars and the labels - # are limited to 48 chars - label = { - "lconfig": "[%s] Configuration Profile" % linode["id"], - "lroot": "[%s] %s Disk Image" % (linode["id"], image.name), - "lswap": "[%s] Swap Space" % linode["id"] - } - for what in ["lconfig", "lroot", "lswap"]: - if what in kwargs: - label[what] = kwargs[what] - - # Step 2: linode.disk.createfromdistribution - if not root: - root = binascii.b2a_base64(os.urandom(8)).decode('ascii').strip() - - params = { - "api_action": "linode.disk.createfromdistribution", - "LinodeID": linode["id"], - "DistributionID": image.id, - "Label": label["lroot"], - "Size": imagesize, - "rootPass": root, - } - if ssh: - params["rootSSHKey"] = ssh - data = self.connection.request(API_ROOT, params=params).objects[0] - linode["rootimage"] = data["DiskID"] - - # Step 3: linode.disk.create for swap - params = { - "api_action": "linode.disk.create", - "LinodeID": linode["id"], - "Label": label["lswap"], - "Type": "swap", - "Size": swap - } - data = self.connection.request(API_ROOT, params=params).objects[0] - linode["swapimage"] = data["DiskID"] - - # Step 4: linode.config.create for main profile - disks = "%s,%s,,,,,,," % (linode["rootimage"], linode["swapimage"]) - params = { - "api_action": "linode.config.create", - "LinodeID": linode["id"], - "KernelID": kernel, - "Label": label["lconfig"], - "Comments": comments, - "DiskList": disks - } - data = self.connection.request(API_ROOT, params=params).objects[0] - linode["config"] = data["ConfigID"] - - # Step 5: linode.boot - params = { - "api_action": "linode.boot", - "LinodeID": linode["id"], - "ConfigID": linode["config"] - } - self.connection.request(API_ROOT, params=params) - - # Make a node out of it and hand it back - params = {"api_action": "linode.list", "LinodeID": linode["id"]} - data = self.connection.request(API_ROOT, params=params).objects[0] - nodes = self._to_nodes(data) - - if len(nodes) == 1: - node = nodes[0] - if getattr(auth, "generated", False): - node.extra['password'] = auth.password - return node - - return None - - def list_sizes(self, location=None): - """ - List available Linode plans - - Gets the sizes that can be used for creating a Linode. Since available - Linode plans vary per-location, this method can also be passed a - location to filter the availability. - - :keyword location: the facility to retrieve plans in - :type location: :class:`NodeLocation` - - :rtype: ``list`` of :class:`NodeSize` - """ - params = {"api_action": "avail.linodeplans"} - data = self.connection.request(API_ROOT, params=params).objects[0] - sizes = [] - for obj in data: - n = NodeSize(id=obj["PLANID"], name=obj["LABEL"], ram=obj["RAM"], - disk=(obj["DISK"] * 1024), bandwidth=obj["XFER"], - price=obj["PRICE"], driver=self.connection.driver) - sizes.append(n) - return sizes - - def list_images(self): - """ - List available Linux distributions - - Retrieve all Linux distributions that can be deployed to a Linode. - - :rtype: ``list`` of :class:`NodeImage` - """ - params = {"api_action": "avail.distributions"} - data = self.connection.request(API_ROOT, params=params).objects[0] - distros = [] - for obj in data: - i = NodeImage(id=obj["DISTRIBUTIONID"], - name=obj["LABEL"], - driver=self.connection.driver, - extra={'pvops': obj['REQUIRESPVOPSKERNEL'], - '64bit': obj['IS64BIT']}) - distros.append(i) - return distros - - def list_locations(self): - """ - List available facilities for deployment - - Retrieve all facilities that a Linode can be deployed in. - - :rtype: ``list`` of :class:`NodeLocation` - """ - params = {"api_action": "avail.datacenters"} - data = self.connection.request(API_ROOT, params=params).objects[0] - nl = [] - for dc in data: - country = None - if "USA" in dc["LOCATION"]: - country = "US" - elif "UK" in dc["LOCATION"]: - country = "GB" - elif "JP" in dc["LOCATION"]: - country = "JP" - else: - country = "??" - nl.append(NodeLocation(dc["DATACENTERID"], - dc["LOCATION"], - country, - self)) - return nl - - def linode_set_datacenter(self, dc): - """ - Set the default datacenter for Linode creation - - Since Linodes must be created in a facility, this function sets the - default that :class:`create_node` will use. If a location keyword is - not passed to :class:`create_node`, this method must have already been - used. - - :keyword dc: the datacenter to create Linodes in unless specified - :type dc: :class:`NodeLocation` - - :rtype: ``bool`` - """ - did = dc.id - params = {"api_action": "avail.datacenters"} - data = self.connection.request(API_ROOT, params=params).objects[0] - for datacenter in data: - if did == dc["DATACENTERID"]: - self.datacenter = did - return - - dcs = ", ".join([d["DATACENTERID"] for d in data]) - self.datacenter = None - raise LinodeException(0xFD, "Invalid datacenter (use one of %s)" % dcs) - - def _to_nodes(self, objs): - """Convert returned JSON Linodes into Node instances - - :keyword objs: ``list`` of JSON dictionaries representing the Linodes - :type objs: ``list`` - :return: ``list`` of :class:`Node`s""" - - # Get the IP addresses for the Linodes - nodes = {} - batch = [] - for o in objs: - lid = o["LINODEID"] - nodes[lid] = n = Node(id=lid, name=o["LABEL"], public_ips=[], - private_ips=[], - state=self.LINODE_STATES[o["STATUS"]], - driver=self.connection.driver) - n.extra = copy(o) - n.extra["PLANID"] = self._linode_plan_ids.get(o.get("TOTALRAM")) - batch.append({"api_action": "linode.ip.list", "LinodeID": lid}) - - # Avoid batch limitation - ip_answers = [] - args = [iter(batch)] * 25 - - if PY3: - izip_longest = itertools.zip_longest - else: - izip_longest = getattr(itertools, 'izip_longest', _izip_longest) - - for twenty_five in izip_longest(*args): - twenty_five = [q for q in twenty_five if q] - params = {"api_action": "batch", - "api_requestArray": json.dumps(twenty_five)} - req = self.connection.request(API_ROOT, params=params) - if not req.success() or len(req.objects) == 0: - return None - ip_answers.extend(req.objects) - - # Add the returned IPs to the nodes and return them - for ip_list in ip_answers: - for ip in ip_list: - lid = ip["LINODEID"] - which = nodes[lid].public_ips if ip["ISPUBLIC"] == 1 else\ - nodes[lid].private_ips - which.append(ip["IPADDRESS"]) - return list(nodes.values()) - - -def _izip_longest(*args, **kwds): - """Taken from Python docs - - http://docs.python.org/library/itertools.html#itertools.izip - """ - - fillvalue = kwds.get('fillvalue') - - def sentinel(counter=([fillvalue] * (len(args) - 1)).pop): - yield counter() # yields the fillvalue, or raises IndexError - - fillers = itertools.repeat(fillvalue) - iters = [itertools.chain(it, sentinel(), fillers) for it in args] - try: - for tup in itertools.izip(*iters): - yield tup - except IndexError: - pass diff --git a/awx/lib/site-packages/libcloud/compute/drivers/nephoscale.py b/awx/lib/site-packages/libcloud/compute/drivers/nephoscale.py deleted file mode 100644 index 1888ac8f50..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/nephoscale.py +++ /dev/null @@ -1,448 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -NephoScale Cloud driver (http://www.nephoscale.com) -API documentation: http://docs.nephoscale.com -Created by Markos Gogoulos (https://mist.io) -""" - -import base64 -import sys -import time -import os -import binascii - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b -from libcloud.utils.py3 import urlencode - -from libcloud.compute.providers import Provider -from libcloud.common.base import JsonResponse, ConnectionUserAndKey -from libcloud.compute.types import (NodeState, InvalidCredsError, - LibcloudError) -from libcloud.compute.base import (Node, NodeDriver, NodeImage, NodeSize, - NodeLocation) -from libcloud.utils.networking import is_private_subnet - -API_HOST = 'api.nephoscale.com' - -NODE_STATE_MAP = { - 'on': NodeState.RUNNING, - 'off': NodeState.UNKNOWN, - 'unknown': NodeState.UNKNOWN, -} - -VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, - httplib.NO_CONTENT] - -# used in create_node and specifies how many times to get the list of nodes and -# check if the newly created node is there. This is because when a request is -# sent to create a node, NephoScale replies with the job id, and not the node -# itself thus we don't have the ip addresses, that are required in deploy_node -CONNECT_ATTEMPTS = 10 - - -class NodeKey(object): - def __init__(self, id, name, public_key=None, key_group=None, - password=None): - self.id = id - self.name = name - self.key_group = key_group - self.password = password - self.public_key = public_key - - def __repr__(self): - return (('<NodeKey: id=%s, name=%s>') % - (self.id, self.name)) - - -class NephoscaleResponse(JsonResponse): - """ - Nephoscale API Response - """ - - def parse_error(self): - if self.status == httplib.UNAUTHORIZED: - raise InvalidCredsError('Authorization Failed') - if self.status == httplib.NOT_FOUND: - raise Exception("The resource you are looking for is not found.") - - return self.body - - def success(self): - return self.status in VALID_RESPONSE_CODES - - -class NephoscaleConnection(ConnectionUserAndKey): - """ - Nephoscale connection class. - Authenticates to the API through Basic Authentication - with username/password - """ - host = API_HOST - responseCls = NephoscaleResponse - - allow_insecure = False - - def add_default_headers(self, headers): - """ - Add parameters that are necessary for every request - """ - user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) - headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) - return headers - - -class NephoscaleNodeDriver(NodeDriver): - """ - Nephoscale node driver class. - - >>> from libcloud.compute.providers import get_driver - >>> driver = get_driver('nephoscale') - >>> conn = driver('nepho_user','nepho_password') - >>> conn.list_nodes() - """ - - type = Provider.NEPHOSCALE - api_name = 'nephoscale' - name = 'NephoScale' - website = 'http://www.nephoscale.com' - connectionCls = NephoscaleConnection - features = {'create_node': ['ssh_key']} - - def list_locations(self): - """ - List available zones for deployment - - :rtype: ``list`` of :class:`NodeLocation` - """ - result = self.connection.request('/datacenter/zone/').object - locations = [] - for value in result.get('data', []): - location = NodeLocation(id=value.get('id'), - name=value.get('name'), - country='US', - driver=self) - locations.append(location) - return locations - - def list_images(self): - """ - List available images for deployment - - :rtype: ``list`` of :class:`NodeImage` - """ - result = self.connection.request('/image/server/').object - images = [] - for value in result.get('data', []): - extra = {'architecture': value.get('architecture'), - 'disks': value.get('disks'), - 'billable_type': value.get('billable_type'), - 'pcpus': value.get('pcpus'), - 'cores': value.get('cores'), - 'uri': value.get('uri'), - 'storage': value.get('storage'), - } - image = NodeImage(id=value.get('id'), - name=value.get('friendly_name'), - driver=self, - extra=extra) - images.append(image) - return images - - def list_sizes(self): - """ - List available sizes containing prices - - :rtype: ``list`` of :class:`NodeSize` - """ - result = self.connection.request('/server/type/cloud/').object - sizes = [] - for value in result.get('data', []): - value_id = value.get('id') - size = NodeSize(id=value_id, - name=value.get('friendly_name'), - ram=value.get('ram'), - disk=value.get('storage'), - bandwidth=None, - price=self._get_size_price(size_id=str(value_id)), - driver=self) - sizes.append(size) - - return sorted(sizes, key=lambda k: k.price) - - def list_nodes(self): - """ - List available nodes - - :rtype: ``list`` of :class:`Node` - """ - result = self.connection.request('/server/cloud/').object - nodes = [self._to_node(value) for value in result.get('data', [])] - return nodes - - def rename_node(self, node, name, hostname=None): - """rename a cloud server, optionally specify hostname too""" - data = {'name': name} - if hostname: - data['hostname'] = hostname - params = urlencode(data) - result = self.connection.request('/server/cloud/%s/' % node.id, - data=params, method='PUT').object - return result.get('response') in VALID_RESPONSE_CODES - - def reboot_node(self, node): - """reboot a running node""" - result = self.connection.request('/server/cloud/%s/initiator/restart/' - % node.id, method='POST').object - return result.get('response') in VALID_RESPONSE_CODES - - def ex_start_node(self, node): - """start a stopped node""" - result = self.connection.request('/server/cloud/%s/initiator/start/' - % node.id, method='POST').object - return result.get('response') in VALID_RESPONSE_CODES - - def ex_stop_node(self, node): - """stop a running node""" - result = self.connection.request('/server/cloud/%s/initiator/stop/' - % node.id, method='POST').object - return result.get('response') in VALID_RESPONSE_CODES - - def destroy_node(self, node): - """destroy a node""" - result = self.connection.request('/server/cloud/%s/' % node.id, - method='DELETE').object - return result.get('response') in VALID_RESPONSE_CODES - - def ex_list_keypairs(self, ssh=False, password=False, key_group=None): - """ - List available console and server keys - There are two types of keys for NephoScale, ssh and password keys. - If run without arguments, lists all keys. Otherwise list only - ssh keys, or only password keys. - Password keys with key_group 4 are console keys. When a server - is created, it has two keys, one password or ssh key, and - one password console key. - - :keyword ssh: if specified, show ssh keys only (optional) - :type ssh: ``bool`` - - :keyword password: if specified, show password keys only (optional) - :type password: ``bool`` - - :keyword key_group: if specified, show keys with this key_group only - eg key_group=4 for console password keys (optional) - :type key_group: ``int`` - - :rtype: ``list`` of :class:`NodeKey` - """ - if (ssh and password): - raise LibcloudError('You can only supply ssh or password. To \ -get all keys call with no arguments') - if ssh: - result = self.connection.request('/key/sshrsa/').object - elif password: - result = self.connection.request('/key/password/').object - else: - result = self.connection.request('/key/').object - keys = [self._to_key(value) for value in result.get('data', [])] - - if key_group: - keys = [key for key in keys if - key.key_group == key_group] - return keys - - def ex_create_keypair(self, name, public_key=None, password=None, - key_group=None): - """Creates a key, ssh or password, for server or console - The group for the key (key_group) is 1 for Server and 4 for Console - Returns the id of the created key - """ - if public_key: - if not key_group: - key_group = 1 - data = { - 'name': name, - 'public_key': public_key, - 'key_group': key_group - - } - params = urlencode(data) - result = self.connection.request('/key/sshrsa/', data=params, - method='POST').object - else: - if not key_group: - key_group = 4 - if not password: - password = self.random_password() - data = { - 'name': name, - 'password': password, - 'key_group': key_group - } - params = urlencode(data) - result = self.connection.request('/key/password/', data=params, - method='POST').object - return result.get('data', {}).get('id', '') - - def ex_delete_keypair(self, key_id, ssh=False): - """Delete an ssh key or password given it's id - """ - if ssh: - result = self.connection.request('/key/sshrsa/%s/' % key_id, - method='DELETE').object - else: - result = self.connection.request('/key/password/%s/' % key_id, - method='DELETE').object - return result.get('response') in VALID_RESPONSE_CODES - - def create_node(self, name, size, image, server_key=None, - console_key=None, zone=None, **kwargs): - """Creates the node, and sets the ssh key, console key - NephoScale will respond with a 200-200 response after sending a valid - request. If nowait=True is specified in the args, we then ask a few - times until the server is created and assigned a public IP address, - so that deploy_node can be run - - >>> from libcloud.compute.providers import get_driver - >>> driver = get_driver('nephoscale') - >>> conn = driver('nepho_user','nepho_password') - >>> conn.list_nodes() - >>> name = 'staging-server' - >>> size = conn.list_sizes()[0] - <NodeSize: id=27, ...name=CS025 - 0.25GB, 10GB, ...> - >>> image = conn.list_images()[9] - <NodeImage: id=49, name=Linux Ubuntu Server 10.04 LTS 64-bit, ...> - >>> server_keys = conn.ex_list_keypairs(key_group=1)[0] - <NodeKey: id=71211, name=markos> - >>> server_key = conn.ex_list_keypairs(key_group=1)[0].id - 70867 - >>> console_keys = conn.ex_list_keypairs(key_group=4)[0] - <NodeKey: id=71213, name=mistio28434> - >>> console_key = conn.ex_list_keypairs(key_group=4)[0].id - 70907 - >>> node = conn.create_node(name=name, size=size, image=image, \ - console_key=console_key, server_key=server_key) - - We can also create an ssh key, plus a console key and - deploy node with them - >>> server_key = conn.ex_create_keypair(name, public_key='123') - 71211 - >>> console_key = conn.ex_create_keypair(name, key_group=4) - 71213 - - We can increase the number of connect attempts to wait until - the node is created, so that deploy_node has ip address to - deploy the script - We can also specify the location - >>> location = conn.list_locations()[0] - >>> node = conn.create_node(name=name, - ... size=size, - ... image=image, - ... console_key=console_key, - ... server_key=server_key, - ... connect_attempts=10, - ... nowait=True, - ... zone=location.id) - """ - hostname = kwargs.get('hostname', name) - service_type = size.id - image = image.id - connect_attempts = int(kwargs.get('connect_attempts', - CONNECT_ATTEMPTS)) - - data = {'name': name, - 'hostname': hostname, - 'service_type': service_type, - 'image': image, - 'server_key': server_key, - 'console_key': console_key, - 'zone': zone - } - - params = urlencode(data) - try: - node = self.connection.request('/server/cloud/', data=params, - method='POST') - except Exception: - e = sys.exc_info()[1] - raise Exception("Failed to create node %s" % e) - node = Node(id='', name=name, state=NodeState.UNKNOWN, public_ips=[], - private_ips=[], driver=self) - - nowait = kwargs.get('ex_wait', False) - if not nowait: - return node - else: - # try to get the created node public ips, for use in deploy_node - # At this point we don't have the id of the newly created Node, - # so search name in nodes - created_node = False - while connect_attempts > 0: - nodes = self.list_nodes() - created_node = [c_node for c_node in nodes if - c_node.name == name] - if created_node: - return created_node[0] - else: - time.sleep(60) - connect_attempts = connect_attempts - 1 - return node - - def _to_node(self, data): - """Convert node in Node instances - """ - - state = NODE_STATE_MAP.get(data.get('power_status'), '4') - public_ips = [] - private_ips = [] - ip_addresses = data.get('ipaddresses', '') - # E.g. "ipaddresses": "198.120.14.6, 10.132.60.1" - if ip_addresses: - for ip in ip_addresses.split(','): - ip = ip.replace(' ', '') - if is_private_subnet(ip): - private_ips.append(ip) - else: - public_ips.append(ip) - extra = { - 'zone_data': data.get('zone'), - 'zone': data.get('zone', {}).get('name'), - 'image': data.get('image', {}).get('friendly_name'), - 'create_time': data.get('create_time'), - 'network_ports': data.get('network_ports'), - 'is_console_enabled': data.get('is_console_enabled'), - 'service_type': data.get('service_type', {}).get('friendly_name'), - 'hostname': data.get('hostname') - } - - node = Node(id=data.get('id'), name=data.get('name'), state=state, - public_ips=public_ips, private_ips=private_ips, - driver=self, extra=extra) - return node - - def _to_key(self, data): - return NodeKey(id=data.get('id'), - name=data.get('name'), - password=data.get('password'), - key_group=data.get('key_group'), - public_key=data.get('public_key')) - - def random_password(self, size=8): - value = os.urandom(size) - password = binascii.hexlify(value).decode('ascii') - return password[:size] diff --git a/awx/lib/site-packages/libcloud/compute/drivers/ninefold.py b/awx/lib/site-packages/libcloud/compute/drivers/ninefold.py deleted file mode 100644 index 2689aad794..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/ninefold.py +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.compute.providers import Provider - -from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver - - -class NinefoldNodeDriver(CloudStackNodeDriver): - "Driver for Ninefold's Compute platform." - - host = 'api.ninefold.com' - path = '/compute/v1.0/' - - type = Provider.NINEFOLD - name = 'Ninefold' - website = 'http://ninefold.com/' diff --git a/awx/lib/site-packages/libcloud/compute/drivers/opennebula.py b/awx/lib/site-packages/libcloud/compute/drivers/opennebula.py deleted file mode 100644 index c295cd49f5..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/opennebula.py +++ /dev/null @@ -1,1264 +0,0 @@ -# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad -# Complutense de Madrid (dsa-research.org) -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -OpenNebula.org driver. -""" - -__docformat__ = 'epytext' - -from base64 import b64encode -import hashlib - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import next -from libcloud.utils.py3 import b - -from libcloud.compute.base import NodeState, NodeDriver, Node, NodeLocation -from libcloud.common.base import ConnectionUserAndKey, XmlResponse -from libcloud.compute.base import NodeImage, NodeSize, StorageVolume -from libcloud.common.types import InvalidCredsError -from libcloud.compute.providers import Provider - -__all__ = [ - 'ACTION', - 'OpenNebulaResponse', - 'OpenNebulaConnection', - 'OpenNebulaNodeSize', - 'OpenNebulaNetwork', - 'OpenNebulaNodeDriver', - 'OpenNebula_1_4_NodeDriver', - 'OpenNebula_2_0_NodeDriver', - 'OpenNebula_3_0_NodeDriver', - 'OpenNebula_3_2_NodeDriver', - 'OpenNebula_3_8_NodeDriver'] - -API_HOST = '' -API_PORT = (4567, 443) -API_SECURE = True -API_PLAIN_AUTH = False -DEFAULT_API_VERSION = '3.2' - - -class ACTION(object): - """ - All actions, except RESUME, only apply when the VM is in the "Running" - state. - """ - - STOP = 'STOPPED' - """ - The VM is stopped, and its memory state stored to a checkpoint file. VM - state, and disk image, are transferred back to the front-end. Resuming - the VM requires the VM instance to be re-scheduled. - """ - - SUSPEND = 'SUSPENDED' - """ - The VM is stopped, and its memory state stored to a checkpoint file. The VM - state, and disk image, are left on the host to be resumed later. Resuming - the VM does not require the VM to be re-scheduled. Rather, after - suspending, the VM resources are reserved for later resuming. - """ - - RESUME = 'RESUME' - """ - The VM is resumed using the saved memory state from the checkpoint file, - and the VM's disk image. The VM is either started immediately, or - re-scheduled depending on how it was suspended. - """ - - CANCEL = 'CANCEL' - """ - The VM is forcibly shutdown, its memory state is deleted. If a persistent - disk image was used, that disk image is transferred back to the front-end. - Any non-persistent disk images are deleted. - """ - - SHUTDOWN = 'SHUTDOWN' - """ - The VM is gracefully shutdown by sending the ACPI signal. If the VM does - not shutdown, then it is considered to still be running. If successfully, - shutdown, its memory state is deleted. If a persistent disk image was used, - that disk image is transferred back to the front-end. Any non-persistent - disk images are deleted. - """ - - REBOOT = 'REBOOT' - """ - Introduced in OpenNebula v3.2. - - The VM is gracefully restarted by sending the ACPI signal. - """ - - DONE = 'DONE' - """ - The VM is forcibly shutdown, its memory state is deleted. If a persistent - disk image was used, that disk image is transferred back to the front-end. - Any non-persistent disk images are deleted. - """ - - -class OpenNebulaResponse(XmlResponse): - """ - XmlResponse class for the OpenNebula.org driver. - """ - - def success(self): - """ - Check if response has the appropriate HTTP response code to be a - success. - - :rtype: ``bool`` - :return: True is success, else False. - """ - i = int(self.status) - return i >= 200 and i <= 299 - - def parse_error(self): - """ - Check if response contains any errors. - - @raise: :class:`InvalidCredsError` - - :rtype: :class:`ElementTree` - :return: Contents of HTTP response body. - """ - if int(self.status) == httplib.UNAUTHORIZED: - raise InvalidCredsError(self.body) - return self.body - - -class OpenNebulaConnection(ConnectionUserAndKey): - """ - Connection class for the OpenNebula.org driver. - with plain_auth support - """ - - host = API_HOST - port = API_PORT - secure = API_SECURE - plain_auth = API_PLAIN_AUTH - responseCls = OpenNebulaResponse - - def __init__(self, *args, **kwargs): - if 'plain_auth' in kwargs: - self.plain_auth = kwargs.pop('plain_auth') - super(OpenNebulaConnection, self).__init__(*args, **kwargs) - - def add_default_headers(self, headers): - """ - Add headers required by the OpenNebula.org OCCI interface. - - Includes adding Basic HTTP Authorization headers for authenticating - against the OpenNebula.org OCCI interface. - - :type headers: ``dict`` - :param headers: Dictionary containing HTTP headers. - - :rtype: ``dict`` - :return: Dictionary containing updated headers. - """ - if self.plain_auth: - passwd = self.key - else: - passwd = hashlib.sha1(b(self.key)).hexdigest() - headers['Authorization'] =\ - ('Basic %s' % b64encode(b('%s:%s' % (self.user_id, - passwd))).decode('utf-8')) - return headers - - -class OpenNebulaNodeSize(NodeSize): - """ - NodeSize class for the OpenNebula.org driver. - """ - - def __init__(self, id, name, ram, disk, bandwidth, price, driver, - cpu=None, vcpu=None): - super(OpenNebulaNodeSize, self).__init__(id=id, name=name, ram=ram, - disk=disk, - bandwidth=bandwidth, - price=price, driver=driver) - self.cpu = cpu - self.vcpu = vcpu - - def __repr__(self): - return (('<OpenNebulaNodeSize: id=%s, name=%s, ram=%s, disk=%s, ' - 'bandwidth=%s, price=%s, driver=%s, cpu=%s, vcpu=%s ...>') - % (self.id, self.name, self.ram, self.disk, self.bandwidth, - self.price, self.driver.name, self.cpu, self.vcpu)) - - -class OpenNebulaNetwork(object): - """ - Provide a common interface for handling networks of all types. - - Network objects are analogous to physical switches connecting two or - more physical nodes together. The Network object provides the interface in - libcloud through which we can manipulate networks in different cloud - providers in the same way. Network objects don't actually do much directly - themselves, instead the network driver handles the connection to the - network. - - You don't normally create a network object yourself; instead you use - a driver and then have that create the network for you. - - >>> from libcloud.compute.drivers.dummy import DummyNodeDriver - >>> driver = DummyNodeDriver() - >>> network = driver.create_network() - >>> network = driver.list_networks()[0] - >>> network.name - 'dummy-1' - """ - - def __init__(self, id, name, address, size, driver, extra=None): - self.id = str(id) - self.name = name - self.address = address - self.size = size - self.driver = driver - self.uuid = self.get_uuid() - self.extra = extra or {} - - def get_uuid(self): - """ - Unique hash for this network. - - The hash is a function of an SHA1 hash of the network's ID and - its driver which means that it should be unique between all - networks. In some subclasses (e.g. GoGrid) there is no ID - available so the public IP address is used. This means that, - unlike a properly done system UUID, the same UUID may mean a - different system install at a different time - - >>> from libcloud.network.drivers.dummy import DummyNetworkDriver - >>> driver = DummyNetworkDriver() - >>> network = driver.create_network() - >>> network.get_uuid() - 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f' - - Note, for example, that this example will always produce the - same UUID! - - :rtype: ``str`` - :return: Unique identifier for this instance. - """ - return hashlib.sha1(b("%s:%s" % (self.id, - self.driver.type))).hexdigest() - - def __repr__(self): - return (('<OpenNebulaNetwork: uuid=%s, name=%s, address=%s, size=%s, ' - 'provider=%s ...>') - % (self.uuid, self.name, self.address, self.size, - self.driver.name)) - - -class OpenNebulaNodeDriver(NodeDriver): - """ - OpenNebula.org node driver. - """ - - connectionCls = OpenNebulaConnection - name = 'OpenNebula' - website = 'http://opennebula.org/' - type = Provider.OPENNEBULA - - NODE_STATE_MAP = { - 'INIT': NodeState.PENDING, - 'PENDING': NodeState.PENDING, - 'HOLD': NodeState.PENDING, - 'ACTIVE': NodeState.RUNNING, - 'STOPPED': NodeState.TERMINATED, - 'SUSPENDED': NodeState.PENDING, - 'DONE': NodeState.TERMINATED, - 'FAILED': NodeState.TERMINATED} - - def __new__(cls, key, secret=None, api_version=DEFAULT_API_VERSION, - **kwargs): - if cls is OpenNebulaNodeDriver: - if api_version in ['1.4']: - cls = OpenNebula_1_4_NodeDriver - elif api_version in ['2.0', '2.2']: - cls = OpenNebula_2_0_NodeDriver - elif api_version in ['3.0']: - cls = OpenNebula_3_0_NodeDriver - elif api_version in ['3.2']: - cls = OpenNebula_3_2_NodeDriver - elif api_version in ['3.6']: - cls = OpenNebula_3_6_NodeDriver - elif api_version in ['3.8']: - cls = OpenNebula_3_8_NodeDriver - if 'plain_auth' not in kwargs: - kwargs['plain_auth'] = cls.plain_auth - else: - cls.plain_auth = kwargs['plain_auth'] - else: - raise NotImplementedError( - "No OpenNebulaNodeDriver found for API version %s" % - (api_version)) - return super(OpenNebulaNodeDriver, cls).__new__(cls) - - def create_node(self, **kwargs): - """ - Create a new OpenNebula node. - - @inherits: :class:`NodeDriver.create_node` - - :keyword networks: List of virtual networks to which this node should - connect. (optional) - :type networks: :class:`OpenNebulaNetwork` or - ``list`` of :class:`OpenNebulaNetwork` - """ - compute = ET.Element('COMPUTE') - - name = ET.SubElement(compute, 'NAME') - name.text = kwargs['name'] - - instance_type = ET.SubElement(compute, 'INSTANCE_TYPE') - instance_type.text = kwargs['size'].name - - storage = ET.SubElement(compute, 'STORAGE') - ET.SubElement(storage, - 'DISK', - {'image': '%s' % (str(kwargs['image'].id))}) - - if 'networks' in kwargs: - if not isinstance(kwargs['networks'], list): - kwargs['networks'] = [kwargs['networks']] - - networkGroup = ET.SubElement(compute, 'NETWORK') - for network in kwargs['networks']: - if network.address: - ET.SubElement(networkGroup, 'NIC', - {'network': '%s' % (str(network.id)), - 'ip': network.address}) - else: - ET.SubElement(networkGroup, 'NIC', - {'network': '%s' % (str(network.id))}) - - xml = ET.tostring(compute) - node = self.connection.request('/compute', method='POST', - data=xml).object - - return self._to_node(node) - - def destroy_node(self, node): - url = '/compute/%s' % (str(node.id)) - resp = self.connection.request(url, method='DELETE') - - return resp.status == httplib.OK - - def list_nodes(self): - return self._to_nodes(self.connection.request('/compute').object) - - def list_images(self, location=None): - return self._to_images(self.connection.request('/storage').object) - - def list_sizes(self, location=None): - """ - Return list of sizes on a provider. - - @inherits: :class:`NodeDriver.list_sizes` - - :return: List of compute node sizes supported by the cloud provider. - :rtype: ``list`` of :class:`OpenNebulaNodeSize` - """ - return [ - NodeSize(id=1, - name='small', - ram=None, - disk=None, - bandwidth=None, - price=None, - driver=self), - NodeSize(id=2, - name='medium', - ram=None, - disk=None, - bandwidth=None, - price=None, - driver=self), - NodeSize(id=3, - name='large', - ram=None, - disk=None, - bandwidth=None, - price=None, - driver=self), - ] - - def list_locations(self): - return [NodeLocation(0, '', '', self)] - - def ex_list_networks(self, location=None): - """ - List virtual networks on a provider. - - :param location: Location from which to request a list of virtual - networks. (optional) - :type location: :class:`NodeLocation` - - :return: List of virtual networks available to be connected to a - compute node. - :rtype: ``list`` of :class:`OpenNebulaNetwork` - """ - return self._to_networks(self.connection.request('/network').object) - - def ex_node_action(self, node, action): - """ - Build action representation and instruct node to commit action. - - Build action representation from the compute node ID, and the - action which should be carried out on that compute node. Then - instruct the node to carry out that action. - - :param node: Compute node instance. - :type node: :class:`Node` - - :param action: Action to be carried out on the compute node. - :type action: ``str`` - - :return: False if an HTTP Bad Request is received, else, True is - returned. - :rtype: ``bool`` - """ - compute_node_id = str(node.id) - - compute = ET.Element('COMPUTE') - - compute_id = ET.SubElement(compute, 'ID') - compute_id.text = compute_node_id - - state = ET.SubElement(compute, 'STATE') - state.text = action - - xml = ET.tostring(compute) - - url = '/compute/%s' % compute_node_id - resp = self.connection.request(url, method='PUT', - data=xml) - - if resp.status == httplib.BAD_REQUEST: - return False - else: - return True - - def _to_images(self, object): - """ - Request a list of images and convert that list to a list of NodeImage - objects. - - Request a list of images from the OpenNebula web interface, and - issue a request to convert each XML object representation of an image - to a NodeImage object. - - :rtype: ``list`` of :class:`NodeImage` - :return: List of images. - """ - images = [] - for element in object.findall('DISK'): - image_id = element.attrib['href'].partition('/storage/')[2] - image = self.connection.request( - ('/storage/%s' % (image_id))).object - images.append(self._to_image(image)) - - return images - - def _to_image(self, image): - """ - Take XML object containing an image description and convert to - NodeImage object. - - :type image: :class:`ElementTree` - :param image: XML representation of an image. - - :rtype: :class:`NodeImage` - :return: The newly extracted :class:`NodeImage`. - """ - return NodeImage(id=image.findtext('ID'), - name=image.findtext('NAME'), - driver=self.connection.driver, - extra={'size': image.findtext('SIZE'), - 'url': image.findtext('URL')}) - - def _to_networks(self, object): - """ - Request a list of networks and convert that list to a list of - OpenNebulaNetwork objects. - - Request a list of networks from the OpenNebula web interface, and - issue a request to convert each XML object representation of a network - to an OpenNebulaNetwork object. - - :rtype: ``list`` of :class:`OpenNebulaNetwork` - :return: List of virtual networks. - """ - networks = [] - for element in object.findall('NETWORK'): - network_id = element.attrib['href'].partition('/network/')[2] - network_element = self.connection.request( - ('/network/%s' % (network_id))).object - networks.append(self._to_network(network_element)) - - return networks - - def _to_network(self, element): - """ - Take XML object containing a network description and convert to - OpenNebulaNetwork object. - - Take XML representation containing a network description and - convert to OpenNebulaNetwork object. - - :rtype: :class:`OpenNebulaNetwork` - :return: The newly extracted :class:`OpenNebulaNetwork`. - """ - return OpenNebulaNetwork(id=element.findtext('ID'), - name=element.findtext('NAME'), - address=element.findtext('ADDRESS'), - size=element.findtext('SIZE'), - driver=self.connection.driver) - - def _to_nodes(self, object): - """ - Request a list of compute nodes and convert that list to a list of - Node objects. - - Request a list of compute nodes from the OpenNebula web interface, and - issue a request to convert each XML object representation of a node - to a Node object. - - :rtype: ``list`` of :class:`Node` - :return: A list of compute nodes. - """ - computes = [] - for element in object.findall('COMPUTE'): - compute_id = element.attrib['href'].partition('/compute/')[2] - compute = self.connection.request( - ('/compute/%s' % (compute_id))).object - computes.append(self._to_node(compute)) - - return computes - - def _to_node(self, compute): - """ - Take XML object containing a compute node description and convert to - Node object. - - Take XML representation containing a compute node description and - convert to Node object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: :class:`Node` - :return: The newly extracted :class:`Node`. - """ - try: - state = self.NODE_STATE_MAP[compute.findtext('STATE').upper()] - except KeyError: - state = NodeState.UNKNOWN - - return Node(id=compute.findtext('ID'), - name=compute.findtext('NAME'), - state=state, - public_ips=self._extract_networks(compute), - private_ips=[], - driver=self.connection.driver, - image=self._extract_images(compute)) - - def _extract_networks(self, compute): - """ - Extract networks from a compute node XML representation. - - Extract network descriptions from a compute node XML representation, - converting each network to an OpenNebulaNetwork object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: ``list`` of :class:`OpenNebulaNetwork`s. - :return: List of virtual networks attached to the compute node. - """ - networks = list() - - network_list = compute.find('NETWORK') - for element in network_list.findall('NIC'): - networks.append( - OpenNebulaNetwork(id=element.attrib.get('network', None), - name=None, - address=element.attrib.get('ip', None), - size=1, - driver=self.connection.driver)) - - return networks - - def _extract_images(self, compute): - """ - Extract image disks from a compute node XML representation. - - Extract image disk descriptions from a compute node XML representation, - converting the disks to an NodeImage object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: :class:`NodeImage`. - :return: First disk attached to a compute node. - """ - disks = list() - - disk_list = compute.find('STORAGE') - if disk_list is not None: - for element in disk_list.findall('DISK'): - disks.append( - NodeImage(id=element.attrib.get('image', None), - name=None, - driver=self.connection.driver, - extra={'dev': element.attrib.get('dev', None)})) - - # @TODO: Return all disks when the Node type accepts multiple - # attached disks per node. - if len(disks) > 0: - return disks[0] - else: - return None - - -class OpenNebula_1_4_NodeDriver(OpenNebulaNodeDriver): - """ - OpenNebula.org node driver for OpenNebula.org v1.4. - """ - - name = 'OpenNebula (v1.4)' - - -class OpenNebula_2_0_NodeDriver(OpenNebulaNodeDriver): - """ - OpenNebula.org node driver for OpenNebula.org v2.0 through OpenNebula.org - v2.2. - """ - - name = 'OpenNebula (v2.0 - v2.2)' - - def create_node(self, **kwargs): - """ - Create a new OpenNebula node. - - @inherits: :class:`NodeDriver.create_node` - - :keyword networks: List of virtual networks to which this node should - connect. (optional) - :type networks: :class:`OpenNebulaNetwork` or ``list`` - of :class:`OpenNebulaNetwork` - - :keyword context: Custom (key, value) pairs to be injected into - compute node XML description. (optional) - :type context: ``dict`` - - :return: Instance of a newly created node. - :rtype: :class:`Node` - """ - compute = ET.Element('COMPUTE') - - name = ET.SubElement(compute, 'NAME') - name.text = kwargs['name'] - - instance_type = ET.SubElement(compute, 'INSTANCE_TYPE') - instance_type.text = kwargs['size'].name - - disk = ET.SubElement(compute, 'DISK') - ET.SubElement(disk, - 'STORAGE', - {'href': '/storage/%s' % (str(kwargs['image'].id))}) - - if 'networks' in kwargs: - if not isinstance(kwargs['networks'], list): - kwargs['networks'] = [kwargs['networks']] - - for network in kwargs['networks']: - nic = ET.SubElement(compute, 'NIC') - ET.SubElement(nic, 'NETWORK', - {'href': '/network/%s' % (str(network.id))}) - if network.address: - ip_line = ET.SubElement(nic, 'IP') - ip_line.text = network.address - - if 'context' in kwargs: - if isinstance(kwargs['context'], dict): - contextGroup = ET.SubElement(compute, 'CONTEXT') - for key, value in list(kwargs['context'].items()): - context = ET.SubElement(contextGroup, key.upper()) - context.text = value - - xml = ET.tostring(compute) - node = self.connection.request('/compute', method='POST', - data=xml).object - - return self._to_node(node) - - def destroy_node(self, node): - url = '/compute/%s' % (str(node.id)) - resp = self.connection.request(url, method='DELETE') - - return resp.status == httplib.NO_CONTENT - - def list_sizes(self, location=None): - """ - Return list of sizes on a provider. - - @inherits: :class:`NodeDriver.list_sizes` - - :return: List of compute node sizes supported by the cloud provider. - :rtype: ``list`` of :class:`OpenNebulaNodeSize` - """ - return [ - OpenNebulaNodeSize(id=1, - name='small', - ram=1024, - cpu=1, - disk=None, - bandwidth=None, - price=None, - driver=self), - OpenNebulaNodeSize(id=2, - name='medium', - ram=4096, - cpu=4, - disk=None, - bandwidth=None, - price=None, - driver=self), - OpenNebulaNodeSize(id=3, - name='large', - ram=8192, - cpu=8, - disk=None, - bandwidth=None, - price=None, - driver=self), - OpenNebulaNodeSize(id=4, - name='custom', - ram=0, - cpu=0, - disk=None, - bandwidth=None, - price=None, - driver=self), - ] - - def _to_images(self, object): - """ - Request a list of images and convert that list to a list of NodeImage - objects. - - Request a list of images from the OpenNebula web interface, and - issue a request to convert each XML object representation of an image - to a NodeImage object. - - :rtype: ``list`` of :class:`NodeImage` - :return: List of images. - """ - images = [] - for element in object.findall('STORAGE'): - image_id = element.attrib["href"].partition("/storage/")[2] - image = self.connection.request( - ("/storage/%s" % (image_id))).object - images.append(self._to_image(image)) - - return images - - def _to_image(self, image): - """ - Take XML object containing an image description and convert to - NodeImage object. - - :type image: :class:`ElementTree` - :param image: XML representation of an image. - - :rtype: :class:`NodeImage` - :return: The newly extracted :class:`NodeImage`. - """ - return NodeImage(id=image.findtext('ID'), - name=image.findtext('NAME'), - driver=self.connection.driver, - extra={'description': image.findtext('DESCRIPTION'), - 'type': image.findtext('TYPE'), - 'size': image.findtext('SIZE'), - 'fstype': image.findtext('FSTYPE', None)}) - - def _to_node(self, compute): - """ - Take XML object containing a compute node description and convert to - Node object. - - Take XML representation containing a compute node description and - convert to Node object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: :class:`Node` - :return: The newly extracted :class:`Node`. - """ - try: - state = self.NODE_STATE_MAP[compute.findtext('STATE').upper()] - except KeyError: - state = NodeState.UNKNOWN - - return Node(id=compute.findtext('ID'), - name=compute.findtext('NAME'), - state=state, - public_ips=self._extract_networks(compute), - private_ips=[], - driver=self.connection.driver, - image=self._extract_images(compute), - size=self._extract_size(compute), - extra={'context': self._extract_context(compute)}) - - def _extract_networks(self, compute): - """ - Extract networks from a compute node XML representation. - - Extract network descriptions from a compute node XML representation, - converting each network to an OpenNebulaNetwork object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: ``list`` of :class:`OpenNebulaNetwork` - :return: List of virtual networks attached to the compute node. - """ - networks = [] - - for element in compute.findall('NIC'): - network = element.find('NETWORK') - network_id = network.attrib['href'].partition('/network/')[2] - - networks.append( - OpenNebulaNetwork(id=network_id, - name=network.attrib.get('name', None), - address=element.findtext('IP'), - size=1, - driver=self.connection.driver, - extra={'mac': element.findtext('MAC')})) - - return networks - - def _extract_images(self, compute): - """ - Extract image disks from a compute node XML representation. - - Extract image disk descriptions from a compute node XML representation, - converting the disks to an NodeImage object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: ``list`` of :class:`NodeImage` - :return: Disks attached to a compute node. - """ - disks = list() - - for element in compute.findall('DISK'): - disk = element.find('STORAGE') - image_id = disk.attrib['href'].partition('/storage/')[2] - - if 'id' in element.attrib: - disk_id = element.attrib['id'] - else: - disk_id = None - - disks.append( - NodeImage(id=image_id, - name=disk.attrib.get('name', None), - driver=self.connection.driver, - extra={'type': element.findtext('TYPE'), - 'disk_id': disk_id, - 'target': element.findtext('TARGET')})) - - # Return all disks when the Node type accepts multiple attached disks - # per node. - if len(disks) > 1: - return disks - elif len(disks) == 1: - return disks[0] - else: - return None - - def _extract_size(self, compute): - """ - Extract size, or node type, from a compute node XML representation. - - Extract node size, or node type, description from a compute node XML - representation, converting the node size to a NodeSize object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: :class:`OpenNebulaNodeSize` - :return: Node type of compute node. - """ - instance_type = compute.find('INSTANCE_TYPE') - - try: - return next((node_size for node_size in self.list_sizes() - if node_size.name == instance_type.text)) - except StopIteration: - return None - - def _extract_context(self, compute): - """ - Extract size, or node type, from a compute node XML representation. - - Extract node size, or node type, description from a compute node XML - representation, converting the node size to a NodeSize object. - - :type compute: :class:`ElementTree` - :param compute: XML representation of a compute node. - - :rtype: ``dict`` - :return: Dictionary containing (key, value) pairs related to - compute node context. - """ - contexts = dict() - context = compute.find('CONTEXT') - - if context is not None: - for context_element in list(context): - contexts[context_element.tag.lower()] = context_element.text - - return contexts - - -class OpenNebula_3_0_NodeDriver(OpenNebula_2_0_NodeDriver): - """ - OpenNebula.org node driver for OpenNebula.org v3.0. - """ - - name = 'OpenNebula (v3.0)' - - def ex_node_set_save_name(self, node, name): - """ - Build action representation and instruct node to commit action. - - Build action representation from the compute node ID, the disk image - which will be saved, and the name under which the image will be saved - upon shutting down the compute node. - - :param node: Compute node instance. - :type node: :class:`Node` - - :param name: Name under which the image should be saved after shutting - down the compute node. - :type name: ``str`` - - :return: False if an HTTP Bad Request is received, else, True is - returned. - :rtype: ``bool`` - """ - compute_node_id = str(node.id) - - compute = ET.Element('COMPUTE') - - compute_id = ET.SubElement(compute, 'ID') - compute_id.text = compute_node_id - - disk = ET.SubElement(compute, 'DISK', {'id': str(node.image.id)}) - - ET.SubElement(disk, 'STORAGE', - {'href': '/storage/%s' % (str(node.image.id)), - 'name': node.image.name}) - - ET.SubElement(disk, 'SAVE_AS', {'name': str(name)}) - - xml = ET.tostring(compute) - - url = '/compute/%s' % compute_node_id - resp = self.connection.request(url, method='PUT', - data=xml) - - if resp.status == httplib.BAD_REQUEST: - return False - else: - return True - - def _to_network(self, element): - """ - Take XML object containing a network description and convert to - OpenNebulaNetwork object. - - Take XML representation containing a network description and - convert to OpenNebulaNetwork object. - - :return: The newly extracted :class:`OpenNebulaNetwork`. - :rtype: :class:`OpenNebulaNetwork` - """ - return OpenNebulaNetwork(id=element.findtext('ID'), - name=element.findtext('NAME'), - address=element.findtext('ADDRESS'), - size=element.findtext('SIZE'), - driver=self.connection.driver, - extra={'public': element.findtext('PUBLIC')}) - - -class OpenNebula_3_2_NodeDriver(OpenNebula_3_0_NodeDriver): - """ - OpenNebula.org node driver for OpenNebula.org v3.2. - """ - - name = 'OpenNebula (v3.2)' - - def reboot_node(self, node): - return self.ex_node_action(node, ACTION.REBOOT) - - def list_sizes(self, location=None): - """ - Return list of sizes on a provider. - - @inherits: :class:`NodeDriver.list_sizes` - - :return: List of compute node sizes supported by the cloud provider. - :rtype: ``list`` of :class:`OpenNebulaNodeSize` - """ - return self._to_sizes(self.connection.request('/instance_type').object) - - def _to_sizes(self, object): - """ - Request a list of instance types and convert that list to a list of - OpenNebulaNodeSize objects. - - Request a list of instance types from the OpenNebula web interface, - and issue a request to convert each XML object representation of an - instance type to an OpenNebulaNodeSize object. - - :return: List of instance types. - :rtype: ``list`` of :class:`OpenNebulaNodeSize` - """ - sizes = [] - size_id = 1 - - attributes = [('name', str, None), ('ram', int, 'MEMORY'), - ('cpu', float, None), ('vcpu', float, None), - ('disk', str, None), ('bandwidth', float, None), - ('price', float, None)] - - for element in object.findall('INSTANCE_TYPE'): - size_kwargs = {'id': size_id, 'driver': self} - values = self._get_attributes_values(attributes=attributes, - element=element) - size_kwargs.update(values) - - size = OpenNebulaNodeSize(**size_kwargs) - sizes.append(size) - size_id += 1 - - return sizes - - def _get_attributes_values(self, attributes, element): - values = {} - - for attribute_name, attribute_type, alias in attributes: - key = alias if alias else attribute_name.upper() - value = element.findtext(key) - - if value is not None: - value = attribute_type(value) - - values[attribute_name] = value - - return values - - -class OpenNebula_3_6_NodeDriver(OpenNebula_3_2_NodeDriver): - """ - OpenNebula.org node driver for OpenNebula.org v3.6. - """ - - name = 'OpenNebula (v3.6)' - - def create_volume(self, size, name, location=None, snapshot=None): - storage = ET.Element('STORAGE') - - vol_name = ET.SubElement(storage, 'NAME') - vol_name.text = name - - vol_type = ET.SubElement(storage, 'TYPE') - vol_type.text = 'DATABLOCK' - - description = ET.SubElement(storage, 'DESCRIPTION') - description.text = 'Attached storage' - - public = ET.SubElement(storage, 'PUBLIC') - public.text = 'NO' - - persistent = ET.SubElement(storage, 'PERSISTENT') - persistent.text = 'YES' - - fstype = ET.SubElement(storage, 'FSTYPE') - fstype.text = 'ext3' - - vol_size = ET.SubElement(storage, 'SIZE') - vol_size.text = str(size) - - xml = ET.tostring(storage) - volume = self.connection.request('/storage', - {'occixml': xml}, - method='POST').object - - return self._to_volume(volume) - - def destroy_volume(self, volume): - url = '/storage/%s' % (str(volume.id)) - resp = self.connection.request(url, method='DELETE') - - return resp.status == httplib.NO_CONTENT - - def attach_volume(self, node, volume, device): - action = ET.Element('ACTION') - - perform = ET.SubElement(action, 'PERFORM') - perform.text = 'ATTACHDISK' - - params = ET.SubElement(action, 'PARAMS') - - ET.SubElement(params, - 'STORAGE', - {'href': '/storage/%s' % (str(volume.id))}) - - target = ET.SubElement(params, 'TARGET') - target.text = device - - xml = ET.tostring(action) - - url = '/compute/%s/action' % node.id - - resp = self.connection.request(url, method='POST', data=xml) - return resp.status == httplib.ACCEPTED - - def _do_detach_volume(self, node_id, disk_id): - action = ET.Element('ACTION') - - perform = ET.SubElement(action, 'PERFORM') - perform.text = 'DETACHDISK' - - params = ET.SubElement(action, 'PARAMS') - - ET.SubElement(params, - 'DISK', - {'id': disk_id}) - - xml = ET.tostring(action) - - url = '/compute/%s/action' % node_id - - resp = self.connection.request(url, method='POST', data=xml) - return resp.status == httplib.ACCEPTED - - def detach_volume(self, volume): - # We need to find the node using this volume - for node in self.list_nodes(): - if type(node.image) is not list: - # This node has only one associated image. It is not the one we - # are after. - continue - - for disk in node.image: - if disk.id == volume.id: - # Node found. We can now detach the volume - disk_id = disk.extra['disk_id'] - return self._do_detach_volume(node.id, disk_id) - - return False - - def list_volumes(self): - return self._to_volumes(self.connection.request('/storage').object) - - def _to_volume(self, storage): - return StorageVolume(id=storage.findtext('ID'), - name=storage.findtext('NAME'), - size=int(storage.findtext('SIZE')), - driver=self.connection.driver) - - def _to_volumes(self, object): - volumes = [] - for storage in object.findall('STORAGE'): - storage_id = storage.attrib['href'].partition('/storage/')[2] - - volumes.append(self._to_volume( - self.connection.request('/storage/%s' % storage_id).object)) - - return volumes - - -class OpenNebula_3_8_NodeDriver(OpenNebula_3_6_NodeDriver): - """ - OpenNebula.org node driver for OpenNebula.org v3.8. - """ - - name = 'OpenNebula (v3.8)' - plain_auth = API_PLAIN_AUTH - - def _to_sizes(self, object): - """ - Request a list of instance types and convert that list to a list of - OpenNebulaNodeSize objects. - - Request a list of instance types from the OpenNebula web interface, - and issue a request to convert each XML object representation of an - instance type to an OpenNebulaNodeSize object. - - :return: List of instance types. - :rtype: ``list`` of :class:`OpenNebulaNodeSize` - """ - sizes = [] - size_id = 1 - - attributes = [('name', str, None), ('ram', int, 'MEMORY'), - ('cpu', float, None), ('vcpu', float, None), - ('disk', str, None), ('bandwidth', float, None), - ('price', float, None)] - - for element in object.findall('INSTANCE_TYPE'): - element = self.connection.request( - ('/instance_type/%s') % (element.attrib['name'])).object - - size_kwargs = {'id': size_id, 'driver': self} - values = self._get_attributes_values(attributes=attributes, - element=element) - size_kwargs.update(values) - - size = OpenNebulaNodeSize(**size_kwargs) - sizes.append(size) - size_id += 1 - return sizes - - def _ex_connection_class_kwargs(self): - """ - Set plain_auth as an extra :class:`OpenNebulaConnection_3_8` argument - - :return: ``dict`` of :class:`OpenNebulaConnection_3_8` input arguments - """ - - return {'plain_auth': self.plain_auth} diff --git a/awx/lib/site-packages/libcloud/compute/drivers/openstack.py b/awx/lib/site-packages/libcloud/compute/drivers/openstack.py deleted file mode 100644 index c09cee6e0c..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/openstack.py +++ /dev/null @@ -1,2439 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -OpenStack driver -""" - -try: - import simplejson as json -except ImportError: - import json - -import warnings -import base64 - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b -from libcloud.utils.py3 import next -from libcloud.utils.py3 import urlparse - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.common.openstack import OpenStackBaseConnection -from libcloud.common.openstack import OpenStackDriverMixin -from libcloud.common.types import MalformedResponseError, ProviderError -from libcloud.utils.networking import is_private_subnet -from libcloud.compute.base import NodeSize, NodeImage -from libcloud.compute.base import (NodeDriver, Node, NodeLocation, - StorageVolume, VolumeSnapshot) -from libcloud.compute.base import KeyPair -from libcloud.compute.types import NodeState, Provider -from libcloud.compute.types import KeyPairDoesNotExistError -from libcloud.pricing import get_size_price -from libcloud.common.base import Response -from libcloud.utils.xml import findall - -__all__ = [ - 'OpenStack_1_0_Response', - 'OpenStack_1_0_Connection', - 'OpenStack_1_0_NodeDriver', - 'OpenStack_1_0_SharedIpGroup', - 'OpenStack_1_0_NodeIpAddresses', - 'OpenStack_1_1_Response', - 'OpenStack_1_1_Connection', - 'OpenStack_1_1_NodeDriver', - 'OpenStack_1_1_FloatingIpPool', - 'OpenStack_1_1_FloatingIpAddress', - 'OpenStackNodeDriver' -] - -ATOM_NAMESPACE = "http://www.w3.org/2005/Atom" - -DEFAULT_API_VERSION = '1.1' - - -class OpenStackException(ProviderError): - pass - - -class OpenStackResponse(Response): - node_driver = None - - def success(self): - i = int(self.status) - return i >= 200 and i <= 299 - - def has_content_type(self, content_type): - content_type_value = self.headers.get('content-type') or '' - content_type_value = content_type_value.lower() - return content_type_value.find(content_type.lower()) > -1 - - def parse_body(self): - if self.status == httplib.NO_CONTENT or not self.body: - return None - - if self.has_content_type('application/xml'): - try: - return ET.XML(self.body) - except: - raise MalformedResponseError( - 'Failed to parse XML', - body=self.body, - driver=self.node_driver) - - elif self.has_content_type('application/json'): - try: - return json.loads(self.body) - except: - raise MalformedResponseError( - 'Failed to parse JSON', - body=self.body, - driver=self.node_driver) - else: - return self.body - - def parse_error(self): - text = None - body = self.parse_body() - - if self.has_content_type('application/xml'): - text = '; '.join([err.text or '' for err in body.getiterator() - if err.text]) - elif self.has_content_type('application/json'): - values = list(body.values()) - - context = self.connection.context - driver = self.connection.driver - key_pair_name = context.get('key_pair_name', None) - - if len(values) > 0 and values[0]['code'] == 404 and key_pair_name: - raise KeyPairDoesNotExistError(name=key_pair_name, - driver=driver) - elif len(values) > 0 and 'message' in values[0]: - text = ';'.join([fault_data['message'] for fault_data - in values]) - else: - text = body - else: - # while we hope a response is always one of xml or json, we have - # seen html or text in the past, its not clear we can really do - # something to make it more readable here, so we will just pass - # it along as the whole response body in the text variable. - text = body - - return '%s %s %s' % (self.status, self.error, text) - - -class OpenStackComputeConnection(OpenStackBaseConnection): - # default config for http://devstack.org/ - service_type = 'compute' - service_name = 'nova' - service_region = 'RegionOne' - - def request(self, action, params=None, data='', headers=None, - method='GET'): - if not headers: - headers = {} - if not params: - params = {} - - if method in ("POST", "PUT"): - headers = {'Content-Type': self.default_content_type} - - return super(OpenStackComputeConnection, self).request( - action=action, - params=params, data=data, - method=method, headers=headers) - - -class OpenStackNodeDriver(NodeDriver, OpenStackDriverMixin): - """ - Base OpenStack node driver. Should not be used directly. - """ - api_name = 'openstack' - name = 'OpenStack' - website = 'http://openstack.org/' - - NODE_STATE_MAP = { - 'BUILD': NodeState.PENDING, - 'REBUILD': NodeState.PENDING, - 'ACTIVE': NodeState.RUNNING, - 'SUSPENDED': NodeState.TERMINATED, - 'DELETED': NodeState.TERMINATED, - 'QUEUE_RESIZE': NodeState.PENDING, - 'PREP_RESIZE': NodeState.PENDING, - 'VERIFY_RESIZE': NodeState.RUNNING, - 'PASSWORD': NodeState.PENDING, - 'RESCUE': NodeState.PENDING, - 'REBOOT': NodeState.REBOOTING, - 'HARD_REBOOT': NodeState.REBOOTING, - 'SHARE_IP': NodeState.PENDING, - 'SHARE_IP_NO_CONFIG': NodeState.PENDING, - 'DELETE_IP': NodeState.PENDING, - 'UNKNOWN': NodeState.UNKNOWN - } - - def __new__(cls, key, secret=None, secure=True, host=None, port=None, - api_version=DEFAULT_API_VERSION, **kwargs): - if cls is OpenStackNodeDriver: - if api_version == '1.0': - cls = OpenStack_1_0_NodeDriver - elif api_version == '1.1': - cls = OpenStack_1_1_NodeDriver - else: - raise NotImplementedError( - "No OpenStackNodeDriver found for API version %s" % - (api_version)) - return super(OpenStackNodeDriver, cls).__new__(cls) - - def __init__(self, *args, **kwargs): - OpenStackDriverMixin.__init__(self, **kwargs) - super(OpenStackNodeDriver, self).__init__(*args, **kwargs) - - def destroy_node(self, node): - uri = '/servers/%s' % (node.id) - resp = self.connection.request(uri, method='DELETE') - # The OpenStack and Rackspace documentation both say this API will - # return a 204, but in-fact, everyone everywhere agrees it actually - # returns a 202, so we are going to accept either, and someday, - # someone will fix either the implementation or the documentation to - # agree. - return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) - - def reboot_node(self, node): - return self._reboot_node(node, reboot_type='HARD') - - def list_nodes(self, ex_all_tenants=False): - """ - List the nodes in a tenant - - :param ex_all_tenants: List nodes for all the tenants. Note: Your user - must have admin privileges for this - functionality to work. - :type ex_all_tenants: ``bool`` - """ - params = {} - if ex_all_tenants: - params = {'all_tenants': 1} - return self._to_nodes( - self.connection.request('/servers/detail', params=params).object) - - def create_volume(self, size, name, location=None, snapshot=None): - if snapshot: - raise NotImplementedError( - "create_volume does not yet support create from snapshot") - return self.connection.request('/os-volumes', - method='POST', - data={ - 'volume': { - 'display_name': name, - 'display_description': name, - 'size': size, - 'volume_type': None, - 'metadata': { - 'contents': name, - }, - 'availability_zone': location, - } - }).success() - - def destroy_volume(self, volume): - return self.connection.request('/os-volumes/%s' % volume.id, - method='DELETE').success() - - def attach_volume(self, node, volume, device="auto"): - # when "auto" or None is provided for device, openstack will let - # the guest OS pick the next available device (fi. /dev/vdb) - return self.connection.request( - '/servers/%s/os-volume_attachments' % node.id, - method='POST', - data={ - 'volumeAttachment': { - 'volumeId': volume.id, - 'device': device, - } - }).success() - - def detach_volume(self, volume, ex_node=None): - # when ex_node is not provided, volume is detached from all nodes - failed_nodes = [] - for attachment in volume.extra['attachments']: - if not ex_node or ex_node.id == attachment['serverId']: - response = self.connection.request( - '/servers/%s/os-volume_attachments/%s' % - (attachment['serverId'], attachment['id']), - method='DELETE') - - if not response.success(): - failed_nodes.append(attachment['serverId']) - if failed_nodes: - raise OpenStackException( - 'detach_volume failed for nodes with id: %s' % - ', '.join(failed_nodes), 500, self - ) - return True - - def list_volumes(self): - return self._to_volumes( - self.connection.request('/os-volumes').object) - - def ex_get_volume(self, volumeId): - return self._to_volume( - self.connection.request('/os-volumes/%s' % volumeId).object) - - def list_images(self, location=None, ex_only_active=True): - """ - Lists all active images - - @inherits: :class:`NodeDriver.list_images` - - :param ex_only_active: True if list only active - :type ex_only_active: ``bool`` - - """ - return self._to_images( - self.connection.request('/images/detail').object, ex_only_active) - - def get_image(self, image_id): - """ - Get an image based on a image_id - - @inherits: :class:`NodeDriver.get_image` - - :param image_id: Image identifier - :type image_id: ``str`` - - :return: A NodeImage object - :rtype: :class:`NodeImage` - - """ - return self._to_image(self.connection.request( - '/images/%s' % (image_id,)).object['image']) - - def list_sizes(self, location=None): - return self._to_sizes( - self.connection.request('/flavors/detail').object) - - def list_locations(self): - return [NodeLocation(0, '', '', self)] - - def _ex_connection_class_kwargs(self): - return self.openstack_connection_kwargs() - - def ex_get_node_details(self, node_id): - """ - Lists details of the specified server. - - :param node_id: ID of the node which should be used - :type node_id: ``str`` - - :rtype: :class:`Node` - """ - # @TODO: Remove this if in 0.6 - if isinstance(node_id, Node): - node_id = node_id.id - - uri = '/servers/%s' % (node_id) - resp = self.connection.request(uri, method='GET') - if resp.status == httplib.NOT_FOUND: - return None - - return self._to_node_from_obj(resp.object) - - def ex_soft_reboot_node(self, node): - """ - Soft reboots the specified server - - :param node: node - :type node: :class:`Node` - - :rtype: ``bool`` - """ - return self._reboot_node(node, reboot_type='SOFT') - - def ex_hard_reboot_node(self, node): - """ - Hard reboots the specified server - - :param node: node - :type node: :class:`Node` - - :rtype: ``bool`` - """ - return self._reboot_node(node, reboot_type='HARD') - - -class OpenStackNodeSize(NodeSize): - """ - NodeSize class for the OpenStack.org driver. - - Following the example of OpenNebula.org driver - and following guidelines: - https://issues.apache.org/jira/browse/LIBCLOUD-119 - """ - - def __init__(self, id, name, ram, disk, bandwidth, price, driver, - vcpus=None): - super(OpenStackNodeSize, self).__init__(id=id, name=name, ram=ram, - disk=disk, - bandwidth=bandwidth, - price=price, driver=driver) - self.vcpus = vcpus - - def __repr__(self): - return (('<OpenStackNodeSize: id=%s, name=%s, ram=%s, disk=%s, ' - 'bandwidth=%s, price=%s, driver=%s, vcpus=%s, ...>') - % (self.id, self.name, self.ram, self.disk, self.bandwidth, - self.price, self.driver.name, self.vcpus)) - - -class OpenStack_1_0_Response(OpenStackResponse): - def __init__(self, *args, **kwargs): - # done because of a circular reference from - # NodeDriver -> Connection -> Response - self.node_driver = OpenStack_1_0_NodeDriver - super(OpenStack_1_0_Response, self).__init__(*args, **kwargs) - - -class OpenStack_1_0_Connection(OpenStackComputeConnection): - responseCls = OpenStack_1_0_Response - default_content_type = 'application/xml; charset=UTF-8' - accept_format = 'application/xml' - XML_NAMESPACE = 'http://docs.rackspacecloud.com/servers/api/v1.0' - - -class OpenStack_1_0_NodeDriver(OpenStackNodeDriver): - """ - OpenStack node driver. - - Extra node attributes: - - password: root password, available after create. - - hostId: represents the host your cloud server runs on - - imageId: id of image - - flavorId: id of flavor - """ - connectionCls = OpenStack_1_0_Connection - type = Provider.OPENSTACK - - features = {'create_node': ['generates_password']} - - def __init__(self, *args, **kwargs): - self._ex_force_api_version = str(kwargs.pop('ex_force_api_version', - None)) - self.XML_NAMESPACE = self.connectionCls.XML_NAMESPACE - super(OpenStack_1_0_NodeDriver, self).__init__(*args, **kwargs) - - def _to_images(self, object, ex_only_active): - images = [] - for image in findall(object, 'image', self.XML_NAMESPACE): - if ex_only_active and image.get('status') != 'ACTIVE': - continue - images.append(self._to_image(image)) - - return images - - def _to_image(self, element): - return NodeImage(id=element.get('id'), - name=element.get('name'), - driver=self.connection.driver, - extra={'updated': element.get('updated'), - 'created': element.get('created'), - 'status': element.get('status'), - 'serverId': element.get('serverId'), - 'progress': element.get('progress'), - 'minDisk': element.get('minDisk'), - 'minRam': element.get('minRam') - } - ) - - def _change_password_or_name(self, node, name=None, password=None): - uri = '/servers/%s' % (node.id) - - if not name: - name = node.name - - body = {'xmlns': self.XML_NAMESPACE, - 'name': name} - - if password is not None: - body['adminPass'] = password - - server_elm = ET.Element('server', body) - - resp = self.connection.request( - uri, method='PUT', data=ET.tostring(server_elm)) - - if resp.status == httplib.NO_CONTENT and password is not None: - node.extra['password'] = password - - return resp.status == httplib.NO_CONTENT - - def create_node(self, **kwargs): - """ - Create a new node - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_metadata: Key/Value metadata to associate with a node - :type ex_metadata: ``dict`` - - :keyword ex_files: File Path => File contents to create on - the node - :type ex_files: ``dict`` - - :keyword ex_shared_ip_group_id: The server is launched into - that shared IP group - :type ex_shared_ip_group_id: ``str`` - """ - name = kwargs['name'] - image = kwargs['image'] - size = kwargs['size'] - - attributes = {'xmlns': self.XML_NAMESPACE, - 'name': name, - 'imageId': str(image.id), - 'flavorId': str(size.id)} - - if 'ex_shared_ip_group' in kwargs: - # Deprecate this. Be explicit and call the variable - # ex_shared_ip_group_id since user needs to pass in the id, not the - # name. - warnings.warn('ex_shared_ip_group argument is deprecated.' - ' Please use ex_shared_ip_group_id') - - if 'ex_shared_ip_group_id' in kwargs: - shared_ip_group_id = kwargs['ex_shared_ip_group_id'] - attributes['sharedIpGroupId'] = shared_ip_group_id - - server_elm = ET.Element('server', attributes) - - metadata_elm = self._metadata_to_xml(kwargs.get("ex_metadata", {})) - if metadata_elm: - server_elm.append(metadata_elm) - - files_elm = self._files_to_xml(kwargs.get("ex_files", {})) - if files_elm: - server_elm.append(files_elm) - - resp = self.connection.request("/servers", - method='POST', - data=ET.tostring(server_elm)) - return self._to_node(resp.object) - - def ex_set_password(self, node, password): - """ - Sets the Node's root password. - - This will reboot the instance to complete the operation. - - :class:`Node.extra['password']` will be set to the new value if the - operation was successful. - - :param node: node to set password - :type node: :class:`Node` - - :param password: new password. - :type password: ``str`` - - :rtype: ``bool`` - """ - return self._change_password_or_name(node, password=password) - - def ex_set_server_name(self, node, name): - """ - Sets the Node's name. - - This will reboot the instance to complete the operation. - - :param node: node to set name - :type node: :class:`Node` - - :param name: new name - :type name: ``str`` - - :rtype: ``bool`` - """ - return self._change_password_or_name(node, name=name) - - def ex_resize(self, node, size): - """ - Change an existing server flavor / scale the server up or down. - - :param node: node to resize. - :type node: :class:`Node` - - :param size: new size. - :type size: :class:`NodeSize` - - :rtype: ``bool`` - """ - elm = ET.Element( - 'resize', - {'xmlns': self.XML_NAMESPACE, - 'flavorId': str(size.id)} - ) - - resp = self.connection.request("/servers/%s/action" % (node.id), - method='POST', - data=ET.tostring(elm)) - return resp.status == httplib.ACCEPTED - - def ex_confirm_resize(self, node): - """ - Confirm a resize request which is currently in progress. If a resize - request is not explicitly confirmed or reverted it's automatically - confirmed after 24 hours. - - For more info refer to the API documentation: http://goo.gl/zjFI1 - - :param node: node for which the resize request will be confirmed. - :type node: :class:`Node` - - :rtype: ``bool`` - """ - elm = ET.Element( - 'confirmResize', - {'xmlns': self.XML_NAMESPACE}, - ) - - resp = self.connection.request("/servers/%s/action" % (node.id), - method='POST', - data=ET.tostring(elm)) - return resp.status == httplib.NO_CONTENT - - def ex_revert_resize(self, node): - """ - Revert a resize request which is currently in progress. - All resizes are automatically confirmed after 24 hours if they have - not already been confirmed explicitly or reverted. - - For more info refer to the API documentation: http://goo.gl/AizBu - - :param node: node for which the resize request will be reverted. - :type node: :class:`Node` - - :rtype: ``bool`` - """ - elm = ET.Element( - 'revertResize', - {'xmlns': self.XML_NAMESPACE} - ) - - resp = self.connection.request("/servers/%s/action" % (node.id), - method='POST', - data=ET.tostring(elm)) - return resp.status == httplib.NO_CONTENT - - def ex_rebuild(self, node_id, image_id): - """ - Rebuilds the specified server. - - :param node_id: ID of the node which should be used - :type node_id: ``str`` - - :param image_id: ID of the image which should be used - :type image_id: ``str`` - - :rtype: ``bool`` - """ - # @TODO: Remove those ifs in 0.6 - if isinstance(node_id, Node): - node_id = node_id.id - - if isinstance(image_id, NodeImage): - image_id = image_id.id - - elm = ET.Element( - 'rebuild', - {'xmlns': self.XML_NAMESPACE, - 'imageId': image_id} - ) - - resp = self.connection.request("/servers/%s/action" % node_id, - method='POST', - data=ET.tostring(elm)) - return resp.status == httplib.ACCEPTED - - def ex_create_ip_group(self, group_name, node_id=None): - """ - Creates a shared IP group. - - :param group_name: group name which should be used - :type group_name: ``str`` - - :param node_id: ID of the node which should be used - :type node_id: ``str`` - - :rtype: ``bool`` - """ - # @TODO: Remove this if in 0.6 - if isinstance(node_id, Node): - node_id = node_id.id - - group_elm = ET.Element( - 'sharedIpGroup', - {'xmlns': self.XML_NAMESPACE, - 'name': group_name} - ) - - if node_id: - ET.SubElement( - group_elm, - 'server', - {'id': node_id} - ) - - resp = self.connection.request('/shared_ip_groups', - method='POST', - data=ET.tostring(group_elm)) - return self._to_shared_ip_group(resp.object) - - def ex_list_ip_groups(self, details=False): - """ - Lists IDs and names for shared IP groups. - If details lists all details for shared IP groups. - - :param details: True if details is required - :type details: ``bool`` - - :rtype: ``list`` of :class:`OpenStack_1_0_SharedIpGroup` - """ - uri = '/shared_ip_groups/detail' if details else '/shared_ip_groups' - resp = self.connection.request(uri, - method='GET') - groups = findall(resp.object, 'sharedIpGroup', - self.XML_NAMESPACE) - return [self._to_shared_ip_group(el) for el in groups] - - def ex_delete_ip_group(self, group_id): - """ - Deletes the specified shared IP group. - - :param group_id: group id which should be used - :type group_id: ``str`` - - :rtype: ``bool`` - """ - uri = '/shared_ip_groups/%s' % group_id - resp = self.connection.request(uri, method='DELETE') - return resp.status == httplib.NO_CONTENT - - def ex_share_ip(self, group_id, node_id, ip, configure_node=True): - """ - Shares an IP address to the specified server. - - :param group_id: group id which should be used - :type group_id: ``str`` - - :param node_id: ID of the node which should be used - :type node_id: ``str`` - - :param ip: ip which should be used - :type ip: ``str`` - - :param configure_node: configure node - :type configure_node: ``bool`` - - :rtype: ``bool`` - """ - # @TODO: Remove this if in 0.6 - if isinstance(node_id, Node): - node_id = node_id.id - - if configure_node: - str_configure = 'true' - else: - str_configure = 'false' - - elm = ET.Element( - 'shareIp', - {'xmlns': self.XML_NAMESPACE, - 'sharedIpGroupId': group_id, - 'configureServer': str_configure}, - ) - - uri = '/servers/%s/ips/public/%s' % (node_id, ip) - - resp = self.connection.request(uri, - method='PUT', - data=ET.tostring(elm)) - return resp.status == httplib.ACCEPTED - - def ex_unshare_ip(self, node_id, ip): - """ - Removes a shared IP address from the specified server. - - :param node_id: ID of the node which should be used - :type node_id: ``str`` - - :param ip: ip which should be used - :type ip: ``str`` - - :rtype: ``bool`` - """ - # @TODO: Remove this if in 0.6 - if isinstance(node_id, Node): - node_id = node_id.id - - uri = '/servers/%s/ips/public/%s' % (node_id, ip) - - resp = self.connection.request(uri, - method='DELETE') - return resp.status == httplib.ACCEPTED - - def ex_list_ip_addresses(self, node_id): - """ - List all server addresses. - - :param node_id: ID of the node which should be used - :type node_id: ``str`` - - :rtype: :class:`OpenStack_1_0_NodeIpAddresses` - """ - # @TODO: Remove this if in 0.6 - if isinstance(node_id, Node): - node_id = node_id.id - - uri = '/servers/%s/ips' % node_id - resp = self.connection.request(uri, - method='GET') - return self._to_ip_addresses(resp.object) - - def _metadata_to_xml(self, metadata): - if len(metadata) == 0: - return None - - metadata_elm = ET.Element('metadata') - for k, v in list(metadata.items()): - meta_elm = ET.SubElement(metadata_elm, 'meta', {'key': str(k)}) - meta_elm.text = str(v) - - return metadata_elm - - def _files_to_xml(self, files): - if len(files) == 0: - return None - - personality_elm = ET.Element('personality') - for k, v in list(files.items()): - file_elm = ET.SubElement(personality_elm, - 'file', - {'path': str(k)}) - file_elm.text = base64.b64encode(b(v)) - - return personality_elm - - def _reboot_node(self, node, reboot_type='SOFT'): - resp = self._node_action(node, ['reboot', ('type', reboot_type)]) - return resp.status == httplib.ACCEPTED - - def _node_action(self, node, body): - if isinstance(body, list): - attr = ' '.join(['%s="%s"' % (item[0], item[1]) - for item in body[1:]]) - body = '<%s xmlns="%s" %s/>' % (body[0], self.XML_NAMESPACE, attr) - uri = '/servers/%s/action' % (node.id) - resp = self.connection.request(uri, method='POST', data=body) - return resp - - def _to_nodes(self, object): - node_elements = findall(object, 'server', self.XML_NAMESPACE) - return [self._to_node(el) for el in node_elements] - - def _to_node_from_obj(self, obj): - return self._to_node(findall(obj, 'server', self.XML_NAMESPACE)[0]) - - def _to_node(self, el): - def get_ips(el): - return [ip.get('addr') for ip in el] - - def get_meta_dict(el): - d = {} - for meta in el: - d[meta.get('key')] = meta.text - return d - - public_ip = get_ips(findall(el, 'addresses/public/ip', - self.XML_NAMESPACE)) - private_ip = get_ips(findall(el, 'addresses/private/ip', - self.XML_NAMESPACE)) - metadata = get_meta_dict(findall(el, 'metadata/meta', - self.XML_NAMESPACE)) - - n = Node(id=el.get('id'), - name=el.get('name'), - state=self.NODE_STATE_MAP.get( - el.get('status'), NodeState.UNKNOWN), - public_ips=public_ip, - private_ips=private_ip, - driver=self.connection.driver, - extra={ - 'password': el.get('adminPass'), - 'hostId': el.get('hostId'), - 'imageId': el.get('imageId'), - 'flavorId': el.get('flavorId'), - 'uri': "https://%s%s/servers/%s" % ( - self.connection.host, - self.connection.request_path, el.get('id')), - 'metadata': metadata}) - return n - - def _to_sizes(self, object): - elements = findall(object, 'flavor', self.XML_NAMESPACE) - return [self._to_size(el) for el in elements] - - def _to_size(self, el): - vcpus = int(el.get('vcpus')) if el.get('vcpus', None) else None - return OpenStackNodeSize(id=el.get('id'), - name=el.get('name'), - ram=int(el.get('ram')), - disk=int(el.get('disk')), - # XXX: needs hardcode - vcpus=vcpus, - bandwidth=None, - # Hardcoded - price=self._get_size_price(el.get('id')), - driver=self.connection.driver) - - def ex_limits(self): - """ - Extra call to get account's limits, such as - rates (for example amount of POST requests per day) - and absolute limits like total amount of available - RAM to be used by servers. - - :return: dict with keys 'rate' and 'absolute' - :rtype: ``dict`` - """ - - def _to_rate(el): - rate = {} - for item in list(el.items()): - rate[item[0]] = item[1] - - return rate - - def _to_absolute(el): - return {el.get('name'): el.get('value')} - - limits = self.connection.request("/limits").object - rate = [_to_rate(el) for el in findall(limits, 'rate/limit', - self.XML_NAMESPACE)] - absolute = {} - for item in findall(limits, 'absolute/limit', - self.XML_NAMESPACE): - absolute.update(_to_absolute(item)) - - return {"rate": rate, "absolute": absolute} - - def create_image(self, node, name, description=None, reboot=True): - """Create an image for node. - - @inherits: :class:`NodeDriver.create_image` - - :param node: node to use as a base for image - :type node: :class:`Node` - - :param name: name for new image - :type name: ``str`` - - :rtype: :class:`NodeImage` - """ - - image_elm = ET.Element( - 'image', - {'xmlns': self.XML_NAMESPACE, - 'name': name, - 'serverId': node.id} - ) - - return self._to_image( - self.connection.request("/images", method="POST", - data=ET.tostring(image_elm)).object) - - def delete_image(self, image): - """Delete an image for node. - - @inherits: :class:`NodeDriver.delete_image` - - :param image: the image to be deleted - :type image: :class:`NodeImage` - - :rtype: ``bool`` - """ - uri = '/images/%s' % image.id - resp = self.connection.request(uri, method='DELETE') - return resp.status == httplib.NO_CONTENT - - def _to_shared_ip_group(self, el): - servers_el = findall(el, 'servers', self.XML_NAMESPACE) - if servers_el: - servers = [s.get('id') - for s in findall(servers_el[0], 'server', - self.XML_NAMESPACE)] - else: - servers = None - return OpenStack_1_0_SharedIpGroup(id=el.get('id'), - name=el.get('name'), - servers=servers) - - def _to_ip_addresses(self, el): - public_ips = [ip.get('addr') for ip in findall( - findall(el, 'public', self.XML_NAMESPACE)[0], - 'ip', self.XML_NAMESPACE)] - private_ips = [ip.get('addr') for ip in findall( - findall(el, 'private', self.XML_NAMESPACE)[0], - 'ip', self.XML_NAMESPACE)] - - return OpenStack_1_0_NodeIpAddresses(public_ips, private_ips) - - def _get_size_price(self, size_id): - try: - return get_size_price(driver_type='compute', - driver_name=self.api_name, - size_id=size_id) - except KeyError: - return 0.0 - - -class OpenStack_1_0_SharedIpGroup(object): - """ - Shared IP group info. - """ - - def __init__(self, id, name, servers=None): - self.id = str(id) - self.name = name - self.servers = servers - - -class OpenStack_1_0_NodeIpAddresses(object): - """ - List of public and private IP addresses of a Node. - """ - - def __init__(self, public_addresses, private_addresses): - self.public_addresses = public_addresses - self.private_addresses = private_addresses - - -class OpenStack_1_1_Response(OpenStackResponse): - def __init__(self, *args, **kwargs): - # done because of a circular reference from - # NodeDriver -> Connection -> Response - self.node_driver = OpenStack_1_1_NodeDriver - super(OpenStack_1_1_Response, self).__init__(*args, **kwargs) - - -class OpenStackNetwork(object): - """ - A Virtual Network. - """ - - def __init__(self, id, name, cidr, driver, extra=None): - self.id = str(id) - self.name = name - self.cidr = cidr - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return '<OpenStackNetwork id="%s" name="%s" cidr="%s">' % (self.id, - self.name, - self.cidr,) - - -class OpenStackSecurityGroup(object): - """ - A Security Group. - """ - - def __init__(self, id, tenant_id, name, description, driver, rules=None, - extra=None): - """ - Constructor. - - :keyword id: Group id. - :type id: ``str`` - - :keyword tenant_id: Owner of the security group. - :type tenant_id: ``str`` - - :keyword name: Human-readable name for the security group. Might - not be unique. - :type name: ``str`` - - :keyword description: Human-readable description of a security - group. - :type description: ``str`` - - :keyword rules: Rules associated with this group. - :type rules: ``list`` of - :class:`OpenStackSecurityGroupRule` - - :keyword extra: Extra attributes associated with this group. - :type extra: ``dict`` - """ - self.id = id - self.tenant_id = tenant_id - self.name = name - self.description = description - self.driver = driver - self.rules = rules or [] - self.extra = extra or {} - - def __repr__(self): - return ('<OpenStackSecurityGroup id=%s tenant_id=%s name=%s \ - description=%s>' % (self.id, self.tenant_id, self.name, - self.description)) - - -class OpenStackSecurityGroupRule(object): - """ - A Rule of a Security Group. - """ - - def __init__(self, id, parent_group_id, ip_protocol, from_port, to_port, - driver, ip_range=None, group=None, tenant_id=None, - extra=None): - """ - Constructor. - - :keyword id: Rule id. - :type id: ``str`` - - :keyword parent_group_id: ID of the parent security group. - :type parent_group_id: ``str`` - - :keyword ip_protocol: IP Protocol (icmp, tcp, udp, etc). - :type ip_protocol: ``str`` - - :keyword from_port: Port at start of range. - :type from_port: ``int`` - - :keyword to_port: Port at end of range. - :type to_port: ``int`` - - :keyword ip_range: CIDR for address range. - :type ip_range: ``str`` - - :keyword group: Name of a source security group to apply to rule. - :type group: ``str`` - - :keyword tenant_id: Owner of the security group. - :type tenant_id: ``str`` - - :keyword extra: Extra attributes associated with this rule. - :type extra: ``dict`` - """ - self.id = id - self.parent_group_id = parent_group_id - self.ip_protocol = ip_protocol - self.from_port = from_port - self.to_port = to_port - self.driver = driver - self.ip_range = '' - self.group = {} - - if group is None: - self.ip_range = ip_range - else: - self.group = {'name': group, 'tenant_id': tenant_id} - - self.tenant_id = tenant_id - self.extra = extra or {} - - def __repr__(self): - return ('<OpenStackSecurityGroupRule id=%s parent_group_id=%s \ - ip_protocol=%s from_port=%s to_port=%s>' % (self.id, - self.parent_group_id, self.ip_protocol, self.from_port, - self.to_port)) - - -class OpenStackKeyPair(object): - """ - A KeyPair. - """ - - def __init__(self, name, fingerprint, public_key, driver, private_key=None, - extra=None): - """ - Constructor. - - :keyword name: Name of the KeyPair. - :type name: ``str`` - - :keyword fingerprint: Fingerprint of the KeyPair - :type fingerprint: ``str`` - - :keyword public_key: Public key in OpenSSH format. - :type public_key: ``str`` - - :keyword private_key: Private key in PEM format. - :type private_key: ``str`` - - :keyword extra: Extra attributes associated with this KeyPair. - :type extra: ``dict`` - """ - self.name = name - self.fingerprint = fingerprint - self.public_key = public_key - self.private_key = private_key - self.driver = driver - self.extra = extra or {} - - def __repr__(self): - return ('<OpenStackKeyPair name=%s fingerprint=%s public_key=%s ...>' - % (self.name, self.fingerprint, self.public_key)) - - -class OpenStack_1_1_Connection(OpenStackComputeConnection): - responseCls = OpenStack_1_1_Response - accept_format = 'application/json' - default_content_type = 'application/json; charset=UTF-8' - - def encode_data(self, data): - return json.dumps(data) - - -class OpenStack_1_1_NodeDriver(OpenStackNodeDriver): - """ - OpenStack node driver. - """ - connectionCls = OpenStack_1_1_Connection - type = Provider.OPENSTACK - - features = {"create_node": ["generates_password"]} - _networks_url_prefix = '/os-networks' - - def __init__(self, *args, **kwargs): - self._ex_force_api_version = str(kwargs.pop('ex_force_api_version', - None)) - super(OpenStack_1_1_NodeDriver, self).__init__(*args, **kwargs) - - def create_node(self, **kwargs): - """Create a new node - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_keyname: The name of the key pair - :type ex_keyname: ``str`` - - :keyword ex_userdata: String containing user data - see - https://help.ubuntu.com/community/CloudInit - :type ex_userdata: ``str`` - - :keyword ex_security_groups: List of security groups to assign to - the node - :type ex_security_groups: ``list`` of - :class:`OpenStackSecurityGroup` - - :keyword ex_metadata: Key/Value metadata to associate with a node - :type ex_metadata: ``dict`` - - :keyword ex_files: File Path => File contents to create on - the no de - :type ex_files: ``dict`` - - - :keyword networks: The server is launched into a set of Networks. - :type networks: :class:`OpenStackNetwork` - - :keyword ex_disk_config: Name of the disk configuration. - Can be either ``AUTO`` or ``MANUAL``. - :type ex_disk_config: ``str`` - - :keyword ex_admin_pass: The root password for the node - :type ex_admin_pass: ``str`` - - :keyword ex_availability_zone: Nova availability zone for the node - :type ex_availability_zone: ``str`` - """ - - server_params = self._create_args_to_params(None, **kwargs) - - resp = self.connection.request("/servers", - method='POST', - data={'server': server_params}) - - create_response = resp.object['server'] - server_resp = self.connection.request( - '/servers/%s' % create_response['id']) - server_object = server_resp.object['server'] - - # adminPass is not always present - # http://docs.openstack.org/essex/openstack-compute/admin/ - # content/configuring-compute-API.html#d6e1833 - server_object['adminPass'] = create_response.get('adminPass', None) - - return self._to_node(server_object) - - def _to_images(self, obj, ex_only_active): - images = [] - for image in obj['images']: - if ex_only_active and image.get('status') != 'ACTIVE': - continue - images.append(self._to_image(image)) - - return images - - def _to_image(self, api_image): - server = api_image.get('server', {}) - return NodeImage( - id=api_image['id'], - name=api_image['name'], - driver=self, - extra=dict( - updated=api_image['updated'], - created=api_image['created'], - status=api_image['status'], - progress=api_image.get('progress'), - metadata=api_image.get('metadata'), - serverId=server.get('id'), - minDisk=api_image.get('minDisk'), - minRam=api_image.get('minRam'), - ) - ) - - def _to_nodes(self, obj): - servers = obj['servers'] - return [self._to_node(server) for server in servers] - - def _to_volumes(self, obj): - volumes = obj['volumes'] - return [self._to_volume(volume) for volume in volumes] - - def _to_snapshots(self, obj): - snapshots = obj['snapshots'] - return [self._to_snapshot(snapshot) for snapshot in snapshots] - - def _to_sizes(self, obj): - flavors = obj['flavors'] - return [self._to_size(flavor) for flavor in flavors] - - def _create_args_to_params(self, node, **kwargs): - server_params = { - 'name': kwargs.get('name'), - 'metadata': kwargs.get('ex_metadata', {}), - 'personality': self._files_to_personality(kwargs.get("ex_files", - {})) - } - - if 'ex_availability_zone' in kwargs: - server_params['availability_zone'] = kwargs['ex_availability_zone'] - - if 'ex_keyname' in kwargs: - server_params['key_name'] = kwargs['ex_keyname'] - - if 'ex_userdata' in kwargs: - server_params['user_data'] = base64.b64encode( - b(kwargs['ex_userdata'])).decode('ascii') - - if 'ex_disk_config' in kwargs: - server_params['OS-DCF:diskConfig'] = kwargs['ex_disk_config'] - - if 'ex_admin_pass' in kwargs: - server_params['adminPass'] = kwargs['ex_admin_pass'] - - if 'networks' in kwargs: - networks = kwargs['networks'] - networks = [{'uuid': network.id} for network in networks] - server_params['networks'] = networks - - if 'ex_security_groups' in kwargs: - server_params['security_groups'] = [] - for security_group in kwargs['ex_security_groups']: - name = security_group.name - server_params['security_groups'].append({'name': name}) - - if 'name' in kwargs: - server_params['name'] = kwargs.get('name') - else: - server_params['name'] = node.name - - if 'image' in kwargs: - server_params['imageRef'] = kwargs.get('image').id - else: - server_params['imageRef'] = node.extra.get('imageId') - - if 'size' in kwargs: - server_params['flavorRef'] = kwargs.get('size').id - else: - server_params['flavorRef'] = node.extra.get('flavorId') - - return server_params - - def _files_to_personality(self, files): - rv = [] - - for k, v in list(files.items()): - rv.append({'path': k, 'contents': base64.b64encode(b(v))}) - - return rv - - def _reboot_node(self, node, reboot_type='SOFT'): - resp = self._node_action(node, 'reboot', type=reboot_type) - return resp.status == httplib.ACCEPTED - - def ex_set_password(self, node, password): - """ - Changes the administrator password for a specified server. - - :param node: Node to rebuild. - :type node: :class:`Node` - - :param password: The administrator password. - :type password: ``str`` - - :rtype: ``bool`` - """ - resp = self._node_action(node, 'changePassword', adminPass=password) - node.extra['password'] = password - return resp.status == httplib.ACCEPTED - - def ex_rebuild(self, node, image, **kwargs): - """ - Rebuild a Node. - - :param node: Node to rebuild. - :type node: :class:`Node` - - :param image: New image to use. - :type image: :class:`NodeImage` - - :keyword ex_metadata: Key/Value metadata to associate with a node - :type ex_metadata: ``dict`` - - :keyword ex_files: File Path => File contents to create on - the no de - :type ex_files: ``dict`` - - :keyword ex_keyname: Name of existing public key to inject into - instance - :type ex_keyname: ``str`` - - :keyword ex_userdata: String containing user data - see - https://help.ubuntu.com/community/CloudInit - :type ex_userdata: ``str`` - - :keyword ex_security_groups: List of security groups to assign to - the node - :type ex_security_groups: ``list`` of - :class:`OpenStackSecurityGroup` - - :keyword ex_disk_config: Name of the disk configuration. - Can be either ``AUTO`` or ``MANUAL``. - :type ex_disk_config: ``str`` - - :rtype: ``bool`` - """ - server_params = self._create_args_to_params(node, image=image, - **kwargs) - resp = self._node_action(node, 'rebuild', **server_params) - return resp.status == httplib.ACCEPTED - - def ex_resize(self, node, size): - """ - Change a node size. - - :param node: Node to resize. - :type node: :class:`Node` - - :type size: :class:`NodeSize` - :param size: New size to use. - - :rtype: ``bool`` - """ - server_params = self._create_args_to_params(node, size=size) - resp = self._node_action(node, 'resize', **server_params) - return resp.status == httplib.ACCEPTED - - def ex_confirm_resize(self, node): - """ - Confirms a pending resize action. - - :param node: Node to resize. - :type node: :class:`Node` - - :rtype: ``bool`` - """ - resp = self._node_action(node, 'confirmResize') - return resp.status == httplib.NO_CONTENT - - def ex_revert_resize(self, node): - """ - Cancels and reverts a pending resize action. - - :param node: Node to resize. - :type node: :class:`Node` - - :rtype: ``bool`` - """ - resp = self._node_action(node, 'revertResize') - return resp.status == httplib.ACCEPTED - - def create_image(self, node, name, metadata=None): - """ - Creates a new image. - - :param node: Node - :type node: :class:`Node` - - :param name: The name for the new image. - :type name: ``str`` - - :param metadata: Key and value pairs for metadata. - :type metadata: ``dict`` - - :rtype: :class:`NodeImage` - """ - optional_params = {} - if metadata: - optional_params['metadata'] = metadata - resp = self._node_action(node, 'createImage', name=name, - **optional_params) - image_id = self._extract_image_id_from_url(resp.headers['location']) - return self.get_image(image_id=image_id) - - def ex_set_server_name(self, node, name): - """ - Sets the Node's name. - - :param node: Node - :type node: :class:`Node` - - :param name: The name of the server. - :type name: ``str`` - - :rtype: :class:`Node` - """ - return self._update_node(node, name=name) - - def ex_get_metadata(self, node): - """ - Get a Node's metadata. - - :param node: Node - :type node: :class:`Node` - - :return: Key/Value metadata associated with node. - :rtype: ``dict`` - """ - return self.connection.request( - '/servers/%s/metadata' % (node.id,), - method='GET',).object['metadata'] - - def ex_set_metadata(self, node, metadata): - """ - Sets the Node's metadata. - - :param node: Node - :type node: :class:`Node` - - :param metadata: Key/Value metadata to associate with a node - :type metadata: ``dict`` - - :rtype: ``dict`` - """ - return self.connection.request( - '/servers/%s/metadata' % (node.id,), method='PUT', - data={'metadata': metadata} - ).object['metadata'] - - def ex_update_node(self, node, **node_updates): - """ - Update the Node's editable attributes. The OpenStack API currently - supports editing name and IPv4/IPv6 access addresses. - - The driver currently only supports updating the node name. - - :param node: Node - :type node: :class:`Node` - - :keyword name: New name for the server - :type name: ``str`` - - :rtype: :class:`Node` - """ - potential_data = self._create_args_to_params(node, **node_updates) - updates = {'name': potential_data['name']} - return self._update_node(node, **updates) - - def _to_networks(self, obj): - networks = obj['networks'] - return [self._to_network(network) for network in networks] - - def _to_network(self, obj): - return OpenStackNetwork(id=obj['id'], - name=obj['label'], - cidr=obj.get('cidr', None), - driver=self) - - def ex_list_networks(self): - """ - Get a list of Networks that are available. - - :rtype: ``list`` of :class:`OpenStackNetwork` - """ - response = self.connection.request(self._networks_url_prefix).object - return self._to_networks(response) - - def ex_create_network(self, name, cidr): - """ - Create a new Network - - :param name: Name of network which should be used - :type name: ``str`` - - :param cidr: cidr of network which should be used - :type cidr: ``str`` - - :rtype: :class:`OpenStackNetwork` - """ - data = {'network': {'cidr': cidr, 'label': name}} - response = self.connection.request(self._networks_url_prefix, - method='POST', data=data).object - return self._to_network(response['network']) - - def ex_delete_network(self, network): - """ - Get a list of NodeNetorks that are available. - - :param network: Network which should be used - :type network: :class:`OpenStackNetwork` - - :rtype: ``bool`` - """ - resp = self.connection.request('%s/%s' % (self._networks_url_prefix, - network.id), - method='DELETE') - return resp.status == httplib.ACCEPTED - - def ex_get_console_output(self, node, length=None): - """ - Get console output - - :param node: node - :type node: :class:`Node` - - :param length: Optional number of lines to fetch from the - console log - :type length: ``int`` - - :return: Dictionary with the output - :rtype: ``dict`` - """ - - data = { - "os-getConsoleOutput": { - "length": length - } - } - - resp = self.connection.request('/servers/%s/action' % node.id, - method='POST', data=data).object - return resp - - def ex_list_snapshots(self): - return self._to_snapshots( - self.connection.request('/os-snapshots').object) - - def ex_create_snapshot(self, volume, name, description=None, force=False): - """ - Create a snapshot based off of a volume. - - :param volume: volume - :type volume: :class:`StorageVolume` - - :keyword name: New name for the volume snapshot - :type name: ``str`` - - :keyword description: Description of the snapshot (optional) - :type description: ``str`` - - :keyword force: Whether to force creation (optional) - :type force: ``bool`` - - :rtype: :class:`VolumeSnapshot` - """ - data = {'snapshot': {'display_name': name, - 'display_description': description, - 'volume_id': volume.id, - 'force': force}} - - return self._to_snapshot(self.connection.request('/os-snapshots', - method='POST', - data=data).object) - - def ex_delete_snapshot(self, snapshot): - """ - Delete a VolumeSnapshot - - :param snapshot: snapshot - :type snapshot: :class:`VolumeSnapshot` - - :rtype: ``bool`` - """ - resp = self.connection.request('/os-snapshots/%s' % snapshot.id, - method='DELETE') - return resp.status == httplib.NO_CONTENT - - def _to_security_group_rules(self, obj): - return [self._to_security_group_rule(security_group_rule) for - security_group_rule in obj] - - def _to_security_group_rule(self, obj): - ip_range = group = tenant_id = None - if obj['group'] == {}: - ip_range = obj['ip_range'].get('cidr', None) - else: - group = obj['group'].get('name', None) - tenant_id = obj['group'].get('tenant_id', None) - - return OpenStackSecurityGroupRule( - id=obj['id'], parent_group_id=obj['parent_group_id'], - ip_protocol=obj['ip_protocol'], from_port=obj['from_port'], - to_port=obj['to_port'], driver=self, ip_range=ip_range, - group=group, tenant_id=tenant_id) - - def _to_security_groups(self, obj): - security_groups = obj['security_groups'] - return [self._to_security_group(security_group) for security_group in - security_groups] - - def _to_security_group(self, obj): - rules = self._to_security_group_rules(obj.get('rules', [])) - return OpenStackSecurityGroup(id=obj['id'], - tenant_id=obj['tenant_id'], - name=obj['name'], - description=obj.get('description', ''), - rules=rules, - driver=self) - - def ex_list_security_groups(self): - """ - Get a list of Security Groups that are available. - - :rtype: ``list`` of :class:`OpenStackSecurityGroup` - """ - return self._to_security_groups( - self.connection.request('/os-security-groups').object) - - def ex_get_node_security_groups(self, node): - """ - Get Security Groups of the specified server. - - :rtype: ``list`` of :class:`OpenStackSecurityGroup` - """ - return self._to_security_groups( - self.connection.request('/servers/%s/os-security-groups' % - (node.id)).object) - - def ex_create_security_group(self, name, description): - """ - Create a new Security Group - - :param name: Name of the new Security Group - :type name: ``str`` - - :param description: Description of the new Security Group - :type description: ``str`` - - :rtype: :class:`OpenStackSecurityGroup` - """ - return self._to_security_group(self.connection.request( - '/os-security-groups', method='POST', - data={'security_group': {'name': name, 'description': description}} - ).object['security_group']) - - def ex_delete_security_group(self, security_group): - """ - Delete a Security Group. - - :param security_group: Security Group should be deleted - :type security_group: :class:`OpenStackSecurityGroup` - - :rtype: ``bool`` - """ - resp = self.connection.request('/os-security-groups/%s' % - (security_group.id), - method='DELETE') - return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) - - def ex_create_security_group_rule(self, security_group, ip_protocol, - from_port, to_port, cidr=None, - source_security_group=None): - """ - Create a new Rule in a Security Group - - :param security_group: Security Group in which to add the rule - :type security_group: :class:`OpenStackSecurityGroup` - - :param ip_protocol: Protocol to which this rule applies - Examples: tcp, udp, ... - :type ip_protocol: ``str`` - - :param from_port: First port of the port range - :type from_port: ``int`` - - :param to_port: Last port of the port range - :type to_port: ``int`` - - :param cidr: CIDR notation of the source IP range for this rule - :type cidr: ``str`` - - :param source_security_group: Existing Security Group to use as the - source (instead of CIDR) - :type source_security_group: L{OpenStackSecurityGroup - - :rtype: :class:`OpenStackSecurityGroupRule` - """ - source_security_group_id = None - if type(source_security_group) == OpenStackSecurityGroup: - source_security_group_id = source_security_group.id - - return self._to_security_group_rule(self.connection.request( - '/os-security-group-rules', method='POST', - data={'security_group_rule': { - 'ip_protocol': ip_protocol, - 'from_port': from_port, - 'to_port': to_port, - 'cidr': cidr, - 'group_id': source_security_group_id, - 'parent_group_id': security_group.id}} - ).object['security_group_rule']) - - def ex_delete_security_group_rule(self, rule): - """ - Delete a Rule from a Security Group. - - :param rule: Rule should be deleted - :type rule: :class:`OpenStackSecurityGroupRule` - - :rtype: ``bool`` - """ - resp = self.connection.request('/os-security-group-rules/%s' % - (rule.id), method='DELETE') - return resp.status == httplib.NO_CONTENT - - def _to_key_pairs(self, obj): - key_pairs = obj['keypairs'] - key_pairs = [self._to_key_pair(key_pair['keypair']) for key_pair in - key_pairs] - return key_pairs - - def _to_key_pair(self, obj): - key_pair = KeyPair(name=obj['name'], - fingerprint=obj['fingerprint'], - public_key=obj['public_key'], - private_key=obj.get('private_key', None), - driver=self) - return key_pair - - def list_key_pairs(self): - response = self.connection.request('/os-keypairs') - key_pairs = self._to_key_pairs(response.object) - return key_pairs - - def get_key_pair(self, name): - self.connection.set_context({'key_pair_name': name}) - - response = self.connection.request('/os-keypairs/%s' % (name)) - key_pair = self._to_key_pair(response.object['keypair']) - return key_pair - - def create_key_pair(self, name): - data = {'keypair': {'name': name}} - response = self.connection.request('/os-keypairs', method='POST', - data=data) - key_pair = self._to_key_pair(response.object['keypair']) - return key_pair - - def import_key_pair_from_string(self, name, key_material): - data = {'keypair': {'name': name, 'public_key': key_material}} - response = self.connection.request('/os-keypairs', method='POST', - data=data) - key_pair = self._to_key_pair(response.object['keypair']) - return key_pair - - def delete_key_pair(self, key_pair): - """ - Delete a KeyPair. - - :param keypair: KeyPair to delete - :type keypair: :class:`OpenStackKeyPair` - - :rtype: ``bool`` - """ - response = self.connection.request('/os-keypairs/%s' % (key_pair.name), - method='DELETE') - return response.status == httplib.ACCEPTED - - def ex_list_keypairs(self): - """ - Get a list of KeyPairs that are available. - - :rtype: ``list`` of :class:`OpenStackKeyPair` - """ - warnings.warn('This method has been deprecated in favor of ' - 'list_key_pairs method') - - return self.list_key_pairs() - - def ex_create_keypair(self, name): - """ - Create a new KeyPair - - :param name: Name of the new KeyPair - :type name: ``str`` - - :rtype: :class:`OpenStackKeyPair` - """ - warnings.warn('This method has been deprecated in favor of ' - 'create_key_pair method') - - return self.create_key_pair(name=name) - - def ex_import_keypair(self, name, keyfile): - """ - Import a KeyPair from a file - - :param name: Name of the new KeyPair - :type name: ``str`` - - :param keyfile: Path to the public key file (in OpenSSH format) - :type keyfile: ``str`` - - :rtype: :class:`OpenStackKeyPair` - """ - warnings.warn('This method has been deprecated in favor of ' - 'import_key_pair_from_file method') - - return self.import_key_pair_from_file(name=name, key_file_path=keyfile) - - def ex_import_keypair_from_string(self, name, key_material): - """ - Import a KeyPair from a string - - :param name: Name of the new KeyPair - :type name: ``str`` - - :param key_material: Public key (in OpenSSH format) - :type key_material: ``str`` - - :rtype: :class:`OpenStackKeyPair` - """ - warnings.warn('This method has been deprecated in favor of ' - 'import_key_pair_from_string method') - - return self.import_key_pair_from_string(name=name, - key_material=key_material) - - def ex_delete_keypair(self, keypair): - """ - Delete a KeyPair. - - :param keypair: KeyPair to delete - :type keypair: :class:`OpenStackKeyPair` - - :rtype: ``bool`` - """ - warnings.warn('This method has been deprecated in favor of ' - 'delete_key_pair method') - - return self.delete_key_pair(key_pair=keypair) - - def ex_get_size(self, size_id): - """ - Get a NodeSize - - :param size_id: ID of the size which should be used - :type size_id: ``str`` - - :rtype: :class:`NodeSize` - """ - return self._to_size(self.connection.request( - '/flavors/%s' % (size_id,)) .object['flavor']) - - def get_image(self, image_id): - """ - Get a NodeImage - - @inherits: :class:`NodeDriver.get_image` - - :param image_id: ID of the image which should be used - :type image_id: ``str`` - - :rtype: :class:`NodeImage` - """ - return self._to_image(self.connection.request( - '/images/%s' % (image_id,)).object['image']) - - def delete_image(self, image): - """ - Delete a NodeImage - - @inherits: :class:`NodeDriver.delete_image` - - :param image: image witch should be used - :type image: :class:`NodeImage` - - :rtype: ``bool`` - """ - resp = self.connection.request('/images/%s' % (image.id,), - method='DELETE') - return resp.status == httplib.NO_CONTENT - - def _node_action(self, node, action, **params): - params = params or None - return self.connection.request('/servers/%s/action' % (node.id,), - method='POST', data={action: params}) - - def _update_node(self, node, **node_updates): - """ - Updates the editable attributes of a server, which currently include - its name and IPv4/IPv6 access addresses. - """ - return self._to_node( - self.connection.request( - '/servers/%s' % (node.id,), method='PUT', - data={'server': node_updates} - ).object['server'] - ) - - def _to_node_from_obj(self, obj): - return self._to_node(obj['server']) - - def _to_node(self, api_node): - public_networks_labels = ['public', 'internet'] - - public_ips, private_ips = [], [] - - for label, values in api_node['addresses'].items(): - ips = [v['addr'] for v in values] - - if label in public_networks_labels: - public_ips.extend(ips) - else: - for ip in ips: - # is_private_subnet does not check for ipv6 - try: - if is_private_subnet(ip): - private_ips.append(ip) - else: - public_ips.append(ip) - except: - private_ips.append(ip) - - # Sometimes 'image' attribute is not present if the node is in an error - # state - image = api_node.get('image', None) - image_id = image.get('id', None) if image else None - - return Node( - id=api_node['id'], - name=api_node['name'], - state=self.NODE_STATE_MAP.get(api_node['status'], - NodeState.UNKNOWN), - public_ips=public_ips, - private_ips=private_ips, - driver=self, - extra=dict( - hostId=api_node['hostId'], - access_ip=api_node.get('accessIPv4'), - # Docs says "tenantId", but actual is "tenant_id". *sigh* - # Best handle both. - tenantId=api_node.get('tenant_id') or api_node['tenantId'], - imageId=image_id, - flavorId=api_node['flavor']['id'], - uri=next(link['href'] for link in api_node['links'] if - link['rel'] == 'self'), - metadata=api_node['metadata'], - password=api_node.get('adminPass', None), - created=api_node['created'], - updated=api_node['updated'], - key_name=api_node.get('key_name', None), - disk_config=api_node.get('OS-DCF:diskConfig', None), - availability_zone=api_node.get('OS-EXT-AZ:availability_zone', - None), - ), - ) - - def _to_volume(self, api_node): - if 'volume' in api_node: - api_node = api_node['volume'] - return StorageVolume( - id=api_node['id'], - name=api_node['displayName'], - size=api_node['size'], - driver=self, - extra={ - 'description': api_node['displayDescription'], - 'attachments': [att for att in api_node['attachments'] if att], - } - ) - - def _to_snapshot(self, data): - if 'snapshot' in data: - data = data['snapshot'] - - volume_id = data.get('volume_id', data.get('volumeId', None)) - display_name = data.get('display_name', data.get('displayName', None)) - created_at = data.get('created_at', data.get('createdAt', None)) - description = data.get('display_description', - data.get('displayDescription', None)) - status = data.get('status', None) - - extra = {'volume_id': volume_id, - 'name': display_name, - 'created': created_at, - 'description': description, - 'status': status} - - snapshot = VolumeSnapshot(id=data['id'], driver=self, - size=data['size'], extra=extra) - return snapshot - - def _to_size(self, api_flavor, price=None, bandwidth=None): - # if provider-specific subclasses can get better values for - # price/bandwidth, then can pass them in when they super(). - if not price: - price = self._get_size_price(str(api_flavor['id'])) - - return OpenStackNodeSize( - id=api_flavor['id'], - name=api_flavor['name'], - ram=api_flavor['ram'], - disk=api_flavor['disk'], - vcpus=api_flavor['vcpus'], - bandwidth=bandwidth, - price=price, - driver=self, - ) - - def _get_size_price(self, size_id): - try: - return get_size_price( - driver_type='compute', - driver_name=self.api_name, - size_id=size_id, - ) - except KeyError: - return(0.0) - - def _extract_image_id_from_url(self, location_header): - path = urlparse.urlparse(location_header).path - image_id = path.split('/')[-1] - return image_id - - def ex_rescue(self, node, password=None): - # Requires Rescue Mode extension - """ - Rescue a node - - :param node: node - :type node: :class:`Node` - - :param password: password - :type password: ``str`` - - :rtype: :class:`Node` - """ - if password: - resp = self._node_action(node, 'rescue', adminPass=password) - else: - resp = self._node_action(node, 'rescue') - password = json.loads(resp.body)['adminPass'] - node.extra['password'] = password - return node - - def ex_unrescue(self, node): - """ - Unrescue a node - - :param node: node - :type node: :class:`Node` - - :rtype: ``bool`` - """ - resp = self._node_action(node, 'unrescue') - return resp.status == httplib.ACCEPTED - - def _to_floating_ip_pools(self, obj): - pool_elements = obj['floating_ip_pools'] - return [self._to_floating_ip_pool(pool) for pool in pool_elements] - - def _to_floating_ip_pool(self, obj): - return OpenStack_1_1_FloatingIpPool(obj['name'], self.connection) - - def ex_list_floating_ip_pools(self): - """ - List available floating IP pools - - :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpPool` - """ - return self._to_floating_ip_pools( - self.connection.request('/os-floating-ip-pools').object) - - def _to_floating_ips(self, obj): - ip_elements = obj['floating_ips'] - return [self._to_floating_ip(ip) for ip in ip_elements] - - def _to_floating_ip(self, obj): - return OpenStack_1_1_FloatingIpAddress(id=obj['id'], - ip_address=obj['ip'], - pool=None, - node_id=obj['instance_id'], - driver=self) - - def ex_list_floating_ips(self): - """ - List floating IPs - - :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpAddress` - """ - return self._to_floating_ips( - self.connection.request('/os-floating-ips').object) - - def ex_get_floating_ip(self, ip): - """ - Get specified floating IP - - :param ip: floating IP to get - :type ip: ``str`` - - :rtype: :class:`OpenStack_1_1_FloatingIpAddress` - """ - floating_ips = self.ex_list_floating_ips() - ip_obj, = [x for x in floating_ips if x.ip_address == ip] - return ip_obj - - def ex_create_floating_ip(self): - """ - Create new floating IP - - :rtype: :class:`OpenStack_1_1_FloatingIpAddress` - """ - resp = self.connection.request('/os-floating-ips', - method='POST', - data={}) - data = resp.object['floating_ip'] - id = data['id'] - ip_address = data['ip'] - return OpenStack_1_1_FloatingIpAddress(id=id, - ip_address=ip_address, - pool=None, - node_id=None, - driver=self) - - def ex_delete_floating_ip(self, ip): - """ - Delete specified floating IP - - :param ip: floating IP to remove - :type ip: :class:`OpenStack_1_1_FloatingIpAddress` - - :rtype: ``bool`` - """ - resp = self.connection.request('/os-floating-ips/%s' % ip.id, - method='DELETE') - return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) - - def ex_attach_floating_ip_to_node(self, node, ip): - """ - Attach the floating IP to the node - - :param node: node - :type node: :class:`Node` - - :param ip: floating IP to attach - :type ip: ``str`` or :class:`OpenStack_1_1_FloatingIpAddress` - - :rtype: ``bool`` - """ - address = ip.ip_address if hasattr(ip, 'ip_address') else ip - data = { - 'addFloatingIp': {'address': address} - } - resp = self.connection.request('/servers/%s/action' % node.id, - method='POST', data=data) - return resp.status == httplib.ACCEPTED - - def ex_detach_floating_ip_from_node(self, node, ip): - """ - Detach the floating IP from the node - - :param node: node - :type node: :class:`Node` - - :param ip: floating IP to remove - :type ip: ``str`` or :class:`OpenStack_1_1_FloatingIpAddress` - - :rtype: ``bool`` - """ - address = ip.ip_address if hasattr(ip, 'ip_address') else ip - data = { - 'removeFloatingIp': {'address': address} - } - resp = self.connection.request('/servers/%s/action' % node.id, - method='POST', data=data) - return resp.status == httplib.ACCEPTED - - def ex_get_metadata_for_node(self, node): - """ - Return the metadata associated with the node. - - :param node: Node instance - :type node: :class:`Node` - - :return: A dictionary or other mapping of strings to strings, - associating tag names with tag values. - :type tags: ``dict`` - """ - return node.extra['metadata'] - - def ex_pause_node(self, node): - uri = '/servers/%s/action' % (node.id) - data = {'pause': None} - resp = self.connection.request(uri, method='POST', data=data) - return resp.status == httplib.ACCEPTED - - def ex_unpause_node(self, node): - uri = '/servers/%s/action' % (node.id) - data = {'unpause': None} - resp = self.connection.request(uri, method='POST', data=data) - return resp.status == httplib.ACCEPTED - - def ex_suspend_node(self, node): - uri = '/servers/%s/action' % (node.id) - data = {'suspend': None} - resp = self.connection.request(uri, method='POST', data=data) - return resp.status == httplib.ACCEPTED - - def ex_resume_node(self, node): - uri = '/servers/%s/action' % (node.id) - data = {'resume': None} - resp = self.connection.request(uri, method='POST', data=data) - return resp.status == httplib.ACCEPTED - - -class OpenStack_1_1_FloatingIpPool(object): - """ - Floating IP Pool info. - """ - - def __init__(self, name, connection): - self.name = name - self.connection = connection - - def list_floating_ips(self): - """ - List floating IPs in the pool - - :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpAddress` - """ - return self._to_floating_ips( - self.connection.request('/os-floating-ips').object) - - def _to_floating_ips(self, obj): - ip_elements = obj['floating_ips'] - return [self._to_floating_ip(ip) for ip in ip_elements] - - def _to_floating_ip(self, obj): - return OpenStack_1_1_FloatingIpAddress(id=obj['id'], - ip_address=obj['ip'], - pool=self, - node_id=obj['instance_id'], - driver=self.connection.driver) - - def get_floating_ip(self, ip): - """ - Get specified floating IP from the pool - - :param ip: floating IP to get - :type ip: ``str`` - - :rtype: :class:`OpenStack_1_1_FloatingIpAddress` - """ - ip_obj, = [x for x in self.list_floating_ips() if x.ip_address == ip] - return ip_obj - - def create_floating_ip(self): - """ - Create new floating IP in the pool - - :rtype: :class:`OpenStack_1_1_FloatingIpAddress` - """ - resp = self.connection.request('/os-floating-ips', - method='POST', - data={'pool': self.name}) - data = resp.object['floating_ip'] - id = data['id'] - ip_address = data['ip'] - return OpenStack_1_1_FloatingIpAddress(id=id, - ip_address=ip_address, - pool=self, - node_id=None, - driver=self.connection.driver) - - def delete_floating_ip(self, ip): - """ - Delete specified floating IP from the pool - - :param ip: floating IP to remove - :type ip::class:`OpenStack_1_1_FloatingIpAddress` - - :rtype: ``bool`` - """ - resp = self.connection.request('/os-floating-ips/%s' % ip.id, - method='DELETE') - return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) - - def __repr__(self): - return ('<OpenStack_1_1_FloatingIpPool: name=%s>' % self.name) - - -class OpenStack_1_1_FloatingIpAddress(object): - """ - Floating IP info. - """ - - def __init__(self, id, ip_address, pool, node_id=None, driver=None): - self.id = str(id) - self.ip_address = ip_address - self.pool = pool - self.node_id = node_id - self.driver = driver - - def delete(self): - """ - Delete this floating IP - - :rtype: ``bool`` - """ - if self.pool is not None: - return self.pool.delete_floating_ip(self) - elif self.driver is not None: - return self.driver.ex_delete_floating_ip(self) - - def __repr__(self): - return ('<OpenStack_1_1_FloatingIpAddress: id=%s, ip_addr=%s,' - ' pool=%s, driver=%s>' - % (self.id, self.ip_address, self.pool, self.driver)) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/opsource.py b/awx/lib/site-packages/libcloud/compute/drivers/opsource.py deleted file mode 100644 index d40155c0e2..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/opsource.py +++ /dev/null @@ -1,620 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Opsource Driver -""" - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from base64 import b64encode - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -from libcloud.compute.base import NodeDriver, Node -from libcloud.compute.base import NodeSize, NodeImage, NodeLocation -from libcloud.common.types import LibcloudError, InvalidCredsError -from libcloud.common.base import ConnectionUserAndKey, XmlResponse -from libcloud.utils.xml import fixxpath, findtext, findall -from libcloud.compute.types import NodeState, Provider - -# Roadmap / TODO: -# -# 0.1 - Basic functionality: create, delete, start, stop, reboot - servers -# (base OS images only, no customer images supported yet) -# x implement list_nodes() -# x implement create_node() (only support Base OS images, -# no customer images yet) -# x implement reboot() -# x implement destroy_node() -# x implement list_sizes() -# x implement list_images() (only support Base OS images, -# no customer images yet) -# x implement list_locations() -# x implement ex_* extension functions for opsource-specific featurebody -# x ex_graceful_shutdown -# x ex_start_node -# x ex_power_off -# x ex_list_networks (needed for create_node()) -# x refactor: switch to using fixxpath() from the vcloud driver for -# dealing with xml namespace tags -# x refactor: move some functionality from OpsourceConnection.request() -# method into new .request_with_orgId() method -# x add OpsourceStatus object support to: -# x _to_node() -# x _to_network() -# x implement test cases -# -# 0.2 - Support customer images (snapshots) and server modification functions -# - support customer-created images: -# - list deployed customer images (in list_images() ?) -# - list pending customer images (in list_images() ?) -# - delete customer images -# - modify customer images -# - add "pending-servers" in list_nodes() -# - implement various ex_* extension functions for opsource-specific -# features -# - ex_modify_server() -# - ex_add_storage_to_server() -# - ex_snapshot_server() (create's customer image) -# -# 0.3 - support Network API -# 0.4 - Support VIP/Load-balancing API -# 0.5 - support Files Account API -# 0.6 - support Reports API -# 1.0 - Opsource 0.9 API feature complete, tested - -# setup a few variables to represent all of the opsource cloud namespaces -NAMESPACE_BASE = "http://oec.api.opsource.net/schemas" -ORGANIZATION_NS = NAMESPACE_BASE + "/organization" -SERVER_NS = NAMESPACE_BASE + "/server" -NETWORK_NS = NAMESPACE_BASE + "/network" -DIRECTORY_NS = NAMESPACE_BASE + "/directory" -RESET_NS = NAMESPACE_BASE + "/reset" -VIP_NS = NAMESPACE_BASE + "/vip" -IMAGEIMPORTEXPORT_NS = NAMESPACE_BASE + "/imageimportexport" -DATACENTER_NS = NAMESPACE_BASE + "/datacenter" -SUPPORT_NS = NAMESPACE_BASE + "/support" -GENERAL_NS = NAMESPACE_BASE + "/general" -IPPLAN_NS = NAMESPACE_BASE + "/ipplan" -WHITELABEL_NS = NAMESPACE_BASE + "/whitelabel" - - -class OpsourceResponse(XmlResponse): - - def parse_error(self): - if self.status == httplib.UNAUTHORIZED: - raise InvalidCredsError(self.body) - elif self.status == httplib.FORBIDDEN: - raise InvalidCredsError(self.body) - - body = self.parse_body() - - if self.status == httplib.BAD_REQUEST: - code = findtext(body, 'resultCode', SERVER_NS) - message = findtext(body, 'resultDetail', SERVER_NS) - raise OpsourceAPIException(code, - message, - driver=OpsourceNodeDriver) - - return self.body - - -class OpsourceAPIException(LibcloudError): - def __init__(self, code, msg, driver): - self.code = code - self.msg = msg - self.driver = driver - - def __str__(self): - return "%s: %s" % (self.code, self.msg) - - def __repr__(self): - return ("<OpsourceAPIException: code='%s', msg='%s'>" % - (self.code, self.msg)) - - -class OpsourceConnection(ConnectionUserAndKey): - """ - Connection class for the Opsource driver - """ - - host = 'api.opsourcecloud.net' - api_path = '/oec' - api_version = '0.9' - _orgId = None - responseCls = OpsourceResponse - - allow_insecure = False - - def add_default_headers(self, headers): - headers['Authorization'] = \ - ('Basic %s' % b64encode(b('%s:%s' % (self.user_id, - self.key))).decode('utf-8')) - return headers - - def request(self, action, params=None, data='', - headers=None, method='GET'): - action = "%s/%s/%s" % (self.api_path, self.api_version, action) - - return super(OpsourceConnection, self).request( - action=action, - params=params, data=data, - method=method, headers=headers) - - def request_with_orgId(self, action, params=None, data='', - headers=None, method='GET'): - action = "%s/%s" % (self.get_resource_path(), action) - - return super(OpsourceConnection, self).request( - action=action, - params=params, data=data, - method=method, headers=headers) - - def get_resource_path(self): - """ - This method returns a resource path which is necessary for referencing - resources that require a full path instead of just an ID, such as - networks, and customer snapshots. - """ - return ("%s/%s/%s" % (self.api_path, self.api_version, - self._get_orgId())) - - def _get_orgId(self): - """ - Send the /myaccount API request to opsource cloud and parse the - 'orgId' from the XML response object. We need the orgId to use most - of the other API functions - """ - if self._orgId is None: - body = self.request('myaccount').object - self._orgId = findtext(body, 'orgId', DIRECTORY_NS) - return self._orgId - - -class OpsourceStatus(object): - """ - Opsource API pending operation status class - action, requestTime, username, numberOfSteps, updateTime, - step.name, step.number, step.percentComplete, failureReason, - """ - def __init__(self, action=None, requestTime=None, userName=None, - numberOfSteps=None, updateTime=None, step_name=None, - step_number=None, step_percentComplete=None, - failureReason=None): - self.action = action - self.requestTime = requestTime - self.userName = userName - self.numberOfSteps = numberOfSteps - self.updateTime = updateTime - self.step_name = step_name - self.step_number = step_number - self.step_percentComplete = step_percentComplete - self.failureReason = failureReason - - def __repr__(self): - return (('<OpsourceStatus: action=%s, requestTime=%s, userName=%s, ' - 'numberOfSteps=%s, updateTime=%s, step_name=%s, ' - 'step_number=%s, step_percentComplete=%s, ' - 'failureReason=%s') - % (self.action, self.requestTime, self.userName, - self.numberOfSteps, self.updateTime, self.step_name, - self.step_number, self.step_percentComplete, - self.failureReason)) - - -class OpsourceNetwork(object): - """ - Opsource network with location. - """ - - def __init__(self, id, name, description, location, privateNet, - multicast, status): - self.id = str(id) - self.name = name - self.description = description - self.location = location - self.privateNet = privateNet - self.multicast = multicast - self.status = status - - def __repr__(self): - return (('<OpsourceNetwork: id=%s, name=%s, description=%s, ' - 'location=%s, privateNet=%s, multicast=%s>') - % (self.id, self.name, self.description, self.location, - self.privateNet, self.multicast)) - - -class OpsourceNodeDriver(NodeDriver): - """ - Opsource node driver. - """ - - connectionCls = OpsourceConnection - name = 'Opsource' - website = 'http://www.opsource.net/' - type = Provider.OPSOURCE - features = {'create_node': ['password']} - - def create_node(self, **kwargs): - """ - Create a new opsource node - - :keyword name: String with a name for this new node (required) - :type name: ``str`` - - :keyword image: OS Image to boot on node. (required) - :type image: :class:`NodeImage` - - :keyword auth: Initial authentication information for the - node (required) - :type auth: :class:`NodeAuthPassword` - - :keyword ex_description: description for this node (required) - :type ex_description: ``str`` - - :keyword ex_network: Network to create the node within (required) - :type ex_network: :class:`OpsourceNetwork` - - :keyword ex_isStarted: Start server after creation? default - true (required) - :type ex_isStarted: ``bool`` - - :return: The newly created :class:`Node`. NOTE: Opsource does not - provide a - way to determine the ID of the server that was just created, - so the returned :class:`Node` is not guaranteed to be the same - one that was created. This is only the case when multiple - nodes with the same name exist. - :rtype: :class:`Node` - """ - name = kwargs['name'] - image = kwargs['image'] - - # XXX: Node sizes can be adjusted after a node is created, but - # cannot be set at create time because size is part of the - # image definition. - password = None - auth = self._get_and_check_auth(kwargs.get('auth')) - password = auth.password - - ex_description = kwargs.get('ex_description', '') - ex_isStarted = kwargs.get('ex_isStarted', True) - - ex_network = kwargs.get('ex_network') - if not isinstance(ex_network, OpsourceNetwork): - raise ValueError('ex_network must be of OpsourceNetwork type') - vlanResourcePath = "%s/%s" % (self.connection.get_resource_path(), - ex_network.id) - - imageResourcePath = None - if 'resourcePath' in image.extra: - imageResourcePath = image.extra['resourcePath'] - else: - imageResourcePath = "%s/%s" % (self.connection.get_resource_path(), - image.id) - - server_elm = ET.Element('Server', {'xmlns': SERVER_NS}) - ET.SubElement(server_elm, "name").text = name - ET.SubElement(server_elm, "description").text = ex_description - ET.SubElement(server_elm, "vlanResourcePath").text = vlanResourcePath - ET.SubElement(server_elm, "imageResourcePath").text = imageResourcePath - ET.SubElement(server_elm, "administratorPassword").text = password - ET.SubElement(server_elm, "isStarted").text = str(ex_isStarted) - - self.connection.request_with_orgId('server', - method='POST', - data=ET.tostring(server_elm)).object - - # XXX: return the last node in the list that has a matching name. this - # is likely but not guaranteed to be the node we just created - # because opsource allows multiple nodes to have the same name - node = list(filter(lambda x: x.name == name, self.list_nodes()))[-1] - - if getattr(auth, "generated", False): - node.extra['password'] = auth.password - - return node - - def destroy_node(self, node): - body = self.connection.request_with_orgId( - 'server/%s?delete' % (node.id)).object - - result = findtext(body, 'result', GENERAL_NS) - return result == 'SUCCESS' - - def reboot_node(self, node): - body = self.connection.request_with_orgId( - 'server/%s?restart' % (node.id)).object - result = findtext(body, 'result', GENERAL_NS) - return result == 'SUCCESS' - - def list_nodes(self): - nodes = self._to_nodes( - self.connection.request_with_orgId('server/deployed').object) - nodes.extend(self._to_nodes( - self.connection.request_with_orgId('server/pendingDeploy').object)) - return nodes - - def list_images(self, location=None): - """ - return a list of available images - Currently only returns the default 'base OS images' provided by - opsource. Customer images (snapshots) are not yet supported. - - @inherits: :class:`NodeDriver.list_images` - """ - return self._to_base_images( - self.connection.request('base/image').object) - - def list_sizes(self, location=None): - return [ - NodeSize(id=1, - name="default", - ram=0, - disk=0, - bandwidth=0, - price=0, - driver=self.connection.driver), - ] - - def list_locations(self): - """ - list locations (datacenters) available for instantiating servers and - networks. - - @inherits: :class:`NodeDriver.list_locations` - """ - return self._to_locations( - self.connection.request_with_orgId('datacenter').object) - - def list_networks(self, location=None): - """ - List networks deployed across all data center locations for your - organization. The response includes the location of each network. - - - :keyword location: The location - :type location: :class:`NodeLocation` - - :return: a list of OpsourceNetwork objects - :rtype: ``list`` of :class:`OpsourceNetwork` - """ - return self._to_networks( - self.connection.request_with_orgId('networkWithLocation').object) - - def _to_base_images(self, object): - images = [] - for element in object.findall(fixxpath("ServerImage", SERVER_NS)): - images.append(self._to_base_image(element)) - - return images - - def _to_base_image(self, element): - # Eventually we will probably need multiple _to_image() functions - # that parse <ServerImage> differently than <DeployedImage>. - # DeployedImages are customer snapshot images, and ServerImages are - # 'base' images provided by opsource - location_id = findtext(element, 'location', SERVER_NS) - location = self.ex_get_location_by_id(location_id) - - extra = { - 'description': findtext(element, 'description', SERVER_NS), - 'OS_type': findtext(element, 'operatingSystem/type', SERVER_NS), - 'OS_displayName': findtext(element, 'operatingSystem/displayName', - SERVER_NS), - 'cpuCount': findtext(element, 'cpuCount', SERVER_NS), - 'resourcePath': findtext(element, 'resourcePath', SERVER_NS), - 'memory': findtext(element, 'memory', SERVER_NS), - 'osStorage': findtext(element, 'osStorage', SERVER_NS), - 'additionalStorage': findtext(element, 'additionalStorage', - SERVER_NS), - 'created': findtext(element, 'created', SERVER_NS), - 'location': location, - } - - return NodeImage(id=str(findtext(element, 'id', SERVER_NS)), - name=str(findtext(element, 'name', SERVER_NS)), - extra=extra, - driver=self.connection.driver) - - def ex_start_node(self, node): - """ - Powers on an existing deployed server - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - body = self.connection.request_with_orgId( - 'server/%s?start' % node.id).object - result = findtext(body, 'result', GENERAL_NS) - return result == 'SUCCESS' - - def ex_shutdown_graceful(self, node): - """ - This function will attempt to "gracefully" stop a server by - initiating a shutdown sequence within the guest operating system. - A successful response on this function means the system has - successfully passed the request into the operating system. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - body = self.connection.request_with_orgId( - 'server/%s?shutdown' % (node.id)).object - result = findtext(body, 'result', GENERAL_NS) - return result == 'SUCCESS' - - def ex_power_off(self, node): - """ - This function will abruptly power-off a server. Unlike - ex_shutdown_graceful, success ensures the node will stop but some OS - and application configurations may be adversely affected by the - equivalent of pulling the power plug out of the machine. - - :param node: Node which should be used - :type node: :class:`Node` - - :rtype: ``bool`` - """ - body = self.connection.request_with_orgId( - 'server/%s?poweroff' % node.id).object - result = findtext(body, 'result', GENERAL_NS) - return result == 'SUCCESS' - - def ex_list_networks(self): - """ - List networks deployed across all data center locations for your - organization. The response includes the location of each network. - - :return: a list of OpsourceNetwork objects - :rtype: ``list`` of :class:`OpsourceNetwork` - """ - response = self.connection.request_with_orgId('networkWithLocation') \ - .object - return self._to_networks(response) - - def ex_get_location_by_id(self, id): - """ - Get location by ID. - - :param id: ID of the node location which should be used - :type id: ``str`` - - :rtype: :class:`NodeLocation` - """ - location = None - if id is not None: - location = list( - filter(lambda x: x.id == id, self.list_locations()))[0] - return location - - def _to_networks(self, object): - networks = [] - for element in findall(object, 'network', NETWORK_NS): - networks.append(self._to_network(element)) - - return networks - - def _to_network(self, element): - multicast = False - if findtext(element, 'multicast', NETWORK_NS) == 'true': - multicast = True - - status = self._to_status(element.find(fixxpath('status', NETWORK_NS))) - - location_id = findtext(element, 'location', NETWORK_NS) - location = self.ex_get_location_by_id(location_id) - - return OpsourceNetwork(id=findtext(element, 'id', NETWORK_NS), - name=findtext(element, 'name', NETWORK_NS), - description=findtext(element, 'description', - NETWORK_NS), - location=location, - privateNet=findtext(element, 'privateNet', - NETWORK_NS), - multicast=multicast, - status=status) - - def _to_locations(self, object): - locations = [] - for element in object.findall(fixxpath('datacenter', DATACENTER_NS)): - locations.append(self._to_location(element)) - - return locations - - def _to_location(self, element): - l = NodeLocation(id=findtext(element, 'location', DATACENTER_NS), - name=findtext(element, 'displayName', DATACENTER_NS), - country=findtext(element, 'country', DATACENTER_NS), - driver=self) - return l - - def _to_nodes(self, object): - node_elements = object.findall(fixxpath('DeployedServer', SERVER_NS)) - node_elements.extend(object.findall( - fixxpath('PendingDeployServer', SERVER_NS))) - return [self._to_node(el) for el in node_elements] - - def _to_node(self, element): - if findtext(element, 'isStarted', SERVER_NS) == 'true': - state = NodeState.RUNNING - else: - state = NodeState.TERMINATED - - status = self._to_status(element.find(fixxpath('status', SERVER_NS))) - - extra = { - 'description': findtext(element, 'description', SERVER_NS), - 'sourceImageId': findtext(element, 'sourceImageId', SERVER_NS), - 'networkId': findtext(element, 'networkId', SERVER_NS), - 'machineName': findtext(element, 'machineName', SERVER_NS), - 'deployedTime': findtext(element, 'deployedTime', SERVER_NS), - 'cpuCount': findtext(element, 'machineSpecification/cpuCount', - SERVER_NS), - 'memoryMb': findtext(element, 'machineSpecification/memoryMb', - SERVER_NS), - 'osStorageGb': findtext(element, - 'machineSpecification/osStorageGb', - SERVER_NS), - 'additionalLocalStorageGb': findtext( - element, 'machineSpecification/additionalLocalStorageGb', - SERVER_NS), - 'OS_type': findtext(element, - 'machineSpecification/operatingSystem/type', - SERVER_NS), - 'OS_displayName': findtext( - element, 'machineSpecification/operatingSystem/displayName', - SERVER_NS), - 'status': status, - } - - public_ip = findtext(element, 'publicIpAddress', SERVER_NS) - - n = Node(id=findtext(element, 'id', SERVER_NS), - name=findtext(element, 'name', SERVER_NS), - state=state, - public_ips=[public_ip] if public_ip is not None else [], - private_ips=findtext(element, 'privateIpAddress', SERVER_NS), - driver=self.connection.driver, - extra=extra) - return n - - def _to_status(self, element): - if element is None: - return OpsourceStatus() - s = OpsourceStatus(action=findtext(element, 'action', SERVER_NS), - requestTime=findtext(element, 'requestTime', - SERVER_NS), - userName=findtext(element, 'userName', - SERVER_NS), - numberOfSteps=findtext(element, 'numberOfSteps', - SERVER_NS), - step_name=findtext(element, 'step/name', - SERVER_NS), - step_number=findtext(element, 'step_number', - SERVER_NS), - step_percentComplete=findtext( - element, 'step/percentComplete', SERVER_NS), - failureReason=findtext(element, 'failureReason', - SERVER_NS)) - return s diff --git a/awx/lib/site-packages/libcloud/compute/drivers/rackspace.py b/awx/lib/site-packages/libcloud/compute/drivers/rackspace.py deleted file mode 100644 index 367facd024..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/rackspace.py +++ /dev/null @@ -1,230 +0,0 @@ -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Rackspace driver -""" -from libcloud.compute.types import Provider, LibcloudError -from libcloud.compute.base import NodeLocation, VolumeSnapshot -from libcloud.compute.drivers.openstack import OpenStack_1_0_Connection,\ - OpenStack_1_0_NodeDriver, OpenStack_1_0_Response -from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection,\ - OpenStack_1_1_NodeDriver - -from libcloud.common.rackspace import AUTH_URL - - -ENDPOINT_ARGS_MAP = { - 'dfw': {'service_type': 'compute', - 'name': 'cloudServersOpenStack', - 'region': 'DFW'}, - 'ord': {'service_type': 'compute', - 'name': 'cloudServersOpenStack', - 'region': 'ORD'}, - 'iad': {'service_type': 'compute', - 'name': 'cloudServersOpenStack', - 'region': 'IAD'}, - 'lon': {'service_type': 'compute', - 'name': 'cloudServersOpenStack', - 'region': 'LON'}, - 'syd': {'service_type': 'compute', - 'name': 'cloudServersOpenStack', - 'region': 'SYD'}, - 'hkg': {'service_type': 'compute', - 'name': 'cloudServersOpenStack', - 'region': 'HKG'}, - -} - - -class RackspaceFirstGenConnection(OpenStack_1_0_Connection): - """ - Connection class for the Rackspace first-gen driver. - """ - responseCls = OpenStack_1_0_Response - XML_NAMESPACE = 'http://docs.rackspacecloud.com/servers/api/v1.0' - auth_url = AUTH_URL - _auth_version = '2.0' - cache_busting = True - - def __init__(self, *args, **kwargs): - self.region = kwargs.pop('region', None) - super(RackspaceFirstGenConnection, self).__init__(*args, **kwargs) - - def get_endpoint(self): - ep = {} - - if '2.0' in self._auth_version: - ep = self.service_catalog.get_endpoint(service_type='compute', - name='cloudServers') - else: - raise LibcloudError( - 'Auth version "%s" not supported' % (self._auth_version)) - - public_url = ep.get('publicURL', None) - - if not public_url: - raise LibcloudError('Could not find specified endpoint') - - # This is a nasty hack, but it's required because of how the - # auth system works. - # Old US accounts can access UK API endpoint, but they don't - # have this endpoint in the service catalog. Same goes for the - # old UK accounts and US endpoint. - if self.region == 'us': - # Old UK account, which only have uk endpoint in the catalog - public_url = public_url.replace('https://lon.servers.api', - 'https://servers.api') - elif self.region == 'uk': - # Old US account, which only has us endpoints in the catalog - public_url = public_url.replace('https://servers.api', - 'https://lon.servers.api') - - return public_url - - -class RackspaceFirstGenNodeDriver(OpenStack_1_0_NodeDriver): - name = 'Rackspace Cloud (First Gen)' - website = 'http://www.rackspace.com' - connectionCls = RackspaceFirstGenConnection - type = Provider.RACKSPACE_FIRST_GEN - api_name = 'rackspace' - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='us', **kwargs): - """ - @inherits: :class:`NodeDriver.__init__` - - :param region: Region ID which should be used - :type region: ``str`` - """ - if region not in ['us', 'uk']: - raise ValueError('Invalid region: %s' % (region)) - - super(RackspaceFirstGenNodeDriver, self).__init__(key=key, - secret=secret, - secure=secure, - host=host, - port=port, - region=region, - **kwargs) - - def list_locations(self): - """ - Lists available locations - - Locations cannot be set or retrieved via the API, but currently - there are two locations, DFW and ORD. - - @inherits: :class:`OpenStack_1_0_NodeDriver.list_locations` - """ - if self.region == 'us': - locations = [NodeLocation(0, "Rackspace DFW1/ORD1", 'US', self)] - elif self.region == 'uk': - locations = [NodeLocation(0, 'Rackspace UK London', 'UK', self)] - - return locations - - def _ex_connection_class_kwargs(self): - kwargs = self.openstack_connection_kwargs() - kwargs['region'] = self.region - return kwargs - - -class RackspaceConnection(OpenStack_1_1_Connection): - """ - Connection class for the Rackspace next-gen OpenStack base driver. - """ - - auth_url = AUTH_URL - _auth_version = '2.0' - - def __init__(self, *args, **kwargs): - self.region = kwargs.pop('region', None) - self.get_endpoint_args = kwargs.pop('get_endpoint_args', None) - super(RackspaceConnection, self).__init__(*args, **kwargs) - - def get_endpoint(self): - if not self.get_endpoint_args: - raise LibcloudError( - 'RackspaceConnection must have get_endpoint_args set') - - if '2.0' in self._auth_version: - ep = self.service_catalog.get_endpoint(**self.get_endpoint_args) - else: - raise LibcloudError( - 'Auth version "%s" not supported' % (self._auth_version)) - - public_url = ep.get('publicURL', None) - - if not public_url: - raise LibcloudError('Could not find specified endpoint') - - return public_url - - -class RackspaceNodeDriver(OpenStack_1_1_NodeDriver): - name = 'Rackspace Cloud (Next Gen)' - website = 'http://www.rackspace.com' - connectionCls = RackspaceConnection - type = Provider.RACKSPACE - - _networks_url_prefix = '/os-networksv2' - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='dfw', **kwargs): - """ - @inherits: :class:`NodeDriver.__init__` - - :param region: ID of the region which should be used. - :type region: ``str`` - """ - valid_regions = ENDPOINT_ARGS_MAP.keys() - - if region not in valid_regions: - raise ValueError('Invalid region: %s' % (region)) - - if region == 'lon': - self.api_name = 'rackspacenovalon' - elif region == 'syd': - self.api_name = 'rackspacenovasyd' - else: - self.api_name = 'rackspacenovaus' - - super(RackspaceNodeDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, - region=region, - **kwargs) - - def _to_snapshot(self, api_node): - if 'snapshot' in api_node: - api_node = api_node['snapshot'] - - extra = {'volume_id': api_node['volumeId'], - 'name': api_node['displayName'], - 'created': api_node['createdAt'], - 'description': api_node['displayDescription'], - 'status': api_node['status']} - - snapshot = VolumeSnapshot(id=api_node['id'], driver=self, - size=api_node['size'], - extra=extra) - return snapshot - - def _ex_connection_class_kwargs(self): - endpoint_args = ENDPOINT_ARGS_MAP[self.region] - kwargs = self.openstack_connection_kwargs() - kwargs['region'] = self.region - kwargs['get_endpoint_args'] = endpoint_args - return kwargs diff --git a/awx/lib/site-packages/libcloud/compute/drivers/rimuhosting.py b/awx/lib/site-packages/libcloud/compute/drivers/rimuhosting.py deleted file mode 100644 index acde574336..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/rimuhosting.py +++ /dev/null @@ -1,337 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -RimuHosting Driver -""" -try: - import simplejson as json -except ImportError: - import json - -from libcloud.common.base import ConnectionKey, JsonResponse -from libcloud.common.types import InvalidCredsError -from libcloud.compute.types import Provider, NodeState -from libcloud.compute.base import NodeDriver, NodeSize, Node, NodeLocation -from libcloud.compute.base import NodeImage - -API_CONTEXT = '/r' -API_HOST = 'rimuhosting.com' - - -class RimuHostingException(Exception): - """ - Exception class for RimuHosting driver - """ - - def __str__(self): - return self.args[0] - - def __repr__(self): - return "<RimuHostingException '%s'>" % (self.args[0]) - - -class RimuHostingResponse(JsonResponse): - """ - Response Class for RimuHosting driver - """ - def success(self): - if self.status == 403: - raise InvalidCredsError() - return True - - def parse_body(self): - try: - js = super(RimuHostingResponse, self).parse_body() - keys = list(js.keys()) - if js[keys[0]]['response_type'] == "ERROR": - raise RimuHostingException( - js[keys[0]]['human_readable_message'] - ) - return js[keys[0]] - except KeyError: - raise RimuHostingException('Could not parse body: %s' - % (self.body)) - - -class RimuHostingConnection(ConnectionKey): - """ - Connection class for the RimuHosting driver - """ - - api_context = API_CONTEXT - host = API_HOST - port = 443 - responseCls = RimuHostingResponse - - def __init__(self, key, secure=True): - # override __init__ so that we can set secure of False for testing - ConnectionKey.__init__(self, key, secure) - - def add_default_headers(self, headers): - # We want JSON back from the server. Could be application/xml - # (but JSON is better). - headers['Accept'] = 'application/json' - # Must encode all data as json, or override this header. - headers['Content-Type'] = 'application/json' - - headers['Authorization'] = 'rimuhosting apikey=%s' % (self.key) - return headers - - def request(self, action, params=None, data='', headers=None, - method='GET'): - if not headers: - headers = {} - if not params: - params = {} - # Override this method to prepend the api_context - return ConnectionKey.request(self, self.api_context + action, - params, data, headers, method) - - -class RimuHostingNodeDriver(NodeDriver): - """ - RimuHosting node driver - """ - - type = Provider.RIMUHOSTING - name = 'RimuHosting' - website = 'http://rimuhosting.com/' - connectionCls = RimuHostingConnection - features = {'create_node': ['password']} - - def __init__(self, key, host=API_HOST, port=443, - api_context=API_CONTEXT, secure=True): - """ - :param key: API key (required) - :type key: ``str`` - - :param host: hostname for connection - :type host: ``str`` - - :param port: Override port used for connections. - :type port: ``int`` - - :param api_context: Optional API context. - :type api_context: ``str`` - - :param secure: Weither to use HTTPS or HTTP. - :type secure: ``bool`` - - :rtype: ``None`` - """ - # Pass in some extra vars so that - self.key = key - self.secure = secure - self.connection = self.connectionCls(key, secure) - self.connection.host = host - self.connection.api_context = api_context - self.connection.port = port - self.connection.driver = self - self.connection.connect() - - def _order_uri(self, node, resource): - # Returns the order uri with its resourse appended. - return "/orders/%s/%s" % (node.id, resource) - - # TODO: Get the node state. - def _to_node(self, order): - n = Node(id=order['slug'], - name=order['domain_name'], - state=NodeState.RUNNING, - public_ips=( - [order['allocated_ips']['primary_ip']] - + order['allocated_ips']['secondary_ips']), - private_ips=[], - driver=self.connection.driver, - extra={ - 'order_oid': order['order_oid'], - 'monthly_recurring_fee': order.get( - 'billing_info').get('monthly_recurring_fee')}) - return n - - def _to_size(self, plan): - return NodeSize( - id=plan['pricing_plan_code'], - name=plan['pricing_plan_description'], - ram=plan['minimum_memory_mb'], - disk=plan['minimum_disk_gb'], - bandwidth=plan['minimum_data_transfer_allowance_gb'], - price=plan['monthly_recurring_amt']['amt_usd'], - driver=self.connection.driver - ) - - def _to_image(self, image): - return NodeImage(id=image['distro_code'], - name=image['distro_description'], - driver=self.connection.driver) - - def list_sizes(self, location=None): - # Returns a list of sizes (aka plans) - # Get plans. Note this is really just for libcloud. - # We are happy with any size. - if location is None: - location = '' - else: - location = ";dc_location=%s" % (location.id) - - res = self.connection.request( - '/pricing-plans;server-type=VPS%s' % (location)).object - return list(map(lambda x: self._to_size(x), res['pricing_plan_infos'])) - - def list_nodes(self): - # Returns a list of Nodes - # Will only include active ones. - res = self.connection.request('/orders;include_inactive=N').object - return list(map(lambda x: self._to_node(x), res['about_orders'])) - - def list_images(self, location=None): - # Get all base images. - # TODO: add other image sources. (Such as a backup of a VPS) - # All Images are available for use at all locations - res = self.connection.request('/distributions').object - return list(map(lambda x: self._to_image(x), res['distro_infos'])) - - def reboot_node(self, node): - # Reboot - # PUT the state of RESTARTING to restart a VPS. - # All data is encoded as JSON - data = {'reboot_request': {'running_state': 'RESTARTING'}} - uri = self._order_uri(node, 'vps/running-state') - self.connection.request(uri, data=json.dumps(data), method='PUT') - # XXX check that the response was actually successful - return True - - def destroy_node(self, node): - # Shutdown a VPS. - uri = self._order_uri(node, 'vps') - self.connection.request(uri, method='DELETE') - # XXX check that the response was actually successful - return True - - def create_node(self, **kwargs): - """Creates a RimuHosting instance - - @inherits: :class:`NodeDriver.create_node` - - :keyword name: Must be a FQDN. e.g example.com. - :type name: ``str`` - - :keyword ex_billing_oid: If not set, - a billing method is automatically picked. - :type ex_billing_oid: ``str`` - - :keyword ex_host_server_oid: The host server to set the VPS up on. - :type ex_host_server_oid: ``str`` - - :keyword ex_vps_order_oid_to_clone: Clone another VPS to use as - the image for the new VPS. - :type ex_vps_order_oid_to_clone: ``str`` - - :keyword ex_num_ips: Number of IPs to allocate. Defaults to 1. - :type ex_num_ips: ``int`` - - :keyword ex_extra_ip_reason: Reason for needing the extra IPs. - :type ex_extra_ip_reason: ``str`` - - :keyword ex_memory_mb: Memory to allocate to the VPS. - :type ex_memory_mb: ``int`` - - :keyword ex_disk_space_mb: Diskspace to allocate to the VPS. - Defaults to 4096 (4GB). - :type ex_disk_space_mb: ``int`` - - :keyword ex_disk_space_2_mb: Secondary disk size allocation. - Disabled by default. - :type ex_disk_space_2_mb: ``int`` - - :keyword ex_control_panel: Control panel to install on the VPS. - :type ex_control_panel: ``str`` - """ - # Note we don't do much error checking in this because we - # expect the API to error out if there is a problem. - name = kwargs['name'] - image = kwargs['image'] - size = kwargs['size'] - - data = { - 'instantiation_options': { - 'domain_name': name, - 'distro': image.id - }, - 'pricing_plan_code': size.id, - 'vps_parameters': {} - } - - if 'ex_control_panel' in kwargs: - data['instantiation_options']['control_panel'] = \ - kwargs['ex_control_panel'] - - auth = self._get_and_check_auth(kwargs.get('auth')) - data['instantiation_options']['password'] = auth.password - - if 'ex_billing_oid' in kwargs: - # TODO check for valid oid. - data['billing_oid'] = kwargs['ex_billing_oid'] - - if 'ex_host_server_oid' in kwargs: - data['host_server_oid'] = kwargs['ex_host_server_oid'] - - if 'ex_vps_order_oid_to_clone' in kwargs: - data['vps_order_oid_to_clone'] = \ - kwargs['ex_vps_order_oid_to_clone'] - - if 'ex_num_ips' in kwargs and int(kwargs['ex_num_ips']) > 1: - if 'ex_extra_ip_reason' not in kwargs: - raise RimuHostingException( - 'Need an reason for having an extra IP') - else: - if 'ip_request' not in data: - data['ip_request'] = {} - data['ip_request']['num_ips'] = int(kwargs['ex_num_ips']) - data['ip_request']['extra_ip_reason'] = \ - kwargs['ex_extra_ip_reason'] - - if 'ex_memory_mb' in kwargs: - data['vps_parameters']['memory_mb'] = kwargs['ex_memory_mb'] - - if 'ex_disk_space_mb' in kwargs: - data['vps_parameters']['disk_space_mb'] = \ - kwargs['ex_disk_space_mb'] - - if 'ex_disk_space_2_mb' in kwargs: - data['vps_parameters']['disk_space_2_mb'] =\ - kwargs['ex_disk_space_2_mb'] - - # Don't send empty 'vps_parameters' attribute - if not data['vps_parameters']: - del data['vps_parameters'] - - res = self.connection.request( - '/orders/new-vps', - method='POST', - data=json.dumps({"new-vps": data}) - ).object - node = self._to_node(res['about_order']) - node.extra['password'] = \ - res['new_order_request']['instantiation_options']['password'] - return node - - def list_locations(self): - return [ - NodeLocation('DCAUCKLAND', "RimuHosting Auckland", 'NZ', self), - NodeLocation('DCDALLAS', "RimuHosting Dallas", 'US', self), - NodeLocation('DCLONDON', "RimuHosting London", 'GB', self), - NodeLocation('DCSYDNEY', "RimuHosting Sydney", 'AU', self), - ] diff --git a/awx/lib/site-packages/libcloud/compute/drivers/serverlove.py b/awx/lib/site-packages/libcloud/compute/drivers/serverlove.py deleted file mode 100644 index 2ba92a9560..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/serverlove.py +++ /dev/null @@ -1,83 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -ServerLove Driver -""" - -from libcloud.compute.types import Provider -from libcloud.compute.drivers.elasticstack import ElasticStackBaseNodeDriver -from libcloud.compute.drivers.elasticstack import ElasticStackBaseConnection - - -# API end-points -API_ENDPOINTS = { - 'uk-1': { - 'name': 'United Kingdom, Manchester', - 'country': 'United Kingdom', - 'host': 'api.z1-man.serverlove.com' - } -} - -# Default API end-point for the base connection class. -DEFAULT_ENDPOINT = 'uk-1' - -# Retrieved from http://www.serverlove.com/cloud-server-faqs/api-questions/ -STANDARD_DRIVES = { - '679f5f44-0be7-4745-a658-cccd4334c1aa': { - 'uuid': '679f5f44-0be7-4745-a658-cccd4334c1aa', - 'description': 'CentOS 5.5', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - '5f2e0e29-2937-42b9-b362-d2d07eddbdeb': { - 'uuid': '5f2e0e29-2937-42b9-b362-d2d07eddbdeb', - 'description': 'Ubuntu Linux 10.04', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - '5795b68f-ed26-4639-b41d-c93235062b6b': { - 'uuid': '5795b68f-ed26-4639-b41d-c93235062b6b', - 'description': 'Debian Linux 5', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - '41993a02-0b22-4e49-bb47-0aa8975217e4': { - 'uuid': '41993a02-0b22-4e49-bb47-0aa8975217e4', - 'description': 'Windows Server 2008 R2 Standard', - 'size_gunzipped': '15GB', - 'supports_deployment': False, - }, - '85623ca1-9c2a-4398-a771-9a43c347e86b': { - 'uuid': '85623ca1-9c2a-4398-a771-9a43c347e86b', - 'description': 'Windows Web Server 2008 R2', - 'size_gunzipped': '15GB', - 'supports_deployment': False, - } -} - - -class ServerLoveConnection(ElasticStackBaseConnection): - host = API_ENDPOINTS[DEFAULT_ENDPOINT]['host'] - - -class ServerLoveNodeDriver(ElasticStackBaseNodeDriver): - type = Provider.SERVERLOVE - api_name = 'serverlove' - website = 'http://www.serverlove.com/' - name = 'ServerLove' - connectionCls = ServerLoveConnection - features = {'create_node': ['generates_password']} - _standard_drives = STANDARD_DRIVES diff --git a/awx/lib/site-packages/libcloud/compute/drivers/skalicloud.py b/awx/lib/site-packages/libcloud/compute/drivers/skalicloud.py deleted file mode 100644 index c0b0d79404..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/skalicloud.py +++ /dev/null @@ -1,83 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -skalicloud Driver -""" - -from libcloud.compute.types import Provider -from libcloud.compute.drivers.elasticstack import ElasticStackBaseNodeDriver -from libcloud.compute.drivers.elasticstack import ElasticStackBaseConnection - - -# API end-points -API_ENDPOINTS = { - 'my-1': { - 'name': 'Malaysia, Kuala Lumpur', - 'country': 'Malaysia', - 'host': 'api.sdg-my.skalicloud.com' - } -} - -# Default API end-point for the base connection class. -DEFAULT_ENDPOINT = 'my-1' - -# Retrieved from http://www.skalicloud.com/cloud-api/ -STANDARD_DRIVES = { - '90aa51f2-15c0-4cff-81ee-e93aa20b9468': { - 'uuid': '90aa51f2-15c0-4cff-81ee-e93aa20b9468', - 'description': 'CentOS 5.5 -64bit', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - 'c144d7a7-e24b-48ab-954b-6b6ec514ed6f': { - 'uuid': 'c144d7a7-e24b-48ab-954b-6b6ec514ed6f', - 'description': 'Debian 5 -64bit', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - '3051699a-a536-4220-aeb5-67f2ec101a09': { - 'uuid': '3051699a-a536-4220-aeb5-67f2ec101a09', - 'description': 'Ubuntu Server 10.10 -64bit', - 'size_gunzipped': '1GB', - 'supports_deployment': True, - }, - '11c4c922-5ff8-4094-b06c-eb8ffaec1ea9': { - 'uuid': '11c4c922-5ff8-4094-b06c-eb8ffaec1ea9', - 'description': 'Windows 2008R2 Web Edition', - 'size_gunzipped': '13GB', - 'supports_deployment': False, - }, - '93bf390e-4f46-4252-a8bc-9d6d80e3f955': { - 'uuid': '93bf390e-4f46-4252-a8bc-9d6d80e3f955', - 'description': 'Windows Server 2008R2 Standard', - 'size_gunzipped': '13GB', - 'supports_deployment': False, - } -} - - -class SkaliCloudConnection(ElasticStackBaseConnection): - host = API_ENDPOINTS[DEFAULT_ENDPOINT]['host'] - - -class SkaliCloudNodeDriver(ElasticStackBaseNodeDriver): - type = Provider.SKALICLOUD - api_name = 'skalicloud' - name = 'skalicloud' - website = 'http://www.skalicloud.com/' - connectionCls = SkaliCloudConnection - features = {"create_node": ["generates_password"]} - _standard_drives = STANDARD_DRIVES diff --git a/awx/lib/site-packages/libcloud/compute/drivers/softlayer.py b/awx/lib/site-packages/libcloud/compute/drivers/softlayer.py deleted file mode 100644 index 4fe8cdd2e3..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/softlayer.py +++ /dev/null @@ -1,474 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Softlayer driver -""" - -import time - -from libcloud.common.base import ConnectionUserAndKey -from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.compute.types import Provider, NodeState -from libcloud.compute.base import NodeDriver, Node, NodeLocation, NodeSize, \ - NodeImage - -DEFAULT_DOMAIN = 'example.com' -DEFAULT_CPU_SIZE = 1 -DEFAULT_RAM_SIZE = 2048 -DEFAULT_DISK_SIZE = 100 - -DATACENTERS = { - 'hou02': {'country': 'US'}, - 'sea01': {'country': 'US', 'name': 'Seattle - West Coast U.S.'}, - 'wdc01': {'country': 'US', 'name': 'Washington, DC - East Coast U.S.'}, - 'dal01': {'country': 'US'}, - 'dal02': {'country': 'US'}, - 'dal04': {'country': 'US'}, - 'dal05': {'country': 'US', 'name': 'Dallas - Central U.S.'}, - 'dal06': {'country': 'US'}, - 'dal07': {'country': 'US'}, - 'sjc01': {'country': 'US', 'name': 'San Jose - West Coast U.S.'}, - 'sng01': {'country': 'SG', 'name': 'Singapore - Southeast Asia'}, - 'ams01': {'country': 'NL', 'name': 'Amsterdam - Western Europe'}, -} - -NODE_STATE_MAP = { - 'RUNNING': NodeState.RUNNING, - 'HALTED': NodeState.UNKNOWN, - 'PAUSED': NodeState.UNKNOWN, - 'INITIATING': NodeState.PENDING -} - -SL_BASE_TEMPLATES = [ - { - 'name': '1 CPU, 1GB ram, 25GB', - 'ram': 1024, - 'disk': 25, - 'cpus': 1, - }, { - 'name': '1 CPU, 1GB ram, 100GB', - 'ram': 1024, - 'disk': 100, - 'cpus': 1, - }, { - 'name': '1 CPU, 2GB ram, 100GB', - 'ram': 2 * 1024, - 'disk': 100, - 'cpus': 1, - }, { - 'name': '1 CPU, 4GB ram, 100GB', - 'ram': 4 * 1024, - 'disk': 100, - 'cpus': 1, - }, { - 'name': '2 CPU, 2GB ram, 100GB', - 'ram': 2 * 1024, - 'disk': 100, - 'cpus': 2, - }, { - 'name': '2 CPU, 4GB ram, 100GB', - 'ram': 4 * 1024, - 'disk': 100, - 'cpus': 2, - }, { - 'name': '2 CPU, 8GB ram, 100GB', - 'ram': 8 * 1024, - 'disk': 100, - 'cpus': 2, - }, { - 'name': '4 CPU, 4GB ram, 100GB', - 'ram': 4 * 1024, - 'disk': 100, - 'cpus': 4, - }, { - 'name': '4 CPU, 8GB ram, 100GB', - 'ram': 8 * 1024, - 'disk': 100, - 'cpus': 4, - }, { - 'name': '6 CPU, 4GB ram, 100GB', - 'ram': 4 * 1024, - 'disk': 100, - 'cpus': 6, - }, { - 'name': '6 CPU, 8GB ram, 100GB', - 'ram': 8 * 1024, - 'disk': 100, - 'cpus': 6, - }, { - 'name': '8 CPU, 8GB ram, 100GB', - 'ram': 8 * 1024, - 'disk': 100, - 'cpus': 8, - }, { - 'name': '8 CPU, 16GB ram, 100GB', - 'ram': 16 * 1024, - 'disk': 100, - 'cpus': 8, - }] - -SL_TEMPLATES = {} -for i, template in enumerate(SL_BASE_TEMPLATES): - # Add local disk templates - local = template.copy() - local['local_disk'] = True - SL_TEMPLATES[i] = local - - -class SoftLayerException(LibcloudError): - """ - Exception class for SoftLayer driver - """ - pass - - -class SoftLayerResponse(XMLRPCResponse): - defaultExceptionCls = SoftLayerException - exceptions = { - 'SoftLayer_Account': InvalidCredsError, - } - - -class SoftLayerConnection(XMLRPCConnection, ConnectionUserAndKey): - responseCls = SoftLayerResponse - host = 'api.softlayer.com' - endpoint = '/xmlrpc/v3' - - def request(self, service, method, *args, **kwargs): - headers = {} - headers.update(self._get_auth_headers()) - headers.update(self._get_init_params(service, kwargs.get('id'))) - headers.update( - self._get_object_mask(service, kwargs.get('object_mask'))) - headers.update( - self._get_object_mask(service, kwargs.get('object_mask'))) - - args = ({'headers': headers}, ) + args - endpoint = '%s/%s' % (self.endpoint, service) - - return super(SoftLayerConnection, self).request(method, *args, - **{'endpoint': - endpoint}) - - def _get_auth_headers(self): - return { - 'authenticate': { - 'username': self.user_id, - 'apiKey': self.key - } - } - - def _get_init_params(self, service, id): - if id is not None: - return { - '%sInitParameters' % service: {'id': id} - } - else: - return {} - - def _get_object_mask(self, service, mask): - if mask is not None: - return { - '%sObjectMask' % service: {'mask': mask} - } - else: - return {} - - -class SoftLayerNodeDriver(NodeDriver): - """ - SoftLayer node driver - - Extra node attributes: - - password: root password - - hourlyRecurringFee: hourly price (if applicable) - - recurringFee : flat rate (if applicable) - - recurringMonths : The number of months in which the recurringFee - will be incurred. - """ - connectionCls = SoftLayerConnection - name = 'SoftLayer' - website = 'http://www.softlayer.com/' - type = Provider.SOFTLAYER - - features = {'create_node': ['generates_password']} - - def _to_node(self, host): - try: - password = \ - host['operatingSystem']['passwords'][0]['password'] - except (IndexError, KeyError): - password = None - - hourlyRecurringFee = host.get('billingItem', {}).get( - 'hourlyRecurringFee', 0) - recurringFee = host.get('billingItem', {}).get('recurringFee', 0) - recurringMonths = host.get('billingItem', {}).get('recurringMonths', 0) - createDate = host.get('createDate', None) - - # When machine is launching it gets state halted - # we change this to pending - state = NODE_STATE_MAP.get(host['powerState']['keyName'], - NodeState.UNKNOWN) - - if not password and state == NodeState.UNKNOWN: - state = NODE_STATE_MAP['INITIATING'] - - public_ips = [] - private_ips = [] - - if 'primaryIpAddress' in host: - public_ips.append(host['primaryIpAddress']) - - if 'primaryBackendIpAddress' in host: - private_ips.append(host['primaryBackendIpAddress']) - - image = host.get('operatingSystem', {}).get('softwareLicense', {}) \ - .get('softwareDescription', {}) \ - .get('longDescription', None) - - return Node( - id=host['id'], - name=host['fullyQualifiedDomainName'], - state=state, - public_ips=public_ips, - private_ips=private_ips, - driver=self, - extra={ - 'hostname': host['hostname'], - 'fullyQualifiedDomainName': host['fullyQualifiedDomainName'], - 'password': password, - 'maxCpu': host.get('maxCpu', None), - 'datacenter': host.get('datacenter', {}).get('longName', None), - 'maxMemory': host.get('maxMemory', None), - 'image': image, - 'hourlyRecurringFee': hourlyRecurringFee, - 'recurringFee': recurringFee, - 'recurringMonths': recurringMonths, - 'created': createDate, - } - ) - - def destroy_node(self, node): - self.connection.request( - 'SoftLayer_Virtual_Guest', 'deleteObject', id=node.id - ) - return True - - def reboot_node(self, node): - self.connection.request( - 'SoftLayer_Virtual_Guest', 'rebootSoft', id=node.id - ) - return True - - def ex_stop_node(self, node): - self.connection.request( - 'SoftLayer_Virtual_Guest', 'powerOff', id=node.id - ) - return True - - def ex_start_node(self, node): - self.connection.request( - 'SoftLayer_Virtual_Guest', 'powerOn', id=node.id - ) - return True - - def _get_order_information(self, node_id, timeout=1200, check_interval=5): - mask = { - 'billingItem': '', - 'powerState': '', - 'operatingSystem': {'passwords': ''}, - 'provisionDate': '', - } - - for i in range(0, timeout, check_interval): - res = self.connection.request( - 'SoftLayer_Virtual_Guest', - 'getObject', - id=node_id, - object_mask=mask - ).object - - if res.get('provisionDate', None): - return res - - time.sleep(check_interval) - - raise SoftLayerException('Timeout on getting node details') - - def create_node(self, **kwargs): - """Create a new SoftLayer node - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_domain: e.g. libcloud.org - :type ex_domain: ``str`` - :keyword ex_cpus: e.g. 2 - :type ex_cpus: ``int`` - :keyword ex_disk: e.g. 100 - :type ex_disk: ``int`` - :keyword ex_ram: e.g. 2048 - :type ex_ram: ``int`` - :keyword ex_bandwidth: e.g. 100 - :type ex_bandwidth: ``int`` - :keyword ex_local_disk: e.g. True - :type ex_local_disk: ``bool`` - :keyword ex_datacenter: e.g. Dal05 - :type ex_datacenter: ``str`` - :keyword ex_os: e.g. UBUNTU_LATEST - :type ex_os: ``str`` - """ - name = kwargs['name'] - os = 'DEBIAN_LATEST' - if 'ex_os' in kwargs: - os = kwargs['ex_os'] - elif 'image' in kwargs: - os = kwargs['image'].id - - size = kwargs.get('size', NodeSize(id=123, name='Custom', ram=None, - disk=None, bandwidth=None, - price=None, - driver=self.connection.driver)) - ex_size_data = SL_TEMPLATES.get(int(size.id)) or {} - # plan keys are ints - cpu_count = kwargs.get('ex_cpus') or ex_size_data.get('cpus') or \ - DEFAULT_CPU_SIZE - ram = kwargs.get('ex_ram') or ex_size_data.get('ram') or \ - DEFAULT_RAM_SIZE - bandwidth = kwargs.get('ex_bandwidth') or size.bandwidth or 10 - hourly = 'true' if kwargs.get('ex_hourly', True) else 'false' - - local_disk = 'true' - if ex_size_data.get('local_disk') is False: - local_disk = 'false' - - if kwargs.get('ex_local_disk') is False: - local_disk = 'false' - - disk_size = DEFAULT_DISK_SIZE - if size.disk: - disk_size = size.disk - if kwargs.get('ex_disk'): - disk_size = kwargs.get('ex_disk') - - datacenter = '' - if 'ex_datacenter' in kwargs: - datacenter = kwargs['ex_datacenter'] - elif 'location' in kwargs: - datacenter = kwargs['location'].id - - domain = kwargs.get('ex_domain') - if domain is None: - if name.find('.') != -1: - domain = name[name.find('.') + 1:] - if domain is None: - # TODO: domain is a required argument for the Sofylayer API, but it - # it shouldn't be. - domain = DEFAULT_DOMAIN - - newCCI = { - 'hostname': name, - 'domain': domain, - 'startCpus': cpu_count, - 'maxMemory': ram, - 'networkComponents': [{'maxSpeed': bandwidth}], - 'hourlyBillingFlag': hourly, - 'operatingSystemReferenceCode': os, - 'localDiskFlag': local_disk, - 'blockDevices': [ - { - 'device': '0', - 'diskImage': { - 'capacity': disk_size, - } - } - ] - - } - - if datacenter: - newCCI['datacenter'] = {'name': datacenter} - - res = self.connection.request( - 'SoftLayer_Virtual_Guest', 'createObject', newCCI - ).object - - node_id = res['id'] - raw_node = self._get_order_information(node_id) - - return self._to_node(raw_node) - - def _to_image(self, img): - return NodeImage( - id=img['template']['operatingSystemReferenceCode'], - name=img['itemPrice']['item']['description'], - driver=self.connection.driver - ) - - def list_images(self, location=None): - result = self.connection.request( - 'SoftLayer_Virtual_Guest', 'getCreateObjectOptions' - ).object - return [self._to_image(i) for i in result['operatingSystems']] - - def _to_size(self, id, size): - return NodeSize( - id=id, - name=size['name'], - ram=size['ram'], - disk=size['disk'], - bandwidth=size.get('bandwidth'), - price=None, - driver=self.connection.driver, - ) - - def list_sizes(self, location=None): - return [self._to_size(id, s) for id, s in SL_TEMPLATES.items()] - - def _to_loc(self, loc): - country = 'UNKNOWN' - loc_id = loc['template']['datacenter']['name'] - name = loc_id - - if loc_id in DATACENTERS: - country = DATACENTERS[loc_id]['country'] - name = DATACENTERS[loc_id].get('name', loc_id) - return NodeLocation(id=loc_id, name=name, - country=country, driver=self) - - def list_locations(self): - res = self.connection.request( - 'SoftLayer_Virtual_Guest', 'getCreateObjectOptions' - ).object - return [self._to_loc(l) for l in res['datacenters']] - - def list_nodes(self): - mask = { - 'virtualGuests': { - 'powerState': '', - 'hostname': '', - 'maxMemory': '', - 'datacenter': '', - 'operatingSystem': {'passwords': ''}, - 'billingItem': '', - }, - } - res = self.connection.request( - "SoftLayer_Account", - "getVirtualGuests", - object_mask=mask - ).object - return [self._to_node(h) for h in res] diff --git a/awx/lib/site-packages/libcloud/compute/drivers/vcl.py b/awx/lib/site-packages/libcloud/compute/drivers/vcl.py deleted file mode 100644 index a5ec4644d7..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/vcl.py +++ /dev/null @@ -1,302 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -VCL driver -""" - -import time - -from libcloud.common.base import ConnectionUserAndKey -from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.compute.types import Provider, NodeState -from libcloud.compute.base import NodeDriver, Node -from libcloud.compute.base import NodeSize, NodeImage - - -class VCLResponse(XMLRPCResponse): - exceptions = { - 'VCL_Account': InvalidCredsError, - } - - -class VCLConnection(XMLRPCConnection, ConnectionUserAndKey): - endpoint = '/index.php?mode=xmlrpccall' - - def add_default_headers(self, headers): - headers['X-APIVERSION'] = '2' - headers['X-User'] = self.user_id - headers['X-Pass'] = self.key - return headers - - -class VCLNodeDriver(NodeDriver): - """ - VCL node driver - - :keyword host: The VCL host to which you make requests(required) - :type host: ``str`` - """ - - NODE_STATE_MAP = { - 'ready': NodeState.RUNNING, - 'failed': NodeState.TERMINATED, - 'timedout': NodeState.TERMINATED, - 'loading': NodeState.PENDING, - 'time': NodeState.PENDING, - 'future': NodeState.PENDING, - 'error': NodeState.UNKNOWN, - 'notready': NodeState.PENDING, - 'notavailable': NodeState.TERMINATED, - 'success': NodeState.PENDING - } - - connectionCls = VCLConnection - name = 'VCL' - website = 'http://incubator.apache.org/vcl/' - type = Provider.VCL - - def __init__(self, key, secret, secure=True, host=None, port=None, *args, - **kwargs): - """ - :param key: API key or username to used (required) - :type key: ``str`` - - :param secret: Secret password to be used (required) - :type secret: ``str`` - - :param secure: Weither to use HTTPS or HTTP. - :type secure: ``bool`` - - :param host: Override hostname used for connections. (required) - :type host: ``str`` - - :param port: Override port used for connections. - :type port: ``int`` - - :rtype: ``None`` - """ - if not host: - raise Exception('When instantiating VCL driver directly ' + - 'you also need to provide host') - - super(VCLNodeDriver, self).__init__(key, secret, secure=True, - host=None, port=None, *args, - **kwargs) - - def _vcl_request(self, method, *args): - res = self.connection.request( - method, - *args - ).object - if(res['status'] == 'error'): - raise LibcloudError(res['errormsg'], driver=self) - return res - - def create_node(self, **kwargs): - """Create a new VCL reservation - size and name ignored, image is the id from list_image - - @inherits: :class:`NodeDriver.create_node` - - :keyword image: image is the id from list_image - :type image: ``str`` - - :keyword start: start time as unix timestamp - :type start: ``str`` - - :keyword length: length of time in minutes - :type length: ``str`` - """ - - image = kwargs["image"] - start = kwargs.get('start', int(time.time())) - length = kwargs.get('length', '60') - - res = self._vcl_request( - "XMLRPCaddRequest", - image.id, - start, - length - ) - - return Node( - id=res['requestid'], - name=image.name, - state=self.NODE_STATE_MAP[res['status']], - public_ips=[], - private_ips=[], - driver=self, - image=image.name - ) - - def destroy_node(self, node): - """ - End VCL reservation for the node passed in. - Throws error if request fails. - - :param node: The node to be destroyed - :type node: :class:`Node` - - :rtype: ``bool`` - """ - try: - self._vcl_request( - 'XMLRPCendRequest', - node.id - ) - except LibcloudError: - return False - return True - - def _to_image(self, img): - return NodeImage( - id=img['id'], - name=img['name'], - driver=self.connection.driver - ) - - def list_images(self, location=None): - """ - List images available to the user provided credentials - - @inherits: :class:`NodeDriver.list_images` - """ - res = self.connection.request( - "XMLRPCgetImages" - ).object - return [self._to_image(i) for i in res] - - def list_sizes(self, location=None): - """ - VCL does not choosing sizes for node creation. - Size of images are statically set by administrators. - - @inherits: :class:`NodeDriver.list_sizes` - """ - return [NodeSize( - 't1.micro', - 'none', - '512', - 0, 0, 0, self) - ] - - def _to_connect_data(self, request_id, ipaddr): - res = self._vcl_request( - "XMLRPCgetRequestConnectData", - request_id, - ipaddr - ) - return res - - def _to_status(self, requestid, imagename, ipaddr): - res = self._vcl_request( - "XMLRPCgetRequestStatus", - requestid - ) - - public_ips = [] - extra = [] - if(res['status'] == 'ready'): - cdata = self._to_connect_data(requestid, ipaddr) - public_ips = [cdata['serverIP']] - extra = { - 'user': cdata['user'], - 'pass': cdata['password'] - } - return Node( - id=requestid, - name=imagename, - state=self.NODE_STATE_MAP[res['status']], - public_ips=public_ips, - private_ips=[], - driver=self, - image=imagename, - extra=extra - ) - - def _to_nodes(self, res, ipaddr): - return [self._to_status( - h['requestid'], - h['imagename'], - ipaddr - ) for h in res] - - def list_nodes(self, ipaddr): - """ - List nodes - - :param ipaddr: IP address which should be used - :type ipaddr: ``str`` - - :rtype: ``list`` of :class:`Node` - """ - res = self._vcl_request( - "XMLRPCgetRequestIds" - ) - return self._to_nodes(res['requests'], ipaddr) - - def ex_update_node_access(self, node, ipaddr): - """ - Update the remote ip accessing the node. - - :param node: the reservation node to update - :type node: :class:`Node` - - :param ipaddr: the ipaddr used to access the node - :type ipaddr: ``str`` - - :return: node with updated information - :rtype: :class:`Node` - """ - return self._to_status(node.id, node.image, ipaddr) - - def ex_extend_request_time(self, node, minutes): - """ - Time in minutes to extend the requested node's reservation time - - :param node: the reservation node to update - :type node: :class:`Node` - - :param minutes: the number of mintes to update - :type minutes: ``str`` - - :return: true on success, throws error on failure - :rtype: ``bool`` - """ - return self._vcl_request( - "XMLRPCextendRequest", - node.id, - minutes - ) - - def ex_get_request_end_time(self, node): - """ - Get the ending time of the node reservation. - - :param node: the reservation node to update - :type node: :class:`Node` - - :return: unix timestamp - :rtype: ``int`` - """ - res = self._vcl_request( - "XMLRPCgetRequestIds" - ) - time = 0 - for i in res['requests']: - if i['requestid'] == node.id: - time = i['end'] - return time diff --git a/awx/lib/site-packages/libcloud/compute/drivers/vcloud.py b/awx/lib/site-packages/libcloud/compute/drivers/vcloud.py deleted file mode 100644 index d18d390d4a..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/vcloud.py +++ /dev/null @@ -1,2090 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -VMware vCloud driver. -""" -import copy -import sys -import re -import base64 -import os -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlencode -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import b -from libcloud.utils.py3 import next - -urlparse = urlparse.urlparse - -import time - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from xml.parsers.expat import ExpatError - -from libcloud.common.base import XmlResponse, ConnectionUserAndKey -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.compute.providers import Provider -from libcloud.compute.types import NodeState -from libcloud.compute.base import Node, NodeDriver, NodeLocation -from libcloud.compute.base import NodeSize, NodeImage - -""" -From vcloud api "The VirtualQuantity element defines the number of MB -of memory. This should be either 512 or a multiple of 1024 (1 GB)." -""" -VIRTUAL_MEMORY_VALS = [512] + [1024 * i for i in range(1, 9)] - -# Default timeout (in seconds) for long running tasks -DEFAULT_TASK_COMPLETION_TIMEOUT = 600 - -DEFAULT_API_VERSION = '0.8' - -""" -Valid vCloud API v1.5 input values. -""" -VIRTUAL_CPU_VALS_1_5 = [i for i in range(1, 9)] -FENCE_MODE_VALS_1_5 = ['bridged', 'isolated', 'natRouted'] -IP_MODE_VALS_1_5 = ['POOL', 'DHCP', 'MANUAL', 'NONE'] - - -def fixxpath(root, xpath): - """ElementTree wants namespaces in its xpaths, so here we add them.""" - namespace, root_tag = root.tag[1:].split("}", 1) - fixed_xpath = "/".join(["{%s}%s" % (namespace, e) - for e in xpath.split("/")]) - return fixed_xpath - - -def get_url_path(url): - return urlparse(url.strip()).path - - -class Vdc(object): - """ - Virtual datacenter (vDC) representation - """ - def __init__(self, id, name, driver, allocation_model=None, cpu=None, - memory=None, storage=None): - self.id = id - self.name = name - self.driver = driver - self.allocation_model = allocation_model - self.cpu = cpu - self.memory = memory - self.storage = storage - - def __repr__(self): - return ('<Vdc: id=%s, name=%s, driver=%s ...>' - % (self.id, self.name, self.driver.name)) - - -class Capacity(object): - """ - Represents CPU, Memory or Storage capacity of vDC. - """ - def __init__(self, limit, used, units): - self.limit = limit - self.used = used - self.units = units - - def __repr__(self): - return ('<Capacity: limit=%s, used=%s, units=%s>' - % (self.limit, self.used, self.units)) - - -class ControlAccess(object): - """ - Represents control access settings of a node - """ - class AccessLevel(object): - READ_ONLY = 'ReadOnly' - CHANGE = 'Change' - FULL_CONTROL = 'FullControl' - - def __init__(self, node, everyone_access_level, subjects=None): - self.node = node - self.everyone_access_level = everyone_access_level - if not subjects: - subjects = [] - self.subjects = subjects - - def __repr__(self): - return ('<ControlAccess: node=%s, everyone_access_level=%s, ' - 'subjects=%s>' - % (self.node, self.everyone_access_level, self.subjects)) - - -class Subject(object): - """ - User or group subject - """ - def __init__(self, type, name, access_level, id=None): - self.type = type - self.name = name - self.access_level = access_level - self.id = id - - def __repr__(self): - return ('<Subject: type=%s, name=%s, access_level=%s>' - % (self.type, self.name, self.access_level)) - - -class InstantiateVAppXML(object): - - def __init__(self, name, template, net_href, cpus, memory, - password=None, row=None, group=None): - self.name = name - self.template = template - self.net_href = net_href - self.cpus = cpus - self.memory = memory - self.password = password - self.row = row - self.group = group - - self._build_xmltree() - - def tostring(self): - return ET.tostring(self.root) - - def _build_xmltree(self): - self.root = self._make_instantiation_root() - - self._add_vapp_template(self.root) - instantiation_params = ET.SubElement(self.root, - "InstantiationParams") - - # product and virtual hardware - self._make_product_section(instantiation_params) - self._make_virtual_hardware(instantiation_params) - - network_config_section = ET.SubElement(instantiation_params, - "NetworkConfigSection") - - network_config = ET.SubElement(network_config_section, - "NetworkConfig") - self._add_network_association(network_config) - - def _make_instantiation_root(self): - return ET.Element( - "InstantiateVAppTemplateParams", - {'name': self.name, - 'xml:lang': 'en', - 'xmlns': "http://www.vmware.com/vcloud/v0.8", - 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} - ) - - def _add_vapp_template(self, parent): - return ET.SubElement( - parent, - "VAppTemplate", - {'href': self.template} - ) - - def _make_product_section(self, parent): - prod_section = ET.SubElement( - parent, - "ProductSection", - {'xmlns:q1': "http://www.vmware.com/vcloud/v0.8", - 'xmlns:ovf': "http://schemas.dmtf.org/ovf/envelope/1"} - ) - - if self.password: - self._add_property(prod_section, 'password', self.password) - - if self.row: - self._add_property(prod_section, 'row', self.row) - - if self.group: - self._add_property(prod_section, 'group', self.group) - - return prod_section - - def _add_property(self, parent, ovfkey, ovfvalue): - return ET.SubElement( - parent, - "Property", - {'xmlns': 'http://schemas.dmtf.org/ovf/envelope/1', - 'ovf:key': ovfkey, - 'ovf:value': ovfvalue} - ) - - def _make_virtual_hardware(self, parent): - vh = ET.SubElement( - parent, - "VirtualHardwareSection", - {'xmlns:q1': "http://www.vmware.com/vcloud/v0.8"} - ) - - self._add_cpu(vh) - self._add_memory(vh) - - return vh - - def _add_cpu(self, parent): - cpu_item = ET.SubElement( - parent, - "Item", - {'xmlns': "http://schemas.dmtf.org/ovf/envelope/1"} - ) - self._add_instance_id(cpu_item, '1') - self._add_resource_type(cpu_item, '3') - self._add_virtual_quantity(cpu_item, self.cpus) - - return cpu_item - - def _add_memory(self, parent): - mem_item = ET.SubElement( - parent, - 'Item', - {'xmlns': "http://schemas.dmtf.org/ovf/envelope/1"} - ) - self._add_instance_id(mem_item, '2') - self._add_resource_type(mem_item, '4') - self._add_virtual_quantity(mem_item, self.memory) - - return mem_item - - def _add_instance_id(self, parent, id): - elm = ET.SubElement( - parent, - 'InstanceID', - {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' - 'CIM_ResourceAllocationSettingData'} - ) - elm.text = id - return elm - - def _add_resource_type(self, parent, type): - elm = ET.SubElement( - parent, - 'ResourceType', - {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' - 'CIM_ResourceAllocationSettingData'} - ) - elm.text = type - return elm - - def _add_virtual_quantity(self, parent, amount): - elm = ET.SubElement( - parent, - 'VirtualQuantity', - {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' - 'CIM_ResourceAllocationSettingData'} - ) - elm.text = amount - return elm - - def _add_network_association(self, parent): - return ET.SubElement( - parent, - 'NetworkAssociation', - {'href': self.net_href} - ) - - -class VCloudResponse(XmlResponse): - - def success(self): - return self.status in (httplib.OK, httplib.CREATED, - httplib.NO_CONTENT, httplib.ACCEPTED) - - -class VCloudConnection(ConnectionUserAndKey): - - """ - Connection class for the vCloud driver - """ - - responseCls = VCloudResponse - token = None - host = None - - def request(self, *args, **kwargs): - self._get_auth_token() - return super(VCloudConnection, self).request(*args, **kwargs) - - def check_org(self): - # the only way to get our org is by logging in. - self._get_auth_token() - - def _get_auth_headers(self): - """Some providers need different headers than others""" - return { - 'Authorization': "Basic %s" % base64.b64encode( - b('%s:%s' % (self.user_id, self.key))).decode('utf-8'), - 'Content-Length': '0', - 'Accept': 'application/*+xml' - } - - def _get_auth_token(self): - if not self.token: - conn = self.conn_classes[self.secure](self.host, - self.port) - conn.request(method='POST', url='/api/v0.8/login', - headers=self._get_auth_headers()) - - resp = conn.getresponse() - headers = dict(resp.getheaders()) - body = ET.XML(resp.read()) - - try: - self.token = headers['set-cookie'] - except KeyError: - raise InvalidCredsError() - - self.driver.org = get_url_path( - body.find(fixxpath(body, 'Org')).get('href') - ) - - def add_default_headers(self, headers): - headers['Cookie'] = self.token - headers['Accept'] = 'application/*+xml' - return headers - - -class VCloudNodeDriver(NodeDriver): - - """ - vCloud node driver - """ - - type = Provider.VCLOUD - name = 'vCloud' - website = 'http://www.vmware.com/products/vcloud/' - connectionCls = VCloudConnection - org = None - _vdcs = None - - NODE_STATE_MAP = {'0': NodeState.PENDING, - '1': NodeState.PENDING, - '2': NodeState.PENDING, - '3': NodeState.PENDING, - '4': NodeState.RUNNING} - - features = {'create_node': ['password']} - - def __new__(cls, key, secret=None, secure=True, host=None, port=None, - api_version=DEFAULT_API_VERSION, **kwargs): - if cls is VCloudNodeDriver: - if api_version == '0.8': - cls = VCloudNodeDriver - elif api_version == '1.5': - cls = VCloud_1_5_NodeDriver - elif api_version == '5.1': - cls = VCloud_5_1_NodeDriver - else: - raise NotImplementedError( - "No VCloudNodeDriver found for API version %s" % - (api_version)) - return super(VCloudNodeDriver, cls).__new__(cls) - - @property - def vdcs(self): - """ - vCloud virtual data centers (vDCs). - - :return: list of vDC objects - :rtype: ``list`` of :class:`Vdc` - """ - if not self._vdcs: - self.connection.check_org() # make sure the org is set. - res = self.connection.request(self.org) - self._vdcs = [ - self._to_vdc( - self.connection.request(get_url_path(i.get('href'))).object - ) - for i in res.object.findall(fixxpath(res.object, "Link")) - if i.get('type') == 'application/vnd.vmware.vcloud.vdc+xml' - ] - return self._vdcs - - def _to_vdc(self, vdc_elm): - return Vdc(vdc_elm.get('href'), vdc_elm.get('name'), self) - - def _get_vdc(self, vdc_name): - vdc = None - if not vdc_name: - # Return the first organisation VDC found - vdc = self.vdcs[0] - else: - for v in self.vdcs: - if v.name == vdc_name: - vdc = v - if vdc is None: - raise ValueError('%s virtual data centre could not be found', - vdc_name) - return vdc - - @property - def networks(self): - networks = [] - for vdc in self.vdcs: - res = self.connection.request(get_url_path(vdc.id)).object - networks.extend( - [network - for network in res.findall( - fixxpath(res, 'AvailableNetworks/Network') - - )] - ) - - return networks - - def _to_image(self, image): - image = NodeImage(id=image.get('href'), - name=image.get('name'), - driver=self.connection.driver) - return image - - def _to_node(self, elm): - state = self.NODE_STATE_MAP[elm.get('status')] - name = elm.get('name') - public_ips = [] - private_ips = [] - - # Following code to find private IPs works for Terremark - connections = elm.findall('%s/%s' % ( - '{http://schemas.dmtf.org/ovf/envelope/1}NetworkConnectionSection', - fixxpath(elm, 'NetworkConnection')) - ) - if not connections: - connections = elm.findall( - fixxpath( - elm, - 'Children/Vm/NetworkConnectionSection/NetworkConnection')) - - for connection in connections: - ips = [ip.text - for ip - in connection.findall(fixxpath(elm, "IpAddress"))] - if connection.get('Network') == 'Internal': - private_ips.extend(ips) - else: - public_ips.extend(ips) - - node = Node(id=elm.get('href'), - name=name, - state=state, - public_ips=public_ips, - private_ips=private_ips, - driver=self.connection.driver) - - return node - - def _get_catalog_hrefs(self): - res = self.connection.request(self.org) - catalogs = [ - i.get('href') - for i in res.object.findall(fixxpath(res.object, "Link")) - if i.get('type') == 'application/vnd.vmware.vcloud.catalog+xml' - ] - - return catalogs - - def _wait_for_task_completion(self, task_href, - timeout=DEFAULT_TASK_COMPLETION_TIMEOUT): - start_time = time.time() - res = self.connection.request(get_url_path(task_href)) - status = res.object.get('status') - while status != 'success': - if status == 'error': - # Get error reason from the response body - error_elem = res.object.find(fixxpath(res.object, 'Error')) - error_msg = "Unknown error" - if error_elem is not None: - error_msg = error_elem.get('message') - raise Exception("Error status returned by task %s.: %s" - % (task_href, error_msg)) - if status == 'canceled': - raise Exception("Canceled status returned by task %s." - % task_href) - if (time.time() - start_time >= timeout): - raise Exception("Timeout (%s sec) while waiting for task %s." - % (timeout, task_href)) - time.sleep(5) - res = self.connection.request(get_url_path(task_href)) - status = res.object.get('status') - - def destroy_node(self, node): - node_path = get_url_path(node.id) - # blindly poweroff node, it will throw an exception if already off - try: - res = self.connection.request('%s/power/action/poweroff' - % node_path, - method='POST') - self._wait_for_task_completion(res.object.get('href')) - except Exception: - pass - - try: - res = self.connection.request('%s/action/undeploy' % node_path, - method='POST') - self._wait_for_task_completion(res.object.get('href')) - except ExpatError: - # The undeploy response is malformed XML atm. - # We can remove this whent he providers fix the problem. - pass - except Exception: - # Some vendors don't implement undeploy at all yet, - # so catch this and move on. - pass - - res = self.connection.request(node_path, method='DELETE') - return res.status == httplib.ACCEPTED - - def reboot_node(self, node): - res = self.connection.request('%s/power/action/reset' - % get_url_path(node.id), - method='POST') - return res.status in [httplib.ACCEPTED, httplib.NO_CONTENT] - - def list_nodes(self): - return self.ex_list_nodes() - - def ex_list_nodes(self, vdcs=None): - """ - List all nodes across all vDCs. Using 'vdcs' you can specify which vDCs - should be queried. - - :param vdcs: None, vDC or a list of vDCs to query. If None all vDCs - will be queried. - :type vdcs: :class:`Vdc` - - :rtype: ``list`` of :class:`Node` - """ - if not vdcs: - vdcs = self.vdcs - if not isinstance(vdcs, (list, tuple)): - vdcs = [vdcs] - nodes = [] - for vdc in vdcs: - res = self.connection.request(get_url_path(vdc.id)) - elms = res.object.findall(fixxpath( - res.object, "ResourceEntities/ResourceEntity") - ) - vapps = [ - (i.get('name'), i.get('href')) - for i in elms - if i.get('type') == 'application/vnd.vmware.vcloud.vApp+xml' - and i.get('name') - ] - - for vapp_name, vapp_href in vapps: - try: - res = self.connection.request( - get_url_path(vapp_href), - headers={'Content-Type': - 'application/vnd.vmware.vcloud.vApp+xml'} - ) - nodes.append(self._to_node(res.object)) - except Exception: - # The vApp was probably removed since the previous vDC - # query, ignore - e = sys.exc_info()[1] - if not (e.args[0].tag.endswith('Error') and - e.args[0].get('minorErrorCode') == - 'ACCESS_TO_RESOURCE_IS_FORBIDDEN'): - raise - - return nodes - - def _to_size(self, ram): - ns = NodeSize( - id=None, - name="%s Ram" % ram, - ram=ram, - disk=None, - bandwidth=None, - price=None, - driver=self.connection.driver - ) - return ns - - def list_sizes(self, location=None): - sizes = [self._to_size(i) for i in VIRTUAL_MEMORY_VALS] - return sizes - - def _get_catalogitems_hrefs(self, catalog): - """Given a catalog href returns contained catalog item hrefs""" - res = self.connection.request( - get_url_path(catalog), - headers={ - 'Content-Type': 'application/vnd.vmware.vcloud.catalog+xml' - } - ).object - - cat_items = res.findall(fixxpath(res, "CatalogItems/CatalogItem")) - cat_item_hrefs = [i.get('href') - for i in cat_items - if i.get('type') == - 'application/vnd.vmware.vcloud.catalogItem+xml'] - - return cat_item_hrefs - - def _get_catalogitem(self, catalog_item): - """Given a catalog item href returns elementree""" - res = self.connection.request( - get_url_path(catalog_item), - headers={ - 'Content-Type': 'application/vnd.vmware.vcloud.catalogItem+xml' - } - ).object - - return res - - def list_images(self, location=None): - images = [] - for vdc in self.vdcs: - res = self.connection.request(get_url_path(vdc.id)).object - res_ents = res.findall(fixxpath( - res, "ResourceEntities/ResourceEntity") - ) - images += [ - self._to_image(i) - for i in res_ents - if i.get('type') == - 'application/vnd.vmware.vcloud.vAppTemplate+xml' - ] - - for catalog in self._get_catalog_hrefs(): - for cat_item in self._get_catalogitems_hrefs(catalog): - res = self._get_catalogitem(cat_item) - res_ents = res.findall(fixxpath(res, 'Entity')) - images += [ - self._to_image(i) - for i in res_ents - if i.get('type') == - 'application/vnd.vmware.vcloud.vAppTemplate+xml' - ] - - def idfun(image): - return image.id - - return self._uniquer(images, idfun) - - def _uniquer(self, seq, idfun=None): - if idfun is None: - def idfun(x): - return x - seen = {} - result = [] - for item in seq: - marker = idfun(item) - if marker in seen: - continue - seen[marker] = 1 - result.append(item) - return result - - def create_node(self, **kwargs): - """ - Creates and returns node. - - :keyword ex_network: link to a "Network" e.g., - ``https://services.vcloudexpress...`` - :type ex_network: ``str`` - - :keyword ex_vdc: Name of organisation's virtual data - center where vApp VMs will be deployed. - :type ex_vdc: ``str`` - - :keyword ex_cpus: number of virtual cpus (limit depends on provider) - :type ex_cpus: ``int`` - - :type ex_row: ``str`` - - :type ex_group: ``str`` - """ - name = kwargs['name'] - image = kwargs['image'] - size = kwargs['size'] - - # Some providers don't require a network link - try: - network = kwargs.get('ex_network', self.networks[0].get('href')) - except IndexError: - network = '' - - password = None - auth = self._get_and_check_auth(kwargs.get('auth')) - password = auth.password - - instantiate_xml = InstantiateVAppXML( - name=name, - template=image.id, - net_href=network, - cpus=str(kwargs.get('ex_cpus', 1)), - memory=str(size.ram), - password=password, - row=kwargs.get('ex_row', None), - group=kwargs.get('ex_group', None) - ) - - vdc = self._get_vdc(kwargs.get('ex_vdc', None)) - - # Instantiate VM and get identifier. - content_type = \ - 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml' - res = self.connection.request( - '%s/action/instantiateVAppTemplate' % get_url_path(vdc.id), - data=instantiate_xml.tostring(), - method='POST', - headers={'Content-Type': content_type} - ) - vapp_path = get_url_path(res.object.get('href')) - - # Deploy the VM from the identifier. - res = self.connection.request('%s/action/deploy' % vapp_path, - method='POST') - - self._wait_for_task_completion(res.object.get('href')) - - # Power on the VM. - res = self.connection.request('%s/power/action/powerOn' % vapp_path, - method='POST') - - res = self.connection.request(vapp_path) - node = self._to_node(res.object) - - if getattr(auth, "generated", False): - node.extra['password'] = auth.password - - return node - - -class HostingComConnection(VCloudConnection): - - """ - vCloud connection subclass for Hosting.com - """ - - host = "vcloud.safesecureweb.com" - - def _get_auth_headers(self): - """hosting.com doesn't follow the standard vCloud authentication API""" - return { - 'Authentication': base64.b64encode(b('%s:%s' % (self.user_id, - self.key))), - 'Content-Length': '0' - } - - -class HostingComDriver(VCloudNodeDriver): - - """ - vCloud node driver for Hosting.com - """ - connectionCls = HostingComConnection - - -class TerremarkConnection(VCloudConnection): - - """ - vCloud connection subclass for Terremark - """ - - host = "services.vcloudexpress.terremark.com" - - -class TerremarkDriver(VCloudNodeDriver): - - """ - vCloud node driver for Terremark - """ - - connectionCls = TerremarkConnection - - def list_locations(self): - return [NodeLocation(0, "Terremark Texas", 'US', self)] - - -class VCloud_1_5_Connection(VCloudConnection): - - def _get_auth_headers(self): - """Compatibility for using v1.5 API under vCloud Director 5.1""" - return { - 'Authorization': "Basic %s" % base64.b64encode( - b('%s:%s' % (self.user_id, self.key))).decode('utf-8'), - 'Content-Length': '0', - 'Accept': 'application/*+xml;version=1.5' - } - - def _get_auth_token(self): - if not self.token: - # Log In - conn = self.conn_classes[self.secure](self.host, - self.port) - conn.request(method='POST', url='/api/sessions', - headers=self._get_auth_headers()) - - resp = conn.getresponse() - headers = dict(resp.getheaders()) - - # Set authorization token - try: - self.token = headers['x-vcloud-authorization'] - except KeyError: - raise InvalidCredsError() - - # Get the URL of the Organization - body = ET.XML(resp.read()) - self.org_name = body.get('org') - org_list_url = get_url_path( - next((link for link in body.findall(fixxpath(body, 'Link')) - if link.get('type') == - 'application/vnd.vmware.vcloud.orgList+xml')).get('href') - ) - - conn.request(method='GET', url=org_list_url, - headers=self.add_default_headers({})) - body = ET.XML(conn.getresponse().read()) - self.driver.org = get_url_path( - next((org for org in body.findall(fixxpath(body, 'Org')) - if org.get('name') == self.org_name)).get('href') - ) - - def add_default_headers(self, headers): - headers['Accept'] = 'application/*+xml;version=1.5' - headers['x-vcloud-authorization'] = self.token - return headers - - -class Instantiate_1_5_VAppXML(object): - - def __init__(self, name, template, network, vm_network=None, - vm_fence=None): - self.name = name - self.template = template - self.network = network - self.vm_network = vm_network - self.vm_fence = vm_fence - self._build_xmltree() - - def tostring(self): - return ET.tostring(self.root) - - def _build_xmltree(self): - self.root = self._make_instantiation_root() - - if self.network is not None: - instantionation_params = ET.SubElement(self.root, - 'InstantiationParams') - network_config_section = ET.SubElement(instantionation_params, - 'NetworkConfigSection') - ET.SubElement( - network_config_section, - 'Info', - {'xmlns': 'http://schemas.dmtf.org/ovf/envelope/1'} - ) - network_config = ET.SubElement(network_config_section, - 'NetworkConfig') - self._add_network_association(network_config) - - self._add_vapp_template(self.root) - - def _make_instantiation_root(self): - return ET.Element( - 'InstantiateVAppTemplateParams', - {'name': self.name, - 'deploy': 'false', - 'powerOn': 'false', - 'xml:lang': 'en', - 'xmlns': 'http://www.vmware.com/vcloud/v1.5', - 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'} - ) - - def _add_vapp_template(self, parent): - return ET.SubElement( - parent, - 'Source', - {'href': self.template} - ) - - def _add_network_association(self, parent): - if self.vm_network is None: - # Don't set a custom vApp VM network name - parent.set('networkName', self.network.get('name')) - else: - # Set a custom vApp VM network name - parent.set('networkName', self.vm_network) - configuration = ET.SubElement(parent, 'Configuration') - ET.SubElement(configuration, 'ParentNetwork', - {'href': self.network.get('href')}) - - if self.vm_fence is None: - fencemode = self.network.find(fixxpath(self.network, - 'Configuration/FenceMode')).text - else: - fencemode = self.vm_fence - ET.SubElement(configuration, 'FenceMode').text = fencemode - - -class VCloud_1_5_NodeDriver(VCloudNodeDriver): - connectionCls = VCloud_1_5_Connection - - # Based on - # http://pubs.vmware.com/vcloud-api-1-5/api_prog/ - # GUID-843BE3AD-5EF6-4442-B864-BCAE44A51867.html - NODE_STATE_MAP = {'-1': NodeState.UNKNOWN, - '0': NodeState.PENDING, - '1': NodeState.PENDING, - '2': NodeState.PENDING, - '3': NodeState.PENDING, - '4': NodeState.RUNNING, - '5': NodeState.RUNNING, - '6': NodeState.UNKNOWN, - '7': NodeState.UNKNOWN, - '8': NodeState.STOPPED, - '9': NodeState.UNKNOWN, - '10': NodeState.UNKNOWN} - - def list_locations(self): - return [NodeLocation(id=self.connection.host, - name=self.connection.host, country="N/A", driver=self)] - - def ex_find_node(self, node_name, vdcs=None): - """ - Searches for node across specified vDCs. This is more effective than - querying all nodes to get a single instance. - - :param node_name: The name of the node to search for - :type node_name: ``str`` - - :param vdcs: None, vDC or a list of vDCs to search in. If None all vDCs - will be searched. - :type vdcs: :class:`Vdc` - - :return: node instance or None if not found - :rtype: :class:`Node` or ``None`` - """ - if not vdcs: - vdcs = self.vdcs - if not getattr(vdcs, '__iter__', False): - vdcs = [vdcs] - for vdc in vdcs: - res = self.connection.request(get_url_path(vdc.id)) - xpath = fixxpath(res.object, "ResourceEntities/ResourceEntity") - entity_elems = res.object.findall(xpath) - for entity_elem in entity_elems: - if entity_elem.get('type') == \ - 'application/vnd.vmware.vcloud.vApp+xml' and \ - entity_elem.get('name') == node_name: - path = get_url_path(entity_elem.get('href')) - headers = {'Content-Type': - 'application/vnd.vmware.vcloud.vApp+xml'} - res = self.connection.request(path, - headers=headers) - return self._to_node(res.object) - return None - - def destroy_node(self, node): - try: - self.ex_undeploy_node(node) - except Exception: - # Some vendors don't implement undeploy at all yet, - # so catch this and move on. - pass - - res = self.connection.request(get_url_path(node.id), method='DELETE') - return res.status == httplib.ACCEPTED - - def reboot_node(self, node): - res = self.connection.request('%s/power/action/reset' - % get_url_path(node.id), - method='POST') - if res.status in [httplib.ACCEPTED, httplib.NO_CONTENT]: - self._wait_for_task_completion(res.object.get('href')) - return True - else: - return False - - def ex_deploy_node(self, node): - """ - Deploys existing node. Equal to vApp "start" operation. - - :param node: The node to be deployed - :type node: :class:`Node` - - :rtype: :class:`Node` - """ - data = {'powerOn': 'true', - 'xmlns': 'http://www.vmware.com/vcloud/v1.5'} - deploy_xml = ET.Element('DeployVAppParams', data) - path = get_url_path(node.id) - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.deployVAppParams+xml' - } - res = self.connection.request('%s/action/deploy' % path, - data=ET.tostring(deploy_xml), - method='POST', - headers=headers) - self._wait_for_task_completion(res.object.get('href')) - res = self.connection.request(get_url_path(node.id)) - return self._to_node(res.object) - - def ex_undeploy_node(self, node): - """ - Undeploys existing node. Equal to vApp "stop" operation. - - :param node: The node to be deployed - :type node: :class:`Node` - - :rtype: :class:`Node` - """ - data = {'xmlns': 'http://www.vmware.com/vcloud/v1.5'} - undeploy_xml = ET.Element('UndeployVAppParams', data) - undeploy_power_action_xml = ET.SubElement(undeploy_xml, - 'UndeployPowerAction') - undeploy_power_action_xml.text = 'shutdown' - - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.undeployVAppParams+xml' - } - - try: - res = self.connection.request( - '%s/action/undeploy' % get_url_path(node.id), - data=ET.tostring(undeploy_xml), - method='POST', - headers=headers) - - self._wait_for_task_completion(res.object.get('href')) - except Exception: - undeploy_power_action_xml.text = 'powerOff' - res = self.connection.request( - '%s/action/undeploy' % get_url_path(node.id), - data=ET.tostring(undeploy_xml), - method='POST', - headers=headers) - self._wait_for_task_completion(res.object.get('href')) - - res = self.connection.request(get_url_path(node.id)) - return self._to_node(res.object) - - def ex_power_off_node(self, node): - """ - Powers on all VMs under specified node. VMs need to be This operation - is allowed only when the vApp/VM is powered on. - - :param node: The node to be powered off - :type node: :class:`Node` - - :rtype: :class:`Node` - """ - return self._perform_power_operation(node, 'powerOff') - - def ex_power_on_node(self, node): - """ - Powers on all VMs under specified node. This operation is allowed - only when the vApp/VM is powered off or suspended. - - :param node: The node to be powered on - :type node: :class:`Node` - - :rtype: :class:`Node` - """ - return self._perform_power_operation(node, 'powerOn') - - def ex_shutdown_node(self, node): - """ - Shutdowns all VMs under specified node. This operation is allowed only - when the vApp/VM is powered on. - - :param node: The node to be shut down - :type node: :class:`Node` - - :rtype: :class:`Node` - """ - return self._perform_power_operation(node, 'shutdown') - - def ex_suspend_node(self, node): - """ - Suspends all VMs under specified node. This operation is allowed only - when the vApp/VM is powered on. - - :param node: The node to be suspended - :type node: :class:`Node` - - :rtype: :class:`Node` - """ - return self._perform_power_operation(node, 'suspend') - - def _perform_power_operation(self, node, operation): - res = self.connection.request( - '%s/power/action/%s' % (get_url_path(node.id), operation), - method='POST') - self._wait_for_task_completion(res.object.get('href')) - res = self.connection.request(get_url_path(node.id)) - return self._to_node(res.object) - - def ex_get_control_access(self, node): - """ - Returns the control access settings for specified node. - - :param node: node to get the control access for - :type node: :class:`Node` - - :rtype: :class:`ControlAccess` - """ - res = self.connection.request( - '%s/controlAccess' % get_url_path(node.id)) - everyone_access_level = None - is_shared_elem = res.object.find( - fixxpath(res.object, "IsSharedToEveryone")) - if is_shared_elem is not None and is_shared_elem.text == 'true': - everyone_access_level = res.object.find( - fixxpath(res.object, "EveryoneAccessLevel")).text - - # Parse all subjects - subjects = [] - xpath = fixxpath(res.object, "AccessSettings/AccessSetting") - for elem in res.object.findall(xpath): - access_level = elem.find(fixxpath(res.object, "AccessLevel")).text - subject_elem = elem.find(fixxpath(res.object, "Subject")) - if subject_elem.get('type') == \ - 'application/vnd.vmware.admin.group+xml': - subj_type = 'group' - else: - subj_type = 'user' - - path = get_url_path(subject_elem.get('href')) - res = self.connection.request(path) - name = res.object.get('name') - subject = Subject(type=subj_type, - name=name, - access_level=access_level, - id=subject_elem.get('href')) - subjects.append(subject) - - return ControlAccess(node, everyone_access_level, subjects) - - def ex_set_control_access(self, node, control_access): - """ - Sets control access for the specified node. - - :param node: node - :type node: :class:`Node` - - :param control_access: control access settings - :type control_access: :class:`ControlAccess` - - :rtype: ``None`` - """ - xml = ET.Element('ControlAccessParams', - {'xmlns': 'http://www.vmware.com/vcloud/v1.5'}) - shared_to_everyone = ET.SubElement(xml, 'IsSharedToEveryone') - if control_access.everyone_access_level: - shared_to_everyone.text = 'true' - everyone_access_level = ET.SubElement(xml, 'EveryoneAccessLevel') - everyone_access_level.text = control_access.everyone_access_level - else: - shared_to_everyone.text = 'false' - - # Set subjects - if control_access.subjects: - access_settings_elem = ET.SubElement(xml, 'AccessSettings') - for subject in control_access.subjects: - setting = ET.SubElement(access_settings_elem, 'AccessSetting') - if subject.id: - href = subject.id - else: - res = self.ex_query(type=subject.type, filter='name==' + - subject.name) - if not res: - raise LibcloudError('Specified subject "%s %s" not found ' - % (subject.type, subject.name)) - href = res[0]['href'] - ET.SubElement(setting, 'Subject', {'href': href}) - ET.SubElement(setting, 'AccessLevel').text = subject.access_level - - headers = { - 'Content-Type': 'application/vnd.vmware.vcloud.controlAccess+xml' - } - self.connection.request( - '%s/action/controlAccess' % get_url_path(node.id), - data=ET.tostring(xml), - headers=headers, - method='POST') - - def ex_get_metadata(self, node): - """ - :param node: node - :type node: :class:`Node` - - :return: dictionary mapping metadata keys to metadata values - :rtype: dictionary mapping ``str`` to ``str`` - """ - res = self.connection.request('%s/metadata' % (get_url_path(node.id))) - xpath = fixxpath(res.object, 'MetadataEntry') - metadata_entries = res.object.findall(xpath) - res_dict = {} - - for entry in metadata_entries: - key = entry.findtext(fixxpath(res.object, 'Key')) - value = entry.findtext(fixxpath(res.object, 'Value')) - res_dict[key] = value - - return res_dict - - def ex_set_metadata_entry(self, node, key, value): - """ - :param node: node - :type node: :class:`Node` - - :param key: metadata key to be set - :type key: ``str`` - - :param value: metadata value to be set - :type value: ``str`` - - :rtype: ``None`` - """ - metadata_elem = ET.Element( - 'Metadata', - {'xmlns': "http://www.vmware.com/vcloud/v1.5", - 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} - ) - entry = ET.SubElement(metadata_elem, 'MetadataEntry') - key_elem = ET.SubElement(entry, 'Key') - key_elem.text = key - value_elem = ET.SubElement(entry, 'Value') - value_elem.text = value - - # send it back to the server - res = self.connection.request( - '%s/metadata' % get_url_path(node.id), - data=ET.tostring(metadata_elem), - headers={ - 'Content-Type': 'application/vnd.vmware.vcloud.metadata+xml' - }, - method='POST') - self._wait_for_task_completion(res.object.get('href')) - - def ex_query(self, type, filter=None, page=1, page_size=100, sort_asc=None, - sort_desc=None): - """ - Queries vCloud for specified type. See - http://www.vmware.com/pdf/vcd_15_api_guide.pdf for details. Each - element of the returned list is a dictionary with all attributes from - the record. - - :param type: type to query (r.g. user, group, vApp etc.) - :type type: ``str`` - - :param filter: filter expression (see documentation for syntax) - :type filter: ``str`` - - :param page: page number - :type page: ``int`` - - :param page_size: page size - :type page_size: ``int`` - - :param sort_asc: sort in ascending order by specified field - :type sort_asc: ``str`` - - :param sort_desc: sort in descending order by specified field - :type sort_desc: ``str`` - - :rtype: ``list`` of dict - """ - # This is a workaround for filter parameter encoding - # the urllib encodes (name==Developers%20Only) into - # %28name%3D%3DDevelopers%20Only%29) which is not accepted by vCloud - params = { - 'type': type, - 'pageSize': page_size, - 'page': page, - } - if sort_asc: - params['sortAsc'] = sort_asc - if sort_desc: - params['sortDesc'] = sort_desc - - url = '/api/query?' + urlencode(params) - if filter: - if not filter.startswith('('): - filter = '(' + filter + ')' - url += '&filter=' + filter.replace(' ', '+') - - results = [] - res = self.connection.request(url) - for elem in res.object: - if not elem.tag.endswith('Link'): - result = elem.attrib - result['type'] = elem.tag.split('}')[1] - results.append(result) - return results - - def create_node(self, **kwargs): - """ - Creates and returns node. If the source image is: - - vApp template - a new vApp is instantiated from template - - existing vApp - a new vApp is cloned from the source vApp. Can - not clone more vApps is parallel otherwise - resource busy error is raised. - - - @inherits: :class:`NodeDriver.create_node` - - :keyword image: OS Image to boot on node. (required). Can be a - NodeImage or existing Node that will be cloned. - :type image: :class:`NodeImage` or :class:`Node` - - :keyword ex_network: Organisation's network name for attaching vApp - VMs to. - :type ex_network: ``str`` - - :keyword ex_vdc: Name of organisation's virtual data center where - vApp VMs will be deployed. - :type ex_vdc: ``str`` - - :keyword ex_vm_names: list of names to be used as a VM and computer - name. The name must be max. 15 characters - long and follow the host name requirements. - :type ex_vm_names: ``list`` of ``str`` - - :keyword ex_vm_cpu: number of virtual CPUs/cores to allocate for - each vApp VM. - :type ex_vm_cpu: ``int`` - - :keyword ex_vm_memory: amount of memory in MB to allocate for each - vApp VM. - :type ex_vm_memory: ``int`` - - :keyword ex_vm_script: full path to file containing guest - customisation script for each vApp VM. - Useful for creating users & pushing out - public SSH keys etc. - :type ex_vm_script: ``str`` - - :keyword ex_vm_network: Override default vApp VM network name. - Useful for when you've imported an OVF - originating from outside of the vCloud. - :type ex_vm_network: ``str`` - - :keyword ex_vm_fence: Fence mode for connecting the vApp VM network - (ex_vm_network) to the parent - organisation network (ex_network). - :type ex_vm_fence: ``str`` - - :keyword ex_vm_ipmode: IP address allocation mode for all vApp VM - network connections. - :type ex_vm_ipmode: ``str`` - - :keyword ex_deploy: set to False if the node shouldn't be deployed - (started) after creation - :type ex_deploy: ``bool`` - - :keyword ex_clone_timeout: timeout in seconds for clone/instantiate - VM operation. - Cloning might be a time consuming - operation especially when linked clones - are disabled or VMs are created on - different datastores. - Overrides the default task completion - value. - :type ex_clone_timeout: ``int`` - """ - name = kwargs['name'] - image = kwargs['image'] - ex_vm_names = kwargs.get('ex_vm_names') - ex_vm_cpu = kwargs.get('ex_vm_cpu') - ex_vm_memory = kwargs.get('ex_vm_memory') - ex_vm_script = kwargs.get('ex_vm_script') - ex_vm_fence = kwargs.get('ex_vm_fence', None) - ex_network = kwargs.get('ex_network', None) - ex_vm_network = kwargs.get('ex_vm_network', None) - ex_vm_ipmode = kwargs.get('ex_vm_ipmode', None) - ex_deploy = kwargs.get('ex_deploy', True) - ex_vdc = kwargs.get('ex_vdc', None) - ex_clone_timeout = kwargs.get('ex_clone_timeout', - DEFAULT_TASK_COMPLETION_TIMEOUT) - - self._validate_vm_names(ex_vm_names) - self._validate_vm_cpu(ex_vm_cpu) - self._validate_vm_memory(ex_vm_memory) - self._validate_vm_fence(ex_vm_fence) - self._validate_vm_ipmode(ex_vm_ipmode) - ex_vm_script = self._validate_vm_script(ex_vm_script) - - # Some providers don't require a network link - if ex_network: - network_href = self._get_network_href(ex_network) - network_elem = self.connection.request( - get_url_path(network_href)).object - else: - network_elem = None - - vdc = self._get_vdc(ex_vdc) - - if self._is_node(image): - vapp_name, vapp_href = self._clone_node(name, - image, - vdc, - ex_clone_timeout) - else: - vapp_name, vapp_href = self._instantiate_node(name, image, - network_elem, - vdc, ex_vm_network, - ex_vm_fence, - ex_clone_timeout) - - self._change_vm_names(vapp_href, ex_vm_names) - self._change_vm_cpu(vapp_href, ex_vm_cpu) - self._change_vm_memory(vapp_href, ex_vm_memory) - self._change_vm_script(vapp_href, ex_vm_script) - self._change_vm_ipmode(vapp_href, ex_vm_ipmode) - - # Power on the VM. - if ex_deploy: - # Retry 3 times: when instantiating large number of VMs at the same - # time some may fail on resource allocation - retry = 3 - while True: - try: - res = self.connection.request( - '%s/power/action/powerOn' % get_url_path(vapp_href), - method='POST') - self._wait_for_task_completion(res.object.get('href')) - break - except Exception: - if retry <= 0: - raise - retry -= 1 - time.sleep(10) - - res = self.connection.request(get_url_path(vapp_href)) - node = self._to_node(res.object) - return node - - def _instantiate_node(self, name, image, network_elem, vdc, vm_network, - vm_fence, instantiate_timeout): - instantiate_xml = Instantiate_1_5_VAppXML( - name=name, - template=image.id, - network=network_elem, - vm_network=vm_network, - vm_fence=vm_fence - ) - - # Instantiate VM and get identifier. - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml' - } - res = self.connection.request( - '%s/action/instantiateVAppTemplate' % get_url_path(vdc.id), - data=instantiate_xml.tostring(), - method='POST', - headers=headers - ) - vapp_name = res.object.get('name') - vapp_href = res.object.get('href') - - task_href = res.object.find(fixxpath(res.object, "Tasks/Task")).get( - 'href') - self._wait_for_task_completion(task_href, instantiate_timeout) - return vapp_name, vapp_href - - def _clone_node(self, name, sourceNode, vdc, clone_timeout): - clone_xml = ET.Element( - "CloneVAppParams", - {'name': name, 'deploy': 'false', 'powerOn': 'false', - 'xmlns': "http://www.vmware.com/vcloud/v1.5", - 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} - ) - ET.SubElement(clone_xml, - 'Description').text = 'Clone of ' + sourceNode.name - ET.SubElement(clone_xml, 'Source', {'href': sourceNode.id}) - - headers = { - 'Content-Type': 'application/vnd.vmware.vcloud.cloneVAppParams+xml' - } - res = self.connection.request( - '%s/action/cloneVApp' % get_url_path(vdc.id), - data=ET.tostring(clone_xml), - method='POST', - headers=headers - ) - vapp_name = res.object.get('name') - vapp_href = res.object.get('href') - - task_href = res.object.find( - fixxpath(res.object, "Tasks/Task")).get('href') - self._wait_for_task_completion(task_href, clone_timeout) - - res = self.connection.request(get_url_path(vapp_href)) - - vms = res.object.findall(fixxpath(res.object, "Children/Vm")) - - # Fix the networking for VMs - for i, vm in enumerate(vms): - # Remove network - network_xml = ET.Element("NetworkConnectionSection", { - 'ovf:required': 'false', - 'xmlns': "http://www.vmware.com/vcloud/v1.5", - 'xmlns:ovf': 'http://schemas.dmtf.org/ovf/envelope/1'}) - ET.SubElement(network_xml, "ovf:Info").text = \ - 'Specifies the available VM network connections' - - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.networkConnectionSection+xml' - } - res = self.connection.request( - '%s/networkConnectionSection' % get_url_path(vm.get('href')), - data=ET.tostring(network_xml), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - # Re-add network - network_xml = vm.find(fixxpath(vm, 'NetworkConnectionSection')) - network_conn_xml = network_xml.find( - fixxpath(network_xml, 'NetworkConnection')) - network_conn_xml.set('needsCustomization', 'true') - network_conn_xml.remove( - network_conn_xml.find(fixxpath(network_xml, 'IpAddress'))) - network_conn_xml.remove( - network_conn_xml.find(fixxpath(network_xml, 'MACAddress'))) - - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.networkConnectionSection+xml' - } - res = self.connection.request( - '%s/networkConnectionSection' % get_url_path(vm.get('href')), - data=ET.tostring(network_xml), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - return vapp_name, vapp_href - - def ex_set_vm_cpu(self, vapp_or_vm_id, vm_cpu): - """ - Sets the number of virtual CPUs for the specified VM or VMs under - the vApp. If the vapp_or_vm_id param represents a link to an vApp - all VMs that are attached to this vApp will be modified. - - Please ensure that hot-adding a virtual CPU is enabled for the - powered on virtual machines. Otherwise use this method on undeployed - vApp. - - :keyword vapp_or_vm_id: vApp or VM ID that will be modified. If - a vApp ID is used here all attached VMs - will be modified - :type vapp_or_vm_id: ``str`` - - :keyword vm_cpu: number of virtual CPUs/cores to allocate for - specified VMs - :type vm_cpu: ``int`` - - :rtype: ``None`` - """ - self._validate_vm_cpu(vm_cpu) - self._change_vm_cpu(vapp_or_vm_id, vm_cpu) - - def ex_set_vm_memory(self, vapp_or_vm_id, vm_memory): - """ - Sets the virtual memory in MB to allocate for the specified VM or - VMs under the vApp. If the vapp_or_vm_id param represents a link - to an vApp all VMs that are attached to this vApp will be modified. - - Please ensure that hot-change of virtual memory is enabled for the - powered on virtual machines. Otherwise use this method on undeployed - vApp. - - :keyword vapp_or_vm_id: vApp or VM ID that will be modified. If - a vApp ID is used here all attached VMs - will be modified - :type vapp_or_vm_id: ``str`` - - :keyword vm_memory: virtual memory in MB to allocate for the - specified VM or VMs - :type vm_memory: ``int`` - - :rtype: ``None`` - """ - self._validate_vm_memory(vm_memory) - self._change_vm_memory(vapp_or_vm_id, vm_memory) - - def ex_add_vm_disk(self, vapp_or_vm_id, vm_disk_size): - """ - Adds a virtual disk to the specified VM or VMs under the vApp. If the - vapp_or_vm_id param represents a link to an vApp all VMs that are - attached to this vApp will be modified. - - :keyword vapp_or_vm_id: vApp or VM ID that will be modified. If a - vApp ID is used here all attached VMs - will be modified - :type vapp_or_vm_id: ``str`` - - :keyword vm_disk_size: the disk capacity in GB that will be added - to the specified VM or VMs - :type vm_disk_size: ``int`` - - :rtype: ``None`` - """ - self._validate_vm_disk_size(vm_disk_size) - self._add_vm_disk(vapp_or_vm_id, vm_disk_size) - - @staticmethod - def _validate_vm_names(names): - if names is None: - return - hname_re = re.compile( - '^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9]*)[\-])*([A-Za-z]|[A-Za-z][A-Za-z0-9]*[A-Za-z0-9])$') # NOQA - for name in names: - if len(name) > 15: - raise ValueError( - 'The VM name "' + name + '" is too long for the computer ' - 'name (max 15 chars allowed).') - if not hname_re.match(name): - raise ValueError('The VM name "' + name + '" can not be ' - 'used. "' + name + '" is not a valid ' - 'computer name for the VM.') - - @staticmethod - def _validate_vm_memory(vm_memory): - if vm_memory is None: - return - elif vm_memory not in VIRTUAL_MEMORY_VALS: - raise ValueError( - '%s is not a valid vApp VM memory value' % vm_memory) - - @staticmethod - def _validate_vm_cpu(vm_cpu): - if vm_cpu is None: - return - elif vm_cpu not in VIRTUAL_CPU_VALS_1_5: - raise ValueError('%s is not a valid vApp VM CPU value' % vm_cpu) - - @staticmethod - def _validate_vm_disk_size(vm_disk): - if vm_disk is None: - return - elif int(vm_disk) < 0: - raise ValueError('%s is not a valid vApp VM disk space value', - vm_disk) - - @staticmethod - def _validate_vm_script(vm_script): - if vm_script is None: - return - # Try to locate the script file - if not os.path.isabs(vm_script): - vm_script = os.path.expanduser(vm_script) - vm_script = os.path.abspath(vm_script) - if not os.path.isfile(vm_script): - raise LibcloudError( - "%s the VM script file does not exist" % vm_script) - try: - open(vm_script).read() - except: - raise - return vm_script - - @staticmethod - def _validate_vm_fence(vm_fence): - if vm_fence is None: - return - elif vm_fence not in FENCE_MODE_VALS_1_5: - raise ValueError('%s is not a valid fencing mode value' % vm_fence) - - @staticmethod - def _validate_vm_ipmode(vm_ipmode): - if vm_ipmode is None: - return - elif vm_ipmode == 'MANUAL': - raise NotImplementedError( - 'MANUAL IP mode: The interface for supplying ' - 'IPAddress does not exist yet') - elif vm_ipmode not in IP_MODE_VALS_1_5: - raise ValueError( - '%s is not a valid IP address allocation mode value' - % vm_ipmode) - - def _change_vm_names(self, vapp_or_vm_id, vm_names): - if vm_names is None: - return - - vms = self._get_vm_elements(vapp_or_vm_id) - for i, vm in enumerate(vms): - if len(vm_names) <= i: - return - - # Get GuestCustomizationSection - res = self.connection.request( - '%s/guestCustomizationSection' % get_url_path(vm.get('href'))) - - # Update GuestCustomizationSection - res.object.find( - fixxpath(res.object, 'ComputerName')).text = vm_names[i] - # Remove AdminPassword from customization section - admin_pass = res.object.find(fixxpath(res.object, 'AdminPassword')) - if admin_pass is not None: - res.object.remove(admin_pass) - - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.guestCustomizationSection+xml' - } - res = self.connection.request( - '%s/guestCustomizationSection' % get_url_path(vm.get('href')), - data=ET.tostring(res.object), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - # Update Vm name - req_xml = ET.Element("Vm", { - 'name': vm_names[i], - 'xmlns': "http://www.vmware.com/vcloud/v1.5"}) - res = self.connection.request( - get_url_path(vm.get('href')), - data=ET.tostring(req_xml), - method='PUT', - headers={ - 'Content-Type': 'application/vnd.vmware.vcloud.vm+xml'} - ) - self._wait_for_task_completion(res.object.get('href')) - - def _change_vm_cpu(self, vapp_or_vm_id, vm_cpu): - if vm_cpu is None: - return - - vms = self._get_vm_elements(vapp_or_vm_id) - for vm in vms: - # Get virtualHardwareSection/cpu section - res = self.connection.request( - '%s/virtualHardwareSection/cpu' % get_url_path(vm.get('href'))) - - # Update VirtualQuantity field - xpath = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' - 'CIM_ResourceAllocationSettingData}VirtualQuantity') - res.object.find(xpath).text = str(vm_cpu) - - headers = { - 'Content-Type': 'application/vnd.vmware.vcloud.rasdItem+xml' - } - res = self.connection.request( - '%s/virtualHardwareSection/cpu' % get_url_path(vm.get('href')), - data=ET.tostring(res.object), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - def _change_vm_memory(self, vapp_or_vm_id, vm_memory): - if vm_memory is None: - return - - vms = self._get_vm_elements(vapp_or_vm_id) - for vm in vms: - # Get virtualHardwareSection/memory section - res = self.connection.request( - '%s/virtualHardwareSection/memory' % - get_url_path(vm.get('href'))) - - # Update VirtualQuantity field - xpath = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' - 'CIM_ResourceAllocationSettingData}VirtualQuantity') - res.object.find(xpath).text = str(vm_memory) - - headers = { - 'Content-Type': 'application/vnd.vmware.vcloud.rasdItem+xml' - } - res = self.connection.request( - '%s/virtualHardwareSection/memory' % get_url_path( - vm.get('href')), - data=ET.tostring(res.object), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - def _add_vm_disk(self, vapp_or_vm_id, vm_disk): - if vm_disk is None: - return - - rasd_ns = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' - 'CIM_ResourceAllocationSettingData}') - - vms = self._get_vm_elements(vapp_or_vm_id) - for vm in vms: - # Get virtualHardwareSection/disks section - res = self.connection.request( - '%s/virtualHardwareSection/disks' % - get_url_path(vm.get('href'))) - - existing_ids = [] - new_disk = None - for item in res.object.findall(fixxpath(res.object, 'Item')): - # Clean Items from unnecessary stuff - for elem in item: - if elem.tag == '%sInstanceID' % rasd_ns: - existing_ids.append(int(elem.text)) - if elem.tag in ['%sAddressOnParent' % rasd_ns, - '%sParent' % rasd_ns]: - item.remove(elem) - if item.find('%sHostResource' % rasd_ns) is not None: - new_disk = item - - new_disk = copy.deepcopy(new_disk) - disk_id = max(existing_ids) + 1 - new_disk.find('%sInstanceID' % rasd_ns).text = str(disk_id) - new_disk.find('%sElementName' % - rasd_ns).text = 'Hard Disk ' + str(disk_id) - new_disk.find('%sHostResource' % rasd_ns).set( - fixxpath(new_disk, 'capacity'), str(int(vm_disk) * 1024)) - res.object.append(new_disk) - - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.rasditemslist+xml' - } - res = self.connection.request( - '%s/virtualHardwareSection/disks' % get_url_path( - vm.get('href')), - data=ET.tostring(res.object), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - def _change_vm_script(self, vapp_or_vm_id, vm_script): - if vm_script is None: - return - - vms = self._get_vm_elements(vapp_or_vm_id) - try: - script = open(vm_script).read() - except: - return - - # ElementTree escapes script characters automatically. Escape - # requirements: - # http://www.vmware.com/support/vcd/doc/rest-api-doc-1.5-html/types/ - # GuestCustomizationSectionType.html - for vm in vms: - # Get GuestCustomizationSection - res = self.connection.request( - '%s/guestCustomizationSection' % get_url_path(vm.get('href'))) - - # Attempt to update any existing CustomizationScript element - try: - res.object.find( - fixxpath(res.object, 'CustomizationScript')).text = script - except: - # CustomizationScript section does not exist, insert it just - # before ComputerName - for i, e in enumerate(res.object): - if e.tag == \ - '{http://www.vmware.com/vcloud/v1.5}ComputerName': - break - e = ET.Element( - '{http://www.vmware.com/vcloud/v1.5}CustomizationScript') - e.text = script - res.object.insert(i, e) - - # Remove AdminPassword from customization section due to an API - # quirk - admin_pass = res.object.find(fixxpath(res.object, 'AdminPassword')) - if admin_pass is not None: - res.object.remove(admin_pass) - - # Update VM's GuestCustomizationSection - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.guestCustomizationSection+xml' - } - res = self.connection.request( - '%s/guestCustomizationSection' % get_url_path(vm.get('href')), - data=ET.tostring(res.object), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - def _change_vm_ipmode(self, vapp_or_vm_id, vm_ipmode): - if vm_ipmode is None: - return - - vms = self._get_vm_elements(vapp_or_vm_id) - - for vm in vms: - res = self.connection.request( - '%s/networkConnectionSection' % get_url_path(vm.get('href'))) - net_conns = res.object.findall( - fixxpath(res.object, 'NetworkConnection')) - for c in net_conns: - c.find(fixxpath(c, 'IpAddressAllocationMode')).text = vm_ipmode - - headers = { - 'Content-Type': - 'application/vnd.vmware.vcloud.networkConnectionSection+xml' - } - - res = self.connection.request( - '%s/networkConnectionSection' % get_url_path(vm.get('href')), - data=ET.tostring(res.object), - method='PUT', - headers=headers - ) - self._wait_for_task_completion(res.object.get('href')) - - def _get_network_href(self, network_name): - network_href = None - - # Find the organisation's network href - res = self.connection.request(self.org) - links = res.object.findall(fixxpath(res.object, 'Link')) - for l in links: - if l.attrib['type'] == \ - 'application/vnd.vmware.vcloud.orgNetwork+xml' \ - and l.attrib['name'] == network_name: - network_href = l.attrib['href'] - - if network_href is None: - raise ValueError( - '%s is not a valid organisation network name' % network_name) - else: - return network_href - - def _get_vm_elements(self, vapp_or_vm_id): - res = self.connection.request(get_url_path(vapp_or_vm_id)) - if res.object.tag.endswith('VApp'): - vms = res.object.findall(fixxpath(res.object, 'Children/Vm')) - elif res.object.tag.endswith('Vm'): - vms = [res.object] - else: - raise ValueError( - 'Specified ID value is not a valid VApp or Vm identifier.') - return vms - - def _is_node(self, node_or_image): - return isinstance(node_or_image, Node) - - def _to_node(self, node_elm): - # Parse VMs as extra field - vms = [] - for vm_elem in node_elm.findall(fixxpath(node_elm, 'Children/Vm')): - public_ips = [] - private_ips = [] - - xpath = fixxpath(vm_elem, - 'NetworkConnectionSection/NetworkConnection') - for connection in vm_elem.findall(xpath): - ip = connection.find(fixxpath(connection, "IpAddress")) - if ip is not None: - private_ips.append(ip.text) - external_ip = connection.find( - fixxpath(connection, "ExternalIpAddress")) - if external_ip is not None: - public_ips.append(external_ip.text) - elif ip is not None: - public_ips.append(ip.text) - - xpath = ('{http://schemas.dmtf.org/ovf/envelope/1}' - 'OperatingSystemSection') - os_type_elem = vm_elem.find(xpath) - if os_type_elem is not None: - os_type = os_type_elem.get( - '{http://www.vmware.com/schema/ovf}osType') - else: - os_type = None - vm = { - 'id': vm_elem.get('href'), - 'name': vm_elem.get('name'), - 'state': self.NODE_STATE_MAP[vm_elem.get('status')], - 'public_ips': public_ips, - 'private_ips': private_ips, - 'os_type': os_type - } - vms.append(vm) - - # Take the node IP addresses from all VMs - public_ips = [] - private_ips = [] - for vm in vms: - public_ips.extend(vm['public_ips']) - private_ips.extend(vm['private_ips']) - - # Find vDC - vdc_id = next(link.get('href') for link - in node_elm.findall(fixxpath(node_elm, 'Link')) - if link.get('type') == - 'application/vnd.vmware.vcloud.vdc+xml') - vdc = next(vdc for vdc in self.vdcs if vdc.id == vdc_id) - - node = Node(id=node_elm.get('href'), - name=node_elm.get('name'), - state=self.NODE_STATE_MAP[node_elm.get('status')], - public_ips=public_ips, - private_ips=private_ips, - driver=self.connection.driver, - extra={'vdc': vdc.name, 'vms': vms}) - return node - - def _to_vdc(self, vdc_elm): - - def get_capacity_values(capacity_elm): - if capacity_elm is None: - return None - limit = int(capacity_elm.findtext(fixxpath(capacity_elm, 'Limit'))) - used = int(capacity_elm.findtext(fixxpath(capacity_elm, 'Used'))) - units = capacity_elm.findtext(fixxpath(capacity_elm, 'Units')) - return Capacity(limit, used, units) - - cpu = get_capacity_values( - vdc_elm.find(fixxpath(vdc_elm, 'ComputeCapacity/Cpu'))) - memory = get_capacity_values( - vdc_elm.find(fixxpath(vdc_elm, 'ComputeCapacity/Memory'))) - storage = get_capacity_values( - vdc_elm.find(fixxpath(vdc_elm, 'StorageCapacity'))) - - return Vdc(id=vdc_elm.get('href'), - name=vdc_elm.get('name'), - driver=self, - allocation_model=vdc_elm.findtext( - fixxpath(vdc_elm, 'AllocationModel')), - cpu=cpu, - memory=memory, - storage=storage) - - -class VCloud_5_1_NodeDriver(VCloud_1_5_NodeDriver): - - @staticmethod - def _validate_vm_memory(vm_memory): - if vm_memory is None: - return None - elif (vm_memory % 4) != 0: - # The vcd 5.1 virtual machine memory size must be a multiple of 4 - # MB - raise ValueError( - '%s is not a valid vApp VM memory value' % (vm_memory)) diff --git a/awx/lib/site-packages/libcloud/compute/drivers/voxel.py b/awx/lib/site-packages/libcloud/compute/drivers/voxel.py deleted file mode 100644 index 98650272d1..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/voxel.py +++ /dev/null @@ -1,307 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Voxel VoxCloud driver -""" -import datetime -import hashlib - -from libcloud.utils.py3 import b - -from libcloud.common.base import XmlResponse, ConnectionUserAndKey -from libcloud.common.types import InvalidCredsError -from libcloud.compute.providers import Provider -from libcloud.compute.types import NodeState -from libcloud.compute.base import Node, NodeDriver -from libcloud.compute.base import NodeSize, NodeImage, NodeLocation - -VOXEL_API_HOST = "api.voxel.net" - - -class VoxelResponse(XmlResponse): - def __init__(self, response, connection): - self.parsed = None - super(VoxelResponse, self).__init__(response=response, - connection=connection) - - def parse_body(self): - if not self.body: - return None - if not self.parsed: - self.parsed = super(VoxelResponse, self).parse_body() - return self.parsed - - def parse_error(self): - err_list = [] - if not self.body: - return None - if not self.parsed: - self.parsed = super(VoxelResponse, self).parse_body() - for err in self.parsed.findall('err'): - code = err.get('code') - err_list.append("(%s) %s" % (code, err.get('msg'))) - # From voxel docs: - # 1: Invalid login or password - # 9: Permission denied: user lacks access rights for this method - if code == "1" or code == "9": - # sucks, but only way to detect - # bad authentication tokens so far - raise InvalidCredsError(err_list[-1]) - return "\n".join(err_list) - - def success(self): - if not self.parsed: - self.parsed = super(VoxelResponse, self).parse_body() - stat = self.parsed.get('stat') - if stat != "ok": - return False - return True - - -class VoxelConnection(ConnectionUserAndKey): - """ - Connection class for the Voxel driver - """ - - host = VOXEL_API_HOST - responseCls = VoxelResponse - - def add_default_params(self, params): - params = dict([(k, v) for k, v in list(params.items()) - if v is not None]) - params["key"] = self.user_id - params["timestamp"] = datetime.datetime.utcnow().isoformat() + "+0000" - - keys = list(params.keys()) - keys.sort() - - md5 = hashlib.md5() - md5.update(b(self.key)) - for key in keys: - if params[key]: - if not params[key] is None: - md5.update(b("%s%s" % (key, params[key]))) - else: - md5.update(b(key)) - params['api_sig'] = md5.hexdigest() - return params - -VOXEL_INSTANCE_TYPES = {} -RAM_PER_CPU = 2048 - -NODE_STATE_MAP = { - 'IN_PROGRESS': NodeState.PENDING, - 'QUEUED': NodeState.PENDING, - 'SUCCEEDED': NodeState.RUNNING, - 'shutting-down': NodeState.TERMINATED, - 'terminated': NodeState.TERMINATED, - 'unknown': NodeState.UNKNOWN, -} - - -class VoxelNodeDriver(NodeDriver): - """ - Voxel VoxCLOUD node driver - """ - - connectionCls = VoxelConnection - type = Provider.VOXEL - name = 'Voxel VoxCLOUD' - website = 'http://www.voxel.net/' - - def _initialize_instance_types(): - for cpus in range(1, 14): - if cpus == 1: - name = "Single CPU" - else: - name = "%d CPUs" % cpus - id = "%dcpu" % cpus - ram = cpus * RAM_PER_CPU - - VOXEL_INSTANCE_TYPES[id] = { - 'id': id, - 'name': name, - 'ram': ram, - 'disk': None, - 'bandwidth': None, - 'price': None} - - features = {"create_node": [], - "list_sizes": ["variable_disk"]} - - _initialize_instance_types() - - def list_nodes(self): - params = {"method": "voxel.devices.list"} - result = self.connection.request('/', params=params).object - return self._to_nodes(result) - - def list_sizes(self, location=None): - return [NodeSize(driver=self.connection.driver, **i) - for i in list(VOXEL_INSTANCE_TYPES.values())] - - def list_images(self, location=None): - params = {"method": "voxel.images.list"} - result = self.connection.request('/', params=params).object - return self._to_images(result) - - def create_node(self, **kwargs): - """Create Voxel Node - - :keyword name: the name to assign the node (mandatory) - :type name: ``str`` - - :keyword image: distribution to deploy - :type image: :class:`NodeImage` - - :keyword size: the plan size to create (mandatory) - Requires size.disk (GB) to be set manually - :type size: :class:`NodeSize` - - :keyword location: which datacenter to create the node in - :type location: :class:`NodeLocation` - - :keyword ex_privateip: Backend IP address to assign to node; - must be chosen from the customer's - private VLAN assignment. - :type ex_privateip: ``str`` - - :keyword ex_publicip: Public-facing IP address to assign to node; - must be chosen from the customer's - public VLAN assignment. - :type ex_publicip: ``str`` - - :keyword ex_rootpass: Password for root access; generated if unset. - :type ex_rootpass: ``str`` - - :keyword ex_consolepass: Password for remote console; - generated if unset. - :type ex_consolepass: ``str`` - - :keyword ex_sshuser: Username for SSH access - :type ex_sshuser: ``str`` - - :keyword ex_sshpass: Password for SSH access; generated if unset. - :type ex_sshpass: ``str`` - - :keyword ex_voxel_access: Allow access Voxel administrative access. - Defaults to False. - :type ex_voxel_access: ``bool`` - - :rtype: :class:`Node` or ``None`` - """ - - # assert that disk > 0 - if not kwargs["size"].disk: - raise ValueError("size.disk must be non-zero") - - # convert voxel_access to string boolean if needed - voxel_access = kwargs.get("ex_voxel_access", None) - if voxel_access is not None: - voxel_access = "true" if voxel_access else "false" - - params = { - 'method': 'voxel.voxcloud.create', - 'hostname': kwargs["name"], - 'disk_size': int(kwargs["size"].disk), - 'facility': kwargs["location"].id, - 'image_id': kwargs["image"].id, - 'processing_cores': kwargs["size"].ram / RAM_PER_CPU, - 'backend_ip': kwargs.get("ex_privateip", None), - 'frontend_ip': kwargs.get("ex_publicip", None), - 'admin_password': kwargs.get("ex_rootpass", None), - 'console_password': kwargs.get("ex_consolepass", None), - 'ssh_username': kwargs.get("ex_sshuser", None), - 'ssh_password': kwargs.get("ex_sshpass", None), - 'voxel_access': voxel_access, - } - - object = self.connection.request('/', params=params).object - - if self._getstatus(object): - return Node( - id=object.findtext("device/id"), - name=kwargs["name"], - state=NODE_STATE_MAP[object.findtext("device/status")], - public_ips=kwargs.get("publicip", None), - private_ips=kwargs.get("privateip", None), - driver=self.connection.driver - ) - else: - return None - - def reboot_node(self, node): - params = {'method': 'voxel.devices.power', - 'device_id': node.id, - 'power_action': 'reboot'} - return self._getstatus( - self.connection.request('/', params=params).object) - - def destroy_node(self, node): - params = {'method': 'voxel.voxcloud.delete', - 'device_id': node.id} - return self._getstatus( - self.connection.request('/', params=params).object) - - def list_locations(self): - params = {"method": "voxel.voxcloud.facilities.list"} - result = self.connection.request('/', params=params).object - nodes = self._to_locations(result) - return nodes - - def _getstatus(self, element): - status = element.attrib["stat"] - return status == "ok" - - def _to_locations(self, object): - return [NodeLocation(element.attrib["label"], - element.findtext("description"), - element.findtext("description"), - self) - for element in object.findall('facilities/facility')] - - def _to_nodes(self, object): - nodes = [] - for element in object.findall('devices/device'): - if element.findtext("type") == "Virtual Server": - try: - state = self.NODE_STATE_MAP[element.attrib['status']] - except KeyError: - state = NodeState.UNKNOWN - - public_ip = private_ip = None - ipassignments = element.findall("ipassignments/ipassignment") - for ip in ipassignments: - if ip.attrib["type"] == "frontend": - public_ip = ip.text - elif ip.attrib["type"] == "backend": - private_ip = ip.text - - nodes.append(Node(id=element.attrib['id'], - name=element.attrib['label'], - state=state, - public_ips=public_ip, - private_ips=private_ip, - driver=self.connection.driver)) - return nodes - - def _to_images(self, object): - images = [] - for element in object.findall("images/image"): - images.append(NodeImage(id=element.attrib["id"], - name=element.attrib["summary"], - driver=self.connection.driver)) - return images diff --git a/awx/lib/site-packages/libcloud/compute/drivers/vpsnet.py b/awx/lib/site-packages/libcloud/compute/drivers/vpsnet.py deleted file mode 100644 index 8d026a8c4a..0000000000 --- a/awx/lib/site-packages/libcloud/compute/drivers/vpsnet.py +++ /dev/null @@ -1,193 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -VPS.net driver -""" -import base64 - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import b - -from libcloud.common.base import ConnectionUserAndKey, JsonResponse -from libcloud.common.types import InvalidCredsError, MalformedResponseError -from libcloud.compute.providers import Provider -from libcloud.compute.types import NodeState -from libcloud.compute.base import Node, NodeDriver -from libcloud.compute.base import NodeSize, NodeImage, NodeLocation - -API_HOST = 'api.vps.net' -API_VERSION = 'api10json' - -RAM_PER_NODE = 256 -DISK_PER_NODE = 10 -BANDWIDTH_PER_NODE = 250 - - -class VPSNetResponse(JsonResponse): - def parse_body(self): - try: - return super(VPSNetResponse, self).parse_body() - except MalformedResponseError: - return self.body - - def success(self): - # vps.net wrongly uses 406 for invalid auth creds - if self.status == 406 or self.status == 403: - raise InvalidCredsError() - return True - - def parse_error(self): - try: - errors = super(VPSNetResponse, self).parse_body()['errors'][0] - except MalformedResponseError: - return self.body - else: - return "\n".join(errors) - - -class VPSNetConnection(ConnectionUserAndKey): - """ - Connection class for the VPS.net driver - """ - - host = API_HOST - responseCls = VPSNetResponse - - allow_insecure = False - - def add_default_headers(self, headers): - user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) - headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) - return headers - - -class VPSNetNodeDriver(NodeDriver): - """ - VPS.net node driver - """ - - type = Provider.VPSNET - api_name = 'vps_net' - name = "vps.net" - website = 'http://vps.net/' - connectionCls = VPSNetConnection - - def _to_node(self, vm): - if vm['running']: - state = NodeState.RUNNING - else: - state = NodeState.PENDING - - n = Node(id=vm['id'], - name=vm['label'], - state=state, - public_ips=[vm.get('primary_ip_address', None)], - private_ips=[], - extra={'slices_count': vm['slices_count']}, - # Number of nodes consumed by VM - driver=self.connection.driver) - return n - - def _to_image(self, image, cloud): - image = NodeImage(id=image['id'], - name="%s: %s" % (cloud, image['label']), - driver=self.connection.driver) - - return image - - def _to_size(self, num): - size = NodeSize(id=num, - name="%d Node" % (num,), - ram=RAM_PER_NODE * num, - disk=DISK_PER_NODE, - bandwidth=BANDWIDTH_PER_NODE * num, - price=self._get_price_per_node(num) * num, - driver=self.connection.driver) - return size - - def _get_price_per_node(self, num): - single_node_price = self._get_size_price(size_id='1') - return num * single_node_price - - def create_node(self, name, image, size, **kwargs): - """Create a new VPS.net node - - @inherits: :class:`NodeDriver.create_node` - - :keyword ex_backups_enabled: Enable automatic backups - :type ex_backups_enabled: ``bool`` - - :keyword ex_fqdn: Fully Qualified domain of the node - :type ex_fqdn: ``str`` - """ - headers = {'Content-Type': 'application/json'} - request = {'virtual_machine': - {'label': name, - 'fqdn': kwargs.get('ex_fqdn', ''), - 'system_template_id': image.id, - 'backups_enabled': kwargs.get('ex_backups_enabled', 0), - 'slices_required': size.id}} - - res = self.connection.request('/virtual_machines.%s' % (API_VERSION,), - data=json.dumps(request), - headers=headers, - method='POST') - node = self._to_node(res.object['virtual_machine']) - return node - - def reboot_node(self, node): - res = self.connection.request( - '/virtual_machines/%s/%s.%s' % (node.id, - 'reboot', - API_VERSION), - method="POST") - node = self._to_node(res.object['virtual_machine']) - return True - - def list_sizes(self, location=None): - res = self.connection.request('/nodes.%s' % (API_VERSION,)) - available_nodes = len([size for size in res.object - if size['slice']['virtual_machine_id']]) - sizes = [self._to_size(i) for i in range(1, available_nodes + 1)] - return sizes - - def destroy_node(self, node): - res = self.connection.request('/virtual_machines/%s.%s' - % (node.id, API_VERSION), - method='DELETE') - return res.status == 200 - - def list_nodes(self): - res = self.connection.request('/virtual_machines.%s' % (API_VERSION,)) - return [self._to_node(i['virtual_machine']) for i in res.object] - - def list_images(self, location=None): - res = self.connection.request('/available_clouds.%s' % (API_VERSION,)) - - images = [] - for cloud in res.object: - label = cloud['cloud']['label'] - templates = cloud['cloud']['system_templates'] - images.extend([self._to_image(image, label) - for image in templates]) - - return images - - def list_locations(self): - return [NodeLocation(0, "VPS.net Western US", 'US', self)] diff --git a/awx/lib/site-packages/libcloud/compute/providers.py b/awx/lib/site-packages/libcloud/compute/providers.py deleted file mode 100644 index 87b3f321d0..0000000000 --- a/awx/lib/site-packages/libcloud/compute/providers.py +++ /dev/null @@ -1,175 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Provider related utilities -""" - -from libcloud.utils.misc import get_driver as _get_provider_driver -from libcloud.utils.misc import set_driver as _set_provider_driver -from libcloud.compute.types import Provider, DEPRECATED_RACKSPACE_PROVIDERS -from libcloud.compute.types import OLD_CONSTANT_TO_NEW_MAPPING - -__all__ = [ - "Provider", - "DRIVERS", - "get_driver"] - -DRIVERS = { - Provider.DUMMY: - ('libcloud.compute.drivers.dummy', 'DummyNodeDriver'), - Provider.EC2_US_EAST: - ('libcloud.compute.drivers.ec2', 'EC2NodeDriver'), - Provider.EC2_EU_WEST: - ('libcloud.compute.drivers.ec2', 'EC2EUNodeDriver'), - Provider.EC2_US_WEST: - ('libcloud.compute.drivers.ec2', 'EC2USWestNodeDriver'), - Provider.EC2_US_WEST_OREGON: - ('libcloud.compute.drivers.ec2', 'EC2USWestOregonNodeDriver'), - Provider.EC2_AP_SOUTHEAST: - ('libcloud.compute.drivers.ec2', 'EC2APSENodeDriver'), - Provider.EC2_AP_NORTHEAST: - ('libcloud.compute.drivers.ec2', 'EC2APNENodeDriver'), - Provider.EC2_SA_EAST: - ('libcloud.compute.drivers.ec2', 'EC2SAEastNodeDriver'), - Provider.EC2_AP_SOUTHEAST2: - ('libcloud.compute.drivers.ec2', 'EC2APSESydneyNodeDriver'), - Provider.ECP: - ('libcloud.compute.drivers.ecp', 'ECPNodeDriver'), - Provider.ELASTICHOSTS: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsNodeDriver'), - Provider.ELASTICHOSTS_UK1: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsUK1NodeDriver'), - Provider.ELASTICHOSTS_UK2: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsUK2NodeDriver'), - Provider.ELASTICHOSTS_US1: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsUS1NodeDriver'), - Provider.ELASTICHOSTS_US2: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsUS2NodeDriver'), - Provider.ELASTICHOSTS_US3: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsUS3NodeDriver'), - Provider.ELASTICHOSTS_CA1: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsCA1NodeDriver'), - Provider.ELASTICHOSTS_AU1: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsAU1NodeDriver'), - Provider.ELASTICHOSTS_CN1: - ('libcloud.compute.drivers.elastichosts', 'ElasticHostsCN1NodeDriver'), - Provider.SKALICLOUD: - ('libcloud.compute.drivers.skalicloud', 'SkaliCloudNodeDriver'), - Provider.SERVERLOVE: - ('libcloud.compute.drivers.serverlove', 'ServerLoveNodeDriver'), - Provider.CLOUDSIGMA: - ('libcloud.compute.drivers.cloudsigma', 'CloudSigmaNodeDriver'), - Provider.GCE: - ('libcloud.compute.drivers.gce', 'GCENodeDriver'), - Provider.GOGRID: - ('libcloud.compute.drivers.gogrid', 'GoGridNodeDriver'), - Provider.RACKSPACE: - ('libcloud.compute.drivers.rackspace', 'RackspaceNodeDriver'), - Provider.RACKSPACE_FIRST_GEN: - ('libcloud.compute.drivers.rackspace', 'RackspaceFirstGenNodeDriver'), - Provider.HPCLOUD: - ('libcloud.compute.drivers.hpcloud', 'HPCloudNodeDriver'), - Provider.KILI: - ('libcloud.compute.drivers.kili', 'KiliCloudNodeDriver'), - Provider.VPSNET: - ('libcloud.compute.drivers.vpsnet', 'VPSNetNodeDriver'), - Provider.LINODE: - ('libcloud.compute.drivers.linode', 'LinodeNodeDriver'), - Provider.RIMUHOSTING: - ('libcloud.compute.drivers.rimuhosting', 'RimuHostingNodeDriver'), - Provider.VOXEL: - ('libcloud.compute.drivers.voxel', 'VoxelNodeDriver'), - Provider.SOFTLAYER: - ('libcloud.compute.drivers.softlayer', 'SoftLayerNodeDriver'), - Provider.EUCALYPTUS: - ('libcloud.compute.drivers.ec2', 'EucNodeDriver'), - Provider.IBM: - ('libcloud.compute.drivers.ibm_sce', 'IBMNodeDriver'), - Provider.OPENNEBULA: - ('libcloud.compute.drivers.opennebula', 'OpenNebulaNodeDriver'), - Provider.DREAMHOST: - ('libcloud.compute.drivers.dreamhost', 'DreamhostNodeDriver'), - Provider.BRIGHTBOX: - ('libcloud.compute.drivers.brightbox', 'BrightboxNodeDriver'), - Provider.NIMBUS: - ('libcloud.compute.drivers.ec2', 'NimbusNodeDriver'), - Provider.BLUEBOX: - ('libcloud.compute.drivers.bluebox', 'BlueboxNodeDriver'), - Provider.GANDI: - ('libcloud.compute.drivers.gandi', 'GandiNodeDriver'), - Provider.OPSOURCE: - ('libcloud.compute.drivers.opsource', 'OpsourceNodeDriver'), - Provider.OPENSTACK: - ('libcloud.compute.drivers.openstack', 'OpenStackNodeDriver'), - Provider.NINEFOLD: - ('libcloud.compute.drivers.ninefold', 'NinefoldNodeDriver'), - Provider.VCLOUD: - ('libcloud.compute.drivers.vcloud', 'VCloudNodeDriver'), - Provider.TERREMARK: - ('libcloud.compute.drivers.vcloud', 'TerremarkDriver'), - Provider.CLOUDSTACK: - ('libcloud.compute.drivers.cloudstack', 'CloudStackNodeDriver'), - Provider.LIBVIRT: - ('libcloud.compute.drivers.libvirt_driver', 'LibvirtNodeDriver'), - Provider.JOYENT: - ('libcloud.compute.drivers.joyent', 'JoyentNodeDriver'), - Provider.VCL: - ('libcloud.compute.drivers.vcl', 'VCLNodeDriver'), - Provider.KTUCLOUD: - ('libcloud.compute.drivers.ktucloud', 'KTUCloudNodeDriver'), - Provider.HOSTVIRTUAL: - ('libcloud.compute.drivers.hostvirtual', 'HostVirtualNodeDriver'), - Provider.ABIQUO: - ('libcloud.compute.drivers.abiquo', 'AbiquoNodeDriver'), - Provider.DIGITAL_OCEAN: - ('libcloud.compute.drivers.digitalocean', 'DigitalOceanNodeDriver'), - Provider.NEPHOSCALE: - ('libcloud.compute.drivers.nephoscale', 'NephoscaleNodeDriver'), - Provider.CLOUDFRAMES: - ('libcloud.compute.drivers.cloudframes', 'CloudFramesNodeDriver'), - Provider.EXOSCALE: - ('libcloud.compute.drivers.exoscale', 'ExoscaleNodeDriver'), - Provider.IKOULA: - ('libcloud.compute.drivers.ikoula', 'IkoulaNodeDriver'), - Provider.OUTSCALE_SAS: - ('libcloud.compute.drivers.ec2', 'OutscaleSASNodeDriver'), - Provider.OUTSCALE_INC: - ('libcloud.compute.drivers.ec2', 'OutscaleINCNodeDriver'), - - # Deprecated - Provider.CLOUDSIGMA_US: - ('libcloud.compute.drivers.cloudsigma', 'CloudSigmaLvsNodeDriver'), -} - - -def get_driver(provider): - if provider in DEPRECATED_RACKSPACE_PROVIDERS: - id_to_name_map = dict([(v, k) for k, v in Provider.__dict__.items()]) - old_name = id_to_name_map[provider] - new_name = id_to_name_map[OLD_CONSTANT_TO_NEW_MAPPING[provider]] - - url = 'http://s.apache.org/lc0140un' - msg = ('Provider constant %s has been removed. New constant ' - 'is now called %s.\n' - 'For more information on this change and how to modify your ' - 'code to work with it, please visit: %s' % - (old_name, new_name, url)) - raise Exception(msg) - - return _get_provider_driver(DRIVERS, provider) - - -def set_driver(provider, module, klass): - return _set_provider_driver(DRIVERS, provider, module, klass) diff --git a/awx/lib/site-packages/libcloud/compute/ssh.py b/awx/lib/site-packages/libcloud/compute/ssh.py deleted file mode 100644 index af9c43a529..0000000000 --- a/awx/lib/site-packages/libcloud/compute/ssh.py +++ /dev/null @@ -1,530 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Wraps multiple ways to communicate over SSH. -""" - -have_paramiko = False - -try: - import paramiko - have_paramiko = True -except ImportError: - pass - -# Depending on your version of Paramiko, it may cause a deprecation -# warning on Python 2.6. -# Ref: https://bugs.launchpad.net/paramiko/+bug/392973 - -import os -import time -import subprocess -import logging -import warnings - -from os.path import split as psplit -from os.path import join as pjoin - -from libcloud.utils.logging import ExtraLogFormatter -from libcloud.utils.py3 import StringIO - -__all__ = [ - 'BaseSSHClient', - 'ParamikoSSHClient', - 'ShellOutSSHClient', - - 'SSHCommandTimeoutError' -] - - -# Maximum number of bytes to read at once from a socket -CHUNK_SIZE = 1024 - - -class SSHCommandTimeoutError(Exception): - """ - Exception which is raised when an SSH command times out. - """ - def __init__(self, cmd, timeout): - self.cmd = cmd - self.timeout = timeout - message = 'Command didn\'t finish in %s seconds' % (timeout) - super(SSHCommandTimeoutError, self).__init__(message) - - def __repr__(self): - return ('<SSHCommandTimeoutError: cmd="%s",timeout=%s)>' % - (self.cmd, self.timeout)) - - def __str__(self): - return self.message - - -class BaseSSHClient(object): - """ - Base class representing a connection over SSH/SCP to a remote node. - """ - - def __init__(self, hostname, port=22, username='root', password=None, - key=None, key_files=None, timeout=None): - """ - :type hostname: ``str`` - :keyword hostname: Hostname or IP address to connect to. - - :type port: ``int`` - :keyword port: TCP port to communicate on, defaults to 22. - - :type username: ``str`` - :keyword username: Username to use, defaults to root. - - :type password: ``str`` - :keyword password: Password to authenticate with or a password used - to unlock a private key if a password protected key - is used. - - :param key: Deprecated in favor of ``key_files`` argument. - - :type key_files: ``str`` or ``list`` - :keyword key_files: A list of paths to the private key files to use. - """ - if key is not None: - message = ('You are using deprecated "key" argument which has ' - 'been replaced with "key_files" argument') - warnings.warn(message, DeprecationWarning) - - # key_files has precedent - key_files = key if not key_files else key_files - - self.hostname = hostname - self.port = port - self.username = username - self.password = password - self.key_files = key_files - self.timeout = timeout - - def connect(self): - """ - Connect to the remote node over SSH. - - :return: True if the connection has been successfuly established, False - otherwise. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'connect not implemented for this ssh client') - - def put(self, path, contents=None, chmod=None, mode='w'): - """ - Upload a file to the remote node. - - :type path: ``str`` - :keyword path: File path on the remote node. - - :type contents: ``str`` - :keyword contents: File Contents. - - :type chmod: ``int`` - :keyword chmod: chmod file to this after creation. - - :type mode: ``str`` - :keyword mode: Mode in which the file is opened. - - :return: Full path to the location where a file has been saved. - :rtype: ``str`` - """ - raise NotImplementedError( - 'put not implemented for this ssh client') - - def delete(self, path): - """ - Delete/Unlink a file on the remote node. - - :type path: ``str`` - :keyword path: File path on the remote node. - - :return: True if the file has been successfuly deleted, False - otherwise. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'delete not implemented for this ssh client') - - def run(self, cmd): - """ - Run a command on a remote node. - - :type cmd: ``str`` - :keyword cmd: Command to run. - - :return ``list`` of [stdout, stderr, exit_status] - """ - raise NotImplementedError( - 'run not implemented for this ssh client') - - def close(self): - """ - Shutdown connection to the remote node. - - :return: True if the connection has been successfuly closed, False - otherwise. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'close not implemented for this ssh client') - - def _get_and_setup_logger(self): - logger = logging.getLogger('libcloud.compute.ssh') - path = os.getenv('LIBCLOUD_DEBUG') - - if path: - handler = logging.FileHandler(path) - handler.setFormatter(ExtraLogFormatter()) - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - return logger - - -class ParamikoSSHClient(BaseSSHClient): - - """ - A SSH Client powered by Paramiko. - """ - def __init__(self, hostname, port=22, username='root', password=None, - key=None, key_files=None, key_material=None, timeout=None): - """ - Authentication is always attempted in the following order: - - - The key passed in (if key is provided) - - Any key we can find through an SSH agent (only if no password and - key is provided) - - Any "id_rsa" or "id_dsa" key discoverable in ~/.ssh/ (only if no - password and key is provided) - - Plain username/password auth, if a password was given (if password is - provided) - """ - if key_files and key_material: - raise ValueError(('key_files and key_material arguments are ' - 'mutually exclusive')) - - super(ParamikoSSHClient, self).__init__(hostname=hostname, port=port, - username=username, - password=password, - key=key, - key_files=key_files, - timeout=timeout) - - self.key_material = key_material - - self.client = paramiko.SSHClient() - self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - self.logger = self._get_and_setup_logger() - - def connect(self): - conninfo = {'hostname': self.hostname, - 'port': self.port, - 'username': self.username, - 'allow_agent': False, - 'look_for_keys': False} - - if self.password: - conninfo['password'] = self.password - - if self.key_files: - conninfo['key_filename'] = self.key_files - - if self.key_material: - conninfo['pkey'] = self._get_pkey_object(key=self.key_material) - - if not self.password and not (self.key_files or self.key_material): - conninfo['allow_agent'] = True - conninfo['look_for_keys'] = True - - if self.timeout: - conninfo['timeout'] = self.timeout - - extra = {'_hostname': self.hostname, '_port': self.port, - '_username': self.username, '_timeout': self.timeout} - self.logger.debug('Connecting to server', extra=extra) - - self.client.connect(**conninfo) - return True - - def put(self, path, contents=None, chmod=None, mode='w'): - extra = {'_path': path, '_mode': mode, '_chmod': chmod} - self.logger.debug('Uploading file', extra=extra) - - sftp = self.client.open_sftp() - # less than ideal, but we need to mkdir stuff otherwise file() fails - head, tail = psplit(path) - - if path[0] == "/": - sftp.chdir("/") - else: - # Relative path - start from a home directory (~) - sftp.chdir('.') - - for part in head.split("/"): - if part != "": - try: - sftp.mkdir(part) - except IOError: - # so, there doesn't seem to be a way to - # catch EEXIST consistently *sigh* - pass - sftp.chdir(part) - - cwd = sftp.getcwd() - - ak = sftp.file(tail, mode=mode) - ak.write(contents) - if chmod is not None: - ak.chmod(chmod) - ak.close() - sftp.close() - - if path[0] == '/': - file_path = path - else: - file_path = pjoin(cwd, path) - - return file_path - - def delete(self, path): - extra = {'_path': path} - self.logger.debug('Deleting file', extra=extra) - - sftp = self.client.open_sftp() - sftp.unlink(path) - sftp.close() - return True - - def run(self, cmd, timeout=None): - """ - Note: This function is based on paramiko's exec_command() - method. - - :param timeout: How long to wait (in seconds) for the command to - finish (optional). - :type timeout: ``float`` - """ - extra = {'_cmd': cmd} - self.logger.debug('Executing command', extra=extra) - - # Use the system default buffer size - bufsize = -1 - - transport = self.client.get_transport() - chan = transport.open_session() - - start_time = time.time() - chan.exec_command(cmd) - - stdout = StringIO() - stderr = StringIO() - - # Create a stdin file and immediately close it to prevent any - # interactive script from hanging the process. - stdin = chan.makefile('wb', bufsize) - stdin.close() - - # Receive all the output - # Note #1: This is used instead of chan.makefile approach to prevent - # buffering issues and hanging if the executed command produces a lot - # of output. - # - # Note #2: If you are going to remove "ready" checks inside the loop - # you are going to have a bad time. Trying to consume from a channel - # which is not ready will block for indefinitely. - exit_status_ready = chan.exit_status_ready() - - while not exit_status_ready: - current_time = time.time() - elapsed_time = (current_time - start_time) - - if timeout and (elapsed_time > timeout): - # TODO: Is this the right way to clean up? - chan.close() - - raise SSHCommandTimeoutError(cmd=cmd, timeout=timeout) - - if chan.recv_ready(): - data = chan.recv(CHUNK_SIZE) - - while data: - stdout.write(data) - ready = chan.recv_ready() - - if not ready: - break - - data = chan.recv(CHUNK_SIZE) - - if chan.recv_stderr_ready(): - data = chan.recv_stderr(CHUNK_SIZE) - - while data: - stderr.write(data) - ready = chan.recv_stderr_ready() - - if not ready: - break - - data = chan.recv_stderr(CHUNK_SIZE) - - # We need to check the exist status here, because the command could - # print some output and exit during this sleep bellow. - exit_status_ready = chan.exit_status_ready() - - if exit_status_ready: - break - - # Short sleep to prevent busy waiting - time.sleep(1.5) - - # Receive the exit status code of the command we ran. - status = chan.recv_exit_status() - - stdout = stdout.getvalue() - stderr = stderr.getvalue() - - extra = {'_status': status, '_stdout': stdout, '_stderr': stderr} - self.logger.debug('Command finished', extra=extra) - - return [stdout, stderr, status] - - def close(self): - self.logger.debug('Closing server connection') - - self.client.close() - return True - - def _get_pkey_object(self, key): - """ - Try to detect private key type and return paramiko.PKey object. - """ - - for cls in [paramiko.RSAKey, paramiko.DSSKey, paramiko.ECDSAKey]: - try: - key = cls.from_private_key(StringIO(key)) - except paramiko.ssh_exception.SSHException: - # Invalid key, try other key type - pass - else: - return key - - msg = 'Invalid or unsupported key type' - raise paramiko.ssh_exception.SSHException(msg) - - -class ShellOutSSHClient(BaseSSHClient): - """ - This client shells out to "ssh" binary to run commands on the remote - server. - - Note: This client should not be used in production. - """ - - def __init__(self, hostname, port=22, username='root', password=None, - key=None, key_files=None, timeout=None): - super(ShellOutSSHClient, self).__init__(hostname=hostname, - port=port, username=username, - password=password, - key=key, - key_files=key_files, - timeout=timeout) - if self.password: - raise ValueError('ShellOutSSHClient only supports key auth') - - child = subprocess.Popen(['ssh'], stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - child.communicate() - - if child.returncode == 127: - raise ValueError('ssh client is not available') - - self.logger = self._get_and_setup_logger() - - def connect(self): - """ - This client doesn't support persistent connections establish a new - connection every time "run" method is called. - """ - return True - - def run(self, cmd): - return self._run_remote_shell_command([cmd]) - - def put(self, path, contents=None, chmod=None, mode='w'): - if mode == 'w': - redirect = '>' - elif mode == 'a': - redirect = '>>' - else: - raise ValueError('Invalid mode: ' + mode) - - cmd = ['echo "%s" %s %s' % (contents, redirect, path)] - self._run_remote_shell_command(cmd) - return path - - def delete(self, path): - cmd = ['rm', '-rf', path] - self._run_remote_shell_command(cmd) - return True - - def close(self): - return True - - def _get_base_ssh_command(self): - cmd = ['ssh'] - - if self.key_files: - cmd += ['-i', self.key_files] - - if self.timeout: - cmd += ['-oConnectTimeout=%s' % (self.timeout)] - - cmd += ['%s@%s' % (self.username, self.hostname)] - - return cmd - - def _run_remote_shell_command(self, cmd): - """ - Run a command on a remote server. - - :param cmd: Command to run. - :type cmd: ``list`` of ``str`` - - :return: Command stdout, stderr and status code. - :rtype: ``tuple`` - """ - base_cmd = self._get_base_ssh_command() - full_cmd = base_cmd + [' '.join(cmd)] - - self.logger.debug('Executing command: "%s"' % (' '.join(full_cmd))) - - child = subprocess.Popen(full_cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = child.communicate() - return (stdout, stderr, child.returncode) - - -class MockSSHClient(BaseSSHClient): - pass - - -SSHClient = ParamikoSSHClient -if not have_paramiko: - SSHClient = MockSSHClient diff --git a/awx/lib/site-packages/libcloud/compute/types.py b/awx/lib/site-packages/libcloud/compute/types.py deleted file mode 100644 index 9f7a308cce..0000000000 --- a/awx/lib/site-packages/libcloud/compute/types.py +++ /dev/null @@ -1,249 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Base types used by other parts of libcloud -""" - -from libcloud.common.types import LibcloudError, MalformedResponseError -from libcloud.common.types import InvalidCredsError, InvalidCredsException - -__all__ = [ - "Provider", - "NodeState", - "DeploymentError", - "DeploymentException", - - # @@TR: should the unused imports below be exported? - "LibcloudError", - "MalformedResponseError", - "InvalidCredsError", - "InvalidCredsException", - "DEPRECATED_RACKSPACE_PROVIDERS", - "OLD_CONSTANT_TO_NEW_MAPPING" -] - - -class Provider(object): - """ - Defines for each of the supported providers - - :cvar DUMMY: Example provider - :cvar EC2_US_EAST: Amazon AWS US N. Virgina - :cvar EC2_US_WEST: Amazon AWS US N. California - :cvar EC2_EU_WEST: Amazon AWS EU Ireland - :cvar RACKSPACE: Rackspace next-gen OpenStack based Cloud Servers - :cvar RACKSPACE_FIRST_GEN: Rackspace First Gen Cloud Servers - :cvar GCE: Google Compute Engine - :cvar GOGRID: GoGrid - :cvar VPSNET: VPS.net - :cvar LINODE: Linode.com - :cvar VCLOUD: vmware vCloud - :cvar RIMUHOSTING: RimuHosting.com - :cvar ECP: Enomaly - :cvar IBM: IBM Developer Cloud - :cvar OPENNEBULA: OpenNebula.org - :cvar DREAMHOST: DreamHost Private Server - :cvar ELASTICHOSTS: ElasticHosts.com - :cvar CLOUDSIGMA: CloudSigma - :cvar NIMBUS: Nimbus - :cvar BLUEBOX: Bluebox - :cvar OPSOURCE: Opsource Cloud - :cvar NINEFOLD: Ninefold - :cvar TERREMARK: Terremark - :cvar EC2_US_WEST_OREGON: Amazon AWS US West 2 (Oregon) - :cvar CLOUDSTACK: CloudStack - :cvar CLOUDSIGMA_US: CloudSigma US Las Vegas - :cvar LIBVIRT: Libvirt driver - :cvar JOYENT: Joyent driver - :cvar VCL: VCL driver - :cvar KTUCLOUD: kt ucloud driver - :cvar GRIDSPOT: Gridspot driver - :cvar ABIQUO: Abiquo driver - :cvar NEPHOSCALE: NephoScale driver - :cvar EXOSCALE: Exoscale driver. - :cvar IKOULA: Ikoula driver. - :cvar OUTSCALE_SAS: Outscale SAS driver. - :cvar OUTSCALE_INC: Outscale INC driver. - """ - DUMMY = 'dummy' - EC2 = 'ec2_us_east' - RACKSPACE = 'rackspace' - GCE = 'gce' - GOGRID = 'gogrid' - VPSNET = 'vpsnet' - LINODE = 'linode' - VCLOUD = 'vcloud' - RIMUHOSTING = 'rimuhosting' - VOXEL = 'voxel' - SOFTLAYER = 'softlayer' - EUCALYPTUS = 'eucalyptus' - ECP = 'ecp' - IBM = 'ibm' - OPENNEBULA = 'opennebula' - DREAMHOST = 'dreamhost' - ELASTICHOSTS = 'elastichosts' - BRIGHTBOX = 'brightbox' - CLOUDSIGMA = 'cloudsigma' - NIMBUS = 'nimbus' - BLUEBOX = 'bluebox' - GANDI = 'gandi' - OPSOURCE = 'opsource' - OPENSTACK = 'openstack' - SKALICLOUD = 'skalicloud' - SERVERLOVE = 'serverlove' - NINEFOLD = 'ninefold' - TERREMARK = 'terremark' - CLOUDSTACK = 'cloudstack' - LIBVIRT = 'libvirt' - JOYENT = 'joyent' - VCL = 'vcl' - KTUCLOUD = 'ktucloud' - GRIDSPOT = 'gridspot' - RACKSPACE_FIRST_GEN = 'rackspace_first_gen' - HOSTVIRTUAL = 'hostvirtual' - ABIQUO = 'abiquo' - DIGITAL_OCEAN = 'digitalocean' - NEPHOSCALE = 'nephoscale' - CLOUDFRAMES = 'cloudframes' - EXOSCALE = 'exoscale' - IKOULA = 'ikoula' - OUTSCALE_SAS = 'outscale_sas' - OUTSCALE_INC = 'outscale_inc' - - # OpenStack based providers - HPCLOUD = 'hpcloud' - KILI = 'kili' - - # Deprecated constants which are still supported - EC2_US_EAST = 'ec2_us_east' - EC2_EU = 'ec2_eu_west' # deprecated name - EC2_EU_WEST = 'ec2_eu_west' - EC2_US_WEST = 'ec2_us_west' - EC2_AP_SOUTHEAST = 'ec2_ap_southeast' - EC2_AP_NORTHEAST = 'ec2_ap_northeast' - EC2_US_WEST_OREGON = 'ec2_us_west_oregon' - EC2_SA_EAST = 'ec2_sa_east' - EC2_AP_SOUTHEAST2 = 'ec2_ap_southeast_2' - - ELASTICHOSTS_UK1 = 'elastichosts_uk1' - ELASTICHOSTS_UK2 = 'elastichosts_uk2' - ELASTICHOSTS_US1 = 'elastichosts_us1' - ELASTICHOSTS_US2 = 'elastichosts_us2' - ELASTICHOSTS_US3 = 'elastichosts_us3' - ELASTICHOSTS_CA1 = 'elastichosts_ca1' - ELASTICHOSTS_AU1 = 'elastichosts_au1' - ELASTICHOSTS_CN1 = 'elastichosts_cn1' - - CLOUDSIGMA_US = 'cloudsigma_us' - - # Deprecated constants which aren't supported anymore - RACKSPACE_UK = 'rackspace_uk' - RACKSPACE_NOVA_BETA = 'rackspace_nova_beta' - RACKSPACE_NOVA_DFW = 'rackspace_nova_dfw' - RACKSPACE_NOVA_LON = 'rackspace_nova_lon' - RACKSPACE_NOVA_ORD = 'rackspace_nova_ord' - - # Removed - # SLICEHOST = 'slicehost' - - -DEPRECATED_RACKSPACE_PROVIDERS = [Provider.RACKSPACE_UK, - Provider.RACKSPACE_NOVA_BETA, - Provider.RACKSPACE_NOVA_DFW, - Provider.RACKSPACE_NOVA_LON, - Provider.RACKSPACE_NOVA_ORD] -OLD_CONSTANT_TO_NEW_MAPPING = { - Provider.RACKSPACE: Provider.RACKSPACE_FIRST_GEN, - Provider.RACKSPACE_UK: Provider.RACKSPACE_FIRST_GEN, - - Provider.RACKSPACE_NOVA_BETA: Provider.RACKSPACE, - Provider.RACKSPACE_NOVA_DFW: Provider.RACKSPACE, - Provider.RACKSPACE_NOVA_LON: Provider.RACKSPACE, - Provider.RACKSPACE_NOVA_ORD: Provider.RACKSPACE -} - - -class NodeState(object): - """ - Standard states for a node - - :cvar RUNNING: Node is running. - :cvar REBOOTING: Node is rebooting. - :cvar TERMINATED: Node is terminated. This node can't be started later on. - :cvar STOPPED: Node is stopped. This node can be started later on. - :cvar PENDING: Node is pending. - :cvar UNKNOWN: Node state is unknown. - """ - RUNNING = 0 - REBOOTING = 1 - TERMINATED = 2 - PENDING = 3 - UNKNOWN = 4 - STOPPED = 5 - - -class Architecture(object): - """ - Image and size architectures. - - :cvar I386: i386 (32 bt) - :cvar X86_64: x86_64 (64 bit) - """ - I386 = 0 - X86_X64 = 1 - - -class DeploymentError(LibcloudError): - """ - Exception used when a Deployment Task failed. - - :ivar node: :class:`Node` on which this exception happened, you might want - to call :func:`Node.destroy` - """ - def __init__(self, node, original_exception=None, driver=None): - self.node = node - self.value = original_exception - self.driver = driver - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return (('<DeploymentError: node=%s, error=%s, driver=%s>' - % (self.node.id, str(self.value), str(self.driver)))) - - -class KeyPairError(LibcloudError): - error_type = 'KeyPairError' - - def __init__(self, name, driver): - self.name = name - self.value = 'Key pair with name %s does not exist' % (name) - super(KeyPairError, self).__init__(value=self.value, driver=driver) - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return ('<%s name=%s, value=%s, driver=%s>' % - (self.error_type, self.name, self.value, self.driver.name)) - - -class KeyPairDoesNotExistError(KeyPairError): - error_type = 'KeyPairDoesNotExistError' - - -"""Deprecated alias of :class:`DeploymentException`""" -DeploymentException = DeploymentError diff --git a/awx/lib/site-packages/libcloud/data/pricing.json b/awx/lib/site-packages/libcloud/data/pricing.json deleted file mode 100644 index e8aa7bf3c2..0000000000 --- a/awx/lib/site-packages/libcloud/data/pricing.json +++ /dev/null @@ -1,566 +0,0 @@ -{ - "compute": { - "ec2_us_west_oregon": { - "m3.medium": "0.070", - "m3.large": "0.140", - "m3.xlarge": "0.280", - "m3.2xlarge": "0.560", - "m1.small": "0.044", - "m1.medium": "0.087", - "m1.large": "0.175", - "m1.xlarge": "0.350", - "c3.large": "0.105", - "c3.xlarge": "0.210", - "c3.2xlarge": "0.420", - "c3.4xlarge": "0.840", - "c3.8xlarge": "1.680", - "c1.medium": "0.130", - "c1.xlarge": "0.520", - "cc2.8xlarge": "2.000", - "g2.2xlarge": "0.650", - "r3.large": "0.175", - "r3.xlarge": "0.350", - "r3.2xlarge": "0.700", - "r3.4xlarge": "1.400", - "r3.8xlarge": "2.800", - "m2.xlarge": "0.245", - "m2.2xlarge": "0.490", - "m2.4xlarge": "0.980", - "cr1.8xlarge": "3.500", - "i2.xlarge": "0.853", - "i2.2xlarge": "1.705", - "i2.4xlarge": "3.410", - "i2.8xlarge": "6.820", - "hs1.8xlarge": "4.600", - "hi1.4xlarge": "3.100", - "t1.micro": "0.020" - }, - "ec2_us_west": { - "m3.medium": "0.077", - "m3.large": "0.154", - "m3.xlarge": "0.308", - "m3.2xlarge": "0.616", - "m1.small": "0.047", - "m1.medium": "0.095", - "m1.large": "0.190", - "m1.xlarge": "0.379", - "c3.large": "0.120", - "c3.xlarge": "0.239", - "c3.2xlarge": "0.478", - "c3.4xlarge": "0.956", - "c3.8xlarge": "1.912", - "c1.medium": "0.148", - "c1.xlarge": "0.592", - "g2.2xlarge": "0.702", - "r3.large": "0.195", - "r3.xlarge": "0.390", - "r3.2xlarge": "0.780", - "r3.4xlarge": "1.560", - "r3.8xlarge": "3.120", - "m2.xlarge": "0.275", - "m2.2xlarge": "0.550", - "m2.4xlarge": "1.100", - "i2.xlarge": "0.938", - "i2.2xlarge": "1.876", - "i2.4xlarge": "3.751", - "i2.8xlarge": "7.502", - "t1.micro": "0.025" - }, - "ec2_eu_west": { - "m3.medium": "0.077", - "m3.large": "0.154", - "m3.xlarge": "0.308", - "m3.2xlarge": "0.616", - "m1.small": "0.047", - "m1.medium": "0.095", - "m1.large": "0.190", - "m1.xlarge": "0.379", - "c3.large": "0.120", - "c3.xlarge": "0.239", - "c3.2xlarge": "0.478", - "c3.4xlarge": "0.956", - "c3.8xlarge": "1.912", - "c1.medium": "0.148", - "c1.xlarge": "0.592", - "cc2.8xlarge": "2.250", - "g2.2xlarge": "0.702", - "cg1.4xlarge": "2.360", - "r3.large": "0.195", - "r3.xlarge": "0.390", - "r3.2xlarge": "0.780", - "r3.4xlarge": "1.560", - "r3.8xlarge": "3.120", - "m2.xlarge": "0.275", - "m2.2xlarge": "0.550", - "m2.4xlarge": "1.100", - "cr1.8xlarge": "3.750", - "i2.xlarge": "0.938", - "i2.2xlarge": "1.876", - "i2.4xlarge": "3.751", - "i2.8xlarge": "7.502", - "hs1.8xlarge": "4.900", - "hi1.4xlarge": "3.100", - "t1.micro": "0.020" - }, - "rackspacenovalon": { - "performance2-60": 2.72, - "performance2-120": 5.44, - "performance1-1": 0.04, - "performance2-15": 0.68, - "performance1-4": 0.16, - "performance2-30": 1.36, - "performance2-90": 4.08, - "3": 0.064, - "2": 0.032, - "performance1-2": 0.08, - "4": 0.129, - "7": 0.967, - "6": 0.516, - "5": 0.258, - "performance1-8": 0.32, - "8": 1.612 - }, - "ec2_ap_southeast_2": { - "m3.medium": "0.098", - "m3.large": "0.196", - "m3.xlarge": "0.392", - "m3.2xlarge": "0.784", - "m1.small": "0.058", - "m1.medium": "0.117", - "m1.large": "0.233", - "m1.xlarge": "0.467", - "c3.large": "0.132", - "c3.xlarge": "0.265", - "c3.2xlarge": "0.529", - "c3.4xlarge": "1.058", - "c3.8xlarge": "2.117", - "c1.medium": "0.164", - "c1.xlarge": "0.655", - "r3.large": "0.210", - "r3.xlarge": "0.420", - "r3.2xlarge": "0.840", - "r3.4xlarge": "1.680", - "r3.8xlarge": "3.360", - "m2.xlarge": "0.296", - "m2.2xlarge": "0.592", - "m2.4xlarge": "1.183", - "i2.xlarge": "1.018", - "i2.2xlarge": "2.035", - "i2.4xlarge": "4.070", - "i2.8xlarge": "8.140", - "hs1.8xlarge": "5.570", - "t1.micro": "0.020" - }, - "vps_net": { - "1": 0.416 - }, - "ec2_us_east": { - "m3.medium": "0.070", - "m3.large": "0.140", - "m3.xlarge": "0.280", - "m3.2xlarge": "0.560", - "m1.small": "0.044", - "m1.medium": "0.087", - "m1.large": "0.175", - "m1.xlarge": "0.350", - "c3.large": "0.105", - "c3.xlarge": "0.210", - "c3.2xlarge": "0.420", - "c3.4xlarge": "0.840", - "c3.8xlarge": "1.680", - "c1.medium": "0.130", - "c1.xlarge": "0.520", - "cc2.8xlarge": "2.000", - "g2.2xlarge": "0.650", - "cg1.4xlarge": "2.100", - "r3.large": "0.175", - "r3.xlarge": "0.350", - "r3.2xlarge": "0.700", - "r3.4xlarge": "1.400", - "r3.8xlarge": "2.800", - "m2.xlarge": "0.245", - "m2.2xlarge": "0.490", - "m2.4xlarge": "0.980", - "cr1.8xlarge": "3.500", - "i2.xlarge": "0.853", - "i2.2xlarge": "1.705", - "i2.4xlarge": "3.410", - "i2.8xlarge": "6.820", - "hs1.8xlarge": "4.600", - "hi1.4xlarge": "3.100", - "t1.micro": "0.020" - }, - "rackspacenovaus": { - "performance2-60": 2.72, - "performance2-120": 5.44, - "performance1-1": 0.04, - "performance2-15": 0.68, - "performance1-4": 0.16, - "performance2-30": 1.36, - "performance2-90": 4.08, - "3": 0.06, - "2": 0.022, - "performance1-2": 0.08, - "4": 0.12, - "7": 0.96, - "6": 0.48, - "5": 0.24, - "performance1-8": 0.32, - "8": 1.2 - }, - "ec2_sa_east": { - "m3.medium": "0.095", - "m3.large": "0.190", - "m3.xlarge": "0.381", - "m3.2xlarge": "0.761", - "m1.small": "0.058", - "m1.medium": "0.117", - "m1.large": "0.233", - "m1.xlarge": "0.467", - "c1.medium": "0.179", - "c1.xlarge": "0.718", - "m2.xlarge": "0.323", - "m2.2xlarge": "0.645", - "m2.4xlarge": "1.291", - "t1.micro": "0.027" - }, - "cloudsigma_zrh": { - "high-cpu-medium": 0.211, - "standard-large": 0.381, - "micro-high-cpu": 0.381, - "standard-extra-large": 0.762, - "high-memory-double-extra-large": 1.383, - "micro-regular": 0.0548, - "standard-small": 0.0796, - "high-memory-extra-large": 0.642, - "high-cpu-extra-large": 0.78 - }, - "rackspacenovasyd": { - "performance2-60": 2.72, - "performance2-120": 5.44, - "performance1-1": 0.04, - "performance2-15": 0.68, - "performance1-4": 0.16, - "performance2-30": 1.36, - "performance2-90": 4.08, - "3": 0.072, - "2": 0.026, - "performance1-2": 0.08, - "4": 0.144, - "7": 1.08, - "6": 0.576, - "5": 0.288, - "performance1-8": 0.32, - "8": 1.44 - }, - "ec2_ap_northeast": { - "m3.medium": "0.101", - "m3.large": "0.203", - "m3.xlarge": "0.405", - "m3.2xlarge": "0.810", - "m1.small": "0.061", - "m1.medium": "0.122", - "m1.large": "0.243", - "m1.xlarge": "0.486", - "c3.large": "0.128", - "c3.xlarge": "0.255", - "c3.2xlarge": "0.511", - "c3.4xlarge": "1.021", - "c3.8xlarge": "2.043", - "c1.medium": "0.158", - "c1.xlarge": "0.632", - "cc2.8xlarge": "2.349", - "g2.2xlarge": "0.898", - "r3.large": "0.210", - "r3.xlarge": "0.420", - "r3.2xlarge": "0.840", - "r3.4xlarge": "1.680", - "r3.8xlarge": "3.360", - "m2.xlarge": "0.287", - "m2.2xlarge": "0.575", - "m2.4xlarge": "1.150", - "cr1.8xlarge": "4.105", - "i2.xlarge": "1.001", - "i2.2xlarge": "2.001", - "i2.4xlarge": "4.002", - "i2.8xlarge": "8.004", - "hs1.8xlarge": "5.400", - "hi1.4xlarge": "3.276", - "t1.micro": "0.026" - }, - "gogrid": { - "24GB": 4.56, - "512MB": 0.095, - "8GB": 1.52, - "4GB": 0.76, - "2GB": 0.38, - "1GB": 0.19, - "16GB": 3.04 - }, - "serverlove": { - "high-cpu-medium": 0.291, - "medium": 0.404, - "large": 0.534, - "small": 0.161, - "extra-large": 0.615, - "high-cpu-extra-large": 0.776 - }, - "elastichosts": { - "high-cpu-medium": 0.18, - "medium": 0.223, - "large": 0.378, - "small": 0.1, - "extra-large": 0.579, - "high-cpu-extra-large": 0.77 - }, - "rackspace": { - "performance2-60": 2.72, - "performance2-120": 5.44, - "performance1-1": 0.04, - "performance2-15": 0.68, - "performance1-4": 0.16, - "performance2-30": 1.36, - "1": 0.015, - "performance2-90": 4.08, - "3": 0.06, - "2": 0.03, - "performance1-2": 0.08, - "4": 0.12, - "7": 0.96, - "6": 0.48, - "5": 0.24, - "performance1-8": 0.32, - "8": 1.8 - }, - "nephoscale": { - "11": 0.35, - "27": 0.0, - "48": 0.15, - "46": 0.1, - "54": 0.938, - "56": 0.75, - "50": 0.28, - "52": 0.48, - "1": 0.6, - "3": 0.063, - "5": 0.031, - "7": 0.125, - "9": 0.188 - }, - "nimbus": { - "m1.xlarge": 0.0, - "m1.small": 0.0, - "m1.large": 0.0 - }, - "gandi": { - "1": 0.02, - "small": 0.02, - "large": 0.06, - "medium": 0.03, - "x-large": 0.12 - }, - "skalicloud": { - "high-cpu-medium": 0.249, - "medium": 0.301, - "large": 0.505, - "small": 0.136, - "extra-large": 0.654, - "high-cpu-extra-large": 0.936 - }, - "bluebox": { - "4gb": 0.35, - "2gb": 0.25, - "8gb": 0.45, - "1gb": 0.15 - }, - "ec2_ap_southeast": { - "m3.medium": "0.098", - "m3.large": "0.196", - "m3.xlarge": "0.392", - "m3.2xlarge": "0.784", - "m1.small": "0.058", - "m1.medium": "0.117", - "m1.large": "0.233", - "m1.xlarge": "0.467", - "c3.large": "0.132", - "c3.xlarge": "0.265", - "c3.2xlarge": "0.529", - "c3.4xlarge": "1.058", - "c3.8xlarge": "2.117", - "c1.medium": "0.164", - "c1.xlarge": "0.655", - "r3.large": "0.210", - "r3.xlarge": "0.420", - "r3.2xlarge": "0.840", - "r3.4xlarge": "1.680", - "r3.8xlarge": "3.360", - "m2.xlarge": "0.296", - "m2.2xlarge": "0.592", - "m2.4xlarge": "1.183", - "i2.xlarge": "1.018", - "i2.2xlarge": "2.035", - "i2.4xlarge": "4.070", - "i2.8xlarge": "8.140", - "hs1.8xlarge": "5.570", - "t1.micro": "0.020" - }, - "cloudsigma_lvs": { - "high-cpu-medium": 0.0, - "standard-large": 0.0, - "micro-high-cpu": 0.0, - "standard-extra-large": 0.0, - "high-memory-double-extra-large": 0.0, - "micro-regular": 0.0, - "standard-small": 0.0, - "high-memory-extra-large": 0.0, - "high-cpu-extra-large": 0.0 - }, - "dreamhost": { - "default": 115, - "high": 150, - "minimum": 15, - "maximum": 200, - "low": 50 - }, - "osc_sas_eu_west_3": { - "t1.micro": "0.040", - "m1.small": "0.090", - "m1.medium": "0.130", - "m1.large": "0.360", - "m1.xlarge": "0.730", - "c1.medium": "0.230", - "c1.xlarge": "0.900", - "m2.xlarge": "0.460", - "m2.2xlarge": "0.920", - "m2.4xlarge": "1.840", - "nv1.small": "5.220", - "nv1.medium": "5.310", - "nv1.large": "5.490", - "nv1.xlarge": "5.860", - "cc1.4xlarge": "1.460", - "cc2.8xlarge": "2.700", - "m3.xlarge": "0.780", - "m3.2xlarge": "1.560", - "cr1.8xlarge": "3.750", - "os1.8xlarge": "6.400", - "os1.8xlarge": "6.400" - }, - "osc_sas_eu_west_1": { - "t1.micro": "0.040", - "m1.small": "0.090", - "m1.medium": "0.130", - "m1.large": "0.360", - "m1.xlarge": "0.730", - "c1.medium": "0.230", - "c1.xlarge": "0.900", - "m2.xlarge": "0.460", - "m2.2xlarge": "0.920", - "m2.4xlarge": "1.840", - "nv1.small": "5.220", - "nv1.medium": "5.310", - "nv1.large": "5.490", - "nv1.xlarge": "5.860", - "cc1.4xlarge": "1.460", - "cc2.8xlarge": "2.700", - "m3.xlarge": "0.780", - "m3.2xlarge": "1.560", - "cr1.8xlarge": "3.750", - "os1.8xlarge": "6.400", - "os1.8xlarge": "6.400" - }, - "osc_sas_us_east_1": { - "t1.micro": "0.020", - "m1.small": "0.070", - "m1.medium": "0.180", - "m1.large": "0.260", - "m1.xlarge": "0.730", - "c1.medium": "0.170", - "c1.xlarge": "0.660", - "m2.xlarge": "0.460", - "m2.2xlarge": "1.020", - "m2.4xlarge": "2.040", - "nv1.small": "5.220", - "nv1.medium": "5.310", - "nv1.large": "5.490", - "nv1.xlarge": "5.860", - "cc1.4xlarge": "1.610", - "cc2.8xlarge": "2.700", - "m3.xlarge": "0.550", - "m3.2xlarge": "1.560", - "cr1.8xlarge": "3.750", - "os1.8xlarge": "6.400", - "os1.8xlarge": "6.400" - }, - "osc_inc_eu_west_1": { - "t1.micro": "0.040", - "m1.small": "0.090", - "m1.medium": "0.120", - "m1.large": "0.360", - "m1.xlarge": "0.730", - "c1.medium": "0.230", - "c1.xlarge": "0.900", - "m2.xlarge": "0.410", - "m2.2xlarge": "0.820", - "m2.4xlarge": "1.640", - "nv1.small": "5.220", - "nv1.medium": "5.250", - "nv1.large": "5.490", - "nv1.xlarge": "5.610", - "cc1.4xlarge": "1.300", - "cc2.8xlarge": "2.400", - "m3.xlarge": "0.780", - "m3.2xlarge": "1.560", - "cr1.8xlarge": "3.500", - "os1.8xlarge": "4.310", - "os1.8xlarge": "4.310" - }, - "osc_inc_eu_west_3": { - "t1.micro": "0.040", - "m1.small": "0.090", - "m1.medium": "0.120", - "m1.large": "0.360", - "m1.xlarge": "0.730", - "c1.medium": "0.230", - "c1.xlarge": "0.900", - "m2.xlarge": "0.410", - "m2.2xlarge": "0.820", - "m2.4xlarge": "1.640", - "nv1.small": "5.220", - "nv1.medium": "5.250", - "nv1.large": "5.490", - "nv1.xlarge": "5.610", - "cc1.4xlarge": "1.300", - "cc2.8xlarge": "2.400", - "m3.xlarge": "0.780", - "m3.2xlarge": "1.560", - "cr1.8xlarge": "3.500", - "os1.8xlarge": "4.310", - "os1.8xlarge": "4.310" - }, - "osc_inc_us_east_1": { - "t1.micro": "0.020", - "m1.small": "0.060", - "m1.medium": "0.180", - "m1.large": "0.240", - "m1.xlarge": "0.730", - "c1.medium": "0.150", - "c1.xlarge": "0.580", - "m2.xlarge": "0.410", - "m2.2xlarge": "1.020", - "m2.4xlarge": "2.040", - "nv1.small": "5.190", - "nv1.medium": "5.250", - "nv1.large": "5.490", - "nv1.xlarge": "5.610", - "cc1.4xlarge": "1.610", - "cc2.8xlarge": "2.400", - "m3.xlarge": "0.500", - "m3.2xlarge": "1.560", - "cr1.8xlarge": "3.500", - "os1.8xlarge": "6.400", - "os1.8xlarge": "6.400" - } - }, - "storage": {}, - "updated": 1397154837 -} diff --git a/awx/lib/site-packages/libcloud/dns/__init__.py b/awx/lib/site-packages/libcloud/dns/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/dns/base.py b/awx/lib/site-packages/libcloud/dns/base.py deleted file mode 100644 index 0e3ac6fe85..0000000000 --- a/awx/lib/site-packages/libcloud/dns/base.py +++ /dev/null @@ -1,486 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import datetime - -from libcloud import __version__ -from libcloud.common.base import ConnectionUserAndKey, BaseDriver -from libcloud.dns.types import RecordType - -__all__ = [ - 'Zone', - 'Record', - 'DNSDriver' -] - - -class Zone(object): - """ - DNS zone. - """ - - def __init__(self, id, domain, type, ttl, driver, extra=None): - """ - :param id: Zone id. - :type id: ``str`` - - :param domain: The name of the domain. - :type domain: ``str`` - - :param type: Zone type (master, slave). - :type type: ``str`` - - :param ttl: Default TTL for records in this zone (in seconds). - :type ttl: ``int`` - - :param driver: DNSDriver instance. - :type driver: :class:`DNSDriver` - - :param extra: (optional) Extra attributes (driver specific). - :type extra: ``dict`` - """ - self.id = str(id) if id else None - self.domain = domain - self.type = type - self.ttl = ttl or None - self.driver = driver - self.extra = extra or {} - - def list_records(self): - return self.driver.list_records(zone=self) - - def create_record(self, name, type, data, extra=None): - return self.driver.create_record(name=name, zone=self, type=type, - data=data, extra=extra) - - def update(self, domain=None, type=None, ttl=None, extra=None): - return self.driver.update_zone(zone=self, domain=domain, type=type, - ttl=ttl, extra=extra) - - def delete(self): - return self.driver.delete_zone(zone=self) - - def export_to_bind_format(self): - return self.driver.export_zone_to_bind_format(zone=self) - - def export_to_bind_zone_file(self, file_path): - self.driver.export_zone_to_bind_zone_file(zone=self, - file_path=file_path) - - def __repr__(self): - return ('<Zone: domain=%s, ttl=%s, provider=%s ...>' % - (self.domain, self.ttl, self.driver.name)) - - -class Record(object): - """ - Zone record / resource. - """ - - def __init__(self, id, name, type, data, zone, driver, extra=None): - """ - :param id: Record id - :type id: ``str`` - - :param name: Hostname or FQDN. - :type name: ``str`` - - :param type: DNS record type (A, AAAA, ...). - :type type: :class:`RecordType` - - :param data: Data for the record (depends on the record type). - :type data: ``str`` - - :param zone: Zone instance. - :type zone: :class:`Zone` - - :param driver: DNSDriver instance. - :type driver: :class:`DNSDriver` - - :param extra: (optional) Extra attributes (driver specific). - :type extra: ``dict`` - """ - self.id = str(id) if id else None - self.name = name - self.type = type - self.data = data - self.zone = zone - self.driver = driver - self.extra = extra or {} - - def update(self, name=None, type=None, data=None, extra=None): - return self.driver.update_record(record=self, name=name, type=type, - data=data, extra=extra) - - def delete(self): - return self.driver.delete_record(record=self) - - def _get_numeric_id(self): - record_id = self.id - - if record_id.isdigit(): - record_id = int(record_id) - - return record_id - - def __repr__(self): - return ('<Record: zone=%s, name=%s, type=%s, data=%s, provider=%s ' - '...>' % - (self.zone.id, self.name, self.type, self.data, - self.driver.name)) - - -class DNSDriver(BaseDriver): - """ - A base DNSDriver class to derive from - - This class is always subclassed by a specific driver. - """ - connectionCls = ConnectionUserAndKey - name = None - website = None - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - **kwargs): - """ - :param key: API key or username to used (required) - :type key: ``str`` - - :param secret: Secret password to be used (required) - :type secret: ``str`` - - :param secure: Weither to use HTTPS or HTTP. Note: Some providers - only support HTTPS, and it is on by default. - :type secure: ``bool`` - - :param host: Override hostname used for connections. - :type host: ``str`` - - :param port: Override port used for connections. - :type port: ``int`` - - :return: ``None`` - """ - super(DNSDriver, self).__init__(key=key, secret=secret, secure=secure, - host=host, port=port, **kwargs) - - def list_record_types(self): - """ - Return a list of RecordType objects supported by the provider. - - :return: ``list`` of :class:`RecordType` - """ - return list(self.RECORD_TYPE_MAP.keys()) - - def iterate_zones(self): - """ - Return a generator to iterate over available zones. - - :rtype: ``generator`` of :class:`Zone` - """ - raise NotImplementedError( - 'iterate_zones not implemented for this driver') - - def list_zones(self): - """ - Return a list of zones. - - :return: ``list`` of :class:`Zone` - """ - return list(self.iterate_zones()) - - def iterate_records(self, zone): - """ - Return a generator to iterate over records for the provided zone. - - :param zone: Zone to list records for. - :type zone: :class:`Zone` - - :rtype: ``generator`` of :class:`Record` - """ - raise NotImplementedError( - 'iterate_records not implemented for this driver') - - def list_records(self, zone): - """ - Return a list of records for the provided zone. - - :param zone: Zone to list records for. - :type zone: :class:`Zone` - - :return: ``list`` of :class:`Record` - """ - return list(self.iterate_records(zone)) - - def get_zone(self, zone_id): - """ - Return a Zone instance. - - :param zone_id: ID of the required zone - :type zone_id: ``str`` - - :rtype: :class:`Zone` - """ - raise NotImplementedError( - 'get_zone not implemented for this driver') - - def get_record(self, zone_id, record_id): - """ - Return a Record instance. - - :param zone_id: ID of the required zone - :type zone_id: ``str`` - - :param record_id: ID of the required record - :type record_id: ``str`` - - :rtype: :class:`Record` - """ - raise NotImplementedError( - 'get_record not implemented for this driver') - - def create_zone(self, domain, type='master', ttl=None, extra=None): - """ - Create a new zone. - - :param domain: Zone domain name (e.g. example.com) - :type domain: ``str`` - - :param type: Zone type (master / slave). - :type type: ``str`` - - :param ttl: TTL for new records. (optional) - :type ttl: ``int`` - - :param extra: Extra attributes (driver specific). (optional) - :type extra: ``dict`` - - :rtype: :class:`Zone` - """ - raise NotImplementedError( - 'create_zone not implemented for this driver') - - def update_zone(self, zone, domain, type='master', ttl=None, extra=None): - """ - Update en existing zone. - - :param zone: Zone to update. - :type zone: :class:`Zone` - - :param domain: Zone domain name (e.g. example.com) - :type domain: ``str`` - - :param type: Zone type (master / slave). - :type type: ``str`` - - :param ttl: TTL for new records. (optional) - :type ttl: ``int`` - - :param extra: Extra attributes (driver specific). (optional) - :type extra: ``dict`` - - :rtype: :class:`Zone` - """ - raise NotImplementedError( - 'update_zone not implemented for this driver') - - def create_record(self, name, zone, type, data, extra=None): - """ - Create a new record. - - :param name: Record name without the domain name (e.g. www). - Note: If you want to create a record for a base domain - name, you should specify empty string ('') for this - argument. - :type name: ``str`` - - :param zone: Zone where the requested record is created. - :type zone: :class:`Zone` - - :param type: DNS record type (A, AAAA, ...). - :type type: :class:`RecordType` - - :param data: Data for the record (depends on the record type). - :type data: ``str`` - - :param extra: Extra attributes (driver specific). (optional) - :type extra: ``dict`` - - :rtype: :class:`Record` - """ - raise NotImplementedError( - 'create_record not implemented for this driver') - - def update_record(self, record, name, type, data, extra): - """ - Update an existing record. - - :param record: Record to update. - :type record: :class:`Record` - - :param name: Record name without the domain name (e.g. www). - Note: If you want to create a record for a base domain - name, you should specify empty string ('') for this - argument. - :type name: ``str`` - - :param type: DNS record type (A, AAAA, ...). - :type type: :class:`RecordType` - - :param data: Data for the record (depends on the record type). - :type data: ``str`` - - :param extra: (optional) Extra attributes (driver specific). - :type extra: ``dict`` - - :rtype: :class:`Record` - """ - raise NotImplementedError( - 'update_record not implemented for this driver') - - def delete_zone(self, zone): - """ - Delete a zone. - - Note: This will delete all the records belonging to this zone. - - :param zone: Zone to delete. - :type zone: :class:`Zone` - - :rtype: ``bool`` - """ - raise NotImplementedError( - 'delete_zone not implemented for this driver') - - def delete_record(self, record): - """ - Delete a record. - - :param record: Record to delete. - :type record: :class:`Record` - - :rtype: ``bool`` - """ - raise NotImplementedError( - 'delete_record not implemented for this driver') - - def export_zone_to_bind_format(self, zone): - """ - Export Zone object to the BIND compatible format. - - :param zone: Zone to export. - :type zone: :class:`Zone` - - :return: Zone data in BIND compatible format. - :rtype: ``str`` - """ - if zone.type != 'master': - raise ValueError('You can only generate BIND out for master zones') - - lines = [] - - # For consistent output, records are sorted based on the id - records = zone.list_records() - records = sorted(records, key=Record._get_numeric_id) - - date = datetime.datetime.now().strftime('%Y-%m-%d %H:%m:%S') - values = {'version': __version__, 'date': date} - - lines.append('; Generated by Libcloud v%(version)s on %(date)s' % - values) - lines.append('$ORIGIN %(domain)s.' % {'domain': zone.domain}) - lines.append('$TTL %(domain_ttl)s\n' % {'domain_ttl': zone.ttl}) - - for record in records: - line = self._get_bind_record_line(record=record) - lines.append(line) - - output = '\n'.join(lines) - return output - - def export_zone_to_bind_zone_file(self, zone, file_path): - """ - Export Zone object to the BIND compatible format and write result to a - file. - - :param zone: Zone to export. - :type zone: :class:`Zone` - - :param file_path: File path where the output will be saved. - :type file_path: ``str`` - """ - result = self.export_zone_to_bind_format(zone=zone) - - with open(file_path, 'w') as fp: - fp.write(result) - - def _get_bind_record_line(self, record): - """ - Generate BIND record line for the provided record. - - :param record: Record to generate the line for. - :type record: :class:`Record` - - :return: Bind compatible record line. - :rtype: ``str`` - """ - parts = [] - - if record.name: - name = '%(name)s.%(domain)s' % {'name': record.name, - 'domain': record.zone.domain} - else: - name = record.zone.domain - - name += '.' - - ttl = record.extra['ttl'] if 'ttl' in record.extra else record.zone.ttl - ttl = str(ttl) - data = record.data - - if record.type in [RecordType.CNAME, RecordType.DNAME, RecordType.MX, - RecordType.PTR, RecordType.SRV]: - # Make sure trailing dot is present - if data[len(data) - 1] != '.': - data += '.' - - if record.type in [RecordType.TXT, RecordType.SPF] and ' ' in data: - # Escape the quotes - data = data.replace('"', '\\"') - - # Quote the string - data = '"%s"' % (data) - - if record.type in [RecordType.MX, RecordType.SRV]: - priority = str(record.extra['priority']) - parts = [name, ttl, 'IN', record.type, priority, data] - else: - parts = [name, ttl, 'IN', record.type, data] - - line = '\t'.join(parts) - return line - - def _string_to_record_type(self, string): - """ - Return a string representation of a DNS record type to a - libcloud RecordType ENUM. - - :rtype: ``str`` - """ - string = string.upper() - record_type = getattr(RecordType, string) - return record_type diff --git a/awx/lib/site-packages/libcloud/dns/drivers/__init__.py b/awx/lib/site-packages/libcloud/dns/drivers/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/dns/drivers/dummy.py b/awx/lib/site-packages/libcloud/dns/drivers/dummy.py deleted file mode 100644 index 04da354a61..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/dummy.py +++ /dev/null @@ -1,218 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.dns.base import DNSDriver, Zone, Record -from libcloud.dns.types import RecordType -from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.types import RecordAlreadyExistsError - - -class DummyDNSDriver(DNSDriver): - """ - Dummy DNS driver. - - >>> from libcloud.dns.drivers.dummy import DummyDNSDriver - >>> driver = DummyDNSDriver('key', 'secret') - >>> driver.name - 'Dummy DNS Provider' - """ - - name = 'Dummy DNS Provider' - website = 'http://example.com' - - def __init__(self, api_key, api_secret): - """ - :param api_key: API key or username to used (required) - :type api_key: ``str`` - - :param api_secret: Secret password to be used (required) - :type api_secret: ``str`` - - :rtype: ``None`` - """ - self._zones = {} - - def list_record_types(self): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> driver.list_record_types() - ['A'] - - @inherits: :class:`DNSDriver.list_record_types` - """ - return [RecordType.A] - - def list_zones(self): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> driver.list_zones() - [] - - @inherits: :class:`DNSDriver.list_zones` - """ - - return [zone['zone'] for zone in list(self._zones.values())] - - def list_records(self, zone): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> zone = driver.create_zone(domain='apache.org', type='master', - ... ttl=100) - >>> list(zone.list_records()) - [] - >>> record = driver.create_record(name='libcloud', zone=zone, - ... type=RecordType.A, data='127.0.0.1') - >>> list(zone.list_records()) #doctest: +ELLIPSIS - [<Record: zone=id-apache.org, name=libcloud, type=A...>] - """ - return self._zones[zone.id]['records'].values() - - def get_zone(self, zone_id): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> driver.get_zone(zone_id='foobar') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ZoneDoesNotExistError: - - @inherits: :class:`DNSDriver.get_zone` - """ - - if zone_id not in self._zones: - raise ZoneDoesNotExistError(driver=self, value=None, - zone_id=zone_id) - - return self._zones[zone_id]['zone'] - - def get_record(self, zone_id, record_id): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> driver.get_record(zone_id='doesnotexist', record_id='exists') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ZoneDoesNotExistError: - - @inherits: :class:`DNSDriver.get_record` - """ - - self.get_zone(zone_id=zone_id) - zone_records = self._zones[zone_id]['records'] - - if record_id not in zone_records: - raise RecordDoesNotExistError(record_id=record_id, value=None, - driver=self) - - return zone_records[record_id] - - def create_zone(self, domain, type='master', ttl=None, extra=None): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> zone = driver.create_zone(domain='apache.org', type='master', - ... ttl=100) - >>> zone - <Zone: domain=apache.org, ttl=100, provider=Dummy DNS Provider ...> - >>> zone = driver.create_zone(domain='apache.org', type='master', - ... ttl=100) - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ZoneAlreadyExistsError: - - @inherits: :class:`DNSDriver.create_zone` - """ - - id = 'id-%s' % (domain) - - if id in self._zones: - raise ZoneAlreadyExistsError(zone_id=id, value=None, driver=self) - - zone = Zone(id=id, domain=domain, type=type, ttl=ttl, extra={}, - driver=self) - self._zones[id] = {'zone': zone, - 'records': {}} - return zone - - def create_record(self, name, zone, type, data, extra=None): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> zone = driver.create_zone(domain='apache.org', type='master', - ... ttl=100) - >>> record = driver.create_record(name='libcloud', zone=zone, - ... type=RecordType.A, data='127.0.0.1') - >>> record #doctest: +ELLIPSIS - <Record: zone=id-apache.org, name=libcloud, type=A, data=127.0.0.1...> - >>> record = driver.create_record(name='libcloud', zone=zone, - ... type=RecordType.A, data='127.0.0.1') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - RecordAlreadyExistsError: - - @inherits: :class:`DNSDriver.create_record` - """ - id = 'id-%s' % (name) - - zone = self.get_zone(zone_id=zone.id) - - if id in self._zones[zone.id]['records']: - raise RecordAlreadyExistsError(record_id=id, value=None, - driver=self) - - record = Record(id=id, name=name, type=type, data=data, extra=extra, - zone=zone, driver=self) - self._zones[zone.id]['records'][id] = record - return record - - def delete_zone(self, zone): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> zone = driver.create_zone(domain='apache.org', type='master', - ... ttl=100) - >>> driver.delete_zone(zone) - True - >>> driver.delete_zone(zone) #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ZoneDoesNotExistError: - - @inherits: :class:`DNSDriver.delete_zone` - """ - self.get_zone(zone_id=zone.id) - - del self._zones[zone.id] - return True - - def delete_record(self, record): - """ - >>> driver = DummyDNSDriver('key', 'secret') - >>> zone = driver.create_zone(domain='apache.org', type='master', - ... ttl=100) - >>> record = driver.create_record(name='libcloud', zone=zone, - ... type=RecordType.A, data='127.0.0.1') - >>> driver.delete_record(record) - True - >>> driver.delete_record(record) #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - RecordDoesNotExistError: - - @inherits: :class:`DNSDriver.delete_record` - """ - self.get_record(zone_id=record.zone.id, record_id=record.id) - - del self._zones[record.zone.id]['records'][record.id] - return True - - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/awx/lib/site-packages/libcloud/dns/drivers/gandi.py b/awx/lib/site-packages/libcloud/dns/drivers/gandi.py deleted file mode 100644 index 48a6ed5d9e..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/gandi.py +++ /dev/null @@ -1,270 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -__all__ = [ - 'GandiDNSDriver' -] - -from libcloud.common.gandi import BaseGandiDriver, GandiConnection -from libcloud.common.gandi import GandiResponse -from libcloud.dns.types import Provider, RecordType -from libcloud.dns.types import RecordError -from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError -from libcloud.dns.base import DNSDriver, Zone, Record - - -TTL_MIN = 30 -TTL_MAX = 2592000 # 30 days - - -class NewZoneVersion(object): - """ - Changes to a zone in the Gandi DNS service need to be wrapped in a new - version object. The changes are made to the new version, then that - version is made active. - - In effect, this is a transaction. - - Any calls made inside this context manager will be applied to a new version - id. If your changes are succesful (and only if they are successful) they - are activated. - """ - - def __init__(self, driver, zone): - self.driver = driver - self.connection = driver.connection - self.zone = zone - - def __enter__(self): - zid = int(self.zone.id) - self.connection.set_context({'zone_id': self.zone.id}) - vid = self.connection.request('domain.zone.version.new', zid).object - self.vid = vid - return vid - - def __exit__(self, type, value, traceback): - if not traceback: - zid = int(self.zone.id) - con = self.connection - con.set_context({'zone_id': self.zone.id}) - con.request('domain.zone.version.set', zid, self.vid).object - - -class GandiDNSResponse(GandiResponse): - exceptions = { - 581042: ZoneDoesNotExistError, - } - - -class GandiDNSConnection(GandiConnection): - responseCls = GandiDNSResponse - - -class GandiDNSDriver(BaseGandiDriver, DNSDriver): - """ - API reference can be found at: - - http://doc.rpc.gandi.net/domain/reference.html - """ - - type = Provider.GANDI - name = 'Gandi DNS' - website = 'http://www.gandi.net/domain' - - connectionCls = GandiDNSConnection - - RECORD_TYPE_MAP = { - RecordType.A: 'A', - RecordType.AAAA: 'AAAA', - RecordType.CNAME: 'CNAME', - RecordType.LOC: 'LOC', - RecordType.MX: 'MX', - RecordType.NS: 'NS', - RecordType.SPF: 'SPF', - RecordType.SRV: 'SRV', - RecordType.TXT: 'TXT', - RecordType.WKS: 'WKS', - } - - def _to_zone(self, zone): - return Zone( - id=str(zone['id']), - domain=zone['name'], - type='master', - ttl=0, - driver=self, - extra={} - ) - - def _to_zones(self, zones): - ret = [] - for z in zones: - ret.append(self._to_zone(z)) - return ret - - def list_zones(self): - zones = self.connection.request('domain.zone.list') - return self._to_zones(zones.object) - - def get_zone(self, zone_id): - zid = int(zone_id) - self.connection.set_context({'zone_id': zone_id}) - zone = self.connection.request('domain.zone.info', zid) - return self._to_zone(zone.object) - - def create_zone(self, domain, type='master', ttl=None, extra=None): - params = { - 'name': domain, - } - info = self.connection.request('domain.zone.create', params) - return self._to_zone(info.object) - - def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): - zid = int(zone.id) - params = {'name': domain} - self.connection.set_context({'zone_id': zone.id}) - zone = self.connection.request('domain.zone.update', zid, params) - return self._to_zone(zone.object) - - def delete_zone(self, zone): - zid = int(zone.id) - self.connection.set_context({'zone_id': zone.id}) - res = self.connection.request('domain.zone.delete', zid) - return res.object - - def _to_record(self, record, zone): - return Record( - id='%s:%s' % (record['type'], record['name']), - name=record['name'], - type=self._string_to_record_type(record['type']), - data=record['value'], - zone=zone, - driver=self, - extra={'ttl': record['ttl']} - ) - - def _to_records(self, records, zone): - retval = [] - for r in records: - retval.append(self._to_record(r, zone)) - return retval - - def list_records(self, zone): - zid = int(zone.id) - self.connection.set_context({'zone_id': zone.id}) - records = self.connection.request('domain.zone.record.list', zid, 0) - return self._to_records(records.object, zone) - - def get_record(self, zone_id, record_id): - zid = int(zone_id) - record_type, name = record_id.split(':', 1) - filter_opts = { - 'name': name, - 'type': record_type - } - self.connection.set_context({'zone_id': zone_id}) - records = self.connection.request('domain.zone.record.list', - zid, 0, filter_opts).object - - if len(records) == 0: - raise RecordDoesNotExistError(value='', driver=self, - record_id=record_id) - - return self._to_record(records[0], self.get_zone(zone_id)) - - def _validate_record(self, record_id, name, record_type, data, extra): - if len(data) > 1024: - raise RecordError('Record data must be <= 1024 characters', - driver=self, record_id=record_id) - if extra and 'ttl' in extra: - if extra['ttl'] < TTL_MIN: - raise RecordError('TTL must be at least 30 seconds', - driver=self, record_id=record_id) - if extra['ttl'] > TTL_MAX: - raise RecordError('TTL must not excdeed 30 days', - driver=self, record_id=record_id) - - def create_record(self, name, zone, type, data, extra=None): - self._validate_record(None, name, type, data, extra) - - zid = int(zone.id) - - create = { - 'name': name, - 'type': self.RECORD_TYPE_MAP[type], - 'value': data - } - - if 'ttl' in extra: - create['ttl'] = extra['ttl'] - - with NewZoneVersion(self, zone) as vid: - con = self.connection - con.set_context({'zone_id': zone.id}) - rec = con.request('domain.zone.record.add', - zid, vid, create).object - - return self._to_record(rec, zone) - - def update_record(self, record, name, type, data, extra): - self._validate_record(record.id, name, type, data, extra) - - filter_opts = { - 'name': record.name, - 'type': self.RECORD_TYPE_MAP[record.type] - } - - update = { - 'name': name, - 'type': self.RECORD_TYPE_MAP[type], - 'value': data - } - - if 'ttl' in extra: - update['ttl'] = extra['ttl'] - - zid = int(record.zone.id) - - with NewZoneVersion(self, record.zone) as vid: - con = self.connection - con.set_context({'zone_id': record.zone.id}) - con.request('domain.zone.record.delete', - zid, vid, filter_opts) - res = con.request('domain.zone.record.add', - zid, vid, update).object - - return self._to_record(res, record.zone) - - def delete_record(self, record): - zid = int(record.zone.id) - - filter_opts = { - 'name': record.name, - 'type': self.RECORD_TYPE_MAP[record.type] - } - - with NewZoneVersion(self, record.zone) as vid: - con = self.connection - con.set_context({'zone_id': record.zone.id}) - count = con.request('domain.zone.record.delete', - zid, vid, filter_opts).object - - if count == 1: - return True - - raise RecordDoesNotExistError(value='No such record', driver=self, - record_id=record.id) diff --git a/awx/lib/site-packages/libcloud/dns/drivers/google.py b/awx/lib/site-packages/libcloud/dns/drivers/google.py deleted file mode 100644 index ca3e5f06da..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/google.py +++ /dev/null @@ -1,345 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'GoogleDNSDriver' -] - -API_VERSION = 'v1beta1' - -import re -from libcloud.common.google import GoogleResponse, GoogleBaseConnection -from libcloud.common.google import ResourceNotFoundError -from libcloud.dns.types import Provider, RecordType -from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError -from libcloud.dns.base import DNSDriver, Zone, Record - - -class GoogleDNSResponse(GoogleResponse): - pass - - -class GoogleDNSConnection(GoogleBaseConnection): - host = "www.googleapis.com" - responseCls = GoogleDNSResponse - - def __init__(self, user_id, key, secure, auth_type=None, - credential_file=None, project=None, **kwargs): - super(GoogleDNSConnection, self).\ - __init__(user_id, key, secure=secure, auth_type=auth_type, - credential_file=credential_file, **kwargs) - self.request_path = '/dns/%s/projects/%s' % (API_VERSION, project) - - -class GoogleDNSDriver(DNSDriver): - type = Provider.GOOGLE - name = 'Google DNS' - connectionCls = GoogleDNSConnection - website = 'https://cloud.google.com/' - - RECORD_TYPE_MAP = { - RecordType.A: 'A', - RecordType.AAAA: 'AAAA', - RecordType.CNAME: 'CNAME', - RecordType.MX: 'MX', - RecordType.NS: 'NS', - RecordType.PTR: 'PTR', - RecordType.SOA: 'SOA', - RecordType.SPF: 'SPF', - RecordType.SRV: 'SRV', - RecordType.TXT: 'TXT', - } - - def __init__(self, user_id, key, project=None, auth_type=None, scopes=None, - **kwargs): - self.auth_type = auth_type - self.project = project - self.scopes = scopes - if not self.project: - raise ValueError('Project name must be specified using ' - '"project" keyword.') - super(GoogleDNSDriver, self).__init__(user_id, key, scopes, **kwargs) - - def iterate_zones(self): - """ - Return a generator to iterate over available zones. - - :rtype: ``generator`` of :class:`Zone` - """ - return self._get_more('zones') - - def iterate_records(self, zone): - """ - Return a generator to iterate over records for the provided zone. - - :param zone: Zone to list records for. - :type zone: :class:`Zone` - - :rtype: ``generator`` of :class:`Record` - """ - return self._get_more('records', zone=zone) - - def get_zone(self, zone_id): - """ - Return a Zone instance. - - :param zone_id: ID of the required zone - :type zone_id: ``str`` - - :rtype: :class:`Zone` - """ - request = '/managedZones/%s' % (zone_id) - - try: - response = self.connection.request(request, method='GET').object - except ResourceNotFoundError: - raise ZoneDoesNotExistError(value='', - driver=self.connection.driver, - zone_id=zone_id) - - return self._to_zone(response) - - def get_record(self, zone_id, record_id): - """ - Return a Record instance. - - :param zone_id: ID of the required zone - :type zone_id: ``str`` - - :param record_id: ID of the required record - :type record_id: ``str`` - - :rtype: :class:`Record` - """ - (record_type, record_name) = record_id.split(':', 1) - - params = { - 'name': record_name, - 'type': record_type, - } - - request = '/managedZones/%s/rrsets' % (zone_id) - - try: - response = self.connection.request(request, method='GET', - params=params).object - except ResourceNotFoundError: - raise ZoneDoesNotExistError(value='', - driver=self.connection.driver, - zone_id=zone_id) - - if len(response['rrsets']) > 0: - zone = self.get_zone(zone_id) - return self._to_record(response['rrsets'][0], zone) - - raise RecordDoesNotExistError(value='', driver=self.connection.driver, - record_id=record_id) - - def create_zone(self, domain, type='master', ttl=None, extra=None): - """ - Create a new zone. - - :param domain: Zone domain name (e.g. example.com.) with a \'.\' - at the end. - :type domain: ``str`` - - :param type: Zone type (master is the only one supported). - :type type: ``str`` - - :param ttl: TTL for new records. (unused) - :type ttl: ``int`` - - :param extra: Extra attributes (driver specific). (optional) - :type extra: ``dict`` - - :rtype: :class:`Zone` - """ - name = None - description = '' - - if extra: - description = extra.get('description') - name = extra.get('name') - - if name is None: - name = self._cleanup_domain(domain) - - data = { - 'dnsName': domain, - 'name': name, - 'description': description, - } - - request = '/managedZones' - response = self.connection.request(request, method='POST', - data=data).object - return self._to_zone(response) - - def create_record(self, name, zone, type, data, extra=None): - """ - Create a new record. - - :param name: Record name fully qualified, with a \'.\' at the end. - :type name: ``str`` - - :param zone: Zone where the requested record is created. - :type zone: :class:`Zone` - - :param type: DNS record type (A, AAAA, ...). - :type type: :class:`RecordType` - - :param data: Data for the record (depends on the record type). - :type data: ``str`` - - :param extra: Extra attributes. (optional) - :type extra: ``dict`` - - :rtype: :class:`Record` - """ - ttl = data.get('ttl', None) - rrdatas = data.get('rrdatas', []) - - data = { - 'additions': [ - { - 'name': name, - 'type': type, - 'ttl': int(ttl), - 'rrdatas': rrdatas, - } - ] - } - request = '/managedZones/%s/changes' % (zone.id) - response = self.connection.request(request, method='POST', - data=data).object - return self._to_record(response['additions'][0], zone) - - def delete_zone(self, zone): - """ - Delete a zone. - - Note: This will delete all the records belonging to this zone. - - :param zone: Zone to delete. - :type zone: :class:`Zone` - - :rtype: ``bool`` - """ - request = '/managedZones/%s' % (zone.id) - response = self.connection.request(request, method='DELETE') - return response.success() - - def delete_record(self, record): - """ - Delete a record. - - :param record: Record to delete. - :type record: :class:`Record` - - :rtype: ``bool`` - """ - data = { - 'deletions': [ - { - 'name': record.name, - 'type': record.type, - 'rrdatas': record.data['rrdatas'], - 'ttl': record.data['ttl'] - } - ] - } - request = '/managedZones/%s/changes' % (record.zone.id) - response = self.connection.request(request, method='POST', - data=data) - return response.success() - - def _get_more(self, rtype, **kwargs): - last_key = None - exhausted = False - while not exhausted: - items, last_key, exhausted = self._get_data(rtype, last_key, - **kwargs) - for item in items: - yield item - - def _get_data(self, rtype, last_key, **kwargs): - params = {} - - if last_key: - params['pageToken'] = last_key - - if rtype == 'zones': - request = '/managedZones' - transform_func = self._to_zones - r_key = 'managedZones' - elif rtype == 'records': - zone = kwargs['zone'] - request = '/managedZones/%s/rrsets' % (zone.id) - transform_func = self._to_records - r_key = 'rrsets' - - response = self.connection.request(request, method='GET', - params=params,) - - if response.success(): - nextpage = response.object.get('nextPageToken', None) - items = transform_func(response.object.get(r_key), **kwargs) - exhausted = False if nextpage is not None else True - return items, nextpage, exhausted - else: - return [], None, True - - def _ex_connection_class_kwargs(self): - return {'auth_type': self.auth_type, - 'project': self.project, - 'scopes': self.scopes} - - def _to_zones(self, response): - zones = [] - for r in response: - zones.append(self._to_zone(r)) - return zones - - def _to_zone(self, r): - extra = {} - - if 'description' in r: - extra['description'] = r.get('description') - - extra['creationTime'] = r.get('creationTime') - extra['nameServers'] = r.get('nameServers') - extra['id'] = r.get('id') - - return Zone(id=r['name'], domain=r['dnsName'], - type='master', ttl=0, driver=self, extra=extra) - - def _to_records(self, response, zone): - records = [] - for r in response: - records.append(self._to_record(r, zone)) - return records - - def _to_record(self, r, zone): - record_id = '%s:%s' % (r['type'], r['name']) - return Record(id=record_id, name=r['name'], - type=r['type'], data=r, zone=zone, - driver=self, extra={}) - - def _cleanup_domain(self, domain): - # name can only contain lower case alphanumeric characters and hyphens - domain = re.sub(r'[^a-zA-Z0-9-]', '-', domain) - if domain[-1] == '-': - domain = domain[:-1] - return domain diff --git a/awx/lib/site-packages/libcloud/dns/drivers/hostvirtual.py b/awx/lib/site-packages/libcloud/dns/drivers/hostvirtual.py deleted file mode 100644 index 1d9eec2ce6..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/hostvirtual.py +++ /dev/null @@ -1,243 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License.You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'HostVirtualDNSDriver' -] - -from libcloud.utils.py3 import httplib -from libcloud.utils.misc import merge_valid_keys, get_new_obj -from libcloud.common.hostvirtual import HostVirtualResponse -from libcloud.common.hostvirtual import HostVirtualConnection -from libcloud.compute.drivers.hostvirtual import API_ROOT -from libcloud.dns.types import Provider, RecordType -from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError -from libcloud.dns.base import DNSDriver, Zone, Record - -try: - import simplejson as json -except: - import json - -VALID_RECORD_EXTRA_PARAMS = ['prio', 'ttl'] - - -class HostVirtualDNSResponse(HostVirtualResponse): - def parse_error(self): - context = self.connection.context - status = int(self.status) - - if status == httplib.NOT_FOUND: - if context['resource'] == 'zone': - raise ZoneDoesNotExistError(value='', driver=self, - zone_id=context['id']) - elif context['resource'] == 'record': - raise RecordDoesNotExistError(value='', driver=self, - record_id=context['id']) - - super(HostVirtualDNSResponse, self).parse_error() - return self.body - - -class HostVirtualDNSConnection(HostVirtualConnection): - responseCls = HostVirtualDNSResponse - - -class HostVirtualDNSDriver(DNSDriver): - type = Provider.HOSTVIRTUAL - name = 'Host Virtual DNS' - website = 'http://www.vr.org/' - connectionCls = HostVirtualDNSConnection - - RECORD_TYPE_MAP = { - RecordType.A: 'A', - RecordType.AAAA: 'AAAA', - RecordType.CNAME: 'CNAME', - RecordType.MX: 'MX', - RecordType.NS: 'SPF', - RecordType.SRV: 'SRV', - RecordType.TXT: 'TXT', - } - - def __init__(self, key, secure=True, host=None, port=None): - super(HostVirtualDNSDriver, self).__init__(key=key, secure=secure, - host=host, port=port) - - def _to_zones(self, items): - zones = [] - for item in items: - zones.append(self._to_zone(item)) - return zones - - def _to_zone(self, item): - extra = {} - if 'records' in item: - extra['records'] = item['records'] - if item['type'] == 'NATIVE': - item['type'] = 'master' - zone = Zone(id=item['id'], domain=item['name'], - type=item['type'], ttl=item['ttl'], - driver=self, extra=extra) - return zone - - def _to_records(self, items, zone=None): - records = [] - - for item in items: - records.append(self._to_record(item=item, zone=zone)) - return records - - def _to_record(self, item, zone=None): - extra = {'ttl': item['ttl']} - type = self._string_to_record_type(item['type']) - record = Record(id=item['id'], name=item['name'], - type=type, data=item['content'], - zone=zone, driver=self, extra=extra) - return record - - def list_zones(self): - result = self.connection.request( - API_ROOT + '/dns/zones/').object - zones = self._to_zones(result) - return zones - - def list_records(self, zone): - params = {'id': zone.id} - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - result = self.connection.request( - API_ROOT + '/dns/records/', params=params).object - records = self._to_records(items=result, zone=zone) - return records - - def get_zone(self, zone_id): - params = {'id': zone_id} - self.connection.set_context({'resource': 'zone', 'id': zone_id}) - result = self.connection.request( - API_ROOT + '/dns/zone/', params=params).object - if 'id' not in result: - raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone_id) - zone = self._to_zone(result) - return zone - - def get_record(self, zone_id, record_id): - zone = self.get_zone(zone_id=zone_id) - params = {'id': record_id} - self.connection.set_context({'resource': 'record', 'id': record_id}) - result = self.connection.request( - API_ROOT + '/dns/record/', params=params).object - if 'id' not in result: - raise RecordDoesNotExistError(value='', - driver=self, record_id=record_id) - record = self._to_record(item=result, zone=zone) - return record - - def delete_zone(self, zone): - params = {'zone_id': zone.id} - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - result = self.connection.request( - API_ROOT + '/dns/zone/', params=params, method='DELETE').object - return bool(result) - - def delete_record(self, record): - params = {'id': record.id} - self.connection.set_context({'resource': 'record', 'id': record.id}) - result = self.connection.request( - API_ROOT + '/dns/record/', params=params, method='DELETE').object - - return bool(result) - - def create_zone(self, domain, type='NATIVE', ttl=None, extra=None): - if type == 'master': - type = 'NATIVE' - elif type == 'slave': - type = 'SLAVE' - params = {'name': domain, 'type': type, 'ttl': ttl} - result = self.connection.request( - API_ROOT + '/dns/zone/', - data=json.dumps(params), method='POST').object - extra = { - 'soa': result['soa'], - 'ns': result['ns'] - } - zone = Zone(id=result['id'], domain=domain, - type=type, ttl=ttl, extra=extra, driver=self) - return zone - - def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): - params = {'id': zone.id} - if domain: - params['name'] = domain - if type: - params['type'] = type - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - self.connection.request(API_ROOT + '/dns/zone/', - data=json.dumps(params), method='PUT').object - updated_zone = get_new_obj( - obj=zone, klass=Zone, - attributes={ - 'domain': domain, - 'type': type, - 'ttl': ttl, - 'extra': extra - }) - return updated_zone - - def create_record(self, name, zone, type, data, extra=None): - params = { - 'name': name, - 'type': self.RECORD_TYPE_MAP[type], - 'domain_id': zone.id, - 'content': data - } - merged = merge_valid_keys( - params=params, - valid_keys=VALID_RECORD_EXTRA_PARAMS, - extra=extra - ) - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - result = self.connection.request( - API_ROOT + '/dns/record/', - data=json.dumps(params), method='POST').object - record = Record(id=result['id'], name=name, - type=type, data=data, - extra=merged, zone=zone, driver=self) - return record - - def update_record(self, record, name=None, type=None, - data=None, extra=None): - params = { - 'domain_id': record.zone.id, - 'record_id': record.id - } - if name: - params['name'] = name - if data: - params['content'] = data - if type is not None: - params['type'] = self.RECORD_TYPE_MAP[type] - merged = merge_valid_keys( - params=params, - valid_keys=VALID_RECORD_EXTRA_PARAMS, - extra=extra - ) - self.connection.set_context({'resource': 'record', 'id': record.id}) - self.connection.request(API_ROOT + '/dns/record/', - data=json.dumps(params), method='PUT').object - updated_record = get_new_obj( - obj=record, klass=Record, attributes={ - 'name': name, 'data': data, - 'type': type, - 'extra': merged - }) - return updated_record diff --git a/awx/lib/site-packages/libcloud/dns/drivers/linode.py b/awx/lib/site-packages/libcloud/dns/drivers/linode.py deleted file mode 100644 index f0fdbdc756..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/linode.py +++ /dev/null @@ -1,272 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'LinodeDNSDriver' -] - -from libcloud.utils.misc import merge_valid_keys, get_new_obj -from libcloud.common.linode import (API_ROOT, LinodeException, - LinodeConnection, LinodeResponse) -from libcloud.dns.types import Provider, RecordType -from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError -from libcloud.dns.base import DNSDriver, Zone, Record - - -VALID_ZONE_EXTRA_PARAMS = ['SOA_Email', 'Refresh_sec', 'Retry_sec', - 'Expire_sec', 'status', 'master_ips'] - -VALID_RECORD_EXTRA_PARAMS = ['Priority', 'Weight', 'Port', 'Protocol', - 'TTL_sec'] - - -class LinodeDNSResponse(LinodeResponse): - def _make_excp(self, error): - result = super(LinodeDNSResponse, self)._make_excp(error) - if isinstance(result, LinodeException) and result.code == 5: - context = self.connection.context - - if context['resource'] == 'zone': - result = ZoneDoesNotExistError(value='', - driver=self.connection.driver, - zone_id=context['id']) - - elif context['resource'] == 'record': - result = RecordDoesNotExistError(value='', - driver=self.connection.driver, - record_id=context['id']) - return result - - -class LinodeDNSConnection(LinodeConnection): - responseCls = LinodeDNSResponse - - -class LinodeDNSDriver(DNSDriver): - type = Provider.LINODE - name = 'Linode DNS' - website = 'http://www.linode.com/' - connectionCls = LinodeDNSConnection - - RECORD_TYPE_MAP = { - RecordType.NS: 'NS', - RecordType.MX: 'MX', - RecordType.A: 'A', - RecordType.AAAA: 'AAAA', - RecordType.CNAME: 'CNAME', - RecordType.TXT: 'TXT', - RecordType.SRV: 'SRV', - } - - def list_zones(self): - params = {'api_action': 'domain.list'} - data = self.connection.request(API_ROOT, params=params).objects[0] - zones = self._to_zones(data) - return zones - - def list_records(self, zone): - params = {'api_action': 'domain.resource.list', 'DOMAINID': zone.id} - - self.connection.set_context(context={'resource': 'zone', - 'id': zone.id}) - data = self.connection.request(API_ROOT, params=params).objects[0] - records = self._to_records(items=data, zone=zone) - return records - - def get_zone(self, zone_id): - params = {'api_action': 'domain.list', 'DomainID': zone_id} - self.connection.set_context(context={'resource': 'zone', - 'id': zone_id}) - data = self.connection.request(API_ROOT, params=params).objects[0] - zones = self._to_zones(data) - - if len(zones) != 1: - raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone_id) - - return zones[0] - - def get_record(self, zone_id, record_id): - zone = self.get_zone(zone_id=zone_id) - params = {'api_action': 'domain.resource.list', 'DomainID': zone_id, - 'ResourceID': record_id} - self.connection.set_context(context={'resource': 'record', - 'id': record_id}) - data = self.connection.request(API_ROOT, params=params).objects[0] - records = self._to_records(items=data, zone=zone) - - if len(records) != 1: - raise RecordDoesNotExistError(value='', driver=self, - record_id=record_id) - - return records[0] - - def create_zone(self, domain, type='master', ttl=None, extra=None): - """ - Create a new zone. - - API docs: http://www.linode.com/api/dns/domain.create - """ - params = {'api_action': 'domain.create', 'Type': type, - 'Domain': domain} - - if ttl: - params['TTL_sec'] = ttl - - merged = merge_valid_keys(params=params, - valid_keys=VALID_ZONE_EXTRA_PARAMS, - extra=extra) - data = self.connection.request(API_ROOT, params=params).objects[0] - zone = Zone(id=data['DomainID'], domain=domain, type=type, ttl=ttl, - extra=merged, driver=self) - return zone - - def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): - """ - Update an existing zone. - - API docs: http://www.linode.com/api/dns/domain.update - """ - params = {'api_action': 'domain.update', 'DomainID': zone.id} - - if type: - params['Type'] = type - - if domain: - params['Domain'] = domain - - if ttl: - params['TTL_sec'] = ttl - - merged = merge_valid_keys(params=params, - valid_keys=VALID_ZONE_EXTRA_PARAMS, - extra=extra) - self.connection.request(API_ROOT, params=params).objects[0] - updated_zone = get_new_obj(obj=zone, klass=Zone, - attributes={'domain': domain, - 'type': type, 'ttl': ttl, - 'extra': merged}) - return updated_zone - - def create_record(self, name, zone, type, data, extra=None): - """ - Create a new record. - - API docs: http://www.linode.com/api/dns/domain.resource.create - """ - params = {'api_action': 'domain.resource.create', 'DomainID': zone.id, - 'Name': name, 'Target': data, - 'Type': self.RECORD_TYPE_MAP[type]} - merged = merge_valid_keys(params=params, - valid_keys=VALID_RECORD_EXTRA_PARAMS, - extra=extra) - - result = self.connection.request(API_ROOT, params=params).objects[0] - record = Record(id=result['ResourceID'], name=name, type=type, - data=data, extra=merged, zone=zone, driver=self) - return record - - def update_record(self, record, name=None, type=None, data=None, - extra=None): - """ - Update an existing record. - - API docs: http://www.linode.com/api/dns/domain.resource.update - """ - params = {'api_action': 'domain.resource.update', - 'ResourceID': record.id, 'DomainID': record.zone.id} - - if name: - params['Name'] = name - - if data: - params['Target'] = data - - if type is not None: - params['Type'] = self.RECORD_TYPE_MAP[type] - - merged = merge_valid_keys(params=params, - valid_keys=VALID_RECORD_EXTRA_PARAMS, - extra=extra) - - self.connection.request(API_ROOT, params=params).objects[0] - updated_record = get_new_obj(obj=record, klass=Record, - attributes={'name': name, 'data': data, - 'type': type, - 'extra': merged}) - return updated_record - - def delete_zone(self, zone): - params = {'api_action': 'domain.delete', 'DomainID': zone.id} - - self.connection.set_context(context={'resource': 'zone', - 'id': zone.id}) - data = self.connection.request(API_ROOT, params=params).objects[0] - - return 'DomainID' in data - - def delete_record(self, record): - params = {'api_action': 'domain.resource.delete', - 'DomainID': record.zone.id, 'ResourceID': record.id} - - self.connection.set_context(context={'resource': 'record', - 'id': record.id}) - data = self.connection.request(API_ROOT, params=params).objects[0] - - return 'ResourceID' in data - - def _to_zones(self, items): - """ - Convert a list of items to the Zone objects. - """ - zones = [] - - for item in items: - zones.append(self._to_zone(item)) - - return zones - - def _to_zone(self, item): - """ - Build an Zone object from the item dictionary. - """ - extra = {'SOA_Email': item['SOA_EMAIL'], 'status': item['STATUS'], - 'description': item['DESCRIPTION']} - zone = Zone(id=item['DOMAINID'], domain=item['DOMAIN'], - type=item['TYPE'], ttl=item['TTL_SEC'], driver=self, - extra=extra) - return zone - - def _to_records(self, items, zone=None): - """ - Convert a list of items to the Record objects. - """ - records = [] - - for item in items: - records.append(self._to_record(item=item, zone=zone)) - - return records - - def _to_record(self, item, zone=None): - """ - Build a Record object from the item dictionary. - """ - extra = {'protocol': item['PROTOCOL'], 'ttl_sec': item['TTL_SEC'], - 'port': item['PORT'], 'weight': item['WEIGHT']} - type = self._string_to_record_type(item['TYPE']) - record = Record(id=item['RESOURCEID'], name=item['NAME'], type=type, - data=item['TARGET'], zone=zone, driver=self, - extra=extra) - return record diff --git a/awx/lib/site-packages/libcloud/dns/drivers/rackspace.py b/awx/lib/site-packages/libcloud/dns/drivers/rackspace.py deleted file mode 100644 index d71f4c5975..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/rackspace.py +++ /dev/null @@ -1,450 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from libcloud.common.openstack import OpenStackDriverMixin - -__all__ = [ - 'RackspaceUSDNSDriver', - 'RackspaceUKDNSDriver' -] - -from libcloud.utils.py3 import httplib -import copy - -from libcloud.common.base import PollingConnection -from libcloud.common.types import LibcloudError -from libcloud.utils.misc import merge_valid_keys, get_new_obj -from libcloud.common.rackspace import AUTH_URL -from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection -from libcloud.compute.drivers.openstack import OpenStack_1_1_Response - -from libcloud.dns.types import Provider, RecordType -from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError -from libcloud.dns.base import DNSDriver, Zone, Record - -VALID_ZONE_EXTRA_PARAMS = ['email', 'comment', 'ns1'] -VALID_RECORD_EXTRA_PARAMS = ['ttl', 'comment', 'priority'] - - -class RackspaceDNSResponse(OpenStack_1_1_Response): - """ - Rackspace DNS Response class. - """ - - def parse_error(self): - status = int(self.status) - context = self.connection.context - body = self.parse_body() - - if status == httplib.NOT_FOUND: - if context['resource'] == 'zone': - raise ZoneDoesNotExistError(value='', driver=self, - zone_id=context['id']) - elif context['resource'] == 'record': - raise RecordDoesNotExistError(value='', driver=self, - record_id=context['id']) - if body: - if 'code' and 'message' in body: - err = '%s - %s (%s)' % (body['code'], body['message'], - body['details']) - return err - elif 'validationErrors' in body: - errors = [m for m in body['validationErrors']['messages']] - err = 'Validation errors: %s' % ', '.join(errors) - return err - - raise LibcloudError('Unexpected status code: %s' % (status)) - - -class RackspaceDNSConnection(OpenStack_1_1_Connection, PollingConnection): - """ - Rackspace DNS Connection class. - """ - - responseCls = RackspaceDNSResponse - XML_NAMESPACE = None - poll_interval = 2.5 - timeout = 30 - - auth_url = AUTH_URL - _auth_version = '2.0' - - def __init__(self, *args, **kwargs): - self.region = kwargs.pop('region', None) - super(RackspaceDNSConnection, self).__init__(*args, **kwargs) - - def get_poll_request_kwargs(self, response, context, request_kwargs): - job_id = response.object['jobId'] - kwargs = {'action': '/status/%s' % (job_id), - 'params': {'showDetails': True}} - return kwargs - - def has_completed(self, response): - status = response.object['status'] - if status == 'ERROR': - data = response.object['error'] - - if 'code' and 'message' in data: - message = '%s - %s (%s)' % (data['code'], data['message'], - data['details']) - else: - message = data['message'] - - raise LibcloudError(message, - driver=self.driver) - - return status == 'COMPLETED' - - def get_endpoint(self): - if '2.0' in self._auth_version: - ep = self.service_catalog.get_endpoint(name='cloudDNS', - service_type='rax:dns', - region=None) - else: - raise LibcloudError("Auth version %s not supported" % - (self._auth_version)) - - public_url = ep.get('publicURL', None) - - # This is a nasty hack, but because of how global auth and old accounts - # work, there is no way around it. - if self.region == 'us': - # Old UK account, which only has us endpoint in the catalog - public_url = public_url.replace('https://lon.dns.api', - 'https://dns.api') - if self.region == 'uk': - # Old US account, which only has uk endpoint in the catalog - public_url = public_url.replace('https://dns.api', - 'https://lon.dns.api') - - return public_url - - -class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin): - name = 'Rackspace DNS' - website = 'http://www.rackspace.com/' - type = Provider.RACKSPACE - connectionCls = RackspaceDNSConnection - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='us', **kwargs): - if region not in ['us', 'uk']: - raise ValueError('Invalid region: %s' % (region)) - - OpenStackDriverMixin.__init__(self, **kwargs) - super(RackspaceDNSDriver, self).__init__(key=key, secret=secret, - host=host, port=port, - region=region) - - RECORD_TYPE_MAP = { - RecordType.A: 'A', - RecordType.AAAA: 'AAAA', - RecordType.CNAME: 'CNAME', - RecordType.MX: 'MX', - RecordType.NS: 'NS', - RecordType.PTR: 'PTR', - RecordType.SRV: 'SRV', - RecordType.TXT: 'TXT', - } - - def iterate_zones(self): - offset = 0 - limit = 100 - while True: - params = { - 'limit': limit, - 'offset': offset, - } - response = self.connection.request( - action='/domains', params=params).object - zones_list = response['domains'] - for item in zones_list: - yield self._to_zone(item) - - if _rackspace_result_has_more(response, len(zones_list), limit): - offset += limit - else: - break - - def iterate_records(self, zone): - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - offset = 0 - limit = 100 - while True: - params = { - 'showRecord': True, - 'limit': limit, - 'offset': offset, - } - response = self.connection.request( - action='/domains/%s' % (zone.id), params=params).object - records_list = response['recordsList'] - records = records_list['records'] - for item in records: - record = self._to_record(data=item, zone=zone) - yield record - - if _rackspace_result_has_more(records_list, len(records), limit): - offset += limit - else: - break - - def get_zone(self, zone_id): - self.connection.set_context({'resource': 'zone', 'id': zone_id}) - response = self.connection.request(action='/domains/%s' % (zone_id)) - zone = self._to_zone(data=response.object) - return zone - - def get_record(self, zone_id, record_id): - zone = self.get_zone(zone_id=zone_id) - self.connection.set_context({'resource': 'record', 'id': record_id}) - response = self.connection.request(action='/domains/%s/records/%s' % - (zone_id, record_id)).object - record = self._to_record(data=response, zone=zone) - return record - - def create_zone(self, domain, type='master', ttl=None, extra=None): - extra = extra if extra else {} - - # Email address is required - if 'email' not in extra: - raise ValueError('"email" key must be present in extra dictionary') - - payload = {'name': domain, 'emailAddress': extra['email'], - 'recordsList': {'records': []}} - - if ttl: - payload['ttl'] = ttl - - if 'comment' in extra: - payload['comment'] = extra['comment'] - - data = {'domains': [payload]} - response = self.connection.async_request(action='/domains', - method='POST', data=data) - zone = self._to_zone(data=response.object['response']['domains'][0]) - return zone - - def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): - # Only ttl, comment and email address can be changed - extra = extra if extra else {} - - if domain: - raise LibcloudError('Domain cannot be changed', driver=self) - - data = {} - - if ttl: - data['ttl'] = int(ttl) - - if 'email' in extra: - data['emailAddress'] = extra['email'] - - if 'comment' in extra: - data['comment'] = extra['comment'] - - type = type if type else zone.type - ttl = ttl if ttl else zone.ttl - - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - self.connection.async_request(action='/domains/%s' % (zone.id), - method='PUT', data=data) - merged = merge_valid_keys(params=copy.deepcopy(zone.extra), - valid_keys=VALID_ZONE_EXTRA_PARAMS, - extra=extra) - updated_zone = get_new_obj(obj=zone, klass=Zone, - attributes={'type': type, - 'ttl': ttl, - 'extra': merged}) - return updated_zone - - def create_record(self, name, zone, type, data, extra=None): - # Name must be a FQDN - e.g. if domain is "foo.com" then a record - # name is "bar.foo.com" - extra = extra if extra else {} - - name = self._to_full_record_name(domain=zone.domain, name=name) - data = {'name': name, 'type': self.RECORD_TYPE_MAP[type], - 'data': data} - - if 'ttl' in extra: - data['ttl'] = int(extra['ttl']) - - if 'priority' in extra: - data['priority'] = int(extra['priority']) - - payload = {'records': [data]} - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - response = self.connection.async_request(action='/domains/%s/records' - % (zone.id), data=payload, - method='POST').object - record = self._to_record(data=response['response']['records'][0], - zone=zone) - return record - - def update_record(self, record, name=None, type=None, data=None, - extra=None): - # Only data, ttl, and comment attributes can be modified, but name - # attribute must always be present. - extra = extra if extra else {} - - name = self._to_full_record_name(domain=record.zone.domain, - name=record.name) - payload = {'name': name} - - if data: - payload['data'] = data - - if 'ttl' in extra: - payload['ttl'] = extra['ttl'] - - if 'comment' in extra: - payload['comment'] = extra['comment'] - - type = type if type is not None else record.type - data = data if data else record.data - - self.connection.set_context({'resource': 'record', 'id': record.id}) - self.connection.async_request(action='/domains/%s/records/%s' % - (record.zone.id, record.id), - method='PUT', data=payload) - - merged = merge_valid_keys(params=copy.deepcopy(record.extra), - valid_keys=VALID_RECORD_EXTRA_PARAMS, - extra=extra) - updated_record = get_new_obj(obj=record, klass=Record, - attributes={'type': type, - 'data': data, - 'driver': self, - 'extra': merged}) - return updated_record - - def delete_zone(self, zone): - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - self.connection.async_request(action='/domains/%s' % (zone.id), - method='DELETE') - return True - - def delete_record(self, record): - self.connection.set_context({'resource': 'record', 'id': record.id}) - self.connection.async_request(action='/domains/%s/records/%s' % - (record.zone.id, record.id), - method='DELETE') - return True - - def _to_zone(self, data): - id = data['id'] - domain = data['name'] - type = 'master' - ttl = data.get('ttl', 0) - extra = {} - - if 'emailAddress' in data: - extra['email'] = data['emailAddress'] - - if 'comment' in data: - extra['comment'] = data['comment'] - - zone = Zone(id=str(id), domain=domain, type=type, ttl=int(ttl), - driver=self, extra=extra) - return zone - - def _to_record(self, data, zone): - id = data['id'] - fqdn = data['name'] - name = self._to_partial_record_name(domain=zone.domain, name=fqdn) - type = self._string_to_record_type(data['type']) - record_data = data['data'] - extra = {'fqdn': fqdn} - - for key in VALID_RECORD_EXTRA_PARAMS: - if key in data: - extra[key] = data[key] - - record = Record(id=str(id), name=name, type=type, data=record_data, - zone=zone, driver=self, extra=extra) - return record - - def _to_full_record_name(self, domain, name): - """ - Build a FQDN from a domain and record name. - - :param domain: Domain name. - :type domain: ``str`` - - :param name: Record name. - :type name: ``str`` - """ - if name: - name = '%s.%s' % (name, domain) - else: - name = domain - - return name - - def _to_partial_record_name(self, domain, name): - """ - Remove domain portion from the record name. - - :param domain: Domain name. - :type domain: ``str`` - - :param name: Full record name (fqdn). - :type name: ``str`` - """ - if name == domain: - # Map "root" record names to None to be consistent with other - # drivers - return None - - # Strip domain portion - name = name.replace('.%s' % (domain), '') - return name - - def _ex_connection_class_kwargs(self): - kwargs = self.openstack_connection_kwargs() - kwargs['region'] = self.region - return kwargs - - -class RackspaceUSDNSDriver(RackspaceDNSDriver): - name = 'Rackspace DNS (US)' - type = Provider.RACKSPACE_US - - def __init__(self, *args, **kwargs): - kwargs['region'] = 'us' - super(RackspaceUSDNSDriver, self).__init__(*args, **kwargs) - - -class RackspaceUKDNSDriver(RackspaceDNSDriver): - name = 'Rackspace DNS (UK)' - type = Provider.RACKSPACE_UK - - def __init__(self, *args, **kwargs): - kwargs['region'] = 'uk' - super(RackspaceUKDNSDriver, self).__init__(*args, **kwargs) - - -def _rackspace_result_has_more(response, result_length, limit): - # If rackspace returns less than the limit, then we've reached the end of - # the result set. - if result_length < limit: - return False - - # Paginated results return links to the previous and next sets of data, but - # 'next' only exists when there is more to get. - for item in response.get('links', ()): - if item['rel'] == 'next': - return True - return False diff --git a/awx/lib/site-packages/libcloud/dns/drivers/route53.py b/awx/lib/site-packages/libcloud/dns/drivers/route53.py deleted file mode 100644 index f1a8f34920..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/route53.py +++ /dev/null @@ -1,527 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'Route53DNSDriver' -] - -import base64 -import hmac -import datetime -import uuid -import copy -from libcloud.utils.py3 import httplib - -from hashlib import sha1 - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.utils.py3 import b, urlencode - -from libcloud.utils.xml import findtext, findall, fixxpath -from libcloud.dns.types import Provider, RecordType -from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError -from libcloud.dns.base import DNSDriver, Zone, Record -from libcloud.common.types import LibcloudError -from libcloud.common.aws import AWSGenericResponse -from libcloud.common.base import ConnectionUserAndKey - - -API_VERSION = '2012-02-29' -API_HOST = 'route53.amazonaws.com' -API_ROOT = '/%s/' % (API_VERSION) - -NAMESPACE = 'https://%s/doc%s' % (API_HOST, API_ROOT) - - -class InvalidChangeBatch(LibcloudError): - pass - - -class Route53DNSResponse(AWSGenericResponse): - """ - Amazon Route53 response class. - """ - - namespace = NAMESPACE - xpath = 'Error' - - exceptions = { - 'NoSuchHostedZone': ZoneDoesNotExistError, - 'InvalidChangeBatch': InvalidChangeBatch, - } - - -class Route53Connection(ConnectionUserAndKey): - host = API_HOST - responseCls = Route53DNSResponse - - def pre_connect_hook(self, params, headers): - time_string = datetime.datetime.utcnow() \ - .strftime('%a, %d %b %Y %H:%M:%S GMT') - headers['Date'] = time_string - tmp = [] - - signature = self._get_aws_auth_b64(self.key, time_string) - auth = {'AWSAccessKeyId': self.user_id, 'Signature': signature, - 'Algorithm': 'HmacSHA1'} - - for k, v in auth.items(): - tmp.append('%s=%s' % (k, v)) - - headers['X-Amzn-Authorization'] = 'AWS3-HTTPS ' + ','.join(tmp) - - return params, headers - - def _get_aws_auth_b64(self, secret_key, time_string): - b64_hmac = base64.b64encode( - hmac.new(b(secret_key), b(time_string), digestmod=sha1).digest() - ) - - return b64_hmac.decode('utf-8') - - -class Route53DNSDriver(DNSDriver): - type = Provider.ROUTE53 - name = 'Route53 DNS' - website = 'http://aws.amazon.com/route53/' - connectionCls = Route53Connection - - RECORD_TYPE_MAP = { - RecordType.A: 'A', - RecordType.AAAA: 'AAAA', - RecordType.CNAME: 'CNAME', - RecordType.MX: 'MX', - RecordType.NS: 'NS', - RecordType.PTR: 'PTR', - RecordType.SOA: 'SOA', - RecordType.SPF: 'SPF', - RecordType.SRV: 'SRV', - RecordType.TXT: 'TXT', - } - - def iterate_zones(self): - return self._get_more('zones') - - def iterate_records(self, zone): - return self._get_more('records', zone=zone) - - def get_zone(self, zone_id): - self.connection.set_context({'zone_id': zone_id}) - uri = API_ROOT + 'hostedzone/' + zone_id - data = self.connection.request(uri).object - elem = findall(element=data, xpath='HostedZone', - namespace=NAMESPACE)[0] - return self._to_zone(elem) - - def get_record(self, zone_id, record_id): - zone = self.get_zone(zone_id=zone_id) - record_type, name = record_id.split(':', 1) - if name: - full_name = ".".join((name, zone.domain)) - else: - full_name = zone.domain - self.connection.set_context({'zone_id': zone_id}) - params = urlencode({ - 'name': full_name, - 'type': record_type, - 'maxitems': '1' - }) - uri = API_ROOT + 'hostedzone/' + zone_id + '/rrset?' + params - data = self.connection.request(uri).object - - record = self._to_records(data=data, zone=zone)[0] - - # A cute aspect of the /rrset filters is that they are more pagination - # hints than filters!! - # So will return a result even if its not what you asked for. - record_type_num = self._string_to_record_type(record_type) - if record.name != name or record.type != record_type_num: - raise RecordDoesNotExistError(value='', driver=self, - record_id=record_id) - - return record - - def create_zone(self, domain, type='master', ttl=None, extra=None): - zone = ET.Element('CreateHostedZoneRequest', {'xmlns': NAMESPACE}) - ET.SubElement(zone, 'Name').text = domain - ET.SubElement(zone, 'CallerReference').text = str(uuid.uuid4()) - - if extra and 'Comment' in extra: - hzg = ET.SubElement(zone, 'HostedZoneConfig') - ET.SubElement(hzg, 'Comment').text = extra['Comment'] - - uri = API_ROOT + 'hostedzone' - data = ET.tostring(zone) - rsp = self.connection.request(uri, method='POST', data=data).object - - elem = findall(element=rsp, xpath='HostedZone', namespace=NAMESPACE)[0] - return self._to_zone(elem=elem) - - def delete_zone(self, zone, ex_delete_records=False): - self.connection.set_context({'zone_id': zone.id}) - - if ex_delete_records: - self.ex_delete_all_records(zone=zone) - - uri = API_ROOT + 'hostedzone/%s' % (zone.id) - response = self.connection.request(uri, method='DELETE') - return response.status in [httplib.OK] - - def create_record(self, name, zone, type, data, extra=None): - extra = extra or {} - batch = [('CREATE', name, type, data, extra)] - self._post_changeset(zone, batch) - id = ':'.join((self.RECORD_TYPE_MAP[type], name)) - return Record(id=id, name=name, type=type, data=data, zone=zone, - driver=self, extra=extra) - - def update_record(self, record, name=None, type=None, data=None, - extra=None): - name = name or record.name - type = type or record.type - extra = extra or record.extra - - if not extra: - extra = record.extra - - # Multiple value records need to be handled specially - we need to - # pass values for other records as well - multiple_value_record = record.extra.get('_multi_value', False) - other_records = record.extra.get('_other_records', []) - - if multiple_value_record and other_records: - self._update_multi_value_record(record=record, name=name, - type=type, data=data, - extra=extra) - else: - self._update_single_value_record(record=record, name=name, - type=type, data=data, - extra=extra) - - id = ':'.join((self.RECORD_TYPE_MAP[type], name)) - return Record(id=id, name=name, type=type, data=data, zone=record.zone, - driver=self, extra=extra) - - def delete_record(self, record): - try: - r = record - batch = [('DELETE', r.name, r.type, r.data, r.extra)] - self._post_changeset(record.zone, batch) - except InvalidChangeBatch: - raise RecordDoesNotExistError(value='', driver=self, - record_id=r.id) - return True - - def ex_create_multi_value_record(self, name, zone, type, data, extra=None): - """ - Create a record with multiple values with a single call. - - :return: A list of created records. - :rtype: ``list`` of :class:`libcloud.dns.base.Record` - """ - extra = extra or {} - - attrs = {'xmlns': NAMESPACE} - changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs) - batch = ET.SubElement(changeset, 'ChangeBatch') - changes = ET.SubElement(batch, 'Changes') - - change = ET.SubElement(changes, 'Change') - ET.SubElement(change, 'Action').text = 'CREATE' - - rrs = ET.SubElement(change, 'ResourceRecordSet') - ET.SubElement(rrs, 'Name').text = name + '.' + zone.domain - ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type] - ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0')) - - rrecs = ET.SubElement(rrs, 'ResourceRecords') - - # Value is provided as a multi line string - values = [value.strip() for value in data.split('\n') if - value.strip()] - - for value in values: - rrec = ET.SubElement(rrecs, 'ResourceRecord') - ET.SubElement(rrec, 'Value').text = value - - uri = API_ROOT + 'hostedzone/' + zone.id + '/rrset' - data = ET.tostring(changeset) - self.connection.set_context({'zone_id': zone.id}) - self.connection.request(uri, method='POST', data=data) - - id = ':'.join((self.RECORD_TYPE_MAP[type], name)) - - records = [] - for value in values: - record = Record(id=id, name=name, type=type, data=value, zone=zone, - driver=self, extra=extra) - records.append(record) - - return record - - def ex_delete_all_records(self, zone): - """ - Remove all the records for the provided zone. - - :param zone: Zone to delete records for. - :type zone: :class:`Zone` - """ - deletions = [] - for r in zone.list_records(): - if r.type in (RecordType.NS, RecordType.SOA): - continue - deletions.append(('DELETE', r.name, r.type, r.data, r.extra)) - - if deletions: - self._post_changeset(zone, deletions) - - def _update_single_value_record(self, record, name=None, type=None, - data=None, extra=None): - batch = [ - ('DELETE', record.name, record.type, record.data, record.extra), - ('CREATE', name, type, data, extra) - ] - - return self._post_changeset(record.zone, batch) - - def _update_multi_value_record(self, record, name=None, type=None, - data=None, extra=None): - other_records = record.extra.get('_other_records', []) - - attrs = {'xmlns': NAMESPACE} - changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs) - batch = ET.SubElement(changeset, 'ChangeBatch') - changes = ET.SubElement(batch, 'Changes') - - # Delete existing records - change = ET.SubElement(changes, 'Change') - ET.SubElement(change, 'Action').text = 'DELETE' - - rrs = ET.SubElement(change, 'ResourceRecordSet') - ET.SubElement(rrs, 'Name').text = record.name + '.' + \ - record.zone.domain - ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[record.type] - ET.SubElement(rrs, 'TTL').text = str(record.extra.get('ttl', '0')) - - rrecs = ET.SubElement(rrs, 'ResourceRecords') - - rrec = ET.SubElement(rrecs, 'ResourceRecord') - ET.SubElement(rrec, 'Value').text = record.data - - for other_record in other_records: - rrec = ET.SubElement(rrecs, 'ResourceRecord') - ET.SubElement(rrec, 'Value').text = other_record['data'] - - # Re-create new (updated) records. Since we are updating a multi value - # record, only a single record is updated and others are left as is. - change = ET.SubElement(changes, 'Change') - ET.SubElement(change, 'Action').text = 'CREATE' - - rrs = ET.SubElement(change, 'ResourceRecordSet') - ET.SubElement(rrs, 'Name').text = name + '.' + record.zone.domain - ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type] - ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0')) - - rrecs = ET.SubElement(rrs, 'ResourceRecords') - - rrec = ET.SubElement(rrecs, 'ResourceRecord') - ET.SubElement(rrec, 'Value').text = data - - for other_record in other_records: - rrec = ET.SubElement(rrecs, 'ResourceRecord') - ET.SubElement(rrec, 'Value').text = other_record['data'] - - uri = API_ROOT + 'hostedzone/' + record.zone.id + '/rrset' - data = ET.tostring(changeset) - self.connection.set_context({'zone_id': record.zone.id}) - response = self.connection.request(uri, method='POST', data=data) - - return response.status == httplib.OK - - def _post_changeset(self, zone, changes_list): - attrs = {'xmlns': NAMESPACE} - changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs) - batch = ET.SubElement(changeset, 'ChangeBatch') - changes = ET.SubElement(batch, 'Changes') - - for action, name, type_, data, extra in changes_list: - change = ET.SubElement(changes, 'Change') - ET.SubElement(change, 'Action').text = action - - rrs = ET.SubElement(change, 'ResourceRecordSet') - ET.SubElement(rrs, 'Name').text = name + '.' + zone.domain - ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type_] - ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0')) - - rrecs = ET.SubElement(rrs, 'ResourceRecords') - rrec = ET.SubElement(rrecs, 'ResourceRecord') - ET.SubElement(rrec, 'Value').text = data - - uri = API_ROOT + 'hostedzone/' + zone.id + '/rrset' - data = ET.tostring(changeset) - self.connection.set_context({'zone_id': zone.id}) - response = self.connection.request(uri, method='POST', data=data) - - return response.status == httplib.OK - - def _to_zones(self, data): - zones = [] - for element in data.findall(fixxpath(xpath='HostedZones/HostedZone', - namespace=NAMESPACE)): - zones.append(self._to_zone(element)) - - return zones - - def _to_zone(self, elem): - name = findtext(element=elem, xpath='Name', namespace=NAMESPACE) - id = findtext(element=elem, xpath='Id', - namespace=NAMESPACE).replace('/hostedzone/', '') - comment = findtext(element=elem, xpath='Config/Comment', - namespace=NAMESPACE) - resource_record_count = int(findtext(element=elem, - xpath='ResourceRecordSetCount', - namespace=NAMESPACE)) - - extra = {'Comment': comment, 'ResourceRecordSetCount': - resource_record_count} - - zone = Zone(id=id, domain=name, type='master', ttl=0, driver=self, - extra=extra) - return zone - - def _to_records(self, data, zone): - records = [] - elems = data.findall( - fixxpath(xpath='ResourceRecordSets/ResourceRecordSet', - namespace=NAMESPACE)) - for elem in elems: - record_set = elem.findall(fixxpath( - xpath='ResourceRecords/ResourceRecord', - namespace=NAMESPACE)) - record_count = len(record_set) - multiple_value_record = (record_count > 1) - - record_set_records = [] - - for index, record in enumerate(record_set): - # Need to special handling for records with multiple values for - # update to work correctly - record = self._to_record(elem=elem, zone=zone, index=index) - record.extra['_multi_value'] = multiple_value_record - - if multiple_value_record: - record.extra['_other_records'] = [] - - record_set_records.append(record) - - # Store reference to other records so update works correctly - if multiple_value_record: - for index in range(0, len(record_set_records)): - record = record_set_records[index] - - for other_index, other_record in \ - enumerate(record_set_records): - if index == other_index: - # Skip current record - continue - - extra = copy.deepcopy(other_record.extra) - extra.pop('_multi_value') - extra.pop('_other_records') - - item = {'name': other_record.name, - 'data': other_record.data, - 'type': other_record.type, - 'extra': extra} - record.extra['_other_records'].append(item) - - records.extend(record_set_records) - - return records - - def _to_record(self, elem, zone, index=0): - name = findtext(element=elem, xpath='Name', - namespace=NAMESPACE) - name = name[:-len(zone.domain) - 1] - - type = self._string_to_record_type(findtext(element=elem, xpath='Type', - namespace=NAMESPACE)) - ttl = int(findtext(element=elem, xpath='TTL', namespace=NAMESPACE)) - - value_elem = elem.findall( - fixxpath(xpath='ResourceRecords/ResourceRecord', - namespace=NAMESPACE))[index] - data = findtext(element=(value_elem), xpath='Value', - namespace=NAMESPACE) - - extra = {'ttl': ttl} - - if type == 'MX': - split = data.split() - priority, data = split - extra['priority'] = int(priority) - elif type == 'SRV': - split = data.split() - priority, weight, port, data = split - extra['priority'] = int(priority) - extra['weight'] = int(weight) - extra['port'] = int(port) - - id = ':'.join((self.RECORD_TYPE_MAP[type], name)) - record = Record(id=id, name=name, type=type, data=data, zone=zone, - driver=self, extra=extra) - return record - - def _get_more(self, rtype, **kwargs): - exhausted = False - last_key = None - while not exhausted: - items, last_key, exhausted = self._get_data(rtype, last_key, - **kwargs) - for item in items: - yield item - - def _get_data(self, rtype, last_key, **kwargs): - params = {} - if last_key: - params['name'] = last_key - path = API_ROOT + 'hostedzone' - - if rtype == 'zones': - response = self.connection.request(path, params=params) - transform_func = self._to_zones - elif rtype == 'records': - zone = kwargs['zone'] - path += '/%s/rrset' % (zone.id) - self.connection.set_context({'zone_id': zone.id}) - response = self.connection.request(path, params=params) - transform_func = self._to_records - - if response.status == httplib.OK: - is_truncated = findtext(element=response.object, - xpath='IsTruncated', - namespace=NAMESPACE) - exhausted = is_truncated != 'true' - last_key = findtext(element=response.object, - xpath='NextRecordName', - namespace=NAMESPACE) - items = transform_func(data=response.object, **kwargs) - return items, last_key, exhausted - else: - return [], None, True diff --git a/awx/lib/site-packages/libcloud/dns/drivers/zerigo.py b/awx/lib/site-packages/libcloud/dns/drivers/zerigo.py deleted file mode 100644 index 0af7a9f453..0000000000 --- a/awx/lib/site-packages/libcloud/dns/drivers/zerigo.py +++ /dev/null @@ -1,484 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'ZerigoDNSDriver' -] - - -import copy -import base64 - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.utils.misc import merge_valid_keys, get_new_obj -from libcloud.utils.xml import findtext, findall -from libcloud.common.base import XmlResponse, ConnectionUserAndKey -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.common.types import MalformedResponseError -from libcloud.dns.types import Provider, RecordType -from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError -from libcloud.dns.base import DNSDriver, Zone, Record - -API_HOST = 'ns.zerigo.com' -API_VERSION = '1.1' -API_ROOT = '/api/%s/' % (API_VERSION) - -VALID_ZONE_EXTRA_PARAMS = ['notes', 'tag-list', 'ns1', 'slave-nameservers'] -VALID_RECORD_EXTRA_PARAMS = ['notes', 'ttl', 'priority'] - -# Number of items per page (maximum limit is 1000) -ITEMS_PER_PAGE = 100 - - -class ZerigoError(LibcloudError): - def __init__(self, code, errors): - self.code = code - self.errors = errors or [] - - def __str__(self): - return 'Errors: %s' % (', '.join(self.errors)) - - def __repr__(self): - return ('<ZerigoError response code=%s, errors count=%s>' % ( - self.code, len(self.errors))) - - -class ZerigoDNSResponse(XmlResponse): - def success(self): - return self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] - - def parse_error(self): - status = int(self.status) - - if status == 401: - if not self.body: - raise InvalidCredsError(str(self.status) + ': ' + self.error) - else: - raise InvalidCredsError(self.body) - elif status == 404: - context = self.connection.context - if context['resource'] == 'zone': - raise ZoneDoesNotExistError(value='', driver=self, - zone_id=context['id']) - elif context['resource'] == 'record': - raise RecordDoesNotExistError(value='', driver=self, - record_id=context['id']) - elif status != 503: - try: - body = ET.XML(self.body) - except: - raise MalformedResponseError('Failed to parse XML', - body=self.body) - - errors = [] - for error in findall(element=body, xpath='error'): - errors.append(error.text) - - raise ZerigoError(code=status, errors=errors) - - return self.body - - -class ZerigoDNSConnection(ConnectionUserAndKey): - host = API_HOST - secure = True - responseCls = ZerigoDNSResponse - - def add_default_headers(self, headers): - auth_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) - headers['Authorization'] = 'Basic %s' % (auth_b64.decode('utf-8')) - return headers - - def request(self, action, params=None, data='', headers=None, - method='GET'): - if not headers: - headers = {} - if not params: - params = {} - - if method in ("POST", "PUT"): - headers = {'Content-Type': 'application/xml; charset=UTF-8'} - return super(ZerigoDNSConnection, self).request(action=action, - params=params, - data=data, - method=method, - headers=headers) - - -class ZerigoDNSDriver(DNSDriver): - type = Provider.ZERIGO - name = 'Zerigo DNS' - website = 'http://www.zerigo.com/' - connectionCls = ZerigoDNSConnection - - RECORD_TYPE_MAP = { - RecordType.A: 'A', - RecordType.AAAA: 'AAAA', - RecordType.CNAME: 'CNAME', - RecordType.GEO: 'GEO', - RecordType.MX: 'MX', - RecordType.NAPTR: 'NAPTR', - RecordType.NS: 'NS', - RecordType.PTR: 'PTR', - RecordType.REDIRECT: 'REDIRECT', - RecordType.SPF: 'SPF', - RecordType.SRV: 'SRV', - RecordType.TXT: 'TXT', - RecordType.URL: 'URL', - } - - def iterate_zones(self): - return self._get_more('zones') - - def iterate_records(self, zone): - return self._get_more('records', zone=zone) - - def get_zone(self, zone_id): - path = API_ROOT + 'zones/%s.xml' % (zone_id) - self.connection.set_context({'resource': 'zone', 'id': zone_id}) - data = self.connection.request(path).object - zone = self._to_zone(elem=data) - return zone - - def get_record(self, zone_id, record_id): - zone = self.get_zone(zone_id=zone_id) - self.connection.set_context({'resource': 'record', 'id': record_id}) - path = API_ROOT + 'hosts/%s.xml' % (record_id) - data = self.connection.request(path).object - record = self._to_record(elem=data, zone=zone) - return record - - def create_zone(self, domain, type='master', ttl=None, extra=None): - """ - Create a new zone. - - Provider API docs: - https://www.zerigo.com/docs/apis/dns/1.1/zones/create - - @inherits: :class:`DNSDriver.create_zone` - """ - path = API_ROOT + 'zones.xml' - zone_elem = self._to_zone_elem(domain=domain, type=type, ttl=ttl, - extra=extra) - data = self.connection.request(action=path, - data=ET.tostring(zone_elem), - method='POST').object - zone = self._to_zone(elem=data) - return zone - - def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): - """ - Update an existing zone. - - Provider API docs: - https://www.zerigo.com/docs/apis/dns/1.1/zones/update - - @inherits: :class:`DNSDriver.update_zone` - """ - if domain: - raise LibcloudError('Domain cannot be changed', driver=self) - - path = API_ROOT + 'zones/%s.xml' % (zone.id) - zone_elem = self._to_zone_elem(domain=domain, type=type, ttl=ttl, - extra=extra) - response = self.connection.request(action=path, - data=ET.tostring(zone_elem), - method='PUT') - assert response.status == httplib.OK - - merged = merge_valid_keys(params=copy.deepcopy(zone.extra), - valid_keys=VALID_ZONE_EXTRA_PARAMS, - extra=extra) - updated_zone = get_new_obj(obj=zone, klass=Zone, - attributes={'type': type, - 'ttl': ttl, - 'extra': merged}) - return updated_zone - - def create_record(self, name, zone, type, data, extra=None): - """ - Create a new record. - - Provider API docs: - https://www.zerigo.com/docs/apis/dns/1.1/hosts/create - - @inherits: :class:`DNSDriver.create_record` - """ - path = API_ROOT + 'zones/%s/hosts.xml' % (zone.id) - record_elem = self._to_record_elem(name=name, type=type, data=data, - extra=extra) - response = self.connection.request(action=path, - data=ET.tostring(record_elem), - method='POST') - assert response.status == httplib.CREATED - record = self._to_record(elem=response.object, zone=zone) - return record - - def update_record(self, record, name=None, type=None, data=None, - extra=None): - path = API_ROOT + 'hosts/%s.xml' % (record.id) - record_elem = self._to_record_elem(name=name, type=type, data=data, - extra=extra) - response = self.connection.request(action=path, - data=ET.tostring(record_elem), - method='PUT') - assert response.status == httplib.OK - - merged = merge_valid_keys(params=copy.deepcopy(record.extra), - valid_keys=VALID_RECORD_EXTRA_PARAMS, - extra=extra) - updated_record = get_new_obj(obj=record, klass=Record, - attributes={'type': type, - 'data': data, - 'extra': merged}) - return updated_record - - def delete_zone(self, zone): - path = API_ROOT + 'zones/%s.xml' % (zone.id) - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - response = self.connection.request(action=path, method='DELETE') - return response.status == httplib.OK - - def delete_record(self, record): - path = API_ROOT + 'hosts/%s.xml' % (record.id) - self.connection.set_context({'resource': 'record', 'id': record.id}) - response = self.connection.request(action=path, method='DELETE') - return response.status == httplib.OK - - def ex_get_zone_by_domain(self, domain): - """ - Retrieve a zone object by the domain name. - - :param domain: The domain which should be used - :type domain: ``str`` - - :rtype: :class:`Zone` - """ - path = API_ROOT + 'zones/%s.xml' % (domain) - self.connection.set_context({'resource': 'zone', 'id': domain}) - data = self.connection.request(path).object - zone = self._to_zone(elem=data) - return zone - - def ex_force_slave_axfr(self, zone): - """ - Force a zone transfer. - - :param zone: Zone which should be used. - :type zone: :class:`Zone` - - :rtype: :class:`Zone` - """ - path = API_ROOT + 'zones/%s/force_slave_axfr.xml' % (zone.id) - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - response = self.connection.request(path, method='POST') - assert response.status == httplib.ACCEPTED - return zone - - def _to_zone_elem(self, domain=None, type=None, ttl=None, extra=None): - zone_elem = ET.Element('zone', {}) - - if domain: - domain_elem = ET.SubElement(zone_elem, 'domain') - domain_elem.text = domain - - if type: - ns_type_elem = ET.SubElement(zone_elem, 'ns-type') - - if type == 'master': - ns_type_elem.text = 'pri_sec' - elif type == 'slave': - if not extra or 'ns1' not in extra: - raise LibcloudError('ns1 extra attribute is required ' + - 'when zone type is slave', driver=self) - - ns_type_elem.text = 'sec' - ns1_elem = ET.SubElement(zone_elem, 'ns1') - ns1_elem.text = extra['ns1'] - elif type == 'std_master': - # TODO: Each driver should provide supported zone types - # Slave name servers are elsewhere - if not extra or 'slave-nameservers' not in extra: - raise LibcloudError('slave-nameservers extra ' + - 'attribute is required whenzone ' + - 'type is std_master', driver=self) - - ns_type_elem.text = 'pri' - slave_nameservers_elem = ET.SubElement(zone_elem, - 'slave-nameservers') - slave_nameservers_elem.text = extra['slave-nameservers'] - - if ttl: - default_ttl_elem = ET.SubElement(zone_elem, 'default-ttl') - default_ttl_elem.text = str(ttl) - - if extra and 'tag-list' in extra: - tags = extra['tag-list'] - - tags_elem = ET.SubElement(zone_elem, 'tag-list') - tags_elem.text = ' '.join(tags) - - return zone_elem - - def _to_record_elem(self, name=None, type=None, data=None, extra=None): - record_elem = ET.Element('host', {}) - - if name: - name_elem = ET.SubElement(record_elem, 'hostname') - name_elem.text = name - - if type is not None: - type_elem = ET.SubElement(record_elem, 'host-type') - type_elem.text = self.RECORD_TYPE_MAP[type] - - if data: - data_elem = ET.SubElement(record_elem, 'data') - data_elem.text = data - - if extra: - if 'ttl' in extra: - ttl_elem = ET.SubElement(record_elem, 'ttl', - {'type': 'integer'}) - ttl_elem.text = str(extra['ttl']) - - if 'priority' in extra: - # Only MX and SRV records support priority - priority_elem = ET.SubElement(record_elem, 'priority', - {'type': 'integer'}) - - priority_elem.text = str(extra['priority']) - - if 'notes' in extra: - notes_elem = ET.SubElement(record_elem, 'notes') - notes_elem.text = extra['notes'] - - return record_elem - - def _to_zones(self, elem): - zones = [] - - for item in findall(element=elem, xpath='zone'): - zone = self._to_zone(elem=item) - zones.append(zone) - - return zones - - def _to_zone(self, elem): - id = findtext(element=elem, xpath='id') - domain = findtext(element=elem, xpath='domain') - type = findtext(element=elem, xpath='ns-type') - type = 'master' if type.find('pri') == 0 else 'slave' - ttl = findtext(element=elem, xpath='default-ttl') - - hostmaster = findtext(element=elem, xpath='hostmaster') - custom_ns = findtext(element=elem, xpath='custom-ns') - custom_nameservers = findtext(element=elem, xpath='custom-nameservers') - notes = findtext(element=elem, xpath='notes') - nx_ttl = findtext(element=elem, xpath='nx-ttl') - slave_nameservers = findtext(element=elem, xpath='slave-nameservers') - tags = findtext(element=elem, xpath='tag-list') - tags = tags.split(' ') if tags else [] - - extra = {'hostmaster': hostmaster, 'custom-ns': custom_ns, - 'custom-nameservers': custom_nameservers, 'notes': notes, - 'nx-ttl': nx_ttl, 'slave-nameservers': slave_nameservers, - 'tags': tags} - zone = Zone(id=str(id), domain=domain, type=type, ttl=int(ttl), - driver=self, extra=extra) - return zone - - def _to_records(self, elem, zone): - records = [] - - for item in findall(element=elem, xpath='host'): - record = self._to_record(elem=item, zone=zone) - records.append(record) - - return records - - def _to_record(self, elem, zone): - id = findtext(element=elem, xpath='id') - name = findtext(element=elem, xpath='hostname') - type = findtext(element=elem, xpath='host-type') - type = self._string_to_record_type(type) - data = findtext(element=elem, xpath='data') - - notes = findtext(element=elem, xpath='notes', no_text_value=None) - state = findtext(element=elem, xpath='state', no_text_value=None) - fqdn = findtext(element=elem, xpath='fqdn', no_text_value=None) - priority = findtext(element=elem, xpath='priority', no_text_value=None) - ttl = findtext(element=elem, xpath='ttl', no_text_value=None) - - if not name: - name = None - - if ttl: - ttl = int(ttl) - - extra = {'notes': notes, 'state': state, 'fqdn': fqdn, - 'priority': priority, 'ttl': ttl} - - record = Record(id=id, name=name, type=type, data=data, - zone=zone, driver=self, extra=extra) - return record - - def _get_more(self, rtype, **kwargs): - exhausted = False - last_key = None - - while not exhausted: - items, last_key, exhausted = self._get_data(rtype, last_key, - **kwargs) - - for item in items: - yield item - - def _get_data(self, rtype, last_key, **kwargs): - # Note: last_key in this case really is a "last_page". - # TODO: Update base driver and change last_key to something more - # generic - e.g. marker - params = {} - params['per_page'] = ITEMS_PER_PAGE - params['page'] = last_key + 1 if last_key else 1 - - if rtype == 'zones': - path = API_ROOT + 'zones.xml' - response = self.connection.request(path) - transform_func = self._to_zones - elif rtype == 'records': - zone = kwargs['zone'] - path = API_ROOT + 'zones/%s/hosts.xml' % (zone.id) - self.connection.set_context({'resource': 'zone', 'id': zone.id}) - response = self.connection.request(path, params=params) - transform_func = self._to_records - - exhausted = False - result_count = int(response.headers.get('x-query-count', 0)) - - if (params['page'] * ITEMS_PER_PAGE) >= result_count: - exhausted = True - - if response.status == httplib.OK: - items = transform_func(elem=response.object, **kwargs) - return items, params['page'], exhausted - else: - return [], None, True diff --git a/awx/lib/site-packages/libcloud/dns/providers.py b/awx/lib/site-packages/libcloud/dns/providers.py deleted file mode 100644 index 64483a45ab..0000000000 --- a/awx/lib/site-packages/libcloud/dns/providers.py +++ /dev/null @@ -1,49 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.utils.misc import get_driver as get_provider_driver -from libcloud.utils.misc import set_driver as set_provider_driver -from libcloud.dns.types import Provider - -DRIVERS = { - Provider.DUMMY: - ('libcloud.dns.drivers.dummy', 'DummyDNSDriver'), - Provider.LINODE: - ('libcloud.dns.drivers.linode', 'LinodeDNSDriver'), - Provider.ZERIGO: - ('libcloud.dns.drivers.zerigo', 'ZerigoDNSDriver'), - Provider.RACKSPACE: - ('libcloud.dns.drivers.rackspace', 'RackspaceDNSDriver'), - Provider.HOSTVIRTUAL: - ('libcloud.dns.drivers.hostvirtual', 'HostVirtualDNSDriver'), - Provider.ROUTE53: - ('libcloud.dns.drivers.route53', 'Route53DNSDriver'), - Provider.GANDI: - ('libcloud.dns.drivers.gandi', 'GandiDNSDriver'), - Provider.GOOGLE: ('libcloud.dns.drivers.google', 'GoogleDNSDriver'), - # Deprecated - Provider.RACKSPACE_US: - ('libcloud.dns.drivers.rackspace', 'RackspaceUSDNSDriver'), - Provider.RACKSPACE_UK: - ('libcloud.dns.drivers.rackspace', 'RackspaceUKDNSDriver') -} - - -def get_driver(provider): - return get_provider_driver(DRIVERS, provider) - - -def set_driver(provider, module, klass): - return set_provider_driver(DRIVERS, provider, module, klass) diff --git a/awx/lib/site-packages/libcloud/dns/types.py b/awx/lib/site-packages/libcloud/dns/types.py deleted file mode 100644 index 3b3a79e60f..0000000000 --- a/awx/lib/site-packages/libcloud/dns/types.py +++ /dev/null @@ -1,115 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.common.types import LibcloudError - -__all__ = [ - 'Provider', - 'RecordType', - 'ZoneError', - 'ZoneDoesNotExistError', - 'ZoneAlreadyExistsError', - 'RecordError', - 'RecordDoesNotExistError', - 'RecordAlreadyExistsError' -] - - -class Provider(object): - DUMMY = 'dummy' - LINODE = 'linode' - RACKSPACE = 'rackspace' - ZERIGO = 'zerigo' - ROUTE53 = 'route53' - HOSTVIRTUAL = 'hostvirtual' - GANDI = 'gandi' - GOOGLE = 'google' - - # Deprecated - RACKSPACE_US = 'rackspace_us' - RACKSPACE_UK = 'rackspace_uk' - - -class RecordType(object): - """ - DNS record type. - """ - A = 'A' - AAAA = 'AAAA' - MX = 'MX' - NS = 'NS' - CNAME = 'CNAME' - DNAME = 'DNAME' - TXT = 'TXT' - PTR = 'PTR' - SOA = 'SOA' - SPF = 'SPF' - SRV = 'SRV' - PTR = 'PTR' - NAPTR = 'NAPTR' - REDIRECT = 'REDIRECT' - GEO = 'GEO' - URL = 'URL' - WKS = 'WKS' - LOC = 'LOC' - - -class ZoneError(LibcloudError): - error_type = 'ZoneError' - kwargs = ('zone_id', ) - - def __init__(self, value, driver, zone_id): - self.zone_id = zone_id - super(ZoneError, self).__init__(value=value, driver=driver) - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return ('<%s in %s, zone_id=%s, value=%s>' % - (self.error_type, repr(self.driver), - self.zone_id, self.value)) - - -class ZoneDoesNotExistError(ZoneError): - error_type = 'ZoneDoesNotExistError' - - -class ZoneAlreadyExistsError(ZoneError): - error_type = 'ZoneAlreadyExistsError' - - -class RecordError(LibcloudError): - error_type = 'RecordError' - - def __init__(self, value, driver, record_id): - self.record_id = record_id - super(RecordError, self).__init__(value=value, driver=driver) - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return ('<%s in %s, record_id=%s, value=%s>' % - (self.error_type, repr(self.driver), - self.record_id, self.value)) - - -class RecordDoesNotExistError(RecordError): - error_type = 'RecordDoesNotExistError' - - -class RecordAlreadyExistsError(RecordError): - error_type = 'RecordAlreadyExistsError' diff --git a/awx/lib/site-packages/libcloud/httplib_ssl.py b/awx/lib/site-packages/libcloud/httplib_ssl.py deleted file mode 100644 index 29136ef201..0000000000 --- a/awx/lib/site-packages/libcloud/httplib_ssl.py +++ /dev/null @@ -1,158 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Subclass for httplib.HTTPSConnection with optional certificate name -verification, depending on libcloud.security settings. -""" -import os -import re -import socket -import ssl -import warnings - -import libcloud.security -from libcloud.utils.py3 import httplib - - -class LibcloudHTTPSConnection(httplib.HTTPSConnection): - """ - LibcloudHTTPSConnection - - Subclass of HTTPSConnection which verifies certificate names - if and only if CA certificates are available. - """ - verify = True # verify by default - ca_cert = None # no default CA Certificate - - def __init__(self, *args, **kwargs): - """ - Constructor - """ - self._setup_verify() - httplib.HTTPSConnection.__init__(self, *args, **kwargs) - - def _setup_verify(self): - """ - Setup Verify SSL or not - - Reads security module's VERIFY_SSL_CERT and toggles whether - the class overrides the connect() class method or runs the - inherited httplib.HTTPSConnection connect() - """ - self.verify = libcloud.security.VERIFY_SSL_CERT - - if self.verify: - self._setup_ca_cert() - else: - warnings.warn(libcloud.security.VERIFY_SSL_DISABLED_MSG) - - def _setup_ca_cert(self): - """ - Setup CA Certs - - Search in CA_CERTS_PATH for valid candidates and - return first match. Otherwise, complain about certs - not being available. - """ - if not self.verify: - return - - ca_certs_available = [cert - for cert in libcloud.security.CA_CERTS_PATH - if os.path.exists(cert) and os.path.isfile(cert)] - if ca_certs_available: - # use first available certificate - self.ca_cert = ca_certs_available[0] - else: - raise RuntimeError( - libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG) - - def connect(self): - """ - Connect - - Checks if verification is toggled; if not, just call - httplib.HTTPSConnection's connect - """ - if not self.verify: - return httplib.HTTPSConnection.connect(self) - - # otherwise, create a connection and verify the hostname - # use socket.create_connection (in 2.6+) if possible - if getattr(socket, 'create_connection', None): - sock = socket.create_connection((self.host, self.port), - self.timeout) - else: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((self.host, self.port)) - self.sock = ssl.wrap_socket(sock, - self.key_file, - self.cert_file, - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=self.ca_cert, - ssl_version=ssl.PROTOCOL_TLSv1) - cert = self.sock.getpeercert() - if not self._verify_hostname(self.host, cert): - raise ssl.SSLError('Failed to verify hostname') - - def _verify_hostname(self, hostname, cert): - """ - Verify hostname against peer cert - - Check both commonName and entries in subjectAltName, using a - rudimentary glob to dns regex check to find matches - """ - common_name = self._get_common_name(cert) - alt_names = self._get_subject_alt_names(cert) - - # replace * with alphanumeric and dash - # replace . with literal . - # http://www.dns.net/dnsrd/trick.html#legal-hostnames - valid_patterns = [ - re.compile('^' + pattern.replace(r".", r"\.") - .replace(r"*", r"[0-9A-Za-z\-]+") + '$') - for pattern in (set(common_name) | set(alt_names))] - - return any( - pattern.search(hostname) - for pattern in valid_patterns - ) - - def _get_subject_alt_names(self, cert): - """ - Get SubjectAltNames - - Retrieve 'subjectAltName' attributes from cert data structure - """ - if 'subjectAltName' not in cert: - values = [] - else: - values = [value - for field, value in cert['subjectAltName'] - if field == 'DNS'] - return values - - def _get_common_name(self, cert): - """ - Get Common Name - - Retrieve 'commonName' attribute from cert data structure - """ - if 'subject' not in cert: - return None - values = [value[0][1] - for value in cert['subject'] - if value[0][0] == 'commonName'] - return values diff --git a/awx/lib/site-packages/libcloud/loadbalancer/__init__.py b/awx/lib/site-packages/libcloud/loadbalancer/__init__.py deleted file mode 100644 index 70891776ff..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Module for working with Load Balancers -""" - -__all__ = [ - 'base', - 'providers', - 'types', - 'drivers' -] diff --git a/awx/lib/site-packages/libcloud/loadbalancer/base.py b/awx/lib/site-packages/libcloud/loadbalancer/base.py deleted file mode 100644 index b785af0232..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/base.py +++ /dev/null @@ -1,346 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.common.base import ConnectionKey, BaseDriver -from libcloud.common.types import LibcloudError - -__all__ = [ - 'Member', - 'LoadBalancer', - 'Algorithm', - 'Driver', - 'DEFAULT_ALGORITHM' -] - - -class Member(object): - """ - Represents a load balancer member. - """ - - def __init__(self, id, ip, port, balancer=None, extra=None): - """ - :param id: Member ID. - :type id: ``str`` - - :param ip: IP address of this member. - :param ip: ``str`` - - :param port: Port of this member - :param port: ``str`` - - :param balancer: Balancer this member is attached to. (optional) - :param balancer: :class:`.LoadBalancer` - - :param extra: Provider specific attributes. - :type extra: ``dict`` - """ - self.id = str(id) if id else None - self.ip = ip - self.port = port - self.balancer = balancer - self.extra = extra or {} - - def __repr__(self): - return ('<Member: id=%s, address=%s:%s>' % (self.id, - self.ip, self.port)) - - -class LoadBalancer(object): - """ - Provide a common interface for handling Load Balancers. - """ - - def __init__(self, id, name, state, ip, port, driver, extra=None): - """ - :param id: Load balancer ID. - :type id: ``str`` - - :param name: Load balancer name. - :type name: ``str`` - - :param state: State this loadbalancer is in. - :type state: :class:`libcloud.loadbalancer.types.State` - - :param ip: IP address of this loadbalancer. - :type ip: ``str`` - - :param port: Port of this loadbalancer. - :type port: ``int`` - - :param driver: Driver this loadbalancer belongs to. - :type driver: :class:`.Driver` - - :param extra: Provier specific attributes. (optional) - :type extra: ``dict`` - """ - self.id = str(id) if id else None - self.name = name - self.state = state - self.ip = ip - self.port = port - self.driver = driver - self.extra = extra or {} - - def attach_compute_node(self, node): - return self.driver.balancer_attach_compute_node(balancer=self, - node=node) - - def attach_member(self, member): - return self.driver.balancer_attach_member(balancer=self, - member=member) - - def detach_member(self, member): - return self.driver.balancer_detach_member(balancer=self, - member=member) - - def list_members(self): - return self.driver.balancer_list_members(balancer=self) - - def destroy(self): - return self.driver.destroy_balancer(balancer=self) - - def __repr__(self): - return ('<LoadBalancer: id=%s, name=%s, state=%s>' % (self.id, - self.name, self.state)) - - -class Algorithm(object): - """ - Represents a load balancing algorithm. - """ - - RANDOM = 0 - ROUND_ROBIN = 1 - LEAST_CONNECTIONS = 2 - WEIGHTED_ROUND_ROBIN = 3 - WEIGHTED_LEAST_CONNECTIONS = 4 - -DEFAULT_ALGORITHM = Algorithm.ROUND_ROBIN - - -class Driver(BaseDriver): - """ - A base Driver class to derive from - - This class is always subclassed by a specific driver. - """ - - name = None - website = None - - connectionCls = ConnectionKey - _ALGORITHM_TO_VALUE_MAP = {} - _VALUE_TO_ALGORITHM_MAP = {} - - def __init__(self, key, secret=None, secure=True, host=None, - port=None, **kwargs): - super(Driver, self).__init__(key=key, secret=secret, secure=secure, - host=host, port=port, **kwargs) - - def list_protocols(self): - """ - Return a list of supported protocols. - - :rtype: ``list`` of ``str`` - """ - raise NotImplementedError( - 'list_protocols not implemented for this driver') - - def list_balancers(self): - """ - List all loadbalancers - - :rtype: ``list`` of :class:`LoadBalancer` - """ - raise NotImplementedError( - 'list_balancers not implemented for this driver') - - def create_balancer(self, name, port, protocol, algorithm, members): - """ - Create a new load balancer instance - - :param name: Name of the new load balancer (required) - :type name: ``str`` - - :param port: Port the load balancer should listen on, defaults to 80 - :type port: ``str`` - - :param protocol: Loadbalancer protocol, defaults to http. - :type protocol: ``str`` - - :param members: list of Members to attach to balancer - :type members: ``list`` of :class:`Member` - - :param algorithm: Load balancing algorithm, defaults to ROUND_ROBIN. - :type algorithm: :class:`Algorithm` - - :rtype: :class:`LoadBalancer` - """ - raise NotImplementedError( - 'create_balancer not implemented for this driver') - - def destroy_balancer(self, balancer): - """ - Destroy a load balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :return: ``True`` if the destroy was successful, otherwise ``False``. - :rtype: ``bool`` - """ - - raise NotImplementedError( - 'destroy_balancer not implemented for this driver') - - def get_balancer(self, balancer_id): - """ - Return a :class:`LoadBalancer` object. - - :param balancer_id: id of a load balancer you want to fetch - :type balancer_id: ``str`` - - :rtype: :class:`LoadBalancer` - """ - - raise NotImplementedError( - 'get_balancer not implemented for this driver') - - def update_balancer(self, balancer, **kwargs): - """ - Sets the name, algorithm, protocol, or port on a load balancer. - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param name: New load balancer name - :type name: ``str`` - - :param algorithm: New load balancer algorithm - :type algorithm: :class:`Algorithm` - - :param protocol: New load balancer protocol - :type protocol: ``str`` - - :param port: New load balancer port - :type port: ``int`` - - :rtype: :class:`LoadBalancer` - """ - raise NotImplementedError( - 'update_balancer not implemented for this driver') - - def balancer_attach_compute_node(self, balancer, node): - """ - Attach a compute node as a member to the load balancer. - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param node: Node to join to the balancer - :type node: :class:`Node` - - :return: Member after joining the balancer. - :rtype: :class:`Member` - """ - - member = Member(id=None, ip=node.public_ips[0], port=balancer.port) - return self.balancer_attach_member(balancer, member) - - def balancer_attach_member(self, balancer, member): - """ - Attach a member to balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param member: Member to join to the balancer - :type member: :class:`Member` - - :return: Member after joining the balancer. - :rtype: :class:`Member` - """ - - raise NotImplementedError( - 'balancer_attach_member not implemented for this driver') - - def balancer_detach_member(self, balancer, member): - """ - Detach member from balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param member: Member which should be used - :type member: :class:`Member` - - :return: ``True`` if member detach was successful, otherwise ``False``. - :rtype: ``bool`` - """ - - raise NotImplementedError( - 'balancer_detach_member not implemented for this driver') - - def balancer_list_members(self, balancer): - """ - Return list of members attached to balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :rtype: ``list`` of :class:`Member` - """ - - raise NotImplementedError( - 'balancer_list_members not implemented for this driver') - - def list_supported_algorithms(self): - """ - Return algorithms supported by this driver. - - :rtype: ``list`` of ``str`` - """ - return list(self._ALGORITHM_TO_VALUE_MAP.keys()) - - def _value_to_algorithm(self, value): - """ - Return :class`Algorithm` based on the value. - - :param value: Algorithm name (e.g. http, tcp, ...). - :type value: ``str`` - - @rype :class:`Algorithm` - """ - try: - return self._VALUE_TO_ALGORITHM_MAP[value] - except KeyError: - raise LibcloudError(value='Invalid value: %s' % (value), - driver=self) - - def _algorithm_to_value(self, algorithm): - """ - Return string value for the provided algorithm. - - :param value: Algorithm enum. - :type value: :class:`Algorithm` - - @rype ``str`` - """ - try: - return self._ALGORITHM_TO_VALUE_MAP[algorithm] - except KeyError: - raise LibcloudError(value='Invalid algorithm: %s' % (algorithm), - driver=self) diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/__init__.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/__init__.py deleted file mode 100644 index f4fdb8666a..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'rackspace', - 'gogrid' -] diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/brightbox.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/brightbox.py deleted file mode 100644 index 22310d4daa..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/brightbox.py +++ /dev/null @@ -1,136 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from libcloud.utils.py3 import httplib -from libcloud.common.brightbox import BrightboxConnection -from libcloud.loadbalancer.base import Driver, Algorithm, Member -from libcloud.loadbalancer.base import LoadBalancer -from libcloud.loadbalancer.types import State -from libcloud.utils.misc import reverse_dict - -API_VERSION = '1.0' - - -class BrightboxLBDriver(Driver): - connectionCls = BrightboxConnection - - name = 'Brightbox' - website = 'http://www.brightbox.co.uk/' - - LB_STATE_MAP = { - 'creating': State.PENDING, - 'active': State.RUNNING, - 'deleting': State.UNKNOWN, - 'deleted': State.UNKNOWN, - 'failing': State.UNKNOWN, - 'failed': State.UNKNOWN, - } - - _VALUE_TO_ALGORITHM_MAP = { - 'round-robin': Algorithm.ROUND_ROBIN, - 'least-connections': Algorithm.LEAST_CONNECTIONS - } - - _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) - - def list_protocols(self): - return ['tcp', 'http'] - - def list_balancers(self): - data = self.connection.request('/%s/load_balancers' % API_VERSION) \ - .object - - return list(map(self._to_balancer, data)) - - def create_balancer(self, name, port, protocol, algorithm, members): - response = self._post( - '/%s/load_balancers' % API_VERSION, - {'name': name, - 'nodes': list(map(self._member_to_node, members)), - 'policy': self._algorithm_to_value(algorithm), - 'listeners': [{'in': port, 'out': port, 'protocol': protocol}], - 'healthcheck': {'type': protocol, 'port': port}} - ) - - return self._to_balancer(response.object) - - def destroy_balancer(self, balancer): - response = self.connection.request('/%s/load_balancers/%s' % - (API_VERSION, balancer.id), - method='DELETE') - - return response.status == httplib.ACCEPTED - - def get_balancer(self, balancer_id): - data = self.connection.request( - '/%s/load_balancers/%s' % (API_VERSION, balancer_id)).object - return self._to_balancer(data) - - def balancer_attach_compute_node(self, balancer, node): - return self.balancer_attach_member(balancer, node) - - def balancer_attach_member(self, balancer, member): - path = '/%s/load_balancers/%s/add_nodes' % (API_VERSION, balancer.id) - - self._post(path, {'nodes': [self._member_to_node(member)]}) - - return member - - def balancer_detach_member(self, balancer, member): - path = '/%s/load_balancers/%s/remove_nodes' % (API_VERSION, - balancer.id) - - response = self._post(path, {'nodes': [self._member_to_node(member)]}) - - return response.status == httplib.ACCEPTED - - def balancer_list_members(self, balancer): - path = '/%s/load_balancers/%s' % (API_VERSION, balancer.id) - - data = self.connection.request(path).object - - func = lambda data: self._node_to_member(data, balancer) - return list(map(func, data['nodes'])) - - def _post(self, path, data={}): - headers = {'Content-Type': 'application/json'} - - return self.connection.request(path, data=data, headers=headers, - method='POST') - - def _to_balancer(self, data): - return LoadBalancer( - id=data['id'], - name=data['name'], - state=self.LB_STATE_MAP.get(data['status'], State.UNKNOWN), - ip=self._public_ip(data), - port=data['listeners'][0]['in'], - driver=self.connection.driver - ) - - def _member_to_node(self, member): - return {'node': member.id} - - def _node_to_member(self, data, balancer): - return Member(id=data['id'], ip=None, port=None, balancer=balancer) - - def _public_ip(self, data): - if len(data['cloud_ips']) > 0: - ip = data['cloud_ips'][0]['public_ip'] - else: - ip = None - - return ip diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/cloudstack.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/cloudstack.py deleted file mode 100644 index ee88824308..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/cloudstack.py +++ /dev/null @@ -1,178 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.common.cloudstack import CloudStackDriverMixIn -from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm -from libcloud.loadbalancer.base import DEFAULT_ALGORITHM -from libcloud.loadbalancer.types import Provider -from libcloud.loadbalancer.types import State -from libcloud.utils.misc import reverse_dict - - -class CloudStackLBDriver(CloudStackDriverMixIn, Driver): - """Driver for CloudStack load balancers.""" - - api_name = 'cloudstack_lb' - name = 'CloudStack' - website = 'http://cloudstack.org/' - type = Provider.CLOUDSTACK - - _VALUE_TO_ALGORITHM_MAP = { - 'roundrobin': Algorithm.ROUND_ROBIN, - 'leastconn': Algorithm.LEAST_CONNECTIONS - } - _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) - - LB_STATE_MAP = { - 'Active': State.RUNNING, - } - - def __init__(self, key, secret=None, secure=True, host=None, - path=None, port=None, *args, **kwargs): - """ - @inherits: :class:`Driver.__init__` - """ - host = host if host else self.host - path = path if path else self.path - - if path is not None: - self.path = path - - if host is not None: - self.host = host - - if (self.type == Provider.CLOUDSTACK) and (not host or not path): - raise Exception('When instantiating CloudStack driver directly ' + - 'you also need to provide host and path argument') - - super(CloudStackLBDriver, self).__init__(key=key, secret=secret, - secure=secure, - host=host, port=port) - - def list_protocols(self): - """ - We don't actually have any protocol awareness beyond TCP. - - :rtype: ``list`` of ``str`` - """ - return ['tcp'] - - def list_balancers(self): - balancers = self._sync_request(command='listLoadBalancerRules', - method='GET') - balancers = balancers.get('loadbalancerrule', []) - return [self._to_balancer(balancer) for balancer in balancers] - - def get_balancer(self, balancer_id): - balancer = self._sync_request(command='listLoadBalancerRules', - params={'id': balancer_id}, - method='GET') - balancer = balancer.get('loadbalancerrule', []) - if not balancer: - raise Exception("no such load balancer: " + str(balancer_id)) - return self._to_balancer(balancer[0]) - - def create_balancer(self, name, members, protocol='http', port=80, - algorithm=DEFAULT_ALGORITHM, location=None, - private_port=None): - """ - @inherits: :class:`Driver.create_balancer` - - :param location: Location - :type location: :class:`NodeLocation` - - :param private_port: Private port - :type private_port: ``int`` - """ - if location is None: - locations = self._sync_request(command='listZones', method='GET') - location = locations['zone'][0]['id'] - else: - location = location.id - if private_port is None: - private_port = port - - result = self._async_request(command='associateIpAddress', - params={'zoneid': location}, - method='GET') - public_ip = result['ipaddress'] - - result = self._sync_request( - command='createLoadBalancerRule', - params={'algorithm': self._ALGORITHM_TO_VALUE_MAP[algorithm], - 'name': name, - 'privateport': private_port, - 'publicport': port, - 'publicipid': public_ip['id']}, - method='GET') - - balancer = self._to_balancer(result['loadbalancer']) - - for member in members: - balancer.attach_member(member) - - return balancer - - def destroy_balancer(self, balancer): - self._async_request(command='deleteLoadBalancerRule', - params={'id': balancer.id}, - method='GET') - self._async_request(command='disassociateIpAddress', - params={'id': balancer.ex_public_ip_id}, - method='GET') - - def balancer_attach_member(self, balancer, member): - member.port = balancer.ex_private_port - self._async_request(command='assignToLoadBalancerRule', - params={'id': balancer.id, - 'virtualmachineids': member.id}, - method='GET') - return True - - def balancer_detach_member(self, balancer, member): - self._async_request(command='removeFromLoadBalancerRule', - params={'id': balancer.id, - 'virtualmachineids': member.id}, - method='GET') - return True - - def balancer_list_members(self, balancer): - members = self._sync_request(command='listLoadBalancerRuleInstances', - params={'id': balancer.id}, - method='GET') - members = members['loadbalancerruleinstance'] - return [self._to_member(m, balancer.ex_private_port, balancer) - for m in members] - - def _to_balancer(self, obj): - balancer = LoadBalancer( - id=obj['id'], - name=obj['name'], - state=self.LB_STATE_MAP.get(obj['state'], State.UNKNOWN), - ip=obj['publicip'], - port=obj['publicport'], - driver=self.connection.driver - ) - balancer.ex_private_port = obj['privateport'] - balancer.ex_public_ip_id = obj['publicipid'] - return balancer - - def _to_member(self, obj, port, balancer): - return Member( - id=obj['id'], - ip=obj['nic'][0]['ipaddress'], - port=port, - balancer=balancer - ) diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/elb.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/elb.py deleted file mode 100644 index 73a3c72d6b..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/elb.py +++ /dev/null @@ -1,350 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'ElasticLBDriver' -] - - -from libcloud.utils.py3 import httplib -from libcloud.utils.xml import findtext, findall -from libcloud.loadbalancer.types import State -from libcloud.loadbalancer.base import Driver, LoadBalancer, Member -from libcloud.common.aws import AWSGenericResponse, SignedAWSConnection - - -VERSION = '2012-06-01' -HOST = 'elasticloadbalancing.%s.amazonaws.com' -ROOT = '/%s/' % (VERSION) -NS = 'http://elasticloadbalancing.amazonaws.com/doc/%s/' % (VERSION, ) - - -class ELBResponse(AWSGenericResponse): - """ - Amazon ELB response class. - """ - namespace = NS - exceptions = {} - xpath = 'Error' - - -class ELBConnection(SignedAWSConnection): - version = VERSION - host = HOST - responseCls = ELBResponse - - -class ElasticLBDriver(Driver): - name = 'Amazon Elastic Load Balancing' - website = 'http://aws.amazon.com/elasticloadbalancing/' - connectionCls = ELBConnection - - def __init__(self, access_id, secret, region): - super(ElasticLBDriver, self).__init__(access_id, secret) - self.region = region - self.connection.host = HOST % (region) - - def list_protocols(self): - return ['tcp', 'ssl', 'http', 'https'] - - def list_balancers(self): - params = {'Action': 'DescribeLoadBalancers'} - data = self.connection.request(ROOT, params=params).object - return self._to_balancers(data) - - def create_balancer(self, name, port, protocol, algorithm, members, - ex_members_availability_zones=None): - if ex_members_availability_zones is None: - ex_members_availability_zones = ['a'] - - params = { - 'Action': 'CreateLoadBalancer', - 'LoadBalancerName': name, - 'Listeners.member.1.InstancePort': str(port), - 'Listeners.member.1.InstanceProtocol': protocol.upper(), - 'Listeners.member.1.LoadBalancerPort': str(port), - 'Listeners.member.1.Protocol': protocol.upper(), - } - - for i, z in enumerate(ex_members_availability_zones): - zone = ''.join((self.region, z)) - params['AvailabilityZones.member.%d' % (i + 1)] = zone - - data = self.connection.request(ROOT, params=params).object - - balancer = LoadBalancer( - id=name, - name=name, - state=State.PENDING, - ip=findtext(element=data, xpath='DNSName', namespace=NS), - port=port, - driver=self.connection.driver - ) - balancer._members = [] - return balancer - - def destroy_balancer(self, balancer): - params = { - 'Action': 'DeleteLoadBalancer', - 'LoadBalancerName': balancer.id - } - self.connection.request(ROOT, params=params) - return True - - def get_balancer(self, balancer_id): - params = { - 'Action': 'DescribeLoadBalancers', - 'LoadBalancerNames.member.1': balancer_id - } - data = self.connection.request(ROOT, params=params).object - return self._to_balancers(data)[0] - - def balancer_attach_compute_node(self, balancer, node): - params = { - 'Action': 'RegisterInstancesWithLoadBalancer', - 'LoadBalancerName': balancer.id, - 'Instances.member.1.InstanceId': node.id - } - self.connection.request(ROOT, params=params) - balancer._members.append(Member(node.id, None, None, balancer=self)) - - def balancer_detach_member(self, balancer, member): - params = { - 'Action': 'DeregisterInstancesFromLoadBalancer', - 'LoadBalancerName': balancer.id, - 'Instances.member.1.InstanceId': member.id - } - self.connection.request(ROOT, params=params) - balancer._members = [m for m in balancer._members if m.id != member.id] - return True - - def balancer_list_members(self, balancer): - return balancer._members - - def ex_list_balancer_policies(self, balancer): - """ - Return a list of policy description string. - - :rtype: ``list`` of ``str`` - """ - params = { - 'Action': 'DescribeLoadBalancerPolicies', - 'LoadBalancerName': balancer.id - } - - data = self.connection.request(ROOT, params=params).object - return self._to_policies(data) - - def ex_list_balancer_policy_types(self): - """ - Return a list of policy type description string. - - :rtype: ``list`` of ``str`` - """ - params = {'Action': 'DescribeLoadBalancerPolicyTypes'} - - data = self.connection.request(ROOT, params=params).object - return self._to_policy_types(data) - - def ex_create_balancer_policy(self, name, policy_name, policy_type, - policy_attributes=None): - """ - Create a new load balancer policy - - :param name: Balancer name to create the policy for - :type name: ``str`` - - :param policy_name: policy to be created - :type policy_name: ``str`` - - :param policy_type: policy type being used to create policy. - :type policy_type: ``str`` - - :param policy_attributes: Each list contain values, ['AttributeName', - 'value'] - :type policy_attributes: ``PolicyAttribute list`` - """ - params = { - 'Action': 'CreateLoadBalancerPolicy', - 'LoadBalancerName': name, - 'PolicyName': policy_name, - 'PolicyTypeName': policy_type - } - - if policy_attributes is not None: - for index, (name, value) in enumerate( - policy_attributes.iteritems(), 1): - params['PolicyAttributes.member.%d. \ - AttributeName' % (index)] = name - params['PolicyAttributes.member.%d. \ - AttributeValue' % (index)] = value - - response = self.connection.request(ROOT, params=params) - return response.status == httplib.OK - - def ex_delete_balancer_policy(self, name, policy_name): - """ - Delete a load balancer policy - - :param name: balancer name for which policy will be deleted - :type name: ``str`` - - :param policy_name: The Mnemonic name for the policy being deleted - :type policy_name: ``str`` - """ - params = { - 'Action': 'DeleteLoadBalancerPolicy', - 'LoadBalancerName': name, - 'PolicyName': policy_name - } - - response = self.connection.request(ROOT, params=params) - return response.status == httplib.OK - - def ex_set_balancer_policies_listener(self, name, port, policies): - """ - Associates, updates, or disables a policy with a listener on - the load balancer - - :param name: balancer name to set policies for listerner - :type name: ``str`` - - :param port: port to use - :type port: ``str`` - - :param policies: List of policies to be associated with the balancer - :type policies: ``string list`` - """ - params = { - 'Action': 'SetLoadBalancerPoliciesOfListener', - 'LoadBalancerName': name, - 'LoadBalancerPort': str(port) - } - - if policies: - params = self._create_list_params(params, policies, - 'PolicyNames.member.%d') - - response = self.connection.request(ROOT, params=params) - return response.status == httplib.OK - - def ex_set_balancer_policies_backend_server(self, name, instance_port, - policies): - """ - Replaces the current set of policies associated with a port on - which the back-end server is listening with a new set of policies - - :param name: balancer name to set policies of backend server - :type name: ``str`` - - :param instance_port: Instance Port - :type instance_port: ``int`` - - :param policies: List of policies to be associated with the balancer - :type policies: ``string list` - """ - params = { - 'Action': 'SetLoadBalancerPoliciesForBackendServer', - 'LoadBalancerName': name, - 'InstancePort': str(instance_port) - } - - if policies: - params = self._create_list_params(params, policies, - 'PolicyNames.member.%d') - - response = self.connection.request(ROOT, params=params) - return response.status == httplib.OK - - def ex_create_balancer_listeners(self, name, listeners=None): - """ - Creates one or more listeners on a load balancer for the specified port - - :param name: The mnemonic name associated with the load balancer - :type name: ``str`` - - :param listeners: Each tuple contain values, (LoadBalancerPortNumber, - InstancePortNumber, Protocol,[SSLCertificateId]) - :type listeners: ``list of tuple` - """ - params = { - 'Action': 'CreateLoadBalancerListeners', - 'LoadBalancerName': name - } - - for index, listener in enumerate(listeners): - i = index + 1 - protocol = listener[2].upper() - params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0] - params['Listeners.member.%d.InstancePort' % i] = listener[1] - params['Listeners.member.%d.Protocol' % i] = listener[2] - if protocol == 'HTTPS' or protocol == 'SSL': - params['Listeners.member.%d. \ - SSLCertificateId' % i] = listener[3] - else: - return False - - response = self.connection.request(ROOT, params=params) - return response.status == httplib.OK - - def _to_policies(self, data): - xpath = 'DescribeLoadBalancerPoliciesResult/PolicyDescriptions/member' - return [findtext(element=el, xpath='PolicyName', namespace=NS) - for el in findall(element=data, xpath=xpath, namespace=NS)] - - def _to_policy_types(self, data): - xpath = 'DescribeLoadBalancerPolicyTypesResult/' - xpath += 'PolicyTypeDescriptions/member' - return [findtext(element=el, xpath='PolicyTypeName', namespace=NS) - for el in findall(element=data, xpath=xpath, namespace=NS)] - - def _to_balancers(self, data): - xpath = 'DescribeLoadBalancersResult/LoadBalancerDescriptions/member' - return [self._to_balancer(el) - for el in findall(element=data, xpath=xpath, namespace=NS)] - - def _to_balancer(self, el): - name = findtext(element=el, xpath='LoadBalancerName', namespace=NS) - dns_name = findtext(el, xpath='DNSName', namespace=NS) - port = findtext(el, xpath='LoadBalancerPort', namespace=NS) - - balancer = LoadBalancer( - id=name, - name=name, - state=State.UNKNOWN, - ip=dns_name, - port=port, - driver=self.connection.driver - ) - - xpath = 'Instances/member/InstanceId' - members = findall(element=el, xpath=xpath, namespace=NS) - balancer._members = [] - - for m in members: - balancer._members.append(Member(m.text, None, None, - balancer=balancer)) - - return balancer - - def _create_list_params(self, params, items, label): - """ - return parameter list - """ - if isinstance(items, str): - items = [items] - for index, item in enumerate(items): - params[label % (index + 1)] = item - return params diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/gce.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/gce.py deleted file mode 100644 index 09a32fdb6d..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/gce.py +++ /dev/null @@ -1,362 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import simplejson as json -except ImportError: - import json # NOQA - -from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm -from libcloud.compute.drivers.gce import GCEConnection, GCENodeDriver - -# GCE doesn't actually give you a algorithm choice, but this is here simply as -# the closest match. The actual algorithm is described here: -# https://developers.google.com/compute/docs/load-balancing/#overview -DEFAULT_ALGORITHM = Algorithm.RANDOM - - -class GCELBDriver(Driver): - connectionCls = GCEConnection - apiname = 'googleapis' - name = 'Google Compute Engine Load Balancer' - website = 'https://cloud.google.com/' - - _VALUE_TO_ALGORITHM_MAP = { - 'RANDOM': Algorithm.RANDOM - } - - def __init__(self, *args, **kwargs): - - if kwargs.get('gce_driver'): - self.gce = kwargs['gce_driver'] - else: - self.gce = GCENodeDriver(*args, **kwargs) - - self.connection = self.gce.connection - - def _get_node_from_ip(self, ip): - """ - Return the node object that matches a given public IP address. - - :param ip: Public IP address to search for - :type ip: ``str`` - - :return: Node object that has the given IP, or None if not found. - :rtype: :class:`Node` or None - """ - all_nodes = self.gce.list_nodes(ex_zone='all') - for node in all_nodes: - if ip in node.public_ips: - return node - return None - - def list_protocols(self): - """ - Return a list of supported protocols. - - For GCE, this is simply a hardcoded list. - - :rtype: ``list`` of ``str`` - """ - return ['TCP', 'UDP'] - - def list_balancers(self, ex_region=None): - """ - List all loadbalancers - - :keyword ex_region: The region to return balancers from. If None, - will default to self.region. If 'all', will - return all balancers. - :type ex_region: ``str`` or :class:`GCERegion` or ``None`` - - :rtype: ``list`` of :class:`LoadBalancer` - """ - balancers = [] - for fwr in self.gce.ex_list_forwarding_rules(region=ex_region): - balancers.append(self._forwarding_rule_to_loadbalancer(fwr)) - return balancers - - def create_balancer(self, name, port, protocol, algorithm, members, - ex_region=None, ex_healthchecks=None, ex_address=None): - """ - Create a new load balancer instance. - - For GCE, this means creating a forwarding rule and a matching target - pool, then adding the members to the target pool. - - :param name: Name of the new load balancer (required) - :type name: ``str`` - - :param port: Port or range of ports the load balancer should listen - on, defaults to all ports. Examples: '80', '5000-5999' - :type port: ``str`` - - :param protocol: Load balancer protocol. Should be 'tcp' or 'udp', - defaults to 'tcp'. - :type protocol: ``str`` - - :param members: List of Members to attach to balancer. Can be Member - objects or Node objects. Node objects are preferred - for GCE, but Member objects are accepted to comply - with the established libcloud API. Note that the - 'port' attribute of the members is ignored. - :type members: ``list`` of :class:`Member` or :class:`Node` - - :param algorithm: Load balancing algorithm. Ignored for GCE which - uses a hashing-based algorithm. - :type algorithm: :class:`Algorithm` or ``None`` - - :keyword ex_region: Optional region to create the load balancer in. - Defaults to the default region of the GCE Node - Driver. - :type ex_region: C{GCERegion} or ``str`` - - :keyword ex_healthchecks: Optional list of healthcheck objects or - names to add to the load balancer. - :type ex_healthchecks: ``list`` of :class:`GCEHealthCheck` or - ``str`` - - :keyword ex_address: Optional static address object to be assigned to - the load balancer. - :type ex_address: C{GCEAddress} - - :return: LoadBalancer object - :rtype: :class:`LoadBalancer` - """ - node_list = [] - for member in members: - # Member object - if hasattr(member, 'ip'): - if member.extra.get('node'): - node_list.append(member.extra['node']) - else: - node_list.append(self._get_node_from_ip(member.ip)) - # Node object - elif hasattr(member, 'name'): - node_list.append(member) - # Assume it's a node name otherwise - else: - node_list.append(self.gce.ex_get_node(member, 'all')) - - # Create Target Pool - tp_name = '%s-tp' % name - targetpool = self.gce.ex_create_targetpool( - tp_name, region=ex_region, healthchecks=ex_healthchecks, - nodes=node_list) - - # Create the Forwarding rule, but if it fails, delete the target pool. - try: - forwarding_rule = self.gce.ex_create_forwarding_rule( - name, targetpool, region=ex_region, protocol=protocol, - port_range=port, address=ex_address) - except: - targetpool.destroy() - raise - - # Reformat forwarding rule to LoadBalancer object - return self._forwarding_rule_to_loadbalancer(forwarding_rule) - - def destroy_balancer(self, balancer): - """ - Destroy a load balancer. - - For GCE, this means destroying the associated forwarding rule, then - destroying the target pool that was attached to the forwarding rule. - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :return: True if successful - :rtype: ``bool`` - """ - destroy = balancer.extra['forwarding_rule'].destroy() - if destroy: - tp_destroy = balancer.extra['targetpool'].destroy() - return tp_destroy - else: - return destroy - - def get_balancer(self, balancer_id): - """ - Return a :class:`LoadBalancer` object. - - :param balancer_id: Name of load balancer you wish to fetch. For GCE, - this is the name of the associated forwarding - rule. - :param balancer_id: ``str`` - - :rtype: :class:`LoadBalancer` - """ - fwr = self.gce.ex_get_forwarding_rule(balancer_id) - return self._forwarding_rule_to_loadbalancer(fwr) - - def balancer_attach_compute_node(self, balancer, node): - """ - Attach a compute node as a member to the load balancer. - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param node: Node to join to the balancer - :type node: :class:`Node` - - :return: Member after joining the balancer. - :rtype: :class:`Member` - """ - add_node = balancer.extra['targetpool'].add_node(node) - if add_node: - return self._node_to_member(node, balancer) - - def balancer_attach_member(self, balancer, member): - """ - Attach a member to balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param member: Member to join to the balancer - :type member: :class:`Member` - - :return: Member after joining the balancer. - :rtype: :class:`Member` - """ - node = member.extra.get('node') or self._get_node_from_ip(member.ip) - add_node = balancer.extra['targetpool'].add_node(node) - if add_node: - return self._node_to_member(node, balancer) - - def balancer_detach_member(self, balancer, member): - """ - Detach member from balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param member: Member which should be used - :type member: :class:`Member` - - :return: True if member detach was successful, otherwise False - :rtype: ``bool`` - """ - node = member.extra.get('node') or self._get_node_from_ip(member.ip) - remove_node = balancer.extra['targetpool'].remove_node(node) - return remove_node - - def balancer_list_members(self, balancer): - """ - Return list of members attached to balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :rtype: ``list`` of :class:`Member` - """ - return [self._node_to_member(n, balancer) for n in - balancer.extra['targetpool'].nodes] - - def ex_create_healthcheck(self, *args, **kwargs): - return self.gce.ex_create_healthcheck(*args, **kwargs) - - def ex_list_healthchecks(self): - return self.gce.ex_list_healthchecks() - - def ex_balancer_attach_healthcheck(self, balancer, healthcheck): - """ - Attach a healthcheck to balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param healthcheck: Healthcheck to add - :type healthcheck: :class:`GCEHealthCheck` - - :return: True if successful - :rtype: ``bool`` - """ - return balancer.extra['targetpool'].add_healthcheck(healthcheck) - - def ex_balancer_detach_healthcheck(self, balancer, healthcheck): - """ - Detach healtcheck from balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :param healthcheck: Healthcheck to remove - :type healthcheck: :class:`GCEHealthCheck` - - :return: True if successful - :rtype: ``bool`` - """ - return balancer.extra['targetpool'].remove_healthcheck(healthcheck) - - def ex_balancer_list_healthchecks(self, balancer): - """ - Return list of healthchecks attached to balancer - - :param balancer: LoadBalancer which should be used - :type balancer: :class:`LoadBalancer` - - :rtype: ``list`` of :class:`HealthChecks` - """ - return balancer.extra['healthchecks'] - - def _node_to_member(self, node, balancer): - """ - Return a Member object based on a Node. - - :param node: Node object - :type node: :class:`Node` - - :keyword balancer: The balancer the member is attached to. - :type balancer: :class:`LoadBalancer` - - :return: Member object - :rtype: :class:`Member` - """ - # A balancer can have a node as a member, even if the node doesn't - # exist. In this case, 'node' is simply a string to where the resource - # would be found if it was there. - if hasattr(node, 'name'): - member_id = node.name - member_ip = node.public_ips[0] - else: - member_id = node - member_ip = None - - extra = {'node': node} - return Member(id=member_id, ip=member_ip, port=balancer.port, - balancer=balancer, extra=extra) - - def _forwarding_rule_to_loadbalancer(self, forwarding_rule): - """ - Return a Load Balancer object based on a GCEForwardingRule object. - - :param forwarding_rule: ForwardingRule object - :type forwarding_rule: :class:`GCEForwardingRule` - - :return: LoadBalancer object - :rtype: :class:`LoadBalancer` - """ - extra = {} - extra['forwarding_rule'] = forwarding_rule - extra['targetpool'] = forwarding_rule.targetpool - extra['healthchecks'] = forwarding_rule.targetpool.healthchecks - - return LoadBalancer(id=forwarding_rule.id, - name=forwarding_rule.name, state=None, - ip=forwarding_rule.address, - port=forwarding_rule.extra['portRange'], - driver=self, extra=extra) diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/gogrid.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/gogrid.py deleted file mode 100644 index 201ad03125..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/gogrid.py +++ /dev/null @@ -1,239 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import time - -from libcloud.utils.py3 import httplib - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.misc import reverse_dict -from libcloud.common.types import LibcloudError -from libcloud.common.gogrid import GoGridConnection, GoGridResponse,\ - BaseGoGridDriver -from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm -from libcloud.loadbalancer.base import DEFAULT_ALGORITHM -from libcloud.loadbalancer.types import State, LibcloudLBImmutableError - - -class GoGridLBResponse(GoGridResponse): - def success(self): - if self.status == httplib.INTERNAL_SERVER_ERROR: - # Hack, but at least this error message is more useful than - # "unexpected server error" - body = json.loads(self.body) - if body['method'] == '/grid/loadbalancer/add' and \ - len(body['list']) >= 1 and \ - body['list'][0]['message'].find( - 'unexpected server error') != -1: - raise LibcloudError( - value='You mostly likely tried to add a member with an IP' - ' address not assigned to your account', driver=self) - return super(GoGridLBResponse, self).success() - - -class GoGridLBConnection(GoGridConnection): - """ - Connection class for the GoGrid load-balancer driver. - """ - responseCls = GoGridLBResponse - - -class GoGridLBDriver(BaseGoGridDriver, Driver): - connectionCls = GoGridLBConnection - api_name = 'gogrid_lb' - name = 'GoGrid LB' - website = 'http://www.gogrid.com/' - - LB_STATE_MAP = {'On': State.RUNNING, - 'Unknown': State.UNKNOWN} - _VALUE_TO_ALGORITHM_MAP = { - 'round robin': Algorithm.ROUND_ROBIN, - 'least connect': Algorithm.LEAST_CONNECTIONS - } - _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) - - def __init__(self, *args, **kwargs): - """ - @inherits: :class:`Driver.__init__` - """ - super(GoGridLBDriver, self).__init__(*args, **kwargs) - - def list_protocols(self): - # GoGrid only supports http - return ['http'] - - def list_balancers(self): - return self._to_balancers( - self.connection.request('/api/grid/loadbalancer/list').object) - - def ex_create_balancer_nowait(self, name, members, protocol='http', - port=80, algorithm=DEFAULT_ALGORITHM): - """ - @inherits: :class:`Driver.create_balancer` - """ - algorithm = self._algorithm_to_value(algorithm) - - params = {'name': name, - 'loadbalancer.type': algorithm, - 'virtualip.ip': self._get_first_ip(), - 'virtualip.port': port} - params.update(self._members_to_params(members)) - - resp = self.connection.request('/api/grid/loadbalancer/add', - method='GET', - params=params) - return self._to_balancers(resp.object)[0] - - def create_balancer(self, name, members, protocol='http', port=80, - algorithm=DEFAULT_ALGORITHM): - balancer = self.ex_create_balancer_nowait(name, members, protocol, - port, algorithm) - - timeout = 60 * 20 - waittime = 0 - interval = 2 * 15 - - if balancer.id is not None: - return balancer - else: - while waittime < timeout: - balancers = self.list_balancers() - - for i in balancers: - if i.name == balancer.name and i.id is not None: - return i - - waittime += interval - time.sleep(interval) - - raise Exception('Failed to get id') - - def destroy_balancer(self, balancer): - try: - resp = self.connection.request( - '/api/grid/loadbalancer/delete', method='POST', - params={'id': balancer.id}) - except Exception: - e = sys.exc_info()[1] - if "Update request for LoadBalancer" in str(e): - raise LibcloudLBImmutableError( - "Cannot delete immutable object", GoGridLBDriver) - else: - raise - - return resp.status == 200 - - def get_balancer(self, **kwargs): - params = {} - - try: - params['name'] = kwargs['ex_balancer_name'] - except KeyError: - balancer_id = kwargs['balancer_id'] - params['id'] = balancer_id - - resp = self.connection.request('/api/grid/loadbalancer/get', - params=params) - - return self._to_balancers(resp.object)[0] - - def balancer_attach_member(self, balancer, member): - members = self.balancer_list_members(balancer) - members.append(member) - - params = {"id": balancer.id} - - params.update(self._members_to_params(members)) - - resp = self._update_balancer(params) - return [m for m in - self._to_members(resp.object["list"][0]["realiplist"], - balancer) - if m.ip == member.ip][0] - - def balancer_detach_member(self, balancer, member): - members = self.balancer_list_members(balancer) - - remaining_members = [n for n in members if n.id != member.id] - - params = {"id": balancer.id} - params.update(self._members_to_params(remaining_members)) - - resp = self._update_balancer(params) - - return resp.status == 200 - - def balancer_list_members(self, balancer): - resp = self.connection.request('/api/grid/loadbalancer/get', - params={'id': balancer.id}) - return self._to_members(resp.object["list"][0]["realiplist"], balancer) - - def _update_balancer(self, params): - try: - return self.connection.request('/api/grid/loadbalancer/edit', - method='POST', - params=params) - except Exception: - e = sys.exc_info()[1] - if "Update already pending" in str(e): - raise LibcloudLBImmutableError( - "Balancer is immutable", GoGridLBDriver) - - raise LibcloudError(value='Exception: %s' % str(e), driver=self) - - def _members_to_params(self, members): - """ - Helper method to convert list of :class:`Member` objects - to GET params. - - """ - - params = {} - - i = 0 - for member in members: - params["realiplist.%s.ip" % i] = member.ip - params["realiplist.%s.port" % i] = member.port - i += 1 - - return params - - def _to_balancers(self, object): - return [self._to_balancer(el) for el in object["list"]] - - def _to_balancer(self, el): - lb = LoadBalancer(id=el.get("id"), - name=el["name"], - state=self.LB_STATE_MAP.get( - el["state"]["name"], State.UNKNOWN), - ip=el["virtualip"]["ip"]["ip"], - port=el["virtualip"]["port"], - driver=self.connection.driver) - return lb - - def _to_members(self, object, balancer=None): - return [self._to_member(el, balancer) for el in object] - - def _to_member(self, el, balancer=None): - member = Member(id=el["ip"]["id"], - ip=el["ip"]["ip"], - port=el["port"], - balancer=balancer) - return member diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/ninefold.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/ninefold.py deleted file mode 100644 index cb28f6c6cc..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/ninefold.py +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.loadbalancer.providers import Provider - -from libcloud.loadbalancer.drivers.cloudstack import CloudStackLBDriver - - -class NinefoldLBDriver(CloudStackLBDriver): - "Driver for load balancers on Ninefold's Compute platform." - - host = 'api.ninefold.com' - path = '/compute/v1.0/' - - type = Provider.NINEFOLD - name = 'Ninefold LB' - website = 'http://ninefold.com/' diff --git a/awx/lib/site-packages/libcloud/loadbalancer/drivers/rackspace.py b/awx/lib/site-packages/libcloud/loadbalancer/drivers/rackspace.py deleted file mode 100644 index bf2a13c617..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/drivers/rackspace.py +++ /dev/null @@ -1,1530 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from datetime import datetime - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import httplib -from libcloud.utils.misc import reverse_dict -from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm -from libcloud.loadbalancer.base import DEFAULT_ALGORITHM -from libcloud.compute.drivers.rackspace import RackspaceConnection -from libcloud.common.types import LibcloudError -from libcloud.common.base import JsonResponse, PollingConnection -from libcloud.loadbalancer.types import State, MemberCondition -from libcloud.common.openstack import OpenStackDriverMixin -from libcloud.common.rackspace import AUTH_URL - -ENDPOINT_ARGS_MAP = { - 'dfw': {'service_type': 'rax:load-balancer', - 'name': 'cloudLoadBalancers', - 'region': 'DFW'}, - 'ord': {'service_type': 'rax:load-balancer', - 'name': 'cloudLoadBalancers', - 'region': 'ORD'}, - 'iad': {'service_type': 'rax:load-balancer', - 'name': 'cloudLoadBalancers', - 'region': 'IAD'}, - 'lon': {'service_type': 'rax:load-balancer', - 'name': 'cloudLoadBalancers', - 'region': 'LON'}, - 'syd': {'service_type': 'rax:load-balancer', - 'name': 'cloudLoadBalancers', - 'region': 'SYD'}, - 'hkg': {'service_type': 'rax:load-balancer', - 'name': 'cloudLoadBalancers', - 'region': 'HKG'}, - -} - - -class RackspaceResponse(JsonResponse): - def parse_body(self): - if not self.body: - return None - return super(RackspaceResponse, self).parse_body() - - def success(self): - return 200 <= int(self.status) <= 299 - - -class RackspaceHealthMonitor(object): - """ - :param type: type of load balancer. currently CONNECT (connection - monitoring), HTTP, HTTPS (connection and HTTP - monitoring) are supported. - :type type: ``str`` - - :param delay: minimum seconds to wait before executing the health - monitor. (Must be between 1 and 3600) - :type delay: ``int`` - - :param timeout: maximum seconds to wait when establishing a - connection before timing out. (Must be between 1 - and 3600) - :type timeout: ``int`` - - :param attempts_before_deactivation: Number of monitor failures - before removing a node from - rotation. (Must be between 1 - and 10) - :type attempts_before_deactivation: ``int`` - """ - - def __init__(self, type, delay, timeout, attempts_before_deactivation): - self.type = type - self.delay = delay - self.timeout = timeout - self.attempts_before_deactivation = attempts_before_deactivation - - def __repr__(self): - return ('<RackspaceHealthMonitor: type=%s, delay=%d, timeout=%d, ' - 'attempts_before_deactivation=%d>' % - (self.type, self.delay, self.timeout, - self.attempts_before_deactivation)) - - def _to_dict(self): - return { - 'type': self.type, - 'delay': self.delay, - 'timeout': self.timeout, - 'attemptsBeforeDeactivation': self.attempts_before_deactivation - } - - -class RackspaceHTTPHealthMonitor(RackspaceHealthMonitor): - """ - A HTTP health monitor adds extra features to a Rackspace health monitor. - - :param path: the HTTP path to monitor. - :type path: ``str`` - - :param body_regex: Regular expression used to evaluate the body of - the HTTP response. - :type body_regex: ``str`` - - :param status_regex: Regular expression used to evaluate the HTTP - status code of the response. - :type status_regex: ``str`` - """ - - def __init__(self, type, delay, timeout, attempts_before_deactivation, - path, body_regex, status_regex): - super(RackspaceHTTPHealthMonitor, self).__init__( - type, delay, timeout, attempts_before_deactivation) - self.path = path - self.body_regex = body_regex - self.status_regex = status_regex - - def __repr__(self): - return ('<RackspaceHTTPHealthMonitor: type=%s, delay=%d, timeout=%d, ' - 'attempts_before_deactivation=%d, path=%s, body_regex=%s, ' - 'status_regex=%s>' % - (self.type, self.delay, self.timeout, - self.attempts_before_deactivation, self.path, self.body_regex, - self.status_regex)) - - def _to_dict(self): - super_dict = super(RackspaceHTTPHealthMonitor, self)._to_dict() - super_dict['path'] = self.path - super_dict['statusRegex'] = self.status_regex - - if self.body_regex: - super_dict['bodyRegex'] = self.body_regex - - return super_dict - - -class RackspaceConnectionThrottle(object): - """ - :param min_connections: Minimum number of connections per IP address - before applying throttling. - :type min_connections: ``int`` - - :param max_connections: Maximum number of connections per IP address. - (Must be between 0 and 100000, 0 allows an - unlimited number of connections.) - :type max_connections: ``int`` - - :param max_connection_rate: Maximum number of connections allowed - from a single IP address within the - given rate_interval_seconds. (Must be - between 0 and 100000, 0 allows an - unlimited number of connections.) - :type max_connection_rate: ``int`` - - :param rate_interval_seconds: Interval at which the - max_connection_rate is enforced. - (Must be between 1 and 3600.) - :type rate_interval_seconds: ``int`` - """ - - def __init__(self, min_connections, max_connections, - max_connection_rate, rate_interval_seconds): - self.min_connections = min_connections - self.max_connections = max_connections - self.max_connection_rate = max_connection_rate - self.rate_interval_seconds = rate_interval_seconds - - def __repr__(self): - return ('<RackspaceConnectionThrottle: min_connections=%d, ' - 'max_connections=%d, max_connection_rate=%d, ' - 'rate_interval_seconds=%d>' % - (self.min_connections, self.max_connections, - self.max_connection_rate, self.rate_interval_seconds)) - - def _to_dict(self): - return { - 'maxConnections': self.max_connections, - 'minConnections': self.min_connections, - 'maxConnectionRate': self.max_connection_rate, - 'rateInterval': self.rate_interval_seconds - } - - -class RackspaceAccessRuleType(object): - ALLOW = 0 - DENY = 1 - - _RULE_TYPE_STRING_MAP = { - ALLOW: 'ALLOW', - DENY: 'DENY' - } - - -class RackspaceAccessRule(object): - """ - An access rule allows or denies traffic to a Load Balancer based on the - incoming IPs. - - :param id: Unique identifier to refer to this rule by. - :type id: ``str`` - - :param rule_type: RackspaceAccessRuleType.ALLOW or - RackspaceAccessRuleType.DENY. - :type id: ``int`` - - :param address: IP address or cidr (can be IPv4 or IPv6). - :type address: ``str`` - """ - - def __init__(self, id=None, rule_type=None, address=None): - self.id = id - self.rule_type = rule_type - self.address = address - - def _to_dict(self): - type_string =\ - RackspaceAccessRuleType._RULE_TYPE_STRING_MAP[self.rule_type] - - as_dict = { - 'type': type_string, - 'address': self.address - } - - if self.id is not None: - as_dict['id'] = self.id - - return as_dict - - -class RackspaceConnection(RackspaceConnection, PollingConnection): - responseCls = RackspaceResponse - auth_url = AUTH_URL - poll_interval = 2 - timeout = 80 - cache_busting = True - - def request(self, action, params=None, data='', headers=None, - method='GET'): - if not headers: - headers = {} - if not params: - params = {} - - if method in ('POST', 'PUT'): - headers['Content-Type'] = 'application/json' - - return super(RackspaceConnection, self).request( - action=action, params=params, - data=data, method=method, headers=headers) - - def get_poll_request_kwargs(self, response, context, request_kwargs): - return {'action': request_kwargs['action'], - 'method': 'GET'} - - def has_completed(self, response): - state = response.object['loadBalancer']['status'] - if state == 'ERROR': - raise LibcloudError("Load balancer entered an ERROR state.", - driver=self.driver) - - return state == 'ACTIVE' - - def encode_data(self, data): - return data - - -class RackspaceLBDriver(Driver, OpenStackDriverMixin): - connectionCls = RackspaceConnection - api_name = 'rackspace_lb' - name = 'Rackspace LB' - website = 'http://www.rackspace.com/' - - LB_STATE_MAP = { - 'ACTIVE': State.RUNNING, - 'BUILD': State.PENDING, - 'ERROR': State.ERROR, - 'DELETED': State.DELETED, - 'PENDING_UPDATE': State.PENDING, - 'PENDING_DELETE': State.PENDING - } - - LB_MEMBER_CONDITION_MAP = { - 'ENABLED': MemberCondition.ENABLED, - 'DISABLED': MemberCondition.DISABLED, - 'DRAINING': MemberCondition.DRAINING - } - - CONDITION_LB_MEMBER_MAP = reverse_dict(LB_MEMBER_CONDITION_MAP) - - _VALUE_TO_ALGORITHM_MAP = { - 'RANDOM': Algorithm.RANDOM, - 'ROUND_ROBIN': Algorithm.ROUND_ROBIN, - 'LEAST_CONNECTIONS': Algorithm.LEAST_CONNECTIONS, - 'WEIGHTED_ROUND_ROBIN': Algorithm.WEIGHTED_ROUND_ROBIN, - 'WEIGHTED_LEAST_CONNECTIONS': Algorithm.WEIGHTED_LEAST_CONNECTIONS - } - - _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='ord', **kwargs): - ex_force_region = kwargs.pop('ex_force_region', None) - if ex_force_region: - # For backward compatibility - region = ex_force_region - OpenStackDriverMixin.__init__(self, **kwargs) - super(RackspaceLBDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, region=region) - - def _ex_connection_class_kwargs(self): - endpoint_args = ENDPOINT_ARGS_MAP[self.region] - kwargs = self.openstack_connection_kwargs() - kwargs['get_endpoint_args'] = endpoint_args - return kwargs - - def list_protocols(self): - return self._to_protocols( - self.connection.request('/loadbalancers/protocols').object) - - def ex_list_protocols_with_default_ports(self): - """ - List protocols with default ports. - - :rtype: ``list`` of ``tuple`` - :return: A list of protocols with default ports included. - """ - return self._to_protocols_with_default_ports( - self.connection.request('/loadbalancers/protocols').object) - - def list_balancers(self, ex_member_address=None): - """ - @inherits: :class:`Driver.list_balancers` - - :param ex_member_address: Optional IP address of the attachment member. - If provided, only the load balancers which - have this member attached will be returned. - :type ex_member_address: ``str`` - """ - params = {} - - if ex_member_address: - params['nodeaddress'] = ex_member_address - - return self._to_balancers( - self.connection.request('/loadbalancers', params=params).object) - - def create_balancer(self, name, members, protocol='http', - port=80, algorithm=DEFAULT_ALGORITHM): - return self.ex_create_balancer(name, members, protocol, port, - algorithm) - - def ex_create_balancer(self, name, members, protocol='http', - port=80, algorithm=DEFAULT_ALGORITHM, vip='PUBLIC'): - """ - Creates a new load balancer instance - - :param name: Name of the new load balancer (required) - :type name: ``str`` - - :param members: ``list`` of:class:`Member`s to attach to balancer - :type members: ``list`` of :class:`Member` - - :param protocol: Loadbalancer protocol, defaults to http. - :type protocol: ``str`` - - :param port: Port the load balancer should listen on, defaults to 80 - :type port: ``str`` - - :param algorithm: Load balancing algorithm, defaults to - LBAlgorithm.ROUND_ROBIN - :type algorithm: :class:`Algorithm` - - :param vip: Virtual ip type of PUBLIC, SERVICENET, or ID of a virtual - ip - :type vip: ``str`` - - :rtype: :class:`LoadBalancer` - """ - balancer_attrs = self._kwargs_to_mutable_attrs( - name=name, - protocol=protocol, - port=port, - algorithm=algorithm, - vip=vip) - - balancer_attrs.update({ - 'nodes': [self._member_attributes(member) for member in members], - }) - # balancer_attrs['nodes'] = ['fu'] - balancer_object = {"loadBalancer": balancer_attrs} - - resp = self.connection.request('/loadbalancers', - method='POST', - data=json.dumps(balancer_object)) - return self._to_balancer(resp.object['loadBalancer']) - - def _member_attributes(self, member): - member_attributes = {'address': member.ip, - 'port': member.port} - - member_attributes.update(self._kwargs_to_mutable_member_attrs( - **member.extra)) - - # If the condition is not specified on the member, then it should be - # set to ENABLED by default - if 'condition' not in member_attributes: - member_attributes['condition'] =\ - self.CONDITION_LB_MEMBER_MAP[MemberCondition.ENABLED] - - return member_attributes - - def destroy_balancer(self, balancer): - uri = '/loadbalancers/%s' % (balancer.id) - resp = self.connection.request(uri, method='DELETE') - - return resp.status == httplib.ACCEPTED - - def ex_destroy_balancers(self, balancers): - """ - Destroys a list of Balancers (the API supports up to 10). - - :param balancers: A list of Balancers to destroy. - :type balancers: ``list`` of :class:`LoadBalancer` - - :return: Returns whether the destroy request was accepted. - :rtype: ``bool`` - """ - ids = [('id', balancer.id) for balancer in balancers] - resp = self.connection.request('/loadbalancers', - method='DELETE', - params=ids) - - return resp.status == httplib.ACCEPTED - - def get_balancer(self, balancer_id): - uri = '/loadbalancers/%s' % (balancer_id) - resp = self.connection.request(uri) - - return self._to_balancer(resp.object["loadBalancer"]) - - def balancer_attach_member(self, balancer, member): - member_object = {"nodes": [self._member_attributes(member)]} - - uri = '/loadbalancers/%s/nodes' % (balancer.id) - resp = self.connection.request(uri, method='POST', - data=json.dumps(member_object)) - return self._to_members(resp.object, balancer)[0] - - def ex_balancer_attach_members(self, balancer, members): - """ - Attaches a list of members to a load balancer. - - :param balancer: The Balancer to which members will be attached. - :type balancer: :class:`LoadBalancer` - - :param members: A list of Members to attach. - :type members: ``list`` of :class:`Member` - - :rtype: ``list`` of :class:`Member` - """ - member_objects = {"nodes": [self._member_attributes(member) for member - in members]} - - uri = '/loadbalancers/%s/nodes' % (balancer.id) - resp = self.connection.request(uri, method='POST', - data=json.dumps(member_objects)) - return self._to_members(resp.object, balancer) - - def balancer_detach_member(self, balancer, member): - # Loadbalancer always needs to have at least 1 member. - # Last member cannot be detached. You can only disable it or destroy - # the balancer. - uri = '/loadbalancers/%s/nodes/%s' % (balancer.id, member.id) - resp = self.connection.request(uri, method='DELETE') - - return resp.status == httplib.ACCEPTED - - def ex_balancer_detach_members(self, balancer, members): - """ - Detaches a list of members from a balancer (the API supports up to 10). - This method blocks until the detach request has been processed and the - balancer is in a RUNNING state again. - - :param balancer: The Balancer to detach members from. - :type balancer: :class:`LoadBalancer` - - :param members: A list of Members to detach. - :type members: ``list`` of :class:`Member` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - accepted = self.ex_balancer_detach_members_no_poll(balancer, members) - - if not accepted: - msg = 'Detach members request was not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_balancer_detach_members_no_poll(self, balancer, members): - """ - Detaches a list of members from a balancer (the API supports up to 10). - This method returns immediately. - - :param balancer: The Balancer to detach members from. - :type balancer: :class:`LoadBalancer` - - :param members: A list of Members to detach. - :type members: ``list`` of :class:`Member` - - :return: Returns whether the detach request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/nodes' % (balancer.id) - ids = [('id', member.id) for member in members] - resp = self.connection.request(uri, method='DELETE', params=ids) - - return resp.status == httplib.ACCEPTED - - def balancer_list_members(self, balancer): - uri = '/loadbalancers/%s/nodes' % (balancer.id) - data = self.connection.request(uri).object - return self._to_members(data, balancer) - - def update_balancer(self, balancer, **kwargs): - attrs = self._kwargs_to_mutable_attrs(**kwargs) - resp = self.connection.async_request( - action='/loadbalancers/%s' % balancer.id, - method='PUT', - data=json.dumps(attrs)) - return self._to_balancer(resp.object["loadBalancer"]) - - def ex_update_balancer_no_poll(self, balancer, **kwargs): - """ - Update balancer no poll. - - @inherits: :class:`Driver.update_balancer` - """ - attrs = self._kwargs_to_mutable_attrs(**kwargs) - resp = self.connection.request( - action='/loadbalancers/%s' % balancer.id, - method='PUT', - data=json.dumps(attrs)) - return resp.status == httplib.ACCEPTED - - def ex_balancer_update_member(self, balancer, member, **kwargs): - """ - Updates a Member's extra attributes for a Balancer. The attributes can - include 'weight' or 'condition'. This method blocks until the update - request has been processed and the balancer is in a RUNNING state - again. - - :param balancer: Balancer to update the member on. - :type balancer: :class:`LoadBalancer` - - :param member: Member which should be used - :type member: :class:`Member` - - :keyword **kwargs: New attributes. Should contain either 'weight' - or 'condition'. 'condition' can be set to 'ENABLED', 'DISABLED'. - or 'DRAINING'. 'weight' can be set to a positive integer between - 1 and 100, with a higher weight indicating that the node will receive - more traffic (assuming the Balancer is using a weighted algorithm). - :type **kwargs: ``dict`` - - :return: Updated Member. - :rtype: :class:`Member` - """ - accepted = self.ex_balancer_update_member_no_poll( - balancer, member, **kwargs) - - if not accepted: - msg = 'Update member attributes was not accepted' - raise LibcloudError(msg, driver=self) - - balancer = self._get_updated_balancer(balancer) - members = balancer.extra['members'] - - updated_members = [m for m in members if m.id == member.id] - - if not updated_members: - raise LibcloudError('Could not find updated member') - - return updated_members[0] - - def ex_balancer_update_member_no_poll(self, balancer, member, **kwargs): - """ - Updates a Member's extra attributes for a Balancer. The attribute can - include 'weight' or 'condition'. This method returns immediately. - - :param balancer: Balancer to update the member on. - :type balancer: :class:`LoadBalancer` - - :param member: Member which should be used - :type member: :class:`Member` - - :keyword **kwargs: New attributes. Should contain either 'weight' - or 'condition'. 'condition' can be set to 'ENABLED', 'DISABLED'. - or 'DRAINING'. 'weight' can be set to a positive integer between - 1 and 100, with a higher weight indicating that the node will receive - more traffic (assuming the Balancer is using a weighted algorithm). - :type **kwargs: ``dict`` - - :return: Returns whether the update request was accepted. - :rtype: ``bool`` - """ - resp = self.connection.request( - action='/loadbalancers/%s/nodes/%s' % (balancer.id, member.id), - method='PUT', - data=json.dumps(self._kwargs_to_mutable_member_attrs(**kwargs)) - ) - - return resp.status == httplib.ACCEPTED - - def ex_list_algorithm_names(self): - """ - Lists algorithms supported by the API. Returned as strings because - this list may change in the future. - - :rtype: ``list`` of ``str`` - """ - response = self.connection.request('/loadbalancers/algorithms') - return [a["name"].upper() for a in response.object["algorithms"]] - - def ex_get_balancer_error_page(self, balancer): - """ - List error page configured for the specified load balancer. - - :param balancer: Balancer which should be used - :type balancer: :class:`LoadBalancer` - - :rtype: ``str`` - """ - uri = '/loadbalancers/%s/errorpage' % (balancer.id) - resp = self.connection.request(uri) - - return resp.object["errorpage"]["content"] - - def ex_balancer_access_list(self, balancer): - """ - List the access list. - - :param balancer: Balancer which should be used - :type balancer: :class:`LoadBalancer` - - :rtype: ``list`` of :class:`RackspaceAccessRule` - """ - uri = '/loadbalancers/%s/accesslist' % (balancer.id) - resp = self.connection.request(uri) - - return [self._to_access_rule(el) for el in resp.object["accessList"]] - - def _get_updated_balancer(self, balancer): - """ - Updating a balancer's attributes puts a balancer into - 'PENDING_UPDATE' status. Wait until the balancer is - back in 'ACTIVE' status and then return the individual - balancer details call. - """ - resp = self.connection.async_request( - action='/loadbalancers/%s' % balancer.id, - method='GET') - - return self._to_balancer(resp.object['loadBalancer']) - - def ex_update_balancer_health_monitor(self, balancer, health_monitor): - """ - Sets a Balancer's health monitor. This method blocks until the update - request has been processed and the balancer is in a RUNNING state - again. - - :param balancer: Balancer to update. - :type balancer: :class:`LoadBalancer` - - :param health_monitor: Health Monitor for the balancer. - :type health_monitor: :class:`RackspaceHealthMonitor` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - accepted = self.ex_update_balancer_health_monitor_no_poll( - balancer, health_monitor) - if not accepted: - msg = 'Update health monitor request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_update_balancer_health_monitor_no_poll(self, balancer, - health_monitor): - """ - Sets a Balancer's health monitor. This method returns immediately. - - :param balancer: Balancer to update health monitor on. - :type balancer: :class:`LoadBalancer` - - :param health_monitor: Health Monitor for the balancer. - :type health_monitor: :class:`RackspaceHealthMonitor` - - :return: Returns whether the update request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/healthmonitor' % (balancer.id) - - resp = self.connection.request( - uri, method='PUT', data=json.dumps(health_monitor._to_dict())) - - return resp.status == httplib.ACCEPTED - - def ex_disable_balancer_health_monitor(self, balancer): - """ - Disables a Balancer's health monitor. This method blocks until the - disable request has been processed and the balancer is in a RUNNING - state again. - - :param balancer: Balancer to disable health monitor on. - :type balancer: :class:`LoadBalancer` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - if not self.ex_disable_balancer_health_monitor_no_poll(balancer): - msg = 'Disable health monitor request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_disable_balancer_health_monitor_no_poll(self, balancer): - """ - Disables a Balancer's health monitor. This method returns - immediately. - - :param balancer: Balancer to disable health monitor on. - :type balancer: :class:`LoadBalancer` - - :return: Returns whether the disable request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/healthmonitor' % (balancer.id) - - resp = self.connection.request(uri, - method='DELETE') - - return resp.status == httplib.ACCEPTED - - def ex_update_balancer_connection_throttle(self, balancer, - connection_throttle): - """ - Updates a Balancer's connection throttle. This method blocks until - the update request has been processed and the balancer is in a - RUNNING state again. - - :param balancer: Balancer to update connection throttle on. - :type balancer: :class:`LoadBalancer` - - :param connection_throttle: Connection Throttle for the balancer. - :type connection_throttle: :class:`RackspaceConnectionThrottle` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - accepted = self.ex_update_balancer_connection_throttle_no_poll( - balancer, connection_throttle) - - if not accepted: - msg = 'Update connection throttle request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_update_balancer_connection_throttle_no_poll(self, balancer, - connection_throttle): - """ - Sets a Balancer's connection throttle. This method returns - immediately. - - :param balancer: Balancer to update connection throttle on. - :type balancer: :class:`LoadBalancer` - - :param connection_throttle: Connection Throttle for the balancer. - :type connection_throttle: :class:`RackspaceConnectionThrottle` - - :return: Returns whether the update request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/connectionthrottle' % (balancer.id) - resp = self.connection.request( - uri, method='PUT', - data=json.dumps(connection_throttle._to_dict())) - - return resp.status == httplib.ACCEPTED - - def ex_disable_balancer_connection_throttle(self, balancer): - """ - Disables a Balancer's connection throttle. This method blocks until - the disable request has been processed and the balancer is in a RUNNING - state again. - - :param balancer: Balancer to disable connection throttle on. - :type balancer: :class:`LoadBalancer` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - if not self.ex_disable_balancer_connection_throttle_no_poll(balancer): - msg = 'Disable connection throttle request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_disable_balancer_connection_throttle_no_poll(self, balancer): - """ - Disables a Balancer's connection throttle. This method returns - immediately. - - :param balancer: Balancer to disable connection throttle on. - :type balancer: :class:`LoadBalancer` - - :return: Returns whether the disable request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/connectionthrottle' % (balancer.id) - resp = self.connection.request(uri, method='DELETE') - - return resp.status == httplib.ACCEPTED - - def ex_enable_balancer_connection_logging(self, balancer): - """ - Enables connection logging for a Balancer. This method blocks until - the enable request has been processed and the balancer is in a RUNNING - state again. - - :param balancer: Balancer to enable connection logging on. - :type balancer: :class:`LoadBalancer` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - if not self.ex_enable_balancer_connection_logging_no_poll(balancer): - msg = 'Enable connection logging request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_enable_balancer_connection_logging_no_poll(self, balancer): - """ - Enables connection logging for a Balancer. This method returns - immediately. - - :param balancer: Balancer to enable connection logging on. - :type balancer: :class:`LoadBalancer` - - :return: Returns whether the enable request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/connectionlogging' % (balancer.id) - - resp = self.connection.request( - uri, method='PUT', - data=json.dumps({'connectionLogging': {'enabled': True}}) - ) - - return resp.status == httplib.ACCEPTED - - def ex_disable_balancer_connection_logging(self, balancer): - """ - Disables connection logging for a Balancer. This method blocks until - the enable request has been processed and the balancer is in a RUNNING - state again. - - :param balancer: Balancer to disable connection logging on. - :type balancer: :class:`LoadBalancer` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - if not self.ex_disable_balancer_connection_logging_no_poll(balancer): - msg = 'Disable connection logging request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_disable_balancer_connection_logging_no_poll(self, balancer): - """ - Disables connection logging for a Balancer. This method returns - immediately. - - :param balancer: Balancer to disable connection logging on. - :type balancer: :class:`LoadBalancer` - - :return: Returns whether the disable request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/connectionlogging' % (balancer.id) - resp = self.connection.request( - uri, method='PUT', - data=json.dumps({'connectionLogging': {'enabled': False}}) - ) - - return resp.status == httplib.ACCEPTED - - def ex_enable_balancer_session_persistence(self, balancer): - """ - Enables session persistence for a Balancer by setting the persistence - type to 'HTTP_COOKIE'. This method blocks until the enable request - has been processed and the balancer is in a RUNNING state again. - - :param balancer: Balancer to enable session persistence on. - :type balancer: :class:`LoadBalancer` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - if not self.ex_enable_balancer_session_persistence_no_poll(balancer): - msg = 'Enable session persistence request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_enable_balancer_session_persistence_no_poll(self, balancer): - """ - Enables session persistence for a Balancer by setting the persistence - type to 'HTTP_COOKIE'. This method returns immediately. - - :param balancer: Balancer to enable session persistence on. - :type balancer: :class:`LoadBalancer` - - :return: Returns whether the enable request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/sessionpersistence' % (balancer.id) - resp = self.connection.request( - uri, method='PUT', - data=json.dumps( - {'sessionPersistence': {'persistenceType': 'HTTP_COOKIE'}}) - ) - - return resp.status == httplib.ACCEPTED - - def ex_disable_balancer_session_persistence(self, balancer): - """ - Disables session persistence for a Balancer. This method blocks until - the disable request has been processed and the balancer is in a RUNNING - state again. - - :param balancer: Balancer to disable session persistence on. - :type balancer: :class:`LoadBalancer` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - if not self.ex_disable_balancer_session_persistence_no_poll(balancer): - msg = 'Disable session persistence request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_disable_balancer_session_persistence_no_poll(self, balancer): - """ - Disables session persistence for a Balancer. This method returns - immediately. - - :param balancer: Balancer to disable session persistence for. - :type balancer: :class:`LoadBalancer` - - :return: Returns whether the disable request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/sessionpersistence' % (balancer.id) - resp = self.connection.request(uri, method='DELETE') - - return resp.status == httplib.ACCEPTED - - def ex_update_balancer_error_page(self, balancer, page_content): - """ - Updates a Balancer's custom error page. This method blocks until - the update request has been processed and the balancer is in a - RUNNING state again. - - :param balancer: Balancer to update the custom error page for. - :type balancer: :class:`LoadBalancer` - - :param page_content: HTML content for the custom error page. - :type page_content: ``str`` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - accepted = self.ex_update_balancer_error_page_no_poll(balancer, - page_content) - if not accepted: - msg = 'Update error page request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_update_balancer_error_page_no_poll(self, balancer, page_content): - """ - Updates a Balancer's custom error page. This method returns - immediately. - - :param balancer: Balancer to update the custom error page for. - :type balancer: :class:`LoadBalancer` - - :param page_content: HTML content for the custom error page. - :type page_content: ``str`` - - :return: Returns whether the update request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/errorpage' % (balancer.id) - resp = self.connection.request( - uri, method='PUT', - data=json.dumps({'errorpage': {'content': page_content}}) - ) - - return resp.status == httplib.ACCEPTED - - def ex_disable_balancer_custom_error_page(self, balancer): - """ - Disables a Balancer's custom error page, returning its error page to - the Rackspace-provided default. This method blocks until the disable - request has been processed and the balancer is in a RUNNING state - again. - - :param balancer: Balancer to disable the custom error page for. - :type balancer: :class:`LoadBalancer` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - if not self.ex_disable_balancer_custom_error_page_no_poll(balancer): - msg = 'Disable custom error page request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_disable_balancer_custom_error_page_no_poll(self, balancer): - """ - Disables a Balancer's custom error page, returning its error page to - the Rackspace-provided default. This method returns immediately. - - :param balancer: Balancer to disable the custom error page for. - :type balancer: :class:`LoadBalancer` - - :return: Returns whether the disable request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/errorpage' % (balancer.id) - resp = self.connection.request(uri, method='DELETE') - - # Load Balancer API currently returns 200 OK on custom error page - # delete. - return resp.status == httplib.OK or resp.status == httplib.ACCEPTED - - def ex_create_balancer_access_rule(self, balancer, rule): - """ - Adds an access rule to a Balancer's access list. This method blocks - until the update request has been processed and the balancer is in a - RUNNING state again. - - :param balancer: Balancer to create the access rule for. - :type balancer: :class:`LoadBalancer` - - :param rule: Access Rule to add to the balancer. - :type rule: :class:`RackspaceAccessRule` - - :return: The created access rule. - :rtype: :class:`RackspaceAccessRule` - """ - accepted = self.ex_create_balancer_access_rule_no_poll(balancer, rule) - if not accepted: - msg = 'Create access rule not accepted' - raise LibcloudError(msg, driver=self) - - balancer = self._get_updated_balancer(balancer) - access_list = balancer.extra['accessList'] - - created_rule = self._find_matching_rule(rule, access_list) - - if not created_rule: - raise LibcloudError('Could not find created rule') - - return created_rule - - def ex_create_balancer_access_rule_no_poll(self, balancer, rule): - """ - Adds an access rule to a Balancer's access list. This method returns - immediately. - - :param balancer: Balancer to create the access rule for. - :type balancer: :class:`LoadBalancer` - - :param rule: Access Rule to add to the balancer. - :type rule: :class:`RackspaceAccessRule` - - :return: Returns whether the create request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/accesslist' % (balancer.id) - resp = self.connection.request( - uri, method='POST', - data=json.dumps({'networkItem': rule._to_dict()}) - ) - - return resp.status == httplib.ACCEPTED - - def ex_create_balancer_access_rules(self, balancer, rules): - """ - Adds a list of access rules to a Balancer's access list. This method - blocks until the update request has been processed and the balancer is - in a RUNNING state again. - - :param balancer: Balancer to create the access rule for. - :type balancer: :class:`LoadBalancer` - - :param rules: List of :class:`RackspaceAccessRule` to add to the - balancer. - :type rules: ``list`` of :class:`RackspaceAccessRule` - - :return: The created access rules. - :rtype: :class:`RackspaceAccessRule` - """ - accepted = self.ex_create_balancer_access_rules_no_poll(balancer, - rules) - if not accepted: - msg = 'Create access rules not accepted' - raise LibcloudError(msg, driver=self) - - balancer = self._get_updated_balancer(balancer) - access_list = balancer.extra['accessList'] - - created_rules = [] - for r in rules: - matched_rule = self._find_matching_rule(r, access_list) - if matched_rule: - created_rules.append(matched_rule) - - if len(created_rules) != len(rules): - raise LibcloudError('Could not find all created rules') - - return created_rules - - def _find_matching_rule(self, rule_to_find, access_list): - """ - LB API does not return the ID for the newly created rules, so we have - to search the list to find the rule with a matching rule type and - address to return an object with the right identifier.it. The API - enforces rule type and address uniqueness. - """ - for r in access_list: - if rule_to_find.rule_type == r.rule_type and\ - rule_to_find.address == r.address: - return r - - return None - - def ex_create_balancer_access_rules_no_poll(self, balancer, rules): - """ - Adds a list of access rules to a Balancer's access list. This method - returns immediately. - - :param balancer: Balancer to create the access rule for. - :type balancer: :class:`LoadBalancer` - - :param rules: List of :class:`RackspaceAccessRule` to add to - the balancer. - :type rules: ``list`` of :class:`RackspaceAccessRule` - - :return: Returns whether the create request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/accesslist' % (balancer.id) - resp = self.connection.request( - uri, method='POST', - data=json.dumps({'accessList': - [rule._to_dict() for rule in rules]}) - ) - - return resp.status == httplib.ACCEPTED - - def ex_destroy_balancer_access_rule(self, balancer, rule): - """ - Removes an access rule from a Balancer's access list. This method - blocks until the update request has been processed and the balancer - is in a RUNNING state again. - - :param balancer: Balancer to remove the access rule from. - :type balancer: :class:`LoadBalancer` - - :param rule: Access Rule to remove from the balancer. - :type rule: :class:`RackspaceAccessRule` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - accepted = self.ex_destroy_balancer_access_rule_no_poll(balancer, rule) - if not accepted: - msg = 'Delete access rule not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_destroy_balancer_access_rule_no_poll(self, balancer, rule): - """ - Removes an access rule from a Balancer's access list. This method - returns immediately. - - :param balancer: Balancer to remove the access rule from. - :type balancer: :class:`LoadBalancer` - - :param rule: Access Rule to remove from the balancer. - :type rule: :class:`RackspaceAccessRule` - - :return: Returns whether the destroy request was accepted. - :rtype: ``bool`` - """ - uri = '/loadbalancers/%s/accesslist/%s' % (balancer.id, rule.id) - resp = self.connection.request(uri, method='DELETE') - - return resp.status == httplib.ACCEPTED - - def ex_destroy_balancer_access_rules(self, balancer, rules): - """ - Removes a list of access rules from a Balancer's access list. This - method blocks until the update request has been processed and the - balancer is in a RUNNING state again. - - :param balancer: Balancer to remove the access rules from. - :type balancer: :class:`LoadBalancer` - - :param rules: List of :class:`RackspaceAccessRule` objects to remove - from the balancer. - :type rules: ``list`` of :class:`RackspaceAccessRule` - - :return: Updated Balancer. - :rtype: :class:`LoadBalancer` - """ - accepted = self.ex_destroy_balancer_access_rules_no_poll( - balancer, rules) - - if not accepted: - msg = 'Destroy access rules request not accepted' - raise LibcloudError(msg, driver=self) - - return self._get_updated_balancer(balancer) - - def ex_destroy_balancer_access_rules_no_poll(self, balancer, rules): - """ - Removes a list of access rules from a Balancer's access list. This - method returns immediately. - - :param balancer: Balancer to remove the access rules from. - :type balancer: :class:`LoadBalancer` - - :param rules: List of :class:`RackspaceAccessRule` objects to remove - from the balancer. - :type rules: ``list`` of :class:`RackspaceAccessRule` - - :return: Returns whether the destroy request was accepted. - :rtype: ``bool`` - """ - ids = [('id', rule.id) for rule in rules] - uri = '/loadbalancers/%s/accesslist' % balancer.id - - resp = self.connection.request(uri, - method='DELETE', - params=ids) - - return resp.status == httplib.ACCEPTED - - def ex_list_current_usage(self, balancer): - """ - Return current load balancer usage report. - - :param balancer: Balancer to remove the access rules from. - :type balancer: :class:`LoadBalancer` - - :return: Raw load balancer usage object. - :rtype: ``dict`` - """ - uri = '/loadbalancers/%s/usage/current' % (balancer.id) - resp = self.connection.request(uri, method='GET') - - return resp.object - - def _to_protocols(self, object): - protocols = [] - for item in object["protocols"]: - protocols.append(item['name'].lower()) - return protocols - - def _to_protocols_with_default_ports(self, object): - protocols = [] - for item in object["protocols"]: - name = item['name'].lower() - port = int(item['port']) - protocols.append((name, port)) - - return protocols - - def _to_balancers(self, object): - return [self._to_balancer(el) for el in object["loadBalancers"]] - - def _to_balancer(self, el): - ip = None - port = None - sourceAddresses = {} - - if 'port' in el: - port = el["port"] - - if 'sourceAddresses' in el: - sourceAddresses = el['sourceAddresses'] - - extra = { - "ipv6PublicSource": sourceAddresses.get("ipv6Public"), - "ipv4PublicSource": sourceAddresses.get("ipv4Public"), - "ipv4PrivateSource": sourceAddresses.get("ipv4Servicenet"), - } - - if 'virtualIps' in el: - ip = el['virtualIps'][0]['address'] - extra['virtualIps'] = el['virtualIps'] - - if 'protocol' in el: - extra['protocol'] = el['protocol'] - - if 'algorithm' in el and \ - el["algorithm"] in self._VALUE_TO_ALGORITHM_MAP: - extra["algorithm"] = self._value_to_algorithm(el["algorithm"]) - - if 'healthMonitor' in el: - health_monitor = self._to_health_monitor(el) - if health_monitor: - extra["healthMonitor"] = health_monitor - - if 'connectionThrottle' in el: - extra["connectionThrottle"] = self._to_connection_throttle(el) - - if 'sessionPersistence' in el: - persistence = el["sessionPersistence"] - extra["sessionPersistenceType"] =\ - persistence.get("persistenceType") - - if 'connectionLogging' in el: - logging = el["connectionLogging"] - extra["connectionLoggingEnabled"] = logging.get("enabled") - - if 'nodes' in el: - extra['members'] = self._to_members(el) - - if 'created' in el: - extra['created'] = self._iso_to_datetime(el['created']['time']) - - if 'updated' in el: - extra['updated'] = self._iso_to_datetime(el['updated']['time']) - - if 'accessList' in el: - extra['accessList'] = [self._to_access_rule(rule) - for rule in el['accessList']] - - return LoadBalancer(id=el["id"], - name=el["name"], - state=self.LB_STATE_MAP.get( - el["status"], State.UNKNOWN), - ip=ip, - port=port, - driver=self.connection.driver, - extra=extra) - - def _to_members(self, object, balancer=None): - return [self._to_member(el, balancer) for el in object["nodes"]] - - def _to_member(self, el, balancer=None): - extra = {} - if 'weight' in el: - extra['weight'] = el["weight"] - - if 'condition' in el and\ - el['condition'] in self.LB_MEMBER_CONDITION_MAP: - extra['condition'] =\ - self.LB_MEMBER_CONDITION_MAP.get(el["condition"]) - - if 'status' in el: - extra['status'] = el["status"] - - lbmember = Member(id=el["id"], - ip=el["address"], - port=el["port"], - balancer=balancer, - extra=extra) - return lbmember - - def _protocol_to_value(self, protocol): - non_standard_protocols = {'imapv2': 'IMAPv2', 'imapv3': 'IMAPv3', - 'imapv4': 'IMAPv4'} - protocol_name = protocol.lower() - - if protocol_name in non_standard_protocols: - protocol_value = non_standard_protocols[protocol_name] - else: - protocol_value = protocol.upper() - - return protocol_value - - def _kwargs_to_mutable_attrs(self, **attrs): - update_attrs = {} - if "name" in attrs: - update_attrs['name'] = attrs['name'] - - if "algorithm" in attrs: - algorithm_value = self._algorithm_to_value(attrs['algorithm']) - update_attrs['algorithm'] = algorithm_value - - if "protocol" in attrs: - update_attrs['protocol'] =\ - self._protocol_to_value(attrs['protocol']) - - if "port" in attrs: - update_attrs['port'] = int(attrs['port']) - - if "vip" in attrs: - if attrs['vip'] == 'PUBLIC' or attrs['vip'] == 'SERVICENET': - update_attrs['virtualIps'] = [{'type': attrs['vip']}] - else: - update_attrs['virtualIps'] = [{'id': attrs['vip']}] - - return update_attrs - - def _kwargs_to_mutable_member_attrs(self, **attrs): - update_attrs = {} - if 'condition' in attrs: - update_attrs['condition'] =\ - self.CONDITION_LB_MEMBER_MAP.get(attrs['condition']) - - if 'weight' in attrs: - update_attrs['weight'] = attrs['weight'] - - return update_attrs - - def _to_health_monitor(self, el): - health_monitor_data = el["healthMonitor"] - - type = health_monitor_data.get("type") - delay = health_monitor_data.get("delay") - timeout = health_monitor_data.get("timeout") - attempts_before_deactivation =\ - health_monitor_data.get("attemptsBeforeDeactivation") - - if type == "CONNECT": - return RackspaceHealthMonitor( - type=type, delay=delay, timeout=timeout, - attempts_before_deactivation=attempts_before_deactivation) - - if type == "HTTP" or type == "HTTPS": - return RackspaceHTTPHealthMonitor( - type=type, delay=delay, timeout=timeout, - attempts_before_deactivation=attempts_before_deactivation, - path=health_monitor_data.get("path"), - status_regex=health_monitor_data.get("statusRegex"), - body_regex=health_monitor_data.get("bodyRegex", '')) - - return None - - def _to_connection_throttle(self, el): - connection_throttle_data = el["connectionThrottle"] - - min_connections = connection_throttle_data.get("minConnections") - max_connections = connection_throttle_data.get("maxConnections") - max_connection_rate = connection_throttle_data.get("maxConnectionRate") - rate_interval = connection_throttle_data.get("rateInterval") - - return RackspaceConnectionThrottle( - min_connections=min_connections, - max_connections=max_connections, - max_connection_rate=max_connection_rate, - rate_interval_seconds=rate_interval) - - def _to_access_rule(self, el): - return RackspaceAccessRule( - id=el.get("id"), - rule_type=self._to_access_rule_type(el.get("type")), - address=el.get("address")) - - def _to_access_rule_type(self, type): - if type == "ALLOW": - return RackspaceAccessRuleType.ALLOW - elif type == "DENY": - return RackspaceAccessRuleType.DENY - - def _iso_to_datetime(self, isodate): - date_formats = ('%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%dT%H:%M:%S%z') - date = None - - for date_format in date_formats: - try: - date = datetime.strptime(isodate, date_format) - except ValueError: - pass - - if date: - break - - return date - - -class RackspaceUKLBDriver(RackspaceLBDriver): - def __init__(self, *args, **kwargs): - kwargs['region'] = 'lon' - super(RackspaceUKLBDriver, self).__init__(*args, **kwargs) diff --git a/awx/lib/site-packages/libcloud/loadbalancer/providers.py b/awx/lib/site-packages/libcloud/loadbalancer/providers.py deleted file mode 100644 index f11e450500..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/providers.py +++ /dev/null @@ -1,55 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.utils.misc import get_driver as get_provider_driver -from libcloud.utils.misc import set_driver as set_provider_driver -from libcloud.loadbalancer.types import Provider - -__all__ = [ - "Provider", - "DRIVERS", - "get_driver", -] - -DRIVERS = { - Provider.RACKSPACE: - ('libcloud.loadbalancer.drivers.rackspace', 'RackspaceLBDriver'), - Provider.GOGRID: - ('libcloud.loadbalancer.drivers.gogrid', 'GoGridLBDriver'), - Provider.NINEFOLD: - ('libcloud.loadbalancer.drivers.ninefold', 'NinefoldLBDriver'), - Provider.BRIGHTBOX: - ('libcloud.loadbalancer.drivers.brightbox', 'BrightboxLBDriver'), - Provider.ELB: - ('libcloud.loadbalancer.drivers.elb', 'ElasticLBDriver'), - Provider.CLOUDSTACK: - ('libcloud.loadbalancer.drivers.cloudstack', 'CloudStackLBDriver'), - Provider.GCE: - ('libcloud.loadbalancer.drivers.gce', 'GCELBDriver'), - - # Deprecated - Provider.RACKSPACE_US: - ('libcloud.loadbalancer.drivers.rackspace', 'RackspaceLBDriver'), - Provider.RACKSPACE_UK: - ('libcloud.loadbalancer.drivers.rackspace', 'RackspaceUKLBDriver'), -} - - -def get_driver(provider): - return get_provider_driver(DRIVERS, provider) - - -def set_driver(provider, module, klass): - return set_provider_driver(DRIVERS, provider, module, klass) diff --git a/awx/lib/site-packages/libcloud/loadbalancer/types.py b/awx/lib/site-packages/libcloud/loadbalancer/types.py deleted file mode 100644 index 6be53e5430..0000000000 --- a/awx/lib/site-packages/libcloud/loadbalancer/types.py +++ /dev/null @@ -1,70 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - "Provider", - "State", - "LibcloudLBError", - "LibcloudLBImmutableError", -] - -from libcloud.common.types import LibcloudError - - -class LibcloudLBError(LibcloudError): - pass - - -class LibcloudLBImmutableError(LibcloudLBError): - pass - - -class Provider(object): - RACKSPACE = 'rackspace' - GOGRID = 'gogrid' - NINEFOLD = 'ninefold' - BRIGHTBOX = 'brightbox' - ELB = 'elb' - CLOUDSTACK = 'cloudstack' - GCE = 'gce' - - # Deprecated - RACKSPACE_US = 'rackspace_us' - RACKSPACE_UK = 'rackspace_uk' - - -class State(object): - """ - Standard states for a loadbalancer - - :cvar RUNNING: loadbalancer is running and ready to use - :cvar UNKNOWN: loabalancer state is unknown - """ - - RUNNING = 0 - PENDING = 1 - UNKNOWN = 2 - ERROR = 3 - DELETED = 4 - - -class MemberCondition(object): - """ - Each member of a load balancer can have an associated condition - which determines its role within the load balancer. - """ - ENABLED = 0 - DISABLED = 1 - DRAINING = 2 diff --git a/awx/lib/site-packages/libcloud/pricing.py b/awx/lib/site-packages/libcloud/pricing.py deleted file mode 100644 index ebe99a8aa5..0000000000 --- a/awx/lib/site-packages/libcloud/pricing.py +++ /dev/null @@ -1,216 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import with_statement - -""" -A class which handles loading the pricing files. -""" - -import os.path -from os.path import join as pjoin - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.connection import get_response_object - -__all__ = [ - 'get_pricing', - 'get_size_price', - 'set_pricing', - 'clear_pricing_data', - 'download_pricing_file' -] - -# Default URL to the pricing file -DEFAULT_FILE_URL = 'https://git-wip-us.apache.org/repos/asf?p=libcloud.git;a=blob_plain;f=libcloud/data/pricing.json' # NOQA - -CURRENT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) -DEFAULT_PRICING_FILE_PATH = pjoin(CURRENT_DIRECTORY, 'data/pricing.json') -CUSTOM_PRICING_FILE_PATH = os.path.expanduser('~/.libcloud/pricing.json') - -# Pricing data cache -PRICING_DATA = { - 'compute': {}, - 'storage': {} -} - -VALID_PRICING_DRIVER_TYPES = ['compute', 'storage'] - - -def get_pricing_file_path(file_path=None): - if os.path.exists(CUSTOM_PRICING_FILE_PATH) and \ - os.path.isfile(CUSTOM_PRICING_FILE_PATH): - # Custom pricing file is available, use it - return CUSTOM_PRICING_FILE_PATH - - return DEFAULT_PRICING_FILE_PATH - - -def get_pricing(driver_type, driver_name, pricing_file_path=None): - """ - Return pricing for the provided driver. - - :type driver_type: ``str`` - :param driver_type: Driver type ('compute' or 'storage') - - :type driver_name: ``str` - :param driver_name: Driver name - - :type pricing_file_path: ``str`` - :param pricing_file_path: Custom path to a price file. If not provided - it uses a default path. - - :rtype: ``dict`` - :return: Dictionary with pricing where a key name is size ID and - the value is a price. - """ - if driver_type not in VALID_PRICING_DRIVER_TYPES: - raise AttributeError('Invalid driver type: %s', driver_type) - - if driver_name in PRICING_DATA[driver_type]: - return PRICING_DATA[driver_type][driver_name] - - if not pricing_file_path: - pricing_file_path = get_pricing_file_path(file_path=pricing_file_path) - - with open(pricing_file_path) as fp: - content = fp.read() - - pricing_data = json.loads(content) - size_pricing = pricing_data[driver_type][driver_name] - - for driver_type in VALID_PRICING_DRIVER_TYPES: - pricing = pricing_data.get(driver_type, None) - if pricing: - PRICING_DATA[driver_type] = pricing - - return size_pricing - - -def set_pricing(driver_type, driver_name, pricing): - """ - Populate the driver pricing dictionary. - - :type driver_type: ``str`` - :param driver_type: Driver type ('compute' or 'storage') - - :type driver_name: ``str`` - :param driver_name: Driver name - - :type pricing: ``dict`` - :param pricing: Dictionary where a key is a size ID and a value is a price. - """ - - PRICING_DATA[driver_type][driver_name] = pricing - - -def get_size_price(driver_type, driver_name, size_id): - """ - Return price for the provided size. - - :type driver_type: ``str`` - :param driver_type: Driver type ('compute' or 'storage') - - :type driver_name: ``str`` - :param driver_name: Driver name - - :type size_id: ``str`` or ``int`` - :param size_id: Unique size ID (can be an integer or a string - depends on - the driver) - - :rtype: ``float`` - :return: Size price. - """ - pricing = get_pricing(driver_type=driver_type, driver_name=driver_name) - price = float(pricing[size_id]) - return price - - -def invalidate_pricing_cache(): - """ - Invalidate pricing cache for all the drivers. - """ - PRICING_DATA['compute'] = {} - PRICING_DATA['storage'] = {} - - -def clear_pricing_data(): - """ - Invalidate pricing cache for all the drivers. - - Note: This method does the same thing as invalidate_pricing_cache and is - here for backward compatibility reasons. - """ - invalidate_pricing_cache() - - -def invalidate_module_pricing_cache(driver_type, driver_name): - """ - Invalidate the cache for the specified driver. - - :type driver_type: ``str`` - :param driver_type: Driver type ('compute' or 'storage') - - :type driver_name: ``str`` - :param driver_name: Driver name - """ - if driver_name in PRICING_DATA[driver_type]: - del PRICING_DATA[driver_type][driver_name] - - -def download_pricing_file(file_url=DEFAULT_FILE_URL, - file_path=CUSTOM_PRICING_FILE_PATH): - """ - Download pricing file from the file_url and save it to file_path. - - :type file_url: ``str`` - :param file_url: URL pointing to the pricing file. - - :type file_path: ``str`` - :param file_path: Path where a download pricing file will be saved. - """ - dir_name = os.path.dirname(file_path) - - if not os.path.exists(dir_name): - # Verify a valid path is provided - msg = ('Can\'t write to %s, directory %s, doesn\'t exist' % - (file_path, dir_name)) - raise ValueError(msg) - - if os.path.exists(file_path) and os.path.isdir(file_path): - msg = ('Can\'t write to %s file path because it\'s a' - ' directory' % (file_path)) - raise ValueError(msg) - - response = get_response_object(file_url) - body = response.body - - # Verify pricing file is valid - try: - data = json.loads(body) - except json.decoder.JSONDecodeError: - msg = 'Provided URL doesn\'t contain valid pricing data' - raise Exception(msg) - - if not data.get('updated', None): - msg = 'Provided URL doesn\'t contain valid pricing data' - raise Exception(msg) - - # No need to stream it since file is small - with open(file_path, 'w') as file_handle: - file_handle.write(body) diff --git a/awx/lib/site-packages/libcloud/security.py b/awx/lib/site-packages/libcloud/security.py deleted file mode 100644 index 81d7a51f67..0000000000 --- a/awx/lib/site-packages/libcloud/security.py +++ /dev/null @@ -1,80 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Security (SSL) Settings - -Usage: - import libcloud.security - libcloud.security.VERIFY_SSL_CERT = True - - # Optional. - libcloud.security.CA_CERTS_PATH.append('/path/to/cacert.txt') -""" - -import os - -VERIFY_SSL_CERT = True - -# File containing one or more PEM-encoded CA certificates -# concatenated together. -CA_CERTS_PATH = [ - # centos/fedora: openssl - '/etc/pki/tls/certs/ca-bundle.crt', - - # debian/ubuntu/arch/gentoo: ca-certificates - '/etc/ssl/certs/ca-certificates.crt', - - # freebsd: ca_root_nss - '/usr/local/share/certs/ca-root-nss.crt', - - # macports: curl-ca-bundle - '/opt/local/share/curl/curl-ca-bundle.crt', - - # homebrew: openssl - '/usr/local/etc/openssl/cert.pem', - - # homebrew: curl-ca-bundle (backward compatibility) - '/usr/local/opt/curl-ca-bundle/share/ca-bundle.crt', -] - -# Allow user to explicitly specify which CA bundle to use, using an environment -# variable -environment_cert_file = os.getenv('SSL_CERT_FILE', None) -if environment_cert_file is not None: - # Make sure the file exists - if not os.path.exists(environment_cert_file): - raise ValueError('Certificate file %s doesn\'t exist' % - (environment_cert_file)) - - if not os.path.isfile(environment_cert_file): - raise ValueError('Certificate file can\'t be a directory') - - # If a provided file exists we ignore other common paths because we - # don't want to fall-back to a potentially less restrictive bundle - CA_CERTS_PATH = [environment_cert_file] - -CA_CERTS_UNAVAILABLE_ERROR_MSG = ( - 'No CA Certificates were found in CA_CERTS_PATH. For information on ' - 'how to get required certificate files, please visit ' - 'https://libcloud.readthedocs.org/en/latest/other/' - 'ssl-certificate-validation.html' -) - -VERIFY_SSL_DISABLED_MSG = ( - 'SSL certificate verification is disabled, this can pose a ' - 'security risk. For more information how to enable the SSL ' - 'certificate verification, please visit the libcloud ' - 'documentation.' -) diff --git a/awx/lib/site-packages/libcloud/storage/__init__.py b/awx/lib/site-packages/libcloud/storage/__init__.py deleted file mode 100644 index f73ddf07a7..0000000000 --- a/awx/lib/site-packages/libcloud/storage/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Module for working with Storage -""" diff --git a/awx/lib/site-packages/libcloud/storage/base.py b/awx/lib/site-packages/libcloud/storage/base.py deleted file mode 100644 index f12b906409..0000000000 --- a/awx/lib/site-packages/libcloud/storage/base.py +++ /dev/null @@ -1,825 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Provides base classes for working with storage -""" - -# Backward compatibility for Python 2.5 -from __future__ import with_statement - -import os.path # pylint: disable-msg=W0404 -import hashlib -from os.path import join as pjoin - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import next -from libcloud.utils.py3 import b - -import libcloud.utils.files -from libcloud.common.types import LibcloudError -from libcloud.common.base import ConnectionUserAndKey, BaseDriver -from libcloud.storage.types import ObjectDoesNotExistError - -__all__ = [ - 'Object', - 'Container', - 'StorageDriver', - - 'CHUNK_SIZE', - 'DEFAULT_CONTENT_TYPE' -] - -CHUNK_SIZE = 8096 - -# Default Content-Type which is sent when uploading an object if one is not -# supplied and can't be detected when using non-strict mode. -DEFAULT_CONTENT_TYPE = 'application/octet-stream' - - -class Object(object): - """ - Represents an object (BLOB). - """ - - def __init__(self, name, size, hash, extra, meta_data, container, - driver): - """ - :param name: Object name (must be unique per container). - :type name: ``str`` - - :param size: Object size in bytes. - :type size: ``int`` - - :param hash: Object hash. - :type hash: ``str`` - - :param container: Object container. - :type container: :class:`Container` - - :param extra: Extra attributes. - :type extra: ``dict`` - - :param meta_data: Optional object meta data. - :type meta_data: ``dict`` - - :param driver: StorageDriver instance. - :type driver: :class:`StorageDriver` - """ - - self.name = name - self.size = size - self.hash = hash - self.container = container - self.extra = extra or {} - self.meta_data = meta_data or {} - self.driver = driver - - def get_cdn_url(self): - return self.driver.get_object_cdn_url(obj=self) - - def enable_cdn(self, **kwargs): - return self.driver.enable_object_cdn(obj=self, **kwargs) - - def download(self, destination_path, overwrite_existing=False, - delete_on_failure=True): - return self.driver.download_object(self, destination_path, - overwrite_existing, - delete_on_failure) - - def as_stream(self, chunk_size=None): - return self.driver.download_object_as_stream(self, chunk_size) - - def delete(self): - return self.driver.delete_object(self) - - def __repr__(self): - return ('<Object: name=%s, size=%s, hash=%s, provider=%s ...>' % - (self.name, self.size, self.hash, self.driver.name)) - - -class Container(object): - """ - Represents a container (bucket) which can hold multiple objects. - """ - - def __init__(self, name, extra, driver): - """ - :param name: Container name (must be unique). - :type name: ``str`` - - :param extra: Extra attributes. - :type extra: ``dict`` - - :param driver: StorageDriver instance. - :type driver: :class:`StorageDriver` - """ - - self.name = name - self.extra = extra or {} - self.driver = driver - - def iterate_objects(self): - return self.driver.iterate_container_objects(container=self) - - def list_objects(self): - return self.driver.list_container_objects(container=self) - - def get_cdn_url(self): - return self.driver.get_container_cdn_url(container=self) - - def enable_cdn(self, **kwargs): - return self.driver.enable_container_cdn(container=self, **kwargs) - - def get_object(self, object_name): - return self.driver.get_object(container_name=self.name, - object_name=object_name) - - def upload_object(self, file_path, object_name, extra=None, **kwargs): - return self.driver.upload_object( - file_path, self, object_name, extra=extra, **kwargs) - - def upload_object_via_stream(self, iterator, object_name, extra=None, - **kwargs): - return self.driver.upload_object_via_stream( - iterator, self, object_name, extra=extra, **kwargs) - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - return self.driver.download_object( - obj, destination_path, overwrite_existing=overwrite_existing, - delete_on_failure=delete_on_failure) - - def download_object_as_stream(self, obj, chunk_size=None): - return self.driver.download_object_as_stream(obj, chunk_size) - - def delete_object(self, obj): - return self.driver.delete_object(obj) - - def delete(self): - return self.driver.delete_container(self) - - def __repr__(self): - return ('<Container: name=%s, provider=%s>' - % (self.name, self.driver.name)) - - -class StorageDriver(BaseDriver): - """ - A base StorageDriver to derive from. - """ - - connectionCls = ConnectionUserAndKey - name = None - hash_type = 'md5' - supports_chunked_encoding = False - - # When strict mode is used, exception will be thrown if no content type is - # provided and none can be detected when uploading an object - strict_mode = False - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - **kwargs): - super(StorageDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, **kwargs) - - def iterate_containers(self): - """ - Return a generator of containers for the given account - - :return: A generator of Container instances. - :rtype: ``generator`` of :class:`Container` - """ - raise NotImplementedError( - 'iterate_containers not implemented for this driver') - - def list_containers(self): - """ - Return a list of containers. - - :return: A list of Container instances. - :rtype: ``list`` of :class:`Container` - """ - return list(self.iterate_containers()) - - def iterate_container_objects(self, container): - """ - Return a generator of objects for the given container. - - :param container: Container instance - :type container: :class:`Container` - - :return: A generator of Object instances. - :rtype: ``generator`` of :class:`Object` - """ - raise NotImplementedError( - 'iterate_container_objects not implemented for this driver') - - def list_container_objects(self, container): - """ - Return a list of objects for the given container. - - :param container: Container instance. - :type container: :class:`Container` - - :return: A list of Object instances. - :rtype: ``list`` of :class:`Object` - """ - return list(self.iterate_container_objects(container)) - - def get_container(self, container_name): - """ - Return a container instance. - - :param container_name: Container name. - :type container_name: ``str`` - - :return: :class:`Container` instance. - :rtype: :class:`Container` - """ - raise NotImplementedError( - 'get_object not implemented for this driver') - - def get_container_cdn_url(self, container): - """ - Return a container CDN URL. - - :param container: Container instance - :type container: :class:`Container` - - :return: A CDN URL for this container. - :rtype: ``str`` - """ - raise NotImplementedError( - 'get_container_cdn_url not implemented for this driver') - - def get_object(self, container_name, object_name): - """ - Return an object instance. - - :param container_name: Container name. - :type container_name: ``str`` - - :param object_name: Object name. - :type object_name: ``str`` - - :return: :class:`Object` instance. - :rtype: :class:`Object` - """ - raise NotImplementedError( - 'get_object not implemented for this driver') - - def get_object_cdn_url(self, obj): - """ - Return a object CDN URL. - - :param obj: Object instance - :type obj: :class:`Object` - - :return: A CDN URL for this object. - :rtype: ``str`` - """ - raise NotImplementedError( - 'get_object_cdn_url not implemented for this driver') - - def enable_container_cdn(self, container): - """ - Enable container CDN. - - :param container: Container instance - :type container: :class:`Container` - - :rtype: ``bool`` - """ - raise NotImplementedError( - 'enable_container_cdn not implemented for this driver') - - def enable_object_cdn(self, obj): - """ - Enable object CDN. - - :param obj: Object instance - :type obj: :class:`Object` - - :rtype: ``bool`` - """ - raise NotImplementedError( - 'enable_object_cdn not implemented for this driver') - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - """ - Download an object to the specified destination path. - - :param obj: Object instance. - :type obj: :class:`Object` - - :param destination_path: Full path to a file or a directory where the - incoming file will be saved. - :type destination_path: ``str`` - - :param overwrite_existing: True to overwrite an existing file, - defaults to False. - :type overwrite_existing: ``bool`` - - :param delete_on_failure: True to delete a partially downloaded file if - the download was not successful (hash - mismatch / file size). - :type delete_on_failure: ``bool`` - - :return: True if an object has been successfully downloaded, False - otherwise. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'download_object not implemented for this driver') - - def download_object_as_stream(self, obj, chunk_size=None): - """ - Return a generator which yields object data. - - :param obj: Object instance - :type obj: :class:`Object` - - :param chunk_size: Optional chunk size (in bytes). - :type chunk_size: ``int`` - """ - raise NotImplementedError( - 'download_object_as_stream not implemented for this driver') - - def upload_object(self, file_path, container, object_name, extra=None, - verify_hash=True): - """ - Upload an object currently located on a disk. - - :param file_path: Path to the object on disk. - :type file_path: ``str`` - - :param container: Destination container. - :type container: :class:`Container` - - :param object_name: Object name. - :type object_name: ``str`` - - :param verify_hash: Verify hash - :type verify_hash: ``bool`` - - :param extra: Extra attributes (driver specific). (optional) - :type extra: ``dict`` - - :rtype: :class:`Object` - """ - raise NotImplementedError( - 'upload_object not implemented for this driver') - - def upload_object_via_stream(self, iterator, container, - object_name, - extra=None): - """ - Upload an object using an iterator. - - If a provider supports it, chunked transfer encoding is used and you - don't need to know in advance the amount of data to be uploaded. - - Otherwise if a provider doesn't support it, iterator will be exhausted - so a total size for data to be uploaded can be determined. - - Note: Exhausting the iterator means that the whole data must be - buffered in memory which might result in memory exhausting when - uploading a very large object. - - If a file is located on a disk you are advised to use upload_object - function which uses fs.stat function to determine the file size and it - doesn't need to buffer whole object in the memory. - - :type iterator: :class:`object` - :param iterator: An object which implements the iterator interface. - - :type container: :class:`Container` - :param container: Destination container. - - :type object_name: ``str`` - :param object_name: Object name. - - :type extra: ``dict`` - :param extra: (optional) Extra attributes (driver specific). Note: - This dictionary must contain a 'content_type' key which represents - a content type of the stored object. - - :rtype: ``object`` - """ - raise NotImplementedError( - 'upload_object_via_stream not implemented for this driver') - - def delete_object(self, obj): - """ - Delete an object. - - :type obj: :class:`Object` - :param obj: Object instance. - - :return: ``bool`` True on success. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'delete_object not implemented for this driver') - - def create_container(self, container_name): - """ - Create a new container. - - :type container_name: ``str`` - :param container_name: Container name. - - :return: Container instance on success. - :rtype: :class:`Container` - """ - raise NotImplementedError( - 'create_container not implemented for this driver') - - def delete_container(self, container): - """ - Delete a container. - - :type container: :class:`Container` - :param container: Container instance - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - raise NotImplementedError( - 'delete_container not implemented for this driver') - - def _get_object(self, obj, callback, callback_kwargs, response, - success_status_code=None): - """ - Call passed callback and start transfer of the object' - - :type obj: :class:`Object` - :param obj: Object instance. - - :type callback: :class:`function` - :param callback: Function which is called with the passed - callback_kwargs - - :type callback_kwargs: ``dict`` - :param callback_kwargs: Keyword arguments which are passed to the - callback. - - :typed response: :class:`Response` - :param response: Response instance. - - :type success_status_code: ``int`` - :param success_status_code: Status code which represents a successful - transfer (defaults to httplib.OK) - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - success_status_code = success_status_code or httplib.OK - - if response.status == success_status_code: - return callback(**callback_kwargs) - elif response.status == httplib.NOT_FOUND: - raise ObjectDoesNotExistError(object_name=obj.name, - value='', driver=self) - - raise LibcloudError(value='Unexpected status code: %s' % - (response.status), - driver=self) - - def _save_object(self, response, obj, destination_path, - overwrite_existing=False, delete_on_failure=True, - chunk_size=None): - """ - Save object to the provided path. - - :type response: :class:`RawResponse` - :param response: RawResponse instance. - - :type obj: :class:`Object` - :param obj: Object instance. - - :type destination_path: ``str`` - :param destination_path: Destination directory. - - :type delete_on_failure: ``bool`` - :param delete_on_failure: True to delete partially downloaded object if - the download fails. - - :type overwrite_existing: ``bool`` - :param overwrite_existing: True to overwrite a local path if it already - exists. - - :type chunk_size: ``int`` - :param chunk_size: Optional chunk size - (defaults to ``libcloud.storage.base.CHUNK_SIZE``, 8kb) - - :return: ``True`` on success, ``False`` otherwise. - :rtype: ``bool`` - """ - - chunk_size = chunk_size or CHUNK_SIZE - - base_name = os.path.basename(destination_path) - - if not base_name and not os.path.exists(destination_path): - raise LibcloudError( - value='Path %s does not exist' % (destination_path), - driver=self) - - if not base_name: - file_path = pjoin(destination_path, obj.name) - else: - file_path = destination_path - - if os.path.exists(file_path) and not overwrite_existing: - raise LibcloudError( - value='File %s already exists, but ' % (file_path) + - 'overwrite_existing=False', - driver=self) - - stream = libcloud.utils.files.read_in_chunks(response, chunk_size) - - try: - data_read = next(stream) - except StopIteration: - # Empty response? - return False - - bytes_transferred = 0 - - with open(file_path, 'wb') as file_handle: - while len(data_read) > 0: - file_handle.write(b(data_read)) - bytes_transferred += len(data_read) - - try: - data_read = next(stream) - except StopIteration: - data_read = '' - - if int(obj.size) != int(bytes_transferred): - # Transfer failed, support retry? - if delete_on_failure: - try: - os.unlink(file_path) - except Exception: - pass - - return False - - return True - - def _upload_object(self, object_name, content_type, upload_func, - upload_func_kwargs, request_path, request_method='PUT', - headers=None, file_path=None, iterator=None): - """ - Helper function for setting common request headers and calling the - passed in callback which uploads an object. - """ - headers = headers or {} - - if file_path and not os.path.exists(file_path): - raise OSError('File %s does not exist' % (file_path)) - - if iterator is not None and not hasattr(iterator, 'next') and not \ - hasattr(iterator, '__next__'): - raise AttributeError('iterator object must implement next() ' + - 'method.') - - if not content_type: - if file_path: - name = file_path - else: - name = object_name - content_type, _ = libcloud.utils.files.guess_file_mime_type(name) - - if not content_type: - if self.strict_mode: - raise AttributeError('File content-type could not be ' - 'guessed and no content_type value ' - 'is provided') - else: - # Fallback to a content-type - content_type = DEFAULT_CONTENT_TYPE - - file_size = None - - if iterator: - if self.supports_chunked_encoding: - headers['Transfer-Encoding'] = 'chunked' - upload_func_kwargs['chunked'] = True - else: - # Chunked transfer encoding is not supported. Need to buffer - # all the data in memory so we can determine file size. - iterator = libcloud.utils.files.read_in_chunks( - iterator=iterator) - data = libcloud.utils.files.exhaust_iterator(iterator=iterator) - - file_size = len(data) - upload_func_kwargs['data'] = data - else: - file_size = os.path.getsize(file_path) - upload_func_kwargs['chunked'] = False - - if file_size is not None and 'Content-Length' not in headers: - headers['Content-Length'] = file_size - - headers['Content-Type'] = content_type - response = self.connection.request(request_path, - method=request_method, data=None, - headers=headers, raw=True) - - upload_func_kwargs['response'] = response - success, data_hash, bytes_transferred = upload_func( - **upload_func_kwargs) - - if not success: - raise LibcloudError( - value='Object upload failed, Perhaps a timeout?', driver=self) - - result_dict = {'response': response, 'data_hash': data_hash, - 'bytes_transferred': bytes_transferred} - return result_dict - - def _upload_data(self, response, data, calculate_hash=True): - """ - Upload data stored in a string. - - :type response: :class:`RawResponse` - :param response: RawResponse object. - - :type data: ``str`` - :param data: Data to upload. - - :type calculate_hash: ``bool`` - :param calculate_hash: True to calculate hash of the transferred data. - (defauls to True). - - :rtype: ``tuple`` - :return: First item is a boolean indicator of success, second - one is the uploaded data MD5 hash and the third one - is the number of transferred bytes. - """ - bytes_transferred = 0 - data_hash = None - - if calculate_hash: - data_hash = self._get_hash_function() - data_hash.update(b(data)) - - try: - response.connection.connection.send(b(data)) - except Exception: - # TODO: let this exception propagate - # Timeout, etc. - return False, None, bytes_transferred - - bytes_transferred = len(data) - - if calculate_hash: - data_hash = data_hash.hexdigest() - - return True, data_hash, bytes_transferred - - def _stream_data(self, response, iterator, chunked=False, - calculate_hash=True, chunk_size=None, data=None): - """ - Stream a data over an http connection. - - :type response: :class:`RawResponse` - :param response: RawResponse object. - - :type iterator: :class:`object` - :param response: An object which implements an iterator interface - or a File like object with read method. - - :type chunked: ``bool`` - :param chunked: True if the chunked transfer encoding should be used - (defauls to False). - - :type calculate_hash: ``bool`` - :param calculate_hash: True to calculate hash of the transferred data. - (defauls to True). - - :type chunk_size: ``int`` - :param chunk_size: Optional chunk size (defaults to ``CHUNK_SIZE``) - - :rtype: ``tuple`` - :return: First item is a boolean indicator of success, second - one is the uploaded data MD5 hash and the third one - is the number of transferred bytes. - """ - - chunk_size = chunk_size or CHUNK_SIZE - - data_hash = None - if calculate_hash: - data_hash = self._get_hash_function() - - generator = libcloud.utils.files.read_in_chunks(iterator, chunk_size) - - bytes_transferred = 0 - try: - chunk = next(generator) - except StopIteration: - # Special case when StopIteration is thrown on the first iteration - # create a 0-byte long object - chunk = '' - if chunked: - response.connection.connection.send(b('%X\r\n' % - (len(chunk)))) - response.connection.connection.send(chunk) - response.connection.connection.send(b('\r\n')) - response.connection.connection.send(b('0\r\n\r\n')) - else: - response.connection.connection.send(chunk) - return True, data_hash.hexdigest(), bytes_transferred - - while len(chunk) > 0: - try: - if chunked: - response.connection.connection.send(b('%X\r\n' % - (len(chunk)))) - response.connection.connection.send(b(chunk)) - response.connection.connection.send(b('\r\n')) - else: - response.connection.connection.send(b(chunk)) - except Exception: - # TODO: let this exception propagate - # Timeout, etc. - return False, None, bytes_transferred - - bytes_transferred += len(chunk) - if calculate_hash: - data_hash.update(b(chunk)) - - try: - chunk = next(generator) - except StopIteration: - chunk = '' - - if chunked: - response.connection.connection.send(b('0\r\n\r\n')) - - if calculate_hash: - data_hash = data_hash.hexdigest() - - return True, data_hash, bytes_transferred - - def _upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - """ - Upload a file to the server. - - :type response: :class:`RawResponse` - :param response: RawResponse object. - - :type file_path: ``str`` - :param file_path: Path to a local file. - - :type iterator: :class:`object` - :param response: An object which implements an iterator interface (File - object, etc.) - - :rtype: ``tuple`` - :return: First item is a boolean indicator of success, second - one is the uploaded data MD5 hash and the third one - is the number of transferred bytes. - """ - with open(file_path, 'rb') as file_handle: - success, data_hash, bytes_transferred = ( - self._stream_data( - response=response, - iterator=iter(file_handle), - chunked=chunked, - calculate_hash=calculate_hash)) - - return success, data_hash, bytes_transferred - - def _get_hash_function(self): - """ - Return instantiated hash function for the hash type supported by - the provider. - """ - try: - func = getattr(hashlib, self.hash_type)() - except AttributeError: - raise RuntimeError('Invalid or unsupported hash type: %s' % - (self.hash_type)) - - return func diff --git a/awx/lib/site-packages/libcloud/storage/drivers/__init__.py b/awx/lib/site-packages/libcloud/storage/drivers/__init__.py deleted file mode 100644 index fe8b04f388..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Drivers for working with different providers -""" - -__all__ = [ - 'dummy', - 'cloudfiles' -] diff --git a/awx/lib/site-packages/libcloud/storage/drivers/atmos.py b/awx/lib/site-packages/libcloud/storage/drivers/atmos.py deleted file mode 100644 index a1e12cc8e5..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/atmos.py +++ /dev/null @@ -1,472 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import base64 -import hashlib -import hmac -import time - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import b -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import next -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import urlencode -from libcloud.utils.py3 import urlquote -from libcloud.utils.py3 import urlunquote - -if PY3: - from io import FileIO as file - -from libcloud.utils.files import read_in_chunks, guess_file_mime_type -from libcloud.common.base import ConnectionUserAndKey, XmlResponse -from libcloud.common.types import LibcloudError - -from libcloud.storage.base import Object, Container, StorageDriver, CHUNK_SIZE -from libcloud.storage.types import ContainerAlreadyExistsError, \ - ContainerDoesNotExistError, ContainerIsNotEmptyError, \ - ObjectDoesNotExistError - - -def collapse(s): - return ' '.join([x for x in s.split(' ') if x]) - - -class AtmosError(LibcloudError): - def __init__(self, code, message, driver=None): - super(AtmosError, self).__init__(value=message, driver=driver) - self.code = code - - -class AtmosResponse(XmlResponse): - def success(self): - return self.status in (httplib.OK, httplib.CREATED, httplib.NO_CONTENT, - httplib.PARTIAL_CONTENT) - - def parse_error(self): - tree = self.parse_body() - - if tree is None: - return None - - code = int(tree.find('Code').text) - message = tree.find('Message').text - raise AtmosError(code=code, message=message, - driver=self.connection.driver) - - -class AtmosConnection(ConnectionUserAndKey): - responseCls = AtmosResponse - - def add_default_headers(self, headers): - headers['x-emc-uid'] = self.user_id - headers['Date'] = time.strftime('%a, %d %b %Y %H:%M:%S GMT', - time.gmtime()) - headers['x-emc-date'] = headers['Date'] - - if 'Content-Type' not in headers: - headers['Content-Type'] = 'application/octet-stream' - if 'Accept' not in headers: - headers['Accept'] = '*/*' - - return headers - - def pre_connect_hook(self, params, headers): - headers['x-emc-signature'] = self._calculate_signature(params, headers) - - return params, headers - - def _calculate_signature(self, params, headers): - pathstring = urlunquote(self.action) - if pathstring.startswith(self.driver.path): - pathstring = pathstring[len(self.driver.path):] - if params: - if type(params) is dict: - params = list(params.items()) - pathstring += '?' + urlencode(params) - pathstring = pathstring.lower() - - xhdrs = [(k, v) for k, v in list(headers.items()) if - k.startswith('x-emc-')] - xhdrs.sort(key=lambda x: x[0]) - - signature = [ - self.method, - headers.get('Content-Type', ''), - headers.get('Range', ''), - headers.get('Date', ''), - pathstring, - ] - signature.extend([k + ':' + collapse(v) for k, v in xhdrs]) - signature = '\n'.join(signature) - key = base64.b64decode(self.key) - signature = hmac.new(b(key), b(signature), hashlib.sha1).digest() - return base64.b64encode(b(signature)).decode('utf-8') - - -class AtmosDriver(StorageDriver): - connectionCls = AtmosConnection - - host = None - path = None - api_name = 'atmos' - supports_chunked_encoding = True - website = 'http://atmosonline.com/' - name = 'atmos' - - DEFAULT_CDN_TTL = 60 * 60 * 24 * 7 # 1 week - - def __init__(self, key, secret=None, secure=True, host=None, port=None): - host = host or self.host - super(AtmosDriver, self).__init__(key, secret, secure, host, port) - - def iterate_containers(self): - result = self.connection.request(self._namespace_path('')) - entries = self._list_objects(result.object, object_type='directory') - for entry in entries: - extra = { - 'object_id': entry['id'] - } - yield Container(entry['name'], extra, self) - - def get_container(self, container_name): - path = self._namespace_path(container_name) + '/?metadata/system' - try: - result = self.connection.request(path) - except AtmosError: - e = sys.exc_info()[1] - if e.code != 1003: - raise - raise ContainerDoesNotExistError(e, self, container_name) - meta = self._emc_meta(result) - extra = { - 'object_id': meta['objectid'] - } - return Container(container_name, extra, self) - - def create_container(self, container_name): - path = self._namespace_path(container_name) + '/' - try: - self.connection.request(path, method='POST') - except AtmosError: - e = sys.exc_info()[1] - if e.code != 1016: - raise - raise ContainerAlreadyExistsError(e, self, container_name) - return self.get_container(container_name) - - def delete_container(self, container): - try: - self.connection.request(self._namespace_path(container.name) + '/', - method='DELETE') - except AtmosError: - e = sys.exc_info()[1] - if e.code == 1003: - raise ContainerDoesNotExistError(e, self, container.name) - elif e.code == 1023: - raise ContainerIsNotEmptyError(e, self, container.name) - return True - - def get_object(self, container_name, object_name): - container = self.get_container(container_name) - object_name_cleaned = self._clean_object_name(object_name) - path = self._namespace_path(container_name) + '/' + object_name_cleaned - - try: - result = self.connection.request(path + '?metadata/system') - system_meta = self._emc_meta(result) - - result = self.connection.request(path + '?metadata/user') - user_meta = self._emc_meta(result) - except AtmosError: - e = sys.exc_info()[1] - if e.code != 1003: - raise - raise ObjectDoesNotExistError(e, self, object_name) - - last_modified = time.strptime(system_meta['mtime'], - '%Y-%m-%dT%H:%M:%SZ') - last_modified = time.strftime('%a, %d %b %Y %H:%M:%S GMT', - last_modified) - extra = { - 'object_id': system_meta['objectid'], - 'last_modified': last_modified - } - data_hash = user_meta.pop('md5', '') - return Object(object_name, int(system_meta['size']), data_hash, extra, - user_meta, container, self) - - def upload_object(self, file_path, container, object_name, extra=None, - verify_hash=True): - upload_func = self._upload_file - upload_func_kwargs = {'file_path': file_path} - method = 'PUT' - - extra = extra or {} - object_name_cleaned = self._clean_object_name(object_name) - request_path = self._namespace_path(container.name) + '/' +\ - object_name_cleaned - content_type = extra.get('content_type', None) - - try: - self.connection.request(request_path + '?metadata/system') - except AtmosError: - e = sys.exc_info()[1] - if e.code != 1003: - raise - method = 'POST' - - result_dict = self._upload_object( - object_name=object_name, - content_type=content_type, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - request_path=request_path, - request_method=method, - headers={}, file_path=file_path) - - bytes_transferred = result_dict['bytes_transferred'] - - if extra is None: - meta_data = {} - else: - meta_data = extra.get('meta_data', {}) - meta_data['md5'] = result_dict['data_hash'] - user_meta = ', '.join([k + '=' + str(v) for k, v in - list(meta_data.items())]) - self.connection.request(request_path + '?metadata/user', method='POST', - headers={'x-emc-meta': user_meta}) - result = self.connection.request(request_path + '?metadata/system') - meta = self._emc_meta(result) - del meta_data['md5'] - extra = { - 'object_id': meta['objectid'], - 'meta_data': meta_data, - } - - return Object(object_name, bytes_transferred, result_dict['data_hash'], - extra, meta_data, container, self) - - def upload_object_via_stream(self, iterator, container, object_name, - extra=None): - if isinstance(iterator, file): - iterator = iter(iterator) - - data_hash = hashlib.md5() - generator = read_in_chunks(iterator, CHUNK_SIZE, True) - bytes_transferred = 0 - try: - chunk = next(generator) - except StopIteration: - chunk = '' - - path = self._namespace_path(container.name + '/' + object_name) - method = 'PUT' - - if extra is not None: - content_type = extra.get('content_type', None) - else: - content_type = None - if not content_type: - content_type, _ = guess_file_mime_type(object_name) - - if not content_type: - raise AttributeError( - 'File content-type could not be guessed and' + - ' no content_type value provided') - - try: - self.connection.request(path + '?metadata/system') - except AtmosError: - e = sys.exc_info()[1] - if e.code != 1003: - raise - method = 'POST' - - while True: - end = bytes_transferred + len(chunk) - 1 - data_hash.update(b(chunk)) - headers = { - 'x-emc-meta': 'md5=' + data_hash.hexdigest(), - 'Content-Type': content_type, - } - - if len(chunk) > 0 and bytes_transferred > 0: - headers['Range'] = 'Bytes=%d-%d' % (bytes_transferred, end) - method = 'PUT' - - result = self.connection.request(path, method=method, data=chunk, - headers=headers) - bytes_transferred += len(chunk) - - try: - chunk = next(generator) - except StopIteration: - break - if len(chunk) == 0: - break - - data_hash = data_hash.hexdigest() - - if extra is None: - meta_data = {} - else: - meta_data = extra.get('meta_data', {}) - meta_data['md5'] = data_hash - user_meta = ', '.join([k + '=' + str(v) for k, v in - list(meta_data.items())]) - self.connection.request(path + '?metadata/user', method='POST', - headers={'x-emc-meta': user_meta}) - - result = self.connection.request(path + '?metadata/system') - - meta = self._emc_meta(result) - extra = { - 'object_id': meta['objectid'], - 'meta_data': meta_data, - } - - return Object(object_name, bytes_transferred, data_hash, extra, - meta_data, container, self) - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - path = self._namespace_path(obj.container.name + '/' + obj.name) - response = self.connection.request(path, method='GET', raw=True) - - return self._get_object(obj=obj, callback=self._save_object, - response=response, - callback_kwargs={ - 'obj': obj, - 'response': response.response, - 'destination_path': destination_path, - 'overwrite_existing': overwrite_existing, - 'delete_on_failure': delete_on_failure - }, - success_status_code=httplib.OK) - - def download_object_as_stream(self, obj, chunk_size=None): - path = self._namespace_path(obj.container.name + '/' + obj.name) - response = self.connection.request(path, method='GET', raw=True) - - return self._get_object(obj=obj, callback=read_in_chunks, - response=response, - callback_kwargs={ - 'iterator': response.response, - 'chunk_size': chunk_size - }, - success_status_code=httplib.OK) - - def delete_object(self, obj): - path = self._namespace_path(obj.container.name) + '/' +\ - self._clean_object_name(obj.name) - try: - self.connection.request(path, method='DELETE') - except AtmosError: - e = sys.exc_info()[1] - if e.code != 1003: - raise - raise ObjectDoesNotExistError(e, self, obj.name) - return True - - def enable_object_cdn(self, obj): - return True - - def get_object_cdn_url(self, obj, expiry=None, use_object=False): - """ - Return a object CDN URL. - - :param obj: Object instance - :type obj: :class:`Object` - - :param expiry: Expiry - :type expiry: ``str`` - - :param use_object: Use object - :type use_object: ``bool`` - - :rtype: ``str`` - """ - if use_object: - path = '/rest/objects' + obj.meta_data['object_id'] - else: - path = '/rest/namespace/' + obj.container.name + '/' + obj.name - - if self.secure: - protocol = 'https' - else: - protocol = 'http' - - expiry = str(expiry or int(time.time()) + self.DEFAULT_CDN_TTL) - params = [ - ('uid', self.key), - ('expires', expiry), - ] - params.append(('signature', self._cdn_signature(path, params, expiry))) - - params = urlencode(params) - path = self.path + path - return urlparse.urlunparse((protocol, self.host, path, '', params, '')) - - def _cdn_signature(self, path, params, expiry): - key = base64.b64decode(self.secret) - signature = '\n'.join(['GET', path.lower(), self.key, expiry]) - signature = hmac.new(key, signature, hashlib.sha1).digest() - - return base64.b64encode(signature) - - def _list_objects(self, tree, object_type=None): - listing = tree.find(self._emc_tag('DirectoryList')) - entries = [] - for entry in listing.findall(self._emc_tag('DirectoryEntry')): - file_type = entry.find(self._emc_tag('FileType')).text - if object_type is not None and object_type != file_type: - continue - entries.append({ - 'id': entry.find(self._emc_tag('ObjectID')).text, - 'type': file_type, - 'name': entry.find(self._emc_tag('Filename')).text - }) - return entries - - def _clean_object_name(self, name): - return urlquote(name.encode('ascii')) - - def _namespace_path(self, path): - return self.path + '/rest/namespace/' + urlquote(path.encode('ascii')) - - def _object_path(self, object_id): - return self.path + '/rest/objects/' + object_id.encode('ascii') - - @staticmethod - def _emc_tag(tag): - return '{http://www.emc.com/cos/}' + tag - - def _emc_meta(self, response): - meta = response.headers.get('x-emc-meta', '') - if len(meta) == 0: - return {} - meta = meta.split(', ') - return dict([x.split('=', 1) for x in meta]) - - def iterate_container_objects(self, container): - headers = {'x-emc-include-meta': '1'} - path = self._namespace_path(container.name) + '/' - result = self.connection.request(path, headers=headers) - entries = self._list_objects(result.object, object_type='regular') - for entry in entries: - metadata = {'object_id': entry['id']} - yield Object(entry['name'], 0, '', {}, metadata, container, self) diff --git a/awx/lib/site-packages/libcloud/storage/drivers/azure_blobs.py b/awx/lib/site-packages/libcloud/storage/drivers/azure_blobs.py deleted file mode 100644 index 8d00a8dcf8..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/azure_blobs.py +++ /dev/null @@ -1,986 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import base64 -import os -import binascii - -from xml.etree.ElementTree import Element, SubElement - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlquote -from libcloud.utils.py3 import tostring -from libcloud.utils.py3 import b - -from libcloud.utils.xml import fixxpath -from libcloud.utils.files import read_in_chunks -from libcloud.common.types import LibcloudError -from libcloud.common.azure import AzureConnection - -from libcloud.storage.base import Object, Container, StorageDriver -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import ContainerAlreadyExistsError -from libcloud.storage.types import InvalidContainerNameError -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ObjectDoesNotExistError -from libcloud.storage.types import ObjectHashMismatchError - -if PY3: - from io import FileIO as file - -# Desired number of items in each response inside a paginated request -RESPONSES_PER_REQUEST = 100 - -# As per the Azure documentation, if the upload file size is less than -# 64MB, we can upload it in a single request. However, in real life azure -# servers seem to disconnect randomly after around 5 MB or 200s of upload. -# So, it is better that for file sizes greater than 4MB, we upload it in -# chunks. -# Also, with large sizes, if we use a lease, the lease will timeout after -# 60 seconds, but the upload might still be in progress. This can be -# handled in code, but if we use chunked uploads, the lease renewal will -# happen automatically. -AZURE_BLOCK_MAX_SIZE = 4 * 1024 * 1024 - -# Azure block blocks must be maximum 4MB -# Azure page blobs must be aligned in 512 byte boundaries (4MB fits that) -AZURE_CHUNK_SIZE = 4 * 1024 * 1024 - -# Azure page blob must be aligned in 512 byte boundaries -AZURE_PAGE_CHUNK_SIZE = 512 - -# The time period (in seconds) for which a lease must be obtained. -# If set as -1, we get an infinite lease, but that is a bad idea. If -# after getting an infinite lease, there was an issue in releasing the -# lease, the object will remain 'locked' forever, unless the lease is -# released using the lease_id (which is not exposed to the user) -AZURE_LEASE_PERIOD = 60 - -AZURE_STORAGE_HOST_SUFFIX = 'blob.core.windows.net' - - -class AzureBlobLease(object): - """ - A class to help in leasing an azure blob and renewing the lease - """ - def __init__(self, driver, object_path, use_lease): - """ - :param driver: The Azure storage driver that is being used - :type driver: :class:`AzureStorageDriver` - - :param object_path: The path of the object we need to lease - :type object_path: ``str`` - - :param use_lease: Indicates if we must take a lease or not - :type use_lease: ``bool`` - """ - self.object_path = object_path - self.driver = driver - self.use_lease = use_lease - self.lease_id = None - self.params = {'comp': 'lease'} - - def renew(self): - """ - Renew the lease if it is older than a predefined time period - """ - if self.lease_id is None: - return - - headers = {'x-ms-lease-action': 'renew', - 'x-ms-lease-id': self.lease_id, - 'x-ms-lease-duration': '60'} - - response = self.driver.connection.request(self.object_path, - headers=headers, - params=self.params, - method='PUT') - - if response.status != httplib.OK: - raise LibcloudError('Unable to obtain lease', driver=self) - - def update_headers(self, headers): - """ - Update the lease id in the headers - """ - if self.lease_id: - headers['x-ms-lease-id'] = self.lease_id - - def __enter__(self): - if not self.use_lease: - return self - - headers = {'x-ms-lease-action': 'acquire', - 'x-ms-lease-duration': '60'} - - response = self.driver.connection.request(self.object_path, - headers=headers, - params=self.params, - method='PUT') - - if response.status == httplib.NOT_FOUND: - return self - elif response.status != httplib.CREATED: - raise LibcloudError('Unable to obtain lease', driver=self) - - self.lease_id = response.headers['x-ms-lease-id'] - return self - - def __exit__(self, type, value, traceback): - if self.lease_id is None: - return - - headers = {'x-ms-lease-action': 'release', - 'x-ms-lease-id': self.lease_id} - response = self.driver.connection.request(self.object_path, - headers=headers, - params=self.params, - method='PUT') - - if response.status != httplib.OK: - raise LibcloudError('Unable to release lease', driver=self) - - -class AzureBlobsConnection(AzureConnection): - """ - Represents a single connection to Azure Blobs - """ - - -class AzureBlobsStorageDriver(StorageDriver): - name = 'Microsoft Azure (blobs)' - website = 'http://windows.azure.com/' - connectionCls = AzureBlobsConnection - hash_type = 'md5' - supports_chunked_encoding = False - ex_blob_type = 'BlockBlob' - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - **kwargs): - self._host_argument_set = bool(host) - - # B64decode() this key and keep it, so that we don't have to do - # so for every request. Minor performance improvement - secret = base64.b64decode(b(secret)) - - super(AzureBlobsStorageDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, **kwargs) - - def _ex_connection_class_kwargs(self): - result = {} - - # host argument has precedence - if not self._host_argument_set: - result['host'] = '%s.%s' % (self.key, AZURE_STORAGE_HOST_SUFFIX) - - return result - - def _xml_to_container(self, node): - """ - Converts a container XML node to a container instance - - :param node: XML info of the container - :type node: :class:`xml.etree.ElementTree.Element` - - :return: A container instance - :rtype: :class:`Container` - """ - - name = node.findtext(fixxpath(xpath='Name')) - props = node.find(fixxpath(xpath='Properties')) - metadata = node.find(fixxpath(xpath='Metadata')) - - extra = { - 'url': node.findtext(fixxpath(xpath='Url')), - 'last_modified': node.findtext(fixxpath(xpath='Last-Modified')), - 'etag': props.findtext(fixxpath(xpath='Etag')), - 'lease': { - 'status': props.findtext(fixxpath(xpath='LeaseStatus')), - 'state': props.findtext(fixxpath(xpath='LeaseState')), - 'duration': props.findtext(fixxpath(xpath='LeaseDuration')), - }, - 'meta_data': {} - } - - for meta in metadata.getchildren(): - extra['meta_data'][meta.tag] = meta.text - - return Container(name=name, extra=extra, driver=self) - - def _response_to_container(self, container_name, response): - """ - Converts a HTTP response to a container instance - - :param container_name: Name of the container - :type container_name: ``str`` - - :param response: HTTP Response - :type node: L{} - - :return: A container instance - :rtype: :class:`Container` - """ - - headers = response.headers - extra = { - 'url': 'http://%s%s' % (response.connection.host, - response.connection.action), - 'etag': headers['etag'], - 'last_modified': headers['last-modified'], - 'lease': { - 'status': headers.get('x-ms-lease-status', None), - 'state': headers.get('x-ms-lease-state', None), - 'duration': headers.get('x-ms-lease-duration', None), - }, - 'meta_data': {} - } - - for key, value in response.headers.items(): - if key.startswith('x-ms-meta-'): - key = key.split('x-ms-meta-')[1] - extra['meta_data'][key] = value - - return Container(name=container_name, extra=extra, driver=self) - - def _xml_to_object(self, container, blob): - """ - Converts a BLOB XML node to an object instance - - :param container: Instance of the container holding the blob - :type: :class:`Container` - - :param blob: XML info of the blob - :type blob: L{} - - :return: An object instance - :rtype: :class:`Object` - """ - - name = blob.findtext(fixxpath(xpath='Name')) - props = blob.find(fixxpath(xpath='Properties')) - metadata = blob.find(fixxpath(xpath='Metadata')) - etag = props.findtext(fixxpath(xpath='Etag')) - size = int(props.findtext(fixxpath(xpath='Content-Length'))) - - extra = { - 'content_type': props.findtext(fixxpath(xpath='Content-Type')), - 'etag': etag, - 'md5_hash': props.findtext(fixxpath(xpath='Content-MD5')), - 'last_modified': props.findtext(fixxpath(xpath='Last-Modified')), - 'url': blob.findtext(fixxpath(xpath='Url')), - 'hash': props.findtext(fixxpath(xpath='Etag')), - 'lease': { - 'status': props.findtext(fixxpath(xpath='LeaseStatus')), - 'state': props.findtext(fixxpath(xpath='LeaseState')), - 'duration': props.findtext(fixxpath(xpath='LeaseDuration')), - }, - 'content_encoding': props.findtext(fixxpath( - xpath='Content-Encoding')), - 'content_language': props.findtext(fixxpath( - xpath='Content-Language')), - 'blob_type': props.findtext(fixxpath(xpath='BlobType')) - } - - if extra['md5_hash']: - value = binascii.hexlify(base64.b64decode(b(extra['md5_hash']))) - value = value.decode('ascii') - extra['md5_hash'] = value - - meta_data = {} - for meta in metadata.getchildren(): - meta_data[meta.tag] = meta.text - - return Object(name=name, size=size, hash=etag, meta_data=meta_data, - extra=extra, container=container, driver=self) - - def _response_to_object(self, object_name, container, response): - """ - Converts a HTTP response to an object (from headers) - - :param object_name: Name of the object - :type object_name: ``str`` - - :param container: Instance of the container holding the blob - :type: :class:`Container` - - :param response: HTTP Response - :type node: L{} - - :return: An object instance - :rtype: :class:`Object` - """ - - headers = response.headers - size = int(headers['content-length']) - etag = headers['etag'] - - extra = { - 'url': 'http://%s%s' % (response.connection.host, - response.connection.action), - 'etag': etag, - 'md5_hash': headers.get('content-md5', None), - 'content_type': headers.get('content-type', None), - 'content_language': headers.get('content-language', None), - 'content_encoding': headers.get('content-encoding', None), - 'last_modified': headers['last-modified'], - 'lease': { - 'status': headers.get('x-ms-lease-status', None), - 'state': headers.get('x-ms-lease-state', None), - 'duration': headers.get('x-ms-lease-duration', None), - }, - 'blob_type': headers['x-ms-blob-type'] - } - - if extra['md5_hash']: - value = binascii.hexlify(base64.b64decode(b(extra['md5_hash']))) - value = value.decode('ascii') - extra['md5_hash'] = value - - meta_data = {} - for key, value in response.headers.items(): - if key.startswith('x-ms-meta-'): - key = key.split('x-ms-meta-')[1] - meta_data[key] = value - - return Object(name=object_name, size=size, hash=etag, extra=extra, - meta_data=meta_data, container=container, driver=self) - - def iterate_containers(self): - """ - @inherits: :class:`StorageDriver.iterate_containers` - """ - params = {'comp': 'list', - 'maxresults': RESPONSES_PER_REQUEST, - 'include': 'metadata'} - - while True: - response = self.connection.request('/', params) - if response.status != httplib.OK: - raise LibcloudError('Unexpected status code: %s' % - (response.status), driver=self) - - body = response.parse_body() - containers = body.find(fixxpath(xpath='Containers')) - containers = containers.findall(fixxpath(xpath='Container')) - - for container in containers: - yield self._xml_to_container(container) - - params['marker'] = body.findtext('NextMarker') - if not params['marker']: - break - - def iterate_container_objects(self, container): - """ - @inherits: :class:`StorageDriver.iterate_container_objects` - """ - params = {'restype': 'container', - 'comp': 'list', - 'maxresults': RESPONSES_PER_REQUEST, - 'include': 'metadata'} - - container_path = self._get_container_path(container) - - while True: - response = self.connection.request(container_path, - params=params) - - if response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError(value=None, - driver=self, - container_name=container.name) - - elif response.status != httplib.OK: - raise LibcloudError('Unexpected status code: %s' % - (response.status), driver=self) - - body = response.parse_body() - blobs = body.find(fixxpath(xpath='Blobs')) - blobs = blobs.findall(fixxpath(xpath='Blob')) - - for blob in blobs: - yield self._xml_to_object(container, blob) - - params['marker'] = body.findtext('NextMarker') - if not params['marker']: - break - - def get_container(self, container_name): - """ - @inherits: :class:`StorageDriver.get_container` - """ - params = {'restype': 'container'} - - container_path = '/%s' % (container_name) - - response = self.connection.request(container_path, params=params, - method='HEAD') - - if response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError('Container %s does not exist' % - (container_name), driver=self, - container_name=container_name) - elif response.status != httplib.OK: - raise LibcloudError('Unexpected status code: %s' % - (response.status), driver=self) - - return self._response_to_container(container_name, response) - - def get_object(self, container_name, object_name): - """ - @inherits: :class:`StorageDriver.get_object` - """ - - container = self.get_container(container_name=container_name) - object_path = self._get_object_path(container, object_name) - - response = self.connection.request(object_path, method='HEAD') - - if response.status == httplib.OK: - obj = self._response_to_object(object_name, container, response) - return obj - - raise ObjectDoesNotExistError(value=None, driver=self, - object_name=object_name) - - def _get_container_path(self, container): - """ - Return a container path - - :param container: Container instance - :type container: :class:`Container` - - :return: A path for this container. - :rtype: ``str`` - """ - return '/%s' % (container.name) - - def _get_object_path(self, container, object_name): - """ - Return an object's CDN path. - - :param container: Container instance - :type container: :class:`Container` - - :param object_name: Object name - :type object_name: :class:`str` - - :return: A path for this object. - :rtype: ``str`` - """ - container_url = self._get_container_path(container) - object_name_cleaned = urlquote(object_name) - object_path = '%s/%s' % (container_url, object_name_cleaned) - return object_path - - def create_container(self, container_name): - """ - @inherits: :class:`StorageDriver.create_container` - """ - params = {'restype': 'container'} - - container_path = '/%s' % (container_name) - response = self.connection.request(container_path, params=params, - method='PUT') - - if response.status == httplib.CREATED: - return self._response_to_container(container_name, response) - elif response.status == httplib.CONFLICT: - raise ContainerAlreadyExistsError( - value='Container with this name already exists. The name must ' - 'be unique among all the containers in the system', - container_name=container_name, driver=self) - elif response.status == httplib.BAD_REQUEST: - raise InvalidContainerNameError(value='Container name contains ' + - 'invalid characters.', - container_name=container_name, - driver=self) - - raise LibcloudError('Unexpected status code: %s' % (response.status), - driver=self) - - def delete_container(self, container): - """ - @inherits: :class:`StorageDriver.delete_container` - """ - # Azure does not check if the container is empty. So, we will do - # a check to ensure that the behaviour is similar to other drivers - for obj in container.iterate_objects(): - raise ContainerIsNotEmptyError( - value='Container must be empty before it can be deleted.', - container_name=container.name, driver=self) - - params = {'restype': 'container'} - container_path = self._get_container_path(container) - - # Note: All the objects in the container must be deleted first - response = self.connection.request(container_path, params=params, - method='DELETE') - - if response.status == httplib.ACCEPTED: - return True - elif response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError(value=None, - driver=self, - container_name=container.name) - - return False - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - """ - @inherits: :class:`StorageDriver.download_object` - """ - obj_path = self._get_object_path(obj.container, obj.name) - response = self.connection.request(obj_path, raw=True, data=None) - - return self._get_object(obj=obj, callback=self._save_object, - response=response, - callback_kwargs={ - 'obj': obj, - 'response': response.response, - 'destination_path': destination_path, - 'overwrite_existing': overwrite_existing, - 'delete_on_failure': delete_on_failure}, - success_status_code=httplib.OK) - - def download_object_as_stream(self, obj, chunk_size=None): - """ - @inherits: :class:`StorageDriver.download_object_as_stream` - """ - obj_path = self._get_object_path(obj.container, obj.name) - response = self.connection.request(obj_path, raw=True, data=None) - - return self._get_object(obj=obj, callback=read_in_chunks, - response=response, - callback_kwargs={'iterator': response.response, - 'chunk_size': chunk_size}, - success_status_code=httplib.OK) - - def _upload_in_chunks(self, response, data, iterator, object_path, - blob_type, lease, calculate_hash=True): - """ - Uploads data from an interator in fixed sized chunks to S3 - - :param response: Response object from the initial POST request - :type response: :class:`RawResponse` - - :param data: Any data from the initial POST request - :type data: ``str`` - - :param iterator: The generator for fetching the upload data - :type iterator: ``generator`` - - :param object_path: The path of the object to which we are uploading - :type object_name: ``str`` - - :param blob_type: The blob type being uploaded - :type blob_type: ``str`` - - :param lease: The lease object to be used for renewal - :type lease: :class:`AzureBlobLease` - - :keyword calculate_hash: Indicates if we must calculate the data hash - :type calculate_hash: ``bool`` - - :return: A tuple of (status, checksum, bytes transferred) - :rtype: ``tuple`` - """ - - # Get the upload id from the response xml - if response.status != httplib.CREATED: - raise LibcloudError('Error initializing upload. Code: %d' % - (response.status), driver=self) - - data_hash = None - if calculate_hash: - data_hash = self._get_hash_function() - - bytes_transferred = 0 - count = 1 - chunks = [] - headers = {} - - lease.update_headers(headers) - - if blob_type == 'BlockBlob': - params = {'comp': 'block'} - else: - params = {'comp': 'page'} - - # Read the input data in chunk sizes suitable for AWS - for data in read_in_chunks(iterator, AZURE_CHUNK_SIZE): - data = b(data) - content_length = len(data) - offset = bytes_transferred - bytes_transferred += content_length - - if calculate_hash: - data_hash.update(data) - - chunk_hash = self._get_hash_function() - chunk_hash.update(data) - chunk_hash = base64.b64encode(b(chunk_hash.digest())) - - headers['Content-MD5'] = chunk_hash.decode('utf-8') - headers['Content-Length'] = content_length - - if blob_type == 'BlockBlob': - # Block id can be any unique string that is base64 encoded - # A 10 digit number can hold the max value of 50000 blocks - # that are allowed for azure - block_id = base64.b64encode(b('%10d' % (count))) - block_id = block_id.decode('utf-8') - params['blockid'] = block_id - - # Keep this data for a later commit - chunks.append(block_id) - else: - headers['x-ms-page-write'] = 'update' - headers['x-ms-range'] = 'bytes=%d-%d' % \ - (offset, bytes_transferred-1) - - # Renew lease before updating - lease.renew() - - resp = self.connection.request(object_path, method='PUT', - data=data, headers=headers, - params=params) - - if resp.status != httplib.CREATED: - resp.parse_error() - raise LibcloudError('Error uploading chunk %d. Code: %d' % - (count, resp.status), driver=self) - - count += 1 - - if calculate_hash: - data_hash = data_hash.hexdigest() - - if blob_type == 'BlockBlob': - self._commit_blocks(object_path, chunks, lease) - - # The Azure service does not return a hash immediately for - # chunked uploads. It takes some time for the data to get synced - response.headers['content-md5'] = None - - return (True, data_hash, bytes_transferred) - - def _commit_blocks(self, object_path, chunks, lease): - """ - Makes a final commit of the data. - - :param object_path: Server side object path. - :type object_path: ``str`` - - :param upload_id: A list of (chunk_number, chunk_hash) tuples. - :type upload_id: ``list`` - """ - - root = Element('BlockList') - - for block_id in chunks: - part = SubElement(root, 'Uncommitted') - part.text = str(block_id) - - data = tostring(root) - params = {'comp': 'blocklist'} - headers = {} - - lease.update_headers(headers) - lease.renew() - - response = self.connection.request(object_path, data=data, - params=params, headers=headers, - method='PUT') - - if response.status != httplib.CREATED: - raise LibcloudError('Error in blocklist commit', driver=self) - - def _check_values(self, blob_type, object_size): - """ - Checks if extension arguments are valid - - :param blob_type: The blob type that is being uploaded - :type blob_type: ``str`` - - :param object_size: The (max) size of the object being uploaded - :type object_size: ``int`` - """ - - if blob_type not in ['BlockBlob', 'PageBlob']: - raise LibcloudError('Invalid blob type', driver=self) - - if blob_type == 'PageBlob': - if not object_size: - raise LibcloudError('Max blob size is mandatory for page blob', - driver=self) - - if object_size % AZURE_PAGE_CHUNK_SIZE: - raise LibcloudError('Max blob size is not aligned to ' - 'page boundary', driver=self) - - def upload_object(self, file_path, container, object_name, extra=None, - verify_hash=True, ex_blob_type=None, ex_use_lease=False): - """ - Upload an object currently located on a disk. - - @inherits: :class:`StorageDriver.upload_object` - - :param ex_blob_type: Storage class - :type ex_blob_type: ``str`` - - :param ex_use_lease: Indicates if we must take a lease before upload - :type ex_use_lease: ``bool`` - """ - - if ex_blob_type is None: - ex_blob_type = self.ex_blob_type - - # Get the size of the file - file_size = os.stat(file_path).st_size - - # The presumed size of the object - object_size = file_size - - self._check_values(ex_blob_type, file_size) - - with file(file_path, 'rb') as file_handle: - iterator = iter(file_handle) - - # If size is greater than 64MB or type is Page, upload in chunks - if ex_blob_type == 'PageBlob' or file_size > AZURE_BLOCK_MAX_SIZE: - # For chunked upload of block blobs, the initial size must - # be 0. - if ex_blob_type == 'BlockBlob': - object_size = None - - object_path = self._get_object_path(container, object_name) - - upload_func = self._upload_in_chunks - upload_func_kwargs = {'iterator': iterator, - 'object_path': object_path, - 'blob_type': ex_blob_type, - 'lease': None} - else: - upload_func = self._stream_data - upload_func_kwargs = {'iterator': iterator, - 'chunked': False, - 'calculate_hash': verify_hash} - - return self._put_object(container=container, - object_name=object_name, - object_size=object_size, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - file_path=file_path, extra=extra, - verify_hash=verify_hash, - blob_type=ex_blob_type, - use_lease=ex_use_lease) - - def upload_object_via_stream(self, iterator, container, object_name, - verify_hash=False, extra=None, - ex_use_lease=False, ex_blob_type=None, - ex_page_blob_size=None): - """ - @inherits: :class:`StorageDriver.upload_object_via_stream` - - :param ex_blob_type: Storage class - :type ex_blob_type: ``str`` - - :param ex_page_blob_size: The maximum size to which the - page blob can grow to - :type ex_page_blob_size: ``int`` - - :param ex_use_lease: Indicates if we must take a lease before upload - :type ex_use_lease: ``bool`` - """ - - if ex_blob_type is None: - ex_blob_type = self.ex_blob_type - - self._check_values(ex_blob_type, ex_page_blob_size) - - object_path = self._get_object_path(container, object_name) - - upload_func = self._upload_in_chunks - upload_func_kwargs = {'iterator': iterator, - 'object_path': object_path, - 'blob_type': ex_blob_type, - 'lease': None} - - return self._put_object(container=container, - object_name=object_name, - object_size=ex_page_blob_size, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - extra=extra, verify_hash=verify_hash, - blob_type=ex_blob_type, - use_lease=ex_use_lease) - - def delete_object(self, obj): - """ - @inherits: :class:`StorageDriver.delete_object` - """ - object_path = self._get_object_path(obj.container, obj.name) - response = self.connection.request(object_path, method='DELETE') - - if response.status == httplib.ACCEPTED: - return True - elif response.status == httplib.NOT_FOUND: - raise ObjectDoesNotExistError(value=None, driver=self, - object_name=obj.name) - - return False - - def _update_metadata(self, headers, meta_data): - """ - Update the given metadata in the headers - - :param headers: The headers dictionary to be updated - :type headers: ``dict`` - - :param meta_data: Metadata key value pairs - :type meta_data: ``dict`` - """ - for key, value in list(meta_data.items()): - key = 'x-ms-meta-%s' % (key) - headers[key] = value - - def _prepare_upload_headers(self, object_name, object_size, - extra, meta_data, blob_type): - """ - Prepare headers for uploading an object - - :param object_name: The full name of the object being updated - :type object_name: ``str`` - - :param object_size: The size of the object. In case of PageBlobs, - this indicates the maximum size the blob can grow to - :type object_size: ``int`` - - :param extra: Extra control data for the upload - :type extra: ``dict`` - - :param meta_data: Metadata key value pairs - :type meta_data: ``dict`` - - :param blob_type: Page or Block blob type - :type blob_type: ``str`` - """ - headers = {} - - if blob_type is None: - blob_type = self.ex_blob_type - - headers['x-ms-blob-type'] = blob_type - - self._update_metadata(headers, meta_data) - - if object_size is not None: - headers['Content-Length'] = object_size - - if blob_type == 'PageBlob': - headers['Content-Length'] = 0 - headers['x-ms-blob-content-length'] = object_size - - return headers - - def _put_object(self, container, object_name, object_size, upload_func, - upload_func_kwargs, file_path=None, extra=None, - verify_hash=True, blob_type=None, use_lease=False): - """ - Control function that does the real job of uploading data to a blob - """ - extra = extra or {} - meta_data = extra.get('meta_data', {}) - content_type = extra.get('content_type', None) - - headers = self._prepare_upload_headers(object_name, object_size, - extra, meta_data, blob_type) - - object_path = self._get_object_path(container, object_name) - - # Get a lease if required and do the operations - with AzureBlobLease(self, object_path, use_lease) as lease: - if 'lease' in upload_func_kwargs: - upload_func_kwargs['lease'] = lease - - lease.update_headers(headers) - - iterator = iter('') - result_dict = self._upload_object(object_name, content_type, - upload_func, upload_func_kwargs, - object_path, headers=headers, - file_path=file_path, - iterator=iterator) - - response = result_dict['response'] - bytes_transferred = result_dict['bytes_transferred'] - data_hash = result_dict['data_hash'] - headers = response.headers - response = response.response - - if response.status != httplib.CREATED: - raise LibcloudError( - 'Unexpected status code, status_code=%s' % (response.status), - driver=self) - - server_hash = headers['content-md5'] - - if server_hash: - server_hash = binascii.hexlify(base64.b64decode(b(server_hash))) - server_hash = server_hash.decode('utf-8') - else: - # TODO: HACK - We could poll the object for a while and get - # the hash - pass - - if (verify_hash and server_hash and data_hash != server_hash): - raise ObjectHashMismatchError( - value='MD5 hash checksum does not match', - object_name=object_name, driver=self) - - return Object(name=object_name, size=bytes_transferred, - hash=headers['etag'], extra=None, - meta_data=meta_data, container=container, - driver=self) - - def ex_set_object_metadata(self, obj, meta_data): - """ - Set metadata for an object - - :param obj: The blob object - :type obj: :class:`Object` - - :param meta_data: Metadata key value pairs - :type meta_data: ``dict`` - """ - object_path = self._get_object_path(obj.container, obj.name) - params = {'comp': 'metadata'} - headers = {} - - self._update_metadata(headers, meta_data) - - response = self.connection.request(object_path, method='PUT', - params=params, - headers=headers) - - if response.status != httplib.OK: - response.parse_error('Setting metadata') diff --git a/awx/lib/site-packages/libcloud/storage/drivers/cloudfiles.py b/awx/lib/site-packages/libcloud/storage/drivers/cloudfiles.py deleted file mode 100644 index bce89a865c..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/cloudfiles.py +++ /dev/null @@ -1,994 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from hashlib import sha1 -import hmac -import os -from time import time - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlencode - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import b -from libcloud.utils.py3 import urlquote - -if PY3: - from io import FileIO as file - -from libcloud.utils.files import read_in_chunks -from libcloud.common.types import MalformedResponseError, LibcloudError -from libcloud.common.base import Response, RawResponse - -from libcloud.storage.providers import Provider -from libcloud.storage.base import Object, Container, StorageDriver -from libcloud.storage.types import ContainerAlreadyExistsError -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import ObjectDoesNotExistError -from libcloud.storage.types import ObjectHashMismatchError -from libcloud.storage.types import InvalidContainerNameError -from libcloud.common.openstack import OpenStackBaseConnection -from libcloud.common.openstack import OpenStackDriverMixin - -from libcloud.common.rackspace import AUTH_URL - -CDN_HOST = 'cdn.clouddrive.com' -API_VERSION = 'v1.0' - -# Keys which are used to select a correct endpoint from the service catalog. -INTERNAL_ENDPOINT_KEY = 'internalURL' -PUBLIC_ENDPOINT_KEY = 'publicURL' - - -class CloudFilesResponse(Response): - valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT] - - def success(self): - i = int(self.status) - return i >= 200 and i <= 299 or i in self.valid_response_codes - - def parse_body(self): - if not self.body: - return None - - if 'content-type' in self.headers: - key = 'content-type' - elif 'Content-Type' in self.headers: - key = 'Content-Type' - else: - raise LibcloudError('Missing content-type header') - - content_type = self.headers[key] - if content_type.find(';') != -1: - content_type = content_type.split(';')[0] - - if content_type == 'application/json': - try: - data = json.loads(self.body) - except: - raise MalformedResponseError('Failed to parse JSON', - body=self.body, - driver=CloudFilesStorageDriver) - elif content_type == 'text/plain': - data = self.body - else: - data = self.body - - return data - - -class CloudFilesRawResponse(CloudFilesResponse, RawResponse): - pass - - -class OpenStackSwiftConnection(OpenStackBaseConnection): - """ - Connection class for the OpenStack Swift endpoint. - """ - - responseCls = CloudFilesResponse - rawResponseCls = CloudFilesRawResponse - - auth_url = AUTH_URL - _auth_version = '1.0' - - # TODO: Reverse the relationship - Swift -> CloudFiles - def __init__(self, user_id, key, secure=True, **kwargs): - # Ignore this for now - kwargs.pop('use_internal_url', None) - super(OpenStackSwiftConnection, self).__init__(user_id, key, - secure=secure, - **kwargs) - self.api_version = API_VERSION - self.accept_format = 'application/json' - - self._service_type = self._ex_force_service_type or 'object-store' - self._service_name = self._ex_force_service_name or 'swift' - - if self._ex_force_service_region: - self._service_region = self._ex_force_service_region - else: - self._service_region = None - - def get_endpoint(self, *args, **kwargs): - if '2.0' in self._auth_version: - endpoint = self.service_catalog.get_endpoint( - service_type=self._service_type, - name=self._service_name, - region=self._service_region) - elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version): - endpoint = self.service_catalog.get_endpoint( - name=self._service_name, region=self._service_region) - - if PUBLIC_ENDPOINT_KEY in endpoint: - return endpoint[PUBLIC_ENDPOINT_KEY] - else: - raise LibcloudError('Could not find specified endpoint') - - def request(self, action, params=None, data='', headers=None, method='GET', - raw=False, cdn_request=False): - if not headers: - headers = {} - if not params: - params = {} - - self.cdn_request = cdn_request - params['format'] = 'json' - - if method in ['POST', 'PUT'] and 'Content-Type' not in headers: - headers.update({'Content-Type': 'application/json; charset=UTF-8'}) - - return super(OpenStackSwiftConnection, self).request( - action=action, - params=params, data=data, - method=method, headers=headers, - raw=raw) - - -class CloudFilesConnection(OpenStackSwiftConnection): - """ - Base connection class for the Cloudfiles driver. - """ - - responseCls = CloudFilesResponse - rawResponseCls = CloudFilesRawResponse - - auth_url = AUTH_URL - _auth_version = '2.0' - - def __init__(self, user_id, key, secure=True, - use_internal_url=False, **kwargs): - super(CloudFilesConnection, self).__init__(user_id, key, secure=secure, - **kwargs) - self.api_version = API_VERSION - self.accept_format = 'application/json' - self.cdn_request = False - self.use_internal_url = use_internal_url - - def _get_endpoint_key(self): - if self.use_internal_url: - endpoint_key = INTERNAL_ENDPOINT_KEY - else: - endpoint_key = PUBLIC_ENDPOINT_KEY - - if self.cdn_request: - # cdn endpoints don't have internal urls - endpoint_key = PUBLIC_ENDPOINT_KEY - - return endpoint_key - - def get_endpoint(self): - region = self._ex_force_service_region.upper() - - if '2.0' in self._auth_version: - ep = self.service_catalog.get_endpoint( - service_type='object-store', - name='cloudFiles', - region=region) - cdn_ep = self.service_catalog.get_endpoint( - service_type='rax:object-cdn', - name='cloudFilesCDN', - region=region) - else: - raise LibcloudError( - 'Auth version "%s" not supported' % (self._auth_version)) - - # if this is a CDN request, return the cdn url instead - if self.cdn_request: - ep = cdn_ep - - endpoint_key = self._get_endpoint_key() - - if not ep: - raise LibcloudError('Could not find specified endpoint') - - if endpoint_key in ep: - return ep[endpoint_key] - else: - raise LibcloudError('Could not find specified endpoint') - - def request(self, action, params=None, data='', headers=None, method='GET', - raw=False, cdn_request=False): - if not headers: - headers = {} - if not params: - params = {} - - self.cdn_request = cdn_request - params['format'] = 'json' - - if method in ['POST', 'PUT'] and 'Content-Type' not in headers: - headers.update({'Content-Type': 'application/json; charset=UTF-8'}) - - return super(CloudFilesConnection, self).request( - action=action, - params=params, data=data, - method=method, headers=headers, - raw=raw) - - -class CloudFilesStorageDriver(StorageDriver, OpenStackDriverMixin): - """ - CloudFiles driver. - """ - name = 'CloudFiles' - website = 'http://www.rackspace.com/' - - connectionCls = CloudFilesConnection - hash_type = 'md5' - supports_chunked_encoding = True - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region='ord', use_internal_url=False, **kwargs): - """ - @inherits: :class:`StorageDriver.__init__` - - :param region: ID of the region which should be used. - :type region: ``str`` - """ - # This is here for backard compatibility - if 'ex_force_service_region' in kwargs: - region = kwargs['ex_force_service_region'] - - self.use_internal_url = use_internal_url - OpenStackDriverMixin.__init__(self, (), **kwargs) - super(CloudFilesStorageDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, region=region, - **kwargs) - - def iterate_containers(self): - response = self.connection.request('') - - if response.status == httplib.NO_CONTENT: - return [] - elif response.status == httplib.OK: - return self._to_container_list(json.loads(response.body)) - - raise LibcloudError('Unexpected status code: %s' % (response.status)) - - def get_container(self, container_name): - container_name_encoded = self._encode_container_name(container_name) - response = self.connection.request('/%s' % (container_name_encoded), - method='HEAD') - - if response.status == httplib.NO_CONTENT: - container = self._headers_to_container( - container_name, response.headers) - return container - elif response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError(None, self, container_name) - - raise LibcloudError('Unexpected status code: %s' % (response.status)) - - def get_object(self, container_name, object_name): - container = self.get_container(container_name) - container_name_encoded = self._encode_container_name(container_name) - object_name_encoded = self._encode_object_name(object_name) - - response = self.connection.request('/%s/%s' % (container_name_encoded, - object_name_encoded), - method='HEAD') - if response.status in [httplib.OK, httplib.NO_CONTENT]: - obj = self._headers_to_object( - object_name, container, response.headers) - return obj - elif response.status == httplib.NOT_FOUND: - raise ObjectDoesNotExistError(None, self, object_name) - - raise LibcloudError('Unexpected status code: %s' % (response.status)) - - def get_container_cdn_url(self, container): - container_name_encoded = self._encode_container_name(container.name) - response = self.connection.request('/%s' % (container_name_encoded), - method='HEAD', - cdn_request=True) - - if response.status == httplib.NO_CONTENT: - cdn_url = response.headers['x-cdn-uri'] - return cdn_url - elif response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError(value='', - container_name=container.name, - driver=self) - - raise LibcloudError('Unexpected status code: %s' % (response.status)) - - def get_object_cdn_url(self, obj): - container_cdn_url = self.get_container_cdn_url(container=obj.container) - return '%s/%s' % (container_cdn_url, obj.name) - - def enable_container_cdn(self, container, ex_ttl=None): - """ - @inherits: :class:`StorageDriver.enable_container_cdn` - - :param ex_ttl: cache time to live - :type ex_ttl: ``int`` - """ - container_name = container.name - headers = {'X-CDN-Enabled': 'True'} - - if ex_ttl: - headers['X-TTL'] = ex_ttl - - response = self.connection.request('/%s' % (container_name), - method='PUT', - headers=headers, - cdn_request=True) - - return response.status in [httplib.CREATED, httplib.ACCEPTED] - - def create_container(self, container_name): - container_name_encoded = self._encode_container_name(container_name) - response = self.connection.request( - '/%s' % (container_name_encoded), method='PUT') - - if response.status == httplib.CREATED: - # Accepted mean that container is not yet created but it will be - # eventually - extra = {'object_count': 0} - container = Container(name=container_name, - extra=extra, driver=self) - - return container - elif response.status == httplib.ACCEPTED: - error = ContainerAlreadyExistsError(None, self, container_name) - raise error - - raise LibcloudError('Unexpected status code: %s' % (response.status)) - - def delete_container(self, container): - name = self._encode_container_name(container.name) - - # Only empty container can be deleted - response = self.connection.request('/%s' % (name), method='DELETE') - - if response.status == httplib.NO_CONTENT: - return True - elif response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError(value='', - container_name=name, driver=self) - elif response.status == httplib.CONFLICT: - # @TODO: Add "delete_all_objects" parameter? - raise ContainerIsNotEmptyError(value='', - container_name=name, driver=self) - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - container_name = obj.container.name - object_name = obj.name - response = self.connection.request('/%s/%s' % (container_name, - object_name), - method='GET', raw=True) - - return self._get_object( - obj=obj, callback=self._save_object, response=response, - callback_kwargs={'obj': obj, - 'response': response.response, - 'destination_path': destination_path, - 'overwrite_existing': overwrite_existing, - 'delete_on_failure': delete_on_failure}, - success_status_code=httplib.OK) - - def download_object_as_stream(self, obj, chunk_size=None): - container_name = obj.container.name - object_name = obj.name - response = self.connection.request('/%s/%s' % (container_name, - object_name), - method='GET', raw=True) - - return self._get_object(obj=obj, callback=read_in_chunks, - response=response, - callback_kwargs={'iterator': response.response, - 'chunk_size': chunk_size}, - success_status_code=httplib.OK) - - def upload_object(self, file_path, container, object_name, extra=None, - verify_hash=True): - """ - Upload an object. - - Note: This will override file with a same name if it already exists. - """ - upload_func = self._upload_file - upload_func_kwargs = {'file_path': file_path} - - return self._put_object(container=container, object_name=object_name, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - extra=extra, file_path=file_path, - verify_hash=verify_hash) - - def upload_object_via_stream(self, iterator, - container, object_name, extra=None): - if isinstance(iterator, file): - iterator = iter(iterator) - - upload_func = self._stream_data - upload_func_kwargs = {'iterator': iterator} - - return self._put_object(container=container, object_name=object_name, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - extra=extra, iterator=iterator) - - def delete_object(self, obj): - container_name = self._encode_container_name(obj.container.name) - object_name = self._encode_object_name(obj.name) - - response = self.connection.request( - '/%s/%s' % (container_name, object_name), method='DELETE') - - if response.status == httplib.NO_CONTENT: - return True - elif response.status == httplib.NOT_FOUND: - raise ObjectDoesNotExistError(value='', object_name=object_name, - driver=self) - - raise LibcloudError('Unexpected status code: %s' % (response.status)) - - def ex_purge_object_from_cdn(self, obj, email=None): - """ - Purge edge cache for the specified object. - - :param email: Email where a notification will be sent when the job - completes. (optional) - :type email: ``str`` - """ - container_name = self._encode_container_name(obj.container.name) - object_name = self._encode_object_name(obj.name) - headers = {'X-Purge-Email': email} if email else {} - - response = self.connection.request('/%s/%s' % (container_name, - object_name), - method='DELETE', - headers=headers, - cdn_request=True) - - return response.status == httplib.NO_CONTENT - - def ex_get_meta_data(self): - """ - Get meta data - - :rtype: ``dict`` - """ - response = self.connection.request('', method='HEAD') - - if response.status == httplib.NO_CONTENT: - container_count = response.headers.get( - 'x-account-container-count', 'unknown') - object_count = response.headers.get( - 'x-account-object-count', 'unknown') - bytes_used = response.headers.get( - 'x-account-bytes-used', 'unknown') - temp_url_key = response.headers.get( - 'x-account-meta-temp-url-key', None) - - return {'container_count': int(container_count), - 'object_count': int(object_count), - 'bytes_used': int(bytes_used), - 'temp_url_key': temp_url_key} - - raise LibcloudError('Unexpected status code: %s' % (response.status)) - - def ex_multipart_upload_object(self, file_path, container, object_name, - chunk_size=33554432, extra=None, - verify_hash=True): - object_size = os.path.getsize(file_path) - if object_size < chunk_size: - return self.upload_object(file_path, container, object_name, - extra=extra, verify_hash=verify_hash) - - iter_chunk_reader = FileChunkReader(file_path, chunk_size) - - for index, iterator in enumerate(iter_chunk_reader): - self._upload_object_part(container=container, - object_name=object_name, - part_number=index, - iterator=iterator, - verify_hash=verify_hash) - - return self._upload_object_manifest(container=container, - object_name=object_name, - extra=extra, - verify_hash=verify_hash) - - def ex_enable_static_website(self, container, index_file='index.html'): - """ - Enable serving a static website. - - :param container: Container instance - :type container: :class:`Container` - - :param index_file: Name of the object which becomes an index page for - every sub-directory in this container. - :type index_file: ``str`` - - :rtype: ``bool`` - """ - container_name = container.name - headers = {'X-Container-Meta-Web-Index': index_file} - - response = self.connection.request('/%s' % (container_name), - method='POST', - headers=headers, - cdn_request=False) - - return response.status in [httplib.CREATED, httplib.ACCEPTED] - - def ex_set_error_page(self, container, file_name='error.html'): - """ - Set a custom error page which is displayed if file is not found and - serving of a static website is enabled. - - :param container: Container instance - :type container: :class:`Container` - - :param file_name: Name of the object which becomes the error page. - :type file_name: ``str`` - - :rtype: ``bool`` - """ - container_name = container.name - headers = {'X-Container-Meta-Web-Error': file_name} - - response = self.connection.request('/%s' % (container_name), - method='POST', - headers=headers, - cdn_request=False) - - return response.status in [httplib.CREATED, httplib.ACCEPTED] - - def ex_set_account_metadata_temp_url_key(self, key): - """ - Set the metadata header X-Account-Meta-Temp-URL-Key on your Cloud - Files account. - - :param key: X-Account-Meta-Temp-URL-Key - :type key: ``str`` - - :rtype: ``bool`` - """ - headers = {'X-Account-Meta-Temp-URL-Key': key} - - response = self.connection.request('', - method='POST', - headers=headers, - cdn_request=False) - - return response.status in [httplib.OK, httplib.NO_CONTENT, - httplib.CREATED, httplib.ACCEPTED] - - def ex_get_object_temp_url(self, obj, method='GET', timeout=60): - """ - Create a temporary URL to allow others to retrieve or put objects - in your Cloud Files account for as long or as short a time as you - wish. This method is specifically for allowing users to retrieve - or update an object. - - :param obj: The object that you wish to make temporarily public - :type obj: :class:`Object` - - :param method: Which method you would like to allow, 'PUT' or 'GET' - :type method: ``str`` - - :param timeout: Time (in seconds) after which you want the TempURL - to expire. - :type timeout: ``int`` - - :rtype: ``bool`` - """ - self.connection._populate_hosts_and_request_paths() - expires = int(time() + timeout) - path = '%s/%s/%s' % (self.connection.request_path, - obj.container.name, obj.name) - try: - key = self.ex_get_meta_data()['temp_url_key'] - assert key is not None - except Exception: - raise KeyError('You must first set the ' + - 'X-Account-Meta-Temp-URL-Key header on your ' + - 'Cloud Files account using ' + - 'ex_set_account_metadata_temp_url_key before ' + - 'you can use this method.') - hmac_body = '%s\n%s\n%s' % (method, expires, path) - sig = hmac.new(b(key), b(hmac_body), sha1).hexdigest() - params = urlencode({'temp_url_sig': sig, - 'temp_url_expires': expires}) - - temp_url = 'https://%s/%s/%s?%s' %\ - (self.connection.host + self.connection.request_path, - obj.container.name, obj.name, params) - - return temp_url - - def _upload_object_part(self, container, object_name, part_number, - iterator, verify_hash=True): - upload_func = self._stream_data - upload_func_kwargs = {'iterator': iterator} - part_name = object_name + '/%08d' % part_number - extra = {'content_type': 'application/octet-stream'} - - self._put_object(container=container, - object_name=part_name, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - extra=extra, iterator=iterator, - verify_hash=verify_hash) - - def _upload_object_manifest(self, container, object_name, extra=None, - verify_hash=True): - extra = extra or {} - meta_data = extra.get('meta_data') - - container_name_encoded = self._encode_container_name(container.name) - object_name_encoded = self._encode_object_name(object_name) - request_path = '/%s/%s' % (container_name_encoded, object_name_encoded) - - headers = {'X-Auth-Token': self.connection.auth_token, - 'X-Object-Manifest': '%s/%s/' % - (container_name_encoded, - object_name_encoded)} - - data = '' - response = self.connection.request(request_path, - method='PUT', data=data, - headers=headers, raw=True) - - object_hash = None - - if verify_hash: - hash_function = self._get_hash_function() - hash_function.update(b(data)) - data_hash = hash_function.hexdigest() - object_hash = response.headers.get('etag') - - if object_hash != data_hash: - raise ObjectHashMismatchError( - value=('MD5 hash checksum does not match (expected=%s, ' + - 'actual=%s)') % - (data_hash, object_hash), - object_name=object_name, driver=self) - - obj = Object(name=object_name, size=0, hash=object_hash, extra=None, - meta_data=meta_data, container=container, driver=self) - - return obj - - def list_container_objects(self, container, ex_prefix=None): - """ - Return a list of objects for the given container. - - :param container: Container instance. - :type container: :class:`Container` - - :param ex_prefix: Only get objects with names starting with ex_prefix - :type ex_prefix: ``str`` - - :return: A list of Object instances. - :rtype: ``list`` of :class:`Object` - """ - return list(self.iterate_container_objects(container, - ex_prefix=ex_prefix)) - - def iterate_container_objects(self, container, ex_prefix=None): - """ - Return a generator of objects for the given container. - - :param container: Container instance - :type container: :class:`Container` - - :param ex_prefix: Only get objects with names starting with ex_prefix - :type ex_prefix: ``str`` - - :return: A generator of Object instances. - :rtype: ``generator`` of :class:`Object` - """ - params = {} - if ex_prefix: - params['prefix'] = ex_prefix - - while True: - container_name_encoded = \ - self._encode_container_name(container.name) - response = self.connection.request('/%s' % - (container_name_encoded), - params=params) - - if response.status == httplib.NO_CONTENT: - # Empty or non-existent container - break - elif response.status == httplib.OK: - objects = self._to_object_list(json.loads(response.body), - container) - - if len(objects) == 0: - break - - for obj in objects: - yield obj - params['marker'] = obj.name - - else: - raise LibcloudError('Unexpected status code: %s' % - (response.status)) - - def _put_object(self, container, object_name, upload_func, - upload_func_kwargs, extra=None, file_path=None, - iterator=None, verify_hash=True): - extra = extra or {} - container_name_encoded = self._encode_container_name(container.name) - object_name_encoded = self._encode_object_name(object_name) - content_type = extra.get('content_type', None) - meta_data = extra.get('meta_data', None) - content_disposition = extra.get('content_disposition', None) - - headers = {} - if meta_data: - for key, value in list(meta_data.items()): - key = 'X-Object-Meta-%s' % (key) - headers[key] = value - - if content_disposition is not None: - headers['Content-Disposition'] = content_disposition - - request_path = '/%s/%s' % (container_name_encoded, object_name_encoded) - result_dict = self._upload_object( - object_name=object_name, content_type=content_type, - upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, - request_path=request_path, request_method='PUT', - headers=headers, file_path=file_path, iterator=iterator) - - response = result_dict['response'].response - bytes_transferred = result_dict['bytes_transferred'] - server_hash = result_dict['response'].headers.get('etag', None) - - if response.status == httplib.EXPECTATION_FAILED: - raise LibcloudError(value='Missing content-type header', - driver=self) - elif verify_hash and not server_hash: - raise LibcloudError(value='Server didn\'t return etag', - driver=self) - elif (verify_hash and result_dict['data_hash'] != server_hash): - raise ObjectHashMismatchError( - value=('MD5 hash checksum does not match (expected=%s, ' + - 'actual=%s)') % (result_dict['data_hash'], server_hash), - object_name=object_name, driver=self) - elif response.status == httplib.CREATED: - obj = Object( - name=object_name, size=bytes_transferred, hash=server_hash, - extra=None, meta_data=meta_data, container=container, - driver=self) - - return obj - else: - # @TODO: Add test case for this condition (probably 411) - raise LibcloudError('status_code=%s' % (response.status), - driver=self) - - def _encode_container_name(self, name): - """ - Encode container name so it can be used as part of the HTTP request. - """ - if name.startswith('/'): - name = name[1:] - name = urlquote(name) - - if name.find('/') != -1: - raise InvalidContainerNameError(value='Container name cannot' - ' contain slashes', - container_name=name, driver=self) - - if len(name) > 256: - raise InvalidContainerNameError( - value='Container name cannot be longer than 256 bytes', - container_name=name, driver=self) - - return name - - def _encode_object_name(self, name): - name = urlquote(name) - return name - - def _to_container_list(self, response): - # @TODO: Handle more than 10k containers - use "lazy list"? - for container in response: - extra = {'object_count': int(container['count']), - 'size': int(container['bytes'])} - yield Container(name=container['name'], extra=extra, driver=self) - - def _to_object_list(self, response, container): - objects = [] - - for obj in response: - name = obj['name'] - size = int(obj['bytes']) - hash = obj['hash'] - extra = {'content_type': obj['content_type'], - 'last_modified': obj['last_modified']} - objects.append(Object( - name=name, size=size, hash=hash, extra=extra, - meta_data=None, container=container, driver=self)) - - return objects - - def _headers_to_container(self, name, headers): - size = int(headers.get('x-container-bytes-used', 0)) - object_count = int(headers.get('x-container-object-count', 0)) - - extra = {'object_count': object_count, - 'size': size} - container = Container(name=name, extra=extra, driver=self) - return container - - def _headers_to_object(self, name, container, headers): - size = int(headers.pop('content-length', 0)) - last_modified = headers.pop('last-modified', None) - etag = headers.pop('etag', None) - content_type = headers.pop('content-type', None) - - meta_data = {} - for key, value in list(headers.items()): - if key.find('x-object-meta-') != -1: - key = key.replace('x-object-meta-', '') - meta_data[key] = value - - extra = {'content_type': content_type, 'last_modified': last_modified} - - obj = Object(name=name, size=size, hash=etag, extra=extra, - meta_data=meta_data, container=container, driver=self) - return obj - - def _ex_connection_class_kwargs(self): - kwargs = self.openstack_connection_kwargs() - kwargs['ex_force_service_region'] = self.region - kwargs['use_internal_url'] = self.use_internal_url - return kwargs - - -class CloudFilesUSStorageDriver(CloudFilesStorageDriver): - """ - Cloudfiles storage driver for the US endpoint. - """ - - type = Provider.CLOUDFILES_US - name = 'CloudFiles (US)' - - def __init__(self, *args, **kwargs): - kwargs['region'] = 'ord' - super(CloudFilesUSStorageDriver, self).__init__(*args, **kwargs) - - -class OpenStackSwiftStorageDriver(CloudFilesStorageDriver): - """ - Storage driver for the OpenStack Swift. - """ - type = Provider.CLOUDFILES_SWIFT - name = 'OpenStack Swift' - connectionCls = OpenStackSwiftConnection - - # TODO: Reverse the relationship - Swift -> CloudFiles - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - region=None, **kwargs): - super(OpenStackSwiftStorageDriver, self).__init__(key=key, - secret=secret, - secure=secure, - host=host, - port=port, - region=region, - **kwargs) - - -class CloudFilesUKStorageDriver(CloudFilesStorageDriver): - """ - Cloudfiles storage driver for the UK endpoint. - """ - - type = Provider.CLOUDFILES_UK - name = 'CloudFiles (UK)' - - def __init__(self, *args, **kwargs): - kwargs['region'] = 'lon' - super(CloudFilesUKStorageDriver, self).__init__(*args, **kwargs) - - -class FileChunkReader(object): - def __init__(self, file_path, chunk_size): - self.file_path = file_path - self.total = os.path.getsize(file_path) - self.chunk_size = chunk_size - self.bytes_read = 0 - self.stop_iteration = False - - def __iter__(self): - return self - - def next(self): - if self.stop_iteration: - raise StopIteration - - start_block = self.bytes_read - end_block = start_block + self.chunk_size - if end_block >= self.total: - end_block = self.total - self.stop_iteration = True - self.bytes_read += end_block - start_block - return ChunkStreamReader(file_path=self.file_path, - start_block=start_block, - end_block=end_block, - chunk_size=8192) - - def __next__(self): - return self.next() - - -class ChunkStreamReader(object): - def __init__(self, file_path, start_block, end_block, chunk_size): - self.fd = open(file_path, 'rb') - self.fd.seek(start_block) - self.start_block = start_block - self.end_block = end_block - self.chunk_size = chunk_size - self.bytes_read = 0 - self.stop_iteration = False - - def __iter__(self): - return self - - def next(self): - if self.stop_iteration: - self.fd.close() - raise StopIteration - - block_size = self.chunk_size - if self.bytes_read + block_size > \ - self.end_block - self.start_block: - block_size = self.end_block - self.start_block - self.bytes_read - self.stop_iteration = True - - block = self.fd.read(block_size) - self.bytes_read += block_size - return block - - def __next__(self): - return self.next() diff --git a/awx/lib/site-packages/libcloud/storage/drivers/dummy.py b/awx/lib/site-packages/libcloud/storage/drivers/dummy.py deleted file mode 100644 index affd265538..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/dummy.py +++ /dev/null @@ -1,490 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os.path -import random -import hashlib - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import b - -if PY3: - from io import FileIO as file - -from libcloud.common.types import LibcloudError - -from libcloud.storage.base import Object, Container, StorageDriver -from libcloud.storage.types import ContainerAlreadyExistsError -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import ObjectDoesNotExistError - - -class DummyFileObject(file): - def __init__(self, yield_count=5, chunk_len=10): - self._yield_count = yield_count - self._chunk_len = chunk_len - - def read(self, size): - i = 0 - - while i < self._yield_count: - yield self._get_chunk(self._chunk_len) - i += 1 - - raise StopIteration - - def _get_chunk(self, chunk_len): - chunk = [str(x) for x in random.randint(97, 120)] - return chunk - - def __len__(self): - return self._yield_count * self._chunk_len - - -class DummyIterator(object): - def __init__(self, data=None): - self.hash = hashlib.md5() - self._data = data or [] - self._current_item = 0 - - def get_md5_hash(self): - return self.hash.hexdigest() - - def next(self): - if self._current_item == len(self._data): - raise StopIteration - - value = self._data[self._current_item] - self.hash.update(b(value)) - self._current_item += 1 - return value - - def __next__(self): - return self.next() - - -class DummyStorageDriver(StorageDriver): - """ - Dummy Storage driver. - - >>> from libcloud.storage.drivers.dummy import DummyStorageDriver - >>> driver = DummyStorageDriver('key', 'secret') - >>> container = driver.create_container(container_name='test container') - >>> container - <Container: name=test container, provider=Dummy Storage Provider> - >>> container.name - 'test container' - >>> container.extra['object_count'] - 0 - """ - - name = 'Dummy Storage Provider' - website = 'http://example.com' - - def __init__(self, api_key, api_secret): - """ - :param api_key: API key or username to used (required) - :type api_key: ``str`` - :param api_secret: Secret password to be used (required) - :type api_secret: ``str`` - :rtype: ``None`` - """ - self._containers = {} - - def get_meta_data(self): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> driver.get_meta_data()['object_count'] - 0 - >>> driver.get_meta_data()['container_count'] - 0 - >>> driver.get_meta_data()['bytes_used'] - 0 - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container_name = 'test container 2' - >>> container = driver.create_container(container_name=container_name) - >>> obj = container.upload_object_via_stream( - ... object_name='test object', iterator=DummyFileObject(5, 10), - ... extra={}) - >>> driver.get_meta_data()['object_count'] - 1 - >>> driver.get_meta_data()['container_count'] - 2 - >>> driver.get_meta_data()['bytes_used'] - 50 - - :rtype: ``dict`` - """ - - container_count = len(self._containers) - object_count = sum([len(self._containers[container]['objects']) for - container in self._containers]) - - bytes_used = 0 - for container in self._containers: - objects = self._containers[container]['objects'] - for _, obj in objects.items(): - bytes_used += obj.size - - return {'container_count': int(container_count), - 'object_count': int(object_count), - 'bytes_used': int(bytes_used)} - - def iterate_containers(self): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> list(driver.iterate_containers()) - [] - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container - <Container: name=test container 1, provider=Dummy Storage Provider> - >>> container.name - 'test container 1' - >>> container_name = 'test container 2' - >>> container = driver.create_container(container_name=container_name) - >>> container - <Container: name=test container 2, provider=Dummy Storage Provider> - >>> container = driver.create_container( - ... container_name='test container 2') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ContainerAlreadyExistsError: - >>> container_list=list(driver.iterate_containers()) - >>> sorted([c.name for c in container_list]) - ['test container 1', 'test container 2'] - - @inherits: :class:`StorageDriver.iterate_containers` - """ - - for container in list(self._containers.values()): - yield container['container'] - - def list_container_objects(self, container): - container = self.get_container(container.name) - - return container.objects - - def get_container(self, container_name): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> driver.get_container('unknown') #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ContainerDoesNotExistError: - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container - <Container: name=test container 1, provider=Dummy Storage Provider> - >>> container.name - 'test container 1' - >>> driver.get_container('test container 1') - <Container: name=test container 1, provider=Dummy Storage Provider> - - @inherits: :class:`StorageDriver.get_container` - """ - - if container_name not in self._containers: - raise ContainerDoesNotExistError(driver=self, value=None, - container_name=container_name) - - return self._containers[container_name]['container'] - - def get_container_cdn_url(self, container): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> driver.get_container('unknown') #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ContainerDoesNotExistError: - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container - <Container: name=test container 1, provider=Dummy Storage Provider> - >>> container.name - 'test container 1' - >>> container.get_cdn_url() - 'http://www.test.com/container/test_container_1' - - @inherits: :class:`StorageDriver.get_container_cdn_url` - """ - - if container.name not in self._containers: - raise ContainerDoesNotExistError(driver=self, value=None, - container_name=container.name) - - return self._containers[container.name]['cdn_url'] - - def get_object(self, container_name, object_name): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> driver.get_object('unknown', 'unknown') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ContainerDoesNotExistError: - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container - <Container: name=test container 1, provider=Dummy Storage Provider> - >>> driver.get_object( - ... 'test container 1', 'unknown') #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ObjectDoesNotExistError: - >>> obj = container.upload_object_via_stream(object_name='test object', - ... iterator=DummyFileObject(5, 10), extra={}) - >>> obj.name - 'test object' - >>> obj.size - 50 - - @inherits: :class:`StorageDriver.get_object` - """ - - self.get_container(container_name) - container_objects = self._containers[container_name]['objects'] - if object_name not in container_objects: - raise ObjectDoesNotExistError(object_name=object_name, value=None, - driver=self) - - return container_objects[object_name] - - def get_object_cdn_url(self, obj): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container - <Container: name=test container 1, provider=Dummy Storage Provider> - >>> obj = container.upload_object_via_stream( - ... object_name='test object 5', - ... iterator=DummyFileObject(5, 10), extra={}) - >>> obj.name - 'test object 5' - >>> obj.get_cdn_url() - 'http://www.test.com/object/test_object_5' - - @inherits: :class:`StorageDriver.get_object_cdn_url` - """ - - container_name = obj.container.name - container_objects = self._containers[container_name]['objects'] - if obj.name not in container_objects: - raise ObjectDoesNotExistError(object_name=obj.name, value=None, - driver=self) - - return container_objects[obj.name].meta_data['cdn_url'] - - def create_container(self, container_name): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container - <Container: name=test container 1, provider=Dummy Storage Provider> - >>> container = driver.create_container( - ... container_name='test container 1') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ContainerAlreadyExistsError: - - @inherits: :class:`StorageDriver.create_container` - """ - - if container_name in self._containers: - raise ContainerAlreadyExistsError(container_name=container_name, - value=None, driver=self) - - extra = {'object_count': 0} - container = Container(name=container_name, extra=extra, driver=self) - - self._containers[container_name] = {'container': container, - 'objects': {}, - 'cdn_url': - 'http://www.test.com/container/%s' - % - (container_name.replace(' ', '_')) - } - return container - - def delete_container(self, container): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> container = Container(name = 'test container', - ... extra={'object_count': 0}, driver=driver) - >>> driver.delete_container(container=container) - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ContainerDoesNotExistError: - >>> container = driver.create_container( - ... container_name='test container 1') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - >>> len(driver._containers) - 1 - >>> driver.delete_container(container=container) - True - >>> len(driver._containers) - 0 - >>> container = driver.create_container( - ... container_name='test container 1') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - >>> obj = container.upload_object_via_stream( - ... object_name='test object', iterator=DummyFileObject(5, 10), - ... extra={}) - >>> driver.delete_container(container=container) - ... #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ContainerIsNotEmptyError: - - @inherits: :class:`StorageDriver.delete_container` - """ - - container_name = container.name - if container_name not in self._containers: - raise ContainerDoesNotExistError(container_name=container_name, - value=None, driver=self) - - container = self._containers[container_name] - if len(container['objects']) > 0: - raise ContainerIsNotEmptyError(container_name=container_name, - value=None, driver=self) - - del self._containers[container_name] - return True - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - kwargs_dict = {'obj': obj, - 'response': DummyFileObject(), - 'destination_path': destination_path, - 'overwrite_existing': overwrite_existing, - 'delete_on_failure': delete_on_failure} - - return self._save_object(**kwargs_dict) - - def download_object_as_stream(self, obj, chunk_size=None): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> container = driver.create_container( - ... container_name='test container 1') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - >>> obj = container.upload_object_via_stream(object_name='test object', - ... iterator=DummyFileObject(5, 10), extra={}) - >>> stream = container.download_object_as_stream(obj) - >>> stream #doctest: +ELLIPSIS - <...closed...> - - @inherits: :class:`StorageDriver.download_object_as_stream` - """ - - return DummyFileObject() - - def upload_object(self, file_path, container, object_name, extra=None, - file_hash=None): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> container_name = 'test container 1' - >>> container = driver.create_container(container_name=container_name) - >>> container.upload_object(file_path='/tmp/inexistent.file', - ... object_name='test') #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - LibcloudError: - >>> file_path = path = os.path.abspath(__file__) - >>> file_size = os.path.getsize(file_path) - >>> obj = container.upload_object(file_path=file_path, - ... object_name='test') - >>> obj #doctest: +ELLIPSIS - <Object: name=test, size=...> - >>> obj.size == file_size - True - - @inherits: :class:`StorageDriver.upload_object` - :param file_hash: File hash - :type file_hash: ``str`` - """ - - if not os.path.exists(file_path): - raise LibcloudError(value='File %s does not exist' % (file_path), - driver=self) - - size = os.path.getsize(file_path) - return self._add_object(container=container, object_name=object_name, - size=size, extra=extra) - - def upload_object_via_stream(self, iterator, container, - object_name, extra=None): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> container = driver.create_container( - ... container_name='test container 1') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - >>> obj = container.upload_object_via_stream( - ... object_name='test object', iterator=DummyFileObject(5, 10), - ... extra={}) - >>> obj #doctest: +ELLIPSIS - <Object: name=test object, size=50, ...> - - @inherits: :class:`StorageDriver.upload_object_via_stream` - """ - - size = len(iterator) - return self._add_object(container=container, object_name=object_name, - size=size, extra=extra) - - def delete_object(self, obj): - """ - >>> driver = DummyStorageDriver('key', 'secret') - >>> container = driver.create_container( - ... container_name='test container 1') - ... #doctest: +IGNORE_EXCEPTION_DETAIL - >>> obj = container.upload_object_via_stream(object_name='test object', - ... iterator=DummyFileObject(5, 10), extra={}) - >>> obj #doctest: +ELLIPSIS - <Object: name=test object, size=50, ...> - >>> container.delete_object(obj=obj) - True - >>> obj = Object(name='test object 2', - ... size=1000, hash=None, extra=None, - ... meta_data=None, container=container,driver=None) - >>> container.delete_object(obj=obj) #doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ObjectDoesNotExistError: - - @inherits: :class:`StorageDriver.delete_object` - """ - - container_name = obj.container.name - object_name = obj.name - obj = self.get_object(container_name=container_name, - object_name=object_name) - - del self._containers[container_name]['objects'][object_name] - return True - - def _add_object(self, container, object_name, size, extra=None): - container = self.get_container(container.name) - - extra = extra or {} - meta_data = extra.get('meta_data', {}) - meta_data.update({'cdn_url': 'http://www.test.com/object/%s' % - (object_name.replace(' ', '_'))}) - obj = Object(name=object_name, size=size, extra=extra, hash=None, - meta_data=meta_data, container=container, driver=self) - - self._containers[container.name]['objects'][object_name] = obj - return obj - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/awx/lib/site-packages/libcloud/storage/drivers/google_storage.py b/awx/lib/site-packages/libcloud/storage/drivers/google_storage.py deleted file mode 100644 index 9caca9b9ee..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/google_storage.py +++ /dev/null @@ -1,136 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import copy -import hmac - -from email.utils import formatdate -from hashlib import sha1 - -from libcloud.utils.py3 import b - -from libcloud.common.base import ConnectionUserAndKey - -from libcloud.storage.drivers.s3 import BaseS3StorageDriver, S3Response -from libcloud.storage.drivers.s3 import S3RawResponse - -SIGNATURE_IDENTIFIER = 'GOOG1' - -# Docs are a lie. Actual namespace returned is different that the one listed in -# the docs. -AUTH_HOST = 'commondatastorage.googleapis.com' -API_VERSION = '2006-03-01' -NAMESPACE = 'http://doc.s3.amazonaws.com/%s' % (API_VERSION) - - -class GoogleStorageConnection(ConnectionUserAndKey): - """ - Repersents a single connection to the Google storage API endpoint. - """ - - host = AUTH_HOST - responseCls = S3Response - rawResponseCls = S3RawResponse - - def add_default_headers(self, headers): - date = formatdate(usegmt=True) - headers['Date'] = date - return headers - - def pre_connect_hook(self, params, headers): - signature = self._get_aws_auth_param(method=self.method, - headers=headers, - params=params, - expires=None, - secret_key=self.key, - path=self.action) - headers['Authorization'] = '%s %s:%s' % (SIGNATURE_IDENTIFIER, - self.user_id, signature) - return params, headers - - def _get_aws_auth_param(self, method, headers, params, expires, - secret_key, path='/'): - # TODO: Refactor and re-use in S3 driver - """ - Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID, - UTF-8-Encoding-Of( StringToSign ) ) ) ); - - StringToSign = HTTP-VERB + "\n" + - Content-MD5 + "\n" + - Content-Type + "\n" + - Date + "\n" + - CanonicalizedHeaders + - CanonicalizedResource; - """ - special_header_keys = ['content-md5', 'content-type', 'date'] - special_header_values = {} - extension_header_values = {} - - headers_copy = copy.deepcopy(headers) - for key, value in list(headers_copy.items()): - if key.lower() in special_header_keys: - if key.lower() == 'date': - value = value.strip() - else: - value = value.lower().strip() - special_header_values[key.lower()] = value - elif key.lower().startswith('x-goog-'): - extension_header_values[key.lower()] = value.strip() - - if 'content-md5' not in special_header_values: - special_header_values['content-md5'] = '' - - if 'content-type' not in special_header_values: - special_header_values['content-type'] = '' - - keys_sorted = list(special_header_values.keys()) - keys_sorted.sort() - - buf = [method] - for key in keys_sorted: - value = special_header_values[key] - buf.append(value) - string_to_sign = '\n'.join(buf) - - keys_sorted = list(extension_header_values.keys()) - keys_sorted.sort() - - extension_header_string = [] - for key in keys_sorted: - value = extension_header_values[key] - extension_header_string.append('%s:%s' % (key, value)) - extension_header_string = '\n'.join(extension_header_string) - - values_to_sign = [] - for value in [string_to_sign, extension_header_string, path]: - if value: - values_to_sign.append(value) - - string_to_sign = '\n'.join(values_to_sign) - b64_hmac = base64.b64encode( - hmac.new(b(secret_key), b(string_to_sign), digestmod=sha1).digest() - ) - return b64_hmac.decode('utf-8') - - -class GoogleStorageDriver(BaseS3StorageDriver): - name = 'Google Storage' - website = 'http://cloud.google.com/' - connectionCls = GoogleStorageConnection - hash_type = 'md5' - namespace = NAMESPACE - supports_chunked_encoding = False - supports_s3_multipart_upload = False diff --git a/awx/lib/site-packages/libcloud/storage/drivers/ktucloud.py b/awx/lib/site-packages/libcloud/storage/drivers/ktucloud.py deleted file mode 100644 index 9708a9b3c4..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/ktucloud.py +++ /dev/null @@ -1,52 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.common.types import LibcloudError -from libcloud.storage.providers import Provider - -from libcloud.storage.drivers.cloudfiles import CloudFilesConnection -from libcloud.storage.drivers.cloudfiles import CloudFilesStorageDriver - -KTUCLOUDSTORAGE_AUTH_URL = "https://ssproxy.ucloudbiz.olleh.com/auth/v1.0" -KTUCLOUDSTORAGE_API_VERSION = "1.0" - - -class KTUCloudStorageConnection(CloudFilesConnection): - """ - Connection class for the KT UCloud Storage endpoint. - """ - - auth_url = KTUCLOUDSTORAGE_AUTH_URL - _auth_version = KTUCLOUDSTORAGE_API_VERSION - - def get_endpoint(self): - eps = self.service_catalog.get_endpoints(name='cloudFiles') - if len(eps) == 0: - raise LibcloudError('Could not find specified endpoint') - ep = eps[0] - if 'publicURL' in ep: - return ep['publicURL'] - else: - raise LibcloudError('Could not find specified endpoint') - - -class KTUCloudStorageDriver(CloudFilesStorageDriver): - """ - Cloudfiles storage driver for the UK endpoint. - """ - - type = Provider.KTUCLOUD - name = 'KTUCloud Storage' - connectionCls = KTUCloudStorageConnection diff --git a/awx/lib/site-packages/libcloud/storage/drivers/local.py b/awx/lib/site-packages/libcloud/storage/drivers/local.py deleted file mode 100644 index 5e326f902e..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/local.py +++ /dev/null @@ -1,600 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Provides storage driver for working with local filesystem -""" - -from __future__ import with_statement - -import errno -import os -import shutil -import sys - -try: - import lockfile - from lockfile import LockTimeout, mkdirlockfile -except ImportError: - raise ImportError('Missing lockfile dependency, you can install it ' - 'using pip: pip install lockfile') - -from libcloud.utils.files import read_in_chunks -from libcloud.utils.py3 import relpath -from libcloud.utils.py3 import u -from libcloud.common.base import Connection -from libcloud.storage.base import Object, Container, StorageDriver -from libcloud.common.types import LibcloudError -from libcloud.storage.types import ContainerAlreadyExistsError -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import ObjectError -from libcloud.storage.types import ObjectDoesNotExistError -from libcloud.storage.types import InvalidContainerNameError - -IGNORE_FOLDERS = ['.lock', '.hash'] - - -class LockLocalStorage(object): - """ - A class to help in locking a local path before being updated - """ - def __init__(self, path): - self.path = path - self.lock = mkdirlockfile.MkdirLockFile(self.path, threaded=True) - - def __enter__(self): - try: - self.lock.acquire(timeout=0.1) - except LockTimeout: - raise LibcloudError('Lock timeout') - - def __exit__(self, type, value, traceback): - if self.lock.is_locked(): - self.lock.release() - - if value is not None: - raise value - - -class LocalStorageDriver(StorageDriver): - """ - Implementation of local file-system based storage. This is helpful - where the user would want to use the same code (using libcloud) and - switch between cloud storage and local storage - """ - - connectionCls = Connection - name = 'Local Storage' - website = 'http://example.com' - hash_type = 'md5' - - def __init__(self, key, secret=None, secure=True, host=None, port=None, - **kwargs): - - # Use the key as the path to the storage - self.base_path = key - - if not os.path.isdir(self.base_path): - raise LibcloudError('The base path is not a directory') - - super(StorageDriver, self).__init__(key=key, secret=secret, - secure=secure, host=host, - port=port, **kwargs) - - def _make_path(self, path, ignore_existing=True): - """ - Create a path by checking if it already exists - """ - - try: - os.makedirs(path) - except OSError: - exp = sys.exc_info()[1] - if exp.errno == errno.EEXIST and not ignore_existing: - raise exp - - def _check_container_name(self, container_name): - """ - Check if the container name is valid - - :param container_name: Container name - :type container_name: ``str`` - """ - - if '/' in container_name or '\\' in container_name: - raise InvalidContainerNameError(value=None, driver=self, - container_name=container_name) - - def _make_container(self, container_name): - """ - Create a container instance - - :param container_name: Container name. - :type container_name: ``str`` - - :return: Container instance. - :rtype: :class:`Container` - """ - - self._check_container_name(container_name) - - full_path = os.path.join(self.base_path, container_name) - - try: - stat = os.stat(full_path) - if not os.path.isdir(full_path): - raise OSError('Target path is not a directory') - except OSError: - raise ContainerDoesNotExistError(value=None, driver=self, - container_name=container_name) - - extra = {} - extra['creation_time'] = stat.st_ctime - extra['access_time'] = stat.st_atime - extra['modify_time'] = stat.st_mtime - - return Container(name=container_name, extra=extra, driver=self) - - def _make_object(self, container, object_name): - """ - Create an object instance - - :param container: Container. - :type container: :class:`Container` - - :param object_name: Object name. - :type object_name: ``str`` - - :return: Object instance. - :rtype: :class:`Object` - """ - - full_path = os.path.join(self.base_path, container.name, object_name) - - if os.path.isdir(full_path): - raise ObjectError(value=None, driver=self, object_name=object_name) - - try: - stat = os.stat(full_path) - except Exception: - raise ObjectDoesNotExistError(value=None, driver=self, - object_name=object_name) - - # Make a hash for the file based on the metadata. We can safely - # use only the mtime attribute here. If the file contents change, - # the underlying file-system will change mtime - data_hash = self._get_hash_function() - data_hash.update(u(stat.st_mtime).encode('ascii')) - data_hash = data_hash.hexdigest() - - extra = {} - extra['creation_time'] = stat.st_ctime - extra['access_time'] = stat.st_atime - extra['modify_time'] = stat.st_mtime - - return Object(name=object_name, size=stat.st_size, extra=extra, - driver=self, container=container, hash=data_hash, - meta_data=None) - - def iterate_containers(self): - """ - Return a generator of containers. - - :return: A generator of Container instances. - :rtype: ``generator`` of :class:`Container` - """ - - for container_name in os.listdir(self.base_path): - full_path = os.path.join(self.base_path, container_name) - if not os.path.isdir(full_path): - continue - yield self._make_container(container_name) - - def _get_objects(self, container): - """ - Recursively iterate through the file-system and return the object names - """ - - cpath = self.get_container_cdn_url(container, check=True) - - for folder, subfolders, files in os.walk(cpath, topdown=True): - # Remove unwanted subfolders - for subf in IGNORE_FOLDERS: - if subf in subfolders: - subfolders.remove(subf) - - for name in files: - full_path = os.path.join(folder, name) - object_name = relpath(full_path, start=cpath) - yield self._make_object(container, object_name) - - def iterate_container_objects(self, container): - """ - Returns a generator of objects for the given container. - - :param container: Container instance - :type container: :class:`Container` - - :return: A generator of Object instances. - :rtype: ``generator`` of :class:`Object` - """ - - return self._get_objects(container) - - def get_container(self, container_name): - """ - Return a container instance. - - :param container_name: Container name. - :type container_name: ``str`` - - :return: :class:`Container` instance. - :rtype: :class:`Container` - """ - return self._make_container(container_name) - - def get_container_cdn_url(self, container, check=False): - """ - Return a container CDN URL. - - :param container: Container instance - :type container: :class:`Container` - - :param check: Indicates if the path's existence must be checked - :type check: ``bool`` - - :return: A CDN URL for this container. - :rtype: ``str`` - """ - path = os.path.join(self.base_path, container.name) - - if check and not os.path.isdir(path): - raise ContainerDoesNotExistError(value=None, driver=self, - container_name=container.name) - - return path - - def get_object(self, container_name, object_name): - """ - Return an object instance. - - :param container_name: Container name. - :type container_name: ``str`` - - :param object_name: Object name. - :type object_name: ``str`` - - :return: :class:`Object` instance. - :rtype: :class:`Object` - """ - container = self._make_container(container_name) - return self._make_object(container, object_name) - - def get_object_cdn_url(self, obj): - """ - Return a object CDN URL. - - :param obj: Object instance - :type obj: :class:`Object` - - :return: A CDN URL for this object. - :rtype: ``str`` - """ - return os.path.join(self.base_path, obj.container.name, obj.name) - - def enable_container_cdn(self, container): - """ - Enable container CDN. - - :param container: Container instance - :type container: :class:`Container` - - :rtype: ``bool`` - """ - - path = self.get_container_cdn_url(container) - lockfile.MkdirFileLock(path, threaded=True) - - with LockLocalStorage(path): - self._make_path(path) - - return True - - def enable_object_cdn(self, obj): - """ - Enable object CDN. - - :param obj: Object instance - :type obj: :class:`Object` - - :rtype: ``bool`` - """ - path = self.get_object_cdn_url(obj) - - with LockLocalStorage(path): - if os.path.exists(path): - return False - try: - obj_file = open(path, 'w') - obj_file.close() - except: - return False - - return True - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - """ - Download an object to the specified destination path. - - :param obj: Object instance. - :type obj: :class:`Object` - - :param destination_path: Full path to a file or a directory where the - incoming file will be saved. - :type destination_path: ``str`` - - :param overwrite_existing: True to overwrite an existing file, - defaults to False. - :type overwrite_existing: ``bool`` - - :param delete_on_failure: True to delete a partially downloaded file if - the download was not successful (hash mismatch / file size). - :type delete_on_failure: ``bool`` - - :return: True if an object has been successfully downloaded, False - otherwise. - :rtype: ``bool`` - """ - - obj_path = self.get_object_cdn_url(obj) - base_name = os.path.basename(destination_path) - - if not base_name and not os.path.exists(destination_path): - raise LibcloudError( - value='Path %s does not exist' % (destination_path), - driver=self) - - if not base_name: - file_path = os.path.join(destination_path, obj.name) - else: - file_path = destination_path - - if os.path.exists(file_path) and not overwrite_existing: - raise LibcloudError( - value='File %s already exists, but ' % (file_path) + - 'overwrite_existing=False', - driver=self) - - try: - shutil.copy(obj_path, file_path) - except IOError: - if delete_on_failure: - try: - os.unlink(file_path) - except Exception: - pass - return False - - return True - - def download_object_as_stream(self, obj, chunk_size=None): - """ - Return a generator which yields object data. - - :param obj: Object instance - :type obj: :class:`Object` - - :param chunk_size: Optional chunk size (in bytes). - :type chunk_size: ``int`` - - :rtype: ``object`` - """ - - path = self.get_object_cdn_url(obj) - - with open(path) as obj_file: - for data in read_in_chunks(obj_file, chunk_size=chunk_size): - yield data - - def upload_object(self, file_path, container, object_name, extra=None, - verify_hash=True): - """ - Upload an object currently located on a disk. - - :param file_path: Path to the object on disk. - :type file_path: ``str`` - - :param container: Destination container. - :type container: :class:`Container` - - :param object_name: Object name. - :type object_name: ``str`` - - :param verify_hash: Verify hast - :type verify_hash: ``bool`` - - :param extra: (optional) Extra attributes (driver specific). - :type extra: ``dict`` - - :rtype: ``object`` - """ - - path = self.get_container_cdn_url(container, check=True) - obj_path = os.path.join(path, object_name) - base_path = os.path.dirname(obj_path) - - self._make_path(base_path) - - with LockLocalStorage(obj_path): - shutil.copy(file_path, obj_path) - - os.chmod(obj_path, int('664', 8)) - - return self._make_object(container, object_name) - - def upload_object_via_stream(self, iterator, container, - object_name, - extra=None): - """ - Upload an object using an iterator. - - If a provider supports it, chunked transfer encoding is used and you - don't need to know in advance the amount of data to be uploaded. - - Otherwise if a provider doesn't support it, iterator will be exhausted - so a total size for data to be uploaded can be determined. - - Note: Exhausting the iterator means that the whole data must be - buffered in memory which might result in memory exhausting when - uploading a very large object. - - If a file is located on a disk you are advised to use upload_object - function which uses fs.stat function to determine the file size and it - doesn't need to buffer whole object in the memory. - - :type iterator: ``object`` - :param iterator: An object which implements the iterator interface. - - :type container: :class:`Container` - :param container: Destination container. - - :type object_name: ``str`` - :param object_name: Object name. - - :type extra: ``dict`` - :param extra: (optional) Extra attributes (driver specific). Note: - This dictionary must contain a 'content_type' key which represents - a content type of the stored object. - - :rtype: ``object`` - """ - - path = self.get_container_cdn_url(container, check=True) - obj_path = os.path.join(path, object_name) - base_path = os.path.dirname(obj_path) - - self._make_path(base_path) - - with LockLocalStorage(obj_path): - obj_file = open(obj_path, 'w') - for data in iterator: - obj_file.write(data) - - obj_file.close() - - os.chmod(obj_path, int('664', 8)) - - return self._make_object(container, object_name) - - def delete_object(self, obj): - """ - Delete an object. - - :type obj: :class:`Object` - :param obj: Object instance. - - :return: ``bool`` True on success. - :rtype: ``bool`` - """ - - path = self.get_object_cdn_url(obj) - - with LockLocalStorage(path): - try: - os.unlink(path) - except Exception: - return False - - # Check and delete all the empty parent folders - path = os.path.dirname(path) - container_url = obj.container.get_cdn_url() - - # Delete the empty parent folders till the container's level - while path != container_url: - try: - os.rmdir(path) - except OSError: - exp = sys.exc_info()[1] - if exp.errno == errno.ENOTEMPTY: - break - raise exp - - path = os.path.dirname(path) - - return True - - def create_container(self, container_name): - """ - Create a new container. - - :type container_name: ``str`` - :param container_name: Container name. - - :return: :class:`Container` instance on success. - :rtype: :class:`Container` - """ - - self._check_container_name(container_name) - - path = os.path.join(self.base_path, container_name) - - try: - self._make_path(path, ignore_existing=False) - except OSError: - exp = sys.exc_info()[1] - if exp.errno == errno.EEXIST: - raise ContainerAlreadyExistsError( - value='Container with this name already exists. The name ' - 'must be unique among all the containers in the ' - 'system', - container_name=container_name, driver=self) - else: - raise LibcloudError( - 'Error creating container %s' % container_name, - driver=self) - except Exception: - raise LibcloudError( - 'Error creating container %s' % container_name, driver=self) - - return self._make_container(container_name) - - def delete_container(self, container): - """ - Delete a container. - - :type container: :class:`Container` - :param container: Container instance - - :return: True on success, False otherwise. - :rtype: ``bool`` - """ - - # Check if there are any objects inside this - for obj in self._get_objects(container): - raise ContainerIsNotEmptyError(value='Container is not empty', - container_name=container.name, - driver=self) - - path = self.get_container_cdn_url(container, check=True) - - with LockLocalStorage(path): - try: - shutil.rmtree(path) - except Exception: - return False - - return True diff --git a/awx/lib/site-packages/libcloud/storage/drivers/nimbus.py b/awx/lib/site-packages/libcloud/storage/drivers/nimbus.py deleted file mode 100644 index b649e8b306..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/nimbus.py +++ /dev/null @@ -1,114 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import time -import hashlib -import hmac - -try: - import simplejson as json -except ImportError: - import json # NOQA - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlencode - -from libcloud.common.base import ConnectionUserAndKey, JsonResponse -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.storage.base import Container, StorageDriver - - -class NimbusResponse(JsonResponse): - valid_response_codes = [httplib.OK, httplib.NOT_FOUND, httplib.CONFLICT, - httplib.BAD_REQUEST] - - def success(self): - return self.status in self.valid_response_codes - - def parse_error(self): - if self.status in [httplib.UNAUTHORIZED]: - raise InvalidCredsError(self.body) - raise LibcloudError('Unknown error. Status code: %d' % (self.status), - driver=self.driver) - - -class NimbusConnection(ConnectionUserAndKey): - host = 'nimbus.io' - responseCls = NimbusResponse - - def __init__(self, *args, **kwargs): - self.id = kwargs.pop('id') - super(NimbusConnection, self).__init__(*args, **kwargs) - - def pre_connect_hook(self, params, headers): - timestamp = str(int(time.time())) - signature = self._calculate_signature(user_id=self.user_id, - method=self.method, - params=params, - path=self.action, - timestamp=timestamp, - key=self.key) - headers['X-NIMBUS-IO-Timestamp'] = timestamp - headers['Authorization'] = 'NIMBUS.IO %s:%s' % (self.id, signature) - return params, headers - - def _calculate_signature(self, user_id, method, params, path, timestamp, - key): - if params: - uri_path = path + '?' + urlencode(params) - else: - uri_path = path - - string_to_sign = [user_id, method, str(timestamp), uri_path] - string_to_sign = '\n'.join(string_to_sign) - - hmac_value = hmac.new(key, string_to_sign, hashlib.sha256) - return hmac_value.hexdigest() - - -class NimbusStorageDriver(StorageDriver): - name = 'Nimbus.io' - website = 'https://nimbus.io/' - connectionCls = NimbusConnection - - def __init__(self, *args, **kwargs): - self.user_id = kwargs['user_id'] - super(NimbusStorageDriver, self).__init__(*args, **kwargs) - - def iterate_containers(self): - response = self.connection.request('/customers/%s/collections' % - (self.connection.user_id)) - return self._to_containers(response.object) - - def create_container(self, container_name): - params = {'action': 'create', 'name': container_name} - response = self.connection.request('/customers/%s/collections' % - (self.connection.user_id), - params=params, - method='POST') - return self._to_container(response.object) - - def _to_containers(self, data): - for item in data: - yield self._to_container(item) - - def _to_container(self, data): - name = data[0] - extra = {'date_created': data[2]} - return Container(name=name, extra=extra, driver=self) - - def _ex_connection_class_kwargs(self): - result = {'id': self.user_id} - return result diff --git a/awx/lib/site-packages/libcloud/storage/drivers/ninefold.py b/awx/lib/site-packages/libcloud/storage/drivers/ninefold.py deleted file mode 100644 index fbdf567842..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/ninefold.py +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.storage.providers import Provider -from libcloud.storage.drivers.atmos import AtmosDriver - - -class NinefoldStorageDriver(AtmosDriver): - host = 'api.ninefold.com' - path = '/storage/v1.0' - - type = Provider.NINEFOLD - name = 'Ninefold' - website = 'http://ninefold.com/' diff --git a/awx/lib/site-packages/libcloud/storage/drivers/s3.py b/awx/lib/site-packages/libcloud/storage/drivers/s3.py deleted file mode 100644 index 9577f98369..0000000000 --- a/awx/lib/site-packages/libcloud/storage/drivers/s3.py +++ /dev/null @@ -1,975 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import time -import copy -import base64 -import hmac -import sys - -from hashlib import sha1 - -try: - from lxml.etree import Element, SubElement -except ImportError: - from xml.etree.ElementTree import Element, SubElement - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlquote -from libcloud.utils.py3 import urlencode -from libcloud.utils.py3 import b -from libcloud.utils.py3 import tostring - -from libcloud.utils.xml import fixxpath, findtext -from libcloud.utils.files import read_in_chunks -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.common.base import ConnectionUserAndKey, RawResponse -from libcloud.common.aws import AWSBaseResponse, AWSDriver, AWSTokenConnection - -from libcloud.storage.base import Object, Container, StorageDriver -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import InvalidContainerNameError -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ObjectDoesNotExistError -from libcloud.storage.types import ObjectHashMismatchError - - -# How long before the token expires -EXPIRATION_SECONDS = 15 * 60 - -S3_US_STANDARD_HOST = 's3.amazonaws.com' -S3_US_WEST_HOST = 's3-us-west-1.amazonaws.com' -S3_US_WEST_OREGON_HOST = 's3-us-west-2.amazonaws.com' -S3_EU_WEST_HOST = 's3-eu-west-1.amazonaws.com' -S3_AP_SOUTHEAST_HOST = 's3-ap-southeast-1.amazonaws.com' -S3_AP_NORTHEAST_HOST = 's3-ap-northeast-1.amazonaws.com' - -API_VERSION = '2006-03-01' -NAMESPACE = 'http://s3.amazonaws.com/doc/%s/' % (API_VERSION) - -# AWS multi-part chunks must be minimum 5MB -CHUNK_SIZE = 5 * 1024 * 1024 - -# Desired number of items in each response inside a paginated request in -# ex_iterate_multipart_uploads. -RESPONSES_PER_REQUEST = 100 - - -class S3Response(AWSBaseResponse): - namespace = None - valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT, - httplib.BAD_REQUEST] - - def success(self): - i = int(self.status) - return i >= 200 and i <= 299 or i in self.valid_response_codes - - def parse_error(self): - if self.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]: - raise InvalidCredsError(self.body) - elif self.status == httplib.MOVED_PERMANENTLY: - raise LibcloudError('This bucket is located in a different ' + - 'region. Please use the correct driver.', - driver=S3StorageDriver) - raise LibcloudError('Unknown error. Status code: %d' % (self.status), - driver=S3StorageDriver) - - -class S3RawResponse(S3Response, RawResponse): - pass - - -class BaseS3Connection(ConnectionUserAndKey): - """ - Represents a single connection to the S3 Endpoint - """ - - host = 's3.amazonaws.com' - responseCls = S3Response - rawResponseCls = S3RawResponse - - def add_default_params(self, params): - expires = str(int(time.time()) + EXPIRATION_SECONDS) - params['AWSAccessKeyId'] = self.user_id - params['Expires'] = expires - return params - - def pre_connect_hook(self, params, headers): - params['Signature'] = self._get_aws_auth_param( - method=self.method, headers=headers, params=params, - expires=params['Expires'], secret_key=self.key, path=self.action) - return params, headers - - def _get_aws_auth_param(self, method, headers, params, expires, - secret_key, path='/'): - """ - Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID, - UTF-8-Encoding-Of( StringToSign ) ) ) ); - - StringToSign = HTTP-VERB + "\n" + - Content-MD5 + "\n" + - Content-Type + "\n" + - Expires + "\n" + - CanonicalizedAmzHeaders + - CanonicalizedResource; - """ - special_header_keys = ['content-md5', 'content-type', 'date'] - special_header_values = {'date': ''} - amz_header_values = {} - - headers_copy = copy.deepcopy(headers) - for key, value in list(headers_copy.items()): - key_lower = key.lower() - if key_lower in special_header_keys: - special_header_values[key_lower] = value.strip() - elif key_lower.startswith('x-amz-'): - amz_header_values[key.lower()] = value.strip() - - if 'content-md5' not in special_header_values: - special_header_values['content-md5'] = '' - - if 'content-type' not in special_header_values: - special_header_values['content-type'] = '' - - if expires: - special_header_values['date'] = str(expires) - - keys_sorted = list(special_header_values.keys()) - keys_sorted.sort() - - buf = [method] - for key in keys_sorted: - value = special_header_values[key] - buf.append(value) - string_to_sign = '\n'.join(buf) - - keys_sorted = list(amz_header_values.keys()) - keys_sorted.sort() - - amz_header_string = [] - for key in keys_sorted: - value = amz_header_values[key] - amz_header_string.append('%s:%s' % (key, value)) - amz_header_string = '\n'.join(amz_header_string) - - values_to_sign = [] - for value in [string_to_sign, amz_header_string, path]: - if value: - values_to_sign.append(value) - - string_to_sign = '\n'.join(values_to_sign) - b64_hmac = base64.b64encode( - hmac.new(b(secret_key), b(string_to_sign), digestmod=sha1).digest() - ) - return b64_hmac.decode('utf-8') - - -class S3Connection(AWSTokenConnection, BaseS3Connection): - """ - Represents a single connection to the S3 endpoint, with AWS-specific - features. - """ - pass - - -class S3MultipartUpload(object): - """ - Class representing an amazon s3 multipart upload - """ - - def __init__(self, key, id, created_at, initiator, owner): - """ - Class representing an amazon s3 multipart upload - - :param key: The object/key that was being uploaded - :type key: ``str`` - - :param id: The upload id assigned by amazon - :type id: ``str`` - - :param created_at: The date/time at which the upload was started - :type created_at: ``str`` - - :param initiator: The AWS owner/IAM user who initiated this - :type initiator: ``str`` - - :param owner: The AWS owner/IAM who will own this object - :type owner: ``str`` - """ - self.key = key - self.id = id - self.created_at = created_at - self.initiator = initiator - self.owner = owner - - def __repr__(self): - return ('<S3MultipartUpload: key=%s>' % (self.key)) - - -class BaseS3StorageDriver(StorageDriver): - name = 'Amazon S3 (standard)' - website = 'http://aws.amazon.com/s3/' - connectionCls = BaseS3Connection - hash_type = 'md5' - supports_chunked_encoding = False - supports_s3_multipart_upload = True - ex_location_name = '' - namespace = NAMESPACE - - def iterate_containers(self): - response = self.connection.request('/') - if response.status == httplib.OK: - containers = self._to_containers(obj=response.object, - xpath='Buckets/Bucket') - return containers - - raise LibcloudError('Unexpected status code: %s' % (response.status), - driver=self) - - def list_container_objects(self, container, ex_prefix=None): - """ - Return a list of objects for the given container. - - :param container: Container instance. - :type container: :class:`Container` - - :param ex_prefix: Only return objects starting with ex_prefix - :type ex_prefix: ``str`` - - :return: A list of Object instances. - :rtype: ``list`` of :class:`Object` - """ - return list(self.iterate_container_objects(container, - ex_prefix=ex_prefix)) - - def iterate_container_objects(self, container, ex_prefix=None): - """ - Return a generator of objects for the given container. - - :param container: Container instance - :type container: :class:`Container` - - :param ex_prefix: Only return objects starting with ex_prefix - :type ex_prefix: ``str`` - - :return: A generator of Object instances. - :rtype: ``generator`` of :class:`Object` - """ - params = {} - if ex_prefix: - params['prefix'] = ex_prefix - - last_key = None - exhausted = False - container_path = self._get_container_path(container) - - while not exhausted: - if last_key: - params['marker'] = last_key - - response = self.connection.request(container_path, - params=params) - - if response.status != httplib.OK: - raise LibcloudError('Unexpected status code: %s' % - (response.status), driver=self) - - objects = self._to_objs(obj=response.object, - xpath='Contents', container=container) - is_truncated = response.object.findtext(fixxpath( - xpath='IsTruncated', namespace=self.namespace)).lower() - exhausted = (is_truncated == 'false') - - last_key = None - for obj in objects: - last_key = obj.name - yield obj - - def get_container(self, container_name): - try: - response = self.connection.request('/%s' % container_name, - method='HEAD') - if response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError(value=None, driver=self, - container_name=container_name) - except InvalidCredsError: - # This just means the user doesn't have IAM permissions to do a - # HEAD request but other requests might work. - pass - return Container(name=container_name, extra=None, driver=self) - - def get_object(self, container_name, object_name): - container = self.get_container(container_name=container_name) - object_path = self._get_object_path(container, object_name) - response = self.connection.request(object_path, method='HEAD') - - if response.status == httplib.OK: - obj = self._headers_to_object(object_name=object_name, - container=container, - headers=response.headers) - return obj - - raise ObjectDoesNotExistError(value=None, driver=self, - object_name=object_name) - - def _get_container_path(self, container): - """ - Return a container path - - :param container: Container instance - :type container: :class:`Container` - - :return: A path for this container. - :rtype: ``str`` - """ - return '/%s' % (container.name) - - def _get_object_path(self, container, object_name): - """ - Return an object's CDN path. - - :param container: Container instance - :type container: :class:`Container` - - :param object_name: Object name - :type object_name: :class:`str` - - :return: A path for this object. - :rtype: ``str`` - """ - container_url = self._get_container_path(container) - object_name_cleaned = self._clean_object_name(object_name) - object_path = '%s/%s' % (container_url, object_name_cleaned) - return object_path - - def create_container(self, container_name): - if self.ex_location_name: - root = Element('CreateBucketConfiguration') - child = SubElement(root, 'LocationConstraint') - child.text = self.ex_location_name - - data = tostring(root) - else: - data = '' - - response = self.connection.request('/%s' % (container_name), - data=data, - method='PUT') - - if response.status == httplib.OK: - container = Container(name=container_name, extra=None, driver=self) - return container - elif response.status == httplib.CONFLICT: - raise InvalidContainerNameError( - value='Container with this name already exists. The name must ' - 'be unique among all the containers in the system', - container_name=container_name, driver=self) - elif response.status == httplib.BAD_REQUEST: - raise InvalidContainerNameError(value='Container name contains ' + - 'invalid characters.', - container_name=container_name, - driver=self) - - raise LibcloudError('Unexpected status code: %s' % (response.status), - driver=self) - - def delete_container(self, container): - # Note: All the objects in the container must be deleted first - response = self.connection.request('/%s' % (container.name), - method='DELETE') - if response.status == httplib.NO_CONTENT: - return True - elif response.status == httplib.CONFLICT: - raise ContainerIsNotEmptyError( - value='Container must be empty before it can be deleted.', - container_name=container.name, driver=self) - elif response.status == httplib.NOT_FOUND: - raise ContainerDoesNotExistError(value=None, - driver=self, - container_name=container.name) - - return False - - def download_object(self, obj, destination_path, overwrite_existing=False, - delete_on_failure=True): - obj_path = self._get_object_path(obj.container, obj.name) - - response = self.connection.request(obj_path, method='GET', raw=True) - - return self._get_object(obj=obj, callback=self._save_object, - response=response, - callback_kwargs={ - 'obj': obj, - 'response': response.response, - 'destination_path': destination_path, - 'overwrite_existing': overwrite_existing, - 'delete_on_failure': delete_on_failure}, - success_status_code=httplib.OK) - - def download_object_as_stream(self, obj, chunk_size=None): - obj_path = self._get_object_path(obj.container, obj.name) - response = self.connection.request(obj_path, method='GET', raw=True) - - return self._get_object(obj=obj, callback=read_in_chunks, - response=response, - callback_kwargs={'iterator': response.response, - 'chunk_size': chunk_size}, - success_status_code=httplib.OK) - - def upload_object(self, file_path, container, object_name, extra=None, - verify_hash=True, ex_storage_class=None): - """ - @inherits: :class:`StorageDriver.upload_object` - - :param ex_storage_class: Storage class - :type ex_storage_class: ``str`` - """ - upload_func = self._upload_file - upload_func_kwargs = {'file_path': file_path} - - return self._put_object(container=container, object_name=object_name, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - extra=extra, file_path=file_path, - verify_hash=verify_hash, - storage_class=ex_storage_class) - - def _upload_multipart(self, response, data, iterator, container, - object_name, calculate_hash=True): - """ - Callback invoked for uploading data to S3 using Amazon's - multipart upload mechanism - - :param response: Response object from the initial POST request - :type response: :class:`S3RawResponse` - - :param data: Any data from the initial POST request - :type data: ``str`` - - :param iterator: The generator for fetching the upload data - :type iterator: ``generator`` - - :param container: The container owning the object to which data is - being uploaded - :type container: :class:`Container` - - :param object_name: The name of the object to which we are uploading - :type object_name: ``str`` - - :keyword calculate_hash: Indicates if we must calculate the data hash - :type calculate_hash: ``bool`` - - :return: A tuple of (status, checksum, bytes transferred) - :rtype: ``tuple`` - """ - - object_path = self._get_object_path(container, object_name) - - # Get the upload id from the response xml - response.body = response.response.read() - body = response.parse_body() - upload_id = body.find(fixxpath(xpath='UploadId', - namespace=self.namespace)).text - - try: - # Upload the data through the iterator - result = self._upload_from_iterator(iterator, object_path, - upload_id, calculate_hash) - (chunks, data_hash, bytes_transferred) = result - - # Commit the chunk info and complete the upload - etag = self._commit_multipart(object_path, upload_id, chunks) - except Exception: - exc = sys.exc_info()[1] - # Amazon provides a mechanism for aborting an upload. - self._abort_multipart(object_path, upload_id) - raise exc - - # Modify the response header of the first request. This is used - # by other functions once the callback is done - response.headers['etag'] = etag - - return (True, data_hash, bytes_transferred) - - def _upload_from_iterator(self, iterator, object_path, upload_id, - calculate_hash=True): - """ - Uploads data from an interator in fixed sized chunks to S3 - - :param iterator: The generator for fetching the upload data - :type iterator: ``generator`` - - :param object_path: The path of the object to which we are uploading - :type object_name: ``str`` - - :param upload_id: The upload id allocated for this multipart upload - :type upload_id: ``str`` - - :keyword calculate_hash: Indicates if we must calculate the data hash - :type calculate_hash: ``bool`` - - :return: A tuple of (chunk info, checksum, bytes transferred) - :rtype: ``tuple`` - """ - - data_hash = None - if calculate_hash: - data_hash = self._get_hash_function() - - bytes_transferred = 0 - count = 1 - chunks = [] - params = {'uploadId': upload_id} - - # Read the input data in chunk sizes suitable for AWS - for data in read_in_chunks(iterator, chunk_size=CHUNK_SIZE, - fill_size=True, yield_empty=True): - bytes_transferred += len(data) - - if calculate_hash: - data_hash.update(data) - - chunk_hash = self._get_hash_function() - chunk_hash.update(data) - chunk_hash = base64.b64encode(chunk_hash.digest()).decode('utf-8') - - # This provides an extra level of data check and is recommended - # by amazon - headers = {'Content-MD5': chunk_hash} - params['partNumber'] = count - - request_path = '?'.join((object_path, urlencode(params))) - - resp = self.connection.request(request_path, method='PUT', - data=data, headers=headers) - - if resp.status != httplib.OK: - raise LibcloudError('Error uploading chunk', driver=self) - - server_hash = resp.headers['etag'] - - # Keep this data for a later commit - chunks.append((count, server_hash)) - count += 1 - - if calculate_hash: - data_hash = data_hash.hexdigest() - - return (chunks, data_hash, bytes_transferred) - - def _commit_multipart(self, object_path, upload_id, chunks): - """ - Makes a final commit of the data. - - :param object_path: Server side object path. - :type object_path: ``str`` - - :param upload_id: ID of the multipart upload. - :type upload_id: ``str`` - - :param upload_id: A list of (chunk_number, chunk_hash) tuples. - :type upload_id: ``list`` - """ - - root = Element('CompleteMultipartUpload') - - for (count, etag) in chunks: - part = SubElement(root, 'Part') - part_no = SubElement(part, 'PartNumber') - part_no.text = str(count) - - etag_id = SubElement(part, 'ETag') - etag_id.text = str(etag) - - data = tostring(root) - - params = {'uploadId': upload_id} - request_path = '?'.join((object_path, urlencode(params))) - response = self.connection.request(request_path, data=data, - method='POST') - - if response.status != httplib.OK: - element = response.object - code, message = response._parse_error_details(element=element) - msg = 'Error in multipart commit: %s (%s)' % (message, code) - raise LibcloudError(msg, driver=self) - - # Get the server's etag to be passed back to the caller - body = response.parse_body() - server_hash = body.find(fixxpath(xpath='ETag', - namespace=self.namespace)).text - return server_hash - - def _abort_multipart(self, object_path, upload_id): - """ - Aborts an already initiated multipart upload - - :param object_path: Server side object path. - :type object_path: ``str`` - - :param upload_id: ID of the multipart upload. - :type upload_id: ``str`` - """ - - params = {'uploadId': upload_id} - request_path = '?'.join((object_path, urlencode(params))) - resp = self.connection.request(request_path, method='DELETE') - - if resp.status != httplib.NO_CONTENT: - raise LibcloudError('Error in multipart abort. status_code=%d' % - (resp.status), driver=self) - - def upload_object_via_stream(self, iterator, container, object_name, - extra=None, ex_storage_class=None): - """ - @inherits: :class:`StorageDriver.upload_object_via_stream` - - :param ex_storage_class: Storage class - :type ex_storage_class: ``str`` - """ - - method = 'PUT' - params = None - - # This driver is used by other S3 API compatible drivers also. - # Amazon provides a different (complex?) mechanism to do multipart - # uploads - if self.supports_s3_multipart_upload: - # Initiate the multipart request and get an upload id - upload_func = self._upload_multipart - upload_func_kwargs = {'iterator': iterator, - 'container': container, - 'object_name': object_name} - method = 'POST' - iterator = iter('') - params = 'uploads' - - elif self.supports_chunked_encoding: - upload_func = self._stream_data - upload_func_kwargs = {'iterator': iterator} - else: - # In this case, we have to load the entire object to - # memory and send it as normal data - upload_func = self._upload_data - upload_func_kwargs = {} - - return self._put_object(container=container, object_name=object_name, - upload_func=upload_func, - upload_func_kwargs=upload_func_kwargs, - extra=extra, method=method, query_args=params, - iterator=iterator, verify_hash=False, - storage_class=ex_storage_class) - - def delete_object(self, obj): - object_path = self._get_object_path(obj.container, obj.name) - response = self.connection.request(object_path, method='DELETE') - if response.status == httplib.NO_CONTENT: - return True - elif response.status == httplib.NOT_FOUND: - raise ObjectDoesNotExistError(value=None, driver=self, - object_name=obj.name) - - return False - - def ex_iterate_multipart_uploads(self, container, prefix=None, - delimiter=None): - """ - Extension method for listing all in-progress S3 multipart uploads. - - Each multipart upload which has not been committed or aborted is - considered in-progress. - - :param container: The container holding the uploads - :type container: :class:`Container` - - :keyword prefix: Print only uploads of objects with this prefix - :type prefix: ``str`` - - :keyword delimiter: The object/key names are grouped based on - being split by this delimiter - :type delimiter: ``str`` - - :return: A generator of S3MultipartUpload instances. - :rtype: ``generator`` of :class:`S3MultipartUpload` - """ - - if not self.supports_s3_multipart_upload: - raise LibcloudError('Feature not supported', driver=self) - - # Get the data for a specific container - request_path = '%s/?uploads' % (self._get_container_path(container)) - params = {'max-uploads': RESPONSES_PER_REQUEST} - - if prefix: - params['prefix'] = prefix - - if delimiter: - params['delimiter'] = delimiter - - finder = lambda node, text: node.findtext(fixxpath(xpath=text, - namespace=self.namespace)) - - while True: - response = self.connection.request(request_path, params=params) - - if response.status != httplib.OK: - raise LibcloudError('Error fetching multipart uploads. ' - 'Got code: %s' % (response.status), - driver=self) - - body = response.parse_body() - for node in body.findall(fixxpath(xpath='Upload', - namespace=self.namespace)): - - initiator = node.find(fixxpath(xpath='Initiator', - namespace=self.namespace)) - owner = node.find(fixxpath(xpath='Owner', - namespace=self.namespace)) - - key = finder(node, 'Key') - upload_id = finder(node, 'UploadId') - created_at = finder(node, 'Initiated') - initiator = finder(initiator, 'DisplayName') - owner = finder(owner, 'DisplayName') - - yield S3MultipartUpload(key, upload_id, created_at, - initiator, owner) - - # Check if this is the last entry in the listing - is_truncated = body.findtext(fixxpath(xpath='IsTruncated', - namespace=self.namespace)) - - if is_truncated.lower() == 'false': - break - - # Provide params for the next request - upload_marker = body.findtext(fixxpath(xpath='NextUploadIdMarker', - namespace=self.namespace)) - key_marker = body.findtext(fixxpath(xpath='NextKeyMarker', - namespace=self.namespace)) - - params['key-marker'] = key_marker - params['upload-id-marker'] = upload_marker - - def ex_cleanup_all_multipart_uploads(self, container, prefix=None): - """ - Extension method for removing all partially completed S3 multipart - uploads. - - :param container: The container holding the uploads - :type container: :class:`Container` - - :keyword prefix: Delete only uploads of objects with this prefix - :type prefix: ``str`` - """ - - # Iterate through the container and delete the upload ids - for upload in self.ex_iterate_multipart_uploads(container, prefix, - delimiter=None): - object_path = '/%s/%s' % (container.name, upload.key) - self._abort_multipart(object_path, upload.id) - - def _clean_object_name(self, name): - name = urlquote(name) - return name - - def _put_object(self, container, object_name, upload_func, - upload_func_kwargs, method='PUT', query_args=None, - extra=None, file_path=None, iterator=None, - verify_hash=True, storage_class=None): - headers = {} - extra = extra or {} - storage_class = storage_class or 'standard' - if storage_class not in ['standard', 'reduced_redundancy']: - raise ValueError( - 'Invalid storage class value: %s' % (storage_class)) - - headers['x-amz-storage-class'] = storage_class.upper() - - content_type = extra.get('content_type', None) - meta_data = extra.get('meta_data', None) - acl = extra.get('acl', None) - - if meta_data: - for key, value in list(meta_data.items()): - key = 'x-amz-meta-%s' % (key) - headers[key] = value - - if acl: - headers['x-amz-acl'] = acl - - request_path = self._get_object_path(container, object_name) - - if query_args: - request_path = '?'.join((request_path, query_args)) - - # TODO: Let the underlying exceptions bubble up and capture the SIGPIPE - # here. - # SIGPIPE is thrown if the provided container does not exist or the - # user does not have correct permission - result_dict = self._upload_object( - object_name=object_name, content_type=content_type, - upload_func=upload_func, upload_func_kwargs=upload_func_kwargs, - request_path=request_path, request_method=method, - headers=headers, file_path=file_path, iterator=iterator) - - response = result_dict['response'] - bytes_transferred = result_dict['bytes_transferred'] - headers = response.headers - response = response.response - server_hash = headers['etag'].replace('"', '') - - if (verify_hash and result_dict['data_hash'] != server_hash): - raise ObjectHashMismatchError( - value='MD5 hash checksum does not match', - object_name=object_name, driver=self) - elif response.status == httplib.OK: - obj = Object( - name=object_name, size=bytes_transferred, hash=server_hash, - extra={'acl': acl}, meta_data=meta_data, container=container, - driver=self) - - return obj - else: - raise LibcloudError( - 'Unexpected status code, status_code=%s' % (response.status), - driver=self) - - def _to_containers(self, obj, xpath): - for element in obj.findall(fixxpath(xpath=xpath, - namespace=self.namespace)): - yield self._to_container(element) - - def _to_objs(self, obj, xpath, container): - return [self._to_obj(element, container) for element in - obj.findall(fixxpath(xpath=xpath, namespace=self.namespace))] - - def _to_container(self, element): - extra = { - 'creation_date': findtext(element=element, xpath='CreationDate', - namespace=self.namespace) - } - - container = Container(name=findtext(element=element, xpath='Name', - namespace=self.namespace), - extra=extra, - driver=self - ) - - return container - - def _headers_to_object(self, object_name, container, headers): - hash = headers['etag'].replace('"', '') - extra = {'content_type': headers['content-type'], - 'etag': headers['etag']} - meta_data = {} - - if 'last-modified' in headers: - extra['last_modified'] = headers['last-modified'] - - for key, value in headers.items(): - if not key.lower().startswith('x-amz-meta-'): - continue - - key = key.replace('x-amz-meta-', '') - meta_data[key] = value - - obj = Object(name=object_name, size=headers['content-length'], - hash=hash, extra=extra, - meta_data=meta_data, - container=container, - driver=self) - return obj - - def _to_obj(self, element, container): - owner_id = findtext(element=element, xpath='Owner/ID', - namespace=self.namespace) - owner_display_name = findtext(element=element, - xpath='Owner/DisplayName', - namespace=self.namespace) - meta_data = {'owner': {'id': owner_id, - 'display_name': owner_display_name}} - last_modified = findtext(element=element, - xpath='LastModified', - namespace=self.namespace) - extra = {'last_modified': last_modified} - - obj = Object(name=findtext(element=element, xpath='Key', - namespace=self.namespace), - size=int(findtext(element=element, xpath='Size', - namespace=self.namespace)), - hash=findtext(element=element, xpath='ETag', - namespace=self.namespace).replace('"', ''), - extra=extra, - meta_data=meta_data, - container=container, - driver=self - ) - - return obj - - -class S3StorageDriver(AWSDriver, BaseS3StorageDriver): - connectionCls = S3Connection - - -class S3USWestConnection(S3Connection): - host = S3_US_WEST_HOST - - -class S3USWestStorageDriver(S3StorageDriver): - name = 'Amazon S3 (us-west-1)' - connectionCls = S3USWestConnection - ex_location_name = 'us-west-1' - - -class S3USWestOregonConnection(S3Connection): - host = S3_US_WEST_OREGON_HOST - - -class S3USWestOregonStorageDriver(S3StorageDriver): - name = 'Amazon S3 (us-west-2)' - connectionCls = S3USWestOregonConnection - ex_location_name = 'us-west-2' - - -class S3EUWestConnection(S3Connection): - host = S3_EU_WEST_HOST - - -class S3EUWestStorageDriver(S3StorageDriver): - name = 'Amazon S3 (eu-west-1)' - connectionCls = S3EUWestConnection - ex_location_name = 'EU' - - -class S3APSEConnection(S3Connection): - host = S3_AP_SOUTHEAST_HOST - - -class S3APSEStorageDriver(S3StorageDriver): - name = 'Amazon S3 (ap-southeast-1)' - connectionCls = S3APSEConnection - ex_location_name = 'ap-southeast-1' - - -class S3APNEConnection(S3Connection): - host = S3_AP_NORTHEAST_HOST - - -class S3APNEStorageDriver(S3StorageDriver): - name = 'Amazon S3 (ap-northeast-1)' - connectionCls = S3APNEConnection - ex_location_name = 'ap-northeast-1' diff --git a/awx/lib/site-packages/libcloud/storage/providers.py b/awx/lib/site-packages/libcloud/storage/providers.py deleted file mode 100644 index 1be212e15b..0000000000 --- a/awx/lib/site-packages/libcloud/storage/providers.py +++ /dev/null @@ -1,67 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.utils.misc import get_driver as get_provider_driver -from libcloud.utils.misc import set_driver as set_provider_driver -from libcloud.storage.types import Provider - -DRIVERS = { - Provider.DUMMY: - ('libcloud.storage.drivers.dummy', 'DummyStorageDriver'), - Provider.CLOUDFILES: - ('libcloud.storage.drivers.cloudfiles', 'CloudFilesStorageDriver'), - Provider.OPENSTACK_SWIFT: - ('libcloud.storage.drivers.cloudfiles', 'OpenStackSwiftStorageDriver'), - Provider.S3: - ('libcloud.storage.drivers.s3', 'S3StorageDriver'), - Provider.S3_US_WEST: - ('libcloud.storage.drivers.s3', 'S3USWestStorageDriver'), - Provider.S3_US_WEST_OREGON: - ('libcloud.storage.drivers.s3', 'S3USWestOregonStorageDriver'), - Provider.S3_EU_WEST: - ('libcloud.storage.drivers.s3', 'S3EUWestStorageDriver'), - Provider.S3_AP_SOUTHEAST: - ('libcloud.storage.drivers.s3', 'S3APSEStorageDriver'), - Provider.S3_AP_NORTHEAST: - ('libcloud.storage.drivers.s3', 'S3APNEStorageDriver'), - Provider.NINEFOLD: - ('libcloud.storage.drivers.ninefold', 'NinefoldStorageDriver'), - Provider.GOOGLE_STORAGE: - ('libcloud.storage.drivers.google_storage', 'GoogleStorageDriver'), - Provider.NIMBUS: - ('libcloud.storage.drivers.nimbus', 'NimbusStorageDriver'), - Provider.LOCAL: - ('libcloud.storage.drivers.local', 'LocalStorageDriver'), - Provider.AZURE_BLOBS: - ('libcloud.storage.drivers.azure_blobs', 'AzureBlobsStorageDriver'), - Provider.KTUCLOUD: - ('libcloud.storage.drivers.ktucloud', 'KTUCloudStorageDriver'), - - # Deprecated - Provider.CLOUDFILES_US: - ('libcloud.storage.drivers.cloudfiles', 'CloudFilesUSStorageDriver'), - Provider.CLOUDFILES_UK: - ('libcloud.storage.drivers.cloudfiles', 'CloudFilesUKStorageDriver'), - Provider.CLOUDFILES_SWIFT: - ('libcloud.storage.drivers.cloudfiles', 'OpenStackSwiftStorageDriver') -} - - -def get_driver(provider): - return get_provider_driver(DRIVERS, provider) - - -def set_driver(provider, module, klass): - return set_provider_driver(DRIVERS, provider, module, klass) diff --git a/awx/lib/site-packages/libcloud/storage/types.py b/awx/lib/site-packages/libcloud/storage/types.py deleted file mode 100644 index ddc80351a0..0000000000 --- a/awx/lib/site-packages/libcloud/storage/types.py +++ /dev/null @@ -1,119 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.common.types import LibcloudError - -__all__ = ['Provider', - 'ContainerError', - 'ObjectError', - 'ContainerAlreadyExistsError', - 'ContainerDoesNotExistError', - 'ContainerIsNotEmptyError', - 'ObjectDoesNotExistError', - 'ObjectHashMismatchError', - 'InvalidContainerNameError'] - - -class Provider(object): - """ - Defines for each of the supported providers - - :cvar DUMMY: Example provider - :cvar CLOUDFILES: CloudFiles - :cvar S3: Amazon S3 US - :cvar S3_US_WEST: Amazon S3 US West (Northern California) - :cvar S3_EU_WEST: Amazon S3 EU West (Ireland) - :cvar S3_AP_SOUTHEAST_HOST: Amazon S3 Asia South East (Singapore) - :cvar S3_AP_NORTHEAST_HOST: Amazon S3 Asia South East (Tokyo) - :cvar NINEFOLD: Ninefold - :cvar GOOGLE_STORAGE Google Storage - :cvar S3_US_WEST_OREGON: Amazon S3 US West 2 (Oregon) - :cvar NIMBUS: Nimbus.io driver - :cvar LOCAL: Local storage driver - """ - DUMMY = 'dummy' - S3 = 's3' - S3_US_WEST = 's3_us_west' - S3_EU_WEST = 's3_eu_west' - S3_AP_SOUTHEAST = 's3_ap_southeast' - S3_AP_NORTHEAST = 's3_ap_northeast' - NINEFOLD = 'ninefold' - GOOGLE_STORAGE = 'google_storage' - S3_US_WEST_OREGON = 's3_us_west_oregon' - NIMBUS = 'nimbus' - LOCAL = 'local' - OPENSTACK_SWIFT = 'openstack_swift' - CLOUDFILES = 'cloudfiles' - AZURE_BLOBS = 'azure_blobs' - KTUCLOUD = 'ktucloud' - - # Deperecated - CLOUDFILES_US = 'cloudfiles_us' - CLOUDFILES_UK = 'cloudfiles_uk' - CLOUDFILES_SWIFT = 'cloudfiles_swift' - - -class ContainerError(LibcloudError): - error_type = 'ContainerError' - - def __init__(self, value, driver, container_name): - self.container_name = container_name - super(ContainerError, self).__init__(value=value, driver=driver) - - def __str__(self): - return ('<%s in %s, container=%s, value=%s>' % - (self.error_type, repr(self.driver), - self.container_name, self.value)) - - -class ObjectError(LibcloudError): - error_type = 'ContainerError' - - def __init__(self, value, driver, object_name): - self.object_name = object_name - super(ObjectError, self).__init__(value=value, driver=driver) - - def __str__(self): - return self.__repr__() - - def __repr__(self): - return '<%s in %s, value=%s, object = %s>' % (self.error_type, - repr(self.driver), - self.value, - self.object_name) - - -class ContainerAlreadyExistsError(ContainerError): - error_type = 'ContainerAlreadyExistsError' - - -class ContainerDoesNotExistError(ContainerError): - error_type = 'ContainerDoesNotExistError' - - -class ContainerIsNotEmptyError(ContainerError): - error_type = 'ContainerIsNotEmptyError' - - -class ObjectDoesNotExistError(ObjectError): - error_type = 'ObjectDoesNotExistError' - - -class ObjectHashMismatchError(ObjectError): - error_type = 'ObjectHashMismatchError' - - -class InvalidContainerNameError(ContainerError): - error_type = 'InvalidContainerNameError' diff --git a/awx/lib/site-packages/libcloud/test/__init__.py b/awx/lib/site-packages/libcloud/test/__init__.py deleted file mode 100644 index 3a701cdb67..0000000000 --- a/awx/lib/site-packages/libcloud/test/__init__.py +++ /dev/null @@ -1,345 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import random - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import StringIO -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import parse_qs -from libcloud.utils.py3 import parse_qsl -from libcloud.utils.py3 import u -from libcloud.utils.py3 import unittest2_required - -if unittest2_required: - import unittest2 as unittest -else: - import unittest - - -XML_HEADERS = {'content-type': 'application/xml'} - - -class LibcloudTestCase(unittest.TestCase): - def __init__(self, *args, **kwargs): - self._visited_urls = [] - self._executed_mock_methods = [] - super(LibcloudTestCase, self).__init__(*args, **kwargs) - - def setUp(self): - self._visited_urls = [] - self._executed_mock_methods = [] - - def _add_visited_url(self, url): - self._visited_urls.append(url) - - def _add_executed_mock_method(self, method_name): - self._executed_mock_methods.append(method_name) - - def assertExecutedMethodCount(self, expected): - actual = len(self._executed_mock_methods) - self.assertEqual(actual, expected, - 'expected %d, but %d mock methods were executed' - % (expected, actual)) - - -class multipleresponse(object): - """ - A decorator that allows MockHttp objects to return multi responses - """ - count = 0 - func = None - - def __init__(self, f): - self.func = f - - def __call__(self, *args, **kwargs): - ret = self.func(self.func.__class__, *args, **kwargs) - response = ret[self.count] - self.count = self.count + 1 - return response - - -class MockResponse(object): - """ - A mock HTTPResponse - """ - headers = {} - body = StringIO() - status = 0 - reason = '' - version = 11 - - def __init__(self, status, body=None, headers=None, reason=None): - self.status = status - self.body = StringIO(u(body)) if body else StringIO() - self.headers = headers or self.headers - self.reason = reason or self.reason - - def read(self, *args, **kwargs): - return self.body.read(*args, **kwargs) - - def next(self): - if sys.version_info >= (2, 5) and sys.version_info <= (2, 6): - return self.body.next() - else: - return next(self.body) - - def __next__(self): - return self.next() - - def getheader(self, name, *args, **kwargs): - return self.headers.get(name, *args, **kwargs) - - def getheaders(self): - return list(self.headers.items()) - - def msg(self): - raise NotImplemented - - -class BaseMockHttpObject(object): - def _get_method_name(self, type, use_param, qs, path): - path = path.split('?')[0] - meth_name = path.replace('/', '_').replace('.', '_').replace('-', '_') - - if type: - meth_name = '%s_%s' % (meth_name, self.type) - - if use_param and use_param in qs: - param = qs[use_param][0].replace('.', '_').replace('-', '_') - meth_name = '%s_%s' % (meth_name, param) - - return meth_name - - -class MockHttp(BaseMockHttpObject): - """ - A mock HTTP client/server suitable for testing purposes. This replaces - `HTTPConnection` by implementing its API and returning a mock response. - - Define methods by request path, replacing slashes (/) with underscores (_). - Each of these mock methods should return a tuple of: - - (int status, str body, dict headers, str reason) - - >>> mock = MockHttp('localhost', 8080) - >>> mock.request('GET', '/example/') - >>> response = mock.getresponse() - >>> response.body.read() - 'Hello World!' - >>> response.status - 200 - >>> response.getheaders() - [('X-Foo', 'libcloud')] - >>> MockHttp.type = 'fail' - >>> mock.request('GET', '/example/') - >>> response = mock.getresponse() - >>> response.body.read() - 'Oh Noes!' - >>> response.status - 403 - >>> response.getheaders() - [('X-Foo', 'fail')] - - """ - responseCls = MockResponse - host = None - port = None - response = None - - type = None - use_param = None # will use this param to namespace the request function - - test = None # TestCase instance which is using this mock - - def __init__(self, host, port, *args, **kwargs): - self.host = host - self.port = port - - def request(self, method, url, body=None, headers=None, raw=False): - # Find a method we can use for this request - parsed = urlparse.urlparse(url) - scheme, netloc, path, params, query, fragment = parsed - qs = parse_qs(query) - if path.endswith('/'): - path = path[:-1] - meth_name = self._get_method_name(type=self.type, - use_param=self.use_param, - qs=qs, path=path) - meth = getattr(self, meth_name.replace('%', '_')) - - if self.test and isinstance(self.test, LibcloudTestCase): - self.test._add_visited_url(url=url) - self.test._add_executed_mock_method(method_name=meth_name) - - status, body, headers, reason = meth(method, url, body, headers) - self.response = self.responseCls(status, body, headers, reason) - - def getresponse(self): - return self.response - - def connect(self): - """ - Can't think of anything to mock here. - """ - pass - - def close(self): - pass - - # Mock request/response example - def _example(self, method, url, body, headers): - """ - Return a simple message and header, regardless of input. - """ - return (httplib.OK, 'Hello World!', {'X-Foo': 'libcloud'}, - httplib.responses[httplib.OK]) - - def _example_fail(self, method, url, body, headers): - return (httplib.FORBIDDEN, 'Oh Noes!', {'X-Foo': 'fail'}, - httplib.responses[httplib.FORBIDDEN]) - - -class MockHttpTestCase(MockHttp, unittest.TestCase): - # Same as the MockHttp class, but you can also use assertions in the - # classes which inherit from this one. - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self) - - if kwargs.get('host', None) and kwargs.get('port', None): - MockHttp.__init__(self, *args, **kwargs) - - def runTest(self): - pass - - def assertUrlContainsQueryParams(self, url, expected_params, strict=False): - """ - Assert that provided url contains provided query parameters. - - :param url: URL to assert. - :type url: ``str`` - - :param expected_params: Dictionary of expected query parameters. - :type expected_params: ``dict`` - - :param strict: Assert that provided url contains only expected_params. - (defaults to ``False``) - :type strict: ``bool`` - """ - question_mark_index = url.find('?') - - if question_mark_index != -1: - url = url[question_mark_index + 1:] - - params = dict(parse_qsl(url)) - - if strict: - self.assertDictEqual(params, expected_params) - else: - for key, value in expected_params.items(): - self.assertEqual(params[key], value) - - -class StorageMockHttp(MockHttp): - def putrequest(self, method, action): - pass - - def putheader(self, key, value): - pass - - def endheaders(self): - pass - - def send(self, data): - pass - - -class MockRawResponse(BaseMockHttpObject): - """ - Mock RawResponse object suitable for testing. - """ - - type = None - responseCls = MockResponse - - def __init__(self, connection): - super(MockRawResponse, self).__init__() - self._data = [] - self._current_item = 0 - - self._status = None - self._response = None - self._headers = None - self._reason = None - self.connection = connection - - def next(self): - if self._current_item == len(self._data): - raise StopIteration - - value = self._data[self._current_item] - self._current_item += 1 - return value - - def __next__(self): - return self.next() - - def _generate_random_data(self, size): - data = '' - current_size = 0 - while current_size < size: - value = str(random.randint(0, 9)) - value_size = len(value) - data += value - current_size += value_size - - return data - - @property - def response(self): - return self._get_response_if_not_availale() - - @property - def status(self): - self._get_response_if_not_availale() - return self._status - - @property - def headers(self): - self._get_response_if_not_availale() - return self._headers - - @property - def reason(self): - self._get_response_if_not_availale() - return self._reason - - def _get_response_if_not_availale(self): - if not self._response: - meth_name = self._get_method_name(type=self.type, - use_param=False, qs=None, - path=self.connection.action) - meth = getattr(self, meth_name.replace('%', '_')) - result = meth(self.connection.method, None, None, None) - self._status, self._body, self._headers, self._reason = result - self._response = self.responseCls(self._status, self._body, - self._headers, self._reason) - return self._response - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/awx/lib/site-packages/libcloud/test/common/__init__.py b/awx/lib/site-packages/libcloud/test/common/__init__.py deleted file mode 100644 index ae1e83eeb3..0000000000 --- a/awx/lib/site-packages/libcloud/test/common/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/awx/lib/site-packages/libcloud/test/common/test_cloudstack.py b/awx/lib/site-packages/libcloud/test/common/test_cloudstack.py deleted file mode 100644 index 2412d5cd92..0000000000 --- a/awx/lib/site-packages/libcloud/test/common/test_cloudstack.py +++ /dev/null @@ -1,210 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import b -from libcloud.utils.py3 import parse_qsl - -from libcloud.common.cloudstack import CloudStackConnection -from libcloud.common.types import MalformedResponseError - -from libcloud.test import MockHttpTestCase - - -async_delay = 0 - - -class CloudStackMockDriver(object): - host = 'nonexistent.' - path = '/path' - async_poll_frequency = 0 - - name = 'fake' - - async_delay = 0 - - -class CloudStackCommonTest(unittest.TestCase): - def setUp(self): - CloudStackConnection.conn_classes = (None, CloudStackMockHttp) - self.connection = CloudStackConnection('apikey', 'secret', - host=CloudStackMockDriver.host) - self.connection.poll_interval = 0.0 - self.driver = self.connection.driver = CloudStackMockDriver() - - def test_sync_request_bad_response(self): - self.driver.path = '/bad/response' - try: - self.connection._sync_request('fake') - except Exception: - e = sys.exc_info()[1] - self.assertTrue(isinstance(e, MalformedResponseError)) - return - self.assertTrue(False) - - def test_sync_request(self): - self.driver.path = '/sync' - self.connection._sync_request('fake') - - def test_async_request_successful(self): - self.driver.path = '/async/success' - result = self.connection._async_request('fake') - self.assertEqual(result, {'fake': 'result'}) - - def test_async_request_unsuccessful(self): - self.driver.path = '/async/fail' - try: - self.connection._async_request('fake') - except Exception: - e = sys.exc_info()[1] - self.assertEqual(CloudStackMockHttp.ERROR_TEXT, str(e)) - return - self.assertFalse(True) - - def test_async_request_delayed(self): - global async_delay - self.driver.path = '/async/delayed' - async_delay = 2 - self.connection._async_request('fake') - self.assertEqual(async_delay, 0) - - def test_signature_algorithm(self): - cases = [ - ( - { - 'command': 'listVirtualMachines' - }, 'z/a9Y7J52u48VpqIgiwaGUMCso0=' - ), ( - { - 'command': 'deployVirtualMachine', - 'name': 'fred', - 'displayname': 'George', - 'serviceofferingid': 5, - 'templateid': 17, - 'zoneid': 23, - 'networkids': 42 - }, 'gHTo7mYmadZ+zluKHzlEKb1i/QU=' - ), ( - { - 'command': 'deployVirtualMachine', - 'name': 'fred', - 'displayname': 'George+Ringo', - 'serviceofferingid': 5, - 'templateid': 17, - 'zoneid': 23, - 'networkids': 42 - }, 'tAgfrreI1ZvWlWLClD3gu4+aKv4=' - ) - ] - - connection = CloudStackConnection('fnord', 'abracadabra') - for case in cases: - params = connection.add_default_params(case[0]) - self.assertEqual(connection._make_signature(params), b(case[1])) - - -class CloudStackMockHttp(MockHttpTestCase): - - ERROR_TEXT = 'ERROR TEXT' - - def _response(self, status, result, response): - return (status, json.dumps(result), result, response) - - def _check_request(self, url): - url = urlparse.urlparse(url) - query = dict(parse_qsl(url.query)) - - self.assertTrue('apiKey' in query) - self.assertTrue('command' in query) - self.assertTrue('response' in query) - self.assertTrue('signature' in query) - - self.assertTrue(query['response'] == 'json') - - return query - - def _bad_response(self, method, url, body, headers): - self._check_request(url) - result = {'success': True} - return self._response(httplib.OK, result, httplib.responses[httplib.OK]) - - def _sync(self, method, url, body, headers): - query = self._check_request(url) - result = {query['command'].lower() + 'response': {}} - return self._response(httplib.OK, result, httplib.responses[httplib.OK]) - - def _async_success(self, method, url, body, headers): - query = self._check_request(url) - if query['command'].lower() == 'queryasyncjobresult': - self.assertEqual(query['jobid'], '42') - result = { - query['command'].lower() + 'response': { - 'jobstatus': 1, - 'jobresult': {'fake': 'result'} - } - } - else: - result = {query['command'].lower() + 'response': {'jobid': '42'}} - return self._response(httplib.OK, result, httplib.responses[httplib.OK]) - - def _async_fail(self, method, url, body, headers): - query = self._check_request(url) - if query['command'].lower() == 'queryasyncjobresult': - self.assertEqual(query['jobid'], '42') - result = { - query['command'].lower() + 'response': { - 'jobstatus': 2, - 'jobresult': {'errortext': self.ERROR_TEXT} - } - } - else: - result = {query['command'].lower() + 'response': {'jobid': '42'}} - return self._response(httplib.OK, result, httplib.responses[httplib.OK]) - - def _async_delayed(self, method, url, body, headers): - global async_delay - - query = self._check_request(url) - if query['command'].lower() == 'queryasyncjobresult': - self.assertEqual(query['jobid'], '42') - if async_delay == 0: - result = { - query['command'].lower() + 'response': { - 'jobstatus': 1, - 'jobresult': {'fake': 'result'} - } - } - else: - result = { - query['command'].lower() + 'response': { - 'jobstatus': 0, - } - } - async_delay -= 1 - else: - result = {query['command'].lower() + 'response': {'jobid': '42'}} - return self._response(httplib.OK, result, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/common/test_gandi.py b/awx/lib/site-packages/libcloud/test/common/test_gandi.py deleted file mode 100644 index d0dfc9dd8e..0000000000 --- a/awx/lib/site-packages/libcloud/test/common/test_gandi.py +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.utils.py3 import xmlrpclib -from libcloud.test import MockHttp - - -class BaseGandiMockHttp(MockHttp): - - def _get_method_name(self, type, use_param, qs, path): - return "_xmlrpc" - - def _xmlrpc(self, method, url, body, headers): - params, methodName = xmlrpclib.loads(body) - meth_name = '_xmlrpc__' + methodName.replace('.', '_') - if self.type: - meth_name = '%s_%s' % (meth_name, self.type) - return getattr(self, meth_name)(method, url, body, headers) diff --git a/awx/lib/site-packages/libcloud/test/common/test_google.py b/awx/lib/site-packages/libcloud/test/common/test_google.py deleted file mode 100644 index 2e9c701dd8..0000000000 --- a/awx/lib/site-packages/libcloud/test/common/test_google.py +++ /dev/null @@ -1,244 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Tests for Google Connection classes. -""" -import datetime -import sys -import unittest - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import httplib - -from libcloud.test import MockHttp, LibcloudTestCase -from libcloud.common.google import (GoogleAuthError, - GoogleBaseAuthConnection, - GoogleInstalledAppAuthConnection, - GoogleServiceAcctAuthConnection, - GoogleBaseConnection) -from libcloud.test.secrets import GCE_PARAMS - -# Skip some tests if PyCrypto is unavailable -try: - from Crypto.Hash import SHA256 -except ImportError: - SHA256 = None - - -class MockJsonResponse(object): - def __init__(self, body): - self.object = body - - -class GoogleBaseAuthConnectionTest(LibcloudTestCase): - """ - Tests for GoogleBaseAuthConnection - """ - GoogleBaseAuthConnection._now = lambda x: datetime.datetime(2013, 6, 26, - 19, 0, 0) - - def setUp(self): - GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp, - GoogleAuthMockHttp) - self.mock_scopes = ['foo', 'bar'] - kwargs = {'scopes': self.mock_scopes} - self.conn = GoogleInstalledAppAuthConnection(*GCE_PARAMS, - **kwargs) - - def test_scopes(self): - self.assertEqual(self.conn.scopes, 'foo bar') - - def test_add_default_headers(self): - old_headers = {} - expected_headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Host': 'accounts.google.com'} - new_headers = self.conn.add_default_headers(old_headers) - self.assertEqual(new_headers, expected_headers) - - def test_token_request(self): - request_body = {'code': 'asdf', 'client_id': self.conn.user_id, - 'client_secret': self.conn.key, - 'redirect_uri': self.conn.redirect_uri, - 'grant_type': 'authorization_code'} - new_token = self.conn._token_request(request_body) - self.assertEqual(new_token['access_token'], 'installedapp') - self.assertEqual(new_token['expire_time'], '2013-06-26T20:00:00Z') - - -class GoogleInstalledAppAuthConnectionTest(LibcloudTestCase): - """ - Tests for GoogleInstalledAppAuthConnection - """ - GoogleInstalledAppAuthConnection.get_code = lambda x: '1234' - - def setUp(self): - GoogleInstalledAppAuthConnection.conn_classes = (GoogleAuthMockHttp, - GoogleAuthMockHttp) - self.mock_scopes = ['https://www.googleapis.com/auth/foo'] - kwargs = {'scopes': self.mock_scopes} - self.conn = GoogleInstalledAppAuthConnection(*GCE_PARAMS, - **kwargs) - - def test_refresh_token(self): - # This token info doesn't have a refresh token, so a new token will be - # requested - token_info1 = {'access_token': 'tokentoken', 'token_type': 'Bearer', - 'expires_in': 3600} - new_token1 = self.conn.refresh_token(token_info1) - self.assertEqual(new_token1['access_token'], 'installedapp') - - # This token info has a refresh token, so it will be able to be - # refreshed. - token_info2 = {'access_token': 'tokentoken', 'token_type': 'Bearer', - 'expires_in': 3600, 'refresh_token': 'refreshrefresh'} - new_token2 = self.conn.refresh_token(token_info2) - self.assertEqual(new_token2['access_token'], 'refreshrefresh') - - # Both sets should have refresh info - self.assertTrue('refresh_token' in new_token1) - self.assertTrue('refresh_token' in new_token2) - - -class GoogleBaseConnectionTest(LibcloudTestCase): - """ - Tests for GoogleBaseConnection - """ - GoogleBaseConnection._get_token_info_from_file = lambda x: None - GoogleBaseConnection._write_token_info_to_file = lambda x: None - GoogleInstalledAppAuthConnection.get_code = lambda x: '1234' - GoogleServiceAcctAuthConnection.get_new_token = \ - lambda x: x._token_request({}) - GoogleBaseConnection._now = lambda x: datetime.datetime(2013, 6, 26, - 19, 0, 0) - - def setUp(self): - GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp, - GoogleAuthMockHttp) - self.mock_scopes = ['https://www.googleapis.com/auth/foo'] - kwargs = {'scopes': self.mock_scopes, 'auth_type': 'IA'} - self.conn = GoogleBaseConnection(*GCE_PARAMS, **kwargs) - - def test_auth_type(self): - self.assertRaises(GoogleAuthError, GoogleBaseConnection, *GCE_PARAMS, - **{'auth_type': 'XX'}) - - kwargs = {'scopes': self.mock_scopes} - - if SHA256: - kwargs['auth_type'] = 'SA' - conn1 = GoogleBaseConnection(*GCE_PARAMS, **kwargs) - self.assertTrue(isinstance(conn1.auth_conn, - GoogleServiceAcctAuthConnection)) - - kwargs['auth_type'] = 'IA' - conn2 = GoogleBaseConnection(*GCE_PARAMS, **kwargs) - self.assertTrue(isinstance(conn2.auth_conn, - GoogleInstalledAppAuthConnection)) - - def test_add_default_headers(self): - old_headers = {} - new_expected_headers = {'Content-Type': 'application/json', - 'Host': 'www.googleapis.com'} - new_headers = self.conn.add_default_headers(old_headers) - self.assertEqual(new_headers, new_expected_headers) - - def test_pre_connect_hook(self): - old_params = {} - old_headers = {} - new_expected_params = {} - new_expected_headers = {'Authorization': 'Bearer installedapp'} - new_params, new_headers = self.conn.pre_connect_hook(old_params, - old_headers) - self.assertEqual(new_params, new_expected_params) - self.assertEqual(new_headers, new_expected_headers) - - def test_encode_data(self): - data = {'key': 'value'} - json_data = '{"key": "value"}' - encoded_data = self.conn.encode_data(data) - self.assertEqual(encoded_data, json_data) - - def test_has_completed(self): - body1 = {"endTime": "2013-06-26T10:05:07.630-07:00", - "id": "3681664092089171723", - "kind": "compute#operation", - "status": "DONE", - "targetId": "16211908079305042870"} - body2 = {"endTime": "2013-06-26T10:05:07.630-07:00", - "id": "3681664092089171723", - "kind": "compute#operation", - "status": "RUNNING", - "targetId": "16211908079305042870"} - response1 = MockJsonResponse(body1) - response2 = MockJsonResponse(body2) - self.assertTrue(self.conn.has_completed(response1)) - self.assertFalse(self.conn.has_completed(response2)) - - def test_get_poll_request_kwargs(self): - body = {"endTime": "2013-06-26T10:05:07.630-07:00", - "id": "3681664092089171723", - "kind": "compute#operation", - "selfLink": "https://www.googleapis.com/operations-test"} - response = MockJsonResponse(body) - expected_kwargs = {'action': - 'https://www.googleapis.com/operations-test'} - kwargs = self.conn.get_poll_request_kwargs(response, None, {}) - self.assertEqual(kwargs, expected_kwargs) - - def test_morph_action_hook(self): - self.conn.request_path = '/compute/apiver/project/project-name' - action1 = ('https://www.googleapis.com/compute/apiver/project' - '/project-name/instances') - action2 = '/instances' - expected_request = '/compute/apiver/project/project-name/instances' - request1 = self.conn.morph_action_hook(action1) - request2 = self.conn.morph_action_hook(action2) - self.assertEqual(request1, expected_request) - self.assertEqual(request2, expected_request) - - -class GoogleAuthMockHttp(MockHttp): - """ - Mock HTTP Class for Google Auth Connections. - """ - json_hdr = {'content-type': 'application/json; charset=UTF-8'} - - def _o_oauth2_token(self, method, url, body, headers): - token_info = {'access_token': 'tokentoken', - 'token_type': 'Bearer', - 'expires_in': 3600} - refresh_token = {'access_token': 'refreshrefresh', - 'token_type': 'Bearer', - 'expires_in': 3600} - ia_token = {'access_token': 'installedapp', - 'token_type': 'Bearer', - 'expires_in': 3600, - 'refresh_token': 'refreshrefresh'} - if 'code' in body: - body = json.dumps(ia_token) - elif 'refresh_token' in body: - body = json.dumps(refresh_token) - else: - body = json.dumps(token_info) - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/common/test_openstack.py b/awx/lib/site-packages/libcloud/test/common/test_openstack.py deleted file mode 100644 index 03f0542973..0000000000 --- a/awx/lib/site-packages/libcloud/test/common/test_openstack.py +++ /dev/null @@ -1,49 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from mock import Mock - -from libcloud.common.openstack import OpenStackBaseConnection -from libcloud.utils.py3 import PY25 - - -class OpenStackBaseConnectionTest(unittest.TestCase): - - def setUp(self): - self.timeout = 10 - OpenStackBaseConnection.conn_classes = (None, Mock()) - self.connection = OpenStackBaseConnection('foo', 'bar', - timeout=self.timeout, - ex_force_auth_url='https://127.0.0.1') - self.connection.driver = Mock() - self.connection.driver.name = 'OpenStackDriver' - - def test_base_connection_timeout(self): - self.connection.connect() - self.assertEqual(self.connection.timeout, self.timeout) - if PY25: - self.connection.conn_classes[1].assert_called_with(host='127.0.0.1', - port=443) - else: - self.connection.conn_classes[1].assert_called_with(host='127.0.0.1', - port=443, - timeout=10) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/__init__.py b/awx/lib/site-packages/libcloud/test/compute/__init__.py deleted file mode 100644 index 42e478c349..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/__init__.py +++ /dev/null @@ -1,105 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.compute.base import Node, NodeImage, NodeLocation, StorageVolume -from libcloud.pricing import get_pricing - - -class TestCaseMixin(object): - should_list_locations = True - should_have_pricing = False - should_list_volumes = False - - def test_list_nodes_response(self): - nodes = self.driver.list_nodes() - self.assertTrue(isinstance(nodes, list)) - for node in nodes: - self.assertTrue(isinstance(node, Node)) - - def test_list_sizes_response(self): - sizes = self.driver.list_sizes() - size = sizes[0] - self.assertTrue(isinstance(sizes, list)) - # Check that size values are ints or None - self.assertTrue(size.ram is None or isinstance(size.ram, int)) - self.assertTrue(size.disk is None or isinstance(size.disk, int)) - self.assertTrue(size.bandwidth is None or - isinstance(size.bandwidth, int)) - # Check that price values are ints, floats, or None. - self.assertTrue(size.price is None or isinstance(size.price, float) - or isinstance(size.price, int)) - - def test_list_images_response(self): - images = self.driver.list_images() - self.assertTrue(isinstance(images, list)) - for image in images: - self.assertTrue(isinstance(image, NodeImage)) - - def test_list_volumes_response(self): - if not self.should_list_volumes: - return None - - volumes = self.driver.list_volumes() - self.assertTrue(isinstance(volumes, list)) - for volume in volumes: - self.assertTrue(isinstance(volume, StorageVolume)) - - def test_list_locations_response(self): - if not self.should_list_locations: - return None - - locations = self.driver.list_locations() - self.assertTrue(isinstance(locations, list)) - for dc in locations: - self.assertTrue(isinstance(dc, NodeLocation)) - - def test_create_node_response(self): - # should return a node object - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node(name='node-name', - image=image, - size=size) - self.assertTrue(isinstance(node, Node)) - - def test_destroy_node_response(self): - # should return a node object - node = self.driver.list_nodes()[0] - ret = self.driver.destroy_node(node) - self.assertTrue(isinstance(ret, bool)) - - def test_reboot_node_response(self): - # should return a node object - node = self.driver.list_nodes()[0] - ret = self.driver.reboot_node(node) - self.assertTrue(isinstance(ret, bool)) - - def test_get_pricing_success(self): - if not self.should_have_pricing: - return None - - driver_type = 'compute' - try: - get_pricing(driver_type=driver_type, - driver_name=self.driver.api_name) - except KeyError: - self.fail("No {driver_type!r} pricing info for {driver}.".format( - driver=self.driver.__class__.__name__, - driver_type=driver_type, - )) - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/dcs.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/dcs.xml deleted file mode 100644 index a014a42fbe..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/dcs.xml +++ /dev/null @@ -1,78 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<datacenters> - <datacenter> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="edit"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/action/getlimits" type="application/vnd.abiquo.limit+xml" rel="getLimits"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/racks" type="application/vnd.abiquo.racks+xml" rel="racks"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices" type="application/vnd.abiquo.remoteservices+xml" rel="remoteservices"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/storage/tiers" type="application/vnd.abiquo.tiers+xml" rel="tiers"/> - <id>2</id> - <location>barcelona</location> - <name>barcelona</name> - <remoteServices> - <remoteService> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/virtualfactory/action/check" rel="check"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/virtualfactory" type="application/vnd.abiquo.remoteservice+xml" rel="edit"/> - <id>3</id> - <status>1</status> - <type>VIRTUAL_FACTORY</type> - <uri>http://10.60.12.7:80/virtualfactory</uri> - </remoteService> - <remoteService> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/virtualsystemmonitor/action/check" rel="check"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/virtualsystemmonitor" type="application/vnd.abiquo.remoteservice+xml" rel="edit"/> - <id>4</id> - <status>1</status> - <type>VIRTUAL_SYSTEM_MONITOR</type> - <uri>http://10.60.12.7:80/vsm</uri> - </remoteService> - <remoteService> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/appliancemanager/action/check" rel="check"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/appliancemanager" type="application/vnd.abiquo.remoteservice+xml" rel="edit"/> - <id>5</id> - <status>1</status> - <type>APPLIANCE_MANAGER</type> - <uri>http://10.60.12.7:80/am</uri> - </remoteService> - <remoteService> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/nodecollector/action/check" rel="check"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/nodecollector" type="application/vnd.abiquo.remoteservice+xml" rel="edit"/> - <id>6</id> - <status>1</status> - <type>NODE_COLLECTOR</type> - <uri>http://10.60.12.7:80/nodecollector</uri> - </remoteService> - <remoteService> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/storagesystemmonitor/action/check" rel="check"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/storagesystemmonitor" type="application/vnd.abiquo.remoteservice+xml" rel="edit"/> - <id>7</id> - <status>1</status> - <type>STORAGE_SYSTEM_MONITOR</type> - <uri>http://10.60.12.7:80/ssm</uri> - </remoteService> - <remoteService> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/dhcpservice" type="application/vnd.abiquo.remoteservice+xml" rel="edit"/> - <id>8</id> - <status>1</status> - <type>DHCP_SERVICE</type> - <uri>omapi://10.60.12.7:7911</uri> - </remoteService> - <remoteService> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/bpmservice/action/check" rel="check"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2/remoteservices/bpmservice" type="application/vnd.abiquo.remoteservice+xml" rel="edit"/> - <id>9</id> - <status>1</status> - <type>BPM_SERVICE</type> - <uri>http://10.60.12.7:80/bpm-async</uri> - </remoteService> - </remoteServices> - <uuid>Abiquo</uuid> - </datacenter> -</datacenters> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1.xml deleted file mode 100644 index 80b055478a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<enterprise> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/appslib/templateDefinitionLists" type="application/vnd.abiquo.templatedefinitionlists+xml" rel="appslib/templateDefinitionLists"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/appslib/templateDefinitions" type="application/vnd.abiquo.templatedefinitions+xml" rel="appslib/templateDefinitions"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/action/virtualdatacenters" type="application/vnd.abiquo.virtualdatacenters+xml" rel="cloud/virtualdatacenters"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1" type="application/vnd.abiquo.enterprise+xml" rel="edit"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/action/externalnetworks" type="application/vnd.abiquo.vlans+xml" rel="externalnetworks"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/action/ips" rel="ips" title="ips"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/limits" type="application/vnd.abiquo.limits+xml" rel="limits"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/reservedmachines" type="application/vnd.abiquo.machines+xml" rel="reservedmachines"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/users" type="application/vnd.abiquo.users+xml" rel="users"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/action/virtualappliances" type="application/vnd.abiquo.virtualappliances+xml; version=2.0" rel="virtualappliances"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/action/virtualappliances" rel="virtualappliances" title="virtualappliances"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/action/virtualmachines" type="application/vnd.abiquo.virtualmachines+xml" rel="virtualmachines"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/action/volumes" type="application/vnd.abiquo.iscsivolumes+xml" rel="volumes"/> - <cpuHard>0</cpuHard> - <cpuSoft>0</cpuSoft> - <hdHard>0</hdHard> - <hdSoft>0</hdSoft> - <publicIpsHard>0</publicIpsHard> - <publicIpsSoft>0</publicIpsSoft> - <ramHard>0</ramHard> - <ramSoft>0</ramSoft> - <storageHard>0</storageHard> - <storageSoft>0</storageSoft> - <vlansHard>0</vlansHard> - <vlansSoft>0</vlansSoft> - <id>1</id> - <isReservationRestricted>false</isReservationRestricted> - <name>Abiquo</name> - <repositoryHard>0</repositoryHard> - <repositorySoft>0</repositorySoft> -</enterprise> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2.xml deleted file mode 100644 index 61264c7e3c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<datacenterRepository> - <link href="http://10.60.12.7:80/am/erepos/1" rel="applianceManagerRepositoryUri"/><link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter" title="barcelona"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2" type="application/vnd.abiquo.datacenterrepository+xml" rel="edit"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1" type="application/vnd.abiquo.enterprise+xml" rel="enterprise"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2/actions/refresh" rel="refresh"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2/virtualmachinetemplates" type="application/vnd.abiquo.virtualmachinetemplates+xml" rel="virtualmachinetemplates"/> -<id>2</id><name>virtual image repo</name><repositoryCapacityMb>0</repositoryCapacityMb><repositoryLocation>10.60.1.72:/opt/vm_repository</repositoryLocation><repositoryRemainingMb>0</repositoryRemainingMb></datacenterRepository> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_template_11.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_template_11.xml deleted file mode 100644 index 7127c102db..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_template_11.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<virtualMachineTemplate> - <link href="http://10.60.12.7:80/api/config/categories/1" type="application/vnd.abiquo.category+xml" rel="category" title="Others"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2" type="application/vnd.abiquo.datacenterrepository+xml" rel="datacenterrepository"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf?format=diskFile" rel="diskfile"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2/virtualmachinetemplates/11" type="application/vnd.abiquo.virtualmachinetemplate+xml" rel="edit" title="m0n0wall-vhd"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1" type="application/vnd.abiquo.enterprise+xml" rel="enterprise"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf?format=envelope" rel="ovfdocument"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf" rel="template"/> - <link href="http://rs:9000/ovf/269/desc.ovf" rel="templatedefinition"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf?format=status" rel="templatestatus"/> - <id>11</id> - <name>m0n0wall-vhd</name> - <description>m0n0wall image in VHD format ready for XenServer and HyperV</description> - <path>1/rs/abiport9000/ovf/269/m0n0wall-1.3b18-i386-flat.vmdk-VHD_SPARSE.vhd</path> - <diskFormatType>VHD_SPARSE</diskFormatType> - <diskFileSize>10490880</diskFileSize> - <cpuRequired>1</cpuRequired> - <ramRequired>128</ramRequired> - <hdRequired>27262976</hdRequired> - <shared>false</shared> - <costCode>0</costCode> - <creationDate>2013-01-10T20:25:12-05:00</creationDate> - <creationUser>SYSTEM</creationUser> - <chefEnabled>false</chefEnabled> - <iconUrl>http://icons.abiquo.com/monowall.jpg</iconUrl> -</virtualMachineTemplate> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_templates.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_templates.xml deleted file mode 100644 index a165f1235c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_templates.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<virtualMachineTemplates> - <virtualMachineTemplate> - <link href="http://10.60.12.7:80/api/config/categories/1" type="application/vnd.abiquo.category+xml" rel="category" title="Others"/><link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2" type="application/vnd.abiquo.datacenterrepository+xml" rel="datacenterrepository"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf?format=diskFile" rel="diskfile"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2/virtualmachinetemplates/11" type="application/vnd.abiquo.virtualmachinetemplate+xml" rel="edit" title="m0n0wall-vhd"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1" type="application/vnd.abiquo.enterprise+xml" rel="enterprise"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf?format=envelope" rel="ovfdocument"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf" rel="template"/> - <link href="http://rs:9000/ovf/269/desc.ovf" rel="templatedefinition"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/269/desc.ovf?format=status" rel="templatestatus"/> - <id>11</id><name>m0n0wall-vhd</name><description>m0n0wall image in VHD format ready for XenServer and HyperV</description><path>1/rs/abiport9000/ovf/269/m0n0wall-1.3b18-i386-flat.vmdk-VHD_SPARSE.vhd</path><diskFormatType>VHD_SPARSE</diskFormatType><diskFileSize>10490880</diskFileSize><cpuRequired>1</cpuRequired><ramRequired>128</ramRequired><hdRequired>27262976</hdRequired><shared>false</shared><costCode>0</costCode><creationDate>2013-01-10T20:25:12-05:00</creationDate><creationUser>SYSTEM</creationUser><chefEnabled>false</chefEnabled><iconUrl>http://icons.abiquo.com/monowall.jpg</iconUrl></virtualMachineTemplate> - <virtualMachineTemplate> - <link href="http://10.60.12.7:80/api/config/categories/1" type="application/vnd.abiquo.category+xml" rel="category" title="Others"/> - <link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2" type="application/vnd.abiquo.datacenterrepository+xml" rel="datacenterrepository"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/73/desc.ovf?format=diskFile" rel="diskfile"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2/virtualmachinetemplates/19" type="application/vnd.abiquo.virtualmachinetemplate+xml" rel="edit" title="RHEL6 Build Bot"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1" type="application/vnd.abiquo.enterprise+xml" rel="enterprise"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/73/desc.ovf?format=envelope" rel="ovfdocument"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/73/desc.ovf" rel="template"/> - <link href="http://rs:9000/ovf/73/desc.ovf" rel="templatedefinition"/> - <link href="http://10.60.12.7:80/am/erepos/1/templates/rs%3A9000/ovf/73/desc.ovf?format=status" rel="templatestatus"/> - <id>19</id> - <name>RHEL6 Build Bot</name> - <description>RHEL6 Build Bot</description> - <path>1/rs/abiport9000/ovf/73/build-bot-rhel6-disk1.vmdk</path> - <diskFormatType>VMDK_STREAM_OPTIMIZED</diskFormatType> - <diskFileSize>351064576</diskFileSize> - <cpuRequired>1</cpuRequired> - <ramRequired>1024</ramRequired> - <hdRequired>4294967296</hdRequired> - <shared>false</shared> - <costCode>0</costCode> - <creationDate>2013-01-10T20:25:12-05:00</creationDate> - <creationUser>SYSTEM</creationUser> - <chefEnabled>false</chefEnabled> - <iconUrl>http://rs.bcn.abiquo.com:9000/public/icons/q.png</iconUrl> - </virtualMachineTemplate> -</virtualMachineTemplates> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcreps.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcreps.xml deleted file mode 100644 index b8b4fca982..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/ent_1_dcreps.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<datacenterRepositories> - <datacenterRepository> - <link href="http://10.60.12.7:80/am/erepos/1" rel="applianceManagerRepositoryUri"/><link href="http://10.60.12.7:80/api/admin/datacenters/2" type="application/vnd.abiquo.datacenter+xml" rel="datacenter" title="barcelona"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2" type="application/vnd.abiquo.datacenterrepository+xml" rel="edit"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1" type="application/vnd.abiquo.enterprise+xml" rel="enterprise"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2/actions/refresh" rel="refresh"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/datacenterrepositories/2/virtualmachinetemplates" type="application/vnd.abiquo.virtualmachinetemplates+xml" rel="virtualmachinetemplates"/> - <id>2</id><name>virtual image repo</name><repositoryCapacityMb>0</repositoryCapacityMb><repositoryLocation>10.60.1.72:/opt/vm_repository</repositoryLocation><repositoryRemainingMb>0</repositoryRemainingMb></datacenterRepository> -</datacenterRepositories> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/login.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/login.xml deleted file mode 100644 index 32ac4d4938..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/login.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<user> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/users/2" type="application/vnd.abiquo.user+xml" rel="edit"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1" type="application/vnd.abiquo.enterprise+xml" rel="enterprise"/> - <link href="http://10.60.12.7:80/api/admin/roles/2" type="application/vnd.abiquo.role+xml" rel="role"/> - <link href="http://10.60.12.7:80/api/admin/enterprises/1/users/2/action/virtualmachines" type="application/vnd.abiquo.virtualmachines+xml" rel="virtualmachines"/> - <active>true</active> - <authType>ABIQUO</authType> - <description>Standard user</description> - <email></email> - <id>2</id> - <locale>en_US</locale> - <name>Standard</name> - <nick>user</nick> - <password>c69a39bd64ffb77ea7ee3369dce742f3</password> - <surname>User</surname> -</user> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/not_found_error.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/not_found_error.xml deleted file mode 100644 index 8aeb650dc0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/not_found_error.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<errors> - <error> - <code>DC-0</code> - <message>The requested datacenter does not exist</message> - </error> -</errors> diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/privilege_errors.html b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/privilege_errors.html deleted file mode 100644 index 888e4bd751..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/privilege_errors.html +++ /dev/null @@ -1,23 +0,0 @@ -<html> - <head> - <title>Apache Tomcat/6.0.35 - Error report - - - -

HTTP Status 403 - Access is denied

-
-

- type - Status report

-

- message - Access is denied -

-

- description - Access to the specified resource (Access is denied) has been forbidden. -

-
-

Apache Tomcat/6.0.35

- - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/unauthorized_user.html b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/unauthorized_user.html deleted file mode 100644 index b35026da38..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/unauthorized_user.html +++ /dev/null @@ -1,23 +0,0 @@ - - - Apache Tomcat/6.0.35 - Error report - - - -

HTTP Status 401 - Bad credentials

-
-

- type - Status report

-

- message - Bad credentials -

-

- description - This request requires HTTP authentication (Bad credentials). -

-
-

Apache Tomcat/6.0.35

- - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4.xml deleted file mode 100644 index 54f295745f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - KVM - 4 - vdc_kvm - - - - -
192.168.0.0
- - 192.168.0.1 - 2 - 24 - default_private_network - - - - INTERNAL -
-
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5.xml deleted file mode 100644 index 171f1aba74..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - 0 - 0 - 5 - libcloud_test_group - 0 - NOT_DEPLOYED - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_needs_sync.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_needs_sync.xml deleted file mode 100644 index 4f831b2cbe..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_needs_sync.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - 0 - 0 - 5 - libcloud_test_group - 0 - NEEDS_SYNC - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vm_3_not_allocated.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vm_3_not_allocated.xml deleted file mode 100644 index 6b70396848..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vm_3_not_allocated.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - 1 - 27262976 - 0 - 3 - 1 - 1 - ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614 - 128 - NOT_ALLOCATED - 914f8125-33d3-4fe3-a162-5d6f5bf32614 - 0 - 3 - node-name - 0 - 0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vms.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vms.xml deleted file mode 100644 index 5a4eefd9d7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vms.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 1272629760311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf3261403node-name00 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6.xml deleted file mode 100644 index 4e0e069067..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - 0 - 0 - 6 - libcloud - <connections/> - 0 - DEPLOYED - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy.xml deleted file mode 100644 index a20e8bd181..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task.xml deleted file mode 100644 index 96db33bc5d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Undeploy task's power off on virtual machine with id 3 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.103a1a6b-4de2-48d8-9a38-8698561020b8 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a - UNKNOWN - DONE - 1358012669 - POWER_OFF - - - Undeploy task's deconfigure on virtual machine with id 3 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.e4250ca9-505d-4640-9ad2-fb101f9e9978 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a - UNKNOWN - DONE - 1358012669 - DECONFIGURE - - - 3 - FINISHED_SUCCESSFULLY - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a - 1358012669 - UNDEPLOY - admin - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task_failed.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task_failed.xml deleted file mode 100644 index 9f4ce06231..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task_failed.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Undeploy task's power off on virtual machine with id 3 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.103a1a6b-4de2-48d8-9a38-8698561020b8 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a - UNKNOWN - DONE - 1358012669 - POWER_OFF - - - Undeploy task's deconfigure on virtual machine with id 3 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.e4250ca9-505d-4640-9ad2-fb101f9e9978 - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a - UNKNOWN - DONE - 1358012669 - DECONFIGURE - - - 3 - FINISHED_UNSUCCESSFULLY - 1da8c8b6-86f6-49ef-9d29-57dcc73b875a - 1358012669 - UNDEPLOY - admin - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3.xml deleted file mode 100644 index 17efdc4ad9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 1272629760311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf3261459013node-name0080.12.23.43 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_allocated.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_allocated.xml deleted file mode 100644 index 2135a00d1a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_allocated.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 1272629760311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf3261459013node-name0080.12.23.43 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy.xml deleted file mode 100644 index 2e376c6dc4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy.xml +++ /dev/null @@ -1,3 +0,0 @@ - - -You can keep track of the progress in the link diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task.xml deleted file mode 100644 index 11cc5ed63d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Deploy task's configure on virtual machine with id 3 - b44fe278-6b0f-4dfb-be81-7c03006a93cb.a04623bd-7b2c-4c23-9441-aeaa39dd4893 - b44fe278-6b0f-4dfb-be81-7c03006a93cb - UNKNOWN - DONE - 1357872859 - CONFIGURE - - - Deploy task's power on on virtual machine with id 3 - b44fe278-6b0f-4dfb-be81-7c03006a93cb.2fdee19a-4fad-4040-bc94-7acfd6fedc48 - b44fe278-6b0f-4dfb-be81-7c03006a93cb - UNKNOWN - DONE - 1357872859 - POWER_ON - - - 3 - FINISHED_SUCCESSFULLY - b44fe278-6b0f-4dfb-be81-7c03006a93cb - 1357872859 - DEPLOY - user - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task_failed.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task_failed.xml deleted file mode 100644 index 80f85baec1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task_failed.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Deploy task's configure on virtual machine with id 3 - b44fe278-6b0f-4dfb-be81-7c03006a93cb.a04623bd-7b2c-4c23-9441-aeaa39dd4893 - b44fe278-6b0f-4dfb-be81-7c03006a93cb - UNKNOWN - DONE - 1357872859 - CONFIGURE - - - Deploy task's power on on virtual machine with id 3 - b44fe278-6b0f-4dfb-be81-7c03006a93cb.2fdee19a-4fad-4040-bc94-7acfd6fedc48 - b44fe278-6b0f-4dfb-be81-7c03006a93cb - UNKNOWN - DONE - 1357872859 - POWER_ON - - - 3 - ABORTED - b44fe278-6b0f-4dfb-be81-7c03006a93cb - 1357872859 - DEPLOY - user - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deployed.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deployed.xml deleted file mode 100644 index 648da69893..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deployed.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 1272629760311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128ON914f8125-33d3-4fe3-a162-5d6f5bf3261459013node-name0080.12.23.43 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_nics.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_nics.xml deleted file mode 100644 index 5825c0498e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_nics.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - 64192.168.0.252:54:00:b7:f7:850 - - - 36434.34.34.552:54:00:b7:f7:880 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset.xml deleted file mode 100644 index 05b858af4f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - You can keep track of the progress in the link - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset_task.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset_task.xml deleted file mode 100644 index 3cff94b90b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset_task.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Reset task's reset on virtual machine with id 3 - a8c9818e-f389-45b7-be2c-3db3a9689940.5f42a7fc-82f3-4121-be26-da62eb8b9b92 - a8c9818e-f389-45b7-be2c-3db3a9689940 - ROLLBACK_DONE - FAILED - 1357873142 - RESET - - - 3 - FINISHED_SUCCESSFULLY - a8c9818e-f389-45b7-be2c-3db3a9689940 - 1357873142 - RESET - user - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy.xml deleted file mode 100644 index 05b858af4f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - You can keep track of the progress in the link - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task.xml deleted file mode 100644 index 3cff94b90b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Reset task's reset on virtual machine with id 3 - a8c9818e-f389-45b7-be2c-3db3a9689940.5f42a7fc-82f3-4121-be26-da62eb8b9b92 - a8c9818e-f389-45b7-be2c-3db3a9689940 - ROLLBACK_DONE - FAILED - 1357873142 - RESET - - - 3 - FINISHED_SUCCESSFULLY - a8c9818e-f389-45b7-be2c-3db3a9689940 - 1357873142 - RESET - user - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task_failed.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task_failed.xml deleted file mode 100644 index 007c12bea6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task_failed.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Reset task's reset on virtual machine with id 3 - a8c9818e-f389-45b7-be2c-3db3a9689940.5f42a7fc-82f3-4121-be26-da62eb8b9b92 - a8c9818e-f389-45b7-be2c-3db3a9689940 - ROLLBACK_DONE - FAILED - 1357873142 - RESET - - - 3 - FINISHED_UNSUCCESSFULLY - a8c9818e-f389-45b7-be2c-3db3a9689940 - 1357873142 - RESET - user - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_creation_ok.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_creation_ok.xml deleted file mode 100644 index 3bc9f0b2b8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_creation_ok.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - -1272629760311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf326140 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms.xml deleted file mode 100644 index 5a4eefd9d7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 1272629760311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf3261403node-name00 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms_allocated.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms_allocated.xml deleted file mode 100644 index a1658f0c8a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms_allocated.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - 1272629760311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf3261403node-name00 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_creation_ok.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_creation_ok.xml deleted file mode 100644 index 30baf15c78..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_creation_ok.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - 0 - 0 - 5 - libcloud_test_group - 0 - NOT_DEPLOYED - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapps.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapps.xml deleted file mode 100644 index f4271aa411..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdc_4_vapps.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - 2 - - - - - - - - - - 006libcloud0DEPLOYED - - - - - - - - - - 005libcloud_test_group0NOT_DEPLOYED - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdcs.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdcs.xml deleted file mode 100644 index 726b99e45e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/abiquo/vdcs.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - KVM - 4 - vdc_kvm - - - - -
192.168.0.0
- - 192.168.0.1 - 2 - 24 - default_private_network - - - - INTERNAL -
-
-
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_block_products_json.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_block_products_json.json deleted file mode 100644 index b3baa12d5b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_block_products_json.json +++ /dev/null @@ -1 +0,0 @@ -[{"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}, {"cost": 0.25, "id": "b412f354-5056-4bf0-a42f-6ddd998aa092", "description": "Block 2GB Virtual Server"}, {"cost": 0.35, "id": "0cd183d3-0287-4b1a-8288-b3ea8302ed58", "description": "Block 4GB Virtual Server"}, {"cost": 0.45, "id": "b9b87a5b-2885-4a2e-b434-44a163ca6251", "description": "Block 8GB Virtual Server"}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_block_templates_json.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_block_templates_json.json deleted file mode 100644 index 2ea7cb620a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_block_templates_json.json +++ /dev/null @@ -1 +0,0 @@ -[{"public": true, "id": "c66b8145-f768-45ef-9878-395bf8b1b7ff", "description": "CentOS 5 (Latest Release)", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "1fc24f51-6d7d-4fa9-9a6e-0d6f36b692e2", "description": "Ubuntu 8.10 64bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "b6f152db-988c-4194-b292-d6dd2aa2dbab", "description": "Debian 5.0 64bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "4b697e48-282b-4140-8cf8-142e2a2711ee", "description": "Ubuntu 8.04 LTS 64bit", "created": "2009/07/31 15:58:20 -0700"}, {"public": true, "id": "a6a141bf-592a-4fa6-b130-4c14f69e82d0", "description": "Ubuntu 8.04 LTS 32Bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "b181033f-aea7-4e6c-8bb4-11169775c0f8", "description": "Ubuntu 9.04 64bit", "created": "2010/01/26 11:31:19 -0800"}, {"public": true, "id": "b5371c5a-9da2-43ee-a745-99a4723f624c", "description": "ArchLinux 2009.08 64bit", "created": "2010/02/13 18:07:01 -0800"}, {"public": true, "id": "a00baa8f-b5d0-4815-8238-b471c4c4bf72", "description": "Ubuntu 9.10 64bit", "created": "2010/02/17 22:06:21 -0800"}, {"public": true, "id": "03807e08-a13d-44e4-b011-ebec7ef2c928", "description": "Ubuntu 10.04 LTS 64bit", "created": "2010/05/04 14:43:30 -0700"}, {"public": true, "id": "8b60e6de-7cbc-4c8e-b7df-5e2f9c4ffd6b", "description": "Ubuntu 10.04 LTS 32bit", "created": "2010/05/04 14:43:30 -0700"}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json deleted file mode 100644 index 9db716d7d1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json +++ /dev/null @@ -1 +0,0 @@ -{"ips": [{"address": "67.214.214.212"}], "memory": 1073741824, "template": "centos", "id": "99df878c-6e5c-4945-a635-d94da9fd3146", "storage": 21474836480, "hostname": "apitest.c44905.c44905.blueboxgrid.com", "description": "1 GB RAM + 20 GB Disk", "cpu": 0.5, "status": "running", "product": {"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json deleted file mode 100644 index 934a00f420..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json +++ /dev/null @@ -1 +0,0 @@ -{"text":"Block destroyed."} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json deleted file mode 100644 index 2ea54d2232..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json +++ /dev/null @@ -1 +0,0 @@ -{ "status": "ok", "text": "Reboot initiated." } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_json.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_json.json deleted file mode 100644 index eb7d35ff6e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_json.json +++ /dev/null @@ -1 +0,0 @@ -[{"ips":[{"address":"67.214.214.212"}],"memory":1073741824,"id":"99df878c-6e5c-4945-a635-d94da9fd3146","storage":21474836480,"hostname":"foo.apitest.blueboxgrid.com","description":"1 GB RAM + 20 GB Disk","cpu":0.5,"status":"running"}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_json_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_json_post.json deleted file mode 100644 index 4452f7185b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/bluebox/api_blocks_json_post.json +++ /dev/null @@ -1 +0,0 @@ -{"ips":[{"address":"67.214.214.212"}],"memory":1073741824,"id":"99df878c-6e5c-4945-a635-d94da9fd3146","storage":21474836480,"hostname":"foo.apitest.blueboxgrid.com","description":"1 GB RAM + 20 GB Disk","cpu":0.5,"status":"queued", "product": {"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_cloud_ip.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_cloud_ip.json deleted file mode 100644 index cdbb1780b9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_cloud_ip.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "id": "cip-jsjc5", - "interface": null, - "load_balancer": null, - "public_ip": "109.107.37.234", - "resource_type": "cloud_ip", - "reverse_dns": "cip-109-107-37-234.gb1.brightbox.com", - "server": null, - "server_group": null, - "status": "unmapped", - "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-jsjc5" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server.json deleted file mode 100644 index e4b31226ba..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server.json +++ /dev/null @@ -1,62 +0,0 @@ -{"id": "srv-3a97e", - "url": "servers/(server_id)", - "name": "My web server", - "status": "active", - "hostname": "srv-3a97e.gb1.brightbox.com", - "created_at": "", - "deleted_at": "", - "started_at": "", - "account": - {"id": "acc-3jd8s", - "url": "accounts/(account_id)", - "name": "Brightbox Systems Ltd.", - "status": "verified", - "ram_limit": 20480, - "ram_used": 2048, - "limits_cloudips": 5}, - "image": - {"id": "img-9vxqi", - "url": "images/(image_id)", - "name": "Brightbox Lucid 32", - "status": "available", - "description": "Jeremy's debian ec2 image", - "source": "jeremy_debian-32_ec2", - "source_type": "upload", - "arch": "32-bit", - "created_at": "", - "owner": "acc-bright"}, - "server_type": - {"id": "typ-a97e6", - "url": "server_types/(server_type_id)", - "handle": "nano", - "name": "Brightbox Nano", - "status": "", - "cores": 2, - "ram": 2048, - "disk_size": ""}, - "zone": - {"id": "zon-8ja0a", - "url": "zones/(zone_id)", - "handle": "gb1-a"}, - "snapshots": - [{"id": "img-9vxqi", - "url": "images/(image_id)", - "name": "Brightbox Lucid 32", - "status": "available", - "description": "Jeremy's debian ec2 image", - "source": "jeremy_debian-32_ec2", - "source_type": "upload", - "arch": "32-bit", - "created_at": "", - "owner": "acc-bright"}], - "cloud_ips": - [{"id": "cip-ja8ub", - "url": "cloud_ips/(cloud_ip_id)", - "public_ip": "109.107.42.129", - "status": "mapped", - "reverse_dns": "cip-109-107-42-129.gb1.brightbox.com"}], - "interfaces": - [{"id": "int-mc3a9", - "url": "interfaces/(interface_id)", - "mac_address": "02:24:19:6e:18:36", - "ipv4_address": "10.110.24.54"}]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server_gb1_a.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server_gb1_a.json deleted file mode 100644 index 5d18aab043..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server_gb1_a.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "cloud_ips": [], - "console_token": null, - "console_token_expires": null, - "console_url": null, - "created_at": "2012-04-12T10:58:49Z", - "deleted_at": null, - "fqdn": "srv-p61uj.gb1.brightbox.com", - "hostname": "srv-p61uj", - "id": "srv-p61uj", - "image": { - "arch": "x86_64", - "created_at": "2012-04-11T01:36:19Z", - "description": "Standard server with cloud-init", - "id": "img-n4yek", - "name": "Ubuntu Precise 12.04 LTS server", - "owner": "acc-tqs4c", - "resource_type": "image", - "source": "precise-amd64-17903.gz", - "status": "deprecated", - "url": "https://api.gb1.brightbox.com/1.0/images/img-n4yek", - "username": "ubuntu" - }, - "interfaces": [ - { - "id": "int-ctud9", - "ipv4_address": "10.240.156.30", - "ipv6_address": "2a02:1348:14c:2707:24:19ff:fef0:9c1e", - "mac_address": "02:24:19:f0:9c:1e", - "resource_type": "interface", - "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-ctud9" - } - ], - "name": "Test Node", - "resource_type": "server", - "server_groups": [ - { - "created_at": "2011-08-24T08:41:56Z", - "default": true, - "description": "All new servers are added to this group unless specified otherwise.", - "id": "grp-irgkb", - "name": "default", - "resource_type": "server_group", - "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" - } - ], - "server_type": { - "cores": 2, - "disk_size": 20480, - "handle": "nano", - "id": "typ-4nssg", - "name": "Brightbox Nano Instance", - "ram": 512, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-4nssg" - }, - "snapshots": [], - "started_at": null, - "status": "creating", - "url": "https://api.gb1.brightbox.com/1.0/servers/srv-p61uj", - "user_data": null, - "zone": { - "handle": "gb1-a", - "id": "zon-6mxqw", - "resource_type": "zone", - "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server_gb1_b.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server_gb1_b.json deleted file mode 100644 index b00b6a4316..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/create_server_gb1_b.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "cloud_ips": [], - "console_token": null, - "console_token_expires": null, - "console_url": null, - "created_at": "2012-04-12T11:01:51Z", - "deleted_at": null, - "fqdn": "srv-nnumd.gb1.brightbox.com", - "hostname": "srv-nnumd", - "id": "srv-nnumd", - "image": { - "arch": "x86_64", - "created_at": "2012-04-11T01:36:19Z", - "description": "Standard server with cloud-init", - "id": "img-n4yek", - "name": "Ubuntu Precise 12.04 LTS server", - "owner": "acc-tqs4c", - "resource_type": "image", - "source": "precise-amd64-17903.gz", - "status": "deprecated", - "url": "https://api.gb1.brightbox.com/1.0/images/img-n4yek", - "username": "ubuntu" - }, - "interfaces": [ - { - "id": "int-2chhk", - "ipv4_address": "10.232.142.194", - "ipv6_address": "2a02:1348:14d:23b0:24:19ff:fee8:8ec2", - "mac_address": "02:24:19:e8:8e:c2", - "resource_type": "interface", - "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-2chhk" - } - ], - "name": "Test Node", - "resource_type": "server", - "server_groups": [ - { - "created_at": "2011-08-24T08:41:56Z", - "default": true, - "description": "All new servers are added to this group unless specified otherwise.", - "id": "grp-irgkb", - "name": "default", - "resource_type": "server_group", - "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" - } - ], - "server_type": { - "cores": 2, - "disk_size": 20480, - "handle": "nano", - "id": "typ-4nssg", - "name": "Brightbox Nano Instance", - "ram": 512, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-4nssg" - }, - "snapshots": [], - "started_at": null, - "status": "creating", - "url": "https://api.gb1.brightbox.com/1.0/servers/srv-nnumd", - "user_data": null, - "zone": { - "handle": "gb1-b", - "id": "zon-remk1", - "resource_type": "zone", - "url": "https://api.gb1.brightbox.com/1.0/zones/zon-remk1" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_cloud_ips.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_cloud_ips.json deleted file mode 100644 index 2697c8076e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_cloud_ips.json +++ /dev/null @@ -1,96 +0,0 @@ -[ - { - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "id": "cip-tlrp3", - "interface": null, - "load_balancer": null, - "public_ip": "109.107.35.16", - "resource_type": "cloud_ip", - "reverse_dns": "cip-109-107-35-16.gb1.brightbox.com", - "server": null, - "server_group": null, - "status": "unmapped", - "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-tlrp3" - }, - { - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "id": "cip-w8vbt", - "interface": null, - "load_balancer": null, - "public_ip": "109.107.35.76", - "resource_type": "cloud_ip", - "reverse_dns": "cip-109-107-35-76.gb1.brightbox.com", - "server": null, - "server_group": null, - "status": "unmapped", - "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-w8vbt" - }, - { - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "id": "cip-uswab", - "interface": { - "id": "int-ztqbx", - "ipv4_address": "10.240.228.234", - "ipv6_address": "2a02:1348:14c:393a:24:19ff:fef0:e4ea", - "mac_address": "02:24:19:f0:e4:ea", - "resource_type": "interface", - "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-ztqbx" - }, - "load_balancer": null, - "public_ip": "109.107.35.105", - "resource_type": "cloud_ip", - "reverse_dns": "cip-109-107-35-105.gb1.brightbox.com", - "server": { - "created_at": "2012-01-30T14:42:28Z", - "deleted_at": null, - "fqdn": "srv-742vn.gb1.brightbox.com", - "hostname": "srv-742vn", - "id": "srv-742vn", - "name": "Kernel builder", - "resource_type": "server", - "started_at": "2012-03-28T15:26:43Z", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/servers/srv-742vn" - }, - "server_group": null, - "status": "mapped", - "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-uswab" - }, - { - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "id": "cip-ui4n1", - "interface": null, - "load_balancer": null, - "public_ip": "109.107.37.135", - "resource_type": "cloud_ip", - "reverse_dns": "cip-109-107-37-135.gb1.brightbox.com", - "server": null, - "server_group": null, - "status": "unmapped", - "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-ui4n1" - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_images.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_images.json deleted file mode 100644 index 0dbf75cad2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_images.json +++ /dev/null @@ -1,89 +0,0 @@ -[ - { - "ancestor": { - "arch": "i686", - "created_at": "2010-10-04T19:03:37Z", - "description": "Creates a blank disk", - "id": "img-6lybc", - "name": "Blank Image", - "owner": "acc-tqs4c", - "resource_type": "image", - "source": "blank_10G", - "status": "deleted", - "url": "https://api.gb1.brightbox.com/1.0/images/img-6lybc", - "username": null - }, - "arch": "i686", - "compatibility_mode": false, - "created_at": "2010-10-02T19:03:37Z", - "description": "login: root using stored ssh key", - "disk_size": 1086, - "id": "img-99q79", - "min_ram": null, - "name": "CentOS 5.5 server", - "official": true, - "owner": "acc-tqs4c", - "public": true, - "resource_type": "image", - "source": "srv-s4mfq", - "source_type": "upload", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/images/img-99q79", - "username": null, - "virtual_size": 10244 - }, - { - "ancestor": { - "arch": "i686", - "created_at": "2010-10-04T19:03:37Z", - "description": "Creates a blank disk", - "id": "img-6lybc", - "name": "Blank Image", - "owner": "acc-tqs4c", - "resource_type": "image", - "source": "blank_10G", - "status": "deleted", - "url": "https://api.gb1.brightbox.com/1.0/images/img-6lybc", - "username": null - }, - "arch": "x86_64", - "compatibility_mode": false, - "created_at": "2010-10-03T19:03:37Z", - "description": "login: root using stored ssh key", - "disk_size": 1133, - "id": "img-pnqnc", - "min_ram": null, - "name": "CentOS 5.5 server", - "official": true, - "owner": "acc-tqs4c", - "public": true, - "resource_type": "image", - "source": "srv-53fez", - "source_type": "upload", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/images/img-pnqnc", - "username": null, - "virtual_size": 10240 - }, - { - "ancestor": null, - "arch": "i686", - "compatibility_mode": false, - "created_at": "2012-01-22T05:36:24Z", - "description": "Standard server with cloud-init", - "disk_size": 671, - "id": "img-joo06", - "min_ram": null, - "name": "Ubuntu Oneiric 11.10 server", - "official": false, - "owner": "acc-tqs4c", - "public": true, - "resource_type": "image", - "source": "oneiric-i386-20178.gz", - "source_type": "upload", - "status": "deprecated", - "url": "https://api.gb1.brightbox.com/1.0/images/img-joo06", - "username": "ubuntu", - "virtual_size": 1025 - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_server_types.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_server_types.json deleted file mode 100644 index 1066230d81..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_server_types.json +++ /dev/null @@ -1,79 +0,0 @@ -[ - { - "cores": 2, - "disk_size": 20480, - "handle": "nano", - "id": "typ-4nssg", - "name": "Brightbox Nano Instance", - "ram": 512, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-4nssg" - }, - { - "cores": 8, - "disk_size": 163840, - "handle": "medium", - "id": "typ-qdiwq", - "name": "Brightbox Medium Instance", - "ram": 4096, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-qdiwq" - }, - { - "cores": 4, - "disk_size": 81920, - "handle": "small", - "id": "typ-urtky", - "name": "Brightbox Small Instance", - "ram": 2048, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-urtky" - }, - { - "cores": 8, - "disk_size": 327680, - "handle": "large", - "id": "typ-mlbt7", - "name": "Brightbox Large Instance", - "ram": 8192, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-mlbt7" - }, - { - "cores": 4, - "disk_size": 40960, - "handle": "mini", - "id": "typ-iqisj", - "name": "Brightbox Mini Instance", - "ram": 1024, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-iqisj" - }, - { - "cores": 8, - "disk_size": 655360, - "handle": "xl", - "id": "typ-wdicw", - "name": "Brightbox XL Instance", - "ram": 16384, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-wdicw" - }, - { - "cores": 8, - "disk_size": 1310720, - "handle": "xxl", - "id": "typ-lr76m", - "name": "Brightbox XXL Instance", - "ram": 32768, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-lr76m" - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_servers.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_servers.json deleted file mode 100644 index e7d45d4617..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_servers.json +++ /dev/null @@ -1,155 +0,0 @@ - -[ - { - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "cloud_ips": [ - { - "id": "cip-tlrp3", - "public_ip": "109.107.35.16", - "resource_type": "cloud_ip", - "reverse_dns": "cip-109-107-35-16.gb1.brightbox.com", - "status": "mapped", - "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-tlrp3" - } - ], - "created_at": "2010-10-14T10:02:38Z", - "deleted_at": null, - "fqdn": "srv-xvpn7.gb1.brightbox.com", - "hostname": "srv-xvpn7", - "id": "srv-xvpn7", - "image": { - "arch": "i686", - "created_at": "2010-10-11T15:23:51Z", - "description": "", - "id": "img-arm8f", - "name": "Snapshot of srv-vf2a4 11 Oct 15:23", - "owner": "acc-tqs4c", - "resource_type": "image", - "source": "srv-vf2a4", - "status": "deleted", - "url": "https://api.gb1.brightbox.com/1.0/images/img-arm8f", - "username": null - }, - "interfaces": [ - { - "id": "int-519up", - "ipv4_address": "10.74.210.210", - "mac_address": "02:24:19:4a:d2:d2", - "resource_type": "interface", - "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-519up" - } - ], - "name": "Ubuntu Image Builder Box", - "resource_type": "server", - "server_groups": [ - { - "created_at": "2011-08-24T08:41:56Z", - "default": true, - "description": "All new servers are added to this group unless specified otherwise.", - "id": "grp-irgkb", - "name": "default", - "resource_type": "server_group", - "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" - } - ], - "server_type": { - "cores": 4, - "disk_size": 81920, - "handle": "small", - "id": "typ-urtky", - "name": "Brightbox Small Instance", - "ram": 2048, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-urtky" - }, - "snapshots": [], - "started_at": "2012-03-28T15:25:56Z", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/servers/srv-xvpn7", - "zone": { - "handle": "gb1-a", - "id": "zon-6mxqw", - "resource_type": "zone", - "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" - } - }, - { - "account": { - "id": "acc-tqs4c", - "name": "bbctest", - "resource_type": "account", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/account" - }, - "cloud_ips": [], - "created_at": "2012-01-30T14:42:28Z", - "deleted_at": null, - "fqdn": "srv-742vn.gb1.brightbox.com", - "hostname": "srv-742vn", - "id": "srv-742vn", - "image": { - "arch": "x86_64", - "created_at": "2012-01-30T13:25:09Z", - "description": "", - "id": "img-j93gd", - "name": "Snapshot of srv-k0pug 30 Jan 13:25", - "owner": "acc-tqs4c", - "resource_type": "image", - "source": "srv-k0pug", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/images/img-j93gd", - "username": null - }, - "interfaces": [ - { - "id": "int-ztqbx", - "ipv4_address": "10.240.228.234", - "ipv6_address": "2a02:1348:14c:393a:24:19ff:fef0:e4ea", - "mac_address": "02:24:19:f0:e4:ea", - "resource_type": "interface", - "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-ztqbx" - } - ], - "name": "Kernel builder", - "resource_type": "server", - "server_groups": [ - { - "created_at": "2011-08-24T08:41:56Z", - "default": true, - "description": "All new servers are added to this group unless specified otherwise.", - "id": "grp-irgkb", - "name": "default", - "resource_type": "server_group", - "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" - } - ], - "server_type": { - "cores": 8, - "disk_size": 163840, - "handle": "medium", - "id": "typ-qdiwq", - "name": "Brightbox Medium Instance", - "ram": 4096, - "resource_type": "server_type", - "status": "available", - "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-qdiwq" - }, - "snapshots": [], - "started_at": "2012-03-28T15:26:43Z", - "status": "active", - "url": "https://api.gb1.brightbox.com/1.0/servers/srv-742vn", - "zone": { - "handle": "gb1-a", - "id": "zon-6mxqw", - "resource_type": "zone", - "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" - } - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_zones.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_zones.json deleted file mode 100644 index 5dad5e041a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/list_zones.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "handle": "gb1-a", - "id": "zon-6mxqw", - "resource_type": "zone", - "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" - }, - { - "handle": "gb1-b", - "id": "zon-remk1", - "resource_type": "zone", - "url": "https://api.gb1.brightbox.com/1.0/zones/zon-remk1" - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/token.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/token.json deleted file mode 100644 index 0c0f12ba06..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/brightbox/token.json +++ /dev/null @@ -1 +0,0 @@ -{"access_token":"k1bjflpsaj8wnrbrwzad0eqo36nxiha", "expires_in": 3600} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_cloudspace_find.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_cloudspace_find.xml deleted file mode 100644 index a42bd690b4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_cloudspace_find.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - -jobguid - - -result - -3e4f8bd5-718c-457e-86f4-024c560d7c28 - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_lan_find.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_lan_find.xml deleted file mode 100644 index 163a656c49..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_lan_find.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - -jobguid - - -result - -8d6a8b91-22fc-4be4-863b-11dc4456b315 - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_createFromTemplate.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_createFromTemplate.xml deleted file mode 100644 index fc4c138500..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_createFromTemplate.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid -e7b75dd9-f4b0-4c11-8b3f-748306964ad7 - - -result -96b2af78-88a0-48a6-a5bd-258e1d00c0b9 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_delete.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_delete.xml deleted file mode 100644 index 17e48384aa..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_delete.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid -ac93fbb6-6b5d-4248-a627-efba9f4d76c7 - - -result -1 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_physical.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_physical.xml deleted file mode 100644 index 002804a126..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_physical.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - -jobguid - - -result - -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_templates.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_templates.xml deleted file mode 100644 index f557ca1e90..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_templates.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - -jobguid - - -result - -0c4da918-9f88-4049-a09c-8ab69142736a - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_virtualdesktop.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_virtualdesktop.xml deleted file mode 100644 index 009a395970..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_virtualdesktop.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid - - -result - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_virtualserver.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_virtualserver.xml deleted file mode 100644 index 09b6ca0a52..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_find_virtualserver.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - -jobguid - - -result - -dea11e50-1b53-4046-8589-cf52eb7b0d25 -c52e4a42-72fe-4f34-bb80-c57d237fcbf9 -64f325ef-28ac-4907-bd37-572a13178edd -9a6b3101-b4ac-4ecb-b114-67d89994ac9b -1dd57d0d-0e23-471d-9f34-b673c7c18bc3 -d3c98151-f064-45fc-a90a-23c481723895 -01dedf71-0c37-441e-9687-085f8bb116ea - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_listSnapshots.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_listSnapshots.xml deleted file mode 100644 index 231a4cd42b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_listSnapshots.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - -jobguid - - -result - - - -description - - -backuplabel -somelabel - - -timestamp -2013-07-25 13:20:52.093959 - - -consistent -t - - -name -node-name-2013-07-25 13:20:52.093931 - - -snapshottype -PAUSED - - -guid -4685d9b5-80e8-44d8-a094-f6f799f90954 - - -parentmachineguid -26348bf8-2e2f-41e8-83c3-11fb5d14c9d2 - - - - -description - - -backuplabel - - -timestamp -2013-07-25 13:19:39.437168 - - -consistent -t - - -name -node-name-2013-07-25 13:19:39.437142 - - -snapshottype -PAUSED - - -guid -5c00bd9e-6c18-4bee-83bf-5ff14426868a - - -parentmachineguid -96b2af78-88a0-48a6-a5bd-258e1d00c0b9 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_01dedf71-0c37-441e-9687-085f8bb116ea.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_01dedf71-0c37-441e-9687-085f8bb116ea.xml deleted file mode 100644 index 8039aaa0e4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_01dedf71-0c37-441e-9687-085f8bb116ea.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -0 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -01dedf71-0c37-441e-9687-085f8bb116ea - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -CONFIGURED - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description -AUTOTEST_94a50c23-715d-4fbc-8cdf-c3f436e04ec0 - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -AUTOTEST_94a50c23-715d-4fbc-8cdf-c3f436e04ec0 - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_0c4da918-9f88-4049-a09c-8ab69142736a.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_0c4da918-9f88-4049-a09c-8ab69142736a.xml deleted file mode 100644 index 6f4af84758..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_0c4da918-9f88-4049-a09c-8ab69142736a.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -0 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -0c4da918-9f88-4049-a09c-8ab69142736a - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid -2 - - -system -0 - - -template -1 - - -memory -512 - - -agentguid - - -status -IMAGEONLY - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description -template_ubuntu_esx - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -411f22e3-2e04-431b-adc7-2a952d2cadc6 - - -name -ubuntu_esx - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_1dd57d0d-0e23-471d-9f34-b673c7c18bc3.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_1dd57d0d-0e23-471d-9f34-b673c7c18bc3.xml deleted file mode 100644 index 1fcc91ac89..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_1dd57d0d-0e23-471d-9f34-b673c7c18bc3.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -1 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -1dd57d0d-0e23-471d-9f34-b673c7c18bc3 - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid -3 - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -RUNNING - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -testvm_running - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_2aea45ee-3ea5-4b4f-88f0-7d4d48bed643.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_2aea45ee-3ea5-4b4f-88f0-7d4d48bed643.xml deleted file mode 100644 index c5fb1347f4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_2aea45ee-3ea5-4b4f-88f0-7d4d48bed643.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -0 - - -replicationstatus - - -machinerole -COMPUTENODE - - -isbackup -0 - - -guid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -machinetype -PHYSICAL - - -hostname -VMWARE-ESX-10-101-163-1 - - -vmachinemanagerid - - -system -0 - - -template -0 - - -memory -262111 - - -agentguid - - -status -RUNNING - - -nrcpu -24 - - -bootstatus -FROMDISK - - -description - - -importancefactor -5 - - -replicationrole - - -parentmachineguid - - -name -VMWARE-ESX-10-101-163-1 - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -esxi5 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_64f325ef-28ac-4907-bd37-572a13178edd.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_64f325ef-28ac-4907-bd37-572a13178edd.xml deleted file mode 100644 index 230ba4520c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_64f325ef-28ac-4907-bd37-572a13178edd.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -0 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -64f325ef-28ac-4907-bd37-572a13178edd - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid -9 - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -RUNNING - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -testvm_clone - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_96b2af78-88a0-48a6-a5bd-258e1d00c0b9.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_96b2af78-88a0-48a6-a5bd-258e1d00c0b9.xml deleted file mode 100644 index ed038e6edb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_96b2af78-88a0-48a6-a5bd-258e1d00c0b9.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -0 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -96b2af78-88a0-48a6-a5bd-258e1d00c0b9 - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -CREATED - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description -node-name - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -node-name - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_9a6b3101-b4ac-4ecb-b114-67d89994ac9b.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_9a6b3101-b4ac-4ecb-b114-67d89994ac9b.xml deleted file mode 100644 index 13afbd2bed..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_9a6b3101-b4ac-4ecb-b114-67d89994ac9b.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -1 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -9a6b3101-b4ac-4ecb-b114-67d89994ac9b - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid -7 - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -STOPPING - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -testvm_stopped - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_c52e4a42-72fe-4f34-bb80-c57d237fcbf9.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_c52e4a42-72fe-4f34-bb80-c57d237fcbf9.xml deleted file mode 100644 index 7db19fbcdf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_c52e4a42-72fe-4f34-bb80-c57d237fcbf9.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -1 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -c52e4a42-72fe-4f34-bb80-c57d237fcbf9 - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -CREATED - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -testvm_created - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_d3c98151-f064-45fc-a90a-23c481723895.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_d3c98151-f064-45fc-a90a-23c481723895.xml deleted file mode 100644 index d95bc44e9d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_d3c98151-f064-45fc-a90a-23c481723895.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -0 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -d3c98151-f064-45fc-a90a-23c481723895 - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -CONFIGURED - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description -AUTOTEST_ec71742b-bd74-4908-8327-717c349e0d79 - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -AUTOTEST_ec71742b-bd74-4908-8327-717c349e0d79 - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_dea11e50-1b53-4046-8589-cf52eb7b0d25.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_dea11e50-1b53-4046-8589-cf52eb7b0d25.xml deleted file mode 100644 index bd7575f5ed..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_list_machineguid_dea11e50-1b53-4046-8589-cf52eb7b0d25.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -jobguid - - -result - - - -backup -1 - - -replicationstatus - - -machinerole - - -isbackup -0 - - -guid -dea11e50-1b53-4046-8589-cf52eb7b0d25 - - -machinetype -VIRTUALSERVER - - -hostname - - -vmachinemanagerid -5 - - -system -0 - - -template -0 - - -memory -512 - - -agentguid - - -status -PAUSED - - -nrcpu -1 - - -bootstatus -FROMDISK - - -description - - -importancefactor -5 - - -replicationrole - - -parentmachineguid -2aea45ee-3ea5-4b4f-88f0-7d4d48bed643 - - -name -testvm_paused - - -hypervisor -VMWARE_ESX - - -replicationtype - - -os -ubuntu1010 - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_reboot.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_reboot.xml deleted file mode 100644 index e8780a3d74..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_reboot.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid -ab93fcb6-6b5d-4248-a627-efba9f4d76c7 - - -result -1 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_rollback.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_rollback.xml deleted file mode 100644 index d104a0e3ee..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_rollback.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid -ababacb6-7a5d-4248-a627-efba9f4d76c7 - - -result -1 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_snapshot.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_snapshot.xml deleted file mode 100644 index e417d546b6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_snapshot.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid -16556e13-a2f9-492c-b094-dc62bc7d2cc9 - - -result -5c00bd9e-6c18-4bee-83bf-5ff14426868a - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_start.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_start.xml deleted file mode 100644 index a9b50ed78b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_start.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid -ab93fcb6-7a5d-4248-a627-efba9f4d76c7 - - -result -1 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_stop.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_stop.xml deleted file mode 100644 index a9b50ed78b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudframes/_machine_stop.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -jobguid -ab93fcb6-7a5d-4248-a627-efba9f4d76c7 - - -result -1 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_clone.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_clone.txt deleted file mode 100644 index d18ae9e4e1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_clone.txt +++ /dev/null @@ -1,19 +0,0 @@ -status active -use dbserver,general -name SQL Server Standard 2008 R2 - Windows Server Standard 2008 R2 - 64bit English pub clone -bits 64 -url http://www.microsoft.com/sqlserver/2008/en/us/ -read:bytes 4096 -description Please refer to the install notes for a full guide to initial configuration. -write:bytes 21474840576 -drive a814def5-1789-49a0-bf88-7abe7bb1682a -install_notes ***You must update the default Administrator password for Windows Server Standard 2008 and the Super Administrator password (sa) for SQL Server Standard 2008***\n\nPre-installed Windows Server 2008 Standard R2 64bit English on 15/07/2010\n=========================================================================\n\n1. Minimum Hardware Requirements\n--------------------------------\n\nThe recommended minimum hardware requirements for the use of SQL Server Standard 2008 R2 with Windows Server Standard 2008 R2 as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/library/ms143506.aspx\n\n\n2. Update your administrator password\n-------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n3. Expanding your drive\n-----------------------\n\nThe system is fully installed, but you will need to extend the\ndisk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n4. Enabling Remote Access\n-------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection according to your Security Configuration\n\n\n5. Pinging Service\n------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules"\n\n\nSQL Server 2008 R2 on 15/07/2010\n================================\n\n1. Change the Super Administrator Password (sa). \n--------------------------------------------------------------------\n\nThe default password has been set to "CloudSigma1"\n\na) Open "Microsoft SQL Server Management Studio"\n\nb) Connect to the Server Using "Windows Indentificaiton"\n\nc) From the Object Explorer select "Security" then "Longins"\n\nd) Right-click on sa and select "Properties"\n\ne) Enter the new password into "Password" and "Confirm Password" and press "OK"\n\n\n2. The following features were installed:\n-----------------------------------------------------\n\na) Main features\n\n-Database Engine Services\n-SQL Server Replication\n-Full-Text Search\n-Analysis Services\n-Reporting Services\n\nb) Shared Features\n\n-Business Intelligengce Development Studio\n-Client Tools Connectivity\n-Integration Services\n-Clinet Tools Backwards Compatibility\n-Clinet Tools SDK\n-SQL Server Books Online\n-Mangement Tools - Basic\n-Management Tools - Complete\n-SQL Client Connectivity SDK\n-Microsoft Sync Framework\n\n3 The following services were configured:\n--------------------------------------------------------\n\n\nService: SQL Server Agent\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Manual\n\nService: SQL Server Database Engine\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Automatic\n\nService: SQL Server Analysis Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Reporting Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Integration Services 10.1\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n \nService: SQL Full-text filter Daemon Lanuch\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nService: SQL Server Browser\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nFor detailed server installation configuration refer to the following installation log files on the system:\nC:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20100716_162426\Summary_WIN-K0F21FV1C1V_20100716_162426.txt\n -volume 000431a5-46d9-4a67-9c03-3c3402a41992 -host 00043e69-ac57-45b1-8692-75db24064fb9 -os windows -user 93b34fd9-7986-4b25-8bfd-98a50383605d -read:requests 1 -licenses msft_p73_04837 msft_tfa_00009 -type disk -write:requests 5242881 -size 21474836480 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_info.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_info.txt deleted file mode 100644 index e9cc833bf0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_info.txt +++ /dev/null @@ -1,39 +0,0 @@ -status active -use general -name test node -bits 64 -url http://www.centos.org/ -read:bytes 4096 -description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. -write:bytes 21474840576 -os linux -drive 3d18db4b-f9bd-4313-b034-12ae181efa88 -install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 1 -free true -type disk -write:requests 5242881 -size 53687091200 - -status active -use general -name test node -bits 64 -url http://www.centos.org/ -read:bytes 4096 -description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. -write:bytes 21474840576 -os linux -drive 3d18db4b-f9bd-4313-b034-12ae181efa99 -install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 1 -free true -type disk -write:requests 5242881 -size 103687091200 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_single_info.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_single_info.txt deleted file mode 100644 index 6efe9aaea7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_single_info.txt +++ /dev/null @@ -1,19 +0,0 @@ -status active -use general -name test node -bits 64 -url http://www.centos.org/ -read:bytes 4096 -description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. -write:bytes 21474840576 -os linux -drive d18119ce_7afa_474a_9242_e0384b160220 -install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 1 -free true -type disk -write:requests 5242881 -size 53687091200 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_standard_info.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_standard_info.txt deleted file mode 100644 index 4a024114eb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/drives_standard_info.txt +++ /dev/null @@ -1,1735 +0,0 @@ -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Yoper is a multipurpose high performance operating system which has been carefully optimised for PC's with either 686 or higher processor types. The binaries that come with Yoper have been built from scratch using the original sources combined with the best features of major distros, measuring up to the demanding proliferation of network communications and more intensive digital multimedia, graphics and audio capabilities which are ushering in a new era of business productivity enabled by a new generation of sophisticated microprocessors, and business application tools. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 102401 -name Yoper 2010 Linux with XFCE Install CD -url http://yoper-linux.org/ -read:bytes 4096 -claim:type shared -drive 7e3e7628-d1e6-47c6-858d-7b54aac5c916 -write:bytes 419434496 -read:requests 1 -os linux - -type cdrom -size 2621440000 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description Ultimate Edition, first released in December 2006, is a fork of Ubuntu. The goal of the project is to create a complete, seamlessly integrated, visually stimulating, and easy-to-install operating system. Single-button upgrade is one of several special characteristics of this distribution. Other main features include custom desktop and theme with 3D effects, support for a wide range of networking options, including WiFi and Bluetooth, and integration of many extra applications and package repositories. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 640001 -name Ultimate 2.6 Linux 64bit Install CD -url http://ultimateedition.info/ -read:bytes 440279040 -claim:type shared -drive 526ed5cb-6fbe-46fb-a064-7707c844d774 -write:bytes 2621444096 -read:requests 107490 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description FreeBSD is a UN*X-like operating system for the i386, IA-64, PC-98, Alpha/AXP, and UltraSPARC platforms based on U.C. Berkeley's "4.4BSD-Lite" release, with some "4.4BSD-Lite2" enhancements. It is also based indirectly on William Jolitz's port of U.C. Berkeley's "Net/2" to the i386, known as "386BSD", though very little of the 386BSD code remains. FreeBSD is used by companies, Internet Service Providers, researchers, computer professionals, students and home users all over the world in their work, education and recreation. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 168961 -name FreeBSD 8.0 Linux 64bit Install CD -url http://www.freebsd.org/ -read:bytes 479866880 -claim:type shared -drive 95380e4c-4f69-432d-be2b-1965a282bdb9 -write:bytes 692064256 -read:requests 117155 -os other - -type cdrom -size 218103808 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description The Fedora 13 x86_64 (64bit) network installation CD -favourite true -install_notes The Fedora 13 network installaton cd will install, through the network, the latest Fedora packages; since it includes the "updates" repo.\n\nThe minimal install option offers great ground to build on top of a very nice base. This configuration is recommended for most servers.\n\nBuild your own and share them wth us! -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 53249 -name Fedora 13 Linux x86 64bit netinst Install CD -url http://fedoraproject.org/ -read:bytes 1444963840 -claim:type shared -drive 14b1e97f-5bba-4cf1-aec4-7b7b573826c2 -write:bytes 218107904 -read:requests 352119 -os linux - -type cdrom -size 452984832 -use security -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description The Untangle Lite package offers a collection of free, open-source software applications to run on the Untangle Server. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server.\n -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 110593 -name Untangle 7.4 Linux 64bit Install CD -url http://www.untangle.com/ -read:bytes 4096 -claim:type shared -drive 06c39099-9f75-40f4-b2e1-6012c87f3579 -write:bytes 452988928 -read:requests 1 -os linux - -type cdrom -size 138412032 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type preinstalled -status active -description Puppy Linux is extraordinarily small, yet quite full featured. Puppy boots into a 64MB ramdisk, and that's it, the whole caboodle runs in RAM. Unlike live CD distributions that have to keep pulling stuff off the CD, Puppy in its entirety loads into RAM. This means that all applications start in the blink of an eye and respond to user input instantly. Puppy Linux has the ability to boot off a flash card or any USB memory device, CDROM, Zip disk or LS/120/240 Superdisk, floppy disks, internal hard drive. It can even use a multisession formatted CD-R/DVD-R to save everything back to the CD/DVD with no hard drive required at all! -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 33793 -name Puppy 5.1 Linux Install CD -url www.puppylinux.org -read:bytes 276828160 -claim:type shared -drive 60111502-6ff3-43e1-9485-5be775f81657 -write:bytes 138416128 -read:requests 67585 -os linux - -type cdrom -size 171966464 -use router,general,networking -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type preinstalled -status active -description Vyatta project is a Linux-based router and firewall offering a free community edition and two commercial editions with support. Vyatta has changed the networking world by developing the first commercially supported, open-source router & firewall solution. Vyatta combines the features, performance and reliability of an enterprise router & firewall with the cost savings, flexibility and security of open source. -favourite true -install_notes \nCD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 41985 -name Vyatta 6.1 Live CD -url www.yyatta.com -read:bytes 687869952 -claim:type shared -drive 8159ab9b-9703-48f6-a206-ac26efe8fdc2 -write:bytes 171970560 -read:requests 167937 -os linux - -type cdrom -size 721420288 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description ZenLive Linux is a live cd derived from Zenwalk distribution. Zenwalk Linux (formerly Minislack) is a Slackware-based Linux distribution with focus on Internet applications, multimedia and programming tools. ZenLive Linux LiveCD is a complete system with software for Internet browsing, mail, chat, multimedia and office, as well as for programming in C, Perl, Python and Ruby. The main objectives of Zenwalk Linux are to be simple and fast, provide one application per task, be a complete development and desktop environment and to be small enough to fit on a 400MB ISO image. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 176129 -name Zenlive 6.4 Linux Install CD -url http://www.zenwalk.org/ -read:bytes 721424384 -claim:type shared -drive fcc2aa68-24ce-438e-8386-1d4e66336155 -write:bytes 721424384 -read:requests 176129 -os linux - -type cdrom -claimed 00059836-5512-4ce2-bf66-4daab2d994e4:guest:2e82c87e-61a1-443c-bc81-5c3167df5c11:ide:0:0 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:3234b1fc-415f-4019-ada1-27781aea8750:ide:0:0 -size 4198498304 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description CentOS as a group is a community of open source contributors and users. Typical CentOS users are organisations and individuals that do not need strong commercial support in order to achieve successful operation. CentOS is 100% compatible rebuild of the Red Hat Enterprise Linux, in full compliance with Red Hat's redistribution requirements. CentOS is for people who need an enterprise class operating system stability without the cost of certification and support. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 1025025 -name CentOS 5.5 Linux 32bit Install DVD -url http://www.centos.org -read:bytes 16706375680 -claim:type shared -drive 6e0e2282-c29a-4d19-97e6-7ddb7cdf0dd2 -write:bytes 4198502400 -read:requests 4078705 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd,livecd -status active -description Ubuntu is a complete desktop Linux operating system, freely available with both community and professional support. The Ubuntu community is built on the ideas enshrined in the Ubuntu Manifesto: that software should be available free of charge, that software tools should be usable by people in their local language and despite any disabilities, and that people should have the freedom to customise and alter their software in whatever way they see fit."Ubuntu&quot; is an ancient African word, meaning"humanity to others&quot;. The Ubuntu distribution brings the spirit of Ubuntu to the software world. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 179201 -name Ubuntu 10.04 Linux 32bit Install CD -url http://www.ubuntu.com/ -read:bytes 1298436608 -claim:type shared -drive 0e305bb9-f512-4d4a-894c-4a733cae570f -write:bytes 734007296 -read:requests 295036 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd,livecd -status active -description Chakra is a user-friendly and powerful distribution and live CD based on Arch Linux. It features a graphical installer, automatic hardware detection and configuration, the latest KDE desktop, and a variety of tools and extras. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 204801 -name Chakra Alpha 5 Linux 64bit Install and Live CD -url http://chakra-project.org/ -read:bytes 185200640 -claim:type shared -drive c0856590-c2b1-4725-9448-bba7c74d35dc -write:bytes 838864896 -read:requests 45215 -os linux - -type cdrom -claimed 00043e69-ac57-45b1-8692-75db24064fb9:guest:4c014a4e-615e-489e-b22a-bf966bce83d7:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:0a9d4833-fc5f-4825-9626-5a3e6555d329:ide:0:0 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:71d09667-fd6b-491a-949f-6a7ab9c70907:ide:0:0 0008d252-5102-43a0-82c6-18e8e2dd2bff:guest:c8264872-67a1-4452-a736-8dc6ef9eb07d:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:6efe92c3-0126-4ddb-9140-73706c804c3b:ide:0:0 000932a7-c74f-4de3-bfc4-227435f78998:guest:158c515f-1649-44f0-895c-f0de39575a1c:ide:0:0 00079b57-1b29-4a89-a8d0-1d648fc20804:guest:7d62f26e-2062-469e-846a-b926dffb00b1:ide:0:0 -size 4697620480 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description - -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 1146881 -name Debian Linux 5.0 Install CD -url http://www.debian.org/ -read:bytes 4612921344 -claim:type shared -drive 794a068d-228c-4758-81f0-e1bc955a6cce -write:bytes 4697624576 -read:requests 985768 -os linux - -type cdrom -size 2751463424 -use dev,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type livecd -status active -description Scientific Linux is a recompiled Red Hat Enterprise Linux put together by various labs and universities around the world. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 674125 -name Scientific Linux 5.5 64bit Live CD -url https://www.scientificlinux.org/ -read:bytes 10903552 -claim:type shared -drive 7aa74ca3-4c64-4b08-9972-eddeb38a650d -write:bytes 2761216000 -read:requests 2662 -os linux - -type cdrom -size 612368384 -use networking,other -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description Nexenta OS is a free and open source operating system combining the OpenSolaris kernel with GNU application userland. Nexenta OS runs on Intel/AMD 32-/64-bit hardware and is distributed as a single installable CD. Upgrades and binary packages not included on the CD can be installed from Nexenta OS repository using Advanced Packaging Tool. In addition, source based software components can be downloaded from network repositories available at Debian/GNU Linux and Ubuntu Linux. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 149357 -name NexentaStor 3.0.3 Linux 32bit/64bit Install CD -url http://www.nexenta.org/ -read:bytes 2822144 -claim:type shared -drive 2c3369a5-22eb-4462-8137-35a62b7a93cf -write:bytes 611766272 -read:requests 689 -os other - -type cdrom -size 301989888 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Zenwalk Linux (formerly Minislack) is a Slackware-based GNU/Linux operating system with a goal of being slim and fast by using only one application per task and with focus on graphical desktop and multimedia usage. Zenwalk features the latest Linux technology along with a complete programming environment and libraries to provide an ideal platform for application programmers. Zenwalk's modular approach also provides a simple way to convert Zenwalk Linux into a finely-tuned modern server (e.g. LAMP, messaging, file sharing). -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 73342 -name Zenwalk Core 6.4 Install CD -url http://yoper-linux.org/ -read:bytes 1576960 -claim:type shared -drive 3d58f1c6-9ec4-4963-917e-9917d39e5003 -write:bytes 300408832 -read:requests 385 -os linux - -type cdrom -size 67108864 -use general,security -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type preinstalled -status active -description IPFire is a linux-distribution that focusses on easy setup, good handling and a high niveau of security. It is operable via an intuitive webinterface, which offers a lot of playground for beginners and even experienced administrators. IPFire is maintained by experienced developers, who are really concerned about security and regulary updates to keep it secure. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 16385 -name IPFire 2.7 Core 40 Linux 32bit Install CD -url http://www.ipfire.org/ -read:bytes 4096 -claim:type shared -drive 231aa9af-f2ef-407c-9374-76a1215b94d3 -write:bytes 67112960 -read:requests 1 -os linux - -type cdrom -size 734003200 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Legacy OS (formerly TEENpup Linux) is a distribution based on Puppy Linux. Although the original concept was to create a flavour of Puppy Linux with more applications and a more appealing desktop aimed at teenage users, Legacy OS has now grown to become a general purpose distribution. It comes with a large number of applications, browser plugins and media codecs as standard software. Despite these enhancements Legacy OS is still perfectly suitable for installation on older and low-resource computers, as well as modern hardware. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 179201 -name Legacy OS Linux 32bit Install CD -url http://pupweb.org/wikka/TeenPup -read:bytes 4096 -claim:type shared -drive 39f24226-dc6c-40e2-abc8-e8f2da976671 -write:bytes 734007296 -read:requests 1 -os linux - -type cdrom -size 209715200 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description Yohsuke Ooi has announced the release of Momonga Linux 7, a Japanese community distribution loosely modelled on Fedora. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 51201 -name Momonga 7 Linux 64bit Net Install CD -url http://www.momonga-linux.org/ -read:bytes 4096 -claim:type shared -drive f424888b-e66e-43f4-99c1-2991a5b82894 -write:bytes 209719296 -read:requests 1 -os linux - -type cdrom -size 713031680 -use general,security,systemrecovery -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type livecd -status active -description CAINE (Computer Aided INvestigative Environment) is an Ubuntu-based GNU/Linux live distribution created as a project of Digital Forensics for Interdepartmental Centre for Research on Security (CRIS), supported by the University of Modena and Reggio Emilia in Italy. The CAINE forensic framework contains a collection of tools wrapped up into a user-friendly environment. It introduces novel features - it aims to fill the interoperability gap across different forensic tools, it provides a homogeneous GUI that guides digital investigators during the acquisition and analysis of electronic evidence, and it offers a semi-automatic process for the documentation and report compilation. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 174081 -name Caine 2.0 Linux 32bit Live CD -url http://www.caine-live.net/ -read:bytes 4096 -claim:type shared -drive 9768a0d1-e90c-44eb-8da7-06bca057cb93 -write:bytes 713035776 -read:requests 1 -os linux - -type cdrom -size 708837376 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Kongoni GNU/Linux is a Slackware-based, desktop-oriented GNU/Linux distribution and live CD. Its main features include a graphical installer, a Kongoni Integrated Setup System (KISS), and an easy-to-use Ports Installation GUI (PIG). The distribution's package management borrows its main concepts from BSD ports, with an intuitive graphical package installer that compiles and installs programs from source code on the user's system. Kongoni, which means gnu (also known as wildebeest) in Shona, includes only software that complies with Free Software Foundation's definition of software freedom. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 173057 -name Kongoni 1.12.3 Linux 32bit Live CD -url http://www.kongoni.org/ -read:bytes 4096 -claim:type shared -drive 6ac51b9d-a1db-44fc-b325-30bdefd0dd0a -write:bytes 708841472 -read:requests 1 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type livecd -status active -description Debris Linux is a minimalist, desktop-oriented distribution and live CD based on Ubuntu. It includes the GNOME desktop and a small set of popular desktop applications, such as GNOME Office, Firefox web browser, Pidgin instant messenger, and ufw firewall manager. Debris Linux ships with a custom kernel, a custom system installer called DebI, and a script that makes it easy to save and restore any customisations made while in live mode. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Debris 2.0 Linux Live CD -url http://debrislinux.org/ -read:bytes 0 -claim:type shared -drive 258e1026-36bf-4368-ba7c-52836de4f757 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 1887436800 -use systemrecovery,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type livecd -status active -description Toorox is a Linux Live-DVD based on Gentoo that starts as a bootable media using KNOPPIX technology. While the system is booting, all necessary drivers will be included automatically (lshwd). Toorox is only using the memory and an existing swap partition at runtime, so your hard disks won't be touched by default. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server.\n -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Toorox 05.2010 Linux 64bit Live CD -url http://toorox.de/ -read:bytes 0 -claim:type shared -drive 8fa3bc29-47e8-496a-89c6-02872a0d2642 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 2516582400 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description FreeBSD is a UN*X-like operating system for the i386, IA-64, PC-98, Alpha/AXP, and UltraSPARC platforms based on U.C. Berkeley's"4.4BSD-Lite&quot; release, with some"4.4BSD-Lite2&quot; enhancements. It is also based indirectly on William Jolitz's port of U.C. Berkeley's"Net/2&quot; to the i386, known as"386BSD&quot;, though very little of the 386BSD code remains. FreeBSD is used by companies, Internet Service Providers, researchers, computer professionals, students and home users all over the world in their work, education and recreation. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name FreeBSD 7.3 Linux 64bit Install CD -url http://www.freebsd.org/ -read:bytes 13836288 -claim:type shared -drive 92444414-dc65-451d-9018-2b1ab8db4ceb -write:bytes 0 -read:requests 3378 -os other - -type cdrom -size 1073741824 -use systemrecovery,security -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd,livecd -status active -description KANOTIX is a Linux distribution based on the latest stable release of Debian GNU/Linux. It is built on top of a latest kernel which is carefully patched with fixes and drivers for most modern hardware. Although it can be used as a live CD, it also includes a graphical installer for hard disk installation. The user-friendly nature of the distribution is further enhanced by a custom-built control centre and specialist scripts. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Kanotix 4-2.6 Linux with KDE 64bit Install and Live CD -url http://www.kanotix.com/ -read:bytes 232169472 -claim:type shared -drive c7c33c07-5e28-42c8-9800-eb40e2aef287 -write:bytes 0 -read:requests 56682 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description TinyMe is a Unity Linux-based mini-distribution. It exists to ease installation of Unity Linux on older computers, to provide a minimal installation for developers, and to deliver a fast Linux installation for where only the bare essentials are needed. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name TinyMe 2010 Linux Install CD -url http://tinymelinux.com/ -read:bytes 0 -claim:type shared -drive 87b3f98c-c95c-454d-a002-bef63f5bbc1a -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description moonOS is a complete, Ubuntu-based distribution featuring the LXDE and Enlightenment 17 desktop managers and imaginative, original artwork. A project created and designed by Cambodian artist Chanrithy Thim, moonOS is intended as an operating system for any desktop, laptop or virtual machine. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name MoonOS 3 Linux 32bit Install CD -url http://www.moonos.org/ -read:bytes 0 -claim:type shared -drive d2651d5b-3760-41be-a8b0-6fe5ca208825 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description - -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Yoper 2010 Linux with KDE3 Install CD -url http://yoper-linux.org/ -read:bytes 0 -claim:type shared -drive 50e0ca32-c04a-47e3-be37-1cd6f0ad9ff8 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Easy Peasy is an Ubuntu based operating system for netbooks. It's optimized for netbooks and favors the best software available by delivering Firefox with Flash and Java, Skype, Google Picasa, Songbird etc. out of the box. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name EasyPeasy 1.6 Linux Install CD -url http://www.geteasypeasy.com/ -read:bytes 195153920 -claim:type shared -drive daac6531-8f59-4c96-baa0-6545350d5a5e -write:bytes 0 -read:requests 47645 -os linux - -type cdrom -size 1572864000 -use email,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description Calculate Linux is a Gentoo-based family of three distinguished distributions. Calculate Directory Server (CDS) is a solution that supports Windows and Linux clients via LDAP + SAMBA, providing proxy, mail and Jabbers servers with streamlined user management. Calculate Linux Desktop (CLD) is a workstation and client distribution with KDE, GNOME or Xfce desktop that includes a wizard to configure a connection to Calculate Directory Server. Calculate Linux Scratch (CLS) is live CD with a build framework for creating a custom distribution. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Calculate 10.4 Linux 64bit Install CD -url http://www.calculate-linux.org/ -read:bytes 16932864 -claim:type shared -drive 20f5b0dd-5c63-40aa-97b8-5b34e5107a25 -write:bytes 0 -read:requests 4134 -os linux - -type cdrom -size 734003200 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description KahelOS is a Linux distribution based on Arch Linux. Its desktop edition comes with pre-configured GNOME as the default desktop environment, GNOME Office productivity suite, Epiphany web browser, GIMP image manipulation program, and other popular GTK+ and GNOME applications. Like Arch Linux, KahelOS maintains a rolling-release model of updating software packages using its parent's repositories. A server edition is also available. Both the desktop and server editions come in the form of installation CDs with text-based installers, but no live media. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name KahelOS 05-01-2010 Linux 64bit Install CD -url http://www.kahelos.org/ -read:bytes 0 -claim:type shared -drive 1ddaedbf-ceb8-43b5-a587-e9e635d97f50 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 524288000 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd,livecd -status active -description PCLinuxOS is a user-friendly, Mandriva-based Linux distribution with out-of-the-box support for many popular graphics and sound cards, as well as other peripheral devices. The bootable live CD provides an easy-to-use graphical installer and the distribution sports a wide range of popular applications for the typical desktop user, including browser plugins and full multimedia playback. The intuitive system configuration tools include Synaptic for package management, Addlocale to add support to many languages, Getopenoffice to install the latest OpenOffice.org, and Mylivecd to create a customised live CD. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name PCLinuxOS 2010.1 Linux with KDE Install and Live CD -url http://www.pc-os.org/ -read:bytes 0 -claim:type shared -drive 3e0f427e-10eb-4277-bc3b-48f054908a09 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 524288000 -use multimedia,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type livecd -status active -description Peppermint was designed for enhanced mobility, efficiency and ease of use. While other operating systems are taking 10 minutes to load, you are already connected, communicating and getting things done. And, unlike other operating systems, Peppermint is ready to use out of the box. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Peppermint 1.0 Linux Live CD -url http://peppermintos.com/ -read:bytes 0 -claim:type shared -drive 92ffa2f6-f663-49d9-98ec-dc0b474369c4 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 419430400 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type livecd -status active -description PureOS and PureOSlight are GNU/Linux live CDs based on Debian's testing repository. These are desktop distributions that can be used as live media (CD or USB) or as full-featured operating systems installed on a hard disk. PureOS is a 700 MB live CD with KDE, Iceweasel, Icedove, OpenOffice.org, Songbird, VLC and K3B. PureOSlight is a small 300 MB live CD with Xfce, Iceweasel, Icedove, AbiWord, Gnumeric and Exaile. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name PureOS 2.0 Linux Live CD -url http://www.pureos.org/ -read:bytes 100663296 -claim:type shared -drive ed6421b5-41c2-4ba3-a3c9-7c330d36e5b3 -write:bytes 0 -read:requests 24576 -os linux - -type cdrom -size 104857600 -use dev,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description ReactOS® is a free, modern operating system based on the design of Windows® XP/2003. Written completely from scratch, it aims to follow the Windows-NT® architecture designed by Microsoft from the hardware level right through to the application level. This is not a Linux based system, and shares none of the unix architecture. The main goal of the ReactOS project is to provide an operating system which is binary compatible with Windows. This will allow your Windows applications and drivers to run as they would on your Windows system. Additionally, the look and feel of the Windows operating system is used, such that people accustomed to the familiar user interface of Windows® would find using ReactOS straightforward. The ultimate goal of ReactOS is to allow you to remove Windows® and install ReactOS without the end user noticing the change. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name ReactOS 0.3.11 Alpha Install CD -url http://www.reactos.org/ -read:bytes 0 -claim:type shared -drive 327fd7dd-a2ca-4437-b87e-7610fccc3202 -write:bytes 0 -read:requests 0 -os other - -type cdrom -size 1887436800 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Ubuntu Studio is a variant of Ubuntu aimed at the GNU/Linux audio, video and graphic enthusiast as well as professional. The distribution provides a collection of open-source applications available for multimedia creation. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Ubuntu Studio 10.04 Linux 32bit Install CD -url http://www.ubuntu.com/ -read:bytes 499675136 -claim:type shared -drive c6a368d1-cae6-43d9-8af6-b42142aed4b9 -write:bytes 0 -read:requests 121991 -os linux - -type cdrom -size 1073741824 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -bits 32 -drive_type livecd -status active -description Vector Linux is a small, fast, Intel based Linux operating system for PC style computers. The creators of Vector Linux had a single credo: keep it simple, keep it small and let the end user decide what their operating system is going to be. What has evolved from this concept is perhaps the best little Linux operating system available anywhere. For the casual computer user you have a lightening fast desktop with graphical programs to handle your daily activities from web surfing, sending and receiving email, chatting on ICQ or IRC to running an ftp server. The power user will be pleased because all the tools are there to compile their own programs, use the system as a server or perhaps the gateway for their home or office computer network. Administrators will be equally as pleased because the small size and memory requirements of the operating system can be deployed on older machines maybe long forgotten. -favourite true -free true -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Vector 6.0 Linux with KDE Live CD -url http://www.vectorlinux.com/ -read:bytes 0 -claim:type shared -drive 0aa0b75d-ce40-4877-9882-8a81443911fe -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 713031680 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Greenie Linux is an Ubuntu-based distribution customised for Slovak and Czech users. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Greenie 7 Linux 32bit Install CD -url http://www.greenie.sk/ -read:bytes 0 -claim:type shared -drive bdddc973-e84f-4cbc-a2c9-a9fce73bc462 -write:bytes 0 -read:requests 0 -os linux - -type cdrom -size 67108864 -use networking,gateway -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd,livecd -status active -description pfSense is a free, open source customized distribution of FreeBSD tailored for use as a firewall and router. In addition to being a powerful, flexible firewalling and routing platform, it includes a long list of related features and a package system allowing further expandability without adding bloat and potential security vulnerabilities to the base distribution. pfSense is a popular project with more than 1 million downloads since its inception, and proven in countless installations ranging from small home networks protecting a PC and an Xbox to large corporations, universities and other organizations protecting thousands of network devices.  -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name PfSense 1.2.3 Linux 32bit Live and Install CD -url http://www.pfsense.org -read:bytes 68657152 -claim:type shared -drive db46ea0d-26f3-4cd0-8a55-54da2af10363 -write:bytes 0 -read:requests 16762 -os linux - -type cdrom -size 46137344 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type installcd -status active -description Mandrake Linux was created in 1998 with the goal of making Linux easier to use for everyone. At that time, Linux was already well-known as a powerful and stable operating system that demanded strong technical knowledge and extensive use of the "command line"; MandrakeSoft saw this as an opportunity to integrate the best graphical desktop environments and contribute its own graphical configuration utilities and quickly became famous for setting the standard in ease-of-use and functionality. Mandriva Linux, formerly known as Mandrakelinux, is a friendly Linux Operating System which specializes in ease-of-use for both servers and the home/office. It is freely available in many languages throughout the world. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Mandriva Spring 2010 Linux 64bit Net Install CD -url http://mandriva.com/ -read:bytes 19488768 -claim:type shared -drive 857456e4-e16c-4a6f-9bfc-f5be3e58bde5 -write:bytes 0 -read:requests 4758 -os linux - -type cdrom -size 1606418432 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description UHU-Linux is the leading distribution of Linux in Hungary. It is primarily intended for Hungarian users, thus special care is taken to support the Hungarian language as much as possible. Ease of installation and sane default settings both help new users of Linux and make veterans feel comfortable. Usability as the main goal involves having all the cutting-edge yet stable releases of Open Source packages, with dpkg as the package manager. Development is completely open and everyone is invited to join. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 392193 -name Uhu Linux 2.2 32bit Install CD -url http://uhulinux.hu/ -read:bytes 354873344 -claim:type shared -drive 9d99705b-818a-49f8-8c77-0cd4a42cdea6 -write:bytes 1606422528 -read:requests 86639 -os linux - -type cdrom -size 734003200 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description Chakra, a fast, user-friendly and extremely powerful Live CD and/or distrolet based on the award winning KDE Software Compilation and on the GNU/Linux distribution for connoisseurs: Arch Linux. Currently in alpha stage, it features a graphical installer, automatic hardware configuration, and of course some more tools and extras. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. -volume 00106cda-0e17-40c8-a576-b516f0eb67bc -host 00109617-2c6b-424b-9cfa-5b572c17bafe -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 179201 -name Chakra 2.0 Linux Live CD -url http://www.chakra-project.org/ -read:bytes 4096 -claim:type shared -drive fdfa8104-05fb-4210-aba5-fe78c4e6ee8c -write:bytes 734007296 -read:requests 1 -os linux - -type cdrom -size 662700032 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 32 -drive_type installcd -status active -description UberStudent ("uber" meaning "productive" in Latin) is an Ubuntu-based distribution on a DVD designed for learning and teaching academic computing at the higher education and advanced secondary levels. UberStudent comes with software for everyday computing tasks, plus a core set of programs and features designed to teach and make easier the tasks and habits common to high-performing students of all academic disciplines. Lifelong learners, as well as any sort of knowledge worker, will equally benefit. UberStudent is supported by a free Moodle virtual learning environment. -favourite true -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0013fc75-b170-4d62-abaf-804b8fc466cc -host 001318df-35c6-439f-8e72-8d57c36ca86b -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 161793 -name UberStudent 1.0 Linux with LXDE 32bit Install CD -url http://www.uberstudent.org/ -read:bytes 4096 -claim:type shared -drive 854a9706-fb14-4868-80df-53d712f1531a -write:bytes 662704128 -read:requests 1 -os linux - -type disk -size 3221225472 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type preinstalled -status active -description This is a pre-installed ready Fedora system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. The Fedora Project is an openly-developed project designed by Red Hat, open for general participation, led by a meritocracy, following a set of project objectives. The goal of The Fedora Project is to work with the Linux community to build a complete, general purpose operating system exclusively from open source software. Development will be done in a public forum. The project will produce time-based releases of Fedora about 2-3 times a year, with a public release schedule. The Red Hat engineering team will continue to participate in building Fedora and will invite and encourage more outside participation than in past releases. By using this more open process, we hope to provide an operating system more in line with the ideals of free software and more appealing to the open source community. -favourite true -install_notes ***You must update the default root/superuser password for Fedora 13 on first login.***\n\nPre-installed Fedora 13 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Complete the personalisation of your new server\n---------------------------------------------------------------------\nUpon first start-up you should be presented with the welcome screen after the initial boot process has completed. You will now have the opportunity to personalise your system installation. \na) Click the 'forward' button to get started.\n\nb) You will now see the license information for this system. Fedora 13 has an open source GNU license. Assuming this is acceptable you should click the 'forward' button again.\n\nc) You can now create your own user account, enter your name and set the password. Please note:\n\nTHIS IS NOT THE ADMINISTRATIVE ACCOUNT. YOU SHOULD RESET THE ROOT/SUPERUSER PASSWORD AS OUTLINED IN STEP 4 BELOW AFTER COMPLETING STEP 3.\n\nd) After clicking forward again you will have the opportunity to set the time servers that will set your servers time. You can just leave the default values unless you have some specific needs. Once you are happy please click the 'forward' button.\n\ne) Finally you have the option to submit your hardware profile to the Fedora Project to help with their development. This is entirely your personal choice. Either way once you are ready click the 'finish' button.\n\n4. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: cloudsigma\nThe default root/superuser password is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\nsu root\n\nWhen prompted use the password 'cloudsigma' (don't type the quote marks). The prompt should change to show you now using the root/superuser account.\n\nc) Now type the command:\n\npasswd\n\nd) When prompted enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\ne) CoudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\nf) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n5. Expanding your drive\n--------------------------------\n\nThe system is fully installed and designed to expand to fill the initial size of the drive. After first login you should find that the system has used the full disk size as its partition.\n\n\n6. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n7. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -volume 0003ca60-6b03-4da9-a409-84d8d7afa738 -host 00031836-a624-4b22-bc7d-41ff8977087b -user 00000000-0000-0000-0000-000000000001 -autoexpanding true -write:requests 786433 -name Fedora 13 Linux 64bit Preinstalled System -url http://fedoraproject.org/ -read:bytes 40962080768 -claim:type shared -drive d18119ce-7afa-474a-9242-e0384b160220 -write:bytes 3221229568 -read:requests 10000508 -os linux - -type disk -size 4294967296 -use dbserver,webserver,email,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type preinstalled -status active -favourite true -install_notes ***You must update the default root/superuser password for Debian 5.0 on first login.***\n\nPre-installed Debian 5.0 64bit Linux on 02/08/2010\n========================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n------------------------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n-------------------------------------------------------\n\nThe default accounta are: root and cloudsigma\nThe default passwords for both accounts is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'cloudsigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -volume 0003ca60-6b03-4da9-a409-84d8d7afa738 -host 00031836-a624-4b22-bc7d-41ff8977087b -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 1048577 -name Debian 5.0 Preinstalled without X -url www.debian.org -read:bytes 35180666880 -claim:type shared -drive fd49670e-17e8-4b0e-b03e-d6a65c138445 -write:bytes 4294971392 -read:requests 8589030 -os linux - -type disk -size 21474836480 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type preinstalled -status active -description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. -favourite true -install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -volume 000431a5-46d9-4a67-9c03-3c3402a41992 -host 00043e69-ac57-45b1-8692-75db24064fb9 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 5242881 -name CentOS 5.5 Linux 64bit Preinstalled System -url http://www.centos.org/ -read:bytes 251925499904 -claim:type shared -drive 1ea7dead-9d52-4e79-9a9b-435db7cc972c -write:bytes 21474840576 -read:requests 61505249 -os linux - -type disk -size 2684354560 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type preinstalled -status active -description This is a pre-installed ready Ubuntu system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. Ubuntu Linux is a complete desktop Linux operating system, freely available with both community and professional support. The Ubuntu community is built on the ideas enshrined in the Ubuntu Manifesto: that software should be available free of charge, that software tools should be usable by people in their local language and despite any disabilities, and that people should have the freedom to customise and alter their software in whatever way they see fit. "Ubuntu" is an ancient African word, meaning "humanity to others". The Ubuntu Linux distribution brings the spirit of Ubuntu to the software world. -favourite true -install_notes ***You must update the default root/superuser password for Ubuntu 10.04 on first login.***\n\nPre-installed Ubuntu 10.04 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: cloudsigma\nThe default root/superuser password is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\nsudo su\n\nWhen prompted use the password 'cloudsigma' (don't type the quote marks). The prompt should change to show you now using the root/superuser account.\n\nc) Now type the command:\n\npasswd\n\nd) When prompted enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\ne) CoudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\nf) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed and designed to expand to fill the initial size of the drive. After first login you should find that the system has used the full disk size as its partition.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -volume 00059deb-640a-464e-9509-6a3ec6cfd549 -host 00059836-5512-4ce2-bf66-4daab2d994e4 -user 00000000-0000-0000-0000-000000000001 -autoexpanding true -write:requests 655361 -name Ubuntu Linux 10.04 Desktop 64bit Preinstalled System -url http://www.ubuntu.com/ -read:bytes 24617140224 -claim:type shared -drive 99a75966-209f-41d5-817c-7a3916354540 -write:bytes 2684358656 -read:requests 6010044 -os linux - -type disk -size 8589934592 -use dbserver,webserver,email,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type preinstalled -status active -favourite true -install_notes ***You must update the default root/superuser password for Ubuntu 10.04 on first login.***\n\nPre-installed Ubuntu 10.04 64bit Linux on 01/09/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: cloudsigma\nThe default root/superuser password is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\nsudo su\n\nWhen prompted use the password 'cloudsigma' (don't type the quote marks). The prompt should change to show you now using the root/superuser account.\n\nc) Now type the command:\n\npasswd\n\nd) When prompted enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\ne) CoudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\nf) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed and designed to expand to fill the initial size of the drive. After first login you should find that the system has used the full disk size as its partition.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 -host 0008d252-5102-43a0-82c6-18e8e2dd2bff -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 2097153 -name Ubuntu 10.04 Server Edition Linux 64bit -url http://www.ubuntu.com/server -read:bytes 71391387648 -claim:type shared -drive 0b060e09-d98b-44cc-95a4-7e3a22ba1b53 -write:bytes 8589938688 -read:requests 17429538 -os linux - -type disk -size 21474836480 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type preinstalled -status active -description This is a pre-installed ready CentOS system including AppFirst monitoring software that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. -favourite true -install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux with AppFirst Monitoring on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\ne) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nf) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ng) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs.\n\n\n6. AppFirst\n-------------------------\nThis disk image includes AppFirst monitoring software already installed. This software is able to provide in-depth server and application performance feedback. In order to take advantage of this software you need to have an AppFirst account.\n\nFull details of AppFirst's services including a 14-day free trial are available at http://www.appfirst.com . -volume 00106cda-0e17-40c8-a576-b516f0eb67bc -host 00109617-2c6b-424b-9cfa-5b572c17bafe -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 5242881 -name CentOS 5.5 Linux 64bit Preinstalled System with AppFirst Monitoring -read:bytes 838707331072 -claim:type shared -drive c157e1eb-aa9c-4dd7-80b8-6fd4a238f2a9 -write:bytes 21474840576 -read:requests 204762532 -os linux - -type disk -size 8589934592 -use dbserver,webserver,email,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free true -bits 64 -drive_type preinstalled -status active -favourite true -install_notes ***You must update the default root/superuser password for Debian 5.0 on first login.***\n\nPre-installed Debian 5.0 64bit Linux on 02/08/2010\n========================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n------------------------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n-------------------------------------------------------\n\nThe default accounta are: root and cloudsigma\nThe default passwords for both accounts is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'cloudsigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. -volume 001118bb-dbdb-4ab0-b7db-d4cceb160098 -host 00115b1d-6fe9-40b2-a013-426a6a584ff7 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 2097153 -name Debian 5.0 Preinstalled -url www.debian.org -read:bytes 71179878400 -claim:type shared -drive 9b732c4e-32a3-4369-b5f7-9a0325195baa -write:bytes 8589938688 -read:requests 17377900 -os linux - -type cdrom -claimed 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:7055acf3-8d9a-4a99-a24f-dda1aaf37944:ide:0:0 00115b1d-6fe9-40b2-a013-426a6a584ff7:guest:0a486768-08c1-419d-ad9c-1c8143df3496:ide:0:0 -size 2248146944 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -bits 64 -email drives@elastichosts.com -drive_type installcd -status active -description - -favourite false -free false -volume 0007aee7-bd5b-4551-9d8f-a958051235a9 -host 00079b57-1b29-4a89-a8d0-1d648fc20804 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Windows Web Server 2008 Trial Install CD -url http://www.microsoft.com -read:bytes 55097581056 -claim:type shared -drive 7aead6d3-c3e6-4940-85c7-f5ee61f6ef2b -write:bytes 0 -read:requests 22364695 -os windows - -type cdrom -claimed 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:6100e29c-708d-4a5b-821b-6a9faa3ba013:ide:0:1 00031836-a624-4b22-bc7d-41ff8977087b:guest:fcde7569-e034-452c-9909-7c485f5d168f:ide:0:0 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:1ac4641e-aa67-47f2-a77d-e9c5982d68b2:ide:0:0 0012c12d-72b1-4dfc-ae0f-aeab09881545:guest:300989f8-da5c-42a6-91f8-97e87b85b748:ide:0:1 00016115-af87-452b-a3bf-3affc8a7d934:guest:f679b4ba-a4de-4254-90d1-27396aac8712:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:65e59c8b-579b-4977-b60c-b3b7eb404026:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:76eaf2fe-554a-4d3f-a3ef-a1214e878793:ide:0:0 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:030cfdda-9c6c-4622-a68c-2e3588fbe828:ide:0:0 00109617-2c6b-424b-9cfa-5b572c17bafe:guest:64a5375a-31cc-414f-9e14-006b5c39b51f:ide:0:0 00059836-5512-4ce2-bf66-4daab2d994e4:guest:83da4fb5-037f-4985-a0f6-f696fa7ff727:ide:0:0 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:90f4a2d3-9b76-4444-a1b2-72bbd06fe3e2:ide:0:0 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:cbb4ecc9-654f-4410-aeb4-b9ca602faa01:ide:0:0 0008d252-5102-43a0-82c6-18e8e2dd2bff:guest:e7ea14b2-aaa0-48b4-b1ac-7c8351c2edf4:ide:0:0 001318df-35c6-439f-8e72-8d57c36ca86b:guest:67f96fa3-8d41-4f8b-8199-4111617d3150:ide:0:1 000663ee-9fb6-4461-90f6-01327a4aff07:guest:245dd0b0-18eb-4e24-b219-9549bafdea87:ide:0:0 000663ee-9fb6-4461-90f6-01327a4aff07:guest:b52e106f-f14c-4312-8597-bcfedf4b0e70:ide:0:0 -size 2663383040 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free false -bits 64 -email drives@elastichosts.com -drive_type installcd -status active -description - -favourite false -install_notes pass:123456 -volume 0007aee7-bd5b-4551-9d8f-a958051235a9 -host 00079b57-1b29-4a89-a8d0-1d648fc20804 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Windows Server 2008 Trial Install CD -url http://www.microsoft.com/windowsserver2008/en/us/default.aspx -read:bytes 78315713024 -claim:type shared -drive f89af28e-ff00-4fc9-a7ed-22e7fa5a88db -write:bytes 0 -read:requests 32289210 -os windows - -status active -name Gentoo Install Minimal amd64 20100408 -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 437561856 -write:bytes 119558144 -claim:type shared -drive 73162606-78ca-4b0a-8f7a-70aa70563d90 -free none -volume 00018aab-c080-4ed3-b52f-459933d34ec9 -host 00016115-af87-452b-a3bf-3affc8a7d934 -os linux -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 79760 -claimed 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:d74c8d2b-a169-486c-adbd-89ca50dccafa:ide:0:1 -type cdrom -write:requests 29189 -size 209715200 - -status active -name Peppermint Ice Linux 32bit Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 1986560 -description Peppermint OS is an Ubuntu-based Linux distribution that aims to be lightning fast and easy on system resources. By employing Mozilla's Prism technology Peppermint integrates seamlessly with Cloud and web-based applications. The distribution's other features include automatic updates, easy step-by-step installation, sleek and user-friendly interface, and increased mobility by integrating directly with Cloud-based applications. -write:bytes 437698560 -claim:type shared -drive f9d92afc-27ff-4139-84c7-ac6655e6f6f1 -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00018aab-c080-4ed3-b52f-459933d34ec9 -host 00016115-af87-452b-a3bf-3affc8a7d934 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 485 -free none -type cdrom -write:requests 106860 -size 436207616 - -status active -name Super Gamer Linux 32bit and 64bit Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 137039872 -description SuperGamer is a live DVD based on VectorLinux, intended to showcase gaming on Linux. The distribution is optimised for a gaming computer environment, with some tweaks to help speed up running from the live DVD. Extra games are added along with some demo editions of proprietary games. All games are native Linux games, but users wishing to run Windows games may install WINE or a related emulator, such as Cedega. -write:bytes 8446324736 -claim:type shared -drive d72701b2-01b9-4ac3-9afa-d0afdb6bcf2f -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00018aab-c080-4ed3-b52f-459933d34ec9 -host 00016115-af87-452b-a3bf-3affc8a7d934 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 33457 -free none -type cdrom -write:requests 2062091 -size 8413773824 - -status active -name ZeroShell 1.3 Linux Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 856064 -description Zeroshell is a Linux distribution for servers and embedded devices aimed at providing the main network services a LAN requires. It is available in the form of Live CD or Compact Flash image and you can configure and administer it using your web browser. -write:bytes 153247744 -claim:type shared -drive 44358ce4-0f30-4e48-86d1-e93330961a8a -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n -volume 00023324-4c49-4567-a017-c85c8a6b8313 -host 0002c6df-a1d2-4d1d-96f0-f95405a28183 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 209 -free none -type cdrom -write:requests 37414 -size 155189248 - -status active -name Astaro Security Gateway Firewall Server 8.0 Linux Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 365871104 -description Astaro offers an integrated software solution that provides superior performance in an all-in-one firewall. Its hardened operating system, stateful packet inspection, content filtering (virus & surf protection), application proxies and IPsec based VPN provides a powerful solution to today's security issues. It is designed to maximize your networks security without compromising its performance enabling telecommuters, branch offices, customers and suppliers to safely share critical business information. Our proprietary user interface, WebAdmin allows ease of use and manageability of all open source firewall components, as well as the Up2Date service via the Internet. It is easy to install with all components on one CD achieving simple implementation and integration to existing network environments. -write:bytes 369696768 -claim:type shared -drive 916b0e39-b234-407b-89ab-e8108f05726f -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00023324-4c49-4567-a017-c85c8a6b8313 -host 0002c6df-a1d2-4d1d-96f0-f95405a28183 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 89324 -claimed 000096ce-ff07-413d-912a-aa1a33963802:guest:20911753-98a6-4951-af34-89e157452c84:ide:0:0 00115b1d-6fe9-40b2-a013-426a6a584ff7:guest:75a96f35-c3fd-492a-a48b-34dcd10987d6:ide:0:0 -free none -type cdrom -write:requests 90258 -size 369098752 - -status active -name Chakra 0.2.2 Linux 64bit Install and Live CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 5451776 -description Chakra GNU/Linux is a user-friendly and powerful distribution and live CD based on Arch Linux. It features a graphical installer, automatic hardware detection and configuration, the latest KDE desktop, and a variety of tools and extras. -write:bytes 724774912 -claim:type shared -drive 0e8c8ac2-f791-4764-a964-c6d2679ae49a -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 0000acbf-fa0a-44a6-8018-2f106f96a45f -host 000096ce-ff07-413d-912a-aa1a33963802 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 1331 -free none -type cdrom -write:requests 176947 -size 721420288 - -status active -name Clonezilla Live 1.2.6 64bit -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 876544 -description Clonezilla Live is a Debian-based live CD containing Clonezilla, a partition and disk cloning software similar to Norton Ghost. It saves and restores only used blocks in hard drive. With Clonezilla, one can clone a 5 GB system to 40 clients in about 10 minutes. -write:bytes 134045696 -claim:type shared -drive cec8330f-59c7-4e20-9577-54df28d598e7 -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. -volume 0000acbf-fa0a-44a6-8018-2f106f96a45f -host 000096ce-ff07-413d-912a-aa1a33963802 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 214 -free none -type cdrom -write:requests 32726 -size 134217728 - -status active -name Absolute Linux 13.1.2 Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 93573632 -description Absolute Linux is a light-weight modification of Slackware Linux. It includes several utilities that make configuration and maintenance easier and it has many common desktop and Internet applications installed and configured with tight integration of menus, applications and MIME types. Absolute Linux uses IceWM and ROX for its window and file managers. -write:bytes 728211456 -claim:type shared -drive b745638c-87ff-4836-8623-e48e67286494 -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 000431a5-46d9-4a67-9c03-3c3402a41992 -host 00043e69-ac57-45b1-8692-75db24064fb9 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 39232 -free none -type cdrom -write:requests 177786 -size 725614592 - -status active -name Sabayon_Linux_5.4_amd64_K.iso -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 12877824 -write:bytes 2160496640 -claim:type shared -drive 75119285-7c20-43f4-9d3b-e6af3f1823e3 -free none -volume 000431a5-46d9-4a67-9c03-3c3402a41992 -host 00043e69-ac57-45b1-8692-75db24064fb9 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 3144 -type cdrom -write:requests 527465 -size 2151677952 - -status active -name FreeBSD 8.1 Linux 64bit Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 60035072 -description About FreeBSD FreeBSD is a UN*X-like operating system for the i386, IA-64, PC-98, Alpha/AXP, and UltraSPARC platforms based on U.C. Berkeley's "4.4BSD-Lite" release, with some "4.4BSD-Lite2" enhancements. It is also based indirectly on William Jolitz's port of U.C. Berkeley's "Net/2" to the i386, known as "386BSD", though very little of the 386BSD code remains. FreeBSD is used by companies, Internet Service Providers, researchers, computer professionals, students and home users all over the world in their work, education and recreation. -write:bytes 2315309056 -claim:type shared -drive fb940d5b-b9a0-4f9c-8cb7-94c3378d1676 -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00059deb-640a-464e-9509-6a3ec6cfd549 -host 00059836-5512-4ce2-bf66-4daab2d994e4 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 14657 -free none -type cdrom -write:requests 565261 -size 2306867200 - -status active -name BackTrack 4 Release 1 Linux Live CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 4008857600 -description A SLAX-based live CD with a comprehensive collection of security and forensics tools BackTrack 4 R1, a Linux-based penetration testing arsenal for security professionals. -write:bytes 2023919616 -claim:type shared -drive ef152c9c-1460-44f5-b192-8e0524909709 -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00059deb-640a-464e-9509-6a3ec6cfd549 -host 00059836-5512-4ce2-bf66-4daab2d994e4 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 978725 -free none -type cdrom -write:requests 494121 -size 2017460224 - -status active -name Vector 6.0 Linux 32bit Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 3035136 -description VECTORLINUX is a small, fast, Intel Linux operating system based on one of the original Linux distributions, Slackware. The enormously popular Slackware is the true "Unix" of Linux distributions and is used by major corporations, universities and home users alike. It's popularity stems from the fact that it is a robust, versatile and almost unbreakable system. Slackware has been traditionally known to be about as user friendly as a coiled rattlesnake and that's where Vector Linux comes into play. We have produced a bloat free, easy to install, configure and maintain Slackware based system that is second to none. -write:bytes 729059328 -claim:type shared -drive c2a757b9-dfd0-432c-bb29-b380b4dd6fb6 -free none -volume 00059deb-640a-464e-9509-6a3ec6cfd549 -host 00059836-5512-4ce2-bf66-4daab2d994e4 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 741 -type cdrom -write:requests 177993 -size 729808896 - -status active -name PCBSD 8.1 Linux 64bit Install CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 15228928 -description PC-BSD has as its goals to be an easy-to-install-and-use desktop operating system, based on FreeBSD. To accomplish this, it currently has a graphical installation, which will enable even UNIX novices to easily install and get it running. It will also come with KDE pre-built, so that the desktop can be used immediately. Currently in development is a graphical software installation program, which will make installing pre-built software as easy as other popular operating systems. -write:bytes 3794726912 -claim:type shared -drive 802fbcab-2723-469c-b775-6fdeb21287da -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 3718 -free none -type cdrom -write:requests 926447 -size 3783262208 - -status active -name nst-2.13.0.x86_64.iso -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 7503872 -write:bytes 1436717056 -claim:type shared -drive 9d04c648-712d-4076-bd99-70088d85fe01 -free none -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 1832 -type cdrom -write:requests 350761 -size 1430257664 - -status active -name Peppermint-Ice-10012010.iso -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 2613248 -write:bytes 452710400 -claim:type shared -drive 2e79eeee-b4ad-4dcf-a072-86dcede6af1b -free none -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 638 -type cdrom -write:requests 110525 -size 452984832 - -status active -name Sabayon_Linux_5.4_amd64_K.iso -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 14082048 -write:bytes 2161713152 -claim:type shared -drive 07e2a6df-8389-4130-a003-edacc19a9ee3 -free none -volume 00065289-b9c8-4548-8d83-e1891f831f51 -host 000663ee-9fb6-4461-90f6-01327a4aff07 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 3438 -type cdrom -write:requests 527762 -size 2151677952 - -type cdrom -claimed 00031836-a624-4b22-bc7d-41ff8977087b:guest:ffe02269-b653-47ad-ab21-a02805b24904:ide:0:0 000096ce-ff07-413d-912a-aa1a33963802:guest:1f378a18-1b59-40e7-8e9a-7f81d7eda6b8:ide:0:0 00079b57-1b29-4a89-a8d0-1d648fc20804:guest:8c13b69d-6d11-4151-975b-a2f084c7ada7:ide:0:0 00166b98-6431-40ad-94b0-244881ff87d5:guest:1705b116-aac2-449a-b0de-3dd4ab7e765f:ide:0:0 000932a7-c74f-4de3-bfc4-227435f78998:guest:30d887ee-ed96-4c32-a1a8-5ab49abd2a7e:ide:0:1 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:bcea8695-baeb-476e-8089-475ce8948646:ide:0:1 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:df1368af-05a3-4ad5-8017-54be3ea70232:ide:0:0 00109617-2c6b-424b-9cfa-5b572c17bafe:guest:3569d646-7ae5-410f-b66e-64bba1381cba:ide:0:0 -size 2663383040 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -bits 64 -drive_type installcd -status active -description - -favourite false -free false -volume 0009c669-9ea6-4825-b788-b40902bb1902 -host 000932a7-c74f-4de3-bfc4-227435f78998 -encryption:cipher aes-xts-plain -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 0 -name Windows Server 2008 Trial Install CD -url http://www.microsoft.com/windowsserver2008/en/us/default.aspx -read:bytes 5261708288 -claim:type shared -drive 7e23b099-dd35-446b-8d90-2953643b664f -write:bytes 0 -read:requests 1883649 -os windows - -status active -name Unity Linux 64bit Install and Live CD -readers ffffffff-ffff-ffff-ffff-ffffffffffff -favourite none -read:bytes 147034112 -description The community-oriented Unity Linux is a minimalist distribution and live CD based on Mandriva Linux. The project's main goal is to create a base operating system from which more complete, user-oriented distribution can easily be built - either by other distribution projects or by the users themselves. Unity Linux uses Openbox as the default window manager. Its package management is handled via Smart and RPM 5 which can download and install additional software packages from the project's online repository. -write:bytes 290488320 -claim:type shared -drive d235dada-407c-4105-b4ef-636eb7604404 -install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. -volume 00106cda-0e17-40c8-a576-b516f0eb67bc -host 00109617-2c6b-424b-9cfa-5b572c17bafe -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -read:requests 35897 -free none -type cdrom -write:requests 70920 -size 289406976 - -type disk -licenses msft_p73_04837 msft_tfa_00009 -size 21474836480 -use dbserver,general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free false -bits 64 -drive_type preinstalled -status active -description Please refer to the install notes for a full guide to initial configuration. -favourite false -install_notes ***You must update the default Administrator password for Windows Server Standard 2008 and the Super Administrator password (sa) for SQL Server Standard 2008***\n\nPre-installed Windows Server 2008 Standard R2 64bit English on 15/07/2010\n=========================================================================\n\n1. Minimum Hardware Requirements\n--------------------------------\n\nThe recommended minimum hardware requirements for the use of SQL Server Standard 2008 R2 with Windows Server Standard 2008 R2 as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/library/ms143506.aspx\n\n\n2. Update your administrator password\n-------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n3. Expanding your drive\n-----------------------\n\nThe system is fully installed, but you will need to extend the\ndisk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n4. Enabling Remote Access\n-------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection according to your Security Configuration\n\n\n5. Pinging Service\n------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules"\n\n\nSQL Server 2008 R2 on 15/07/2010\n================================\n\n1. Change the Super Administrator Password (sa). \n--------------------------------------------------------------------\n\nThe default password has been set to "CloudSigma1"\n\na) Open "Microsoft SQL Server Management Studio"\n\nb) Connect to the Server Using "Windows Indentificaiton"\n\nc) From the Object Explorer select "Security" then "Longins"\n\nd) Right-click on sa and select "Properties"\n\ne) Enter the new password into "Password" and "Confirm Password" and press "OK"\n\n\n2. The following features were installed:\n-----------------------------------------------------\n\na) Main features\n\n-Database Engine Services\n-SQL Server Replication\n-Full-Text Search\n-Analysis Services\n-Reporting Services\n\nb) Shared Features\n\n-Business Intelligengce Development Studio\n-Client Tools Connectivity\n-Integration Services\n-Clinet Tools Backwards Compatibility\n-Clinet Tools SDK\n-SQL Server Books Online\n-Mangement Tools - Basic\n-Management Tools - Complete\n-SQL Client Connectivity SDK\n-Microsoft Sync Framework\n\n3 The following services were configured:\n--------------------------------------------------------\n\n\nService: SQL Server Agent\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Manual\n\nService: SQL Server Database Engine\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Automatic\n\nService: SQL Server Analysis Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Reporting Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Integration Services 10.1\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n \nService: SQL Full-text filter Daemon Lanuch\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nService: SQL Server Browser\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nFor detailed server installation configuration refer to the following installation log files on the system:\nC:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20100716_162426\Summary_WIN-K0F21FV1C1V_20100716_162426.txt\n -volume 00023324-4c49-4567-a017-c85c8a6b8313 -host 0002c6df-a1d2-4d1d-96f0-f95405a28183 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 5242881 -name SQL Server Standard 2008 R2 - Windows Server Standard 2008 R2 - 64bit English pub -url http://www.microsoft.com/sqlserver/2008/en/us/ -read:bytes 49172439040 -claim:type shared -drive 7b013f8c-dd4c-4701-b1ca-936506dc37ca -write:bytes 21474840576 -read:requests 12004990 -os windows - -type disk -licenses msft_lwa_00135 -size 13958643712 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free false -bits 64 -drive_type preinstalled -status active -description Please refer to the install notes for a full guide to initial configuration. -favourite false -install_notes ***You must update the default Administrator password for Windows Web Server 2008***\n\nPre-installed Windows Server 2008 Web R2 64bit English on 24/07/2010\n============================================================\n\n1. Connecting to your server via VNC\n--------------------------------------------------\n\na) Having installed a compatible VNC client, open a VNC connection to your server.\n\nb) Enter your IP address and VNC password as displayed on your Server Summary Window.\n\nc) Start to configure your server.\n\n\n2. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/windowsserver/cc196364.aspx\n\nWe recommend specifying a higher level of RAM for a better user experience.\n\n\n3. Update your administrator password\n----------------------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" from the "Start" menu and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n4. Configuring your Networking\n------------------------------------------\n\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs.\n\n\n5. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n6. Enabling Remote Access\n--------------------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection type according to your Security Configuration\n\n\n7. Pinging Service\n-------------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules" -volume 00120946-d7a4-486e-867e-8348bebe0b95 -host 0012c12d-72b1-4dfc-ae0f-aeab09881545 -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 3407873 -name Windows Server Web 2008 R2 64bit English -url http://www.microsoft.com/windowsserver2008/en/us/default.aspx -read:bytes 145252270080 -claim:type shared -drive 71697799-c611-41b9-93be-f79152aefbe5 -write:bytes 13958647808 -read:requests 35461980 -os windows - -type disk -licenses msft_p73_04837 -size 13958643712 -use general -readers ffffffff-ffff-ffff-ffff-ffffffffffff -free false -bits 64 -drive_type preinstalled -status active -description Please refer to the install notes for a full guide to initial configuration. -favourite false -install_notes ***You must update the default Administrator password for Windows Server Standard 2008***\n\nPre-installed Windows Server 2008 Standard R2 64bit English on 24/07/2010\n============================================================\n\n1. Connecting to your server via VNC\n--------------------------------------------------\n\na) Having installed a compatible VNC client, open a VNC connection to your server.\n\nb) Enter your IP address and VNC password as displayed on your Server Summary Window.\n\nc) Start to configure your server.\n\n\n2. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/windowsserver/cc196364.aspx\n\nWe recommend specifying a higher level of RAM for a better user experience.\n\n\n3. Update your administrator password\n----------------------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" from the "Start" menu and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n4. Configuring your Networking\n------------------------------------------\n\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs.\n\n\n5. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n6. Enabling Remote Access\n--------------------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection type according to your Security Configuration\n\n\n7. Pinging Service\n-------------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules" -volume 0013fc75-b170-4d62-abaf-804b8fc466cc -host 001318df-35c6-439f-8e72-8d57c36ca86b -user 00000000-0000-0000-0000-000000000001 -autoexpanding false -write:requests 3407873 -name Windows Server Standard 2008 R2 64bit English -url http://www.microsoft.com/windowsserver2008/en/us/default.aspx -read:bytes 257073537024 -claim:type shared -drive 0611be3f-0607-4b3c-8bad-a0af392d928a -write:bytes 13958647808 -read:requests 62762094 -os windows diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/resources_ip_create.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/resources_ip_create.txt deleted file mode 100644 index 89db213e3d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/resources_ip_create.txt +++ /dev/null @@ -1,13 +0,0 @@ -resource 1.2.3.4 -netmask 255.255.255.0 -nameserver 91.203.56.1 -user f2e19d5c-eaa1-44e5-94aa-dc194594bd7b -type ip -gateway 91.203.56.1 - -resource 1.2.3.5 -netmask 255.255.255.0 -nameserver 91.203.56.1 -user f2e19d5c-eaa1-44e5-94aa-dc194594bd7b -type ip -gateway 91.203.56.1 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/resources_ip_list.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/resources_ip_list.txt deleted file mode 100644 index 73435077e0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/resources_ip_list.txt +++ /dev/null @@ -1,3 +0,0 @@ -ip 1.2.3.4 -ip 1.2.3.5 -ip 1.2.3.6 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_create.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_create.txt deleted file mode 100644 index 95b8e14369..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_create.txt +++ /dev/null @@ -1,26 +0,0 @@ -ide:0:0:write:requests 466 -rx 760681 -vnc:password testpass -ide:0:0 f0202f1c-0b4f-4cfc-8ae3-e30951d09ef0 -ide:0:0:read:requests 7467 -ide:0:0:read:bytes 165395968 -vnc:ip 178.22.66.28 -tx:packets 32 -tx 2568 -boot ide:0:0 -smp 1 -started 1286568422 -nic:0:model virtio -status active -mem 640 -rx:packets 12662 -user 93b34fd9-7986-4b25-8bfd-98a50383605d -ide:0:0:media disk -name cloudsigma node -persistent true -nic:0:block tcp/22 tcp/23 tcp/25 tcp/43594 tcp/43595 -server 62fe7cde-4fb9-4c63-bd8c-e757930066a0 -nic:0:dhcp 1.2.3.4 -nic:1:dhcp 1.2.3.5 -ide:0:0:write:bytes 7358464 -cpu 1100 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_info.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_info.txt deleted file mode 100644 index 95b8e14369..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_info.txt +++ /dev/null @@ -1,26 +0,0 @@ -ide:0:0:write:requests 466 -rx 760681 -vnc:password testpass -ide:0:0 f0202f1c-0b4f-4cfc-8ae3-e30951d09ef0 -ide:0:0:read:requests 7467 -ide:0:0:read:bytes 165395968 -vnc:ip 178.22.66.28 -tx:packets 32 -tx 2568 -boot ide:0:0 -smp 1 -started 1286568422 -nic:0:model virtio -status active -mem 640 -rx:packets 12662 -user 93b34fd9-7986-4b25-8bfd-98a50383605d -ide:0:0:media disk -name cloudsigma node -persistent true -nic:0:block tcp/22 tcp/23 tcp/25 tcp/43594 tcp/43595 -server 62fe7cde-4fb9-4c63-bd8c-e757930066a0 -nic:0:dhcp 1.2.3.4 -nic:1:dhcp 1.2.3.5 -ide:0:0:write:bytes 7358464 -cpu 1100 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_set.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_set.txt deleted file mode 100644 index 095a88c3e9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma/servers_set.txt +++ /dev/null @@ -1,26 +0,0 @@ -ide:0:0:write:requests 466 -rx 760681 -vnc:password testpass -ide:0:0 f0202f1c-0b4f-4cfc-8ae3-e30951d09ef0 -ide:0:0:read:requests 7467 -ide:0:0:read:bytes 165395968 -vnc:ip 178.22.66.28 -tx:packets 32 -tx 2568 -boot ide:0:0 -smp 2 -started 1286568422 -nic:0:model virtio -status active -mem 640 -rx:packets 12662 -user 93b34fd9-7986-4b25-8bfd-98a50383605d -ide:0:0:media disk -name cloudsigma node -persistent true -nic:0:block tcp/22 tcp/23 tcp/25 tcp/43594 tcp/43595 -server 62fe7cde-4fb9-4c63-bd8c-e757930066a0 -nic:0:dhcp 1.2.3.4 -nic:1:dhcp 1.2.3.5 -ide:0:0:write:bytes 7358464 -cpu 1100 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json deleted file mode 100644 index 8f86b0609a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json +++ /dev/null @@ -1 +0,0 @@ -{"balance": "10.00", "currency": "USD"} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json deleted file mode 100644 index 62ee576291..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "drives": { - "dssd": { - "max_size": 8858013190752, - "min_size": 536870912 - } - }, - "servers": { - "cpu": { - "max": 80000, - "min": 250 - }, - "cpu_per_smp": { - "max": 2200, - "min": 1000 - }, - "mem": { - "max": 137438953472, - "min": 268435456 - }, - "smp": { - "max": 40, - "min": 1 - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/create_subscription.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/create_subscription.json deleted file mode 100644 index 7699d40e9c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/create_subscription.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "objects": [ - { - "amount": "1", - "auto_renew": false, - "descendants": [], - "discount_amount": "0", - "discount_percent": "0", - "end_time": "2014-03-01T12:00:00+00:00", - "id": "228816", - "period": "1 month", - "price": "10.26666666666666666666666667", - "remaining": "1", - "resource": "vlan", - "resource_uri": "/api/2.0/subscriptions/228816/", - "start_time": "2014-01-31T17:06:19.388295+00:00", - "status": "active", - "subscribed_object": "2494079f-8376-40bf-9b37-34d633b8a7b7", - "uuid": "0dd25c5c-6c01-498f-b009-e07d76552a1a" - } - ], - "price": "10.26666666666666666666666667" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json deleted file mode 100644 index 8d5af60599..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "balance": { - "balance": "378.74599035374868510600", - "currency": "USD" - }, - "usage": { - "cpu": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "dssd": { - "burst": 13958643712, - "subscribed": 0, - "using": 13958643712 - }, - "ip": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "mem": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_7jq_00341": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_7nq_00302": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_lwa_00135": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_p71_01031": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_p73_04837": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_p73_04837_core": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_tfa_00009": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "msft_tfa_00523": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "sms": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "ssd": { - "burst": 0, - "subscribed": 0, - "using": 0 - }, - "tx": { - "burst": 0, - "subscribed": 5368709120, - "using": 0 - }, - "vlan": { - "burst": 0, - "subscribed": 0, - "using": 0 - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_avail_groups.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_avail_groups.json deleted file mode 100644 index 62706d78b2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_avail_groups.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - [ - "ad2b0b9c-8b66-45bc-a0f8-3a8514b78406", - "e464a01b-ad2a-4bed-a4dd-30d1687560fd", - "2246e488-a1b9-4da2-af30-0b6c73a1529c", - "51a6b22f-2884-48d9-87f8-c85cb6f43c99", - "a67c932d-6766-470b-b1c5-17856e4a5b4e", - "3af58efd-8442-466f-80bf-48c5a2ee84b6", - "ab35089c-0a89-435f-aedd-eaa05fae0ef1", - "9972280b-3d74-4b0d-85de-caa0ef0117a6", - "c47bca85-0199-438c-9ae4-d308357cf22d", - "3e166706-188c-4f38-b8d5-7fc10a5019a1", - "ba47e1e9-1848-48bd-8786-9cc45744214c" - ] -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json deleted file mode 100644 index 5e2b6e2b8a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "objects": [ - { - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "cloned drive", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": null - }, - "size": 2097152000, - "snapshots": [], - "status": "creating", - "storage_type": null, - "tags": [], - "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json deleted file mode 100644 index 02c4b35a46..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "objects": [ - { - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "test drive 5", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": null - }, - "size": 2097152000, - "snapshots": [], - "status": "creating", - "storage_type": null, - "tags": [], - "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json deleted file mode 100644 index 8fe0d438e1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "meta": { - "limit": 20, - "offset": 0, - "total_count": 4 - }, - "objects": [ - { - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": { - "arch": "64", - "category": "general", - "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", - "favourite": "False", - "image_type": "preinst", - "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", - "os": "linux", - "paid": "False", - "url": "http://www.debian.org/" - }, - "mounted_on": [], - "name": "test node 2-drive", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/9d1d2cf3-08c1-462f-8485-f4b073560809/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": "dssd" - }, - "size": 13958643712, - "snapshots": [], - "status": "unmounted", - "storage_type": "dssd", - "tags": [], - "uuid": "9d1d2cf3-08c1-462f-8485-f4b073560809" - }, - { - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": { - "arch": "64", - "category": "general", - "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", - "favourite": "False", - "image_type": "preinst", - "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", - "os": "linux", - "paid": "False", - "url": "http://www.debian.org/" - }, - "mounted_on": [], - "name": "test node 3-drive", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/c9799969-0016-4298-a72c-93cabc067c6e/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": "dssd" - }, - "size": 13958643712, - "snapshots": [], - "status": "unmounted", - "storage_type": "dssd", - "tags": [], - "uuid": "c9799969-0016-4298-a72c-93cabc067c6e" - }, - { - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": { - "arch": "64", - "category": "general", - "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", - "favourite": "False", - "image_type": "preinst", - "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", - "os": "linux", - "paid": "False", - "url": "http://www.debian.org/" - }, - "mounted_on": [], - "name": "test node 2-drive", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/967c8bbd-ca32-42db-a9b8-95e270e0aae1/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": "dssd" - }, - "size": 13958643712, - "snapshots": [], - "status": "unmounted", - "storage_type": "dssd", - "tags": [], - "uuid": "967c8bbd-ca32-42db-a9b8-95e270e0aae1" - }, - { - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": { - "arch": "64", - "category": "general", - "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", - "favourite": "False", - "image_type": "preinst", - "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", - "os": "linux", - "paid": "False", - "url": "http://www.debian.org/" - }, - "mounted_on": [ - { - "resource_uri": "/api/2.0/servers/e06cf7b3-ea46-4d38-87e0-3f918c4648d3/", - "uuid": "e06cf7b3-ea46-4d38-87e0-3f918c4648d3" - } - ], - "name": "test node 2-drive", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/3e166706-188c-4f38-b8d5-7fc10a5019a1/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": "dssd" - }, - "size": 13958643712, - "snapshots": [], - "status": "mounted", - "storage_type": "dssd", - "tags": [], - "uuid": "3e166706-188c-4f38-b8d5-7fc10a5019a1" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json deleted file mode 100644 index 3a68140069..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "test drive 5", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": null - }, - "size": 2097152000, - "snapshots": [], - "status": "unmounted", - "storage_type": null, - "tags": [], - "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json deleted file mode 100644 index b3f45e092e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "objects": [ - { - "affinities": [], - "allow_multimount": false, - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "test drive 5", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", - "runtime": { - "snapshots_allocated_size": 0, - "storage_type": null - }, - "size": 1164967936, - "snapshots": [], - "status": "creating", - "storage_type": null, - "tags": [], - "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json deleted file mode 100644 index 3a437bbea2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "objects": [ - { - "meta": {}, - "name": "test policy 1", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/fwpolicies/ae9e5982-33fd-4e89-a467-4480256ccdb6/", - "rules": [], - "servers": [], - "uuid": "ae9e5982-33fd-4e89-a467-4480256ccdb6" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json deleted file mode 100644 index 95e604b701..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "objects": [ - { - "meta": {}, - "name": "test policy 2", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/fwpolicies/324819a5-7a5b-4231-957d-662a7429fb8c/", - "rules": [ - { - "action": "accept", - "comment": null, - "direction": "out", - "dst_ip": "127.0.0.1/32", - "dst_port": null, - "ip_proto": "tcp", - "src_ip": "127.0.0.1/32", - "src_port": null - } - ], - "servers": [], - "uuid": "324819a5-7a5b-4231-957d-662a7429fb8c" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json deleted file mode 100644 index d34616bc0d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "meta": { - "limit": 0, - "offset": 0, - "total_count": 2 - }, - "objects": [ - { - "meta": {}, - "name": "test policy", - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "resource_uri": "/api/2.0/fwpolicies/0e339282-0cb5-41ac-a9db-727fb62ff2dc/", - "rules": [], - "servers": [], - "uuid": "0e339282-0cb5-41ac-a9db-727fb62ff2dc" - }, - { - "meta": {}, - "name": "My awesome policy", - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "resource_uri": "/api/2.0/fwpolicies/0c754845-f2ed-4347-8758-4315f7fa9c22/", - "rules": [ - { - "action": "drop", - "comment": "Drop traffic from the VM to IP address 23.0.0.0/32", - "direction": "out", - "dst_ip": "23.0.0.0/32", - "dst_port": null, - "ip_proto": "tcp", - "src_ip": null, - "src_port": null - }, - { - "action": "accept", - "comment": "Allow SSH traffic to the VM from our office in Dubai", - "direction": "in", - "dst_ip": null, - "dst_port": "22", - "ip_proto": "tcp", - "src_ip": "172.66.32.0/24", - "src_port": null - }, - { - "action": "drop", - "comment": "Drop all other SSH traffic to the VM", - "direction": "in", - "dst_ip": null, - "dst_port": "22", - "ip_proto": "tcp", - "src_ip": null, - "src_port": null - }, - { - "action": "drop", - "comment": "Drop all UDP traffic to the VM, not originating from 172.66.32.55", - "direction": "in", - "dst_ip": null, - "dst_port": null, - "ip_proto": "udp", - "src_ip": "!172.66.32.55/32", - "src_port": null - }, - { - "action": "drop", - "comment": "Drop any traffic, to the VM with destination port not between 1-1024", - "direction": "in", - "dst_ip": null, - "dst_port": "!1:1024", - "ip_proto": "tcp", - "src_ip": null, - "src_port": null - } - ], - "servers": [], - "uuid": "0c754845-f2ed-4347-8758-4315f7fa9c22" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json deleted file mode 100644 index c55e9a5f6d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json +++ /dev/null @@ -1,569 +0,0 @@ -{ - "meta": { - "limit": 20, - "offset": 0, - "total_count": 89 - }, - "objects": [ - { - "affinities": [], - "allow_multimount": false, - "arch": "32", - "category": [ - "security" - ], - "description": "IPCop 2.0.2 - i486 - CD.\r\nThe IPCop Firewall is a Linux firewall distribution.", - "favourite": true, - "image_type": "install", - "install_notes": "1. Attach the CD.\\n Please be aware that the CD needs to be attached to the server to IDE. \\n \\n 2. Attach a Drive.\\n Please be aware that the minimum drive size where you are going to install the OS should be 5 GB. \\n \\n 3. Connecting to your server via VNC.\\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 4. Minimum Hardware Requirements.\\n The recommended minimum hardware requirements as publishes by ipcop.org are: 32MB RAM and 386MHz CPU \\n We recommend specifying a higher level of RAM for a better user experience.\\n", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "IPCop 2.0.2", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/6eca8d96-44bc-4637-af97-77ccd7ba4144/", - "size": 1000000000, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.ipcop.org/", - "uuid": "6eca8d96-44bc-4637-af97-77ccd7ba4144" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "FreeBSD-8.4-RELEASE-amd64-disc1", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD.\\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \\n\r\n\\n\r\n2. Attach a Drive.\\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \\n\r\n\\n\r\n3. Connecting to your server via VNC.\\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \\n\r\n\\n\r\n4. Minimum Hardware Requirements.\\n\r\nThe recommended minimum hardware requirements as publishes by freebsd.org are: 0.5 GB RAM and 0.5\\n GHz CPU We recommend specifying a higher level of RAM for a better user experience.\\n\r\n", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "FreeBSD 8.4", - "os": "other", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/c143724d-4d40-4871-bc2c-5120b4263ab3/", - "size": 536870912, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.freebsd.org/", - "uuid": "c143724d-4d40-4871-bc2c-5120b4263ab3" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "32", - "category": [ - "general" - ], - "description": "Ubuntu 12.04 Desktop - 32bit - Install CD", - "favourite": true, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Ubuntu 12.04 Desktop", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/703e693e-056d-4cd6-9531-36ec045fee7c/", - "size": 1000000000, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.ubuntu.com/", - "uuid": "703e693e-056d-4cd6-9531-36ec045fee7c" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "32", - "category": [ - "general" - ], - "description": "Ubuntu 12.04 Server - 32bit - Install CD", - "favourite": true, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. \r\n", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Ubuntu 12.04 Server", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/36b01118-55f4-454f-92ee-578eb6d99867/", - "size": 1000000000, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.ubuntu.com/", - "uuid": "36b01118-55f4-454f-92ee-578eb6d99867" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Windows Server 2012 Standard - 64bit Install CD", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD \\n Please be aware that the CD needs to be attached to the server to IDE. \\n \\n 2. Attach a Drive \\n Please be aware that the minimum drive size where you are going to install the OS should be 32 GB. \\n \\n 3. Connecting to your server via VNC \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 4. Minimum Hardware Requirements \\n The recommended minimum hardware requirements as publishes by Microsoft can be found through the following link: http://msdn.microsoft.com/library/dn303418.aspx We recommend specifying a higher level of RAM for a better user experience. \\n \\n 5. Enter your license key. \\n", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Windows Server Standard 2012", - "os": "windows", - "owner": null, - "paid": true, - "resource_uri": "/api/2.0/libdrives/b4273b6d-b227-4966-9e6e-5d48cebfcaa5/", - "size": 3694116864, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.microsoft.com/", - "uuid": "b4273b6d-b227-4966-9e6e-5d48cebfcaa5" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "32", - "category": [ - "general" - ], - "description": "Knoppix 6 - 32bit - CD", - "favourite": false, - "image_type": "live", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Knoppix.net are: 512MB RAM and 512MHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Knoppix 6.4.3", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/ed47dc6d-4efd-4c05-b2f8-ab32ccf6de3b/", - "size": 3670016000, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://knoppix.net/", - "uuid": "ed47dc6d-4efd-4c05-b2f8-ab32ccf6de3b" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "This image is produced by SixSq specifically to work with SlipStream.", - "favourite": false, - "image_type": "preinst", - "install_notes": "", - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "ubuntu-10.04-toMP", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/5236b9ee-f735-42fd-a236-17558f9e12d3/", - "size": 3221225472, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "5236b9ee-f735-42fd-a236-17558f9e12d3" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "CentOS 6.4 Server - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/30.", - "favourite": false, - "image_type": "preinst", - "install_notes": "1. Clone the Image.\\n\r\nThe image needs to be cloned and then attached to the server.\\n\r\n\\n\r\n2. Connecting to your server via VNC.\\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI.\\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window.\\n\r\nc) Start to configure your server.\\n\r\n\\n\r\n3. Minimum Hardware Requirements.\\n\r\nThe recommended minimum hardware requirements as publishes by centos.org: 0.5GB RAM and 0.5GHz CPU\\n\r\n\\n\r\n4. Update your administrator password.\\n\r\nBy default and for security reasons \"root\" login is completely disabled (including for ssh)\\n\r\nUser \"cloudsigma\" with password \"cloudsigma\" is available for access.\\n\r\nPlease be aware that on the first login you will be asked to change the current password \"cloudsigma\" and set a secure password.\\n\r\nFor \"root\" please use the command \"sudo su\"\\n\r\n\\n\r\n5. Setup your CentOS.\\n\r\n\\n\r\n6. Configuring your Networking.\\n\r\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will assign the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\\n\r\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs.\\n", - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "CentOS 6.4 Server", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/cc08cd15-0c17-429f-bd56-15fefaca9d88/", - "size": 10737418240, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.centos.org/", - "uuid": "cc08cd15-0c17-429f-bd56-15fefaca9d88" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", - "favourite": false, - "image_type": "preinst", - "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "Debian 6.0.7 Desktop", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/e848e216-76bb-4c1d-a376-54e4bdf54fe4/", - "size": 10737418240, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.debian.org/", - "uuid": "e848e216-76bb-4c1d-a376-54e4bdf54fe4" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "CentOS 6.3 - 64bit - DVD\r\n", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5 GB RAM and 0.5 GHz CPU We recommend specifying a higher level of RAM for a better user experience.", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "CentOS 6.3 DVD", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/65c99e46-296c-4d3f-ad1f-88dc06772624/", - "size": 4289396736, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "65c99e46-296c-4d3f-ad1f-88dc06772624" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "CentOS 6.4 - 64bit - DVD\r\n", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the DVD. \\n\r\nPlease be aware that the DVD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5GB RAM and 0.5GHz CPU We recommend specifying a higher level of RAM for a better user experience.", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "CentOS 6.4 DVD", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/608e784a-5bff-4d25-afeb-bf7f998f56ef/", - "size": 4353392640, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "608e784a-5bff-4d25-afeb-bf7f998f56ef" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Ubuntu 10.04.3 LTS Server Edition 64bit - CD", - "favourite": true, - "image_type": "install", - "install_notes": "\r\n1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu,com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Ubuntu 10.04.3 Server", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/b69cbf27-d2a8-44f7-bc5a-3facc70021a8/", - "size": 1000000000, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://ubuntu.com/", - "uuid": "b69cbf27-d2a8-44f7-bc5a-3facc70021a8" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Slackware-13.37 - 64bit - Install DVD", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Slackware.com are: 128MB RAM and 512MHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Slackware 13.37", - "os": "linux", - "owner": null, - "paid": true, - "resource_uri": "/api/2.0/libdrives/e209e588-8c06-44ce-8d57-c10df32c5876/", - "size": 4613734400, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "e209e588-8c06-44ce-8d57-c10df32c5876" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "32", - "category": [ - "general" - ], - "description": "RedHat Enterprise 6.0 - 32bit - Install DVD", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by RedHat.com are: 2GB RAM and 2GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "RedHat Enterprise 6.0", - "os": "linux", - "owner": null, - "paid": true, - "resource_uri": "/api/2.0/libdrives/a0638d80-bc5b-48a3-a7ba-dec2416239bf/", - "size": 2936012800, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.redhat.com/", - "uuid": "a0638d80-bc5b-48a3-a7ba-dec2416239bf" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "CentOS 6.3 SlipStream. This image is produced by SixSq specifically to work with SlipStream.", - "favourite": false, - "image_type": "preinst", - "install_notes": "CentOS 6.3 SlipStream", - "jobs": [], - "licenses": [], - "media": "disk", - "meta": {}, - "mounted_on": [], - "name": "CentOS 6.3 for SlipStream", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/ac51c08f-d22b-4da8-9591-d343947f7455/", - "size": 7516192768, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "ac51c08f-d22b-4da8-9591-d343947f7455" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Debian 6 - 64bit - CD", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Debian 6", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/98f810a3-b8f0-4441-89cd-02be4f2614d7/", - "size": 676331520, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "98f810a3-b8f0-4441-89cd-02be4f2614d7" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Ubuntu 12.10 Server - 64bit - Install CD", - "favourite": true, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. \r\n", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Ubuntu 12.10 Server", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/6afbda4b-1027-4405-9ae9-c7d32f097d31/", - "size": 1000000000, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.ubuntu.com/", - "uuid": "6afbda4b-1027-4405-9ae9-c7d32f097d31" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Debian 7.1 - 64bit - CD", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience.", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Debian 7.1", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/958bf26c-f25b-457d-aedb-a5cfb36bdeef/", - "size": 536870912, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "958bf26c-f25b-457d-aedb-a5cfb36bdeef" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "CentOS 6.2 - 64bit - DVD\r\n", - "favourite": false, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5 GB RAM and 0.5 GHz CPU We recommend specifying a higher level of RAM for a better user experience.\r\n", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "CentOS 6.2 DVD", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/d7cdd30f-2197-47ac-a878-c285c1e67426/", - "size": 4423139328, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "", - "uuid": "d7cdd30f-2197-47ac-a878-c285c1e67426" - }, - { - "affinities": [], - "allow_multimount": false, - "arch": "64", - "category": [ - "general" - ], - "description": "Debian 5.0 - 64bit - CD", - "favourite": true, - "image_type": "install", - "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", - "jobs": [], - "licenses": [], - "media": "cdrom", - "meta": {}, - "mounted_on": [], - "name": "Debian 5.0", - "os": "linux", - "owner": null, - "paid": false, - "resource_uri": "/api/2.0/libdrives/794a068d-228c-4758-81f0-e1bc955a6cce/", - "size": 4697620480, - "status": "unmounted", - "storage_type": null, - "tags": [], - "url": "http://www.debian.org/", - "uuid": "794a068d-228c-4758-81f0-e1bc955a6cce" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json deleted file mode 100644 index 5ddafd751d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json +++ /dev/null @@ -1,2889 +0,0 @@ -{ - "current": { - "cpu": 5, - "dssd": 1, - "ip": 1, - "mem": 7, - "msft_7jq_00341": 1, - "msft_7nq_00302": 1, - "msft_lwa_00135": 1, - "msft_p71_01031": 1, - "msft_p73_04837": 1, - "msft_p73_04837_core": 1, - "msft_tfa_00009": 1, - "msft_tfa_00523": 1, - "sms": 1, - "ssd": 1, - "tx": 8, - "vlan": 1 - }, - "meta": { - "limit": 0, - "offset": 0, - "total_count": 316 - }, - "next": { - "cpu": 5, - "dssd": 1, - "ip": 1, - "mem": 7, - "msft_7jq_00341": 1, - "msft_7nq_00302": 1, - "msft_lwa_00135": 1, - "msft_p71_01031": 1, - "msft_p73_04837": 1, - "msft_p73_04837_core": 1, - "msft_tfa_00009": 1, - "msft_tfa_00523": 1, - "sms": 1, - "ssd": 1, - "tx": 10, - "vlan": 1 - }, - "objects": [ - { - "currency": "CHF", - "id": "18", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.26600000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "EUR", - "id": "20", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.21000000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "GBP", - "id": "22", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.18200000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "USD", - "id": "24", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.28000000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "CHF", - "id": "26", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.76000000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "EUR", - "id": "28", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.60000000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "GBP", - "id": "30", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.52000000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "USD", - "id": "32", - "level": 1, - "multiplier": 2783138807808000, - "price": "0.80000000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "CHF", - "id": "34", - "level": 1, - "multiplier": 2592000, - "price": "4.75000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "EUR", - "id": "36", - "level": 1, - "multiplier": 2592000, - "price": "3.75000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "GBP", - "id": "38", - "level": 1, - "multiplier": 2592000, - "price": "3.25000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "USD", - "id": "40", - "level": 1, - "multiplier": 2592000, - "price": "5.00000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "USD", - "id": "8", - "level": 1, - "multiplier": 3600000, - "price": "0.00790500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "42", - "level": 1, - "multiplier": 2592000, - "price": "19.00000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "USD", - "id": "104", - "level": 2, - "multiplier": 3600000, - "price": "0.00816000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "44", - "level": 1, - "multiplier": 2592000, - "price": "15.00000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "USD", - "id": "108", - "level": 3, - "multiplier": 3600000, - "price": "0.00841500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "46", - "level": 1, - "multiplier": 2592000, - "price": "13.00000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "USD", - "id": "112", - "level": 4, - "multiplier": 3600000, - "price": "0.00867000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "48", - "level": 1, - "multiplier": 2592000, - "price": "20.00000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "CHF", - "id": "2", - "level": 1, - "multiplier": 3600000, - "price": "0.00875500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "54", - "level": 1, - "multiplier": 1073741824, - "price": "0.01950000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "101", - "level": 2, - "multiplier": 3600000, - "price": "0.00901000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "105", - "level": 3, - "multiplier": 3600000, - "price": "0.00935000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "109", - "level": 4, - "multiplier": 3600000, - "price": "0.00960500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "113", - "level": 5, - "multiplier": 3600000, - "price": "0.01028500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "117", - "level": 6, - "multiplier": 3600000, - "price": "0.01088000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "121", - "level": 7, - "multiplier": 3600000, - "price": "0.01207000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "125", - "level": 8, - "multiplier": 3600000, - "price": "0.01385500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "10", - "level": 1, - "multiplier": 3865470566400, - "price": "0.01256000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "133", - "level": 10, - "multiplier": 3865470566400, - "price": "0.02080000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "137", - "level": 11, - "multiplier": 3865470566400, - "price": "0.02192000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "141", - "level": 12, - "multiplier": 3865470566400, - "price": "0.02288000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "116", - "level": 5, - "multiplier": 3600000, - "price": "0.00926500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "120", - "level": 6, - "multiplier": 3600000, - "price": "0.00977500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "124", - "level": 7, - "multiplier": 3600000, - "price": "0.01088000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "16", - "level": 1, - "multiplier": 3865470566400, - "price": "0.01128000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "136", - "level": 10, - "multiplier": 3865470566400, - "price": "0.01872000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "140", - "level": 11, - "multiplier": 3865470566400, - "price": "0.01968000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "144", - "level": 12, - "multiplier": 3865470566400, - "price": "0.02064000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "148", - "level": 13, - "multiplier": 3865470566400, - "price": "0.02136000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "152", - "level": 14, - "multiplier": 3865470566400, - "price": "0.02184000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "156", - "level": 15, - "multiplier": 3865470566400, - "price": "0.02232000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "160", - "level": 16, - "multiplier": 3865470566400, - "price": "0.02280000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "4", - "level": 1, - "multiplier": 3600000, - "price": "0.00612000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "102", - "level": 2, - "multiplier": 3600000, - "price": "0.00637500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "106", - "level": 3, - "multiplier": 3600000, - "price": "0.00654500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "110", - "level": 4, - "multiplier": 3600000, - "price": "0.00671500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "114", - "level": 5, - "multiplier": 3600000, - "price": "0.00714000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "128", - "level": 8, - "multiplier": 3600000, - "price": "0.01249500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "132", - "level": 9, - "multiplier": 3600000, - "price": "0.01411000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "60", - "level": 10, - "multiplier": 3600000, - "price": "0.01623500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "64", - "level": 11, - "multiplier": 3600000, - "price": "0.01734000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "68", - "level": 12, - "multiplier": 3600000, - "price": "0.01844500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "72", - "level": 13, - "multiplier": 3600000, - "price": "0.01921000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "76", - "level": 14, - "multiplier": 3600000, - "price": "0.01980500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "80", - "level": 15, - "multiplier": 3600000, - "price": "0.02031500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "118", - "level": 6, - "multiplier": 3600000, - "price": "0.00756500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "122", - "level": 7, - "multiplier": 3600000, - "price": "0.00841500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "126", - "level": 8, - "multiplier": 3600000, - "price": "0.00969000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "130", - "level": 9, - "multiplier": 3600000, - "price": "0.01096500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "58", - "level": 10, - "multiplier": 3600000, - "price": "0.01266500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "62", - "level": 11, - "multiplier": 3600000, - "price": "0.01351500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "66", - "level": 12, - "multiplier": 3600000, - "price": "0.01428000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "145", - "level": 13, - "multiplier": 3865470566400, - "price": "0.02376000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "149", - "level": 14, - "multiplier": 3865470566400, - "price": "0.02424000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "153", - "level": 15, - "multiplier": 3865470566400, - "price": "0.02480000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "157", - "level": 16, - "multiplier": 3865470566400, - "price": "0.02536000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "50", - "level": 1, - "multiplier": 1073741824, - "price": "0.03250000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "253", - "level": 2, - "multiplier": 1073741824, - "price": "0.03420000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "257", - "level": 3, - "multiplier": 1073741824, - "price": "0.03750000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "261", - "level": 4, - "multiplier": 1073741824, - "price": "0.04250000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "265", - "level": 5, - "multiplier": 1073741824, - "price": "0.04750000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "269", - "level": 6, - "multiplier": 1073741824, - "price": "0.05170000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "273", - "level": 7, - "multiplier": 1073741824, - "price": "0.05580000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "277", - "level": 8, - "multiplier": 1073741824, - "price": "0.05920000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "281", - "level": 9, - "multiplier": 1073741824, - "price": "0.06250000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "209", - "level": 10, - "multiplier": 1073741824, - "price": "0.06500000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "213", - "level": 11, - "multiplier": 1073741824, - "price": "0.06750000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "217", - "level": 12, - "multiplier": 1073741824, - "price": "0.07000000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "221", - "level": 13, - "multiplier": 1073741824, - "price": "0.07330000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "225", - "level": 14, - "multiplier": 1073741824, - "price": "0.07830000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "229", - "level": 15, - "multiplier": 1073741824, - "price": "0.08330000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "233", - "level": 16, - "multiplier": 1073741824, - "price": "0.08830000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "84", - "level": 16, - "multiplier": 3600000, - "price": "0.02091000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "5", - "level": 0, - "multiplier": 3600000, - "price": "0.01105000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "13", - "level": 0, - "multiplier": 3865470566400, - "price": "0.01352000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "53", - "level": 0, - "multiplier": 1073741824, - "price": "0.04225000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "255", - "level": 2, - "multiplier": 1073741824, - "price": "0.02050000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "129", - "level": 9, - "multiplier": 3600000, - "price": "0.01564000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "57", - "level": 10, - "multiplier": 3600000, - "price": "0.01810500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "61", - "level": 11, - "multiplier": 3600000, - "price": "0.01929500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "65", - "level": 12, - "multiplier": 3600000, - "price": "0.02048500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "69", - "level": 13, - "multiplier": 3600000, - "price": "0.02142000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "73", - "level": 14, - "multiplier": 3600000, - "price": "0.02193000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "77", - "level": 15, - "multiplier": 3600000, - "price": "0.02261000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "81", - "level": 16, - "multiplier": 3600000, - "price": "0.02320500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "259", - "level": 3, - "multiplier": 1073741824, - "price": "0.02250000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "85", - "level": 17, - "multiplier": 3600000, - "price": "0.02558500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "263", - "level": 4, - "multiplier": 1073741824, - "price": "0.02550000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "89", - "level": 18, - "multiplier": 3600000, - "price": "0.02805000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "267", - "level": 5, - "multiplier": 1073741824, - "price": "0.02850000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "271", - "level": 6, - "multiplier": 1073741824, - "price": "0.03100000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "210", - "level": 10, - "multiplier": 1073741824, - "price": "0.04550000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "212", - "level": 10, - "multiplier": 1073741824, - "price": "0.05850000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "275", - "level": 7, - "multiplier": 1073741824, - "price": "0.03350000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "214", - "level": 11, - "multiplier": 1073741824, - "price": "0.04730000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "216", - "level": 11, - "multiplier": 1073741824, - "price": "0.06080000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "279", - "level": 8, - "multiplier": 1073741824, - "price": "0.03550000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "218", - "level": 12, - "multiplier": 1073741824, - "price": "0.04900000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "220", - "level": 12, - "multiplier": 1073741824, - "price": "0.06300000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "283", - "level": 9, - "multiplier": 1073741824, - "price": "0.03750000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "222", - "level": 13, - "multiplier": 1073741824, - "price": "0.05130000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "224", - "level": 13, - "multiplier": 1073741824, - "price": "0.06600000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "211", - "level": 10, - "multiplier": 1073741824, - "price": "0.03900000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "226", - "level": 14, - "multiplier": 1073741824, - "price": "0.05480000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "228", - "level": 14, - "multiplier": 1073741824, - "price": "0.07050000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "215", - "level": 11, - "multiplier": 1073741824, - "price": "0.04050000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "230", - "level": 15, - "multiplier": 1073741824, - "price": "0.05830000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "232", - "level": 15, - "multiplier": 1073741824, - "price": "0.07500000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "219", - "level": 12, - "multiplier": 1073741824, - "price": "0.04200000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "234", - "level": 16, - "multiplier": 1073741824, - "price": "0.06180000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "236", - "level": 16, - "multiplier": 1073741824, - "price": "0.07950000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "223", - "level": 13, - "multiplier": 1073741824, - "price": "0.04400000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "238", - "level": 17, - "multiplier": 1073741824, - "price": "0.06530000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "240", - "level": 17, - "multiplier": 1073741824, - "price": "0.08400000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "227", - "level": 14, - "multiplier": 1073741824, - "price": "0.04700000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "242", - "level": 18, - "multiplier": 1073741824, - "price": "0.07000000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "244", - "level": 18, - "multiplier": 1073741824, - "price": "0.09000000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "231", - "level": 15, - "multiplier": 1073741824, - "price": "0.05000000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "246", - "level": 19, - "multiplier": 1073741824, - "price": "0.07580000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "248", - "level": 19, - "multiplier": 1073741824, - "price": "0.09750000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "52", - "level": 1, - "multiplier": 1073741824, - "price": "0.02280000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "56", - "level": 1, - "multiplier": 1073741824, - "price": "0.02930000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "235", - "level": 16, - "multiplier": 1073741824, - "price": "0.05300000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "250", - "level": 20, - "multiplier": 1073741824, - "price": "0.08280000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "252", - "level": 20, - "multiplier": 1073741824, - "price": "0.10650000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "239", - "level": 17, - "multiplier": 1073741824, - "price": "0.05600000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "254", - "level": 2, - "multiplier": 1073741824, - "price": "0.02390000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "256", - "level": 2, - "multiplier": 1073741824, - "price": "0.03080000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "243", - "level": 18, - "multiplier": 1073741824, - "price": "0.06000000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "258", - "level": 3, - "multiplier": 1073741824, - "price": "0.02630000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "260", - "level": 3, - "multiplier": 1073741824, - "price": "0.03380000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "247", - "level": 19, - "multiplier": 1073741824, - "price": "0.06500000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "262", - "level": 4, - "multiplier": 1073741824, - "price": "0.02980000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "264", - "level": 4, - "multiplier": 1073741824, - "price": "0.03830000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "GBP", - "id": "251", - "level": 20, - "multiplier": 1073741824, - "price": "0.07100000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "266", - "level": 5, - "multiplier": 1073741824, - "price": "0.03330000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "268", - "level": 5, - "multiplier": 1073741824, - "price": "0.04280000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "270", - "level": 6, - "multiplier": 1073741824, - "price": "0.03620000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "272", - "level": 6, - "multiplier": 1073741824, - "price": "0.04650000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "274", - "level": 7, - "multiplier": 1073741824, - "price": "0.03910000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "276", - "level": 7, - "multiplier": 1073741824, - "price": "0.05030000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "278", - "level": 8, - "multiplier": 1073741824, - "price": "0.04140000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "280", - "level": 8, - "multiplier": 1073741824, - "price": "0.05330000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "282", - "level": 9, - "multiplier": 1073741824, - "price": "0.04380000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "284", - "level": 9, - "multiplier": 1073741824, - "price": "0.05630000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "180", - "level": 2, - "multiplier": 3865470566400, - "price": "0.01152000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "93", - "level": 19, - "multiplier": 3600000, - "price": "0.03162000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "CHF", - "id": "97", - "level": 20, - "multiplier": 3600000, - "price": "0.03638000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "184", - "level": 3, - "multiplier": 3865470566400, - "price": "0.01176000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "306", - "level": 0, - "multiplier": 2592000, - "price": "15.69000000000000000000", - "resource": "msft_7nq_00302", - "unit": "" - }, - { - "currency": "CHF", - "id": "297", - "level": 0, - "multiplier": 2592000, - "price": "8.50000000000000000000", - "resource": "msft_p71_01031", - "unit": "" - }, - { - "currency": "CHF", - "id": "301", - "level": 0, - "multiplier": 2592000, - "price": "1.60000000000000000000", - "resource": "msft_p73_04837_core", - "unit": "" - }, - { - "currency": "CHF", - "id": "307", - "level": 0, - "multiplier": 2592000, - "price": "0.98000000000000000000", - "resource": "msft_tfa_00523", - "unit": "" - }, - { - "currency": "EUR", - "id": "295", - "level": 0, - "multiplier": 2592000, - "price": "350.00000000000000000000", - "resource": "msft_tfa_00009", - "unit": "count/month" - }, - { - "currency": "EUR", - "id": "313", - "level": 0, - "multiplier": 2592000, - "price": "0.73010000000000000000", - "resource": "msft_tfa_00523", - "unit": "" - }, - { - "currency": "GBP", - "id": "314", - "level": 0, - "multiplier": 2592000, - "price": "38.51520000000000000000", - "resource": "msft_7jq_00341", - "unit": "" - }, - { - "currency": "GBP", - "id": "315", - "level": 0, - "multiplier": 2592000, - "price": "10.04160000000000000000", - "resource": "msft_7nq_00302", - "unit": "" - }, - { - "currency": "GBP", - "id": "288", - "level": 0, - "multiplier": 2592000, - "price": "15.00000000000000000000", - "resource": "msft_lwa_00135", - "unit": "count/month" - }, - { - "currency": "GBP", - "id": "300", - "level": 0, - "multiplier": 2592000, - "price": "5.44000000000000000000", - "resource": "msft_p71_01031", - "unit": "" - }, - { - "currency": "GBP", - "id": "292", - "level": 0, - "multiplier": 2592000, - "price": "27.00000000000000000000", - "resource": "msft_p73_04837", - "unit": "count/month" - }, - { - "currency": "GBP", - "id": "304", - "level": 0, - "multiplier": 2592000, - "price": "1.02400000000000000000", - "resource": "msft_p73_04837_core", - "unit": "" - }, - { - "currency": "GBP", - "id": "296", - "level": 0, - "multiplier": 2592000, - "price": "300.00000000000000000000", - "resource": "msft_tfa_00009", - "unit": "count/month" - }, - { - "currency": "GBP", - "id": "316", - "level": 0, - "multiplier": 2592000, - "price": "0.62720000000000000000", - "resource": "msft_tfa_00523", - "unit": "" - }, - { - "currency": "USD", - "id": "188", - "level": 4, - "multiplier": 3865470566400, - "price": "0.01200000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "192", - "level": 5, - "multiplier": 3865470566400, - "price": "0.01248000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "196", - "level": 6, - "multiplier": 3865470566400, - "price": "0.01296000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "200", - "level": 7, - "multiplier": 3865470566400, - "price": "0.01392000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "204", - "level": 8, - "multiplier": 3865470566400, - "price": "0.01536000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "208", - "level": 9, - "multiplier": 3865470566400, - "price": "0.01680000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "164", - "level": 17, - "multiplier": 3865470566400, - "price": "0.02472000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "168", - "level": 18, - "multiplier": 3865470566400, - "price": "0.02664000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "172", - "level": 19, - "multiplier": 3865470566400, - "price": "0.02952000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "176", - "level": 20, - "multiplier": 3865470566400, - "price": "0.03336000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "178", - "level": 2, - "multiplier": 3865470566400, - "price": "0.00896000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "182", - "level": 3, - "multiplier": 3865470566400, - "price": "0.00912000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "186", - "level": 4, - "multiplier": 3865470566400, - "price": "0.00936000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "190", - "level": 5, - "multiplier": 3865470566400, - "price": "0.00976000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "194", - "level": 6, - "multiplier": 3865470566400, - "price": "0.01008000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "198", - "level": 7, - "multiplier": 3865470566400, - "price": "0.01080000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "202", - "level": 8, - "multiplier": 3865470566400, - "price": "0.01200000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "206", - "level": 9, - "multiplier": 3865470566400, - "price": "0.01304000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "162", - "level": 17, - "multiplier": 3865470566400, - "price": "0.01920000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "166", - "level": 18, - "multiplier": 3865470566400, - "price": "0.02072000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "170", - "level": 19, - "multiplier": 3865470566400, - "price": "0.02296000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "174", - "level": 20, - "multiplier": 3865470566400, - "price": "0.02592000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "179", - "level": 2, - "multiplier": 3865470566400, - "price": "0.00768000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "183", - "level": 3, - "multiplier": 3865470566400, - "price": "0.00784000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "187", - "level": 4, - "multiplier": 3865470566400, - "price": "0.00800000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "191", - "level": 5, - "multiplier": 3865470566400, - "price": "0.00832000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "195", - "level": 6, - "multiplier": 3865470566400, - "price": "0.00864000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "1", - "level": 0, - "multiplier": 3600000, - "price": "0.01700000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "3", - "level": 0, - "multiplier": 3600000, - "price": "0.01360000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "11", - "level": 0, - "multiplier": 3865470566400, - "price": "0.01664000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "51", - "level": 0, - "multiplier": 1073741824, - "price": "0.05200000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "EUR", - "id": "19", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.16000000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "EUR", - "id": "27", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.16000000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "EUR", - "id": "35", - "level": 0, - "multiplier": 2592000, - "price": "4.00000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "EUR", - "id": "43", - "level": 0, - "multiplier": 2592000, - "price": "8.00000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "GBP", - "id": "21", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.01352000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "GBP", - "id": "29", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.01352000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "GBP", - "id": "37", - "level": 0, - "multiplier": 2592000, - "price": "3.25000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "GBP", - "id": "45", - "level": 0, - "multiplier": 2592000, - "price": "6.50000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "CHF", - "id": "9", - "level": 0, - "multiplier": 3865470566400, - "price": "0.02080000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "49", - "level": 0, - "multiplier": 1073741824, - "price": "0.06500000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "17", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.20000000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "CHF", - "id": "25", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.45000000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "CHF", - "id": "33", - "level": 0, - "multiplier": 2592000, - "price": "5.00000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "CHF", - "id": "41", - "level": 0, - "multiplier": 2592000, - "price": "9.50000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "USD", - "id": "7", - "level": 0, - "multiplier": 3600000, - "price": "0.01640000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "15", - "level": 0, - "multiplier": 3865470566400, - "price": "0.01840000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "USD", - "id": "55", - "level": 0, - "multiplier": 1073741824, - "price": "0.05850000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "23", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.18000000000000000000", - "resource": "dssd", - "unit": "GB/month" - }, - { - "currency": "USD", - "id": "31", - "level": 0, - "multiplier": 2783138807808000, - "price": "0.47400000000000000000", - "resource": "ssd", - "unit": "GB/month" - }, - { - "currency": "USD", - "id": "39", - "level": 0, - "multiplier": 2592000, - "price": "4.50000000000000000000", - "resource": "ip", - "unit": "IP" - }, - { - "currency": "USD", - "id": "47", - "level": 0, - "multiplier": 2592000, - "price": "10.00000000000000000000", - "resource": "vlan", - "unit": "VLAN" - }, - { - "currency": "CHF", - "id": "177", - "level": 2, - "multiplier": 3865470566400, - "price": "0.01280000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "181", - "level": 3, - "multiplier": 3865470566400, - "price": "0.01304000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "185", - "level": 4, - "multiplier": 3865470566400, - "price": "0.01328000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "189", - "level": 5, - "multiplier": 3865470566400, - "price": "0.01392000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "193", - "level": 6, - "multiplier": 3865470566400, - "price": "0.01440000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "197", - "level": 7, - "multiplier": 3865470566400, - "price": "0.01552000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "201", - "level": 8, - "multiplier": 3865470566400, - "price": "0.01712000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "205", - "level": 9, - "multiplier": 3865470566400, - "price": "0.01872000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "161", - "level": 17, - "multiplier": 3865470566400, - "price": "0.02744000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "165", - "level": 18, - "multiplier": 3865470566400, - "price": "0.02960000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "169", - "level": 19, - "multiplier": 3865470566400, - "price": "0.03280000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "173", - "level": 20, - "multiplier": 3865470566400, - "price": "0.03704000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "237", - "level": 17, - "multiplier": 1073741824, - "price": "0.09330000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "241", - "level": 18, - "multiplier": 1073741824, - "price": "0.10000000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "245", - "level": 19, - "multiplier": 1073741824, - "price": "0.10830000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "CHF", - "id": "249", - "level": 20, - "multiplier": 1073741824, - "price": "0.11830000000000000000", - "resource": "tx", - "unit": "GB" - }, - { - "currency": "USD", - "id": "88", - "level": 17, - "multiplier": 3600000, - "price": "0.02303500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "92", - "level": 18, - "multiplier": 3600000, - "price": "0.02524500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "96", - "level": 19, - "multiplier": 3600000, - "price": "0.02847500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "USD", - "id": "100", - "level": 20, - "multiplier": 3600000, - "price": "0.03281000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "70", - "level": 13, - "multiplier": 3600000, - "price": "0.01496000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "74", - "level": 14, - "multiplier": 3600000, - "price": "0.01538500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "78", - "level": 15, - "multiplier": 3600000, - "price": "0.01581000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "82", - "level": 16, - "multiplier": 3600000, - "price": "0.01623500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "86", - "level": 17, - "multiplier": 3600000, - "price": "0.01793500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "90", - "level": 18, - "multiplier": 3600000, - "price": "0.01955000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "94", - "level": 19, - "multiplier": 3600000, - "price": "0.02210000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "98", - "level": 20, - "multiplier": 3600000, - "price": "0.02550000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "EUR", - "id": "12", - "level": 1, - "multiplier": 3865470566400, - "price": "0.00880000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "134", - "level": 10, - "multiplier": 3865470566400, - "price": "0.01456000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "138", - "level": 11, - "multiplier": 3865470566400, - "price": "0.01528000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "142", - "level": 12, - "multiplier": 3865470566400, - "price": "0.01608000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "146", - "level": 13, - "multiplier": 3865470566400, - "price": "0.01664000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "150", - "level": 14, - "multiplier": 3865470566400, - "price": "0.01696000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "154", - "level": 15, - "multiplier": 3865470566400, - "price": "0.01736000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "EUR", - "id": "158", - "level": 16, - "multiplier": 3865470566400, - "price": "0.01776000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "6", - "level": 1, - "multiplier": 3600000, - "price": "0.00527000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "103", - "level": 2, - "multiplier": 3600000, - "price": "0.00544000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "107", - "level": 3, - "multiplier": 3600000, - "price": "0.00561000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "111", - "level": 4, - "multiplier": 3600000, - "price": "0.00578000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "115", - "level": 5, - "multiplier": 3600000, - "price": "0.00612000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "119", - "level": 6, - "multiplier": 3600000, - "price": "0.00654500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "123", - "level": 7, - "multiplier": 3600000, - "price": "0.00722500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "127", - "level": 8, - "multiplier": 3600000, - "price": "0.00833000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "131", - "level": 9, - "multiplier": 3600000, - "price": "0.00943500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "59", - "level": 10, - "multiplier": 3600000, - "price": "0.01088000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "63", - "level": 11, - "multiplier": 3600000, - "price": "0.01156000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "67", - "level": 12, - "multiplier": 3600000, - "price": "0.01232500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "71", - "level": 13, - "multiplier": 3600000, - "price": "0.01283500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "75", - "level": 14, - "multiplier": 3600000, - "price": "0.01326000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "79", - "level": 15, - "multiplier": 3600000, - "price": "0.01360000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "83", - "level": 16, - "multiplier": 3600000, - "price": "0.01394000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "87", - "level": 17, - "multiplier": 3600000, - "price": "0.01538500000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "91", - "level": 18, - "multiplier": 3600000, - "price": "0.01683000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "95", - "level": 19, - "multiplier": 3600000, - "price": "0.01904000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "99", - "level": 20, - "multiplier": 3600000, - "price": "0.02193000000000000000", - "resource": "cpu", - "unit": "GHz/hour" - }, - { - "currency": "GBP", - "id": "14", - "level": 1, - "multiplier": 3865470566400, - "price": "0.00752000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "199", - "level": 7, - "multiplier": 3865470566400, - "price": "0.00928000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "203", - "level": 8, - "multiplier": 3865470566400, - "price": "0.01024000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "207", - "level": 9, - "multiplier": 3865470566400, - "price": "0.01120000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "135", - "level": 10, - "multiplier": 3865470566400, - "price": "0.01248000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "139", - "level": 11, - "multiplier": 3865470566400, - "price": "0.01312000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "143", - "level": 12, - "multiplier": 3865470566400, - "price": "0.01376000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "147", - "level": 13, - "multiplier": 3865470566400, - "price": "0.01424000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "151", - "level": 14, - "multiplier": 3865470566400, - "price": "0.01456000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "155", - "level": 15, - "multiplier": 3865470566400, - "price": "0.01488000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "159", - "level": 16, - "multiplier": 3865470566400, - "price": "0.01520000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "163", - "level": 17, - "multiplier": 3865470566400, - "price": "0.01648000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "167", - "level": 18, - "multiplier": 3865470566400, - "price": "0.01776000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "171", - "level": 19, - "multiplier": 3865470566400, - "price": "0.01968000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "GBP", - "id": "175", - "level": 20, - "multiplier": 3865470566400, - "price": "0.02224000000000000000", - "resource": "mem", - "unit": "GB/hour" - }, - { - "currency": "CHF", - "id": "305", - "level": 0, - "multiplier": 2592000, - "price": "60.18000000000000000000", - "resource": "msft_7jq_00341", - "unit": "" - }, - { - "currency": "CHF", - "id": "285", - "level": 0, - "multiplier": 2592000, - "price": "25.00000000000000000000", - "resource": "msft_lwa_00135", - "unit": "count/month" - }, - { - "currency": "CHF", - "id": "289", - "level": 0, - "multiplier": 2592000, - "price": "45.00000000000000000000", - "resource": "msft_p73_04837", - "unit": "count/month" - }, - { - "currency": "CHF", - "id": "293", - "level": 0, - "multiplier": 2592000, - "price": "500.00000000000000000000", - "resource": "msft_tfa_00009", - "unit": "count/month" - }, - { - "currency": "USD", - "id": "308", - "level": 0, - "multiplier": 2592000, - "price": "58.07370000000000000000", - "resource": "msft_7jq_00341", - "unit": "" - }, - { - "currency": "USD", - "id": "309", - "level": 0, - "multiplier": 2592000, - "price": "15.14085000000000000000", - "resource": "msft_7nq_00302", - "unit": "" - }, - { - "currency": "USD", - "id": "286", - "level": 0, - "multiplier": 2592000, - "price": "22.50000000000000000000", - "resource": "msft_lwa_00135", - "unit": "count/month" - }, - { - "currency": "USD", - "id": "298", - "level": 0, - "multiplier": 2592000, - "price": "8.20250000000000000000", - "resource": "msft_p71_01031", - "unit": "" - }, - { - "currency": "USD", - "id": "290", - "level": 0, - "multiplier": 2592000, - "price": "40.50000000000000000000", - "resource": "msft_p73_04837", - "unit": "count/month" - }, - { - "currency": "USD", - "id": "302", - "level": 0, - "multiplier": 2592000, - "price": "1.54400000000000000000", - "resource": "msft_p73_04837_core", - "unit": "" - }, - { - "currency": "USD", - "id": "294", - "level": 0, - "multiplier": 2592000, - "price": "450.00000000000000000000", - "resource": "msft_tfa_00009", - "unit": "count/month" - }, - { - "currency": "USD", - "id": "310", - "level": 0, - "multiplier": 2592000, - "price": "0.94570000000000000000", - "resource": "msft_tfa_00523", - "unit": "" - }, - { - "currency": "EUR", - "id": "311", - "level": 0, - "multiplier": 2592000, - "price": "44.83410000000000000000", - "resource": "msft_7jq_00341", - "unit": "" - }, - { - "currency": "EUR", - "id": "312", - "level": 0, - "multiplier": 2592000, - "price": "11.68905000000000000000", - "resource": "msft_7nq_00302", - "unit": "" - }, - { - "currency": "EUR", - "id": "287", - "level": 0, - "multiplier": 2592000, - "price": "17.50000000000000000000", - "resource": "msft_lwa_00135", - "unit": "count/month" - }, - { - "currency": "EUR", - "id": "299", - "level": 0, - "multiplier": 2592000, - "price": "6.33250000000000000000", - "resource": "msft_p71_01031", - "unit": "" - }, - { - "currency": "EUR", - "id": "291", - "level": 0, - "multiplier": 2592000, - "price": "31.50000000000000000000", - "resource": "msft_p73_04837", - "unit": "count/month" - }, - { - "currency": "EUR", - "id": "303", - "level": 0, - "multiplier": 2592000, - "price": "1.19200000000000000000", - "resource": "msft_p73_04837_core", - "unit": "" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json deleted file mode 100644 index 55f1d39fd2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "context": true, - "cpu": 2000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 536870912, - "meta": {}, - "name": "test_server_updated", - "nics": [ - { - "boot_order": null, - "firewall_policy": { - "resource_uri": "/api/2.0/fwpolicies/461dfb8c-e641-43d7-a20e-32e2aa399086/", - "uuid": "461dfb8c-e641-43d7-a20e-32e2aa399086" - }, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:58:83:c4:07:fc", - "model": "virtio", - "runtime": null, - "vlan": null - } - ], - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/d6bde7f2-69ca-4825-909b-fcc08ea928ef/", - "runtime": null, - "smp": 1, - "status": "stopped", - "tags": [], - "uuid": "d6bde7f2-69ca-4825-909b-fcc08ea928ef", - "vnc_password": "updated_password" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_avail_groups.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_avail_groups.json deleted file mode 100644 index 6a4b2a8798..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_avail_groups.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - [ - "63456dc4-36f9-4a3f-b478-4d376b8ff5a9", - "ede05e68-c997-4aad-816a-39469fd1a562" - ], - [ - "ad8caf99-45c4-45fc-8ba7-acb8a68be66f", - "4b9e1487-0b80-4f65-9c3e-e840dde27ccd" - ], - [ - "658bafdf-8fbf-4fc6-be4f-74ecc7f0e8a5" - ] -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json deleted file mode 100644 index 44b03c64d1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "context": true, - "cpu": 1000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [ - { - "boot_order": 1, - "dev_channel": "0:0", - "device": "ide", - "drive": { - "resource_uri": "/api/2.0/drives/f1e42abe-f7db-4dcc-b37e-e53aca7a3ba9/", - "uuid": "f1e42abe-f7db-4dcc-b37e-e53aca7a3ba9" - } - } - ], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 2147483648, - "meta": { - "description": "ddd", - "ssh_public_key": "" - }, - "name": "test cloned node", - "nics": [ - { - "boot_order": null, - "firewall_policy": { - "resource_uri": "/api/2.0/fwpolicies/461dfb8c-e641-43d7-a20e-32e2aa399086/", - "uuid": "461dfb8c-e641-43d7-a20e-32e2aa399086" - }, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:76:4c:96:e1:98", - "model": "virtio", - "runtime": null, - "vlan": null - } - ], - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/470ea5b9-3beb-4506-9cac-e3c63002480b/", - "runtime": null, - "smp": 1, - "status": "cloning", - "tags": [ - { - "resource_uri": "/api/2.0/tags/e60bb2d2-08d4-4255-adac-5faf87efcdd2/", - "uuid": "e60bb2d2-08d4-4255-adac-5faf87efcdd2" - } - ], - "uuid": "470ea5b9-3beb-4506-9cac-e3c63002480b", - "vnc_password": "xxxx" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json deleted file mode 100644 index e1322739bb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "action": "close_vnc", - "result": "success", - "uuid": "2e64e5e4-f31d-471a-ac1b-1ae079652e40" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json deleted file mode 100644 index 4c93a60f0b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "objects": [ - { - "context": true, - "cpu": 1000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 536870912, - "meta": {}, - "name": "test node", - "nics": [ - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:08:76:b1:ce:41", - "model": "virtio", - "runtime": null, - "vlan": null - } - ], - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/9de75ed6_fd33_45e2_963f_d405f31fd911/", - "runtime": null, - "smp": 1, - "status": "started", - "tags": [], - "uuid": "9de75ed6_fd33_45e2_963f_d405f31fd911", - "vnc_password": "testserver" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create_with_vlan.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create_with_vlan.json deleted file mode 100644 index ee1b2d7820..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create_with_vlan.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "objects": [ - { - "context": true, - "cpu": 1100, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [ - { - "boot_order": 1, - "dev_channel": "0:0", - "device": "ide", - "drive": { - "resource_uri": "/api/2.0/drives/7c0efbb2-b1e8-4e77-9d72-9f9f9d75ae7b/", - "uuid": "7c0efbb2-b1e8-4e77-9d72-9f9f9d75ae7b" - }, - "runtime": null - } - ], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 671088640, - "meta": {}, - "name": "test node vlan", - "nics": [ - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:94:75:3c:16:34", - "model": "virtio", - "runtime": null, - "vlan": null - }, - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": null, - "ip_v6_conf": null, - "mac": "22:84:c4:af:f3:fc", - "model": "virtio", - "runtime": null, - "vlan": { - "resource_uri": "/api/2.0/vlans/39ae851d-433f-4ac2-a803-ffa24cb1fa3e/", - "uuid": "39ae851d-433f-4ac2-a803-ffa24cb1fa3e" - } - } - ], - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/c8b034fb-9e66-4892-be12-a36121d4b704/", - "runtime": null, - "smp": 1, - "status": "stopped", - "tags": [], - "uuid": "9de75ed6_fd33_45e2_963f_d405f31fd911", - "vnc_password": "testserver" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json deleted file mode 100644 index 24eb4b229b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "meta": { - "limit": 20, - "offset": 0, - "total_count": 2 - }, - "objects": [ - { - "context": true, - "cpu": 1000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 1073741824, - "meta": { - "description": "test description 2", - "ssh_public_key": "" - }, - "name": "test no drives", - "nics": [ - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:98:ce:04:50:df", - "model": "virtio", - "runtime": null, - "vlan": null - } - ], - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/9de75ed6-fd33-45e2-963f-d405f31fd911/", - "runtime": null, - "smp": 1, - "status": "stopped", - "tags": [], - "uuid": "9de75ed6-fd33-45e2-963f-d405f31fd911", - "vnc_password": "bar" - }, - { - "context": true, - "cpu": 2000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [ - { - "boot_order": 1, - "dev_channel": "0:0", - "device": "ide", - "drive": { - "resource_uri": "/api/2.0/drives/3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9/", - "uuid": "3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9" - } - } - ], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 2147483648, - "meta": { - "description": "test1" - }, - "name": "test-1", - "nics": [ - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:22:4e:1e:e0:7e", - "model": "virtio", - "runtime": null, - "vlan": null - } - ], - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/9414bbeb-e908-4e55-ae3f-2eb61adc50d8/", - "runtime": null, - "smp": 1, - "status": "stopped", - "tags": [], - "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8", - "vnc_password": "foo" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json deleted file mode 100644 index b89ec2b86e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json +++ /dev/null @@ -1,162 +0,0 @@ -{ - "meta": { - "limit": 20, - "offset": 0, - "total_count": 2 - }, - "objects": [ - { - "context": true, - "cpu": 1000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 1073741824, - "meta": { - "description": "test description 2", - "ssh_public_key": "" - }, - "name": "test no drives", - "nics": [ - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:98:ce:04:50:df", - "model": "virtio", - "runtime": { - "interface_type": "public", - "io": { - "bytes_recv": "1323", - "bytes_sent": "21535", - "packets_recv": "3", - "packets_sent": "278" - }, - "ip_v4": { - "resource_uri": "/api/2.0/ips/185.12.5.181/", - "uuid": "185.12.5.181" - }, - "ip_v6": null - }, - "vlan": null - }, - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:2c:03:99:32:be", - "model": "virtio", - "runtime": { - "interface_type": "public", - "io": { - "bytes_recv": "0", - "bytes_sent": "0", - "packets_recv": "0", - "packets_sent": "0" - }, - "ip_v4": { - "resource_uri": "/api/2.0/ips/178.22.68.55/", - "uuid": "178.22.68.55" - }, - "ip_v6": null - }, - "vlan": null - } - ], - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/9de75ed6-fd33-45e2-963f-d405f31fd911/", - "runtime": { - "active_since": "2013-11-05T10:15:42+00:00", - "nics": [ - { - "interface_type": "public", - "io": { - "bytes_recv": "1323", - "bytes_sent": "21535", - "packets_recv": "3", - "packets_sent": "278" - }, - "ip_v4": { - "resource_uri": "/api/2.0/ips/185.12.5.181/", - "uuid": "185.12.5.181" - }, - "ip_v6": null, - "mac": "22:98:ce:04:50:df" - } - ] - }, - "smp": 1, - "status": "running", - "tags": [], - "uuid": "9de75ed6-fd33-45e2-963f-d405f31fd911", - "vnc_password": "foo" - }, - { - "context": true, - "cpu": 2000, - "cpu_model": null, - "cpus_instead_of_cores": false, - "drives": [ - { - "boot_order": 1, - "dev_channel": "0:0", - "device": "ide", - "drive": { - "resource_uri": "/api/2.0/drives/3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9/", - "uuid": "3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9" - } - } - ], - "enable_numa": false, - "hv_relaxed": false, - "hv_tsc": false, - "mem": 2147483648, - "meta": { - "description": "test1" - }, - "name": "test-1", - "nics": [ - { - "boot_order": null, - "firewall_policy": null, - "ip_v4_conf": { - "conf": "dhcp", - "ip": null - }, - "ip_v6_conf": null, - "mac": "22:22:4e:1e:e0:7e", - "model": "virtio", - "runtime": null, - "vlan": null - } - ], - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "requirements": [], - "resource_uri": "/api/2.0/servers/9414bbeb-e908-4e55-ae3f-2eb61adc50d8/", - "runtime": null, - "smp": 1, - "status": "stopped", - "tags": [], - "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8", - "vnc_password": "bar" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json deleted file mode 100644 index a04b183c2c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "action": "open_vnc", - "result": "success", - "uuid": "2e64e5e4-f31d-471a-ac1b-1ae079652e40", - "vnc_url": "vnc://direct.lvs.cloudsigma.com:41111" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json deleted file mode 100644 index e612d8ec9f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json +++ /dev/null @@ -1 +0,0 @@ -[{"error_point": null, "error_type": "permission", "error_message": "Cannot start guest in state \"started\". Guest should be in state \"stopped\""}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json deleted file mode 100644 index 1e60e5ddf8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json +++ /dev/null @@ -1 +0,0 @@ -{"action": "start", "result": "success", "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8"} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json deleted file mode 100644 index 52abcfc004..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json +++ /dev/null @@ -1 +0,0 @@ -[{"error_point": null, "error_type": "permission", "error_message": "Cannot stop guest in state \"stopped\". Guest should be in state \"['started', 'running_legacy']\""}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json deleted file mode 100644 index e35b107f5e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json +++ /dev/null @@ -1 +0,0 @@ -{"action": "stop", "result": "success", "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8"} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json deleted file mode 100644 index f57b6efe2b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "meta": { - "limit": 20, - "offset": 0, - "total_count": 5 - }, - "objects": [ - { - "amount": "1", - "auto_renew": true, - "descendants": [], - "discount_amount": null, - "discount_percent": null, - "end_time": "2014-02-20T11:12:34.930946+00:00", - "id": "7272", - "last_notification": null, - "period": "345 days, 0:00:00", - "price": "0E-20", - "remaining": "1", - "resource": "vlan", - "resource_uri": "/api/2.0/subscriptions/7272/", - "start_time": "2013-03-12T11:12:34.930946+00:00", - "status": "active", - "subscribed_object": "96537817-f4b6-496b-a861-e74192d3ccb0", - "uuid": "509f8e27-1e64-49bb-aa5a-baec074b0210" - }, - { - "amount": "1", - "auto_renew": true, - "descendants": [], - "discount_amount": null, - "discount_percent": null, - "end_time": "2014-02-20T11:12:41.837474+00:00", - "id": "7273", - "last_notification": null, - "period": "345 days, 0:00:00", - "price": "0E-20", - "remaining": "1", - "resource": "ip", - "resource_uri": "/api/2.0/subscriptions/7273/", - "start_time": "2013-03-12T11:12:41.837474+00:00", - "status": "active", - "subscribed_object": "185.12.6.183", - "uuid": "c2423c1a-8768-462c-bdc3-4ca09c1e650b" - }, - { - "amount": "17179869184", - "auto_renew": true, - "descendants": [], - "discount_amount": null, - "discount_percent": null, - "end_time": "2014-02-20T14:04:14.142181+00:00", - "id": "3985", - "last_notification": null, - "period": "365 days, 0:00:00", - "price": "0E-20", - "remaining": "17179869184", - "resource": "mem", - "resource_uri": "/api/2.0/subscriptions/3985/", - "start_time": "2013-02-20T14:04:14.142181+00:00", - "status": "active", - "subscribed_object": null, - "uuid": "9bb117d3-4bc5-4e2d-a907-b20abd48eaf9" - }, - { - "amount": "8000", - "auto_renew": true, - "descendants": [], - "discount_amount": null, - "discount_percent": null, - "end_time": "2014-02-20T14:04:29.040258+00:00", - "id": "3986", - "last_notification": null, - "period": "365 days, 0:00:00", - "price": "0E-20", - "remaining": "8000", - "resource": "cpu", - "resource_uri": "/api/2.0/subscriptions/3986/", - "start_time": "2013-02-20T14:04:29.040258+00:00", - "status": "active", - "subscribed_object": null, - "uuid": "a265c47f-1a00-4095-acfc-2193622bfbd8" - }, - { - "amount": "32212254720", - "auto_renew": true, - "descendants": [], - "discount_amount": null, - "discount_percent": null, - "end_time": "2014-02-20T14:04:44.088984+00:00", - "id": "3987", - "last_notification": null, - "period": "365 days, 0:00:00", - "price": "0E-20", - "remaining": "32212254720", - "resource": "dssd", - "resource_uri": "/api/2.0/subscriptions/3987/", - "start_time": "2013-02-20T14:04:44.088984+00:00", - "status": "active", - "subscribed_object": null, - "uuid": "8965ff95-4924-40a9-b923-a58615149732" - } - ], - "price": "0E-20" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json deleted file mode 100644 index 8b4d843c3f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "objects": [ - { - "meta": {}, - "name": "test tag 3", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/tags/c0008127-6dbf-4cf3-85f5-203f4c3967fa/", - "resources": [], - "uuid": "c0008127-6dbf-4cf3-85f5-203f4c3967fa" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json deleted file mode 100644 index d2e1f2fdc5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "objects": [ - { - "meta": {}, - "name": "test tag 3", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/tags/c0008127-6dbf-4cf3-85f5-203f4c3967fa/", - "resources": [ - { - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "res_type": "vlans", - "resource_uri": "/api/2.0/vlans/96537817-f4b6-496b-a861-e74192d3ccb0/", - "uuid": "1" - } - ], - "uuid": "c0008127-6dbf-4cf3-85f5-203f4c3967fa" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json deleted file mode 100644 index c54dd223a6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "meta": { - "limit": 20, - "offset": 0, - "total_count": 2 - }, - "objects": [ - { - "meta": {}, - "name": "test tag 2", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/tags/a010ec41-2ead-4630-a1d0-237fa77e4d4d/", - "resources": [], - "uuid": "a010ec41-2ead-4630-a1d0-237fa77e4d4d" - }, - { - "meta": {}, - "name": "test tag 1", - "owner": { - "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", - "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" - }, - "resource_uri": "/api/2.0/tags/e60bb2d2-08d4-4255-adac-5faf87efcdd2/", - "resources": [], - "uuid": "e60bb2d2-08d4-4255-adac-5faf87efcdd2" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json deleted file mode 100644 index cc794c202a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "meta": {}, - "name": "test tag 2", - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "resource_uri": "/api/2.0/tags/a010ec41-2ead-4630-a1d0-237fa77e4d4d/", - "resources": [], - "uuid": "a010ec41-2ead-4630-a1d0-237fa77e4d4d" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json deleted file mode 100644 index 28e7be6cfe..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "meta": {}, - "name": "test tag 3", - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "resource_uri": "/api/2.0/tags/900ac9c6-2f98-48a4-b406-5494b4ea4663/", - "resources": [ - { - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "res_type": "servers", - "resource_uri": "/api/2.0/servers/79f7853b-04bd-44f5-a2c2-fa56f6861994/", - "uuid": "79f7853b-04bd-44f5-a2c2-fa56f6861994" - }, - { - "owner": { - "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", - "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" - }, - "res_type": "drives", - "resource_uri": "/api/2.0/drives/8c48e0bd-e17b-49ca-8926-654107d2b7e7/", - "uuid": "8c48e0bd-e17b-49ca-8926-654107d2b7e7" - } - ], - "uuid": "900ac9c6-2f98-48a4-b406-5494b4ea4663" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json deleted file mode 100644 index 8543d1ccc2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json +++ /dev/null @@ -1 +0,0 @@ -[{"error_point": null, "error_type": "backend", "error_message": "unknown error"}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/associateIpAddress_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/associateIpAddress_default.json deleted file mode 100644 index 54aebb268e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/associateIpAddress_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "associateipaddressresponse" : {"id":"10987171-8cc9-4d0a-b98f-1698c09ddd2d","jobid":11111} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/attachVolume_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/attachVolume_default.json deleted file mode 100644 index 27535ba4af..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/attachVolume_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "attachvolumeresponse" : {"jobid":"attachvolumejob"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json deleted file mode 100644 index 92f053e4d9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "authorizesecuritygroupegressresponse" : {"jobid":17202} } - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json deleted file mode 100644 index 262ab05564..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "authorizesecuritygroupingressresponse" : {"jobid":17200} } - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createNetwork_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createNetwork_default.json deleted file mode 100644 index 9b2d904819..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createNetwork_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "createnetworkresponse" : { "network" : {"id":"a804d341-996e-4d9a-b2b0-226c648dc6e3","name":"test","displaytext":"test","broadcastdomaintype":"Lswitch","traffictype":"Guest","gateway":"10.1.1.1","netmask":"255.255.255.0","cidr":"10.1.1.0/24","zoneid":"2","zonename":"BETA-SBP-DC-1","networkofferingid":"c348cabe-0208-49e0-91ad-32b88c55fd8c","networkofferingname":"SourceNatNiciraNvpNetwork","networkofferingdisplaytext":"Offering for a Nicira Nvp isolated network with SourceNat","networkofferingconservemode":true,"networkofferingavailability":"Optional","issystem":false,"state":"Allocated","related":"a804d341-996e-4d9a-b2b0-226c648dc6e3","dns1":"8.8.8.8","dns2":"8.8.8.4","type":"Isolated","acltype":"Account","account":"rkuipers_admin","projectid":"d5f1209d-3a28-4dfb-8cc1-884e5d5e1d56","domainid":"4b6e626c-9d50-4480-bf77-daae632c7ffd","domain":"rkuipers","service":[{"name":"Firewall","capability":[{"name":"SupportedProtocols","value":"tcp,udp,icmp","canchooseservicecapability":false},{"name":"SupportedTrafficDirection","value":"ingress, egress","canchooseservicecapability":false},{"name":"MultipleIps","value":"true","canchooseservicecapability":false},{"name":"SupportedEgressProtocols","value":"tcp,udp,icmp, all","canchooseservicecapability":false},{"name":"TrafficStatistics","value":"per public ip","canchooseservicecapability":false}]},{"name":"StaticNat"},{"name":"Lb","capability":[{"name":"LbSchemes","value":"Public","canchooseservicecapability":false},{"name":"SupportedStickinessMethods","value":"[{\"methodname\":\"LbCookie\",\"paramlist\":[{\"paramname\":\"cookie-name\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"mode\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"nocache\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"indirect\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"postonly\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"domain\",\"required\":false,\"isflag\":false,\"description\":\" \"}],\"description\":\"This is loadbalancer cookie based stickiness method.\"},{\"methodname\":\"AppCookie\",\"paramlist\":[{\"paramname\":\"cookie-name\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"length\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"holdtime\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"request-learn\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"prefix\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"mode\",\"required\":false,\"isflag\":false,\"description\":\" \"}],\"description\":\"This is App session based sticky method. Define session stickiness on an existing application cookie. It can be used only for a specific http traffic\"},{\"methodname\":\"SourceBased\",\"paramlist\":[{\"paramname\":\"tablesize\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"expire\",\"required\":false,\"isflag\":false,\"description\":\" \"}],\"description\":\"This is source based Stickiness method, it can be used for any type of protocol.\"}]","canchooseservicecapability":false},{"name":"SupportedLBIsolation","value":"dedicated","canchooseservicecapability":false},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn,source","canchooseservicecapability":false},{"name":"SupportedProtocols","value":"tcp, udp","canchooseservicecapability":false}]},{"name":"SourceNat","capability":[{"name":"RedundantRouter","value":"true","canchooseservicecapability":false},{"name":"SupportedSourceNatTypes","value":"peraccount","canchooseservicecapability":false}]},{"name":"Dns","capability":[{"name":"AllowDnsSuffixModification","value":"true","canchooseservicecapability":false}]},{"name":"Connectivity"},{"name":"Vpn","capability":[{"name":"SupportedVpnTypes","value":"pptp,l2tp,ipsec","canchooseservicecapability":false},{"name":"VpnTypes","value":"removeaccessvpn","canchooseservicecapability":false}]},{"name":"Dhcp","capability":[{"name":"DhcpAccrossMultipleSubnets","value":"true","canchooseservicecapability":false}]},{"name":"UserData"},{"name":"PortForwarding"}],"networkdomain":"rkuipers.local","physicalnetworkid":"e48527a6-6882-4c5f-bce9-c02ecd5ef8c1","restartrequired":false,"specifyipranges":false,"vpcid":"22e8388c-21bf-4b84-8f20-e92a7f550898","canusefordeploy":true,"ispersistent":false,"tags":[],"displaynetwork":true} } } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createPortForwardingRule_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createPortForwardingRule_default.json deleted file mode 100644 index 9e4a45a86b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createPortForwardingRule_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "createportforwardingruleresponse" : {"id":"bc7ea3ee-a2c3-4b86-a53f-01bdaa1b2e32","jobid":"11113"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json deleted file mode 100644 index a4892a70a1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "createsshkeypairresponse" : { "keypair" : {"name":"test-keypair","fingerprint":"51:9f:81:30:ec:82:0c:e5:8c:81:ac:14:27:d0:e5:e2","privatekey":"-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDMaSZY4v228AWWcXYLoojgaZ+K8SbuI8YoPDEi9UWcww5mWSTx\nVl6Ksb8YPFxL6+3/unlfr4zK1LksxgN8XRuZr+YBFGphUB6a5EcyshkXi3mfAE7d\n6a26ah6ySXFK9GmZoXcJqQ1xLC9rKGPL7tWgHmbX1lCbN6QinV0mZVEHNwIDAQAB\nAoGACXQngN7mqwpIx99xfTJEMFTSOyPSEBt5c6zs/NfpI0nmJZej3MGI19NGqkFI\nZ35+4F/ocyN0WIEkG00BJkRMHWdPNd+YnVSuVgEyGCD8hDvBbUEQrmdZ0VfQt+2q\nd52g573s6D6Skk/SZHGi3yHca4H52c3EpLJzThxUmJSSqmECQQD0loEIiQzQaap3\n/Gce7nZeLCSNXf0Q5aKFQv/X22srw6YvJ9/25cLahiFtQUadId9VUXSYTgEKX0ST\nB2CZ4UJxAkEA1fK/PT+YIHaiQIiCK/xTnoIuTvdXmH0IozolRxGAKpQZNvaMpKgn\nvXU84/yztekEPG0pKmCm7CZUZoGdfiJoJwJALwUsAy8NtpdJvU1ZqbmgKdSEpmS2\nPORYjRPnSWEWRlCThyc8SCO9hPMaQ/2zjIuxep5xMsJ0MsFD1pwpdwu2EQJBAMrG\nEZ7ZQTOzfMAxIT7THeWjeIR7RNhP2PnrSB19Zr30M5m2P0Jn5ZJZJWbnwOPuf4dN\n5rA1fr9e7KtiuYQs1A0CQQCT06qHdHaQr78A6YTEbDVr0M57qVrdsm5xyXzCmpMy\n9LxXAACghjHbjF//FEOjNG21IutbCg6cNIRz5EM8+MD+\n-----END RSA PRIVATE KEY-----\n"} } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json deleted file mode 100644 index 0d3cdaf5f0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json +++ /dev/null @@ -1 +0,0 @@ -{"createsecuritygroupresponse":{"securitygroup":{"account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","id":"895f9e41-4d89-468e-9b69-19a8f0d3a889","domain":"runseb@gmail.com","name":"MySG"}}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createTags_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createTags_default.json deleted file mode 100644 index aeeb1e0c2a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createTags_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "createtagsresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"createtagsjob"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createVolume_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createVolume_default.json deleted file mode 100644 index dc51b35ef7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createVolume_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "createvolumeresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"createvolumejob"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createVolume_withcustomdisksize.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createVolume_withcustomdisksize.json deleted file mode 100644 index dc51b35ef7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/createVolume_withcustomdisksize.json +++ /dev/null @@ -1 +0,0 @@ -{ "createvolumeresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"createvolumejob"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteNetwork_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteNetwork_default.json deleted file mode 100644 index ad161b20ac..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteNetwork_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "deletenetworkresponse" : {"jobid":"deleteNetwork"} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deletePortForwardingRule_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deletePortForwardingRule_default.json deleted file mode 100644 index f45af81796..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deletePortForwardingRule_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "deleteportforwardingruleresponse" : {"jobid":"11114"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json deleted file mode 100644 index 9e2c854042..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "deletesshkeypairresponse" : { "success" : "true"} } - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json deleted file mode 100644 index 19ba7237ad..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "deletesecuritygroupresponse" : { "success" : "true"} } - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteTags_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteTags_default.json deleted file mode 100644 index e136a00272..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteTags_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "deletetagsresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"deletetagsjob"} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteVolume_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteVolume_default.json deleted file mode 100644 index 3786dabc51..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deleteVolume_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "deletevolumeresponse" : { "success" : "true"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json deleted file mode 100644 index 5fbec216b1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"jobid":17164,"id":2602} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json deleted file mode 100644 index 2162fe1a0a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"errorcode" : 431, "errortext" : "Unable to find service offering: 104"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json deleted file mode 100644 index 05790d2f42..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"jobid":17177,"id":2602} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploykeyname.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploykeyname.json deleted file mode 100644 index 979df700fa..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploykeyname.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"id":"fc4fd31a","jobid":"11116"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json deleted file mode 100644 index bf7b25e562..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"jobid":11117,"id":"19253fbf-abb7-4013-a8a1-97df3b93f206"} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploysecuritygroup.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploysecuritygroup.json deleted file mode 100644 index 524cdb3d79..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploysecuritygroup.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"id":"fc4fd31a-16d3-49db-814a-56b39b9ef986","jobid":"11115"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json deleted file mode 100644 index dfd664f9ea..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "destroyvirtualmachineresponse" : {"jobid":17166} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/detachVolume_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/detachVolume_default.json deleted file mode 100644 index 6266238e61..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/detachVolume_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "detachvolumeresponse" : {"jobid":"detachvolumejob"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/disassociateIpAddress_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/disassociateIpAddress_default.json deleted file mode 100644 index 334d4795cb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/disassociateIpAddress_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "disassociateipaddressresponse" : {"jobid":"11112"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/dummy_rsa.pub b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/dummy_rsa.pub deleted file mode 100644 index 1d18ad6e8b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/dummy_rsa.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCw3Fw6AdX+3Ul3lRJIPE0Hd5oBaHnCVB1Wl325FVeJZeQiKF9Z0sw+/StWuo2ZA5ra6/A8X7tITiO7goUncdd7xLT3r3UCwKGNZXrTn8e2Kutqd9S7EN+SUh63kZmcEQsFCuC3hg0O8TzG5ROQxukYc+7PAvcYk7+KV8r3B5eh2lvp5tHTpCX/63pm4zHm5rnE38DnESeh4Dh2R8hkhnoxo9ixQCdETbufUTo5abCkKbcf8/1+qA5A13uXqBsx/KtmZX0SvyQW3hKFPGXSaYxAE/u+DZU8Myr/dDKLrGPYt6e5CSXlQLFcnz99akuVdqOP9ygPGcgwlAajOZgt+Vwn sebgoa@sebmini.local diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_default.json deleted file mode 100644 index f279b95536..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listdiskofferingsresponse" : { "count":1 ,"diskoffering" : [ {"id":"6345e3b7-227e-4209-8f8c-1f94219696e6","name":"Disk offer 1","displaytext":"Disk offer 1 display name","disksize":10,"created":"2012-04-24T16:35:55+0200","iscustomized":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withcustomdisksize.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withcustomdisksize.json deleted file mode 100644 index f4660e0c3c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withcustomdisksize.json +++ /dev/null @@ -1 +0,0 @@ -{ "listdiskofferingsresponse" : { "count":1 ,"diskoffering" : [ {"id":"6345e3b7-227e-4209-8f8c-1f94219696e6","name":"Disk offer 1","displaytext":"Disk offer 1 display name","disksize":10,"created":"2012-04-24T16:35:55+0200","iscustomized":true} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworkOfferings_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworkOfferings_default.json deleted file mode 100644 index 35d8bcc658..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworkOfferings_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listnetworkofferingsresponse" : { "count":2 ,"networkoffering" : [ {"id":"c348cabe-0208-49e0-91ad-32b88c55fd8c","name":"SourceNatNiciraNvpNetwork","displaytext":"Offering for a Nicira Nvp isolated network with SourceNat","tags":"BETA-SBP-DC-1-pSTT","traffictype":"Guest","isdefault":true,"specifyvlan":false,"conservemode":true,"specifyipranges":false,"availability":"Optional","networkrate":-1,"state":"Enabled","guestiptype":"Isolated","serviceofferingid":"01f93707-3a35-44a6-84e9-ea767287a6b2","service":[{"name":"Firewall","provider":[{"name":"VirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"ElasticIp","value":"false","canchooseservicecapability":false},{"name":"AssociatePublicIP","value":"false","canchooseservicecapability":false}]},{"name":"Lb","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedLBIsolation","value":"dedicated","canchooseservicecapability":false},{"name":"ElasticLb","value":"false","canchooseservicecapability":false},{"name":"InlineMode","value":"false","canchooseservicecapability":false}]},{"name":"SourceNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedSourceNatTypes","value":"peraccount","canchooseservicecapability":false},{"name":"RedundantRouter","value":"false","canchooseservicecapability":false}]},{"name":"Dns","provider":[{"name":"VirtualRouter"}]},{"name":"Connectivity","provider":[{"name":"NiciraNvp"}]},{"name":"Vpn","provider":[{"name":"VirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VirtualRouter"}]},{"name":"UserData","provider":[{"name":"VirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VirtualRouter"}]}],"forvpc":false,"ispersistent":false,"egressdefaultpolicy":false}, {"id":"7c09e208-2af5-43d6-9f0b-53868ef788ea","name":"OAT offering for OAT purposes","displaytext":"OAT offering for OAT purposes","tags":"BETA-SBP-DC-1-pSTT","traffictype":"Guest","isdefault":false,"specifyvlan":false,"conservemode":true,"specifyipranges":false,"availability":"Optional","networkrate":-1,"state":"Enabled","guestiptype":"Isolated","serviceofferingid":"01f93707-3a35-44a6-84e9-ea767287a6b2","service":[{"name":"Firewall","provider":[{"name":"VirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"ElasticIp","value":"false","canchooseservicecapability":false},{"name":"AssociatePublicIP","value":"false","canchooseservicecapability":false}]},{"name":"Lb","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedLBIsolation","value":"dedicated","canchooseservicecapability":false},{"name":"ElasticLb","value":"false","canchooseservicecapability":false},{"name":"InlineMode","value":"false","canchooseservicecapability":false}]},{"name":"SourceNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedSourceNatTypes","value":"peraccount","canchooseservicecapability":false},{"name":"RedundantRouter","value":"false","canchooseservicecapability":false}]},{"name":"Dns","provider":[{"name":"VirtualRouter"}]},{"name":"Connectivity","provider":[{"name":"NiciraNvp"}]},{"name":"Vpn","provider":[{"name":"VirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VirtualRouter"}]},{"name":"UserData","provider":[{"name":"VirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VirtualRouter"}]}],"forvpc":false,"ispersistent":false,"egressdefaultpolicy":true,"maxconnections":4096} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_default.json deleted file mode 100644 index 7f696f01e4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listnetworksresponse" : {"count": 1, "network": [{"domain": "ROOT", "acltype": "Domain", "specifyipranges": true, "related": "00304a04-c7ea-4e77-a786-18bc64347bf7", "zoneid": "1128bd56-b4d9-4ac6-a7b9-c715b187ce11", "domainid": "4a8857b8-7235-4e31-a7ef-b8b44d180850", "displaytext": "guestNetworkForBasicZone", "id": "00304a04-c7ea-4e77-a786-18bc64347bf7", "canusefordeploy": true, "physicalnetworkid": "07f747f5-b445-487f-b2d7-81a5a512989e", "networkdomain": "cs1cloud.internal", "service": [{"name": "SecurityGroup"}, {"name": "UserData"}, {"name": "Dhcp"}], "state": "Setup", "type": "Shared", "zonename": "CH-GV2", "networkofferingavailability": "Optional", "networkofferingid": "45964a3a-8a1c-4438-a377-0ff1e264047a", "tags": [], "networkofferingdisplaytext": "Exoscale Offering for Shared Security group enabled networks", "subdomainaccess": true, "traffictype": "Guest", "restartrequired": false, "broadcastdomaintype": "Vlan", "name": "guestNetworkForBasicZone", "dns2": "80.245.17.230", "dns1": "80.245.17.229", "networkofferingname": "ExoscaleSharedNetworkOfferingWithSGService", "issystem": false}]} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail.json deleted file mode 100644 index 270134783f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail.json +++ /dev/null @@ -1 +0,0 @@ -{ "listnetworksresponse" : { "network" : [ {"id":860,"name":"Virtual Network","displaytext":"A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.","broadcastdomaintype":"Vlan","traffictype":"Guest","zoneid":1,"networkofferingid":6,"networkofferingname":"DefaultVirtualizedNetworkOffering","networkofferingdisplaytext":"Virtual Vlan","networkofferingavailability":"Required","isshared":false,"issystem":false,"state":"Implemented","related":860,"broadcasturi":"vlan://1459","dns1":"1.1.1.1","dns2":"1.1.1.2","type":"Virtual","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","isdefault":true,"service":[{"name":"Gateway"},{"name":"Firewall","capability":[{"name":"MultipleIps","value":"true"},{"name":"TrafficStatistics","value":"per public ip"},{"name":"StaticNat","value":"true"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedSourceNatTypes","value":"per account"}]},{"name":"UserData"},{"name":"Dns"},{"name":"Dhcp"},{"name":"Lb","capability":[{"name":"TrafficStatistics","value":"per public ip"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn"}]}],"networkdomain":"cs363local","securitygroupenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json deleted file mode 100644 index 270134783f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json +++ /dev/null @@ -1 +0,0 @@ -{ "listnetworksresponse" : { "network" : [ {"id":860,"name":"Virtual Network","displaytext":"A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.","broadcastdomaintype":"Vlan","traffictype":"Guest","zoneid":1,"networkofferingid":6,"networkofferingname":"DefaultVirtualizedNetworkOffering","networkofferingdisplaytext":"Virtual Vlan","networkofferingavailability":"Required","isshared":false,"issystem":false,"state":"Implemented","related":860,"broadcasturi":"vlan://1459","dns1":"1.1.1.1","dns2":"1.1.1.2","type":"Virtual","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","isdefault":true,"service":[{"name":"Gateway"},{"name":"Firewall","capability":[{"name":"MultipleIps","value":"true"},{"name":"TrafficStatistics","value":"per public ip"},{"name":"StaticNat","value":"true"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedSourceNatTypes","value":"per account"}]},{"name":"UserData"},{"name":"Dns"},{"name":"Dhcp"},{"name":"Lb","capability":[{"name":"TrafficStatistics","value":"per public ip"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn"}]}],"networkdomain":"cs363local","securitygroupenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listPortForwardingRules_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listPortForwardingRules_default.json deleted file mode 100644 index d6aae0f03e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listPortForwardingRules_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listportforwardingrulesresponse" : { "count":1 ,"portforwardingrule" : [ {"id":"bc7ea3ee-a2c3-4b86-a53f-01bdaa1b2e32","privateport":"33","privateendport":"34","protocol":"tcp","publicport":"33","publicendport":"34","virtualmachineid":"2600","virtualmachinename":"testlib","virtualmachinedisplayname":"testlib","ipaddressid":"96dac96f-0b5d-42c1-b5de-8a97f3e34c43","ipaddress":"1.1.1.116","state":"Active","cidrlist":"","tags":[]} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json deleted file mode 100644 index b100edf756..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json +++ /dev/null @@ -1,49 +0,0 @@ -{ "listprojectsresponse": { - "count": 1, - "project": [ - { - "id": "e7ce14a8-abb7-48b9-931f-5f426febed6d", - "name": "ExampleProjectName", - "displaytext": "ExampleProject", - "account": "CB0512", - "cpuavailable": 18, - "cpulimit": 32, - "cputotal": 14, - "domain": "ExampleDomain", - "domainid": "dc0314d4-09aa-4e8f-8a54-419ecf344635", - "ipavailable": 8, - "iplimit": 8, - "iptotal": 0, - "memoryavailable": 72000, - "memorylimit": 128000, - "memorytotal": 56000, - "networkavailable": 0, - "networklimit": 0, - "networktotal": 0, - "primarystorageavailable": 1204, - "primarystoragelimit": 1600, - "primarystoragetotal": 396, - "secondarystorageavailable": 3817, - "secondarystoragelimit": 4000, - "secondarystoragetotal": 183, - "snapshotavailable": 17, - "snapshotlimit": 20, - "snapshottotal": 3, - "state": "Active", - "tags": [], - "templateavailable": 17, - "templatelimit": 20, - "templatetotal": 3, - "vmavailable": 1, - "vmlimit": 8, - "vmrunning": 7, - "vmtotal": 7, - "volumeavailable": 1, - "volumelimit": 16, - "volumetotal": 15, - "vpcavailable": 20, - "vpclimit": 0, - "vpctotal": 0 - } - ] -} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json deleted file mode 100644 index ca80e129a1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listpublicipaddressesresponse" : { "publicipaddress" : [ {"id":34000,"ipaddress":"1.1.1.116","virtualmachineid":"2600","allocated":"2011-06-23T05:20:39+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33999,"ipaddress":"1.1.1.48","allocated":"2011-06-23T05:20:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33998,"ipaddress":"1.1.1.47","allocated":"2011-06-23T05:20:30+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33970,"ipaddress":"1.1.1.19","allocated":"2011-06-20T04:08:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":true,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listResourceLimits_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listResourceLimits_default.json deleted file mode 100644 index 2f0dd8733f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listResourceLimits_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listresourcelimitsresponse" : { "count":8 ,"resourcelimit" : [ {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"0","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"1","max":-1}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"2","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"3","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"4","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"5","max":-1}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"6","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"7","max":20} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json deleted file mode 100644 index d7728aaa18..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json +++ /dev/null @@ -1 +0,0 @@ -{"listsshkeypairsresponse":{"count":1,"sshkeypair":[{"name":"cs-keypair","fingerprint":"00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"}]}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one.json deleted file mode 100644 index d7728aaa18..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one.json +++ /dev/null @@ -1 +0,0 @@ -{"listsshkeypairsresponse":{"count":1,"sshkeypair":[{"name":"cs-keypair","fingerprint":"00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"}]}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one_doesnt_exist.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one_doesnt_exist.json deleted file mode 100644 index dc7b1c9196..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one_doesnt_exist.json +++ /dev/null @@ -1 +0,0 @@ -{ "listsshkeypairsresponse" : { } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_no_keys.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_no_keys.json deleted file mode 100644 index ccc9283c40..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_no_keys.json +++ /dev/null @@ -1 +0,0 @@ -{"listsshkeypairsresponse":{}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json deleted file mode 100644 index fcc25fa9fd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listsecuritygroupsresponse" : { "count":2 ,"securitygroup" : [ {"id":"ebfa2339","name":"default","description":"Default Security Group","account":"gmail.com","domainid":"ab53d864","domain":"gmail.com","ingressrule":[{"ruleid":"b83428c0-7f4c-44d1-bc96-4e1720168fdf","protocol":"tcp","startport":22,"endport":22,"cidr":"0.0.0.0/0"},{"ruleid":"bcb528e7-1a77-48f5-9bac-65cdcbc760e8","protocol":"tcp","startport":9200,"endport":9200,"cidr":"0.0.0.0/0"},{"ruleid":"80cca966-aa85-4bf0-9cb3-6b318b5d577f","protocol":"tcp","startport":9200,"endport":9300,"securitygroupname":"default","account":"runseb@gmail.com"},{"ruleid":"04f1264d-d0af-4c51-bcf9-4776166bba7d","protocol":"tcp","startport":8080,"endport":8080,"cidr":"0.0.0.0/0"}],"egressrule":[],"tags":[]}, {"id":"efae588b-5d74-4d0f-aeb8-96250d45fdee","name":"mongodb","description":"A SG for replica sets","account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","domain":"runseb@gmail.com","ingressrule":[{"ruleid":"ed30a29e-4456-4df6-ba26-26b350da0bd9","protocol":"tcp","startport":27017,"endport":27017,"securitygroupname":"default","account":"runseb@gmail.com"},{"ruleid":"4b5722f0-fc04-4263-93e7-c93564e5619c","protocol":"tcp","startport":22,"endport":22,"cidr":"0.0.0.0/0"},{"ruleid":"2430f851-189f-4d10-9bcd-b2276bc7d6a3","protocol":"tcp","startport":27017,"endport":27017,"cidr":"0.0.0.0/0"}],"egressrule":[],"tags":[]} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_no_groups.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_no_groups.json deleted file mode 100644 index d3c6a0147a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_no_groups.json +++ /dev/null @@ -1 +0,0 @@ -{ "listsecuritygroupsresponse" : {} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_default.json deleted file mode 100644 index a56d8906ba..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listserviceofferingsresponse" : { "serviceoffering" : [ {"id":105,"name":"Compute Micro PRD","displaytext":"1CPU, 384MB, 80GB HDD","cpunumber":1,"cpuspeed":1200,"memory":384,"created":"2011-06-01T03:38:05+0000","storagetype":"shared","offerha":false,"domainid":14,"domain":"AA000062"}, {"id":70,"name":"Compute XLarge PRD","displaytext":"8CPU, 13.6GB RAM, 160GB Storage","cpunumber":8,"cpuspeed":1200,"memory":13928,"created":"2011-02-08T07:06:19+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":69,"name":"Compute Large PRD","displaytext":"4CPU, 6.8GB RAM, 160GB Storage","cpunumber":4,"cpuspeed":1200,"memory":6964,"created":"2011-02-08T07:05:47+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":68,"name":"Compute Medium PRD","displaytext":"2CPU, 3.4GB RAM, 160GB Storage","cpunumber":2,"cpuspeed":1200,"memory":3484,"created":"2011-02-08T07:05:03+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":67,"name":"Compute Small PRD","displaytext":"1CPU, 1.7GB RAM, 160GB Storage","cpunumber":1,"cpuspeed":1200,"memory":1744,"created":"2011-02-08T07:03:44+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listTemplates_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listTemplates_default.json deleted file mode 100644 index b7f99007ec..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listTemplates_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listtemplatesresponse" : { "template" : [ {"id":576,"name":"ESX[beta] Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","displaytext":"ESX[beta] Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","ispublic":true,"created":"2011-06-01T01:25:12+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":126,"ostypename":"Ubuntu 10.04 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":702743552,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":443,"name":"XEN Basic Windows Svr 2008 R2 x64 R2.1","displaytext":"XEN Basic Windows Svr 2008 R2 x64 R2.1","ispublic":true,"created":"2011-03-25T01:29:46+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":54,"ostypename":"Windows Server 2008 R2 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":474,"name":"XEN Basic Windows Svr 2003 SP2 STD","displaytext":"XEN Basic Windows Svr 2003 SP2 STD","ispublic":true,"created":"2011-04-07T10:38:45+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":89,"ostypename":"Windows Server 2003 Standard Edition(32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":444,"name":"ESX[beta] Windows 2003 x32 R2.0","displaytext":"ESX[beta] Windows 2003 x32 R2.0","ispublic":true,"created":"2011-03-25T01:34:00+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":89,"ostypename":"Windows Server 2003 Standard Edition(32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":876909056,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":447,"name":"ESX[beta] Windows 2008 x32 R2.0","displaytext":"ESX[beta] Windows 2008 x32 R2.0","ispublic":true,"created":"2011-03-25T01:45:23+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":52,"ostypename":"Windows Server 2008 (32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":3391547904,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":462,"name":"ESX[beta] Centos 5.5 x64 R2.0","displaytext":"ESX[beta] Centos 5.5 x64 R2.0","ispublic":true,"created":"2011-03-28T05:06:36+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":2263178240,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":425,"name":"XEN Windows 2008 x32 R2.0","displaytext":"XEN Windows 2008 x32 R2.0","ispublic":true,"created":"2011-03-22T03:22:21+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":52,"ostypename":"Windows Server 2008 (32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":461,"name":"ESX[beta] Basic Windows 2008 R2 x64","displaytext":"ESX[beta] Basic Windows 2008 R2 x64","ispublic":true,"created":"2011-03-26T22:48:48+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":54,"ostypename":"Windows Server 2008 R2 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":3230146048,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":575,"name":"Xen Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","displaytext":"Xen Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","ispublic":true,"created":"2011-06-01T01:06:21+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":85899345920,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":481,"name":"XEN Centos 5.4 x64 R2.0","displaytext":"XEN Centos 5.4 x64 R2.0","ispublic":true,"created":"2011-04-14T01:43:49+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171966464000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":421,"name":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","displaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","ispublic":true,"created":"2011-03-22T02:54:06+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":167772160000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":423,"name":"XEN Basic Centos 5.5 x64 PV r2.2","displaytext":"XEN Basic Centos 5.5 x64 PV r2.2","ispublic":true,"created":"2011-03-22T02:59:31+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":167772160000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":422,"name":"XEN OpenSUSE x64 11.4 R2.0","displaytext":"XEN OpenSUSE x64 11.4 R2.0","ispublic":true,"created":"2011-03-22T02:58:25+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171966464000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listTemplates_notemplates.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listTemplates_notemplates.json deleted file mode 100644 index 64a1a75cac..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listTemplates_notemplates.json +++ /dev/null @@ -1 +0,0 @@ -{ "listtemplatesresponse" : {} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listVirtualMachines_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listVirtualMachines_default.json deleted file mode 100644 index d55c436b2e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listVirtualMachines_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listvirtualmachinesresponse" : { "virtualmachine" : [ {"id":2600,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:06:42+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"1.78%","networkkbsread":2,"networkkbswrite":2,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3891,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.116","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}, {"id":2601,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:09:44+0000","state":"Starting","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"jobid":17147,"jobstatus":0,"nic":[{"id":3892,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.203","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listVolumes_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listVolumes_default.json deleted file mode 100644 index 5fa8fd171b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listVolumes_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listvolumesresponse" : { "count":1 ,"volume" : [ {"id":"fe1ada16-57a0-40ae-b577-01a153690fb4","name":"ROOT-69942","zoneid":"7dbc4787-ec2f-498d-95f0-848c8c81e5da","zonename":"MTV-Zone1","type":"ROOT","deviceid":0,"virtualmachineid":"3239ade9-fd25-405c-8eda-59f0313a3fb0","vmname":"apb-cent32-bld","vmdisplayname":"apb-cent32-bld","vmstate":"Stopped","size":139264,"created":"2013-04-16T16:25:57-0700","state":"Ready","account":"andrew","domainid":"41a4917b-7952-499d-ba7f-4c57464d3dc8","domain":"ROOT","storagetype":"local","hypervisor":"KVM","storage":"c2422.halxg.cloudera.com","destroyed":false,"serviceofferingid":"7cc4f8c3-7c56-4155-9916-9f42072ea712","serviceofferingname":"Tiny","serviceofferingdisplaytext":"Tiny (1 core, 1GB RAM)","isextractable":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_default.json deleted file mode 100644 index 0316936e45..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail.json deleted file mode 100644 index 0316936e45..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail.json +++ /dev/null @@ -1 +0,0 @@ -{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail2.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail2.json deleted file mode 100644 index 0316936e45..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail2.json +++ /dev/null @@ -1 +0,0 @@ -{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_withcustomdisksize.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_withcustomdisksize.json deleted file mode 100644 index 0316936e45..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/listZones_withcustomdisksize.json +++ /dev/null @@ -1 +0,0 @@ -{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11111.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11111.json deleted file mode 100644 index bb31181b24..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11111.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"cb13887","userid":"11110","cmd":"org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"ipaddress":{"id":"10987171-8cc9-4d0a-b98f-1698c09ddd2d","ipaddress":"7.5.6.1","allocated":"2013-09-05T06:19:59-0400","zoneid":"d06193b2-7980-4ad1-b5d8-7b2f2eda63c3","zonename":"SanJose","issourcenat":false,"account":"admin","domainid":"0ce03bf9-540d-47da-b3f3-75df64fddf2f","domain":"ROOT","forvirtualnetwork":true,"vlanid":"0cf2e30a-1d75-4108-8a50-259e0590faf9","vlanname":"67","isstaticnat":false,"issystem":false,"associatednetworkid":"edd15baf-b5af-4805-8484-3478ad236372","associatednetworkname":"defaultown","networkid":"9a3b3ed4-40f4-4def-aecb-8b9f54536693","state":"Allocating","physicalnetworkid":"3a997df4-ea89-4b53-b523-010857a9087b","tags":[]}},"created":"2013-09-05T06:19:59-0400","jobid":"11111"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11112.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11112.json deleted file mode 100644 index ed79afadbb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11112.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"cb13887c-7c6a-464d-aa8f-c6971f9dd458","userid":"11110e27-5a51-4109-9598-7df34141761a","cmd":"org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2013-09-05T06:36:44-0400","jobid":"11112"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11113.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11113.json deleted file mode 100644 index 9ca41c9197..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11113.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"cb13887c","userid":"11110","cmd":"org.apache.cloudstack.api.command.user.firewall.CreatePortForwardingRuleCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"portforwardingrule":{"id":"bc7ea3ee-a2c3-4b86-a53f-01bdaa1b2e32","privateport":"33","privateendport":"33","protocol":"tcp","publicport":"33","publicendport":"33","virtualmachineid":"8879e159-d4a6-4a1d-bc75-074c097bef2a","virtualmachinename":"testlib","virtualmachinedisplayname":"libcloud","ipaddressid":"96dac96f-0b5d-42c1-b5de-8a97f3e34c43","ipaddress":"7.5.1.7","state":"Active","cidrlist":"","tags":[]}},"created":"2013-09-05T07:33:43-0400","jobid":"11113"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11114.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11114.json deleted file mode 100644 index 5d501ebd9d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11114.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"cb13887c-7c6a-464d-aa8f-c6971f9dd458","userid":"11110e27-5a51-4109-9598-7df34141761a","cmd":"org.apache.cloudstack.api.command.user.firewall.DeletePortForwardingRuleCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2013-09-05T09:09:01-0400","jobid":"11114"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11115.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11115.json deleted file mode 100644 index a8f8b53cc7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11115.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"b8c0baab","userid":"968f6b4e","cmd":"com.cloud.api.commands.DeployVMCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":"fc4fd31a-16d3-49db-814a-56b39b9ef986","name":"test","displayname":"test","account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","domain":"runseb@gmail.com","created":"2013-09-05T15:45:11+0200","state":"Running","haenable":false,"zoneid":"1128bd56-b4d9-4ac6-a7b9-c715b187ce11","zonename":"CH-GV2","templateid":"a17b40d6-83e4-4f2a-9ef0-dce6af575789","templatename":"Linux Ubuntu 12.04 LTS 64-bit","templatedisplaytext":"Linux Ubuntu 12.04 LTS 64-bit 10GB Disk","passwordenabled":true,"serviceofferingid":"71004023-bb72-4a97-b1e9-bc66dfce9470","serviceofferingname":"Micro","cpunumber":1,"cpuspeed":2198,"memory":512,"guestosid":"113038d0-a8cd-4d20-92be-ea313f87c3ac","rootdeviceid":0,"rootdevicetype":"Filesystem","securitygroup":[{"id":"efae588b-5d74-4d0f-aeb8-96250d45fdee","name":"default","description":"A SG for replica sets"},{"id":"ebfa2339-e9ae-4dcb-b73c-a76cd3fce39e","name":"mongodb","description":"Default Security Group"}],"password":"iQ7hbmrjw","nic":[{"id":"09a806c7-ab1e-452d-a779-dda974ea7e41","networkid":"00304a04-c7ea-4e77-a786-18bc64347bf7","netmask":"255.255.254.0","gateway":"185.19.28.1","ipaddress":"185.19.28.98","traffictype":"Guest","type":"Shared","isdefault":true,"macaddress":"06:54:5a:00:00:95"}],"hypervisor":"KVM","tags":[]}},"created":"2013-09-05T15:45:11+0200","jobid":"10046ad6-917f-4c25-add3-e08cd98e0e87"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11116.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11116.json deleted file mode 100644 index 40358b10c1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11116.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"b8c0baab-18a1-44c0-ab67-e24049212925","userid":"968f6b4e-b382-4802-afea-dd731d4cf9b9","cmd":"com.cloud.api.commands.DeployVMCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":"94fa7e76-9a39-4e5a-8f84-40e496650780","name":"test","displayname":"test","account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","domain":"runseb@gmail.com","created":"2012-09-05T16:05:50+0200","state":"Running","haenable":false,"zoneid":"1128bd56-b4d9-4ac6-a7b9-c715b187ce11","zonename":"CH-GV2","templateid":"a17b40d6-83e4-4f2a-9ef0-dce6af575789","templatename":"Linux Ubuntu 12.04 LTS 64-bit","templatedisplaytext":"Linux Ubuntu 12.04 LTS 64-bit 10GB Disk","passwordenabled":true,"serviceofferingid":"71004023-bb72-4a97-b1e9-bc66dfce9470","serviceofferingname":"Micro","cpunumber":1,"cpuspeed":2198,"memory":512,"guestosid":"113038d0-a8cd-4d20-92be-ea313f87c3ac","rootdeviceid":0,"rootdevicetype":"Filesystem","securitygroup":[{"id":"ebfa2339-e9ae-4dcb-b73c-a76cd3fce39e","name":"default","description":"Default Security Group"}],"password":"zU3gwurmi","nic":[{"id":"2bd513cf-7453-4594-87c2-2d8b17ae8fad","networkid":"00304a04-c7ea-4e77-a786-18bc64347bf7","netmask":"255.255.254.0","gateway":"185.19.28.1","ipaddress":"185.19.28.96","traffictype":"Guest","type":"Shared","isdefault":true,"macaddress":"06:84:e0:00:00:93"}],"hypervisor":"KVM","tags":[],"keypair":"foobar"}},"created":"2013-09-05T16:05:51+0200","jobid":"a0c97348-4d21-43ba-879e-9d8340ec0805"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json deleted file mode 100644 index 8f7c76ad61..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json +++ /dev/null @@ -1,63 +0,0 @@ -{ "queryasyncjobresultresponse": { - "accountid": "86d47ca2-726b-4b85-a18a-77d6b0d79829", - "userid": "20cd68f5-0633-48a5-826e-e4e2a00dd6b8", - "cmd": "org.apache.cloudstack.api.command.user.vm.DeployVMCmd", - "jobstatus": 1, - "jobprocstatus": 0, - "jobresultcode": 0, - "jobresulttype": "object", - "jobresult": { - "virtualmachine": { - "id": "19253fbf-abb7-4013-a8a1-97df3b93f206", - "name": "TestNode", - "projectid": "b90442d1-079b-4066-ab7d-41f8f3a5078b", - "project": "Test Project", - "domainid": "dc0314d4-09aa-4e8f-8a54-419ecf344635", - "domain": "Test Domain", - "created": "2014-03-06T15:39:44-0600", - "state": "Running", - "haenable": false, - "zoneid": "d630b15a-a9e1-4641-bee8-355005b7a14d", - "zonename": "TestZone", - "templateid": "a032e8a0-3411-48b7-9e78-ff66823e6561", - "templatename": "OL-6.3.1-64-13.11.01", - "templatedisplaytext": "OL-6.3.1-64-13.11.01", - "passwordenabled": true, - "serviceofferingid": "519f8667-26d0-40e5-a1cd-da04be1fd9b5", - "serviceofferingname": "Test Service Offering", - "cpunumber": 1, - "cpuspeed": 2000, - "memory": 2000, - "guestosid": "b8506c91-6d8e-4086-8659-f6296a7b71ac", - "rootdeviceid": 0, - "rootdevicetype": "ROOT", - "securitygroup": [], - "password": "mW6crjxag", - "nic": [ - { - "id": "1c144283-979a-4359-b695-3334dc403457", - "networkid": "1bf4acce-19a5-4830-ab1d-444f8acb9986", - "networkname": "Public", - "netmask": "255.255.252.0", - "gateway": "10.1.2.2", - "ipaddress": "10.2.2.8", - "isolationuri": "vlan://2950", - "broadcasturi": "vlan://2950", - "traffictype": "Guest", - "type": "Shared", - "isdefault": true, - "macaddress": "06:ef:30:00:04:22" - } - ], - "hypervisor": "VMware", - "tags": [], - "affinitygroup": [], - "displayvm": true, - "isdynamicallyscalable": false, - "jobid": "e23b9f0c-b7ae-4ffe-aea0-c9cf436cc315", - "jobstatus": 0 - } - }, - "created": "2014-03-06T15:39:44-0600", - "jobid": "e23b9f0c-b7ae-4ffe-aea0-c9cf436cc315" -} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json deleted file mode 100644 index 33dc74662b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17164,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"192.168.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json deleted file mode 100644 index 694d7d032e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17165,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json deleted file mode 100644 index 5245af2d3d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Destroyed","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json deleted file mode 100644 index 7b743c54c8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17177,"jobstatus":2} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json deleted file mode 100644 index 43ca40d047..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Starting","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json deleted file mode 100644 index 485175acea..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Stopped","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json deleted file mode 100644 index d028ab4949..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json +++ /dev/null @@ -1 +0,0 @@ -{"queryasyncjobresultresponse":{"jobid":17200,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"securitygroup":[{"egressrule":[],"account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","name":"MySG","domain":"runseb@gmail.com","ingressrule":[{"startport":22,"cidr":"0.0.0.0/0","protocol":"tcp","endport":22,"ruleid":"7df1edc8-6e56-48d7-b816-39377506d787"}],"id":"fa334c44-21c6-4809-ad7d-287bbb23c29b"}]}}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17201.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17201.json deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17202.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17202.json deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17203.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17203.json deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_attachvolumejob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_attachvolumejob.json deleted file mode 100644 index cd5278f8e0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_attachvolumejob.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.AttachVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","deviceid":5,"virtualmachineid":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmname":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmdisplayname":"gre-kickstart","vmstate":"Running","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Ready","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"KVM","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering 1","diskofferingdisplaytext":"Disk offering 1 display name","storage":"Shared Storage CL01","attached":"2012-06-05T09:17:38+0200","destroyed":false,"isextractable":false}},"created":"2012-06-05T09:17:38+0200","jobid":"e07d6b9b-2b6c-45bd-840b-3c4c3d890168"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createtagsjob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createtagsjob.json deleted file mode 100644 index ab6a8452bc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createtagsjob.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"dcfd4b83-2ae6-43d1-a2eb-af87066ecbc9","userid":"c3d3cb3c-0f13-429a-b900-5bacc346df32","cmd":"com.cloud.api.commands.CreateTagsCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-02-07T20:10:40+0100","jobid":"2a7426a5-e25e-4400-900d-09bca3c0a039"} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createvolumejob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createvolumejob.json deleted file mode 100644 index 9955c93250..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createvolumejob.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.CreateVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Allocated","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"None","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering","diskofferingdisplaytext":"Disk offering display name","storage":"none","destroyed":false,"isextractable":false}},"created":"2012-06-05T08:47:54+0200","jobid":"35416f6d-1b5b-4ceb-a7d4-aab0deede71b"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteNetwork.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteNetwork.json deleted file mode 100644 index 19494c3595..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteNetwork.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"02c9bf08-6f36-44b1-a57f-df0708f90de4","userid":"6ef2b921-4ecf-4651-8188-f9868db73e73","cmd":"org.apache.cloudstack.api.command.user.network.DeleteNetworkCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-06-11T10:09:00+0200","jobid":"65789636-d2c8-484c-9d13-47ad3de384ed"} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deletetagsjob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deletetagsjob.json deleted file mode 100644 index b16cb4d869..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deletetagsjob.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"dcfd4b83-2ae6-43d1-a2eb-af87066ecbc9","userid":"c3d3cb3c-0f13-429a-b900-5bacc346df32","cmd":"com.cloud.api.commands.DeleteTagsCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-02-08T13:43:24+0100","jobid":"02425faf-4cf4-44c2-9241-cb8b1eabc957"} } \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_detachvolumejob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_detachvolumejob.json deleted file mode 100644 index 6d48599fc9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_detachvolumejob.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.DetachVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"5931d2ca-4e90-4915-88a8-32b38b3991a3","name":"gre-test-volume","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","size":10737418240,"created":"2012-06-15T14:56:40+0200","state":"Ready","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"KVM","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"OS disk for Windows","diskofferingdisplaytext":"OS disk for Windows","storage":"Shared Storage CL01","destroyed":false,"isextractable":false}},"created":"2012-06-15T15:08:39+0200","jobid":"ca6c856d-1f36-4e27-989e-09cad2dad808"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json deleted file mode 100644 index 07cdba36a1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "rebootvirtualmachineresponse" : {"jobid":17165} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_default.json deleted file mode 100644 index f52ee31112..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "registersshkeypairresponse": { "keypair": { "name": "foobar", "fingerprint": "c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15" } } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_error.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_error.json deleted file mode 100644 index 6622ab148d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_error.json +++ /dev/null @@ -1 +0,0 @@ -{ "registersshkeypairresponse" : {"uuidList":[],"errorcode":431,"errortext":"Public key is invalid"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json deleted file mode 100644 index 6919656f42..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "revokesecuritygroupegressresponse" : {"jobid":17203} } - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json deleted file mode 100644 index c60ad160f0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "revokesecuritygroupingressresponse" : {"jobid":17201} } - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json deleted file mode 100644 index 750e493725..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "startvirtualmachineresponse" : {"jobid":17188} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json deleted file mode 100644 index cb30e00498..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "stopvirtualmachineresponse" : {"jobid":17199} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/create_node.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/create_node.json deleted file mode 100644 index acddc0800b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/create_node.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","droplet":{"id":119461,"name":"test-2","image_id":1601,"size_id":66,"event_id":919341}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/destroy_node.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/destroy_node.json deleted file mode 100644 index bae818d035..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/destroy_node.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","event_id":918910} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/error.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/error.txt deleted file mode 100644 index 0e90e519ee..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/error.txt +++ /dev/null @@ -1 +0,0 @@ -You are being redirected. diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/error_invalid_image.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/error_invalid_image.json deleted file mode 100644 index e1ccb4f939..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/error_invalid_image.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"ERROR","error_message":"You specified an invalid image for Droplet creation.","message":"You specified an invalid image for Droplet creation."} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_create_ssh_key.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_create_ssh_key.json deleted file mode 100644 index 029cab266e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_create_ssh_key.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","ssh_key":{"id":7717,"name":"test1","ssh_pub_key":"aaq"}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_destroy_ssh_key.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_destroy_ssh_key.json deleted file mode 100644 index 12d1b5927d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_destroy_ssh_key.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK"} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_list_ssh_keys.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_list_ssh_keys.json deleted file mode 100644 index 11119763b2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_list_ssh_keys.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","ssh_keys":[{"id":7717,"name":"test1"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_rename_node.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_rename_node.json deleted file mode 100644 index bae818d035..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/ex_rename_node.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","event_id":918910} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_images.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_images.json deleted file mode 100644 index 007a57d73b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_images.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "status": "OK", - "images": [ - { - "id": 1601, - "name": "CentOS 5.8 x64", - "distribution": "CentOS" - }, - { - "id": 1602, - "name": "CentOS 5.8 x32", - "distribution": "CentOS" - }, - { - "id": 1605, - "name": "CentOS 6.0 x32", - "distribution": "CentOS" - }, - { - "id": 1606, - "name": "Fedora 15 x64", - "distribution": "Fedora" - }, - { - "id": 1609, - "name": "Ubuntu 11.10 x32 Server", - "distribution": "Ubuntu" - }, - { - "id": 1611, - "name": "CentOS 6.2 x64", - "distribution": "CentOS" - }, - { - "id": 1615, - "name": "Fedora 16 x64 Server", - "distribution": "Fedora" - }, - { - "id": 1618, - "name": "Fedora 16 x64 Desktop", - "distribution": "Fedora" - }, - { - "id": 2676, - "name": "Ubuntu 12.04 x64 Server", - "distribution": "Ubuntu" - }, - { - "id": 12573, - "name": "Debian 6.0 x64", - "distribution": "Debian" - }, - { - "id": 12574, - "name": "CentOS 6.3 x64", - "distribution": "CentOS" - }, - { - "id": 12575, - "name": "Debian 6.0 x32", - "distribution": "Debian" - }, - { - "id": 12578, - "name": "CentOS 6.3 x32", - "distribution": "CentOS" - }, - { - "id": 14097, - "name": "Ubuntu 10.04 x64 Server", - "distribution": "Ubuntu" - }, - { - "id": 14098, - "name": "Ubuntu 10.04 x32 Server", - "distribution": "Ubuntu" - }, - { - "id": 14218, - "name": "Ubuntu 12.04 x64 Desktop", - "distribution": "Ubuntu" - }, - { - "id": 25306, - "name": "Ubuntu 12.10 x32 Server", - "distribution": "Ubuntu" - }, - { - "id": 25485, - "name": "Ubuntu 12.10 x32 Desktop", - "distribution": "Ubuntu" - }, - { - "id": 25489, - "name": "Ubuntu 12.10 x64 Server", - "distribution": "Ubuntu" - }, - { - "id": 25493, - "name": "Ubuntu 12.10 x64 Desktop", - "distribution": "Ubuntu" - }, - { - "id": 32387, - "name": "Fedora 17 x32 Server", - "distribution": "Fedora" - }, - { - "id": 32399, - "name": "Fedora 17 x32 Desktop", - "distribution": "Fedora" - }, - { - "id": 32419, - "name": "Fedora 17 x64 Desktop", - "distribution": "Fedora" - }, - { - "id": 32428, - "name": "Fedora 17 x64 Server", - "distribution": "Fedora" - }, - { - "id": 42735, - "name": "Ubuntu 12.04 x32 Server", - "distribution": "Ubuntu" - }, - { - "id": 43458, - "name": "Ubuntu 11.04x64 Server", - "distribution": "Ubuntu" - }, - { - "id": 43462, - "name": "Ubuntu 11.04x32 Desktop", - "distribution": "Ubuntu" - }, - { - "id": 46964, - "name": "LAMP on Ubuntu 12.04", - "distribution": "Ubuntu" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_locations.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_locations.json deleted file mode 100644 index a87b38f2cd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_locations.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","regions":[{"id":1,"name":"New York 1"},{"id":2,"name":"Amsterdam 1"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_nodes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_nodes.json deleted file mode 100644 index 5fe59491ac..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_nodes.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","droplets":[{"id":119461,"name":"test-2","image_id":1601,"size_id":66,"region_id":1,"backups_active":null,"ip_address":null,"status":"new"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_nodes_empty.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_nodes_empty.json deleted file mode 100644 index bc62108c5a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_nodes_empty.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","droplets":[]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_sizes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_sizes.json deleted file mode 100644 index 99acc575c6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/list_sizes.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","sizes":[{"id":66,"name":"512MB"},{"id":63,"name":"1GB"},{"id":62,"name":"2GB"},{"id":64,"name":"4GB"},{"id":65,"name":"8GB"},{"id":61,"name":"16GB"},{"id":60,"name":"32GB"},{"id":70,"name":"48GB"},{"id":69,"name":"64GB"},{"id":68,"name":"96GB"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/reboot_node.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/reboot_node.json deleted file mode 100644 index bae818d035..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/digitalocean/reboot_node.json +++ /dev/null @@ -1 +0,0 @@ -{"status":"OK","event_id":918910} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/allocate_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/allocate_address.xml deleted file mode 100644 index 94587b6430..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/allocate_address.xml +++ /dev/null @@ -1,5 +0,0 @@ - - 56926e0e-5fa3-41f3-927c-17212def59df - 192.0.2.1 - standard - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/allocate_vpc_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/allocate_vpc_address.xml deleted file mode 100644 index 9029d677a9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/allocate_vpc_address.xml +++ /dev/null @@ -1,6 +0,0 @@ - - eb920193-37a9-401a-8fff-089783b2c153 - 192.0.2.2 - vpc - eipalloc-666d7f04 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/associate_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/associate_address.xml deleted file mode 100644 index 39c29bbffe..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/associate_address.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 1a470be4-b44d-4423-a80c-44ef2070b8be - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/associate_vpc_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/associate_vpc_address.xml deleted file mode 100644 index 21348edcdc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/associate_vpc_address.xml +++ /dev/null @@ -1,5 +0,0 @@ - - s132fsz2-6cdg-4ox3-a148-lpqnvdc98c2a - true - eipassoc-167a8073 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml deleted file mode 100644 index 852ec39e9b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 1eb45fd7-d4f6-4b63-a52f-54fc0c82617e - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_network_interface.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_network_interface.xml deleted file mode 100644 index 7b6baa8123..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_network_interface.xml +++ /dev/null @@ -1,4 +0,0 @@ - - e46c7abc-8b14-4315-99cb-773a0f95d833 - eni-attach-2b588b47 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_volume.xml deleted file mode 100644 index b0df438ac8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/attach_volume.xml +++ /dev/null @@ -1,8 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - vol-4d826724 - i-6058a509 - /dev/sdh - attaching - 2008-05-07T11:51:50.000Z - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml deleted file mode 100644 index 41e7e463b3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/authorize_security_group_ingress.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/authorize_security_group_ingress.xml deleted file mode 100644 index 18b02ac9bc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/authorize_security_group_ingress.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/copy_image.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/copy_image.xml deleted file mode 100644 index f2e76b0f1d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/copy_image.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 7b7d87d5-c045-4c2c-a2c4-b538debe14b2 - ami-4db38224 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_image.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_image.xml deleted file mode 100644 index 1213f0a21c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_image.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 3629ec66-c1f8-4b66-aac5-a8ad1cdf6c15 - ami-e9b38280 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml deleted file mode 100644 index 0891423c85..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml +++ /dev/null @@ -1,8 +0,0 @@ - - 437b9824-8143-4583-98f7-0937d53aea83 - - igw-13ac2b36 - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_key_pair.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_key_pair.xml deleted file mode 100644 index 2404991938..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_key_pair.xml +++ /dev/null @@ -1,22 +0,0 @@ - - my-key-pair - - 1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f - - ---- BEGIN RSA PRIVATE KEY ---- -MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC -VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6 -b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd -BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN -MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD -VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z -b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt -YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ -21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T -rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE -Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4 -nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb -FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb -NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE ------END RSA PRIVATE KEY----- - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_network_interface.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_network_interface.xml deleted file mode 100644 index 416477ed05..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_network_interface.xml +++ /dev/null @@ -1,30 +0,0 @@ - - ca764ebe-8abc-4d37-9995-b9e88c086fa8 - - eni-2b36086d - subnet-5ed9d432 - vpc-62ded30e - us-east-1d - My Test - 123456789098 - false - pending - 0e:bd:49:3e:11:74 - 172.16.4.144 - ip-172-16-4-144.ec2.internal - true - - - sg-495a9926 - default - - - - - - 172.16.4.144 - true - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_security_group.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_security_group.xml deleted file mode 100644 index f714eb676f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_security_group.xml +++ /dev/null @@ -1,5 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - sg-52e2f530 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_snapshot.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_snapshot.xml deleted file mode 100644 index 046778b669..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_snapshot.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587 - snap-a7cb2hd9 - vol-4282672b - pending - 2013-08-15T16:22:30.000Z - 60% - 1836219348 - 10 - Test description - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_subnet.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_subnet.xml deleted file mode 100644 index b04a69e896..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_subnet.xml +++ /dev/null @@ -1,11 +0,0 @@ - - e94b315e-6424-4536-b48d-0dfb47732c72 - - subnet-ce0e7ce6 - pending - vpc-532135d1 - 192.168.51.128/26 - 59 - us-east-1b - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_tags.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_tags.xml deleted file mode 100644 index 87aef51a27..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_tags.xml +++ /dev/null @@ -1,4 +0,0 @@ - - b001068a-ca0d-4f05-b622-28fe984f44be - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_volume.xml deleted file mode 100644 index a80cd427a4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_volume.xml +++ /dev/null @@ -1,9 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - vol-4d826724 - 10 - - us-east-1a - creating - 2008-05-07T11:51:50.000Z - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_vpc.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_vpc.xml deleted file mode 100644 index 70bff318c8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/create_vpc.xml +++ /dev/null @@ -1,10 +0,0 @@ - - 7a662fe5-1f34-4e17-9ee9-69a28a8ac0be - - vpc-ad3527cf - pending - 192.168.55.0/24 - dopt-7eded312 - default - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml deleted file mode 100644 index 619ab540b6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml +++ /dev/null @@ -1,4 +0,0 @@ - - b1a5c8c9-91c7-43f3-8234-c162db89a2df - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_key_pair.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_key_pair.xml deleted file mode 100644 index 3e605b0b75..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_key_pair.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587 - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_network_interface.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_network_interface.xml deleted file mode 100644 index 07bc619c50..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_network_interface.xml +++ /dev/null @@ -1,4 +0,0 @@ - - c0bc0036-e328-47c6-bd6d-318b007f66ee - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_security_group.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_security_group.xml deleted file mode 100644 index 2dc4eec71d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_security_group.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_snapshot.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_snapshot.xml deleted file mode 100644 index fb24a7033f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_snapshot.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 5cd6fa89-35bd-4aac-99ed-na8af7 - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_subnet.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_subnet.xml deleted file mode 100644 index dd5ed645fc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_subnet.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 5cd6fa89-35bd-4aac-99ed-na8af7 - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_tags.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_tags.xml deleted file mode 100644 index bcc2ffd4b5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_tags.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 7a297da7-3ecb-4156-8bcb-3be73896cc14 - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_volume.xml deleted file mode 100644 index c6065bcb63..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_volume.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_vpc.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_vpc.xml deleted file mode 100644 index e402a502fe..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/delete_vpc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 85793fa6-2ece-480c-855f-0f82c3257e50 - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/deregister_image.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/deregister_image.xml deleted file mode 100644 index 63ecce932f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/deregister_image.xml +++ /dev/null @@ -1,4 +0,0 @@ - - d06f248d-444e-475d-a8f8-1ebb4ac39842 - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_account_attributes.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_account_attributes.xml deleted file mode 100644 index bca2e42139..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_account_attributes.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - a00adaf6-f86c-48eb-85f8-7ac470ae993d - - - max-instances - - - 20 - - - - - max-elastic-ips - - - 5 - - - - - vpc-max-elastic-ips - - - 5 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses.xml deleted file mode 100644 index e6147c5ddf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses.xml +++ /dev/null @@ -1,15 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - - - 1.2.3.4 - eipalloc-602b5d01 - vpc - i-4382922a - eipassoc-cea049ab - eni-83e3c5c5 - 123456789098 - 192.168.1.5 - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_all.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_all.xml deleted file mode 100644 index 2803dce135..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_all.xml +++ /dev/null @@ -1,35 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - - - 1.2.3.4 - eipalloc-602b5d01 - vpc - i-4382922a - eipassoc-cea049ab - eni-83e3c5c5 - 123456789098 - 192.168.1.5 - - - 1.2.3.5 - eipalloc-998195fb - vpc - i-4382922b - eipassoc-cea049ac - eni-83e3c5c6 - 123456789098 - 192.168.1.6 - - - 1.2.3.6 - eipalloc-922a5cf3 - standard - - - 1.2.3.7 - eipalloc-992a5cf8 - vpc - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_multi.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_multi.xml deleted file mode 100644 index 09cc217ccc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_multi.xml +++ /dev/null @@ -1,17 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - - - 1.2.3.4 - i-4382922a - - - 1.2.3.6 - i-4382922b - - - 1.2.3.5 - i-4382922b - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_single.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_single.xml deleted file mode 100644 index d8b1c2975e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_addresses_single.xml +++ /dev/null @@ -1,9 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - - - 1.2.3.4 - i-4382922a - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_availability_zones.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_availability_zones.xml deleted file mode 100644 index 37ab047067..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_availability_zones.xml +++ /dev/null @@ -1,17 +0,0 @@ - - cc0dfb29-efef-451c-974f-341b3edfb28f - - - eu-west-1a - available - eu-west-1 - - - - eu-west-1b - available - eu-west-1 - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_images.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_images.xml deleted file mode 100644 index 03594e9e4c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_images.xml +++ /dev/null @@ -1,62 +0,0 @@ - - 73fac9c5-f6d2-4b45-846f-47adf1e82d6c - - - ami-57ba933a - 123456788908/Test Image - available - 123456788908 - false - x86_64 - machine - aki-88aa75e1 - Test Image - Testing Stuff - ebs - /dev/sda1 - - - /dev/sda1 - - snap-88123ed9 - 10 - true - standard - - - - /dev/sda2 - ephemeral0 - - - paravirtual - xen - - - ami-85b2a8ae - 123456788908/Test Image 2 - available - 123456788908 - false - x86_64 - machine - aki-88aa75e1 - Test Image 2 - ebs - /dev/sda1 - - - /dev/sda1 - - snap-c0bfbbdb - 20 - false - standard - - - - paravirtual - xen - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml deleted file mode 100644 index 47f2be0d19..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml +++ /dev/null @@ -1,36 +0,0 @@ - - 73fac9c5-f6d2-4b45-846f-47adf1e82d6c - - - ami-57ba933a - 123456788908/Test Image - available - 123456788908 - false - x86_64 - machine - aki-88aa75e1 - Test Image - Testing Stuff - ebs - /dev/sda1 - - - /dev/sda1 - - snap-88123ed9 - 10 - true - standard - - - - /dev/sda2 - ephemeral0 - - - paravirtual - xen - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_instance_types.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_instance_types.xml deleted file mode 100644 index 3fff98b77f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_instance_types.xml +++ /dev/null @@ -1 +0,0 @@ -truem1.small15256t1.micro15256m1.medium110512c1.medium210512m1.large1101024c1.xlarge2101024m1.xlarge1102048m2.xlarge2102048m3.xlarge16152048m2.2xlarge16304096m3.2xlarge16304096cc1.4xlarge16603072m2.4xlarge16604096cc2.8xlarge161206144hi1.4xlarge161206144cg1.4xlarge1620012288cr1.8xlarge1624016384hs1.8xlarge1624000119808 \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_instances.xml deleted file mode 100644 index 1c3233ef4a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_instances.xml +++ /dev/null @@ -1,182 +0,0 @@ - - ec0d2a7d-5080-4f4b-9b02-cb0d5d2d4274 - - - r-fd67fb97 - 123456789098 - - - - i-4382922a - ami-3215fe5a - - 80 - stopped - - - - User initiated (2014-01-11 14:39:31 GMT) - fauxkey - 0 - - m1.small - 2013-12-02T11:58:11.000Z - - us-east-1d - - default - - aki-88aa75e1 - - disabled - - 10.211.11.211 - 1.2.3.4 - - - sg-42916629 - Test Group 1 - - - sg-42916628 - Test Group 2 - - - - Client.UserInitiatedShutdown - Client.UserInitiatedShutdown: User initiated shutdown - - x86_64 - ebs - /dev/sda1 - - - /dev/sda1 - - vol-5e312311 - attached - 2013-04-09T18:01:01.000Z - true - - - - paravirtual - ifmxj1365530456668 - - xen - - false - - - - - r-88dc1bef - 123456789098 - - - - i-8474834a - ami-29674340 - - 80 - stopped - - ip-172-16-9-139.ec2.internal - - User initiated (2014-01-11 14:39:31 GMT) - cderamus - 0 - - t1.micro - 2013-12-02T15:58:29.000Z - - us-east-1d - - default - - aki-88aa75e1 - - disabled - - subnet-5fd9d412 - vpc-61dcd30e - 172.16.9.139 - 1.2.3.5 - true - - - sg-495a9926 - default - - - - Client.UserInitiatedShutdown - Client.UserInitiatedShutdown: User initiated shutdown - - x86_64 - ebs - /dev/sda1 - - - /dev/sda1 - - vol-60124921 - attached - 2013-12-02T15:58:32.000Z - false - - - - paravirtual - - - - Name - Test Server 2 - - - Group - VPC Test - - - xen - - - eni-c5dffd83 - subnet-5fd9d412 - vpc-61dcd30e - - 123456789098 - in-use - 0e:27:72:16:52:ab - 172.16.9.139 - ip-172-16-9-139.ec2.internal - true - - - sg-495a9926 - default - - - - eni-attach-4d924721 - 0 - attached - 2013-12-02T15:58:29.000Z - true - - - - 172.16.4.139 - ip-172-16-4-139.ec2.internal - true - - - - - false - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml deleted file mode 100644 index 44c7185248..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml +++ /dev/null @@ -1,20 +0,0 @@ - - 843ff26c-f1ac-48f5-93a6-fa28f8abd9dd - - - igw-84dd3ae1 - - - - - igw-7fdae215 - - - vpc-62cad41e - available - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_key_pairs.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_key_pairs.xml deleted file mode 100644 index e386eedafa..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_key_pairs.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - - - gsg-keypair - - 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_key_pairs_doesnt_exist.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_key_pairs_doesnt_exist.xml deleted file mode 100644 index d5a9cae290..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_key_pairs_doesnt_exist.xml +++ /dev/null @@ -1,2 +0,0 @@ - -InvalidKeyPair.NotFoundThe key pair 'test-key-pair' does not exist31b97300-eb8e-405e-9567-b0f57b791fed diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_network_interfaces.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_network_interfaces.xml deleted file mode 100644 index f5208778db..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_network_interfaces.xml +++ /dev/null @@ -1,83 +0,0 @@ - - e8fc6c0b-d6f8-4b85-aa29-e6a097eb4631 - - - eni-18e6c05e - subnet-5ed9d432 - vpc-62ded30e - us-east-1d - Test Interface 1 - 123456789098 - false - in-use - 0e:6e:df:72:78:af - 172.16.4.133 - ip-172-16-4-133.ec2.internal - true - - - sg-495a9926 - default - - - - eni-attach-c87dd1a4 - i-caa71db1 - 123456789098 - 1 - attached - 2013-12-02T17:46:27.000Z - false - - - - - 172.16.4.133 - ip-172-16-4-133.ec2.internal - true - - - - - eni-83e3c5c5 - subnet-5ed9d432 - vpc-62ded30e - us-east-1d - - 123456789098 - false - in-use - 0e:93:0b:e9:e9:c4 - 172.16.4.145 - ip-172-16-4-145.ec2.internal - true - - - sg-13e4607c - Test Group - - - sg-495a9926 - default - - - - eni-attach-bae984d6 - i-caa71db1 - 123456789098 - 0 - attached - 2013-11-25T13:35:03.000Z - true - - - - - 172.16.4.145 - ip-172-16-4-145.ec2.internal - true - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_reserved_instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_reserved_instances.xml deleted file mode 100644 index 15e14e3e70..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_reserved_instances.xml +++ /dev/null @@ -1,21 +0,0 @@ - - 56d0fffa-8819-4658-bdd7-548f143a86d2 - - - 93bbbca2-c500-49d0-9ede-9d8737400498 - t1.micro - us-east-1b - 2013-06-18T12:07:53.161Z - 31536000 - 23.0 - 0.012 - 1 - Linux/UNIX - active - default - USD - Light Utilization - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_security_groups.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_security_groups.xml deleted file mode 100644 index a292970315..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_security_groups.xml +++ /dev/null @@ -1,50 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - - - 111122223333 - sg-443d0a12 - WebServers - Web Servers - - - - tcp - 80 - 80 - - - - 0.0.0.0/0 - - - - - - - - - 111122223333 - sg-5ff8a023 - RangedPortsBySource - Group A - - - tcp - 6000 - 7000 - - - 111122223333 - sg-99gh4012 - Group B - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_snapshots.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_snapshots.xml deleted file mode 100644 index b884c79c4e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_snapshots.xml +++ /dev/null @@ -1,43 +0,0 @@ - - and4xcasi-35bd-4e3c-89ab-cb183 - - - snap-428abd35 - vol-e020df80 - pending - 2013-09-15T15:40:30.000Z - 90% - 1938218230 - 30 - Daily Backup - - - Keyone - DB_Backup - - - - - - - snap-18349159 - vol-b5a2c1v9 - pending - 2013-09-15T16:00:30.000Z - 30% - 1938218230 - 15 - Weekly backup - - - Name - DB Backup 1 - - - Key2 - db_backup - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_subnets.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_subnets.xml deleted file mode 100644 index 3d14d504b6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_subnets.xml +++ /dev/null @@ -1,37 +0,0 @@ - - 67bba371-8044-45a7-b4a3-d72fef8b96d8 - - - subnet-ce0e7ce5 - available - vpc-532135d1 - 192.168.51.0/25 - 123 - us-east-1a - false - false - - - Name - Test Subnet 1 - - - - - subnet-ce0e7ce6 - available - vpc-532135d1 - 192.168.51.128/64 - 59 - us-east-1b - false - false - - - Name - Test Subnet 2 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_tags.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_tags.xml deleted file mode 100644 index 988b3e19b8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_tags.xml +++ /dev/null @@ -1,23 +0,0 @@ - - fa7e0e44-df5e-49a0-98d7-5d4d19a29f95 - - - i-4382922a - instance - tag - test one - - - i-4382922a - instance - owner - libcloud - - - i-4382922a - instance - stack - Production - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_volumes.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_volumes.xml deleted file mode 100644 index 5dde8e4593..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_volumes.xml +++ /dev/null @@ -1,42 +0,0 @@ - - 766b978a-f574-4c8d-a974-57547a8c304e - - - vol-10ae5e2b - 1 - - us-east-1d - available - 2013-10-09T05:41:37.000Z - - - - vol-v24bfh75 - 11 - - us-east-1c - available - 2013-10-08T19:36:49.000Z - - - - vol-b6c851ec - 8 - snap-30d37269 - us-east-1d - in-use - 2013-06-25T02:04:12.000Z - - - vol-b6c851ec - i-d334b4b3 - /dev/sda1 - attached - 2013-06-25T02:04:12.000Z - true - - - standard - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_vpcs.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_vpcs.xml deleted file mode 100644 index 0341edb04a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/describe_vpcs.xml +++ /dev/null @@ -1,28 +0,0 @@ - - be8cfa34-0710-4895-941f-961c5738f8f8 - - - vpc-532335e1 - available - 192.168.51.0/24 - dopt-7eded312 - - default - false - - - vpc-62ded30e - available - 192.168.52.0/24 - dopt-7eded312 - - - Name - Test VPC - - - default - false - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml deleted file mode 100644 index 8fa1e50030..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 7098cc6d-a984-4d34-a5ed-6ae1a645c0b6 - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_network_interface.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_network_interface.xml deleted file mode 100644 index 0f95a8bcca..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_network_interface.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 1a683cd6-58ea-4b93-a6e9-a23b56afddf0 - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_volume.xml deleted file mode 100644 index c49817696d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/detach_volume.xml +++ /dev/null @@ -1,8 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - vol-4d826724 - i-6058a509 - /dev/sdh - detaching - 2008-05-08T11:51:50.000Z - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/disassociate_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/disassociate_address.xml deleted file mode 100644 index 99d81023af..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/disassociate_address.xml +++ /dev/null @@ -1,4 +0,0 @@ - - dfb841f8-cc26-4f45-a3ac-dc08589eec1d - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/get_console_output.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/get_console_output.xml deleted file mode 100644 index 5d74cd6303..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/get_console_output.xml +++ /dev/null @@ -1,6 +0,0 @@ - - f0ffb5ce-8d62-4ab9-add7-67a0f99c9811 - i-40128925 - 2013-12-02T12:31:38.000Z - VGVzdCBTdHJpbmc= - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/import_key_pair.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/import_key_pair.xml deleted file mode 100644 index 09479f1675..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/import_key_pair.xml +++ /dev/null @@ -1,5 +0,0 @@ - - 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE - keypair - 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/modify_image_attribute.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/modify_image_attribute.xml deleted file mode 100644 index 200cb6a041..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/modify_image_attribute.xml +++ /dev/null @@ -1,3 +0,0 @@ - - true - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/modify_instance_attribute.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/modify_instance_attribute.xml deleted file mode 100644 index 2ff14e96b0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/modify_instance_attribute.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/reboot_instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/reboot_instances.xml deleted file mode 100644 index df7aa31a6d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/reboot_instances.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 76dabb7a-fb39-4ed1-b5e0-31a4a0fdf5c0 - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/register_image.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/register_image.xml deleted file mode 100644 index ebaeb08206..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/register_image.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 6d858ea7-053e-4751-9fae-b891019fc8d2 - ami-57c2fb3e - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/release_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/release_address.xml deleted file mode 100644 index 67ccf4e8e5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/release_address.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 23ec1390-8c1d-4a3e-8042-b1ad84933f57 - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml deleted file mode 100644 index 248fbb79de..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml deleted file mode 100644 index 26708dae9a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml +++ /dev/null @@ -1,4 +0,0 @@ - - 59dbff89-35bd-4eac-99ed-be587EXAMPLE - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances.xml deleted file mode 100644 index dd0852ee27..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances.xml +++ /dev/null @@ -1,31 +0,0 @@ - - r-47a5402e - AIDADH4IGTRXXKCD - - - default - - - - - i-2ba64342 - ami-be3adfd7 - - 0 - pending - - - - example-key-name - 0 - m1.small - 2007-08-07T11:51:50.000Z - - us-east-1b - - - true - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_iam_profile.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_iam_profile.xml deleted file mode 100644 index b61d8358e8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_iam_profile.xml +++ /dev/null @@ -1,35 +0,0 @@ - - r-47a5403e - AIDADH4IGTRXXKCD - - - default - - - - - i-2ba64343 - ami-be3adfd7 - - 0 - pending - - - - example-key-name - 0 - m1.small - 2007-08-07T11:51:50.000Z - - us-east-1b - - - true - - - AIDGPMS9RO4H3FEXAMPLE - arn:aws:iam::123456789012:instance-profile/ExampleInstanceProfile - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_idem.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_idem.xml deleted file mode 100644 index 30824ff889..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_idem.xml +++ /dev/null @@ -1,32 +0,0 @@ - - r-47a5402e - AIDADH4IGTRXXKCD - - - default - - - - - i-2ba64342 - ami-be3adfd7 - - 0 - pending - - - - example-key-name - 0 - m1.small - 2007-08-07T11:51:50.000Z - - us-east-1b - - - true - - testclienttoken - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_idem_mismatch.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_idem_mismatch.xml deleted file mode 100644 index 9b704e7b90..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/run_instances_idem_mismatch.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - IdempotentParameterMismatch - - Arguments on this idempotent request are inconsistent with arguments used in previous request(s). - - - - 5dabd361-d2e0-4f79-937d-4b2852a3b719 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/start_instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/start_instances.xml deleted file mode 100644 index cd793ec2b2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/start_instances.xml +++ /dev/null @@ -1,17 +0,0 @@ - - 322f78ee-967b-40c9-aecd-8d442022da20 - - - i-ff5de6aa - - 0 - pending - - - 80 - stopped - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/stop_instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/stop_instances.xml deleted file mode 100644 index 79bc6fe0bb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/stop_instances.xml +++ /dev/null @@ -1,16 +0,0 @@ - - 4ace6850-c876-4971-af0b-67a4278c36a1 - - - i-2ba64342 - - 64 - stopping - - - 16 - running - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/terminate_instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/terminate_instances.xml deleted file mode 100644 index de314de642..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ec2/terminate_instances.xml +++ /dev/null @@ -1,16 +0,0 @@ - - fa63083d-e0f7-4933-b31a-f266643bdee8 - - - i-4382922a - - 32 - shutting-down - - - 16 - running - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/htemplate_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/htemplate_list.json deleted file mode 100644 index cffa9e3b78..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/htemplate_list.json +++ /dev/null @@ -1,9 +0,0 @@ -{"templates": [ - -{"uuid": "1", "hypervisor_name": "kvm-hvm", "cpus": 1, "memory": 512, "arch": "i686", "id": 1, "name": "Small"}, - -{"uuid": "2", "hypervisor_name": "kvm-hvm", "cpus": 2, "memory": 1024, "arch": "i686", "id": 2, "name": "Medium"}, - -{"uuid": "3", "hypervisor_name": "kvm-hvm", "cpus": 3, "memory": 2048, "arch": "x86_64", "id": 3, "name": "Large"} - -], "errno": 0, "message": "Success"} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/network_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/network_list.json deleted file mode 100644 index c588ab5b63..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/network_list.json +++ /dev/null @@ -1 +0,0 @@ -{"errno": 0, "message": "Success", "networks": [{"uuid": "1", "vlan_id": null, "name": "Default"}]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/ptemplate_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/ptemplate_list.json deleted file mode 100644 index 1f45c47c4f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/ptemplate_list.json +++ /dev/null @@ -1,6 +0,0 @@ -{"errno": 0, "message": "Success", "packages": [ - -{"os": "unknown", "description": "AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2", "storage": 20480, "uuid": "1", "name": "centos54"}, - -{"os": "unknown", "description": "AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2", "storage": 20480, "uuid": "2", "name": "centos54 two"} -]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_delete.json deleted file mode 100644 index abe1a6d51c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_delete.json +++ /dev/null @@ -1 +0,0 @@ -{"errno": 0, "message": "Success"} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_start.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_start.json deleted file mode 100644 index 6dd8dacbad..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_start.json +++ /dev/null @@ -1,3 +0,0 @@ -{"errno": 0, "message": "Success", "vm": -{"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "unkown", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.12", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_stop.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_stop.json deleted file mode 100644 index 78838b6b38..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_action_stop.json +++ /dev/null @@ -1,3 +0,0 @@ -{"errno": 0, "message": "Success", "vm": -{"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "unkown", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_get.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_get.json deleted file mode 100644 index 8bb5614851..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_1_get.json +++ /dev/null @@ -1,3 +0,0 @@ -{"errno": 0, "message": "Success", "vm": -{"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "off", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_list.json deleted file mode 100644 index 48436a85d4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_list.json +++ /dev/null @@ -1,10 +0,0 @@ -{"errno": 0, "message": "Success", "vms": -[ -{"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "running", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"}, - -{"vnc_enabled": true, "uuid": 2, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:72:b4:71:21", "network_name": "Default", "uuid": "c76edd61-2dfd-11df-84ca-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5902", "name": "dummy-2", "state": "running", "trusted": null, "os": "unknown", "vnc_password": "zoiZW31T", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"}, - -{"vnc_enabled": true, "uuid": 3, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "stopped", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} - -] -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_put.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_put.json deleted file mode 100644 index 55f01bfe6f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ecp/vm_put.json +++ /dev/null @@ -1 +0,0 @@ -{"errno": 0, "message": "Success", "txid": "fc38963c-a9fa-11de-8c4b-001baaa56c51", "machine_id": "1234"} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/drives_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/drives_create.json deleted file mode 100644 index 659ea4151c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/drives_create.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "drive": "0012e24a-6eae-4279-9912-3432f698cec8", - "encryption:cipher": "aes-xts-plain", - "name": "test drive", - "read:bytes": "4096", - "read:requests": "1", - "size": 10737418240, - "status": "active", - "user": "2164ce57-591c-43ee-ade5-e2fe0ee13c3e", - "write:bytes": "4096", - "write:requests": "1" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/drives_info.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/drives_info.json deleted file mode 100644 index 659ea4151c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/drives_info.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "drive": "0012e24a-6eae-4279-9912-3432f698cec8", - "encryption:cipher": "aes-xts-plain", - "name": "test drive", - "read:bytes": "4096", - "read:requests": "1", - "size": 10737418240, - "status": "active", - "user": "2164ce57-591c-43ee-ade5-e2fe0ee13c3e", - "write:bytes": "4096", - "write:requests": "1" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/servers_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/servers_create.json deleted file mode 100644 index 3a17f9645a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/servers_create.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "boot": "ide:0:0", - "cpu": 2000, - "ide:0:0": "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3", - "ide:0:0:read:bytes": "299696128", - "ide:0:0:read:requests": "73168", - "ide:0:0:write:bytes": "321044480", - "ide:0:0:write:requests": "78380", - "mem": 1024, - "name": "test api node", - "nic:0:block": "tcp/21 tcp/22 tcp/23 tcp/25", - "nic:0:dhcp": ["1.2.3.4", "1.2.3.5"], - "nic:0:model": "virtio", - "rx": 679560, - "rx:packets": 644, - "server": "b605ca90-c3e6-4cee-85f8-a8ebdf8f9903", - "smp": 1, - "started": 1280723696, - "status": "active", - "tx": 21271, - "tx:packets": "251", - "user": "2164ce57-591a-43ee-ade5-e2fe0ee13c3f", - "vnc:ip": "216.151.208.174", - "vnc:password": "testvncpass" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/servers_info.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/servers_info.json deleted file mode 100644 index 72b6b48bef..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/elastichosts/servers_info.json +++ /dev/null @@ -1,27 +0,0 @@ -[ - { - "boot": "ide:0:0", - "cpu": 2000, - "ide:0:0": "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3", - "ide:0:0:read:bytes": "299696128", - "ide:0:0:read:requests": "73168", - "ide:0:0:write:bytes": "321044480", - "ide:0:0:write:requests": "78380", - "mem": 1024, - "name": "test api node", - "nic:0:block": "tcp/21 tcp/22 tcp/23 tcp/25", - "nic:0:dhcp": ["1.2.3.4", "1.2.3.5"], - "nic:0:model": "virtio", - "rx": 679560, - "rx:packets": 644, - "server": "b605ca90-c3e6-4cee-85f8-a8ebdf8f9903", - "smp": 1, - "started": 1280723696, - "status": "active", - "tx": 21271, - "tx:packets": "251", - "user": "2164ce57-591a-43ee-ade5-e2fe0ee13c3f", - "vnc:ip": "216.151.208.174", - "vnc:password": "testvncpass" - } -] \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/account_info.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/account_info.xml deleted file mode 100644 index 58499fbc7c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/account_info.xml +++ /dev/null @@ -1,317 +0,0 @@ - - - - - - -handle -AB3917-GANDI - - -products - - - -errors_for_updating - -product_name_does_not_match -no_action_on_free_product - - - -can_release -1 - - -date_end - - - -product_name -shares_fixed - - -autorenew - - - -errors_for_removing - - - - -errors_for_releasing - -no_action_on_free_product -not_available_resource - - - -is_in_redemption - - - -errors_for_autorenewing - -no_action_on_free_product - - - -duration -1y - - -date_created -20101028T12:38:17 - - -quantity -12 - - -errors_for_renewing - -no_action_on_free_product - - - -id -11153 - - -redemption -7 - - - - -errors_for_updating - -no_action_on_free_product - - - -can_release -0 - - -date_end - - - -product_name -ips - - -autorenew - - - -errors_for_removing - - - - -errors_for_releasing - -no_action_on_free_product -db_can_not_release - - - -is_in_redemption - - - -errors_for_autorenewing - -no_action_on_free_product - - - -duration -1m - - -date_created -20110124T11:42:35 - - -quantity -4 - - -errors_for_renewing - -no_action_on_free_product - - - -id -11196 - - -redemption -7 - - - - - -share_definition - - -servers -1 - - -bandwidth -5120.0 - - -memory -256 - - -cores -0.25 - - -slots -0.66666666666666663 - - -disk -8192 - - - - -fullname -Aymeric Barantal - - -id -58757 - - -resources - - -available - - -shares -12 - - -servers -8 - - -ips -4 - - -bandwidth -51200.0 - - -memory -2560 - - -cores -3.0 - - -slots -4.0 - - -disk -89088 - - - - -granted - - -shares -12 - - -servers -12 - - -ips -8 - - -bandwidth -61440 - - -memory -3072 - - -cores -5.0 - - -slots -8.0 - - -disk -98304 - - - - -used - - -servers -4 - - -ips -4 - - -bandwidth -10240.0 - - -memory -512 - - -cores -2.0 - - -slots -4 - - -disk -9216 - - - - -expired - - - - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/account_info_rating.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/account_info_rating.xml deleted file mode 100644 index 9514f990f0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/account_info_rating.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - -handle -AB9090-GANDI - - -rating_enabled -1 - - -date_credits_expiration - - -credits -0 - - -products - - -average_credit_cost - - -share_definition - - -fullname -Aymeric BARANTAL - - -id -24 - - -resources - - -available - - -granted - - -used - - -expired - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/datacenter_list.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/datacenter_list.xml deleted file mode 100644 index 9d8cc688af..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/datacenter_list.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - country - France - - - iso - FR - - - id - 1 - - - name - Equinix Paris - - - - - - - country - United States of America - - - iso - US - - - id - 2 - - - name - Level3 Baltimore - - - - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_attach.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_attach.xml deleted file mode 100644 index 88e1c2a7fa..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_attach.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id - - - -date_updated -20110921T12:57:05 - - -vm_id -250133 - - -date_start - - - -disk_id -34918 - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110921T12:57:05 - - -type -disk_attach - - -id -657982 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_create.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_create.xml deleted file mode 100644 index 1fffb08a6f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_create.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - -iface_id - - -date_updated -20120629T11:48:20 - - -vm_id - - -date_start - - -disk_id -1263 - - -source -AB3917-GANDI - - -step -DONE - - -ip_id - - -date_created -20120629T11:48:20 - - -type -disk_create - - -id -10895 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_create_from.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_create_from.xml deleted file mode 100644 index 4d34d0e19c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_create_from.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id - - - -date_updated -20110921T14:20:56 - - -vm_id - - - -date_start - - - -disk_id -35288 - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110921T14:20:56 - - -type -disk_create - - -id -657985 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_delete.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_delete.xml deleted file mode 100644 index 1b39803dbc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_delete.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - -iface_id - - -date_updated -20120629T11:47:06 - - -vm_id - - -date_start - - -disk_id -1262 - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - -date_created -20120629T11:47:06 - - -type -disk_delete - - -id -10894 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_detach.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_detach.xml deleted file mode 100644 index 388ad6d899..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_detach.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id - - - -date_updated -20110921T12:57:35 - - -vm_id -250133 - - -date_start - - - -disk_id -34918 - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110921T12:57:35 - - -type -disk_detach - - -id -657983 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_info.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_info.xml deleted file mode 100644 index 390d4a4718..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_info.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - -datacenter_id -1 - - -name -libcloud - - -snapshot_profile - - -kernel_version - - -can_snapshot -1 - - -kernel_cmdline - - -visibility -private - - -label - - -vms_id - - - - -source - - -state -created - - -is_boot_disk -0 - - -date_updated -20120629T11:49:00 - - -date_created -20120629T11:48:20 - - -type -data - - -id -1263 - - -size -1024 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_list.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_list.xml deleted file mode 100644 index 5af7613f10..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_list.xml +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - - -datacenter_id -1 - - -name -disk_libcloud2 - - -kernel_version -2.6.32 - - -can_snapshot -0 - - -visibility -private - - -label -Debian 5 - - -vms_id - - - - -source -23351 - - -state -created - - -is_boot_disk -0 - - -date_updated -20101116T10:51:59 - - -date_created -20101028T13:52:38 - - -type -data - - -id -34918 - - -size -3072 - - - - -datacenter_id -1 - - -name -test1 - - -kernel_version -2.6.32 - - -can_snapshot - - - -visibility -private - - -label -Debian 5 - - -vms_id - -250133 - - - -source -23351 - - -state -created - - -is_boot_disk -1 - - -date_updated -20110120T15:02:01 - - -date_created -20110120T14:57:55 - - -type -data - - -id -34951 - - -size -3072 - - - - -datacenter_id -1 - - -name -test_disk - - -kernel_version -2.6.32 - - -can_snapshot -1 - - -visibility -private - - -label -Debian 5 - - -vms_id - -250288 - - - -source -23351 - - -state -created - - -is_boot_disk -1 - - -date_updated -20110325T16:31:11 - - -date_created -20110324T17:14:06 - - -type -data - - -id -35170 - - -size -3072 - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_update.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_update.xml deleted file mode 100644 index 9dcd73e479..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/disk_update.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id - - - -date_updated -20110921T14:23:10 - - -vm_id - - - -date_start - - - -disk_id -34951 - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110921T14:23:10 - - -type -disk_update - - -id -657987 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_attach.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_attach.xml deleted file mode 100644 index 33856c1ed4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_attach.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id -7857 - - -date_updated -20110921T12:49:35 - - -vm_id -250133 - - -date_start - - - -disk_id - - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110921T12:49:35 - - -type -iface_attach - - -id -657980 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_detach.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_detach.xml deleted file mode 100644 index f5080d9013..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_detach.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id -7857 - - -date_updated -20110921T12:53:29 - - -vm_id -250133 - - -date_start - - - -disk_id - - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110921T12:53:29 - - -type -iface_detach - - -id -657981 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_list.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_list.xml deleted file mode 100644 index ba530a6711..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/iface_list.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - -date_updated -20110120T14:58:44 - - -vm_id -250133 - - -bandwidth -5120.0 - - -datacenter_id -1 - - -state -used - - -num -0 - - -ips_id - -9256 -9294 - - - -date_created -20110120T14:57:55 - - -type -public - - -id -7857 - - - - -date_updated -20110324T17:14:16 - - -vm_id -250288 - - -bandwidth -5192.0 - - -datacenter_id -1 - - -state -used - - -num -0 - - -ips_id - -9298 -9508 - - - -date_created -20110324T17:14:06 - - -type -public - - -id -8019 - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/image_list_dc0.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/image_list_dc0.xml deleted file mode 100644 index ee68292ceb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/image_list_dc0.xml +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - - - - - - date_updated - 20100928T10:41:38 - - - disk_id - 34198 - - - label - GandiOS - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20070101T00:00:00 - - - author_id - 248842 - - - id - 2 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11233 - - - label - Mandriva 2008.0 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20070101T00:00:00 - - - author_id - 248842 - - - id - 3 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11235 - - - label - Centos 5 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20070101T00:00:00 - - - author_id - 248842 - - - id - 4 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11236 - - - label - Fedora Core 7 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20070101T00:00:00 - - - author_id - 248842 - - - id - 5 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11237 - - - label - Open SUSE 10.3 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20070101T00:00:00 - - - author_id - 248842 - - - id - 6 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11238 - - - label - Debian 4 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20070101T00:00:00 - - - author_id - 248842 - - - id - 7 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11239 - - - label - Fedora Core 8 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20080101T00:00:00 - - - author_id - 248842 - - - id - 8 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11240 - - - label - Open SUSE 11.0 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20080101T00:00:00 - - - author_id - 248842 - - - id - 9 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11241 - - - label - Mandriva 2008.1 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20080101T00:00:00 - - - author_id - 248842 - - - id - 10 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 11242 - - - label - Ubuntu 8.04 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20080101T00:00:00 - - - author_id - 248842 - - - id - 11 - - - - - - - date_updated - 20100922T11:56:05 - - - disk_id - 23351 - - - label - Debian 5 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20090101T00:00:00 - - - author_id - 248842 - - - id - 12 - - - - - - - date_updated - 20100811T16:30:06 - - - disk_id - 23352 - - - label - Ubuntu 9.04 - - - datacenter_id - 1 - - - visibility - all - - - os_arch - x86-32 - - - date_created - 20090101T00:00:00 - - - author_id - 248842 - - - id - 13 - - - - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/ip_list.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/ip_list.xml deleted file mode 100644 index 74cce54587..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/ip_list.xml +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - - -reverse -xvm-6-186.ghst.net - - -iface_id -7857 - - -date_updated -20110120T14:57:55 - - -ip -10.5.6.186 - - -datacenter_id -1 - - -state -created - - -num -0 - - -version -4 - - -date_created -20101028T12:49:11 - - -id -9256 - - - - -reverse -xvm6-fe37-9f7b.ghst.net - - -iface_id -7857 - - -date_updated -20110120T14:58:44 - - -ip -2001:4b98:dc0:543:216:3eff:fe37:9f7b - - -datacenter_id -1 - - -state -created - - -num -1 - - -version -6 - - -date_created -20110120T14:58:44 - - -id -9294 - - - - -reverse -xvm-6-179.ghst.net - - -iface_id -7861 - - -date_updated -20110124T15:53:44 - - -ip -10.5.6.179 - - -datacenter_id -1 - - -state -created - - -num -0 - - -version -4 - - -date_created -20110124T11:43:17 - - -id -9298 - - - - -reverse -xvm6-fea8-3724.ghst.net - - -iface_id -7861 - - -date_updated -20110124T15:54:44 - - -ip -2001:4b98:dc0:543:216:3eff:fea8:3724 - - -datacenter_id -1 - - -state -created - - -num -1 - - -version -6 - - -date_created -20110124T15:54:44 - - -id -9301 - - - - -reverse - - - -iface_id - - - -date_updated -20110217T17:39:39 - - -ip - - - -datacenter_id -1 - - -state -being_created - - -num - - - -version -4 - - -date_created -20110217T17:39:39 - - -id -9323 - - - - -reverse -xvm-6-26.ghst.net - - -iface_id - - - -date_updated -20110225T11:59:55 - - -ip -10.5.6.26 - - -datacenter_id -1 - - -state -created - - -num -0 - - -version -4 - - -date_created -20110224T16:46:33 - - -id -9332 - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/operation_info.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/operation_info.xml deleted file mode 100644 index 33163438a0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/operation_info.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - -date_updated -20110324T15:49:50 - - -last_error - - - -date_start - - - -source -AB3917-GANDI - - -step -DONE - - -eta -39 - - -date_created -20110324T15:49:32 - - -type -vm_delete - - -id -637366 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_create_from.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_create_from.xml deleted file mode 100644 index eda889a3c3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_create_from.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - -iface_id - - - -date_updated -20110324T17:14:06 - - -type -disk_create - - -date_start - - - -disk_id -35170 - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110324T17:14:06 - - -vm_id - - - -id -637370 - - - - -iface_id -8019 - - -date_updated -20110324T17:14:06 - - -vm_id - - - -date_start - - - -disk_id - - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id -9298 - - -date_created -20110324T17:14:06 - - -type -iface_create - - -id -637371 - - - - -iface_id - - - -date_updated -20110324T17:14:07 - - -type -vm_create - - -date_start - - - -disk_id - - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110324T17:14:07 - - -vm_id -250288 - - -id -637372 - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_delete.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_delete.xml deleted file mode 100644 index a731b41032..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_delete.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id - - - -date_updated -20110324T15:49:32 - - -vm_id -250136 - - -date_start - - - -disk_id - - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110324T15:49:32 - - -type -vm_delete - - -id -637366 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_info.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_info.xml deleted file mode 100644 index 5b01c94ced..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_info.xml +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - -memory -256 - - -hostname -test2 - - -console -0 - - -description - - - -triggers - - - - -date_updated -20110120T15:25:07 - - -disks - - - -datacenter_id -1 - - -name -test2 - - -kernel_version -2.6.32 - - -can_snapshot - - - -kernel_cmdline - - -root -/dev/xvda1 - - -ro -1 - - -console -xvc0 - - -nosep -1 - - - - -visibility -private - - -label -Debian 5 - - -vms_id - -250133 - - - -source -23351 - - -state -running - - -is_boot_disk -1 - - -date_updated -20110120T15:02:01 - - -date_created -20110120T14:57:55 - - -type -data - - -id -34951 - - -size -3072 - - - - - -disks_id - -34951 - - - -datacenter_id -1 - - -state -running - - -flex_shares -0 - - -ai_active -0 - - -vm_max_memory -2048 - - -ifaces - - - -date_updated -20110120T14:58:44 - - -vm_id -250133 - - -bandwidth -5120.0 - - -datacenter_id -1 - - -ips - - - -reverse -xvm-6-186.ghst.net - - -iface_id -7857 - - -date_updated -20110120T14:57:55 - - -ip -10.5.6.186 - - -datacenter_id -1 - - -state -created - - -num -0 - - -version -4 - - -date_created -20101028T12:49:11 - - -id -9256 - - - - -reverse -xvm6-fe37-9f7b.ghst.net - - -iface_id -7857 - - -date_updated -20110120T14:58:44 - - -ip -2001:4b98:dc0:543:216:3eff:fe37:9f7b - - -datacenter_id -1 - - -state -created - - -num -1 - - -version -6 - - -date_created -20110120T14:58:44 - - -id -9294 - - - - - -state -used - - -num -0 - - -ips_id - -9256 -9294 - - - -date_created -20110120T14:57:55 - - -type -public - - -id -7857 - - - - - -cores -1 - - -ifaces_id - -7857 - - - -graph_urls - - -vcpu - -http://graph.dev.hosting.gandi.net:8080//?key=88a6b2a04f21c3b9c055d73310ee37ea47fe25c7&vm_id=379&dc_id=1&stats_target=vcpu&device_number=0 - - - -vdi - -http://graph.dev.hosting.gandi.net:8080//?key=88a6b2a04f21c3b9c055d73310ee37ea47fe25c7&vm_id=379&dc_id=1&stats_target=vdi&device_number=0 - - - -vif - -http://graph.dev.hosting.gandi.net:8080//?key=88a6b2a04f21c3b9c055d73310ee37ea47fe25c7&vm_id=379&dc_id=1&stats_target=vif&device_number=0 - - - - - -date_created -20110120T14:57:55 - - -id -250133 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_list.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_list.xml deleted file mode 100644 index d0f40729ca..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_list.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - -memory -256 - - -console -0 - - -description - - - -date_updated -20110120T15:25:07 - - -hostname -test1 - - -disks_id - -34951 - - - -datacenter_id -1 - - -state -running - - -flex_shares -0 - - -ai_active -0 - - -vm_max_memory -2048 - - -cores -1 - - -ifaces_id - -7857 - - - -date_created -20110120T14:57:55 - - -id -250133 - - - - -memory -256 - - -console -0 - - -description - - - -date_updated -20110225T12:09:31 - - -hostname -test2 - - -disks_id - -34954 - - - -datacenter_id -1 - - -state -halted - - -flex_shares -0 - - -ai_active -0 - - -vm_max_memory -2048 - - -cores -1 - - -ifaces_id - -7861 - - - -date_created -20110124T15:53:44 - - -id -250136 - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_reboot.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_reboot.xml deleted file mode 100644 index 4a8aab2fa1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_reboot.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id - - - -date_updated -20110325T13:18:27 - - -vm_id -250133 - - -date_start - - - -disk_id - - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110325T13:18:27 - - -type -vm_reboot - - -id -637398 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_stop.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_stop.xml deleted file mode 100644 index 67461fb291..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gandi/vm_stop.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -iface_id - - - -date_updated -20110325T13:19:52 - - -vm_id -250133 - - -date_start - - - -disk_id - - - -source -AB3917-GANDI - - -step -WAIT - - -ip_id - - - -date_created -20110325T13:19:52 - - -type -vm_stop - - -id -637399 - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_addresses.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_addresses.json deleted file mode 100644 index 4bab3a2bc4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_addresses.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "id": "projects/project_name/aggregated/addresses", - "items": { - "regions/europe-west1": { - "addresses": [ - { - "address": "192.158.29.247", - "creationTimestamp": "2013-06-26T09:51:47.506-07:00", - "description": "", - "id": "10955781597205896134", - "kind": "compute#address", - "name": "libcloud-demo-europe-address", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1/addresses/libcloud-demo-europe-address", - "status": "RESERVED" - } - ] - }, - "regions/us-central1": { - "addresses": [ - { - "address": "173.255.113.20", - "creationTimestamp": "2013-06-26T12:21:40.625-07:00", - "description": "", - "id": "01531551729918243104", - "kind": "compute#address", - "name": "lcaddress", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", - "status": "RESERVED" - }, - { - "address": "108.59.82.4", - "creationTimestamp": "2013-06-26T09:48:31.184-07:00", - "description": "", - "id": "17634862894218443422", - "kind": "compute#address", - "name": "libcloud-demo-address", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/libcloud-demo-address", - "status": "RESERVED" - }, - { - "address": "173.255.114.104", - "creationTimestamp": "2013-06-04T16:28:43.764-07:00", - "description": "", - "id": "11879548153827627972", - "kind": "compute#address", - "name": "testaddress", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/testaddress", - "status": "RESERVED" - } - ] - }, - "regions/us-central2": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "regions/us-central2" - } - ], - "message": "There are no results for scope 'regions/us-central2' on this page." - } - } - }, - "kind": "compute#addressAggregatedList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/addresses" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_disks.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_disks.json deleted file mode 100644 index 9133041802..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_disks.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "id": "projects/project_name/aggregated/disks", - "items": { - "zones/europe-west1-a": { - "disks": [ - { - "creationTimestamp": "2013-12-13T10:43:33.753-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "0819226106922408217", - "kind": "compute#disk", - "name": "libcloud-demo-europe-boot-disk", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-boot-disk", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - }, - { - "creationTimestamp": "2013-12-13T10:43:20.420-08:00", - "id": "30789070506648158", - "kind": "compute#disk", - "name": "libcloud-demo-europe-attach-disk", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-attach-disk", - "sizeGb": "1", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - }, - { - "creationTimestamp": "2013-12-13T10:43:07.390-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "01221310665639400697", - "kind": "compute#disk", - "name": "libcloud-demo-europe-np-node", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-np-node", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - }, - { - "creationTimestamp": "2013-12-13T10:43:53.598-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "17495188440080825940", - "kind": "compute#disk", - "name": "libcloud-demo-europe-multiple-nodes-000", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-multiple-nodes-000", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - } - ] - }, - "zones/europe-west1-b": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "zones/europe-west1-b" - } - ], - "message": "There are no results for scope 'zones/europe-west1-b' on this page." - } - }, - "zones/us-central1-a": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "zones/us-central1-a" - } - ], - "message": "There are no results for scope 'zones/us-central1-a' on this page." - } - }, - "zones/us-central1-b": { - "disks": [ - { - "creationTimestamp": "2013-09-04T11:03:54.122-07:00", - "description": "Persistent boot disk created from https://www.googleapis.com/compute/v1beta15/projects/debian-cloud/global/images/debian-7-wheezy-v20130723.", - "id": "8658241308250794904", - "kind": "compute#disk", - "name": "test1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/test1", - "sizeGb": "10", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" - } - ] - }, - "zones/us-central2-a": { - "disks": [ - { - "creationTimestamp": "2013-12-13T10:41:59.430-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "3371304879167251249", - "kind": "compute#disk", - "name": "libcloud-demo-boot-disk", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-boot-disk", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - }, - { - "creationTimestamp": "2013-12-13T10:42:15.355-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "12650345960824309663", - "kind": "compute#disk", - "name": "libcloud-demo-multiple-nodes-000", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-000", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - }, - { - "creationTimestamp": "2013-12-13T10:41:52.533-08:00", - "id": "01867312924613359214", - "kind": "compute#disk", - "name": "libcloud-demo-attach-disk", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-attach-disk", - "sizeGb": "1", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - }, - { - "creationTimestamp": "2013-12-13T10:42:15.949-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "12498700959701905851", - "kind": "compute#disk", - "name": "libcloud-demo-multiple-nodes-001", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-001", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - }, - { - "creationTimestamp": "2013-12-13T10:41:44.063-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "345757781195247006", - "kind": "compute#disk", - "name": "libcloud-demo-np-node", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-np-node", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - } - ] - } - }, - "kind": "compute#diskAggregatedList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/disks" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_forwardingRules.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_forwardingRules.json deleted file mode 100644 index 06a1a0e880..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_forwardingRules.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "id": "projects/project_name/aggregated/forwardingRules", - "items": { - "regions/europe-west1": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "regions/europe-west1" - } - ], - "message": "There are no results for scope 'regions/europe-west1' on this page." - } - }, - "regions/us-central1": { - "forwardingRules": [ - { - "IPAddress": "108.59.86.60", - "IPProtocol": "TCP", - "creationTimestamp": "2013-12-13T10:51:47.602-08:00", - "id": "0401221837226610637", - "kind": "compute#forwardingRule", - "name": "libcloud-lb-demo-lb", - "portRange": "80-80", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/libcloud-lb-demo-lb", - "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" - }, - { - "IPAddress": "173.255.114.35", - "IPProtocol": "TCP", - "creationTimestamp": "2013-12-13T10:52:57.170-08:00", - "id": "06342111469679701315", - "kind": "compute#forwardingRule", - "name": "lcforwardingrule", - "portRange": "8000-8500", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", - "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" - } - ] - }, - "regions/us-central2": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "regions/us-central2" - } - ], - "message": "There are no results for scope 'regions/us-central2' on this page." - } - } - }, - "kind": "compute#forwardingRuleAggregatedList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/forwardingRules" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_instances.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_instances.json deleted file mode 100644 index 3624fd0c82..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_instances.json +++ /dev/null @@ -1,466 +0,0 @@ -{ - "id": "projects/project_name/aggregated/instances", - "items": { - "zones/europe-west1-a": { - "instances": [ - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:43:58.782-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-europe-multiple-nodes-000", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-multiple-nodes-000", - "type": "PERSISTENT" - } - ], - "id": "10947706194464948790", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-europe-multiple-nodes-000", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "192.158.28.252", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.122.85" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-multiple-nodes-000", - "status": "RUNNING", - "tags": { - "fingerprint": "W7t6ZyTyIrc=", - "items": [ - "libcloud" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - }, - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:43:37.267-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-europe-boot-disk", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-boot-disk", - "type": "PERSISTENT" - } - ], - "id": "517678477070693411", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-europe-persist-node", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.251.128.32", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.240.204" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-persist-node", - "status": "RUNNING", - "tags": { - "fingerprint": "EbZdwVRtKyg=", - "items": [ - "libcloud", - "newtag" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - }, - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:43:12.706-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-europe-np-node", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-np-node", - "type": "PERSISTENT" - }, - { - "deviceName": "libcloud-demo-europe-attach-disk", - "index": 1, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-attach-disk", - "type": "PERSISTENT" - } - ], - "id": "3421745795082776097", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-europe-np-node", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.251.128.10", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.221.125" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", - "status": "RUNNING", - "tags": { - "fingerprint": "W7t6ZyTyIrc=", - "items": [ - "libcloud" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - } - ] - }, - "zones/europe-west1-b": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "zones/europe-west1-b" - } - ], - "message": "There are no results for scope 'zones/europe-west1-b' on this page." - } - }, - "zones/us-central1-a": { - "instances": [ - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:45:23.351-08:00", - "disks": [ - { - "boot": true, - "deviceName": "persistent-disk-0", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", - "type": "PERSISTENT" - } - ], - "id": "4006034190819017667", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "node-name", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.236.58.15", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.72.75" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "status": "RUNNING", - "tags": { - "fingerprint": "42WmSpB8rSM=" - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" - } - ] - }, - "zones/us-central1-b": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "zones/us-central1-b" - } - ], - "message": "There are no results for scope 'zones/us-central1-b' on this page." - } - }, - "zones/us-central2-a": { - "instances": [ - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:42:03.180-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-boot-disk", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-boot-disk", - "type": "PERSISTENT" - } - ], - "id": "2184470466384636715", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-persist-node", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "173.255.120.70", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.235.148" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-persist-node", - "status": "RUNNING", - "tags": { - "fingerprint": "EbZdwVRtKyg=", - "items": [ - "libcloud", - "newtag" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - }, - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:41:47.059-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-np-node", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-np-node", - "type": "PERSISTENT" - }, - { - "deviceName": "libcloud-demo-attach-disk", - "index": 1, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-attach-disk", - "type": "PERSISTENT" - } - ], - "id": "18059053700460342373", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-np-node", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "173.255.120.58", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.45.206" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-np-node", - "status": "RUNNING", - "tags": { - "fingerprint": "W7t6ZyTyIrc=", - "items": [ - "libcloud" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - }, - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:42:24.841-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-multiple-nodes-000", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-000", - "type": "PERSISTENT" - } - ], - "id": "4196532528539285480", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-multiple-nodes-000", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "173.255.120.211", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.218.251" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-multiple-nodes-000", - "status": "RUNNING", - "tags": { - "fingerprint": "W7t6ZyTyIrc=", - "items": [ - "libcloud" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - }, - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:42:19.041-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-multiple-nodes-001", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-001", - "type": "PERSISTENT" - } - ], - "id": "1066146046261788296", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-multiple-nodes-001", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "173.255.120.207", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.24.29" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-multiple-nodes-001", - "status": "RUNNING", - "tags": { - "fingerprint": "W7t6ZyTyIrc=", - "items": [ - "libcloud" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - } - ] - } - }, - "kind": "compute#instanceAggregatedList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/instances" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_machineTypes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_machineTypes.json deleted file mode 100644 index e8da4f84f6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_machineTypes.json +++ /dev/null @@ -1,1908 +0,0 @@ -{ - "id": "projects/project_name/aggregated/machineTypes", - "items": { - "zones/europe-west1-a": { - "machineTypes": [ - { - "creationTimestamp": "2012-11-16T11:43:17.400-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "05095504563332567951", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-4-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:48:06.087-08:00", - "description": "4 vCPUs, 3.6 GB RAM", - "guestCpus": 4, - "id": "04759000181765218034", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-4", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:51:04.549-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "02507333096579477005", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-8-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:44:25.985-08:00", - "description": "8 vCPUs, 52 GB RAM", - "guestCpus": 8, - "id": "01717932668777642040", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-8", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2013-04-25T13:32:49.088-07:00", - "description": "1 vCPU (shared physical core) and 0.6 GB RAM", - "guestCpus": 1, - "id": "1133568312750571513", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 614, - "name": "f1-micro", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/f1-micro", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:34.258-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "state": "DEPRECATED" - }, - "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", - "guestCpus": 1, - "id": "10583029372018866711", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1-d", - "scratchDisks": [ - { - "diskGb": 420 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:46:10.572-08:00", - "description": "2 vCPUs, 1.8 GB RAM", - "guestCpus": 2, - "id": "16898271314080235997", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-2", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:45:08.195-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "07181827135536388552", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-8-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-06-07T13:49:19.448-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "06313284160910191442", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-2-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:49:07.563-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "01151097524490134507", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-4-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:06.129-08:00", - "description": "2 vCPUs, 13 GB RAM", - "guestCpus": 2, - "id": "05438694236916301519", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-2", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:56.867-07:00", - "description": "2 vCPUs, 7.5 GB RAM", - "guestCpus": 2, - "id": "17936898073622676356", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-2", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2013-04-25T13:32:45.550-07:00", - "description": "1 vCPU (shared physical core) and 1.7 GB RAM", - "guestCpus": 1, - "id": "1500265464823777597", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 1740, - "name": "g1-small", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/g1-small", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:59.630-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "00770157291441082211", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-2-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-06-07T13:49:40.050-07:00", - "description": "4 vCPUs, 15 GB RAM", - "guestCpus": 4, - "id": "09494636486174545828", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-4", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:50:15.128-08:00", - "description": "8 vCPUs, 7.2 GB RAM", - "guestCpus": 8, - "id": "01206886442411821831", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-8", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:42:08.983-08:00", - "description": "4 vCPUs, 26 GB RAM", - "guestCpus": 4, - "id": "11556032176405786676", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-4", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-11-16T11:47:07.825-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "15178384466070744001", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-2-d", - "zone": "europe-west1-a" - }, - { - "creationTimestamp": "2012-06-07T13:50:05.677-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "00523085164784013586", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-4-d", - "zone": "europe-west1-a" - } - ] - }, - "zones/europe-west1-b": { - "machineTypes": [ - { - "creationTimestamp": "2012-11-16T11:43:17.400-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "05095504563332567951", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-4-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:45:08.195-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "07181827135536388552", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-8-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2013-04-25T13:32:49.088-07:00", - "description": "1 vCPU (shared physical core) and 0.6 GB RAM", - "guestCpus": 1, - "id": "1133568312750571513", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 614, - "name": "f1-micro", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/f1-micro", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:40:59.630-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "00770157291441082211", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-2-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:40:06.129-08:00", - "description": "2 vCPUs, 13 GB RAM", - "guestCpus": 2, - "id": "05438694236916301519", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-2", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:47:07.825-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "15178384466070744001", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-2-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-06-07T13:48:56.867-07:00", - "description": "2 vCPUs, 7.5 GB RAM", - "guestCpus": 2, - "id": "17936898073622676356", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-2", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:50:15.128-08:00", - "description": "8 vCPUs, 7.2 GB RAM", - "guestCpus": 8, - "id": "01206886442411821831", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-8", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:44:25.985-08:00", - "description": "8 vCPUs, 52 GB RAM", - "guestCpus": 8, - "id": "01717932668777642040", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-8", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2013-04-25T13:32:45.550-07:00", - "description": "1 vCPU (shared physical core) and 1.7 GB RAM", - "guestCpus": 1, - "id": "1500265464823777597", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 1740, - "name": "g1-small", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/g1-small", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-06-07T13:49:19.448-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "06313284160910191442", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-2-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-06-07T13:50:05.677-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "00523085164784013586", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-4-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:49:07.563-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "01151097524490134507", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-4-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-06-07T13:48:34.258-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-1", - "state": "DEPRECATED" - }, - "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", - "guestCpus": 1, - "id": "10583029372018866711", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1-d", - "scratchDisks": [ - { - "diskGb": 420 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-1-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-1", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:48:06.087-08:00", - "description": "4 vCPUs, 3.6 GB RAM", - "guestCpus": 4, - "id": "04759000181765218034", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-4", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:46:10.572-08:00", - "description": "2 vCPUs, 1.8 GB RAM", - "guestCpus": 2, - "id": "16898271314080235997", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-2", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-06-07T13:49:40.050-07:00", - "description": "4 vCPUs, 15 GB RAM", - "guestCpus": 4, - "id": "09494636486174545828", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-4", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:51:04.549-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "02507333096579477005", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-8-d", - "zone": "europe-west1-b" - }, - { - "creationTimestamp": "2012-11-16T11:42:08.983-08:00", - "description": "4 vCPUs, 26 GB RAM", - "guestCpus": 4, - "id": "11556032176405786676", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-4", - "zone": "europe-west1-b" - } - ] - }, - "zones/us-central1-a": { - "machineTypes": [ - { - "creationTimestamp": "2012-06-07T13:49:40.050-07:00", - "description": "4 vCPUs, 15 GB RAM", - "guestCpus": 4, - "id": "09494636486174545828", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:47:07.825-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "15178384466070744001", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2013-04-25T13:32:45.550-07:00", - "description": "1 vCPU (shared physical core) and 1.7 GB RAM", - "guestCpus": 1, - "id": "1500265464823777597", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 1740, - "name": "g1-small", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/g1-small", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:49:19.448-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "06313284160910191442", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2013-04-25T13:32:49.088-07:00", - "description": "1 vCPU (shared physical core) and 0.6 GB RAM", - "guestCpus": 1, - "id": "1133568312750571513", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 614, - "name": "f1-micro", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/f1-micro", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:49:07.563-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "01151097524490134507", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:48:06.087-08:00", - "description": "4 vCPUs, 3.6 GB RAM", - "guestCpus": 4, - "id": "04759000181765218034", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:59.630-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "00770157291441082211", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:43:17.400-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "05095504563332567951", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:45:08.195-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "07181827135536388552", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:56.867-07:00", - "description": "2 vCPUs, 7.5 GB RAM", - "guestCpus": 2, - "id": "17936898073622676356", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:34.258-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "state": "DEPRECATED" - }, - "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", - "guestCpus": 1, - "id": "10583029372018866711", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1-d", - "scratchDisks": [ - { - "diskGb": 420 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:46:10.572-08:00", - "description": "2 vCPUs, 1.8 GB RAM", - "guestCpus": 2, - "id": "16898271314080235997", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:50:15.128-08:00", - "description": "8 vCPUs, 7.2 GB RAM", - "guestCpus": 8, - "id": "01206886442411821831", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:42:08.983-08:00", - "description": "4 vCPUs, 26 GB RAM", - "guestCpus": 4, - "id": "11556032176405786676", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:44:25.985-08:00", - "description": "8 vCPUs, 52 GB RAM", - "guestCpus": 8, - "id": "01717932668777642040", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:06.129-08:00", - "description": "2 vCPUs, 13 GB RAM", - "guestCpus": 2, - "id": "05438694236916301519", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:50:05.677-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "00523085164784013586", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:51:04.549-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "02507333096579477005", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8-d", - "zone": "us-central1-a" - } - ] - }, - "zones/us-central1-b": { - "machineTypes": [ - { - "creationTimestamp": "2013-04-25T13:32:45.550-07:00", - "description": "1 vCPU (shared physical core) and 1.7 GB RAM", - "guestCpus": 1, - "id": "1500265464823777597", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 1740, - "name": "g1-small", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/g1-small", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:40:59.630-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "00770157291441082211", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-2-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:51:04.549-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "02507333096579477005", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-8-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:46:10.572-08:00", - "description": "2 vCPUs, 1.8 GB RAM", - "guestCpus": 2, - "id": "16898271314080235997", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-2", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:44:25.985-08:00", - "description": "8 vCPUs, 52 GB RAM", - "guestCpus": 8, - "id": "01717932668777642040", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-8", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:42:08.983-08:00", - "description": "4 vCPUs, 26 GB RAM", - "guestCpus": 4, - "id": "11556032176405786676", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-4", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2013-04-25T13:32:49.088-07:00", - "description": "1 vCPU (shared physical core) and 0.6 GB RAM", - "guestCpus": 1, - "id": "1133568312750571513", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 614, - "name": "f1-micro", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/f1-micro", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-06-07T13:50:05.677-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "00523085164784013586", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-4-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:47:07.825-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "15178384466070744001", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-2-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:43:17.400-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "05095504563332567951", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-4-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-06-07T13:48:56.867-07:00", - "description": "2 vCPUs, 7.5 GB RAM", - "guestCpus": 2, - "id": "17936898073622676356", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-2", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:48:06.087-08:00", - "description": "4 vCPUs, 3.6 GB RAM", - "guestCpus": 4, - "id": "04759000181765218034", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-4", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:50:15.128-08:00", - "description": "8 vCPUs, 7.2 GB RAM", - "guestCpus": 8, - "id": "01206886442411821831", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-8", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:49:07.563-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "01151097524490134507", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-4-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:45:08.195-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "07181827135536388552", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-8-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-06-07T13:49:40.050-07:00", - "description": "4 vCPUs, 15 GB RAM", - "guestCpus": 4, - "id": "09494636486174545828", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-4", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-06-07T13:49:19.448-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "06313284160910191442", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-2-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-11-16T11:40:06.129-08:00", - "description": "2 vCPUs, 13 GB RAM", - "guestCpus": 2, - "id": "05438694236916301519", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-2", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-06-07T13:48:34.258-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", - "state": "DEPRECATED" - }, - "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", - "guestCpus": 1, - "id": "10583029372018866711", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1-d", - "scratchDisks": [ - { - "diskGb": 420 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1-d", - "zone": "us-central1-b" - }, - { - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", - "zone": "us-central1-b" - } - ] - }, - "zones/us-central2-a": { - "machineTypes": [ - { - "creationTimestamp": "2012-06-07T13:49:40.050-07:00", - "description": "4 vCPUs, 15 GB RAM", - "guestCpus": 4, - "id": "09494636486174545828", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-4", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:56.867-07:00", - "description": "2 vCPUs, 7.5 GB RAM", - "guestCpus": 2, - "id": "17936898073622676356", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-2", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:48:06.087-08:00", - "description": "4 vCPUs, 3.6 GB RAM", - "guestCpus": 4, - "id": "04759000181765218034", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-4", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2013-04-25T13:32:45.550-07:00", - "description": "1 vCPU (shared physical core) and 1.7 GB RAM", - "guestCpus": 1, - "id": "1500265464823777597", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 1740, - "name": "g1-small", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/g1-small", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:47:07.825-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "15178384466070744001", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-2-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:59.630-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "00770157291441082211", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-2-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2013-04-25T13:32:49.088-07:00", - "description": "1 vCPU (shared physical core) and 0.6 GB RAM", - "guestCpus": 1, - "id": "1133568312750571513", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 614, - "name": "f1-micro", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/f1-micro", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:42:08.983-08:00", - "description": "4 vCPUs, 26 GB RAM", - "guestCpus": 4, - "id": "11556032176405786676", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-4", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:51:04.549-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "02507333096579477005", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-8-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:44:25.985-08:00", - "description": "8 vCPUs, 52 GB RAM", - "guestCpus": 8, - "id": "01717932668777642040", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-8", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-06-07T13:50:05.677-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "00523085164784013586", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-4-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-06-07T13:49:19.448-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "06313284160910191442", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-2-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:50:15.128-08:00", - "description": "8 vCPUs, 7.2 GB RAM", - "guestCpus": 8, - "id": "01206886442411821831", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-8", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:45:08.195-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "07181827135536388552", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-8-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:43:17.400-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "05095504563332567951", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-4-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:46:10.572-08:00", - "description": "2 vCPUs, 1.8 GB RAM", - "guestCpus": 2, - "id": "16898271314080235997", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-2", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:06.129-08:00", - "description": "2 vCPUs, 13 GB RAM", - "guestCpus": 2, - "id": "05438694236916301519", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-2", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-11-16T11:49:07.563-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "01151097524490134507", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-4-d", - "zone": "us-central2-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:34.258-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", - "state": "DEPRECATED" - }, - "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", - "guestCpus": 1, - "id": "10583029372018866711", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1-d", - "scratchDisks": [ - { - "diskGb": 420 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1-d", - "zone": "us-central2-a" - } - ] - } - }, - "kind": "compute#machineTypeAggregatedList", - "nextPageToken": "ChhQRVJfUFJPSkVDVF9NQUNISU5FX1RZUEUSGjYwMDUzMTk1NTY3NS5uMS1zdGFuZGFyZC04", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/machineTypes" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_targetPools.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_targetPools.json deleted file mode 100644 index 565e323abd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/aggregated_targetPools.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "id": "projects/project_name/aggregated/targetPools", - "items": { - "regions/europe-west1": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "regions/europe-west1" - } - ], - "message": "There are no results for scope 'regions/europe-west1' on this page." - } - }, - "regions/us-central1": { - "targetPools": [ - { - "creationTimestamp": "2013-11-01T14:50:04.620-07:00", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" - ], - "id": "6918395933376220338", - "instances": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" - ], - "kind": "compute#targetPool", - "name": "libcloud-lb-demo-lb-tp", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" - }, - { - "creationTimestamp": "2013-11-01T14:51:45.822-07:00", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" - ], - "id": "2277093827336176997", - "instances": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" - ], - "kind": "compute#targetPool", - "name": "lctargetpool", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" - }, - { - "creationTimestamp": "2013-11-01T12:09:45.831-07:00", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check" - ], - "id": "03531496913089065061", - "kind": "compute#targetPool", - "name": "www-pool", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/www-pool", - "sessionAffinity": "NONE" - } - ] - }, - "regions/us-central2": { - "warning": { - "code": "NO_RESULTS_ON_PAGE", - "data": [ - { - "key": "scope", - "value": "regions/us-central2" - } - ], - "message": "There are no results for scope 'regions/us-central2' on this page." - } - } - }, - "kind": "compute#targetPoolAggregatedList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/targetPools" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/generic_disk.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/generic_disk.json deleted file mode 100644 index b0d646b7e2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/generic_disk.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "creationTimestamp": "2013-12-13T10:54:04.074-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "3535838963674672928", - "kind": "compute#disk", - "name": "genericdisk", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/genericdisk", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls.json deleted file mode 100644 index 8348658512..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "id": "projects/project_name/global/firewalls", - "items": [ - { - "allowed": [ - { - "IPProtocol": "udp" - }, - { - "IPProtocol": "tcp" - }, - { - "IPProtocol": "icmp" - } - ], - "creationTimestamp": "2013-06-25T19:50:41.630-07:00", - "description": "", - "id": "5399576268464751692", - "kind": "compute#firewall", - "name": "default-allow-internal", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/default-allow-internal", - "sourceRanges": [ - "10.240.0.0/16" - ] - }, - { - "allowed": [ - { - "IPProtocol": "tcp", - "ports": [ - "22" - ] - } - ], - "creationTimestamp": "2013-06-25T19:48:25.111-07:00", - "description": "", - "id": "8063006729705804986", - "kind": "compute#firewall", - "name": "default-ssh", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/default-ssh", - "sourceRanges": [ - "0.0.0.0/0" - ] - }, - { - "allowed": [ - { - "IPProtocol": "tcp", - "ports": [ - "3141" - ] - } - ], - "creationTimestamp": "2013-11-01T14:46:25.155-07:00", - "id": "13827675544891616808", - "kind": "compute#firewall", - "name": "libcloud-demo-europe-firewall", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-europe-network", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/libcloud-demo-europe-firewall", - "sourceRanges": [ - "0.0.0.0/0" - ], - "sourceTags": [ - "libcloud" - ] - }, - { - "allowed": [ - { - "IPProtocol": "tcp", - "ports": [ - "3141" - ] - } - ], - "creationTimestamp": "2013-11-01T14:44:31.284-07:00", - "id": "1648761630208029546", - "kind": "compute#firewall", - "name": "libcloud-demo-firewall", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-network", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/libcloud-demo-firewall", - "sourceRanges": [ - "0.0.0.0/0" - ], - "sourceTags": [ - "libcloud" - ] - }, - { - "allowed": [ - { - "IPProtocol": "tcp", - "ports": [ - "80" - ] - } - ], - "creationTimestamp": "2013-08-19T14:40:22.562-07:00", - "description": "", - "id": "01326795494450101956", - "kind": "compute#firewall", - "name": "www-firewall", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/www-firewall", - "sourceRanges": [ - "0.0.0.0/0" - ], - "targetTags": [ - "www-tag" - ] - } - ], - "kind": "compute#firewallList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall.json deleted file mode 100644 index 51f1d914d6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "allowed": [ - { - "IPProtocol": "tcp", - "ports": [ - "4567" - ] - } - ], - "creationTimestamp": "2013-06-26T10:04:43.773-07:00", - "id": "0565629596395414121", - "kind": "compute#firewall", - "name": "lcfirewall", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", - "sourceTags": [ - "libcloud" - ] -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_delete.json deleted file mode 100644 index cc0a508d7a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "8983098895755095934", - "insertTime": "2013-06-26T10:04:53.453-07:00", - "kind": "compute#operation", - "name": "operation-global_firewalls_lcfirewall_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_delete", - "startTime": "2013-06-26T10:04:53.508-07:00", - "status": "PENDING", - "targetId": "0565629596395414121", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_put.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_put.json deleted file mode 100644 index 47f9d8f98f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_put.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "6526551968265354277", - "insertTime": "2013-06-26T20:52:00.355-07:00", - "kind": "compute#operation", - "name": "operation-global_firewalls_lcfirewall_put", - "operationType": "update", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_put", - "startTime": "2013-06-26T20:52:00.410-07:00", - "status": "PENDING", - "targetId": "10942695305090163011", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_post.json deleted file mode 100644 index 5e77ca1de5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_firewalls_post.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "16789512465352307784", - "insertTime": "2013-06-26T20:51:06.068-07:00", - "kind": "compute#operation", - "name": "operation-global_firewalls_post", - "operationType": "insert", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_post", - "startTime": "2013-06-26T20:51:06.128-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks.json deleted file mode 100644 index e1f25a6864..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "id": "projects/project_name/global/httpHealthChecks", - "items": [ - { - "checkIntervalSec": 5, - "creationTimestamp": "2013-08-19T14:42:28.947-07:00", - "description": "", - "healthyThreshold": 2, - "host": "", - "id": "7660832580304455442", - "kind": "compute#httpHealthCheck", - "name": "basic-check", - "port": 80, - "requestPath": "/", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check", - "timeoutSec": 5, - "unhealthyThreshold": 2 - }, - { - "checkIntervalSec": 10, - "creationTimestamp": "2013-12-13T10:52:46.800-08:00", - "healthyThreshold": 3, - "host": "lchost", - "id": "022194976205566532", - "kind": "compute#httpHealthCheck", - "name": "lchealthcheck", - "port": 9000, - "requestPath": "/lc", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/lchealthcheck", - "timeoutSec": 10, - "unhealthyThreshold": 4 - }, - { - "checkIntervalSec": 5, - "creationTimestamp": "2013-12-13T10:51:42.762-08:00", - "healthyThreshold": 2, - "id": "08359377740909791076", - "kind": "compute#httpHealthCheck", - "name": "libcloud-lb-demo-healthcheck", - "port": 80, - "requestPath": "/", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck", - "timeoutSec": 5, - "unhealthyThreshold": 2 - } - ], - "kind": "compute#httpHealthCheckList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_basic-check.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_basic-check.json deleted file mode 100644 index c29f271e57..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_basic-check.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "checkIntervalSec": 5, - "creationTimestamp": "2013-08-19T14:42:28.947-07:00", - "description": "", - "healthyThreshold": 2, - "host": "", - "id": "7660832580304455442", - "kind": "compute#httpHealthCheck", - "name": "basic-check", - "port": 80, - "requestPath": "/", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check", - "timeoutSec": 5, - "unhealthyThreshold": 2 -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck.json deleted file mode 100644 index 80c9aebfe7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "checkIntervalSec": 10, - "creationTimestamp": "2013-09-02T22:18:01.180-07:00", - "healthyThreshold": 3, - "host": "lchost", - "id": "06860603312991823381", - "kind": "compute#httpHealthCheck", - "name": "lchealthcheck", - "port": 8000, - "requestPath": "/lc", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/lchealthcheck", - "timeoutSec": 10, - "unhealthyThreshold": 4 -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_delete.json deleted file mode 100644 index e8463ec454..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "1159296103027566387", - "insertTime": "2013-09-02T22:18:02.509-07:00", - "kind": "compute#operation", - "name": "operation-global_httpHealthChecks_lchealthcheck_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_delete", - "startTime": "2013-09-02T22:18:02.558-07:00", - "status": "PENDING", - "targetId": "06860603312991823381", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_put.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_put.json deleted file mode 100644 index 8ddeae3e4e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_put.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "6717642434182216609", - "insertTime": "2013-09-03T02:19:55.574-07:00", - "kind": "compute#operation", - "name": "operation-global_httpHealthChecks_lchealthcheck_put", - "operationType": "update", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_put", - "startTime": "2013-09-03T02:19:55.628-07:00", - "status": "PENDING", - "targetId": "0742691415598204878", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_libcloud-lb-demo-healthcheck.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_libcloud-lb-demo-healthcheck.json deleted file mode 100644 index 188f9e0407..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_libcloud-lb-demo-healthcheck.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "checkIntervalSec": 5, - "creationTimestamp": "2013-09-02T22:25:44.759-07:00", - "healthyThreshold": 2, - "id": "16372093408499501663", - "kind": "compute#httpHealthCheck", - "name": "libcloud-lb-demo-healthcheck", - "port": 80, - "requestPath": "/", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck", - "timeoutSec": 5, - "unhealthyThreshold": 2 -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_post.json deleted file mode 100644 index 5cd564fddf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_post.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "3903393118268087410", - "insertTime": "2013-09-03T02:19:54.629-07:00", - "kind": "compute#operation", - "name": "operation-global_httpHealthChecks_post", - "operationType": "insert", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_post", - "startTime": "2013-09-03T02:19:54.718-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images.json deleted file mode 100644 index d583b78c4e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "id": "projects/project_name/global/images", - "items": [ - { - "creationTimestamp": "2013-06-19T13:47:20.563-07:00", - "description": "Local Debian GNU/Linux 7.1 (wheezy) built on 2013-06-17", - "id": "1549141992333368759", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130617", - "preferredKernel": "https://www.googleapis.com/compute/v1/projects/google/global/kernels/gce-v20130603", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130617", - "sourceType": "RAW", - "status": "READY" - }, - { - "creationTimestamp": "2013-11-18T12:24:21.560-07:00", - "id": "1539141992335368259", - "kind": "compute#image", - "name": "centos-6-v20131118", - "preferredKernel": "https://www.googleapis.com/compute/v1/projects/google/global/kernels/gce-v20130603", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/centos-6-v20131118", - "sourceType": "RAW", - "status": "READY" - }, - { - "creationTimestamp": "2014-03-09T21:04:31.291-07:00", - "description": "CoreOS test image", - "id": "15196339658718959621", - "kind": "compute#image", - "name": "coreos", - "preferredKernel": "https://www.googleapis.com/compute/v1/projects/google/global/kernels/gce-v20130603", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/coreos", - "sourceType": "RAW", - "status": "READY" - } - ], - "kind": "compute#imageList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_debian_6_squeeze_v20130926_deprecate.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_debian_6_squeeze_v20130926_deprecate.json deleted file mode 100644 index fdc665473e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_debian_6_squeeze_v20130926_deprecate.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "status": "PENDING", - "kind": "compute#operation", - "name": "operation-1394594316110-4f4604ad0e708-2e4622ab", - "startTime": "2014-03-11T20:18:36.194-07:00", - "insertTime": "2014-03-11T20:18:36.110-07:00", - "targetId": "10034929421075729520", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/debian_6_squeeze_v20130926", - "operationType": "setDeprecation", - "progress": 0, - "id": "11223768474922166090", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-1394594316110-4f4604ad0e708-2e4622ab", - "user": "user@developer.gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20130617_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20130617_delete.json deleted file mode 100644 index 7b70942170..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20130617_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "kind": "compute#operation", - "id": "10762099380229198553", - "name": "operation-global_images_debian7_delete", - "operationType": "delete", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/debian-7-wheezy-v20130617", - "targetId": "14881612020726561163", - "status": "PENDING", - "user": "user@developer.gserviceaccount.com", - "progress": 0, - "insertTime": "2014-03-11T14:37:48.075-07:00", - "startTime": "2014-03-11T14:37:48.158-07:00", - "endTime": "2014-03-11T14:37:48.634-07:00", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_images_debian7_delete" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_post.json deleted file mode 100644 index 91ca4d3853..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_images_post.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "15196339658718959621", - "insertTime": "2014-03-09T21:04:31.228-07:00", - "kind": "compute#operation", - "name": "coreos", - "operationType": "insert", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_image_post", - "startTime": "2014-03-09T21:04:31.291-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/coreos", - "user": "897001307951@developer.gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks.json deleted file mode 100644 index dc7ca55d26..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "id": "projects/project_name/global/networks", - "items": [ - { - "IPv4Range": "10.240.0.0/16", - "creationTimestamp": "2013-06-19T12:37:13.233-07:00", - "gatewayIPv4": "10.240.0.1", - "id": "08257021638942464470", - "kind": "compute#network", - "name": "default", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default" - }, - { - "IPv4Range": "10.10.0.0/16", - "creationTimestamp": "2013-06-26T09:51:34.018-07:00", - "gatewayIPv4": "10.10.0.1", - "id": "13254259054875092094", - "kind": "compute#network", - "name": "libcloud-demo-europe-network", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-europe-network" - }, - { - "IPv4Range": "10.10.0.0/16", - "creationTimestamp": "2013-06-26T09:48:15.703-07:00", - "gatewayIPv4": "10.10.0.1", - "id": "17172579178188075621", - "kind": "compute#network", - "name": "libcloud-demo-network", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-network" - } - ], - "kind": "compute#networkList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_default.json deleted file mode 100644 index a7ddd3e8b2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_default.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "IPv4Range": "10.240.0.0/16", - "creationTimestamp": "2013-06-19T12:37:13.233-07:00", - "gatewayIPv4": "10.240.0.1", - "id": "08257021638942464470", - "kind": "compute#network", - "name": "default", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork.json deleted file mode 100644 index 5ba0d9ef56..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "IPv4Range": "10.11.0.0/16", - "creationTimestamp": "2013-06-26T10:05:03.500-07:00", - "gatewayIPv4": "10.11.0.1", - "id": "16211908079305042870", - "kind": "compute#network", - "name": "lcnetwork", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork_delete.json deleted file mode 100644 index ea6b1bbcb9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork_delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "4914541423567262393", - "insertTime": "2013-06-26T10:05:11.102-07:00", - "kind": "compute#operation", - "name": "operation-global_networks_lcnetwork_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_lcnetwork_delete", - "startTime": "2013-06-26T10:05:11.273-07:00", - "status": "PENDING", - "targetId": "16211908079305042870", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-europe-network.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-europe-network.json deleted file mode 100644 index ecb80e65dd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-europe-network.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "IPv4Range": "10.10.0.0/16", - "creationTimestamp": "2013-06-26T09:51:34.018-07:00", - "gatewayIPv4": "10.10.0.1", - "id": "13254259054875092094", - "kind": "compute#network", - "name": "libcloud-demo-europe-network", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-europe-network" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-network.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-network.json deleted file mode 100644 index 5d263253bf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-network.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "IPv4Range": "10.10.0.0/16", - "creationTimestamp": "2013-06-26T09:48:15.703-07:00", - "gatewayIPv4": "10.10.0.1", - "id": "17172579178188075621", - "kind": "compute#network", - "name": "libcloud-demo-network", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-network" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_post.json deleted file mode 100644 index 77aa7c5a44..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_networks_post.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "3681664092089171723", - "insertTime": "2013-06-26T10:05:03.271-07:00", - "kind": "compute#operation", - "name": "operation-global_networks_post", - "operationType": "insert", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_post", - "startTime": "2013-06-26T10:05:03.315-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots.json deleted file mode 100644 index d839107a7c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "id": "projects/project_name/global/snapshots", - "items": [ - { - "creationTimestamp": "2013-12-16T13:03:51.345-08:00", - "description": "", - "diskSizeGb": "1", - "id": "17482266715940883688", - "kind": "compute#snapshot", - "name": "lcsnapshot", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", - "sourceDisk": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "sourceDiskId": "-2511816066479461182", - "status": "READY" - }, - { - "creationTimestamp": "2013-12-16T12:48:12.557-08:00", - "description": "", - "diskSizeGb": "10", - "id": "3341332334980930052", - "kind": "compute#snapshot", - "name": "libcloud-demo-snapshot", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/libcloud-demo-snapshot", - "sourceDisk": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-snap-template", - "sourceDiskId": "-6245698478147030397", - "status": "READY" - } - ], - "kind": "compute#snapshotList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot.json deleted file mode 100644 index 9b071a941e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "creationTimestamp": "2013-12-16T13:03:51.345-08:00", - "description": "", - "diskSizeGb": "1", - "id": "17482266715940883688", - "kind": "compute#snapshot", - "name": "lcsnapshot", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", - "sourceDisk": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "sourceDiskId": "-2511816066479461182", - "status": "READY" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot_delete.json deleted file mode 100644 index 59cd70ce04..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot_delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "5994251357251874363", - "insertTime": "2013-12-16T13:04:03.831-08:00", - "kind": "compute#operation", - "name": "operation-global_snapshots_lcsnapshot_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_snapshots_lcsnapshot_delete", - "startTime": "2013-12-16T13:04:03.924-08:00", - "status": "PENDING", - "targetId": "17482266715940883688", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", - "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_delete.json deleted file mode 100644 index d50c5e0b25..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2013-06-26T10:05:00.978-07:00", - "id": "8983098895755095934", - "insertTime": "2013-06-26T10:04:53.453-07:00", - "kind": "compute#operation", - "name": "operation-global_firewalls_lcfirewall_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_delete", - "startTime": "2013-06-26T10:04:53.508-07:00", - "status": "DONE", - "targetId": "0565629596395414121", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_put.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_put.json deleted file mode 100644 index 225c06125b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_put.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2013-06-26T20:52:10.075-07:00", - "id": "6526551968265354277", - "insertTime": "2013-06-26T20:52:00.355-07:00", - "kind": "compute#operation", - "name": "operation-global_firewalls_lcfirewall_put", - "operationType": "update", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_put", - "startTime": "2013-06-26T20:52:00.410-07:00", - "status": "DONE", - "targetId": "10942695305090163011", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_post.json deleted file mode 100644 index 4b87327fc8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2013-06-26T20:51:12.108-07:00", - "id": "16789512465352307784", - "insertTime": "2013-06-26T20:51:06.068-07:00", - "kind": "compute#operation", - "name": "operation-global_firewalls_post", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_post", - "startTime": "2013-06-26T20:51:06.128-07:00", - "status": "DONE", - "targetId": "10942695305090163011", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_delete.json deleted file mode 100644 index 59f3d81ee8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "1159296103027566387", - "insertTime": "2013-09-02T22:18:02.509-07:00", - "kind": "compute#operation", - "name": "operation-global_httpHealthChecks_lchealthcheck_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_delete", - "startTime": "2013-09-02T22:18:02.558-07:00", - "status": "DONE", - "targetId": "06860603312991823381", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_put.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_put.json deleted file mode 100644 index 396ffc17cf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_put.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2013-09-03T02:20:02.194-07:00", - "id": "6717642434182216609", - "insertTime": "2013-09-03T02:19:55.574-07:00", - "kind": "compute#operation", - "name": "operation-global_httpHealthChecks_lchealthcheck_put", - "operationType": "update", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_put", - "startTime": "2013-09-03T02:19:55.628-07:00", - "status": "DONE", - "targetId": "0742691415598204878", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_post.json deleted file mode 100644 index 5ea8836df7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_post.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "3903393118268087410", - "insertTime": "2013-09-03T02:19:54.629-07:00", - "kind": "compute#operation", - "name": "operation-global_httpHealthChecks_post", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_post", - "startTime": "2013-09-03T02:19:54.718-07:00", - "status": "DONE", - "targetId": "0742691415598204878", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_image_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_image_post.json deleted file mode 100644 index bcd653ace0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_image_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2014-03-09T21:04:33.291-07:00", - "id": "15196339658718959621", - "insertTime": "2014-03-09T21:04:31.228-07:00", - "kind": "compute#operation", - "name": "coreos", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_image_post", - "startTime": "2014-03-09T21:04:31.291-07:00", - "status": "DONE", - "targetId": "12551176716147327315", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/coreos", - "user": "897001307951@developer.gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_images_debian7_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_images_debian7_delete.json deleted file mode 100644 index 0c085a9ecc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_images_debian7_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "kind": "compute#operation", - "id": "10762099380229198553", - "name": "operation-global_images_debian7_delete", - "operationType": "delete", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/debian-7-wheezy-v20130617", - "targetId": "14881612020726561163", - "status": "DONE", - "user": "user@developer.gserviceaccount.com", - "progress": 100, - "insertTime": "2014-03-11T14:37:48.075-07:00", - "startTime": "2014-03-11T14:37:48.158-07:00", - "endTime": "2014-03-11T14:37:48.634-07:00", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_images_debian7_delete" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_lcnetwork_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_lcnetwork_delete.json deleted file mode 100644 index 6cf88f721e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_lcnetwork_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2013-06-26T10:05:12.607-07:00", - "id": "4914541423567262393", - "insertTime": "2013-06-26T10:05:11.102-07:00", - "kind": "compute#operation", - "name": "operation-global_networks_lcnetwork_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_lcnetwork_delete", - "startTime": "2013-06-26T10:05:11.273-07:00", - "status": "DONE", - "targetId": "16211908079305042870", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_post.json deleted file mode 100644 index 5b5888bfb2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2013-06-26T10:05:07.630-07:00", - "id": "3681664092089171723", - "insertTime": "2013-06-26T10:05:03.271-07:00", - "kind": "compute#operation", - "name": "operation-global_networks_post", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_post", - "startTime": "2013-06-26T10:05:03.315-07:00", - "status": "DONE", - "targetId": "16211908079305042870", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_snapshots_lcsnapshot_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_snapshots_lcsnapshot_delete.json deleted file mode 100644 index e869f26649..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_global_snapshots_lcsnapshot_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "endTime": "2013-12-16T13:04:11.565-08:00", - "id": "5994251357251874363", - "insertTime": "2013-12-16T13:04:03.831-08:00", - "kind": "compute#operation", - "name": "operation-global_snapshots_lcsnapshot_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_snapshots_lcsnapshot_delete", - "startTime": "2013-12-16T13:04:03.924-08:00", - "status": "DONE", - "targetId": "17482266715940883688", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", - "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_lcaddress_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_lcaddress_delete.json deleted file mode 100644 index f8087600ec..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_lcaddress_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "7128783508312083402", - "insertTime": "2013-06-26T12:21:44.075-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_addresses_lcaddress_delete", - "operationType": "delete", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_lcaddress_delete", - "startTime": "2013-06-26T12:21:44.110-07:00", - "status": "DONE", - "targetId": "01531551729918243104", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_post.json deleted file mode 100644 index a68d628029..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "16064059851942653139", - "insertTime": "2013-06-26T12:21:40.299-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_addresses_post", - "operationType": "insert", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_post", - "startTime": "2013-06-26T12:21:40.358-07:00", - "status": "DONE", - "targetId": "01531551729918243104", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_lcforwardingrule_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_lcforwardingrule_delete.json deleted file mode 100644 index eb43122dac..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_lcforwardingrule_delete.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-09-03T00:17:43.917-07:00", - "id": "09064254309855814339", - "insertTime": "2013-09-03T00:17:36.062-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", - "operationType": "delete", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", - "startTime": "2013-09-03T00:17:36.168-07:00", - "status": "DONE", - "targetId": "10901665092293158938", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_post.json deleted file mode 100644 index fd2fc18591..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-09-03T00:17:33.965-07:00", - "id": "0651769405845333112", - "insertTime": "2013-09-03T00:17:25.381-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_forwardingRules_post", - "operationType": "insert", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_post", - "startTime": "2013-09-03T00:17:25.434-07:00", - "status": "DONE", - "targetId": "10901665092293158938", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json deleted file mode 100644 index 482edee6fc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-09-03T01:28:49.271-07:00", - "id": "17341029456963557514", - "insertTime": "2013-09-03T01:28:40.774-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", - "operationType": "addHealthCheck", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", - "startTime": "2013-09-03T01:28:40.838-07:00", - "status": "DONE", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addInstance_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addInstance_post.json deleted file mode 100644 index b9a28dc328..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addInstance_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-09-03T01:29:07.021-07:00", - "id": "04072826501537092633", - "insertTime": "2013-09-03T01:29:03.082-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", - "operationType": "addInstance", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", - "startTime": "2013-09-03T01:29:03.145-07:00", - "status": "DONE", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_delete.json deleted file mode 100644 index d281fe0f82..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "13500662190763995965", - "insertTime": "2013-09-03T00:51:06.799-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_delete", - "operationType": "delete", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_delete", - "startTime": "2013-09-03T00:51:06.840-07:00", - "status": "DONE", - "targetId": "13598380121688918358", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json deleted file mode 100644 index 5beb4a451f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-09-03T01:28:37.095-07:00", - "id": "14738174613993796821", - "insertTime": "2013-09-03T01:28:32.889-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", - "operationType": "removeHealthCheck", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", - "startTime": "2013-09-03T01:28:32.942-07:00", - "status": "DONE", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeInstance_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeInstance_post.json deleted file mode 100644 index 4add4041d2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeInstance_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-09-03T01:28:59.247-07:00", - "id": "1815686149437875016", - "insertTime": "2013-09-03T01:28:53.049-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", - "operationType": "removeInstance", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", - "startTime": "2013-09-03T01:28:53.109-07:00", - "status": "DONE", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_post.json deleted file mode 100644 index 5b7b4d9b1f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "7487852523793007955", - "insertTime": "2013-09-03T00:51:05.064-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_post", - "operationType": "insert", - "progress": 100, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_post", - "startTime": "2013-09-03T00:51:05.115-07:00", - "status": "DONE", - "targetId": "13598380121688918358", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_europe-west1-a_instances_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_europe-west1-a_instances_post.json deleted file mode 100644 index c9fff8ff98..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_europe-west1-a_instances_post.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "error": { - "errors": [ - { - "code": "RESOURCE_ALREADY_EXISTS", - "message": "The resource 'projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node' already exists" - } - ] - }, - "httpErrorMessage": "CONFLICT", - "httpErrorStatusCode": 409, - "id": "1510575454210533141", - "insertTime": "2013-06-26T20:57:34.366-07:00", - "kind": "compute#operation", - "name": "operation-zones_europe-west1-a_instances_post", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/operations/operation-zones_europe-west1-a_instances_post", - "startTime": "2013-06-26T20:57:34.453-07:00", - "status": "DONE", - "targetId": "14308265828754333159", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_createSnapshot_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_createSnapshot_post.json deleted file mode 100644 index f765ebfaba..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_createSnapshot_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-12-16T13:04:01.580-08:00", - "id": "0158330665043557584", - "insertTime": "2013-12-16T13:03:51.000-08:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", - "operationType": "createSnapshot", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", - "startTime": "2013-12-16T13:03:51.042-08:00", - "status": "DONE", - "targetId": "07494414044179227172", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_delete.json deleted file mode 100644 index e892ab5f40..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "06887337364510109333", - "insertTime": "2013-06-26T10:06:11.835-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_disks_lcdisk_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_delete", - "startTime": "2013-06-26T10:06:12.006-07:00", - "status": "DONE", - "targetId": "16109451798967042451", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_post.json deleted file mode 100644 index 296273007d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T16:48:25.375-07:00", - "id": "0211151278250678078", - "insertTime": "2013-06-26T16:48:17.403-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_disks_post", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_post", - "startTime": "2013-06-26T16:48:17.479-07:00", - "status": "DONE", - "targetId": "03196637868764498730", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-000_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-000_delete.json deleted file mode 100644 index 3dd003e11f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-000_delete.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T16:13:36.800-07:00", - "id": "3319596145594427549", - "insertTime": "2013-06-26T16:13:12.903-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_lcnode-000_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-000_delete", - "startTime": "2013-06-26T16:13:12.948-07:00", - "status": "DONE", - "targetId": "5390075309006132922", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-000", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-001_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-001_delete.json deleted file mode 100644 index f07a5816f5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-001_delete.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T16:13:56.931-07:00", - "id": "17469711273432628502", - "insertTime": "2013-06-26T16:13:40.579-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_lcnode-001_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-001_delete", - "startTime": "2013-06-26T16:13:40.620-07:00", - "status": "DONE", - "targetId": "16630486471904253898", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_attachDisk_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_attachDisk_post.json deleted file mode 100644 index 1962a1ca0d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_attachDisk_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T16:48:31.831-07:00", - "id": "7455886659787654716", - "insertTime": "2013-06-26T16:48:27.691-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_attachDisk_post", - "operationType": "attachDisk", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_attachDisk_post", - "startTime": "2013-06-26T16:48:27.762-07:00", - "status": "DONE", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_delete.json deleted file mode 100644 index b8137516db..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_delete.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T10:06:00.917-07:00", - "id": "6999931397447918763", - "insertTime": "2013-06-26T10:05:40.350-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_delete", - "operationType": "delete", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_delete", - "startTime": "2013-06-26T10:05:40.405-07:00", - "status": "DONE", - "targetId": "07410051435384876224", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_detachDisk_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_detachDisk_post.json deleted file mode 100644 index 3659387040..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_detachDisk_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T16:48:41.278-07:00", - "id": "3921383727105838816", - "insertTime": "2013-06-26T16:48:35.357-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_detachDisk_post", - "operationType": "detachDisk", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_detachDisk_post", - "startTime": "2013-06-26T16:48:35.398-07:00", - "status": "DONE", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_reset_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_reset_post.json deleted file mode 100644 index bbdcbac182..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_reset_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "10507122129283663728", - "insertTime": "2013-06-26T15:03:02.766-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_reset_post", - "operationType": "reset", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_reset_post", - "startTime": "2013-06-26T15:03:02.813-07:00", - "status": "DONE", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_setTags_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_setTags_post.json deleted file mode 100644 index 0733627e49..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_setTags_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T21:20:10.487-07:00", - "id": "8115150846190320932", - "insertTime": "2013-06-26T21:20:03.962-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_setTags_post", - "operationType": "setTags", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_setTags_post", - "startTime": "2013-06-26T21:20:04.103-07:00", - "status": "DONE", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_post.json deleted file mode 100644 index 40d2857555..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_post.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "endTime": "2013-06-26T16:13:08.382-07:00", - "id": "1858155812259649243", - "insertTime": "2013-06-26T16:12:51.492-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_post", - "operationType": "insert", - "progress": 100, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_post", - "startTime": "2013-06-26T16:12:51.537-07:00", - "status": "DONE", - "targetId": "16630486471904253898", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/project.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/project.json deleted file mode 100644 index 6b65499ea9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/project.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "commonInstanceMetadata": { - "items": [ - { - "key": "sshKeys", - "value": "ASDFASDF" - } - ], - "kind": "compute#metadata" - }, - "creationTimestamp": "2013-02-05T16:19:20.516-08:00", - "description": "", - "id": "2193465259114366848", - "kind": "compute#project", - "name": "project_name", - "quotas": [ - { - "limit": 1000.0, - "metric": "SNAPSHOTS", - "usage": 0.0 - }, - { - "limit": 5.0, - "metric": "NETWORKS", - "usage": 3.0 - }, - { - "limit": 100.0, - "metric": "FIREWALLS", - "usage": 5.0 - }, - { - "limit": 100.0, - "metric": "IMAGES", - "usage": 0.0 - }, - { - "limit": 100.0, - "metric": "ROUTES", - "usage": 6.0 - }, - { - "limit": 50.0, - "metric": "FORWARDING_RULES", - "usage": 0.0 - }, - { - "limit": 50.0, - "metric": "TARGET_POOLS", - "usage": 1.0 - }, - { - "limit": 50.0, - "metric": "HEALTH_CHECKS", - "usage": 1.0 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json deleted file mode 100644 index 32de60da63..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "id": "projects/debian-cloud/global/images", - "items": [ - { - "archiveSizeBytes": "365056004", - "creationTimestamp": "2013-12-02T17:49:01.206-08:00", - "description": "Debian GNU/Linux 7.2 (wheezy) with backports kernel built on 2013-11-27", - "id": "11823693270029497919", - "kind": "compute#image", - "name": "backports-debian-7-wheezy-v20131127", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/backports-debian-7-wheezy-v20131127", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "214107225", - "creationTimestamp": "2013-05-07T17:09:22.111-07:00", - "deprecated": { - "deleted": "1970-01-03", - "deprecated": "1970-01-01", - "obsolete": "1970-01-02", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130507", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-07", - "id": "647943287916432906", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130507", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130507", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "255972840", - "creationTimestamp": "2013-05-09T12:56:21.720-07:00", - "deprecated": { - "deprecated": "2013-11-12T21:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-09", - "id": "15745758816845911589", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130509", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130509", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "219458106", - "creationTimestamp": "2013-05-14T21:01:12.124-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-15", - "id": "006866479348046290", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130515", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130515", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "265118282", - "creationTimestamp": "2013-05-30T09:48:37.837-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-22", - "id": "1266148899538866390", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130522", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130522", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "233984980", - "creationTimestamp": "2013-06-19T13:45:44.111-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-06-17", - "id": "04009358257173422091", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130617", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130617", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "258168500", - "creationTimestamp": "2013-07-24T12:31:06.054-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-07-23", - "id": "3115342424904648000", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130723", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130723", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "300710522", - "creationTimestamp": "2013-09-04T13:21:53.292-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-08-16", - "id": "06130699342353523133", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130816", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130816", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "300710522", - "creationTimestamp": "2013-10-11T09:26:47.736-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-09-26", - "id": "0225119674082940764", - "kind": "compute#image", - "name": "debian-6-squeeze-v20130926", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130926", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "237290472", - "creationTimestamp": "2013-05-07T17:01:30.071-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-07", - "id": "15638477823580670459", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130507", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130507", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "270107366", - "creationTimestamp": "2013-05-09T12:56:47.910-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-09", - "id": "020034532765408091", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130509", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130509", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "265604335", - "creationTimestamp": "2013-05-14T21:02:55.044-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-15", - "id": "0587071888358410836", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130515", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130515", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "284301993", - "creationTimestamp": "2013-05-30T09:47:30.980-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-22", - "id": "622079684385221180", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130522", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130522", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "310882322", - "creationTimestamp": "2013-06-19T13:47:20.563-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-06-17", - "id": "1549141992333368759", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130617", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130617", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "258869806", - "creationTimestamp": "2013-07-24T12:31:36.790-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-07-23", - "id": "3119304810142650253", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130723", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130723", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "279162251", - "creationTimestamp": "2013-09-04T13:24:30.479-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-08-16", - "id": "2595370902107306327", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130816", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130816", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "279162251", - "creationTimestamp": "2013-10-11T09:26:56.993-07:00", - "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-09-26", - "id": "06737951524754934395", - "kind": "compute#image", - "name": "debian-7-wheezy-v20130926", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130926", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "405683884", - "creationTimestamp": "2013-10-28T13:52:08.233-07:00", - "deprecated": { - "deprecated": "2013-12-02T12:00:00Z", - "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "state": "DEPRECATED" - }, - "description": "Debian GNU/Linux 7.2 (wheezy) built on 2013-10-14", - "id": "1405559880052641502", - "kind": "compute#image", - "name": "debian-7-wheezy-v20131014", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", - "sourceType": "RAW", - "status": "READY" - }, - { - "archiveSizeBytes": "341857472", - "creationTimestamp": "2013-11-25T15:17:00.436-08:00", - "description": "Debian GNU/Linux 7.2 (wheezy) built on 2013-11-20", - "id": "05708985343919147751", - "kind": "compute#image", - "name": "debian-7-wheezy-v20131120", - "rawDisk": { - "containerType": "TAR", - "source": "" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceType": "RAW", - "status": "READY" - } - ], - "kind": "compute#imageList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions.json deleted file mode 100644 index f6d12c0039..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "id": "projects/project_name/regions", - "items": [ - { - "creationTimestamp": "2013-04-19T17:58:16.641-07:00", - "description": "europe-west1", - "id": "0827308347805275727", - "kind": "compute#region", - "name": "europe-west1", - "quotas": [ - { - "limit": 24.0, - "metric": "CPUS", - "usage": 0.0 - }, - { - "limit": 5120.0, - "metric": "DISKS_TOTAL_GB", - "usage": 0.0 - }, - { - "limit": 7.0, - "metric": "STATIC_ADDRESSES", - "usage": 0.0 - }, - { - "limit": 23.0, - "metric": "IN_USE_ADDRESSES", - "usage": 0.0 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", - "status": "UP", - "zones": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b" - ] - }, - { - "creationTimestamp": "2013-04-19T18:17:05.050-07:00", - "description": "us-central1", - "id": "06713580496607310378", - "kind": "compute#region", - "name": "us-central1", - "quotas": [ - { - "limit": 24.0, - "metric": "CPUS", - "usage": 3.0 - }, - { - "limit": 5120.0, - "metric": "DISKS_TOTAL_GB", - "usage": 10.0 - }, - { - "limit": 7.0, - "metric": "STATIC_ADDRESSES", - "usage": 0.0 - }, - { - "limit": 23.0, - "metric": "IN_USE_ADDRESSES", - "usage": 4.0 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "status": "UP", - "zones": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" - ] - }, - { - "creationTimestamp": "2013-04-19T18:19:05.482-07:00", - "description": "us-central2", - "id": "04157375529195793136", - "kind": "compute#region", - "name": "us-central2", - "quotas": [ - { - "limit": 24.0, - "metric": "CPUS", - "usage": 0.0 - }, - { - "limit": 5120.0, - "metric": "DISKS_TOTAL_GB", - "usage": 0.0 - }, - { - "limit": 7.0, - "metric": "STATIC_ADDRESSES", - "usage": 0.0 - }, - { - "limit": 23.0, - "metric": "IN_USE_ADDRESSES", - "usage": 0.0 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central2", - "status": "UP", - "zones": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" - ] - } - ], - "kind": "compute#regionList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses.json deleted file mode 100644 index 65c5bd61ae..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "id": "projects/project_name/regions/us-central1/addresses", - "items": [ - { - "address": "108.59.82.4", - "creationTimestamp": "2013-06-26T09:48:31.184-07:00", - "description": "", - "id": "17634862894218443422", - "kind": "compute#address", - "name": "libcloud-demo-address", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/libcloud-demo-address", - "status": "RESERVED" - }, - { - "address": "173.255.114.104", - "creationTimestamp": "2013-06-04T16:28:43.764-07:00", - "description": "", - "id": "11879548153827627972", - "kind": "compute#address", - "name": "testaddress", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/testaddress", - "status": "RESERVED" - } - ], - "kind": "compute#addressList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress.json deleted file mode 100644 index 6579a2d7d0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "address": "173.255.113.20", - "creationTimestamp": "2013-06-26T12:21:40.625-07:00", - "description": "", - "id": "01531551729918243104", - "kind": "compute#address", - "name": "lcaddress", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", - "status": "RESERVED" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress_delete.json deleted file mode 100644 index 90fec9ea61..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "7128783508312083402", - "insertTime": "2013-06-26T12:21:44.075-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_addresses_lcaddress_delete", - "operationType": "delete", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_lcaddress_delete", - "startTime": "2013-06-26T12:21:44.110-07:00", - "status": "PENDING", - "targetId": "01531551729918243104", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_post.json deleted file mode 100644 index 3bcbf1ee41..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_post.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "16064059851942653139", - "insertTime": "2013-06-26T12:21:40.299-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_addresses_post", - "operationType": "insert", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_post", - "startTime": "2013-06-26T12:21:40.358-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", - "user": "897001307951@developer.gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules.json deleted file mode 100644 index 2eedb8a063..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "id": "projects/project_name/regions/us-central1/forwardingRules", - "items": [ - { - "IPAddress": "173.255.119.224", - "IPProtocol": "TCP", - "creationTimestamp": "2013-09-03T00:17:25.544-07:00", - "id": "10901665092293158938", - "kind": "compute#forwardingRule", - "name": "lcforwardingrule", - "portRange": "8000-8500", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", - "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" - }, - { - "IPAddress": "173.255.119.185", - "IPProtocol": "TCP", - "creationTimestamp": "2013-09-02T22:25:50.575-07:00", - "id": "15826316229163619337", - "kind": "compute#forwardingRule", - "name": "libcloud-lb-demo-lb", - "portRange": "80-80", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/libcloud-lb-demo-lb", - "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" - } - ], - "kind": "compute#forwardingRuleList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule.json deleted file mode 100644 index 6301a559da..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "IPAddress": "173.255.119.224", - "IPProtocol": "TCP", - "creationTimestamp": "2013-09-03T00:17:25.544-07:00", - "id": "10901665092293158938", - "kind": "compute#forwardingRule", - "name": "lcforwardingrule", - "portRange": "8000-8500", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", - "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule_delete.json deleted file mode 100644 index b12f003a9f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "09064254309855814339", - "insertTime": "2013-09-03T00:17:36.062-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", - "operationType": "delete", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", - "startTime": "2013-09-03T00:17:36.168-07:00", - "status": "PENDING", - "targetId": "10901665092293158938", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_libcloud-lb-demo-lb.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_libcloud-lb-demo-lb.json deleted file mode 100644 index 7925845605..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_libcloud-lb-demo-lb.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "IPAddress": "108.59.83.110", - "IPProtocol": "TCP", - "creationTimestamp": "2013-09-29T13:30:00.702-07:00", - "id": "1077550228014866104", - "kind": "compute#forwardingRule", - "name": "libcloud-lb-demo-lb", - "portRange": "80-80", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/libcloud-lb-demo-lb", - "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_post.json deleted file mode 100644 index c65f2839ba..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_post.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "0651769405845333112", - "insertTime": "2013-09-03T00:17:25.381-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_forwardingRules_post", - "operationType": "insert", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_post", - "startTime": "2013-09-03T00:17:25.434-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools.json deleted file mode 100644 index 72584ecc28..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "id": "projects/project_name/regions/us-central1/targetPools", - "items": [ - { - "creationTimestamp": "2013-09-03T00:51:05.300-07:00", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" - ], - "id": "13598380121688918358", - "instances": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" - ], - "kind": "compute#targetPool", - "name": "lctargetpool", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" - }, - { - "creationTimestamp": "2013-09-02T22:25:45.817-07:00", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" - ], - "id": "16862638289615591831", - "instances": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-002", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000" - ], - "kind": "compute#targetPool", - "name": "libcloud-lb-demo-lb-tp", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" - } - ], - "kind": "compute#targetPoolList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool.json deleted file mode 100644 index 1875ed1780..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "creationTimestamp": "2013-09-03T00:51:05.300-07:00", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" - ], - "id": "13598380121688918358", - "instances": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" - ], - "kind": "compute#targetPool", - "name": "lctargetpool", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json deleted file mode 100644 index 9db7b24208..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "17341029456963557514", - "insertTime": "2013-09-03T01:28:40.774-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", - "operationType": "addHealthCheck", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", - "startTime": "2013-09-03T01:28:40.838-07:00", - "status": "PENDING", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addInstance_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addInstance_post.json deleted file mode 100644 index 7f61c1de1f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addInstance_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "04072826501537092633", - "insertTime": "2013-09-03T01:29:03.082-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", - "operationType": "addInstance", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", - "startTime": "2013-09-03T01:29:03.145-07:00", - "status": "PENDING", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_delete.json deleted file mode 100644 index 276a465e72..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "13500662190763995965", - "insertTime": "2013-09-03T00:51:06.799-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_delete", - "operationType": "delete", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_delete", - "startTime": "2013-09-03T00:51:06.840-07:00", - "status": "PENDING", - "targetId": "13598380121688918358", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json deleted file mode 100644 index eebae15c29..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "14738174613993796821", - "insertTime": "2013-09-03T01:28:32.889-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", - "operationType": "removeHealthCheck", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", - "startTime": "2013-09-03T01:28:32.942-07:00", - "status": "PENDING", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeInstance_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeInstance_post.json deleted file mode 100644 index fc0c69f7f3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeInstance_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "1815686149437875016", - "insertTime": "2013-09-03T01:28:53.049-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", - "operationType": "removeInstance", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", - "startTime": "2013-09-03T01:28:53.109-07:00", - "status": "PENDING", - "targetId": "16862638289615591831", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_libcloud-lb-demo-lb-tp.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_libcloud-lb-demo-lb-tp.json deleted file mode 100644 index 44a7af554c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_libcloud-lb-demo-lb-tp.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "creationTimestamp": "2013-09-02T22:25:45.817-07:00", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" - ], - "id": "16862638289615591831", - "instances": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-002", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000" - ], - "kind": "compute#targetPool", - "name": "libcloud-lb-demo-lb-tp", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_post.json deleted file mode 100644 index 6437bc7991..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_post.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "7487852523793007955", - "insertTime": "2013-09-03T00:51:05.064-07:00", - "kind": "compute#operation", - "name": "operation-regions_us-central1_targetPools_post", - "operationType": "insert", - "progress": 0, - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_post", - "startTime": "2013-09-03T00:51:05.115-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", - "user": "user@gserviceaccount.com" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_www-pool.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_www-pool.json deleted file mode 100644 index d41068f1c0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_www-pool.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "creationTimestamp": "2013-08-19T14:43:25.289-07:00", - "description": "", - "healthChecks": [ - "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check" - ], - "id": "09965129111508633746", - "instances": [ - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/www1", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/www2", - "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/www3" - ], - "kind": "compute#targetPool", - "name": "www-pool", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/www-pool" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones.json deleted file mode 100644 index 0d564e7bbb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "id": "projects/project_name/zones", - "items": [ - { - "creationTimestamp": "2013-02-05T16:19:23.254-08:00", - "description": "europe-west1-a", - "id": "13416642339679437530", - "kind": "compute#zone", - "maintenanceWindows": [ - { - "beginTime": "2014-01-18T12:00:00.000-08:00", - "description": "maintenance zone", - "endTime": "2014-02-02T12:00:00.000-08:00", - "name": "2014-01-18-planned-outage" - } - ], - "name": "europe-west1-a", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a", - "status": "UP" - }, - { - "creationTimestamp": "2013-02-05T16:19:23.254-08:00", - "description": "europe-west1-b", - "id": "20623650177407096", - "kind": "compute#zone", - "maintenanceWindows": [ - { - "beginTime": "2014-03-15T12:00:00.000-07:00", - "description": "maintenance zone", - "endTime": "2014-03-30T12:00:00.000-07:00", - "name": "2014-03-15-planned-outage" - } - ], - "name": "europe-west1-b", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b", - "status": "UP" - }, - { - "creationTimestamp": "2013-02-05T16:19:23.269-08:00", - "description": "us-central1-a", - "id": "13462829244527433283", - "kind": "compute#zone", - "name": "us-central1-a", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", - "status": "UP" - }, - { - "creationTimestamp": "2013-02-05T16:19:23.269-08:00", - "description": "us-central1-b", - "id": "1045862591201432620", - "kind": "compute#zone", - "name": "us-central1-b", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", - "status": "UP" - }, - { - "creationTimestamp": "2013-02-05T16:19:23.257-08:00", - "deprecated": { - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", - "state": "DEPRECATED" - }, - "description": "us-central2-a", - "id": "1001467574647549152", - "kind": "compute#zone", - "maintenanceWindows": [ - { - "beginTime": "2013-12-31T12:00:00.000-08:00", - "description": "maintenance zone", - "endTime": "2014-07-01T12:00:00.000-07:00", - "name": "2013-12-31-planned-outage" - } - ], - "name": "us-central2-a", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a", - "status": "UP" - } - ], - "kind": "compute#zoneList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances.json deleted file mode 100644 index 1dd88d64d4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "id": "projects/project_name/zones/europe-west1-a/instances", - "items": [ - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:43:58.782-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-europe-multiple-nodes-000", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-multiple-nodes-000", - "type": "PERSISTENT" - } - ], - "id": "10947706194464948790", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-europe-multiple-nodes-000", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "192.158.28.252", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.122.85" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-multiple-nodes-000", - "status": "RUNNING", - "tags": { - "fingerprint": "W7t6ZyTyIrc=", - "items": [ - "libcloud" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - }, - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:43:12.706-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-europe-np-node", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-np-node", - "type": "PERSISTENT" - }, - { - "deviceName": "libcloud-demo-europe-attach-disk", - "index": 1, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-attach-disk", - "type": "PERSISTENT" - } - ], - "id": "3421745795082776097", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-europe-np-node", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.251.128.10", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.221.125" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", - "status": "RUNNING", - "tags": { - "fingerprint": "W7t6ZyTyIrc=", - "items": [ - "libcloud" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - }, - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:43:37.267-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-demo-europe-boot-disk", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-boot-disk", - "type": "PERSISTENT" - } - ], - "id": "517678477070693411", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "libcloud-demo-europe-persist-node", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.251.128.32", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.240.204" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-persist-node", - "status": "RUNNING", - "tags": { - "fingerprint": "EbZdwVRtKyg=", - "items": [ - "libcloud", - "newtag" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" - } - ], - "kind": "compute#instanceList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances_post.json deleted file mode 100644 index 710517c06d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "1510575454210533141", - "insertTime": "2013-06-26T20:57:34.366-07:00", - "kind": "compute#operation", - "name": "operation-zones_europe-west1-a_instances_post", - "operationType": "insert", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/operations/operation-zones_europe-west1-a_instances_post", - "startTime": "2013-06-26T20:57:34.453-07:00", - "status": "PENDING", - "targetId": "14308265828754333159", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_machineTypes_n1-standard-1.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_machineTypes_n1-standard-1.json deleted file mode 100644 index e4e8fcfef7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_machineTypes_n1-standard-1.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", - "zone": "europe-west1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a.json deleted file mode 100644 index c917966cb8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "creationTimestamp": "2013-02-05T16:19:23.269-08:00", - "description": "us-central1-a", - "id": "13462829244527433283", - "kind": "compute#zone", - "name": "us-central1-a", - "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", - "status": "UP" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks.json deleted file mode 100644 index 68d40fc9a0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id": "projects/project_name/zones/us-central1-a/disks", - "items": [ - { - "creationTimestamp": "2013-12-13T10:45:42.139-08:00", - "id": "08045379695757218000", - "kind": "compute#disk", - "name": "lcdisk", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "sizeGb": "1", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" - }, - { - "creationTimestamp": "2013-12-13T10:45:20.308-08:00", - "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "id": "0265567475385851075", - "kind": "compute#disk", - "name": "node-name", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", - "sizeGb": "10", - "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", - "sourceImageId": "17312518942796567788", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" - } - ], - "kind": "compute#diskList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk.json deleted file mode 100644 index d88ba6ee42..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "creationTimestamp": "2013-06-26T10:06:04.007-07:00", - "id": "16109451798967042451", - "kind": "compute#disk", - "name": "lcdisk", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "sizeGb": "1", - "status": "READY", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_createSnapshot_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_createSnapshot_post.json deleted file mode 100644 index 97be56a2d8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_createSnapshot_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "0158330665043557584", - "insertTime": "2013-12-16T13:03:51.000-08:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", - "operationType": "createSnapshot", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", - "startTime": "2013-12-16T13:03:51.042-08:00", - "status": "PENDING", - "targetId": "07494414044179227172", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_delete.json deleted file mode 100644 index 84d222a0e3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "06887337364510109333", - "insertTime": "2013-06-26T10:06:11.835-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_disks_lcdisk_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_delete", - "startTime": "2013-06-26T10:06:12.006-07:00", - "status": "PENDING", - "targetId": "16109451798967042451", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_post.json deleted file mode 100644 index ed69408a69..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_post.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "0211151278250678078", - "insertTime": "2013-06-26T16:48:17.403-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_disks_post", - "operationType": "insert", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_post", - "startTime": "2013-06-26T16:48:17.479-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances.json deleted file mode 100644 index 9fccb06efc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "id": "projects/project_name/zones/us-central1-a/instances", - "items": [ - { - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:45:23.351-08:00", - "disks": [ - { - "boot": true, - "deviceName": "persistent-disk-0", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", - "type": "PERSISTENT" - } - ], - "id": "4006034190819017667", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "node-name", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.236.58.15", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.72.75" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "status": "RUNNING", - "tags": { - "fingerprint": "42WmSpB8rSM=" - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" - } - ], - "kind": "compute#instanceList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000.json deleted file mode 100644 index 43661c2d88..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:54:07.687-08:00", - "disks": [ - { - "boot": true, - "deviceName": "lcnode-000", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcnode-000", - "type": "PERSISTENT" - } - ], - "id": "17170905942674172532", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "lcnode-000", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "173.255.114.35", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.160.66" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-000", - "status": "RUNNING", - "tags": { - "fingerprint": "42WmSpB8rSM=" - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000_delete.json deleted file mode 100644 index ffbf1520bf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "3319596145594427549", - "insertTime": "2013-06-26T16:13:12.903-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_lcnode-000_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-000_delete", - "startTime": "2013-06-26T16:13:12.948-07:00", - "status": "PENDING", - "targetId": "5390075309006132922", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-000", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001.json deleted file mode 100644 index 7cd6be9d04..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:54:08.639-08:00", - "disks": [ - { - "boot": true, - "deviceName": "lcnode-001", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcnode-001", - "type": "PERSISTENT" - } - ], - "id": "09356229693786319079", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "lcnode-001", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "173.255.117.19", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.168.208" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", - "status": "RUNNING", - "tags": { - "fingerprint": "42WmSpB8rSM=" - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001_delete.json deleted file mode 100644 index fa887cef29..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "17469711273432628502", - "insertTime": "2013-06-26T16:13:40.579-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_lcnode-001_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-001_delete", - "startTime": "2013-06-26T16:13:40.620-07:00", - "status": "PENDING", - "targetId": "16630486471904253898", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name.json deleted file mode 100644 index 439e00be11..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:45:23.351-08:00", - "disks": [ - { - "boot": true, - "deviceName": "persistent-disk-0", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", - "type": "PERSISTENT" - } - ], - "id": "4006034190819017667", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "42WmSpB8rSM=", - "kind": "compute#metadata" - }, - "name": "node-name", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.236.58.15", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.72.75" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "status": "RUNNING", - "tags": { - "fingerprint": "42WmSpB8rSM=" - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_attachDisk_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_attachDisk_post.json deleted file mode 100644 index e6167b5179..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_attachDisk_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "7455886659787654716", - "insertTime": "2013-06-26T16:48:27.691-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_attachDisk_post", - "operationType": "attachDisk", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_attachDisk_post", - "startTime": "2013-06-26T16:48:27.762-07:00", - "status": "PENDING", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_delete.json deleted file mode 100644 index e74dbbaf60..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_delete.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "6999931397447918763", - "insertTime": "2013-06-26T10:05:40.350-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_delete", - "operationType": "delete", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_delete", - "startTime": "2013-06-26T10:05:40.405-07:00", - "status": "PENDING", - "targetId": "07410051435384876224", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_detachDisk_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_detachDisk_post.json deleted file mode 100644 index d8d2e63832..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_detachDisk_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "3921383727105838816", - "insertTime": "2013-06-26T16:48:35.357-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_detachDisk_post", - "operationType": "detachDisk", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_detachDisk_post", - "startTime": "2013-06-26T16:48:35.398-07:00", - "status": "PENDING", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_reset_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_reset_post.json deleted file mode 100644 index 240a255358..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_reset_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "10507122129283663728", - "insertTime": "2013-06-26T15:03:02.766-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_reset_post", - "operationType": "reset", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_reset_post", - "startTime": "2013-06-26T15:03:02.813-07:00", - "status": "PENDING", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_setTags_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_setTags_post.json deleted file mode 100644 index 2dfdcd462f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_setTags_post.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "8115150846190320932", - "insertTime": "2013-06-26T21:20:03.962-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_node-name_setTags_post", - "operationType": "setTags", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_setTags_post", - "startTime": "2013-06-26T21:20:04.103-07:00", - "status": "PENDING", - "targetId": "1845312225624811608", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_post.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_post.json deleted file mode 100644 index 77c95e8074..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_post.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "1858155812259649243", - "insertTime": "2013-06-26T16:12:51.492-07:00", - "kind": "compute#operation", - "name": "operation-zones_us-central1-a_instances_post", - "operationType": "insert", - "progress": 0, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_post", - "startTime": "2013-06-26T16:12:51.537-07:00", - "status": "PENDING", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", - "user": "897001307951@developer.gserviceaccount.com", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes.json deleted file mode 100644 index 7cbae6f077..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes.json +++ /dev/null @@ -1,424 +0,0 @@ -{ - "id": "projects/project_name/zones/us-central1-a/machineTypes", - "items": [ - { - "creationTimestamp": "2013-04-25T13:32:49.088-07:00", - "description": "1 vCPU (shared physical core) and 0.6 GB RAM", - "guestCpus": 1, - "id": "1133568312750571513", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 614, - "name": "f1-micro", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/f1-micro", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2013-04-25T13:32:45.550-07:00", - "description": "1 vCPU (shared physical core) and 1.7 GB RAM", - "guestCpus": 1, - "id": "1500265464823777597", - "imageSpaceGb": 0, - "kind": "compute#machineType", - "maximumPersistentDisks": 4, - "maximumPersistentDisksSizeGb": "3072", - "memoryMb": 1740, - "name": "g1-small", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/g1-small", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:46:10.572-08:00", - "description": "2 vCPUs, 1.8 GB RAM", - "guestCpus": 2, - "id": "16898271314080235997", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:47:07.825-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "15178384466070744001", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 1843, - "name": "n1-highcpu-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:48:06.087-08:00", - "description": "4 vCPUs, 3.6 GB RAM", - "guestCpus": 4, - "id": "04759000181765218034", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:49:07.563-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "01151097524490134507", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3686, - "name": "n1-highcpu-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:50:15.128-08:00", - "description": "8 vCPUs, 7.2 GB RAM", - "guestCpus": 8, - "id": "01206886442411821831", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:51:04.549-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "02507333096579477005", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7373, - "name": "n1-highcpu-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:06.129-08:00", - "description": "2 vCPUs, 13 GB RAM", - "guestCpus": 2, - "id": "05438694236916301519", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:40:59.630-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "00770157291441082211", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 13312, - "name": "n1-highmem-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:42:08.983-08:00", - "description": "4 vCPUs, 26 GB RAM", - "guestCpus": 4, - "id": "11556032176405786676", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:43:17.400-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "05095504563332567951", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 26624, - "name": "n1-highmem-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:44:25.985-08:00", - "description": "8 vCPUs, 52 GB RAM", - "guestCpus": 8, - "id": "01717932668777642040", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-11-16T11:45:08.195-08:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "07181827135536388552", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 53248, - "name": "n1-highmem-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:34.258-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "state": "DEPRECATED" - }, - "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", - "guestCpus": 1, - "id": "10583029372018866711", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1-d", - "scratchDisks": [ - { - "diskGb": 420 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:48:56.867-07:00", - "description": "2 vCPUs, 7.5 GB RAM", - "guestCpus": 2, - "id": "17936898073622676356", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:49:19.448-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", - "state": "DEPRECATED" - }, - "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", - "guestCpus": 2, - "id": "06313284160910191442", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 7680, - "name": "n1-standard-2-d", - "scratchDisks": [ - { - "diskGb": 870 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:49:40.050-07:00", - "description": "4 vCPUs, 15 GB RAM", - "guestCpus": 4, - "id": "09494636486174545828", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:50:05.677-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", - "state": "DEPRECATED" - }, - "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", - "guestCpus": 4, - "id": "00523085164784013586", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 15360, - "name": "n1-standard-4-d", - "scratchDisks": [ - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4-d", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:50:42.334-07:00", - "description": "8 vCPUs, 30 GB RAM", - "guestCpus": 8, - "id": "04084282969223214132", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 30720, - "name": "n1-standard-8", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-8", - "zone": "us-central1-a" - }, - { - "creationTimestamp": "2012-06-07T13:51:19.936-07:00", - "deprecated": { - "deprecated": "2013-12-02T20:00:00-08:00", - "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-8", - "state": "DEPRECATED" - }, - "description": "8 vCPUs, 30 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", - "guestCpus": 8, - "id": "00035824420671580077", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 30720, - "name": "n1-standard-8-d", - "scratchDisks": [ - { - "diskGb": 1770 - }, - { - "diskGb": 1770 - } - ], - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-8-d", - "zone": "us-central1-a" - } - ], - "kind": "compute#machineTypeList", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json deleted file mode 100644 index d1b3d74bd3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "id": "11077240422128681563", - "imageSpaceGb": 10, - "kind": "compute#machineType", - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "memoryMb": 3840, - "name": "n1-standard-1", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", - "zone": "us-central1-a" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-000.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-000.json deleted file mode 100644 index 858b0de811..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-000.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:51:24.339-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-lb-demo-www-000", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/libcloud-lb-demo-www-000", - "type": "PERSISTENT" - } - ], - "id": "08447900841145802741", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "IZjMMp0A_8k=", - "items": [ - { - "key": "startup-script", - "value": "apt-get -y update && apt-get -y install apache2 && hostname > /var/www/index.html" - } - ], - "kind": "compute#metadata" - }, - "name": "libcloud-lb-demo-www-000", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.236.58.15", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.104.11" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", - "status": "RUNNING", - "tags": { - "fingerprint": "XI0he92M8l8=", - "items": [ - "libcloud-lb-demo-www" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-001.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-001.json deleted file mode 100644 index df6b0c62e5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-001.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "canIpForward": false, - "creationTimestamp": "2013-12-13T10:51:25.165-08:00", - "disks": [ - { - "boot": true, - "deviceName": "libcloud-lb-demo-www-001", - "index": 0, - "kind": "compute#attachedDisk", - "mode": "READ_WRITE", - "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/libcloud-lb-demo-www-001", - "type": "PERSISTENT" - } - ], - "id": "11523404878553997348", - "kind": "compute#instance", - "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", - "metadata": { - "fingerprint": "09vSzO6KXcw=", - "items": [ - { - "key": "startup-script", - "value": "apt-get -y update && apt-get -y install apache2 && hostname > /var/www/index.html" - } - ], - "kind": "compute#metadata" - }, - "name": "libcloud-lb-demo-www-001", - "networkInterfaces": [ - { - "accessConfigs": [ - { - "kind": "compute#accessConfig", - "name": "External NAT", - "natIP": "23.236.58.59", - "type": "ONE_TO_ONE_NAT" - } - ], - "name": "nic0", - "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", - "networkIP": "10.240.94.107" - } - ], - "scheduling": { - "automaticRestart": true, - "onHostMaintenance": "MIGRATE" - }, - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001", - "status": "RUNNING", - "tags": { - "fingerprint": "XI0he92M8l8=", - "items": [ - "libcloud-lb-demo-www" - ] - }, - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-002.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-002.json deleted file mode 100644 index 4800d575c4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-002.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "error": { - "code": 404, - "errors": [ - { - "domain": "global", - "message": "The resource 'projects/project-name/zones/us-central1-b/instances/libcloud-lb-demo-www-002' was not found", - "reason": "notFound" - } - ], - "message": "The resource 'projects/project-name/zones/us-central1-b/instances/libcloud-lb-demo-www-002' was not found" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setDiskAutoDelete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setDiskAutoDelete.json deleted file mode 100644 index 4087a420c4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setDiskAutoDelete.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "kind": "compute#operation", - "id": "14265294323024381703", - "name": "operation-volume-auto-delete", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", - "operationType": "setDiskAutoDelete", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/dev-test", - "targetId": "4313186599918690450", - "status": "PENDING", - "user": "user@developer.gserviceaccount.com", - "progress": 0, - "insertTime": "2014-03-13T21:50:57.612-07:00", - "startTime": "2014-03-13T21:50:57.717-07:00", - "endTime": "2014-03-13T21:50:58.047-07:00", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-volume-auto-delete" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_volume_auto_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_volume_auto_delete.json deleted file mode 100644 index dc8231c84b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_volume_auto_delete.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "kind": "compute#operation", - "id": "14265294323024381703", - "name": "operation-volume-auto-delete", - "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", - "operationType": "setDiskAutoDelete", - "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/dev-test", - "targetId": "4313186599918690450", - "status": "DONE", - "user": "user@developer.gserviceaccount.com", - "progress": 100, - "insertTime": "2014-03-13T21:50:57.612-07:00", - "startTime": "2014-03-13T21:50:57.717-07:00", - "endTime": "2014-03-13T21:50:58.047-07:00", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-volume-auto-delete" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/image_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/image_list.json deleted file mode 100644 index 761a14988b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/image_list.json +++ /dev/null @@ -1,180 +0,0 @@ -{ - "list": [ - { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - { - "billingtokens": [ - { - "id": 47, - "name": "CentOS 5.3 64bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (64-bit) w/ None", - "friendlyName": "CentOS 5.3 (64-bit) w/ None", - "id": 1532, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-939ef909-84b8-4a2f-ad56-02ccd7da05ff.img", - "name": "centos5.3_64_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (64-bit)", - "id": 17, - "name": "CentOS 5.3 (64-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789076417 - }, - { - "billingtokens": [ - { - "id": 48, - "name": "RHEL 5.4 32bit", - "price": 0 - } - ], - "description": "RHEL 5.4 (32-bit) w/ None", - "friendlyName": "RHEL 5.4 (32-bit) w/ None", - "id": 1533, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-4c88cb92-dd7b-4bb1-95b6-7cc93eb1d2aa.img", - "name": "rhel5.4_32_base", - "object": "serverimage", - "os": { - "description": "RHEL 5.4 (32-bit)", - "id": 18, - "name": "RHEL 5.4 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789076417 - }, - { - "billingtokens": [ - { - "id": 49, - "name": "RHEL 5.4 64bit", - "price": 0 - } - ], - "description": "RHEL 5.4 (64-bit) w/ None", - "friendlyName": "RHEL 5.4 (64-bit) w/ None", - "id": 1534, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2bd8ddb3-cc53-4a76-8188-0dce7537a422.img", - "name": "rhel5.4_64_base", - "object": "serverimage", - "os": { - "description": "RHEL 5.4 (64-bit)", - "id": 19, - "name": "RHEL 5.4 (64-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789076417 - } - ], - "method": "/grid/image/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 59, - "start": 0, - "total": 59 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/image_save.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/image_save.json deleted file mode 100644 index e20c6d8022..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/image_save.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "list": [ - { - "architecture": { - "description": "32 bit OS", - "id": 1, - "name": "32-bit", - "object": "option" - }, - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "object": "billingtoken", - "price": 0 - } - ], - "createdTime": 1289119839685, - "description": "", - "friendlyName": "testimage", - "id": 5050, - "isActive": true, - "isPublic": false, - "location": "123/GSI-3ee65927-f80d-43df-92df-6c7e352f009c.img", - "name": "GSI-3ee65927-f80d-43df-92df-6c7e352f009c", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": 123, - "name": "name", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is being saved", - "id": 1, - "name": "Saving", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1289119839685 - } - ], - "method": "/grid/image/save", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/ip_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/ip_list.json deleted file mode 100644 index cf44eb9782..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/ip_list.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "list": [ - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 5348099, - "ip": "192.168.75.66", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "192.168.75.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 5348100, - "ip": "192.168.75.67", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.75.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 5348101, - "ip": "192.168.75.68", - "object": "ip", - "public": false, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "192.168.75.64/255.255.255.240" - } - ], - "method": "/grid/ip/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 3, - "start": 0, - "total": 3 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/ip_list_empty.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/ip_list_empty.json deleted file mode 100644 index 146bd9f45a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/ip_list_empty.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "list": [ - ], - "method": "/grid/ip/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 0, - "start": 0, - "total": 0 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/lookup_list_ip_datacenter.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/lookup_list_ip_datacenter.json deleted file mode 100644 index 81a61c142e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/lookup_list_ip_datacenter.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "list": [ - { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - } - ], - "method": "/common/lookup/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 2, - "start": 0, - "total": 2 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/password_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/password_list.json deleted file mode 100644 index a06a3ef7dd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/password_list.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "list": [ - { - "password": "bebebe", - "object": "password", - "username": "root", - "server": { - "id": 90967, - "image": { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - "ip": { - "id": 1659927, - "ip": "192.168.0.202", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.0.192/255.255.255.240" - }, - "isSandbox": false, - "name": "test1", - "object": "server", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "ram": { - "description": "Server with 512MB RAM", - "id": 1, - "name": "512MB", - "object": "option" - }, - "state": { - "description": "Server is in active state.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - } - } - } - ], - "method": "/grid/server/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_add.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_add.json deleted file mode 100644 index 35a4ca1af7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_add.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "list": [ - { - "image": { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - "ip": { - "id": 1659927, - "ip": "192.168.0.202", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.0.192/255.255.255.240" - }, - "isSandbox": false, - "name": "test1", - "object": "server", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "ram": { - "description": "Server with 512MB RAM", - "id": 1, - "name": "512MB", - "object": "option" - }, - "state": { - "description": "Server is in active state.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - } - } - ], - "method": "/grid/server/add", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_delete.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_delete.json deleted file mode 100644 index 068ff83013..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_delete.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "list": [ - { - "id": 90967, - "image": { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - "ip": { - "id": 1659927, - "ip": "192.168.0.202", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.0.192/255.255.255.240" - }, - "isSandbox": false, - "name": "test1", - "object": "server", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "ram": { - "description": "Server with 512MB RAM", - "id": 1, - "name": "512MB", - "object": "option" - }, - "state": { - "description": "Server is in active state.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - } - } - ], - "method": "/grid/server/delete", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_edit.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_edit.json deleted file mode 100644 index 0133a1bb7f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_edit.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "list": [ - { - "id": 90967, - "image": { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - "ip": { - "id": 1659927, - "ip": "192.168.0.202", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.0.192/255.255.255.240" - }, - "isSandbox": false, - "name": "test1", - "object": "server", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "ram": { - "description": "Server with 512MB RAM", - "id": 1, - "name": "512MB", - "object": "option" - }, - "state": { - "description": "Server is in active state.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - } - } - ], - "method": "/grid/server/edit", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_list.json deleted file mode 100644 index 23e43ff78b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_list.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "list": [ - { - "id": 90967, - "image": { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - "ip": { - "id": 1659927, - "ip": "192.168.0.202", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.0.192/255.255.255.240" - }, - "isSandbox": false, - "name": "test1", - "description": "test server", - "object": "server", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "ram": { - "description": "Server with 512MB RAM", - "id": 1, - "name": "512MB", - "object": "option" - }, - "state": { - "description": "Server is in active state.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - } - } - ], - "method": "/grid/server/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_power.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_power.json deleted file mode 100644 index 71ba6780b8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_power.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "list": [ - { - "id": 90967, - "image": { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - "ip": { - "id": 1659927, - "ip": "192.168.0.202", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.0.192/255.255.255.240" - }, - "isSandbox": false, - "name": "test1", - "object": "server", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "ram": { - "description": "Server with 512MB RAM", - "id": 1, - "name": "512MB", - "object": "option" - }, - "state": { - "description": "Server is in active state.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - } - } - ], - "method": "/grid/server/power", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_power_fail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_power_fail.json deleted file mode 100644 index b938016483..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/gogrid/server_power_fail.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "list": [ - { - "id": 90967, - "image": { - "billingtokens": [ - { - "id": 46, - "name": "CentOS 5.3 32bit", - "price": 0 - } - ], - "description": "CentOS 5.3 (32-bit) w/ None", - "friendlyName": "CentOS 5.3 (32-bit) w/ None", - "id": 1531, - "isActive": true, - "isPublic": true, - "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", - "name": "centos5.3_32_base", - "object": "serverimage", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "owner": { - "id": -1, - "name": "GoGrid", - "object": "customer" - }, - "price": 0, - "state": { - "description": "Image is available for adds", - "id": 2, - "name": "Available", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - }, - "updatedTime": 1257789046453 - }, - "ip": { - "id": 1659927, - "ip": "192.168.0.202", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "192.168.0.192/255.255.255.240" - }, - "isSandbox": false, - "name": "test1", - "object": "server", - "os": { - "description": "CentOS 5.3 (32-bit)", - "id": 16, - "name": "CentOS 5.3 (32-bit)", - "object": "option" - }, - "ram": { - "description": "Server with 512MB RAM", - "id": 1, - "name": "512MB", - "object": "option" - }, - "state": { - "description": "Server is in active state.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "Web or Application Server", - "id": 1, - "name": "Web Server", - "object": "option" - } - } - ], - "method": "/grid/server/power", - "status": "failure", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/create_node.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/create_node.json deleted file mode 100644 index b9b3a09fbf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/create_node.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "62291" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/get_node.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/get_node.json deleted file mode 100644 index 5f00d4dfbf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/get_node.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "host": "659", - "rescue": "0", - "fqdn": "server1.vr-cluster.org", - "mbpkgid": "62291", - "locked": "0", - "os_id": "1613", - "os": "Debian 6 i386 PV", - "ip": "208.111.45.250", - "installed": "0", - "state": "DOWN", - "package": "VR512", - "ipv6": "2607:f740:10::f98", - "city": "MAA - Chennai (Madras), India", - "status": "TERMINATED" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_images.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_images.json deleted file mode 100644 index fd5ca5e8d5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_images.json +++ /dev/null @@ -1,98 +0,0 @@ -[ - { - "id": "1739", - "os": "Gentoo 2012 (0619) i386", - "description": "Gentoo 2012 0619 i386", - "type": "gentoo", - "subtype": "pv", - "size": "840mb", - "created": "2012-06-27 13:21:03", - "updated": "2012-06-27 13:28:50", - "bits": "32", - "tech": "pv" - }, - { - "id": "1613", - "os": "CentOS 5.8 x64", - "description": "CentOS 5.8 x64", - "type": "centos", - "subtype": "pv", - "size": "1.2gb", - "created": "2012-03-31 01:34:54", - "updated": "2012-05-23 16:15:29", - "bits": "32", - "tech": "pv" - }, - { - "id": "1676", - "os": "Ubuntu Server 12.04 LTS 64 bit", - "description": "Ubuntu 12.04 LTS x64", - "type": "ubuntu", - "subtype": "pv", - "size": "800mb", - "created": "2012-05-04 06:20:59", - "updated": "2012-05-04 06:31:09", - "bits": "64", - "tech": "pv" - }, - { - "id": "1667", - "os": "Ubuntu Server 12.04 LTS 32 bit", - "description": "Ubuntu 12.04 i386", - "type": "ubuntu", - "subtype": "pv", - "size": "700mb", - "created": "2012-05-04 06:18:10", - "updated": "2012-05-04 06:31:08", - "bits": "32", - "tech": "pv" - }, - { - "id": "1640", - "os": "CentOS 6.2 x64", - "description": "CentOS 6.2 x64", - "type": "centos", - "subtype": "pv", - "size": "1.2gb", - "created": "2012-03-31 01:36:44", - "updated": "2012-03-31 01:39:25", - "bits": "64", - "tech": "pv" - }, - { - "id": "1631", - "os": "CentOS 6.2 i386", - "description": "CentOS 6.2 i386", - "type": "centos", - "subtype": "pv", - "size": "1.1gb", - "created": "2012-03-31 01:36:15", - "updated": "2012-03-31 01:38:50", - "bits": "32", - "tech": "pv" - }, - { - "id": "1622", - "os": "CentOS 5.8 i386", - "description": "CentOS 5.8 i386", - "type": "centos", - "subtype": "pv", - "size": "1.1gb", - "created": "2012-03-31 01:35:30", - "updated": "2012-03-31 01:38:49", - "bits": "32", - "tech": "pv" - }, - { - "id": "721", - "os": "Ubuntu 11.04 Server x64 PV", - "description": "

Ubuntu 11.04 base server installation.<\/p>", - "type": "ubuntu", - "subtype": "pv", - "size": "600mb", - "created": "2011-05-01 06:21:08", - "updated": "2011-05-01 13:21:08", - "bits": "64", - "tech": "pv" - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_locations.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_locations.json deleted file mode 100644 index 4172105250..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_locations.json +++ /dev/null @@ -1,46 +0,0 @@ -[ - { - "id": "3", - "name": "SJC - San Jose, CA" - }, - { - "id": "13", - "name": "IAD2- Reston, VA" - }, - { - "id": "21", - "name": "LAX3 - Los Angeles, CA" - }, - { - "id": "31", - "name": "CHI - Chicago, IL" - }, - { - "id": "41", - "name": "NYC - New York, NY" - }, - { - "id": "61", - "name": "MAA - Chennai (Madras), India" - }, - { - "id": "71", - "name": "LON - London, United Kingdom" - }, - { - "id": "72", - "name": "AMS2 - Amsterdam, NL" - }, - { - "id": "82", - "name": "FRA - Paris, France" - }, - { - "id": "83", - "name": "HK - Hong Kong, HK" - }, - { - "id": "101", - "name": "DFW - Dallas, TX" - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json deleted file mode 100644 index 3eb8ba6b00..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json +++ /dev/null @@ -1,72 +0,0 @@ -[{ - "host": "659", - "rescue": "0", - "fqdn": "server1.vr-cluster.org", - "mbpkgid": "62291", - "locked": "0", - "os": "Debian 6 i386 PV", - "ip": "208.111.45.250", - "installed": "0", - "state": "DOWN", - "package": "VR512", - "ipv6": "2607:f740:10::f98", - "city": "MAA - Chennai (Madras), India", - "status": "TERMINATED", - "os_id" : "1613", - "location_id" : "3", - "plan_id" : "51" -}, -{ - "host": "902", - "rescue": "0", - "fqdn": "newbuild.vr.com", - "mbpkgid": "62327", - "locked": "0", - "os": "CentOS 5.8 x64", - "ip": "208.111.39.118", - "installed": "0", - "state": "DOWN", - "package": "VR512", - "ipv6": "2607:f740:0:3f::f0d", - "city": "SJC - San Jose, CA", - "status": "TERMINATED", - "os_id" : "1613", - "location_id" : "3", - "plan_id" : "51" -}, -{ - "host": "1010", - "rescue": "0", - "fqdn": "3test.build.com", - "mbpkgid": "62300", - "locked": "0", - "os": "CentOS 6.2 x64", - "ip": "208.111.40.179", - "installed": "0", - "state": "DOWN", - "package": "VR512", - "ipv6": "2607:f740:c::f4f", - "city": "LAX3 - Los Angeles, CA", - "status": "TERMINATED", - "os_id" : "1613", - "location_id" : "3", - "plan_id" : "51" -}, -{ - "host": "1028", - "rescue": "0", - "fqdn": "libcloud2.node.com", - "mbpkgid": "74567", - "locked": "0", - "os": "CentOS 5.8 x64", - "ip": "209.177.157.99", - "installed": "1", - "state": "UP", - "package": "VR512", - "ipv6": "2607:f740:b::eff", - "city": "IAD2- Reston, VA", - "status": "RUNNING", - "os_id" : "1613", - "location_id" : "3", - "plan_id" : "51" -}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json deleted file mode 100644 index ec7f9afe53..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json +++ /dev/null @@ -1,128 +0,0 @@ -[ - { - "plan_id": "31", - "plan": "VR256", - "ram": "256MB", - "disk": "10GB", - "transfer": "200GB", - "price": "10.00", - "available": "1167" - }, - { - "plan_id": "41", - "plan": "VR384", - "ram": "384MB", - "disk": "15GB", - "transfer": "300GB", - "price": "15.00", - "available": "768" - }, - { - "plan_id": "51", - "plan": "VR512", - "ram": "512MB", - "disk": "20GB", - "transfer": "400GB", - "price": "20.00", - "available": "620" - }, - { - "plan_id": "61", - "plan": "VR768", - "ram": "768MB", - "disk": "30GB", - "transfer": "600GB", - "price": "30.00", - "available": "403" - }, - { - "plan_id": "71", - "plan": "VR1024", - "ram": "1024MB", - "disk": "40GB", - "transfer": "800GB", - "price": "40.00", - "available": "304" - }, - { - "plan_id": "81", - "plan": "VR1280", - "ram": "1280MB", - "disk": "50GB", - "transfer": "1000GB", - "price": "50.00", - "available": "234" - }, - { - "plan_id": "91", - "plan": "VR1536", - "ram": "1536MB", - "disk": "60GB", - "transfer": "1200GB", - "price": "60.00", - "available": "190" - }, - { - "plan_id": "101", - "plan": "VR2048", - "ram": "2048MB", - "disk": "80GB", - "transfer": "1600GB", - "price": "80.00", - "available": "138" - }, - { - "plan_id": "128", - "plan": "VRBL1G", - "ram": "1024MB", - "disk": "50GB", - "transfer": "1000GB", - "price": "150.00", - "available": "34" - }, - { - "plan_id": "111", - "plan": "VR4048", - "ram": "4048MB", - "disk": "160GB", - "transfer": "3200GB", - "price": "160.00", - "available": "60" - }, - { - "plan_id": "137", - "plan": "VRBL2G", - "ram": "2048MB", - "disk": "100GB", - "transfer": "2000GB", - "price": "200.00", - "available": "16" - }, - { - "plan_id": "146", - "plan": "VRBL4G", - "ram": "4048MB", - "disk": "150GB", - "transfer": "3000GB", - "price": "300.00", - "available": "8" - }, - { - "plan_id": "119", - "plan": "VR8096", - "ram": "8096MB", - "disk": "320GB", - "transfer": "6400GB", - "price": "320.00", - "available": "11" - }, - { - "plan_id": "155", - "plan": "VRBL8G", - "ram": "8096MB", - "disk": "200GB", - "transfer": "5000GB", - "price": "400.00", - "available": "4" - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_destroy.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_destroy.json deleted file mode 100644 index 9daa87dcdd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_destroy.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "status" : "success" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_reboot.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_reboot.json deleted file mode 100644 index 9daa87dcdd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_reboot.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "status" : "success" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_start.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_start.json deleted file mode 100644 index 9daa87dcdd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_start.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "status" : "success" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_stop.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_stop.json deleted file mode 100644 index 9daa87dcdd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/hostvirtual/node_stop.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "status" : "success" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/allocate_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/allocate_address.xml deleted file mode 100644 index e786c0e2b0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/allocate_address.xml +++ /dev/null @@ -1 +0,0 @@ -

RESERVED14129279520001223PRIMARY0user@domain.com
\ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/attach_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/attach_volume.xml deleted file mode 100644 index 89b4e13a2c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/attach_volume.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/create.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/create.xml deleted file mode 100644 index 71d8811434..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/create.xml +++ /dev/null @@ -1 +0,0 @@ -28558128558RationalInsight4woodser@us.ibm.com11LARGEMyPublicKey02010-04-19T10:03:34.327-04:002010-04-26T10:03:43.610-04:00SUSE Linux Enterprise10 SP2OS diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/create_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/create_volume.xml deleted file mode 100644 index 920471c553..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/create_volume.xml +++ /dev/null @@ -1 +0,0 @@ -3929314120001208user@domain.comtest-volumeraw25602012-08-20T12:25:02.792Z2011-08-12T00:00:00.000ZUSD0.001CNT020 \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/delete.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/delete.xml deleted file mode 100644 index 7f2027262e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/delete.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/delete_address.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/delete_address.xml deleted file mode 100644 index 23b3278ded..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/delete_address.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/destroy_image.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/destroy_image.xml deleted file mode 100644 index a957946ae0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/destroy_image.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/destroy_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/destroy_volume.xml deleted file mode 100644 index 5b0b35fa42..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/destroy_volume.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/detach_volume.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/detach_volume.xml deleted file mode 100644 index e3683e450d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/detach_volume.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/images.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/images.xml deleted file mode 100644 index 91732f7072..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/images.xml +++ /dev/null @@ -1,2 +0,0 @@ - -2fd2d0478b132490897526b9b4433a334Rational Build Forge Agent11SYSTEMPUBLICi386SUSE Linux Enterprise/10 SP2Rational Build Forge provides an adaptive process execution framework that automates, orchestrates, manages, and tracks all the processes between each handoff within the assembly line of software development, creating an automated software factory.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A233F5A0-05A5-F21D-3E92-3793B722DFBD}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A233F5A0-05A5-F21D-3E92-3793B722DFBD}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-04-25T00:00:00.000-04:00384e900960c3d4b648fa6d4670aed2cd1SUSE 10 SP211SYSTEMPUBLICi386SUSE Linux Enterprise/10 SP2SuSE v10.2 Base OS Imagehttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{07F112A1-84A7-72BF-B8FD-B36011E0E433}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{07F112A1-84A7-72BF-B8FD-B36011E0E433}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-04-25T00:00:00.000-04:0015a72d3e7bb1cb4942ab0da2968e2e77bbWebSphere Application Server and Rational Agent Controller11SYSTEMPUBLICi386SUSE Linux Enterprise/10 SP2WebSphere Application Server and Rational Agent Controller enables a performance based foundation to build, reuse, run, integrate and manage Service Oriented Architecture (SOA) applications and services.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{86E8E71D-29A3-86DE-8A26-792C5E839D92}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{86E8E71D-29A3-86DE-8A26-792C5E839D92}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-04-25T00:00:00.000-04:00117da905ba0fdf4d8b8f94e7f4ef43c1beRational Insight11SYSTEMPUBLICi386SUSE Linux Enterprise/10 SP2Rational Insight helps organizations reduce time to market, improve quality, and take greater control of software and systems development and delivery. It provides objective dashboards and best practice metrics to identify risks, status, and trends.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{4F774DCF-1469-EAAB-FBC3-64AE241CF8E8}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{4F774DCF-1469-EAAB-FBC3-64AE241CF8E8}/1.0/GettingStarted.htmlLARGE2009-04-25T00:00:00.000-04:0018edf7ad43f75943b1b0c0f915dba8d86cDB2 Express-C11SYSTEMPUBLICi386SUSE Linux Enterprise/10 SP2DB2 Express-C is an entry-level edition of the DB2 database server for the developer community. It has standard relational functionality and includes pureXML, and other features of DB2 for Linux, Unix, and Windows (LUW).https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{E69488DE-FB79-63CD-E51E-79505A1309BD}/2.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{E69488DE-FB79-63CD-E51E-79505A1309BD}/2.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-04-25T00:00:00.000-04:0021c03be6800bf043c0b44c584545e04099Informix Dynamic Server Developer Edition11SYSTEMPUBLICi386SUSE Linux Enterprise/10 SP2Informix Dynamic Server (IDS) Developer Edition is a development version of the IDS Enterprise Edition. IDS is designed to meet the database server needs of small-size to large-size enterprise businesses.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{9B0C8F66-9639-CA0A-0A94-7928D7DAD6CB}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{9B0C8F66-9639-CA0A-0A94-7928D7DAD6CB}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-04-25T00:00:00.000-04:00229b2b6482ba374a6ab4bb3585414a910aWebSphere sMash with AppBuilder11SYSTEMPUBLICi386SUSE Linux Enterprise/10 SP2WebSphere sMash® provides a web platform that includes support for dynamic scripting in PHP and Groovy.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{88E74AC6-9CCB-2710-7E9B-936DA2CE496C}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{88E74AC6-9CCB-2710-7E9B-936DA2CE496C}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-04-25T00:00:00.000-04:001000150416662e71fae44bdba4d7bb502a09c5e7DB2 Enterprise V9.7 (32-bit, 90-day trial)11leonsp@ca.ibm.comPUBLICi386SuSE v10.2DB2 Enterprise V9.7 (32-bit, 90-day trial)https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{38F2AB86-9F03-E463-024D-A9ABC3AE3831}/2.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{38F2AB86-9F03-E463-024D-A9ABC3AE3831}/2.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-11-09T17:01:28.000-05:00100020639da8863714964624b8b13631642c785bRHEL 5.4 Base OS11youngdj@us.ibm.comPUBLICi386Redhat Enterprise Linux (32-bit)/5.4Red Hat Enterprise Linux 5.4 Base OShttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{34904879-E794-A2D8-2D7C-2E8D6AD6AE77}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{34904879-E794-A2D8-2D7C-2E8D6AD6AE77}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2009-11-18T13:51:12.000-05:0010002573e5f09a64667e4faeaf3ac661600ec6caRational Build Forge11leighw@us.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2Rational Build Forge provides an adaptive process execution framework that automates, orchestrates, manages, and tracks all the processes between each handoff within the assembly line of software development, creating an automated software factory.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{22E039C6-108E-B626-ECC9-E2C9B62479FF}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{22E039C6-108E-B626-ECC9-E2C9B62479FF}/1.0/GettingStarted.htmlMEDIUMLARGE2009-12-08T16:34:37.000-05:00100030563e276d758ed842caafe77770d60dedeaRational Asset Manager 7.2.0.111gmendel@us.ibm.comPUBLICi386Redhat Enterprise Linux (32-bit)/5.4Rational Asset Manager helps to create, modify, govern, find and reuse development assets, including SOA and systems development assets. It facilitates the reuse of all types of software development related assets, potentially saving development time.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{296C6DDF-B87B-327B-3E5A-F2C50C353A69}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{296C6DDF-B87B-327B-3E5A-F2C50C353A69}/1.0/GettingStarted.htmlMEDIUMLARGE2009-12-14T14:30:57.000-05:0010003854e3067f999edf4914932295cfb5f79d59WebSphere Portal/WCM 6.1.511mlamb@us.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2IBM® WebSphere® Portal Server enables you to quickly consolidate applications and content into role-based applications, complete with search, personalization, and security capabilities.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{279F3E12-A7EF-0768-135B-F08B66DF8F71}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{279F3E12-A7EF-0768-135B-F08B66DF8F71}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2010-01-12T18:06:29.000-05:00100038640112efd8f1e144998f2a70a165d00bd3Rational Quality Manager11brownms@gmail.comPUBLICi386Redhat Enterprise Linux (32-bit)/5.4Rational Quality Manager provides a collaborative application lifecycle management (ALM) environment for test planning, construction, and execution.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{9DA927BA-2CEF-1686-71B0-2BAC468B7445}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{9DA927BA-2CEF-1686-71B0-2BAC468B7445}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2010-01-15T09:40:12.000-05:00100038653fbf6936e5cb42b5959ad9837add054fIBM Mashup Center with IBM Lotus Widget Factory11mgilmore@us.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2IBM Mashup Center is an end-to-end enterprise mashup platform, supporting rapid assembly of dynamic web applications with the management, security, and governance capabilities.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{0F867D03-588B-BA51-4E18-4CE9D11AECFC}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{0F867D03-588B-BA51-4E18-4CE9D11AECFC}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2010-01-15T10:44:24.000-05:0010003780425e2dfef95647498561f98c4de356abRational Team Concert11sonia_dimitrov@ca.ibm.comPUBLICi386Redhat Enterprise Linux (32-bit)/5.4Rational Team Concert is a collaborative software delivery environment that empowers project teams to simplify, automate and govern software delivery.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{679CA6F5-1E8E-267B-0C84-F7B0B41DF1DC}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{679CA6F5-1E8E-267B-0C84-F7B0B41DF1DC}/1.0/GettingStarted.htmlMEDIUMLARGE2010-01-19T14:13:58.000-05:0010003785c4867b72f2fc43fe982e76c76c32efaaLotus Forms Turbo 3.5.111rlintern@ca.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2Lotus Forms Turbo requires no training and is designed to help customers address basic form software requirements such as surveys, applications, feedback, orders, request for submission, and more - without involvement from the IT department.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{846AD7D3-9A0F-E02C-89D2-BE250CAE2318}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{846AD7D3-9A0F-E02C-89D2-BE250CAE2318}/1.0/GettingStarted.htmlLARGE2010-01-22T13:27:08.000-05:0010005598Rational Requirements Composer11mutdosch@us.ibm.comPUBLICi386Redhat Enterprise Linux (32-bit)/5.4Rational Requirements Composer helps teams define and use requirements effectively across the project lifecycle.https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/GettingStarted.htmlMEDIUMLARGE2010-02-08T11:43:18.000-05:0010007509Rational Software Architecture11danberg@us.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2Rational Software Architect for WebSphere with the Cloud Client plug-ins created on 2/22/10 8:06 PMhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{2C6FB6D2-CB87-C4A0-CDE0-5AAF03E214B2}/1.1/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{2C6FB6D2-CB87-C4A0-CDE0-5AAF03E214B2}/1.1/GettingStarted.htmlLARGE2010-02-22T20:03:18.000-05:0010008319WebSphere Feature Pack for OSGi Apps and JPA 2.011radavenp@us.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2IBM WebSphere Application Server V7.0 Fix Pack 7, Feature Pack for OSGi Applications and Java Persistence API 2.0 Open Beta, and Feature Pack for Service Component Architecture (SCA) V1.0.1 Fix Pack V1.0.1.1https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A397B7CD-A1C7-1956-7AEF-6AB495E37958}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A397B7CD-A1C7-1956-7AEF-6AB495E37958}/1.0/GettingStarted.htmlSMALLMEDIUMLARGE2010-03-14T21:06:38.000-04:0010008273Rational Software Architect for WebSphere11danberg@us.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2Rational Software Architect for WebSphere with the Cloud Client plug-ins created on 3/15/10 12:21 PMhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{839D92BB-DEA5-9820-8E2E-AE5D0A6DEAE3}/1.1/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{839D92BB-DEA5-9820-8E2E-AE5D0A6DEAE3}/1.1/GettingStarted.htmlLARGE2010-03-15T12:17:26.000-04:0010008404Rational Application Developer11khiamt@ca.ibm.comPUBLICi386SUSE Linux Enterprise/10 SP2An Eclipse-based IDE with visual development features that helps Java developers rapidly design, develop, assemble, test, profile and deploy high quality Java/J2EE, Portal, Web/Web 2.0, Web services and SOA applications. (03/16/2010)https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{6A957586-A17A-4927-7C71-0FDE280DB66B}/1.0/parameters.xmlhttps://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{6A957586-A17A-4927-7C71-0FDE280DB66B}/1.0/GettingStarted.htmlMEDIUMLARGE2010-03-16T00:10:30.000-04:00 \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/instances.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/instances.xml deleted file mode 100644 index aecd2d5fed..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/instances.xml +++ /dev/null @@ -1 +0,0 @@ -26557126557Insight Instancewoodser@us.ibm.com11LARGEPublic keyvm519.developer.ihost.com129.33.196.12852010-04-06T15:40:24.745-04:002010-04-19T04:00:00.000-04:00SUSE Linux Enterprise10 SP2OS28193128193RAD instancewoodser@us.ibm.com10008404MEDIUMasdff22010-04-15T15:20:10.317-04:002010-04-22T15:20:19.564-04:00SUSE Linux Enterprise10 SP2OS28194128194RSAwoodser@us.ibm.com10007509LARGEasdff22010-04-15T15:23:04.753-04:002010-04-22T15:23:13.658-04:00SUSE Linux Enterprise10 SP2OS \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/instances_deleted.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/instances_deleted.xml deleted file mode 100644 index 05e8644254..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/instances_deleted.xml +++ /dev/null @@ -1 +0,0 @@ -26557126557Insight Instancewoodser@us.ibm.com11LARGEPublic keyvm519.developer.ihost.com129.33.196.12852010-04-06T15:40:24.745-04:002010-04-19T04:00:00.000-04:00SUSE Linux Enterprise10 SP2OS28194128194RSAwoodser@us.ibm.com10007509LARGEasdff22010-04-15T15:23:04.753-04:002010-04-22T15:23:13.658-04:00SUSE Linux Enterprise10 SP2OS \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_addresses.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_addresses.xml deleted file mode 100644 index 6af5238e0d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_addresses.xml +++ /dev/null @@ -1 +0,0 @@ -
RESERVED170.225.160.218vhost021814129279520001223PRIMARY2user@dmain.com
\ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_storage_offerings.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_storage_offerings.xml deleted file mode 100644 index ed96dc6416..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_storage_offerings.xml +++ /dev/null @@ -1 +0,0 @@ -2000120861Small256256EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000120882Small256256EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000120961Medium512512EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000120982Medium512512EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000120841Small256256EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000120941Medium512512EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001208121Small256256EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001209121Medium512512EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000121061Large20482048EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000121082Large20482048EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR2000121041Large20482048EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001210121Large20482048EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001208101Small256256EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001209101Medium512512EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001208141Small256256EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001209141Medium512512EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001210101Large20482048EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR20001210141Large20482048EXT3RAW2011-08-12T00:00:00.000ZUSD0.00001UHR \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_volumes.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_volumes.xml deleted file mode 100644 index a6c2617604..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/list_volumes.xml +++ /dev/null @@ -1 +0,0 @@ -39281141200012100user@domain.comlibcloudvolraw204842012-08-19T13:46:50.000Z2011-08-12T00:00:00.000ZUSD0.001CNT020 \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/locations.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/locations.xml deleted file mode 100644 index 68012dec35..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/locations.xml +++ /dev/null @@ -1 +0,0 @@ -41Raleigh, U.S.AThis data center is located in Raleigh, North Carolina, U.S.A. The services provided are: Guest Instances, Image Capture, Persistent Storage, Reserved IP, Private VLAN/VPN.RTPext3rawArea2gpfs2 of SONAS1Area1gpfs1 of SONAS1161Ehningen, GermanyThis data center is located in Ehningen(near Baden-Wurttemberg), Germany. The services provided are: Guest Instances, Image Capture, Persistent Storage, Reserved IP, Private VLAN/VPN.EHNext3rawArea2gpfs2 of SONAS1Area1gpfs1 of SONAS1182Boulder1, U.S.AThis data center is located in Boulder(near Denver), Colorado, U.S.A. The services provided are: Guest Instances, Image Capture, Persistent Storage, Reserved IP, Private VLAN/VPN.us-co-dc1ext3raw1101Markham, CanadaThis data center is located in Markham(near Toronto), Ontario, Canada. The services provided are: Guest Instances, Image Capture, Persistent Storage, Reserved IP, Private VLAN/VPN.ca-on-dc1ext3raw1121Makuhari, JapanThis data center is located in Makuhari(near Tokoyo), Japan. The services provided are: Guest Instances, Image Capture, Persistent Storage, Reserved IP, Private VLAN/VPN.ap-jp-dc1ext3raw1141Singapore, SingaporeThis data center is located in Singapore. The services provided are: Guest Instances, Image Capture, Persistent Storage, Reserved IP, Private VLAN/VPN.ap-sg-dc1ext3raw1 \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/reboot_active.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/reboot_active.xml deleted file mode 100644 index 2a43c1cbaf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/reboot_active.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/sizes.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/sizes.xml deleted file mode 100644 index 2a43c1cbaf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ibm_sce/sizes.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_datasets.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_datasets.json deleted file mode 100644 index 75c6fe291b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_datasets.json +++ /dev/null @@ -1 +0,0 @@ -[{"id":"f953e97e-4991-11e1-9ea4-27c6e7e8afda","urn":"sdc:sdc:nodejs:1.3.3","name":"nodejs","os":"smartos","type":"smartmachine","description":"Node.js git-deploy PaaS dataset","default":false,"requirements":{},"version":"1.3.3","created":"2012-02-14T03:54:01+00:00"},{"id":"71101322-43a5-11e1-8f01-cf2a3031a7f4","urn":"sdc:sdc:ubuntu-10.04:1.0.1","name":"ubuntu-10.04","os":"linux","type":"virtualmachine","description":"Ubuntu 10.04 VM 1.0.1","default":false,"requirements":{},"version":"1.0.1","created":"2012-02-22T18:27:32+00:00"},{"id":"7a4f84be-df6d-11e0-a504-3f6609d83831","urn":"sdc:admin:windows2008r2:1.5.0","name":"windows2008r2","os":"windows","type":"virtualmachine","description":"Windows 2008r2 Enterprise Edition","default":false,"requirements":{"max_memory":32768,"min_memory":4096},"version":"1.5.0","created":"2012-02-16T19:31:01+00:00"},{"id":"e4cd7b9e-4330-11e1-81cf-3bb50a972bda","urn":"sdc:sdc:centos-6:1.0.1","name":"centos-6","os":"linux","type":"virtualmachine","description":"Centos 6 VM 1.0.1","default":false,"requirements":{},"version":"1.0.1","created":"2012-02-15T20:04:18+00:00"},{"id":"988c2f4e-4314-11e1-8dc3-2bc6d58f4be2","urn":"sdc:sdc:centos-5.7:1.2.1","name":"centos-5.7","os":"linux","type":"virtualmachine","description":"Centos 5.7 VM 1.2.1","default":false,"requirements":{},"version":"1.2.1","created":"2012-02-14T05:53:49+00:00"},{"id":"e6ac6784-44b3-11e1-8555-87c3dd87aafe","urn":"sdc:sdc:debian-6.03:1.0.0","name":"debian-6.03","os":"linux","type":"virtualmachine","description":"Debian 6.03 VM 1.0.0","default":false,"requirements":{},"version":"1.0.0","created":"2012-02-14T05:21:53+00:00"},{"id":"3f8a3d02-43e4-11e1-9565-7f82a075e289","urn":"sdc:sdc:fedora-14:1.0.1","name":"fedora-14","os":"linux","type":"virtualmachine","description":"Fedora 14 VM 1.0.1","default":false,"requirements":{},"version":"1.0.1","created":"2012-02-14T05:20:52+00:00"},{"id":"d239389c-7535-11e1-b60a-6f75edc139df","urn":"sdc:sdc:mongodb:1.2.4","name":"mongodb","os":"smartos","type":"smartmachine","description":"MongoDB SmartMachine","default":false,"requirements":{},"version":"1.2.4","created":"2012-03-23T22:33:31+00:00"},{"id":"98f38e14-6f83-11e1-bc32-2b9d0a8b6759","urn":"sdc:sdc:mongodb:1.1.1","name":"mongodb","os":"smartos","type":"smartmachine","description":"MongoDB SmartMachine","default":false,"requirements":{},"version":"1.1.1","created":"2012-03-16T16:54:14+00:00"},{"id":"64d81cee-689e-11e1-a130-232647306089","urn":"local:admin:stingray-standard-1gbps:1.2.0","name":"stingray-standard-1gbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager Hi-Throughput SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:40+00:00"},{"id":"29a2fb18-689d-11e1-a2a5-47b01f708bb0","urn":"local:admin:stingray-enterprise-1gbps:1.2.0","name":"stingray-enterprise-1gbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager Enterprise Hi-Throughput SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:12+00:00"},{"id":"27750b5c-689c-11e1-a67e-6331aba2c777","urn":"local:admin:stingray-enterprise-200mbps:1.2.0","name":"stingray-enterprise-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager Enterprise SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:19+00:00"},{"id":"56ffd3bc-689b-11e1-837f-735e255247ac","urn":"local:admin:stingray-standard-200mbps:1.2.0","name":"stingray-standard-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:49+00:00"},{"id":"c79e581a-689a-11e1-91f3-932bbde56874","urn":"local:admin:stingray-lb-200mbps:1.2.0","name":"stingray-lb-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Load Balancer SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:26+00:00"},{"id":"4ca85e3a-689a-11e1-a5df-1b5ffe7065e9","urn":"local:admin:stingray-simple-lb-200mbps:1.2.0","name":"stingray-simple-lb-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Simple Load Balancer SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:33+00:00"},{"id":"8c4c0f30-66df-11e1-a3f4-0f8e0a382b60","urn":"sdc:sdc:percona:1.3.9","name":"percona","os":"smartos","type":"smartmachine","description":"Percona SmartMachine","default":false,"requirements":{},"version":"1.3.9","created":"2012-03-05T16:41:01+00:00"},{"id":"618d80f8-66d5-11e1-998e-e384c47940f0","urn":"sdc:sdc:mongodb:1.0.9","name":"mongodb","os":"smartos","type":"smartmachine","description":"MongoDB SmartMachine","default":false,"requirements":{},"version":"1.0.9","created":"2012-03-05T15:29:21+00:00"},{"id":"a54da3a0-6319-11e1-a3d9-9fdedd2f9e17","urn":"sdc:sdc:riak:1.5.6","name":"riak","os":"smartos","type":"smartmachine","description":"Riak SmartMachine template","default":false,"requirements":{},"version":"1.5.6","created":"2012-03-01T16:18:13+00:00"},{"id":"81641caa-6321-11e1-a79a-731161c6d519","urn":"local:admin:riakeds:1.5.6","name":"riakeds","os":"smartos","type":"smartmachine","description":"Riak EDS SmartMachine template","default":false,"requirements":{},"version":"1.5.6","created":"2012-03-01T19:52:37+00:00"},{"id":"f4bc70ca-5e2c-11e1-8380-fb28785857cb","urn":"sdc:sdc:smartosplus64:3.1.0","name":"smartosplus64","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.1.0","created":"2012-03-02T15:30:58+00:00"},{"id":"a963d5d0-5e29-11e1-a4d7-a31977b1e6dd","urn":"sdc:sdc:smartosplus:3.1.0","name":"smartosplus","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.1.0","created":"2012-03-02T15:24:10+00:00"},{"id":"31bc4dbe-5e06-11e1-907c-5bed6b255fd1","urn":"sdc:sdc:smartos64:1.5.4","name":"smartos64","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.5.4","created":"2012-03-02T15:20:17+00:00"},{"id":"489754f2-5e01-11e1-8ff8-f770c2116b0d","urn":"sdc:sdc:smartos:1.5.4","name":"smartos","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.5.4","created":"2012-03-02T15:16:12+00:00"},{"id":"e05dbcac-1d44-11e1-b8ab-bf1bc04c2d65","urn":"sdc:sdc:smartosplus64:3.0.7","name":"smartosplus64","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.7","created":"2012-02-13T19:18:56+00:00"},{"id":"fcc5996a-1d34-11e1-899e-7bd98b87947a","urn":"sdc:sdc:smartosplus:3.0.7","name":"smartosplus","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.7","created":"2012-02-13T19:22:05+00:00"},{"id":"5fef6eda-05f2-11e1-90fc-13dac5e4a347","urn":"sdc:sdc:percona:1.2.2","name":"percona","os":"smartos","type":"smartmachine","description":"Percona SmartMachine","default":false,"requirements":{},"version":"1.2.2","created":"2012-02-13T19:23:12+00:00"},{"id":"34359ccc-21d2-2e4e-87e8-69fb36412008","urn":"sdc:sdc:windows2008r2standard:1.5.1","name":"windows2008r2standard","os":"windows","type":"virtualmachine","description":"windows2008r2standard VM image","default":false,"requirements":{"max_memory":32768,"min_memory":4096},"version":"1.5.1","created":"2012-03-13T18:25:53+00:00"},{"id":"a9380908-ea0e-11e0-aeee-4ba794c83c33","urn":"sdc:sdc:percona:1.0.7","name":"percona","os":"smartos","type":"smartmachine","description":"Percona SmartMachine","default":false,"requirements":{},"version":"1.0.7","created":"2012-02-13T19:24:17+00:00"},{"id":"df3589dc-df9a-11e0-a3a3-07ceee3e7d54","urn":"sdc:sdc:smartosplus64:3.0.4","name":"smartosplus64","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.4","created":"2012-02-13T19:27:27+00:00"},{"id":"aded640a-df98-11e0-b050-1f55ff3ddfa7","urn":"sdc:sdc:smartosplus:3.0.4","name":"smartosplus","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.4","created":"2012-02-13T19:30:28+00:00"},{"id":"3fcf35d2-dd79-11e0-bdcd-b3c7ac8aeea6","urn":"sdc:sdc:mysql:1.4.1","name":"mysql","os":"smartos","type":"smartmachine","description":"MySQL SmartMachine","default":false,"requirements":{},"version":"1.4.1","created":"2012-02-13T19:32:51+00:00"},{"id":"141194fa-dd77-11e0-8539-27dd8d8264b8","urn":"sdc:sdc:smartos64:1.4.7","name":"smartos64","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.4.7","created":"2012-02-13T19:33:21+00:00"},{"id":"f8ea0bb8-dd75-11e0-87c3-af5352ad3bd6","urn":"sdc:sdc:smartos:1.4.7","name":"smartos","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.4.7","created":"2012-02-13T19:33:50+00:00"}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_machines.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_machines.json deleted file mode 100644 index 1446492487..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_machines.json +++ /dev/null @@ -1,2 +0,0 @@ -[{"id":"2fb67f5f-53f2-40ab-9d99-b9ff68cfb2ab","name":"testlc1","type":"virtualmachine","state":"running","dataset":"sdc:sdc:ubuntu-10.04:1.0.1","ips":["165.225.129.129","10.112.1.130"],"memory":1024,"disk":30720,"metadata":{"root_authorized_keys":"ssh-rsa abc== JoyentSSH\n"},"created":"2012-04-11T04:08:32+00:00","updated":"2012-04-11T04:08:42+00:00"}, -{"id":"2fb67f5f-53f2-40ab-9d99-b9ff68cfb2ab","name":"testlc2","type":"virtualmachine","state":"running","dataset":"sdc:sdc:ubuntu-10.04:1.0.1","ips":["165.225.129.128","10.112.1.131"],"memory":1024,"disk":30720,"metadata":{"root_authorized_keys":"ssh-rsa abc== Joyent SSH\n", "credentials": {"root": "abc"}},"created":"2012-04-11T04:08:32+00:00","updated":"2012-04-11T04:08:42+00:00"}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_machines_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_machines_create.json deleted file mode 100644 index 7565823735..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_machines_create.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"2fb67f5f-53f2-40ab-9d99-b9ff68cfb2ab","name":"testlc","type":"virtualmachine","state":"provisioning","dataset":"sdc:sdc:ubuntu-10.04:1.0.1","ips":["165.225.129.129","10.112.1.130"],"memory":1024,"disk":30720,"metadata":{"root_authorized_keys":"ssh-rsa abcd== Joyent SSH\n"},"created":"2012-04-11T04:08:27+00:00","updated":"2012-04-11T04:08:27+00:00"} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_packages.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_packages.json deleted file mode 100644 index a38acde0b3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/joyent/my_packages.json +++ /dev/null @@ -1 +0,0 @@ -[{"name":"Large 16GB","memory":16384,"disk":491520,"vcpus":3,"swap":32768,"default":false},{"name":"XL 8GB High CPU","memory":8192,"disk":245760,"vcpus":4,"swap":16384,"default":false},{"name":"XL 32GB","memory":32768,"disk":778240,"vcpus":4,"swap":65536,"default":false},{"name":"XXL 48GB","memory":49152,"disk":1048576,"vcpus":8,"swap":98304,"default":false},{"name":"XXXL 64GB ","memory":65536,"disk":1572864,"vcpus":12,"swap":131072,"default":false},{"name":"Medium 1GB High-CPU","memory":1024,"disk":61440,"vcpus":2,"swap":2048,"default":false},{"name":"Small 1GB","memory":1024,"disk":30720,"vcpus":1,"swap":2048,"default":true},{"name":"Medium 2GB","memory":2048,"disk":61440,"vcpus":1,"swap":4096,"default":false},{"name":"Medium 4GB","memory":4096,"disk":122880,"vcpus":1,"swap":8192,"default":false},{"name":"Large 8GB","memory":8192,"disk":245760,"vcpus":2,"swap":16384,"default":false}] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_default.json deleted file mode 100644 index 5fbec216b1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"jobid":17164,"id":2602} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail.json deleted file mode 100644 index 2162fe1a0a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"errorcode" : 431, "errortext" : "Unable to find service offering: 104"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail2.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail2.json deleted file mode 100644 index 05790d2f42..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail2.json +++ /dev/null @@ -1 +0,0 @@ -{ "deployvirtualmachineresponse" : {"jobid":17177,"id":2602} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/destroyVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/destroyVirtualMachine_default.json deleted file mode 100644 index dfd664f9ea..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/destroyVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "destroyvirtualmachineresponse" : {"jobid":17166} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_default.json deleted file mode 100644 index d121e3372c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_default.json +++ /dev/null @@ -1 +0,0 @@ -{"listavailableproducttypesresponse":{"count":112,"producttypes":[{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-829-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-829-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-829-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-829-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-829-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-829-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-829-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-829-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-830-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-830-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-830-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-830-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-830-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-830-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-830-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-830-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-867-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-867-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-867-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-867-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-867-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-867-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-867-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-867-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-880-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-880-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-880-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-880-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-880-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-880-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-880-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-880-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-881-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-881-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-881-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-881-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-881-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-881-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-881-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-881-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-877-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-877-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-877-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-877-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-877-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-877-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-877-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-877-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-878-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-878-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-878-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-878-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-878-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-878-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-878-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-878-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-988-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-988-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-988-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-988-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-988-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-988-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-988-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-988-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-986-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-986-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-986-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-986-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-986-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-986-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-986-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-986-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-989-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-989-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-989-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-989-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-989-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-989-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-989-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-989-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-990-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-990-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-990-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-990-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-990-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-990-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-990-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-990-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-991-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-991-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-991-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-991-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-991-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-991-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-991-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-991-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1111-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1111-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1111-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1111-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1111-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1111-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1111-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1111-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1109-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1109-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1109-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1109-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1109-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1109-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1109-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1109-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"}]}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_nodisk.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_nodisk.json deleted file mode 100644 index e799b122ce..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_nodisk.json +++ /dev/null @@ -1 +0,0 @@ -{"listavailableproducttypesresponse": {"count": 2, "producttypes": [{"diskofferingdesc": "100GB", "templatedesc": "Centos 5.4 32bit", "serviceofferingdesc": "premium 2vCore 2GB RAM", "productstate": "available", "product": "Standard", "zoneid": "eceb5d65-6571-4696-875f-5a17949f3317", "zonedesc": "KOR-Central A", "templateid": "d2241244-0b6c-444d-b075-72cfcd562826", "diskofferingid": "cc85e4dd-bfd9-4cec-aa22-cf226c1da92f", "serviceofferingid": "94341d94-ccd4-4dc4-9ccb-05c0c632d0b4", "productid": "eceb5d65-6571-4696-875f-5a17949f3317-d2241244-0b6c-444d-b075-72cfcd562826-94341d94-ccd4-4dc4-9ccb-05c0c632d0b4-cc85e4dd-bfd9-4cec-aa22-cf226c1da92f"}, {"diskofferingdesc": "20GB", "templatedesc": "Centos 5.4 32bit", "serviceofferingdesc": "premium 2vCore 2GB RAM", "productstate": "available", "product": "Standard", "zoneid": "eceb5d65-6571-4696-875f-5a17949f3317", "zonedesc": "KOR-Central A", "templateid": "d2241244-0b6c-444d-b075-72cfcd562826", "serviceofferingid": "94341d94-ccd4-4dc4-9ccb-05c0c632d0b4", "productid": "eceb5d65-6571-4696-875f-5a17949f3317-d2241244-0b6c-444d-b075-72cfcd562826-94341d94-ccd4-4dc4-9ccb-05c0c632d0b4-0"}]}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_notemplates.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_notemplates.json deleted file mode 100644 index 5f1604cf55..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_notemplates.json +++ /dev/null @@ -1 +0,0 @@ -{ "listavailableproducttypesresponse" : { "count" : 0, "producttypes" : [] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listPortForwardingRules_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listPortForwardingRules_default.json deleted file mode 100644 index 460645c549..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listPortForwardingRules_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listportforwardingrulesresponse" : {"count": 1, "portforwardingrule": [{"protocol": "tcp", "virtualmachineid": "7d8de712-aa7a-4901-a8b1-fd223f0ca459", "ipaddress": "178.170.71.253", "cidrlist": "", "tags": [], "ipaddressid": "50cd9456-d4db-4a48-8cf5-950dba8d2fdb", "virtualmachinedisplayname": "yoyo", "privateendport": "22", "state": "Active", "publicendport": "22", "privateport": "22", "virtualmachinename": "yoyo", "publicport": "22", "id": "4644652a-7573-4e50-aafb-48a171c9bcb2"}]}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listPublicIpAddresses_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listPublicIpAddresses_default.json deleted file mode 100644 index b9b8527df5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listPublicIpAddresses_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listpublicipaddressesresponse" : { "publicipaddress" : [ {"id":34000,"ipaddress":"1.1.1.49","allocated":"2011-06-23T05:20:39+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33999,"ipaddress":"1.1.1.48","allocated":"2011-06-23T05:20:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33998,"ipaddress":"1.1.1.47","allocated":"2011-06-23T05:20:30+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33970,"ipaddress":"1.1.1.19","allocated":"2011-06-20T04:08:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":true,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listVirtualMachines_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listVirtualMachines_default.json deleted file mode 100644 index d55c436b2e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listVirtualMachines_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listvirtualmachinesresponse" : { "virtualmachine" : [ {"id":2600,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:06:42+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"1.78%","networkkbsread":2,"networkkbswrite":2,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3891,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.116","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}, {"id":2601,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:09:44+0000","state":"Starting","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"jobid":17147,"jobstatus":0,"nic":[{"id":3892,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.203","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listZones_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listZones_default.json deleted file mode 100644 index 0316936e45..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/listZones_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17164.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17164.json deleted file mode 100644 index 31fd39e97c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17164.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17164,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17165.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17165.json deleted file mode 100644 index 694d7d032e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17165.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17165,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17166.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17166.json deleted file mode 100644 index 5245af2d3d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17166.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Destroyed","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17177.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17177.json deleted file mode 100644 index 7b743c54c8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17177.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17177,"jobstatus":2} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_attachvolumejob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_attachvolumejob.json deleted file mode 100644 index cd5278f8e0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_attachvolumejob.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.AttachVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","deviceid":5,"virtualmachineid":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmname":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmdisplayname":"gre-kickstart","vmstate":"Running","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Ready","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"KVM","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering 1","diskofferingdisplaytext":"Disk offering 1 display name","storage":"Shared Storage CL01","attached":"2012-06-05T09:17:38+0200","destroyed":false,"isextractable":false}},"created":"2012-06-05T09:17:38+0200","jobid":"e07d6b9b-2b6c-45bd-840b-3c4c3d890168"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_createvolumejob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_createvolumejob.json deleted file mode 100644 index 9955c93250..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_createvolumejob.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.CreateVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Allocated","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"None","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering","diskofferingdisplaytext":"Disk offering display name","storage":"none","destroyed":false,"isextractable":false}},"created":"2012-06-05T08:47:54+0200","jobid":"35416f6d-1b5b-4ceb-a7d4-aab0deede71b"} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/rebootVirtualMachine_default.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/rebootVirtualMachine_default.json deleted file mode 100644 index 07cdba36a1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/ktucloud/rebootVirtualMachine_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "rebootvirtualmachineresponse" : {"jobid":17165} } diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_datacenters.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_datacenters.json deleted file mode 100644 index eb169623b1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_datacenters.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": [ - { - "LOCATION": "Dallas, TX, USA", - "DATACENTERID": 2, - "ABBR": "dallas" - }, - { - "LOCATION": "Fremont, CA, USA", - "DATACENTERID": 3, - "ABBR": "fremont" - }, - { - "LOCATION": "Atlanta, GA, USA", - "DATACENTERID": 4, - "ABBR": "atlanta" - }, - { - "LOCATION": "Newark, NJ, USA", - "DATACENTERID": 6, - "ABBR": "newark" - }, - { - "LOCATION": "London, England, UK", - "DATACENTERID": 7, - "ABBR": "london" - }, - { - "LOCATION": "Tokyo, JP", - "DATACENTERID": 8, - "ABBR": "tokyo" - } - ], - "ACTION": "avail.datacenters" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_distributions.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_distributions.json deleted file mode 100644 index f1bdee61b9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_distributions.json +++ /dev/null @@ -1,246 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": [ - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 112, - "IS64BIT": 1, - "LABEL": "Arch Linux 2013.06", - "MINIMAGESIZE": 500, - "CREATE_DT": "2013-06-06 02:45:11.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 89, - "IS64BIT": 1, - "LABEL": "CentOS 6.2", - "MINIMAGESIZE": 800, - "CREATE_DT": "2011-07-19 11:38:20.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 78, - "IS64BIT": 1, - "LABEL": "Debian 6", - "MINIMAGESIZE": 550, - "CREATE_DT": "2011-02-08 16:54:31.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 109, - "IS64BIT": 1, - "LABEL": "Debian 7", - "MINIMAGESIZE": 660, - "CREATE_DT": "2013-05-08 11:31:32.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 114, - "IS64BIT": 1, - "LABEL": "Fedora 19", - "MINIMAGESIZE": 750, - "CREATE_DT": "2013-08-26 15:29:21.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 53, - "IS64BIT": 1, - "LABEL": "Gentoo", - "MINIMAGESIZE": 1000, - "CREATE_DT": "2009-04-04 00:00:00.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 115, - "IS64BIT": 1, - "LABEL": "openSUSE 12.3", - "MINIMAGESIZE": 1024, - "CREATE_DT": "2013-09-19 10:49:09.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 87, - "IS64BIT": 1, - "LABEL": "Slackware 13.37", - "MINIMAGESIZE": 600, - "CREATE_DT": "2011-06-05 15:11:59.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 65, - "IS64BIT": 1, - "LABEL": "Ubuntu 10.04 LTS", - "MINIMAGESIZE": 450, - "CREATE_DT": "2010-04-29 00:00:00.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 99, - "IS64BIT": 1, - "LABEL": "Ubuntu 12.04 LTS", - "MINIMAGESIZE": 600, - "CREATE_DT": "2012-04-26 17:25:16.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 111, - "IS64BIT": 1, - "LABEL": "Ubuntu 13.04", - "MINIMAGESIZE": 770, - "CREATE_DT": "2013-05-08 11:31:32.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 113, - "IS64BIT": 0, - "LABEL": "Arch Linux 2013.06 32bit", - "MINIMAGESIZE": 500, - "CREATE_DT": "2013-06-06 02:45:11.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 88, - "IS64BIT": 0, - "LABEL": "CentOS 6.2 32bit", - "MINIMAGESIZE": 800, - "CREATE_DT": "2011-07-19 11:38:20.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 77, - "IS64BIT": 0, - "LABEL": "Debian 6 32bit", - "MINIMAGESIZE": 550, - "CREATE_DT": "2011-02-08 16:54:31.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 108, - "IS64BIT": 0, - "LABEL": "Debian 7 32bit", - "MINIMAGESIZE": 660, - "CREATE_DT": "2013-05-08 11:31:32.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 72, - "IS64BIT": 0, - "LABEL": "Gentoo 32bit", - "MINIMAGESIZE": 1000, - "CREATE_DT": "2010-09-13 00:00:00.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 86, - "IS64BIT": 0, - "LABEL": "Slackware 13.37 32bit", - "MINIMAGESIZE": 600, - "CREATE_DT": "2011-06-05 15:11:59.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 64, - "IS64BIT": 0, - "LABEL": "Ubuntu 10.04 LTS 32bit", - "MINIMAGESIZE": 450, - "CREATE_DT": "2010-04-29 00:00:00.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 98, - "IS64BIT": 0, - "LABEL": "Ubuntu 12.04 LTS 32bit", - "MINIMAGESIZE": 600, - "CREATE_DT": "2012-04-26 17:25:16.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 110, - "IS64BIT": 0, - "LABEL": "Ubuntu 13.04 32bit", - "MINIMAGESIZE": 770, - "CREATE_DT": "2013-05-08 11:31:32.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 105, - "IS64BIT": 1, - "LABEL": "Arch Linux 2012.10", - "MINIMAGESIZE": 500, - "CREATE_DT": "2012-10-22 15:00:49.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 60, - "IS64BIT": 1, - "LABEL": "CentOS 5.6 64bit", - "MINIMAGESIZE": 950, - "CREATE_DT": "2009-08-17 00:00:00.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 100, - "IS64BIT": 1, - "LABEL": "Fedora 17", - "MINIMAGESIZE": 800, - "CREATE_DT": "2012-05-31 16:03:49.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 97, - "IS64BIT": 1, - "LABEL": "openSUSE 12.1", - "MINIMAGESIZE": 1000, - "CREATE_DT": "2012-04-13 11:43:30.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 107, - "IS64BIT": 1, - "LABEL": "Ubuntu 12.10", - "MINIMAGESIZE": 660, - "CREATE_DT": "2012-11-06 11:51:25.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 104, - "IS64BIT": 0, - "LABEL": "Arch Linux 2012.10 32bit", - "MINIMAGESIZE": 500, - "CREATE_DT": "2012-10-22 15:00:49.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 59, - "IS64BIT": 0, - "LABEL": "CentOS 5.6 32bit", - "MINIMAGESIZE": 950, - "CREATE_DT": "2009-08-17 00:00:00.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 101, - "IS64BIT": 0, - "LABEL": "Fedora 17 32bit", - "MINIMAGESIZE": 800, - "CREATE_DT": "2012-05-31 16:03:49.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 96, - "IS64BIT": 0, - "LABEL": "openSUSE 12.1 32bit", - "MINIMAGESIZE": 1000, - "CREATE_DT": "2012-04-13 11:43:30.0" - }, - { - "REQUIRESPVOPSKERNEL": 1, - "DISTRIBUTIONID": 106, - "IS64BIT": 0, - "LABEL": "Ubuntu 12.10 32bit", - "MINIMAGESIZE": 660, - "CREATE_DT": "2012-11-06 11:51:25.0" - } - ], - "ACTION": "avail.distributions" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_kernels.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_kernels.json deleted file mode 100644 index 9552c46c5f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_kernels.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ERRORARRAY": [], - "ACTION": "avail.kernels", - "DATA": [ - { - "LABEL": "Latest 2.6 Stable (2.6.18.8-linode19)", - "ISXEN": 1, - "KERNELID": 60 - }, - { - "LABEL": "2.6.18.8-linode19", - "ISXEN": 1, - "KERNELID": 103 - }, - { - "LABEL": "2.6.30.5-linode20", - "ISXEN": 1, - "KERNELID": 105 - }, - { - "LABEL": "Latest 2.6 Stable (2.6.18.8-x86_64-linode7)", - "ISXEN": 1, - "KERNELID": 107 - }, - { - "LABEL": "2.6.18.8-x86_64-linode7", - "ISXEN": 1, - "KERNELID": 104 - }, - { - "LABEL": "2.6.30.5-x86_64-linode8", - "ISXEN": 1, - "KERNELID": 106 - }, - { - "LABEL": "pv-grub-x86_32", - "ISXEN": 1, - "KERNELID": 92 - }, - { - "LABEL": "pv-grub-x86_64", - "ISXEN": 1, - "KERNELID": 95 - }, - { - "LABEL": "Recovery - Finnix (kernel)", - "ISXEN": 1, - "KERNELID": 61 - }, - { - "LABEL": "2.6.18.8-domU-linode7", - "ISXEN": 1, - "KERNELID": 81 - }, - { - "LABEL": "2.6.18.8-linode10", - "ISXEN": 1, - "KERNELID": 89 - }, - { - "LABEL": "2.6.18.8-linode16", - "ISXEN": 1, - "KERNELID": 98 - }, - { - "LABEL": "2.6.24.4-linode8", - "ISXEN": 1, - "KERNELID": 84 - }, - { - "LABEL": "2.6.25-linode9", - "ISXEN": 1, - "KERNELID": 88 - }, - { - "LABEL": "2.6.25.10-linode12", - "ISXEN": 1, - "KERNELID": 90 - }, - { - "LABEL": "2.6.26-linode13", - "ISXEN": 1, - "KERNELID": 91 - }, - { - "LABEL": "2.6.27.4-linode14", - "ISXEN": 1, - "KERNELID": 93 - }, - { - "LABEL": "2.6.28-linode15", - "ISXEN": 1, - "KERNELID": 96 - }, - { - "LABEL": "2.6.28.3-linode17", - "ISXEN": 1, - "KERNELID": 99 - }, - { - "LABEL": "2.6.29-linode18", - "ISXEN": 1, - "KERNELID": 101 - }, - { - "LABEL": "2.6.16.38-x86_64-linode2", - "ISXEN": 1, - "KERNELID": 85 - }, - { - "LABEL": "2.6.18.8-x86_64-linode1", - "ISXEN": 1, - "KERNELID": 86 - }, - { - "LABEL": "2.6.27.4-x86_64-linode3", - "ISXEN": 1, - "KERNELID": 94 - }, - { - "LABEL": "2.6.28-x86_64-linode4", - "ISXEN": 1, - "KERNELID": 97 - }, - { - "LABEL": "2.6.28.3-x86_64-linode5", - "ISXEN": 1, - "KERNELID": 100 - }, - { - "LABEL": "2.6.29-x86_64-linode6", - "ISXEN": 1, - "KERNELID": 102 - }, - { - "LABEL": "3.9.3-x86-linode52", - "ISXEN": 1, - "KERNELID": 137 - }, - { - "LABEL": "3.9.3-x86_64-linode33", - "ISXEN": 1, - "KERNELID": 138 - } - ] -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_linodeplans.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_linodeplans.json deleted file mode 100644 index c492e626a6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_avail_linodeplans.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": [{ - "PRICE": 20.00, - "RAM": 2048, - "XFER": 3000, - "PLANID": 1, - "LABEL": "Linode 2048", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 48 - }, { - "PRICE": 40.00, - "RAM": 4096, - "XFER": 4000, - "PLANID": 3, - "LABEL": "Linode 4096", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 96 - }, { - "PRICE": 80.00, - "RAM": 8192, - "XFER": 8000, - "PLANID": 5, - "LABEL": "Linode 8192", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 192 - }, { - "PRICE": 160.00, - "RAM": 16384, - "XFER": 16000, - "PLANID": 6, - "LABEL": "Linode 16384", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 384 - }, { - "PRICE": 320.00, - "RAM": 32768, - "XFER": 20000, - "PLANID": 7, - "LABEL": "Linode 32768", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 768 - }, { - "PRICE": 480.00, - "RAM": 49152, - "XFER": 20000, - "PLANID": 8, - "LABEL": "Linode 49152", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 1152 - }, { - "PRICE": 640.00, - "RAM": 65536, - "XFER": 20000, - "PLANID": 9, - "LABEL": "Linode 65536", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 1536 - }, { - "PRICE": 960.00, - "RAM": 98304, - "XFER": 20000, - "PLANID": 11, - "LABEL": "Linode 98304", - "AVAIL": { - "3": 500, - "2": 500, - "7": 500, - "6": 500, - "4": 500, - "8": 500 - }, - "DISK": 1920 - }], - "ACTION": "avail.linodeplans" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_batch.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_batch.json deleted file mode 100644 index 36e28f9050..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_batch.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "ERRORARRAY": [], - "DATA": [ - { - "IPADDRESSID": 5384, - "RDNS_NAME": "li22-54.members.linode.com", - "LINODEID": 8098, - "ISPUBLIC": 1, - "IPADDRESS": "66.228.43.47" - }, - { - "IPADDRESSID": 5575, - "RDNS_NAME": "li22-245.members.linode.com", - "LINODEID": 8098, - "ISPUBLIC": 1, - "IPADDRESS": "75.127.96.245" - } - ], - "ACTION": "linode.ip.list" - } -] diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_linode_ip_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_linode_ip_list.json deleted file mode 100644 index 33a969ca68..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_linode_ip_list.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "ACTION": "linode.ip.list", - "DATA": [ - { - "IPADDRESS": "66.228.43.47", - "IPADDRESSID": 5384, - "ISPUBLIC": 1, - "LINODEID": 8098, - "RDNS_NAME": "li22-54.members.linode.com" - }, - { - "IPADDRESS": "75.127.96.245", - "IPADDRESSID": 5575, - "ISPUBLIC": 1, - "LINODEID": 8098, - "RDNS_NAME": "li22-245.members.linode.com" - } - ], - "ERRORARRAY": [] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_linode_list.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_linode_list.json deleted file mode 100644 index 4baf897257..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/linode/_linode_list.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": [ - { - "ALERT_CPU_ENABLED": 1, - "ALERT_BWIN_ENABLED": 1, - "ALERT_BWQUOTA_ENABLED": 1, - "BACKUPWINDOW": 0, - "ALERT_DISKIO_THRESHOLD": 1000, - "DISTRIBUTIONVENDOR": "Debian", - "WATCHDOG": 1, - "DATACENTERID": 6, - "STATUS": 1, - "ALERT_DISKIO_ENABLED": 1, - "CREATE_DT": "2012-05-04 19:31:30.0", - "TOTALHD": 49152, - "ALERT_BWQUOTA_THRESHOLD": 80, - "TOTALRAM": 2048, - "ALERT_BWIN_THRESHOLD": 5, - "LINODEID": 8098, - "ALERT_BWOUT_THRESHOLD": 5, - "ALERT_BWOUT_ENABLED": 1, - "BACKUPSENABLED": 1, - "ALERT_CPU_THRESHOLD": 90, - "PLANID": "1", - "BACKUPWEEKLYDAY": 0, - "LABEL": "api-node3", - "LPM_DISPLAYGROUP": "test", - "TOTALXFER": 3000 - } - ], - "ACTION": "linode.list" -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/meta/helloworld.txt b/awx/lib/site-packages/libcloud/test/compute/fixtures/meta/helloworld.txt deleted file mode 100644 index b45ef6fec8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/meta/helloworld.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, World! \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/misc/dummy_rsa b/awx/lib/site-packages/libcloud/test/compute/fixtures/misc/dummy_rsa deleted file mode 100644 index 7f0cd9e530..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/misc/dummy_rsa +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAs0ya+QTUpUyAxbFWN81CbW23D7Fm8O1wxP3l0UPu9OO/dAES -irxNxbBEanTGb8HMdaLEdLBlXaYAIlf8+YhG+c9o7kKe8kCR3j4hJ3x0x/fTVSTf -mNQc7XIUaM9tuCGj/fO2zfn3fD5fztWAwssPm1+cyP3pAgvc/H03SNpdQG05ylZ+ -1I2QYymYtbjzGh9Nen6dN/aSDrZI7yIA1o3hsDoiY2Nb82l958UI3uJKaxGeBSpO -Mshutar3gWa/v9F6uqHDTmFEqQdvQGdCHHyWuz98jMVUc0kvWjdH5q5X95CBZFQM -uOQPNxn2aYjMaP7pU2jvfrU0sLpWT/tG8ZApJwIDAQABAoIBAECotZJr7YuW5TFl -3GPPP89aq5ObNDZaSjqgHUq0Ju5lW1uoL1mcwqcyA9ooNo+C4griIdq66jM1dALu -nCoYvQ/Ffl+94rgWFQSCf05QEYUzmCCyZXgltjDi3P1XIIgwiYVBaIErTdaeX8ql -MAQPWpd7iXzqJCc6w/zB4zgAl3Rt1Fb8GBFHlYf3VTpiU9LA5/IG04GoPk80OgiW -98lercisWT+nPrTMDu2GoEqqls8OkM9CcT5AgeXIpSF9nPmQgUQWXoqWkrZhD+eQ -mOxCqpqzwkW/JdsUaBqhPAJtK/eBHTPAfsOabQ5G6/Un1HejN0GTIR0GJzTSEOvi -blM3YuECgYEA53XL8c8S5ckc1BGfM22obY1daAVgFqsNpqVSV4OKKnRlcmtYaUXq -61vrQN/OG9Ogrr7FuL7HwavJnr3IbT8uET1/pUje/NQviERwSZWiNX++GUCSXUvq -hSe9LZb3ezTEkUROdGXOfl+TfI/bhojsk6egaqqKAVv8LR92cwzMD28CgYEAxk8T -x278NOLUn+F6ije186xpcI0JV+NydhXk40ViDHc7M2ycHNArc6iJzQIlQjkEDejK -yae3c3QMVtszwONSd6wPkPr9bLbiiT0UlG5gpGAGyEyYZjMQukg2e8ImnwMVMm2l -bJsrDI5CRq4G20CWPDqxzs8FTuX78tX4uewzJckCgYBmi1a2o8JAkZA3GDOLClsj -Zgzq5+7BPDlJCldntDxDQNwtDAfYZASHD2szi7P5uhGnOZfJmKRRVnV14ajpVaNo -OfHSXW2FX9BLM973itaZkyW6dFQkB104bvmuOAMez6sCnNuRUAVjEZ77AZUFjqYZ -aJt2hmWr4n/f0d+dax8A+wKBgEVV7LJ0KZZMIM9txKyC4gk6pPsHNNcX3TNQYGDe -J3P4VCicttCUMD0WFmgpceF/kd1TIWP0Uf35+z57EdNFJ9ZTwHWObAEQyI/3XTSw -ivWt5XEu5rIE9LpM+U+4CEzchRLGp2obrqeLLb0Mp7UNFfolA3otg8ucOcUj7v0C -ireRAoGAMM5MDDtWyduLH9srxC3PBKdD4Hi8dtzkQ9yAFYTJ0HB4vV7MmIZ2U2j7 -x2KTrPc/go/Jm7+UOmVa4LNkdRvXxVOlAxH85Hqr+n74mm/dWcS4dDWrZvL+Sn+l -GFa29M3Ix5SnlfFkZhijvTFLICC7XPTRj6uqVHscZVfENhAYGoU= ------END RSA PRIVATE KEY----- diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/misc/dummy_rsa.pub b/awx/lib/site-packages/libcloud/test/compute/fixtures/misc/dummy_rsa.pub deleted file mode 100644 index f51e5aad1f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/misc/dummy_rsa.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzTJr5BNSlTIDFsVY3zUJtbbcPsWbw7XDE/eXRQ+704790ARKKvE3FsERqdMZvwcx1osR0sGVdpgAiV/z5iEb5z2juQp7yQJHePiEnfHTH99NVJN+Y1BztchRoz224IaP987bN+fd8Pl/O1YDCyw+bX5zI/ekCC9z8fTdI2l1AbTnKVn7UjZBjKZi1uPMaH016fp039pIOtkjvIgDWjeGwOiJjY1vzaX3nxQje4kprEZ4FKk4yyG61qveBZr+/0Xq6ocNOYUSpB29AZ0IcfJa7P3yMxVRzSS9aN0fmrlf3kIFkVAy45A83GfZpiMxo/ulTaO9+tTSwulZP+0bxkCkn dummycomment diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_images.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_images.json deleted file mode 100644 index 1ede35dfcd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_images.json +++ /dev/null @@ -1,243 +0,0 @@ -{ - "success": true, - "total_count": 18, - "subcode": 0, - "message": "Your request was processed successfully.", - "data": [ - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux CentOS 5.5 32-bit", - "uri": "https://api.nephoscale.com/image/server/3/", - "max_memory": 128, - "id": 3, - "is_default": true, - "create_time": "2010-12-20 14:25:36", - "architecture": "x86", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux CentOS 5.5 64-bit", - "uri": "https://api.nephoscale.com/image/server/5/", - "max_memory": 128, - "id": 5, - "is_default": true, - "create_time": "2010-12-20 14:25:36", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Windows Server 2008 64-bit", - "uri": "https://api.nephoscale.com/image/server/21/", - "max_memory": 128, - "id": 21, - "is_default": true, - "create_time": "2010-12-20 14:25:36", - "architecture": "x86_64", - "base_type": "windows" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Debian Server 5.05 32-bit", - "uri": "https://api.nephoscale.com/image/server/23/", - "max_memory": 128, - "id": 23, - "is_default": true, - "create_time": "2010-12-20 16:51:20", - "architecture": "x86", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Debian Server 5.05 64-bit", - "uri": "https://api.nephoscale.com/image/server/25/", - "max_memory": 128, - "id": 25, - "is_default": true, - "create_time": "2010-12-20 16:55:42", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Windows Server 2003 Enterprise 64-bit", - "uri": "https://api.nephoscale.com/image/server/33/", - "max_memory": 128, - "id": 33, - "is_default": true, - "create_time": "2011-03-02 14:20:49", - "architecture": "x86_64", - "base_type": "windows" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux CentOS 5.7 64-bit", - "uri": "https://api.nephoscale.com/image/server/41/", - "max_memory": 128, - "id": 41, - "is_default": true, - "create_time": "2011-09-19 17:30:04", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Ubuntu Server 10.04 LTS 32-bit", - "uri": "https://api.nephoscale.com/image/server/43/", - "max_memory": 128, - "id": 43, - "is_default": true, - "create_time": "2011-10-01 02:26:17", - "architecture": "x86", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux CentOS 5.7 32-bit", - "uri": "https://api.nephoscale.com/image/server/45/", - "max_memory": 128, - "id": 45, - "is_default": true, - "create_time": "2011-10-05 19:41:30", - "architecture": "x86", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Ubuntu Server 10.04 LTS 64-bit", - "uri": "https://api.nephoscale.com/image/server/49/", - "max_memory": 128, - "id": 49, - "is_default": true, - "create_time": "2011-10-08 05:01:10", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Debian Server 6.0.3 64-bit", - "uri": "https://api.nephoscale.com/image/server/51/", - "max_memory": 128, - "id": 51, - "is_default": true, - "create_time": "2011-10-08 19:54:41", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Debian 5.0.9 64-bit", - "uri": "https://api.nephoscale.com/image/server/55/", - "max_memory": 128, - "id": 55, - "is_default": false, - "create_time": "2011-10-13 12:53:36", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Debian 5.0.9 32-bit", - "uri": "https://api.nephoscale.com/image/server/57/", - "max_memory": 128, - "id": 57, - "is_default": false, - "create_time": "2011-10-13 12:55:09", - "architecture": "x86", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux CentOS 6.2 64-bit", - "uri": "https://api.nephoscale.com/image/server/59/", - "max_memory": 128, - "id": 59, - "is_default": true, - "create_time": "2011-10-15 17:11:34", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux CentOS 5.8 64-bit", - "uri": "https://api.nephoscale.com/image/server/64/", - "max_memory": 128, - "id": 64, - "is_default": true, - "create_time": "2012-03-28 19:54:10", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Ubuntu Server 12.04 LTS 64-bit", - "uri": "https://api.nephoscale.com/image/server/75/", - "max_memory": 128, - "id": 75, - "is_default": true, - "create_time": "2012-05-18 08:41:03", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "cloud", - "is_active": true, - "friendly_name": "VOD Cloud Storage Proxy (FTP:HTTP)", - "uri": "https://api.nephoscale.com/image/server/101/", - "max_memory": 128, - "id": 101, - "is_default": false, - "create_time": "2012-08-30 08:49:55", - "architecture": "x86_64", - "base_type": "linux" - }, - { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Debian 7.1 64-bit", - "uri": "https://api.nephoscale.com/image/server/177/", - "max_memory": 128, - "id": 177, - "is_default": true, - "create_time": "2013-09-10 16:12:10", - "architecture": "x86_64", - "base_type": "linux" - } - ], - "response": 200 -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_keys.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_keys.json deleted file mode 100644 index f6f9205ec7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_keys.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "success": true, - "total_count": 2, - "subcode": 0, - "message": "Your request was processed successfully.", - "data": [ - { - "name": "mistio-ssh", - "key_group": 1, - "uri": "https://api.nephoscale.com/key/sshrsa/72209/", - "key_type": 2, - "create_time": "2013-10-02 07:24:37", - "id": 72209 - }, - { - "name": "mistio-testing", - "key_group": 4, - "uri": "https://api.nephoscale.com/key/password/72211/", - "key_type": 1, - "create_time": "2013-10-02 07:27:10", - "id": 72211 - } - ], - "response": 200 -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_locations.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_locations.json deleted file mode 100644 index 952fac4b6e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_locations.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "success": true, - "total_count": 2, - "subcode": 0, - "message": "Your request was processed successfully.", - "data": [ - { - "datacenter": { - "airport_code": "SJC", - "name": "SJC-1", - "uri": "https://api.nephoscale.com/datacenter/1/", - "id": 1 - }, - "uri": "https://api.nephoscale.com/datacenter/zone/86945/", - "id": 86945, - "name": "SJC-1" - }, - { - "datacenter": { - "airport_code": "RIC", - "name": "RIC-1", - "uri": "https://api.nephoscale.com/datacenter/3/", - "id": 3 - }, - "uri": "https://api.nephoscale.com/datacenter/zone/87729/", - "id": 87729, - "name": "RIC-1" - } - ], - "response": 200 -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_nodes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_nodes.json deleted file mode 100644 index 7fdff6c7a6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_nodes.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "success": true, - "total_count": 2, - "subcode": 0, - "message": "Your request was processed successfully.", - "data": [ - { - "server_keys": [ - { - "key_type": 2, - "key_group": 1, - "id": 71757, - "uri": "https://api.nephoscale.com/key/sshrsa/71157/" - } - ], - "name": "mongodb-staging", - "zone": { - "uri": "https://api.nephoscale.com/datacenter/zone/88211/", - "id": 87729, - "name": "RIC-1" - }, - "image": { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Ubuntu Server 10.04 LTS 64-bit", - "uri": "https://api.nephoscale.com/image/server/49/", - "max_memory": 128, - "id": 49, - "is_default": true, - "create_time": "2011-10-08 05:01:10", - "architecture": "x86_64", - "has_agent": true, - "base_type": "linux" - }, - "hostname": "mongodb-staging", - "podzone": "P1A2", - "uri": "https://api.nephoscale.com/server/cloud/87241/", - "ipaddresses": "198.89.117.16", - "power_status": "on", - "create_time": "2013-09-25 07:38:53", - "postinit_state": 1, - "console_keys": [ - { - "key_type": 1, - "key_group": 4, - "id": 71761, - "uri": "https://api.nephoscale.com/key/password/71761/" - } - ], - "memory": 512, - "service_type": { - "sku": { - "name": "CS05", - "description": "Cloud Server 0.5 GB RAM, 1 Core" - }, - "uri": "https://api.nephoscale.com/server/type/cloud/5/", - "friendly_name": "CS05 - 0.5GB, 1Core, 25GB", - "id": 5, - "billable_type": 1 - }, - "network_ports": [ - { - "macaddress": "00:16:3e:06:dc:41", - "devname": "eth0", - "network_domain": { - "domain_type": 0, - "name": "default_public_network_RIC" - } - }, - { - "macaddress": "00:16:3e:06:dc:45", - "devname": "eth1", - "network_domain": { - "domain_type": 1, - "name": "default_private_network_RIC" - } - } - ], - "id": 88241, - "is_console_enabled": true - }, - { - "server_keys": [ - { - "key_type": 2, - "key_group": 1, - "id": 72049, - "uri": "https://api.nephoscale.com/key/sshrsa/72049/" - } - ], - "name": "backup-server2", - "zone": { - "uri": "https://api.nephoscale.com/datacenter/zone/88751/", - "id": 87729, - "name": "RIC-1" - }, - "image": { - "max_cpu": 64, - "deployable_type": "both", - "is_active": true, - "friendly_name": "Linux Debian Server 6.0.3 64-bit", - "uri": "https://api.nephoscale.com/image/server/51/", - "max_memory": 128, - "id": 51, - "is_default": true, - "create_time": "2011-10-08 19:54:41", - "architecture": "x86_64", - "has_agent": true, - "base_type": "linux" - }, - "hostname": "backup-server2", - "podzone": "P1A2", - "uri": "https://api.nephoscale.com/server/cloud/88751/", - "ipaddresses": "198.89.112.115", - "power_status": "on", - "create_time": "2013-10-02 05:02:50", - "postinit_state": 1, - "console_keys": [ - { - "key_type": 1, - "key_group": 4, - "id": 72165, - "uri": "https://api.nephoscale.com/key/password/72165/" - } - ], - "memory": 512, - "service_type": { - "sku": { - "name": "CS05", - "description": "Cloud Server 0.5 GB RAM, 1 Core" - }, - "uri": "https://api.nephoscale.com/server/type/cloud/5/", - "friendly_name": "CS05 - 0.5GB, 1Core, 25GB", - "id": 5, - "billable_type": 1 - }, - "network_ports": [ - { - "macaddress": "00:16:3e:06:f5:2f", - "devname": "eth0", - "network_domain": { - "domain_type": 0, - "name": "default_public_network_RIC" - } - }, - { - "macaddress": "00:16:3e:06:f5:33", - "devname": "eth1", - "network_domain": { - "domain_type": 1, - "name": "default_private_network_RIC" - } - } - ], - "id": 88751, - "is_console_enabled": true - } - ], - "response": 200 -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json deleted file mode 100644 index ca3c629f7f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "success": true, - "total_count": 1, - "subcode": 0, - "message": "Your request was processed successfully.", - "data": [ - { - "name": "mistio-testing", - "key_group": 4, - "uri": "https://api.nephoscale.com/key/password/72211/", - "key_type": 1, - "create_time": "2013-10-02 07:27:10", - "password": "23d493j5", - "id": 72211 - } - ], - "response": 200 -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_sizes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_sizes.json deleted file mode 100644 index c6d89f398e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_sizes.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "success": true, - "total_count": 13, - "subcode": 0, - "message": "Your request was processed successfully.", - "data": [ - { - "sku": { - "name": "CS16.16", - "description": "Cloud Server 16 GB RAM, 16 Cores" - }, - "storage": 800, - "ram": 16384, - "friendly_name": "CS16.16 - 16GB, 16Core, 800GB", - "uri": "https://api.nephoscale.com/server/type/cloud/1/", - "vcpus": 16, - "id": 1, - "billable_type": 1 - }, - { - "sku": { - "name": "CS1", - "description": "Cloud Server 1 GB RAM, 1 Core" - }, - "storage": 50, - "ram": 1024, - "friendly_name": "CS1 - 1GB, 1Core, 50GB", - "uri": "https://api.nephoscale.com/server/type/cloud/3/", - "vcpus": 1, - "id": 3, - "billable_type": 1 - }, - { - "sku": { - "name": "CS05", - "description": "Cloud Server 0.5 GB RAM, 1 Core" - }, - "storage": 25, - "ram": 512, - "friendly_name": "CS05 - 0.5GB, 1Core, 25GB", - "uri": "https://api.nephoscale.com/server/type/cloud/5/", - "vcpus": 1, - "id": 5, - "billable_type": 1 - }, - { - "sku": { - "name": "CS2.2", - "description": "Cloud Server 2 GB RAM, 2 Cores" - }, - "storage": 100, - "ram": 2048, - "friendly_name": "CS2.2 - 2GB, 2Core, 100GB", - "uri": "https://api.nephoscale.com/server/type/cloud/7/", - "vcpus": 2, - "id": 7, - "billable_type": 1 - }, - { - "sku": { - "name": "CS4.4", - "description": "Cloud Server 4 GB RAM, 4 Cores" - }, - "storage": 200, - "ram": 4096, - "friendly_name": "CS4.4 - 4GB, 4Core, 200GB", - "uri": "https://api.nephoscale.com/server/type/cloud/9/", - "vcpus": 4, - "id": 9, - "billable_type": 1 - }, - { - "sku": { - "name": "CS8.8", - "description": "Cloud Server 8 GB RAM, 8 Cores" - }, - "storage": 400, - "ram": 8192, - "friendly_name": "CS8.8 - 8GB, 8Core, 400GB", - "uri": "https://api.nephoscale.com/server/type/cloud/11/", - "vcpus": 8, - "id": 11, - "billable_type": 1 - }, - { - "sku": { - "name": "CS025", - "description": "Cloud Server 0.25 GB RAM" - }, - "storage": 15, - "ram": 256, - "friendly_name": "CS025 - 0.25GB, 10GB", - "uri": "https://api.nephoscale.com/server/type/cloud/27/", - "vcpus": 1, - "id": 27, - "billable_type": 1 - }, - { - "sku": { - "name": "CS2.1", - "description": "Cloud Server 2 GB RAM, 1 Core" - }, - "storage": 75, - "ram": 2048, - "friendly_name": "CS2.1 - 2GB, 1Core, 75GB", - "uri": "https://api.nephoscale.com/server/type/cloud/46/", - "vcpus": 1, - "id": 46, - "billable_type": 1 - }, - { - "sku": { - "name": "CS4.2", - "description": "Cloud Server 4 GB RAM, 2 Cores" - }, - "storage": 150, - "ram": 4096, - "friendly_name": "CS4.2 - 4GB, 2Core, 150GB", - "uri": "https://api.nephoscale.com/server/type/cloud/48/", - "vcpus": 2, - "id": 48, - "billable_type": 1 - }, - { - "sku": { - "name": "CS8.4", - "description": "Cloud Server 8 GB RAM, 4 Cores" - }, - "storage": 300, - "ram": 8192, - "friendly_name": "CS8.4 - 8GB, 4Core, 300GB", - "uri": "https://api.nephoscale.com/server/type/cloud/50/", - "vcpus": 4, - "id": 50, - "billable_type": 1 - }, - { - "sku": { - "name": "CS16.8", - "description": "Cloud Server 16 GB RAM, 8 Cores" - }, - "storage": 600, - "ram": 16384, - "friendly_name": "CS16.8 - 16GB, 8Core, 600GB", - "uri": "https://api.nephoscale.com/server/type/cloud/52/", - "vcpus": 8, - "id": 52, - "billable_type": 1 - }, - { - "sku": { - "name": "CS32.16", - "description": "Cloud Server 32 GB RAM, 16 Cores" - }, - "storage": 1200, - "ram": 32768, - "friendly_name": "CS32.16 - 32GB, 16Core, 1200GB", - "uri": "https://api.nephoscale.com/server/type/cloud/54/", - "vcpus": 16, - "id": 54, - "billable_type": 1 - }, - { - "sku": { - "name": "CS32.8", - "description": "Cloud Server 32 GB RAM, 8 Cores" - }, - "storage": 1000, - "ram": 32768, - "friendly_name": "CS32.8 - 32GB, 8Core, 1000GB", - "uri": "https://api.nephoscale.com/server/type/cloud/56/", - "vcpus": 8, - "id": 56, - "billable_type": 1 - } - ], - "response": 200 -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json deleted file mode 100644 index dc83a8f0c0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "success": true, - "total_count": 1, - "subcode": 0, - "message": "Your request was processed successfully.", - "data": [ - { - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBs+gQwoeFNa+4pYz2AKz5Op7EqrzeP3YsyTKxx7P9gt4aSt5w8Z+lRn3p3CVG+th5i6lZqOxWgCZ1kp2KEKNbSsA2HWl3OwkY8IqHGSEeMrF+3A2Ncz88kUIAWzCswxPY4uqb/yA4EzEQDk7PJj7Q1DruObhOm7qyHT40n2KJ3TqHJQlV9XE3RcXSaQcwUt0YFXFMx8wkgy0NKqqSiQuH8RofyfnOABEzKAARGbcQjZWxh2ITzUmwMxUCBa0X5wvblgcE6/pRZN5Xq6NQr2XEU5Z48+mLy6asdasdwrM0v10Y7ojDL/TosK/8T5+d5yaRsvtBlBstDZhNWY31n5iCLxx user@mistio", - "name": "mistio-ssh", - "key_group": 1, - "uri": "https://api.nephoscale.com/key/sshrsa/72209/", - "key_type": 2, - "create_time": "2013-10-02 07:24:37", - "id": 72209 - } - ], - "response": 200 -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/success_action.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/success_action.json deleted file mode 100644 index 62db155664..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/nephoscale/success_action.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "subcode": 0, - "message": "Your request was processed successfully.", - "data": { - "id": 141229, - "resource_type": "/job", - "uri": "https://api.nephoscale.com/job/141229/" - }, - "response": 202, - "success": true -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_15.xml deleted file mode 100644 index 80d4f1bb9d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_15.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - 15 - Compute 15 - ACTIVE - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_25.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_25.xml deleted file mode 100644 index abc8b49ac3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_25.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - 25 - Compute 25 - none - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_5.xml deleted file mode 100644 index 5bb10a9b16..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/compute_5.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - 5 - Compute 5 - ACTIVE - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/computes.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/computes.xml deleted file mode 100644 index 2f6a082f52..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/computes.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/disk_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/disk_15.xml deleted file mode 100644 index b187c2df75..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/disk_15.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 15 - Ubuntu 9.04 LAMP - 2048 - file:///images/ubuntu/jaunty.img - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/disk_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/disk_5.xml deleted file mode 100644 index 657db8c68d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/disk_5.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 5 - Ubuntu 9.04 LAMP - 2048 - file:///images/ubuntu/jaunty.img - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/network_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/network_15.xml deleted file mode 100644 index 14b600d79e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/network_15.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 15 - Network 15 -
192.168.1.0
- 256 -
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/network_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/network_5.xml deleted file mode 100644 index a043250e27..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/network_5.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 5 - Network 5 -
192.168.0.0
- 256 -
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/networks.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/networks.xml deleted file mode 100644 index 5c7c301ab9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/networks.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/storage.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/storage.xml deleted file mode 100644 index 99c5a65c43..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_1_4/storage.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_15.xml deleted file mode 100644 index 0fdb625f54..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_15.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 15 - Compute 15 - small - ACTIVE - - - DISK - hda - - - - 192.168.0.2 - 02:00:c0:a8:00:02 - - - - 192.168.1.2 - 02:00:c0:a8:01:02 - - - compute-15 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_25.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_25.xml deleted file mode 100644 index 94daadb24e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_25.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 25 - Compute 25 - none - none - - - 192.168.0.3 - 02:00:c0:a8:00:03 - - - - 192.168.1.3 - 02:00:c0:a8:01:03 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_5.xml deleted file mode 100644 index 691ff76365..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_5.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 5 - Compute 5 - small - ACTIVE - - - DISK - hda - - - - 192.168.0.1 - 02:00:c0:a8:00:01 - - - - 192.168.1.1 - 02:00:c0:a8:01:01 - - - compute-5 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_collection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_collection.xml deleted file mode 100644 index f3fd581152..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/compute_collection.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_15.xml deleted file mode 100644 index 14b600d79e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_15.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 15 - Network 15 -
192.168.1.0
- 256 -
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_5.xml deleted file mode 100644 index a043250e27..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_5.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 5 - Network 5 -
192.168.0.0
- 256 -
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_collection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_collection.xml deleted file mode 100644 index 02765bcfab..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/network_collection.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_15.xml deleted file mode 100644 index ad342896d0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_15.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - 15 - Ubuntu 9.04 LAMP - OS - Ubuntu 9.04 LAMP Description - 2048 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_5.xml deleted file mode 100644 index 3e11aab7b3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_5.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - 5 - Ubuntu 9.04 LAMP - OS - Ubuntu 9.04 LAMP Description - 2048 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_collection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_collection.xml deleted file mode 100644 index f521125eb5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_2_0/storage_collection.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_15.xml deleted file mode 100644 index 9126be01f4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_15.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - 15 - Network 15 -
192.168.1.0
- 256 - NO -
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_5.xml deleted file mode 100644 index ece9266303..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_5.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - 5 - Network 5 -
192.168.0.0
- 256 - YES -
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_collection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_collection.xml deleted file mode 100644 index 02765bcfab..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_0/network_collection.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_2/compute_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_2/compute_5.xml deleted file mode 100644 index 691ff76365..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_2/compute_5.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 5 - Compute 5 - small - ACTIVE - - - DISK - hda - - - - 192.168.0.1 - 02:00:c0:a8:00:01 - - - - 192.168.1.1 - 02:00:c0:a8:01:01 - - - compute-5 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_2/instance_type_collection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_2/instance_type_collection.xml deleted file mode 100644 index 228098adaf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_2/instance_type_collection.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - small - 1 - 1024 - - - medium - 4 - 4096 - - - large - 8 - 8192 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/compute_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/compute_15.xml deleted file mode 100644 index ce928ecfd0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/compute_15.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 15 - Compute 15 Test - small - ACTIVE - - - FILE - hda - - - - 192.168.122.2 - 02:00:c0:a8:7a:02 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/compute_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/compute_5.xml deleted file mode 100644 index 6767122d49..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/compute_5.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - 5 - Compute 5 Test - small - ACTIVE - - - FILE - hda - - - - FILE - sda - - - - 192.168.122.2 - 02:00:c0:a8:7a:02 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/disk_10.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/disk_10.xml deleted file mode 100644 index 1da6fa241b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/disk_10.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 10 - Debian 7.1 LAMP - 2048 - file:///images/debian/wheezy.img - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/disk_15.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/disk_15.xml deleted file mode 100644 index 811369bf5d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/disk_15.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 15 - Debian Sid - 1024 - file:///images/debian/sid.img - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/storage_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/storage_5.xml deleted file mode 100644 index 27aaf735ea..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_6/storage_5.xml +++ /dev/null @@ -1,13 +0,0 @@ - - 5 - test-volume - - oneadmin - READY - DATABLOCK - Attached storage - 1000 - ext3 - NO - YES - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_collection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_collection.xml deleted file mode 100644 index 97523ac41b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_collection.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_large.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_large.xml deleted file mode 100644 index 141d5b666b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_large.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - large - 8 - 8192 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_medium.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_medium.xml deleted file mode 100644 index 97bd72f3ec..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_medium.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - medium - 4 - 4096 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_small.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_small.xml deleted file mode 100644 index 346e640f40..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_small.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - small - 1 - 1024 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/300_multiple_choices.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/300_multiple_choices.json deleted file mode 100644 index 51e3100efc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/300_multiple_choices.json +++ /dev/null @@ -1,7 +0,0 @@ -{"choices": [{"status": "CURRENT", "media-types": [{"base": -"application/xml", "type": -"application/vnd.openstack.compute+xml;version=2"}, {"base": -"application/json", "type": -"application/vnd.openstack.compute+json;version=2"}], "id": "v2.0", -"links": [{"href": "http://50.56.213.226:8774/v2/v2.0/images/detail", -"rel": "self"}]}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth.json deleted file mode 100644 index 365551d952..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "auth": { - "token": { - "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", - "expires": "2031-11-23T21:00:14-06:00" - }, - "serviceCatalog": { - "cloudFilesCDN": [ - { - "region": "ORD", - "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS", - "v1Default": true - }, - { - "region": "LON", - "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS", - "v1Default": false - } - ], - "cloudFiles": [ - { - "region": "ORD", - "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS", - "v1Default": true, - "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS" - }, - { - "region": "LON", - "publicURL": "https://storage101.lon1.clouddrive.com/v1/MossoCloudFS", - "v1Default": false, - "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS" - } - ], - "cloudServers": [ - { - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/slug", - "v1Default": true - } - ] - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth_mssing_token.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth_mssing_token.json deleted file mode 100644 index db0c3d1ada..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth_mssing_token.json +++ /dev/null @@ -1 +0,0 @@ -{"auth":{"token":{"expires":"2011-09-18T02:44:17.000-05:00"},"serviceCatalog":{"cloudFilesCDN":[{"region":"ORD","publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS","v1Default":true}],"cloudFiles":[{"region":"ORD","publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS","v1Default":true,"internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS"}],"cloudServers":[{"publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/slug","v1Default":true}]}}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth_unauthorized.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth_unauthorized.json deleted file mode 100644 index bdf8a74b83..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v1_1__auth_unauthorized.json +++ /dev/null @@ -1 +0,0 @@ -{"unauthorized":{"message":"Username or api key is invalid","code":401}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth.json deleted file mode 100644 index c40a8ee21c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth.json +++ /dev/null @@ -1,142 +0,0 @@ -{ - "access": { - "token": { - "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", - "expires": "2031-11-23T21:00:14.000-06:00" - }, - "serviceCatalog": [ - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - } - ], - "name": "cloudFilesCDN", - "type": "rax:object-cdn" - }, - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - } - ], - "name": "cloudFiles", - "type": "object-store" - }, - { - "endpoints": [ - { - "tenantId": "1337", - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", - "version": { - "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", - "versionList": "https://servers.api.rackspacecloud.com/", - "versionId": "1.0" - } - } - ], - "name": "cloudServers", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "RegionOne", - "tenantId": "1337", - "publicURL": "https://127.0.0.1/v2/1337", - "versionInfo": "https://127.0.0.1/v2/", - "versionList": "https://127.0.0.1/", - "versionId": "2" - } - ], - "name": "nova", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "613469", - "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", - "versionList": "https://dfw.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "ORD", - "tenantId": "613469", - "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", - "versionList": "https://ord.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "IAD", - "tenantId": "613469", - "publicURL": "https://iad.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://iad.servers.api.rackspacecloud.com/v2/", - "versionList": "https://iad.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "SYD", - "tenantId": "613469", - "publicURL": "https://syd.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://syd.servers.api.rackspacecloud.com/v2/", - "versionList": "https://syd.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "HKG", - "tenantId": "613469", - "publicURL": "https://hkg.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://hkg.servers.api.rackspacecloud.com/v2/", - "versionList": "https://hkg.servers.api.rackspacecloud.com/", - "versionId": "2" - } - - ], - "name": "cloudServersOpenStack", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "1337", - "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/1337" - } - ], - "name": "cloudServersPreprod", - "type": "compute" - } - ], - "user": { - "id": "7", - "roles": [ - { - "id": "identity:default", - "description": "Default Role.", - "name": "identity:default" - } - ], - "name": "testuser" - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth_deployment.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth_deployment.json deleted file mode 100644 index b3d16294a6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth_deployment.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "access": { - "token": { - "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", - "expires": "2031-11-23T21:00:14.000-06:00" - }, - "serviceCatalog": [ - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - } - ], - "name": "cloudFilesCDN", - "type": "rax:object-cdn" - }, - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - } - ], - "name": "cloudFiles", - "type": "object-store" - }, - { - "endpoints": [ - { - "tenantId": "slug", - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/slug", - "version": { - "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", - "versionList": "https://servers.api.rackspacecloud.com/", - "versionId": "1.0" - } - } - ], - "name": "cloudServers", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "RegionOne", - "tenantId": "slug", - "publicURL": "https://127.0.0.1/v2/slug", - "versionInfo": "https://127.0.0.1/v2/", - "versionList": "https://127.0.0.1/", - "versionId": "2" - } - ], - "name": "nova", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "613469", - "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/slug", - "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", - "versionList": "https://dfw.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "ORD", - "tenantId": "613469", - "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/slug", - "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", - "versionList": "https://ord.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "IAD", - "tenantId": "613469", - "publicURL": "https://iad.servers.api.rackspacecloud.com/v2/slug", - "versionInfo": "https://iad.servers.api.rackspacecloud.com/v2/", - "versionList": "https://iad.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "SYD", - "tenantId": "613469", - "publicURL": "https://syd.servers.api.rackspacecloud.com/v2/slug", - "versionInfo": "https://syd.servers.api.rackspacecloud.com/v2/", - "versionList": "https://syd.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "HKG", - "tenantId": "613469", - "publicURL": "https://hkg.servers.api.rackspacecloud.com/v2/slug", - "versionInfo": "https://hkg.servers.api.rackspacecloud.com/v2/", - "versionList": "https://hkg.servers.api.rackspacecloud.com/", - "versionId": "2" - } - - - ], - "name": "cloudServersOpenStack", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "slug", - "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/slug" - } - ], - "name": "cloudServersPreprod", - "type": "compute" - } - ], - "user": { - "id": "7", - "roles": [ - { - "id": "identity:default", - "description": "Default Role.", - "name": "identity:default" - } - ], - "name": "testuser" - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth_lon.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth_lon.json deleted file mode 100644 index ba4a10d8ef..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/_v2_0__auth_lon.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "access": { - "token": { - "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", - "expires": "2031-11-23T21:00:14.000-06:00" - }, - "serviceCatalog": [ - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - } - ], - "name": "cloudFilesCDN", - "type": "rax:object-cdn" - }, - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", - "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - } - ], - "name": "cloudFiles", - "type": "object-store" - }, - { - "endpoints": [ - { - "tenantId": "1337", - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", - "version": { - "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", - "versionList": "https://servers.api.rackspacecloud.com/", - "versionId": "1.0" - } - } - ], - "name": "cloudServers", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "RegionOne", - "tenantId": "1337", - "publicURL": "https://127.0.0.1/v2/1337", - "versionInfo": "https://127.0.0.1/v2/", - "versionList": "https://127.0.0.1/", - "versionId": "2" - } - ], - "name": "nova", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "LON", - "tenantId": "613469", - "publicURL": "https://lon.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://lon.servers.api.rackspacecloud.com/v2/", - "versionList": "https://lon.servers.api.rackspacecloud.com/", - "versionId": "2" - } - ], - "name": "cloudServersOpenStack", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "LON", - "tenantId": "1337", - "publicURL": "https://preprod.lon.servers.api.rackspacecloud.com/v2/1337" - } - ], - "name": "cloudServersPreprod", - "type": "compute" - } - ], - "user": { - "id": "7", - "roles": [ - { - "id": "identity:default", - "description": "Default Role.", - "name": "identity:default" - } - ], - "name": "testuser" - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_flavors_detail.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_flavors_detail.xml deleted file mode 100644 index 9a1f313be2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_flavors_detail.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_images_detail.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_images_detail.xml deleted file mode 100644 index 5a2ae7f693..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_images_detail.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_images_post.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_images_post.xml deleted file mode 100644 index 302e94b357..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_images_post.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_limits.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_limits.xml deleted file mode 100644 index 89bd811cb4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_limits.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers.xml deleted file mode 100644 index eeb150cc3e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail.xml deleted file mode 100644 index ae2d47741b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_missing.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_missing.xml deleted file mode 100644 index a2d75bab7c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_missing.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_multiple_nodes.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_multiple_nodes.xml deleted file mode 100644 index 44babd89df..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_multiple_nodes.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_pending.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_pending.xml deleted file mode 100644 index a35609b565..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_pending.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_same_uuid.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_same_uuid.xml deleted file mode 100644 index cc31715ccf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_same_uuid.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_success.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_success.xml deleted file mode 100644 index 6d8a120289..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_success.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_empty.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_empty.xml deleted file mode 100644 index 49fae832e3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_empty.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_metadata.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_metadata.xml deleted file mode 100644 index 714199689b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_metadata.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - somevalue - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_ips.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_ips.xml deleted file mode 100644 index cf7b9274de..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_ips.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_metadata.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_metadata.xml deleted file mode 100644 index c9ad5d65cc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_metadata.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - b - d - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_no_admin_pass.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_no_admin_pass.xml deleted file mode 100644 index e9b9d35115..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_servers_no_admin_pass.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_group.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_group.xml deleted file mode 100644 index 01df93817f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_group.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups.xml deleted file mode 100644 index 3654b3402e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups_detail.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups_detail.xml deleted file mode 100644 index fa368bd969..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups_detail.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/README b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/README deleted file mode 100644 index 47bdca9c5e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/README +++ /dev/null @@ -1,7 +0,0 @@ -The json responses contained in this directory are copied directly from the -OpenStack 1.1 documentation at -http://docs.openstack.org/trunk/openstack-compute/developer/openstack-compute-api-1.1/ -as of this writing. - -The only exception is _os_quota_sets_aTenantId.json, which was captured (and -perturbed) via packet capture. diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_7.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_7.json deleted file mode 100644 index 900d1b1d25..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_7.json +++ /dev/null @@ -1 +0,0 @@ -{"flavor": {"rxtx_quota": 2500, "name": "15.5GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/7", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/7", "rel": "bookmark"}], "ram": 16384, "vcpus": 8, "rxtx_cap": 200, "swap": 0, "disk": 620, "id": 7}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_detail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_detail.json deleted file mode 100644 index 46739e0df8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_detail.json +++ /dev/null @@ -1 +0,0 @@ -{"flavors": [{"rxtx_quota": 2500, "name": "15.5GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/7", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/7", "rel": "bookmark"}], "ram": 16384, "vcpus": 8, "rxtx_cap": 200, "swap": 0, "disk": 620, "id": 7}, {"rxtx_quota": 600, "name": "1GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/3", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/3", "rel": "bookmark"}], "ram": 1024, "vcpus": 1, "rxtx_cap": 30, "swap": 0, "disk": 40, "id": 3}, {"rxtx_quota": 150, "name": "256 slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/1", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/1", "rel": "bookmark"}], "ram": 256, "vcpus": 1, "rxtx_cap": 10, "swap": 0, "disk": 10, "id": 1}, {"rxtx_quota": 1200, "name": "2GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/4", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/4", "rel": "bookmark"}], "ram": 2048, "vcpus": 2, "rxtx_cap": 60, "swap": 0, "disk": 80, "id": 4}, {"rxtx_quota": 2500, "name": "30GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/8", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/8", "rel": "bookmark"}], "ram": 30720, "vcpus": 8, "rxtx_cap": 400, "swap": 0, "disk": 1200, "id": 8}, {"rxtx_quota": 2500, "name": "4GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/5", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/5", "rel": "bookmark"}], "ram": 4096, "vcpus": 2, "rxtx_cap": 100, "swap": 0, "disk": 160, "id": 5}, {"rxtx_quota": 300, "name": "512 slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/2", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}], "ram": 512, "vcpus": 1, "rxtx_cap": 20, "swap": 0, "disk": 20, "id": 2}, {"rxtx_quota": 2500, "name": "8GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/6", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/6", "rel": "bookmark"}], "ram": 8192, "vcpus": 4, "rxtx_cap": 150, "swap": 0, "disk": 320, "id": 6}]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip.json deleted file mode 100644 index 7825a4857d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip.json +++ /dev/null @@ -1 +0,0 @@ -{"floating_ip": {"instance_id": null, "ip": "10.3.1.42", "fixed_ip": null, "id": "09ea1784-2f81-46dc-8c91-244b4df75bde", "pool": "public"}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip_pools.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip_pools.json deleted file mode 100644 index 8961f51797..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip_pools.json +++ /dev/null @@ -1 +0,0 @@ -{"floating_ip_pools": [{"name": "public"}, {"name": "foobar"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ips.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ips.json deleted file mode 100644 index 82a01576a0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ips.json +++ /dev/null @@ -1 +0,0 @@ -{"floating_ips": [{"instance_id": null, "ip": "10.3.1.42", "fixed_ip": null, "id": "09ea1784-2f81-46dc-8c91-244b4df75bde", "pool": "public"}, {"instance_id": "fcfc96da-19e2-40fd-8497-f29da1b21143", "ip": "10.3.1.1", "fixed_ip": "172.16.21.4", "id": "04c5336a-0629-4694-ba30-04b0bdfa88a4", "pool": "public"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_13.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_13.json deleted file mode 100644 index 7b8297c234..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_13.json +++ /dev/null @@ -1 +0,0 @@ -{"image": {"status": "ACTIVE", "updated": "2011-08-06T18:14:02Z", "name": "Windows 2008 SP2 x86 (B24)", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/13", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/13", "rel": "bookmark"}, {"href": "http://10.13.136.245:9292/rs-reach-project/images/13", "type": "application/vnd.openstack.image", "rel": "alternate"}], "created": "2011-08-06T18:13:11Z", "minDisk": "5", "progress": 100, "minRam": "256", "id": "13", "metadata": {"os_type": "windows"}}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.json deleted file mode 100644 index 0e7207088c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.json +++ /dev/null @@ -1 +0,0 @@ -{"image": {"status": "SAVING", "updated": "2012-01-05T19:42:20Z", "name": "new_image", "links": [{"href": "http://127.0.0.1/v1.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "rel": "self"}, {"href": "http://127.0.0.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "rel": "bookmark"}, {"href": "http://10.13.136.213:9292/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "type": "application/vnd.openstack.image", "rel": "alternate"}], "created": "2012-01-05T19:42:20Z", "minDisk": 0, "server": {"id": "a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "links": [{"href": "http://127.0.0.1/v1.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "rel": "self"}, {"href": "http://127.0.0.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "rel": "bookmark"}]}, "progress": 25, "minRam": 0, "id": "4949f9ee-2421-4c81-8b49-13119446008b", "metadata": {"instance_uuid": "a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "image_state": "creating", "user_id": "reach6", "instance_ref": "http://127.0.0.1/v1.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "image_type": "snapshot", "backup_type": null}}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_detail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_detail.json deleted file mode 100644 index 1c54bd6587..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_images_detail.json +++ /dev/null @@ -1,366 +0,0 @@ -{ - "images": [ - { - "status": "ACTIVE", - "updated": "2011-08-06T18:14:02Z", - "name": "Windows 2008 SP2 x86 (B24)", - "server" : { - "id": "52415800-8b69-11e0-9b19-734f335aa7b3", - "name": "test-server", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3" - }, - { - "rel": "bookmark", - "href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3" - } - ] - }, - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/13", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/13", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/13", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-06T18:13:11Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "13", - "metadata": { - "os_type": "windows" - } - }, - { - "status": "ACTIVE", - "updated": "2011-08-06T18:13:11Z", - "name": "Windows 2003 R2 x86 (B24)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/12", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/12", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/12", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-06T18:12:33Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "12", - "metadata": { - "os_type": "windows" - } - }, - { - "status": "ACTIVE", - "updated": "2011-08-06T16:27:56Z", - "name": "Windows 2008 SP2 x64 (B24)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/11", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/11", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/11", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-06T16:26:15Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "11", - "metadata": { - "os_type": "windows" - } - }, - { - "status": "ACTIVE", - "updated": "2011-08-06T16:26:14Z", - "name": "Windows 2008 R2 x64 (B24)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/10", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/10", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/10", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-06T16:24:51Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "10", - "metadata": { - "os_type": "windows" - } - }, - { - "status": "ACTIVE", - "updated": "2011-08-06T16:24:51Z", - "name": "Windows 2003 R2 x64 (B24)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/9", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/9", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/9", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-06T16:23:52Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "9", - "metadata": { - "os_type": "windows" - } - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:58:29Z", - "name": "Ubuntu Natty (11.04)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/8", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/8", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/8", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:58:20Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "8", - "metadata": {} - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:58:19Z", - "name": "Ubuntu Lucid (10.04)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/7", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/7", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:58:14Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "7", - "metadata": {} - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:58:14Z", - "name": "Fedora 15", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/6", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/6", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/6", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:58:01Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "6", - "metadata": {} - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:58:00Z", - "name": "Fedora 14", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/5", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/5", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/5", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:57:47Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "5", - "metadata": {} - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:57:47Z", - "name": "Debian Squeeze (6.0)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/4", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/4", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/4", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:57:41Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "4", - "metadata": {} - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:57:40Z", - "name": "Debian Lenny (5.0)", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/3", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/3", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/3", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:57:30Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "3", - "metadata": {} - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:57:30Z", - "name": "CentOS 6.0", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/2", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/2", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/2", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:57:20Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "2", - "metadata": {} - }, - { - "status": "ACTIVE", - "updated": "2011-08-05T22:56:20Z", - "name": "CentOS 5.6", - "links": [ - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/1", - "rel": "self" - }, - { - "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/1", - "rel": "bookmark" - }, - { - "href": "http://10.13.136.170:9292/rs-reach-project/images/1", - "type": "application/vnd.openstack.image", - "rel": "alternate" - } - ], - "created": "2011-08-05T22:56:03Z", - "minDisk": 0, - "progress": 100, - "minRam": 0, - "id": "1", - "metadata": {} - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs.json deleted file mode 100644 index dff716492a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "keypairs": [ - { - "keypair": { - "fingerprint": "22:0e:d6:f7:bd:5e:ee:49:cf:1f:10:d5:9c:a8:35:64", - "name": "key1", - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/ePvJuMEOc90gidxWN+8lYekv+S6j8SJhcQRBjE5DVs/M+3VXyJTQc6fguUS9c7o8GZXpP/0dwbVa9y76HeZs6In+XE1egoUyz4zLHQ5jUepFeekChpSlo6yQWI2SHUxJOshqPLOEU1XlrwvN0h5FcXGVV0x6DJgLZuCRS7oIxQ== Generated by Nova\n" - } - }, - { - "keypair": { - "fingerprint": "5d:66:33:ae:99:0f:fb:cb:86:f2:bc:ae:53:99:b6:ed", - "name": "key2", - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCz5sy4u8KwAPAMPr+4bEMlU6BwpSD6eZVokwMclojqIz9nKAvQD9AEw/6ok9Xsn0oixBrCoW2HYsXIiUziufzheoGsZIzuj3D7Rpbtrft53FtICe5UtQrOo3WJb8bvbzpDDd7xYlb9PpQTXoxInzjgBW+Ox6OODx2NazTk7PHZDQ== Generated by Nova\n" - } - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create.json deleted file mode 100644 index fbfdbb9b23..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "keypair": { - "fingerprint": "80:f8:03:a7:8e:c1:c3:b1:7e:c5:8c:50:04:5e:1c:5b", - "name": "key0", - "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQDPC4MDHBbUjeGZ4pK5svGxkFHJFdDatpMAYcW/fyDxsMbyiHnu\nUOxB0WJupUQd4tc7B8+MNOLzcZVQkUjIhhkb5qCbjcoOqzb59owtNCSi7TleaC6w\n15j1LJb3zdHVxEhGJ19I95DhOtiFRHp2Ik3bYV6p+uv0sQxfaqw3q5M3+QIDAQAB\nAoGAW2LqZfH9Bb7GSEUgnESmt8hKwSYW9KLHidCeFyNG6Ect2RlyMEWZsod4Gfxq\nb4KTm6Ob8XfagLeuv0wRQyklZUbyb4aurfn4hX0cpkxSPAVar8uG/0TJY1wswxfo\nkReZCq7CQFlt7w3Y1RHZyXo/inyAxohi393trVhIGAqdXp0CQQDt7/GeI5QWKjYj\nwe5kFTRowVJ+y61MP237Bz+YF5+pq28ikdLAMzdDOyd3LJTnBGJ/DK1ksfJDCSue\nEgdifYJrAkEA3sM1fRQB/PyyyCR1DcZGlOfc/OBCSG4aTMYOK+g0PnibKPj5wS6q\nuK8w1q+0CztpgKsmEtQ+H7H8Fva81S7wKwJANY7tNEuN6e9WgHYG00Byq6HYj/II\n8EDW4Mqg5ftrVSXhvkZUyi69IcUO/SRr4BR8l1yjKydjAPPvfYVRZDocQQJASHXr\nQkJt2yM/7IafZNmoP+ukIMW6CeF2wJ50IagoxmFo500FwOczNVwXYN5KjJTI3sfN\nXLaZdqnovHeKOTZJfQJAZ2HBnmgsLoFE6ONF492TXIs7JxJr8z4QUp1AXGUXcZmy\njuL3b9XW6K908Ev8uTSNzRo6TyGuYKGllp10K6A3bA==\n-----END RSA PRIVATE KEY-----\n", - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDPC4MDHBbUjeGZ4pK5svGxkFHJFdDatpMAYcW/fyDxsMbyiHnuUOxB0WJupUQd4tc7B8+MNOLzcZVQkUjIhhkb5qCbjcoOqzb59owtNCSi7TleaC6w15j1LJb3zdHVxEhGJ19I95DhOtiFRHp2Ik3bYV6p+uv0sQxfaqw3q5M3+Q== Generated by Nova\n", - "user_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create_import.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create_import.json deleted file mode 100644 index 56f0958bb2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create_import.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "keypair": { - "fingerprint": "97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a", - "name": "key3", - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzTJr5BNSlTIDFsVY3zUJtbbcPsWbw7XDE/eXRQ+704790ARKKvE3FsERqdMZvwcx1osR0sGVdpgAiV/z5iEb5z2juQp7yQJHePiEnfHTH99NVJN+Y1BztchRoz224IaP987bN+fd8Pl/O1YDCyw+bX5zI/ekCC9z8fTdI2l1AbTnKVn7UjZBjKZi1uPMaH016fp039pIOtkjvIgDWjeGwOiJjY1vzaX3nxQje4kprEZ4FKk4yyG61qveBZr+/0Xq6ocNOYUSpB29AZ0IcfJa7P3yMxVRzSS9aN0fmrlf3kIFkVAy45A83GfZpiMxo/ulTaO9+tTSwulZP+0bxkCkn dummycomment\n", - "user_id": "dbdf4c6cab0c4ae78bef0bcdb03c2440" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_get_one.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_get_one.json deleted file mode 100644 index 6b0135d21c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_get_one.json +++ /dev/null @@ -1 +0,0 @@ -{"keypair": {"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDkRJ+f6VibLJJRPtuVM3g5ZCporVfoFJhRt8vcBbD4x/1h8OSBvWwuj9tKoZha0ijpGJIRW5HylRKYZPFL7gxlmqS9LM/lewx3c/fZItmP4kDYuXX2Dn9XwHFLS/bSy/JHVgnrHopHUH/2a57iUNe+QRrngEGz13N1S9If3EGDxIhZuO8S1BRLWK3SqtHjOQ6mWZOF6xAs3nwKaBNJTWVp6XUshzlcwWUA5nFysN9MVXX7t/J1qo+xcSAwt/ew8v6dZJcCQM+y30bQhPJzSN8LepN5tSTI4iEN0Y+LtNQDtCEYacr4qEFkAxj3CcSAeQVMaT/a7ps0xiHg9GnCbGsV Generated by Nova\n", "user_id": "1234", "name": "test-key-pair", "deleted": false, "created_at": "2013-12-07T15:17:16.000000", "updated_at": null, "fingerprint": "a9:55:e8:b8:49:45:7b:aa:a9:33:fb:97:86:79:2c:1b", "deleted_at": null, "id": 4567}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_not_found.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_not_found.json deleted file mode 100644 index fa3927a2f4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_not_found.json +++ /dev/null @@ -1 +0,0 @@ -{"itemNotFound": {"message": "The resource could not be found.", "code": 404}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks.json deleted file mode 100644 index 26fb34cdd4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks.json +++ /dev/null @@ -1 +0,0 @@ -{"networks": [{"cidr": "127.0.0.0/24", "id": "f13e5051-feea-416b-827a-1a0acc2dad14", "label": "test1"}, {"id": "00000000-0000-0000-0000-000000000000", "label": "public"}, {"id": "11111111-1111-1111-1111-111111111111", "label": "private"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks_POST.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks_POST.json deleted file mode 100644 index 7b916daf02..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks_POST.json +++ /dev/null @@ -1 +0,0 @@ -{"network": {"cidr": "127.0.0.0/24", "id": "ef2143d4-2353-4e3c-b577-0de372411f42", "label": "test1"}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_quota_sets_aTenantId.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_quota_sets_aTenantId.json deleted file mode 100644 index 568350059d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_quota_sets_aTenantId.json +++ /dev/null @@ -1 +0,0 @@ -{"quota_set": {"metadata_items": 10, "injected_file_content_bytes": 1000, "injected_files": 10, "volumes": 0, "instances": 25, "gigabytes": 500, "cores": 50, "ram": 102400, "id": "aTenantId", "floating_ips": 10}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_group_rules_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_group_rules_create.json deleted file mode 100644 index f983442126..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_group_rules_create.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "security_group_rule": { - "from_port": 14, - "group": {}, - "id": 2, - "ip_protocol": "tcp", - "ip_range": { - "cidr": "0.0.0.0/0" - }, - "parent_group_id": 6, - "to_port": 16 - } -} - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups.json deleted file mode 100644 index dc5d6ad4df..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "security_groups": [ - { - "description": "default", - "id": 2, - "name": "default", - "rules": [], - "tenant_id": "68" - }, - { - "description": "FTP Client-Server - Open 20-21 ports", - "id": 4, - "name": "ftp", - "rules": [ - { - "from_port": 20, - "group": {}, - "id": 1, - "ip_protocol": "tcp", - "ip_range": { - "cidr": "0.0.0.0/0" - }, - "parent_group_id": 4, - "to_port": 21 - } - ], - "tenant_id": "68" - } - ] -} - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups_create.json deleted file mode 100644 index af627b73e0..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups_create.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "security_group": { - "description": "Test Security Group", - "id": 6, - "name": "test", - "rules": [], - "tenant_id": "68" - } -} - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json deleted file mode 100644 index 032b553f4a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "snapshots": [ - { - "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", - "display_name": "snap-001", - "display_description": "Daily backup", - "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", - "status": "available", - "size": 30, - "created_at": "2012-02-29T03:50:07Z" - }, - { - "id": "e479997c-650b-40a4-9dfe-77655818b0d2", - "display_name": "snap-002", - "display_description": "Weekly backup", - "volume_id": "76b8950a-8594-4e5b-8dce-0dfa9c696358", - "status": "available", - "size": 25, - "created_at": "2012-03-19T01:52:47Z" - } - ] -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json deleted file mode 100644 index e1059b5119..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "snapshot": { - "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", - "display_name": "snap-001", - "display_description": "Daily backup", - "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", - "status": "available", - "size": 30, - "created_at": "2012-02-29T03:50:07Z" - } -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create_rackspace.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create_rackspace.json deleted file mode 100644 index 8f90319301..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create_rackspace.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "snapshot": { - "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", - "displayName": "snap-001", - "displayDescription": "Daily backup", - "volumeId": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", - "status": "available", - "size": 30, - "createdAt": "2012-02-29T03:50:07Z" - } -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_rackspace.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_rackspace.json deleted file mode 100644 index 877945b427..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_rackspace.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "snapshots": [ - { - "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", - "displayName": "snap-001", - "displayDescription": "Daily backup", - "volumeId": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", - "status": "available", - "size": 30, - "createdAt": "2012-02-29T03:50:07Z" - }, - { - "id": "e479997c-650b-40a4-9dfe-77655818b0d2", - "displayName": "snap-002", - "displayDescription": "Weekly backup", - "volumeId": "76b8950a-8594-4e5b-8dce-0dfa9c696358", - "status": "available", - "size": 25, - "createdAt": "2012-03-19T01:52:47Z" - } - ] -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json deleted file mode 100644 index d92e3e84b9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "volumes": [ - { - "attachments": [ - { - "device": "/dev/vdb", - "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", - "serverId": "12065", - "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d" - } - ], - "availabilityZone": "nova", - "createdAt": "2013-06-24T11:20:13.000000", - "displayDescription": "", - "displayName": "test_volume_2", - "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", - "metadata": {}, - "size": 2, - "snapshotId": null, - "status": "available", - "volumeType": "None" - }, - { - "attachments": [ - {} - ], - "availabilityZone": "nova", - "createdAt": "2013-06-21T12:39:02.000000", - "displayDescription": "some description", - "displayName": "test_volume", - "id": "cfcec3bc-b736-4db5-9535-4c24112691b5", - "metadata": {}, - "size": 50, - "snapshotId": null, - "status": "available", - "volumeType": "None" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d.json deleted file mode 100644 index b2c580fa98..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "volume": { - "attachments": [ - { - "device": "/dev/vdb", - "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", - "serverId": "12065", - "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d" - } - ], - "availabilityZone": "nova", - "createdAt": "2013-06-24T11:20:13.000000", - "displayDescription": "", - "displayName": "test_volume_2", - "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", - "metadata": {}, - "size": 2, - "snapshotId": null, - "status": "in-use", - "volumeType": "None" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_create.json deleted file mode 100644 index d1a0cdf383..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_create.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "volume": { - "attachments": [ - {} - ], - "availabilityZone": "nova", - "createdAt": "2013-06-28T12:22:39.616660", - "displayDescription": null, - "displayName": "test", - "id": "43b7db44-0497-40fa-b817-c906f13bbea3", - "metadata": {}, - "size": 1, - "snapshotId": null, - "status": "creating", - "volumeType": "None" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers.json deleted file mode 100644 index c50f22bae4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "server": { - "id": "52415800-8b69-11e0-9b19-734f565bc83b", - "tenantId": "1234", - "userId": "5678", - "name": "new-server-test", - "created": "2010-11-11T12:00:00Z", - "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0", - "accessIPv4" : "67.23.10.138", - "accessIPv6" : "::babe:67.23.10.138", - "progress": 0, - "status": "BUILD", - "adminPass": "GFf1j9aP", - "image" : { - "id": "52415800-8b69-11e0-9b19-734f6f006e54", - "name": "CentOS 5.2", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/1234/images/52415800-8b69-11e0-9b19-734f6f006e54" - }, - { - "rel": "bookmark", - "href": "http://servers.api.openstack.org/1234/images/52415800-8b69-11e0-9b19-734f6f006e54" - } - ] - }, - "flavor" : { - "id": "52415800-8b69-11e0-9b19-734f1195ff37", - "name": "256 MB Server", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/1234/flavors/52415800-8b69-11e0-9b19-734f1195ff37" - }, - { - "rel": "bookmark", - "href": "http://servers.api.openstack.org/1234/flavors/52415800-8b69-11e0-9b19-734f1195ff37" - } - ] - }, - "metadata": { - "My Server Name": "Apache1" - }, - "addresses": { - "public" : [ - { - "version": 4, - "addr": "67.23.10.138" - }, - { - "version": 6, - "addr": "::babe:67.23.10.138" - } - ], - "private" : [ - { - "version": 4, - "addr": "10.176.42.19" - }, - { - "version": 6, - "addr": "::babe:10.176.42.19" - } - ] - }, - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734fcece0043" - }, - { - "rel": "bookmark", - "href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734fcece0043" - } - ] - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12063_metadata_two_keys.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12063_metadata_two_keys.json deleted file mode 100644 index 1d88ccc8ce..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12063_metadata_two_keys.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "metadata" : { - "Server Label" : "Web Head 1", - "Image Version" : "2.1" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064.json deleted file mode 100644 index 3b36d512a7..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064.json +++ /dev/null @@ -1 +0,0 @@ -{"server": {"status": "ACTIVE", "updated": "2011-10-11T00:44:20Z", "hostId": "a024053a6201e6c6c12660aab3d8fd879e332e663a5e1fdbc02a0307", "user_id": "rs-reach", "name": "lc-test", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12064", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12064", "rel": "bookmark"}], "addresses": {"public": [{"version": 4, "addr": "50.57.94.30"}, {"version": 6, "addr": "2001:4801:7808:52:16:3eff:fe77:32e3"}], "private": [{"version": 4, "addr": "10.182.64.29"}, {"version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe6e:b7e2"}]}, "tenant_id": "rs-reach-project", "image": {"id": "7", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark"}]}, "created": "2011-10-11T00:45:02Z", "uuid": "ec53630b-e4fb-442a-a748-c376f5c4345b", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 100, "flavor": {"id": "2", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}]}, "config_drive": "", "id": 12064, "metadata": {}}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064_updated_name_bob.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064_updated_name_bob.json deleted file mode 100644 index 02c57eae91..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064_updated_name_bob.json +++ /dev/null @@ -1 +0,0 @@ -{"server": {"status": "ACTIVE", "updated": "2011-10-11T01:22:04Z", "hostId": "a024053a6201e6c6c12660aab3d8fd879e332e663a5e1fdbc02a0307", "user_id": "rs-reach", "name": "Bob", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12064", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12064", "rel": "bookmark"}], "addresses": {"public": [{"version": 4, "addr": "50.57.94.30"}, {"version": 6, "addr": "2001:4801:7808:52:16:3eff:fe77:32e3"}], "private": [{"version": 4, "addr": "10.182.64.29"}, {"version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe6e:b7e2"}]}, "tenant_id": "rs-reach-project", "image": {"id": "7", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark"}]}, "created": "2011-10-11T00:45:02Z", "uuid": "ec53630b-e4fb-442a-a748-c376f5c4345b", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 100, "flavor": {"id": "2", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}]}, "config_drive": "", "id": 12064, "metadata": {}}} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12065_os_volume_attachments.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12065_os_volume_attachments.json deleted file mode 100644 index c381384ac5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12065_os_volume_attachments.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "volumeAttachment": { - "device": "/dev/vdb", - "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", - "serverId": "12065", - "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12086_console_output.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12086_console_output.json deleted file mode 100644 index 27ffe7d4c2..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12086_console_output.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "output": "FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_1c01300f-ef97-4937-8f03-ac676d6234be_os-security-groups.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_1c01300f-ef97-4937-8f03-ac676d6234be_os-security-groups.json deleted file mode 100644 index dc5d6ad4df..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_1c01300f-ef97-4937-8f03-ac676d6234be_os-security-groups.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "security_groups": [ - { - "description": "default", - "id": 2, - "name": "default", - "rules": [], - "tenant_id": "68" - }, - { - "description": "FTP Client-Server - Open 20-21 ports", - "id": 4, - "name": "ftp", - "rules": [ - { - "from_port": 20, - "group": {}, - "id": 1, - "ip_protocol": "tcp", - "ip_range": { - "cidr": "0.0.0.0/0" - }, - "parent_group_id": 4, - "to_port": 21 - } - ], - "tenant_id": "68" - } - ] -} - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe.json deleted file mode 100644 index d972cfd66c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "server": { - "status": "BUILD", - "updated": "2011-11-30T16:39:19Z", - "hostId": "", - "user_id": "reach6", - "name": "racktest", - "links": [ - { - "href": "http://127.0.0.1/v1.1/68/servers/39d04103-984b-4a52-b4ec-ffec452e284c", - "rel": "self" - }, - { - "href": "http://127.0.0.1/68/servers/39d04103-984b-4a52-b4ec-ffec452e284c", - "rel": "bookmark" - } - ], - "created": "2011-11-30T16:39:18Z", - "tenant_id": "68", - "image": { - "id": "fcf5582a-ad13-4d98-90a6-742116f1793c", - "links": [ - { - "href": "http://127.0.0.1/68/images/fcf5582a-ad13-4d98-90a6-742116f1793c", - "rel": "bookmark" - } - ] - }, - "addresses": {}, - "accessIPv4": "", - "accessIPv6": "", - "key_name": "devstack", - "progress": null, - "flavor": { - "id": "1", - "links": [ - { - "href": "http://127.0.0.1/68/flavors/1", - "rel": "bookmark" - } - ] - }, - "config_drive": "", - "id": "26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", - "metadata": { - "My Server Name" : "Apache1" - }, - "OS-DCF:diskConfig": "AUTO", - "OS-EXT-AZ:availability_zone": "testaz" - - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create.json deleted file mode 100644 index 7eaf89076a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "server": { - "id": "26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", - "links": [ - { - "href": "http://127.0.0.1/v1.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", - "rel": "self" - }, - { - "href": "http://127.0.0.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", - "rel": "bookmark" - } - ], - "adminPass": "racktestvJq7d3" - } -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create_disk_config.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create_disk_config.json deleted file mode 100644 index 4b955ce240..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create_disk_config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "server": { - "OS-DCF:diskConfig": "MANUAL", - "id": "26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", - "links": [ - { - "href": "http://127.0.0.1/v1.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", - "rel": "self" - }, - { - "href": "http://127.0.0.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", - "rel": "bookmark" - } - ], - "adminPass": "racktestvJq7d3" - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail.json deleted file mode 100644 index 35d90858a1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail.json +++ /dev/null @@ -1 +0,0 @@ -{"servers": [{"status": "BUILD", "updated": "2011-10-11T00:50:04Z", "hostId": "912566d83a13fbb357ea3f13c629363d9f7e1ba3f925b49f3d2ab725", "user_id": "rs-reach", "name": "lc-test-2", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12065", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12065", "rel": "bookmark"}], "addresses": {"public": [{"version": 4, "addr": "50.57.94.35"}, {"version": 6, "addr": "2001:4801:7808:52:16:3eff:fe47:788a"}], "private": [{"version": 4, "addr": "10.182.64.34"}, {"version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe60:187d"}], "mynetwork": [{"version": 4, "addr": "12.16.18.28"}]}, "tenant_id": "rs-reach-project", "image": {"id": "7", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark"}]}, "created": "2011-10-11T00:51:39Z", "uuid": "02786501-714e-40af-8342-9c17eccb166d", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 25, "flavor": {"id": "2", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}]}, "config_drive": "", "id": 12065, "metadata": {}, "OS-DCF:diskConfig": "AUTO"}, {"status": "ACTIVE", "updated": "2011-10-11T00:44:20Z", "hostId": "a024053a6201e6c6c12660aab3d8fd879e332e663a5e1fdbc02a0307", "user_id": "rs-reach", "name": "lc-test", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12064", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12064", "rel": "bookmark"}], "addresses": {"public": [{"version": 4, "addr": "50.57.94.30"}, {"version": 6, "addr": "2001:4801:7808:52:16:3eff:fe77:32e3"}], "private": [{"version": 4, "addr": "10.182.64.29"}, {"version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe6e:b7e2"}]}, "tenant_id": "rs-reach-project", "image": {"id": "7", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark"}]}, "created": "2011-10-11T00:45:02Z", "uuid": "ec53630b-e4fb-442a-a748-c376f5c4345b", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 100, "flavor": {"id": "2", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}]}, "config_drive": "", "id": 12064, "metadata": {}, "OS-DCF:diskConfig": "AUTO"}]} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_EMPTY.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_EMPTY.json deleted file mode 100644 index 2dfcfbb9dc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_EMPTY.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "servers": [] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_ERROR_STATE.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_ERROR_STATE.json deleted file mode 100644 index 3e41379b4d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_ERROR_STATE.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "servers": [ - { - "status": "ERROR", - "updated": "2013-12-05T21:07:07Z", - "hostId": "2a4a12656a7a57c10188e4ea37f9e09dfb99e3d628f4064f97761e09", - "addresses": { - "pool": [ - { - "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:be:f5:87", - "version": 4, - "addr": "192.168.3.4", - "OS-EXT-IPS:type": "fixed" - } - ] - }, - "links": [ - { - "href": "http://192.168.0.1:8774/v2/dd3eca3de72846948f5d6d975660d325/servers/2d05bd68-3fbb-4b47-9f38-c690a5d93e45", - "rel": "self" - }, - { - "href": "http://192.168.0.1:8774/dd3eca3de72846948f5d6d975660d325/servers/2d05bd68-3fbb-4b47-9f38-c690a5d93e45", - "rel": "bookmark" - } - ], - "key_name": "my_key", - "image": "", - "OS-EXT-STS:task_state": null, - "OS-EXT-STS:vm_state": "error", - "OS-SRV-USG:launched_at": null, - "flavor": { - "id": "4", - "links": [ - { - "href": "http://192.168.0.1:8774/dd3eca3de72846948f5d6d975660d325/flavors/4", - "rel": "bookmark" - } - ] - }, - "id": "2d05bd68-3fbb-4b47-9f38-c690a5d93e45", - "OS-SRV-USG:terminated_at": null, - "OS-EXT-AZ:availability_zone": "nova", - "user_id": "a75c583fa46148eaa020d3e88ab53802", - "name": "test_vm", - "created": "2013-12-02T18:40:36Z", - "tenant_id": "dd3eca3de72846948f5d6d975660d325", - "OS-DCF:diskConfig": "MANUAL", - "os-extended-volumes:volumes_attached": [ - { - "id": "0056485c-ada5-4e44-9905-5b09a18b0139" - } - ], - "accessIPv4": "", - "accessIPv6": "", - "fault": { - "message": "The server has either erred or is incapable of performing the requested operation. (HTTP 500) (Request-ID: req-5ec1e01c-bc04-43e7-957d-c810d4357908)", - "code": 500, - "created": "2013-12-05T21:07:07Z" - }, - "OS-EXT-STS:power_state": 0, - "config_drive": "", - "metadata": {} - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_pause.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_pause.json deleted file mode 100644 index c44ca70599..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_pause.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "pause": null -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_resume.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_resume.json deleted file mode 100644 index 008ff18c71..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_resume.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "resume": null -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_suspend.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_suspend.json deleted file mode 100644 index 7bee702052..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_suspend.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "suspend": null -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_unpause.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_unpause.json deleted file mode 100644 index fdc0c410c3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/openstack_v1.1/_servers_unpause.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "unpause": null -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml deleted file mode 100644 index 191c7ae406..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Deploy Server - SUCCESS - Server "Deploy" issued - REASON_0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xml deleted file mode 100644 index 4870ee1c1f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - NA1 - US - East - Ashburn - Virginia - US - https://opsource-na1.cloud-vpn.net/ - true - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml deleted file mode 100644 index ca27554d8e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - 53b4c05b-341e-4ac3-b688-bdd74e53ca9b - test-net1 - test-net1 description - NA1 - 10.162.1.0 - false - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xml deleted file mode 100644 index 90686b9038..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Delete Server - SUCCESS - Server "Delete" issued - REASON_0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xml deleted file mode 100644 index df55852b14..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Delete Server - ERROR - Operation in progress on Server with Id 11 - REASON_392 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xml deleted file mode 100644 index 03c0f3d94d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Power Off Server - SUCCESS - Server "Power Off" issued - REASON_0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xml deleted file mode 100644 index 7b9a9d7e0f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Power Off Server - ERROR - Operation in progress on Server with Id 11 - REASON_392 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xml deleted file mode 100644 index 0638febd1e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Restart Server - SUCCESS - Server "Restart" issued - REASON_0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xml deleted file mode 100644 index ab9e31f66b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Restart Server - ERROR - Operation in progress on Server with Id 11 - REASON_392 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xml deleted file mode 100644 index b0937c88b4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Graceful Shutdown Server - SUCCESS - Server "Graceful Shutdown" issued - REASON_0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xml deleted file mode 100644 index eb3cbb52a4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Graceful Shutdown Server - ERROR - Operation in progress on Server with Id 11 - REASON_392 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xml deleted file mode 100644 index 274e05f77d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Start Server - SUCCESS - Server "Start" issued - REASON_0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xml deleted file mode 100644 index 6d1714f261..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Start Server - ERROR - Operation in progress on Server with Id 11 - REASON_392 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xml deleted file mode 100644 index a11d6c2312..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - abadbc7e-9e10-46ca-9d4a-194bcc6b6c16 - testnode01 - this is testnode01 description - - 2 - 2048 - 10 - 20 - - UNIX - REDHAT5/64 - - - 44ed8b72-ebea-11df-bdc1-001517c46384 - 53b4c05b-341e-4ac3-b688-bdd78e43ca9e - 10.162.1.1 - 200.16.132.7 - 10-162-1-1 - true - 2011-03-02T17:16:09.882Z - - - dbadbc8e-9e10-56ca-5d4a-155bcc5b5c15 - testnode02 - this is testnode02 description - - 4 - 4096 - 10 - 20 - - UNIX - REDHAT5/64 - - - 44ed8b72-ebea-11df-bdc1-001517c46384 - 53b4c05b-341e-4ac3-b688-bdd78e43ca9e - 10.162.1.2 - 10-162-1-2 - true - 2011-03-02T17:16:10.882Z - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xml deleted file mode 100644 index f24073f5b3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - e75ead52-692f-4314-8725-c8a4f4d13a87 - test2 - test2 node - - 1 - 2048 - 10 - 0 - - UNIX - REDHAT5/64 - - - 52ed8b72-ebea-11df-bdc1-001517c46384 - 52f4c05b-341e-4ac3-b688-bdd78e43ca9e - 10.162.151.11 - - DEPLOY_SERVER - 2011-03-20T22:32:23.000Z - copia - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_base_image.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_base_image.xml deleted file mode 100644 index 3be14f069f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_base_image.xml +++ /dev/null @@ -1,339 +0,0 @@ - - - - 52ed8b72-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed8b72-ebea-11df-bdc1-001517c46384 - RedHat 5.5 64-bit 1 CPU - RedHat 5.5 Enterprise (Tikanga), 64-bit - - UNIX - REDHAT5/64 - - NA1 - 1 - 2048 - 10 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed8dca-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed8dca-ebea-11df-bdc1-001517c46384 - RedHat 5.5 64-bit 2 CPU - RedHat 5.5 Enterprise (Tikanga), 64-bit - - UNIX - REDHAT5/64 - - NA1 - 2 - 4096 - 10 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed8ed8-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed8ed8-ebea-11df-bdc1-001517c46384 - RedHat 5.5 64-bit 4 CPU - RedHat 5.5 Enterprise (Tikanga), 64-bit - - UNIX - REDHAT5/64 - - NA1 - 4 - 6144 - 10 - 0 - 1970-01-01T00:00:02.010Z - - - 6fc040ae-3605-11e0-bfb5-001517c46384 - /oec/base/image/6fc040ae-3605-11e0-bfb5-001517c46384 - RedHat 5.5 32-bit 1 CPU - RedHat 5.5 Enterprise (Tikanga), 32-bit - - UNIX - REDHAT5/32 - - NA1 - 1 - 2048 - 10 - 0 - 2011-02-11T17:36:19.000Z - - - 52ed92d4-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed92d4-ebea-11df-bdc1-001517c46384 - Ubuntu 8.04.4 2 CPU - Ubuntu 8.04.4 LTS, 64-bit - - UNIX - UBUNTU8/64 - - NA1 - 2 - 4096 - 10 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed876c-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed876c-ebea-11df-bdc1-001517c46384 - Win2008 Ent 64-bit R2 2 CPU - Windows 2008 Enterprise R2 64-bit - - WINDOWS - WIN2008R2E/64 - - NA1 - 2 - 4096 - 50 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed8a5a-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed8a5a-ebea-11df-bdc1-001517c46384 - Win2008 Ent 64-bit R2 4 CPU - Windows 2008 Enterprise R2 64-bit - - WINDOWS - WIN2008R2E/64 - - NA1 - 4 - 8192 - 50 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed865e-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed865e-ebea-11df-bdc1-001517c46384 - Win2008 Std 64-bit R2 2 CPU - Windows 2008 Standard R2 64-bit - - WINDOWS - WIN2008R2S/64 - - NA1 - 2 - 4096 - 50 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed7b96-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed7b96-ebea-11df-bdc1-001517c46384 - Win2008 Std 32-bit 1 CPU - Windows 2008 Standard SP2 32-bit - - WINDOWS - WIN2008S/32 - - NA1 - 1 - 2048 - 50 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed7cb8-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed7cb8-ebea-11df-bdc1-001517c46384 - Win2008 Std 32-bit 2 CPU - Windows 2008 Standard SP2 32-bit - - WINDOWS - WIN2008S/32 - - NA1 - 2 - 4096 - 50 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed7da8-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed7da8-ebea-11df-bdc1-001517c46384 - Win2008 Std 32-bit 4 CPU - Windows 2008 Standard SP2 32-bit - - WINDOWS - WIN2008S/32 - - NA1 - 4 - 4096 - 50 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed7ea2-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed7ea2-ebea-11df-bdc1-001517c46384 - Win2008 Ent 32-bit 2 CPU - Windows 2008 Enterprise SP2 32-bit - - WINDOWS - WIN2008E/32 - - NA1 - 2 - 4096 - 50 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed8fd2-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed8fd2-ebea-11df-bdc1-001517c46384 - Red Hat 4.8 32-bit 1 CPU - Red Hat ES 4.8 (Nahant), 32-bit - - UNIX - REDHAT4/32 - - NA1 - 1 - 2048 - 10 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed90cc-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed90cc-ebea-11df-bdc1-001517c46384 - CentOS 5.5 32-bit 1 CPU - CentOS release 5.5, 32-bit - - UNIX - CENTOS5/32 - - NA1 - 1 - 2048 - 10 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed91da-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed91da-ebea-11df-bdc1-001517c46384 - CentOS 5.5 64-bit 1 CPU - CentOS release 5.5, 64-bit - - UNIX - CENTOS5/64 - - NA1 - 1 - 2048 - 10 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed766e-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed766e-ebea-11df-bdc1-001517c46384 - Win2003 Ent 32-bit 1 CPU - Windows 2003 Enterprise SP2 32-bit - - WINDOWS - WIN2003E/32 - - NA1 - 1 - 2048 - 16 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed7876-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed7876-ebea-11df-bdc1-001517c46384 - Win2003 Ent 32-bit 2 CPU - Windows 2003 Enterprise SP2 32-bit - - WINDOWS - WIN2003E/32 - - NA1 - 2 - 4096 - 16 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed7984-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed7984-ebea-11df-bdc1-001517c46384 - Win2003 Ent 32-bit 4 CPU - Windows 2003 Enterprise SP2 32-bit - - WINDOWS - WIN2003E/32 - - NA1 - 4 - 4096 - 16 - 0 - 1970-01-01T00:00:02.010Z - - - 52ed7a88-ebea-11df-bdc1-001517c46384 - /oec/base/image/52ed7a88-ebea-11df-bdc1-001517c46384 - Win2003 Std 64-bit 2 CPU - Windows 2003 Standard x64 SP2, 64-bit - - WINDOWS - WIN2003S/64 - - NA1 - 2 - 4096 - 16 - 0 - 1970-01-01T00:00:02.010Z - - - 0c231ef0-2a42-11e0-bfb5-001517c46384 - /oec/base/image/0c231ef0-2a42-11e0-bfb5-001517c46384 - RedHat 64-bit 2 CPU with MySQL - RedHat 5.5 Enterprise with MySQL 5.5 installed - - UNIX - REDHAT5/64 - - NA1 - 2 - 8192 - 10 - 0 - 2011-01-27T18:19:58.000Z - - - 2fb5261a-2a42-11e0-bfb5-001517c46384 - /oec/base/image/2fb5261a-2a42-11e0-bfb5-001517c46384 - RedHat 64-bit 2 CPU with PostgreSQL - RedHat 5.5 Enterprise with PostgreSQL 9.0 installed - - UNIX - REDHAT5/64 - - NA1 - 2 - 8192 - 10 - 0 - 2011-01-27T18:20:57.000Z - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_myaccount.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_myaccount.xml deleted file mode 100644 index 4f3b132879..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/opsource/oec_0_9_myaccount.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - testuser - Test User - Test - User - test@example.com - 8a8f6abc-2745-4d8a-9cbc-8dabe5a7d0e4 - - - create image - - - reports - - - server - - - primary administrator - - - network - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_distributions.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_distributions.json deleted file mode 100644 index 5e29122094..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_distributions.json +++ /dev/null @@ -1,22 +0,0 @@ -{ "get_distros_response" : - { "status_message" : null - , "status_code" : 200 - , "error_info" : null - , "response_type" : "OK" - , "human_readable_message" : "Here are the distros we are offering on new orders." - , "response_display_duration_type" : "REGULAR" - , "distro_infos" : - [{ "distro_code" : "lenny" - , "distro_description" : "Debian 5.0 (aka Lenny, RimuHosting recommended distro)"} - , { "distro_code" : "centos5" - , "distro_description" : "Centos5"} - , { "distro_code" : "ubuntu904" - , "distro_description" : "Ubuntu 9.04 (Jaunty Jackalope, from 2009-04)"} - , { "distro_code" : "ubuntu804" - , "distro_description" : "Ubuntu 8.04 (Hardy Heron, 5 yr long term support (LTS))"} - , { "distro_code" : "ubuntu810" - , "distro_description" : "Ubuntu 8.10 (Intrepid Ibex, from 2008-10)"} - , { "distro_code" : "fedora10" - , "distro_description" : "Fedora 10"}] - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders.json deleted file mode 100644 index 0706efce29..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders.json +++ /dev/null @@ -1,27 +0,0 @@ -{ "get_orders_response" : - { "status_message" : null - , "status_code" : 200 - , "error_info" : null - , "response_type" : "OK" - , "human_readable_message" : "Found 15 orders" - , "response_display_duration_type" : "REGULAR", - "about_orders" : - [{ "order_oid" : 88833465 - , "domain_name" : "api.ivan.net.nz" - , "slug" : "order-88833465-api-ivan-net-nz" - , "billing_oid" : 96122465 - , "is_on_customers_own_physical_server" : false - , "vps_parameters" : { "memory_mb" : 160 - , "disk_space_mb" : 4096 - , "disk_space_2_mb" : 0} - , "host_server_oid" : "764" - , "server_type" : "VPS" - , "data_transfer_allowance" : { "data_transfer_gb" : 30 - , "data_transfer" : "30"} - , "billing_info" : { "monthly_recurring_fee": 19.99 } - , "allocated_ips" : { "primary_ip" : "1.2.3.4" - , "secondary_ips" : ["1.2.3.5","1.2.3.6"]} - , "running_state" : "RUNNING" - }] - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_new_vps.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_new_vps.json deleted file mode 100644 index 3f0ce39b8e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_new_vps.json +++ /dev/null @@ -1,62 +0,0 @@ -{ "post_new_vps_response" : - { "status_message" : null - , "status_code" : 200 - , "error_info" : null - , "response_type" : "OK" - , "human_readable_message" : null - , "response_display_duration_type" : "REGULAR" - , "setup_messages" : - ["Using user-specified billing data: Wire Transfer" , "Selected user as the owner of the billing details: Ivan Meredith" - , "No VPS paramters provided, using default values."] - , "about_order" : - { "order_oid" : 52255865 - , "domain_name" : "api.ivan.net.nz" - , "slug" : "order-52255865-api-ivan-net-nz" - , "billing_oid" : 96122465 - , "is_on_customers_own_physical_server" : false - , "vps_parameters" : - { "memory_mb" : 160 - , "disk_space_mb" : 4096 - , "disk_space_2_mb" : 0} - , "host_server_oid" : "764" - , "server_type" : "VPS" - , "data_transfer_allowance" : - { "data_transfer_gb" : 30 , "data_transfer" : "30"} - , "billing_info" : { "monthly_recurring_fee" : 19.99 } - , "allocated_ips" : - { "primary_ip" : "74.50.57.80", "secondary_ips" : []} - , "running_state" : "RUNNING"} - , "new_order_request" : - { "billing_oid" : 96122465 - , "user_oid" : 0 - , "host_server_oid" : null - , "vps_order_oid_to_clone" : 0 - , "ip_request" : - { "num_ips" : 1, "extra_ip_reason" : ""} - , "vps_parameters" : - { "memory_mb" : 160 - , "disk_space_mb" : 4096 - , "disk_space_2_mb" : 0} - , "pricing_plan_code" : "MIRO1B" - , "instantiation_options" : - { "control_panel" : "webmin" - , "domain_name" : "api.ivan.net.nz" - , "password" : "aruxauce27" - , "distro" : "lenny"}} - , "running_vps_info" : - { "pings_ok" : true - , "current_kernel" : "default" - , "current_kernel_canonical" : "2.6.30.5-xenU.i386" - , "last_backup_message" : "" - , "is_console_login_enabled" : false - , "console_public_authorized_keys" : null - , "is_backup_running" : false - , "is_backups_enabled" : true - , "next_backup_time" : - { "ms_since_epoch": 1256446800000, "iso_format" : "2009-10-25T05:00:00Z", "users_tz_offset_ms" : 46800000} - , "vps_uptime_s" : 31 - , "vps_cpu_time_s" : 6 - , "running_state" : "RUNNING" - , "is_suspended" : false} - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps.json deleted file mode 100644 index ca2f635cff..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps.json +++ /dev/null @@ -1,13 +0,0 @@ -{ "delete_server_response" : - { "status_message" : null - , "status_code" : 200 - , "error_info" : null - , "response_type" : "OK" - , "human_readable_message" : "Server removed" - , "response_display_duration_type" : "REGULAR" - , "cancel_messages" : - ["api.ivan.net.nz is being shut down." - , "A $7.98 credit has been added to your account." - , "If you need to un-cancel the server please contact our support team."] - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps_running_state.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps_running_state.json deleted file mode 100644 index 9deaf6ca03..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps_running_state.json +++ /dev/null @@ -1,40 +0,0 @@ -{ "put_running_state_response" : - { "status_message" : null - , "status_code" : 200 - , "error_info" : null - , "response_type" : "OK" - , "human_readable_message" : "api.ivan.net.nz restarted. After the reboot api.ivan.net.nz is pinging OK." - , "response_display_duration_type" : "REGULAR" - , "is_restarted" : true - , "is_pinging" : true - , "running_vps_info" : - { "pings_ok" : true - , "current_kernel" : "default" - , "current_kernel_canonical" : "2.6.30.5-xenU.i386" - , "last_backup_message" : "" - , "is_console_login_enabled" : false - , "console_public_authorized_keys" : null - , "is_backup_running" : false - , "is_backups_enabled" : true - , "next_backup_time" : - { "ms_since_epoch": 1256446800000, "iso_format" : "2009-10-25T05:00:00Z", "users_tz_offset_ms" : 46800000} - , "vps_uptime_s" : 19 - , "vps_cpu_time_s" : 5 - , "running_state" : "RUNNING" - , "is_suspended" : false} - , "host_server_info" : { "is_host64_bit_capable" : true - , "default_kernel_i386" : "2.6.30.5-xenU.i386" - , "default_kernel_x86_64" : "2.6.30.5-xenU.x86_64" - , "cpu_model_name" : "Intel(R) Xeon(R) CPU E5506 @ 2.13GHz" - , "host_num_cores" : 1 - , "host_xen_version" : "3.4.1" - , "hostload" : [1.45 - , 0.56 - , 0.28] - , "host_uptime_s" : 3378276 - , "host_mem_mb_free" : 51825 - , "host_mem_mb_total" : 73719 - , "running_vpss" : 34} - , "running_state_messages" : null - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_pricing_plans.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_pricing_plans.json deleted file mode 100644 index c0e2962eb9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/rimuhosting/r_pricing_plans.json +++ /dev/null @@ -1,26 +0,0 @@ -{"get_pricing_plans_response" : - { "status_message" : null - , "status_code" : 200 - , "error_info" : null - , "response_type" : "OK" - , "human_readable_message" : "Here some pricing plans we are offering on new orders.  Note we offer most disk and memory sizes.  So if you setup a new server feel free to vary these (e.g. different memory, disk, etc) and we will just adjust the pricing to suit.  Pricing is in USD.  If you are an NZ-based customer then we would need to add GST." - , "response_display_duration_type" : "REGULAR" - , "pricing_plan_infos" : - [{ "pricing_plan_code" : "MiroVPSLowContention" - , "pricing_plan_description" : "MiroVPS Semi-Dedicated Server (Dallas)" - , "monthly_recurring_fee" : 32.54 - , "monthly_recurring_amt" : { - "amt" : 35.0 - , "currency" : "CUR_AUD" - , "amt_usd" : 32.54} - , "minimum_memory_mb" : 950 - , "minimum_disk_gb" : 20 - , "minimum_data_transfer_allowance_gb" : 75 - , "see_also_url" : "http://rimuhosting.com/order/serverdetails.jsp?plan=MiroVPSLowContention" - , "server_type" : "VPS" - , "offered_at_data_center" : - { "data_center_location_code" : "DCDALLAS" - , "data_center_location_name" : "Dallas" } - }] - } -} diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml deleted file mode 100644 index 0f38ef053f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - faultCode - SoftLayer_Account - - - faultString - Failed Call - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/empty.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/empty.xml deleted file mode 100644 index 1acdcc956a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/empty.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/fail.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/fail.xml deleted file mode 100644 index 4cd0162f66..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/fail.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - faultCode - fail - - - faultString - Failed Call - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml deleted file mode 100644 index b37dc47450..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml +++ /dev/null @@ -1,1538 +0,0 @@ - - - - - - - - - - accountId - - 282402 - - - - createDate - - 2013-11-06T14:38:36+01:00 - - - - dedicatedAccountHostOnlyFlag - - 0 - - - - domain - - example.com - - - - fullyQualifiedDomainName - - libcloud-testing1.example.com - - - - hostname - - libcloud-testing1 - - - - id - - 2875152 - - - - lastPowerStateId - - - - - - lastVerifiedDate - - - - - - maxCpu - - 1 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 2048 - - - - metricPollDate - - - - - - modifyDate - - 2013-11-06T14:41:25+01:00 - - - - startCpus - - 1 - - - - statusId - - 1001 - - - - uuid - - ab98fc82-9d74-bc34-6701-f88957ebbba8 - - - - billingItem - - - - allowCancellationFlag - - 1 - - - - cancellationDate - - - - - - categoryCode - - guest_core - - - - createDate - - 2013-11-06T14:38:38+01:00 - - - - currentHourlyCharge - - .112 - - - - cycleStartDate - - 2013-11-06T14:43:20+01:00 - - - - description - - 1 x 2.0 GHz Core - - - - domainName - - example.com - - - - hostName - - libcloud-testing1 - - - - hourlyRecurringFee - - .056 - - - - hoursUsed - - 2 - - - - id - - 16447700 - - - - laborFee - - 0 - - - - laborFeeTaxRate - - .21 - - - - lastBillDate - - 2013-11-06T14:43:20+01:00 - - - - modifyDate - - 2013-11-06T14:43:20+01:00 - - - - nextBillDate - - 2013-11-28T07:00:00+01:00 - - - - oneTimeFee - - 0 - - - - oneTimeFeeTaxRate - - .21 - - - - orderItemId - - 22662589 - - - - parentId - - - - - - recurringFee - - .112 - - - - recurringFeeTaxRate - - .21 - - - - recurringMonths - - 1 - - - - serviceProviderId - - 1 - - - - setupFee - - 0 - - - - setupFeeTaxRate - - .21 - - - - resourceTableId - - 2875152 - - - - - - - datacenter - - - - id - - 168642 - - - - longName - - San Jose 1 - - - - name - - sjc01 - - - - - - - globalIdentifier - - 9ee84f87-e558-4548-9b89-fe7d997706b8 - - - - operatingSystem - - - - hardwareId - - - - - - id - - 2200995 - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - createDate - - 2013-11-06T14:38:56+01:00 - - - - id - - 1856975 - - - - modifyDate - - 2013-11-06T14:38:56+01:00 - - - - password - - L3TJVubf - - - - port - - - - - - softwareId - - 2200995 - - - - username - - root - - - - - - - - - - softwareLicense - - - - id - - 1523 - - - - softwareDescriptionId - - 1163 - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 1163 - - - - longDescription - - Debian / Debian / 7.0.0-64 Minimal for CCI - - - - manufacturer - - Debian - - - - name - - Debian - - - - operatingSystem - - 1 - - - - referenceCode - - DEBIAN_7_64 - - - - upgradeSoftwareDescriptionId - - - - - - upgradeSwDescId - - - - - - version - - 7.0.0-64 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - powerState - - - - keyName - - RUNNING - - - - name - - Running - - - - - - - primaryBackendIpAddress - - 10.55.43.130 - - - - primaryIpAddress - - 50.23.95.202 - - - - - - - - accountId - - 282402 - - - - createDate - - 2013-11-06T15:14:52+01:00 - - - - dedicatedAccountHostOnlyFlag - - 0 - - - - domain - - example.com - - - - fullyQualifiedDomainName - - libcloud-testing2.example.com - - - - hostname - - libcloud-testing2 - - - - id - - 2875213 - - - - lastPowerStateId - - - - - - lastVerifiedDate - - - - - - maxCpu - - 1 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 2048 - - - - metricPollDate - - - - - - modifyDate - - 2013-11-06T15:17:56+01:00 - - - - startCpus - - 1 - - - - statusId - - 1001 - - - - uuid - - 8f10bea1-3e26-70d7-d581-0d9e820eae0c - - - - billingItem - - - - allowCancellationFlag - - 1 - - - - cancellationDate - - - - - - categoryCode - - guest_core - - - - createDate - - 2013-11-06T15:14:55+01:00 - - - - currentHourlyCharge - - .056 - - - - cycleStartDate - - 2013-11-06T15:19:50+01:00 - - - - description - - 1 x 2.0 GHz Core - - - - domainName - - example.com - - - - hostName - - libcloud-testing2 - - - - hourlyRecurringFee - - .056 - - - - hoursUsed - - 1 - - - - id - - 16447908 - - - - laborFee - - 0 - - - - laborFeeTaxRate - - .21 - - - - lastBillDate - - 2013-11-06T15:19:50+01:00 - - - - modifyDate - - 2013-11-06T15:19:50+01:00 - - - - nextBillDate - - 2013-11-28T07:00:00+01:00 - - - - oneTimeFee - - 0 - - - - oneTimeFeeTaxRate - - .21 - - - - orderItemId - - 22663091 - - - - parentId - - - - - - recurringFee - - .056 - - - - recurringFeeTaxRate - - .21 - - - - recurringMonths - - 1 - - - - serviceProviderId - - 1 - - - - setupFee - - 0 - - - - setupFeeTaxRate - - .21 - - - - resourceTableId - - 2875213 - - - - - - - datacenter - - - - id - - 168642 - - - - longName - - San Jose 1 - - - - name - - sjc01 - - - - - - - globalIdentifier - - 5c704e34-6ee7-4efe-9722-af9d406fa930 - - - - operatingSystem - - - - hardwareId - - - - - - id - - 2201027 - - - - manufacturerLicenseInstance - - - - - - softwareLicense - - - - id - - 1523 - - - - softwareDescriptionId - - 1163 - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 1163 - - - - longDescription - - Debian / Debian / 7.0.0-64 Minimal for CCI - - - - manufacturer - - Debian - - - - name - - Debian - - - - operatingSystem - - 1 - - - - referenceCode - - DEBIAN_7_64 - - - - upgradeSoftwareDescriptionId - - - - - - upgradeSwDescId - - - - - - version - - 7.0.0-64 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - powerState - - - - keyName - - INITIATING - - - - name - - Running - - - - - - - primaryBackendIpAddress - - 10.55.43.131 - - - - primaryIpAddress - - 50.23.95.203 - - - - - - - - accountId - - 282402 - - - - createDate - - 2013-11-06T15:36:53+01:00 - - - - dedicatedAccountHostOnlyFlag - - 0 - - - - domain - - example.com - - - - fullyQualifiedDomainName - - libcloud-testing.example.com - - - - hostname - - libcloud-testing - - - - id - - 2875273 - - - - lastPowerStateId - - - - - - lastVerifiedDate - - - - - - maxCpu - - 1 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 2048 - - - - metricPollDate - - - - - - modifyDate - - 2013-11-06T15:39:35+01:00 - - - - startCpus - - 1 - - - - statusId - - 1001 - - - - uuid - - f86371c5-103b-34d3-ae27-e4dafa1c4718 - - - - billingItem - - - - allowCancellationFlag - - 1 - - - - cancellationDate - - - - - - categoryCode - - guest_core - - - - createDate - - 2013-11-06T15:36:55+01:00 - - - - currentHourlyCharge - - .056 - - - - cycleStartDate - - 2013-11-06T15:41:31+01:00 - - - - description - - 1 x 2.0 GHz Core - - - - domainName - - example.com - - - - hostName - - libcloud-testing - - - - hourlyRecurringFee - - .056 - - - - hoursUsed - - 1 - - - - id - - 16448162 - - - - laborFee - - 0 - - - - laborFeeTaxRate - - .21 - - - - lastBillDate - - 2013-11-06T15:41:31+01:00 - - - - modifyDate - - 2013-11-06T15:41:31+01:00 - - - - nextBillDate - - 2013-11-28T07:00:00+01:00 - - - - oneTimeFee - - 0 - - - - oneTimeFeeTaxRate - - .21 - - - - orderItemId - - 22663578 - - - - parentId - - - - - - recurringFee - - .056 - - - - recurringFeeTaxRate - - .21 - - - - recurringMonths - - 1 - - - - serviceProviderId - - 1 - - - - setupFee - - 0 - - - - setupFeeTaxRate - - .21 - - - - resourceTableId - - 2875273 - - - - - - - datacenter - - - - id - - 168642 - - - - longName - - San Jose 1 - - - - name - - sjc01 - - - - - - - globalIdentifier - - e8ab9d1c-edd8-4a1a-a13c-ff74838b5ab6 - - - - operatingSystem - - - - hardwareId - - - - - - id - - 2201049 - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - createDate - - 2013-11-06T15:37:10+01:00 - - - - id - - 1857066 - - - - modifyDate - - 2013-11-06T15:37:10+01:00 - - - - password - - HmyHw89J - - - - port - - - - - - softwareId - - 2201049 - - - - username - - root - - - - - - - - - - softwareLicense - - - - id - - 1523 - - - - softwareDescriptionId - - 1163 - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 1163 - - - - longDescription - - Debian / Debian / 7.0.0-64 Minimal for CCI - - - - manufacturer - - Debian - - - - name - - Debian - - - - operatingSystem - - 1 - - - - referenceCode - - DEBIAN_7_64 - - - - upgradeSoftwareDescriptionId - - - - - - upgradeSwDescId - - - - - - version - - 7.0.0-64 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - powerState - - - - keyName - - RUNNING - - - - name - - Running - - - - - - - primaryBackendIpAddress - - 10.55.43.132 - - - - primaryIpAddress - - 50.23.95.204 - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml deleted file mode 100644 index b70419488e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - id - - 2 - - - - name - - dal05 - - - - longName - - Dallas 5 - - - - - - - - id - - 3 - - - - name - - dal01 - - - - longName - - Dallas - - - - - - - - id - - 18171 - - - - name - - sea01 - - - - longName - - Seattle - - - - - - - - id - - 37473 - - - - name - - wdc01 - - - - longName - - Washington, DC - - - - - - - - id - - 12345 - - - - name - - newcity01 - - - - longName - - New City - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml deleted file mode 100644 index 09659cde75..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - accountId - - 12345 - - - - createDate - - 2013-01-01T19:31:22-06:00 - - - - dedicatedAccountHostOnlyFlag - - 0 - - - - domain - - domain.com - - - - fullyQualifiedDomainName - - hostname.domain.com - - - - hostname - - hostname - - - - id - - 123456 - - - - lastPowerStateId - - - - - - lastVerifiedDate - - - - - - maxCpu - - 2 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 2048 - - - - metricPollDate - - - - - - modifyDate - - - - - - privateNetworkOnlyFlag - - 0 - - - - startCpus - - 2 - - - - statusId - - 1001 - - - - globalIdentifier - - f47ac10b-58cc-4372-a567-0e02b2c3d479 - - - - managedResourceFlag - - 0 - - - - powerState - - - - keyName - - HALTED - - - - name - - Halted - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml deleted file mode 100644 index a6d94a6c5b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml +++ /dev/null @@ -1,12527 +0,0 @@ - - - - - - - blockDevices - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - 25 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 0 - - - - diskImage - - - - capacity - - 25 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .025 - - - - recurringFee - - 18 - - - - item - - - - description - - 100 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 0 - - - - diskImage - - - - capacity - - 100 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .012 - - - - recurringFee - - 8 - - - - item - - - - description - - 10 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 10 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .015 - - - - recurringFee - - 10 - - - - item - - - - description - - 20 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 20 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .016 - - - - recurringFee - - 11 - - - - item - - - - description - - 25 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 25 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .017 - - - - recurringFee - - 12 - - - - item - - - - description - - 30 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 30 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .019 - - - - recurringFee - - 14 - - - - item - - - - description - - 40 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 40 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .021 - - - - recurringFee - - 16 - - - - item - - - - description - - 50 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 50 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .023 - - - - recurringFee - - 17 - - - - item - - - - description - - 75 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 75 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .025 - - - - recurringFee - - 18 - - - - item - - - - description - - 100 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 100 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .028 - - - - recurringFee - - 19 - - - - item - - - - description - - 125 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 125 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .03 - - - - recurringFee - - 20 - - - - item - - - - description - - 150 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 150 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .035 - - - - recurringFee - - 21 - - - - item - - - - description - - 175 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 175 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .04 - - - - recurringFee - - 22 - - - - item - - - - description - - 200 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 200 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 25 - - - - item - - - - description - - 250 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 250 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .06 - - - - recurringFee - - 32.5 - - - - item - - - - description - - 300 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 300 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .07 - - - - recurringFee - - 40 - - - - item - - - - description - - 350 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 350 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - 400 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 400 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .1 - - - - recurringFee - - 50 - - - - item - - - - description - - 500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .15 - - - - recurringFee - - 75 - - - - item - - - - description - - 750 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 750 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .2 - - - - recurringFee - - 100 - - - - item - - - - description - - 1,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 1000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .25 - - - - recurringFee - - 150 - - - - item - - - - description - - 1,500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 1500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .3 - - - - recurringFee - - 200 - - - - item - - - - description - - 2,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 2000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .012 - - - - recurringFee - - 8 - - - - item - - - - description - - 10 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 10 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .015 - - - - recurringFee - - 10 - - - - item - - - - description - - 20 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 20 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .016 - - - - recurringFee - - 11 - - - - item - - - - description - - 25 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 25 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .017 - - - - recurringFee - - 12 - - - - item - - - - description - - 30 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 30 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .019 - - - - recurringFee - - 14 - - - - item - - - - description - - 40 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 40 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .021 - - - - recurringFee - - 16 - - - - item - - - - description - - 50 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 50 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .023 - - - - recurringFee - - 17 - - - - item - - - - description - - 75 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 75 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .025 - - - - recurringFee - - 18 - - - - item - - - - description - - 100 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 100 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .028 - - - - recurringFee - - 19 - - - - item - - - - description - - 125 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 125 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .03 - - - - recurringFee - - 20 - - - - item - - - - description - - 150 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 150 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .035 - - - - recurringFee - - 21 - - - - item - - - - description - - 175 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 175 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .04 - - - - recurringFee - - 22 - - - - item - - - - description - - 200 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 200 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 25 - - - - item - - - - description - - 250 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 250 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .06 - - - - recurringFee - - 32.5 - - - - item - - - - description - - 300 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 300 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .07 - - - - recurringFee - - 40 - - - - item - - - - description - - 350 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 350 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - 400 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 400 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .1 - - - - recurringFee - - 50 - - - - item - - - - description - - 500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .15 - - - - recurringFee - - 75 - - - - item - - - - description - - 750 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 750 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .2 - - - - recurringFee - - 100 - - - - item - - - - description - - 1,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 1000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .25 - - - - recurringFee - - 150 - - - - item - - - - description - - 1,500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 1500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .3 - - - - recurringFee - - 200 - - - - item - - - - description - - 2,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 3 - - - - diskImage - - - - capacity - - 2000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .012 - - - - recurringFee - - 8 - - - - item - - - - description - - 10 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 10 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .015 - - - - recurringFee - - 10 - - - - item - - - - description - - 20 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 20 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .016 - - - - recurringFee - - 11 - - - - item - - - - description - - 25 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 25 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .017 - - - - recurringFee - - 12 - - - - item - - - - description - - 30 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 30 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .019 - - - - recurringFee - - 14 - - - - item - - - - description - - 40 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 40 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .021 - - - - recurringFee - - 16 - - - - item - - - - description - - 50 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 50 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .023 - - - - recurringFee - - 17 - - - - item - - - - description - - 75 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 75 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .025 - - - - recurringFee - - 18 - - - - item - - - - description - - 100 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 100 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .028 - - - - recurringFee - - 19 - - - - item - - - - description - - 125 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 125 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .03 - - - - recurringFee - - 20 - - - - item - - - - description - - 150 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 150 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .035 - - - - recurringFee - - 21 - - - - item - - - - description - - 175 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 175 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .04 - - - - recurringFee - - 22 - - - - item - - - - description - - 200 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 200 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 25 - - - - item - - - - description - - 250 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 250 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .06 - - - - recurringFee - - 32.5 - - - - item - - - - description - - 300 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 300 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .07 - - - - recurringFee - - 40 - - - - item - - - - description - - 350 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 350 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - 400 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 400 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .1 - - - - recurringFee - - 50 - - - - item - - - - description - - 500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .15 - - - - recurringFee - - 75 - - - - item - - - - description - - 750 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 750 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .2 - - - - recurringFee - - 100 - - - - item - - - - description - - 1,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 1000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .25 - - - - recurringFee - - 150 - - - - item - - - - description - - 1,500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 1500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .3 - - - - recurringFee - - 200 - - - - item - - - - description - - 2,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 4 - - - - diskImage - - - - capacity - - 2000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .012 - - - - recurringFee - - 8 - - - - item - - - - description - - 10 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 10 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .015 - - - - recurringFee - - 10 - - - - item - - - - description - - 20 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 20 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .016 - - - - recurringFee - - 11 - - - - item - - - - description - - 25 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 25 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .017 - - - - recurringFee - - 12 - - - - item - - - - description - - 30 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 30 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .019 - - - - recurringFee - - 14 - - - - item - - - - description - - 40 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 40 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .021 - - - - recurringFee - - 16 - - - - item - - - - description - - 50 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 50 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .023 - - - - recurringFee - - 17 - - - - item - - - - description - - 75 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 75 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .025 - - - - recurringFee - - 18 - - - - item - - - - description - - 100 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 100 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .028 - - - - recurringFee - - 19 - - - - item - - - - description - - 125 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 125 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .03 - - - - recurringFee - - 20 - - - - item - - - - description - - 150 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 150 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .035 - - - - recurringFee - - 21 - - - - item - - - - description - - 175 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 175 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .04 - - - - recurringFee - - 22 - - - - item - - - - description - - 200 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 200 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 25 - - - - item - - - - description - - 250 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 250 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .06 - - - - recurringFee - - 32.5 - - - - item - - - - description - - 300 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 300 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .07 - - - - recurringFee - - 40 - - - - item - - - - description - - 350 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 350 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - 400 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 400 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .1 - - - - recurringFee - - 50 - - - - item - - - - description - - 500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .15 - - - - recurringFee - - 75 - - - - item - - - - description - - 750 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 750 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .2 - - - - recurringFee - - 100 - - - - item - - - - description - - 1,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 1000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .25 - - - - recurringFee - - 150 - - - - item - - - - description - - 1,500 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 1500 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .3 - - - - recurringFee - - 200 - - - - item - - - - description - - 2,000 GB (SAN) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 5 - - - - diskImage - - - - capacity - - 2000 - - - - - - - - - - - - - localDiskFlag - - 0 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - 25 GB (LOCAL) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 0 - - - - diskImage - - - - capacity - - 25 - - - - - - - - - - - - - localDiskFlag - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .01 - - - - recurringFee - - 7 - - - - item - - - - description - - 100 GB (LOCAL) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 0 - - - - diskImage - - - - capacity - - 100 - - - - - - - - - - - - - localDiskFlag - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .005 - - - - recurringFee - - 3.25 - - - - item - - - - description - - 25 GB (LOCAL) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 25 - - - - - - - - - - - - - localDiskFlag - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .01 - - - - recurringFee - - 7 - - - - item - - - - description - - 100 GB (LOCAL) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 100 - - - - - - - - - - - - - localDiskFlag - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .015 - - - - recurringFee - - 9 - - - - item - - - - description - - 150 GB (LOCAL) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 150 - - - - - - - - - - - - - localDiskFlag - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .02 - - - - recurringFee - - 14 - - - - item - - - - description - - 200 GB (LOCAL) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 200 - - - - - - - - - - - - - localDiskFlag - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .03 - - - - recurringFee - - 21 - - - - item - - - - description - - 300 GB (LOCAL) - - - - - - - - - - template - - - - blockDevices - - - - - - - device - - 2 - - - - diskImage - - - - capacity - - 300 - - - - - - - - - - - - - localDiskFlag - - 1 - - - - - - - - - - - - - datacenters - - - - - - - template - - - - datacenter - - - - name - - ams01 - - - - - - - - - - - - - - template - - - - datacenter - - - - name - - dal05 - - - - - - - - - - - - - - template - - - - datacenter - - - - name - - dal06 - - - - - - - - - - - - - - template - - - - datacenter - - - - name - - sea01 - - - - - - - - - - - - - - template - - - - datacenter - - - - name - - sjc01 - - - - - - - - - - - - - - template - - - - datacenter - - - - name - - sng01 - - - - - - - - - - - - - - template - - - - datacenter - - - - name - - wdc01 - - - - - - - - - - - - - - - - memory - - - - - - - itemPrice - - - - hourlyRecurringFee - - .03 - - - - recurringFee - - 21 - - - - item - - - - description - - 1 GB - - - - - - - - - - template - - - - maxMemory - - 1024 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .06 - - - - recurringFee - - 42 - - - - item - - - - description - - 2 GB - - - - - - - - - - template - - - - maxMemory - - 2048 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .085 - - - - recurringFee - - 59.5 - - - - item - - - - description - - 3 GB - - - - - - - - - - template - - - - maxMemory - - 3072 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .11 - - - - recurringFee - - 77 - - - - item - - - - description - - 4 GB - - - - - - - - - - template - - - - maxMemory - - 4096 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .14 - - - - recurringFee - - 98 - - - - item - - - - description - - 5 GB - - - - - - - - - - template - - - - maxMemory - - 5120 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .165 - - - - recurringFee - - 115.5 - - - - item - - - - description - - 6 GB - - - - - - - - - - template - - - - maxMemory - - 6144 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .195 - - - - recurringFee - - 136.5 - - - - item - - - - description - - 7 GB - - - - - - - - - - template - - - - maxMemory - - 7168 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .215 - - - - recurringFee - - 150.5 - - - - item - - - - description - - 8 GB - - - - - - - - - - template - - - - maxMemory - - 8192 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .245 - - - - recurringFee - - 171.5 - - - - item - - - - description - - 9 GB - - - - - - - - - - template - - - - maxMemory - - 9216 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .265 - - - - recurringFee - - 185.5 - - - - item - - - - description - - 10 GB - - - - - - - - - - template - - - - maxMemory - - 10240 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .29 - - - - recurringFee - - 203 - - - - item - - - - description - - 11 GB - - - - - - - - - - template - - - - maxMemory - - 11264 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .31 - - - - recurringFee - - 217 - - - - item - - - - description - - 12 GB - - - - - - - - - - template - - - - maxMemory - - 12288 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .33 - - - - recurringFee - - 231 - - - - item - - - - description - - 13 GB - - - - - - - - - - template - - - - maxMemory - - 13312 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .345 - - - - recurringFee - - 241.5 - - - - item - - - - description - - 14 GB - - - - - - - - - - template - - - - maxMemory - - 14336 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .36 - - - - recurringFee - - 252 - - - - item - - - - description - - 15 GB - - - - - - - - - - template - - - - maxMemory - - 15360 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .375 - - - - recurringFee - - 262.5 - - - - item - - - - description - - 16 GB - - - - - - - - - - template - - - - maxMemory - - 16384 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .76 - - - - recurringFee - - 525 - - - - item - - - - description - - 32 GB - - - - - - - - - - template - - - - maxMemory - - 32768 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 3.5 - - - - recurringFee - - 2500 - - - - item - - - - description - - 48 GB - - - - - - - - - - template - - - - maxMemory - - 49152 - - - - - - - - - - - - - networkComponents - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - 10 Mbps Public & Private Networks - - - - - - - - - - template - - - - networkComponents - - - - - - - maxSpeed - - 10 - - - - - - - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - 100 Mbps Private Network - - - - - - - - - - template - - - - networkComponents - - - - - - - maxSpeed - - 100 - - - - - - - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .04 - - - - recurringFee - - 20 - - - - item - - - - description - - 1 Gbps Public & Private Networks - - - - - - - - - - template - - - - networkComponents - - - - - - - maxSpeed - - 1000 - - - - - - - - - - - - - - - - - - - operatingSystems - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - CentOS 6.0 - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CENTOS_6_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - CentOS 6.0 - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CENTOS_6_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - CentOS 5 - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CENTOS_5_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - CentOS 5 - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CENTOS_5_32 - - - - - - - - - - - itemPrice - - - - recurringFee - - 12 - - - - item - - - - description - - CloudLinux 6 (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CLOUDLINUX_6_64 - - - - - - - - - - - itemPrice - - - - recurringFee - - 12 - - - - item - - - - description - - CloudLinux 6 (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CLOUDLINUX_6_32 - - - - - - - - - - - itemPrice - - - - recurringFee - - 12 - - - - item - - - - description - - CloudLinux 5 (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CLOUDLINUX_5_64 - - - - - - - - - - - itemPrice - - - - recurringFee - - 12 - - - - item - - - - description - - CloudLinux 5 (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - CLOUDLINUX_5_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Debian GNU/Linux 7.0 Wheezy/Stable - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - DEBIAN_7_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Debian GNU/Linux 7.0 Wheezy/Stable - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - DEBIAN_7_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Debian GNU/Linux 6.0 Squeeze/Stable - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - DEBIAN_6_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Debian GNU/Linux 6.0 Squeeze/Stable - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - DEBIAN_6_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - DEBIAN_5_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - DEBIAN_5_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - Red Hat Enterprise Linux 6 - Minimal Install (64 bit) (1 - 4 Core) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_6_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .12 - - - - recurringFee - - 100 - - - - item - - - - description - - Red Hat Enterprise Linux 6 - Minimal Install (64 bit) (5 - 100 Core) - - - - id - - -3839 - - - - softwareDescriptionId - - - - - - upgradeItemId - - - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 795 - - - - longDescription - - Redhat / EL / 6.0-64 Minimal for CCI - - - - manufacturer - - Redhat - - - - name - - EL - - - - operatingSystem - - 1 - - - - referenceCode - - REDHAT_6_64 - - - - upgradeSoftwareDescriptionId - - - - - - upgradeSwDescId - - - - - - version - - 6.0-64 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_6_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - Red Hat Enterprise Linux 6 - Minimal Install (32 bit) (1 - 4 Core) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_6_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .12 - - - - recurringFee - - 100 - - - - item - - - - description - - Red Hat Enterprise Linux 6 - Minimal Install (32 bit) (5 - 100 Core) - - - - id - - -3837 - - - - softwareDescriptionId - - - - - - upgradeItemId - - - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 796 - - - - longDescription - - Redhat / EL / 6.0-32 Minimal for CCI - - - - manufacturer - - Redhat - - - - name - - EL - - - - operatingSystem - - 1 - - - - referenceCode - - REDHAT_6_32 - - - - upgradeSoftwareDescriptionId - - - - - - upgradeSwDescId - - - - - - version - - 6.0-32 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_6_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - Red Hat Enterprise Linux 5 - Minimal Install (64 bit) (1 - 4 Core) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_5_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .12 - - - - recurringFee - - 100 - - - - item - - - - description - - Red Hat Enterprise Linux 5 - Minimal Install (64 bit) (5 - 100 Core) - - - - id - - -880 - - - - softwareDescriptionId - - - - - - upgradeItemId - - - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 664 - - - - longDescription - - Redhat / EL / 5.5-64 Minimal for CCI - - - - manufacturer - - Redhat - - - - name - - EL - - - - operatingSystem - - 1 - - - - referenceCode - - REDHAT_5_64 - - - - upgradeSoftwareDescriptionId - - - - - - upgradeSwDescId - - - - - - version - - 5.5-64 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_5_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .08 - - - - recurringFee - - 45 - - - - item - - - - description - - Red Hat Enterprise Linux 5 - Minimal Install (32 bit) (1 - 4 Core) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_5_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .12 - - - - recurringFee - - 100 - - - - item - - - - description - - Red Hat Enterprise Linux 5 - Minimal Install (32 bit) (5 - 100 Core) - - - - id - - -879 - - - - softwareDescriptionId - - - - - - upgradeItemId - - - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 662 - - - - longDescription - - Redhat / EL / 5.5-32 Minimal for CCI - - - - manufacturer - - Redhat - - - - name - - EL - - - - operatingSystem - - 1 - - - - referenceCode - - REDHAT_5_32 - - - - upgradeSoftwareDescriptionId - - 927 - - - - upgradeSwDescId - - 927 - - - - version - - 5.5-32 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - template - - - - operatingSystemReferenceCode - - REDHAT_5_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Ubuntu Linux 12.04 LTS Precise Pangolin - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - UBUNTU_12_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Ubuntu Linux 12.04 LTS Precise Pangolin - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - UBUNTU_12_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - UBUNTU_10_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - UBUNTU_10_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - UBUNTU_8_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - UBUNTU_8_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Vyatta 6.6 Community Edition (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - VYATTACE_6.6_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - 0 - - - - recurringFee - - 0 - - - - item - - - - description - - Vyatta 6.5 Community Edition (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - VYATTACE_6.5_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2012 Standard Edition (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2012-STD_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2012 Datacenter Edition (64bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2012-DC_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2008 Standard Edition SP2 (64bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-STD-SP2_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2008 Standard Edition SP2 (32bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-STD-SP2_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2008 Standard SP1 with R2 (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-STD-R2-SP1_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2008 R2 Standard Edition (64bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-STD-R2_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .1 - - - - recurringFee - - 50 - - - - item - - - - description - - Windows Server 2008 Enterprise Edition SP2 (64bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-ENT-SP2_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .1 - - - - recurringFee - - 50 - - - - item - - - - description - - Windows Server 2008 Enterprise Edition SP2 (32bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-ENT-SP2_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .1 - - - - recurringFee - - 50 - - - - item - - - - description - - Windows Server 2008 R2 Enterprise Edition (64bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-ENT-R2_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2008 Datacenter Edition SP2 (64bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-DC-SP2_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2008 R2 Datacenter Edition (64bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2008-DC-R2_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2003 Standard SP2 with R2 (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2003-STD-SP2-5_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2003 Standard SP2 with R2 (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2003-STD-SP2-5_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 50 - - - - item - - - - description - - Windows Server 2003 Enterprise SP2 with R2 (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2003-ENT-SP2-5_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 50 - - - - item - - - - description - - Windows Server 2003 Enterprise SP2 with R2 (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2003-ENT-SP2-5_32 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2003 Datacenter SP2 with R2 (64 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2003-DC-SP2-1_64 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .05 - - - - recurringFee - - 20 - - - - item - - - - description - - Windows Server 2003 Datacenter SP2 with R2 (32 bit) - - - - - - - - - - template - - - - operatingSystemReferenceCode - - WIN_2003-DC-SP2-1_32 - - - - - - - - - - - - - processors - - - - - - - itemPrice - - - - hourlyRecurringFee - - .07 - - - - recurringFee - - 29 - - - - item - - - - description - - 1 x 2.0 GHz Core - - - - - - - - - - template - - - - startCpus - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .14 - - - - recurringFee - - 78 - - - - item - - - - description - - 2 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 2 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .205 - - - - recurringFee - - 123.5 - - - - item - - - - description - - 3 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 3 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .265 - - - - recurringFee - - 165.5 - - - - item - - - - description - - 4 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 4 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .325 - - - - recurringFee - - 207.5 - - - - item - - - - description - - 5 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 5 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .39 - - - - recurringFee - - 253 - - - - item - - - - description - - 6 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 6 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .445 - - - - recurringFee - - 291.5 - - - - item - - - - description - - 7 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 7 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .495 - - - - recurringFee - - 326.5 - - - - item - - - - description - - 8 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 8 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .54 - - - - recurringFee - - 358 - - - - item - - - - description - - 9 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 9 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .59 - - - - recurringFee - - 393 - - - - item - - - - description - - 10 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 10 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .635 - - - - recurringFee - - 424.5 - - - - item - - - - description - - 11 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 11 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .66 - - - - recurringFee - - 442 - - - - item - - - - description - - 12 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 12 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .695 - - - - recurringFee - - 466.5 - - - - item - - - - description - - 13 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 13 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .72 - - - - recurringFee - - 484 - - - - item - - - - description - - 14 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 14 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .74 - - - - recurringFee - - 498 - - - - item - - - - description - - 15 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 15 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .75 - - - - recurringFee - - 505 - - - - item - - - - description - - 16 x 2.0 GHz Cores - - - - - - - - - - template - - - - startCpus - - 16 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .22 - - - - recurringFee - - 159 - - - - item - - - - description - - Private 1 x 2.0 GHz Core - - - - - - - - - - template - - - - dedicatedAccountHostOnlyFlag - - 1 - - - - startCpus - - 1 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .3 - - - - recurringFee - - 199 - - - - item - - - - description - - Private 2 x 2.0 GHz Cores - - - - - - - - - - template - - - - dedicatedAccountHostOnlyFlag - - 1 - - - - startCpus - - 2 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .44 - - - - recurringFee - - 299 - - - - item - - - - description - - Private 4 x 2.0 GHz Cores - - - - - - - - - - template - - - - dedicatedAccountHostOnlyFlag - - 1 - - - - startCpus - - 4 - - - - - - - - - - - itemPrice - - - - hourlyRecurringFee - - .58 - - - - recurringFee - - 399 - - - - item - - - - description - - Private 8 x 2.0 GHz Cores - - - - - - - - - - template - - - - dedicatedAccountHostOnlyFlag - - 1 - - - - startCpus - - 8 - - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml deleted file mode 100644 index cf84f2a24a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - - accountId - - 282402 - - - - createDate - - 2013-11-12T19:33:57+01:00 - - - - dedicatedAccountHostOnlyFlag - - 0 - - - - domain - - example.com - - - - fullyQualifiedDomainName - - libcloud-testing.example.com - - - - hostname - - libcloud-testing - - - - id - - 2905761 - - - - lastPowerStateId - - - - - - lastVerifiedDate - - - - - - maxCpu - - 1 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 2048 - - - - metricPollDate - - - - - - modifyDate - - 2013-11-12T19:36:55+01:00 - - - - startCpus - - 1 - - - - statusId - - 1001 - - - - uuid - - cbc33604-afd0-4820-57c3-6c68ae7c5fe0 - - - - billingItem - - - - allowCancellationFlag - - 1 - - - - cancellationDate - - - - - - categoryCode - - guest_core - - - - createDate - - 2013-11-12T19:33:59+01:00 - - - - currentHourlyCharge - - .056 - - - - cycleStartDate - - 2013-11-12T19:39:03+01:00 - - - - description - - 1 x 2.0 GHz Core - - - - domainName - - example.com - - - - hostName - - libcloud-testing - - - - hourlyRecurringFee - - .056 - - - - hoursUsed - - 1 - - - - id - - 16538495 - - - - laborFee - - 0 - - - - laborFeeTaxRate - - .21 - - - - lastBillDate - - 2013-11-12T19:39:03+01:00 - - - - modifyDate - - 2013-11-12T19:39:03+01:00 - - - - nextBillDate - - 2013-11-28T07:00:00+01:00 - - - - oneTimeFee - - 0 - - - - oneTimeFeeTaxRate - - .21 - - - - orderItemId - - 22774406 - - - - parentId - - - - - - recurringFee - - .056 - - - - recurringFeeTaxRate - - .21 - - - - recurringMonths - - 1 - - - - serviceProviderId - - 1 - - - - setupFee - - 0 - - - - setupFeeTaxRate - - .21 - - - - resourceTableId - - 2905761 - - - - - - - globalIdentifier - - 633fd9e3-4cf7-4c78-b746-c2b76e2c8b88 - - - - managedResourceFlag - - 0 - - - - operatingSystem - - - - hardwareId - - - - - - id - - 2211183 - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - createDate - - 2013-11-12T19:34:16+01:00 - - - - id - - 1867597 - - - - modifyDate - - 2013-11-12T19:34:16+01:00 - - - - password - - LTSp4cpJ - - - - port - - - - - - softwareId - - 2211183 - - - - username - - root - - - - - - - - - - softwareLicense - - - - id - - 1523 - - - - softwareDescriptionId - - 1163 - - - - softwareDescription - - - - controlPanel - - 0 - - - - id - - 1163 - - - - longDescription - - Debian / Debian / 7.0.0-64 Minimal for CCI - - - - manufacturer - - Debian - - - - name - - Debian - - - - operatingSystem - - 1 - - - - referenceCode - - DEBIAN_7_64 - - - - upgradeSoftwareDescriptionId - - - - - - upgradeSwDescId - - - - - - version - - 7.0.0-64 Minimal for CCI - - - - virtualLicense - - 0 - - - - virtualizationPlatform - - 0 - - - - requiredUser - - root - - - - - - - - - - - - - powerState - - - - keyName - - RUNNING - - - - name - - Running - - - - - - - primaryBackendIpAddress - - 10.55.62.124 - - - - primaryIpAddress - - 50.97.215.202 - - - - provisionDate - - 2013-11-12T19:39:03+01:00 - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_catalogItem_5.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_catalogItem_5.xml deleted file mode 100644 index 005ca534e9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_catalogItem_5.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - 0 - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_login.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_login.xml deleted file mode 100644 index 7888f04673..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_login.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_org_240.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_org_240.xml deleted file mode 100644 index e097046489..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_org_240.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_task_10496.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_task_10496.xml deleted file mode 100644 index 25baec7e9b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_task_10496.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_task_11001.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_task_11001.xml deleted file mode 100644 index a81d59ec47..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_task_11001.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031.xml deleted file mode 100644 index 35692ad4ba..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - 10.112.78.69 - - - - The kind of installed guest operating system - Red Hat Enterprise Linux 5 (32-bit) - - - Virtual Hardware - - - - - - - - - - - - - Virtual Hardware Family - 0 - - - - - - testerpart2 - vmx-07 - - -
- - hertz * 10^6 - - - - - Number of Virtual CPUs - 2 virtual CPU(s) - 1 - - - - - - - - 3 - 2 - count - - - -
- - byte * 2^20 - - - - - Memory Size - 512MB of memory - 2 - - - - - - - - 4 - 512 - byte * 2^20 - - - -
0
- - - - - - - SCSI Controller - SCSI Controller 0 - 3 - - - - - - - lsilogic - 6 - - - -
- -
- 0 - - - - - - - Hard Disk 1 - 10485760 - 9 - - - - 3 - - - - 17 - 10485760 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_action_deploy.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_action_deploy.xml deleted file mode 100644 index 4203cfd41a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_action_deploy.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_get.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_get.xml deleted file mode 100644 index 35692ad4ba..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_get.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - 10.112.78.69 - - - - The kind of installed guest operating system - Red Hat Enterprise Linux 5 (32-bit) - - - Virtual Hardware - - - - - - - - - - - - - Virtual Hardware Family - 0 - - - - - - testerpart2 - vmx-07 - - -
- - hertz * 10^6 - - - - - Number of Virtual CPUs - 2 virtual CPU(s) - 1 - - - - - - - - 3 - 2 - count - - - -
- - byte * 2^20 - - - - - Memory Size - 512MB of memory - 2 - - - - - - - - 4 - 512 - byte * 2^20 - - - -
0
- - - - - - - SCSI Controller - SCSI Controller 0 - 3 - - - - - - - lsilogic - 6 - - - -
- -
- 0 - - - - - - - Hard Disk 1 - 10485760 - 9 - - - - 3 - - - - 17 - 10485760 - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_powerOn.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_powerOn.xml deleted file mode 100644 index 4f0b52bac6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_powerOn.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_poweroff.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_poweroff.xml deleted file mode 100644 index 22dd84e9f5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_poweroff.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_reset.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_reset.xml deleted file mode 100644 index 35fdc8ecf6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_reset.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224.xml deleted file mode 100644 index 9da42da547..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_action_instantiateVAppTemplate.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_action_instantiateVAppTemplate.xml deleted file mode 100644 index b6a216b076..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_action_instantiateVAppTemplate.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_catalog.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_catalog.xml deleted file mode 100644 index 286a3befe4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_catalog.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCaddRequest.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCaddRequest.xml deleted file mode 100644 index 32c9893598..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCaddRequest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - requestid - - 51 - - - - status - - success - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCendRequest.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCendRequest.xml deleted file mode 100644 index 09bd5d85af..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCendRequest.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - status - - success - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCextendRequest.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCextendRequest.xml deleted file mode 100644 index 09bd5d85af..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCextendRequest.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - status - - success - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetImages.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetImages.xml deleted file mode 100644 index 381978eba3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetImages.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - id - - 8 - - - - name - - CentOS 5 (EC2) - - - - - - - - id - - 5 - - - - name - - CentOS 5.4 Base (32 bit VM) - - - - - - - - id - - 6 - - - - name - - WinXP Base (32 bit VM) - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestConnectData.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestConnectData.xml deleted file mode 100644 index 78345e72a4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestConnectData.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - status - - ready - - - - serverIP - - 152.46.20.67 - - - - user - - admin - - - - password - - ehkNGW - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestIds.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestIds.xml deleted file mode 100644 index a9e56ca1e1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestIds.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - status - - success - - - - requests - - - - - - - requestid - - 51 - - - - imageid - - 5 - - - - imagename - - CentOS 5.4 Base (32 bit VM) - - - - start - - 1334150100 - - - - end - - 1334168100 - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestStatus.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestStatus.xml deleted file mode 100644 index 89b509bbf6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestStatus.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - status - - ready - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Account_getVirtualGuests.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Account_getVirtualGuests.xml deleted file mode 100644 index 0452f07a64..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Account_getVirtualGuests.xml +++ /dev/null @@ -1,1066 +0,0 @@ - - - - - - - - - - privateNetworkOnlyFlag - - 0 - - - - id - - 1832 - - - - accountId - - 11111 - - - - statusId - - 1001 - - - - uuid - - eaa9aaa2-8e2e-d6e0-ce11-6f01e765779c - - - - hostname - - test1 - - - - domain - - libcloud.org - - - - maxCpu - - 2 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 2048 - - - - startCpus - - 2 - - - - createDate - - 2009-09-04T14:49:45-05:00 - - - - modifyDate - - 2010-04-22T13:08:47-05:00 - - - - metricPollDate - - 2010-04-22T13:08:00-05:00 - - - - dedicatedAccountHostOnlyFlag - - 0 - - - - powerState - - - - name - - Running - - - - keyName - - RUNNING - - - - - - - softwareComponents - - - - - - - id - - 191115 - - - - hardwareId - - - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - id - - 166980 - - - - softwareId - - 191115 - - - - username - - root - - - - password - - TEST - - - - createDate - - 2009-09-04T14:49:51-05:00 - - - - modifyDate - - 2009-09-04T14:49:51-05:00 - - - - port - - - - - - - - - - - - - - - - - - primaryIpAddress - - 67.254.254.254 - - - - primaryBackendIpAddress - - 10.254.254.254 - - - - - - - - privateNetworkOnlyFlag - - 0 - - - - id - - 13402 - - - - accountId - - 11111 - - - - statusId - - 1001 - - - - uuid - - 9e9e9e99-4ed9-4645-19f3-55ee4e404d56 - - - - hostname - - test2 - - - - domain - - libcloud.org - - - - maxCpu - - 1 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 1024 - - - - startCpus - - 1 - - - - createDate - - 2010-03-23T17:06:13-05:00 - - - - modifyDate - - 2010-04-22T13:08:43-05:00 - - - - metricPollDate - - 2010-04-22T13:08:00-05:00 - - - - dedicatedAccountHostOnlyFlag - - 0 - - - - powerState - - - - name - - Running - - - - keyName - - RUNNING - - - - - - - softwareComponents - - - - - - - id - - 257314 - - - - hardwareId - - - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - id - - 235268 - - - - softwareId - - 257314 - - - - username - - root - - - - password - - TEST - - - - createDate - - 2010-03-23T17:06:17-05:00 - - - - modifyDate - - 2010-03-23T17:06:17-05:00 - - - - port - - - - - - - - - - - - - - - - - - primaryIpAddress - - 174.254.254.254 - - - - primaryBackendIpAddress - - 10.254.254.254 - - - - - - - - privateNetworkOnlyFlag - - 0 - - - - id - - 19293 - - - - accountId - - 11111 - - - - statusId - - 1001 - - - - uuid - - 9f99e19b-2c61-9cd5-2081-67b57fd7977b - - - - hostname - - test3 - - - - domain - - libcloud.org - - - - maxCpu - - 2 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 1024 - - - - startCpus - - 2 - - - - createDate - - 2010-04-22T12:38:53-05:00 - - - - modifyDate - - 2010-04-22T13:08:01-05:00 - - - - metricPollDate - - 2010-04-22T13:08:00-05:00 - - - - dedicatedAccountHostOnlyFlag - - 1 - - - - powerState - - - - name - - Running - - - - keyName - - RUNNING - - - - - - - softwareComponents - - - - - - - id - - 277185 - - - - hardwareId - - - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - id - - 250826 - - - - softwareId - - 277185 - - - - username - - root - - - - password - - TEST - - - - createDate - - 2010-04-22T12:38:57-05:00 - - - - modifyDate - - 2010-04-22T12:38:57-05:00 - - - - port - - - - - - - - - - - - - - - - - - primaryIpAddress - - 174.254.254.254 - - - - primaryBackendIpAddress - - 10.254.254.254 - - - - - - - - privateNetworkOnlyFlag - - 0 - - - - id - - 19288 - - - - accountId - - 11111 - - - - statusId - - 1001 - - - - uuid - - 999f77d9-679b-c47d-136d-04cd302384ec - - - - hostname - - test4 - - - - domain - - libcloud.org - - - - maxCpu - - 2 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 1024 - - - - startCpus - - 2 - - - - createDate - - 2010-04-22T12:15:24-05:00 - - - - modifyDate - - 2010-04-22T13:08:31-05:00 - - - - metricPollDate - - 2010-04-22T13:08:00-05:00 - - - - dedicatedAccountHostOnlyFlag - - 1 - - - - powerState - - - - name - - Running - - - - keyName - - RUNNING - - - - - - - softwareComponents - - - - - - - id - - 277171 - - - - hardwareId - - - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - id - - 250815 - - - - softwareId - - 277171 - - - - username - - root - - - - password - - TEST - - - - createDate - - 2010-04-22T12:15:26-05:00 - - - - modifyDate - - 2010-04-22T12:15:26-05:00 - - - - port - - - - - - - - - - - - - - - - - - primaryIpAddress - - 174.254.254.254 - - - - primaryBackendIpAddress - - 10.254.254.254 - - - - - - - - privateNetworkOnlyFlag - - 0 - - - - id - - 19284 - - - - accountId - - 11111 - - - - statusId - - 1001 - - - - uuid - - f3c73738-7731-1372-f3c3-e6808082f824 - - - - hostname - - test5 - - - - domain - - libcloud.org - - - - maxCpu - - 2 - - - - maxCpuUnits - - CORE - - - - maxMemory - - 1024 - - - - startCpus - - 2 - - - - createDate - - 2010-04-22T12:11:23-05:00 - - - - modifyDate - - 2010-04-22T13:08:31-05:00 - - - - metricPollDate - - 2010-04-22T13:08:00-05:00 - - - - dedicatedAccountHostOnlyFlag - - 1 - - - - powerState - - - - name - - Running - - - - keyName - - RUNNING - - - - - - - softwareComponents - - - - - - - id - - 277167 - - - - hardwareId - - - - - - manufacturerLicenseInstance - - - - - - passwords - - - - - - - id - - 250811 - - - - softwareId - - 277167 - - - - username - - root - - - - password - - TEST - - - - createDate - - 2010-04-22T12:11:27-05:00 - - - - modifyDate - - 2010-04-22T12:11:27-05:00 - - - - port - - - - - - - - - - - - - - - - - - primaryIpAddress - - 174.254.254.254 - - - - primaryBackendIpAddress - - 10.254.254.254 - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Location_Datacenter_getDatacenters.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Location_Datacenter_getDatacenters.xml deleted file mode 100644 index 9b3799dee6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Location_Datacenter_getDatacenters.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - id - - 2 - - - - name - - dal00 - - - - longName - - Corporate HQ - - - - - - - - id - - 3 - - - - name - - dal01 - - - - longName - - Dallas - - - - - - - - id - - 18171 - - - - name - - sea01 - - - - longName - - Seattle - - - - - - - - id - - 37473 - - - - name - - wdc01 - - - - longName - - Washington, DC - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml deleted file mode 100644 index e3ec14ddad..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - \CF\CB\AD\5D\1D\34\09\4D\A4\77\8D\A3\CA\99\75\FB - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_catalogItem_3132e037_759b_4627_9056_ca66466fa607.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_catalogItem_3132e037_759b_4627_9056_ca66466fa607.xml deleted file mode 100644 index d48b6f8feb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_catalogItem_3132e037_759b_4627_9056_ca66466fa607.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4.xml deleted file mode 100644 index 9cca0b7ee5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - false - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4.xml deleted file mode 100644 index 33853751df..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - true - 65.41.64.1 - 255.255.252.0 - 65.41.42.113 - 65.41.42.114 - vm.netsuite.com - - - 65.41.65.1 - 65.41.65.64 - - - 65.41.65.70 - 65.41.65.88 - - - 65.41.65.90 - 65.41.66.6 - - - 65.41.66.8 - 65.41.66.67 - - - 65.41.66.69 - 65.41.66.108 - - - 65.41.66.110 - 65.41.66.227 - - - 65.41.66.229 - 65.41.67.254 - - - - bridged - false - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_org.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_org.xml deleted file mode 100644 index 6cf4081606..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_org.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xml deleted file mode 100644 index 641fcada63..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - MyOrg Product Development - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml deleted file mode 100644 index bcbbd182fc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml deleted file mode 100644 index 13c89db9c4..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_sessions.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_sessions.xml deleted file mode 100644 index bccdc58f73..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_sessions.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml deleted file mode 100644 index 1f55575580..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - 100 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy.xml deleted file mode 100644 index 05f0953f7c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy_error.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy_error.xml deleted file mode 100644 index 59effee344..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy_error.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_undeployTest.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_undeployTest.xml deleted file mode 100644 index 6b05191678..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_undeployTest.xml +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Lease settings section - - 0 - 0 - - - VApp startup section - - - - - The list of logical networks - - - - - - The configuration parameters for logical networks - - - - - - - true - 65.41.64.1 - 255.255.252.0 - 65.41.42.113 - 65.41.42.114 - vm.myorg.com - - - 65.41.67.1 - 65.41.67.254 - - - - - bridged - false - - - false - 3600 - 7200 - - 65.41.64.2 - 65.41.67.0 - - - - true - drop - false - - true - Allow all outgoing traffic - allow - - true - - -1 - Any - -1 - Any - out - false - - - - true - ipTranslation - allowTraffic - - - automatic - ScrumVM_Master - 0 - - - - - false - - - - - false - - - - - - false - - - - - - - - - - - - - - - Virtual hardware requirements - - Virtual Hardware Family - 0 - mgalet-test2 - vmx-07 - - - 00:50:56:01:00:99 - 0 - true - vCloud - Default - PCNet32 ethernet adapter - Network adapter 0 - 1 - PCNet32 - 10 - - - 0 - SCSI Controller - SCSI Controller 0 - 2 - lsilogic - 6 - - - 0 - Hard disk - Hard disk 1 - - 2000 - 2 - 17 - - - 0 - IDE Controller - IDE Controller 0 - 3 - 5 - - - 0 - false - CD/DVD Drive - CD/DVD Drive 1 - - 3002 - 3 - 15 - - - 0 - false - Floppy Drive - Floppy Drive 1 - - 8000 - 14 - - - hertz * 10^6 - Number of Virtual CPUs - 2 virtual CPU(s) - 4 - 0 - 3 - 2 - 0 - - - - byte * 2^20 - Memory Size - 4096 MB of memory - 5 - 0 - 4 - 4096 - 0 - - - - - - - - - - - - - - - - - Specifies the operating system installed - Red Hat Enterprise Linux 5 (64-bit) - - - - Specifies the available VM network connections - 0 - - 0 - 65.41.67.2 - true - 00:50:56:01:00:99 - POOL - - - - - Specifies Guest OS Customization Settings - true - false - dd75d1d3-5b7b-48f0-aff3-69622ab7e045 - false - false - true - true - sN#9QH9# - false - mgalet-test2 - - - - Specifies Runtime info - - - ScrumVM_Master - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a.xml deleted file mode 100644 index a4de57eee6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a.xml +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - - - - - - - Lease settings section - - 0 - 0 - - - VApp startup section - - - - - The list of logical networks - - - - - - The configuration parameters for logical networks - - - - - - - true - 65.41.64.1 - 255.255.252.0 - 65.41.42.113 - 65.41.42.114 - vm.myorg.com - - - 65.41.67.1 - 65.41.67.254 - - - - - bridged - false - - - false - 3600 - 7200 - - 65.41.64.2 - 65.41.67.0 - - - - true - drop - false - - true - Allow all outgoing traffic - allow - - true - - -1 - Any - -1 - Any - out - false - - - - true - ipTranslation - allowTraffic - - - automatic - ScrumVM_Master - 0 - - - - - false - - - - - true - - - - - - false - - - - - - - - - - - - - - - - - - - Virtual hardware requirements - - Virtual Hardware Family - 0 - mgalet-test2 - vmx-07 - - - 00:50:56:01:00:99 - 0 - true - vCloud - Default - PCNet32 ethernet adapter - Network adapter 0 - 1 - PCNet32 - 10 - - - 0 - SCSI Controller - SCSI Controller 0 - 2 - lsilogic - 6 - - - 0 - Hard disk - Hard disk 1 - - 2000 - 2 - 17 - - - 0 - IDE Controller - IDE Controller 0 - 3 - 5 - - - 0 - false - CD/DVD Drive - CD/DVD Drive 1 - - 3002 - 3 - 15 - - - 0 - false - Floppy Drive - Floppy Drive 1 - - 8000 - 14 - - - hertz * 10^6 - Number of Virtual CPUs - 2 virtual CPU(s) - 4 - 0 - 3 - 2 - 0 - - - - byte * 2^20 - Memory Size - 4096 MB of memory - 5 - 0 - 4 - 4096 - 0 - - - - - - - - - - - - - - - - - Specifies the operating system installed - Red Hat Enterprise Linux 5 (64-bit) - - - - Specifies the available VM network connections - 0 - - 0 - 65.41.67.2 - true - 00:50:56:01:00:99 - POOL - - - - - Specifies Guest OS Customization Settings - true - false - dd75d1d3-5b7b-48f0-aff3-69622ab7e045 - false - false - true - true - sN#9QH9# - false - mgalet-test2 - - - - Specifies Runtime info - - - ScrumVM_Master - - - VMware ESXi - 5.0.0 - VMware, Inc. - en - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml deleted file mode 100644 index d6f426e2ad..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml +++ /dev/null @@ -1,10 +0,0 @@ - - true - ReadOnly - - - - FullControl - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xml deleted file mode 100644 index 5427533908..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_powerOn.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_powerOn.xml deleted file mode 100644 index 5472234659..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_powerOn.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_reset.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_reset.xml deleted file mode 100644 index 568b8d5961..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_reset.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b.xml deleted file mode 100644 index 78192f88dc..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b.xml +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - - - - - - - - - - Lease settings section - - 0 - 0 - - - VApp startup section - - - - - The list of logical networks - - - - - - The configuration parameters for logical networks - - - - - - - true - 65.41.64.1 - 255.255.252.0 - 65.41.42.113 - 65.41.42.114 - vm.myorg.com - - - 65.41.67.1 - 65.41.67.254 - - - - - bridged - false - - - false - 3600 - 7200 - - 65.41.64.2 - 65.41.67.0 - - - - true - drop - false - - true - Allow all outgoing traffic - allow - - true - - -1 - Any - -1 - Any - out - false - - - - true - ipTranslation - allowTraffic - - - automatic - ScrumVM_Master - 0 - - - - - false - - - - - true - - - - - - false - - - - - - - - - - - - - - - - - - - Virtual hardware requirements - - Virtual Hardware Family - 0 - mgalet-test2 - vmx-07 - - - 00:50:56:01:00:99 - 0 - true - vCloud - Default - PCNet32 ethernet adapter - Network adapter 0 - 1 - PCNet32 - 10 - - - 0 - SCSI Controller - SCSI Controller 0 - 2 - lsilogic - 6 - - - 0 - Hard disk - Hard disk 1 - - 2000 - 2 - 17 - - - 0 - IDE Controller - IDE Controller 0 - 3 - 5 - - - 0 - false - CD/DVD Drive - CD/DVD Drive 1 - - 3002 - 3 - 15 - - - 0 - false - Floppy Drive - Floppy Drive 1 - - 8000 - 14 - - - hertz * 10^6 - Number of Virtual CPUs - 2 virtual CPU(s) - 4 - 0 - 3 - 2 - 0 - - - - byte * 2^20 - Memory Size - 4096 MB of memory - 5 - 0 - 4 - 4096 - 0 - - - - - - - - - - - - - - - - - Specifies the operating system installed - Red Hat Enterprise Linux 5 (64-bit) - - - - Specifies the available VM network connections - 0 - - 0 - 192.168.0.100 - 192.168.0.103 - true - 00:50:56:01:00:d9 - POOL - - - - Specifies Guest OS Customization Settings - true - false - dd75d1d3-5b7b-48f0-aff3-69622ab7e045 - false - false - true - true - sN#9QH9# - false - mgalet-test2 - - - - Specifies Runtime info - - - ScrumVM_Master - - - VMware ESXi - 5.0.0 - VMware, Inc. - en - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c.xml deleted file mode 100644 index 75712d3f04..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c.xml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - Lease settings section - - 0 - 0 - - - VApp startup section - - - - - The list of logical networks - - - - - - The configuration parameters for logical networks - - - - - - - true - 65.41.64.1 - 255.255.252.0 - 65.41.42.113 - 65.41.42.114 - vm.myorg.com - - - 65.41.67.1 - 65.41.67.254 - - - - - bridged - false - - - false - 3600 - 7200 - - 65.41.64.2 - 65.41.67.0 - - - - true - drop - false - - true - Allow all outgoing traffic - allow - - true - - -1 - Any - -1 - Any - out - false - - - - true - ipTranslation - allowTraffic - - - automatic - ScrumVM_Master - 0 - - - - - false - - - - - true - - - - - - false - - - - - - - - - - - - - - - - - - - Virtual hardware requirements - - Virtual Hardware Family - 0 - mgalet-test2 - vmx-07 - - - 00:50:56:01:00:99 - 0 - true - vCloud - Default - PCNet32 ethernet adapter - Network adapter 0 - 1 - PCNet32 - 10 - - - 0 - SCSI Controller - SCSI Controller 0 - 2 - lsilogic - 6 - - - 0 - Hard disk - Hard disk 1 - - 2000 - 2 - 17 - - - 0 - IDE Controller - IDE Controller 0 - 3 - 5 - - - 0 - false - CD/DVD Drive - CD/DVD Drive 1 - - 3002 - 3 - 15 - - - 0 - false - Floppy Drive - Floppy Drive 1 - - 8000 - 14 - - - hertz * 10^6 - Number of Virtual CPUs - 2 virtual CPU(s) - 4 - 0 - 3 - 2 - 0 - - - - byte * 2^20 - Memory Size - 4096 MB of memory - 5 - 0 - 4 - 4096 - 0 - - - - - - - - - - - - - - - - - Specifies the available VM network connections - 0 - - 0 - 192.168.0.100 - 192.168.0.103 - true - 00:50:56:01:00:d9 - POOL - - - - Specifies Guest OS Customization Settings - true - false - dd75d1d3-5b7b-48f0-aff3-69622ab7e045 - false - false - true - true - sN#9QH9# - false - mgalet-test2 - - - - Specifies Runtime info - - - ScrumVM_Master - - - VMware ESXi - 5.0.0 - VMware, Inc. - en - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_access_to_resource_forbidden.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_access_to_resource_forbidden.xml deleted file mode 100644 index 830c059b19..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_access_to_resource_forbidden.xml +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vm_test.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vm_test.xml deleted file mode 100644 index bc9260fd39..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vm_test.xml +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Virtual hardware requirements - - Virtual Hardware Family - 0 - ScrumVM_Master - vmx-07 - - - 00:50:56:01:00:d9 - 0 - true - vCloud - Default - PCNet32 ethernet adapter - Network adapter 0 - 1 - PCNet32 - 10 - - - 0 - SCSI Controller - SCSI Controller 0 - 2 - lsilogic - 6 - - - 0 - Hard disk - Hard disk 1 - - 2000 - 2 - 17 - - - 1 - Hard disk - Hard disk 2 - - 2001 - 2 - 17 - - - 2 - Hard disk - Hard disk 3 - - 2002 - 2 - 17 - - - 3 - Hard disk - Hard disk 4 - - 2003 - 2 - 17 - - - 0 - IDE Controller - IDE Controller 0 - 3 - 5 - - - 0 - false - CD/DVD Drive - CD/DVD Drive 1 - - 3002 - 3 - 15 - - - 0 - false - Floppy Drive - Floppy Drive 1 - - 8000 - 14 - - - hertz * 10^6 - Number of Virtual CPUs - 2 virtual CPU(s) - 4 - 0 - 3 - 2 - 0 - - - - byte * 2^20 - Memory Size - 4096 MB of memory - 5 - 0 - 4 - 4096 - 0 - - - - - - - - - - - - - - - - - Specifies the operating system installed - Red Hat Enterprise Linux 5 (64-bit) - - - - Specifies the available VM network connections - 0 - - 0 - 65.33.65.9 - true - 00:50:56:01:00:d9 - POOL - - - - - Specifies Guest OS Customization Settings - true - false - cbfe57d5-7362-482b-b313-e5b5bcff3309 - false - false - true - true - jW!4$$2i - false - #/bin/sh - /usr/local/sbin/ns-guest-customization.sh "$@" - ScrumVMMast-001 - - - - Specifies Runtime info - - - ScrumVM_Master - - - VMware ESXi - 5.0.0 - VMware, Inc. - en - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_get_metadata.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_get_metadata.xml deleted file mode 100644 index 31d88a824d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_get_metadata.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - owners - msamia@netsuite.com - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_post_metadata.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_post_metadata.xml deleted file mode 100644 index 04c7049412..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_post_metadata.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0.xml deleted file mode 100644 index 3e55b5d09d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - AllocationPool - - MB - 5120000 - 5120000 - 1984512 - 0 - - - - MHz - 130000 - 160000 - 0 - 0 - - - MB - 527360 - 527360 - 130752 - 0 - - - - - - - - - - - - - - - vmx-04 - vmx-07 - vmx-08 - - - 0 - 1024 - 150 - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp.xml deleted file mode 100644 index c162a36e9b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - testing instance - - - - - - - 1 - - - - - - false - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate.xml deleted file mode 100644 index 7ba1576dc6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - testing instance - - - - - - - 1 - - - - - - false - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_brokenVdc.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_brokenVdc.xml deleted file mode 100644 index 80993ea602..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_brokenVdc.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - AllocationPool - - MB - 5120000 - 5120000 - 1984512 - 0 - - - - MHz - 130000 - 160000 - 0 - 0 - - - MB - 527360 - 527360 - 130752 - 0 - - - - - - - - - - - - - - vmx-04 - vmx-07 - vmx-08 - - - 0 - 1024 - 150 - true - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml deleted file mode 100644 index 49da7892d3..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml +++ /dev/null @@ -1,17 +0,0 @@ - - Specifies Guest OS Customization Settings - true - false - 9e8837e6-5c4c-4112-bf01-5498616d865f - false - false - true - true - aabbccddee - false - VMMast-001 - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_cpu.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_cpu.xml deleted file mode 100644 index 1cc9c3c24e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_cpu.xml +++ /dev/null @@ -1,11 +0,0 @@ - - hertz * 10^6 - Number of Virtual CPUs - 1 virtual CPU(s) - 4 - 0 - 3 - 1 - 0 - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_disks.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_disks.xml deleted file mode 100644 index 69d9d28609..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_disks.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - 0 - SCSI Controller - SCSI Controller 0 - 2 - lsilogic - 6 - - - 0 - Hard disk - Hard disk 1 - - 2000 - 2 - 17 - - - 1 - Hard disk - Hard disk 2 - - 2001 - 2 - 17 - - - 2 - Hard disk - Hard disk 3 - - 2002 - 2 - 17 - - - 3 - Hard disk - Hard disk 4 - - 2003 - 2 - 17 - - - 0 - IDE Controller - IDE Controller 0 - 3 - 5 - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_memory.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_memory.xml deleted file mode 100644 index 1d23916650..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_memory.xml +++ /dev/null @@ -1,11 +0,0 @@ - - byte * 2^20 - Memory Size - 4096 MB of memory - 5 - 0 - 4 - 4096 - 0 - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml deleted file mode 100644 index 31cd08f33b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_cpu.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_cpu.xml deleted file mode 100644 index ab55770cfb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_cpu.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_disks.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_disks.xml deleted file mode 100644 index ab55770cfb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_disks.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_memory.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_memory.xml deleted file mode 100644 index ab55770cfb..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_memory.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/create_node.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/create_node.xml deleted file mode 100644 index e33bdd6c44..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/create_node.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 1234 - 1235386846 - QUEUED - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/failure.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/failure.xml deleted file mode 100644 index 1424e812fd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/failure.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/images.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/images.xml deleted file mode 100644 index 7d83ea6294..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/images.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 32 - Linux - 2.6.18 - CentOS - 5.1 - root - - - ext3 - 880 - - Base install of CentOS 5.1 i386. - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/locations.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/locations.xml deleted file mode 100644 index a8b81b1d23..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/locations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - Amsterdam - - - New York - - - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/nodes.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/nodes.xml deleted file mode 100644 index f9a3117bab..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/nodes.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - Z100.12 - Virtual Server - Voxrox Intel Platform - - LGA7 - XO / 12th Floor - Private cage - primary - Row Z - Rack 100 - 12 - - - - 172.x.x.x - - - - - user - - - root - - -
zz.zz.us.voxel.net
- 55555 - user -
-
- Voxel TruManaged Server Configuration 1 -
- ... -
-
diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/success.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/success.xml deleted file mode 100644 index c2d0c8d48e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/success.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/unauthorized.xml b/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/unauthorized.xml deleted file mode 100644 index 89d7df0b04..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/voxel/unauthorized.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - voxel.devices.list - - 2010-02-10T23:39:25.808107+0000 - authshouldfail - ae069bb835e998622caaddaeff8c98e0 - - YOUR_SECRETtimestamp2010-02-10T23:39:25.808107+0000methodvoxel.devices.listkeyauthshouldfail - diff --git a/awx/lib/site-packages/libcloud/test/compute/fixtures/vpsnet/_available_clouds_api10json_templates.json b/awx/lib/site-packages/libcloud/test/compute/fixtures/vpsnet/_available_clouds_api10json_templates.json deleted file mode 100644 index 6b719592ea..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/fixtures/vpsnet/_available_clouds_api10json_templates.json +++ /dev/null @@ -1 +0,0 @@ -[{"cloud":{"system_templates":[{"id":9,"label":"Ubuntu 8.04 x64"},{"id":10,"label":"CentOS 5.2 x64"},{"id":11,"label":"Gentoo 2008.0 x64"},{"id":18,"label":"Ubuntu 8.04 x64 LAMP"},{"id":19,"label":"Ubuntu 8.04 x64 MySQL"},{"id":20,"label":"Ubuntu 8.04 x64 Postfix"},{"id":21,"label":"Ubuntu 8.04 x64 Apache"},{"id":22,"label":"CentOS 5.2 x64 MySQL"},{"id":23,"label":"CentOS 5.2 x64 LAMP"},{"id":24,"label":"CentOS 5.2 x64 HAProxy"},{"id":25,"label":"CentOS 5.2 x64 Postfix"},{"id":26,"label":"CentOS 5.2 x64 Varnish"},{"id":27,"label":"CentOS 5.2 x64 Shoutcast"},{"id":28,"label":"CentOS 5.2 x64 Apache"},{"id":40,"label":"cPanel"},{"id":42,"label":"Debian 5.0 (Lenny) x64"},{"id":58,"label":"Django on Ubuntu 8.04 (x86)"},{"id":59,"label":"Drupal 5 on Ubuntu 8.04 (x86)"},{"id":60,"label":"Drupal 6 on Ubuntu 8.04 (x86)"},{"id":61,"label":"Google App Engine on Ubuntu 8.04 (x86)"},{"id":62,"label":"LAMP on Ubuntu 8.04 (x86)"},{"id":63,"label":"LAPP on Ubuntu 8.04 (x86)"},{"id":64,"label":"MediaWiki on Ubuntu 8.04 (x86)"},{"id":65,"label":"MySQL on Ubuntu 8.04 (x86)"},{"id":66,"label":"phpBB on Ubuntu 8.04 (x86)"},{"id":67,"label":"PostgreSQL on Ubuntu 8.04 (x86)"},{"id":68,"label":"Rails on Ubuntu 8.04 (x86)"},{"id":69,"label":"Tomcat on Ubuntu 8.04 (x86)"},{"id":70,"label":"Wordpress on Ubuntu 8.04 (x86)"},{"id":71,"label":"Joomla on Ubuntu 8.04 (x86)"},{"id":72,"label":"Ubuntu 8.04 Default Install (turnkey)"},{"id":128,"label":"CentOS Optimised"},{"id":129,"label":"Optimised CentOS + Apache + MySQL + PHP"},{"id":130,"label":"Optimised CentOS + Apache + MySQL + Ruby"},{"id":131,"label":"Optimised CentOS + Apache + MySQL + Ruby + PHP"},{"id":132,"label":"Debian Optimised"},{"id":133,"label":"Optimised Debian + Apache + MySQL + PHP"},{"id":134,"label":"Optimised Debian + NGINX + MySQL + PHP"},{"id":135,"label":"Optimised Debian + Lighttpd + MySQL + PHP"},{"id":136,"label":"Optimised Debian + Apache + MySQL + Ruby + PHP"},{"id":137,"label":"Optimised Debian + Apache + MySQL + Ruby"},{"id":138,"label":"Optimised Debian + NGINX + MySQL + Ruby + PHP"},{"id":139,"label":"Optimised Debian + NGINX + MySQL + Ruby"},{"id":140,"label":"Optimised Debian + Apache + MySQL + PHP + Magento"},{"id":141,"label":"Optimised Debian + NGINX + MySQL + PHP + Magento"},{"id":142,"label":"Optimised Debian + Lighttpd + MySQL + PHP + Wordpress"}],"id":2,"label":"USA VPS Cloud"}},{"cloud":{"system_templates":[{"id":15,"label":"Ubuntu 8.04 x64"},{"id":16,"label":"CentOS 5.2 x64"},{"id":17,"label":"Gentoo 2008.0 x64"},{"id":29,"label":"Ubuntu 8.04 x64 LAMP"},{"id":30,"label":"Ubuntu 8.04 x64 MySQL"},{"id":31,"label":"Ubuntu 8.04 x64 Postfix"},{"id":32,"label":"Ubuntu 8.04 x64 Apache"},{"id":33,"label":"CentOS 5.2 x64 MySQL"},{"id":34,"label":"CentOS 5.2 x64 LAMP"},{"id":35,"label":"CentOS 5.2 x64 HAProxy"},{"id":36,"label":"CentOS 5.2 x64 Postfix"},{"id":37,"label":"CentOS 5.2 x64 Varnish"},{"id":38,"label":"CentOS 5.2 x64 Shoutcast"},{"id":39,"label":"CentOS 5.2 x64 Apache"},{"id":41,"label":"cPanel"},{"id":43,"label":"Debian 5.0 (Lenny) x64"},{"id":44,"label":"Django on Ubuntu 8.04 (x86)"},{"id":45,"label":"Drupal 5 on Ubuntu 8.04 (x86)"},{"id":46,"label":"Drupal 6 on Ubuntu 8.04 (x86)"},{"id":47,"label":"Google App Engine on Ubuntu 8.04 (x86)"},{"id":48,"label":"LAMP on Ubuntu 8.04 (x86)"},{"id":49,"label":"LAPP on Ubuntu 8.04 (x86)"},{"id":50,"label":"MediaWiki on Ubuntu 8.04 (x86)"},{"id":51,"label":"MySQL on Ubuntu 8.04 (x86)"},{"id":52,"label":"phpBB on Ubuntu 8.04 (x86)"},{"id":53,"label":"PostgreSQL on Ubuntu 8.04 (x86)"},{"id":54,"label":"Rails on Ubuntu 8.04 (x86)"},{"id":55,"label":"Tomcat on Ubuntu 8.04 (x86)"},{"id":56,"label":"Wordpress on Ubuntu 8.04 (x86)"},{"id":57,"label":"Joomla on Ubuntu 8.04 (x86)"},{"id":73,"label":"Ubuntu 8.04 Default Install (turnkey)"},{"id":148,"label":"CentOS Optimised"},{"id":149,"label":"Optimised CentOS + Apache + MySQL + PHP"},{"id":150,"label":"Optimised CentOS + Apache + MySQL + Ruby"},{"id":151,"label":"Optimised CentOS + Apache + MySQL + Ruby + PHP"},{"id":152,"label":"Debian Optimised"},{"id":153,"label":"Optimised Debian + Apache + MySQL + PHP"},{"id":154,"label":"Optimised Debian + NGINX + MySQL + PHP"},{"id":155,"label":"Optimised Debian + Lighttpd + MySQL + PHP"},{"id":156,"label":"Optimised Debian + Apache + MySQL + Ruby + PHP"},{"id":157,"label":"Optimised Debian + Apache + MySQL + Ruby"},{"id":158,"label":"Optimised Debian + NGINX + MySQL + Ruby + PHP"},{"id":159,"label":"Optimised Debian + NGINX + MySQL + Ruby"},{"id":160,"label":"Optimised Debian + Lighttpd + MySQL + PHP + Wordpress"}],"id":3,"label":"UK VPS Cloud"}}] diff --git a/awx/lib/site-packages/libcloud/test/compute/test_abiquo.py b/awx/lib/site-packages/libcloud/test/compute/test_abiquo.py deleted file mode 100644 index 2c5cc5c0c9..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_abiquo.py +++ /dev/null @@ -1,481 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Abiquo Test Suite -""" -import unittest -import sys - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.abiquo import AbiquoNodeDriver -from libcloud.common.abiquo import ForbiddenError, get_href -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.compute.base import NodeLocation, NodeImage -from libcloud.test.compute import TestCaseMixin -from libcloud.test import MockHttpTestCase -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class AbiquoNodeDriverTest(unittest.TestCase, TestCaseMixin): - - """ - Abiquo Node Driver test suite - """ - - def setUp(self): - """ - Set up the driver with the main user - """ - AbiquoNodeDriver.connectionCls.conn_classes = (AbiquoMockHttp, None) - self.driver = AbiquoNodeDriver('son', 'goku', - 'http://dummy.host.com/api') - - def test_unauthorized_controlled(self): - """ - Test the Unauthorized Exception is Controlled. - - Test, through the 'login' method, that a '401 Unauthorized' - raises a 'InvalidCredsError' instead of the 'MalformedUrlException' - """ - self.assertRaises(InvalidCredsError, AbiquoNodeDriver, 'son', - 'goten', 'http://dummy.host.com/api') - - def test_forbidden_controlled(self): - """ - Test the Forbidden Exception is Controlled. - - Test, through the 'list_images' method, that a '403 Forbidden' - raises an 'ForbidenError' instead of the 'MalformedUrlException' - """ - AbiquoNodeDriver.connectionCls.conn_classes = (AbiquoMockHttp, None) - conn = AbiquoNodeDriver('son', 'gohan', 'http://dummy.host.com/api') - self.assertRaises(ForbiddenError, conn.list_images) - - def test_handle_other_errors_such_as_not_found(self): - """ - Test common 'logical' exceptions are controlled. - - Test that common exception (normally 404-Not Found and 409-Conflict), - that return an XMLResponse with the explanation of the errors are - controlled. - """ - self.driver = AbiquoNodeDriver('go', 'trunks', - 'http://dummy.host.com/api') - self.assertRaises(LibcloudError, self.driver.list_images) - - def test_ex_create_and_delete_empty_group(self): - """ - Test the creation and deletion of an empty group. - """ - group = self.driver.ex_create_group('libcloud_test_group') - group.destroy() - - def test_create_node_no_image_raise_exception(self): - """ - Test 'create_node' without image. - - Test the 'create_node' function without 'image' parameter raises - an Exception - """ - self.assertRaises(LibcloudError, self.driver.create_node) - - def test_create_node_specify_location(self): - """ - Test you can create a node specifying the location. - """ - image = self.driver.list_images()[0] - location = self.driver.list_locations()[0] - self.driver.create_node(image=image, location=location) - - def test_create_node_specify_wrong_location(self): - """ - Test you can not create a node with wrong location. - """ - image = self.driver.list_images()[0] - location = NodeLocation(435, 'fake-location', 'Spain', self.driver) - self.assertRaises(LibcloudError, self.driver.create_node, image=image, - location=location) - - def test_create_node_specify_wrong_image(self): - """ - Test image compatibility. - - Some locations only can handle a group of images, not all of them. - Test you can not create a node with incompatible image-location. - """ - # Create fake NodeImage - image = NodeImage(3234, 'dummy-image', self.driver) - location = self.driver.list_locations()[0] - # With this image, it should raise an Exception - self.assertRaises(LibcloudError, self.driver.create_node, image=image, - location=location) - - def test_create_node_specify_group_name(self): - """ - Test 'create_node' into a concrete group. - """ - image = self.driver.list_images()[0] - self.driver.create_node(image=image, group_name='new_group_name') - - def test_create_group_location_does_not_exist(self): - """ - Test 'create_node' with an unexistent location. - - Defines a 'fake' location and tries to create a node into it. - """ - location = NodeLocation(435, 'fake-location', 'Spain', self.driver) - # With this location, it should raise an Exception - self.assertRaises(LibcloudError, self.driver.ex_create_group, - name='new_group_name', - location=location) - - def test_destroy_node_response(self): - """ - 'destroy_node' basic test. - - Override the destroy to return a different node available - to be undeployed. (by default it returns an already undeployed node, - for test creation). - """ - self.driver = AbiquoNodeDriver('go', 'trunks', - 'http://dummy.host.com/api') - node = self.driver.list_nodes()[0] - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - def test_destroy_node_response_failed(self): - """ - 'destroy_node' asynchronous error. - - Test that the driver handles correctly when, for some reason, - the 'destroy' job fails. - """ - self.driver = AbiquoNodeDriver('muten', 'roshi', - 'http://dummy.host.com/api') - node = self.driver.list_nodes()[0] - ret = self.driver.destroy_node(node) - self.assertFalse(ret) - - def test_destroy_node_allocation_state(self): - """ - Test the 'destroy_node' invalid state. - - Try to destroy a node when the node is not running. - """ - self.driver = AbiquoNodeDriver('ve', 'geta', - 'http://dummy.host.com/api') - # Override the destroy to return a different node available to be - # undeployed - node = self.driver.list_nodes()[0] - # The mock class with the user:password 've:geta' returns a node that - # is in 'ALLOCATION' state and hence, the 'destroy_node' method should - # raise a LibcloudError - self.assertRaises(LibcloudError, self.driver.destroy_node, node) - - def test_destroy_not_deployed_group(self): - """ - Test 'ex_destroy_group' when group is not deployed. - """ - location = self.driver.list_locations()[0] - group = self.driver.ex_list_groups(location)[1] - self.assertTrue(group.destroy()) - - def test_destroy_deployed_group(self): - """ - Test 'ex_destroy_group' when there are machines running. - """ - location = self.driver.list_locations()[0] - group = self.driver.ex_list_groups(location)[0] - self.assertTrue(group.destroy()) - - def test_destroy_deployed_group_failed(self): - """ - Test 'ex_destroy_group' fails. - - Test driver handles correctly when, for some reason, the - asynchronous job fails. - """ - self.driver = AbiquoNodeDriver('muten', 'roshi', - 'http://dummy.host.com/api') - location = self.driver.list_locations()[0] - group = self.driver.ex_list_groups(location)[0] - self.assertFalse(group.destroy()) - - def test_destroy_group_invalid_state(self): - """ - Test 'ex_destroy_group' invalid state. - - Test the Driver raises an exception when the group is in - invalid temporal state. - """ - self.driver = AbiquoNodeDriver('ve', 'geta', - 'http://dummy.host.com/api') - location = self.driver.list_locations()[0] - group = self.driver.ex_list_groups(location)[1] - self.assertRaises(LibcloudError, group.destroy) - - def test_run_node(self): - """ - Test 'ex_run_node' feature. - """ - node = self.driver.list_nodes()[0] - # Node is by default in NodeState.TERMINATED and AbiquoState == - # 'NOT_ALLOCATED' - # so it is available to be runned - self.driver.ex_run_node(node) - - def test_run_node_invalid_state(self): - """ - Test 'ex_run_node' invalid state. - - Test the Driver raises an exception when try to run a - node that is in invalid state to run. - """ - self.driver = AbiquoNodeDriver('go', 'trunks', - 'http://dummy.host.com/api') - node = self.driver.list_nodes()[0] - # Node is by default in AbiquoState = 'ON' for user 'go:trunks' - # so is not available to be runned - self.assertRaises(LibcloudError, self.driver.ex_run_node, node) - - def test_run_node_failed(self): - """ - Test 'ex_run_node' fails. - - Test driver handles correctly when, for some reason, the - asynchronous job fails. - """ - self.driver = AbiquoNodeDriver('ten', 'shin', - 'http://dummy.host.com/api') - node = self.driver.list_nodes()[0] - # Node is in the correct state, but it fails because of the - # async task and it raises the error. - self.assertRaises(LibcloudError, self.driver.ex_run_node, node) - - def test_get_href(self): - xml = ''' - - - - - -''' - - elem = ET.XML(xml) - - href = get_href(element=elem, rel='edit1') - self.assertEqual(href, '/admin/datacenters/2') - href = get_href(element=elem, rel='edit2') - self.assertEqual(href, '/admin/datacenters/3') - href = get_href(element=elem, rel='edit3') - self.assertEqual(href, '/admin/enterprises/1234') - - -class AbiquoMockHttp(MockHttpTestCase): - - """ - Mock the functionallity of the remote Abiquo API. - """ - fixtures = ComputeFileFixtures('abiquo') - fixture_tag = 'default' - - def _api_login(self, method, url, body, headers): - if headers['Authorization'] == 'Basic c29uOmdvdGVu': - expected_response = self.fixtures.load('unauthorized_user.html') - expected_status = httplib.UNAUTHORIZED - else: - expected_response = self.fixtures.load('login.xml') - expected_status = httplib.OK - return (expected_status, expected_response, {}, '') - - def _api_cloud_virtualdatacenters(self, method, url, body, headers): - return (httplib.OK, self.fixtures.load('vdcs.xml'), {}, '') - - def _api_cloud_virtualdatacenters_4(self, method, url, body, headers): - return (httplib.OK, self.fixtures.load('vdc_4.xml'), {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances(self, method, url, body, headers): - if method == 'POST': - vapp_name = ET.XML(body).findtext('name') - if vapp_name == 'libcloud_test_group': - # we come from 'test_ex_create_and_delete_empty_group(self):' - # method and so, we return the 'ok' return - response = self.fixtures.load('vdc_4_vapp_creation_ok.xml') - return (httplib.OK, response, {}, '') - elif vapp_name == 'new_group_name': - # we come from 'test_ex_create_and_delete_empty_group(self):' - # method and so, we return the 'ok' return - response = self.fixtures.load('vdc_4_vapp_creation_ok.xml') - return (httplib.OK, response, {}, '') - else: - # It will be a 'GET'; - return (httplib.OK, self.fixtures.load('vdc_4_vapps.xml'), {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_5(self, method, url, body, headers): - if method == 'GET': - if headers['Authorization'] == 'Basic dmU6Z2V0YQ==': - # Try to destroy a group with 'needs_sync' state - response = self.fixtures.load('vdc_4_vapp_5_needs_sync.xml') - else: - # Try to destroy a group with 'undeployed' state - response = self.fixtures.load('vdc_4_vapp_5.xml') - return (httplib.OK, response, {}, '') - else: - # it will be a 'DELETE' - return (httplib.NO_CONTENT, '', {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6(self, method, url, body, headers): - if method == 'GET': - # deployed vapp - response = self.fixtures.load('vdc_4_vapp_6.xml') - return (httplib.OK, response, {}, '') - else: - # it will be a 'DELETE' - return (httplib.NO_CONTENT, '', {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_tasks_1da8c8b6_86f6_49ef_9d29_57dcc73b875a(self, method, url, body, headers): - if headers['Authorization'] == 'Basic bXV0ZW46cm9zaGk=': - # User 'muten:roshi' failed task - response = self.fixtures.load( - 'vdc_4_vapp_6_undeploy_task_failed.xml') - else: - response = self.fixtures.load('vdc_4_vapp_6_undeploy_task.xml') - return (httplib.OK, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_5_virtualmachines( - self, method, url, body, headers): - # This virtual app never have virtual machines - if method == 'GET': - response = self.fixtures.load('vdc_4_vapp_5_vms.xml') - return (httplib.OK, response, {}, '') - elif method == 'POST': - # it must be a POST - response = self.fixtures.load('vdc_4_vapp_6_vm_creation_ok.xml') - return (httplib.CREATED, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines( - self, method, url, body, headers): - # Default-created virtual app virtual machines' - if method == 'GET': - if headers['Authorization'] == 'Basic dmU6Z2V0YQ==': - response = self.fixtures.load('vdc_4_vapp_6_vms_allocated.xml') - else: - response = self.fixtures.load('vdc_4_vapp_6_vms.xml') - return (httplib.OK, response, {}, '') - else: - # it must be a POST - response = self.fixtures.load('vdc_4_vapp_6_vm_creation_ok.xml') - return (httplib.CREATED, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3(self, method, url, body, headers): - if (headers['Authorization'] == 'Basic Z286dHJ1bmtz' or - headers['Authorization'] == 'Basic bXV0ZW46cm9zaGk='): - # Undeploy node - response = self.fixtures.load("vdc_4_vapp_6_vm_3_deployed.xml") - elif headers['Authorization'] == 'Basic dmU6Z2V0YQ==': - # Try to undeploy a node with 'allocation' state - response = self.fixtures.load('vdc_4_vapp_6_vm_3_allocated.xml') - else: - # Get node - response = self.fixtures.load('vdc_4_vapp_6_vm_3.xml') - return (httplib.OK, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_action_deploy(self, method, url, - body, headers): - response = self.fixtures.load('vdc_4_vapp_6_vm_3_deploy.xml') - return (httplib.CREATED, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_tasks_b44fe278_6b0f_4dfb_be81_7c03006a93cb(self, method, url, body, headers): - - if headers['Authorization'] == 'Basic dGVuOnNoaW4=': - # User 'ten:shin' failed task - response = self.fixtures.load( - 'vdc_4_vapp_6_vm_3_deploy_task_failed.xml') - else: - response = self.fixtures.load('vdc_4_vapp_6_vm_3_deploy_task.xml') - return (httplib.OK, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_action_undeploy( - self, method, url, body, headers): - response = self.fixtures.load('vdc_4_vapp_6_undeploy.xml') - return (httplib.OK, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_action_reset(self, method, - url, body, headers): - response = self.fixtures.load('vdc_4_vapp_6_vm_3_reset.xml') - return (httplib.CREATED, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_tasks_a8c9818e_f389_45b7_be2c_3db3a9689940(self, method, url, body, headers): - if headers['Authorization'] == 'Basic bXV0ZW46cm9zaGk=': - # User 'muten:roshi' failed task - response = self.fixtures.load( - 'vdc_4_vapp_6_undeploy_task_failed.xml') - else: - response = self.fixtures.load('vdc_4_vapp_6_vm_3_reset_task.xml') - return (httplib.OK, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_action_undeploy(self, method, url, - body, headers): - response = self.fixtures.load('vdc_4_vapp_6_vm_3_undeploy.xml') - return (httplib.CREATED, response, {}, '') - - def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_network_nics(self, method, url, - body, headers): - response = self.fixtures.load('vdc_4_vapp_6_vm_3_nics.xml') - return (httplib.OK, response, {}, '') - - def _api_admin_datacenters(self, method, url, body, headers): - return (httplib.OK, self.fixtures.load('dcs.xml'), {}, '') - - def _api_admin_enterprises_1(self, method, url, body, headers): - return (httplib.OK, self.fixtures.load('ent_1.xml'), {}, '') - - def _api_admin_enterprises_1_datacenterrepositories(self, method, url, body, headers): - # When the user is the common one for all the tests ('son, 'goku') - # it creates this basic auth and we return the datacenters value - if headers['Authorization'] == 'Basic Z286dHJ1bmtz': - expected_response = self.fixtures.load("not_found_error.xml") - return (httplib.NOT_FOUND, expected_response, {}, '') - elif headers['Authorization'] != 'Basic c29uOmdvaGFu': - return (httplib.OK, self.fixtures.load('ent_1_dcreps.xml'), {}, '') - else: - # son:gohan user: forbidden error - expected_response = self.fixtures.load("privilege_errors.html") - return (httplib.FORBIDDEN, expected_response, {}, '') - - def _api_admin_enterprises_1_datacenterrepositories_2(self, method, url, body, headers): - return (httplib.OK, self.fixtures.load('ent_1_dcrep_2.xml'), {}, '') - - def _api_admin_enterprises_1_datacenterrepositories_2_virtualmachinetemplates(self, method, url, body, headers): - return (httplib.OK, self.fixtures.load('ent_1_dcrep_2_templates.xml'), - {}, '') - - def _api_admin_enterprises_1_datacenterrepositories_2_virtualmachinetemplates_11(self, method, url, body, headers): - return ( - httplib.OK, self.fixtures.load('ent_1_dcrep_2_template_11.xml'), - {}, '') - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_base.py b/awx/lib/site-packages/libcloud/test/compute/test_base.py deleted file mode 100644 index 84edf951a1..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_base.py +++ /dev/null @@ -1,114 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest - -from libcloud.common.base import Response -from libcloud.common.base import Connection, ConnectionKey, ConnectionUserAndKey -from libcloud.common.types import LibcloudError -from libcloud.compute.base import Node, NodeSize, NodeImage, NodeDriver -from libcloud.compute.base import NodeAuthSSHKey, NodeAuthPassword - -from libcloud.test import MockResponse # pylint: disable-msg=E0611 - - -class FakeDriver(object): - type = 0 - - -class BaseTests(unittest.TestCase): - - def test_base_node(self): - Node(id=0, name=0, state=0, public_ips=0, private_ips=0, - driver=FakeDriver()) - - def test_base_node_size(self): - NodeSize(id=0, name=0, ram=0, disk=0, bandwidth=0, price=0, - driver=FakeDriver()) - - def test_base_node_image(self): - NodeImage(id=0, name=0, driver=FakeDriver()) - - def test_base_response(self): - Response(MockResponse(status=200, body='foo'), ConnectionKey('foo')) - - def test_base_node_driver(self): - NodeDriver('foo') - - def test_base_connection_key(self): - ConnectionKey('foo') - - def test_base_connection_userkey(self): - ConnectionUserAndKey('foo', 'bar') - - def test_base_connection_timeout(self): - Connection(timeout=10) - - -class TestValidateAuth(unittest.TestCase): - - def test_get_auth_ssh(self): - n = NodeDriver('foo') - n.features = {'create_node': ['ssh_key']} - auth = NodeAuthSSHKey('pubkey...') - self.assertEqual(auth, n._get_and_check_auth(auth)) - - def test_get_auth_ssh_but_given_password(self): - n = NodeDriver('foo') - n.features = {'create_node': ['ssh_key']} - auth = NodeAuthPassword('password') - self.assertRaises(LibcloudError, n._get_and_check_auth, auth) - - def test_get_auth_password(self): - n = NodeDriver('foo') - n.features = {'create_node': ['password']} - auth = NodeAuthPassword('password') - self.assertEqual(auth, n._get_and_check_auth(auth)) - - def test_get_auth_password_but_given_ssh_key(self): - n = NodeDriver('foo') - n.features = {'create_node': ['password']} - auth = NodeAuthSSHKey('publickey') - self.assertRaises(LibcloudError, n._get_and_check_auth, auth) - - def test_get_auth_default_ssh_key(self): - n = NodeDriver('foo') - n.features = {'create_node': ['ssh_key']} - self.assertEqual(None, n._get_and_check_auth(None)) - - def test_get_auth_default_password(self): - n = NodeDriver('foo') - n.features = {'create_node': ['password']} - auth = n._get_and_check_auth(None) - self.assertTrue(isinstance(auth, NodeAuthPassword)) - - def test_get_auth_default_no_feature(self): - n = NodeDriver('foo') - self.assertEqual(None, n._get_and_check_auth(None)) - - def test_get_auth_generates_password_but_given_nonsense(self): - n = NodeDriver('foo') - n.features = {'create_node': ['generates_password']} - auth = "nonsense" - self.assertRaises(LibcloudError, n._get_and_check_auth, auth) - - def test_get_auth_no_features_but_given_nonsense(self): - n = NodeDriver('foo') - auth = "nonsense" - self.assertRaises(LibcloudError, n._get_and_check_auth, auth) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_bluebox.py b/awx/lib/site-packages/libcloud/test/compute/test_bluebox.py deleted file mode 100644 index bcee0a3161..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_bluebox.py +++ /dev/null @@ -1,117 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.bluebox import BlueboxNodeDriver as Bluebox -from libcloud.compute.base import Node, NodeAuthPassword -from libcloud.compute.types import NodeState - - -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import BLUEBOX_PARAMS - - -class BlueboxTest(unittest.TestCase): - - def setUp(self): - Bluebox.connectionCls.conn_classes = (None, BlueboxMockHttp) - self.driver = Bluebox(*BLUEBOX_PARAMS) - - def test_create_node(self): - node = self.driver.create_node( - name='foo', - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[0], - auth=NodeAuthPassword("test123") - ) - self.assertTrue(isinstance(node, Node)) - self.assertEqual(node.state, NodeState.PENDING) - self.assertEqual(node.name, 'foo.apitest.blueboxgrid.com') - - def test_list_nodes(self): - node = self.driver.list_nodes()[0] - self.assertEqual(node.name, 'foo.apitest.blueboxgrid.com') - self.assertEqual(node.state, NodeState.RUNNING) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 4) - - ids = [s.id for s in sizes] - - for size in sizes: - self.assertTrue(size.price > 0) - - self.assertTrue('94fd37a7-2606-47f7-84d5-9000deda52ae' in ids) - self.assertTrue('b412f354-5056-4bf0-a42f-6ddd998aa092' in ids) - self.assertTrue('0cd183d3-0287-4b1a-8288-b3ea8302ed58' in ids) - self.assertTrue('b9b87a5b-2885-4a2e-b434-44a163ca6251' in ids) - - def test_list_images(self): - images = self.driver.list_images() - image = images[0] - self.assertEqual(len(images), 10) - self.assertEqual(image.name, 'CentOS 5 (Latest Release)') - self.assertEqual(image.id, 'c66b8145-f768-45ef-9878-395bf8b1b7ff') - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - ret = self.driver.reboot_node(node) - self.assertTrue(ret) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - -class BlueboxMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('bluebox') - - def _api_blocks_json(self, method, url, body, headers): - if method == "POST": - body = self.fixtures.load('api_blocks_json_post.json') - else: - body = self.fixtures.load('api_blocks_json.json') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_block_products_json(self, method, url, body, headers): - body = self.fixtures.load('api_block_products_json.json') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_block_templates_json(self, method, url, body, headers): - body = self.fixtures.load('api_block_templates_json.json') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json(self, method, url, body, headers): - if method == 'DELETE': - body = self.fixtures.load( - 'api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json') - else: - body = self.fixtures.load( - 'api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json(self, method, url, body, headers): - body = self.fixtures.load( - 'api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_brightbox.py b/awx/lib/site-packages/libcloud/test/compute/test_brightbox.py deleted file mode 100644 index 651c34977a..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_brightbox.py +++ /dev/null @@ -1,350 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest -import base64 - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import b - -from libcloud.common.types import InvalidCredsError -from libcloud.compute.drivers.brightbox import BrightboxNodeDriver -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import BRIGHTBOX_PARAMS - -USER_DATA = '#!/bin/sh\ntest_script.sh\n' - - -class BrightboxTest(unittest.TestCase, TestCaseMixin): - - def setUp(self): - BrightboxNodeDriver.connectionCls.conn_classes = ( - None, BrightboxMockHttp) - BrightboxMockHttp.type = None - self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS) - - def test_authentication(self): - BrightboxMockHttp.type = 'INVALID_CLIENT' - self.assertRaises(InvalidCredsError, self.driver.list_nodes) - - BrightboxMockHttp.type = 'UNAUTHORIZED_CLIENT' - self.assertRaises(InvalidCredsError, self.driver.list_nodes) - - def test_invalid_api_version(self): - kwargs = {'api_version': '2.0'} - self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS, **kwargs) - self.assertRaises(Exception, self.driver.list_locations) - - def test_other_host(self): - kwargs = {'host': 'api.gbt.brightbox.com'} - self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS, **kwargs) - locations = self.driver.list_locations() - self.assertEqual(len(locations), 0) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 2) - self.assertEqual(len(nodes[0].public_ips), 1) - self.assertEqual(len(nodes[1].public_ips), 1) - self.assertEqual(len(nodes[0].private_ips), 1) - self.assertEqual(len(nodes[1].private_ips), 1) - self.assertTrue('109.107.35.16' in nodes[0].public_ips) - self.assertTrue('10.74.210.210' in nodes[0].private_ips) - self.assertTrue('10.240.228.234' in nodes[1].private_ips) - self.assertTrue( - '2a02:1348:14c:393a:24:19ff:fef0:e4ea' in nodes[1].public_ips) - self.assertEqual(nodes[0].state, NodeState.RUNNING) - self.assertEqual(nodes[1].state, NodeState.RUNNING) - - def test_list_node_extras(self): - nodes = self.driver.list_nodes() - self.assertFalse(nodes[0].size is None) - self.assertFalse(nodes[1].size is None) - self.assertFalse(nodes[0].image is None) - self.assertFalse(nodes[1].image is None) - self.assertEqual(nodes[0].image.id, 'img-arm8f') - self.assertEqual(nodes[0].size.id, 'typ-urtky') - self.assertEqual(nodes[1].image.id, 'img-j93gd') - self.assertEqual(nodes[1].size.id, 'typ-qdiwq') - self.assertEqual(nodes[0].extra['fqdn'], 'srv-xvpn7.gb1.brightbox.com') - self.assertEqual(nodes[1].extra['fqdn'], 'srv-742vn.gb1.brightbox.com') - self.assertEqual(nodes[0].extra['hostname'], 'srv-xvpn7') - self.assertEqual(nodes[1].extra['hostname'], 'srv-742vn') - self.assertEqual(nodes[0].extra['status'], 'active') - self.assertEqual(nodes[1].extra['status'], 'active') - self.assertTrue('interfaces' in nodes[0].extra) - self.assertTrue('zone' in nodes[0].extra) - self.assertTrue('snapshots' in nodes[0].extra) - self.assertTrue('server_groups' in nodes[0].extra) - self.assertTrue('started_at' in nodes[0].extra) - self.assertTrue('created_at' in nodes[0].extra) - self.assertFalse('deleted_at' in nodes[0].extra) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 7) - self.assertEqual(sizes[0].id, 'typ-4nssg') - self.assertEqual(sizes[0].name, 'Brightbox Nano Instance') - self.assertEqual(sizes[0].ram, 512) - self.assertEqual(sizes[0].disk, 20480) - self.assertEqual(sizes[0].bandwidth, 0) - self.assertEqual(sizes[0].price, 0) - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), 3) - self.assertEqual(images[0].id, 'img-99q79') - self.assertEqual(images[0].name, 'CentOS 5.5 server') - self.assertTrue('ancestor' in images[0].extra) - self.assertFalse('licence_name' in images[0].extra) - - def test_list_images_extras(self): - images = self.driver.list_images() - extra = images[-1].extra - self.assertEqual(extra['arch'], 'i686') - self.assertFalse(extra['compatibility_mode']) - self.assertEqual(extra['created_at'], '2012-01-22T05:36:24Z') - self.assertTrue('description' in extra) - self.assertEqual(extra['disk_size'], 671) - self.assertFalse('min_ram' in extra) - self.assertFalse(extra['official']) - self.assertEqual(extra['owner'], 'acc-tqs4c') - self.assertTrue(extra['public']) - self.assertEqual(extra['source'], 'oneiric-i386-20178.gz') - self.assertEqual(extra['source_type'], 'upload') - self.assertEqual(extra['status'], 'deprecated') - self.assertEqual(extra['username'], 'ubuntu') - self.assertEqual(extra['virtual_size'], 1025) - self.assertFalse('ancestor' in extra) - self.assertFalse('licence_name' in extra) - - def test_list_locations(self): - locations = self.driver.list_locations() - self.assertEqual(locations[0].id, 'zon-6mxqw') - self.assertEqual(locations[0].name, 'gb1-a') - self.assertEqual(locations[1].id, 'zon-remk1') - self.assertEqual(locations[1].name, 'gb1-b') - - def test_reboot_node_response(self): - node = self.driver.list_nodes()[0] - self.assertRaises(NotImplementedError, self.driver.reboot_node, [node]) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.destroy_node(node)) - - def test_create_node(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node( - name='Test Node', image=image, size=size) - self.assertEqual('srv-p61uj', node.id) - self.assertEqual('Test Node', node.name) - self.assertEqual('gb1-a', node.extra['zone'].name) - - def test_create_node_in_location(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - location = self.driver.list_locations()[1] - node = self.driver.create_node( - name='Test Node', image=image, size=size, location=location) - self.assertEqual('srv-nnumd', node.id) - self.assertEqual('Test Node', node.name) - self.assertEqual('gb1-b', node.extra['zone'].name) - - def test_create_node_with_user_data(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node( - name='Test Node', image=image, size=size, ex_userdata=USER_DATA) - decoded = base64.b64decode(b(node.extra['user_data'])).decode('ascii') - self.assertEqual('gb1-a', node.extra['zone'].name) - self.assertEqual(USER_DATA, decoded) - - def test_create_node_with_a_server_group(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node( - name='Test Node', image=image, size=size, ex_servergroup='grp-12345') - self.assertEqual('gb1-a', node.extra['zone'].name) - self.assertEqual(len(node.extra['server_groups']), 1) - self.assertEqual(node.extra['server_groups'][0]['id'], 'grp-12345') - - def test_create_node_with_a_list_of_server_groups(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node( - name='Test Node', image=image, size=size, ex_servergroup=['grp-12345', 'grp-67890']) - self.assertEqual('gb1-a', node.extra['zone'].name) - self.assertEqual(len(node.extra['server_groups']), 2) - self.assertEqual(node.extra['server_groups'][0]['id'], 'grp-12345') - self.assertEqual(node.extra['server_groups'][1]['id'], 'grp-67890') - - def test_list_cloud_ips(self): - cip_list = self.driver.ex_list_cloud_ips() - self.assertEqual(len(cip_list), 4) - self.assertEqual(cip_list[2]['status'], 'mapped') - cip_check = cip_list[0] - self.assertEqual(cip_check['id'], 'cip-tlrp3') - self.assertEqual(cip_check['public_ip'], '109.107.35.16') - self.assertEqual( - cip_check['reverse_dns'], 'cip-109-107-35-16.gb1.brightbox.com') - self.assertEqual(cip_check['status'], 'unmapped') - self.assertTrue(cip_check['server'] is None) - self.assertTrue(cip_check['server_group'] is None) - self.assertTrue(cip_check['interface'] is None) - self.assertTrue(cip_check['load_balancer'] is None) - - def test_create_cloud_ip(self): - cip = self.driver.ex_create_cloud_ip() - self.assertEqual(cip['id'], 'cip-jsjc5') - self.assertEqual( - cip['reverse_dns'], 'cip-109-107-37-234.gb1.brightbox.com') - - def test_create_cloud_ip_with_dns(self): - cip = self.driver.ex_create_cloud_ip('fred.co.uk') - self.assertEqual(cip['id'], 'cip-jsjc5') - self.assertEqual(cip['reverse_dns'], 'fred.co.uk') - - def test_map_cloud_ip(self): - self.assertTrue(self.driver.ex_map_cloud_ip('cip-jsjc5', 'int-ztqbx')) - - def test_unmap_cloud_ip(self): - self.assertTrue(self.driver.ex_unmap_cloud_ip('cip-jsjc5')) - - def test_update_cloud_ip(self): - self.assertTrue( - self.driver.ex_update_cloud_ip('cip-jsjc5', 'fred.co.uk')) - - def test_destroy_cloud_ip(self): - self.assertTrue(self.driver.ex_destroy_cloud_ip('cip-jsjc5')) - - -class BrightboxMockHttp(MockHttp): - fixtures = ComputeFileFixtures('brightbox') - - def _token(self, method, url, body, headers): - if method == 'POST': - return self.response(httplib.OK, self.fixtures.load('token.json')) - - def _token_INVALID_CLIENT(self, method, url, body, headers): - if method == 'POST': - return self.response(httplib.BAD_REQUEST, '{"error":"invalid_client"}') - - def _token_UNAUTHORIZED_CLIENT(self, method, url, body, headers): - if method == 'POST': - return self.response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}') - - def _1_0_images(self, method, url, body, headers): - if method == 'GET': - return self.response(httplib.OK, self.fixtures.load('list_images.json')) - - def _1_0_servers(self, method, url, body, headers): - if method == 'GET': - return self.response(httplib.OK, self.fixtures.load('list_servers.json')) - elif method == 'POST': - body = json.loads(body) - encoded = base64.b64encode(b(USER_DATA)).decode('ascii') - - if 'user_data' in body and body['user_data'] != encoded: - data = '{"error_name":"dodgy user data", "errors": ["User data not encoded properly"]}' - return self.response(httplib.BAD_REQUEST, data) - if body.get('zone', '') == 'zon-remk1': - node = json.loads( - self.fixtures.load('create_server_gb1_b.json')) - else: - node = json.loads( - self.fixtures.load('create_server_gb1_a.json')) - node['name'] = body['name'] - if 'server_groups' in body: - node['server_groups'] = [{'id': x} - for x in body['server_groups']] - if 'user_data' in body: - node['user_data'] = body['user_data'] - return self.response(httplib.ACCEPTED, json.dumps(node)) - - def _1_0_servers_srv_xvpn7(self, method, url, body, headers): - if method == 'DELETE': - return self.response(httplib.ACCEPTED, '') - - def _1_0_server_types(self, method, url, body, headers): - if method == 'GET': - return self.response(httplib.OK, self.fixtures.load('list_server_types.json')) - - def _1_0_zones(self, method, url, body, headers): - if method == 'GET': - if headers['Host'] == 'api.gbt.brightbox.com': - return self.response(httplib.OK, "{}") - else: - return self.response(httplib.OK, self.fixtures.load('list_zones.json')) - - def _2_0_zones(self, method, url, body, headers): - data = '{"error_name":"unrecognised_endpoint", "errors": ["The request was for an unrecognised API endpoint"]}' - return self.response(httplib.BAD_REQUEST, data) - - def _1_0_cloud_ips(self, method, url, body, headers): - if method == 'GET': - return self.response(httplib.OK, self.fixtures.load('list_cloud_ips.json')) - elif method == 'POST': - if body: - body = json.loads(body) - - node = json.loads(self.fixtures.load('create_cloud_ip.json')) - - if 'reverse_dns' in body: - node['reverse_dns'] = body['reverse_dns'] - return self.response(httplib.ACCEPTED, json.dumps(node)) - - def _1_0_cloud_ips_cip_jsjc5(self, method, url, body, headers): - if method == 'DELETE': - return self.response(httplib.OK, '') - elif method == 'PUT': - body = json.loads(body) - if body.get('reverse_dns', None) == 'fred.co.uk': - return self.response(httplib.OK, '') - else: - return self.response(httplib.BAD_REQUEST, '{"error_name":"bad dns", "errors": ["Bad dns"]}') - - def _1_0_cloud_ips_cip_jsjc5_map(self, method, url, body, headers): - if method == 'POST': - body = json.loads(body) - if 'destination' in body: - return self.response(httplib.ACCEPTED, '') - else: - data = '{"error_name":"bad destination", "errors": ["Bad destination"]}' - return self.response(httplib.BAD_REQUEST, data) - - def _1_0_cloud_ips_cip_jsjc5_unmap(self, method, url, body, headers): - if method == 'POST': - return self.response(httplib.ACCEPTED, '') - - def response(self, status, body): - return (status, body, {'content-type': 'application/json'}, httplib.responses[status]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) - -# vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 -# filetype=python diff --git a/awx/lib/site-packages/libcloud/test/compute/test_cloudframes.py b/awx/lib/site-packages/libcloud/test/compute/test_cloudframes.py deleted file mode 100644 index 1698198440..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_cloudframes.py +++ /dev/null @@ -1,292 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import uuid -import base64 -import unittest -import datetime - -from libcloud.compute.base import Node, NodeImage, NodeLocation -from libcloud.compute.types import NodeState -from libcloud.compute.drivers.cloudframes import CloudFramesNodeDriver -from libcloud.compute.drivers.cloudframes import CloudFramesSnapshot - -from libcloud.utils.py3 import httplib, xmlrpclib, b -from libcloud.test import MockHttpTestCase -from libcloud.test.compute import TestCaseMixin -from libcloud.test.secrets import CLOUDFRAMES_PARAMS -from libcloud.test.file_fixtures import ComputeFileFixtures - - -# how many seconds to give the vm to boot and have VMWare tools start up -START_TIMEOUT = 300 - - -class CloudFramesMockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('cloudframes') - - content_headers = { - 'Server': 'TwistedWeb/9.0.0', - 'Date': datetime.datetime.now().ctime(), - 'Content-Type': 'text/xml', - } - - def __getattr__(self, key): - if key == '_appserver_xmlrpc_http:__host:8888_appserver_xmlrpc': - return self._xmlrpc - raise AttributeError(key) - - def _xmlrpc(self, method, url, body, headers): - params, methodname = xmlrpclib.loads(body) - meth_name = methodname.replace('.', '_').replace('cloud_api_', '') - return getattr(self, meth_name)(method, url, params, headers) - - def _authenticate(self, headers): - self.assertTrue('Authorization' in headers.keys()) - self.assertTrue(headers['Authorization'].startswith('Basic ')) - auth = base64.b64decode( - b(headers['Authorization'].split(' ', 1)[1])).decode('ascii') - username, password = auth.split(':', 1) - self.assertEqual(username, CLOUDFRAMES_PARAMS[0]) - self.assertEqual(password, CLOUDFRAMES_PARAMS[1]) - - def cloudspace_find(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_cloudspace_find.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_find(self, method, url, params, headers): - self._authenticate(headers) - if params[18]: - body = self.fixtures.load('_machine_find_templates.xml') - elif params[17] == 'PHYSICAL': - body = self.fixtures.load('_machine_find_physical.xml') - elif params[17] == 'VIRTUALSERVER': - body = self.fixtures.load('_machine_find_virtualserver.xml') - elif params[17] == 'VIRTUALDESKTOP': - body = self.fixtures.load('_machine_find_virtualdesktop.xml') - else: - raise Exception( - 'unknown machine.find query with params: %s' % params) - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_list(self, method, url, params, headers): - self._authenticate(headers) - body = None - if params[3]: - body = self.fixtures.load( - '_machine_list_machineguid_%s.xml' % params[3]) - if body: - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - else: - return (httplib.INTERNAL_SERVER_ERROR, '', - self.content_headers, 'Could not parse request') - - def machine_delete(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_delete.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_stop(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_stop.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_reboot(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_reboot.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_createFromTemplate(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_createFromTemplate.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_start(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_start.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_snapshot(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_snapshot.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_listSnapshots(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_listSnapshots.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def machine_rollback(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_machine_rollback.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - def lan_find(self, method, url, params, headers): - self._authenticate(headers) - body = self.fixtures.load('_lan_find.xml') - return (httplib.OK, body, self.content_headers, - httplib.responses[httplib.OK]) - - -class CloudFramesTests(unittest.TestCase, TestCaseMixin): - - should_list_locations = True - should_have_pricing = False - should_list_volumes = False - - def __init__(self, name, url=None): - self.url = url - super(CloudFramesTests, self).__init__(name) - - def setUp(self): - if self.url: - args = () - kwargs = {'url': self.url} - else: - CloudFramesNodeDriver.connectionCls.conn_classes = ( - CloudFramesMockHttp, CloudFramesMockHttp) - args = CLOUDFRAMES_PARAMS - kwargs = {} - self.driver = CloudFramesNodeDriver(*args, **kwargs) - - def _retry_until_up(self, cmd, *args, **kwargs): - """ - When testing against a live system, this will cause the given command - to be retried until it succeeds. - (Calls like snapshot/reboot will fail until the vm has started fully.) - """ - now = datetime.datetime.now() - while not (datetime.datetime.now() - now).seconds > START_TIMEOUT: - try: - return cmd(*args, **kwargs) - except: - pass - else: - raise Exception('VMWare tools did not become available in time') - - def test_connection(self): - key, secret, secure, host, port = CLOUDFRAMES_PARAMS - CloudFramesNodeDriver(key, secret, secure, host) - CloudFramesNodeDriver(key, secret, secure, host, 80) - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - key, secret, True, host, 80) - CloudFramesNodeDriver(key, secret, secure, host, '80') - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - key, secure=secure, host=host) - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - secret=secret, secure=secure, host=host) - CloudFramesNodeDriver( - url='http://%s:%s@%s:80/appserver/xmlrpc' % (key, secret, host)) - CloudFramesNodeDriver( - url='http://%s:%s@%s/appserver/xmlrpc' % (key, secret, host)) - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - key=key, secret=secret, - url='https://%s/appserver/xmlrpc' % host) - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - key=key, secret=secret, secure=False, - url='https://%s/appserver/xmlrpc' % host) - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - url='http://%s@%s/appserver/xmlrpc' % (key, host)) - CloudFramesNodeDriver( - secret=secret, url='http://%s@%s/appserver/xmlrpc' % (key, host)) - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - url='http://%s/appserver/xmlrpc' % host) - self.assertRaises( - NotImplementedError, CloudFramesNodeDriver, - secret=secret, url='http://%s/appserver/xmlrpc' % host) - self.assertRaises(NotImplementedError, CloudFramesNodeDriver, - key=key, url='http://%s/appserver/xmlrpc' % host) - CloudFramesNodeDriver( - key=key, secret=secret, url='http://%s/appserver/xmlrpc' % host) - - def test_snapshot(self): - nodes = [node for node in self.driver.list_nodes() - if node.state == NodeState.RUNNING] - if not nodes: - raise Exception('No running vm to test snapshotting') - self._test_snapshot(nodes[0]) - - def _test_snapshot(self, node): - if self.url: - self.assertEqual(len(self.driver.ex_list_snapshots(node)), 0) - snapshot1 = self._retry_until_up( - self.driver.ex_snapshot_node, node) - self.assertTrue(isinstance(snapshot1, CloudFramesSnapshot)) - if self.url: - self.assertEqual(len(self.driver.ex_list_snapshots(node)), 1) - snapshot2 = self.driver.ex_snapshot_node(node) - self.assertTrue(isinstance(snapshot2, CloudFramesSnapshot)) - if self.url: - self.assertEqual(len(self.driver.ex_list_snapshots(node)), 2) - self.driver.ex_destroy_snapshot(node, snapshot2) - if self.url: - self.assertEqual(len(self.driver.ex_list_snapshots(node)), 1) - self.driver.ex_rollback_node(node, snapshot1) - if self.url: - self.assertEqual(len(self.driver.ex_list_snapshots(node)), 1) - self.driver.ex_destroy_snapshot(node, snapshot1) - - def test_comprehensive(self): - """ - Creates a node with the first location, image and size it finds. - - Then boots the node, reboots, creates two snapshots. - Deletes one snapshot, rolls back to the other, then destroys the node. - - In between these operations it verifies the node status and lists. - """ - if not self.url: - return - location = self.driver.list_locations()[0] - self.assertTrue(isinstance(location, NodeLocation)) - image = self.driver.list_images()[0] - self.assertTrue(isinstance(image, NodeImage)) - size = self.driver.list_sizes()[0] - name = 'AUTOTEST_%s' % uuid.uuid4() - node = self.driver.create_node( - image=image, name=name, size=size, location=location) - # give the node time to boot up and load the vmware tools - self.assertTrue(isinstance(node, Node)) - self.assertTrue(node.id in [x.id for x in self.driver.list_nodes()]) - self.assertTrue(node.state == NodeState.RUNNING) - self._test_snapshot(node) - self._retry_until_up(self.driver.reboot_node, node) - self.driver.destroy_node(node) - self.assertFalse(node.id in [x.id for x in self.driver.list_nodes()]) - - -if __name__ == '__main__': - # add a full url as first arg to this script to test against a live system - # fi: http://key:secret@host:port/appserver/xmlrpc - if len(sys.argv) > 1: - suite = unittest.TestSuite() - suite.addTest(CloudFramesTests('test_comprehensive', sys.argv[1])) - if not unittest.TextTestRunner().run(suite).wasSuccessful(): - sys.exit(1) - del sys.argv[1] - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_cloudsigma_v1_0.py b/awx/lib/site-packages/libcloud/test/compute/test_cloudsigma_v1_0.py deleted file mode 100644 index d8fb310a7f..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_cloudsigma_v1_0.py +++ /dev/null @@ -1,223 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.base import Node -from libcloud.compute.drivers.cloudsigma import CloudSigmaNodeDriver -from libcloud.compute.drivers.cloudsigma import CloudSigmaZrhNodeDriver -from libcloud.utils.misc import str2dicts, str2list, dict2str - -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class CloudSigmaAPI10BaseTestCase(object): - should_list_locations = False - - driver_klass = CloudSigmaZrhNodeDriver - driver_kwargs = {} - - def setUp(self): - self.driver = self.driver_klass(*self.driver_args, - **self.driver_kwargs) - - self.driver.connectionCls.conn_classes = (None, - CloudSigmaHttp) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertTrue(isinstance(nodes, list)) - self.assertEqual(len(nodes), 1) - - node = nodes[0] - self.assertEqual(node.public_ips[0], "1.2.3.4") - self.assertEqual(node.extra['smp'], 1) - self.assertEqual(node.extra['cpu'], 1100) - self.assertEqual(node.extra['mem'], 640) - - def test_list_sizes(self): - images = self.driver.list_sizes() - self.assertEqual(len(images), 9) - - def test_list_images(self): - sizes = self.driver.list_images() - self.assertEqual(len(sizes), 10) - - def test_start_node(self): - nodes = self.driver.list_nodes() - node = nodes[0] - self.assertTrue(self.driver.ex_start_node(node)) - - def test_shutdown_node(self): - nodes = self.driver.list_nodes() - node = nodes[0] - self.assertTrue(self.driver.ex_stop_node(node)) - self.assertTrue(self.driver.ex_shutdown_node(node)) - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.reboot_node(node)) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.destroy_node(node)) - self.driver.list_nodes() - - def test_create_node(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node( - name="cloudsigma node", image=image, size=size) - self.assertTrue(isinstance(node, Node)) - - def test_ex_static_ip_list(self): - ips = self.driver.ex_static_ip_list() - self.assertEqual(len(ips), 3) - - def test_ex_static_ip_create(self): - result = self.driver.ex_static_ip_create() - self.assertEqual(len(result), 2) - self.assertEqual(len(list(result[0].keys())), 6) - self.assertEqual(len(list(result[1].keys())), 6) - - def test_ex_static_ip_destroy(self): - result = self.driver.ex_static_ip_destroy('1.2.3.4') - self.assertTrue(result) - - def test_ex_drives_list(self): - result = self.driver.ex_drives_list() - self.assertEqual(len(result), 2) - - def test_ex_drive_destroy(self): - result = self.driver.ex_drive_destroy( - # @@TR: this should be soft-coded: - 'd18119ce_7afa_474a_9242_e0384b160220') - self.assertTrue(result) - - def test_ex_set_node_configuration(self): - node = self.driver.list_nodes()[0] - result = self.driver.ex_set_node_configuration(node, **{'smp': 2}) - self.assertTrue(result) - - def test_str2dicts(self): - string = 'mem 1024\ncpu 2200\n\nmem2048\cpu 1100' - result = str2dicts(string) - self.assertEqual(len(result), 2) - - def test_str2list(self): - string = 'ip 1.2.3.4\nip 1.2.3.5\nip 1.2.3.6' - result = str2list(string) - self.assertEqual(len(result), 3) - self.assertEqual(result[0], '1.2.3.4') - self.assertEqual(result[1], '1.2.3.5') - self.assertEqual(result[2], '1.2.3.6') - - def test_dict2str(self): - d = {'smp': 5, 'cpu': 2200, 'mem': 1024} - result = dict2str(d) - self.assertTrue(len(result) > 0) - self.assertTrue(result.find('smp 5') >= 0) - self.assertTrue(result.find('cpu 2200') >= 0) - self.assertTrue(result.find('mem 1024') >= 0) - - -class CloudSigmaAPI10DirectTestCase(CloudSigmaAPI10BaseTestCase, - unittest.TestCase): - driver_klass = CloudSigmaZrhNodeDriver - driver_args = ('foo', 'bar') - driver_kwargs = {} - - -class CloudSigmaAPI10IndiretTestCase(CloudSigmaAPI10BaseTestCase, - unittest.TestCase): - driver_klass = CloudSigmaNodeDriver - driver_args = ('foo', 'bar') - driver_kwargs = {'api_version': '1.0'} - - -class CloudSigmaHttp(MockHttp): - fixtures = ComputeFileFixtures('cloudsigma') - - def _drives_standard_info(self, method, url, body, headers): - body = self.fixtures.load('drives_standard_info.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_start( - self, method, url, body, headers): - - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_stop( - self, method, url, body, headers): - - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK]) - - def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_destroy( - self, method, url, body, headers): - - return (httplib.NO_CONTENT, - body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _drives_d18119ce_7afa_474a_9242_e0384b160220_clone( - self, method, url, body, headers): - - body = self.fixtures.load('drives_clone.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _drives_a814def5_1789_49a0_bf88_7abe7bb1682a_info( - self, method, url, body, headers): - - body = self.fixtures.load('drives_single_info.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _drives_info(self, method, url, body, headers): - body = self.fixtures.load('drives_info.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _servers_create(self, method, url, body, headers): - body = self.fixtures.load('servers_create.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _servers_info(self, method, url, body, headers): - body = self.fixtures.load('servers_info.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _resources_ip_list(self, method, url, body, headers): - body = self.fixtures.load('resources_ip_list.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _resources_ip_create(self, method, url, body, headers): - body = self.fixtures.load('resources_ip_create.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _resources_ip_1_2_3_4_destroy(self, method, url, body, headers): - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK]) - - def _drives_d18119ce_7afa_474a_9242_e0384b160220_destroy( - self, method, url, body, headers): - - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK]) - - def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_set( - self, method, url, body, headers): - - body = self.fixtures.load('servers_set.txt') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_cloudsigma_v2_0.py b/awx/lib/site-packages/libcloud/test/compute/test_cloudsigma_v2_0.py deleted file mode 100644 index 4bc66a5b90..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_cloudsigma_v2_0.py +++ /dev/null @@ -1,646 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - -try: - import simplejson as json -except: - import json - -from libcloud.utils.py3 import httplib - -from libcloud.common.types import InvalidCredsError -from libcloud.compute.drivers.cloudsigma import CloudSigmaNodeDriver -from libcloud.compute.drivers.cloudsigma import CloudSigma_2_0_NodeDriver -from libcloud.compute.drivers.cloudsigma import CloudSigmaError -from libcloud.compute.types import NodeState - -from libcloud.test import unittest -from libcloud.test import MockHttpTestCase -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class CloudSigmaAPI20BaseTestCase(object): - def setUp(self): - self.driver_klass.connectionCls.conn_classes = \ - (CloudSigmaMockHttp, CloudSigmaMockHttp) - - CloudSigmaMockHttp.type = None - CloudSigmaMockHttp.use_param = 'do' - - self.driver = self.driver_klass(*self.driver_args, - **self.driver_kwargs) - self.driver.DRIVE_TRANSITION_SLEEP_INTERVAL = 0.1 - self.driver.DRIVE_TRANSITION_TIMEOUT = 1 - self.node = self.driver.list_nodes()[0] - - def test_invalid_api_versions(self): - expected_msg = 'Unsupported API version: invalid' - self.assertRaisesRegexp(NotImplementedError, expected_msg, - CloudSigmaNodeDriver, 'username', 'password', - api_version='invalid') - - def test_invalid_credentials(self): - CloudSigmaMockHttp.type = 'INVALID_CREDS' - self.assertRaises(InvalidCredsError, self.driver.list_nodes) - - def test_invalid_region(self): - expected_msg = 'Invalid region:' - self.assertRaisesRegexp(ValueError, expected_msg, - CloudSigma_2_0_NodeDriver, 'foo', 'bar', - region='invalid') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - - size = sizes[0] - self.assertEqual(size.id, 'micro-regular') - - def test_list_images(self): - images = self.driver.list_images() - - image = images[0] - self.assertEqual(image.name, 'ubuntu-10.04-toMP') - self.assertEqual(image.extra['image_type'], 'preinst') - self.assertEqual(image.extra['media'], 'disk') - self.assertEqual(image.extra['os'], 'linux') - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - - node = nodes[0] - self.assertEqual(len(nodes), 2) - self.assertEqual(node.id, '9de75ed6-fd33-45e2-963f-d405f31fd911') - self.assertEqual(node.name, 'test no drives') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.public_ips, ['185.12.5.181', '178.22.68.55']) - self.assertEqual(node.private_ips, []) - - def test_create_node(self): - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - metadata = {'foo': 'bar'} - - node = self.driver.create_node(name='test node', size=size, image=image, - ex_metadata=metadata) - self.assertEqual(node.name, 'test node') - self.assertEqual(len(node.extra['nics']), 1) - self.assertEqual(node.extra['nics'][0]['ip_v4_conf']['conf'], 'dhcp') - - def test_create_node_with_vlan(self): - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - - vlan_uuid = '39ae851d-433f-4ac2-a803-ffa24cb1fa3e' - - node = self.driver.create_node(name='test node vlan', size=size, - image=image, ex_vlan=vlan_uuid) - self.assertEqual(node.name, 'test node vlan') - self.assertEqual(len(node.extra['nics']), 2) - self.assertEqual(node.extra['nics'][0]['ip_v4_conf']['conf'], 'dhcp') - self.assertEqual(node.extra['nics'][1]['vlan']['uuid'], vlan_uuid) - - def test_destroy_node(self): - status = self.driver.destroy_node(node=self.node) - self.assertTrue(status) - - def test_ex_start_node(self): - status = self.driver.ex_start_node(node=self.node) - self.assertTrue(status) - - def test_ex_start_node_avoid_mode(self): - CloudSigmaMockHttp.type = 'AVOID_MODE' - ex_avoid = ['1', '2'] - status = self.driver.ex_start_node(node=self.node, - ex_avoid=ex_avoid) - self.assertTrue(status) - - def test_ex_start_node_already_started(self): - CloudSigmaMockHttp.type = 'ALREADY_STARTED' - - expected_msg = 'Cannot start guest in state "started". Guest should ' \ - 'be in state "stopped' - - self.assertRaisesRegexp(CloudSigmaError, expected_msg, - self.driver.ex_start_node, node=self.node) - - def test_ex_stop_node(self): - status = self.driver.ex_stop_node(node=self.node) - self.assertTrue(status) - - def test_ex_stop_node_already_stopped(self): - CloudSigmaMockHttp.type = 'ALREADY_STOPPED' - - expected_msg = 'Cannot stop guest in state "stopped"' - self.assertRaisesRegexp(CloudSigmaError, expected_msg, - self.driver.ex_stop_node, node=self.node) - - def test_ex_clone_node(self): - node_to_clone = self.driver.list_nodes()[0] - - cloned_node = self.driver.ex_clone_node(node=node_to_clone, - name='test cloned node') - self.assertEqual(cloned_node.name, 'test cloned node') - - def test_ex_open_vnc_tunnel(self): - node = self.driver.list_nodes()[0] - vnc_url = self.driver.ex_open_vnc_tunnel(node=node) - self.assertEqual(vnc_url, 'vnc://direct.lvs.cloudsigma.com:41111') - - def test_ex_close_vnc_tunnel(self): - node = self.driver.list_nodes()[0] - status = self.driver.ex_close_vnc_tunnel(node=node) - self.assertTrue(status) - - def test_ex_list_library_drives(self): - drives = self.driver.ex_list_library_drives() - - drive = drives[0] - self.assertEqual(drive.name, 'IPCop 2.0.2') - self.assertEqual(drive.size, 1000000000) - self.assertEqual(drive.media, 'cdrom') - self.assertEqual(drive.status, 'unmounted') - - def test_ex_list_user_drives(self): - drives = self.driver.ex_list_user_drives() - - drive = drives[0] - self.assertEqual(drive.name, 'test node 2-drive') - self.assertEqual(drive.size, 13958643712) - self.assertEqual(drive.media, 'disk') - self.assertEqual(drive.status, 'unmounted') - - def test_ex_create_drive(self): - CloudSigmaMockHttp.type = 'CREATE' - - name = 'test drive 5' - size = 2000 * 1024 * 1024 - - drive = self.driver.ex_create_drive(name=name, size=size, media='disk') - self.assertEqual(drive.name, 'test drive 5') - self.assertEqual(drive.media, 'disk') - - def test_ex_clone_drive(self): - drive = self.driver.ex_list_user_drives()[0] - cloned_drive = self.driver.ex_clone_drive(drive=drive, - name='cloned drive') - - self.assertEqual(cloned_drive.name, 'cloned drive') - - def test_ex_resize_drive(self): - drive = self.driver.ex_list_user_drives()[0] - - size = 1111 * 1024 * 1024 - - resized_drive = self.driver.ex_resize_drive(drive=drive, size=size) - self.assertEqual(resized_drive.name, 'test drive 5') - self.assertEqual(resized_drive.media, 'disk') - self.assertEqual(resized_drive.size, size) - - def test_ex_list_firewall_policies(self): - policies = self.driver.ex_list_firewall_policies() - - policy = policies[1] - rule = policy.rules[0] - self.assertEqual(policy.name, 'My awesome policy') - self.assertEqual(rule.action, 'drop') - self.assertEqual(rule.direction, 'out') - self.assertEqual(rule.dst_ip, '23.0.0.0/32') - self.assertEqual(rule.ip_proto, 'tcp') - self.assertEqual(rule.dst_port, None) - self.assertEqual(rule.src_ip, None) - self.assertEqual(rule.src_port, None) - self.assertEqual(rule.comment, 'Drop traffic from the VM to IP address 23.0.0.0/32') - - def test_ex_create_firewall_policy_no_rules(self): - CloudSigmaMockHttp.type = 'CREATE_NO_RULES' - policy = self.driver.ex_create_firewall_policy(name='test policy 1') - - self.assertEqual(policy.name, 'test policy 1') - self.assertEqual(policy.rules, []) - - def test_ex_create_firewall_policy_with_rules(self): - CloudSigmaMockHttp.type = 'CREATE_WITH_RULES' - rules = [ - { - 'action': 'accept', - 'direction': 'out', - 'ip_proto': 'tcp', - 'src_ip': '127.0.0.1', - 'dst_ip': '127.0.0.1' - } - ] - - policy = self.driver.ex_create_firewall_policy(name='test policy 2', - rules=rules) - rule = policy.rules[0] - - self.assertEqual(policy.name, 'test policy 2') - self.assertEqual(len(policy.rules), 1) - - self.assertEqual(rule.action, 'accept') - self.assertEqual(rule.direction, 'out') - self.assertEqual(rule.ip_proto, 'tcp') - - def test_ex_attach_firewall_policy(self): - policy = self.driver.ex_list_firewall_policies()[0] - node = self.driver.list_nodes()[0] - - CloudSigmaMockHttp.type = 'ATTACH_POLICY' - updated_node = self.driver.ex_attach_firewall_policy(policy=policy, - node=node) - nic = updated_node.extra['nics'][0] - self.assertEqual(nic['firewall_policy']['uuid'], - '461dfb8c-e641-43d7-a20e-32e2aa399086') - - def test_ex_attach_firewall_policy_inexistent_nic(self): - policy = self.driver.ex_list_firewall_policies()[0] - node = self.driver.list_nodes()[0] - - nic_mac = 'inexistent' - expected_msg = 'Cannot find the NIC interface to attach a policy to' - self.assertRaisesRegexp(ValueError, expected_msg, - self.driver.ex_attach_firewall_policy, - policy=policy, - node=node, - nic_mac=nic_mac) - - def test_ex_delete_firewall_policy(self): - policy = self.driver.ex_list_firewall_policies()[0] - status = self.driver.ex_delete_firewall_policy(policy=policy) - self.assertTrue(status) - - def test_ex_list_tags(self): - tags = self.driver.ex_list_tags() - - tag = tags[0] - self.assertEqual(tag.id, 'a010ec41-2ead-4630-a1d0-237fa77e4d4d') - self.assertEqual(tag.name, 'test tag 2') - - def test_ex_get_tag(self): - tag = self.driver.ex_get_tag(tag_id='a010ec41-2ead-4630-a1d0-237fa77e4d4d') - - self.assertEqual(tag.id, 'a010ec41-2ead-4630-a1d0-237fa77e4d4d') - self.assertEqual(tag.name, 'test tag 2') - - def test_ex_create_tag(self): - tag = self.driver.ex_create_tag(name='test tag 3') - self.assertEqual(tag.name, 'test tag 3') - - def test_ex_create_tag_with_resources(self): - CloudSigmaMockHttp.type = 'WITH_RESOURCES' - resource_uuids = ['1'] - tag = self.driver.ex_create_tag(name='test tag 3', - resource_uuids=resource_uuids) - self.assertEqual(tag.name, 'test tag 3') - self.assertEqual(tag.resources, resource_uuids) - - def test_ex_tag_resource(self): - node = self.driver.list_nodes()[0] - tag = self.driver.ex_list_tags()[0] - - updated_tag = self.driver.ex_tag_resource(resource=node, tag=tag) - self.assertEqual(updated_tag.name, 'test tag 3') - - def test_ex_tag_resources(self): - nodes = self.driver.list_nodes() - tag = self.driver.ex_list_tags()[0] - - updated_tag = self.driver.ex_tag_resources(resources=nodes, tag=tag) - self.assertEqual(updated_tag.name, 'test tag 3') - - def test_ex_tag_resource_invalid_resource_object(self): - tag = self.driver.ex_list_tags()[0] - - expected_msg = 'Resource doesn\'t have id attribute' - self.assertRaisesRegexp(ValueError, expected_msg, - self.driver.ex_tag_resource, tag=tag, - resource={}) - - def test_ex_delete_tag(self): - tag = self.driver.ex_list_tags()[0] - status = self.driver.ex_delete_tag(tag=tag) - self.assertTrue(status) - - def test_ex_get_balance(self): - balance = self.driver.ex_get_balance() - self.assertEqual(balance['balance'], '10.00') - self.assertEqual(balance['currency'], 'USD') - - def test_ex_get_pricing(self): - pricing = self.driver.ex_get_pricing() - - self.assertTrue('current' in pricing) - self.assertTrue('next' in pricing) - self.assertTrue('objects' in pricing) - - def test_ex_get_usage(self): - pricing = self.driver.ex_get_usage() - - self.assertTrue('balance' in pricing) - self.assertTrue('usage' in pricing) - - def test_ex_list_subscriptions(self): - subscriptions = self.driver.ex_list_subscriptions() - - subscription = subscriptions[0] - self.assertEqual(len(subscriptions), 5) - self.assertEqual(subscription.id, '7272') - self.assertEqual(subscription.resource, 'vlan') - self.assertEqual(subscription.amount, 1) - self.assertEqual(subscription.period, '345 days, 0:00:00') - self.assertEqual(subscription.status, 'active') - self.assertEqual(subscription.price, '0E-20') - - def test_ex_create_subscription(self): - CloudSigmaMockHttp.type = 'CREATE_SUBSCRIPTION' - subscription = self.driver.ex_create_subscription(amount=1, - period='1 month', - resource='vlan') - self.assertEqual(subscription.amount, 1) - self.assertEqual(subscription.period, '1 month') - self.assertEqual(subscription.resource, 'vlan') - self.assertEqual(subscription.price, '10.26666666666666666666666667') - self.assertEqual(subscription.auto_renew, False) - self.assertEqual(subscription.subscribed_object, '2494079f-8376-40bf-9b37-34d633b8a7b7') - - def test_ex_list_subscriptions_status_filterting(self): - CloudSigmaMockHttp.type = 'STATUS_FILTER' - self.driver.ex_list_subscriptions(status='active') - - def test_ex_list_subscriptions_resource_filterting(self): - CloudSigmaMockHttp.type = 'RESOURCE_FILTER' - resources = ['cpu', 'mem'] - self.driver.ex_list_subscriptions(resources=resources) - - def test_ex_toggle_subscription_auto_renew(self): - subscription = self.driver.ex_list_subscriptions()[0] - status = self.driver.ex_toggle_subscription_auto_renew( - subscription=subscription) - self.assertTrue(status) - - def test_ex_list_capabilities(self): - capabilities = self.driver.ex_list_capabilities() - self.assertEqual(capabilities['servers']['cpu']['min'], 250) - - def test_ex_list_servers_availability_groups(self): - groups = self.driver.ex_list_servers_availability_groups() - self.assertEqual(len(groups), 3) - self.assertEqual(len(groups[0]), 2) - self.assertEqual(len(groups[2]), 1) - - def test_ex_list_drives_availability_groups(self): - groups = self.driver.ex_list_drives_availability_groups() - self.assertEqual(len(groups), 1) - self.assertEqual(len(groups[0]), 11) - - def test_wait_for_drive_state_transition_timeout(self): - drive = self.driver.ex_list_user_drives()[0] - state = 'timeout' - - expected_msg = 'Timed out while waiting for drive transition' - self.assertRaisesRegexp(Exception, expected_msg, - self.driver._wait_for_drive_state_transition, - drive=drive, state=state, - timeout=0.5) - - def test_wait_for_drive_state_transition_success(self): - drive = self.driver.ex_list_user_drives()[0] - state = 'unmounted' - - drive = self.driver._wait_for_drive_state_transition(drive=drive, - state=state, - timeout=0.5) - self.assertEqual(drive.status, state) - - -class CloudSigmaAPI20DirectTestCase(CloudSigmaAPI20BaseTestCase, - unittest.TestCase): - driver_klass = CloudSigma_2_0_NodeDriver - driver_args = ('foo', 'bar') - driver_kwargs = {} - - -class CloudSigmaAPI20IndirectTestCase(CloudSigmaAPI20BaseTestCase, - unittest.TestCase): - driver_klass = CloudSigmaNodeDriver - driver_args = ('foo', 'bar') - driver_kwargs = {'api_version': '2.0'} - - -class CloudSigmaMockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('cloudsigma_2_0') - - def _api_2_0_servers_detail_INVALID_CREDS(self, method, url, body, headers): - body = self.fixtures.load('libdrives.json') - return (httplib.UNAUTHORIZED, body, {}, - httplib.responses[httplib.UNAUTHORIZED]) - - def _api_2_0_libdrives(self, method, url, body, headers): - body = self.fixtures.load('libdrives.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_servers_detail(self, method, url, body, headers): - body = self.fixtures.load('servers_detail_mixed_state.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911(self, method, url, body, headers): - body = '' - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _api_2_0_servers(self, method, url, body, headers): - if method == 'POST': - # create_node - - parsed = json.loads(body) - - if 'vlan' in parsed['name']: - self.assertEqual(len(parsed['nics']), 2) - body = self.fixtures.load('servers_create_with_vlan.json') - else: - body = self.fixtures.load('servers_create.json') - - return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_start(self, method, url, body, headers): - body = self.fixtures.load('start_success.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_AVOID_MODE_start(self, method, url, body, headers): - self.assertUrlContainsQueryParams(url, {'avoid': '1,2'}) - - body = self.fixtures.load('start_success.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_ALREADY_STARTED_start(self, method, url, body, headers): - body = self.fixtures.load('start_already_started.json') - return (httplib.FORBIDDEN, body, {}, httplib.responses[httplib.FORBIDDEN]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_stop(self, method, url, body, headers): - body = self.fixtures.load('stop_success.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_ALREADY_STOPPED_stop(self, method, url, body, headers): - body = self.fixtures.load('stop_already_stopped.json') - return (httplib.FORBIDDEN, body, {}, httplib.responses[httplib.FORBIDDEN]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_clone(self, method, url, body, headers): - body = self.fixtures.load('servers_clone.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_open_vnc(self, method, url, body, headers): - body = self.fixtures.load('servers_open_vnc.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_close_vnc(self, method, url, body, headers): - body = self.fixtures.load('servers_close_vnc.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_drives_detail(self, method, url, body, headers): - body = self.fixtures.load('drives_detail.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_drives_b02311e2_a83c_4c12_af10_b30d51c86913(self, method, url, body, headers): - body = self.fixtures.load('drives_get.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809(self, method, url, body, headers): - body = self.fixtures.load('drives_get.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_drives_CREATE(self, method, url, body, headers): - body = self.fixtures.load('drives_create.json') - return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) - - def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809_action_clone(self, method, url, body, headers): - body = self.fixtures.load('drives_clone.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_drives_5236b9ee_f735_42fd_a236_17558f9e12d3_action_clone(self, method, url, body, headers): - body = self.fixtures.load('drives_clone.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_drives_b02311e2_a83c_4c12_af10_b30d51c86913_action_resize(self, method, url, body, headers): - body = self.fixtures.load('drives_resize.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809_action_resize(self, method, url, body, headers): - body = self.fixtures.load('drives_resize.json') - return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) - - def _api_2_0_fwpolicies_detail(self, method, url, body, headers): - body = self.fixtures.load('fwpolicies_detail.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_fwpolicies_CREATE_NO_RULES(self, method, url, body, headers): - body = self.fixtures.load('fwpolicies_create_no_rules.json') - return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) - - def _api_2_0_fwpolicies_CREATE_WITH_RULES(self, method, url, body, headers): - body = self.fixtures.load('fwpolicies_create_with_rules.json') - return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) - - def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_ATTACH_POLICY(self, method, url, body, headers): - body = self.fixtures.load('servers_attach_policy.json') - return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) - - def _api_2_0_fwpolicies_0e339282_0cb5_41ac_a9db_727fb62ff2dc(self, method, url, body, headers): - if method == 'DELETE': - body = '' - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _api_2_0_tags_detail(self, method, url, body, headers): - body = self.fixtures.load('tags_detail.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_tags(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('tags_create.json') - return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) - - def _api_2_0_tags_WITH_RESOURCES(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('tags_create_with_resources.json') - return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) - - def _api_2_0_tags_a010ec41_2ead_4630_a1d0_237fa77e4d4d(self, method, url, body, headers): - if method == 'GET': - # ex_get_tag - body = self.fixtures.load('tags_get.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == 'PUT': - # ex_tag_resource - body = self.fixtures.load('tags_update.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == 'DELETE': - # ex_delete_tag - body = '' - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _api_2_0_balance(self, method, url, body, headers): - body = self.fixtures.load('balance.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_pricing(self, method, url, body, headers): - body = self.fixtures.load('pricing.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_currentusage(self, method, url, body, headers): - body = self.fixtures.load('currentusage.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_subscriptions(self, method, url, body, headers): - body = self.fixtures.load('subscriptions.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_subscriptions_STATUS_FILTER(self, method, url, body, headers): - self.assertUrlContainsQueryParams(url, {'status': 'active'}) - - body = self.fixtures.load('subscriptions.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_subscriptions_RESOURCE_FILTER(self, method, url, body, headers): - expected_params = {'resource': 'cpu,mem', 'status': 'all'} - self.assertUrlContainsQueryParams(url, expected_params) - - body = self.fixtures.load('subscriptions.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_subscriptions_7272_action_auto_renew(self, method, url, body, headers): - body = '' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_subscriptions_CREATE_SUBSCRIPTION(self, method, url, body, headers): - body = self.fixtures.load('create_subscription.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_capabilities(self, method, url, body, headers): - body = self.fixtures.load('capabilities.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_servers_availability_groups(self, method, url, body, headers): - body = self.fixtures.load('servers_avail_groups.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_2_0_drives_availability_groups(self, method, url, body, headers): - body = self.fixtures.load('drives_avail_groups.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_cloudstack.py b/awx/lib/site-packages/libcloud/test/compute/test_cloudstack.py deleted file mode 100644 index 091d98b0ee..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_cloudstack.py +++ /dev/null @@ -1,696 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import os - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import parse_qsl - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.common.types import ProviderError -from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver -from libcloud.compute.types import LibcloudError, Provider, InvalidCredsError -from libcloud.compute.types import KeyPairDoesNotExistError -from libcloud.compute.providers import get_driver - -from libcloud.test import unittest -from libcloud.test import MockHttpTestCase -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class CloudStackCommonTestCase(TestCaseMixin): - driver_klass = CloudStackNodeDriver - - def setUp(self): - self.driver_klass.connectionCls.conn_classes = \ - (None, CloudStackMockHttp) - self.driver = self.driver_klass('apikey', 'secret', - path='/test/path', - host='api.dummy.com') - self.driver.path = '/test/path' - self.driver.type = -1 - CloudStackMockHttp.type = None - CloudStackMockHttp.fixture_tag = 'default' - self.driver.connection.poll_interval = 0.0 - - def test_invalid_credentials(self): - CloudStackMockHttp.type = 'invalid_credentials' - driver = self.driver_klass('invalid', 'invalid', path='/test/path', - host='api.dummy.com') - self.assertRaises(InvalidCredsError, driver.list_nodes) - - def test_import_keypair_from_string_api_error(self): - CloudStackMockHttp.type = 'api_error' - - name = 'test-pair' - key_material = '' - - expected_msg = 'Public key is invalid' - self.assertRaisesRegexp(ProviderError, expected_msg, - self.driver.import_key_pair_from_string, - name=name, key_material=key_material) - - def test_create_node_immediate_failure(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - CloudStackMockHttp.fixture_tag = 'deployfail' - try: - self.driver.create_node(name='node-name', - image=image, - size=size) - except: - return - self.assertTrue(False) - - def test_create_node_delayed_failure(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - CloudStackMockHttp.fixture_tag = 'deployfail2' - try: - self.driver.create_node(name='node-name', - image=image, - size=size) - except: - return - self.assertTrue(False) - - def test_create_node_default_location_success(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - default_location = self.driver.list_locations()[0] - - node = self.driver.create_node(name='fred', - image=image, - size=size) - - self.assertEqual(node.name, 'fred') - self.assertEqual(node.public_ips, []) - self.assertEqual(node.private_ips, ['192.168.1.2']) - self.assertEqual(node.extra['zone_id'], default_location.id) - - def test_create_node_ex_security_groups(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - location = self.driver.list_locations()[0] - sg = [sg['name'] for sg in self.driver.ex_list_security_groups()] - CloudStackMockHttp.fixture_tag = 'deploysecuritygroup' - node = self.driver.create_node(name='test', - location=location, - image=image, - size=size, - ex_security_groups=sg) - self.assertEqual(node.name, 'test') - self.assertEqual(node.extra['security_group'], sg) - self.assertEqual(node.id, 'fc4fd31a-16d3-49db-814a-56b39b9ef986') - - def test_create_node_ex_keyname(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - location = self.driver.list_locations()[0] - CloudStackMockHttp.fixture_tag = 'deploykeyname' - node = self.driver.create_node(name='test', - location=location, - image=image, - size=size, - ex_keyname='foobar') - self.assertEqual(node.name, 'test') - self.assertEqual(node.extra['key_name'], 'foobar') - - def test_create_node_project(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - location = self.driver.list_locations()[0] - project = self.driver.ex_list_projects()[0] - CloudStackMockHttp.fixture_tag = 'deployproject' - node = self.driver.create_node(name='test', - location=location, - image=image, - size=size, - project=project) - self.assertEqual(node.name, 'TestNode') - self.assertEqual(node.extra['project'], 'Test Project') - - def test_list_images_no_images_available(self): - CloudStackMockHttp.fixture_tag = 'notemplates' - - images = self.driver.list_images() - self.assertEqual(0, len(images)) - - def test_list_images(self): - _, fixture = CloudStackMockHttp()._load_fixture( - 'listTemplates_default.json') - templates = fixture['listtemplatesresponse']['template'] - - images = self.driver.list_images() - for i, image in enumerate(images): - # NodeImage expects id to be a string, - # the CloudStack fixture has an int - tid = str(templates[i]['id']) - tname = templates[i]['name'] - self.assertIsInstance(image.driver, CloudStackNodeDriver) - self.assertEqual(image.id, tid) - self.assertEqual(image.name, tname) - - def test_ex_list_disk_offerings(self): - diskOfferings = self.driver.ex_list_disk_offerings() - self.assertEqual(1, len(diskOfferings)) - - diskOffering, = diskOfferings - - self.assertEqual('Disk offer 1', diskOffering.name) - self.assertEqual(10, diskOffering.size) - - def test_ex_list_networks(self): - _, fixture = CloudStackMockHttp()._load_fixture( - 'listNetworks_default.json') - fixture_networks = fixture['listnetworksresponse']['network'] - - networks = self.driver.ex_list_networks() - - for i, network in enumerate(networks): - self.assertEqual(network.id, fixture_networks[i]['id']) - self.assertEqual( - network.displaytext, fixture_networks[i]['displaytext']) - self.assertEqual(network.name, fixture_networks[i]['name']) - self.assertEqual( - network.networkofferingid, - fixture_networks[i]['networkofferingid']) - self.assertEqual(network.zoneid, fixture_networks[i]['zoneid']) - - def test_ex_list_network_offerings(self): - _, fixture = CloudStackMockHttp()._load_fixture( - 'listNetworkOfferings_default.json') - fixture_networkoffers = \ - fixture['listnetworkofferingsresponse']['networkoffering'] - - networkoffers = self.driver.ex_list_network_offerings() - - for i, networkoffer in enumerate(networkoffers): - self.assertEqual(networkoffer.id, fixture_networkoffers[i]['id']) - self.assertEqual(networkoffer.name, - fixture_networkoffers[i]['name']) - self.assertEqual(networkoffer.display_text, - fixture_networkoffers[i]['displaytext']) - self.assertEqual(networkoffer.for_vpc, - fixture_networkoffers[i]['forvpc']) - self.assertEqual(networkoffer.guest_ip_type, - fixture_networkoffers[i]['guestiptype']) - self.assertEqual(networkoffer.service_offering_id, - fixture_networkoffers[i]['serviceofferingid']) - - def test_ex_create_network(self): - _, fixture = CloudStackMockHttp()._load_fixture( - 'createNetwork_default.json') - - fixture_network = fixture['createnetworkresponse']['network'] - - netoffer = self.driver.ex_list_network_offerings()[0] - location = self.driver.list_locations()[0] - network = self.driver.ex_create_network(display_text='test', - name='test', - network_offering=netoffer, - location=location, - gateway='10.1.1.1', - netmask='255.255.255.0', - network_domain='cloud.local', - vpc_id="2", - project_id="2") - - self.assertEqual(network.name, fixture_network['name']) - self.assertEqual(network.displaytext, fixture_network['displaytext']) - self.assertEqual(network.id, fixture_network['id']) - self.assertEqual(network.extra['gateway'], fixture_network['gateway']) - self.assertEqual(network.extra['netmask'], fixture_network['netmask']) - self.assertEqual(network.networkofferingid, - fixture_network['networkofferingid']) - self.assertEqual(network.extra['vpc_id'], fixture_network['vpcid']) - self.assertEqual(network.extra['project_id'], - fixture_network['projectid']) - - def test_ex_delete_network(self): - - network = self.driver.ex_list_networks()[0] - - result = self.driver.ex_delete_network(network=network) - self.assertTrue(result) - - def test_ex_list_projects(self): - _, fixture = CloudStackMockHttp()._load_fixture( - 'listProjects_default.json') - fixture_projects = fixture['listprojectsresponse']['project'] - - projects = self.driver.ex_list_projects() - - for i, project in enumerate(projects): - self.assertEqual(project.id, fixture_projects[i]['id']) - self.assertEqual( - project.display_text, fixture_projects[i]['displaytext']) - self.assertEqual(project.name, fixture_projects[i]['name']) - self.assertEqual( - project.extra['domainid'], - fixture_projects[i]['domainid']) - self.assertEqual( - project.extra['cpulimit'], - fixture_projects[i]['cpulimit']) - - def test_create_volume(self): - volumeName = 'vol-0' - location = self.driver.list_locations()[0] - - volume = self.driver.create_volume(10, volumeName, location) - - self.assertEqual(volumeName, volume.name) - self.assertEqual(10, volume.size) - - def test_create_volume_no_noncustomized_offering_with_size(self): - """If the sizes of disk offerings are not configurable and there - are no disk offerings with the requested size, an exception should - be thrown.""" - - location = self.driver.list_locations()[0] - - self.assertRaises( - LibcloudError, - self.driver.create_volume, - 'vol-0', location, 11) - - def test_create_volume_with_custom_disk_size_offering(self): - CloudStackMockHttp.fixture_tag = 'withcustomdisksize' - - volumeName = 'vol-0' - location = self.driver.list_locations()[0] - - volume = self.driver.create_volume(10, volumeName, location) - - self.assertEqual(volumeName, volume.name) - - def test_attach_volume(self): - node = self.driver.list_nodes()[0] - volumeName = 'vol-0' - location = self.driver.list_locations()[0] - - volume = self.driver.create_volume(10, volumeName, location) - attachReturnVal = self.driver.attach_volume(volume, node) - - self.assertTrue(attachReturnVal) - - def test_detach_volume(self): - volumeName = 'gre-test-volume' - location = self.driver.list_locations()[0] - volume = self.driver.create_volume(10, volumeName, location) - res = self.driver.detach_volume(volume) - self.assertTrue(res) - - def test_destroy_volume(self): - volumeName = 'gre-test-volume' - location = self.driver.list_locations()[0] - volume = self.driver.create_volume(10, volumeName, location) - res = self.driver.destroy_volume(volume) - self.assertTrue(res) - - def test_list_volumes(self): - volumes = self.driver.list_volumes() - self.assertEqual(1, len(volumes)) - self.assertEqual('ROOT-69942', volumes[0].name) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(2, len(nodes)) - self.assertEqual('test', nodes[0].name) - self.assertEqual('2600', nodes[0].id) - self.assertEqual([], nodes[0].extra['security_group']) - self.assertEqual(None, nodes[0].extra['key_name']) - - def test_list_locations(self): - location = self.driver.list_locations()[0] - self.assertEqual('1', location.id) - self.assertEqual('Sydney', location.name) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual('Compute Micro PRD', sizes[0].name) - self.assertEqual('105', sizes[0].id) - self.assertEqual(384, sizes[0].ram) - self.assertEqual('Compute Large PRD', sizes[2].name) - self.assertEqual('69', sizes[2].id) - self.assertEqual(6964, sizes[2].ram) - - def test_ex_start_node(self): - node = self.driver.list_nodes()[0] - res = node.ex_start() - self.assertEqual('Starting', res) - - def test_ex_stop_node(self): - node = self.driver.list_nodes()[0] - res = node.ex_stop() - self.assertEqual('Stopped', res) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - res = node.destroy() - self.assertTrue(res) - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - res = node.reboot() - self.assertTrue(res) - - def test_list_key_pairs(self): - keypairs = self.driver.list_key_pairs() - fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \ - '00:00:00:00:00' - - self.assertEqual(keypairs[0].name, 'cs-keypair') - self.assertEqual(keypairs[0].fingerprint, fingerprint) - - # Test old and deprecated way - keypairs = self.driver.ex_list_keypairs() - - self.assertEqual(keypairs[0]['name'], 'cs-keypair') - self.assertEqual(keypairs[0]['fingerprint'], fingerprint) - - def test_list_key_pairs_no_keypair_key(self): - CloudStackMockHttp.fixture_tag = 'no_keys' - keypairs = self.driver.list_key_pairs() - self.assertEqual(keypairs, []) - - def test_get_key_pair(self): - CloudStackMockHttp.fixture_tag = 'get_one' - key_pair = self.driver.get_key_pair(name='cs-keypair') - self.assertEqual(key_pair.name, 'cs-keypair') - - def test_get_key_pair_doesnt_exist(self): - CloudStackMockHttp.fixture_tag = 'get_one_doesnt_exist' - - self.assertRaises(KeyPairDoesNotExistError, self.driver.get_key_pair, - name='does-not-exist') - - def test_create_keypair(self): - key_pair = self.driver.create_key_pair(name='test-keypair') - - self.assertEqual(key_pair.name, 'test-keypair') - self.assertTrue(key_pair.fingerprint is not None) - self.assertTrue(key_pair.private_key is not None) - - # Test old and deprecated way - res = self.driver.ex_create_keypair(name='test-keypair') - self.assertEqual(res['name'], 'test-keypair') - self.assertTrue(res['fingerprint'] is not None) - self.assertTrue(res['privateKey'] is not None) - - def test_import_keypair_from_file(self): - fingerprint = 'c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15' - path = os.path.join(os.path.dirname(__file__), 'fixtures', - 'cloudstack', - 'dummy_rsa.pub') - - key_pair = self.driver.import_key_pair_from_file('foobar', path) - self.assertEqual(key_pair.name, 'foobar') - self.assertEqual(key_pair.fingerprint, fingerprint) - - # Test old and deprecated way - res = self.driver.ex_import_keypair('foobar', path) - self.assertEqual(res['keyName'], 'foobar') - self.assertEqual(res['keyFingerprint'], fingerprint) - - def test_ex_import_keypair_from_string(self): - fingerprint = 'c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15' - path = os.path.join(os.path.dirname(__file__), 'fixtures', - 'cloudstack', - 'dummy_rsa.pub') - fh = open(path) - key_material = fh.read() - fh.close() - - key_pair = self.driver.import_key_pair_from_string('foobar', key_material=key_material) - self.assertEqual(key_pair.name, 'foobar') - self.assertEqual(key_pair.fingerprint, fingerprint) - - # Test old and deprecated way - res = self.driver.ex_import_keypair_from_string('foobar', key_material=key_material) - self.assertEqual(res['keyName'], 'foobar') - self.assertEqual(res['keyFingerprint'], fingerprint) - - def test_delete_key_pair(self): - key_pair = self.driver.list_key_pairs()[0] - - res = self.driver.delete_key_pair(key_pair=key_pair) - self.assertTrue(res) - - # Test old and deprecated way - res = self.driver.ex_delete_keypair(keypair='cs-keypair') - self.assertTrue(res) - - def test_ex_list_security_groups(self): - groups = self.driver.ex_list_security_groups() - self.assertEqual(2, len(groups)) - self.assertEqual(groups[0]['name'], 'default') - self.assertEqual(groups[1]['name'], 'mongodb') - - def test_ex_list_security_groups_no_securitygroup_key(self): - CloudStackMockHttp.fixture_tag = 'no_groups' - - groups = self.driver.ex_list_security_groups() - self.assertEqual(groups, []) - - def test_ex_create_security_group(self): - group = self.driver.ex_create_security_group(name='MySG') - self.assertEqual(group['name'], 'MySG') - - def test_ex_delete_security_group(self): - res = self.driver.ex_delete_security_group(name='MySG') - self.assertTrue(res) - - def test_ex_authorize_security_group_ingress(self): - res = self.driver.ex_authorize_security_group_ingress('MySG', - 'TCP', - '22', - '22', - '0.0.0.0/0') - self.assertTrue(res) - - def test_ex_list_public_ips(self): - ips = self.driver.ex_list_public_ips() - self.assertEqual(ips[0].address, '1.1.1.116') - - def test_ex_allocate_public_ip(self): - addr = self.driver.ex_allocate_public_ip() - self.assertEqual(addr.address, '7.5.6.1') - self.assertEqual(addr.id, '10987171-8cc9-4d0a-b98f-1698c09ddd2d') - - def test_ex_release_public_ip(self): - addresses = self.driver.ex_list_public_ips() - res = self.driver.ex_release_public_ip(addresses[0]) - self.assertTrue(res) - - def test_ex_create_port_forwarding_rule(self): - node = self.driver.list_nodes()[0] - address = self.driver.ex_list_public_ips()[0] - private_port = 33 - private_end_port = 34 - public_port = 33 - public_end_port = 34 - openfirewall = True - protocol = 'TCP' - rule = self.driver.ex_create_port_forwarding_rule(node, - address, - private_port, - public_port, - protocol, - public_end_port, - private_end_port, - openfirewall) - self.assertEqual(rule.address, address) - self.assertEqual(rule.protocol, protocol) - self.assertEqual(rule.public_port, public_port) - self.assertEqual(rule.public_end_port, public_end_port) - self.assertEqual(rule.private_port, private_port) - self.assertEqual(rule.private_end_port, private_end_port) - - def test_ex_list_port_forwarding_rules(self): - rules = self.driver.ex_list_port_forwarding_rules() - self.assertEqual(len(rules), 1) - rule = rules[0] - self.assertTrue(rule.node) - self.assertEqual(rule.protocol, 'tcp') - self.assertEqual(rule.public_port, '33') - self.assertEqual(rule.public_end_port, '34') - self.assertEqual(rule.private_port, '33') - self.assertEqual(rule.private_end_port, '34') - self.assertEqual(rule.address.address, '1.1.1.116') - - def test_ex_delete_port_forwarding_rule(self): - node = self.driver.list_nodes()[0] - rule = self.driver.ex_list_port_forwarding_rules()[0] - res = self.driver.ex_delete_port_forwarding_rule(node, rule) - self.assertTrue(res) - - def test_node_ex_delete_port_forwarding_rule(self): - node = self.driver.list_nodes()[0] - self.assertEqual(len(node.extra['port_forwarding_rules']), 1) - node.extra['port_forwarding_rules'][0].delete() - self.assertEqual(len(node.extra['port_forwarding_rules']), 0) - - def test_node_ex_create_port_forwarding_rule(self): - node = self.driver.list_nodes()[0] - self.assertEqual(len(node.extra['port_forwarding_rules']), 1) - address = self.driver.ex_list_public_ips()[0] - private_port = 33 - private_end_port = 34 - public_port = 33 - public_end_port = 34 - openfirewall = True - protocol = 'TCP' - rule = node.ex_create_port_forwarding_rule(address, - private_port, - public_port, - protocol, - public_end_port, - private_end_port, - openfirewall) - self.assertEqual(rule.address, address) - self.assertEqual(rule.protocol, protocol) - self.assertEqual(rule.public_port, public_port) - self.assertEqual(rule.public_end_port, public_end_port) - self.assertEqual(rule.private_port, private_port) - self.assertEqual(rule.private_end_port, private_end_port) - self.assertEqual(len(node.extra['port_forwarding_rules']), 2) - - def test_ex_limits(self): - limits = self.driver.ex_limits() - self.assertEqual(limits['max_images'], 20) - self.assertEqual(limits['max_networks'], 20) - self.assertEqual(limits['max_public_ips'], -1) - self.assertEqual(limits['max_vpc'], 20) - self.assertEqual(limits['max_instances'], 20) - self.assertEqual(limits['max_projects'], -1) - self.assertEqual(limits['max_volumes'], 20) - self.assertEqual(limits['max_snapshots'], 20) - - def test_ex_create_tags(self): - node = self.driver.list_nodes()[0] - tags = {'Region': 'Canada'} - resp = self.driver.ex_create_tags([node.id], 'UserVm', tags) - self.assertTrue(resp) - - def test_ex_delete_tags(self): - node = self.driver.list_nodes()[0] - tag_keys = ['Region'] - resp = self.driver.ex_delete_tags([node.id], 'UserVm', tag_keys) - self.assertTrue(resp) - - -class CloudStackTestCase(CloudStackCommonTestCase, unittest.TestCase): - def test_driver_instantiation(self): - urls = [ - 'http://api.exoscale.ch/compute1', # http, default port - 'https://api.exoscale.ch/compute2', # https, default port - 'http://api.exoscale.ch:8888/compute3', # https, custom port - 'https://api.exoscale.ch:8787/compute4', # https, custom port - 'https://api.test.com/compute/endpoint' # https, default port - ] - - expected_values = [ - {'host': 'api.exoscale.ch', 'port': 80, 'path': '/compute1'}, - {'host': 'api.exoscale.ch', 'port': 443, 'path': '/compute2'}, - {'host': 'api.exoscale.ch', 'port': 8888, 'path': '/compute3'}, - {'host': 'api.exoscale.ch', 'port': 8787, 'path': '/compute4'}, - {'host': 'api.test.com', 'port': 443, 'path': '/compute/endpoint'} - ] - - cls = get_driver(Provider.CLOUDSTACK) - - for url, expected in zip(urls, expected_values): - driver = cls('key', 'secret', url=url) - - self.assertEqual(driver.host, expected['host']) - self.assertEqual(driver.path, expected['path']) - self.assertEqual(driver.connection.port, expected['port']) - - def test_user_must_provide_host_and_path_or_url(self): - expected_msg = ('When instantiating CloudStack driver directly ' - 'you also need to provide url or host and path ' - 'argument') - cls = get_driver(Provider.CLOUDSTACK) - - self.assertRaisesRegexp(Exception, expected_msg, cls, - 'key', 'secret') - - try: - cls('key', 'secret', True, 'localhost', '/path') - except Exception: - self.fail('host and path provided but driver raised an exception') - - try: - cls('key', 'secret', url='https://api.exoscale.ch/compute') - except Exception: - self.fail('url provided but driver raised an exception') - - -class CloudStackMockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('cloudstack') - fixture_tag = 'default' - - def _load_fixture(self, fixture): - body = self.fixtures.load(fixture) - return body, json.loads(body) - - def _test_path_invalid_credentials(self, method, url, body, headers): - body = '' - return (httplib.UNAUTHORIZED, body, {}, - httplib.responses[httplib.UNAUTHORIZED]) - - def _test_path_api_error(self, method, url, body, headers): - body = self.fixtures.load('registerSSHKeyPair_error.json') - return (431, body, {}, - httplib.responses[httplib.OK]) - - def _test_path(self, method, url, body, headers): - url = urlparse.urlparse(url) - query = dict(parse_qsl(url.query)) - - self.assertTrue('apiKey' in query) - self.assertTrue('command' in query) - self.assertTrue('response' in query) - self.assertTrue('signature' in query) - - self.assertTrue(query['response'] == 'json') - - del query['apiKey'] - del query['response'] - del query['signature'] - command = query.pop('command') - - if hasattr(self, '_cmd_' + command): - return getattr(self, '_cmd_' + command)(**query) - else: - fixture = command + '_' + self.fixture_tag + '.json' - body, obj = self._load_fixture(fixture) - return (httplib.OK, body, obj, httplib.responses[httplib.OK]) - - def _cmd_queryAsyncJobResult(self, jobid): - fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json' - body, obj = self._load_fixture(fixture) - return (httplib.OK, body, obj, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_deployment.py b/awx/lib/site-packages/libcloud/test/compute/test_deployment.py deleted file mode 100644 index 7fda79c541..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_deployment.py +++ /dev/null @@ -1,503 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed to the Apache Software Foundation (ASF) under one or more§ -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import os -import sys -import time -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import u -from libcloud.utils.py3 import PY3 - -from libcloud.compute.deployment import MultiStepDeployment, Deployment -from libcloud.compute.deployment import SSHKeyDeployment, ScriptDeployment -from libcloud.compute.deployment import ScriptFileDeployment, FileDeployment -from libcloud.compute.base import Node -from libcloud.compute.types import NodeState, DeploymentError, LibcloudError -from libcloud.compute.ssh import BaseSSHClient -from libcloud.compute.drivers.rackspace import RackspaceFirstGenNodeDriver as Rackspace - -from libcloud.test import MockHttp, XML_HEADERS -from libcloud.test.file_fixtures import ComputeFileFixtures -from mock import Mock, patch - -from libcloud.test.secrets import RACKSPACE_PARAMS - - -class MockDeployment(Deployment): - - def run(self, node, client): - return node - - -class MockClient(BaseSSHClient): - - def __init__(self, *args, **kwargs): - self.stdout = '' - self.stderr = '' - self.exit_status = 0 - - def put(self, path, contents, chmod=755, mode='w'): - return contents - - def run(self, name): - return self.stdout, self.stderr, self.exit_status - - def delete(self, name): - return True - - -class DeploymentTests(unittest.TestCase): - - def setUp(self): - Rackspace.connectionCls.conn_classes = (None, RackspaceMockHttp) - RackspaceMockHttp.type = None - self.driver = Rackspace(*RACKSPACE_PARAMS) - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - self.driver.features = {'create_node': ['generates_password']} - self.node = Node(id=12345, name='test', state=NodeState.RUNNING, - public_ips=['1.2.3.4'], private_ips=['1.2.3.5'], - driver=Rackspace) - self.node2 = Node(id=123456, name='test', state=NodeState.RUNNING, - public_ips=['1.2.3.4'], private_ips=['1.2.3.5'], - driver=Rackspace) - - def test_multi_step_deployment(self): - msd = MultiStepDeployment() - self.assertEqual(len(msd.steps), 0) - - msd.add(MockDeployment()) - self.assertEqual(len(msd.steps), 1) - - self.assertEqual(self.node, msd.run(node=self.node, client=None)) - - def test_ssh_key_deployment(self): - sshd = SSHKeyDeployment(key='1234') - - self.assertEqual(self.node, sshd.run(node=self.node, - client=MockClient(hostname='localhost'))) - - def test_file_deployment(self): - # use this file (__file__) for obtaining permissions - target = os.path.join('/tmp', os.path.basename(__file__)) - fd = FileDeployment(__file__, target) - self.assertEqual(target, fd.target) - self.assertEqual(__file__, fd.source) - self.assertEqual(self.node, fd.run( - node=self.node, client=MockClient(hostname='localhost'))) - - def test_script_deployment(self): - sd1 = ScriptDeployment(script='foobar', delete=True) - sd2 = ScriptDeployment(script='foobar', delete=False) - sd3 = ScriptDeployment( - script='foobar', delete=False, name='foobarname') - - self.assertTrue(sd1.name.find('deployment') != '1') - self.assertEqual(sd3.name, 'foobarname') - - self.assertEqual(self.node, sd1.run(node=self.node, - client=MockClient(hostname='localhost'))) - self.assertEqual(self.node, sd2.run(node=self.node, - client=MockClient(hostname='localhost'))) - - def test_script_file_deployment(self): - file_path = os.path.abspath(__file__) - with open(file_path, 'rb') as fp: - content = fp.read() - - if PY3: - content = content.decode('utf-8') - - sfd1 = ScriptFileDeployment(script_file=file_path) - self.assertEqual(sfd1.script, content) - - def test_script_deployment_relative_path(self): - client = Mock() - client.put.return_value = '/home/ubuntu/relative.sh' - client.run.return_value = ('', '', 0) - - sd = ScriptDeployment(script='echo "foo"', name='relative.sh') - sd.run(self.node, client) - - client.run.assert_called_once_with('/home/ubuntu/relative.sh') - - def test_script_deployment_absolute_path(self): - client = Mock() - client.put.return_value = '/home/ubuntu/relative.sh' - client.run.return_value = ('', '', 0) - - sd = ScriptDeployment(script='echo "foo"', name='/root/relative.sh') - sd.run(self.node, client) - - client.run.assert_called_once_with('/root/relative.sh') - - def test_script_deployment_with_arguments(self): - client = Mock() - client.put.return_value = '/home/ubuntu/relative.sh' - client.run.return_value = ('', '', 0) - - args = ['arg1', 'arg2', '--option1=test'] - sd = ScriptDeployment(script='echo "foo"', args=args, - name='/root/relative.sh') - sd.run(self.node, client) - - expected = '/root/relative.sh arg1 arg2 --option1=test' - client.run.assert_called_once_with(expected) - - client.reset_mock() - - args = [] - sd = ScriptDeployment(script='echo "foo"', args=args, - name='/root/relative.sh') - sd.run(self.node, client) - - expected = '/root/relative.sh' - client.run.assert_called_once_with(expected) - - def test_script_file_deployment_with_arguments(self): - file_path = os.path.abspath(__file__) - client = Mock() - client.put.return_value = '/home/ubuntu/relative.sh' - client.run.return_value = ('', '', 0) - - args = ['arg1', 'arg2', '--option1=test', 'option2'] - sfd = ScriptFileDeployment(script_file=file_path, args=args, - name='/root/relative.sh') - - sfd.run(self.node, client) - - expected = '/root/relative.sh arg1 arg2 --option1=test option2' - client.run.assert_called_once_with(expected) - - def test_script_deployment_and_sshkey_deployment_argument_types(self): - class FileObject(object): - - def __init__(self, name): - self.name = name - - def read(self): - return 'bar' - - ScriptDeployment(script='foobar') - ScriptDeployment(script=u('foobar')) - ScriptDeployment(script=FileObject('test')) - - SSHKeyDeployment(key='foobar') - SSHKeyDeployment(key=u('foobar')) - SSHKeyDeployment(key=FileObject('test')) - - try: - ScriptDeployment(script=[]) - except TypeError: - pass - else: - self.fail('TypeError was not thrown') - - try: - SSHKeyDeployment(key={}) - except TypeError: - pass - else: - self.fail('TypeError was not thrown') - - def test_wait_until_running_running_instantly(self): - node2, ips = self.driver.wait_until_running( - nodes=[self.node], wait_period=1, - timeout=0.5)[0] - self.assertEqual(self.node.uuid, node2.uuid) - self.assertEqual(['67.23.21.33'], ips) - - def test_wait_until_running_running_after_1_second(self): - RackspaceMockHttp.type = '05_SECOND_DELAY' - node2, ips = self.driver.wait_until_running( - nodes=[self.node], wait_period=1, - timeout=0.5)[0] - self.assertEqual(self.node.uuid, node2.uuid) - self.assertEqual(['67.23.21.33'], ips) - - def test_wait_until_running_running_after_1_second_private_ips(self): - RackspaceMockHttp.type = '05_SECOND_DELAY' - node2, ips = self.driver.wait_until_running( - nodes=[self.node], wait_period=1, - timeout=0.5, ssh_interface='private_ips')[0] - self.assertEqual(self.node.uuid, node2.uuid) - self.assertEqual(['10.176.168.218'], ips) - - def test_wait_until_running_invalid_ssh_interface_argument(self): - try: - self.driver.wait_until_running(nodes=[self.node], wait_period=1, - ssh_interface='invalid') - except ValueError: - pass - else: - self.fail('Exception was not thrown') - - def test_wait_until_running_timeout(self): - RackspaceMockHttp.type = 'TIMEOUT' - - try: - self.driver.wait_until_running(nodes=[self.node], wait_period=0.1, - timeout=0.5) - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(e.value.find('Timed out') != -1) - else: - self.fail('Exception was not thrown') - - def test_wait_until_running_running_node_missing_from_list_nodes(self): - RackspaceMockHttp.type = 'MISSING' - - try: - self.driver.wait_until_running(nodes=[self.node], wait_period=0.1, - timeout=0.5) - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(e.value.find('Timed out after 0.5 second') != -1) - else: - self.fail('Exception was not thrown') - - def test_wait_until_running_running_multiple_nodes_have_same_uuid(self): - RackspaceMockHttp.type = 'SAME_UUID' - - try: - self.driver.wait_until_running(nodes=[self.node], wait_period=0.1, - timeout=0.5) - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue( - e.value.find('Unable to match specified uuids') != -1) - else: - self.fail('Exception was not thrown') - - def test_wait_until_running_running_wait_for_multiple_nodes(self): - RackspaceMockHttp.type = 'MULTIPLE_NODES' - - nodes = self.driver.wait_until_running( - nodes=[self.node, self.node2], wait_period=0.1, - timeout=0.5) - self.assertEqual(self.node.uuid, nodes[0][0].uuid) - self.assertEqual(self.node2.uuid, nodes[1][0].uuid) - self.assertEqual(['67.23.21.33'], nodes[0][1]) - self.assertEqual(['67.23.21.34'], nodes[1][1]) - - def test_ssh_client_connect_success(self): - mock_ssh_client = Mock() - mock_ssh_client.return_value = None - - ssh_client = self.driver._ssh_client_connect( - ssh_client=mock_ssh_client, - timeout=0.5) - self.assertEqual(mock_ssh_client, ssh_client) - - def test_ssh_client_connect_timeout(self): - mock_ssh_client = Mock() - mock_ssh_client.connect = Mock() - mock_ssh_client.connect.side_effect = IOError('bam') - - try: - self.driver._ssh_client_connect(ssh_client=mock_ssh_client, - timeout=0.5) - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(e.value.find('Giving up') != -1) - else: - self.fail('Exception was not thrown') - - def test_run_deployment_script_success(self): - task = Mock() - ssh_client = Mock() - - ssh_client2 = self.driver._run_deployment_script(task=task, - node=self.node, - ssh_client=ssh_client, - max_tries=2) - self.assertTrue(isinstance(ssh_client2, Mock)) - - def test_run_deployment_script_exception(self): - task = Mock() - task.run = Mock() - task.run.side_effect = Exception('bar') - ssh_client = Mock() - - try: - self.driver._run_deployment_script(task=task, - node=self.node, - ssh_client=ssh_client, - max_tries=2) - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(e.value.find('Failed after 2 tries') != -1) - else: - self.fail('Exception was not thrown') - - @patch('libcloud.compute.base.SSHClient') - @patch('libcloud.compute.ssh') - def test_deploy_node_success(self, mock_ssh_module, _): - self.driver.create_node = Mock() - self.driver.create_node.return_value = self.node - mock_ssh_module.have_paramiko = True - - deploy = Mock() - - node = self.driver.deploy_node(deploy=deploy) - self.assertEqual(self.node.id, node.id) - - @patch('libcloud.compute.base.SSHClient') - @patch('libcloud.compute.ssh') - def test_deploy_node_exception_run_deployment_script(self, mock_ssh_module, - _): - self.driver.create_node = Mock() - self.driver.create_node.return_value = self.node - mock_ssh_module.have_paramiko = True - - deploy = Mock() - deploy.run = Mock() - deploy.run.side_effect = Exception('foo') - - try: - self.driver.deploy_node(deploy=deploy) - except DeploymentError: - e = sys.exc_info()[1] - self.assertTrue(e.node.id, self.node.id) - else: - self.fail('Exception was not thrown') - - @patch('libcloud.compute.base.SSHClient') - @patch('libcloud.compute.ssh') - def test_deploy_node_exception_ssh_client_connect(self, mock_ssh_module, - ssh_client): - self.driver.create_node = Mock() - self.driver.create_node.return_value = self.node - - mock_ssh_module.have_paramiko = True - - deploy = Mock() - ssh_client.side_effect = IOError('bar') - - try: - self.driver.deploy_node(deploy=deploy) - except DeploymentError: - e = sys.exc_info()[1] - self.assertTrue(e.node.id, self.node.id) - else: - self.fail('Exception was not thrown') - - @patch('libcloud.compute.ssh') - def test_deploy_node_depoy_node_not_implemented(self, mock_ssh_module): - self.driver.features = {'create_node': []} - mock_ssh_module.have_paramiko = True - - try: - self.driver.deploy_node(deploy=Mock()) - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - self.driver.features = {} - - try: - self.driver.deploy_node(deploy=Mock()) - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - @patch('libcloud.compute.base.SSHClient') - @patch('libcloud.compute.ssh') - def test_deploy_node_password_auth(self, mock_ssh_module, _): - self.driver.features = {'create_node': ['password']} - mock_ssh_module.have_paramiko = True - - self.driver.create_node = Mock() - self.driver.create_node.return_value = self.node - - node = self.driver.deploy_node(deploy=Mock()) - self.assertEqual(self.node.id, node.id) - - @patch('libcloud.compute.base.SSHClient') - @patch('libcloud.compute.ssh') - def test_exception_is_thrown_is_paramiko_is_not_available(self, - mock_ssh_module, - _): - self.driver.features = {'create_node': ['password']} - self.driver.create_node = Mock() - self.driver.create_node.return_value = self.node - - mock_ssh_module.have_paramiko = False - - try: - self.driver.deploy_node(deploy=Mock()) - except RuntimeError: - e = sys.exc_info()[1] - self.assertTrue(str(e).find('paramiko is not installed') != -1) - else: - self.fail('Exception was not thrown') - - mock_ssh_module.have_paramiko = True - node = self.driver.deploy_node(deploy=Mock()) - self.assertEqual(self.node.id, node.id) - - -class RackspaceMockHttp(MockHttp): - fixtures = ComputeFileFixtures('openstack') - - def _v2_0_tokens(self, method, url, body, headers): - body = self.fixtures.load('_v2_0__auth_deployment.json') - headers = { - 'content-type': 'application/json' - } - return (httplib.OK, body, headers, - httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail(self, method, url, body, headers): - body = self.fixtures.load( - 'v1_slug_servers_detail_deployment_success.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail_05_SECOND_DELAY(self, method, url, body, headers): - time.sleep(0.5) - body = self.fixtures.load( - 'v1_slug_servers_detail_deployment_success.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail_TIMEOUT(self, method, url, body, headers): - body = self.fixtures.load( - 'v1_slug_servers_detail_deployment_pending.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail_MISSING(self, method, url, body, headers): - body = self.fixtures.load( - 'v1_slug_servers_detail_deployment_missing.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail_SAME_UUID(self, method, url, body, headers): - body = self.fixtures.load( - 'v1_slug_servers_detail_deployment_same_uuid.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail_MULTIPLE_NODES(self, method, url, body, headers): - body = self.fixtures.load( - 'v1_slug_servers_detail_deployment_multiple_nodes.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_digitalocean.py b/awx/lib/site-packages/libcloud/test/compute/test_digitalocean.py deleted file mode 100644 index ee9ef555a5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_digitalocean.py +++ /dev/null @@ -1,179 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest - -try: - import simplejson as json -except ImportError: - import json # NOQA - -from libcloud.utils.py3 import httplib - -from libcloud.common.types import InvalidCredsError -from libcloud.compute.base import NodeImage -from libcloud.compute.drivers.digitalocean import DigitalOceanNodeDriver - -from libcloud.test import LibcloudTestCase, MockHttpTestCase -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import DIGITAL_OCEAN_PARAMS - - -# class DigitalOceanTests(unittest.TestCase, TestCaseMixin): -class DigitalOceanTests(LibcloudTestCase): - - def setUp(self): - DigitalOceanNodeDriver.connectionCls.conn_classes = \ - (None, DigitalOceanMockHttp) - DigitalOceanMockHttp.type = None - self.driver = DigitalOceanNodeDriver(*DIGITAL_OCEAN_PARAMS) - - def test_authentication(self): - DigitalOceanMockHttp.type = 'UNAUTHORIZED_CLIENT' - self.assertRaises(InvalidCredsError, self.driver.list_nodes) - - def test_list_images_success(self): - images = self.driver.list_images() - self.assertTrue(len(images) >= 1) - - image = images[0] - self.assertTrue(image.id is not None) - self.assertTrue(image.name is not None) - - def test_list_sizes_success(self): - sizes = self.driver.list_sizes() - self.assertTrue(len(sizes) >= 1) - - size = sizes[0] - self.assertTrue(size.id is not None) - self.assertEqual(size.name, '512MB') - self.assertEqual(size.ram, 512) - - size = sizes[4] - self.assertTrue(size.id is not None) - self.assertEqual(size.name, '8GB') - self.assertEqual(size.ram, 8 * 1024) - - def test_list_locations_success(self): - locations = self.driver.list_locations() - self.assertTrue(len(locations) >= 1) - - location = locations[0] - self.assertEqual(location.id, '1') - self.assertEqual(location.name, 'New York 1') - - def test_list_nodes_success(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 1) - self.assertEqual(nodes[0].name, 'test-2') - self.assertEqual(nodes[0].public_ips, []) - - def test_create_node_invalid_size(self): - image = NodeImage(id='invalid', name=None, driver=self.driver) - size = self.driver.list_sizes()[0] - location = self.driver.list_locations()[0] - - DigitalOceanMockHttp.type = 'INVALID_IMAGE' - expected_msg = r'You specified an invalid image for Droplet creation. \(code: 404\)' - self.assertRaisesRegexp(Exception, expected_msg, - self.driver.create_node, - name='test', size=size, image=image, - location=location) - - def test_reboot_node_success(self): - node = self.driver.list_nodes()[0] - result = self.driver.reboot_node(node) - self.assertTrue(result) - - def test_destroy_node_success(self): - node = self.driver.list_nodes()[0] - result = self.driver.destroy_node(node) - self.assertTrue(result) - - def test_ex_rename_node_success(self): - node = self.driver.list_nodes()[0] - result = self.driver.ex_rename_node(node, 'fedora helios') - self.assertTrue(result) - - def test_ex_list_ssh_keys(self): - keys = self.driver.ex_list_ssh_keys() - self.assertEqual(len(keys), 1) - - self.assertEqual(keys[0].id, 7717) - self.assertEqual(keys[0].name, 'test1') - self.assertEqual(keys[0].pub_key, None) - - def test_ex_destroy_ssh_key(self): - key = self.driver.ex_list_ssh_keys()[0] - result = self.driver.ex_destroy_ssh_key(key.id) - self.assertTrue(result) - - -class DigitalOceanMockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('digitalocean') - - def _regions(self, method, url, body, headers): - body = self.fixtures.load('list_locations.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _images(self, method, url, body, headers): - body = self.fixtures.load('list_images.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _sizes(self, method, url, body, headers): - body = self.fixtures.load('list_sizes.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _droplets(self, method, url, body, headers): - body = self.fixtures.load('list_nodes.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _droplets_new_INVALID_IMAGE(self, method, url, body, headers): - # reboot_node - body = self.fixtures.load('error_invalid_image.json') - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) - - def _droplets_119461_reboot(self, method, url, body, headers): - # reboot_node - body = self.fixtures.load('reboot_node.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _droplets_119461_destroy(self, method, url, body, headers): - # destroy_node - self.assertUrlContainsQueryParams(url, {'scrub_data': '1'}) - body = self.fixtures.load('destroy_node.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _droplets_119461_rename(self, method, url, body, headers): - # reboot_node - self.assertUrlContainsQueryParams(url, {'name': 'fedora helios'}) - body = self.fixtures.load('ex_rename_node.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ssh_keys(self, method, url, body, headers): - body = self.fixtures.load('ex_list_ssh_keys.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ssh_keys_7717_destroy(self, method, url, body, headers): - # destroy_ssh_key - body = self.fixtures.load('ex_destroy_ssh_key.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _droplets_UNAUTHORIZED_CLIENT(self, method, url, body, headers): - body = self.fixtures.load('error.txt') - return (httplib.FOUND, body, {}, httplib.responses[httplib.FOUND]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_dreamhost.py b/awx/lib/site-packages/libcloud/test/compute/test_dreamhost.py deleted file mode 100644 index d9cef5cb22..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_dreamhost.py +++ /dev/null @@ -1,284 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest -from libcloud.utils.py3 import httplib - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.common.types import InvalidCredsError -from libcloud.compute.drivers.dreamhost import DreamhostNodeDriver -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.secrets import DREAMHOST_PARAMS - - -class DreamhostTest(unittest.TestCase, TestCaseMixin): - - def setUp(self): - DreamhostNodeDriver.connectionCls.conn_classes = ( - None, - DreamhostMockHttp - ) - DreamhostMockHttp.type = None - DreamhostMockHttp.use_param = 'cmd' - self.driver = DreamhostNodeDriver(*DREAMHOST_PARAMS) - - def test_invalid_creds(self): - """ - Tests the error-handling for passing a bad API Key to the DreamHost API - """ - DreamhostMockHttp.type = 'BAD_AUTH' - try: - self.driver.list_nodes() - self.assertTrue( - False) # Above command should have thrown an InvalidCredsException - except InvalidCredsError: - self.assertTrue(True) - - def test_list_nodes(self): - """ - Test list_nodes for DreamHost PS driver. Should return a list of two nodes: - - account_id: 000000 - ip: 75.119.203.51 - memory_mb: 500 - ps: ps22174 - start_date: 2010-02-25 - type: web - - account_id: 000000 - ip: 75.119.203.52 - memory_mb: 1500 - ps: ps22175 - start_date: 2010-02-25 - type: mysql - """ - - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 2) - web_node = nodes[0] - mysql_node = nodes[1] - - # Web node tests - self.assertEqual(web_node.id, 'ps22174') - self.assertEqual(web_node.state, NodeState.UNKNOWN) - self.assertTrue('75.119.203.51' in web_node.public_ips) - self.assertTrue( - 'current_size' in web_node.extra and - web_node.extra['current_size'] == 500 - ) - self.assertTrue( - 'account_id' in web_node.extra and - web_node.extra['account_id'] == 000000 - ) - self.assertTrue( - 'type' in web_node.extra and - web_node.extra['type'] == 'web' - ) - # MySql node tests - self.assertEqual(mysql_node.id, 'ps22175') - self.assertEqual(mysql_node.state, NodeState.UNKNOWN) - self.assertTrue('75.119.203.52' in mysql_node.public_ips) - self.assertTrue( - 'current_size' in mysql_node.extra and - mysql_node.extra['current_size'] == 1500 - ) - self.assertTrue( - 'account_id' in mysql_node.extra and - mysql_node.extra['account_id'] == 000000 - ) - self.assertTrue( - 'type' in mysql_node.extra and - mysql_node.extra['type'] == 'mysql' - ) - - def test_create_node(self): - """ - Test create_node for DreamHost PS driver. - This is not remarkably compatible with libcloud. The DH API allows - users to specify what image they want to create and whether to move - all their data to the (web) PS. It does NOT accept a name, size, or - location. The only information it returns is the PS's context id - Once the PS is ready it will appear in the list generated by list_ps. - """ - new_node = self.driver.create_node( - image=self.driver.list_images()[0], - size=self.driver.list_sizes()[0], - movedata='no', - ) - self.assertEqual(new_node.id, 'ps12345') - self.assertEqual(new_node.state, NodeState.PENDING) - self.assertTrue( - 'type' in new_node.extra and - new_node.extra['type'] == 'web' - ) - - def test_destroy_node(self): - """ - Test destroy_node for DreamHost PS driver - """ - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.destroy_node(node)) - - def test_destroy_node_failure(self): - """ - Test destroy_node failure for DreamHost PS driver - """ - node = self.driver.list_nodes()[0] - - DreamhostMockHttp.type = 'API_FAILURE' - self.assertFalse(self.driver.destroy_node(node)) - - def test_reboot_node(self): - """ - Test reboot_node for DreamHost PS driver. - """ - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.reboot_node(node)) - - def test_reboot_node_failure(self): - """ - Test reboot_node failure for DreamHost PS driver - """ - node = self.driver.list_nodes()[0] - - DreamhostMockHttp.type = 'API_FAILURE' - self.assertFalse(self.driver.reboot_node(node)) - - def test_resize_node(self): - """ - Test resize_node for DreamHost PS driver - """ - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver._resize_node(node, 400)) - - def test_resize_node_failure(self): - """ - Test reboot_node faliure for DreamHost PS driver - """ - node = self.driver.list_nodes()[0] - - DreamhostMockHttp.type = 'API_FAILURE' - self.assertFalse(self.driver._resize_node(node, 400)) - - def test_list_images(self): - """ - Test list_images for DreamHost PS driver. - """ - images = self.driver.list_images() - self.assertEqual(len(images), 2) - self.assertEqual(images[0].id, 'web') - self.assertEqual(images[0].name, 'web') - self.assertEqual(images[1].id, 'mysql') - self.assertEqual(images[1].name, 'mysql') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 5) - - size = [s for s in sizes if s.id == 'default'][0] - self.assertEqual(size.id, 'default') - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.ram, 2300) - self.assertEqual(size.price, 115) - - def test_list_locations(self): - try: - self.driver.list_locations() - except NotImplementedError: - pass - - def test_list_locations_response(self): - self.assertRaises(NotImplementedError, self.driver.list_locations) - - -class DreamhostMockHttp(MockHttp): - - def _BAD_AUTH_dreamhost_ps_list_ps(self, method, url, body, headers): - body = json.dumps({'data': 'invalid_api_key', 'result': 'error'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dreamhost_ps_add_ps(self, method, url, body, headers): - body = json.dumps( - {'data': {'added_web': 'ps12345'}, 'result': 'success'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dreamhost_ps_list_ps(self, method, url, body, headers): - data = [{ - 'account_id': 000000, - 'ip': '75.119.203.51', - 'memory_mb': 500, - 'ps': 'ps22174', - 'start_date': '2010-02-25', - 'type': 'web' - }, - { - 'account_id': 000000, - 'ip': '75.119.203.52', - 'memory_mb': 1500, - 'ps': 'ps22175', - 'start_date': '2010-02-25', - 'type': 'mysql' - }] - result = 'success' - body = json.dumps({'data': data, 'result': result}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dreamhost_ps_list_images(self, method, url, body, headers): - data = [{ - 'description': 'Private web server', - 'image': 'web' - }, - { - 'description': 'Private MySQL server', - 'image': 'mysql' - }] - result = 'success' - body = json.dumps({'data': data, 'result': result}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dreamhost_ps_reboot(self, method, url, body, headers): - body = json.dumps({'data': 'reboot_scheduled', 'result': 'success'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _API_FAILURE_dreamhost_ps_reboot(self, method, url, body, headers): - body = json.dumps({'data': 'no_such_ps', 'result': 'error'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dreamhost_ps_set_size(self, method, url, body, headers): - body = json.dumps( - {'data': {'memory-mb': '500'}, 'result': 'success'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _API_FAILURE_dreamhost_ps_set_size(self, method, url, body, headers): - body = json.dumps( - {'data': 'internal_error_setting_size', 'result': 'error'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dreamhost_ps_remove_ps(self, method, url, body, headers): - body = json.dumps({'data': 'removed_web', 'result': 'success'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _API_FAILURE_dreamhost_ps_remove_ps(self, method, url, body, headers): - body = json.dumps({'data': 'no_such_ps', 'result': 'error'}) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_ec2.py b/awx/lib/site-packages/libcloud/test/compute/test_ec2.py deleted file mode 100644 index 3f531cde29..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_ec2.py +++ /dev/null @@ -1,1682 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import os -import sys -from datetime import datetime - -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.ec2 import EC2NodeDriver -from libcloud.compute.drivers.ec2 import EC2USWestNodeDriver -from libcloud.compute.drivers.ec2 import EC2USWestOregonNodeDriver -from libcloud.compute.drivers.ec2 import EC2EUNodeDriver -from libcloud.compute.drivers.ec2 import EC2APSENodeDriver -from libcloud.compute.drivers.ec2 import EC2APNENodeDriver -from libcloud.compute.drivers.ec2 import EC2APSESydneyNodeDriver -from libcloud.compute.drivers.ec2 import EC2SAEastNodeDriver -from libcloud.compute.drivers.ec2 import NimbusNodeDriver, EucNodeDriver -from libcloud.compute.drivers.ec2 import OutscaleSASNodeDriver -from libcloud.compute.drivers.ec2 import IdempotentParamError -from libcloud.compute.drivers.ec2 import REGION_DETAILS -from libcloud.compute.drivers.ec2 import ExEC2AvailabilityZone -from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation -from libcloud.compute.base import StorageVolume, VolumeSnapshot -from libcloud.compute.types import KeyPairDoesNotExistError - -from libcloud.test import MockHttpTestCase, LibcloudTestCase -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - -from libcloud.test import unittest -from libcloud.test.secrets import EC2_PARAMS - - -null_fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \ - '00:00:00:00:00' - - -class BaseEC2Tests(LibcloudTestCase): - - def test_instantiate_driver_valid_regions(self): - regions = REGION_DETAILS.keys() - regions = [d for d in regions if d != 'nimbus'] - - for region in regions: - EC2NodeDriver(*EC2_PARAMS, **{'region': region}) - - def test_instantiate_driver_invalid_regions(self): - for region in ['invalid', 'nimbus']: - try: - EC2NodeDriver(*EC2_PARAMS, **{'region': region}) - except ValueError: - pass - else: - self.fail('Invalid region, but exception was not thrown') - - -class EC2Tests(LibcloudTestCase, TestCaseMixin): - image_name = 'ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml' - region = 'us-east-1' - - def setUp(self): - EC2MockHttp.test = self - EC2NodeDriver.connectionCls.conn_classes = (None, EC2MockHttp) - EC2MockHttp.use_param = 'Action' - EC2MockHttp.type = None - - self.driver = EC2NodeDriver(*EC2_PARAMS, - **{'region': self.region}) - - def test_create_node(self): - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='foo', image=image, size=size) - self.assertEqual(node.id, 'i-2ba64342') - self.assertEqual(node.name, 'foo') - self.assertEqual(node.extra['tags']['Name'], 'foo') - self.assertEqual(len(node.extra['tags']), 1) - - def test_create_node_with_ex_mincount(self): - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='foo', image=image, size=size, - ex_mincount=1, ex_maxcount=10) - self.assertEqual(node.id, 'i-2ba64342') - self.assertEqual(node.name, 'foo') - self.assertEqual(node.extra['tags']['Name'], 'foo') - self.assertEqual(len(node.extra['tags']), 1) - - def test_create_node_with_metadata(self): - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='foo', - image=image, - size=size, - ex_metadata={'Bar': 'baz', 'Num': '42'}) - self.assertEqual(node.name, 'foo') - self.assertEqual(node.extra['tags']['Name'], 'foo') - self.assertEqual(node.extra['tags']['Bar'], 'baz') - self.assertEqual(node.extra['tags']['Num'], '42') - self.assertEqual(len(node.extra['tags']), 3) - - def test_create_node_idempotent(self): - EC2MockHttp.type = 'idempotent' - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - token = 'testclienttoken' - node = self.driver.create_node(name='foo', image=image, size=size, - ex_clienttoken=token) - self.assertEqual(node.id, 'i-2ba64342') - self.assertEqual(node.extra['client_token'], token) - - # from: http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/index.html?Run_Instance_Idempotency.html - # If you repeat the request with the same client token, but change - # another request parameter, Amazon EC2 returns an - # IdempotentParameterMismatch error. - # In our case, changing the parameter doesn't actually matter since we - # are forcing the error response fixture. - EC2MockHttp.type = 'idempotent_mismatch' - - idem_error = None - # different count - try: - self.driver.create_node(name='foo', image=image, size=size, - ex_mincount='2', ex_maxcount='2', - ex_clienttoken=token) - except IdempotentParamError: - e = sys.exc_info()[1] - idem_error = e - self.assertTrue(idem_error is not None) - - def test_create_node_no_availability_zone(self): - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='foo', image=image, size=size) - location = NodeLocation(0, 'Amazon US N. Virginia', 'US', self.driver) - self.assertEqual(node.id, 'i-2ba64342') - node = self.driver.create_node(name='foo', image=image, size=size, - location=location) - self.assertEqual(node.id, 'i-2ba64342') - self.assertEqual(node.name, 'foo') - - def test_list_nodes(self): - node = self.driver.list_nodes()[0] - public_ips = sorted(node.public_ips) - self.assertEqual(node.id, 'i-4382922a') - self.assertEqual(node.name, node.id) - self.assertEqual(len(node.public_ips), 2) - self.assertEqual(node.extra['launch_time'], - '2013-12-02T11:58:11.000Z') - self.assertTrue('instance_type' in node.extra) - self.assertEqual(node.extra['availability'], 'us-east-1d') - self.assertEqual(node.extra['key_name'], 'fauxkey') - self.assertEqual(node.extra['monitoring'], 'disabled') - self.assertEqual(node.extra['image_id'], 'ami-3215fe5a') - self.assertEqual(len(node.extra['groups']), 2) - self.assertEqual(len(node.extra['block_device_mapping']), 1) - self.assertEqual(node.extra['block_device_mapping'][0]['device_name'], '/dev/sda1') - self.assertEqual(node.extra['block_device_mapping'][0]['ebs']['volume_id'], 'vol-5e312311') - self.assertTrue(node.extra['block_device_mapping'][0]['ebs']['delete']) - - self.assertEqual(public_ips[0], '1.2.3.4') - - nodes = self.driver.list_nodes(ex_node_ids=['i-4382922a', - 'i-8474834a']) - ret_node1 = nodes[0] - ret_node2 = nodes[1] - - self.assertEqual(ret_node1.id, 'i-4382922a') - self.assertEqual(ret_node2.id, 'i-8474834a') - self.assertEqual(ret_node2.name, 'Test Server 2') - self.assertEqual(ret_node2.extra['subnet_id'], 'subnet-5fd9d412') - self.assertEqual(ret_node2.extra['vpc_id'], 'vpc-61dcd30e') - self.assertEqual(ret_node2.extra['tags']['Group'], 'VPC Test') - self.assertEqual(ret_node1.extra['launch_time'], - '2013-12-02T11:58:11.000Z') - self.assertTrue('instance_type' in ret_node1.extra) - self.assertEqual(ret_node2.extra['launch_time'], - '2013-12-02T15:58:29.000Z') - self.assertTrue('instance_type' in ret_node2.extra) - - def test_ex_list_reserved_nodes(self): - node = self.driver.ex_list_reserved_nodes()[0] - self.assertEqual(node.id, '93bbbca2-c500-49d0-9ede-9d8737400498') - self.assertEqual(node.state, 'active') - self.assertEqual(node.extra['instance_type'], 't1.micro') - self.assertEqual(node.extra['availability'], 'us-east-1b') - self.assertEqual(node.extra['start'], '2013-06-18T12:07:53.161Z') - self.assertEqual(node.extra['duration'], 31536000) - self.assertEqual(node.extra['usage_price'], 0.012) - self.assertEqual(node.extra['fixed_price'], 23.0) - self.assertEqual(node.extra['instance_count'], 1) - self.assertEqual(node.extra['description'], 'Linux/UNIX') - self.assertEqual(node.extra['instance_tenancy'], 'default') - self.assertEqual(node.extra['currency_code'], 'USD') - self.assertEqual(node.extra['offering_type'], 'Light Utilization') - - def test_list_location(self): - locations = self.driver.list_locations() - self.assertTrue(len(locations) > 0) - self.assertEqual(locations[0].name, 'eu-west-1a') - self.assertTrue(locations[0].availability_zone is not None) - self.assertTrue(isinstance(locations[0].availability_zone, - ExEC2AvailabilityZone)) - - def test_list_security_groups(self): - groups = self.driver.ex_list_security_groups() - self.assertEqual(groups, ['WebServers', 'RangedPortsBySource']) - - def test_ex_delete_security_group_by_id(self): - group_id = 'sg-443d0a12' - retValue = self.driver.ex_delete_security_group_by_id(group_id) - self.assertTrue(retValue) - - def test_delete_security_group_by_name(self): - group_name = 'WebServers' - retValue = self.driver.ex_delete_security_group_by_name(group_name) - self.assertTrue(retValue) - - def test_ex_delete_security_group(self): - name = 'WebServers' - retValue = self.driver.ex_delete_security_group(name) - self.assertTrue(retValue) - - def test_authorize_security_group(self): - resp = self.driver.ex_authorize_security_group('TestGroup', '22', '22', - '0.0.0.0/0') - self.assertTrue(resp) - - def test_authorize_security_group_ingress(self): - ranges = ['1.1.1.1/32', '2.2.2.2/32'] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges) - self.assertTrue(resp) - groups = [{'group_id': 'sg-949265ff'}] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 23, group_pairs=groups) - self.assertTrue(resp) - - def test_authorize_security_group_egress(self): - ranges = ['1.1.1.1/32', '2.2.2.2/32'] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges) - self.assertTrue(resp) - groups = [{'group_id': 'sg-949265ff'}] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, group_pairs=groups) - self.assertTrue(resp) - - def test_revoke_security_group_ingress(self): - ranges = ['1.1.1.1/32', '2.2.2.2/32'] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges) - self.assertTrue(resp) - groups = [{'group_id': 'sg-949265ff'}] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, group_pairs=groups) - self.assertTrue(resp) - - def test_revoke_security_group_egress(self): - ranges = ['1.1.1.1/32', '2.2.2.2/32'] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges) - self.assertTrue(resp) - groups = [{'group_id': 'sg-949265ff'}] - resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, group_pairs=groups) - self.assertTrue(resp) - - def test_reboot_node(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - ret = self.driver.reboot_node(node) - self.assertTrue(ret) - - def test_ex_start_node(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - ret = self.driver.ex_start_node(node) - self.assertTrue(ret) - - def test_ex_stop_node(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - ret = self.driver.ex_stop_node(node) - self.assertTrue(ret) - - def test_ex_create_node_with_ex_blockdevicemappings(self): - EC2MockHttp.type = 'create_ex_blockdevicemappings' - - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - mappings = [ - {'DeviceName': '/dev/sda1', 'Ebs.VolumeSize': 10}, - {'DeviceName': '/dev/sdb', 'VirtualName': 'ephemeral0'}, - {'DeviceName': '/dev/sdc', 'VirtualName': 'ephemeral1'} - ] - node = self.driver.create_node(name='foo', image=image, size=size, - ex_blockdevicemappings=mappings) - self.assertEqual(node.id, 'i-2ba64342') - - def test_ex_create_node_with_ex_blockdevicemappings_attribute_error(self): - EC2MockHttp.type = 'create_ex_blockdevicemappings' - - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - - mappings = 'this should be a list' - self.assertRaises(AttributeError, self.driver.create_node, name='foo', - image=image, size=size, - ex_blockdevicemappings=mappings) - - mappings = ['this should be a dict'] - self.assertRaises(AttributeError, self.driver.create_node, name='foo', - image=image, size=size, - ex_blockdevicemappings=mappings) - - def test_destroy_node(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - def test_list_sizes(self): - region_old = self.driver.region_name - - names = [ - ('ec2_us_east', 'us-east-1'), - ('ec2_us_west', 'us-west-1'), - ('ec2_eu_west', 'eu-west-1'), - ('ec2_ap_southeast', 'ap-southeast-1'), - ('ec2_ap_northeast', 'ap-northeast-1'), - ('ec2_ap_southeast_2', 'ap-southeast-2') - ] - - for api_name, region_name in names: - self.driver.api_name = api_name - self.driver.region_name = region_name - sizes = self.driver.list_sizes() - - ids = [s.id for s in sizes] - self.assertTrue('t1.micro' in ids) - self.assertTrue('m1.small' in ids) - self.assertTrue('m1.large' in ids) - self.assertTrue('m1.xlarge' in ids) - self.assertTrue('c1.medium' in ids) - self.assertTrue('c1.xlarge' in ids) - self.assertTrue('m2.xlarge' in ids) - self.assertTrue('m2.2xlarge' in ids) - self.assertTrue('m2.4xlarge' in ids) - - if region_name == 'us-east-1': - self.assertEqual(len(sizes), 33) - self.assertTrue('cg1.4xlarge' in ids) - self.assertTrue('cc2.8xlarge' in ids) - self.assertTrue('cr1.8xlarge' in ids) - elif region_name == 'us-west-1': - self.assertEqual(len(sizes), 29) - if region_name == 'us-west-2': - self.assertEqual(len(sizes), 29) - elif region_name == 'ap-southeast-1': - self.assertEqual(len(sizes), 24) - elif region_name == 'ap-southeast-2': - self.assertEqual(len(sizes), 29) - elif region_name == 'eu-west-1': - self.assertEqual(len(sizes), 31) - - self.driver.region_name = region_old - - def test_ex_create_node_with_ex_iam_profile(self): - iamProfile = { - 'id': 'AIDGPMS9RO4H3FEXAMPLE', - 'name': 'Foo', - 'arn': 'arn:aws:iam:...' - } - - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - - EC2MockHttp.type = None - node1 = self.driver.create_node(name='foo', image=image, size=size) - EC2MockHttp.type = 'ex_iam_profile' - node2 = self.driver.create_node(name='bar', image=image, size=size, - ex_iam_profile=iamProfile['name']) - node3 = self.driver.create_node(name='bar', image=image, size=size, - ex_iam_profile=iamProfile['arn']) - - self.assertFalse(node1.extra['iam_profile']) - self.assertEqual(node2.extra['iam_profile'], iamProfile['id']) - self.assertEqual(node3.extra['iam_profile'], iamProfile['id']) - - def test_list_images(self): - images = self.driver.list_images() - - self.assertEqual(len(images), 2) - location = '123456788908/Test Image' - self.assertEqual(images[0].id, 'ami-57ba933a') - self.assertEqual(images[0].name, 'Test Image') - self.assertEqual(images[0].extra['image_location'], location) - self.assertEqual(images[0].extra['architecture'], 'x86_64') - self.assertEqual(len(images[0].extra['block_device_mapping']), 2) - ephemeral = images[0].extra['block_device_mapping'][1]['virtual_name'] - self.assertEqual(ephemeral, 'ephemeral0') - - location = '123456788908/Test Image 2' - self.assertEqual(images[1].id, 'ami-85b2a8ae') - self.assertEqual(images[1].name, 'Test Image 2') - self.assertEqual(images[1].extra['image_location'], location) - self.assertEqual(images[1].extra['architecture'], 'x86_64') - size = images[1].extra['block_device_mapping'][0]['ebs']['volume_size'] - self.assertEqual(size, 20) - - def test_list_images_with_image_ids(self): - EC2MockHttp.type = 'ex_imageids' - images = self.driver.list_images(ex_image_ids=['ami-57ba933a']) - - self.assertEqual(len(images), 1) - self.assertEqual(images[0].name, 'Test Image') - - def test_list_images_with_executable_by(self): - images = self.driver.list_images(ex_executableby='self') - - self.assertEqual(len(images), 2) - - def test_get_image(self): - image = self.driver.get_image('ami-57ba933a') - self.assertEqual(image.id, 'ami-57ba933a') - self.assertEqual(image.name, 'Test Image') - self.assertEqual(image.extra['architecture'], 'x86_64') - self.assertEqual(len(image.extra['block_device_mapping']), 2) - - def test_copy_image(self): - image = self.driver.list_images()[0] - resp = self.driver.copy_image(image, 'us-east-1', - name='Faux Image', - description='Test Image Copy') - self.assertEqual(resp.id, 'ami-4db38224') - - def test_create_image(self): - node = self.driver.list_nodes()[0] - - mapping = [{'VirtualName': None, - 'Ebs': {'VolumeSize': 10, - 'VolumeType': 'standard', - 'DeleteOnTermination': 'true'}, - 'DeviceName': '/dev/sda1'}] - - resp = self.driver.create_image(node, - 'New Image', - description='New EBS Image', - block_device_mapping=mapping) - self.assertEqual(resp.id, 'ami-e9b38280') - - def test_create_image_no_mapping(self): - node = self.driver.list_nodes()[0] - - resp = self.driver.create_image(node, - 'New Image', - description='New EBS Image') - self.assertEqual(resp.id, 'ami-e9b38280') - - def delete_image(self): - images = self.driver.list_images() - image = images[0] - - resp = self.driver.delete_image(image) - self.assertTrue(resp) - - def ex_register_image(self): - mapping = [{'DeviceName': '/dev/sda1', - 'Ebs': {'SnapshotId': 'snap-5ade3e4e'}}] - image = self.driver.ex_register_image(name='Test Image', - root_device_name='/dev/sda1', - description='My Image', - architecture='x86_64', - block_device_mapping=mapping) - self.assertEqual(image.id, 'ami-57c2fb3e') - - def test_ex_list_availability_zones(self): - availability_zones = self.driver.ex_list_availability_zones() - availability_zone = availability_zones[0] - self.assertTrue(len(availability_zones) > 0) - self.assertEqual(availability_zone.name, 'eu-west-1a') - self.assertEqual(availability_zone.zone_state, 'available') - self.assertEqual(availability_zone.region_name, 'eu-west-1') - - def test_list_keypairs(self): - keypairs = self.driver.list_key_pairs() - - self.assertEqual(len(keypairs), 1) - self.assertEqual(keypairs[0].name, 'gsg-keypair') - self.assertEqual(keypairs[0].fingerprint, null_fingerprint) - - # Test old deprecated method - keypairs = self.driver.ex_list_keypairs() - - self.assertEqual(len(keypairs), 1) - self.assertEqual(keypairs[0]['keyName'], 'gsg-keypair') - self.assertEqual(keypairs[0]['keyFingerprint'], null_fingerprint) - - def test_get_key_pair(self): - EC2MockHttp.type = 'get_one' - - key_pair = self.driver.get_key_pair(name='gsg-keypair') - self.assertEqual(key_pair.name, 'gsg-keypair') - - def test_get_key_pair_does_not_exist(self): - EC2MockHttp.type = 'doesnt_exist' - - self.assertRaises(KeyPairDoesNotExistError, self.driver.get_key_pair, - name='test-key-pair') - - def test_create_key_pair(self): - key_pair = self.driver.create_key_pair(name='test-keypair') - - fingerprint = ('1f:51:ae:28:bf:89:e9:d8:1f:25:5d' - ':37:2d:7d:b8:ca:9f:f5:f1:6f') - - self.assertEqual(key_pair.name, 'my-key-pair') - self.assertEqual(key_pair.fingerprint, fingerprint) - self.assertTrue(key_pair.private_key is not None) - - # Test old and deprecated method - key_pair = self.driver.ex_create_keypair(name='test-keypair') - self.assertEqual(key_pair['keyFingerprint'], fingerprint) - self.assertTrue(key_pair['keyMaterial'] is not None) - - def test_ex_describe_all_keypairs(self): - keys = self.driver.ex_describe_all_keypairs() - self.assertEqual(keys, ['gsg-keypair']) - - def test_list_key_pairs(self): - keypair1 = self.driver.list_key_pairs()[0] - - self.assertEqual(keypair1.name, 'gsg-keypair') - self.assertEqual(keypair1.fingerprint, null_fingerprint) - - # Test backward compatibility - keypair2 = self.driver.ex_describe_keypairs('gsg-keypair') - - self.assertEqual(keypair2['keyName'], 'gsg-keypair') - self.assertEqual(keypair2['keyFingerprint'], null_fingerprint) - - def test_delete_key_pair(self): - keypair = self.driver.list_key_pairs()[0] - success = self.driver.delete_key_pair(keypair) - - self.assertTrue(success) - - # Test old and deprecated method - resp = self.driver.ex_delete_keypair('gsg-keypair') - self.assertTrue(resp) - - def test_ex_describe_tags(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - tags = self.driver.ex_describe_tags(resource=node) - - self.assertEqual(len(tags), 3) - self.assertTrue('tag' in tags) - self.assertTrue('owner' in tags) - self.assertTrue('stack' in tags) - - def test_import_key_pair_from_string(self): - path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', - 'dummy_rsa.pub') - - with open(path, 'r') as fp: - key_material = fp.read() - - key = self.driver.import_key_pair_from_string(name='keypair', - key_material=key_material) - self.assertEqual(key.name, 'keypair') - self.assertEqual(key.fingerprint, null_fingerprint) - - # Test old and deprecated method - key = self.driver.ex_import_keypair_from_string('keypair', - key_material) - self.assertEqual(key['keyName'], 'keypair') - self.assertEqual(key['keyFingerprint'], null_fingerprint) - - def test_import_key_pair_from_file(self): - path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', - 'dummy_rsa.pub') - - key = self.driver.import_key_pair_from_file('keypair', path) - self.assertEqual(key.name, 'keypair') - self.assertEqual(key.fingerprint, null_fingerprint) - - # Test old and deprecated method - key = self.driver.ex_import_keypair('keypair', path) - self.assertEqual(key['keyName'], 'keypair') - self.assertEqual(key['keyFingerprint'], null_fingerprint) - - def test_ex_create_tags(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - self.driver.ex_create_tags(node, {'sample': 'tag'}) - - def test_ex_delete_tags(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - self.driver.ex_delete_tags(node, {'sample': 'tag'}) - - def test_ex_describe_addresses_for_node(self): - node1 = Node('i-4382922a', None, None, None, None, self.driver) - ip_addresses1 = self.driver.ex_describe_addresses_for_node(node1) - node2 = Node('i-4382922b', None, None, None, None, self.driver) - ip_addresses2 = sorted( - self.driver.ex_describe_addresses_for_node(node2)) - node3 = Node('i-4382922g', None, None, None, None, self.driver) - ip_addresses3 = sorted( - self.driver.ex_describe_addresses_for_node(node3)) - - self.assertEqual(len(ip_addresses1), 1) - self.assertEqual(ip_addresses1[0], '1.2.3.4') - - self.assertEqual(len(ip_addresses2), 2) - self.assertEqual(ip_addresses2[0], '1.2.3.5') - self.assertEqual(ip_addresses2[1], '1.2.3.6') - - self.assertEqual(len(ip_addresses3), 0) - - def test_ex_describe_addresses(self): - node1 = Node('i-4382922a', None, None, None, None, self.driver) - node2 = Node('i-4382922g', None, None, None, None, self.driver) - nodes_elastic_ips1 = self.driver.ex_describe_addresses([node1]) - nodes_elastic_ips2 = self.driver.ex_describe_addresses([node2]) - - self.assertEqual(len(nodes_elastic_ips1), 1) - self.assertTrue(node1.id in nodes_elastic_ips1) - self.assertEqual(nodes_elastic_ips1[node1.id], ['1.2.3.4']) - - self.assertEqual(len(nodes_elastic_ips2), 1) - self.assertTrue(node2.id in nodes_elastic_ips2) - self.assertEqual(nodes_elastic_ips2[node2.id], []) - - def test_ex_describe_all_addresses(self): - EC2MockHttp.type = 'all_addresses' - elastic_ips1 = self.driver.ex_describe_all_addresses() - elastic_ips2 = self.driver.ex_describe_all_addresses( - only_associated=True) - self.assertEqual('1.2.3.7', elastic_ips1[3].ip) - self.assertEqual('vpc', elastic_ips1[3].domain) - self.assertEqual('eipalloc-992a5cf8', elastic_ips1[3].extra['allocation_id']) - - self.assertEqual(len(elastic_ips2), 2) - self.assertEqual('1.2.3.5', elastic_ips2[1].ip) - self.assertEqual('vpc', elastic_ips2[1].domain) - - def test_ex_allocate_address(self): - elastic_ip = self.driver.ex_allocate_address() - self.assertEqual('192.0.2.1', elastic_ip.ip) - self.assertEqual('standard', elastic_ip.domain) - EC2MockHttp.type = 'vpc' - elastic_ip = self.driver.ex_allocate_address(domain='vpc') - self.assertEqual('192.0.2.2', elastic_ip.ip) - self.assertEqual('vpc', elastic_ip.domain) - self.assertEqual('eipalloc-666d7f04', elastic_ip.extra['allocation_id']) - - def test_ex_release_address(self): - EC2MockHttp.type = 'all_addresses' - elastic_ips = self.driver.ex_describe_all_addresses() - EC2MockHttp.type = '' - ret = self.driver.ex_release_address(elastic_ips[2]) - self.assertTrue(ret) - ret = self.driver.ex_release_address(elastic_ips[0], domain='vpc') - self.assertTrue(ret) - self.assertRaises(AttributeError, - self.driver.ex_release_address, - elastic_ips[0], - domain='bogus') - - def test_ex_associate_address_with_node(self): - node = Node('i-4382922a', None, None, None, None, self.driver) - EC2MockHttp.type = 'all_addresses' - elastic_ips = self.driver.ex_describe_all_addresses() - EC2MockHttp.type = '' - ret1 = self.driver.ex_associate_address_with_node( - node, elastic_ips[2]) - ret2 = self.driver.ex_associate_addresses( - node, elastic_ips[2]) - self.assertEqual(None, ret1) - self.assertEqual(None, ret2) - EC2MockHttp.type = 'vpc' - ret3 = self.driver.ex_associate_address_with_node( - node, elastic_ips[3], domain='vpc') - ret4 = self.driver.ex_associate_addresses( - node, elastic_ips[3], domain='vpc') - self.assertEqual('eipassoc-167a8073', ret3) - self.assertEqual('eipassoc-167a8073', ret4) - self.assertRaises(AttributeError, - self.driver.ex_associate_address_with_node, - node, - elastic_ips[1], - domain='bogus') - - def test_ex_disassociate_address(self): - EC2MockHttp.type = 'all_addresses' - elastic_ips = self.driver.ex_describe_all_addresses() - EC2MockHttp.type = '' - ret = self.driver.ex_disassociate_address(elastic_ips[2]) - self.assertTrue(ret) - # Test a VPC disassociation - ret = self.driver.ex_disassociate_address(elastic_ips[1], - domain='vpc') - self.assertTrue(ret) - self.assertRaises(AttributeError, - self.driver.ex_disassociate_address, - elastic_ips[1], - domain='bogus') - - def test_ex_change_node_size_same_size(self): - size = NodeSize('m1.small', 'Small Instance', - None, None, None, None, driver=self.driver) - node = Node('i-4382922a', None, None, None, None, self.driver, - extra={'instancetype': 'm1.small'}) - - try: - self.driver.ex_change_node_size(node=node, new_size=size) - except ValueError: - pass - else: - self.fail('Same size was passed, but an exception was not thrown') - - def test_ex_change_node_size(self): - size = NodeSize('m1.large', 'Small Instance', - None, None, None, None, driver=self.driver) - node = Node('i-4382922a', None, None, None, None, self.driver, - extra={'instancetype': 'm1.small'}) - - result = self.driver.ex_change_node_size(node=node, new_size=size) - self.assertTrue(result) - - def test_list_volumes(self): - volumes = self.driver.list_volumes() - - self.assertEqual(len(volumes), 3) - - self.assertEqual('vol-10ae5e2b', volumes[0].id) - self.assertEqual(1, volumes[0].size) - self.assertEqual('available', volumes[0].extra['state']) - - self.assertEqual('vol-v24bfh75', volumes[1].id) - self.assertEqual(11, volumes[1].size) - self.assertEqual('available', volumes[1].extra['state']) - - self.assertEqual('vol-b6c851ec', volumes[2].id) - self.assertEqual(8, volumes[2].size) - self.assertEqual('in-use', volumes[2].extra['state']) - self.assertEqual('i-d334b4b3', volumes[2].extra['instance_id']) - self.assertEqual('/dev/sda1', volumes[2].extra['device']) - - def test_create_volume(self): - location = self.driver.list_locations()[0] - vol = self.driver.create_volume(10, 'vol', location) - - self.assertEqual(10, vol.size) - self.assertEqual('vol', vol.name) - self.assertEqual('creating', vol.extra['state']) - self.assertTrue(isinstance(vol.extra['create_time'], datetime)) - - def test_destroy_volume(self): - vol = StorageVolume(id='vol-4282672b', name='test', - size=10, driver=self.driver) - - retValue = self.driver.destroy_volume(vol) - self.assertTrue(retValue) - - def test_attach(self): - vol = StorageVolume(id='vol-4282672b', name='test', - size=10, driver=self.driver) - - node = Node('i-4382922a', None, None, None, None, self.driver) - retValue = self.driver.attach_volume(node, vol, '/dev/sdh') - - self.assertTrue(retValue) - - def test_detach(self): - vol = StorageVolume(id='vol-4282672b', name='test', - size=10, driver=self.driver) - - retValue = self.driver.detach_volume(vol) - self.assertTrue(retValue) - - def test_create_volume_snapshot(self): - vol = StorageVolume(id='vol-4282672b', name='test', - size=10, driver=self.driver) - snap = self.driver.create_volume_snapshot( - vol, 'Test snapshot') - self.assertEqual('snap-a7cb2hd9', snap.id) - self.assertEqual(vol.size, snap.size) - self.assertEqual('Test snapshot', snap.extra['name']) - self.assertEqual(vol.id, snap.extra['volume_id']) - self.assertEqual('pending', snap.extra['state']) - - def test_list_snapshots(self): - snaps = self.driver.list_snapshots() - - self.assertEqual(len(snaps), 2) - - self.assertEqual('snap-428abd35', snaps[0].id) - self.assertEqual('vol-e020df80', snaps[0].extra['volume_id']) - self.assertEqual(30, snaps[0].size) - self.assertEqual('Daily Backup', snaps[0].extra['description']) - - self.assertEqual('snap-18349159', snaps[1].id) - self.assertEqual('vol-b5a2c1v9', snaps[1].extra['volume_id']) - self.assertEqual(15, snaps[1].size) - self.assertEqual('Weekly backup', snaps[1].extra['description']) - self.assertEqual('DB Backup 1', snaps[1].extra['name']) - - def test_destroy_snapshot(self): - snap = VolumeSnapshot(id='snap-428abd35', size=10, driver=self.driver) - resp = snap.destroy() - self.assertTrue(resp) - - def test_ex_modify_image_attribute(self): - images = self.driver.list_images() - image = images[0] - - data = {'LaunchPermission.Add.1.Group': 'all'} - resp = self.driver.ex_modify_image_attribute(image, data) - self.assertTrue(resp) - - def test_create_node_ex_security_groups(self): - EC2MockHttp.type = 'ex_security_groups' - - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - - security_groups = ['group1', 'group2'] - - # Old, deprecated argument name - self.driver.create_node(name='foo', image=image, size=size, - ex_securitygroup=security_groups) - - # New argument name - self.driver.create_node(name='foo', image=image, size=size, - ex_security_groups=security_groups) - - # Test old and new arguments are mutually exclusive - self.assertRaises(ValueError, self.driver.create_node, - name='foo', image=image, size=size, - ex_securitygroup=security_groups, - ex_security_groups=security_groups) - - def test_ex_get_metadata_for_node(self): - image = NodeImage(id='ami-be3adfd7', - name=self.image_name, - driver=self.driver) - size = NodeSize('m1.small', 'Small Instance', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='foo', - image=image, - size=size, - ex_metadata={'Bar': 'baz', 'Num': '42'}) - - metadata = self.driver.ex_get_metadata_for_node(node) - self.assertEqual(metadata['Name'], 'foo') - self.assertEqual(metadata['Bar'], 'baz') - self.assertEqual(metadata['Num'], '42') - self.assertEqual(len(metadata), 3) - - def test_ex_get_limits(self): - limits = self.driver.ex_get_limits() - - expected = {'max-instances': 20, 'vpc-max-elastic-ips': 5, - 'max-elastic-ips': 5} - self.assertEqual(limits['resource'], expected) - - def test_ex_create_security_group(self): - group = self.driver.ex_create_security_group("WebServers", - "Rules to protect web nodes", - "vpc-143cab4") - - self.assertEqual(group["group_id"], "sg-52e2f530") - - def test_ex_list_networks(self): - vpcs = self.driver.ex_list_networks() - - self.assertEqual(len(vpcs), 2) - - self.assertEqual('vpc-532335e1', vpcs[0].id) - self.assertEqual('vpc-532335e1', vpcs[0].name) - self.assertEqual('192.168.51.0/24', vpcs[0].cidr_block) - self.assertEqual('available', vpcs[0].extra['state']) - self.assertEqual('dopt-7eded312', vpcs[0].extra['dhcp_options_id']) - - self.assertEqual('vpc-62ded30e', vpcs[1].id) - self.assertEqual('Test VPC', vpcs[1].name) - self.assertEqual('192.168.52.0/24', vpcs[1].cidr_block) - self.assertEqual('available', vpcs[1].extra['state']) - self.assertEqual('dopt-7eded312', vpcs[1].extra['dhcp_options_id']) - - def test_ex_list_networks_network_ids(self): - EC2MockHttp.type = 'network_ids' - network_ids = ['vpc-532335e1'] - - # We assert in the mock http method - self.driver.ex_list_networks(network_ids=network_ids) - - def test_ex_list_networks_filters(self): - EC2MockHttp.type = 'filters' - filters = {'dhcp-options-id': 'dopt-7eded312', # matches two networks - 'cidr': '192.168.51.0/24'} # matches one network - - # We assert in the mock http method - self.driver.ex_list_networks(filters=filters) - - def test_ex_create_network(self): - vpc = self.driver.ex_create_network('192.168.55.0/24', - name='Test VPC', - instance_tenancy='default') - - self.assertEqual('vpc-ad3527cf', vpc.id) - self.assertEqual('192.168.55.0/24', vpc.cidr_block) - self.assertEqual('pending', vpc.extra['state']) - - def test_ex_delete_network(self): - vpcs = self.driver.ex_list_networks() - vpc = vpcs[0] - - resp = self.driver.ex_delete_network(vpc) - self.assertTrue(resp) - - def test_ex_list_subnets(self): - subnets = self.driver.ex_list_subnets() - - self.assertEqual(len(subnets), 2) - - self.assertEqual('subnet-ce0e7ce5', subnets[0].id) - self.assertEqual('available', subnets[0].state) - self.assertEqual(123, subnets[0].extra['available_ips']) - - self.assertEqual('subnet-ce0e7ce6', subnets[1].id) - self.assertEqual('available', subnets[1].state) - self.assertEqual(59, subnets[1].extra['available_ips']) - - def test_ex_create_subnet(self): - subnet = self.driver.ex_create_subnet('vpc-532135d1', - '192.168.51.128/26', - 'us-east-1b', - name='Test Subnet') - - self.assertEqual('subnet-ce0e7ce6', subnet.id) - self.assertEqual('pending', subnet.state) - self.assertEqual('vpc-532135d1', subnet.extra['vpc_id']) - - def test_ex_delete_subnet(self): - subnet = self.driver.ex_list_subnets()[0] - resp = self.driver.ex_delete_subnet(subnet=subnet) - self.assertTrue(resp) - - def test_ex_get_console_output(self): - node = self.driver.list_nodes()[0] - resp = self.driver.ex_get_console_output(node) - self.assertEqual('Test String', resp['output']) - - def test_ex_list_network_interfaces(self): - interfaces = self.driver.ex_list_network_interfaces() - - self.assertEqual(len(interfaces), 2) - - self.assertEqual('eni-18e6c05e', interfaces[0].id) - self.assertEqual('in-use', interfaces[0].state) - self.assertEqual('0e:6e:df:72:78:af', - interfaces[0].extra['mac_address']) - - self.assertEqual('eni-83e3c5c5', interfaces[1].id) - self.assertEqual('in-use', interfaces[1].state) - self.assertEqual('0e:93:0b:e9:e9:c4', - interfaces[1].extra['mac_address']) - - def test_ex_create_network_interface(self): - subnet = self.driver.ex_list_subnets()[0] - interface = self.driver.ex_create_network_interface( - subnet, - name='Test Interface', - description='My Test') - - self.assertEqual('eni-2b36086d', interface.id) - self.assertEqual('pending', interface.state) - self.assertEqual('0e:bd:49:3e:11:74', interface.extra['mac_address']) - - def test_ex_delete_network_interface(self): - interface = self.driver.ex_list_network_interfaces()[0] - resp = self.driver.ex_delete_network_interface(interface) - self.assertTrue(resp) - - def test_ex_attach_network_interface_to_node(self): - node = self.driver.list_nodes()[0] - interface = self.driver.ex_list_network_interfaces()[0] - resp = self.driver.ex_attach_network_interface_to_node(interface, - node, 1) - self.assertTrue(resp) - - def test_ex_detach_network_interface(self): - resp = self.driver.ex_detach_network_interface('eni-attach-2b588b47') - self.assertTrue(resp) - - def test_ex_list_internet_gateways(self): - gateways = self.driver.ex_list_internet_gateways() - - self.assertEqual(len(gateways), 2) - - self.assertEqual('igw-84dd3ae1', gateways[0].id) - self.assertEqual('igw-7fdae215', gateways[1].id) - self.assertEqual('available', gateways[1].state) - self.assertEqual('vpc-62cad41e', gateways[1].vpc_id) - - def test_ex_create_internet_gateway(self): - gateway = self.driver.ex_create_internet_gateway() - - self.assertEqual('igw-13ac2b36', gateway.id) - - def test_ex_delete_internet_gateway(self): - gateway = self.driver.ex_list_internet_gateways()[0] - resp = self.driver.ex_delete_internet_gateway(gateway) - self.assertTrue(resp) - - def test_ex_attach_internet_gateway(self): - gateway = self.driver.ex_list_internet_gateways()[0] - network = self.driver.ex_list_networks()[0] - resp = self.driver.ex_attach_internet_gateway(gateway, network) - self.assertTrue(resp) - - def test_ex_detach_internet_gateway(self): - gateway = self.driver.ex_list_internet_gateways()[0] - network = self.driver.ex_list_networks()[0] - resp = self.driver.ex_detach_internet_gateway(gateway, network) - self.assertTrue(resp) - - -class EC2USWest1Tests(EC2Tests): - region = 'us-west-1' - - -class EC2USWest2Tests(EC2Tests): - region = 'us-west-2' - - -class EC2EUWestTests(EC2Tests): - region = 'eu-west-1' - - -class EC2APSE1Tests(EC2Tests): - region = 'ap-southeast-1' - - -class EC2APNETests(EC2Tests): - region = 'ap-northeast-1' - - -class EC2APSE2Tests(EC2Tests): - region = 'ap-southeast-2' - - -class EC2SAEastTests(EC2Tests): - region = 'sa-east-1' - - -# Tests for the old, deprecated way of instantiating a driver. -class EC2OldStyleModelTests(EC2Tests): - driver_klass = EC2USWestNodeDriver - - def setUp(self): - EC2MockHttp.test = self - EC2NodeDriver.connectionCls.conn_classes = (None, EC2MockHttp) - EC2MockHttp.use_param = 'Action' - EC2MockHttp.type = None - - self.driver = self.driver_klass(*EC2_PARAMS) - - -class EC2USWest1OldStyleModelTests(EC2OldStyleModelTests): - driver_klass = EC2USWestNodeDriver - - -class EC2USWest2OldStyleModelTests(EC2OldStyleModelTests): - driver_klass = EC2USWestOregonNodeDriver - - -class EC2EUWestOldStyleModelTests(EC2OldStyleModelTests): - driver_klass = EC2EUNodeDriver - - -class EC2APSE1OldStyleModelTests(EC2OldStyleModelTests): - driver_klass = EC2APSENodeDriver - - -class EC2APNEOldStyleModelTests(EC2OldStyleModelTests): - driver_klass = EC2APNENodeDriver - - -class EC2APSE2OldStyleModelTests(EC2OldStyleModelTests): - driver_klass = EC2APSESydneyNodeDriver - - -class EC2SAEastOldStyleModelTests(EC2OldStyleModelTests): - driver_klass = EC2SAEastNodeDriver - - -class EC2MockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('ec2') - - def _DescribeInstances(self, method, url, body, headers): - body = self.fixtures.load('describe_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeReservedInstances(self, method, url, body, headers): - body = self.fixtures.load('describe_reserved_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeAvailabilityZones(self, method, url, body, headers): - body = self.fixtures.load('describe_availability_zones.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _RebootInstances(self, method, url, body, headers): - body = self.fixtures.load('reboot_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _StartInstances(self, method, url, body, headers): - body = self.fixtures.load('start_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _StopInstances(self, method, url, body, headers): - body = self.fixtures.load('stop_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeSecurityGroups(self, method, url, body, headers): - body = self.fixtures.load('describe_security_groups.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteSecurityGroup(self, method, url, body, headers): - body = self.fixtures.load('delete_security_group.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _AuthorizeSecurityGroupIngress(self, method, url, body, headers): - body = self.fixtures.load('authorize_security_group_ingress.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeImages(self, method, url, body, headers): - body = self.fixtures.load('describe_images.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _RegisterImages(self, method, url, body, headers): - body = self.fixtures.load('register_image.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ex_imageids_DescribeImages(self, method, url, body, headers): - body = self.fixtures.load('describe_images_ex_imageids.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _RunInstances(self, method, url, body, headers): - body = self.fixtures.load('run_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ex_security_groups_RunInstances(self, method, url, body, headers): - self.assertUrlContainsQueryParams(url, {'SecurityGroup.1': 'group1'}) - self.assertUrlContainsQueryParams(url, {'SecurityGroup.2': 'group2'}) - - body = self.fixtures.load('run_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _create_ex_blockdevicemappings_RunInstances(self, method, url, body, headers): - expected_params = { - 'BlockDeviceMapping.1.DeviceName': '/dev/sda1', - 'BlockDeviceMapping.1.Ebs.VolumeSize': '10', - 'BlockDeviceMapping.2.DeviceName': '/dev/sdb', - 'BlockDeviceMapping.2.VirtualName': 'ephemeral0', - 'BlockDeviceMapping.3.DeviceName': '/dev/sdc', - 'BlockDeviceMapping.3.VirtualName': 'ephemeral1' - } - self.assertUrlContainsQueryParams(url, expected_params) - - body = self.fixtures.load('run_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _idempotent_RunInstances(self, method, url, body, headers): - body = self.fixtures.load('run_instances_idem.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _idempotent_mismatch_RunInstances(self, method, url, body, headers): - body = self.fixtures.load('run_instances_idem_mismatch.xml') - return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.BAD_REQUEST]) - - def _ex_iam_profile_RunInstances(self, method, url, body, headers): - body = self.fixtures.load('run_instances_iam_profile.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _TerminateInstances(self, method, url, body, headers): - body = self.fixtures.load('terminate_instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeKeyPairs(self, method, url, body, headers): - body = self.fixtures.load('describe_key_pairs.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _get_one_DescribeKeyPairs(self, method, url, body, headers): - self.assertUrlContainsQueryParams(url, {'KeyName': 'gsg-keypair'}) - - body = self.fixtures.load('describe_key_pairs.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _doesnt_exist_DescribeKeyPairs(self, method, url, body, headers): - body = self.fixtures.load('describe_key_pairs_doesnt_exist.xml') - return (httplib.BAD_REQUEST, body, {}, - httplib.responses[httplib.BAD_REQUEST]) - - def _CreateKeyPair(self, method, url, body, headers): - body = self.fixtures.load('create_key_pair.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ImportKeyPair(self, method, url, body, headers): - body = self.fixtures.load('import_key_pair.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeTags(self, method, url, body, headers): - body = self.fixtures.load('describe_tags.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateTags(self, method, url, body, headers): - body = self.fixtures.load('create_tags.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteTags(self, method, url, body, headers): - body = self.fixtures.load('delete_tags.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeAddresses(self, method, url, body, headers): - body = self.fixtures.load('describe_addresses_multi.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _AllocateAddress(self, method, url, body, headers): - body = self.fixtures.load('allocate_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _vpc_AllocateAddress(self, method, url, body, headers): - body = self.fixtures.load('allocate_vpc_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _AssociateAddress(self, method, url, body, headers): - body = self.fixtures.load('associate_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _vpc_AssociateAddress(self, method, url, body, headers): - body = self.fixtures.load('associate_vpc_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DisassociateAddress(self, method, url, body, headers): - body = self.fixtures.load('disassociate_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ReleaseAddress(self, method, url, body, headers): - body = self.fixtures.load('release_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _all_addresses_DescribeAddresses(self, method, url, body, headers): - body = self.fixtures.load('describe_addresses_all.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _WITH_TAGS_DescribeAddresses(self, method, url, body, headers): - body = self.fixtures.load('describe_addresses_multi.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ModifyInstanceAttribute(self, method, url, body, headers): - body = self.fixtures.load('modify_instance_attribute.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _idempotent_CreateTags(self, method, url, body, headers): - body = self.fixtures.load('create_tags.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateVolume(self, method, url, body, headers): - body = self.fixtures.load('create_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteVolume(self, method, url, body, headers): - body = self.fixtures.load('delete_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _AttachVolume(self, method, url, body, headers): - body = self.fixtures.load('attach_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DetachVolume(self, method, url, body, headers): - body = self.fixtures.load('detach_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeVolumes(self, method, url, body, headers): - body = self.fixtures.load('describe_volumes.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateSnapshot(self, method, url, body, headers): - body = self.fixtures.load('create_snapshot.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeSnapshots(self, method, url, body, headers): - body = self.fixtures.load('describe_snapshots.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteSnapshot(self, method, url, body, headers): - body = self.fixtures.load('delete_snapshot.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CopyImage(self, method, url, body, headers): - body = self.fixtures.load('copy_image.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateImage(self, method, url, body, headers): - body = self.fixtures.load('create_image.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeregisterImage(self, method, url, body, headers): - body = self.fixtures.load('deregister_image.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteKeyPair(self, method, url, body, headers): - self.assertUrlContainsQueryParams(url, {'KeyName': 'gsg-keypair'}) - - body = self.fixtures.load('delete_key_pair.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ModifyImageAttribute(self, method, url, body, headers): - body = self.fixtures.load('modify_image_attribute.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeAccountAttributes(self, method, url, body, headers): - body = self.fixtures.load('describe_account_attributes.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateSecurityGroup(self, method, url, body, headers): - body = self.fixtures.load('create_security_group.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeVpcs(self, method, url, body, headers): - body = self.fixtures.load('describe_vpcs.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _network_ids_DescribeVpcs(self, method, url, body, headers): - expected_params = { - 'VpcId.1': 'vpc-532335e1' - } - self.assertUrlContainsQueryParams(url, expected_params) - - body = self.fixtures.load('describe_vpcs.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _filters_DescribeVpcs(self, method, url, body, headers): - expected_params_1 = { - 'Filter.1.Name': 'dhcp-options-id', - 'Filter.1.Value.1': 'dopt-7eded312', - 'Filter.2.Name': 'cidr', - 'Filter.2.Value.1': '192.168.51.0/24' - } - - expected_params_2 = { - 'Filter.1.Name': 'cidr', - 'Filter.1.Value.1': '192.168.51.0/24', - 'Filter.2.Name': 'dhcp-options-id', - 'Filter.2.Value.1': 'dopt-7eded312' - } - - try: - self.assertUrlContainsQueryParams(url, expected_params_1) - except AssertionError: - # dict ordering is not guaranteed - self.assertUrlContainsQueryParams(url, expected_params_2) - - body = self.fixtures.load('describe_vpcs.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateVpc(self, method, url, body, headers): - body = self.fixtures.load('create_vpc.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteVpc(self, method, url, body, headers): - body = self.fixtures.load('delete_vpc.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeSubnets(self, method, url, body, headers): - body = self.fixtures.load('describe_subnets.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateSubnet(self, method, url, body, headers): - body = self.fixtures.load('create_subnet.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteSubnet(self, method, url, body, headers): - body = self.fixtures.load('delete_subnet.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GetConsoleOutput(self, method, url, body, headers): - body = self.fixtures.load('get_console_output.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeNetworkInterfaces(self, method, url, body, headers): - body = self.fixtures.load('describe_network_interfaces.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateNetworkInterface(self, method, url, body, headers): - body = self.fixtures.load('create_network_interface.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteNetworkInterface(self, method, url, body, headers): - body = self.fixtures.load('delete_network_interface.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _AttachNetworkInterface(self, method, url, body, headers): - body = self.fixtures.load('attach_network_interface.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DetachNetworkInterface(self, method, url, body, headers): - body = self.fixtures.load('detach_network_interface.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DescribeInternetGateways(self, method, url, body, headers): - body = self.fixtures.load('describe_internet_gateways.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CreateInternetGateway(self, method, url, body, headers): - body = self.fixtures.load('create_internet_gateway.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DeleteInternetGateway(self, method, url, body, headers): - body = self.fixtures.load('delete_internet_gateway.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _AttachInternetGateway(self, method, url, body, headers): - body = self.fixtures.load('attach_internet_gateway.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DetachInternetGateway(self, method, url, body, headers): - body = self.fixtures.load('detach_internet_gateway.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -class EucMockHttp(EC2MockHttp): - fixtures = ComputeFileFixtures('ec2') - - def _services_Eucalyptus_DescribeInstances(self, method, url, body, - headers): - return self._DescribeInstances(method, url, body, headers) - - def _services_Eucalyptus_DescribeImages(self, method, url, body, - headers): - return self._DescribeImages(method, url, body, headers) - - def _services_Eucalyptus_DescribeAddresses(self, method, url, body, - headers): - return self._DescribeAddresses(method, url, body, headers) - - def _services_Eucalyptus_RebootInstances(self, method, url, body, - headers): - return self._RebootInstances(method, url, body, headers) - - def _services_Eucalyptus_TerminateInstances(self, method, url, body, - headers): - return self._TerminateInstances(method, url, body, headers) - - def _services_Eucalyptus_RunInstances(self, method, url, body, - headers): - return self._RunInstances(method, url, body, headers) - - def _services_Eucalyptus_CreateTags(self, method, url, body, - headers): - return self._CreateTags(method, url, body, headers) - - def _services_Eucalyptus_DescribeInstanceTypes(self, method, url, body, - headers): - body = self.fixtures.load('describe_instance_types.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -class NimbusTests(EC2Tests): - - def setUp(self): - NimbusNodeDriver.connectionCls.conn_classes = (None, EC2MockHttp) - EC2MockHttp.use_param = 'Action' - EC2MockHttp.type = None - self.driver = NimbusNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1], - host='some.nimbuscloud.com') - - def test_ex_describe_addresses_for_node(self): - # overridden from EC2Tests -- Nimbus doesn't support elastic IPs. - node = Node('i-4382922a', None, None, None, None, self.driver) - ip_addresses = self.driver.ex_describe_addresses_for_node(node) - self.assertEqual(len(ip_addresses), 0) - - def test_ex_describe_addresses(self): - # overridden from EC2Tests -- Nimbus doesn't support elastic IPs. - node = Node('i-4382922a', None, None, None, None, self.driver) - nodes_elastic_ips = self.driver.ex_describe_addresses([node]) - - self.assertEqual(len(nodes_elastic_ips), 1) - self.assertEqual(len(nodes_elastic_ips[node.id]), 0) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - - ids = [s.id for s in sizes] - self.assertTrue('m1.small' in ids) - self.assertTrue('m1.large' in ids) - self.assertTrue('m1.xlarge' in ids) - - def test_list_nodes(self): - # overridden from EC2Tests -- Nimbus doesn't support elastic IPs. - node = self.driver.list_nodes()[0] - self.assertExecutedMethodCount(0) - public_ips = node.public_ips - self.assertEqual(node.id, 'i-4382922a') - self.assertEqual(len(node.public_ips), 1) - self.assertEqual(public_ips[0], '1.2.3.4') - self.assertEqual(node.extra['tags'], {}) - - node = self.driver.list_nodes()[1] - self.assertExecutedMethodCount(0) - public_ips = node.public_ips - self.assertEqual(node.id, 'i-8474834a') - self.assertEqual(len(node.public_ips), 1) - self.assertEqual(public_ips[0], '1.2.3.5') - self.assertEqual(node.extra['tags'], - {'Name': 'Test Server 2', 'Group': 'VPC Test'}) - - def test_ex_create_tags(self): - # Nimbus doesn't support creating tags so this one should be a - # passthrough - node = self.driver.list_nodes()[0] - self.driver.ex_create_tags(resource=node, tags={'foo': 'bar'}) - self.assertExecutedMethodCount(0) - - -class EucTests(LibcloudTestCase, TestCaseMixin): - - def setUp(self): - EucNodeDriver.connectionCls.conn_classes = (None, EucMockHttp) - EC2MockHttp.use_param = 'Action' - EC2MockHttp.type = None - self.driver = EucNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1], - host='some.eucalyptus.com', api_version='3.4.1') - - def test_list_locations_response(self): - try: - self.driver.list_locations() - except Exception: - pass - else: - self.fail('Exception was not thrown') - - def test_list_location(self): - pass - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - ids = [s.id for s in sizes] - self.assertEqual(len(ids), 18) - self.assertTrue('t1.micro' in ids) - self.assertTrue('m1.medium' in ids) - self.assertTrue('m3.xlarge' in ids) - - -class OutscaleTests(EC2Tests): - - def setUp(self): - OutscaleSASNodeDriver.connectionCls.conn_classes = (None, EC2MockHttp) - EC2MockHttp.use_param = 'Action' - EC2MockHttp.type = None - self.driver = OutscaleSASNodeDriver(key=EC2_PARAMS[0], - secret=EC2_PARAMS[1], - host='some.outscalecloud.com') - - def test_ex_create_network(self): - # overridden from EC2Tests -- Outscale don't support instance_tenancy - vpc = self.driver.ex_create_network('192.168.55.0/24', - name='Test VPC') - - self.assertEqual('vpc-ad3527cf', vpc.id) - self.assertEqual('192.168.55.0/24', vpc.cidr_block) - self.assertEqual('pending', vpc.extra['state']) - - def test_ex_copy_image(self): - # overridden from EC2Tests -- Outscale does not support copying images - image = self.driver.list_images()[0] - try: - self.driver.ex_copy_image('us-east-1', image, - name='Faux Image', - description='Test Image Copy') - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - def test_ex_get_limits(self): - # overridden from EC2Tests -- Outscale does not support getting limits - try: - self.driver.ex_get_limits() - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - def test_ex_create_network_interface(self): - # overridden from EC2Tests -- Outscale don't allow creating interfaces - subnet = self.driver.ex_list_subnets()[0] - try: - self.driver.ex_create_network_interface( - subnet, - name='Test Interface', - description='My Test') - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - def test_ex_delete_network_interface(self): - # overridden from EC2Tests -- Outscale don't allow deleting interfaces - interface = self.driver.ex_list_network_interfaces()[0] - try: - self.driver.ex_delete_network_interface(interface) - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - def test_ex_attach_network_interface_to_node(self): - # overridden from EC2Tests -- Outscale don't allow attaching interfaces - node = self.driver.list_nodes()[0] - interface = self.driver.ex_list_network_interfaces()[0] - try: - self.driver.ex_attach_network_interface_to_node(interface, node, 1) - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - def test_ex_detach_network_interface(self): - # overridden from EC2Tests -- Outscale don't allow detaching interfaces - try: - self.driver.ex_detach_network_interface('eni-attach-2b588b47') - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - - ids = [s.id for s in sizes] - self.assertTrue('m1.small' in ids) - self.assertTrue('m1.large' in ids) - self.assertTrue('m1.xlarge' in ids) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_ecp.py b/awx/lib/site-packages/libcloud/test/compute/test_ecp.py deleted file mode 100644 index c39875c5a8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_ecp.py +++ /dev/null @@ -1,131 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.ecp import ECPNodeDriver -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - -from libcloud.test.secrets import ECP_PARAMS - - -class ECPTests(unittest.TestCase, TestCaseMixin): - - def setUp(self): - ECPNodeDriver.connectionCls.conn_classes = (None, - ECPMockHttp) - self.driver = ECPNodeDriver(*ECP_PARAMS) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 2) - node = nodes[0] - self.assertEqual(node.id, '1') - self.assertEqual(node.name, 'dummy-1') - self.assertEqual(node.public_ips[0], "42.78.124.75") - self.assertEqual(node.state, NodeState.RUNNING) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 3) - size = sizes[0] - self.assertEqual(size.id, '1') - self.assertEqual(size.ram, 512) - self.assertEqual(size.disk, 0) - self.assertEqual(size.bandwidth, 0) - self.assertEqual(size.price, 0) - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), 2) - self.assertEqual( - images[0].name, "centos54: AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2") - self.assertEqual(images[0].id, "1") - - name = "centos54 two: AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2" - self.assertEqual(images[1].name, name) - self.assertEqual(images[1].id, "2") - - def test_reboot_node(self): - # Raises exception on failure - node = self.driver.list_nodes()[0] - self.driver.reboot_node(node) - - def test_destroy_node(self): - # Raises exception on failure - node = self.driver.list_nodes()[0] - self.driver.destroy_node(node) - - def test_create_node(self): - # Raises exception on failure - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node( - name="api.ivan.net.nz", image=image, size=size) - self.assertEqual(node.name, "api.ivan.net.nz") - self.assertEqual(node.id, "1234") - - -class ECPMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('ecp') - - def _modules_hosting(self, method, url, body, headers): - headers = {} - headers['set-cookie'] = 'vcloud-token=testtoken' - body = 'Anything' - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _rest_hosting_vm_1(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('vm_1_get.json') - if method == 'POST': - if body.find('delete', 0): - body = self.fixtures.load('vm_1_action_delete.json') - if body.find('stop', 0): - body = self.fixtures.load('vm_1_action_stop.json') - if body.find('start', 0): - body = self.fixtures.load('vm_1_action_start.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_hosting_vm(self, method, url, body, headers): - if method == 'PUT': - body = self.fixtures.load('vm_put.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_hosting_vm_list(self, method, url, body, headers): - body = self.fixtures.load('vm_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_hosting_htemplate_list(self, method, url, body, headers): - body = self.fixtures.load('htemplate_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_hosting_network_list(self, method, url, body, headers): - body = self.fixtures.load('network_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_hosting_ptemplate_list(self, method, url, body, headers): - body = self.fixtures.load('ptemplate_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_elasticstack.py b/awx/lib/site-packages/libcloud/test/compute/test_elasticstack.py deleted file mode 100644 index 31896c864e..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_elasticstack.py +++ /dev/null @@ -1,264 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -from libcloud.utils.py3 import httplib - -from libcloud.compute.base import Node -from libcloud.compute.drivers.elasticstack import ElasticStackException -from libcloud.compute.drivers.elastichosts import \ - ElasticHostsNodeDriver as ElasticHosts -from libcloud.compute.drivers.skalicloud import \ - SkaliCloudNodeDriver as SkaliCloud -from libcloud.compute.drivers.serverlove import \ - ServerLoveNodeDriver as ServerLove -from libcloud.common.types import InvalidCredsError, MalformedResponseError - -from libcloud.test import MockHttp, unittest -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class ElasticStackTestCase(object): - - def setUp(self): - # Re-use ElasticHosts fixtures for the base ElasticStack platform tests - """ElasticStack.type = Provider.ELASTICHOSTS - ElasticStack.api_name = 'elastichosts' - - ElasticStackBaseConnection.host = 'test.com' - ElasticStack.connectionCls.conn_classes = (None, - ElasticStackMockHttp) - ElasticStack._standard_drives = ElasticHosts._standard_drives - - self.driver = ElasticStack('foo', 'bar') - """ - self.mockHttp = ElasticStackMockHttp - self.mockHttp.type = None - - self.node = Node(id=72258, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - - def test_invalid_creds(self): - self.mockHttp.type = 'UNAUTHORIZED' - try: - self.driver.list_nodes() - except InvalidCredsError: - e = sys.exc_info()[1] - self.assertEqual(True, isinstance(e, InvalidCredsError)) - else: - self.fail('test should have thrown') - - def test_malformed_response(self): - self.mockHttp.type = 'MALFORMED' - try: - self.driver.list_nodes() - except MalformedResponseError: - pass - else: - self.fail('test should have thrown') - - def test_parse_error(self): - self.mockHttp.type = 'PARSE_ERROR' - try: - self.driver.list_nodes() - except Exception: - e = sys.exc_info()[1] - self.assertTrue(str(e).find('X-Elastic-Error') != -1) - else: - self.fail('test should have thrown') - - def test_ex_set_node_configuration(self): - success = self.driver.ex_set_node_configuration(node=self.node, - name='name', - cpu='2') - self.assertTrue(success) - - def test_ex_set_node_configuration_invalid_keys(self): - try: - self.driver.ex_set_node_configuration(node=self.node, foo='bar') - except ElasticStackException: - pass - else: - self.fail( - 'Invalid option specified, but an exception was not thrown') - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertTrue(isinstance(nodes, list)) - self.assertEqual(len(nodes), 1) - - node = nodes[0] - self.assertEqual(node.public_ips[0], "1.2.3.4") - self.assertEqual(node.public_ips[1], "1.2.3.5") - self.assertEqual(node.extra['smp'], 1) - self.assertEqual( - node.extra['ide:0:0'], "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3") - - def test_list_sizes(self): - images = self.driver.list_sizes() - self.assertEqual(len(images), 6) - image = [i for i in images if i.id == 'small'][0] - self.assertEqual(image.id, 'small') - self.assertEqual(image.name, 'Small instance') - self.assertEqual(image.cpu, 2000) - self.assertEqual(image.ram, 1700) - self.assertEqual(image.disk, 160) - self.assertTrue(isinstance(image.price, float)) - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), len(self.driver._standard_drives)) - - for uuid, values in list(self.driver._standard_drives.items()): - self.assertEqual( - len([image for image in images if image.id == uuid]), 1) - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.reboot_node(node)) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.destroy_node(node)) - - def test_create_node(self): - sizes = self.driver.list_sizes() - size = [s for s in sizes if s.id == 'large'][0] - image = self.image - - self.assertTrue(self.driver.create_node(name="api.ivan.net.nz", - image=image, size=size)) - - -class ElasticHostsTestCase(ElasticStackTestCase, unittest.TestCase): - - def setUp(self): - ElasticHosts.connectionCls.conn_classes = (None, - ElasticStackMockHttp) - - self.driver = ElasticHosts('foo', 'bar') - images = self.driver.list_images() - self.image = [i for i in images if - i.id == '38df0986-4d85-4b76-b502-3878ffc80161'][0] - super(ElasticHostsTestCase, self).setUp() - - def test_multiple_drivers_with_different_regions(self): - driver1 = ElasticHosts('foo', 'bar', region='lon-p') - driver2 = ElasticHosts('foo', 'bar', region='sat-p') - - self.assertTrue(driver1.connection.host.startswith('api-lon-p')) - self.assertTrue(driver2.connection.host.startswith('api-sat-p')) - - driver1.list_nodes() - driver2.list_nodes() - driver1.list_nodes() - - self.assertTrue(driver1.connection.host.startswith('api-lon-p')) - self.assertTrue(driver2.connection.host.startswith('api-sat-p')) - - def test_invalid_region(self): - expected_msg = r'Invalid region.+' - self.assertRaisesRegexp(ValueError, expected_msg, ElasticHosts, - 'foo', 'bar', region='invalid') - - -class SkaliCloudTestCase(ElasticStackTestCase, unittest.TestCase): - - def setUp(self): - SkaliCloud.connectionCls.conn_classes = (None, - ElasticStackMockHttp) - - self.driver = SkaliCloud('foo', 'bar') - - images = self.driver.list_images() - self.image = [i for i in images if - i.id == '90aa51f2-15c0-4cff-81ee-e93aa20b9468'][0] - super(SkaliCloudTestCase, self).setUp() - - -class ServerLoveTestCase(ElasticStackTestCase, unittest.TestCase): - - def setUp(self): - ServerLove.connectionCls.conn_classes = (None, - ElasticStackMockHttp) - - self.driver = ServerLove('foo', 'bar') - - images = self.driver.list_images() - self.image = [i for i in images if - i.id == '679f5f44-0be7-4745-a658-cccd4334c1aa'][0] - super(ServerLoveTestCase, self).setUp() - - -class ElasticStackMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('elastichosts') - - def _servers_info_UNAUTHORIZED(self, method, url, body, headers): - return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _servers_info_MALFORMED(self, method, url, body, headers): - body = "{malformed: '" - return (httplib.OK, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _servers_info_PARSE_ERROR(self, method, url, body, headers): - return (505, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _servers_b605ca90_c3e6_4cee_85f8_a8ebdf8f9903_reset(self, method, url, body, headers): - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _servers_b605ca90_c3e6_4cee_85f8_a8ebdf8f9903_destroy(self, method, url, body, headers): - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _drives_create(self, method, url, body, headers): - body = self.fixtures.load('drives_create.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _drives_0012e24a_6eae_4279_9912_3432f698cec8_image_38df0986_4d85_4b76_b502_3878ffc80161_gunzip(self, method, - url, body, - headers): - # ElasticHosts image - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _drives_0012e24a_6eae_4279_9912_3432f698cec8_image_90aa51f2_15c0_4cff_81ee_e93aa20b9468_gunzip(self, method, - url, body, - headers): - # Skalikloud image - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _drives_0012e24a_6eae_4279_9912_3432f698cec8_image_679f5f44_0be7_4745_a658_cccd4334c1aa_gunzip(self, method, - url, body, - headers): - # ServerLove image - return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) - - def _drives_0012e24a_6eae_4279_9912_3432f698cec8_info(self, method, url, body, headers): - body = self.fixtures.load('drives_info.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _servers_create(self, method, url, body, headers): - body = self.fixtures.load('servers_create.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _servers_info(self, method, url, body, headers): - body = self.fixtures.load('servers_info.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _servers_72258_set(self, method, url, body, headers): - body = '{}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_exoscale.py b/awx/lib/site-packages/libcloud/test/compute/test_exoscale.py deleted file mode 100644 index 1a4cbec088..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_exoscale.py +++ /dev/null @@ -1,28 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - -from libcloud.compute.drivers.exoscale import ExoscaleNodeDriver -from libcloud.test.compute.test_cloudstack import CloudStackCommonTestCase - -from libcloud.test import unittest - - -class ExoscaleNodeDriverTestCase(CloudStackCommonTestCase, unittest.TestCase): - driver_klass = ExoscaleNodeDriver - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_gandi.py b/awx/lib/site-packages/libcloud/test/compute/test_gandi.py deleted file mode 100644 index e4a11e8c56..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_gandi.py +++ /dev/null @@ -1,322 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest -import sys -import random -import string - -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.gandi import GandiNodeDriver -from libcloud.common.gandi import GandiException -from libcloud.compute.types import NodeState - -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import GANDI_PARAMS -from libcloud.test.common.test_gandi import BaseGandiMockHttp - - -class GandiTests(unittest.TestCase): - - node_name = 'test2' - - def setUp(self): - GandiNodeDriver.connectionCls.conn_classes = ( - GandiMockHttp, GandiMockHttp) - GandiMockHttp.type = None - self.driver = GandiNodeDriver(*GANDI_PARAMS) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertTrue(len(nodes) > 0) - self.assertTrue(len(nodes[0].public_ips) > 1) - - def test_list_locations(self): - loc = list(filter(lambda x: 'france' in x.country.lower(), - self.driver.list_locations()))[0] - self.assertEqual(loc.country, 'France') - - def test_list_images(self): - loc = list(filter(lambda x: 'france' in x.country.lower(), - self.driver.list_locations()))[0] - images = self.driver.list_images(loc) - self.assertTrue(len(images) > 2) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertTrue(len(sizes) >= 1) - - def test_destroy_node_running(self): - nodes = self.driver.list_nodes() - test_node = list(filter(lambda x: x.state == NodeState.RUNNING, - nodes))[0] - self.assertTrue(self.driver.destroy_node(test_node)) - - def test_destroy_node_halted(self): - nodes = self.driver.list_nodes() - test_node = list(filter(lambda x: x.state == NodeState.TERMINATED, - nodes))[0] - self.assertTrue(self.driver.destroy_node(test_node)) - - def test_reboot_node(self): - nodes = self.driver.list_nodes() - test_node = list(filter(lambda x: x.state == NodeState.RUNNING, - nodes))[0] - self.assertTrue(self.driver.reboot_node(test_node)) - - def test_create_node(self): - login = 'libcloud' - passwd = ''.join(random.choice(string.ascii_letters) - for i in range(10)) - - # Get france datacenter - loc = list(filter(lambda x: 'france' in x.country.lower(), - self.driver.list_locations()))[0] - - # Get a debian image - images = self.driver.list_images(loc) - images = [x for x in images if x.name.lower().startswith('debian')] - img = list(filter(lambda x: '5' in x.name, images))[0] - - # Get a configuration size - size = self.driver.list_sizes()[0] - node = self.driver.create_node(name=self.node_name, login=login, - password=passwd, image=img, - location=loc, size=size) - self.assertEqual(node.name, self.node_name) - - def test_create_volume(self): - loc = list(filter(lambda x: 'france' in x.country.lower(), - self.driver.list_locations()))[0] - volume = self.driver.create_volume( - size=1024, name='libcloud', location=loc) - self.assertEqual(volume.name, 'libcloud') - self.assertEqual(volume.size, 1024) - - def test_list_volumes(self): - disks = self.driver.list_volumes() - self.assertTrue(len(disks) > 0) - - def test_destroy_volume(self): - volumes = self.driver.list_volumes() - test_vol = list(filter(lambda x: x.name == 'test_disk', - volumes))[0] - self.assertTrue(self.driver.destroy_volume(test_vol)) - - def test_attach_volume(self): - disks = self.driver.list_volumes() - nodes = self.driver.list_nodes() - res = self.driver.attach_volume(nodes[0], disks[0]) - self.assertTrue(res) - - def test_detach_volume(self): - disks = self.driver.list_volumes() - nodes = self.driver.list_nodes() - res = self.driver.detach_volume(nodes[0], disks[0]) - self.assertTrue(res) - - def test_ex_list_interfaces(self): - ifaces = self.driver.ex_list_interfaces() - self.assertTrue(len(ifaces) > 0) - - def test_ex_attach_interface(self): - ifaces = self.driver.ex_list_interfaces() - nodes = self.driver.list_nodes() - res = self.driver.ex_node_attach_interface(nodes[0], ifaces[0]) - self.assertTrue(res) - - def test_ex_detach_interface(self): - ifaces = self.driver.ex_list_interfaces() - nodes = self.driver.list_nodes() - res = self.driver.ex_node_detach_interface(nodes[0], ifaces[0]) - self.assertTrue(res) - - def test_ex_snapshot_disk(self): - disks = self.driver.list_volumes() - self.assertTrue(self.driver.ex_snapshot_disk(disks[2])) - self.assertRaises(GandiException, - self.driver.ex_snapshot_disk, disks[0]) - - def test_ex_update_disk(self): - disks = self.driver.list_volumes() - self.assertTrue(self.driver.ex_update_disk(disks[0], new_size=4096)) - - -class GandiRatingTests(unittest.TestCase): - - """Tests where rating model is involved""" - - node_name = 'test2' - - def setUp(self): - GandiNodeDriver.connectionCls.conn_classes = ( - GandiMockRatingHttp, GandiMockRatingHttp) - GandiMockRatingHttp.type = None - self.driver = GandiNodeDriver(*GANDI_PARAMS) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 4) - - def test_create_node(self): - login = 'libcloud' - passwd = ''.join(random.choice(string.ascii_letters) - for i in range(10)) - - # Get france datacenter - loc = list(filter(lambda x: 'france' in x.country.lower(), - self.driver.list_locations()))[0] - - # Get a debian image - images = self.driver.list_images(loc) - images = [x for x in images if x.name.lower().startswith('debian')] - img = list(filter(lambda x: '5' in x.name, images))[0] - - # Get a configuration size - size = self.driver.list_sizes()[0] - node = self.driver.create_node(name=self.node_name, login=login, - password=passwd, image=img, - location=loc, size=size) - self.assertEqual(node.name, self.node_name) - - -class GandiMockHttp(BaseGandiMockHttp): - - fixtures = ComputeFileFixtures('gandi') - - def _xmlrpc__hosting_datacenter_list(self, method, url, body, headers): - body = self.fixtures.load('datacenter_list.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_image_list(self, method, url, body, headers): - body = self.fixtures.load('image_list_dc0.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_list(self, method, url, body, headers): - body = self.fixtures.load('vm_list.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_ip_list(self, method, url, body, headers): - body = self.fixtures.load('ip_list.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_account_info(self, method, url, body, headers): - body = self.fixtures.load('account_info.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_info(self, method, url, body, headers): - body = self.fixtures.load('vm_info.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_delete(self, method, url, body, headers): - body = self.fixtures.load('vm_delete.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__operation_info(self, method, url, body, headers): - body = self.fixtures.load('operation_info.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_create_from(self, method, url, body, headers): - body = self.fixtures.load('vm_create_from.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_reboot(self, method, url, body, headers): - body = self.fixtures.load('vm_reboot.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_stop(self, method, url, body, headers): - body = self.fixtures.load('vm_stop.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_iface_list(self, method, url, body, headers): - body = self.fixtures.load('iface_list.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_disk_list(self, method, url, body, headers): - body = self.fixtures.load('disk_list.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_iface_attach(self, method, url, body, headers): - body = self.fixtures.load('iface_attach.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_iface_detach(self, method, url, body, headers): - body = self.fixtures.load('iface_detach.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_disk_attach(self, method, url, body, headers): - body = self.fixtures.load('disk_attach.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_disk_detach(self, method, url, body, headers): - body = self.fixtures.load('disk_detach.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_disk_create(self, method, url, body, headers): - body = self.fixtures.load('disk_create.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_disk_create_from(self, method, url, body, headers): - body = self.fixtures.load('disk_create_from.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_disk_info(self, method, url, body, headers): - body = self.fixtures.load('disk_info.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_disk_update(self, method, url, body, headers): - body = self.fixtures.load('disk_update.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_disk_delete(self, method, url, body, headers): - body = self.fixtures.load('disk_delete.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -class GandiMockRatingHttp(BaseGandiMockHttp): - - """Fixtures needed for tests related to rating model""" - - fixtures = ComputeFileFixtures('gandi') - - def _xmlrpc__hosting_datacenter_list(self, method, url, body, headers): - body = self.fixtures.load('datacenter_list.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_image_list(self, method, url, body, headers): - body = self.fixtures.load('image_list_dc0.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_create_from(self, method, url, body, headers): - body = self.fixtures.load('vm_create_from.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__operation_info(self, method, url, body, headers): - body = self.fixtures.load('operation_info.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__hosting_vm_info(self, method, url, body, headers): - body = self.fixtures.load('vm_info.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - # Specific to rating tests - def _xmlrpc__hosting_account_info(self, method, url, body, headers): - body = self.fixtures.load('account_info_rating.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_gce.py b/awx/lib/site-packages/libcloud/test/compute/test_gce.py deleted file mode 100644 index 80110d0176..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_gce.py +++ /dev/null @@ -1,1278 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Tests for Google Compute Engine Driver -""" -import sys -import unittest -import datetime - -from libcloud.utils.py3 import httplib -from libcloud.compute.drivers.gce import (GCENodeDriver, API_VERSION, - timestamp_to_datetime, - GCEAddress, GCEHealthCheck, - GCEFirewall, GCEForwardingRule, - GCENetwork, - GCEZone) -from libcloud.common.google import (GoogleBaseAuthConnection, - GoogleInstalledAppAuthConnection, - GoogleBaseConnection, - ResourceNotFoundError, ResourceExistsError) -from libcloud.test.common.test_google import GoogleAuthMockHttp -from libcloud.compute.base import Node, StorageVolume - -from libcloud.test import MockHttpTestCase, LibcloudTestCase -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - -from libcloud.test.secrets import GCE_PARAMS, GCE_KEYWORD_PARAMS - - -class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): - - """ - Google Compute Engine Test Class. - """ - # Mock out a few specific calls that interact with the user, system or - # environment. - GoogleBaseConnection._get_token_info_from_file = lambda x: None - GoogleBaseConnection._write_token_info_to_file = lambda x: None - GoogleInstalledAppAuthConnection.get_code = lambda x: '1234' - GCEZone._now = lambda x: datetime.datetime(2013, 6, 26, 19, 0, 0) - datacenter = 'us-central1-a' - - def setUp(self): - GCEMockHttp.test = self - GCENodeDriver.connectionCls.conn_classes = (GCEMockHttp, GCEMockHttp) - GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp, - GoogleAuthMockHttp) - GCEMockHttp.type = None - kwargs = GCE_KEYWORD_PARAMS.copy() - kwargs['auth_type'] = 'IA' - kwargs['datacenter'] = self.datacenter - self.driver = GCENodeDriver(*GCE_PARAMS, **kwargs) - - def test_default_scopes(self): - self.assertEqual(self.driver.scopes, None) - - def test_timestamp_to_datetime(self): - timestamp1 = '2013-06-26T10:05:19.340-07:00' - datetime1 = datetime.datetime(2013, 6, 26, 17, 5, 19) - self.assertEqual(timestamp_to_datetime(timestamp1), datetime1) - timestamp2 = '2013-06-26T17:43:15.000-00:00' - datetime2 = datetime.datetime(2013, 6, 26, 17, 43, 15) - self.assertEqual(timestamp_to_datetime(timestamp2), datetime2) - - def test_get_region_from_zone(self): - zone1 = self.driver.ex_get_zone('us-central1-a') - expected_region1 = 'us-central1' - region1 = self.driver._get_region_from_zone(zone1) - self.assertEqual(region1.name, expected_region1) - zone2 = self.driver.ex_get_zone('europe-west1-b') - expected_region2 = 'europe-west1' - region2 = self.driver._get_region_from_zone(zone2) - self.assertEqual(region2.name, expected_region2) - - def test_find_zone_or_region(self): - zone1 = self.driver._find_zone_or_region('libcloud-demo-np-node', - 'instances') - self.assertEqual(zone1.name, 'us-central2-a') - zone2 = self.driver._find_zone_or_region( - 'libcloud-demo-europe-np-node', 'instances') - self.assertEqual(zone2.name, 'europe-west1-a') - region = self.driver._find_zone_or_region('libcloud-demo-address', - 'addresses', region=True) - self.assertEqual(region.name, 'us-central1') - - def test_match_images(self): - project = 'debian-cloud' - image = self.driver._match_images(project, 'debian-7') - self.assertEqual(image.name, 'debian-7-wheezy-v20131120') - image = self.driver._match_images(project, 'debian-6') - self.assertEqual(image.name, 'debian-6-squeeze-v20130926') - - def test_ex_list_addresses(self): - address_list = self.driver.ex_list_addresses() - address_list_all = self.driver.ex_list_addresses('all') - address_list_uc1 = self.driver.ex_list_addresses('us-central1') - self.assertEqual(len(address_list), 2) - self.assertEqual(len(address_list_all), 4) - self.assertEqual(address_list[0].name, 'libcloud-demo-address') - self.assertEqual(address_list_uc1[0].name, 'libcloud-demo-address') - names = [a.name for a in address_list_all] - self.assertTrue('libcloud-demo-address' in names) - - def test_ex_list_healthchecks(self): - healthchecks = self.driver.ex_list_healthchecks() - self.assertEqual(len(healthchecks), 3) - self.assertEqual(healthchecks[0].name, 'basic-check') - - def test_ex_list_firewalls(self): - firewalls = self.driver.ex_list_firewalls() - self.assertEqual(len(firewalls), 5) - self.assertEqual(firewalls[0].name, 'default-allow-internal') - - def test_ex_list_forwarding_rules(self): - forwarding_rules = self.driver.ex_list_forwarding_rules() - forwarding_rules_all = self.driver.ex_list_forwarding_rules('all') - forwarding_rules_uc1 = self.driver.ex_list_forwarding_rules( - 'us-central1') - self.assertEqual(len(forwarding_rules), 2) - self.assertEqual(len(forwarding_rules_all), 2) - self.assertEqual(forwarding_rules[0].name, 'lcforwardingrule') - self.assertEqual(forwarding_rules_uc1[0].name, 'lcforwardingrule') - names = [f.name for f in forwarding_rules_all] - self.assertTrue('lcforwardingrule' in names) - - def test_list_images(self): - local_images = self.driver.list_images() - debian_images = self.driver.list_images(ex_project='debian-cloud') - self.assertEqual(len(local_images), 3) - self.assertEqual(len(debian_images), 19) - self.assertEqual(local_images[0].name, 'debian-7-wheezy-v20130617') - self.assertEqual(local_images[1].name, 'centos-6-v20131118') - - def test_list_locations(self): - locations = self.driver.list_locations() - self.assertEqual(len(locations), 5) - self.assertEqual(locations[0].name, 'europe-west1-a') - - def test_ex_list_networks(self): - networks = self.driver.ex_list_networks() - self.assertEqual(len(networks), 3) - self.assertEqual(networks[0].name, 'default') - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - nodes_all = self.driver.list_nodes(ex_zone='all') - nodes_uc1a = self.driver.list_nodes(ex_zone='us-central1-a') - self.assertEqual(len(nodes), 1) - self.assertEqual(len(nodes_all), 8) - self.assertEqual(len(nodes_uc1a), 1) - self.assertEqual(nodes[0].name, 'node-name') - self.assertEqual(nodes_uc1a[0].name, 'node-name') - names = [n.name for n in nodes_all] - self.assertTrue('node-name' in names) - - def test_ex_list_regions(self): - regions = self.driver.ex_list_regions() - self.assertEqual(len(regions), 3) - self.assertEqual(regions[0].name, 'europe-west1') - - def test_ex_list_snapshots(self): - snapshots = self.driver.ex_list_snapshots() - self.assertEqual(len(snapshots), 2) - self.assertEqual(snapshots[0].name, 'lcsnapshot') - - def test_ex_list_targetpools(self): - target_pools = self.driver.ex_list_targetpools() - target_pools_all = self.driver.ex_list_targetpools('all') - target_pools_uc1 = self.driver.ex_list_targetpools('us-central1') - self.assertEqual(len(target_pools), 2) - self.assertEqual(len(target_pools_all), 3) - self.assertEqual(len(target_pools_uc1), 2) - self.assertEqual(target_pools[0].name, 'lctargetpool') - self.assertEqual(target_pools_uc1[0].name, 'lctargetpool') - names = [t.name for t in target_pools_all] - self.assertTrue('www-pool' in names) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - sizes_all = self.driver.list_sizes('all') - self.assertEqual(len(sizes), 22) - self.assertEqual(len(sizes_all), 100) - self.assertEqual(sizes[0].name, 'f1-micro') - self.assertEqual(sizes[0].extra['zone'].name, 'us-central1-a') - names = [s.name for s in sizes_all] - self.assertEqual(names.count('n1-standard-1'), 5) - - def test_list_volumes(self): - volumes = self.driver.list_volumes() - volumes_all = self.driver.list_volumes('all') - volumes_uc1a = self.driver.list_volumes('us-central1-a') - self.assertEqual(len(volumes), 2) - self.assertEqual(len(volumes_all), 10) - self.assertEqual(len(volumes_uc1a), 2) - self.assertEqual(volumes[0].name, 'lcdisk') - self.assertEqual(volumes_uc1a[0].name, 'lcdisk') - names = [v.name for v in volumes_all] - self.assertTrue('libcloud-demo-europe-boot-disk' in names) - - def test_ex_list_zones(self): - zones = self.driver.ex_list_zones() - self.assertEqual(len(zones), 5) - self.assertEqual(zones[0].name, 'europe-west1-a') - - def test_ex_create_address(self): - address_name = 'lcaddress' - address = self.driver.ex_create_address(address_name) - self.assertTrue(isinstance(address, GCEAddress)) - self.assertEqual(address.name, address_name) - - def test_ex_create_healthcheck(self): - healthcheck_name = 'lchealthcheck' - kwargs = {'host': 'lchost', - 'path': '/lc', - 'port': 8000, - 'interval': 10, - 'timeout': 10, - 'unhealthy_threshold': 4, - 'healthy_threshold': 3} - hc = self.driver.ex_create_healthcheck(healthcheck_name, **kwargs) - self.assertTrue(isinstance(hc, GCEHealthCheck)) - self.assertEqual(hc.name, healthcheck_name) - self.assertEqual(hc.path, '/lc') - self.assertEqual(hc.port, 8000) - self.assertEqual(hc.interval, 10) - - def test_ex_create_firewall(self): - firewall_name = 'lcfirewall' - allowed = [{'IPProtocol': 'tcp', 'ports': ['4567']}] - source_tags = ['libcloud'] - firewall = self.driver.ex_create_firewall(firewall_name, allowed, - source_tags=source_tags) - self.assertTrue(isinstance(firewall, GCEFirewall)) - self.assertEqual(firewall.name, firewall_name) - - def test_ex_create_forwarding_rule(self): - fwr_name = 'lcforwardingrule' - targetpool = 'lctargetpool' - region = 'us-central1' - fwr = self.driver.ex_create_forwarding_rule(fwr_name, targetpool, - region=region, - port_range='8000-8500') - self.assertTrue(isinstance(fwr, GCEForwardingRule)) - self.assertEqual(fwr.name, fwr_name) - - def test_ex_create_network(self): - network_name = 'lcnetwork' - cidr = '10.11.0.0/16' - network = self.driver.ex_create_network(network_name, cidr) - self.assertTrue(isinstance(network, GCENetwork)) - self.assertEqual(network.name, network_name) - self.assertEqual(network.cidr, cidr) - - def test_create_node_req(self): - image = self.driver.ex_get_image('debian-7') - size = self.driver.ex_get_size('n1-standard-1') - location = self.driver.zone - network = self.driver.ex_get_network('default') - tags = ['libcloud'] - metadata = [{'key': 'test_key', 'value': 'test_value'}] - boot_disk = self.driver.ex_get_volume('lcdisk') - node_request, node_data = self.driver._create_node_req('lcnode', size, - image, location, - network, tags, - metadata, - boot_disk) - self.assertEqual(node_request, '/zones/%s/instances' % location.name) - self.assertEqual(node_data['metadata'][0]['key'], 'test_key') - self.assertEqual(node_data['tags']['items'][0], 'libcloud') - self.assertEqual(node_data['name'], 'lcnode') - self.assertTrue(node_data['disks'][0]['boot']) - - def test_create_node(self): - node_name = 'node-name' - image = self.driver.ex_get_image('debian-7') - size = self.driver.ex_get_size('n1-standard-1') - node = self.driver.create_node(node_name, size, image) - self.assertTrue(isinstance(node, Node)) - self.assertEqual(node.name, node_name) - - def test_create_node_existing(self): - node_name = 'libcloud-demo-europe-np-node' - image = self.driver.ex_get_image('debian-7') - size = self.driver.ex_get_size('n1-standard-1', zone='europe-west1-a') - self.assertRaises(ResourceExistsError, self.driver.create_node, - node_name, size, image, location='europe-west1-a') - - def test_ex_create_multiple_nodes(self): - base_name = 'lcnode' - image = self.driver.ex_get_image('debian-7') - size = self.driver.ex_get_size('n1-standard-1') - number = 2 - nodes = self.driver.ex_create_multiple_nodes(base_name, size, image, - number) - self.assertEqual(len(nodes), 2) - self.assertTrue(isinstance(nodes[0], Node)) - self.assertTrue(isinstance(nodes[1], Node)) - self.assertEqual(nodes[0].name, '%s-000' % base_name) - self.assertEqual(nodes[1].name, '%s-001' % base_name) - - def test_ex_create_targetpool(self): - targetpool_name = 'lctargetpool' - region = 'us-central1' - healthchecks = ['libcloud-lb-demo-healthcheck'] - node1 = self.driver.ex_get_node('libcloud-lb-demo-www-000', - 'us-central1-b') - node2 = self.driver.ex_get_node('libcloud-lb-demo-www-001', - 'us-central1-b') - nodes = [node1, node2] - targetpool = self.driver.ex_create_targetpool( - targetpool_name, region=region, healthchecks=healthchecks, - nodes=nodes) - self.assertEqual(targetpool.name, targetpool_name) - self.assertEqual(len(targetpool.nodes), len(nodes)) - self.assertEqual(targetpool.region.name, region) - - def test_ex_create_volume_snapshot(self): - snapshot_name = 'lcsnapshot' - volume = self.driver.ex_get_volume('lcdisk') - snapshot = volume.snapshot(snapshot_name) - self.assertEqual(snapshot.name, snapshot_name) - self.assertEqual(snapshot.size, '1') - - def test_create_volume(self): - volume_name = 'lcdisk' - size = 1 - volume = self.driver.create_volume(size, volume_name) - self.assertTrue(isinstance(volume, StorageVolume)) - self.assertEqual(volume.name, volume_name) - - def test_ex_update_healthcheck(self): - healthcheck_name = 'lchealthcheck' - healthcheck = self.driver.ex_get_healthcheck(healthcheck_name) - healthcheck.port = 9000 - healthcheck2 = self.driver.ex_update_healthcheck(healthcheck) - self.assertTrue(isinstance(healthcheck2, GCEHealthCheck)) - - def test_ex_update_firewall(self): - firewall_name = 'lcfirewall' - firewall = self.driver.ex_get_firewall(firewall_name) - firewall.source_ranges = ['10.0.0.0/16'] - firewall.source_tags = ['libcloud', 'test'] - firewall2 = self.driver.ex_update_firewall(firewall) - self.assertTrue(isinstance(firewall2, GCEFirewall)) - - def test_ex_targetpool_remove_add_node(self): - targetpool = self.driver.ex_get_targetpool('lctargetpool') - node = self.driver.ex_get_node('libcloud-lb-demo-www-001', - 'us-central1-b') - remove_node = self.driver.ex_targetpool_remove_node(targetpool, node) - self.assertTrue(remove_node) - self.assertEqual(len(targetpool.nodes), 1) - - add_node = self.driver.ex_targetpool_add_node(targetpool, node) - self.assertTrue(add_node) - self.assertEqual(len(targetpool.nodes), 2) - - def test_ex_targetpool_remove_add_healthcheck(self): - targetpool = self.driver.ex_get_targetpool('lctargetpool') - healthcheck = self.driver.ex_get_healthcheck( - 'libcloud-lb-demo-healthcheck') - remove_healthcheck = self.driver.ex_targetpool_remove_healthcheck( - targetpool, healthcheck) - self.assertTrue(remove_healthcheck) - self.assertEqual(len(targetpool.healthchecks), 0) - - add_healthcheck = self.driver.ex_targetpool_add_healthcheck( - targetpool, healthcheck) - self.assertTrue(add_healthcheck) - self.assertEqual(len(targetpool.healthchecks), 1) - - def test_reboot_node(self): - node = self.driver.ex_get_node('node-name') - reboot = self.driver.reboot_node(node) - self.assertTrue(reboot) - - def test_ex_set_node_tags(self): - new_tags = ['libcloud'] - node = self.driver.ex_get_node('node-name') - set_tags = self.driver.ex_set_node_tags(node, new_tags) - self.assertTrue(set_tags) - - def test_attach_volume(self): - volume = self.driver.ex_get_volume('lcdisk') - node = self.driver.ex_get_node('node-name') - attach = volume.attach(node) - self.assertTrue(attach) - - def test_detach_volume(self): - volume = self.driver.ex_get_volume('lcdisk') - node = self.driver.ex_get_node('node-name') - # This fails since the node is required - detach = volume.detach() - self.assertFalse(detach) - # This should pass - detach = self.driver.detach_volume(volume, node) - self.assertTrue(detach) - - def test_ex_destroy_address(self): - address = self.driver.ex_get_address('lcaddress') - destroyed = address.destroy() - self.assertTrue(destroyed) - - def test_ex_destroy_healthcheck(self): - hc = self.driver.ex_get_healthcheck('lchealthcheck') - destroyed = hc.destroy() - self.assertTrue(destroyed) - - def test_ex_delete_image(self): - image = self.driver.ex_get_image('debian-7') - deleted = self.driver.ex_delete_image(image) - self.assertTrue(deleted) - - def test_ex_deprecate_image(self): - image = self.driver.ex_get_image('debian-6') - deprecated = image.deprecate('debian-7', 'DEPRECATED') - self.assertTrue(deprecated) - - def test_ex_destroy_firewall(self): - firewall = self.driver.ex_get_firewall('lcfirewall') - destroyed = firewall.destroy() - self.assertTrue(destroyed) - - def test_ex_destroy_forwarding_rule(self): - fwr = self.driver.ex_get_forwarding_rule('lcforwardingrule') - destroyed = fwr.destroy() - self.assertTrue(destroyed) - - def test_ex_destroy_network(self): - network = self.driver.ex_get_network('lcnetwork') - destroyed = network.destroy() - self.assertTrue(destroyed) - - def test_destroy_node(self): - node = self.driver.ex_get_node('node-name') - destroyed = node.destroy() - self.assertTrue(destroyed) - - def test_ex_destroy_multiple_nodes(self): - nodes = [] - nodes.append(self.driver.ex_get_node('lcnode-000')) - nodes.append(self.driver.ex_get_node('lcnode-001')) - destroyed = self.driver.ex_destroy_multiple_nodes(nodes) - for d in destroyed: - self.assertTrue(d) - - def test_destroy_targetpool(self): - targetpool = self.driver.ex_get_targetpool('lctargetpool') - destroyed = targetpool.destroy() - self.assertTrue(destroyed) - - def test_destroy_volume(self): - disk = self.driver.ex_get_volume('lcdisk') - destroyed = disk.destroy() - self.assertTrue(destroyed) - - def test_ex_set_volume_auto_delete(self): - node = self.driver.ex_get_node('node-name') - volume = node.extra['boot_disk'] - auto_delete = self.driver.ex_set_volume_auto_delete( - volume, node) - self.assertTrue(auto_delete) - - def test_destroy_volume_snapshot(self): - snapshot = self.driver.ex_get_snapshot('lcsnapshot') - destroyed = snapshot.destroy() - self.assertTrue(destroyed) - - def test_ex_get_address(self): - address_name = 'lcaddress' - address = self.driver.ex_get_address(address_name) - self.assertEqual(address.name, address_name) - self.assertEqual(address.address, '173.255.113.20') - self.assertEqual(address.region.name, 'us-central1') - self.assertEqual(address.extra['status'], 'RESERVED') - - def test_ex_get_healthcheck(self): - healthcheck_name = 'lchealthcheck' - healthcheck = self.driver.ex_get_healthcheck(healthcheck_name) - self.assertEqual(healthcheck.name, healthcheck_name) - self.assertEqual(healthcheck.port, 8000) - self.assertEqual(healthcheck.path, '/lc') - - def test_ex_get_firewall(self): - firewall_name = 'lcfirewall' - firewall = self.driver.ex_get_firewall(firewall_name) - self.assertEqual(firewall.name, firewall_name) - self.assertEqual(firewall.network.name, 'default') - self.assertEqual(firewall.source_tags, ['libcloud']) - - def test_ex_get_forwarding_rule(self): - fwr_name = 'lcforwardingrule' - fwr = self.driver.ex_get_forwarding_rule(fwr_name) - self.assertEqual(fwr.name, fwr_name) - self.assertEqual(fwr.extra['portRange'], '8000-8500') - self.assertEqual(fwr.targetpool.name, 'lctargetpool') - self.assertEqual(fwr.protocol, 'TCP') - - def test_ex_get_image(self): - partial_name = 'debian-7' - image = self.driver.ex_get_image(partial_name) - self.assertEqual(image.name, 'debian-7-wheezy-v20130617') - # A 'debian-7' image exists in the local project - self.assertTrue(image.extra['description'].startswith('Local')) - - partial_name = 'debian-6' - image = self.driver.ex_get_image(partial_name) - self.assertEqual(image.name, 'debian-6-squeeze-v20130926') - self.assertTrue(image.extra['description'].startswith('Debian')) - - def test_ex_copy_image(self): - name = 'coreos' - url = 'gs://storage.core-os.net/coreos/amd64-generic/247.0.0/coreos_production_gce.tar.gz' - description = 'CoreOS test image' - image = self.driver.ex_copy_image(name, url, description) - self.assertEqual(image.name, name) - self.assertEqual(image.extra['description'], description) - - def test_ex_get_network(self): - network_name = 'lcnetwork' - network = self.driver.ex_get_network(network_name) - self.assertEqual(network.name, network_name) - self.assertEqual(network.cidr, '10.11.0.0/16') - self.assertEqual(network.extra['gatewayIPv4'], '10.11.0.1') - - def test_ex_get_node(self): - node_name = 'node-name' - zone = 'us-central1-a' - node = self.driver.ex_get_node(node_name, zone) - self.assertEqual(node.name, node_name) - self.assertEqual(node.size, 'n1-standard-1') - removed_node = 'libcloud-lb-demo-www-002' - self.assertRaises(ResourceNotFoundError, self.driver.ex_get_node, - removed_node, 'us-central1-b') - missing_node = 'dummy-node' - self.assertRaises(ResourceNotFoundError, self.driver.ex_get_node, - missing_node, 'all') - - def test_ex_get_project(self): - project = self.driver.ex_get_project() - self.assertEqual(project.name, 'project_name') - networks_quota = project.quotas[1] - self.assertEqual(networks_quota['usage'], 3.0) - self.assertEqual(networks_quota['limit'], 5.0) - self.assertEqual(networks_quota['metric'], 'NETWORKS') - - def test_ex_get_region(self): - region_name = 'us-central1' - region = self.driver.ex_get_region(region_name) - self.assertEqual(region.name, region_name) - self.assertEqual(region.status, 'UP') - self.assertEqual(region.zones[0].name, 'us-central1-a') - - def test_ex_get_size(self): - size_name = 'n1-standard-1' - size = self.driver.ex_get_size(size_name) - self.assertEqual(size.name, size_name) - self.assertEqual(size.extra['zone'].name, 'us-central1-a') - self.assertEqual(size.disk, 10) - self.assertEqual(size.ram, 3840) - self.assertEqual(size.extra['guestCpus'], 1) - - def test_ex_get_targetpool(self): - targetpool_name = 'lctargetpool' - targetpool = self.driver.ex_get_targetpool(targetpool_name) - self.assertEqual(targetpool.name, targetpool_name) - self.assertEqual(len(targetpool.nodes), 2) - self.assertEqual(targetpool.region.name, 'us-central1') - - def test_ex_get_snapshot(self): - snapshot_name = 'lcsnapshot' - snapshot = self.driver.ex_get_snapshot(snapshot_name) - self.assertEqual(snapshot.name, snapshot_name) - self.assertEqual(snapshot.size, '1') - self.assertEqual(snapshot.status, 'READY') - - def test_ex_get_volume(self): - volume_name = 'lcdisk' - volume = self.driver.ex_get_volume(volume_name) - self.assertEqual(volume.name, volume_name) - self.assertEqual(volume.size, '1') - self.assertEqual(volume.extra['status'], 'READY') - - def test_ex_get_zone(self): - zone_name = 'us-central1-b' - zone = self.driver.ex_get_zone(zone_name) - self.assertEqual(zone.name, zone_name) - self.assertFalse(zone.time_until_mw) - self.assertFalse(zone.next_mw_duration) - - zone_no_mw = self.driver.ex_get_zone('us-central1-a') - self.assertEqual(zone_no_mw.time_until_mw, None) - - -class GCEMockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('gce') - json_hdr = {'content-type': 'application/json; charset=UTF-8'} - - def _get_method_name(self, type, use_param, qs, path): - api_path = '/compute/%s' % API_VERSION - project_path = '/projects/%s' % GCE_KEYWORD_PARAMS['project'] - path = path.replace(api_path, '') - # This replace is separate, since there is a call with a different - # project name - path = path.replace(project_path, '') - # The path to get project information is the base path, so use a fake - # '/project' path instead - if not path: - path = '/project' - method_name = super(GCEMockHttp, self)._get_method_name(type, - use_param, - qs, path) - return method_name - - def _aggregated_addresses(self, method, url, body, headers): - body = self.fixtures.load('aggregated_addresses.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _aggregated_disks(self, method, url, body, headers): - body = self.fixtures.load('aggregated_disks.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _aggregated_forwardingRules(self, method, url, body, headers): - body = self.fixtures.load('aggregated_forwardingRules.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _aggregated_instances(self, method, url, body, headers): - body = self.fixtures.load('aggregated_instances.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _aggregated_machineTypes(self, method, url, body, headers): - body = self.fixtures.load('aggregated_machineTypes.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _aggregated_targetPools(self, method, url, body, headers): - body = self.fixtures.load('aggregated_targetPools.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_httpHealthChecks(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('global_httpHealthChecks_post.json') - else: - body = self.fixtures.load('global_httpHealthChecks.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_httpHealthChecks_basic_check(self, method, url, body, headers): - body = self.fixtures.load('global_httpHealthChecks_basic-check.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_httpHealthChecks_libcloud_lb_demo_healthcheck( - self, method, url, body, headers): - body = self.fixtures.load( - 'global_httpHealthChecks_libcloud-lb-demo-healthcheck.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_httpHealthChecks_lchealthcheck(self, method, url, body, - headers): - if method == 'DELETE': - body = self.fixtures.load( - 'global_httpHealthChecks_lchealthcheck_delete.json') - elif method == 'PUT': - body = self.fixtures.load( - 'global_httpHealthChecks_lchealthcheck_put.json') - else: - body = self.fixtures.load( - 'global_httpHealthChecks_lchealthcheck.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_firewalls(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('global_firewalls_post.json') - else: - body = self.fixtures.load('global_firewalls.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_firewalls_lcfirewall(self, method, url, body, headers): - if method == 'DELETE': - body = self.fixtures.load( - 'global_firewalls_lcfirewall_delete.json') - elif method == 'PUT': - body = self.fixtures.load('global_firewalls_lcfirewall_put.json') - else: - body = self.fixtures.load('global_firewalls_lcfirewall.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_images(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('global_images_post.json') - else: - body = self.fixtures.load('global_images.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_images_debian_7_wheezy_v20130617( - self, method, url, body, headers): - body = self.fixtures.load('global_images_debian_7_wheezy_v20130617_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_images_debian_6_squeeze_v20130926_deprecate( - self, method, url, body, headers): - body = self.fixtures.load('global_images_debian_6_squeeze_v20130926_deprecate.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_networks(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('global_networks_post.json') - else: - body = self.fixtures.load('global_networks.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_networks_default(self, method, url, body, headers): - body = self.fixtures.load('global_networks_default.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_networks_libcloud_demo_network(self, method, url, body, - headers): - body = self.fixtures.load('global_networks_libcloud-demo-network.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_networks_libcloud_demo_europe_network(self, method, url, body, - headers): - body = self.fixtures.load( - 'global_networks_libcloud-demo-europe-network.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_networks_lcnetwork(self, method, url, body, headers): - if method == 'DELETE': - body = self.fixtures.load('global_networks_lcnetwork_delete.json') - else: - body = self.fixtures.load('global_networks_lcnetwork.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_snapshots(self, method, url, body, headers): - body = self.fixtures.load('global_snapshots.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_snapshots_lcsnapshot(self, method, url, body, headers): - if method == 'DELETE': - body = self.fixtures.load( - 'global_snapshots_lcsnapshot_delete.json') - else: - body = self.fixtures.load('global_snapshots_lcsnapshot.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_httpHealthChecks_lchealthcheck_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_httpHealthChecks_lchealthcheck_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_images_debian7_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_images_debian7_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_httpHealthChecks_lchealthcheck_put( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_httpHealthChecks_lchealthcheck_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_httpHealthChecks_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_httpHealthChecks_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_firewalls_lcfirewall_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_firewalls_lcfirewall_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_firewalls_lcfirewall_put( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_firewalls_lcfirewall_put.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_firewalls_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_firewalls_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_networks_lcnetwork_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_networks_lcnetwork_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_networks_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_networks_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_snapshots_lcsnapshot_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_snapshots_lcsnapshot_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _global_operations_operation_global_image_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_global_image_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_addresses_lcaddress_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_addresses_lcaddress_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_addresses_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_addresses_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_forwardingRules_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_forwardingRules_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_forwardingRules_lcforwardingrule_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_forwardingRules_lcforwardingrule_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_targetPools_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_targetPools_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_targetPools_lctargetpool_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_removeHealthCheck_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_addHealthCheck_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_removeInstance_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_targetPools_lctargetpool_removeInstance_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_addInstance_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_regions_us-central1_targetPools_lctargetpool_addInstance_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_lcdisk_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_disks_lcdisk_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_node_name_setDiskAutoDelete( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us_central1_a_instances_node_name_setDiskAutoDelete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_volume_auto_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us_central1_a_operations_operation_volume_auto_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_lcdisk_createSnapshot_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_disks_lcdisk_createSnapshot_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_disks_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_lcnode_000_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_lcnode-000_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_lcnode_001_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_lcnode-001_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_delete( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_node-name_delete.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_attachDisk_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_node-name_attachDisk_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_detachDisk_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_node-name_detachDisk_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_setTags_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_node-name_setTags_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_reset_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_node-name_reset_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_europe_west1_a_operations_operation_zones_europe_west1_a_instances_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_europe-west1-a_instances_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_post( - self, method, url, body, headers): - body = self.fixtures.load( - 'operations_operation_zones_us-central1-a_instances_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _project(self, method, url, body, headers): - body = self.fixtures.load('project.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _projects_debian_cloud_global_images(self, method, url, body, headers): - body = self.fixtures.load('projects_debian-cloud_global_images.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions(self, method, url, body, headers): - body = self.fixtures.load( - 'regions.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_addresses(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load( - 'regions_us-central1_addresses_post.json') - else: - body = self.fixtures.load('regions_us-central1_addresses.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_addresses_lcaddress(self, method, url, body, - headers): - if method == 'DELETE': - body = self.fixtures.load( - 'regions_us-central1_addresses_lcaddress_delete.json') - else: - body = self.fixtures.load( - 'regions_us-central1_addresses_lcaddress.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_forwardingRules(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load( - 'regions_us-central1_forwardingRules_post.json') - else: - body = self.fixtures.load( - 'regions_us-central1_forwardingRules.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_forwardingRules_libcloud_lb_demo_lb( - self, method, url, body, headers): - body = self.fixtures.load( - 'regions_us-central1_forwardingRules_libcloud-lb-demo-lb.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_forwardingRules_lcforwardingrule( - self, method, url, body, headers): - if method == 'DELETE': - body = self.fixtures.load( - 'regions_us-central1_forwardingRules_lcforwardingrule_delete.json') - else: - body = self.fixtures.load( - 'regions_us-central1_forwardingRules_lcforwardingrule.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_targetPools(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load( - 'regions_us-central1_targetPools_post.json') - else: - body = self.fixtures.load('regions_us-central1_targetPools.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_targetPools_lctargetpool(self, method, url, - body, headers): - if method == 'DELETE': - body = self.fixtures.load( - 'regions_us-central1_targetPools_lctargetpool_delete.json') - else: - body = self.fixtures.load( - 'regions_us-central1_targetPools_lctargetpool.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_targetPools_libcloud_lb_demo_lb_tp( - self, method, url, body, headers): - body = self.fixtures.load( - 'regions_us-central1_targetPools_libcloud-lb-demo-lb-tp.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_targetPools_lctargetpool_removeHealthCheck( - self, method, url, body, headers): - body = self.fixtures.load( - 'regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_targetPools_lctargetpool_addHealthCheck( - self, method, url, body, headers): - body = self.fixtures.load( - 'regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_targetPools_lctargetpool_removeInstance( - self, method, url, body, headers): - body = self.fixtures.load( - 'regions_us-central1_targetPools_lctargetpool_removeInstance_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _regions_us_central1_targetPools_lctargetpool_addInstance( - self, method, url, body, headers): - body = self.fixtures.load( - 'regions_us-central1_targetPools_lctargetpool_addInstance_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones(self, method, url, body, headers): - body = self.fixtures.load('zones.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_disks(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('zones_us-central1-a_disks_post.json') - else: - body = self.fixtures.load('zones_us-central1-a_disks.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_disks_lcdisk(self, method, url, body, headers): - if method == 'DELETE': - body = self.fixtures.load( - 'zones_us-central1-a_disks_lcdisk_delete.json') - else: - body = self.fixtures.load('zones_us-central1-a_disks_lcdisk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_disks_lcdisk_createSnapshot(self, method, url, - body, headers): - body = self.fixtures.load( - 'zones_us-central1-a_disks_lcdisk_createSnapshot_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_disks_node_name(self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_disks_lcnode_000( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_disks_lcnode_001( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_b_disks_libcloud_lb_demo_www_000( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_b_disks_libcloud_lb_demo_www_001( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_b_disks_libcloud_lb_demo_www_002( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central2_a_disks_libcloud_demo_boot_disk( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central2_a_disks_libcloud_demo_np_node( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central2_a_disks_libcloud_demo_multiple_nodes_000( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central2_a_disks_libcloud_demo_multiple_nodes_001( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_europe_west1_a_disks(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('zones_us-central1-a_disks_post.json') - else: - body = self.fixtures.load('zones_us-central1-a_disks.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_europe_west1_a_disks_libcloud_demo_europe_np_node( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_europe_west1_a_disks_libcloud_demo_europe_boot_disk( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_europe_west1_a_disks_libcloud_demo_europe_multiple_nodes_000( - self, method, url, body, headers): - body = self.fixtures.load('generic_disk.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_europe_west1_a_instances(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load( - 'zones_europe-west1-a_instances_post.json') - else: - body = self.fixtures.load('zones_europe-west1-a_instances.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load( - 'zones_us-central1-a_instances_post.json') - else: - body = self.fixtures.load('zones_us-central1-a_instances.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_node_name(self, method, url, body, - headers): - if method == 'DELETE': - body = self.fixtures.load( - 'zones_us-central1-a_instances_node-name_delete.json') - else: - body = self.fixtures.load( - 'zones_us-central1-a_instances_node-name.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_node_name_attachDisk( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us-central1-a_instances_node-name_attachDisk_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_node_name_detachDisk( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us-central1-a_instances_node-name_detachDisk_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_node_name_setTags( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us-central1-a_instances_node-name_setTags_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_node_name_reset( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us-central1-a_instances_node-name_reset_post.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_lcnode_000(self, method, url, body, - headers): - if method == 'DELETE': - body = self.fixtures.load( - 'zones_us-central1-a_instances_lcnode-000_delete.json') - else: - body = self.fixtures.load( - 'zones_us-central1-a_instances_lcnode-000.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_instances_lcnode_001(self, method, url, body, - headers): - if method == 'DELETE': - body = self.fixtures.load( - 'zones_us-central1-a_instances_lcnode-001_delete.json') - else: - body = self.fixtures.load( - 'zones_us-central1-a_instances_lcnode-001.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_b_instances_libcloud_lb_demo_www_000( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us-central1-b_instances_libcloud-lb-demo-www-000.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_b_instances_libcloud_lb_demo_www_001( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us-central1-b_instances_libcloud-lb-demo-www-001.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_b_instances_libcloud_lb_demo_www_002( - self, method, url, body, headers): - body = self.fixtures.load( - 'zones_us-central1-b_instances_libcloud-lb-demo-www-002.json') - return (httplib.NOT_FOUND, body, self.json_hdr, - httplib.responses[httplib.NOT_FOUND]) - - def _zones_us_central1_a(self, method, url, body, headers): - body = self.fixtures.load('zones_us-central1-a.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_machineTypes(self, method, url, body, headers): - body = self.fixtures.load('zones_us-central1-a_machineTypes.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_europe_west1_a_machineTypes_n1_standard_1(self, method, url, - body, headers): - body = self.fixtures.load( - 'zones_europe-west1-a_machineTypes_n1-standard-1.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - def _zones_us_central1_a_machineTypes_n1_standard_1(self, method, url, - body, headers): - body = self.fixtures.load( - 'zones_us-central1-a_machineTypes_n1-standard-1.json') - return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_gogrid.py b/awx/lib/site-packages/libcloud/test/compute/test_gogrid.py deleted file mode 100644 index f7ceae63c6..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_gogrid.py +++ /dev/null @@ -1,283 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import parse_qs - -from libcloud.compute.base import NodeState, NodeLocation -from libcloud.common.types import LibcloudError, InvalidCredsError -from libcloud.common.gogrid import GoGridIpAddress -from libcloud.compute.drivers.gogrid import GoGridNodeDriver -from libcloud.compute.base import Node, NodeImage, NodeSize - -from libcloud.test import MockHttp # pylint: disable-msg=E0611 -from libcloud.test.compute import TestCaseMixin # pylint: disable-msg=E0611 -from libcloud.test.file_fixtures import ComputeFileFixtures # pylint: disable-msg=E0611 - - -class GoGridTests(unittest.TestCase, TestCaseMixin): - - def setUp(self): - GoGridNodeDriver.connectionCls.conn_classes = (None, GoGridMockHttp) - GoGridMockHttp.type = None - self.driver = GoGridNodeDriver("foo", "bar") - - def _get_test_512Mb_node_size(self): - return NodeSize(id='512Mb', - name=None, - ram=None, - disk=None, - bandwidth=None, - price=None, - driver=self.driver) - - def test_create_node(self): - image = NodeImage(1531, None, self.driver) - node = self.driver.create_node( - name='test1', - image=image, - size=self._get_test_512Mb_node_size()) - self.assertEqual(node.name, 'test1') - self.assertTrue(node.id is not None) - self.assertEqual(node.extra['password'], 'bebebe') - - def test_list_nodes(self): - node = self.driver.list_nodes()[0] - - self.assertEqual(node.id, '90967') - self.assertEqual(node.extra['password'], 'bebebe') - self.assertEqual(node.extra['description'], 'test server') - - def test_reboot_node(self): - node = Node(90967, None, None, None, None, self.driver) - ret = self.driver.reboot_node(node) - self.assertTrue(ret) - - def test_reboot_node_not_successful(self): - GoGridMockHttp.type = 'FAIL' - node = Node(90967, None, None, None, None, self.driver) - - try: - self.driver.reboot_node(node) - except Exception: - pass - else: - self.fail('Exception was not thrown') - - def test_destroy_node(self): - node = Node(90967, None, None, None, None, self.driver) - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - def test_list_images(self): - images = self.driver.list_images() - image = images[0] - self.assertEqual(len(images), 4) - self.assertEqual(image.name, 'CentOS 5.3 (32-bit) w/ None') - self.assertEqual(image.id, '1531') - - location = NodeLocation( - id='gogrid/GSI-939ef909-84b8-4a2f-ad56-02ccd7da05ff.img', - name='test location', country='Slovenia', - driver=self.driver) - images = self.driver.list_images(location=location) - image = images[0] - self.assertEqual(len(images), 4) - self.assertEqual(image.name, 'CentOS 5.3 (32-bit) w/ None') - self.assertEqual(image.id, '1531') - - def test_malformed_reply(self): - GoGridMockHttp.type = 'FAIL' - try: - self.driver.list_images() - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(isinstance(e, LibcloudError)) - else: - self.fail("test should have thrown") - - def test_invalid_creds(self): - GoGridMockHttp.type = 'FAIL' - try: - self.driver.list_nodes() - except InvalidCredsError: - e = sys.exc_info()[1] - self.assertTrue(e.driver is not None) - self.assertEqual(e.driver.name, self.driver.name) - else: - self.fail("test should have thrown") - - def test_node_creation_without_free_public_ips(self): - GoGridMockHttp.type = 'NOPUBIPS' - try: - image = NodeImage(1531, None, self.driver) - self.driver.create_node( - name='test1', - image=image, - size=self._get_test_512Mb_node_size()) - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(isinstance(e, LibcloudError)) - self.assertTrue(e.driver is not None) - self.assertEqual(e.driver.name, self.driver.name) - else: - self.fail("test should have thrown") - - def test_list_locations(self): - locations = self.driver.list_locations() - location_names = [location.name for location in locations] - - self.assertEqual(len(locations), 2) - for i in 0, 1: - self.assertTrue(isinstance(locations[i], NodeLocation)) - self.assertTrue("US-West-1" in location_names) - self.assertTrue("US-East-1" in location_names) - - def test_ex_save_image(self): - node = self.driver.list_nodes()[0] - image = self.driver.ex_save_image(node, "testimage") - self.assertEqual(image.name, "testimage") - - def test_ex_edit_image(self): - image = self.driver.list_images()[0] - ret = self.driver.ex_edit_image(image=image, public=False, - ex_description="test", name="testname") - - self.assertTrue(isinstance(ret, NodeImage)) - - def test_ex_edit_node(self): - node = Node(id=90967, name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - ret = self.driver.ex_edit_node(node=node, - size=self._get_test_512Mb_node_size()) - - self.assertTrue(isinstance(ret, Node)) - - def test_ex_list_ips(self): - ips = self.driver.ex_list_ips() - - expected_ips = {"192.168.75.66": GoGridIpAddress(id="5348099", - ip="192.168.75.66", public=True, state="Unassigned", - subnet="192.168.75.64/255.255.255.240"), - "192.168.75.67": GoGridIpAddress(id="5348100", - ip="192.168.75.67", public=True, state="Assigned", - subnet="192.168.75.64/255.255.255.240"), - "192.168.75.68": GoGridIpAddress(id="5348101", - ip="192.168.75.68", public=False, state="Unassigned", - subnet="192.168.75.64/255.255.255.240")} - - self.assertEqual(len(expected_ips), 3) - - for ip in ips: - self.assertTrue(ip.ip in expected_ips) - self.assertEqual(ip.public, expected_ips[ip.ip].public) - self.assertEqual(ip.state, expected_ips[ip.ip].state) - self.assertEqual(ip.subnet, expected_ips[ip.ip].subnet) - - del expected_ips[ip.ip] - - self.assertEqual(len(expected_ips), 0) - - def test_get_state_invalid(self): - state = self.driver._get_state('invalid') - self.assertEqual(state, NodeState.UNKNOWN) - - -class GoGridMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('gogrid') - - def _api_grid_image_list(self, method, url, body, headers): - body = self.fixtures.load('image_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_image_list_FAIL(self, method, url, body, headers): - body = "

some non valid json here

" - return (httplib.SERVICE_UNAVAILABLE, body, {}, - httplib.responses[httplib.SERVICE_UNAVAILABLE]) - - def _api_grid_server_list(self, method, url, body, headers): - body = self.fixtures.load('server_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - _api_grid_server_list_NOPUBIPS = _api_grid_server_list - - def _api_grid_server_list_FAIL(self, method, url, body, headers): - return (httplib.FORBIDDEN, - "123", {}, httplib.responses[httplib.FORBIDDEN]) - - def _api_grid_ip_list(self, method, url, body, headers): - body = self.fixtures.load('ip_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_ip_list_NOPUBIPS(self, method, url, body, headers): - body = self.fixtures.load('ip_list_empty.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_server_power(self, method, url, body, headers): - body = self.fixtures.load('server_power.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_server_power_FAIL(self, method, url, body, headers): - body = self.fixtures.load('server_power_fail.json') - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_server_add(self, method, url, body, headers): - body = self.fixtures.load('server_add.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - _api_grid_server_add_NOPUBIPS = _api_grid_server_add - - def _api_grid_server_delete(self, method, url, body, headers): - body = self.fixtures.load('server_delete.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_server_edit(self, method, url, body, headers): - body = self.fixtures.load('server_edit.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_support_password_list(self, method, url, body, headers): - body = self.fixtures.load('password_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - _api_support_password_list_NOPUBIPS = _api_support_password_list - - def _api_grid_image_save(self, method, url, body, headers): - body = self.fixtures.load('image_save.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_image_edit(self, method, url, body, headers): - # edit method is quite similar to save method from the response - # perspective - body = self.fixtures.load('image_save.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_common_lookup_list(self, method, url, body, headers): - _valid_lookups = ("ip.datacenter",) - - lookup = parse_qs(urlparse.urlparse(url).query)["lookup"][0] - if lookup in _valid_lookups: - fixture_path = "lookup_list_%s.json" % \ - (lookup.replace(".", "_")) - else: - raise NotImplementedError - body = self.fixtures.load(fixture_path) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_gridspot.py b/awx/lib/site-packages/libcloud/test/compute/test_gridspot.py deleted file mode 100644 index 0160f8e4e5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_gridspot.py +++ /dev/null @@ -1,234 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest -from libcloud.utils.py3 import httplib - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.common.types import InvalidCredsError -from libcloud.compute.drivers.gridspot import GridspotNodeDriver -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.secrets import GRIDSPOT_PARAMS - - -class GridspotTest(unittest.TestCase, TestCaseMixin): - - def setUp(self): - GridspotNodeDriver.connectionCls.conn_classes = ( - None, - GridspotMockHttp - ) - GridspotMockHttp.type = None - self.driver = GridspotNodeDriver(*GRIDSPOT_PARAMS) - - def test_invalid_creds(self): - """ - Tests the error-handling for passing a bad API Key to the Gridspot API - """ - GridspotMockHttp.type = 'BAD_AUTH' - try: - self.driver.list_nodes() - # Above command should have thrown an InvalidCredsException - self.assertTrue(False) - except InvalidCredsError: - self.assertTrue(True) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 2) - - running_node = nodes[0] - starting_node = nodes[1] - - self.assertEqual(running_node.id, 'inst_CP2WrQi2WIS4iheyAVkQYw') - self.assertEqual(running_node.state, NodeState.RUNNING) - self.assertTrue('69.4.239.74' in running_node.public_ips) - self.assertEqual(running_node.extra['port'], 62394) - self.assertEqual(running_node.extra['vm_ram'], 1429436743) - self.assertEqual(running_node.extra['start_state_time'], 1342108905) - self.assertEqual(running_node.extra['vm_num_logical_cores'], 8) - self.assertEqual(running_node.extra['vm_num_physical_cores'], 4) - self.assertEqual(running_node.extra['winning_bid_id'], - 'bid_X5xhotGYiGUk7_RmIqVafA') - self.assertFalse('ended_state_time' in running_node.extra) - self.assertEqual(running_node.extra['running_state_time'], 1342108989) - - self.assertEqual(starting_node.id, 'inst_CP2WrQi2WIS4iheyAVkQYw2') - self.assertEqual(starting_node.state, NodeState.PENDING) - self.assertTrue('69.4.239.74' in starting_node.public_ips) - self.assertEqual(starting_node.extra['port'], 62395) - self.assertEqual(starting_node.extra['vm_ram'], 1429436744) - self.assertEqual(starting_node.extra['start_state_time'], 1342108906) - self.assertEqual(starting_node.extra['vm_num_logical_cores'], 7) - self.assertEqual(starting_node.extra['vm_num_physical_cores'], 5) - self.assertEqual(starting_node.extra['winning_bid_id'], - 'bid_X5xhotGYiGUk7_RmIqVafA1') - self.assertFalse('ended_state_time' in starting_node.extra) - self.assertEqual(starting_node.extra['running_state_time'], 1342108990) - - def test_create_node(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_destroy_node(self): - """ - Test destroy_node for Gridspot driver - """ - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.destroy_node(node)) - - def test_destroy_node_failure(self): - """ - Gridspot does not fail a destroy node unless the parameters are bad, in - which case it 404s - """ - self.assertTrue(True) - - def test_reboot_node(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_reboot_node_failure(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_resize_node(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_reboot_node_response(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_list_images_response(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_create_node_response(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_destroy_node_response(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_list_sizes_response(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_resize_node_failure(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_list_images(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_list_sizes(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_list_locations(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - def test_list_locations_response(self): - """ - Gridspot does not implement this functionality - """ - self.assertTrue(True) - - -class GridspotMockHttp(MockHttp): - - def _compute_api_v1_list_instances_BAD_AUTH(self, method, url, body, - headers): - return (httplib.NOT_FOUND, "", {}, - httplib.responses[httplib.NOT_FOUND]) - - def _compute_api_v1_list_instances(self, method, url, body, headers): - body = json.dumps({ - "instances": [ - { - "instance_id": "inst_CP2WrQi2WIS4iheyAVkQYw", - "vm_num_logical_cores": 8, - "vm_num_physical_cores": 4, - "winning_bid_id": "bid_X5xhotGYiGUk7_RmIqVafA", - "vm_ram": 1429436743, - "start_state_time": 1342108905, - "vm_ssh_wan_ip_endpoint": "69.4.239.74:62394", - "current_state": "Running", - "ended_state_time": "null", - "running_state_time": 1342108989 - }, - { - "instance_id": "inst_CP2WrQi2WIS4iheyAVkQYw2", - "vm_num_logical_cores": 7, - "vm_num_physical_cores": 5, - "winning_bid_id": "bid_X5xhotGYiGUk7_RmIqVafA1", - "vm_ram": 1429436744, - "start_state_time": 1342108906, - "vm_ssh_wan_ip_endpoint": "69.4.239.74:62395", - "current_state": "Starting", - "ended_state_time": "null", - "running_state_time": 1342108990 - } - ], - "exception_name": "" - }) - - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _compute_api_v1_stop_instance(self, method, url, body, headers): - body = json.dumps({"exception_name": ""}) - - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_hostvirtual.py b/awx/lib/site-packages/libcloud/test/compute/test_hostvirtual.py deleted file mode 100644 index 7098a637e5..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_hostvirtual.py +++ /dev/null @@ -1,188 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest - -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.hostvirtual import HostVirtualNodeDriver -from libcloud.compute.types import NodeState -from libcloud.compute.base import NodeAuthPassword -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import HOSTVIRTUAL_PARAMS - - -class HostVirtualTest(unittest.TestCase): - - def setUp(self): - HostVirtualNodeDriver.connectionCls.conn_classes = ( - None, HostVirtualMockHttp) - self.driver = HostVirtualNodeDriver(*HOSTVIRTUAL_PARAMS) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 4) - self.assertEqual(len(nodes[0].public_ips), 1) - self.assertEqual(len(nodes[1].public_ips), 1) - self.assertEqual(len(nodes[0].private_ips), 0) - self.assertEqual(len(nodes[1].private_ips), 0) - self.assertTrue('208.111.39.118' in nodes[1].public_ips) - self.assertTrue('208.111.45.250' in nodes[0].public_ips) - self.assertEqual(nodes[3].state, NodeState.RUNNING) - self.assertEqual(nodes[1].state, NodeState.TERMINATED) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 14) - self.assertEqual(sizes[0].id, '31') - self.assertEqual(sizes[4].id, '71') - self.assertEqual(sizes[2].ram, '512MB') - self.assertEqual(sizes[2].disk, '20GB') - self.assertEqual(sizes[3].bandwidth, '600GB') - self.assertEqual(sizes[1].price, '15.00') - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), 8) - self.assertEqual(images[0].id, '1739') - self.assertEqual(images[0].name, 'Gentoo 2012 (0619) i386') - - def test_list_locations(self): - locations = self.driver.list_locations() - self.assertEqual(locations[0].id, '3') - self.assertEqual(locations[0].name, 'SJC - San Jose, CA') - self.assertEqual(locations[1].id, '13') - self.assertEqual(locations[1].name, 'IAD2- Reston, VA') - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.reboot_node(node)) - - def test_ex_get_node(self): - node = self.driver.ex_get_node(node_id='62291') - self.assertEqual(node.id, '62291') - self.assertEqual(node.name, 'server1.vr-cluster.org') - self.assertEqual(node.state, NodeState.TERMINATED) - self.assertTrue('208.111.45.250' in node.public_ips) - - def test_ex_stop_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.ex_stop_node(node)) - - def test_ex_start_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.ex_start_node(node)) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.destroy_node(node)) - - def test_ex_delete_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.ex_delete_node(node)) - - def test_create_node(self): - auth = NodeAuthPassword('vr!@#hosted#@!') - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - node = self.driver.create_node( - name='test.com', - image=image, - size=size, - auth=auth - ) - self.assertEqual('62291', node.id) - self.assertEqual('server1.vr-cluster.org', node.name) - - def test_ex_provision_node(self): - node = self.driver.list_nodes()[0] - auth = NodeAuthPassword('vr!@#hosted#@!') - self.assertTrue(self.driver.ex_provision_node( - node=node, - auth=auth - )) - - def test_create_node_in_location(self): - auth = NodeAuthPassword('vr!@#hosted#@!') - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - location = self.driver.list_locations()[1] - node = self.driver.create_node( - name='test.com', - image=image, - size=size, - auth=auth, - location=location - ) - self.assertEqual('62291', node.id) - self.assertEqual('server1.vr-cluster.org', node.name) - - -class HostVirtualMockHttp(MockHttp): - fixtures = ComputeFileFixtures('hostvirtual') - - def _cloud_servers(self, method, url, body, headers): - body = self.fixtures.load('list_nodes.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_server(self, method, url, body, headers): - body = self.fixtures.load('get_node.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_sizes(self, method, url, body, headers): - body = self.fixtures.load('list_sizes.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_images(self, method, url, body, headers): - body = self.fixtures.load('list_images.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_locations(self, method, url, body, headers): - body = self.fixtures.load('list_locations.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_cancel(self, method, url, body, headers): - body = self.fixtures.load('node_destroy.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_server_reboot(self, method, url, body, headers): - body = self.fixtures.load('node_reboot.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_server_shutdown(self, method, url, body, headers): - body = self.fixtures.load('node_stop.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_server_start(self, method, url, body, headers): - body = self.fixtures.load('node_start.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_buy(self, method, url, body, headers): - body = self.fixtures.load('create_node.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_server_build(self, method, url, body, headers): - body = self.fixtures.load('create_node.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _cloud_server_delete(self, method, url, body, headers): - body = self.fixtures.load('node_destroy.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) - -# vim:autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python diff --git a/awx/lib/site-packages/libcloud/test/compute/test_ibm_sce.py b/awx/lib/site-packages/libcloud/test/compute/test_ibm_sce.py deleted file mode 100644 index 55071a43e8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_ibm_sce.py +++ /dev/null @@ -1,325 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -import unittest -from libcloud.utils.py3 import httplib -import sys - -from libcloud.compute.types import InvalidCredsError -from libcloud.compute.drivers.ibm_sce import IBMNodeDriver as IBM -from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import IBM_PARAMS - - -class IBMTests(unittest.TestCase, TestCaseMixin): - - """ - Tests the IBM SmartCloud Enterprise driver. - """ - - def setUp(self): - IBM.connectionCls.conn_classes = (None, IBMMockHttp) - IBMMockHttp.type = None - self.driver = IBM(*IBM_PARAMS) - - def test_auth(self): - IBMMockHttp.type = 'UNAUTHORIZED' - - try: - self.driver.list_nodes() - except InvalidCredsError: - e = sys.exc_info()[1] - self.assertTrue(isinstance(e, InvalidCredsError)) - self.assertEqual(e.value, '401: Unauthorized') - else: - self.fail('test should have thrown') - - def test_list_nodes(self): - ret = self.driver.list_nodes() - self.assertEqual(len(ret), 3) - self.assertEqual(ret[0].id, '26557') - self.assertEqual(ret[0].name, 'Insight Instance') - self.assertEqual(ret[0].public_ips, ['129.33.196.128']) - self.assertEqual(ret[0].private_ips, []) # Private IPs not supported - self.assertEqual(ret[1].public_ips, []) # Node is non-active (no IP) - self.assertEqual(ret[1].private_ips, []) - self.assertEqual(ret[1].id, '28193') - - def test_list_sizes(self): - ret = self.driver.list_sizes() - self.assertEqual(len(ret), 9) # 9 instance configurations supported - self.assertEqual(ret[0].id, 'BRZ32.1/2048/60*175') - self.assertEqual(ret[1].id, 'BRZ64.2/4096/60*500*350') - self.assertEqual(ret[2].id, 'COP32.1/2048/60') - self.assertEqual(ret[0].name, 'Bronze 32 bit') - self.assertEqual(ret[0].disk, None) - - def test_list_images(self): - ret = self.driver.list_images() - self.assertEqual(len(ret), 21) - self.assertEqual(ret[10].name, "Rational Asset Manager 7.2.0.1") - self.assertEqual(ret[9].id, '10002573') - - def test_list_locations(self): - ret = self.driver.list_locations() - self.assertEqual(len(ret), 6) - self.assertEqual(ret[0].id, '41') - self.assertEqual(ret[0].name, 'Raleigh') - self.assertEqual(ret[0].country, 'U.S.A') - - def test_create_node(self): - # Test creation of node - IBMMockHttp.type = 'CREATE' - image = NodeImage(id=11, name='Rational Insight', driver=self.driver) - size = NodeSize('LARGE', 'LARGE', None, None, None, None, self.driver) - location = NodeLocation('1', 'POK', 'US', driver=self.driver) - ret = self.driver.create_node(name='RationalInsight4', - image=image, - size=size, - location=location, - publicKey='MyPublicKey', - configurationData={ - 'insight_admin_password': 'myPassword1', - 'db2_admin_password': 'myPassword2', - 'report_user_password': 'myPassword3'}) - self.assertTrue(isinstance(ret, Node)) - self.assertEqual(ret.name, 'RationalInsight4') - - # Test creation attempt with invalid location - IBMMockHttp.type = 'CREATE_INVALID' - location = NodeLocation('3', 'DOESNOTEXIST', 'US', driver=self.driver) - try: - ret = self.driver.create_node(name='RationalInsight5', - image=image, - size=size, - location=location, - publicKey='MyPublicKey', - configurationData={ - 'insight_admin_password': 'myPassword1', - 'db2_admin_password': 'myPassword2', - 'report_user_password': 'myPassword3'}) - except Exception: - e = sys.exc_info()[1] - self.assertEqual(e.args[0], 'Error 412: No DataCenter with id: 3') - else: - self.fail('test should have thrown') - - def test_destroy_node(self): - # Delete existent node - nodes = self.driver.list_nodes() # retrieves 3 nodes - self.assertEqual(len(nodes), 3) - IBMMockHttp.type = 'DELETE' - toDelete = nodes[1] - ret = self.driver.destroy_node(toDelete) - self.assertTrue(ret) - - # Delete non-existent node - IBMMockHttp.type = 'DELETED' - nodes = self.driver.list_nodes() # retrieves 2 nodes - self.assertEqual(len(nodes), 2) - try: - self.driver.destroy_node(toDelete) # delete non-existent node - except Exception: - e = sys.exc_info()[1] - self.assertEqual(e.args[0], 'Error 404: Invalid Instance ID 28193') - else: - self.fail('test should have thrown') - - def test_reboot_node(self): - nodes = self.driver.list_nodes() - IBMMockHttp.type = 'REBOOT' - - # Reboot active node - self.assertEqual(len(nodes), 3) - ret = self.driver.reboot_node(nodes[0]) - self.assertTrue(ret) - - # Reboot inactive node - try: - ret = self.driver.reboot_node(nodes[1]) - except Exception: - e = sys.exc_info()[1] - self.assertEqual( - e.args[0], 'Error 412: Instance must be in the Active state') - else: - self.fail('test should have thrown') - - def test_list_volumes(self): - ret = self.driver.list_volumes() - self.assertEqual(len(ret), 1) - self.assertEqual(ret[0].name, 'libcloudvol') - self.assertEqual(ret[0].extra['location'], '141') - self.assertEqual(ret[0].size, '2048') - self.assertEqual(ret[0].id, '39281') - - def test_attach_volume(self): - vols = self.driver.list_volumes() - nodes = self.driver.list_nodes() - IBMMockHttp.type = 'ATTACH' - ret = self.driver.attach_volume(nodes[0], vols[0]) - self.assertTrue(ret) - - def test_create_volume(self): - IBMMockHttp.type = 'CREATE' - ret = self.driver.create_volume('256', - 'test-volume', - location='141', - format='RAW', - offering_id='20001208') - self.assertEqual(ret.id, '39293') - self.assertEqual(ret.size, '256') - self.assertEqual(ret.name, 'test-volume') - self.assertEqual(ret.extra['location'], '141') - - def test_destroy_volume(self): - vols = self.driver.list_volumes() - IBMMockHttp.type = 'DESTROY' - ret = self.driver.destroy_volume(vols[0]) - self.assertTrue(ret) - - def test_ex_destroy_image(self): - image = self.driver.list_images() - IBMMockHttp.type = 'DESTROY' - ret = self.driver.ex_destroy_image(image[0]) - self.assertTrue(ret) - - def test_detach_volume(self): - nodes = self.driver.list_nodes() - vols = self.driver.list_volumes() - IBMMockHttp.type = 'DETACH' - ret = self.driver.detach_volume(nodes[0], vols[0]) - self.assertTrue(ret) - - def test_ex_allocate_address(self): - IBMMockHttp.type = 'ALLOCATE' - ret = self.driver.ex_allocate_address('141', '20001223') - self.assertEqual(ret.id, '292795') - self.assertEqual(ret.state, '0') - self.assertEqual(ret.options['location'], '141') - - def test_ex_delete_address(self): - IBMMockHttp.type = 'DELETE' - ret = self.driver.ex_delete_address('292795') - self.assertTrue(ret) - - def test_ex_list_addresses(self): - ret = self.driver.ex_list_addresses() - self.assertEqual(ret[0].ip, '170.225.160.218') - self.assertEqual(ret[0].options['location'], '141') - self.assertEqual(ret[0].id, '292795') - self.assertEqual(ret[0].state, '2') - - def test_ex_list_storage_offerings(self): - ret = self.driver.ex_list_storage_offerings() - self.assertEqual(ret[0].name, 'Small') - self.assertEqual(ret[0].location, '61') - self.assertEqual(ret[0].id, '20001208') - - -class IBMMockHttp(MockHttp): - fixtures = ComputeFileFixtures('ibm_sce') - - def _computecloud_enterprise_api_rest_20100331_instances(self, method, url, body, headers): - body = self.fixtures.load('instances.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_DELETED(self, method, url, body, headers): - body = self.fixtures.load('instances_deleted.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_UNAUTHORIZED(self, method, url, body, headers): - return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.UNAUTHORIZED]) - - def _computecloud_enterprise_api_rest_20100331_offerings_image(self, method, url, body, headers): - body = self.fixtures.load('images.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_locations(self, method, url, body, headers): - body = self.fixtures.load('locations.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_26557_REBOOT(self, method, url, body, headers): - body = self.fixtures.load('reboot_active.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_28193_REBOOT(self, method, url, body, headers): - return (412, 'Error 412: Instance must be in the Active state', {}, 'Precondition Failed') - - def _computecloud_enterprise_api_rest_20100331_instances_28193_DELETE(self, method, url, body, headers): - body = self.fixtures.load('delete.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_28193_DELETED(self, method, url, body, headers): - return (404, 'Error 404: Invalid Instance ID 28193', {}, 'Precondition Failed') - - def _computecloud_enterprise_api_rest_20100331_instances_CREATE(self, method, url, body, headers): - body = self.fixtures.load('create.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_CREATE_INVALID(self, method, url, body, headers): - return (412, 'Error 412: No DataCenter with id: 3', {}, 'Precondition Failed') - - def _computecloud_enterprise_api_rest_20100331_storage(self, method, url, body, headers): - body = self.fixtures.load('list_volumes.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_26557_ATTACH(self, method, url, body, headers): - body = self.fixtures.load('attach_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_storage_CREATE(self, method, url, body, headers): - body = self.fixtures.load('create_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_storage_39281_DESTROY(self, method, url, body, headers): - body = self.fixtures.load('destroy_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_offerings_image_2_DESTROY(self, method, url, body, headers): - body = self.fixtures.load('destroy_image.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_instances_26557_DETACH(self, method, url, body, headers): - body = self.fixtures.load('detach_volume.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_addresses_ALLOCATE(self, method, url, body, headers): - body = self.fixtures.load('allocate_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_addresses_292795_DELETE(self, method, url, body, headers): - body = self.fixtures.load('delete_address.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_addresses(self, method, url, body, headers): - body = self.fixtures.load('list_addresses.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _computecloud_enterprise_api_rest_20100331_offerings_storage(self, method, url, body, headers): - body = self.fixtures.load('list_storage_offerings.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - # This is only to accommodate the response tests built into test\__init__.py - def _computecloud_enterprise_api_rest_20100331_instances_26557(self, method, url, body, headers): - if method == 'DELETE': - body = self.fixtures.load('delete.xml') - else: - body = self.fixtures.load('reboot_active.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_ikoula.py b/awx/lib/site-packages/libcloud/test/compute/test_ikoula.py deleted file mode 100644 index 45dda25f4b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_ikoula.py +++ /dev/null @@ -1,28 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - -from libcloud.compute.drivers.ikoula import IkoulaNodeDriver -from libcloud.test.compute.test_cloudstack import CloudStackCommonTestCase - -from libcloud.test import unittest - - -class IkoulaNodeDriverTestCase(CloudStackCommonTestCase, unittest.TestCase): - driver_klass = IkoulaNodeDriver - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_joyent.py b/awx/lib/site-packages/libcloud/test/compute/test_joyent.py deleted file mode 100644 index 86b2890e71..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_joyent.py +++ /dev/null @@ -1,128 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - -from libcloud.utils.py3 import httplib -from libcloud.common.types import LibcloudError -from libcloud.compute.base import NodeState -from libcloud.compute.drivers.joyent import JoyentNodeDriver - -from libcloud.test import MockHttp, unittest -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import JOYENT_PARAMS - - -class JoyentTestCase(unittest.TestCase): - - def setUp(self): - JoyentNodeDriver.connectionCls.conn_classes = (None, JoyentHttp) - self.driver = JoyentNodeDriver(*JOYENT_PARAMS) - - def test_instantiate_multiple_drivers_with_different_region(self): - kwargs1 = {'region': 'us-east-1'} - kwargs2 = {'region': 'us-west-1'} - driver1 = JoyentNodeDriver(*JOYENT_PARAMS, **kwargs1) - driver2 = JoyentNodeDriver(*JOYENT_PARAMS, **kwargs2) - - self.assertTrue(driver1.connection.host.startswith(kwargs1['region'])) - self.assertTrue(driver2.connection.host.startswith(kwargs2['region'])) - - driver1.list_nodes() - driver2.list_nodes() - driver1.list_nodes() - - self.assertTrue(driver1.connection.host.startswith(kwargs1['region'])) - self.assertTrue(driver2.connection.host.startswith(kwargs2['region'])) - - def test_location_backward_compatibility(self): - kwargs = {'location': 'us-west-1'} - driver = JoyentNodeDriver(*JOYENT_PARAMS, **kwargs) - self.assertTrue(driver.connection.host.startswith(kwargs['location'])) - - def test_instantiate_invalid_region(self): - expected_msg = 'Invalid region.+' - - self.assertRaisesRegexp(LibcloudError, expected_msg, JoyentNodeDriver, - 'user', 'key', location='invalid') - self.assertRaisesRegexp(LibcloudError, expected_msg, JoyentNodeDriver, - 'user', 'key', region='invalid') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - - self.assertEqual(sizes[0].ram, 16384) - - def test_list_images(self): - images = self.driver.list_images() - - self.assertEqual(images[0].name, 'nodejs') - - def test_list_nodes_with_and_without_credentials(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 2) - - node = nodes[0] - self.assertEqual(node.public_ips[0], '165.225.129.129') - self.assertEqual(node.private_ips[0], '10.112.1.130') - self.assertEqual(node.state, NodeState.RUNNING) - - node = nodes[1] - self.assertEqual(node.public_ips[0], '165.225.129.128') - self.assertEqual(node.private_ips[0], '10.112.1.131') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.extra['password'], 'abc') - - def test_create_node(self): - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - node = self.driver.create_node(image=image, size=size, name='testlc') - - self.assertEqual(node.name, 'testlc') - - def test_ex_stop_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.ex_stop_node(node)) - - def test_ex_start_node(self): - node = self.driver.list_nodes()[0] - self.assertTrue(self.driver.ex_start_node(node)) - - -class JoyentHttp(MockHttp): - fixtures = ComputeFileFixtures('joyent') - - def _my_packages(self, method, url, body, headers): - body = self.fixtures.load('my_packages.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _my_datasets(self, method, url, body, headers): - body = self.fixtures.load('my_datasets.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _my_machines(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('my_machines.json') - elif method == 'POST': - body = self.fixtures.load('my_machines_create.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _my_machines_2fb67f5f_53f2_40ab_9d99_b9ff68cfb2ab(self, method, url, - body, headers): - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_ktucloud.py b/awx/lib/site-packages/libcloud/test/compute/test_ktucloud.py deleted file mode 100644 index 83a0838e13..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_ktucloud.py +++ /dev/null @@ -1,133 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import parse_qsl - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.compute.drivers.ktucloud import KTUCloudNodeDriver - -from libcloud.test import MockHttpTestCase -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class KTUCloudNodeDriverTest(unittest.TestCase, TestCaseMixin): - - def setUp(self): - KTUCloudNodeDriver.connectionCls.conn_classes = \ - (None, KTUCloudStackMockHttp) - self.driver = KTUCloudNodeDriver('apikey', 'secret', - path='/test/path', - host='api.dummy.com') - self.driver.path = '/test/path' - self.driver.type = -1 - KTUCloudStackMockHttp.fixture_tag = 'default' - self.driver.connection.poll_interval = 0.0 - - def test_create_node_immediate_failure(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - KTUCloudStackMockHttp.fixture_tag = 'deployfail' - try: - self.driver.create_node(name='node-name', image=image, size=size) - except: - return - self.assertTrue(False) - - def test_create_node_delayed_failure(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - KTUCloudStackMockHttp.fixture_tag = 'deployfail2' - try: - self.driver.create_node(name='node-name', image=image, size=size) - except: - return - self.assertTrue(False) - - def test_list_images_no_images_available(self): - KTUCloudStackMockHttp.fixture_tag = 'notemplates' - - images = self.driver.list_images() - self.assertEqual(0, len(images)) - - def test_list_images_available(self): - images = self.driver.list_images() - self.assertEqual(112, len(images)) - - def test_list_sizes_available(self): - sizes = self.driver.list_sizes() - self.assertEqual(112, len(sizes)) - - def test_list_sizes_nodisk(self): - KTUCloudStackMockHttp.fixture_tag = 'nodisk' - - sizes = self.driver.list_sizes() - self.assertEqual(2, len(sizes)) - - check = False - size = sizes[1] - if size.id == KTUCloudNodeDriver.EMPTY_DISKOFFERINGID: - check = True - - self.assertTrue(check) - - -class KTUCloudStackMockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('ktucloud') - fixture_tag = 'default' - - def _load_fixture(self, fixture): - body = self.fixtures.load(fixture) - return body, json.loads(body) - - def _test_path(self, method, url, body, headers): - url = urlparse.urlparse(url) - query = dict(parse_qsl(url.query)) - - self.assertTrue('apiKey' in query) - self.assertTrue('command' in query) - self.assertTrue('response' in query) - self.assertTrue('signature' in query) - - self.assertTrue(query['response'] == 'json') - - del query['apiKey'] - del query['response'] - del query['signature'] - command = query.pop('command') - - if hasattr(self, '_cmd_' + command): - return getattr(self, '_cmd_' + command)(**query) - else: - fixture = command + '_' + self.fixture_tag + '.json' - body, obj = self._load_fixture(fixture) - return (httplib.OK, body, obj, httplib.responses[httplib.OK]) - - def _cmd_queryAsyncJobResult(self, jobid): - fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json' - body, obj = self._load_fixture(fixture) - return (httplib.OK, body, obj, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_linode.py b/awx/lib/site-packages/libcloud/test/compute/test_linode.py deleted file mode 100644 index 4c7c80f10c..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_linode.py +++ /dev/null @@ -1,164 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Maintainer: Jed Smith -# Based upon code written by Alex Polvi -# - -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.linode import LinodeNodeDriver -from libcloud.compute.base import Node, NodeAuthPassword, NodeAuthSSHKey - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class LinodeTest(unittest.TestCase, TestCaseMixin): - # The Linode test suite - - def setUp(self): - LinodeNodeDriver.connectionCls.conn_classes = (None, LinodeMockHttp) - LinodeMockHttp.use_param = 'api_action' - self.driver = LinodeNodeDriver('foo') - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 1) - node = nodes[0] - self.assertEqual(node.id, "8098") - self.assertEqual(node.name, 'api-node3') - self.assertEqual(node.extra['PLANID'], '1') - self.assertTrue('75.127.96.245' in node.public_ips) - self.assertEqual(node.private_ips, []) - - def test_reboot_node(self): - # An exception would indicate failure - node = self.driver.list_nodes()[0] - self.driver.reboot_node(node) - - def test_destroy_node(self): - # An exception would indicate failure - node = self.driver.list_nodes()[0] - self.driver.destroy_node(node) - - def test_create_node_password_auth(self): - # Will exception on failure - self.driver.create_node(name="Test", - location=self.driver.list_locations()[0], - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[6], - auth=NodeAuthPassword("test123")) - - def test_create_node_ssh_key_auth(self): - # Will exception on failure - node = self.driver.create_node(name="Test", - location=self.driver.list_locations()[ - 0], - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[6], - auth=NodeAuthSSHKey('foo')) - self.assertTrue(isinstance(node, Node)) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 8) - for size in sizes: - self.assertEqual(size.ram, int(size.name.split(" ")[1])) - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), 30) - - def test_create_node_response(self): - # should return a node object - node = self.driver.create_node(name="node-name", - location=self.driver.list_locations()[ - 0], - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[0], - auth=NodeAuthPassword("foobar")) - self.assertTrue(isinstance(node, Node)) - - -class LinodeMockHttp(MockHttp): - fixtures = ComputeFileFixtures('linode') - - def _avail_datacenters(self, method, url, body, headers): - body = self.fixtures.load('_avail_datacenters.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _avail_linodeplans(self, method, url, body, headers): - body = self.fixtures.load('_avail_linodeplans.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _avail_distributions(self, method, url, body, headers): - body = self.fixtures.load('_avail_distributions.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_create(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.create","DATA":{"LinodeID":8098}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_disk_createfromdistribution(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.disk.createFromDistribution","DATA":{"JobID":1298,"DiskID":55647}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_delete(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.delete","DATA":{"LinodeID":8098}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_update(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.update","DATA":{"LinodeID":8098}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_reboot(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.reboot","DATA":{"JobID":1305}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _avail_kernels(self, method, url, body, headers): - body = self.fixtures.load('_avail_kernels.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_disk_create(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.disk.create","DATA":{"JobID":1299,"DiskID":55648}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_boot(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.boot","DATA":{"JobID":1300}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_config_create(self, method, url, body, headers): - body = '{"ERRORARRAY":[],"ACTION":"linode.config.create","DATA":{"ConfigID":31239}}' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_list(self, method, url, body, headers): - body = self.fixtures.load('_linode_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _linode_ip_list(self, method, url, body, headers): - body = self.fixtures.load('_linode_ip_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _batch(self, method, url, body, headers): - body = self.fixtures.load('_batch.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_nephoscale.py b/awx/lib/site-packages/libcloud/test/compute/test_nephoscale.py deleted file mode 100644 index bb30f68a08..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_nephoscale.py +++ /dev/null @@ -1,188 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Created by Markos Gogoulos (https://mist.io) -# - -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.nephoscale import NephoscaleNodeDriver - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class NephoScaleTest(unittest.TestCase, TestCaseMixin): - - def setUp(self): - NephoscaleNodeDriver.connectionCls.conn_classes = ( - NephoscaleMockHttp, NephoscaleMockHttp) - self.driver = NephoscaleNodeDriver('user', 'password') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 13) - for size in sizes: - self.assertEqual(type(size.disk), int) - self.assertEqual(type(size.ram), int) - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), 18) - for image in images: - arch = image.extra.get('architecture') - self.assertTrue(arch.startswith('x86')) - - def test_list_locations(self): - locations = self.driver.list_locations() - self.assertEqual(len(locations), 2) - self.assertEqual(locations[0].name, "SJC-1") - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 2) - self.assertEqual(nodes[0].extra.get('zone'), 'RIC-1') - self.assertEqual(nodes[0].name, 'mongodb-staging') - self.assertEqual(nodes[0].extra.get('service_type'), - 'CS05 - 0.5GB, 1Core, 25GB') - - def test_list_keys(self): - keys = self.driver.ex_list_keypairs() - self.assertEqual(len(keys), 2) - self.assertEqual(keys[0].name, 'mistio-ssh') - - def test_list_ssh_keys(self): - ssh_keys = self.driver.ex_list_keypairs(ssh=True) - self.assertEqual(len(ssh_keys), 1) - self.assertTrue(ssh_keys[0].public_key.startswith('ssh-rsa')) - - def test_list_password_keys(self): - password_keys = self.driver.ex_list_keypairs(password=True) - self.assertEqual(len(password_keys), 1) - self.assertEquals(password_keys[0].password, '23d493j5') - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - result = self.driver.reboot_node(node) - self.assertTrue(result) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - result = self.driver.destroy_node(node) - self.assertTrue(result) - - def test_stop_node(self): - node = self.driver.list_nodes()[0] - result = self.driver.ex_stop_node(node) - self.assertTrue(result) - - def test_start_node(self): - node = self.driver.list_nodes()[0] - result = self.driver.ex_start_node(node) - self.assertTrue(result) - - def test_rename_node(self): - node = self.driver.list_nodes()[0] - result = self.driver.rename_node(node, 'new-name') - self.assertTrue(result) - - def test_create_node(self): - name = 'mongodb-staging' - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[3] - node = self.driver.create_node(name=name, - size=size, - nowait=True, - image=image) - self.assertEqual(node.name, 'mongodb-staging') - - def test_create_node_no_name(self): - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[3] - self.assertRaises(TypeError, self.driver.create_node, size=size, - image=image) - - def test_delete_ssh_keys(self): - self.assertTrue(self.driver.ex_delete_keypair(key_id=72209, ssh=True)) - - def test_delete_password_keys(self): - self.assertTrue(self.driver.ex_delete_keypair(key_id=72211)) - - -class NephoscaleMockHttp(MockHttp): - fixtures = ComputeFileFixtures('nephoscale') - - def _server_type_cloud(self, method, url, body, headers): - body = self.fixtures.load('list_sizes.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _server_cloud(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('success_action.json') - else: - body = self.fixtures.load('list_nodes.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _image_server(self, method, url, body, headers): - body = self.fixtures.load('list_images.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _datacenter_zone(self, method, url, body, headers): - body = self.fixtures.load('list_locations.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _key(self, method, url, body, headers): - body = self.fixtures.load('list_keys.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _key_sshrsa(self, method, url, body, headers): - body = self.fixtures.load('list_ssh_keys.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _key_password(self, method, url, body, headers): - body = self.fixtures.load('list_password_keys.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _server_cloud_88241(self, method, url, body, headers): - body = self.fixtures.load('success_action.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _server_cloud_88241_initiator_restart(self, method, url, body, - headers): - body = self.fixtures.load('success_action.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _server_cloud_88241_initiator_start(self, method, url, body, headers): - body = self.fixtures.load('success_action.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _server_cloud_88241_initiator_stop(self, method, url, body, headers): - body = self.fixtures.load('success_action.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _key_password_72211(self, method, url, body, headers): - body = self.fixtures.load('success_action.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _key_sshrsa_72209(self, method, url, body, headers): - body = self.fixtures.load('success_action.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_opennebula.py b/awx/lib/site-packages/libcloud/test/compute/test_opennebula.py deleted file mode 100644 index 8dcedfd767..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_opennebula.py +++ /dev/null @@ -1,1273 +0,0 @@ -# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad -# Complutense de Madrid (dsa-research.org) -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -OpenNebula.org test suite. -""" - -__docformat__ = 'epytext' - -import unittest -import sys - -from libcloud.utils.py3 import httplib - -from libcloud.compute.base import Node, NodeImage, NodeSize, NodeState -from libcloud.compute.drivers.opennebula import OpenNebulaNodeDriver -from libcloud.compute.drivers.opennebula import OpenNebulaNetwork -from libcloud.compute.drivers.opennebula import OpenNebulaResponse -from libcloud.compute.drivers.opennebula import OpenNebulaNodeSize -from libcloud.compute.drivers.opennebula import ACTION - -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.common.types import InvalidCredsError -from libcloud.test import MockResponse, MockHttp -from libcloud.test.compute import TestCaseMixin - -from libcloud.test.secrets import OPENNEBULA_PARAMS - - -class OpenNebulaCaseMixin(TestCaseMixin): - - def test_reboot_node_response(self): - pass - - -class OpenNebula_ResponseTests(unittest.TestCase): - XML = """""" - - def test_unauthorized_response(self): - http_response = MockResponse(httplib.UNAUTHORIZED, - OpenNebula_ResponseTests.XML, - headers={'content-type': - 'application/xml'}) - try: - OpenNebulaResponse(http_response, None).parse_body() - except InvalidCredsError: - exceptionType = sys.exc_info()[0] - self.assertEqual(exceptionType, type(InvalidCredsError())) - - -class OpenNebula_1_4_Tests(unittest.TestCase, OpenNebulaCaseMixin): - - """ - OpenNebula.org test suite for OpenNebula v1.4. - """ - - def setUp(self): - """ - Setup test environment. - """ - OpenNebulaNodeDriver.connectionCls.conn_classes = ( - OpenNebula_1_4_MockHttp, OpenNebula_1_4_MockHttp) - self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('1.4',)) - - def test_create_node(self): - """ - Test create_node functionality. - """ - image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) - size = NodeSize(id=1, name='small', ram=None, disk=None, - bandwidth=None, price=None, driver=self.driver) - networks = list() - networks.append(OpenNebulaNetwork(id=5, name='Network 5', - address='192.168.0.0', size=256, driver=self.driver)) - networks.append(OpenNebulaNetwork(id=15, name='Network 15', - address='192.168.1.0', size=256, driver=self.driver)) - - node = self.driver.create_node(name='Compute 5', image=image, - size=size, networks=networks) - - self.assertEqual(node.id, '5') - self.assertEqual(node.name, 'Compute 5') - self.assertEqual(node.state, - OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) - self.assertEqual(node.public_ips[0].name, None) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].address, '192.168.0.1') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[1].name, None) - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].address, '192.168.1.1') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.private_ips, []) - self.assertEqual(node.image.id, '5') - self.assertEqual(node.image.extra['dev'], 'sda1') - - def test_destroy_node(self): - """ - Test destroy_node functionality. - """ - node = Node(5, None, None, None, None, self.driver) - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - def test_list_nodes(self): - """ - Test list_nodes functionality. - """ - nodes = self.driver.list_nodes() - - self.assertEqual(len(nodes), 3) - node = nodes[0] - self.assertEqual(node.id, '5') - self.assertEqual(node.name, 'Compute 5') - self.assertEqual(node.state, - OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].name, None) - self.assertEqual(node.public_ips[0].address, '192.168.0.1') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].name, None) - self.assertEqual(node.public_ips[1].address, '192.168.1.1') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.private_ips, []) - self.assertEqual(node.image.id, '5') - self.assertEqual(node.image.extra['dev'], 'sda1') - node = nodes[1] - self.assertEqual(node.id, '15') - self.assertEqual(node.name, 'Compute 15') - self.assertEqual(node.state, - OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].name, None) - self.assertEqual(node.public_ips[0].address, '192.168.0.2') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].name, None) - self.assertEqual(node.public_ips[1].address, '192.168.1.2') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.private_ips, []) - self.assertEqual(node.image.id, '15') - self.assertEqual(node.image.extra['dev'], 'sda1') - node = nodes[2] - self.assertEqual(node.id, '25') - self.assertEqual(node.name, 'Compute 25') - self.assertEqual(node.state, - NodeState.UNKNOWN) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].name, None) - self.assertEqual(node.public_ips[0].address, '192.168.0.3') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].name, None) - self.assertEqual(node.public_ips[1].address, '192.168.1.3') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.private_ips, []) - self.assertEqual(node.image, None) - - def test_list_images(self): - """ - Test list_images functionality. - """ - images = self.driver.list_images() - - self.assertEqual(len(images), 2) - image = images[0] - self.assertEqual(image.id, '5') - self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') - self.assertEqual(image.extra['size'], '2048') - self.assertEqual(image.extra['url'], - 'file:///images/ubuntu/jaunty.img') - image = images[1] - self.assertEqual(image.id, '15') - self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') - self.assertEqual(image.extra['size'], '2048') - self.assertEqual(image.extra['url'], - 'file:///images/ubuntu/jaunty.img') - - def test_list_sizes(self): - """ - Test list_sizes functionality. - """ - sizes = self.driver.list_sizes() - - self.assertEqual(len(sizes), 3) - size = sizes[0] - self.assertEqual(size.id, '1') - self.assertEqual(size.name, 'small') - self.assertEqual(size.ram, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - size = sizes[1] - self.assertEqual(size.id, '2') - self.assertEqual(size.name, 'medium') - self.assertEqual(size.ram, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - size = sizes[2] - self.assertEqual(size.id, '3') - self.assertEqual(size.name, 'large') - self.assertEqual(size.ram, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - - def test_list_locations(self): - """ - Test list_locations functionality. - """ - locations = self.driver.list_locations() - - self.assertEqual(len(locations), 1) - location = locations[0] - self.assertEqual(location.id, '0') - self.assertEqual(location.name, '') - self.assertEqual(location.country, '') - - def test_ex_list_networks(self): - """ - Test ex_list_networks functionality. - """ - networks = self.driver.ex_list_networks() - - self.assertEqual(len(networks), 2) - network = networks[0] - self.assertEqual(network.id, '5') - self.assertEqual(network.name, 'Network 5') - self.assertEqual(network.address, '192.168.0.0') - self.assertEqual(network.size, '256') - network = networks[1] - self.assertEqual(network.id, '15') - self.assertEqual(network.name, 'Network 15') - self.assertEqual(network.address, '192.168.1.0') - self.assertEqual(network.size, '256') - - def test_ex_node_action(self): - """ - Test ex_node_action functionality. - """ - node = Node(5, None, None, None, None, self.driver) - ret = self.driver.ex_node_action(node, ACTION.STOP) - self.assertTrue(ret) - - -class OpenNebula_2_0_Tests(unittest.TestCase, OpenNebulaCaseMixin): - - """ - OpenNebula.org test suite for OpenNebula v2.0 through v2.2. - """ - - def setUp(self): - """ - Setup test environment. - """ - OpenNebulaNodeDriver.connectionCls.conn_classes = ( - OpenNebula_2_0_MockHttp, OpenNebula_2_0_MockHttp) - self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('2.0',)) - - def test_create_node(self): - """ - Test create_node functionality. - """ - image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) - size = OpenNebulaNodeSize(id=1, name='small', ram=1024, cpu=1, - disk=None, bandwidth=None, price=None, - driver=self.driver) - networks = list() - networks.append(OpenNebulaNetwork(id=5, name='Network 5', - address='192.168.0.0', size=256, driver=self.driver)) - networks.append(OpenNebulaNetwork(id=15, name='Network 15', - address='192.168.1.0', size=256, driver=self.driver)) - context = {'hostname': 'compute-5'} - - node = self.driver.create_node(name='Compute 5', image=image, - size=size, networks=networks, - context=context) - - self.assertEqual(node.id, '5') - self.assertEqual(node.name, 'Compute 5') - self.assertEqual(node.state, - OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].name, 'Network 5') - self.assertEqual(node.public_ips[0].address, '192.168.0.1') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:01') - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].name, 'Network 15') - self.assertEqual(node.public_ips[1].address, '192.168.1.1') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:01') - self.assertEqual(node.private_ips, []) - self.assertTrue(len([s for s in self.driver.list_sizes() - if s.id == node.size.id]) == 1) - self.assertEqual(node.image.id, '5') - self.assertEqual(node.image.name, 'Ubuntu 9.04 LAMP') - self.assertEqual(node.image.extra['type'], 'DISK') - self.assertEqual(node.image.extra['target'], 'hda') - context = node.extra['context'] - self.assertEqual(context['hostname'], 'compute-5') - - def test_destroy_node(self): - """ - Test destroy_node functionality. - """ - node = Node(5, None, None, None, None, self.driver) - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - def test_list_nodes(self): - """ - Test list_nodes functionality. - """ - nodes = self.driver.list_nodes() - - self.assertEqual(len(nodes), 3) - node = nodes[0] - self.assertEqual(node.id, '5') - self.assertEqual(node.name, 'Compute 5') - self.assertEqual(node.state, - OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].name, 'Network 5') - self.assertEqual(node.public_ips[0].address, '192.168.0.1') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:01') - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].name, 'Network 15') - self.assertEqual(node.public_ips[1].address, '192.168.1.1') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:01') - self.assertEqual(node.private_ips, []) - self.assertTrue(len([size for size in self.driver.list_sizes() - if size.id == node.size.id]) == 1) - self.assertEqual(node.size.id, '1') - self.assertEqual(node.size.name, 'small') - self.assertEqual(node.size.ram, 1024) - self.assertTrue(node.size.cpu is None or isinstance(node.size.cpu, - int)) - self.assertTrue(node.size.vcpu is None or isinstance(node.size.vcpu, - int)) - self.assertEqual(node.size.cpu, 1) - self.assertEqual(node.size.vcpu, None) - self.assertEqual(node.size.disk, None) - self.assertEqual(node.size.bandwidth, None) - self.assertEqual(node.size.price, None) - self.assertTrue(len([image for image in self.driver.list_images() - if image.id == node.image.id]) == 1) - self.assertEqual(node.image.id, '5') - self.assertEqual(node.image.name, 'Ubuntu 9.04 LAMP') - self.assertEqual(node.image.extra['type'], 'DISK') - self.assertEqual(node.image.extra['target'], 'hda') - context = node.extra['context'] - self.assertEqual(context['hostname'], 'compute-5') - node = nodes[1] - self.assertEqual(node.id, '15') - self.assertEqual(node.name, 'Compute 15') - self.assertEqual(node.state, - OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].name, 'Network 5') - self.assertEqual(node.public_ips[0].address, '192.168.0.2') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:02') - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].name, 'Network 15') - self.assertEqual(node.public_ips[1].address, '192.168.1.2') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:02') - self.assertEqual(node.private_ips, []) - self.assertTrue(len([size for size in self.driver.list_sizes() - if size.id == node.size.id]) == 1) - self.assertEqual(node.size.id, '1') - self.assertEqual(node.size.name, 'small') - self.assertEqual(node.size.ram, 1024) - self.assertTrue(node.size.cpu is None or isinstance(node.size.cpu, - int)) - self.assertTrue(node.size.vcpu is None or isinstance(node.size.vcpu, - int)) - self.assertEqual(node.size.cpu, 1) - self.assertEqual(node.size.vcpu, None) - self.assertEqual(node.size.disk, None) - self.assertEqual(node.size.bandwidth, None) - self.assertEqual(node.size.price, None) - self.assertTrue(len([image for image in self.driver.list_images() - if image.id == node.image.id]) == 1) - self.assertEqual(node.image.id, '15') - self.assertEqual(node.image.name, 'Ubuntu 9.04 LAMP') - self.assertEqual(node.image.extra['type'], 'DISK') - self.assertEqual(node.image.extra['target'], 'hda') - context = node.extra['context'] - self.assertEqual(context['hostname'], 'compute-15') - node = nodes[2] - self.assertEqual(node.id, '25') - self.assertEqual(node.name, 'Compute 25') - self.assertEqual(node.state, - NodeState.UNKNOWN) - self.assertEqual(node.public_ips[0].id, '5') - self.assertEqual(node.public_ips[0].name, 'Network 5') - self.assertEqual(node.public_ips[0].address, '192.168.0.3') - self.assertEqual(node.public_ips[0].size, 1) - self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:03') - self.assertEqual(node.public_ips[1].id, '15') - self.assertEqual(node.public_ips[1].name, 'Network 15') - self.assertEqual(node.public_ips[1].address, '192.168.1.3') - self.assertEqual(node.public_ips[1].size, 1) - self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:03') - self.assertEqual(node.private_ips, []) - self.assertEqual(node.size, None) - self.assertEqual(node.image, None) - context = node.extra['context'] - self.assertEqual(context, {}) - - def test_list_images(self): - """ - Test list_images functionality. - """ - images = self.driver.list_images() - - self.assertEqual(len(images), 2) - image = images[0] - self.assertEqual(image.id, '5') - self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') - self.assertEqual(image.extra['description'], - 'Ubuntu 9.04 LAMP Description') - self.assertEqual(image.extra['type'], 'OS') - self.assertEqual(image.extra['size'], '2048') - image = images[1] - self.assertEqual(image.id, '15') - self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') - self.assertEqual(image.extra['description'], - 'Ubuntu 9.04 LAMP Description') - self.assertEqual(image.extra['type'], 'OS') - self.assertEqual(image.extra['size'], '2048') - - def test_list_sizes(self): - """ - Test list_sizes functionality. - """ - sizes = self.driver.list_sizes() - - self.assertEqual(len(sizes), 4) - size = sizes[0] - self.assertEqual(size.id, '1') - self.assertEqual(size.name, 'small') - self.assertEqual(size.ram, 1024) - self.assertTrue(size.cpu is None or isinstance(size.cpu, int)) - self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) - self.assertEqual(size.cpu, 1) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - size = sizes[1] - self.assertEqual(size.id, '2') - self.assertEqual(size.name, 'medium') - self.assertEqual(size.ram, 4096) - self.assertTrue(size.cpu is None or isinstance(size.cpu, int)) - self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) - self.assertEqual(size.cpu, 4) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - size = sizes[2] - self.assertEqual(size.id, '3') - self.assertEqual(size.name, 'large') - self.assertEqual(size.ram, 8192) - self.assertTrue(size.cpu is None or isinstance(size.cpu, int)) - self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) - self.assertEqual(size.cpu, 8) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - size = sizes[3] - self.assertEqual(size.id, '4') - self.assertEqual(size.name, 'custom') - self.assertEqual(size.ram, 0) - self.assertEqual(size.cpu, 0) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - - def test_list_locations(self): - """ - Test list_locations functionality. - """ - locations = self.driver.list_locations() - - self.assertEqual(len(locations), 1) - location = locations[0] - self.assertEqual(location.id, '0') - self.assertEqual(location.name, '') - self.assertEqual(location.country, '') - - def test_ex_list_networks(self): - """ - Test ex_list_networks functionality. - """ - networks = self.driver.ex_list_networks() - - self.assertEqual(len(networks), 2) - network = networks[0] - self.assertEqual(network.id, '5') - self.assertEqual(network.name, 'Network 5') - self.assertEqual(network.address, '192.168.0.0') - self.assertEqual(network.size, '256') - network = networks[1] - self.assertEqual(network.id, '15') - self.assertEqual(network.name, 'Network 15') - self.assertEqual(network.address, '192.168.1.0') - self.assertEqual(network.size, '256') - - -class OpenNebula_3_0_Tests(unittest.TestCase, OpenNebulaCaseMixin): - - """ - OpenNebula.org test suite for OpenNebula v3.0. - """ - - def setUp(self): - """ - Setup test environment. - """ - OpenNebulaNodeDriver.connectionCls.conn_classes = ( - OpenNebula_3_0_MockHttp, OpenNebula_3_0_MockHttp) - self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.0',)) - - def test_ex_list_networks(self): - """ - Test ex_list_networks functionality. - """ - networks = self.driver.ex_list_networks() - - self.assertEqual(len(networks), 2) - network = networks[0] - self.assertEqual(network.id, '5') - self.assertEqual(network.name, 'Network 5') - self.assertEqual(network.address, '192.168.0.0') - self.assertEqual(network.size, '256') - self.assertEqual(network.extra['public'], 'YES') - network = networks[1] - self.assertEqual(network.id, '15') - self.assertEqual(network.name, 'Network 15') - self.assertEqual(network.address, '192.168.1.0') - self.assertEqual(network.size, '256') - self.assertEqual(network.extra['public'], 'NO') - - def test_ex_node_set_save_name(self): - """ - Test ex_node_action functionality. - """ - image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) - node = Node(5, None, None, None, None, self.driver, image=image) - ret = self.driver.ex_node_set_save_name(node, 'test') - self.assertTrue(ret) - - -class OpenNebula_3_2_Tests(unittest.TestCase, OpenNebulaCaseMixin): - - """ - OpenNebula.org test suite for OpenNebula v3.2. - """ - - def setUp(self): - """ - Setup test environment. - """ - OpenNebulaNodeDriver.connectionCls.conn_classes = ( - OpenNebula_3_2_MockHttp, OpenNebula_3_2_MockHttp) - self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.2',)) - - def test_reboot_node(self): - """ - Test reboot_node functionality. - """ - image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) - node = Node(5, None, None, None, None, self.driver, image=image) - ret = self.driver.reboot_node(node) - self.assertTrue(ret) - - def test_list_sizes(self): - """ - Test ex_list_networks functionality. - """ - sizes = self.driver.list_sizes() - - self.assertEqual(len(sizes), 3) - size = sizes[0] - self.assertEqual(size.id, '1') - self.assertEqual(size.name, 'small') - self.assertEqual(size.ram, 1024) - self.assertTrue(size.cpu is None or isinstance(size.cpu, float)) - self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) - self.assertEqual(size.cpu, 1) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - size = sizes[1] - self.assertEqual(size.id, '2') - self.assertEqual(size.name, 'medium') - self.assertEqual(size.ram, 4096) - self.assertTrue(size.cpu is None or isinstance(size.cpu, float)) - self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) - self.assertEqual(size.cpu, 4) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - size = sizes[2] - self.assertEqual(size.id, '3') - self.assertEqual(size.name, 'large') - self.assertEqual(size.ram, 8192) - self.assertTrue(size.cpu is None or isinstance(size.cpu, float)) - self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) - self.assertEqual(size.cpu, 8) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - - -class OpenNebula_3_6_Tests(unittest.TestCase, OpenNebulaCaseMixin): - - """ - OpenNebula.org test suite for OpenNebula v3.6. - """ - - def setUp(self): - """ - Setup test environment. - """ - OpenNebulaNodeDriver.connectionCls.conn_classes = ( - OpenNebula_3_6_MockHttp, OpenNebula_3_6_MockHttp) - self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.6',)) - - def test_create_volume(self): - new_volume = self.driver.create_volume(1000, 'test-volume') - - self.assertEqual(new_volume.id, '5') - self.assertEqual(new_volume.size, 1000) - self.assertEqual(new_volume.name, 'test-volume') - - def test_destroy_volume(self): - images = self.driver.list_images() - - self.assertEqual(len(images), 2) - image = images[0] - - ret = self.driver.destroy_volume(image) - self.assertTrue(ret) - - def test_attach_volume(self): - nodes = self.driver.list_nodes() - node = nodes[0] - - images = self.driver.list_images() - image = images[0] - - ret = self.driver.attach_volume(node, image, 'sda') - self.assertTrue(ret) - - def test_detach_volume(self): - images = self.driver.list_images() - image = images[1] - - ret = self.driver.detach_volume(image) - self.assertTrue(ret) - - nodes = self.driver.list_nodes() - # node with only a single associated image - node = nodes[1] - - ret = self.driver.detach_volume(node.image) - self.assertFalse(ret) - - def test_list_volumes(self): - volumes = self.driver.list_volumes() - - self.assertEqual(len(volumes), 2) - - volume = volumes[0] - self.assertEqual(volume.id, '5') - self.assertEqual(volume.size, 2048) - self.assertEqual(volume.name, 'Ubuntu 9.04 LAMP') - - volume = volumes[1] - self.assertEqual(volume.id, '15') - self.assertEqual(volume.size, 1024) - self.assertEqual(volume.name, 'Debian Sid') - - -class OpenNebula_3_8_Tests(unittest.TestCase, OpenNebulaCaseMixin): - - """ - OpenNebula.org test suite for OpenNebula v3.8. - """ - - def setUp(self): - """ - Setup test environment. - """ - OpenNebulaNodeDriver.connectionCls.conn_classes = ( - OpenNebula_3_8_MockHttp, OpenNebula_3_8_MockHttp) - self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.8',)) - - def test_list_sizes(self): - """ - Test ex_list_networks functionality. - """ - sizes = self.driver.list_sizes() - - self.assertEqual(len(sizes), 3) - size = sizes[0] - self.assertEqual(size.id, '1') - self.assertEqual(size.name, 'small') - self.assertEqual(size.ram, 1024) - self.assertEqual(size.cpu, 1) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - - size = sizes[1] - self.assertEqual(size.id, '2') - self.assertEqual(size.name, 'medium') - self.assertEqual(size.ram, 4096) - self.assertEqual(size.cpu, 4) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - - size = sizes[2] - self.assertEqual(size.id, '3') - self.assertEqual(size.name, 'large') - self.assertEqual(size.ram, 8192) - self.assertEqual(size.cpu, 8) - self.assertEqual(size.vcpu, None) - self.assertEqual(size.disk, None) - self.assertEqual(size.bandwidth, None) - self.assertEqual(size.price, None) - - -class OpenNebula_1_4_MockHttp(MockHttp): - - """ - Mock HTTP server for testing v1.4 of the OpenNebula.org compute driver. - """ - - fixtures = ComputeFileFixtures('opennebula_1_4') - - def _compute(self, method, url, body, headers): - """ - Compute pool resources. - """ - if method == 'GET': - body = self.fixtures.load('computes.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures.load('compute_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _storage(self, method, url, body, headers): - """ - Storage pool resources. - """ - if method == 'GET': - body = self.fixtures.load('storage.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures.load('disk_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _network(self, method, url, body, headers): - """ - Network pool resources. - """ - if method == 'GET': - body = self.fixtures.load('networks.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures.load('network_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _compute_5(self, method, url, body, headers): - """ - Compute entry resource. - """ - if method == 'GET': - body = self.fixtures.load('compute_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.OK, body, {}, - httplib.responses[httplib.OK]) - - def _compute_15(self, method, url, body, headers): - """ - Compute entry resource. - """ - if method == 'GET': - body = self.fixtures.load('compute_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.OK, body, {}, - httplib.responses[httplib.OK]) - - def _compute_25(self, method, url, body, headers): - """ - Compute entry resource. - """ - if method == 'GET': - body = self.fixtures.load('compute_25.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.OK, body, {}, - httplib.responses[httplib.OK]) - - def _storage_5(self, method, url, body, headers): - """ - Storage entry resource. - """ - if method == 'GET': - body = self.fixtures.load('disk_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.OK, body, {}, - httplib.responses[httplib.OK]) - - def _storage_15(self, method, url, body, headers): - """ - Storage entry resource. - """ - if method == 'GET': - body = self.fixtures.load('disk_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.OK, body, {}, - httplib.responses[httplib.OK]) - - def _network_5(self, method, url, body, headers): - """ - Network entry resource. - """ - if method == 'GET': - body = self.fixtures.load('network_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.OK, body, {}, - httplib.responses[httplib.OK]) - - def _network_15(self, method, url, body, headers): - """ - Network entry resource. - """ - if method == 'GET': - body = self.fixtures.load('network_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.OK, body, {}, - httplib.responses[httplib.OK]) - - -class OpenNebula_2_0_MockHttp(MockHttp): - - """ - Mock HTTP server for testing v2.0 through v3.2 of the OpenNebula.org - compute driver. - """ - - fixtures = ComputeFileFixtures('opennebula_2_0') - - def _compute(self, method, url, body, headers): - """ - Compute pool resources. - """ - if method == 'GET': - body = self.fixtures.load('compute_collection.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures.load('compute_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _storage(self, method, url, body, headers): - """ - Storage pool resources. - """ - if method == 'GET': - body = self.fixtures.load('storage_collection.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures.load('storage_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _network(self, method, url, body, headers): - """ - Network pool resources. - """ - if method == 'GET': - body = self.fixtures.load('network_collection.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures.load('network_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _compute_5(self, method, url, body, headers): - """ - Compute entry resource. - """ - if method == 'GET': - body = self.fixtures.load('compute_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _compute_15(self, method, url, body, headers): - """ - Compute entry resource. - """ - if method == 'GET': - body = self.fixtures.load('compute_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _compute_25(self, method, url, body, headers): - """ - Compute entry resource. - """ - if method == 'GET': - body = self.fixtures.load('compute_25.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _storage_5(self, method, url, body, headers): - """ - Storage entry resource. - """ - if method == 'GET': - body = self.fixtures.load('storage_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _storage_15(self, method, url, body, headers): - """ - Storage entry resource. - """ - if method == 'GET': - body = self.fixtures.load('storage_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _network_5(self, method, url, body, headers): - """ - Network entry resource. - """ - if method == 'GET': - body = self.fixtures.load('network_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _network_15(self, method, url, body, headers): - """ - Network entry resource. - """ - if method == 'GET': - body = self.fixtures.load('network_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - -class OpenNebula_3_0_MockHttp(OpenNebula_2_0_MockHttp): - - """ - Mock HTTP server for testing v3.0 of the OpenNebula.org compute driver. - """ - - fixtures_3_0 = ComputeFileFixtures('opennebula_3_0') - - def _network(self, method, url, body, headers): - """ - Network pool resources. - """ - if method == 'GET': - body = self.fixtures_3_0.load('network_collection.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures.load('network_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _network_5(self, method, url, body, headers): - """ - Network entry resource. - """ - if method == 'GET': - body = self.fixtures_3_0.load('network_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _network_15(self, method, url, body, headers): - """ - Network entry resource. - """ - if method == 'GET': - body = self.fixtures_3_0.load('network_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - -class OpenNebula_3_2_MockHttp(OpenNebula_3_0_MockHttp): - - """ - Mock HTTP server for testing v3.2 of the OpenNebula.org compute driver. - """ - - fixtures_3_2 = ComputeFileFixtures('opennebula_3_2') - - def _compute_5(self, method, url, body, headers): - """ - Compute entry resource. - """ - if method == 'GET': - body = self.fixtures.load('compute_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _instance_type(self, method, url, body, headers): - """ - Instance type pool. - """ - if method == 'GET': - body = self.fixtures_3_2.load('instance_type_collection.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -class OpenNebula_3_6_MockHttp(OpenNebula_3_2_MockHttp): - - """ - Mock HTTP server for testing v3.6 of the OpenNebula.org compute driver. - """ - - fixtures_3_6 = ComputeFileFixtures('opennebula_3_6') - - def _storage(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('storage_collection.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'POST': - body = self.fixtures_3_6.load('storage_5.xml') - return (httplib.CREATED, body, {}, - httplib.responses[httplib.CREATED]) - - def _compute_5(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures_3_6.load('compute_5.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _compute_5_action(self, method, url, body, headers): - body = self.fixtures_3_6.load('compute_5.xml') - if method == 'POST': - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'GET': - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _compute_15(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures_3_6.load('compute_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - if method == 'PUT': - body = "" - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - if method == 'DELETE': - body = "" - return (httplib.NO_CONTENT, body, {}, - httplib.responses[httplib.NO_CONTENT]) - - def _storage_10(self, method, url, body, headers): - """ - Storage entry resource. - """ - if method == 'GET': - body = self.fixtures_3_6.load('disk_10.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _storage_15(self, method, url, body, headers): - """ - Storage entry resource. - """ - if method == 'GET': - body = self.fixtures_3_6.load('disk_15.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -class OpenNebula_3_8_MockHttp(OpenNebula_3_2_MockHttp): - - """ - Mock HTTP server for testing v3.8 of the OpenNebula.org compute driver. - """ - - fixtures_3_8 = ComputeFileFixtures('opennebula_3_8') - - def _instance_type(self, method, url, body, headers): - """ - Instance type pool. - """ - if method == 'GET': - body = self.fixtures_3_8.load('instance_type_collection.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _instance_type_small(self, method, url, body, headers): - """ - Small instance type. - """ - if method == 'GET': - body = self.fixtures_3_8.load('instance_type_small.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _instance_type_medium(self, method, url, body, headers): - """ - Medium instance type pool. - """ - if method == 'GET': - body = self.fixtures_3_8.load('instance_type_medium.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _instance_type_large(self, method, url, body, headers): - """ - Large instance type pool. - """ - if method == 'GET': - body = self.fixtures_3_8.load('instance_type_large.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_openstack.py b/awx/lib/site-packages/libcloud/test/compute/test_openstack.py deleted file mode 100644 index 6f5af3c3cd..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_openstack.py +++ /dev/null @@ -1,2014 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import os -import sys -import unittest -import datetime - -try: - import simplejson as json -except ImportError: - import json - -from mock import Mock - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import method_type -from libcloud.utils.py3 import u - -from libcloud.common.types import InvalidCredsError, MalformedResponseError, \ - LibcloudError -from libcloud.common.openstack import OpenStackBaseConnection -from libcloud.common.openstack import OpenStackAuthConnection -from libcloud.common.openstack import AUTH_TOKEN_EXPIRES_GRACE_SECONDS -from libcloud.compute.types import Provider, KeyPairDoesNotExistError -from libcloud.compute.providers import get_driver -from libcloud.compute.drivers.openstack import ( - OpenStack_1_0_NodeDriver, OpenStack_1_0_Response, - OpenStack_1_1_NodeDriver, OpenStackSecurityGroup, - OpenStackSecurityGroupRule, OpenStack_1_1_FloatingIpPool, - OpenStack_1_1_FloatingIpAddress, OpenStackKeyPair -) -from libcloud.compute.base import Node, NodeImage, NodeSize -from libcloud.pricing import set_pricing, clear_pricing_data - -from libcloud.test import MockResponse, MockHttpTestCase, XML_HEADERS -from libcloud.test.file_fixtures import ComputeFileFixtures, OpenStackFixtures -from libcloud.test.compute import TestCaseMixin - -from libcloud.test.secrets import OPENSTACK_PARAMS - -BASE_DIR = os.path.abspath(os.path.split(__file__)[0]) - - -class OpenStack_1_0_ResponseTestCase(unittest.TestCase): - XML = """""" - - def test_simple_xml_content_type_handling(self): - http_response = MockResponse( - 200, OpenStack_1_0_ResponseTestCase.XML, headers={'content-type': 'application/xml'}) - body = OpenStack_1_0_Response(http_response, None).parse_body() - - self.assertTrue(hasattr(body, 'tag'), "Body should be parsed as XML") - - def test_extended_xml_content_type_handling(self): - http_response = MockResponse(200, - OpenStack_1_0_ResponseTestCase.XML, - headers={'content-type': 'application/xml; charset=UTF-8'}) - body = OpenStack_1_0_Response(http_response, None).parse_body() - - self.assertTrue(hasattr(body, 'tag'), "Body should be parsed as XML") - - def test_non_xml_content_type_handling(self): - RESPONSE_BODY = "Accepted" - - http_response = MockResponse( - 202, RESPONSE_BODY, headers={'content-type': 'text/html'}) - body = OpenStack_1_0_Response(http_response, None).parse_body() - - self.assertEqual( - body, RESPONSE_BODY, "Non-XML body should be returned as is") - - -class OpenStackServiceCatalogTests(unittest.TestCase): - # TODO refactor and move into libcloud/test/common - - def setUp(self): - OpenStackBaseConnection.conn_classes = (OpenStackMockHttp, - OpenStackMockHttp) - - def test_connection_get_service_catalog(self): - connection = OpenStackBaseConnection(*OPENSTACK_PARAMS) - connection.auth_url = "https://auth.api.example.com" - connection._ex_force_base_url = "https://www.foo.com" - connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS) - - result = connection.get_service_catalog() - catalog = result.get_catalog() - endpoints = result.get_endpoints('cloudFilesCDN', 'cloudFilesCDN') - public_urls = result.get_public_urls('cloudFilesCDN', 'cloudFilesCDN') - - expected_urls = [ - 'https://cdn2.clouddrive.com/v1/MossoCloudFS', - 'https://cdn2.clouddrive.com/v1/MossoCloudFS' - ] - - self.assertTrue('cloudFilesCDN' in catalog) - self.assertEqual(len(endpoints), 2) - self.assertEqual(public_urls, expected_urls) - - -class OpenStackAuthConnectionTests(unittest.TestCase): - # TODO refactor and move into libcloud/test/common - - def setUp(self): - OpenStackBaseConnection.auth_url = None - OpenStackBaseConnection.conn_classes = (OpenStackMockHttp, - OpenStackMockHttp) - - def test_auth_url_is_correctly_assembled(self): - tuples = [ - ('1.0', OpenStackMockHttp), - ('1.1', OpenStackMockHttp), - ('2.0', OpenStack_2_0_MockHttp), - ('2.0_apikey', OpenStack_2_0_MockHttp), - ('2.0_password', OpenStack_2_0_MockHttp) - ] - - APPEND = 0 - NOTAPPEND = 1 - - auth_urls = [ - ('https://auth.api.example.com', APPEND, ''), - ('https://auth.api.example.com/', NOTAPPEND, '/'), - ('https://auth.api.example.com/foo/bar', NOTAPPEND, '/foo/bar'), - ('https://auth.api.example.com/foo/bar/', NOTAPPEND, '/foo/bar/') - ] - - actions = { - '1.0': '/v1.0', - '1.1': '/v1.1/auth', - '2.0': '/v2.0/tokens', - '2.0_apikey': '/v2.0/tokens', - '2.0_password': '/v2.0/tokens' - } - - user_id = OPENSTACK_PARAMS[0] - key = OPENSTACK_PARAMS[1] - - for (auth_version, mock_http_class) in tuples: - for (url, should_append_default_path, expected_path) in auth_urls: - connection = \ - self._get_mock_connection(mock_http_class=mock_http_class, - auth_url=url) - - auth_url = connection.auth_url - - osa = OpenStackAuthConnection(connection, - auth_url, - auth_version, - user_id, key) - - try: - osa = osa.authenticate() - except: - pass - - if (should_append_default_path == APPEND): - expected_path = actions[auth_version] - - self.assertEqual(osa.action, expected_path) - - def test_basic_authentication(self): - tuples = [ - ('1.0', OpenStackMockHttp), - ('1.1', OpenStackMockHttp), - ('2.0', OpenStack_2_0_MockHttp), - ('2.0_apikey', OpenStack_2_0_MockHttp), - ('2.0_password', OpenStack_2_0_MockHttp) - ] - - user_id = OPENSTACK_PARAMS[0] - key = OPENSTACK_PARAMS[1] - - for (auth_version, mock_http_class) in tuples: - connection = \ - self._get_mock_connection(mock_http_class=mock_http_class) - auth_url = connection.auth_url - - osa = OpenStackAuthConnection(connection, auth_url, auth_version, - user_id, key) - - self.assertEqual(osa.urls, {}) - self.assertEqual(osa.auth_token, None) - self.assertEqual(osa.auth_user_info, None) - osa = osa.authenticate() - - self.assertTrue(len(osa.urls) >= 1) - self.assertTrue(osa.auth_token is not None) - - if auth_version in ['1.1', '2.0', '2.0_apikey', '2.0_password']: - self.assertTrue(osa.auth_token_expires is not None) - - if auth_version in ['2.0', '2.0_apikey', '2.0_password']: - self.assertTrue(osa.auth_user_info is not None) - - def test_token_expiration_and_force_reauthentication(self): - user_id = OPENSTACK_PARAMS[0] - key = OPENSTACK_PARAMS[1] - - connection = self._get_mock_connection(OpenStack_2_0_MockHttp) - auth_url = connection.auth_url - auth_version = '2.0' - - yesterday = datetime.datetime.today() - datetime.timedelta(1) - tomorrow = datetime.datetime.today() + datetime.timedelta(1) - - osa = OpenStackAuthConnection(connection, auth_url, auth_version, - user_id, key) - - mocked_auth_method = Mock(wraps=osa.authenticate_2_0_with_body) - osa.authenticate_2_0_with_body = mocked_auth_method - - # Force re-auth, expired token - osa.auth_token = None - osa.auth_token_expires = yesterday - count = 5 - - for i in range(0, count): - osa.authenticate(force=True) - - self.assertEqual(mocked_auth_method.call_count, count) - - # No force reauth, expired token - osa.auth_token = None - osa.auth_token_expires = yesterday - - mocked_auth_method.call_count = 0 - self.assertEqual(mocked_auth_method.call_count, 0) - - for i in range(0, count): - osa.authenticate(force=False) - - self.assertEqual(mocked_auth_method.call_count, 1) - - # No force reauth, valid / non-expired token - osa.auth_token = None - - mocked_auth_method.call_count = 0 - self.assertEqual(mocked_auth_method.call_count, 0) - - for i in range(0, count): - osa.authenticate(force=False) - - if i == 0: - osa.auth_token_expires = tomorrow - - self.assertEqual(mocked_auth_method.call_count, 1) - - # No force reauth, valid / non-expired token which is about to expire in - # less than AUTH_TOKEN_EXPIRES_GRACE_SECONDS - soon = datetime.datetime.utcnow() + \ - datetime.timedelta(seconds=AUTH_TOKEN_EXPIRES_GRACE_SECONDS - 1) - osa.auth_token = None - - mocked_auth_method.call_count = 0 - self.assertEqual(mocked_auth_method.call_count, 0) - - for i in range(0, count): - if i == 0: - osa.auth_token_expires = soon - - osa.authenticate(force=False) - - self.assertEqual(mocked_auth_method.call_count, 1) - - def _get_mock_connection(self, mock_http_class, auth_url=None): - OpenStackBaseConnection.conn_classes = (mock_http_class, - mock_http_class) - - if auth_url is None: - auth_url = "https://auth.api.example.com" - - OpenStackBaseConnection.auth_url = auth_url - connection = OpenStackBaseConnection(*OPENSTACK_PARAMS) - - connection._ex_force_base_url = "https://www.foo.com" - connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS) - - return connection - - -class OpenStack_1_0_Tests(unittest.TestCase, TestCaseMixin): - should_list_locations = False - should_list_volumes = False - - driver_klass = OpenStack_1_0_NodeDriver - driver_args = OPENSTACK_PARAMS - driver_kwargs = {} - # driver_kwargs = {'ex_force_auth_version': '1.0'} - - @classmethod - def create_driver(self): - if self is not OpenStack_1_0_FactoryMethodTests: - self.driver_type = self.driver_klass - return self.driver_type(*self.driver_args, **self.driver_kwargs) - - def setUp(self): - # monkeypatch get_endpoint because the base openstack driver doesn't actually - # work with old devstack but this class/tests are still used by the rackspace - # driver - def get_endpoint(*args, **kwargs): - return "https://servers.api.rackspacecloud.com/v1.0/slug" - self.driver_klass.connectionCls.get_endpoint = get_endpoint - - self.driver_klass.connectionCls.conn_classes = (OpenStackMockHttp, - OpenStackMockHttp) - self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" - - OpenStackMockHttp.type = None - - self.driver = self.create_driver() - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - clear_pricing_data() - - def test_populate_hosts_and_requests_path(self): - tomorrow = datetime.datetime.today() + datetime.timedelta(1) - cls = self.driver_klass.connectionCls - - count = 5 - - # Test authentication and token re-use - con = cls('username', 'key') - osa = con._osa - - mocked_auth_method = Mock() - osa.authenticate = mocked_auth_method - - # Valid token returned on first call, should be reused. - for i in range(0, count): - con._populate_hosts_and_request_paths() - - if i == 0: - osa.auth_token = '1234' - osa.auth_token_expires = tomorrow - - self.assertEqual(mocked_auth_method.call_count, 1) - - osa.auth_token = None - osa.auth_token_expires = None - - # ex_force_auth_token provided, authenticate should never be called - con = cls('username', 'key', ex_force_base_url='http://ponies', - ex_force_auth_token='1234') - osa = con._osa - - mocked_auth_method = Mock() - osa.authenticate = mocked_auth_method - - for i in range(0, count): - con._populate_hosts_and_request_paths() - - self.assertEqual(mocked_auth_method.call_count, 0) - - def test_auth_token_is_set(self): - self.driver.connection._populate_hosts_and_request_paths() - self.assertEqual( - self.driver.connection.auth_token, "aaaaaaaaaaaa-bbb-cccccccccccccc") - - def test_auth_token_expires_is_set(self): - self.driver.connection._populate_hosts_and_request_paths() - - expires = self.driver.connection.auth_token_expires - self.assertEqual(expires.isoformat(), "2031-11-23T21:00:14-06:00") - - def test_auth(self): - if self.driver.connection._auth_version == '2.0': - return - - OpenStackMockHttp.type = 'UNAUTHORIZED' - try: - self.driver = self.create_driver() - self.driver.list_nodes() - except InvalidCredsError: - e = sys.exc_info()[1] - self.assertEqual(True, isinstance(e, InvalidCredsError)) - else: - self.fail('test should have thrown') - - def test_auth_missing_key(self): - if self.driver.connection._auth_version == '2.0': - return - - OpenStackMockHttp.type = 'UNAUTHORIZED_MISSING_KEY' - try: - self.driver = self.create_driver() - self.driver.list_nodes() - except MalformedResponseError: - e = sys.exc_info()[1] - self.assertEqual(True, isinstance(e, MalformedResponseError)) - else: - self.fail('test should have thrown') - - def test_auth_server_error(self): - if self.driver.connection._auth_version == '2.0': - return - - OpenStackMockHttp.type = 'INTERNAL_SERVER_ERROR' - try: - self.driver = self.create_driver() - self.driver.list_nodes() - except MalformedResponseError: - e = sys.exc_info()[1] - self.assertEqual(True, isinstance(e, MalformedResponseError)) - else: - self.fail('test should have thrown') - - def test_error_parsing_when_body_is_missing_message(self): - OpenStackMockHttp.type = 'NO_MESSAGE_IN_ERROR_BODY' - try: - self.driver.list_images() - except Exception: - e = sys.exc_info()[1] - self.assertEqual(True, isinstance(e, Exception)) - else: - self.fail('test should have thrown') - - def test_list_locations(self): - locations = self.driver.list_locations() - self.assertEqual(len(locations), 1) - - def test_list_nodes(self): - OpenStackMockHttp.type = 'EMPTY' - ret = self.driver.list_nodes() - self.assertEqual(len(ret), 0) - OpenStackMockHttp.type = None - ret = self.driver.list_nodes() - self.assertEqual(len(ret), 1) - node = ret[0] - self.assertEqual('67.23.21.33', node.public_ips[0]) - self.assertTrue('10.176.168.218' in node.private_ips) - self.assertEqual(node.extra.get('flavorId'), '1') - self.assertEqual(node.extra.get('imageId'), '11') - self.assertEqual(type(node.extra.get('metadata')), type(dict())) - OpenStackMockHttp.type = 'METADATA' - ret = self.driver.list_nodes() - self.assertEqual(len(ret), 1) - node = ret[0] - self.assertEqual(type(node.extra.get('metadata')), type(dict())) - self.assertEqual(node.extra.get('metadata').get('somekey'), - 'somevalue') - OpenStackMockHttp.type = None - - def test_list_images(self): - ret = self.driver.list_images() - expected = {10: {'serverId': None, - 'status': 'ACTIVE', - 'created': '2009-07-20T09:14:37-05:00', - 'updated': '2009-07-20T09:14:37-05:00', - 'progress': None, - 'minDisk': None, - 'minRam': None}, - 11: {'serverId': '91221', - 'status': 'ACTIVE', - 'created': '2009-11-29T20:22:09-06:00', - 'updated': '2009-11-29T20:24:08-06:00', - 'progress': '100', - 'minDisk': '5', - 'minRam': '256'}} - for ret_idx, extra in list(expected.items()): - for key, value in list(extra.items()): - self.assertEqual(ret[ret_idx].extra[key], value) - - def test_create_node(self): - image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', - driver=self.driver) - size = NodeSize(1, '256 slice', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size) - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra.get('password'), 'racktestvJq7d3') - - def test_create_node_without_adminPass(self): - OpenStackMockHttp.type = 'NO_ADMIN_PASS' - image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', - driver=self.driver) - size = NodeSize(1, '256 slice', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size) - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra.get('password'), None) - - def test_create_node_ex_shared_ip_group(self): - OpenStackMockHttp.type = 'EX_SHARED_IP_GROUP' - image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', - driver=self.driver) - size = NodeSize(1, '256 slice', None, None, None, None, - driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size, - ex_shared_ip_group_id='12345') - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra.get('password'), 'racktestvJq7d3') - - def test_create_node_with_metadata(self): - OpenStackMockHttp.type = 'METADATA' - image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', - driver=self.driver) - size = NodeSize(1, '256 slice', None, None, None, None, - driver=self.driver) - metadata = {'a': 'b', 'c': 'd'} - files = {'/file1': 'content1', '/file2': 'content2'} - node = self.driver.create_node(name='racktest', image=image, size=size, - metadata=metadata, files=files) - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra.get('password'), 'racktestvJq7d3') - self.assertEqual(node.extra.get('metadata'), metadata) - - def test_reboot_node(self): - node = Node(id=72258, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - ret = node.reboot() - self.assertTrue(ret is True) - - def test_destroy_node(self): - node = Node(id=72258, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - ret = node.destroy() - self.assertTrue(ret is True) - - def test_ex_limits(self): - limits = self.driver.ex_limits() - self.assertTrue("rate" in limits) - self.assertTrue("absolute" in limits) - - def test_create_image(self): - node = Node(id=444222, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - image = self.driver.create_image(node, "imgtest") - self.assertEqual(image.name, "imgtest") - self.assertEqual(image.id, "12345") - - def test_delete_image(self): - image = NodeImage(id=333111, name='Ubuntu 8.10 (intrepid)', - driver=self.driver) - ret = self.driver.delete_image(image) - self.assertTrue(ret) - - def test_ex_list_ip_addresses(self): - ret = self.driver.ex_list_ip_addresses(node_id=72258) - self.assertEqual(2, len(ret.public_addresses)) - self.assertTrue('67.23.10.131' in ret.public_addresses) - self.assertTrue('67.23.10.132' in ret.public_addresses) - self.assertEqual(1, len(ret.private_addresses)) - self.assertTrue('10.176.42.16' in ret.private_addresses) - - def test_ex_list_ip_groups(self): - ret = self.driver.ex_list_ip_groups() - self.assertEqual(2, len(ret)) - self.assertEqual('1234', ret[0].id) - self.assertEqual('Shared IP Group 1', ret[0].name) - self.assertEqual('5678', ret[1].id) - self.assertEqual('Shared IP Group 2', ret[1].name) - self.assertTrue(ret[0].servers is None) - - def test_ex_list_ip_groups_detail(self): - ret = self.driver.ex_list_ip_groups(details=True) - - self.assertEqual(2, len(ret)) - - self.assertEqual('1234', ret[0].id) - self.assertEqual('Shared IP Group 1', ret[0].name) - self.assertEqual(2, len(ret[0].servers)) - self.assertEqual('422', ret[0].servers[0]) - self.assertEqual('3445', ret[0].servers[1]) - - self.assertEqual('5678', ret[1].id) - self.assertEqual('Shared IP Group 2', ret[1].name) - self.assertEqual(3, len(ret[1].servers)) - self.assertEqual('23203', ret[1].servers[0]) - self.assertEqual('2456', ret[1].servers[1]) - self.assertEqual('9891', ret[1].servers[2]) - - def test_ex_create_ip_group(self): - ret = self.driver.ex_create_ip_group('Shared IP Group 1', '5467') - self.assertEqual('1234', ret.id) - self.assertEqual('Shared IP Group 1', ret.name) - self.assertEqual(1, len(ret.servers)) - self.assertEqual('422', ret.servers[0]) - - def test_ex_delete_ip_group(self): - ret = self.driver.ex_delete_ip_group('5467') - self.assertEqual(True, ret) - - def test_ex_share_ip(self): - ret = self.driver.ex_share_ip('1234', '3445', '67.23.21.133') - self.assertEqual(True, ret) - - def test_ex_unshare_ip(self): - ret = self.driver.ex_unshare_ip('3445', '67.23.21.133') - self.assertEqual(True, ret) - - def test_ex_resize(self): - node = Node(id=444222, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - size = NodeSize(1, '256 slice', None, None, None, None, - driver=self.driver) - self.assertTrue(self.driver.ex_resize(node=node, size=size)) - - def test_ex_confirm_resize(self): - node = Node(id=444222, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - self.assertTrue(self.driver.ex_confirm_resize(node=node)) - - def test_ex_revert_resize(self): - node = Node(id=444222, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - self.assertTrue(self.driver.ex_revert_resize(node=node)) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 7, 'Wrong sizes count') - - for size in sizes: - self.assertTrue(isinstance(size.price, float), - 'Wrong size price type') - - if self.driver.api_name == 'openstack': - self.assertEqual(size.price, 0, - 'Size price should be zero by default') - - def test_list_sizes_with_specified_pricing(self): - if self.driver.api_name != 'openstack': - return - - pricing = dict((str(i), i) for i in range(1, 8)) - - set_pricing(driver_type='compute', driver_name='openstack', - pricing=pricing) - - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 7, 'Wrong sizes count') - - for size in sizes: - self.assertTrue(isinstance(size.price, float), - 'Wrong size price type') - self.assertEqual(float(size.price), float(pricing[size.id])) - - -class OpenStack_1_0_FactoryMethodTests(OpenStack_1_0_Tests): - should_list_locations = False - should_list_volumes = False - - driver_klass = OpenStack_1_0_NodeDriver - driver_type = get_driver(Provider.OPENSTACK) - driver_args = OPENSTACK_PARAMS + ('1.0',) - - def test_factory_method_invalid_version(self): - try: - self.driver_type(*(OPENSTACK_PARAMS + ('15.5',))) - except NotImplementedError: - pass - else: - self.fail('Exception was not thrown') - - -class OpenStackMockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('openstack') - auth_fixtures = OpenStackFixtures() - json_content_headers = {'content-type': 'application/json; charset=UTF-8'} - - # fake auth token response - def _v1_0(self, method, url, body, headers): - headers = { - 'x-server-management-url': 'https://servers.api.rackspacecloud.com/v1.0/slug', - 'x-auth-token': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', - 'x-cdn-management-url': 'https://cdn.clouddrive.com/v1/MossoCloudFS_FE011C19-CF86-4F87-BE5D-9229145D7A06', - 'x-storage-token': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', - 'x-storage-url': 'https://storage4.clouddrive.com/v1/MossoCloudFS_FE011C19-CF86-4F87-BE5D-9229145D7A06'} - return (httplib.NO_CONTENT, "", headers, httplib.responses[httplib.NO_CONTENT]) - - def _v1_0_UNAUTHORIZED(self, method, url, body, headers): - return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) - - def _v1_0_INTERNAL_SERVER_ERROR(self, method, url, body, headers): - return (httplib.INTERNAL_SERVER_ERROR, "

500: Internal Server Error

", {}, - httplib.responses[httplib.INTERNAL_SERVER_ERROR]) - - def _v1_0_slug_images_detail_NO_MESSAGE_IN_ERROR_BODY(self, method, url, body, headers): - body = self.fixtures.load('300_multiple_choices.json') - return (httplib.MULTIPLE_CHOICES, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_0_UNAUTHORIZED_MISSING_KEY(self, method, url, body, headers): - headers = { - 'x-server-management-url': 'https://servers.api.rackspacecloud.com/v1.0/slug', - 'x-auth-tokenx': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', - 'x-cdn-management-url': 'https://cdn.clouddrive.com/v1/MossoCloudFS_FE011C19-CF86-4F87-BE5D-9229145D7A06'} - return (httplib.NO_CONTENT, "", headers, httplib.responses[httplib.NO_CONTENT]) - - def _v2_0_tokens(self, method, url, body, headers): - body = self.auth_fixtures.load('_v2_0__auth.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_servers_detail_empty.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_servers_detail.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers_detail_METADATA(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_servers_detail_metadata.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_images_333111(self, method, url, body, headers): - if method != "DELETE": - raise NotImplementedError() - # this is currently used for deletion of an image - # as such it should not accept GET/POST - return(httplib.NO_CONTENT, "", "", httplib.responses[httplib.NO_CONTENT]) - - def _v1_0_slug_images(self, method, url, body, headers): - if method != "POST": - raise NotImplementedError() - # this is currently used for creation of new image with - # POST request, don't handle GET to avoid possible confusion - body = self.fixtures.load('v1_slug_images_post.xml') - return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) - - def _v1_0_slug_images_detail(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_images_detail.xml') - return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) - - def _v1_0_slug_servers(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_servers.xml') - return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) - - def _v1_0_slug_servers_NO_ADMIN_PASS(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_servers_no_admin_pass.xml') - return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) - - def _v1_0_slug_servers_EX_SHARED_IP_GROUP(self, method, url, body, headers): - # test_create_node_ex_shared_ip_group - # Verify that the body contains sharedIpGroupId XML element - body = u(body) - self.assertTrue(body.find('sharedIpGroupId="12345"') != -1) - body = self.fixtures.load('v1_slug_servers.xml') - return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) - - def _v1_0_slug_servers_METADATA(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_servers_metadata.xml') - return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) - - def _v1_0_slug_servers_72258_action(self, method, url, body, headers): - if method != "POST" or body[:8] != "500: Internal Server Error", {'content-type': 'text/html'}, - httplib.responses[httplib.INTERNAL_SERVER_ERROR]) - - -class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin): - should_list_locations = False - should_list_volumes = True - - driver_klass = OpenStack_1_1_NodeDriver - driver_type = OpenStack_1_1_NodeDriver - driver_args = OPENSTACK_PARAMS - driver_kwargs = {'ex_force_auth_version': '2.0'} - - @classmethod - def create_driver(self): - if self is not OpenStack_1_1_FactoryMethodTests: - self.driver_type = self.driver_klass - return self.driver_type(*self.driver_args, **self.driver_kwargs) - - def setUp(self): - self.driver_klass.connectionCls.conn_classes = ( - OpenStack_2_0_MockHttp, OpenStack_2_0_MockHttp) - self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" - - OpenStackMockHttp.type = None - OpenStack_1_1_MockHttp.type = None - OpenStack_2_0_MockHttp.type = None - - self.driver = self.create_driver() - - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - clear_pricing_data() - self.node = self.driver.list_nodes()[1] - - def _force_reauthentication(self): - """ - Trash current auth token so driver will be forced to re-authentication - on next request. - """ - self.driver.connection._ex_force_base_url = 'http://ex_force_base_url.com:666/forced_url' - self.driver.connection.auth_token = None - self.driver.connection.auth_token_expires = None - self.driver.connection._osa.auth_token = None - self.driver.connection._osa.auth_token_expires = None - - def test_auth_token_is_set(self): - self._force_reauthentication() - self.driver.connection._populate_hosts_and_request_paths() - - self.assertEqual( - self.driver.connection.auth_token, "aaaaaaaaaaaa-bbb-cccccccccccccc") - - def test_auth_token_expires_is_set(self): - self._force_reauthentication() - self.driver.connection._populate_hosts_and_request_paths() - - expires = self.driver.connection.auth_token_expires - self.assertEqual(expires.isoformat(), "2031-11-23T21:00:14-06:00") - - def test_ex_force_base_url(self): - # change base url and trash the current auth token so we can - # re-authenticate - self.driver.connection._ex_force_base_url = 'http://ex_force_base_url.com:666/forced_url' - self.driver.connection.auth_token = None - self.driver.connection._populate_hosts_and_request_paths() - - # assert that we use the base url and not the auth url - self.assertEqual(self.driver.connection.host, 'ex_force_base_url.com') - self.assertEqual(self.driver.connection.port, '666') - self.assertEqual(self.driver.connection.request_path, '/forced_url') - - def test_get_endpoint_populates_host_port_and_request_path(self): - # simulate a subclass overriding this method - self.driver.connection.get_endpoint = lambda: 'http://endpoint_auth_url.com:1555/service_url' - self.driver.connection.auth_token = None - self.driver.connection._ex_force_base_url = None - self.driver.connection._populate_hosts_and_request_paths() - - # assert that we use the result of get endpoint - self.assertEqual(self.driver.connection.host, 'endpoint_auth_url.com') - self.assertEqual(self.driver.connection.port, '1555') - self.assertEqual(self.driver.connection.request_path, '/service_url') - - def test_set_auth_token_populates_host_port_and_request_path(self): - # change base url and trash the current auth token so we can - # re-authenticate - self.driver.connection._ex_force_base_url = 'http://some_other_ex_force_base_url.com:1222/some-service' - self.driver.connection.auth_token = "preset-auth-token" - self.driver.connection._populate_hosts_and_request_paths() - - # assert that we use the base url and not the auth url - self.assertEqual( - self.driver.connection.host, 'some_other_ex_force_base_url.com') - self.assertEqual(self.driver.connection.port, '1222') - self.assertEqual(self.driver.connection.request_path, '/some-service') - - def test_auth_token_without_base_url_raises_exception(self): - kwargs = { - 'ex_force_auth_version': '2.0', - 'ex_force_auth_token': 'preset-auth-token' - } - try: - self.driver_type(*self.driver_args, **kwargs) - self.fail('Expected failure setting auth token without base url') - except LibcloudError: - pass - else: - self.fail('Expected failure setting auth token without base url') - - def test_ex_force_auth_token_passed_to_connection(self): - base_url = 'https://servers.api.rackspacecloud.com/v1.1/slug' - kwargs = { - 'ex_force_auth_version': '2.0', - 'ex_force_auth_token': 'preset-auth-token', - 'ex_force_base_url': base_url - } - - driver = self.driver_type(*self.driver_args, **kwargs) - driver.list_nodes() - - self.assertEqual(kwargs['ex_force_auth_token'], - driver.connection.auth_token) - self.assertEqual('servers.api.rackspacecloud.com', - driver.connection.host) - self.assertEqual('/v1.1/slug', driver.connection.request_path) - self.assertEqual(443, driver.connection.port) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 2) - node = nodes[0] - - self.assertEqual('12065', node.id) - # test public IPv4 - self.assertTrue('12.16.18.28' in node.public_ips) - self.assertTrue('50.57.94.35' in node.public_ips) - # test public IPv6 - self.assertTrue( - '2001:4801:7808:52:16:3eff:fe47:788a' in node.public_ips) - # test private IPv4 - self.assertTrue('10.182.64.34' in node.private_ips) - # test private IPv6 - self.assertTrue( - 'fec0:4801:7808:52:16:3eff:fe60:187d' in node.private_ips) - - self.assertEqual(node.extra.get('flavorId'), '2') - self.assertEqual(node.extra.get('imageId'), '7') - self.assertEqual(node.extra.get('metadata'), {}) - self.assertEqual(node.extra['updated'], '2011-10-11T00:50:04Z') - self.assertEqual(node.extra['created'], '2011-10-11T00:51:39Z') - - def test_list_nodes_no_image_id_attribute(self): - # Regression test for LIBCLOD-455 - self.driver_klass.connectionCls.conn_classes[0].type = 'ERROR_STATE_NO_IMAGE_ID' - self.driver_klass.connectionCls.conn_classes[1].type = 'ERROR_STATE_NO_IMAGE_ID' - - nodes = self.driver.list_nodes() - self.assertEqual(nodes[0].extra['imageId'], None) - - def test_list_volumes(self): - volumes = self.driver.list_volumes() - self.assertEqual(len(volumes), 2) - volume = volumes[0] - - self.assertEqual('cd76a3a1-c4ce-40f6-9b9f-07a61508938d', volume.id) - self.assertEqual('test_volume_2', volume.name) - self.assertEqual(2, volume.size) - - self.assertEqual(volume.extra['description'], '') - self.assertEqual(volume.extra['attachments'][0][ - 'id'], 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d') - - volume = volumes[1] - self.assertEqual('cfcec3bc-b736-4db5-9535-4c24112691b5', volume.id) - self.assertEqual('test_volume', volume.name) - self.assertEqual(50, volume.size) - - self.assertEqual(volume.extra['description'], 'some description') - self.assertEqual(volume.extra['attachments'], []) - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 8, 'Wrong sizes count') - - for size in sizes: - self.assertTrue(isinstance(size.price, float), - 'Wrong size price type') - - self.assertEqual(sizes[0].vcpus, 8) - - def test_list_sizes_with_specified_pricing(self): - - pricing = dict((str(i), i * 5.0) for i in range(1, 9)) - - set_pricing(driver_type='compute', - driver_name=self.driver.api_name, pricing=pricing) - - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 8, 'Wrong sizes count') - - for size in sizes: - self.assertTrue(isinstance(size.price, float), - 'Wrong size price type') - - self.assertEqual(size.price, pricing[size.id], - 'Size price should match') - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), 13, 'Wrong images count') - - image = images[0] - self.assertEqual(image.id, '13') - self.assertEqual(image.name, 'Windows 2008 SP2 x86 (B24)') - self.assertEqual(image.extra['updated'], '2011-08-06T18:14:02Z') - self.assertEqual(image.extra['created'], '2011-08-06T18:13:11Z') - self.assertEqual(image.extra['status'], 'ACTIVE') - self.assertEqual(image.extra['metadata']['os_type'], 'windows') - self.assertEqual( - image.extra['serverId'], '52415800-8b69-11e0-9b19-734f335aa7b3') - self.assertEqual(image.extra['minDisk'], 0) - self.assertEqual(image.extra['minRam'], 0) - - def test_create_node(self): - image = NodeImage( - id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', None, None, None, None, driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size) - self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra['password'], 'racktestvJq7d3') - self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1') - - def test_create_node_with_ex_keyname_and_ex_userdata(self): - image = NodeImage( - id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', None, None, None, None, driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size, - ex_keyname='devstack', - ex_userdata='sample data') - self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra['password'], 'racktestvJq7d3') - self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1') - self.assertEqual(node.extra['key_name'], 'devstack') - - def test_create_node_with_availability_zone(self): - image = NodeImage( - id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', None, None, None, None, driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size, - availability_zone='testaz') - self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra['password'], 'racktestvJq7d3') - self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1') - self.assertEqual(node.extra['availability_zone'], 'testaz') - - def test_create_node_with_ex_disk_config(self): - OpenStack_1_1_MockHttp.type = 'EX_DISK_CONFIG' - image = NodeImage( - id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', None, None, None, None, driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size, - ex_disk_config='AUTO') - self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') - self.assertEqual(node.name, 'racktest') - self.assertEqual(node.extra['disk_config'], 'AUTO') - - def test_destroy_node(self): - self.assertTrue(self.node.destroy()) - - def test_reboot_node(self): - self.assertTrue(self.node.reboot()) - - def test_create_volume(self): - self.assertEqual(self.driver.create_volume(1, 'test'), True) - - def test_destroy_volume(self): - volume = self.driver.ex_get_volume( - 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d') - self.assertEqual(self.driver.destroy_volume(volume), True) - - def test_attach_volume(self): - node = self.driver.list_nodes()[0] - volume = self.driver.ex_get_volume( - 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d') - self.assertEqual( - self.driver.attach_volume(node, volume, '/dev/sdb'), True) - - def test_detach_volume(self): - node = self.driver.list_nodes()[0] - volume = self.driver.ex_get_volume( - 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d') - self.assertEqual( - self.driver.attach_volume(node, volume, '/dev/sdb'), True) - self.assertEqual(self.driver.detach_volume(volume), True) - - def test_ex_set_password(self): - self.assertTrue(self.driver.ex_set_password(self.node, 'New1&53jPass')) - - def test_ex_rebuild(self): - image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', - driver=self.driver) - success = self.driver.ex_rebuild(self.node, image=image) - self.assertTrue(success) - - def test_ex_rebuild_with_ex_disk_config(self): - image = NodeImage(id=58, name='Ubuntu 10.10 (intrepid)', - driver=self.driver) - node = Node(id=12066, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - success = self.driver.ex_rebuild(node, image=image, - ex_disk_config='MANUAL') - self.assertTrue(success) - - def test_ex_resize(self): - size = NodeSize(1, '256 slice', None, None, None, None, - driver=self.driver) - try: - self.driver.ex_resize(self.node, size) - except Exception: - e = sys.exc_info()[1] - self.fail('An error was raised: ' + repr(e)) - - def test_ex_confirm_resize(self): - try: - self.driver.ex_confirm_resize(self.node) - except Exception: - e = sys.exc_info()[1] - self.fail('An error was raised: ' + repr(e)) - - def test_ex_revert_resize(self): - try: - self.driver.ex_revert_resize(self.node) - except Exception: - e = sys.exc_info()[1] - self.fail('An error was raised: ' + repr(e)) - - def test_create_image(self): - image = self.driver.create_image(self.node, 'new_image') - self.assertEqual(image.name, 'new_image') - self.assertEqual(image.id, '4949f9ee-2421-4c81-8b49-13119446008b') - - def test_ex_set_server_name(self): - old_node = Node( - id='12064', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - new_node = self.driver.ex_set_server_name(old_node, 'Bob') - self.assertEqual('Bob', new_node.name) - - def test_ex_set_metadata(self): - old_node = Node( - id='12063', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - metadata = {'Image Version': '2.1', 'Server Label': 'Web Head 1'} - returned_metadata = self.driver.ex_set_metadata(old_node, metadata) - self.assertEqual(metadata, returned_metadata) - - def test_ex_get_metadata(self): - node = Node( - id='12063', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - - metadata = {'Image Version': '2.1', 'Server Label': 'Web Head 1'} - returned_metadata = self.driver.ex_get_metadata(node) - self.assertEqual(metadata, returned_metadata) - - def test_ex_update_node(self): - old_node = Node( - id='12064', - name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, - ) - - new_node = self.driver.ex_update_node(old_node, name='Bob') - - self.assertTrue(new_node) - self.assertEqual('Bob', new_node.name) - self.assertEqual('50.57.94.30', new_node.public_ips[0]) - - def test_ex_get_node_details(self): - node_id = '12064' - node = self.driver.ex_get_node_details(node_id) - self.assertEqual(node.id, '12064') - self.assertEqual(node.name, 'lc-test') - - def test_ex_get_size(self): - size_id = '7' - size = self.driver.ex_get_size(size_id) - self.assertEqual(size.id, size_id) - self.assertEqual(size.name, '15.5GB slice') - - def test_get_image(self): - image_id = '13' - image = self.driver.get_image(image_id) - self.assertEqual(image.id, image_id) - self.assertEqual(image.name, 'Windows 2008 SP2 x86 (B24)') - self.assertEqual(image.extra['serverId'], None) - self.assertEqual(image.extra['minDisk'], "5") - self.assertEqual(image.extra['minRam'], "256") - - def test_delete_image(self): - image = NodeImage( - id='26365521-8c62-11f9-2c33-283d153ecc3a', name='My Backup', driver=self.driver) - result = self.driver.delete_image(image) - self.assertTrue(result) - - def test_extract_image_id_from_url(self): - url = 'http://127.0.0.1/v1.1/68/images/1d4a8ea9-aae7-4242-a42d-5ff4702f2f14' - url_two = 'http://127.0.0.1/v1.1/68/images/13' - image_id = self.driver._extract_image_id_from_url(url) - image_id_two = self.driver._extract_image_id_from_url(url_two) - self.assertEqual(image_id, '1d4a8ea9-aae7-4242-a42d-5ff4702f2f14') - self.assertEqual(image_id_two, '13') - - def test_ex_rescue_with_password(self): - node = Node(id=12064, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - n = self.driver.ex_rescue(node, 'foo') - self.assertEqual(n.extra['password'], 'foo') - - def test_ex_rescue_no_password(self): - node = Node(id=12064, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - n = self.driver.ex_rescue(node) - self.assertEqual(n.extra['password'], 'foo') - - def test_ex_unrescue(self): - node = Node(id=12064, name=None, state=None, public_ips=None, - private_ips=None, driver=self.driver) - result = self.driver.ex_unrescue(node) - self.assertTrue(result) - - def test_ex_get_node_security_groups(self): - node = Node(id='1c01300f-ef97-4937-8f03-ac676d6234be', name=None, - state=None, public_ips=None, private_ips=None, driver=self.driver) - security_groups = self.driver.ex_get_node_security_groups(node) - self.assertEqual( - len(security_groups), 2, 'Wrong security groups count') - - security_group = security_groups[1] - self.assertEqual(security_group.id, 4) - self.assertEqual(security_group.tenant_id, '68') - self.assertEqual(security_group.name, 'ftp') - self.assertEqual( - security_group.description, 'FTP Client-Server - Open 20-21 ports') - self.assertEqual(security_group.rules[0].id, 1) - self.assertEqual(security_group.rules[0].parent_group_id, 4) - self.assertEqual(security_group.rules[0].ip_protocol, "tcp") - self.assertEqual(security_group.rules[0].from_port, 20) - self.assertEqual(security_group.rules[0].to_port, 21) - self.assertEqual(security_group.rules[0].ip_range, '0.0.0.0/0') - - def test_ex_list_security_groups(self): - security_groups = self.driver.ex_list_security_groups() - self.assertEqual( - len(security_groups), 2, 'Wrong security groups count') - - security_group = security_groups[1] - self.assertEqual(security_group.id, 4) - self.assertEqual(security_group.tenant_id, '68') - self.assertEqual(security_group.name, 'ftp') - self.assertEqual( - security_group.description, 'FTP Client-Server - Open 20-21 ports') - self.assertEqual(security_group.rules[0].id, 1) - self.assertEqual(security_group.rules[0].parent_group_id, 4) - self.assertEqual(security_group.rules[0].ip_protocol, "tcp") - self.assertEqual(security_group.rules[0].from_port, 20) - self.assertEqual(security_group.rules[0].to_port, 21) - self.assertEqual(security_group.rules[0].ip_range, '0.0.0.0/0') - - def test_ex_create_security_group(self): - name = 'test' - description = 'Test Security Group' - security_group = self.driver.ex_create_security_group( - name, description) - - self.assertEqual(security_group.id, 6) - self.assertEqual(security_group.tenant_id, '68') - self.assertEqual(security_group.name, name) - self.assertEqual(security_group.description, description) - self.assertEqual(len(security_group.rules), 0) - - def test_ex_delete_security_group(self): - security_group = OpenStackSecurityGroup( - id=6, tenant_id=None, name=None, description=None, driver=self.driver) - result = self.driver.ex_delete_security_group(security_group) - self.assertTrue(result) - - def test_ex_create_security_group_rule(self): - security_group = OpenStackSecurityGroup( - id=6, tenant_id=None, name=None, description=None, driver=self.driver) - security_group_rule = self.driver.ex_create_security_group_rule( - security_group, 'tcp', 14, 16, '0.0.0.0/0') - - self.assertEqual(security_group_rule.id, 2) - self.assertEqual(security_group_rule.parent_group_id, 6) - self.assertEqual(security_group_rule.ip_protocol, 'tcp') - self.assertEqual(security_group_rule.from_port, 14) - self.assertEqual(security_group_rule.to_port, 16) - self.assertEqual(security_group_rule.ip_range, '0.0.0.0/0') - self.assertEqual(security_group_rule.tenant_id, None) - - def test_ex_delete_security_group_rule(self): - security_group_rule = OpenStackSecurityGroupRule( - id=2, parent_group_id=None, ip_protocol=None, from_port=None, to_port=None, driver=self.driver) - result = self.driver.ex_delete_security_group_rule(security_group_rule) - self.assertTrue(result) - - def test_list_key_pairs(self): - keypairs = self.driver.list_key_pairs() - self.assertEqual(len(keypairs), 2, 'Wrong keypairs count') - keypair = keypairs[1] - self.assertEqual(keypair.name, 'key2') - self.assertEqual( - keypair.fingerprint, '5d:66:33:ae:99:0f:fb:cb:86:f2:bc:ae:53:99:b6:ed') - self.assertTrue(len(keypair.public_key) > 10) - self.assertEqual(keypair.private_key, None) - - def test_get_key_pair(self): - key_pair = self.driver.get_key_pair(name='test-key-pair') - - self.assertEqual(key_pair.name, 'test-key-pair') - - def test_get_key_pair_doesnt_exist(self): - self.assertRaises(KeyPairDoesNotExistError, - self.driver.get_key_pair, - name='doesnt-exist') - - def test_create_key_pair(self): - name = 'key0' - keypair = self.driver.create_key_pair(name=name) - self.assertEqual(keypair.name, name) - - self.assertEqual(keypair.fingerprint, - '80:f8:03:a7:8e:c1:c3:b1:7e:c5:8c:50:04:5e:1c:5b') - self.assertTrue(len(keypair.public_key) > 10) - self.assertTrue(len(keypair.private_key) > 10) - - def test_import_key_pair_from_file(self): - name = 'key3' - path = os.path.join( - os.path.dirname(__file__), 'fixtures', 'misc', 'dummy_rsa.pub') - pub_key = open(path, 'r').read() - keypair = self.driver.import_key_pair_from_file(name=name, - key_file_path=path) - self.assertEqual(keypair.name, name) - self.assertEqual( - keypair.fingerprint, '97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a') - self.assertEqual(keypair.public_key, pub_key) - self.assertEqual(keypair.private_key, None) - - def test_import_key_pair_from_string(self): - name = 'key3' - path = os.path.join( - os.path.dirname(__file__), 'fixtures', 'misc', 'dummy_rsa.pub') - pub_key = open(path, 'r').read() - keypair = self.driver.import_key_pair_from_string(name=name, - key_material=pub_key) - self.assertEqual(keypair.name, name) - self.assertEqual( - keypair.fingerprint, '97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a') - self.assertEqual(keypair.public_key, pub_key) - self.assertEqual(keypair.private_key, None) - - def test_delete_key_pair(self): - keypair = OpenStackKeyPair( - name='key1', fingerprint=None, public_key=None, driver=self.driver) - result = self.driver.delete_key_pair(key_pair=keypair) - self.assertTrue(result) - - def test_ex_list_floating_ip_pools(self): - ret = self.driver.ex_list_floating_ip_pools() - self.assertEqual(ret[0].name, 'public') - self.assertEqual(ret[1].name, 'foobar') - - def test_ex_attach_floating_ip_to_node(self): - image = NodeImage( - id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', None, None, None, None, driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size) - node.id = 4242 - ip = '42.42.42.42' - - self.assertTrue(self.driver.ex_attach_floating_ip_to_node(node, ip)) - - def test_detach_floating_ip_from_node(self): - image = NodeImage( - id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', None, None, None, None, driver=self.driver) - node = self.driver.create_node(name='racktest', image=image, size=size) - node.id = 4242 - ip = '42.42.42.42' - - self.assertTrue(self.driver.ex_detach_floating_ip_from_node(node, ip)) - - def test_OpenStack_1_1_FloatingIpPool_list_floating_ips(self): - pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) - ret = pool.list_floating_ips() - - self.assertEqual(ret[0].id, '09ea1784-2f81-46dc-8c91-244b4df75bde') - self.assertEqual(ret[0].pool, pool) - self.assertEqual(ret[0].ip_address, '10.3.1.42') - self.assertEqual(ret[0].node_id, None) - self.assertEqual(ret[1].id, '04c5336a-0629-4694-ba30-04b0bdfa88a4') - self.assertEqual(ret[1].pool, pool) - self.assertEqual(ret[1].ip_address, '10.3.1.1') - self.assertEqual( - ret[1].node_id, 'fcfc96da-19e2-40fd-8497-f29da1b21143') - - def test_OpenStack_1_1_FloatingIpPool_get_floating_ip(self): - pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) - ret = pool.get_floating_ip('10.3.1.42') - - self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde') - self.assertEqual(ret.pool, pool) - self.assertEqual(ret.ip_address, '10.3.1.42') - self.assertEqual(ret.node_id, None) - - def test_OpenStack_1_1_FloatingIpPool_create_floating_ip(self): - pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) - ret = pool.create_floating_ip() - - self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde') - self.assertEqual(ret.pool, pool) - self.assertEqual(ret.ip_address, '10.3.1.42') - self.assertEqual(ret.node_id, None) - - def test_OpenStack_1_1_FloatingIpPool_delete_floating_ip(self): - pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) - ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool) - - self.assertTrue(pool.delete_floating_ip(ip)) - - def test_OpenStack_1_1_FloatingIpAddress_delete(self): - pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) - pool.delete_floating_ip = Mock() - ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool) - - ip.pool.delete_floating_ip() - - self.assertEqual(pool.delete_floating_ip.call_count, 1) - - def test_ex_list_network(self): - networks = self.driver.ex_list_networks() - network = networks[0] - - self.assertEqual(len(networks), 3) - self.assertEqual(network.name, 'test1') - self.assertEqual(network.cidr, '127.0.0.0/24') - - def test_ex_create_network(self): - network = self.driver.ex_create_network(name='test1', - cidr='127.0.0.0/24') - self.assertEqual(network.name, 'test1') - self.assertEqual(network.cidr, '127.0.0.0/24') - - def test_ex_delete_network(self): - network = self.driver.ex_list_networks()[0] - self.assertTrue(self.driver.ex_delete_network(network=network)) - - def test_ex_get_metadata_for_node(self): - image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) - node = self.driver.create_node(name='foo', - image=image, - size=size) - - metadata = self.driver.ex_get_metadata_for_node(node) - self.assertEqual(metadata['My Server Name'], 'Apache1') - self.assertEqual(len(metadata), 1) - - def test_ex_pause_node(self): - node = Node( - id='12063', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - ret = self.driver.ex_pause_node(node) - self.assertTrue(ret is True) - - def test_ex_unpause_node(self): - node = Node( - id='12063', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - ret = self.driver.ex_unpause_node(node) - self.assertTrue(ret is True) - - def test_ex_suspend_node(self): - node = Node( - id='12063', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - ret = self.driver.ex_suspend_node(node) - self.assertTrue(ret is True) - - def test_ex_resume_node(self): - node = Node( - id='12063', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - ret = self.driver.ex_resume_node(node) - self.assertTrue(ret is True) - - def test_ex_get_console_output(self): - node = Node( - id='12086', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver, - ) - resp = self.driver.ex_get_console_output(node) - expected_output = 'FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE' - self.assertEqual(resp['output'], expected_output) - - def test_ex_list_snapshots(self): - if self.driver_type.type == 'rackspace': - self.conn_classes[0].type = 'RACKSPACE' - self.conn_classes[1].type = 'RACKSPACE' - - snapshots = self.driver.ex_list_snapshots() - self.assertEqual(len(snapshots), 2) - self.assertEqual(snapshots[0].extra['name'], 'snap-001') - - def test_ex_create_snapshot(self): - volume = self.driver.list_volumes()[0] - if self.driver_type.type == 'rackspace': - self.conn_classes[0].type = 'RACKSPACE' - self.conn_classes[1].type = 'RACKSPACE' - - ret = self.driver.ex_create_snapshot(volume, - 'Test Volume', - 'This is a test') - self.assertEqual(ret.id, '3fbbcccf-d058-4502-8844-6feeffdf4cb5') - - def test_ex_delete_snapshot(self): - if self.driver_type.type == 'rackspace': - self.conn_classes[0].type = 'RACKSPACE' - self.conn_classes[1].type = 'RACKSPACE' - - snapshot = self.driver.ex_list_snapshots()[0] - ret = self.driver.ex_delete_snapshot(snapshot) - self.assertTrue(ret) - - -class OpenStack_1_1_FactoryMethodTests(OpenStack_1_1_Tests): - should_list_locations = False - should_list_volumes = True - - driver_klass = OpenStack_1_1_NodeDriver - driver_type = get_driver(Provider.OPENSTACK) - driver_args = OPENSTACK_PARAMS + ('1.1',) - driver_kwargs = {'ex_force_auth_version': '2.0'} - - -class OpenStack_1_1_MockHttp(MockHttpTestCase): - fixtures = ComputeFileFixtures('openstack_v1.1') - auth_fixtures = OpenStackFixtures() - json_content_headers = {'content-type': 'application/json; charset=UTF-8'} - - def _v2_0_tokens(self, method, url, body, headers): - body = self.auth_fixtures.load('_v2_0__auth.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_0(self, method, url, body, headers): - headers = { - 'x-auth-token': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', - 'x-server-management-url': 'https://api.example.com/v1.1/slug', - } - return (httplib.NO_CONTENT, "", headers, httplib.responses[httplib.NO_CONTENT]) - - def _v1_1_slug_servers_detail(self, method, url, body, headers): - body = self.fixtures.load('_servers_detail.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_detail_ERROR_STATE_NO_IMAGE_ID(self, method, url, body, headers): - body = self.fixtures.load('_servers_detail_ERROR_STATE.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_flavors_detail(self, method, url, body, headers): - body = self.fixtures.load('_flavors_detail.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_images_detail(self, method, url, body, headers): - body = self.fixtures.load('_images_detail.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers(self, method, url, body, headers): - if method == "POST": - body = self.fixtures.load('_servers_create.json') - elif method == "GET": - body = self.fixtures.load('_servers.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - '_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_12065_action(self, method, url, body, headers): - if method != "POST": - self.fail('HTTP method other than POST to action URL') - - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - - def _v1_1_slug_servers_12064_action(self, method, url, body, headers): - if method != "POST": - self.fail('HTTP method other than POST to action URL') - if "createImage" in json.loads(body): - return (httplib.ACCEPTED, "", - {"location": "http://127.0.0.1/v1.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b"}, - httplib.responses[httplib.ACCEPTED]) - elif "rescue" in json.loads(body): - return (httplib.OK, '{"adminPass": "foo"}', {}, - httplib.responses[httplib.OK]) - - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - - def _v1_1_slug_servers_12066_action(self, method, url, body, headers): - if method != "POST": - self.fail('HTTP method other than POST to action URL') - if "rebuild" not in json.loads(body): - self.fail("Did not get expected action (rebuild) in action URL") - - self.assertTrue('\"OS-DCF:diskConfig\": \"MANUAL\"' in body, - msg="Manual disk configuration option was not specified in rebuild body: " + body) - - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - - def _v1_1_slug_servers_12065(self, method, url, body, headers): - if method == "DELETE": - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - else: - raise NotImplementedError() - - def _v1_1_slug_servers_12064(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_servers_12064.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - elif method == "PUT": - body = self.fixtures.load('_servers_12064_updated_name_bob.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - elif method == "DELETE": - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - else: - raise NotImplementedError() - - def _v1_1_slug_servers_12062(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_servers_12064.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_12063_metadata(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_servers_12063_metadata_two_keys.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - elif method == "PUT": - body = self.fixtures.load('_servers_12063_metadata_two_keys.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_EX_DISK_CONFIG(self, method, url, body, headers): - if method == "POST": - body = u(body) - self.assertTrue(body.find('\"OS-DCF:diskConfig\": \"AUTO\"')) - body = self.fixtures.load('_servers_create_disk_config.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_flavors_7(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_flavors_7.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - def _v1_1_slug_images_13(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_images_13.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - def _v1_1_slug_images_26365521_8c62_11f9_2c33_283d153ecc3a(self, method, url, body, headers): - if method == "DELETE": - return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) - else: - raise NotImplementedError() - - def _v1_1_slug_images_4949f9ee_2421_4c81_8b49_13119446008b(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - '_images_4949f9ee_2421_4c81_8b49_13119446008b.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - def _v1_1_slug_servers_1c01300f_ef97_4937_8f03_ac676d6234be_os_security_groups(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - '_servers_1c01300f-ef97-4937-8f03-ac676d6234be_os-security-groups.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_security_groups(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_os_security_groups.json') - elif method == "POST": - body = self.fixtures.load('_os_security_groups_create.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_security_groups_6(self, method, url, body, headers): - if method == "DELETE": - return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) - else: - raise NotImplementedError() - - def _v1_1_slug_os_security_group_rules(self, method, url, body, headers): - if method == "POST": - body = self.fixtures.load('_os_security_group_rules_create.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_security_group_rules_2(self, method, url, body, headers): - if method == "DELETE": - return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) - else: - raise NotImplementedError() - - def _v1_1_slug_os_keypairs(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_os_keypairs.json') - elif method == "POST": - if 'public_key' in body: - body = self.fixtures.load('_os_keypairs_create_import.json') - else: - body = self.fixtures.load('_os_keypairs_create.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_keypairs_test_key_pair(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('_os_keypairs_get_one.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_keypairs_doesnt_exist(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('_os_keypairs_not_found.json') - else: - raise NotImplementedError() - - return (httplib.NOT_FOUND, body, self.json_content_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _v1_1_slug_os_keypairs_key1(self, method, url, body, headers): - if method == "DELETE": - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - else: - raise NotImplementedError() - - def _v1_1_slug_os_volumes(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_os_volumes.json') - elif method == "POST": - body = self.fixtures.load('_os_volumes_create.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - '_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d.json') - elif method == "DELETE": - body = '' - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_12065_os_volume_attachments(self, method, url, body, headers): - if method == "POST": - body = self.fixtures.load( - '_servers_12065_os_volume_attachments.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_12065_os_volume_attachments_cd76a3a1_c4ce_40f6_9b9f_07a61508938d(self, method, url, body, - headers): - if method == "DELETE": - body = '' - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_floating_ip_pools(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_floating_ip_pools.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - def _v1_1_slug_os_floating_ips_foo_bar_id(self, method, url, body, headers): - if method == "DELETE": - body = '' - return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - def _v1_1_slug_os_floating_ips(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('_floating_ips.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - elif method == "POST": - body = self.fixtures.load('_floating_ip.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - def _v1_1_slug_servers_4242_action(self, method, url, body, headers): - if method == "POST": - body = '' - return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_networks(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('_os_networks.json') - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - elif method == 'POST': - body = self.fixtures.load('_os_networks_POST.json') - return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) - raise NotImplementedError() - - def _v1_1_slug_os_networks_f13e5051_feea_416b_827a_1a0acc2dad14(self, method, url, body, headers): - if method == 'DELETE': - body = '' - return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) - raise NotImplementedError() - - def _v1_1_slug_servers_72258_action(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('_servers_suspend.json') - return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_12063_action(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('_servers_unpause.json') - return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_servers_12086_action(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('_servers_12086_console_output.json') - return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) - else: - raise NotImplementedError() - - def _v1_1_slug_os_snapshots(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('_os_snapshots.json') - elif method == 'POST': - body = self.fixtures.load('_os_snapshots_create.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_snapshots_RACKSPACE(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('_os_snapshots_rackspace.json') - elif method == 'POST': - body = self.fixtures.load('_os_snapshots_create_rackspace.json') - else: - raise NotImplementedError() - - return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_snapshots_3fbbcccf_d058_4502_8844_6feeffdf4cb5(self, method, url, body, headers): - if method == 'DELETE': - body = '' - status_code = httplib.NO_CONTENT - else: - raise NotImplementedError() - - return (status_code, body, self.json_content_headers, httplib.responses[httplib.OK]) - - def _v1_1_slug_os_snapshots_3fbbcccf_d058_4502_8844_6feeffdf4cb5_RACKSPACE(self, method, url, body, headers): - if method == 'DELETE': - body = '' - status_code = httplib.NO_CONTENT - else: - raise NotImplementedError() - - return (status_code, body, self.json_content_headers, httplib.responses[httplib.OK]) - - -# This exists because the nova compute url in devstack has v2 in there but the v1.1 fixtures -# work fine. - - -class OpenStack_2_0_MockHttp(OpenStack_1_1_MockHttp): - - def __init__(self, *args, **kwargs): - super(OpenStack_2_0_MockHttp, self).__init__(*args, **kwargs) - - methods1 = OpenStack_1_1_MockHttp.__dict__ - - names1 = [m for m in methods1 if m.find('_v1_1') == 0] - - for name in names1: - method = methods1[name] - new_name = name.replace('_v1_1_slug_', '_v2_1337_') - setattr(self, new_name, method_type(method, self, - OpenStack_2_0_MockHttp)) - - -class OpenStack_1_1_Auth_2_0_Tests(OpenStack_1_1_Tests): - driver_args = OPENSTACK_PARAMS + ('1.1',) - driver_kwargs = {'ex_force_auth_version': '2.0'} - - def setUp(self): - self.driver_klass.connectionCls.conn_classes = \ - (OpenStack_2_0_MockHttp, OpenStack_2_0_MockHttp) - self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" - OpenStackMockHttp.type = None - OpenStack_1_1_MockHttp.type = None - OpenStack_2_0_MockHttp.type = None - self.driver = self.create_driver() - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - clear_pricing_data() - self.node = self.driver.list_nodes()[1] - - def test_auth_user_info_is_set(self): - self.driver.connection._populate_hosts_and_request_paths() - self.assertEqual(self.driver.connection.auth_user_info, { - 'id': '7', - 'name': 'testuser', - 'roles': [{'description': 'Default Role.', - 'id': 'identity:default', - 'name': 'identity:default'}]}) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_opsource.py b/awx/lib/site-packages/libcloud/test/compute/test_opsource.py deleted file mode 100644 index f9efdcf59d..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_opsource.py +++ /dev/null @@ -1,251 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.common.types import InvalidCredsError -from libcloud.compute.drivers.opsource import OpsourceNodeDriver as Opsource -from libcloud.compute.drivers.opsource import OpsourceAPIException -from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - -from libcloud.test.secrets import OPSOURCE_PARAMS - - -class OpsourceTests(unittest.TestCase, TestCaseMixin): - - def setUp(self): - Opsource.connectionCls.conn_classes = (None, OpsourceMockHttp) - OpsourceMockHttp.type = None - self.driver = Opsource(*OPSOURCE_PARAMS) - - def test_invalid_creds(self): - OpsourceMockHttp.type = 'UNAUTHORIZED' - try: - self.driver.list_nodes() - self.assertTrue( - False) # Above command should have thrown an InvalidCredsException - except InvalidCredsError: - self.assertTrue(True) - - def test_list_sizes_response(self): - OpsourceMockHttp.type = None - ret = self.driver.list_sizes() - self.assertEqual(len(ret), 1) - size = ret[0] - self.assertEqual(size.name, 'default') - - def test_reboot_node_response(self): - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - ret = node.reboot() - self.assertTrue(ret is True) - - def test_reboot_node_response_INPROGRESS(self): - OpsourceMockHttp.type = 'INPROGRESS' - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - try: - node.reboot() - self.assertTrue( - False) # above command should have thrown OpsourceAPIException - except OpsourceAPIException: - self.assertTrue(True) - - def test_destroy_node_response(self): - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - ret = node.destroy() - self.assertTrue(ret is True) - - def test_destroy_node_response_INPROGRESS(self): - OpsourceMockHttp.type = 'INPROGRESS' - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - try: - node.destroy() - self.assertTrue( - False) # above command should have thrown OpsourceAPIException - except OpsourceAPIException: - self.assertTrue(True) - - def test_create_node_response(self): - rootPw = NodeAuthPassword('pass123') - image = self.driver.list_images()[0] - network = self.driver.ex_list_networks()[0] - node = self.driver.create_node(name='test2', image=image, auth=rootPw, - ex_description='test2 node', ex_network=network, - ex_isStarted=False) - self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') - self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') - - def test_ex_shutdown_graceful(self): - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - ret = self.driver.ex_shutdown_graceful(node) - self.assertTrue(ret is True) - - def test_ex_shutdown_graceful_INPROGRESS(self): - OpsourceMockHttp.type = 'INPROGRESS' - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - try: - self.driver.ex_shutdown_graceful(node) - self.assertTrue( - False) # above command should have thrown OpsourceAPIException - except OpsourceAPIException: - self.assertTrue(True) - - def test_ex_start_node(self): - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - ret = self.driver.ex_start_node(node) - self.assertTrue(ret is True) - - def test_ex_start_node_INPROGRESS(self): - OpsourceMockHttp.type = 'INPROGRESS' - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - try: - self.driver.ex_start_node(node) - self.assertTrue( - False) # above command should have thrown OpsourceAPIException - except OpsourceAPIException: - self.assertTrue(True) - - def test_ex_power_off(self): - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - ret = self.driver.ex_power_off(node) - self.assertTrue(ret is True) - - def test_ex_power_off_INPROGRESS(self): - OpsourceMockHttp.type = 'INPROGRESS' - node = Node(id='11', name=None, state=None, - public_ips=None, private_ips=None, driver=self.driver) - try: - self.driver.ex_power_off(node) - self.assertTrue( - False) # above command should have thrown OpsourceAPIException - except OpsourceAPIException: - self.assertTrue(True) - - def test_ex_list_networks(self): - nets = self.driver.ex_list_networks() - self.assertEqual(nets[0].name, 'test-net1') - self.assertTrue(isinstance(nets[0].location, NodeLocation)) - - def test_node_public_ip(self): - nodes = self.driver.list_nodes() - node = [n for n in nodes if n.id == - 'abadbc7e-9e10-46ca-9d4a-194bcc6b6c16'][0] - self.assertEqual(node.public_ips[0], '200.16.132.7') - - -class OpsourceMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('opsource') - - def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): - return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) - - def _oec_0_9_myaccount(self, method, url, body, headers): - body = self.fixtures.load('oec_0_9_myaccount.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): - body = self.fixtures.load('oec_0_9_myaccount.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_base_image(self, method, url, body, headers): - body = self.fixtures.load('oec_0_9_base_image.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed(self, method, url, body, headers): - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy(self, method, url, body, headers): - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter(self, method, url, body, headers): - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11(self, method, url, body, headers): - body = None - action = url.split('?')[-1] - - if action == 'restart': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xml') - elif action == 'shutdown': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xml') - elif action == 'delete': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xml') - elif action == 'start': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xml') - elif action == 'poweroff': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xml') - - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_INPROGRESS(self, method, url, body, headers): - body = None - action = url.split('?')[-1] - - if action == 'restart': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xml') - elif action == 'shutdown': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xml') - elif action == 'delete': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xml') - elif action == 'start': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xml') - elif action == 'poweroff': - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xml') - - return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers): - body = self.fixtures.load( - '_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation(self, method, url, body, headers): - body = self.fixtures.load( - 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_rackspace.py b/awx/lib/site-packages/libcloud/test/compute/test_rackspace.py deleted file mode 100644 index d42e6681cf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_rackspace.py +++ /dev/null @@ -1,213 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest - -from libcloud.utils.py3 import method_type -from libcloud.utils.py3 import httplib -from libcloud.compute.providers import DEPRECATED_RACKSPACE_PROVIDERS -from libcloud.compute.providers import get_driver -from libcloud.compute.drivers.rackspace import RackspaceFirstGenNodeDriver -from libcloud.compute.drivers.rackspace import RackspaceNodeDriver -from libcloud.test.compute.test_openstack import OpenStack_1_0_Tests -from libcloud.test.compute.test_openstack import OpenStack_1_1_Tests, \ - OpenStack_1_1_MockHttp -from libcloud.pricing import clear_pricing_data - -from libcloud.test.secrets import RACKSPACE_NOVA_PARAMS -from libcloud.test.secrets import RACKSPACE_PARAMS - - -class RackspaceusFirstGenUsTests(OpenStack_1_0_Tests): - should_list_locations = True - should_have_pricing = True - - driver_klass = RackspaceFirstGenNodeDriver - driver_type = RackspaceFirstGenNodeDriver - driver_args = RACKSPACE_PARAMS - driver_kwargs = {'region': 'us'} - - def test_error_is_thrown_on_accessing_old_constant(self): - for provider in DEPRECATED_RACKSPACE_PROVIDERS: - try: - get_driver(provider) - except Exception: - e = sys.exc_info()[1] - self.assertTrue(str(e).find('has been removed') != -1) - else: - self.fail('Exception was not thrown') - - def test_list_sizes_pricing(self): - sizes = self.driver.list_sizes() - - for size in sizes: - self.assertTrue(size.price > 0) - - -class RackspaceusFirstGenUkTests(OpenStack_1_0_Tests): - should_list_locations = True - should_have_pricing = True - - driver_klass = RackspaceFirstGenNodeDriver - driver_type = RackspaceFirstGenNodeDriver - driver_args = RACKSPACE_PARAMS - driver_kwargs = {'region': 'uk'} - - def test_list_sizes_pricing(self): - sizes = self.driver.list_sizes() - - for size in sizes: - self.assertTrue(size.price > 0) - - -class RackspaceNovaMockHttp(OpenStack_1_1_MockHttp): - - def __init__(self, *args, **kwargs): - super(RackspaceNovaMockHttp, self).__init__(*args, **kwargs) - - methods1 = OpenStack_1_1_MockHttp.__dict__ - - names1 = [m for m in methods1 if m.find('_v1_1') == 0] - - for name in names1: - method = methods1[name] - new_name = name.replace('_v1_1_slug_', '_v2_1337_') - setattr(self, new_name, method_type(method, self, - RackspaceNovaMockHttp)) - - def _v2_1337_os_networksv2(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('_os_networks.json') - return (httplib.OK, body, self.json_content_headers, - httplib.responses[httplib.OK]) - elif method == 'POST': - body = self.fixtures.load('_os_networks_POST.json') - return (httplib.ACCEPTED, body, self.json_content_headers, - httplib.responses[httplib.OK]) - raise NotImplementedError() - - def _v2_1337_os_networksv2_f13e5051_feea_416b_827a_1a0acc2dad14(self, - method, - url, body, - headers): - if method == 'DELETE': - body = '' - return (httplib.ACCEPTED, body, self.json_content_headers, - httplib.responses[httplib.OK]) - raise NotImplementedError() - - -class RackspaceNovaLonMockHttp(RackspaceNovaMockHttp): - - def _v2_0_tokens(self, method, url, body, headers): - body = self.auth_fixtures.load('_v2_0__auth_lon.json') - return (httplib.OK, body, self.json_content_headers, - httplib.responses[httplib.OK]) - - -class BaseRackspaceNovaTestCase(object): - conn_classes = (RackspaceNovaMockHttp, RackspaceNovaMockHttp) - auth_url = 'https://auth.api.example.com' - - def create_driver(self): - return self.driver_type(*self.driver_args, **self.driver_kwargs) - - def setUp(self): - self.driver_klass.connectionCls.conn_classes = self.conn_classes - self.driver_klass.connectionCls.auth_url = self.auth_url - self.conn_classes[0].type = None - self.conn_classes[1].type = None - self.driver = self.create_driver() - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - clear_pricing_data() - self.node = self.driver.list_nodes()[1] - - def test_service_catalog_contais_right_endpoint(self): - self.assertEqual(self.driver.connection.get_endpoint(), - self.expected_endpoint) - - def test_list_sizes_pricing(self): - sizes = self.driver.list_sizes() - - for size in sizes: - if size.ram > 256: - self.assertTrue(size.price > 0) - - -class RackspaceNovaDfwTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): - - driver_klass = RackspaceNodeDriver - driver_type = RackspaceNodeDriver - driver_args = RACKSPACE_NOVA_PARAMS - driver_kwargs = {'region': 'dfw'} - - expected_endpoint = 'https://dfw.servers.api.rackspacecloud.com/v2/1337' - - -class RackspaceNovaOrdTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): - - driver_klass = RackspaceNodeDriver - driver_type = RackspaceNodeDriver - driver_args = RACKSPACE_NOVA_PARAMS - driver_kwargs = {'region': 'ord'} - - expected_endpoint = 'https://ord.servers.api.rackspacecloud.com/v2/1337' - - -class RackspaceNovaIadTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): - - driver_klass = RackspaceNodeDriver - driver_type = RackspaceNodeDriver - driver_args = RACKSPACE_NOVA_PARAMS - driver_kwargs = {'region': 'iad'} - - expected_endpoint = 'https://iad.servers.api.rackspacecloud.com/v2/1337' - - -class RackspaceNovaLonTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): - - driver_klass = RackspaceNodeDriver - driver_type = RackspaceNodeDriver - driver_args = RACKSPACE_NOVA_PARAMS - driver_kwargs = {'region': 'lon'} - - conn_classes = (RackspaceNovaLonMockHttp, RackspaceNovaLonMockHttp) - auth_url = 'https://lon.auth.api.example.com' - - expected_endpoint = 'https://lon.servers.api.rackspacecloud.com/v2/1337' - - -class RackspaceNovaSydTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): - - driver_klass = RackspaceNodeDriver - driver_type = RackspaceNodeDriver - driver_args = RACKSPACE_NOVA_PARAMS - driver_kwargs = {'region': 'syd'} - - expected_endpoint = 'https://syd.servers.api.rackspacecloud.com/v2/1337' - - -class RackspaceNovaHkgTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): - - driver_klass = RackspaceNodeDriver - driver_type = RackspaceNodeDriver - driver_args = RACKSPACE_NOVA_PARAMS - driver_kwargs = {'region': 'hkg'} - - expected_endpoint = 'https://hkg.servers.api.rackspacecloud.com/v2/1337' - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_rimuhosting.py b/awx/lib/site-packages/libcloud/test/compute/test_rimuhosting.py deleted file mode 100644 index f8eb3ab16b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_rimuhosting.py +++ /dev/null @@ -1,113 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# Copyright 2009 RedRata Ltd - -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.rimuhosting import RimuHostingNodeDriver - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class RimuHostingTest(unittest.TestCase, TestCaseMixin): - - def setUp(self): - RimuHostingNodeDriver.connectionCls.conn_classes = (None, - RimuHostingMockHttp) - self.driver = RimuHostingNodeDriver('foo') - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - self.assertEqual(len(nodes), 1) - node = nodes[0] - self.assertEqual(node.public_ips[0], "1.2.3.4") - self.assertEqual(node.public_ips[1], "1.2.3.5") - self.assertEqual(node.extra['order_oid'], 88833465) - self.assertEqual(node.id, "order-88833465-api-ivan-net-nz") - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 1) - size = sizes[0] - self.assertEqual(size.ram, 950) - self.assertEqual(size.disk, 20) - self.assertEqual(size.bandwidth, 75) - self.assertEqual(size.price, 32.54) - - def test_list_images(self): - images = self.driver.list_images() - self.assertEqual(len(images), 6) - image = images[0] - self.assertEqual(image.name, "Debian 5.0 (aka Lenny, RimuHosting" - " recommended distro)") - self.assertEqual(image.id, "lenny") - - def test_reboot_node(self): - # Raises exception on failure - node = self.driver.list_nodes()[0] - self.driver.reboot_node(node) - - def test_destroy_node(self): - # Raises exception on failure - node = self.driver.list_nodes()[0] - self.driver.destroy_node(node) - - def test_create_node(self): - # Raises exception on failure - size = self.driver.list_sizes()[0] - image = self.driver.list_images()[0] - self.driver.create_node(name="api.ivan.net.nz", image=image, size=size) - - -class RimuHostingMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('rimuhosting') - - def _r_orders(self, method, url, body, headers): - body = self.fixtures.load('r_orders.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _r_pricing_plans(self, method, url, body, headers): - body = self.fixtures.load('r_pricing_plans.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _r_distributions(self, method, url, body, headers): - body = self.fixtures.load('r_distributions.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _r_orders_new_vps(self, method, url, body, headers): - body = self.fixtures.load('r_orders_new_vps.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _r_orders_order_88833465_api_ivan_net_nz_vps(self, method, url, body, headers): - body = self.fixtures.load( - 'r_orders_order_88833465_api_ivan_net_nz_vps.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _r_orders_order_88833465_api_ivan_net_nz_vps_running_state( - self, method, - url, body, - headers): - body = self.fixtures.load( - 'r_orders_order_88833465_api_ivan_net_nz_vps_running_state.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_softlayer.py b/awx/lib/site-packages/libcloud/test/compute/test_softlayer.py deleted file mode 100644 index 74f4a3278b..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_softlayer.py +++ /dev/null @@ -1,193 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest -import sys - -from libcloud.common.types import InvalidCredsError - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import xmlrpclib -from libcloud.utils.py3 import next - -from libcloud.compute.drivers.softlayer import SoftLayerNodeDriver as SoftLayer -from libcloud.compute.drivers.softlayer import SoftLayerException, \ - NODE_STATE_MAP -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp # pylint: disable-msg=E0611 -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import SOFTLAYER_PARAMS - - -class SoftLayerTests(unittest.TestCase): - - def setUp(self): - SoftLayer.connectionCls.conn_classes = ( - SoftLayerMockHttp, SoftLayerMockHttp) - SoftLayerMockHttp.type = None - self.driver = SoftLayer(*SOFTLAYER_PARAMS) - - def test_list_nodes(self): - nodes = self.driver.list_nodes() - node = nodes[0] - self.assertEqual(node.name, 'libcloud-testing1.example.com') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.extra['password'], 'L3TJVubf') - - def test_initializing_state(self): - nodes = self.driver.list_nodes() - node = nodes[1] - self.assertEqual(node.state, NODE_STATE_MAP['INITIATING']) - - def test_list_locations(self): - locations = self.driver.list_locations() - dal = next(l for l in locations if l.id == 'dal05') - self.assertEqual(dal.country, 'US') - self.assertEqual(dal.id, 'dal05') - self.assertEqual(dal.name, 'Dallas - Central U.S.') - - def test_list_images(self): - images = self.driver.list_images() - image = images[0] - self.assertEqual(image.id, 'CENTOS_6_64') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 13) - - def test_create_node(self): - node = self.driver.create_node(name="libcloud-testing", - location=self.driver.list_locations()[0], - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[0]) - self.assertEqual(node.name, 'libcloud-testing.example.com') - self.assertEqual(node.state, NODE_STATE_MAP['RUNNING']) - - def test_create_fail(self): - SoftLayerMockHttp.type = "SOFTLAYEREXCEPTION" - self.assertRaises( - SoftLayerException, - self.driver.create_node, - name="SOFTLAYEREXCEPTION", - location=self.driver.list_locations()[0], - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[0]) - - def test_create_creds_error(self): - SoftLayerMockHttp.type = "INVALIDCREDSERROR" - self.assertRaises( - InvalidCredsError, - self.driver.create_node, - name="INVALIDCREDSERROR", - location=self.driver.list_locations()[0], - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[0]) - - def test_create_node_no_location(self): - self.driver.create_node(name="Test", - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[0]) - - def test_create_node_no_image(self): - self.driver.create_node(name="Test", size=self.driver.list_sizes()[0]) - - def test_create_node_san(self): - self.driver.create_node(name="Test", ex_local_disk=False) - - def test_create_node_domain_for_name(self): - self.driver.create_node(name="libcloud.org") - - def test_create_node_ex_options(self): - self.driver.create_node(name="Test", - location=self.driver.list_locations()[0], - size=self.driver.list_sizes()[0], - image=self.driver.list_images()[0], - ex_domain='libcloud.org', - ex_cpus=2, - ex_ram=2048, - ex_disk=100, - ex_bandwidth=10, - ex_local_disk=False, - ex_datacenter='Dal05', - ex_os='UBUNTU_LATEST') - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - self.driver.reboot_node(node) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - self.driver.destroy_node(node) - - -class SoftLayerMockHttp(MockHttp): - fixtures = ComputeFileFixtures('softlayer') - - def _get_method_name(self, type, use_param, qs, path): - return "_xmlrpc" - - def _xmlrpc(self, method, url, body, headers): - params, meth_name = xmlrpclib.loads(body) - url = url.replace("/", "_") - meth_name = "%s_%s" % (url, meth_name) - return getattr(self, meth_name)(method, url, body, headers) - - def _xmlrpc_v3_SoftLayer_Virtual_Guest_getCreateObjectOptions( - self, method, url, body, headers): - body = self.fixtures.load( - 'v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc_v3_SoftLayer_Account_getVirtualGuests( - self, method, url, body, headers): - body = self.fixtures.load('v3_SoftLayer_Account_getVirtualGuests.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc_v3_SoftLayer_Location_Datacenter_getDatacenters( - self, method, url, body, headers): - body = self.fixtures.load( - 'v3_SoftLayer_Location_Datacenter_getDatacenters.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc_v3_SoftLayer_Virtual_Guest_createObject( - self, method, url, body, headers): - fixture = { - None: 'v3__SoftLayer_Virtual_Guest_createObject.xml', - 'INVALIDCREDSERROR': 'SoftLayer_Account.xml', - 'SOFTLAYEREXCEPTION': 'fail.xml', - }[self.type] - body = self.fixtures.load(fixture) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc_v3_SoftLayer_Virtual_Guest_getObject( - self, method, url, body, headers): - body = self.fixtures.load( - 'v3__SoftLayer_Virtual_Guest_getObject.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc_v3_SoftLayer_Virtual_Guest_rebootSoft( - self, method, url, body, headers): - body = self.fixtures.load('empty.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc_v3_SoftLayer_Virtual_Guest_deleteObject( - self, method, url, body, headers): - body = self.fixtures.load('empty.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_ssh_client.py b/awx/lib/site-packages/libcloud/test/compute/test_ssh_client.py deleted file mode 100644 index 857f4e2eea..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_ssh_client.py +++ /dev/null @@ -1,321 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed to the Apache Software Foundation (ASF) under one or more§ -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -from __future__ import with_statement - -import os -import sys -import tempfile - -from libcloud import _init_once -from libcloud.test import LibcloudTestCase -from libcloud.test import unittest -from libcloud.compute.ssh import ParamikoSSHClient -from libcloud.compute.ssh import ShellOutSSHClient -from libcloud.compute.ssh import have_paramiko - -from libcloud.utils.py3 import StringIO - -from mock import patch, Mock - -if not have_paramiko: - ParamikoSSHClient = None # NOQA -else: - import paramiko - - -class ParamikoSSHClientTests(LibcloudTestCase): - - @patch('paramiko.SSHClient', Mock) - def setUp(self): - """ - Creates the object patching the actual connection. - """ - conn_params = {'hostname': 'dummy.host.org', - 'port': 8822, - 'username': 'ubuntu', - 'key': '~/.ssh/ubuntu_ssh', - 'timeout': '600'} - _, self.tmp_file = tempfile.mkstemp() - os.environ['LIBCLOUD_DEBUG'] = self.tmp_file - _init_once() - self.ssh_cli = ParamikoSSHClient(**conn_params) - - @patch('paramiko.SSHClient', Mock) - def test_create_with_password(self): - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu', - 'password': 'ubuntu'} - mock = ParamikoSSHClient(**conn_params) - mock.connect() - - expected_conn = {'username': 'ubuntu', - 'password': 'ubuntu', - 'allow_agent': False, - 'hostname': 'dummy.host.org', - 'look_for_keys': False, - 'port': 22} - mock.client.connect.assert_called_once_with(**expected_conn) - self.assertLogMsg('Connecting to server') - - @patch('paramiko.SSHClient', Mock) - def test_deprecated_key_argument(self): - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu', - 'key': 'id_rsa'} - mock = ParamikoSSHClient(**conn_params) - mock.connect() - - expected_conn = {'username': 'ubuntu', - 'allow_agent': False, - 'hostname': 'dummy.host.org', - 'look_for_keys': False, - 'key_filename': 'id_rsa', - 'port': 22} - mock.client.connect.assert_called_once_with(**expected_conn) - self.assertLogMsg('Connecting to server') - - def test_key_files_and_key_material_arguments_are_mutual_exclusive(self): - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu', - 'key_files': 'id_rsa', - 'key_material': 'key'} - - expected_msg = ('key_files and key_material arguments are mutually ' - 'exclusive') - self.assertRaisesRegexp(ValueError, expected_msg, - ParamikoSSHClient, **conn_params) - - @patch('paramiko.SSHClient', Mock) - def test_key_material_argument(self): - path = os.path.join(os.path.dirname(__file__), - 'fixtures', 'misc', 'dummy_rsa') - - with open(path, 'r') as fp: - private_key = fp.read() - - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu', - 'key_material': private_key} - mock = ParamikoSSHClient(**conn_params) - mock.connect() - - pkey = paramiko.RSAKey.from_private_key(StringIO(private_key)) - expected_conn = {'username': 'ubuntu', - 'allow_agent': False, - 'hostname': 'dummy.host.org', - 'look_for_keys': False, - 'pkey': pkey, - 'port': 22} - mock.client.connect.assert_called_once_with(**expected_conn) - self.assertLogMsg('Connecting to server') - - @patch('paramiko.SSHClient', Mock) - def test_key_material_argument_invalid_key(self): - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu', - 'key_material': 'id_rsa'} - - mock = ParamikoSSHClient(**conn_params) - - expected_msg = 'Invalid or unsupported key type' - self.assertRaisesRegexp(paramiko.ssh_exception.SSHException, - expected_msg, mock.connect) - - @patch('paramiko.SSHClient', Mock) - def test_create_with_key(self): - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu', - 'key_files': 'id_rsa'} - mock = ParamikoSSHClient(**conn_params) - mock.connect() - - expected_conn = {'username': 'ubuntu', - 'allow_agent': False, - 'hostname': 'dummy.host.org', - 'look_for_keys': False, - 'key_filename': 'id_rsa', - 'port': 22} - mock.client.connect.assert_called_once_with(**expected_conn) - self.assertLogMsg('Connecting to server') - - @patch('paramiko.SSHClient', Mock) - def test_create_with_password_and_key(self): - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu', - 'password': 'ubuntu', - 'key': 'id_rsa'} - mock = ParamikoSSHClient(**conn_params) - mock.connect() - - expected_conn = {'username': 'ubuntu', - 'password': 'ubuntu', - 'allow_agent': False, - 'hostname': 'dummy.host.org', - 'look_for_keys': False, - 'key_filename': 'id_rsa', - 'port': 22} - mock.client.connect.assert_called_once_with(**expected_conn) - self.assertLogMsg('Connecting to server') - - @patch('paramiko.SSHClient', Mock) - def test_create_without_credentials(self): - """ - Initialize object with no credentials. - - Just to have better coverage, initialize the object - without 'password' neither 'key'. - """ - conn_params = {'hostname': 'dummy.host.org', - 'username': 'ubuntu'} - mock = ParamikoSSHClient(**conn_params) - mock.connect() - - expected_conn = {'username': 'ubuntu', - 'hostname': 'dummy.host.org', - 'allow_agent': True, - 'look_for_keys': True, - 'port': 22} - mock.client.connect.assert_called_once_with(**expected_conn) - - def test_basic_usage_absolute_path(self): - """ - Basic execution. - """ - mock = self.ssh_cli - # script to execute - sd = "/root/random_script.sh" - - # Connect behavior - mock.connect() - mock_cli = mock.client # The actual mocked object: SSHClient - expected_conn = {'username': 'ubuntu', - 'key_filename': '~/.ssh/ubuntu_ssh', - 'allow_agent': False, - 'hostname': 'dummy.host.org', - 'look_for_keys': False, - 'timeout': '600', - 'port': 8822} - mock_cli.connect.assert_called_once_with(**expected_conn) - - mock.put(sd) - # Make assertions over 'put' method - mock_cli.open_sftp().chdir.assert_called_with('root') - mock_cli.open_sftp().file.assert_called_once_with('random_script.sh', - mode='w') - - mock.run(sd) - - # Make assertions over 'run' method - mock_cli.get_transport().open_session().exec_command \ - .assert_called_once_with(sd) - self.assertLogMsg('Executing command (cmd=/root/random_script.sh)') - self.assertLogMsg('Command finished') - - mock.close() - - def test_delete_script(self): - """ - Provide a basic test with 'delete' action. - """ - mock = self.ssh_cli - # script to execute - sd = '/root/random_script.sh' - - mock.connect() - - mock.delete(sd) - # Make assertions over the 'delete' method - mock.client.open_sftp().unlink.assert_called_with(sd) - self.assertLogMsg('Deleting file') - - mock.close() - self.assertLogMsg('Closing server connection') - - def assertLogMsg(self, expected_msg): - with open(self.tmp_file, 'r') as fp: - content = fp.read() - - self.assertTrue(content.find(expected_msg) != -1) - - -if not ParamikoSSHClient: - class ParamikoSSHClientTests(LibcloudTestCase): # NOQA - pass - - -class ShellOutSSHClientTests(LibcloudTestCase): - - def test_password_auth_not_supported(self): - try: - ShellOutSSHClient(hostname='localhost', username='foo', - password='bar') - except ValueError: - e = sys.exc_info()[1] - msg = str(e) - self.assertTrue('ShellOutSSHClient only supports key auth' in msg) - else: - self.fail('Exception was not thrown') - - def test_ssh_executable_not_available(self): - class MockChild(object): - returncode = 127 - - def communicate(*args, **kwargs): - pass - - def mock_popen(*args, **kwargs): - return MockChild() - - with patch('subprocess.Popen', mock_popen): - try: - ShellOutSSHClient(hostname='localhost', username='foo') - except ValueError: - e = sys.exc_info()[1] - msg = str(e) - self.assertTrue('ssh client is not available' in msg) - else: - self.fail('Exception was not thrown') - - def test_connect_success(self): - client = ShellOutSSHClient(hostname='localhost', username='root') - self.assertTrue(client.connect()) - - def test_close_success(self): - client = ShellOutSSHClient(hostname='localhost', username='root') - self.assertTrue(client.close()) - - def test_get_base_ssh_command(self): - client1 = ShellOutSSHClient(hostname='localhost', username='root') - client2 = ShellOutSSHClient(hostname='localhost', username='root', - key='/home/my.key') - client3 = ShellOutSSHClient(hostname='localhost', username='root', - key='/home/my.key', timeout=5) - - cmd1 = client1._get_base_ssh_command() - cmd2 = client2._get_base_ssh_command() - cmd3 = client3._get_base_ssh_command() - - self.assertEqual(cmd1, ['ssh', 'root@localhost']) - self.assertEqual(cmd2, ['ssh', '-i', '/home/my.key', - 'root@localhost']) - self.assertEqual(cmd3, ['ssh', '-i', '/home/my.key', - '-oConnectTimeout=5', 'root@localhost']) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_vcl.py b/awx/lib/site-packages/libcloud/test/compute/test_vcl.py deleted file mode 100644 index 31d0fb09f8..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_vcl.py +++ /dev/null @@ -1,127 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest -import sys - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import xmlrpclib - -from libcloud.compute.drivers.vcl import VCLNodeDriver as VCL -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import ComputeFileFixtures -from libcloud.test.secrets import VCL_PARAMS - - -class VCLTests(unittest.TestCase): - - def setUp(self): - VCL.connectionCls.conn_classes = ( - VCLMockHttp, VCLMockHttp) - VCLMockHttp.type = None - self.driver = VCL(*VCL_PARAMS) - - def test_list_nodes(self): - node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] - self.assertEqual(node.name, 'CentOS 5.4 Base (32 bit VM)') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.extra['pass'], 'ehkNGW') - - def test_list_images(self): - images = self.driver.list_images() - image = images[0] - self.assertEqual(image.id, '8') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - self.assertEqual(len(sizes), 1) - - def test_create_node(self): - image = self.driver.list_images()[0] - node = self.driver.create_node(image=image) - self.assertEqual(node.id, '51') - - def test_destroy_node(self): - node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] - self.assertTrue(self.driver.destroy_node(node)) - - def test_ex_update_node_access(self): - node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] - node = self.driver.ex_update_node_access(node, ipaddr='192.168.1.2') - self.assertEqual(node.name, 'CentOS 5.4 Base (32 bit VM)') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.extra['pass'], 'ehkNGW') - - def test_ex_extend_request_time(self): - node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] - self.assertTrue(self.driver.ex_extend_request_time(node, 60)) - - def test_ex_get_request_end_time(self): - node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] - self.assertEqual( - self.driver.ex_get_request_end_time(node), - 1334168100 - ) - - -class VCLMockHttp(MockHttp): - fixtures = ComputeFileFixtures('vcl') - - def _get_method_name(self, type, use_param, qs, path): - return "_xmlrpc" - - def _xmlrpc(self, method, url, body, headers): - params, meth_name = xmlrpclib.loads(body) - if self.type: - meth_name = "%s_%s" % (meth_name, self.type) - return getattr(self, meth_name)(method, url, body, headers) - - def XMLRPCgetImages(self, method, url, body, headers): - body = self.fixtures.load('XMLRPCgetImages.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def XMLRPCextendRequest(self, method, url, body, headers): - body = self.fixtures.load('XMLRPCextendRequest.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def XMLRPCgetRequestIds(self, method, url, body, headers): - body = self.fixtures.load( - 'XMLRPCgetRequestIds.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def XMLRPCgetRequestStatus(self, method, url, body, headers): - body = self.fixtures.load( - 'XMLRPCgetRequestStatus.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def XMLRPCendRequest(self, method, url, body, headers): - body = self.fixtures.load( - 'XMLRPCendRequest.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def XMLRPCaddRequest(self, method, url, body, headers): - body = self.fixtures.load( - 'XMLRPCaddRequest.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def XMLRPCgetRequestConnectData(self, method, url, body, headers): - body = self.fixtures.load( - 'XMLRPCgetRequestConnectData.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_vcloud.py b/awx/lib/site-packages/libcloud/test/compute/test_vcloud.py deleted file mode 100644 index fc801bebbf..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_vcloud.py +++ /dev/null @@ -1,717 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.utils.py3 import httplib, b - -from libcloud.compute.drivers.vcloud import TerremarkDriver, VCloudNodeDriver, Subject -from libcloud.compute.drivers.vcloud import VCloud_1_5_NodeDriver, ControlAccess -from libcloud.compute.drivers.vcloud import VCloud_5_1_NodeDriver -from libcloud.compute.drivers.vcloud import Vdc -from libcloud.compute.base import Node, NodeImage -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin -from libcloud.test.file_fixtures import ComputeFileFixtures - -from libcloud.test.secrets import VCLOUD_PARAMS - - -class TerremarkTests(unittest.TestCase, TestCaseMixin): - - def setUp(self): - VCloudNodeDriver.connectionCls.host = "test" - VCloudNodeDriver.connectionCls.conn_classes = (None, TerremarkMockHttp) - TerremarkMockHttp.type = None - self.driver = TerremarkDriver(*VCLOUD_PARAMS) - - def test_list_images(self): - ret = self.driver.list_images() - self.assertEqual( - ret[0].id, 'https://services.vcloudexpress.terremark.com/api/v0.8/vAppTemplate/5') - - def test_list_sizes(self): - ret = self.driver.list_sizes() - self.assertEqual(ret[0].ram, 512) - - def test_create_node(self): - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - node = self.driver.create_node( - name='testerpart2', - image=image, - size=size, - vdc='https://services.vcloudexpress.terremark.com/api/v0.8/vdc/224', - network='https://services.vcloudexpress.terremark.com/api/v0.8/network/725', - cpus=2, - ) - self.assertTrue(isinstance(node, Node)) - self.assertEqual( - node.id, 'https://services.vcloudexpress.terremark.com/api/v0.8/vapp/14031') - self.assertEqual(node.name, 'testerpart2') - - def test_list_nodes(self): - ret = self.driver.list_nodes() - node = ret[0] - self.assertEqual( - node.id, 'https://services.vcloudexpress.terremark.com/api/v0.8/vapp/14031') - self.assertEqual(node.name, 'testerpart2') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.public_ips, []) - self.assertEqual(node.private_ips, ['10.112.78.69']) - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - ret = self.driver.reboot_node(node) - self.assertTrue(ret) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - -class VCloud_1_5_Tests(unittest.TestCase, TestCaseMixin): - - def setUp(self): - VCloudNodeDriver.connectionCls.host = 'test' - VCloudNodeDriver.connectionCls.conn_classes = ( - None, VCloud_1_5_MockHttp) - VCloud_1_5_MockHttp.type = None - self.driver = VCloud_1_5_NodeDriver(*VCLOUD_PARAMS) - - def test_list_images(self): - ret = self.driver.list_images() - self.assertEqual( - 'https://vm-vcloud/api/vAppTemplate/vappTemplate-ac1bc027-bf8c-4050-8643-4971f691c158', ret[0].id) - - def test_list_sizes(self): - ret = self.driver.list_sizes() - self.assertEqual(ret[0].ram, 512) - - def test_networks(self): - ret = self.driver.networks - self.assertEqual( - ret[0].get('href'), 'https://vm-vcloud/api/network/dca8b667-6c8f-4c3e-be57-7a9425dba4f4') - - def test_create_node(self): - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - node = self.driver.create_node( - name='testNode', - image=image, - size=size, - ex_vdc='MyVdc', - ex_network='vCloud - Default', - cpus=2, - ) - self.assertTrue(isinstance(node, Node)) - self.assertEqual( - 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', node.id) - self.assertEqual('testNode', node.name) - - def test_create_node_clone(self): - image = self.driver.list_nodes()[0] - node = self.driver.create_node(name='testNode', image=image) - self.assertTrue(isinstance(node, Node)) - self.assertEqual( - 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', node.id) - self.assertEqual('testNode', node.name) - - def test_list_nodes(self): - ret = self.driver.list_nodes() - node = ret[0] - self.assertEqual( - node.id, 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a') - self.assertEqual(node.name, 'testNode') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.public_ips, ['65.41.67.2']) - self.assertEqual(node.private_ips, ['65.41.67.2']) - self.assertEqual(node.extra, {'vdc': 'MyVdc', - 'vms': [{ - 'id': 'https://vm-vcloud/api/vApp/vm-dd75d1d3-5b7b-48f0-aff3-69622ab7e045', - 'name': 'testVm', - 'state': NodeState.RUNNING, - 'public_ips': ['65.41.67.2'], - 'private_ips': ['65.41.67.2'], - 'os_type': 'rhel5_64Guest' - }]}) - node = ret[1] - self.assertEqual( - node.id, 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b') - self.assertEqual(node.name, 'testNode2') - self.assertEqual(node.state, NodeState.RUNNING) - self.assertEqual(node.public_ips, ['192.168.0.103']) - self.assertEqual(node.private_ips, ['192.168.0.100']) - self.assertEqual(node.extra, {'vdc': 'MyVdc', - 'vms': [{ - 'id': 'https://vm-vcloud/api/vApp/vm-dd75d1d3-5b7b-48f0-aff3-69622ab7e046', - 'name': 'testVm2', - 'state': NodeState.RUNNING, - 'public_ips': ['192.168.0.103'], - 'private_ips': ['192.168.0.100'], - 'os_type': 'rhel5_64Guest' - }]}) - - def test_reboot_node(self): - node = self.driver.list_nodes()[0] - ret = self.driver.reboot_node(node) - self.assertTrue(ret) - - def test_destroy_node(self): - node = self.driver.list_nodes()[0] - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - - def test_validate_vm_names(self): - # valid inputs - self.driver._validate_vm_names(['host-n-ame-name']) - self.driver._validate_vm_names(['tc-mybuild-b1']) - self.driver._validate_vm_names(None) - # invalid inputs - self.assertRaises( - ValueError, self.driver._validate_vm_names, ['invalid.host']) - self.assertRaises( - ValueError, self.driver._validate_vm_names, ['inv-alid.host']) - self.assertRaises( - ValueError, self.driver._validate_vm_names, ['hostnametoooolong']) - self.assertRaises( - ValueError, self.driver._validate_vm_names, ['host$name']) - - def test_change_vm_names(self): - self.driver._change_vm_names( - '/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', ['changed1', 'changed2']) - - def test_is_node(self): - self.assertTrue(self.driver._is_node( - Node('testId', 'testNode', state=0, public_ips=[], private_ips=[], driver=self.driver))) - self.assertFalse(self.driver._is_node( - NodeImage('testId', 'testNode', driver=self.driver))) - - def test_ex_undeploy(self): - node = self.driver.ex_undeploy_node( - Node('https://test/api/vApp/undeployTest', 'testNode', state=0, - public_ips=[], private_ips=[], driver=self.driver)) - self.assertEqual(node.state, NodeState.STOPPED) - - def test_ex_undeploy_with_error(self): - node = self.driver.ex_undeploy_node( - Node('https://test/api/vApp/undeployErrorTest', 'testNode', - state=0, public_ips=[], private_ips=[], driver=self.driver)) - self.assertEqual(node.state, NodeState.STOPPED) - - def test_ex_find_node(self): - node = self.driver.ex_find_node('testNode') - self.assertEqual(node.name, "testNode") - node = self.driver.ex_find_node('testNode', self.driver.vdcs[0]) - self.assertEqual(node.name, "testNode") - node = self.driver.ex_find_node('testNonExisting', self.driver.vdcs[0]) - self.assertEqual(node, None) - - def test_ex_add_vm_disk__with_invalid_values(self): - self.assertRaises( - ValueError, self.driver.ex_add_vm_disk, 'dummy', 'invalid value') - self.assertRaises( - ValueError, self.driver.ex_add_vm_disk, 'dummy', '-1') - - def test_ex_add_vm_disk(self): - self.driver.ex_add_vm_disk('https://test/api/vApp/vm-test', '20') - - def test_ex_set_vm_cpu__with_invalid_values(self): - self.assertRaises(ValueError, self.driver.ex_set_vm_cpu, 'dummy', 50) - self.assertRaises(ValueError, self.driver.ex_set_vm_cpu, 'dummy', -1) - - def test_ex_set_vm_cpu(self): - self.driver.ex_set_vm_cpu('https://test/api/vApp/vm-test', 4) - - def test_ex_set_vm_memory__with_invalid_values(self): - self.assertRaises( - ValueError, self.driver.ex_set_vm_memory, 'dummy', 777) - self.assertRaises( - ValueError, self.driver.ex_set_vm_memory, 'dummy', -1024) - - def test_ex_set_vm_memory(self): - self.driver.ex_set_vm_memory('https://test/api/vApp/vm-test', 1024) - - def test_vdcs(self): - vdcs = self.driver.vdcs - self.assertEqual(len(vdcs), 1) - self.assertEqual( - vdcs[0].id, 'https://vm-vcloud/api/vdc/3d9ae28c-1de9-4307-8107-9356ff8ba6d0') - self.assertEqual(vdcs[0].name, 'MyVdc') - self.assertEqual(vdcs[0].allocation_model, 'AllocationPool') - self.assertEqual(vdcs[0].storage.limit, 5120000) - self.assertEqual(vdcs[0].storage.used, 1984512) - self.assertEqual(vdcs[0].storage.units, 'MB') - self.assertEqual(vdcs[0].cpu.limit, 160000) - self.assertEqual(vdcs[0].cpu.used, 0) - self.assertEqual(vdcs[0].cpu.units, 'MHz') - self.assertEqual(vdcs[0].memory.limit, 527360) - self.assertEqual(vdcs[0].memory.used, 130752) - self.assertEqual(vdcs[0].memory.units, 'MB') - - def test_ex_list_nodes(self): - self.assertEqual( - len(self.driver.ex_list_nodes()), len(self.driver.list_nodes())) - - def test_ex_list_nodes__masked_exception(self): - """ - Test that we don't mask other exceptions. - """ - brokenVdc = Vdc('/api/vdc/brokenVdc', 'brokenVdc', self.driver) - self.assertRaises(AnotherError, self.driver.ex_list_nodes, (brokenVdc)) - - def test_ex_power_off(self): - node = Node( - 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', - 'testNode', NodeState.RUNNING, [], [], self.driver) - self.driver.ex_power_off_node(node) - - def test_ex_query(self): - results = self.driver.ex_query( - 'user', filter='name==jrambo', page=2, page_size=30, sort_desc='startDate') - self.assertEqual(len(results), 1) - self.assertEqual(results[0]['type'], 'UserRecord') - self.assertEqual(results[0]['name'], 'jrambo') - self.assertEqual(results[0]['isLdapUser'], 'true') - - def test_ex_get_control_access(self): - node = Node( - 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', - 'testNode', NodeState.RUNNING, [], [], self.driver) - control_access = self.driver.ex_get_control_access(node) - self.assertEqual( - control_access.everyone_access_level, ControlAccess.AccessLevel.READ_ONLY) - self.assertEqual(len(control_access.subjects), 1) - self.assertEqual(control_access.subjects[0].type, 'group') - self.assertEqual(control_access.subjects[0].name, 'MyGroup') - self.assertEqual(control_access.subjects[ - 0].id, 'https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413') - self.assertEqual(control_access.subjects[ - 0].access_level, ControlAccess.AccessLevel.FULL_CONTROL) - - def test_ex_set_control_access(self): - node = Node( - 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', - 'testNode', NodeState.RUNNING, [], [], self.driver) - control_access = ControlAccess(node, None, [Subject( - name='MyGroup', - type='group', - access_level=ControlAccess.AccessLevel.FULL_CONTROL)]) - self.driver.ex_set_control_access(node, control_access) - - def test_ex_get_metadata(self): - node = Node( - 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', - 'testNode', NodeState.RUNNING, [], [], self.driver) - metadata = self.driver.ex_get_metadata(node) - self.assertEqual(metadata, {'owners': 'msamia@netsuite.com'}) - - def test_ex_set_metadata_entry(self): - node = Node( - 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', - 'testNode', NodeState.RUNNING, [], [], self.driver) - self.driver.ex_set_metadata_entry(node, 'foo', 'bar') - - -class VCloud_5_1_Tests(unittest.TestCase, TestCaseMixin): - - def setUp(self): - VCloudNodeDriver.connectionCls.host = 'test' - VCloudNodeDriver.connectionCls.conn_classes = ( - None, VCloud_1_5_MockHttp) - VCloud_1_5_MockHttp.type = None - self.driver = VCloudNodeDriver( - *VCLOUD_PARAMS, **{'api_version': '5.1'}) - - self.assertTrue(isinstance(self.driver, VCloud_5_1_NodeDriver)) - - def _test_create_node_valid_ex_vm_memory(self): - # TODO: Hook up the fixture - values = [4, 1024, 4096] - - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - - for value in values: - self.driver.create_node( - name='testerpart2', - image=image, - size=size, - vdc='https://services.vcloudexpress.terremark.com/api/v0.8/vdc/224', - network='https://services.vcloudexpress.terremark.com/api/v0.8/network/725', - cpus=2, - ex_vm_memory=value - ) - - def test_create_node_invalid_ex_vm_memory(self): - values = [1, 3, 7] - - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - - for value in values: - try: - self.driver.create_node( - name='testerpart2', - image=image, - size=size, - vdc='https://services.vcloudexpress.terremark.com/api/v0.8/vdc/224', - network='https://services.vcloudexpress.terremark.com/api/v0.8/network/725', - cpus=2, - ex_vm_memory=value - ) - except ValueError: - pass - else: - self.fail('Exception was not thrown') - - def test_list_images(self): - ret = self.driver.list_images() - self.assertEqual( - 'https://vm-vcloud/api/vAppTemplate/vappTemplate-ac1bc027-bf8c-4050-8643-4971f691c158', ret[0].id) - - -class TerremarkMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('terremark') - - def _api_v0_8_login(self, method, url, body, headers): - headers['set-cookie'] = 'vcloud-token=testtoken' - body = self.fixtures.load('api_v0_8_login.xml') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_v0_8_org_240(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_org_240.xml') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_v0_8_vdc_224(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_vdc_224.xml') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_v0_8_vdc_224_catalog(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_vdc_224_catalog.xml') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_v0_8_catalogItem_5(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_catalogItem_5.xml') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_v0_8_vdc_224_action_instantiateVAppTemplate(self, method, url, body, headers): - body = self.fixtures.load( - 'api_v0_8_vdc_224_action_instantiateVAppTemplate.xml') - return (httplib.OK, body, headers, httplib.responses[httplib.OK]) - - def _api_v0_8_vapp_14031_action_deploy(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_vapp_14031_action_deploy.xml') - return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) - - def _api_v0_8_task_10496(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_task_10496.xml') - return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) - - def _api_v0_8_vapp_14031_power_action_powerOn(self, method, url, body, headers): - body = self.fixtures.load( - 'api_v0_8_vapp_14031_power_action_powerOn.xml') - return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) - - def _api_v0_8_vapp_14031(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('api_v0_8_vapp_14031_get.xml') - elif method == 'DELETE': - body = '' - return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) - - def _api_v0_8_vapp_14031_power_action_reset(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_vapp_14031_power_action_reset.xml') - return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) - - def _api_v0_8_vapp_14031_power_action_poweroff(self, method, url, body, headers): - body = self.fixtures.load( - 'api_v0_8_vapp_14031_power_action_poweroff.xml') - return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) - - def _api_v0_8_task_11001(self, method, url, body, headers): - body = self.fixtures.load('api_v0_8_task_11001.xml') - return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) - - -class AnotherErrorMember(Exception): - - """ - helper class for the synthetic exception - """ - - def __init__(self): - self.tag = 'Error' - - def get(self, foo): - return 'ACCESS_TO_RESOURCE_IS_FORBIDDEN_1' - - -class AnotherError(Exception): - pass - - -class VCloud_1_5_MockHttp(MockHttp, unittest.TestCase): - - fixtures = ComputeFileFixtures('vcloud_1_5') - - def request(self, method, url, body=None, headers=None, raw=False): - self.assertTrue(url.startswith('/api/'), - ('"%s" is invalid. Needs to ' - 'start with "/api". The passed URL should be just ' - 'the path, not full URL.', url)) - super(VCloud_1_5_MockHttp, self).request(method, url, body, headers, - raw) - - def _api_sessions(self, method, url, body, headers): - headers['x-vcloud-authorization'] = 'testtoken' - body = self.fixtures.load('api_sessions.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_org(self, method, url, body, headers): - body = self.fixtures.load('api_org.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a(self, method, url, body, headers): - body = self.fixtures.load( - 'api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4(self, method, url, body, headers): - body = self.fixtures.load( - 'api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0(self, method, url, body, headers): - body = self.fixtures.load( - 'api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vdc_brokenVdc(self, method, url, body, headers): - body = self.fixtures.load('api_vdc_brokenVdc.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vapp_errorRaiser(self, method, url, body, headers): - m = AnotherErrorMember() - raise AnotherError(m) - - def _api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate(self, method, url, body, headers): - body = self.fixtures.load( - 'api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_powerOn(self, method, url, body, headers): - return self._api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(method, url, body, headers) - - # Clone - def _api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp(self, method, url, body, headers): - body = self.fixtures.load( - 'api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - - def _api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_networkConnectionSection(self, method, url, body, headers): - body = self.fixtures.load( - 'api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a(self, method, url, body, headers): - status = httplib.OK - if method == 'GET': - body = self.fixtures.load( - 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a.xml') - status = httplib.OK - elif method == 'DELETE': - body = self.fixtures.load( - 'api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml') - status = httplib.ACCEPTED - return status, body, headers, httplib.responses[status] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b(self, method, url, body, headers): - body = self.fixtures.load( - 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c(self, method, url, body, headers): - body = self.fixtures.load( - 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045(self, method, url, body, headers): - body = self.fixtures.load( - 'put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - - def _api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load( - 'get_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml') - status = httplib.OK - else: - body = self.fixtures.load( - 'put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml') - status = httplib.ACCEPTED - return status, body, headers, httplib.responses[status] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_reset(self, method, url, body, headers): - return self._api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(method, url, body, headers) - - def _api_task_b034df55_fe81_4798_bc81_1f0fd0ead450(self, method, url, body, headers): - body = self.fixtures.load( - 'api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4(self, method, url, body, headers): - body = self.fixtures.load( - 'api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_catalogItem_3132e037_759b_4627_9056_ca66466fa607(self, method, url, body, headers): - body = self.fixtures.load( - 'api_catalogItem_3132e037_759b_4627_9056_ca66466fa607.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_undeployTest(self, method, url, body, headers): - body = self.fixtures.load('api_vApp_undeployTest.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_undeployTest_action_undeploy(self, method, url, body, headers): - body = self.fixtures.load('api_task_undeploy.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - - def _api_task_undeploy(self, method, url, body, headers): - body = self.fixtures.load('api_task_undeploy.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_undeployErrorTest(self, method, url, body, headers): - body = self.fixtures.load('api_vApp_undeployTest.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_undeployErrorTest_action_undeploy(self, method, url, body, headers): - if b('shutdown') in b(body): - body = self.fixtures.load('api_task_undeploy_error.xml') - else: - body = self.fixtures.load('api_task_undeploy.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - - def _api_task_undeployError(self, method, url, body, headers): - body = self.fixtures.load('api_task_undeploy_error.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vapp_access_to_resource_forbidden(self, method, url, body, headers): - raise Exception( - ET.fromstring(self.fixtures.load('api_vApp_vapp_access_to_resource_forbidden.xml'))) - - def _api_vApp_vm_test(self, method, url, body, headers): - body = self.fixtures.load('api_vApp_vm_test.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vm_test_virtualHardwareSection_disks(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load( - 'get_api_vApp_vm_test_virtualHardwareSection_disks.xml') - status = httplib.OK - else: - body = self.fixtures.load( - 'put_api_vApp_vm_test_virtualHardwareSection_disks.xml') - status = httplib.ACCEPTED - return status, body, headers, httplib.responses[status] - - def _api_vApp_vm_test_virtualHardwareSection_cpu(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load( - 'get_api_vApp_vm_test_virtualHardwareSection_cpu.xml') - status = httplib.OK - else: - body = self.fixtures.load( - 'put_api_vApp_vm_test_virtualHardwareSection_cpu.xml') - status = httplib.ACCEPTED - return status, body, headers, httplib.responses[status] - - def _api_vApp_vm_test_virtualHardwareSection_memory(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load( - 'get_api_vApp_vm_test_virtualHardwareSection_memory.xml') - status = httplib.OK - else: - body = self.fixtures.load( - 'put_api_vApp_vm_test_virtualHardwareSection_memory.xml') - status = httplib.ACCEPTED - return status, body, headers, httplib.responses[status] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_powerOff(self, method, url, body, headers): - return self._api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(method, url, body, headers) - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(self, method, url, body, headers): - assert method == 'POST' - body = self.fixtures.load( - 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - - def _api_query(self, method, url, body, headers): - assert method == 'GET' - if 'type=user' in url: - self.assertTrue('page=2' in url) - self.assertTrue('filter=(name==jrambo)' in url) - self.assertTrue('sortDesc=startDate') - body = self.fixtures.load('api_query_user.xml') - elif 'type=group' in url: - body = self.fixtures.load('api_query_group.xml') - else: - raise AssertionError('Unexpected query type') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_metadata(self, method, url, body, headers): - if method == 'POST': - body = self.fixtures.load('api_vapp_post_metadata.xml') - return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] - else: - body = self.fixtures.load('api_vapp_get_metadata.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_controlAccess(self, method, url, body, headers): - body = self.fixtures.load( - 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_action_controlAccess(self, method, url, body, headers): - body = str(body) - self.assertTrue(method == 'POST') - self.assertTrue( - 'false' in body) - self.assertTrue( - '' in body) - self.assertTrue('FullControl' in body) - body = self.fixtures.load( - 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - def _api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413(self, method, url, body, headers): - body = self.fixtures.load( - 'api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml') - return httplib.OK, body, headers, httplib.responses[httplib.OK] - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_voxel.py b/awx/lib/site-packages/libcloud/test/compute/test_voxel.py deleted file mode 100644 index e8ea8b0874..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_voxel.py +++ /dev/null @@ -1,170 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.base import Node, NodeSize, NodeImage, NodeLocation -from libcloud.compute.drivers.voxel import VoxelNodeDriver as Voxel -from libcloud.compute.types import InvalidCredsError - -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import ComputeFileFixtures - -from libcloud.test.secrets import VOXEL_PARAMS - - -class VoxelTest(unittest.TestCase): - - def setUp(self): - - Voxel.connectionCls.conn_classes = (None, VoxelMockHttp) - VoxelMockHttp.type = None - self.driver = Voxel(*VOXEL_PARAMS) - - def test_auth_failed(self): - VoxelMockHttp.type = 'UNAUTHORIZED' - try: - self.driver.list_nodes() - except Exception: - e = sys.exc_info()[1] - self.assertTrue(isinstance(e, InvalidCredsError)) - else: - self.fail('test should have thrown') - - def test_response_failure(self): - VoxelMockHttp.type = 'FAILURE' - - try: - self.driver.list_nodes() - except Exception: - pass - else: - self.fail('Invalid response, but exception was not thrown') - - def test_list_nodes(self): - VoxelMockHttp.type = 'LIST_NODES' - nodes = self.driver.list_nodes() - - self.assertEqual(len(nodes), 1) - self.assertEqual(nodes[0].name, 'www.voxel.net') - - def test_list_sizes(self): - sizes = self.driver.list_sizes() - - self.assertEqual(len(sizes), 13) - - def test_list_images(self): - VoxelMockHttp.type = 'LIST_IMAGES' - images = self.driver.list_images() - - self.assertEqual(len(images), 1) - - def test_list_locations(self): - VoxelMockHttp.type = 'LIST_LOCATIONS' - locations = self.driver.list_locations() - - self.assertEqual(len(locations), 2) - self.assertEqual(locations[0].name, 'Amsterdam') - - def test_create_node_invalid_disk_size(self): - image = NodeImage( - id=1, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', None, None, None, None, driver=self.driver) - location = NodeLocation(id=1, name='Europe', country='England', - driver=self.driver) - - try: - self.driver.create_node(name='foo', image=image, size=size, - location=location) - except ValueError: - pass - else: - self.fail('Invalid disk size provided but an exception was not' - ' thrown') - - def test_create_node(self): - VoxelMockHttp.type = 'CREATE_NODE' - image = NodeImage( - id=1, name='Ubuntu 8.10 (intrepid)', driver=self.driver) - size = NodeSize( - 1, '256 slice', 1024, 500, None, None, driver=self.driver) - location = NodeLocation(id=1, name='Europe', country='England', - driver=self.driver) - - node = self.driver.create_node(name='foo', image=image, size=size, - location=location) - self.assertEqual(node.id, '1234') - - node = self.driver.create_node(name='foo', image=image, size=size, - location=location, voxel_access=True) - self.assertEqual(node.id, '1234') - - def test_reboot_node(self): - VoxelMockHttp.type = 'REBOOT_NODE' - node = Node( - id=72258, name=None, state=None, public_ips=None, private_ips=None, - driver=self.driver) - - self.assertTrue(node.reboot()) - - def test_destroy_node(self): - VoxelMockHttp.type = 'DESTROY_NODE' - node = Node( - id=72258, name=None, state=None, public_ips=None, private_ips=None, - driver=self.driver) - - self.assertTrue(node.destroy()) - - -class VoxelMockHttp(MockHttp): - - fixtures = ComputeFileFixtures('voxel') - - def _UNAUTHORIZED(self, method, url, body, headers): - body = self.fixtures.load('unauthorized.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _FAILURE(self, method, url, body, headers): - body = self.fixtures.load('failure.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _LIST_NODES(self, method, url, body, headers): - body = self.fixtures.load('nodes.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _LIST_IMAGES(self, method, url, body, headers): - body = self.fixtures.load('images.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _LIST_LOCATIONS(self, method, url, body, headers): - body = self.fixtures.load('locations.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _CREATE_NODE(self, method, url, body, headers): - body = self.fixtures.load('create_node.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _REBOOT_NODE(self, method, url, body, headers): - body = self.fixtures.load('success.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _DESTROY_NODE(self, method, url, body, headers): - body = self.fixtures.load('success.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/compute/test_vpsnet.py b/awx/lib/site-packages/libcloud/test/compute/test_vpsnet.py deleted file mode 100644 index 9053a46406..0000000000 --- a/awx/lib/site-packages/libcloud/test/compute/test_vpsnet.py +++ /dev/null @@ -1,212 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest -from libcloud.utils.py3 import httplib - -from libcloud.compute.drivers.vpsnet import VPSNetNodeDriver -from libcloud.compute.base import Node -from libcloud.compute.types import NodeState - -from libcloud.test import MockHttp -from libcloud.test.compute import TestCaseMixin - -from libcloud.test.secrets import VPSNET_PARAMS -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class VPSNetTests(unittest.TestCase, TestCaseMixin): - - def setUp(self): - VPSNetNodeDriver.connectionCls.conn_classes = (None, VPSNetMockHttp) - self.driver = VPSNetNodeDriver(*VPSNET_PARAMS) - - def test_create_node(self): - VPSNetMockHttp.type = 'create' - image = self.driver.list_images()[0] - size = self.driver.list_sizes()[0] - node = self.driver.create_node('foo', image, size) - self.assertEqual(node.name, 'foo') - - def test_list_nodes(self): - VPSNetMockHttp.type = 'virtual_machines' - node = self.driver.list_nodes()[0] - self.assertEqual(node.id, '1384') - self.assertEqual(node.state, NodeState.RUNNING) - - def test_reboot_node(self): - VPSNetMockHttp.type = 'virtual_machines' - node = self.driver.list_nodes()[0] - - VPSNetMockHttp.type = 'reboot' - ret = self.driver.reboot_node(node) - self.assertEqual(ret, True) - - def test_destroy_node(self): - VPSNetMockHttp.type = 'delete' - node = Node('2222', None, None, None, None, self.driver) - ret = self.driver.destroy_node(node) - self.assertTrue(ret) - VPSNetMockHttp.type = 'delete_fail' - node = Node('2223', None, None, None, None, self.driver) - self.assertRaises(Exception, self.driver.destroy_node, node) - - def test_list_images(self): - VPSNetMockHttp.type = 'templates' - ret = self.driver.list_images() - self.assertEqual(ret[0].id, '9') - self.assertEqual(ret[-1].id, '160') - - def test_list_sizes(self): - VPSNetMockHttp.type = 'sizes' - ret = self.driver.list_sizes() - self.assertEqual(len(ret), 1) - self.assertEqual(ret[0].id, '1') - self.assertEqual(ret[0].name, '1 Node') - - def test_destroy_node_response(self): - # should return a node object - node = Node('2222', None, None, None, None, self.driver) - VPSNetMockHttp.type = 'delete' - ret = self.driver.destroy_node(node) - self.assertTrue(isinstance(ret, bool)) - - def test_reboot_node_response(self): - # should return a node object - VPSNetMockHttp.type = 'virtual_machines' - node = self.driver.list_nodes()[0] - VPSNetMockHttp.type = 'reboot' - ret = self.driver.reboot_node(node) - self.assertTrue(isinstance(ret, bool)) - - -class VPSNetMockHttp(MockHttp): - fixtures = ComputeFileFixtures('vpsnet') - - def _nodes_api10json_sizes(self, method, url, body, headers): - body = """[{"slice":{"virtual_machine_id":8592,"id":12256,"consumer_id":0}}, - {"slice":{"virtual_machine_id":null,"id":12258,"consumer_id":0}}, - {"slice":{"virtual_machine_id":null,"id":12434,"consumer_id":0}}]""" - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _nodes_api10json_create(self, method, url, body, headers): - body = """[{"slice":{"virtual_machine_id":8592,"id":12256,"consumer_id":0}}, - {"slice":{"virtual_machine_id":null,"id":12258,"consumer_id":0}}, - {"slice":{"virtual_machine_id":null,"id":12434,"consumer_id":0}}]""" - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _virtual_machines_2222_api10json_delete_fail(self, method, url, body, headers): - return (httplib.FORBIDDEN, '', {}, httplib.responses[httplib.FORBIDDEN]) - - def _virtual_machines_2222_api10json_delete(self, method, url, body, headers): - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _virtual_machines_1384_reboot_api10json_reboot(self, method, url, body, headers): - body = """{ - "virtual_machine": - { - "running": true, - "updated_at": "2009-05-15T06:55:02-04:00", - "power_action_pending": false, - "system_template_id": 41, - "id": 1384, - "cloud_id": 3, - "domain_name": "demodomain.com", - "hostname": "web01", - "consumer_id": 0, - "backups_enabled": false, - "password": "a8hjsjnbs91", - "label": "foo", - "slices_count": null, - "created_at": "2009-04-16T08:17:39-04:00" - } - }""" - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _virtual_machines_api10json_create(self, method, url, body, headers): - body = """{ - "virtual_machine": - { - "running": true, - "updated_at": "2009-05-15T06:55:02-04:00", - "power_action_pending": false, - "system_template_id": 41, - "id": 1384, - "cloud_id": 3, - "domain_name": "demodomain.com", - "hostname": "web01", - "consumer_id": 0, - "backups_enabled": false, - "password": "a8hjsjnbs91", - "label": "foo", - "slices_count": null, - "created_at": "2009-04-16T08:17:39-04:00" - } - }""" - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _virtual_machines_api10json_virtual_machines(self, method, url, body, headers): - body = """ [{ - "virtual_machine": - { - "running": true, - "updated_at": "2009-05-15T06:55:02-04:00", - "power_action_pending": false, - "system_template_id": 41, - "id": 1384, - "cloud_id": 3, - "domain_name": "demodomain.com", - "hostname": "web01", - "consumer_id": 0, - "backups_enabled": false, - "password": "a8hjsjnbs91", - "label": "Web Server 01", - "slices_count": null, - "created_at": "2009-04-16T08:17:39-04:00" - } - }, - { - "virtual_machine": - { - "running": true, - "updated_at": "2009-05-15T06:55:02-04:00", - "power_action_pending": false, - "system_template_id": 41, - "id": 1385, - "cloud_id": 3, - "domain_name": "demodomain.com", - "hostname": "mysql01", - "consumer_id": 0, - "backups_enabled": false, - "password": "dsi8h38hd2s", - "label": "MySQL Server 01", - "slices_count": null, - "created_at": "2009-04-16T08:17:39-04:00" - } - }]""" - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _available_clouds_api10json_templates(self, method, url, body, headers): - body = self.fixtures.load('_available_clouds_api10json_templates.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _available_clouds_api10json_create(self, method, url, body, headers): - body = """ - [{"cloud":{"system_templates":[{"id":9,"label":"Ubuntu 8.04 x64"}],"id":2,"label":"USA VPS Cloud"}}] - """ - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/__init__.py b/awx/lib/site-packages/libcloud/test/dns/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/create_record.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/create_record.xml deleted file mode 100644 index 13b6cbe62c..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/create_record.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - id - 47234 - - - name - www - - - ttl - 0 - - - type - A - - - value - 127.0.0.1 - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/create_zone.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/create_zone.xml deleted file mode 100644 index e8b7a1e58a..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/create_zone.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - date_updated - 20101028T12:38:17 - - - domains - 0 - - - id - 47234 - - - name - t.com - - - owner - AB3917-GANDI - - - public - 0 - - - version - 1 - - - versions - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_record.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_record.xml deleted file mode 100644 index 32aaf65d11..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_record.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - 1 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_record_doesnotexist.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_record_doesnotexist.xml deleted file mode 100644 index aaa5471235..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_record_doesnotexist.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - 0 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_zone.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_zone.xml deleted file mode 100644 index efe775c400..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_zone.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - 1 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_zone_fail.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_zone_fail.xml deleted file mode 100644 index 3601450683..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/delete_zone_fail.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - 0 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/get_zone.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/get_zone.xml deleted file mode 100644 index e8b7a1e58a..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/get_zone.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - date_updated - 20101028T12:38:17 - - - domains - 0 - - - id - 47234 - - - name - t.com - - - owner - AB3917-GANDI - - - public - 0 - - - version - 1 - - - versions - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_records.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_records.xml deleted file mode 100644 index e91c565448..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_records.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - id - 47234 - - - name - wibble - - - ttl - 86400 - - - type - CNAME - - - value - t.com - - - - - - - - id - 47234 - - - name - www - - - ttl - 86400 - - - type - A - - - value - 208.111.35.173 - - - - - - - - id - 47234 - - - name - blahblah - - - ttl - 86400 - - - type - A - - - value - 208.111.35.173 - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_records_empty.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_records_empty.xml deleted file mode 100644 index 528b45c587..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_records_empty.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_zones.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_zones.xml deleted file mode 100644 index 09258a9a35..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/list_zones.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - date_updated - 20101028T12:38:17 - - - id - 47234 - - - name - t.com - - - public - 0 - - - version - 1 - - - - - - - - date_updated - 20101028T12:38:17 - - - id - 48170 - - - name - newbug.net - - - public - 0 - - - version - 1 - - - - - - - - date_updated - 20101028T12:38:17 - - - id - 48017 - - - name - newblah.com - - - public - 0 - - - version - 1 - - - - - - - - date_updated - 20101028T12:38:17 - - - id - 47288 - - - name - fromapi.com - - - public - 0 - - - version - 1 - - - - - - - - date_updated - 20101028T12:38:17 - - - id - 48008 - - - name - blahnew.com - - - public - 0 - - - version - 1 - - - - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/new_version.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/new_version.xml deleted file mode 100644 index 32aaf65d11..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/new_version.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - 1 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml deleted file mode 100644 index c9f245d0cf..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - faultCode - 581042 - - - faultString - Zone does not exist - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json deleted file mode 100644 index a38eb6aac1..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "error": { - "errors": [ - { - "domain": "global", - "reason": "notFound", - "message": "The 'parameters.managedZone' resource named 'example-com' does not exist." - } - ], - "code": 404, - "message": "The 'parameters.managedZone' resource named 'example-com' does not exist." - } -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/managed_zones_1.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/managed_zones_1.json deleted file mode 100644 index 240eb10a2d..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/managed_zones_1.json +++ /dev/null @@ -1 +0,0 @@ -{"kind": "dns#managedZone", "name": "example-com", "nameServers": ["ns-cloud1.googledomains.com.", "ns-cloud2.googledomains.com.", "ns-cloud3.googledomains.com.", "ns-cloud4.googledomains.com."], "creationTime": "2014-03-29T23:06:00.921Z", "dnsName": "example.com.", "id": "1", "description": ""} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/no_record.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/no_record.json deleted file mode 100644 index f23c44394e..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/no_record.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "kind": "dns#resourceRecordSetsListResponse", - "rrsets": [ - ] -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/record.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/record.json deleted file mode 100644 index c1bb80738f..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/record.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "kind": "dns#resourceRecordSetsListResponse", - "rrsets": [ - { - "kind": "dns#resourceRecordSet", - "name": "foo.example.com.", - "type": "A", - "ttl": 21600, - "rrdatas": [ - "ns-cloud-c1.googledomains.com.", - "ns-cloud-c2.googledomains.com.", - "ns-cloud-c3.googledomains.com.", - "ns-cloud-c4.googledomains.com." - ] - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/records_list.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/records_list.json deleted file mode 100644 index 3c3f2b1b38..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/records_list.json +++ /dev/null @@ -1 +0,0 @@ -{"rrsets": [{"rrdatas": ["ns-cloud-d1.googledomains.com.", "ns-cloud-d2.googledomains.com.", "ns-cloud-d3.googledomains.com.", "ns-cloud-d4.googledomains.com."], "kind": "dns#resourceRecordSet", "type": "NS", "name": "example.com.", "ttl": 21600}, {"rrdatas": ["ns-cloud-d1.googledomains.com. dns-admin.google.com. 0 21600 3600 1209600 300"], "kind": "dns#resourceRecordSet", "type": "SOA", "name": "example.com.", "ttl": 21600}, {"rrdatas": ["1.2.3.4"], "kind": "dns#resourceRecordSet", "type": "A", "name": "foo.example.com.", "ttl": 3600}], "kind": "dns#resourceRecordSetsListResponse"} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone.json deleted file mode 100644 index a380c6ee38..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone.json +++ /dev/null @@ -1 +0,0 @@ -{"kind": "dns#managedZone", "name": "example-com", "nameServers": ["ns-cloud-e1.googledomains.com.", "ns-cloud-e2.googledomains.com.", "ns-cloud-e3.googledomains.com.", "ns-cloud-e4.googledomains.com."], "creationTime": "2014-03-29T22:45:47.618Z", "dnsName": "example.com.", "id": "1", "description": ""} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone_create.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone_create.json deleted file mode 100644 index bdaafddc44..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone_create.json +++ /dev/null @@ -1 +0,0 @@ -{"kind": "dns#managedZone", "name": "example-org", "nameServers": ["ns-cloud-b1.googledomains.com.", "ns-cloud-b2.googledomains.com.", "ns-cloud-b3.googledomains.com.", "ns-cloud-b4.googledomains.com."], "creationTime": "2014-03-30T04:44:20.834Z", "dnsName": "example.org.", "id": "3", "description": "new domain for example.org"} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone_list.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone_list.json deleted file mode 100644 index b3f0fd7840..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/google/zone_list.json +++ /dev/null @@ -1 +0,0 @@ -{"kind": "dns#managedZonesListResponse", "managedZones": [{"kind": "dns#managedZone", "name": "example-com", "nameServers": ["ns-cloud-e1.googledomains.com.", "ns-cloud-e2.googledomains.com.", "ns-cloud-e3.googledomains.com.", "ns-cloud-e4.googledomains.com."], "creationTime": "2014-03-29T22:45:47.618Z", "dnsName": "example.com.", "id": "1", "description": ""}, {"kind": "dns#managedZone", "name": "example-net", "nameServers": ["ns-cloud-d1.googledomains.com.", "ns-cloud-d2.googledomains.com.", "ns-cloud-d3.googledomains.com.", "ns-cloud-d4.googledomains.com."], "creationTime": "2014-03-29T22:45:46.990Z", "dnsName": "example.net.", "id": "2", "description": ""}]} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/get_record.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/get_record.json deleted file mode 100644 index 52f5b0adac..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/get_record.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "300377", - "name": "*.t.com", - "type": "CNAME", - "content": "t.com", - "ttl": "86400", - "prio": null -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/get_zone.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/get_zone.json deleted file mode 100644 index 67d562b479..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/get_zone.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "47234", - "name": "t.com", - "type": "NATIVE", - "ttl": "3600", - "soa": { - "primary": "ns1.hostvirtual.com", - "hostmaster": "support@HOSTVIRTUAL.COM", - "serial": "2012100901", - "refresh": "10800", - "retry": "3600", - "expire": "604800", - "default_ttl": "3600" - }, - "ns": [ - "ns4.hostvirtual.com", - "ns3.hostvirtual.com", - "ns2.hostvirtual.com", - "ns1.hostvirtual.com" - ], - "records": [ - { - "id": "300377", - "name": "*.t.com", - "type": "CNAME", - "content": "t.com", - "ttl": "86400", - "prio": null - }, - { - "id": "300719", - "name": "blah.com.", - "type": "A", - "content": "0.0.0.0", - "ttl": null, - "prio": null - }, - { - "id": "300728", - "name": "blahblah.com.t.com", - "type": "A", - "content": "1.1.1.1", - "ttl": null, - "prio": "10" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/list_records.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/list_records.json deleted file mode 100644 index d6ad4ca997..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/list_records.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "id": "300377", - "name": "*.t.com", - "type": "CNAME", - "content": "t.com", - "ttl": "86400", - "prio": null - }, - { - "id": "300719", - "name": "www.t.com", - "type": "A", - "content": "208.111.35.173", - "ttl": null, - "prio": null - }, - { - "id": "300728", - "name": "blahblah.t.com", - "type": "A", - "content": "208.111.35.173", - "ttl": null, - "prio": "10" - } -] diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/list_zones.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/list_zones.json deleted file mode 100644 index c298ed9f5d..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/list_zones.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "id": "47234", - "name": "t.com", - "type": "NATIVE", - "ttl": "3600" - }, - { - "id": "48170", - "name": "newbug.net", - "type": "NATIVE", - "ttl": "3600" - }, - { - "id": "48017", - "name": "newblah.com", - "type": "NATIVE", - "ttl": "3600" - }, - { - "id": "47288", - "name": "fromapi.com", - "type": "NATIVE", - "ttl": "3600" - }, - { - "id": "48008", - "name": "blahnew.com", - "type": "NATIVE", - "ttl": "3600" - } -] diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json deleted file mode 100644 index 21621833c6..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "error": { - "code": 404, - "message": "Not Found: id, validate_dns_zone_owner" - } -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_domain.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_domain.json deleted file mode 100644 index a9eef97a03..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_domain.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ERRORARRAY": [], - "ACTION": "domain.create", - "DATA": { - "DomainID": 5094 - } -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_domain_validation_error.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_domain_validation_error.json deleted file mode 100644 index 3c7059724f..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_domain_validation_error.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ERRORARRAY": [ - { - "ERRORCODE": 8, - "ERRORMESSAGE": "The domain 'linode.com' already exists in our database. Please open a ticket if you think this is in error." - } - ], - "DATA": {}, - "ACTION": "domain.create" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_resource.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_resource.json deleted file mode 100644 index 0fa3738e35..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/create_resource.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": { - "ResourceID": 3585100 - }, - "ACTION": "domain.resource.create" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_domain.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_domain.json deleted file mode 100644 index ff39a38ed7..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_domain.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ERRORARRAY": [], - "ACTION": "domain.delete", - "DATA": { - "DomainID": 5123 - } -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_domain_does_not_exist.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_domain_does_not_exist.json deleted file mode 100644 index 8965baa6ee..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_domain_does_not_exist.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ERRORARRAY": [ - { - "ERRORCODE": 5, - "ERRORMESSAGE": "Object not found" - } - ], - "DATA": {}, - "ACTION": "domain.delete" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_resource.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_resource.json deleted file mode 100644 index 7f7af2adbf..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_resource.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": { - "ResourceID": 3585141 - }, - "ACTION": "domain.resource.delete" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_resource_does_not_exist.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_resource_does_not_exist.json deleted file mode 100644 index b6969aa64c..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/delete_resource_does_not_exist.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ERRORARRAY": [ - { - "ERRORCODE": 5, - "ERRORMESSAGE": "Object not found" - } - ], - "DATA": {}, - "ACTION": "domain.resource.delete" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/domain_list.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/domain_list.json deleted file mode 100644 index ac88b9b5ef..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/domain_list.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "ERRORARRAY": [], - "ACTION": "domain.list", - "DATA": [ - { - "DOMAINID": 5093, - "DESCRIPTION": "", - "EXPIRE_SEC": 0, - "RETRY_SEC": 0, - "STATUS": 1, - "LPM_DISPLAYGROUP": "thing", - "MASTER_IPS": "", - "REFRESH_SEC": 0, - "SOA_EMAIL": "dns@example.com", - "TTL_SEC": 0, - "DOMAIN": "linode.com", - "AXFR_IPS": "none", - "TYPE": "master" - }, - { - "DOMAINID": 5094, - "DESCRIPTION": "", - "EXPIRE_SEC": 0, - "RETRY_SEC": 0, - "STATUS": 1, - "LPM_DISPLAYGROUP": "", - "MASTER_IPS": "2600:3c03::f03c:91ff:feae:e071;66.228.43.47;", - "REFRESH_SEC": 0, - "SOA_EMAIL": "", - "TTL_SEC": 0, - "DOMAIN": "0.c.d.7.0.6.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa", - "AXFR_IPS": "2600:3c03::f03c:91ff:feae:e071;66.228.43.47;", - "TYPE": "slave" - } - ] -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_record.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_record.json deleted file mode 100644 index 4d5b0eb597..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_record.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": [ - { - "DOMAINID": 5093, - "PORT": 80, - "RESOURCEID": 3585100, - "NAME": "www", - "WEIGHT": 5, - "TTL_SEC": 0, - "TARGET": "127.0.0.1", - "PRIORITY": 10, - "PROTOCOL": "", - "TYPE": "a" - } - ], - "ACTION": "domain.resource.list" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_record_does_not_exist.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_record_does_not_exist.json deleted file mode 100644 index c2c1fb499d..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_record_does_not_exist.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ERRORARRAY": [ - { - "ERRORCODE": 5, - "ERRORMESSAGE": "Object not found" - } - ], - "DATA": {}, - "ACTION": "domain.resource.list" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_zone.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_zone.json deleted file mode 100644 index e9387122f6..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_zone.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": [ - { - "DOMAINID": 5093, - "DESCRIPTION": "", - "EXPIRE_SEC": 0, - "RETRY_SEC": 0, - "STATUS": 1, - "LPM_DISPLAYGROUP": "thing", - "MASTER_IPS": "", - "REFRESH_SEC": 0, - "SOA_EMAIL": "dns@example.com", - "TTL_SEC": 0, - "DOMAIN": "linode.com", - "AXFR_IPS": "none", - "TYPE": "master" - } - ], - "ACTION": "domain.list" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_zone_does_not_exist.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_zone_does_not_exist.json deleted file mode 100644 index ea18547f51..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/get_zone_does_not_exist.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ERRORARRAY": [ - { - "ERRORCODE": 5, - "ERRORMESSAGE": "Object not found" - } - ], - "DATA": {}, - "ACTION": "domain.list" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/resource_list.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/resource_list.json deleted file mode 100644 index 2ed18cd821..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/resource_list.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": [ - { - "DOMAINID": 5093, - "PORT": 80, - "RESOURCEID": 3585100, - "NAME": "mc", - "WEIGHT": 5, - "TTL_SEC": 0, - "TARGET": "127.0.0.1", - "PRIORITY": 10, - "PROTOCOL": "", - "TYPE": "a" - }, - { - "DOMAINID": 5093, - "PORT": 25565, - "RESOURCEID": 3585141, - "NAME": "_minecraft._udp", - "WEIGHT": 5, - "TTL_SEC": 0, - "TARGET": "mc.linode.com", - "PRIORITY": 10, - "PROTOCOL": "udp", - "TYPE": "srv" - } - ], - "ACTION": "domain.resource.list" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/resource_list_does_not_exist.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/resource_list_does_not_exist.json deleted file mode 100644 index c2c1fb499d..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/resource_list_does_not_exist.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ERRORARRAY": [ - { - "ERRORCODE": 5, - "ERRORMESSAGE": "Object not found" - } - ], - "DATA": {}, - "ACTION": "domain.resource.list" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/update_domain.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/update_domain.json deleted file mode 100644 index f695f4c103..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/update_domain.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": { - "DomainID": 5093 - }, - "ACTION": "domain.update" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/update_resource.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/update_resource.json deleted file mode 100644 index 7f88aabe6f..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/linode/update_resource.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ERRORARRAY": [], - "DATA": { - "ResourceID": 3585100 - }, - "ACTION": "domain.resource.update" -} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/auth_1_1.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/auth_1_1.json deleted file mode 100644 index fb02cf77f4..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/auth_1_1.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "auth":{ - "token":{ - "id":"fooo-bar-fooo-bar-fooo-bar", - "expires":"2031-10-29T17:39:28.000-05:00" - }, - "serviceCatalog":{ - "cloudFilesCDN":[ - { - "region":"ORD", - "publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS_f66473fb-2e1e-4a44-barr-foooooo", - "v1Default":true - } - ], - "cloudFiles":[ - { - "region":"ORD", - "publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_fbarr-foooo-barr", - "v1Default":true, - "internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_fbarr-foooo-barr" - } - ], - "cloudServers":[ - { - "publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/11111", - "v1Default":true - } - ] - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/auth_2_0.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/auth_2_0.json deleted file mode 100644 index f142179c91..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/auth_2_0.json +++ /dev/null @@ -1,159 +0,0 @@ -{ - "access": { - "token": { - "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", - "expires": "2031-11-23T21:00:14.000-06:00" - }, - "serviceCatalog": [ - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - } - - ], - "name": "cloudFilesCDN", - "type": "rax:object-cdn" - }, - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage4.ord1.clouddrive.com/v1/MossoCloudFS", - "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage4.lon1.clouddrive.com/v1/MossoCloudFS", - "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - } - ], - "name": "cloudFiles", - "type": "object-store" - }, - { - "endpoints": [ - { - "tenantId": "1337", - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", - "version": { - "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", - "versionList": "https://servers.api.rackspacecloud.com/", - "versionId": "1.0" - } - } - ], - "name": "cloudServers", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "RegionOne", - "tenantId": "1337", - "publicURL": "https://127.0.0.1/v2/1337", - "versionInfo": "https://127.0.0.1/v2/", - "versionList": "https://127.0.0.1/", - "versionId": "2" - } - ], - "name": "nova", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "613469", - "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", - "versionList": "https://dfw.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "ORD", - "tenantId": "613469", - "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", - "versionList": "https://ord.servers.api.rackspacecloud.com/", - "versionId": "2" - } - ], - "name": "cloudServersOpenStack", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "1337", - "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/1337" - } - ], - "name": "cloudServersPreprod", - "type": "compute" - }, - { - "name": "cloudDNS", - "endpoints": [ - { - "tenantId": "11111", - "publicURL": "https://dns.api.rackspacecloud.com/v1.0/11111" - } - ], - "type": "rax:dns" - }, - { - "name": "cloudLoadBalancers", - "endpoints": [ - { - "region": "SYD", - "tenantId": "11111", - "publicURL": "https://syd.loadbalancers.api.rackspacecloud.com/v1.0/11111" - }, - { - "region": "DFW", - "tenantId": "11111", - "publicURL": "https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/11111" - }, - { - "region": "ORD", - "tenantId": "11111", - "publicURL": "https://ord.loadbalancers.api.rackspacecloud.com/v1.0/11111" - } - ], - "type": "rax:load-balancer" - } - ], - "user": { - "id": "7", - "roles": [ - { - "id": "identity:default", - "description": "Default Role.", - "name": "identity:default" - } - ], - "name": "testuser" - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_record_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_record_success.json deleted file mode 100644 index 7d09b7e48c..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_record_success.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "request":"{\"records\": [{\"data\": \"127.1.1.1\", \"type\": \"A\", \"name\": \"www.foo4.bar.com\"}]}", - "response":{ - "records":[ - { - "name":"www.foo4.bar.com", - "id":"A-7423317", - "type":"A", - "data":"127.1.1.1", - "updated":"2011-10-29T20:50:41.000+0000", - "ttl":3600, - "created":"2011-10-29T20:50:41.000+0000" - } - ] - }, - "status":"COMPLETED", - "verb":"POST", - "jobId":"586605c8-5739-43fb-8939-f3a2c4c0e99c", - "callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/546514/status/586605c8-5739-43fb-8939-f3a2c4c0e99c", - "requestUrl":"http://dns.api.rackspacecloud.com/v1.0/546514/domains/2946173/records" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_zone_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_zone_success.json deleted file mode 100644 index b53a7af72f..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_zone_success.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "request":"{\"domains\": [{\"recordsList\": {\"records\": []}, \"emailAddress\": \"test@test.com\", \"name\": \"bar.foo1.com\"}]}", - "response":{ - "domains":[ - { - "name":"bar.foo1.com", - "id":2946173, - "accountId":11111, - "updated":"2011-10-29T20:28:59.000+0000", - "ttl":3600, - "emailAddress":"test@test.com", - "nameservers":[ - { - "name":"ns.rackspace.com" - }, - { - "name":"ns2.rackspace.com" - } - ], - "created":"2011-10-29T20:28:59.000+0000" - } - ] - }, - "status":"COMPLETED", - "verb":"POST", - "jobId":"288795f9-e74d-48be-880b-a9e36e0de61e", - "callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/11111/status/288795f9-e74d-48be-880b-a9e36e0de61e", - "requestUrl":"http://dns.api.rackspacecloud.com/v1.0/11111/domains" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_zone_validation_error.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_zone_validation_error.json deleted file mode 100644 index f604873ba0..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/create_zone_validation_error.json +++ /dev/null @@ -1 +0,0 @@ -{"validationErrors":{"messages":["Domain TTL is required and must be greater than or equal to 300"]},"code":400} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/delete_record_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/delete_record_success.json deleted file mode 100644 index 04b15833ba..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/delete_record_success.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "status":"COMPLETED", - "verb":"DELETE", - "jobId":"0b40cd14-2e5d-490f-bb6e-fdc65d1118a9", - "callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/11111/status/0b40cd14-2e5d-490f-bb6e-fdc65d1118a9", - "requestUrl":"http://dns.api.rackspacecloud.com/v1.0/11111/domains/2946181/records/2346" -} - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/delete_zone_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/delete_zone_success.json deleted file mode 100644 index 4ea7528e0a..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/delete_zone_success.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "status":"COMPLETED", - "verb":"DELETE", - "jobId":"0b40cd14-2e5d-490f-bb6e-fdc65d1118a9", - "callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/11111/status/0b40cd14-2e5d-490f-bb6e-fdc65d1118a9", - "requestUrl":"http://dns.api.rackspacecloud.com/v1.0/11111/domains/2946181" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/does_not_exist.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/does_not_exist.json deleted file mode 100644 index e9ec9e21c2..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/does_not_exist.json +++ /dev/null @@ -1 +0,0 @@ -{"message":"Object not Found.","code":404,"details":""} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/get_record_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/get_record_success.json deleted file mode 100644 index d2d2df7d66..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/get_record_success.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name":"test3.foo4.bar.com", - "id":"A-7423034", - "type":"A", - "comment":"lulz", - "data":"127.7.7.7", - "updated":"2011-10-29T18:42:28.000+0000", - "ttl":777, - "created":"2011-10-29T15:29:29.000+0000" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/get_zone_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/get_zone_success.json deleted file mode 100644 index 5f0a6ce8cd..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/get_zone_success.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name":"foo4.bar.com", - "id":2946063, - "comment":"wazaaa", - "accountId":11111, - "updated":"2011-10-29T18:42:28.000+0000", - "ttl":855, - "recordsList":{ - "records":[ - { - "name":"test3.foo4.bar.com", - "id":"A-7423034", - "type":"A", - "comment":"lulz", - "data":"127.7.7.7", - "updated":"2011-10-29T18:42:28.000+0000", - "ttl":777, - "created":"2011-10-29T15:29:29.000+0000" - }, - { - "name":"foo4.bar.com", - "id":"NS-6717885", - "type":"NS", - "data":"dns1.stabletransit.com", - "updated":"2011-10-29T14:47:09.000+0000", - "ttl":3600, - "created":"2011-10-29T14:47:09.000+0000" - }, - { - "name":"foo4.bar.com", - "id":"NS-6717886", - "type":"NS", - "data":"dns2.stabletransit.com", - "updated":"2011-10-29T14:47:09.000+0000", - "ttl":3600, - "created":"2011-10-29T14:47:09.000+0000" - } - ], - "totalEntries":3 - }, - "emailAddress":"test@test.com", - "nameservers":[ - { - "name":"ns.rackspace.com" - }, - { - "name":"ns2.rackspace.com" - } - ], - "created":"2011-10-29T14:47:09.000+0000" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_records_no_results.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_records_no_results.json deleted file mode 100644 index dc64965aab..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_records_no_results.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name":"foo4.bar.com", - "id":2946063, - "comment":"wazaaa", - "accountId":11111, - "updated":"2011-10-29T18:42:28.000+0000", - "ttl":855, - "recordsList":{ - "records":[], - "totalEntries":0 - }, - "emailAddress":"kami@kami.si", - "nameservers":[ - { - "name":"ns.rackspace.com" - }, - { - "name":"ns2.rackspace.com" - } - ], - "created":"2011-10-29T14:47:09.000+0000" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_records_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_records_success.json deleted file mode 100644 index 5f0a6ce8cd..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_records_success.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name":"foo4.bar.com", - "id":2946063, - "comment":"wazaaa", - "accountId":11111, - "updated":"2011-10-29T18:42:28.000+0000", - "ttl":855, - "recordsList":{ - "records":[ - { - "name":"test3.foo4.bar.com", - "id":"A-7423034", - "type":"A", - "comment":"lulz", - "data":"127.7.7.7", - "updated":"2011-10-29T18:42:28.000+0000", - "ttl":777, - "created":"2011-10-29T15:29:29.000+0000" - }, - { - "name":"foo4.bar.com", - "id":"NS-6717885", - "type":"NS", - "data":"dns1.stabletransit.com", - "updated":"2011-10-29T14:47:09.000+0000", - "ttl":3600, - "created":"2011-10-29T14:47:09.000+0000" - }, - { - "name":"foo4.bar.com", - "id":"NS-6717886", - "type":"NS", - "data":"dns2.stabletransit.com", - "updated":"2011-10-29T14:47:09.000+0000", - "ttl":3600, - "created":"2011-10-29T14:47:09.000+0000" - } - ], - "totalEntries":3 - }, - "emailAddress":"test@test.com", - "nameservers":[ - { - "name":"ns.rackspace.com" - }, - { - "name":"ns2.rackspace.com" - } - ], - "created":"2011-10-29T14:47:09.000+0000" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_zones_no_results.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_zones_no_results.json deleted file mode 100644 index 86e3bc37e8..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_zones_no_results.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "domains":[], - "totalEntries":0 -} - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_zones_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_zones_success.json deleted file mode 100644 index b1f54c0ca6..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/list_zones_success.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "domains":[ - { - "name":"foo4.bar.com", - "id":2946063, - "comment":"wazaaa", - "accountId":11111, - "updated":"2011-10-29T18:42:28.000+0000", - "created":"2011-10-29T14:47:09.000+0000" - }, - { - "name":"foo5.bar.com", - "id":2946065, - "comment":"fuu", - "accountId":11111, - "updated":"2011-10-29T14:48:39.000+0000", - "created":"2011-10-29T14:48:39.000+0000" - }, - { - "name":"foo6.bar.com", - "id":2946066, - "comment":"fuu", - "accountId":11111, - "updated":"2011-10-29T14:48:59.000+0000", - "created":"2011-10-29T14:48:58.000+0000" - }, - { - "name":"foo7.bar.com", - "id":2946068, - "comment":"fuu", - "accountId":11111, - "updated":"2011-10-29T14:49:14.000+0000", - "created":"2011-10-29T14:49:13.000+0000" - }, - { - "name":"foo8.bar.com", - "id":2946069, - "comment":"fuu", - "accountId":11111, - "updated":"2011-10-29T14:49:44.000+0000", - "created":"2011-10-29T14:49:43.000+0000" - }, - { - "name":"foo9.bar.com", - "id":2946071, - "comment":"fuu", - "accountId":11111, - "updated":"2011-10-29T14:54:45.000+0000", - "created":"2011-10-29T14:54:45.000+0000" - } - ], - "totalEntries":6 -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/unauthorized.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/unauthorized.json deleted file mode 100644 index 2a6fac24c0..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/unauthorized.json +++ /dev/null @@ -1 +0,0 @@ -{"unauthorized":{"message":"Username or api key is invalid","code":401}} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/update_record_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/update_record_success.json deleted file mode 100644 index fc6b975c2c..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/update_record_success.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "request":"{\"comment\": \"lulz\", \"data\": \"127.3.3.3\", \"name\": \"www.bar.foo1.com\", \"ttl\": 777}", - "status":"COMPLETED", - "verb":"PUT", - "jobId":"251c0d0c-95bc-4e09-b99f-4b8748b66246", - "callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/546514/status/251c0d0c-95bc-4e09-b99f-4b8748b66246", - "requestUrl":"http://dns.api.rackspacecloud.com/v1.0/546514/domains/2946173/records/A-7423317" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/update_zone_success.json b/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/update_zone_success.json deleted file mode 100644 index 1c9d8e08d8..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/rackspace/update_zone_success.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "request":"{}", - "status":"COMPLETED", - "verb":"PUT", - "jobId":"116a8f17-38ac-4862-827c-506cd04800d5", - "callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/11111/status/116a8f17-38ac-4862-827c-506cd04800d5", - "requestUrl":"http://dns.api.rackspacecloud.com/v1.0/11111/domains/2946173" -} diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/create_zone.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/create_zone.xml deleted file mode 100644 index 7a7117f71b..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/create_zone.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - /hostedzone/47234 - t.com - some unique reference - - some comment - - 0 - - - - ns1.example.com - ns2.example.com - ns3.example.com - ns4.example.com - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/get_zone.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/get_zone.xml deleted file mode 100644 index 3a1ffbef01..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/get_zone.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - /hostedzone/47234 - t.com - some unique reference - - some comment - - 0 - - - - ns1.example.com - ns2.example.com - ns3.example.com - ns4.example.com - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/invalid_change_batch.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/invalid_change_batch.xml deleted file mode 100644 index 36d7ea1dea..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/invalid_change_batch.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Sender - InvalidChangeBatch - Invalid change - - 376c64a6-6194-11e1-847f-ddaa49e4c811 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/list_records.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/list_records.xml deleted file mode 100644 index b9638fa21e..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/list_records.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - wibble.t.com - CNAME - 86400 - - - t.com - - - - - - www.t.com - A - 86400 - - - 208.111.35.173 - - - - - - blahblah.t.com - A - 86400 - - - 208.111.35.173 - - - - - - testdomain.com - MX - 3600 - - - 1 ASPMX.L.GOOGLE.COM. - - - 5 ALT1.ASPMX.L.GOOGLE.COM. - - - 5 ALT2.ASPMX.L.GOOGLE.COM. - - - 10 ASPMX2.GOOGLEMAIL.COM. - - - 10 ASPMX3.GOOGLEMAIL.COM. - - - - - - foo.test.com. - SRV - 300 - - - 1 10 5269 xmpp-server.example.com. - - - 2 12 5060 sip-server.example.com. - - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/list_zones.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/list_zones.xml deleted file mode 100644 index e0da2cfe5c..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/list_zones.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - /hostedzone/47234 - t.com - unique description - - some comment - - 0 - - - - /hostedzone/48170 - newbug.net - unique description - - some comment - - 0 - - - - /hostedzone/48017 - newblah.com - unique description - - some comment - - 0 - - - - /hostedzone/47288 - fromapi.com - unique description - - some comment - - 0 - - - - /hostedzone/48008 - blahnew.com - unique description - - some comment - - 0 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml deleted file mode 100644 index 6a767d149a..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - definitely.not.what.you.askedfor.t.com - CNAME - 86400 - - - t.com - - - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/zone_does_not_exist.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/zone_does_not_exist.xml deleted file mode 100644 index 6fba7392d3..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/route53/zone_does_not_exist.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Sender - NoSuchHostedZone - No hosted zone found with ID: 47234 - - 376c64a6-6194-11e1-847f-ddaa49e4c811 - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_record.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_record.xml deleted file mode 100644 index 2a44e00e22..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_record.xml +++ /dev/null @@ -1,13 +0,0 @@ - - 2008-12-07T02:51:13Z - 127.0.0.1 - www.example.com - A - www - 23456780 - - - - 2008-12-07T02:51:13Z - 12345678 - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_zone.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_zone.xml deleted file mode 100644 index a48156c667..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_zone.xml +++ /dev/null @@ -1,18 +0,0 @@ - - 2008-12-07T02:40:02Z - ns1.example.com,ns2.example.com - true - 600 - foo.bar.com - dnsadmin@example.com - 12345679 - - - pri_sec - - - - 2008-12-07T02:40:02Z - 0 - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_zone_validation_error.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_zone_validation_error.xml deleted file mode 100644 index 664b9719ed..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/create_zone_validation_error.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Ns type is not included in the list - Default ttl must be greater than or equal to 60 - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/get_record.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/get_record.xml deleted file mode 100644 index 31619a8935..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/get_record.xml +++ /dev/null @@ -1,13 +0,0 @@ - - 2008-12-07T02:51:13Z - 172.16.16.1 - example.com - A - www - 23456789 - - - - 2008-12-07T02:51:13Z - 12345678 - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/get_zone.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/get_zone.xml deleted file mode 100644 index f94522c457..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/get_zone.xml +++ /dev/null @@ -1,32 +0,0 @@ - - 2008-12-07T02:40:02Z - ns1.example.com,ns2.example.com - true - 600 - example.com - dnsadmin@example.com - 12345678 - - - pri_sec - - - one two - 2008-12-07T02:40:02Z - 1 - - - 2008-12-07T02:51:13Z - 172.16.16.1 - example.com - A - - 23456789 - - - - 2008-12-07T02:51:13Z - 12345678 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_records.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_records.xml deleted file mode 100644 index f226162c79..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_records.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 2008-12-07T02:51:13Z - 172.16.16.1 - www.example.com - A - www - 23456789 - - - - 2008-12-07T02:51:13Z - 12345678 - - - 2008-12-07T02:51:13Z - 172.16.16.2 - test.example.com - A - test - 23456789 - - - 3600 - 2008-12-07T02:51:13Z - 12345678 - - - 2008-12-07T02:51:13Z - 172.16.16.3 - test2.example.com - A - - 23456789 - - - 3600 - 2008-12-07T02:51:13Z - 12345678 - - - 2008-12-07T02:51:13Z - 172.16.16.4 - test4.example.com - A - 23456789 - - - 3600 - 2008-12-07T02:51:13Z - 12345678 - - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_records_no_results.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_records_no_results.xml deleted file mode 100644 index 7020c67a6e..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_records_no_results.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_zones.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_zones.xml deleted file mode 100644 index 3870926e05..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_zones.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 2008-12-07T02:40:02Z - - false - 600 - example.com - - 12345678 - test foo bar - - pri_sec - - - 2008-12-07T02:40:02Z - - diff --git a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_zones_no_results.xml b/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_zones_no_results.xml deleted file mode 100644 index 0572fec45c..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/fixtures/zerigo/list_zones_no_results.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/awx/lib/site-packages/libcloud/test/dns/test_base.py b/awx/lib/site-packages/libcloud/test/dns/test_base.py deleted file mode 100644 index 499aa71851..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_base.py +++ /dev/null @@ -1,108 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and - -from __future__ import with_statement - -import sys -import tempfile - -from mock import Mock - -from libcloud.test import unittest -from libcloud.dns.base import DNSDriver, Zone, Record -from libcloud.dns.types import RecordType - - -MOCK_RECORDS_VALUES = [ - {'id': 1, 'name': 'www', 'type': RecordType.A, 'data': '127.0.0.1'}, - {'id': 2, 'name': 'www', 'type': RecordType.AAAA, - 'data': '2a01:4f8:121:3121::2'}, - - # Custom TTL - {'id': 3, 'name': 'www', 'type': RecordType.A, 'data': '127.0.0.1', - 'extra': {'ttl': 123}}, - - # Record without a name - {'id': 4, 'name': '', 'type': RecordType.A, - 'data': '127.0.0.1'}, - - {'id': 5, 'name': 'test1', 'type': RecordType.TXT, - 'data': 'test foo bar'}, - - # TXT record with quotes - {'id': 5, 'name': 'test2', 'type': RecordType.TXT, - 'data': 'test "foo" "bar"'}, - - # Records with priority - {'id': 5, 'name': '', 'type': RecordType.MX, - 'data': 'mx.example.com', 'extra': {'priority': 10}}, - {'id': 5, 'name': '', 'type': RecordType.SRV, - 'data': '10 3333 example.com', 'extra': {'priority': 20}}, -] - - -class BaseTestCase(unittest.TestCase): - def setUp(self): - self.driver = DNSDriver('none', 'none') - self.tmp_file = tempfile.mkstemp() - self.tmp_path = self.tmp_file[1] - - def test_export_zone_to_bind_format_slave_should_throw(self): - zone = Zone(id=1, domain='example.com', type='slave', ttl=900, - driver=self.driver) - self.assertRaises(ValueError, zone.export_to_bind_format) - - def test_export_zone_to_bind_format_success(self): - zone = Zone(id=1, domain='example.com', type='master', ttl=900, - driver=self.driver) - - mock_records = [] - - for values in MOCK_RECORDS_VALUES: - values = values.copy() - values['driver'] = self.driver - values['zone'] = zone - record = Record(**values) - mock_records.append(record) - - self.driver.list_records = Mock() - self.driver.list_records.return_value = mock_records - - result = self.driver.export_zone_to_bind_format(zone=zone) - self.driver.export_zone_to_bind_zone_file(zone=zone, - file_path=self.tmp_path) - - with open(self.tmp_path, 'r') as fp: - content = fp.read() - - lines1 = result.split('\n') - lines2 = content.split('\n') - - for lines in [lines1, lines2]: - self.assertEqual(len(lines), 2 + 1 + 9) - self.assertRegexpMatches(lines[1], r'\$ORIGIN example\.com\.') - self.assertRegexpMatches(lines[2], r'\$TTL 900') - - self.assertRegexpMatches(lines[4], r'www.example.com\.\s+900\s+IN\s+A\s+127\.0\.0\.1') - self.assertRegexpMatches(lines[5], r'www.example.com\.\s+900\s+IN\s+AAAA\s+2a01:4f8:121:3121::2') - self.assertRegexpMatches(lines[6], r'www.example.com\.\s+123\s+IN\s+A\s+127\.0\.0\.1') - self.assertRegexpMatches(lines[7], r'example.com\.\s+900\s+IN\s+A\s+127\.0\.0\.1') - self.assertRegexpMatches(lines[8], r'test1.example.com\.\s+900\s+IN\s+TXT\s+"test foo bar"') - self.assertRegexpMatches(lines[9], r'test2.example.com\.\s+900\s+IN\s+TXT\s+"test \\"foo\\" \\"bar\\""') - self.assertRegexpMatches(lines[10], r'example.com\.\s+900\s+IN\s+MX\s+10\s+mx.example.com') - self.assertRegexpMatches(lines[11], r'example.com\.\s+900\s+IN\s+SRV\s+20\s+10 3333 example.com') - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/test_gandi.py b/awx/lib/site-packages/libcloud/test/dns/test_gandi.py deleted file mode 100644 index 04060778b2..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_gandi.py +++ /dev/null @@ -1,296 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.dns.types import RecordType, ZoneDoesNotExistError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.drivers.gandi import GandiDNSDriver -from libcloud.test.file_fixtures import DNSFileFixtures -from libcloud.test.secrets import DNS_GANDI -from libcloud.test.common.test_gandi import BaseGandiMockHttp - - -class GandiTests(unittest.TestCase): - - def setUp(self): - GandiDNSDriver.connectionCls.conn_classes = ( - GandiMockHttp, GandiMockHttp) - GandiMockHttp.type = None - self.driver = GandiDNSDriver(*DNS_GANDI) - - def test_list_record_types(self): - record_types = self.driver.list_record_types() - self.assertEqual(len(record_types), 10) - self.assertTrue(RecordType.A in record_types) - - def test_list_zones(self): - zones = self.driver.list_zones() - self.assertEqual(len(zones), 5) - - zone = zones[0] - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 't.com') - - def test_list_records(self): - zone = self.driver.list_zones()[0] - records = self.driver.list_records(zone=zone) - self.assertEqual(len(records), 3) - - record = records[1] - self.assertEqual(record.name, 'www') - self.assertEqual(record.id, 'A:www') - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '208.111.35.173') - - def test_get_zone(self): - zone = self.driver.get_zone(zone_id='47234') - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 't.com') - - def test_get_record(self): - record = self.driver.get_record(zone_id='47234', - record_id='CNAME:t.com') - self.assertEqual(record.name, 'wibble') - self.assertEqual(record.type, RecordType.CNAME) - self.assertEqual(record.data, 't.com') - - def test_list_records_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - GandiMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.list_records(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_get_zone_does_not_exist(self): - GandiMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_zone(zone_id='47234') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, '47234') - else: - self.fail('Exception was not thrown') - - def test_get_record_zone_does_not_exist(self): - GandiMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='4444', record_id='CNAME:t.com') - except ZoneDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_record_record_does_not_exist(self): - GandiMockHttp.type = 'RECORD_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='47234', - record_id='CNAME:t.com') - except RecordDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_zone(self): - zone = self.driver.create_zone(domain='t.com', type='master', - ttl=None, extra=None) - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.domain, 't.com') - - def test_update_zone(self): - zone = self.driver.get_zone(zone_id='47234') - zone = self.driver.update_zone(zone, domain='t.com') - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 't.com') - - def test_create_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.create_record( - name='www', zone=zone, - type=RecordType.A, data='127.0.0.1', - extra={'ttl': 30} - ) - - self.assertEqual(record.id, 'A:www') - self.assertEqual(record.name, 'www') - self.assertEqual(record.zone, zone) - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '127.0.0.1') - - def test_update_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[1] - - params = { - 'record': record, - 'name': 'www', - 'type': RecordType.A, - 'data': '127.0.0.1', - 'extra': {'ttl': 30}} - updated_record = self.driver.update_record(**params) - - self.assertEqual(record.data, '208.111.35.173') - - self.assertEqual(updated_record.id, 'A:www') - self.assertEqual(updated_record.name, 'www') - self.assertEqual(updated_record.zone, record.zone) - self.assertEqual(updated_record.type, RecordType.A) - self.assertEqual(updated_record.data, '127.0.0.1') - - def test_delete_zone(self): - zone = self.driver.list_zones()[0] - status = self.driver.delete_zone(zone=zone) - self.assertTrue(status) - - def test_delete_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - GandiMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.delete_zone(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_delete_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - status = self.driver.delete_record(record=record) - self.assertTrue(status) - - def test_delete_record_does_not_exist(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - GandiMockHttp.type = 'RECORD_DOES_NOT_EXIST' - try: - self.driver.delete_record(record=record) - except RecordDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.record_id, record.id) - else: - self.fail('Exception was not thrown') - - -class GandiMockHttp(BaseGandiMockHttp): - fixtures = DNSFileFixtures('gandi') - - def _xmlrpc__domain_zone_create(self, method, url, body, headers): - body = self.fixtures.load('create_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_update(self, method, url, body, headers): - body = self.fixtures.load('get_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_list(self, method, url, body, headers): - body = self.fixtures.load('list_zones.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_record_list(self, method, url, body, headers): - body = self.fixtures.load('list_records.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_record_add(self, method, url, body, headers): - body = self.fixtures.load('create_record.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_delete(self, method, url, body, headers): - body = self.fixtures.load('delete_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_info(self, method, url, body, headers): - body = self.fixtures.load('get_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_record_delete(self, method, url, body, headers): - body = self.fixtures.load('delete_record.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_record_update(self, method, url, body, headers): - body = self.fixtures.load('create_record.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_version_new(self, method, url, body, headers): - body = self.fixtures.load('new_version.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_version_set(self, method, url, body, headers): - body = self.fixtures.load('new_version.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_record_list_ZONE_DOES_NOT_EXIST(self, method, url, - body, headers): - body = self.fixtures.load('zone_doesnt_exist.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_info_ZONE_DOES_NOT_EXIST(self, method, url, body, - headers): - body = self.fixtures.load('zone_doesnt_exist.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_list_ZONE_DOES_NOT_EXIST(self, method, url, body, - headers): - body = self.fixtures.load('zone_doesnt_exist.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_delete_ZONE_DOES_NOT_EXIST(self, method, url, - body, headers): - body = self.fixtures.load('zone_doesnt_exist.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_record_list_RECORD_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('list_records_empty.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_info_RECORD_DOES_NOT_EXIST(self, method, url, - body, headers): - body = self.fixtures.load('list_zones.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_record_delete_RECORD_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('delete_record_doesnotexist.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_version_new_RECORD_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('new_version.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _xmlrpc__domain_zone_version_set_RECORD_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('new_version.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/test_google.py b/awx/lib/site-packages/libcloud/test/dns/test_google.py deleted file mode 100644 index a0743005e0..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_google.py +++ /dev/null @@ -1,182 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and - -import sys -import unittest - -from libcloud.utils.py3 import httplib - -from libcloud.dns.types import ZoneDoesNotExistError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.drivers.google import GoogleDNSDriver -from libcloud.common.google import (GoogleBaseAuthConnection, - GoogleInstalledAppAuthConnection, - GoogleBaseConnection) - -from libcloud.test.common.test_google import GoogleAuthMockHttp -from libcloud.test import MockHttpTestCase, LibcloudTestCase -from libcloud.test.file_fixtures import DNSFileFixtures -from libcloud.test.secrets import DNS_PARAMS_GOOGLE, DNS_KEYWORD_PARAMS_GOOGLE - - -class GoogleTests(LibcloudTestCase): - GoogleBaseConnection._get_token_info_from_file = lambda x: None - GoogleBaseConnection._write_token_info_to_file = lambda x: None - GoogleInstalledAppAuthConnection.get_code = lambda x: '1234' - - def setUp(self): - GoogleDNSMockHttp.test = self - GoogleDNSDriver.connectionCls.conn_classes = (GoogleDNSMockHttp, - GoogleDNSMockHttp) - GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp, - GoogleAuthMockHttp) - GoogleDNSMockHttp.type = None - kwargs = DNS_KEYWORD_PARAMS_GOOGLE.copy() - kwargs['auth_type'] = 'IA' - self.driver = GoogleDNSDriver(*DNS_PARAMS_GOOGLE, **kwargs) - - def test_default_scopes(self): - self.assertEqual(self.driver.scopes, None) - - def test_list_zones(self): - zones = self.driver.list_zones() - self.assertEqual(len(zones), 2) - - def test_list_records(self): - zone = self.driver.list_zones()[0] - records = self.driver.list_records(zone=zone) - self.assertEqual(len(records), 3) - - def test_get_zone(self): - zone = self.driver.get_zone('example-com') - self.assertEqual(zone.id, 'example-com') - self.assertEqual(zone.domain, 'example.com.') - - def test_get_zone_does_not_exist(self): - GoogleDNSMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_zone('example-com') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, 'example-com') - else: - self.fail('Exception not thrown') - - def test_get_record(self): - GoogleDNSMockHttp.type = 'FILTER_ZONES' - zone = self.driver.list_zones()[0] - record = self.driver.get_record(zone.id, "A:foo.example.com.") - self.assertEqual(record.id, 'A:foo.example.com.') - self.assertEqual(record.name, 'foo.example.com.') - self.assertEqual(record.type, 'A') - self.assertEqual(record.zone.id, 'example-com') - - def test_get_record_zone_does_not_exist(self): - GoogleDNSMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_record('example-com', 'a:a') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, 'example-com') - else: - self.fail('Exception not thrown') - - def test_get_record_record_does_not_exist(self): - GoogleDNSMockHttp.type = 'RECORD_DOES_NOT_EXIST' - try: - self.driver.get_record('example-com', "A:foo") - except RecordDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.record_id, 'A:foo') - else: - self.fail('Exception not thrown') - - def test_create_zone(self): - extra = {'description': 'new domain for example.org'} - zone = self.driver.create_zone('example.org.', extra) - self.assertEqual(zone.domain, 'example.org.') - self.assertEqual(zone.extra['description'], extra['description']) - self.assertEqual(len(zone.extra['nameServers']), 4) - - def test_delete_zone(self): - zone = self.driver.get_zone('example-com') - res = self.driver.delete_zone(zone) - self.assertTrue(res) - - -class GoogleDNSMockHttp(MockHttpTestCase): - fixtures = DNSFileFixtures('google') - - def _dns_v1beta1_projects_project_name_managedZones(self, method, url, - body, headers): - if method == 'POST': - body = self.fixtures.load('zone_create.json') - else: - body = self.fixtures.load('zone_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_v1beta1_projects_project_name_managedZones_FILTER_ZONES( - self, method, url, body, headers): - body = self.fixtures.load('zone_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com_rrsets_FILTER_ZONES( - self, method, url, body, headers): - body = self.fixtures.load('record.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com_rrsets( - self, method, url, body, headers): - body = self.fixtures.load('records_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com( - self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('managed_zones_1.json') - elif method == 'DELETE': - body = None - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com_ZONE_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('get_zone_does_not_exists.json') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com_RECORD_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('managed_zones_1.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com_rrsets_RECORD_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('no_record.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com_rrsets_ZONE_DOES_NOT_EXIST( - self, method, url, body, headers): - body = self.fixtures.load('get_zone_does_not_exists.json') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - def _dns_v1beta1_projects_project_name_managedZones_example_com_FILTER_ZONES( - self, method, url, body, headers): - body = self.fixtures.load('zone.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/test_hostvirtual.py b/awx/lib/site-packages/libcloud/test/dns/test_hostvirtual.py deleted file mode 100644 index f74571b92a..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_hostvirtual.py +++ /dev/null @@ -1,258 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.utils.py3 import httplib - -from libcloud.dns.types import RecordType, ZoneDoesNotExistError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.drivers.hostvirtual import HostVirtualDNSDriver -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import DNSFileFixtures -from libcloud.test.secrets import DNS_PARAMS_HOSTVIRTUAL - - -class HostVirtualTests(unittest.TestCase): - def setUp(self): - HostVirtualDNSDriver.connectionCls.conn_classes = ( - None, HostVirtualMockHttp) - HostVirtualMockHttp.type = None - self.driver = HostVirtualDNSDriver(*DNS_PARAMS_HOSTVIRTUAL) - - def test_list_record_types(self): - record_types = self.driver.list_record_types() - self.assertEqual(len(record_types), 7) - self.assertTrue(RecordType.A in record_types) - - def test_list_zones(self): - zones = self.driver.list_zones() - self.assertEqual(len(zones), 5) - - zone = zones[0] - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 't.com') - self.assertEqual(zone.ttl, '3600') - - def test_list_records(self): - zone = self.driver.list_zones()[0] - records = self.driver.list_records(zone=zone) - self.assertEqual(len(records), 3) - - record = records[1] - self.assertEqual(record.name, 'www.t.com') - self.assertEqual(record.id, '300719') - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '208.111.35.173') - - def test_get_zone(self): - zone = self.driver.get_zone(zone_id='47234') - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 't.com') - self.assertEqual(zone.ttl, '3600') - - def test_get_record(self): - record = self.driver.get_record(zone_id='47234', record_id='300377') - self.assertEqual(record.id, '300377') - self.assertEqual(record.name, '*.t.com') - self.assertEqual(record.type, RecordType.CNAME) - self.assertEqual(record.data, 't.com') - - def test_list_records_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.list_records(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_get_zone_does_not_exist(self): - HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_zone(zone_id='4444') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, '4444') - else: - self.fail('Exception was not thrown') - - def test_get_record_zone_does_not_exist(self): - HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='4444', record_id='28536') - except ZoneDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_record_record_does_not_exist(self): - HostVirtualMockHttp.type = 'RECORD_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='47234', record_id='4444') - except RecordDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_zone(self): - zone = self.driver.create_zone(domain='t.com', type='master', - ttl=None, extra=None) - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.domain, 't.com') - - def test_update_zone(self): - zone = self.driver.list_zones()[0] - updated_zone = self.driver.update_zone(zone=zone, domain='tt.com') - - self.assertEqual(updated_zone.id, zone.id) - self.assertEqual(updated_zone.domain, 'tt.com') - self.assertEqual(updated_zone.type, zone.type) - self.assertEqual(updated_zone.ttl, '3600') - - def test_create_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.create_record( - name='www', zone=zone, - type=RecordType.A, data='127.0.0.1' - ) - - self.assertEqual(record.id, '300377') - self.assertEqual(record.name, 'www') - self.assertEqual(record.zone, zone) - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '127.0.0.1') - - def test_update_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[1] - updated_record = self.driver.update_record(record=record, name='www', - type=RecordType.AAAA, - data='::1') - self.assertEqual(record.data, '208.111.35.173') - - self.assertEqual(updated_record.id, record.id) - self.assertEqual(updated_record.name, 'www') - self.assertEqual(updated_record.zone, record.zone) - self.assertEqual(updated_record.type, RecordType.AAAA) - self.assertEqual(updated_record.data, '::1') - - def test_delete_zone(self): - zone = self.driver.list_zones()[0] - status = self.driver.delete_zone(zone=zone) - self.assertTrue(status) - - def test_delete_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - HostVirtualMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.delete_zone(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_delete_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - status = self.driver.delete_record(record=record) - self.assertTrue(status) - - def test_delete_record_does_not_exist(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - HostVirtualMockHttp.type = 'RECORD_DOES_NOT_EXIST' - try: - self.driver.delete_record(record=record) - except RecordDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.record_id, record.id) - else: - self.fail('Exception was not thrown') - - -class HostVirtualMockHttp(MockHttp): - fixtures = DNSFileFixtures('hostvirtual') - - def _dns_zone(self, method, url, body, headers): - body = self.fixtures.load('get_zone.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_zones(self, method, url, body, headers): - body = self.fixtures.load('list_zones.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_record(self, method, url, body, headers): - body = self.fixtures.load('get_record.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_records(self, method, url, body, headers): - body = self.fixtures.load('list_records.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_zone_ZONE_DOES_NOT_EXIST(self, method, url, body, headers): - body = self.fixtures.load('zone_does_not_exist.json') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _dns_zone_RECORD_DOES_NOT_EXIST(self, method, url, body, headers): - body = self.fixtures.load('get_zone.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _dns_zones_ZONE_DOES_NOT_EXIST(self, method, url, body, headers): - body = self.fixtures.load('zone_does_not_exist.json') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _dns_record_ZONE_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('zone_does_not_exist.json') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _dns_record_RECORD_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('zone_does_not_exist.json') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _dns_records_ZONE_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('zone_does_not_exist.json') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _dns_zones_RECORD_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('zone_does_not_exist.json') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/test_linode.py b/awx/lib/site-packages/libcloud/test/dns/test_linode.py deleted file mode 100644 index 7933a515bf..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_linode.py +++ /dev/null @@ -1,329 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and - -import sys -import unittest - -from libcloud.utils.py3 import httplib - -from libcloud.common.linode import LinodeException -from libcloud.dns.types import RecordType, ZoneDoesNotExistError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.drivers.linode import LinodeDNSDriver - -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import DNSFileFixtures -from libcloud.test.secrets import DNS_PARAMS_LINODE - - -class LinodeTests(unittest.TestCase): - def setUp(self): - LinodeDNSDriver.connectionCls.conn_classes = ( - None, LinodeMockHttp) - LinodeMockHttp.use_param = 'api_action' - LinodeMockHttp.type = None - self.driver = LinodeDNSDriver(*DNS_PARAMS_LINODE) - - def assertHasKeys(self, dictionary, keys): - for key in keys: - self.assertTrue(key in dictionary, 'key "%s" not in dictionary' % - (key)) - - def test_list_record_types(self): - record_types = self.driver.list_record_types() - self.assertEqual(len(record_types), 7) - self.assertTrue(RecordType.A in record_types) - - def test_list_zones_success(self): - zones = self.driver.list_zones() - self.assertEqual(len(zones), 2) - - zone = zones[0] - self.assertEqual(zone.id, '5093') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 'linode.com') - self.assertEqual(zone.ttl, None) - self.assertHasKeys(zone.extra, ['description', 'SOA_Email', 'status']) - - def test_list_records_success(self): - zone = self.driver.list_zones()[0] - records = self.driver.list_records(zone=zone) - self.assertEqual(len(records), 2) - - arecord = records[0] - self.assertEqual(arecord.id, '3585100') - self.assertEqual(arecord.name, 'mc') - self.assertEqual(arecord.type, RecordType.A) - self.assertEqual(arecord.data, '127.0.0.1') - self.assertHasKeys(arecord.extra, ['protocol', 'ttl_sec', 'port', - 'weight']) - - def test_list_records_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - LinodeMockHttp.type = 'ZONE_DOES_NOT_EXIST' - try: - self.driver.list_records(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_get_zone_success(self): - LinodeMockHttp.type = 'GET_ZONE' - - zone = self.driver.get_zone(zone_id='5093') - self.assertEqual(zone.id, '5093') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 'linode.com') - self.assertEqual(zone.ttl, None) - self.assertHasKeys(zone.extra, ['description', 'SOA_Email', 'status']) - - def test_get_zone_does_not_exist(self): - LinodeMockHttp.type = 'GET_ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_zone(zone_id='4444') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, '4444') - else: - self.fail('Exception was not thrown') - - def test_get_record_success(self): - LinodeMockHttp.type = 'GET_RECORD' - record = self.driver.get_record(zone_id='1234', record_id='3585100') - self.assertEqual(record.id, '3585100') - self.assertEqual(record.name, 'www') - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '127.0.0.1') - self.assertHasKeys(record.extra, ['protocol', 'ttl_sec', 'port', - 'weight']) - - def test_get_record_zone_does_not_exist(self): - LinodeMockHttp.type = 'GET_RECORD_ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='444', record_id='3585100') - except ZoneDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_record_record_does_not_exist(self): - LinodeMockHttp.type = 'GET_RECORD_RECORD_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='4441', record_id='3585100') - except RecordDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_zone_success(self): - zone = self.driver.create_zone(domain='foo.bar.com', type='master', - ttl=None, extra=None) - self.assertEqual(zone.id, '5094') - self.assertEqual(zone.domain, 'foo.bar.com') - - def test_create_zone_validaton_error(self): - LinodeMockHttp.type = 'VALIDATION_ERROR' - - try: - self.driver.create_zone(domain='foo.bar.com', type='master', - ttl=None, extra=None) - except LinodeException: - pass - else: - self.fail('Exception was not thrown') - - def test_update_zone_success(self): - zone = self.driver.list_zones()[0] - updated_zone = self.driver.update_zone(zone=zone, - domain='libcloud.org', - ttl=10, - extra={'SOA_Email': - 'bar@libcloud.org'}) - - self.assertEqual(zone.extra['SOA_Email'], 'dns@example.com') - - self.assertEqual(updated_zone.id, zone.id) - self.assertEqual(updated_zone.domain, 'libcloud.org') - self.assertEqual(updated_zone.type, zone.type) - self.assertEqual(updated_zone.ttl, 10) - self.assertEqual(updated_zone.extra['SOA_Email'], 'bar@libcloud.org') - self.assertEqual(updated_zone.extra['status'], zone.extra['status']) - self.assertEqual(updated_zone.extra['description'], - zone.extra['description']) - - def test_create_record_success(self): - zone = self.driver.list_zones()[0] - record = self.driver.create_record(name='www', zone=zone, - type=RecordType.A, data='127.0.0.1') - - self.assertEqual(record.id, '3585100') - self.assertEqual(record.name, 'www') - self.assertEqual(record.zone, zone) - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '127.0.0.1') - - def test_update_record_success(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - updated_record = self.driver.update_record(record=record, name='www', - type=RecordType.AAAA, - data='::1') - - self.assertEqual(record.data, '127.0.0.1') - - self.assertEqual(updated_record.id, record.id) - self.assertEqual(updated_record.name, 'www') - self.assertEqual(updated_record.zone, record.zone) - self.assertEqual(updated_record.type, RecordType.AAAA) - self.assertEqual(updated_record.data, '::1') - - def test_delete_zone_success(self): - zone = self.driver.list_zones()[0] - status = self.driver.delete_zone(zone=zone) - self.assertTrue(status) - - def test_delete_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - LinodeMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.delete_zone(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_delete_record_success(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - status = self.driver.delete_record(record=record) - self.assertTrue(status) - - def test_delete_record_does_not_exist(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - - LinodeMockHttp.type = 'RECORD_DOES_NOT_EXIST' - - try: - self.driver.delete_record(record=record) - except RecordDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.record_id, record.id) - else: - self.fail('Exception was not thrown') - - -class LinodeMockHttp(MockHttp): - fixtures = DNSFileFixtures('linode') - - def _domain_list(self, method, url, body, headers): - body = self.fixtures.load('domain_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _domain_resource_list(self, method, url, body, headers): - body = self.fixtures.load('resource_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ZONE_DOES_NOT_EXIST_domain_resource_list(self, method, url, body, - headers): - body = self.fixtures.load('resource_list_does_not_exist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_ZONE_domain_list(self, method, url, body, headers): - body = self.fixtures.load('get_zone.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_ZONE_DOES_NOT_EXIST_domain_list(self, method, url, body, - headers): - body = self.fixtures.load('get_zone_does_not_exist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_RECORD_domain_list(self, method, url, body, headers): - body = self.fixtures.load('get_zone.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_RECORD_domain_resource_list(self, method, url, body, headers): - body = self.fixtures.load('get_record.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_RECORD_ZONE_DOES_NOT_EXIST_domain_list(self, method, url, body, - headers): - body = self.fixtures.load('get_zone_does_not_exist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_RECORD_ZONE_DOES_NOT_EXIST_domain_resource_list(self, method, url, - body, headers): - body = self.fixtures.load('get_record_does_not_exist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_RECORD_RECORD_DOES_NOT_EXIST_domain_list(self, method, url, body, - headers): - body = self.fixtures.load('get_zone.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _GET_RECORD_RECORD_DOES_NOT_EXIST_domain_resource_list(self, method, - url, body, - headers): - body = self.fixtures.load('get_record_does_not_exist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _domain_create(self, method, url, body, headers): - body = self.fixtures.load('create_domain.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _VALIDATION_ERROR_domain_create(self, method, url, body, headers): - body = self.fixtures.load('create_domain_validation_error.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _domain_update(self, method, url, body, headers): - body = self.fixtures.load('update_domain.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _domain_resource_create(self, method, url, body, headers): - body = self.fixtures.load('create_resource.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _domain_resource_update(self, method, url, body, headers): - body = self.fixtures.load('update_resource.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _domain_delete(self, method, url, body, headers): - body = self.fixtures.load('delete_domain.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _ZONE_DOES_NOT_EXIST_domain_delete(self, method, url, body, headers): - body = self.fixtures.load('delete_domain_does_not_exist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _domain_resource_delete(self, method, url, body, headers): - body = self.fixtures.load('delete_resource.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _RECORD_DOES_NOT_EXIST_domain_resource_delete(self, method, url, body, - headers): - body = self.fixtures.load('delete_resource_does_not_exist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/test_rackspace.py b/awx/lib/site-packages/libcloud/test/dns/test_rackspace.py deleted file mode 100644 index 4a211a3f85..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_rackspace.py +++ /dev/null @@ -1,490 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and - -import sys -import unittest - -from libcloud.utils.py3 import httplib - -from libcloud.common.types import LibcloudError -from libcloud.dns.types import RecordType, ZoneDoesNotExistError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.drivers.rackspace import RackspaceUSDNSDriver -from libcloud.dns.drivers.rackspace import RackspaceUKDNSDriver - -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import DNSFileFixtures -from libcloud.test.secrets import DNS_PARAMS_RACKSPACE - - -class RackspaceUSTests(unittest.TestCase): - klass = RackspaceUSDNSDriver - endpoint_url = 'https://dns.api.rackspacecloud.com/v1.0/11111' - - def setUp(self): - self.klass.connectionCls.conn_classes = ( - None, RackspaceMockHttp) - RackspaceMockHttp.type = None - self.driver = self.klass(*DNS_PARAMS_RACKSPACE) - self.driver.connection.poll_interval = 0.0 - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - - def test_force_auth_token_kwargs(self): - kwargs = { - 'ex_force_auth_token': 'some-auth-token', - 'ex_force_base_url': 'https://dns.api.rackspacecloud.com/v1.0/11111' - } - driver = self.klass(*DNS_PARAMS_RACKSPACE, **kwargs) - driver.list_zones() - - self.assertEqual(kwargs['ex_force_auth_token'], - driver.connection.auth_token) - self.assertEqual('/v1.0/11111', - driver.connection.request_path) - - def test_force_auth_url_kwargs(self): - kwargs = { - 'ex_force_auth_version': '2.0', - 'ex_force_auth_url': 'https://identity.api.rackspace.com' - } - driver = self.klass(*DNS_PARAMS_RACKSPACE, **kwargs) - - self.assertEqual(kwargs['ex_force_auth_url'], - driver.connection._ex_force_auth_url) - self.assertEqual(kwargs['ex_force_auth_version'], - driver.connection._auth_version) - - def test_gets_auth_2_0_endpoint(self): - kwargs = {'ex_force_auth_version': '2.0_password'} - driver = self.klass(*DNS_PARAMS_RACKSPACE, **kwargs) - driver.connection._populate_hosts_and_request_paths() - - self.assertEquals(self.endpoint_url, driver.connection.get_endpoint()) - - def test_list_record_types(self): - record_types = self.driver.list_record_types() - self.assertEqual(len(record_types), 8) - self.assertTrue(RecordType.A in record_types) - - def test_list_zones_success(self): - zones = self.driver.list_zones() - - self.assertEqual(len(zones), 6) - self.assertEqual(zones[0].domain, 'foo4.bar.com') - self.assertEqual(zones[0].extra['comment'], 'wazaaa') - - def test_list_zones_http_413(self): - RackspaceMockHttp.type = '413' - - try: - self.driver.list_zones() - except LibcloudError: - pass - else: - self.fail('Exception was not thrown') - - def test_list_zones_no_results(self): - RackspaceMockHttp.type = 'NO_RESULTS' - zones = self.driver.list_zones() - self.assertEqual(len(zones), 0) - - def test_list_records_success(self): - zone = self.driver.list_zones()[0] - records = self.driver.list_records(zone=zone) - - self.assertEqual(len(records), 3) - self.assertEqual(records[0].name, 'test3') - self.assertEqual(records[0].type, RecordType.A) - self.assertEqual(records[0].data, '127.7.7.7') - self.assertEqual(records[0].extra['ttl'], 777) - self.assertEqual(records[0].extra['comment'], 'lulz') - self.assertEqual(records[0].extra['fqdn'], 'test3.%s' % - (records[0].zone.domain)) - - def test_list_records_no_results(self): - zone = self.driver.list_zones()[0] - RackspaceMockHttp.type = 'NO_RESULTS' - records = self.driver.list_records(zone=zone) - self.assertEqual(len(records), 0) - - def test_list_records_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - RackspaceMockHttp.type = 'ZONE_DOES_NOT_EXIST' - try: - self.driver.list_records(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_get_zone_success(self): - RackspaceMockHttp.type = 'GET_ZONE' - zone = self.driver.get_zone(zone_id='2946063') - - self.assertEqual(zone.id, '2946063') - self.assertEqual(zone.domain, 'foo4.bar.com') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.extra['email'], 'test@test.com') - - def test_get_zone_does_not_exist(self): - RackspaceMockHttp.type = 'DOES_NOT_EXIST' - - try: - self.driver.get_zone(zone_id='4444') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, '4444') - else: - self.fail('Exception was not thrown') - - def test_get_record_success(self): - record = self.driver.get_record(zone_id='12345678', - record_id='23456789') - self.assertEqual(record.id, 'A-7423034') - self.assertEqual(record.name, 'test3') - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.extra['comment'], 'lulz') - - def test_get_record_zone_does_not_exist(self): - RackspaceMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='444', record_id='28536') - except ZoneDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_record_record_does_not_exist(self): - RackspaceMockHttp.type = 'RECORD_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='12345678', - record_id='28536') - except RecordDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_zone_success(self): - RackspaceMockHttp.type = 'CREATE_ZONE' - - zone = self.driver.create_zone(domain='bar.foo1.com', type='master', - ttl=None, - extra={'email': 'test@test.com'}) - self.assertEqual(zone.id, '2946173') - self.assertEqual(zone.domain, 'bar.foo1.com') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.extra['email'], 'test@test.com') - - def test_create_zone_validaton_error(self): - RackspaceMockHttp.type = 'CREATE_ZONE_VALIDATION_ERROR' - - try: - self.driver.create_zone(domain='foo.bar.com', type='master', - ttl=10, - extra={'email': 'test@test.com'}) - except Exception: - e = sys.exc_info()[1] - self.assertEqual(str(e), 'Validation errors: Domain TTL is ' + - 'required and must be greater than ' + - 'or equal to 300') - else: - self.fail('Exception was not thrown') - - def test_update_zone_success(self): - zone = self.driver.list_zones()[0] - updated_zone = self.driver.update_zone(zone=zone, - extra={'comment': - 'bar foo'}) - - self.assertEqual(zone.extra['comment'], 'wazaaa') - - self.assertEqual(updated_zone.id, zone.id) - self.assertEqual(updated_zone.domain, 'foo4.bar.com') - self.assertEqual(updated_zone.type, zone.type) - self.assertEqual(updated_zone.ttl, zone.ttl) - self.assertEqual(updated_zone.extra['comment'], 'bar foo') - - def test_update_zone_domain_cannot_be_changed(self): - zone = self.driver.list_zones()[0] - - try: - self.driver.update_zone(zone=zone, domain='libcloud.org') - except LibcloudError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_record_success(self): - zone = self.driver.list_zones()[0] - - RackspaceMockHttp.type = 'CREATE_RECORD' - record = self.driver.create_record(name='www', zone=zone, - type=RecordType.A, data='127.1.1.1') - - self.assertEqual(record.id, 'A-7423317') - self.assertEqual(record.name, 'www') - self.assertEqual(record.zone, zone) - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '127.1.1.1') - self.assertEqual(record.extra['fqdn'], 'www.%s' % (zone.domain)) - - def test_update_record_success(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - updated_record = self.driver.update_record(record=record, - data='127.3.3.3') - - self.assertEqual(record.name, 'test3') - self.assertEqual(record.data, '127.7.7.7') - - self.assertEqual(updated_record.id, record.id) - self.assertEqual(updated_record.name, record.name) - self.assertEqual(updated_record.zone, record.zone) - self.assertEqual(updated_record.type, record.type) - self.assertEqual(updated_record.data, '127.3.3.3') - - def test_delete_zone_success(self): - zone = self.driver.list_zones()[0] - status = self.driver.delete_zone(zone=zone) - self.assertTrue(status) - - def test_delete_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - RackspaceMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.delete_zone(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_delete_record_success(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - status = self.driver.delete_record(record=record) - self.assertTrue(status) - - def test_delete_record_does_not_exist(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - - RackspaceMockHttp.type = 'RECORD_DOES_NOT_EXIST' - - try: - self.driver.delete_record(record=record) - except RecordDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.record_id, record.id) - else: - self.fail('Exception was not thrown') - - def test_to_full_record_name_name_provided(self): - domain = 'foo.bar' - name = 'test' - self.assertEqual(self.driver._to_full_record_name(domain, name), - 'test.foo.bar') - - def test_to_full_record_name_name_not_provided(self): - domain = 'foo.bar' - name = None - self.assertEqual(self.driver._to_full_record_name(domain, name), - 'foo.bar') - - def test_to_partial_record_name(self): - domain = 'example.com' - names = ['test.example.com', 'foo.bar.example.com', - 'example.com.example.com', 'example.com'] - expected_values = ['test', 'foo.bar', 'example.com', None] - - for name, expected_value in zip(names, expected_values): - value = self.driver._to_partial_record_name(domain=domain, - name=name) - self.assertEqual(value, expected_value) - - -class RackspaceUKTests(RackspaceUSTests): - klass = RackspaceUKDNSDriver - endpoint_url = 'https://lon.dns.api.rackspacecloud.com/v1.0/11111' - - -class RackspaceMockHttp(MockHttp): - fixtures = DNSFileFixtures('rackspace') - base_headers = {'content-type': 'application/json'} - - def _v2_0_tokens(self, method, url, body, headers): - body = self.fixtures.load('auth_2_0.json') - headers = { - 'content-type': 'application/json' - } - return (httplib.OK, body, headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains(self, method, url, body, headers): - body = self.fixtures.load('list_zones_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_413(self, method, url, body, headers): - body = '' - return (httplib.REQUEST_ENTITY_TOO_LARGE, body, self.base_headers, - httplib.responses[httplib.REQUEST_ENTITY_TOO_LARGE]) - - def _v1_0_11111_domains_NO_RESULTS(self, method, url, body, headers): - body = self.fixtures.load('list_zones_no_results.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_2946063(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('list_records_success.json') - elif method == 'PUT': - # Async - update_zone - body = self.fixtures.load('update_zone_success.json') - elif method == 'DELETE': - # Aync - delete_zone - body = self.fixtures.load('delete_zone_success.json') - - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_2946063_NO_RESULTS(self, method, url, body, - headers): - body = self.fixtures.load('list_records_no_results.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_2946063_ZONE_DOES_NOT_EXIST(self, method, url, - body, headers): - body = self.fixtures.load('does_not_exist.json') - return (httplib.NOT_FOUND, body, self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _v1_0_11111_domains_2946063_GET_ZONE(self, method, url, body, headers): - body = self.fixtures.load('get_zone_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_4444_DOES_NOT_EXIST(self, method, url, body, - headers): - body = self.fixtures.load('does_not_exist.json') - return (httplib.NOT_FOUND, body, self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _v1_0_11111_domains_12345678(self, method, url, body, headers): - body = self.fixtures.load('get_zone_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_12345678_records_23456789(self, method, url, body, - headers): - body = self.fixtures.load('get_record_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_444_ZONE_DOES_NOT_EXIST(self, method, url, body, - headers): - body = self.fixtures.load('does_not_exist.json') - return (httplib.NOT_FOUND, body, self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _v1_0_11111_domains_12345678_RECORD_DOES_NOT_EXIST(self, method, url, - body, headers): - body = self.fixtures.load('get_zone_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_12345678_records_28536_RECORD_DOES_NOT_EXIST(self, method, url, body, headers): - body = self.fixtures.load('does_not_exist.json') - return (httplib.NOT_FOUND, body, self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _v1_0_11111_domains_CREATE_ZONE(self, method, url, body, headers): - # Async response - create_zone - body = self.fixtures.load('create_zone_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_status_288795f9_e74d_48be_880b_a9e36e0de61e_CREATE_ZONE(self, method, url, body, headers): - # Async status - create_zone - body = self.fixtures.load('create_zone_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_CREATE_ZONE_VALIDATION_ERROR(self, method, url, body, headers): - body = self.fixtures.load('create_zone_validation_error.json') - return (httplib.BAD_REQUEST, body, self.base_headers, - httplib.responses[httplib.BAD_REQUEST]) - - def _v1_0_11111_status_116a8f17_38ac_4862_827c_506cd04800d5(self, method, url, body, headers): - # Aync status - update_zone - body = self.fixtures.load('update_zone_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_status_586605c8_5739_43fb_8939_f3a2c4c0e99c_CREATE_RECORD(self, method, url, body, headers): - # Aync status - create_record - body = self.fixtures.load('create_record_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_2946063_records_CREATE_RECORD(self, method, url, body, headers): - # Aync response - create_record - body = self.fixtures.load('create_record_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_status_251c0d0c_95bc_4e09_b99f_4b8748b66246(self, method, url, body, headers): - # Aync response - update_record - body = self.fixtures.load('update_record_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_2946063_records_A_7423034(self, method, url, body, - headers): - # Aync response - update_record - body = self.fixtures.load('update_record_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_status_0b40cd14_2e5d_490f_bb6e_fdc65d1118a9(self, method, - url, body, - headers): - # Async status - delete_zone - body = self.fixtures.load('delete_zone_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_status_0b40cd14_2e5d_490f_bb6e_fdc65d1118a9_RECORD_DOES_NOT_EXIST(self, method, url, body, headers): - # Async status - delete_record - body = self.fixtures.load('delete_record_success.json') - return (httplib.OK, body, self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_domains_2946063_records_A_7423034_RECORD_DOES_NOT_EXIST(self, method, url, body, headers): - # Async response - delete_record - body = self.fixtures.load('does_not_exist.json') - return (httplib.NOT_FOUND, body, self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/test_route53.py b/awx/lib/site-packages/libcloud/test/dns/test_route53.py deleted file mode 100644 index 299420381e..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_route53.py +++ /dev/null @@ -1,267 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.utils.py3 import httplib - -from libcloud.dns.types import RecordType, ZoneDoesNotExistError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.drivers.route53 import Route53DNSDriver -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import DNSFileFixtures -from libcloud.test.secrets import DNS_PARAMS_ROUTE53 - - -class Route53Tests(unittest.TestCase): - def setUp(self): - Route53DNSDriver.connectionCls.conn_classes = ( - Route53MockHttp, Route53MockHttp) - Route53MockHttp.type = None - self.driver = Route53DNSDriver(*DNS_PARAMS_ROUTE53) - - def test_list_record_types(self): - record_types = self.driver.list_record_types() - self.assertEqual(len(record_types), 10) - self.assertTrue(RecordType.A in record_types) - - def test_list_zones(self): - zones = self.driver.list_zones() - self.assertEqual(len(zones), 5) - - zone = zones[0] - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 't.com') - - def test_list_records(self): - zone = self.driver.list_zones()[0] - records = self.driver.list_records(zone=zone) - self.assertEqual(len(records), 10) - - record = records[1] - self.assertEqual(record.name, 'www') - self.assertEqual(record.id, 'A:www') - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '208.111.35.173') - self.assertEqual(record.extra['ttl'], 86400) - - record = records[3] - self.assertEqual(record.type, RecordType.MX) - self.assertEqual(record.data, 'ASPMX.L.GOOGLE.COM.') - self.assertEqual(record.extra['priority'], 1) - - record = records[4] - self.assertEqual(record.type, RecordType.MX) - self.assertEqual(record.data, 'ALT1.ASPMX.L.GOOGLE.COM.') - self.assertEqual(record.extra['priority'], 5) - - record = records[8] - self.assertEqual(record.type, RecordType.SRV) - self.assertEqual(record.data, 'xmpp-server.example.com.') - self.assertEqual(record.extra['priority'], 1) - self.assertEqual(record.extra['weight'], 10) - self.assertEqual(record.extra['port'], 5269) - - def test_get_zone(self): - zone = self.driver.get_zone(zone_id='47234') - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.type, 'master') - self.assertEqual(zone.domain, 't.com') - - def test_get_record(self): - record = self.driver.get_record(zone_id='47234', - record_id='CNAME:wibble') - self.assertEqual(record.name, 'wibble') - self.assertEqual(record.type, RecordType.CNAME) - self.assertEqual(record.data, 't.com') - - def test_list_records_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - Route53MockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.list_records(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_get_zone_does_not_exist(self): - Route53MockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_zone(zone_id='47234') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, '47234') - else: - self.fail('Exception was not thrown') - - def test_get_record_zone_does_not_exist(self): - Route53MockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='4444', record_id='28536') - except ZoneDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_record_record_does_not_exist(self): - Route53MockHttp.type = 'RECORD_DOES_NOT_EXIST' - - rid = 'CNAME:doesnotexist.t.com' - try: - self.driver.get_record(zone_id='47234', - record_id=rid) - except RecordDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_zone(self): - zone = self.driver.create_zone(domain='t.com', type='master', - ttl=None, extra=None) - self.assertEqual(zone.id, '47234') - self.assertEqual(zone.domain, 't.com') - - def test_create_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.create_record( - name='www', zone=zone, - type=RecordType.A, data='127.0.0.1', - extra={'ttl': 0} - ) - - self.assertEqual(record.id, 'A:www') - self.assertEqual(record.name, 'www') - self.assertEqual(record.zone, zone) - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '127.0.0.1') - - def test_update_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[1] - - params = { - 'record': record, - 'name': 'www', - 'type': RecordType.A, - 'data': '::1', - 'extra': {'ttle': 0}} - updated_record = self.driver.update_record(**params) - - self.assertEqual(record.data, '208.111.35.173') - - self.assertEqual(updated_record.id, 'A:www') - self.assertEqual(updated_record.name, 'www') - self.assertEqual(updated_record.zone, record.zone) - self.assertEqual(updated_record.type, RecordType.A) - self.assertEqual(updated_record.data, '::1') - - def test_delete_zone(self): - zone = self.driver.list_zones()[0] - status = self.driver.delete_zone(zone=zone) - self.assertTrue(status) - - def test_delete_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - Route53MockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.delete_zone(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_delete_record(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - status = self.driver.delete_record(record=record) - self.assertTrue(status) - - def test_delete_record_does_not_exist(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - Route53MockHttp.type = 'RECORD_DOES_NOT_EXIST' - try: - self.driver.delete_record(record=record) - except RecordDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.record_id, record.id) - else: - self.fail('Exception was not thrown') - - -class Route53MockHttp(MockHttp): - fixtures = DNSFileFixtures('route53') - - def _2012_02_29_hostedzone_47234(self, method, url, body, headers): - body = self.fixtures.load('get_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_02_29_hostedzone(self, method, url, body, headers): - # print method, url, body, headers - if method == "POST": - body = self.fixtures.load("create_zone.xml") - return (httplib.CREATED, body, {}, httplib.responses[httplib.OK]) - body = self.fixtures.load('list_zones.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_02_29_hostedzone_47234_rrset(self, method, url, body, headers): - body = self.fixtures.load('list_records.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_02_29_hostedzone_47234_rrset_ZONE_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('zone_does_not_exist.xml') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _2012_02_29_hostedzone_4444_ZONE_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('zone_does_not_exist.xml') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _2012_02_29_hostedzone_47234_ZONE_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('zone_does_not_exist.xml') - return (httplib.NOT_FOUND, body, - {}, httplib.responses[httplib.NOT_FOUND]) - - def _2012_02_29_hostedzone_47234_rrset_RECORD_DOES_NOT_EXIST(self, method, - url, body, headers): - if method == "POST": - body = self.fixtures.load('invalid_change_batch.xml') - return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.BAD_REQUEST]) - body = self.fixtures.load('record_does_not_exist.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_02_29_hostedzone_47234_RECORD_DOES_NOT_EXIST(self, method, - url, body, headers): - body = self.fixtures.load('get_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/dns/test_zerigo.py b/awx/lib/site-packages/libcloud/test/dns/test_zerigo.py deleted file mode 100644 index 7897c00fea..0000000000 --- a/awx/lib/site-packages/libcloud/test/dns/test_zerigo.py +++ /dev/null @@ -1,374 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and - -import sys -import unittest - -from libcloud.utils.py3 import httplib - -from libcloud.common.types import InvalidCredsError, LibcloudError -from libcloud.dns.types import RecordType, ZoneDoesNotExistError -from libcloud.dns.types import RecordDoesNotExistError -from libcloud.dns.drivers.zerigo import ZerigoDNSDriver, ZerigoError - -from libcloud.test import MockHttp -from libcloud.test.file_fixtures import DNSFileFixtures -from libcloud.test.secrets import DNS_PARAMS_ZERIGO - - -class ZerigoTests(unittest.TestCase): - def setUp(self): - ZerigoDNSDriver.connectionCls.conn_classes = ( - None, ZerigoMockHttp) - ZerigoMockHttp.type = None - self.driver = ZerigoDNSDriver(*DNS_PARAMS_ZERIGO) - - def test_invalid_credentials(self): - ZerigoMockHttp.type = 'INVALID_CREDS' - - try: - list(self.driver.list_zones()) - except InvalidCredsError: - pass - else: - self.fail('Exception was not thrown') - - def test_list_record_types(self): - record_types = self.driver.list_record_types() - self.assertEqual(len(record_types), 13) - self.assertTrue(RecordType.A in record_types) - - def test_list_zones_success(self): - zones = self.driver.list_zones() - self.assertEqual(len(zones), 1) - self.assertEqual(zones[0].domain, 'example.com') - self.assertEqual(zones[0].type, 'master') - self.assertEqual(zones[0].extra['notes'], 'test foo bar') - - def test_list_zones_no_results(self): - ZerigoMockHttp.type = 'NO_RESULTS' - zones = self.driver.list_zones() - self.assertEqual(len(zones), 0) - - def test_list_records_success(self): - zone = self.driver.list_zones()[0] - records = list(self.driver.list_records(zone=zone)) - - self.assertEqual(len(records), 4) - self.assertEqual(records[0].name, 'www') - self.assertEqual(records[0].type, RecordType.A) - self.assertEqual(records[0].data, '172.16.16.1') - self.assertEqual(records[0].extra['fqdn'], 'www.example.com') - self.assertEqual(records[0].extra['notes'], None) - self.assertEqual(records[0].extra['priority'], None) - - self.assertEqual(records[1].name, 'test') - self.assertEqual(records[1].extra['ttl'], 3600) - - def test_record_with_empty_name(self): - zone = self.driver.list_zones()[0] - record1 = list(self.driver.list_records(zone=zone))[-1] - record2 = list(self.driver.list_records(zone=zone))[-2] - - self.assertEqual(record1.name, None) - self.assertEqual(record2.name, None) - - def test_list_records_no_results(self): - zone = self.driver.list_zones()[0] - ZerigoMockHttp.type = 'NO_RESULTS' - records = list(self.driver.list_records(zone=zone)) - self.assertEqual(len(records), 0) - - def test_list_records_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - ZerigoMockHttp.type = 'ZONE_DOES_NOT_EXIST' - try: - list(self.driver.list_records(zone=zone)) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - pass - - def test_get_zone_success(self): - zone = self.driver.get_zone(zone_id=12345678) - - self.assertEqual(zone.id, '12345678') - self.assertEqual(zone.domain, 'example.com') - self.assertEqual(zone.extra['hostmaster'], 'dnsadmin@example.com') - self.assertEqual(zone.type, 'master') - - def test_get_zone_does_not_exist(self): - ZerigoMockHttp.type = 'DOES_NOT_EXIST' - - try: - self.driver.get_zone(zone_id='4444') - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, '4444') - else: - self.fail('Exception was not thrown') - - def test_get_record_success(self): - record = self.driver.get_record(zone_id='12345678', - record_id='23456789') - self.assertEqual(record.id, '23456789') - self.assertEqual(record.name, 'www') - self.assertEqual(record.type, RecordType.A) - - def test_get_record_zone_does_not_exist(self): - ZerigoMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='444', record_id='28536') - except ZoneDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_record_record_does_not_exist(self): - ZerigoMockHttp.type = 'RECORD_DOES_NOT_EXIST' - - try: - self.driver.get_record(zone_id='12345678', - record_id='28536') - except RecordDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_zone_success(self): - ZerigoMockHttp.type = 'CREATE_ZONE' - - zone = self.driver.create_zone(domain='foo.bar.com', type='master', - ttl=None, extra=None) - self.assertEqual(zone.id, '12345679') - self.assertEqual(zone.domain, 'foo.bar.com') - - def test_create_zone_validaton_error(self): - ZerigoMockHttp.type = 'CREATE_ZONE_VALIDATION_ERROR' - - try: - self.driver.create_zone(domain='foo.bar.com', type='master', - ttl=10, extra=None) - except ZerigoError: - e = sys.exc_info()[1] - self.assertEqual(len(e.errors), 2) - else: - self.fail('Exception was not thrown') - - def test_update_zone_success(self): - zone = self.driver.list_zones()[0] - updated_zone = self.driver.update_zone(zone=zone, - ttl=10, - extra={'notes': - 'bar foo'}) - - self.assertEqual(zone.extra['notes'], 'test foo bar') - - self.assertEqual(updated_zone.id, zone.id) - self.assertEqual(updated_zone.domain, 'example.com') - self.assertEqual(updated_zone.type, zone.type) - self.assertEqual(updated_zone.ttl, 10) - self.assertEqual(updated_zone.extra['notes'], 'bar foo') - - def test_update_zone_domain_cannot_be_changed(self): - zone = self.driver.list_zones()[0] - - try: - self.driver.update_zone(zone=zone, domain='libcloud.org') - except LibcloudError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_record_success(self): - zone = self.driver.list_zones()[0] - - ZerigoMockHttp.type = 'CREATE_RECORD' - record = self.driver.create_record(name='www', zone=zone, - type=RecordType.A, data='127.0.0.1') - - self.assertEqual(record.id, '23456780') - self.assertEqual(record.name, 'www') - self.assertEqual(record.zone, zone) - self.assertEqual(record.type, RecordType.A) - self.assertEqual(record.data, '127.0.0.1') - - def test_update_record_success(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - updated_record = self.driver.update_record(record=record, name='www', - type=RecordType.AAAA, - data='::1') - - self.assertEqual(record.data, '172.16.16.1') - - self.assertEqual(updated_record.id, record.id) - self.assertEqual(updated_record.name, 'www') - self.assertEqual(updated_record.zone, record.zone) - self.assertEqual(updated_record.type, RecordType.AAAA) - self.assertEqual(updated_record.data, '::1') - - def test_delete_zone_success(self): - zone = self.driver.list_zones()[0] - status = self.driver.delete_zone(zone=zone) - self.assertTrue(status) - - def test_delete_zone_does_not_exist(self): - zone = self.driver.list_zones()[0] - - ZerigoMockHttp.type = 'ZONE_DOES_NOT_EXIST' - - try: - self.driver.delete_zone(zone=zone) - except ZoneDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.zone_id, zone.id) - else: - self.fail('Exception was not thrown') - - def test_delete_record_success(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - status = self.driver.delete_record(record=record) - self.assertTrue(status) - - def test_delete_record_does_not_exist(self): - zone = self.driver.list_zones()[0] - record = self.driver.list_records(zone=zone)[0] - - ZerigoMockHttp.type = 'RECORD_DOES_NOT_EXIST' - - try: - self.driver.delete_record(record=record) - except RecordDoesNotExistError: - e = sys.exc_info()[1] - self.assertEqual(e.record_id, record.id) - else: - self.fail('Exception was not thrown') - - -class ZerigoMockHttp(MockHttp): - fixtures = DNSFileFixtures('zerigo') - - def _api_1_1_zones_xml_INVALID_CREDS(self, method, url, body, headers): - body = 'HTTP Basic: Access denied.\n' - return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_xml(self, method, url, body, headers): - body = self.fixtures.load('list_zones.xml') - return (httplib.OK, body, {'x-query-count': 1}, - httplib.responses[httplib.OK]) - - def _api_1_1_zones_xml_NO_RESULTS(self, method, url, body, headers): - body = self.fixtures.load('list_zones_no_results.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_12345678_hosts_xml(self, method, url, body, headers): - body = self.fixtures.load('list_records.xml') - return (httplib.OK, body, {'x-query-count': 1}, - httplib.responses[httplib.OK]) - - def _api_1_1_zones_12345678_hosts_xml_NO_RESULTS(self, method, url, body, - headers): - body = self.fixtures.load('list_records_no_results.xml') - return (httplib.OK, body, {'x-query-count': 0}, - httplib.responses[httplib.OK]) - - def _api_1_1_zones_12345678_hosts_xml_ZONE_DOES_NOT_EXIST(self, method, - url, body, - headers): - body = '' - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_12345678_xml(self, method, url, body, headers): - body = self.fixtures.load('get_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_4444_xml_DOES_NOT_EXIST(self, method, url, body, - headers): - body = '' - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_hosts_23456789_xml(self, method, url, body, headers): - body = self.fixtures.load('get_record.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_444_xml_ZONE_DOES_NOT_EXIST(self, method, url, body, - headers): - body = '' - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_12345678_xml_RECORD_DOES_NOT_EXIST(self, method, url, - body, headers): - body = self.fixtures.load('get_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_hosts_28536_xml_RECORD_DOES_NOT_EXIST(self, method, url, body, - headers): - body = '' - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_xml_CREATE_ZONE(self, method, url, body, headers): - body = self.fixtures.load('create_zone.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_xml_CREATE_ZONE_VALIDATION_ERROR(self, method, url, - body, headers): - body = self.fixtures.load('create_zone_validation_error.xml') - return (httplib.UNPROCESSABLE_ENTITY, body, {}, - httplib.responses[httplib.OK]) - - def _api_1_1_zones_12345678_hosts_xml_CREATE_RECORD(self, method, url, - body, headers): - body = self.fixtures.load('create_record.xml') - return (httplib.CREATED, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_zones_12345678_xml_ZONE_DOES_NOT_EXIST(self, method, url, - body, headers): - body = '' - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) - - def _api_1_1_hosts_23456789_xml_RECORD_DOES_NOT_EXIST(self, method, url, - body, headers): - body = '' - return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) - - """ - def (self, method, url, body, headers): - body = self.fixtures.load('.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def (self, method, url, body, headers): - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def (self, method, url, body, headers): - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def (self, method, url, body, headers): - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def (self, method, url, body, headers): - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def (self, method, url, body, headers): - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - """ - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/file_fixtures.py b/awx/lib/site-packages/libcloud/test/file_fixtures.py deleted file mode 100644 index 42e3d36a4b..0000000000 --- a/awx/lib/site-packages/libcloud/test/file_fixtures.py +++ /dev/null @@ -1,81 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Helper class for loading large fixture data -from __future__ import with_statement - -import os - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import u - -FIXTURES_ROOT = { - 'compute': 'compute/fixtures', - 'storage': 'storage/fixtures', - 'loadbalancer': 'loadbalancer/fixtures', - 'dns': 'dns/fixtures', - 'openstack': 'compute/fixtures/openstack', -} - - -class FileFixtures(object): - def __init__(self, fixtures_type, sub_dir=''): - script_dir = os.path.abspath(os.path.split(__file__)[0]) - self.root = os.path.join(script_dir, FIXTURES_ROOT[fixtures_type], - sub_dir) - - def load(self, file): - path = os.path.join(self.root, file) - if os.path.exists(path): - if PY3: - kwargs = {'encoding': 'utf-8'} - else: - kwargs = {} - - with open(path, 'r', **kwargs) as fh: - content = fh.read() - return u(content) - else: - raise IOError(path) - - -class ComputeFileFixtures(FileFixtures): - def __init__(self, sub_dir=''): - super(ComputeFileFixtures, self).__init__(fixtures_type='compute', - sub_dir=sub_dir) - - -class StorageFileFixtures(FileFixtures): - def __init__(self, sub_dir=''): - super(StorageFileFixtures, self).__init__(fixtures_type='storage', - sub_dir=sub_dir) - - -class LoadBalancerFileFixtures(FileFixtures): - def __init__(self, sub_dir=''): - super(LoadBalancerFileFixtures, self).__init__(fixtures_type='loadbalancer', - sub_dir=sub_dir) - - -class DNSFileFixtures(FileFixtures): - def __init__(self, sub_dir=''): - super(DNSFileFixtures, self).__init__(fixtures_type='dns', - sub_dir=sub_dir) - - -class OpenStackFixtures(FileFixtures): - def __init__(self, sub_dir=''): - super(OpenStackFixtures, self).__init__(fixtures_type='openstack', - sub_dir=sub_dir) diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/__init__.py b/awx/lib/site-packages/libcloud/test/loadbalancer/__init__.py deleted file mode 100644 index ae1e83eeb3..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers.json deleted file mode 100644 index f66b88dd44..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers.json +++ /dev/null @@ -1,22 +0,0 @@ -[{"id": "lba-1235f", - "resource_type": "load_balancer", - "url": "https://api.gb1.brightbox.com/1.0/load_balancers/lba-1235f", - "name": "lb1", - "created_at": "2011-10-06T14:50:28Z", - "deleted_at": null, - "status": "active", - "listeners": [{"out": 80, "protocol": "http", "in": 80}], - "cloud_ips": - [{"id": "cip-c2v98", - "public_ip": "109.107.37.179", - "resource_type": "cloud_ip", - "reverse_dns": "cip-109-107-37-179.gb1.brightbox.com", - "status": "mapped", - "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-c2v98"}], - "account": - {"id": "acc-43ks4", - "resource_type": "account", - "url": "https://api.gb1.brightbox.com/1.0/account", - "name": "Brightbox", - "status": "active"}, - "nodes": []}] diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_lba_1235f.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_lba_1235f.json deleted file mode 100644 index 330413321c..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_lba_1235f.json +++ /dev/null @@ -1,38 +0,0 @@ -{"id": "lba-1235f", - "resource_type": "load_balancer", - "url": "https://api.gb1.brightbox.com/1.0/load_balancers/lba-1235f", - "policy": "least-connections", - "name": "lb1", - "created_at": "2011-10-01T01:00:00Z", - "deleted_at": null, - "healthcheck": - {"threshold_down": 3, - "timeout": 5000, - "port": 80, - "request": "/", - "type": "http", - "interval": 5000, - "threshold_up": 3}, - "listeners": - [{"out": 80, - "protocol": "http", - "in": 80}], - "status": "active", - "cloud_ips": - [], - "account": - {"id": "acc-43ks4", - "resource_type": "account", - "url": "https://api.gb1.brightbox.com/1.0/account", - "name": "Brightbox", - "status": "active"}, - "nodes": - [{"id": "srv-lv426", - "resource_type": "server", - "url": "https://api.gb1.brightbox.com/1.0/servers/srv-lv426", - "name": "web1", - "created_at": "2011-10-01T01:00:00Z", - "deleted_at": null, - "hostname": "srv-lv426", - "started_at": "2011-10-01T01:01:00Z", - "status": "active"}]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_post.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_post.json deleted file mode 100644 index 9fefd09a4c..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_post.json +++ /dev/null @@ -1,38 +0,0 @@ -{"id": "lba-o466u", - "resource_type": "load_balancer", - "url": "https://api.gb1.brightbox.com/1.0/load_balancers/lba-o466u", - "policy": "least-connections", - "name": "lb2", - "created_at": "2011-10-01T01:00:00Z", - "deleted_at": null, - "healthcheck": - {"threshold_down": 3, - "timeout": 5000, - "port": 80, - "request": "/", - "type": "http", - "interval": 5000, - "threshold_up": 3}, - "listeners": - [{"out": 80, - "protocol": "http", - "in": 80}], - "status": "creating", - "cloud_ips": - [], - "account": - {"id": "acc-43ks4", - "resource_type": "account", - "url": "https://api.gb1.brightbox.com/1.0/account", - "name": "Brightbox", - "status": "active"}, - "nodes": - [{"id": "srv-lv426", - "resource_type": "server", - "url": "https://api.gb1.brightbox.com/1.0/servers/srv-lv426", - "name": "web1", - "created_at": "2011-10-01T01:00:00Z", - "deleted_at": null, - "hostname": "srv-lv426", - "started_at": "2011-10-01T01:01:00Z", - "status": "active"}]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/token.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/token.json deleted file mode 100644 index 4508c292ae..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/brightbox/token.json +++ /dev/null @@ -1 +0,0 @@ -{"access_token": "k1bjflpsaj8wnrbrwzad0eqo36nxiha", "expires_in": 3600} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json deleted file mode 100644 index a2175dc56e..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "assigntoloadbalancerruleresponse" : {"jobid":17341} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json deleted file mode 100644 index a62dd4efb6..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "associateipaddressresponse" : {"jobid":17346,"id":34000} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json deleted file mode 100644 index 4a442a0e4a..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "createloadbalancerruleresponse" : { "loadbalancer" : {"id":2253,"name":"fake","publicipid":34000,"publicip":"1.1.1.49","publicport":"80","privateport":"80","algorithm":"roundrobin","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","state":"Add"} } } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json deleted file mode 100644 index bec847a991..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "deleteloadbalancerruleresponse" : {"jobid":17342} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json deleted file mode 100644 index eb1ec6b396..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "disassociateipaddressresponse" : {"jobid":17344} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json deleted file mode 100644 index 912a268533..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listloadbalancerruleinstancesresponse" : { "loadbalancerruleinstance" : [ {"id":2614,"name":"test_1308874974","displayname":"test_1308874974","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-24T00:22:56+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":2185,"networkkbswrite":109,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3914,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.3.122","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}, {"id":2615,"name":"test_1308875456","displayname":"test_1308875456","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-24T00:30:57+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":1118,"networkkbswrite":75,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3915,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.2.62","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"} ] } } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json deleted file mode 100644 index f3ae05acd5..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listloadbalancerrulesresponse" : { "loadbalancerrule" : [ {"id":2247,"name":"test","publicipid":34000,"publicip":"1.1.1.49","publicport":"80","privateport":"80","algorithm":"roundrobin","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","state":"Active"},{"id":2249,"name":"testmore","publicipid":34001,"publicip":"1.1.2.49","publicport":"80","privateport":"80","algorithm":"leastconn","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","state":"Active"} ] } } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listZones_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listZones_default.json deleted file mode 100644 index 0316936e45..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/listZones_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json deleted file mode 100644 index 67a51fed0f..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17340,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json deleted file mode 100644 index 6ea3b16a21..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17341,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json deleted file mode 100644 index 95c4e4a835..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17342,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json deleted file mode 100644 index 65d29c5422..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17344,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json deleted file mode 100644 index aac339b235..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json +++ /dev/null @@ -1 +0,0 @@ -{ "queryasyncjobresultresponse" : {"jobid":17346,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"ipaddress":{"id":34000,"ipaddress":"1.1.1.49","allocated":"2011-06-24T05:52:55+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocating"}}} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json deleted file mode 100644 index a70b5c5642..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json +++ /dev/null @@ -1 +0,0 @@ -{ "removefromloadbalancerruleresponse" : {"jobid":17340} } diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/create_load_balancer.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/create_load_balancer.xml deleted file mode 100644 index f22c540fb4..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/create_load_balancer.xml +++ /dev/null @@ -1,3 +0,0 @@ - - tests.example.com - diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/create_load_balancer_policy.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/create_load_balancer_policy.xml deleted file mode 100644 index 8c0b4c8e9a..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/create_load_balancer_policy.xml +++ /dev/null @@ -1,3 +0,0 @@ - - tests.example.com - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/deregister_instances_from_load_balancer.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/deregister_instances_from_load_balancer.xml deleted file mode 100644 index a7221f0014..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/deregister_instances_from_load_balancer.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancer_policies.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancer_policies.xml deleted file mode 100644 index 188af765ea..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancer_policies.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - MyDurationStickyPolicy - LBCookieStickinessPolicyType - - - CookieExpirationPeriod - 60 - - - - - MyAppStickyPolicy - AppCookieStickinessPolicyType - - - CookieName - MyAppCookie - - - - - - - 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers.xml deleted file mode 100644 index 90bdba1598..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - tests - 2013-01-01T00:00:00.19000Z - - 30 - TCP:22 - 10 - 5 - 2 - - vpc-56e10e3d - - - - AWSConsolePolicy-1 - - - HTTP - 80 - HTTP - 80 - - - - - - i-64bd081c - - - - - - - - AWSConsolePolicy-1 - 30 - - - - - us-east-1e - - tests.us-east-1.elb.amazonaws.com - Z3ZONEID - internet-facing - tests.us-east-1.elb.amazonaws.com - - - - - - - - f9880f01-7852-629d-a6c3-3ae2-666a409287e6dc0c - - diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers_policy_types.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers_policy_types.xml deleted file mode 100644 index 05635f34e2..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers_policy_types.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - ProxyProtocol - Boolean - ONE - - - ProxyProtocolPolicyType - Policy that controls whether to include the IP address and port of the originating request for TCP messages. - This policy operates on TCP/SSL listeners only - - - - - 1549581b-12b7-11e3-895e-1334aEXAMPLE - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_for_backend_server.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_for_backend_server.xml deleted file mode 100644 index 39cfc3d872..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_for_backend_server.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 0eb9b381-dde0-11e2-8d78-6ddbaEXAMPLE - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_of_listener.xml b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_of_listener.xml deleted file mode 100644 index 699350b3c6..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_of_listener.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/ip_list.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/ip_list.json deleted file mode 100644 index f13a358286..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/ip_list.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "list": [ - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868101, - "ip": "10.0.0.68", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868102, - "ip": "10.0.0.69", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868106, - "ip": "10.0.0.73", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868107, - "ip": "10.0.0.74", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868108, - "ip": "10.0.0.75", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868109, - "ip": "10.0.0.76", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868110, - "ip": "10.0.0.77", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868111, - "ip": "10.0.0.78", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277337, - "ip": "10.0.0.244", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277338, - "ip": "10.0.0.245", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277342, - "ip": "10.0.0.249", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277343, - "ip": "10.0.0.250", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277344, - "ip": "10.0.0.251", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277345, - "ip": "10.0.0.252", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277346, - "ip": "10.0.0.253", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - }, - { - "datacenter": { - "description": "US East 1 Datacenter", - "id": 2, - "name": "US-East-1", - "object": "option" - }, - "id": 2277347, - "ip": "10.0.0.254", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.240/255.255.255.240" - } - ], - "method": "/grid/ip/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 16, - "start": 0, - "total": 16 - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_add.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_add.json deleted file mode 100644 index 42bea63e1b..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_add.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "list": [ - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "name": "test2", - "id": 123, - "object": "loadbalancer", - "os": { - "description": "The F5 Load Balancer.", - "id": 1, - "name": "F5", - "object": "option" - }, - "persistence": { - "description": "", - "id": 1, - "name": "None", - "object": "option" - }, - "realiplist": [ - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868109, - "ip": "10.1.0.10", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.1.0.10/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868110, - "ip": "10.1.0.11", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.1.0.11/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868111, - "ip": "10.1.0.12", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.1.0.12/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - ], - "state": { - "description": "Loadbalancer is enabled and on.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "", - "id": 1, - "name": "Round Robin", - "object": "option" - }, - "virtualip": { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868101, - "ip": "1.1.1.1", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "1.1.1.1/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - } - ], - "method": "/grid/loadbalancer/add", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_edit.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_edit.json deleted file mode 100644 index 7afc7945b8..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_edit.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "list": [ - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 23530, - "name": "test2", - "object": "loadbalancer", - "os": { - "description": "The F5 Load Balancer.", - "id": 1, - "name": "F5", - "object": "option" - }, - "persistence": { - "description": "", - "id": 1, - "name": "None", - "object": "option" - }, - "realiplist": [ - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868108, - "ip": "10.0.0.75", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868109, - "ip": "10.0.0.76", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868110, - "ip": "10.0.0.77", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868111, - "ip": "10.0.0.78", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - ], - "state": { - "description": "Loadbalancer is enabled and on.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "", - "id": 1, - "name": "Round Robin", - "object": "option" - }, - "virtualip": { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868101, - "ip": "10.0.0.68", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - } - ], - "method": "/grid/loadbalancer/edit", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_get.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_get.json deleted file mode 100644 index 55878003f2..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_get.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "list": [ - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 23530, - "name": "test2", - "object": "loadbalancer", - "os": { - "description": "The F5 Load Balancer.", - "id": 1, - "name": "F5", - "object": "option" - }, - "persistence": { - "description": "", - "id": 1, - "name": "None", - "object": "option" - }, - "realiplist": [ - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868109, - "ip": "10.0.0.76", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868110, - "ip": "10.0.0.77", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868111, - "ip": "10.0.0.78", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - ], - "state": { - "description": "Loadbalancer is enabled and on.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "", - "id": 1, - "name": "Round Robin", - "object": "option" - }, - "virtualip": { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868101, - "ip": "10.0.0.68", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - } - ], - "method": "/grid/loadbalancer/get", - "status": "success", - "summary": { - "numpages": 0, - "returned": 1, - "start": 0, - "total": 1 - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_list.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_list.json deleted file mode 100644 index e1c366eb5c..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_list.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "list": [ - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 23517, - "name": "foo", - "object": "loadbalancer", - "os": { - "description": "The F5 Load Balancer.", - "id": 1, - "name": "F5", - "object": "option" - }, - "persistence": { - "description": "", - "id": 1, - "name": "None", - "object": "option" - }, - "realiplist": [ - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868111, - "ip": "10.0.0.78", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - ], - "state": { - "description": "Loadbalancer is enabled and on.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "", - "id": 1, - "name": "Round Robin", - "object": "option" - }, - "virtualip": { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868099, - "ip": "10.0.0.66", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - }, - { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 23526, - "name": "bar", - "object": "loadbalancer", - "os": { - "description": "The F5 Load Balancer.", - "id": 1, - "name": "F5", - "object": "option" - }, - "persistence": { - "description": "", - "id": 1, - "name": "None", - "object": "option" - }, - "realiplist": [ - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868109, - "ip": "10.0.0.76", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868110, - "ip": "10.0.0.77", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - }, - { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868111, - "ip": "10.0.0.78", - "object": "ip", - "public": true, - "state": { - "description": "IP is available to use", - "id": 1, - "name": "Unassigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - ], - "state": { - "description": "Loadbalancer is enabled and on.", - "id": 1, - "name": "On", - "object": "option" - }, - "type": { - "description": "", - "id": 1, - "name": "Round Robin", - "object": "option" - }, - "virtualip": { - "ip": { - "datacenter": { - "description": "US West 1 Datacenter", - "id": 1, - "name": "US-West-1", - "object": "option" - }, - "id": 1868100, - "ip": "10.0.0.67", - "object": "ip", - "public": true, - "state": { - "description": "IP is reserved or in use", - "id": 2, - "name": "Assigned", - "object": "option" - }, - "subnet": "10.0.0.64/255.255.255.240" - }, - "object": "ipportpair", - "port": 80 - } - } - ], - "method": "/grid/loadbalancer/list", - "status": "success", - "summary": { - "numpages": 0, - "returned": 2, - "start": 0, - "total": 2 - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/unexpected_error.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/unexpected_error.json deleted file mode 100644 index 87ed4e56ba..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/gogrid/unexpected_error.json +++ /dev/null @@ -1 +0,0 @@ -{"summary":{"total":1,"start":0,"returned":1},"status":"failure","method":"/grid/loadbalancer/add","list":[{"message":"An unexpected server error has occured. Please email this error to apisupport@gogrid.com. Error Message : null","object":"error","errorcode":"UnexpectedException"}]} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/_v2_0__auth.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/_v2_0__auth.json deleted file mode 100644 index e106e93c5a..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/_v2_0__auth.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "access": { - "token": { - "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", - "expires": "2031-11-23T21:00:14.000-06:00" - }, - "serviceCatalog": [ - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - } - - ], - "name": "cloudFilesCDN", - "type": "rax:object-cdn" - }, - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage4.ord1.clouddrive.com/v1/MossoCloudFS", - "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage4.lon1.clouddrive.com/v1/MossoCloudFS", - "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - } - ], - "name": "cloudFiles", - "type": "object-store" - }, - { - "endpoints": [ - { - "tenantId": "1337", - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", - "version": { - "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", - "versionList": "https://servers.api.rackspacecloud.com/", - "versionId": "1.0" - } - } - ], - "name": "cloudServers", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "RegionOne", - "tenantId": "1337", - "publicURL": "https://127.0.0.1/v2/1337", - "versionInfo": "https://127.0.0.1/v2/", - "versionList": "https://127.0.0.1/", - "versionId": "2" - } - ], - "name": "nova", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "613469", - "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", - "versionList": "https://dfw.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "ORD", - "tenantId": "613469", - "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", - "versionList": "https://ord.servers.api.rackspacecloud.com/", - "versionId": "2" - } - ], - "name": "cloudServersOpenStack", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "1337", - "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/1337" - } - ], - "name": "cloudServersPreprod", - "type": "compute" - }, - { - "name": "cloudLoadBalancers", - "endpoints": [ - { - "region": "SYD", - "tenantId": "11111", - "publicURL": "https://syd.loadbalancers.api.rackspacecloud.com/v1.0/11111" - }, - { - "region": "DFW", - "tenantId": "11111", - "publicURL": "https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/11111" - }, - { - "region": "ORD", - "tenantId": "11111", - "publicURL": "https://ord.loadbalancers.api.rackspacecloud.com/v1.0/11111" - }, - { - "region": "LON", - "tenantId": "11111", - "publicURL": "https://lon.loadbalancers.api.rackspacecloud.com/v1.0/11111" - } - ], - "type": "rax:load-balancer" - } - ], - "user": { - "id": "7", - "roles": [ - { - "id": "identity:default", - "description": "Default Role.", - "name": "identity:default" - } - ], - "name": "testuser" - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/auth_2_0.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/auth_2_0.json deleted file mode 100644 index 49b5369ee0..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/auth_2_0.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "access": { - "token": { - "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "expires": "2031-03-14T08:10:14.000-05:00" - }, - "serviceCatalog": [ - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "MossoCloudFS_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - "publicURL": "https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - "internalURL": "https://snet-storage101.dfw1.clouddrive.com/v1/MossoCloudFS_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - } - ], - "name": "cloudFiles", - "type": "object-store" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "11111", - "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/11111", - "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", - "versionList": "https://dfw.servers.api.rackspacecloud.com/", - "versionId": "2" - } - ], - "name": "cloudServersOpenStack", - "type": "compute" - }, - { - "endpoints": [ - { - "tenantId": "11111", - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/11111", - "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", - "versionList": "https://servers.api.rackspacecloud.com/", - "versionId": "1.0" - } - ], - "name": "cloudServers", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "MossoCloudFS_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - "publicURL": "https://cdn1.clouddrive.com/v1/MossoCloudFS_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - } - ], - "name": "cloudFilesCDN", - "type": "rax:object-cdn" - } - ], - "user": { - "id": "9586", - "roles": [ - { - "id": "identity:default", - "description": "Default Role.", - "name": "identity:default" - } - ], - "name": "libclouduser" - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/error_page_default.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/error_page_default.json deleted file mode 100644 index 76d8189e38..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/error_page_default.json +++ /dev/null @@ -1 +0,0 @@ -{"errorpage":{"content":"Service Unavailable

Service Unavailable

The service is temporarily unavailable. Please try again later.

"}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_0_slug_loadbalancers_8290_usage_current.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_0_slug_loadbalancers_8290_usage_current.json deleted file mode 100644 index 9eb9313fc5..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_0_slug_loadbalancers_8290_usage_current.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "links": [], - "loadBalancerUsageRecords": [ - { - "id": 1234, - "startTime": "2013-04-22T22:00:00Z", - "endTime": "2013-04-22T23:00:00Z", - "numVips": 1, - "incomingTransfer": 0, - "outgoingTransfer": 0, - "incomingTransferSsl": 6182163, - "outgoingTransferSsl": 9702071, - "vipType": "PUBLIC", - "averageNumConnections": 0, - "averageNumConnectionsSsl": 14.9166666666666, - "numPolls": 12, - "sslMode": "ON" - }, - { - "id": 12345, - "startTime": "2013-04-22T23:00:00Z", - "endTime": "2013-04-23T00:00:00Z", - "numVips": 1, - "incomingTransfer": 0, - "outgoingTransfer": 0, - "incomingTransferSsl": 6815503, - "outgoingTransferSsl": 10474092, - "vipType": "PUBLIC", - "averageNumConnections": 0, - "averageNumConnectionsSsl": 19.9166666666667, - "numPolls": 12, - "sslMode": "ON" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers.json deleted file mode 100644 index 99a8175110..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "loadBalancers": [ - { - "algorithm": "RANDOM", - "created": { - "time": "2011-04-06T21:25:19+0000" - }, - "id": 8155, - "name": "test0", - "port": 80, - "protocol": "HTTP", - "status": "ACTIVE", - "updated": { - "time": "2011-04-06T21:25:31+0000" - }, - "virtualIps": [ - { - "address": "1.1.1.25", - "id": 965, - "ipVersion": "IPV4", - "type": "PUBLIC" - } - ] - }, - { - "algorithm": "RANDOM", - "created": { - "time": "2011-04-06T21:26:22+0000" - }, - "id": 8156, - "name": "test1", - "port": 80, - "protocol": "HTTP", - "status": "ACTIVE", - "updated": { - "time": "2011-04-06T21:26:33+0000" - }, - "virtualIps": [ - { - "address": "1.1.1.83", - "id": 1279, - "ipVersion": "IPV4", - "type": "PUBLIC" - } - ] - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_accesslist.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_accesslist.json deleted file mode 100644 index ef2e377e90..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_accesslist.json +++ /dev/null @@ -1 +0,0 @@ -{"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"}]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_errorpage.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_errorpage.json deleted file mode 100644 index 76d8189e38..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_errorpage.json +++ /dev/null @@ -1 +0,0 @@ -{"errorpage":{"content":"Service Unavailable

Service Unavailable

The service is temporarily unavailable. Please try again later.

"}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_ex_public_ips.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_ex_public_ips.json deleted file mode 100644 index 69c1e2049e..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_ex_public_ips.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"RANDOM","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED"}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T13:32:05Z"},"connectionLogging":{"enabled":false}}} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18941_ex_private_ips.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18941_ex_private_ips.json deleted file mode 100644 index 5d7f0a8205..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18941_ex_private_ips.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"servicenet","id":18941,"protocol":"HTTP","port":80,"algorithm":"RANDOM","status":"BUILD","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.183.32.247","id":94693,"port":80,"status":"ONLINE","condition":"ENABLED"}],"created":{"time":"2011-12-09T13:33:28Z"},"virtualIps":[{"address":"10.183.252.175","id":572,"type":"SERVICENET","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T13:33:28Z"},"connectionLogging":{"enabled":false}}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18945_ex_public_ips.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18945_ex_public_ips.json deleted file mode 100644 index 69c1e2049e..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18945_ex_public_ips.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"RANDOM","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED"}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T13:32:05Z"},"connectionLogging":{"enabled":false}}} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_3xxx.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_3xxx.json deleted file mode 100644 index 2c3d6faf18..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_3xxx.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "loadBalancer": { - "algorithm": "UUUUUUUUUU", - "cluster": { - "name": "ztm-n05.lbaas.ord1.rackspace.net" - }, - "connectionLogging": { - "enabled": false - }, - "created": { - "time": "2011-04-07T16:27:50Z" - }, - "id": 9999999, - "name": "test2", - "nodes": [ - { - "address": "10.1.0.11", - "condition": "ENABLED", - "id": 30944, - "port": 80, - "status": "ONLINE" - }, - { - "address": "10.1.0.10", - "condition": "ENABLED", - "id": 30945, - "port": 80, - "status": "ONLINE" - } - ], - "port": 88888, - "protocol": "XXXXX", - "status": "ACTIVE", - "updated": { - "time": "2011-04-07T16:28:12Z" - }, - "virtualIps": [ - { - "address": "1.1.1.1", - "id": 1151, - "ipVersion": "IPV4", - "type": "PUBLIC" - } - ] - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290.json deleted file mode 100644 index af3c99d68f..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "loadBalancer": { - "algorithm": "RANDOM", - "cluster": { - "name": "ztm-n05.lbaas.ord1.rackspace.net" - }, - "connectionLogging": { - "enabled": false - }, - "created": { - "time": "2011-04-07T16:27:50Z" - }, - "id": 8290, - "name": "test2", - "nodes": [ - { - "address": "10.1.0.11", - "condition": "ENABLED", - "id": 30944, - "port": 80, - "status": "ONLINE", - "weight": 12 - }, - { - "address": "10.1.0.10", - "condition": "DISABLED", - "id": 30945, - "port": 80, - "status": "OFFLINE", - "weight": 8 - }, - { - "address": "10.1.0.9", - "condition": "DRAINING", - "id": 30946, - "port": 8080, - "status": "DRAINING", - "weight": 20 - } - ], - "port": 80, - "protocol": "HTTP", - "status": "ACTIVE", - "updated": { - "time": "2011-04-07T16:28:12Z" - }, - "virtualIps": [ - { - "address": "1.1.1.1", - "id": 1151, - "ipVersion": "IPV4", - "type": "PUBLIC" - } - ] - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_errorpage.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_errorpage.json deleted file mode 100644 index 88f44c8b1f..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_errorpage.json +++ /dev/null @@ -1 +0,0 @@ -{"errorpage":{"content":"Generic Error Page"}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes.json deleted file mode 100644 index ea67075ae1..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "nodes": [ - { - "address": "10.1.0.11", - "condition": "ENABLED", - "id": 30944, - "port": 80, - "status": "ONLINE", - "weight": 12 - }, - { - "address": "10.1.0.10", - "condition": "DISABLED", - "id": 30945, - "port": 80, - "status": "OFFLINE", - "weight": 8 - }, - { - "address": "10.1.0.9", - "condition": "DRAINING", - "id": 30946, - "port": 8080, - "status": "DRAINING", - "weight": 20 - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes_post.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes_post.json deleted file mode 100644 index fa397621b0..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes_post.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "nodes": [ - { - "address": "10.1.0.12", - "condition": "ENABLED", - "id": 30972, - "port": 80, - "status": "ONLINE", - "weight": 1 - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8291.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8291.json deleted file mode 100644 index b623f46cb2..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8291.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "loadBalancer": { - "algorithm": "RANDOM", - "cluster": { - "name": "ztm-n05.lbaas.ord1.rackspace.net" - }, - "connectionLogging": { - "enabled": false - }, - "created": { - "time": "2011-04-07T16:27:50Z" - }, - "id": 8291, - "name": "test8291", - "nodes": [ - { - "address": "10.1.0.11", - "condition": "ENABLED", - "id": 30944, - "port": 80, - "status": "ONLINE", - "weight": 12 - }, - { - "address": "10.1.0.10", - "condition": "DISABLED", - "id": 30945, - "port": 80, - "status": "OFFLINE", - "weight": 8 - }, - { - "address": "10.1.0.9", - "condition": "DRAINING", - "id": 30946, - "port": 8080, - "status": "DRAINING", - "weight": 20 - } - ], - "port": 80, - "protocol": "HTTP", - "status": "ACTIVE", - "updated": { - "time": "2011-04-07T16:28:12Z" - }, - "virtualIps": [ - { - "address": "1.1.1.1", - "id": 1151, - "ipVersion": "IPV4", - "type": "PUBLIC" - } - ] - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292.json deleted file mode 100644 index c62a3dcc8c..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "loadBalancer": { - "algorithm": "RANDOM", - "cluster": { - "name": "ztm-n05.lbaas.ord1.rackspace.net" - }, - "connectionLogging": { - "enabled": false - }, - "created": { - "time": "2011-04-07T16:27:50Z" - }, - "id": 8292, - "name": "test8292", - "nodes": [ - { - "address": "10.1.0.11", - "condition": "ENABLED", - "id": 30944, - "port": 80, - "status": "ONLINE", - "weight": 12 - }, - { - "address": "10.1.0.10", - "condition": "DISABLED", - "id": 30945, - "port": 80, - "status": "OFFLINE", - "weight": 8 - }, - { - "address": "10.1.0.9", - "condition": "DRAINING", - "id": 30946, - "port": 8080, - "status": "DRAINING", - "weight": 20 - } - ], - "port": 80, - "protocol": "HTTP", - "status": "ACTIVE", - "updated": { - "time": "2011-04-07T16:28:12Z" - }, - "virtualIps": [ - { - "address": "1.1.1.2", - "id": 1151, - "ipVersion": "IPV4", - "type": "PUBLIC" - } - ] - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292_nodes_post.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292_nodes_post.json deleted file mode 100644 index e127c82fe5..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292_nodes_post.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "nodes": [ - { - "address": "10.1.0.12", - "condition": "ENABLED", - "id": 30972, - "port": 80, - "status": "ONLINE", - "weight": 1 - }, - { - "address": "10.1.0.13", - "condition": "ENABLED", - "id": 30973, - "port": 80, - "status": "ONLINE", - "weight": 1 - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94692_weighted_round_robin.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94692_weighted_round_robin.json deleted file mode 100644 index 3bc670377a..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94692_weighted_round_robin.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_ROUND_ROBIN","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T14:39:40Z"},"connectionLogging":{"enabled":false}}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94693_weighted_least_connections.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94693_weighted_least_connections.json deleted file mode 100644 index 886ffca006..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94693_weighted_least_connections.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"PENDING_UPDATE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T15:18:38Z"},"connectionLogging":{"enabled":false}}} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94694_unknown_algorithm.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94694_unknown_algorithm.json deleted file mode 100644 index 098c73c733..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94694_unknown_algorithm.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"UNSPECIFIED_FUTURE_ALGORITHM","status":"PENDING_UPDATE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T15:18:38Z"},"connectionLogging":{"enabled":false}}} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94695_full_details.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94695_full_details.json deleted file mode 100644 index 68883b5f9e..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94695_full_details.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":94695,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"OFFLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"CONNECT","delay":10,"timeout":5,"attemptsBeforeDeactivation":2},"sessionPersistence":{"persistenceType":"HTTP_COOKIE"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T16:01:36Z"},"connectionThrottle":{"maxConnections":200,"minConnections":50,"maxConnectionRate":50,"rateInterval":10},"connectionLogging":{"enabled":true}}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94696_http_health_monitor.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94696_http_health_monitor.json deleted file mode 100644 index ac26cb4fe0..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94696_http_health_monitor.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":94696,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"HTTP","path":"/","delay":10,"timeout":5,"attemptsBeforeDeactivation":2,"statusRegex":"^[234][0-9][0-9]$","bodyRegex":"Hello World!"},"sessionPersistence":{"persistenceType":"HTTP_COOKIE"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T16:51:32Z"},"connectionThrottle":{"maxConnections":100,"minConnections":25,"maxConnectionRate":25,"rateInterval":5},"connectionLogging":{"enabled":true}}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94697_https_health_monitor.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94697_https_health_monitor.json deleted file mode 100644 index eaac2f0672..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94697_https_health_monitor.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":94697,"protocol":"HTTPS","port":443,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"PENDING_UPDATE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"OFFLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"HTTPS","path":"/test","delay":15,"timeout":12,"attemptsBeforeDeactivation":5,"statusRegex":"^[234][0-9][0-9]$","bodyRegex":"abcdef"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T19:34:34Z"},"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"}],"connectionThrottle":{"maxConnections":100,"minConnections":25,"maxConnectionRate":25,"rateInterval":5},"connectionLogging":{"enabled":true}}} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_access_list.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_access_list.json deleted file mode 100644 index 4f1621f65b..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_access_list.json +++ /dev/null @@ -1 +0,0 @@ -{"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"},{"address":"8.8.8.8/0","id":3006,"type":"DENY"}]} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_with_access_list.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_with_access_list.json deleted file mode 100644 index 01d8c5d075..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_with_access_list.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":94698,"protocol":"HTTPS","port":443,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"OFFLINE","condition":"DRAINING","weight":25},{"address":"10.181.238.11","id":97683,"port":443,"status":"OFFLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"CONNECT","delay":5,"timeout":10,"attemptsBeforeDeactivation":4},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2012-01-05T19:31:38Z"},"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"},{"address":"8.8.8.8/0","id":3006,"type":"DENY"}],"connectionThrottle":{"maxConnections":200,"minConnections":50,"maxConnectionRate":50,"rateInterval":10},"connectionLogging":{"enabled":true}}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94700_http_health_monitor_no_body_regex.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94700_http_health_monitor_no_body_regex.json deleted file mode 100644 index 8809f725d6..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94700_http_health_monitor_no_body_regex.json +++ /dev/null @@ -1 +0,0 @@ -{"loadBalancer":{"name":"new ord balancer","id":94700,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"HTTP","path":"/","delay":10,"timeout":5,"attemptsBeforeDeactivation":2,"statusRegex":"^[234][0-9][0-9]$"},"sessionPersistence":{"persistenceType":"HTTP_COOKIE"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T16:51:32Z"},"connectionThrottle":{"maxConnections":100,"minConnections":25,"maxConnectionRate":25,"rateInterval":5},"connectionLogging":{"enabled":true}}} \ No newline at end of file diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_algorithms.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_algorithms.json deleted file mode 100644 index a09c1a3a31..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_algorithms.json +++ /dev/null @@ -1 +0,0 @@ -{"algorithms":[{"name":"LEAST_CONNECTIONS"},{"name":"RANDOM"},{"name":"ROUND_ROBIN"},{"name":"WEIGHTED_LEAST_CONNECTIONS"},{"name":"WEIGHTED_ROUND_ROBIN"}]} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_nodeaddress.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_nodeaddress.json deleted file mode 100644 index 2bc76be3ca..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_nodeaddress.json +++ /dev/null @@ -1,18 +0,0 @@ -{"loadBalancers": [ - { - "name": "First Loadbalancer", - "id": 1, - "status": "ACTIVE" - }, - { - "name": "Second Loadbalancer", - "id": 2, - "status": "PENDING_UPDATE" - }, - { - "name": "Third Loadbalancer", - "id": 8, - "status": "ERROR" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_post.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_post.json deleted file mode 100644 index e1d030b26c..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_post.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "loadBalancer": { - "algorithm": "RANDOM", - "cluster": { - "name": "ztm-n05.lbaas.ord1.rackspace.net" - }, - "connectionLogging": { - "enabled": false - }, - "created": { - "time": "2011-04-07T16:27:50+0000" - }, - "id": 8290, - "name": "test2", - "nodes": [ - { - "address": "10.1.0.11", - "condition": "ENABLED", - "id": 30944, - "port": 80, - "status": "ONLINE", - "weight": 1 - }, - { - "address": "10.1.0.10", - "condition": "ENABLED", - "id": 30945, - "port": 80, - "status": "ONLINE", - "weight": 1 - } - ], - "port": 80, - "protocol": "HTTP", - "status": "BUILD", - "updated": { - "time": "2011-04-07T16:27:50+0000" - }, - "virtualIps": [ - { - "address": "1.1.1.1", - "id": 1151, - "ipVersion": "IPV4", - "type": "PUBLIC" - } - ] - } -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_protocols.json b/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_protocols.json deleted file mode 100644 index d966c396b7..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_protocols.json +++ /dev/null @@ -1,43 +0,0 @@ -{"protocols": [ - { - "name": "HTTP", - "port": "80" - }, - { - "name": "FTP", - "port": "21" - }, - { - "name": "IMAPv4", - "port": "143" - }, - { - "name": "POP3", - "port": "110" - }, - { - "name": "SMTP", - "port": "25" - }, - { - "name": "LDAP", - "port": "389" - }, - { - "name": "HTTPS", - "port": "443" - }, - { - "name": "IMAPS", - "port": "993" - }, - { - "name": "POP3S", - "port": "995" - }, - { - "name": "LDAPS", - "port": "636" - } - ] -} diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/test_brightbox.py b/awx/lib/site-packages/libcloud/test/loadbalancer/test_brightbox.py deleted file mode 100644 index 2509d13804..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/test_brightbox.py +++ /dev/null @@ -1,134 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.loadbalancer.base import Member, Algorithm -from libcloud.loadbalancer.drivers.brightbox import BrightboxLBDriver -from libcloud.loadbalancer.types import State - -from libcloud.test import MockHttpTestCase -from libcloud.test.secrets import LB_BRIGHTBOX_PARAMS -from libcloud.test.file_fixtures import LoadBalancerFileFixtures - - -class BrightboxLBTests(unittest.TestCase): - def setUp(self): - BrightboxLBDriver.connectionCls.conn_classes = (None, - BrightboxLBMockHttp) - BrightboxLBMockHttp.type = None - self.driver = BrightboxLBDriver(*LB_BRIGHTBOX_PARAMS) - - def test_list_protocols(self): - protocols = self.driver.list_protocols() - - self.assertEqual(len(protocols), 2) - self.assertTrue('tcp' in protocols) - self.assertTrue('http' in protocols) - - def test_list_balancers(self): - balancers = self.driver.list_balancers() - - self.assertEqual(len(balancers), 1) - self.assertEqual(balancers[0].id, 'lba-1235f') - self.assertEqual(balancers[0].name, 'lb1') - - def test_get_balancer(self): - balancer = self.driver.get_balancer(balancer_id='lba-1235f') - - self.assertEqual(balancer.id, 'lba-1235f') - self.assertEqual(balancer.name, 'lb1') - self.assertEqual(balancer.state, State.RUNNING) - - def test_destroy_balancer(self): - balancer = self.driver.get_balancer(balancer_id='lba-1235f') - - self.assertTrue(self.driver.destroy_balancer(balancer)) - - def test_create_balancer(self): - members = [Member('srv-lv426', None, None)] - - balancer = self.driver.create_balancer(name='lb2', port=80, - protocol='http', - algorithm=Algorithm.ROUND_ROBIN, - members=members) - - self.assertEqual(balancer.name, 'lb2') - self.assertEqual(balancer.port, 80) - self.assertEqual(balancer.state, State.PENDING) - - def test_balancer_list_members(self): - balancer = self.driver.get_balancer(balancer_id='lba-1235f') - members = balancer.list_members() - - self.assertEqual(len(members), 1) - self.assertEqual(members[0].balancer, balancer) - self.assertEqual('srv-lv426', members[0].id) - - def test_balancer_attach_member(self): - balancer = self.driver.get_balancer(balancer_id='lba-1235f') - member = balancer.attach_member(Member('srv-kg983', ip=None, - port=None)) - - self.assertEqual(member.id, 'srv-kg983') - - def test_balancer_detach_member(self): - balancer = self.driver.get_balancer(balancer_id='lba-1235f') - member = Member('srv-lv426', None, None) - - self.assertTrue(balancer.detach_member(member)) - - -class BrightboxLBMockHttp(MockHttpTestCase): - fixtures = LoadBalancerFileFixtures('brightbox') - - def _token(self, method, url, body, headers): - if method == 'POST': - return self.response(httplib.OK, self.fixtures.load('token.json')) - - def _1_0_load_balancers(self, method, url, body, headers): - if method == 'GET': - return self.response(httplib.OK, - self.fixtures.load('load_balancers.json')) - elif method == 'POST': - body = self.fixtures.load('load_balancers_post.json') - return self.response(httplib.ACCEPTED, body) - - def _1_0_load_balancers_lba_1235f(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load('load_balancers_lba_1235f.json') - return self.response(httplib.OK, body) - elif method == 'DELETE': - return self.response(httplib.ACCEPTED, '') - - def _1_0_load_balancers_lba_1235f_add_nodes(self, method, url, body, - headers): - if method == 'POST': - return self.response(httplib.ACCEPTED, '') - - def _1_0_load_balancers_lba_1235f_remove_nodes(self, method, url, body, - headers): - if method == 'POST': - return self.response(httplib.ACCEPTED, '') - - def response(self, status, body): - return (status, body, {'content-type': 'application/json'}, - httplib.responses[status]) - - -if __name__ == "__main__": - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/test_cloudstack.py b/awx/lib/site-packages/libcloud/test/loadbalancer/test_cloudstack.py deleted file mode 100644 index a54c177fd7..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/test_cloudstack.py +++ /dev/null @@ -1,125 +0,0 @@ -import sys - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import parse_qsl - -from libcloud.loadbalancer.types import Provider -from libcloud.loadbalancer.providers import get_driver -from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm -from libcloud.loadbalancer.drivers.cloudstack import CloudStackLBDriver - -from libcloud.test import unittest -from libcloud.test import MockHttpTestCase -from libcloud.test.file_fixtures import LoadBalancerFileFixtures - - -class CloudStackLBTests(unittest.TestCase): - def setUp(self): - CloudStackLBDriver.connectionCls.conn_classes = \ - (None, CloudStackMockHttp) - - CloudStackLBDriver.path = '/test/path' - CloudStackLBDriver.type = -1 - CloudStackLBDriver.name = 'CloudStack' - self.driver = CloudStackLBDriver('apikey', 'secret') - CloudStackMockHttp.fixture_tag = 'default' - self.driver.connection.poll_interval = 0.0 - - def test_user_must_provide_host_and_path(self): - CloudStackLBDriver.path = None - CloudStackLBDriver.type = Provider.CLOUDSTACK - - expected_msg = 'When instantiating CloudStack driver directly ' + \ - 'you also need to provide host and path argument' - cls = get_driver(Provider.CLOUDSTACK) - - self.assertRaisesRegexp(Exception, expected_msg, cls, - 'key', 'secret') - - try: - cls('key', 'secret', True, 'localhost', '/path') - except Exception: - self.fail('host and path provided but driver raised an exception') - - def test_list_supported_algorithms(self): - algorithms = self.driver.list_supported_algorithms() - - self.assertTrue(Algorithm.ROUND_ROBIN in algorithms) - self.assertTrue(Algorithm.LEAST_CONNECTIONS in algorithms) - - def test_list_balancers(self): - balancers = self.driver.list_balancers() - for balancer in balancers: - self.assertTrue(isinstance(balancer, LoadBalancer)) - - def test_create_balancer(self): - members = [Member(1, '1.1.1.1', 80), Member(2, '1.1.1.2', 80)] - balancer = self.driver.create_balancer('fake', members) - self.assertTrue(isinstance(balancer, LoadBalancer)) - - def test_destroy_balancer(self): - balancer = self.driver.list_balancers()[0] - self.driver.destroy_balancer(balancer) - - def test_balancer_attach_member(self): - balancer = self.driver.list_balancers()[0] - member = Member(id=1234, ip='1.1.1.1', port=80) - balancer.attach_member(member) - - def test_balancer_detach_member(self): - balancer = self.driver.list_balancers()[0] - member = balancer.list_members()[0] - balancer.detach_member(member) - - def test_balancer_list_members(self): - balancer = self.driver.list_balancers()[0] - members = balancer.list_members() - for member in members: - self.assertTrue(isinstance(member, Member)) - self.assertEqual(member.balancer, balancer) - - -class CloudStackMockHttp(MockHttpTestCase): - fixtures = LoadBalancerFileFixtures('cloudstack') - fixture_tag = 'default' - - def _load_fixture(self, fixture): - body = self.fixtures.load(fixture) - return body, json.loads(body) - - def _test_path(self, method, url, body, headers): - url = urlparse.urlparse(url) - query = dict(parse_qsl(url.query)) - - self.assertTrue('apiKey' in query) - self.assertTrue('command' in query) - self.assertTrue('response' in query) - self.assertTrue('signature' in query) - - self.assertTrue(query['response'] == 'json') - - del query['apiKey'] - del query['response'] - del query['signature'] - command = query.pop('command') - - if hasattr(self, '_cmd_' + command): - return getattr(self, '_cmd_' + command)(**query) - else: - fixture = command + '_' + self.fixture_tag + '.json' - body, obj = self._load_fixture(fixture) - return (httplib.OK, body, obj, httplib.responses[httplib.OK]) - - def _cmd_queryAsyncJobResult(self, jobid): - fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json' - body, obj = self._load_fixture(fixture) - return (httplib.OK, body, obj, httplib.responses[httplib.OK]) - -if __name__ == "__main__": - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/test_elb.py b/awx/lib/site-packages/libcloud/test/loadbalancer/test_elb.py deleted file mode 100644 index 88f5555b75..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/test_elb.py +++ /dev/null @@ -1,188 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.loadbalancer.base import Member, Algorithm -from libcloud.loadbalancer.drivers.elb import ElasticLBDriver -from libcloud.loadbalancer.types import State - -from libcloud.test import MockHttpTestCase -from libcloud.test.secrets import LB_ELB_PARAMS -from libcloud.test.file_fixtures import LoadBalancerFileFixtures - - -class ElasticLBTests(unittest.TestCase): - def setUp(self): - ElasticLBMockHttp.test = self - ElasticLBDriver.connectionCls.conn_classes = (None, - ElasticLBMockHttp) - ElasticLBMockHttp.type = None - ElasticLBMockHttp.use_param = 'Action' - - self.driver = ElasticLBDriver(*LB_ELB_PARAMS) - - def test_list_protocols(self): - protocols = self.driver.list_protocols() - - self.assertEqual(len(protocols), 4) - self.assertTrue('tcp' in protocols) - self.assertTrue('http' in protocols) - - def test_list_balancers(self): - balancers = self.driver.list_balancers() - - self.assertEqual(len(balancers), 1) - self.assertEqual(balancers[0].id, 'tests') - self.assertEqual(balancers[0].name, 'tests') - - def test_get_balancer(self): - balancer = self.driver.get_balancer(balancer_id='tests') - - self.assertEqual(balancer.id, 'tests') - self.assertEqual(balancer.name, 'tests') - self.assertEqual(balancer.state, State.UNKNOWN) - - def test_destroy_balancer(self): - balancer = self.driver.get_balancer(balancer_id='tests') - - self.assertTrue(self.driver.destroy_balancer(balancer)) - - def test_create_balancer(self): - members = [Member('srv-lv426', None, None)] - - balancer = self.driver.create_balancer(name='lb2', port=80, - protocol='http', - algorithm=Algorithm.ROUND_ROBIN, - members=members) - - self.assertEqual(balancer.name, 'lb2') - self.assertEqual(balancer.port, 80) - self.assertEqual(balancer.state, State.PENDING) - - def test_balancer_list_members(self): - balancer = self.driver.get_balancer(balancer_id='tests') - members = balancer.list_members() - - self.assertEqual(len(members), 1) - self.assertEqual(members[0].balancer, balancer) - self.assertEqual('i-64bd081c', members[0].id) - - def test_balancer_detach_member(self): - balancer = self.driver.get_balancer(balancer_id='lba-1235f') - member = Member('i-64bd081c', None, None) - - self.assertTrue(balancer.detach_member(member)) - - def test_ex_list_balancer_policies(self): - balancer = self.driver.get_balancer(balancer_id='tests') - policies = self.driver.ex_list_balancer_policies(balancer) - - self.assertTrue('MyDurationStickyPolicy' in policies) - - def test_ex_list_balancer_policy_types(self): - policy_types = self.driver.ex_list_balancer_policy_types() - - self.assertTrue('ProxyProtocolPolicyType' in policy_types) - - def test_ex_create_balancer_policy(self): - self.assertTrue( - self.driver.ex_create_balancer_policy( - name='tests', - policy_name='MyDurationProxyPolicy', - policy_type='ProxyProtocolPolicyType')) - - def test_ex_delete_balancer_policy(self): - self.assertTrue( - self.driver.ex_delete_balancer_policy( - name='tests', - policy_name='MyDurationProxyPolicy')) - - def test_ex_set_balancer_policies_listener(self): - self.assertTrue( - self.driver.ex_set_balancer_policies_listener( - name='tests', - port=80, - policies=['MyDurationStickyPolicy'])) - - def test_ex_set_balancer_policies_backend_server(self): - self.assertTrue( - self.driver.ex_set_balancer_policies_backend_server( - name='tests', - instance_port=80, - policies=['MyDurationProxyPolicy'])) - - def text_ex_create_balancer_listeners(self): - self.assertTrue( - self.driver.ex_create_balancer_listeners( - name='tests', - listeners=[[1024, 65533, 'HTTP']])) - - -class ElasticLBMockHttp(MockHttpTestCase): - fixtures = LoadBalancerFileFixtures('elb') - - def _2012_06_01_DescribeLoadBalancers(self, method, url, body, headers): - body = self.fixtures.load('describe_load_balancers.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_CreateLoadBalancer(self, method, url, body, headers): - body = self.fixtures.load('create_load_balancer.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_DeregisterInstancesFromLoadBalancer(self, method, url, - body, headers): - body = self.fixtures.load( - 'deregister_instances_from_load_balancer.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_CreateLoadBalancerPolicy(self, method, url, body, headers): - body = self.fixtures.load('create_load_balancer_policy.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_DeleteLoadBalancer(self, method, url, body, headers): - body = '' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_DescribeLoadBalancerPolicies(self, method, url, body, - headers): - body = self.fixtures.load('describe_load_balancer_policies.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_DescribeLoadBalancerPolicyTypes(self, method, url, body, - headers): - body = self.fixtures.load('describe_load_balancers_policy_types.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_DeleteLoadBalancerPolicy(self, method, url, body, headers): - body = '' - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_SetLoadBalancerPoliciesOfListener(self, method, url, body, - headers): - body = self.fixtures.load('set_load_balancer_policies_of_listener.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _2012_06_01_SetLoadBalancerPoliciesForBackendServer(self, method, url, - body, headers): - body = self.fixtures.load( - 'set_load_balancer_policies_for_backend_server.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == "__main__": - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/test_gce.py b/awx/lib/site-packages/libcloud/test/loadbalancer/test_gce.py deleted file mode 100644 index 9b55a2a89f..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/test_gce.py +++ /dev/null @@ -1,207 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Tests for Google Compute Engine Load Balancer Driver -""" -import sys -import unittest - -from libcloud.common.google import (GoogleBaseAuthConnection, - GoogleInstalledAppAuthConnection, - GoogleBaseConnection) -from libcloud.compute.drivers.gce import (GCENodeDriver) -from libcloud.loadbalancer.drivers.gce import (GCELBDriver) -from libcloud.test.common.test_google import GoogleAuthMockHttp -from libcloud.test.compute.test_gce import GCEMockHttp - -from libcloud.test import LibcloudTestCase - -from libcloud.test.secrets import GCE_PARAMS, GCE_KEYWORD_PARAMS - - -class GCELoadBalancerTest(LibcloudTestCase): - GoogleBaseConnection._get_token_info_from_file = lambda x: None - GoogleBaseConnection._write_token_info_to_file = lambda x: None - GoogleInstalledAppAuthConnection.get_code = lambda x: '1234' - datacenter = 'us-central1-a' - - def setUp(self): - GCEMockHttp.test = self - GCELBDriver.connectionCls.conn_classes = (GCEMockHttp, GCEMockHttp) - GCENodeDriver.connectionCls.conn_classes = (GCEMockHttp, GCEMockHttp) - GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp, - GoogleAuthMockHttp) - GCEMockHttp.type = None - kwargs = GCE_KEYWORD_PARAMS.copy() - kwargs['auth_type'] = 'IA' - kwargs['datacenter'] = self.datacenter - self.driver = GCELBDriver(*GCE_PARAMS, **kwargs) - - def test_get_node_from_ip(self): - ip = '23.236.58.15' - expected_name = 'node-name' - node = self.driver._get_node_from_ip(ip) - self.assertEqual(node.name, expected_name) - - dummy_ip = '8.8.8.8' - node = self.driver._get_node_from_ip(dummy_ip) - self.assertTrue(node is None) - - def test_list_protocols(self): - expected_protocols = ['TCP', 'UDP'] - protocols = self.driver.list_protocols() - self.assertEqual(protocols, expected_protocols) - - def test_list_balancers(self): - balancers = self.driver.list_balancers() - balancers_all = self.driver.list_balancers(ex_region='all') - balancer_name = 'lcforwardingrule' - self.assertEqual(len(balancers), 2) - self.assertEqual(len(balancers_all), 2) - self.assertEqual(balancers[0].name, balancer_name) - - def test_create_balancer(self): - balancer_name = 'libcloud-lb-demo-lb' - tp_name = '%s-tp' % (balancer_name) - port = '80' - protocol = 'tcp' - algorithm = None - node0 = self.driver.gce.ex_get_node('libcloud-lb-demo-www-000', - 'us-central1-b') - node1 = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', - 'us-central1-b') - members = [node0, node1] - balancer = self.driver.create_balancer(balancer_name, port, protocol, - algorithm, members) - self.assertEqual(balancer.name, balancer_name) - self.assertEqual(balancer.extra['targetpool'].name, tp_name) - self.assertEqual(len(balancer.list_members()), 3) - - def test_destory_balancer(self): - balancer_name = 'lcforwardingrule' - balancer = self.driver.get_balancer(balancer_name) - destroyed = balancer.destroy() - self.assertTrue(destroyed) - - def test_get_balancer(self): - balancer_name = 'lcforwardingrule' - tp_name = 'lctargetpool' - balancer_ip = '173.255.119.224' - balancer = self.driver.get_balancer(balancer_name) - self.assertEqual(balancer.name, balancer_name) - self.assertEqual(balancer.extra['forwarding_rule'].name, balancer_name) - self.assertEqual(balancer.ip, balancer_ip) - self.assertEqual(balancer.extra['targetpool'].name, tp_name) - - def test_attach_compute_node(self): - node = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', - 'us-central1-b') - balancer = self.driver.get_balancer('lcforwardingrule') - member = self.driver._node_to_member(node, balancer) - # Detach member first - balancer.detach_member(member) - self.assertEqual(len(balancer.list_members()), 1) - # Attach Node - balancer.attach_compute_node(node) - self.assertEqual(len(balancer.list_members()), 2) - - def test_detach_attach_member(self): - node = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', - 'us-central1-b') - balancer = self.driver.get_balancer('lcforwardingrule') - member = self.driver._node_to_member(node, balancer) - - # Check that balancer has 2 members - self.assertEqual(len(balancer.list_members()), 2) - - # Remove a member and check that it now has 1 member - balancer.detach_member(member) - self.assertEqual(len(balancer.list_members()), 1) - - # Reattach member and check that it has 2 members again - balancer.attach_member(member) - self.assertEqual(len(balancer.list_members()), 2) - - def test_balancer_list_members(self): - balancer = self.driver.get_balancer('lcforwardingrule') - members = balancer.list_members() - self.assertEqual(len(members), 2) - member_ips = [m.ip for m in members] - self.assertTrue('23.236.58.15' in member_ips) - - def test_ex_create_healthcheck(self): - healthcheck_name = 'lchealthcheck' - kwargs = {'host': 'lchost', - 'path': '/lc', - 'port': 8000, - 'interval': 10, - 'timeout': 10, - 'unhealthy_threshold': 4, - 'healthy_threshold': 3} - hc = self.driver.ex_create_healthcheck(healthcheck_name, **kwargs) - self.assertEqual(hc.name, healthcheck_name) - self.assertEqual(hc.path, '/lc') - self.assertEqual(hc.port, 8000) - self.assertEqual(hc.interval, 10) - - def test_ex_list_healthchecks(self): - healthchecks = self.driver.ex_list_healthchecks() - self.assertEqual(len(healthchecks), 3) - self.assertEqual(healthchecks[0].name, 'basic-check') - - def test_ex_balancer_detach_attach_healthcheck(self): - healthcheck = self.driver.gce.ex_get_healthcheck( - 'libcloud-lb-demo-healthcheck') - balancer = self.driver.get_balancer('lcforwardingrule') - - healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) - self.assertEqual(len(healthchecks), 1) - # Detach Healthcheck - detach_healthcheck = self.driver.ex_balancer_detach_healthcheck( - balancer, healthcheck) - self.assertTrue(detach_healthcheck) - healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) - self.assertEqual(len(healthchecks), 0) - - # Reattach Healthcheck - attach_healthcheck = self.driver.ex_balancer_attach_healthcheck( - balancer, healthcheck) - self.assertTrue(attach_healthcheck) - healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) - self.assertEqual(len(healthchecks), 1) - - def test_ex_balancer_list_healthchecks(self): - balancer = self.driver.get_balancer('lcforwardingrule') - healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) - self.assertEqual(healthchecks[0].name, 'libcloud-lb-demo-healthcheck') - - def test_node_to_member(self): - node = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', - 'us-central1-b') - balancer = self.driver.get_balancer('lcforwardingrule') - member = self.driver._node_to_member(node, balancer) - self.assertEqual(member.ip, node.public_ips[0]) - self.assertEqual(member.id, node.name) - self.assertEqual(member.port, balancer.port) - - def test_forwarding_rule_to_loadbalancer(self): - fwr = self.driver.gce.ex_get_forwarding_rule('lcforwardingrule') - balancer = self.driver._forwarding_rule_to_loadbalancer(fwr) - self.assertEqual(fwr.name, balancer.name) - self.assertEqual(fwr.address, balancer.ip) - self.assertEqual(fwr.extra['portRange'], balancer.port) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/test_gogrid.py b/awx/lib/site-packages/libcloud/test/loadbalancer/test_gogrid.py deleted file mode 100644 index 3e32a37f19..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/test_gogrid.py +++ /dev/null @@ -1,197 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse - -from libcloud.common.types import LibcloudError -from libcloud.compute.base import Node -from libcloud.compute.drivers.dummy import DummyNodeDriver -from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm -from libcloud.loadbalancer.drivers.gogrid import GoGridLBDriver - -from libcloud.test import MockHttpTestCase -from libcloud.test.file_fixtures import LoadBalancerFileFixtures - - -class GoGridTests(unittest.TestCase): - - def setUp(self): - GoGridLBDriver.connectionCls.conn_classes = (None, - GoGridLBMockHttp) - GoGridLBMockHttp.type = None - self.driver = GoGridLBDriver('user', 'key') - - def test_list_supported_algorithms(self): - algorithms = self.driver.list_supported_algorithms() - - self.assertTrue(Algorithm.ROUND_ROBIN in algorithms) - self.assertTrue(Algorithm.LEAST_CONNECTIONS in algorithms) - - def test_list_protocols(self): - protocols = self.driver.list_protocols() - - self.assertEqual(len(protocols), 1) - self.assertEqual(protocols[0], 'http') - - def test_list_balancers(self): - balancers = self.driver.list_balancers() - - self.assertEqual(len(balancers), 2) - self.assertEqual(balancers[0].name, "foo") - self.assertEqual(balancers[0].id, "23517") - self.assertEqual(balancers[1].name, "bar") - self.assertEqual(balancers[1].id, "23526") - - def test_create_balancer(self): - balancer = self.driver.create_balancer(name='test2', - port=80, - protocol='http', - algorithm=Algorithm.ROUND_ROBIN, - members=( - Member( - None, '10.1.0.10', 80), - Member(None, '10.1.0.11', 80)) - ) - - self.assertEqual(balancer.name, 'test2') - self.assertEqual(balancer.id, '123') - - def test_create_balancer_UNEXPECTED_ERROR(self): - # Try to create new balancer and attach members with an IP address which - # does not belong to this account - GoGridLBMockHttp.type = 'UNEXPECTED_ERROR' - - try: - self.driver.create_balancer(name='test2', - port=80, - protocol='http', - algorithm=Algorithm.ROUND_ROBIN, - members=(Member(None, '10.1.0.10', 80), - Member(None, '10.1.0.11', 80)) - ) - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue( - str(e).find('tried to add a member with an IP address not assigned to your account') != -1) - else: - self.fail('Exception was not thrown') - - def test_destroy_balancer(self): - balancer = self.driver.list_balancers()[0] - - ret1 = self.driver.destroy_balancer(balancer) - ret2 = balancer.destroy() - - self.assertTrue(ret1) - self.assertTrue(ret2) - - def test_get_balancer(self): - balancer = self.driver.get_balancer(balancer_id='23530') - - self.assertEqual(balancer.name, 'test2') - self.assertEqual(balancer.id, '23530') - - def test_balancer_list_members(self): - balancer = self.driver.get_balancer(balancer_id='23530') - members1 = self.driver.balancer_list_members(balancer=balancer) - members2 = balancer.list_members() - - expected_members = set(['10.0.0.78:80', '10.0.0.77:80', - '10.0.0.76:80']) - - self.assertEqual(len(members1), 3) - self.assertEqual(len(members2), 3) - self.assertEqual(expected_members, - set(["%s:%s" % (member.ip, member.port) for member in members1])) - self.assertEquals(members1[0].balancer, balancer) - - def test_balancer_attach_compute_node(self): - balancer = LoadBalancer(23530, None, None, None, None, self.driver) - node = Node(id='1', name='test', state=None, public_ips=['10.0.0.75'], - private_ips=[], driver=DummyNodeDriver) - member1 = self.driver.balancer_attach_compute_node(balancer, node) - member2 = balancer.attach_compute_node(node) - - self.assertEqual(member1.ip, '10.0.0.75') - self.assertEqual(member1.port, 80) - self.assertEqual(member2.ip, '10.0.0.75') - self.assertEqual(member2.port, 80) - - def test_balancer_attach_member(self): - balancer = LoadBalancer(23530, None, None, None, None, self.driver) - member = Member(None, ip='10.0.0.75', port='80') - member1 = self.driver.balancer_attach_member(balancer, member=member) - member2 = balancer.attach_member(member=member) - - self.assertEqual(member1.ip, '10.0.0.75') - self.assertEqual(member1.port, 80) - self.assertEqual(member2.ip, '10.0.0.75') - self.assertEqual(member2.port, 80) - - def test_balancer_detach_member(self): - balancer = LoadBalancer(23530, None, None, None, None, self.driver) - member = self.driver.balancer_list_members(balancer)[0] - - ret1 = self.driver.balancer_detach_member(balancer, member) - ret2 = balancer.detach_member(member) - - self.assertTrue(ret1) - self.assertTrue(ret2) - - -class GoGridLBMockHttp(MockHttpTestCase): - fixtures = LoadBalancerFileFixtures('gogrid') - - def _api_grid_loadbalancer_list(self, method, url, body, headers): - body = self.fixtures.load('loadbalancer_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_ip_list(self, method, url, body, headers): - body = self.fixtures.load('ip_list.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_loadbalancer_add(self, method, url, body, headers): - query = urlparse.urlparse(url).query - self.assertTrue(query.find('loadbalancer.type=round+robin') != -1) - - body = self.fixtures.load('loadbalancer_add.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_ip_list_UNEXPECTED_ERROR(self, method, url, body, headers): - return self._api_grid_ip_list(method, url, body, headers) - - def _api_grid_loadbalancer_add_UNEXPECTED_ERROR(self, method, url, body, headers): - body = self.fixtures.load('unexpected_error.json') - return (httplib.INTERNAL_SERVER_ERROR, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_loadbalancer_delete(self, method, url, body, headers): - body = self.fixtures.load('loadbalancer_add.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_loadbalancer_get(self, method, url, body, headers): - body = self.fixtures.load('loadbalancer_get.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _api_grid_loadbalancer_edit(self, method, url, body, headers): - body = self.fixtures.load('loadbalancer_edit.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - -if __name__ == "__main__": - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/test_ninefold.py b/awx/lib/site-packages/libcloud/test/loadbalancer/test_ninefold.py deleted file mode 100644 index c3c514ff43..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/test_ninefold.py +++ /dev/null @@ -1,15 +0,0 @@ -import sys -import unittest - -from libcloud.loadbalancer.types import Provider -from libcloud.loadbalancer.providers import get_driver - - -class NinefoldLbTestCase(unittest.TestCase): - def test_driver_instantiation(self): - cls = get_driver(Provider.NINEFOLD) - cls('username', 'key') - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/loadbalancer/test_rackspace.py b/awx/lib/site-packages/libcloud/test/loadbalancer/test_rackspace.py deleted file mode 100644 index 5d6a0cfbfb..0000000000 --- a/awx/lib/site-packages/libcloud/test/loadbalancer/test_rackspace.py +++ /dev/null @@ -1,1511 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import datetime - -try: - import simplejson as json -except ImportError: - import json - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlencode - -from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm -from libcloud.loadbalancer.types import MemberCondition -from libcloud.loadbalancer.drivers.rackspace import RackspaceLBDriver, \ - RackspaceHealthMonitor, RackspaceHTTPHealthMonitor, \ - RackspaceConnectionThrottle, RackspaceAccessRule -from libcloud.loadbalancer.drivers.rackspace import RackspaceUKLBDriver -from libcloud.loadbalancer.drivers.rackspace import RackspaceAccessRuleType -from libcloud.common.types import LibcloudError - -from libcloud.test import unittest -from libcloud.test import MockHttpTestCase -from libcloud.test.file_fixtures import LoadBalancerFileFixtures -from libcloud.test.file_fixtures import OpenStackFixtures - - -class RackspaceLBTests(unittest.TestCase): - - def setUp(self): - RackspaceLBDriver.connectionCls.conn_classes = (None, - RackspaceLBMockHttp) - RackspaceLBMockHttp.type = None - self.driver = RackspaceLBDriver('user', 'key') - self.driver.connection.poll_interval = 0.0 - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - - def test_force_auth_token_kwargs(self): - base_url = 'https://ord.loadbalancer.api.rackspacecloud.com/v1.0/11111' - kwargs = { - 'ex_force_auth_token': 'some-auth-token', - 'ex_force_base_url': base_url - } - driver = RackspaceLBDriver('user', 'key', **kwargs) - driver.list_balancers() - - self.assertEqual(kwargs['ex_force_auth_token'], - driver.connection.auth_token) - self.assertEqual('/v1.0/11111', - driver.connection.request_path) - - def test_force_auth_url_kwargs(self): - kwargs = { - 'ex_force_auth_version': '2.0', - 'ex_force_auth_url': 'https://identity.api.rackspace.com' - } - driver = RackspaceLBDriver('user', 'key', **kwargs) - - self.assertEqual(kwargs['ex_force_auth_url'], - driver.connection._ex_force_auth_url) - self.assertEqual(kwargs['ex_force_auth_version'], - driver.connection._auth_version) - - def test_gets_auth_2_0_endpoint_defaults_to_ord_region(self): - driver = RackspaceLBDriver('user', 'key', - ex_force_auth_version='2.0_password' - ) - driver.connection._populate_hosts_and_request_paths() - - self.assertEqual( - 'https://ord.loadbalancers.api.rackspacecloud.com/v1.0/11111', - driver.connection.get_endpoint()) - - def test_gets_auth_2_0_endpoint_for_dfw(self): - driver = RackspaceLBDriver('user', 'key', - ex_force_auth_version='2.0_password', - ex_force_region='dfw' - ) - driver.connection._populate_hosts_and_request_paths() - - self.assertEqual( - 'https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/11111', - driver.connection.get_endpoint()) - - def test_list_protocols(self): - protocols = self.driver.list_protocols() - - self.assertEqual(len(protocols), 10) - self.assertTrue('http' in protocols) - - def test_ex_list_protocols_with_default_ports(self): - protocols = self.driver.ex_list_protocols_with_default_ports() - - self.assertEqual(len(protocols), 10) - self.assertTrue(('http', 80) in protocols) - - def test_list_supported_algorithms(self): - algorithms = self.driver.list_supported_algorithms() - - self.assertTrue(Algorithm.RANDOM in algorithms) - self.assertTrue(Algorithm.ROUND_ROBIN in algorithms) - self.assertTrue(Algorithm.LEAST_CONNECTIONS in algorithms) - self.assertTrue(Algorithm.WEIGHTED_ROUND_ROBIN in algorithms) - self.assertTrue(Algorithm.WEIGHTED_LEAST_CONNECTIONS in algorithms) - - def test_ex_list_algorithms(self): - algorithms = self.driver.ex_list_algorithm_names() - - self.assertTrue("RANDOM" in algorithms) - self.assertTrue("ROUND_ROBIN" in algorithms) - self.assertTrue("LEAST_CONNECTIONS" in algorithms) - self.assertTrue("WEIGHTED_ROUND_ROBIN" in algorithms) - self.assertTrue("WEIGHTED_LEAST_CONNECTIONS" in algorithms) - - def test_list_balancers(self): - balancers = self.driver.list_balancers() - - self.assertEqual(len(balancers), 2) - self.assertEqual(balancers[0].name, "test0") - self.assertEqual(balancers[0].id, "8155") - self.assertEqual(balancers[0].port, 80) - self.assertEqual(balancers[0].ip, "1.1.1.25") - self.assertEqual(balancers[1].name, "test1") - self.assertEqual(balancers[1].id, "8156") - - def test_list_balancers_ex_member_address(self): - RackspaceLBMockHttp.type = 'EX_MEMBER_ADDRESS' - balancers = self.driver.list_balancers(ex_member_address='127.0.0.1') - - self.assertEqual(len(balancers), 3) - self.assertEqual(balancers[0].name, "First Loadbalancer") - self.assertEqual(balancers[0].id, "1") - self.assertEqual(balancers[1].name, "Second Loadbalancer") - self.assertEqual(balancers[1].id, "2") - self.assertEqual(balancers[2].name, "Third Loadbalancer") - self.assertEqual(balancers[2].id, "8") - - def test_create_balancer(self): - balancer = self.driver.create_balancer(name='test2', - port=80, - algorithm=Algorithm.ROUND_ROBIN, - members=( - Member( - None, '10.1.0.10', 80, - extra={'condition': MemberCondition.DISABLED, - 'weight': 10}), - Member(None, '10.1.0.11', 80)) - ) - - self.assertEqual(balancer.name, 'test2') - self.assertEqual(balancer.id, '8290') - - def test_ex_create_balancer(self): - RackspaceLBDriver.connectionCls.conn_classes = (None, - RackspaceLBWithVIPMockHttp) - RackspaceLBMockHttp.type = None - driver = RackspaceLBDriver('user', 'key') - balancer = driver.ex_create_balancer(name='test2', - port=80, - algorithm=Algorithm.ROUND_ROBIN, - members=( - Member( - None, '10.1.0.11', 80),), - vip='12af' - ) - - self.assertEqual(balancer.name, 'test2') - self.assertEqual(balancer.id, '8290') - - def test_destroy_balancer(self): - balancer = self.driver.list_balancers()[0] - - ret = self.driver.destroy_balancer(balancer) - self.assertTrue(ret) - - def test_ex_destroy_balancers(self): - balancers = self.driver.list_balancers() - ret = self.driver.ex_destroy_balancers(balancers) - self.assertTrue(ret) - - def test_get_balancer(self): - balancer = self.driver.get_balancer(balancer_id='8290') - - self.assertEqual(balancer.name, 'test2') - self.assertEqual(balancer.id, '8290') - - def test_get_balancer_extra_vips(self): - balancer = self.driver.get_balancer(balancer_id='18940') - self.assertEqual(balancer.extra["virtualIps"], - [{"address": "50.56.49.149", - "id": 2359, - "type": "PUBLIC", - "ipVersion": "IPV4"}]) - - def test_get_balancer_extra_public_source_ipv4(self): - balancer = self.driver.get_balancer(balancer_id='18940') - self.assertEqual(balancer.extra["ipv4PublicSource"], '184.106.100.25') - - def test_get_balancer_extra_public_source_ipv6(self): - balancer = self.driver.get_balancer(balancer_id='18940') - self.assertEqual(balancer.extra["ipv6PublicSource"], - '2001:4801:7901::6/64') - - def test_get_balancer_extra_private_source_ipv4(self): - balancer = self.driver.get_balancer(balancer_id='18940') - self.assertEqual(balancer.extra["ipv4PrivateSource"], '10.183.252.25') - - def test_get_balancer_extra_members(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = balancer.extra['members'] - self.assertEqual(3, len(members)) - self.assertEqual('10.1.0.11', members[0].ip) - self.assertEqual('10.1.0.10', members[1].ip) - self.assertEqual('10.1.0.9', members[2].ip) - - def test_get_balancer_extra_created(self): - balancer = self.driver.get_balancer(balancer_id='8290') - - created_8290 = datetime.datetime(2011, 4, 7, 16, 27, 50) - self.assertEqual(created_8290, balancer.extra['created']) - - def test_get_balancer_extra_updated(self): - balancer = self.driver.get_balancer(balancer_id='8290') - - updated_8290 = datetime.datetime(2011, 4, 7, 16, 28, 12) - self.assertEqual(updated_8290, balancer.extra['updated']) - - def test_get_balancer_extra_access_list(self): - balancer = self.driver.get_balancer(balancer_id='94698') - - access_list = balancer.extra['accessList'] - - self.assertEqual(3, len(access_list)) - self.assertEqual(2883, access_list[0].id) - self.assertEqual("0.0.0.0/0", access_list[0].address) - self.assertEqual(RackspaceAccessRuleType.DENY, - access_list[0].rule_type) - - self.assertEqual(2884, access_list[1].id) - self.assertEqual("2001:4801:7901::6/64", - access_list[1].address) - self.assertEqual(RackspaceAccessRuleType.ALLOW, - access_list[1].rule_type) - - self.assertEqual(3006, access_list[2].id) - self.assertEqual("8.8.8.8/0", access_list[2].address) - self.assertEqual(RackspaceAccessRuleType.DENY, - access_list[2].rule_type) - - def test_get_balancer_algorithm(self): - balancer = self.driver.get_balancer(balancer_id='8290') - self.assertEqual(balancer.extra["algorithm"], Algorithm.RANDOM) - - def test_get_balancer_protocol(self): - balancer = self.driver.get_balancer(balancer_id='94695') - self.assertEqual(balancer.extra['protocol'], 'HTTP') - - def test_get_balancer_weighted_round_robin_algorithm(self): - balancer = self.driver.get_balancer(balancer_id='94692') - self.assertEqual(balancer.extra["algorithm"], - Algorithm.WEIGHTED_ROUND_ROBIN) - - def test_get_balancer_weighted_least_connections_algorithm(self): - balancer = self.driver.get_balancer(balancer_id='94693') - self.assertEqual(balancer.extra["algorithm"], - Algorithm.WEIGHTED_LEAST_CONNECTIONS) - - def test_get_balancer_unknown_algorithm(self): - balancer = self.driver.get_balancer(balancer_id='94694') - self.assertFalse('algorithm' in balancer.extra) - - def test_get_balancer_connect_health_monitor(self): - balancer = self.driver.get_balancer(balancer_id='94695') - balancer_health_monitor = balancer.extra["healthMonitor"] - - self.assertEqual(balancer_health_monitor.type, "CONNECT") - self.assertEqual(balancer_health_monitor.delay, 10) - self.assertEqual(balancer_health_monitor.timeout, 5) - self.assertEqual(balancer_health_monitor.attempts_before_deactivation, - 2) - - def test_get_balancer_http_health_monitor(self): - balancer = self.driver.get_balancer(balancer_id='94696') - balancer_health_monitor = balancer.extra["healthMonitor"] - - self.assertEqual(balancer_health_monitor.type, "HTTP") - self.assertEqual(balancer_health_monitor.delay, 10) - self.assertEqual(balancer_health_monitor.timeout, 5) - self.assertEqual(balancer_health_monitor.attempts_before_deactivation, - 2) - self.assertEqual(balancer_health_monitor.path, "/") - self.assertEqual(balancer_health_monitor.status_regex, - "^[234][0-9][0-9]$") - self.assertEqual(balancer_health_monitor.body_regex, - "Hello World!") - - def test_get_balancer_https_health_monitor(self): - balancer = self.driver.get_balancer(balancer_id='94697') - balancer_health_monitor = balancer.extra["healthMonitor"] - - self.assertEqual(balancer_health_monitor.type, "HTTPS") - self.assertEqual(balancer_health_monitor.delay, 15) - self.assertEqual(balancer_health_monitor.timeout, 12) - self.assertEqual(balancer_health_monitor.attempts_before_deactivation, - 5) - self.assertEqual(balancer_health_monitor.path, "/test") - self.assertEqual(balancer_health_monitor.status_regex, - "^[234][0-9][0-9]$") - self.assertEqual(balancer_health_monitor.body_regex, "abcdef") - - def test_get_balancer_connection_throttle(self): - balancer = self.driver.get_balancer(balancer_id='94695') - balancer_connection_throttle = balancer.extra["connectionThrottle"] - - self.assertEqual(balancer_connection_throttle.min_connections, 50) - self.assertEqual(balancer_connection_throttle.max_connections, 200) - self.assertEqual(balancer_connection_throttle.max_connection_rate, 50) - self.assertEqual(balancer_connection_throttle.rate_interval_seconds, - 10) - - def test_get_session_persistence(self): - balancer = self.driver.get_balancer(balancer_id='94695') - self.assertEqual(balancer.extra["sessionPersistenceType"], - "HTTP_COOKIE") - - def test_get_connection_logging(self): - balancer = self.driver.get_balancer(balancer_id='94695') - self.assertEqual(balancer.extra["connectionLoggingEnabled"], True) - - def test_get_error_page(self): - balancer = self.driver.get_balancer(balancer_id='18940') - error_page = self.driver.ex_get_balancer_error_page(balancer) - self.assertTrue("The service is temporarily unavailable" in error_page) - - def test_get_access_list(self): - balancer = self.driver.get_balancer(balancer_id='18940') - deny_rule, allow_rule = self.driver.ex_balancer_access_list(balancer) - - self.assertEqual(deny_rule.id, 2883) - self.assertEqual(deny_rule.rule_type, RackspaceAccessRuleType.DENY) - self.assertEqual(deny_rule.address, "0.0.0.0/0") - - self.assertEqual(allow_rule.id, 2884) - self.assertEqual(allow_rule.address, "2001:4801:7901::6/64") - self.assertEqual(allow_rule.rule_type, RackspaceAccessRuleType.ALLOW) - - def test_ex_create_balancer_access_rule(self): - balancer = self.driver.get_balancer(balancer_id='94698') - - rule = RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, - address='0.0.0.0/0') - - rule = self.driver.ex_create_balancer_access_rule(balancer, rule) - - self.assertEqual(2883, rule.id) - - def test_ex_create_balancer_access_rule_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94698') - - rule = RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, - address='0.0.0.0/0') - - resp = self.driver.ex_create_balancer_access_rule_no_poll(balancer, - rule) - - self.assertTrue(resp) - - def test_ex_create_balancer_access_rules(self): - balancer = self.driver.get_balancer(balancer_id='94699') - - rules = [RackspaceAccessRule(rule_type=RackspaceAccessRuleType.ALLOW, - address='2001:4801:7901::6/64'), - RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, - address='8.8.8.8/0')] - - rules = self.driver.ex_create_balancer_access_rules(balancer, rules) - - self.assertEqual(2, len(rules)) - self.assertEqual(2884, rules[0].id) - self.assertEqual(3006, rules[1].id) - - def test_ex_create_balancer_access_rules_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94699') - - rules = [RackspaceAccessRule(rule_type=RackspaceAccessRuleType.ALLOW, - address='2001:4801:7901::6/64'), - RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, - address='8.8.8.8/0')] - - resp = self.driver.ex_create_balancer_access_rules_no_poll(balancer, - rules) - - self.assertTrue(resp) - - def test_ex_destroy_balancer_access_rule(self): - balancer = self.driver.get_balancer(balancer_id='94698') - - rule = RackspaceAccessRule(id='1007', - rule_type=RackspaceAccessRuleType.ALLOW, - address="10.45.13.5/12" - ) - - balancer = self.driver.ex_destroy_balancer_access_rule(balancer, rule) - - rule_ids = [r.id for r in balancer.extra['accessList']] - - self.assertTrue(1007 not in rule_ids) - - def test_ex_destroy_balancer_access_rule_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94698') - - rule = RackspaceAccessRule(id=1007, - rule_type=RackspaceAccessRuleType.ALLOW, - address="10.45.13.5/12" - ) - - resp = self.driver.ex_destroy_balancer_access_rule_no_poll(balancer, - rule) - - self.assertTrue(resp) - - def test_ex_destroy_balancer_access_rules(self): - balancer = self.driver.get_balancer(balancer_id='94699') - balancer = self.driver.ex_destroy_balancer_access_rules(balancer, - balancer.extra['accessList']) - - self.assertEqual('94699', balancer.id) - - def test_ex_destroy_balancer_access_rules_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94699') - - resp = self.driver.ex_destroy_balancer_access_rules_no_poll(balancer, - balancer.extra['accessList']) - - self.assertTrue(resp) - - def test_ex_update_balancer_health_monitor(self): - balancer = self.driver.get_balancer(balancer_id='94695') - monitor = RackspaceHealthMonitor(type='CONNECT', delay=10, timeout=5, - attempts_before_deactivation=2) - - balancer = self.driver.ex_update_balancer_health_monitor( - balancer, monitor) - updated_monitor = balancer.extra['healthMonitor'] - - self.assertEqual('CONNECT', updated_monitor.type) - self.assertEqual(10, updated_monitor.delay) - self.assertEqual(5, updated_monitor.timeout) - self.assertEqual(2, updated_monitor.attempts_before_deactivation) - - def test_ex_update_balancer_http_health_monitor(self): - balancer = self.driver.get_balancer(balancer_id='94696') - monitor = RackspaceHTTPHealthMonitor(type='HTTP', delay=10, timeout=5, - attempts_before_deactivation=2, - path='/', - status_regex='^[234][0-9][0-9]$', - body_regex='Hello World!') - - balancer = self.driver.ex_update_balancer_health_monitor( - balancer, monitor) - updated_monitor = balancer.extra['healthMonitor'] - - self.assertEqual('HTTP', updated_monitor.type) - self.assertEqual(10, updated_monitor.delay) - self.assertEqual(5, updated_monitor.timeout) - self.assertEqual(2, updated_monitor.attempts_before_deactivation) - self.assertEqual('/', updated_monitor.path) - self.assertEqual('^[234][0-9][0-9]$', updated_monitor.status_regex) - self.assertEqual('Hello World!', updated_monitor.body_regex) - - def test_ex_update_balancer_health_monitor_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94695') - monitor = RackspaceHealthMonitor(type='CONNECT', delay=10, timeout=5, - attempts_before_deactivation=2) - - resp = self.driver.ex_update_balancer_health_monitor_no_poll(balancer, - monitor) - - self.assertTrue(resp) - - def test_ex_update_balancer_http_health_monitor_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94696') - monitor = RackspaceHTTPHealthMonitor(type='HTTP', delay=10, timeout=5, - attempts_before_deactivation=2, - path='/', - status_regex='^[234][0-9][0-9]$', - body_regex='Hello World!') - - resp = self.driver.ex_update_balancer_health_monitor_no_poll(balancer, - monitor) - - self.assertTrue(resp) - - def test_ex_update_balancer_http_health_monitor_with_no_option_body_regex(self): - balancer = self.driver.get_balancer(balancer_id='94700') - monitor = RackspaceHTTPHealthMonitor(type='HTTP', delay=10, timeout=5, - attempts_before_deactivation=2, - path='/', - status_regex='^[234][0-9][0-9]$', - body_regex='') - - balancer = self.driver.ex_update_balancer_health_monitor( - balancer, monitor) - updated_monitor = balancer.extra['healthMonitor'] - - self.assertEqual('HTTP', updated_monitor.type) - self.assertEqual(10, updated_monitor.delay) - self.assertEqual(5, updated_monitor.timeout) - self.assertEqual(2, updated_monitor.attempts_before_deactivation) - self.assertEqual('/', updated_monitor.path) - self.assertEqual('^[234][0-9][0-9]$', updated_monitor.status_regex) - self.assertEqual('', updated_monitor.body_regex) - - def test_ex_disable_balancer_health_monitor(self): - balancer = self.driver.get_balancer(balancer_id='8290') - balancer = self.driver.ex_disable_balancer_health_monitor(balancer) - - self.assertTrue('healthMonitor' not in balancer.extra) - - def test_ex_disable_balancer_health_monitor_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='8290') - resp = self.driver.ex_disable_balancer_health_monitor_no_poll(balancer) - - self.assertTrue(resp) - - def test_ex_update_balancer_connection_throttle(self): - balancer = self.driver.get_balancer(balancer_id='94695') - connection_throttle = RackspaceConnectionThrottle(max_connections=200, - min_connections=50, - max_connection_rate=50, - rate_interval_seconds=10) - - balancer = self.driver.ex_update_balancer_connection_throttle(balancer, - connection_throttle) - updated_throttle = balancer.extra['connectionThrottle'] - - self.assertEqual(200, updated_throttle.max_connections) - self.assertEqual(50, updated_throttle.min_connections) - self.assertEqual(50, updated_throttle.max_connection_rate) - self.assertEqual(10, updated_throttle.rate_interval_seconds) - - def test_ex_update_balancer_connection_throttle_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94695') - connection_throttle = RackspaceConnectionThrottle(max_connections=200, - min_connections=50, - max_connection_rate=50, - rate_interval_seconds=10) - - resp = self.driver.ex_update_balancer_connection_throttle_no_poll( - balancer, connection_throttle) - - self.assertTrue(resp) - - def test_ex_disable_balancer_connection_throttle(self): - balancer = self.driver.get_balancer(balancer_id='8290') - balancer = self.driver.ex_disable_balancer_connection_throttle( - balancer) - - self.assertTrue('connectionThrottle' not in balancer.extra) - - def test_ex_disable_balancer_connection_throttle_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='8290') - resp = self.driver.ex_disable_balancer_connection_throttle_no_poll( - balancer) - - self.assertTrue(resp) - - def test_ex_enable_balancer_connection_logging(self): - balancer = self.driver.get_balancer(balancer_id='94695') - balancer = self.driver.ex_enable_balancer_connection_logging( - balancer) - - self.assertTrue(balancer.extra["connectionLoggingEnabled"]) - - def test_ex_enable_balancer_connection_logging_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94695') - resp = self.driver.ex_enable_balancer_connection_logging_no_poll( - balancer) - - self.assertTrue(resp) - - def test_ex_disable_balancer_connection_logging(self): - balancer = self.driver.get_balancer(balancer_id='8290') - balancer = self.driver.ex_disable_balancer_connection_logging( - balancer - ) - - self.assertFalse(balancer.extra["connectionLoggingEnabled"]) - - def test_ex_disable_balancer_connection_logging_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='8290') - resp = self.driver.ex_disable_balancer_connection_logging_no_poll( - balancer - ) - - self.assertTrue(resp) - - def test_ex_enable_balancer_session_persistence(self): - balancer = self.driver.get_balancer(balancer_id='94695') - balancer = self.driver.ex_enable_balancer_session_persistence(balancer) - - persistence_type = balancer.extra['sessionPersistenceType'] - self.assertEqual('HTTP_COOKIE', persistence_type) - - def test_ex_enable_balancer_session_persistence_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94695') - resp = self.driver.ex_enable_balancer_session_persistence_no_poll( - balancer) - - self.assertTrue(resp) - - def test_disable_balancer_session_persistence(self): - balancer = self.driver.get_balancer(balancer_id='8290') - balancer = self.driver.ex_disable_balancer_session_persistence( - balancer) - - self.assertTrue('sessionPersistenceType' not in balancer.extra) - - def test_disable_balancer_session_persistence_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='8290') - resp = self.driver.ex_disable_balancer_session_persistence_no_poll( - balancer) - - self.assertTrue(resp) - - def test_ex_update_balancer_error_page(self): - balancer = self.driver.get_balancer(balancer_id='8290') - content = "Generic Error Page" - balancer = self.driver.ex_update_balancer_error_page( - balancer, content) - - error_page_content = self.driver.ex_get_balancer_error_page(balancer) - self.assertEqual(content, error_page_content) - - def test_ex_update_balancer_error_page_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='8290') - content = "Generic Error Page" - resp = self.driver.ex_update_balancer_error_page_no_poll( - balancer, content) - - self.assertTrue(resp) - - def test_ex_disable_balancer_custom_error_page_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='94695') - resp = self.driver.ex_disable_balancer_custom_error_page_no_poll( - balancer) - - self.assertTrue(resp) - - def test_ex_disable_balancer_custom_error_page(self): - fixtures = LoadBalancerFileFixtures('rackspace') - error_page_fixture = json.loads( - fixtures.load('error_page_default.json')) - - default_error_page = error_page_fixture['errorpage']['content'] - - balancer = self.driver.get_balancer(balancer_id='94695') - balancer = self.driver.ex_disable_balancer_custom_error_page(balancer) - - error_page_content = self.driver.ex_get_balancer_error_page(balancer) - self.assertEqual(default_error_page, error_page_content) - - def test_balancer_list_members(self): - expected = set(['10.1.0.10:80', '10.1.0.11:80', '10.1.0.9:8080']) - balancer = self.driver.get_balancer(balancer_id='8290') - members = balancer.list_members() - - self.assertEqual(len(members), 3) - self.assertEqual(members[0].balancer, balancer) - self.assertEqual(expected, set(["%s:%s" % (member.ip, member.port) for - member in members])) - - def test_balancer_members_extra_weight(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = balancer.list_members() - - self.assertEqual(12, members[0].extra['weight']) - self.assertEqual(8, members[1].extra['weight']) - - def test_balancer_members_extra_condition(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = balancer.list_members() - - self.assertEqual(MemberCondition.ENABLED, - members[0].extra['condition']) - self.assertEqual(MemberCondition.DISABLED, - members[1].extra['condition']) - self.assertEqual(MemberCondition.DRAINING, - members[2].extra['condition']) - - def test_balancer_members_extra_status(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = balancer.list_members() - - self.assertEqual('ONLINE', members[0].extra['status']) - self.assertEqual('OFFLINE', members[1].extra['status']) - self.assertEqual('DRAINING', members[2].extra['status']) - - def test_balancer_attach_member(self): - balancer = self.driver.get_balancer(balancer_id='8290') - extra = {'condition': MemberCondition.DISABLED, - 'weight': 10} - member = balancer.attach_member(Member(None, ip='10.1.0.12', - port='80', extra=extra)) - - self.assertEqual(member.ip, '10.1.0.12') - self.assertEqual(member.port, 80) - - def test_balancer_attach_member_with_no_condition_specified(self): - balancer = self.driver.get_balancer(balancer_id='8291') - member = balancer.attach_member(Member(None, ip='10.1.0.12', - port='80')) - - self.assertEqual(member.ip, '10.1.0.12') - self.assertEqual(member.port, 80) - - def test_balancer_attach_members(self): - balancer = self.driver.get_balancer(balancer_id='8292') - members = [Member(None, ip='10.1.0.12', port='80'), - Member(None, ip='10.1.0.13', port='80')] - - attached_members = self.driver.ex_balancer_attach_members(balancer, - members) - - first_member = attached_members[0] - second_member = attached_members[1] - self.assertEqual(first_member.ip, '10.1.0.12') - self.assertEqual(first_member.port, 80) - self.assertEqual(second_member.ip, '10.1.0.13') - self.assertEqual(second_member.port, 80) - - def test_balancer_detach_member(self): - balancer = self.driver.get_balancer(balancer_id='8290') - member = balancer.list_members()[0] - - ret = balancer.detach_member(member) - self.assertTrue(ret) - - def test_ex_detach_members(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = balancer.list_members() - - balancer = self.driver.ex_balancer_detach_members(balancer, members) - - self.assertEqual('8290', balancer.id) - - def test_ex_detach_members_no_poll(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = balancer.list_members() - - ret = self.driver.ex_balancer_detach_members_no_poll(balancer, members) - self.assertTrue(ret) - - def test_update_balancer_protocol(self): - balancer = LoadBalancer(id='3130', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - updated_balancer = self.driver.update_balancer( - balancer, protocol='HTTPS') - self.assertEqual('HTTPS', updated_balancer.extra['protocol']) - - def test_update_balancer_protocol_to_imapv2(self): - balancer = LoadBalancer(id='3135', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - updated_balancer = self.driver.update_balancer( - balancer, protocol='imapv2') - self.assertEqual('IMAPv2', updated_balancer.extra['protocol']) - - def test_update_balancer_protocol_to_imapv3(self): - balancer = LoadBalancer(id='3136', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - updated_balancer = self.driver.update_balancer( - balancer, protocol='IMAPV3') - self.assertEqual('IMAPv3', updated_balancer.extra['protocol']) - - def test_update_balancer_protocol_to_imapv4(self): - balancer = LoadBalancer(id='3137', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - updated_balancer = self.driver.update_balancer( - balancer, protocol='IMAPv4') - self.assertEqual('IMAPv4', updated_balancer.extra['protocol']) - - def test_update_balancer_port(self): - balancer = LoadBalancer(id='3131', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - updated_balancer = self.driver.update_balancer(balancer, port=1337) - self.assertEqual(1337, updated_balancer.port) - - def test_update_balancer_name(self): - balancer = LoadBalancer(id='3132', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - updated_balancer = self.driver.update_balancer( - balancer, name='new_lb_name') - self.assertEqual('new_lb_name', updated_balancer.name) - - def test_update_balancer_algorithm(self): - balancer = LoadBalancer(id='3133', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - updated_balancer = self.driver.update_balancer(balancer, - algorithm=Algorithm.ROUND_ROBIN) - self.assertEqual( - Algorithm.ROUND_ROBIN, updated_balancer.extra['algorithm']) - - def test_update_balancer_bad_algorithm_exception(self): - balancer = LoadBalancer(id='3134', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - try: - self.driver.update_balancer(balancer, - algorithm='HAVE_MERCY_ON_OUR_SERVERS') - except LibcloudError: - pass - else: - self.fail( - 'Should have thrown an exception with bad algorithm value') - - def test_ex_update_balancer_no_poll_protocol(self): - balancer = LoadBalancer(id='3130', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - action_succeeded = self.driver.ex_update_balancer_no_poll( - balancer, - protocol='HTTPS') - self.assertTrue(action_succeeded) - - def test_ex_update_balancer_no_poll_port(self): - balancer = LoadBalancer(id='3131', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - action_succeeded = self.driver.ex_update_balancer_no_poll( - balancer, - port=1337) - self.assertTrue(action_succeeded) - - def test_ex_update_balancer_no_poll_name(self): - balancer = LoadBalancer(id='3132', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - - action_succeeded = self.driver.ex_update_balancer_no_poll( - balancer, - name='new_lb_name') - self.assertTrue(action_succeeded) - - def test_ex_update_balancer_no_poll_algorithm(self): - balancer = LoadBalancer(id='3133', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - action_succeeded = self.driver.ex_update_balancer_no_poll(balancer, - algorithm=Algorithm.ROUND_ROBIN) - self.assertTrue(action_succeeded) - - def test_ex_update_balancer_no_poll_bad_algorithm_exception(self): - balancer = LoadBalancer(id='3134', name='LB_update', - state='PENDING_UPDATE', ip='10.34.4.3', - port=80, driver=self.driver) - try: - self.driver.update_balancer(balancer, - algorithm='HAVE_MERCY_ON_OUR_SERVERS') - except LibcloudError: - pass - else: - self.fail('Should have thrown exception with bad algorithm value') - - def test_ex_update_balancer_member_extra_attributes(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = self.driver.balancer_list_members(balancer) - - first_member = members[0] - - member = self.driver.ex_balancer_update_member(balancer, first_member, - condition=MemberCondition.ENABLED, weight=12) - - self.assertEqual(MemberCondition.ENABLED, member.extra['condition']) - self.assertEqual(12, member.extra['weight']) - - def test_ex_update_balancer_member_no_poll_extra_attributes(self): - balancer = self.driver.get_balancer(balancer_id='8290') - members = self.driver.balancer_list_members(balancer) - - first_member = members[0] - - resp = self.driver.ex_balancer_update_member_no_poll( - balancer, first_member, - condition=MemberCondition.ENABLED, weight=12) - self.assertTrue(resp) - - def test_ex_list_current_usage(self): - balancer = self.driver.get_balancer(balancer_id='8290') - usage = self.driver.ex_list_current_usage(balancer=balancer) - self.assertEqual( - usage['loadBalancerUsageRecords'][0]['incomingTransferSsl'], - 6182163) - - -class RackspaceUKLBTests(RackspaceLBTests): - - def setUp(self): - RackspaceLBDriver.connectionCls.conn_classes = (None, - RackspaceLBMockHttp) - RackspaceLBMockHttp.type = None - self.driver = RackspaceUKLBDriver('user', 'key') - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - - -class RackspaceLBMockHttp(MockHttpTestCase): - fixtures = LoadBalancerFileFixtures('rackspace') - auth_fixtures = OpenStackFixtures() - - def _v2_0_tokens(self, method, url, body, headers): - body = self.fixtures.load('_v2_0__auth.json') - return (httplib.OK, body, headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_loadbalancers_protocols(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_loadbalancers_protocols.json') - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - def _v1_0_11111_loadbalancers_algorithms(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('v1_slug_loadbalancers_algorithms.json') - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('v1_slug_loadbalancers.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == "POST": - json_body = json.loads(body) - - loadbalancer_json = json_body['loadBalancer'] - member_1_json, member_2_json = loadbalancer_json['nodes'] - - self.assertEqual(loadbalancer_json['protocol'], 'HTTP') - self.assertEqual(loadbalancer_json['algorithm'], 'ROUND_ROBIN') - self.assertEqual(loadbalancer_json['virtualIps'][0]['type'], - 'PUBLIC') - self.assertEqual(member_1_json['condition'], 'DISABLED') - self.assertEqual(member_1_json['weight'], 10) - self.assertEqual(member_2_json['condition'], 'ENABLED') - - body = self.fixtures.load('v1_slug_loadbalancers_post.json') - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - elif method == 'DELETE': - balancers = self.fixtures.load('v1_slug_loadbalancers.json') - balancers_json = json.loads(balancers) - - for balancer in balancers_json['loadBalancers']: - id = balancer['id'] - self.assertTrue(urlencode([('id', id)]) in url, - msg='Did not delete balancer with id %d' % id) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_EX_MEMBER_ADDRESS(self, method, url, body, headers): - body = self.fixtures.load('v1_slug_loadbalancers_nodeaddress.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _v1_0_11111_loadbalancers_8155(self, method, url, body, headers): - if method == "DELETE": - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('v1_slug_loadbalancers_8290.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_nodes(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('v1_slug_loadbalancers_8290_nodes.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == "POST": - json_body = json.loads(body) - json_node = json_body['nodes'][0] - self.assertEqual('DISABLED', json_node['condition']) - self.assertEqual(10, json_node['weight']) - response_body = self.fixtures.load( - 'v1_slug_loadbalancers_8290_nodes_post.json') - return (httplib.ACCEPTED, response_body, {}, - httplib.responses[httplib.ACCEPTED]) - elif method == "DELETE": - nodes = self.fixtures.load('v1_slug_loadbalancers_8290_nodes.json') - json_nodes = json.loads(nodes) - - for node in json_nodes['nodes']: - id = node['id'] - self.assertTrue(urlencode([('id', id)]) in url, - msg='Did not delete member with id %d' % id) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8291(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('v1_slug_loadbalancers_8291.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8291_nodes(self, method, url, body, headers): - if method == "POST": - json_body = json.loads(body) - json_node = json_body['nodes'][0] - self.assertEqual('ENABLED', json_node['condition']) - response_body = self.fixtures.load( - 'v1_slug_loadbalancers_8290_nodes_post.json') - return (httplib.ACCEPTED, response_body, {}, - httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8292(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('v1_slug_loadbalancers_8292.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8292_nodes(self, method, url, body, headers): - if method == "POST": - json_body = json.loads(body) - json_node_1 = json_body['nodes'][0] - json_node_2 = json_body['nodes'][1] - self.assertEqual('10.1.0.12', json_node_1['address']) - self.assertEqual('10.1.0.13', json_node_2['address']) - response_body = self.fixtures.load( - 'v1_slug_loadbalancers_8292_nodes_post.json') - return (httplib.ACCEPTED, response_body, {}, - httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_nodes_30944(self, method, url, body, headers): - if method == "PUT": - json_body = json.loads(body) - self.assertEqual('ENABLED', json_body['condition']) - self.assertEqual(12, json_body['weight']) - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - elif method == "DELETE": - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_healthmonitor(self, method, url, body, headers): - if method == "DELETE": - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_connectionthrottle(self, method, url, body, headers): - if method == 'DELETE': - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_connectionlogging(self, method, url, body, headers): - # Connection Logging uses a PUT to disable connection logging - if method == 'PUT': - json_body = json.loads(body) - self.assertFalse(json_body["connectionLogging"]["enabled"]) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_sessionpersistence(self, method, url, body, headers): - if method == 'DELETE': - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_errorpage(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load( - 'v1_slug_loadbalancers_8290_errorpage.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == 'PUT': - json_body = json.loads(body) - - self.assertEqual('Generic Error Page', - json_body['errorpage']['content']) - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_18940(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_18940_ex_public_ips.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_18945(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_18945_ex_public_ips.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_18940_errorpage(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_18940_errorpage.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_18940_accesslist(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load( - 'v1_slug_loadbalancers_18940_accesslist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_18941(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_18941_ex_private_ips.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94692(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94692_weighted_round_robin.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94693(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94693_weighted_least_connections.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94694(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94694_unknown_algorithm.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94695(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94695_full_details.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94695_healthmonitor(self, method, url, body, headers): - if method == 'PUT': - json_body = json.loads(body) - - self.assertEqual('CONNECT', json_body['type']) - self.assertEqual(10, json_body['delay']) - self.assertEqual(5, json_body['timeout']) - self.assertEqual(2, json_body['attemptsBeforeDeactivation']) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94695_connectionthrottle(self, method, url, body, headers): - if method == 'PUT': - json_body = json.loads(body) - - self.assertEqual(50, json_body['minConnections']) - self.assertEqual(200, json_body['maxConnections']) - self.assertEqual(50, json_body['maxConnectionRate']) - self.assertEqual(10, json_body['rateInterval']) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94695_connectionlogging(self, method, url, body, headers): - if method == 'PUT': - json_body = json.loads(body) - - self.assertTrue(json_body["connectionLogging"]["enabled"]) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94695_sessionpersistence(self, method, url, body, headers): - if method == 'PUT': - json_body = json.loads(body) - - persistence_type = json_body[ - 'sessionPersistence']['persistenceType'] - self.assertEqual('HTTP_COOKIE', persistence_type) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94695_errorpage(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load("error_page_default.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == 'DELETE': - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94696(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94696_http_health_monitor.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94696_healthmonitor(self, method, url, body, headers): - if method == 'PUT': - json_body = json.loads(body) - - self.assertEqual('HTTP', json_body['type']) - self.assertEqual(10, json_body['delay']) - self.assertEqual(5, json_body['timeout']) - self.assertEqual(2, json_body['attemptsBeforeDeactivation']) - self.assertEqual('/', json_body['path']) - self.assertEqual('^[234][0-9][0-9]$', json_body['statusRegex']) - self.assertEqual('Hello World!', json_body['bodyRegex']) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94697(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94697_https_health_monitor.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94698(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94698_with_access_list.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94698_accesslist(self, method, url, body, headers): - if method == 'GET': - body = self.fixtures.load( - 'v1_slug_loadbalancers_94698_accesslist.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == 'POST': - json_body = json.loads(body) - - self.assertEqual('0.0.0.0/0', json_body['networkItem']['address']) - self.assertEqual('DENY', json_body['networkItem']['type']) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94699(self, method, url, body, headers): - if method == 'GET': - # Use the same fixture for batch deletes as for single deletes - body = self.fixtures.load( - 'v1_slug_loadbalancers_94698_with_access_list.json') - json_body = json.loads(body) - json_body['loadBalancer']['id'] = 94699 - - updated_body = json.dumps(json_body) - return (httplib.OK, updated_body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94699_accesslist(self, method, url, body, headers): - if method == 'DELETE': - fixture = 'v1_slug_loadbalancers_94698_with_access_list.json' - fixture_json = json.loads(self.fixtures.load(fixture)) - access_list_json = fixture_json['loadBalancer']['accessList'] - - for access_rule in access_list_json: - id = access_rule['id'] - self.assertTrue(urlencode([('id', id)]) in url, - msg='Did not delete access rule with id %d' % id) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - elif method == 'POST': - - json_body = json.loads(body) - access_list = json_body['accessList'] - self.assertEqual('ALLOW', access_list[0]['type']) - self.assertEqual('2001:4801:7901::6/64', access_list[0]['address']) - self.assertEqual('DENY', access_list[1]['type']) - self.assertEqual('8.8.8.8/0', access_list[1]['address']) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94698_accesslist_1007(self, method, url, body, headers): - if method == 'DELETE': - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94700(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load( - "v1_slug_loadbalancers_94700_http_health_monitor_no_body_regex.json") - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_94700_healthmonitor(self, method, url, body, headers): - if method == 'PUT': - json_body = json.loads(body) - - self.assertEqual('HTTP', json_body['type']) - self.assertEqual(10, json_body['delay']) - self.assertEqual(5, json_body['timeout']) - self.assertEqual(2, json_body['attemptsBeforeDeactivation']) - self.assertEqual('/', json_body['path']) - self.assertEqual('^[234][0-9][0-9]$', json_body['statusRegex']) - self.assertFalse('bodyRegex' in json_body) - - return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3130(self, method, url, body, headers): - """ update_balancer(b, protocol='HTTPS'), then get_balancer('3130') """ - if method == "PUT": - json_body = json.loads(body) - self.assertDictEqual(json_body, {'protocol': 'HTTPS'}) - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - elif method == "GET": - response_body = json.loads( - self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) - response_body['loadBalancer']['id'] = 3130 - response_body['loadBalancer']['protocol'] = 'HTTPS' - return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3131(self, method, url, body, headers): - """ update_balancer(b, port=443), then get_balancer('3131') """ - if method == "PUT": - json_body = json.loads(body) - self.assertDictEqual(json_body, {'port': 1337}) - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - elif method == "GET": - response_body = json.loads( - self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) - response_body['loadBalancer']['id'] = 3131 - response_body['loadBalancer']['port'] = 1337 - return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3132(self, method, url, body, headers): - """ update_balancer(b, name='new_lb_name'), then get_balancer('3132') """ - if method == "PUT": - json_body = json.loads(body) - self.assertDictEqual(json_body, {'name': 'new_lb_name'}) - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - elif method == "GET": - response_body = json.loads( - self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) - response_body['loadBalancer']['id'] = 3132 - response_body['loadBalancer']['name'] = 'new_lb_name' - return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3133(self, method, url, body, headers): - """ update_balancer(b, algorithm='ROUND_ROBIN'), then get_balancer('3133') """ - if method == "PUT": - json_body = json.loads(body) - self.assertDictEqual(json_body, {'algorithm': 'ROUND_ROBIN'}) - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - elif method == "GET": - response_body = json.loads( - self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) - response_body['loadBalancer']['id'] = 3133 - response_body['loadBalancer']['algorithm'] = 'ROUND_ROBIN' - return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3134(self, method, url, body, headers): - """ update.balancer(b, algorithm='HAVE_MERCY_ON_OUR_SERVERS') """ - if method == "PUT": - return (httplib.BAD_REQUEST, "", {}, httplib.responses[httplib.BAD_REQUEST]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3135(self, method, url, body, headers): - """ update_balancer(b, protocol='IMAPv3'), then get_balancer('3135') """ - if method == "PUT": - json_body = json.loads(body) - self.assertDictEqual(json_body, {'protocol': 'IMAPv2'}) - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - elif method == "GET": - response_body = json.loads( - self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) - response_body['loadBalancer']['id'] = 3135 - response_body['loadBalancer']['protocol'] = 'IMAPv2' - return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3136(self, method, url, body, headers): - """ update_balancer(b, protocol='IMAPv3'), then get_balancer('3136') """ - if method == "PUT": - json_body = json.loads(body) - self.assertDictEqual(json_body, {'protocol': 'IMAPv3'}) - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - elif method == "GET": - response_body = json.loads( - self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) - response_body['loadBalancer']['id'] = 3136 - response_body['loadBalancer']['protocol'] = 'IMAPv3' - return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_3137(self, method, url, body, headers): - """ update_balancer(b, protocol='IMAPv3'), then get_balancer('3137') """ - if method == "PUT": - json_body = json.loads(body) - self.assertDictEqual(json_body, {'protocol': 'IMAPv4'}) - return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) - elif method == "GET": - response_body = json.loads( - self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) - response_body['loadBalancer']['id'] = 3137 - response_body['loadBalancer']['protocol'] = 'IMAPv4' - return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - def _v1_0_11111_loadbalancers_8290_usage_current(self, method, url, body, - headers): - if method == 'GET': - body = self.fixtures.load( - 'v1_0_slug_loadbalancers_8290_usage_current.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - raise NotImplementedError - - -class RackspaceLBWithVIPMockHttp(MockHttpTestCase): - fixtures = LoadBalancerFileFixtures('rackspace') - auth_fixtures = OpenStackFixtures() - - def _v2_0_tokens(self, method, url, body, headers): - body = self.fixtures.load('_v2_0__auth.json') - return (httplib.OK, body, headers, - httplib.responses[httplib.OK]) - - def _v1_0_11111_loadbalancers(self, method, url, body, headers): - if method == "GET": - body = self.fixtures.load('v1_slug_loadbalancers.json') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - elif method == "POST": - json_body = json.loads(body) - loadbalancer_json = json_body['loadBalancer'] - - self.assertEqual(loadbalancer_json['virtualIps'][0]['id'], '12af') - - body = self.fixtures.load('v1_slug_loadbalancers_post.json') - return (httplib.ACCEPTED, body, {}, - httplib.responses[httplib.ACCEPTED]) - - raise NotImplementedError - -if __name__ == "__main__": - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/pricing_test.json b/awx/lib/site-packages/libcloud/test/pricing_test.json deleted file mode 100644 index 92778743a4..0000000000 --- a/awx/lib/site-packages/libcloud/test/pricing_test.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compute": { - "foo": { - "1": 1.00, - "2": 2.00 - } - }, - - "updated": 1309019791 -} diff --git a/awx/lib/site-packages/libcloud/test/secrets.py-dist b/awx/lib/site-packages/libcloud/test/secrets.py-dist deleted file mode 100644 index 030176e4c0..0000000000 --- a/awx/lib/site-packages/libcloud/test/secrets.py-dist +++ /dev/null @@ -1,67 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Make a copy of this file named 'secrets.py' and add your credentials there. -# Note you can run unit tests without setting your credentials. - -BLUEBOX_PARAMS = ('customer_id', 'api_key') -BRIGHTBOX_PARAMS = ('client_id', 'client_secret') -DREAMHOST_PARAMS = ('key',) -EC2_PARAMS = ('access_id', 'secret') -ECP_PARAMS = ('user_name', 'password') -GANDI_PARAMS = ('user',) -GCE_PARAMS = ('email_address', 'key') # Service Account Authentication -# GCE_PARAMS = ('client_id', 'client_secret') # Installed App Authentication -GCE_KEYWORD_PARAMS = {'project': 'project_name'} -HOSTINGCOM_PARAMS = ('user', 'secret') -IBM_PARAMS = ('user', 'secret') -# OPENSTACK_PARAMS = ('user_name', 'api_key', secure_bool, 'host', port_int) -OPENSTACK_PARAMS = ('user_name', 'api_key', False, 'host', 8774) -OPENNEBULA_PARAMS = ('user', 'key') -OPSOURCE_PARAMS = ('user', 'password') -RACKSPACE_PARAMS = ('user', 'key') -RACKSPACE_NOVA_PARAMS = ('user_name', 'api_key', False, 'host', 8774) -SLICEHOST_PARAMS = ('key',) -SOFTLAYER_PARAMS = ('user', 'api_key') -VCLOUD_PARAMS = ('user', 'secret') -VOXEL_PARAMS = ('key', 'secret') -VPSNET_PARAMS = ('user', 'key') -JOYENT_PARAMS = ('user', 'key') -VCL_PARAMS = ('user', 'pass', True, 'foo.bar.com') -GRIDSPOT_PARAMS = ('key',) -HOSTVIRTUAL_PARAMS = ('key',) -DIGITAL_OCEAN_PARAMS = ('user', 'key') -CLOUDFRAMES_PARAMS = ('key', 'secret', False, 'host', 8888) - -# Storage -STORAGE_S3_PARAMS = ('key', 'secret') -STORAGE_GOOGLE_STORAGE_PARAMS = ('key', 'secret') - -# Azure key is b64 encoded and must be decoded before signing requests -STORAGE_AZURE_BLOBS_PARAMS = ('account', 'cGFzc3dvcmQ=') - -# Loadbalancer -LB_BRIGHTBOX_PARAMS = ('user', 'key') -LB_ELB_PARAMS = ('access_id', 'secret', 'region') - -# DNS -DNS_PARAMS_LINODE = ('user', 'key') -DNS_PARAMS_ZERIGO = ('email', 'api token') -DNS_PARAMS_RACKSPACE = ('user', 'key') -DNS_PARAMS_HOSTVIRTUAL = ('key',) -DNS_PARAMS_ROUTE53 = ('access_id', 'secret') -DNS_GANDI = ('user', ) -DNS_PARAMS_GOOGLE = ('email_address', 'key') -DNS_KEYWORD_PARAMS_GOOGLE = {'project': 'project_name'} diff --git a/awx/lib/site-packages/libcloud/test/storage/__init__.py b/awx/lib/site-packages/libcloud/test/storage/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/already_exists.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/already_exists.xml deleted file mode 100644 index 2b9d94cb64..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/already_exists.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 1016 - The resource you are trying to create already exists. - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/empty_directory_listing.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/empty_directory_listing.xml deleted file mode 100644 index 8040444d50..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/empty_directory_listing.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/list_containers.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/list_containers.xml deleted file mode 100644 index 71befd84a8..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/list_containers.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9 - directory - container1 - - - 860855a4a445b5e45eeef4024371fd5c73ee3ada - directory - container2 - - - 651eae32634bf84529c74eabd555fda48c7cead6 - regular - not-a-container1 - - - 089293be672782a255498b0b05c4877acf23ef9e - directory - container3 - - - bd804e9f356b51844f93273ec8c94b2e274711d0 - directory - container4 - - - b40b0f3a17fad1d8c8b2085f668f8107bb400fa5 - regular - not-a-container-2 - - - 10bd74388b55a3c8c329ff5dd6d21bd55bfb7370 - directory - container5 - - - c04fa4aa3d0adcdf104baa0cef7b6279680a23c3 - directory - container6 - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/not_empty.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/not_empty.xml deleted file mode 100644 index 6c46d5962d..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/not_empty.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 1023 - The directory you are trying to delete is not empty. - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/not_found.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/not_found.xml deleted file mode 100644 index 3f157a2942..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/atmos/not_found.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 1003 - The requested object was not found. - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_1.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_1.xml deleted file mode 100644 index 2d3678e697..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_1.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 2 - - - container1 - https://account.blob.core.windows.net/container1 - - Mon, 07 Jan 2013 06:31:06 GMT - "0x8CFBAB7B4F23346" - unlocked - available - - - - - container2 - https://account.blob.core.windows.net/container2 - - Mon, 07 Jan 2013 06:31:07 GMT - "0x8CFBAB7B5B82D8E" - unlocked - available - - - - - /account/container3 - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_2.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_2.xml deleted file mode 100644 index 3c0e6c3a87..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_2.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - /account/container3 - 2 - - - container3 - https://account.blob.core.windows.net/container3 - - Mon, 07 Jan 2013 06:31:08 GMT - "0x8CFBAB7B6452A71" - unlocked - available - - - - - container4 - https://account.blob.core.windows.net/container4 - - Fri, 04 Jan 2013 08:32:41 GMT - "0x8CFB86D32305484" - unlocked - available - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_empty.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_empty.xml deleted file mode 100644 index d79dd65f16..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_containers_empty.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - 100 - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_1.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_1.xml deleted file mode 100644 index 713f8d6baa..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_1.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - 2 - - - object1.txt - https://account.blob.core.windows.net/test_container/object1.txt - - Fri, 04 Jan 2013 09:48:06 GMT - 0x8CFB877BB56A6FB - 0 - application/octet-stream - - - 1B2M2Y8AsgTpgAmY7PhCfg== - - BlockBlob - unlocked - available - - - value1 - value2 - - - - object2.txt - https://account.blob.core.windows.net/test_container/object2.txt - - Sat, 05 Jan 2013 03:51:42 GMT - 0x8CFB90F1BA8CD8F - 1048576 - application/octet-stream - - - ttgbNgpWctgMJ0MPORU+LA== - - BlockBlob - unlocked - available - - - value1 - value2 - - - - 2!76!MDAwMDExIXNvbWUxMTcudHh0ITAwMDAyOCE5OTk5LTEyLTMxVDIzOjU5OjU5Ljk5OTk5OTlaIQ-- - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_2.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_2.xml deleted file mode 100644 index 973985b665..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_2.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - object3.txt - 2 - - - object3.txt - https://account.blob.core.windows.net/test_container/object3.txt - - Sat, 05 Jan 2013 03:52:08 GMT - 0x8CFB90F2B6FC022 - 1048576 - application/octet-stream - - - ttgbNgpWctgMJ0MPORU+LA== - - BlockBlob - unlocked - available - - - - - object4.txt - https://account.blob.core.windows.net/test_container/object4.txt - - Fri, 04 Jan 2013 10:20:14 GMT - 0x8CFB87C38717450 - 0 - application/octet-stream - - 1B2M2Y8AsgTpgAmY7PhCfg== - - BlockBlob - unlocked - available - - - - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_empty.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_empty.xml deleted file mode 100644 index 2ccbf4f20a..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/azure_blobs/list_objects_empty.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 2 - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/_v2_0__auth.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/_v2_0__auth.json deleted file mode 100644 index 8e91196923..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/_v2_0__auth.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "access": { - "token": { - "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", - "expires": "2031-11-23T21:00:14.000-06:00" - }, - "serviceCatalog": [ - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", - "version": { - "versionInfo": "https://cdn2.clouddrive.com/v1/", - "versionList": "https://cdn2.clouddrive.com/", - "versionId": "1" - } - } - - ], - "name": "cloudFilesCDN", - "type": "rax:object-cdn" - }, - { - "endpoints": [ - { - "region": "ORD", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage4.ord1.clouddrive.com/v1/MossoCloudFS", - "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - }, - { - "region": "LON", - "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", - "publicURL": "https://storage4.lon1.clouddrive.com/v1/MossoCloudFS", - "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" - } - ], - "name": "cloudFiles", - "type": "object-store" - }, - { - "endpoints": [ - { - "tenantId": "1337", - "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", - "version": { - "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", - "versionList": "https://servers.api.rackspacecloud.com/", - "versionId": "1.0" - } - } - ], - "name": "cloudServers", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "RegionOne", - "tenantId": "1337", - "publicURL": "https://127.0.0.1/v2/1337", - "versionInfo": "https://127.0.0.1/v2/", - "versionList": "https://127.0.0.1/", - "versionId": "2" - } - ], - "name": "nova", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "613469", - "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", - "versionList": "https://dfw.servers.api.rackspacecloud.com/", - "versionId": "2" - }, - { - "region": "ORD", - "tenantId": "613469", - "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/1337", - "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", - "versionList": "https://ord.servers.api.rackspacecloud.com/", - "versionId": "2" - } - ], - "name": "cloudServersOpenStack", - "type": "compute" - }, - { - "endpoints": [ - { - "region": "DFW", - "tenantId": "1337", - "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/1337" - } - ], - "name": "cloudServersPreprod", - "type": "compute" - } - ], - "user": { - "id": "7", - "roles": [ - { - "id": "identity:default", - "description": "Default Role.", - "name": "identity:default" - } - ], - "name": "testuser" - } - } -} diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects.json deleted file mode 100644 index 4c47200bb4..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - {"name":"foo test 1","hash":"16265549b5bda64ecdaa5156de4c97cc", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:50.351810"}, - {"name":"foo test 2","hash":"16265549b5bda64ecdaa5156de4c97bb", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:50.351810"}, - {"name":"foo tes 3","hash":"16265549b5bda64ecdaa5156de4c97ee", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:46.549890"}, - {"name":"foo test 3","hash":"16265549b5bda64ecdaa5156de4c97ff", - "bytes":1160520,"content_type":"application/text", - "last_modified":"2011-01-25T22:01:50.351810"} -] diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_empty.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_empty.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_empty.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted1.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted1.json deleted file mode 100644 index f6382d3b5f..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted1.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - {"name":"foo-test-1","hash":"16265549b5bda64ecdaa5156de4c97cc", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:50.351810"}, - {"name":"foo-test-2","hash":"16265549b5bda64ecdaa5156de4c97bb", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:50.351810"}, - {"name":"foo-test-3","hash":"16265549b5bda64ecdaa5156de4c97ee", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:46.549890"} -] diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted2.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted2.json deleted file mode 100644 index 6ad8210010..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted2.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - {"name":"foo-test-4","hash":"16265549b5bda64ecdaa5156de4c97cc", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:50.351810"}, - {"name":"foo-test-5","hash":"16265549b5bda64ecdaa5156de4c97bb", - "bytes":1160520,"content_type":"application/zip", - "last_modified":"2011-01-25T22:01:50.351810"} -] diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_containers.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_containers.json deleted file mode 100644 index ded31c02c3..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_containers.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - {"name":"container1","count":4,"bytes":3484450}, - {"name":"container2","count":120,"bytes":340084450}, - {"name":"container3","count":0,"bytes":0} -] diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_containers_empty.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_containers_empty.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/list_containers_empty.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/meta_data.json b/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/meta_data.json deleted file mode 100644 index 5049f58492..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/cloudfiles/meta_data.json +++ /dev/null @@ -1 +0,0 @@ -{"bytes_used": 1234567, "container_count": 10, "object_count": 400} diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects.xml deleted file mode 100644 index 7636f5413c..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - test_container - - - 1000 - false - - 1.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_empty.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_empty.xml deleted file mode 100644 index 1a933cb323..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_empty.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - test_container - - - 1000 - false - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted1.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted1.xml deleted file mode 100644 index 1904a7e355..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted1.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - test_container - - - 1000 - true - - 1.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - - 2.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - - 3.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted2.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted2.xml deleted file mode 100644 index 3e7d28769c..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted2.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - test_container - - - 3 - false - - 4.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - - 5.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_containers.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_containers.xml deleted file mode 100644 index 9f23f24621..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_containers.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 - foobar - - - - test1 - 2011-04-09T12:34:49.000Z - - - test2 - 2011-02-09T12:34:49.000Z - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_containers_empty.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_containers_empty.xml deleted file mode 100644 index 2584babacc..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/google_storage/list_containers_empty.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 - foobar - - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/complete_multipart.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/complete_multipart.xml deleted file mode 100644 index f5aa94ffa3..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/complete_multipart.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - http://Example-Bucket.s3.amazonaws.com/Example-Object - Example-Bucket - Example-Object - "3858f62230ac3c915f300c664312c11f-9" - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/initiate_multipart.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/initiate_multipart.xml deleted file mode 100644 index 4c0b8bf1d4..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/initiate_multipart.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - example-bucket - example-object - VXBsb2FkIElEIGZvciA2aWWpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects.xml deleted file mode 100644 index 6cfdcd30f8..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - test_container - - - 1000 - false - - 1.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_empty.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_empty.xml deleted file mode 100644 index 0702683a51..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_empty.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - test_container - - - 1000 - false - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted1.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted1.xml deleted file mode 100644 index 5a02ed0b5b..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted1.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - test_container - - - 1000 - true - - 1.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - - 2.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - - 3.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted2.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted2.xml deleted file mode 100644 index 0bf5af4afc..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted2.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - test_container - - - 3 - false - - 4.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - - 5.zip - 2011-04-09T19:05:18.000Z - "4397da7a7649e8085de9916c240e8166" - 1234567 - - 65a011niqo39cdf8ec533ec3d1ccaafsa932 - - STANDARD - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_containers.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_containers.xml deleted file mode 100644 index ec66b73c54..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_containers.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 - foobar - - - - test1 - 2011-04-09T12:34:49.000Z - - - test2 - 2011-02-09T12:34:49.000Z - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_containers_empty.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_containers_empty.xml deleted file mode 100644 index 463cb24d03..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_containers_empty.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 - foobar - - - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_multipart_1.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_multipart_1.xml deleted file mode 100644 index fd2facef33..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_multipart_1.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - foo_bar_container - - - my-movie.m2ts - YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ - 3 - true - - my-divisor - XMgbGlrZSBlbHZpbmcncyBub3QgaGF2aW5nIG11Y2ggbHVjaw - - arn:aws:iam::111122223333:user/user1-11111a31-17b5-4fb7-9df5-b111111f13de - user1-11111a31-17b5-4fb7-9df5-b111111f13de - - - 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a - OwnerDisplayName - - STANDARD - 2010-11-10T20:48:33.000Z - - - my-movie.m2ts - VXBsb2FkIElEIGZvciBlbHZpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA - - b1d16700c70b0b05597d7acd6a3f92be - InitiatorDisplayName - - - b1d16700c70b0b05597d7acd6a3f92be - OwnerDisplayName - - STANDARD - 2010-11-10T20:48:33.000Z - - - my-movie.m2ts - YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ - - arn:aws:iam::444455556666:user/user1-22222a31-17b5-4fb7-9df5-b222222f13de - user1-22222a31-17b5-4fb7-9df5-b222222f13de - - - b1d16700c70b0b05597d7acd6a3f92be - OwnerDisplayName - - STANDARD - 2010-11-10T20:49:33.000Z - - diff --git a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_multipart_2.xml b/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_multipart_2.xml deleted file mode 100644 index a7683bd814..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/fixtures/s3/list_multipart_2.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - foo_bar_container - - - - - 3 - false - - my-divisor - XMgbGlrZSBlbHZpbmcncyBub3QgaGF2aW5nIG11Y2ggbHVjaw - - arn:aws:iam::111122223333:user/user1-11111a31-17b5-4fb7-9df5-b111111f13de - user1-11111a31-17b5-4fb7-9df5-b111111f13de - - - 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a - OwnerDisplayName - - STANDARD - 2010-11-10T20:48:33.000Z - - - my-movie.m2ts - VXBsb2FkIElEIGZvciBlbHZpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA - - b1d16700c70b0b05597d7acd6a3f92be - InitiatorDisplayName - - - b1d16700c70b0b05597d7acd6a3f92be - OwnerDisplayName - - STANDARD - 2010-11-10T20:48:33.000Z - - - my-movie.m2ts - YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ - - arn:aws:iam::444455556666:user/user1-22222a31-17b5-4fb7-9df5-b222222f13de - user1-22222a31-17b5-4fb7-9df5-b222222f13de - - - b1d16700c70b0b05597d7acd6a3f92be - OwnerDisplayName - - STANDARD - 2010-11-10T20:49:33.000Z - - diff --git a/awx/lib/site-packages/libcloud/test/storage/test_atmos.py b/awx/lib/site-packages/libcloud/test/storage/test_atmos.py deleted file mode 100644 index 561ac2fb39..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/test_atmos.py +++ /dev/null @@ -1,772 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import os.path -import sys -import unittest - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import b - -import libcloud.utils.files - -from libcloud.common.types import LibcloudError -from libcloud.storage.base import Container, Object -from libcloud.storage.types import ContainerAlreadyExistsError, \ - ContainerDoesNotExistError, \ - ContainerIsNotEmptyError, \ - ObjectDoesNotExistError -from libcloud.storage.drivers.atmos import AtmosConnection, AtmosDriver -from libcloud.storage.drivers.dummy import DummyIterator - -from libcloud.test import StorageMockHttp, MockRawResponse -from libcloud.test.file_fixtures import StorageFileFixtures - - -class AtmosTests(unittest.TestCase): - - def setUp(self): - AtmosDriver.connectionCls.conn_classes = (None, AtmosMockHttp) - AtmosDriver.connectionCls.rawResponseCls = AtmosMockRawResponse - AtmosDriver.path = '' - AtmosMockHttp.type = None - AtmosMockHttp.upload_created = False - AtmosMockRawResponse.type = None - self.driver = AtmosDriver('dummy', base64.b64encode(b('dummy'))) - self._remove_test_file() - - def tearDown(self): - self._remove_test_file() - - def _remove_test_file(self): - file_path = os.path.abspath(__file__) + '.temp' - - try: - os.unlink(file_path) - except OSError: - pass - - def test_list_containers(self): - AtmosMockHttp.type = 'EMPTY' - containers = self.driver.list_containers() - self.assertEqual(len(containers), 0) - - AtmosMockHttp.type = None - containers = self.driver.list_containers() - self.assertEqual(len(containers), 6) - - def test_list_container_objects(self): - container = Container(name='test_container', extra={}, - driver=self.driver) - - AtmosMockHttp.type = 'EMPTY' - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 0) - - AtmosMockHttp.type = None - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 2) - - obj = [o for o in objects if o.name == 'not-a-container1'][0] - self.assertEqual(obj.meta_data['object_id'], - '651eae32634bf84529c74eabd555fda48c7cead6') - self.assertEqual(obj.container.name, 'test_container') - - def test_get_container(self): - container = self.driver.get_container(container_name='test_container') - self.assertEqual(container.name, 'test_container') - self.assertEqual(container.extra['object_id'], - 'b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9') - - def test_get_container_escaped(self): - container = self.driver.get_container( - container_name='test & container') - self.assertEqual(container.name, 'test & container') - self.assertEqual(container.extra['object_id'], - 'b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9') - - def test_get_container_not_found(self): - try: - self.driver.get_container(container_name='not_found') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_container_success(self): - container = self.driver.create_container( - container_name='test_create_container') - self.assertTrue(isinstance(container, Container)) - self.assertEqual(container.name, 'test_create_container') - self.assertEqual(container.extra['object_id'], - '31a27b593629a3fe59f887fd973fd953e80062ce') - - def test_create_container_already_exists(self): - AtmosMockHttp.type = 'ALREADY_EXISTS' - - try: - self.driver.create_container( - container_name='test_create_container') - except ContainerAlreadyExistsError: - pass - else: - self.fail( - 'Container already exists but an exception was not thrown') - - def test_delete_container_success(self): - container = Container(name='foo_bar_container', extra={}, driver=self) - result = self.driver.delete_container(container=container) - self.assertTrue(result) - - def test_delete_container_not_found(self): - AtmosMockHttp.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, driver=self) - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail( - 'Container does not exist but an exception was not thrown') - - def test_delete_container_not_empty(self): - AtmosMockHttp.type = 'NOT_EMPTY' - container = Container(name='foo_bar_container', extra={}, driver=self) - try: - self.driver.delete_container(container=container) - except ContainerIsNotEmptyError: - pass - else: - self.fail('Container is not empty but an exception was not thrown') - - def test_get_object_success(self): - obj = self.driver.get_object(container_name='test_container', - object_name='test_object') - self.assertEqual(obj.container.name, 'test_container') - self.assertEqual(obj.size, 555) - self.assertEqual(obj.hash, '6b21c4a111ac178feacf9ec9d0c71f17') - self.assertEqual(obj.extra['object_id'], - '322dce3763aadc41acc55ef47867b8d74e45c31d6643') - self.assertEqual( - obj.extra['last_modified'], 'Tue, 25 Jan 2011 22:01:49 GMT') - self.assertEqual(obj.meta_data['foo-bar'], 'test 1') - self.assertEqual(obj.meta_data['bar-foo'], 'test 2') - - def test_get_object_escaped(self): - obj = self.driver.get_object(container_name='test & container', - object_name='test & object') - self.assertEqual(obj.container.name, 'test & container') - self.assertEqual(obj.size, 555) - self.assertEqual(obj.hash, '6b21c4a111ac178feacf9ec9d0c71f17') - self.assertEqual(obj.extra['object_id'], - '322dce3763aadc41acc55ef47867b8d74e45c31d6643') - self.assertEqual( - obj.extra['last_modified'], 'Tue, 25 Jan 2011 22:01:49 GMT') - self.assertEqual(obj.meta_data['foo-bar'], 'test 1') - self.assertEqual(obj.meta_data['bar-foo'], 'test 2') - - def test_get_object_not_found(self): - try: - self.driver.get_object(container_name='test_container', - object_name='not_found') - except ObjectDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_delete_object_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver) - status = self.driver.delete_object(obj=obj) - self.assertTrue(status) - - def test_delete_object_escaped_success(self): - container = Container(name='foo & bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo & bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver) - status = self.driver.delete_object(obj=obj) - self.assertTrue(status) - - def test_delete_object_not_found(self): - AtmosMockHttp.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver) - try: - self.driver.delete_object(obj=obj) - except ObjectDoesNotExistError: - pass - else: - self.fail('Object does not exist but an exception was not thrown') - - def test_download_object_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertTrue(result) - - def test_download_object_escaped_success(self): - container = Container(name='foo & bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo & bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertTrue(result) - - def test_download_object_success_not_found(self): - AtmosMockRawResponse.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, - meta_data=None, - driver=self.driver) - destination_path = os.path.abspath(__file__) + '.temp' - try: - self.driver.download_object( - obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - except ObjectDoesNotExistError: - pass - else: - self.fail('Object does not exist but an exception was not thrown') - - def test_download_object_as_stream(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver) - - stream = self.driver.download_object_as_stream( - obj=obj, chunk_size=None) - self.assertTrue(hasattr(stream, '__iter__')) - - def test_download_object_as_stream_escaped(self): - container = Container(name='foo & bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo & bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver) - - stream = self.driver.download_object_as_stream( - obj=obj, chunk_size=None) - self.assertTrue(hasattr(stream, '__iter__')) - - def test_upload_object_success(self): - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, 'hash343hhash89h932439jsaa89', 1000 - - old_func = AtmosDriver._upload_file - AtmosDriver._upload_file = upload_file - path = os.path.abspath(__file__) - container = Container(name='fbc', extra={}, driver=self) - object_name = 'ftu' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=path, container=container, - extra=extra, object_name=object_name) - self.assertEqual(obj.name, 'ftu') - self.assertEqual(obj.size, 1000) - self.assertTrue('some-value' in obj.meta_data) - AtmosDriver._upload_file = old_func - - def test_upload_object_no_content_type(self): - def no_content_type(name): - return None, None - - old_func = libcloud.utils.files.guess_file_mime_type - libcloud.utils.files.guess_file_mime_type = no_content_type - file_path = os.path.abspath(__file__) - container = Container(name='fbc', extra={}, driver=self) - object_name = 'ftu' - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name) - - # Just check that the file was uploaded OK, as the fallback - # Content-Type header should be set (application/octet-stream). - self.assertEqual(obj.name, object_name) - libcloud.utils.files.guess_file_mime_type = old_func - - def test_upload_object_error(self): - def dummy_content_type(name): - return 'application/zip', None - - def send(instance): - raise Exception('') - - old_func1 = libcloud.utils.files.guess_file_mime_type - libcloud.utils.files.guess_file_mime_type = dummy_content_type - old_func2 = AtmosMockHttp.send - AtmosMockHttp.send = send - - file_path = os.path.abspath(__file__) - container = Container(name='fbc', extra={}, driver=self) - object_name = 'ftu' - try: - self.driver.upload_object( - file_path=file_path, - container=container, - object_name=object_name) - except LibcloudError: - pass - else: - self.fail( - 'Timeout while uploading but an exception was not thrown') - finally: - libcloud.utils.files.guess_file_mime_type = old_func1 - AtmosMockHttp.send = old_func2 - - def test_upload_object_nonexistent_file(self): - def dummy_content_type(name): - return 'application/zip', None - - old_func = libcloud.utils.files.guess_file_mime_type - libcloud.utils.files.guess_file_mime_type = dummy_content_type - - file_path = os.path.abspath(__file__ + '.inexistent') - container = Container(name='fbc', extra={}, driver=self) - object_name = 'ftu' - try: - self.driver.upload_object( - file_path=file_path, - container=container, - object_name=object_name) - except OSError: - pass - else: - self.fail('Inesitent but an exception was not thrown') - finally: - libcloud.utils.files.guess_file_mime_type = old_func - - def test_upload_object_via_stream_new_object(self): - def dummy_content_type(name): - return 'application/zip', None - - old_func = libcloud.storage.drivers.atmos.guess_file_mime_type - libcloud.storage.drivers.atmos.guess_file_mime_type = dummy_content_type - - container = Container(name='fbc', extra={}, driver=self) - object_name = 'ftsdn' - iterator = DummyIterator(data=['2', '3', '5']) - try: - self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator) - finally: - libcloud.storage.drivers.atmos.guess_file_mime_type = old_func - - def test_upload_object_via_stream_existing_object(self): - def dummy_content_type(name): - return 'application/zip', None - - old_func = libcloud.storage.drivers.atmos.guess_file_mime_type - libcloud.storage.drivers.atmos.guess_file_mime_type = dummy_content_type - - container = Container(name='fbc', extra={}, driver=self) - object_name = 'ftsde' - iterator = DummyIterator(data=['2', '3', '5']) - try: - self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator) - finally: - libcloud.storage.drivers.atmos.guess_file_mime_type = old_func - - def test_upload_object_via_stream_no_content_type(self): - def no_content_type(name): - return None, None - - old_func = libcloud.storage.drivers.atmos.guess_file_mime_type - libcloud.storage.drivers.atmos.guess_file_mime_type = no_content_type - - container = Container(name='fbc', extra={}, driver=self) - object_name = 'ftsdct' - iterator = DummyIterator(data=['2', '3', '5']) - try: - self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator) - except AttributeError: - pass - else: - self.fail( - 'File content type not provided' - ' but an exception was not thrown') - finally: - libcloud.storage.drivers.atmos.guess_file_mime_type = old_func - - def test_signature_algorithm(self): - test_uid = 'fredsmagicuid' - test_key = base64.b64encode(b('ssssshhhhhmysecretkey')) - test_date = 'Mon, 04 Jul 2011 07:39:19 GMT' - test_values = [ - ('GET', '/rest/namespace/foo', '', {}, - 'WfSASIA25TuqO2n0aO9k/dtg6S0='), - ('GET', '/rest/namespace/foo%20%26%20bar', '', {}, - 'vmlqXqcInxxoP4YX5mR09BonjX4='), - ('POST', '/rest/namespace/foo', '', {}, - 'oYKdsF+1DOuUT7iX5CJCDym2EQk='), - ('PUT', '/rest/namespace/foo', '', {}, - 'JleF9dpSWhaT3B2swZI3s41qqs4='), - ('DELETE', '/rest/namespace/foo', '', {}, - '2IX+Bd5XZF5YY+g4P59qXV1uLpo='), - ('GET', '/rest/namespace/foo?metata/system', '', {}, - 'zuHDEAgKM1winGnWn3WBsqnz4ks='), - ('POST', '/rest/namespace/foo?metadata/user', '', { - 'x-emc-meta': 'fakemeta=fake, othermeta=faketoo' - }, '7sLx1nxPIRAtocfv02jz9h1BjbU='), - ] - - class FakeDriver(object): - path = '' - - for method, action, api_path, headers, expected in test_values: - c = AtmosConnection(test_uid, test_key) - c.method = method - c.action = action - d = FakeDriver() - d.path = api_path - c.driver = d - headers = c.add_default_headers(headers) - headers['Date'] = headers['x-emc-date'] = test_date - self.assertEqual(c._calculate_signature({}, headers), - b(expected).decode('utf-8')) - - -class AtmosMockHttp(StorageMockHttp, unittest.TestCase): - fixtures = StorageFileFixtures('atmos') - upload_created = False - upload_stream_created = False - - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self) - - if kwargs.get('host', None) and kwargs.get('port', None): - StorageMockHttp.__init__(self, *args, **kwargs) - - self._upload_object_via_stream_first_request = True - - def runTest(self): - pass - - def request(self, method, url, body=None, headers=None, raw=False): - headers = headers or {} - parsed = urlparse.urlparse(url) - if parsed.query.startswith('metadata/'): - parsed = list(parsed) - parsed[2] = parsed[2] + '/' + parsed[4] - parsed[4] = '' - url = urlparse.urlunparse(parsed) - return super(AtmosMockHttp, self).request(method, url, body, headers, - raw) - - def _rest_namespace_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('empty_directory_listing.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_namespace(self, method, url, body, headers): - body = self.fixtures.load('list_containers.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_namespace_test_container_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('empty_directory_listing.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_namespace_test_container(self, method, url, body, headers): - body = self.fixtures.load('list_containers.xml') - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_namespace_test_container__metadata_system( - self, method, url, body, - headers): - headers = { - 'x-emc-meta': 'objectid=b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9' - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_test_20_26_20container__metadata_system( - self, method, url, body, - headers): - headers = { - 'x-emc-meta': 'objectid=b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9' - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_not_found__metadata_system(self, method, url, body, - headers): - body = self.fixtures.load('not_found.xml') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - def _rest_namespace_test_create_container(self, method, url, body, headers): - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_test_create_container__metadata_system(self, method, - url, body, - headers): - headers = { - 'x-emc-meta': 'objectid=31a27b593629a3fe59f887fd973fd953e80062ce' - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_test_create_container_ALREADY_EXISTS(self, method, url, - body, headers): - body = self.fixtures.load('already_exists.xml') - return (httplib.BAD_REQUEST, body, {}, - httplib.responses[httplib.BAD_REQUEST]) - - def _rest_namespace_foo_bar_container(self, method, url, body, headers): - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_foo_bar_container_NOT_FOUND(self, method, url, body, - headers): - body = self.fixtures.load('not_found.xml') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - def _rest_namespace_foo_bar_container_NOT_EMPTY(self, method, url, body, - headers): - body = self.fixtures.load('not_empty.xml') - return (httplib.BAD_REQUEST, body, {}, - httplib.responses[httplib.BAD_REQUEST]) - - def _rest_namespace_test_container_test_object_metadata_system( - self, method, - url, body, - headers): - meta = { - 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', - 'size': '555', - 'mtime': '2011-01-25T22:01:49Z' - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_test_20_26_20container_test_20_26_20object_metadata_system( - self, method, - url, body, - headers): - meta = { - 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', - 'size': '555', - 'mtime': '2011-01-25T22:01:49Z' - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_test_container_test_object_metadata_user(self, method, - url, body, - headers): - meta = { - 'md5': '6b21c4a111ac178feacf9ec9d0c71f17', - 'foo-bar': 'test 1', - 'bar-foo': 'test 2', - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_test_20_26_20container_test_20_26_20object_metadata_user( - self, method, - url, body, - headers): - meta = { - 'md5': '6b21c4a111ac178feacf9ec9d0c71f17', - 'foo-bar': 'test 1', - 'bar-foo': 'test 2', - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_test_container_not_found_metadata_system(self, method, - url, body, - headers): - body = self.fixtures.load('not_found.xml') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - def _rest_namespace_foo_bar_container_foo_bar_object(self, method, url, - body, headers): - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_foo_20_26_20bar_container_foo_20_26_20bar_object( - self, method, url, - body, headers): - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_foo_bar_container_foo_bar_object_NOT_FOUND( - self, method, - url, body, - headers): - body = self.fixtures.load('not_found.xml') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - def _rest_namespace_fbc_ftu_metadata_system(self, method, url, body, - headers): - if not self.upload_created: - self.__class__.upload_created = True - body = self.fixtures.load('not_found.xml') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - self.__class__.upload_created = False - meta = { - 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', - 'size': '555', - 'mtime': '2011-01-25T22:01:49Z' - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftu_metadata_user(self, method, url, body, headers): - self.assertTrue('x-emc-meta' in headers) - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftsdn_metadata_system(self, method, url, body, - headers): - if not self.upload_stream_created: - self.__class__.upload_stream_created = True - body = self.fixtures.load('not_found.xml') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - self.__class__.upload_stream_created = False - meta = { - 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', - 'size': '555', - 'mtime': '2011-01-25T22:01:49Z' - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftsdn(self, method, url, body, headers): - if self._upload_object_via_stream_first_request: - self.assertTrue('Range' not in headers) - self.assertEqual(method, 'POST') - self._upload_object_via_stream_first_request = False - else: - self.assertTrue('Range' in headers) - self.assertEqual(method, 'PUT') - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftsdn_metadata_user(self, method, url, body, - headers): - self.assertTrue('x-emc-meta' in headers) - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftsde_metadata_system(self, method, url, body, - headers): - meta = { - 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', - 'size': '555', - 'mtime': '2011-01-25T22:01:49Z' - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftsde(self, method, url, body, headers): - if self._upload_object_via_stream_first_request: - self.assertTrue('Range' not in headers) - self._upload_object_via_stream_first_request = False - else: - self.assertTrue('Range' in headers) - self.assertEqual(method, 'PUT') - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftsde_metadata_user(self, method, url, body, - headers): - self.assertTrue('x-emc-meta' in headers) - return (httplib.OK, '', {}, httplib.responses[httplib.OK]) - - def _rest_namespace_fbc_ftsd_metadata_system(self, method, url, body, - headers): - meta = { - 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', - 'size': '555', - 'mtime': '2011-01-25T22:01:49Z' - } - headers = { - 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) - } - return (httplib.OK, '', headers, httplib.responses[httplib.OK]) - - -class AtmosMockRawResponse(MockRawResponse): - fixtures = StorageFileFixtures('atmos') - - def _rest_namespace_foo_bar_container_foo_bar_object(self, method, url, - body, headers): - body = self._generate_random_data(1000) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_namespace_foo_20_26_20bar_container_foo_20_26_20bar_object( - self, method, url, - body, headers): - body = self._generate_random_data(1000) - return (httplib.OK, body, {}, httplib.responses[httplib.OK]) - - def _rest_namespace_foo_bar_container_foo_bar_object_NOT_FOUND( - self, method, - url, body, - headers): - body = self.fixtures.load('not_found.xml') - return (httplib.NOT_FOUND, body, {}, - httplib.responses[httplib.NOT_FOUND]) - - def _rest_namespace_fbc_ftu(self, method, url, body, headers): - return (httplib.CREATED, '', {}, httplib.responses[httplib.CREATED]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/storage/test_azure_blobs.py b/awx/lib/site-packages/libcloud/test/storage/test_azure_blobs.py deleted file mode 100644 index 87f1238ee4..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/test_azure_blobs.py +++ /dev/null @@ -1,954 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import os -import sys -import unittest -import tempfile - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import parse_qs - -from libcloud.common.types import InvalidCredsError -from libcloud.common.types import LibcloudError -from libcloud.storage.base import Container, Object -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import ContainerAlreadyExistsError -from libcloud.storage.types import InvalidContainerNameError -from libcloud.storage.types import ObjectDoesNotExistError -from libcloud.storage.types import ObjectHashMismatchError -from libcloud.storage.drivers.azure_blobs import AzureBlobsStorageDriver -from libcloud.storage.drivers.azure_blobs import AZURE_BLOCK_MAX_SIZE -from libcloud.storage.drivers.azure_blobs import AZURE_PAGE_CHUNK_SIZE -from libcloud.storage.drivers.dummy import DummyIterator - -from libcloud.test import StorageMockHttp, MockRawResponse # pylint: disable-msg=E0611 -from libcloud.test import MockHttpTestCase # pylint: disable-msg=E0611 -from libcloud.test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611 -from libcloud.test.secrets import STORAGE_AZURE_BLOBS_PARAMS - - -class AzureBlobsMockHttp(StorageMockHttp, MockHttpTestCase): - - fixtures = StorageFileFixtures('azure_blobs') - base_headers = {} - - def _UNAUTHORIZED(self, method, url, body, headers): - return (httplib.UNAUTHORIZED, - '', - self.base_headers, - httplib.responses[httplib.UNAUTHORIZED]) - - def _list_containers_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('list_containers_empty.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _list_containers(self, method, url, body, headers): - query_string = urlparse.urlsplit(url).query - query = parse_qs(query_string) - - if 'marker' not in query: - body = self.fixtures.load('list_containers_1.xml') - else: - body = self.fixtures.load('list_containers_2.xml') - - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _test_container_EMPTY(self, method, url, body, headers): - if method == 'DELETE': - body = '' - return (httplib.ACCEPTED, - body, - self.base_headers, - httplib.responses[httplib.ACCEPTED]) - - else: - body = self.fixtures.load('list_objects_empty.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _new__container_INVALID_NAME(self, method, url, body, headers): - return (httplib.BAD_REQUEST, - body, - self.base_headers, - httplib.responses[httplib.BAD_REQUEST]) - - def _test_container(self, method, url, body, headers): - query_string = urlparse.urlsplit(url).query - query = parse_qs(query_string) - - if 'marker' not in query: - body = self.fixtures.load('list_objects_1.xml') - else: - body = self.fixtures.load('list_objects_2.xml') - - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _test_container100(self, method, url, body, headers): - body = '' - - if method != 'HEAD': - return (httplib.BAD_REQUEST, - body, - self.base_headers, - httplib.responses[httplib.BAD_REQUEST]) - - return (httplib.NOT_FOUND, - body, - self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _test_container200(self, method, url, body, headers): - body = '' - - if method != 'HEAD': - return (httplib.BAD_REQUEST, - body, - self.base_headers, - httplib.responses[httplib.BAD_REQUEST]) - - headers = {} - - headers['etag'] = '0x8CFB877BB56A6FB' - headers['last-modified'] = 'Fri, 04 Jan 2013 09:48:06 GMT' - headers['x-ms-lease-status'] = 'unlocked' - headers['x-ms-lease-state'] = 'available' - headers['x-ms-meta-meta1'] = 'value1' - - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _test_container200_test(self, method, url, body, headers): - body = '' - - if method != 'HEAD': - return (httplib.BAD_REQUEST, - body, - self.base_headers, - httplib.responses[httplib.BAD_REQUEST]) - - headers = {} - - headers['etag'] = '0x8CFB877BB56A6FB' - headers['last-modified'] = 'Fri, 04 Jan 2013 09:48:06 GMT' - headers['content-length'] = 12345 - headers['content-type'] = 'application/zip' - headers['x-ms-blob-type'] = 'Block' - headers['x-ms-lease-status'] = 'unlocked' - headers['x-ms-lease-state'] = 'available' - headers['x-ms-meta-rabbits'] = 'monkeys' - - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _test2_test_list_containers(self, method, url, body, headers): - # test_get_object - body = self.fixtures.load('list_containers.xml') - headers = {'content-type': 'application/zip', - 'etag': '"e31208wqsdoj329jd"', - 'x-amz-meta-rabbits': 'monkeys', - 'content-length': 12345, - 'last-modified': 'Thu, 13 Sep 2012 07:13:22 GMT' - } - - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _new_container_ALREADY_EXISTS(self, method, url, body, headers): - # test_create_container - return (httplib.CONFLICT, - body, - headers, - httplib.responses[httplib.CONFLICT]) - - def _new_container(self, method, url, body, headers): - # test_create_container, test_delete_container - - headers = {} - - if method == 'PUT': - status = httplib.CREATED - - headers['etag'] = '0x8CFB877BB56A6FB' - headers['last-modified'] = 'Fri, 04 Jan 2013 09:48:06 GMT' - headers['x-ms-lease-status'] = 'unlocked' - headers['x-ms-lease-state'] = 'available' - headers['x-ms-meta-meta1'] = 'value1' - - elif method == 'DELETE': - status = httplib.NO_CONTENT - - return (status, - body, - headers, - httplib.responses[status]) - - def _new_container_DOESNT_EXIST(self, method, url, body, headers): - # test_delete_container - return (httplib.NOT_FOUND, - body, - headers, - httplib.responses[httplib.NOT_FOUND]) - - def _foo_bar_container_NOT_FOUND(self, method, url, body, headers): - # test_delete_container_not_found - return (httplib.NOT_FOUND, - body, - headers, - httplib.responses[httplib.NOT_FOUND]) - - def _foo_bar_container_foo_bar_object_NOT_FOUND(self, method, url, body, - headers): - # test_delete_object_not_found - return (httplib.NOT_FOUND, - body, - headers, - httplib.responses[httplib.NOT_FOUND]) - - def _foo_bar_container_foo_bar_object(self, method, url, body, headers): - # test_delete_object - return (httplib.ACCEPTED, - body, - headers, - httplib.responses[httplib.ACCEPTED]) - - def _foo_bar_container_foo_test_upload(self, method, url, body, headers): - # test_upload_object_success - body = '' - headers = {} - headers['etag'] = '0x8CFB877BB56A6FB' - headers['content-md5'] = 'd4fe4c9829f7ca1cc89db7ad670d2bbd' - return (httplib.CREATED, - body, - headers, - httplib.responses[httplib.CREATED]) - - def _foo_bar_container_foo_test_upload_block(self, method, url, - body, headers): - # test_upload_object_success - body = '' - headers = {} - headers['etag'] = '0x8CFB877BB56A6FB' - return (httplib.CREATED, - body, - headers, - httplib.responses[httplib.CREATED]) - - def _foo_bar_container_foo_test_upload_page(self, method, url, - body, headers): - # test_upload_object_success - body = '' - headers = {} - headers['etag'] = '0x8CFB877BB56A6FB' - return (httplib.CREATED, - body, - headers, - httplib.responses[httplib.CREATED]) - - def _foo_bar_container_foo_test_upload_blocklist(self, method, url, - body, headers): - # test_upload_object_success - body = '' - headers = {} - headers['etag'] = '0x8CFB877BB56A6FB' - headers['content-md5'] = 'd4fe4c9829f7ca1cc89db7ad670d2bbd' - - return (httplib.CREATED, - body, - headers, - httplib.responses[httplib.CREATED]) - - def _foo_bar_container_foo_test_upload_lease(self, method, url, - body, headers): - # test_upload_object_success - action = headers['x-ms-lease-action'] - rheaders = {'x-ms-lease-id': 'someleaseid'} - body = '' - - if action == 'acquire': - return (httplib.CREATED, - body, - rheaders, - httplib.responses[httplib.CREATED]) - - else: - if headers.get('x-ms-lease-id', None) != 'someleaseid': - return (httplib.BAD_REQUEST, - body, - rheaders, - httplib.responses[httplib.BAD_REQUEST]) - - return (httplib.OK, - body, - headers, - httplib.responses[httplib.CREATED]) - - -class AzureBlobsMockRawResponse(MockRawResponse): - - fixtures = StorageFileFixtures('azure_blobs') - - def _foo_bar_container_foo_test_upload_INVALID_HASH(self, method, url, - body, headers): - body = '' - headers = {} - headers['etag'] = '0x8CFB877BB56A6FB' - headers['content-md5'] = 'd4fe4c9829f7ca1cc89db7ad670d2bbd' - - # test_upload_object_invalid_hash1 - return (httplib.CREATED, - body, - headers, - httplib.responses[httplib.CREATED]) - - def _foo_bar_container_foo_test_upload(self, method, url, body, headers): - # test_upload_object_success - body = '' - headers = {} - headers['etag'] = '0x8CFB877BB56A6FB' - headers['content-md5'] = 'd4fe4c9829f7ca1cc89db7ad670d2bbd' - return (httplib.CREATED, - body, - headers, - httplib.responses[httplib.CREATED]) - - def _foo_bar_container_foo_bar_object(self, method, url, body, headers): - # test_upload_object_invalid_file_size - body = self._generate_random_data(1000) - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_bar_object_INVALID_SIZE(self, method, url, - body, headers): - # test_upload_object_invalid_file_size - body = '' - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - -class AzureBlobsTests(unittest.TestCase): - driver_type = AzureBlobsStorageDriver - driver_args = STORAGE_AZURE_BLOBS_PARAMS - mock_response_klass = AzureBlobsMockHttp - mock_raw_response_klass = AzureBlobsMockRawResponse - - @classmethod - def create_driver(self): - return self.driver_type(*self.driver_args) - - def setUp(self): - self.driver_type.connectionCls.conn_classes = (None, - self.mock_response_klass) - self.driver_type.connectionCls.rawResponseCls = \ - self.mock_raw_response_klass - self.mock_response_klass.type = None - self.mock_raw_response_klass.type = None - self.driver = self.create_driver() - - def tearDown(self): - self._remove_test_file() - - def _remove_test_file(self): - file_path = os.path.abspath(__file__) + '.temp' - - try: - os.unlink(file_path) - except OSError: - pass - - def test_invalid_credentials(self): - self.mock_response_klass.type = 'UNAUTHORIZED' - try: - self.driver.list_containers() - except InvalidCredsError: - e = sys.exc_info()[1] - self.assertEqual(True, isinstance(e, InvalidCredsError)) - else: - self.fail('Exception was not thrown') - - def test_list_containers_empty(self): - self.mock_response_klass.type = 'list_containers_EMPTY' - containers = self.driver.list_containers() - self.assertEqual(len(containers), 0) - - def test_list_containers_success(self): - self.mock_response_klass.type = 'list_containers' - AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 - containers = self.driver.list_containers() - self.assertEqual(len(containers), 4) - - self.assertTrue('last_modified' in containers[1].extra) - self.assertTrue('url' in containers[1].extra) - self.assertTrue('etag' in containers[1].extra) - self.assertTrue('lease' in containers[1].extra) - self.assertTrue('meta_data' in containers[1].extra) - - def test_list_container_objects_empty(self): - self.mock_response_klass.type = 'EMPTY' - container = Container(name='test_container', extra={}, - driver=self.driver) - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 0) - - def test_list_container_objects_success(self): - self.mock_response_klass.type = None - AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 - - container = Container(name='test_container', extra={}, - driver=self.driver) - - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 4) - - obj = objects[1] - self.assertEqual(obj.name, 'object2.txt') - self.assertEqual(obj.hash, '0x8CFB90F1BA8CD8F') - self.assertEqual(obj.size, 1048576) - self.assertEqual(obj.container.name, 'test_container') - self.assertTrue('meta1' in obj.meta_data) - self.assertTrue('meta2' in obj.meta_data) - self.assertTrue('last_modified' in obj.extra) - self.assertTrue('content_type' in obj.extra) - self.assertTrue('content_encoding' in obj.extra) - self.assertTrue('content_language' in obj.extra) - - def test_get_container_doesnt_exist(self): - self.mock_response_klass.type = None - try: - self.driver.get_container(container_name='test_container100') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_container_success(self): - self.mock_response_klass.type = None - container = self.driver.get_container( - container_name='test_container200') - - self.assertTrue(container.name, 'test_container200') - self.assertTrue(container.extra['etag'], '0x8CFB877BB56A6FB') - self.assertTrue(container.extra['last_modified'], - 'Fri, 04 Jan 2013 09:48:06 GMT') - self.assertTrue(container.extra['lease']['status'], 'unlocked') - self.assertTrue(container.extra['lease']['state'], 'available') - self.assertTrue(container.extra['meta_data']['meta1'], 'value1') - - def test_get_object_container_doesnt_exist(self): - # This method makes two requests which makes mocking the response a bit - # trickier - self.mock_response_klass.type = None - try: - self.driver.get_object(container_name='test_container100', - object_name='test') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_object_success(self): - # This method makes two requests which makes mocking the response a bit - # trickier - self.mock_response_klass.type = None - obj = self.driver.get_object(container_name='test_container200', - object_name='test') - - self.assertEqual(obj.name, 'test') - self.assertEqual(obj.container.name, 'test_container200') - self.assertEqual(obj.size, 12345) - self.assertEqual(obj.hash, '0x8CFB877BB56A6FB') - self.assertEqual(obj.extra['last_modified'], - 'Fri, 04 Jan 2013 09:48:06 GMT') - self.assertEqual(obj.extra['content_type'], 'application/zip') - self.assertEqual(obj.meta_data['rabbits'], 'monkeys') - - def test_create_container_invalid_name(self): - # invalid container name - self.mock_response_klass.type = 'INVALID_NAME' - try: - self.driver.create_container(container_name='new--container') - except InvalidContainerNameError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_container_already_exists(self): - # container with this name already exists - self.mock_response_klass.type = 'ALREADY_EXISTS' - try: - self.driver.create_container(container_name='new-container') - except ContainerAlreadyExistsError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_container_success(self): - # success - self.mock_response_klass.type = None - name = 'new-container' - container = self.driver.create_container(container_name=name) - self.assertEqual(container.name, name) - - def test_delete_container_doesnt_exist(self): - container = Container(name='new_container', extra=None, - driver=self.driver) - self.mock_response_klass.type = 'DOESNT_EXIST' - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_delete_container_not_empty(self): - self.mock_response_klass.type = None - AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 - - container = Container(name='test_container', extra={}, - driver=self.driver) - - try: - self.driver.delete_container(container=container) - except ContainerIsNotEmptyError: - pass - else: - self.fail('Exception was not thrown') - - def test_delete_container_success(self): - self.mock_response_klass.type = 'EMPTY' - AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 - - container = Container(name='test_container', extra={}, - driver=self.driver) - - self.assertTrue(self.driver.delete_container(container=container)) - - def test_delete_container_not_found(self): - self.mock_response_klass.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail('Container does not exist but an exception was not' + - 'thrown') - - def test_download_object_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertTrue(result) - - def test_download_object_invalid_file_size(self): - self.mock_raw_response_klass.type = 'INVALID_SIZE' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertFalse(result) - - def test_download_object_invalid_file_already_exists(self): - self.mock_raw_response_klass.type = 'INVALID_SIZE' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - destination_path = os.path.abspath(__file__) - try: - self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - except LibcloudError: - pass - else: - self.fail('Exception was not thrown') - - def test_download_object_as_stream_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - - stream = self.driver.download_object_as_stream(obj=obj, - chunk_size=None) - self.assertTrue(hasattr(stream, '__iter__')) - - def test_upload_object_invalid_ex_blob_type(self): - # Invalid hash is detected on the amazon side and BAD_REQUEST is - # returned - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - try: - self.driver.upload_object(file_path=file_path, container=container, - object_name=object_name, - verify_hash=True, - ex_blob_type='invalid-blob') - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(str(e).lower().find('invalid blob type') != -1) - else: - self.fail('Exception was not thrown') - - def test_upload_object_invalid_md5(self): - # Invalid md5 is returned by azure - self.mock_raw_response_klass.type = 'INVALID_HASH' - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - file_path = os.path.abspath(__file__) - try: - self.driver.upload_object(file_path=file_path, container=container, - object_name=object_name, - verify_hash=True) - except ObjectHashMismatchError: - pass - else: - self.fail( - 'Invalid hash was returned but an exception was not thrown') - - def test_upload_small_block_object_success(self): - file_path = os.path.abspath(__file__) - file_size = os.stat(file_path).st_size - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=False, - ex_blob_type='BlockBlob') - - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, file_size) - self.assertTrue('some-value' in obj.meta_data) - - def test_upload_big_block_object_success(self): - file_path = tempfile.mktemp(suffix='.jpg') - file_size = AZURE_BLOCK_MAX_SIZE + 1 - - with open(file_path, 'w') as file_hdl: - file_hdl.write('0' * file_size) - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=False, - ex_blob_type='BlockBlob') - - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, file_size) - self.assertTrue('some-value' in obj.meta_data) - - os.remove(file_path) - - def test_upload_page_object_success(self): - self.mock_response_klass.use_param = None - file_path = tempfile.mktemp(suffix='.jpg') - file_size = AZURE_PAGE_CHUNK_SIZE * 4 - - with open(file_path, 'w') as file_hdl: - file_hdl.write('0' * file_size) - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=False, - ex_blob_type='PageBlob') - - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, file_size) - self.assertTrue('some-value' in obj.meta_data) - - os.remove(file_path) - - def test_upload_page_object_failure(self): - file_path = tempfile.mktemp(suffix='.jpg') - file_size = AZURE_PAGE_CHUNK_SIZE * 2 + 1 - - with open(file_path, 'w') as file_hdl: - file_hdl.write('0' * file_size) - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - - try: - self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=False, - ex_blob_type='PageBlob') - except LibcloudError: - e = sys.exc_info()[1] - self.assertTrue(str(e).lower().find('not aligned') != -1) - - os.remove(file_path) - - def test_upload_small_block_object_success_with_lease(self): - self.mock_response_klass.use_param = 'comp' - file_path = os.path.abspath(__file__) - file_size = os.stat(file_path).st_size - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=False, - ex_blob_type='BlockBlob', - ex_use_lease=True) - - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, file_size) - self.assertTrue('some-value' in obj.meta_data) - self.mock_response_klass.use_param = None - - def test_upload_big_block_object_success_with_lease(self): - self.mock_response_klass.use_param = 'comp' - file_path = tempfile.mktemp(suffix='.jpg') - file_size = AZURE_BLOCK_MAX_SIZE * 2 - - with open(file_path, 'w') as file_hdl: - file_hdl.write('0' * file_size) - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=False, - ex_blob_type='BlockBlob', - ex_use_lease=False) - - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, file_size) - self.assertTrue('some-value' in obj.meta_data) - - os.remove(file_path) - self.mock_response_klass.use_param = None - - def test_upload_page_object_success_with_lease(self): - self.mock_response_klass.use_param = 'comp' - file_path = tempfile.mktemp(suffix='.jpg') - file_size = AZURE_PAGE_CHUNK_SIZE * 4 - - with open(file_path, 'w') as file_hdl: - file_hdl.write('0' * file_size) - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=False, - ex_blob_type='PageBlob', - ex_use_lease=True) - - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, file_size) - self.assertTrue('some-value' in obj.meta_data) - - os.remove(file_path) - self.mock_response_klass.use_param = None - - def test_upload_blob_object_via_stream(self): - self.mock_response_klass.use_param = 'comp' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - object_name = 'foo_test_upload' - iterator = DummyIterator(data=['2', '3', '5']) - extra = {'content_type': 'text/plain'} - obj = self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra, - ex_blob_type='BlockBlob') - - self.assertEqual(obj.name, object_name) - self.assertEqual(obj.size, 3) - self.mock_response_klass.use_param = None - - def test_upload_blob_object_via_stream_with_lease(self): - self.mock_response_klass.use_param = 'comp' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - object_name = 'foo_test_upload' - iterator = DummyIterator(data=['2', '3', '5']) - extra = {'content_type': 'text/plain'} - obj = self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra, - ex_blob_type='BlockBlob', - ex_use_lease=True) - - self.assertEqual(obj.name, object_name) - self.assertEqual(obj.size, 3) - self.mock_response_klass.use_param = None - - def test_upload_page_object_via_stream(self): - self.mock_response_klass.use_param = 'comp' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - object_name = 'foo_test_upload' - blob_size = AZURE_PAGE_CHUNK_SIZE - iterator = DummyIterator(data=['1'] * blob_size) - extra = {'content_type': 'text/plain'} - obj = self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra, - ex_blob_type='PageBlob', - ex_page_blob_size=blob_size) - - self.assertEqual(obj.name, object_name) - self.assertEqual(obj.size, blob_size) - self.mock_response_klass.use_param = None - - def test_upload_page_object_via_stream_with_lease(self): - self.mock_response_klass.use_param = 'comp' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - object_name = 'foo_test_upload' - blob_size = AZURE_PAGE_CHUNK_SIZE - iterator = DummyIterator(data=['1'] * blob_size) - extra = {'content_type': 'text/plain'} - obj = self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra, - ex_blob_type='PageBlob', - ex_page_blob_size=blob_size, - ex_use_lease=True) - - self.assertEqual(obj.name, object_name) - self.assertEqual(obj.size, blob_size) - - def test_delete_object_not_found(self): - self.mock_response_klass.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, - meta_data=None, container=container, driver=self.driver) - try: - self.driver.delete_object(obj=obj) - except ObjectDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_delete_object_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, - meta_data=None, container=container, driver=self.driver) - - result = self.driver.delete_object(obj=obj) - self.assertTrue(result) - - def test_storage_driver_host(self): - # Non regression tests for issue LIBCLOUD-399 dealing with the bad - # management of the connectionCls.host class attribute - driver1 = self.driver_type('fakeaccount1', 'deadbeafcafebabe==') - driver2 = self.driver_type('fakeaccount2', 'deadbeafcafebabe==') - driver3 = self.driver_type('fakeaccount3', 'deadbeafcafebabe==', - host='test.foo.bar.com') - - host1 = driver1.connection.host - host2 = driver2.connection.host - host3 = driver3.connection.host - - self.assertEquals(host1, 'fakeaccount1.blob.core.windows.net') - self.assertEquals(host2, 'fakeaccount2.blob.core.windows.net') - self.assertEquals(host3, 'test.foo.bar.com') - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/storage/test_base.py b/awx/lib/site-packages/libcloud/test/storage/test_base.py deleted file mode 100644 index 5c234b8b95..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/test_base.py +++ /dev/null @@ -1,193 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import hashlib - -from mock import Mock - -from libcloud.utils.py3 import StringIO -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import b - -if PY3: - from io import FileIO as file - -from libcloud.storage.base import StorageDriver -from libcloud.storage.base import DEFAULT_CONTENT_TYPE - -from libcloud.test import unittest -from libcloud.test import StorageMockHttp - - -class BaseStorageTests(unittest.TestCase): - - def setUp(self): - self.send_called = 0 - StorageDriver.connectionCls.conn_classes = (None, StorageMockHttp) - - self.driver1 = StorageDriver('username', 'key', host='localhost') - self.driver1.supports_chunked_encoding = True - self.driver2 = StorageDriver('username', 'key', host='localhost') - self.driver2.supports_chunked_encoding = False - - self.driver1.strict_mode = False - self.driver1.strict_mode = False - - def test__upload_object_iterator_must_have_next_method(self): - class Iterator(object): - - def next(self): - pass - - class Iterator2(file): - - def __init__(self): - pass - - class SomeClass(object): - pass - - valid_iterators = [Iterator(), Iterator2(), StringIO('bar')] - invalid_iterators = ['foobar', '', False, True, 1, object()] - - def upload_func(*args, **kwargs): - return True, 'barfoo', 100 - - kwargs = {'object_name': 'foo', 'content_type': 'foo/bar', - 'upload_func': upload_func, 'upload_func_kwargs': {}, - 'request_path': '/', 'headers': {}} - - for value in valid_iterators: - kwargs['iterator'] = value - self.driver1._upload_object(**kwargs) - - for value in invalid_iterators: - kwargs['iterator'] = value - - try: - self.driver1._upload_object(**kwargs) - except AttributeError: - pass - else: - self.fail('Exception was not thrown') - - def test_upload_zero_bytes_long_object_via_stream(self): - iterator = Mock() - - if PY3: - iterator.__next__ = Mock() - iterator.__next__.side_effect = StopIteration() - else: - iterator.next.side_effect = StopIteration() - - def mock_send(data): - self.send_called += 1 - - response = Mock() - response.connection.connection.send = mock_send - - # Normal - success, data_hash, bytes_transferred = \ - self.driver1._stream_data(response=response, - iterator=iterator, - chunked=False, calculate_hash=True) - - self.assertTrue(success) - self.assertEqual(data_hash, hashlib.md5(b('')).hexdigest()) - self.assertEqual(bytes_transferred, 0) - self.assertEqual(self.send_called, 1) - - # Chunked - success, data_hash, bytes_transferred = \ - self.driver1._stream_data(response=response, - iterator=iterator, - chunked=True, calculate_hash=True) - - self.assertTrue(success) - self.assertEqual(data_hash, hashlib.md5(b('')).hexdigest()) - self.assertEqual(bytes_transferred, 0) - self.assertEqual(self.send_called, 5) - - def test__upload_data(self): - def mock_send(data): - self.send_called += 1 - - response = Mock() - response.connection.connection.send = mock_send - - data = '123456789901234567' - success, data_hash, bytes_transferred = \ - self.driver1._upload_data(response=response, data=data, - calculate_hash=True) - - self.assertTrue(success) - self.assertEqual(data_hash, hashlib.md5(b(data)).hexdigest()) - self.assertEqual(bytes_transferred, (len(data))) - self.assertEqual(self.send_called, 1) - - def test__get_hash_function(self): - self.driver1.hash_type = 'md5' - func = self.driver1._get_hash_function() - self.assertTrue(func) - - self.driver1.hash_type = 'sha1' - func = self.driver1._get_hash_function() - self.assertTrue(func) - - try: - self.driver1.hash_type = 'invalid-hash-function' - func = self.driver1._get_hash_function() - except RuntimeError: - pass - else: - self.fail('Invalid hash type but exception was not thrown') - - def test_upload_no_content_type_supplied_or_detected(self): - iterator = StringIO() - - upload_func = Mock() - upload_func.return_value = True, '', 0 - - # strict_mode is disabled, default content type should be used - self.driver1.connection = Mock() - - self.driver1._upload_object(object_name='test', - content_type=None, - upload_func=upload_func, - upload_func_kwargs={}, - request_path='/', - iterator=iterator) - - headers = self.driver1.connection.request.call_args[-1]['headers'] - self.assertEqual(headers['Content-Type'], DEFAULT_CONTENT_TYPE) - - # strict_mode is enabled, exception should be thrown - - self.driver1.strict_mode = True - expected_msg = ('File content-type could not be guessed and no' - ' content_type value is provided') - self.assertRaisesRegexp(AttributeError, expected_msg, - self.driver1._upload_object, - object_name='test', - content_type=None, - upload_func=upload_func, - upload_func_kwargs={}, - request_path='/', - iterator=iterator) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/storage/test_cloudfiles.py b/awx/lib/site-packages/libcloud/test/storage/test_cloudfiles.py deleted file mode 100644 index 84ec615931..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/test_cloudfiles.py +++ /dev/null @@ -1,1133 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from hashlib import sha1 -import hmac -import os -import os.path # pylint: disable-msg=W0404 -import math -import sys -import copy -import unittest - -import mock - -import libcloud.utils.files - -from libcloud.utils.py3 import b -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlquote - -from libcloud.common.types import LibcloudError, MalformedResponseError -from libcloud.storage.base import Container, Object -from libcloud.storage.types import ContainerAlreadyExistsError -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import ObjectDoesNotExistError -from libcloud.storage.types import ObjectHashMismatchError -from libcloud.storage.types import InvalidContainerNameError -from libcloud.storage.drivers.cloudfiles import CloudFilesStorageDriver -from libcloud.storage.drivers.cloudfiles import CloudFilesUSStorageDriver -from libcloud.storage.drivers.cloudfiles import CloudFilesUKStorageDriver -from libcloud.storage.drivers.dummy import DummyIterator - -from libcloud.test import StorageMockHttp, MockRawResponse # pylint: disable-msg=E0611 -from libcloud.test import MockHttpTestCase # pylint: disable-msg=E0611 -from libcloud.test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611 - - -class CloudFilesTests(unittest.TestCase): - driver_klass = CloudFilesStorageDriver - driver_args = ('dummy', 'dummy') - driver_kwargs = {} - region = 'ord' - - def setUp(self): - self.driver_klass.connectionCls.conn_classes = ( - None, CloudFilesMockHttp) - self.driver_klass.connectionCls.rawResponseCls = \ - CloudFilesMockRawResponse - CloudFilesMockHttp.type = None - CloudFilesMockRawResponse.type = None - self.driver = self.driver_klass(*self.driver_args, - **self.driver_kwargs) - - # normally authentication happens lazily, but we force it here - self.driver.connection._populate_hosts_and_request_paths() - self._remove_test_file() - - def tearDown(self): - self._remove_test_file() - - def test_invalid_ex_force_service_region(self): - driver = CloudFilesStorageDriver('driver', 'dummy', - ex_force_service_region='invalid') - - try: - driver.list_containers() - except: - e = sys.exc_info()[1] - self.assertEqual(e.value, 'Could not find specified endpoint') - else: - self.fail('Exception was not thrown') - - def test_ex_force_service_region(self): - driver = CloudFilesStorageDriver('driver', 'dummy', - ex_force_service_region='ORD') - driver.list_containers() - - def test_force_auth_token_kwargs(self): - base_url = 'https://cdn2.clouddrive.com/v1/MossoCloudFS' - kwargs = { - 'ex_force_auth_token': 'some-auth-token', - 'ex_force_base_url': base_url - } - driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs) - driver.list_containers() - - self.assertEqual(kwargs['ex_force_auth_token'], - driver.connection.auth_token) - self.assertEqual('cdn2.clouddrive.com', - driver.connection.host) - self.assertEqual('/v1/MossoCloudFS', - driver.connection.request_path) - - def test_force_auth_url_kwargs(self): - kwargs = { - 'ex_force_auth_version': '2.0', - 'ex_force_auth_url': 'https://identity.api.rackspace.com' - } - driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs) - - self.assertEqual(kwargs['ex_force_auth_url'], - driver.connection._ex_force_auth_url) - self.assertEqual(kwargs['ex_force_auth_version'], - driver.connection._auth_version) - - def test_invalid_json_throws_exception(self): - CloudFilesMockHttp.type = 'MALFORMED_JSON' - try: - self.driver.list_containers() - except MalformedResponseError: - pass - else: - self.fail('Exception was not thrown') - - def test_service_catalog(self): - url = 'https://storage4.%s1.clouddrive.com/v1/MossoCloudFS' % \ - (self.region) - self.assertEqual( - url, - self.driver.connection.get_endpoint()) - - self.driver.connection.cdn_request = True - self.assertEqual( - 'https://cdn.clouddrive.com/v1/MossoCloudFS', - self.driver.connection.get_endpoint()) - self.driver.connection.cdn_request = False - - def test_endpoint_pointer(self): - kwargs = {'use_internal_url': False} - driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs) - self.assertEquals(driver.connection._get_endpoint_key(), libcloud.storage.drivers.cloudfiles.PUBLIC_ENDPOINT_KEY) - kwargs = {'use_internal_url': True} - driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs) - self.assertEquals(driver.connection._get_endpoint_key(), libcloud.storage.drivers.cloudfiles.INTERNAL_ENDPOINT_KEY) - driver.connection.cdn_request = True - self.assertEquals(driver.connection._get_endpoint_key(), libcloud.storage.drivers.cloudfiles.PUBLIC_ENDPOINT_KEY) - - def test_list_containers(self): - CloudFilesMockHttp.type = 'EMPTY' - containers = self.driver.list_containers() - self.assertEqual(len(containers), 0) - - CloudFilesMockHttp.type = None - containers = self.driver.list_containers() - self.assertEqual(len(containers), 3) - - container = [c for c in containers if c.name == 'container2'][0] - self.assertEqual(container.extra['object_count'], 120) - self.assertEqual(container.extra['size'], 340084450) - - def test_list_container_objects(self): - CloudFilesMockHttp.type = 'EMPTY' - container = Container( - name='test_container', extra={}, driver=self.driver) - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 0) - - CloudFilesMockHttp.type = None - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 4) - - obj = [o for o in objects if o.name == 'foo test 1'][0] - self.assertEqual(obj.hash, '16265549b5bda64ecdaa5156de4c97cc') - self.assertEqual(obj.size, 1160520) - self.assertEqual(obj.container.name, 'test_container') - - def test_list_container_object_name_encoding(self): - CloudFilesMockHttp.type = 'EMPTY' - container = Container(name='test container 1', extra={}, - driver=self.driver) - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 0) - - def test_list_container_objects_with_prefix(self): - CloudFilesMockHttp.type = 'EMPTY' - container = Container( - name='test_container', extra={}, driver=self.driver) - objects = self.driver.list_container_objects(container=container, - ex_prefix='test_prefix1') - self.assertEqual(len(objects), 0) - - CloudFilesMockHttp.type = None - objects = self.driver.list_container_objects(container=container, - ex_prefix='test_prefix2') - self.assertEqual(len(objects), 4) - - obj = [o for o in objects if o.name == 'foo test 1'][0] - self.assertEqual(obj.hash, '16265549b5bda64ecdaa5156de4c97cc') - self.assertEqual(obj.size, 1160520) - self.assertEqual(obj.container.name, 'test_container') - - def test_list_container_objects_iterator(self): - CloudFilesMockHttp.type = 'ITERATOR' - container = Container( - name='test_container', extra={}, driver=self.driver) - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 5) - - obj = [o for o in objects if o.name == 'foo-test-1'][0] - self.assertEqual(obj.hash, '16265549b5bda64ecdaa5156de4c97cc') - self.assertEqual(obj.size, 1160520) - self.assertEqual(obj.container.name, 'test_container') - - def test_get_container(self): - container = self.driver.get_container(container_name='test_container') - self.assertEqual(container.name, 'test_container') - self.assertEqual(container.extra['object_count'], 800) - self.assertEqual(container.extra['size'], 1234568) - - def test_get_container_not_found(self): - try: - self.driver.get_container(container_name='not_found') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_object_success(self): - obj = self.driver.get_object(container_name='test_container', - object_name='test_object') - self.assertEqual(obj.container.name, 'test_container') - self.assertEqual(obj.size, 555) - self.assertEqual(obj.hash, '6b21c4a111ac178feacf9ec9d0c71f17') - self.assertEqual(obj.extra['content_type'], 'application/zip') - self.assertEqual( - obj.extra['last_modified'], 'Tue, 25 Jan 2011 22:01:49 GMT') - self.assertEqual(obj.meta_data['foo-bar'], 'test 1') - self.assertEqual(obj.meta_data['bar-foo'], 'test 2') - - def test_get_object_object_name_encoding(self): - obj = self.driver.get_object(container_name='test_container', - object_name='~/test_object/') - self.assertEqual(obj.name, '~/test_object/') - - def test_get_object_not_found(self): - try: - self.driver.get_object(container_name='test_container', - object_name='not_found') - except ObjectDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_container_success(self): - container = self.driver.create_container( - container_name='test_create_container') - self.assertTrue(isinstance(container, Container)) - self.assertEqual(container.name, 'test_create_container') - self.assertEqual(container.extra['object_count'], 0) - - def test_create_container_already_exists(self): - CloudFilesMockHttp.type = 'ALREADY_EXISTS' - - try: - self.driver.create_container( - container_name='test_create_container') - except ContainerAlreadyExistsError: - pass - else: - self.fail( - 'Container already exists but an exception was not thrown') - - def test_create_container_invalid_name_too_long(self): - name = ''.join(['x' for x in range(0, 257)]) - try: - self.driver.create_container(container_name=name) - except InvalidContainerNameError: - pass - else: - self.fail( - 'Invalid name was provided (name is too long)' - ', but exception was not thrown') - - def test_create_container_invalid_name_slashes_in_name(self): - try: - self.driver.create_container(container_name='test/slashes/') - except InvalidContainerNameError: - pass - else: - self.fail( - 'Invalid name was provided (name contains slashes)' - ', but exception was not thrown') - - def test_delete_container_success(self): - container = Container(name='foo_bar_container', extra={}, driver=self) - result = self.driver.delete_container(container=container) - self.assertTrue(result) - - def test_delete_container_not_found(self): - CloudFilesMockHttp.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, driver=self) - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail( - 'Container does not exist but an exception was not thrown') - - def test_delete_container_not_empty(self): - CloudFilesMockHttp.type = 'NOT_EMPTY' - container = Container(name='foo_bar_container', extra={}, driver=self) - try: - self.driver.delete_container(container=container) - except ContainerIsNotEmptyError: - pass - else: - self.fail('Container is not empty but an exception was not thrown') - - def test_download_object_success(self): - container = Container(name='foo_bar_container', extra={}, driver=self) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=CloudFilesStorageDriver) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertTrue(result) - - def test_download_object_invalid_file_size(self): - CloudFilesMockRawResponse.type = 'INVALID_SIZE' - container = Container(name='foo_bar_container', extra={}, driver=self) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=CloudFilesStorageDriver) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertFalse(result) - - def test_download_object_success_not_found(self): - CloudFilesMockRawResponse.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, driver=self) - - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, - meta_data=None, - driver=CloudFilesStorageDriver) - destination_path = os.path.abspath(__file__) + '.temp' - try: - self.driver.download_object( - obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - except ObjectDoesNotExistError: - pass - else: - self.fail('Object does not exist but an exception was not thrown') - - def test_download_object_as_stream(self): - container = Container(name='foo_bar_container', extra={}, driver=self) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=CloudFilesStorageDriver) - - stream = self.driver.download_object_as_stream( - obj=obj, chunk_size=None) - self.assertTrue(hasattr(stream, '__iter__')) - - def test_upload_object_success(self): - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, 'hash343hhash89h932439jsaa89', 1000 - - old_func = CloudFilesStorageDriver._upload_file - CloudFilesStorageDriver._upload_file = upload_file - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object( - file_path=file_path, container=container, - extra=extra, object_name=object_name) - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, 1000) - self.assertTrue('some-value' in obj.meta_data) - CloudFilesStorageDriver._upload_file = old_func - - def test_upload_object_zero_size_object(self): - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, 'hash343hhash89h932439jsaa89', 0 - - old_func = CloudFilesStorageDriver._upload_file - old_request = self.driver.connection.request - CloudFilesStorageDriver._upload_file = upload_file - file_path = os.path.join(os.path.dirname(__file__), '__init__.py') - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'empty' - extra = {} - - def func(*args, **kwargs): - self.assertEqual(kwargs['headers']['Content-Length'], 0) - func.called = True - return old_request(*args, **kwargs) - - self.driver.connection.request = func - func.called = False - obj = self.driver.upload_object( - file_path=file_path, container=container, - extra=extra, object_name=object_name) - self.assertEqual(obj.name, 'empty') - self.assertEqual(obj.size, 0) - self.assertTrue(func.called) - CloudFilesStorageDriver._upload_file = old_func - self.driver.connection.request = old_request - - def test_upload_object_invalid_hash(self): - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, 'hash343hhash89h932439jsaa89', 1000 - - CloudFilesMockRawResponse.type = 'INVALID_HASH' - - old_func = CloudFilesStorageDriver._upload_file - CloudFilesStorageDriver._upload_file = upload_file - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_upload' - try: - self.driver.upload_object(file_path=file_path, container=container, - object_name=object_name, - verify_hash=True) - except ObjectHashMismatchError: - pass - else: - self.fail( - 'Invalid hash was returned but an exception was not thrown') - finally: - CloudFilesStorageDriver._upload_file = old_func - - def test_upload_object_no_content_type(self): - def no_content_type(name): - return None, None - - old_func = libcloud.utils.files.guess_file_mime_type - libcloud.utils.files.guess_file_mime_type = no_content_type - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_upload' - - obj = self.driver.upload_object(file_path=file_path, verify_hash=False, - container=container, - object_name=object_name) - - self.assertEqual(obj.name, object_name) - libcloud.utils.files.guess_file_mime_type = old_func - - def test_upload_object_error(self): - def dummy_content_type(name): - return 'application/zip', None - - def send(instance): - raise Exception('') - - old_func1 = libcloud.utils.files.guess_file_mime_type - libcloud.utils.files.guess_file_mime_type = dummy_content_type - old_func2 = CloudFilesMockHttp.send - CloudFilesMockHttp.send = send - - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_upload' - try: - self.driver.upload_object( - file_path=file_path, - container=container, - object_name=object_name) - except LibcloudError: - pass - else: - self.fail( - 'Timeout while uploading but an exception was not thrown') - finally: - libcloud.utils.files.guess_file_mime_type = old_func1 - CloudFilesMockHttp.send = old_func2 - - def test_upload_object_inexistent_file(self): - def dummy_content_type(name): - return 'application/zip', None - - old_func = libcloud.utils.files.guess_file_mime_type - libcloud.utils.files.guess_file_mime_type = dummy_content_type - - file_path = os.path.abspath(__file__ + '.inexistent') - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_upload' - try: - self.driver.upload_object( - file_path=file_path, - container=container, - object_name=object_name) - except OSError: - pass - else: - self.fail('Inexistent but an exception was not thrown') - finally: - libcloud.utils.files.guess_file_mime_type = old_func - - def test_upload_object_via_stream(self): - def dummy_content_type(name): - return 'application/zip', None - - old_func = libcloud.utils.files.guess_file_mime_type - libcloud.utils.files.guess_file_mime_type = dummy_content_type - - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_stream_data' - iterator = DummyIterator(data=['2', '3', '5']) - try: - self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator) - finally: - libcloud.utils.files.guess_file_mime_type = old_func - - def test_delete_object_success(self): - container = Container(name='foo_bar_container', extra={}, driver=self) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=CloudFilesStorageDriver) - status = self.driver.delete_object(obj=obj) - self.assertTrue(status) - - def test_delete_object_not_found(self): - CloudFilesMockHttp.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, driver=self) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=CloudFilesStorageDriver) - try: - self.driver.delete_object(obj=obj) - except ObjectDoesNotExistError: - pass - else: - self.fail('Object does not exist but an exception was not thrown') - - def test_ex_get_meta_data(self): - meta_data = self.driver.ex_get_meta_data() - self.assertTrue(isinstance(meta_data, dict)) - self.assertTrue('object_count' in meta_data) - self.assertTrue('container_count' in meta_data) - self.assertTrue('bytes_used' in meta_data) - self.assertTrue('temp_url_key' in meta_data) - - def test_ex_purge_object_from_cdn(self): - CloudFilesMockHttp.type = 'PURGE_SUCCESS' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self) - - self.assertTrue(self.driver.ex_purge_object_from_cdn(obj=obj)) - - def test_ex_purge_object_from_cdn_with_email(self): - CloudFilesMockHttp.type = 'PURGE_SUCCESS_EMAIL' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self) - self.assertTrue(self.driver.ex_purge_object_from_cdn(obj=obj, - email='test@test.com')) - - @mock.patch('os.path.getsize') - def test_ex_multipart_upload_object_for_small_files(self, getsize_mock): - getsize_mock.return_value = 0 - - old_func = CloudFilesStorageDriver.upload_object - mocked_upload_object = mock.Mock(return_value="test") - CloudFilesStorageDriver.upload_object = mocked_upload_object - - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_upload' - obj = self.driver.ex_multipart_upload_object( - file_path=file_path, container=container, - object_name=object_name) - CloudFilesStorageDriver.upload_object = old_func - - self.assertTrue(mocked_upload_object.called) - self.assertEqual(obj, "test") - - def test_ex_multipart_upload_object_success(self): - _upload_object_part = CloudFilesStorageDriver._upload_object_part - _upload_object_manifest = CloudFilesStorageDriver._upload_object_manifest - - mocked__upload_object_part = mock.Mock(return_value="test_part") - mocked__upload_object_manifest = mock.Mock( - return_value="test_manifest") - - CloudFilesStorageDriver._upload_object_part = mocked__upload_object_part - CloudFilesStorageDriver._upload_object_manifest = mocked__upload_object_manifest - - parts = 5 - file_path = os.path.abspath(__file__) - chunk_size = int(math.ceil(float(os.path.getsize(file_path)) / parts)) - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = 'foo_test_upload' - self.driver.ex_multipart_upload_object( - file_path=file_path, container=container, - object_name=object_name, chunk_size=chunk_size) - - CloudFilesStorageDriver._upload_object_part = _upload_object_part - CloudFilesStorageDriver._upload_object_manifest = _upload_object_manifest - - self.assertEqual(mocked__upload_object_part.call_count, parts) - self.assertTrue(mocked__upload_object_manifest.call_count, 1) - - def test__upload_object_part(self): - _put_object = CloudFilesStorageDriver._put_object - mocked__put_object = mock.Mock(return_value="test") - CloudFilesStorageDriver._put_object = mocked__put_object - - part_number = 7 - object_name = "test_object" - expected_name = object_name + '/%08d' % part_number - container = Container(name='foo_bar_container', extra={}, driver=self) - - self.driver._upload_object_part(container, object_name, - part_number, None) - - CloudFilesStorageDriver._put_object = _put_object - - func_kwargs = tuple(mocked__put_object.call_args)[1] - self.assertEqual(func_kwargs['object_name'], expected_name) - self.assertEqual(func_kwargs['container'], container) - - def test__upload_object_manifest(self): - hash_function = self.driver._get_hash_function() - hash_function.update(b('')) - data_hash = hash_function.hexdigest() - - fake_response = type('CloudFilesResponse', (), {'headers': - {'etag': data_hash} - }) - - _request = self.driver.connection.request - mocked_request = mock.Mock(return_value=fake_response) - self.driver.connection.request = mocked_request - - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = "test_object" - - self.driver._upload_object_manifest(container, object_name) - - func_args, func_kwargs = tuple(mocked_request.call_args) - - self.driver.connection.request = _request - - self.assertEqual( - func_args[0], "/" + container.name + "/" + object_name) - self.assertEqual(func_kwargs["headers"]["X-Object-Manifest"], - container.name + "/" + object_name + "/") - self.assertEqual(func_kwargs["method"], "PUT") - - def test__upload_object_manifest_wrong_hash(self): - fake_response = type('CloudFilesResponse', (), {'headers': - {'etag': '0000000'}}) - - _request = self.driver.connection.request - mocked_request = mock.Mock(return_value=fake_response) - self.driver.connection.request = mocked_request - - container = Container(name='foo_bar_container', extra={}, driver=self) - object_name = "test_object" - - try: - self.driver._upload_object_manifest(container, object_name) - except ObjectHashMismatchError: - pass - else: - self.fail('Exception was not thrown') - finally: - self.driver.connection.request = _request - - def test_create_container_put_object_name_encoding(self): - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, 'hash343hhash89h932439jsaa89', 1000 - - old_func = CloudFilesStorageDriver._upload_file - CloudFilesStorageDriver._upload_file = upload_file - - container_name = 'speci@l_name' - object_name = 'm@obj€ct' - file_path = os.path.abspath(__file__) - - container = self.driver.create_container(container_name=container_name) - self.assertEqual(container.name, container_name) - - obj = self.driver.upload_object( - file_path=file_path, container=container, - object_name=object_name) - self.assertEqual(obj.name, object_name) - CloudFilesStorageDriver._upload_file = old_func - - def test_ex_enable_static_website(self): - container = Container(name='foo_bar_container', extra={}, driver=self) - result = self.driver.ex_enable_static_website(container=container, - index_file='index.html') - self.assertTrue(result) - - def test_ex_set_error_page(self): - container = Container(name='foo_bar_container', extra={}, driver=self) - result = self.driver.ex_set_error_page(container=container, - file_name='error.html') - self.assertTrue(result) - - def test_ex_set_account_metadata_temp_url_key(self): - result = self.driver.ex_set_account_metadata_temp_url_key("a key") - self.assertTrue(result) - - @mock.patch("libcloud.storage.drivers.cloudfiles.time") - def test_ex_get_object_temp_url(self, time): - time.return_value = 0 - self.driver.ex_get_meta_data = mock.Mock() - self.driver.ex_get_meta_data.return_value = {'container_count': 1, - 'object_count': 1, - 'bytes_used': 1, - 'temp_url_key': 'foo'} - container = Container(name='foo_bar_container', extra={}, driver=self) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self) - hmac_body = "%s\n%s\n%s" % ('GET', 60, - "/v1/MossoCloudFS/foo_bar_container/foo_bar_object") - sig = hmac.new(b('foo'), b(hmac_body), sha1).hexdigest() - ret = self.driver.ex_get_object_temp_url(obj, 'GET') - temp_url = ('https://storage4.%s1.clouddrive.com/v1/MossoCloudFS/' - 'foo_bar_container/foo_bar_object?temp_url_expires=60&temp_url_sig=%s' % - (self.region, sig)) - - self.assertEqual(''.join(sorted(ret)), ''.join(sorted(temp_url))) - - def test_ex_get_object_temp_url_no_key_raises_key_error(self): - self.driver.ex_get_meta_data = mock.Mock() - self.driver.ex_get_meta_data.return_value = {'container_count': 1, - 'object_count': 1, - 'bytes_used': 1, - 'temp_url_key': None} - container = Container(name='foo_bar_container', extra={}, driver=self) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self) - self.assertRaises( - KeyError, self.driver.ex_get_object_temp_url, obj, 'GET') - - def _remove_test_file(self): - file_path = os.path.abspath(__file__) + '.temp' - - try: - os.unlink(file_path) - except OSError: - pass - - -class CloudFilesDeprecatedUSTests(CloudFilesTests): - driver_klass = CloudFilesUSStorageDriver - region = 'ord' - - -class CloudFilesDeprecatedUKTests(CloudFilesTests): - driver_klass = CloudFilesUKStorageDriver - region = 'lon' - - -class CloudFilesMockHttp(StorageMockHttp, MockHttpTestCase): - - fixtures = StorageFileFixtures('cloudfiles') - base_headers = {'content-type': 'application/json; charset=UTF-8'} - - # fake auth token response - def _v2_0_tokens(self, method, url, body, headers): - headers = copy.deepcopy(self.base_headers) - body = self.fixtures.load('_v2_0__auth.json') - return (httplib.OK, body, headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_MALFORMED_JSON(self, method, url, body, headers): - # test_invalid_json_throws_exception - body = 'broken: json /*"' - return (httplib.NO_CONTENT, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_EMPTY(self, method, url, body, headers): - return (httplib.NO_CONTENT, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS(self, method, url, body, headers): - headers = copy.deepcopy(self.base_headers) - if method == 'GET': - # list_containers - body = self.fixtures.load('list_containers.json') - status_code = httplib.OK - elif method == 'HEAD': - # get_meta_data - body = self.fixtures.load('meta_data.json') - status_code = httplib.NO_CONTENT - headers.update({'x-account-container-count': 10, - 'x-account-object-count': 400, - 'x-account-bytes-used': 1234567 - }) - elif method == 'POST': - body = '' - status_code = httplib.NO_CONTENT - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_not_found(self, method, url, body, headers): - # test_get_object_not_found - if method == 'HEAD': - body = '' - else: - raise ValueError('Invalid method') - - return (httplib.NOT_FOUND, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_container_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('list_container_objects_empty.json') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_20container_201_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('list_container_objects_empty.json') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_container(self, method, url, body, headers): - headers = copy.deepcopy(self.base_headers) - if method == 'GET': - # list_container_objects - if url.find('marker') == -1: - body = self.fixtures.load('list_container_objects.json') - status_code = httplib.OK - else: - body = '' - status_code = httplib.NO_CONTENT - elif method == 'HEAD': - # get_container - body = self.fixtures.load('list_container_objects_empty.json') - status_code = httplib.NO_CONTENT - headers.update({'x-container-object-count': 800, - 'x-container-bytes-used': 1234568 - }) - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_container_ITERATOR(self, method, url, body, headers): - headers = copy.deepcopy(self.base_headers) - # list_container_objects - if url.find('foo-test-3') != -1: - body = self.fixtures.load( - 'list_container_objects_not_exhausted2.json') - status_code = httplib.OK - elif url.find('foo-test-5') != -1: - body = '' - status_code = httplib.NO_CONTENT - else: - # First request - body = self.fixtures.load( - 'list_container_objects_not_exhausted1.json') - status_code = httplib.OK - - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_container_not_found( - self, method, url, body, headers): - # test_get_container_not_found - if method == 'HEAD': - body = '' - else: - raise ValueError('Invalid method') - - return (httplib.NOT_FOUND, body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_container_test_object( - self, method, url, body, headers): - headers = copy.deepcopy(self.base_headers) - if method == 'HEAD': - # get_object - body = self.fixtures.load('list_container_objects_empty.json') - status_code = httplib.NO_CONTENT - headers.update({'content-length': 555, - 'last-modified': 'Tue, 25 Jan 2011 22:01:49 GMT', - 'etag': '6b21c4a111ac178feacf9ec9d0c71f17', - 'x-object-meta-foo-bar': 'test 1', - 'x-object-meta-bar-foo': 'test 2', - 'content-type': 'application/zip'}) - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_container__7E_test_object( - self, method, url, body, headers): - headers = copy.deepcopy(self.base_headers) - if method == 'HEAD': - # get_object_name_encoding - body = self.fixtures.load('list_container_objects_empty.json') - status_code = httplib.NO_CONTENT - headers.update({'content-length': 555, - 'last-modified': 'Tue, 25 Jan 2011 22:01:49 GMT', - 'etag': '6b21c4a111ac178feacf9ec9d0c71f17', - 'x-object-meta-foo-bar': 'test 1', - 'x-object-meta-bar-foo': 'test 2', - 'content-type': 'application/zip'}) - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_create_container( - self, method, url, body, headers): - # test_create_container_success - headers = copy.deepcopy(self.base_headers) - body = self.fixtures.load('list_container_objects_empty.json') - headers = copy.deepcopy(self.base_headers) - headers.update({'content-length': 18, - 'date': 'Mon, 28 Feb 2011 07:52:57 GMT' - }) - status_code = httplib.CREATED - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_speci_40l_name(self, method, url, body, headers): - # test_create_container_put_object_name_encoding - # Verify that the name is properly url encoded - container_name = 'speci@l_name' - encoded_container_name = urlquote(container_name) - self.assertTrue(encoded_container_name in url) - - headers = copy.deepcopy(self.base_headers) - body = self.fixtures.load('list_container_objects_empty.json') - headers = copy.deepcopy(self.base_headers) - headers.update({'content-length': 18, - 'date': 'Mon, 28 Feb 2011 07:52:57 GMT' - }) - status_code = httplib.CREATED - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_test_create_container_ALREADY_EXISTS( - self, method, url, body, headers): - # test_create_container_already_exists - headers = copy.deepcopy(self.base_headers) - body = self.fixtures.load('list_container_objects_empty.json') - headers.update({'content-type': 'text/plain'}) - status_code = httplib.ACCEPTED - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container(self, method, url, body, headers): - if method == 'DELETE': - # test_delete_container_success - body = self.fixtures.load('list_container_objects_empty.json') - headers = self.base_headers - status_code = httplib.NO_CONTENT - elif method == 'POST': - # test_ex_enable_static_website - body = '' - headers = self.base_headers - status_code = httplib.ACCEPTED - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_object_PURGE_SUCCESS( - self, method, url, body, headers): - - if method == 'DELETE': - # test_ex_purge_from_cdn - headers = self.base_headers - status_code = httplib.NO_CONTENT - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_object_PURGE_SUCCESS_EMAIL( - self, method, url, body, headers): - - if method == 'DELETE': - # test_ex_purge_from_cdn_with_email - self.assertEqual(headers['X-Purge-Email'], 'test@test.com') - headers = self.base_headers - status_code = httplib.NO_CONTENT - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_NOT_FOUND( - self, method, url, body, headers): - - if method == 'DELETE': - # test_delete_container_not_found - body = self.fixtures.load('list_container_objects_empty.json') - headers = self.base_headers - status_code = httplib.NOT_FOUND - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_NOT_EMPTY( - self, method, url, body, headers): - - if method == 'DELETE': - # test_delete_container_not_empty - body = self.fixtures.load('list_container_objects_empty.json') - headers = self.base_headers - status_code = httplib.CONFLICT - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_foo_bar_object( - self, method, url, body, headers): - - if method == 'DELETE': - # test_delete_object_success - body = self.fixtures.load('list_container_objects_empty.json') - headers = self.base_headers - status_code = httplib.NO_CONTENT - return (status_code, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_foo_bar_object_NOT_FOUND( - self, method, url, body, headers): - - if method == 'DELETE': - # test_delete_object_success - body = self.fixtures.load('list_container_objects_empty.json') - headers = self.base_headers - status_code = httplib.NOT_FOUND - - return (status_code, body, headers, httplib.responses[httplib.OK]) - - -class CloudFilesMockRawResponse(MockRawResponse): - - fixtures = StorageFileFixtures('cloudfiles') - base_headers = {'content-type': 'application/json; charset=UTF-8'} - - def _v1_MossoCloudFS_foo_bar_container_foo_test_upload( - self, method, url, body, headers): - # test_object_upload_success - - body = '' - headers = {} - headers.update(self.base_headers) - headers['etag'] = 'hash343hhash89h932439jsaa89' - return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_speci_40l_name_m_40obj_E2_82_ACct(self, method, url, - body, headers): - # test_create_container_put_object_name_encoding - # Verify that the name is properly url encoded - object_name = 'm@obj€ct' - urlquote(object_name) - - headers = copy.deepcopy(self.base_headers) - body = '' - headers['etag'] = 'hash343hhash89h932439jsaa89' - return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_empty(self, method, url, body, - headers): - # test_upload_object_zero_size_object - body = '' - headers = {} - headers.update(self.base_headers) - headers['etag'] = 'hash343hhash89h932439jsaa89' - return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_foo_test_upload_INVALID_HASH( - self, method, url, body, headers): - # test_object_upload_invalid_hash - body = '' - headers = {} - headers.update(self.base_headers) - headers['etag'] = 'foobar' - return (httplib.CREATED, body, headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_foo_bar_object( - self, method, url, body, headers): - - # test_download_object_success - body = self._generate_random_data(1000) - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_foo_bar_object_INVALID_SIZE( - self, method, url, body, headers): - # test_download_object_invalid_file_size - body = self._generate_random_data(100) - return (httplib.OK, body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_foo_bar_object_NOT_FOUND( - self, method, url, body, headers): - body = '' - return (httplib.NOT_FOUND, body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _v1_MossoCloudFS_foo_bar_container_foo_test_stream_data( - self, method, url, body, headers): - - # test_upload_object_via_stream_success - headers = {} - headers.update(self.base_headers) - headers['etag'] = '577ef1154f3240ad5b9b413aa7346a1e' - body = 'test' - return (httplib.CREATED, - body, - headers, - httplib.responses[httplib.OK]) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/storage/test_google_storage.py b/awx/lib/site-packages/libcloud/test/storage/test_google_storage.py deleted file mode 100644 index ed6dd57f91..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/test_google_storage.py +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.storage.drivers.google_storage import GoogleStorageDriver -from libcloud.test.storage.test_s3 import S3Tests, S3MockHttp - -from libcloud.test.file_fixtures import StorageFileFixtures -from libcloud.test.secrets import STORAGE_GOOGLE_STORAGE_PARAMS - - -class GoogleStorageMockHttp(S3MockHttp): - fixtures = StorageFileFixtures('google_storage') - - -class GoogleStorageTests(S3Tests): - driver_type = GoogleStorageDriver - driver_args = STORAGE_GOOGLE_STORAGE_PARAMS - mock_response_klass = GoogleStorageMockHttp - - def test_billing_not_enabled(self): - # TODO - pass - - def test_token(self): - # Not supported on Google Storage - pass - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/storage/test_local.py b/awx/lib/site-packages/libcloud/test/storage/test_local.py deleted file mode 100644 index e326a79587..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/test_local.py +++ /dev/null @@ -1,334 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import with_statement - -import os -import sys -import shutil -import unittest -import tempfile - -import mock - -from libcloud.common.types import LibcloudError -from libcloud.storage.base import Container -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ContainerAlreadyExistsError -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import InvalidContainerNameError - -try: - from libcloud.storage.drivers.local import LocalStorageDriver - from libcloud.storage.drivers.local import LockLocalStorage - from lockfile import LockTimeout -except ImportError: - print('lockfile library is not available, skipping local_storage tests...') - LocalStorageDriver = None - LockTimeout = None - - -class LocalTests(unittest.TestCase): - driver_type = LocalStorageDriver - - @classmethod - def create_driver(self): - self.key = tempfile.mkdtemp() - return self.driver_type(self.key, None) - - def setUp(self): - self.driver = self.create_driver() - - def tearDown(self): - shutil.rmtree(self.key) - self.key = None - - def make_tmp_file(self): - _, tmppath = tempfile.mkstemp() - - with open(tmppath, 'w') as fp: - fp.write('blah' * 1024) - - return tmppath - - def remove_tmp_file(self, tmppath): - os.unlink(tmppath) - - def test_list_containers_empty(self): - containers = self.driver.list_containers() - self.assertEqual(len(containers), 0) - - def test_containers_success(self): - self.driver.create_container('test1') - self.driver.create_container('test2') - containers = self.driver.list_containers() - self.assertEqual(len(containers), 2) - - container = containers[1] - - self.assertTrue('creation_time' in container.extra) - self.assertTrue('modify_time' in container.extra) - self.assertTrue('access_time' in container.extra) - - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 0) - - objects = container.list_objects() - self.assertEqual(len(objects), 0) - - for container in containers: - self.driver.delete_container(container) - - def test_objects_success(self): - tmppath = self.make_tmp_file() - tmpfile = open(tmppath) - - container = self.driver.create_container('test3') - obj1 = container.upload_object(tmppath, 'object1') - obj2 = container.upload_object(tmppath, 'path/object2') - obj3 = container.upload_object(tmppath, 'path/to/object3') - obj4 = container.upload_object(tmppath, 'path/to/object4.ext') - obj5 = container.upload_object_via_stream(tmpfile, 'object5') - - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 5) - - for obj in objects: - self.assertNotEqual(obj.hash, None) - self.assertEqual(obj.size, 4096) - self.assertEqual(obj.container.name, 'test3') - self.assertTrue('creation_time' in obj.extra) - self.assertTrue('modify_time' in obj.extra) - self.assertTrue('access_time' in obj.extra) - - obj1.delete() - obj2.delete() - - objects = container.list_objects() - self.assertEqual(len(objects), 3) - - container.delete_object(obj3) - container.delete_object(obj4) - container.delete_object(obj5) - - objects = container.list_objects() - self.assertEqual(len(objects), 0) - - container.delete() - tmpfile.close() - self.remove_tmp_file(tmppath) - - def test_get_container_doesnt_exist(self): - try: - self.driver.get_container(container_name='container1') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_container_success(self): - self.driver.create_container('test4') - container = self.driver.get_container(container_name='test4') - self.assertTrue(container.name, 'test4') - container.delete() - - def test_get_object_container_doesnt_exist(self): - try: - self.driver.get_object(container_name='test-inexistent', - object_name='test') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_object_success(self): - tmppath = self.make_tmp_file() - container = self.driver.create_container('test5') - container.upload_object(tmppath, 'test') - - obj = self.driver.get_object(container_name='test5', - object_name='test') - - self.assertEqual(obj.name, 'test') - self.assertEqual(obj.container.name, 'test5') - self.assertEqual(obj.size, 4096) - self.assertNotEqual(obj.hash, None) - self.assertTrue('creation_time' in obj.extra) - self.assertTrue('modify_time' in obj.extra) - self.assertTrue('access_time' in obj.extra) - - obj.delete() - container.delete() - self.remove_tmp_file(tmppath) - - def test_create_container_invalid_name(self): - try: - self.driver.create_container(container_name='new/container') - except InvalidContainerNameError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_container_already_exists(self): - container = self.driver.create_container( - container_name='new-container') - try: - self.driver.create_container(container_name='new-container') - except ContainerAlreadyExistsError: - pass - else: - self.fail('Exception was not thrown') - - # success - self.driver.delete_container(container) - - def test_create_container_success(self): - name = 'new_container' - container = self.driver.create_container(container_name=name) - self.assertEqual(container.name, name) - self.driver.delete_container(container) - - def test_delete_container_doesnt_exist(self): - container = Container(name='new_container', extra=None, - driver=self.driver) - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_delete_container_not_empty(self): - tmppath = self.make_tmp_file() - container = self.driver.create_container('test6') - obj = container.upload_object(tmppath, 'test') - - try: - self.driver.delete_container(container=container) - except ContainerIsNotEmptyError: - pass - else: - self.fail('Exception was not thrown') - - # success - obj.delete() - self.remove_tmp_file(tmppath) - self.assertTrue(self.driver.delete_container(container=container)) - - def test_delete_container_not_found(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail('Container does not exist but an exception was not' + - 'thrown') - - def test_delete_container_success(self): - container = self.driver.create_container('test7') - self.assertTrue(self.driver.delete_container(container=container)) - - def test_download_object_success(self): - tmppath = self.make_tmp_file() - container = self.driver.create_container('test6') - obj = container.upload_object(tmppath, 'test') - - destination_path = tmppath + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - - self.assertTrue(result) - - obj.delete() - container.delete() - self.remove_tmp_file(tmppath) - os.unlink(destination_path) - - def test_download_object_and_overwrite(self): - tmppath = self.make_tmp_file() - container = self.driver.create_container('test6') - obj = container.upload_object(tmppath, 'test') - - destination_path = tmppath + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - - self.assertTrue(result) - - try: - self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - except LibcloudError: - pass - else: - self.fail('Exception was not thrown') - - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=True, - delete_on_failure=True) - - self.assertTrue(result) - - # success - obj.delete() - container.delete() - self.remove_tmp_file(tmppath) - os.unlink(destination_path) - - def test_download_object_as_stream_success(self): - tmppath = self.make_tmp_file() - container = self.driver.create_container('test6') - obj = container.upload_object(tmppath, 'test') - - stream = self.driver.download_object_as_stream(obj=obj, - chunk_size=1024) - - self.assertTrue(hasattr(stream, '__iter__')) - - data = '' - for buff in stream: - data += buff.decode('utf-8') - - self.assertTrue(len(data), 4096) - - obj.delete() - container.delete() - self.remove_tmp_file(tmppath) - - @mock.patch("lockfile.mkdirlockfile.MkdirLockFile.acquire", - mock.MagicMock(side_effect=LockTimeout)) - def test_proper_lockfile_imports(self): - # LockLocalStorage was previously using an un-imported exception - # in its __enter__ method, so the following would raise a NameError. - lls = LockLocalStorage("blah") - self.assertRaises(LibcloudError, lls.__enter__) - - -if not LocalStorageDriver: - class LocalTests(unittest.TestCase): # NOQA - pass - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/storage/test_s3.py b/awx/lib/site-packages/libcloud/test/storage/test_s3.py deleted file mode 100644 index 667e57c8c9..0000000000 --- a/awx/lib/site-packages/libcloud/test/storage/test_s3.py +++ /dev/null @@ -1,979 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys -import unittest - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import urlparse -from libcloud.utils.py3 import parse_qs - -from libcloud.common.types import InvalidCredsError -from libcloud.common.types import LibcloudError, MalformedResponseError -from libcloud.storage.base import Container, Object -from libcloud.storage.types import ContainerDoesNotExistError -from libcloud.storage.types import ContainerIsNotEmptyError -from libcloud.storage.types import InvalidContainerNameError -from libcloud.storage.types import ObjectDoesNotExistError -from libcloud.storage.types import ObjectHashMismatchError -from libcloud.storage.drivers.s3 import S3StorageDriver, S3USWestStorageDriver -from libcloud.storage.drivers.s3 import S3EUWestStorageDriver -from libcloud.storage.drivers.s3 import S3APSEStorageDriver -from libcloud.storage.drivers.s3 import S3APNEStorageDriver -from libcloud.storage.drivers.s3 import CHUNK_SIZE -from libcloud.storage.drivers.dummy import DummyIterator - -from libcloud.test import StorageMockHttp, MockRawResponse # pylint: disable-msg=E0611 -from libcloud.test import MockHttpTestCase # pylint: disable-msg=E0611 -from libcloud.test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611 -from libcloud.test.secrets import STORAGE_S3_PARAMS - - -class S3MockHttp(StorageMockHttp, MockHttpTestCase): - - fixtures = StorageFileFixtures('s3') - base_headers = {} - - def _UNAUTHORIZED(self, method, url, body, headers): - return (httplib.UNAUTHORIZED, - '', - self.base_headers, - httplib.responses[httplib.OK]) - - def _DIFFERENT_REGION(self, method, url, body, headers): - return (httplib.MOVED_PERMANENTLY, - '', - self.base_headers, - httplib.responses[httplib.OK]) - - def _list_containers_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('list_containers_empty.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _list_containers_TOKEN(self, method, url, body, headers): - self.assertEqual(headers['x-amz-security-token'], 'asdf') - body = self.fixtures.load('list_containers_empty.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _list_containers(self, method, url, body, headers): - body = self.fixtures.load('list_containers.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _test_container_EMPTY(self, method, url, body, headers): - body = self.fixtures.load('list_container_objects_empty.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _test_container(self, method, url, body, headers): - body = self.fixtures.load('list_container_objects.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _test_container_ITERATOR(self, method, url, body, headers): - if url.find('3.zip') == -1: - # First part of the response (first 3 objects) - file_name = 'list_container_objects_not_exhausted1.xml' - else: - file_name = 'list_container_objects_not_exhausted2.xml' - - body = self.fixtures.load(file_name) - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _test2_get_object(self, method, url, body, headers): - body = self.fixtures.load('list_container_objects.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _test2_test_get_object(self, method, url, body, headers): - # test_get_object - body = self.fixtures.load('list_containers.xml') - headers = {'content-type': 'application/zip', - 'etag': '"e31208wqsdoj329jd"', - 'x-amz-meta-rabbits': 'monkeys', - 'content-length': 12345, - 'last-modified': 'Thu, 13 Sep 2012 07:13:22 GMT' - } - - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _new_container_INVALID_NAME(self, method, url, body, headers): - # test_create_container - return (httplib.BAD_REQUEST, - body, - headers, - httplib.responses[httplib.OK]) - - def _new_container_ALREADY_EXISTS(self, method, url, body, headers): - # test_create_container - return (httplib.CONFLICT, - body, - headers, - httplib.responses[httplib.OK]) - - def _new_container(self, method, url, body, headers): - # test_create_container, test_delete_container - - if method == 'PUT': - status = httplib.OK - elif method == 'DELETE': - status = httplib.NO_CONTENT - - return (status, - body, - headers, - httplib.responses[httplib.OK]) - - def _new_container_DOESNT_EXIST(self, method, url, body, headers): - # test_delete_container - return (httplib.NOT_FOUND, - body, - headers, - httplib.responses[httplib.OK]) - - def _new_container_NOT_EMPTY(self, method, url, body, headers): - # test_delete_container - return (httplib.CONFLICT, - body, - headers, - httplib.responses[httplib.OK]) - - def _test1_get_container(self, method, url, body, headers): - body = self.fixtures.load('list_container_objects.xml') - return (httplib.OK, - body, - self.base_headers, - httplib.responses[httplib.OK]) - - def _container1_get_container(self, method, url, body, headers): - return (httplib.NOT_FOUND, - '', - self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _test_inexistent_get_object(self, method, url, body, headers): - return (httplib.NOT_FOUND, - '', - self.base_headers, - httplib.responses[httplib.NOT_FOUND]) - - def _foo_bar_container(self, method, url, body, headers): - # test_delete_container - return (httplib.NO_CONTENT, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_NOT_FOUND(self, method, url, body, headers): - # test_delete_container_not_found - return (httplib.NOT_FOUND, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_bar_object_NOT_FOUND(self, method, url, body, - headers): - # test_delete_object_not_found - return (httplib.NOT_FOUND, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_bar_object(self, method, url, body, headers): - # test_delete_object - return (httplib.NO_CONTENT, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_test_stream_data(self, method, url, body, - headers): - # test_upload_object_via_stream - body = '' - headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_test_stream_data_MULTIPART(self, method, url, - body, headers): - headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} - TEST_ID = 'VXBsb2FkIElEIGZvciA2aWWpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA' - - query_string = urlparse.urlsplit(url).query - query = parse_qs(query_string) - - if not query.get('uploadId', False): - self.fail('Request doesnt contain uploadId query parameter') - - upload_id = query['uploadId'][0] - if upload_id != TEST_ID: - self.fail('first uploadId doesnt match TEST_ID') - - if method == 'PUT': - # PUT is used for uploading the part. part number is mandatory - if not query.get('partNumber', False): - self.fail('Request is missing partNumber query parameter') - - body = '' - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - elif method == 'DELETE': - # DELETE is done for aborting the upload - body = '' - return (httplib.NO_CONTENT, - body, - headers, - httplib.responses[httplib.NO_CONTENT]) - - else: - # POST is done for committing the upload. Parse the XML and - # check if the commit is proper (TODO: XML Schema based check?) - commit = ET.fromstring(body) - count = 0 - - for part in commit.findall('Part'): - count += 1 - part_no = part.find('PartNumber').text - etag = part.find('ETag').text - - self.assertEqual(part_no, str(count)) - self.assertEqual(etag, headers['etag']) - - # Make sure that manifest contains at least one part - self.assertTrue(count >= 1) - - body = self.fixtures.load('complete_multipart.xml') - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_LIST_MULTIPART(self, method, url, body, headers): - query_string = urlparse.urlsplit(url).query - query = parse_qs(query_string) - - if 'key-marker' not in query: - body = self.fixtures.load('list_multipart_1.xml') - else: - body = self.fixtures.load('list_multipart_2.xml') - - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_my_divisor_LIST_MULTIPART(self, method, url, - body, headers): - body = '' - return (httplib.NO_CONTENT, - body, - headers, - httplib.responses[httplib.NO_CONTENT]) - - def _foo_bar_container_my_movie_m2ts_LIST_MULTIPART(self, method, url, - body, headers): - body = '' - return (httplib.NO_CONTENT, - body, - headers, - httplib.responses[httplib.NO_CONTENT]) - - -class S3MockRawResponse(MockRawResponse): - - fixtures = StorageFileFixtures('s3') - - def parse_body(self): - if len(self.body) == 0 and not self.parse_zero_length_body: - return self.body - - try: - body = ET.XML(self.body) - except: - raise MalformedResponseError("Failed to parse XML", - body=self.body, - driver=self.connection.driver) - return body - - def _foo_bar_container_foo_bar_object(self, method, url, body, headers): - # test_download_object_success - body = self._generate_random_data(1000) - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_test_upload_INVALID_HASH1(self, method, url, - body, headers): - body = '' - headers = {} - headers['etag'] = '"foobar"' - # test_upload_object_invalid_hash1 - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_test_upload_INVALID_HASH2(self, method, url, - body, headers): - # test_upload_object_invalid_hash2 - body = '' - headers = {'etag': '"hash343hhash89h932439jsaa89"'} - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_test_upload(self, method, url, body, headers): - # test_upload_object_success - body = '' - headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_bar_object_INVALID_SIZE(self, method, url, - body, headers): - # test_upload_object_invalid_file_size - body = '' - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_test_stream_data(self, method, url, body, - headers): - # test_upload_object_via_stream - body = '' - headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - - def _foo_bar_container_foo_test_stream_data_MULTIPART(self, method, url, - body, headers): - headers = {} - # POST is done for initiating multipart upload - if method == 'POST': - body = self.fixtures.load('initiate_multipart.xml') - return (httplib.OK, - body, - headers, - httplib.responses[httplib.OK]) - else: - body = '' - return (httplib.BAD_REQUEST, - body, - headers, - httplib.responses[httplib.BAD_REQUEST]) - - -class S3Tests(unittest.TestCase): - driver_type = S3StorageDriver - driver_args = STORAGE_S3_PARAMS - mock_response_klass = S3MockHttp - mock_raw_response_klass = S3MockRawResponse - - @classmethod - def create_driver(self): - return self.driver_type(*self.driver_args) - - def setUp(self): - self.driver_type.connectionCls.conn_classes = (None, - self.mock_response_klass) - self.driver_type.connectionCls.rawResponseCls = \ - self.mock_raw_response_klass - self.mock_response_klass.type = None - self.mock_raw_response_klass.type = None - self.driver = self.create_driver() - - def tearDown(self): - self._remove_test_file() - - def _remove_test_file(self): - file_path = os.path.abspath(__file__) + '.temp' - - try: - os.unlink(file_path) - except OSError: - pass - - def test_invalid_credentials(self): - self.mock_response_klass.type = 'UNAUTHORIZED' - try: - self.driver.list_containers() - except InvalidCredsError: - e = sys.exc_info()[1] - self.assertEqual(True, isinstance(e, InvalidCredsError)) - else: - self.fail('Exception was not thrown') - - def test_token(self): - self.mock_response_klass.type = 'list_containers_TOKEN' - self.driver = self.driver_type(*self.driver_args, token='asdf') - self.driver.list_containers() - - def test_bucket_is_located_in_different_region(self): - self.mock_response_klass.type = 'DIFFERENT_REGION' - try: - self.driver.list_containers() - except LibcloudError: - pass - else: - self.fail('Exception was not thrown') - - def test_list_containers_empty(self): - self.mock_response_klass.type = 'list_containers_EMPTY' - containers = self.driver.list_containers() - self.assertEqual(len(containers), 0) - - def test_list_containers_success(self): - self.mock_response_klass.type = 'list_containers' - containers = self.driver.list_containers() - self.assertEqual(len(containers), 2) - - self.assertTrue('creation_date' in containers[1].extra) - - def test_list_container_objects_empty(self): - self.mock_response_klass.type = 'EMPTY' - container = Container(name='test_container', extra={}, - driver=self.driver) - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 0) - - def test_list_container_objects_success(self): - self.mock_response_klass.type = None - container = Container(name='test_container', extra={}, - driver=self.driver) - objects = self.driver.list_container_objects(container=container) - self.assertEqual(len(objects), 1) - - obj = [o for o in objects if o.name == '1.zip'][0] - self.assertEqual(obj.hash, '4397da7a7649e8085de9916c240e8166') - self.assertEqual(obj.size, 1234567) - self.assertEqual(obj.container.name, 'test_container') - self.assertEqual( - obj.extra['last_modified'], '2011-04-09T19:05:18.000Z') - self.assertTrue('owner' in obj.meta_data) - - def test_list_container_objects_iterator_has_more(self): - self.mock_response_klass.type = 'ITERATOR' - container = Container(name='test_container', extra={}, - driver=self.driver) - objects = self.driver.list_container_objects(container=container) - - obj = [o for o in objects if o.name == '1.zip'][0] - self.assertEqual(obj.hash, '4397da7a7649e8085de9916c240e8166') - self.assertEqual(obj.size, 1234567) - self.assertEqual(obj.container.name, 'test_container') - - self.assertTrue(obj in objects) - self.assertEqual(len(objects), 5) - - def test_list_container_objects_with_prefix(self): - self.mock_response_klass.type = None - container = Container(name='test_container', extra={}, - driver=self.driver) - objects = self.driver.list_container_objects(container=container, - ex_prefix='test_prefix') - self.assertEqual(len(objects), 1) - - obj = [o for o in objects if o.name == '1.zip'][0] - self.assertEqual(obj.hash, '4397da7a7649e8085de9916c240e8166') - self.assertEqual(obj.size, 1234567) - self.assertEqual(obj.container.name, 'test_container') - self.assertTrue('owner' in obj.meta_data) - - def test_get_container_doesnt_exist(self): - self.mock_response_klass.type = 'get_container' - try: - self.driver.get_container(container_name='container1') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_container_success(self): - self.mock_response_klass.type = 'get_container' - container = self.driver.get_container(container_name='test1') - self.assertTrue(container.name, 'test1') - - def test_get_object_container_doesnt_exist(self): - # This method makes two requests which makes mocking the response a bit - # trickier - self.mock_response_klass.type = 'get_object' - try: - self.driver.get_object(container_name='test-inexistent', - object_name='test') - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_get_object_success(self): - # This method makes two requests which makes mocking the response a bit - # trickier - self.mock_response_klass.type = 'get_object' - obj = self.driver.get_object(container_name='test2', - object_name='test') - - self.assertEqual(obj.name, 'test') - self.assertEqual(obj.container.name, 'test2') - self.assertEqual(obj.size, 12345) - self.assertEqual(obj.hash, 'e31208wqsdoj329jd') - self.assertEqual(obj.extra['last_modified'], - 'Thu, 13 Sep 2012 07:13:22 GMT') - self.assertEqual(obj.extra['content_type'], 'application/zip') - self.assertEqual(obj.meta_data['rabbits'], 'monkeys') - - def test_create_container_invalid_name(self): - # invalid container name - self.mock_response_klass.type = 'INVALID_NAME' - try: - self.driver.create_container(container_name='new_container') - except InvalidContainerNameError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_container_already_exists(self): - # container with this name already exists - self.mock_response_klass.type = 'ALREADY_EXISTS' - try: - self.driver.create_container(container_name='new-container') - except InvalidContainerNameError: - pass - else: - self.fail('Exception was not thrown') - - def test_create_container_success(self): - # success - self.mock_response_klass.type = None - name = 'new_container' - container = self.driver.create_container(container_name=name) - self.assertEqual(container.name, name) - - def test_delete_container_doesnt_exist(self): - container = Container(name='new_container', extra=None, - driver=self.driver) - self.mock_response_klass.type = 'DOESNT_EXIST' - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_delete_container_not_empty(self): - container = Container(name='new_container', extra=None, - driver=self.driver) - self.mock_response_klass.type = 'NOT_EMPTY' - try: - self.driver.delete_container(container=container) - except ContainerIsNotEmptyError: - pass - else: - self.fail('Exception was not thrown') - - # success - self.mock_response_klass.type = None - self.assertTrue(self.driver.delete_container(container=container)) - - def test_delete_container_not_found(self): - self.mock_response_klass.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - try: - self.driver.delete_container(container=container) - except ContainerDoesNotExistError: - pass - else: - self.fail('Container does not exist but an exception was not' + - 'thrown') - - def test_delete_container_success(self): - self.mock_response_klass.type = None - container = Container(name='new_container', extra=None, - driver=self.driver) - self.assertTrue(self.driver.delete_container(container=container)) - - def test_download_object_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertTrue(result) - - def test_download_object_invalid_file_size(self): - self.mock_raw_response_klass.type = 'INVALID_SIZE' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - destination_path = os.path.abspath(__file__) + '.temp' - result = self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - self.assertFalse(result) - - def test_download_object_invalid_file_already_exists(self): - self.mock_raw_response_klass.type = 'INVALID_SIZE' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - destination_path = os.path.abspath(__file__) - try: - self.driver.download_object(obj=obj, - destination_path=destination_path, - overwrite_existing=False, - delete_on_failure=True) - except LibcloudError: - pass - else: - self.fail('Exception was not thrown') - - def test_download_object_as_stream_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, - container=container, meta_data=None, - driver=self.driver_type) - - stream = self.driver.download_object_as_stream(obj=obj, - chunk_size=None) - self.assertTrue(hasattr(stream, '__iter__')) - - def test_upload_object_invalid_ex_storage_class(self): - # Invalid hash is detected on the amazon side and BAD_REQUEST is - # returned - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - try: - self.driver.upload_object(file_path=file_path, container=container, - object_name=object_name, - verify_hash=True, - ex_storage_class='invalid-class') - except ValueError: - e = sys.exc_info()[1] - self.assertTrue(str(e).lower().find('invalid storage class') != -1) - else: - self.fail('Exception was not thrown') - - def test_upload_object_invalid_hash1(self): - # Invalid hash is detected on the amazon side and BAD_REQUEST is - # returned - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, 'hash343hhash89h932439jsaa89', 1000 - - self.mock_raw_response_klass.type = 'INVALID_HASH1' - - old_func = self.driver_type._upload_file - self.driver_type._upload_file = upload_file - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - try: - self.driver.upload_object(file_path=file_path, container=container, - object_name=object_name, - verify_hash=True) - except ObjectHashMismatchError: - pass - else: - self.fail( - 'Invalid hash was returned but an exception was not thrown') - finally: - self.driver_type._upload_file = old_func - - def test_upload_object_invalid_hash2(self): - # Invalid hash is detected when comparing hash provided in the response - # ETag header - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, '0cc175b9c0f1b6a831c399e269772661', 1000 - - self.mock_raw_response_klass.type = 'INVALID_HASH2' - - old_func = self.driver_type._upload_file - self.driver_type._upload_file = upload_file - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - try: - self.driver.upload_object(file_path=file_path, container=container, - object_name=object_name, - verify_hash=True) - except ObjectHashMismatchError: - pass - else: - self.fail( - 'Invalid hash was returned but an exception was not thrown') - finally: - self.driver_type._upload_file = old_func - - def test_upload_object_success(self): - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, '0cc175b9c0f1b6a831c399e269772661', 1000 - - old_func = self.driver_type._upload_file - self.driver_type._upload_file = upload_file - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'meta_data': {'some-value': 'foobar'}} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=True) - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, 1000) - self.assertTrue('some-value' in obj.meta_data) - self.driver_type._upload_file = old_func - - def test_upload_object_with_acl(self): - def upload_file(self, response, file_path, chunked=False, - calculate_hash=True): - return True, '0cc175b9c0f1b6a831c399e269772661', 1000 - - old_func = self.driver_type._upload_file - self.driver_type._upload_file = upload_file - file_path = os.path.abspath(__file__) - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_upload' - extra = {'acl': 'public-read'} - obj = self.driver.upload_object(file_path=file_path, - container=container, - object_name=object_name, - extra=extra, - verify_hash=True) - self.assertEqual(obj.name, 'foo_test_upload') - self.assertEqual(obj.size, 1000) - self.assertEqual(obj.extra['acl'], 'public-read') - self.driver_type._upload_file = old_func - - def test_upload_empty_object_via_stream(self): - if self.driver.supports_s3_multipart_upload: - self.mock_raw_response_klass.type = 'MULTIPART' - self.mock_response_klass.type = 'MULTIPART' - else: - self.mock_raw_response_klass.type = None - self.mock_response_klass.type = None - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_stream_data' - iterator = DummyIterator(data=['']) - extra = {'content_type': 'text/plain'} - obj = self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra) - - self.assertEqual(obj.name, object_name) - self.assertEqual(obj.size, 0) - - def test_upload_small_object_via_stream(self): - if self.driver.supports_s3_multipart_upload: - self.mock_raw_response_klass.type = 'MULTIPART' - self.mock_response_klass.type = 'MULTIPART' - else: - self.mock_raw_response_klass.type = None - self.mock_response_klass.type = None - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_stream_data' - iterator = DummyIterator(data=['2', '3', '5']) - extra = {'content_type': 'text/plain'} - obj = self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra) - - self.assertEqual(obj.name, object_name) - self.assertEqual(obj.size, 3) - - def test_upload_big_object_via_stream(self): - if self.driver.supports_s3_multipart_upload: - self.mock_raw_response_klass.type = 'MULTIPART' - self.mock_response_klass.type = 'MULTIPART' - else: - self.mock_raw_response_klass.type = None - self.mock_response_klass.type = None - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_stream_data' - iterator = DummyIterator( - data=['2' * CHUNK_SIZE, '3' * CHUNK_SIZE, '5']) - extra = {'content_type': 'text/plain'} - obj = self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra) - - self.assertEqual(obj.name, object_name) - self.assertEqual(obj.size, CHUNK_SIZE * 2 + 1) - - def test_upload_object_via_stream_abort(self): - if not self.driver.supports_s3_multipart_upload: - return - - self.mock_raw_response_klass.type = 'MULTIPART' - self.mock_response_klass.type = 'MULTIPART' - - def _faulty_iterator(): - for i in range(0, 5): - yield str(i) - raise RuntimeError('Error in fetching data') - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - object_name = 'foo_test_stream_data' - iterator = _faulty_iterator() - extra = {'content_type': 'text/plain'} - - try: - self.driver.upload_object_via_stream(container=container, - object_name=object_name, - iterator=iterator, - extra=extra) - except Exception: - pass - - return - - def test_s3_list_multipart_uploads(self): - if not self.driver.supports_s3_multipart_upload: - return - - self.mock_response_klass.type = 'LIST_MULTIPART' - S3StorageDriver.RESPONSES_PER_REQUEST = 2 - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - for upload in self.driver.ex_iterate_multipart_uploads(container): - self.assertNotEqual(upload.key, None) - self.assertNotEqual(upload.id, None) - self.assertNotEqual(upload.created_at, None) - self.assertNotEqual(upload.owner, None) - self.assertNotEqual(upload.initiator, None) - - def test_s3_abort_multipart_uploads(self): - if not self.driver.supports_s3_multipart_upload: - return - - self.mock_response_klass.type = 'LIST_MULTIPART' - S3StorageDriver.RESPONSES_PER_REQUEST = 2 - - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - - self.driver.ex_cleanup_all_multipart_uploads(container) - - def test_delete_object_not_found(self): - self.mock_response_klass.type = 'NOT_FOUND' - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, - meta_data=None, container=container, driver=self.driver) - try: - self.driver.delete_object(obj=obj) - except ObjectDoesNotExistError: - pass - else: - self.fail('Exception was not thrown') - - def test_delete_object_success(self): - container = Container(name='foo_bar_container', extra={}, - driver=self.driver) - obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, - meta_data=None, container=container, driver=self.driver) - - result = self.driver.delete_object(obj=obj) - self.assertTrue(result) - - -class S3USWestTests(S3Tests): - driver_type = S3USWestStorageDriver - - -class S3EUWestTests(S3Tests): - driver_type = S3EUWestStorageDriver - - -class S3APSETests(S3Tests): - driver_type = S3APSEStorageDriver - - -class S3APNETests(S3Tests): - driver_tyoe = S3APNEStorageDriver - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/test_connection.py b/awx/lib/site-packages/libcloud/test/test_connection.py deleted file mode 100644 index 5df79191a0..0000000000 --- a/awx/lib/site-packages/libcloud/test/test_connection.py +++ /dev/null @@ -1,207 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed to the Apache Software Foundation (ASF) under one or more§ -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import ssl - -from mock import Mock, call - -from libcloud.test import unittest -from libcloud.common.base import Connection -from libcloud.common.base import LoggingConnection - - -class ConnectionClassTestCase(unittest.TestCase): - def setUp(self): - self.originalConnect = Connection.connect - self.originalResponseCls = Connection.responseCls - - Connection.connect = Mock() - Connection.responseCls = Mock() - Connection.allow_insecure = True - - def tearDown(self): - Connection.connect = self.originalConnect - Connection.responseCls = Connection.responseCls - Connection.allow_insecure = True - - def test_dont_allow_insecure(self): - Connection.allow_insecure = True - Connection(secure=False) - - Connection.allow_insecure = False - - expected_msg = (r'Non https connections are not allowed \(use ' - 'secure=True\)') - self.assertRaisesRegexp(ValueError, expected_msg, Connection, - secure=False) - - def test_content_length(self): - con = Connection() - con.connection = Mock() - - # GET method - # No data, no content length should be present - con.request('/test', method='GET', data=None) - call_kwargs = con.connection.request.call_args[1] - self.assertTrue('Content-Length' not in call_kwargs['headers']) - - # '' as data, no content length should be present - con.request('/test', method='GET', data='') - call_kwargs = con.connection.request.call_args[1] - self.assertTrue('Content-Length' not in call_kwargs['headers']) - - # 'a' as data, content length should be present (data in GET is not - # correct, but anyways) - con.request('/test', method='GET', data='a') - call_kwargs = con.connection.request.call_args[1] - self.assertEqual(call_kwargs['headers']['Content-Length'], '1') - - # POST, PUT method - # No data, content length should be present - for method in ['POST', 'PUT', 'post', 'put']: - con.request('/test', method=method, data=None) - call_kwargs = con.connection.request.call_args[1] - self.assertEqual(call_kwargs['headers']['Content-Length'], '0') - - # '' as data, content length should be present - for method in ['POST', 'PUT', 'post', 'put']: - con.request('/test', method=method, data='') - call_kwargs = con.connection.request.call_args[1] - self.assertEqual(call_kwargs['headers']['Content-Length'], '0') - - # No data, raw request, do not touch Content-Length if present - for method in ['POST', 'PUT', 'post', 'put']: - con.request('/test', method=method, data=None, - headers={'Content-Length': '42'}, raw=True) - putheader_call_list = con.connection.putheader.call_args_list - self.assertIn(call('Content-Length', '42'), putheader_call_list) - - # '' as data, raw request, do not touch Content-Length if present - for method in ['POST', 'PUT', 'post', 'put']: - con.request('/test', method=method, data=None, - headers={'Content-Length': '42'}, raw=True) - putheader_call_list = con.connection.putheader.call_args_list - self.assertIn(call('Content-Length', '42'), putheader_call_list) - - # 'a' as data, content length should be present - for method in ['POST', 'PUT', 'post', 'put']: - con.request('/test', method=method, data='a') - call_kwargs = con.connection.request.call_args[1] - self.assertEqual(call_kwargs['headers']['Content-Length'], '1') - - def test_cache_busting(self): - params1 = {'foo1': 'bar1', 'foo2': 'bar2'} - params2 = [('foo1', 'bar1'), ('foo2', 'bar2')] - - con = Connection() - con.connection = Mock() - con.pre_connect_hook = Mock() - con.pre_connect_hook.return_value = {}, {} - con.cache_busting = False - - con.request(action='/path', params=params1) - args, kwargs = con.pre_connect_hook.call_args - self.assertFalse('cache-busting' in args[0]) - self.assertEqual(args[0], params1) - - con.request(action='/path', params=params2) - args, kwargs = con.pre_connect_hook.call_args - self.assertFalse('cache-busting' in args[0]) - self.assertEqual(args[0], params2) - - con.cache_busting = True - - con.request(action='/path', params=params1) - args, kwargs = con.pre_connect_hook.call_args - self.assertTrue('cache-busting' in args[0]) - - con.request(action='/path', params=params2) - args, kwargs = con.pre_connect_hook.call_args - self.assertTrue('cache-busting' in args[0][len(params2)]) - - def test_context_is_reset_after_request_has_finished(self): - context = {'foo': 'bar'} - - def responseCls(connection, response): - connection.called = True - self.assertEqual(connection.context, context) - - con = Connection() - con.called = False - con.connection = Mock() - con.responseCls = responseCls - - con.set_context(context) - self.assertEqual(con.context, context) - - con.request('/') - - # Context should have been reset - self.assertTrue(con.called) - self.assertEqual(con.context, {}) - - # Context should also be reset if a method inside request throws - con = Connection() - con.connection = Mock() - - con.set_context(context) - self.assertEqual(con.context, context) - - con.connection.request = Mock(side_effect=ssl.SSLError()) - - try: - con.request('/') - except ssl.SSLError: - pass - - self.assertEqual(con.context, {}) - - con.connection = Mock() - con.set_context(context) - self.assertEqual(con.context, context) - - con.responseCls = Mock(side_effect=ValueError()) - - try: - con.request('/') - except ValueError: - pass - - self.assertEqual(con.context, {}) - - def test_log_curl(self): - url = '/test/path' - body = None - headers = {} - - con = LoggingConnection() - con.protocol = 'http' - con.host = 'example.com' - con.port = 80 - - for method in ['GET', 'POST', 'PUT', 'DELETE']: - cmd = con._log_curl(method=method, url=url, body=body, - headers=headers) - self.assertEqual(cmd, 'curl -i -X %s --compress http://example.com:80/test/path' % - (method)) - - # Should use --head for head requests - cmd = con._log_curl(method='HEAD', url=url, body=body, headers=headers) - self.assertEqual(cmd, 'curl -i --head --compress http://example.com:80/test/path') - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/test_file_fixtures.py b/awx/lib/site-packages/libcloud/test/test_file_fixtures.py deleted file mode 100644 index 395f3155d9..0000000000 --- a/awx/lib/site-packages/libcloud/test/test_file_fixtures.py +++ /dev/null @@ -1,32 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import sys -import unittest - -from libcloud.test.file_fixtures import ComputeFileFixtures - - -class FileFixturesTests(unittest.TestCase): - - def test_success(self): - f = ComputeFileFixtures('meta') - self.assertEqual("Hello, World!", f.load('helloworld.txt')) - - def test_failure(self): - f = ComputeFileFixtures('meta') - self.assertRaises(IOError, f.load, 'nil') - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/test_httplib_ssl.py b/awx/lib/site-packages/libcloud/test/test_httplib_ssl.py deleted file mode 100644 index 5308eee624..0000000000 --- a/awx/lib/site-packages/libcloud/test/test_httplib_ssl.py +++ /dev/null @@ -1,236 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys -import os.path - -from mock import patch - -import libcloud.security - -from libcloud.utils.py3 import reload -from libcloud.httplib_ssl import LibcloudHTTPSConnection - -from libcloud.test import unittest - -ORIGINAL_CA_CERS_PATH = libcloud.security.CA_CERTS_PATH - - -class TestHttpLibSSLTests(unittest.TestCase): - - def setUp(self): - libcloud.security.VERIFY_SSL_CERT = False - libcloud.security.CA_CERTS_PATH = ORIGINAL_CA_CERS_PATH - self.httplib_object = LibcloudHTTPSConnection('foo.bar') - - def test_custom_ca_path_using_env_var_doesnt_exist(self): - os.environ['SSL_CERT_FILE'] = '/foo/doesnt/exist' - - try: - reload(libcloud.security) - except ValueError: - e = sys.exc_info()[1] - msg = 'Certificate file /foo/doesnt/exist doesn\'t exist' - self.assertEqual(str(e), msg) - else: - self.fail('Exception was not thrown') - - def test_custom_ca_path_using_env_var_is_directory(self): - file_path = os.path.dirname(os.path.abspath(__file__)) - os.environ['SSL_CERT_FILE'] = file_path - - expected_msg = 'Certificate file can\'t be a directory' - self.assertRaisesRegexp(ValueError, expected_msg, - reload, libcloud.security) - - def test_custom_ca_path_using_env_var_exist(self): - # When setting a path we don't actually check that a valid CA file is - # provided. - # This happens later in the code in httplib_ssl.connect method - file_path = os.path.abspath(__file__) - os.environ['SSL_CERT_FILE'] = file_path - - reload(libcloud.security) - - self.assertEqual(libcloud.security.CA_CERTS_PATH, [file_path]) - - def test_verify_hostname(self): - # commonName - cert1 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', - 'subject': ((('countryName', 'US'),), - (('stateOrProvinceName', 'Delaware'),), - (('localityName', 'Wilmington'),), - (('organizationName', 'Python Software Foundation'),), - (('organizationalUnitName', 'SSL'),), - (('commonName', 'somemachine.python.org'),))} - - # commonName - cert2 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', - 'subject': ((('countryName', 'US'),), - (('stateOrProvinceName', 'Delaware'),), - (('localityName', 'Wilmington'),), - (('organizationName', 'Python Software Foundation'),), - (('organizationalUnitName', 'SSL'),), - (('commonName', 'somemachine.python.org'),)), - 'subjectAltName': ((('DNS', 'foo.alt.name')), - (('DNS', 'foo.alt.name.1')))} - - # commonName - cert3 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', - 'subject': ((('countryName', 'US'),), - (('stateOrProvinceName', 'Delaware'),), - (('localityName', 'Wilmington'),), - (('organizationName', 'Python Software Foundation'),), - (('organizationalUnitName', 'SSL'),), - (('commonName', 'python.org'),))} - - # wildcard commonName - cert4 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', - 'subject': ((('countryName', 'US'),), - (('stateOrProvinceName', 'Delaware'),), - (('localityName', 'Wilmington'),), - (('organizationName', 'Python Software Foundation'),), - (('organizationalUnitName', 'SSL'),), - (('commonName', '*.api.joyentcloud.com'),))} - - self.assertFalse(self.httplib_object._verify_hostname( - hostname='invalid', cert=cert1)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='machine.python.org', cert=cert1)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='foomachine.python.org', cert=cert1)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='somesomemachine.python.org', cert=cert1)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='somemachine.python.orga', cert=cert1)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='somemachine.python.org.org', cert=cert1)) - self.assertTrue(self.httplib_object._verify_hostname( - hostname='somemachine.python.org', cert=cert1)) - - self.assertFalse(self.httplib_object._verify_hostname( - hostname='invalid', cert=cert2)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='afoo.alt.name.1', cert=cert2)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='a.foo.alt.name.1', cert=cert2)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='foo.alt.name.1.2', cert=cert2)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='afoo.alt.name.1.2', cert=cert2)) - self.assertTrue(self.httplib_object._verify_hostname( - hostname='foo.alt.name.1', cert=cert2)) - - self.assertTrue(self.httplib_object._verify_hostname( - hostname='python.org', cert=cert3)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='opython.org', cert=cert3)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='ython.org', cert=cert3)) - - self.assertTrue(self.httplib_object._verify_hostname( - hostname='us-east-1.api.joyentcloud.com', cert=cert4)) - self.assertTrue(self.httplib_object._verify_hostname( - hostname='useast-1.api.joyentcloud.com', cert=cert4)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='t1.useast-1.api.joyentcloud.com', cert=cert4)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='ponies.useast-1.api.joyentcloud.com', cert=cert4)) - self.assertFalse(self.httplib_object._verify_hostname( - hostname='api.useast-1.api.joyentcloud.com', cert=cert4)) - - def test_get_subject_alt_names(self): - cert1 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', - 'subject': ((('countryName', 'US'),), - (('stateOrProvinceName', 'Delaware'),), - (('localityName', 'Wilmington'),), - (('organizationName', 'Python Software Foundation'),), - (('organizationalUnitName', 'SSL'),), - (('commonName', 'somemachine.python.org'),))} - - cert2 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', - 'subject': ((('countryName', 'US'),), - (('stateOrProvinceName', 'Delaware'),), - (('localityName', 'Wilmington'),), - (('organizationName', 'Python Software Foundation'),), - (('organizationalUnitName', 'SSL'),), - (('commonName', 'somemachine.python.org'),)), - 'subjectAltName': ((('DNS', 'foo.alt.name')), - (('DNS', 'foo.alt.name.1')))} - - self.assertEqual(self.httplib_object._get_subject_alt_names(cert=cert1), - []) - - alt_names = self.httplib_object._get_subject_alt_names(cert=cert2) - self.assertEqual(len(alt_names), 2) - self.assertTrue('foo.alt.name' in alt_names) - self.assertTrue('foo.alt.name.1' in alt_names) - - def test_get_common_name(self): - cert = {'notAfter': 'Feb 16 16:54:50 2013 GMT', - 'subject': ((('countryName', 'US'),), - (('stateOrProvinceName', 'Delaware'),), - (('localityName', 'Wilmington'),), - (('organizationName', 'Python Software Foundation'),), - (('organizationalUnitName', 'SSL'),), - (('commonName', 'somemachine.python.org'),))} - - self.assertEqual(self.httplib_object._get_common_name(cert)[0], - 'somemachine.python.org') - self.assertEqual(self.httplib_object._get_common_name({}), - None) - - @patch('warnings.warn') - def test_setup_verify(self, _): - libcloud.security.CA_CERTS_PATH = [] - - # Should throw a runtime error - libcloud.security.VERIFY_SSL_CERT = True - - expected_msg = libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG - self.assertRaisesRegexp(RuntimeError, expected_msg, - self.httplib_object._setup_verify) - - libcloud.security.VERIFY_SSL_CERT = False - self.httplib_object._setup_verify() - - @patch('warnings.warn') - def test_setup_ca_cert(self, _): - # verify = False, _setup_ca_cert should be a no-op - self.httplib_object.verify = False - self.httplib_object._setup_ca_cert() - - self.assertEqual(self.httplib_object.ca_cert, None) - - # verify = True, a valid path is provided, self.ca_cert should be set to - # a valid path - self.httplib_object.verify = True - - libcloud.security.CA_CERTS_PATH = [os.path.abspath(__file__)] - self.httplib_object._setup_ca_cert() - - self.assertTrue(self.httplib_object.ca_cert is not None) - - # verify = True, no CA certs are available, exception should be thrown - libcloud.security.CA_CERTS_PATH = [] - - expected_msg = libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG - self.assertRaisesRegexp(RuntimeError, expected_msg, - self.httplib_object._setup_ca_cert) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/test_pricing.py b/awx/lib/site-packages/libcloud/test/test_pricing.py deleted file mode 100644 index 5b6d132f4f..0000000000 --- a/awx/lib/site-packages/libcloud/test/test_pricing.py +++ /dev/null @@ -1,106 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os.path -import sys -import unittest - -import libcloud.pricing - -PRICING_FILE_PATH = os.path.join(os.path.dirname(__file__), 'pricing_test.json') - - -class PricingTestCase(unittest.TestCase): - - def test_get_pricing_success(self): - self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) - - pricing = libcloud.pricing.get_pricing(driver_type='compute', - driver_name='foo', - pricing_file_path=PRICING_FILE_PATH) - self.assertEqual(pricing['1'], 1.0) - self.assertEqual(pricing['2'], 2.0) - - self.assertEqual(libcloud.pricing.PRICING_DATA['compute']['foo']['1'], 1.0) - self.assertEqual(libcloud.pricing.PRICING_DATA['compute']['foo']['2'], 2.0) - - def test_get_pricing_invalid_file_path(self): - try: - libcloud.pricing.get_pricing(driver_type='compute', driver_name='bar', - pricing_file_path='inexistent.json') - except IOError: - pass - else: - self.fail('Invalid pricing file path provided, but an exception was not' - ' thrown') - - def test_get_pricing_invalid_driver_type(self): - try: - libcloud.pricing.get_pricing(driver_type='invalid_type', driver_name='bar', - pricing_file_path='inexistent.json') - except AttributeError: - pass - else: - self.fail('Invalid driver_type provided, but an exception was not' - ' thrown') - - def test_get_pricing_not_in_cache(self): - try: - libcloud.pricing.get_pricing(driver_type='compute', driver_name='inexistent', - pricing_file_path=PRICING_FILE_PATH) - except KeyError: - pass - else: - self.fail('Invalid driver provided, but an exception was not' - ' thrown') - - def test_get_size_price(self): - libcloud.pricing.PRICING_DATA['compute']['foo'] = {2: 2, '3': 3} - price1 = libcloud.pricing.get_size_price(driver_type='compute', - driver_name='foo', - size_id=2) - price2 = libcloud.pricing.get_size_price(driver_type='compute', - driver_name='foo', - size_id='3') - self.assertEqual(price1, 2) - self.assertEqual(price2, 3) - - def test_invalid_pricing_cache(self): - libcloud.pricing.PRICING_DATA['compute']['foo'] = {2: 2} - self.assertTrue('foo' in libcloud.pricing.PRICING_DATA['compute']) - - libcloud.pricing.invalidate_pricing_cache() - self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) - - def test_invalid_module_pricing_cache(self): - libcloud.pricing.PRICING_DATA['compute']['foo'] = {1: 1} - - self.assertTrue('foo' in libcloud.pricing.PRICING_DATA['compute']) - - libcloud.pricing.invalidate_module_pricing_cache(driver_type='compute', - driver_name='foo') - self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) - libcloud.pricing.invalidate_module_pricing_cache(driver_type='compute', - driver_name='foo1') - - def test_set_pricing(self): - self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) - - libcloud.pricing.set_pricing(driver_type='compute', driver_name='foo', - pricing={'foo': 1}) - self.assertTrue('foo' in libcloud.pricing.PRICING_DATA['compute']) - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/test_response_classes.py b/awx/lib/site-packages/libcloud/test/test_response_classes.py deleted file mode 100644 index ceeab4cfc1..0000000000 --- a/awx/lib/site-packages/libcloud/test/test_response_classes.py +++ /dev/null @@ -1,151 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest -import zlib -import gzip - -from mock import Mock - -from libcloud.utils.py3 import httplib, b, StringIO, PY3 -from libcloud.common.base import Response, XmlResponse, JsonResponse -from libcloud.common.types import MalformedResponseError - - -class ResponseClassesTests(unittest.TestCase): - def setUp(self): - self._mock_response = Mock() - self._mock_response.getheaders.return_value = [] - self._mock_response.status = httplib.OK - self._mock_response._original_data = None - self._mock_connection = Mock() - - def test_XmlResponse_class(self): - self._mock_response.read.return_value = 'bar' - response = XmlResponse(response=self._mock_response, - connection=self._mock_connection) - - parsed = response.parse_body() - self.assertEqual(parsed.tag, 'foo') - self.assertEqual(parsed.text, 'bar') - - def test_XmlResponse_class_malformed_response(self): - self._mock_response.read.return_value = '' - - try: - XmlResponse(response=self._mock_response, - connection=self._mock_connection) - except MalformedResponseError: - pass - else: - self.fail('Exception was not thrown') - - def test_XmlResponse_class_zero_length_body_strip(self): - self._mock_response.read.return_value = ' ' - - response = XmlResponse(response=self._mock_response, - connection=self._mock_connection) - - parsed = response.parse_body() - self.assertEqual(parsed, '') - - def test_JsonResponse_class_success(self): - self._mock_response.read.return_value = '{"foo": "bar"}' - response = JsonResponse(response=self._mock_response, - connection=self._mock_connection) - - parsed = response.parse_body() - self.assertEqual(parsed, {'foo': 'bar'}) - - def test_JsonResponse_class_malformed_response(self): - self._mock_response.read.return_value = '{"foo": "bar' - - try: - JsonResponse(response=self._mock_response, - connection=self._mock_connection) - except MalformedResponseError: - pass - else: - self.fail('Exception was not thrown') - - def test_JsonResponse_class_zero_length_body_strip(self): - self._mock_response.read.return_value = ' ' - - response = JsonResponse(response=self._mock_response, - connection=self._mock_connection) - - parsed = response.parse_body() - self.assertEqual(parsed, '') - - def test_deflate_encoding(self): - original_data = 'foo bar ponies, wooo zlib' - compressed_data = zlib.compress(b(original_data)) - - self._mock_response.read.return_value = compressed_data - self._mock_response.getheaders.return_value = \ - {'Content-Encoding': 'deflate'} - - response = Response(response=self._mock_response, - connection=self._mock_connection) - - body = response.parse_body() - self.assertEqual(body, original_data) - - self._mock_response.getheaders.return_value = \ - {'Content-Encoding': 'zlib'} - - response = Response(response=self._mock_response, - connection=self._mock_connection) - - body = response.parse_body() - self.assertEqual(body, original_data) - - def test_gzip_encoding(self): - original_data = 'foo bar ponies, wooo gzip' - - if PY3: - from io import BytesIO - string_io = BytesIO() - else: - string_io = StringIO() - - stream = gzip.GzipFile(fileobj=string_io, mode='w') - stream.write(b(original_data)) - stream.close() - compressed_data = string_io.getvalue() - - self._mock_response.read.return_value = compressed_data - self._mock_response.getheaders.return_value = \ - {'Content-Encoding': 'gzip'} - - response = Response(response=self._mock_response, - connection=self._mock_connection) - - body = response.parse_body() - self.assertEqual(body, original_data) - - self._mock_response.getheaders.return_value = \ - {'Content-Encoding': 'x-gzip'} - - response = Response(response=self._mock_response, - connection=self._mock_connection) - - body = response.parse_body() - self.assertEqual(body, original_data) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/test_types.py b/awx/lib/site-packages/libcloud/test/test_types.py deleted file mode 100644 index 453ffcc299..0000000000 --- a/awx/lib/site-packages/libcloud/test/test_types.py +++ /dev/null @@ -1,112 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import unittest - -from libcloud.common.types import LazyList - - -class TestLazyList(unittest.TestCase): - def setUp(self): - super(TestLazyList, self).setUp - self._get_more_counter = 0 - - def tearDown(self): - super(TestLazyList, self).tearDown - - def test_init(self): - data = [1, 2, 3, 4, 5] - ll = LazyList(get_more=self._get_more_exhausted) - ll_list = list(ll) - self.assertEqual(ll_list, data) - - def test_iterator(self): - data = [1, 2, 3, 4, 5] - ll = LazyList(get_more=self._get_more_exhausted) - for i, d in enumerate(ll): - self.assertEqual(d, data[i]) - - def test_empty_list(self): - ll = LazyList(get_more=self._get_more_empty) - - self.assertEqual(list(ll), []) - self.assertEqual(len(ll), 0) - self.assertTrue(10 not in ll) - - def test_iterator_not_exhausted(self): - data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - ll = LazyList(get_more=self._get_more_not_exhausted) - number_of_iterations = 0 - for i, d in enumerate(ll): - self.assertEqual(d, data[i]) - number_of_iterations += 1 - self.assertEqual(number_of_iterations, 10) - - def test_len(self): - ll = LazyList(get_more=self._get_more_not_exhausted) - ll = LazyList(get_more=self._get_more_not_exhausted) - - self.assertEqual(len(ll), 10) - - def test_contains(self): - ll = LazyList(get_more=self._get_more_not_exhausted) - - self.assertTrue(40 not in ll) - self.assertTrue(1 in ll) - self.assertTrue(5 in ll) - self.assertTrue(10 in ll) - - def test_indexing(self): - ll = LazyList(get_more=self._get_more_not_exhausted) - - self.assertEqual(ll[0], 1) - self.assertEqual(ll[9], 10) - self.assertEqual(ll[-1], 10) - - try: - ll[11] - except IndexError: - pass - else: - self.fail('Exception was not thrown') - - def test_repr(self): - ll1 = LazyList(get_more=self._get_more_empty) - ll2 = LazyList(get_more=self._get_more_exhausted) - ll3 = LazyList(get_more=self._get_more_not_exhausted) - - self.assertEqual(repr(ll1), '[]') - self.assertEqual(repr(ll2), '[1, 2, 3, 4, 5]') - self.assertEqual(repr(ll3), '[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]') - - def _get_more_empty(self, last_key, value_dict): - return [], None, True - - def _get_more_exhausted(self, last_key, value_dict): - data = [1, 2, 3, 4, 5] - return data, 5, True - - def _get_more_not_exhausted(self, last_key, value_dict): - self._get_more_counter += 1 - if not last_key: - data, last_key, exhausted = [1, 2, 3, 4, 5], 5, False - else: - data, last_key, exhausted = [6, 7, 8, 9, 10], 10, True - - return data, last_key, exhausted - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/test/test_utils.py b/awx/lib/site-packages/libcloud/test/test_utils.py deleted file mode 100644 index 58b350662e..0000000000 --- a/awx/lib/site-packages/libcloud/test/test_utils.py +++ /dev/null @@ -1,360 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed to the Apache Software Foundation (ASF) under one or more§ -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys -import socket -import codecs -import unittest -import warnings -import os.path - -from itertools import chain - -# In Python > 2.7 DeprecationWarnings are disabled by default -warnings.simplefilter('default') - -import libcloud.utils.files - -from libcloud.utils.misc import get_driver, set_driver - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import StringIO -from libcloud.utils.py3 import b -from libcloud.utils.py3 import bchr -from libcloud.utils.py3 import hexadigits -from libcloud.utils.py3 import urlquote -from libcloud.compute.types import Provider -from libcloud.compute.providers import DRIVERS -from libcloud.utils.misc import get_secure_random_string -from libcloud.utils.networking import is_public_subnet -from libcloud.utils.networking import is_private_subnet -from libcloud.utils.networking import is_valid_ip_address -from libcloud.storage.drivers.dummy import DummyIterator - - -WARNINGS_BUFFER = [] - -if PY3: - from io import FileIO as file - - -def show_warning(msg, cat, fname, lno, line=None): - WARNINGS_BUFFER.append((msg, cat, fname, lno)) - -original_func = warnings.showwarning - - -class TestUtils(unittest.TestCase): - def setUp(self): - global WARNINGS_BUFFER - WARNINGS_BUFFER = [] - - def tearDown(self): - global WARNINGS_BUFFER - WARNINGS_BUFFER = [] - warnings.showwarning = original_func - - def test_guess_file_mime_type(self): - file_path = os.path.abspath(__file__) - mimetype, encoding = libcloud.utils.files.guess_file_mime_type( - file_path=file_path) - - self.assertTrue(mimetype.find('python') != -1) - - def test_get_driver(self): - driver = get_driver(drivers=DRIVERS, provider=Provider.DUMMY) - self.assertTrue(driver is not None) - - try: - driver = get_driver(drivers=DRIVERS, provider='fooba') - except AttributeError: - pass - else: - self.fail('Invalid provider, but an exception was not thrown') - - def test_set_driver(self): - # Set an existing driver - try: - driver = set_driver(DRIVERS, Provider.DUMMY, - 'libcloud.storage.drivers.dummy', - 'DummyStorageDriver') - except AttributeError: - pass - - # Register a new driver - driver = set_driver(DRIVERS, 'testingset', - 'libcloud.storage.drivers.dummy', - 'DummyStorageDriver') - - self.assertTrue(driver is not None) - - # Register it again - try: - set_driver(DRIVERS, 'testingset', - 'libcloud.storage.drivers.dummy', - 'DummyStorageDriver') - except AttributeError: - pass - - # Register an invalid module - try: - set_driver(DRIVERS, 'testingnew', - 'libcloud.storage.drivers.dummy1', - 'DummyStorageDriver') - except ImportError: - pass - - # Register an invalid class - try: - set_driver(DRIVERS, 'testingnew', - 'libcloud.storage.drivers.dummy', - 'DummyStorageDriver1') - except AttributeError: - pass - - def test_deprecated_warning(self): - warnings.showwarning = show_warning - - libcloud.utils.SHOW_DEPRECATION_WARNING = False - self.assertEqual(len(WARNINGS_BUFFER), 0) - libcloud.utils.deprecated_warning('test_module') - self.assertEqual(len(WARNINGS_BUFFER), 0) - - libcloud.utils.SHOW_DEPRECATION_WARNING = True - self.assertEqual(len(WARNINGS_BUFFER), 0) - libcloud.utils.deprecated_warning('test_module') - self.assertEqual(len(WARNINGS_BUFFER), 1) - - def test_in_development_warning(self): - warnings.showwarning = show_warning - - libcloud.utils.SHOW_IN_DEVELOPMENT_WARNING = False - self.assertEqual(len(WARNINGS_BUFFER), 0) - libcloud.utils.in_development_warning('test_module') - self.assertEqual(len(WARNINGS_BUFFER), 0) - - libcloud.utils.SHOW_IN_DEVELOPMENT_WARNING = True - self.assertEqual(len(WARNINGS_BUFFER), 0) - libcloud.utils.in_development_warning('test_module') - self.assertEqual(len(WARNINGS_BUFFER), 1) - - def test_read_in_chunks_iterator_no_data(self): - iterator = DummyIterator() - generator1 = libcloud.utils.files.read_in_chunks(iterator=iterator, - yield_empty=False) - generator2 = libcloud.utils.files.read_in_chunks(iterator=iterator, - yield_empty=True) - - # yield_empty=False - count = 0 - for data in generator1: - count += 1 - self.assertEqual(data, b('')) - - self.assertEqual(count, 0) - - # yield_empty=True - count = 0 - for data in generator2: - count += 1 - self.assertEqual(data, b('')) - - self.assertEqual(count, 1) - - def test_read_in_chunks_iterator(self): - def iterator(): - for x in range(0, 1000): - yield 'aa' - - for result in libcloud.utils.files.read_in_chunks(iterator(), - chunk_size=10, - fill_size=False): - self.assertEqual(result, b('aa')) - - for result in libcloud.utils.files.read_in_chunks(iterator(), chunk_size=10, - fill_size=True): - self.assertEqual(result, b('aaaaaaaaaa')) - - def test_read_in_chunks_filelike(self): - class FakeFile(file): - def __init__(self): - self.remaining = 500 - - def read(self, size): - self.remaining -= 1 - if self.remaining == 0: - return '' - return 'b' * (size + 1) - - for index, result in enumerate(libcloud.utils.files.read_in_chunks( - FakeFile(), chunk_size=10, - fill_size=False)): - self.assertEqual(result, b('b' * 11)) - - self.assertEqual(index, 498) - - for index, result in enumerate(libcloud.utils.files.read_in_chunks( - FakeFile(), chunk_size=10, - fill_size=True)): - if index != 548: - self.assertEqual(result, b('b' * 10)) - else: - self.assertEqual(result, b('b' * 9)) - - self.assertEqual(index, 548) - - def test_exhaust_iterator(self): - def iterator_func(): - for x in range(0, 1000): - yield 'aa' - - data = b('aa' * 1000) - iterator = libcloud.utils.files.read_in_chunks(iterator=iterator_func()) - result = libcloud.utils.files.exhaust_iterator(iterator=iterator) - self.assertEqual(result, data) - - result = libcloud.utils.files.exhaust_iterator(iterator=iterator_func()) - self.assertEqual(result, data) - - data = '12345678990' - iterator = StringIO(data) - result = libcloud.utils.files.exhaust_iterator(iterator=iterator) - self.assertEqual(result, b(data)) - - def test_exhaust_iterator_empty_iterator(self): - data = '' - iterator = StringIO(data) - result = libcloud.utils.files.exhaust_iterator(iterator=iterator) - self.assertEqual(result, b(data)) - - def test_unicode_urlquote(self): - # Regression tests for LIBCLOUD-429 - if PY3: - # Note: this is a unicode literal - val = '\xe9' - else: - val = codecs.unicode_escape_decode('\xe9')[0] - - uri = urlquote(val) - self.assertEqual(b(uri), b('%C3%A9')) - - # Unicode without unicode characters - uri = urlquote('~abc') - self.assertEqual(b(uri), b('%7Eabc')) - - # Already-encoded bytestring without unicode characters - uri = urlquote(b('~abc')) - self.assertEqual(b(uri), b('%7Eabc')) - - def test_get_secure_random_string(self): - for i in range(1, 500): - value = get_secure_random_string(size=i) - self.assertEqual(len(value), i) - - def test_hexadigits(self): - self.assertEqual(hexadigits(b('')), []) - self.assertEqual(hexadigits(b('a')), ['61']) - self.assertEqual(hexadigits(b('AZaz09-')), - ['41', '5a', '61', '7a', '30', '39', '2d']) - - def test_bchr(self): - if PY3: - self.assertEqual(bchr(0), b'\x00') - self.assertEqual(bchr(97), b'a') - else: - self.assertEqual(bchr(0), '\x00') - self.assertEqual(bchr(97), 'a') - - -class NetworkingUtilsTestCase(unittest.TestCase): - def test_is_public_and_is_private_subnet(self): - public_ips = [ - '213.151.0.8', - '86.87.86.1', - '8.8.8.8', - '8.8.4.4' - ] - - private_ips = [ - '192.168.1.100', - '10.0.0.1', - '172.16.0.0' - ] - - for address in public_ips: - is_public = is_public_subnet(ip=address) - is_private = is_private_subnet(ip=address) - - self.assertTrue(is_public) - self.assertFalse(is_private) - - for address in private_ips: - is_public = is_public_subnet(ip=address) - is_private = is_private_subnet(ip=address) - - self.assertFalse(is_public) - self.assertTrue(is_private) - - def test_is_valid_ip_address(self): - valid_ipv4_addresses = [ - '192.168.1.100', - '10.0.0.1', - '213.151.0.8', - '77.77.77.77' - ] - - invalid_ipv4_addresses = [ - '10.1', - '256.256.256.256', - '0.567.567.567', - '192.168.0.257' - ] - - valid_ipv6_addresses = [ - 'fe80::200:5aee:feaa:20a2', - '2607:f0d0:1002:51::4', - '2607:f0d0:1002:0051:0000:0000:0000:0004', - '::1' - ] - - invalid_ipv6_addresses = [ - '2607:f0d', - '2607:f0d0:0004', - ] - - for address in valid_ipv4_addresses: - status = is_valid_ip_address(address=address, - family=socket.AF_INET) - self.assertTrue(status) - - for address in valid_ipv6_addresses: - status = is_valid_ip_address(address=address, - family=socket.AF_INET6) - self.assertTrue(status) - - for address in chain(invalid_ipv4_addresses, invalid_ipv6_addresses): - status = is_valid_ip_address(address=address, - family=socket.AF_INET) - self.assertFalse(status) - - for address in chain(invalid_ipv4_addresses, invalid_ipv6_addresses): - status = is_valid_ip_address(address=address, - family=socket.AF_INET6) - self.assertFalse(status) - - -if __name__ == '__main__': - sys.exit(unittest.main()) diff --git a/awx/lib/site-packages/libcloud/utils/__init__.py b/awx/lib/site-packages/libcloud/utils/__init__.py deleted file mode 100644 index cfceb49b63..0000000000 --- a/awx/lib/site-packages/libcloud/utils/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import warnings - -__all__ = [ - 'SHOW_DEPRECATION_WARNING', - 'SHOW_IN_DEVELOPMENT_WARNING', - 'OLD_API_REMOVE_VERSION', - 'deprecated_warning', - 'in_development_warning' -] - - -SHOW_DEPRECATION_WARNING = True -SHOW_IN_DEVELOPMENT_WARNING = True -OLD_API_REMOVE_VERSION = '0.7.0' - - -def deprecated_warning(module): - if SHOW_DEPRECATION_WARNING: - warnings.warn('This path has been deprecated and the module' - ' is now available at "libcloud.compute.%s".' - ' This path will be fully removed in libcloud %s.' % - (module, OLD_API_REMOVE_VERSION), - category=DeprecationWarning) - - -def in_development_warning(module): - if SHOW_IN_DEVELOPMENT_WARNING: - warnings.warn('The module %s is in development and your are advised ' - 'against using it in production.' % (module), - category=FutureWarning) diff --git a/awx/lib/site-packages/libcloud/utils/compression.py b/awx/lib/site-packages/libcloud/utils/compression.py deleted file mode 100644 index 9840538c78..0000000000 --- a/awx/lib/site-packages/libcloud/utils/compression.py +++ /dev/null @@ -1,42 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import zlib -import gzip - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import StringIO - - -__all__ = [ - 'decompress_data' -] - - -def decompress_data(compression_type, data): - if compression_type == 'zlib': - return zlib.decompress(data) - elif compression_type == 'gzip': - # TODO: Should export BytesIO as StringIO in libcloud.utils.py3 - if PY3: - from io import BytesIO - cls = BytesIO - else: - cls = StringIO - - return gzip.GzipFile(fileobj=cls(data)).read() - else: - raise Exception('Invalid or onsupported compression type: %s' % - (compression_type)) diff --git a/awx/lib/site-packages/libcloud/utils/connection.py b/awx/lib/site-packages/libcloud/utils/connection.py deleted file mode 100644 index db381a31fd..0000000000 --- a/awx/lib/site-packages/libcloud/utils/connection.py +++ /dev/null @@ -1,42 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from libcloud.utils.py3 import urlparse, parse_qs -from libcloud.common.base import Connection - -__all__ = [ - 'get_response_object' -] - - -def get_response_object(url): - """ - Utility function which uses libcloud's connection class to issue an HTTP - request. - - :param url: URL to send the request to. - :type url: ``str`` - - :return: Response object. - :rtype: :class:`Response`. - """ - parsed_url = urlparse.urlparse(url) - parsed_qs = parse_qs(parsed_url.query) - secure = parsed_url.scheme == 'https' - - con = Connection(secure=secure, host=parsed_url.netloc) - response = con.request(method='GET', action=parsed_url.path, - params=parsed_qs) - return response diff --git a/awx/lib/site-packages/libcloud/utils/dist.py b/awx/lib/site-packages/libcloud/utils/dist.py deleted file mode 100644 index 4477e2ae2d..0000000000 --- a/awx/lib/site-packages/libcloud/utils/dist.py +++ /dev/null @@ -1,136 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Taken From Twisted Python which licensed under MIT license -# https://github.com/powdahound/twisted/blob/master/twisted/python/dist.py -# https://github.com/powdahound/twisted/blob/master/LICENSE - -import os -import fnmatch - -# Names that are excluded from globbing results: -EXCLUDE_NAMES = ['{arch}', 'CVS', '.cvsignore', '_darcs', - 'RCS', 'SCCS', '.svn'] -EXCLUDE_PATTERNS = ['*.py[cdo]', '*.s[ol]', '.#*', '*~', '*.py'] - - -def _filter_names(names): - """ - Given a list of file names, return those names that should be copied. - """ - names = [n for n in names - if n not in EXCLUDE_NAMES] - # This is needed when building a distro from a working - # copy (likely a checkout) rather than a pristine export: - for pattern in EXCLUDE_PATTERNS: - names = [n for n in names - if (not fnmatch.fnmatch(n, pattern)) - and (not n.endswith('.py'))] - return names - - -def relative_to(base, relativee): - """ - Gets 'relativee' relative to 'basepath'. - - i.e., - - >>> relative_to('/home/', '/home/radix/') - 'radix' - >>> relative_to('.', '/home/radix/Projects/Twisted') - 'Projects/Twisted' - - The 'relativee' must be a child of 'basepath'. - """ - basepath = os.path.abspath(base) - relativee = os.path.abspath(relativee) - if relativee.startswith(basepath): - relative = relativee[len(basepath):] - if relative.startswith(os.sep): - relative = relative[1:] - return os.path.join(base, relative) - raise ValueError("%s is not a subpath of %s" % (relativee, basepath)) - - -def get_packages(dname, pkgname=None, results=None, ignore=None, parent=None): - """ - Get all packages which are under dname. This is necessary for - Python 2.2's distutils. Pretty similar arguments to getDataFiles, - including 'parent'. - """ - parent = parent or "" - prefix = [] - if parent: - prefix = [parent] - bname = os.path.basename(dname) - ignore = ignore or [] - if bname in ignore: - return [] - if results is None: - results = [] - if pkgname is None: - pkgname = [] - subfiles = os.listdir(dname) - abssubfiles = [os.path.join(dname, x) for x in subfiles] - - if '__init__.py' in subfiles: - results.append(prefix + pkgname + [bname]) - for subdir in filter(os.path.isdir, abssubfiles): - get_packages(subdir, pkgname=pkgname + [bname], - results=results, ignore=ignore, - parent=parent) - res = ['.'.join(result) for result in results] - return res - - -def get_data_files(dname, ignore=None, parent=None): - """ - Get all the data files that should be included in this distutils Project. - - 'dname' should be the path to the package that you're distributing. - - 'ignore' is a list of sub-packages to ignore. This facilitates - disparate package hierarchies. That's a fancy way of saying that - the 'twisted' package doesn't want to include the 'twisted.conch' - package, so it will pass ['conch'] as the value. - - 'parent' is necessary if you're distributing a subpackage like - twisted.conch. 'dname' should point to 'twisted/conch' and 'parent' - should point to 'twisted'. This ensures that your data_files are - generated correctly, only using relative paths for the first element - of the tuple ('twisted/conch/*'). - The default 'parent' is the current working directory. - """ - parent = parent or "." - ignore = ignore or [] - result = [] - for directory, subdirectories, filenames in os.walk(dname): - resultfiles = [] - for exname in EXCLUDE_NAMES: - if exname in subdirectories: - subdirectories.remove(exname) - for ig in ignore: - if ig in subdirectories: - subdirectories.remove(ig) - for filename in _filter_names(filenames): - resultfiles.append(filename) - if resultfiles: - for filename in resultfiles: - file_path = os.path.join(directory, filename) - if parent: - file_path = file_path.replace(parent + os.sep, '') - result.append(file_path) - - return result diff --git a/awx/lib/site-packages/libcloud/utils/files.py b/awx/lib/site-packages/libcloud/utils/files.py deleted file mode 100644 index a71e1c488f..0000000000 --- a/awx/lib/site-packages/libcloud/utils/files.py +++ /dev/null @@ -1,129 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import mimetypes - -from libcloud.utils.py3 import PY3 -from libcloud.utils.py3 import httplib -from libcloud.utils.py3 import next -from libcloud.utils.py3 import b - -if PY3: - from io import FileIO as file - -CHUNK_SIZE = 8096 - -__all__ = [ - 'read_in_chunks', - 'exhaust_iterator', - 'guess_file_mime_type' -] - - -def read_in_chunks(iterator, chunk_size=None, fill_size=False, - yield_empty=False): - """ - Return a generator which yields data in chunks. - - :param terator: An object which implements an iterator interface - or a File like object with read method. - :type iterator: :class:`object` which implements iterator interface. - - :param chunk_size: Optional chunk size (defaults to CHUNK_SIZE) - :type chunk_size: ``int`` - - :param fill_size: If True, make sure chunks are exactly chunk_size in - length (except for last chunk). - :type fill_size: ``bool`` - - :param yield_empty: If true and iterator returned no data, yield empty - bytes object before raising StopIteration. - :type yield_empty: ``bool`` - - TODO: At some point in the future we could use byte arrays here if version - >= Python 3. This should speed things up a bit and reduce memory usage. - """ - chunk_size = chunk_size or CHUNK_SIZE - - if isinstance(iterator, (file, httplib.HTTPResponse)): - get_data = iterator.read - args = (chunk_size, ) - else: - get_data = next - args = (iterator, ) - - data = b('') - empty = False - - while not empty or len(data) > 0: - if not empty: - try: - chunk = b(get_data(*args)) - if len(chunk) > 0: - data += chunk - else: - empty = True - except StopIteration: - empty = True - - if len(data) == 0: - if empty and yield_empty: - yield b('') - - raise StopIteration - - if fill_size: - if empty or len(data) >= chunk_size: - yield data[:chunk_size] - data = data[chunk_size:] - else: - yield data - data = b('') - - -def exhaust_iterator(iterator): - """ - Exhaust an iterator and return all data returned by it. - - :type iterator: :class:`object` which implements iterator interface. - :param response: An object which implements an iterator interface - or a File like object with read method. - - :rtype ``str`` - :return Data returned by the iterator. - """ - data = b('') - - try: - chunk = b(next(iterator)) - except StopIteration: - chunk = b('') - - while len(chunk) > 0: - data += chunk - - try: - chunk = b(next(iterator)) - except StopIteration: - chunk = b('') - - return data - - -def guess_file_mime_type(file_path): - filename = os.path.basename(file_path) - (mimetype, encoding) = mimetypes.guess_type(filename) - return mimetype, encoding diff --git a/awx/lib/site-packages/libcloud/utils/iso8601.py b/awx/lib/site-packages/libcloud/utils/iso8601.py deleted file mode 100644 index e02d49684d..0000000000 --- a/awx/lib/site-packages/libcloud/utils/iso8601.py +++ /dev/null @@ -1,129 +0,0 @@ -""" -Copyright (c) 2007 Michael Twomey - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -ISO 8601 date time string parsing - -Basic usage: ->>> import iso8601 ->>> iso8601.parse_date("2007-01-25T12:00:00Z") -datetime.datetime(2007, 1, 25, 12, 0, tzinfo=) ->>> -""" - -# Taken from pyiso8601 which is licensed under the MIT license. - -from datetime import datetime, timedelta, tzinfo -import re - -__all__ = ["parse_date", "ParseError"] - -# Adapted from http://delete.me.uk/2005/03/iso8601.html -ISO8601_REGEX = re.compile( - r"(?P[0-9]{4})(-(?P[0-9]{1,2})(-(?P[0-9]{1,2})" - r"((?P.)(?P[0-9]{2}):(?P[0-9]{2})(:(?P[0-9]{2})(\.(?P[0-9]+))?)?" # NOQA - r"(?PZ|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?") -TIMEZONE_REGEX = re.compile("(?P[+-])(?P[0-9]{2}).(?P[0-9]{2})") # NOQA - - -class ParseError(Exception): - """Raised when there is a problem parsing a date string""" - -# Yoinked from python docs -ZERO = timedelta(0) - - -class Utc(tzinfo): - """UTC - - """ - def utcoffset(self, dt): - return ZERO - - def tzname(self, dt): - return "UTC" - - def dst(self, dt): - return ZERO -UTC = Utc() - - -class FixedOffset(tzinfo): - """Fixed offset in hours and minutes from UTC - - """ - def __init__(self, offset_hours, offset_minutes, name): - self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) - self.__name = name - - def utcoffset(self, dt): - return self.__offset - - def tzname(self, dt): - return self.__name - - def dst(self, dt): - return ZERO - - def __repr__(self): - return "" % self.__name - - -def parse_timezone(tzstring, default_timezone=UTC): - """Parses ISO 8601 time zone specs into tzinfo offsets - - """ - if tzstring == "Z": - return default_timezone - # This isn't strictly correct, but it's common to encounter dates without - # timezones so I'll assume the default (which defaults to UTC). - # Addresses issue 4. - if tzstring is None: - return default_timezone - m = TIMEZONE_REGEX.match(tzstring) - prefix, hours, minutes = m.groups() - hours, minutes = int(hours), int(minutes) - if prefix == "-": - hours = -hours - minutes = -minutes - return FixedOffset(hours, minutes, tzstring) - - -def parse_date(datestring, default_timezone=UTC): - """Parses ISO 8601 dates into datetime objects - - The timezone is parsed from the date string. However it is quite common to - have dates without a timezone (not strictly correct). In this case the - default timezone specified in default_timezone is used. This is UTC by - default. - """ - m = ISO8601_REGEX.match(datestring) - if not m: - raise ParseError("Unable to parse date string %r" % datestring) - groups = m.groupdict() - tz = parse_timezone(groups["timezone"], default_timezone=default_timezone) - if groups["fraction"] is None: - groups["fraction"] = 0 - else: - groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6) - return datetime(int(groups["year"]), int(groups["month"]), - int(groups["day"]), int(groups["hour"]), - int(groups["minute"]), int(groups["second"]), - int(groups["fraction"]), tz) diff --git a/awx/lib/site-packages/libcloud/utils/logging.py b/awx/lib/site-packages/libcloud/utils/logging.py deleted file mode 100644 index e95ca9cf86..0000000000 --- a/awx/lib/site-packages/libcloud/utils/logging.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Taken from https://github.com/Kami/python-extra-log-formatters - -from __future__ import absolute_import - -import logging - -__all__ = [ - 'ExtraLogFormatter' -] - - -class ExtraLogFormatter(logging.Formatter): - """ - Custom log formatter which attaches all the attributes from the "extra" - dictionary which start with an underscore to the end of the log message. - - For example: - extra={'_id': 'user-1', '_path': '/foo/bar'} - """ - def format(self, record): - custom_attributes = dict([(k, v) for k, v in record.__dict__.items() - if k.startswith('_')]) - custom_attributes = self._dict_to_str(custom_attributes) - - msg = logging.Formatter.format(self, record) - msg = '%s (%s)' % (msg, custom_attributes) - return msg - - def _dict_to_str(self, dictionary): - result = ['%s=%s' % (k[1:], str(v)) for k, v in dictionary.items()] - result = ','.join(result) - return result diff --git a/awx/lib/site-packages/libcloud/utils/misc.py b/awx/lib/site-packages/libcloud/utils/misc.py deleted file mode 100644 index fbca4cb100..0000000000 --- a/awx/lib/site-packages/libcloud/utils/misc.py +++ /dev/null @@ -1,254 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys -import binascii - - -__all__ = [ - 'get_driver', - 'set_driver', - 'merge_valid_keys', - 'get_new_obj', - 'str2dicts', - 'dict2str', - 'reverse_dict', - 'lowercase_keys', - 'get_secure_random_string' -] - - -def get_driver(drivers, provider): - """ - Get a driver. - - :param drivers: Dictionary containing valid providers. - :param provider: Id of provider to get driver - :type provider: :class:`libcloud.types.Provider` - """ - if provider in drivers: - mod_name, driver_name = drivers[provider] - _mod = __import__(mod_name, globals(), locals(), [driver_name]) - return getattr(_mod, driver_name) - - raise AttributeError('Provider %s does not exist' % (provider)) - - -def set_driver(drivers, provider, module, klass): - """ - Sets a driver. - - :param drivers: Dictionary to store providers. - :param provider: Id of provider to set driver for - :type provider: :class:`libcloud.types.Provider` - :param module: The module which contains the driver - :type module: L - :param klass: The driver class name - :type klass: - """ - - if provider in drivers: - raise AttributeError('Provider %s already registered' % (provider)) - - drivers[provider] = (module, klass) - - # Check if this driver is valid - try: - driver = get_driver(drivers, provider) - except (ImportError, AttributeError): - exp = sys.exc_info()[1] - drivers.pop(provider) - raise exp - - return driver - - -def merge_valid_keys(params, valid_keys, extra): - """ - Merge valid keys from extra into params dictionary and return - dictionary with keys which have been merged. - - Note: params is modified in place. - """ - merged = {} - if not extra: - return merged - - for key in valid_keys: - if key in extra: - params[key] = extra[key] - merged[key] = extra[key] - - return merged - - -def get_new_obj(obj, klass, attributes): - """ - Pass attributes from the existing object 'obj' and attributes - dictionary to a 'klass' constructor. - Attributes from 'attributes' dictionary are only passed to the - constructor if they are not None. - """ - kwargs = {} - for key, value in list(obj.__dict__.items()): - if isinstance(value, dict): - kwargs[key] = value.copy() - elif isinstance(value, (tuple, list)): - kwargs[key] = value[:] - else: - kwargs[key] = value - - for key, value in list(attributes.items()): - if value is None: - continue - - if isinstance(value, dict): - kwargs_value = kwargs.get(key, {}) - for key1, value2 in list(value.items()): - if value2 is None: - continue - - kwargs_value[key1] = value2 - kwargs[key] = kwargs_value - else: - kwargs[key] = value - - return klass(**kwargs) - - -def str2dicts(data): - """ - Create a list of dictionaries from a whitespace and newline delimited text. - - For example, this: - cpu 1100 - ram 640 - - cpu 2200 - ram 1024 - - becomes: - [{'cpu': '1100', 'ram': '640'}, {'cpu': '2200', 'ram': '1024'}] - """ - list_data = [] - list_data.append({}) - d = list_data[-1] - - lines = data.split('\n') - for line in lines: - line = line.strip() - - if not line: - d = {} - list_data.append(d) - d = list_data[-1] - continue - - whitespace = line.find(' ') - - if not whitespace: - continue - - key = line[0:whitespace] - value = line[whitespace + 1:] - d.update({key: value}) - - list_data = [val for val in list_data if val != {}] - return list_data - - -def str2list(data): - """ - Create a list of values from a whitespace and newline delimited text - (keys are ignored). - - For example, this: - ip 1.2.3.4 - ip 1.2.3.5 - ip 1.2.3.6 - - becomes: - ['1.2.3.4', '1.2.3.5', '1.2.3.6'] - """ - list_data = [] - - for line in data.split('\n'): - line = line.strip() - - if not line: - continue - - try: - splitted = line.split(' ') - # key = splitted[0] - value = splitted[1] - except Exception: - continue - - list_data.append(value) - - return list_data - - -def dict2str(data): - """ - Create a string with a whitespace and newline delimited text from a - dictionary. - - For example, this: - {'cpu': '1100', 'ram': '640', 'smp': 'auto'} - - becomes: - cpu 1100 - ram 640 - smp auto - - cpu 2200 - ram 1024 - """ - result = '' - for k in data: - if data[k] is not None: - result += '%s %s\n' % (str(k), str(data[k])) - else: - result += '%s\n' % str(k) - - return result - - -def reverse_dict(dictionary): - return dict([(value, key) for key, value in list(dictionary.items())]) - - -def lowercase_keys(dictionary): - return dict(((k.lower(), v) for k, v in dictionary.items())) - - -def get_secure_random_string(size): - """ - Return a string of ``size`` random bytes. Returned string is suitable for - cryptographic use. - - :param size: Size of the generated string. - :type size: ``int`` - - :return: Random string. - :rtype: ``str`` - """ - value = os.urandom(size) - value = binascii.hexlify(value) - value = value.decode('utf-8')[:size] - return value diff --git a/awx/lib/site-packages/libcloud/utils/networking.py b/awx/lib/site-packages/libcloud/utils/networking.py deleted file mode 100644 index f7dca9bbc5..0000000000 --- a/awx/lib/site-packages/libcloud/utils/networking.py +++ /dev/null @@ -1,80 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import socket -import struct - -__all__ = [ - 'is_private_subnet', - 'is_public_subnet', - 'is_valid_ip_address' -] - - -def is_private_subnet(ip): - """ - Utility function to check if an IP address is inside a private subnet. - - :type ip: ``str`` - :param ip: IP address to check - - :return: ``bool`` if the specified IP address is private. - """ - priv_subnets = [{'subnet': '10.0.0.0', 'mask': '255.0.0.0'}, - {'subnet': '172.16.0.0', 'mask': '255.240.0.0'}, - {'subnet': '192.168.0.0', 'mask': '255.255.0.0'}] - - ip = struct.unpack('I', socket.inet_aton(ip))[0] - - for network in priv_subnets: - subnet = struct.unpack('I', socket.inet_aton(network['subnet']))[0] - mask = struct.unpack('I', socket.inet_aton(network['mask']))[0] - - if (ip & mask) == (subnet & mask): - return True - - return False - - -def is_public_subnet(ip): - """ - Utility function to check if an IP address is inside a public subnet. - - :type ip: ``str`` - :param ip: IP address to check - - :return: ``bool`` if the specified IP address is public. - """ - return not is_private_subnet(ip=ip) - - -def is_valid_ip_address(address, family=socket.AF_INET): - """ - Check if the provided address is valid IPv4 or IPv6 address. - - :param address: IPv4 or IPv6 ddress to check. - :type address: ``str`` - - :param family: Address family (socket.AF_INTET / socket.AF_INET6). - :type family: ``int`` - - :return: ``bool`` True if the provided address is valid. - """ - try: - socket.inet_pton(family, address) - except socket.error: - return False - - return True diff --git a/awx/lib/site-packages/libcloud/utils/publickey.py b/awx/lib/site-packages/libcloud/utils/publickey.py deleted file mode 100644 index 86c6ec30c1..0000000000 --- a/awx/lib/site-packages/libcloud/utils/publickey.py +++ /dev/null @@ -1,70 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import hashlib - -from libcloud.utils.py3 import hexadigits -from libcloud.utils.py3 import bchr - -__all__ = [ - 'get_pubkey_openssh_fingerprint', - 'get_pubkey_ssh2_fingerprint', - 'get_pubkey_comment' -] - -try: - from Crypto.Util.asn1 import DerSequence, DerObject - from Crypto.PublicKey.RSA import algorithmIdentifier, importKey - pycrypto_available = True -except ImportError: - pycrypto_available = False - - -def _to_md5_fingerprint(data): - hashed = hashlib.md5(data).digest() - return ":".join(hexadigits(hashed)) - - -def get_pubkey_openssh_fingerprint(pubkey): - # We import and export the key to make sure it is in OpenSSH format - if not pycrypto_available: - raise RuntimeError('pycrypto is not available') - k = importKey(pubkey) - pubkey = k.exportKey('OpenSSH')[7:] - decoded = base64.decodestring(pubkey) - return _to_md5_fingerprint(decoded) - - -def get_pubkey_ssh2_fingerprint(pubkey): - # This is the format that EC2 shows for public key fingerprints in its - # KeyPair mgmt API - if not pycrypto_available: - raise RuntimeError('pycrypto is not available') - k = importKey(pubkey) - derPK = DerSequence([k.n, k.e]) - bitmap = DerObject('BIT STRING') - bitmap.payload = bchr(0x00) + derPK.encode() - der = DerSequence([algorithmIdentifier, bitmap.encode()]) - return _to_md5_fingerprint(der.encode()) - - -def get_pubkey_comment(pubkey, default=None): - if pubkey.startswith("ssh-"): - # This is probably an OpenSSH key - return pubkey.strip().split(' ', 3)[2] - if default: - return default - raise ValueError('Public key is not in a supported format') diff --git a/awx/lib/site-packages/libcloud/utils/py3.py b/awx/lib/site-packages/libcloud/utils/py3.py deleted file mode 100644 index 1f7d229ec6..0000000000 --- a/awx/lib/site-packages/libcloud/utils/py3.py +++ /dev/null @@ -1,195 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Libcloud Python 2.x and 3.x compatibility layer -# Some methods below are taken from Django PYK3 port which is licensed under 3 -# clause BSD license -# https://bitbucket.org/loewis/django-3k - -from __future__ import absolute_import - -import sys -import types - -try: - from lxml import etree as ET -except ImportError: - from xml.etree import ElementTree as ET - -PY2 = False -PY25 = False -PY27 = False -PY3 = False -PY32 = False - -if sys.version_info >= (2, 0) and sys.version_info < (3, 0): - PY2 = True - -if sys.version_info >= (2, 5) and sys.version_info <= (2, 6): - PY25 = True - -if sys.version_info >= (2, 7) and sys.version_info <= (2, 8): - PY27 = True - -if sys.version_info >= (3, 0): - PY3 = True - -if sys.version_info >= (3, 2) and sys.version_info < (3, 3): - PY32 = True - -if PY3: - import http.client as httplib - from io import StringIO - import urllib - import urllib as urllib2 - import urllib.parse as urlparse - import xmlrpc.client as xmlrpclib - - from urllib.parse import quote as urlquote - from urllib.parse import unquote as urlunquote - from urllib.parse import urlencode as urlencode - from os.path import relpath - - from imp import reload - - from builtins import bytes - from builtins import next - - parse_qs = urlparse.parse_qs - parse_qsl = urlparse.parse_qsl - - basestring = str - - def method_type(callable, instance, klass): - return types.MethodType(callable, instance or klass()) - - def b(s): - if isinstance(s, str): - return s.encode('utf-8') - elif isinstance(s, bytes): - return s - else: - raise TypeError("Invalid argument %r for b()" % (s,)) - - def ensure_string(s): - if isinstance(s, str): - return s - elif isinstance(s, bytes): - return s.decode('utf-8') - else: - raise TypeError("Invalid argument %r for ensure_string()" % (s,)) - - def byte(n): - # assume n is a Latin-1 string of length 1 - return ord(n) - u = str - - def bchr(s): - """Take an integer and make a 1-character byte string.""" - return bytes([s]) - - def dictvalues(d): - return list(d.values()) - - def tostring(node): - return ET.tostring(node, encoding='unicode') - - def hexadigits(s): - # s needs to be a byte string. - return [format(x, "x") for x in s] - -else: - import httplib # NOQA - from StringIO import StringIO # NOQA - import urllib # NOQA - import urllib2 # NOQA - import urlparse # NOQA - import xmlrpclib # NOQA - from urllib import quote as _urlquote # NOQA - from urllib import unquote as urlunquote # NOQA - from urllib import urlencode as urlencode # NOQA - - from __builtin__ import reload # NOQA - - if PY25: - import cgi - - parse_qs = cgi.parse_qs - parse_qsl = cgi.parse_qsl - else: - parse_qs = urlparse.parse_qs - parse_qsl = urlparse.parse_qsl - - if not PY25: - from os.path import relpath # NOQA - - # Save the real value of unicode because urlquote needs it to tell the - # difference between a unicode string and a byte string. - _real_unicode = unicode - basestring = unicode = str - - method_type = types.MethodType - - b = bytes = ensure_string = str - - def byte(n): - return n - - u = unicode - - def bchr(s): - """Take an integer and make a 1-character byte string.""" - return chr(s) - - def next(i): - return i.next() - - def dictvalues(d): - return d.values() - - tostring = ET.tostring - - def urlquote(s, safe='/'): - if isinstance(s, _real_unicode): - # Pretend to be py3 by encoding the URI automatically. - s = s.encode('utf8') - return _urlquote(s, safe) - - def hexadigits(s): - # s needs to be a string. - return [x.encode("hex") for x in s] - -if PY25: - import posixpath - - # Taken from http://jimmyg.org/work/code/barenecessities/index.html - # (MIT license) - def relpath(path, start=posixpath.curdir): # NOQA - """Return a relative version of a path""" - if not path: - raise ValueError("no path specified") - start_list = posixpath.abspath(start).split(posixpath.sep) - path_list = posixpath.abspath(path).split(posixpath.sep) - # Work out how much of the filepath is shared by start and path. - i = len(posixpath.commonprefix([start_list, path_list])) - rel_list = [posixpath.pardir] * (len(start_list) - i) + path_list[i:] - if not rel_list: - return posixpath.curdir - return posixpath.join(*rel_list) - -if PY27 or PY3: - unittest2_required = False -else: - unittest2_required = True diff --git a/awx/lib/site-packages/libcloud/utils/xml.py b/awx/lib/site-packages/libcloud/utils/xml.py deleted file mode 100644 index c2c1321221..0000000000 --- a/awx/lib/site-packages/libcloud/utils/xml.py +++ /dev/null @@ -1,50 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -__all__ = [ - 'fixxpath', - 'findtext', - 'findattr', - 'findall' -] - - -def fixxpath(xpath, namespace=None): - # ElementTree wants namespaces in its xpaths, so here we add them. - if not namespace: - return xpath - - return '/'.join(['{%s}%s' % (namespace, e) for e in xpath.split('/')]) - - -def findtext(element, xpath, namespace=None, no_text_value=''): - """ - :param no_text_value: Value to return if the provided element has no text - value. - :type no_text_value: ``object`` - """ - value = element.findtext(fixxpath(xpath=xpath, namespace=namespace)) - - if value == '': - return no_text_value - return value - - -def findattr(element, xpath, namespace=None): - return element.findtext(fixxpath(xpath=xpath, namespace=namespace)) - - -def findall(element, xpath, namespace=None): - return element.findall(fixxpath(xpath=xpath, namespace=namespace)) diff --git a/awx/lib/site-packages/markdown/__init__.py b/awx/lib/site-packages/markdown/__init__.py deleted file mode 100644 index 4943388ed0..0000000000 --- a/awx/lib/site-packages/markdown/__init__.py +++ /dev/null @@ -1,442 +0,0 @@ -""" -Python Markdown -=============== - -Python Markdown converts Markdown to HTML and can be used as a library or -called from the command line. - -## Basic usage as a module: - - import markdown - html = markdown.markdown(your_text_string) - -See for more -information and instructions on how to extend the functionality of -Python Markdown. Read that before you try modifying this file. - -## Authors and License - -Started by [Manfred Stienstra](http://www.dwerg.net/). Continued and -maintained by [Yuri Takhteyev](http://www.freewisdom.org), [Waylan -Limberg](http://achinghead.com/) and [Artem Yunusov](http://blog.splyer.com). - -Contact: markdown@freewisdom.org - -Copyright 2007-2013 The Python Markdown Project (v. 1.7 and later) -Copyright 200? Django Software Foundation (OrderedDict implementation) -Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) -Copyright 2004 Manfred Stienstra (the original version) - -License: BSD (see LICENSE for details). -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from .__version__ import version, version_info -import codecs -import sys -import logging -from . import util -from .preprocessors import build_preprocessors -from .blockprocessors import build_block_parser -from .treeprocessors import build_treeprocessors -from .inlinepatterns import build_inlinepatterns -from .postprocessors import build_postprocessors -from .extensions import Extension -from .serializers import to_html_string, to_xhtml_string - -__all__ = ['Markdown', 'markdown', 'markdownFromFile'] - -logger = logging.getLogger('MARKDOWN') - - -class Markdown(object): - """Convert Markdown to HTML.""" - - doc_tag = "div" # Element used to wrap document - later removed - - option_defaults = { - 'html_replacement_text' : '[HTML_REMOVED]', - 'tab_length' : 4, - 'enable_attributes' : True, - 'smart_emphasis' : True, - 'lazy_ol' : True, - } - - output_formats = { - 'html' : to_html_string, - 'html4' : to_html_string, - 'html5' : to_html_string, - 'xhtml' : to_xhtml_string, - 'xhtml1': to_xhtml_string, - 'xhtml5': to_xhtml_string, - } - - ESCAPED_CHARS = ['\\', '`', '*', '_', '{', '}', '[', ']', - '(', ')', '>', '#', '+', '-', '.', '!'] - - def __init__(self, *args, **kwargs): - """ - Creates a new Markdown instance. - - Keyword arguments: - - * extensions: A list of extensions. - If they are of type string, the module mdx_name.py will be loaded. - If they are a subclass of markdown.Extension, they will be used - as-is. - * extension_configs: Configuration settingis for extensions. - * output_format: Format of output. Supported formats are: - * "xhtml1": Outputs XHTML 1.x. Default. - * "xhtml5": Outputs XHTML style tags of HTML 5 - * "xhtml": Outputs latest supported version of XHTML (currently XHTML 1.1). - * "html4": Outputs HTML 4 - * "html5": Outputs HTML style tags of HTML 5 - * "html": Outputs latest supported version of HTML (currently HTML 4). - Note that it is suggested that the more specific formats ("xhtml1" - and "html4") be used as "xhtml" or "html" may change in the future - if it makes sense at that time. - * safe_mode: Disallow raw html. One of "remove", "replace" or "escape". - * html_replacement_text: Text used when safe_mode is set to "replace". - * tab_length: Length of tabs in the source. Default: 4 - * enable_attributes: Enable the conversion of attributes. Default: True - * smart_emphasis: Treat `_connected_words_` intelligently Default: True - * lazy_ol: Ignore number of first item of ordered lists. Default: True - - """ - - # For backward compatibility, loop through old positional args - pos = ['extensions', 'extension_configs', 'safe_mode', 'output_format'] - c = 0 - for arg in args: - if pos[c] not in kwargs: - kwargs[pos[c]] = arg - c += 1 - if c == len(pos): - # ignore any additional args - break - - # Loop through kwargs and assign defaults - for option, default in self.option_defaults.items(): - setattr(self, option, kwargs.get(option, default)) - - self.safeMode = kwargs.get('safe_mode', False) - if self.safeMode and 'enable_attributes' not in kwargs: - # Disable attributes in safeMode when not explicitly set - self.enable_attributes = False - - self.registeredExtensions = [] - self.docType = "" - self.stripTopLevelTags = True - - self.build_parser() - - self.references = {} - self.htmlStash = util.HtmlStash() - self.registerExtensions(extensions=kwargs.get('extensions', []), - configs=kwargs.get('extension_configs', {})) - self.set_output_format(kwargs.get('output_format', 'xhtml1')) - self.reset() - - def build_parser(self): - """ Build the parser from the various parts. """ - self.preprocessors = build_preprocessors(self) - self.parser = build_block_parser(self) - self.inlinePatterns = build_inlinepatterns(self) - self.treeprocessors = build_treeprocessors(self) - self.postprocessors = build_postprocessors(self) - return self - - def registerExtensions(self, extensions, configs): - """ - Register extensions with this instance of Markdown. - - Keyword arguments: - - * extensions: A list of extensions, which can either - be strings or objects. See the docstring on Markdown. - * configs: A dictionary mapping module names to config options. - - """ - for ext in extensions: - if isinstance(ext, util.string_type): - ext = self.build_extension(ext, configs.get(ext, [])) - if isinstance(ext, Extension): - ext.extendMarkdown(self, globals()) - elif ext is not None: - raise TypeError( - 'Extension "%s.%s" must be of type: "markdown.Extension"' - % (ext.__class__.__module__, ext.__class__.__name__)) - - return self - - def build_extension(self, ext_name, configs = []): - """Build extension by name, then return the module. - - The extension name may contain arguments as part of the string in the - following format: "extname(key1=value1,key2=value2)" - - """ - - # Parse extensions config params (ignore the order) - configs = dict(configs) - pos = ext_name.find("(") # find the first "(" - if pos > 0: - ext_args = ext_name[pos+1:-1] - ext_name = ext_name[:pos] - pairs = [x.split("=") for x in ext_args.split(",")] - configs.update([(x.strip(), y.strip()) for (x, y) in pairs]) - - # Setup the module name - module_name = ext_name - if '.' not in ext_name: - module_name = '.'.join(['markdown.extensions', ext_name]) - - # Try loading the extension first from one place, then another - try: # New style (markdown.extensions.) - module = __import__(module_name, {}, {}, [module_name.rpartition('.')[0]]) - except ImportError: - module_name_old_style = '_'.join(['mdx', ext_name]) - try: # Old style (mdx_) - module = __import__(module_name_old_style) - except ImportError as e: - message = "Failed loading extension '%s' from '%s' or '%s'" \ - % (ext_name, module_name, module_name_old_style) - e.args = (message,) + e.args[1:] - raise - - # If the module is loaded successfully, we expect it to define a - # function called makeExtension() - try: - return module.makeExtension(configs.items()) - except AttributeError as e: - message = e.args[0] - message = "Failed to initiate extension " \ - "'%s': %s" % (ext_name, message) - e.args = (message,) + e.args[1:] - raise - - def registerExtension(self, extension): - """ This gets called by the extension """ - self.registeredExtensions.append(extension) - return self - - def reset(self): - """ - Resets all state variables so that we can start with a new text. - """ - self.htmlStash.reset() - self.references.clear() - - for extension in self.registeredExtensions: - if hasattr(extension, 'reset'): - extension.reset() - - return self - - def set_output_format(self, format): - """ Set the output format for the class instance. """ - self.output_format = format.lower() - try: - self.serializer = self.output_formats[self.output_format] - except KeyError as e: - valid_formats = list(self.output_formats.keys()) - valid_formats.sort() - message = 'Invalid Output Format: "%s". Use one of %s.' \ - % (self.output_format, - '"' + '", "'.join(valid_formats) + '"') - e.args = (message,) + e.args[1:] - raise - return self - - def convert(self, source): - """ - Convert markdown to serialized XHTML or HTML. - - Keyword arguments: - - * source: Source text as a Unicode string. - - Markdown processing takes place in five steps: - - 1. A bunch of "preprocessors" munge the input text. - 2. BlockParser() parses the high-level structural elements of the - pre-processed text into an ElementTree. - 3. A bunch of "treeprocessors" are run against the ElementTree. One - such treeprocessor runs InlinePatterns against the ElementTree, - detecting inline markup. - 4. Some post-processors are run against the text after the ElementTree - has been serialized into text. - 5. The output is written to a string. - - """ - - # Fixup the source text - if not source.strip(): - return '' # a blank unicode string - - try: - source = util.text_type(source) - except UnicodeDecodeError as e: - # Customise error message while maintaining original trackback - e.reason += '. -- Note: Markdown only accepts unicode input!' - raise - - # Split into lines and run the line preprocessors. - self.lines = source.split("\n") - for prep in self.preprocessors.values(): - self.lines = prep.run(self.lines) - - # Parse the high-level elements. - root = self.parser.parseDocument(self.lines).getroot() - - # Run the tree-processors - for treeprocessor in self.treeprocessors.values(): - newRoot = treeprocessor.run(root) - if newRoot is not None: - root = newRoot - - # Serialize _properly_. Strip top-level tags. - output = self.serializer(root) - if self.stripTopLevelTags: - try: - start = output.index('<%s>'%self.doc_tag)+len(self.doc_tag)+2 - end = output.rindex(''%self.doc_tag) - output = output[start:end].strip() - except ValueError: - if output.strip().endswith('<%s />'%self.doc_tag): - # We have an empty document - output = '' - else: - # We have a serious problem - raise ValueError('Markdown failed to strip top-level tags. Document=%r' % output.strip()) - - # Run the text post-processors - for pp in self.postprocessors.values(): - output = pp.run(output) - - return output.strip() - - def convertFile(self, input=None, output=None, encoding=None): - """Converts a markdown file and returns the HTML as a unicode string. - - Decodes the file using the provided encoding (defaults to utf-8), - passes the file content to markdown, and outputs the html to either - the provided stream or the file with provided name, using the same - encoding as the source file. The 'xmlcharrefreplace' error handler is - used when encoding the output. - - **Note:** This is the only place that decoding and encoding of unicode - takes place in Python-Markdown. (All other code is unicode-in / - unicode-out.) - - Keyword arguments: - - * input: File object or path. Reads from stdin if `None`. - * output: File object or path. Writes to stdout if `None`. - * encoding: Encoding of input and output files. Defaults to utf-8. - - """ - - encoding = encoding or "utf-8" - - # Read the source - if input: - if isinstance(input, util.string_type): - input_file = codecs.open(input, mode="r", encoding=encoding) - else: - input_file = codecs.getreader(encoding)(input) - text = input_file.read() - input_file.close() - else: - text = sys.stdin.read() - if not isinstance(text, util.text_type): - text = text.decode(encoding) - - text = text.lstrip('\ufeff') # remove the byte-order mark - - # Convert - html = self.convert(text) - - # Write to file or stdout - if output: - if isinstance(output, util.string_type): - output_file = codecs.open(output, "w", - encoding=encoding, - errors="xmlcharrefreplace") - output_file.write(html) - output_file.close() - else: - writer = codecs.getwriter(encoding) - output_file = writer(output, errors="xmlcharrefreplace") - output_file.write(html) - # Don't close here. User may want to write more. - else: - # Encode manually and write bytes to stdout. - html = html.encode(encoding, "xmlcharrefreplace") - try: - # Write bytes directly to buffer (Python 3). - sys.stdout.buffer.write(html) - except AttributeError: - # Probably Python 2, which works with bytes by default. - sys.stdout.write(html) - - return self - - -""" -EXPORTED FUNCTIONS -============================================================================= - -Those are the two functions we really mean to export: markdown() and -markdownFromFile(). -""" - -def markdown(text, *args, **kwargs): - """Convert a markdown string to HTML and return HTML as a unicode string. - - This is a shortcut function for `Markdown` class to cover the most - basic use case. It initializes an instance of Markdown, loads the - necessary extensions and runs the parser on the given text. - - Keyword arguments: - - * text: Markdown formatted text as Unicode or ASCII string. - * Any arguments accepted by the Markdown class. - - Returns: An HTML document as a string. - - """ - md = Markdown(*args, **kwargs) - return md.convert(text) - - -def markdownFromFile(*args, **kwargs): - """Read markdown code from a file and write it to a file or a stream. - - This is a shortcut function which initializes an instance of Markdown, - and calls the convertFile method rather than convert. - - Keyword arguments: - - * input: a file name or readable object. - * output: a file name or writable object. - * encoding: Encoding of input and output. - * Any arguments accepted by the Markdown class. - - """ - # For backward compatibility loop through positional args - pos = ['input', 'output', 'extensions', 'encoding'] - c = 0 - for arg in args: - if pos[c] not in kwargs: - kwargs[pos[c]] = arg - c += 1 - if c == len(pos): - break - - md = Markdown(**kwargs) - md.convertFile(kwargs.get('input', None), - kwargs.get('output', None), - kwargs.get('encoding', None)) - diff --git a/awx/lib/site-packages/markdown/__main__.py b/awx/lib/site-packages/markdown/__main__.py deleted file mode 100644 index 8ee8c8222e..0000000000 --- a/awx/lib/site-packages/markdown/__main__.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -COMMAND-LINE SPECIFIC STUFF -============================================================================= - -""" - -import markdown -import sys -import optparse - -import logging -from logging import DEBUG, INFO, CRITICAL - -logger = logging.getLogger('MARKDOWN') - -def parse_options(): - """ - Define and parse `optparse` options for command-line usage. - """ - usage = """%prog [options] [INPUTFILE] - (STDIN is assumed if no INPUTFILE is given)""" - desc = "A Python implementation of John Gruber's Markdown. " \ - "http://packages.python.org/Markdown/" - ver = "%%prog %s" % markdown.version - - parser = optparse.OptionParser(usage=usage, description=desc, version=ver) - parser.add_option("-f", "--file", dest="filename", default=None, - help="Write output to OUTPUT_FILE. Defaults to STDOUT.", - metavar="OUTPUT_FILE") - parser.add_option("-e", "--encoding", dest="encoding", - help="Encoding for input and output files.",) - parser.add_option("-q", "--quiet", default = CRITICAL, - action="store_const", const=CRITICAL+10, dest="verbose", - help="Suppress all warnings.") - parser.add_option("-v", "--verbose", - action="store_const", const=INFO, dest="verbose", - help="Print all warnings.") - parser.add_option("-s", "--safe", dest="safe", default=False, - metavar="SAFE_MODE", - help="'replace', 'remove' or 'escape' HTML tags in input") - parser.add_option("-o", "--output_format", dest="output_format", - default='xhtml1', metavar="OUTPUT_FORMAT", - help="'xhtml1' (default), 'html4' or 'html5'.") - parser.add_option("--noisy", - action="store_const", const=DEBUG, dest="verbose", - help="Print debug messages.") - parser.add_option("-x", "--extension", action="append", dest="extensions", - help = "Load extension EXTENSION.", metavar="EXTENSION") - parser.add_option("-n", "--no_lazy_ol", dest="lazy_ol", - action='store_false', default=True, - help="Observe number of first item of ordered lists.") - - (options, args) = parser.parse_args() - - if len(args) == 0: - input_file = None - else: - input_file = args[0] - - if not options.extensions: - options.extensions = [] - - return {'input': input_file, - 'output': options.filename, - 'safe_mode': options.safe, - 'extensions': options.extensions, - 'encoding': options.encoding, - 'output_format': options.output_format, - 'lazy_ol': options.lazy_ol}, options.verbose - -def run(): - """Run Markdown from the command line.""" - - # Parse options and adjust logging level if necessary - options, logging_level = parse_options() - if not options: sys.exit(2) - logger.setLevel(logging_level) - logger.addHandler(logging.StreamHandler()) - - # Run - markdown.markdownFromFile(**options) - -if __name__ == '__main__': - # Support running module as a commandline command. - # Python 2.5 & 2.6 do: `python -m markdown.__main__ [options] [args]`. - # Python 2.7 & 3.x do: `python -m markdown [options] [args]`. - run() diff --git a/awx/lib/site-packages/markdown/__version__.py b/awx/lib/site-packages/markdown/__version__.py deleted file mode 100644 index 2132ce6631..0000000000 --- a/awx/lib/site-packages/markdown/__version__.py +++ /dev/null @@ -1,28 +0,0 @@ -# -# markdown/__version__.py -# -# version_info should conform to PEP 386 -# (major, minor, micro, alpha/beta/rc/final, #) -# (1, 1, 2, 'alpha', 0) => "1.1.2.dev" -# (1, 2, 0, 'beta', 2) => "1.2b2" -version_info = (2, 4, 1, 'final', 0) - -def _get_version(): - " Returns a PEP 386-compliant version number from version_info. " - assert len(version_info) == 5 - assert version_info[3] in ('alpha', 'beta', 'rc', 'final') - - parts = 2 if version_info[2] == 0 else 3 - main = '.'.join(map(str, version_info[:parts])) - - sub = '' - if version_info[3] == 'alpha' and version_info[4] == 0: - # TODO: maybe append some sort of git info here?? - sub = '.dev' - elif version_info[3] != 'final': - mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'c'} - sub = mapping[version_info[3]] + str(version_info[4]) - - return str(main + sub) - -version = _get_version() diff --git a/awx/lib/site-packages/markdown/blockparser.py b/awx/lib/site-packages/markdown/blockparser.py deleted file mode 100644 index 4504a16f51..0000000000 --- a/awx/lib/site-packages/markdown/blockparser.py +++ /dev/null @@ -1,99 +0,0 @@ -from __future__ import unicode_literals -from __future__ import absolute_import -from . import util -from . import odict - -class State(list): - """ Track the current and nested state of the parser. - - This utility class is used to track the state of the BlockParser and - support multiple levels if nesting. It's just a simple API wrapped around - a list. Each time a state is set, that state is appended to the end of the - list. Each time a state is reset, that state is removed from the end of - the list. - - Therefore, each time a state is set for a nested block, that state must be - reset when we back out of that level of nesting or the state could be - corrupted. - - While all the methods of a list object are available, only the three - defined below need be used. - - """ - - def set(self, state): - """ Set a new state. """ - self.append(state) - - def reset(self): - """ Step back one step in nested state. """ - self.pop() - - def isstate(self, state): - """ Test that top (current) level is of given state. """ - if len(self): - return self[-1] == state - else: - return False - -class BlockParser: - """ Parse Markdown blocks into an ElementTree object. - - A wrapper class that stitches the various BlockProcessors together, - looping through them and creating an ElementTree object. - """ - - def __init__(self, markdown): - self.blockprocessors = odict.OrderedDict() - self.state = State() - self.markdown = markdown - - def parseDocument(self, lines): - """ Parse a markdown document into an ElementTree. - - Given a list of lines, an ElementTree object (not just a parent Element) - is created and the root element is passed to the parser as the parent. - The ElementTree object is returned. - - This should only be called on an entire document, not pieces. - - """ - # Create a ElementTree from the lines - self.root = util.etree.Element(self.markdown.doc_tag) - self.parseChunk(self.root, '\n'.join(lines)) - return util.etree.ElementTree(self.root) - - def parseChunk(self, parent, text): - """ Parse a chunk of markdown text and attach to given etree node. - - While the ``text`` argument is generally assumed to contain multiple - blocks which will be split on blank lines, it could contain only one - block. Generally, this method would be called by extensions when - block parsing is required. - - The ``parent`` etree Element passed in is altered in place. - Nothing is returned. - - """ - self.parseBlocks(parent, text.split('\n\n')) - - def parseBlocks(self, parent, blocks): - """ Process blocks of markdown text and attach to given etree node. - - Given a list of ``blocks``, each blockprocessor is stepped through - until there are no blocks left. While an extension could potentially - call this method directly, it's generally expected to be used internally. - - This is a public method as an extension may need to add/alter additional - BlockProcessors which call this method to recursively parse a nested - block. - - """ - while blocks: - for processor in self.blockprocessors.values(): - if processor.test(parent, blocks[0]): - if processor.run(parent, blocks) is not False: - # run returns True or None - break - - diff --git a/awx/lib/site-packages/markdown/blockprocessors.py b/awx/lib/site-packages/markdown/blockprocessors.py deleted file mode 100644 index 147ff0ff9a..0000000000 --- a/awx/lib/site-packages/markdown/blockprocessors.py +++ /dev/null @@ -1,558 +0,0 @@ -""" -CORE MARKDOWN BLOCKPARSER -=========================================================================== - -This parser handles basic parsing of Markdown blocks. It doesn't concern itself -with inline elements such as **bold** or *italics*, but rather just catches -blocks, lists, quotes, etc. - -The BlockParser is made up of a bunch of BlockProssors, each handling a -different type of block. Extensions may add/replace/remove BlockProcessors -as they need to alter how markdown blocks are parsed. -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import unicode_literals -import logging -import re -from . import util -from .blockparser import BlockParser - -logger = logging.getLogger('MARKDOWN') - - -def build_block_parser(md_instance, **kwargs): - """ Build the default block parser used by Markdown. """ - parser = BlockParser(md_instance) - parser.blockprocessors['empty'] = EmptyBlockProcessor(parser) - parser.blockprocessors['indent'] = ListIndentProcessor(parser) - parser.blockprocessors['code'] = CodeBlockProcessor(parser) - parser.blockprocessors['hashheader'] = HashHeaderProcessor(parser) - parser.blockprocessors['setextheader'] = SetextHeaderProcessor(parser) - parser.blockprocessors['hr'] = HRProcessor(parser) - parser.blockprocessors['olist'] = OListProcessor(parser) - parser.blockprocessors['ulist'] = UListProcessor(parser) - parser.blockprocessors['quote'] = BlockQuoteProcessor(parser) - parser.blockprocessors['paragraph'] = ParagraphProcessor(parser) - return parser - - -class BlockProcessor: - """ Base class for block processors. - - Each subclass will provide the methods below to work with the source and - tree. Each processor will need to define it's own ``test`` and ``run`` - methods. The ``test`` method should return True or False, to indicate - whether the current block should be processed by this processor. If the - test passes, the parser will call the processors ``run`` method. - - """ - - def __init__(self, parser): - self.parser = parser - self.tab_length = parser.markdown.tab_length - - def lastChild(self, parent): - """ Return the last child of an etree element. """ - if len(parent): - return parent[-1] - else: - return None - - def detab(self, text): - """ Remove a tab from the front of each line of the given text. """ - newtext = [] - lines = text.split('\n') - for line in lines: - if line.startswith(' '*self.tab_length): - newtext.append(line[self.tab_length:]) - elif not line.strip(): - newtext.append('') - else: - break - return '\n'.join(newtext), '\n'.join(lines[len(newtext):]) - - def looseDetab(self, text, level=1): - """ Remove a tab from front of lines but allowing dedented lines. """ - lines = text.split('\n') - for i in range(len(lines)): - if lines[i].startswith(' '*self.tab_length*level): - lines[i] = lines[i][self.tab_length*level:] - return '\n'.join(lines) - - def test(self, parent, block): - """ Test for block type. Must be overridden by subclasses. - - As the parser loops through processors, it will call the ``test`` method - on each to determine if the given block of text is of that type. This - method must return a boolean ``True`` or ``False``. The actual method of - testing is left to the needs of that particular block type. It could - be as simple as ``block.startswith(some_string)`` or a complex regular - expression. As the block type may be different depending on the parent - of the block (i.e. inside a list), the parent etree element is also - provided and may be used as part of the test. - - Keywords: - - * ``parent``: A etree element which will be the parent of the block. - * ``block``: A block of text from the source which has been split at - blank lines. - """ - pass - - def run(self, parent, blocks): - """ Run processor. Must be overridden by subclasses. - - When the parser determines the appropriate type of a block, the parser - will call the corresponding processor's ``run`` method. This method - should parse the individual lines of the block and append them to - the etree. - - Note that both the ``parent`` and ``etree`` keywords are pointers - to instances of the objects which should be edited in place. Each - processor must make changes to the existing objects as there is no - mechanism to return new/different objects to replace them. - - This means that this method should be adding SubElements or adding text - to the parent, and should remove (``pop``) or add (``insert``) items to - the list of blocks. - - Keywords: - - * ``parent``: A etree element which is the parent of the current block. - * ``blocks``: A list of all remaining blocks of the document. - """ - pass - - -class ListIndentProcessor(BlockProcessor): - """ Process children of list items. - - Example: - * a list item - process this part - - or this part - - """ - - ITEM_TYPES = ['li'] - LIST_TYPES = ['ul', 'ol'] - - def __init__(self, *args): - BlockProcessor.__init__(self, *args) - self.INDENT_RE = re.compile(r'^(([ ]{%s})+)'% self.tab_length) - - def test(self, parent, block): - return block.startswith(' '*self.tab_length) and \ - not self.parser.state.isstate('detabbed') and \ - (parent.tag in self.ITEM_TYPES or \ - (len(parent) and parent[-1] and \ - (parent[-1].tag in self.LIST_TYPES) - ) - ) - - def run(self, parent, blocks): - block = blocks.pop(0) - level, sibling = self.get_level(parent, block) - block = self.looseDetab(block, level) - - self.parser.state.set('detabbed') - if parent.tag in self.ITEM_TYPES: - # It's possible that this parent has a 'ul' or 'ol' child list - # with a member. If that is the case, then that should be the - # parent. This is intended to catch the edge case of an indented - # list whose first member was parsed previous to this point - # see OListProcessor - if len(parent) and parent[-1].tag in self.LIST_TYPES: - self.parser.parseBlocks(parent[-1], [block]) - else: - # The parent is already a li. Just parse the child block. - self.parser.parseBlocks(parent, [block]) - elif sibling.tag in self.ITEM_TYPES: - # The sibling is a li. Use it as parent. - self.parser.parseBlocks(sibling, [block]) - elif len(sibling) and sibling[-1].tag in self.ITEM_TYPES: - # The parent is a list (``ol`` or ``ul``) which has children. - # Assume the last child li is the parent of this block. - if sibling[-1].text: - # If the parent li has text, that text needs to be moved to a p - # The p must be 'inserted' at beginning of list in the event - # that other children already exist i.e.; a nested sublist. - p = util.etree.Element('p') - p.text = sibling[-1].text - sibling[-1].text = '' - sibling[-1].insert(0, p) - self.parser.parseChunk(sibling[-1], block) - else: - self.create_item(sibling, block) - self.parser.state.reset() - - def create_item(self, parent, block): - """ Create a new li and parse the block with it as the parent. """ - li = util.etree.SubElement(parent, 'li') - self.parser.parseBlocks(li, [block]) - - def get_level(self, parent, block): - """ Get level of indent based on list level. """ - # Get indent level - m = self.INDENT_RE.match(block) - if m: - indent_level = len(m.group(1))/self.tab_length - else: - indent_level = 0 - if self.parser.state.isstate('list'): - # We're in a tightlist - so we already are at correct parent. - level = 1 - else: - # We're in a looselist - so we need to find parent. - level = 0 - # Step through children of tree to find matching indent level. - while indent_level > level: - child = self.lastChild(parent) - if child is not None and (child.tag in self.LIST_TYPES or child.tag in self.ITEM_TYPES): - if child.tag in self.LIST_TYPES: - level += 1 - parent = child - else: - # No more child levels. If we're short of indent_level, - # we have a code block. So we stop here. - break - return level, parent - - -class CodeBlockProcessor(BlockProcessor): - """ Process code blocks. """ - - def test(self, parent, block): - return block.startswith(' '*self.tab_length) - - def run(self, parent, blocks): - sibling = self.lastChild(parent) - block = blocks.pop(0) - theRest = '' - if sibling is not None and sibling.tag == "pre" and len(sibling) \ - and sibling[0].tag == "code": - # The previous block was a code block. As blank lines do not start - # new code blocks, append this block to the previous, adding back - # linebreaks removed from the split into a list. - code = sibling[0] - block, theRest = self.detab(block) - code.text = util.AtomicString('%s\n%s\n' % (code.text, block.rstrip())) - else: - # This is a new codeblock. Create the elements and insert text. - pre = util.etree.SubElement(parent, 'pre') - code = util.etree.SubElement(pre, 'code') - block, theRest = self.detab(block) - code.text = util.AtomicString('%s\n' % block.rstrip()) - if theRest: - # This block contained unindented line(s) after the first indented - # line. Insert these lines as the first block of the master blocks - # list for future processing. - blocks.insert(0, theRest) - - -class BlockQuoteProcessor(BlockProcessor): - - RE = re.compile(r'(^|\n)[ ]{0,3}>[ ]?(.*)') - - def test(self, parent, block): - return bool(self.RE.search(block)) - - def run(self, parent, blocks): - block = blocks.pop(0) - m = self.RE.search(block) - if m: - before = block[:m.start()] # Lines before blockquote - # Pass lines before blockquote in recursively for parsing forst. - self.parser.parseBlocks(parent, [before]) - # Remove ``> `` from begining of each line. - block = '\n'.join([self.clean(line) for line in - block[m.start():].split('\n')]) - sibling = self.lastChild(parent) - if sibling is not None and sibling.tag == "blockquote": - # Previous block was a blockquote so set that as this blocks parent - quote = sibling - else: - # This is a new blockquote. Create a new parent element. - quote = util.etree.SubElement(parent, 'blockquote') - # Recursively parse block with blockquote as parent. - # change parser state so blockquotes embedded in lists use p tags - self.parser.state.set('blockquote') - self.parser.parseChunk(quote, block) - self.parser.state.reset() - - def clean(self, line): - """ Remove ``>`` from beginning of a line. """ - m = self.RE.match(line) - if line.strip() == ">": - return "" - elif m: - return m.group(2) - else: - return line - -class OListProcessor(BlockProcessor): - """ Process ordered list blocks. """ - - TAG = 'ol' - # Detect an item (``1. item``). ``group(1)`` contains contents of item. - RE = re.compile(r'^[ ]{0,3}\d+\.[ ]+(.*)') - # Detect items on secondary lines. they can be of either list type. - CHILD_RE = re.compile(r'^[ ]{0,3}((\d+\.)|[*+-])[ ]+(.*)') - # Detect indented (nested) items of either type - INDENT_RE = re.compile(r'^[ ]{4,7}((\d+\.)|[*+-])[ ]+.*') - # The integer (python string) with which the lists starts (default=1) - # Eg: If list is intialized as) - # 3. Item - # The ol tag will get starts="3" attribute - STARTSWITH = '1' - # List of allowed sibling tags. - SIBLING_TAGS = ['ol', 'ul'] - - def test(self, parent, block): - return bool(self.RE.match(block)) - - def run(self, parent, blocks): - # Check fr multiple items in one block. - items = self.get_items(blocks.pop(0)) - sibling = self.lastChild(parent) - - if sibling is not None and sibling.tag in self.SIBLING_TAGS: - # Previous block was a list item, so set that as parent - lst = sibling - # make sure previous item is in a p- if the item has text, then it - # it isn't in a p - if lst[-1].text: - # since it's possible there are other children for this sibling, - # we can't just SubElement the p, we need to insert it as the - # first item - p = util.etree.Element('p') - p.text = lst[-1].text - lst[-1].text = '' - lst[-1].insert(0, p) - # if the last item has a tail, then the tail needs to be put in a p - # likely only when a header is not followed by a blank line - lch = self.lastChild(lst[-1]) - if lch is not None and lch.tail: - p = util.etree.SubElement(lst[-1], 'p') - p.text = lch.tail.lstrip() - lch.tail = '' - - # parse first block differently as it gets wrapped in a p. - li = util.etree.SubElement(lst, 'li') - self.parser.state.set('looselist') - firstitem = items.pop(0) - self.parser.parseBlocks(li, [firstitem]) - self.parser.state.reset() - elif parent.tag in ['ol', 'ul']: - # this catches the edge case of a multi-item indented list whose - # first item is in a blank parent-list item: - # * * subitem1 - # * subitem2 - # see also ListIndentProcessor - lst = parent - else: - # This is a new list so create parent with appropriate tag. - lst = util.etree.SubElement(parent, self.TAG) - # Check if a custom start integer is set - if not self.parser.markdown.lazy_ol and self.STARTSWITH !='1': - lst.attrib['start'] = self.STARTSWITH - - self.parser.state.set('list') - # Loop through items in block, recursively parsing each with the - # appropriate parent. - for item in items: - if item.startswith(' '*self.tab_length): - # Item is indented. Parse with last item as parent - self.parser.parseBlocks(lst[-1], [item]) - else: - # New item. Create li and parse with it as parent - li = util.etree.SubElement(lst, 'li') - self.parser.parseBlocks(li, [item]) - self.parser.state.reset() - - def get_items(self, block): - """ Break a block into list items. """ - items = [] - for line in block.split('\n'): - m = self.CHILD_RE.match(line) - if m: - # This is a new list item - # Check first item for the start index - if not items and self.TAG=='ol': - # Detect the integer value of first list item - INTEGER_RE = re.compile('(\d+)') - self.STARTSWITH = INTEGER_RE.match(m.group(1)).group() - # Append to the list - items.append(m.group(3)) - elif self.INDENT_RE.match(line): - # This is an indented (possibly nested) item. - if items[-1].startswith(' '*self.tab_length): - # Previous item was indented. Append to that item. - items[-1] = '%s\n%s' % (items[-1], line) - else: - items.append(line) - else: - # This is another line of previous item. Append to that item. - items[-1] = '%s\n%s' % (items[-1], line) - return items - - -class UListProcessor(OListProcessor): - """ Process unordered list blocks. """ - - TAG = 'ul' - RE = re.compile(r'^[ ]{0,3}[*+-][ ]+(.*)') - - -class HashHeaderProcessor(BlockProcessor): - """ Process Hash Headers. """ - - # Detect a header at start of any line in block - RE = re.compile(r'(^|\n)(?P#{1,6})(?P
.*?)#*(\n|$)') - - def test(self, parent, block): - return bool(self.RE.search(block)) - - def run(self, parent, blocks): - block = blocks.pop(0) - m = self.RE.search(block) - if m: - before = block[:m.start()] # All lines before header - after = block[m.end():] # All lines after header - if before: - # As the header was not the first line of the block and the - # lines before the header must be parsed first, - # recursively parse this lines as a block. - self.parser.parseBlocks(parent, [before]) - # Create header using named groups from RE - h = util.etree.SubElement(parent, 'h%d' % len(m.group('level'))) - h.text = m.group('header').strip() - if after: - # Insert remaining lines as first block for future parsing. - blocks.insert(0, after) - else: - # This should never happen, but just in case... - logger.warn("We've got a problem header: %r" % block) - - -class SetextHeaderProcessor(BlockProcessor): - """ Process Setext-style Headers. """ - - # Detect Setext-style header. Must be first 2 lines of block. - RE = re.compile(r'^.*?\n[=-]+[ ]*(\n|$)', re.MULTILINE) - - def test(self, parent, block): - return bool(self.RE.match(block)) - - def run(self, parent, blocks): - lines = blocks.pop(0).split('\n') - # Determine level. ``=`` is 1 and ``-`` is 2. - if lines[1].startswith('='): - level = 1 - else: - level = 2 - h = util.etree.SubElement(parent, 'h%d' % level) - h.text = lines[0].strip() - if len(lines) > 2: - # Block contains additional lines. Add to master blocks for later. - blocks.insert(0, '\n'.join(lines[2:])) - - -class HRProcessor(BlockProcessor): - """ Process Horizontal Rules. """ - - RE = r'^[ ]{0,3}((-+[ ]{0,2}){3,}|(_+[ ]{0,2}){3,}|(\*+[ ]{0,2}){3,})[ ]*' - # Detect hr on any line of a block. - SEARCH_RE = re.compile(RE, re.MULTILINE) - - def test(self, parent, block): - m = self.SEARCH_RE.search(block) - # No atomic grouping in python so we simulate it here for performance. - # The regex only matches what would be in the atomic group - the HR. - # Then check if we are at end of block or if next char is a newline. - if m and (m.end() == len(block) or block[m.end()] == '\n'): - # Save match object on class instance so we can use it later. - self.match = m - return True - return False - - def run(self, parent, blocks): - block = blocks.pop(0) - # Check for lines in block before hr. - prelines = block[:self.match.start()].rstrip('\n') - if prelines: - # Recursively parse lines before hr so they get parsed first. - self.parser.parseBlocks(parent, [prelines]) - # create hr - util.etree.SubElement(parent, 'hr') - # check for lines in block after hr. - postlines = block[self.match.end():].lstrip('\n') - if postlines: - # Add lines after hr to master blocks for later parsing. - blocks.insert(0, postlines) - - - -class EmptyBlockProcessor(BlockProcessor): - """ Process blocks that are empty or start with an empty line. """ - - def test(self, parent, block): - return not block or block.startswith('\n') - - def run(self, parent, blocks): - block = blocks.pop(0) - filler = '\n\n' - if block: - # Starts with empty line - # Only replace a single line. - filler = '\n' - # Save the rest for later. - theRest = block[1:] - if theRest: - # Add remaining lines to master blocks for later. - blocks.insert(0, theRest) - sibling = self.lastChild(parent) - if sibling is not None and sibling.tag == 'pre' and len(sibling) and sibling[0].tag == 'code': - # Last block is a codeblock. Append to preserve whitespace. - sibling[0].text = util.AtomicString('%s%s' % (sibling[0].text, filler)) - - -class ParagraphProcessor(BlockProcessor): - """ Process Paragraph blocks. """ - - def test(self, parent, block): - return True - - def run(self, parent, blocks): - block = blocks.pop(0) - if block.strip(): - # Not a blank block. Add to parent, otherwise throw it away. - if self.parser.state.isstate('list'): - # The parent is a tight-list. - # - # Check for any children. This will likely only happen in a - # tight-list when a header isn't followed by a blank line. - # For example: - # - # * # Header - # Line 2 of list item - not part of header. - sibling = self.lastChild(parent) - if sibling is not None: - # Insetrt after sibling. - if sibling.tail: - sibling.tail = '%s\n%s' % (sibling.tail, block) - else: - sibling.tail = '\n%s' % block - else: - # Append to parent.text - if parent.text: - parent.text = '%s\n%s' % (parent.text, block) - else: - parent.text = block.lstrip() - else: - # Create a regular paragraph - p = util.etree.SubElement(parent, 'p') - p.text = block.lstrip() diff --git a/awx/lib/site-packages/markdown/extensions/__init__.py b/awx/lib/site-packages/markdown/extensions/__init__.py deleted file mode 100644 index 184c4d1b1d..0000000000 --- a/awx/lib/site-packages/markdown/extensions/__init__.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Extensions ------------------------------------------------------------------------------ -""" - -from __future__ import unicode_literals - -class Extension(object): - """ Base class for extensions to subclass. """ - def __init__(self, configs = {}): - """Create an instance of an Extention. - - Keyword arguments: - - * configs: A dict of configuration setting used by an Extension. - """ - self.config = configs - - def getConfig(self, key, default=''): - """ Return a setting for the given key or an empty string. """ - if key in self.config: - return self.config[key][0] - else: - return default - - def getConfigs(self): - """ Return all configs settings as a dict. """ - return dict([(key, self.getConfig(key)) for key in self.config.keys()]) - - def getConfigInfo(self): - """ Return all config descriptions as a list of tuples. """ - return [(key, self.config[key][1]) for key in self.config.keys()] - - def setConfig(self, key, value): - """ Set a config setting for `key` with the given `value`. """ - self.config[key][0] = value - - def extendMarkdown(self, md, md_globals): - """ - Add the various proccesors and patterns to the Markdown Instance. - - This method must be overriden by every extension. - - Keyword arguments: - - * md: The Markdown instance. - - * md_globals: Global variables in the markdown module namespace. - - """ - raise NotImplementedError('Extension "%s.%s" must define an "extendMarkdown"' \ - 'method.' % (self.__class__.__module__, self.__class__.__name__)) - diff --git a/awx/lib/site-packages/markdown/extensions/abbr.py b/awx/lib/site-packages/markdown/extensions/abbr.py deleted file mode 100644 index 3f8a443585..0000000000 --- a/awx/lib/site-packages/markdown/extensions/abbr.py +++ /dev/null @@ -1,96 +0,0 @@ -''' -Abbreviation Extension for Python-Markdown -========================================== - -This extension adds abbreviation handling to Python-Markdown. - -Simple Usage: - - >>> import markdown - >>> text = """ - ... Some text with an ABBR and a REF. Ignore REFERENCE and ref. - ... - ... *[ABBR]: Abbreviation - ... *[REF]: Abbreviation Reference - ... """ - >>> print markdown.markdown(text, ['abbr']) -

Some text with an ABBR and a REF. Ignore REFERENCE and ref.

- -Copyright 2007-2008 -* [Waylan Limberg](http://achinghead.com/) -* [Seemant Kulleen](http://www.kulleen.org/) - - -''' - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..preprocessors import Preprocessor -from ..inlinepatterns import Pattern -from ..util import etree, AtomicString -import re - -# Global Vars -ABBR_REF_RE = re.compile(r'[*]\[(?P[^\]]*)\][ ]?:\s*(?P.*)') - -class AbbrExtension(Extension): - """ Abbreviation Extension for Python-Markdown. """ - - def extendMarkdown(self, md, md_globals): - """ Insert AbbrPreprocessor before ReferencePreprocessor. """ - md.preprocessors.add('abbr', AbbrPreprocessor(md), '<reference') - - -class AbbrPreprocessor(Preprocessor): - """ Abbreviation Preprocessor - parse text for abbr references. """ - - def run(self, lines): - ''' - Find and remove all Abbreviation references from the text. - Each reference is set as a new AbbrPattern in the markdown instance. - - ''' - new_text = [] - for line in lines: - m = ABBR_REF_RE.match(line) - if m: - abbr = m.group('abbr').strip() - title = m.group('title').strip() - self.markdown.inlinePatterns['abbr-%s'%abbr] = \ - AbbrPattern(self._generate_pattern(abbr), title) - else: - new_text.append(line) - return new_text - - def _generate_pattern(self, text): - ''' - Given a string, returns an regex pattern to match that string. - - 'HTML' -> r'(?P<abbr>[H][T][M][L])' - - Note: we force each char as a literal match (in brackets) as we don't - know what they will be beforehand. - - ''' - chars = list(text) - for i in range(len(chars)): - chars[i] = r'[%s]' % chars[i] - return r'(?P<abbr>\b%s\b)' % (r''.join(chars)) - - -class AbbrPattern(Pattern): - """ Abbreviation inline pattern. """ - - def __init__(self, pattern, title): - super(AbbrPattern, self).__init__(pattern) - self.title = title - - def handleMatch(self, m): - abbr = etree.Element('abbr') - abbr.text = AtomicString(m.group('abbr')) - abbr.set('title', self.title) - return abbr - -def makeExtension(configs=None): - return AbbrExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/admonition.py b/awx/lib/site-packages/markdown/extensions/admonition.py deleted file mode 100644 index 9a45b9249c..0000000000 --- a/awx/lib/site-packages/markdown/extensions/admonition.py +++ /dev/null @@ -1,118 +0,0 @@ -""" -Admonition extension for Python-Markdown -======================================== - -Adds rST-style admonitions. Inspired by [rST][] feature with the same name. - -The syntax is (followed by an indented block with the contents): - !!! [type] [optional explicit title] - -Where `type` is used as a CSS class name of the div. If not present, `title` -defaults to the capitalized `type`, so "note" -> "Note". - -rST suggests the following `types`, but you're free to use whatever you want: - attention, caution, danger, error, hint, important, note, tip, warning - - -A simple example: - !!! note - This is the first line inside the box. - -Outputs: - <div class="admonition note"> - <p class="admonition-title">Note</p> - <p>This is the first line inside the box</p> - </div> - -You can also specify the title and CSS class of the admonition: - !!! custom "Did you know?" - Another line here. - -Outputs: - <div class="admonition custom"> - <p class="admonition-title">Did you know?</p> - <p>Another line here.</p> - </div> - -[rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions - -By [Tiago Serafim](http://www.tiagoserafim.com/). - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..blockprocessors import BlockProcessor -from ..util import etree -import re - - -class AdmonitionExtension(Extension): - """ Admonition extension for Python-Markdown. """ - - def extendMarkdown(self, md, md_globals): - """ Add Admonition to Markdown instance. """ - md.registerExtension(self) - - md.parser.blockprocessors.add('admonition', - AdmonitionProcessor(md.parser), - '_begin') - - -class AdmonitionProcessor(BlockProcessor): - - CLASSNAME = 'admonition' - CLASSNAME_TITLE = 'admonition-title' - RE = re.compile(r'(?:^|\n)!!!\ ?([\w\-]+)(?:\ "(.*?)")?') - - def test(self, parent, block): - sibling = self.lastChild(parent) - return self.RE.search(block) or \ - (block.startswith(' ' * self.tab_length) and sibling and \ - sibling.get('class', '').find(self.CLASSNAME) != -1) - - def run(self, parent, blocks): - sibling = self.lastChild(parent) - block = blocks.pop(0) - m = self.RE.search(block) - - if m: - block = block[m.end() + 1:] # removes the first line - - block, theRest = self.detab(block) - - if m: - klass, title = self.get_class_and_title(m) - div = etree.SubElement(parent, 'div') - div.set('class', '%s %s' % (self.CLASSNAME, klass)) - if title: - p = etree.SubElement(div, 'p') - p.text = title - p.set('class', self.CLASSNAME_TITLE) - else: - div = sibling - - self.parser.parseChunk(div, block) - - if theRest: - # This block contained unindented line(s) after the first indented - # line. Insert these lines as the first block of the master blocks - # list for future processing. - blocks.insert(0, theRest) - - def get_class_and_title(self, match): - klass, title = match.group(1).lower(), match.group(2) - if title is None: - # no title was provided, use the capitalized classname as title - # e.g.: `!!! note` will render `<p class="admonition-title">Note</p>` - title = klass.capitalize() - elif title == '': - # an explicit blank title should not be rendered - # e.g.: `!!! warning ""` will *not* render `p` with a title - title = None - return klass, title - - -def makeExtension(configs={}): - return AdmonitionExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/attr_list.py b/awx/lib/site-packages/markdown/extensions/attr_list.py deleted file mode 100644 index 8b65f5661d..0000000000 --- a/awx/lib/site-packages/markdown/extensions/attr_list.py +++ /dev/null @@ -1,168 +0,0 @@ -""" -Attribute List Extension for Python-Markdown -============================================ - -Adds attribute list syntax. Inspired by -[maruku](http://maruku.rubyforge.org/proposal.html#attribute_lists)'s -feature of the same name. - -Copyright 2011 [Waylan Limberg](http://achinghead.com/). - -Contact: markdown@freewisdom.org - -License: BSD (see ../LICENSE.md for details) - -Dependencies: -* [Python 2.4+](http://python.org) -* [Markdown 2.1+](http://packages.python.org/Markdown/) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..treeprocessors import Treeprocessor -from ..util import isBlockLevel -import re - -try: - Scanner = re.Scanner -except AttributeError: - # must be on Python 2.4 - from sre import Scanner - -def _handle_double_quote(s, t): - k, v = t.split('=') - return k, v.strip('"') - -def _handle_single_quote(s, t): - k, v = t.split('=') - return k, v.strip("'") - -def _handle_key_value(s, t): - return t.split('=') - -def _handle_word(s, t): - if t.startswith('.'): - return '.', t[1:] - if t.startswith('#'): - return 'id', t[1:] - return t, t - -_scanner = Scanner([ - (r'[^ ]+=".*?"', _handle_double_quote), - (r"[^ ]+='.*?'", _handle_single_quote), - (r'[^ ]+=[^ ]*', _handle_key_value), - (r'[^ ]+', _handle_word), - (r' ', None) -]) - -def get_attrs(str): - """ Parse attribute list and return a list of attribute tuples. """ - return _scanner.scan(str)[0] - -def isheader(elem): - return elem.tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] - -class AttrListTreeprocessor(Treeprocessor): - - BASE_RE = r'\{\:?([^\}]*)\}' - HEADER_RE = re.compile(r'[ ]+%s[ ]*$' % BASE_RE) - BLOCK_RE = re.compile(r'\n[ ]*%s[ ]*$' % BASE_RE) - INLINE_RE = re.compile(r'^%s' % BASE_RE) - NAME_RE = re.compile(r'[^A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d' - r'\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef' - r'\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd' - r'\:\-\.0-9\u00b7\u0300-\u036f\u203f-\u2040]+') - - def run(self, doc): - for elem in doc.getiterator(): - if isBlockLevel(elem.tag): - # Block level: check for attrs on last line of text - RE = self.BLOCK_RE - if isheader(elem) or elem.tag == 'dt': - # header or def-term: check for attrs at end of line - RE = self.HEADER_RE - if len(elem) and elem.tag == 'li': - # special case list items. children may include a ul or ol. - pos = None - # find the ul or ol position - for i, child in enumerate(elem): - if child.tag in ['ul', 'ol']: - pos = i - break - if pos is None and elem[-1].tail: - # use tail of last child. no ul or ol. - m = RE.search(elem[-1].tail) - if m: - self.assign_attrs(elem, m.group(1)) - elem[-1].tail = elem[-1].tail[:m.start()] - elif pos is not None and pos > 0 and elem[pos-1].tail: - # use tail of last child before ul or ol - m = RE.search(elem[pos-1].tail) - if m: - self.assign_attrs(elem, m.group(1)) - elem[pos-1].tail = elem[pos-1].tail[:m.start()] - elif elem.text: - # use text. ul is first child. - m = RE.search(elem.text) - if m: - self.assign_attrs(elem, m.group(1)) - elem.text = elem.text[:m.start()] - elif len(elem) and elem[-1].tail: - # has children. Get from tail of last child - m = RE.search(elem[-1].tail) - if m: - self.assign_attrs(elem, m.group(1)) - elem[-1].tail = elem[-1].tail[:m.start()] - if isheader(elem): - # clean up trailing #s - elem[-1].tail = elem[-1].tail.rstrip('#').rstrip() - elif elem.text: - # no children. Get from text. - m = RE.search(elem.text) - if not m and elem.tag == 'td': - m = re.search(self.BASE_RE, elem.text) - if m: - self.assign_attrs(elem, m.group(1)) - elem.text = elem.text[:m.start()] - if isheader(elem): - # clean up trailing #s - elem.text = elem.text.rstrip('#').rstrip() - else: - # inline: check for attrs at start of tail - if elem.tail: - m = self.INLINE_RE.match(elem.tail) - if m: - self.assign_attrs(elem, m.group(1)) - elem.tail = elem.tail[m.end():] - - def assign_attrs(self, elem, attrs): - """ Assign attrs to element. """ - for k, v in get_attrs(attrs): - if k == '.': - # add to class - cls = elem.get('class') - if cls: - elem.set('class', '%s %s' % (cls, v)) - else: - elem.set('class', v) - else: - # assign attr k with v - elem.set(self.sanitize_name(k), v) - - def sanitize_name(self, name): - """ - Sanitize name as 'an XML Name, minus the ":"'. - See http://www.w3.org/TR/REC-xml-names/#NT-NCName - """ - return self.NAME_RE.sub('_', name) - - -class AttrListExtension(Extension): - def extendMarkdown(self, md, md_globals): - md.treeprocessors.add('attr_list', AttrListTreeprocessor(md), '>prettify') - - -def makeExtension(configs={}): - return AttrListExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/codehilite.py b/awx/lib/site-packages/markdown/extensions/codehilite.py deleted file mode 100644 index 428bd0cb2b..0000000000 --- a/awx/lib/site-packages/markdown/extensions/codehilite.py +++ /dev/null @@ -1,268 +0,0 @@ -""" -CodeHilite Extension for Python-Markdown -======================================== - -Adds code/syntax highlighting to standard Python-Markdown code blocks. - -Copyright 2006-2008 [Waylan Limberg](http://achinghead.com/). - -Project website: <http://packages.python.org/Markdown/extensions/code_hilite.html> -Contact: markdown@freewisdom.org - -License: BSD (see ../LICENSE.md for details) - -Dependencies: -* [Python 2.3+](http://python.org/) -* [Markdown 2.0+](http://packages.python.org/Markdown/) -* [Pygments](http://pygments.org/) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..treeprocessors import Treeprocessor -import warnings -try: - from pygments import highlight - from pygments.lexers import get_lexer_by_name, guess_lexer, TextLexer - from pygments.formatters import HtmlFormatter - pygments = True -except ImportError: - pygments = False - - -def parse_hl_lines(expr): - """Support our syntax for emphasizing certain lines of code. - - expr should be like '1 2' to emphasize lines 1 and 2 of a code block. - Returns a list of ints, the line numbers to emphasize. - """ - if not expr: - return [] - - try: - return list(map(int, expr.split())) - except ValueError: - return [] - - -# ------------------ The Main CodeHilite Class ---------------------- -class CodeHilite(object): - """ - Determine language of source code, and pass it into the pygments hilighter. - - Basic Usage: - >>> code = CodeHilite(src = 'some text') - >>> html = code.hilite() - - * src: Source string or any object with a .readline attribute. - - * linenums: (Boolean) Set line numbering to 'on' (True), 'off' (False) or 'auto'(None). - Set to 'auto' by default. - - * guess_lang: (Boolean) Turn language auto-detection 'on' or 'off' (on by default). - - * css_class: Set class name of wrapper div ('codehilite' by default). - - * hl_lines: (List of integers) Lines to emphasize, 1-indexed. - - Low Level Usage: - >>> code = CodeHilite() - >>> code.src = 'some text' # String or anything with a .readline attr. - >>> code.linenos = True # True or False; Turns line numbering on or of. - >>> html = code.hilite() - - """ - - def __init__(self, src=None, linenums=None, guess_lang=True, - css_class="codehilite", lang=None, style='default', - noclasses=False, tab_length=4, hl_lines=None): - self.src = src - self.lang = lang - self.linenums = linenums - self.guess_lang = guess_lang - self.css_class = css_class - self.style = style - self.noclasses = noclasses - self.tab_length = tab_length - self.hl_lines = hl_lines or [] - - def hilite(self): - """ - Pass code to the [Pygments](http://pygments.pocoo.org/) highliter with - optional line numbers. The output should then be styled with css to - your liking. No styles are applied by default - only styling hooks - (i.e.: <span class="k">). - - returns : A string of html. - - """ - - self.src = self.src.strip('\n') - - if self.lang is None: - self._parseHeader() - - if pygments: - try: - lexer = get_lexer_by_name(self.lang) - except ValueError: - try: - if self.guess_lang: - lexer = guess_lexer(self.src) - else: - lexer = TextLexer() - except ValueError: - lexer = TextLexer() - formatter = HtmlFormatter(linenos=self.linenums, - cssclass=self.css_class, - style=self.style, - noclasses=self.noclasses, - hl_lines=self.hl_lines) - return highlight(self.src, lexer, formatter) - else: - # just escape and build markup usable by JS highlighting libs - txt = self.src.replace('&', '&') - txt = txt.replace('<', '<') - txt = txt.replace('>', '>') - txt = txt.replace('"', '"') - classes = [] - if self.lang: - classes.append('language-%s' % self.lang) - if self.linenums: - classes.append('linenums') - class_str = '' - if classes: - class_str = ' class="%s"' % ' '.join(classes) - return '<pre class="%s"><code%s>%s</code></pre>\n'% \ - (self.css_class, class_str, txt) - - def _parseHeader(self): - """ - Determines language of a code block from shebang line and whether said - line should be removed or left in place. If the sheband line contains a - path (even a single /) then it is assumed to be a real shebang line and - left alone. However, if no path is given (e.i.: #!python or :::python) - then it is assumed to be a mock shebang for language identifitation of a - code fragment and removed from the code block prior to processing for - code highlighting. When a mock shebang (e.i: #!python) is found, line - numbering is turned on. When colons are found in place of a shebang - (e.i.: :::python), line numbering is left in the current state - off - by default. - - Also parses optional list of highlight lines, like: - - :::python hl_lines="1 3" - """ - - import re - - #split text into lines - lines = self.src.split("\n") - #pull first line to examine - fl = lines.pop(0) - - c = re.compile(r''' - (?:(?:^::+)|(?P<shebang>^[#]!)) # Shebang or 2 or more colons - (?P<path>(?:/\w+)*[/ ])? # Zero or 1 path - (?P<lang>[\w+-]*) # The language - \s* # Arbitrary whitespace - # Optional highlight lines, single- or double-quote-delimited - (hl_lines=(?P<quot>"|')(?P<hl_lines>.*?)(?P=quot))? - ''', re.VERBOSE) - # search first line for shebang - m = c.search(fl) - if m: - # we have a match - try: - self.lang = m.group('lang').lower() - except IndexError: - self.lang = None - if m.group('path'): - # path exists - restore first line - lines.insert(0, fl) - if self.linenums is None and m.group('shebang'): - # Overridable and Shebang exists - use line numbers - self.linenums = True - - self.hl_lines = parse_hl_lines(m.group('hl_lines')) - else: - # No match - lines.insert(0, fl) - - self.src = "\n".join(lines).strip("\n") - - - -# ------------------ The Markdown Extension ------------------------------- -class HiliteTreeprocessor(Treeprocessor): - """ Hilight source code in code blocks. """ - - def run(self, root): - """ Find code blocks and store in htmlStash. """ - blocks = root.getiterator('pre') - for block in blocks: - children = block.getchildren() - if len(children) == 1 and children[0].tag == 'code': - code = CodeHilite(children[0].text, - linenums=self.config['linenums'], - guess_lang=self.config['guess_lang'], - css_class=self.config['css_class'], - style=self.config['pygments_style'], - noclasses=self.config['noclasses'], - tab_length=self.markdown.tab_length) - placeholder = self.markdown.htmlStash.store(code.hilite(), - safe=True) - # Clear codeblock in etree instance - block.clear() - # Change to p element which will later - # be removed when inserting raw html - block.tag = 'p' - block.text = placeholder - - -class CodeHiliteExtension(Extension): - """ Add source code hilighting to markdown codeblocks. """ - - def __init__(self, configs): - # define default configs - self.config = { - 'linenums': [None, "Use lines numbers. True=yes, False=no, None=auto"], - 'force_linenos' : [False, "Depreciated! Use 'linenums' instead. Force line numbers - Default: False"], - 'guess_lang' : [True, "Automatic language detection - Default: True"], - 'css_class' : ["codehilite", - "Set class name for wrapper <div> - Default: codehilite"], - 'pygments_style' : ['default', 'Pygments HTML Formatter Style (Colorscheme) - Default: default'], - 'noclasses': [False, 'Use inline styles instead of CSS classes - Default false'] - } - - # Override defaults with user settings - for key, value in configs: - # convert strings to booleans - if value == 'True': value = True - if value == 'False': value = False - if value == 'None': value = None - - if key == 'force_linenos': - warnings.warn('The "force_linenos" config setting' - ' to the CodeHilite extension is deprecrecated.' - ' Use "linenums" instead.', DeprecationWarning) - if value: - # Carry 'force_linenos' over to new 'linenos'. - self.setConfig('linenums', True) - - self.setConfig(key, value) - - def extendMarkdown(self, md, md_globals): - """ Add HilitePostprocessor to Markdown instance. """ - hiliter = HiliteTreeprocessor(md) - hiliter.config = self.getConfigs() - md.treeprocessors.add("hilite", hiliter, "<inline") - - md.registerExtension(self) - - -def makeExtension(configs={}): - return CodeHiliteExtension(configs=configs) - diff --git a/awx/lib/site-packages/markdown/extensions/def_list.py b/awx/lib/site-packages/markdown/extensions/def_list.py deleted file mode 100644 index df639df931..0000000000 --- a/awx/lib/site-packages/markdown/extensions/def_list.py +++ /dev/null @@ -1,118 +0,0 @@ -""" -Definition List Extension for Python-Markdown -============================================= - -Added parsing of Definition Lists to Python-Markdown. - -A simple example: - - Apple - : Pomaceous fruit of plants of the genus Malus in - the family Rosaceae. - : An american computer company. - - Orange - : The fruit of an evergreen tree of the genus Citrus. - -Copyright 2008 - [Waylan Limberg](http://achinghead.com) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..blockprocessors import BlockProcessor, ListIndentProcessor -from ..util import etree -import re - - -class DefListProcessor(BlockProcessor): - """ Process Definition Lists. """ - - RE = re.compile(r'(^|\n)[ ]{0,3}:[ ]{1,3}(.*?)(\n|$)') - NO_INDENT_RE = re.compile(r'^[ ]{0,3}[^ :]') - - def test(self, parent, block): - return bool(self.RE.search(block)) - - def run(self, parent, blocks): - - raw_block = blocks.pop(0) - m = self.RE.search(raw_block) - terms = [l.strip() for l in raw_block[:m.start()].split('\n') if l.strip()] - block = raw_block[m.end():] - no_indent = self.NO_INDENT_RE.match(block) - if no_indent: - d, theRest = (block, None) - else: - d, theRest = self.detab(block) - if d: - d = '%s\n%s' % (m.group(2), d) - else: - d = m.group(2) - sibling = self.lastChild(parent) - if not terms and sibling is None: - # This is not a definition item. Most likely a paragraph that - # starts with a colon at the begining of a document or list. - blocks.insert(0, raw_block) - return False - if not terms and sibling.tag == 'p': - # The previous paragraph contains the terms - state = 'looselist' - terms = sibling.text.split('\n') - parent.remove(sibling) - # Aquire new sibling - sibling = self.lastChild(parent) - else: - state = 'list' - - if sibling and sibling.tag == 'dl': - # This is another item on an existing list - dl = sibling - if not terms and len(dl) and dl[-1].tag == 'dd' and len(dl[-1]): - state = 'looselist' - else: - # This is a new list - dl = etree.SubElement(parent, 'dl') - # Add terms - for term in terms: - dt = etree.SubElement(dl, 'dt') - dt.text = term - # Add definition - self.parser.state.set(state) - dd = etree.SubElement(dl, 'dd') - self.parser.parseBlocks(dd, [d]) - self.parser.state.reset() - - if theRest: - blocks.insert(0, theRest) - -class DefListIndentProcessor(ListIndentProcessor): - """ Process indented children of definition list items. """ - - ITEM_TYPES = ['dd'] - LIST_TYPES = ['dl'] - - def create_item(self, parent, block): - """ Create a new dd and parse the block with it as the parent. """ - dd = etree.SubElement(parent, 'dd') - self.parser.parseBlocks(dd, [block]) - - - -class DefListExtension(Extension): - """ Add definition lists to Markdown. """ - - def extendMarkdown(self, md, md_globals): - """ Add an instance of DefListProcessor to BlockParser. """ - md.parser.blockprocessors.add('defindent', - DefListIndentProcessor(md.parser), - '>indent') - md.parser.blockprocessors.add('deflist', - DefListProcessor(md.parser), - '>ulist') - - -def makeExtension(configs={}): - return DefListExtension(configs=configs) - diff --git a/awx/lib/site-packages/markdown/extensions/extra.py b/awx/lib/site-packages/markdown/extensions/extra.py deleted file mode 100644 index 8986ba683f..0000000000 --- a/awx/lib/site-packages/markdown/extensions/extra.py +++ /dev/null @@ -1,123 +0,0 @@ -""" -Python-Markdown Extra Extension -=============================== - -A compilation of various Python-Markdown extensions that imitates -[PHP Markdown Extra](http://michelf.com/projects/php-markdown/extra/). - -Note that each of the individual extensions still need to be available -on your PYTHONPATH. This extension simply wraps them all up as a -convenience so that only one extension needs to be listed when -initiating Markdown. See the documentation for each individual -extension for specifics about that extension. - -In the event that one or more of the supported extensions are not -available for import, Markdown will issue a warning and simply continue -without that extension. - -There may be additional extensions that are distributed with -Python-Markdown that are not included here in Extra. Those extensions -are not part of PHP Markdown Extra, and therefore, not part of -Python-Markdown Extra. If you really would like Extra to include -additional extensions, we suggest creating your own clone of Extra -under a differant name. You could also edit the `extensions` global -variable defined below, but be aware that such changes may be lost -when you upgrade to any future version of Python-Markdown. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..blockprocessors import BlockProcessor -from .. import util -import re - -extensions = ['smart_strong', - 'fenced_code', - 'footnotes', - 'attr_list', - 'def_list', - 'tables', - 'abbr', - ] - - -class ExtraExtension(Extension): - """ Add various extensions to Markdown class.""" - - def extendMarkdown(self, md, md_globals): - """ Register extension instances. """ - md.registerExtensions(extensions, self.config) - if not md.safeMode: - # Turn on processing of markdown text within raw html - md.preprocessors['html_block'].markdown_in_raw = True - md.parser.blockprocessors.add('markdown_block', - MarkdownInHtmlProcessor(md.parser), - '_begin') - md.parser.blockprocessors.tag_counter = -1 - md.parser.blockprocessors.contain_span_tags = re.compile( - r'^(p|h[1-6]|li|dd|dt|td|th|legend|address)$', re.IGNORECASE) - - -def makeExtension(configs={}): - return ExtraExtension(configs=dict(configs)) - - -class MarkdownInHtmlProcessor(BlockProcessor): - """Process Markdown Inside HTML Blocks.""" - def test(self, parent, block): - return block == util.TAG_PLACEHOLDER % \ - str(self.parser.blockprocessors.tag_counter + 1) - - def _process_nests(self, element, block): - """Process the element's child elements in self.run.""" - # Build list of indexes of each nest within the parent element. - nest_index = [] # a list of tuples: (left index, right index) - i = self.parser.blockprocessors.tag_counter + 1 - while len(self._tag_data) > i and self._tag_data[i]['left_index']: - left_child_index = self._tag_data[i]['left_index'] - right_child_index = self._tag_data[i]['right_index'] - nest_index.append((left_child_index - 1, right_child_index)) - i += 1 - - # Create each nest subelement. - for i, (left_index, right_index) in enumerate(nest_index[:-1]): - self.run(element, block[left_index:right_index], - block[right_index:nest_index[i + 1][0]], True) - self.run(element, block[nest_index[-1][0]:nest_index[-1][1]], # last - block[nest_index[-1][1]:], True) # nest - - def run(self, parent, blocks, tail=None, nest=False): - self._tag_data = self.parser.markdown.htmlStash.tag_data - - self.parser.blockprocessors.tag_counter += 1 - tag = self._tag_data[self.parser.blockprocessors.tag_counter] - - # Create Element - markdown_value = tag['attrs'].pop('markdown') - element = util.etree.SubElement(parent, tag['tag'], tag['attrs']) - - # Slice Off Block - if nest: - self.parser.parseBlocks(parent, tail) # Process Tail - block = blocks[1:] - else: # includes nests since a third level of nesting isn't supported - block = blocks[tag['left_index'] + 1: tag['right_index']] - del blocks[:tag['right_index']] - - # Process Text - if (self.parser.blockprocessors.contain_span_tags.match( # Span Mode - tag['tag']) and markdown_value != 'block') or \ - markdown_value == 'span': - element.text = '\n'.join(block) - else: # Block Mode - i = self.parser.blockprocessors.tag_counter + 1 - if len(self._tag_data) > i and self._tag_data[i]['left_index']: - first_subelement_index = self._tag_data[i]['left_index'] - 1 - self.parser.parseBlocks( - element, block[:first_subelement_index]) - if not nest: - block = self._process_nests(element, block) - else: - self.parser.parseBlocks(element, block) diff --git a/awx/lib/site-packages/markdown/extensions/fenced_code.py b/awx/lib/site-packages/markdown/extensions/fenced_code.py deleted file mode 100644 index d6e043c99b..0000000000 --- a/awx/lib/site-packages/markdown/extensions/fenced_code.py +++ /dev/null @@ -1,179 +0,0 @@ -""" -Fenced Code Extension for Python Markdown -========================================= - -This extension adds Fenced Code Blocks to Python-Markdown. - - >>> import markdown - >>> text = ''' - ... A paragraph before a fenced code block: - ... - ... ~~~ - ... Fenced code block - ... ~~~ - ... ''' - >>> html = markdown.markdown(text, extensions=['fenced_code']) - >>> print html - <p>A paragraph before a fenced code block:</p> - <pre><code>Fenced code block - </code></pre> - -Works with safe_mode also (we check this because we are using the HtmlStash): - - >>> print markdown.markdown(text, extensions=['fenced_code'], safe_mode='replace') - <p>A paragraph before a fenced code block:</p> - <pre><code>Fenced code block - </code></pre> - -Include tilde's in a code block and wrap with blank lines: - - >>> text = ''' - ... ~~~~~~~~ - ... - ... ~~~~ - ... ~~~~~~~~''' - >>> print markdown.markdown(text, extensions=['fenced_code']) - <pre><code> - ~~~~ - </code></pre> - -Language tags: - - >>> text = ''' - ... ~~~~{.python} - ... # Some python code - ... ~~~~''' - >>> print markdown.markdown(text, extensions=['fenced_code']) - <pre><code class="python"># Some python code - </code></pre> - -Optionally backticks instead of tildes as per how github's code block markdown is identified: - - >>> text = ''' - ... ````` - ... # Arbitrary code - ... ~~~~~ # these tildes will not close the block - ... `````''' - >>> print markdown.markdown(text, extensions=['fenced_code']) - <pre><code># Arbitrary code - ~~~~~ # these tildes will not close the block - </code></pre> - -If the codehighlite extension and Pygments are installed, lines can be highlighted: - - >>> text = ''' - ... ```hl_lines="1 3" - ... line 1 - ... line 2 - ... line 3 - ... ```''' - >>> print markdown.markdown(text, extensions=['codehilite', 'fenced_code']) - <pre><code><span class="hilight">line 1</span> - line 2 - <span class="hilight">line 3</span> - </code></pre> - -Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/). - -Project website: <http://packages.python.org/Markdown/extensions/fenced_code_blocks.html> -Contact: markdown@freewisdom.org - -License: BSD (see ../docs/LICENSE for details) - -Dependencies: -* [Python 2.4+](http://python.org) -* [Markdown 2.0+](http://packages.python.org/Markdown/) -* [Pygments (optional)](http://pygments.org) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..preprocessors import Preprocessor -from .codehilite import CodeHilite, CodeHiliteExtension, parse_hl_lines -import re - - -class FencedCodeExtension(Extension): - - def extendMarkdown(self, md, md_globals): - """ Add FencedBlockPreprocessor to the Markdown instance. """ - md.registerExtension(self) - - md.preprocessors.add('fenced_code_block', - FencedBlockPreprocessor(md), - ">normalize_whitespace") - - -class FencedBlockPreprocessor(Preprocessor): - FENCED_BLOCK_RE = re.compile(r''' -(?P<fence>^(?:~{3,}|`{3,}))[ ]* # Opening ``` or ~~~ -(\{?\.?(?P<lang>[a-zA-Z0-9_+-]*))?[ ]* # Optional {, and lang -# Optional highlight lines, single- or double-quote-delimited -(hl_lines=(?P<quot>"|')(?P<hl_lines>.*?)(?P=quot))?[ ]* -}?[ ]*\n # Optional closing } -(?P<code>.*?)(?<=\n) -(?P=fence)[ ]*$''', re.MULTILINE | re.DOTALL | re.VERBOSE) - CODE_WRAP = '<pre><code%s>%s</code></pre>' - LANG_TAG = ' class="%s"' - - def __init__(self, md): - super(FencedBlockPreprocessor, self).__init__(md) - - self.checked_for_codehilite = False - self.codehilite_conf = {} - - def run(self, lines): - """ Match and store Fenced Code Blocks in the HtmlStash. """ - - # Check for code hilite extension - if not self.checked_for_codehilite: - for ext in self.markdown.registeredExtensions: - if isinstance(ext, CodeHiliteExtension): - self.codehilite_conf = ext.config - break - - self.checked_for_codehilite = True - - text = "\n".join(lines) - while 1: - m = self.FENCED_BLOCK_RE.search(text) - if m: - lang = '' - if m.group('lang'): - lang = self.LANG_TAG % m.group('lang') - - # If config is not empty, then the codehighlite extension - # is enabled, so we call it to highlight the code - if self.codehilite_conf: - highliter = CodeHilite(m.group('code'), - linenums=self.codehilite_conf['linenums'][0], - guess_lang=self.codehilite_conf['guess_lang'][0], - css_class=self.codehilite_conf['css_class'][0], - style=self.codehilite_conf['pygments_style'][0], - lang=(m.group('lang') or None), - noclasses=self.codehilite_conf['noclasses'][0], - hl_lines=parse_hl_lines(m.group('hl_lines'))) - - code = highliter.hilite() - else: - code = self.CODE_WRAP % (lang, self._escape(m.group('code'))) - - placeholder = self.markdown.htmlStash.store(code, safe=True) - text = '%s\n%s\n%s'% (text[:m.start()], placeholder, text[m.end():]) - else: - break - return text.split("\n") - - def _escape(self, txt): - """ basic html escaping """ - txt = txt.replace('&', '&') - txt = txt.replace('<', '<') - txt = txt.replace('>', '>') - txt = txt.replace('"', '"') - return txt - - -def makeExtension(configs=None): - return FencedCodeExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/footnotes.py b/awx/lib/site-packages/markdown/extensions/footnotes.py deleted file mode 100644 index 9f93ad1b5d..0000000000 --- a/awx/lib/site-packages/markdown/extensions/footnotes.py +++ /dev/null @@ -1,315 +0,0 @@ -""" -========================= FOOTNOTES ================================= - -This section adds footnote handling to markdown. It can be used as -an example for extending python-markdown with relatively complex -functionality. While in this case the extension is included inside -the module itself, it could just as easily be added from outside the -module. Not that all markdown classes above are ignorant about -footnotes. All footnote functionality is provided separately and -then added to the markdown instance at the run time. - -Footnote functionality is attached by calling extendMarkdown() -method of FootnoteExtension. The method also registers the -extension to allow it's state to be reset by a call to reset() -method. - -Example: - Footnotes[^1] have a label[^label] and a definition[^!DEF]. - - [^1]: This is a footnote - [^label]: A footnote on "label" - [^!DEF]: The footnote for definition - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..preprocessors import Preprocessor -from ..inlinepatterns import Pattern -from ..treeprocessors import Treeprocessor -from ..postprocessors import Postprocessor -from ..util import etree, text_type -from ..odict import OrderedDict -import re - -FN_BACKLINK_TEXT = "zz1337820767766393qq" -NBSP_PLACEHOLDER = "qq3936677670287331zz" -DEF_RE = re.compile(r'[ ]{0,3}\[\^([^\]]*)\]:\s*(.*)') -TABBED_RE = re.compile(r'((\t)|( ))(.*)') - -class FootnoteExtension(Extension): - """ Footnote Extension. """ - - def __init__ (self, configs): - """ Setup configs. """ - self.config = {'PLACE_MARKER': - ["///Footnotes Go Here///", - "The text string that marks where the footnotes go"], - 'UNIQUE_IDS': - [False, - "Avoid name collisions across " - "multiple calls to reset()."], - "BACKLINK_TEXT": - ["↩", - "The text string that links from the footnote to the reader's place."] - } - - for key, value in configs: - self.config[key][0] = value - - # In multiple invocations, emit links that don't get tangled. - self.unique_prefix = 0 - - self.reset() - - def extendMarkdown(self, md, md_globals): - """ Add pieces to Markdown. """ - md.registerExtension(self) - self.parser = md.parser - self.md = md - # Insert a preprocessor before ReferencePreprocessor - md.preprocessors.add("footnote", FootnotePreprocessor(self), - "<reference") - # Insert an inline pattern before ImageReferencePattern - FOOTNOTE_RE = r'\[\^([^\]]*)\]' # blah blah [^1] blah - md.inlinePatterns.add("footnote", FootnotePattern(FOOTNOTE_RE, self), - "<reference") - # Insert a tree-processor that would actually add the footnote div - # This must be before all other treeprocessors (i.e., inline and - # codehilite) so they can run on the the contents of the div. - md.treeprocessors.add("footnote", FootnoteTreeprocessor(self), - "_begin") - # Insert a postprocessor after amp_substitute oricessor - md.postprocessors.add("footnote", FootnotePostprocessor(self), - ">amp_substitute") - - def reset(self): - """ Clear the footnotes on reset, and prepare for a distinct document. """ - self.footnotes = OrderedDict() - self.unique_prefix += 1 - - def findFootnotesPlaceholder(self, root): - """ Return ElementTree Element that contains Footnote placeholder. """ - def finder(element): - for child in element: - if child.text: - if child.text.find(self.getConfig("PLACE_MARKER")) > -1: - return child, element, True - if child.tail: - if child.tail.find(self.getConfig("PLACE_MARKER")) > -1: - return child, element, False - finder(child) - return None - - res = finder(root) - return res - - def setFootnote(self, id, text): - """ Store a footnote for later retrieval. """ - self.footnotes[id] = text - - def get_separator(self): - if self.md.output_format in ['html5', 'xhtml5']: - return '-' - return ':' - - def makeFootnoteId(self, id): - """ Return footnote link id. """ - if self.getConfig("UNIQUE_IDS"): - return 'fn%s%d-%s' % (self.get_separator(), self.unique_prefix, id) - else: - return 'fn%s%s' % (self.get_separator(), id) - - def makeFootnoteRefId(self, id): - """ Return footnote back-link id. """ - if self.getConfig("UNIQUE_IDS"): - return 'fnref%s%d-%s' % (self.get_separator(), self.unique_prefix, id) - else: - return 'fnref%s%s' % (self.get_separator(), id) - - def makeFootnotesDiv(self, root): - """ Return div of footnotes as et Element. """ - - if not list(self.footnotes.keys()): - return None - - div = etree.Element("div") - div.set('class', 'footnote') - etree.SubElement(div, "hr") - ol = etree.SubElement(div, "ol") - - for id in self.footnotes.keys(): - li = etree.SubElement(ol, "li") - li.set("id", self.makeFootnoteId(id)) - self.parser.parseChunk(li, self.footnotes[id]) - backlink = etree.Element("a") - backlink.set("href", "#" + self.makeFootnoteRefId(id)) - if self.md.output_format not in ['html5', 'xhtml5']: - backlink.set("rev", "footnote") # Invalid in HTML5 - backlink.set("class", "footnote-backref") - backlink.set("title", "Jump back to footnote %d in the text" % \ - (self.footnotes.index(id)+1)) - backlink.text = FN_BACKLINK_TEXT - - if li.getchildren(): - node = li[-1] - if node.tag == "p": - node.text = node.text + NBSP_PLACEHOLDER - node.append(backlink) - else: - p = etree.SubElement(li, "p") - p.append(backlink) - return div - - -class FootnotePreprocessor(Preprocessor): - """ Find all footnote references and store for later use. """ - - def __init__ (self, footnotes): - self.footnotes = footnotes - - def run(self, lines): - """ - Loop through lines and find, set, and remove footnote definitions. - - Keywords: - - * lines: A list of lines of text - - Return: A list of lines of text with footnote definitions removed. - - """ - newlines = [] - i = 0 - while True: - m = DEF_RE.match(lines[i]) - if m: - fn, _i = self.detectTabbed(lines[i+1:]) - fn.insert(0, m.group(2)) - i += _i-1 # skip past footnote - self.footnotes.setFootnote(m.group(1), "\n".join(fn)) - else: - newlines.append(lines[i]) - if len(lines) > i+1: - i += 1 - else: - break - return newlines - - def detectTabbed(self, lines): - """ Find indented text and remove indent before further proccesing. - - Keyword arguments: - - * lines: an array of strings - - Returns: a list of post processed items and the index of last line. - - """ - items = [] - blank_line = False # have we encountered a blank line yet? - i = 0 # to keep track of where we are - - def detab(line): - match = TABBED_RE.match(line) - if match: - return match.group(4) - - for line in lines: - if line.strip(): # Non-blank line - detabbed_line = detab(line) - if detabbed_line: - items.append(detabbed_line) - i += 1 - continue - elif not blank_line and not DEF_RE.match(line): - # not tabbed but still part of first par. - items.append(line) - i += 1 - continue - else: - return items, i+1 - - else: # Blank line: _maybe_ we are done. - blank_line = True - i += 1 # advance - - # Find the next non-blank line - for j in range(i, len(lines)): - if lines[j].strip(): - next_line = lines[j]; break - else: - break # There is no more text; we are done. - - # Check if the next non-blank line is tabbed - if detab(next_line): # Yes, more work to do. - items.append("") - continue - else: - break # No, we are done. - else: - i += 1 - - return items, i - - -class FootnotePattern(Pattern): - """ InlinePattern for footnote markers in a document's body text. """ - - def __init__(self, pattern, footnotes): - super(FootnotePattern, self).__init__(pattern) - self.footnotes = footnotes - - def handleMatch(self, m): - id = m.group(2) - if id in self.footnotes.footnotes.keys(): - sup = etree.Element("sup") - a = etree.SubElement(sup, "a") - sup.set('id', self.footnotes.makeFootnoteRefId(id)) - a.set('href', '#' + self.footnotes.makeFootnoteId(id)) - if self.footnotes.md.output_format not in ['html5', 'xhtml5']: - a.set('rel', 'footnote') # invalid in HTML5 - a.set('class', 'footnote-ref') - a.text = text_type(self.footnotes.footnotes.index(id) + 1) - return sup - else: - return None - - -class FootnoteTreeprocessor(Treeprocessor): - """ Build and append footnote div to end of document. """ - - def __init__ (self, footnotes): - self.footnotes = footnotes - - def run(self, root): - footnotesDiv = self.footnotes.makeFootnotesDiv(root) - if footnotesDiv: - result = self.footnotes.findFootnotesPlaceholder(root) - if result: - child, parent, isText = result - ind = parent.getchildren().index(child) - if isText: - parent.remove(child) - parent.insert(ind, footnotesDiv) - else: - parent.insert(ind + 1, footnotesDiv) - child.tail = None - else: - root.append(footnotesDiv) - -class FootnotePostprocessor(Postprocessor): - """ Replace placeholders with html entities. """ - def __init__(self, footnotes): - self.footnotes = footnotes - - def run(self, text): - text = text.replace(FN_BACKLINK_TEXT, self.footnotes.getConfig("BACKLINK_TEXT")) - return text.replace(NBSP_PLACEHOLDER, " ") - -def makeExtension(configs=[]): - """ Return an instance of the FootnoteExtension """ - return FootnoteExtension(configs=configs) - diff --git a/awx/lib/site-packages/markdown/extensions/headerid.py b/awx/lib/site-packages/markdown/extensions/headerid.py deleted file mode 100644 index 8221fe1d52..0000000000 --- a/awx/lib/site-packages/markdown/extensions/headerid.py +++ /dev/null @@ -1,208 +0,0 @@ -""" -HeaderID Extension for Python-Markdown -====================================== - -Auto-generate id attributes for HTML headers. - -Basic usage: - - >>> import markdown - >>> text = "# Some Header #" - >>> md = markdown.markdown(text, ['headerid']) - >>> print md - <h1 id="some-header">Some Header</h1> - -All header IDs are unique: - - >>> text = ''' - ... #Header - ... #Header - ... #Header''' - >>> md = markdown.markdown(text, ['headerid']) - >>> print md - <h1 id="header">Header</h1> - <h1 id="header_1">Header</h1> - <h1 id="header_2">Header</h1> - -To fit within a html template's hierarchy, set the header base level: - - >>> text = ''' - ... #Some Header - ... ## Next Level''' - >>> md = markdown.markdown(text, ['headerid(level=3)']) - >>> print md - <h3 id="some-header">Some Header</h3> - <h4 id="next-level">Next Level</h4> - -Works with inline markup. - - >>> text = '#Some *Header* with [markup](http://example.com).' - >>> md = markdown.markdown(text, ['headerid']) - >>> print md - <h1 id="some-header-with-markup">Some <em>Header</em> with <a href="http://example.com">markup</a>.</h1> - -Turn off auto generated IDs: - - >>> text = ''' - ... # Some Header - ... # Another Header''' - >>> md = markdown.markdown(text, ['headerid(forceid=False)']) - >>> print md - <h1>Some Header</h1> - <h1>Another Header</h1> - -Use with MetaData extension: - - >>> text = '''header_level: 2 - ... header_forceid: Off - ... - ... # A Header''' - >>> md = markdown.markdown(text, ['headerid', 'meta']) - >>> print md - <h2>A Header</h2> - -Copyright 2007-2011 [Waylan Limberg](http://achinghead.com/). - -Project website: <http://packages.python.org/Markdown/extensions/header_id.html> -Contact: markdown@freewisdom.org - -License: BSD (see ../docs/LICENSE for details) - -Dependencies: -* [Python 2.3+](http://python.org) -* [Markdown 2.0+](http://packages.python.org/Markdown/) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..treeprocessors import Treeprocessor -from ..util import HTML_PLACEHOLDER_RE, parseBoolValue -import re -import logging -import unicodedata - -logger = logging.getLogger('MARKDOWN') - -IDCOUNT_RE = re.compile(r'^(.*)_([0-9]+)$') - - -def slugify(value, separator): - """ Slugify a string, to make it URL friendly. """ - value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') - value = re.sub('[^\w\s-]', '', value.decode('ascii')).strip().lower() - return re.sub('[%s\s]+' % separator, separator, value) - - -def unique(id, ids): - """ Ensure id is unique in set of ids. Append '_1', '_2'... if not """ - while id in ids or not id: - m = IDCOUNT_RE.match(id) - if m: - id = '%s_%d'% (m.group(1), int(m.group(2))+1) - else: - id = '%s_%d'% (id, 1) - ids.add(id) - return id - - -def itertext(elem): - """ Loop through all children and return text only. - - Reimplements method of same name added to ElementTree in Python 2.7 - - """ - if elem.text: - yield elem.text - for e in elem: - for s in itertext(e): - yield s - if e.tail: - yield e.tail - - -def stashedHTML2text(text, md): - """ Extract raw HTML, reduce to plain text and swap with placeholder. """ - def _html_sub(m): - """ Substitute raw html with plain text. """ - try: - raw, safe = md.htmlStash.rawHtmlBlocks[int(m.group(1))] - except (IndexError, TypeError): - return m.group(0) - if md.safeMode and not safe: - return '' - # Strip out tags and entities - leaveing text - return re.sub(r'(<[^>]+>)|(&[\#a-zA-Z0-9]+;)', '', raw) - - return HTML_PLACEHOLDER_RE.sub(_html_sub, text) - - -class HeaderIdTreeprocessor(Treeprocessor): - """ Assign IDs to headers. """ - - IDs = set() - - def run(self, doc): - start_level, force_id = self._get_meta() - slugify = self.config['slugify'] - sep = self.config['separator'] - for elem in doc.getiterator(): - if elem.tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']: - if force_id: - if "id" in elem.attrib: - id = elem.get('id') - else: - id = stashedHTML2text(''.join(itertext(elem)), self.md) - id = slugify(id, sep) - elem.set('id', unique(id, self.IDs)) - if start_level: - level = int(elem.tag[-1]) + start_level - if level > 6: - level = 6 - elem.tag = 'h%d' % level - - - def _get_meta(self): - """ Return meta data suported by this ext as a tuple """ - level = int(self.config['level']) - 1 - force = parseBoolValue(self.config['forceid']) - if hasattr(self.md, 'Meta'): - if 'header_level' in self.md.Meta: - level = int(self.md.Meta['header_level'][0]) - 1 - if 'header_forceid' in self.md.Meta: - force = parseBoolValue(self.md.Meta['header_forceid'][0]) - return level, force - - -class HeaderIdExtension(Extension): - def __init__(self, configs): - # set defaults - self.config = { - 'level' : ['1', 'Base level for headers.'], - 'forceid' : ['True', 'Force all headers to have an id.'], - 'separator' : ['-', 'Word separator.'], - 'slugify' : [slugify, 'Callable to generate anchors'], - } - - for key, value in configs: - self.setConfig(key, value) - - def extendMarkdown(self, md, md_globals): - md.registerExtension(self) - self.processor = HeaderIdTreeprocessor() - self.processor.md = md - self.processor.config = self.getConfigs() - if 'attr_list' in md.treeprocessors.keys(): - # insert after attr_list treeprocessor - md.treeprocessors.add('headerid', self.processor, '>attr_list') - else: - # insert after 'prettify' treeprocessor. - md.treeprocessors.add('headerid', self.processor, '>prettify') - - def reset(self): - self.processor.IDs = set() - - -def makeExtension(configs=None): - return HeaderIdExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/meta.py b/awx/lib/site-packages/markdown/extensions/meta.py deleted file mode 100644 index c4a4b210f9..0000000000 --- a/awx/lib/site-packages/markdown/extensions/meta.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -Meta Data Extension for Python-Markdown -======================================= - -This extension adds Meta Data handling to markdown. - -Basic Usage: - - >>> import markdown - >>> text = '''Title: A Test Doc. - ... Author: Waylan Limberg - ... John Doe - ... Blank_Data: - ... - ... The body. This is paragraph one. - ... ''' - >>> md = markdown.Markdown(['meta']) - >>> print md.convert(text) - <p>The body. This is paragraph one.</p> - >>> print md.Meta - {u'blank_data': [u''], u'author': [u'Waylan Limberg', u'John Doe'], u'title': [u'A Test Doc.']} - -Make sure text without Meta Data still works (markdown < 1.6b returns a <p>). - - >>> text = ' Some Code - not extra lines of meta data.' - >>> md = markdown.Markdown(['meta']) - >>> print md.convert(text) - <pre><code>Some Code - not extra lines of meta data. - </code></pre> - >>> md.Meta - {} - -Copyright 2007-2008 [Waylan Limberg](http://achinghead.com). - -Project website: <http://packages.python.org/Markdown/meta_data.html> -Contact: markdown@freewisdom.org - -License: BSD (see ../LICENSE.md for details) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..preprocessors import Preprocessor -import re - -# Global Vars -META_RE = re.compile(r'^[ ]{0,3}(?P<key>[A-Za-z0-9_-]+):\s*(?P<value>.*)') -META_MORE_RE = re.compile(r'^[ ]{4,}(?P<value>.*)') - -class MetaExtension (Extension): - """ Meta-Data extension for Python-Markdown. """ - - def extendMarkdown(self, md, md_globals): - """ Add MetaPreprocessor to Markdown instance. """ - - md.preprocessors.add("meta", MetaPreprocessor(md), "_begin") - - -class MetaPreprocessor(Preprocessor): - """ Get Meta-Data. """ - - def run(self, lines): - """ Parse Meta-Data and store in Markdown.Meta. """ - meta = {} - key = None - while lines: - line = lines.pop(0) - if line.strip() == '': - break # blank line - done - m1 = META_RE.match(line) - if m1: - key = m1.group('key').lower().strip() - value = m1.group('value').strip() - try: - meta[key].append(value) - except KeyError: - meta[key] = [value] - else: - m2 = META_MORE_RE.match(line) - if m2 and key: - # Add another line to existing key - meta[key].append(m2.group('value').strip()) - else: - lines.insert(0, line) - break # no meta data - done - self.markdown.Meta = meta - return lines - - -def makeExtension(configs={}): - return MetaExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/nl2br.py b/awx/lib/site-packages/markdown/extensions/nl2br.py deleted file mode 100644 index da4b339958..0000000000 --- a/awx/lib/site-packages/markdown/extensions/nl2br.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -NL2BR Extension -=============== - -A Python-Markdown extension to treat newlines as hard breaks; like -GitHub-flavored Markdown does. - -Usage: - - >>> import markdown - >>> print markdown.markdown('line 1\\nline 2', extensions=['nl2br']) - <p>line 1<br /> - line 2</p> - -Copyright 2011 [Brian Neal](http://deathofagremmie.com/) - -Dependencies: -* [Python 2.4+](http://python.org) -* [Markdown 2.1+](http://packages.python.org/Markdown/) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..inlinepatterns import SubstituteTagPattern - -BR_RE = r'\n' - -class Nl2BrExtension(Extension): - - def extendMarkdown(self, md, md_globals): - br_tag = SubstituteTagPattern(BR_RE, 'br') - md.inlinePatterns.add('nl', br_tag, '_end') - - -def makeExtension(configs=None): - return Nl2BrExtension(configs) diff --git a/awx/lib/site-packages/markdown/extensions/sane_lists.py b/awx/lib/site-packages/markdown/extensions/sane_lists.py deleted file mode 100644 index fda663828e..0000000000 --- a/awx/lib/site-packages/markdown/extensions/sane_lists.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Sane List Extension for Python-Markdown -======================================= - -Modify the behavior of Lists in Python-Markdown t act in a sane manor. - -In standard Markdown syntax, the following would constitute a single -ordered list. However, with this extension, the output would include -two lists, the first an ordered list and the second and unordered list. - - 1. ordered - 2. list - - * unordered - * list - -Copyright 2011 - [Waylan Limberg](http://achinghead.com) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..blockprocessors import OListProcessor, UListProcessor -import re - - -class SaneOListProcessor(OListProcessor): - - CHILD_RE = re.compile(r'^[ ]{0,3}((\d+\.))[ ]+(.*)') - SIBLING_TAGS = ['ol'] - - -class SaneUListProcessor(UListProcessor): - - CHILD_RE = re.compile(r'^[ ]{0,3}(([*+-]))[ ]+(.*)') - SIBLING_TAGS = ['ul'] - - -class SaneListExtension(Extension): - """ Add sane lists to Markdown. """ - - def extendMarkdown(self, md, md_globals): - """ Override existing Processors. """ - md.parser.blockprocessors['olist'] = SaneOListProcessor(md.parser) - md.parser.blockprocessors['ulist'] = SaneUListProcessor(md.parser) - - -def makeExtension(configs={}): - return SaneListExtension(configs=configs) - diff --git a/awx/lib/site-packages/markdown/extensions/smart_strong.py b/awx/lib/site-packages/markdown/extensions/smart_strong.py deleted file mode 100644 index 4818cf9ea8..0000000000 --- a/awx/lib/site-packages/markdown/extensions/smart_strong.py +++ /dev/null @@ -1,42 +0,0 @@ -''' -Smart_Strong Extension for Python-Markdown -========================================== - -This extention adds smarter handling of double underscores within words. - -Simple Usage: - - >>> import markdown - >>> print markdown.markdown('Text with double__underscore__words.', - ... extensions=['smart_strong']) - <p>Text with double__underscore__words.</p> - >>> print markdown.markdown('__Strong__ still works.', - ... extensions=['smart_strong']) - <p><strong>Strong</strong> still works.</p> - >>> print markdown.markdown('__this__works__too__.', - ... extensions=['smart_strong']) - <p><strong>this__works__too</strong>.</p> - -Copyright 2011 -[Waylan Limberg](http://achinghead.com) - -''' - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..inlinepatterns import SimpleTagPattern - -SMART_STRONG_RE = r'(?<!\w)(_{2})(?!_)(.+?)(?<!_)\2(?!\w)' -STRONG_RE = r'(\*{2})(.+?)\2' - -class SmartEmphasisExtension(Extension): - """ Add smart_emphasis extension to Markdown class.""" - - def extendMarkdown(self, md, md_globals): - """ Modify inline patterns. """ - md.inlinePatterns['strong'] = SimpleTagPattern(STRONG_RE, 'strong') - md.inlinePatterns.add('strong2', SimpleTagPattern(SMART_STRONG_RE, 'strong'), '>emphasis2') - -def makeExtension(configs={}): - return SmartEmphasisExtension(configs=dict(configs)) diff --git a/awx/lib/site-packages/markdown/extensions/smarty.py b/awx/lib/site-packages/markdown/extensions/smarty.py deleted file mode 100644 index 2f946f8294..0000000000 --- a/awx/lib/site-packages/markdown/extensions/smarty.py +++ /dev/null @@ -1,191 +0,0 @@ -# -*- coding: utf-8 -*- -# Smarty extension for Python-Markdown -# Author: 2013, Dmitry Shachnev <mitya57@gmail.com> - -# SmartyPants license: -# -# Copyright (c) 2003 John Gruber <http://daringfireball.net/> -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# * Neither the name "SmartyPants" nor the names of its contributors -# may be used to endorse or promote products derived from this -# software without specific prior written permission. -# -# This software is provided by the copyright holders and contributors "as -# is" and any express or implied warranties, including, but not limited -# to, the implied warranties of merchantability and fitness for a -# particular purpose are disclaimed. In no event shall the copyright -# owner or contributors be liable for any direct, indirect, incidental, -# special, exemplary, or consequential damages (including, but not -# limited to, procurement of substitute goods or services; loss of use, -# data, or profits; or business interruption) however caused and on any -# theory of liability, whether in contract, strict liability, or tort -# (including negligence or otherwise) arising in any way out of the use -# of this software, even if advised of the possibility of such damage. -# -# -# smartypants.py license: -# -# smartypants.py is a derivative work of SmartyPants. -# Copyright (c) 2004, 2007 Chad Miller <http://web.chad.org/> -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# This software is provided by the copyright holders and contributors "as -# is" and any express or implied warranties, including, but not limited -# to, the implied warranties of merchantability and fitness for a -# particular purpose are disclaimed. In no event shall the copyright -# owner or contributors be liable for any direct, indirect, incidental, -# special, exemplary, or consequential damages (including, but not -# limited to, procurement of substitute goods or services; loss of use, -# data, or profits; or business interruption) however caused and on any -# theory of liability, whether in contract, strict liability, or tort -# (including negligence or otherwise) arising in any way out of the use -# of this software, even if advised of the possibility of such damage. - -from __future__ import unicode_literals -from . import Extension -from ..inlinepatterns import HtmlPattern -from ..util import parseBoolValue - -# Constants for quote education. -punctClass = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]""" -endOfWordClass = r"[\s.,;:!?)]" -closeClass = "[^\ \t\r\n\[\{\(\-\u0002\u0003]" - -openingQuotesBase = ( - '(\s' # a whitespace char - '| ' # or a non-breaking space entity - '|--' # or dashes - '|–|—' # or unicode - '|&[mn]dash;' # or named dash entities - '|–|—' # or decimal entities - ')' -) - -# Special case if the very first character is a quote -# followed by punctuation at a non-word-break. Close the quotes by brute force: -singleQuoteStartRe = r"^'(?=%s\\B)" % punctClass -doubleQuoteStartRe = r'^"(?=%s\\B)' % punctClass - -# Special case for double sets of quotes, e.g.: -# <p>He said, "'Quoted' words in a larger quote."</p> -doubleQuoteSetsRe = r""""'(?=\w)""" -singleQuoteSetsRe = r"""'"(?=\w)""" - -# Get most opening double quotes: -openingDoubleQuotesRegex = r'%s"(?=\w)' % openingQuotesBase - -# Double closing quotes: -closingDoubleQuotesRegex = r'"(?=\s)' -closingDoubleQuotesRegex2 = '(?<=%s)"' % closeClass - -# Get most opening single quotes: -openingSingleQuotesRegex = r"%s'(?=\w)" % openingQuotesBase - -# Single closing quotes: -closingSingleQuotesRegex = r"(?<=%s)'(?!\s|s\b|\d)" % closeClass -closingSingleQuotesRegex2 = r"(?<=%s)'(\s|s\b)" % closeClass - -# All remaining quotes should be opening ones -remainingSingleQuotesRegex = "'" -remainingDoubleQuotesRegex = '"' - -lsquo, rsquo, ldquo, rdquo = '‘', '’', '“', '”' - -class SubstituteTextPattern(HtmlPattern): - def __init__(self, pattern, replace, markdown_instance): - """ Replaces matches with some text. """ - HtmlPattern.__init__(self, pattern) - self.replace = replace - self.markdown = markdown_instance - - def handleMatch(self, m): - result = '' - for part in self.replace: - if isinstance(part, int): - result += m.group(part) - else: - result += self.markdown.htmlStash.store(part, safe=True) - return result - -class SmartyExtension(Extension): - def __init__(self, configs): - self.config = { - 'smart_quotes': [True, 'Educate quotes'], - 'smart_dashes': [True, 'Educate dashes'], - 'smart_ellipses': [True, 'Educate ellipses'] - } - for key, value in configs: - self.setConfig(key, parseBoolValue(value)) - - def _addPatterns(self, md, patterns, serie): - for ind, pattern in enumerate(patterns): - pattern += (md,) - pattern = SubstituteTextPattern(*pattern) - after = ('>smarty-%s-%d' % (serie, ind - 1) if ind else '>entity') - name = 'smarty-%s-%d' % (serie, ind) - md.inlinePatterns.add(name, pattern, after) - - def educateDashes(self, md): - emDashesPattern = SubstituteTextPattern(r'(?<!-)---(?!-)', ('—',), md) - enDashesPattern = SubstituteTextPattern(r'(?<!-)--(?!-)', ('–',), md) - md.inlinePatterns.add('smarty-em-dashes', emDashesPattern, '>entity') - md.inlinePatterns.add('smarty-en-dashes', enDashesPattern, - '>smarty-em-dashes') - - def educateEllipses(self, md): - ellipsesPattern = SubstituteTextPattern(r'(?<!\.)\.{3}(?!\.)', ('…',), md) - md.inlinePatterns.add('smarty-ellipses', ellipsesPattern, '>entity') - - def educateQuotes(self, md): - patterns = ( - (singleQuoteStartRe, (rsquo,)), - (doubleQuoteStartRe, (rdquo,)), - (doubleQuoteSetsRe, (ldquo + lsquo,)), - (singleQuoteSetsRe, (lsquo + ldquo,)), - (openingSingleQuotesRegex, (2, lsquo)), - (closingSingleQuotesRegex, (rsquo,)), - (closingSingleQuotesRegex2, (rsquo, 2)), - (remainingSingleQuotesRegex, (lsquo,)), - (openingDoubleQuotesRegex, (2, ldquo)), - (closingDoubleQuotesRegex, (rdquo,)), - (closingDoubleQuotesRegex2, (rdquo,)), - (remainingDoubleQuotesRegex, (ldquo,)) - ) - self._addPatterns(md, patterns, 'quotes') - - def extendMarkdown(self, md, md_globals): - configs = self.getConfigs() - if configs['smart_quotes']: - self.educateQuotes(md) - if configs['smart_dashes']: - self.educateDashes(md) - if configs['smart_ellipses']: - self.educateEllipses(md) - md.ESCAPED_CHARS.extend(['"', "'"]) - -def makeExtension(configs=None): - return SmartyExtension(configs) diff --git a/awx/lib/site-packages/markdown/extensions/tables.py b/awx/lib/site-packages/markdown/extensions/tables.py deleted file mode 100644 index ad52ec11c7..0000000000 --- a/awx/lib/site-packages/markdown/extensions/tables.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -Tables Extension for Python-Markdown -==================================== - -Added parsing of tables to Python-Markdown. - -A simple example: - - First Header | Second Header - ------------- | ------------- - Content Cell | Content Cell - Content Cell | Content Cell - -Copyright 2009 - [Waylan Limberg](http://achinghead.com) -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..blockprocessors import BlockProcessor -from ..util import etree - -class TableProcessor(BlockProcessor): - """ Process Tables. """ - - def test(self, parent, block): - rows = block.split('\n') - return (len(rows) > 2 and '|' in rows[0] and - '|' in rows[1] and '-' in rows[1] and - rows[1].strip()[0] in ['|', ':', '-']) - - def run(self, parent, blocks): - """ Parse a table block and build table. """ - block = blocks.pop(0).split('\n') - header = block[0].strip() - seperator = block[1].strip() - rows = block[2:] - # Get format type (bordered by pipes or not) - border = False - if header.startswith('|'): - border = True - # Get alignment of columns - align = [] - for c in self._split_row(seperator, border): - if c.startswith(':') and c.endswith(':'): - align.append('center') - elif c.startswith(':'): - align.append('left') - elif c.endswith(':'): - align.append('right') - else: - align.append(None) - # Build table - table = etree.SubElement(parent, 'table') - thead = etree.SubElement(table, 'thead') - self._build_row(header, thead, align, border) - tbody = etree.SubElement(table, 'tbody') - for row in rows: - self._build_row(row.strip(), tbody, align, border) - - def _build_row(self, row, parent, align, border): - """ Given a row of text, build table cells. """ - tr = etree.SubElement(parent, 'tr') - tag = 'td' - if parent.tag == 'thead': - tag = 'th' - cells = self._split_row(row, border) - # We use align here rather than cells to ensure every row - # contains the same number of columns. - for i, a in enumerate(align): - c = etree.SubElement(tr, tag) - try: - c.text = cells[i].strip() - except IndexError: - c.text = "" - if a: - c.set('align', a) - - def _split_row(self, row, border): - """ split a row of text into list of cells. """ - if border: - if row.startswith('|'): - row = row[1:] - if row.endswith('|'): - row = row[:-1] - return row.split('|') - - -class TableExtension(Extension): - """ Add tables to Markdown. """ - - def extendMarkdown(self, md, md_globals): - """ Add an instance of TableProcessor to BlockParser. """ - md.parser.blockprocessors.add('table', - TableProcessor(md.parser), - '<hashheader') - - -def makeExtension(configs={}): - return TableExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/toc.py b/awx/lib/site-packages/markdown/extensions/toc.py deleted file mode 100644 index 89468d60c7..0000000000 --- a/awx/lib/site-packages/markdown/extensions/toc.py +++ /dev/null @@ -1,240 +0,0 @@ -""" -Table of Contents Extension for Python-Markdown -* * * - -(c) 2008 [Jack Miller](http://codezen.org) - -Dependencies: -* [Markdown 2.1+](http://packages.python.org/Markdown/) - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..treeprocessors import Treeprocessor -from ..util import etree, parseBoolValue, AMP_SUBSTITUTE -from .headerid import slugify, unique, itertext, stashedHTML2text -import re - - -def order_toc_list(toc_list): - """Given an unsorted list with errors and skips, return a nested one. - [{'level': 1}, {'level': 2}] - => - [{'level': 1, 'children': [{'level': 2, 'children': []}]}] - - A wrong list is also converted: - [{'level': 2}, {'level': 1}] - => - [{'level': 2, 'children': []}, {'level': 1, 'children': []}] - """ - - def build_correct(remaining_list, prev_elements=[{'level': 1000}]): - - if not remaining_list: - return [], [] - - current = remaining_list.pop(0) - if not 'children' in current.keys(): - current['children'] = [] - - if not prev_elements: - # This happens for instance with [8, 1, 1], ie. when some - # header level is outside a scope. We treat it as a - # top-level - next_elements, children = build_correct(remaining_list, [current]) - current['children'].append(children) - return [current] + next_elements, [] - - prev_element = prev_elements.pop() - children = [] - next_elements = [] - # Is current part of the child list or next list? - if current['level'] > prev_element['level']: - #print "%d is a child of %d" % (current['level'], prev_element['level']) - prev_elements.append(prev_element) - prev_elements.append(current) - prev_element['children'].append(current) - next_elements2, children2 = build_correct(remaining_list, prev_elements) - children += children2 - next_elements += next_elements2 - else: - #print "%d is ancestor of %d" % (current['level'], prev_element['level']) - if not prev_elements: - #print "No previous elements, so appending to the next set" - next_elements.append(current) - prev_elements = [current] - next_elements2, children2 = build_correct(remaining_list, prev_elements) - current['children'].extend(children2) - else: - #print "Previous elements, comparing to those first" - remaining_list.insert(0, current) - next_elements2, children2 = build_correct(remaining_list, prev_elements) - children.extend(children2) - next_elements += next_elements2 - - return next_elements, children - - ordered_list, __ = build_correct(toc_list) - return ordered_list - - -class TocTreeprocessor(Treeprocessor): - - # Iterator wrapper to get parent and child all at once - def iterparent(self, root): - for parent in root.getiterator(): - for child in parent: - yield parent, child - - def add_anchor(self, c, elem_id): #@ReservedAssignment - anchor = etree.Element("a") - anchor.text = c.text - anchor.attrib["href"] = "#" + elem_id - anchor.attrib["class"] = "toclink" - c.text = "" - for elem in c.getchildren(): - anchor.append(elem) - c.remove(elem) - c.append(anchor) - - def add_permalink(self, c, elem_id): - permalink = etree.Element("a") - permalink.text = ("%spara;" % AMP_SUBSTITUTE - if self.use_permalinks is True else self.use_permalinks) - permalink.attrib["href"] = "#" + elem_id - permalink.attrib["class"] = "headerlink" - permalink.attrib["title"] = "Permanent link" - c.append(permalink) - - def build_toc_etree(self, div, toc_list): - # Add title to the div - if self.config["title"]: - header = etree.SubElement(div, "span") - header.attrib["class"] = "toctitle" - header.text = self.config["title"] - - def build_etree_ul(toc_list, parent): - ul = etree.SubElement(parent, "ul") - for item in toc_list: - # List item link, to be inserted into the toc div - li = etree.SubElement(ul, "li") - link = etree.SubElement(li, "a") - link.text = item.get('name', '') - link.attrib["href"] = '#' + item.get('id', '') - if item['children']: - build_etree_ul(item['children'], li) - return ul - - return build_etree_ul(toc_list, div) - - def run(self, doc): - - div = etree.Element("div") - div.attrib["class"] = "toc" - header_rgx = re.compile("[Hh][123456]") - - self.use_anchors = parseBoolValue(self.config["anchorlink"]) - self.use_permalinks = parseBoolValue(self.config["permalink"], False) - if self.use_permalinks is None: - self.use_permalinks = self.config["permalink"] - - # Get a list of id attributes - used_ids = set() - for c in doc.getiterator(): - if "id" in c.attrib: - used_ids.add(c.attrib["id"]) - - toc_list = [] - marker_found = False - for (p, c) in self.iterparent(doc): - text = ''.join(itertext(c)).strip() - if not text: - continue - - # To keep the output from screwing up the - # validation by putting a <div> inside of a <p> - # we actually replace the <p> in its entirety. - # We do not allow the marker inside a header as that - # would causes an enless loop of placing a new TOC - # inside previously generated TOC. - if c.text and c.text.strip() == self.config["marker"] and \ - not header_rgx.match(c.tag) and c.tag not in ['pre', 'code']: - for i in range(len(p)): - if p[i] == c: - p[i] = div - break - marker_found = True - - if header_rgx.match(c.tag): - - # Do not override pre-existing ids - if not "id" in c.attrib: - elem_id = stashedHTML2text(text, self.markdown) - elem_id = unique(self.config["slugify"](elem_id, '-'), used_ids) - c.attrib["id"] = elem_id - else: - elem_id = c.attrib["id"] - - tag_level = int(c.tag[-1]) - - toc_list.append({'level': tag_level, - 'id': elem_id, - 'name': text}) - - if self.use_anchors: - self.add_anchor(c, elem_id) - if self.use_permalinks: - self.add_permalink(c, elem_id) - - toc_list_nested = order_toc_list(toc_list) - self.build_toc_etree(div, toc_list_nested) - prettify = self.markdown.treeprocessors.get('prettify') - if prettify: prettify.run(div) - if not marker_found: - # serialize and attach to markdown instance. - toc = self.markdown.serializer(div) - for pp in self.markdown.postprocessors.values(): - toc = pp.run(toc) - self.markdown.toc = toc - - -class TocExtension(Extension): - - TreeProcessorClass = TocTreeprocessor - - def __init__(self, configs=[]): - self.config = { "marker" : ["[TOC]", - "Text to find and replace with Table of Contents -" - "Defaults to \"[TOC]\""], - "slugify" : [slugify, - "Function to generate anchors based on header text-" - "Defaults to the headerid ext's slugify function."], - "title" : [None, - "Title to insert into TOC <div> - " - "Defaults to None"], - "anchorlink" : [0, - "1 if header should be a self link" - "Defaults to 0"], - "permalink" : [0, - "1 or link text if a Sphinx-style permalink should be added", - "Defaults to 0"] - } - - for key, value in configs: - self.setConfig(key, value) - - def extendMarkdown(self, md, md_globals): - tocext = self.TreeProcessorClass(md) - tocext.config = self.getConfigs() - # Headerid ext is set to '>prettify'. With this set to '_end', - # it should always come after headerid ext (and honor ids assinged - # by the header id extension) if both are used. Same goes for - # attr_list extension. This must come last because we don't want - # to redefine ids after toc is created. But we do want toc prettified. - md.treeprocessors.add("toc", tocext, "_end") - - -def makeExtension(configs={}): - return TocExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/extensions/wikilinks.py b/awx/lib/site-packages/markdown/extensions/wikilinks.py deleted file mode 100644 index ba1947c0b1..0000000000 --- a/awx/lib/site-packages/markdown/extensions/wikilinks.py +++ /dev/null @@ -1,151 +0,0 @@ -''' -WikiLinks Extension for Python-Markdown -====================================== - -Converts [[WikiLinks]] to relative links. Requires Python-Markdown 2.0+ - -Basic usage: - - >>> import markdown - >>> text = "Some text with a [[WikiLink]]." - >>> html = markdown.markdown(text, ['wikilinks']) - >>> print html - <p>Some text with a <a class="wikilink" href="/WikiLink/">WikiLink</a>.</p> - -Whitespace behavior: - - >>> print markdown.markdown('[[ foo bar_baz ]]', ['wikilinks']) - <p><a class="wikilink" href="/foo_bar_baz/">foo bar_baz</a></p> - >>> print markdown.markdown('foo [[ ]] bar', ['wikilinks']) - <p>foo bar</p> - -To define custom settings the simple way: - - >>> print markdown.markdown(text, - ... ['wikilinks(base_url=/wiki/,end_url=.html,html_class=foo)'] - ... ) - <p>Some text with a <a class="foo" href="/wiki/WikiLink.html">WikiLink</a>.</p> - -Custom settings the complex way: - - >>> md = markdown.Markdown( - ... extensions = ['wikilinks'], - ... extension_configs = {'wikilinks': [ - ... ('base_url', 'http://example.com/'), - ... ('end_url', '.html'), - ... ('html_class', '') ]}, - ... safe_mode = True) - >>> print md.convert(text) - <p>Some text with a <a href="http://example.com/WikiLink.html">WikiLink</a>.</p> - -Use MetaData with mdx_meta.py (Note the blank html_class in MetaData): - - >>> text = """wiki_base_url: http://example.com/ - ... wiki_end_url: .html - ... wiki_html_class: - ... - ... Some text with a [[WikiLink]].""" - >>> md = markdown.Markdown(extensions=['meta', 'wikilinks']) - >>> print md.convert(text) - <p>Some text with a <a href="http://example.com/WikiLink.html">WikiLink</a>.</p> - -MetaData should not carry over to next document: - - >>> print md.convert("No [[MetaData]] here.") - <p>No <a class="wikilink" href="/MetaData/">MetaData</a> here.</p> - -Define a custom URL builder: - - >>> def my_url_builder(label, base, end): - ... return '/bar/' - >>> md = markdown.Markdown(extensions=['wikilinks'], - ... extension_configs={'wikilinks' : [('build_url', my_url_builder)]}) - >>> print md.convert('[[foo]]') - <p><a class="wikilink" href="/bar/">foo</a></p> - -From the command line: - - python markdown.py -x wikilinks(base_url=http://example.com/,end_url=.html,html_class=foo) src.txt - -By [Waylan Limberg](http://achinghead.com/). - -License: [BSD](http://www.opensource.org/licenses/bsd-license.php) - -Dependencies: -* [Python 2.3+](http://python.org) -* [Markdown 2.0+](http://packages.python.org/Markdown/) -''' - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import Extension -from ..inlinepatterns import Pattern -from ..util import etree -import re - -def build_url(label, base, end): - """ Build a url from the label, a base, and an end. """ - clean_label = re.sub(r'([ ]+_)|(_[ ]+)|([ ]+)', '_', label) - return '%s%s%s'% (base, clean_label, end) - - -class WikiLinkExtension(Extension): - def __init__(self, configs): - # set extension defaults - self.config = { - 'base_url' : ['/', 'String to append to beginning or URL.'], - 'end_url' : ['/', 'String to append to end of URL.'], - 'html_class' : ['wikilink', 'CSS hook. Leave blank for none.'], - 'build_url' : [build_url, 'Callable formats URL from label.'], - } - configs = dict(configs) or {} - # Override defaults with user settings - for key, value in configs.items(): - self.setConfig(key, value) - - def extendMarkdown(self, md, md_globals): - self.md = md - - # append to end of inline patterns - WIKILINK_RE = r'\[\[([\w0-9_ -]+)\]\]' - wikilinkPattern = WikiLinks(WIKILINK_RE, self.getConfigs()) - wikilinkPattern.md = md - md.inlinePatterns.add('wikilink', wikilinkPattern, "<not_strong") - - -class WikiLinks(Pattern): - def __init__(self, pattern, config): - super(WikiLinks, self).__init__(pattern) - self.config = config - - def handleMatch(self, m): - if m.group(2).strip(): - base_url, end_url, html_class = self._getMeta() - label = m.group(2).strip() - url = self.config['build_url'](label, base_url, end_url) - a = etree.Element('a') - a.text = label - a.set('href', url) - if html_class: - a.set('class', html_class) - else: - a = '' - return a - - def _getMeta(self): - """ Return meta data or config data. """ - base_url = self.config['base_url'] - end_url = self.config['end_url'] - html_class = self.config['html_class'] - if hasattr(self.md, 'Meta'): - if 'wiki_base_url' in self.md.Meta: - base_url = self.md.Meta['wiki_base_url'][0] - if 'wiki_end_url' in self.md.Meta: - end_url = self.md.Meta['wiki_end_url'][0] - if 'wiki_html_class' in self.md.Meta: - html_class = self.md.Meta['wiki_html_class'][0] - return base_url, end_url, html_class - - -def makeExtension(configs=None) : - return WikiLinkExtension(configs=configs) diff --git a/awx/lib/site-packages/markdown/inlinepatterns.py b/awx/lib/site-packages/markdown/inlinepatterns.py deleted file mode 100644 index 9335748730..0000000000 --- a/awx/lib/site-packages/markdown/inlinepatterns.py +++ /dev/null @@ -1,482 +0,0 @@ -""" -INLINE PATTERNS -============================================================================= - -Inline patterns such as *emphasis* are handled by means of auxiliary -objects, one per pattern. Pattern objects must be instances of classes -that extend markdown.Pattern. Each pattern object uses a single regular -expression and needs support the following methods: - - pattern.getCompiledRegExp() # returns a regular expression - - pattern.handleMatch(m) # takes a match object and returns - # an ElementTree element or just plain text - -All of python markdown's built-in patterns subclass from Pattern, -but you can add additional patterns that don't. - -Also note that all the regular expressions used by inline must -capture the whole block. For this reason, they all start with -'^(.*)' and end with '(.*)!'. In case with built-in expression -Pattern takes care of adding the "^(.*)" and "(.*)!". - -Finally, the order in which regular expressions are applied is very -important - e.g. if we first replace http://.../ links with <a> tags -and _then_ try to replace inline html, we would end up with a mess. -So, we apply the expressions in the following order: - -* escape and backticks have to go before everything else, so - that we can preempt any markdown patterns by escaping them. - -* then we handle auto-links (must be done before inline html) - -* then we handle inline HTML. At this point we will simply - replace all inline HTML strings with a placeholder and add - the actual HTML to a hash. - -* then inline images (must be done before links) - -* then bracketed links, first regular then reference-style - -* finally we apply strong and emphasis -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import util -from . import odict -import re -try: - from urllib.parse import urlparse, urlunparse -except ImportError: - from urlparse import urlparse, urlunparse -try: - from html import entities -except ImportError: - import htmlentitydefs as entities - - -def build_inlinepatterns(md_instance, **kwargs): - """ Build the default set of inline patterns for Markdown. """ - inlinePatterns = odict.OrderedDict() - inlinePatterns["backtick"] = BacktickPattern(BACKTICK_RE) - inlinePatterns["escape"] = EscapePattern(ESCAPE_RE, md_instance) - inlinePatterns["reference"] = ReferencePattern(REFERENCE_RE, md_instance) - inlinePatterns["link"] = LinkPattern(LINK_RE, md_instance) - inlinePatterns["image_link"] = ImagePattern(IMAGE_LINK_RE, md_instance) - inlinePatterns["image_reference"] = \ - ImageReferencePattern(IMAGE_REFERENCE_RE, md_instance) - inlinePatterns["short_reference"] = \ - ReferencePattern(SHORT_REF_RE, md_instance) - inlinePatterns["autolink"] = AutolinkPattern(AUTOLINK_RE, md_instance) - inlinePatterns["automail"] = AutomailPattern(AUTOMAIL_RE, md_instance) - inlinePatterns["linebreak"] = SubstituteTagPattern(LINE_BREAK_RE, 'br') - if md_instance.safeMode != 'escape': - inlinePatterns["html"] = HtmlPattern(HTML_RE, md_instance) - inlinePatterns["entity"] = HtmlPattern(ENTITY_RE, md_instance) - inlinePatterns["not_strong"] = SimpleTextPattern(NOT_STRONG_RE) - inlinePatterns["strong_em"] = DoubleTagPattern(STRONG_EM_RE, 'strong,em') - inlinePatterns["strong"] = SimpleTagPattern(STRONG_RE, 'strong') - inlinePatterns["emphasis"] = SimpleTagPattern(EMPHASIS_RE, 'em') - if md_instance.smart_emphasis: - inlinePatterns["emphasis2"] = SimpleTagPattern(SMART_EMPHASIS_RE, 'em') - else: - inlinePatterns["emphasis2"] = SimpleTagPattern(EMPHASIS_2_RE, 'em') - return inlinePatterns - -""" -The actual regular expressions for patterns ------------------------------------------------------------------------------ -""" - -NOBRACKET = r'[^\]\[]*' -BRK = ( r'\[(' - + (NOBRACKET + r'(\[')*6 - + (NOBRACKET+ r'\])*')*6 - + NOBRACKET + r')\]' ) -NOIMG = r'(?<!\!)' - -BACKTICK_RE = r'(?<!\\)(`+)(.+?)(?<!`)\2(?!`)' # `e=f()` or ``e=f("`")`` -ESCAPE_RE = r'\\(.)' # \< -EMPHASIS_RE = r'(\*)([^\*]+)\2' # *emphasis* -STRONG_RE = r'(\*{2}|_{2})(.+?)\2' # **strong** -STRONG_EM_RE = r'(\*{3}|_{3})(.+?)\2' # ***strong*** -SMART_EMPHASIS_RE = r'(?<!\w)(_)(?!_)(.+?)(?<!_)\2(?!\w)' # _smart_emphasis_ -EMPHASIS_2_RE = r'(_)(.+?)\2' # _emphasis_ -LINK_RE = NOIMG + BRK + \ -r'''\(\s*(<.*?>|((?:(?:\(.*?\))|[^\(\)]))*?)\s*((['"])(.*?)\12\s*)?\)''' -# [text](url) or [text](<url>) or [text](url "title") - -IMAGE_LINK_RE = r'\!' + BRK + r'\s*\((<.*?>|([^")]+"[^"]*"|[^\)]*))\)' -# ![alttxt](http://x.com/) or ![alttxt](<http://x.com/>) -REFERENCE_RE = NOIMG + BRK+ r'\s?\[([^\]]*)\]' # [Google][3] -SHORT_REF_RE = NOIMG + r'\[([^\]]+)\]' # [Google] -IMAGE_REFERENCE_RE = r'\!' + BRK + '\s?\[([^\]]*)\]' # ![alt text][2] -NOT_STRONG_RE = r'((^| )(\*|_)( |$))' # stand-alone * or _ -AUTOLINK_RE = r'<((?:[Ff]|[Hh][Tt])[Tt][Pp][Ss]?://[^>]*)>' # <http://www.123.com> -AUTOMAIL_RE = r'<([^> \!]*@[^> ]*)>' # <me@example.com> - -HTML_RE = r'(\<([a-zA-Z/][^\>]*?|\!--.*?--)\>)' # <...> -ENTITY_RE = r'(&[\#a-zA-Z0-9]*;)' # & -LINE_BREAK_RE = r' \n' # two spaces at end of line - - -def dequote(string): - """Remove quotes from around a string.""" - if ( ( string.startswith('"') and string.endswith('"')) - or (string.startswith("'") and string.endswith("'")) ): - return string[1:-1] - else: - return string - -ATTR_RE = re.compile("\{@([^\}]*)=([^\}]*)}") # {@id=123} - -def handleAttributes(text, parent): - """Set values of an element based on attribute definitions ({@id=123}).""" - def attributeCallback(match): - parent.set(match.group(1), match.group(2).replace('\n', ' ')) - return ATTR_RE.sub(attributeCallback, text) - - -""" -The pattern classes ------------------------------------------------------------------------------ -""" - -class Pattern(object): - """Base class that inline patterns subclass. """ - - def __init__(self, pattern, markdown_instance=None): - """ - Create an instant of an inline pattern. - - Keyword arguments: - - * pattern: A regular expression that matches a pattern - - """ - self.pattern = pattern - self.compiled_re = re.compile("^(.*?)%s(.*?)$" % pattern, - re.DOTALL | re.UNICODE) - - # Api for Markdown to pass safe_mode into instance - self.safe_mode = False - if markdown_instance: - self.markdown = markdown_instance - - def getCompiledRegExp(self): - """ Return a compiled regular expression. """ - return self.compiled_re - - def handleMatch(self, m): - """Return a ElementTree element from the given match. - - Subclasses should override this method. - - Keyword arguments: - - * m: A re match object containing a match of the pattern. - - """ - pass - - def type(self): - """ Return class name, to define pattern type """ - return self.__class__.__name__ - - def unescape(self, text): - """ Return unescaped text given text with an inline placeholder. """ - try: - stash = self.markdown.treeprocessors['inline'].stashed_nodes - except KeyError: - return text - def itertext(el): - ' Reimplement Element.itertext for older python versions ' - tag = el.tag - if not isinstance(tag, util.string_type) and tag is not None: - return - if el.text: - yield el.text - for e in el: - for s in itertext(e): - yield s - if e.tail: - yield e.tail - def get_stash(m): - id = m.group(1) - if id in stash: - value = stash.get(id) - if isinstance(value, util.string_type): - return value - else: - # An etree Element - return text content only - return ''.join(itertext(value)) - return util.INLINE_PLACEHOLDER_RE.sub(get_stash, text) - - -class SimpleTextPattern(Pattern): - """ Return a simple text of group(2) of a Pattern. """ - def handleMatch(self, m): - text = m.group(2) - if text == util.INLINE_PLACEHOLDER_PREFIX: - return None - return text - - -class EscapePattern(Pattern): - """ Return an escaped character. """ - - def handleMatch(self, m): - char = m.group(2) - if char in self.markdown.ESCAPED_CHARS: - return '%s%s%s' % (util.STX, ord(char), util.ETX) - else: - return None - - -class SimpleTagPattern(Pattern): - """ - Return element of type `tag` with a text attribute of group(3) - of a Pattern. - - """ - def __init__ (self, pattern, tag): - Pattern.__init__(self, pattern) - self.tag = tag - - def handleMatch(self, m): - el = util.etree.Element(self.tag) - el.text = m.group(3) - return el - - -class SubstituteTagPattern(SimpleTagPattern): - """ Return an element of type `tag` with no children. """ - def handleMatch (self, m): - return util.etree.Element(self.tag) - - -class BacktickPattern(Pattern): - """ Return a `<code>` element containing the matching text. """ - def __init__ (self, pattern): - Pattern.__init__(self, pattern) - self.tag = "code" - - def handleMatch(self, m): - el = util.etree.Element(self.tag) - el.text = util.AtomicString(m.group(3).strip()) - return el - - -class DoubleTagPattern(SimpleTagPattern): - """Return a ElementTree element nested in tag2 nested in tag1. - - Useful for strong emphasis etc. - - """ - def handleMatch(self, m): - tag1, tag2 = self.tag.split(",") - el1 = util.etree.Element(tag1) - el2 = util.etree.SubElement(el1, tag2) - el2.text = m.group(3) - return el1 - - -class HtmlPattern(Pattern): - """ Store raw inline html and return a placeholder. """ - def handleMatch (self, m): - rawhtml = self.unescape(m.group(2)) - place_holder = self.markdown.htmlStash.store(rawhtml) - return place_holder - - def unescape(self, text): - """ Return unescaped text given text with an inline placeholder. """ - try: - stash = self.markdown.treeprocessors['inline'].stashed_nodes - except KeyError: - return text - def get_stash(m): - id = m.group(1) - value = stash.get(id) - if value is not None: - try: - return self.markdown.serializer(value) - except: - return '\%s' % value - - return util.INLINE_PLACEHOLDER_RE.sub(get_stash, text) - - -class LinkPattern(Pattern): - """ Return a link element from the given match. """ - def handleMatch(self, m): - el = util.etree.Element("a") - el.text = m.group(2) - title = m.group(13) - href = m.group(9) - - if href: - if href[0] == "<": - href = href[1:-1] - el.set("href", self.sanitize_url(self.unescape(href.strip()))) - else: - el.set("href", "") - - if title: - title = dequote(self.unescape(title)) - el.set("title", title) - return el - - def sanitize_url(self, url): - """ - Sanitize a url against xss attacks in "safe_mode". - - Rather than specifically blacklisting `javascript:alert("XSS")` and all - its aliases (see <http://ha.ckers.org/xss.html>), we whitelist known - safe url formats. Most urls contain a network location, however some - are known not to (i.e.: mailto links). Script urls do not contain a - location. Additionally, for `javascript:...`, the scheme would be - "javascript" but some aliases will appear to `urlparse()` to have no - scheme. On top of that relative links (i.e.: "foo/bar.html") have no - scheme. Therefore we must check "path", "parameters", "query" and - "fragment" for any literal colons. We don't check "scheme" for colons - because it *should* never have any and "netloc" must allow the form: - `username:password@host:port`. - - """ - if not self.markdown.safeMode: - # Return immediately bipassing parsing. - return url - - try: - scheme, netloc, path, params, query, fragment = url = urlparse(url) - except ValueError: - # Bad url - so bad it couldn't be parsed. - return '' - - locless_schemes = ['', 'mailto', 'news'] - allowed_schemes = locless_schemes + ['http', 'https', 'ftp', 'ftps'] - if scheme not in allowed_schemes: - # Not a known (allowed) scheme. Not safe. - return '' - - if netloc == '' and scheme not in locless_schemes: - # This should not happen. Treat as suspect. - return '' - - for part in url[2:]: - if ":" in part: - # A colon in "path", "parameters", "query" or "fragment" is suspect. - return '' - - # Url passes all tests. Return url as-is. - return urlunparse(url) - -class ImagePattern(LinkPattern): - """ Return a img element from the given match. """ - def handleMatch(self, m): - el = util.etree.Element("img") - src_parts = m.group(9).split() - if src_parts: - src = src_parts[0] - if src[0] == "<" and src[-1] == ">": - src = src[1:-1] - el.set('src', self.sanitize_url(self.unescape(src))) - else: - el.set('src', "") - if len(src_parts) > 1: - el.set('title', dequote(self.unescape(" ".join(src_parts[1:])))) - - if self.markdown.enable_attributes: - truealt = handleAttributes(m.group(2), el) - else: - truealt = m.group(2) - - el.set('alt', self.unescape(truealt)) - return el - -class ReferencePattern(LinkPattern): - """ Match to a stored reference and return link element. """ - - NEWLINE_CLEANUP_RE = re.compile(r'[ ]?\n', re.MULTILINE) - - def handleMatch(self, m): - try: - id = m.group(9).lower() - except IndexError: - id = None - if not id: - # if we got something like "[Google][]" or "[Goggle]" - # we'll use "google" as the id - id = m.group(2).lower() - - # Clean up linebreaks in id - id = self.NEWLINE_CLEANUP_RE.sub(' ', id) - if not id in self.markdown.references: # ignore undefined refs - return None - href, title = self.markdown.references[id] - - text = m.group(2) - return self.makeTag(href, title, text) - - def makeTag(self, href, title, text): - el = util.etree.Element('a') - - el.set('href', self.sanitize_url(href)) - if title: - el.set('title', title) - - el.text = text - return el - - -class ImageReferencePattern(ReferencePattern): - """ Match to a stored reference and return img element. """ - def makeTag(self, href, title, text): - el = util.etree.Element("img") - el.set("src", self.sanitize_url(href)) - if title: - el.set("title", title) - - if self.markdown.enable_attributes: - text = handleAttributes(text, el) - - el.set("alt", self.unescape(text)) - return el - - -class AutolinkPattern(Pattern): - """ Return a link Element given an autolink (`<http://example/com>`). """ - def handleMatch(self, m): - el = util.etree.Element("a") - el.set('href', self.unescape(m.group(2))) - el.text = util.AtomicString(m.group(2)) - return el - -class AutomailPattern(Pattern): - """ - Return a mailto link Element given an automail link (`<foo@example.com>`). - """ - def handleMatch(self, m): - el = util.etree.Element('a') - email = self.unescape(m.group(2)) - if email.startswith("mailto:"): - email = email[len("mailto:"):] - - def codepoint2name(code): - """Return entity definition by code, or the code if not defined.""" - entity = entities.codepoint2name.get(code) - if entity: - return "%s%s;" % (util.AMP_SUBSTITUTE, entity) - else: - return "%s#%d;" % (util.AMP_SUBSTITUTE, code) - - letters = [codepoint2name(ord(letter)) for letter in email] - el.text = util.AtomicString(''.join(letters)) - - mailto = "mailto:" + email - mailto = "".join([util.AMP_SUBSTITUTE + '#%d;' % - ord(letter) for letter in mailto]) - el.set('href', mailto) - return el - diff --git a/awx/lib/site-packages/markdown/odict.py b/awx/lib/site-packages/markdown/odict.py deleted file mode 100644 index 68c12593f7..0000000000 --- a/awx/lib/site-packages/markdown/odict.py +++ /dev/null @@ -1,189 +0,0 @@ -from __future__ import unicode_literals -from __future__ import absolute_import -from . import util - -from copy import deepcopy - -class OrderedDict(dict): - """ - A dictionary that keeps its keys in the order in which they're inserted. - - Copied from Django's SortedDict with some modifications. - - """ - def __new__(cls, *args, **kwargs): - instance = super(OrderedDict, cls).__new__(cls, *args, **kwargs) - instance.keyOrder = [] - return instance - - def __init__(self, data=None): - if data is None or isinstance(data, dict): - data = data or [] - super(OrderedDict, self).__init__(data) - self.keyOrder = list(data) if data else [] - else: - super(OrderedDict, self).__init__() - super_set = super(OrderedDict, self).__setitem__ - for key, value in data: - # Take the ordering from first key - if key not in self: - self.keyOrder.append(key) - # But override with last value in data (dict() does this) - super_set(key, value) - - def __deepcopy__(self, memo): - return self.__class__([(key, deepcopy(value, memo)) - for key, value in self.items()]) - - def __copy__(self): - # The Python's default copy implementation will alter the state - # of self. The reason for this seems complex but is likely related to - # subclassing dict. - return self.copy() - - def __setitem__(self, key, value): - if key not in self: - self.keyOrder.append(key) - super(OrderedDict, self).__setitem__(key, value) - - def __delitem__(self, key): - super(OrderedDict, self).__delitem__(key) - self.keyOrder.remove(key) - - def __iter__(self): - return iter(self.keyOrder) - - def __reversed__(self): - return reversed(self.keyOrder) - - def pop(self, k, *args): - result = super(OrderedDict, self).pop(k, *args) - try: - self.keyOrder.remove(k) - except ValueError: - # Key wasn't in the dictionary in the first place. No problem. - pass - return result - - def popitem(self): - result = super(OrderedDict, self).popitem() - self.keyOrder.remove(result[0]) - return result - - def _iteritems(self): - for key in self.keyOrder: - yield key, self[key] - - def _iterkeys(self): - for key in self.keyOrder: - yield key - - def _itervalues(self): - for key in self.keyOrder: - yield self[key] - - if util.PY3: - items = _iteritems - keys = _iterkeys - values = _itervalues - else: - iteritems = _iteritems - iterkeys = _iterkeys - itervalues = _itervalues - - def items(self): - return [(k, self[k]) for k in self.keyOrder] - - def keys(self): - return self.keyOrder[:] - - def values(self): - return [self[k] for k in self.keyOrder] - - def update(self, dict_): - for k in dict_: - self[k] = dict_[k] - - def setdefault(self, key, default): - if key not in self: - self.keyOrder.append(key) - return super(OrderedDict, self).setdefault(key, default) - - def value_for_index(self, index): - """Returns the value of the item at the given zero-based index.""" - return self[self.keyOrder[index]] - - def insert(self, index, key, value): - """Inserts the key, value pair before the item with the given index.""" - if key in self.keyOrder: - n = self.keyOrder.index(key) - del self.keyOrder[n] - if n < index: - index -= 1 - self.keyOrder.insert(index, key) - super(OrderedDict, self).__setitem__(key, value) - - def copy(self): - """Returns a copy of this object.""" - # This way of initializing the copy means it works for subclasses, too. - return self.__class__(self) - - def __repr__(self): - """ - Replaces the normal dict.__repr__ with a version that returns the keys - in their Ordered order. - """ - return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self._iteritems()]) - - def clear(self): - super(OrderedDict, self).clear() - self.keyOrder = [] - - def index(self, key): - """ Return the index of a given key. """ - try: - return self.keyOrder.index(key) - except ValueError: - raise ValueError("Element '%s' was not found in OrderedDict" % key) - - def index_for_location(self, location): - """ Return index or None for a given location. """ - if location == '_begin': - i = 0 - elif location == '_end': - i = None - elif location.startswith('<') or location.startswith('>'): - i = self.index(location[1:]) - if location.startswith('>'): - if i >= len(self): - # last item - i = None - else: - i += 1 - else: - raise ValueError('Not a valid location: "%s". Location key ' - 'must start with a ">" or "<".' % location) - return i - - def add(self, key, value, location): - """ Insert by key location. """ - i = self.index_for_location(location) - if i is not None: - self.insert(i, key, value) - else: - self.__setitem__(key, value) - - def link(self, key, location): - """ Change location of an existing item. """ - n = self.keyOrder.index(key) - del self.keyOrder[n] - try: - i = self.index_for_location(location) - if i is not None: - self.keyOrder.insert(i, key) - else: - self.keyOrder.append(key) - except Exception as e: - # restore to prevent data loss and reraise - self.keyOrder.insert(n, key) - raise e diff --git a/awx/lib/site-packages/markdown/postprocessors.py b/awx/lib/site-packages/markdown/postprocessors.py deleted file mode 100644 index 5f3f032c15..0000000000 --- a/awx/lib/site-packages/markdown/postprocessors.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -POST-PROCESSORS -============================================================================= - -Markdown also allows post-processors, which are similar to preprocessors in -that they need to implement a "run" method. However, they are run after core -processing. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import util -from . import odict -import re - - -def build_postprocessors(md_instance, **kwargs): - """ Build the default postprocessors for Markdown. """ - postprocessors = odict.OrderedDict() - postprocessors["raw_html"] = RawHtmlPostprocessor(md_instance) - postprocessors["amp_substitute"] = AndSubstitutePostprocessor() - postprocessors["unescape"] = UnescapePostprocessor() - return postprocessors - - -class Postprocessor(util.Processor): - """ - Postprocessors are run after the ElementTree it converted back into text. - - Each Postprocessor implements a "run" method that takes a pointer to a - text string, modifies it as necessary and returns a text string. - - Postprocessors must extend markdown.Postprocessor. - - """ - - def run(self, text): - """ - Subclasses of Postprocessor should implement a `run` method, which - takes the html document as a single text string and returns a - (possibly modified) string. - - """ - pass - - -class RawHtmlPostprocessor(Postprocessor): - """ Restore raw html to the document. """ - - def run(self, text): - """ Iterate over html stash and restore "safe" html. """ - for i in range(self.markdown.htmlStash.html_counter): - html, safe = self.markdown.htmlStash.rawHtmlBlocks[i] - if self.markdown.safeMode and not safe: - if str(self.markdown.safeMode).lower() == 'escape': - html = self.escape(html) - elif str(self.markdown.safeMode).lower() == 'remove': - html = '' - else: - html = self.markdown.html_replacement_text - if self.isblocklevel(html) and (safe or not self.markdown.safeMode): - text = text.replace("<p>%s</p>" % - (self.markdown.htmlStash.get_placeholder(i)), - html + "\n") - text = text.replace(self.markdown.htmlStash.get_placeholder(i), - html) - return text - - def escape(self, html): - """ Basic html escaping """ - html = html.replace('&', '&') - html = html.replace('<', '<') - html = html.replace('>', '>') - return html.replace('"', '"') - - def isblocklevel(self, html): - m = re.match(r'^\<\/?([^ >]+)', html) - if m: - if m.group(1)[0] in ('!', '?', '@', '%'): - # Comment, php etc... - return True - return util.isBlockLevel(m.group(1)) - return False - - -class AndSubstitutePostprocessor(Postprocessor): - """ Restore valid entities """ - - def run(self, text): - text = text.replace(util.AMP_SUBSTITUTE, "&") - return text - - -class UnescapePostprocessor(Postprocessor): - """ Restore escaped chars """ - - RE = re.compile('%s(\d+)%s' % (util.STX, util.ETX)) - - def unescape(self, m): - return util.int2str(int(m.group(1))) - - def run(self, text): - return self.RE.sub(self.unescape, text) diff --git a/awx/lib/site-packages/markdown/preprocessors.py b/awx/lib/site-packages/markdown/preprocessors.py deleted file mode 100644 index 5bfca55530..0000000000 --- a/awx/lib/site-packages/markdown/preprocessors.py +++ /dev/null @@ -1,341 +0,0 @@ -""" -PRE-PROCESSORS -============================================================================= - -Preprocessors work on source text before we start doing anything too -complicated. -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import util -from . import odict -import re - - -def build_preprocessors(md_instance, **kwargs): - """ Build the default set of preprocessors used by Markdown. """ - preprocessors = odict.OrderedDict() - preprocessors['normalize_whitespace'] = NormalizeWhitespace(md_instance) - if md_instance.safeMode != 'escape': - preprocessors["html_block"] = HtmlBlockPreprocessor(md_instance) - preprocessors["reference"] = ReferencePreprocessor(md_instance) - return preprocessors - - -class Preprocessor(util.Processor): - """ - Preprocessors are run after the text is broken into lines. - - Each preprocessor implements a "run" method that takes a pointer to a - list of lines of the document, modifies it as necessary and returns - either the same pointer or a pointer to a new list. - - Preprocessors must extend markdown.Preprocessor. - - """ - def run(self, lines): - """ - Each subclass of Preprocessor should override the `run` method, which - takes the document as a list of strings split by newlines and returns - the (possibly modified) list of lines. - - """ - pass - - -class NormalizeWhitespace(Preprocessor): - """ Normalize whitespace for consistant parsing. """ - - def run(self, lines): - source = '\n'.join(lines) - source = source.replace(util.STX, "").replace(util.ETX, "") - source = source.replace("\r\n", "\n").replace("\r", "\n") + "\n\n" - source = source.expandtabs(self.markdown.tab_length) - source = re.sub(r'(?<=\n) +\n', '\n', source) - return source.split('\n') - - -class HtmlBlockPreprocessor(Preprocessor): - """Remove html blocks from the text and store them for later retrieval.""" - - right_tag_patterns = ["</%s>", "%s>"] - attrs_pattern = r""" - \s+(?P<attr>[^>"'/= ]+)=(?P<q>['"])(?P<value>.*?)(?P=q) # attr="value" - | # OR - \s+(?P<attr1>[^>"'/= ]+)=(?P<value1>[^> ]+) # attr=value - | # OR - \s+(?P<attr2>[^>"'/= ]+) # attr - """ - left_tag_pattern = r'^\<(?P<tag>[^> ]+)(?P<attrs>(%s)*)\s*\/?\>?' % attrs_pattern - attrs_re = re.compile(attrs_pattern, re.VERBOSE) - left_tag_re = re.compile(left_tag_pattern, re.VERBOSE) - markdown_in_raw = False - - def _get_left_tag(self, block): - m = self.left_tag_re.match(block) - if m: - tag = m.group('tag') - raw_attrs = m.group('attrs') - attrs = {} - if raw_attrs: - for ma in self.attrs_re.finditer(raw_attrs): - if ma.group('attr'): - if ma.group('value'): - attrs[ma.group('attr').strip()] = ma.group('value') - else: - attrs[ma.group('attr').strip()] = "" - elif ma.group('attr1'): - if ma.group('value1'): - attrs[ma.group('attr1').strip()] = ma.group('value1') - else: - attrs[ma.group('attr1').strip()] = "" - elif ma.group('attr2'): - attrs[ma.group('attr2').strip()] = "" - return tag, len(m.group(0)), attrs - else: - tag = block[1:].split(">", 1)[0].lower() - return tag, len(tag)+2, {} - - def _recursive_tagfind(self, ltag, rtag, start_index, block): - while 1: - i = block.find(rtag, start_index) - if i == -1: - return -1 - j = block.find(ltag, start_index) - # if no ltag, or rtag found before another ltag, return index - if (j > i or j == -1): - return i + len(rtag) - # another ltag found before rtag, use end of ltag as starting - # point and search again - j = block.find('>', j) - start_index = self._recursive_tagfind(ltag, rtag, j + 1, block) - if start_index == -1: - # HTML potentially malformed- ltag has no corresponding - # rtag - return -1 - - def _get_right_tag(self, left_tag, left_index, block): - for p in self.right_tag_patterns: - tag = p % left_tag - i = self._recursive_tagfind("<%s" % left_tag, tag, left_index, block) - if i > 2: - return tag.lstrip("<").rstrip(">"), i - return block.rstrip()[-left_index:-1].lower(), len(block) - - def _equal_tags(self, left_tag, right_tag): - if left_tag[0] in ['?', '@', '%']: # handle PHP, etc. - return True - if ("/" + left_tag) == right_tag: - return True - if (right_tag == "--" and left_tag == "--"): - return True - elif left_tag == right_tag[1:] \ - and right_tag[0] == "/": - return True - else: - return False - - def _is_oneliner(self, tag): - return (tag in ['hr', 'hr/']) - - def _stringindex_to_listindex(self, stringindex, items): - """ - Same effect as concatenating the strings in items, - finding the character to which stringindex refers in that string, - and returning the index of the item in which that character resides. - """ - items.append('dummy') - i, count = 0, 0 - while count <= stringindex: - count += len(items[i]) - i += 1 - return i - 1 - - def _nested_markdown_in_html(self, items): - """Find and process html child elements of the given element block.""" - for i, item in enumerate(items): - if self.left_tag_re.match(item): - left_tag, left_index, attrs = \ - self._get_left_tag(''.join(items[i:])) - right_tag, data_index = self._get_right_tag( - left_tag, left_index, ''.join(items[i:])) - right_listindex = \ - self._stringindex_to_listindex(data_index, items[i:]) + i - if 'markdown' in attrs.keys(): - items[i] = items[i][left_index:] # remove opening tag - placeholder = self.markdown.htmlStash.store_tag( - left_tag, attrs, i + 1, right_listindex + 1) - items.insert(i, placeholder) - if len(items) - right_listindex <= 1: # last nest, no tail - right_listindex -= 1 - items[right_listindex] = items[right_listindex][ - :-len(right_tag) - 2] # remove closing tag - else: # raw html - if len(items) - right_listindex <= 1: # last element - right_listindex -= 1 - placeholder = self.markdown.htmlStash.store('\n\n'.join( - items[i:right_listindex + 1])) - del items[i:right_listindex + 1] - items.insert(i, placeholder) - return items - - def run(self, lines): - text = "\n".join(lines) - new_blocks = [] - text = text.rsplit("\n\n") - items = [] - left_tag = '' - right_tag = '' - in_tag = False # flag - - while text: - block = text[0] - if block.startswith("\n"): - block = block[1:] - text = text[1:] - - if block.startswith("\n"): - block = block[1:] - - if not in_tag: - if block.startswith("<") and len(block.strip()) > 1: - - if block[1:4] == "!--": - # is a comment block - left_tag, left_index, attrs = "--", 2, {} - else: - left_tag, left_index, attrs = self._get_left_tag(block) - right_tag, data_index = self._get_right_tag(left_tag, - left_index, - block) - # keep checking conditions below and maybe just append - - if data_index < len(block) \ - and (util.isBlockLevel(left_tag) - or left_tag == '--'): - text.insert(0, block[data_index:]) - block = block[:data_index] - - if not (util.isBlockLevel(left_tag) \ - or block[1] in ["!", "?", "@", "%"]): - new_blocks.append(block) - continue - - if self._is_oneliner(left_tag): - new_blocks.append(block.strip()) - continue - - if block.rstrip().endswith(">") \ - and self._equal_tags(left_tag, right_tag): - if self.markdown_in_raw and 'markdown' in attrs.keys(): - block = block[left_index:-len(right_tag) - 2] - new_blocks.append(self.markdown.htmlStash. - store_tag(left_tag, attrs, 0, 2)) - new_blocks.extend([block]) - else: - new_blocks.append( - self.markdown.htmlStash.store(block.strip())) - continue - else: - # if is block level tag and is not complete - if (not self._equal_tags(left_tag, right_tag)) and \ - (util.isBlockLevel(left_tag) or left_tag == "--"): - items.append(block.strip()) - in_tag = True - else: - new_blocks.append( - self.markdown.htmlStash.store(block.strip())) - - continue - - else: - new_blocks.append(block) - - else: - items.append(block) - - right_tag, data_index = self._get_right_tag(left_tag, 0, block) - - if self._equal_tags(left_tag, right_tag): - # if find closing tag - - if data_index < len(block): - # we have more text after right_tag - items[-1] = block[:data_index] - text.insert(0, block[data_index:]) - - in_tag = False - if self.markdown_in_raw and 'markdown' in attrs.keys(): - items[0] = items[0][left_index:] - items[-1] = items[-1][:-len(right_tag) - 2] - if items[len(items) - 1]: # not a newline/empty string - right_index = len(items) + 3 - else: - right_index = len(items) + 2 - new_blocks.append(self.markdown.htmlStash.store_tag( - left_tag, attrs, 0, right_index)) - placeholderslen = len(self.markdown.htmlStash.tag_data) - new_blocks.extend( - self._nested_markdown_in_html(items)) - nests = len(self.markdown.htmlStash.tag_data) - \ - placeholderslen - self.markdown.htmlStash.tag_data[-1 - nests][ - 'right_index'] += nests - 2 - else: - new_blocks.append( - self.markdown.htmlStash.store('\n\n'.join(items))) - items = [] - - if items: - if self.markdown_in_raw and 'markdown' in attrs.keys(): - items[0] = items[0][left_index:] - items[-1] = items[-1][:-len(right_tag) - 2] - if items[len(items) - 1]: # not a newline/empty string - right_index = len(items) + 3 - else: - right_index = len(items) + 2 - new_blocks.append( - self.markdown.htmlStash.store_tag( - left_tag, attrs, 0, right_index)) - placeholderslen = len(self.markdown.htmlStash.tag_data) - new_blocks.extend(self._nested_markdown_in_html(items)) - nests = len(self.markdown.htmlStash.tag_data) - placeholderslen - self.markdown.htmlStash.tag_data[-1 - nests][ - 'right_index'] += nests - 2 - else: - new_blocks.append( - self.markdown.htmlStash.store('\n\n'.join(items))) - new_blocks.append('\n') - - new_text = "\n\n".join(new_blocks) - return new_text.split("\n") - - -class ReferencePreprocessor(Preprocessor): - """ Remove reference definitions from text and store for later use. """ - - TITLE = r'[ ]*(\"(.*)\"|\'(.*)\'|\((.*)\))[ ]*' - RE = re.compile(r'^[ ]{0,3}\[([^\]]*)\]:\s*([^ ]*)[ ]*(%s)?$' % TITLE, re.DOTALL) - TITLE_RE = re.compile(r'^%s$' % TITLE) - - def run (self, lines): - new_text = []; - while lines: - line = lines.pop(0) - m = self.RE.match(line) - if m: - id = m.group(1).strip().lower() - link = m.group(2).lstrip('<').rstrip('>') - t = m.group(5) or m.group(6) or m.group(7) - if not t: - # Check next line for title - tm = self.TITLE_RE.match(lines[0]) - if tm: - lines.pop(0) - t = tm.group(2) or tm.group(3) or tm.group(4) - self.markdown.references[id] = (link, t) - else: - new_text.append(line) - - return new_text #+ "\n" diff --git a/awx/lib/site-packages/markdown/serializers.py b/awx/lib/site-packages/markdown/serializers.py deleted file mode 100644 index aa828066b4..0000000000 --- a/awx/lib/site-packages/markdown/serializers.py +++ /dev/null @@ -1,276 +0,0 @@ -# markdown/searializers.py -# -# Add x/html serialization to Elementree -# Taken from ElementTree 1.3 preview with slight modifications -# -# Copyright (c) 1999-2007 by Fredrik Lundh. All rights reserved. -# -# fredrik@pythonware.com -# http://www.pythonware.com -# -# -------------------------------------------------------------------- -# The ElementTree toolkit is -# -# Copyright (c) 1999-2007 by Fredrik Lundh -# -# By obtaining, using, and/or copying this software and/or its -# associated documentation, you agree that you have read, understood, -# and will comply with the following terms and conditions: -# -# Permission to use, copy, modify, and distribute this software and -# its associated documentation for any purpose and without fee is -# hereby granted, provided that the above copyright notice appears in -# all copies, and that both that copyright notice and this permission -# notice appear in supporting documentation, and that the name of -# Secret Labs AB or the author not be used in advertising or publicity -# pertaining to distribution of the software without specific, written -# prior permission. -# -# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD -# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- -# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR -# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY -# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE -# OF THIS SOFTWARE. -# -------------------------------------------------------------------- - - -from __future__ import absolute_import -from __future__ import unicode_literals -from . import util -ElementTree = util.etree.ElementTree -QName = util.etree.QName -if hasattr(util.etree, 'test_comment'): - Comment = util.etree.test_comment -else: - Comment = util.etree.Comment -PI = util.etree.PI -ProcessingInstruction = util.etree.ProcessingInstruction - -__all__ = ['to_html_string', 'to_xhtml_string'] - -HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr", - "img", "input", "isindex", "link", "meta" "param") - -try: - HTML_EMPTY = set(HTML_EMPTY) -except NameError: - pass - -_namespace_map = { - # "well-known" namespace prefixes - "http://www.w3.org/XML/1998/namespace": "xml", - "http://www.w3.org/1999/xhtml": "html", - "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf", - "http://schemas.xmlsoap.org/wsdl/": "wsdl", - # xml schema - "http://www.w3.org/2001/XMLSchema": "xs", - "http://www.w3.org/2001/XMLSchema-instance": "xsi", - # dublic core - "http://purl.org/dc/elements/1.1/": "dc", -} - - -def _raise_serialization_error(text): - raise TypeError( - "cannot serialize %r (type %s)" % (text, type(text).__name__) - ) - -def _encode(text, encoding): - try: - return text.encode(encoding, "xmlcharrefreplace") - except (TypeError, AttributeError): - _raise_serialization_error(text) - -def _escape_cdata(text): - # escape character data - try: - # it's worth avoiding do-nothing calls for strings that are - # shorter than 500 character, or so. assume that's, by far, - # the most common case in most applications. - if "&" in text: - text = text.replace("&", "&") - if "<" in text: - text = text.replace("<", "<") - if ">" in text: - text = text.replace(">", ">") - return text - except (TypeError, AttributeError): - _raise_serialization_error(text) - - -def _escape_attrib(text): - # escape attribute value - try: - if "&" in text: - text = text.replace("&", "&") - if "<" in text: - text = text.replace("<", "<") - if ">" in text: - text = text.replace(">", ">") - if "\"" in text: - text = text.replace("\"", """) - if "\n" in text: - text = text.replace("\n", " ") - return text - except (TypeError, AttributeError): - _raise_serialization_error(text) - -def _escape_attrib_html(text): - # escape attribute value - try: - if "&" in text: - text = text.replace("&", "&") - if "<" in text: - text = text.replace("<", "<") - if ">" in text: - text = text.replace(">", ">") - if "\"" in text: - text = text.replace("\"", """) - return text - except (TypeError, AttributeError): - _raise_serialization_error(text) - - -def _serialize_html(write, elem, qnames, namespaces, format): - tag = elem.tag - text = elem.text - if tag is Comment: - write("<!--%s-->" % _escape_cdata(text)) - elif tag is ProcessingInstruction: - write("<?%s?>" % _escape_cdata(text)) - else: - tag = qnames[tag] - if tag is None: - if text: - write(_escape_cdata(text)) - for e in elem: - _serialize_html(write, e, qnames, None, format) - else: - write("<" + tag) - items = elem.items() - if items or namespaces: - items = sorted(items) # lexical order - for k, v in items: - if isinstance(k, QName): - k = k.text - if isinstance(v, QName): - v = qnames[v.text] - else: - v = _escape_attrib_html(v) - if qnames[k] == v and format == 'html': - # handle boolean attributes - write(" %s" % v) - else: - write(" %s=\"%s\"" % (qnames[k], v)) - if namespaces: - items = namespaces.items() - items.sort(key=lambda x: x[1]) # sort on prefix - for v, k in items: - if k: - k = ":" + k - write(" xmlns%s=\"%s\"" % (k, _escape_attrib(v))) - if format == "xhtml" and tag.lower() in HTML_EMPTY: - write(" />") - else: - write(">") - if text: - if tag.lower() in ["script", "style"]: - write(text) - else: - write(_escape_cdata(text)) - for e in elem: - _serialize_html(write, e, qnames, None, format) - if tag.lower() not in HTML_EMPTY: - write("</" + tag + ">") - if elem.tail: - write(_escape_cdata(elem.tail)) - -def _write_html(root, - encoding=None, - default_namespace=None, - format="html"): - assert root is not None - data = [] - write = data.append - qnames, namespaces = _namespaces(root, default_namespace) - _serialize_html(write, root, qnames, namespaces, format) - if encoding is None: - return "".join(data) - else: - return _encode("".join(data)) - - -# -------------------------------------------------------------------- -# serialization support - -def _namespaces(elem, default_namespace=None): - # identify namespaces used in this tree - - # maps qnames to *encoded* prefix:local names - qnames = {None: None} - - # maps uri:s to prefixes - namespaces = {} - if default_namespace: - namespaces[default_namespace] = "" - - def add_qname(qname): - # calculate serialized qname representation - try: - if qname[:1] == "{": - uri, tag = qname[1:].split("}", 1) - prefix = namespaces.get(uri) - if prefix is None: - prefix = _namespace_map.get(uri) - if prefix is None: - prefix = "ns%d" % len(namespaces) - if prefix != "xml": - namespaces[uri] = prefix - if prefix: - qnames[qname] = "%s:%s" % (prefix, tag) - else: - qnames[qname] = tag # default element - else: - if default_namespace: - raise ValueError( - "cannot use non-qualified names with " - "default_namespace option" - ) - qnames[qname] = qname - except TypeError: - _raise_serialization_error(qname) - - # populate qname and namespaces table - try: - iterate = elem.iter - except AttributeError: - iterate = elem.getiterator # cET compatibility - for elem in iterate(): - tag = elem.tag - if isinstance(tag, QName) and tag.text not in qnames: - add_qname(tag.text) - elif isinstance(tag, util.string_type): - if tag not in qnames: - add_qname(tag) - elif tag is not None and tag is not Comment and tag is not PI: - _raise_serialization_error(tag) - for key, value in elem.items(): - if isinstance(key, QName): - key = key.text - if key not in qnames: - add_qname(key) - if isinstance(value, QName) and value.text not in qnames: - add_qname(value.text) - text = elem.text - if isinstance(text, QName) and text.text not in qnames: - add_qname(text.text) - return qnames, namespaces - -def to_html_string(element): - return _write_html(ElementTree(element).getroot(), format="html") - -def to_xhtml_string(element): - return _write_html(ElementTree(element).getroot(), format="xhtml") diff --git a/awx/lib/site-packages/markdown/treeprocessors.py b/awx/lib/site-packages/markdown/treeprocessors.py deleted file mode 100644 index ef0a2aa00c..0000000000 --- a/awx/lib/site-packages/markdown/treeprocessors.py +++ /dev/null @@ -1,360 +0,0 @@ -from __future__ import unicode_literals -from __future__ import absolute_import -from . import util -from . import odict -from . import inlinepatterns - - -def build_treeprocessors(md_instance, **kwargs): - """ Build the default treeprocessors for Markdown. """ - treeprocessors = odict.OrderedDict() - treeprocessors["inline"] = InlineProcessor(md_instance) - treeprocessors["prettify"] = PrettifyTreeprocessor(md_instance) - return treeprocessors - - -def isString(s): - """ Check if it's string """ - if not isinstance(s, util.AtomicString): - return isinstance(s, util.string_type) - return False - - -class Treeprocessor(util.Processor): - """ - Treeprocessors are run on the ElementTree object before serialization. - - Each Treeprocessor implements a "run" method that takes a pointer to an - ElementTree, modifies it as necessary and returns an ElementTree - object. - - Treeprocessors must extend markdown.Treeprocessor. - - """ - def run(self, root): - """ - Subclasses of Treeprocessor should implement a `run` method, which - takes a root ElementTree. This method can return another ElementTree - object, and the existing root ElementTree will be replaced, or it can - modify the current tree and return None. - """ - pass - - -class InlineProcessor(Treeprocessor): - """ - A Treeprocessor that traverses a tree, applying inline patterns. - """ - - def __init__(self, md): - self.__placeholder_prefix = util.INLINE_PLACEHOLDER_PREFIX - self.__placeholder_suffix = util.ETX - self.__placeholder_length = 4 + len(self.__placeholder_prefix) \ - + len(self.__placeholder_suffix) - self.__placeholder_re = util.INLINE_PLACEHOLDER_RE - self.markdown = md - - def __makePlaceholder(self, type): - """ Generate a placeholder """ - id = "%04d" % len(self.stashed_nodes) - hash = util.INLINE_PLACEHOLDER % id - return hash, id - - def __findPlaceholder(self, data, index): - """ - Extract id from data string, start from index - - Keyword arguments: - - * data: string - * index: index, from which we start search - - Returns: placeholder id and string index, after the found placeholder. - - """ - m = self.__placeholder_re.search(data, index) - if m: - return m.group(1), m.end() - else: - return None, index + 1 - - def __stashNode(self, node, type): - """ Add node to stash """ - placeholder, id = self.__makePlaceholder(type) - self.stashed_nodes[id] = node - return placeholder - - def __handleInline(self, data, patternIndex=0): - """ - Process string with inline patterns and replace it - with placeholders - - Keyword arguments: - - * data: A line of Markdown text - * patternIndex: The index of the inlinePattern to start with - - Returns: String with placeholders. - - """ - if not isinstance(data, util.AtomicString): - startIndex = 0 - while patternIndex < len(self.markdown.inlinePatterns): - data, matched, startIndex = self.__applyPattern( - self.markdown.inlinePatterns.value_for_index(patternIndex), - data, patternIndex, startIndex) - if not matched: - patternIndex += 1 - return data - - def __processElementText(self, node, subnode, isText=True): - """ - Process placeholders in Element.text or Element.tail - of Elements popped from self.stashed_nodes. - - Keywords arguments: - - * node: parent node - * subnode: processing node - * isText: bool variable, True - it's text, False - it's tail - - Returns: None - - """ - if isText: - text = subnode.text - subnode.text = None - else: - text = subnode.tail - subnode.tail = None - - childResult = self.__processPlaceholders(text, subnode) - - if not isText and node is not subnode: - pos = list(node).index(subnode) - node.remove(subnode) - else: - pos = 0 - - childResult.reverse() - for newChild in childResult: - node.insert(pos, newChild) - - def __processPlaceholders(self, data, parent): - """ - Process string with placeholders and generate ElementTree tree. - - Keyword arguments: - - * data: string with placeholders instead of ElementTree elements. - * parent: Element, which contains processing inline data - - Returns: list with ElementTree elements with applied inline patterns. - - """ - def linkText(text): - if text: - if result: - if result[-1].tail: - result[-1].tail += text - else: - result[-1].tail = text - else: - if parent.text: - parent.text += text - else: - parent.text = text - result = [] - strartIndex = 0 - while data: - index = data.find(self.__placeholder_prefix, strartIndex) - if index != -1: - id, phEndIndex = self.__findPlaceholder(data, index) - - if id in self.stashed_nodes: - node = self.stashed_nodes.get(id) - - if index > 0: - text = data[strartIndex:index] - linkText(text) - - if not isString(node): # it's Element - for child in [node] + list(node): - if child.tail: - if child.tail.strip(): - self.__processElementText(node, child,False) - if child.text: - if child.text.strip(): - self.__processElementText(child, child) - else: # it's just a string - linkText(node) - strartIndex = phEndIndex - continue - - strartIndex = phEndIndex - result.append(node) - - else: # wrong placeholder - end = index + len(self.__placeholder_prefix) - linkText(data[strartIndex:end]) - strartIndex = end - else: - text = data[strartIndex:] - if isinstance(data, util.AtomicString): - # We don't want to loose the AtomicString - text = util.AtomicString(text) - linkText(text) - data = "" - - return result - - def __applyPattern(self, pattern, data, patternIndex, startIndex=0): - """ - Check if the line fits the pattern, create the necessary - elements, add it to stashed_nodes. - - Keyword arguments: - - * data: the text to be processed - * pattern: the pattern to be checked - * patternIndex: index of current pattern - * startIndex: string index, from which we start searching - - Returns: String with placeholders instead of ElementTree elements. - - """ - match = pattern.getCompiledRegExp().match(data[startIndex:]) - leftData = data[:startIndex] - - if not match: - return data, False, 0 - - node = pattern.handleMatch(match) - - if node is None: - return data, True, len(leftData)+match.span(len(match.groups()))[0] - - if not isString(node): - if not isinstance(node.text, util.AtomicString): - # We need to process current node too - for child in [node] + list(node): - if not isString(node): - if child.text: - child.text = self.__handleInline(child.text, - patternIndex + 1) - if child.tail: - child.tail = self.__handleInline(child.tail, - patternIndex) - - placeholder = self.__stashNode(node, pattern.type()) - - return "%s%s%s%s" % (leftData, - match.group(1), - placeholder, match.groups()[-1]), True, 0 - - def run(self, tree): - """Apply inline patterns to a parsed Markdown tree. - - Iterate over ElementTree, find elements with inline tag, apply inline - patterns and append newly created Elements to tree. If you don't - want to process your data with inline paterns, instead of normal string, - use subclass AtomicString: - - node.text = markdown.AtomicString("This will not be processed.") - - Arguments: - - * tree: ElementTree object, representing Markdown tree. - - Returns: ElementTree object with applied inline patterns. - - """ - self.stashed_nodes = {} - - stack = [tree] - - while stack: - currElement = stack.pop() - insertQueue = [] - for child in currElement: - if child.text and not isinstance(child.text, util.AtomicString): - text = child.text - child.text = None - lst = self.__processPlaceholders(self.__handleInline( - text), child) - stack += lst - insertQueue.append((child, lst)) - if child.tail: - tail = self.__handleInline(child.tail) - dumby = util.etree.Element('d') - tailResult = self.__processPlaceholders(tail, dumby) - if dumby.text: - child.tail = dumby.text - else: - child.tail = None - pos = list(currElement).index(child) + 1 - tailResult.reverse() - for newChild in tailResult: - currElement.insert(pos, newChild) - if len(child): - stack.append(child) - - for element, lst in insertQueue: - if self.markdown.enable_attributes: - if element.text and isString(element.text): - element.text = \ - inlinepatterns.handleAttributes(element.text, - element) - i = 0 - for newChild in lst: - if self.markdown.enable_attributes: - # Processing attributes - if newChild.tail and isString(newChild.tail): - newChild.tail = \ - inlinepatterns.handleAttributes(newChild.tail, - element) - if newChild.text and isString(newChild.text): - newChild.text = \ - inlinepatterns.handleAttributes(newChild.text, - newChild) - element.insert(i, newChild) - i += 1 - return tree - - -class PrettifyTreeprocessor(Treeprocessor): - """ Add linebreaks to the html document. """ - - def _prettifyETree(self, elem): - """ Recursively add linebreaks to ElementTree children. """ - - i = "\n" - if util.isBlockLevel(elem.tag) and elem.tag not in ['code', 'pre']: - if (not elem.text or not elem.text.strip()) \ - and len(elem) and util.isBlockLevel(elem[0].tag): - elem.text = i - for e in elem: - if util.isBlockLevel(e.tag): - self._prettifyETree(e) - if not elem.tail or not elem.tail.strip(): - elem.tail = i - if not elem.tail or not elem.tail.strip(): - elem.tail = i - - def run(self, root): - """ Add linebreaks to ElementTree root object. """ - - self._prettifyETree(root) - # Do <br />'s seperately as they are often in the middle of - # inline content and missed by _prettifyETree. - brs = root.getiterator('br') - for br in brs: - if not br.tail or not br.tail.strip(): - br.tail = '\n' - else: - br.tail = '\n%s' % br.tail - # Clean up extra empty lines at end of code blocks. - pres = root.getiterator('pre') - for pre in pres: - if len(pre) and pre[0].tag == 'code': - pre[0].text = pre[0].text.rstrip() + '\n' diff --git a/awx/lib/site-packages/markdown/util.py b/awx/lib/site-packages/markdown/util.py deleted file mode 100644 index edb25886ad..0000000000 --- a/awx/lib/site-packages/markdown/util.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals -import re -import sys - - -""" -Python 3 Stuff -============================================================================= -""" -PY3 = sys.version_info[0] == 3 - -if PY3: - string_type = str - text_type = str - int2str = chr -else: - string_type = basestring - text_type = unicode - int2str = unichr - - -""" -Constants you might want to modify ------------------------------------------------------------------------------ -""" - -BLOCK_LEVEL_ELEMENTS = re.compile("^(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul" - "|script|noscript|form|fieldset|iframe|math" - "|hr|hr/|style|li|dt|dd|thead|tbody" - "|tr|th|td|section|footer|header|group|figure" - "|figcaption|aside|article|canvas|output" - "|progress|video|nav)$", re.IGNORECASE) -# Placeholders -STX = '\u0002' # Use STX ("Start of text") for start-of-placeholder -ETX = '\u0003' # Use ETX ("End of text") for end-of-placeholder -INLINE_PLACEHOLDER_PREFIX = STX+"klzzwxh:" -INLINE_PLACEHOLDER = INLINE_PLACEHOLDER_PREFIX + "%s" + ETX -INLINE_PLACEHOLDER_RE = re.compile(INLINE_PLACEHOLDER % r'([0-9]+)') -AMP_SUBSTITUTE = STX+"amp"+ETX -HTML_PLACEHOLDER = STX + "wzxhzdk:%s" + ETX -HTML_PLACEHOLDER_RE = re.compile(HTML_PLACEHOLDER % r'([0-9]+)') -TAG_PLACEHOLDER = STX + "hzzhzkh:%s" + ETX - - -""" -Constants you probably do not need to change ------------------------------------------------------------------------------ -""" - -RTL_BIDI_RANGES = ( ('\u0590', '\u07FF'), - # Hebrew (0590-05FF), Arabic (0600-06FF), - # Syriac (0700-074F), Arabic supplement (0750-077F), - # Thaana (0780-07BF), Nko (07C0-07FF). - ('\u2D30', '\u2D7F'), # Tifinagh - ) - -# Extensions should use "markdown.util.etree" instead of "etree" (or do `from -# markdown.util import etree`). Do not import it by yourself. - -try: # Is the C implementation of ElementTree available? - import xml.etree.cElementTree as etree - from xml.etree.ElementTree import Comment - # Serializers (including ours) test with non-c Comment - etree.test_comment = Comment - if etree.VERSION < "1.0.5": - raise RuntimeError("cElementTree version 1.0.5 or higher is required.") -except (ImportError, RuntimeError): - # Use the Python implementation of ElementTree? - import xml.etree.ElementTree as etree - if etree.VERSION < "1.1": - raise RuntimeError("ElementTree version 1.1 or higher is required") - - -""" -AUXILIARY GLOBAL FUNCTIONS -============================================================================= -""" - - -def isBlockLevel(tag): - """Check if the tag is a block level HTML tag.""" - if isinstance(tag, string_type): - return BLOCK_LEVEL_ELEMENTS.match(tag) - # Some ElementTree tags are not strings, so return False. - return False - -def parseBoolValue(value, fail_on_errors=True): - """Parses a string representing bool value. If parsing was successful, - returns True or False. If parsing was not successful, raises - ValueError, or, if fail_on_errors=False, returns None.""" - if not isinstance(value, string_type): - return bool(value) - elif value.lower() in ('true', 'yes', 'y', 'on', '1'): - return True - elif value.lower() in ('false', 'no', 'n', 'off', '0'): - return False - elif fail_on_errors: - raise ValueError('Cannot parse bool value: %r' % value) - -""" -MISC AUXILIARY CLASSES -============================================================================= -""" - -class AtomicString(text_type): - """A string which should not be further processed.""" - pass - - -class Processor(object): - def __init__(self, markdown_instance=None): - if markdown_instance: - self.markdown = markdown_instance - - -class HtmlStash(object): - """ - This class is used for stashing HTML objects that we extract - in the beginning and replace with place-holders. - """ - - def __init__(self): - """ Create a HtmlStash. """ - self.html_counter = 0 # for counting inline html segments - self.rawHtmlBlocks = [] - self.tag_counter = 0 - self.tag_data = [] # list of dictionaries in the order tags appear - - def store(self, html, safe=False): - """ - Saves an HTML segment for later reinsertion. Returns a - placeholder string that needs to be inserted into the - document. - - Keyword arguments: - - * html: an html segment - * safe: label an html segment as safe for safemode - - Returns : a placeholder string - - """ - self.rawHtmlBlocks.append((html, safe)) - placeholder = self.get_placeholder(self.html_counter) - self.html_counter += 1 - return placeholder - - def reset(self): - self.html_counter = 0 - self.rawHtmlBlocks = [] - - def get_placeholder(self, key): - return HTML_PLACEHOLDER % key - - def store_tag(self, tag, attrs, left_index, right_index): - """Store tag data and return a placeholder.""" - self.tag_data.append({'tag': tag, 'attrs': attrs, - 'left_index': left_index, - 'right_index': right_index}) - placeholder = TAG_PLACEHOLDER % str(self.tag_counter) - self.tag_counter += 1 # equal to the tag's index in self.tag_data - return placeholder diff --git a/awx/lib/site-packages/mock.py b/awx/lib/site-packages/mock.py deleted file mode 100644 index c8fc5d1d25..0000000000 --- a/awx/lib/site-packages/mock.py +++ /dev/null @@ -1,2367 +0,0 @@ -# mock.py -# Test tools for mocking and patching. -# Copyright (C) 2007-2012 Michael Foord & the mock team -# E-mail: fuzzyman AT voidspace DOT org DOT uk - -# mock 1.0 -# http://www.voidspace.org.uk/python/mock/ - -# Released subject to the BSD License -# Please see http://www.voidspace.org.uk/python/license.shtml - -# Scripts maintained at http://www.voidspace.org.uk/python/index.shtml -# Comments, suggestions and bug reports welcome. - - -__all__ = ( - 'Mock', - 'MagicMock', - 'patch', - 'sentinel', - 'DEFAULT', - 'ANY', - 'call', - 'create_autospec', - 'FILTER_DIR', - 'NonCallableMock', - 'NonCallableMagicMock', - 'mock_open', - 'PropertyMock', -) - - -__version__ = '1.0.1' - - -import pprint -import sys - -try: - import inspect -except ImportError: - # for alternative platforms that - # may not have inspect - inspect = None - -try: - from functools import wraps as original_wraps -except ImportError: - # Python 2.4 compatibility - def wraps(original): - def inner(f): - f.__name__ = original.__name__ - f.__doc__ = original.__doc__ - f.__module__ = original.__module__ - f.__wrapped__ = original - return f - return inner -else: - if sys.version_info[:2] >= (3, 3): - wraps = original_wraps - else: - def wraps(func): - def inner(f): - f = original_wraps(func)(f) - f.__wrapped__ = func - return f - return inner - -try: - unicode -except NameError: - # Python 3 - basestring = unicode = str - -try: - long -except NameError: - # Python 3 - long = int - -try: - BaseException -except NameError: - # Python 2.4 compatibility - BaseException = Exception - -try: - next -except NameError: - def next(obj): - return obj.next() - - -BaseExceptions = (BaseException,) -if 'java' in sys.platform: - # jython - import java - BaseExceptions = (BaseException, java.lang.Throwable) - -try: - _isidentifier = str.isidentifier -except AttributeError: - # Python 2.X - import keyword - import re - regex = re.compile(r'^[a-z_][a-z0-9_]*$', re.I) - def _isidentifier(string): - if string in keyword.kwlist: - return False - return regex.match(string) - - -inPy3k = sys.version_info[0] == 3 - -# Needed to work around Python 3 bug where use of "super" interferes with -# defining __class__ as a descriptor -_super = super - -self = 'im_self' -builtin = '__builtin__' -if inPy3k: - self = '__self__' - builtin = 'builtins' - -FILTER_DIR = True - - -def _is_instance_mock(obj): - # can't use isinstance on Mock objects because they override __class__ - # The base class for all mocks is NonCallableMock - return issubclass(type(obj), NonCallableMock) - - -def _is_exception(obj): - return ( - isinstance(obj, BaseExceptions) or - isinstance(obj, ClassTypes) and issubclass(obj, BaseExceptions) - ) - - -class _slotted(object): - __slots__ = ['a'] - - -DescriptorTypes = ( - type(_slotted.a), - property, -) - - -def _getsignature(func, skipfirst, instance=False): - if inspect is None: - raise ImportError('inspect module not available') - - if isinstance(func, ClassTypes) and not instance: - try: - func = func.__init__ - except AttributeError: - return - skipfirst = True - elif not isinstance(func, FunctionTypes): - # for classes where instance is True we end up here too - try: - func = func.__call__ - except AttributeError: - return - - if inPy3k: - try: - argspec = inspect.getfullargspec(func) - except TypeError: - # C function / method, possibly inherited object().__init__ - return - regargs, varargs, varkw, defaults, kwonly, kwonlydef, ann = argspec - else: - try: - regargs, varargs, varkwargs, defaults = inspect.getargspec(func) - except TypeError: - # C function / method, possibly inherited object().__init__ - return - - # instance methods and classmethods need to lose the self argument - if getattr(func, self, None) is not None: - regargs = regargs[1:] - if skipfirst: - # this condition and the above one are never both True - why? - regargs = regargs[1:] - - if inPy3k: - signature = inspect.formatargspec( - regargs, varargs, varkw, defaults, - kwonly, kwonlydef, ann, formatvalue=lambda value: "") - else: - signature = inspect.formatargspec( - regargs, varargs, varkwargs, defaults, - formatvalue=lambda value: "") - return signature[1:-1], func - - -def _check_signature(func, mock, skipfirst, instance=False): - if not _callable(func): - return - - result = _getsignature(func, skipfirst, instance) - if result is None: - return - signature, func = result - - # can't use self because "self" is common as an argument name - # unfortunately even not in the first place - src = "lambda _mock_self, %s: None" % signature - checksig = eval(src, {}) - _copy_func_details(func, checksig) - type(mock)._mock_check_sig = checksig - - -def _copy_func_details(func, funcopy): - funcopy.__name__ = func.__name__ - funcopy.__doc__ = func.__doc__ - #funcopy.__dict__.update(func.__dict__) - funcopy.__module__ = func.__module__ - if not inPy3k: - funcopy.func_defaults = func.func_defaults - return - funcopy.__defaults__ = func.__defaults__ - funcopy.__kwdefaults__ = func.__kwdefaults__ - - -def _callable(obj): - if isinstance(obj, ClassTypes): - return True - if getattr(obj, '__call__', None) is not None: - return True - return False - - -def _is_list(obj): - # checks for list or tuples - # XXXX badly named! - return type(obj) in (list, tuple) - - -def _instance_callable(obj): - """Given an object, return True if the object is callable. - For classes, return True if instances would be callable.""" - if not isinstance(obj, ClassTypes): - # already an instance - return getattr(obj, '__call__', None) is not None - - klass = obj - # uses __bases__ instead of __mro__ so that we work with old style classes - if klass.__dict__.get('__call__') is not None: - return True - - for base in klass.__bases__: - if _instance_callable(base): - return True - return False - - -def _set_signature(mock, original, instance=False): - # creates a function with signature (*args, **kwargs) that delegates to a - # mock. It still does signature checking by calling a lambda with the same - # signature as the original. - if not _callable(original): - return - - skipfirst = isinstance(original, ClassTypes) - result = _getsignature(original, skipfirst, instance) - if result is None: - # was a C function (e.g. object().__init__ ) that can't be mocked - return - - signature, func = result - - src = "lambda %s: None" % signature - checksig = eval(src, {}) - _copy_func_details(func, checksig) - - name = original.__name__ - if not _isidentifier(name): - name = 'funcopy' - context = {'_checksig_': checksig, 'mock': mock} - src = """def %s(*args, **kwargs): - _checksig_(*args, **kwargs) - return mock(*args, **kwargs)""" % name - exec (src, context) - funcopy = context[name] - _setup_func(funcopy, mock) - return funcopy - - -def _setup_func(funcopy, mock): - funcopy.mock = mock - - # can't use isinstance with mocks - if not _is_instance_mock(mock): - return - - def assert_called_with(*args, **kwargs): - return mock.assert_called_with(*args, **kwargs) - def assert_called_once_with(*args, **kwargs): - return mock.assert_called_once_with(*args, **kwargs) - def assert_has_calls(*args, **kwargs): - return mock.assert_has_calls(*args, **kwargs) - def assert_any_call(*args, **kwargs): - return mock.assert_any_call(*args, **kwargs) - def reset_mock(): - funcopy.method_calls = _CallList() - funcopy.mock_calls = _CallList() - mock.reset_mock() - ret = funcopy.return_value - if _is_instance_mock(ret) and not ret is mock: - ret.reset_mock() - - funcopy.called = False - funcopy.call_count = 0 - funcopy.call_args = None - funcopy.call_args_list = _CallList() - funcopy.method_calls = _CallList() - funcopy.mock_calls = _CallList() - - funcopy.return_value = mock.return_value - funcopy.side_effect = mock.side_effect - funcopy._mock_children = mock._mock_children - - funcopy.assert_called_with = assert_called_with - funcopy.assert_called_once_with = assert_called_once_with - funcopy.assert_has_calls = assert_has_calls - funcopy.assert_any_call = assert_any_call - funcopy.reset_mock = reset_mock - - mock._mock_delegate = funcopy - - -def _is_magic(name): - return '__%s__' % name[2:-2] == name - - -class _SentinelObject(object): - "A unique, named, sentinel object." - def __init__(self, name): - self.name = name - - def __repr__(self): - return 'sentinel.%s' % self.name - - -class _Sentinel(object): - """Access attributes to return a named object, usable as a sentinel.""" - def __init__(self): - self._sentinels = {} - - def __getattr__(self, name): - if name == '__bases__': - # Without this help(mock) raises an exception - raise AttributeError - return self._sentinels.setdefault(name, _SentinelObject(name)) - - -sentinel = _Sentinel() - -DEFAULT = sentinel.DEFAULT -_missing = sentinel.MISSING -_deleted = sentinel.DELETED - - -class OldStyleClass: - pass -ClassType = type(OldStyleClass) - - -def _copy(value): - if type(value) in (dict, list, tuple, set): - return type(value)(value) - return value - - -ClassTypes = (type,) -if not inPy3k: - ClassTypes = (type, ClassType) - -_allowed_names = set( - [ - 'return_value', '_mock_return_value', 'side_effect', - '_mock_side_effect', '_mock_parent', '_mock_new_parent', - '_mock_name', '_mock_new_name' - ] -) - - -def _delegating_property(name): - _allowed_names.add(name) - _the_name = '_mock_' + name - def _get(self, name=name, _the_name=_the_name): - sig = self._mock_delegate - if sig is None: - return getattr(self, _the_name) - return getattr(sig, name) - def _set(self, value, name=name, _the_name=_the_name): - sig = self._mock_delegate - if sig is None: - self.__dict__[_the_name] = value - else: - setattr(sig, name, value) - - return property(_get, _set) - - - -class _CallList(list): - - def __contains__(self, value): - if not isinstance(value, list): - return list.__contains__(self, value) - len_value = len(value) - len_self = len(self) - if len_value > len_self: - return False - - for i in range(0, len_self - len_value + 1): - sub_list = self[i:i+len_value] - if sub_list == value: - return True - return False - - def __repr__(self): - return pprint.pformat(list(self)) - - -def _check_and_set_parent(parent, value, name, new_name): - if not _is_instance_mock(value): - return False - if ((value._mock_name or value._mock_new_name) or - (value._mock_parent is not None) or - (value._mock_new_parent is not None)): - return False - - _parent = parent - while _parent is not None: - # setting a mock (value) as a child or return value of itself - # should not modify the mock - if _parent is value: - return False - _parent = _parent._mock_new_parent - - if new_name: - value._mock_new_parent = parent - value._mock_new_name = new_name - if name: - value._mock_parent = parent - value._mock_name = name - return True - - - -class Base(object): - _mock_return_value = DEFAULT - _mock_side_effect = None - def __init__(self, *args, **kwargs): - pass - - - -class NonCallableMock(Base): - """A non-callable version of `Mock`""" - - def __new__(cls, *args, **kw): - # every instance has its own class - # so we can create magic methods on the - # class without stomping on other mocks - new = type(cls.__name__, (cls,), {'__doc__': cls.__doc__}) - instance = object.__new__(new) - return instance - - - def __init__( - self, spec=None, wraps=None, name=None, spec_set=None, - parent=None, _spec_state=None, _new_name='', _new_parent=None, - **kwargs - ): - if _new_parent is None: - _new_parent = parent - - __dict__ = self.__dict__ - __dict__['_mock_parent'] = parent - __dict__['_mock_name'] = name - __dict__['_mock_new_name'] = _new_name - __dict__['_mock_new_parent'] = _new_parent - - if spec_set is not None: - spec = spec_set - spec_set = True - - self._mock_add_spec(spec, spec_set) - - __dict__['_mock_children'] = {} - __dict__['_mock_wraps'] = wraps - __dict__['_mock_delegate'] = None - - __dict__['_mock_called'] = False - __dict__['_mock_call_args'] = None - __dict__['_mock_call_count'] = 0 - __dict__['_mock_call_args_list'] = _CallList() - __dict__['_mock_mock_calls'] = _CallList() - - __dict__['method_calls'] = _CallList() - - if kwargs: - self.configure_mock(**kwargs) - - _super(NonCallableMock, self).__init__( - spec, wraps, name, spec_set, parent, - _spec_state - ) - - - def attach_mock(self, mock, attribute): - """ - Attach a mock as an attribute of this one, replacing its name and - parent. Calls to the attached mock will be recorded in the - `method_calls` and `mock_calls` attributes of this one.""" - mock._mock_parent = None - mock._mock_new_parent = None - mock._mock_name = '' - mock._mock_new_name = None - - setattr(self, attribute, mock) - - - def mock_add_spec(self, spec, spec_set=False): - """Add a spec to a mock. `spec` can either be an object or a - list of strings. Only attributes on the `spec` can be fetched as - attributes from the mock. - - If `spec_set` is True then only attributes on the spec can be set.""" - self._mock_add_spec(spec, spec_set) - - - def _mock_add_spec(self, spec, spec_set): - _spec_class = None - - if spec is not None and not _is_list(spec): - if isinstance(spec, ClassTypes): - _spec_class = spec - else: - _spec_class = _get_class(spec) - - spec = dir(spec) - - __dict__ = self.__dict__ - __dict__['_spec_class'] = _spec_class - __dict__['_spec_set'] = spec_set - __dict__['_mock_methods'] = spec - - - def __get_return_value(self): - ret = self._mock_return_value - if self._mock_delegate is not None: - ret = self._mock_delegate.return_value - - if ret is DEFAULT: - ret = self._get_child_mock( - _new_parent=self, _new_name='()' - ) - self.return_value = ret - return ret - - - def __set_return_value(self, value): - if self._mock_delegate is not None: - self._mock_delegate.return_value = value - else: - self._mock_return_value = value - _check_and_set_parent(self, value, None, '()') - - __return_value_doc = "The value to be returned when the mock is called." - return_value = property(__get_return_value, __set_return_value, - __return_value_doc) - - - @property - def __class__(self): - if self._spec_class is None: - return type(self) - return self._spec_class - - called = _delegating_property('called') - call_count = _delegating_property('call_count') - call_args = _delegating_property('call_args') - call_args_list = _delegating_property('call_args_list') - mock_calls = _delegating_property('mock_calls') - - - def __get_side_effect(self): - sig = self._mock_delegate - if sig is None: - return self._mock_side_effect - return sig.side_effect - - def __set_side_effect(self, value): - value = _try_iter(value) - sig = self._mock_delegate - if sig is None: - self._mock_side_effect = value - else: - sig.side_effect = value - - side_effect = property(__get_side_effect, __set_side_effect) - - - def reset_mock(self): - "Restore the mock object to its initial state." - self.called = False - self.call_args = None - self.call_count = 0 - self.mock_calls = _CallList() - self.call_args_list = _CallList() - self.method_calls = _CallList() - - for child in self._mock_children.values(): - if isinstance(child, _SpecState): - continue - child.reset_mock() - - ret = self._mock_return_value - if _is_instance_mock(ret) and ret is not self: - ret.reset_mock() - - - def configure_mock(self, **kwargs): - """Set attributes on the mock through keyword arguments. - - Attributes plus return values and side effects can be set on child - mocks using standard dot notation and unpacking a dictionary in the - method call: - - >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError} - >>> mock.configure_mock(**attrs)""" - for arg, val in sorted(kwargs.items(), - # we sort on the number of dots so that - # attributes are set before we set attributes on - # attributes - key=lambda entry: entry[0].count('.')): - args = arg.split('.') - final = args.pop() - obj = self - for entry in args: - obj = getattr(obj, entry) - setattr(obj, final, val) - - - def __getattr__(self, name): - if name == '_mock_methods': - raise AttributeError(name) - elif self._mock_methods is not None: - if name not in self._mock_methods or name in _all_magics: - raise AttributeError("Mock object has no attribute %r" % name) - elif _is_magic(name): - raise AttributeError(name) - - result = self._mock_children.get(name) - if result is _deleted: - raise AttributeError(name) - elif result is None: - wraps = None - if self._mock_wraps is not None: - # XXXX should we get the attribute without triggering code - # execution? - wraps = getattr(self._mock_wraps, name) - - result = self._get_child_mock( - parent=self, name=name, wraps=wraps, _new_name=name, - _new_parent=self - ) - self._mock_children[name] = result - - elif isinstance(result, _SpecState): - result = create_autospec( - result.spec, result.spec_set, result.instance, - result.parent, result.name - ) - self._mock_children[name] = result - - return result - - - def __repr__(self): - _name_list = [self._mock_new_name] - _parent = self._mock_new_parent - last = self - - dot = '.' - if _name_list == ['()']: - dot = '' - seen = set() - while _parent is not None: - last = _parent - - _name_list.append(_parent._mock_new_name + dot) - dot = '.' - if _parent._mock_new_name == '()': - dot = '' - - _parent = _parent._mock_new_parent - - # use ids here so as not to call __hash__ on the mocks - if id(_parent) in seen: - break - seen.add(id(_parent)) - - _name_list = list(reversed(_name_list)) - _first = last._mock_name or 'mock' - if len(_name_list) > 1: - if _name_list[1] not in ('()', '().'): - _first += '.' - _name_list[0] = _first - name = ''.join(_name_list) - - name_string = '' - if name not in ('mock', 'mock.'): - name_string = ' name=%r' % name - - spec_string = '' - if self._spec_class is not None: - spec_string = ' spec=%r' - if self._spec_set: - spec_string = ' spec_set=%r' - spec_string = spec_string % self._spec_class.__name__ - return "<%s%s%s id='%s'>" % ( - type(self).__name__, - name_string, - spec_string, - id(self) - ) - - - def __dir__(self): - """Filter the output of `dir(mock)` to only useful members. - XXXX - """ - extras = self._mock_methods or [] - from_type = dir(type(self)) - from_dict = list(self.__dict__) - - if FILTER_DIR: - from_type = [e for e in from_type if not e.startswith('_')] - from_dict = [e for e in from_dict if not e.startswith('_') or - _is_magic(e)] - return sorted(set(extras + from_type + from_dict + - list(self._mock_children))) - - - def __setattr__(self, name, value): - if name in _allowed_names: - # property setters go through here - return object.__setattr__(self, name, value) - elif (self._spec_set and self._mock_methods is not None and - name not in self._mock_methods and - name not in self.__dict__): - raise AttributeError("Mock object has no attribute '%s'" % name) - elif name in _unsupported_magics: - msg = 'Attempting to set unsupported magic method %r.' % name - raise AttributeError(msg) - elif name in _all_magics: - if self._mock_methods is not None and name not in self._mock_methods: - raise AttributeError("Mock object has no attribute '%s'" % name) - - if not _is_instance_mock(value): - setattr(type(self), name, _get_method(name, value)) - original = value - value = lambda *args, **kw: original(self, *args, **kw) - else: - # only set _new_name and not name so that mock_calls is tracked - # but not method calls - _check_and_set_parent(self, value, None, name) - setattr(type(self), name, value) - self._mock_children[name] = value - elif name == '__class__': - self._spec_class = value - return - else: - if _check_and_set_parent(self, value, name, name): - self._mock_children[name] = value - return object.__setattr__(self, name, value) - - - def __delattr__(self, name): - if name in _all_magics and name in type(self).__dict__: - delattr(type(self), name) - if name not in self.__dict__: - # for magic methods that are still MagicProxy objects and - # not set on the instance itself - return - - if name in self.__dict__: - object.__delattr__(self, name) - - obj = self._mock_children.get(name, _missing) - if obj is _deleted: - raise AttributeError(name) - if obj is not _missing: - del self._mock_children[name] - self._mock_children[name] = _deleted - - - - def _format_mock_call_signature(self, args, kwargs): - name = self._mock_name or 'mock' - return _format_call_signature(name, args, kwargs) - - - def _format_mock_failure_message(self, args, kwargs): - message = 'Expected call: %s\nActual call: %s' - expected_string = self._format_mock_call_signature(args, kwargs) - call_args = self.call_args - if len(call_args) == 3: - call_args = call_args[1:] - actual_string = self._format_mock_call_signature(*call_args) - return message % (expected_string, actual_string) - - - def assert_called_with(_mock_self, *args, **kwargs): - """assert that the mock was called with the specified arguments. - - Raises an AssertionError if the args and keyword args passed in are - different to the last call to the mock.""" - self = _mock_self - if self.call_args is None: - expected = self._format_mock_call_signature(args, kwargs) - raise AssertionError('Expected call: %s\nNot called' % (expected,)) - - if self.call_args != (args, kwargs): - msg = self._format_mock_failure_message(args, kwargs) - raise AssertionError(msg) - - - def assert_called_once_with(_mock_self, *args, **kwargs): - """assert that the mock was called exactly once and with the specified - arguments.""" - self = _mock_self - if not self.call_count == 1: - msg = ("Expected to be called once. Called %s times." % - self.call_count) - raise AssertionError(msg) - return self.assert_called_with(*args, **kwargs) - - - def assert_has_calls(self, calls, any_order=False): - """assert the mock has been called with the specified calls. - The `mock_calls` list is checked for the calls. - - If `any_order` is False (the default) then the calls must be - sequential. There can be extra calls before or after the - specified calls. - - If `any_order` is True then the calls can be in any order, but - they must all appear in `mock_calls`.""" - if not any_order: - if calls not in self.mock_calls: - raise AssertionError( - 'Calls not found.\nExpected: %r\n' - 'Actual: %r' % (calls, self.mock_calls) - ) - return - - all_calls = list(self.mock_calls) - - not_found = [] - for kall in calls: - try: - all_calls.remove(kall) - except ValueError: - not_found.append(kall) - if not_found: - raise AssertionError( - '%r not all found in call list' % (tuple(not_found),) - ) - - - def assert_any_call(self, *args, **kwargs): - """assert the mock has been called with the specified arguments. - - The assert passes if the mock has *ever* been called, unlike - `assert_called_with` and `assert_called_once_with` that only pass if - the call is the most recent one.""" - kall = call(*args, **kwargs) - if kall not in self.call_args_list: - expected_string = self._format_mock_call_signature(args, kwargs) - raise AssertionError( - '%s call not found' % expected_string - ) - - - def _get_child_mock(self, **kw): - """Create the child mocks for attributes and return value. - By default child mocks will be the same type as the parent. - Subclasses of Mock may want to override this to customize the way - child mocks are made. - - For non-callable mocks the callable variant will be used (rather than - any custom subclass).""" - _type = type(self) - if not issubclass(_type, CallableMixin): - if issubclass(_type, NonCallableMagicMock): - klass = MagicMock - elif issubclass(_type, NonCallableMock) : - klass = Mock - else: - klass = _type.__mro__[1] - return klass(**kw) - - - -def _try_iter(obj): - if obj is None: - return obj - if _is_exception(obj): - return obj - if _callable(obj): - return obj - try: - return iter(obj) - except TypeError: - # XXXX backwards compatibility - # but this will blow up on first call - so maybe we should fail early? - return obj - - - -class CallableMixin(Base): - - def __init__(self, spec=None, side_effect=None, return_value=DEFAULT, - wraps=None, name=None, spec_set=None, parent=None, - _spec_state=None, _new_name='', _new_parent=None, **kwargs): - self.__dict__['_mock_return_value'] = return_value - - _super(CallableMixin, self).__init__( - spec, wraps, name, spec_set, parent, - _spec_state, _new_name, _new_parent, **kwargs - ) - - self.side_effect = side_effect - - - def _mock_check_sig(self, *args, **kwargs): - # stub method that can be replaced with one with a specific signature - pass - - - def __call__(_mock_self, *args, **kwargs): - # can't use self in-case a function / method we are mocking uses self - # in the signature - _mock_self._mock_check_sig(*args, **kwargs) - return _mock_self._mock_call(*args, **kwargs) - - - def _mock_call(_mock_self, *args, **kwargs): - self = _mock_self - self.called = True - self.call_count += 1 - self.call_args = _Call((args, kwargs), two=True) - self.call_args_list.append(_Call((args, kwargs), two=True)) - - _new_name = self._mock_new_name - _new_parent = self._mock_new_parent - self.mock_calls.append(_Call(('', args, kwargs))) - - seen = set() - skip_next_dot = _new_name == '()' - do_method_calls = self._mock_parent is not None - name = self._mock_name - while _new_parent is not None: - this_mock_call = _Call((_new_name, args, kwargs)) - if _new_parent._mock_new_name: - dot = '.' - if skip_next_dot: - dot = '' - - skip_next_dot = False - if _new_parent._mock_new_name == '()': - skip_next_dot = True - - _new_name = _new_parent._mock_new_name + dot + _new_name - - if do_method_calls: - if _new_name == name: - this_method_call = this_mock_call - else: - this_method_call = _Call((name, args, kwargs)) - _new_parent.method_calls.append(this_method_call) - - do_method_calls = _new_parent._mock_parent is not None - if do_method_calls: - name = _new_parent._mock_name + '.' + name - - _new_parent.mock_calls.append(this_mock_call) - _new_parent = _new_parent._mock_new_parent - - # use ids here so as not to call __hash__ on the mocks - _new_parent_id = id(_new_parent) - if _new_parent_id in seen: - break - seen.add(_new_parent_id) - - ret_val = DEFAULT - effect = self.side_effect - if effect is not None: - if _is_exception(effect): - raise effect - - if not _callable(effect): - result = next(effect) - if _is_exception(result): - raise result - return result - - ret_val = effect(*args, **kwargs) - if ret_val is DEFAULT: - ret_val = self.return_value - - if (self._mock_wraps is not None and - self._mock_return_value is DEFAULT): - return self._mock_wraps(*args, **kwargs) - if ret_val is DEFAULT: - ret_val = self.return_value - return ret_val - - - -class Mock(CallableMixin, NonCallableMock): - """ - Create a new `Mock` object. `Mock` takes several optional arguments - that specify the behaviour of the Mock object: - - * `spec`: This can be either a list of strings or an existing object (a - class or instance) that acts as the specification for the mock object. If - you pass in an object then a list of strings is formed by calling dir on - the object (excluding unsupported magic attributes and methods). Accessing - any attribute not in this list will raise an `AttributeError`. - - If `spec` is an object (rather than a list of strings) then - `mock.__class__` returns the class of the spec object. This allows mocks - to pass `isinstance` tests. - - * `spec_set`: A stricter variant of `spec`. If used, attempting to *set* - or get an attribute on the mock that isn't on the object passed as - `spec_set` will raise an `AttributeError`. - - * `side_effect`: A function to be called whenever the Mock is called. See - the `side_effect` attribute. Useful for raising exceptions or - dynamically changing return values. The function is called with the same - arguments as the mock, and unless it returns `DEFAULT`, the return - value of this function is used as the return value. - - Alternatively `side_effect` can be an exception class or instance. In - this case the exception will be raised when the mock is called. - - If `side_effect` is an iterable then each call to the mock will return - the next value from the iterable. If any of the members of the iterable - are exceptions they will be raised instead of returned. - - * `return_value`: The value returned when the mock is called. By default - this is a new Mock (created on first access). See the - `return_value` attribute. - - * `wraps`: Item for the mock object to wrap. If `wraps` is not None then - calling the Mock will pass the call through to the wrapped object - (returning the real result). Attribute access on the mock will return a - Mock object that wraps the corresponding attribute of the wrapped object - (so attempting to access an attribute that doesn't exist will raise an - `AttributeError`). - - If the mock has an explicit `return_value` set then calls are not passed - to the wrapped object and the `return_value` is returned instead. - - * `name`: If the mock has a name then it will be used in the repr of the - mock. This can be useful for debugging. The name is propagated to child - mocks. - - Mocks can also be called with arbitrary keyword arguments. These will be - used to set attributes on the mock after it is created. - """ - - - -def _dot_lookup(thing, comp, import_path): - try: - return getattr(thing, comp) - except AttributeError: - __import__(import_path) - return getattr(thing, comp) - - -def _importer(target): - components = target.split('.') - import_path = components.pop(0) - thing = __import__(import_path) - - for comp in components: - import_path += ".%s" % comp - thing = _dot_lookup(thing, comp, import_path) - return thing - - -def _is_started(patcher): - # XXXX horrible - return hasattr(patcher, 'is_local') - - -class _patch(object): - - attribute_name = None - _active_patches = set() - - def __init__( - self, getter, attribute, new, spec, create, - spec_set, autospec, new_callable, kwargs - ): - if new_callable is not None: - if new is not DEFAULT: - raise ValueError( - "Cannot use 'new' and 'new_callable' together" - ) - if autospec is not None: - raise ValueError( - "Cannot use 'autospec' and 'new_callable' together" - ) - - self.getter = getter - self.attribute = attribute - self.new = new - self.new_callable = new_callable - self.spec = spec - self.create = create - self.has_local = False - self.spec_set = spec_set - self.autospec = autospec - self.kwargs = kwargs - self.additional_patchers = [] - - - def copy(self): - patcher = _patch( - self.getter, self.attribute, self.new, self.spec, - self.create, self.spec_set, - self.autospec, self.new_callable, self.kwargs - ) - patcher.attribute_name = self.attribute_name - patcher.additional_patchers = [ - p.copy() for p in self.additional_patchers - ] - return patcher - - - def __call__(self, func): - if isinstance(func, ClassTypes): - return self.decorate_class(func) - return self.decorate_callable(func) - - - def decorate_class(self, klass): - for attr in dir(klass): - if not attr.startswith(patch.TEST_PREFIX): - continue - - attr_value = getattr(klass, attr) - if not hasattr(attr_value, "__call__"): - continue - - patcher = self.copy() - setattr(klass, attr, patcher(attr_value)) - return klass - - - def decorate_callable(self, func): - if hasattr(func, 'patchings'): - func.patchings.append(self) - return func - - @wraps(func) - def patched(*args, **keywargs): - # don't use a with here (backwards compatability with Python 2.4) - extra_args = [] - entered_patchers = [] - - # can't use try...except...finally because of Python 2.4 - # compatibility - exc_info = tuple() - try: - try: - for patching in patched.patchings: - arg = patching.__enter__() - entered_patchers.append(patching) - if patching.attribute_name is not None: - keywargs.update(arg) - elif patching.new is DEFAULT: - extra_args.append(arg) - - args += tuple(extra_args) - return func(*args, **keywargs) - except: - if (patching not in entered_patchers and - _is_started(patching)): - # the patcher may have been started, but an exception - # raised whilst entering one of its additional_patchers - entered_patchers.append(patching) - # Pass the exception to __exit__ - exc_info = sys.exc_info() - # re-raise the exception - raise - finally: - for patching in reversed(entered_patchers): - patching.__exit__(*exc_info) - - patched.patchings = [self] - if hasattr(func, 'func_code'): - # not in Python 3 - patched.compat_co_firstlineno = getattr( - func, "compat_co_firstlineno", - func.func_code.co_firstlineno - ) - return patched - - - def get_original(self): - target = self.getter() - name = self.attribute - - original = DEFAULT - local = False - - try: - original = target.__dict__[name] - except (AttributeError, KeyError): - original = getattr(target, name, DEFAULT) - else: - local = True - - if not self.create and original is DEFAULT: - raise AttributeError( - "%s does not have the attribute %r" % (target, name) - ) - return original, local - - - def __enter__(self): - """Perform the patch.""" - new, spec, spec_set = self.new, self.spec, self.spec_set - autospec, kwargs = self.autospec, self.kwargs - new_callable = self.new_callable - self.target = self.getter() - - # normalise False to None - if spec is False: - spec = None - if spec_set is False: - spec_set = None - if autospec is False: - autospec = None - - if spec is not None and autospec is not None: - raise TypeError("Can't specify spec and autospec") - if ((spec is not None or autospec is not None) and - spec_set not in (True, None)): - raise TypeError("Can't provide explicit spec_set *and* spec or autospec") - - original, local = self.get_original() - - if new is DEFAULT and autospec is None: - inherit = False - if spec is True: - # set spec to the object we are replacing - spec = original - if spec_set is True: - spec_set = original - spec = None - elif spec is not None: - if spec_set is True: - spec_set = spec - spec = None - elif spec_set is True: - spec_set = original - - if spec is not None or spec_set is not None: - if original is DEFAULT: - raise TypeError("Can't use 'spec' with create=True") - if isinstance(original, ClassTypes): - # If we're patching out a class and there is a spec - inherit = True - - Klass = MagicMock - _kwargs = {} - if new_callable is not None: - Klass = new_callable - elif spec is not None or spec_set is not None: - this_spec = spec - if spec_set is not None: - this_spec = spec_set - if _is_list(this_spec): - not_callable = '__call__' not in this_spec - else: - not_callable = not _callable(this_spec) - if not_callable: - Klass = NonCallableMagicMock - - if spec is not None: - _kwargs['spec'] = spec - if spec_set is not None: - _kwargs['spec_set'] = spec_set - - # add a name to mocks - if (isinstance(Klass, type) and - issubclass(Klass, NonCallableMock) and self.attribute): - _kwargs['name'] = self.attribute - - _kwargs.update(kwargs) - new = Klass(**_kwargs) - - if inherit and _is_instance_mock(new): - # we can only tell if the instance should be callable if the - # spec is not a list - this_spec = spec - if spec_set is not None: - this_spec = spec_set - if (not _is_list(this_spec) and not - _instance_callable(this_spec)): - Klass = NonCallableMagicMock - - _kwargs.pop('name') - new.return_value = Klass(_new_parent=new, _new_name='()', - **_kwargs) - elif autospec is not None: - # spec is ignored, new *must* be default, spec_set is treated - # as a boolean. Should we check spec is not None and that spec_set - # is a bool? - if new is not DEFAULT: - raise TypeError( - "autospec creates the mock for you. Can't specify " - "autospec and new." - ) - if original is DEFAULT: - raise TypeError("Can't use 'autospec' with create=True") - spec_set = bool(spec_set) - if autospec is True: - autospec = original - - new = create_autospec(autospec, spec_set=spec_set, - _name=self.attribute, **kwargs) - elif kwargs: - # can't set keyword args when we aren't creating the mock - # XXXX If new is a Mock we could call new.configure_mock(**kwargs) - raise TypeError("Can't pass kwargs to a mock we aren't creating") - - new_attr = new - - self.temp_original = original - self.is_local = local - setattr(self.target, self.attribute, new_attr) - if self.attribute_name is not None: - extra_args = {} - if self.new is DEFAULT: - extra_args[self.attribute_name] = new - for patching in self.additional_patchers: - arg = patching.__enter__() - if patching.new is DEFAULT: - extra_args.update(arg) - return extra_args - - return new - - - def __exit__(self, *exc_info): - """Undo the patch.""" - if not _is_started(self): - raise RuntimeError('stop called on unstarted patcher') - - if self.is_local and self.temp_original is not DEFAULT: - setattr(self.target, self.attribute, self.temp_original) - else: - delattr(self.target, self.attribute) - if not self.create and not hasattr(self.target, self.attribute): - # needed for proxy objects like django settings - setattr(self.target, self.attribute, self.temp_original) - - del self.temp_original - del self.is_local - del self.target - for patcher in reversed(self.additional_patchers): - if _is_started(patcher): - patcher.__exit__(*exc_info) - - - def start(self): - """Activate a patch, returning any created mock.""" - result = self.__enter__() - self._active_patches.add(self) - return result - - - def stop(self): - """Stop an active patch.""" - self._active_patches.discard(self) - return self.__exit__() - - - -def _get_target(target): - try: - target, attribute = target.rsplit('.', 1) - except (TypeError, ValueError): - raise TypeError("Need a valid target to patch. You supplied: %r" % - (target,)) - getter = lambda: _importer(target) - return getter, attribute - - -def _patch_object( - target, attribute, new=DEFAULT, spec=None, - create=False, spec_set=None, autospec=None, - new_callable=None, **kwargs - ): - """ - patch.object(target, attribute, new=DEFAULT, spec=None, create=False, - spec_set=None, autospec=None, new_callable=None, **kwargs) - - patch the named member (`attribute`) on an object (`target`) with a mock - object. - - `patch.object` can be used as a decorator, class decorator or a context - manager. Arguments `new`, `spec`, `create`, `spec_set`, - `autospec` and `new_callable` have the same meaning as for `patch`. Like - `patch`, `patch.object` takes arbitrary keyword arguments for configuring - the mock object it creates. - - When used as a class decorator `patch.object` honours `patch.TEST_PREFIX` - for choosing which methods to wrap. - """ - getter = lambda: target - return _patch( - getter, attribute, new, spec, create, - spec_set, autospec, new_callable, kwargs - ) - - -def _patch_multiple(target, spec=None, create=False, spec_set=None, - autospec=None, new_callable=None, **kwargs): - """Perform multiple patches in a single call. It takes the object to be - patched (either as an object or a string to fetch the object by importing) - and keyword arguments for the patches:: - - with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'): - ... - - Use `DEFAULT` as the value if you want `patch.multiple` to create - mocks for you. In this case the created mocks are passed into a decorated - function by keyword, and a dictionary is returned when `patch.multiple` is - used as a context manager. - - `patch.multiple` can be used as a decorator, class decorator or a context - manager. The arguments `spec`, `spec_set`, `create`, - `autospec` and `new_callable` have the same meaning as for `patch`. These - arguments will be applied to *all* patches done by `patch.multiple`. - - When used as a class decorator `patch.multiple` honours `patch.TEST_PREFIX` - for choosing which methods to wrap. - """ - if type(target) in (unicode, str): - getter = lambda: _importer(target) - else: - getter = lambda: target - - if not kwargs: - raise ValueError( - 'Must supply at least one keyword argument with patch.multiple' - ) - # need to wrap in a list for python 3, where items is a view - items = list(kwargs.items()) - attribute, new = items[0] - patcher = _patch( - getter, attribute, new, spec, create, spec_set, - autospec, new_callable, {} - ) - patcher.attribute_name = attribute - for attribute, new in items[1:]: - this_patcher = _patch( - getter, attribute, new, spec, create, spec_set, - autospec, new_callable, {} - ) - this_patcher.attribute_name = attribute - patcher.additional_patchers.append(this_patcher) - return patcher - - -def patch( - target, new=DEFAULT, spec=None, create=False, - spec_set=None, autospec=None, new_callable=None, **kwargs - ): - """ - `patch` acts as a function decorator, class decorator or a context - manager. Inside the body of the function or with statement, the `target` - is patched with a `new` object. When the function/with statement exits - the patch is undone. - - If `new` is omitted, then the target is replaced with a - `MagicMock`. If `patch` is used as a decorator and `new` is - omitted, the created mock is passed in as an extra argument to the - decorated function. If `patch` is used as a context manager the created - mock is returned by the context manager. - - `target` should be a string in the form `'package.module.ClassName'`. The - `target` is imported and the specified object replaced with the `new` - object, so the `target` must be importable from the environment you are - calling `patch` from. The target is imported when the decorated function - is executed, not at decoration time. - - The `spec` and `spec_set` keyword arguments are passed to the `MagicMock` - if patch is creating one for you. - - In addition you can pass `spec=True` or `spec_set=True`, which causes - patch to pass in the object being mocked as the spec/spec_set object. - - `new_callable` allows you to specify a different class, or callable object, - that will be called to create the `new` object. By default `MagicMock` is - used. - - A more powerful form of `spec` is `autospec`. If you set `autospec=True` - then the mock with be created with a spec from the object being replaced. - All attributes of the mock will also have the spec of the corresponding - attribute of the object being replaced. Methods and functions being - mocked will have their arguments checked and will raise a `TypeError` if - they are called with the wrong signature. For mocks replacing a class, - their return value (the 'instance') will have the same spec as the class. - - Instead of `autospec=True` you can pass `autospec=some_object` to use an - arbitrary object as the spec instead of the one being replaced. - - By default `patch` will fail to replace attributes that don't exist. If - you pass in `create=True`, and the attribute doesn't exist, patch will - create the attribute for you when the patched function is called, and - delete it again afterwards. This is useful for writing tests against - attributes that your production code creates at runtime. It is off by by - default because it can be dangerous. With it switched on you can write - passing tests against APIs that don't actually exist! - - Patch can be used as a `TestCase` class decorator. It works by - decorating each test method in the class. This reduces the boilerplate - code when your test methods share a common patchings set. `patch` finds - tests by looking for method names that start with `patch.TEST_PREFIX`. - By default this is `test`, which matches the way `unittest` finds tests. - You can specify an alternative prefix by setting `patch.TEST_PREFIX`. - - Patch can be used as a context manager, with the with statement. Here the - patching applies to the indented block after the with statement. If you - use "as" then the patched object will be bound to the name after the - "as"; very useful if `patch` is creating a mock object for you. - - `patch` takes arbitrary keyword arguments. These will be passed to - the `Mock` (or `new_callable`) on construction. - - `patch.dict(...)`, `patch.multiple(...)` and `patch.object(...)` are - available for alternate use-cases. - """ - getter, attribute = _get_target(target) - return _patch( - getter, attribute, new, spec, create, - spec_set, autospec, new_callable, kwargs - ) - - -class _patch_dict(object): - """ - Patch a dictionary, or dictionary like object, and restore the dictionary - to its original state after the test. - - `in_dict` can be a dictionary or a mapping like container. If it is a - mapping then it must at least support getting, setting and deleting items - plus iterating over keys. - - `in_dict` can also be a string specifying the name of the dictionary, which - will then be fetched by importing it. - - `values` can be a dictionary of values to set in the dictionary. `values` - can also be an iterable of `(key, value)` pairs. - - If `clear` is True then the dictionary will be cleared before the new - values are set. - - `patch.dict` can also be called with arbitrary keyword arguments to set - values in the dictionary:: - - with patch.dict('sys.modules', mymodule=Mock(), other_module=Mock()): - ... - - `patch.dict` can be used as a context manager, decorator or class - decorator. When used as a class decorator `patch.dict` honours - `patch.TEST_PREFIX` for choosing which methods to wrap. - """ - - def __init__(self, in_dict, values=(), clear=False, **kwargs): - if isinstance(in_dict, basestring): - in_dict = _importer(in_dict) - self.in_dict = in_dict - # support any argument supported by dict(...) constructor - self.values = dict(values) - self.values.update(kwargs) - self.clear = clear - self._original = None - - - def __call__(self, f): - if isinstance(f, ClassTypes): - return self.decorate_class(f) - @wraps(f) - def _inner(*args, **kw): - self._patch_dict() - try: - return f(*args, **kw) - finally: - self._unpatch_dict() - - return _inner - - - def decorate_class(self, klass): - for attr in dir(klass): - attr_value = getattr(klass, attr) - if (attr.startswith(patch.TEST_PREFIX) and - hasattr(attr_value, "__call__")): - decorator = _patch_dict(self.in_dict, self.values, self.clear) - decorated = decorator(attr_value) - setattr(klass, attr, decorated) - return klass - - - def __enter__(self): - """Patch the dict.""" - self._patch_dict() - - - def _patch_dict(self): - values = self.values - in_dict = self.in_dict - clear = self.clear - - try: - original = in_dict.copy() - except AttributeError: - # dict like object with no copy method - # must support iteration over keys - original = {} - for key in in_dict: - original[key] = in_dict[key] - self._original = original - - if clear: - _clear_dict(in_dict) - - try: - in_dict.update(values) - except AttributeError: - # dict like object with no update method - for key in values: - in_dict[key] = values[key] - - - def _unpatch_dict(self): - in_dict = self.in_dict - original = self._original - - _clear_dict(in_dict) - - try: - in_dict.update(original) - except AttributeError: - for key in original: - in_dict[key] = original[key] - - - def __exit__(self, *args): - """Unpatch the dict.""" - self._unpatch_dict() - return False - - start = __enter__ - stop = __exit__ - - -def _clear_dict(in_dict): - try: - in_dict.clear() - except AttributeError: - keys = list(in_dict) - for key in keys: - del in_dict[key] - - -def _patch_stopall(): - """Stop all active patches.""" - for patch in list(_patch._active_patches): - patch.stop() - - -patch.object = _patch_object -patch.dict = _patch_dict -patch.multiple = _patch_multiple -patch.stopall = _patch_stopall -patch.TEST_PREFIX = 'test' - -magic_methods = ( - "lt le gt ge eq ne " - "getitem setitem delitem " - "len contains iter " - "hash str sizeof " - "enter exit " - "divmod neg pos abs invert " - "complex int float index " - "trunc floor ceil " -) - -numerics = "add sub mul div floordiv mod lshift rshift and xor or pow " -inplace = ' '.join('i%s' % n for n in numerics.split()) -right = ' '.join('r%s' % n for n in numerics.split()) -extra = '' -if inPy3k: - extra = 'bool next ' -else: - extra = 'unicode long nonzero oct hex truediv rtruediv ' - -# not including __prepare__, __instancecheck__, __subclasscheck__ -# (as they are metaclass methods) -# __del__ is not supported at all as it causes problems if it exists - -_non_defaults = set('__%s__' % method for method in [ - 'cmp', 'getslice', 'setslice', 'coerce', 'subclasses', - 'format', 'get', 'set', 'delete', 'reversed', - 'missing', 'reduce', 'reduce_ex', 'getinitargs', - 'getnewargs', 'getstate', 'setstate', 'getformat', - 'setformat', 'repr', 'dir' -]) - - -def _get_method(name, func): - "Turns a callable object (like a mock) into a real function" - def method(self, *args, **kw): - return func(self, *args, **kw) - method.__name__ = name - return method - - -_magics = set( - '__%s__' % method for method in - ' '.join([magic_methods, numerics, inplace, right, extra]).split() -) - -_all_magics = _magics | _non_defaults - -_unsupported_magics = set([ - '__getattr__', '__setattr__', - '__init__', '__new__', '__prepare__' - '__instancecheck__', '__subclasscheck__', - '__del__' -]) - -_calculate_return_value = { - '__hash__': lambda self: object.__hash__(self), - '__str__': lambda self: object.__str__(self), - '__sizeof__': lambda self: object.__sizeof__(self), - '__unicode__': lambda self: unicode(object.__str__(self)), -} - -_return_values = { - '__lt__': NotImplemented, - '__gt__': NotImplemented, - '__le__': NotImplemented, - '__ge__': NotImplemented, - '__int__': 1, - '__contains__': False, - '__len__': 0, - '__exit__': False, - '__complex__': 1j, - '__float__': 1.0, - '__bool__': True, - '__nonzero__': True, - '__oct__': '1', - '__hex__': '0x1', - '__long__': long(1), - '__index__': 1, -} - - -def _get_eq(self): - def __eq__(other): - ret_val = self.__eq__._mock_return_value - if ret_val is not DEFAULT: - return ret_val - return self is other - return __eq__ - -def _get_ne(self): - def __ne__(other): - if self.__ne__._mock_return_value is not DEFAULT: - return DEFAULT - return self is not other - return __ne__ - -def _get_iter(self): - def __iter__(): - ret_val = self.__iter__._mock_return_value - if ret_val is DEFAULT: - return iter([]) - # if ret_val was already an iterator, then calling iter on it should - # return the iterator unchanged - return iter(ret_val) - return __iter__ - -_side_effect_methods = { - '__eq__': _get_eq, - '__ne__': _get_ne, - '__iter__': _get_iter, -} - - - -def _set_return_value(mock, method, name): - fixed = _return_values.get(name, DEFAULT) - if fixed is not DEFAULT: - method.return_value = fixed - return - - return_calulator = _calculate_return_value.get(name) - if return_calulator is not None: - try: - return_value = return_calulator(mock) - except AttributeError: - # XXXX why do we return AttributeError here? - # set it as a side_effect instead? - return_value = AttributeError(name) - method.return_value = return_value - return - - side_effector = _side_effect_methods.get(name) - if side_effector is not None: - method.side_effect = side_effector(mock) - - - -class MagicMixin(object): - def __init__(self, *args, **kw): - _super(MagicMixin, self).__init__(*args, **kw) - self._mock_set_magics() - - - def _mock_set_magics(self): - these_magics = _magics - - if self._mock_methods is not None: - these_magics = _magics.intersection(self._mock_methods) - - remove_magics = set() - remove_magics = _magics - these_magics - - for entry in remove_magics: - if entry in type(self).__dict__: - # remove unneeded magic methods - delattr(self, entry) - - # don't overwrite existing attributes if called a second time - these_magics = these_magics - set(type(self).__dict__) - - _type = type(self) - for entry in these_magics: - setattr(_type, entry, MagicProxy(entry, self)) - - - -class NonCallableMagicMock(MagicMixin, NonCallableMock): - """A version of `MagicMock` that isn't callable.""" - def mock_add_spec(self, spec, spec_set=False): - """Add a spec to a mock. `spec` can either be an object or a - list of strings. Only attributes on the `spec` can be fetched as - attributes from the mock. - - If `spec_set` is True then only attributes on the spec can be set.""" - self._mock_add_spec(spec, spec_set) - self._mock_set_magics() - - - -class MagicMock(MagicMixin, Mock): - """ - MagicMock is a subclass of Mock with default implementations - of most of the magic methods. You can use MagicMock without having to - configure the magic methods yourself. - - If you use the `spec` or `spec_set` arguments then *only* magic - methods that exist in the spec will be created. - - Attributes and the return value of a `MagicMock` will also be `MagicMocks`. - """ - def mock_add_spec(self, spec, spec_set=False): - """Add a spec to a mock. `spec` can either be an object or a - list of strings. Only attributes on the `spec` can be fetched as - attributes from the mock. - - If `spec_set` is True then only attributes on the spec can be set.""" - self._mock_add_spec(spec, spec_set) - self._mock_set_magics() - - - -class MagicProxy(object): - def __init__(self, name, parent): - self.name = name - self.parent = parent - - def __call__(self, *args, **kwargs): - m = self.create_mock() - return m(*args, **kwargs) - - def create_mock(self): - entry = self.name - parent = self.parent - m = parent._get_child_mock(name=entry, _new_name=entry, - _new_parent=parent) - setattr(parent, entry, m) - _set_return_value(parent, m, entry) - return m - - def __get__(self, obj, _type=None): - return self.create_mock() - - - -class _ANY(object): - "A helper object that compares equal to everything." - - def __eq__(self, other): - return True - - def __ne__(self, other): - return False - - def __repr__(self): - return '<ANY>' - -ANY = _ANY() - - - -def _format_call_signature(name, args, kwargs): - message = '%s(%%s)' % name - formatted_args = '' - args_string = ', '.join([repr(arg) for arg in args]) - kwargs_string = ', '.join([ - '%s=%r' % (key, value) for key, value in kwargs.items() - ]) - if args_string: - formatted_args = args_string - if kwargs_string: - if formatted_args: - formatted_args += ', ' - formatted_args += kwargs_string - - return message % formatted_args - - - -class _Call(tuple): - """ - A tuple for holding the results of a call to a mock, either in the form - `(args, kwargs)` or `(name, args, kwargs)`. - - If args or kwargs are empty then a call tuple will compare equal to - a tuple without those values. This makes comparisons less verbose:: - - _Call(('name', (), {})) == ('name',) - _Call(('name', (1,), {})) == ('name', (1,)) - _Call(((), {'a': 'b'})) == ({'a': 'b'},) - - The `_Call` object provides a useful shortcut for comparing with call:: - - _Call(((1, 2), {'a': 3})) == call(1, 2, a=3) - _Call(('foo', (1, 2), {'a': 3})) == call.foo(1, 2, a=3) - - If the _Call has no name then it will match any name. - """ - def __new__(cls, value=(), name=None, parent=None, two=False, - from_kall=True): - name = '' - args = () - kwargs = {} - _len = len(value) - if _len == 3: - name, args, kwargs = value - elif _len == 2: - first, second = value - if isinstance(first, basestring): - name = first - if isinstance(second, tuple): - args = second - else: - kwargs = second - else: - args, kwargs = first, second - elif _len == 1: - value, = value - if isinstance(value, basestring): - name = value - elif isinstance(value, tuple): - args = value - else: - kwargs = value - - if two: - return tuple.__new__(cls, (args, kwargs)) - - return tuple.__new__(cls, (name, args, kwargs)) - - - def __init__(self, value=(), name=None, parent=None, two=False, - from_kall=True): - self.name = name - self.parent = parent - self.from_kall = from_kall - - - def __eq__(self, other): - if other is ANY: - return True - try: - len_other = len(other) - except TypeError: - return False - - self_name = '' - if len(self) == 2: - self_args, self_kwargs = self - else: - self_name, self_args, self_kwargs = self - - other_name = '' - if len_other == 0: - other_args, other_kwargs = (), {} - elif len_other == 3: - other_name, other_args, other_kwargs = other - elif len_other == 1: - value, = other - if isinstance(value, tuple): - other_args = value - other_kwargs = {} - elif isinstance(value, basestring): - other_name = value - other_args, other_kwargs = (), {} - else: - other_args = () - other_kwargs = value - else: - # len 2 - # could be (name, args) or (name, kwargs) or (args, kwargs) - first, second = other - if isinstance(first, basestring): - other_name = first - if isinstance(second, tuple): - other_args, other_kwargs = second, {} - else: - other_args, other_kwargs = (), second - else: - other_args, other_kwargs = first, second - - if self_name and other_name != self_name: - return False - - # this order is important for ANY to work! - return (other_args, other_kwargs) == (self_args, self_kwargs) - - - def __ne__(self, other): - return not self.__eq__(other) - - - def __call__(self, *args, **kwargs): - if self.name is None: - return _Call(('', args, kwargs), name='()') - - name = self.name + '()' - return _Call((self.name, args, kwargs), name=name, parent=self) - - - def __getattr__(self, attr): - if self.name is None: - return _Call(name=attr, from_kall=False) - name = '%s.%s' % (self.name, attr) - return _Call(name=name, parent=self, from_kall=False) - - - def __repr__(self): - if not self.from_kall: - name = self.name or 'call' - if name.startswith('()'): - name = 'call%s' % name - return name - - if len(self) == 2: - name = 'call' - args, kwargs = self - else: - name, args, kwargs = self - if not name: - name = 'call' - elif not name.startswith('()'): - name = 'call.%s' % name - else: - name = 'call%s' % name - return _format_call_signature(name, args, kwargs) - - - def call_list(self): - """For a call object that represents multiple calls, `call_list` - returns a list of all the intermediate calls as well as the - final call.""" - vals = [] - thing = self - while thing is not None: - if thing.from_kall: - vals.append(thing) - thing = thing.parent - return _CallList(reversed(vals)) - - -call = _Call(from_kall=False) - - - -def create_autospec(spec, spec_set=False, instance=False, _parent=None, - _name=None, **kwargs): - """Create a mock object using another object as a spec. Attributes on the - mock will use the corresponding attribute on the `spec` object as their - spec. - - Functions or methods being mocked will have their arguments checked - to check that they are called with the correct signature. - - If `spec_set` is True then attempting to set attributes that don't exist - on the spec object will raise an `AttributeError`. - - If a class is used as a spec then the return value of the mock (the - instance of the class) will have the same spec. You can use a class as the - spec for an instance object by passing `instance=True`. The returned mock - will only be callable if instances of the mock are callable. - - `create_autospec` also takes arbitrary keyword arguments that are passed to - the constructor of the created mock.""" - if _is_list(spec): - # can't pass a list instance to the mock constructor as it will be - # interpreted as a list of strings - spec = type(spec) - - is_type = isinstance(spec, ClassTypes) - - _kwargs = {'spec': spec} - if spec_set: - _kwargs = {'spec_set': spec} - elif spec is None: - # None we mock with a normal mock without a spec - _kwargs = {} - - _kwargs.update(kwargs) - - Klass = MagicMock - if type(spec) in DescriptorTypes: - # descriptors don't have a spec - # because we don't know what type they return - _kwargs = {} - elif not _callable(spec): - Klass = NonCallableMagicMock - elif is_type and instance and not _instance_callable(spec): - Klass = NonCallableMagicMock - - _new_name = _name - if _parent is None: - # for a top level object no _new_name should be set - _new_name = '' - - mock = Klass(parent=_parent, _new_parent=_parent, _new_name=_new_name, - name=_name, **_kwargs) - - if isinstance(spec, FunctionTypes): - # should only happen at the top level because we don't - # recurse for functions - mock = _set_signature(mock, spec) - else: - _check_signature(spec, mock, is_type, instance) - - if _parent is not None and not instance: - _parent._mock_children[_name] = mock - - if is_type and not instance and 'return_value' not in kwargs: - mock.return_value = create_autospec(spec, spec_set, instance=True, - _name='()', _parent=mock) - - for entry in dir(spec): - if _is_magic(entry): - # MagicMock already does the useful magic methods for us - continue - - if isinstance(spec, FunctionTypes) and entry in FunctionAttributes: - # allow a mock to actually be a function - continue - - # XXXX do we need a better way of getting attributes without - # triggering code execution (?) Probably not - we need the actual - # object to mock it so we would rather trigger a property than mock - # the property descriptor. Likewise we want to mock out dynamically - # provided attributes. - # XXXX what about attributes that raise exceptions other than - # AttributeError on being fetched? - # we could be resilient against it, or catch and propagate the - # exception when the attribute is fetched from the mock - try: - original = getattr(spec, entry) - except AttributeError: - continue - - kwargs = {'spec': original} - if spec_set: - kwargs = {'spec_set': original} - - if not isinstance(original, FunctionTypes): - new = _SpecState(original, spec_set, mock, entry, instance) - mock._mock_children[entry] = new - else: - parent = mock - if isinstance(spec, FunctionTypes): - parent = mock.mock - - new = MagicMock(parent=parent, name=entry, _new_name=entry, - _new_parent=parent, **kwargs) - mock._mock_children[entry] = new - skipfirst = _must_skip(spec, entry, is_type) - _check_signature(original, new, skipfirst=skipfirst) - - # so functions created with _set_signature become instance attributes, - # *plus* their underlying mock exists in _mock_children of the parent - # mock. Adding to _mock_children may be unnecessary where we are also - # setting as an instance attribute? - if isinstance(new, FunctionTypes): - setattr(mock, entry, new) - - return mock - - -def _must_skip(spec, entry, is_type): - if not isinstance(spec, ClassTypes): - if entry in getattr(spec, '__dict__', {}): - # instance attribute - shouldn't skip - return False - spec = spec.__class__ - if not hasattr(spec, '__mro__'): - # old style class: can't have descriptors anyway - return is_type - - for klass in spec.__mro__: - result = klass.__dict__.get(entry, DEFAULT) - if result is DEFAULT: - continue - if isinstance(result, (staticmethod, classmethod)): - return False - return is_type - - # shouldn't get here unless function is a dynamically provided attribute - # XXXX untested behaviour - return is_type - - -def _get_class(obj): - try: - return obj.__class__ - except AttributeError: - # in Python 2, _sre.SRE_Pattern objects have no __class__ - return type(obj) - - -class _SpecState(object): - - def __init__(self, spec, spec_set=False, parent=None, - name=None, ids=None, instance=False): - self.spec = spec - self.ids = ids - self.spec_set = spec_set - self.parent = parent - self.instance = instance - self.name = name - - -FunctionTypes = ( - # python function - type(create_autospec), - # instance method - type(ANY.__eq__), - # unbound method - type(_ANY.__eq__), -) - -FunctionAttributes = set([ - 'func_closure', - 'func_code', - 'func_defaults', - 'func_dict', - 'func_doc', - 'func_globals', - 'func_name', -]) - - -file_spec = None - - -def mock_open(mock=None, read_data=''): - """ - A helper function to create a mock to replace the use of `open`. It works - for `open` called directly or used as a context manager. - - The `mock` argument is the mock object to configure. If `None` (the - default) then a `MagicMock` will be created for you, with the API limited - to methods or attributes available on standard file handles. - - `read_data` is a string for the `read` method of the file handle to return. - This is an empty string by default. - """ - global file_spec - if file_spec is None: - # set on first use - if inPy3k: - import _io - file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO)))) - else: - file_spec = file - - if mock is None: - mock = MagicMock(name='open', spec=open) - - handle = MagicMock(spec=file_spec) - handle.write.return_value = None - handle.__enter__.return_value = handle - handle.read.return_value = read_data - - mock.return_value = handle - return mock - - -class PropertyMock(Mock): - """ - A mock intended to be used as a property, or other descriptor, on a class. - `PropertyMock` provides `__get__` and `__set__` methods so you can specify - a return value when it is fetched. - - Fetching a `PropertyMock` instance from an object calls the mock, with - no args. Setting it calls the mock with the value being set. - """ - def _get_child_mock(self, **kwargs): - return MagicMock(**kwargs) - - def __get__(self, obj, obj_type): - return self() - def __set__(self, obj, val): - self(val) diff --git a/awx/lib/site-packages/mongoengine/__init__.py b/awx/lib/site-packages/mongoengine/__init__.py deleted file mode 100644 index b215181adc..0000000000 --- a/awx/lib/site-packages/mongoengine/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -import document -from document import * -import fields -from fields import * -import connection -from connection import * -import queryset -from queryset import * -import signals -from signals import * -from errors import * -import errors -import django - -__all__ = (list(document.__all__) + fields.__all__ + connection.__all__ + - list(queryset.__all__) + signals.__all__ + list(errors.__all__)) - -VERSION = (0, 9, 0) - - -def get_version(): - if isinstance(VERSION[-1], basestring): - return '.'.join(map(str, VERSION[:-1])) + VERSION[-1] - return '.'.join(map(str, VERSION)) - -__version__ = get_version() diff --git a/awx/lib/site-packages/mongoengine/base/__init__.py b/awx/lib/site-packages/mongoengine/base/__init__.py deleted file mode 100644 index e8d4b6ad96..0000000000 --- a/awx/lib/site-packages/mongoengine/base/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from mongoengine.base.common import * -from mongoengine.base.datastructures import * -from mongoengine.base.document import * -from mongoengine.base.fields import * -from mongoengine.base.metaclasses import * - -# Help with backwards compatibility -from mongoengine.errors import * diff --git a/awx/lib/site-packages/mongoengine/base/common.py b/awx/lib/site-packages/mongoengine/base/common.py deleted file mode 100644 index 3a966c792f..0000000000 --- a/awx/lib/site-packages/mongoengine/base/common.py +++ /dev/null @@ -1,26 +0,0 @@ -from mongoengine.errors import NotRegistered - -__all__ = ('ALLOW_INHERITANCE', 'get_document', '_document_registry') - -ALLOW_INHERITANCE = False - -_document_registry = {} - - -def get_document(name): - doc = _document_registry.get(name, None) - if not doc: - # Possible old style name - single_end = name.split('.')[-1] - compound_end = '.%s' % single_end - possible_match = [k for k in _document_registry.keys() - if k.endswith(compound_end) or k == single_end] - if len(possible_match) == 1: - doc = _document_registry.get(possible_match.pop(), None) - if not doc: - raise NotRegistered(""" - `%s` has not been registered in the document registry. - Importing the document class automatically registers it, has it - been imported? - """.strip() % name) - return doc diff --git a/awx/lib/site-packages/mongoengine/base/datastructures.py b/awx/lib/site-packages/mongoengine/base/datastructures.py deleted file mode 100644 index bac67ddca0..0000000000 --- a/awx/lib/site-packages/mongoengine/base/datastructures.py +++ /dev/null @@ -1,449 +0,0 @@ -import weakref -import functools -import itertools -from mongoengine.common import _import_class -from mongoengine.errors import DoesNotExist, MultipleObjectsReturned - -__all__ = ("BaseDict", "BaseList", "EmbeddedDocumentList") - - -class BaseDict(dict): - """A special dict so we can watch any changes""" - - _dereferenced = False - _instance = None - _name = None - - def __init__(self, dict_items, instance, name): - Document = _import_class('Document') - EmbeddedDocument = _import_class('EmbeddedDocument') - - if isinstance(instance, (Document, EmbeddedDocument)): - self._instance = weakref.proxy(instance) - self._name = name - return super(BaseDict, self).__init__(dict_items) - - def __getitem__(self, key, *args, **kwargs): - value = super(BaseDict, self).__getitem__(key) - - EmbeddedDocument = _import_class('EmbeddedDocument') - if isinstance(value, EmbeddedDocument) and value._instance is None: - value._instance = self._instance - elif not isinstance(value, BaseDict) and isinstance(value, dict): - value = BaseDict(value, None, '%s.%s' % (self._name, key)) - super(BaseDict, self).__setitem__(key, value) - value._instance = self._instance - elif not isinstance(value, BaseList) and isinstance(value, list): - value = BaseList(value, None, '%s.%s' % (self._name, key)) - super(BaseDict, self).__setitem__(key, value) - value._instance = self._instance - return value - - def __setitem__(self, key, value, *args, **kwargs): - self._mark_as_changed(key) - return super(BaseDict, self).__setitem__(key, value) - - def __delete__(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseDict, self).__delete__(*args, **kwargs) - - def __delitem__(self, key, *args, **kwargs): - self._mark_as_changed(key) - return super(BaseDict, self).__delitem__(key) - - def __delattr__(self, key, *args, **kwargs): - self._mark_as_changed(key) - return super(BaseDict, self).__delattr__(key) - - def __getstate__(self): - self.instance = None - self._dereferenced = False - return self - - def __setstate__(self, state): - self = state - return self - - def clear(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseDict, self).clear(*args, **kwargs) - - def pop(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseDict, self).pop(*args, **kwargs) - - def popitem(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseDict, self).popitem(*args, **kwargs) - - def setdefault(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseDict, self).setdefault(*args, **kwargs) - - def update(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseDict, self).update(*args, **kwargs) - - def _mark_as_changed(self, key=None): - if hasattr(self._instance, '_mark_as_changed'): - if key: - self._instance._mark_as_changed('%s.%s' % (self._name, key)) - else: - self._instance._mark_as_changed(self._name) - - -class BaseList(list): - """A special list so we can watch any changes - """ - - _dereferenced = False - _instance = None - _name = None - - def __init__(self, list_items, instance, name): - Document = _import_class('Document') - EmbeddedDocument = _import_class('EmbeddedDocument') - - if isinstance(instance, (Document, EmbeddedDocument)): - self._instance = weakref.proxy(instance) - self._name = name - super(BaseList, self).__init__(list_items) - - def __getitem__(self, key, *args, **kwargs): - value = super(BaseList, self).__getitem__(key) - - EmbeddedDocument = _import_class('EmbeddedDocument') - if isinstance(value, EmbeddedDocument) and value._instance is None: - value._instance = self._instance - elif not isinstance(value, BaseDict) and isinstance(value, dict): - value = BaseDict(value, None, '%s.%s' % (self._name, key)) - super(BaseList, self).__setitem__(key, value) - value._instance = self._instance - elif not isinstance(value, BaseList) and isinstance(value, list): - value = BaseList(value, None, '%s.%s' % (self._name, key)) - super(BaseList, self).__setitem__(key, value) - value._instance = self._instance - return value - - def __setitem__(self, key, value, *args, **kwargs): - if isinstance(key, slice): - self._mark_as_changed() - else: - self._mark_as_changed(key) - return super(BaseList, self).__setitem__(key, value) - - def __delitem__(self, key, *args, **kwargs): - if isinstance(key, slice): - self._mark_as_changed() - else: - self._mark_as_changed(key) - return super(BaseList, self).__delitem__(key) - - def __setslice__(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).__setslice__(*args, **kwargs) - - def __delslice__(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).__delslice__(*args, **kwargs) - - def __getstate__(self): - self.instance = None - self._dereferenced = False - return self - - def __setstate__(self, state): - self = state - return self - - def append(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).append(*args, **kwargs) - - def extend(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).extend(*args, **kwargs) - - def insert(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).insert(*args, **kwargs) - - def pop(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).pop(*args, **kwargs) - - def remove(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).remove(*args, **kwargs) - - def reverse(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).reverse(*args, **kwargs) - - def sort(self, *args, **kwargs): - self._mark_as_changed() - return super(BaseList, self).sort(*args, **kwargs) - - def _mark_as_changed(self, key=None): - if hasattr(self._instance, '_mark_as_changed'): - if key: - self._instance._mark_as_changed('%s.%s' % (self._name, key)) - else: - self._instance._mark_as_changed(self._name) - - -class EmbeddedDocumentList(BaseList): - - @classmethod - def __match_all(cls, i, kwargs): - items = kwargs.items() - return all([ - getattr(i, k) == v or str(getattr(i, k)) == v for k, v in items - ]) - - @classmethod - def __only_matches(cls, obj, kwargs): - if not kwargs: - return obj - return filter(lambda i: cls.__match_all(i, kwargs), obj) - - def __init__(self, list_items, instance, name): - super(EmbeddedDocumentList, self).__init__(list_items, instance, name) - self._instance = instance - - def filter(self, **kwargs): - """ - Filters the list by only including embedded documents with the - given keyword arguments. - - :param kwargs: The keyword arguments corresponding to the fields to - filter on. *Multiple arguments are treated as if they are ANDed - together.* - :return: A new ``EmbeddedDocumentList`` containing the matching - embedded documents. - - Raises ``AttributeError`` if a given keyword is not a valid field for - the embedded document class. - """ - values = self.__only_matches(self, kwargs) - return EmbeddedDocumentList(values, self._instance, self._name) - - def exclude(self, **kwargs): - """ - Filters the list by excluding embedded documents with the given - keyword arguments. - - :param kwargs: The keyword arguments corresponding to the fields to - exclude on. *Multiple arguments are treated as if they are ANDed - together.* - :return: A new ``EmbeddedDocumentList`` containing the non-matching - embedded documents. - - Raises ``AttributeError`` if a given keyword is not a valid field for - the embedded document class. - """ - exclude = self.__only_matches(self, kwargs) - values = [item for item in self if item not in exclude] - return EmbeddedDocumentList(values, self._instance, self._name) - - def count(self): - """ - The number of embedded documents in the list. - - :return: The length of the list, equivalent to the result of ``len()``. - """ - return len(self) - - def get(self, **kwargs): - """ - Retrieves an embedded document determined by the given keyword - arguments. - - :param kwargs: The keyword arguments corresponding to the fields to - search on. *Multiple arguments are treated as if they are ANDed - together.* - :return: The embedded document matched by the given keyword arguments. - - Raises ``DoesNotExist`` if the arguments used to query an embedded - document returns no results. ``MultipleObjectsReturned`` if more - than one result is returned. - """ - values = self.__only_matches(self, kwargs) - if len(values) == 0: - raise DoesNotExist( - "%s matching query does not exist." % self._name - ) - elif len(values) > 1: - raise MultipleObjectsReturned( - "%d items returned, instead of 1" % len(values) - ) - - return values[0] - - def first(self): - """ - Returns the first embedded document in the list, or ``None`` if empty. - """ - if len(self) > 0: - return self[0] - - def create(self, **values): - """ - Creates a new embedded document and saves it to the database. - - .. note:: - The embedded document changes are not automatically saved - to the database after calling this method. - - :param values: A dictionary of values for the embedded document. - :return: The new embedded document instance. - """ - name = self._name - EmbeddedClass = self._instance._fields[name].field.document_type_obj - self._instance[self._name].append(EmbeddedClass(**values)) - - return self._instance[self._name][-1] - - def save(self, *args, **kwargs): - """ - Saves the ancestor document. - - :param args: Arguments passed up to the ancestor Document's save - method. - :param kwargs: Keyword arguments passed up to the ancestor Document's - save method. - """ - self._instance.save(*args, **kwargs) - - def delete(self): - """ - Deletes the embedded documents from the database. - - .. note:: - The embedded document changes are not automatically saved - to the database after calling this method. - - :return: The number of entries deleted. - """ - values = list(self) - for item in values: - self._instance[self._name].remove(item) - - return len(values) - - def update(self, **update): - """ - Updates the embedded documents with the given update values. - - .. note:: - The embedded document changes are not automatically saved - to the database after calling this method. - - :param update: A dictionary of update values to apply to each - embedded document. - :return: The number of entries updated. - """ - if len(update) == 0: - return 0 - values = list(self) - for item in values: - for k, v in update.items(): - setattr(item, k, v) - - return len(values) - - -class StrictDict(object): - __slots__ = () - _special_fields = set(['get', 'pop', 'iteritems', 'items', 'keys', 'create']) - _classes = {} - def __init__(self, **kwargs): - for k,v in kwargs.iteritems(): - setattr(self, k, v) - def __getitem__(self, key): - key = '_reserved_' + key if key in self._special_fields else key - try: - return getattr(self, key) - except AttributeError: - raise KeyError(key) - def __setitem__(self, key, value): - key = '_reserved_' + key if key in self._special_fields else key - return setattr(self, key, value) - def __contains__(self, key): - return hasattr(self, key) - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - def pop(self, key, default=None): - v = self.get(key, default) - try: - delattr(self, key) - except AttributeError: - pass - return v - def iteritems(self): - for key in self: - yield key, self[key] - def items(self): - return [(k, self[k]) for k in iter(self)] - def keys(self): - return list(iter(self)) - def __iter__(self): - return (key for key in self.__slots__ if hasattr(self, key)) - def __len__(self): - return len(list(self.iteritems())) - def __eq__(self, other): - return self.items() == other.items() - def __neq__(self, other): - return self.items() != other.items() - - @classmethod - def create(cls, allowed_keys): - allowed_keys_tuple = tuple(('_reserved_' + k if k in cls._special_fields else k) for k in allowed_keys) - allowed_keys = frozenset(allowed_keys_tuple) - if allowed_keys not in cls._classes: - class SpecificStrictDict(cls): - __slots__ = allowed_keys_tuple - def __repr__(self): - return "{%s}" % ', '.join('"{0!s}": {0!r}'.format(k,v) for (k,v) in self.iteritems()) - cls._classes[allowed_keys] = SpecificStrictDict - return cls._classes[allowed_keys] - - -class SemiStrictDict(StrictDict): - __slots__ = ('_extras') - _classes = {} - def __getattr__(self, attr): - try: - super(SemiStrictDict, self).__getattr__(attr) - except AttributeError: - try: - return self.__getattribute__('_extras')[attr] - except KeyError as e: - raise AttributeError(e) - def __setattr__(self, attr, value): - try: - super(SemiStrictDict, self).__setattr__(attr, value) - except AttributeError: - try: - self._extras[attr] = value - except AttributeError: - self._extras = {attr: value} - - def __delattr__(self, attr): - try: - super(SemiStrictDict, self).__delattr__(attr) - except AttributeError: - try: - del self._extras[attr] - except KeyError as e: - raise AttributeError(e) - - def __iter__(self): - try: - extras_iter = iter(self.__getattribute__('_extras')) - except AttributeError: - extras_iter = () - return itertools.chain(super(SemiStrictDict, self).__iter__(), extras_iter) diff --git a/awx/lib/site-packages/mongoengine/base/document.py b/awx/lib/site-packages/mongoengine/base/document.py deleted file mode 100644 index bcd7617200..0000000000 --- a/awx/lib/site-packages/mongoengine/base/document.py +++ /dev/null @@ -1,999 +0,0 @@ -import copy -import operator -import numbers -from collections import Hashable -from functools import partial - -import pymongo -from bson import json_util, ObjectId -from bson.dbref import DBRef -from bson.son import SON - -from mongoengine import signals -from mongoengine.common import _import_class -from mongoengine.errors import (ValidationError, InvalidDocumentError, - LookUpError, FieldDoesNotExist) -from mongoengine.python_support import PY3, txt_type - -from mongoengine.base.common import get_document, ALLOW_INHERITANCE -from mongoengine.base.datastructures import ( - BaseDict, - BaseList, - EmbeddedDocumentList, - StrictDict, - SemiStrictDict -) -from mongoengine.base.fields import ComplexBaseField - -__all__ = ('BaseDocument', 'NON_FIELD_ERRORS') - -NON_FIELD_ERRORS = '__all__' - - -class BaseDocument(object): - __slots__ = ('_changed_fields', '_initialised', '_created', '_data', - '_dynamic_fields', '_auto_id_field', '_db_field_map', '__weakref__') - - _dynamic = False - _dynamic_lock = True - STRICT = False - - def __init__(self, *args, **values): - """ - Initialise a document or embedded document - - :param __auto_convert: Try and will cast python objects to Object types - :param values: A dictionary of values for the document - """ - self._initialised = False - self._created = True - if args: - # Combine positional arguments with named arguments. - # We only want named arguments. - field = iter(self._fields_ordered) - # If its an automatic id field then skip to the first defined field - if self._auto_id_field: - next(field) - for value in args: - name = next(field) - if name in values: - raise TypeError( - "Multiple values for keyword argument '" + name + "'") - values[name] = value - - __auto_convert = values.pop("__auto_convert", True) - - # 399: set default values only to fields loaded from DB - __only_fields = set(values.pop("__only_fields", values)) - - _created = values.pop("_created", True) - - signals.pre_init.send(self.__class__, document=self, values=values) - - # Check if there are undefined fields supplied, if so raise an - # Exception. - if not self._dynamic: - for var in values.keys(): - if var not in self._fields.keys() + ['id', 'pk', '_cls', '_text_score']: - msg = ( - "The field '{0}' does not exist on the document '{1}'" - ).format(var, self._class_name) - raise FieldDoesNotExist(msg) - - if self.STRICT and not self._dynamic: - self._data = StrictDict.create(allowed_keys=self._fields_ordered)() - else: - self._data = SemiStrictDict.create( - allowed_keys=self._fields_ordered)() - - self._data = {} - self._dynamic_fields = SON() - - # Assign default values to instance - for key, field in self._fields.iteritems(): - if self._db_field_map.get(key, key) in __only_fields: - continue - value = getattr(self, key, None) - setattr(self, key, value) - - if "_cls" not in values: - self._cls = self._class_name - - # Set passed values after initialisation - if self._dynamic: - dynamic_data = {} - for key, value in values.iteritems(): - if key in self._fields or key == '_id': - setattr(self, key, value) - elif self._dynamic: - dynamic_data[key] = value - else: - FileField = _import_class('FileField') - for key, value in values.iteritems(): - if key == '__auto_convert': - continue - key = self._reverse_db_field_map.get(key, key) - if key in self._fields or key in ('id', 'pk', '_cls'): - if __auto_convert and value is not None: - field = self._fields.get(key) - if field and not isinstance(field, FileField): - value = field.to_python(value) - setattr(self, key, value) - else: - self._data[key] = value - - # Set any get_fieldname_display methods - self.__set_field_display() - - if self._dynamic: - self._dynamic_lock = False - for key, value in dynamic_data.iteritems(): - setattr(self, key, value) - - # Flag initialised - self._initialised = True - self._created = _created - signals.post_init.send(self.__class__, document=self) - - def __delattr__(self, *args, **kwargs): - """Handle deletions of fields""" - field_name = args[0] - if field_name in self._fields: - default = self._fields[field_name].default - if callable(default): - default = default() - setattr(self, field_name, default) - else: - super(BaseDocument, self).__delattr__(*args, **kwargs) - - def __setattr__(self, name, value): - # Handle dynamic data only if an initialised dynamic document - if self._dynamic and not self._dynamic_lock: - - field = None - if not hasattr(self, name) and not name.startswith('_'): - DynamicField = _import_class("DynamicField") - field = DynamicField(db_field=name) - field.name = name - self._dynamic_fields[name] = field - self._fields_ordered += (name,) - - if not name.startswith('_'): - value = self.__expand_dynamic_values(name, value) - - # Handle marking data as changed - if name in self._dynamic_fields: - self._data[name] = value - if hasattr(self, '_changed_fields'): - self._mark_as_changed(name) - try: - self__created = self._created - except AttributeError: - self__created = True - - if (self._is_document and not self__created and - name in self._meta.get('shard_key', tuple()) and - self._data.get(name) != value): - OperationError = _import_class('OperationError') - msg = "Shard Keys are immutable. Tried to update %s" % name - raise OperationError(msg) - - try: - self__initialised = self._initialised - except AttributeError: - self__initialised = False - # Check if the user has created a new instance of a class - if (self._is_document and self__initialised - and self__created and name == self._meta['id_field']): - super(BaseDocument, self).__setattr__('_created', False) - - super(BaseDocument, self).__setattr__(name, value) - - def __getstate__(self): - data = {} - for k in ('_changed_fields', '_initialised', '_created', - '_dynamic_fields', '_fields_ordered'): - if hasattr(self, k): - data[k] = getattr(self, k) - data['_data'] = self.to_mongo() - return data - - def __setstate__(self, data): - if isinstance(data["_data"], SON): - data["_data"] = self.__class__._from_son(data["_data"])._data - for k in ('_changed_fields', '_initialised', '_created', '_data', - '_dynamic_fields'): - if k in data: - setattr(self, k, data[k]) - if '_fields_ordered' in data: - setattr(type(self), '_fields_ordered', data['_fields_ordered']) - dynamic_fields = data.get('_dynamic_fields') or SON() - for k in dynamic_fields.keys(): - setattr(self, k, data["_data"].get(k)) - - def __iter__(self): - return iter(self._fields_ordered) - - def __getitem__(self, name): - """Dictionary-style field access, return a field's value if present. - """ - try: - if name in self._fields_ordered: - return getattr(self, name) - except AttributeError: - pass - raise KeyError(name) - - def __setitem__(self, name, value): - """Dictionary-style field access, set a field's value. - """ - # Ensure that the field exists before settings its value - if not self._dynamic and name not in self._fields: - raise KeyError(name) - return setattr(self, name, value) - - def __contains__(self, name): - try: - val = getattr(self, name) - return val is not None - except AttributeError: - return False - - def __len__(self): - return len(self._data) - - def __repr__(self): - try: - u = self.__str__() - except (UnicodeEncodeError, UnicodeDecodeError): - u = '[Bad Unicode data]' - repr_type = str if u is None else type(u) - return repr_type('<%s: %s>' % (self.__class__.__name__, u)) - - def __str__(self): - if hasattr(self, '__unicode__'): - if PY3: - return self.__unicode__() - else: - return unicode(self).encode('utf-8') - return txt_type('%s object' % self.__class__.__name__) - - def __eq__(self, other): - if isinstance(other, self.__class__) and hasattr(other, 'id') and other.id is not None: - return self.id == other.id - if isinstance(other, DBRef): - return self._get_collection_name() == other.collection and self.id == other.id - if self.id is None: - return self is other - return False - - def __ne__(self, other): - return not self.__eq__(other) - - def __hash__(self): - if getattr(self, 'pk', None) is None: - # For new object - return super(BaseDocument, self).__hash__() - else: - return hash(self.pk) - - def clean(self): - """ - Hook for doing document level data cleaning before validation is run. - - Any ValidationError raised by this method will not be associated with - a particular field; it will have a special-case association with the - field defined by NON_FIELD_ERRORS. - """ - pass - - def get_text_score(self): - """ - Get text score from text query - """ - - if '_text_score' not in self._data: - raise InvalidDocumentError('This document is not originally built from a text query') - - return self._data['_text_score'] - - def to_mongo(self, use_db_field=True, fields=None): - """ - Return as SON data ready for use with MongoDB. - """ - if not fields: - fields = [] - - data = SON() - data["_id"] = None - data['_cls'] = self._class_name - EmbeddedDocumentField = _import_class("EmbeddedDocumentField") - # only root fields ['test1.a', 'test2'] => ['test1', 'test2'] - root_fields = set([f.split('.')[0] for f in fields]) - - for field_name in self: - if root_fields and field_name not in root_fields: - continue - - value = self._data.get(field_name, None) - field = self._fields.get(field_name) - - if field is None and self._dynamic: - field = self._dynamic_fields.get(field_name) - - if value is not None: - - if isinstance(field, (EmbeddedDocumentField)): - if fields: - key = '%s.' % field_name - embedded_fields = [ - i.replace(key, '') for i in fields - if i.startswith(key)] - - else: - embedded_fields = [] - - value = field.to_mongo(value, use_db_field=use_db_field, - fields=embedded_fields) - else: - value = field.to_mongo(value) - - # Handle self generating fields - if value is None and field._auto_gen: - value = field.generate() - self._data[field_name] = value - - if value is not None: - if use_db_field: - data[field.db_field] = value - else: - data[field.name] = value - - # If "_id" has not been set, then try and set it - Document = _import_class("Document") - if isinstance(self, Document): - if data["_id"] is None: - data["_id"] = self._data.get("id", None) - - if data['_id'] is None: - data.pop('_id') - - # Only add _cls if allow_inheritance is True - if (not hasattr(self, '_meta') or - not self._meta.get('allow_inheritance', ALLOW_INHERITANCE)): - data.pop('_cls') - - return data - - def validate(self, clean=True): - """Ensure that all fields' values are valid and that required fields - are present. - """ - # Ensure that each field is matched to a valid value - errors = {} - if clean: - try: - self.clean() - except ValidationError, error: - errors[NON_FIELD_ERRORS] = error - - # Get a list of tuples of field names and their current values - fields = [(self._fields.get(name, self._dynamic_fields.get(name)), - self._data.get(name)) for name in self._fields_ordered] - - EmbeddedDocumentField = _import_class("EmbeddedDocumentField") - GenericEmbeddedDocumentField = _import_class( - "GenericEmbeddedDocumentField") - - for field, value in fields: - if value is not None: - try: - if isinstance(field, (EmbeddedDocumentField, - GenericEmbeddedDocumentField)): - field._validate(value, clean=clean) - else: - field._validate(value) - except ValidationError, error: - errors[field.name] = error.errors or error - except (ValueError, AttributeError, AssertionError), error: - errors[field.name] = error - elif field.required and not getattr(field, '_auto_gen', False): - errors[field.name] = ValidationError('Field is required', - field_name=field.name) - - if errors: - pk = "None" - if hasattr(self, 'pk'): - pk = self.pk - elif self._instance and hasattr(self._instance, 'pk'): - pk = self._instance.pk - message = "ValidationError (%s:%s) " % (self._class_name, pk) - raise ValidationError(message, errors=errors) - - def to_json(self, *args, **kwargs): - """Converts a document to JSON. - :param use_db_field: Set to True by default but enables the output of the json structure with the field names and not the mongodb store db_names in case of set to False - """ - use_db_field = kwargs.pop('use_db_field', True) - return json_util.dumps(self.to_mongo(use_db_field), *args, **kwargs) - - @classmethod - def from_json(cls, json_data, created=False): - """Converts json data to an unsaved document instance""" - return cls._from_son(json_util.loads(json_data), created=created) - - def __expand_dynamic_values(self, name, value): - """expand any dynamic values to their correct types / values""" - if not isinstance(value, (dict, list, tuple)): - return value - - EmbeddedDocumentListField = _import_class('EmbeddedDocumentListField') - - is_list = False - if not hasattr(value, 'items'): - is_list = True - value = dict([(k, v) for k, v in enumerate(value)]) - - if not is_list and '_cls' in value: - cls = get_document(value['_cls']) - return cls(**value) - - data = {} - for k, v in value.items(): - key = name if is_list else k - data[k] = self.__expand_dynamic_values(key, v) - - if is_list: # Convert back to a list - data_items = sorted(data.items(), key=operator.itemgetter(0)) - value = [v for k, v in data_items] - else: - value = data - - # Convert lists / values so we can watch for any changes on them - if (isinstance(value, (list, tuple)) and - not isinstance(value, BaseList)): - if issubclass(type(self), EmbeddedDocumentListField): - value = EmbeddedDocumentList(value, self, name) - else: - value = BaseList(value, self, name) - elif isinstance(value, dict) and not isinstance(value, BaseDict): - value = BaseDict(value, self, name) - - return value - - def _mark_as_changed(self, key): - """Marks a key as explicitly changed by the user - """ - if not key: - return - - if not hasattr(self, '_changed_fields'): - return - - if '.' in key: - key, rest = key.split('.', 1) - key = self._db_field_map.get(key, key) - key = '%s.%s' % (key, rest) - else: - key = self._db_field_map.get(key, key) - - if key not in self._changed_fields: - self._changed_fields.append(key) - - def _clear_changed_fields(self): - """Using get_changed_fields iterate and remove any fields that are - marked as changed""" - for changed in self._get_changed_fields(): - parts = changed.split(".") - data = self - for part in parts: - if isinstance(data, list): - try: - data = data[int(part)] - except IndexError: - data = None - elif isinstance(data, dict): - data = data.get(part, None) - else: - data = getattr(data, part, None) - if hasattr(data, "_changed_fields"): - if hasattr(data, "_is_document") and data._is_document: - continue - data._changed_fields = [] - self._changed_fields = [] - - def _nestable_types_changed_fields(self, changed_fields, key, data, inspected): - # Loop list / dict fields as they contain documents - # Determine the iterator to use - if not hasattr(data, 'items'): - iterator = enumerate(data) - else: - iterator = data.iteritems() - - for index, value in iterator: - list_key = "%s%s." % (key, index) - # don't check anything lower if this key is already marked - # as changed. - if list_key[:-1] in changed_fields: - continue - if hasattr(value, '_get_changed_fields'): - changed = value._get_changed_fields(inspected) - changed_fields += ["%s%s" % (list_key, k) - for k in changed if k] - elif isinstance(value, (list, tuple, dict)): - self._nestable_types_changed_fields( - changed_fields, list_key, value, inspected) - - def _get_changed_fields(self, inspected=None): - """Returns a list of all fields that have explicitly been changed. - """ - EmbeddedDocument = _import_class("EmbeddedDocument") - DynamicEmbeddedDocument = _import_class("DynamicEmbeddedDocument") - ReferenceField = _import_class("ReferenceField") - changed_fields = [] - changed_fields += getattr(self, '_changed_fields', []) - - inspected = inspected or set() - if hasattr(self, 'id') and isinstance(self.id, Hashable): - if self.id in inspected: - return changed_fields - inspected.add(self.id) - - for field_name in self._fields_ordered: - db_field_name = self._db_field_map.get(field_name, field_name) - key = '%s.' % db_field_name - data = self._data.get(field_name, None) - field = self._fields.get(field_name) - - if hasattr(data, 'id'): - if data.id in inspected: - continue - inspected.add(data.id) - if isinstance(field, ReferenceField): - continue - elif (isinstance(data, (EmbeddedDocument, DynamicEmbeddedDocument)) - and db_field_name not in changed_fields): - # Find all embedded fields that have been changed - changed = data._get_changed_fields(inspected) - changed_fields += ["%s%s" % (key, k) for k in changed if k] - elif (isinstance(data, (list, tuple, dict)) and - db_field_name not in changed_fields): - if (hasattr(field, 'field') and - isinstance(field.field, ReferenceField)): - continue - self._nestable_types_changed_fields( - changed_fields, key, data, inspected) - return changed_fields - - def _delta(self): - """Returns the delta (set, unset) of the changes for a document. - Gets any values that have been explicitly changed. - """ - # Handles cases where not loaded from_son but has _id - doc = self.to_mongo() - - set_fields = self._get_changed_fields() - unset_data = {} - parts = [] - if hasattr(self, '_changed_fields'): - set_data = {} - # Fetch each set item from its path - for path in set_fields: - parts = path.split('.') - d = doc - new_path = [] - for p in parts: - if isinstance(d, (ObjectId, DBRef)): - break - elif isinstance(d, list) and p.isdigit(): - try: - d = d[int(p)] - except IndexError: - d = None - elif hasattr(d, 'get'): - d = d.get(p) - new_path.append(p) - path = '.'.join(new_path) - set_data[path] = d - else: - set_data = doc - if '_id' in set_data: - del(set_data['_id']) - - # Determine if any changed items were actually unset. - for path, value in set_data.items(): - if value or isinstance(value, (numbers.Number, bool)): - continue - - # If we've set a value that ain't the default value dont unset it. - default = None - if (self._dynamic and len(parts) and parts[0] in - self._dynamic_fields): - del(set_data[path]) - unset_data[path] = 1 - continue - elif path in self._fields: - default = self._fields[path].default - else: # Perform a full lookup for lists / embedded lookups - d = self - parts = path.split('.') - db_field_name = parts.pop() - for p in parts: - if isinstance(d, list) and p.isdigit(): - d = d[int(p)] - elif (hasattr(d, '__getattribute__') and - not isinstance(d, dict)): - real_path = d._reverse_db_field_map.get(p, p) - d = getattr(d, real_path) - else: - d = d.get(p) - - if hasattr(d, '_fields'): - field_name = d._reverse_db_field_map.get(db_field_name, - db_field_name) - if field_name in d._fields: - default = d._fields.get(field_name).default - else: - default = None - - if default is not None: - if callable(default): - default = default() - - if default != value: - continue - - del(set_data[path]) - unset_data[path] = 1 - return set_data, unset_data - - @classmethod - def _get_collection_name(cls): - """Returns the collection name for this class. - """ - return cls._meta.get('collection', None) - - @classmethod - def _from_son(cls, son, _auto_dereference=True, only_fields=None, created=False): - """Create an instance of a Document (subclass) from a PyMongo SON. - """ - if not only_fields: - only_fields = [] - - # get the class name from the document, falling back to the given - # class if unavailable - class_name = son.get('_cls', cls._class_name) - data = dict(("%s" % key, value) for key, value in son.iteritems()) - - # Return correct subclass for document type - if class_name != cls._class_name: - cls = get_document(class_name) - - changed_fields = [] - errors_dict = {} - - fields = cls._fields - if not _auto_dereference: - fields = copy.copy(fields) - - for field_name, field in fields.iteritems(): - field._auto_dereference = _auto_dereference - if field.db_field in data: - value = data[field.db_field] - try: - data[field_name] = (value if value is None - else field.to_python(value)) - if field_name != field.db_field: - del data[field.db_field] - except (AttributeError, ValueError), e: - errors_dict[field_name] = e - elif field.default: - default = field.default - if callable(default): - default = default() - if isinstance(default, BaseDocument): - changed_fields.append(field_name) - elif not only_fields or field_name in only_fields: - changed_fields.append(field_name) - - if errors_dict: - errors = "\n".join(["%s - %s" % (k, v) - for k, v in errors_dict.items()]) - msg = ("Invalid data to create a `%s` instance.\n%s" - % (cls._class_name, errors)) - raise InvalidDocumentError(msg) - - if cls.STRICT: - data = dict((k, v) - for k, v in data.iteritems() if k in cls._fields) - obj = cls(__auto_convert=False, _created=created, __only_fields=only_fields, **data) - obj._changed_fields = changed_fields - if not _auto_dereference: - obj._fields = fields - - return obj - - @classmethod - def _build_index_specs(cls, meta_indexes): - """Generate and merge the full index specs - """ - - geo_indices = cls._geo_indices() - unique_indices = cls._unique_with_indexes() - index_specs = [cls._build_index_spec(spec) - for spec in meta_indexes] - - def merge_index_specs(index_specs, indices): - if not indices: - return index_specs - - spec_fields = [v['fields'] - for k, v in enumerate(index_specs)] - # Merge unique_indexes with existing specs - for k, v in enumerate(indices): - if v['fields'] in spec_fields: - index_specs[spec_fields.index(v['fields'])].update(v) - else: - index_specs.append(v) - return index_specs - - index_specs = merge_index_specs(index_specs, geo_indices) - index_specs = merge_index_specs(index_specs, unique_indices) - return index_specs - - @classmethod - def _build_index_spec(cls, spec): - """Build a PyMongo index spec from a MongoEngine index spec. - """ - if isinstance(spec, basestring): - spec = {'fields': [spec]} - elif isinstance(spec, (list, tuple)): - spec = {'fields': list(spec)} - elif isinstance(spec, dict): - spec = dict(spec) - - index_list = [] - direction = None - - # Check to see if we need to include _cls - allow_inheritance = cls._meta.get('allow_inheritance', - ALLOW_INHERITANCE) - include_cls = (allow_inheritance and not spec.get('sparse', False) and - spec.get('cls', True)) - - # 733: don't include cls if index_cls is False unless there is an explicit cls with the index - include_cls = include_cls and (spec.get('cls', False) or cls._meta.get('index_cls', True)) - if "cls" in spec: - spec.pop('cls') - for key in spec['fields']: - # If inherited spec continue - if isinstance(key, (list, tuple)): - continue - - # ASCENDING from + - # DESCENDING from - - # GEO2D from * - # TEXT from $ - direction = pymongo.ASCENDING - if key.startswith("-"): - direction = pymongo.DESCENDING - elif key.startswith("*"): - direction = pymongo.GEO2D - elif key.startswith("$"): - direction = pymongo.TEXT - if key.startswith(("+", "-", "*", "$")): - key = key[1:] - - # Use real field name, do it manually because we need field - # objects for the next part (list field checking) - parts = key.split('.') - if parts in (['pk'], ['id'], ['_id']): - key = '_id' - fields = [] - else: - fields = cls._lookup_field(parts) - parts = [] - for field in fields: - try: - if field != "_id": - field = field.db_field - except AttributeError: - pass - parts.append(field) - key = '.'.join(parts) - index_list.append((key, direction)) - - # Don't add cls to a geo index - if include_cls and direction is not pymongo.GEO2D: - index_list.insert(0, ('_cls', 1)) - - if index_list: - spec['fields'] = index_list - if spec.get('sparse', False) and len(spec['fields']) > 1: - raise ValueError( - 'Sparse indexes can only have one field in them. ' - 'See https://jira.mongodb.org/browse/SERVER-2193') - - return spec - - @classmethod - def _unique_with_indexes(cls, namespace=""): - """ - Find and set unique indexes - """ - unique_indexes = [] - for field_name, field in cls._fields.items(): - sparse = field.sparse - # Generate a list of indexes needed by uniqueness constraints - if field.unique: - unique_fields = [field.db_field] - - # Add any unique_with fields to the back of the index spec - if field.unique_with: - if isinstance(field.unique_with, basestring): - field.unique_with = [field.unique_with] - - # Convert unique_with field names to real field names - unique_with = [] - for other_name in field.unique_with: - parts = other_name.split('.') - # Lookup real name - parts = cls._lookup_field(parts) - name_parts = [part.db_field for part in parts] - unique_with.append('.'.join(name_parts)) - # Unique field should be required - parts[-1].required = True - sparse = (not sparse and - parts[-1].name not in cls.__dict__) - unique_fields += unique_with - - # Add the new index to the list - fields = [("%s%s" % (namespace, f), pymongo.ASCENDING) - for f in unique_fields] - index = {'fields': fields, 'unique': True, 'sparse': sparse} - unique_indexes.append(index) - - if field.__class__.__name__ == "ListField": - field = field.field - - # Grab any embedded document field unique indexes - if (field.__class__.__name__ == "EmbeddedDocumentField" and - field.document_type != cls): - field_namespace = "%s." % field_name - doc_cls = field.document_type - unique_indexes += doc_cls._unique_with_indexes(field_namespace) - - return unique_indexes - - @classmethod - def _geo_indices(cls, inspected=None, parent_field=None): - inspected = inspected or [] - geo_indices = [] - inspected.append(cls) - - geo_field_type_names = ["EmbeddedDocumentField", "GeoPointField", - "PointField", "LineStringField", "PolygonField"] - - geo_field_types = tuple([_import_class(field) - for field in geo_field_type_names]) - - for field in cls._fields.values(): - if not isinstance(field, geo_field_types): - continue - if hasattr(field, 'document_type'): - field_cls = field.document_type - if field_cls in inspected: - continue - if hasattr(field_cls, '_geo_indices'): - geo_indices += field_cls._geo_indices( - inspected, parent_field=field.db_field) - elif field._geo_index: - field_name = field.db_field - if parent_field: - field_name = "%s.%s" % (parent_field, field_name) - geo_indices.append({'fields': - [(field_name, field._geo_index)]}) - return geo_indices - - @classmethod - def _lookup_field(cls, parts): - """Lookup a field based on its attribute and return a list containing - the field's parents and the field. - """ - - ListField = _import_class("ListField") - - if not isinstance(parts, (list, tuple)): - parts = [parts] - fields = [] - field = None - - for field_name in parts: - # Handle ListField indexing: - if field_name.isdigit() and isinstance(field, ListField): - new_field = field.field - fields.append(field_name) - continue - - if field is None: - # Look up first field from the document - if field_name == 'pk': - # Deal with "primary key" alias - field_name = cls._meta['id_field'] - if field_name in cls._fields: - field = cls._fields[field_name] - elif cls._dynamic: - DynamicField = _import_class('DynamicField') - field = DynamicField(db_field=field_name) - elif cls._meta.get("allow_inheritance", False) or cls._meta.get("abstract", False): - # 744: in case the field is defined in a subclass - field = None - for subcls in cls.__subclasses__(): - try: - field = subcls._lookup_field([field_name])[0] - except LookUpError: - continue - - if field is not None: - break - else: - raise LookUpError('Cannot resolve field "%s"' % field_name) - else: - raise LookUpError('Cannot resolve field "%s"' - % field_name) - else: - ReferenceField = _import_class('ReferenceField') - GenericReferenceField = _import_class('GenericReferenceField') - if isinstance(field, (ReferenceField, GenericReferenceField)): - raise LookUpError('Cannot perform join in mongoDB: %s' % - '__'.join(parts)) - if hasattr(getattr(field, 'field', None), 'lookup_member'): - new_field = field.field.lookup_member(field_name) - else: - # Look up subfield on the previous field - new_field = field.lookup_member(field_name) - if not new_field and isinstance(field, ComplexBaseField): - if hasattr(field.field, 'document_type') and cls._dynamic \ - and field.field.document_type._dynamic: - DynamicField = _import_class('DynamicField') - new_field = DynamicField(db_field=field_name) - else: - fields.append(field_name) - continue - elif not new_field and hasattr(field, 'document_type') and cls._dynamic \ - and field.document_type._dynamic: - DynamicField = _import_class('DynamicField') - new_field = DynamicField(db_field=field_name) - elif not new_field: - raise LookUpError('Cannot resolve field "%s"' - % field_name) - field = new_field # update field to the new field type - fields.append(field) - return fields - - @classmethod - def _translate_field_name(cls, field, sep='.'): - """Translate a field attribute name to a database field name. - """ - parts = field.split(sep) - parts = [f.db_field for f in cls._lookup_field(parts)] - return '.'.join(parts) - - def __set_field_display(self): - """Dynamically set the display value for a field with choices""" - for attr_name, field in self._fields.items(): - if field.choices: - if self._dynamic: - obj = self - else: - obj = type(self) - setattr(obj, - 'get_%s_display' % attr_name, - partial(self.__get_field_display, field=field)) - - def __get_field_display(self, field): - """Returns the display value for a choice field""" - value = getattr(self, field.name) - if field.choices and isinstance(field.choices[0], (list, tuple)): - return dict(field.choices).get(value, value) - return value diff --git a/awx/lib/site-packages/mongoengine/base/fields.py b/awx/lib/site-packages/mongoengine/base/fields.py deleted file mode 100644 index aa16804e61..0000000000 --- a/awx/lib/site-packages/mongoengine/base/fields.py +++ /dev/null @@ -1,596 +0,0 @@ -import operator -import warnings -import weakref - -from bson import DBRef, ObjectId, SON -import pymongo - -from mongoengine.common import _import_class -from mongoengine.errors import ValidationError - -from mongoengine.base.common import ALLOW_INHERITANCE -from mongoengine.base.datastructures import ( - BaseDict, BaseList, EmbeddedDocumentList -) - -__all__ = ("BaseField", "ComplexBaseField", - "ObjectIdField", "GeoJsonBaseField") - - -class BaseField(object): - - """A base class for fields in a MongoDB document. Instances of this class - may be added to subclasses of `Document` to define a document's schema. - - .. versionchanged:: 0.5 - added verbose and help text - """ - - name = None - _geo_index = False - _auto_gen = False # Call `generate` to generate a value - _auto_dereference = True - - # These track each time a Field instance is created. Used to retain order. - # The auto_creation_counter is used for fields that MongoEngine implicitly - # creates, creation_counter is used for all user-specified fields. - creation_counter = 0 - auto_creation_counter = -1 - - def __init__(self, db_field=None, name=None, required=False, default=None, - unique=False, unique_with=None, primary_key=False, - validation=None, choices=None, verbose_name=None, - help_text=None, null=False, sparse=False): - """ - :param db_field: The database field to store this field in - (defaults to the name of the field) - :param name: Depreciated - use db_field - :param required: If the field is required. Whether it has to have a - value or not. Defaults to False. - :param default: (optional) The default value for this field if no value - has been set (or if the value has been unset). It can be a - callable. - :param unique: Is the field value unique or not. Defaults to False. - :param unique_with: (optional) The other field this field should be - unique with. - :param primary_key: Mark this field as the primary key. Defaults to False. - :param validation: (optional) A callable to validate the value of the - field. Generally this is deprecated in favour of the - `FIELD.validate` method - :param choices: (optional) The valid choices - :param verbose_name: (optional) The verbose name for the field. - Designed to be human readable and is often used when generating - model forms from the document model. - :param help_text: (optional) The help text for this field and is often - used when generating model forms from the document model. - :param null: (optional) Is the field value can be null. If no and there is a default value - then the default value is set - :param sparse: (optional) `sparse=True` combined with `unique=True` and `required=False` - means that uniqueness won't be enforced for `None` values - """ - self.db_field = (db_field or name) if not primary_key else '_id' - - if name: - msg = "Fields' 'name' attribute deprecated in favour of 'db_field'" - warnings.warn(msg, DeprecationWarning) - self.required = required or primary_key - self.default = default - self.unique = bool(unique or unique_with) - self.unique_with = unique_with - self.primary_key = primary_key - self.validation = validation - self.choices = choices - self.verbose_name = verbose_name - self.help_text = help_text - self.null = null - self.sparse = sparse - - # Adjust the appropriate creation counter, and save our local copy. - if self.db_field == '_id': - self.creation_counter = BaseField.auto_creation_counter - BaseField.auto_creation_counter -= 1 - else: - self.creation_counter = BaseField.creation_counter - BaseField.creation_counter += 1 - - def __get__(self, instance, owner): - """Descriptor for retrieving a value from a field in a document. - """ - if instance is None: - # Document class being used rather than a document object - return self - - # Get value from document instance if available - return instance._data.get(self.name) - - def __set__(self, instance, value): - """Descriptor for assigning a value to a field in a document. - """ - - # If setting to None and theres a default - # Then set the value to the default value - if value is None: - if self.null: - value = None - elif self.default is not None: - value = self.default - if callable(value): - value = value() - - if instance._initialised: - try: - if (self.name not in instance._data or - instance._data[self.name] != value): - instance._mark_as_changed(self.name) - except: - # Values cant be compared eg: naive and tz datetimes - # So mark it as changed - instance._mark_as_changed(self.name) - - EmbeddedDocument = _import_class('EmbeddedDocument') - if isinstance(value, EmbeddedDocument): - value._instance = weakref.proxy(instance) - instance._data[self.name] = value - - def error(self, message="", errors=None, field_name=None): - """Raises a ValidationError. - """ - field_name = field_name if field_name else self.name - raise ValidationError(message, errors=errors, field_name=field_name) - - def to_python(self, value): - """Convert a MongoDB-compatible type to a Python type. - """ - return value - - def to_mongo(self, value): - """Convert a Python type to a MongoDB-compatible type. - """ - return self.to_python(value) - - def prepare_query_value(self, op, value): - """Prepare a value that is being used in a query for PyMongo. - """ - return value - - def validate(self, value, clean=True): - """Perform validation on a value. - """ - pass - - def _validate(self, value, **kwargs): - Document = _import_class('Document') - EmbeddedDocument = _import_class('EmbeddedDocument') - - # Check the Choices Constraint - if self.choices: - - choice_list = self.choices - if isinstance(self.choices[0], (list, tuple)): - choice_list = [k for k, v in self.choices] - - # Choices which are other types of Documents - if isinstance(value, (Document, EmbeddedDocument)): - if not any(isinstance(value, c) for c in choice_list): - self.error( - 'Value must be instance of %s' % unicode(choice_list) - ) - # Choices which are types other than Documents - elif value not in choice_list: - self.error('Value must be one of %s' % unicode(choice_list)) - - # check validation argument - if self.validation is not None: - if callable(self.validation): - if not self.validation(value): - self.error('Value does not match custom validation method') - else: - raise ValueError('validation argument for "%s" must be a ' - 'callable.' % self.name) - - self.validate(value, **kwargs) - - -class ComplexBaseField(BaseField): - - """Handles complex fields, such as lists / dictionaries. - - Allows for nesting of embedded documents inside complex types. - Handles the lazy dereferencing of a queryset by lazily dereferencing all - items in a list / dict rather than one at a time. - - .. versionadded:: 0.5 - """ - - field = None - - def __get__(self, instance, owner): - """Descriptor to automatically dereference references. - """ - if instance is None: - # Document class being used rather than a document object - return self - - ReferenceField = _import_class('ReferenceField') - GenericReferenceField = _import_class('GenericReferenceField') - EmbeddedDocumentListField = _import_class('EmbeddedDocumentListField') - dereference = (self._auto_dereference and - (self.field is None or isinstance(self.field, - (GenericReferenceField, ReferenceField)))) - - _dereference = _import_class("DeReference")() - - self._auto_dereference = instance._fields[self.name]._auto_dereference - if instance._initialised and dereference and instance._data.get(self.name): - instance._data[self.name] = _dereference( - instance._data.get(self.name), max_depth=1, instance=instance, - name=self.name - ) - - value = super(ComplexBaseField, self).__get__(instance, owner) - - # Convert lists / values so we can watch for any changes on them - if isinstance(value, (list, tuple)): - if (issubclass(type(self), EmbeddedDocumentListField) and - not isinstance(value, EmbeddedDocumentList)): - value = EmbeddedDocumentList(value, instance, self.name) - elif not isinstance(value, BaseList): - value = BaseList(value, instance, self.name) - instance._data[self.name] = value - elif isinstance(value, dict) and not isinstance(value, BaseDict): - value = BaseDict(value, instance, self.name) - instance._data[self.name] = value - - if (self._auto_dereference and instance._initialised and - isinstance(value, (BaseList, BaseDict)) - and not value._dereferenced): - value = _dereference( - value, max_depth=1, instance=instance, name=self.name - ) - value._dereferenced = True - instance._data[self.name] = value - - return value - - def to_python(self, value): - """Convert a MongoDB-compatible type to a Python type. - """ - Document = _import_class('Document') - - if isinstance(value, basestring): - return value - - if hasattr(value, 'to_python'): - return value.to_python() - - is_list = False - if not hasattr(value, 'items'): - try: - is_list = True - value = dict([(k, v) for k, v in enumerate(value)]) - except TypeError: # Not iterable return the value - return value - - if self.field: - value_dict = dict([(key, self.field.to_python(item)) - for key, item in value.items()]) - else: - value_dict = {} - for k, v in value.items(): - if isinstance(v, Document): - # We need the id from the saved object to create the DBRef - if v.pk is None: - self.error('You can only reference documents once they' - ' have been saved to the database') - collection = v._get_collection_name() - value_dict[k] = DBRef(collection, v.pk) - elif hasattr(v, 'to_python'): - value_dict[k] = v.to_python() - else: - value_dict[k] = self.to_python(v) - - if is_list: # Convert back to a list - return [v for k, v in sorted(value_dict.items(), - key=operator.itemgetter(0))] - return value_dict - - def to_mongo(self, value): - """Convert a Python type to a MongoDB-compatible type. - """ - Document = _import_class("Document") - EmbeddedDocument = _import_class("EmbeddedDocument") - GenericReferenceField = _import_class("GenericReferenceField") - - if isinstance(value, basestring): - return value - - if hasattr(value, 'to_mongo'): - if isinstance(value, Document): - return GenericReferenceField().to_mongo(value) - cls = value.__class__ - val = value.to_mongo() - # If we its a document thats not inherited add _cls - if (isinstance(value, EmbeddedDocument)): - val['_cls'] = cls.__name__ - return val - - is_list = False - if not hasattr(value, 'items'): - try: - is_list = True - value = dict([(k, v) for k, v in enumerate(value)]) - except TypeError: # Not iterable return the value - return value - - if self.field: - value_dict = dict([(key, self.field.to_mongo(item)) - for key, item in value.iteritems()]) - else: - value_dict = {} - for k, v in value.iteritems(): - if isinstance(v, Document): - # We need the id from the saved object to create the DBRef - if v.pk is None: - self.error('You can only reference documents once they' - ' have been saved to the database') - - # If its a document that is not inheritable it won't have - # any _cls data so make it a generic reference allows - # us to dereference - meta = getattr(v, '_meta', {}) - allow_inheritance = ( - meta.get('allow_inheritance', ALLOW_INHERITANCE) - is True) - if not allow_inheritance and not self.field: - value_dict[k] = GenericReferenceField().to_mongo(v) - else: - collection = v._get_collection_name() - value_dict[k] = DBRef(collection, v.pk) - elif hasattr(v, 'to_mongo'): - cls = v.__class__ - val = v.to_mongo() - # If we its a document thats not inherited add _cls - if (isinstance(v, (Document, EmbeddedDocument))): - val['_cls'] = cls.__name__ - value_dict[k] = val - else: - value_dict[k] = self.to_mongo(v) - - if is_list: # Convert back to a list - return [v for k, v in sorted(value_dict.items(), - key=operator.itemgetter(0))] - return value_dict - - def validate(self, value): - """If field is provided ensure the value is valid. - """ - errors = {} - if self.field: - if hasattr(value, 'iteritems') or hasattr(value, 'items'): - sequence = value.iteritems() - else: - sequence = enumerate(value) - for k, v in sequence: - try: - self.field._validate(v) - except ValidationError, error: - errors[k] = error.errors or error - except (ValueError, AssertionError), error: - errors[k] = error - - if errors: - field_class = self.field.__class__.__name__ - self.error('Invalid %s item (%s)' % (field_class, value), - errors=errors) - # Don't allow empty values if required - if self.required and not value: - self.error('Field is required and cannot be empty') - - def prepare_query_value(self, op, value): - return self.to_mongo(value) - - def lookup_member(self, member_name): - if self.field: - return self.field.lookup_member(member_name) - return None - - def _set_owner_document(self, owner_document): - if self.field: - self.field.owner_document = owner_document - self._owner_document = owner_document - - def _get_owner_document(self, owner_document): - self._owner_document = owner_document - - owner_document = property(_get_owner_document, _set_owner_document) - - -class ObjectIdField(BaseField): - - """A field wrapper around MongoDB's ObjectIds. - """ - - def to_python(self, value): - if not isinstance(value, ObjectId): - value = ObjectId(value) - return value - - def to_mongo(self, value): - if not isinstance(value, ObjectId): - try: - return ObjectId(unicode(value)) - except Exception, e: - # e.message attribute has been deprecated since Python 2.6 - self.error(unicode(e)) - return value - - def prepare_query_value(self, op, value): - return self.to_mongo(value) - - def validate(self, value): - try: - ObjectId(unicode(value)) - except: - self.error('Invalid Object ID') - - -class GeoJsonBaseField(BaseField): - - """A geo json field storing a geojson style object. - - .. versionadded:: 0.8 - """ - - _geo_index = pymongo.GEOSPHERE - _type = "GeoBase" - - def __init__(self, auto_index=True, *args, **kwargs): - """ - :param bool auto_index: Automatically create a "2dsphere" index.\ - Defaults to `True`. - """ - self._name = "%sField" % self._type - if not auto_index: - self._geo_index = False - super(GeoJsonBaseField, self).__init__(*args, **kwargs) - - def validate(self, value): - """Validate the GeoJson object based on its type - """ - if isinstance(value, dict): - if set(value.keys()) == set(['type', 'coordinates']): - if value['type'] != self._type: - self.error('%s type must be "%s"' % - (self._name, self._type)) - return self.validate(value['coordinates']) - else: - self.error('%s can only accept a valid GeoJson dictionary' - ' or lists of (x, y)' % self._name) - return - elif not isinstance(value, (list, tuple)): - self.error('%s can only accept lists of [x, y]' % self._name) - return - - validate = getattr(self, "_validate_%s" % self._type.lower()) - error = validate(value) - if error: - self.error(error) - - def _validate_polygon(self, value, top_level=True): - if not isinstance(value, (list, tuple)): - return 'Polygons must contain list of linestrings' - - # Quick and dirty validator - try: - value[0][0][0] - except: - return "Invalid Polygon must contain at least one valid linestring" - - errors = [] - for val in value: - error = self._validate_linestring(val, False) - if not error and val[0] != val[-1]: - error = 'LineStrings must start and end at the same point' - if error and error not in errors: - errors.append(error) - if errors: - if top_level: - return "Invalid Polygon:\n%s" % ", ".join(errors) - else: - return "%s" % ", ".join(errors) - - def _validate_linestring(self, value, top_level=True): - """Validates a linestring""" - if not isinstance(value, (list, tuple)): - return 'LineStrings must contain list of coordinate pairs' - - # Quick and dirty validator - try: - value[0][0] - except: - return "Invalid LineString must contain at least one valid point" - - errors = [] - for val in value: - error = self._validate_point(val) - if error and error not in errors: - errors.append(error) - if errors: - if top_level: - return "Invalid LineString:\n%s" % ", ".join(errors) - else: - return "%s" % ", ".join(errors) - - def _validate_point(self, value): - """Validate each set of coords""" - if not isinstance(value, (list, tuple)): - return 'Points must be a list of coordinate pairs' - elif not len(value) == 2: - return "Value (%s) must be a two-dimensional point" % repr(value) - elif (not isinstance(value[0], (float, int)) or - not isinstance(value[1], (float, int))): - return "Both values (%s) in point must be float or int" % repr(value) - - def _validate_multipoint(self, value): - if not isinstance(value, (list, tuple)): - return 'MultiPoint must be a list of Point' - - # Quick and dirty validator - try: - value[0][0] - except: - return "Invalid MultiPoint must contain at least one valid point" - - errors = [] - for point in value: - error = self._validate_point(point) - if error and error not in errors: - errors.append(error) - - if errors: - return "%s" % ", ".join(errors) - - def _validate_multilinestring(self, value, top_level=True): - if not isinstance(value, (list, tuple)): - return 'MultiLineString must be a list of LineString' - - # Quick and dirty validator - try: - value[0][0][0] - except: - return "Invalid MultiLineString must contain at least one valid linestring" - - errors = [] - for linestring in value: - error = self._validate_linestring(linestring, False) - if error and error not in errors: - errors.append(error) - - if errors: - if top_level: - return "Invalid MultiLineString:\n%s" % ", ".join(errors) - else: - return "%s" % ", ".join(errors) - - def _validate_multipolygon(self, value): - if not isinstance(value, (list, tuple)): - return 'MultiPolygon must be a list of Polygon' - - # Quick and dirty validator - try: - value[0][0][0][0] - except: - return "Invalid MultiPolygon must contain at least one valid Polygon" - - errors = [] - for polygon in value: - error = self._validate_polygon(polygon, False) - if error and error not in errors: - errors.append(error) - - if errors: - return "Invalid MultiPolygon:\n%s" % ", ".join(errors) - - def to_mongo(self, value): - if isinstance(value, dict): - return value - return SON([("type", self._type), ("coordinates", value)]) diff --git a/awx/lib/site-packages/mongoengine/base/metaclasses.py b/awx/lib/site-packages/mongoengine/base/metaclasses.py deleted file mode 100644 index 48da84f42c..0000000000 --- a/awx/lib/site-packages/mongoengine/base/metaclasses.py +++ /dev/null @@ -1,431 +0,0 @@ -import warnings - -import pymongo - -from mongoengine.common import _import_class -from mongoengine.errors import InvalidDocumentError -from mongoengine.python_support import PY3 -from mongoengine.queryset import (DO_NOTHING, DoesNotExist, - MultipleObjectsReturned, - QuerySet, QuerySetManager) - -from mongoengine.base.common import _document_registry, ALLOW_INHERITANCE -from mongoengine.base.fields import BaseField, ComplexBaseField, ObjectIdField - -__all__ = ('DocumentMetaclass', 'TopLevelDocumentMetaclass') - - -class DocumentMetaclass(type): - - """Metaclass for all documents. - """ - - def __new__(cls, name, bases, attrs): - flattened_bases = cls._get_bases(bases) - super_new = super(DocumentMetaclass, cls).__new__ - - # If a base class just call super - metaclass = attrs.get('my_metaclass') - if metaclass and issubclass(metaclass, DocumentMetaclass): - return super_new(cls, name, bases, attrs) - - attrs['_is_document'] = attrs.get('_is_document', False) - attrs['_cached_reference_fields'] = [] - - # EmbeddedDocuments could have meta data for inheritance - if 'meta' in attrs: - attrs['_meta'] = attrs.pop('meta') - - # EmbeddedDocuments should inherit meta data - if '_meta' not in attrs: - meta = MetaDict() - for base in flattened_bases[::-1]: - # Add any mixin metadata from plain objects - if hasattr(base, 'meta'): - meta.merge(base.meta) - elif hasattr(base, '_meta'): - meta.merge(base._meta) - attrs['_meta'] = meta - attrs['_meta']['abstract'] = False # 789: EmbeddedDocument shouldn't inherit abstract - - if attrs['_meta'].get('allow_inheritance', ALLOW_INHERITANCE): - StringField = _import_class('StringField') - attrs['_cls'] = StringField() - - # Handle document Fields - - # Merge all fields from subclasses - doc_fields = {} - for base in flattened_bases[::-1]: - if hasattr(base, '_fields'): - doc_fields.update(base._fields) - - # Standard object mixin - merge in any Fields - if not hasattr(base, '_meta'): - base_fields = {} - for attr_name, attr_value in base.__dict__.iteritems(): - if not isinstance(attr_value, BaseField): - continue - attr_value.name = attr_name - if not attr_value.db_field: - attr_value.db_field = attr_name - base_fields[attr_name] = attr_value - - doc_fields.update(base_fields) - - # Discover any document fields - field_names = {} - for attr_name, attr_value in attrs.iteritems(): - if not isinstance(attr_value, BaseField): - continue - attr_value.name = attr_name - if not attr_value.db_field: - attr_value.db_field = attr_name - doc_fields[attr_name] = attr_value - - # Count names to ensure no db_field redefinitions - field_names[attr_value.db_field] = field_names.get( - attr_value.db_field, 0) + 1 - - # Ensure no duplicate db_fields - duplicate_db_fields = [k for k, v in field_names.items() if v > 1] - if duplicate_db_fields: - msg = ("Multiple db_fields defined for: %s " % - ", ".join(duplicate_db_fields)) - raise InvalidDocumentError(msg) - - # Set _fields and db_field maps - attrs['_fields'] = doc_fields - attrs['_db_field_map'] = dict([(k, getattr(v, 'db_field', k)) - for k, v in doc_fields.iteritems()]) - attrs['_reverse_db_field_map'] = dict( - (v, k) for k, v in attrs['_db_field_map'].iteritems()) - - attrs['_fields_ordered'] = tuple(i[1] for i in sorted( - (v.creation_counter, v.name) - for v in doc_fields.itervalues())) - - # - # Set document hierarchy - # - superclasses = () - class_name = [name] - for base in flattened_bases: - if (not getattr(base, '_is_base_cls', True) and - not getattr(base, '_meta', {}).get('abstract', True)): - # Collate heirarchy for _cls and _subclasses - class_name.append(base.__name__) - - if hasattr(base, '_meta'): - # Warn if allow_inheritance isn't set and prevent - # inheritance of classes where inheritance is set to False - allow_inheritance = base._meta.get('allow_inheritance', - ALLOW_INHERITANCE) - if (allow_inheritance is not True and - not base._meta.get('abstract')): - raise ValueError('Document %s may not be subclassed' % - base.__name__) - - # Get superclasses from last base superclass - document_bases = [b for b in flattened_bases - if hasattr(b, '_class_name')] - if document_bases: - superclasses = document_bases[0]._superclasses - superclasses += (document_bases[0]._class_name, ) - - _cls = '.'.join(reversed(class_name)) - attrs['_class_name'] = _cls - attrs['_superclasses'] = superclasses - attrs['_subclasses'] = (_cls, ) - attrs['_types'] = attrs['_subclasses'] # TODO depreciate _types - - # Create the new_class - new_class = super_new(cls, name, bases, attrs) - - # Set _subclasses - for base in document_bases: - if _cls not in base._subclasses: - base._subclasses += (_cls,) - base._types = base._subclasses # TODO depreciate _types - - (Document, EmbeddedDocument, DictField, - CachedReferenceField) = cls._import_classes() - - if issubclass(new_class, Document): - new_class._collection = None - - # Add class to the _document_registry - _document_registry[new_class._class_name] = new_class - - # In Python 2, User-defined methods objects have special read-only - # attributes 'im_func' and 'im_self' which contain the function obj - # and class instance object respectively. With Python 3 these special - # attributes have been replaced by __func__ and __self__. The Blinker - # module continues to use im_func and im_self, so the code below - # copies __func__ into im_func and __self__ into im_self for - # classmethod objects in Document derived classes. - if PY3: - for key, val in new_class.__dict__.items(): - if isinstance(val, classmethod): - f = val.__get__(new_class) - if hasattr(f, '__func__') and not hasattr(f, 'im_func'): - f.__dict__.update({'im_func': getattr(f, '__func__')}) - if hasattr(f, '__self__') and not hasattr(f, 'im_self'): - f.__dict__.update({'im_self': getattr(f, '__self__')}) - - # Handle delete rules - for field in new_class._fields.itervalues(): - f = field - f.owner_document = new_class - delete_rule = getattr(f, 'reverse_delete_rule', DO_NOTHING) - if isinstance(f, CachedReferenceField): - - if issubclass(new_class, EmbeddedDocument): - raise InvalidDocumentError( - "CachedReferenceFields is not allowed in EmbeddedDocuments") - if not f.document_type: - raise InvalidDocumentError( - "Document is not avaiable to sync") - - if f.auto_sync: - f.start_listener() - - f.document_type._cached_reference_fields.append(f) - - if isinstance(f, ComplexBaseField) and hasattr(f, 'field'): - delete_rule = getattr(f.field, - 'reverse_delete_rule', - DO_NOTHING) - if isinstance(f, DictField) and delete_rule != DO_NOTHING: - msg = ("Reverse delete rules are not supported " - "for %s (field: %s)" % - (field.__class__.__name__, field.name)) - raise InvalidDocumentError(msg) - - f = field.field - - if delete_rule != DO_NOTHING: - if issubclass(new_class, EmbeddedDocument): - msg = ("Reverse delete rules are not supported for " - "EmbeddedDocuments (field: %s)" % field.name) - raise InvalidDocumentError(msg) - f.document_type.register_delete_rule(new_class, - field.name, delete_rule) - - if (field.name and hasattr(Document, field.name) and - EmbeddedDocument not in new_class.mro()): - msg = ("%s is a document method and not a valid " - "field name" % field.name) - raise InvalidDocumentError(msg) - - return new_class - - def add_to_class(self, name, value): - setattr(self, name, value) - - @classmethod - def _get_bases(cls, bases): - if isinstance(bases, BasesTuple): - return bases - seen = [] - bases = cls.__get_bases(bases) - unique_bases = (b for b in bases if not (b in seen or seen.append(b))) - return BasesTuple(unique_bases) - - @classmethod - def __get_bases(cls, bases): - for base in bases: - if base is object: - continue - yield base - for child_base in cls.__get_bases(base.__bases__): - yield child_base - - @classmethod - def _import_classes(cls): - Document = _import_class('Document') - EmbeddedDocument = _import_class('EmbeddedDocument') - DictField = _import_class('DictField') - CachedReferenceField = _import_class('CachedReferenceField') - return (Document, EmbeddedDocument, DictField, CachedReferenceField) - - -class TopLevelDocumentMetaclass(DocumentMetaclass): - - """Metaclass for top-level documents (i.e. documents that have their own - collection in the database. - """ - - def __new__(cls, name, bases, attrs): - flattened_bases = cls._get_bases(bases) - super_new = super(TopLevelDocumentMetaclass, cls).__new__ - - # Set default _meta data if base class, otherwise get user defined meta - if (attrs.get('my_metaclass') == TopLevelDocumentMetaclass): - # defaults - attrs['_meta'] = { - 'abstract': True, - 'max_documents': None, - 'max_size': None, - 'ordering': [], # default ordering applied at runtime - 'indexes': [], # indexes to be ensured at runtime - 'id_field': None, - 'index_background': False, - 'index_drop_dups': False, - 'index_opts': None, - 'delete_rules': None, - 'allow_inheritance': None, - } - attrs['_is_base_cls'] = True - attrs['_meta'].update(attrs.get('meta', {})) - else: - attrs['_meta'] = attrs.get('meta', {}) - # Explictly set abstract to false unless set - attrs['_meta']['abstract'] = attrs['_meta'].get('abstract', False) - attrs['_is_base_cls'] = False - - # Set flag marking as document class - as opposed to an object mixin - attrs['_is_document'] = True - - # Ensure queryset_class is inherited - if 'objects' in attrs: - manager = attrs['objects'] - if hasattr(manager, 'queryset_class'): - attrs['_meta']['queryset_class'] = manager.queryset_class - - # Clean up top level meta - if 'meta' in attrs: - del(attrs['meta']) - - # Find the parent document class - parent_doc_cls = [b for b in flattened_bases - if b.__class__ == TopLevelDocumentMetaclass] - parent_doc_cls = None if not parent_doc_cls else parent_doc_cls[0] - - # Prevent classes setting collection different to their parents - # If parent wasn't an abstract class - if (parent_doc_cls and 'collection' in attrs.get('_meta', {}) - and not parent_doc_cls._meta.get('abstract', True)): - msg = "Trying to set a collection on a subclass (%s)" % name - warnings.warn(msg, SyntaxWarning) - del(attrs['_meta']['collection']) - - # Ensure abstract documents have abstract bases - if attrs.get('_is_base_cls') or attrs['_meta'].get('abstract'): - if (parent_doc_cls and - not parent_doc_cls._meta.get('abstract', False)): - msg = "Abstract document cannot have non-abstract base" - raise ValueError(msg) - return super_new(cls, name, bases, attrs) - - # Merge base class metas. - # Uses a special MetaDict that handles various merging rules - meta = MetaDict() - for base in flattened_bases[::-1]: - # Add any mixin metadata from plain objects - if hasattr(base, 'meta'): - meta.merge(base.meta) - elif hasattr(base, '_meta'): - meta.merge(base._meta) - - # Set collection in the meta if its callable - if (getattr(base, '_is_document', False) and - not base._meta.get('abstract')): - collection = meta.get('collection', None) - if callable(collection): - meta['collection'] = collection(base) - - meta.merge(attrs.get('_meta', {})) # Top level meta - - # Only simple classes (direct subclasses of Document) - # may set allow_inheritance to False - simple_class = all([b._meta.get('abstract') - for b in flattened_bases if hasattr(b, '_meta')]) - if (not simple_class and meta['allow_inheritance'] is False and - not meta['abstract']): - raise ValueError('Only direct subclasses of Document may set ' - '"allow_inheritance" to False') - - # Set default collection name - if 'collection' not in meta: - meta['collection'] = ''.join('_%s' % c if c.isupper() else c - for c in name).strip('_').lower() - attrs['_meta'] = meta - - # Call super and get the new class - new_class = super_new(cls, name, bases, attrs) - - meta = new_class._meta - - # Set index specifications - meta['index_specs'] = new_class._build_index_specs(meta['indexes']) - - # If collection is a callable - call it and set the value - collection = meta.get('collection') - if callable(collection): - new_class._meta['collection'] = collection(new_class) - - # Provide a default queryset unless exists or one has been set - if 'objects' not in dir(new_class): - new_class.objects = QuerySetManager() - - # Validate the fields and set primary key if needed - for field_name, field in new_class._fields.iteritems(): - if field.primary_key: - # Ensure only one primary key is set - current_pk = new_class._meta.get('id_field') - if current_pk and current_pk != field_name: - raise ValueError('Cannot override primary key field') - - # Set primary key - if not current_pk: - new_class._meta['id_field'] = field_name - new_class.id = field - - # Set primary key if not defined by the document - new_class._auto_id_field = getattr(parent_doc_cls, - '_auto_id_field', False) - if not new_class._meta.get('id_field'): - new_class._auto_id_field = True - new_class._meta['id_field'] = 'id' - new_class._fields['id'] = ObjectIdField(db_field='_id') - new_class._fields['id'].name = 'id' - new_class.id = new_class._fields['id'] - - # Prepend id field to _fields_ordered - if 'id' in new_class._fields and 'id' not in new_class._fields_ordered: - new_class._fields_ordered = ('id', ) + new_class._fields_ordered - - # Merge in exceptions with parent hierarchy - exceptions_to_merge = (DoesNotExist, MultipleObjectsReturned) - module = attrs.get('__module__') - for exc in exceptions_to_merge: - name = exc.__name__ - parents = tuple(getattr(base, name) for base in flattened_bases - if hasattr(base, name)) or (exc,) - # Create new exception and set to new_class - exception = type(name, parents, {'__module__': module}) - setattr(new_class, name, exception) - - return new_class - - -class MetaDict(dict): - - """Custom dictionary for meta classes. - Handles the merging of set indexes - """ - _merge_options = ('indexes',) - - def merge(self, new_options): - for k, v in new_options.iteritems(): - if k in self._merge_options: - self[k] = self.get(k, []) + v - else: - self[k] = v - - -class BasesTuple(tuple): - - """Special class to handle introspection of bases tuple in __new__""" - pass diff --git a/awx/lib/site-packages/mongoengine/common.py b/awx/lib/site-packages/mongoengine/common.py deleted file mode 100644 index 3e63e98ee8..0000000000 --- a/awx/lib/site-packages/mongoengine/common.py +++ /dev/null @@ -1,55 +0,0 @@ -_class_registry_cache = {} -_field_list_cache = [] - - -def _import_class(cls_name): - """Cache mechanism for imports. - - Due to complications of circular imports mongoengine needs to do lots of - inline imports in functions. This is inefficient as classes are - imported repeated throughout the mongoengine code. This is - compounded by some recursive functions requiring inline imports. - - :mod:`mongoengine.common` provides a single point to import all these - classes. Circular imports aren't an issue as it dynamically imports the - class when first needed. Subsequent calls to the - :func:`~mongoengine.common._import_class` can then directly retrieve the - class from the :data:`mongoengine.common._class_registry_cache`. - """ - if cls_name in _class_registry_cache: - return _class_registry_cache.get(cls_name) - - doc_classes = ('Document', 'DynamicEmbeddedDocument', 'EmbeddedDocument', - 'MapReduceDocument') - - # Field Classes - if not _field_list_cache: - from mongoengine.fields import __all__ as fields - _field_list_cache.extend(fields) - from mongoengine.base.fields import __all__ as fields - _field_list_cache.extend(fields) - - field_classes = _field_list_cache - - queryset_classes = ('OperationError',) - deref_classes = ('DeReference',) - - if cls_name in doc_classes: - from mongoengine import document as module - import_classes = doc_classes - elif cls_name in field_classes: - from mongoengine import fields as module - import_classes = field_classes - elif cls_name in queryset_classes: - from mongoengine import queryset as module - import_classes = queryset_classes - elif cls_name in deref_classes: - from mongoengine import dereference as module - import_classes = deref_classes - else: - raise ValueError('No import set for: ' % cls_name) - - for cls in import_classes: - _class_registry_cache[cls] = getattr(module, cls) - - return _class_registry_cache.get(cls_name) diff --git a/awx/lib/site-packages/mongoengine/connection.py b/awx/lib/site-packages/mongoengine/connection.py deleted file mode 100644 index dcecdd9ad2..0000000000 --- a/awx/lib/site-packages/mongoengine/connection.py +++ /dev/null @@ -1,169 +0,0 @@ -import pymongo -from pymongo import MongoClient, MongoReplicaSetClient, uri_parser - - -__all__ = ['ConnectionError', 'connect', 'register_connection', - 'DEFAULT_CONNECTION_NAME'] - - -DEFAULT_CONNECTION_NAME = 'default' - - -class ConnectionError(Exception): - pass - - -_connection_settings = {} -_connections = {} -_dbs = {} - - -def register_connection(alias, name=None, host=None, port=None, - read_preference=False, - username=None, password=None, authentication_source=None, - **kwargs): - """Add a connection. - - :param alias: the name that will be used to refer to this connection - throughout MongoEngine - :param name: the name of the specific database to use - :param host: the host name of the :program:`mongod` instance to connect to - :param port: the port that the :program:`mongod` instance is running on - :param read_preference: The read preference for the collection - ** Added pymongo 2.1 - :param username: username to authenticate with - :param password: password to authenticate with - :param authentication_source: database to authenticate against - :param kwargs: allow ad-hoc parameters to be passed into the pymongo driver - - """ - global _connection_settings - - conn_settings = { - 'name': name or 'test', - 'host': host or 'localhost', - 'port': port or 27017, - 'read_preference': read_preference, - 'username': username, - 'password': password, - 'authentication_source': authentication_source - } - - # Handle uri style connections - if "://" in conn_settings['host']: - uri_dict = uri_parser.parse_uri(conn_settings['host']) - conn_settings.update({ - 'name': uri_dict.get('database') or name, - 'username': uri_dict.get('username'), - 'password': uri_dict.get('password'), - 'read_preference': read_preference, - }) - if "replicaSet" in conn_settings['host']: - conn_settings['replicaSet'] = True - - # Deprecated parameters that should not be passed on - kwargs.pop('slaves', None) - kwargs.pop('is_slave', None) - - conn_settings.update(kwargs) - _connection_settings[alias] = conn_settings - - -def disconnect(alias=DEFAULT_CONNECTION_NAME): - global _connections - global _dbs - - if alias in _connections: - get_connection(alias=alias).disconnect() - del _connections[alias] - if alias in _dbs: - del _dbs[alias] - - -def get_connection(alias=DEFAULT_CONNECTION_NAME, reconnect=False): - global _connections - # Connect to the database if not already connected - if reconnect: - disconnect(alias) - - if alias not in _connections: - if alias not in _connection_settings: - msg = 'Connection with alias "%s" has not been defined' % alias - if alias == DEFAULT_CONNECTION_NAME: - msg = 'You have not defined a default connection' - raise ConnectionError(msg) - conn_settings = _connection_settings[alias].copy() - - conn_settings.pop('name', None) - conn_settings.pop('username', None) - conn_settings.pop('password', None) - conn_settings.pop('authentication_source', None) - - connection_class = MongoClient - if 'replicaSet' in conn_settings: - conn_settings['hosts_or_uri'] = conn_settings.pop('host', None) - # Discard port since it can't be used on MongoReplicaSetClient - conn_settings.pop('port', None) - # Discard replicaSet if not base string - if not isinstance(conn_settings['replicaSet'], basestring): - conn_settings.pop('replicaSet', None) - connection_class = MongoReplicaSetClient - - try: - connection = None - # check for shared connections - connection_settings_iterator = ((db_alias, settings.copy()) for db_alias, settings in _connection_settings.iteritems()) - for db_alias, connection_settings in connection_settings_iterator: - connection_settings.pop('name', None) - connection_settings.pop('username', None) - connection_settings.pop('password', None) - if conn_settings == connection_settings and _connections.get(db_alias, None): - connection = _connections[db_alias] - break - - _connections[alias] = connection if connection else connection_class(**conn_settings) - except Exception, e: - raise ConnectionError("Cannot connect to database %s :\n%s" % (alias, e)) - return _connections[alias] - - -def get_db(alias=DEFAULT_CONNECTION_NAME, reconnect=False): - global _dbs - if reconnect: - disconnect(alias) - - if alias not in _dbs: - conn = get_connection(alias) - conn_settings = _connection_settings[alias] - db = conn[conn_settings['name']] - # Authenticate if necessary - if conn_settings['username'] and conn_settings['password']: - db.authenticate(conn_settings['username'], - conn_settings['password'], - source=conn_settings['authentication_source']) - _dbs[alias] = db - return _dbs[alias] - - -def connect(db=None, alias=DEFAULT_CONNECTION_NAME, **kwargs): - """Connect to the database specified by the 'db' argument. - - Connection settings may be provided here as well if the database is not - running on the default port on localhost. If authentication is needed, - provide username and password arguments as well. - - Multiple databases are supported by using aliases. Provide a separate - `alias` to connect to a different instance of :program:`mongod`. - - .. versionchanged:: 0.6 - added multiple database support. - """ - global _connections - if alias not in _connections: - register_connection(alias, db, **kwargs) - - return get_connection(alias) - - -# Support old naming convention -_get_connection = get_connection -_get_db = get_db diff --git a/awx/lib/site-packages/mongoengine/context_managers.py b/awx/lib/site-packages/mongoengine/context_managers.py deleted file mode 100644 index cc86006600..0000000000 --- a/awx/lib/site-packages/mongoengine/context_managers.py +++ /dev/null @@ -1,221 +0,0 @@ -from mongoengine.common import _import_class -from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_db - - -__all__ = ("switch_db", "switch_collection", "no_dereference", - "no_sub_classes", "query_counter") - - -class switch_db(object): - """ switch_db alias context manager. - - Example :: - - # Register connections - register_connection('default', 'mongoenginetest') - register_connection('testdb-1', 'mongoenginetest2') - - class Group(Document): - name = StringField() - - Group(name="test").save() # Saves in the default db - - with switch_db(Group, 'testdb-1') as Group: - Group(name="hello testdb!").save() # Saves in testdb-1 - - """ - - def __init__(self, cls, db_alias): - """ Construct the switch_db context manager - - :param cls: the class to change the registered db - :param db_alias: the name of the specific database to use - """ - self.cls = cls - self.collection = cls._get_collection() - self.db_alias = db_alias - self.ori_db_alias = cls._meta.get("db_alias", DEFAULT_CONNECTION_NAME) - - def __enter__(self): - """ change the db_alias and clear the cached collection """ - self.cls._meta["db_alias"] = self.db_alias - self.cls._collection = None - return self.cls - - def __exit__(self, t, value, traceback): - """ Reset the db_alias and collection """ - self.cls._meta["db_alias"] = self.ori_db_alias - self.cls._collection = self.collection - - -class switch_collection(object): - """ switch_collection alias context manager. - - Example :: - - class Group(Document): - name = StringField() - - Group(name="test").save() # Saves in the default db - - with switch_collection(Group, 'group1') as Group: - Group(name="hello testdb!").save() # Saves in group1 collection - - """ - - def __init__(self, cls, collection_name): - """ Construct the switch_collection context manager - - :param cls: the class to change the registered db - :param collection_name: the name of the collection to use - """ - self.cls = cls - self.ori_collection = cls._get_collection() - self.ori_get_collection_name = cls._get_collection_name - self.collection_name = collection_name - - def __enter__(self): - """ change the _get_collection_name and clear the cached collection """ - - @classmethod - def _get_collection_name(cls): - return self.collection_name - - self.cls._get_collection_name = _get_collection_name - self.cls._collection = None - return self.cls - - def __exit__(self, t, value, traceback): - """ Reset the collection """ - self.cls._collection = self.ori_collection - self.cls._get_collection_name = self.ori_get_collection_name - - -class no_dereference(object): - """ no_dereference context manager. - - Turns off all dereferencing in Documents for the duration of the context - manager:: - - with no_dereference(Group) as Group: - Group.objects.find() - - """ - - def __init__(self, cls): - """ Construct the no_dereference context manager. - - :param cls: the class to turn dereferencing off on - """ - self.cls = cls - - ReferenceField = _import_class('ReferenceField') - GenericReferenceField = _import_class('GenericReferenceField') - ComplexBaseField = _import_class('ComplexBaseField') - - self.deref_fields = [k for k, v in self.cls._fields.iteritems() - if isinstance(v, (ReferenceField, - GenericReferenceField, - ComplexBaseField))] - - def __enter__(self): - """ change the objects default and _auto_dereference values""" - for field in self.deref_fields: - self.cls._fields[field]._auto_dereference = False - return self.cls - - def __exit__(self, t, value, traceback): - """ Reset the default and _auto_dereference values""" - for field in self.deref_fields: - self.cls._fields[field]._auto_dereference = True - return self.cls - - -class no_sub_classes(object): - """ no_sub_classes context manager. - - Only returns instances of this class and no sub (inherited) classes:: - - with no_sub_classes(Group) as Group: - Group.objects.find() - - """ - - def __init__(self, cls): - """ Construct the no_sub_classes context manager. - - :param cls: the class to turn querying sub classes on - """ - self.cls = cls - - def __enter__(self): - """ change the objects default and _auto_dereference values""" - self.cls._all_subclasses = self.cls._subclasses - self.cls._subclasses = (self.cls,) - return self.cls - - def __exit__(self, t, value, traceback): - """ Reset the default and _auto_dereference values""" - self.cls._subclasses = self.cls._all_subclasses - delattr(self.cls, '_all_subclasses') - return self.cls - - -class query_counter(object): - """ Query_counter context manager to get the number of queries. """ - - def __init__(self): - """ Construct the query_counter. """ - self.counter = 0 - self.db = get_db() - - def __enter__(self): - """ On every with block we need to drop the profile collection. """ - self.db.set_profiling_level(0) - self.db.system.profile.drop() - self.db.set_profiling_level(2) - return self - - def __exit__(self, t, value, traceback): - """ Reset the profiling level. """ - self.db.set_profiling_level(0) - - def __eq__(self, value): - """ == Compare querycounter. """ - counter = self._get_count() - return value == counter - - def __ne__(self, value): - """ != Compare querycounter. """ - return not self.__eq__(value) - - def __lt__(self, value): - """ < Compare querycounter. """ - return self._get_count() < value - - def __le__(self, value): - """ <= Compare querycounter. """ - return self._get_count() <= value - - def __gt__(self, value): - """ > Compare querycounter. """ - return self._get_count() > value - - def __ge__(self, value): - """ >= Compare querycounter. """ - return self._get_count() >= value - - def __int__(self): - """ int representation. """ - return self._get_count() - - def __repr__(self): - """ repr query_counter as the number of queries. """ - return u"%s" % self._get_count() - - def _get_count(self): - """ Get the number of queries. """ - ignore_query = {"ns": {"$ne": "%s.system.indexes" % self.db.name}} - count = self.db.system.profile.find(ignore_query).count() - self.counter - self.counter += 1 - return count diff --git a/awx/lib/site-packages/mongoengine/dereference.py b/awx/lib/site-packages/mongoengine/dereference.py deleted file mode 100644 index 415d56782f..0000000000 --- a/awx/lib/site-packages/mongoengine/dereference.py +++ /dev/null @@ -1,237 +0,0 @@ -from bson import DBRef, SON - -from base import ( - BaseDict, BaseList, EmbeddedDocumentList, - TopLevelDocumentMetaclass, get_document -) -from fields import (ReferenceField, ListField, DictField, MapField) -from connection import get_db -from queryset import QuerySet -from document import Document, EmbeddedDocument - - -class DeReference(object): - - def __call__(self, items, max_depth=1, instance=None, name=None): - """ - Cheaply dereferences the items to a set depth. - Also handles the conversion of complex data types. - - :param items: The iterable (dict, list, queryset) to be dereferenced. - :param max_depth: The maximum depth to recurse to - :param instance: The owning instance used for tracking changes by - :class:`~mongoengine.base.ComplexBaseField` - :param name: The name of the field, used for tracking changes by - :class:`~mongoengine.base.ComplexBaseField` - :param get: A boolean determining if being called by __get__ - """ - if items is None or isinstance(items, basestring): - return items - - # cheapest way to convert a queryset to a list - # list(queryset) uses a count() query to determine length - if isinstance(items, QuerySet): - items = [i for i in items] - - self.max_depth = max_depth - doc_type = None - - if instance and isinstance(instance, (Document, EmbeddedDocument, - TopLevelDocumentMetaclass)): - doc_type = instance._fields.get(name) - while hasattr(doc_type, 'field'): - doc_type = doc_type.field - - if isinstance(doc_type, ReferenceField): - field = doc_type - doc_type = doc_type.document_type - is_list = not hasattr(items, 'items') - - if is_list and all([i.__class__ == doc_type for i in items]): - return items - elif not is_list and all([i.__class__ == doc_type - for i in items.values()]): - return items - elif not field.dbref: - if not hasattr(items, 'items'): - - def _get_items(items): - new_items = [] - for v in items: - if isinstance(v, list): - new_items.append(_get_items(v)) - elif not isinstance(v, (DBRef, Document)): - new_items.append(field.to_python(v)) - else: - new_items.append(v) - return new_items - - items = _get_items(items) - else: - items = dict([ - (k, field.to_python(v)) - if not isinstance(v, (DBRef, Document)) else (k, v) - for k, v in items.iteritems()] - ) - - self.reference_map = self._find_references(items) - self.object_map = self._fetch_objects(doc_type=doc_type) - return self._attach_objects(items, 0, instance, name) - - def _find_references(self, items, depth=0): - """ - Recursively finds all db references to be dereferenced - - :param items: The iterable (dict, list, queryset) - :param depth: The current depth of recursion - """ - reference_map = {} - if not items or depth >= self.max_depth: - return reference_map - - # Determine the iterator to use - if not hasattr(items, 'items'): - iterator = enumerate(items) - else: - iterator = items.iteritems() - - # Recursively find dbreferences - depth += 1 - for k, item in iterator: - if isinstance(item, (Document, EmbeddedDocument)): - for field_name, field in item._fields.iteritems(): - v = item._data.get(field_name, None) - if isinstance(v, (DBRef)): - reference_map.setdefault(field.document_type, []).append(v.id) - elif isinstance(v, (dict, SON)) and '_ref' in v: - reference_map.setdefault(get_document(v['_cls']), []).append(v['_ref'].id) - elif isinstance(v, (dict, list, tuple)) and depth <= self.max_depth: - field_cls = getattr(getattr(field, 'field', None), 'document_type', None) - references = self._find_references(v, depth) - for key, refs in references.iteritems(): - if isinstance(field_cls, (Document, TopLevelDocumentMetaclass)): - key = field_cls - reference_map.setdefault(key, []).extend(refs) - elif isinstance(item, (DBRef)): - reference_map.setdefault(item.collection, []).append(item.id) - elif isinstance(item, (dict, SON)) and '_ref' in item: - reference_map.setdefault(get_document(item['_cls']), []).append(item['_ref'].id) - elif isinstance(item, (dict, list, tuple)) and depth - 1 <= self.max_depth: - references = self._find_references(item, depth - 1) - for key, refs in references.iteritems(): - reference_map.setdefault(key, []).extend(refs) - - return reference_map - - def _fetch_objects(self, doc_type=None): - """Fetch all references and convert to their document objects - """ - object_map = {} - for collection, dbrefs in self.reference_map.iteritems(): - keys = object_map.keys() - refs = list(set([dbref for dbref in dbrefs if unicode(dbref).encode('utf-8') not in keys])) - if hasattr(collection, 'objects'): # We have a document class for the refs - references = collection.objects.in_bulk(refs) - for key, doc in references.iteritems(): - object_map[key] = doc - else: # Generic reference: use the refs data to convert to document - if isinstance(doc_type, (ListField, DictField, MapField,)): - continue - - if doc_type: - references = doc_type._get_db()[collection].find({'_id': {'$in': refs}}) - for ref in references: - doc = doc_type._from_son(ref) - object_map[doc.id] = doc - else: - references = get_db()[collection].find({'_id': {'$in': refs}}) - for ref in references: - if '_cls' in ref: - doc = get_document(ref["_cls"])._from_son(ref) - elif doc_type is None: - doc = get_document( - ''.join(x.capitalize() - for x in collection.split('_')))._from_son(ref) - else: - doc = doc_type._from_son(ref) - object_map[doc.id] = doc - return object_map - - def _attach_objects(self, items, depth=0, instance=None, name=None): - """ - Recursively finds all db references to be dereferenced - - :param items: The iterable (dict, list, queryset) - :param depth: The current depth of recursion - :param instance: The owning instance used for tracking changes by - :class:`~mongoengine.base.ComplexBaseField` - :param name: The name of the field, used for tracking changes by - :class:`~mongoengine.base.ComplexBaseField` - """ - if not items: - if isinstance(items, (BaseDict, BaseList)): - return items - - if instance: - if isinstance(items, dict): - return BaseDict(items, instance, name) - else: - return BaseList(items, instance, name) - - if isinstance(items, (dict, SON)): - if '_ref' in items: - return self.object_map.get(items['_ref'].id, items) - elif '_cls' in items: - doc = get_document(items['_cls'])._from_son(items) - _cls = doc._data.pop('_cls', None) - del items['_cls'] - doc._data = self._attach_objects(doc._data, depth, doc, None) - if _cls is not None: - doc._data['_cls'] = _cls - return doc - - if not hasattr(items, 'items'): - is_list = True - list_type = BaseList - if isinstance(items, EmbeddedDocumentList): - list_type = EmbeddedDocumentList - as_tuple = isinstance(items, tuple) - iterator = enumerate(items) - data = [] - else: - is_list = False - iterator = items.iteritems() - data = {} - - depth += 1 - for k, v in iterator: - if is_list: - data.append(v) - else: - data[k] = v - - if k in self.object_map and not is_list: - data[k] = self.object_map[k] - elif isinstance(v, (Document, EmbeddedDocument)): - for field_name, field in v._fields.iteritems(): - v = data[k]._data.get(field_name, None) - if isinstance(v, (DBRef)): - data[k]._data[field_name] = self.object_map.get(v.id, v) - elif isinstance(v, (dict, SON)) and '_ref' in v: - data[k]._data[field_name] = self.object_map.get(v['_ref'].id, v) - elif isinstance(v, dict) and depth <= self.max_depth: - data[k]._data[field_name] = self._attach_objects(v, depth, instance=instance, name=name) - elif isinstance(v, (list, tuple)) and depth <= self.max_depth: - data[k]._data[field_name] = self._attach_objects(v, depth, instance=instance, name=name) - elif isinstance(v, (dict, list, tuple)) and depth <= self.max_depth: - item_name = '%s.%s' % (name, k) if name else name - data[k] = self._attach_objects(v, depth - 1, instance=instance, name=item_name) - elif hasattr(v, 'id'): - data[k] = self.object_map.get(v.id, v) - - if instance and name: - if is_list: - return tuple(data) if as_tuple else list_type(data, instance, name) - return BaseDict(data, instance, name) - depth += 1 - return data diff --git a/awx/lib/site-packages/mongoengine/django/__init__.py b/awx/lib/site-packages/mongoengine/django/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/mongoengine/django/auth.py b/awx/lib/site-packages/mongoengine/django/auth.py deleted file mode 100644 index 0a309c4cd8..0000000000 --- a/awx/lib/site-packages/mongoengine/django/auth.py +++ /dev/null @@ -1,412 +0,0 @@ -from mongoengine import * - -from django.utils.encoding import smart_str -from django.contrib.auth.models import _user_has_perm, _user_get_all_permissions, _user_has_module_perms -from django.db import models -from django.contrib.contenttypes.models import ContentTypeManager -from django.contrib import auth -from django.contrib.auth.models import AnonymousUser -from django.utils.translation import ugettext_lazy as _ - -from .utils import datetime_now - -REDIRECT_FIELD_NAME = 'next' - -try: - from django.contrib.auth.hashers import check_password, make_password -except ImportError: - """Handle older versions of Django""" - from django.utils.hashcompat import md5_constructor, sha_constructor - - def get_hexdigest(algorithm, salt, raw_password): - raw_password, salt = smart_str(raw_password), smart_str(salt) - if algorithm == 'md5': - return md5_constructor(salt + raw_password).hexdigest() - elif algorithm == 'sha1': - return sha_constructor(salt + raw_password).hexdigest() - raise ValueError('Got unknown password algorithm type in password') - - def check_password(raw_password, password): - algo, salt, hash = password.split('$') - return hash == get_hexdigest(algo, salt, raw_password) - - def make_password(raw_password): - from random import random - algo = 'sha1' - salt = get_hexdigest(algo, str(random()), str(random()))[:5] - hash = get_hexdigest(algo, salt, raw_password) - return '%s$%s$%s' % (algo, salt, hash) - - -class ContentType(Document): - name = StringField(max_length=100) - app_label = StringField(max_length=100) - model = StringField(max_length=100, verbose_name=_('python model class name'), - unique_with='app_label') - objects = ContentTypeManager() - - class Meta: - verbose_name = _('content type') - verbose_name_plural = _('content types') - # db_table = 'django_content_type' - # ordering = ('name',) - # unique_together = (('app_label', 'model'),) - - def __unicode__(self): - return self.name - - def model_class(self): - "Returns the Python model class for this type of content." - from django.db import models - return models.get_model(self.app_label, self.model) - - def get_object_for_this_type(self, **kwargs): - """ - Returns an object of this type for the keyword arguments given. - Basically, this is a proxy around this object_type's get_object() model - method. The ObjectNotExist exception, if thrown, will not be caught, - so code that calls this method should catch it. - """ - return self.model_class()._default_manager.using(self._state.db).get(**kwargs) - - def natural_key(self): - return (self.app_label, self.model) - - -class SiteProfileNotAvailable(Exception): - pass - - -class PermissionManager(models.Manager): - def get_by_natural_key(self, codename, app_label, model): - return self.get( - codename=codename, - content_type=ContentType.objects.get_by_natural_key(app_label, model) - ) - - -class Permission(Document): - """The permissions system provides a way to assign permissions to specific - users and groups of users. - - The permission system is used by the Django admin site, but may also be - useful in your own code. The Django admin site uses permissions as follows: - - - The "add" permission limits the user's ability to view the "add" - form and add an object. - - The "change" permission limits a user's ability to view the change - list, view the "change" form and change an object. - - The "delete" permission limits the ability to delete an object. - - Permissions are set globally per type of object, not per specific object - instance. It is possible to say "Mary may change news stories," but it's - not currently possible to say "Mary may change news stories, but only the - ones she created herself" or "Mary may only change news stories that have - a certain status or publication date." - - Three basic permissions -- add, change and delete -- are automatically - created for each Django model. - """ - name = StringField(max_length=50, verbose_name=_('username')) - content_type = ReferenceField(ContentType) - codename = StringField(max_length=100, verbose_name=_('codename')) - # FIXME: don't access field of the other class - # unique_with=['content_type__app_label', 'content_type__model']) - - objects = PermissionManager() - - class Meta: - verbose_name = _('permission') - verbose_name_plural = _('permissions') - # unique_together = (('content_type', 'codename'),) - # ordering = ('content_type__app_label', 'content_type__model', 'codename') - - def __unicode__(self): - return u"%s | %s | %s" % ( - unicode(self.content_type.app_label), - unicode(self.content_type), - unicode(self.name)) - - def natural_key(self): - return (self.codename,) + self.content_type.natural_key() - natural_key.dependencies = ['contenttypes.contenttype'] - - -class Group(Document): - """Groups are a generic way of categorizing users to apply permissions, - or some other label, to those users. A user can belong to any number of - groups. - - A user in a group automatically has all the permissions granted to that - group. For example, if the group Site editors has the permission - can_edit_home_page, any user in that group will have that permission. - - Beyond permissions, groups are a convenient way to categorize users to - apply some label, or extended functionality, to them. For example, you - could create a group 'Special users', and you could write code that would - do special things to those users -- such as giving them access to a - members-only portion of your site, or sending them members-only - e-mail messages. - """ - name = StringField(max_length=80, unique=True, verbose_name=_('name')) - permissions = ListField(ReferenceField(Permission, verbose_name=_('permissions'), required=False)) - - class Meta: - verbose_name = _('group') - verbose_name_plural = _('groups') - - def __unicode__(self): - return self.name - - -class UserManager(models.Manager): - def create_user(self, username, email, password=None): - """ - Creates and saves a User with the given username, e-mail and password. - """ - now = datetime_now() - - # Normalize the address by lowercasing the domain part of the email - # address. - try: - email_name, domain_part = email.strip().split('@', 1) - except ValueError: - pass - else: - email = '@'.join([email_name, domain_part.lower()]) - - user = self.model(username=username, email=email, is_staff=False, - is_active=True, is_superuser=False, last_login=now, - date_joined=now) - - user.set_password(password) - user.save(using=self._db) - return user - - def create_superuser(self, username, email, password): - u = self.create_user(username, email, password) - u.is_staff = True - u.is_active = True - u.is_superuser = True - u.save(using=self._db) - return u - - def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'): - "Generates a random password with the given length and given allowed_chars" - # Note that default value of allowed_chars does not have "I" or letters - # that look like it -- just to avoid confusion. - from random import choice - return ''.join([choice(allowed_chars) for i in range(length)]) - - -class User(Document): - """A User document that aims to mirror most of the API specified by Django - at http://docs.djangoproject.com/en/dev/topics/auth/#users - """ - username = StringField(max_length=30, required=True, - verbose_name=_('username'), - help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters")) - - first_name = StringField(max_length=30, - verbose_name=_('first name')) - - last_name = StringField(max_length=30, - verbose_name=_('last name')) - email = EmailField(verbose_name=_('e-mail address')) - password = StringField(max_length=128, - verbose_name=_('password'), - help_text=_("Use '[algo]$[iterations]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>.")) - is_staff = BooleanField(default=False, - verbose_name=_('staff status'), - help_text=_("Designates whether the user can log into this admin site.")) - is_active = BooleanField(default=True, - verbose_name=_('active'), - help_text=_("Designates whether this user should be treated as active. Unselect this instead of deleting accounts.")) - is_superuser = BooleanField(default=False, - verbose_name=_('superuser status'), - help_text=_("Designates that this user has all permissions without explicitly assigning them.")) - last_login = DateTimeField(default=datetime_now, - verbose_name=_('last login')) - date_joined = DateTimeField(default=datetime_now, - verbose_name=_('date joined')) - - user_permissions = ListField(ReferenceField(Permission), verbose_name=_('user permissions'), - help_text=_('Permissions for the user.')) - - USERNAME_FIELD = 'username' - REQUIRED_FIELDS = ['email'] - - meta = { - 'allow_inheritance': True, - 'indexes': [ - {'fields': ['username'], 'unique': True, 'sparse': True} - ] - } - - def __unicode__(self): - return self.username - - def get_full_name(self): - """Returns the users first and last names, separated by a space. - """ - full_name = u'%s %s' % (self.first_name or '', self.last_name or '') - return full_name.strip() - - def is_anonymous(self): - return False - - def is_authenticated(self): - return True - - def set_password(self, raw_password): - """Sets the user's password - always use this rather than directly - assigning to :attr:`~mongoengine.django.auth.User.password` as the - password is hashed before storage. - """ - self.password = make_password(raw_password) - self.save() - return self - - def check_password(self, raw_password): - """Checks the user's password against a provided password - always use - this rather than directly comparing to - :attr:`~mongoengine.django.auth.User.password` as the password is - hashed before storage. - """ - return check_password(raw_password, self.password) - - @classmethod - def create_user(cls, username, password, email=None): - """Create (and save) a new user with the given username, password and - email address. - """ - now = datetime_now() - - # Normalize the address by lowercasing the domain part of the email - # address. - if email is not None: - try: - email_name, domain_part = email.strip().split('@', 1) - except ValueError: - pass - else: - email = '@'.join([email_name, domain_part.lower()]) - - user = cls(username=username, email=email, date_joined=now) - user.set_password(password) - user.save() - return user - - def get_group_permissions(self, obj=None): - """ - Returns a list of permission strings that this user has through his/her - groups. This method queries all available auth backends. If an object - is passed in, only permissions matching this object are returned. - """ - permissions = set() - for backend in auth.get_backends(): - if hasattr(backend, "get_group_permissions"): - permissions.update(backend.get_group_permissions(self, obj)) - return permissions - - def get_all_permissions(self, obj=None): - return _user_get_all_permissions(self, obj) - - def has_perm(self, perm, obj=None): - """ - Returns True if the user has the specified permission. This method - queries all available auth backends, but returns immediately if any - backend returns True. Thus, a user who has permission from a single - auth backend is assumed to have permission in general. If an object is - provided, permissions for this specific object are checked. - """ - - # Active superusers have all permissions. - if self.is_active and self.is_superuser: - return True - - # Otherwise we need to check the backends. - return _user_has_perm(self, perm, obj) - - def has_module_perms(self, app_label): - """ - Returns True if the user has any permissions in the given app label. - Uses pretty much the same logic as has_perm, above. - """ - # Active superusers have all permissions. - if self.is_active and self.is_superuser: - return True - - return _user_has_module_perms(self, app_label) - - def email_user(self, subject, message, from_email=None): - "Sends an e-mail to this User." - from django.core.mail import send_mail - send_mail(subject, message, from_email, [self.email]) - - def get_profile(self): - """ - Returns site-specific profile for this user. Raises - SiteProfileNotAvailable if this site does not allow profiles. - """ - if not hasattr(self, '_profile_cache'): - from django.conf import settings - if not getattr(settings, 'AUTH_PROFILE_MODULE', False): - raise SiteProfileNotAvailable('You need to set AUTH_PROFILE_MO' - 'DULE in your project settings') - try: - app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.') - except ValueError: - raise SiteProfileNotAvailable('app_label and model_name should' - ' be separated by a dot in the AUTH_PROFILE_MODULE set' - 'ting') - - try: - model = models.get_model(app_label, model_name) - if model is None: - raise SiteProfileNotAvailable('Unable to load the profile ' - 'model, check AUTH_PROFILE_MODULE in your project sett' - 'ings') - self._profile_cache = model._default_manager.using(self._state.db).get(user__id__exact=self.id) - self._profile_cache.user = self - except (ImportError, ImproperlyConfigured): - raise SiteProfileNotAvailable - return self._profile_cache - - -class MongoEngineBackend(object): - """Authenticate using MongoEngine and mongoengine.django.auth.User. - """ - - supports_object_permissions = False - supports_anonymous_user = False - supports_inactive_user = False - _user_doc = False - - def authenticate(self, username=None, password=None): - user = self.user_document.objects(username=username).first() - if user: - if password and user.check_password(password): - backend = auth.get_backends()[0] - user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) - return user - return None - - def get_user(self, user_id): - return self.user_document.objects.with_id(user_id) - - @property - def user_document(self): - if self._user_doc is False: - from .mongo_auth.models import get_user_document - self._user_doc = get_user_document() - return self._user_doc - -def get_user(userid): - """Returns a User object from an id (User.id). Django's equivalent takes - request, but taking an id instead leaves it up to the developer to store - the id in any way they want (session, signed cookie, etc.) - """ - if not userid: - return AnonymousUser() - return MongoEngineBackend().get_user(userid) or AnonymousUser() diff --git a/awx/lib/site-packages/mongoengine/django/mongo_auth/__init__.py b/awx/lib/site-packages/mongoengine/django/mongo_auth/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/mongoengine/django/mongo_auth/models.py b/awx/lib/site-packages/mongoengine/django/mongo_auth/models.py deleted file mode 100644 index ad4ceff8df..0000000000 --- a/awx/lib/site-packages/mongoengine/django/mongo_auth/models.py +++ /dev/null @@ -1,119 +0,0 @@ -from django.conf import settings -from django.contrib.auth.hashers import make_password -from django.contrib.auth.models import UserManager -from django.core.exceptions import ImproperlyConfigured -from django.db import models -try: - from django.utils.module_loading import import_module -except ImportError: - """Handle older versions of Django""" - from django.utils.importlib import import_module -from django.utils.translation import ugettext_lazy as _ - - -__all__ = ( - 'get_user_document', -) - - -MONGOENGINE_USER_DOCUMENT = getattr( - settings, 'MONGOENGINE_USER_DOCUMENT', 'mongoengine.django.auth.User') - - -def get_user_document(): - """Get the user document class used for authentication. - - This is the class defined in settings.MONGOENGINE_USER_DOCUMENT, which - defaults to `mongoengine.django.auth.User`. - - """ - - name = MONGOENGINE_USER_DOCUMENT - dot = name.rindex('.') - module = import_module(name[:dot]) - return getattr(module, name[dot + 1:]) - - -class MongoUserManager(UserManager): - """A User manager wich allows the use of MongoEngine documents in Django. - - To use the manager, you must tell django.contrib.auth to use MongoUser as - the user model. In you settings.py, you need: - - INSTALLED_APPS = ( - ... - 'django.contrib.auth', - 'mongoengine.django.mongo_auth', - ... - ) - AUTH_USER_MODEL = 'mongo_auth.MongoUser' - - Django will use the model object to access the custom Manager, which will - replace the original queryset with MongoEngine querysets. - - By default, mongoengine.django.auth.User will be used to store users. You - can specify another document class in MONGOENGINE_USER_DOCUMENT in your - settings.py. - - The User Document class has the same requirements as a standard custom user - model: https://docs.djangoproject.com/en/dev/topics/auth/customizing/ - - In particular, the User Document class must define USERNAME_FIELD and - REQUIRED_FIELDS. - - `AUTH_USER_MODEL` has been added in Django 1.5. - - """ - - def contribute_to_class(self, model, name): - super(MongoUserManager, self).contribute_to_class(model, name) - self.dj_model = self.model - self.model = get_user_document() - - self.dj_model.USERNAME_FIELD = self.model.USERNAME_FIELD - username = models.CharField(_('username'), max_length=30, unique=True) - username.contribute_to_class(self.dj_model, self.dj_model.USERNAME_FIELD) - - self.dj_model.REQUIRED_FIELDS = self.model.REQUIRED_FIELDS - for name in self.dj_model.REQUIRED_FIELDS: - field = models.CharField(_(name), max_length=30) - field.contribute_to_class(self.dj_model, name) - - - def get(self, *args, **kwargs): - try: - return self.get_query_set().get(*args, **kwargs) - except self.model.DoesNotExist: - # ModelBackend expects this exception - raise self.dj_model.DoesNotExist - - @property - def db(self): - raise NotImplementedError - - def get_empty_query_set(self): - return self.model.objects.none() - - def get_query_set(self): - return self.model.objects - - -class MongoUser(models.Model): - """"Dummy user model for Django. - - MongoUser is used to replace Django's UserManager with MongoUserManager. - The actual user document class is mongoengine.django.auth.User or any - other document class specified in MONGOENGINE_USER_DOCUMENT. - - To get the user document class, use `get_user_document()`. - - """ - - objects = MongoUserManager() - - class Meta: - app_label = 'mongo_auth' - - def set_password(self, password): - """Doesn't do anything, but works around the issue with Django 1.6.""" - make_password(password) diff --git a/awx/lib/site-packages/mongoengine/django/sessions.py b/awx/lib/site-packages/mongoengine/django/sessions.py deleted file mode 100644 index f260951beb..0000000000 --- a/awx/lib/site-packages/mongoengine/django/sessions.py +++ /dev/null @@ -1,124 +0,0 @@ -from bson import json_util -from django.conf import settings -from django.contrib.sessions.backends.base import SessionBase, CreateError -from django.core.exceptions import SuspiciousOperation -try: - from django.utils.encoding import force_unicode -except ImportError: - from django.utils.encoding import force_text as force_unicode - -from mongoengine.document import Document -from mongoengine import fields -from mongoengine.queryset import OperationError -from mongoengine.connection import DEFAULT_CONNECTION_NAME - -from .utils import datetime_now - - -MONGOENGINE_SESSION_DB_ALIAS = getattr( - settings, 'MONGOENGINE_SESSION_DB_ALIAS', - DEFAULT_CONNECTION_NAME) - -# a setting for the name of the collection used to store sessions -MONGOENGINE_SESSION_COLLECTION = getattr( - settings, 'MONGOENGINE_SESSION_COLLECTION', - 'django_session') - -# a setting for whether session data is stored encoded or not -MONGOENGINE_SESSION_DATA_ENCODE = getattr( - settings, 'MONGOENGINE_SESSION_DATA_ENCODE', - True) - - -class MongoSession(Document): - session_key = fields.StringField(primary_key=True, max_length=40) - session_data = fields.StringField() if MONGOENGINE_SESSION_DATA_ENCODE \ - else fields.DictField() - expire_date = fields.DateTimeField() - - meta = { - 'collection': MONGOENGINE_SESSION_COLLECTION, - 'db_alias': MONGOENGINE_SESSION_DB_ALIAS, - 'allow_inheritance': False, - 'indexes': [ - { - 'fields': ['expire_date'], - 'expireAfterSeconds': 0 - } - ] - } - - def get_decoded(self): - return SessionStore().decode(self.session_data) - - -class SessionStore(SessionBase): - """A MongoEngine-based session store for Django. - """ - - def _get_session(self, *args, **kwargs): - sess = super(SessionStore, self)._get_session(*args, **kwargs) - if sess.get('_auth_user_id', None): - sess['_auth_user_id'] = str(sess.get('_auth_user_id')) - return sess - - def load(self): - try: - s = MongoSession.objects(session_key=self.session_key, - expire_date__gt=datetime_now)[0] - if MONGOENGINE_SESSION_DATA_ENCODE: - return self.decode(force_unicode(s.session_data)) - else: - return s.session_data - except (IndexError, SuspiciousOperation): - self.create() - return {} - - def exists(self, session_key): - return bool(MongoSession.objects(session_key=session_key).first()) - - def create(self): - while True: - self._session_key = self._get_new_session_key() - try: - self.save(must_create=True) - except CreateError: - continue - self.modified = True - self._session_cache = {} - return - - def save(self, must_create=False): - if self.session_key is None: - self._session_key = self._get_new_session_key() - s = MongoSession(session_key=self.session_key) - if MONGOENGINE_SESSION_DATA_ENCODE: - s.session_data = self.encode(self._get_session(no_load=must_create)) - else: - s.session_data = self._get_session(no_load=must_create) - s.expire_date = self.get_expiry_date() - try: - s.save(force_insert=must_create) - except OperationError: - if must_create: - raise CreateError - raise - - def delete(self, session_key=None): - if session_key is None: - if self.session_key is None: - return - session_key = self.session_key - MongoSession.objects(session_key=session_key).delete() - - -class BSONSerializer(object): - """ - Serializer that can handle BSON types (eg ObjectId). - """ - def dumps(self, obj): - return json_util.dumps(obj, separators=(',', ':')).encode('ascii') - - def loads(self, data): - return json_util.loads(data.decode('ascii')) - diff --git a/awx/lib/site-packages/mongoengine/django/shortcuts.py b/awx/lib/site-packages/mongoengine/django/shortcuts.py deleted file mode 100644 index 9cc8370b00..0000000000 --- a/awx/lib/site-packages/mongoengine/django/shortcuts.py +++ /dev/null @@ -1,47 +0,0 @@ -from mongoengine.queryset import QuerySet -from mongoengine.base import BaseDocument -from mongoengine.errors import ValidationError - -def _get_queryset(cls): - """Inspired by django.shortcuts.*""" - if isinstance(cls, QuerySet): - return cls - else: - return cls.objects - -def get_document_or_404(cls, *args, **kwargs): - """ - Uses get() to return an document, or raises a Http404 exception if the document - does not exist. - - cls may be a Document or QuerySet object. All other passed - arguments and keyword arguments are used in the get() query. - - Note: Like with get(), an MultipleObjectsReturned will be raised if more than one - object is found. - - Inspired by django.shortcuts.* - """ - queryset = _get_queryset(cls) - try: - return queryset.get(*args, **kwargs) - except (queryset._document.DoesNotExist, ValidationError): - from django.http import Http404 - raise Http404('No %s matches the given query.' % queryset._document._class_name) - -def get_list_or_404(cls, *args, **kwargs): - """ - Uses filter() to return a list of documents, or raise a Http404 exception if - the list is empty. - - cls may be a Document or QuerySet object. All other passed - arguments and keyword arguments are used in the filter() query. - - Inspired by django.shortcuts.* - """ - queryset = _get_queryset(cls) - obj_list = list(queryset.filter(*args, **kwargs)) - if not obj_list: - from django.http import Http404 - raise Http404('No %s matches the given query.' % queryset._document._class_name) - return obj_list diff --git a/awx/lib/site-packages/mongoengine/django/storage.py b/awx/lib/site-packages/mongoengine/django/storage.py deleted file mode 100644 index 9df6f9e80c..0000000000 --- a/awx/lib/site-packages/mongoengine/django/storage.py +++ /dev/null @@ -1,112 +0,0 @@ -import os -import itertools -import urlparse - -from mongoengine import * -from django.conf import settings -from django.core.files.storage import Storage -from django.core.exceptions import ImproperlyConfigured - - -class FileDocument(Document): - """A document used to store a single file in GridFS. - """ - file = FileField() - - -class GridFSStorage(Storage): - """A custom storage backend to store files in GridFS - """ - - def __init__(self, base_url=None): - - if base_url is None: - base_url = settings.MEDIA_URL - self.base_url = base_url - self.document = FileDocument - self.field = 'file' - - def delete(self, name): - """Deletes the specified file from the storage system. - """ - if self.exists(name): - doc = self.document.objects.first() - field = getattr(doc, self.field) - self._get_doc_with_name(name).delete() # Delete the FileField - field.delete() # Delete the FileDocument - - def exists(self, name): - """Returns True if a file referened by the given name already exists in the - storage system, or False if the name is available for a new file. - """ - doc = self._get_doc_with_name(name) - if doc: - field = getattr(doc, self.field) - return bool(field.name) - else: - return False - - def listdir(self, path=None): - """Lists the contents of the specified path, returning a 2-tuple of lists; - the first item being directories, the second item being files. - """ - def name(doc): - return getattr(doc, self.field).name - docs = self.document.objects - return [], [name(d) for d in docs if name(d)] - - def size(self, name): - """Returns the total size, in bytes, of the file specified by name. - """ - doc = self._get_doc_with_name(name) - if doc: - return getattr(doc, self.field).length - else: - raise ValueError("No such file or directory: '%s'" % name) - - def url(self, name): - """Returns an absolute URL where the file's contents can be accessed - directly by a web browser. - """ - if self.base_url is None: - raise ValueError("This file is not accessible via a URL.") - return urlparse.urljoin(self.base_url, name).replace('\\', '/') - - def _get_doc_with_name(self, name): - """Find the documents in the store with the given name - """ - docs = self.document.objects - doc = [d for d in docs if hasattr(getattr(d, self.field), 'name') and getattr(d, self.field).name == name] - if doc: - return doc[0] - else: - return None - - def _open(self, name, mode='rb'): - doc = self._get_doc_with_name(name) - if doc: - return getattr(doc, self.field) - else: - raise ValueError("No file found with the name '%s'." % name) - - def get_available_name(self, name): - """Returns a filename that's free on the target storage system, and - available for new content to be written to. - """ - file_root, file_ext = os.path.splitext(name) - # If the filename already exists, add an underscore and a number (before - # the file extension, if one exists) to the filename until the generated - # filename doesn't exist. - count = itertools.count(1) - while self.exists(name): - # file_ext includes the dot. - name = os.path.join("%s_%s%s" % (file_root, count.next(), file_ext)) - - return name - - def _save(self, name, content): - doc = self.document() - getattr(doc, self.field).put(content, filename=name) - doc.save() - - return name diff --git a/awx/lib/site-packages/mongoengine/django/tests.py b/awx/lib/site-packages/mongoengine/django/tests.py deleted file mode 100644 index b130acc824..0000000000 --- a/awx/lib/site-packages/mongoengine/django/tests.py +++ /dev/null @@ -1,31 +0,0 @@ -#coding: utf-8 - -from unittest import TestCase - -from mongoengine import connect -from mongoengine.connection import get_db - - -class MongoTestCase(TestCase): - """ - TestCase class that clear the collection between the tests - """ - - @property - def db_name(self): - from django.conf import settings - return 'test_%s' % getattr(settings, 'MONGO_DATABASE_NAME', 'dummy') - - def __init__(self, methodName='runtest'): - connect(self.db_name) - self.db = get_db() - super(MongoTestCase, self).__init__(methodName) - - def dropCollections(self): - for collection in self.db.collection_names(): - if collection.startswith('system.'): - continue - self.db.drop_collection(collection) - - def tearDown(self): - self.dropCollections() diff --git a/awx/lib/site-packages/mongoengine/django/utils.py b/awx/lib/site-packages/mongoengine/django/utils.py deleted file mode 100644 index d3ef8a4b77..0000000000 --- a/awx/lib/site-packages/mongoengine/django/utils.py +++ /dev/null @@ -1,6 +0,0 @@ -try: - # django >= 1.4 - from django.utils.timezone import now as datetime_now -except ImportError: - from datetime import datetime - datetime_now = datetime.now diff --git a/awx/lib/site-packages/mongoengine/document.py b/awx/lib/site-packages/mongoengine/document.py deleted file mode 100644 index eea5dabc1a..0000000000 --- a/awx/lib/site-packages/mongoengine/document.py +++ /dev/null @@ -1,869 +0,0 @@ -import warnings - -import hashlib -import pymongo -import re - -from pymongo.read_preferences import ReadPreference -from bson import ObjectId -from bson.dbref import DBRef -from mongoengine import signals -from mongoengine.common import _import_class -from mongoengine.base import ( - DocumentMetaclass, - TopLevelDocumentMetaclass, - BaseDocument, - BaseDict, - BaseList, - EmbeddedDocumentList, - ALLOW_INHERITANCE, - get_document -) -from mongoengine.errors import ValidationError, InvalidQueryError, InvalidDocumentError -from mongoengine.queryset import (OperationError, NotUniqueError, - QuerySet, transform) -from mongoengine.connection import get_db, DEFAULT_CONNECTION_NAME -from mongoengine.context_managers import switch_db, switch_collection - -__all__ = ('Document', 'EmbeddedDocument', 'DynamicDocument', - 'DynamicEmbeddedDocument', 'OperationError', - 'InvalidCollectionError', 'NotUniqueError', 'MapReduceDocument') - - -def includes_cls(fields): - """ Helper function used for ensuring and comparing indexes - """ - - first_field = None - if len(fields): - if isinstance(fields[0], basestring): - first_field = fields[0] - elif isinstance(fields[0], (list, tuple)) and len(fields[0]): - first_field = fields[0][0] - return first_field == '_cls' - - -class InvalidCollectionError(Exception): - pass - - -class EmbeddedDocument(BaseDocument): - - """A :class:`~mongoengine.Document` that isn't stored in its own - collection. :class:`~mongoengine.EmbeddedDocument`\ s should be used as - fields on :class:`~mongoengine.Document`\ s through the - :class:`~mongoengine.EmbeddedDocumentField` field type. - - A :class:`~mongoengine.EmbeddedDocument` subclass may be itself subclassed, - to create a specialised version of the embedded document that will be - stored in the same collection. To facilitate this behaviour a `_cls` - field is added to documents (hidden though the MongoEngine interface). - To disable this behaviour and remove the dependence on the presence of - `_cls` set :attr:`allow_inheritance` to ``False`` in the :attr:`meta` - dictionary. - """ - - __slots__ = ('_instance') - - # The __metaclass__ attribute is removed by 2to3 when running with Python3 - # my_metaclass is defined so that metaclass can be queried in Python 2 & 3 - my_metaclass = DocumentMetaclass - __metaclass__ = DocumentMetaclass - - def __init__(self, *args, **kwargs): - super(EmbeddedDocument, self).__init__(*args, **kwargs) - self._instance = None - self._changed_fields = [] - - def __eq__(self, other): - if isinstance(other, self.__class__): - return self._data == other._data - return False - - def __ne__(self, other): - return not self.__eq__(other) - - def save(self, *args, **kwargs): - self._instance.save(*args, **kwargs) - - def reload(self, *args, **kwargs): - self._instance.reload(*args, **kwargs) - - -class Document(BaseDocument): - - """The base class used for defining the structure and properties of - collections of documents stored in MongoDB. Inherit from this class, and - add fields as class attributes to define a document's structure. - Individual documents may then be created by making instances of the - :class:`~mongoengine.Document` subclass. - - By default, the MongoDB collection used to store documents created using a - :class:`~mongoengine.Document` subclass will be the name of the subclass - converted to lowercase. A different collection may be specified by - providing :attr:`collection` to the :attr:`meta` dictionary in the class - definition. - - A :class:`~mongoengine.Document` subclass may be itself subclassed, to - create a specialised version of the document that will be stored in the - same collection. To facilitate this behaviour a `_cls` - field is added to documents (hidden though the MongoEngine interface). - To disable this behaviour and remove the dependence on the presence of - `_cls` set :attr:`allow_inheritance` to ``False`` in the :attr:`meta` - dictionary. - - A :class:`~mongoengine.Document` may use a **Capped Collection** by - specifying :attr:`max_documents` and :attr:`max_size` in the :attr:`meta` - dictionary. :attr:`max_documents` is the maximum number of documents that - is allowed to be stored in the collection, and :attr:`max_size` is the - maximum size of the collection in bytes. If :attr:`max_size` is not - specified and :attr:`max_documents` is, :attr:`max_size` defaults to - 10000000 bytes (10MB). - - Indexes may be created by specifying :attr:`indexes` in the :attr:`meta` - dictionary. The value should be a list of field names or tuples of field - names. Index direction may be specified by prefixing the field names with - a **+** or **-** sign. - - Automatic index creation can be disabled by specifying - :attr:`auto_create_index` in the :attr:`meta` dictionary. If this is set to - False then indexes will not be created by MongoEngine. This is useful in - production systems where index creation is performed as part of a - deployment system. - - By default, _cls will be added to the start of every index (that - doesn't contain a list) if allow_inheritance is True. This can be - disabled by either setting cls to False on the specific index or - by setting index_cls to False on the meta dictionary for the document. - """ - - # The __metaclass__ attribute is removed by 2to3 when running with Python3 - # my_metaclass is defined so that metaclass can be queried in Python 2 & 3 - my_metaclass = TopLevelDocumentMetaclass - __metaclass__ = TopLevelDocumentMetaclass - - __slots__ = ('__objects') - - def pk(): - """Primary key alias - """ - - def fget(self): - return getattr(self, self._meta['id_field']) - - def fset(self, value): - return setattr(self, self._meta['id_field'], value) - return property(fget, fset) - pk = pk() - - @classmethod - def _get_db(cls): - """Some Model using other db_alias""" - return get_db(cls._meta.get("db_alias", DEFAULT_CONNECTION_NAME)) - - @classmethod - def _get_collection(cls): - """Returns the collection for the document.""" - if not hasattr(cls, '_collection') or cls._collection is None: - db = cls._get_db() - collection_name = cls._get_collection_name() - # Create collection as a capped collection if specified - if cls._meta['max_size'] or cls._meta['max_documents']: - # Get max document limit and max byte size from meta - max_size = cls._meta['max_size'] or 10000000 # 10MB default - max_documents = cls._meta['max_documents'] - - if collection_name in db.collection_names(): - cls._collection = db[collection_name] - # The collection already exists, check if its capped - # options match the specified capped options - options = cls._collection.options() - if options.get('max') != max_documents or \ - options.get('size') != max_size: - msg = (('Cannot create collection "%s" as a capped ' - 'collection as it already exists') - % cls._collection) - raise InvalidCollectionError(msg) - else: - # Create the collection as a capped collection - opts = {'capped': True, 'size': max_size} - if max_documents: - opts['max'] = max_documents - cls._collection = db.create_collection( - collection_name, **opts - ) - else: - cls._collection = db[collection_name] - if cls._meta.get('auto_create_index', True): - cls.ensure_indexes() - return cls._collection - - def modify(self, query={}, **update): - """Perform an atomic update of the document in the database and reload - the document object using updated version. - - Returns True if the document has been updated or False if the document - in the database doesn't match the query. - - .. note:: All unsaved changes that has been made to the document are - rejected if the method returns True. - - :param query: the update will be performed only if the document in the - database matches the query - :param update: Django-style update keyword arguments - """ - - if self.pk is None: - raise InvalidDocumentError("The document does not have a primary key.") - - id_field = self._meta["id_field"] - query = query.copy() if isinstance(query, dict) else query.to_query(self) - - if id_field not in query: - query[id_field] = self.pk - elif query[id_field] != self.pk: - raise InvalidQueryError("Invalid document modify query: it must modify only this document.") - - updated = self._qs(**query).modify(new=True, **update) - if updated is None: - return False - - for field in self._fields_ordered: - setattr(self, field, self._reload(field, updated[field])) - - self._changed_fields = updated._changed_fields - self._created = False - - return True - - def save(self, force_insert=False, validate=True, clean=True, - write_concern=None, cascade=None, cascade_kwargs=None, - _refs=None, save_condition=None, **kwargs): - """Save the :class:`~mongoengine.Document` to the database. If the - document already exists, it will be updated, otherwise it will be - created. - - :param force_insert: only try to create a new document, don't allow - updates of existing documents - :param validate: validates the document; set to ``False`` to skip. - :param clean: call the document clean method, requires `validate` to be - True. - :param write_concern: Extra keyword arguments are passed down to - :meth:`~pymongo.collection.Collection.save` OR - :meth:`~pymongo.collection.Collection.insert` - which will be used as options for the resultant - ``getLastError`` command. For example, - ``save(..., write_concern={w: 2, fsync: True}, ...)`` will - wait until at least two servers have recorded the write and - will force an fsync on the primary server. - :param cascade: Sets the flag for cascading saves. You can set a - default by setting "cascade" in the document __meta__ - :param cascade_kwargs: (optional) kwargs dictionary to be passed throw - to cascading saves. Implies ``cascade=True``. - :param _refs: A list of processed references used in cascading saves - :param save_condition: only perform save if matching record in db - satisfies condition(s) (e.g., version number) - - .. versionchanged:: 0.5 - In existing documents it only saves changed fields using - set / unset. Saves are cascaded and any - :class:`~bson.dbref.DBRef` objects that have changes are - saved as well. - .. versionchanged:: 0.6 - Added cascading saves - .. versionchanged:: 0.8 - Cascade saves are optional and default to False. If you want - fine grain control then you can turn off using document - meta['cascade'] = True. Also you can pass different kwargs to - the cascade save using cascade_kwargs which overwrites the - existing kwargs with custom values. - .. versionchanged:: 0.8.5 - Optional save_condition that only overwrites existing documents - if the condition is satisfied in the current db record. - """ - signals.pre_save.send(self.__class__, document=self) - - if validate: - self.validate(clean=clean) - - if write_concern is None: - write_concern = {"w": 1} - - doc = self.to_mongo() - - created = ('_id' not in doc or self._created or force_insert) - - signals.pre_save_post_validation.send(self.__class__, document=self, - created=created) - - try: - collection = self._get_collection() - if self._meta.get('auto_create_index', True): - self.ensure_indexes() - if created: - if force_insert: - object_id = collection.insert(doc, **write_concern) - else: - object_id = collection.save(doc, **write_concern) - else: - object_id = doc['_id'] - updates, removals = self._delta() - # Need to add shard key to query, or you get an error - if save_condition is not None: - select_dict = transform.query(self.__class__, - **save_condition) - else: - select_dict = {} - select_dict['_id'] = object_id - shard_key = self.__class__._meta.get('shard_key', tuple()) - for k in shard_key: - actual_key = self._db_field_map.get(k, k) - select_dict[actual_key] = doc[actual_key] - - def is_new_object(last_error): - if last_error is not None: - updated = last_error.get("updatedExisting") - if updated is not None: - return not updated - return created - - update_query = {} - - if updates: - update_query["$set"] = updates - if removals: - update_query["$unset"] = removals - if updates or removals: - upsert = save_condition is None - last_error = collection.update(select_dict, update_query, - upsert=upsert, **write_concern) - created = is_new_object(last_error) - - if cascade is None: - cascade = self._meta.get( - 'cascade', False) or cascade_kwargs is not None - - if cascade: - kwargs = { - "force_insert": force_insert, - "validate": validate, - "write_concern": write_concern, - "cascade": cascade - } - if cascade_kwargs: # Allow granular control over cascades - kwargs.update(cascade_kwargs) - kwargs['_refs'] = _refs - self.cascade_save(**kwargs) - except pymongo.errors.DuplicateKeyError, err: - message = u'Tried to save duplicate unique keys (%s)' - raise NotUniqueError(message % unicode(err)) - except pymongo.errors.OperationFailure, err: - message = 'Could not save document (%s)' - if re.match('^E1100[01] duplicate key', unicode(err)): - # E11000 - duplicate key error index - # E11001 - duplicate key on update - message = u'Tried to save duplicate unique keys (%s)' - raise NotUniqueError(message % unicode(err)) - raise OperationError(message % unicode(err)) - id_field = self._meta['id_field'] - if created or id_field not in self._meta.get('shard_key', []): - self[id_field] = self._fields[id_field].to_python(object_id) - - signals.post_save.send(self.__class__, document=self, created=created) - self._clear_changed_fields() - self._created = False - return self - - def cascade_save(self, *args, **kwargs): - """Recursively saves any references / - generic references on an objects""" - _refs = kwargs.get('_refs', []) or [] - - ReferenceField = _import_class('ReferenceField') - GenericReferenceField = _import_class('GenericReferenceField') - - for name, cls in self._fields.items(): - if not isinstance(cls, (ReferenceField, - GenericReferenceField)): - continue - - ref = self._data.get(name) - if not ref or isinstance(ref, DBRef): - continue - - if not getattr(ref, '_changed_fields', True): - continue - - ref_id = "%s,%s" % (ref.__class__.__name__, str(ref._data)) - if ref and ref_id not in _refs: - _refs.append(ref_id) - kwargs["_refs"] = _refs - ref.save(**kwargs) - ref._changed_fields = [] - - @property - def _qs(self): - """ - Returns the queryset to use for updating / reloading / deletions - """ - if not hasattr(self, '__objects'): - self.__objects = QuerySet(self, self._get_collection()) - return self.__objects - - @property - def _object_key(self): - """Dict to identify object in collection - """ - select_dict = {'pk': self.pk} - shard_key = self.__class__._meta.get('shard_key', tuple()) - for k in shard_key: - select_dict[k] = getattr(self, k) - return select_dict - - def update(self, **kwargs): - """Performs an update on the :class:`~mongoengine.Document` - A convenience wrapper to :meth:`~mongoengine.QuerySet.update`. - - Raises :class:`OperationError` if called on an object that has not yet - been saved. - """ - if not self.pk: - if kwargs.get('upsert', False): - query = self.to_mongo() - if "_cls" in query: - del(query["_cls"]) - return self._qs.filter(**query).update_one(**kwargs) - else: - raise OperationError( - 'attempt to update a document not yet saved') - - # Need to add shard key to query, or you get an error - return self._qs.filter(**self._object_key).update_one(**kwargs) - - def delete(self, **write_concern): - """Delete the :class:`~mongoengine.Document` from the database. This - will only take effect if the document has been previously saved. - - :param write_concern: Extra keyword arguments are passed down which - will be used as options for the resultant - ``getLastError`` command. For example, - ``save(..., write_concern={w: 2, fsync: True}, ...)`` will - wait until at least two servers have recorded the write and - will force an fsync on the primary server. - """ - signals.pre_delete.send(self.__class__, document=self) - - try: - self._qs.filter( - **self._object_key).delete(write_concern=write_concern, _from_doc_delete=True) - except pymongo.errors.OperationFailure, err: - message = u'Could not delete document (%s)' % err.message - raise OperationError(message) - signals.post_delete.send(self.__class__, document=self) - - def switch_db(self, db_alias): - """ - Temporarily switch the database for a document instance. - - Only really useful for archiving off data and calling `save()`:: - - user = User.objects.get(id=user_id) - user.switch_db('archive-db') - user.save() - - :param str db_alias: The database alias to use for saving the document - - .. seealso:: - Use :class:`~mongoengine.context_managers.switch_collection` - if you need to read from another collection - """ - with switch_db(self.__class__, db_alias) as cls: - collection = cls._get_collection() - db = cls._get_db() - self._get_collection = lambda: collection - self._get_db = lambda: db - self._collection = collection - self._created = True - self.__objects = self._qs - self.__objects._collection_obj = collection - return self - - def switch_collection(self, collection_name): - """ - Temporarily switch the collection for a document instance. - - Only really useful for archiving off data and calling `save()`:: - - user = User.objects.get(id=user_id) - user.switch_collection('old-users') - user.save() - - :param str collection_name: The database alias to use for saving the - document - - .. seealso:: - Use :class:`~mongoengine.context_managers.switch_db` - if you need to read from another database - """ - with switch_collection(self.__class__, collection_name) as cls: - collection = cls._get_collection() - self._get_collection = lambda: collection - self._collection = collection - self._created = True - self.__objects = self._qs - self.__objects._collection_obj = collection - return self - - def select_related(self, max_depth=1): - """Handles dereferencing of :class:`~bson.dbref.DBRef` objects to - a maximum depth in order to cut down the number queries to mongodb. - - .. versionadded:: 0.5 - """ - DeReference = _import_class('DeReference') - DeReference()([self], max_depth + 1) - return self - - def reload(self, *fields, **kwargs): - """Reloads all attributes from the database. - - :param fields: (optional) args list of fields to reload - :param max_depth: (optional) depth of dereferencing to follow - - .. versionadded:: 0.1.2 - .. versionchanged:: 0.6 Now chainable - .. versionchanged:: 0.9 Can provide specific fields to reload - """ - max_depth = 1 - if fields and isinstance(fields[0], int): - max_depth = fields[0] - fields = fields[1:] - elif "max_depth" in kwargs: - max_depth = kwargs["max_depth"] - - if not self.pk: - raise self.DoesNotExist("Document does not exist") - obj = self._qs.read_preference(ReadPreference.PRIMARY).filter( - **self._object_key).only(*fields).limit(1 - ).select_related(max_depth=max_depth) - - if obj: - obj = obj[0] - else: - raise self.DoesNotExist("Document does not exist") - - for field in self._fields_ordered: - if not fields or field in fields: - try: - setattr(self, field, self._reload(field, obj[field])) - except KeyError: - # If field is removed from the database while the object - # is in memory, a reload would cause a KeyError - # i.e. obj.update(unset__field=1) followed by obj.reload() - delattr(self, field) - - self._changed_fields = obj._changed_fields - self._created = False - return self - - def _reload(self, key, value): - """Used by :meth:`~mongoengine.Document.reload` to ensure the - correct instance is linked to self. - """ - if isinstance(value, BaseDict): - value = [(k, self._reload(k, v)) for k, v in value.items()] - value = BaseDict(value, self, key) - elif isinstance(value, EmbeddedDocumentList): - value = [self._reload(key, v) for v in value] - value = EmbeddedDocumentList(value, self, key) - elif isinstance(value, BaseList): - value = [self._reload(key, v) for v in value] - value = BaseList(value, self, key) - elif isinstance(value, (EmbeddedDocument, DynamicEmbeddedDocument)): - value._instance = None - value._changed_fields = [] - return value - - def to_dbref(self): - """Returns an instance of :class:`~bson.dbref.DBRef` useful in - `__raw__` queries.""" - if not self.pk: - msg = "Only saved documents can have a valid dbref" - raise OperationError(msg) - return DBRef(self.__class__._get_collection_name(), self.pk) - - @classmethod - def register_delete_rule(cls, document_cls, field_name, rule): - """This method registers the delete rules to apply when removing this - object. - """ - classes = [get_document(class_name) - for class_name in cls._subclasses - if class_name != cls.__name__] + [cls] - documents = [get_document(class_name) - for class_name in document_cls._subclasses - if class_name != document_cls.__name__] + [document_cls] - - for cls in classes: - for document_cls in documents: - delete_rules = cls._meta.get('delete_rules') or {} - delete_rules[(document_cls, field_name)] = rule - cls._meta['delete_rules'] = delete_rules - - @classmethod - def drop_collection(cls): - """Drops the entire collection associated with this - :class:`~mongoengine.Document` type from the database. - """ - cls._collection = None - db = cls._get_db() - db.drop_collection(cls._get_collection_name()) - - @classmethod - def ensure_index(cls, key_or_list, drop_dups=False, background=False, - **kwargs): - """Ensure that the given indexes are in place. - - :param key_or_list: a single index key or a list of index keys (to - construct a multi-field index); keys may be prefixed with a **+** - or a **-** to determine the index ordering - """ - index_spec = cls._build_index_spec(key_or_list) - index_spec = index_spec.copy() - fields = index_spec.pop('fields') - index_spec['drop_dups'] = drop_dups - index_spec['background'] = background - index_spec.update(kwargs) - - return cls._get_collection().ensure_index(fields, **index_spec) - - @classmethod - def ensure_indexes(cls): - """Checks the document meta data and ensures all the indexes exist. - - Global defaults can be set in the meta - see :doc:`guide/defining-documents` - - .. note:: You can disable automatic index creation by setting - `auto_create_index` to False in the documents meta data - """ - background = cls._meta.get('index_background', False) - drop_dups = cls._meta.get('index_drop_dups', False) - index_opts = cls._meta.get('index_opts') or {} - index_cls = cls._meta.get('index_cls', True) - - collection = cls._get_collection() - # 746: when connection is via mongos, the read preference is not necessarily an indication that - # this code runs on a secondary - if not collection.is_mongos and collection.read_preference > 1: - return - - # determine if an index which we are creating includes - # _cls as its first field; if so, we can avoid creating - # an extra index on _cls, as mongodb will use the existing - # index to service queries against _cls - cls_indexed = False - - # Ensure document-defined indexes are created - if cls._meta['index_specs']: - index_spec = cls._meta['index_specs'] - for spec in index_spec: - spec = spec.copy() - fields = spec.pop('fields') - cls_indexed = cls_indexed or includes_cls(fields) - opts = index_opts.copy() - opts.update(spec) - collection.ensure_index(fields, background=background, - drop_dups=drop_dups, **opts) - - # If _cls is being used (for polymorphism), it needs an index, - # only if another index doesn't begin with _cls - if (index_cls and not cls_indexed and - cls._meta.get('allow_inheritance', ALLOW_INHERITANCE) is True): - collection.ensure_index('_cls', background=background, - **index_opts) - - @classmethod - def list_indexes(cls, go_up=True, go_down=True): - """ Lists all of the indexes that should be created for given - collection. It includes all the indexes from super- and sub-classes. - """ - - if cls._meta.get('abstract'): - return [] - - # get all the base classes, subclasses and siblings - classes = [] - - def get_classes(cls): - - if (cls not in classes and - isinstance(cls, TopLevelDocumentMetaclass)): - classes.append(cls) - - for base_cls in cls.__bases__: - if (isinstance(base_cls, TopLevelDocumentMetaclass) and - base_cls != Document and - not base_cls._meta.get('abstract') and - base_cls._get_collection().full_name == cls._get_collection().full_name and - base_cls not in classes): - classes.append(base_cls) - get_classes(base_cls) - for subclass in cls.__subclasses__(): - if (isinstance(base_cls, TopLevelDocumentMetaclass) and - subclass._get_collection().full_name == cls._get_collection().full_name and - subclass not in classes): - classes.append(subclass) - get_classes(subclass) - - get_classes(cls) - - # get the indexes spec for all of the gathered classes - def get_indexes_spec(cls): - indexes = [] - - if cls._meta['index_specs']: - index_spec = cls._meta['index_specs'] - for spec in index_spec: - spec = spec.copy() - fields = spec.pop('fields') - indexes.append(fields) - return indexes - - indexes = [] - for cls in classes: - for index in get_indexes_spec(cls): - if index not in indexes: - indexes.append(index) - - # finish up by appending { '_id': 1 } and { '_cls': 1 }, if needed - if [(u'_id', 1)] not in indexes: - indexes.append([(u'_id', 1)]) - if (cls._meta.get('index_cls', True) and - cls._meta.get('allow_inheritance', ALLOW_INHERITANCE) is True): - indexes.append([(u'_cls', 1)]) - - return indexes - - @classmethod - def compare_indexes(cls): - """ Compares the indexes defined in MongoEngine with the ones existing - in the database. Returns any missing/extra indexes. - """ - - required = cls.list_indexes() - existing = [info['key'] - for info in cls._get_collection().index_information().values()] - missing = [index for index in required if index not in existing] - extra = [index for index in existing if index not in required] - - # if { _cls: 1 } is missing, make sure it's *really* necessary - if [(u'_cls', 1)] in missing: - cls_obsolete = False - for index in existing: - if includes_cls(index) and index not in extra: - cls_obsolete = True - break - if cls_obsolete: - missing.remove([(u'_cls', 1)]) - - return {'missing': missing, 'extra': extra} - - -class DynamicDocument(Document): - - """A Dynamic Document class allowing flexible, expandable and uncontrolled - schemas. As a :class:`~mongoengine.Document` subclass, acts in the same - way as an ordinary document but has expando style properties. Any data - passed or set against the :class:`~mongoengine.DynamicDocument` that is - not a field is automatically converted into a - :class:`~mongoengine.fields.DynamicField` and data can be attributed to that - field. - - .. note:: - - There is one caveat on Dynamic Documents: fields cannot start with `_` - """ - - # The __metaclass__ attribute is removed by 2to3 when running with Python3 - # my_metaclass is defined so that metaclass can be queried in Python 2 & 3 - my_metaclass = TopLevelDocumentMetaclass - __metaclass__ = TopLevelDocumentMetaclass - - _dynamic = True - - def __delattr__(self, *args, **kwargs): - """Deletes the attribute by setting to None and allowing _delta to unset - it""" - field_name = args[0] - if field_name in self._dynamic_fields: - setattr(self, field_name, None) - else: - super(DynamicDocument, self).__delattr__(*args, **kwargs) - - -class DynamicEmbeddedDocument(EmbeddedDocument): - - """A Dynamic Embedded Document class allowing flexible, expandable and - uncontrolled schemas. See :class:`~mongoengine.DynamicDocument` for more - information about dynamic documents. - """ - - # The __metaclass__ attribute is removed by 2to3 when running with Python3 - # my_metaclass is defined so that metaclass can be queried in Python 2 & 3 - my_metaclass = DocumentMetaclass - __metaclass__ = DocumentMetaclass - - _dynamic = True - - def __delattr__(self, *args, **kwargs): - """Deletes the attribute by setting to None and allowing _delta to unset - it""" - field_name = args[0] - if field_name in self._fields: - default = self._fields[field_name].default - if callable(default): - default = default() - setattr(self, field_name, default) - else: - setattr(self, field_name, None) - - -class MapReduceDocument(object): - - """A document returned from a map/reduce query. - - :param collection: An instance of :class:`~pymongo.Collection` - :param key: Document/result key, often an instance of - :class:`~bson.objectid.ObjectId`. If supplied as - an ``ObjectId`` found in the given ``collection``, - the object can be accessed via the ``object`` property. - :param value: The result(s) for this key. - - .. versionadded:: 0.3 - """ - - def __init__(self, document, collection, key, value): - self._document = document - self._collection = collection - self.key = key - self.value = value - - @property - def object(self): - """Lazy-load the object referenced by ``self.key``. ``self.key`` - should be the ``primary_key``. - """ - id_field = self._document()._meta['id_field'] - id_field_type = type(id_field) - - if not isinstance(self.key, id_field_type): - try: - self.key = id_field_type(self.key) - except: - raise Exception("Could not cast key as %s" % - id_field_type.__name__) - - if not hasattr(self, "_key_object"): - self._key_object = self._document.objects.with_id(self.key) - return self._key_object - return self._key_object diff --git a/awx/lib/site-packages/mongoengine/errors.py b/awx/lib/site-packages/mongoengine/errors.py deleted file mode 100644 index 6cde7771e5..0000000000 --- a/awx/lib/site-packages/mongoengine/errors.py +++ /dev/null @@ -1,131 +0,0 @@ -from collections import defaultdict - -from mongoengine.python_support import txt_type - - -__all__ = ('NotRegistered', 'InvalidDocumentError', 'LookUpError', - 'DoesNotExist', 'MultipleObjectsReturned', 'InvalidQueryError', - 'OperationError', 'NotUniqueError', 'FieldDoesNotExist', - 'ValidationError') - - -class NotRegistered(Exception): - pass - - -class InvalidDocumentError(Exception): - pass - - -class LookUpError(AttributeError): - pass - - -class DoesNotExist(Exception): - pass - - -class MultipleObjectsReturned(Exception): - pass - - -class InvalidQueryError(Exception): - pass - - -class OperationError(Exception): - pass - - -class NotUniqueError(OperationError): - pass - - -class FieldDoesNotExist(Exception): - pass - - -class ValidationError(AssertionError): - """Validation exception. - - May represent an error validating a field or a - document containing fields with validation errors. - - :ivar errors: A dictionary of errors for fields within this - document or list, or None if the error is for an - individual field. - """ - - errors = {} - field_name = None - _message = None - - def __init__(self, message="", **kwargs): - self.errors = kwargs.get('errors', {}) - self.field_name = kwargs.get('field_name') - self.message = message - - def __str__(self): - return txt_type(self.message) - - def __repr__(self): - return '%s(%s,)' % (self.__class__.__name__, self.message) - - def __getattribute__(self, name): - message = super(ValidationError, self).__getattribute__(name) - if name == 'message': - if self.field_name: - message = '%s' % message - if self.errors: - message = '%s(%s)' % (message, self._format_errors()) - return message - - def _get_message(self): - return self._message - - def _set_message(self, message): - self._message = message - - message = property(_get_message, _set_message) - - def to_dict(self): - """Returns a dictionary of all errors within a document - - Keys are field names or list indices and values are the - validation error messages, or a nested dictionary of - errors for an embedded document or list. - """ - - def build_dict(source): - errors_dict = {} - if not source: - return errors_dict - if isinstance(source, dict): - for field_name, error in source.iteritems(): - errors_dict[field_name] = build_dict(error) - elif isinstance(source, ValidationError) and source.errors: - return build_dict(source.errors) - else: - return unicode(source) - return errors_dict - if not self.errors: - return {} - return build_dict(self.errors) - - def _format_errors(self): - """Returns a string listing all errors within a document""" - - def generate_key(value, prefix=''): - if isinstance(value, list): - value = ' '.join([generate_key(k) for k in value]) - if isinstance(value, dict): - value = ' '.join( - [generate_key(v, k) for k, v in value.iteritems()]) - - results = "%s.%s" % (prefix, value) if prefix else value - return results - - error_dict = defaultdict(list) - for k, v in self.to_dict().iteritems(): - error_dict[generate_key(v)].append(k) - return ' '.join(["%s: %s" % (k, v) for k, v in error_dict.iteritems()]) diff --git a/awx/lib/site-packages/mongoengine/fields.py b/awx/lib/site-packages/mongoengine/fields.py deleted file mode 100644 index 3c1db4ac38..0000000000 --- a/awx/lib/site-packages/mongoengine/fields.py +++ /dev/null @@ -1,2006 +0,0 @@ -import datetime -import decimal -import itertools -import re -import time -import urllib2 -import uuid -import warnings -from operator import itemgetter - -try: - import dateutil -except ImportError: - dateutil = None -else: - import dateutil.parser - -import pymongo -import gridfs -from bson import Binary, DBRef, SON, ObjectId - -from mongoengine.errors import ValidationError -from mongoengine.python_support import (PY3, bin_type, txt_type, - str_types, StringIO) -from base import (BaseField, ComplexBaseField, ObjectIdField, GeoJsonBaseField, - get_document, BaseDocument) -from queryset import DO_NOTHING, QuerySet -from document import Document, EmbeddedDocument -from connection import get_db, DEFAULT_CONNECTION_NAME - -try: - from PIL import Image, ImageOps -except ImportError: - Image = None - ImageOps = None - -__all__ = [ - 'StringField', 'URLField', 'EmailField', 'IntField', 'LongField', - 'FloatField', 'DecimalField', 'BooleanField', 'DateTimeField', - 'ComplexDateTimeField', 'EmbeddedDocumentField', 'ObjectIdField', - 'GenericEmbeddedDocumentField', 'DynamicField', 'ListField', - 'SortedListField', 'EmbeddedDocumentListField', 'DictField', - 'MapField', 'ReferenceField', 'CachedReferenceField', - 'GenericReferenceField', 'BinaryField', 'GridFSError', 'GridFSProxy', - 'FileField', 'ImageGridFsProxy', 'ImproperlyConfigured', 'ImageField', - 'GeoPointField', 'PointField', 'LineStringField', 'PolygonField', - 'SequenceField', 'UUIDField', 'MultiPointField', 'MultiLineStringField', - 'MultiPolygonField', 'GeoJsonBaseField'] - - -RECURSIVE_REFERENCE_CONSTANT = 'self' - - -class StringField(BaseField): - - """A unicode string field. - """ - - def __init__(self, regex=None, max_length=None, min_length=None, **kwargs): - self.regex = re.compile(regex) if regex else None - self.max_length = max_length - self.min_length = min_length - super(StringField, self).__init__(**kwargs) - - def to_python(self, value): - if isinstance(value, unicode): - return value - try: - value = value.decode('utf-8') - except: - pass - return value - - def validate(self, value): - if not isinstance(value, basestring): - self.error('StringField only accepts string values') - - if self.max_length is not None and len(value) > self.max_length: - self.error('String value is too long') - - if self.min_length is not None and len(value) < self.min_length: - self.error('String value is too short') - - if self.regex is not None and self.regex.match(value) is None: - self.error('String value did not match validation regex') - - def lookup_member(self, member_name): - return None - - def prepare_query_value(self, op, value): - if not isinstance(op, basestring): - return value - - if op.lstrip('i') in ('startswith', 'endswith', 'contains', 'exact'): - flags = 0 - if op.startswith('i'): - flags = re.IGNORECASE - op = op.lstrip('i') - - regex = r'%s' - if op == 'startswith': - regex = r'^%s' - elif op == 'endswith': - regex = r'%s$' - elif op == 'exact': - regex = r'^%s$' - - # escape unsafe characters which could lead to a re.error - value = re.escape(value) - value = re.compile(regex % value, flags) - return value - - -class URLField(StringField): - - """A field that validates input as an URL. - - .. versionadded:: 0.3 - """ - - _URL_REGEX = re.compile( - r'^(?:http|ftp)s?://' # http:// or https:// - # domain... - r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' - r'localhost|' # localhost... - r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip - r'(?::\d+)?' # optional port - r'(?:/?|[/?]\S+)$', re.IGNORECASE) - - def __init__(self, verify_exists=False, url_regex=None, **kwargs): - self.verify_exists = verify_exists - self.url_regex = url_regex or self._URL_REGEX - super(URLField, self).__init__(**kwargs) - - def validate(self, value): - if not self.url_regex.match(value): - self.error('Invalid URL: %s' % value) - return - - if self.verify_exists: - warnings.warn( - "The URLField verify_exists argument has intractable security " - "and performance issues. Accordingly, it has been deprecated.", - DeprecationWarning) - try: - request = urllib2.Request(value) - urllib2.urlopen(request) - except Exception, e: - self.error('This URL appears to be a broken link: %s' % e) - - -class EmailField(StringField): - - """A field that validates input as an E-Mail-Address. - - .. versionadded:: 0.4 - """ - - EMAIL_REGEX = re.compile( - # dot-atom - r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" - # quoted-string - r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' - # domain (max length of an ICAAN TLD is 22 characters) - r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,253}[A-Z0-9])?\.)+[A-Z]{2,22}$', re.IGNORECASE - ) - - def validate(self, value): - if not EmailField.EMAIL_REGEX.match(value): - self.error('Invalid Mail-address: %s' % value) - super(EmailField, self).validate(value) - - -class IntField(BaseField): - - """An 32-bit integer field. - """ - - def __init__(self, min_value=None, max_value=None, **kwargs): - self.min_value, self.max_value = min_value, max_value - super(IntField, self).__init__(**kwargs) - - def to_python(self, value): - try: - value = int(value) - except ValueError: - pass - return value - - def validate(self, value): - try: - value = int(value) - except: - self.error('%s could not be converted to int' % value) - - if self.min_value is not None and value < self.min_value: - self.error('Integer value is too small') - - if self.max_value is not None and value > self.max_value: - self.error('Integer value is too large') - - def prepare_query_value(self, op, value): - if value is None: - return value - - return int(value) - - -class LongField(BaseField): - - """An 64-bit integer field. - """ - - def __init__(self, min_value=None, max_value=None, **kwargs): - self.min_value, self.max_value = min_value, max_value - super(LongField, self).__init__(**kwargs) - - def to_python(self, value): - try: - value = long(value) - except ValueError: - pass - return value - - def validate(self, value): - try: - value = long(value) - except: - self.error('%s could not be converted to long' % value) - - if self.min_value is not None and value < self.min_value: - self.error('Long value is too small') - - if self.max_value is not None and value > self.max_value: - self.error('Long value is too large') - - def prepare_query_value(self, op, value): - if value is None: - return value - - return long(value) - - -class FloatField(BaseField): - - """An floating point number field. - """ - - def __init__(self, min_value=None, max_value=None, **kwargs): - self.min_value, self.max_value = min_value, max_value - super(FloatField, self).__init__(**kwargs) - - def to_python(self, value): - try: - value = float(value) - except ValueError: - pass - return value - - def validate(self, value): - if isinstance(value, int): - value = float(value) - if not isinstance(value, float): - self.error('FloatField only accepts float values') - - if self.min_value is not None and value < self.min_value: - self.error('Float value is too small') - - if self.max_value is not None and value > self.max_value: - self.error('Float value is too large') - - def prepare_query_value(self, op, value): - if value is None: - return value - - return float(value) - - -class DecimalField(BaseField): - - """A fixed-point decimal number field. - - .. versionchanged:: 0.8 - .. versionadded:: 0.3 - """ - - def __init__(self, min_value=None, max_value=None, force_string=False, - precision=2, rounding=decimal.ROUND_HALF_UP, **kwargs): - """ - :param min_value: Validation rule for the minimum acceptable value. - :param max_value: Validation rule for the maximum acceptable value. - :param force_string: Store as a string. - :param precision: Number of decimal places to store. - :param rounding: The rounding rule from the python decimal library: - - - decimal.ROUND_CEILING (towards Infinity) - - decimal.ROUND_DOWN (towards zero) - - decimal.ROUND_FLOOR (towards -Infinity) - - decimal.ROUND_HALF_DOWN (to nearest with ties going towards zero) - - decimal.ROUND_HALF_EVEN (to nearest with ties going to nearest even integer) - - decimal.ROUND_HALF_UP (to nearest with ties going away from zero) - - decimal.ROUND_UP (away from zero) - - decimal.ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero) - - Defaults to: ``decimal.ROUND_HALF_UP`` - - """ - self.min_value = min_value - self.max_value = max_value - self.force_string = force_string - self.precision = precision - self.rounding = rounding - - super(DecimalField, self).__init__(**kwargs) - - def to_python(self, value): - if value is None: - return value - - # Convert to string for python 2.6 before casting to Decimal - try: - value = decimal.Decimal("%s" % value) - except decimal.InvalidOperation: - return value - return value.quantize(decimal.Decimal(".%s" % ("0" * self.precision)), rounding=self.rounding) - - def to_mongo(self, value, use_db_field=True): - if value is None: - return value - if self.force_string: - return unicode(value) - return float(self.to_python(value)) - - def validate(self, value): - if not isinstance(value, decimal.Decimal): - if not isinstance(value, basestring): - value = unicode(value) - try: - value = decimal.Decimal(value) - except Exception, exc: - self.error('Could not convert value to decimal: %s' % exc) - - if self.min_value is not None and value < self.min_value: - self.error('Decimal value is too small') - - if self.max_value is not None and value > self.max_value: - self.error('Decimal value is too large') - - def prepare_query_value(self, op, value): - return self.to_mongo(value) - - -class BooleanField(BaseField): - - """A boolean field type. - - .. versionadded:: 0.1.2 - """ - - def to_python(self, value): - try: - value = bool(value) - except ValueError: - pass - return value - - def validate(self, value): - if not isinstance(value, bool): - self.error('BooleanField only accepts boolean values') - - -class DateTimeField(BaseField): - - """A datetime field. - - Uses the python-dateutil library if available alternatively use time.strptime - to parse the dates. Note: python-dateutil's parser is fully featured and when - installed you can utilise it to convert varying types of date formats into valid - python datetime objects. - - Note: Microseconds are rounded to the nearest millisecond. - Pre UTC microsecond support is effectively broken. - Use :class:`~mongoengine.fields.ComplexDateTimeField` if you - need accurate microsecond support. - """ - - def validate(self, value): - new_value = self.to_mongo(value) - if not isinstance(new_value, (datetime.datetime, datetime.date)): - self.error(u'cannot parse date "%s"' % value) - - def to_mongo(self, value): - if value is None: - return value - if isinstance(value, datetime.datetime): - return value - if isinstance(value, datetime.date): - return datetime.datetime(value.year, value.month, value.day) - if callable(value): - return value() - - if not isinstance(value, basestring): - return None - - # Attempt to parse a datetime: - if dateutil: - try: - return dateutil.parser.parse(value) - except (TypeError, ValueError): - return None - - # split usecs, because they are not recognized by strptime. - if '.' in value: - try: - value, usecs = value.split('.') - usecs = int(usecs) - except ValueError: - return None - else: - usecs = 0 - kwargs = {'microsecond': usecs} - try: # Seconds are optional, so try converting seconds first. - return datetime.datetime(*time.strptime(value, - '%Y-%m-%d %H:%M:%S')[:6], **kwargs) - except ValueError: - try: # Try without seconds. - return datetime.datetime(*time.strptime(value, - '%Y-%m-%d %H:%M')[:5], **kwargs) - except ValueError: # Try without hour/minutes/seconds. - try: - return datetime.datetime(*time.strptime(value, - '%Y-%m-%d')[:3], **kwargs) - except ValueError: - return None - - def prepare_query_value(self, op, value): - return self.to_mongo(value) - - -class ComplexDateTimeField(StringField): - - """ - ComplexDateTimeField handles microseconds exactly instead of rounding - like DateTimeField does. - - Derives from a StringField so you can do `gte` and `lte` filtering by - using lexicographical comparison when filtering / sorting strings. - - The stored string has the following format: - - YYYY,MM,DD,HH,MM,SS,NNNNNN - - Where NNNNNN is the number of microseconds of the represented `datetime`. - The `,` as the separator can be easily modified by passing the `separator` - keyword when initializing the field. - - .. versionadded:: 0.5 - """ - - def __init__(self, separator=',', **kwargs): - self.names = ['year', 'month', 'day', 'hour', 'minute', 'second', - 'microsecond'] - self.separtor = separator - super(ComplexDateTimeField, self).__init__(**kwargs) - - def _leading_zero(self, number): - """ - Converts the given number to a string. - - If it has only one digit, a leading zero so as it has always at least - two digits. - """ - if int(number) < 10: - return "0%s" % number - else: - return str(number) - - def _convert_from_datetime(self, val): - """ - Convert a `datetime` object to a string representation (which will be - stored in MongoDB). This is the reverse function of - `_convert_from_string`. - - >>> a = datetime(2011, 6, 8, 20, 26, 24, 192284) - >>> RealDateTimeField()._convert_from_datetime(a) - '2011,06,08,20,26,24,192284' - """ - data = [] - for name in self.names: - data.append(self._leading_zero(getattr(val, name))) - return ','.join(data) - - def _convert_from_string(self, data): - """ - Convert a string representation to a `datetime` object (the object you - will manipulate). This is the reverse function of - `_convert_from_datetime`. - - >>> a = '2011,06,08,20,26,24,192284' - >>> ComplexDateTimeField()._convert_from_string(a) - datetime.datetime(2011, 6, 8, 20, 26, 24, 192284) - """ - data = data.split(',') - data = map(int, data) - values = {} - for i in range(7): - values[self.names[i]] = data[i] - return datetime.datetime(**values) - - def __get__(self, instance, owner): - data = super(ComplexDateTimeField, self).__get__(instance, owner) - if data is None: - return None if self.null else datetime.datetime.now() - if isinstance(data, datetime.datetime): - return data - return self._convert_from_string(data) - - def __set__(self, instance, value): - value = self._convert_from_datetime(value) if value else value - return super(ComplexDateTimeField, self).__set__(instance, value) - - def validate(self, value): - value = self.to_python(value) - if not isinstance(value, datetime.datetime): - self.error('Only datetime objects may used in a ' - 'ComplexDateTimeField') - - def to_python(self, value): - original_value = value - try: - return self._convert_from_string(value) - except: - return original_value - - def to_mongo(self, value): - value = self.to_python(value) - return self._convert_from_datetime(value) - - def prepare_query_value(self, op, value): - return self._convert_from_datetime(value) - - -class EmbeddedDocumentField(BaseField): - - """An embedded document field - with a declared document_type. - Only valid values are subclasses of :class:`~mongoengine.EmbeddedDocument`. - """ - - def __init__(self, document_type, **kwargs): - if not isinstance(document_type, basestring): - if not issubclass(document_type, EmbeddedDocument): - self.error('Invalid embedded document class provided to an ' - 'EmbeddedDocumentField') - self.document_type_obj = document_type - super(EmbeddedDocumentField, self).__init__(**kwargs) - - @property - def document_type(self): - if isinstance(self.document_type_obj, basestring): - if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT: - self.document_type_obj = self.owner_document - else: - self.document_type_obj = get_document(self.document_type_obj) - return self.document_type_obj - - def to_python(self, value): - if not isinstance(value, self.document_type): - return self.document_type._from_son(value) - return value - - def to_mongo(self, value, use_db_field=True, fields=[]): - if not isinstance(value, self.document_type): - return value - return self.document_type.to_mongo(value, use_db_field, - fields=fields) - - def validate(self, value, clean=True): - """Make sure that the document instance is an instance of the - EmbeddedDocument subclass provided when the document was defined. - """ - # Using isinstance also works for subclasses of self.document - if not isinstance(value, self.document_type): - self.error('Invalid embedded document instance provided to an ' - 'EmbeddedDocumentField') - self.document_type.validate(value, clean) - - def lookup_member(self, member_name): - return self.document_type._fields.get(member_name) - - def prepare_query_value(self, op, value): - return self.to_mongo(value) - - -class GenericEmbeddedDocumentField(BaseField): - - """A generic embedded document field - allows any - :class:`~mongoengine.EmbeddedDocument` to be stored. - - Only valid values are subclasses of :class:`~mongoengine.EmbeddedDocument`. - - .. note :: - You can use the choices param to limit the acceptable - EmbeddedDocument types - """ - - def prepare_query_value(self, op, value): - return self.to_mongo(value) - - def to_python(self, value): - if isinstance(value, dict): - doc_cls = get_document(value['_cls']) - value = doc_cls._from_son(value) - - return value - - def validate(self, value, clean=True): - if not isinstance(value, EmbeddedDocument): - self.error('Invalid embedded document instance provided to an ' - 'GenericEmbeddedDocumentField') - - value.validate(clean=clean) - - def to_mongo(self, document, use_db_field=True): - if document is None: - return None - - data = document.to_mongo(use_db_field) - if not '_cls' in data: - data['_cls'] = document._class_name - return data - - -class DynamicField(BaseField): - - """A truly dynamic field type capable of handling different and varying - types of data. - - Used by :class:`~mongoengine.DynamicDocument` to handle dynamic data""" - - def to_mongo(self, value): - """Convert a Python type to a MongoDB compatible type. - """ - - if isinstance(value, basestring): - return value - - if hasattr(value, 'to_mongo'): - cls = value.__class__ - val = value.to_mongo() - # If we its a document thats not inherited add _cls - if (isinstance(value, Document)): - val = {"_ref": value.to_dbref(), "_cls": cls.__name__} - if (isinstance(value, EmbeddedDocument)): - val['_cls'] = cls.__name__ - return val - - if not isinstance(value, (dict, list, tuple)): - return value - - is_list = False - if not hasattr(value, 'items'): - is_list = True - value = dict([(k, v) for k, v in enumerate(value)]) - - data = {} - for k, v in value.iteritems(): - data[k] = self.to_mongo(v) - - value = data - if is_list: # Convert back to a list - value = [v for k, v in sorted(data.iteritems(), key=itemgetter(0))] - return value - - def to_python(self, value): - if isinstance(value, dict) and '_cls' in value: - doc_cls = get_document(value['_cls']) - if '_ref' in value: - value = doc_cls._get_db().dereference(value['_ref']) - return doc_cls._from_son(value) - - return super(DynamicField, self).to_python(value) - - def lookup_member(self, member_name): - return member_name - - def prepare_query_value(self, op, value): - if isinstance(value, basestring): - from mongoengine.fields import StringField - return StringField().prepare_query_value(op, value) - return self.to_mongo(value) - - def validate(self, value, clean=True): - if hasattr(value, "validate"): - value.validate(clean=clean) - - -class ListField(ComplexBaseField): - - """A list field that wraps a standard field, allowing multiple instances - of the field to be used as a list in the database. - - If using with ReferenceFields see: :ref:`one-to-many-with-listfields` - - .. note:: - Required means it cannot be empty - as the default for ListFields is [] - """ - - def __init__(self, field=None, **kwargs): - self.field = field - kwargs.setdefault('default', lambda: []) - super(ListField, self).__init__(**kwargs) - - def validate(self, value): - """Make sure that a list of valid fields is being used. - """ - if (not isinstance(value, (list, tuple, QuerySet)) or - isinstance(value, basestring)): - self.error('Only lists and tuples may be used in a list field') - super(ListField, self).validate(value) - - def prepare_query_value(self, op, value): - if self.field: - if op in ('set', 'unset') and (not isinstance(value, basestring) - and not isinstance(value, BaseDocument) - and hasattr(value, '__iter__')): - return [self.field.prepare_query_value(op, v) for v in value] - return self.field.prepare_query_value(op, value) - return super(ListField, self).prepare_query_value(op, value) - - -class EmbeddedDocumentListField(ListField): - """A :class:`~mongoengine.ListField` designed specially to hold a list of - embedded documents to provide additional query helpers. - - .. note:: - The only valid list values are subclasses of - :class:`~mongoengine.EmbeddedDocument`. - - .. versionadded:: 0.9 - - """ - - def __init__(self, document_type, *args, **kwargs): - """ - :param document_type: The type of - :class:`~mongoengine.EmbeddedDocument` the list will hold. - :param args: Arguments passed directly into the parent - :class:`~mongoengine.ListField`. - :param kwargs: Keyword arguments passed directly into the parent - :class:`~mongoengine.ListField`. - """ - super(EmbeddedDocumentListField, self).__init__( - field=EmbeddedDocumentField(document_type), **kwargs - ) - - -class SortedListField(ListField): - - """A ListField that sorts the contents of its list before writing to - the database in order to ensure that a sorted list is always - retrieved. - - .. warning:: - There is a potential race condition when handling lists. If you set / - save the whole list then other processes trying to save the whole list - as well could overwrite changes. The safest way to append to a list is - to perform a push operation. - - .. versionadded:: 0.4 - .. versionchanged:: 0.6 - added reverse keyword - """ - - _ordering = None - _order_reverse = False - - def __init__(self, field, **kwargs): - if 'ordering' in kwargs.keys(): - self._ordering = kwargs.pop('ordering') - if 'reverse' in kwargs.keys(): - self._order_reverse = kwargs.pop('reverse') - super(SortedListField, self).__init__(field, **kwargs) - - def to_mongo(self, value): - value = super(SortedListField, self).to_mongo(value) - if self._ordering is not None: - return sorted(value, key=itemgetter(self._ordering), - reverse=self._order_reverse) - return sorted(value, reverse=self._order_reverse) - - -def key_not_string(d): - """ Helper function to recursively determine if any key in a dictionary is - not a string. - """ - for k, v in d.items(): - if not isinstance(k, basestring) or (isinstance(v, dict) and key_not_string(v)): - return True - - -def key_has_dot_or_dollar(d): - """ Helper function to recursively determine if any key in a dictionary - contains a dot or a dollar sign. - """ - for k, v in d.items(): - if ('.' in k or '$' in k) or (isinstance(v, dict) and key_has_dot_or_dollar(v)): - return True - - -class DictField(ComplexBaseField): - - """A dictionary field that wraps a standard Python dictionary. This is - similar to an embedded document, but the structure is not defined. - - .. note:: - Required means it cannot be empty - as the default for DictFields is {} - - .. versionadded:: 0.3 - .. versionchanged:: 0.5 - Can now handle complex / varying types of data - """ - - def __init__(self, basecls=None, field=None, *args, **kwargs): - self.field = field - self.basecls = basecls or BaseField - if not issubclass(self.basecls, BaseField): - self.error('DictField only accepts dict values') - kwargs.setdefault('default', lambda: {}) - super(DictField, self).__init__(*args, **kwargs) - - def validate(self, value): - """Make sure that a list of valid fields is being used. - """ - if not isinstance(value, dict): - self.error('Only dictionaries may be used in a DictField') - - if key_not_string(value): - msg = ("Invalid dictionary key - documents must " - "have only string keys") - self.error(msg) - if key_has_dot_or_dollar(value): - self.error('Invalid dictionary key name - keys may not contain "."' - ' or "$" characters') - super(DictField, self).validate(value) - - def lookup_member(self, member_name): - return DictField(basecls=self.basecls, db_field=member_name) - - def prepare_query_value(self, op, value): - match_operators = ['contains', 'icontains', 'startswith', - 'istartswith', 'endswith', 'iendswith', - 'exact', 'iexact'] - - if op in match_operators and isinstance(value, basestring): - return StringField().prepare_query_value(op, value) - - if hasattr(self.field, 'field'): - if op in ('set', 'unset') and isinstance(value, dict): - return dict( - (k, self.field.prepare_query_value(op, v)) - for k, v in value.items()) - return self.field.prepare_query_value(op, value) - - return super(DictField, self).prepare_query_value(op, value) - - -class MapField(DictField): - - """A field that maps a name to a specified field type. Similar to - a DictField, except the 'value' of each item must match the specified - field type. - - .. versionadded:: 0.5 - """ - - def __init__(self, field=None, *args, **kwargs): - if not isinstance(field, BaseField): - self.error('Argument to MapField constructor must be a valid ' - 'field') - super(MapField, self).__init__(field=field, *args, **kwargs) - - -class ReferenceField(BaseField): - - """A reference to a document that will be automatically dereferenced on - access (lazily). - - Use the `reverse_delete_rule` to handle what should happen if the document - the field is referencing is deleted. EmbeddedDocuments, DictFields and - MapFields does not support reverse_delete_rule and an `InvalidDocumentError` - will be raised if trying to set on one of these Document / Field types. - - The options are: - - * DO_NOTHING - don't do anything (default). - * NULLIFY - Updates the reference to null. - * CASCADE - Deletes the documents associated with the reference. - * DENY - Prevent the deletion of the reference object. - * PULL - Pull the reference from a :class:`~mongoengine.fields.ListField` - of references - - Alternative syntax for registering delete rules (useful when implementing - bi-directional delete rules) - - .. code-block:: python - - class Bar(Document): - content = StringField() - foo = ReferenceField('Foo') - - Bar.register_delete_rule(Foo, 'bar', NULLIFY) - - .. note :: - `reverse_delete_rule` does not trigger pre / post delete signals to be - triggered. - - .. versionchanged:: 0.5 added `reverse_delete_rule` - """ - - def __init__(self, document_type, dbref=False, - reverse_delete_rule=DO_NOTHING, **kwargs): - """Initialises the Reference Field. - - :param dbref: Store the reference as :class:`~pymongo.dbref.DBRef` - or as the :class:`~pymongo.objectid.ObjectId`.id . - :param reverse_delete_rule: Determines what to do when the referring - object is deleted - """ - if not isinstance(document_type, basestring): - if not issubclass(document_type, (Document, basestring)): - self.error('Argument to ReferenceField constructor must be a ' - 'document class or a string') - - self.dbref = dbref - self.document_type_obj = document_type - self.reverse_delete_rule = reverse_delete_rule - super(ReferenceField, self).__init__(**kwargs) - - @property - def document_type(self): - if isinstance(self.document_type_obj, basestring): - if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT: - self.document_type_obj = self.owner_document - else: - self.document_type_obj = get_document(self.document_type_obj) - return self.document_type_obj - - def __get__(self, instance, owner): - """Descriptor to allow lazy dereferencing. - """ - if instance is None: - # Document class being used rather than a document object - return self - - # Get value from document instance if available - value = instance._data.get(self.name) - self._auto_dereference = instance._fields[self.name]._auto_dereference - # Dereference DBRefs - if self._auto_dereference and isinstance(value, DBRef): - value = self.document_type._get_db().dereference(value) - if value is not None: - instance._data[self.name] = self.document_type._from_son(value) - - return super(ReferenceField, self).__get__(instance, owner) - - def to_mongo(self, document): - if isinstance(document, DBRef): - if not self.dbref: - return document.id - return document - - id_field_name = self.document_type._meta['id_field'] - id_field = self.document_type._fields[id_field_name] - - if isinstance(document, Document): - # We need the id from the saved object to create the DBRef - id_ = document.pk - if id_ is None: - self.error('You can only reference documents once they have' - ' been saved to the database') - else: - id_ = document - - id_ = id_field.to_mongo(id_) - if self.dbref: - collection = self.document_type._get_collection_name() - return DBRef(collection, id_) - - return id_ - - def to_python(self, value): - """Convert a MongoDB-compatible type to a Python type. - """ - if (not self.dbref and - not isinstance(value, (DBRef, Document, EmbeddedDocument))): - collection = self.document_type._get_collection_name() - value = DBRef(collection, self.document_type.id.to_python(value)) - return value - - def prepare_query_value(self, op, value): - if value is None: - return None - return self.to_mongo(value) - - def validate(self, value): - - if not isinstance(value, (self.document_type, DBRef)): - self.error("A ReferenceField only accepts DBRef or documents") - - if isinstance(value, Document) and value.id is None: - self.error('You can only reference documents once they have been ' - 'saved to the database') - - def lookup_member(self, member_name): - return self.document_type._fields.get(member_name) - - -class CachedReferenceField(BaseField): - - """ - A referencefield with cache fields to porpuse pseudo-joins - .. versionadded:: 0.9 - """ - - def __init__(self, document_type, fields=[], auto_sync=True, **kwargs): - """Initialises the Cached Reference Field. - - :param fields: A list of fields to be cached in document - :param auto_sync: if True documents are auto updated. - """ - if not isinstance(document_type, basestring) and \ - not issubclass(document_type, (Document, basestring)): - - self.error('Argument to CachedReferenceField constructor must be a' - ' document class or a string') - - self.auto_sync = auto_sync - self.document_type_obj = document_type - self.fields = fields - super(CachedReferenceField, self).__init__(**kwargs) - - def start_listener(self): - from mongoengine import signals - signals.post_save.connect(self.on_document_pre_save, - sender=self.document_type) - - def on_document_pre_save(self, sender, document, created, **kwargs): - if not created: - update_kwargs = dict( - ('set__%s__%s' % (self.name, k), v) - for k, v in document._delta()[0].items() - if k in self.fields) - - if update_kwargs: - filter_kwargs = {} - filter_kwargs[self.name] = document - - self.owner_document.objects( - **filter_kwargs).update(**update_kwargs) - - def to_python(self, value): - if isinstance(value, dict): - collection = self.document_type._get_collection_name() - value = DBRef( - collection, self.document_type.id.to_python(value['_id'])) - - return value - - @property - def document_type(self): - if isinstance(self.document_type_obj, basestring): - if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT: - self.document_type_obj = self.owner_document - else: - self.document_type_obj = get_document(self.document_type_obj) - return self.document_type_obj - - def __get__(self, instance, owner): - if instance is None: - # Document class being used rather than a document object - return self - - # Get value from document instance if available - value = instance._data.get(self.name) - self._auto_dereference = instance._fields[self.name]._auto_dereference - # Dereference DBRefs - if self._auto_dereference and isinstance(value, DBRef): - value = self.document_type._get_db().dereference(value) - if value is not None: - instance._data[self.name] = self.document_type._from_son(value) - - return super(CachedReferenceField, self).__get__(instance, owner) - - def to_mongo(self, document): - id_field_name = self.document_type._meta['id_field'] - id_field = self.document_type._fields[id_field_name] - doc_tipe = self.document_type - - if isinstance(document, Document): - # We need the id from the saved object to create the DBRef - id_ = document.pk - if id_ is None: - self.error('You can only reference documents once they have' - ' been saved to the database') - else: - self.error('Only accept a document object') - - value = SON(( - ("_id", id_field.to_mongo(id_)), - )) - - value.update(dict(document.to_mongo(fields=self.fields))) - return value - - def prepare_query_value(self, op, value): - if value is None: - return None - - if isinstance(value, Document): - if value.pk is None: - self.error('You can only reference documents once they have' - ' been saved to the database') - return {'_id': value.pk} - - raise NotImplementedError - - def validate(self, value): - - if not isinstance(value, (self.document_type)): - self.error("A CachedReferenceField only accepts documents") - - if isinstance(value, Document) and value.id is None: - self.error('You can only reference documents once they have been ' - 'saved to the database') - - def lookup_member(self, member_name): - return self.document_type._fields.get(member_name) - - def sync_all(self): - """ - Sync all cached fields on demand. - Caution: this operation may be slower. - """ - update_key = 'set__%s' % self.name - - for doc in self.document_type.objects: - filter_kwargs = {} - filter_kwargs[self.name] = doc - - update_kwargs = {} - update_kwargs[update_key] = doc - - self.owner_document.objects( - **filter_kwargs).update(**update_kwargs) - - -class GenericReferenceField(BaseField): - - """A reference to *any* :class:`~mongoengine.document.Document` subclass - that will be automatically dereferenced on access (lazily). - - .. note :: - * Any documents used as a generic reference must be registered in the - document registry. Importing the model will automatically register - it. - - * You can use the choices param to limit the acceptable Document types - - .. versionadded:: 0.3 - """ - - def __get__(self, instance, owner): - if instance is None: - return self - - value = instance._data.get(self.name) - - self._auto_dereference = instance._fields[self.name]._auto_dereference - if self._auto_dereference and isinstance(value, (dict, SON)): - instance._data[self.name] = self.dereference(value) - - return super(GenericReferenceField, self).__get__(instance, owner) - - def validate(self, value): - if not isinstance(value, (Document, DBRef, dict, SON)): - self.error('GenericReferences can only contain documents') - - if isinstance(value, (dict, SON)): - if '_ref' not in value or '_cls' not in value: - self.error('GenericReferences can only contain documents') - - # We need the id from the saved object to create the DBRef - elif isinstance(value, Document) and value.id is None: - self.error('You can only reference documents once they have been' - ' saved to the database') - - def dereference(self, value): - doc_cls = get_document(value['_cls']) - reference = value['_ref'] - doc = doc_cls._get_db().dereference(reference) - if doc is not None: - doc = doc_cls._from_son(doc) - return doc - - def to_mongo(self, document, use_db_field=True): - if document is None: - return None - - if isinstance(document, (dict, SON)): - return document - - id_field_name = document.__class__._meta['id_field'] - id_field = document.__class__._fields[id_field_name] - - if isinstance(document, Document): - # We need the id from the saved object to create the DBRef - id_ = document.id - if id_ is None: - self.error('You can only reference documents once they have' - ' been saved to the database') - else: - id_ = document - - id_ = id_field.to_mongo(id_) - collection = document._get_collection_name() - ref = DBRef(collection, id_) - return SON(( - ('_cls', document._class_name), - ('_ref', ref) - )) - - def prepare_query_value(self, op, value): - if value is None: - return None - - return self.to_mongo(value) - - -class BinaryField(BaseField): - - """A binary data field. - """ - - def __init__(self, max_bytes=None, **kwargs): - self.max_bytes = max_bytes - super(BinaryField, self).__init__(**kwargs) - - def __set__(self, instance, value): - """Handle bytearrays in python 3.1""" - if PY3 and isinstance(value, bytearray): - value = bin_type(value) - return super(BinaryField, self).__set__(instance, value) - - def to_mongo(self, value): - return Binary(value) - - def validate(self, value): - if not isinstance(value, (bin_type, txt_type, Binary)): - self.error("BinaryField only accepts instances of " - "(%s, %s, Binary)" % ( - bin_type.__name__, txt_type.__name__)) - - if self.max_bytes is not None and len(value) > self.max_bytes: - self.error('Binary value is too long') - - -class GridFSError(Exception): - pass - - -class GridFSProxy(object): - - """Proxy object to handle writing and reading of files to and from GridFS - - .. versionadded:: 0.4 - .. versionchanged:: 0.5 - added optional size param to read - .. versionchanged:: 0.6 - added collection name param - """ - - _fs = None - - def __init__(self, grid_id=None, key=None, - instance=None, - db_alias=DEFAULT_CONNECTION_NAME, - collection_name='fs'): - self.grid_id = grid_id # Store GridFS id for file - self.key = key - self.instance = instance - self.db_alias = db_alias - self.collection_name = collection_name - self.newfile = None # Used for partial writes - self.gridout = None - - def __getattr__(self, name): - attrs = ('_fs', 'grid_id', 'key', 'instance', 'db_alias', - 'collection_name', 'newfile', 'gridout') - if name in attrs: - return self.__getattribute__(name) - obj = self.get() - if hasattr(obj, name): - return getattr(obj, name) - raise AttributeError - - def __get__(self, instance, value): - return self - - def __nonzero__(self): - return bool(self.grid_id) - - def __getstate__(self): - self_dict = self.__dict__ - self_dict['_fs'] = None - return self_dict - - def __copy__(self): - copied = GridFSProxy() - copied.__dict__.update(self.__getstate__()) - return copied - - def __deepcopy__(self, memo): - return self.__copy__() - - def __repr__(self): - return '<%s: %s>' % (self.__class__.__name__, self.grid_id) - - def __str__(self): - name = getattr( - self.get(), 'filename', self.grid_id) if self.get() else '(no file)' - return '<%s: %s>' % (self.__class__.__name__, name) - - def __eq__(self, other): - if isinstance(other, GridFSProxy): - return ((self.grid_id == other.grid_id) and - (self.collection_name == other.collection_name) and - (self.db_alias == other.db_alias)) - else: - return False - - @property - def fs(self): - if not self._fs: - self._fs = gridfs.GridFS( - get_db(self.db_alias), self.collection_name) - return self._fs - - def get(self, id=None): - if id: - self.grid_id = id - if self.grid_id is None: - return None - try: - if self.gridout is None: - self.gridout = self.fs.get(self.grid_id) - return self.gridout - except: - # File has been deleted - return None - - def new_file(self, **kwargs): - self.newfile = self.fs.new_file(**kwargs) - self.grid_id = self.newfile._id - self._mark_as_changed() - - def put(self, file_obj, **kwargs): - if self.grid_id: - raise GridFSError('This document already has a file. Either delete ' - 'it or call replace to overwrite it') - self.grid_id = self.fs.put(file_obj, **kwargs) - self._mark_as_changed() - - def write(self, string): - if self.grid_id: - if not self.newfile: - raise GridFSError('This document already has a file. Either ' - 'delete it or call replace to overwrite it') - else: - self.new_file() - self.newfile.write(string) - - def writelines(self, lines): - if not self.newfile: - self.new_file() - self.grid_id = self.newfile._id - self.newfile.writelines(lines) - - def read(self, size=-1): - gridout = self.get() - if gridout is None: - return None - else: - try: - return gridout.read(size) - except: - return "" - - def delete(self): - # Delete file from GridFS, FileField still remains - self.fs.delete(self.grid_id) - self.grid_id = None - self.gridout = None - self._mark_as_changed() - - def replace(self, file_obj, **kwargs): - self.delete() - self.put(file_obj, **kwargs) - - def close(self): - if self.newfile: - self.newfile.close() - - def _mark_as_changed(self): - """Inform the instance that `self.key` has been changed""" - if self.instance: - self.instance._mark_as_changed(self.key) - - -class FileField(BaseField): - - """A GridFS storage field. - - .. versionadded:: 0.4 - .. versionchanged:: 0.5 added optional size param for read - .. versionchanged:: 0.6 added db_alias for multidb support - """ - proxy_class = GridFSProxy - - def __init__(self, - db_alias=DEFAULT_CONNECTION_NAME, - collection_name="fs", **kwargs): - super(FileField, self).__init__(**kwargs) - self.collection_name = collection_name - self.db_alias = db_alias - - def __get__(self, instance, owner): - if instance is None: - return self - - # Check if a file already exists for this model - grid_file = instance._data.get(self.name) - if not isinstance(grid_file, self.proxy_class): - grid_file = self.get_proxy_obj(key=self.name, instance=instance) - instance._data[self.name] = grid_file - - if not grid_file.key: - grid_file.key = self.name - grid_file.instance = instance - return grid_file - - def __set__(self, instance, value): - key = self.name - if ((hasattr(value, 'read') and not - isinstance(value, GridFSProxy)) or isinstance(value, str_types)): - # using "FileField() = file/string" notation - grid_file = instance._data.get(self.name) - # If a file already exists, delete it - if grid_file: - try: - grid_file.delete() - except: - pass - - # Create a new proxy object as we don't already have one - instance._data[key] = self.get_proxy_obj( - key=key, instance=instance) - instance._data[key].put(value) - else: - instance._data[key] = value - - instance._mark_as_changed(key) - - def get_proxy_obj(self, key, instance, db_alias=None, collection_name=None): - if db_alias is None: - db_alias = self.db_alias - if collection_name is None: - collection_name = self.collection_name - - return self.proxy_class(key=key, instance=instance, - db_alias=db_alias, - collection_name=collection_name) - - def to_mongo(self, value): - # Store the GridFS file id in MongoDB - if isinstance(value, self.proxy_class) and value.grid_id is not None: - return value.grid_id - return None - - def to_python(self, value): - if value is not None: - return self.proxy_class(value, - collection_name=self.collection_name, - db_alias=self.db_alias) - - def validate(self, value): - if value.grid_id is not None: - if not isinstance(value, self.proxy_class): - self.error('FileField only accepts GridFSProxy values') - if not isinstance(value.grid_id, ObjectId): - self.error('Invalid GridFSProxy value') - - -class ImageGridFsProxy(GridFSProxy): - - """ - Proxy for ImageField - - versionadded: 0.6 - """ - - def put(self, file_obj, **kwargs): - """ - Insert a image in database - applying field properties (size, thumbnail_size) - """ - field = self.instance._fields[self.key] - # Handle nested fields - if hasattr(field, 'field') and isinstance(field.field, FileField): - field = field.field - - try: - img = Image.open(file_obj) - img_format = img.format - except Exception, e: - raise ValidationError('Invalid image: %s' % e) - - # Progressive JPEG - progressive = img.info.get('progressive') or False - - if (kwargs.get('progressive') and - isinstance(kwargs.get('progressive'), bool) and - img_format == 'JPEG'): - progressive = True - else: - progressive = False - - if (field.size and (img.size[0] > field.size['width'] or - img.size[1] > field.size['height'])): - size = field.size - - if size['force']: - img = ImageOps.fit(img, - (size['width'], - size['height']), - Image.ANTIALIAS) - else: - img.thumbnail((size['width'], - size['height']), - Image.ANTIALIAS) - - thumbnail = None - if field.thumbnail_size: - size = field.thumbnail_size - - if size['force']: - thumbnail = ImageOps.fit( - img, (size['width'], size['height']), Image.ANTIALIAS) - else: - thumbnail = img.copy() - thumbnail.thumbnail((size['width'], - size['height']), - Image.ANTIALIAS) - - if thumbnail: - thumb_id = self._put_thumbnail(thumbnail, img_format, progressive) - else: - thumb_id = None - - w, h = img.size - - io = StringIO() - img.save(io, img_format, progressive=progressive) - io.seek(0) - - return super(ImageGridFsProxy, self).put(io, - width=w, - height=h, - format=img_format, - thumbnail_id=thumb_id, - **kwargs) - - def delete(self, *args, **kwargs): - # deletes thumbnail - out = self.get() - if out and out.thumbnail_id: - self.fs.delete(out.thumbnail_id) - - return super(ImageGridFsProxy, self).delete(*args, **kwargs) - - def _put_thumbnail(self, thumbnail, format, progressive, **kwargs): - w, h = thumbnail.size - - io = StringIO() - thumbnail.save(io, format, progressive=progressive) - io.seek(0) - - return self.fs.put(io, width=w, - height=h, - format=format, - **kwargs) - - @property - def size(self): - """ - return a width, height of image - """ - out = self.get() - if out: - return out.width, out.height - - @property - def format(self): - """ - return format of image - ex: PNG, JPEG, GIF, etc - """ - out = self.get() - if out: - return out.format - - @property - def thumbnail(self): - """ - return a gridfs.grid_file.GridOut - representing a thumbnail of Image - """ - out = self.get() - if out and out.thumbnail_id: - return self.fs.get(out.thumbnail_id) - - def write(self, *args, **kwargs): - raise RuntimeError("Please use \"put\" method instead") - - def writelines(self, *args, **kwargs): - raise RuntimeError("Please use \"put\" method instead") - - -class ImproperlyConfigured(Exception): - pass - - -class ImageField(FileField): - - """ - A Image File storage field. - - @size (width, height, force): - max size to store images, if larger will be automatically resized - ex: size=(800, 600, True) - - @thumbnail (width, height, force): - size to generate a thumbnail - - .. versionadded:: 0.6 - """ - proxy_class = ImageGridFsProxy - - def __init__(self, size=None, thumbnail_size=None, - collection_name='images', **kwargs): - if not Image: - raise ImproperlyConfigured("PIL library was not found") - - params_size = ('width', 'height', 'force') - extra_args = dict(size=size, thumbnail_size=thumbnail_size) - for att_name, att in extra_args.items(): - value = None - if isinstance(att, (tuple, list)): - if PY3: - value = dict(itertools.zip_longest(params_size, att, - fillvalue=None)) - else: - value = dict(map(None, params_size, att)) - - setattr(self, att_name, value) - - super(ImageField, self).__init__( - collection_name=collection_name, - **kwargs) - - -class SequenceField(BaseField): - - """Provides a sequential counter see: - http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-SequenceNumbers - - .. note:: - - Although traditional databases often use increasing sequence - numbers for primary keys. In MongoDB, the preferred approach is to - use Object IDs instead. The concept is that in a very large - cluster of machines, it is easier to create an object ID than have - global, uniformly increasing sequence numbers. - - Use any callable as `value_decorator` to transform calculated counter into - any value suitable for your needs, e.g. string or hexadecimal - representation of the default integer counter value. - - .. versionadded:: 0.5 - - .. versionchanged:: 0.8 added `value_decorator` - """ - - _auto_gen = True - COLLECTION_NAME = 'mongoengine.counters' - VALUE_DECORATOR = int - - def __init__(self, collection_name=None, db_alias=None, sequence_name=None, - value_decorator=None, *args, **kwargs): - self.collection_name = collection_name or self.COLLECTION_NAME - self.db_alias = db_alias or DEFAULT_CONNECTION_NAME - self.sequence_name = sequence_name - self.value_decorator = (callable(value_decorator) and - value_decorator or self.VALUE_DECORATOR) - return super(SequenceField, self).__init__(*args, **kwargs) - - def generate(self): - """ - Generate and Increment the counter - """ - sequence_name = self.get_sequence_name() - sequence_id = "%s.%s" % (sequence_name, self.name) - collection = get_db(alias=self.db_alias)[self.collection_name] - counter = collection.find_and_modify(query={"_id": sequence_id}, - update={"$inc": {"next": 1}}, - new=True, - upsert=True) - return self.value_decorator(counter['next']) - - def set_next_value(self, value): - """Helper method to set the next sequence value""" - sequence_name = self.get_sequence_name() - sequence_id = "%s.%s" % (sequence_name, self.name) - collection = get_db(alias=self.db_alias)[self.collection_name] - counter = collection.find_and_modify(query={"_id": sequence_id}, - update={"$set": {"next": value}}, - new=True, - upsert=True) - return self.value_decorator(counter['next']) - - def get_next_value(self): - """Helper method to get the next value for previewing. - - .. warning:: There is no guarantee this will be the next value - as it is only fixed on set. - """ - sequence_name = self.get_sequence_name() - sequence_id = "%s.%s" % (sequence_name, self.name) - collection = get_db(alias=self.db_alias)[self.collection_name] - data = collection.find_one({"_id": sequence_id}) - - if data: - return self.value_decorator(data['next'] + 1) - - return self.value_decorator(1) - - def get_sequence_name(self): - if self.sequence_name: - return self.sequence_name - owner = self.owner_document - if issubclass(owner, Document): - return owner._get_collection_name() - else: - return ''.join('_%s' % c if c.isupper() else c - for c in owner._class_name).strip('_').lower() - - def __get__(self, instance, owner): - value = super(SequenceField, self).__get__(instance, owner) - if value is None and instance._initialised: - value = self.generate() - instance._data[self.name] = value - instance._mark_as_changed(self.name) - - return value - - def __set__(self, instance, value): - - if value is None and instance._initialised: - value = self.generate() - - return super(SequenceField, self).__set__(instance, value) - - def prepare_query_value(self, op, value): - """ - This method is overridden in order to convert the query value into to required - type. We need to do this in order to be able to successfully compare query - values passed as string, the base implementation returns the value as is. - """ - return self.value_decorator(value) - - def to_python(self, value): - if value is None: - value = self.generate() - return value - - -class UUIDField(BaseField): - - """A UUID field. - - .. versionadded:: 0.6 - """ - _binary = None - - def __init__(self, binary=True, **kwargs): - """ - Store UUID data in the database - - :param binary: if False store as a string. - - .. versionchanged:: 0.8.0 - .. versionchanged:: 0.6.19 - """ - self._binary = binary - super(UUIDField, self).__init__(**kwargs) - - def to_python(self, value): - if not self._binary: - original_value = value - try: - if not isinstance(value, basestring): - value = unicode(value) - return uuid.UUID(value) - except: - return original_value - return value - - def to_mongo(self, value): - if not self._binary: - return unicode(value) - elif isinstance(value, basestring): - return uuid.UUID(value) - return value - - def prepare_query_value(self, op, value): - if value is None: - return None - return self.to_mongo(value) - - def validate(self, value): - if not isinstance(value, uuid.UUID): - if not isinstance(value, basestring): - value = str(value) - try: - value = uuid.UUID(value) - except Exception, exc: - self.error('Could not convert to UUID: %s' % exc) - - -class GeoPointField(BaseField): - - """A list storing a longitude and latitude coordinate. - - .. note:: this represents a generic point in a 2D plane and a legacy way of - representing a geo point. It admits 2d indexes but not "2dsphere" indexes - in MongoDB > 2.4 which are more natural for modeling geospatial points. - See :ref:`geospatial-indexes` - - .. versionadded:: 0.4 - """ - - _geo_index = pymongo.GEO2D - - def validate(self, value): - """Make sure that a geo-value is of type (x, y) - """ - if not isinstance(value, (list, tuple)): - self.error('GeoPointField can only accept tuples or lists ' - 'of (x, y)') - - if not len(value) == 2: - self.error("Value (%s) must be a two-dimensional point" % - repr(value)) - elif (not isinstance(value[0], (float, int)) or - not isinstance(value[1], (float, int))): - self.error( - "Both values (%s) in point must be float or int" % repr(value)) - - -class PointField(GeoJsonBaseField): - - """A GeoJSON field storing a longitude and latitude coordinate. - - The data is represented as: - - .. code-block:: js - - { "type" : "Point" , - "coordinates" : [x, y]} - - You can either pass a dict with the full information or a list - to set the value. - - Requires mongodb >= 2.4 - - .. versionadded:: 0.8 - """ - _type = "Point" - - -class LineStringField(GeoJsonBaseField): - - """A GeoJSON field storing a line of longitude and latitude coordinates. - - The data is represented as: - - .. code-block:: js - - { "type" : "LineString" , - "coordinates" : [[x1, y1], [x1, y1] ... [xn, yn]]} - - You can either pass a dict with the full information or a list of points. - - Requires mongodb >= 2.4 - - .. versionadded:: 0.8 - """ - _type = "LineString" - - -class PolygonField(GeoJsonBaseField): - - """A GeoJSON field storing a polygon of longitude and latitude coordinates. - - The data is represented as: - - .. code-block:: js - - { "type" : "Polygon" , - "coordinates" : [[[x1, y1], [x1, y1] ... [xn, yn]], - [[x1, y1], [x1, y1] ... [xn, yn]]} - - You can either pass a dict with the full information or a list - of LineStrings. The first LineString being the outside and the rest being - holes. - - Requires mongodb >= 2.4 - - .. versionadded:: 0.8 - """ - _type = "Polygon" - - -class MultiPointField(GeoJsonBaseField): - - """A GeoJSON field storing a list of Points. - - The data is represented as: - - .. code-block:: js - - { "type" : "MultiPoint" , - "coordinates" : [[x1, y1], [x2, y2]]} - - You can either pass a dict with the full information or a list - to set the value. - - Requires mongodb >= 2.6 - - .. versionadded:: 0.9 - """ - _type = "MultiPoint" - - -class MultiLineStringField(GeoJsonBaseField): - - """A GeoJSON field storing a list of LineStrings. - - The data is represented as: - - .. code-block:: js - - { "type" : "MultiLineString" , - "coordinates" : [[[x1, y1], [x1, y1] ... [xn, yn]], - [[x1, y1], [x1, y1] ... [xn, yn]]]} - - You can either pass a dict with the full information or a list of points. - - Requires mongodb >= 2.6 - - .. versionadded:: 0.9 - """ - _type = "MultiLineString" - - -class MultiPolygonField(GeoJsonBaseField): - - """A GeoJSON field storing list of Polygons. - - The data is represented as: - - .. code-block:: js - - { "type" : "MultiPolygon" , - "coordinates" : [[ - [[x1, y1], [x1, y1] ... [xn, yn]], - [[x1, y1], [x1, y1] ... [xn, yn]] - ], [ - [[x1, y1], [x1, y1] ... [xn, yn]], - [[x1, y1], [x1, y1] ... [xn, yn]] - ] - } - - You can either pass a dict with the full information or a list - of Polygons. - - Requires mongodb >= 2.6 - - .. versionadded:: 0.9 - """ - _type = "MultiPolygon" diff --git a/awx/lib/site-packages/mongoengine/python_support.py b/awx/lib/site-packages/mongoengine/python_support.py deleted file mode 100644 index 2c4df00c2f..0000000000 --- a/awx/lib/site-packages/mongoengine/python_support.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Helper functions and types to aid with Python 2.5 - 3 support.""" - -import sys - -PY3 = sys.version_info[0] == 3 - -if PY3: - import codecs - from io import BytesIO as StringIO - # return s converted to binary. b('test') should be equivalent to b'test' - def b(s): - return codecs.latin_1_encode(s)[0] - - bin_type = bytes - txt_type = str -else: - try: - from cStringIO import StringIO - except ImportError: - from StringIO import StringIO - - # Conversion to binary only necessary in Python 3 - def b(s): - return s - - bin_type = str - txt_type = unicode - -str_types = (bin_type, txt_type) diff --git a/awx/lib/site-packages/mongoengine/queryset/__init__.py b/awx/lib/site-packages/mongoengine/queryset/__init__.py deleted file mode 100644 index 026a7acdd5..0000000000 --- a/awx/lib/site-packages/mongoengine/queryset/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from mongoengine.errors import (DoesNotExist, MultipleObjectsReturned, - InvalidQueryError, OperationError, - NotUniqueError) -from mongoengine.queryset.field_list import * -from mongoengine.queryset.manager import * -from mongoengine.queryset.queryset import * -from mongoengine.queryset.transform import * -from mongoengine.queryset.visitor import * - -__all__ = (field_list.__all__ + manager.__all__ + queryset.__all__ + - transform.__all__ + visitor.__all__) diff --git a/awx/lib/site-packages/mongoengine/queryset/base.py b/awx/lib/site-packages/mongoengine/queryset/base.py deleted file mode 100644 index 7ffb9976f8..0000000000 --- a/awx/lib/site-packages/mongoengine/queryset/base.py +++ /dev/null @@ -1,1750 +0,0 @@ -from __future__ import absolute_import - -import copy -import itertools -import operator -import pprint -import re -import warnings - -from bson import SON -from bson.code import Code -from bson import json_util -import pymongo -import pymongo.errors -from pymongo.common import validate_read_preference - -from mongoengine import signals -from mongoengine.connection import get_db -from mongoengine.context_managers import switch_db -from mongoengine.common import _import_class -from mongoengine.base.common import get_document -from mongoengine.errors import (OperationError, NotUniqueError, - InvalidQueryError, LookUpError) -from mongoengine.queryset import transform -from mongoengine.queryset.field_list import QueryFieldList -from mongoengine.queryset.visitor import Q, QNode - - -__all__ = ('BaseQuerySet', 'DO_NOTHING', 'NULLIFY', 'CASCADE', 'DENY', 'PULL') - -# Delete rules -DO_NOTHING = 0 -NULLIFY = 1 -CASCADE = 2 -DENY = 3 -PULL = 4 - -RE_TYPE = type(re.compile('')) - - -class BaseQuerySet(object): - - """A set of results returned from a query. Wraps a MongoDB cursor, - providing :class:`~mongoengine.Document` objects as the results. - """ - __dereference = False - _auto_dereference = True - - def __init__(self, document, collection): - self._document = document - self._collection_obj = collection - self._mongo_query = None - self._query_obj = Q() - self._initial_query = {} - self._where_clause = None - self._loaded_fields = QueryFieldList() - self._ordering = None - self._snapshot = False - self._timeout = True - self._class_check = True - self._slave_okay = False - self._read_preference = None - self._iter = False - self._scalar = [] - self._none = False - self._as_pymongo = False - self._as_pymongo_coerce = False - self._search_text = None - - # If inheritance is allowed, only return instances and instances of - # subclasses of the class being used - if document._meta.get('allow_inheritance') is True: - if len(self._document._subclasses) == 1: - self._initial_query = {"_cls": self._document._subclasses[0]} - else: - self._initial_query = { - "_cls": {"$in": self._document._subclasses}} - self._loaded_fields = QueryFieldList(always_include=['_cls']) - self._cursor_obj = None - self._limit = None - self._skip = None - self._hint = -1 # Using -1 as None is a valid value for hint - self.only_fields = [] - self._max_time_ms = None - - def __call__(self, q_obj=None, class_check=True, slave_okay=False, - read_preference=None, **query): - """Filter the selected documents by calling the - :class:`~mongoengine.queryset.QuerySet` with a query. - - :param q_obj: a :class:`~mongoengine.queryset.Q` object to be used in - the query; the :class:`~mongoengine.queryset.QuerySet` is filtered - multiple times with different :class:`~mongoengine.queryset.Q` - objects, only the last one will be used - :param class_check: If set to False bypass class name check when - querying collection - :param slave_okay: if True, allows this query to be run against a - replica secondary. - :params read_preference: if set, overrides connection-level - read_preference from `ReplicaSetConnection`. - :param query: Django-style query keyword arguments - """ - query = Q(**query) - if q_obj: - # make sure proper query object is passed - if not isinstance(q_obj, QNode): - msg = ("Not a query object: %s. " - "Did you intend to use key=value?" % q_obj) - raise InvalidQueryError(msg) - query &= q_obj - - if read_preference is None: - queryset = self.clone() - else: - # Use the clone provided when setting read_preference - queryset = self.read_preference(read_preference) - - queryset._query_obj &= query - queryset._mongo_query = None - queryset._cursor_obj = None - queryset._class_check = class_check - - return queryset - - def __getitem__(self, key): - """Support skip and limit using getitem and slicing syntax. - """ - queryset = self.clone() - - # Slice provided - if isinstance(key, slice): - try: - queryset._cursor_obj = queryset._cursor[key] - queryset._skip, queryset._limit = key.start, key.stop - if key.start and key.stop: - queryset._limit = key.stop - key.start - except IndexError, err: - # PyMongo raises an error if key.start == key.stop, catch it, - # bin it, kill it. - start = key.start or 0 - if start >= 0 and key.stop >= 0 and key.step is None: - if start == key.stop: - queryset.limit(0) - queryset._skip = key.start - queryset._limit = key.stop - start - return queryset - raise err - # Allow further QuerySet modifications to be performed - return queryset - # Integer index provided - elif isinstance(key, int): - if queryset._scalar: - return queryset._get_scalar( - queryset._document._from_son(queryset._cursor[key], - _auto_dereference=self._auto_dereference, - only_fields=self.only_fields)) - - if queryset._as_pymongo: - return queryset._get_as_pymongo(queryset._cursor[key]) - return queryset._document._from_son(queryset._cursor[key], - _auto_dereference=self._auto_dereference, only_fields=self.only_fields) - - raise AttributeError - - def __iter__(self): - raise NotImplementedError - - def _has_data(self): - """ Retrieves whether cursor has any data. """ - - queryset = self.order_by() - return False if queryset.first() is None else True - - def __nonzero__(self): - """ Avoid to open all records in an if stmt in Py2. """ - - return self._has_data() - - def __bool__(self): - """ Avoid to open all records in an if stmt in Py3. """ - - return self._has_data() - - # Core functions - - def all(self): - """Returns all documents.""" - return self.__call__() - - def filter(self, *q_objs, **query): - """An alias of :meth:`~mongoengine.queryset.QuerySet.__call__` - """ - return self.__call__(*q_objs, **query) - - def search_text(self, text, language=None): - """ - Start a text search, using text indexes. - Require: MongoDB server version 2.6+. - - :param language: The language that determines the list of stop words - for the search and the rules for the stemmer and tokenizer. - If not specified, the search uses the default language of the index. - For supported languages, see `Text Search Languages <http://docs.mongodb.org/manual/reference/text-search-languages/#text-search-languages>`. - """ - queryset = self.clone() - if queryset._search_text: - raise OperationError( - "It is not possible to use search_text two times.") - - query_kwargs = SON({'$search': text}) - if language: - query_kwargs['$language'] = language - - queryset._query_obj &= Q(__raw__={'$text': query_kwargs}) - queryset._mongo_query = None - queryset._cursor_obj = None - queryset._search_text = text - - return queryset - - def get(self, *q_objs, **query): - """Retrieve the the matching object raising - :class:`~mongoengine.queryset.MultipleObjectsReturned` or - `DocumentName.MultipleObjectsReturned` exception if multiple results - and :class:`~mongoengine.queryset.DoesNotExist` or - `DocumentName.DoesNotExist` if no results are found. - - .. versionadded:: 0.3 - """ - queryset = self.clone() - queryset = queryset.order_by().limit(2) - queryset = queryset.filter(*q_objs, **query) - - try: - result = queryset.next() - except StopIteration: - msg = ("%s matching query does not exist." - % queryset._document._class_name) - raise queryset._document.DoesNotExist(msg) - try: - queryset.next() - except StopIteration: - return result - - queryset.rewind() - message = u'%d items returned, instead of 1' % queryset.count() - raise queryset._document.MultipleObjectsReturned(message) - - def create(self, **kwargs): - """Create new object. Returns the saved object instance. - - .. versionadded:: 0.4 - """ - return self._document(**kwargs).save() - - def get_or_create(self, write_concern=None, auto_save=True, - *q_objs, **query): - """Retrieve unique object or create, if it doesn't exist. Returns a - tuple of ``(object, created)``, where ``object`` is the retrieved or - created object and ``created`` is a boolean specifying whether a new - object was created. Raises - :class:`~mongoengine.queryset.MultipleObjectsReturned` or - `DocumentName.MultipleObjectsReturned` if multiple results are found. - A new document will be created if the document doesn't exists; a - dictionary of default values for the new document may be provided as a - keyword argument called :attr:`defaults`. - - .. note:: This requires two separate operations and therefore a - race condition exists. Because there are no transactions in - mongoDB other approaches should be investigated, to ensure you - don't accidentally duplicate data when using this method. This is - now scheduled to be removed before 1.0 - - :param write_concern: optional extra keyword arguments used if we - have to create a new document. - Passes any write_concern onto :meth:`~mongoengine.Document.save` - - :param auto_save: if the object is to be saved automatically if - not found. - - .. deprecated:: 0.8 - .. versionchanged:: 0.6 - added `auto_save` - .. versionadded:: 0.3 - """ - msg = ("get_or_create is scheduled to be deprecated. The approach is " - "flawed without transactions. Upserts should be preferred.") - warnings.warn(msg, DeprecationWarning) - - defaults = query.get('defaults', {}) - if 'defaults' in query: - del query['defaults'] - - try: - doc = self.get(*q_objs, **query) - return doc, False - except self._document.DoesNotExist: - query.update(defaults) - doc = self._document(**query) - - if auto_save: - doc.save(write_concern=write_concern) - return doc, True - - def first(self): - """Retrieve the first object matching the query. - """ - queryset = self.clone() - try: - result = queryset[0] - except IndexError: - result = None - return result - - def insert(self, doc_or_docs, load_bulk=True, write_concern=None): - """bulk insert documents - - :param docs_or_doc: a document or list of documents to be inserted - :param load_bulk (optional): If True returns the list of document - instances - :param write_concern: Extra keyword arguments are passed down to - :meth:`~pymongo.collection.Collection.insert` - which will be used as options for the resultant - ``getLastError`` command. For example, - ``insert(..., {w: 2, fsync: True})`` will wait until at least - two servers have recorded the write and will force an fsync on - each server being written to. - - By default returns document instances, set ``load_bulk`` to False to - return just ``ObjectIds`` - - .. versionadded:: 0.5 - """ - Document = _import_class('Document') - - if write_concern is None: - write_concern = {} - - docs = doc_or_docs - return_one = False - if isinstance(docs, Document) or issubclass(docs.__class__, Document): - return_one = True - docs = [docs] - - raw = [] - for doc in docs: - if not isinstance(doc, self._document): - msg = ("Some documents inserted aren't instances of %s" - % str(self._document)) - raise OperationError(msg) - if doc.pk and not doc._created: - msg = "Some documents have ObjectIds use doc.update() instead" - raise OperationError(msg) - raw.append(doc.to_mongo()) - - signals.pre_bulk_insert.send(self._document, documents=docs) - try: - ids = self._collection.insert(raw, **write_concern) - except pymongo.errors.DuplicateKeyError, err: - message = 'Could not save document (%s)' - raise NotUniqueError(message % unicode(err)) - except pymongo.errors.OperationFailure, err: - message = 'Could not save document (%s)' - if re.match('^E1100[01] duplicate key', unicode(err)): - # E11000 - duplicate key error index - # E11001 - duplicate key on update - message = u'Tried to save duplicate unique keys (%s)' - raise NotUniqueError(message % unicode(err)) - raise OperationError(message % unicode(err)) - - if not load_bulk: - signals.post_bulk_insert.send( - self._document, documents=docs, loaded=False) - return return_one and ids[0] or ids - - documents = self.in_bulk(ids) - results = [] - for obj_id in ids: - results.append(documents.get(obj_id)) - signals.post_bulk_insert.send( - self._document, documents=results, loaded=True) - return return_one and results[0] or results - - def count(self, with_limit_and_skip=False): - """Count the selected elements in the query. - - :param with_limit_and_skip (optional): take any :meth:`limit` or - :meth:`skip` that has been applied to this cursor into account when - getting the count - """ - if self._limit == 0 and with_limit_and_skip or self._none: - return 0 - return self._cursor.count(with_limit_and_skip=with_limit_and_skip) - - def delete(self, write_concern=None, _from_doc_delete=False): - """Delete the documents matched by the query. - - :param write_concern: Extra keyword arguments are passed down which - will be used as options for the resultant - ``getLastError`` command. For example, - ``save(..., write_concern={w: 2, fsync: True}, ...)`` will - wait until at least two servers have recorded the write and - will force an fsync on the primary server. - :param _from_doc_delete: True when called from document delete therefore - signals will have been triggered so don't loop. - - :returns number of deleted documents - """ - queryset = self.clone() - doc = queryset._document - - if write_concern is None: - write_concern = {} - - # Handle deletes where skips or limits have been applied or - # there is an untriggered delete signal - has_delete_signal = signals.signals_available and ( - signals.pre_delete.has_receivers_for(self._document) or - signals.post_delete.has_receivers_for(self._document)) - - call_document_delete = (queryset._skip or queryset._limit or - has_delete_signal) and not _from_doc_delete - - if call_document_delete: - cnt = 0 - for doc in queryset: - doc.delete(write_concern=write_concern) - cnt += 1 - return cnt - - delete_rules = doc._meta.get('delete_rules') or {} - # Check for DENY rules before actually deleting/nullifying any other - # references - for rule_entry in delete_rules: - document_cls, field_name = rule_entry - if document_cls._meta.get('abstract'): - continue - rule = doc._meta['delete_rules'][rule_entry] - if rule == DENY and document_cls.objects( - **{field_name + '__in': self}).count() > 0: - msg = ("Could not delete document (%s.%s refers to it)" - % (document_cls.__name__, field_name)) - raise OperationError(msg) - - for rule_entry in delete_rules: - document_cls, field_name = rule_entry - if document_cls._meta.get('abstract'): - continue - rule = doc._meta['delete_rules'][rule_entry] - if rule == CASCADE: - ref_q = document_cls.objects(**{field_name + '__in': self}) - ref_q_count = ref_q.count() - if (doc != document_cls and ref_q_count > 0 - or (doc == document_cls and ref_q_count > 0)): - ref_q.delete(write_concern=write_concern) - elif rule == NULLIFY: - document_cls.objects(**{field_name + '__in': self}).update( - write_concern=write_concern, **{'unset__%s' % field_name: 1}) - elif rule == PULL: - document_cls.objects(**{field_name + '__in': self}).update( - write_concern=write_concern, - **{'pull_all__%s' % field_name: self}) - - result = queryset._collection.remove(queryset._query, **write_concern) - return result["n"] - - def update(self, upsert=False, multi=True, write_concern=None, - full_result=False, **update): - """Perform an atomic update on the fields matched by the query. - - :param upsert: Any existing document with that "_id" is overwritten. - :param multi: Update multiple documents. - :param write_concern: Extra keyword arguments are passed down which - will be used as options for the resultant - ``getLastError`` command. For example, - ``save(..., write_concern={w: 2, fsync: True}, ...)`` will - wait until at least two servers have recorded the write and - will force an fsync on the primary server. - :param full_result: Return the full result rather than just the number - updated. - :param update: Django-style update keyword arguments - - .. versionadded:: 0.2 - """ - if not update and not upsert: - raise OperationError("No update parameters, would remove data") - - if write_concern is None: - write_concern = {} - - queryset = self.clone() - query = queryset._query - update = transform.update(queryset._document, **update) - - # If doing an atomic upsert on an inheritable class - # then ensure we add _cls to the update operation - if upsert and '_cls' in query: - if '$set' in update: - update["$set"]["_cls"] = queryset._document._class_name - else: - update["$set"] = {"_cls": queryset._document._class_name} - try: - result = queryset._collection.update(query, update, multi=multi, - upsert=upsert, **write_concern) - if full_result: - return result - elif result: - return result['n'] - except pymongo.errors.DuplicateKeyError, err: - raise NotUniqueError(u'Update failed (%s)' % unicode(err)) - except pymongo.errors.OperationFailure, err: - if unicode(err) == u'multi not coded yet': - message = u'update() method requires MongoDB 1.1.3+' - raise OperationError(message) - raise OperationError(u'Update failed (%s)' % unicode(err)) - - def update_one(self, upsert=False, write_concern=None, **update): - """Perform an atomic update on first field matched by the query. - - :param upsert: Any existing document with that "_id" is overwritten. - :param write_concern: Extra keyword arguments are passed down which - will be used as options for the resultant - ``getLastError`` command. For example, - ``save(..., write_concern={w: 2, fsync: True}, ...)`` will - wait until at least two servers have recorded the write and - will force an fsync on the primary server. - :param update: Django-style update keyword arguments - - .. versionadded:: 0.2 - """ - return self.update( - upsert=upsert, multi=False, write_concern=write_concern, **update) - - def modify(self, upsert=False, full_response=False, remove=False, new=False, **update): - """Update and return the updated document. - - Returns either the document before or after modification based on `new` - parameter. If no documents match the query and `upsert` is false, - returns ``None``. If upserting and `new` is false, returns ``None``. - - If the full_response parameter is ``True``, the return value will be - the entire response object from the server, including the 'ok' and - 'lastErrorObject' fields, rather than just the modified document. - This is useful mainly because the 'lastErrorObject' document holds - information about the command's execution. - - :param upsert: insert if document doesn't exist (default ``False``) - :param full_response: return the entire response object from the - server (default ``False``) - :param remove: remove rather than updating (default ``False``) - :param new: return updated rather than original document - (default ``False``) - :param update: Django-style update keyword arguments - - .. versionadded:: 0.9 - """ - - if remove and new: - raise OperationError("Conflicting parameters: remove and new") - - if not update and not upsert and not remove: - raise OperationError( - "No update parameters, must either update or remove") - - queryset = self.clone() - query = queryset._query - update = transform.update(queryset._document, **update) - sort = queryset._ordering - - try: - result = queryset._collection.find_and_modify( - query, update, upsert=upsert, sort=sort, remove=remove, new=new, - full_response=full_response, **self._cursor_args) - except pymongo.errors.DuplicateKeyError, err: - raise NotUniqueError(u"Update failed (%s)" % err) - except pymongo.errors.OperationFailure, err: - raise OperationError(u"Update failed (%s)" % err) - - if full_response: - if result["value"] is not None: - result["value"] = self._document._from_son(result["value"], only_fields=self.only_fields) - else: - if result is not None: - result = self._document._from_son(result, only_fields=self.only_fields) - - return result - - def with_id(self, object_id): - """Retrieve the object matching the id provided. Uses `object_id` only - and raises InvalidQueryError if a filter has been applied. Returns - `None` if no document exists with that id. - - :param object_id: the value for the id of the document to look up - - .. versionchanged:: 0.6 Raises InvalidQueryError if filter has been set - """ - queryset = self.clone() - if not queryset._query_obj.empty: - msg = "Cannot use a filter whilst using `with_id`" - raise InvalidQueryError(msg) - return queryset.filter(pk=object_id).first() - - def in_bulk(self, object_ids): - """Retrieve a set of documents by their ids. - - :param object_ids: a list or tuple of ``ObjectId``\ s - :rtype: dict of ObjectIds as keys and collection-specific - Document subclasses as values. - - .. versionadded:: 0.3 - """ - doc_map = {} - - docs = self._collection.find({'_id': {'$in': object_ids}}, - **self._cursor_args) - if self._scalar: - for doc in docs: - doc_map[doc['_id']] = self._get_scalar( - self._document._from_son(doc, only_fields=self.only_fields)) - elif self._as_pymongo: - for doc in docs: - doc_map[doc['_id']] = self._get_as_pymongo(doc) - else: - for doc in docs: - doc_map[doc['_id']] = self._document._from_son(doc, - only_fields=self.only_fields, - _auto_dereference=self._auto_dereference) - - return doc_map - - def none(self): - """Helper that just returns a list""" - queryset = self.clone() - queryset._none = True - return queryset - - def no_sub_classes(self): - """ - Only return instances of this document and not any inherited documents - """ - if self._document._meta.get('allow_inheritance') is True: - self._initial_query = {"_cls": self._document._class_name} - - return self - - def using(self, alias): - """This method is for controlling which database the QuerySet will be evaluated against if you are using more than one database. - - :param alias: The database alias - - .. versionadded:: 0.9 - """ - - with switch_db(self._document, alias) as cls: - collection = cls._get_collection() - - return self.clone_into(self.__class__(self._document, collection)) - - def clone(self): - """Creates a copy of the current - :class:`~mongoengine.queryset.QuerySet` - - .. versionadded:: 0.5 - """ - return self.clone_into(self.__class__(self._document, self._collection_obj)) - - def clone_into(self, cls): - """Creates a copy of the current - :class:`~mongoengine.queryset.base.BaseQuerySet` into another child class - """ - if not isinstance(cls, BaseQuerySet): - raise OperationError( - '%s is not a subclass of BaseQuerySet' % cls.__name__) - - copy_props = ('_mongo_query', '_initial_query', '_none', '_query_obj', - '_where_clause', '_loaded_fields', '_ordering', '_snapshot', - '_timeout', '_class_check', '_slave_okay', '_read_preference', - '_iter', '_scalar', '_as_pymongo', '_as_pymongo_coerce', - '_limit', '_skip', '_hint', '_auto_dereference', - '_search_text', 'only_fields', '_max_time_ms') - - for prop in copy_props: - val = getattr(self, prop) - setattr(cls, prop, copy.copy(val)) - - if self._cursor_obj: - cls._cursor_obj = self._cursor_obj.clone() - - return cls - - def select_related(self, max_depth=1): - """Handles dereferencing of :class:`~bson.dbref.DBRef` objects or - :class:`~bson.object_id.ObjectId` a maximum depth in order to cut down - the number queries to mongodb. - - .. versionadded:: 0.5 - """ - # Make select related work the same for querysets - max_depth += 1 - queryset = self.clone() - return queryset._dereference(queryset, max_depth=max_depth) - - def limit(self, n): - """Limit the number of returned documents to `n`. This may also be - achieved using array-slicing syntax (e.g. ``User.objects[:5]``). - - :param n: the maximum number of objects to return - """ - queryset = self.clone() - if n == 0: - queryset._cursor.limit(1) - else: - queryset._cursor.limit(n) - queryset._limit = n - # Return self to allow chaining - return queryset - - def skip(self, n): - """Skip `n` documents before returning the results. This may also be - achieved using array-slicing syntax (e.g. ``User.objects[5:]``). - - :param n: the number of objects to skip before returning results - """ - queryset = self.clone() - queryset._cursor.skip(n) - queryset._skip = n - return queryset - - def hint(self, index=None): - """Added 'hint' support, telling Mongo the proper index to use for the - query. - - Judicious use of hints can greatly improve query performance. When - doing a query on multiple fields (at least one of which is indexed) - pass the indexed field as a hint to the query. - - Hinting will not do anything if the corresponding index does not exist. - The last hint applied to this cursor takes precedence over all others. - - .. versionadded:: 0.5 - """ - queryset = self.clone() - queryset._cursor.hint(index) - queryset._hint = index - return queryset - - def distinct(self, field): - """Return a list of distinct values for a given field. - - :param field: the field to select distinct values from - - .. note:: This is a command and won't take ordering or limit into - account. - - .. versionadded:: 0.4 - .. versionchanged:: 0.5 - Fixed handling references - .. versionchanged:: 0.6 - Improved db_field refrence handling - """ - queryset = self.clone() - try: - field = self._fields_to_dbfields([field]).pop() - finally: - distinct = self._dereference(queryset._cursor.distinct(field), 1, - name=field, instance=self._document) - - doc_field = self._document._fields.get(field.split('.', 1)[0]) - instance = False - # We may need to cast to the correct type eg. ListField(EmbeddedDocumentField) - EmbeddedDocumentField = _import_class('EmbeddedDocumentField') - ListField = _import_class('ListField') - GenericEmbeddedDocumentField = _import_class('GenericEmbeddedDocumentField') - if isinstance(doc_field, ListField): - doc_field = getattr(doc_field, "field", doc_field) - if isinstance(doc_field, (EmbeddedDocumentField, GenericEmbeddedDocumentField)): - instance = getattr(doc_field, "document_type", False) - # handle distinct on subdocuments - if '.' in field: - for field_part in field.split('.')[1:]: - # if looping on embedded document, get the document type instance - if instance and isinstance(doc_field, (EmbeddedDocumentField, GenericEmbeddedDocumentField)): - doc_field = instance - # now get the subdocument - doc_field = getattr(doc_field, field_part, doc_field) - # We may need to cast to the correct type eg. ListField(EmbeddedDocumentField) - if isinstance(doc_field, ListField): - doc_field = getattr(doc_field, "field", doc_field) - if isinstance(doc_field, (EmbeddedDocumentField, GenericEmbeddedDocumentField)): - instance = getattr(doc_field, "document_type", False) - if instance and isinstance(doc_field, (EmbeddedDocumentField, - GenericEmbeddedDocumentField)): - distinct = [instance(**doc) for doc in distinct] - return distinct - - def only(self, *fields): - """Load only a subset of this document's fields. :: - - post = BlogPost.objects(...).only("title", "author.name") - - .. note :: `only()` is chainable and will perform a union :: - So with the following it will fetch both: `title` and `author.name`:: - - post = BlogPost.objects.only("title").only("author.name") - - :func:`~mongoengine.queryset.QuerySet.all_fields` will reset any - field filters. - - :param fields: fields to include - - .. versionadded:: 0.3 - .. versionchanged:: 0.5 - Added subfield support - """ - fields = dict([(f, QueryFieldList.ONLY) for f in fields]) - self.only_fields = fields.keys() - return self.fields(True, **fields) - - def exclude(self, *fields): - """Opposite to .only(), exclude some document's fields. :: - - post = BlogPost.objects(...).exclude("comments") - - .. note :: `exclude()` is chainable and will perform a union :: - So with the following it will exclude both: `title` and `author.name`:: - - post = BlogPost.objects.exclude("title").exclude("author.name") - - :func:`~mongoengine.queryset.QuerySet.all_fields` will reset any - field filters. - - :param fields: fields to exclude - - .. versionadded:: 0.5 - """ - fields = dict([(f, QueryFieldList.EXCLUDE) for f in fields]) - return self.fields(**fields) - - def fields(self, _only_called=False, **kwargs): - """Manipulate how you load this document's fields. Used by `.only()` - and `.exclude()` to manipulate which fields to retrieve. Fields also - allows for a greater level of control for example: - - Retrieving a Subrange of Array Elements: - - You can use the $slice operator to retrieve a subrange of elements in - an array. For example to get the first 5 comments:: - - post = BlogPost.objects(...).fields(slice__comments=5) - - :param kwargs: A dictionary identifying what to include - - .. versionadded:: 0.5 - """ - - # Check for an operator and transform to mongo-style if there is - operators = ["slice"] - cleaned_fields = [] - for key, value in kwargs.items(): - parts = key.split('__') - op = None - if parts[0] in operators: - op = parts.pop(0) - value = {'$' + op: value} - key = '.'.join(parts) - cleaned_fields.append((key, value)) - - fields = sorted(cleaned_fields, key=operator.itemgetter(1)) - queryset = self.clone() - for value, group in itertools.groupby(fields, lambda x: x[1]): - fields = [field for field, value in group] - fields = queryset._fields_to_dbfields(fields) - queryset._loaded_fields += QueryFieldList( - fields, value=value, _only_called=_only_called) - - return queryset - - def all_fields(self): - """Include all fields. Reset all previously calls of .only() or - .exclude(). :: - - post = BlogPost.objects.exclude("comments").all_fields() - - .. versionadded:: 0.5 - """ - queryset = self.clone() - queryset._loaded_fields = QueryFieldList( - always_include=queryset._loaded_fields.always_include) - return queryset - - def order_by(self, *keys): - """Order the :class:`~mongoengine.queryset.QuerySet` by the keys. The - order may be specified by prepending each of the keys by a + or a -. - Ascending order is assumed. - - :param keys: fields to order the query results by; keys may be - prefixed with **+** or **-** to determine the ordering direction - """ - queryset = self.clone() - queryset._ordering = queryset._get_order_by(keys) - return queryset - - def explain(self, format=False): - """Return an explain plan record for the - :class:`~mongoengine.queryset.QuerySet`\ 's cursor. - - :param format: format the plan before returning it - """ - plan = self._cursor.explain() - if format: - plan = pprint.pformat(plan) - return plan - - def snapshot(self, enabled): - """Enable or disable snapshot mode when querying. - - :param enabled: whether or not snapshot mode is enabled - - ..versionchanged:: 0.5 - made chainable - """ - queryset = self.clone() - queryset._snapshot = enabled - return queryset - - def timeout(self, enabled): - """Enable or disable the default mongod timeout when querying. - - :param enabled: whether or not the timeout is used - - ..versionchanged:: 0.5 - made chainable - """ - queryset = self.clone() - queryset._timeout = enabled - return queryset - - def slave_okay(self, enabled): - """Enable or disable the slave_okay when querying. - - :param enabled: whether or not the slave_okay is enabled - """ - queryset = self.clone() - queryset._slave_okay = enabled - return queryset - - def read_preference(self, read_preference): - """Change the read_preference when querying. - - :param read_preference: override ReplicaSetConnection-level - preference. - """ - validate_read_preference('read_preference', read_preference) - queryset = self.clone() - queryset._read_preference = read_preference - return queryset - - def scalar(self, *fields): - """Instead of returning Document instances, return either a specific - value or a tuple of values in order. - - Can be used along with - :func:`~mongoengine.queryset.QuerySet.no_dereference` to turn off - dereferencing. - - .. note:: This effects all results and can be unset by calling - ``scalar`` without arguments. Calls ``only`` automatically. - - :param fields: One or more fields to return instead of a Document. - """ - queryset = self.clone() - queryset._scalar = list(fields) - - if fields: - queryset = queryset.only(*fields) - else: - queryset = queryset.all_fields() - - return queryset - - def values_list(self, *fields): - """An alias for scalar""" - return self.scalar(*fields) - - def as_pymongo(self, coerce_types=False): - """Instead of returning Document instances, return raw values from - pymongo. - - :param coerce_type: Field types (if applicable) would be use to - coerce types. - """ - queryset = self.clone() - queryset._as_pymongo = True - queryset._as_pymongo_coerce = coerce_types - return queryset - - def max_time_ms(self, ms): - """Wait `ms` milliseconds before killing the query on the server - - :param ms: the number of milliseconds before killing the query on the server - """ - return self._chainable_method("max_time_ms", ms) - - # JSON Helpers - - def to_json(self, *args, **kwargs): - """Converts a queryset to JSON""" - return json_util.dumps(self.as_pymongo(), *args, **kwargs) - - def from_json(self, json_data): - """Converts json data to unsaved objects""" - son_data = json_util.loads(json_data) - return [self._document._from_son(data, only_fields=self.only_fields) for data in son_data] - - def aggregate(self, *pipeline, **kwargs): - """ - Perform a aggregate function based in your queryset params - :param pipeline: list of aggregation commands,\ - see: http://docs.mongodb.org/manual/core/aggregation-pipeline/ - - .. versionadded:: 0.9 - """ - initial_pipeline = [] - - if self._query: - initial_pipeline.append({'$match': self._query}) - - if self._ordering: - initial_pipeline.append({'$sort': dict(self._ordering)}) - - if self._limit is not None: - initial_pipeline.append({'$limit': self._limit}) - - if self._skip is not None: - initial_pipeline.append({'$skip': self._skip}) - - pipeline = initial_pipeline + list(pipeline) - - return self._collection.aggregate(pipeline, cursor={}, **kwargs) - - # JS functionality - def map_reduce(self, map_f, reduce_f, output, finalize_f=None, limit=None, - scope=None): - """Perform a map/reduce query using the current query spec - and ordering. While ``map_reduce`` respects ``QuerySet`` chaining, - it must be the last call made, as it does not return a maleable - ``QuerySet``. - - See the :meth:`~mongoengine.tests.QuerySetTest.test_map_reduce` - and :meth:`~mongoengine.tests.QuerySetTest.test_map_advanced` - tests in ``tests.queryset.QuerySetTest`` for usage examples. - - :param map_f: map function, as :class:`~bson.code.Code` or string - :param reduce_f: reduce function, as - :class:`~bson.code.Code` or string - :param output: output collection name, if set to 'inline' will try to - use :class:`~pymongo.collection.Collection.inline_map_reduce` - This can also be a dictionary containing output options - see: http://docs.mongodb.org/manual/reference/command/mapReduce/#dbcmd.mapReduce - :param finalize_f: finalize function, an optional function that - performs any post-reduction processing. - :param scope: values to insert into map/reduce global scope. Optional. - :param limit: number of objects from current query to provide - to map/reduce method - - Returns an iterator yielding - :class:`~mongoengine.document.MapReduceDocument`. - - .. note:: - - Map/Reduce changed in server version **>= 1.7.4**. The PyMongo - :meth:`~pymongo.collection.Collection.map_reduce` helper requires - PyMongo version **>= 1.11**. - - .. versionchanged:: 0.5 - - removed ``keep_temp`` keyword argument, which was only relevant - for MongoDB server versions older than 1.7.4 - - .. versionadded:: 0.3 - """ - queryset = self.clone() - - MapReduceDocument = _import_class('MapReduceDocument') - - if not hasattr(self._collection, "map_reduce"): - raise NotImplementedError("Requires MongoDB >= 1.7.1") - - map_f_scope = {} - if isinstance(map_f, Code): - map_f_scope = map_f.scope - map_f = unicode(map_f) - map_f = Code(queryset._sub_js_fields(map_f), map_f_scope) - - reduce_f_scope = {} - if isinstance(reduce_f, Code): - reduce_f_scope = reduce_f.scope - reduce_f = unicode(reduce_f) - reduce_f_code = queryset._sub_js_fields(reduce_f) - reduce_f = Code(reduce_f_code, reduce_f_scope) - - mr_args = {'query': queryset._query} - - if finalize_f: - finalize_f_scope = {} - if isinstance(finalize_f, Code): - finalize_f_scope = finalize_f.scope - finalize_f = unicode(finalize_f) - finalize_f_code = queryset._sub_js_fields(finalize_f) - finalize_f = Code(finalize_f_code, finalize_f_scope) - mr_args['finalize'] = finalize_f - - if scope: - mr_args['scope'] = scope - - if limit: - mr_args['limit'] = limit - - if output == 'inline' and not queryset._ordering: - map_reduce_function = 'inline_map_reduce' - else: - map_reduce_function = 'map_reduce' - - if isinstance(output, basestring): - mr_args['out'] = output - - elif isinstance(output, dict): - ordered_output = [] - - for part in ('replace', 'merge', 'reduce'): - value = output.get(part) - if value: - ordered_output.append((part, value)) - break - - else: - raise OperationError("actionData not specified for output") - - db_alias = output.get('db_alias') - remaing_args = ['db', 'sharded', 'nonAtomic'] - - if db_alias: - ordered_output.append(('db', get_db(db_alias).name)) - del remaing_args[0] - - for part in remaing_args: - value = output.get(part) - if value: - ordered_output.append((part, value)) - - mr_args['out'] = SON(ordered_output) - - results = getattr(queryset._collection, map_reduce_function)( - map_f, reduce_f, **mr_args) - - if map_reduce_function == 'map_reduce': - results = results.find() - - if queryset._ordering: - results = results.sort(queryset._ordering) - - for doc in results: - yield MapReduceDocument(queryset._document, queryset._collection, - doc['_id'], doc['value']) - - def exec_js(self, code, *fields, **options): - """Execute a Javascript function on the server. A list of fields may be - provided, which will be translated to their correct names and supplied - as the arguments to the function. A few extra variables are added to - the function's scope: ``collection``, which is the name of the - collection in use; ``query``, which is an object representing the - current query; and ``options``, which is an object containing any - options specified as keyword arguments. - - As fields in MongoEngine may use different names in the database (set - using the :attr:`db_field` keyword argument to a :class:`Field` - constructor), a mechanism exists for replacing MongoEngine field names - with the database field names in Javascript code. When accessing a - field, use square-bracket notation, and prefix the MongoEngine field - name with a tilde (~). - - :param code: a string of Javascript code to execute - :param fields: fields that you will be using in your function, which - will be passed in to your function as arguments - :param options: options that you want available to the function - (accessed in Javascript through the ``options`` object) - """ - queryset = self.clone() - - code = queryset._sub_js_fields(code) - - fields = [queryset._document._translate_field_name(f) for f in fields] - collection = queryset._document._get_collection_name() - - scope = { - 'collection': collection, - 'options': options or {}, - } - - query = queryset._query - if queryset._where_clause: - query['$where'] = queryset._where_clause - - scope['query'] = query - code = Code(code, scope=scope) - - db = queryset._document._get_db() - return db.eval(code, *fields) - - def where(self, where_clause): - """Filter ``QuerySet`` results with a ``$where`` clause (a Javascript - expression). Performs automatic field name substitution like - :meth:`mongoengine.queryset.Queryset.exec_js`. - - .. note:: When using this mode of query, the database will call your - function, or evaluate your predicate clause, for each object - in the collection. - - .. versionadded:: 0.5 - """ - queryset = self.clone() - where_clause = queryset._sub_js_fields(where_clause) - queryset._where_clause = where_clause - return queryset - - def sum(self, field): - """Sum over the values of the specified field. - - :param field: the field to sum over; use dot-notation to refer to - embedded document fields - - .. versionchanged:: 0.5 - updated to map_reduce as db.eval doesnt work - with sharding. - """ - map_func = """ - function() { - var path = '{{~%(field)s}}'.split('.'), - field = this; - - for (p in path) { - if (typeof field != 'undefined') - field = field[path[p]]; - else - break; - } - - if (field && field.constructor == Array) { - field.forEach(function(item) { - emit(1, item||0); - }); - } else if (typeof field != 'undefined') { - emit(1, field||0); - } - } - """ % dict(field=field) - - reduce_func = Code(""" - function(key, values) { - var sum = 0; - for (var i in values) { - sum += values[i]; - } - return sum; - } - """) - - for result in self.map_reduce(map_func, reduce_func, output='inline'): - return result.value - else: - return 0 - - def average(self, field): - """Average over the values of the specified field. - - :param field: the field to average over; use dot-notation to refer to - embedded document fields - - .. versionchanged:: 0.5 - updated to map_reduce as db.eval doesnt work - with sharding. - """ - map_func = """ - function() { - var path = '{{~%(field)s}}'.split('.'), - field = this; - - for (p in path) { - if (typeof field != 'undefined') - field = field[path[p]]; - else - break; - } - - if (field && field.constructor == Array) { - field.forEach(function(item) { - emit(1, {t: item||0, c: 1}); - }); - } else if (typeof field != 'undefined') { - emit(1, {t: field||0, c: 1}); - } - } - """ % dict(field=field) - - reduce_func = Code(""" - function(key, values) { - var out = {t: 0, c: 0}; - for (var i in values) { - var value = values[i]; - out.t += value.t; - out.c += value.c; - } - return out; - } - """) - - finalize_func = Code(""" - function(key, value) { - return value.t / value.c; - } - """) - - for result in self.map_reduce(map_func, reduce_func, - finalize_f=finalize_func, output='inline'): - return result.value - else: - return 0 - - def item_frequencies(self, field, normalize=False, map_reduce=True): - """Returns a dictionary of all items present in a field across - the whole queried set of documents, and their corresponding frequency. - This is useful for generating tag clouds, or searching documents. - - .. note:: - - Can only do direct simple mappings and cannot map across - :class:`~mongoengine.fields.ReferenceField` or - :class:`~mongoengine.fields.GenericReferenceField` for more complex - counting a manual map reduce call would is required. - - If the field is a :class:`~mongoengine.fields.ListField`, the items within - each list will be counted individually. - - :param field: the field to use - :param normalize: normalize the results so they add to 1.0 - :param map_reduce: Use map_reduce over exec_js - - .. versionchanged:: 0.5 defaults to map_reduce and can handle embedded - document lookups - """ - if map_reduce: - return self._item_frequencies_map_reduce(field, - normalize=normalize) - return self._item_frequencies_exec_js(field, normalize=normalize) - - # Iterator helpers - - def next(self): - """Wrap the result in a :class:`~mongoengine.Document` object. - """ - if self._limit == 0 or self._none: - raise StopIteration - - raw_doc = self._cursor.next() - if self._as_pymongo: - return self._get_as_pymongo(raw_doc) - doc = self._document._from_son(raw_doc, - _auto_dereference=self._auto_dereference, only_fields=self.only_fields) - - if self._scalar: - return self._get_scalar(doc) - - return doc - - def rewind(self): - """Rewind the cursor to its unevaluated state. - - - .. versionadded:: 0.3 - """ - self._iter = False - self._cursor.rewind() - - # Properties - - @property - def _collection(self): - """Property that returns the collection object. This allows us to - perform operations only if the collection is accessed. - """ - return self._collection_obj - - @property - def _cursor_args(self): - cursor_args = { - 'snapshot': self._snapshot, - 'timeout': self._timeout - } - if self._read_preference is not None: - cursor_args['read_preference'] = self._read_preference - else: - cursor_args['slave_okay'] = self._slave_okay - if self._loaded_fields: - cursor_args['fields'] = self._loaded_fields.as_dict() - - if self._search_text: - if 'fields' not in cursor_args: - cursor_args['fields'] = {} - - cursor_args['fields']['_text_score'] = {'$meta': "textScore"} - - return cursor_args - - @property - def _cursor(self): - if self._cursor_obj is None: - - self._cursor_obj = self._collection.find(self._query, - **self._cursor_args) - # Apply where clauses to cursor - if self._where_clause: - where_clause = self._sub_js_fields(self._where_clause) - self._cursor_obj.where(where_clause) - - if self._ordering: - # Apply query ordering - self._cursor_obj.sort(self._ordering) - elif self._ordering is None and self._document._meta['ordering']: - # Otherwise, apply the ordering from the document model, unless - # it's been explicitly cleared via order_by with no arguments - order = self._get_order_by(self._document._meta['ordering']) - self._cursor_obj.sort(order) - - if self._limit is not None: - self._cursor_obj.limit(self._limit) - - if self._skip is not None: - self._cursor_obj.skip(self._skip) - - if self._hint != -1: - self._cursor_obj.hint(self._hint) - - return self._cursor_obj - - def __deepcopy__(self, memo): - """Essential for chained queries with ReferenceFields involved""" - return self.clone() - - @property - def _query(self): - if self._mongo_query is None: - self._mongo_query = self._query_obj.to_query(self._document) - if self._class_check and self._initial_query: - if "_cls" in self._mongo_query: - self._mongo_query = {"$and": [self._initial_query, self._mongo_query]} - else: - self._mongo_query.update(self._initial_query) - return self._mongo_query - - @property - def _dereference(self): - if not self.__dereference: - self.__dereference = _import_class('DeReference')() - return self.__dereference - - def no_dereference(self): - """Turn off any dereferencing for the results of this queryset. - """ - queryset = self.clone() - queryset._auto_dereference = False - return queryset - - # Helper Functions - - def _item_frequencies_map_reduce(self, field, normalize=False): - map_func = """ - function() { - var path = '{{~%(field)s}}'.split('.'); - var field = this; - - for (p in path) { - if (typeof field != 'undefined') - field = field[path[p]]; - else - break; - } - if (field && field.constructor == Array) { - field.forEach(function(item) { - emit(item, 1); - }); - } else if (typeof field != 'undefined') { - emit(field, 1); - } else { - emit(null, 1); - } - } - """ % dict(field=field) - reduce_func = """ - function(key, values) { - var total = 0; - var valuesSize = values.length; - for (var i=0; i < valuesSize; i++) { - total += parseInt(values[i], 10); - } - return total; - } - """ - values = self.map_reduce(map_func, reduce_func, 'inline') - frequencies = {} - for f in values: - key = f.key - if isinstance(key, float): - if int(key) == key: - key = int(key) - frequencies[key] = int(f.value) - - if normalize: - count = sum(frequencies.values()) - frequencies = dict([(k, float(v) / count) - for k, v in frequencies.items()]) - - return frequencies - - def _item_frequencies_exec_js(self, field, normalize=False): - """Uses exec_js to execute""" - freq_func = """ - function(path) { - var path = path.split('.'); - - var total = 0.0; - db[collection].find(query).forEach(function(doc) { - var field = doc; - for (p in path) { - if (field) - field = field[path[p]]; - else - break; - } - if (field && field.constructor == Array) { - total += field.length; - } else { - total++; - } - }); - - var frequencies = {}; - var types = {}; - var inc = 1.0; - - db[collection].find(query).forEach(function(doc) { - field = doc; - for (p in path) { - if (field) - field = field[path[p]]; - else - break; - } - if (field && field.constructor == Array) { - field.forEach(function(item) { - frequencies[item] = inc + (isNaN(frequencies[item]) ? 0: frequencies[item]); - }); - } else { - var item = field; - types[item] = item; - frequencies[item] = inc + (isNaN(frequencies[item]) ? 0: frequencies[item]); - } - }); - return [total, frequencies, types]; - } - """ - total, data, types = self.exec_js(freq_func, field) - values = dict([(types.get(k), int(v)) for k, v in data.iteritems()]) - - if normalize: - values = dict([(k, float(v) / total) for k, v in values.items()]) - - frequencies = {} - for k, v in values.iteritems(): - if isinstance(k, float): - if int(k) == k: - k = int(k) - - frequencies[k] = v - - return frequencies - - def _fields_to_dbfields(self, fields, subdoc=False): - """Translate fields paths to its db equivalents""" - ret = [] - subclasses = [] - document = self._document - if document._meta['allow_inheritance']: - subclasses = [get_document(x) - for x in document._subclasses][1:] - for field in fields: - try: - field = ".".join(f.db_field for f in - document._lookup_field(field.split('.'))) - ret.append(field) - except LookUpError, err: - found = False - for subdoc in subclasses: - try: - subfield = ".".join(f.db_field for f in - subdoc._lookup_field(field.split('.'))) - ret.append(subfield) - found = True - break - except LookUpError, e: - pass - - if not found: - raise err - return ret - - def _get_order_by(self, keys): - """Creates a list of order by fields - """ - key_list = [] - for key in keys: - if not key: - continue - - if key == '$text_score': - key_list.append(('_text_score', {'$meta': "textScore"})) - continue - - direction = pymongo.ASCENDING - if key[0] == '-': - direction = pymongo.DESCENDING - if key[0] in ('-', '+'): - key = key[1:] - key = key.replace('__', '.') - try: - key = self._document._translate_field_name(key) - except: - pass - key_list.append((key, direction)) - - if self._cursor_obj and key_list: - self._cursor_obj.sort(key_list) - return key_list - - def _get_scalar(self, doc): - - def lookup(obj, name): - chunks = name.split('__') - for chunk in chunks: - obj = getattr(obj, chunk) - return obj - - data = [lookup(doc, n) for n in self._scalar] - if len(data) == 1: - return data[0] - - return tuple(data) - - def _get_as_pymongo(self, row): - # Extract which fields paths we should follow if .fields(...) was - # used. If not, handle all fields. - if not getattr(self, '__as_pymongo_fields', None): - self.__as_pymongo_fields = [] - - for field in self._loaded_fields.fields - set(['_cls']): - self.__as_pymongo_fields.append(field) - while '.' in field: - field, _ = field.rsplit('.', 1) - self.__as_pymongo_fields.append(field) - - all_fields = not self.__as_pymongo_fields - - def clean(data, path=None): - path = path or '' - - if isinstance(data, dict): - new_data = {} - for key, value in data.iteritems(): - new_path = '%s.%s' % (path, key) if path else key - - if all_fields: - include_field = True - elif self._loaded_fields.value == QueryFieldList.ONLY: - include_field = new_path in self.__as_pymongo_fields - else: - include_field = new_path not in self.__as_pymongo_fields - - if include_field: - new_data[key] = clean(value, path=new_path) - data = new_data - elif isinstance(data, list): - data = [clean(d, path=path) for d in data] - else: - if self._as_pymongo_coerce: - # If we need to coerce types, we need to determine the - # type of this field and use the corresponding - # .to_python(...) - from mongoengine.fields import EmbeddedDocumentField - - obj = self._document - for chunk in path.split('.'): - obj = getattr(obj, chunk, None) - if obj is None: - break - elif isinstance(obj, EmbeddedDocumentField): - obj = obj.document_type - if obj and data is not None: - data = obj.to_python(data) - return data - - return clean(row) - - def _sub_js_fields(self, code): - """When fields are specified with [~fieldname] syntax, where - *fieldname* is the Python name of a field, *fieldname* will be - substituted for the MongoDB name of the field (specified using the - :attr:`name` keyword argument in a field's constructor). - """ - - def field_sub(match): - # Extract just the field name, and look up the field objects - field_name = match.group(1).split('.') - fields = self._document._lookup_field(field_name) - # Substitute the correct name for the field into the javascript - return u'["%s"]' % fields[-1].db_field - - def field_path_sub(match): - # Extract just the field name, and look up the field objects - field_name = match.group(1).split('.') - fields = self._document._lookup_field(field_name) - # Substitute the correct name for the field into the javascript - return ".".join([f.db_field for f in fields]) - - code = re.sub(u'\[\s*~([A-z_][A-z_0-9.]+?)\s*\]', field_sub, code) - code = re.sub(u'\{\{\s*~([A-z_][A-z_0-9.]+?)\s*\}\}', field_path_sub, - code) - return code - - def _chainable_method(self, method_name, val): - queryset = self.clone() - method = getattr(queryset._cursor, method_name) - method(val) - setattr(queryset, "_" + method_name, val) - return queryset - - # Deprecated - def ensure_index(self, **kwargs): - """Deprecated use :func:`Document.ensure_index`""" - msg = ("Doc.objects()._ensure_index() is deprecated. " - "Use Doc.ensure_index() instead.") - warnings.warn(msg, DeprecationWarning) - self._document.__class__.ensure_index(**kwargs) - return self - - def _ensure_indexes(self): - """Deprecated use :func:`~Document.ensure_indexes`""" - msg = ("Doc.objects()._ensure_indexes() is deprecated. " - "Use Doc.ensure_indexes() instead.") - warnings.warn(msg, DeprecationWarning) - self._document.__class__.ensure_indexes() diff --git a/awx/lib/site-packages/mongoengine/queryset/field_list.py b/awx/lib/site-packages/mongoengine/queryset/field_list.py deleted file mode 100644 index 140a71e051..0000000000 --- a/awx/lib/site-packages/mongoengine/queryset/field_list.py +++ /dev/null @@ -1,86 +0,0 @@ - -__all__ = ('QueryFieldList',) - - -class QueryFieldList(object): - """Object that handles combinations of .only() and .exclude() calls""" - ONLY = 1 - EXCLUDE = 0 - - def __init__(self, fields=None, value=ONLY, always_include=None, _only_called=False): - """The QueryFieldList builder - - :param fields: A list of fields used in `.only()` or `.exclude()` - :param value: How to handle the fields; either `ONLY` or `EXCLUDE` - :param always_include: Any fields to always_include eg `_cls` - :param _only_called: Has `.only()` been called? If so its a set of fields - otherwise it performs a union. - """ - self.value = value - self.fields = set(fields or []) - self.always_include = set(always_include or []) - self._id = None - self._only_called = _only_called - self.slice = {} - - def __add__(self, f): - if isinstance(f.value, dict): - for field in f.fields: - self.slice[field] = f.value - if not self.fields: - self.fields = f.fields - elif not self.fields: - self.fields = f.fields - self.value = f.value - self.slice = {} - elif self.value is self.ONLY and f.value is self.ONLY: - self._clean_slice() - if self._only_called: - self.fields = self.fields.union(f.fields) - else: - self.fields = f.fields - elif self.value is self.EXCLUDE and f.value is self.EXCLUDE: - self.fields = self.fields.union(f.fields) - self._clean_slice() - elif self.value is self.ONLY and f.value is self.EXCLUDE: - self.fields -= f.fields - self._clean_slice() - elif self.value is self.EXCLUDE and f.value is self.ONLY: - self.value = self.ONLY - self.fields = f.fields - self.fields - self._clean_slice() - - if '_id' in f.fields: - self._id = f.value - - if self.always_include: - if self.value is self.ONLY and self.fields: - if sorted(self.slice.keys()) != sorted(self.fields): - self.fields = self.fields.union(self.always_include) - else: - self.fields -= self.always_include - - if getattr(f, '_only_called', False): - self._only_called = True - return self - - def __nonzero__(self): - return bool(self.fields) - - def as_dict(self): - field_list = dict((field, self.value) for field in self.fields) - if self.slice: - field_list.update(self.slice) - if self._id is not None: - field_list['_id'] = self._id - return field_list - - def reset(self): - self.fields = set([]) - self.slice = {} - self.value = self.ONLY - - def _clean_slice(self): - if self.slice: - for field in set(self.slice.keys()) - self.fields: - del self.slice[field] diff --git a/awx/lib/site-packages/mongoengine/queryset/manager.py b/awx/lib/site-packages/mongoengine/queryset/manager.py deleted file mode 100644 index 47c2143dac..0000000000 --- a/awx/lib/site-packages/mongoengine/queryset/manager.py +++ /dev/null @@ -1,57 +0,0 @@ -from functools import partial -from mongoengine.queryset.queryset import QuerySet - -__all__ = ('queryset_manager', 'QuerySetManager') - - -class QuerySetManager(object): - """ - The default QuerySet Manager. - - Custom QuerySet Manager functions can extend this class and users can - add extra queryset functionality. Any custom manager methods must accept a - :class:`~mongoengine.Document` class as its first argument, and a - :class:`~mongoengine.queryset.QuerySet` as its second argument. - - The method function should return a :class:`~mongoengine.queryset.QuerySet` - , probably the same one that was passed in, but modified in some way. - """ - - get_queryset = None - default = QuerySet - - def __init__(self, queryset_func=None): - if queryset_func: - self.get_queryset = queryset_func - - def __get__(self, instance, owner): - """Descriptor for instantiating a new QuerySet object when - Document.objects is accessed. - """ - if instance is not None: - # Document class being used rather than a document object - return self - - # owner is the document that contains the QuerySetManager - queryset_class = owner._meta.get('queryset_class', self.default) - queryset = queryset_class(owner, owner._get_collection()) - if self.get_queryset: - arg_count = self.get_queryset.func_code.co_argcount - if arg_count == 1: - queryset = self.get_queryset(queryset) - elif arg_count == 2: - queryset = self.get_queryset(owner, queryset) - else: - queryset = partial(self.get_queryset, owner, queryset) - return queryset - - -def queryset_manager(func): - """Decorator that allows you to define custom QuerySet managers on - :class:`~mongoengine.Document` classes. The manager must be a function that - accepts a :class:`~mongoengine.Document` class as its first argument, and a - :class:`~mongoengine.queryset.QuerySet` as its second argument. The method - function should return a :class:`~mongoengine.queryset.QuerySet`, probably - the same one that was passed in, but modified in some way. - """ - return QuerySetManager(func) diff --git a/awx/lib/site-packages/mongoengine/queryset/queryset.py b/awx/lib/site-packages/mongoengine/queryset/queryset.py deleted file mode 100644 index e8bd66ae0a..0000000000 --- a/awx/lib/site-packages/mongoengine/queryset/queryset.py +++ /dev/null @@ -1,164 +0,0 @@ -from mongoengine.errors import OperationError -from mongoengine.queryset.base import (BaseQuerySet, DO_NOTHING, NULLIFY, - CASCADE, DENY, PULL) - -__all__ = ('QuerySet', 'QuerySetNoCache', 'DO_NOTHING', 'NULLIFY', 'CASCADE', - 'DENY', 'PULL') - -# The maximum number of items to display in a QuerySet.__repr__ -REPR_OUTPUT_SIZE = 20 -ITER_CHUNK_SIZE = 100 - - -class QuerySet(BaseQuerySet): - """The default queryset, that builds queries and handles a set of results - returned from a query. - - Wraps a MongoDB cursor, providing :class:`~mongoengine.Document` objects as - the results. - """ - - _has_more = True - _len = None - _result_cache = None - - def __iter__(self): - """Iteration utilises a results cache which iterates the cursor - in batches of ``ITER_CHUNK_SIZE``. - - If ``self._has_more`` the cursor hasn't been exhausted so cache then - batch. Otherwise iterate the result_cache. - """ - self._iter = True - if self._has_more: - return self._iter_results() - - # iterating over the cache. - return iter(self._result_cache) - - def __len__(self): - """Since __len__ is called quite frequently (for example, as part of - list(qs) we populate the result cache and cache the length. - """ - if self._len is not None: - return self._len - if self._has_more: - # populate the cache - list(self._iter_results()) - - self._len = len(self._result_cache) - return self._len - - def __repr__(self): - """Provides the string representation of the QuerySet - """ - if self._iter: - return '.. queryset mid-iteration ..' - - self._populate_cache() - data = self._result_cache[:REPR_OUTPUT_SIZE + 1] - if len(data) > REPR_OUTPUT_SIZE: - data[-1] = "...(remaining elements truncated)..." - return repr(data) - - - def _iter_results(self): - """A generator for iterating over the result cache. - - Also populates the cache if there are more possible results to yield. - Raises StopIteration when there are no more results""" - if self._result_cache is None: - self._result_cache = [] - pos = 0 - while True: - upper = len(self._result_cache) - while pos < upper: - yield self._result_cache[pos] - pos = pos + 1 - if not self._has_more: - raise StopIteration - if len(self._result_cache) <= pos: - self._populate_cache() - - def _populate_cache(self): - """ - Populates the result cache with ``ITER_CHUNK_SIZE`` more entries - (until the cursor is exhausted). - """ - if self._result_cache is None: - self._result_cache = [] - if self._has_more: - try: - for i in xrange(ITER_CHUNK_SIZE): - self._result_cache.append(self.next()) - except StopIteration: - self._has_more = False - - def count(self, with_limit_and_skip=False): - """Count the selected elements in the query. - - :param with_limit_and_skip (optional): take any :meth:`limit` or - :meth:`skip` that has been applied to this cursor into account when - getting the count - """ - if with_limit_and_skip is False: - return super(QuerySet, self).count(with_limit_and_skip) - - if self._len is None: - self._len = super(QuerySet, self).count(with_limit_and_skip) - - return self._len - - def no_cache(self): - """Convert to a non_caching queryset - - .. versionadded:: 0.8.3 Convert to non caching queryset - """ - if self._result_cache is not None: - raise OperationError("QuerySet already cached") - return self.clone_into(QuerySetNoCache(self._document, self._collection)) - - -class QuerySetNoCache(BaseQuerySet): - """A non caching QuerySet""" - - def cache(self): - """Convert to a caching queryset - - .. versionadded:: 0.8.3 Convert to caching queryset - """ - return self.clone_into(QuerySet(self._document, self._collection)) - - def __repr__(self): - """Provides the string representation of the QuerySet - - .. versionchanged:: 0.6.13 Now doesnt modify the cursor - """ - if self._iter: - return '.. queryset mid-iteration ..' - - data = [] - for i in xrange(REPR_OUTPUT_SIZE + 1): - try: - data.append(self.next()) - except StopIteration: - break - if len(data) > REPR_OUTPUT_SIZE: - data[-1] = "...(remaining elements truncated)..." - - self.rewind() - return repr(data) - - def __iter__(self): - queryset = self - if queryset._iter: - queryset = self.clone() - queryset.rewind() - return queryset - - -class QuerySetNoDeRef(QuerySet): - """Special no_dereference QuerySet""" - - def __dereference(items, max_depth=1, instance=None, name=None): - return items \ No newline at end of file diff --git a/awx/lib/site-packages/mongoengine/queryset/transform.py b/awx/lib/site-packages/mongoengine/queryset/transform.py deleted file mode 100644 index 03a09dc516..0000000000 --- a/awx/lib/site-packages/mongoengine/queryset/transform.py +++ /dev/null @@ -1,372 +0,0 @@ -from collections import defaultdict - -import pymongo -from bson import SON - -from mongoengine.connection import get_connection -from mongoengine.common import _import_class -from mongoengine.errors import InvalidQueryError, LookUpError - -__all__ = ('query', 'update') - - -COMPARISON_OPERATORS = ('ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod', - 'all', 'size', 'exists', 'not', 'elemMatch', 'type') -GEO_OPERATORS = ('within_distance', 'within_spherical_distance', - 'within_box', 'within_polygon', 'near', 'near_sphere', - 'max_distance', 'geo_within', 'geo_within_box', - 'geo_within_polygon', 'geo_within_center', - 'geo_within_sphere', 'geo_intersects') -STRING_OPERATORS = ('contains', 'icontains', 'startswith', - 'istartswith', 'endswith', 'iendswith', - 'exact', 'iexact') -CUSTOM_OPERATORS = ('match',) -MATCH_OPERATORS = (COMPARISON_OPERATORS + GEO_OPERATORS + - STRING_OPERATORS + CUSTOM_OPERATORS) - -UPDATE_OPERATORS = ('set', 'unset', 'inc', 'dec', 'pop', 'push', - 'push_all', 'pull', 'pull_all', 'add_to_set', - 'set_on_insert', 'min', 'max') - - -def query(_doc_cls=None, _field_operation=False, **query): - """Transform a query from Django-style format to Mongo format. - """ - mongo_query = {} - merge_query = defaultdict(list) - for key, value in sorted(query.items()): - if key == "__raw__": - mongo_query.update(value) - continue - - parts = key.rsplit('__') - indices = [(i, p) for i, p in enumerate(parts) if p.isdigit()] - parts = [part for part in parts if not part.isdigit()] - # Check for an operator and transform to mongo-style if there is - op = None - if len(parts) > 1 and parts[-1] in MATCH_OPERATORS: - op = parts.pop() - - negate = False - if len(parts) > 1 and parts[-1] == 'not': - parts.pop() - negate = True - - if _doc_cls: - # Switch field names to proper names [set in Field(name='foo')] - try: - fields = _doc_cls._lookup_field(parts) - except Exception, e: - raise InvalidQueryError(e) - parts = [] - - CachedReferenceField = _import_class('CachedReferenceField') - - cleaned_fields = [] - for field in fields: - append_field = True - if isinstance(field, basestring): - parts.append(field) - append_field = False - # is last and CachedReferenceField - elif isinstance(field, CachedReferenceField) and fields[-1] == field: - parts.append('%s._id' % field.db_field) - else: - parts.append(field.db_field) - - if append_field: - cleaned_fields.append(field) - - # Convert value to proper value - field = cleaned_fields[-1] - - singular_ops = [None, 'ne', 'gt', 'gte', 'lt', 'lte', 'not'] - singular_ops += STRING_OPERATORS - if op in singular_ops: - if isinstance(field, basestring): - if (op in STRING_OPERATORS and - isinstance(value, basestring)): - StringField = _import_class('StringField') - value = StringField.prepare_query_value(op, value) - else: - value = field - else: - value = field.prepare_query_value(op, value) - - if isinstance(field, CachedReferenceField) and value: - value = value['_id'] - - elif op in ('in', 'nin', 'all', 'near') and not isinstance(value, dict): - # 'in', 'nin' and 'all' require a list of values - value = [field.prepare_query_value(op, v) for v in value] - - # if op and op not in COMPARISON_OPERATORS: - if op: - if op in GEO_OPERATORS: - value = _geo_operator(field, op, value) - elif op in CUSTOM_OPERATORS: - if op in ('elem_match', 'match'): - value = field.prepare_query_value(op, value) - value = {"$elemMatch": value} - else: - NotImplementedError("Custom method '%s' has not " - "been implemented" % op) - elif op not in STRING_OPERATORS: - value = {'$' + op: value} - - if negate: - value = {'$not': value} - - for i, part in indices: - parts.insert(i, part) - key = '.'.join(parts) - if op is None or key not in mongo_query: - mongo_query[key] = value - elif key in mongo_query: - if key in mongo_query and isinstance(mongo_query[key], dict): - mongo_query[key].update(value) - # $maxDistance needs to come last - convert to SON - value_dict = mongo_query[key] - if ('$maxDistance' in value_dict and '$near' in value_dict): - value_son = SON() - if isinstance(value_dict['$near'], dict): - for k, v in value_dict.iteritems(): - if k == '$maxDistance': - continue - value_son[k] = v - if (get_connection().max_wire_version <= 1): - value_son['$maxDistance'] = value_dict[ - '$maxDistance'] - else: - value_son['$near'] = SON(value_son['$near']) - value_son['$near'][ - '$maxDistance'] = value_dict['$maxDistance'] - else: - for k, v in value_dict.iteritems(): - if k == '$maxDistance': - continue - value_son[k] = v - value_son['$maxDistance'] = value_dict['$maxDistance'] - - mongo_query[key] = value_son - else: - # Store for manually merging later - merge_query[key].append(value) - - # The queryset has been filter in such a way we must manually merge - for k, v in merge_query.items(): - merge_query[k].append(mongo_query[k]) - del mongo_query[k] - if isinstance(v, list): - value = [{k: val} for val in v] - if '$and' in mongo_query.keys(): - mongo_query['$and'].extend(value) - else: - mongo_query['$and'] = value - - return mongo_query - - -def update(_doc_cls=None, **update): - """Transform an update spec from Django-style format to Mongo format. - """ - mongo_update = {} - for key, value in update.items(): - if key == "__raw__": - mongo_update.update(value) - continue - parts = key.split('__') - # if there is no operator, default to "set" - if len(parts) < 3 and parts[0] not in UPDATE_OPERATORS: - parts.insert(0, 'set') - # Check for an operator and transform to mongo-style if there is - op = None - if parts[0] in UPDATE_OPERATORS: - op = parts.pop(0) - # Convert Pythonic names to Mongo equivalents - if op in ('push_all', 'pull_all'): - op = op.replace('_all', 'All') - elif op == 'dec': - # Support decrement by flipping a positive value's sign - # and using 'inc' - op = 'inc' - if value > 0: - value = -value - elif op == 'add_to_set': - op = 'addToSet' - elif op == 'set_on_insert': - op = "setOnInsert" - - match = None - if parts[-1] in COMPARISON_OPERATORS: - match = parts.pop() - - if _doc_cls: - # Switch field names to proper names [set in Field(name='foo')] - try: - fields = _doc_cls._lookup_field(parts) - except Exception, e: - raise InvalidQueryError(e) - parts = [] - - cleaned_fields = [] - appended_sub_field = False - for field in fields: - append_field = True - if isinstance(field, basestring): - # Convert the S operator to $ - if field == 'S': - field = '$' - parts.append(field) - append_field = False - else: - parts.append(field.db_field) - if append_field: - appended_sub_field = False - cleaned_fields.append(field) - if hasattr(field, 'field'): - cleaned_fields.append(field.field) - appended_sub_field = True - - # Convert value to proper value - if appended_sub_field: - field = cleaned_fields[-2] - else: - field = cleaned_fields[-1] - - GeoJsonBaseField = _import_class("GeoJsonBaseField") - if isinstance(field, GeoJsonBaseField): - value = field.to_mongo(value) - - if op in (None, 'set', 'push', 'pull'): - if field.required or value is not None: - value = field.prepare_query_value(op, value) - elif op in ('pushAll', 'pullAll'): - value = [field.prepare_query_value(op, v) for v in value] - elif op in ('addToSet', 'setOnInsert'): - if isinstance(value, (list, tuple, set)): - value = [field.prepare_query_value(op, v) for v in value] - elif field.required or value is not None: - value = field.prepare_query_value(op, value) - elif op == "unset": - value = 1 - - if match: - match = '$' + match - value = {match: value} - - key = '.'.join(parts) - - if not op: - raise InvalidQueryError("Updates must supply an operation " - "eg: set__FIELD=value") - - if 'pull' in op and '.' in key: - # Dot operators don't work on pull operations - # unless they point to a list field - # Otherwise it uses nested dict syntax - if op == 'pullAll': - raise InvalidQueryError("pullAll operations only support " - "a single field depth") - - # Look for the last list field and use dot notation until there - field_classes = [c.__class__ for c in cleaned_fields] - field_classes.reverse() - ListField = _import_class('ListField') - if ListField in field_classes: - # Join all fields via dot notation to the last ListField - # Then process as normal - last_listField = len( - cleaned_fields) - field_classes.index(ListField) - key = ".".join(parts[:last_listField]) - parts = parts[last_listField:] - parts.insert(0, key) - - parts.reverse() - for key in parts: - value = {key: value} - elif op == 'addToSet' and isinstance(value, list): - value = {key: {"$each": value}} - else: - value = {key: value} - key = '$' + op - - if key not in mongo_update: - mongo_update[key] = value - elif key in mongo_update and isinstance(mongo_update[key], dict): - mongo_update[key].update(value) - - return mongo_update - - -def _geo_operator(field, op, value): - """Helper to return the query for a given geo query""" - if field._geo_index == pymongo.GEO2D: - if op == "within_distance": - value = {'$within': {'$center': value}} - elif op == "within_spherical_distance": - value = {'$within': {'$centerSphere': value}} - elif op == "within_polygon": - value = {'$within': {'$polygon': value}} - elif op == "near": - value = {'$near': value} - elif op == "near_sphere": - value = {'$nearSphere': value} - elif op == 'within_box': - value = {'$within': {'$box': value}} - elif op == "max_distance": - value = {'$maxDistance': value} - else: - raise NotImplementedError("Geo method '%s' has not " - "been implemented for a GeoPointField" % op) - else: - if op == "geo_within": - value = {"$geoWithin": _infer_geometry(value)} - elif op == "geo_within_box": - value = {"$geoWithin": {"$box": value}} - elif op == "geo_within_polygon": - value = {"$geoWithin": {"$polygon": value}} - elif op == "geo_within_center": - value = {"$geoWithin": {"$center": value}} - elif op == "geo_within_sphere": - value = {"$geoWithin": {"$centerSphere": value}} - elif op == "geo_intersects": - value = {"$geoIntersects": _infer_geometry(value)} - elif op == "near": - value = {'$near': _infer_geometry(value)} - elif op == "max_distance": - value = {'$maxDistance': value} - else: - raise NotImplementedError("Geo method '%s' has not " - "been implemented for a %s " % (op, field._name)) - return value - - -def _infer_geometry(value): - """Helper method that tries to infer the $geometry shape for a given value""" - if isinstance(value, dict): - if "$geometry" in value: - return value - elif 'coordinates' in value and 'type' in value: - return {"$geometry": value} - raise InvalidQueryError("Invalid $geometry dictionary should have " - "type and coordinates keys") - elif isinstance(value, (list, set)): - try: - value[0][0][0] - return {"$geometry": {"type": "Polygon", "coordinates": value}} - except: - pass - try: - value[0][0] - return {"$geometry": {"type": "LineString", "coordinates": value}} - except: - pass - try: - value[0] - return {"$geometry": {"type": "Point", "coordinates": value}} - except: - pass - - raise InvalidQueryError("Invalid $geometry data. Can be either a dictionary " - "or (nested) lists of coordinate(s)") diff --git a/awx/lib/site-packages/mongoengine/queryset/visitor.py b/awx/lib/site-packages/mongoengine/queryset/visitor.py deleted file mode 100644 index e5d2e6152b..0000000000 --- a/awx/lib/site-packages/mongoengine/queryset/visitor.py +++ /dev/null @@ -1,162 +0,0 @@ -import copy - -from itertools import product -from functools import reduce - -from mongoengine.errors import InvalidQueryError -from mongoengine.queryset import transform - -__all__ = ('Q',) - - -class QNodeVisitor(object): - """Base visitor class for visiting Q-object nodes in a query tree. - """ - - def visit_combination(self, combination): - """Called by QCombination objects. - """ - return combination - - def visit_query(self, query): - """Called by (New)Q objects. - """ - return query - - -class DuplicateQueryConditionsError(InvalidQueryError): - pass - - -class SimplificationVisitor(QNodeVisitor): - """Simplifies query trees by combining unnecessary 'and' connection nodes - into a single Q-object. - """ - - def visit_combination(self, combination): - if combination.operation == combination.AND: - # The simplification only applies to 'simple' queries - if all(isinstance(node, Q) for node in combination.children): - queries = [n.query for n in combination.children] - try: - return Q(**self._query_conjunction(queries)) - except DuplicateQueryConditionsError: - # Cannot be simplified - pass - return combination - - def _query_conjunction(self, queries): - """Merges query dicts - effectively &ing them together. - """ - query_ops = set() - combined_query = {} - for query in queries: - ops = set(query.keys()) - # Make sure that the same operation isn't applied more than once - # to a single field - intersection = ops.intersection(query_ops) - if intersection: - raise DuplicateQueryConditionsError() - - query_ops.update(ops) - combined_query.update(copy.deepcopy(query)) - return combined_query - - -class QueryCompilerVisitor(QNodeVisitor): - """Compiles the nodes in a query tree to a PyMongo-compatible query - dictionary. - """ - - def __init__(self, document): - self.document = document - - def visit_combination(self, combination): - operator = "$and" - if combination.operation == combination.OR: - operator = "$or" - return {operator: combination.children} - - def visit_query(self, query): - return transform.query(self.document, **query.query) - - -class QNode(object): - """Base class for nodes in query trees. - """ - - AND = 0 - OR = 1 - - def to_query(self, document): - query = self.accept(SimplificationVisitor()) - query = query.accept(QueryCompilerVisitor(document)) - return query - - def accept(self, visitor): - raise NotImplementedError - - def _combine(self, other, operation): - """Combine this node with another node into a QCombination object. - """ - if getattr(other, 'empty', True): - return self - - if self.empty: - return other - - return QCombination(operation, [self, other]) - - @property - def empty(self): - return False - - def __or__(self, other): - return self._combine(other, self.OR) - - def __and__(self, other): - return self._combine(other, self.AND) - - -class QCombination(QNode): - """Represents the combination of several conditions by a given logical - operator. - """ - - def __init__(self, operation, children): - self.operation = operation - self.children = [] - for node in children: - # If the child is a combination of the same type, we can merge its - # children directly into this combinations children - if isinstance(node, QCombination) and node.operation == operation: - self.children += node.children - else: - self.children.append(node) - - def accept(self, visitor): - for i in range(len(self.children)): - if isinstance(self.children[i], QNode): - self.children[i] = self.children[i].accept(visitor) - - return visitor.visit_combination(self) - - @property - def empty(self): - return not bool(self.children) - - -class Q(QNode): - """A simple query object, used in a query tree to build up more complex - query structures. - """ - - def __init__(self, **query): - self.query = query - - def accept(self, visitor): - return visitor.visit_query(self) - - @property - def empty(self): - return not bool(self.query) diff --git a/awx/lib/site-packages/mongoengine/signals.py b/awx/lib/site-packages/mongoengine/signals.py deleted file mode 100644 index 06fb8b4f11..0000000000 --- a/awx/lib/site-packages/mongoengine/signals.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- - -__all__ = ['pre_init', 'post_init', 'pre_save', 'pre_save_post_validation', - 'post_save', 'pre_delete', 'post_delete'] - -signals_available = False -try: - from blinker import Namespace - signals_available = True -except ImportError: - class Namespace(object): - def signal(self, name, doc=None): - return _FakeSignal(name, doc) - - class _FakeSignal(object): - """If blinker is unavailable, create a fake class with the same - interface that allows sending of signals but will fail with an - error on anything else. Instead of doing anything on send, it - will just ignore the arguments and do nothing instead. - """ - - def __init__(self, name, doc=None): - self.name = name - self.__doc__ = doc - - def _fail(self, *args, **kwargs): - raise RuntimeError('signalling support is unavailable ' - 'because the blinker library is ' - 'not installed.') - send = lambda *a, **kw: None - connect = disconnect = has_receivers_for = receivers_for = \ - temporarily_connected_to = _fail - del _fail - -# the namespace for code signals. If you are not mongoengine code, do -# not put signals in here. Create your own namespace instead. -_signals = Namespace() - -pre_init = _signals.signal('pre_init') -post_init = _signals.signal('post_init') -pre_save = _signals.signal('pre_save') -pre_save_post_validation = _signals.signal('pre_save_post_validation') -post_save = _signals.signal('post_save') -pre_delete = _signals.signal('pre_delete') -post_delete = _signals.signal('post_delete') -pre_bulk_insert = _signals.signal('pre_bulk_insert') -post_bulk_insert = _signals.signal('post_bulk_insert') diff --git a/awx/lib/site-packages/netaddr/__init__.py b/awx/lib/site-packages/netaddr/__init__.py deleted file mode 100644 index a25511adeb..0000000000 --- a/awx/lib/site-packages/netaddr/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""A Python library for manipulating IP and EUI network addresses.""" - -#: Version info (major, minor, maintenance, status) -VERSION = (0, 7, 14) -STATUS = '' -__version__ = '%d.%d.%d' % VERSION[0:3] + STATUS - -import sys as _sys - -if _sys.version_info[0:2] < (2, 4): - raise RuntimeError('Python 2.4.x or higher is required!') - -from netaddr.core import AddrConversionError, AddrFormatError, \ - NotRegisteredError, ZEROFILL, Z, INET_PTON, P, NOHOST, N - -from netaddr.ip import IPAddress, IPNetwork, IPRange, all_matching_cidrs, \ - cidr_abbrev_to_verbose, cidr_exclude, cidr_merge, iprange_to_cidrs, \ - iter_iprange, iter_unique_ips, largest_matching_cidr, \ - smallest_matching_cidr, spanning_cidr - -from netaddr.ip.sets import IPSet - -from netaddr.ip.glob import IPGlob, cidr_to_glob, glob_to_cidrs, \ - glob_to_iprange, glob_to_iptuple, iprange_to_globs, valid_glob - -from netaddr.ip.nmap import valid_nmap_range, iter_nmap_range - -from netaddr.ip.rfc1924 import base85_to_ipv6, ipv6_to_base85 - -from netaddr.eui import EUI, IAB, OUI - -from netaddr.strategy.ipv4 import valid_str as valid_ipv4 - -from netaddr.strategy.ipv6 import valid_str as valid_ipv6, ipv6_compact, \ - ipv6_full, ipv6_verbose - -from netaddr.strategy.eui48 import mac_eui48, mac_unix, mac_unix_expanded, \ - mac_cisco, mac_bare, mac_pgsql, valid_str as valid_mac - -__all__ = [ - # Constants. - 'ZEROFILL', 'Z', 'INET_PTON', 'P', 'NOHOST', 'N', - - # Custom Exceptions. - 'AddrConversionError', 'AddrFormatError', 'NotRegisteredError', - - # IP classes. - 'IPAddress', 'IPNetwork', 'IPRange', 'IPSet', - - # IPv6 dialect classes. - 'ipv6_compact', 'ipv6_full', 'ipv6_verbose', - - # IP functions and generators. - 'all_matching_cidrs', 'cidr_abbrev_to_verbose', 'cidr_exclude', - 'cidr_merge', 'iprange_to_cidrs', 'iter_iprange', 'iter_unique_ips', - 'largest_matching_cidr', 'smallest_matching_cidr', 'spanning_cidr', - - # IP globbing class. - 'IPGlob', - - # IP globbing functions. - 'cidr_to_glob', 'glob_to_cidrs', 'glob_to_iprange', 'glob_to_iptuple', - 'iprange_to_globs', - - # IEEE EUI classes. - 'EUI', 'IAB', 'OUI', - - # EUI-48 (MAC) dialect classes. - 'mac_bare', 'mac_cisco', 'mac_eui48', 'mac_pgsql', 'mac_unix', - 'mac_unix_expanded', - - # Validation functions. - 'valid_ipv4', 'valid_ipv6', 'valid_glob', 'valid_mac', - - # nmap-style range functions. - 'valid_nmap_range', 'iter_nmap_range', - - # RFC 1924 functions. - 'base85_to_ipv6', 'ipv6_to_base85', -] diff --git a/awx/lib/site-packages/netaddr/compat.py b/awx/lib/site-packages/netaddr/compat.py deleted file mode 100644 index ea17954936..0000000000 --- a/awx/lib/site-packages/netaddr/compat.py +++ /dev/null @@ -1,92 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -Compatibility wrappers providing uniform behaviour for Python code required to -run under both Python 2.x and 3.x. - -All operations emulate 2.x behaviour where applicable. -""" -import sys as _sys - -if _sys.version_info[0] == 3: - # Python 3.x specific logic. - _sys_maxint = _sys.maxsize - - _int_type = int - - _str_type = str - - _is_str = lambda x: isinstance(x, (str, type(''.encode()))) - - _is_int = lambda x: isinstance(x, int) - - _callable = lambda x: hasattr(x, '__call__') - - _func_doc = lambda x: x.__doc__ - - _dict_keys = lambda x: list(x.keys()) - - _dict_items = lambda x: list(x.items()) - - _iter_dict_keys = lambda x: x.keys() - - def _bytes_join(*args): return ''.encode().join(*args) - - def _zip(*args): return list(zip(*args)) - - def _range(*args, **kwargs): return list(range(*args, **kwargs)) - - _iter_range = range - - def _func_name(f, name=None): - if name is not None: f.__name__ = name - else: return f.__name__ - - def _func_doc(f, docstring=None): - if docstring is not None: f.__doc__ = docstring - else: return f.__doc__ - -elif _sys.version_info[0:2] > [2, 3]: - # Python 2.4 or higher. - _sys_maxint = _sys.maxint - - _int_type = (int, long) - - _str_type = basestring - - _is_str = lambda x: isinstance(x, basestring) - - _is_int = lambda x: isinstance(x, (int, long)) - - _callable = lambda x: callable(x) - - _dict_keys = lambda x: x.keys() - - _dict_items = lambda x: x.items() - - _iter_dict_keys = lambda x: iter(x.keys()) - - def _bytes_join(*args): return ''.join(*args) - - def _zip(*args): return zip(*args) - - def _range(*args, **kwargs): return range(*args, **kwargs) - - _iter_range = xrange - - def _func_name(f, name=None): - if name is not None: f.func_name = name - else: return f.func_name - - def _func_doc(f, docstring=None): - if docstring is not None: f.func_doc = docstring - else: return f.func_doc - -else: - # Unsupported versions. - raise RuntimeError( - 'this module only supports Python 2.4.x or higher (including 3.x)!') - diff --git a/awx/lib/site-packages/netaddr/core.py b/awx/lib/site-packages/netaddr/core.py deleted file mode 100644 index 7bc80a95db..0000000000 --- a/awx/lib/site-packages/netaddr/core.py +++ /dev/null @@ -1,223 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""Common code shared between various netaddr sub modules""" - -import sys as _sys -import pprint as _pprint - -from netaddr.compat import _callable, _iter_dict_keys - -#: True if platform is natively big endian, False otherwise. -BIG_ENDIAN_PLATFORM = _sys.byteorder == 'big' - -#: Use inet_pton() semantics instead of inet_aton() when parsing IPv4. -P = INET_PTON = 1 - -#: Remove any preceding zeros from IPv4 address octets before parsing. -Z = ZEROFILL = 2 - -#: Remove any host bits found to the right of an applied CIDR prefix. -N = NOHOST = 4 - -#----------------------------------------------------------------------------- -# Custom exceptions. -#----------------------------------------------------------------------------- -class AddrFormatError(Exception): - """ - An Exception indicating a network address is not correctly formatted. - """ - pass - - -class AddrConversionError(Exception): - """ - An Exception indicating a failure to convert between address types or - notations. - """ - pass - - -class NotRegisteredError(Exception): - """ - An Exception indicating that an OUI or IAB was not found in the IEEE - Registry. - """ - pass - - -try: - a = 42 - a.bit_length() - # No exception, must be Python 2.7 or 3.1+ -> can use bit_length() - def num_bits(int_val): - """ - :param int_val: an unsigned integer. - - :return: the minimum number of bits needed to represent value provided. - """ - return int_val.bit_length() -except AttributeError: - # a.bit_length() excepted, must be an older Python version. - def num_bits(int_val): - """ - :param int_val: an unsigned integer. - - :return: the minimum number of bits needed to represent value provided. - """ - numbits = 0 - while int_val: - numbits += 1 - int_val >>= 1 - return numbits - - -class Subscriber(object): - """ - An abstract class defining the interface expected by a Publisher. - """ - def update(self, data): - """ - A callback method used by a Publisher to notify this Subscriber about - updates. - - :param data: a Python object containing data provided by Publisher. - """ - raise NotImplementedError('cannot invoke virtual method!') - - -class PrettyPrinter(Subscriber): - """ - A concrete Subscriber that employs the pprint in the standard library to - format all data from updates received, writing them to a file-like - object. - - Useful as a debugging aid. - """ - def __init__(self, fh=_sys.stdout, write_eol=True): - """ - Constructor. - - :param fh: a file-like object to write updates to. - Default: sys.stdout. - - - :param write_eol: if ``True`` this object will write newlines to - output, if ``False`` it will not. - """ - self.fh = fh - self.write_eol = write_eol - - def update(self, data): - """ - A callback method used by a Publisher to notify this Subscriber about - updates. - - :param data: a Python object containing data provided by Publisher. - """ - self.fh.write(_pprint.pformat(data)) - if self.write_eol: - self.fh.write("\n") - - -class Publisher(object): - """ - A 'push' Publisher that maintains a list of Subscriber objects notifying - them of state changes by passing them update data when it encounter events - of interest. - """ - def __init__(self): - """Constructor""" - self.subscribers = [] - - def attach(self, subscriber): - """ - Add a new subscriber. - - :param subscriber: a new object that implements the Subscriber object - interface. - """ - if hasattr(subscriber, 'update') and \ - _callable(eval('subscriber.update')): - if subscriber not in self.subscribers: - self.subscribers.append(subscriber) - else: - raise TypeError('%r does not support required interface!' \ - % subscriber) - - def detach(self, subscriber): - """ - Remove an existing subscriber. - - :param subscriber: a new object that implements the Subscriber object - interface. - """ - try: - self.subscribers.remove(subscriber) - except ValueError: - pass - - def notify(self, data): - """ - Send update data to to all registered Subscribers. - - :param data: the data to be passed to each registered Subscriber. - """ - for subscriber in self.subscribers: - subscriber.update(data) - - -class DictDotLookup(object): - """ - Creates objects that behave much like a dictionaries, but allow nested - key access using object '.' (dot) lookups. - - Recipe 576586: Dot-style nested lookups over dictionary based data - structures - http://code.activestate.com/recipes/576586/ - - """ - def __init__(self, d): - for k in d: - if isinstance(d[k], dict): - self.__dict__[k] = DictDotLookup(d[k]) - elif isinstance(d[k], (list, tuple)): - l = [] - for v in d[k]: - if isinstance(v, dict): - l.append(DictDotLookup(v)) - else: - l.append(v) - self.__dict__[k] = l - else: - self.__dict__[k] = d[k] - - def __getitem__(self, name): - if name in self.__dict__: - return self.__dict__[name] - - def __iter__(self): - return _iter_dict_keys(self.__dict__) - - def __repr__(self): - return _pprint.pformat(self.__dict__) - - -def dos2unix(filename): - """ - Replace DOS line endings (CRLF) with UNIX line endings (LF) in file. - - """ - fh = open(filename, "rb") - data = fh.read() - fh.close() - - if '\0' in data: - raise ValueError('file contains binary data: %s!' % filename) - - newdata = data.replace("\r\n".encode(), "\n".encode()) - if newdata != data: - f = open(filename, "wb") - f.write(newdata) - f.close() diff --git a/awx/lib/site-packages/netaddr/eui/__init__.py b/awx/lib/site-packages/netaddr/eui/__init__.py deleted file mode 100644 index 214db4a4b3..0000000000 --- a/awx/lib/site-packages/netaddr/eui/__init__.py +++ /dev/null @@ -1,730 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -Classes and functions for dealing with MAC addresses, EUI-48, EUI-64, OUI, IAB -identifiers. -""" - -from netaddr.core import NotRegisteredError, AddrFormatError, \ - AddrConversionError, Subscriber, Publisher, DictDotLookup -from netaddr.strategy import eui48 as _eui48, eui64 as _eui64 -from netaddr.strategy.eui48 import mac_eui48 -from netaddr.ip import IPAddress - -from netaddr.compat import _is_int, _is_str - - -class BaseIdentifier(object): - """Base class for all IEEE identifiers.""" - __slots__ = ('_value',) - - def __init__(self): - self._value = None - - def __int__(self): - """:return: integer value of this identifier""" - return self._value - - def __long__(self): - """:return: integer value of this identifier""" - return self._value - - def __oct__(self): - """:return: octal string representation of this identifier.""" - # Python 2.x only. - if self._value == 0: - return '0' - return '0%o' % self._value - - def __hex__(self): - """:return: hexadecimal string representation of this identifier.""" - # Python 2.x only. - return '0x%x' % self._value - - def __index__(self): - """ - :return: return the integer value of this identifier when passed to - hex(), oct() or bin(). - """ - # Python 3.x only. - return self._value - - -class OUI(BaseIdentifier): - """ - An individual IEEE OUI (Organisationally Unique Identifier). - - For online details see - http://standards.ieee.org/regauth/oui/ - - """ - __slots__ = ('records',) - - def __init__(self, oui): - """ - Constructor - - :param oui: an OUI string ``XX-XX-XX`` or an unsigned integer. \ - Also accepts and parses full MAC/EUI-48 address strings (but not \ - MAC/EUI-48 integers)! - """ - super(OUI, self).__init__() - - # Lazy loading of IEEE data structures. - from netaddr.eui import ieee - - self.records = [] - - if isinstance(oui, str): - #TODO: Improve string parsing here. - #TODO: Accept full MAC/EUI-48 addressses as well as XX-XX-XX - #TODO: and just take /16 (see IAB for details) - self._value = int(oui.replace('-', ''), 16) - elif _is_int(oui): - if 0 <= oui <= 0xffffff: - self._value = oui - else: - raise ValueError('OUI int outside expected range: %r' % oui) - else: - raise TypeError('unexpected OUI format: %r' % oui) - - # Discover offsets. - if self._value in ieee.OUI_INDEX: - fh = open(ieee.OUI_REGISTRY) - for (offset, size) in ieee.OUI_INDEX[self._value]: - fh.seek(offset) - data = fh.read(size) - self._parse_data(data, offset, size) - fh.close() - else: - raise NotRegisteredError('OUI %r not registered!' % oui) - - def __eq__(self, other): - if not isinstance(other, OUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return self._value == other._value - - def __ne__(self, other): - if not isinstance(other, OUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return self._value != other._value - - def __getstate__(self): - """:returns: Pickled state of an `OUI` object.""" - return self._value, self.records - - def __setstate__(self, state): - """:param state: data used to unpickle a pickled `OUI` object.""" - self._value, self.records = state - - def _parse_data(self, data, offset, size): - """Returns a dict record from raw OUI record data""" - record = { - 'idx': 0, - 'oui': '', - 'org': '', - 'address' : [], - 'offset': offset, - 'size': size, - } - - for line in data.split("\n"): - line = line.strip() - if not line: - continue - - if '(hex)' in line: - record['idx'] = self._value - record['org'] = line.split(None, 2)[2] - record['oui'] = str(self) - elif '(base 16)' in line: - continue - else: - record['address'].append(line) - - self.records.append(record) - - @property - def reg_count(self): - """Number of registered organisations with this OUI""" - return len(self.records) - - def registration(self, index=0): - """ - The IEEE registration details for this OUI. - - :param index: the index of record (may contain multiple registrations) - (Default: 0 - first registration) - - :return: Objectified Python data structure containing registration - details. - """ - return DictDotLookup(self.records[index]) - - def __str__(self): - """:return: string representation of this OUI""" - int_val = self._value - return "%02X-%02X-%02X" % ( - (int_val >> 16) & 0xff, - (int_val >> 8) & 0xff, - int_val & 0xff) - - def __repr__(self): - """:return: executable Python string to recreate equivalent object.""" - return "OUI('%s')" % self - - -class IAB(BaseIdentifier): - """ - An individual IEEE IAB (Individual Address Block) identifier. - - For online details see - http://standards.ieee.org/regauth/oui/ - - """ - __slots__ = ('record',) - - @staticmethod - def split_iab_mac(eui_int, strict=False): - """ - :param eui_int: a MAC IAB as an unsigned integer. - - :param strict: If True, raises a ValueError if the last 12 bits of - IAB MAC/EUI-48 address are non-zero, ignores them otherwise. - (Default: False) - """ - if 0x50c2000 <= eui_int <= 0x50c2fff: - return eui_int, 0 - - user_mask = 2 ** 12 - 1 - iab_mask = (2 ** 48 - 1) ^ user_mask - iab_bits = eui_int >> 12 - user_bits = (eui_int | iab_mask) - iab_mask - - if 0x50c2000 <= iab_bits <= 0x50c2fff: - if strict and user_bits != 0: - raise ValueError('%r is not a strict IAB!' % hex(user_bits)) - else: - raise ValueError('%r is not an IAB address!' % hex(eui_int)) - - return iab_bits, user_bits - - def __init__(self, iab, strict=False): - """ - Constructor - - :param iab: an IAB string ``00-50-C2-XX-X0-00`` or an unsigned \ - integer. This address looks like an EUI-48 but it should not \ - have any non-zero bits in the last 3 bytes. - - :param strict: If True, raises a ValueError if the last 12 bits \ - of IAB MAC/EUI-48 address are non-zero, ignores them otherwise. \ - (Default: False) - """ - super(IAB, self).__init__() - - # Lazy loading of IEEE data structures. - from netaddr.eui import ieee - - self.record = { - 'idx': 0, - 'iab': '', - 'org': '', - 'address' : [], - 'offset': 0, - 'size': 0, - } - - if isinstance(iab, str): - #TODO: Improve string parsing here. - #TODO: '00-50-C2' is actually invalid. - #TODO: Should be '00-50-C2-00-00-00' (i.e. a full MAC/EUI-48) - int_val = int(iab.replace('-', ''), 16) - iab_int, user_int = self.split_iab_mac(int_val, - strict=strict) - self._value = iab_int - elif _is_int(iab): - iab_int, user_int = self.split_iab_mac(iab, strict=strict) - self._value = iab_int - else: - raise TypeError('unexpected IAB format: %r!' % iab) - - # Discover offsets. - if self._value in ieee.IAB_INDEX: - fh = open(ieee.IAB_REGISTRY) - (offset, size) = ieee.IAB_INDEX[self._value][0] - self.record['offset'] = offset - self.record['size'] = size - fh.seek(offset) - data = fh.read(size) - self._parse_data(data, offset, size) - fh.close() - else: - raise NotRegisteredError('IAB %r not unregistered!' % iab) - - def __eq__(self, other): - if not isinstance(other, IAB): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return self._value == other._value - - def __ne__(self, other): - if not isinstance(other, IAB): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return self._value != other._value - - def __getstate__(self): - """:returns: Pickled state of an `IAB` object.""" - return self._value, self.record - - def __setstate__(self, state): - """:param state: data used to unpickle a pickled `IAB` object.""" - self._value, self.record = state - - def _parse_data(self, data, offset, size): - """Returns a dict record from raw IAB record data""" - for line in data.split("\n"): - line = line.strip() - if not line: - continue - - if '(hex)' in line: - self.record['idx'] = self._value - self.record['org'] = line.split(None, 2)[2] - self.record['iab'] = str(self) - elif '(base 16)' in line: - continue - else: - self.record['address'].append(line) - - def registration(self): - """The IEEE registration details for this IAB""" - return DictDotLookup(self.record) - - def __str__(self): - """:return: string representation of this IAB""" - int_val = self._value << 4 - - return "%02X-%02X-%02X-%02X-%02X-00" % ( - (int_val >> 32) & 0xff, - (int_val >> 24) & 0xff, - (int_val >> 16) & 0xff, - (int_val >> 8) & 0xff, - int_val & 0xff) - - def __repr__(self): - """:return: executable Python string to recreate equivalent object.""" - return "IAB('%s')" % self - - -class EUI(BaseIdentifier): - """ - An IEEE EUI (Extended Unique Identifier). - - Both EUI-48 (used for layer 2 MAC addresses) and EUI-64 are supported. - - Input parsing for EUI-48 addresses is flexible, supporting many MAC - variants. - - """ - __slots__ = ('_module', '_dialect') - - def __init__(self, addr, version=None, dialect=None): - """ - Constructor. - - :param addr: an EUI-48 (MAC) or EUI-64 address in string format or \ - an unsigned integer. May also be another EUI object (copy \ - construction). - - :param version: (optional) the explicit EUI address version, either \ - 48 or 64. Mainly used to distinguish EUI-48 and EUI-64 identifiers \ - specified as integers which may be numerically equivalent. - - :param dialect: (optional) the mac_* dialect to be used to configure \ - the formatting of EUI-48 (MAC) addresses. - """ - super(EUI, self).__init__() - - self._module = None - - if isinstance(addr, EUI): - # Copy constructor. - if version is not None and version != addr._module.version: - raise ValueError('cannot switch EUI versions using ' - 'copy constructor!') - self._module = addr._module - self._value = addr._value - self.dialect = addr.dialect - return - - if version is not None: - if version == 48: - self._module = _eui48 - elif version == 64: - self._module = _eui64 - else: - raise ValueError('unsupported EUI version %r' % version) - else: - # Choose a default version when addr is an integer and version is - # not specified. - if _is_int(addr): - if 0 <= addr <= 0xffffffffffff: - self._module = _eui48 - elif 0xffffffffffff < addr <= 0xffffffffffffffff: - self._module = _eui64 - - self.value = addr - - # Choose a dialect for MAC formatting. - self.dialect = dialect - - def __getstate__(self): - """:returns: Pickled state of an `EUI` object.""" - return self._value, self._module.version, self.dialect - - def __setstate__(self, state): - """ - :param state: data used to unpickle a pickled `EUI` object. - - """ - value, version, dialect = state - - self._value = value - - if version == 48: - self._module = _eui48 - elif version == 64: - self._module = _eui64 - else: - raise ValueError('unpickling failed for object state: %s' \ - % str(state)) - - self.dialect = dialect - - def _get_value(self): - return self._value - - def _set_value(self, value): - if self._module is None: - # EUI version is implicit, detect it from value. - for module in (_eui48, _eui64): - try: - self._value = module.str_to_int(value) - self._module = module - break - except AddrFormatError: - try: - if 0 <= int(value) <= module.max_int: - self._value = int(value) - self._module = module - break - except ValueError: - pass - - if self._module is None: - raise AddrFormatError('failed to detect EUI version: %r' - % value) - else: - # EUI version is explicit. - if _is_str(value): - try: - self._value = self._module.str_to_int(value) - except AddrFormatError: - raise AddrFormatError('address %r is not an EUIv%d' - % (value, self._module.version)) - else: - if 0 <= int(value) <= self._module.max_int: - self._value = int(value) - else: - raise AddrFormatError('bad address format: %r' % value) - - value = property(_get_value, _set_value, None, - 'a positive integer representing the value of this EUI indentifier.') - - def _get_dialect(self): - return self._dialect - - def _set_dialect(self, value): - if value is None: - self._dialect = mac_eui48 - else: - if hasattr(value, 'word_size') and hasattr(value, 'word_fmt'): - self._dialect = value - else: - raise TypeError('custom dialects should subclass mac_eui48!') - - dialect = property(_get_dialect, _set_dialect, None, - "a Python class providing support for the interpretation of " - "various MAC\n address formats.") - - @property - def oui(self): - """The OUI (Organisationally Unique Identifier) for this EUI.""" - if self._module == _eui48: - return OUI(self.value >> 24) - elif self._module == _eui64: - return OUI(self.value >> 40) - - @property - def ei(self): - """The EI (Extension Identifier) for this EUI""" - if self._module == _eui48: - return '%02X-%02X-%02X' % tuple(self[3:6]) - elif self._module == _eui64: - return '%02X-%02X-%02X-%02X-%02X' % tuple(self[3:8]) - - def is_iab(self): - """:return: True if this EUI is an IAB address, False otherwise""" - return 0x50c2000 <= (self._value >> 12) <= 0x50c2fff - - @property - def iab(self): - """ - If is_iab() is True, the IAB (Individual Address Block) is returned, - ``None`` otherwise. - """ - if self.is_iab(): - return IAB(self._value >> 12) - - @property - def version(self): - """The EUI version represented by this EUI object.""" - return self._module.version - - def __getitem__(self, idx): - """ - :return: The integer value of the word referenced by index (both \ - positive and negative). Raises ``IndexError`` if index is out \ - of bounds. Also supports Python list slices for accessing \ - word groups. - """ - if _is_int(idx): - # Indexing, including negative indexing goodness. - num_words = self._dialect.num_words - if not (-num_words) <= idx <= (num_words - 1): - raise IndexError('index out range for address type!') - return self._module.int_to_words(self._value, self._dialect)[idx] - elif isinstance(idx, slice): - words = self._module.int_to_words(self._value, self._dialect) - return [words[i] for i in range(*idx.indices(len(words)))] - else: - raise TypeError('unsupported type %r!' % idx) - - def __setitem__(self, idx, value): - """Set the value of the word referenced by index in this address""" - if isinstance(idx, slice): - # TODO - settable slices. - raise NotImplementedError('settable slices are not supported!') - - if not _is_int(idx): - raise TypeError('index not an integer!') - - if not 0 <= idx <= (self._dialect.num_words - 1): - raise IndexError('index %d outside address type boundary!' % idx) - - if not _is_int(value): - raise TypeError('value not an integer!') - - if not 0 <= value <= self._dialect.max_word: - raise IndexError('value %d outside word size maximum of %d bits!' - % (value, self._dialect.word_size)) - - words = list(self._module.int_to_words(self._value, self._dialect)) - words[idx] = value - self._value = self._module.words_to_int(words) - - def __hash__(self): - """:return: hash of this EUI object suitable for dict keys, sets etc""" - return hash((self.version, self._value)) - - def __eq__(self, other): - """ - :return: ``True`` if this EUI object is numerically the same as other, \ - ``False`` otherwise. - """ - if not isinstance(other, EUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return (self.version, self._value) == (other.version, other._value) - - def __ne__(self, other): - """ - :return: ``True`` if this EUI object is numerically the same as other, \ - ``False`` otherwise. - """ - if not isinstance(other, EUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return (self.version, self._value) != (other.version, other._value) - - def __lt__(self, other): - """ - :return: ``True`` if this EUI object is numerically lower in value than \ - other, ``False`` otherwise. - """ - if not isinstance(other, EUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return (self.version, self._value) < (other.version, other._value) - - def __le__(self, other): - """ - :return: ``True`` if this EUI object is numerically lower or equal in \ - value to other, ``False`` otherwise. - """ - if not isinstance(other, EUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return (self.version, self._value) <= (other.version, other._value) - - def __gt__(self, other): - """ - :return: ``True`` if this EUI object is numerically greater in value \ - than other, ``False`` otherwise. - """ - if not isinstance(other, EUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return (self.version, self._value) > (other.version, other._value) - - def __ge__(self, other): - """ - :return: ``True`` if this EUI object is numerically greater or equal \ - in value to other, ``False`` otherwise. - """ - if not isinstance(other, EUI): - try: - other = self.__class__(other) - except Exception: - return NotImplemented - return (self.version, self._value) >= (other.version, other._value) - - def bits(self, word_sep=None): - """ - :param word_sep: (optional) the separator to insert between words. \ - Default: None - use default separator for address type. - - :return: human-readable binary digit string of this address. - """ - return self._module.int_to_bits(self._value, word_sep) - - @property - def packed(self): - """The value of this EUI address as a packed binary string.""" - return self._module.int_to_packed(self._value) - - @property - def words(self): - """A list of unsigned integer octets found in this EUI address.""" - return self._module.int_to_words(self._value) - - @property - def bin(self): - """ - The value of this EUI adddress in standard Python binary - representational form (0bxxx). A back port of the format provided by - the builtin bin() function found in Python 2.6.x and higher. - """ - return self._module.int_to_bin(self._value) - - def eui64(self): - """ - - If this object represents an EUI-48 it is converted to EUI-64 \ - as per the standard. - - If this object is already an EUI-64, a new, numerically \ - equivalent object is returned instead. - - :return: The value of this EUI object as a new 64-bit EUI object. - """ - if self.version == 48: - # Convert 11:22:33:44:55:66 into 11:22:33:FF:FE:44:55:66. - first_three = self._value >> 24 - last_three = self._value & 0xffffff - new_value = (first_three << 40) | 0xfffe000000 | last_three - else: - # is already a EUI64 - new_value = self._value - return self.__class__(new_value, version=64) - - def modified_eui64(self): - """ - - create a new EUI object with a modified EUI-64 as described in RFC 4291 section 2.5.1 - - :return: a new and modified 64-bit EUI object. - """ - # Modified EUI-64 format interface identifiers are formed by inverting - # the "u" bit (universal/local bit in IEEE EUI-64 terminology) when - # forming the interface identifier from IEEE EUI-64 identifiers. In - # the resulting Modified EUI-64 format, the "u" bit is set to one (1) - # to indicate universal scope, and it is set to zero (0) to indicate - # local scope. - eui64 = self.eui64() - eui64._value ^= 0x00000000000000000200000000000000 - return eui64 - - def ipv6(self, prefix): - """ - .. note:: This poses security risks in certain scenarios. \ - Please read RFC 4941 for details. Reference: RFCs 4291 and 4941. - - :param prefix: ipv6 prefix - - :return: new IPv6 `IPAddress` object based on this `EUI` \ - using the technique described in RFC 4291. - """ - int_val = int(prefix) + int(self.modified_eui64()) - return IPAddress(int_val, version=6) - - def ipv6_link_local(self): - """ - .. note:: This poses security risks in certain scenarios. \ - Please read RFC 4941 for details. Reference: RFCs 4291 and 4941. - - :return: new link local IPv6 `IPAddress` object based on this `EUI` \ - using the technique described in RFC 4291. - """ - return self.ipv6(0xfe800000000000000000000000000000) - - @property - def info(self): - """ - A record dict containing IEEE registration details for this EUI - (MAC-48) if available, None otherwise. - """ - data = {'OUI': self.oui.registration()} - if self.is_iab(): - data['IAB'] = self.iab.registration() - - return DictDotLookup(data) - - def __str__(self): - """:return: EUI in representational format""" - return self._module.int_to_str(self._value, self._dialect) - - def __repr__(self): - """:return: executable Python string to recreate equivalent object.""" - return "EUI('%s')" % self - diff --git a/awx/lib/site-packages/netaddr/eui/iab.idx b/awx/lib/site-packages/netaddr/eui/iab.idx deleted file mode 100644 index 5316b6dca2..0000000000 --- a/awx/lib/site-packages/netaddr/eui/iab.idx +++ /dev/null @@ -1,4575 +0,0 @@ -84680704,123,139 -84680705,262,146 -84680706,408,178 -84680707,586,145 -84680708,731,147 -84680709,878,150 -84680710,1028,201 -84680711,1229,172 -84680712,1401,184 -84680713,1585,157 -84680714,1742,147 -84680715,1889,168 -84680716,2057,176 -84680717,2233,144 -84680718,2377,118 -84680719,2495,110 -84680720,2605,140 -84680721,2745,145 -84680722,2890,173 -84680723,3063,160 -84680724,3223,127 -84680725,3350,175 -84680726,3525,198 -84680727,3723,191 -84680728,3914,117 -84680729,4031,211 -84680730,4242,180 -84680731,4422,170 -84680732,4592,116 -84680733,4708,169 -84680734,4877,192 -84680735,5069,159 -84680736,5228,166 -84680737,5394,165 -84680738,5559,153 -84680739,5712,154 -84680740,5866,120 -84680741,5986,169 -84680742,6155,167 -84680743,6322,158 -84680744,6480,187 -84680745,6667,157 -84680746,6824,140 -84680747,6964,158 -84680748,7122,181 -84680749,7303,139 -84680750,7442,158 -84680751,7600,151 -84680752,7751,201 -84680753,7952,183 -84680754,8135,126 -84680755,8261,157 -84680756,8418,166 -84680757,8584,189 -84680758,8773,163 -84680759,8936,156 -84680760,9092,157 -84680761,9249,167 -84680762,9416,156 -84680763,9572,150 -84680764,9722,196 -84680765,9918,155 -84680766,10073,155 -84680767,10228,125 -84680768,10353,196 -84680769,10549,177 -84680770,10726,202 -84680771,10928,159 -84680772,11087,56 -84680773,11143,169 -84680774,11312,56 -84680775,11368,137 -84680776,11505,141 -84680777,11646,148 -84680778,11794,173 -84680779,11967,167 -84680780,12134,158 -84680782,12292,189 -84680783,12481,146 -84680784,12627,139 -84680785,12766,141 -84680786,12907,167 -84680788,13074,181 -84680789,13255,181 -84680790,13436,127 -84680791,13563,119 -84680792,13682,149 -84680793,13831,197 -84680794,14028,157 -84680795,14185,145 -84680796,14330,174 -84680797,14504,158 -84680798,14662,139 -84680799,14801,156 -84680800,14957,56 -84680801,15013,175 -84680802,15188,56 -84680803,15244,157 -84680804,15401,56 -84680805,15457,145 -84680806,15602,56 -84680807,15658,182 -84680808,15840,135 -84680809,15975,158 -84680810,16133,122 -84680811,16255,165 -84680812,16420,163 -84680813,16583,149 -84680814,16732,177 -84680815,16909,152 -84680816,17061,165 -84680817,17226,163 -84680818,17389,192 -84680819,17581,191 -84680820,17772,187 -84680821,17959,131 -84680822,18090,181 -84680823,18271,152 -84680824,18423,127 -84680825,18550,131 -84680826,18681,117 -84680827,18798,165 -84680828,18963,156 -84680829,19119,148 -84680830,19267,117 -84680831,19384,147 -84680832,19531,119 -84680833,19650,168 -84680834,19818,134 -84680835,19952,117 -84680836,20069,167 -84680837,20236,161 -84680838,20397,164 -84680839,20561,174 -84680840,20735,150 -84680841,20885,153 -84680842,21038,162 -84680843,21200,147 -84680844,21347,129 -84680845,21476,207 -84680846,21683,128 -84680847,21811,193 -84680848,22004,174 -84680849,22178,158 -84680850,22336,227 -84680851,22563,163 -84680852,22726,188 -84680853,22914,127 -84680854,23041,167 -84680855,23208,138 -84680856,23346,160 -84680857,23506,213 -84680858,23719,204 -84680859,23923,134 -84680860,24057,155 -84680861,24212,117 -84680862,24329,158 -84680863,24487,178 -84680864,24665,116 -84680865,24781,157 -84680866,24938,190 -84680867,25128,127 -84680868,25255,153 -84680869,25408,148 -84680870,25556,167 -84680871,25723,160 -84680872,25883,139 -84680873,26022,184 -84680874,26206,156 -84680875,26362,160 -84680876,26522,133 -84680877,26655,146 -84680878,26801,151 -84680879,26952,174 -84680880,27126,168 -84680881,27294,162 -84680882,27456,148 -84680883,27604,143 -84680884,27747,163 -84680885,27910,159 -84680886,28069,196 -84680887,28265,122 -84680888,28387,144 -84680889,28531,143 -84680890,28674,143 -84680891,28817,124 -84680892,28941,143 -84680893,29084,130 -84680894,29214,202 -84680895,29416,56 -84680896,29472,144 -84680897,29616,119 -84680898,29735,187 -84680899,29922,128 -84680900,30050,219 -84680901,30269,153 -84680902,30422,208 -84680903,30630,180 -84680904,30810,151 -84680905,30961,154 -84680906,31115,148 -84680907,31263,142 -84680908,31405,184 -84680909,31589,113 -84680910,31702,158 -84680911,31860,121 -84680912,31981,130 -84680913,32111,180 -84680914,32291,177 -84680915,32468,166 -84680916,32634,157 -84680917,32791,132 -84680918,32923,140 -84680919,33063,160 -84680920,33223,178 -84680921,33401,134 -84680922,33535,157 -84680923,33692,135 -84680924,33827,133 -84680925,33960,177 -84680926,34137,154 -84680927,34291,160 -84680928,34451,129 -84680929,34580,154 -84680930,34734,173 -84680931,34907,122 -84680932,35029,182 -84680933,35211,148 -84680934,35359,155 -84680935,35514,161 -84680936,35675,179 -84680937,35854,160 -84680938,36014,154 -84680939,36168,154 -84680940,36322,144 -84680941,36466,156 -84680942,36622,173 -84680943,36795,162 -84680944,36957,179 -84680945,37136,174 -84680946,37310,144 -84680947,37454,200 -84680948,37654,146 -84680949,37800,231 -84680950,38031,167 -84680951,38198,166 -84680952,38364,149 -84680953,38513,161 -84680954,38674,167 -84680955,38841,180 -84680956,39021,175 -84680957,39196,151 -84680958,39347,123 -84680959,39470,165 -84680960,39635,160 -84680961,39795,150 -84680962,39945,207 -84680963,40152,168 -84680964,40320,136 -84680965,40456,131 -84680966,40587,128 -84680967,40715,138 -84680968,40853,143 -84680969,40996,141 -84680970,41137,124 -84680971,41261,132 -84680972,41393,160 -84680973,41553,127 -84680974,41680,122 -84680975,41802,144 -84680976,41946,151 -84680977,42097,183 -84680978,42280,123 -84680979,42403,149 -84680980,42552,160 -84680981,42712,134 -84680982,42846,193 -84680983,43039,123 -84680984,43162,127 -84680985,43289,207 -84680986,43496,152 -84680987,43648,139 -84680988,43787,149 -84680989,43936,170 -84680990,44106,150 -84680991,44256,158 -84680992,44414,148 -84680993,44562,145 -84680994,44707,137 -84680995,44844,176 -84680996,45020,160 -84680997,45180,132 -84680998,45312,177 -84680999,45489,172 -84681000,45661,135 -84681001,45796,174 -84681002,45970,151 -84681003,46121,221 -84681004,46342,168 -84681005,46510,171 -84681006,46681,116 -84681007,46797,139 -84681008,46936,163 -84681009,47099,160 -84681010,47259,150 -84681011,47409,145 -84681012,47554,134 -84681013,47688,120 -84681014,47808,145 -84681015,47953,218 -84681016,48171,153 -84681017,48324,149 -84681018,48473,141 -84681019,48614,134 -84681020,48748,167 -84681021,48915,190 -84681022,49105,178 -84681023,49283,154 -84681024,49437,144 -84681025,49581,162 -84681026,49743,129 -84681027,49872,124 -84681028,49996,153 -84681029,50149,135 -84681030,50284,147 -84681031,50431,177 -84681032,50608,120 -84681033,50728,139 -84681034,50867,139 -84681035,51006,136 -84681036,51142,119 -84681037,51261,209 -84681038,51470,144 -84681039,51614,152 -84681040,51766,115 -84681041,51881,140 -84681042,52021,175 -84681043,52196,173 -84681044,52369,112 -84681045,52481,134 -84681046,52615,189 -84681047,52804,134 -84681048,52938,172 -84681049,53110,150 -84681050,53260,156 -84681051,53416,148 -84681052,53564,148 -84681053,53712,128 -84681054,53840,176 -84681055,54016,132 -84681056,54148,197 -84681057,54345,162 -84681058,54507,170 -84681059,54677,149 -84681060,54826,125 -84681061,54951,161 -84681062,55112,126 -84681063,55238,155 -84681064,55393,170 -84681065,55563,137 -84681066,55700,139 -84681067,55839,147 -84681068,55986,248 -84681069,56234,150 -84681070,56384,106 -84681071,56490,150 -84681072,56640,165 -84681073,56805,141 -84681074,56946,144 -84681075,57090,127 -84681076,57217,193 -84681077,57410,125 -84681078,57535,127 -84681079,57662,167 -84681080,57829,156 -84681081,57985,136 -84681082,58121,165 -84681083,58286,163 -84681084,58449,156 -84681085,58605,153 -84681086,58758,176 -84681087,58934,146 -84681088,59080,155 -84681089,59235,132 -84681090,59367,133 -84681091,59500,181 -84681092,59681,188 -84681093,59869,171 -84681094,60040,157 -84681095,60197,175 -84681096,60372,143 -84681097,60515,115 -84681098,60630,167 -84681099,60797,140 -84681100,60937,149 -84681101,61086,179 -84681102,61265,166 -84681103,61431,151 -84681104,61582,144 -84681105,61726,157 -84681106,61883,161 -84681107,62044,158 -84681108,62202,115 -84681109,62317,180 -84681110,62497,121 -84681111,62618,193 -84681112,62811,156 -84681113,62967,177 -84681114,63144,164 -84681115,63308,162 -84681116,63470,124 -84681117,63594,144 -84681118,63738,153 -84681119,63891,176 -84681120,64067,160 -84681121,64227,146 -84681122,64373,146 -84681123,64519,158 -84681124,64677,206 -84681125,64883,146 -84681126,65029,131 -84681127,65160,173 -84681128,65333,144 -84681129,65477,160 -84681130,65637,172 -84681131,65809,147 -84681132,65956,155 -84681133,66111,119 -84681134,66230,152 -84681135,66382,167 -84681136,66549,176 -84681137,66725,141 -84681138,66866,170 -84681139,67036,176 -84681140,67212,142 -84681141,67354,150 -84681142,67504,127 -84681143,67631,132 -84681144,67763,181 -84681145,67944,174 -84681146,68118,134 -84681147,68252,143 -84681148,68395,150 -84681149,68545,175 -84681150,68720,157 -84681151,68877,224 -84681152,69101,154 -84681153,69255,170 -84681154,69425,163 -84681155,69588,207 -84681156,69795,159 -84681157,69954,132 -84681158,70086,142 -84681159,70228,158 -84681160,70386,209 -84681161,70595,117 -84681162,70712,149 -84681163,70861,176 -84681164,71037,129 -84681165,71166,170 -84681166,71336,176 -84681167,71512,171 -84681168,71683,162 -84681169,71845,152 -84681170,71997,179 -84681171,72176,152 -84681172,72328,178 -84681173,72506,162 -84681174,72668,209 -84681175,72877,165 -84681176,73042,181 -84681177,73223,107 -84681178,73330,134 -84681179,73464,188 -84681180,73652,215 -84681181,73867,175 -84681182,74042,133 -84681183,74175,173 -84681184,74348,142 -84681185,74490,163 -84681186,74653,190 -84681187,74843,170 -84681188,75013,153 -84681189,75166,167 -84681190,75333,167 -84681191,75500,140 -84681192,75640,162 -84681193,75802,148 -84681194,75950,124 -84681195,76074,138 -84681196,76212,143 -84681197,76355,149 -84681198,76504,228 -84681199,76732,161 -84681200,76893,166 -84681201,77059,153 -84681202,77212,141 -84681203,77353,163 -84681204,77516,158 -84681205,77674,190 -84681206,77864,164 -84681207,78028,186 -84681208,78214,181 -84681209,78395,124 -84681210,78519,148 -84681211,78667,153 -84681212,78820,138 -84681213,78958,139 -84681214,79097,193 -84681215,79290,233 -84681216,79523,189 -84681217,79712,125 -84681218,79837,138 -84681219,79975,187 -84681220,80162,161 -84681221,80323,125 -84681222,80448,149 -84681223,80597,251 -84681224,80848,149 -84681225,80997,158 -84681226,81155,146 -84681227,81301,134 -84681228,81435,234 -84681229,81669,178 -84681230,81847,167 -84681231,82014,145 -84681232,82159,173 -84681233,82332,230 -84681234,82562,185 -84681235,82747,134 -84681236,82881,162 -84681237,83043,131 -84681238,83174,153 -84681239,83327,162 -84681240,83489,204 -84681241,83693,139 -84681242,83832,182 -84681243,84014,200 -84681244,84214,169 -84681245,84383,182 -84681246,84565,181 -84681247,84746,175 -84681248,84921,158 -84681249,85079,151 -84681250,85230,138 -84681251,85368,158 -84681252,85526,142 -84681253,85668,179 -84681254,85847,135 -84681255,85982,165 -84681256,86147,190 -84681257,86337,158 -84681258,86495,140 -84681259,86635,192 -84681260,86827,156 -84681261,86983,123 -84681262,87106,151 -84681263,87257,147 -84681264,87404,188 -84681265,87592,158 -84681266,87750,117 -84681267,87867,186 -84681268,88053,158 -84681269,88211,192 -84681270,88403,148 -84681271,88551,170 -84681272,88721,153 -84681273,88874,148 -84681274,89022,163 -84681275,89185,135 -84681276,89320,158 -84681277,89478,159 -84681278,89637,143 -84681279,89780,147 -84681280,89927,153 -84681281,90080,167 -84681282,90247,131 -84681283,90378,140 -84681284,90518,127 -84681285,90645,175 -84681286,90820,98 -84681287,90918,163 -84681288,91081,190 -84681289,91271,152 -84681290,91423,152 -84681291,91575,146 -84681292,91721,143 -84681293,91864,147 -84681294,92011,196 -84681295,92207,132 -84681296,92339,153 -84681297,92492,147 -84681298,92639,144 -84681299,92783,157 -84681300,92940,167 -84681301,93107,210 -84681302,93317,169 -84681303,93486,144 -84681304,93630,172 -84681305,93802,143 -84681306,93945,157 -84681307,94102,151 -84681308,94253,173 -84681309,94426,125 -84681310,94551,170 -84681311,94721,191 -84681312,94912,139 -84681313,95051,141 -84681314,95192,207 -84681315,95399,162 -84681316,95561,155 -84681317,95716,141 -84681318,95857,144 -84681319,96001,186 -84681320,96187,146 -84681321,96333,158 -84681322,96491,137 -84681323,96628,193 -84681324,96821,193 -84681325,97014,179 -84681326,97193,136 -84681327,97329,166 -84681328,97495,170 -84681329,97665,164 -84681330,97829,148 -84681331,97977,222 -84681332,98199,220 -84681333,98419,181 -84681334,98600,161 -84681335,98761,147 -84681336,98908,126 -84681337,99034,149 -84681338,99183,136 -84681339,99319,129 -84681340,99448,140 -84681341,99588,143 -84681342,99731,149 -84681343,99880,190 -84681344,100070,141 -84681345,100211,133 -84681346,100344,112 -84681347,100456,172 -84681348,100628,123 -84681349,100751,157 -84681350,100908,130 -84681351,101038,220 -84681352,101258,179 -84681353,101437,135 -84681354,101572,150 -84681355,101722,195 -84681356,101917,160 -84681357,102077,114 -84681358,102191,141 -84681359,102332,188 -84681360,102520,127 -84681361,102647,136 -84681362,102783,137 -84681363,102920,128 -84681364,103048,135 -84681365,103183,171 -84681366,103354,124 -84681367,103478,121 -84681368,103599,142 -84681369,103741,125 -84681370,103866,163 -84681371,104029,153 -84681372,104182,157 -84681373,104339,163 -84681374,104502,196 -84681375,104698,158 -84681376,104856,179 -84681377,105035,143 -84681378,105178,119 -84681379,105297,170 -84681380,105467,162 -84681381,105629,167 -84681382,105796,167 -84681383,105963,179 -84681384,106142,129 -84681385,106271,179 -84681386,106450,132 -84681387,106582,196 -84681388,106778,157 -84681389,106935,149 -84681390,107084,183 -84681391,107267,185 -84681392,107452,183 -84681393,107635,56 -84681394,107691,144 -84681395,107835,153 -84681396,107988,163 -84681397,108151,183 -84681398,108334,121 -84681399,108455,155 -84681400,108610,174 -84681401,108784,161 -84681402,108945,178 -84681403,109123,154 -84681404,109277,149 -84681405,109426,158 -84681406,109584,174 -84681407,109758,140 -84681408,109898,163 -84681409,110061,227 -84681410,110288,163 -84681411,110451,148 -84681412,110599,183 -84681413,110782,132 -84681414,110914,191 -84681415,111105,152 -84681416,111257,112 -84681417,111369,147 -84681418,111516,182 -84681419,111698,163 -84681420,111861,151 -84681421,112012,164 -84681422,112176,136 -84681423,112312,205 -84681424,112517,144 -84681425,112661,168 -84681426,112829,158 -84681427,112987,178 -84681428,113165,224 -84681429,113389,117 -84681430,113506,148 -84681431,113654,164 -84681432,113818,148 -84681433,113966,56 -84681434,114022,151 -84681435,114173,188 -84681436,114361,152 -84681437,114513,183 -84681438,114696,149 -84681439,114845,141 -84681440,114986,157 -84681441,115143,141 -84681442,115284,173 -84681443,115457,155 -84681444,115612,115 -84681445,115727,167 -84681446,115894,120 -84681447,116014,157 -84681448,116171,164 -84681449,116335,151 -84681450,116486,131 -84681451,116617,139 -84681452,116756,220 -84681453,116976,165 -84681454,117141,185 -84681455,117326,146 -84681456,117472,151 -84681457,117623,144 -84681458,117767,142 -84681459,117909,160 -84681460,118069,185 -84681461,118254,168 -84681462,118422,170 -84681463,118592,129 -84681464,118721,147 -84681465,118868,129 -84681466,118997,165 -84681467,119162,213 -84681468,119375,165 -84681469,119540,167 -84681470,119707,131 -84681471,119838,150 -84681472,119988,146 -84681473,120134,171 -84681474,120305,192 -84681475,120497,168 -84681476,120665,143 -84681477,120808,155 -84681478,120963,178 -84681479,121141,177 -84681480,121318,118 -84681481,121436,173 -84681482,121609,152 -84681483,121761,155 -84681484,121916,129 -84681485,122045,122 -84681486,122167,142 -84681487,122309,173 -84681488,122482,177 -84681489,122659,134 -84681490,122793,181 -84681491,122974,153 -84681492,123127,157 -84681493,123284,146 -84681494,123430,126 -84681495,123556,166 -84681496,123722,164 -84681497,123886,175 -84681498,124061,166 -84681499,124227,114 -84681500,124341,143 -84681501,124484,215 -84681502,124699,142 -84681503,124841,158 -84681504,124999,145 -84681505,125144,169 -84681506,125313,190 -84681507,125503,139 -84681508,125642,128 -84681509,125770,189 -84681510,125959,140 -84681511,126099,145 -84681512,126244,197 -84681513,126441,124 -84681514,126565,167 -84681515,126732,173 -84681516,126905,245 -84681517,127150,150 -84681518,127300,180 -84681519,127480,134 -84681520,127614,137 -84681521,127751,161 -84681522,127912,172 -84681523,128084,155 -84681524,128239,155 -84681525,128394,144 -84681526,128538,184 -84681527,128722,135 -84681528,128857,116 -84681529,128973,149 -84681530,129122,181 -84681531,129303,150 -84681532,129453,125 -84681533,129578,200 -84681534,129778,162 -84681535,129940,118 -84681536,130058,122 -84681537,130180,150 -84681538,130330,164 -84681539,130494,228 -84681540,130722,147 -84681541,130869,128 -84681542,130997,151 -84681543,131148,130 -84681544,131278,148 -84681545,131426,146 -84681546,131572,173 -84681547,131745,172 -84681548,131917,181 -84681549,132098,184 -84681550,132282,226 -84681551,132508,187 -84681552,132695,185 -84681553,132880,170 -84681554,133050,117 -84681555,133167,169 -84681556,133336,175 -84681557,133511,115 -84681558,133626,152 -84681559,133778,152 -84681560,133930,156 -84681561,134086,148 -84681562,134234,200 -84681563,134434,164 -84681564,134598,123 -84681565,134721,127 -84681566,134848,133 -84681567,134981,136 -84681568,135117,187 -84681569,135304,107 -84681570,135411,141 -84681571,135552,145 -84681572,135697,146 -84681573,135843,103 -84681574,135946,169 -84681575,136115,192 -84681576,136307,135 -84681577,136442,139 -84681578,136581,140 -84681579,136721,145 -84681580,136866,123 -84681581,136989,164 -84681582,137153,155 -84681583,137308,122 -84681584,137430,180 -84681585,137610,150 -84681586,137760,149 -84681587,137909,156 -84681588,138065,181 -84681589,138246,154 -84681590,138400,118 -84681591,138518,127 -84681592,138645,168 -84681593,138813,154 -84681594,138967,144 -84681595,139111,153 -84681596,139264,162 -84681597,139426,150 -84681598,139576,141 -84681599,139717,190 -84681600,139907,139 -84681601,140046,160 -84681602,140206,145 -84681603,140351,146 -84681604,140497,175 -84681605,140672,211 -84681606,140883,172 -84681607,141055,157 -84681608,141212,131 -84681609,141343,142 -84681610,141485,160 -84681611,141645,125 -84681612,141770,131 -84681613,141901,167 -84681614,142068,129 -84681615,142197,118 -84681616,142315,147 -84681617,142462,153 -84681618,142615,166 -84681619,142781,158 -84681620,142939,120 -84681621,143059,141 -84681622,143200,144 -84681623,143344,127 -84681624,143471,173 -84681625,143644,165 -84681626,143809,161 -84681627,143970,156 -84681628,144126,147 -84681629,144273,163 -84681630,144436,200 -84681631,144636,131 -84681632,144767,178 -84681633,144945,114 -84681634,145059,140 -84681635,145199,221 -84681636,145420,198 -84681637,145618,155 -84681638,145773,171 -84681639,145944,186 -84681640,146130,126 -84681641,146256,154 -84681642,146410,186 -84681643,146596,160 -84681644,146756,142 -84681645,146898,246 -84681646,147144,186 -84681647,147330,128 -84681648,147458,196 -84681649,147654,189 -84681650,147843,202 -84681651,148045,142 -84681652,148187,166 -84681653,148353,159 -84681654,148512,154 -84681655,148666,170 -84681656,148836,142 -84681657,148978,167 -84681658,149145,166 -84681659,149311,158 -84681660,149469,135 -84681661,149604,134 -84681662,149738,195 -84681663,149933,205 -84681664,150138,148 -84681665,150286,177 -84681666,150463,156 -84681667,150619,174 -84681668,150793,150 -84681669,150943,177 -84681670,151120,146 -84681671,151266,183 -84681672,151449,153 -84681673,151602,144 -84681674,151746,145 -84681675,151891,150 -84681676,152041,221 -84681677,152262,145 -84681678,152407,171 -84681679,152578,176 -84681680,152754,161 -84681681,152915,133 -84681682,153048,155 -84681683,153203,161 -84681684,153364,207 -84681685,153571,203 -84681686,153774,138 -84681687,153912,172 -84681688,154084,145 -84681689,154229,165 -84681690,154394,156 -84681691,154550,141 -84681692,154691,138 -84681693,154829,124 -84681694,154953,220 -84681695,155173,131 -84681696,155304,131 -84681697,155435,156 -84681698,155591,120 -84681699,155711,183 -84681700,155894,127 -84681701,156021,111 -84681702,156132,123 -84681703,156255,188 -84681704,156443,169 -84681705,156612,170 -84681706,156782,162 -84681707,156944,167 -84681708,157111,150 -84681709,157261,151 -84681710,157412,144 -84681711,157556,213 -84681712,157769,153 -84681713,157922,176 -84681714,158098,145 -84681715,158243,152 -84681716,158395,137 -84681717,158532,172 -84681718,158704,160 -84681719,158864,138 -84681720,159002,129 -84681721,159131,136 -84681722,159267,110 -84681723,159377,179 -84681724,159556,165 -84681725,159721,156 -84681726,159877,153 -84681727,160030,157 -84681728,160187,143 -84681729,160330,156 -84681730,160486,145 -84681731,160631,166 -84681732,160797,193 -84681733,160990,190 -84681734,161180,154 -84681735,161334,127 -84681736,161461,128 -84681737,161589,127 -84681738,161716,191 -84681739,161907,140 -84681740,162047,166 -84681741,162213,190 -84681742,162403,163 -84681743,162566,130 -84681744,162696,160 -84681745,162856,214 -84681746,163070,166 -84681747,163236,159 -84681748,163395,153 -84681749,163548,153 -84681750,163701,137 -84681751,163838,142 -84681752,163980,123 -84681753,164103,121 -84681754,164224,172 -84681755,164396,169 -84681756,164565,158 -84681757,164723,138 -84681758,164861,185 -84681759,165046,137 -84681760,165183,154 -84681761,165337,133 -84681762,165470,163 -84681763,165633,151 -84681764,165784,176 -84681765,165960,157 -84681766,166117,162 -84681767,166279,161 -84681768,166440,134 -84681769,166574,149 -84681770,166723,178 -84681771,166901,169 -84681772,167070,166 -84681773,167236,130 -84681774,167366,160 -84681775,167526,159 -84681776,167685,131 -84681777,167816,152 -84681778,167968,196 -84681779,168164,181 -84681780,168345,129 -84681781,168474,158 -84681782,168632,173 -84681783,168805,145 -84681784,168950,239 -84681785,169189,161 -84681786,169350,130 -84681787,169480,140 -84681788,169620,188 -84681789,169808,182 -84681790,169990,132 -84681791,170122,155 -84681792,170277,239 -84681793,170516,193 -84681794,170709,165 -84681795,170874,170 -84681796,171044,163 -84681797,171207,139 -84681798,171346,130 -84681799,171476,134 -84681800,171610,166 -84681801,171776,150 -84681802,171926,149 -84681803,172075,171 -84681804,172246,195 -84681805,172441,183 -84681806,172624,191 -84681807,172815,132 -84681808,172947,178 -84681809,173125,123 -84681810,173248,142 -84681811,173390,159 -84681812,173549,166 -84681813,173715,160 -84681814,173875,161 -84681815,174036,116 -84681816,174152,126 -84681817,174278,166 -84681818,174444,178 -84681819,174622,157 -84681820,174779,173 -84681821,174952,166 -84681822,175118,194 -84681823,175312,160 -84681824,175472,123 -84681825,175595,145 -84681826,175740,144 -84681827,175884,155 -84681828,176039,168 -84681829,176207,116 -84681830,176323,132 -84681831,176455,174 -84681832,176629,137 -84681833,176766,169 -84681834,176935,132 -84681835,177067,132 -84681836,177199,119 -84681837,177318,167 -84681838,177485,159 -84681839,177644,135 -84681840,177779,166 -84681841,177945,207 -84681842,178152,144 -84681843,178296,163 -84681844,178459,155 -84681845,178614,144 -84681846,178758,131 -84681847,178889,140 -84681848,179029,135 -84681849,179164,171 -84681850,179335,185 -84681851,179520,159 -84681852,179679,126 -84681853,179805,119 -84681854,179924,177 -84681855,180101,152 -84681856,180253,142 -84681857,180395,172 -84681858,180567,162 -84681859,180729,132 -84681860,180861,156 -84681861,181017,166 -84681862,181183,149 -84681863,181332,171 -84681864,181503,134 -84681865,181637,149 -84681866,181786,173 -84681867,181959,162 -84681868,182121,129 -84681869,182250,141 -84681870,182391,149 -84681871,182540,155 -84681872,182695,152 -84681873,182847,129 -84681874,182976,125 -84681875,183101,150 -84681876,183251,162 -84681877,183413,145 -84681878,183558,164 -84681879,183722,199 -84681880,183921,160 -84681881,184081,136 -84681882,184217,188 -84681883,184405,150 -84681884,184555,177 -84681885,184732,142 -84681886,184874,182 -84681887,185056,147 -84681888,185203,200 -84681889,185403,179 -84681890,185582,118 -84681891,185700,165 -84681892,185865,151 -84681893,186016,156 -84681894,186172,196 -84681895,186368,174 -84681896,186542,179 -84681897,186721,157 -84681898,186878,147 -84681899,187025,168 -84681900,187193,162 -84681901,187355,157 -84681902,187512,163 -84681903,187675,111 -84681904,187786,178 -84681905,187964,214 -84681906,188178,132 -84681907,188310,182 -84681908,188492,146 -84681909,188638,174 -84681910,188812,193 -84681911,189005,134 -84681912,189139,196 -84681913,189335,167 -84681914,189502,174 -84681915,189676,134 -84681916,189810,160 -84681917,189970,129 -84681918,190099,158 -84681919,190257,172 -84681920,190429,158 -84681921,190587,162 -84681922,190749,122 -84681923,190871,147 -84681924,191018,176 -84681925,191194,150 -84681926,191344,130 -84681927,191474,152 -84681928,191626,105 -84681929,191731,120 -84681930,191851,164 -84681931,192015,136 -84681932,192151,158 -84681933,192309,137 -84681934,192446,219 -84681935,192665,153 -84681936,192818,178 -84681937,192996,159 -84681938,193155,212 -84681939,193367,166 -84681940,193533,138 -84681941,193671,148 -84681942,193819,154 -84681943,193973,167 -84681944,194140,142 -84681945,194282,202 -84681946,194484,128 -84681947,194612,179 -84681948,194791,159 -84681949,194950,216 -84681950,195166,186 -84681951,195352,156 -84681952,195508,135 -84681953,195643,141 -84681954,195784,174 -84681955,195958,161 -84681956,196119,134 -84681957,196253,149 -84681958,196402,162 -84681959,196564,173 -84681960,196737,138 -84681961,196875,153 -84681962,197028,123 -84681963,197151,153 -84681964,197304,174 -84681965,197478,180 -84681966,197658,234 -84681967,197892,183 -84681968,198075,170 -84681969,198245,156 -84681970,198401,126 -84681971,198527,154 -84681972,198681,152 -84681973,198833,162 -84681974,198995,135 -84681975,199130,129 -84681976,199259,158 -84681977,199417,163 -84681978,199580,167 -84681979,199747,161 -84681980,199908,205 -84681981,200113,149 -84681982,200262,158 -84681983,200420,139 -84681984,200559,150 -84681985,200709,147 -84681986,200856,195 -84681987,201051,160 -84681988,201211,148 -84681989,201359,145 -84681990,201504,125 -84681991,201629,152 -84681992,201781,204 -84681993,201985,193 -84681994,202178,186 -84681995,202364,143 -84681996,202507,218 -84681997,202725,165 -84681998,202890,165 -84681999,203055,167 -84682000,203222,148 -84682001,203370,128 -84682002,203498,164 -84682003,203662,240 -84682004,203902,154 -84682005,204056,178 -84682006,204234,178 -84682007,204412,169 -84682008,204581,153 -84682009,204734,144 -84682010,204878,164 -84682011,205042,181 -84682012,205223,146 -84682013,205369,114 -84682014,205483,171 -84682015,205654,160 -84682016,205814,151 -84682017,205965,147 -84682018,206112,148 -84682019,206260,224 -84682020,206484,146 -84682021,206630,125 -84682022,206755,140 -84682023,206895,122 -84682024,207017,159 -84682025,207176,166 -84682026,207342,162 -84682027,207504,134 -84682028,207638,139 -84682029,207777,190 -84682030,207967,178 -84682031,208145,232 -84682032,208377,169 -84682033,208546,195 -84682034,208741,155 -84682035,208896,201 -84682036,209097,167 -84682037,209264,148 -84682038,209412,174 -84682039,209586,129 -84682040,209715,171 -84682041,209886,155 -84682042,210041,190 -84682043,210231,154 -84682044,210385,131 -84682045,210516,192 -84682046,210708,144 -84682047,210852,144 -84682048,210996,161 -84682049,211157,139 -84682050,211296,201 -84682051,211497,128 -84682052,211625,136 -84682053,211761,210 -84682054,211971,194 -84682055,212165,185 -84682056,212350,150 -84682057,212500,126 -84682058,212626,152 -84682059,212778,114 -84682060,212892,126 -84682061,213018,145 -84682062,213163,170 -84682063,213333,142 -84682064,213475,174 -84682065,213649,176 -84682066,213825,142 -84682067,213967,127 -84682068,214094,162 -84682069,214256,198 -84682070,214454,150 -84682071,214604,146 -84682072,214750,142 -84682073,214892,154 -84682074,215046,149 -84682075,215195,162 -84682076,215357,163 -84682077,215520,141 -84682078,215661,154 -84682079,215815,148 -84682080,215963,150 -84682081,216113,145 -84682082,216258,189 -84682083,216447,130 -84682084,216577,141 -84682085,216718,206 -84682086,216924,194 -84682087,217118,126 -84682088,217244,147 -84682089,217391,205 -84682090,217596,134 -84682091,217730,138 -84682092,217868,185 -84682093,218053,161 -84682094,218214,182 -84682095,218396,129 -84682096,218525,161 -84682097,218686,130 -84682098,218816,180 -84682099,218996,160 -84682100,219156,169 -84682101,219325,139 -84682102,219464,189 -84682103,219653,170 -84682104,219823,179 -84682105,220002,159 -84682106,220161,179 -84682107,220340,124 -84682108,220464,135 -84682109,220599,155 -84682110,220754,135 -84682111,220889,135 -84682112,221024,201 -84682113,221225,129 -84682114,221354,133 -84682115,221487,175 -84682116,221662,144 -84682117,221806,158 -84682118,221964,138 -84682119,222102,134 -84682120,222236,160 -84682121,222396,137 -84682122,222533,137 -84682123,222670,165 -84682124,222835,201 -84682125,223036,126 -84682126,223162,175 -84682127,223337,157 -84682128,223494,166 -84682129,223660,199 -84682130,223859,151 -84682131,224010,116 -84682132,224126,172 -84682133,224298,147 -84682134,224445,158 -84682135,224603,154 -84682136,224757,159 -84682137,224916,196 -84682138,225112,176 -84682139,225288,111 -84682140,225399,150 -84682141,225549,171 -84682142,225720,146 -84682143,225866,163 -84682144,226029,170 -84682145,226199,179 -84682146,226378,164 -84682147,226542,141 -84682148,226683,272 -84682149,226955,219 -84682150,227174,177 -84682151,227351,167 -84682152,227518,124 -84682153,227642,168 -84682154,227810,133 -84682155,227943,259 -84682156,228202,144 -84682157,228346,156 -84682158,228502,145 -84682159,228647,160 -84682160,228807,134 -84682161,228941,150 -84682162,229091,123 -84682163,229214,180 -84682164,229394,161 -84682165,229555,105 -84682166,229660,199 -84682167,229859,202 -84682168,230061,140 -84682169,230201,173 -84682170,230374,154 -84682171,230528,155 -84682172,230683,249 -84682173,230932,171 -84682174,231103,194 -84682175,231297,156 -84682176,231453,153 -84682177,231606,152 -84682178,231758,145 -84682179,231903,133 -84682180,232036,131 -84682181,232167,177 -84682182,232344,173 -84682183,232517,178 -84682184,232695,188 -84682185,232883,197 -84682186,233080,204 -84682187,233284,173 -84682188,233457,142 -84682189,233599,167 -84682190,233766,182 -84682191,233948,145 -84682192,234093,140 -84682193,234233,162 -84682194,234395,128 -84682195,234523,127 -84682196,234650,201 -84682197,234851,169 -84682198,235020,190 -84682199,235210,135 -84682200,235345,138 -84682201,235483,167 -84682202,235650,148 -84682203,235798,149 -84682204,235947,186 -84682205,236133,171 -84682206,236304,145 -84682207,236449,144 -84682208,236593,166 -84682209,236759,172 -84682210,236931,151 -84682211,237082,154 -84682212,237236,204 -84682213,237440,131 -84682214,237571,131 -84682215,237702,150 -84682216,237852,181 -84682217,238033,190 -84682218,238223,167 -84682219,238390,177 -84682220,238567,183 -84682221,238750,170 -84682222,238920,163 -84682223,239083,129 -84682224,239212,145 -84682225,239357,157 -84682226,239514,172 -84682227,239686,140 -84682228,239826,133 -84682229,239959,181 -84682230,240140,181 -84682231,240321,141 -84682232,240462,134 -84682233,240596,149 -84682234,240745,123 -84682235,240868,181 -84682236,241049,147 -84682237,241196,188 -84682238,241384,147 -84682239,241531,177 -84682240,241708,183 -84682241,241891,170 -84682242,242061,137 -84682243,242198,129 -84682244,242327,139 -84682245,242466,136 -84682246,242602,226 -84682247,242828,139 -84682248,242967,172 -84682249,243139,154 -84682250,243293,163 -84682251,243456,203 -84682252,243659,114 -84682253,243773,134 -84682254,243907,199 -84682255,244106,207 -84682256,244313,168 -84682257,244481,160 -84682258,244641,142 -84682259,244783,141 -84682260,244924,114 -84682261,245038,172 -84682262,245210,155 -84682263,245365,176 -84682264,245541,201 -84682265,245742,155 -84682266,245897,177 -84682267,246074,158 -84682268,246232,160 -84682269,246392,152 -84682270,246544,190 -84682271,246734,157 -84682272,246891,185 -84682273,247076,146 -84682274,247222,151 -84682275,247373,150 -84682276,247523,140 -84682277,247663,128 -84682278,247791,173 -84682279,247964,188 -84682280,248152,142 -84682281,248294,191 -84682282,248485,144 -84682283,248629,163 -84682284,248792,141 -84682285,248933,150 -84682286,249083,142 -84682287,249225,103 -84682288,249328,156 -84682289,249484,137 -84682290,249621,139 -84682291,249760,149 -84682292,249909,158 -84682293,250067,142 -84682294,250209,148 -84682295,250357,163 -84682296,250520,172 -84682297,250692,170 -84682298,250862,170 -84682299,251032,150 -84682300,251182,174 -84682301,251356,136 -84682302,251492,210 -84682303,251702,180 -84682304,251882,123 -84682305,252005,235 -84682306,252240,202 -84682307,252442,137 -84682308,252579,167 -84682309,252746,165 -84682310,252911,184 -84682311,253095,202 -84682312,253297,162 -84682313,253459,131 -84682314,253590,142 -84682315,253732,110 -84682316,253842,153 -84682317,253995,185 -84682318,254180,142 -84682319,254322,171 -84682320,254493,159 -84682321,254652,116 -84682322,254768,137 -84682323,254905,141 -84682324,255046,152 -84682325,255198,178 -84682326,255376,201 -84682327,255577,167 -84682328,255744,124 -84682329,255868,178 -84682330,256046,132 -84682331,256178,143 -84682332,256321,117 -84682333,256438,170 -84682334,256608,120 -84682335,256728,144 -84682336,256872,158 -84682337,257030,122 -84682338,257152,229 -84682339,257381,157 -84682340,257538,154 -84682341,257692,153 -84682342,257845,164 -84682343,258009,187 -84682344,258196,145 -84682345,258341,178 -84682346,258519,289 -84682347,258808,162 -84682348,258970,115 -84682349,259085,150 -84682350,259235,155 -84682351,259390,123 -84682352,259513,141 -84682353,259654,160 -84682354,259814,142 -84682355,259956,157 -84682356,260113,207 -84682357,260320,167 -84682358,260487,119 -84682359,260606,136 -84682360,260742,102 -84682361,260844,175 -84682362,261019,114 -84682363,261133,154 -84682364,261287,160 -84682365,261447,147 -84682366,261594,154 -84682367,261748,166 -84682368,261914,197 -84682369,262111,181 -84682370,262292,132 -84682371,262424,164 -84682372,262588,202 -84682373,262790,127 -84682374,262917,171 -84682375,263088,174 -84682376,263262,156 -84682377,263418,152 -84682378,263570,213 -84682379,263783,135 -84682380,263918,150 -84682381,264068,155 -84682382,264223,114 -84682383,264337,138 -84682384,264475,197 -84682385,264672,157 -84682386,264829,167 -84682387,264996,143 -84682388,265139,131 -84682389,265270,168 -84682390,265438,156 -84682391,265594,146 -84682392,265740,159 -84682393,265899,177 -84682394,266076,161 -84682395,266237,159 -84682396,266396,149 -84682397,266545,183 -84682398,266728,110 -84682399,266838,138 -84682400,266976,129 -84682401,267105,172 -84682402,267277,176 -84682403,267453,162 -84682404,267615,140 -84682405,267755,179 -84682406,267934,190 -84682407,268124,173 -84682408,268297,172 -84682409,268469,186 -84682410,268655,205 -84682411,268860,161 -84682412,269021,146 -84682413,269167,158 -84682414,269325,123 -84682415,269448,136 -84682416,269584,204 -84682417,269788,144 -84682418,269932,126 -84682419,270058,160 -84682420,270218,123 -84682421,270341,155 -84682422,270496,140 -84682423,270636,180 -84682424,270816,146 -84682425,270962,130 -84682426,271092,225 -84682427,271317,131 -84682428,271448,166 -84682429,271614,123 -84682430,271737,148 -84682431,271885,126 -84682432,272011,176 -84682433,272187,136 -84682434,272323,179 -84682435,272502,169 -84682436,272671,138 -84682437,272809,149 -84682438,272958,188 -84682439,273146,166 -84682440,273312,192 -84682441,273504,141 -84682442,273645,151 -84682443,273796,148 -84682444,273944,168 -84682445,274112,115 -84682446,274227,161 -84682447,274388,124 -84682448,274512,139 -84682449,274651,174 -84682450,274825,169 -84682451,274994,200 -84682452,275194,166 -84682453,275360,154 -84682454,275514,168 -84682455,275682,168 -84682456,275850,165 -84682457,276015,126 -84682458,276141,153 -84682459,276294,164 -84682460,276458,181 -84682461,276639,152 -84682462,276791,190 -84682463,276981,135 -84682464,277116,159 -84682465,277275,188 -84682466,277463,166 -84682467,277629,120 -84682468,277749,110 -84682469,277859,169 -84682470,278028,138 -84682471,278166,196 -84682472,278362,126 -84682473,278488,211 -84682474,278699,151 -84682475,278850,152 -84682476,279002,198 -84682477,279200,162 -84682478,279362,172 -84682479,279534,176 -84682480,279710,182 -84682481,279892,122 -84682482,280014,169 -84682483,280183,135 -84682484,280318,179 -84682485,280497,157 -84682486,280654,145 -84682487,280799,214 -84682488,281013,158 -84682489,281171,145 -84682490,281316,116 -84682491,281432,119 -84682492,281551,129 -84682493,281680,154 -84682494,281834,129 -84682495,281963,173 -84682496,282136,137 -84682497,282273,145 -84682498,282418,132 -84682499,282550,167 -84682500,282717,168 -84682501,282885,126 -84682502,283011,224 -84682503,283235,137 -84682504,283372,135 -84682505,283507,167 -84682506,283674,168 -84682507,283842,202 -84682508,284044,118 -84682509,284162,148 -84682510,284310,146 -84682511,284456,148 -84682512,284604,200 -84682513,284804,138 -84682514,284942,126 -84682515,285068,186 -84682516,285254,149 -84682517,285403,159 -84682518,285562,144 -84682519,285706,154 -84682520,285860,138 -84682521,285998,145 -84682522,286143,190 -84682523,286333,168 -84682524,286501,134 -84682525,286635,129 -84682526,286764,175 -84682527,286939,136 -84682528,287075,185 -84682529,287260,166 -84682530,287426,161 -84682531,287587,152 -84682532,287739,176 -84682533,287915,178 -84682534,288093,137 -84682535,288230,154 -84682536,288384,171 -84682537,288555,148 -84682538,288703,166 -84682539,288869,167 -84682540,289036,193 -84682541,289229,184 -84682542,289413,154 -84682543,289567,158 -84682544,289725,177 -84682545,289902,170 -84682546,290072,152 -84682547,290224,157 -84682548,290381,151 -84682549,290532,159 -84682550,290691,115 -84682551,290806,148 -84682552,290954,205 -84682553,291159,150 -84682554,291309,125 -84682555,291434,192 -84682556,291626,140 -84682557,291766,126 -84682558,291892,156 -84682559,292048,143 -84682560,292191,198 -84682561,292389,172 -84682562,292561,155 -84682563,292716,148 -84682564,292864,182 -84682565,293046,131 -84682566,293177,155 -84682567,293332,150 -84682568,293482,144 -84682569,293626,151 -84682570,293777,166 -84682571,293943,178 -84682572,294121,154 -84682573,294275,179 -84682574,294454,136 -84682575,294590,181 -84682576,294771,217 -84682577,294988,181 -84682578,295169,118 -84682579,295287,119 -84682580,295406,161 -84682581,295567,138 -84682582,295705,166 -84682583,295871,194 -84682584,296065,136 -84682585,296201,178 -84682586,296379,144 -84682587,296523,136 -84682588,296659,191 -84682589,296850,153 -84682590,297003,155 -84682591,297158,183 -84682592,297341,179 -84682593,297520,217 -84682594,297737,204 -84682595,297941,144 -84682596,298085,152 -84682597,298237,166 -84682598,298403,165 -84682599,298568,131 -84682600,298699,190 -84682601,298889,122 -84682602,299011,148 -84682603,299159,206 -84682604,299365,156 -84682605,299521,183 -84682606,299704,139 -84682607,299843,170 -84682608,300013,153 -84682609,300166,161 -84682610,300327,168 -84682611,300495,188 -84682612,300683,136 -84682613,300819,159 -84682614,300978,172 -84682615,301150,137 -84682616,301287,166 -84682617,301453,132 -84682618,301585,137 -84682619,301722,167 -84682620,301889,129 -84682621,302018,148 -84682622,302166,138 -84682623,302304,141 -84682624,302445,168 -84682625,302613,161 -84682626,302774,164 -84682627,302938,156 -84682628,303094,147 -84682629,303241,167 -84682630,303408,145 -84682631,303553,198 -84682632,303751,158 -84682633,303909,209 -84682634,304118,188 -84682635,304306,143 -84682636,304449,154 -84682637,304603,136 -84682638,304739,146 -84682639,304885,136 -84682640,305021,208 -84682641,305229,201 -84682642,305430,182 -84682643,305612,147 -84682644,305759,169 -84682645,305928,155 -84682646,306083,154 -84682647,306237,171 -84682648,306408,146 -84682649,306554,127 -84682650,306681,135 -84682651,306816,158 -84682652,306974,153 -84682653,307127,134 -84682654,307261,169 -84682655,307430,134 -84682656,307564,158 -84682657,307722,149 -84682658,307871,162 -84682659,308033,325 -84682660,308358,172 -84682661,308530,167 -84682662,308697,175 -84682663,308872,203 -84682664,309075,194 -84682665,309269,165 -84682666,309434,134 -84682667,309568,184 -84682668,309752,174 -84682669,309926,146 -84682670,310072,147 -84682671,310219,160 -84682672,310379,119 -84682673,310498,137 -84682674,310635,163 -84682675,310798,140 -84682676,310938,144 -84682677,311082,166 -84682678,311248,150 -84682679,311398,134 -84682680,311532,175 -84682681,311707,171 -84682682,311878,163 -84682683,312041,173 -84682684,312214,125 -84682685,312339,183 -84682686,312522,177 -84682687,312699,134 -84682688,312833,190 -84682689,313023,191 -84682690,313214,173 -84682691,313387,150 -84682692,313537,124 -84682693,313661,162 -84682694,313823,138 -84682695,313961,147 -84682696,314108,129 -84682697,314237,190 -84682698,314427,159 -84682699,314586,169 -84682700,314755,135 -84682701,314890,194 -84682702,315084,142 -84682703,315226,200 -84682704,315426,142 -84682705,315568,166 -84682706,315734,129 -84682707,315863,166 -84682708,316029,155 -84682709,316184,152 -84682710,316336,192 -84682711,316528,138 -84682712,316666,125 -84682713,316791,170 -84682714,316961,182 -84682715,317143,158 -84682716,317301,128 -84682717,317429,144 -84682718,317573,203 -84682719,317776,56 -84682720,317832,155 -84682721,317987,158 -84682722,318145,154 -84682723,318299,185 -84682724,318484,199 -84682725,318683,147 -84682726,318830,146 -84682727,318976,153 -84682728,319129,205 -84682729,319334,134 -84682730,319468,178 -84682731,319646,226 -84682732,319872,153 -84682733,320025,162 -84682734,320187,129 -84682735,320316,134 -84682736,320450,165 -84682737,320615,146 -84682738,320761,175 -84682739,320936,145 -84682740,321081,158 -84682741,321239,145 -84682742,321384,154 -84682743,321538,110 -84682744,321648,223 -84682745,321871,153 -84682746,322024,135 -84682747,322159,152 -84682748,322311,151 -84682749,322462,115 -84682750,322577,160 -84682751,322737,278 -84682752,323015,171 -84682753,323186,123 -84682754,323309,56 -84682755,323365,190 -84682756,323555,168 -84682757,323723,158 -84682758,323881,122 -84682759,324003,141 -84682760,324144,150 -84682761,324294,149 -84682762,324443,163 -84682763,324606,142 -84682764,324748,201 -84682765,324949,156 -84682766,325105,154 -84682767,325259,149 -84682768,325408,186 -84682769,325594,206 -84682770,325800,126 -84682771,325926,160 -84682772,326086,119 -84682773,326205,180 -84682774,326385,153 -84682775,326538,173 -84682776,326711,140 -84682777,326851,128 -84682778,326979,125 -84682779,327104,209 -84682780,327313,122 -84682781,327435,193 -84682782,327628,132 -84682783,327760,149 -84682784,327909,133 -84682785,328042,150 -84682786,328192,196 -84682787,328388,156 -84682788,328544,128 -84682789,328672,195 -84682790,328867,162 -84682791,329029,163 -84682792,329192,159 -84682793,329351,151 -84682794,329502,161 -84682795,329663,145 -84682796,329808,141 -84682797,329949,130 -84682798,330079,137 -84682799,330216,180 -84682800,330396,156 -84682801,330552,157 -84682802,330709,152 -84682803,330861,140 -84682804,331001,143 -84682805,331144,182 -84682806,331326,178 -84682807,331504,129 -84682808,331633,224 -84682809,331857,173 -84682810,332030,168 -84682811,332198,132 -84682812,332330,159 -84682813,332489,125 -84682814,332614,139 -84682815,332753,172 -84682816,332925,191 -84682817,333116,193 -84682818,333309,150 -84682819,333459,169 -84682820,333628,198 -84682821,333826,162 -84682822,333988,181 -84682823,334169,179 -84682824,334348,254 -84682825,334602,172 -84682826,334774,193 -84682827,334967,207 -84682828,335174,162 -84682829,335336,111 -84682830,335447,162 -84682831,335609,153 -84682832,335762,153 -84682833,335915,194 -84682834,336109,181 -84682835,336290,170 -84682836,336460,164 -84682837,336624,187 -84682838,336811,144 -84682839,336955,134 -84682840,337089,170 -84682841,337259,130 -84682842,337389,137 -84682843,337526,146 -84682844,337672,129 -84682845,337801,171 -84682846,337972,154 -84682847,338126,196 -84682848,338322,145 -84682849,338467,165 -84682850,338632,132 -84682851,338764,155 -84682852,338919,181 -84682853,339100,179 -84682854,339279,154 -84682855,339433,141 -84682856,339574,145 -84682857,339719,178 -84682858,339897,169 -84682859,340066,175 -84682860,340241,163 -84682861,340404,161 -84682862,340565,183 -84682863,340748,137 -84682864,340885,152 -84682865,341037,184 -84682866,341221,125 -84682867,341346,197 -84682868,341543,164 -84682869,341707,166 -84682870,341873,184 -84682871,342057,154 -84682872,342211,214 -84682873,342425,137 -84682874,342562,156 -84682875,342718,169 -84682876,342887,140 -84682877,343027,178 -84682878,343205,155 -84682879,343360,172 -84682880,343532,172 -84682881,343704,181 -84682882,343885,155 -84682883,344040,206 -84682884,344246,139 -84682885,344385,171 -84682886,344556,154 -84682887,344710,192 -84682888,344902,166 -84682889,345068,171 -84682890,345239,171 -84682891,345410,179 -84682892,345589,139 -84682893,345728,186 -84682894,345914,153 -84682895,346067,150 -84682896,346217,175 -84682897,346392,191 -84682898,346583,130 -84682899,346713,171 -84682900,346884,142 -84682901,347026,193 -84682902,347219,141 -84682903,347360,158 -84682904,347518,182 -84682905,347700,165 -84682906,347865,177 -84682907,348042,176 -84682908,348218,170 -84682909,348388,149 -84682910,348537,146 -84682911,348683,180 -84682912,348863,190 -84682913,349053,155 -84682914,349208,192 -84682915,349400,130 -84682916,349530,174 -84682917,349704,142 -84682918,349846,114 -84682919,349960,121 -84682920,350081,164 -84682921,350245,212 -84682922,350457,161 -84682923,350618,165 -84682924,350783,134 -84682925,350917,174 -84682926,351091,227 -84682927,351318,126 -84682928,351444,160 -84682929,351604,181 -84682930,351785,147 -84682931,351932,149 -84682932,352081,129 -84682933,352210,145 -84682934,352355,191 -84682935,352546,169 -84682936,352715,171 -84682937,352886,141 -84682938,353027,130 -84682939,353157,158 -84682940,353315,150 -84682941,353465,164 -84682942,353629,201 -84682943,353830,179 -84682944,354009,129 -84682945,354138,155 -84682946,354293,177 -84682947,354470,150 -84682948,354620,251 -84682949,354871,184 -84682950,355055,163 -84682951,355218,143 -84682952,355361,216 -84682953,355577,183 -84682954,355760,151 -84682955,355911,145 -84682956,356056,157 -84682957,356213,174 -84682958,356387,172 -84682959,356559,129 -84682960,356688,154 -84682961,356842,168 -84682962,357010,136 -84682963,357146,126 -84682964,357272,199 -84682965,357471,146 -84682966,357617,187 -84682967,357804,150 -84682968,357954,180 -84682969,358134,220 -84682970,358354,147 -84682971,358501,242 -84682972,358743,170 -84682973,358913,119 -84682974,359032,135 -84682975,359167,172 -84682976,359339,266 -84682977,359605,148 -84682978,359753,158 -84682979,359911,161 -84682980,360072,201 -84682981,360273,138 -84682982,360411,149 -84682983,360560,142 -84682984,360702,153 -84682985,360855,118 -84682986,360973,137 -84682987,361110,166 -84682988,361276,157 -84682989,361433,174 -84682990,361607,124 -84682991,361731,169 -84682992,361900,156 -84682993,362056,207 -84682994,362263,147 -84682995,362410,161 -84682996,362571,142 -84682997,362713,113 -84682998,362826,153 -84682999,362979,169 -84683000,363148,153 -84683001,363301,179 -84683002,363480,138 -84683003,363618,157 -84683004,363775,159 -84683005,363934,230 -84683006,364164,137 -84683007,364301,123 -84683008,364424,153 -84683009,364577,176 -84683010,364753,203 -84683011,364956,180 -84683012,365136,140 -84683013,365276,163 -84683014,365439,112 -84683015,365551,148 -84683016,365699,143 -84683017,365842,154 -84683018,365996,174 -84683019,366170,128 -84683020,366298,129 -84683021,366427,155 -84683022,366582,166 -84683023,366748,160 -84683024,366908,158 -84683025,367066,143 -84683026,367209,178 -84683027,367387,175 -84683028,367562,122 -84683029,367684,142 -84683030,367826,156 -84683031,367982,152 -84683032,368134,171 -84683033,368305,139 -84683034,368444,157 -84683035,368601,172 -84683036,368773,116 -84683037,368889,174 -84683038,369063,135 -84683039,369198,193 -84683040,369391,161 -84683041,369552,162 -84683042,369714,146 -84683043,369860,144 -84683044,370004,180 -84683045,370184,146 -84683046,370330,169 -84683047,370499,179 -84683048,370678,137 -84683049,370815,175 -84683050,370990,166 -84683051,371156,178 -84683052,371334,147 -84683053,371481,149 -84683054,371630,177 -84683055,371807,166 -84683056,371973,189 -84683057,372162,246 -84683058,372408,168 -84683059,372576,154 -84683060,372730,138 -84683061,372868,132 -84683062,373000,155 -84683063,373155,112 -84683064,373267,179 -84683065,373446,166 -84683066,373612,171 -84683067,373783,152 -84683068,373935,162 -84683069,374097,198 -84683070,374295,187 -84683071,374482,166 -84683072,374648,166 -84683073,374814,110 -84683074,374924,145 -84683075,375069,217 -84683076,375286,129 -84683077,375415,177 -84683078,375592,160 -84683079,375752,147 -84683080,375899,172 -84683081,376071,129 -84683082,376200,137 -84683083,376337,174 -84683084,376511,138 -84683085,376649,165 -84683086,376814,191 -84683087,377005,132 -84683088,377137,162 -84683089,377299,142 -84683090,377441,138 -84683091,377579,134 -84683092,377713,166 -84683093,377879,155 -84683094,378034,134 -84683095,378168,168 -84683096,378336,166 -84683097,378502,131 -84683098,378633,126 -84683099,378759,141 -84683100,378900,176 -84683101,379076,172 -84683102,379248,154 -84683103,379402,186 -84683104,379588,178 -84683105,379766,208 -84683106,379974,142 -84683107,380116,134 -84683108,380250,136 -84683109,380386,201 -84683110,380587,143 -84683111,380730,167 -84683112,380897,150 -84683113,381047,176 -84683114,381223,175 -84683115,381398,209 -84683116,381607,146 -84683117,381753,189 -84683118,381942,165 -84683119,382107,141 -84683120,382248,174 -84683121,382422,125 -84683122,382547,178 -84683123,382725,136 -84683124,382861,145 -84683125,383006,182 -84683126,383188,222 -84683127,383410,154 -84683128,383564,173 -84683129,383737,173 -84683130,383910,194 -84683131,384104,136 -84683132,384240,164 -84683133,384404,180 -84683134,384584,122 -84683135,384706,129 -84683136,384835,166 -84683137,385001,147 -84683138,385148,168 -84683139,385316,153 -84683140,385469,157 -84683141,385626,161 -84683142,385787,134 -84683143,385921,230 -84683144,386151,161 -84683145,386312,150 -84683146,386462,173 -84683147,386635,175 -84683148,386810,142 -84683149,386952,126 -84683150,387078,159 -84683151,387237,139 -84683152,387376,145 -84683153,387521,137 -84683154,387658,177 -84683155,387835,216 -84683156,388051,139 -84683157,388190,212 -84683158,388402,159 -84683159,388561,149 -84683160,388710,166 -84683161,388876,181 -84683162,389057,129 -84683163,389186,144 -84683164,389330,155 -84683165,389485,134 -84683166,389619,160 -84683167,389779,146 -84683168,389925,156 -84683169,390081,125 -84683170,390206,133 -84683171,390339,145 -84683172,390484,160 -84683173,390644,149 -84683174,390793,125 -84683175,390918,197 -84683176,391115,117 -84683177,391232,192 -84683178,391424,158 -84683179,391582,146 -84683180,391728,153 -84683181,391881,192 -84683182,392073,150 -84683183,392223,151 -84683184,392374,122 -84683185,392496,138 -84683186,392634,128 -84683187,392762,145 -84683188,392907,163 -84683189,393070,128 -84683190,393198,163 -84683191,393361,163 -84683192,393524,158 -84683193,393682,223 -84683194,393905,149 -84683195,394054,143 -84683196,394197,173 -84683197,394370,170 -84683198,394540,169 -84683199,394709,163 -84683200,394872,173 -84683201,395045,126 -84683202,395171,183 -84683203,395354,208 -84683204,395562,141 -84683205,395703,143 -84683206,395846,141 -84683207,395987,138 -84683208,396125,136 -84683209,396261,181 -84683210,396442,140 -84683211,396582,124 -84683212,396706,186 -84683213,396892,138 -84683214,397030,150 -84683215,397180,155 -84683216,397335,213 -84683217,397548,152 -84683218,397700,154 -84683219,397854,171 -84683220,398025,135 -84683221,398160,132 -84683222,398292,169 -84683223,398461,128 -84683224,398589,233 -84683225,398822,154 -84683226,398976,135 -84683227,399111,144 -84683228,399255,188 -84683229,399443,142 -84683230,399585,123 -84683231,399708,148 -84683232,399856,135 -84683233,399991,155 -84683234,400146,178 -84683235,400324,145 -84683236,400469,139 -84683237,400608,158 -84683238,400766,184 -84683239,400950,156 -84683240,401106,182 -84683241,401288,157 -84683242,401445,172 -84683243,401617,167 -84683244,401784,166 -84683245,401950,122 -84683246,402072,188 -84683247,402260,142 -84683248,402402,148 -84683249,402550,140 -84683250,402690,145 -84683251,402835,155 -84683252,402990,130 -84683253,403120,140 -84683254,403260,146 -84683255,403406,136 -84683256,403542,198 -84683257,403740,326 -84683258,404066,206 -84683259,404272,127 -84683260,404399,155 -84683261,404554,159 -84683262,404713,253 -84683263,404966,146 -84683264,405112,158 -84683265,405270,187 -84683266,405457,161 -84683267,405618,150 -84683268,405768,110 -84683269,405878,138 -84683270,406016,164 -84683271,406180,148 -84683272,406328,155 -84683273,406483,192 -84683274,406675,137 -84683275,406812,180 -84683276,406992,166 -84683277,407158,152 -84683278,407310,141 -84683279,407451,160 -84683280,407611,172 -84683281,407783,157 -84683282,407940,145 -84683283,408085,152 -84683284,408237,224 -84683285,408461,173 -84683286,408634,178 -84683287,408812,225 -84683288,409037,166 -84683289,409203,160 -84683290,409363,147 -84683291,409510,173 -84683292,409683,138 -84683293,409821,166 -84683294,409987,164 -84683295,410151,171 -84683296,410322,163 -84683297,410485,128 -84683298,410613,273 -84683299,410886,142 -84683300,411028,134 -84683301,411162,154 -84683302,411316,141 -84683303,411457,135 -84683304,411592,194 -84683305,411786,155 -84683306,411941,151 -84683307,412092,170 -84683308,412262,155 -84683309,412417,159 -84683310,412576,152 -84683311,412728,158 -84683312,412886,130 -84683313,413016,147 -84683314,413163,164 -84683315,413327,167 -84683316,413494,144 -84683317,413638,162 -84683318,413800,218 -84683319,414018,163 -84683320,414181,157 -84683321,414338,194 -84683322,414532,143 -84683323,414675,136 -84683324,414811,178 -84683325,414989,120 -84683326,415109,159 -84683327,415268,170 -84683328,415438,159 -84683329,415597,166 -84683330,415763,156 -84683331,415919,136 -84683332,416055,153 -84683333,416208,134 -84683334,416342,147 -84683335,416489,164 -84683336,416653,158 -84683337,416811,147 -84683338,416958,134 -84683339,417092,181 -84683340,417273,142 -84683341,417415,142 -84683342,417557,164 -84683343,417721,154 -84683344,417875,163 -84683345,418038,160 -84683346,418198,151 -84683347,418349,132 -84683348,418481,240 -84683349,418721,177 -84683350,418898,146 -84683351,419044,154 -84683352,419198,153 -84683353,419351,152 -84683354,419503,118 -84683355,419621,168 -84683356,419789,178 -84683357,419967,135 -84683358,420102,204 -84683359,420306,149 -84683360,420455,195 -84683361,420650,127 -84683362,420777,158 -84683363,420935,153 -84683364,421088,145 -84683365,421233,162 -84683366,421395,125 -84683367,421520,167 -84683368,421687,167 -84683369,421854,175 -84683370,422029,139 -84683371,422168,145 -84683372,422313,183 -84683373,422496,149 -84683374,422645,186 -84683375,422831,154 -84683376,422985,185 -84683377,423170,133 -84683378,423303,155 -84683379,423458,197 -84683380,423655,176 -84683381,423831,170 -84683382,424001,183 -84683383,424184,145 -84683384,424329,145 -84683385,424474,144 -84683386,424618,207 -84683387,424825,198 -84683388,425023,172 -84683389,425195,141 -84683390,425336,191 -84683391,425527,166 -84683392,425693,109 -84683393,425802,154 -84683394,425956,142 -84683395,426098,155 -84683396,426253,163 -84683397,426416,137 -84683398,426553,119 -84683399,426672,159 -84683400,426831,109 -84683401,426940,151 -84683402,427091,160 -84683403,427251,121 -84683404,427372,131 -84683405,427503,176 -84683406,427679,185 -84683407,427864,144 -84683408,428008,143 -84683409,428151,199 -84683410,428350,134 -84683411,428484,166 -84683412,428650,139 -84683413,428789,275 -84683414,429064,136 -84683415,429200,148 -84683416,429348,165 -84683417,429513,142 -84683418,429655,154 -84683419,429809,158 -84683420,429967,188 -84683421,430155,148 -84683422,430303,182 -84683423,430485,146 -84683424,430631,140 -84683425,430771,153 -84683426,430924,118 -84683427,431042,165 -84683428,431207,183 -84683429,431390,177 -84683430,431567,197 -84683431,431764,114 -84683432,431878,158 -84683433,432036,145 -84683434,432181,173 -84683435,432354,176 -84683436,432530,151 -84683437,432681,151 -84683438,432832,137 -84683439,432969,179 -84683440,433148,187 -84683441,433335,137 -84683442,433472,154 -84683443,433626,199 -84683444,433825,168 -84683445,433993,149 -84683446,434142,210 -84683447,434352,153 -84683448,434505,199 -84683449,434704,120 -84683450,434824,154 -84683451,434978,138 -84683452,435116,158 -84683453,435274,178 -84683454,435452,137 -84683455,435589,176 -84683456,435765,174 -84683457,435939,157 -84683458,436096,133 -84683459,436229,173 -84683460,436402,195 -84683461,436597,160 -84683462,436757,158 -84683463,436915,118 -84683464,437033,147 -84683465,437180,233 -84683466,437413,177 -84683467,437590,200 -84683468,437790,140 -84683469,437930,149 -84683470,438079,161 -84683471,438240,151 -84683472,438391,183 -84683473,438574,166 -84683474,438740,141 -84683475,438881,165 -84683476,439046,167 -84683477,439213,194 -84683478,439407,122 -84683479,439529,193 -84683480,439722,114 -84683481,439836,156 -84683482,439992,129 -84683483,440121,157 -84683484,440278,173 -84683485,440451,197 -84683486,440648,139 -84683487,440787,131 -84683488,440918,153 -84683489,441071,150 -84683490,441221,170 -84683491,441391,115 -84683492,441506,178 -84683493,441684,249 -84683494,441933,138 -84683495,442071,141 -84683496,442212,134 -84683497,442346,163 -84683498,442509,128 -84683499,442637,175 -84683500,442812,165 -84683501,442977,152 -84683502,443129,157 -84683503,443286,168 -84683504,443454,125 -84683505,443579,134 -84683506,443713,137 -84683507,443850,178 -84683508,444028,145 -84683509,444173,157 -84683510,444330,140 -84683511,444470,188 -84683512,444658,174 -84683513,444832,187 -84683514,445019,165 -84683515,445184,187 -84683516,445371,149 -84683517,445520,166 -84683518,445686,161 -84683519,445847,140 -84683520,445987,154 -84683521,446141,189 -84683522,446330,158 -84683523,446488,197 -84683524,446685,142 -84683525,446827,124 -84683526,446951,160 -84683527,447111,142 -84683528,447253,144 -84683529,447397,191 -84683530,447588,189 -84683531,447777,153 -84683532,447930,193 -84683533,448123,179 -84683534,448302,127 -84683535,448429,171 -84683536,448600,189 -84683537,448789,124 -84683538,448913,161 -84683539,449074,214 -84683540,449288,145 -84683541,449433,160 -84683542,449593,139 -84683543,449732,145 -84683544,449877,207 -84683545,450084,148 -84683546,450232,144 -84683547,450376,158 -84683548,450534,166 -84683549,450700,125 -84683550,450825,163 -84683551,450988,178 -84683552,451166,180 -84683553,451346,161 -84683554,451507,213 -84683555,451720,182 -84683556,451902,199 -84683557,452101,121 -84683558,452222,148 -84683559,452370,130 -84683560,452500,144 -84683561,452644,189 -84683562,452833,151 -84683563,452984,171 -84683564,453155,157 -84683565,453312,185 -84683566,453497,133 -84683567,453630,185 -84683568,453815,180 -84683569,453995,140 -84683570,454135,150 -84683571,454285,117 -84683572,454402,182 -84683573,454584,110 -84683574,454694,119 -84683575,454813,167 -84683576,454980,154 -84683577,455134,147 -84683578,455281,188 -84683579,455469,146 -84683580,455615,123 -84683581,455738,125 -84683582,455863,154 -84683583,456017,190 -84683584,456207,140 -84683585,456347,256 -84683586,456603,171 -84683587,456774,138 -84683588,456912,148 -84683589,457060,181 -84683590,457241,115 -84683591,457356,176 -84683592,457532,135 -84683593,457667,194 -84683594,457861,154 -84683595,458015,149 -84683596,458164,117 -84683597,458281,160 -84683598,458441,133 -84683599,458574,169 -84683600,458743,114 -84683601,458857,139 -84683602,458996,158 -84683603,459154,121 -84683604,459275,150 -84683605,459425,174 -84683606,459599,133 -84683607,459732,166 -84683608,459898,124 -84683609,460022,159 -84683610,460181,142 -84683611,460323,151 -84683612,460474,141 -84683613,460615,165 -84683614,460780,145 -84683615,460925,159 -84683616,461084,153 -84683617,461237,116 -84683618,461353,164 -84683619,461517,152 -84683620,461669,135 -84683621,461804,165 -84683622,461969,166 -84683623,462135,144 -84683624,462279,201 -84683625,462480,127 -84683626,462607,166 -84683627,462773,166 -84683628,462939,114 -84683629,463053,172 -84683630,463225,56 -84683631,463281,142 -84683632,463423,178 -84683633,463601,220 -84683634,463821,179 -84683635,464000,183 -84683636,464183,179 -84683637,464362,134 -84683638,464496,148 -84683639,464644,121 -84683640,464765,142 -84683641,464907,178 -84683642,465085,202 -84683643,465287,160 -84683644,465447,140 -84683645,465587,125 -84683646,465712,181 -84683647,465893,120 -84683648,466013,148 -84683649,466161,199 -84683650,466360,139 -84683651,466499,189 -84683652,466688,197 -84683653,466885,153 -84683654,467038,115 -84683655,467153,129 -84683656,467282,154 -84683657,467436,217 -84683658,467653,131 -84683659,467784,126 -84683660,467910,145 -84683661,468055,140 -84683662,468195,131 -84683663,468326,108 -84683664,468434,195 -84683665,468629,171 -84683666,468800,306 -84683667,469106,140 -84683668,469246,168 -84683669,469414,152 -84683670,469566,174 -84683671,469740,130 -84683672,469870,170 -84683673,470040,179 -84683674,470219,155 -84683675,470374,146 -84683676,470520,119 -84683677,470639,137 -84683678,470776,154 -84683679,470930,131 -84683680,471061,121 -84683681,471182,158 -84683682,471340,142 -84683683,471482,186 -84683684,471668,159 -84683685,471827,147 -84683686,471974,114 -84683687,472088,212 -84683688,472300,165 -84683689,472465,189 -84683690,472654,169 -84683691,472823,221 -84683692,473044,146 -84683693,473190,133 -84683694,473323,150 -84683695,473473,116 -84683696,473589,110 -84683697,473699,133 -84683698,473832,165 -84683699,473997,146 -84683700,474143,176 -84683701,474319,209 -84683702,474528,182 -84683703,474710,192 -84683704,474902,125 -84683705,475027,154 -84683706,475181,180 -84683707,475361,188 -84683708,475549,144 -84683709,475693,119 -84683710,475812,148 -84683711,475960,166 -84683712,476126,216 -84683713,476342,168 -84683714,476510,179 -84683715,476689,166 -84683716,476855,158 -84683717,477013,167 -84683718,477180,254 -84683719,477434,134 -84683720,477568,148 -84683721,477716,163 -84683722,477879,170 -84683723,478049,141 -84683724,478190,193 -84683725,478383,170 -84683726,478553,149 -84683727,478702,180 -84683728,478882,123 -84683729,479005,205 -84683730,479210,125 -84683731,479335,191 -84683732,479526,175 -84683733,479701,152 -84683734,479853,145 -84683735,479998,138 -84683736,480136,152 -84683737,480288,162 -84683738,480450,164 -84683739,480614,134 -84683740,480748,139 -84683742,480887,166 -84683743,481053,159 -84683744,481212,172 -84683745,481384,131 -84683746,481515,155 -84683747,481670,149 -84683748,481819,134 -84683749,481953,151 -84683750,482104,155 -84683751,482259,156 -84683752,482415,193 -84683753,482608,137 -84683754,482745,151 -84683755,482896,160 -84683756,483056,157 -84683757,483213,174 -84683758,483387,56 -84683759,483443,260 -84683760,483703,120 -84683761,483823,164 -84683762,483987,154 -84683763,484141,129 -84683764,484270,246 -84683765,484516,160 -84683766,484676,152 -84683767,484828,166 -84683768,484994,142 -84683769,485136,142 -84683770,485278,166 -84683771,485444,116 -84683772,485560,149 -84683773,485709,170 -84683774,485879,163 -84683775,486042,128 -84683776,486170,139 -84683777,486309,162 -84683778,486471,181 -84683779,486652,174 -84683780,486826,117 -84683781,486943,180 -84683782,487123,122 -84683783,487245,192 -84683784,487437,138 -84683785,487575,152 -84683786,487727,312 -84683787,488039,140 -84683788,488179,130 -84683789,488309,125 -84683790,488434,140 -84683791,488574,139 -84683792,488713,145 -84683793,488858,178 -84683794,489036,172 -84683795,489208,140 -84683796,489348,165 -84683797,489513,172 -84683798,489685,143 -84683799,489828,161 -84683800,489989,156 -84683801,490145,148 -84683802,490293,158 -84683803,490451,151 -84683804,490602,150 -84683805,490752,177 -84683806,490929,133 -84683807,491062,203 -84683808,491265,159 -84683809,491424,56 -84683810,491480,159 -84683811,491639,134 -84683812,491773,155 -84683813,491928,56 -84683814,491984,198 -84683815,492182,136 -84683816,492318,152 -84683817,492470,153 -84683818,492623,166 -84683819,492789,164 -84683820,492953,146 -84683821,493099,220 -84683822,493319,151 -84683823,493470,140 -84683824,493610,143 -84683825,493753,185 -84683826,493938,150 -84683828,494088,122 -84683829,494210,140 -84683830,494350,124 -84683831,494474,202 -84683832,494676,185 -84683833,494861,128 -84683834,494989,134 -84683835,495123,172 -84683836,495295,144 -84683837,495439,218 -84683838,495657,120 -84683839,495777,170 -84683840,495947,155 -84683841,496102,131 -84683842,496233,154 -84683843,496387,150 -84683844,496537,227 -84683845,496764,191 -84683846,496955,154 -84683847,497109,221 -84683848,497330,156 -84683849,497486,146 -84683850,497632,222 -84683851,497854,155 -84683852,498009,159 -84683853,498168,171 -84683854,498339,130 -84683855,498469,132 -84683856,498601,182 -84683857,498783,170 -84683858,498953,153 -84683859,499106,150 -84683860,499256,143 -84683861,499399,148 -84683862,499547,162 -84683863,499709,162 -84683864,499871,159 -84683865,500030,127 -84683866,500157,135 -84683867,500292,147 -84683868,500439,152 -84683869,500591,122 -84683870,500713,186 -84683871,500899,169 -84683872,501068,216 -84683873,501284,160 -84683874,501444,203 -84683875,501647,178 -84683876,501825,183 -84683877,502008,210 -84683878,502218,180 -84683879,502398,171 -84683880,502569,175 -84683881,502744,164 -84683882,502908,169 -84683883,503077,150 -84683884,503227,167 -84683885,503394,177 -84683886,503571,134 -84683887,503705,177 -84683888,503882,147 -84683889,504029,191 -84683890,504220,116 -84683891,504336,170 -84683892,504506,136 -84683893,504642,133 -84683894,504775,123 -84683895,504898,175 -84683896,505073,124 -84683897,505197,191 -84683898,505388,134 -84683899,505522,149 -84683900,505671,169 -84683901,505840,158 -84683902,505998,159 -84683903,506157,162 -84683904,506319,145 -84683905,506464,174 -84683906,506638,144 -84683907,506782,139 -84683908,506921,115 -84683909,507036,165 -84683910,507201,195 -84683911,507396,152 -84683912,507548,201 -84683913,507749,151 -84683914,507900,173 -84683915,508073,107 -84683916,508180,161 -84683917,508341,176 -84683918,508517,109 -84683919,508626,145 -84683920,508771,122 -84683921,508893,174 -84683922,509067,129 -84683923,509196,139 -84683924,509335,155 -84683925,509490,127 -84683926,509617,135 -84683927,509752,176 -84683928,509928,177 -84683929,510105,168 -84683930,510273,143 -84683931,510416,173 -84683932,510589,154 -84683933,510743,138 -84683934,510881,166 -84683935,511047,132 -84683936,511179,158 -84683937,511337,203 -84683938,511540,153 -84683939,511693,142 -84683940,511835,145 -84683941,511980,143 -84683942,512123,139 -84683943,512262,167 -84683944,512429,185 -84683945,512614,165 -84683946,512779,186 -84683947,512965,167 -84683948,513132,177 -84683949,513309,162 -84683950,513471,174 -84683951,513645,129 -84683952,513774,125 -84683953,513899,158 -84683954,514057,145 -84683955,514202,166 -84683956,514368,155 -84683957,514523,56 -84683958,514579,135 -84683959,514714,128 -84683960,514842,129 -84683961,514971,130 -84683962,515101,155 -84683963,515256,129 -84683964,515385,156 -84683965,515541,152 -84683966,515693,148 -84683967,515841,132 -84683968,515973,186 -84683969,516159,164 -84683970,516323,144 -84683971,516467,149 -84683972,516616,165 -84683973,516781,132 -84683974,516913,172 -84683975,517085,209 -84683976,517294,56 -84683977,517350,130 -84683978,517480,169 -84683979,517649,158 -84683980,517807,168 -84683981,517975,181 -84683982,518156,163 -84683983,518319,194 -84683984,518513,163 -84683985,518676,137 -84683986,518813,150 -84683987,518963,123 -84683988,519086,131 -84683989,519217,150 -84683990,519367,160 -84683991,519527,154 -84683992,519681,204 -84683993,519885,179 -84683994,520064,128 -84683995,520192,137 -84683996,520329,305 -84683997,520634,163 -84683998,520797,160 -84683999,520957,196 -84684000,521153,170 -84684001,521323,141 -84684002,521464,134 -84684003,521598,210 -84684004,521808,144 -84684005,521952,139 -84684006,522091,154 -84684007,522245,136 -84684008,522381,146 -84684009,522527,56 -84684010,522583,145 -84684011,522728,162 -84684012,522890,155 -84684013,523045,195 -84684014,523240,118 -84684015,523358,224 -84684016,523582,134 -84684017,523716,138 -84684018,523854,178 -84684019,524032,165 -84684020,524197,178 -84684021,524375,142 -84684022,524517,130 -84684023,524647,202 -84684024,524849,162 -84684025,525011,169 -84684026,525180,134 -84684027,525314,177 -84684028,525491,141 -84684029,525632,154 -84684030,525786,167 -84684031,525953,158 -84684032,526111,190 -84684033,526301,173 -84684034,526474,165 -84684035,526639,157 -84684036,526796,146 -84684038,526942,160 -84684039,527102,123 -84684040,527225,188 -84684041,527413,175 -84684042,527588,177 -84684043,527765,158 -84684044,527923,154 -84684045,528077,157 -84684046,528234,173 -84684047,528407,154 -84684048,528561,206 -84684049,528767,208 -84684050,528975,146 -84684051,529121,153 -84684052,529274,131 -84684053,529405,155 -84684054,529560,175 -84684055,529735,124 -84684056,529859,142 -84684057,530001,222 -84684058,530223,130 -84684059,530353,138 -84684060,530491,151 -84684061,530642,156 -84684062,530798,161 -84684063,530959,158 -84684064,531117,107 -84684065,531224,166 -84684066,531390,161 -84684067,531551,176 -84684068,531727,188 -84684069,531915,138 -84684070,532053,120 -84684071,532173,127 -84684072,532300,220 -84684073,532520,142 -84684074,532662,176 -84684075,532838,186 -84684076,533024,170 -84684077,533194,161 -84684078,533355,248 -84684079,533603,141 -84684080,533744,187 -84684081,533931,165 -84684082,534096,162 -84684083,534258,139 -84684084,534397,201 -84684085,534598,156 -84684086,534754,147 -84684087,534901,169 -84684088,535070,164 -84684089,535234,126 -84684090,535360,150 -84684091,535510,178 -84684092,535688,183 -84684093,535871,191 -84684094,536062,183 -84684095,536245,130 -84684096,536375,130 -84684097,536505,170 -84684098,536675,137 -84684099,536812,135 -84684100,536947,154 -84684101,537101,138 -84684102,537239,174 -84684103,537413,166 -84684104,537579,209 -84684105,537788,138 -84684106,537926,129 -84684107,538055,147 -84684108,538202,162 -84684109,538364,184 -84684110,538548,145 -84684111,538693,121 -84684112,538814,164 -84684113,538978,139 -84684114,539117,176 -84684115,539293,134 -84684116,539427,137 -84684117,539564,155 -84684118,539719,197 -84684119,539916,148 -84684120,540064,137 -84684121,540201,134 -84684122,540335,206 -84684123,540541,140 -84684124,540681,160 -84684125,540841,146 -84684126,540987,149 -84684127,541136,219 -84684128,541355,171 -84684129,541526,128 -84684130,541654,129 -84684131,541783,141 -84684132,541924,125 -84684133,542049,149 -84684134,542198,168 -84684135,542366,146 -84684136,542512,146 -84684137,542658,182 -84684138,542840,212 -84684139,543052,139 -84684140,543191,218 -84684141,543409,182 -84684142,543591,158 -84684143,543749,169 -84684144,543918,178 -84684145,544096,129 -84684146,544225,152 -84684147,544377,154 -84684148,544531,164 -84684149,544695,136 -84684150,544831,118 -84684151,544949,121 -84684152,545070,154 -84684153,545224,155 -84684154,545379,139 -84684155,545518,121 -84684156,545639,200 -84684157,545839,171 -84684158,546010,137 -84684159,546147,139 -84684160,546286,145 -84684161,546431,131 -84684162,546562,157 -84684163,546719,134 -84684164,546853,306 -84684165,547159,117 -84684166,547276,147 -84684167,547423,182 -84684168,547605,168 -84684169,547773,197 -84684170,547970,188 -84684171,548158,134 -84684172,548292,131 -84684173,548423,159 -84684174,548582,190 -84684175,548772,115 -84684176,548887,139 -84684177,549026,123 -84684178,549149,140 -84684179,549289,116 -84684180,549405,167 -84684181,549572,135 -84684182,549707,130 -84684183,549837,149 -84684184,549986,195 -84684185,550181,151 -84684186,550332,154 -84684187,550486,156 -84684188,550642,157 -84684189,550799,201 -84684190,551000,176 -84684191,551176,161 -84684192,551337,158 -84684193,551495,164 -84684194,551659,149 -84684195,551808,187 -84684196,551995,166 -84684197,552161,153 -84684198,552314,155 -84684199,552469,137 -84684200,552606,148 -84684201,552754,161 -84684202,552915,170 -84684203,553085,192 -84684204,553277,140 -84684205,553417,145 -84684206,553562,161 -84684207,553723,151 -84684208,553874,164 -84684209,554038,151 -84684210,554189,144 -84684211,554333,198 -84684212,554531,196 -84684213,554727,186 -84684214,554913,181 -84684215,555094,155 -84684216,555249,148 -84684217,555397,165 -84684218,555562,145 -84684219,555707,153 -84684220,555860,211 -84684221,556071,124 -84684222,556195,208 -84684223,556403,187 -84684224,556590,213 -84684225,556803,190 -84684226,556993,173 -84684227,557166,174 -84684228,557340,145 -84684229,557485,154 -84684230,557639,181 -84684231,557820,163 -84684232,557983,129 -84684233,558112,136 -84684234,558248,140 -84684235,558388,142 -84684236,558530,192 -84684237,558722,137 -84684238,558859,118 -84684239,558977,165 -84684240,559142,167 -84684241,559309,134 -84684242,559443,177 -84684243,559620,166 -84684244,559786,131 -84684245,559917,213 -84684246,560130,172 -84684247,560302,167 -84684248,560469,176 -84684249,560645,136 -84684250,560781,173 -84684251,560954,117 -84684252,561071,146 -84684253,561217,162 -84684254,561379,132 -84684255,561511,128 -84684256,561639,199 -84684257,561838,306 -84684258,562144,134 -84684259,562278,154 -84684260,562432,193 -84684261,562625,105 -84684262,562730,129 -84684263,562859,122 -84684264,562981,144 -84684265,563125,132 -84684266,563257,155 -84684267,563412,143 -84684268,563555,159 -84684269,563714,132 -84684271,563846,125 -84684272,563971,184 -84684273,564155,154 -84684274,564309,159 -84684275,564468,131 -84684276,564599,164 -84684277,564763,141 -84684278,564904,153 -84684279,565057,115 -84684280,565172,165 -84684281,565337,127 -84684282,565464,136 -84684283,565600,130 -84684284,565730,178 -84684285,565908,170 -84684286,566078,171 -84684287,566249,140 -84684288,566389,194 -84684289,566583,164 -84684290,566747,137 -84684291,566884,163 -84684292,567047,175 -84684293,567222,127 -84684294,567349,149 -84684295,567498,172 -84684296,567670,159 -84684297,567829,130 -84684298,567959,134 -84684299,568093,157 -84684300,568250,192 -84684301,568442,131 -84684302,568573,161 -84684303,568734,129 -84684304,568863,185 -84684305,569048,143 -84684306,569191,156 -84684307,569347,170 -84684308,569517,190 -84684309,569707,150 -84684310,569857,135 -84684311,569992,155 -84684312,570147,287 -84684313,570434,134 -84684314,570568,212 -84684315,570780,153 -84684316,570933,154 -84684317,571087,203 -84684318,571290,150 -84684319,571440,145 -84684320,571585,163 -84684321,571748,113 -84684322,571861,180 -84684323,572041,117 -84684324,572158,167 -84684325,572325,137 -84684326,572462,125 -84684327,572587,140 -84684328,572727,135 -84684329,572862,127 -84684330,572989,169 -84684331,573158,187 -84684332,573345,174 -84684333,573519,162 -84684334,573681,134 -84684335,573815,168 -84684336,573983,163 -84684337,574146,189 -84684338,574335,149 -84684339,574484,189 -84684340,574673,161 -84684341,574834,151 -84684342,574985,154 -84684343,575139,182 -84684344,575321,133 -84684345,575454,141 -84684346,575595,178 -84684347,575773,214 -84684348,575987,134 -84684349,576121,178 -84684350,576299,154 -84684351,576453,139 -84684352,576592,134 -84684353,576726,143 -84684354,576869,140 -84684355,577009,158 -84684356,577167,169 -84684357,577336,153 -84684358,577489,162 -84684359,577651,122 -84684360,577773,167 -84684361,577940,205 -84684362,578145,182 -84684363,578327,169 -84684364,578496,181 -84684365,578677,120 -84684366,578797,228 -84684367,579025,181 -84684368,579206,126 -84684369,579332,146 -84684370,579478,147 -84684371,579625,210 -84684372,579835,154 -84684373,579989,136 -84684374,580125,182 -84684375,580307,143 -84684376,580450,139 -84684377,580589,154 -84684378,580743,131 -84684379,580874,183 -84684380,581057,186 -84684381,581243,143 -84684382,581386,118 -84684383,581504,176 -84684384,581680,176 -84684385,581856,147 -84684386,582003,167 -84684387,582170,132 -84684388,582302,130 -84684389,582432,158 -84684390,582590,129 -84684391,582719,152 -84684392,582871,192 -84684393,583063,156 -84684394,583219,194 -84684395,583413,140 -84684396,583553,244 -84684397,583797,124 -84684398,583921,167 -84684399,584088,148 -84684400,584236,169 -84684401,584405,172 -84684403,584577,179 -84684404,584756,146 -84684405,584902,137 -84684406,585039,232 -84684407,585271,127 -84684408,585398,185 -84684409,585583,180 -84684410,585763,133 -84684411,585896,144 -84684412,586040,151 -84684413,586191,182 -84684414,586373,135 -84684415,586508,141 -84684416,586649,154 -84684417,586803,181 -84684418,586984,168 -84684419,587152,178 -84684420,587330,313 -84684421,587643,167 -84684422,587810,190 -84684423,588000,153 -84684424,588153,149 -84684425,588302,163 -84684426,588465,132 -84684427,588597,179 -84684428,588776,130 -84684429,588906,146 -84684430,589052,183 -84684431,589235,145 -84684432,589380,202 -84684433,589582,186 -84684434,589768,142 -84684435,589910,167 -84684436,590077,136 -84684437,590213,232 -84684438,590445,170 -84684439,590615,198 -84684440,590813,165 -84684441,590978,162 -84684442,591140,151 -84684443,591291,159 -84684444,591450,132 -84684445,591582,127 -84684446,591709,164 -84684447,591873,173 -84684448,592046,182 -84684449,592228,140 -84684450,592368,146 -84684451,592514,166 -84684452,592680,148 -84684453,592828,149 -84684454,592977,125 -84684455,593102,154 -84684456,593256,158 -84684457,593414,149 -84684458,593563,141 -84684459,593704,160 -84684460,593864,166 -84684461,594030,181 -84684462,594211,145 -84684463,594356,146 -84684464,594502,190 -84684465,594692,145 -84684466,594837,169 -84684467,595006,178 -84684468,595184,197 -84684469,595381,123 -84684470,595504,172 -84684471,595676,130 -84684472,595806,116 -84684473,595922,126 -84684474,596048,179 -84684475,596227,166 -84684476,596393,152 -84684477,596545,176 -84684478,596721,166 -84684479,596887,131 -84684480,597018,165 -84684481,597183,130 -84684482,597313,141 -84684483,597454,194 -84684484,597648,184 -84684485,597832,195 -84684486,598027,205 -84684487,598232,158 -84684488,598390,166 -84684489,598556,178 -84684490,598734,147 -84684491,598881,141 -84684492,599022,154 -84684493,599176,165 -84684494,599341,148 -84684495,599489,194 -84684496,599683,187 -84684497,599870,149 -84684498,600019,134 -84684499,600153,208 -84684500,600361,181 -84684501,600542,161 -84684502,600703,140 -84684503,600843,146 -84684504,600989,174 -84684505,601163,154 -84684506,601317,206 -84684507,601523,139 -84684508,601662,165 -84684509,601827,128 -84684510,601955,141 -84684511,602096,169 -84684512,602265,177 -84684513,602442,150 -84684514,602592,177 -84684515,602769,140 -84684516,602909,161 -84684517,603070,154 -84684518,603224,137 -84684519,603361,132 -84684520,603493,170 -84684521,603663,133 -84684522,603796,184 -84684523,603980,147 -84684524,604127,152 -84684525,604279,185 -84684526,604464,305 -84684527,604769,138 -84684528,604907,167 -84684529,605074,154 -84684530,605228,164 -84684531,605392,200 -84684532,605592,152 -84684533,605744,175 -84684534,605919,204 -84684535,606123,173 -84684536,606296,140 -84684537,606436,122 -84684538,606558,166 -84684539,606724,128 -84684540,606852,56 -84684541,606908,109 -84684542,607017,191 -84684543,607208,167 -84684544,607375,152 -84684545,607527,146 -84684546,607673,123 -84684547,607796,151 -84684548,607947,201 -84684549,608148,144 -84684550,608292,141 -84684551,608433,159 -84684552,608592,194 -84684553,608786,158 -84684554,608944,178 -84684555,609122,171 -84684556,609293,175 -84684557,609468,128 -84684558,609596,130 -84684559,609726,186 -84684560,609912,158 -84684561,610070,129 -84684562,610199,188 -84684563,610387,157 -84684564,610544,149 -84684565,610693,174 -84684566,610867,200 -84684567,611067,303 -84684568,611370,139 -84684569,611509,223 -84684570,611732,160 -84684571,611892,154 -84684572,612046,178 -84684573,612224,158 -84684574,612382,133 -84684575,612515,150 -84684576,612665,153 -84684577,612818,144 -84684578,612962,164 -84684579,613126,153 -84684580,613279,148 -84684581,613427,157 -84684582,613584,136 -84684583,613720,121 -84684584,613841,157 -84684585,613998,159 -84684586,614157,137 -84684587,614294,172 -84684588,614466,159 -84684589,614625,196 -84684590,614821,151 -84684591,614972,143 -84684592,615115,113 -84684593,615228,158 -84684594,615386,128 -84684595,615514,180 -84684596,615694,144 -84684597,615838,134 -84684598,615972,122 -84684599,616094,207 -84684600,616301,141 -84684601,616442,163 -84684602,616605,154 -84684603,616759,132 -84684604,616891,145 -84684605,617036,148 -84684606,617184,140 -84684607,617324,160 -84684608,617484,157 -84684609,617641,171 -84684610,617812,126 -84684611,617938,193 -84684612,618131,175 -84684613,618306,166 -84684614,618472,178 -84684615,618650,135 -84684616,618785,207 -84684617,618992,148 -84684618,619140,158 -84684619,619298,112 -84684620,619410,176 -84684621,619586,171 -84684622,619757,158 -84684623,619915,194 -84684624,620109,172 -84684625,620281,179 -84684626,620460,174 -84684627,620634,254 -84684628,620888,156 -84684629,621044,169 -84684630,621213,172 -84684631,621385,164 -84684632,621549,123 -84684633,621672,147 -84684634,621819,175 -84684635,621994,154 -84684636,622148,186 -84684637,622334,192 -84684638,622526,166 -84684639,622692,200 -84684640,622892,145 -84684641,623037,168 -84684642,623205,129 -84684643,623334,118 -84684644,623452,178 -84684645,623630,137 -84684646,623767,145 -84684647,623912,138 -84684648,624050,138 -84684649,624188,178 -84684650,624366,149 -84684651,624515,157 -84684652,624672,170 -84684653,624842,173 -84684654,625015,139 -84684655,625154,194 -84684656,625348,163 -84684657,625511,151 -84684658,625662,130 -84684659,625792,126 -84684660,625918,164 -84684661,626082,154 -84684662,626236,190 -84684663,626426,150 -84684664,626576,146 -84684665,626722,126 -84684666,626848,128 -84684667,626976,149 -84684668,627125,160 -84684669,627285,220 -84684670,627505,207 -84684671,627712,155 -84684672,627867,158 -84684673,628025,140 -84684674,628165,171 -84684675,628336,152 -84684676,628488,148 -84684677,628636,137 -84684678,628773,157 -84684679,628930,139 -84684680,629069,160 -84684681,629229,149 -84684682,629378,129 -84684683,629507,177 -84684684,629684,217 -84684685,629901,226 -84684686,630127,168 -84684687,630295,151 -84684688,630446,174 -84684689,630620,136 -84684690,630756,149 -84684691,630905,178 -84684692,631083,167 -84684693,631250,218 -84684694,631468,148 -84684695,631616,134 -84684696,631750,171 -84684697,631921,175 -84684698,632096,118 -84684699,632214,201 -84684700,632415,146 -84684701,632561,224 -84684702,632785,147 -84684703,632932,236 -84684704,633168,170 -84684705,633338,143 -84684706,633481,141 -84684707,633622,129 -84684709,633751,172 -84684710,633923,158 -84684711,634081,149 -84684712,634230,184 -84684713,634414,139 -84684714,634553,151 -84684715,634704,194 -84684716,634898,128 -84684717,635026,147 -84684718,635173,276 -84684719,635449,171 -84684720,635620,156 -84684721,635776,141 -84684722,635917,181 -84684723,636098,142 -84684724,636240,145 -84684725,636385,203 -84684726,636588,155 -84684727,636743,147 -84684728,636890,156 -84684729,637046,132 -84684730,637178,169 -84684731,637347,115 -84684732,637462,163 -84684733,637625,179 -84684734,637804,157 -84684735,637961,174 -84684736,638135,181 -84684737,638316,146 -84684738,638462,116 -84684739,638578,165 -84684740,638743,131 -84684741,638874,163 -84684742,639037,149 -84684743,639186,141 -84684744,639327,181 -84684745,639508,144 -84684746,639652,166 -84684747,639818,226 -84684748,640044,139 -84684749,640183,178 -84684750,640361,160 -84684751,640521,192 -84684752,640713,161 -84684753,640874,128 -84684754,641002,153 -84684755,641155,173 -84684756,641328,143 -84684757,641471,161 -84684758,641632,166 -84684759,641798,149 -84684760,641947,149 -84684761,642096,179 -84684762,642275,121 -84684763,642396,155 -84684764,642551,161 -84684765,642712,164 -84684766,642876,136 -84684767,643012,137 -84684768,643149,132 -84684769,643281,137 -84684770,643418,177 -84684771,643595,56 -84684772,643651,176 -84684773,643827,140 -84684774,643967,125 -84684775,644092,148 -84684776,644240,149 -84684777,644389,158 -84684778,644547,182 -84684779,644729,142 -84684780,644871,230 -84684781,645101,133 -84684782,645234,147 -84684783,645381,197 -84684784,645578,172 -84684785,645750,167 -84684786,645917,146 -84684787,646063,140 -84684788,646203,144 -84684789,646347,288 -84684790,646635,176 -84684791,646811,168 -84684792,646979,162 -84684793,647141,136 -84684794,647277,147 -84684795,647424,133 -84684796,647557,170 -84684797,647727,167 -84684798,647894,164 -84684799,648058,166 -17406709760,648224,132 -17406709761,648356,152 -17406709762,648508,209 -17406709763,648717,148 -17406709764,648865,160 -17406709765,649025,146 -17406709766,649171,183 -17406709767,649354,157 -17406709768,649511,198 -17406709769,649709,179 -17406709770,649888,175 -17406709771,650063,144 -17406709772,650207,194 -17406709773,650401,174 -17406709774,650575,192 -17406709775,650767,159 -17406709776,650926,157 -17406709777,651083,167 -17406709778,651250,139 -17406709779,651389,158 -17406709780,651547,185 -17406709781,651732,122 -17406709782,651854,141 -17406709783,651995,142 -17406709784,652137,132 -17406709785,652269,155 -17406709786,652424,168 -17406709787,652592,150 -17406709788,652742,159 -17406709789,652901,154 -17406709790,653055,102 -17406709791,653157,153 -17406709792,653310,221 -17406709793,653531,126 -17406709794,653657,162 -17406709795,653819,259 -17406709796,654078,186 -17406709797,654264,169 -17406709798,654433,152 -17406709799,654585,151 -17406709800,654736,156 -17406709801,654892,160 -17406709802,655052,137 -17406709803,655189,133 -17406709804,655322,150 -17406709805,655472,132 -17406709806,655604,218 -17406709807,655822,141 -17406709808,655963,196 -17406709809,656159,134 -17406709810,656293,123 -17406709811,656416,155 -17406709812,656571,132 -17406709813,656703,169 -17406709814,656872,182 -17406709815,657054,171 -17406709816,657225,177 -17406709817,657402,149 -17406709818,657551,184 -17406709819,657735,168 -17406709820,657903,194 -17406709821,658097,151 -17406709822,658248,215 -17406709823,658463,238 -17406709824,658701,188 -17406709825,658889,166 -17406709826,659055,175 -17406709827,659230,159 -17406709828,659389,212 -17406709829,659601,185 -17406709830,659786,149 -17406709831,659935,130 -17406709832,660065,186 -17406709833,660251,167 -17406709834,660418,188 -17406709835,660606,226 -17406709836,660832,176 -17406709837,661008,156 -17406709838,661164,217 -17406709839,661381,189 -17406709840,661570,157 -17406709841,661727,200 -17406709842,661927,217 -17406709843,662144,192 -17406709844,662336,130 -17406709845,662466,198 -17406709846,662664,127 -17406709847,662791,143 -17406709848,662934,162 -17406709849,663096,191 -17406709850,663287,188 -17406709851,663475,164 -17406709852,663639,212 -17406709853,663851,145 -17406709854,663996,129 -17406709855,664125,141 -17406709856,664266,192 -17406709857,664458,127 -17406709858,664585,166 -17406709859,664751,146 -17406709860,664897,223 -17406709861,665120,151 -17406709862,665271,144 -17406709863,665415,155 -17406709864,665570,150 -17406709865,665720,173 -17406709866,665893,122 -17406709867,666015,172 -17406709868,666187,161 -17406709869,666348,155 -17406709870,666503,166 -17406709871,666669,161 -17406709872,666830,176 -17406709873,667006,131 -17406709874,667137,148 -17406709875,667285,173 -17406709876,667458,145 -17406709877,667603,134 -17406709878,667737,199 -17406709879,667936,157 -17406709880,668093,148 -17406709881,668241,153 -17406709882,668394,120 -17406709883,668514,211 -17406709884,668725,166 -17406709885,668891,263 -17406709886,669154,142 -17406709887,669296,158 -17406709888,669454,135 -17406709889,669589,128 -17406709890,669717,121 -17406709891,669838,156 -17406709892,669994,197 -17406709893,670191,160 -17406709894,670351,178 -17406709895,670529,144 -17406709896,670673,188 -17406709897,670861,199 -17406709898,671060,159 -17406709899,671219,147 -17406709900,671366,141 -17406709901,671507,165 -17406709902,671672,148 -17406709903,671820,127 -17406709904,671947,207 -17406709905,672154,173 -17406709906,672327,139 -17406709907,672466,154 -17406709908,672620,161 -17406709909,672781,152 -17406709910,672933,153 -17406709911,673086,191 -17406709912,673277,124 -17406709913,673401,167 -17406709914,673568,191 -17406709915,673759,157 -17406709916,673916,159 -17406709917,674075,135 -17406709918,674210,163 -17406709919,674373,144 -17406709920,674517,143 -17406709921,674660,179 -17406709922,674839,125 -17406709923,674964,135 -17406709924,675099,184 -17406709925,675283,172 -17406709926,675455,231 -17406709927,675686,200 -17406709928,675886,180 -17406709929,676066,137 -17406709930,676203,184 -17406709931,676387,171 -17406709932,676558,126 -17406709933,676684,145 -17406709934,676829,179 -17406709935,677008,148 -17406709936,677156,134 -17406709937,677290,268 -17406709938,677558,205 -17406709939,677763,121 -17406709940,677884,209 -17406709941,678093,189 -17406709942,678282,137 -17406709943,678419,137 -17406709944,678556,155 -17406709945,678711,250 -17406709946,678961,137 -17406709947,679098,148 -17406709948,679246,197 -17406709949,679443,144 -17406709950,679587,189 -17406709951,679776,216 -17406709952,679992,131 -17406709953,680123,199 -17406709954,680322,187 -17406709955,680509,157 -17406709956,680666,140 -17406709957,680806,137 -17406709958,680943,129 -17406709959,681072,152 -17406709960,681224,145 -17406709961,681369,124 -17406709962,681493,126 -17406709963,681619,131 -17406709964,681750,124 -17406709965,681874,166 -17406709966,682040,140 -17406709967,682180,145 -17406709968,682325,120 -17406709969,682445,138 -17406709970,682583,121 -17406709971,682704,152 -17406709972,682856,185 -17406709973,683041,184 -17406709974,683225,173 -17406709975,683398,178 -17406709976,683576,162 -17406709977,683738,180 -17406709978,683918,120 -17406709979,684038,126 -17406709980,684164,157 -17406709981,684321,192 -17406709982,684513,103 -17406709983,684616,133 -17406709984,684749,130 -17406709985,684879,163 -17406709986,685042,142 -17406709987,685184,150 -17406709988,685334,156 -17406709989,685490,153 -17406709990,685643,172 -17406709991,685815,168 -17406709992,685983,133 -17406709993,686116,123 -17406709994,686239,125 -17406709995,686364,150 -17406709996,686514,169 -17406709997,686683,164 -17406709998,686847,139 -17406709999,686986,150 -17406710000,687136,149 -17406710001,687285,157 -17406710002,687442,157 -17406710003,687599,163 -17406710004,687762,152 -17406710005,687914,131 -17406710006,688045,56 -17406710007,688101,190 -17406710008,688291,143 -17406710009,688434,153 -17406710010,688587,129 -17406710011,688716,179 -17406710012,688895,151 -17406710013,689046,154 -17406710014,689200,162 -17406710015,689362,175 -17406710016,689537,199 -17406710017,689736,152 -17406710018,689888,149 -17406710019,690037,160 -17406710020,690197,229 -17406710021,690426,161 -17406710022,690587,118 -17406710023,690705,138 -17406710024,690843,159 -17406710025,691002,212 -17406710026,691214,149 -17406710027,691363,189 -17406710028,691552,158 -17406710029,691710,194 -17406710030,691904,166 -17406710031,692070,149 -17406710032,692219,192 -17406710033,692411,147 -17406710034,692558,197 -17406710035,692755,169 -17406710036,692924,184 -17406710037,693108,147 -17406710038,693255,143 -17406710039,693398,187 -17406710040,693585,226 -17406710041,693811,189 -17406710042,694000,128 -17406710043,694128,133 -17406710044,694261,169 -17406710045,694430,137 -17406710046,694567,152 -17406710047,694719,161 -17406710048,694880,132 -17406710049,695012,235 -17406710050,695247,150 -17406710051,695397,196 -17406710052,695593,134 -17406710053,695727,120 -17406710054,695847,150 -17406710055,695997,165 -17406710056,696162,127 -17406710057,696289,178 -17406710058,696467,218 -17406710059,696685,149 -17406710060,696834,181 -17406710061,697015,132 -17406710062,697147,163 -17406710063,697310,56 -17406710064,697366,152 -17406710065,697518,129 -17406710066,697647,191 -17406710067,697838,126 -17406710068,697964,161 -17406710069,698125,146 -17406710070,698271,137 -17406710071,698408,131 -17406710072,698539,167 -17406710073,698706,198 -17406710074,698904,233 -17406710075,699137,211 -17406710076,699348,249 -17406710077,699597,257 -17406710078,699854,181 -17406710079,700035,212 -17406710080,700247,180 -17406710081,700427,141 -17406710082,700568,170 -17406710083,700738,149 -17406710084,700887,138 -17406710085,701025,178 -17406710086,701203,172 -17406710087,701375,197 -17406710088,701572,151 -17406710089,701723,154 -17406710090,701877,183 -17406710091,702060,176 -17406710092,702236,133 -17406710093,702369,143 -17406710094,702512,135 -17406710095,702647,179 -17406710096,702826,172 -17406710097,702998,243 -17406710098,703241,154 -17406710099,703395,156 -17406710100,703551,126 -17406710101,703677,160 -17406710102,703837,134 -17406710103,703971,177 -17406710104,704148,114 -17406710105,704262,127 -17406710106,704389,173 -17406710107,704562,149 -17406710108,704711,145 -17406710109,704856,155 -17406710110,705011,160 -17406710111,705171,148 -17406710112,705319,167 -17406710113,705486,145 -17406710114,705631,157 -17406710115,705788,140 -17406710116,705928,179 -17406710117,706107,134 -17406710118,706241,274 -17406710119,706515,195 -17406710120,706710,143 -17406710121,706853,140 -17406710122,706993,197 -17406710123,707190,155 -17406710124,707345,56 -17406710125,707401,172 -17406710126,707573,199 -17406710127,707772,147 -17406710128,707919,156 -17406710129,708075,128 -17406710130,708203,181 -17406710131,708384,187 -17406710132,708571,123 -17406710133,708694,154 -17406710134,708848,199 -17406710135,709047,153 -17406710136,709200,153 -17406710137,709353,134 -17406710138,709487,156 -17406710139,709643,118 -17406710140,709761,142 -17406710141,709903,135 -17406710142,710038,139 -17406710143,710177,137 -17406710144,710314,153 -17406710145,710467,125 -17406710146,710592,140 -17406710147,710732,129 -17406710148,710861,126 -17406710149,710987,174 -17406710150,711161,162 -17406710151,711323,156 -17406710152,711479,142 -17406710153,711621,166 -17406710154,711787,197 -17406710155,711984,172 -17406710156,712156,118 -17406710157,712274,145 -17406710158,712419,225 -17406710159,712644,173 -17406710160,712817,197 -17406710161,713014,156 -17406710162,713170,183 -17406710163,713353,170 -17406710164,713523,141 -17406710165,713664,150 -17406710166,713814,163 -17406710167,713977,159 -17406710168,714136,131 -17406710169,714267,163 -17406710170,714430,171 -17406710171,714601,170 -17406710172,714771,160 -17406710173,714931,129 -17406710174,715060,148 -17406710175,715208,132 -17406710176,715340,161 -17406710177,715501,167 -17406710178,715668,224 -17406710179,715892,171 -17406710180,716063,120 -17406710181,716183,162 -17406710182,716345,164 -17406710183,716509,218 -17406710184,716727,163 -17406710185,716890,162 -17406710186,717052,234 -17406710187,717286,212 -17406710188,717498,121 -17406710189,717619,156 -17406710190,717775,167 -17406710191,717942,173 -17406710192,718115,186 -17406710193,718301,136 -17406710194,718437,158 -17406710195,718595,123 -17406710196,718718,161 -17406710197,718879,163 -17406710198,719042,147 -17406710199,719189,157 -17406710200,719346,173 -17406710201,719519,185 -17406710202,719704,236 -17406710203,719940,198 -17406710204,720138,221 -17406710205,720359,122 -17406710206,720481,136 -17406710207,720617,230 -17406710208,720847,139 -17406710209,720986,133 -17406710210,721119,190 -17406710211,721309,148 -17406710212,721457,209 -17406710213,721666,56 -17406710214,721722,150 -17406710215,721872,132 -17406710216,722004,164 -17406710217,722168,139 -17406710218,722307,155 -17406710219,722462,129 -17406710220,722591,129 -17406710221,722720,149 -17406710222,722869,168 -17406710223,723037,181 -17406710224,723218,127 -17406710225,723345,221 -17406710226,723566,150 -17406710227,723716,212 -17406710228,723928,147 -17406710229,724075,131 -17406710230,724206,156 -17406710231,724362,158 -17406710232,724520,190 -17406710233,724710,210 -17406710234,724920,186 -17406710235,725106,202 -17406710236,725308,194 -17406710237,725502,142 -17406710238,725644,139 -17406710239,725783,223 -17406710240,726006,194 -17406710241,726200,141 -17406710242,726341,120 -17406710243,726461,151 -17406710244,726612,146 -17406711053,726758,277 -17406713574,727035,193 diff --git a/awx/lib/site-packages/netaddr/eui/iab.txt b/awx/lib/site-packages/netaddr/eui/iab.txt deleted file mode 100644 index 7ac31a982c..0000000000 --- a/awx/lib/site-packages/netaddr/eui/iab.txt +++ /dev/null @@ -1,28589 +0,0 @@ - Generated: Tue, 31 Mar 2015 05:00:03 -0400 - - OUI Organization - IAB Range Organization - Address - - - 00-50-C2 (hex) T.L.S. Corp. - 000000-000FFF (base 16) T.L.S. Corp. - 1241 Superieor Ave E - Cleveland OH 44114 - UNITED STATES - - 00-50-C2 (hex) JMBS Developpements - 001000-001FFF (base 16) JMBS Developpements - 5, rue de la Verrerie - 38120 Le Fontanil - FRANCE - - 00-50-C2 (hex) Integrated Automation Solutions - 002000-002FFF (base 16) Integrated Automation Solutions - 111 Lakefront Drive - Hunt Valley MD 21030 - UNITED STATES - - 00-50-C2 (hex) Microsoft - 003000-003FFF (base 16) Microsoft - Bldg 32/2316 - One Microsoft Way - Redmond WA 98052 - UNITED STATES - - 00-50-C2 (hex) SCI Technology Inc. - 004000-004FFF (base 16) SCI Technology Inc. - P.O. Box 1000 - Huntsville AL 35807 - UNITED STATES - - 00-50-C2 (hex) GD California, Inc. - 005000-005FFF (base 16) GD California, Inc. - 1799 Portola Ave. - Livermore CA 94550 - UNITED STATES - - 00-50-C2 (hex) Project Management Enterprises, Inc. - 006000-006FFF (base 16) Project Management Enterprises, Inc. - 7900 Wisconsin Avenue - Suite 201 - Bethesda MD 20817 - UNITED STATES - - 00-50-C2 (hex) Clive Green & Co. Ltd. - 007000-007FFF (base 16) Clive Green & Co. Ltd. - 1 New Street - Luton Bedfordshire - England LU1 SDX - UNITED KINGDOM - - 00-50-C2 (hex) Portable Add-Ons - 008000-008FFF (base 16) Portable Add-Ons - Chineham Court, Lutyens Close - Chineham, Basingstoke - Hampshire RG24 8AH - UNITED KINGDOM - - 00-50-C2 (hex) Datakinetics Ltd. - 009000-009FFF (base 16) Datakinetics Ltd. - 21 Green Lane - Fordingbridge, Hants - SP6 1HU - UNITED KINGDOM - - 00-50-C2 (hex) Tharsys - 00A000-00AFFF (base 16) Tharsys - 3 rue Ariane-Parl - Technologique Du Canal - 31520 Rationville - FRANCE - - 00-50-C2 (hex) IO Limited - 00B000-00BFFF (base 16) IO Limited - Woodhouse Barn, - Lower End, Swattham Prior - Cambridge England CB5 QHT - UNITED KINGDOM - - 00-50-C2 (hex) Vbrick Systems Inc. - 00C000-00CFFF (base 16) Vbrick Systems Inc. - 101 N. Plains Industrial Rd. - Bldg. 1A - Wallingford CT 06492 - UNITED STATES - - 00-50-C2 (hex) Opus Telecom Inc. - 00D000-00DFFF (base 16) Opus Telecom Inc. - 11 Herbert St. - Framingham MA 01702 - UNITED STATES - - 00-50-C2 (hex) TTTech - 00E000-00EFFF (base 16) TTTech - Schoenbrunnerstrasse 7 - A-1040 Vienna - AUSTRIA - - 00-50-C2 (hex) XLN-t - 00F000-00FFFF (base 16) XLN-t - Waran De Straat 9B - B2580 Putte - BELGIUM - - 00-50-C2 (hex) Moisture Systems - 010000-010FFF (base 16) Moisture Systems - 220 Mill Rd. - Chelmsford MA 01824 - UNITED STATES - - 00-50-C2 (hex) Bihl + Wiedemann GmbH - 011000-011FFF (base 16) Bihl + Wiedemann GmbH - Flosswoerthstr 41 - Mannheim 68199 - GERMANY - - 00-50-C2 (hex) Floware System Solutions Ltd. - 012000-012FFF (base 16) Floware System Solutions Ltd. - 28 Hacharoshet St., P.O.B. 812 - Or Yehuda 60250 - ISRAEL - - 00-50-C2 (hex) Sensys Technologies Inc. - 013000-013FFF (base 16) Sensys Technologies Inc. - 8419 Terminal Rd. - Newington VA 22122 - UNITED STATES - - 00-50-C2 (hex) Canal + - 014000-014FFF (base 16) Canal + - 23, rue leblanc - Le Ponant C - Paris 75015 - FRANCE - - 00-50-C2 (hex) Leroy Automatique Industrielle - 015000-015FFF (base 16) Leroy Automatique Industrielle - Boulevard du Libre - Echange - 31650 Saint-Orens - FRANCE - - 00-50-C2 (hex) DSP Design Ltd. - 016000-016FFF (base 16) DSP Design Ltd. - Tapton Park Innovation Centre - Brimington Road, Chesterfield, - Derbyshire England S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) Hunter Technology Inc. - 017000-017FFF (base 16) Hunter Technology Inc. - 1408, Woolim e-biz Center, - 170-5, Guro-3dong, Guro-gu, - Seoul - KOREA, REPUBLIC OF - - 00-50-C2 (hex) CAD-UL GmbH - 018000-018FFF (base 16) CAD-UL GmbH - Laemmerweg 32 - D-89079 Ulm - GERMANY - - 00-50-C2 (hex) Emtac Technology Corp. - 019000-019FFF (base 16) Emtac Technology Corp. - 1F No. 22 Industry East 9 Road - Science-Based Industrial Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Skylake Talix - 01A000-01AFFF (base 16) Skylake Talix - Unit 3, Lulworth Business Ctr. - Nutwood Way, Totton - S040 Southampton 3WW - UNITED KINGDOM - - 00-50-C2 (hex) Cross Products Ltd. - 01B000-01BFFF (base 16) Cross Products Ltd. - 23 The Calls, Leeds - L52 7EH, West Yorkshire - England - UNITED KINGDOM - - 00-50-C2 (hex) Tadiran Scopus - 01C000-01CFFF (base 16) Tadiran Scopus - 5 Hatzorf St. - Holon - ISRAEL - - 00-50-C2 (hex) Princeton Gamma Tech - 01D000-01DFFF (base 16) Princeton Gamma Tech - 1010 Commerce Park Dr. - Suite G - Old Ridge TN 37830 - UNITED STATES - - 00-50-C2 (hex) CallTech International Limited - 01E000-01EFFF (base 16) CallTech International Limited - Telford Point Telford Rd. - Basingstoke Hants - RG2 6X2 - UNITED KINGDOM - - 00-50-C2 (hex) KBS Industrieelektronik GmbH - 01F000-01FFFF (base 16) KBS Industrieelektronik GmbH - Burkheimer Str. 3 - D79111 Freiburg - GERMANY - - 00-50-C2 (hex) Icon Research Ltd. - 020000-020FFF (base 16) Icon Research Ltd. - 3 Raw Holdings - East Calder, West Lothian - EH53 0HY - UNITED KINGDOM - - 00-50-C2 (hex) DRS Technologies Canada Co. - 021000-021FFF (base 16) DRS Technologies Canada Co. - 40 Concourse Gate, Nepean - Ontario K2E 8A6 - CANADA - - 00-50-C2 (hex) Ashling Microsystems Ltd. - 022000-022FFF (base 16) Ashling Microsystems Ltd. - National Technology Park - Limerick - IRELAND - - 00-50-C2 (hex) Zabacom, Inc. - 023000-023FFF (base 16) Zabacom, Inc. - 5 Choke Cherry Road - Suite 378 - Rockville MD 20850 - UNITED STATES - - 00-50-C2 (hex) IPITEK - 024000-024FFF (base 16) IPITEK - 2330 Faraday Ave - Carlsbad CA 920 - UNITED STATES - - 00-50-C2 (hex) Teracom Telematica Ltda. - 025000-025FFF (base 16) Teracom Telematica Ltda. - R. Felipe Neri, 246 CJ 301 - 90440-150 Porto Alegre RS - BRAZIL - - 00-50-C2 (hex) Abatis Systems Corp. - 026000-026FFF (base 16) Abatis Systems Corp. - 4190 Still Creek Drive - Suite 200 - Burnaby B.C. V5C 6C6 - CANADA - - 00-50-C2 (hex) Industrial Control Links - 027000-027FFF (base 16) Industrial Control Links - 12840 Earhart Ave. - Auburn CA 95602 - UNITED STATES - - 00-50-C2 (hex) The Frensch Corporation (Pty) Ltd. - 028000-028FFF (base 16) The Frensch Corporation (Pty) Ltd. - P.O. Box 21008 - Unit 1, Plot 60 - GICP Gabrone - BOTSWANA - - 00-50-C2 (hex) Grossenbacher Systeme AG - 029000-029FFF (base 16) Grossenbacher Systeme AG - Spinnereistrasse 40 - 9008 St. Gallen - SWITZERLAND - - 00-50-C2 (hex) VersaLogic Corp. - 02A000-02AFFF (base 16) VersaLogic Corp. - 3888 Stewart Rd. - Eugene OR 97402 - UNITED STATES - - 00-50-C2 (hex) Nova Engineering Inc. - 02B000-02BFFF (base 16) Nova Engineering Inc. - 5 Circle Freeway Dr. - Cincinnati OH 45426 - UNITED STATES - - 00-50-C2 (hex) Narrowband Telecommunications - 02C000-02CFFF (base 16) Narrowband Telecommunications - Unit 1A - 3751 - North Fraser Way - Burnaby BC V5J 5G4 - CANADA - - 00-50-C2 (hex) Innocor LTD - 02D000-02DFFF (base 16) Innocor LTD - 210 - 362 Terry Fox Drive - Kanata Ontario K2K 2P5 - CANADA - - 00-50-C2 (hex) Turtle Mountain Corp - 02E000-02EFFF (base 16) Turtle Mountain Corp - Box 940 - First St., S - Dunseith ND 58329 - UNITED STATES - - 00-50-C2 (hex) Sinetica Corp - 02F000-02FFFF (base 16) Sinetica Corp - Singleton Court - Wonastow Rd - Monmouth NP53AH - UNITED KINGDOM - - 00-50-C2 (hex) Lockheed Martin Tactical Defense Systems Eagan - 030000-030FFF (base 16) Lockheed Martin Tactical Defense Systems Eagan - 3333 Pilot Knob Rd - Eagan MN 55121 - UNITED STATES - - 00-50-C2 (hex) Eloquence Ltd - 031000-031FFF (base 16) Eloquence Ltd - Unit 4, Progress Business Centre - Whittle Parkway, Slough - Berkshire SL1 6DQ - UNITED KINGDOM - - 00-50-C2 (hex) MotionIO - 032000-032FFF (base 16) MotionIO - 650 Saratoga Ave - San Jose CA 95129 - UNITED STATES - - 00-50-C2 (hex) Doble Engineering Company - 033000-033FFF (base 16) Doble Engineering Company - 85 Walnut St - Watertown MA 02472 - UNITED STATES - - 00-50-C2 (hex) Ing. Buero W. Kanis GmbH - 034000-034FFF (base 16) Ing. Buero W. Kanis GmbH - Ortsteil Traubing - Brueckenweg 2 D-82327 Tutzing - GERMANY - - 00-50-C2 (hex) Alliant Techsystems, Inc. - 035000-035FFF (base 16) Alliant Techsystems, Inc. - 600 Second St NE - Mail Station 11-2881 - Hopkins MN 55343-8384 - UNITED STATES - - 00-50-C2 (hex) Arcturus Networks Inc. - 036000-036FFF (base 16) Arcturus Networks Inc. - 701 Evans Ave. - Suite 300 - Toronto Ontario M9C 1A3 - CANADA - - 00-50-C2 (hex) E.I.S.M. - 037000-037FFF (base 16) E.I.S.M. - Z.I. des Paluds - 553, Avenue des Paluds - BP 1441 13782 Aubagne Cedex - FRANCE - - 00-50-C2 (hex) Etheira Technologies - 038000-038FFF (base 16) Etheira Technologies - 104 Macintosh Street - Shepparton Victoria 3630 - AUSTRALIA - - 00-50-C2 (hex) Apex Signal Corp - 039000-039FFF (base 16) Apex Signal Corp - 3285 Vets Memorial Highway - Suite 15 - Ronkonkoma NY 11779 - UNITED STATES - - 00-50-C2 (hex) PLLB Elettronica SPA - 03A000-03AFFF (base 16) PLLB Elettronica SPA - Via Carducce 39 - 20099 Sesto San Giovanni Milano - ITALY - - 00-50-C2 (hex) VNR Electronique SA - 03B000-03BFFF (base 16) VNR Electronique SA - Avenue de France 90 - CH-1004 Lausanne - SWITZERLAND - - 00-50-C2 (hex) BrainBoxes Ltd - 03C000-03CFFF (base 16) BrainBoxes Ltd - Unit 3C, Wavertree Boulevard South - Wavertree Technology Park - Liverpool L7 9PF, England - UNITED KINGDOM - - 00-50-C2 (hex) ISDN Gateway Technology AG - 03D000-03DFFF (base 16) ISDN Gateway Technology AG - Karlstrasse 5 - CH-8610 Uster - SWITZERLAND - - 00-50-C2 (hex) MSU UK Ltd - 03E000-03EFFF (base 16) MSU UK Ltd - 526-528 Elder House - Elder Gate - Milton Keynes MK9 1LR - UNITED KINGDOM - - 00-50-C2 (hex) Celotek Corp - 03F000-03FFFF (base 16) Celotek Corp - PO Box 14285 - RTP NC 27709 - UNITED STATES - - 00-50-C2 (hex) MiSPO Co., Ltd. - 040000-040FFF (base 16) MiSPO Co., Ltd. - Kanagawa Prefecture, - Takatsu-ku,Futago, 5-1-1, Takatsu Park plaza, 3F - Kawasaki City, 213-0002 - JAPAN - - 00-50-C2 (hex) Damler Chrysler Rail System (Signal) AB - 041000-041FFF (base 16) Damler Chrysler Rail System (Signal) AB - Box 42505 - SE-12616 Stockholm - SWEDEN - - 00-50-C2 (hex) B.E.A.R. Solutions (Australasia) Pty, Ltd - 042000-042FFF (base 16) B.E.A.R. Solutions (Australasia) Pty, Ltd - Unit 226 - 14 Lexington Drive - Bella Vista NSW - AUSTRALIA - - 00-50-C2 (hex) Curtis, Inc. - 043000-043FFF (base 16) Curtis, Inc. - 2155 Niagara Lane, North - Suite 108 - Minneapolis MN 55447 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - 044000-044FFF (base 16) - - 00-50-C2 (hex) Chase Manhattan Bank - 045000-045FFF (base 16) Chase Manhattan Bank - 380 Madison Ave - 11th Floor - New York City NY 10817 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - 046000-046FFF (base 16) - - 00-50-C2 (hex) B. R. Electronics - 047000-047FFF (base 16) B. R. Electronics - PO Box 717 - Pinegowrie 2123 - SOUTH AFRICA - - 00-50-C2 (hex) Cybectec Inc. - 048000-048FFF (base 16) Cybectec Inc. - 8165 rue du Mistral #100 - Charny Quebec G6X 3R8 - CANADA - - 00-50-C2 (hex) Computer Concepts Corp - 049000-049FFF (base 16) Computer Concepts Corp - 8375 Melrose - Lenexa KS 66214 - UNITED STATES - - 00-50-C2 (hex) Telecom Analysis Systems, LP - 04A000-04AFFF (base 16) Telecom Analysis Systems, LP - 34 Industrial Way East - Eatontown NJ 07724 - UNITED STATES - - 00-50-C2 (hex) Tecstar Demo Systems Division - 04B000-04BFFF (base 16) Tecstar Demo Systems Division - 379 Science Dr. - Moorpark CA 93021 - UNITED STATES - - 00-50-C2 (hex) New Standard Engineering NV - 04C000-04CFFF (base 16) New Standard Engineering NV - Inter Leu Ven Laan 3 - 3001 Leuven - BELGIUM - - 00-50-C2 (hex) Industrial Electronic Engineers, Inc. - 04E000-04EFFF (base 16) Industrial Electronic Engineers, Inc. - 7740 Lemona Ave. - Van Nuys CA 91409-9234 - UNITED STATES - - 00-50-C2 (hex) Luma Corporation - 04F000-04FFFF (base 16) Luma Corporation - 311 Courthouse Road - Princeton WV 24740 - UNITED STATES - - 00-50-C2 (hex) Dataprobe, Inc. - 050000-050FFF (base 16) Dataprobe, Inc. - 1B Pearl Court - Allendale NJ 07401 - UNITED STATES - - 00-50-C2 (hex) JSR Ultrasonics - 051000-051FFF (base 16) JSR Ultrasonics - 3800 Monroe Ave. - Pittsford NY 14534 - UNITED STATES - - 00-50-C2 (hex) Mayo Foundation - 052000-052FFF (base 16) Mayo Foundation - Division of Engineering - 200 1st St. SW - Rochester MN 55905 - UNITED STATES - - 00-50-C2 (hex) Optionexist Limited - 054000-054FFF (base 16) Optionexist Limited - Nixon's Hall, 1 Chapel Road - Great Eversden - Cambridge CB3 7HP - UNITED KINGDOM - - 00-50-C2 (hex) San Castle Technologies, Inc. - 055000-055FFF (base 16) San Castle Technologies, Inc. - 2375 Zanker Rd. - Suite 205 - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) Base 2 - 056000-056FFF (base 16) Base 2 - 3/28 Pritchard Rd. - Virginia Queensland 4014 - AUSTRALIA - - 00-50-C2 (hex) Lite F GmBH - 057000-057FFF (base 16) Lite F GmBH - PO Box 774 - 79007 Freiburg - GERMANY - - 00-50-C2 (hex) Vision Research, Inc. - 058000-058FFF (base 16) Vision Research, Inc. - 190 Parish Drive - Wayne NJ 07470 - UNITED STATES - - 00-50-C2 (hex) Austco Communication Systems Pty, Ltd - 059000-059FFF (base 16) Austco Communication Systems Pty, Ltd - 40 O'Malley St - Osborne Park Western Australia 6017 - AUSTRALIA - - 00-50-C2 (hex) Sonifex Ltd - 05A000-05AFFF (base 16) Sonifex Ltd - 61 Station Road - Irthlingborough Northants NN9 5QE England - UNITED KINGDOM - - 00-50-C2 (hex) Radiometer Medical A/S - 05B000-05BFFF (base 16) Radiometer Medical A/S - Akandevej 21 - DK 2700 Bronshoj - DENMARK - - 00-50-C2 (hex) Nortel Networks PLC (UK) - 05C000-05CFFF (base 16) Nortel Networks PLC (UK) - Harlow Labs - London Road - Harlow Essex CM179NA - UNITED KINGDOM - - 00-50-C2 (hex) Ignitus Communications, LLC - 05D000-05DFFF (base 16) Ignitus Communications, LLC - 43 Nagog Park - Acton MA 01720 - UNITED STATES - - 00-50-C2 (hex) DIVA Systems - 05E000-05EFFF (base 16) DIVA Systems - 800 Saginaw Drive - Redwood City CA 94063 - UNITED STATES - - 00-50-C2 (hex) Malden Electronics Ltd - 05F000-05FFFF (base 16) Malden Electronics Ltd - 2 High Street - Ewell Surrey KT17 1SJ - UNITED KINGDOM - - 00-50-C2 (hex) PRIVATE - 060000-060FFF (base 16) - - 00-50-C2 (hex) Simple Network Magic Corporation - 061000-061FFF (base 16) Simple Network Magic Corporation - 401 Kentucky Lane - McKinney TX 75069 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - 062000-062FFF (base 16) - - 00-50-C2 (hex) Ticketmaster Corp - 063000-063FFF (base 16) Ticketmaster Corp - 8181 S. 48th St. - Suite 100 - Phoenix AZ 85044 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - 064000-064FFF (base 16) - - 00-50-C2 (hex) Clever Devices, Ltd. - 065000-065FFF (base 16) Clever Devices, Ltd. - 5 Aerial Way - Syosset NY 11791 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - 066000-066FFF (base 16) - - 00-50-C2 (hex) Riverlink Computers, Ltd. - 067000-067FFF (base 16) Riverlink Computers, Ltd. - Pixmore Centre - Pixmore Avenue - Letchworth, SG6 1JG - UNITED KINGDOM - - 00-50-C2 (hex) Seabridge - 068000-068FFF (base 16) Seabridge - PO Box 470 - 3 Hanagar St. - Hod Hasharon 45800 - ISRAEL - - 00-50-C2 (hex) EC Elettronica S.R.L. - 069000-069FFF (base 16) EC Elettronica S.R.L. - Via Industriale TR. 3, 15 - 25060 Cellatica (BS) - ITALY - - 00-50-C2 (hex) Unimark - 06A000-06AFFF (base 16) Unimark - 9910 Widner Road - Lenexa KS 66215 - UNITED STATES - - 00-50-C2 (hex) NCast Corporation - 06B000-06BFFF (base 16) NCast Corporation - 155A Moffet Park Drive - Suite 103 - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) WaveCom Electronics, Inc. - 06C000-06CFFF (base 16) WaveCom Electronics, Inc. - 222 Cardinal Crescent - Saskatcon, SK S7L 6H8 - CANADA - - 00-50-C2 (hex) Advanced Signal Corp. - 06D000-06DFFF (base 16) Advanced Signal Corp. - PO Box 713 - Quincy IL 62306-0713 - UNITED STATES - - 00-50-C2 (hex) Avtron Manufacturing Inc. - 06E000-06EFFF (base 16) Avtron Manufacturing Inc. - 7900 East Pleasant Valley Rd. - Independence OH 44131 - UNITED STATES - - 00-50-C2 (hex) Digital Services Group - 06F000-06FFFF (base 16) Digital Services Group - PO Box 36848 - Birmingham AL 35236 - UNITED STATES - - 00-50-C2 (hex) Katchall Technologies Group - 070000-070FFF (base 16) Katchall Technologies Group - 5800 Creek Road - Cincinnati OH 45242 - UNITED STATES - - 00-50-C2 (hex) NetVision Telecom - 071000-071FFF (base 16) NetVision Telecom - 117-11, Jungchon-Dong, Jung-Gu - Taejon, 301-080 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Neuberger Gebaeudeautomation GmbH & Co. - 072000-072FFF (base 16) Neuberger Gebaeudeautomation GmbH & Co. - Oberer Kaiserweg 6 - 91541 Rothenburg o.d.T. - GERMANY - - 00-50-C2 (hex) Alstom Signalling Ltd. - 073000-073FFF (base 16) Alstom Signalling Ltd. - Borehamwood Industrial Park - Rowley Lane - Borehamwood Herts WD6 5PZ - UNITED KINGDOM - - 00-50-C2 (hex) Edge Tech Co., Ltd. - 074000-074FFF (base 16) Edge Tech Co., Ltd. - 6th-F. Dae Rewing Techo Town-1, 327-24 - Kasan-dong, Kumchon-gu Seoul - KOREA, REPUBLIC OF - - 00-50-C2 (hex) ENTTEC Pty Ltd. - 075000-075FFF (base 16) ENTTEC Pty Ltd. - PO Box 4051 - ringwood vic 3134 - AUSTRALIA - - 00-50-C2 (hex) Litton Guidance & Control Systems - 076000-076FFF (base 16) Litton Guidance & Control Systems - 5500 Canoga Ave - Woodland Hills CA 91367 - UNITED STATES - - 00-50-C2 (hex) Saco Smartvision Inc. - 077000-077FFF (base 16) Saco Smartvision Inc. - 7809 Trans Canada - Montreal Quebec H4S 1L3 - CANADA - - 00-50-C2 (hex) Reselec AG - 078000-078FFF (base 16) Reselec AG - Schlosserstr. 4 - CH-8180 Buelach - SWITZERLAND - - 00-50-C2 (hex) Flextel S.p.A - 079000-079FFF (base 16) Flextel S.p.A - Corso Vercelli 328 - 10015 Ivrea (To) - ITALY - - 00-50-C2 (hex) RadioTel - 07A000-07AFFF (base 16) RadioTel - 17 Hatasiya St. - Or Yehuda 60373 - ISRAEL - - 00-50-C2 (hex) Trikon Technologies Ltd. - 07B000-07BFFF (base 16) Trikon Technologies Ltd. - Ringland Way - Newport - Gwent NP18 2TA - UNITED KINGDOM - - 00-50-C2 (hex) PLLB elettronica spa - 07C000-07CFFF (base 16) PLLB elettronica spa - via Carducci 39 - 20099 Sesto San Giovanni Milano - ITALY - - 00-50-C2 (hex) Caspian Networks - 07D000-07DFFF (base 16) Caspian Networks - 2880 West Bayshore Rd - Palo Alto CA 94303 - UNITED STATES - - 00-50-C2 (hex) JL-teknik - 07E000-07EFFF (base 16) JL-teknik - Isbjornsvagen 3 - SE-35245 Vaxjo - SWEDEN - - 00-50-C2 (hex) Dunti Corporation - 07F000-07FFFF (base 16) Dunti Corporation - 3925 West Braker Lane - Austin TX 78759 - UNITED STATES - - 00-50-C2 (hex) AIM - 080000-080FFF (base 16) AIM - 21 Avenue de la plaine fleure - 38240 Meylon - FRANCE - - 00-50-C2 (hex) Matuschek Messtechnik GmbH - 081000-081FFF (base 16) Matuschek Messtechnik GmbH - Werner-Heisenberg-Straße 14 - Alsdorf NRW 52477 - GERMANY - - 00-50-C2 (hex) GFI Chrono Time - 082000-082FFF (base 16) GFI Chrono Time - 121 rue des Guillees - CHAURAY 79180 - FRANCE - - 00-50-C2 (hex) ARD SA - 083000-083FFF (base 16) ARD SA - Micropolis BP 169 - C5 005 GAP cedex - FRANCE - - 00-50-C2 (hex) DIALOG4 System Engineering GmbH - 084000-084FFF (base 16) DIALOG4 System Engineering GmbH - Monreposstr. 55 - 71634 Ludwigsburg - GERMANY - - 00-50-C2 (hex) Crossport Systems - 085000-085FFF (base 16) Crossport Systems - 10940 NE 33rd Place - Suite 101 - Bellevue WA 98005 - UNITED STATES - - 00-50-C2 (hex) Validyne Engineering Corp. - 086000-086FFF (base 16) Validyne Engineering Corp. - 8626 Wilbur Ave. - Northridge CA 91324 - UNITED STATES - - 00-50-C2 (hex) Monitor Business Machines Ltd. - 087000-087FFF (base 16) Monitor Business Machines Ltd. - PO Box 108042 - Symonds St. - Auckland - NEW ZEALAND - - 00-50-C2 (hex) TELINC Corporation - 088000-088FFF (base 16) TELINC Corporation - 22 Springdale Rd. - Cherry Hill NJ 08003 - UNITED STATES - - 00-50-C2 (hex) Fenwal Italia S.P.A. - 089000-089FFF (base 16) Fenwal Italia S.P.A. - Viale A. De Gasperi, 44 - 20010 Bareggio (MI) - ITALY - - 00-50-C2 (hex) Rising Edge Technologies - 08A000-08AFFF (base 16) Rising Edge Technologies - 500-D Huntmar Park Dr - Herndon VA 20170 - UNITED STATES - - 00-50-C2 (hex) HYPERCHIP Inc. - 08B000-08BFFF (base 16) HYPERCHIP Inc. - 180 Peel St. - Suite 333 - Montreal Quebec H3C 2G7 - CANADA - - 00-50-C2 (hex) IP Unity - 08C000-08CFFF (base 16) IP Unity - 1575 McCandless Dr. - Milpitas CA 95035 - UNITED STATES - - 00-50-C2 (hex) Kylink Communications Corp. - 08D000-08DFFF (base 16) Kylink Communications Corp. - No. 31, Tzyh Chyang St. - Tu Cheng Industrial District - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) BSQUARE - 08E000-08EFFF (base 16) BSQUARE - 1136 W. Evelyn Ave. - Sunnyvale CA 94086 - UNITED STATES - - 00-50-C2 (hex) General Industries Argentina - 08F000-08FFFF (base 16) General Industries Argentina - Herrera 1175 - General Industries Arg. - C1295 Abu Buenos Aires - ARGENTINA - - 00-50-C2 (hex) Invensys Controls Network Systems - 090000-090FFF (base 16) Invensys Controls Network Systems - 1701 Byrd Ave. - Richmond VA 23230 - UNITED STATES - - 00-50-C2 (hex) StorLogic, Inc. - 091000-091FFF (base 16) StorLogic, Inc. - 100 Technology Park - Suite 175 - Lake Mary FL 32746 - UNITED STATES - - 00-50-C2 (hex) DigitAll World Co., Ltd - 092000-092FFF (base 16) DigitAll World Co., Ltd - 248-4, YouSeong Twin Plaza Bldg, 4F - Seohyun-Dong, Bundang-Ku, Seongnam-City - Kyungki-Do 463 050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) KOREALINK - 093000-093FFF (base 16) KOREALINK - 10F CCMM Bldg. 12 Yoido-dong - Youngdeungpo-ku - Seoul 150-010 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Analytical Spectral Devices, Inc. - 094000-094FFF (base 16) Analytical Spectral Devices, Inc. - 5335 Sterling Dr. - Suite A - Boulder CO 80301 - UNITED STATES - - 00-50-C2 (hex) SEATECH - 095000-095FFF (base 16) SEATECH - 101 N. Beach Rd. - Dania Beach FL 33004 - UNITED STATES - - 00-50-C2 (hex) Utronix Elektronikutreckling AB - 096000-096FFF (base 16) Utronix Elektronikutreckling AB - Teknikringen 1 - SE-583 30 Linkoping - SWEDEN - - 00-50-C2 (hex) IMV Invertomatic - 097000-097FFF (base 16) IMV Invertomatic - via Cantonale - CH-6595 Riazzino - SWITZERLAND - - 00-50-C2 (hex) EPEL Industrial, S.A. - 098000-098FFF (base 16) EPEL Industrial, S.A. - CRTA. STA. Cruz Calafell No. 35 - 08830 - Sant Boi - SPAIN - - 00-50-C2 (hex) Case Information & Communications - 099000-099FFF (base 16) Case Information & Communications - 18F Daishin Bldg., 395-68 - Shindaebang-dong, Dongjak-gu - Seoul - KOREA, REPUBLIC OF - - 00-50-C2 (hex) NBO Development Center Sekusui Chemical Co. Ltd. - 09A000-09AFFF (base 16) NBO Development Center Sekusui Chemical Co. Ltd. - 32 Wadai, Tsukuba-shi - Ibaraki, 300-4292 - JAPAN - - 00-50-C2 (hex) Seffle Instrument AB - 09B000-09BFFF (base 16) Seffle Instrument AB - PO Box 25 - 661 21 Saffle - SWEDEN - - 00-50-C2 (hex) RF Applications, Inc. - 09C000-09CFFF (base 16) RF Applications, Inc. - 7345 Production Drive - Mentor OH 44060 - UNITED STATES - - 00-50-C2 (hex) ZELPOS - 09D000-09DFFF (base 16) ZELPOS - Rosickeho 25 - 77900 Olomouc - CZECH REPUBLIC - - 00-50-C2 (hex) Infinitec Networks, Inc. - 09E000-09EFFF (base 16) Infinitec Networks, Inc. - 4343 S. 118 E. Ave. - Tulsa OK 74146 - UNITED STATES - - 00-50-C2 (hex) MetaWave Vedeo Systems - 09F000-09FFFF (base 16) MetaWave Vedeo Systems - 11 Kingsclere Park - Kingsclere, Newbury Berkshire RG20 4SW - UNITED KINGDOM - - 00-50-C2 (hex) CYNAPS - 0A0000-0A0FFF (base 16) CYNAPS - PO Box 131276 - Bryanston 2021 - SOUTH AFRICA - - 00-50-C2 (hex) Visable Genetics, Inc. - 0A1000-0A1FFF (base 16) Visable Genetics, Inc. - 291/295 Evans Ave. - Etobicoke Ontario M8Z 1K2 - CANADA - - 00-50-C2 (hex) Jäger Computergesteuerte Messtechnik GmbH - 0A2000-0A2FFF (base 16) Jäger Computergesteuerte Messtechnik GmbH - Rheinstraße 2-4 - Lorsch Hessen 64653 - GERMANY - - 00-50-C2 (hex) BaSyTec GmbH - 0A3000-0A3FFF (base 16) BaSyTec GmbH - Karlstraße 14 - 89561 Dischingen - GERMANY - - 00-50-C2 (hex) Bounty Systems Pty Ltd. - 0A4000-0A4FFF (base 16) Bounty Systems Pty Ltd. - PO Box 499 - Coffs Harbour NSW 2450 - AUSTRALIA - - 00-50-C2 (hex) Mobiltex Data Ltd. - 0A5000-0A5FFF (base 16) Mobiltex Data Ltd. - 3640 - 26th St. NE - Calgary Alberta T1Y 4T7 - CANADA - - 00-50-C2 (hex) Arula Systems, Inc. - 0A6000-0A6FFF (base 16) Arula Systems, Inc. - 10670 N. Tantau Ave. - Suite 200 - Cupertino CA 95014 - UNITED STATES - - 00-50-C2 (hex) WaterCove Networks - 0A7000-0A7FFF (base 16) WaterCove Networks - 6 New England Executive Park - Burlington MA 01803 - UNITED STATES - - 00-50-C2 (hex) Kaveri Networks - 0A8000-0A8FFF (base 16) Kaveri Networks - 950 Kifer Road - Sunnyvale CA 94086 - UNITED STATES - - 00-50-C2 (hex) Radiant Networks Plc - 0A9000-0A9FFF (base 16) Radiant Networks Plc - The Mansion - Chesterford Park - Little Chesterford Essex CB10 1XL - UNITED KINGDOM - - 00-50-C2 (hex) Log-In, Inc. - 0AA000-0AAFFF (base 16) Log-In, Inc. - 3419 N. Kennicott - Suite B - Arlington Heights IL 60004 - UNITED STATES - - 00-50-C2 (hex) Fastware.Net, LLC - 0AB000-0ABFFF (base 16) Fastware.Net, LLC - 7985 S. Bemis St. - Suite 100 - Littleton CO 80120 - UNITED STATES - - 00-50-C2 (hex) Honeywell GNO - 0AC000-0ACFFF (base 16) Honeywell GNO - 13051 66th St. N - Largo FL 33773 - UNITED STATES - - 00-50-C2 (hex) BMC Messsysteme GmbH - 0AD000-0ADFFF (base 16) BMC Messsysteme GmbH - Peter-Henlein-Str. 4 - 82140 Olching - GERMANY - - 00-50-C2 (hex) Zarak Systems Corp. - 0AE000-0AEFFF (base 16) Zarak Systems Corp. - 1175 Borregas Ave. - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) Latus Lightworks, Inc. - 0AF000-0AFFFF (base 16) Latus Lightworks, Inc. - 250 East Arapaho Rd. - Suite 200 - Richardson TX 75081 - UNITED STATES - - 00-50-C2 (hex) LMI Technologies, Inc. - 0B0000-0B0FFF (base 16) LMI Technologies, Inc. - #205 - 7088 Venture St. - Delta British Columbia V49 1H5 - CANADA - - 00-50-C2 (hex) Beeline Networks, Inc. - 0B1000-0B1FFF (base 16) Beeline Networks, Inc. - 2025 Stierlin Court - Mountain View CA 94043 - UNITED STATES - - 00-50-C2 (hex) R F Micro Devices - 0B2000-0B2FFF (base 16) R F Micro Devices - 7628 Thorndike Rd. - Greensboro NC 27409 - UNITED STATES - - 00-50-C2 (hex) SMX Corporation - 0B3000-0B3FFF (base 16) SMX Corporation - 222 Gale Lane - Kennett Square PA 19348 - UNITED STATES - - 00-50-C2 (hex) Wavefly Corporation - 0B4000-0B4FFF (base 16) Wavefly Corporation - 9420 Research Blvd. - Suite 330 - Austin TX 78759 - UNITED STATES - - 00-50-C2 (hex) Extreme Copper, Inc. - 0B5000-0B5FFF (base 16) Extreme Copper, Inc. - 4342 Avenida Gregory - Spring Valley CA 91977 - UNITED STATES - - 00-50-C2 (hex) ApSecure Technologies (Canada), Inc. - 0B6000-0B6FFF (base 16) ApSecure Technologies (Canada), Inc. - 4603 Kinsway, Suite 402 - Burnby British Columbia V5H 4M4 - CANADA - - 00-50-C2 (hex) RYMIC - 0B7000-0B7FFF (base 16) RYMIC - 102-A Wynn Drive - Huntsville AL 35805 - UNITED STATES - - 00-50-C2 (hex) LAN Controls, Inc. - 0B8000-0B8FFF (base 16) LAN Controls, Inc. - 10 Woodvue Road - Windham NH 03087 - UNITED STATES - - 00-50-C2 (hex) Helmut Mauell GmbH - 0B9000-0B9FFF (base 16) Helmut Mauell GmbH - Theodor Korner Alle 16 - 02763 Zittau - GERMANY - - 00-50-C2 (hex) Pro-Active - 0BA000-0BAFFF (base 16) Pro-Active - Parc Gutenberg - 13 Voie La Cardon - 91120 Palaiseau - FRANCE - - 00-50-C2 (hex) MAZet GmbH - 0BB000-0BBFFF (base 16) MAZet GmbH - Goeschwitzer Str.32 - D-07745 Jena - GERMANY - - 00-50-C2 (hex) Infolink Software AG - 0BC000-0BCFFF (base 16) Infolink Software AG - Bernstrasse 49 - CH-3018 Bern - SWITZERLAND - - 00-50-C2 (hex) Tattile - 0BD000-0BDFFF (base 16) Tattile - via Trento 127 - Capriano Del Colle 25020 Brescia - ITALY - - 00-50-C2 (hex) Stella Electronics & Tagging - 0BE000-0BEFFF (base 16) Stella Electronics & Tagging - Technopole de Chateau Gombert - D1 11 Avenue Joliot Curie - 13013 Marseille - FRANCE - - 00-50-C2 (hex) PRIVATE - 0BF000-0BFFFF (base 16) - - 00-50-C2 (hex) Imigix Ltd. - 0C0000-0C0FFF (base 16) Imigix Ltd. - Cardiff Gate Business Park - Cardiff CF23 8RD - UNITED KINGDOM - - 00-50-C2 (hex) Casabyte - 0C1000-0C1FFF (base 16) Casabyte - PO Box 1166 - Renton WA 98055 - UNITED STATES - - 00-50-C2 (hex) Alchemy Semiconductor, Inc. - 0C2000-0C2FFF (base 16) Alchemy Semiconductor, Inc. - 7800 Shoal Creek Blvd. - Suite 222 West - Austin TX 78757 - UNITED STATES - - 00-50-C2 (hex) Tonbu, Inc. - 0C3000-0C3FFF (base 16) Tonbu, Inc. - 871 Fox Lane - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) InterEpoch Technology, Inc. - 0C4000-0C4FFF (base 16) InterEpoch Technology, Inc. - &f, No. 3, Alley 6, Lane 235 - Pao-Chiao Rd., Hsin-Tien city - Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) SAIA Burgess Controls AG - 0C5000-0C5FFF (base 16) SAIA Burgess Controls AG - Bahnhofstrasse 18 - 3280 Murten - SWITZERLAND - - 00-50-C2 (hex) Advanced Medical Information Technologies, Inc. - 0C6000-0C6FFF (base 16) Advanced Medical Information Technologies, Inc. - PO Box 870 - Hermosa Beach CA 90254-0870 - UNITED STATES - - 00-50-C2 (hex) TransComm Technology System, Inc. - 0C7000-0C7FFF (base 16) TransComm Technology System, Inc. - 4221 Technology Drive - Fremont CA 94538 - UNITED STATES - - 00-50-C2 (hex) The Trane Company - 0C8000-0C8FFF (base 16) The Trane Company - 4833 White Bear Parkway - St. Paul MN 55110 - UNITED STATES - - 00-50-C2 (hex) DSS Networks, Inc. - 0C9000-0C9FFF (base 16) DSS Networks, Inc. - 111 Pacifica - Suite 250 - Irvine CA 92618 - UNITED STATES - - 00-50-C2 (hex) J D Richards - 0CA000-0CAFFF (base 16) J D Richards - 12840 Earhart Ave. - Suite 200 - Auburn CA 95602 - UNITED STATES - - 00-50-C2 (hex) STUDIEL - 0CB000-0CBFFF (base 16) STUDIEL - 1027 Avenue Dactan Lefebvre - 06271 Villenaur Lou Pet cedex - FRANCE - - 00-50-C2 (hex) AlphaMedia Co., Ltd - 0CC000-0CCFFF (base 16) AlphaMedia Co., Ltd - Technical Center - Chuko Build. 5F 4-12-3 - Shimoyamatedori Chuoku Kobe Hyogo - JAPAN - - 00-50-C2 (hex) LINET OY - 0CD000-0CDFFF (base 16) LINET OY - Riihitie 8 - 00330 Helsinki - FINLAND - - 00-50-C2 (hex) RFL Electronics, Inc. - 0CE000-0CEFFF (base 16) RFL Electronics, Inc. - 353 Powerville Road - Booton Twp. NJ 07005 - UNITED STATES - - 00-50-C2 (hex) PCSC - 0CF000-0CFFFF (base 16) PCSC - 3541 Challenger St. - Torrance CA 90503 - UNITED STATES - - 00-50-C2 (hex) Telefrang AB - 0D0000-0D0FFF (base 16) Telefrang AB - Varbergsgatan 8 - S-412 65 Gothenburg - SWEDEN - - 00-50-C2 (hex) Renaissance Networking, Inc. - 0D1000-0D1FFF (base 16) Renaissance Networking, Inc. - 415 S. McClintock Dr. - Suite 5 - Tempe AZ 85281 - UNITED STATES - - 00-50-C2 (hex) Real World Computing Partnership - 0D2000-0D2FFF (base 16) Real World Computing Partnership - 1-6-1 Takezono Tsukuba-shi - Ibaraki 305-0032 - JAPAN - - 00-50-C2 (hex) Lake Technology, Ltd. - 0D3000-0D3FFF (base 16) Lake Technology, Ltd. - PO Box 736 - Broadway Post Office - Broadway, 2007 - AUSTRALIA - - 00-50-C2 (hex) Palm, Inc. - 0D4000-0D4FFF (base 16) Palm, Inc. - 5470 Great America Parkway - M/S 15112 - Santa Clara CA 95052 - UNITED STATES - - 00-50-C2 (hex) Zelax - 0D5000-0D5FFF (base 16) Zelax - Office 8, 146, Zelenograd - Moscow 103305 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Inco Startec GmbH - 0D6000-0D6FFF (base 16) Inco Startec GmbH - Potsdamer Straße 8 - D-14513 Teltow - GERMANY - - 00-50-C2 (hex) Summit Avionics, Inc. - 0D7000-0D7FFF (base 16) Summit Avionics, Inc. - 2224 E. Enterprise Pkwy - Twinsburg OH 44087 - UNITED STATES - - 00-50-C2 (hex) Charlotte's Web Networks - 0D8000-0D8FFF (base 16) Charlotte's Web Networks - PO Box 333 - 2nd Hamada St. - Industrial Park Yokneam 20600 - ISRAEL - - 00-50-C2 (hex) Loewe Opta GmbH - 0D9000-0D9FFF (base 16) Loewe Opta GmbH - Industriestrasse 11 - Kronach 96317 - GERMANY - - 00-50-C2 (hex) Motion Analysis Corp. - 0DA000-0DAFFF (base 16) Motion Analysis Corp. - 3617 Westwind Blvd. - Santa Rosa CA 95403 - UNITED STATES - - 00-50-C2 (hex) Cyberex - 0DB000-0DBFFF (base 16) Cyberex - 5335 Avion Park Dr. - Highland Heights OH 44143 - UNITED STATES - - 00-50-C2 (hex) Elbit Systems Ltd. - 0DC000-0DCFFF (base 16) Elbit Systems Ltd. - P.O.B. 539 - Matam Haifa 31053 - ISRAEL - - 00-50-C2 (hex) Interisa Electronica, S.A. - 0DD000-0DDFFF (base 16) Interisa Electronica, S.A. - Avda. de los Artesanos, 46 - 28760 Tres Cantos - Madrid - SPAIN - - 00-50-C2 (hex) Frederick Engineering - 0DE000-0DEFFF (base 16) Frederick Engineering - 3620 Commerce Dr. - Baltimore MD 21227 - UNITED STATES - - 00-50-C2 (hex) Innovation Institute, Inc. - 0DF000-0DFFFF (base 16) Innovation Institute, Inc. - PO Box 9359 - Caguas PR 00726-9359 - UNITED STATES - - 00-50-C2 (hex) EMAC, Inc. - 0E0000-0E0FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62901 - UNITED STATES - - 00-50-C2 (hex) Inspiration Technology P/L - 0E1000-0E1FFF (base 16) Inspiration Technology P/L - PO Box 165, Goodwood - SA 5034 - AUSTRALIA - - 00-50-C2 (hex) Visual Circuits Corp. - 0E2000-0E2FFF (base 16) Visual Circuits Corp. - 5155 East River Road - Suite 401 - Minneapolis MN 55421 - UNITED STATES - - 00-50-C2 (hex) Lanex S.A. - 0E3000-0E3FFF (base 16) Lanex S.A. - Ceramiczna 8 Str. - 20-150 Lublin - POLAND - - 00-50-C2 (hex) Collabo Tec. Co., Ltd. - 0E4000-0E4FFF (base 16) Collabo Tec. Co., Ltd. - 5-2, 2-chome, Shinryoudai - Tarumi-ku, Kobe-shi - Hyougo-Ken 655-0041 - JAPAN - - 00-50-C2 (hex) Clearwater Networks - 0E5000-0E5FFF (base 16) Clearwater Networks - 160 Knowles Dr. - Los Gatos CA 95032 - UNITED STATES - - 00-50-C2 (hex) RouteFree, Inc. - 0E6000-0E6FFF (base 16) RouteFree, Inc. - 3400 Hillview Ave., Building 5 - Palo Alto CA 94304 - UNITED STATES - - 00-50-C2 (hex) Century Geophysical Corp. - 0E7000-0E7FFF (base 16) Century Geophysical Corp. - 1223 S. 71st E. Ave. - Tulsa OK 74112 - UNITED STATES - - 00-50-C2 (hex) Audio Design Associates, Inc. - 0E8000-0E8FFF (base 16) Audio Design Associates, Inc. - 602-610 Mamaroneck Ave. - White Plains NY 10605 - UNITED STATES - - 00-50-C2 (hex) Smartmedia LLC - 0E9000-0E9FFF (base 16) Smartmedia LLC - 1625 W. Olympic Blvd. - Suite 818 - Los Angeles CA 90015 - UNITED STATES - - 00-50-C2 (hex) iReady Corporation - 0EA000-0EAFFF (base 16) iReady Corporation - 2903 Bunker Hill Lane - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) iREZ Technologies LLC - 0EB000-0EBFFF (base 16) iREZ Technologies LLC - 15020 N 74th St. - Scottsdale AZ 85260 - UNITED STATES - - 00-50-C2 (hex) Keith & Koep GmbH - 0EC000-0ECFFF (base 16) Keith & Koep GmbH - Koenigsberger Str. 2 - D-42277 Wuppertal - GERMANY - - 00-50-C2 (hex) Valley Products Corporation - 0ED000-0EDFFF (base 16) Valley Products Corporation - PO Box 668 - Valley NE 68064 - UNITED STATES - - 00-50-C2 (hex) Industrial Indexing Systems, Inc. - 0EE000-0EEFFF (base 16) Industrial Indexing Systems, Inc. - 626 Fishers Run - Victor NY 14564 - UNITED STATES - - 00-50-C2 (hex) Movaz Networks, Inc. - 0EF000-0EFFFF (base 16) Movaz Networks, Inc. - One Technology Parkway South - Norcross GA 30092 - UNITED STATES - - 00-50-C2 (hex) VHB Technologies, Inc. - 0F0000-0F0FFF (base 16) VHB Technologies, Inc. - 405 International Parkway - Suite 203 - Richardson TX 75081 - UNITED STATES - - 00-50-C2 (hex) Polyvision Corporation - 0F1000-0F1FFF (base 16) Polyvision Corporation - 14523 SW Milliken Way - Suite 140 - Beaverton OR 97005 - UNITED STATES - - 00-50-C2 (hex) KMS Systems, Inc. - 0F2000-0F2FFF (base 16) KMS Systems, Inc. - PO Box 7264 - The Woodlands TX 77387 - UNITED STATES - - 00-50-C2 (hex) Young Computer Co., Ltd. - 0F3000-0F3FFF (base 16) Young Computer Co., Ltd. - 6th Fl. Bojung Bldg. - 158-2, Sokchon-dong, Songpa-Ku - Seoul 138-190 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Sysnet Co., Ltd. - 0F4000-0F4FFF (base 16) Sysnet Co., Ltd. - 78 Ikenouchicho, Kishoin - Minami-Ku, Kyoto-City - JAPAN - - 00-50-C2 (hex) Spectra Technologies Holding Co., Ltd. - 0F5000-0F5FFF (base 16) Spectra Technologies Holding Co., Ltd. - Unit 1301-09, 19-20 - Tower II, Grand Century Place - 193 Prince Edward Road West - HONG KONG - - 00-50-C2 (hex) Carl Baasel Lasertechnik GmbH - 0F6000-0F6FFF (base 16) Carl Baasel Lasertechnik GmbH - Petersbrunner Str. 1b - 82319 Starnberg - GERMANY - - 00-50-C2 (hex) Foss NIRSystems, Inc. - 0F7000-0F7FFF (base 16) Foss NIRSystems, Inc. - 7703 Montpelier Road - Suite 1 - Laurel MD 20723 - UNITED STATES - - 00-50-C2 (hex) Tecnint HTE S.r.L. - 0F8000-0F8FFF (base 16) Tecnint HTE S.r.L. - Via della tecnica 16/18 - Osnago (Lecco) 23875 - ITALY - - 00-50-C2 (hex) Raven Industries - 0F9000-0F9FFF (base 16) Raven Industries - PO Box 1007 - 101 East 6th St. - Sioux Falls SD 57104 - UNITED STATES - - 00-50-C2 (hex) GE Lubrizol, LLC - 0FA000-0FAFFF (base 16) GE Lubrizol, LLC - 29400 Lakeland Blvd. - Bldg. 282A - Wickliffe OH 44092-2298 - UNITED STATES - - 00-50-C2 (hex) PIUSYS Co., Ltd. - 0FB000-0FBFFF (base 16) PIUSYS Co., Ltd. - Daemyoung Bldg, 5F - 2-37 Yangjae-Dong, Seocho-Ku - Seoul 137-886 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Kimmon Manufacturing Co., Ltd. - 0FC000-0FCFFF (base 16) Kimmon Manufacturing Co., Ltd. - 748, Shimoakasaka - Kawagoe-Shi, Saitama 350-1155 - JAPAN - - 00-50-C2 (hex) Inducomp Corporation - 0FD000-0FDFFF (base 16) Inducomp Corporation - 1265 Jefferson St. - Pacific MO 63069 - UNITED STATES - - 00-50-C2 (hex) Energy ICT - 0FE000-0FEFFF (base 16) Energy ICT - Zandbergstraat 19 - 8500 Kortrijk - BELGIUM - - 00-50-C2 (hex) IPAXS Corporation - 0FF000-0FFFFF (base 16) IPAXS Corporation - 5802 Benjamin Center Drive - Suite 105 - Tampa FL 33634 - UNITED STATES - - 00-50-C2 (hex) Corelatus A.B. - 100000-100FFF (base 16) Corelatus A.B. - Ulf Svarte Bagge - Gardshuset - Tegnerg. 37 Stockholm SE-111 61 - SWEDEN - - 00-50-C2 (hex) LAUD Electronic Design AS - 101000-101FFF (base 16) LAUD Electronic Design AS - Froyhovveien 37 - N-3269 Larvik - NORWAY - - 00-50-C2 (hex) Million Tech Development Ltd. - 102000-102FFF (base 16) Million Tech Development Ltd. - Unit D, s/F., Leroy Plaza - 15 Cheung Shun Street - Cheung Sha Wan, Kowloon - HONG KONG - - 00-50-C2 (hex) Green Hills Software, Inc. - 103000-103FFF (base 16) Green Hills Software, Inc. - 30 W. Sola Street - Santa Barbara CA 93101 - UNITED STATES - - 00-50-C2 (hex) Adescom Inc. - 104000-104FFF (base 16) Adescom Inc. - 256 Calvin Place - Santa Cruz CA 95060 - UNITED STATES - - 00-50-C2 (hex) Lumentis AB - 105000-105FFF (base 16) Lumentis AB - Jakobsdalsvagen 17 - SE-126 53 Hagersten - SWEDEN - - 00-50-C2 (hex) MATSUOKA - 106000-106FFF (base 16) MATSUOKA - kishimachi 2-9-17-102 - kita-ku - Tokyo-to - JAPAN - - 00-50-C2 (hex) NewHer Systems - 107000-107FFF (base 16) NewHer Systems - Rivierensingel 598 - 5704 NV Helmond - NETHERLANDS - - 00-50-C2 (hex) Balogh S.A. - 108000-108FFF (base 16) Balogh S.A. - 189, rue d'Aubervilliers - CP97 75886 Paris cedex 18 - FRANCE - - 00-50-C2 (hex) ITK Dr. Kassen GmbH - 109000-109FFF (base 16) ITK Dr. Kassen GmbH - Beim Eberacker 3 - D-35633 Lahnau - GERMANY - - 00-50-C2 (hex) Quinx AG - 10A000-10AFFF (base 16) Quinx AG - Hauptstrasse 115 - CH-5732 Zetzwil - SWITZERLAND - - 00-50-C2 (hex) MarekMicro GmbH - 10B000-10BFFF (base 16) MarekMicro GmbH - Fuggerstrasse 9 - D-92224 Amberg - GERMANY - - 00-50-C2 (hex) Photonic Bridges, Inc. - 10C000-10CFFF (base 16) Photonic Bridges, Inc. - 249 Mountain Road - Basking Ridge NJ 07920 - UNITED STATES - - 00-50-C2 (hex) Implementa GmbH - 10D000-10DFFF (base 16) Implementa GmbH - Leineweg 26 - 30823 Garbsen - GERMANY - - 00-50-C2 (hex) Unipower AB - 10E000-10EFFF (base 16) Unipower AB - PO Box 411 - SE-441 28 Alingsas - SWEDEN - - 00-50-C2 (hex) Perceptics Corp. - 10F000-10FFFF (base 16) Perceptics Corp. - 9737 Cogdill Road - Knoxville TN 37932 - UNITED STATES - - 00-50-C2 (hex) QuesCom - 110000-110FFF (base 16) QuesCom - Arche des Dolines - 79 Rue de Sevres - 92100 Boulogne Billancourt - FRANCE - - 00-50-C2 (hex) Endusis Limited - 111000-111FFF (base 16) Endusis Limited - Strawberry How Business Centre - Lorton Road - Cockermouth Cumbria CA13 9XQ - UNITED KINGDOM - - 00-50-C2 (hex) Compuworx - 112000-112FFF (base 16) Compuworx - 141-143 Szabadsag U. - 2040 Budaors - HUNGARY - - 00-50-C2 (hex) Ace Electronics, Inc. - 113000-113FFF (base 16) Ace Electronics, Inc. - PO Box 890955 - Temecula CA 92590 - UNITED STATES - - 00-50-C2 (hex) Quest Innovations - 114000-114FFF (base 16) Quest Innovations - Dr Sicco Mansholstraat 7 - 1771 CS - Wieringerwerf - NETHERLANDS - - 00-50-C2 (hex) Vidco, Inc. - 115000-115FFF (base 16) Vidco, Inc. - 6175 SW 112th Ave - Beaverton OR 97008 - UNITED STATES - - 00-50-C2 (hex) DSP Design, Ltd. - 116000-116FFF (base 16) DSP Design, Ltd. - Tapton Park Innovation Centre - Brimington Road, Chesterfield - Derbyshire S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) Wintegra Ltd. - 117000-117FFF (base 16) Wintegra Ltd. - PO Box 3048 - Ra'anana 43654 - ISRAEL - - 00-50-C2 (hex) Microbit 2.0 AB - 118000-118FFF (base 16) Microbit 2.0 AB - Nystaden 1 - SE-952 61 Kalix - SWEDEN - - 00-50-C2 (hex) Global Opto Communication Tech. Corp - 119000-119FFF (base 16) Global Opto Communication Tech. Corp - 7F, 162-31, Sec. 3, - Sin-Yi Rd. - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Teamaxess Ticketing GmbH - 11A000-11AFFF (base 16) Teamaxess Ticketing GmbH - Gewerbepark Habach1 - A-5321 Koppl - AUSTRIA - - 00-50-C2 (hex) Digital Vision AB - 11B000-11BFFF (base 16) Digital Vision AB - Upplagsvagen 1 - SE-117 43 Stockholm - SWEDEN - - 00-50-C2 (hex) Stonefly Networks - 11C000-11CFFF (base 16) Stonefly Networks - 10170 Huennekens St. - San Diego CA 92121 - UNITED STATES - - 00-50-C2 (hex) Destiny Networks, Inc. - 11D000-11DFFF (base 16) Destiny Networks, Inc. - 15790 Monterey Rd., Suite 300 - Morgan Hill CA 95037 - UNITED STATES - - 00-50-C2 (hex) Volvo Car Corporation - 11E000-11EFFF (base 16) Volvo Car Corporation - Dept. 93861, PVOS27 - SE-40531 Goteborg - SWEDEN - - 00-50-C2 (hex) CSS Industrie Computer GmbH - 11F000-11FFFF (base 16) CSS Industrie Computer GmbH - Osterhofstr. 14 - 87600 Kaufbeuren - GERMANY - - 00-50-C2 (hex) XStore, Inc. - 120000-120FFF (base 16) XStore, Inc. - 1200 N. Federal Highway #200 - Boca Raton FL 33432 - UNITED STATES - - 00-50-C2 (hex) COE Limited - 121000-121FFF (base 16) COE Limited - Photon House - Percy Street - Leeds LS12 1EG - UNITED KINGDOM - - 00-50-C2 (hex) Diva Systems - 122000-122FFF (base 16) Diva Systems - 800 Saginaw Dr. - Redwood City CA 94963 - UNITED STATES - - 00-50-C2 (hex) Seranoa Networks, Inc. - 123000-123FFF (base 16) Seranoa Networks, Inc. - Concord Office Center - 2352 Main St. - Concord MA 01742 - UNITED STATES - - 00-50-C2 (hex) Tokai Soft Corporation - 124000-124FFF (base 16) Tokai Soft Corporation - 6-55 Nagaosacho, Nakamuraku - Nagoya City, Aichi - JAPAN - - 00-50-C2 (hex) Tecwings GmBh - 125000-125FFF (base 16) Tecwings GmBh - A-2100 Korneuburg - Industriestrasse 1 - AUSTRIA - - 00-50-C2 (hex) Marvell Hispana S.L. - 126000-126FFF (base 16) Marvell Hispana S.L. - C/Charles Robert Darwin, 2 - Parc Tecnologic - Valencia Paterna 46980 - SPAIN - - 00-50-C2 (hex) TPA Traffic & Parking Automation BV - 127000-127FFF (base 16) TPA Traffic & Parking Automation BV - PO Box 5000 - 6802EA, Arnhem - NETHERLANDS - - 00-50-C2 (hex) Pycon, Inc. - 128000-128FFF (base 16) Pycon, Inc. - 3301 Leonard Ct. - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) TTPCom Ltd. - 129000-129FFF (base 16) TTPCom Ltd. - Melbourn Science Park - Cambridge Road, Melbourn - Royston, Herts SG8 6EE - UNITED KINGDOM - - 00-50-C2 (hex) Symbolic Sound Corp. - 12A000-12AFFF (base 16) Symbolic Sound Corp. - PO Box 2549 - Champaign IL 61825-2549 - UNITED STATES - - 00-50-C2 (hex) Dong A Eltek Co., Ltd. - 12B000-12BFFF (base 16) Dong A Eltek Co., Ltd. - 7704 Dongil Techno Town #7, 823 - Kwan Yang-2 Dong, DongAn-gu, Anyang-Si - Kyungki-Do, 431-062 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Delta Tau Data Systems, Inc. - 12C000-12CFFF (base 16) Delta Tau Data Systems, Inc. - 21314 Lassen St. - Chatsworth CA 91311 - UNITED STATES - - 00-50-C2 (hex) Megisto Systems, Inc. - 12D000-12DFFF (base 16) Megisto Systems, Inc. - 20251 Century Blvd. - Suite 120 - Germantown MD 20874 - UNITED STATES - - 00-50-C2 (hex) RUNCOM - 12E000-12EFFF (base 16) RUNCOM - 2 Hachoma St. 75655 - Rishon Lezion - ISRAEL - - 00-50-C2 (hex) HAAG-STREIT AG - 12F000-12FFFF (base 16) HAAG-STREIT AG - Gartenstadtstrasse 10 - Koeniz CH-3098 - SWITZERLAND - - 00-50-C2 (hex) U.S. Traffic Corporation - 130000-130FFF (base 16) U.S. Traffic Corporation - 9603 John St. - Santa Fe Springs CA 90670 - UNITED STATES - - 00-50-C2 (hex) InBus Engineering, Inc. - 131000-131FFF (base 16) InBus Engineering, Inc. - 6233 Industrial Way - Livermore CA 94550 - UNITED STATES - - 00-50-C2 (hex) Procon Electronics - 132000-132FFF (base 16) Procon Electronics - PO Box 164 - Seven Hills - Sydney NSW 1730 - AUSTRALIA - - 00-50-C2 (hex) ChipWrights, Inc. - 133000-133FFF (base 16) ChipWrights, Inc. - 2150 Washington St. - Newton MA 02462 - UNITED STATES - - 00-50-C2 (hex) DRS Photronics - 134000-134FFF (base 16) DRS Photronics - 133 Bauer Dr. - Oakland NJ 07436 - UNITED STATES - - 00-50-C2 (hex) ELAD SRL - 135000-135FFF (base 16) ELAD SRL - via col de rust, 11 - CANEVA PN 33070 - ITALY - - 00-50-C2 (hex) Tensilica, Inc. - 136000-136FFF (base 16) Tensilica, Inc. - 3255-G Scott Blvd. - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) Uniwell Systems (UK) Ltd. - 137000-137FFF (base 16) Uniwell Systems (UK) Ltd. - Uniwell Building, Challenge Way - Greenbank Technology Park - Blackburn Lancashire BB1 5US - UNITED KINGDOM - - 00-50-C2 (hex) Delphin Technology AG - 138000-138FFF (base 16) Delphin Technology AG - Offsermannsheider Str. 184 - 51515 Kurten - GERMANY - - 00-50-C2 (hex) SR Research Ltd. - 139000-139FFF (base 16) SR Research Ltd. - 740 Meadow Wood Road - Mississauga Ontario L5J 2S6 - CANADA - - 00-50-C2 (hex) Tex Computer SRL - 13A000-13AFFF (base 16) Tex Computer SRL - Via Mercadante, 35 - 47841 Cattocica (RN) - ITALY - - 00-50-C2 (hex) Vaisala Oyj - 13B000-13BFFF (base 16) Vaisala Oyj - Vanha Nurmijarventie 21 - Fin-01670 Vantaa - FINLAND - - 00-50-C2 (hex) NBG Industrial Automation B.V. - 13C000-13CFFF (base 16) NBG Industrial Automation B.V. - Hulsenweg 19 - 6031 SP Nederweert - NETHERLANDS - - 00-50-C2 (hex) Formula One Management Ltd. - 13D000-13DFFF (base 16) Formula One Management Ltd. - Sapphire House - Churchill Way - Biggin Hill Kent TN16 3BW - UNITED KINGDOM - - 00-50-C2 (hex) AVerMedia Systems, Inc. - 13E000-13EFFF (base 16) AVerMedia Systems, Inc. - 7F.,No. 137,Jian Yi Rd - Chung-Ho City Taipei - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Sentito Networks - 13F000-13FFFF (base 16) Sentito Networks - 2096 Gaither Rd., Suite 100 - Rockville MD 20850 - UNITED STATES - - 00-50-C2 (hex) ITS, Inc. - 140000-140FFF (base 16) ITS, Inc. - 3109 Poplarwood Ct. - Suite 206 - Raleigh NC 27604 - UNITED STATES - - 00-50-C2 (hex) Time Terminal Adductor Group AB - 141000-141FFF (base 16) Time Terminal Adductor Group AB - Norrbergrgatan 8 - Vaxholm 18532 - SWEDEN - - 00-50-C2 (hex) Instrumeter A/S - 142000-142FFF (base 16) Instrumeter A/S - Linde Alle 29 - Naerum DK-2850 - DENMARK - - 00-50-C2 (hex) AARTESYS AG - 143000-143FFF (base 16) AARTESYS AG - Bahnhofplatz 7 - Biel CH-2502 - SWITZERLAND - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 144000-144FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz D-55129 - GERMANY - - 00-50-C2 (hex) ELC Lighting - 145000-145FFF (base 16) ELC Lighting - Vic vd Asdocnstraat 14 - Gemert 5421VB - NETHERLANDS - - 00-50-C2 (hex) APCON, Inc. - 146000-146FFF (base 16) APCON, Inc. - 17938 SW Upper Bones Ferry Road - Portland OR 97224 - UNITED STATES - - 00-50-C2 (hex) UniSUR - 147000-147FFF (base 16) UniSUR - 7F, No.2-1, Industry E. Rd. - 1, Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Alltec GmbH - 148000-148FFF (base 16) Alltec GmbH - Seelandstr. 67 - Lubeck 23569 - GERMANY - - 00-50-C2 (hex) Haag-Streit AG - 149000-149FFF (base 16) Haag-Streit AG - Gartenstadtstrasse 10 - Köniz CH-3098 - SWITZERLAND - - 00-50-C2 (hex) DYCEC, S.A. - 14A000-14AFFF (base 16) DYCEC, S.A. - Torres Quevedo, 1-P.T.M. - Tres Cantos Madrid 28760 - SPAIN - - 00-50-C2 (hex) HECUBA Elektronik - 14B000-14BFFF (base 16) HECUBA Elektronik - Kranichweg 14 - St. Marien A-4502 - AUSTRIA - - 00-50-C2 (hex) Optibase Ltd. - 14C000-14CFFF (base 16) Optibase Ltd. - Shenkar 7 - Herzlya 46725 - ISRAEL - - 00-50-C2 (hex) wellink, Ltd. - 14D000-14DFFF (base 16) wellink, Ltd. - R&D Center, #307, A-Dong, - Bundang Technopark, 150 - Yatop-Dong, Pundang-Ku, Sungnam-Si, Kyungki-Do, - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Corinex Global - 14E000-14EFFF (base 16) Corinex Global - #308 1168, Hamilton Str. - Vancouver B.C. V6B 2S2 - CANADA - - 00-50-C2 (hex) Telephonics Corp. - 14F000-14FFFF (base 16) Telephonics Corp. - 815 Broad Hollow Road - Farmingdale NY 11735 - UNITED STATES - - 00-50-C2 (hex) Torse - 150000-150FFF (base 16) Torse - Waldrainstrasse 11 - Koeniz 3098 - SWITZERLAND - - 00-50-C2 (hex) Redux Communications Ltd. - 151000-151FFF (base 16) Redux Communications Ltd. - POB 101 - Modiin 71700 - ISRAEL - - 00-50-C2 (hex) AirVast Technology Inc. - 152000-152FFF (base 16) AirVast Technology Inc. - 22F, No. 1247, Chung-Chang Rd. - Tao Yuan - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Advanced Devices SpA - 153000-153FFF (base 16) Advanced Devices SpA - Via Spagna, 50 - Zona industriale, C/DA cutura - Rende (Cosenza) - ITALY - - 00-50-C2 (hex) Jostra AB - 154000-154FFF (base 16) Jostra AB - Annedalsv. 2B - Lund 22764 - SWEDEN - - 00-50-C2 (hex) Enea Real Time AB - 155000-155FFF (base 16) Enea Real Time AB - Drauegatan 7 - Goteborg SE-41250 - SWEDEN - - 00-50-C2 (hex) CommServ Solutions Inc. - 156000-156FFF (base 16) CommServ Solutions Inc. - 2217 Princess Anne Street - Suite 202 A-H - Fredericksburg VA 22401 - UNITED STATES - - 00-50-C2 (hex) nCore, Inc. - 157000-157FFF (base 16) nCore, Inc. - 2870 Perrowville Rd. - Forest VA 24551 - UNITED STATES - - 00-50-C2 (hex) Communication Solutions, Inc. - 158000-158FFF (base 16) Communication Solutions, Inc. - P.O. Box 43550 - Baltimore MD 21236-0550 - UNITED STATES - - 00-50-C2 (hex) Standard Comm. Corp. - 159000-159FFF (base 16) Standard Comm. Corp. - 1111 Knox Street - Torrance CA 90502 - UNITED STATES - - 00-50-C2 (hex) Plextek Limited - 15A000-15AFFF (base 16) Plextek Limited - London Road - Great Chesterford - Essex CB10 1NY - UNITED KINGDOM - - 00-50-C2 (hex) Dune Networks - 15B000-15BFFF (base 16) Dune Networks - France Bldg. - Indutstrial-Park. - Kibutz Yakum 60972 - ISRAEL - - 00-50-C2 (hex) Aoptix Technologies - 15C000-15CFFF (base 16) Aoptix Technologies - 580 Division St. - Campbell CA 95008 - UNITED STATES - - 00-50-C2 (hex) Cepheid - 15D000-15DFFF (base 16) Cepheid - 904 Caribbean Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) Celite Systems, Inc. - 15E000-15EFFF (base 16) Celite Systems, Inc. - 7600B Capital of Texas Hwy. N. - Suite 200 - Austin TX 78731 - UNITED STATES - - 00-50-C2 (hex) Pulsar GmbH - 15F000-15FFFF (base 16) Pulsar GmbH - Hollenstedter Strasse 43 - Heidenau 21258 - GERMANY - - 00-50-C2 (hex) TTI - Telecom International Ltd. - 160000-160FFF (base 16) TTI - Telecom International Ltd. - 7 Martin Gehl St. - Kinyat-Arie - Petach-Tikva P.O.B. 3050 49512 - ISRAEL - - 00-50-C2 (hex) J&B Engineering Group S.L. - 161000-161FFF (base 16) J&B Engineering Group S.L. - c/Francisco Silvela 36 Of. 5 - Madrid 28028 - SPAIN - - 00-50-C2 (hex) Teseda Corporation - 162000-162FFF (base 16) Teseda Corporation - 812 SW Washington St. - Suite 500 - Portland OR 97205-3232 - UNITED STATES - - 00-50-C2 (hex) Computerwise, Inc. - 163000-163FFF (base 16) Computerwise, Inc. - 302 N. Winchester Ln. - Olathe KS 66062 - UNITED STATES - - 00-50-C2 (hex) Acunia N.V. - 164000-164FFF (base 16) Acunia N.V. - Philips-Site 5 Box 3 - Leoven 3001 - BELGIUM - - 00-50-C2 (hex) IPCAST - 165000-165FFF (base 16) IPCAST - 2F, Youngwon B/D, 305-11, - Yangjae-Dong, Seocho-Gu - Seoul 137-130 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Infineer Ltd. - 166000-166FFF (base 16) Infineer Ltd. - Balloo Avenue - Bangor BT22 2SE - IRELAND - - 00-50-C2 (hex) Precision Filters, Inc. - 167000-167FFF (base 16) Precision Filters, Inc. - 240 Cherry Street - Ithica NY 14850 - UNITED STATES - - 00-50-C2 (hex) ExtremeSpeed Inc. - 168000-168FFF (base 16) ExtremeSpeed Inc. - PO Box 600 - 4634-46th Street Suite 201 - Mannville Alberta T0B 2W0 - CANADA - - 00-50-C2 (hex) Nordson Corp. - 169000-169FFF (base 16) Nordson Corp. - 11475 Lakefield Dr. - Daluth GA 30097 - UNITED STATES - - 00-50-C2 (hex) Time Domain - 16A000-16AFFF (base 16) Time Domain - 7057 Old Madison Pike - Huntsville AL 35806 - UNITED STATES - - 00-50-C2 (hex) Masterclock, Inc. - 16B000-16BFFF (base 16) Masterclock, Inc. - 2484 W. Clay St. - St. Charles MO 63301 - UNITED STATES - - 00-50-C2 (hex) Brijing Embedor Embedded Internet Tech. Co. Ltd. - 16C000-16CFFF (base 16) Brijing Embedor Embedded Internet Tech. Co. Ltd. - Room 401, Library Building, Noo. 35, - North Middle 4th Ring Road, - Beijing 100101 - CHINA - - 00-50-C2 (hex) Postec Data Systems Ltd. - 16D000-16DFFF (base 16) Postec Data Systems Ltd. - PO Box 302-230 - NHPC, Aukland - NEW ZEALAND - - 00-50-C2 (hex) PMC - 16E000-16EFFF (base 16) PMC - 56, Avenue Raspail - Saint Maur - FRANCE - - 00-50-C2 (hex) Dickson Technologies - 16F000-16FFFF (base 16) Dickson Technologies - 930 Westwood Ave. - Addison IL 60101 - UNITED STATES - - 00-50-C2 (hex) Taishodo Seiko Co., Ltd. - 170000-170FFF (base 16) Taishodo Seiko Co., Ltd. - 1-34, Kawahana-Chou, Toyokawa-shi, - Aich 442-0837 - JAPAN - - 00-50-C2 (hex) Quantronix, Inc. - 171000-171FFF (base 16) Quantronix, Inc. - 380 S. 200 W. - Farmington UT 84025 - UNITED STATES - - 00-50-C2 (hex) SAET I.S. S.r.l. - 172000-172FFF (base 16) SAET I.S. S.r.l. - Via Leini l/b - San Maurizio Canavese 10077 TO - ITALY - - 00-50-C2 (hex) DeMeTec GmbH - 173000-173FFF (base 16) DeMeTec GmbH - Luetzelwiessen 5 - Langgoens 35428 - GERMANY - - 00-50-C2 (hex) N&P Technologies - 174000-174FFF (base 16) N&P Technologies - Samsung Jangchung Branch - Office 201 120-1, Jangchung - Dong lga Jung-gu Seoul - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Sei S.p.A. - 175000-175FFF (base 16) Sei S.p.A. - Via Ruffilli, 1 - Curno (Bergamo) 24035 - ITALY - - 00-50-C2 (hex) Wavium AB - 176000-176FFF (base 16) Wavium AB - Västberga Allé 60 - Stockholm SE-126 75 - SWEDEN - - 00-50-C2 (hex) Unicoi Systems - 177000-177FFF (base 16) Unicoi Systems - 410 Peachtree Parkway - Bldg 400, Suite 4226 - Cumming GA 30041 - UNITED STATES - - 00-50-C2 (hex) Partner Voxstream A/S - 178000-178FFF (base 16) Partner Voxstream A/S - Trekanten 17 - Postboks 119 - Vojens D-6500 - DENMARK - - 00-50-C2 (hex) Verifiber LLC - 179000-179FFF (base 16) Verifiber LLC - 49 Buford Highway - Suwanne GA 30024 - UNITED STATES - - 00-50-C2 (hex) WOLF Industrial Systems Inc. - 17A000-17AFFF (base 16) WOLF Industrial Systems Inc. - 5 Foxfire Chase - Uxbridge Ontario L9P 1R4 - CANADA - - 00-50-C2 (hex) Broadstorm Telecom - 17B000-17BFFF (base 16) Broadstorm Telecom - 400 - 112th Ave. NE - Suite 250 - Bellevue WA 98004 - UNITED STATES - - 00-50-C2 (hex) Jeffress Engineering Pty Ltd - 17C000-17CFFF (base 16) Jeffress Engineering Pty Ltd - PO Box 195 - Dry Creek SA 5094 - AUSTRALIA - - 00-50-C2 (hex) Cognex Corporation - 17D000-17DFFF (base 16) Cognex Corporation - 15865 SW 74th Suite 105 - Portland OR 97224 - UNITED STATES - - 00-50-C2 (hex) Binary Wave Technologies Inc. - 17E000-17EFFF (base 16) Binary Wave Technologies Inc. - 106 Schneider Road, Unit C - Ottawa Ontario K2K 1Y2 - CANADA - - 00-50-C2 (hex) PDQ Manufacturing - 17F000-17FFFF (base 16) PDQ Manufacturing - 1698 Scheuring Road - De Pere WI 54115 - UNITED STATES - - 00-50-C2 (hex) Zultys Technologies - 180000-180FFF (base 16) Zultys Technologies - 771 Vagueros Ave. - Sunnyvale CA 94085-5327 - UNITED STATES - - 00-50-C2 (hex) Task 84 Spa - 181000-181FFF (base 16) Task 84 Spa - Via Boschetti N. 61 - Grassobbio (BG) 24050 - ITALY - - 00-50-C2 (hex) wolf-inf-tec - 182000-182FFF (base 16) wolf-inf-tec - Heinrich-Hertz-Strasse 19 - Bremen 28211 - GERMANY - - 00-50-C2 (hex) Mixbaal S.A. de C.V. - 183000-183FFF (base 16) Mixbaal S.A. de C.V. - Blvd. José Guadalupe Zuno #48-MIX - Los Belenes - Zapopan Jalisco 45101 - MEXICO - - 00-50-C2 (hex) H M Computing Limited - 184000-184FFF (base 16) H M Computing Limited - Harmac House - Enigma Business Park - Malvern Worcestershire WR14 1GP - UNITED KINGDOM - - 00-50-C2 (hex) Optical Wireless Link Inc. - 185000-185FFF (base 16) Optical Wireless Link Inc. - 9 Cushing Suite 100 - Irvine California 92618 - UNITED STATES - - 00-50-C2 (hex) Pantec Engineering AG - 186000-186FFF (base 16) Pantec Engineering AG - Industriezone - Mauren Liechtenstein 9493 - LIECHTENSTEIN - - 00-50-C2 (hex) Cyan Technology Ltd - 187000-187FFF (base 16) Cyan Technology Ltd - Unit 2, Buckingway Business Park - Swavesey Cambridge CB24 4UQ - UNITED KINGDOM - - 00-50-C2 (hex) dresden-elektronik - 188000-188FFF (base 16) dresden-elektronik - Glasewaldtstraße 22 - Dresden D-01277 - GERMANY - - 00-50-C2 (hex) CC Systems AB - 189000-189FFF (base 16) CC Systems AB - Box 83 - Alfta 822 22 - SWEDEN - - 00-50-C2 (hex) Basler Electric Company - 18A000-18AFFF (base 16) Basler Electric Company - 12570 State Route 143 - Highland Illinois 62249 - UNITED STATES - - 00-50-C2 (hex) Teradyne Inc. - 18B000-18BFFF (base 16) Teradyne Inc. - 30801 Agoura Rd. - Agoura Hills CA 91301 - UNITED STATES - - 00-50-C2 (hex) Technodrive srl - 18C000-18CFFF (base 16) Technodrive srl - Via Leonardo da Vinci 162 - Trezzano S/N Milan 20090 - ITALY - - 00-50-C2 (hex) CCII Systems (Pty) Ltd - 18D000-18DFFF (base 16) CCII Systems (Pty) Ltd - Unit 3, 67 Rosmead Avenue - Kenilworth - Cape Town Cape 7708 - SOUTH AFRICA - - 00-50-C2 (hex) SPARR ELECTRONICS LTD - 18E000-18EFFF (base 16) SPARR ELECTRONICS LTD - 43, HMT MAIN RD - MATHIKERE - BANGALORE KARNATAKA 560054 - INDIA - - 00-50-C2 (hex) MATSUI MFG CO.,LTD - 18F000-18FFFF (base 16) MATSUI MFG CO.,LTD - 2-19 Shodai-Tadika - Hirakata-City Osaka 573-1132 - JAPAN - - 00-50-C2 (hex) Goerlitz AG - 190000-190FFF (base 16) Goerlitz AG - August-Thyssen-Str. 32 - Koblenz Rheinland-Pfalz 56070 - GERMANY - - 00-50-C2 (hex) Partner Voxstream A/S - 191000-191FFF (base 16) Partner Voxstream A/S - Trekanten 17 - Postboks 119 - Vojens DK-6500 - DENMARK - - 00-50-C2 (hex) Advanced Concepts, Inc. - 192000-192FFF (base 16) Advanced Concepts, Inc. - 158 W. Johnstown Rd. - Gahanna Ohio 43230 - UNITED STATES - - 00-50-C2 (hex) LaserBit Communications Corp. - 193000-193FFF (base 16) LaserBit Communications Corp. - Kunigunda u. 45 - Budapest 1037 - HUNGARY - - 00-50-C2 (hex) COMINFO - 194000-194FFF (base 16) COMINFO - Lesetin 651 - Zlin 760 01 - CZECH REPUBLIC - - 00-50-C2 (hex) Momentum Data Systems - 195000-195FFF (base 16) Momentum Data Systems - 17330 Brookhurst Street - Suite 230 - Fountain Valley CA 92708 - UNITED STATES - - 00-50-C2 (hex) Netsynt Spa - 196000-196FFF (base 16) Netsynt Spa - Via A. G. Resti, 53 - Roma 00143 - ITALY - - 00-50-C2 (hex) EPM Tecnologia e Equipamentos - 197000-197FFF (base 16) EPM Tecnologia e Equipamentos - Av Com Gumercindo Barranqueiros, 285 - Jundiaí São Paulo 13211-410 - BRAZIL - - 00-50-C2 (hex) PotsTek, Inc - 198000-198FFF (base 16) PotsTek, Inc - 100 Saint Albans Dr. - Suite 100 - Raleigh NC 27609-5872 - UNITED STATES - - 00-50-C2 (hex) Survalent Technology Corporation - 199000-199FFF (base 16) Survalent Technology Corporation - 2600 Argentia RD - Mississauga Ontario L5N 5V4 - CANADA - - 00-50-C2 (hex) AZIO TECHNOLOGY CO. - 19A000-19AFFF (base 16) AZIO TECHNOLOGY CO. - 1F, 215-7, Poi-dong, Kangnam-Gu - Seoul 135-260 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Wilcoxon Research, Inc. - 19B000-19BFFF (base 16) Wilcoxon Research, Inc. - 21 Firstfield Road - Gaithersburg MD 20878 - UNITED STATES - - 00-50-C2 (hex) Artec Design - 19C000-19CFFF (base 16) Artec Design - Teaduspargi 6/1 - Tallinn 12618 - ESTONIA - - 00-50-C2 (hex) ELECTREX S.R.L - 19D000-19DFFF (base 16) ELECTREX S.R.L - VIA CLAUDIA 96 - SAVIGNANO SUL PANARO MODENA 41056 - ITALY - - 00-50-C2 (hex) Paltronics, Inc. - 19E000-19EFFF (base 16) Paltronics, Inc. - 9246 Trinity Drive - Lake in the Hills IL 60156 - UNITED STATES - - 00-50-C2 (hex) Fleetwood Electronics Ltd - 19F000-19FFFF (base 16) Fleetwood Electronics Ltd - The Irwin Centre - Cambridge Cambridgeshire CB3 8AR - UNITED KINGDOM - - 00-50-C2 (hex) SCA Data Systems - 1A0000-1A0FFF (base 16) SCA Data Systems - 3400 Airport Ave - Suite 101 - Santa Monica CA 90405 - UNITED STATES - - 00-50-C2 (hex) Portalplayer, Inc - 1A1000-1A1FFF (base 16) Portalplayer, Inc - 3255 Scott Blvd - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) ABB Switzerland Inc - 1A2000-1A2FFF (base 16) ABB Switzerland Inc - Dept. Dw/ATBN - Baden Aargau CH 5401 - SWITZERLAND - - 00-50-C2 (hex) Tidel Engineering, L.P. - 1A3000-1A3FFF (base 16) Tidel Engineering, L.P. - 2310 McDaniel Dr - Carrollton TX 75006 - UNITED STATES - - 00-50-C2 (hex) Protech Optronics Co. Ltd. - 1A4000-1A4FFF (base 16) Protech Optronics Co. Ltd. - 5th Floor, No. 82-3 Dongsung Street, Sulin City - Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) NORCO - 1A5000-1A5FFF (base 16) NORCO - 5# QUNYINGKEJIYUAN - SHANGDI HAIDIAN BEIJING - BEIJIN BEIJING 100084 - CHINA - - 00-50-C2 (hex) RF Code - 1A6000-1A6FFF (base 16) RF Code - 1250 S. Clearview Ave. - Mesa AZ 85208-3378 - UNITED STATES - - 00-50-C2 (hex) Alpha Beta Technologies, Inc. - 1A7000-1A7FFF (base 16) Alpha Beta Technologies, Inc. - 3112 12th Ave. S.W. - Huntsville AL 35805 - UNITED STATES - - 00-50-C2 (hex) ANOVA BROADBAND - 1A8000-1A8FFF (base 16) ANOVA BROADBAND - 4501 SINGER CT #201 - CHANTILLY VA 20151 - UNITED STATES - - 00-50-C2 (hex) Axotec Technologies GmbH - 1A9000-1A9FFF (base 16) Axotec Technologies GmbH - Sudetenstraße 88 - Geretsried Bavaria 82538 - GERMANY - - 00-50-C2 (hex) BitBox Ltd - 1AA000-1AAFFF (base 16) BitBox Ltd - Whitney Road - Daneshill Industrial Estate - Basingstoke Hampshire RG24 8NS - UNITED KINGDOM - - 00-50-C2 (hex) Streaming Networks - 1AB000-1ABFFF (base 16) Streaming Networks - House # 8 St # 31 F-7/1 - Islamabad 44000 - PAKISTAN - - 00-50-C2 (hex) Beckmann+Egle GmbH - 1AC000-1ACFFF (base 16) Beckmann+Egle GmbH - Auf der Höhe 10 - Kernen-Rommelshausen BaWü 71394 - GERMANY - - 00-50-C2 (hex) Remia s.r.o. - 1AD000-1ADFFF (base 16) Remia s.r.o. - Letna 42 - Kosice KE 04001 - SLOVAKIA - - 00-50-C2 (hex) Home Director, Inc - 1AE000-1AEFFF (base 16) Home Director, Inc - 3751-A South Alston Ave. - Durham NC 27713 - UNITED STATES - - 00-50-C2 (hex) PESA Switching Systems, Inc. - 1AF000-1AFFFF (base 16) PESA Switching Systems, Inc. - 330A Wynn Drive - Huntsville AL 35805 - UNITED STATES - - 00-50-C2 (hex) BLANKOM Antennentechnik GmbH - 1B0000-1B0FFF (base 16) BLANKOM Antennentechnik GmbH - Bahnhofstr. 39 - Bad Blankenburg Deutschland D-07422 - GERMANY - - 00-50-C2 (hex) Axes Technologies - 1B1000-1B1FFF (base 16) Axes Technologies - 14333 Proton Rd - Dallas TX 75244 - UNITED STATES - - 00-50-C2 (hex) SIGOS Systemintegration GmbH - 1B2000-1B2FFF (base 16) SIGOS Systemintegration GmbH - Klingenhofstrasse 50d - Nuernberg Bayern 90411 - GERMANY - - 00-50-C2 (hex) DSP DESIGN - 1B3000-1B3FFF (base 16) DSP DESIGN - TAPTON PK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) DSP Group Inc. - 1B4000-1B4FFF (base 16) DSP Group Inc. - 937D Plum Grove rd. - Shaumburg IL 60173 - UNITED STATES - - 00-50-C2 (hex) Thrane & Thrane A/S - 1B5000-1B5FFF (base 16) Thrane & Thrane A/S - Lundtoftegaardsvej 93D - Kgl. Lyngby DK 2800 - DENMARK - - 00-50-C2 (hex) DTS, Inc. - 1B6000-1B6FFF (base 16) DTS, Inc. - 4920 Grisham Dr. - Rowlett TX 75093 - UNITED STATES - - 00-50-C2 (hex) MosChip USA - 1B7000-1B7FFF (base 16) MosChip USA - 3335 Kifer Rd - Santa Clara CA 95051 - UNITED STATES - - 00-50-C2 (hex) Electronic Systems Development - 1B8000-1B8FFF (base 16) Electronic Systems Development - 39 Batavia St - Somerset West Cape Province 7130 - SOUTH AFRICA - - 00-50-C2 (hex) EmCom Technology Inc. - 1B9000-1B9FFF (base 16) EmCom Technology Inc. - 7F, 219, Sec. 3, Nanking E. Rd., - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) INTERZEAG AG - 1BA000-1BAFFF (base 16) INTERZEAG AG - Rietbachstrasse 5 - Schlieren CH-8952 - SWITZERLAND - - 00-50-C2 (hex) Email Metering - 1BB000-1BBFFF (base 16) Email Metering - Joynton Avenue - Zetland New South Wales 2017 - AUSTRALIA - - 00-50-C2 (hex) DINEC International - 1BC000-1BCFFF (base 16) DINEC International - Rue de la Gare, 30 - BRAINE L'ALLEUD BW 1420 - BELGIUM - - 00-50-C2 (hex) AIOI Systems Co., Ltd. - 1BD000-1BDFFF (base 16) AIOI Systems Co., Ltd. - KDX Omori, Bldg 8F - 1-6-8 Omori Kita, Ota-ku - Tokyo 140-0016 - JAPAN - - 00-50-C2 (hex) Sedia Electronics - 1BE000-1BEFFF (base 16) Sedia Electronics - Omilio Monteiro Soares, 1590 - Curitiba Parana 80320-210 - BRAZIL - - 00-50-C2 (hex) International Test & Engineering Services Co.,Ltd. - 1BF000-1BFFFF (base 16) International Test & Engineering Services Co.,Ltd. - 800, Ichimiyake, - Yasu-cho, Yasu-gun, Shiga-ken, 520-2392 - JAPAN - - 00-50-C2 (hex) WillMonius Inc. - 1C0000-1C0FFF (base 16) WillMonius Inc. - 425-1 Kil1-dong, Kangdong-gu - Seoul 134-011 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) InfinitiNetworks Inc. - 1C1000-1C1FFF (base 16) InfinitiNetworks Inc. - 1095 E. Duane Ave. - Suite #205 - Sunnyvale CA 94085 - UNITED STATES - - 00-50-C2 (hex) Weltronics Corp. - 1C2000-1C2FFF (base 16) Weltronics Corp. - 1414 Fair Oaks Ave. - Suite 7 - South Pasadena CA 91030 - UNITED STATES - - 00-50-C2 (hex) TT electronic manufacturing services ltd - 1C3000-1C3FFF (base 16) TT electronic manufacturing services ltd - Kitty Brewster Estate - Blyth Northumberland NE3 2AX - UNITED KINGDOM - - 00-50-C2 (hex) Palm Solutions Group - 1C4000-1C4FFF (base 16) Palm Solutions Group - 400 N. McCarthy Blvd - Milpitas CA 95035-5112 - UNITED STATES - - 00-50-C2 (hex) Flander Oy - 1C5000-1C5FFF (base 16) Flander Oy - Satakunnankatu 18B - Tampere Pirkkala 33 210 - FINLAND - - 00-50-C2 (hex) Remco Italia Spa - 1C6000-1C6FFF (base 16) Remco Italia Spa - Strada Rivoltana Nuova 53 - Vignate MI 20060 - ITALY - - 00-50-C2 (hex) TWIN DEVELOPMENT S.A. - 1C7000-1C7FFF (base 16) TWIN DEVELOPMENT S.A. - Av. General Michel, 1E - CHARLEROI Hainaut B6000 - BELGIUM - - 00-50-C2 (hex) Euphony technology CO., LTD. - 1C8000-1C8FFF (base 16) Euphony technology CO., LTD. - 7FI.-4, No.131, Lane235, Bauchiau RD., S - Shindian City Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) modas GmbH - 1C9000-1C9FFF (base 16) modas GmbH - Buelowstr. 90 - Berlin 10783 - GERMANY - - 00-50-C2 (hex) EVER Sp. z o.o. - 1CA000-1CAFFF (base 16) EVER Sp. z o.o. - ul. Grudzinskiego 30 - Swarzedz wielkopolskie 62-020 - POLAND - - 00-50-C2 (hex) quantumBEAM Limited - 1CB000-1CBFFF (base 16) quantumBEAM Limited - Abbey Barns - Duxford Road - Ickleton Cambridgeshire CB10 1SX - UNITED KINGDOM - - 00-50-C2 (hex) WaveIP ltd. - 1CC000-1CCFFF (base 16) WaveIP ltd. - Teradion Industrial Park - Misgav 20179 - ISRAEL - - 00-50-C2 (hex) INCAA Informatica Italia srl - 1CD000-1CDFFF (base 16) INCAA Informatica Italia srl - Via dei Castagni, 84/2 - MALGESSO VARESE 21023 - ITALY - - 00-50-C2 (hex) Datatek Applications, Inc. - 1CE000-1CEFFF (base 16) Datatek Applications, Inc. - 399 Campus Drive - Suite 140 - Somerset NJ 08873 - UNITED STATES - - 00-50-C2 (hex) LIFETIME MEMORY PRODUCTS, INC. - 1CF000-1CFFFF (base 16) LIFETIME MEMORY PRODUCTS, INC. - 2505 DAVINCI STREET - IRVINE CA 92614 - UNITED STATES - - 00-50-C2 (hex) Yazaki North America, Inc. - 1D0000-1D0FFF (base 16) Yazaki North America, Inc. - 6801 Haggerty Road - Canton MI 48187 - UNITED STATES - - 00-50-C2 (hex) Benchmark Electronics - 1D1000-1D1FFF (base 16) Benchmark Electronics - 4065 Theurer Blvd. - Winona MN 55987 - UNITED STATES - - 00-50-C2 (hex) Shenyang Internet Technology Inc - 1D2000-1D2FFF (base 16) Shenyang Internet Technology Inc - 2413 Frosted Green Ln - Plano Texas 75025 - UNITED STATES - - 00-50-C2 (hex) Synopsys - 1D3000-1D3FFF (base 16) Synopsys - Le Symphonie Sud - 1140 Avenue Albert Einstein - Montpellier 34000 - FRANCE - - 00-50-C2 (hex) Phase IV Engineering Inc. - 1D4000-1D4FFF (base 16) Phase IV Engineering Inc. - 2820 Wilderness Place, Suite C - Bolder Colorado 80301 - UNITED STATES - - 00-50-C2 (hex) Redpoint Controls - 1D5000-1D5FFF (base 16) Redpoint Controls - 364 Patteson Drive - Suite 279 - Morgantown WV 26505 - UNITED STATES - - 00-50-C2 (hex) shanghai trend intelligent systems CO.,LTD - 1D6000-1D6FFF (base 16) shanghai trend intelligent systems CO.,LTD - floor 10,xinan building,NO.200,zhennin R - shanghai 200040 - CHINA - - 00-50-C2 (hex) Pleora Technologies Inc. - 1D7000-1D7FFF (base 16) Pleora Technologies Inc. - 359 Terry Fox Drive, Suite 230 - Kanata ON K2K 2E7 - CANADA - - 00-50-C2 (hex) Guardian Controls International - 1D8000-1D8FFF (base 16) Guardian Controls International - 56, Crewe Road, - Sandbach Cheshire CW11 4NN - UNITED KINGDOM - - 00-50-C2 (hex) EDC - 1D9000-1D9FFF (base 16) EDC - Hansestr. 24 - Muenster NRW 48163 - GERMANY - - 00-50-C2 (hex) GFI Chrono Time - 1DA000-1DAFFF (base 16) GFI Chrono Time - 121 rue des Guillees - CHAURAY 79180 - FRANCE - - 00-50-C2 (hex) Applied Systems Engineering, Inc. - 1DB000-1DBFFF (base 16) Applied Systems Engineering, Inc. - 1671 Dell Ave. - Suite 200 - Campbell CA 95008 - UNITED STATES - - 00-50-C2 (hex) Imarda New Zealand Limited - 1DC000-1DCFFF (base 16) Imarda New Zealand Limited - Suite G16, National Innovation Centre, - Australian Technology Park, - Eveleigh NSW 2015 - NEW ZEALAND - - 00-50-C2 (hex) Peiker acustic GmbH & Co. KG - 1DD000-1DDFFF (base 16) Peiker acustic GmbH & Co. KG - Max-Planck-Strasse 32 - Friedrichsdorf Hessen 61381 - GERMANY - - 00-50-C2 (hex) ReliOn Inc. - 1DE000-1DEFFF (base 16) ReliOn Inc. - 15913 E Euclid Ave - Spokane WA 99216 - UNITED STATES - - 00-50-C2 (hex) Lulea University of Technology - 1DF000-1DFFFF (base 16) Lulea University of Technology - University Campus - Lulea Norrbotten SE-971 87 - SWEDEN - - 00-50-C2 (hex) Cognex Corporation - 1E0000-1E0FFF (base 16) Cognex Corporation - 1 Vision Drive - Natick MA 01760 - UNITED STATES - - 00-50-C2 (hex) Automaatiotekniikka Seppo Saari Oy - 1E1000-1E1FFF (base 16) Automaatiotekniikka Seppo Saari Oy - Tilhenkatu 1 - Turku 20610 - FINLAND - - 00-50-C2 (hex) DIGITRONIC Automationsanlagen GmbH - 1E2000-1E2FFF (base 16) DIGITRONIC Automationsanlagen GmbH - Auf der Langwies 1 - Huenstetten-Wallbach Hessen 65510 - GERMANY - - 00-50-C2 (hex) Bluesocket, Inc. - 1E3000-1E3FFF (base 16) Bluesocket, Inc. - 7 New England Executive Park - 4th Floor - Burlington MA 01803 - UNITED STATES - - 00-50-C2 (hex) Soronti, Inc. - 1E4000-1E4FFF (base 16) Soronti, Inc. - 12159 Business Park Dr, suite 140 - Draper Utah 84020 - UNITED STATES - - 00-50-C2 (hex) DORLET S.A. - 1E5000-1E5FFF (base 16) DORLET S.A. - Albert Einstein 34 - Parque Tecnológico de Alava - Miñano Mayor ALAVA 01510 - SPAIN - - 00-50-C2 (hex) United Tri-Tech Corporation - 1E6000-1E6FFF (base 16) United Tri-Tech Corporation - 550 Campbell Street - Cornwall Ontario K6H 6T7 - CANADA - - 00-50-C2 (hex) Smith Meter, Inc. - 1E7000-1E7FFF (base 16) Smith Meter, Inc. - 1602 Wagner Ave. - Erie PA 16510 - UNITED STATES - - 00-50-C2 (hex) Metrotech - 1E8000-1E8FFF (base 16) Metrotech - 901-Ho, 21 Century City Building, 55-1 B - Busan KyungNam 608-743 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Ranch Networks - 1E9000-1E9FFF (base 16) Ranch Networks - 65 Rt. 34 - Suite 200 - Morganville NJ 07751 - UNITED STATES - - 00-50-C2 (hex) DAVE S.r.L. - 1EA000-1EAFFF (base 16) DAVE S.r.L. - via Talponedo 29/A - Porcia PN 33170 - ITALY - - 00-50-C2 (hex) Data Respons A/S - 1EB000-1EBFFF (base 16) Data Respons A/S - Horkaer 18, 1. floor - Herlev DK-2730 - DENMARK - - 00-50-C2 (hex) COSMO co.,ltd. - 1EC000-1ECFFF (base 16) COSMO co.,ltd. - TAKARAMACHI 1-BANCHI - YOKKAICHI-SHI MIE 510-0844 - JAPAN - - 00-50-C2 (hex) EMKA-electronic AG - 1ED000-1EDFFF (base 16) EMKA-electronic AG - Lohmühlenweg 18a - Arnstadt Thüringen 99310 - GERMANY - - 00-50-C2 (hex) Perto Periféricos de Automação S.A. - 1EE000-1EEFFF (base 16) Perto Periféricos de Automação S.A. - Rua Nissin Castiel, 640 - Distrito Industrial de Gravataí - Gravataí RS 94000-970 - BRAZIL - - 00-50-C2 (hex) M2 Technology Pty Ltd - 1EF000-1EFFFF (base 16) M2 Technology Pty Ltd - 26 Greenhill Road - Wayville South Australia 5034 - AUSTRALIA - - 00-50-C2 (hex) EXI Wireless Systems Inc. - 1F0000-1F0FFF (base 16) EXI Wireless Systems Inc. - #100-13551 Commerce Parkway - Richmond BC V6V 2L1 - CANADA - - 00-50-C2 (hex) SKY Computers, Inc. - 1F1000-1F1FFF (base 16) SKY Computers, Inc. - 27 Industrial Ave - Chelmsford Mass 01824 - UNITED STATES - - 00-50-C2 (hex) Tattile srl - 1F2000-1F2FFF (base 16) Tattile srl - Via Trento 127/129 - Capriano del Colle Brescia 25020 - ITALY - - 00-50-C2 (hex) Radionor Communications AS - 1F3000-1F3FFF (base 16) Radionor Communications AS - Ingvald Ystgaards vei 23 - N-7047 Trondheim - NORWAY - - 00-50-C2 (hex) Covia, Inc - 1F4000-1F4FFF (base 16) Covia, Inc - 2F-1,No.166,Chien-Yi Rd., - Chung Ho City Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Abest Communication Corp. - 1F5000-1F5FFF (base 16) Abest Communication Corp. - 19-7 Ting-Tien-Liao, Hsien-Jenli Tamshui - Taipei 251 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) BAE SYSTEMS Controls - 1F6000-1F6FFF (base 16) BAE SYSTEMS Controls - Rm 373 - 600 Main Street - Johnson City NY 13790 - UNITED STATES - - 00-50-C2 (hex) ARC'Créations - 1F7000-1F7FFF (base 16) ARC'Créations - ZI les Milles 100 rue Pierre DUHEM - La Robole Bt A Cedex 3 - Aix en Provence BDR 13856 - FRANCE - - 00-50-C2 (hex) ULTRACKER TECHNOLOGY - 1F8000-1F8FFF (base 16) ULTRACKER TECHNOLOGY - 3F-2,No.1247 ,Chung-Cheng Rd,Taoyuan cit - Taoyuan 330 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Fr. Sauter AG - 1F9000-1F9FFF (base 16) Fr. Sauter AG - Im Surinam - Basel BL 4016 - SWITZERLAND - - 00-50-C2 (hex) SP Controls, Inc - 1FA000-1FAFFF (base 16) SP Controls, Inc - 930 Linden Avenue - San Francisco CA 94080 - UNITED STATES - - 00-50-C2 (hex) Willowglen Systems Inc. - 1FB000-1FBFFF (base 16) Willowglen Systems Inc. - 8522 - Davies Road - Edmonton AB T6E 4Y5 - CANADA - - 00-50-C2 (hex) EDD Srl - 1FC000-1FCFFF (base 16) EDD Srl - Via della Repubblica,27 - Levata - Curtatone Mantova 46010 - ITALY - - 00-50-C2 (hex) SouthWing S.L. - 1FD000-1FDFFF (base 16) SouthWing S.L. - Calle Llacuna 162 - Barcelona Catalunya 08018 - SPAIN - - 00-50-C2 (hex) Safetran Traffic Systems Inc. - 1FE000-1FEFFF (base 16) Safetran Traffic Systems Inc. - 1485 Garden of the Gods Rd. - Colorado Springs Colorado 80907 - UNITED STATES - - 00-50-C2 (hex) Product Design Dept., Sohwa Corporation - 1FF000-1FFFFF (base 16) Product Design Dept., Sohwa Corporation - Shinyokohama Tobu AK Bldg. - 3-23-3 Shinyokohama Kohoku-ku - Yokohama Kanagawa 222-0033 - JAPAN - - 00-50-C2 (hex) Whittier Mailing Products, Inc. - 200000-200FFF (base 16) Whittier Mailing Products, Inc. - 13019 Park Street - Santa Fe Springs California 90670 - UNITED STATES - - 00-50-C2 (hex) OlympusNDT - 201000-201FFF (base 16) OlympusNDT - 421 N Quay - Kennewick WA 99336 - UNITED STATES - - 00-50-C2 (hex) Audio Riders Oy - 202000-202FFF (base 16) Audio Riders Oy - Jarvihaantie 4 - Klaukkala Uusimaa 01800 - FINLAND - - 00-50-C2 (hex) Vocality International Ltd - 203000-203FFF (base 16) Vocality International Ltd - Lydling Barn - Puttenham Lane - Shackleford Surrey GU8 6AP - UNITED KINGDOM - - 00-50-C2 (hex) Algodue Elettronica srl - 204000-204FFF (base 16) Algodue Elettronica srl - Via Passerina 3 - Fontaneto d'Agogna Novara 28010 - ITALY - - 00-50-C2 (hex) SystIng - 205000-205FFF (base 16) SystIng - Schmalholzstr. 17 - Kaufering bavaria 86916 - GERMANY - - 00-50-C2 (hex) Windmill Innovations - 206000-206FFF (base 16) Windmill Innovations - Beurtschipper 20 - Nijkerk GLD 3861SC - NETHERLANDS - - 00-50-C2 (hex) Solectron Ind.Com.Servs.Exportadora do Brasil Ltda. - 207000-207FFF (base 16) Solectron Ind.Com.Servs.Exportadora do Brasil Ltda. - ROD. CAMPINAS-MOGI MIRIM, KM 133 - JD. ROSEIRA - JAGUARIUNA São Paulo 13820-000 - BRAZIL - - 00-50-C2 (hex) nNovia, Inc. - 208000-208FFF (base 16) nNovia, Inc. - 1620 Oakland Rd. - Suite D200 - San jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) LK Ltd - 209000-209FFF (base 16) LK Ltd - Argosy Road - East Midlands Airport - Castle Donington Derby DE74 2SA - UNITED KINGDOM - - 00-50-C2 (hex) Ferrari electronic AG - 20A000-20AFFF (base 16) Ferrari electronic AG - Ruhlsdorfer Str. 138 - TELTOW 14513 - GERMANY - - 00-50-C2 (hex) Rafael - 20B000-20BFFF (base 16) Rafael - Library dep. C0-900 - P.o.b. 962 31009 - Haifa 31009 - ISRAEL - - 00-50-C2 (hex) Communication and Telemechanical Systems Company Limited - 20C000-20CFFF (base 16) Communication and Telemechanical Systems Company Limited - Gragdanski str. 111 - St.Petersburg 195256 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Varisys Ltd - 20D000-20DFFF (base 16) Varisys Ltd - 17 Manor Courtyard - Hughenden Avenue - Great Haseley High Wycombe BUCKS HP13 5 - UNITED KINGDOM - - 00-50-C2 (hex) PYRAMID Computer Systeme GmbH - 20E000-20EFFF (base 16) PYRAMID Computer Systeme GmbH - Boetzinger Strasse 60 - Freiburg BW 79111 - GERMANY - - 00-50-C2 (hex) OMICRON electronics GmbH - 20F000-20FFFF (base 16) OMICRON electronics GmbH - Oberes Ried 1 - Klaus A-6833 - AUSTRIA - - 00-50-C2 (hex) Innovics Wireless Inc - 210000-210FFF (base 16) Innovics Wireless Inc - 11500 W Olympic Blvd - Suite 398 - Los Angeles CA 90064 - UNITED STATES - - 00-50-C2 (hex) Hochschule für Technik, Wirtschaft und Kultur Leipzig (FH) - 211000-211FFF (base 16) Hochschule für Technik, Wirtschaft und Kultur Leipzig (FH) - Wächterstraße 13 - Leipzig Saxonia D-04107 - GERMANY - - 00-50-C2 (hex) 4Links Limited - 212000-212FFF (base 16) 4Links Limited - PO Box 816, The Mansion - Bletchley Park - Milton Keynes Buckinghamshire MK3 6ZP - UNITED KINGDOM - - 00-50-C2 (hex) SysAware S.A.R.L. - 213000-213FFF (base 16) SysAware S.A.R.L. - Mas David - Vezenobres Gard 30360 - FRANCE - - 00-50-C2 (hex) Oshimi System Design Inc. - 214000-214FFF (base 16) Oshimi System Design Inc. - 2-55-2 - Arakawa - Arakawa-ku Tokyo 116-0002 - JAPAN - - 00-50-C2 (hex) VoiceCom AG - 215000-215FFF (base 16) VoiceCom AG - Südwestpark 65 - Nürnberg Germany 90449 - GERMANY - - 00-50-C2 (hex) Level Control Systems - 216000-216FFF (base 16) Level Control Systems - #42 - 100 Kal Lake Rd. - Vernon B.C. V1T 9G1 - CANADA - - 00-50-C2 (hex) Linn Products Ltd - 217000-217FFF (base 16) Linn Products Ltd - Glasgow Road - Waterfoot - Glasgow Scotland G76 0EQ - UNITED KINGDOM - - 00-50-C2 (hex) Nansen S. A. - Instrumentos de Precisão - 218000-218FFF (base 16) Nansen S. A. - Instrumentos de Precisão - José Pedro Araújo, 960 - Contagem Minas Gerais 32341560 - BRAZIL - - 00-50-C2 (hex) Aeroflex GmbH - 219000-219FFF (base 16) Aeroflex GmbH - Gutenbergstrasse 2-4 - Ismaning Bavaria 85737 - GERMANY - - 00-50-C2 (hex) MST SYSTEMS LIMITED - 21A000-21AFFF (base 16) MST SYSTEMS LIMITED - The Haysfield - Spring Lane North - Malvern Worcestershire WR14 1GF - UNITED KINGDOM - - 00-50-C2 (hex) General Dynamics Decision Systems - 21B000-21BFFF (base 16) General Dynamics Decision Systems - 8220 E. Roosevelt Street - M/D R7125 - Scottsdale AZ 85257 - UNITED STATES - - 00-50-C2 (hex) Fracarro Radioindustrie SPA - 21C000-21CFFF (base 16) Fracarro Radioindustrie SPA - Via Cazzaro 3 - Castelfranco Veneto Treviso 31033 - ITALY - - 00-50-C2 (hex) ESG Elektroniksystem u. Logistik GmbH - 21D000-21DFFF (base 16) ESG Elektroniksystem u. Logistik GmbH - Einsteinstr. 174 - Muenchen Bayern 81675 - GERMANY - - 00-50-C2 (hex) Applied Technologies Associates - 21E000-21EFFF (base 16) Applied Technologies Associates - 3025 Buena Vista Drive - Paso Robles CA 93446 - UNITED STATES - - 00-50-C2 (hex) Monitor Business Machines Ltd - 21F000-21FFFF (base 16) Monitor Business Machines Ltd - PO Box 108042 - Symonds Street - Auckland - NEW ZEALAND - - 00-50-C2 (hex) Serveron Corporation - 220000-220FFF (base 16) Serveron Corporation - 3305 NW Aloclek Dr - Hillsboro OR 97124-7101 - UNITED STATES - - 00-50-C2 (hex) Getinge IT Solutions ApS - 221000-221FFF (base 16) Getinge IT Solutions ApS - Amaliegade 4 - Copenhagen K DK 1256 - DENMARK - - 00-50-C2 (hex) imo-elektronik GmbH - 222000-222FFF (base 16) imo-elektronik GmbH - Edisonstr. 19 - Bielefeld 33689 - GERMANY - - 00-50-C2 (hex) visicontrol GmbH - 223000-223FFF (base 16) visicontrol GmbH - Ettishofer Straße 8 - Weingarten Baden-Württemberg 88250 - GERMANY - - 00-50-C2 (hex) PANNOCOM Ltd. - 224000-224FFF (base 16) PANNOCOM Ltd. - Törökvész út 98/b - Budapest Pest Megye 1025 - HUNGARY - - 00-50-C2 (hex) Pigeon Point Systems LLC - 225000-225FFF (base 16) Pigeon Point Systems LLC - 2191 S. El Camino Real - Suite 209 - Oceanside CA 95054 - UNITED STATES - - 00-50-C2 (hex) Ross Video Limited - 226000-226FFF (base 16) Ross Video Limited - 8 John St. - Iroquois ON K0E 1K0 - CANADA - - 00-50-C2 (hex) Intelligent Photonics Control - 227000-227FFF (base 16) Intelligent Photonics Control - 200-350 Palladium Rd - Kanata On K2V 1A8 - CANADA - - 00-50-C2 (hex) Intelligent Media Technologies, Inc. - 228000-228FFF (base 16) Intelligent Media Technologies, Inc. - 9460 Delegates Drive - Orlando Florida 32837 - UNITED STATES - - 00-50-C2 (hex) eko systems inc. - 229000-229FFF (base 16) eko systems inc. - 2750 Prosperity Ave - Suite 200 - Fairfax VA 22031 - UNITED STATES - - 00-50-C2 (hex) Crescendo Networks - 22A000-22AFFF (base 16) Crescendo Networks - 28 Hacharoshet St. - Or-Yehuda 60375 - ISRAEL - - 00-50-C2 (hex) Riegl Laser Measurement Systems GmbH - 22B000-22BFFF (base 16) Riegl Laser Measurement Systems GmbH - Riedenburgstraße 48 - Horn Niederösterreich A-3580 - AUSTRIA - - 00-50-C2 (hex) Intrinsity - 22C000-22CFFF (base 16) Intrinsity - 11612 Bee Caves Road - Bldg. II, Suite 200 - Austin TX 78738 - UNITED STATES - - 00-50-C2 (hex) asetek Inc. - 22D000-22DFFF (base 16) asetek Inc. - Saltumvej 27 - Broenderslev 9700 - DENMARK - - 00-50-C2 (hex) LORD INGENIERIE - 22E000-22EFFF (base 16) LORD INGENIERIE - ZA de Marly BP110 - 2 rue Fresnel - CORBREUSE 91410 - FRANCE - - 00-50-C2 (hex) HTEC Limited - 22F000-22FFFF (base 16) HTEC Limited - George Curl Way - Southampton Hampshire SO18 2RX - UNITED KINGDOM - - 00-50-C2 (hex) AutoTOOLS group Co. Ltd. - 230000-230FFF (base 16) AutoTOOLS group Co. Ltd. - 15F, No. 88, Chung Hsiao E. Rd., Sec. 2, - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Legra Systems, Inc. - 231000-231FFF (base 16) Legra Systems, Inc. - 3 Burlington Woods Drive - Burlington MA 01803 - UNITED STATES - - 00-50-C2 (hex) SIMET - 232000-232FFF (base 16) SIMET - Via Rivoli 122 - Villarbasse Torino 10090 - ITALY - - 00-50-C2 (hex) EdenTree Technologies, Inc. - 233000-233FFF (base 16) EdenTree Technologies, Inc. - 1040 Flynn Road - Suite 201 - Camarillo California 93012 - UNITED STATES - - 00-50-C2 (hex) Silverback Systems - 234000-234FFF (base 16) Silverback Systems - 695 Campbell Technology Pkwy - Campbell CA 95008 - UNITED STATES - - 00-50-C2 (hex) POLIMAR ELEKTRONIK LTD. - 235000-235FFF (base 16) POLIMAR ELEKTRONIK LTD. - AEGEAN FREE ZONE - ESBAS - AKCAY CD. NO:144 NILUFER SOKAK - IZMIR ESBAS 35410 - TURKEY - - 00-50-C2 (hex) JLCooper Electronics - 236000-236FFF (base 16) JLCooper Electronics - 142 Arena St - El Segundo CA 90245 - UNITED STATES - - 00-50-C2 (hex) Tandata Systems Ltd - 237000-237FFF (base 16) Tandata Systems Ltd - Richmond House - Bath Road - Newbury Berkshire RG14 1QY - UNITED KINGDOM - - 00-50-C2 (hex) Schwer+Kopka GmbH - 238000-238FFF (base 16) Schwer+Kopka GmbH - Herknerstr. 4 - Weingarten Baden-Württemberg 88250 - GERMANY - - 00-50-C2 (hex) Stins Coman - 239000-239FFF (base 16) Stins Coman - Pervomayskaya street build 126 - Moscow 105203 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Chantry Networks - 23A000-23AFFF (base 16) Chantry Networks - 1900 Minnesota Court - Suite 125 - Mississauga Ontario L5N 3C9 - CANADA - - 00-50-C2 (hex) Envara - 23B000-23BFFF (base 16) Envara - 3 Ha'Tidhar St. - Millennium Building - Raanana 43000 - ISRAEL - - 00-50-C2 (hex) Wheatstone Corporation - 23C000-23CFFF (base 16) Wheatstone Corporation - 600 Industrial Drive - New Bern NC 28562 - UNITED STATES - - 00-50-C2 (hex) Gauging Systems Inc - 23D000-23DFFF (base 16) Gauging Systems Inc - 910A Industrial Blvd - Sugar Land TX 77478-2828 - UNITED STATES - - 00-50-C2 (hex) Kallastra Inc. - 23E000-23EFFF (base 16) Kallastra Inc. - 5190 de Mentana - Unit B - Montreal QC H2J 3C4 - CANADA - - 00-50-C2 (hex) Halliburton - NUMAR - 23F000-23FFFF (base 16) Halliburton - NUMAR - 710 Stockton Drive - Exton PA 19341 - UNITED STATES - - 00-50-C2 (hex) Geoquip Ltd - 240000-240FFF (base 16) Geoquip Ltd - Cromford Road - Wirksworth - Matlock Derbyshire D4 4FR - UNITED KINGDOM - - 00-50-C2 (hex) Contronics Automacao Ltda - 241000-241FFF (base 16) Contronics Automacao Ltda - R. Lauro Linhares 589 - Florianopolis SC 88036-002 - BRAZIL - - 00-50-C2 (hex) MDS SCIEX - 242000-242FFF (base 16) MDS SCIEX - 71 Four Valley Drive - Concord Ontario L4K 4V8 - CANADA - - 00-50-C2 (hex) RGB Spectrum - 243000-243FFF (base 16) RGB Spectrum - 950 Marina Village Pkwy - Alameda CA 94501 - UNITED STATES - - 00-50-C2 (hex) intec GmbH - 244000-244FFF (base 16) intec GmbH - Rahmedestr. 90 - Luedenscheid NRW 58507 - GERMANY - - 00-50-C2 (hex) Hauppauge Computer Works, Inc. - 245000-245FFF (base 16) Hauppauge Computer Works, Inc. - 91 Cabot Court - Hauppauge New York 11788 - UNITED STATES - - 00-50-C2 (hex) Hardmeier - 246000-246FFF (base 16) Hardmeier - - Tallinn - ESTONIA - - 00-50-C2 (hex) Gradual Tecnologia Ltda. - 247000-247FFF (base 16) Gradual Tecnologia Ltda. - Rua Attilio Giaretta, 110 - Itatiba SP 13257-584 - BRAZIL - - 00-50-C2 (hex) Dixtal Biomedica Ind. Com. Ltda. - 248000-248FFF (base 16) Dixtal Biomedica Ind. Com. Ltda. - R. Eng. Francisco Pitta Brito, 703 - São Paulo SP 04753080 - BRAZIL - - 00-50-C2 (hex) Bender GmbH & Co. KG - 249000-249FFF (base 16) Bender GmbH & Co. KG - Londorfer Straße 65 - 35305 Grünberg 1161 - GERMANY - - 00-50-C2 (hex) CDS Rail - 24A000-24AFFF (base 16) CDS Rail - Unit 1, Fulcrum 4 - Solent Way - Fareham Hampshire PO15 7FT - UNITED KINGDOM - - 00-50-C2 (hex) Azimuth Systems, Inc. - 24B000-24BFFF (base 16) Azimuth Systems, Inc. - 31 Nagog Park - Acton MA 01720 - UNITED STATES - - 00-50-C2 (hex) Supertel - 24C000-24CFFF (base 16) Supertel - 38a, Petrogradskaya emb. - St.Petersburg 197101 - RUSSIAN FEDERATION - - 00-50-C2 (hex) METTLER-TOLEDO HI-SPEED - 24D000-24DFFF (base 16) METTLER-TOLEDO HI-SPEED - 5 Barr Rd - Ithaca NY 14850 - UNITED STATES - - 00-50-C2 (hex) Scharff Weisberg Systems Integration Inc - 24E000-24EFFF (base 16) Scharff Weisberg Systems Integration Inc - 36-36 33rd St. - Long Island City NY 11106 - UNITED STATES - - 00-50-C2 (hex) Macronet s.r.l. - 24F000-24FFFF (base 16) Macronet s.r.l. - Alsina 2965 - Buenos Aires 1207 - ARGENTINA - - 00-50-C2 (hex) ACD Elektronik GmbH - 250000-250FFF (base 16) ACD Elektronik GmbH - Industriegebiet Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) DGT Sp. z o.o. - 251000-251FFF (base 16) DGT Sp. z o.o. - ul. Jaskowa Dolina 15 - Gdansk woj. pomorskie 80-252 - POLAND - - 00-50-C2 (hex) ads-tec GmbH - 252000-252FFF (base 16) ads-tec GmbH - Raiffeisenstr. 14 - Leinfelden-Echterdingen BW 70771 - GERMANY - - 00-50-C2 (hex) DSM-Messtechnik GmbH - 253000-253FFF (base 16) DSM-Messtechnik GmbH - Dieselstraße 16 - Aalen Baden-Württemberg 73431 - GERMANY - - 00-50-C2 (hex) Thales Communications Ltd - 254000-254FFF (base 16) Thales Communications Ltd - Newton Road - Crawley West Sussex RH10 9TS - UNITED KINGDOM - - 00-50-C2 (hex) STMicroelectronics (R&D) Ltd - 255000-255FFF (base 16) STMicroelectronics (R&D) Ltd - Abbey House, 1650 Arlington Business Par - Theale - Reading Berkshire RG7 4SA - UNITED KINGDOM - - 00-50-C2 (hex) Information Technology Corp. - 256000-256FFF (base 16) Information Technology Corp. - 647 Sanctuary Dr. - Boca Raton FL 33431 - UNITED STATES - - 00-50-C2 (hex) Digicast Networks - 257000-257FFF (base 16) Digicast Networks - 204 Rod Circle - Middletown MD 21769 - UNITED STATES - - 00-50-C2 (hex) Spacesaver Corporation - 258000-258FFF (base 16) Spacesaver Corporation - 1450 Janesville Avenue - Fort Atkinson Wisconsin 53538 - UNITED STATES - - 00-50-C2 (hex) Omicron Ceti AB - 259000-259FFF (base 16) Omicron Ceti AB - Borgarfjordsgatan 7 - KISTA STOCKHOLM SE-16440 - SWEDEN - - 00-50-C2 (hex) Zendex Corporation - 25A000-25AFFF (base 16) Zendex Corporation - 6780 Sierra Court - Suite A - Dublin CA 94568 - UNITED STATES - - 00-50-C2 (hex) Winford Engineering - 25B000-25BFFF (base 16) Winford Engineering - 4169 Four Mile Road - Bay City MI 48706 - UNITED STATES - - 00-50-C2 (hex) Softhill Technologies Ltd. - 25C000-25CFFF (base 16) Softhill Technologies Ltd. - 1329 Una Way - Port Coquitlam British Columbia V3C 2V1 - CANADA - - 00-50-C2 (hex) RDTECH - 25D000-25DFFF (base 16) RDTECH - 505, boul Parc Technologique - Quebec G1P 4S9 - CANADA - - 00-50-C2 (hex) MITE Hradec Kralove, s.r.o. - 25E000-25EFFF (base 16) MITE Hradec Kralove, s.r.o. - Veverkova 1343 - Hradec Kralove CZ 500 02 - CZECH REPUBLIC - - 00-50-C2 (hex) Handtmann Maschinenfabrik GmbH&Co.KG - 25F000-25FFFF (base 16) Handtmann Maschinenfabrik GmbH&Co.KG - Hubertus Liebrecht Str. 10-12 - Biberach D-BW 88483 - GERMANY - - 00-50-C2 (hex) BIOTAGE - 260000-260FFF (base 16) BIOTAGE - 1725 DISCOVERY DR. - CHARLOTTESVILLE VIRGINIA 22911 - UNITED STATES - - 00-50-C2 (hex) Tattile Srl - 261000-261FFF (base 16) Tattile Srl - Via Trento 127/129 - Capriano del Colle Brescia 25020 - ITALY - - 00-50-C2 (hex) Shanghai Gaozhi Science&Technology Development Ltd. - 262000-262FFF (base 16) Shanghai Gaozhi Science&Technology Development Ltd. - No.283 QingJiang Rd. - Shanghai 200233 - CHINA - - 00-50-C2 (hex) Vansco Electronics Oy - 263000-263FFF (base 16) Vansco Electronics Oy - PO Box 86 - Tiilenlyojankatu 5 - FORSSA FIN-30101 - FINLAND - - 00-50-C2 (hex) Confidence Direct Ltd - 264000-264FFF (base 16) Confidence Direct Ltd - 17-20 Napier Road - Luton Beds LU1 1RF - UNITED KINGDOM - - 00-50-C2 (hex) BELIK S.P.R.L. - 265000-265FFF (base 16) BELIK S.P.R.L. - Rue du Roussart 147 - Waterloo Brabant B-1410 - BELGIUM - - 00-50-C2 (hex) ATOM GIKEN Co.,Ltd. - 266000-266FFF (base 16) ATOM GIKEN Co.,Ltd. - 92-2 KATASE - FUJISAWA KANAGAWA 251-0032 - JAPAN - - 00-50-C2 (hex) Allen Martin Conservation Ltd - 267000-267FFF (base 16) Allen Martin Conservation Ltd - 504 Dudley Road - Wolverhampton West Midlands WV2 3AA - UNITED KINGDOM - - 00-50-C2 (hex) Parabit Systems - 268000-268FFF (base 16) Parabit Systems - One Shore Road - Glenwood Landing NY 11547 - UNITED STATES - - 00-50-C2 (hex) Technisyst Pty Ltd - 269000-269FFF (base 16) Technisyst Pty Ltd - Level 4, 175 Eagle Street - Brisbane Queensland 4001 - AUSTRALIA - - 00-50-C2 (hex) FG SYNERYS - 26A000-26AFFF (base 16) FG SYNERYS - 19, impasse Fourcaran - BP2160 - TOULOUSE 31021 - FRANCE - - 00-50-C2 (hex) Continental Gateway Limited - 26B000-26BFFF (base 16) Continental Gateway Limited - Unit A, 6/F., Two Chinachem Plaza, - 68 Connaught Road, - Central - HONG KONG - - 00-50-C2 (hex) Crystal Vision Ltd - 26C000-26CFFF (base 16) Crystal Vision Ltd - Lion Technology Park, Station Road East - Whittlesford - Cambridge Cambs CB2 4NL - UNITED KINGDOM - - 00-50-C2 (hex) DSP DESIGN - 26D000-26DFFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) ZP Engineering srl - 26E000-26EFFF (base 16) ZP Engineering srl - via Ardito Desio, 60 - ROME 00131 - ITALY - - 00-50-C2 (hex) Digital Recorders Inc - 26F000-26FFFF (base 16) Digital Recorders Inc - 4018 Patriot Drive - Suite 100 - Durham NC 27703 - UNITED STATES - - 00-50-C2 (hex) S4 Technology Pty Ltd - 270000-270FFF (base 16) S4 Technology Pty Ltd - 325 Pitt Street - Suite 14, Level 4 - Sydney NSW 2000 - NEW ZEALAND - - 00-50-C2 (hex) VLSIP TECHNOLOGIES INC. - 271000-271FFF (base 16) VLSIP TECHNOLOGIES INC. - 750 PRESIDENTIAL DR - RICHARDSON TEXAS 75081 - UNITED STATES - - 00-50-C2 (hex) Verex Technology - 272000-272FFF (base 16) Verex Technology - 5201 Explorer Drive - Mississauga Ontario L4W 4H1 - CANADA - - 00-50-C2 (hex) Servicios Condumex, S. A. de C. V. - 273000-273FFF (base 16) Servicios Condumex, S. A. de C. V. - Carretera a San Luis Potosí­ km. 9.6 - Parque industrial Jurica - Querétaro 76120 - MEXICO - - 00-50-C2 (hex) Fundación TECNALIA Research & Innovation - 274000-274FFF (base 16) Fundación TECNALIA Research & Innovation - C/ Geldo Edificio 700, Parque Tecnológico Bizkaia - Derio Vizcaya 48160 - SPAIN - - 00-50-C2 (hex) Extreme Engineering Solutions - 275000-275FFF (base 16) Extreme Engineering Solutions - 7878 Big Sky Drive - Suite H - Madison WI 53719 - UNITED STATES - - 00-50-C2 (hex) Tieline Research Pty Ltd - 276000-276FFF (base 16) Tieline Research Pty Ltd - PO Box 2092 - MALAGA Western Australia 6944 - AUSTRALIA - - 00-50-C2 (hex) T/R Systems, Inc. - 277000-277FFF (base 16) T/R Systems, Inc. - 1300 Oakbrook Drive - Norcross GA 30093 - UNITED STATES - - 00-50-C2 (hex) Replicom Ltd. - 278000-278FFF (base 16) Replicom Ltd. - 2 Hailan Street - Or Akiva 30600 - ISRAEL - - 00-50-C2 (hex) PATLITE Corporation - 279000-279FFF (base 16) PATLITE Corporation - 3-50 Wakabayashi-cho - Yao-shi Osaka 581-0038 - JAPAN - - 00-50-C2 (hex) Maestro Pty Ltd - 27A000-27AFFF (base 16) Maestro Pty Ltd - 925 Macs Reef Raod - Bywong NSW 2621 - AUSTRALIA - - 00-50-C2 (hex) LinkSecurity A/S - 27B000-27BFFF (base 16) LinkSecurity A/S - Glerupvej 20 - Rødovre 2610 - DENMARK - - 00-50-C2 (hex) Danlaw Inc - 27C000-27CFFF (base 16) Danlaw Inc - 23700 Research Dr. - Farmington Hills MI 48335 - UNITED STATES - - 00-50-C2 (hex) ALLIED TELESIS K.K. - 27D000-27DFFF (base 16) ALLIED TELESIS K.K. - PIAZZA TIRANA N. 24/4 B - MILANO 20147 - ITALY - - 00-50-C2 (hex) AnaLogic Computers Ltd. - 27E000-27EFFF (base 16) AnaLogic Computers Ltd. - 13-17 Kende Str. - Budapest H-1111 - HUNGARY - - 00-50-C2 (hex) Air Broadband Communications, Inc. - 27F000-27FFFF (base 16) Air Broadband Communications, Inc. - 2620 Albany Dr. Suite 245 - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) AGECODAGIS SARL - 280000-280FFF (base 16) AGECODAGIS SARL - 16, rue d'Auriac - Rieux Haute Garonne 31310 - FRANCE - - 00-50-C2 (hex) CabTronix GmbH - 281000-281FFF (base 16) CabTronix GmbH - Hohstrass 1 - Kloten Zuerich 8302 - SWITZERLAND - - 00-50-C2 (hex) Telvent - 282000-282FFF (base 16) Telvent - Tamarguillo, 29 - Seville 41006 - SPAIN - - 00-50-C2 (hex) ANSITEX CORP. - 283000-283FFF (base 16) ANSITEX CORP. - 24F., No.56, Liansing Rd., Sijhih City, - Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Micronet Ltd. - 284000-284FFF (base 16) Micronet Ltd. - 27 Hametzuda st. - Azor 58001 - ISRAEL - - 00-50-C2 (hex) Littwin GmbH & Co KG - 285000-285FFF (base 16) Littwin GmbH & Co KG - Am Strehl 153-155 - Oldenburg Niedersachsen 26125 - GERMANY - - 00-50-C2 (hex) ATEME - 286000-286FFF (base 16) ATEME - 26 Burospace - Route de Gizy - BIEVRES Cedex 91573 - FRANCE - - 00-50-C2 (hex) TECNEW Electronics Engineering Cr., Ltd. - 287000-287FFF (base 16) TECNEW Electronics Engineering Cr., Ltd. - 16F, No. 75, Shin Tai Wu Rd., Sec. 1, Sh - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) RPM Systems Corporation - 288000-288FFF (base 16) RPM Systems Corporation - 17371 NE 67th Court - Suite A5 - Redmond Washington 98052 - UNITED STATES - - 00-50-C2 (hex) Rototype S.p.A. - 289000-289FFF (base 16) Rototype S.p.A. - Via Bessi, 15 - Calenzano Firenze 50041 - ITALY - - 00-50-C2 (hex) Real Time Systems - 28A000-28AFFF (base 16) Real Time Systems - 108 E. Austin St - Fredericksburg Tx 78624 - UNITED STATES - - 00-50-C2 (hex) Orion Technologies, Incorporated - 28B000-28BFFF (base 16) Orion Technologies, Incorporated - 690 Cone Park Court - Suite A - Merritt Island FL 32952 - UNITED STATES - - 00-50-C2 (hex) Futaba Corporation - 28C000-28CFFF (base 16) Futaba Corporation - 1080 Yabutsuka - Chosei-gun,Chosei-mura Chiba-ken 299-4395 - JAPAN - - 00-50-C2 (hex) AXODE SA - 28D000-28DFFF (base 16) AXODE SA - 7 RUE FLEMING - ANGERS F-49000 - FRANCE - - 00-50-C2 (hex) TATTILE SRL - 28E000-28EFFF (base 16) TATTILE SRL - VIA TRENTO 127/129 - CAPRIANO DEL COLLE BRESCIA 25020 - ITALY - - 00-50-C2 (hex) Spellman High Voltage Electronics Corp - 28F000-28FFFF (base 16) Spellman High Voltage Electronics Corp - 475 Wireless Blvd - Hauppauge NY 11788 - UNITED STATES - - 00-50-C2 (hex) EBNEURO SPA - 290000-290FFF (base 16) EBNEURO SPA - VIA PIETRO FANFANI 97a - FIRENZE 50127 - ITALY - - 00-50-C2 (hex) CHAUVIN ARNOUX - 291000-291FFF (base 16) CHAUVIN ARNOUX - LA QUEUE DEVEE - REUX PONT L EVEQUE 14130 - FRANCE - - 00-50-C2 (hex) AMIRIX Systems - 292000-292FFF (base 16) AMIRIX Systems - 20 Angus Morton Drive - Bedford NS B4B 0L9 - CANADA - - 00-50-C2 (hex) IP Unity - 293000-293FFF (base 16) IP Unity - 475 Sycamore Drive - Milpitas CA 94535 - UNITED STATES - - 00-50-C2 (hex) EPSa GmbH - 294000-294FFF (base 16) EPSa GmbH - Göschwitzer Straße 32 - Jena Thüringen D-07745 - GERMANY - - 00-50-C2 (hex) LOGOSOL, INC. - 295000-295FFF (base 16) LOGOSOL, INC. - 5041 Robert J. Mathews Parkway - Suite 100 - El Dorado Hills CA 95762 - UNITED STATES - - 00-50-C2 (hex) OpVista - 296000-296FFF (base 16) OpVista - 25A Technology Dr. - Irvine CA 92618 - UNITED STATES - - 00-50-C2 (hex) KINETICS - 297000-297FFF (base 16) KINETICS - P.O.BOX 50 - BEN-GURION AIRPORT 79100 - ISRAEL - - 00-50-C2 (hex) Harvad University - 298000-298FFF (base 16) Harvad University - 17 Oxford St. - Cambridge MA 01238 - UNITED STATES - - 00-50-C2 (hex) CAD-UL GmbH - 299000-299FFF (base 16) CAD-UL GmbH - Nicolaus-Otto Str. 4 - Ulm BW 89079 - GERMANY - - 00-50-C2 (hex) Packet Techniques Inc. - 29A000-29AFFF (base 16) Packet Techniques Inc. - 223 North 12th St #314B - Tampa Florida 33602 - UNITED STATES - - 00-50-C2 (hex) ACD Elektronik GmbH - 29B000-29BFFF (base 16) ACD Elektronik GmbH - Industriegebiet Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) 2N TELEKOMUNIKACE a.s. - 29C000-29CFFF (base 16) 2N TELEKOMUNIKACE a.s. - Modranska 621 - Prague 4 Prague 143 01 - CZECH REPUBLIC - - 00-50-C2 (hex) Globe Wireless - 29D000-29DFFF (base 16) Globe Wireless - 2300 Commerce Park Drive - Suite 8 - Palm Bay Florida 32905 - UNITED STATES - - 00-50-C2 (hex) SELEX Communications Ltd - 29E000-29EFFF (base 16) SELEX Communications Ltd - Liverpool Digital, Baird House - Edge Lane - Liverpool Fairfield L7 9NJ - UNITED KINGDOM - - 00-50-C2 (hex) Baudisch Electronic GmbH - 29F000-29FFFF (base 16) Baudisch Electronic GmbH - Im Gewerbegebiet 7 - Waeschenbeuren 73116 - GERMANY - - 00-50-C2 (hex) Sterling Industry Consult GmbH - 2A0000-2A0FFF (base 16) Sterling Industry Consult GmbH - Lindenstr. 170 - Itzehoe Schleswig-Holstein D 25524 - GERMANY - - 00-50-C2 (hex) Infinetix Corp - 2A1000-2A1FFF (base 16) Infinetix Corp - 2721 N. Van Marter #3 - Spokane WA 99206 - UNITED STATES - - 00-50-C2 (hex) Epelsa, SL - 2A2000-2A2FFF (base 16) Epelsa, SL - C/albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) West-Com Nurse Call Systems, Inc. - 2A3000-2A3FFF (base 16) West-Com Nurse Call Systems, Inc. - PO Box 640 - Danville CA 94526 - UNITED STATES - - 00-50-C2 (hex) Xipher Embedded Networking - 2A4000-2A4FFF (base 16) Xipher Embedded Networking - 434 Turnpike Road - Ashford CT 06278 - UNITED STATES - - 00-50-C2 (hex) Septier Communication Ltd - 2A5000-2A5FFF (base 16) Septier Communication Ltd - POB 7603 - 21 Yegia Kapaim - Petach Tikva 49170 - ISRAEL - - 00-50-C2 (hex) Brannstroms Elektronik AB - 2A6000-2A6FFF (base 16) Brannstroms Elektronik AB - Uddevallagatan 14 - Goteborg Vastra Gotaland 41670 - SWEDEN - - 00-50-C2 (hex) Micro System Architecturing srl - 2A7000-2A7FFF (base 16) Micro System Architecturing srl - Via della Tecnica 8/P - Agrate Brianza Milano 20041 - ITALY - - 00-50-C2 (hex) DVTel Israel Ltd. - 2A8000-2A8FFF (base 16) DVTel Israel Ltd. - 4 Hamelacha St. - Lod 71520 - ISRAEL - - 00-50-C2 (hex) Dr. Staiger, Mohilo + Co GmbH - 2A9000-2A9FFF (base 16) Dr. Staiger, Mohilo + Co GmbH - Maierhofstraße 35 - Lorch Baden-Württemberg D 73547 - GERMANY - - 00-50-C2 (hex) DEUTA Werke GmbH - 2AA000-2AAFFF (base 16) DEUTA Werke GmbH - ET - Bergisch Gladbach NRW 51465 - GERMANY - - 00-50-C2 (hex) AUM Infotech Private Limited - 2AB000-2ABFFF (base 16) AUM Infotech Private Limited - 306,17c main Road, - III Block, Rajajinagar - Bangalore Karnataka 560010 - INDIA - - 00-50-C2 (hex) BBI Engineering, Inc. - 2AC000-2ACFFF (base 16) BBI Engineering, Inc. - 241 Quint Street - San Francisco CA 94124 - UNITED STATES - - 00-50-C2 (hex) ABB T&D Spa - 2AD000-2ADFFF (base 16) ABB T&D Spa - division SACE T.M.S. - via Friuli 4 - Dalmine Bergamo 24044 - ITALY - - 00-50-C2 (hex) Quest Retail Technology Pty Ltd - 2AE000-2AEFFF (base 16) Quest Retail Technology Pty Ltd - 37-39 Walsh Street - Thebarton South Australia 5031 - AUSTRALIA - - 00-50-C2 (hex) CSA Computer & Antriebstechnik GmbH - 2AF000-2AFFFF (base 16) CSA Computer & Antriebstechnik GmbH - RHEINSTRASSE 7E - TELTOW BRANDENBURG D-14513 - GERMANY - - 00-50-C2 (hex) Telda Electronics - 2B0000-2B0FFF (base 16) Telda Electronics - #102 Electronics Bldg. 220-10, Buen 2Dong, Kangbuk-Ku - Seoul 142-705 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) PRIVATE - 2B1000-2B1FFF (base 16) - - 00-50-C2 (hex) Smiths Detection - 2B2000-2B2FFF (base 16) Smiths Detection - 1730 Aimco Blvd - Mississauga Ontario L4W 1V1 - CANADA - - 00-50-C2 (hex) Embedded Systems Design - 2B3000-2B3FFF (base 16) Embedded Systems Design - 1064 Tabernacle - Sequin TX 78155 - UNITED STATES - - 00-50-C2 (hex) Polatis Ltd - 2B4000-2B4FFF (base 16) Polatis Ltd - 332/2 Cambridge Science Park, - Milton Road - Cambridge CB4 0BZ - UNITED KINGDOM - - 00-50-C2 (hex) Hobbes Computer Network Accessories - 2B5000-2B5FFF (base 16) Hobbes Computer Network Accessories - 2015 S. Myrtle Ave. - Monrovia CA 91016 - UNITED STATES - - 00-50-C2 (hex) Softier Inc. - 2B6000-2B6FFF (base 16) Softier Inc. - 3 HaTidhar St - Raanana 43665 - ISRAEL - - 00-50-C2 (hex) Rafi GmbH & Co. KG - 2B7000-2B7FFF (base 16) Rafi GmbH & Co. KG - P.O. Box 2060 - Ravensburg Baden-Württemberg 88190 - GERMANY - - 00-50-C2 (hex) Admiral Secure Products, Ltd. - 2B8000-2B8FFF (base 16) Admiral Secure Products, Ltd. - 866 Mantle Crescent - Mississauga Ontario L5V 2G3 - CANADA - - 00-50-C2 (hex) Richmond Sound Design Ltd. - 2B9000-2B9FFF (base 16) Richmond Sound Design Ltd. - 205-11780 River Road - Richmond BC V6X 1Z7 - CANADA - - 00-50-C2 (hex) NORCO INDUSTRIAL TECHNOLOGY INC - 2BA000-2BAFFF (base 16) NORCO INDUSTRIAL TECHNOLOGY INC - UNIT 211-739 BIRCHMOUNT ROAD - TORONTO ON M1K 1R6 - CANADA - - 00-50-C2 (hex) TA Instruments Ltd - 2BB000-2BBFFF (base 16) TA Instruments Ltd - 159 Lukens Drive - New Castle Delaware 19720 - UNITED STATES - - 00-50-C2 (hex) Uster Technologies AG - 2BC000-2BCFFF (base 16) Uster Technologies AG - Wilstrasse 11 - CH-8610 - Uster - SWITZERLAND - - 00-50-C2 (hex) StorLink Semi - 2BD000-2BDFFF (base 16) StorLink Semi - 1804 N. Shoreline Blvd, Suite 240 - Mountain View CA 94043 - UNITED STATES - - 00-50-C2 (hex) Lipowsky Industrie-Elektronik GmbH - 2BE000-2BEFFF (base 16) Lipowsky Industrie-Elektronik GmbH - Roemerstr. 57 - Darmstadt Hessen 64291 - GERMANY - - 00-50-C2 (hex) PERAX - 2BF000-2BFFFF (base 16) PERAX - 48 rue de Fenouillet - BP56 - Saint ALBAN Haute garonne 31140 - FRANCE - - 00-50-C2 (hex) Magellan Technology Pty Ltd - 2C0000-2C0FFF (base 16) Magellan Technology Pty Ltd - 65 Johnston Street - Annandale NSW 2038 - AUSTRALIA - - 00-50-C2 (hex) Stage Tec Entwicklungsgesellschaft für professionelle Audio - 2C1000-2C1FFF (base 16) Stage Tec Entwicklungsgesellschaft für professionelle Audio - Tabbertstraße 10 - Berlin Berlin 12459 - GERMANY - - 00-50-C2 (hex) Smarteye Corporation - 2C2000-2C2FFF (base 16) Smarteye Corporation - 2637 Bond Street - Rochester Hills Michigan 48309 - UNITED STATES - - 00-50-C2 (hex) Digital SP Ltd - 2C3000-2C3FFF (base 16) Digital SP Ltd - Heathcourt - Morven Way - Ballater AB355SF - UNITED KINGDOM - - 00-50-C2 (hex) Invensys Energy Systens (NZ) Limited - 2C4000-2C4FFF (base 16) Invensys Energy Systens (NZ) Limited - 39 Princess Street - Christchurch 8030 - NEW ZEALAND - - 00-50-C2 (hex) Elman srl - 2C5000-2C5FFF (base 16) Elman srl - Via di Valle Caia, km 4.700 - Pomezia Roma 00040 - ITALY - - 00-50-C2 (hex) Initial Electronic Security Systems - 2C6000-2C6FFF (base 16) Initial Electronic Security Systems - Shadsworth Road - Blackburn Lancashire BB1 2PR - UNITED KINGDOM - - 00-50-C2 (hex) Siliquent Technologies Ltd - 2C7000-2C7FFF (base 16) Siliquent Technologies Ltd - 33 Bezalel St. - Ramat-Gan 52521 - ISRAEL - - 00-50-C2 (hex) SELCO - 2C8000-2C8FFF (base 16) SELCO - ZI DU VAL D OMBREE - COMBREE 49520 - FRANCE - - 00-50-C2 (hex) Roseman Engineering Ltd. - 2C9000-2C9FFF (base 16) Roseman Engineering Ltd. - 65 Weizman St. - Givataim 53468 - ISRAEL - - 00-50-C2 (hex) PUTERCOM CO., LTD - 2CA000-2CAFFF (base 16) PUTERCOM CO., LTD - 5F-3, NO. 130 JIAN KANG ROAD - CHUNG HO CITY, Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) FACTS Engineering LLC - 2CB000-2CBFFF (base 16) FACTS Engineering LLC - 8049 Photonics Drive - New Port Richey Fl 34655 - UNITED STATES - - 00-50-C2 (hex) EMBEDDED TOOLSMITHS - 2CC000-2CCFFF (base 16) EMBEDDED TOOLSMITHS - 3007 RIDGE VALE CIRCLE - TAMPA FL 33594 - UNITED STATES - - 00-50-C2 (hex) DataWind Research - 2CD000-2CDFFF (base 16) DataWind Research - 555 Rene-Levesque West - Suite 1130 - Montreal Quebec H2Z 1B1 - CANADA - - 00-50-C2 (hex) Ross Video Limited - 2CE000-2CEFFF (base 16) Ross Video Limited - 8 John Street - Iroquois Ontario - CANADA - - 00-50-C2 (hex) Diseño de Sistemas en Silicio S.A. - 2CF000-2CFFFF (base 16) Diseño de Sistemas en Silicio S.A. - Charles Robert Darwin, 2 - Parc tecnologic - Paterna Valencia 46980 - SPAIN - - 00-50-C2 (hex) Worth Data, Inc. - 2D0000-2D0FFF (base 16) Worth Data, Inc. - 623 Swift Street - Santa Cruz CA 95060 - UNITED STATES - - 00-50-C2 (hex) Miritek, Inc. - 2D1000-2D1FFF (base 16) Miritek, Inc. - 32321 TBI, ICU - 58-4 Hwaam-dong Yuseong-ku - Daejon 305-732 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) AIRNET COMMUNICATIONS CORP - 2D2000-2D2FFF (base 16) AIRNET COMMUNICATIONS CORP - 3950 DOW RD - MELBOURNE FL 32934 - UNITED STATES - - 00-50-C2 (hex) Gerber Scientific Products, Inc. - 2D3000-2D3FFF (base 16) Gerber Scientific Products, Inc. - 83 Gerber Road - South Windsor CT 06074 - UNITED STATES - - 00-50-C2 (hex) Integrated System Solution Corp. - 2D4000-2D4FFF (base 16) Integrated System Solution Corp. - 3F,No.2-1, Industry E Rd., I, Science-based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) PIXY AG - 2D5000-2D5FFF (base 16) PIXY AG - Bruggerstrasse 37 - Baden 5400 - SWITZERLAND - - 00-50-C2 (hex) WIS Technologies - 2D6000-2D6FFF (base 16) WIS Technologies - 683 River Oaks Parkway - San Jose CA 95134 - UNITED STATES - - 00-50-C2 (hex) Neo Electronics Ltd - 2D7000-2D7FFF (base 16) Neo Electronics Ltd - Neo House - Shaw Road - Oldham Lancashire OL1 4AW - UNITED KINGDOM - - 00-50-C2 (hex) SYN-TECH SYSTEMS INC - 2D8000-2D8FFF (base 16) SYN-TECH SYSTEMS INC - PO BOX 5258 - TALLAHASSEE FL 32314 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - 2D9000-2D9FFF (base 16) - - 00-50-C2 (hex) PYRAMID Computer GmbH - 2DA000-2DAFFF (base 16) PYRAMID Computer GmbH - Boetzinger Strasse 60 - Freiburg BW 79111 - GERMANY - - 00-50-C2 (hex) AutoTOOLS group Co. Ltd. - 2DB000-2DBFFF (base 16) AutoTOOLS group Co. Ltd. - 15F, No. 88, Chung Hsiao E. Rd., Sec. 2, - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Wiener, Plein & Baus GmbH - 2DC000-2DCFFF (base 16) Wiener, Plein & Baus GmbH - Muellersbaum 20 - Burscheid 51399 - GERMANY - - 00-50-C2 (hex) Westek Technology Ltd - 2DD000-2DDFFF (base 16) Westek Technology Ltd - Unit 1, Lancaster Road - Bowerhill - Melksham Wiltshire SN12 6TT - UNITED KINGDOM - - 00-50-C2 (hex) Research Applications - 2DE000-2DEFFF (base 16) Research Applications - 650 S 79th St - Chandler Az 85226 - UNITED STATES - - 00-50-C2 (hex) MICREL-NKE - 2DF000-2DFFFF (base 16) MICREL-NKE - rue gutenberg - Z.I. de Kerandré - HENNEBONT 56700 - FRANCE - - 00-50-C2 (hex) Baxter Healthcare - 2E0000-2E0FFF (base 16) Baxter Healthcare - 3925 Gateway Centre Blvd - Pinellas Park FL 33782 - UNITED STATES - - 00-50-C2 (hex) Access IS - 2E1000-2E1FFF (base 16) Access IS - 18 Suttons Business Park - READING Berks RG6 1AZ - UNITED KINGDOM - - 00-50-C2 (hex) Ballard Technology, Inc. - 2E2000-2E2FFF (base 16) Ballard Technology, Inc. - 11400 Airport Road - Suite 201 - Everett WA 98204 - UNITED STATES - - 00-50-C2 (hex) MG Industrieelektronik GmbH - 2E3000-2E3FFF (base 16) MG Industrieelektronik GmbH - Nobelstraße 7 - Ettlingen 76275 - GERMANY - - 00-50-C2 (hex) iamba LTD. - 2E4000-2E4FFF (base 16) iamba LTD. - Hatidhar 3 - Ra'anana 43000 - ISRAEL - - 00-50-C2 (hex) Transtech DSP - 2E5000-2E5FFF (base 16) Transtech DSP - Manor Courtyard - Hughenden Avenue - High Wycombe Bucks HP13 5RE - UNITED KINGDOM - - 00-50-C2 (hex) DALSA - 2E6000-2E6FFF (base 16) DALSA - 605 McMurray Rd. - Waterloo Ontario N2V 2E9 - CANADA - - 00-50-C2 (hex) SafeView, Inc. - 2E7000-2E7FFF (base 16) SafeView, Inc. - 469 El Camino Real - Suite 110 - Santa Clara CA 95050 - UNITED STATES - - 00-50-C2 (hex) S.M.V. Systemelektronik GmbH - 2E8000-2E8FFF (base 16) S.M.V. Systemelektronik GmbH - Firkenweg 7 - Unterföhring Bayern 85774 - GERMANY - - 00-50-C2 (hex) SRI International - 2E9000-2E9FFF (base 16) SRI International - 333 Ravenswood Avenue - Menlo Park CA 94025 - UNITED STATES - - 00-50-C2 (hex) QUBIsoft S.r.l. - 2EA000-2EAFFF (base 16) QUBIsoft S.r.l. - C.so del POpolo 8/C - PADOVA 35131 - ITALY - - 00-50-C2 (hex) Lingg & Janke OHG - 2EB000-2EBFFF (base 16) Lingg & Janke OHG - Zeppelinstr. 30 - Radolfzell BW 78315 - GERMANY - - 00-50-C2 (hex) CHENGDU BOOK DIGITAL CO., LTD - 2EC000-2ECFFF (base 16) CHENGDU BOOK DIGITAL CO., LTD - 9/F, BLOCK C, SKYWORTH BLD. SCI & - TECH. PART, NANSHAN DISTRICT - SHENZHEN GUANGDONG 518057 - CHINA - - 00-50-C2 (hex) 4RF Communications Ltd - 2ED000-2EDFFF (base 16) 4RF Communications Ltd - 26 Glover Street - Ngauranga - Wellington 6032 - NEW ZEALAND - - 00-50-C2 (hex) SHF Communication Technologies AG - 2EE000-2EEFFF (base 16) SHF Communication Technologies AG - Wilhelm-von-Siemens-Str. 23 d - Berlin Berlin 12277 - GERMANY - - 00-50-C2 (hex) Profline B.V. - 2EF000-2EFFFF (base 16) Profline B.V. - Marga Klompeelaan 18 - Arnhem Gelderland 6836 BH - NETHERLANDS - - 00-50-C2 (hex) LECO Corporation - 2F0000-2F0FFF (base 16) LECO Corporation - 3000 Lakeview Ave., CC1 - St. Joseph MI 49085 - UNITED STATES - - 00-50-C2 (hex) Geometrics, Inc. - 2F1000-2F1FFF (base 16) Geometrics, Inc. - 2190 Fortune Drive - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) Eurotek Srl - 2F2000-2F2FFF (base 16) Eurotek Srl - Strada Comunale Savonesa, 9 - Rivalta Scrivia AL 15050 - ITALY - - 00-50-C2 (hex) Crossbow Technology, Inc. - 2F3000-2F3FFF (base 16) Crossbow Technology, Inc. - 41 Daggett Drive - San Jose CA 95134 - UNITED STATES - - 00-50-C2 (hex) Efficient Channel Coding - 2F4000-2F4FFF (base 16) Efficient Channel Coding - 600 Safeguard Plaza - Suite 100 - Brooklyn Heights Ohio 44131 - UNITED STATES - - 00-50-C2 (hex) ADChips - 2F5000-2F5FFF (base 16) ADChips - 4th floor SamKwang Bldg. - Samsung-2Dong Kangnam-Ku - Seoul Seoul 135-508 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Clifford Chance LLP - 2F6000-2F6FFF (base 16) Clifford Chance LLP - Canary Wharf - 10 Upper Bank Street - London UK E14 5JJ - UNITED KINGDOM - - 00-50-C2 (hex) GILLAM-FEI S.A. - 2F7000-2F7FFF (base 16) GILLAM-FEI S.A. - Mont St Martin 58 - LIEGE 4000 - BELGIUM - - 00-50-C2 (hex) SavvyCorp.com Ltd - 2F8000-2F8FFF (base 16) SavvyCorp.com Ltd - 4040 Palmer Court - Naperville IL 60564 - UNITED STATES - - 00-50-C2 (hex) Digilent Inc. - 2F9000-2F9FFF (base 16) Digilent Inc. - PO BOX 428 - Pullman WA 99163 - UNITED STATES - - 00-50-C2 (hex) Tornado Modular Systems, Ltd - 2FA000-2FAFFF (base 16) Tornado Modular Systems, Ltd - p.b. 709 - Novosibirsk 630090 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Arthur Industries Inc., dba On Hold Media Group - 2FB000-2FBFFF (base 16) Arthur Industries Inc., dba On Hold Media Group - 6836 Dallas Pkwy - Ste 200 - Plano TX 75024 - UNITED STATES - - 00-50-C2 (hex) Blackline Systems Corporation - 2FC000-2FCFFF (base 16) Blackline Systems Corporation - 2794 Fenton Road - Ottawa Ontario K1T3T7 - CANADA - - 00-50-C2 (hex) American Microsystems, Ltd. - 2FD000-2FDFFF (base 16) American Microsystems, Ltd. - 2190 Regal Parkway - Euless Texas 76040 - UNITED STATES - - 00-50-C2 (hex) Saab AB - 2FE000-2FEFFF (base 16) Saab AB - Nobymalmsvägen - Linköping Östergötland 581 82 - SWEDEN - - 00-50-C2 (hex) Patria Advanced Solutions - 2FF000-2FFFFF (base 16) Patria Advanced Solutions - Naulakatu 3 - Tampere FIN-33100 - FINLAND - - 00-50-C2 (hex) Soredex Instrumentarium Oyj - 300000-300FFF (base 16) Soredex Instrumentarium Oyj - PL 250 - Helsinki 00031 - FINLAND - - 00-50-C2 (hex) Delphi Display Systems, Inc. - 301000-301FFF (base 16) Delphi Display Systems, Inc. - 3160 Pullman Street - Costa Mesa CA 92626 - UNITED STATES - - 00-50-C2 (hex) EuroDesign embedded technologies GmbH - 302000-302FFF (base 16) EuroDesign embedded technologies GmbH - Waldstraße 4A - Kirchdorf a.d. Amper Bayern 85414 - GERMANY - - 00-50-C2 (hex) CI Systems Ltd. - 303000-303FFF (base 16) CI Systems Ltd. - P.O.Box 147 - Industrial Park Ramat Gavriel - Migdal HaEmek ISR 10551 - ISRAEL - - 00-50-C2 (hex) COMERSON S.r.l. - 304000-304FFF (base 16) COMERSON S.r.l. - Via Lombardia, 15 - Carate Brianza MILANO 20048 - ITALY - - 00-50-C2 (hex) Symbium Corporation - 305000-305FFF (base 16) Symbium Corporation - 603 March Road, Suite 100 - Kanata Ontario K2K 2M5 - CANADA - - 00-50-C2 (hex) Noran Tel Communications Ltd. - 306000-306FFF (base 16) Noran Tel Communications Ltd. - 3033 Saskatchewan Drive - Regina Saskatchewan S4T 1H5 - CANADA - - 00-50-C2 (hex) UNIONDIGITAL.,CO.LTD - 307000-307FFF (base 16) UNIONDIGITAL.,CO.LTD - 34F,TM21,546-4 Gueui-dong, - Kwangjin-gu - Seoul 143-721 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) FiveCo - 308000-308FFF (base 16) FiveCo - Ch. de la Rueyre 116 - Renens 1020 - SWITZERLAND - - 00-50-C2 (hex) Rackmaster Systems, Inc. - 309000-309FFF (base 16) Rackmaster Systems, Inc. - 5244 Valley Industrial Blvd. S. - Shakopee MN 55379 - UNITED STATES - - 00-50-C2 (hex) Innings Telecom Inc. - 30A000-30AFFF (base 16) Innings Telecom Inc. - 1241 Denison Street - Markham Ontario L3R 4B4 - CANADA - - 00-50-C2 (hex) VX Technologies Inc. - 30B000-30BFFF (base 16) VX Technologies Inc. - #2000, 777-8 Avenue SW - Calgary Alberta T2P 3R5 - CANADA - - 00-50-C2 (hex) TEAMLOG - 30C000-30CFFF (base 16) TEAMLOG - 10, rue Lavoisier - Montbonnot Isère (38) 38330 - FRANCE - - 00-50-C2 (hex) SETARAM - 30D000-30DFFF (base 16) SETARAM - 7 Rue de l'oratoire - CALUIRE rhone 69300 - FRANCE - - 00-50-C2 (hex) Obvius - 30E000-30EFFF (base 16) Obvius - 20811 NW Cornell Road - Suite 700 - Hillsboro OR 97124 - UNITED STATES - - 00-50-C2 (hex) Digicontrole Lda - 30F000-30FFFF (base 16) Digicontrole Lda - Av. Eng. Arantes e Oliveira N°5 2° D - Olaias - Lisboa 1900-221 LIS - PORTUGAL - - 00-50-C2 (hex) CYBERTRON CO., LTD. - 310000-310FFF (base 16) CYBERTRON CO., LTD. - 14F Hansihn IT Tower #235 Guro-Dong Guro-gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Comodo - 311000-311FFF (base 16) Comodo - 10 Hey Street - Bradford West Yorkshire BD7 1DQ - UNITED KINGDOM - - 00-50-C2 (hex) Dese Technologies SL - 312000-312FFF (base 16) Dese Technologies SL - Av. Benjamin Franklin 12 , Edif CEEI - Modulo 11 - Paterna Valencia 46980 - SPAIN - - 00-50-C2 (hex) SAIA Burgess Controls AG - 313000-313FFF (base 16) SAIA Burgess Controls AG - Bahnhofstrasse 18 - 3280 Murten - SWITZERLAND - - 00-50-C2 (hex) MicroBee Systems, Inc - 314000-314FFF (base 16) MicroBee Systems, Inc - 9414 Danese Lane SE - Huntsville AL 35803 - UNITED STATES - - 00-50-C2 (hex) ifak system GmbH - 315000-315FFF (base 16) ifak system GmbH - Schleinufer 11 - Magdeburg Saxony-Anhalt 39104 - GERMANY - - 00-50-C2 (hex) Dataline AB - 316000-316FFF (base 16) Dataline AB - Katrinedalsgatan 53 - BORÃ…S S-50451 - SWEDEN - - 00-50-C2 (hex) Cosine Systems, Inc. - 317000-317FFF (base 16) Cosine Systems, Inc. - 736 West Algonquin Road - Arlington Heights IL 60005 - UNITED STATES - - 00-50-C2 (hex) Milmega Ltd - 318000-318FFF (base 16) Milmega Ltd - Ryde Business Park - Nicholson Road - Ryde Isle of WIght PO33 1BQ - UNITED KINGDOM - - 00-50-C2 (hex) Invatron Systems Corp. - 319000-319FFF (base 16) Invatron Systems Corp. - 5710 Timberlea Blvd. - Suite 201 - Mississauga Ontario L4W 4W1 - CANADA - - 00-50-C2 (hex) Zodiak Data Systems - 31A000-31AFFF (base 16) Zodiak Data Systems - 5, Avenue des Andes - CS 90101 - 91978 Courtaboeuf Cedex - FRANCE - - 00-50-C2 (hex) Datacon - 31B000-31BFFF (base 16) Datacon - Instrasse 6 - Radfeld Tirol 6240 - AUSTRIA - - 00-50-C2 (hex) Casa Systems Inc. - 31C000-31CFFF (base 16) Casa Systems Inc. - 500 Clark Road - Tewksbury MA 01876 - UNITED STATES - - 00-50-C2 (hex) Imarda New Zealand Limited - 31D000-31DFFF (base 16) Imarda New Zealand Limited - Suite G16, National Innovation Centre, - Australian Technology Park, - Eveleigh NSW 2015 - NEW ZEALAND - - 00-50-C2 (hex) C3-ilex, LLC - 31E000-31EFFF (base 16) C3-ilex, LLC - 47009 Benicia St. - Fremont California 94538 - UNITED STATES - - 00-50-C2 (hex) Geotech Instruments, LLC - 31F000-31FFFF (base 16) Geotech Instruments, LLC - 10755 Sanden Drive - Dallas TX 75238 - UNITED STATES - - 00-50-C2 (hex) DTASENSOR S.p.A. - 320000-320FFF (base 16) DTASENSOR S.p.A. - Via Lavino 265 - Monte San Pietro BOLOGNA 40050 - ITALY - - 00-50-C2 (hex) UXP - 321000-321FFF (base 16) UXP - 12 AVENUE PIERRE DE COUBERTIN - ZI PERCEVALIERE N° 7408 - SEYSSINET PARISET CEDEX ISERE 38174 - FRANCE - - 00-50-C2 (hex) BQT Solutions (Australia) Limited - 322000-322FFF (base 16) BQT Solutions (Australia) Limited - Unit 5, 12-18 Victoria Street East - Lidcombe NSW 2141 - AUSTRALIA - - 00-50-C2 (hex) Red Rock Networks - 323000-323FFF (base 16) Red Rock Networks - P.O. Box 3465 - Sonora CA 95370 - UNITED STATES - - 00-50-C2 (hex) ODIXION - 324000-324FFF (base 16) ODIXION - 188 rue de la Liberté - AVRANCHES France 50300 - FRANCE - - 00-50-C2 (hex) Federal Aviation Administration - 325000-325FFF (base 16) Federal Aviation Administration - FAA Technical Center - Atlantic City New Jersey 08405 - UNITED STATES - - 00-50-C2 (hex) Navionics S.p.A. - 326000-326FFF (base 16) Navionics S.p.A. - via Vespucci 289 - Viareggio Lucca I-55049 - ITALY - - 00-50-C2 (hex) Dornier GmbH - 327000-327FFF (base 16) Dornier GmbH - an der B31 - Friedrichshafen Baden-Württemberg 88039 - GERMANY - - 00-50-C2 (hex) I.C.S. Electronics Limited - 328000-328FFF (base 16) I.C.S. Electronics Limited - Unit V Rudford Industrial Est. - Ford - Arundel West Sussex BN18 0BF - UNITED KINGDOM - - 00-50-C2 (hex) Imax - 329000-329FFF (base 16) Imax - 2525 Speakman Drive - Mississauga Ontario L5K 1B1 - CANADA - - 00-50-C2 (hex) PHYTEC Messtechnik GmbH - 32A000-32AFFF (base 16) PHYTEC Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Digital Multimedia Technologies Spa - 32B000-32BFFF (base 16) Digital Multimedia Technologies Spa - Via Zanella, 21 - Lissone Milan 20035 - ITALY - - 00-50-C2 (hex) Integrated Silicon Solution (Taiwan), Inc. - 32C000-32CFFF (base 16) Integrated Silicon Solution (Taiwan), Inc. - 5F, No.1, Creation Rd. II, - Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Consens Zeiterfassung GMBH - 32D000-32DFFF (base 16) Consens Zeiterfassung GMBH - Ambachweg 1 - Rietz Tirol 6421 - AUSTRIA - - 00-50-C2 (hex) MANUSA-GEST, S.L. - 32E000-32EFFF (base 16) MANUSA-GEST, S.L. - Avinguda Via Augusta, 71-73 - Planta 4 - Sant Cugat del Valles Barcelona 08174 - SPAIN - - 00-50-C2 (hex) PULTRONICS - 32F000-32FFFF (base 16) PULTRONICS - 5375, PARE str. #200 - MONTREAL QUEBEC H4P 1P7 - CANADA - - 00-50-C2 (hex) Sicon S.r.l. - 330000-330FFF (base 16) Sicon S.r.l. - Via della tecnica, 1 - Villaverla Vicenza 36030 - ITALY - - 00-50-C2 (hex) Broadcast Sports Inc - 331000-331FFF (base 16) Broadcast Sports Inc - 1360 Blair Drive - Suite A - Odenton MD 21113 - UNITED STATES - - 00-50-C2 (hex) PUNJAB COMMUNICATIONS LTD - 332000-332FFF (base 16) PUNJAB COMMUNICATIONS LTD - B-91,INDUSTRIAL AREA, PHASE 8, - SAS NAGAR PUNJAB 160059 - INDIA - - 00-50-C2 (hex) Radix Corporation - 333000-333FFF (base 16) Radix Corporation - 4855 Wiley Post Way - Salt Lake City Utah 84116 - UNITED STATES - - 00-50-C2 (hex) Picture Elements, Inc. - 334000-334FFF (base 16) Picture Elements, Inc. - 777 Panoramic Way - Berkeley CA 94704 - UNITED STATES - - 00-50-C2 (hex) Nimcat Networks - 335000-335FFF (base 16) Nimcat Networks - 1135 Innovation Driver - Ottawa Ontario K2K 3G7 - CANADA - - 00-50-C2 (hex) Golden River Traffic - 336000-336FFF (base 16) Golden River Traffic - 6 Talisman Business Centre - Talisman road - Bicester OXON OX26 6HR - UNITED KINGDOM - - 00-50-C2 (hex) ETI - 337000-337FFF (base 16) ETI - 272-20 Taejun-Dong - Kwang Joo Kyung Ki-Do 464-808 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Ernitec A/S - 338000-338FFF (base 16) Ernitec A/S - Hoerkaer 24 - Herlev 2730 - DENMARK - - 00-50-C2 (hex) CEGELEC SUD EST - 339000-339FFF (base 16) CEGELEC SUD EST - ROUTE DE SALON - BP 9 - LES PENNES MIRABEAU 13755 - FRANCE - - 00-50-C2 (hex) United Telecoms Ltd - 33A000-33AFFF (base 16) United Telecoms Ltd - 18A/19 Doddanagundi Indl area - Mahadevapura - Banagalore Karnataka 560048 - INDIA - - 00-50-C2 (hex) MultimediaLED - 33B000-33BFFF (base 16) MultimediaLED - 11370 Sunrise Park Drive - Rancho Cordova CA 95742 - UNITED STATES - - 00-50-C2 (hex) SkipJam - 33C000-33CFFF (base 16) SkipJam - 386 North Street - Greenwich CT 06830 - UNITED STATES - - 00-50-C2 (hex) General Dynamics Decision Systems - 33D000-33DFFF (base 16) General Dynamics Decision Systems - 8220 E. Roosevelt Street - M/D R7125 - Scottsdale AZ 85257 - UNITED STATES - - 00-50-C2 (hex) CA Technology, Inc - 33E000-33EFFF (base 16) CA Technology, Inc - 533 Fellowship Rd - Suite 250 - Mt Laurel NJ 08054 - UNITED STATES - - 00-50-C2 (hex) EXYS bvba - 33F000-33FFFF (base 16) EXYS bvba - Populierenlaan 6 - Tildonk 3150 - BELGIUM - - 00-50-C2 (hex) Virtu - 340000-340FFF (base 16) Virtu - Auke Vleerstraat 1 - Enschede OV 7521 PE - NETHERLANDS - - 00-50-C2 (hex) Novx Systems - 341000-341FFF (base 16) Novx Systems - Suite 100 - Leslie Street - Richmond Hill Ontario L4B 4N1 - CANADA - - 00-50-C2 (hex) St. Michael Strategies - 342000-342FFF (base 16) St. Michael Strategies - 701, Salaberry - suite 201 - Chambly Quebec J3L 1R2 - CANADA - - 00-50-C2 (hex) ABB Xiamen Switchgear Co. Ltd. - 343000-343FFF (base 16) ABB Xiamen Switchgear Co. Ltd. - ABB Industrial Park, Torch Hi-Tech Industrial Development Zone - Xiamen S.E.Z. Fujian Province 361006 - CHINA - - 00-50-C2 (hex) ads-tec GmbH - 344000-344FFF (base 16) ads-tec GmbH - Raiffeisenstrasse 14 - Leinfelden-Echterdingen BW 70771 - GERMANY - - 00-50-C2 (hex) ACT - 345000-345FFF (base 16) ACT - Unit C1, South City Business Center - Tallaght Dublin - IRELAND - - 00-50-C2 (hex) biokeysystem - 346000-346FFF (base 16) biokeysystem - 2f, 170-13, guro3-dong, guro-gu - seoul 152-847 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Row Seven Ltd - 347000-347FFF (base 16) Row Seven Ltd - 13 Swan Yard - London N1 1SD - UNITED KINGDOM - - 00-50-C2 (hex) KoolSpan, Inc. - 348000-348FFF (base 16) KoolSpan, Inc. - 11134 Stephalee Lane - North Bethesda MD 20852 - UNITED STATES - - 00-50-C2 (hex) SSI Schaefer Peem - 349000-349FFF (base 16) SSI Schaefer Peem - Fischeraustrasse 27 - Graz Steiermark A-8051 - AUSTRIA - - 00-50-C2 (hex) NIE Corporation - 34A000-34AFFF (base 16) NIE Corporation - Ohara-Sanden Bldg. 7-F - 1-8-2 Higashigotanda - Shinagawa-ku Tokyo 141-0022 - JAPAN - - 00-50-C2 (hex) Ecutel Systems, Inc. - 34B000-34BFFF (base 16) Ecutel Systems, Inc. - 2300 Corporate Park Drive - Suite 410 - Herndon VA 20171 - UNITED STATES - - 00-50-C2 (hex) Chuo Electric Works Co., LTD. - 34C000-34CFFF (base 16) Chuo Electric Works Co., LTD. - 51 Tateminami - Watari-Cho - Watari-Gun Miyagi 989-2361 - JAPAN - - 00-50-C2 (hex) BMK professional electronics GmbH - 34D000-34DFFF (base 16) BMK professional electronics GmbH - Werner-von-Siemens-Str. 6 - Augsburg Bavaria 86156 - GERMANY - - 00-50-C2 (hex) ABB Power Technologies S.p.A. Unità  Operativa SACE (PTMV) - 34E000-34EFFF (base 16) ABB Power Technologies S.p.A. Unità  Operativa SACE (PTMV) - vai Friuli 4 - Dalmine (Bergamo) 20044 - ITALY - - 00-50-C2 (hex) North Pole Engineering, Inc. - 34F000-34FFFF (base 16) North Pole Engineering, Inc. - 212 3rd Ave N - Suite 565 - Minneapolis Minnesota 55401 - UNITED STATES - - 00-50-C2 (hex) Kinesys Projects Limited - 350000-350FFF (base 16) Kinesys Projects Limited - The Business Village - 3-9 Broomhill Road - LONDON SW18 4JQ - UNITED KINGDOM - - 00-50-C2 (hex) Finesystem Co., Ltd - 351000-351FFF (base 16) Finesystem Co., Ltd - FINE BLDG. 2F - 2956-6 ISHIKAWACYO - HACHIOUJI TOKYO-TO 192-0032 - JAPAN - - 00-50-C2 (hex) LUCEO - 352000-352FFF (base 16) LUCEO - 16 Rue Laënnec - Vern Sur Seiche 35770 - FRANCE - - 00-50-C2 (hex) Crossing Informationssysteme GmbH - 353000-353FFF (base 16) Crossing Informationssysteme GmbH - Schlesische Str. 26 - Berlin 10997 - GERMANY - - 00-50-C2 (hex) Advanced IP Communications - 354000-354FFF (base 16) Advanced IP Communications - 1909 N. Glenville Suite 100 - Richardson TX 75081 - UNITED STATES - - 00-50-C2 (hex) IHM - 355000-355FFF (base 16) IHM - Vandtaarnsvej 87 - Soborg Copenhagen 2860 - DENMARK - - 00-50-C2 (hex) Baytech Cinema - 356000-356FFF (base 16) Baytech Cinema - 2755 Campus Drive - Ste 200 - San Mateo CA 94403 - UNITED STATES - - 00-50-C2 (hex) Athena Semiconductor - 357000-357FFF (base 16) Athena Semiconductor - 47538 Fremont Blvd. - Fremont CA 94358 - UNITED STATES - - 00-50-C2 (hex) ALCEA - 358000-358FFF (base 16) ALCEA - 3 Rue Joly de Bammeville - Zac de La fontaine de Jouvence - 91460 Marcoussis - FRANCE - - 00-50-C2 (hex) Kramer Electronics Ltd. - 359000-359FFF (base 16) Kramer Electronics Ltd. - 3 Am VeOlamo St. - Jerusalem 95463 - ISRAEL - - 00-50-C2 (hex) Advanced Si-Net Co., LTD. - 35A000-35AFFF (base 16) Advanced Si-Net Co., LTD. - 9F-2, No. 245, Sec. 3, Roosevelt Rd. - Taipei Da-an District 106 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) VLSIP TECHNOLOGIES, INC - 35B000-35BFFF (base 16) VLSIP TECHNOLOGIES, INC - 750 PRESIDENTIAL DR - RICHARDSON TEXAS 75081 - UNITED STATES - - 00-50-C2 (hex) Ratotec GmbH - 35C000-35CFFF (base 16) Ratotec GmbH - Steinfurt 39 - Stolberg 522222 - GERMANY - - 00-50-C2 (hex) NetTest A/S - 35D000-35DFFF (base 16) NetTest A/S - Kirkebjerg Alle 90 - Brondby CPH 2605 - DENMARK - - 00-50-C2 (hex) Jobin Yvon,Inc - 35E000-35EFFF (base 16) Jobin Yvon,Inc - 3880 Park Ave - Edison NJ 08820 - UNITED STATES - - 00-50-C2 (hex) F.Imm. S.r.L. - 35F000-35FFFF (base 16) F.Imm. S.r.L. - Viale delle Industrie 13/a - ROVIGO RO 45100 - ITALY - - 00-50-C2 (hex) Digital Receiver Technology, Inc. - 360000-360FFF (base 16) Digital Receiver Technology, Inc. - 20250 Century Blvd., #300 - Germantown MD 20874 - UNITED STATES - - 00-50-C2 (hex) Contec - 361000-361FFF (base 16) Contec - Burleska 3a - Warsaw 01-939 - POLAND - - 00-50-C2 (hex) AZD Praha s.r.o. - 362000-362FFF (base 16) AZD Praha s.r.o. - Zirovnicka 2/3146 - Prague 106 17 - CZECH REPUBLIC - - 00-50-C2 (hex) Septentrio nv/sa - 363000-363FFF (base 16) Septentrio nv/sa - Ubicenter - Philipssite 5 - Leuven BE-3001 - BELGIUM - - 00-50-C2 (hex) TATTILE SRL - 364000-364FFF (base 16) TATTILE SRL - VIA TRENTO 127/129 - CAPRIANO DEL COLLE - BRESCIA 25020 - ITALY - - 00-50-C2 (hex) VPG - 365000-365FFF (base 16) VPG - Box 423 - Karlskoga SE-691 27 - SWEDEN - - 00-50-C2 (hex) Vanguard Technology Corp. - 366000-366FFF (base 16) Vanguard Technology Corp. - 5633 Paradise Blvd. NW - Albuquerque NM 87114 - UNITED STATES - - 00-50-C2 (hex) CANMAX Technology Ltd. - 367000-367FFF (base 16) CANMAX Technology Ltd. - 7F, No.183. Section 1, Tatung Road - Hsi Chih Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) ASPEL S.A. - 368000-368FFF (base 16) ASPEL S.A. - os. Sienkiewicza 33 - Zabierzow Malopolska 32080 - POLAND - - 00-50-C2 (hex) Always On Wireless - 369000-369FFF (base 16) Always On Wireless - 410 Pierce - Houston TX 77002 - UNITED STATES - - 00-50-C2 (hex) Optronic Partner pr AB - 36A000-36AFFF (base 16) Optronic Partner pr AB - Box 733 - SKELLEFTEA SE 93127 - SWEDEN - - 00-50-C2 (hex) Minerva Technology Inc - 36B000-36BFFF (base 16) Minerva Technology Inc - 645 Island Rd - Victoria BC V8S2T7 - CANADA - - 00-50-C2 (hex) RISCO Group - 36C000-36CFFF (base 16) RISCO Group - 14 Hachoma - Rishon Letzion 75655 - ISRAEL - - 00-50-C2 (hex) Oplink Communications - 36D000-36DFFF (base 16) Oplink Communications - 3469 North First St. - San Jose California 95134 - UNITED STATES - - 00-50-C2 (hex) Minicom Advanced Systems Ltd - 36E000-36EFFF (base 16) Minicom Advanced Systems Ltd - 16 Hartom str - Jerusalem 91450 - ISRAEL - - 00-50-C2 (hex) XIMEA s.r.o. - 36F000-36FFFF (base 16) XIMEA s.r.o. - Lesna 52 - Marianka SK 900 33 - SLOVAKIA - - 00-50-C2 (hex) Europe Technologies - 370000-370FFF (base 16) Europe Technologies - 1681, Route des Dolines - Les Taissounieres BAT HB3 - Valbonne PACA 06560 - FRANCE - - 00-50-C2 (hex) DIGITAL ART SYSTEM - 371000-371FFF (base 16) DIGITAL ART SYSTEM - 838 rue de l'Aiguelongue - Montpellier HR 34090 - FRANCE - - 00-50-C2 (hex) ELV Elektronik AG - 372000-372FFF (base 16) ELV Elektronik AG - Maiburger Str. 32-36 - Leer Niedersachsen 26789 - GERMANY - - 00-50-C2 (hex) Companion Worlds, inc. - 373000-373FFF (base 16) Companion Worlds, inc. - 10171 Carmen Road - Cupertino CA 95014 - UNITED STATES - - 00-50-C2 (hex) Owasys Advanced Wireless Devices - 374000-374FFF (base 16) Owasys Advanced Wireless Devices - Parque Tecnologico, 207-B - Zamudio Vizcaya E-48170 - SPAIN - - 00-50-C2 (hex) TIR Systems Ltd. - 375000-375FFF (base 16) TIR Systems Ltd. - 7700 Riverfront Gate - Burnaby British Columbia V5J 5M4 - CANADA - - 00-50-C2 (hex) CLEODE - 376000-376FFF (base 16) CLEODE - 5 rue Louis de Broglie - LANNION 22300 - FRANCE - - 00-50-C2 (hex) Xycom VME - 377000-377FFF (base 16) Xycom VME - 710 N. Maple Road - Saline MI 48176 - UNITED STATES - - 00-50-C2 (hex) Daintree Networks Inc - 378000-378FFF (base 16) Daintree Networks Inc - 111 N. Market St, Suite 615 - San Jose CA 95113-1101 - UNITED STATES - - 00-50-C2 (hex) Control LAN S.A. - 379000-379FFF (base 16) Control LAN S.A. - Ortiz de Ocampo 3060 - Piso 2 - Buenos Aires CF 1425 - ARGENTINA - - 00-50-C2 (hex) IDA Corporation - 37A000-37AFFF (base 16) IDA Corporation - 1345 Main Ave - Fargo North Dakota 58103 - UNITED STATES - - 00-50-C2 (hex) freescale semiconductor - 37B000-37BFFF (base 16) freescale semiconductor - 2100 east elliot - Tempe Az 85284 - UNITED STATES - - 00-50-C2 (hex) MODIA SYSTEMS Co., Ltd - 37C000-37CFFF (base 16) MODIA SYSTEMS Co., Ltd - 1-14-12, Ohsawa - Koshigaya-shi Saitama-ken 343-0025 - JAPAN - - 00-50-C2 (hex) VeroTrak Inc. - 37D000-37DFFF (base 16) VeroTrak Inc. - 6062 Hollow Tree Court - Colorado Springs CO 80918 - UNITED STATES - - 00-50-C2 (hex) Ni.Co. S.r.l. - 37E000-37EFFF (base 16) Ni.Co. S.r.l. - C.so Torino, 91/B - Buttigliera Alta Torino 10090 - ITALY - - 00-50-C2 (hex) Foresearch - 37F000-37FFFF (base 16) Foresearch - Kwanak-ku, Shinrim-dong 56-1 Bldg 138 Rm 302 - Seoul National Univ. - Seoul Korea 151-742 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) EKE-Electronics Ltd. - 380000-380FFF (base 16) EKE-Electronics Ltd. - Piispanportti 7 - ESPOO - 02240 - FINLAND - - 00-50-C2 (hex) Realtime Engineering AG - 381000-381FFF (base 16) Realtime Engineering AG - Rickenbacherstr. 29 - Gelterkinden BL 4460 - SWITZERLAND - - 00-50-C2 (hex) Colorado vNet - 382000-382FFF (base 16) Colorado vNet - 255 East 6th Street - Loveland Colorado 80537 - UNITED STATES - - 00-50-C2 (hex) ICS Electronics - 383000-383FFF (base 16) ICS Electronics - 7034 Commerce Circle - Pleasanton CA 94588 - UNITED STATES - - 00-50-C2 (hex) Wireless Reading Systems Holding ASA - 384000-384FFF (base 16) Wireless Reading Systems Holding ASA - Skredderveien 9 - Moss Østfold 1537 - NORWAY - - 00-50-C2 (hex) SUNGJIN NEOTECH Co.Ltd. - 385000-385FFF (base 16) SUNGJIN NEOTECH Co.Ltd. - #105,Suntechcity Bldg,513-15 Sangdaewon-Dong, Jungwon-Gu - Seongnam Kyonggi-Do 462-806 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Precision System Science Co.,Ltd - 386000-386FFF (base 16) Precision System Science Co.,Ltd - 88 - Kamihongou,Matsudo-shi Chiba 271-0064 - JAPAN - - 00-50-C2 (hex) Inoteska s.r.o. - 387000-387FFF (base 16) Inoteska s.r.o. - Podturen-Roven 221 - Liptovsky Hradok Zilina region 033 01 - SLOVAKIA - - 00-50-C2 (hex) IEE Inc - 388000-388FFF (base 16) IEE Inc - 7740 Lemona Ave - Van Nuys California 91409 - UNITED STATES - - 00-50-C2 (hex) Exavio Inc. - 389000-389FFF (base 16) Exavio Inc. - 3121 Jay Street - Santa Clara California 95054 - UNITED STATES - - 00-50-C2 (hex) Embedtronics Enterprise - 38A000-38AFFF (base 16) Embedtronics Enterprise - 16 Jalan Krian - Georgetown - 10400 Penang - MALAYSIA - - 00-50-C2 (hex) InterBridge,Inc. - 38B000-38BFFF (base 16) InterBridge,Inc. - Inabe - Ina Nagano 396-0011 - JAPAN - - 00-50-C2 (hex) EPSILON SRL - 38C000-38CFFF (base 16) EPSILON SRL - VIA DELLE GEROLE 24 - CAPONAGO MILANO 20040 - ITALY - - 00-50-C2 (hex) A&G Soluzioni Digitali - 38D000-38DFFF (base 16) A&G Soluzioni Digitali - Palazzo S.Elisabetta - Via Marradi 4 - Livorno LI 57126 - ITALY - - 00-50-C2 (hex) Nordic Alarm AB - 38E000-38EFFF (base 16) Nordic Alarm AB - Englundavägen 11 - Solna 17141 - SWEDEN - - 00-50-C2 (hex) TTC Telecom - 38F000-38FFFF (base 16) TTC Telecom - Jiskrova 4 - Kosice 040 01 - SLOVAKIA - - 00-50-C2 (hex) TC Communications - 390000-390FFF (base 16) TC Communications - 17575 Cartwright Road - Irvine CA 92614 - UNITED STATES - - 00-50-C2 (hex) Esensors, Inc. - 391000-391FFF (base 16) Esensors, Inc. - 4240 Ridge Lea Road - Suite 37 - Amherst NY 14226 - UNITED STATES - - 00-50-C2 (hex) PHYTEC Messtechnik GmbH - 392000-392FFF (base 16) PHYTEC Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) SYS TEC electronic GmbH - 393000-393FFF (base 16) SYS TEC electronic GmbH - August-Bebel-Str. 29 - Greiz Thuringia 07973 - GERMANY - - 00-50-C2 (hex) Embedit A/S - 394000-394FFF (base 16) Embedit A/S - Generatorvej 8A - Herlev 2730 - DENMARK - - 00-50-C2 (hex) vidisys gmbh - 395000-395FFF (base 16) vidisys gmbh - Rudolf-Diesel-Ring 30 - Sauerlach Bavaria D-82054 - GERMANY - - 00-50-C2 (hex) RapidWave Inc. - 396000-396FFF (base 16) RapidWave Inc. - 6296A San Ignacio Ave. - San Jose CA 95119 - UNITED STATES - - 00-50-C2 (hex) MANGO DSP Ltd. - 397000-397FFF (base 16) MANGO DSP Ltd. - 8 HARATOM St. - JERUSALEM 91450 - ISRAEL - - 00-50-C2 (hex) InHand Electronics, Inc. - 398000-398FFF (base 16) InHand Electronics, Inc. - 30 W. Gude Drive - Suite 100 - Rockville MD 20850 - UNITED STATES - - 00-50-C2 (hex) Advanced Micro Controls Inc. - 399000-399FFF (base 16) Advanced Micro Controls Inc. - 20 Gear Drive - Terryville CT 06786 - UNITED STATES - - 00-50-C2 (hex) Optical Air Data Systems - 39A000-39AFFF (base 16) Optical Air Data Systems - 10531 Terminal road - Manassas VA 20110 - UNITED STATES - - 00-50-C2 (hex) YUYAMA MFG. CO., LTD. - 39B000-39BFFF (base 16) YUYAMA MFG. CO., LTD. - 3-3-1 - MEISHINGUCHI - TOYONAKA OSAKA 561-0841 - JAPAN - - 00-50-C2 (hex) TIYODA MFG CO.,LTD. - 39C000-39CFFF (base 16) TIYODA MFG CO.,LTD. - 75-5 Imojiya - Chikuma-city NAGANO 387-0015 - JAPAN - - 00-50-C2 (hex) DigitalDeck, Inc. - 39D000-39DFFF (base 16) DigitalDeck, Inc. - 3 Twin Dolphin Drive, Suite 160 - Redwood City CA 94065 - UNITED STATES - - 00-50-C2 (hex) A.R.G ElectroDesign Ltd - 39E000-39EFFF (base 16) A.R.G ElectroDesign Ltd - Querns Business Centre - Whitworth Road - Cirencester Gloucestershire GL7 1RT - UNITED KINGDOM - - 00-50-C2 (hex) Isensix - 39F000-39FFFF (base 16) Isensix - 8555 Aero Dr Suite 201 - San Diego CA 92111 - UNITED STATES - - 00-50-C2 (hex) StreetFire Sound Labs, LLC - 3A0000-3A0FFF (base 16) StreetFire Sound Labs, LLC - 795 Folsom St., First Floor - San Francisco CA 94107 - UNITED STATES - - 00-50-C2 (hex) Samsoft - 3A1000-3A1FFF (base 16) Samsoft - Linde alle 20 - Glostrup DK 2600 - DENMARK - - 00-50-C2 (hex) Vegas Amusement - 3A2000-3A2FFF (base 16) Vegas Amusement - P.O. Box 11 - Mountain Rest SC 29664 - UNITED STATES - - 00-50-C2 (hex) Star Link Communication Pvt. Ltd. - 3A3000-3A3FFF (base 16) Star Link Communication Pvt. Ltd. - HR114/6 & Hr132/6, Pulprehladpur, - Suraj kund Road, Near Badarpur, - New Delhi 110044 - INDIA - - 00-50-C2 (hex) Silvertree Engineering Ltd - 3A4000-3A4FFF (base 16) Silvertree Engineering Ltd - Unit 9 Heron Way - Newham Industrial Estate - Truro Cornwall TR1 2XN - UNITED KINGDOM - - 00-50-C2 (hex) LabJack Corporation - 3A5000-3A5FFF (base 16) LabJack Corporation - 3232 S Vance St STE 100 - Lakewood CO 80227 - UNITED STATES - - 00-50-C2 (hex) IntelliDesign Pty Ltd - 3A6000-3A6FFF (base 16) IntelliDesign Pty Ltd - 99 Bluestone Circuit - Seventeen Mile Rocks Queensland 4073 - AUSTRALIA - - 00-50-C2 (hex) Elektrotechnik & Elektronik Oltmann GmbH - 3A7000-3A7FFF (base 16) Elektrotechnik & Elektronik Oltmann GmbH - Gartenfelder Str. 29 - Berlin D-13599 - GERMANY - - 00-50-C2 (hex) Engim, Inc. - 3A8000-3A8FFF (base 16) Engim, Inc. - 40 Nagog Park - Acton MA 01720 - UNITED STATES - - 00-50-C2 (hex) Westronic Systems Inc. - 3A9000-3A9FFF (base 16) Westronic Systems Inc. - #1, 1715 - 27th Ave NE - Calgary AB T2E 7E1 - CANADA - - 00-50-C2 (hex) Networked Robotics Corporation - 3AA000-3AAFFF (base 16) Networked Robotics Corporation - 825 Chicago Avenue Suite F - Evanston Illinois 60202 - UNITED STATES - - 00-50-C2 (hex) taskit Rechnertechnik GmbH - 3AB000-3ABFFF (base 16) taskit Rechnertechnik GmbH - Seelenbinder Straße 33 - Berlin 12 555 - GERMANY - - 00-50-C2 (hex) InAccess Networks - 3AC000-3ACFFF (base 16) InAccess Networks - 230 Sigrou Avenue - Kalithea Athens 17672 - GREECE - - 00-50-C2 (hex) Spirent Communications (Scotland) Limited - 3AD000-3ADFFF (base 16) Spirent Communications (Scotland) Limited - Hamilton International Technology Park - Watt Place - Glasgow South Lanarkshire G72 0FF - UNITED KINGDOM - - 00-50-C2 (hex) Hankuk Tapi Computer Co., Ltd - 3AE000-3AEFFF (base 16) Hankuk Tapi Computer Co., Ltd - 357-1, Jangdae-Dong, Yusung-Gu - Daejeon 305-308 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Norbit ODM AS - 3AF000-3AFFFF (base 16) Norbit ODM AS - Stiklestadveien 1 - Trondheim 7041 - NORWAY - - 00-50-C2 (hex) Microtarget Tecnologia Digital Ltda. - 3B0000-3B0FFF (base 16) Microtarget Tecnologia Digital Ltda. - Rua Eng. Mesquita Sampaio, 54-FDS - São Paulo 04711-000 - BRAZIL - - 00-50-C2 (hex) RDC Specstroy-Svyaz Ltd - 3B1000-3B1FFF (base 16) RDC Specstroy-Svyaz Ltd - Office 208, Shevchenko street, 2 - Taganrog Rostov region 347922 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Tennessee Valley Authority - 3B2000-3B2FFF (base 16) Tennessee Valley Authority - Computer Engineering TVAN - 1101 Market St., MP5G-C - Chattanooga TN 37402 - UNITED STATES - - 00-50-C2 (hex) Media Lab., Inc. - 3B3000-3B3FFF (base 16) Media Lab., Inc. - 3-6-7 Sotokanda Chiyoda-ku - Tokyo 101-0021 - JAPAN - - 00-50-C2 (hex) Contrôle Analytique inc. - 3B4000-3B4FFF (base 16) Contrôle Analytique inc. - 1076 rue Johnson - Thetford Mines Québec G6G 5W6 - CANADA - - 00-50-C2 (hex) NEC TOKIN Corporation - 3B5000-3B5FFF (base 16) NEC TOKIN Corporation - 1-1,Asahi-Cho 7-chome,Shiroishi, - Miyagi 989-0223 - JAPAN - - 00-50-C2 (hex) Arecont Vision, LLC - 3B6000-3B6FFF (base 16) Arecont Vision, LLC - 754 Brookside Lane - Sierra Madre CA 91024 - UNITED STATES - - 00-50-C2 (hex) Mindspeed Technologies - 3B7000-3B7FFF (base 16) Mindspeed Technologies - 8 Technology Drive - Westborough Massachusetts 01581 - UNITED STATES - - 00-50-C2 (hex) Keith & Koep GmbH - 3B8000-3B8FFF (base 16) Keith & Koep GmbH - Koenigsberger Str. 2 - Wuppertal D 42277 - GERMANY - - 00-50-C2 (hex) Gilbarco Autotank AB - 3B9000-3B9FFF (base 16) Gilbarco Autotank AB - P.O. Box 11059 - Johannesfredsvagen 11A - BROMMA SE-16111 - SWEDEN - - 00-50-C2 (hex) PHYTEC Messtechnik GmbH - 3BA000-3BAFFF (base 16) PHYTEC Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) IMAGO Technologies GmbH - 3BB000-3BBFFF (base 16) IMAGO Technologies GmbH - Strassheimer Strasse 45 - Friedberg D-61169 - GERMANY - - 00-50-C2 (hex) Tyzx, Inc. - 3BC000-3BCFFF (base 16) Tyzx, Inc. - 3895 Bohannon Drive - Menlo Park CA 94025 - UNITED STATES - - 00-50-C2 (hex) Bigbang L.T.D. - 3BD000-3BDFFF (base 16) Bigbang L.T.D. - Shikahama 8-7-18 - Adachi Tokyo 123-0864 - JAPAN - - 00-50-C2 (hex) Pauly Steuer- und Regelanlagen GmbH & Co. KG - 3BE000-3BEFFF (base 16) Pauly Steuer- und Regelanlagen GmbH & Co. KG - Pfingstweide 8 - Friedberg Hessen 61169 - GERMANY - - 00-50-C2 (hex) Audio Processing Technology Ltd - 3BF000-3BFFFF (base 16) Audio Processing Technology Ltd - Whiterock Business Park - 729 Springfield Road - Belfast BT12 7FP - UNITED KINGDOM - - 00-50-C2 (hex) EDA Industries Srl - 3C0000-3C0FFF (base 16) EDA Industries Srl - Via dell'elettronica - Cittaducale Rieti 02015 - ITALY - - 00-50-C2 (hex) MicroTek Electronics, Inc. - 3C1000-3C1FFF (base 16) MicroTek Electronics, Inc. - 1020 Calle Cordillera, #105 - San Clemente CA 92673 - UNITED STATES - - 00-50-C2 (hex) Casabyte Inc. - 3C2000-3C2FFF (base 16) Casabyte Inc. - POB 10127 - 2801 Prosperity Road - Blacksburg VA 24062 - UNITED STATES - - 00-50-C2 (hex) 4g Technologies, L.P. - 3C3000-3C3FFF (base 16) 4g Technologies, L.P. - 1900 Industrial Blvd. - Suite 200 - Colleyville TX 76034 - UNITED STATES - - 00-50-C2 (hex) Sypris Electronics - 3C4000-3C4FFF (base 16) Sypris Electronics - 10901N McKinley Dr - Tampa Florida 33612 - UNITED STATES - - 00-50-C2 (hex) Silicon Optix Canada Inc. - 3C5000-3C5FFF (base 16) Silicon Optix Canada Inc. - 2005 Sheppard Ave. East, Suite 100 - Toronto Ontario L2J 5B4 - CANADA - - 00-50-C2 (hex) Net Optics - 3C6000-3C6FFF (base 16) Net Optics - 5303 Betsy Ross Drive - Santa Clara California 95054 - UNITED STATES - - 00-50-C2 (hex) Salent Technologies Ltd - 3C7000-3C7FFF (base 16) Salent Technologies Ltd - Rowan House - Wyndford Brae - Philpstoun Linlithgow EH49 6RN - UNITED KINGDOM - - 00-50-C2 (hex) Wheels of Zeus Inc. - 3C8000-3C8FFF (base 16) Wheels of Zeus Inc. - 15595 Los Gatos Blvd - Los Gatos CA 95032 - UNITED STATES - - 00-50-C2 (hex) Dilax Intelcom AG - 3C9000-3C9FFF (base 16) Dilax Intelcom AG - Fidlerstr. 2 - Ermatingen Thurgau 8272 - SWITZERLAND - - 00-50-C2 (hex) ABB Inc. - 3CA000-3CAFFF (base 16) ABB Inc. - 843 North Jefferson St. - Lewisburg West Virginia 24901 - UNITED STATES - - 00-50-C2 (hex) Analytica GmbH - 3CB000-3CBFFF (base 16) Analytica GmbH - Vorholzstraße 36 - Karlsruhe Baden-Württemberg 76137 - GERMANY - - 00-50-C2 (hex) LINKWELL TELESYSTEMS PRIVATE LIMITED - 3CC000-3CCFFF (base 16) LINKWELL TELESYSTEMS PRIVATE LIMITED - # 1-11-252/1/A, GOWRA KLASSIC - BEGUMPET - HYDERABAD-500016 ANDHRA PRADESH 500016 - INDIA - - 00-50-C2 (hex) Micro-Measurements - 3CD000-3CDFFF (base 16) Micro-Measurements - 961 Wendell Blvd - Wendell NC 27591 - UNITED STATES - - 00-50-C2 (hex) Ward Leonard Electric Company - 3CE000-3CEFFF (base 16) Ward Leonard Electric Company - 401 Watertown Road - Thomaston CT 06787 - UNITED STATES - - 00-50-C2 (hex) Technovare Systems, Inc. - 3CF000-3CFFFF (base 16) Technovare Systems, Inc. - 1675 Scenic Avenue - Suite 200 - Costa Mesa CA 92626 - UNITED STATES - - 00-50-C2 (hex) Micro-Robotics Limited - 3D0000-3D0FFF (base 16) Micro-Robotics Limited - 135 Ditton Walk - CAMBRIDGE Cambs. CB5 8QB - UNITED KINGDOM - - 00-50-C2 (hex) Braintronics BV - 3D1000-3D1FFF (base 16) Braintronics BV - Gildemark 130 - Almere 1351 HL - NETHERLANDS - - 00-50-C2 (hex) Adilec Enginyeria SL - 3D2000-3D2FFF (base 16) Adilec Enginyeria SL - Francesc Macia, 1 - Molins de Rei Barcelona 08750 - SPAIN - - 00-50-C2 (hex) American LED-gible Inc. - 3D3000-3D3FFF (base 16) American LED-gible Inc. - 1776 Lone Eagle St. - Columbus Ohio 43228 - UNITED STATES - - 00-50-C2 (hex) Wisnu and Supak Co.Ltd. - 3D4000-3D4FFF (base 16) Wisnu and Supak Co.Ltd. - 102/111-112 Moo-Ban Sinpattanathanee - Tessabansongkroh Rd. Ladyao - Jatujak Bangkok 10900 - THAILAND - - 00-50-C2 (hex) Fluke Biomedical, Radiation Management Services - 3D5000-3D5FFF (base 16) Fluke Biomedical, Radiation Management Services - 6045 Cochran Rd. - Solon Ohio 44139 - UNITED STATES - - 00-50-C2 (hex) Comlab Inc. - 3D6000-3D6FFF (base 16) Comlab Inc. - 2300, Leon-Harmel - Suite 220 - Quebec G1N 4L2 - CANADA - - 00-50-C2 (hex) TTC TELEKOMUNIKACE Ltd - 3D7000-3D7FFF (base 16) TTC TELEKOMUNIKACE Ltd - Tøebohostická 987/5, Prague 10 - Prague CZ-100 00 - CZECH REPUBLIC - - 00-50-C2 (hex) Key Systems , Inc. - 3D8000-3D8FFF (base 16) Key Systems , Inc. - 7635 Glacier Hill - Victor NY 14564 - UNITED STATES - - 00-50-C2 (hex) Bavaria Digital Technik GmbH - 3D9000-3D9FFF (base 16) Bavaria Digital Technik GmbH - Rehbichler Weg 26 - Pfronten Bayern 87459 - GERMANY - - 00-50-C2 (hex) M5 Data Limited - 3DA000-3DAFFF (base 16) M5 Data Limited - Mendip Court - Bath Road - Wells Somerset BA5 3DG - UNITED KINGDOM - - 00-50-C2 (hex) Osmetech Inc. - 3DB000-3DBFFF (base 16) Osmetech Inc. - 235 Hembree Park Drive - Roswell GA 30076 - UNITED STATES - - 00-50-C2 (hex) 3D perception - 3DC000-3DCFFF (base 16) 3D perception - PO Box 455 - Solbraveien 41 - Asker N-1373 - NORWAY - - 00-50-C2 (hex) ELMIC GmbH - 3DD000-3DDFFF (base 16) ELMIC GmbH - Grabenstr. 149a - Duisburg NRW 47057 - GERMANY - - 00-50-C2 (hex) ABB Power Technologies S.p.A. Unità Operativa SACE (PTMV) - 3DE000-3DEFFF (base 16) ABB Power Technologies S.p.A. Unità Operativa SACE (PTMV) - via Friuli 4 - Dalmine Bergamo 24044 - ITALY - - 00-50-C2 (hex) BiODE Inc. - 3DF000-3DFFFF (base 16) BiODE Inc. - 100 Larrabee Rd. - Westbrook ME 04092 - UNITED STATES - - 00-50-C2 (hex) Oy Stinghorn Ltd - 3E0000-3E0FFF (base 16) Oy Stinghorn Ltd - Stinghorn - LAPPEENRANTA 53101 - FINLAND - - 00-50-C2 (hex) NeuLion Incorporated - 3E1000-3E1FFF (base 16) NeuLion Incorporated - 1600 Old Country Road - Plainview NY 11803 - UNITED STATES - - 00-50-C2 (hex) SysNova - 3E2000-3E2FFF (base 16) SysNova - Herweg 24 - Maennedorf Zurich 8708 - SWITZERLAND - - 00-50-C2 (hex) CSIRO - Division of Exploration and Mining - 3E3000-3E3FFF (base 16) CSIRO - Division of Exploration and Mining - PO Box 883 - Kenmore QLD 4069 - AUSTRALIA - - 00-50-C2 (hex) CUE, a.s. - 3E4000-3E4FFF (base 16) CUE, a.s. - K Nouzovu 2090/6 - Praha 4 143 00 - CZECH REPUBLIC - - 00-50-C2 (hex) Vacon Plc - 3E5000-3E5FFF (base 16) Vacon Plc - P.O.Box 25 - Vaasa 65381 - FINLAND - - 00-50-C2 (hex) CRDE - 3E6000-3E6FFF (base 16) CRDE - ZI DES GRANDS CAMPS - BP 9 - MERCUES LOT 46090 - FRANCE - - 00-50-C2 (hex) Revolution Education Ltd - 3E7000-3E7FFF (base 16) Revolution Education Ltd - 4 Old Dairy Business Centre - Melcombe Road - Bath BNES BA2 3LR - UNITED KINGDOM - - 00-50-C2 (hex) Conformative Systems, Inc. - 3E8000-3E8FFF (base 16) Conformative Systems, Inc. - 4516 Seton Center Parkway - Austin TX 78759 - UNITED STATES - - 00-50-C2 (hex) MedAvant Healthcare - 3E9000-3E9FFF (base 16) MedAvant Healthcare - 2533 Centennial Blvd - Suite B - Jeffersonville IN 47150 - UNITED STATES - - 00-50-C2 (hex) Alro Information Systems SA - 3EA000-3EAFFF (base 16) Alro Information Systems SA - Route d'Onnens 1 - Neyruz FR CH-1740 - SWITZERLAND - - 00-50-C2 (hex) ISS International - 3EB000-3EBFFF (base 16) ISS International - P.O Box 12063 - Die Boord - Stellenbosch Western Cape 7613 - SOUTH AFRICA - - 00-50-C2 (hex) Teneros - 3EC000-3ECFFF (base 16) Teneros - 215 Castro Street - 3rd Floor - Mountain View California 94041 - UNITED STATES - - 00-50-C2 (hex) The Board Room Inc. - 3ED000-3EDFFF (base 16) The Board Room Inc. - 1220 Lakeview Ct. - Romeoville IL 60446 - UNITED STATES - - 00-50-C2 (hex) Commoca, Inc - 3EE000-3EEFFF (base 16) Commoca, Inc - #68 East Mendez Vigo Suite 3 - Mayaguez PR 00680 - PUERTO RICO - - 00-50-C2 (hex) PAT Industries, DBA Pacific Advanced Technology - 3EF000-3EFFFF (base 16) PAT Industries, DBA Pacific Advanced Technology - 85 Industrial Way, Unit A - Buellton CA 93427 - UNITED STATES - - 00-50-C2 (hex) megatec electronic GmbH - 3F0000-3F0FFF (base 16) megatec electronic GmbH - Lehenhammer 14 - Etzelwang Bayern 92268 - GERMANY - - 00-50-C2 (hex) Salland Electronics Holding BV - 3F1000-3F1FFF (base 16) Salland Electronics Holding BV - Katwolderweg 15 - Zwolle Overijssel NL8041AC - NETHERLANDS - - 00-50-C2 (hex) STL GmbH - 3F2000-3F2FFF (base 16) STL GmbH - Max-Stromeyer-Straße 116 - Konstanz Baden-Württemberg 78467 - GERMANY - - 00-50-C2 (hex) Hytec Geraetebau GmbH - 3F3000-3F3FFF (base 16) Hytec Geraetebau GmbH - Cochemer Straße 12 - 14 - Mannheim 68309 - GERMANY - - 00-50-C2 (hex) MC TECHNOLOGY GmbH - 3F4000-3F4FFF (base 16) MC TECHNOLOGY GmbH - Ottilienweg 9 - Blumberg BW 78176 - GERMANY - - 00-50-C2 (hex) Phaedrus Limited - 3F5000-3F5FFF (base 16) Phaedrus Limited - 5 Marsh House Mill - Brussels Road, - Darwen Lancashire BB3 3JJ - UNITED KINGDOM - - 00-50-C2 (hex) dAFTdATA Limited - 3F6000-3F6FFF (base 16) dAFTdATA Limited - dAFT HQ - 8 Roddam Close - Colchester Essex CO3 3UN - UNITED KINGDOM - - 00-50-C2 (hex) Advantage R&D - 3F7000-3F7FFF (base 16) Advantage R&D - 16210 West Hardy - Houston Texas 77060 - UNITED STATES - - 00-50-C2 (hex) Superna Ltd - 3F8000-3F8FFF (base 16) Superna Ltd - 102 Donald Dr - Hamilton NJ 08619 - UNITED STATES - - 00-50-C2 (hex) Sintium Ltd - 3F9000-3F9FFF (base 16) Sintium Ltd - PO Box 14-273 - Panmure - Auckland 1134 - NEW ZEALAND - - 00-50-C2 (hex) Tumsan - 3FA000-3FAFFF (base 16) Tumsan - Sturenatu 27 - Helsinki 00510 - FINLAND - - 00-50-C2 (hex) Pigeon Point Systems LLC - 3FB000-3FBFFF (base 16) Pigeon Point Systems LLC - 2191 S. El Camino Real - Suite 209 - Oceanside CA 95054 - UNITED STATES - - 00-50-C2 (hex) Weinberger Deutschland GmbH - 3FC000-3FCFFF (base 16) Weinberger Deutschland GmbH - Am Weichselgarten 3 - Erlangen Bayern 91058 - GERMANY - - 00-50-C2 (hex) HARTMANN software GbR - 3FD000-3FDFFF (base 16) HARTMANN software GbR - Johann-Feilner-Str.1 - Mistelbach Bayern 95511 - GERMANY - - 00-50-C2 (hex) HaiVision Systems Inc - 3FE000-3FEFFF (base 16) HaiVision Systems Inc - 4445 Garand - Ville St-Laurent Quebec H4R2H9 - CANADA - - 00-50-C2 (hex) Cast Iron Systems - 3FF000-3FFFFF (base 16) Cast Iron Systems - 2593 Coast Ave Suite 200 - Mountain View CA 94043 - UNITED STATES - - 00-50-C2 (hex) SmartMotor AS - 400000-400FFF (base 16) SmartMotor AS - Stiklestadveien 1 - Trondheim Sør-Trøndelag 7041 - NORWAY - - 00-50-C2 (hex) Promess Incorporated - 401000-401FFF (base 16) Promess Incorporated - 11429 Grand River Road - Brighton MI 48116 - UNITED STATES - - 00-50-C2 (hex) Numeron Sp. z o.o. - 402000-402FFF (base 16) Numeron Sp. z o.o. - Bronislawa Czecha 16 - Czestochowa 42-200 - POLAND - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - 403000-403FFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu Street, district 1, - Bucharest 014186 - ROMANIA - - 00-50-C2 (hex) NanShanBridge Co.Ltd - 404000-404FFF (base 16) NanShanBridge Co.Ltd - C241, National Hi-Tech(westzone) - Incubation Service Center - ChengDu SiChuan 611731 - CHINA - - 00-50-C2 (hex) Guralp Systems Limited - 405000-405FFF (base 16) Guralp Systems Limited - 3 Midas House - Calleva Park, Aldermaston - Reading Berkshire RG7 8EA - UNITED KINGDOM - - 00-50-C2 (hex) CoreStreet, Ltd - 406000-406FFF (base 16) CoreStreet, Ltd - One Alewife Center, Suite 200 - Cambridge MA 02140 - UNITED STATES - - 00-50-C2 (hex) AIE Etudes - 407000-407FFF (base 16) AIE Etudes - 2 rue du Charles DE GAULLE - 27220 27220 - FRANCE - - 00-50-C2 (hex) TERN, Inc. - 408000-408FFF (base 16) TERN, Inc. - 1724 Picasso Ave. - Davis CA 95616 - UNITED STATES - - 00-50-C2 (hex) KTEC LTD - 409000-409FFF (base 16) KTEC LTD - 13 Giborei Israel ST - Netanya P.O BOX 8709 - ISRAEL - - 00-50-C2 (hex) Contec Steuerungstechnik & Automation GmbH - 40A000-40AFFF (base 16) Contec Steuerungstechnik & Automation GmbH - Wildbichlerstrasse 2e - Ebbs Tirol 6341 - AUSTRIA - - 00-50-C2 (hex) Center VOSPI JSC - 40B000-40BFFF (base 16) Center VOSPI JSC - Obrucheva 52 - Moscow 117393 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Applied Materials UK Ltd - 40C000-40CFFF (base 16) Applied Materials UK Ltd - Foundry Lane - Horsham West Sussex RH13 5PY - UNITED KINGDOM - - 00-50-C2 (hex) Afonics Fibreoptics Ltd - 40D000-40DFFF (base 16) Afonics Fibreoptics Ltd - Unit 16, - Thorney Leys Business Park - Witney Oxfordshire OX28 4GW - UNITED KINGDOM - - 00-50-C2 (hex) ads-tec GmbH - 40E000-40EFFF (base 16) ads-tec GmbH - Raiffeisenstraße 14 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-50-C2 (hex) BIR,INC. - 40F000-40FFFF (base 16) BIR,INC. - 425 BARCLAY BLVD - LINCOLNSHIRE IL 60069 - UNITED STATES - - 00-50-C2 (hex) Grossenbacher Systeme AG - 410000-410FFF (base 16) Grossenbacher Systeme AG - Spinnereistrasse 10 - St. Gallen SG 9008 - SWITZERLAND - - 00-50-C2 (hex) Multimessage Systems Ltd. - 411000-411FFF (base 16) Multimessage Systems Ltd. - Units 1 / 2, Cranbourne Ind. Est. - Cranbourne Road - Potters Bar Hertfordshire EN6 3JH - UNITED KINGDOM - - 00-50-C2 (hex) TSB Solutions Inc. - 412000-412FFF (base 16) TSB Solutions Inc. - 5399 Eglinton Ave West. - Suite 115 - Toronto Ontario M9C 5K6 - CANADA - - 00-50-C2 (hex) Goodrich - 413000-413FFF (base 16) Goodrich - Fuels & Utility Systems - 100 Panton Road - Vergennes Vermont 05491 - UNITED STATES - - 00-50-C2 (hex) Talleres de Escoriaza SA - 414000-414FFF (base 16) Talleres de Escoriaza SA - Barrio Ventas, 35 - Irun Gipuzkoa 20305 - SPAIN - - 00-50-C2 (hex) SensoTech GmbH - 415000-415FFF (base 16) SensoTech GmbH - Steinfeldstr. 3 - Magdeburg-Barleben Sachsen-Anhalt 39179 - GERMANY - - 00-50-C2 (hex) SELCO s.r.l. - 416000-416FFF (base 16) SELCO s.r.l. - Via Palladio 19 - Onara di Tombolo PADOVA 35010 - ITALY - - 00-50-C2 (hex) QT systems ab - 417000-417FFF (base 16) QT systems ab - Finnbacksgatan 11 - Lycksele Västerbotten 921 32 - SWEDEN - - 00-50-C2 (hex) Planea Oy - 418000-418FFF (base 16) Planea Oy - Lantinen Pitkakatu 23A - Turku 20100 - FINLAND - - 00-50-C2 (hex) Mecsel Oy - 419000-419FFF (base 16) Mecsel Oy - Soittajantie 1 - Helsinki FI-00420 - FINLAND - - 00-50-C2 (hex) Bluewater Systems Ltd - 41A000-41AFFF (base 16) Bluewater Systems Ltd - Level 17, 119 Armagh Street - Christchurch Canterbury 8001 - NEW ZEALAND - - 00-50-C2 (hex) LogiM GmbH Software und Entwicklung - 41B000-41BFFF (base 16) LogiM GmbH Software und Entwicklung - Mahonienweg 22b - Berlin 12437 - GERMANY - - 00-50-C2 (hex) Infrasafe, Inc. - 41C000-41CFFF (base 16) Infrasafe, Inc. - 12612 Challenger Pkwy - Suite 300 - Orlando FL 32826 - UNITED STATES - - 00-50-C2 (hex) Altronic, Inc. - 41D000-41DFFF (base 16) Altronic, Inc. - 712 Trumbull Ave - Girard OHIO 44420 - UNITED STATES - - 00-50-C2 (hex) Videotek Sistemas Eletronicos Ltda. - 41E000-41EFFF (base 16) Videotek Sistemas Eletronicos Ltda. - Rua Atilio Piffer, 513 - São Paulo SP 02516-000 - BRAZIL - - 00-50-C2 (hex) Avionica, Inc - 41F000-41FFFF (base 16) Avionica, Inc - 9941 W. Jessamine St - Miami FL 33157 - UNITED STATES - - 00-50-C2 (hex) Boundless Technologies - 420000-420FFF (base 16) Boundless Technologies - 100 Marcus Blvd - Hauppauge NY 11788 - UNITED STATES - - 00-50-C2 (hex) EFSYS - 421000-421FFF (base 16) EFSYS - 60, rue de la bolle - Saint-Dié des Vosges Vosges 88100 - FRANCE - - 00-50-C2 (hex) ads-tec GmbH - 422000-422FFF (base 16) ads-tec GmbH - Raiffeisenstraße 14 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-50-C2 (hex) Power-One Inc. - 423000-423FFF (base 16) Power-One Inc. - via san giorgio 642 - Terranuova Bracciolini Arezzo 52028 - ITALY - - 00-50-C2 (hex) Metrolab Technology SA - 424000-424FFF (base 16) Metrolab Technology SA - ch. du Pont-du-Centenaire 110 - Plan-les-Ouates Genève 1228 - SWITZERLAND - - 00-50-C2 (hex) Pinnacle Technology - 425000-425FFF (base 16) Pinnacle Technology - 619 E. 8th street suite D - Lawrence KS 66044 - UNITED STATES - - 00-50-C2 (hex) STOM System - 426000-426FFF (base 16) STOM System - Yangjae-dong 316-9, OSL B/D 5F - Seocho-gu - Seoul 137-876 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Scheidt & Bachmann GmbH - 427000-427FFF (base 16) Scheidt & Bachmann GmbH - Breite Strasse 132 - Moenchengladbach NRW 41238 - GERMANY - - 00-50-C2 (hex) Roxar A/S - 428000-428FFF (base 16) Roxar A/S - Bjellandveien 24. - Box 2248. - Toensberg 3103 - NORWAY - - 00-50-C2 (hex) Matthews Australasia - 429000-429FFF (base 16) Matthews Australasia - 35 Laser Drive - Rowville Victoria 3178 - AUSTRALIA - - 00-50-C2 (hex) DSP DESIGN - 42A000-42AFFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) VLSIP TECHNOLOGIES, INC. - 42B000-42BFFF (base 16) VLSIP TECHNOLOGIES, INC. - 750 PRESIDENTIAL DRIVE - RICHARDSON TEXAS 75081 - UNITED STATES - - 00-50-C2 (hex) Trapeze ITS U.S.A., LLC - 42C000-42CFFF (base 16) Trapeze ITS U.S.A., LLC - 5265 Rockwell Drive NE - Cedar Rapids IA 52402 - UNITED STATES - - 00-50-C2 (hex) Argo-Tech - 42D000-42DFFF (base 16) Argo-Tech - 23555 Euclid Ave. - Cleveland OH 44117 - UNITED STATES - - 00-50-C2 (hex) Oelmann Elektronik GmbH - 42E000-42EFFF (base 16) Oelmann Elektronik GmbH - Allerfeldstr. 17 - Springe Niedersachsen 31832 - GERMANY - - 00-50-C2 (hex) Win4NET - 42F000-42FFFF (base 16) Win4NET - KOLON Digital Tower 1301, 222-7 - Seoul Kuro-dong, Kuro-gu 152-848 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Arcom Digital - 430000-430FFF (base 16) Arcom Digital - PO Box 6729 - Syracuse NY 13217 - UNITED STATES - - 00-50-C2 (hex) Octatron, Inc. - 431000-431FFF (base 16) Octatron, Inc. - 1925 McKinley Ave. - Suite C - La Verne CA 91750 - UNITED STATES - - 00-50-C2 (hex) Topway Industries Ltd. - 432000-432FFF (base 16) Topway Industries Ltd. - Rm 1506, Cheung Fung Ind. Bldg., - 23-39 Pak Tin Par Street, - Tsuen Wan, N.T. - HONG KONG - - 00-50-C2 (hex) Idetech Europe S.A. - 433000-433FFF (base 16) Idetech Europe S.A. - Pedrosa C nº23 (Polígono Pedrosa) - Hospitalet de Llobregat BARCELONA 08908 - SPAIN - - 00-50-C2 (hex) ImperativeNetworks - 434000-434FFF (base 16) ImperativeNetworks - Hatamar 2 - Yokneam 20692 - ISRAEL - - 00-50-C2 (hex) ADATEL TELECOMUNICACIONES S.A. - 435000-435FFF (base 16) ADATEL TELECOMUNICACIONES S.A. - Manuel Tovar, 38 - Madrid 28034 - SPAIN - - 00-50-C2 (hex) Satellite Services BV - 436000-436FFF (base 16) Satellite Services BV - Scheepmakerstraat 40 - Katwijk aan Zee Zuid-holland 2222 AC - NETHERLANDS - - 00-50-C2 (hex) PowerWAN, Inc - 437000-437FFF (base 16) PowerWAN, Inc - 2445 Faber Place - Palo Alto California 94303 - UNITED STATES - - 00-50-C2 (hex) Telecom Protection Technologies Limited - 438000-438FFF (base 16) Telecom Protection Technologies Limited - Unit 1A, Garden Close - Langage Industrial Estate, Plympton - Plymouth Devon PL7 5EU - UNITED KINGDOM - - 00-50-C2 (hex) Peleton Photonic Systems - 439000-439FFF (base 16) Peleton Photonic Systems - 2355 St. Laurent BLVD - Ottawa Ontario K1G 6C3 - CANADA - - 00-50-C2 (hex) ProDesign GmbH - 43A000-43AFFF (base 16) ProDesign GmbH - Hochheimer Str. 47 - Erfurt 99094 - GERMANY - - 00-50-C2 (hex) A3IP - 43B000-43BFFF (base 16) A3IP - Batiment Placel, route de vannes - SAUTRON Pays de la loire 44880 - FRANCE - - 00-50-C2 (hex) Ducommun LaBarge Technologies, Inc - 43C000-43CFFF (base 16) Ducommun LaBarge Technologies, Inc - 700 Braddock Avenue - East Pittsburgh PA 15112 - UNITED STATES - - 00-50-C2 (hex) Ann Arbor Sensor Systems LLC - 43D000-43DFFF (base 16) Ann Arbor Sensor Systems LLC - 7300 Huron River Drive - Suite B - Dexter MI 48130 - UNITED STATES - - 00-50-C2 (hex) Coppercom - 43E000-43EFFF (base 16) Coppercom - 3600 FAU Blvd - Boca Raton Florida 33431 - UNITED STATES - - 00-50-C2 (hex) ARVOO Imaging Products BV - 43F000-43FFFF (base 16) ARVOO Imaging Products BV - Tasveld 13 - Montfoort UT 3417 XS - NETHERLANDS - - 00-50-C2 (hex) Advanced Modular Computers Ltd. - 440000-440FFF (base 16) Advanced Modular Computers Ltd. - Union House, Unit B1, Deseronto Trading Estate - St Mary's Road, - Langley, Slough Berkshire SL3 7EW - UNITED KINGDOM - - 00-50-C2 (hex) Sammi Information Systems Co.,Ltd - 441000-441FFF (base 16) Sammi Information Systems Co.,Ltd - 103-15, Galwor-dong, Yongsan-gu - Seoul 140-807 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Pico Computing, Inc. - 442000-442FFF (base 16) Pico Computing, Inc. - 9747 Businesspark Ave. - 235 - San Diego CA 92131 - UNITED STATES - - 00-50-C2 (hex) Pickering Laboratories - 443000-443FFF (base 16) Pickering Laboratories - 1280 space park way - mountain view california 94943 - UNITED STATES - - 00-50-C2 (hex) Offshore Systems Ltd - 444000-444FFF (base 16) Offshore Systems Ltd - 107 - 930 West 1st Street - North Vancouver B.C. V7P 3N4 - CANADA - - 00-50-C2 (hex) MICRONIC s.r.o. - 445000-445FFF (base 16) MICRONIC s.r.o. - Trebejov 41 - Kysak Kosice okolie 044 81 - SLOVAKIA - - 00-50-C2 (hex) Micro Technic A-S - 446000-446FFF (base 16) Micro Technic A-S - Smedevaenget 5 - Aarup 5560 - DENMARK - - 00-50-C2 (hex) Grupo Epelsa S.L. - 447000-447FFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) Comtech Systems Inc. - 448000-448FFF (base 16) Comtech Systems Inc. - 2900 Titan Row - Suite 142 - Orlando Florida 32809 - UNITED STATES - - 00-50-C2 (hex) BLEILE DATENTECHNIK GmbH - 449000-449FFF (base 16) BLEILE DATENTECHNIK GmbH - AM KREBSBACH 2 - IHRINGEN D-79241 - GERMANY - - 00-50-C2 (hex) ELETTRONICA SANTERNO SPA - 44A000-44AFFF (base 16) ELETTRONICA SANTERNO SPA - S. SELICE, 47 - IMOLA BOLOGNA 40026 - ITALY - - 00-50-C2 (hex) Solace Systems, Inc. - 44B000-44BFFF (base 16) Solace Systems, Inc. - 555 Legget Drive - Tower B, Suite 532 - Kanata Ontario K2K 2X3 - CANADA - - 00-50-C2 (hex) Computime Systems UK Ltd. - 44C000-44CFFF (base 16) Computime Systems UK Ltd. - 4 Woodside Mews - Clayton Wood Close - Leeds West Yorkshire LS16 6QE - UNITED KINGDOM - - 00-50-C2 (hex) Electro-Matic Products, Inc. - 44D000-44DFFF (base 16) Electro-Matic Products, Inc. - 23409 Industrial Park Ct. - Farmington Hills MI 48335 - UNITED STATES - - 00-50-C2 (hex) QQ Technology,Inc - 44E000-44EFFF (base 16) QQ Technology,Inc - 8F TowerB,wantong new world plaza,No.2 Fuwai street - Xi Cheng District - BeiJing 100037 - CHINA - - 00-50-C2 (hex) kippdata GmbH - 44F000-44FFFF (base 16) kippdata GmbH - Bornheimer Str. 33a - Bonn NRW D-53111 - GERMANY - - 00-50-C2 (hex) Enconair Ecological Chambers Inc. - 450000-450FFF (base 16) Enconair Ecological Chambers Inc. - 474 Jarvis Avenue - Winnipeg Manitoba R2W 3A8 - CANADA - - 00-50-C2 (hex) HAMEG GmbH - 451000-451FFF (base 16) HAMEG GmbH - Industriestr. 6 - Mainhausen 63533 - GERMANY - - 00-50-C2 (hex) SCAME SISTEMI s.r.l. - 452000-452FFF (base 16) SCAME SISTEMI s.r.l. - Via Lombardia N°5 - ARLUNO MI 20010 - ITALY - - 00-50-C2 (hex) Erhardt + Leimer GmbH - 453000-453FFF (base 16) Erhardt + Leimer GmbH - Albert-Leimer-Platz 1 - Stadtbergen Bavaria 86391 - GERMANY - - 00-50-C2 (hex) Brivo Systems, LLC - 454000-454FFF (base 16) Brivo Systems, LLC - 4330 East-West Highway - Suite 250 - Bethesda MD 20814 - UNITED STATES - - 00-50-C2 (hex) Aircell - 455000-455FFF (base 16) Aircell - 1172 Century Drive - Building B, Suite 280 - Louisville Colorado 80027 - UNITED STATES - - 00-50-C2 (hex) DRDC Valcartier - 456000-456FFF (base 16) DRDC Valcartier - 2459 blvd. Pie XI North - Bldg 53 - Val-Belair Québec G3J 1X5 - CANADA - - 00-50-C2 (hex) Danbridge - 457000-457FFF (base 16) Danbridge - Hirsemarken 5 - Farum DK-3520 - DENMARK - - 00-50-C2 (hex) HRZ data GmbH - 458000-458FFF (base 16) HRZ data GmbH - Oberkrone 20e - Witten NRW 58455 - GERMANY - - 00-50-C2 (hex) PHYTEC Messtechnik GmbH - 459000-459FFF (base 16) PHYTEC Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Funkwerk plettac electronic GmbH - 45A000-45AFFF (base 16) Funkwerk plettac electronic GmbH - Wuerzburger Strasse 150 - Fuerth Bavaria 90766 - GERMANY - - 00-50-C2 (hex) Matra Electronique - 45B000-45BFFF (base 16) Matra Electronique - 6, rue Ferdinand Meunier - La Croix St Ouen Oise 60610 - FRANCE - - 00-50-C2 (hex) Deister Electronic GmbH - 45C000-45CFFF (base 16) Deister Electronic GmbH - Hermann-Bahlsen-Str. 11 - Barsinghausen Niedersachsen 30890 - GERMANY - - 00-50-C2 (hex) Digital Engineering, Inc. - 45D000-45DFFF (base 16) Digital Engineering, Inc. - 740 Harold Crescent - Thunder Bay Ontario P7C 5H7 - CANADA - - 00-50-C2 (hex) Halliburton - Sperry Drilling Service - 45E000-45EFFF (base 16) Halliburton - Sperry Drilling Service - 3000 N. Sam Houston Pkwy E. - Houston TX 77032 - UNITED STATES - - 00-50-C2 (hex) T2C Marketing AB - 45F000-45FFFF (base 16) T2C Marketing AB - Sjovagen 1 - c/o Minom AB - Upplands Vasby Stockholm 194 67 - SWEDEN - - 00-50-C2 (hex) Vitelnet - 460000-460FFF (base 16) Vitelnet - 221 Elizabeth St - Utica NY 13501 - UNITED STATES - - 00-50-C2 (hex) TATTILE SRL - 461000-461FFF (base 16) TATTILE SRL - VIA TRENTO 127/129 - CAPRIANO DEL COLLE - BRESCIA 25020 - ITALY - - 00-50-C2 (hex) CT Company - 462000-462FFF (base 16) CT Company - Nizhni Krasnoselsky st., 35. - Moscow 140070 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Codem Systems, Inc. - 463000-463FFF (base 16) Codem Systems, Inc. - 7 Executive Park Drive - Merrimack NH 03054 - UNITED STATES - - 00-50-C2 (hex) XYTAC system technologies - 464000-464FFF (base 16) XYTAC system technologies - 3755-1-2-212 Totsukacho - Yokohama Kanagawa 244-0003 - JAPAN - - 00-50-C2 (hex) PDTS GmbH - 465000-465FFF (base 16) PDTS GmbH - Moeringgasse 20 - Vienna 1150 - AUSTRIA - - 00-50-C2 (hex) LONAP Limited - 466000-466FFF (base 16) LONAP Limited - 5 Fleet Place - London EC4M 7RD - UNITED KINGDOM - - 00-50-C2 (hex) United Western Technologies - 467000-467FFF (base 16) United Western Technologies - 330 West Clark Street - Pasco Washington 99301 - UNITED STATES - - 00-50-C2 (hex) Network I/O - 468000-468FFF (base 16) Network I/O - 6703 Rain Creek Parkway - Austin TX 78759 - UNITED STATES - - 00-50-C2 (hex) BiPOM Electronics, Inc. - 469000-469FFF (base 16) BiPOM Electronics, Inc. - 16301 Blue Ridge Road - Missouri City TEXAS 77489 - UNITED STATES - - 00-50-C2 (hex) ISE GmbH - 46A000-46AFFF (base 16) ISE GmbH - Kaiserstrasse 14 - Oldenburg Niedersachsen 26122 - GERMANY - - 00-50-C2 (hex) EASYTECH GmbH - 46B000-46BFFF (base 16) EASYTECH GmbH - Sommerauerstr.18 - St.Georgen BW 78112 - GERMANY - - 00-50-C2 (hex) CAMCO GmbH - 46C000-46CFFF (base 16) CAMCO GmbH - Fischpicke 5 - Wenden NRW 57482 - GERMANY - - 00-50-C2 (hex) Paul Scherrer Institut (PSI) - 46D000-46DFFF (base 16) Paul Scherrer Institut (PSI) - WHGA/U130 - Villigen-PSI Aargau CH-5232 - SWITZERLAND - - 00-50-C2 (hex) Avenir Technologies Inc. - 46E000-46EFFF (base 16) Avenir Technologies Inc. - 20 Riverview Drive - Norwalk CT 06850 - UNITED STATES - - 00-50-C2 (hex) Neuroware - 46F000-46FFFF (base 16) Neuroware - 6726 Golden Hills Way - Mississauga Ontario L5W1P1 - CANADA - - 00-50-C2 (hex) Cybectec inc. - 470000-470FFF (base 16) Cybectec inc. - 730 Commerciale St. - Suite 200 - Saint-Jean-Chrysostome Quebec G6Z 2C5 - CANADA - - 00-50-C2 (hex) Pixtree Technologies, inc. - 471000-471FFF (base 16) Pixtree Technologies, inc. - ShinChon-Dong SeoDaeMun-Gu - 250 YERC, YeonSei Univ., 134 - Seoul 120-749 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) KOP Ltd - 472000-472FFF (base 16) KOP Ltd - Howe Moss Ave - Kirkhill - Aberdeen Scotland AB21 0NA - UNITED KINGDOM - - 00-50-C2 (hex) Sensus Metering Systems Israel - 473000-473FFF (base 16) Sensus Metering Systems Israel - 16 Hamelacha st - Rosh Haayin 48091 - ISRAEL - - 00-50-C2 (hex) Venue 1, Inc. - 474000-474FFF (base 16) Venue 1, Inc. - 5000 SW 52nd Street - Suite 501 - Davie Florida 33314 - UNITED STATES - - 00-50-C2 (hex) ISEPOS GmbH - 475000-475FFF (base 16) ISEPOS GmbH - Untere Straße 33 - Tuebingen Baden-Württemberg 72070 - GERMANY - - 00-50-C2 (hex) Ascon S.p.a. - 476000-476FFF (base 16) Ascon S.p.a. - Via Falzarego 9/11 - Bollate Milano 20021 - ITALY - - 00-50-C2 (hex) SEV Tidsystem AB - 477000-477FFF (base 16) SEV Tidsystem AB - Box 121 - Västerhaninge Stockholm 137 22 - SWEDEN - - 00-50-C2 (hex) Metafix Inc. - 478000-478FFF (base 16) Metafix Inc. - 1925, 46 th. Avenue - Lachine Quebec H8T 2P1 - CANADA - - 00-50-C2 (hex) Unlimited Bandwidth LLC - 479000-479FFF (base 16) Unlimited Bandwidth LLC - 1320 W. Northwest Highway - Palatine Illinois 60067 - UNITED STATES - - 00-50-C2 (hex) Efficient Channel Coding - 47A000-47AFFF (base 16) Efficient Channel Coding - 600 Safeguard Plaza - Suite 100 - Brooklyn Heights Ohio 44131 - UNITED STATES - - 00-50-C2 (hex) Pitney Bowes, Inc - 47B000-47BFFF (base 16) Pitney Bowes, Inc - 35 Waterview Drive - MSC 26-21 - Shelton CT 06484 - UNITED STATES - - 00-50-C2 (hex) AUCONET GmbH - 47C000-47CFFF (base 16) AUCONET GmbH - Rudower Chaussee 31 - Berlin 12489 - GERMANY - - 00-50-C2 (hex) WIT Inc - 47D000-47DFFF (base 16) WIT Inc - 420 E Lana Ct - Draper UT 84020 - UNITED STATES - - 00-50-C2 (hex) Energie Umwelt Systemtechnik GmbH - 47E000-47EFFF (base 16) Energie Umwelt Systemtechnik GmbH - Friedrich-Barnewitz-Str. 3a - Rostock 18119 - GERMANY - - 00-50-C2 (hex) BRIT Inc. - 47F000-47FFFF (base 16) BRIT Inc. - 703, Aves Bld,1452 Dunsan-Dong - Seo-ku Daejeon 302-120 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) SELKOM GmbH - 480000-480FFF (base 16) SELKOM GmbH - Jahnstraße 4 - Muggensturm Baden-Württemberg 76461 - GERMANY - - 00-50-C2 (hex) Computer Sciences Corp - 481000-481FFF (base 16) Computer Sciences Corp - 2315 Meredith Lane, Ste. A - Santa Maria CA 93455-1145 - UNITED STATES - - 00-50-C2 (hex) PRIAMUS SYSTEM TECHNOLOGIES AG - 482000-482FFF (base 16) PRIAMUS SYSTEM TECHNOLOGIES AG - Rheinweg 4 - Schaffhausen 8200 - SWITZERLAND - - 00-50-C2 (hex) SES - 483000-483FFF (base 16) SES - 35-39 avenue du Danemark - BP 7267 - Tours Cedex 2 37072 - FRANCE - - 00-50-C2 (hex) Kooltech LLC - 484000-484FFF (base 16) Kooltech LLC - 336 Atlantic Avenue - Suite 303 - East Rockaway NY 11518 - UNITED STATES - - 00-50-C2 (hex) PHYTEC Messtechnik GmbH - 485000-485FFF (base 16) PHYTEC Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Safegate International AB - 486000-486FFF (base 16) Safegate International AB - Djurhagegatan 19 - Malmö 21376 - SWEDEN - - 00-50-C2 (hex) Eridon Corporation - 487000-487FFF (base 16) Eridon Corporation - 901 Twelve Oaks Center Drive - Suite 934 - Wayzata MN 55391 - UNITED STATES - - 00-50-C2 (hex) DA SISTEMI SPA - 488000-488FFF (base 16) DA SISTEMI SPA - Via Cadorna, 73 - Vimodrone Milano 20090 - ITALY - - 00-50-C2 (hex) EREE Electronique - 489000-489FFF (base 16) EREE Electronique - 6 avenu Dr Schweitzer - BP 95 - MEYZIEU 69882 - FRANCE - - 00-50-C2 (hex) Mobile Matrix, Inc. - 48A000-48AFFF (base 16) Mobile Matrix, Inc. - 125 Half Mile Road - Suite 201A - Red Bank New Jersey 07701 - UNITED STATES - - 00-50-C2 (hex) ads-tec GmbH - 48B000-48BFFF (base 16) ads-tec GmbH - Raiffeisentraße 14 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-50-C2 (hex) UNITON AG - 48C000-48CFFF (base 16) UNITON AG - Pumpwerkstrasse 18 - Regensdorf ZH 8105 - SWITZERLAND - - 00-50-C2 (hex) Metron Sp. z o.o. - 48D000-48DFFF (base 16) Metron Sp. z o.o. - ul. Targowa 12/22 - Torun Kuj-pom 87-100 - POLAND - - 00-50-C2 (hex) Teledyne Tekmar - 48E000-48EFFF (base 16) Teledyne Tekmar - 4736 Socialville Foster Rd - Mason Ohio 45040 - UNITED STATES - - 00-50-C2 (hex) DENGYOSHA co.,LTD. - 48F000-48FFFF (base 16) DENGYOSHA co.,LTD. - 7-17, Midorigaoka 3 Tyome - Hamura-shi Tokyo 205-0003 - JAPAN - - 00-50-C2 (hex) Cloanto Corporation - 490000-490FFF (base 16) Cloanto Corporation - P.O. Box 27740 - Las Vegas NV 89126-7740 - UNITED STATES - - 00-50-C2 (hex) Fr. Sauter AG - 491000-491FFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS CH4016 - SWITZERLAND - - 00-50-C2 (hex) TRAFSYS AS - 492000-492FFF (base 16) TRAFSYS AS - Fabrikkgaten 5 - Bergen Hordaland 5059 - NORWAY - - 00-50-C2 (hex) Artis GmbH - 493000-493FFF (base 16) Artis GmbH - Sellhorner Weg 28-30 - Bispingen-Behringen Niedersachsen 29646 - GERMANY - - 00-50-C2 (hex) Ultimate Technology, Inc. - 494000-494FFF (base 16) Ultimate Technology, Inc. - 30 Waverly St. - Taunton MA 02780-1460 - UNITED STATES - - 00-50-C2 (hex) VAZA Elektronik AB - 495000-495FFF (base 16) VAZA Elektronik AB - Furuheds vagen 1 - Kalix Norrbotten 952 31 - SWEDEN - - 00-50-C2 (hex) Acutelogic Corporation - 496000-496FFF (base 16) Acutelogic Corporation - 3-7-1 - Kanda-ogawamachi - Chiyoda-ku Tokyo 101-0052 - JAPAN - - 00-50-C2 (hex) Advanced Driver Information Technology GmbH - 497000-497FFF (base 16) Advanced Driver Information Technology GmbH - Robert Bosch Strasse 200 - Hildesheim . 31139 - GERMANY - - 00-50-C2 (hex) Quartet Technology, Inc. - 498000-498FFF (base 16) Quartet Technology, Inc. - 1934 Lakeview Avenue - Dracut MA 01826 - UNITED STATES - - 00-50-C2 (hex) Trellia Networks - 499000-499FFF (base 16) Trellia Networks - 774 Decarie - Montreal Quebec H4L 3L5 - CANADA - - 00-50-C2 (hex) TelASIC Communications, Inc. - 49A000-49AFFF (base 16) TelASIC Communications, Inc. - 1940 E Mariposa Avenue - Suite 100 - El Segundo CA 90245 - UNITED STATES - - 00-50-C2 (hex) vg controls, inc - 49B000-49BFFF (base 16) vg controls, inc - 11 butternut drive - vernon new jersey 07462 - UNITED STATES - - 00-50-C2 (hex) Envisacor Technologies Inc. - 49C000-49CFFF (base 16) Envisacor Technologies Inc. - 237 Romina Drive - Suite 201 - Concord Ontario L4K 4V3 - CANADA - - 00-50-C2 (hex) Critical Link - 49D000-49DFFF (base 16) Critical Link - 6712 Brooklawn Parkway - Syracuse NY 13211 - UNITED STATES - - 00-50-C2 (hex) Armorlink CO .Ltd - 49E000-49EFFF (base 16) Armorlink CO .Ltd - No. 515 of xinzhuang industry park shenfu road - Shanghai province SHANGHAI 201108 - CHINA - - 00-50-C2 (hex) GCS, Inc - 49F000-49FFFF (base 16) GCS, Inc - 2665 Pine Grove Rd. - Suite 400 - Cumming Georgia 30041 - UNITED STATES - - 00-50-C2 (hex) Advanced technologies & Engineering (pty) Ltd - 4A0000-4A0FFF (base 16) Advanced technologies & Engineering (pty) Ltd - 998 16 th Road - Midrand Gauteng 1685 - SOUTH AFRICA - - 00-50-C2 (hex) Pigeon Point Systems LLC - 4A1000-4A1FFF (base 16) Pigeon Point Systems LLC - 2191 S. El Camino Real - Suite 209 - Oceanside CA 95054 - UNITED STATES - - 00-50-C2 (hex) SPECS GmbH - 4A2000-4A2FFF (base 16) SPECS GmbH - Voltastrasse 5 - Berlin 13355 - GERMANY - - 00-50-C2 (hex) Protium Technologies, Inc. - 4A3000-4A3FFF (base 16) Protium Technologies, Inc. - 10 Bearfoot Rd. - Northborough MA 01532 - UNITED STATES - - 00-50-C2 (hex) IEEE P1609 WG - 4A4000-4A4FFF (base 16) IEEE P1609 WG - 3800 N Fairfax Drive #207 - Arlington VA 22203-1759 - UNITED STATES - - 00-50-C2 (hex) Teledyne Monitor Labs - 4A5000-4A5FFF (base 16) Teledyne Monitor Labs - 5310 N. Pioneer Road - Gibsonia PA 15044 - UNITED STATES - - 00-50-C2 (hex) BUYANG ELECTRONICS INDUSTRIAL CO., LTD. - 4A6000-4A6FFF (base 16) BUYANG ELECTRONICS INDUSTRIAL CO., LTD. - ORYU-DONG - SEO-KU - INCHEON 434-140 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) iseg Spezialelektronik GmbH - 4A7000-4A7FFF (base 16) iseg Spezialelektronik GmbH - Bautzner Landstr. 23 - Radeberg OT Rossendorf 01454 - GERMANY - - 00-50-C2 (hex) CYJAYA Korea - 4A8000-4A8FFF (base 16) CYJAYA Korea - 1209, Manhattan21 Livingtel, Yoido-dong - Youngdeungpo-gu - Seoul 150-870 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Faber Electronics BV - 4A9000-4A9FFF (base 16) Faber Electronics BV - Th. Dobbeweg 1 - Velp Gelderland 6883 GN Velp - NETHERLANDS - - 00-50-C2 (hex) HEINEN ELEKTRONIK GmbH - 4AA000-4AAFFF (base 16) HEINEN ELEKTRONIK GmbH - Hunsrückstraße 7 - HAAN NRW 42781 - GERMANY - - 00-50-C2 (hex) JVF Communications Ltd - 4AB000-4ABFFF (base 16) JVF Communications Ltd - 30 Loughborough Road - Mountsorrel Leics LE12 7AT - UNITED KINGDOM - - 00-50-C2 (hex) Doramu Co.,Ltd. - 4AC000-4ACFFF (base 16) Doramu Co.,Ltd. - 4F Oyama Bldg. - 2-25-15 Higashiueno, - Taito-ku, Tokyo 110-0015 - JAPAN - - 00-50-C2 (hex) OpenPeak, Inc. - 4AD000-4ADFFF (base 16) OpenPeak, Inc. - 5355 Town Center Rd - Suite 301 - Boca Raton FL 33486 - UNITED STATES - - 00-50-C2 (hex) ads-tec GmbH - 4AE000-4AEFFF (base 16) ads-tec GmbH - Raiffeisenstraße 14 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-50-C2 (hex) Orbis Oy - 4AF000-4AFFFF (base 16) Orbis Oy - Taivaltie 5 - Vantaa 01610 - FINLAND - - 00-50-C2 (hex) Esmart Distribution Pte Ltd - 4B0000-4B0FFF (base 16) Esmart Distribution Pte Ltd - 17 Kallang Junction #04-03 - Esmart Center, - 339274 - SINGAPORE - - 00-50-C2 (hex) Nsfocus Information Technology Co.,Ltd - 4B1000-4B1FFF (base 16) Nsfocus Information Technology Co.,Ltd - 5F Either Building, No 4 Beiwa Rd - Haidian DIstrict - Beijing 100089 - CHINA - - 00-50-C2 (hex) TESLA, a.s. - 4B2000-4B2FFF (base 16) TESLA, a.s. - Podebradska 56/186 - Praha 9 180 66 - CZECH REPUBLIC - - 00-50-C2 (hex) ANSA Corporation - 4B3000-4B3FFF (base 16) ANSA Corporation - 17F, No. 738, Chung Cheng Road - Chung Ho City Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Matrix Audio Designs - 4B4000-4B4FFF (base 16) Matrix Audio Designs - 20 Hamilton Rd - Barrie Ontario L4N 8Y5 - CANADA - - 00-50-C2 (hex) Valley Tecnologia - 4B5000-4B5FFF (base 16) Valley Tecnologia - R. Manoel Soares Sebastiao, 410 - Jd. Maraba - São Paulo SP 04775-160 - BRAZIL - - 00-50-C2 (hex) General Resources Co., LTD. - 4B6000-4B6FFF (base 16) General Resources Co., LTD. - B1,No. 15,Lane 174,Hsin-Ming Rd.,Nei Hu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) GFI Chrono Time - 4B7000-4B7FFF (base 16) GFI Chrono Time - 121 rue des Guillees - CHAURAY 79180 - FRANCE - - 00-50-C2 (hex) Shenzhen Hongdian Technologies.,Ltd - 4B8000-4B8FFF (base 16) Shenzhen Hongdian Technologies.,Ltd - 15H,Jinsong Building,Chegongmiao - Shenzhen Guangdong 518040 - CHINA - - 00-50-C2 (hex) Rose Technologies - 4B9000-4B9FFF (base 16) Rose Technologies - 13400 NE 20th Street, #32 - Suite 218 - Bellevue WA 98005 - UNITED STATES - - 00-50-C2 (hex) Mistletoe Technologies - 4BA000-4BAFFF (base 16) Mistletoe Technologies - 20450 Stevens Creek Blvd. Suite 200 - Cupertino CA 95014 - UNITED STATES - - 00-50-C2 (hex) Protonic Holland - 4BB000-4BBFFF (base 16) Protonic Holland - Factorij 36 - Zwaag NH 1689 AL - NETHERLANDS - - 00-50-C2 (hex) Saia Burgess Controls AG - 4BC000-4BCFFF (base 16) Saia Burgess Controls AG - Bahnhofstrasse 18 - Murten Freiburg 3280 - SWITZERLAND - - 00-50-C2 (hex) Argon ST - 4BD000-4BDFFF (base 16) Argon ST - 8419 Terminal Road - Newington VA 22122 - UNITED STATES - - 00-50-C2 (hex) Digital Dynamics, Inc. - 4BE000-4BEFFF (base 16) Digital Dynamics, Inc. - 5 Victor Square - Scotts Valley CA 95066 - UNITED STATES - - 00-50-C2 (hex) Westinghouse Rail Systems Ltd - 4BF000-4BFFFF (base 16) Westinghouse Rail Systems Ltd - Pew Hill - Chippenham Wiltshire SN151JD - UNITED KINGDOM - - 00-50-C2 (hex) Bio-logic Systems Corp - 4C0000-4C0FFF (base 16) Bio-logic Systems Corp - One Bio-logic Plaza - Mundelein IL 60060 - UNITED STATES - - 00-50-C2 (hex) Movaz Networks, Inc. - 4C1000-4C1FFF (base 16) Movaz Networks, Inc. - One Technology Parkway South - Norcross GA 30092 - UNITED STATES - - 00-50-C2 (hex) Elbit Systems - 4C2000-4C2FFF (base 16) Elbit Systems - p.o.b. 539 - Haifa Moon 36925 - ISRAEL - - 00-50-C2 (hex) Quantum3D, Inc. - 4C3000-4C3FFF (base 16) Quantum3D, Inc. - 6330 San Ignacio Avenue - San Jose CA 95051 - UNITED STATES - - 00-50-C2 (hex) Black Diamond Video, Inc. - 4C4000-4C4FFF (base 16) Black Diamond Video, Inc. - 1151 Harbor Bay Parkway Suite 101 - Alameda CA 94502 - UNITED STATES - - 00-50-C2 (hex) eXray Broadband Inc. - 4C5000-4C5FFF (base 16) eXray Broadband Inc. - 31 Broadway Avenue - Ottawa Ontario K1S 2V4 - CANADA - - 00-50-C2 (hex) Rubin Ltd. - 4C6000-4C6FFF (base 16) Rubin Ltd. - Egressy St. 17. - Budapest Budapest H-1149 - HUNGARY - - 00-50-C2 (hex) Transbit Sp.z o.o. - 4C7000-4C7FFF (base 16) Transbit Sp.z o.o. - ul. Przyczolkowa 109A - Warsaw Mazowieckie 02-968 - POLAND - - 00-50-C2 (hex) Neets - 4C8000-4C8FFF (base 16) Neets - Langballe 4 - Horsens 8700 - DENMARK - - 00-50-C2 (hex) Scirocco AB - 4C9000-4C9FFF (base 16) Scirocco AB - Electrum 217 - Kista SE-164 40 - SWEDEN - - 00-50-C2 (hex) Yarg Biometrics Limited - 4CA000-4CAFFF (base 16) Yarg Biometrics Limited - 141 St James Road - Glasgow Scotland G4 0LT - UNITED KINGDOM - - 00-50-C2 (hex) Verint Systems Ltd - 4CB000-4CBFFF (base 16) Verint Systems Ltd - 23 Habarzel St. - Tel Aviv 69710 - ISRAEL - - 00-50-C2 (hex) ImpediMed Limited - 4CC000-4CCFFF (base 16) ImpediMed Limited - 4B/2404 Logan Road - Eight Mile Plains Queensland 4113 - AUSTRALIA - - 00-50-C2 (hex) Bixi Systems AG - 4CD000-4CDFFF (base 16) Bixi Systems AG - Grammetstrasse 14 - Liestal BL 4410 - SWITZERLAND - - 00-50-C2 (hex) Open Date Equipment Limited - 4CE000-4CEFFF (base 16) Open Date Equipment Limited - Units 7 & 8 Furmston Court - Icknield Way - Letchworth Garden City Hertfordshire SG6 1UJ - UNITED KINGDOM - - 00-50-C2 (hex) Ziehl-Abegg AG - 4CF000-4CFFFF (base 16) Ziehl-Abegg AG - Heinz-Ziehl-Straße - Kuenzelsau Baden-Württemberg 74653 - GERMANY - - 00-50-C2 (hex) RCS Energy Management Ltd - 4D0000-4D0FFF (base 16) RCS Energy Management Ltd - RMS House - Kennetside - Newbury Berkshire RG14 5PX - UNITED KINGDOM - - 00-50-C2 (hex) SLICAN sp. z o.o. - 4D1000-4D1FFF (base 16) SLICAN sp. z o.o. - ul.M.Konopnickiej 18 - Bydgoszcz Kujawsko-Pomorskie 85-124 - POLAND - - 00-50-C2 (hex) Twoway CATV SERVICE INC. - 4D2000-4D2FFF (base 16) Twoway CATV SERVICE INC. - 41 Wu Kung 6 Rd., Wu Ku Industrial Park, - Taipei Hsien,248 - TPI Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) ELPROC sp. z o.o. - 4D3000-4D3FFF (base 16) ELPROC sp. z o.o. - Skwer Ks. Krd. St. WyszyÅ„skiego 2/62 - Warsaw Mazowieckie 01-015 - POLAND - - 00-50-C2 (hex) Herholdt Controls srl - 4D4000-4D4FFF (base 16) Herholdt Controls srl - Via Mestre 13 - Milan MI 20132 - ITALY - - 00-50-C2 (hex) SEBA Design Pty Ltd - 4D5000-4D5FFF (base 16) SEBA Design Pty Ltd - 164 Princes Highway - Dandenong VIC 3175 - AUSTRALIA - - 00-50-C2 (hex) Ingenieurbüro Schober - 4D6000-4D6FFF (base 16) Ingenieurbüro Schober - Schloßgarten 16 - Cadolzburg Bayern 90556 - GERMANY - - 00-50-C2 (hex) Delta Tau Data Systems, Inc. - 4D7000-4D7FFF (base 16) Delta Tau Data Systems, Inc. - 21314 Lassen St - Chatsworth CA 91311 - UNITED STATES - - 00-50-C2 (hex) Avantry Ltd. - 4D8000-4D8FFF (base 16) Avantry Ltd. - New Industrial Park, Bldg 7A - Yokneam Israel 20692 - ISRAEL - - 00-50-C2 (hex) GE Security Kampro - 4D9000-4D9FFF (base 16) GE Security Kampro - 2F, No.8,Lane 97,Wugong Rd.,Wu-Ku Ind. Park - Hsin-Chuang City Taipei County 248 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) MEDIORNET GmbH - 4DA000-4DAFFF (base 16) MEDIORNET GmbH - Hietzinger Kai 67 - Vienna 1130 - AUSTRIA - - 00-50-C2 (hex) Alfing Montagetechnik GmbH - 4DB000-4DBFFF (base 16) Alfing Montagetechnik GmbH - Auguste-Kessler-Straße 20 - Aalen Baden-Württemberg 73433 - GERMANY - - 00-50-C2 (hex) Ace Electronics, Inc. - 4DC000-4DCFFF (base 16) Ace Electronics, Inc. - 27574 Commerce ctr. dr. - Temecula CA 92590 - UNITED STATES - - 00-50-C2 (hex) Truteq Wireless (PTY) Ltd. - 4DD000-4DDFFF (base 16) Truteq Wireless (PTY) Ltd. - Unit 6, Falcon Village Office Park - 149 Suid Street, Lyttelton - Centurion Gauteng 0157 - SOUTH AFRICA - - 00-50-C2 (hex) General Dynamics C4 Systems - 4DE000-4DEFFF (base 16) General Dynamics C4 Systems - 8220 E. Roosevelt St. - R1122 - Scottsdale Arizona 85257 - UNITED STATES - - 00-50-C2 (hex) Thermo Electron - 4DF000-4DFFFF (base 16) Thermo Electron - 9303 W. Sam Houston Parkway South - Houston TX 77099 - UNITED STATES - - 00-50-C2 (hex) Telematrix - 4E0000-4E0FFF (base 16) Telematrix - 2948 Woodside Terrace - Fremont Ca. 94539 - UNITED STATES - - 00-50-C2 (hex) SS Telecoms CC - 4E1000-4E1FFF (base 16) SS Telecoms CC - 23 Botha Avenue - Lyttelton Gauteng 0157 - SOUTH AFRICA - - 00-50-C2 (hex) Applied Research Laboratories: UT - 4E2000-4E2FFF (base 16) Applied Research Laboratories: UT - 10000 Burnet Rd. - Austin TX 78758 - UNITED STATES - - 00-50-C2 (hex) Romteck Pty Ltd - 4E3000-4E3FFF (base 16) Romteck Pty Ltd - 37 Collingwood Street, Osborne Park - Osborne Park Perth 6017 - AUSTRALIA - - 00-50-C2 (hex) Embigence GmbH - 4E4000-4E4FFF (base 16) Embigence GmbH - Goethestrasse 52 - Ladbergen NRW 49549 - GERMANY - - 00-50-C2 (hex) Sedo Systems Ltd - 4E5000-4E5FFF (base 16) Sedo Systems Ltd - 19 Hertford Road - Stevenage HERTS SG2 8RS - UNITED KINGDOM - - 00-50-C2 (hex) Photonic Bridges Inc. - 4E6000-4E6FFF (base 16) Photonic Bridges Inc. - 405 Fawns Run - Morganville New Jersey 07751 - UNITED STATES - - 00-50-C2 (hex) Computerized Elevator Contol - 4E7000-4E7FFF (base 16) Computerized Elevator Contol - 24 Empire Blvd - Moonachie New Jersey 07074 - UNITED STATES - - 00-50-C2 (hex) SATEL sp. z o.o. - 4E8000-4E8FFF (base 16) SATEL sp. z o.o. - Schuberta 79 - GdaÅ„sk pomorskie 80-172 - POLAND - - 00-50-C2 (hex) Seachange international - 4E9000-4E9FFF (base 16) Seachange international - 32 Mill st. - Greenville NH 03048 - UNITED STATES - - 00-50-C2 (hex) PMC - 4EA000-4EAFFF (base 16) PMC - 56, Avenue Raspail - Saint Maur val de marne 94100 - FRANCE - - 00-50-C2 (hex) Mandozzi Elettronica SA - 4EB000-4EBFFF (base 16) Mandozzi Elettronica SA - Via Volta 2 - Ponte Capriasca 6946 - SWITZERLAND - - 00-50-C2 (hex) Thales Defence and Security Systems GmbH - 4EC000-4ECFFF (base 16) Thales Defence and Security Systems GmbH - Edisonstr. 3 - 24145 Keil - GERMANY - - 00-50-C2 (hex) Lab X Technologies, LLC - 4ED000-4EDFFF (base 16) Lab X Technologies, LLC - 176 Anderson Avenue - Suite 302 - Rochester New York 14607 - UNITED STATES - - 00-50-C2 (hex) Beijing Corelogic Communication Co., Ltd. - 4EE000-4EEFFF (base 16) Beijing Corelogic Communication Co., Ltd. - F-5,Huayuelong Mansion, - No.3 Jingyuan Road, Shijingshan District, - Beijing 100043 - CHINA - - 00-50-C2 (hex) Creative Retail Entertainment - 4EF000-4EFFFF (base 16) Creative Retail Entertainment - Unit 2 - Pincents Kiln - Calcot Reading RG31 7SD - UNITED KINGDOM - - 00-50-C2 (hex) MedAvant Healthcare - 4F0000-4F0FFF (base 16) MedAvant Healthcare - 2533 Centennial Blvd - Suite B - Jeffersonville IN 47150 - UNITED STATES - - 00-50-C2 (hex) Packet Island Inc. - 4F1000-4F1FFF (base 16) Packet Island Inc. - 2332B Walsh Ave - Santa Clara California 95051 - UNITED STATES - - 00-50-C2 (hex) Tantronic AG - 4F2000-4F2FFF (base 16) Tantronic AG - Allmendweg 5 - Zufikon AG 5621 - SWITZERLAND - - 00-50-C2 (hex) Autronica Fire & Security - 4F3000-4F3FFF (base 16) Autronica Fire & Security - Haakon VII's gate 4 - Trondheim 7483 - NORWAY - - 00-50-C2 (hex) O2RUN - 4F4000-4F4FFF (base 16) O2RUN - 8F/Hagye Techno Town.,250-3,Hagye-dong,Nowon-gu - SEOUL 139-727 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Monroe Electronics, Inc. - 4F5000-4F5FFF (base 16) Monroe Electronics, Inc. - 100 Housel Avenue - Lyndonville NY 14098 - UNITED STATES - - 00-50-C2 (hex) REAL D - 4F6000-4F6FFF (base 16) REAL D - 100 N. CRESCENT DR. #120 - BEVERLY HILLS CA 90210 - UNITED STATES - - 00-50-C2 (hex) WaveIP Ltd. - 4F7000-4F7FFF (base 16) WaveIP Ltd. - Teradion Industrial Park - Misgav 20179 - ISRAEL - - 00-50-C2 (hex) Prodco International Inc. - 4F8000-4F8FFF (base 16) Prodco International Inc. - 4529 De Castille - Montreal Quebec H1H1Y3 - CANADA - - 00-50-C2 (hex) RTDS Technologies Inc. - 4F9000-4F9FFF (base 16) RTDS Technologies Inc. - 100-150 Innovation Drive - Winnipeg Manitoba R3T 2E1 - CANADA - - 00-50-C2 (hex) Cambridge Technology, Inc. - 4FA000-4FAFFF (base 16) Cambridge Technology, Inc. - 25 Hartwell Ave - Lexington MA 02421-3102 - UNITED STATES - - 00-50-C2 (hex) BES Technology Group - 4FB000-4FBFFF (base 16) BES Technology Group - 3080 Olcott str ste 205a - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) Hwayoung RF Solution Inc - 4FC000-4FCFFF (base 16) Hwayoung RF Solution Inc - 152-050 514, Woolim e-BIZ Center, 170-5 - Guro-Dong, Guro-Gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Network Automation mxc AB - 4FD000-4FDFFF (base 16) Network Automation mxc AB - P.O Box 7294 - Stockholm 103 90 - SWEDEN - - 00-50-C2 (hex) GEM ELETTRONICA Srl - 4FE000-4FEFFF (base 16) GEM ELETTRONICA Srl - Via A. Vespucci, 9 - San Benedetto del Tronto AP 63074 - ITALY - - 00-50-C2 (hex) Dakty GmbH - 4FF000-4FFFFF (base 16) Dakty GmbH - Campusallee 9927 - Hoppstaedten-Weiersbach D-55768 - GERMANY - - 00-50-C2 (hex) Orenco Systems, Inc. - 500000-500FFF (base 16) Orenco Systems, Inc. - 814 Airway Ave. - Sutherlin OR 97479 - UNITED STATES - - 00-50-C2 (hex) IBEX UK Limited - 501000-501FFF (base 16) IBEX UK Limited - 32A Station Road West - Oxted Kent RH8 9EU - UNITED KINGDOM - - 00-50-C2 (hex) Criterion Systems Limited - 502000-502FFF (base 16) Criterion Systems Limited - Criterion House - 116 Wellington Street - Stockport Cheshire SK1 1YH - UNITED KINGDOM - - 00-50-C2 (hex) RESPIRONICS INC. - 503000-503FFF (base 16) RESPIRONICS INC. - 1001 MURRY RIDGE LANE - MURRYSVILLE PENNSYLVANIA 15668 - UNITED STATES - - 00-50-C2 (hex) Aphex Systems Ltd. - 504000-504FFF (base 16) Aphex Systems Ltd. - 11068 Randall St - Sun Valley CA 91352 - UNITED STATES - - 00-50-C2 (hex) Computerwise, Inc. - 505000-505FFF (base 16) Computerwise, Inc. - 302 N. Winchester - Olathe Ks 66062 - UNITED STATES - - 00-50-C2 (hex) 7+ Kft - 506000-506FFF (base 16) 7+ Kft - Homoród 17 - Budapest magyarország 1118 - HUNGARY - - 00-50-C2 (hex) Micro Connect Pty Ltd - 507000-507FFF (base 16) Micro Connect Pty Ltd - 22 Gardenia Place - FOREST GLEN QLD 4556 - AUSTRALIA - - 00-50-C2 (hex) PUTERCOM ENTERPRISE CO., LTD. - 508000-508FFF (base 16) PUTERCOM ENTERPRISE CO., LTD. - 5F-3, NO. 130 JIAN KANG ROAD - CHUNGHO CITY TAIPEI HSIEN 235 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Hillcrest Laboratories, Inc. - 509000-509FFF (base 16) Hillcrest Laboratories, Inc. - 15245 Shady Grove Road - Suite 400 - Rockville Maryland 20850 - UNITED STATES - - 00-50-C2 (hex) Monitor Business Machines Ltd - 50A000-50AFFF (base 16) Monitor Business Machines Ltd - Level 3, 56-58 Grafton Road - Grafton - Auckland 1035 - NEW ZEALAND - - 00-50-C2 (hex) Logic Beach Inc - 50B000-50BFFF (base 16) Logic Beach Inc - 8363-6F Center Drive - La Mesa CA 91942 - UNITED STATES - - 00-50-C2 (hex) AIRWISE TECHNOLOGY CO., LTD. - 50C000-50CFFF (base 16) AIRWISE TECHNOLOGY CO., LTD. - 21Fl-3, No. 107, Sec. 1 Jhongshan Road, - Sinjhuang City Taipei County 24250 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Clearsonics Pty. Ltd. - 50D000-50DFFF (base 16) Clearsonics Pty. Ltd. - Level 1 - 33 King William Street - Adelaide SA 5000 - AUSTRALIA - - 00-50-C2 (hex) Fibresavers Corporation - 50E000-50EFFF (base 16) Fibresavers Corporation - 14252 Culver Dr. Ste. A356 - Irvine Ca 92604 - UNITED STATES - - 00-50-C2 (hex) Polystar Instruments AB - 50F000-50FFFF (base 16) Polystar Instruments AB - MÃ¥rbackagatan 19 - 123 43 Farsta - Stockholm 11559 - SWEDEN - - 00-50-C2 (hex) Summit Developmen - 510000-510FFF (base 16) Summit Developmen - Karlstejnska 162 - Orech Jinocany 25225 - CZECH REPUBLIC - - 00-50-C2 (hex) Tecna Srl - 511000-511FFF (base 16) Tecna Srl - Via Statale Sud 115 - Mirandola Modena 41037 - ITALY - - 00-50-C2 (hex) Linear Acoustic, Inc - 512000-512FFF (base 16) Linear Acoustic, Inc - 354 N Prince St - Suite 110 - Lancaster PA 17603 - UNITED STATES - - 00-50-C2 (hex) Genie Network Resource Management Inc. - 513000-513FFF (base 16) Genie Network Resource Management Inc. - 5F., No. 150, Lane 360, - Sec. 1, Neihu Road, Neihu Dist. - Taipei city 114 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Tadian Electronics Systems LTD - 514000-514FFF (base 16) Tadian Electronics Systems LTD - Hamerkava 29 - Holon 58101 - ISRAEL - - 00-50-C2 (hex) Monaghan Engineering, Inc. - 515000-515FFF (base 16) Monaghan Engineering, Inc. - 862 Las Colinas Drive - Dripping Springs Texas 78620 - UNITED STATES - - 00-50-C2 (hex) SOWA ELECTRIC CO., LTD. - 516000-516FFF (base 16) SOWA ELECTRIC CO., LTD. - 92 Kitanokuchi-cho Shimotoba - Fushimi-Ku - Kyoto-City 612-8392 - JAPAN - - 00-50-C2 (hex) Solid State Logic - 517000-517FFF (base 16) Solid State Logic - 25 Springhill Road - Begbroke - Oxford Oxfordshire OX5 1RU - UNITED KINGDOM - - 00-50-C2 (hex) Christ Elektronik GmbH - 518000-518FFF (base 16) Christ Elektronik GmbH - Alpenstraße 34 - Memmingen Bavaria 87700 - GERMANY - - 00-50-C2 (hex) DBMCORP, Inc. - 519000-519FFF (base 16) DBMCORP, Inc. - 32A Spruce Street - Oakland New Jersey 07436 - UNITED STATES - - 00-50-C2 (hex) SpeasTech, Inc. - 51A000-51AFFF (base 16) SpeasTech, Inc. - 1527 S. Bowman Road - Suite F - Little Rock Arkansas 72211 - UNITED STATES - - 00-50-C2 (hex) Beta Lasermike Ltd - 51B000-51BFFF (base 16) Beta Lasermike Ltd - Stirling Road - Cressex Business Parks - High Wycombe Bucks HP12 3RT - UNITED KINGDOM - - 00-50-C2 (hex) TOA Systems - 51C000-51CFFF (base 16) TOA Systems - 305 East Dr. - Suite H - Melbourne Florida 32904 - UNITED STATES - - 00-50-C2 (hex) VELUX - 51D000-51DFFF (base 16) VELUX - Baekgaardsvej 40 - Skjern Skjer 6900 - DENMARK - - 00-50-C2 (hex) Alcon Technologies - 51E000-51EFFF (base 16) Alcon Technologies - 11201 Hampshire Ave. South - Suite E - Bloomington MN 55438 - UNITED STATES - - 00-50-C2 (hex) Traquair Data Systems, Inc. - 51F000-51FFFF (base 16) Traquair Data Systems, Inc. - 114 Sheldon Rd - Ithaca NY 14850 - UNITED STATES - - 00-50-C2 (hex) McCain Traffic Supply - 520000-520FFF (base 16) McCain Traffic Supply - 2365 Oak Ridge Way - Vista CA 92081 - UNITED STATES - - 00-50-C2 (hex) ARIS TECHNOLOGIES - 521000-521FFF (base 16) ARIS TECHNOLOGIES - 20 RUE DU FONDS PERNANT - COMPIEGNE OISE 60200 - FRANCE - - 00-50-C2 (hex) Mark IV IDS Corp. - 522000-522FFF (base 16) Mark IV IDS Corp. - 5959 Ambler Drive - Mississauga Ontario L4W 2N3 - CANADA - - 00-50-C2 (hex) AMRDEC Prototype Integration Facility - 523000-523FFF (base 16) AMRDEC Prototype Integration Facility - SES INC. AMSRD-AMR-SE-PI - BLDG 5405 FOWLER RD - REDSTONE ARSENAL AL 35898 - UNITED STATES - - 00-50-C2 (hex) Motec Pty Ltd - 524000-524FFF (base 16) Motec Pty Ltd - 121 Merrindale Drive - Croydon South Victoria 3136 - AUSTRALIA - - 00-50-C2 (hex) VASTech - 525000-525FFF (base 16) VASTech - PO Box 36124 - Menlo Park Gauteng 0102 - SOUTH AFRICA - - 00-50-C2 (hex) AC SYSTEMS, s.r.o. - 526000-526FFF (base 16) AC SYSTEMS, s.r.o. - Srobarova 3 - Praha 3 130 00 - CZECH REPUBLIC - - 00-50-C2 (hex) IRTrans - 527000-527FFF (base 16) IRTrans - Hagener Strasse 512 - Dortmund NRW 44227 - GERMANY - - 00-50-C2 (hex) tattile srl - 528000-528FFF (base 16) tattile srl - via trento 127/129 - fenili belasi - capriano del colle brescia 25020 - ITALY - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 529000-529FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) OMNITRONICS PTY LTD - 52A000-52AFFF (base 16) OMNITRONICS PTY LTD - 15 HECTOR STREET - OSBORNE PARK WESTERN AUSTRALIA 6017 - AUSTRALIA - - 00-50-C2 (hex) Sicon s.r.l. - 52B000-52BFFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) VITEC MULTIMEDIA - 52C000-52CFFF (base 16) VITEC MULTIMEDIA - 99, rue Pierre Semard - CHATILLON 92324 - FRANCE - - 00-50-C2 (hex) Smartcom-Bulgaria AD - 52D000-52DFFF (base 16) Smartcom-Bulgaria AD - Office 419, BIC IZOT Building 1 - Tsarigradsko Shosse Blvd. 7th km - SOFIA 1784 - BULGARIA - - 00-50-C2 (hex) DSP DESIGN - 52E000-52EFFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) Gesellschaft für Rationalisierung und Rechentechnik mbH - 52F000-52FFFF (base 16) Gesellschaft für Rationalisierung und Rechentechnik mbH - Ob der Eck 4 - Gütenbach Baden-Württemberg 78148 - GERMANY - - 00-50-C2 (hex) Innovation, Institute, Inc - 530000-530FFF (base 16) Innovation, Institute, Inc - P.O. Box 9359 - Caguas Puerto Rico 00726-9359 - PUERTO RICO - - 00-50-C2 (hex) Orion Technologies, Incorporated - 531000-531FFF (base 16) Orion Technologies, Incorporated - 690 Cone Park Court - Suite A - Merritt Island FL 32952 - UNITED STATES - - 00-50-C2 (hex) NVE Corporation - 532000-532FFF (base 16) NVE Corporation - 11409 Valley View Road - Eden Prairie MN 55344-3617 - UNITED STATES - - 00-50-C2 (hex) NanShanBridge Co.Ltd - 533000-533FFF (base 16) NanShanBridge Co.Ltd - C241 National Hi-Tech(westzone) Incubatiuon Service Center,Chengdu,PRC - ChengDu SiChuan 611731 - CHINA - - 00-50-C2 (hex) Hyundai J. Comm - 534000-534FFF (base 16) Hyundai J. Comm - 254-1, Makok-Ri, Hopub-Myoun - Ichun-Si Kyungki-Do 467-820 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) MMS Servis s.r.o. - 535000-535FFF (base 16) MMS Servis s.r.o. - Hodzova 261/1 - Myjava Slovak Republic 907 01 - SLOVAKIA - - 00-50-C2 (hex) C2 DIAGNOSTICS - 536000-536FFF (base 16) C2 DIAGNOSTICS - Parc Euromedecine II - Rue de la Valsiere - MONTPELLIER Cedex 5 Herault 34099 - FRANCE - - 00-50-C2 (hex) DST CONTROL AB - 537000-537FFF (base 16) DST CONTROL AB - Akerbogatan 10 - Linköping 58254 - SWEDEN - - 00-50-C2 (hex) EtherTek Circuits - 538000-538FFF (base 16) EtherTek Circuits - #38 - 473 Corina Ave. - Box 1576 - Princeton British Columbia V0X1W0 - CANADA - - 00-50-C2 (hex) Detection Technology Inc. - 539000-539FFF (base 16) Detection Technology Inc. - Micropolis - Piisilta 1 - Ii 91100 - FINLAND - - 00-50-C2 (hex) Image Control Design Limited - 53A000-53AFFF (base 16) Image Control Design Limited - 78 London Road - Widley - Waterlooville Hampshire PO7 5AB - UNITED KINGDOM - - 00-50-C2 (hex) Teleks Co. Ltd. - 53B000-53BFFF (base 16) Teleks Co. Ltd. - ul. Dostojevskogo, 15 - St.Petersburg 191002 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Marposs SPA - 53C000-53CFFF (base 16) Marposs SPA - Via Saliceto 13 - Bentivoglio Bologna 40010 - ITALY - - 00-50-C2 (hex) Digital communications Technologies - 53D000-53DFFF (base 16) Digital communications Technologies - 5201 Blue Lagoon Dr. #843 - Miami Florida 33126 - UNITED STATES - - 00-50-C2 (hex) Honeywell GNO - 53E000-53EFFF (base 16) Honeywell GNO - 13350 us hwy 19 n - clearwater florida 33764 - UNITED STATES - - 00-50-C2 (hex) Ellips B.V. - 53F000-53FFFF (base 16) Ellips B.V. - Urkhovenseweg 11 - Eindhoven Noord-Brabant 5641 KA - NETHERLANDS - - 00-50-C2 (hex) Mesure Controle Commande - 540000-540FFF (base 16) Mesure Controle Commande - Rue Guillaume MASSICOT - ISSOUDUN CENTRE 36100 - FRANCE - - 00-50-C2 (hex) WAVES SYSTEM - 541000-541FFF (base 16) WAVES SYSTEM - La Ville en Bois - BOUAYE Loire Atlantique 44830 - FRANCE - - 00-50-C2 (hex) AVerMedia Technologies, Inc. - 542000-542FFF (base 16) AVerMedia Technologies, Inc. - 7F.,No. 137, Jian Yi Rd. - Chung Ho City Taipei Hsien 23585 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) DIGI SESN AG - 543000-543FFF (base 16) DIGI SESN AG - Freiburgstr. 65 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Zetera - 544000-544FFF (base 16) Zetera - 16842 Von Karman Ave., Suite 100 - Irvine CA 92606 - UNITED STATES - - 00-50-C2 (hex) SecuInfo Co., Ltd. - 545000-545FFF (base 16) SecuInfo Co., Ltd. - 1411, Kranz Techno, 5442-1, - Sangdaewon 2-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462729 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Universidad de Chile Facultad de Medicina - 546000-546FFF (base 16) Universidad de Chile Facultad de Medicina - Avda. Independencia 1027 - Santiago RM 8380453 - CHILE - - 00-50-C2 (hex) BLANKOM Antennentechnik GmbH - 547000-547FFF (base 16) BLANKOM Antennentechnik GmbH - Hermann-Petersilge-Str. 1 - Bad Blankenburg Thuringia D-07422 - GERMANY - - 00-50-C2 (hex) I.T.W. Betaprint - 548000-548FFF (base 16) I.T.W. Betaprint - Ponce de Leon 4 - Sant Just Desvern Barcelona 08960 - SPAIN - - 00-50-C2 (hex) Netsynt S.p.A. - 549000-549FFF (base 16) Netsynt S.p.A. - Via G. A. Resti 53 - Roma 00143 - ITALY - - 00-50-C2 (hex) IPTC Tech. Comm. AB - 54A000-54AFFF (base 16) IPTC Tech. Comm. AB - Pyramidbacken 6 - Kungens Kurva Stockholm 14175 - SWEDEN - - 00-50-C2 (hex) Innopsys - 54B000-54BFFF (base 16) Innopsys - ZA Activestre - Carbonne 31390 - FRANCE - - 00-50-C2 (hex) Sintecnos srl - 54C000-54CFFF (base 16) Sintecnos srl - Via Boncompagni, 34 - Milan 20139 - ITALY - - 00-50-C2 (hex) Silent System - 54D000-54DFFF (base 16) Silent System - Sumikawa 5-5-1-6 Minamiku - Sapporo Hokkaido 005-0005 - JAPAN - - 00-50-C2 (hex) Convergent Design - 54E000-54EFFF (base 16) Convergent Design - 4465 Northpark Dr. Suite 400 - Colorado Springs Colorado 80907 - UNITED STATES - - 00-50-C2 (hex) Valtronic SA - 54F000-54FFFF (base 16) Valtronic SA - Rue de Bon Port - Les CharbonniÄres Vaud 1343 - SWITZERLAND - - 00-50-C2 (hex) LJU Automatisierungstechnik GmbH - 550000-550FFF (base 16) LJU Automatisierungstechnik GmbH - Am Schlahn 1 - Potsdam Brandenburg D-14476 - GERMANY - - 00-50-C2 (hex) Innovative Neurotroncs - 551000-551FFF (base 16) Innovative Neurotroncs - 2 Bethesda Metro Center - Suite 1200 - Bethesda MD 20814 - UNITED STATES - - 00-50-C2 (hex) Elfiq Inc. - 552000-552FFF (base 16) Elfiq Inc. - 1125 university - suite 712 - Montreal Quebec H3B 3A7 - CANADA - - 00-50-C2 (hex) ATH system - 553000-553FFF (base 16) ATH system - Osady Lezaku 498 - Chrast 53851 - CZECH REPUBLIC - - 00-50-C2 (hex) Weinzierl Engineering GmbH - 554000-554FFF (base 16) Weinzierl Engineering GmbH - Bahnhofstrasse 6 - Tyrlaching Bayern 84558 - GERMANY - - 00-50-C2 (hex) Control Alternative Solutions, Inc. - 555000-555FFF (base 16) Control Alternative Solutions, Inc. - 1001 Barton Creek Drive - Dripping Springs Texas 78620 - UNITED STATES - - 00-50-C2 (hex) Freiburger BlickZentrum - 556000-556FFF (base 16) Freiburger BlickZentrum - Hans-Sachs-Gasse 6 - 79098 Freiburg - GERMANY - - 00-50-C2 (hex) Netcomsec Co Ltd - 557000-557FFF (base 16) Netcomsec Co Ltd - 10 Nisshinco 2-chome - Fuchu City Tokyo 253-0197 - JAPAN - - 00-50-C2 (hex) Bedo Elektronik GmbH - 558000-558FFF (base 16) Bedo Elektronik GmbH - Ennsstrasse 19 - Krefeld NRW 47809 - GERMANY - - 00-50-C2 (hex) Fail Safe Solutions LLC - 559000-559FFF (base 16) Fail Safe Solutions LLC - 950 Salem Ave. - Hillside NJ 07205 - UNITED STATES - - 00-50-C2 (hex) Valde Systems, Inc. - 55A000-55AFFF (base 16) Valde Systems, Inc. - 26 Iron Works Ln - Brookline NH 03033 - UNITED STATES - - 00-50-C2 (hex) MATRIX TELECOM PVT. LTD. - 55B000-55BFFF (base 16) MATRIX TELECOM PVT. LTD. - 394-GIDC - MAKARPURA - VADODARA GUJARAT 390010 - INDIA - - 00-50-C2 (hex) ads-tec GmbH - 55C000-55CFFF (base 16) ads-tec GmbH - Raiffeisenstraße 14 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-50-C2 (hex) ACD Elektronik GmbH - 55D000-55DFFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten bawu 88480 - GERMANY - - 00-50-C2 (hex) HANZAS ELEKTRONIKA, SIA - 55E000-55EFFF (base 16) HANZAS ELEKTRONIKA, SIA - Akmenu iela 72 - OGRE OGRES NOVADS LV5001 - LATVIA - - 00-50-C2 (hex) Moog Broad Reach - 55F000-55FFFF (base 16) Moog Broad Reach - 1113 Washington Ave #200 - Golden CO 80401 - UNITED STATES - - 00-50-C2 (hex) Procon Electronics - 560000-560FFF (base 16) Procon Electronics - PO Box 164 - Seven Hills - Sydney NSW 1730 - AUSTRALIA - - 00-50-C2 (hex) Seitec Elektronik GmbH - 561000-561FFF (base 16) Seitec Elektronik GmbH - Kastanienweg 4 - Troeglitz 06729 - GERMANY - - 00-50-C2 (hex) C21 Systems Limited - 562000-562FFF (base 16) C21 Systems Limited - Dunston Innovation Centre - Dunston Road - Chesterfield Derbyshire S41 8NG - UNITED KINGDOM - - 00-50-C2 (hex) ORTRAT, S.L. - 563000-563FFF (base 16) ORTRAT, S.L. - Calle de la Sófora 15 - E-28020 Madrid - SPAIN - - 00-50-C2 (hex) Last Mile Gear - 564000-564FFF (base 16) Last Mile Gear - 1324 Vandercook Way - Longview WA 98632 - UNITED STATES - - 00-50-C2 (hex) WORKPOWER TECNOLOGIA ELETRONICA LTDA-EPP - 565000-565FFF (base 16) WORKPOWER TECNOLOGIA ELETRONICA LTDA-EPP - RUA OTAVIO PASSOS, 132 - CASA 2 - São Paulo SP 05590-190 - BRAZIL - - 00-50-C2 (hex) ubinetsys.co..ltd - 566000-566FFF (base 16) ubinetsys.co..ltd - 3F Sang-gal B.D,220-3 - Sanggal-Dong, Giheung-Gu - Yongin-Si Gyunggi-Do 449-905 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Tess GmbH - 567000-567FFF (base 16) Tess GmbH - Schumanstraße 33d - Würselen NRW 52146 - GERMANY - - 00-50-C2 (hex) GeoFocus, LLC - 568000-568FFF (base 16) GeoFocus, LLC - 3651 FAU Blvd., Suite 215 - Boca Raton FL 33431 - UNITED STATES - - 00-50-C2 (hex) Twinwin Technplogy Co.,Ltd. - 569000-569FFF (base 16) Twinwin Technplogy Co.,Ltd. - 6F-2 ,No.400,Sec 1,Changping Rd.,Beirict, - Taichung City - 406 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Grupo Epelsa S.L. - 56A000-56AFFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) Dataton Utvecklings AB - 56B000-56BFFF (base 16) Dataton Utvecklings AB - Box 454 - Linkoping . 58105 - SWEDEN - - 00-50-C2 (hex) Targeted Technologies, LLC - 56C000-56CFFF (base 16) Targeted Technologies, LLC - 273 Azalea Road - Buidling 1, Suite 515 - Mobile AL 36609 - UNITED STATES - - 00-50-C2 (hex) Computrol Fuel Systems Inc. - 56D000-56DFFF (base 16) Computrol Fuel Systems Inc. - 8537 Commerce Court - Burnaby BC V5A 4N4 - CANADA - - 00-50-C2 (hex) LAB-EL ELEKTRONIKA LABORATORYJNA S.J. - 56E000-56EFFF (base 16) LAB-EL ELEKTRONIKA LABORATORYJNA S.J. - Bodycha 68B - Warszawa Mazowieckie 02-495 - POLAND - - 00-50-C2 (hex) GMA, LLC - 56F000-56FFFF (base 16) GMA, LLC - 18314 Kinzie St. - Los Angeles CA 91325 - UNITED STATES - - 00-50-C2 (hex) Ellex Medical Pty Ltd - 570000-570FFF (base 16) Ellex Medical Pty Ltd - 82 Gilbert Street - Adelaide South Australia 5000 - AUSTRALIA - - 00-50-C2 (hex) Oberon Service srl - 571000-571FFF (base 16) Oberon Service srl - Via Meda 28 - Milan MI 20141 - ITALY - - 00-50-C2 (hex) Chell Instruments Ltd - 572000-572FFF (base 16) Chell Instruments Ltd - Folgate House - Folgate Road - North Walsham Norfolk NR28 0AJ - UNITED KINGDOM - - 00-50-C2 (hex) DATAMICRO Co., Ltd. - 573000-573FFF (base 16) DATAMICRO Co., Ltd. - P.O. Box 17 - Taganrog Rostov Region 347916 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Ingeniería Almudí S.L. - 574000-574FFF (base 16) Ingeniería Almudí S.L. - c/ San Luis, 8 bajo 1ÅŸ - Murcia Alcantarilla 30820 - SPAIN - - 00-50-C2 (hex) SOLYSTIC - 575000-575FFF (base 16) SOLYSTIC - 14 Avenue de Raspail - GENTILLY Cedex Val de Marne 94257 - FRANCE - - 00-50-C2 (hex) Visi-tech Systems Ltd - 576000-576FFF (base 16) Visi-tech Systems Ltd - Unit X Cerphilly Bus Pk - Van Road - Caerphilly Mid Glamorgan CF83 3ED - UNITED KINGDOM - - 00-50-C2 (hex) Advanced Software Technologies - 577000-577FFF (base 16) Advanced Software Technologies - c/ Caleruega, 102 2° Planta - Madrid 28033 - SPAIN - - 00-50-C2 (hex) Delphi Display Systems, Inc. - 578000-578FFF (base 16) Delphi Display Systems, Inc. - 3160 Pullman Street - Costa Mesa California 92626 - UNITED STATES - - 00-50-C2 (hex) Gastager Systemtechnik GmbH - 579000-579FFF (base 16) Gastager Systemtechnik GmbH - Gerating 10 - Traunstein Bayern 83278 - GERMANY - - 00-50-C2 (hex) Pigeon Point Systems LLC - 57A000-57AFFF (base 16) Pigeon Point Systems LLC - 2191 S. El Camino Real - Suite 209 - Oceanside CA 95054 - UNITED STATES - - 00-50-C2 (hex) ptswitch - 57B000-57BFFF (base 16) ptswitch - 1416 Tanaka Dr - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) éolane - 57C000-57CFFF (base 16) éolane - 667 rue Aristide Berges - 38330 Montbonnot St Martin - FRANCE - - 00-50-C2 (hex) Sierra Video Systems - 57D000-57DFFF (base 16) Sierra Video Systems - 104B New Mohawk Rd - Nevada City CA 95959 - UNITED STATES - - 00-50-C2 (hex) Digital Way - 57E000-57EFFF (base 16) Digital Way - 1 Chemin des CHAUX - Saint-Etienne Loire 42000 - FRANCE - - 00-50-C2 (hex) Orderite, Inc. - 57F000-57FFFF (base 16) Orderite, Inc. - P. O. Box 48004 - Athens GA 30604 - UNITED STATES - - 00-50-C2 (hex) Buyang Electronics Industrial co.,Ltd. - 580000-580FFF (base 16) Buyang Electronics Industrial co.,Ltd. - Oryu-Dong - 434-140 - Seo-Ku Incheon 404-300 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Devitech ApS - 581000-581FFF (base 16) Devitech ApS - Sundsholmen 12 - Noerresundby DK 9400 - DENMARK - - 00-50-C2 (hex) AllSun A/S - 582000-582FFF (base 16) AllSun A/S - Brundtlandparken 2 - Toftlund Jutland DK-6520 - DENMARK - - 00-50-C2 (hex) Jünger Audio-Studiotechnik GmbH - 583000-583FFF (base 16) Jünger Audio-Studiotechnik GmbH - Justus-von-Liebig-Straße 7 - Berlin 12489 - GERMANY - - 00-50-C2 (hex) Toyota Motorsport GmbH - 584000-584FFF (base 16) Toyota Motorsport GmbH - Toyota-Allee 7 - Köln NRW 50858 - GERMANY - - 00-50-C2 (hex) Wireless Cables Inc - 585000-585FFF (base 16) Wireless Cables Inc - 1414 Soquel Ave, Ste 212 - Santa Cruz CA 95062 - UNITED STATES - - 00-50-C2 (hex) Genetix Ltd - 586000-586FFF (base 16) Genetix Ltd - Queensway - New Milton Hampshire BH25 5NN - UNITED KINGDOM - - 00-50-C2 (hex) Dynalco - 587000-587FFF (base 16) Dynalco - 3690 NW 53rd St - Ft. Lauderdale Florida 33309 - UNITED STATES - - 00-50-C2 (hex) Federal Electronics - 588000-588FFF (base 16) Federal Electronics - 75 Stamp Farm Road - Cranston Rhode Island 02921 - UNITED STATES - - 00-50-C2 (hex) HORIBA MEDICAL - 589000-589FFF (base 16) HORIBA MEDICAL - rue du caducee - Montpellier Herault 34000 - FRANCE - - 00-50-C2 (hex) Dixell S.p.a. - 58A000-58AFFF (base 16) Dixell S.p.a. - Via Dell'Industria 27 - Pieve D'Alpago 32010 - ITALY - - 00-50-C2 (hex) Innovative Dynamics GmbH - 58B000-58BFFF (base 16) Innovative Dynamics GmbH - Wiesenweg 9 - Vordorf / Rethen Lower Saxony 38533 - GERMANY - - 00-50-C2 (hex) Lattice Semiconductor Corp. (LPA) - 58C000-58CFFF (base 16) Lattice Semiconductor Corp. (LPA) - 1605 Valley Center Parkway - Suite 300 - Bethlehem PA 18017 - UNITED STATES - - 00-50-C2 (hex) ZAO - 58D000-58DFFF (base 16) ZAO - Frunze, 40 - Omsk Omskaia district 644099 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Penny & Giles Aerospace Ltd - 58E000-58EFFF (base 16) Penny & Giles Aerospace Ltd - 1 Airfield Road - Christchurch Dorset BH23 3TH - UNITED KINGDOM - - 00-50-C2 (hex) XoIP Systems Pty Ltd - 58F000-58FFFF (base 16) XoIP Systems Pty Ltd - Unit 17, 538 Gardeners Rd - Alexandria NSW 2015 - AUSTRALIA - - 00-50-C2 (hex) EM Motorsport Ltd - 590000-590FFF (base 16) EM Motorsport Ltd - Church Farmhouse - Holton - Oxford Oxfordshire OX33 1PR - UNITED KINGDOM - - 00-50-C2 (hex) Grosvenor Technology Ltd - 591000-591FFF (base 16) Grosvenor Technology Ltd - Millars Three - Southmill Road - Bishop's Stortford Hertfordshire CM23 3DH - UNITED KINGDOM - - 00-50-C2 (hex) PaloDEx Group Oy - 592000-592FFF (base 16) PaloDEx Group Oy - Nahkelantie 160 - P.O.Box 64 - TUUSULA FIN 04301 - FINLAND - - 00-50-C2 (hex) Broadlight - 593000-593FFF (base 16) Broadlight - 7 Begin st - Ramat Gan 52521 - ISRAEL - - 00-50-C2 (hex) Pixel Velocity, Inc. - 594000-594FFF (base 16) Pixel Velocity, Inc. - 3917 Research Park Drive - Suite B7 - Ann Arbor MI 48108 - UNITED STATES - - 00-50-C2 (hex) Callpod, Inc. - 595000-595FFF (base 16) Callpod, Inc. - 850 W. Jackson - Suite 260 - Chicago IL 60607 - UNITED STATES - - 00-50-C2 (hex) SPANSION - 596000-596FFF (base 16) SPANSION - PO Box 3453, Mail Stop 9 - 915 Deguigne Drive - Sunnyvale CA 94088 - UNITED STATES - - 00-50-C2 (hex) Nautel Limited - 597000-597FFF (base 16) Nautel Limited - 10089 Peggy's Cove Road - Hackett's Cove Nova Scotia B3Z3J4 - CANADA - - 00-50-C2 (hex) Bundesamt für Strahlenschutz - 598000-598FFF (base 16) Bundesamt für Strahlenschutz - Rosastraße 9 - Freiburg NA 79098 - GERMANY - - 00-50-C2 (hex) Fen Technology Limited - 599000-599FFF (base 16) Fen Technology Limited - 4 Oakington Business Park - Dry Drayton Road - Oakington Cambridge CB24 3DQ - UNITED KINGDOM - - 00-50-C2 (hex) MultiTrode Pty Ltd - 59A000-59AFFF (base 16) MultiTrode Pty Ltd - 18 Brandl Street - PO Box 4633 Eight Mile Plains - Brisbane QLD 4113 - AUSTRALIA - - 00-50-C2 (hex) SAPEC - 59B000-59BFFF (base 16) SAPEC - Rufino Gonzalez, 15 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) DELSAT GROUP S.A. - 59C000-59CFFF (base 16) DELSAT GROUP S.A. - CORDOBA 3197 - MAR DEL PLATA BUENOS AIRES 7600 - ARGENTINA - - 00-50-C2 (hex) DSS Networks, Inc. - 59D000-59DFFF (base 16) DSS Networks, Inc. - 23 Spectrum Pointe Drive - Suite 202 - Lake Forest CA 92630 - UNITED STATES - - 00-50-C2 (hex) Legerity - 59E000-59EFFF (base 16) Legerity - 4509 Freidrich Lane - Bld 2, Ste 200 - Austin TX 78744 - UNITED STATES - - 00-50-C2 (hex) ads-tec GmbH - 59F000-59FFFF (base 16) ads-tec GmbH - Raiffeisenstraße 14 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-50-C2 (hex) Rudolph Technologies, Inc. - 5A0000-5A0FFF (base 16) Rudolph Technologies, Inc. - 4900 West 78th Street - Bloomington MN 55435 - UNITED STATES - - 00-50-C2 (hex) Vestfold Butikkdata AS - 5A1000-5A1FFF (base 16) Vestfold Butikkdata AS - Wirgenesveg 1 - Branch Wireless Systems - BARKAKER VESTFOLD N-3157 - NORWAY - - 00-50-C2 (hex) iNET Systems Inc. - 5A2000-5A2FFF (base 16) iNET Systems Inc. - 4633 Old Ironsides Dr. Suite 418 - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) LUMEL S.A. - 5A3000-5A3FFF (base 16) LUMEL S.A. - UL. SULECHOWSKA 1 - ZIELONA Góra WOJ. LUBUSKIE 65-022 - POLAND - - 00-50-C2 (hex) Federal State Unitary Enterprise Experimental Factory for Sc - 5A4000-5A4FFF (base 16) Federal State Unitary Enterprise Experimental Factory for Sc - EZAN, Academician Semenov Avenue, 9, - Chernogolovka Moscow Region 142432 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Equipos de Telecomunicación Optoelectronicos, S.A. - 5A5000-5A5FFF (base 16) Equipos de Telecomunicación Optoelectronicos, S.A. - Poligono Malpica G. Quejido, 74 - Zaragoza 50007 - SPAIN - - 00-50-C2 (hex) Plastic Logic - 5A6000-5A6FFF (base 16) Plastic Logic - 34 Cambridge Science Park - Milton Road - Cambridge Cambridgeshire CB4 0FX - UNITED KINGDOM - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 5A7000-5A7FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) ETAP NV - 5A8000-5A8FFF (base 16) ETAP NV - Antwerpsesteenweg 130 - Malle Antwerp 2390 - BELGIUM - - 00-50-C2 (hex) AYC Telecom Ltd - 5A9000-5A9FFF (base 16) AYC Telecom Ltd - Unit 2 Fleet Business Park - Church Crookham Hampshire GU52 8BF - UNITED KINGDOM - - 00-50-C2 (hex) Transenna AB - 5AA000-5AAFFF (base 16) Transenna AB - Roslinvagen 48 - Bromma Stockholm SE-16851 - SWEDEN - - 00-50-C2 (hex) Eaton Corporation Electrical Group Data Center Solutions - Pulizzi - 5AB000-5ABFFF (base 16) Eaton Corporation Electrical Group Data Center Solutions - Pulizzi - 3200 S. Susan Street - Santa Ana California 92704 - UNITED STATES - - 00-50-C2 (hex) Kinemetrics, Inc. - 5AC000-5ACFFF (base 16) Kinemetrics, Inc. - 222 Vista Avenue - Pasadena CA 91107 - UNITED STATES - - 00-50-C2 (hex) Emcom Systems - 5AD000-5ADFFF (base 16) Emcom Systems - 127 Route 206 South, Suite 27 - Trenton New Jersey 08610 - UNITED STATES - - 00-50-C2 (hex) CPS EUROPE B.V. - 5AE000-5AEFFF (base 16) CPS EUROPE B.V. - Boxtelseweg 26 - Vught Noord Brabant 5261NE - NETHERLANDS - - 00-50-C2 (hex) DORLET S.A. - 5AF000-5AFFFF (base 16) DORLET S.A. - Albert Einstein 34 - Parque Tecnologico de Alava - Vitoria Alava 01510 - SPAIN - - 00-50-C2 (hex) INCOTEC GmbH - 5B0000-5B0FFF (base 16) INCOTEC GmbH - Blomestrasse 25 - 27 - Bielefeld NRW 33609 - GERMANY - - 00-50-C2 (hex) Rosta Ltd - 5B1000-5B1FFF (base 16) Rosta Ltd - Office 17, - 3/1 Zhivopisnaya Str. - Moscow 123103 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Syntronic AB - 5B2000-5B2FFF (base 16) Syntronic AB - Utmarksvagen 33C - Gavle 802 91 - SWEDEN - - 00-50-C2 (hex) HITECOM System - 5B3000-5B3FFF (base 16) HITECOM System - (6F Kolon-Techno valley) 60-4, Gasan-Dong, Geumcheon-gu, - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Terrascience Systems Ltd. - 5B4000-5B4FFF (base 16) Terrascience Systems Ltd. - 2040 West 10th Ave. - Vancouver B.C. V6J 2B3 - CANADA - - 00-50-C2 (hex) RAFAEL - 5B5000-5B5FFF (base 16) RAFAEL - P.O.B. 2250 - HAIFA 31201 - ISRAEL - - 00-50-C2 (hex) Kontron (Beijing) Technology Co.,Ltd. - 5B6000-5B6FFF (base 16) Kontron (Beijing) Technology Co.,Ltd. - 5F,NO5,Haiying Road, Fengtai Science Park - Beijing 100070 - CHINA - - 00-50-C2 (hex) AVerMedia Technologies, Inc. - 5B7000-5B7FFF (base 16) AVerMedia Technologies, Inc. - 7F., No.137, Jian Yi Rd. - Chung Ho City Taipei Hesien 23585 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) WestfaliaSurge GmbH - 5B8000-5B8FFF (base 16) WestfaliaSurge GmbH - Siemenstr.25-27 - Boenen NRW 59199 - GERMANY - - 00-50-C2 (hex) Taiwan Video & Monitor - 5B9000-5B9FFF (base 16) Taiwan Video & Monitor - 3F, 141 Jen Ai Rd Sec. 3 - Taipei City 106 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) SAIA Burgess Controls AG - 5BA000-5BAFFF (base 16) SAIA Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) UNIC TECHNOLOGIES INC - 5BB000-5BBFFF (base 16) UNIC TECHNOLOGIES INC - NO.7, 5TH AVE. SHANGDI - HAIDIAN BEIJING 100085 - CHINA - - 00-50-C2 (hex) Guangzhou Hui Si Information Technologies Inc. - 5BC000-5BCFFF (base 16) Guangzhou Hui Si Information Technologies Inc. - A-406, GD Soft Science Park, No.11 CaiPin Rd, GZ Science City, - GuangZhou GuangDong 510663 - CHINA - - 00-50-C2 (hex) Nomus Comm-Systems - 5BD000-5BDFFF (base 16) Nomus Comm-Systems - Plot 9A, Commercial Complex - Srinagar Colony - Hyderabad AP 500073 - INDIA - - 00-50-C2 (hex) Card Access Services Pty Ltd - 5BE000-5BEFFF (base 16) Card Access Services Pty Ltd - Level 2, 7-9 Albany St - St Leonards - Sydney New South Wales 2065 - AUSTRALIA - - 00-50-C2 (hex) Techimp Systems S.r.l. - 5BF000-5BFFFF (base 16) Techimp Systems S.r.l. - Via Toscana, 11/C - Zola Predosa Bologna 40069 - ITALY - - 00-50-C2 (hex) Pyott-Boone Electronics - 5C0000-5C0FFF (base 16) Pyott-Boone Electronics - P. O. Box 809 - Tazewell VA 24651 - UNITED STATES - - 00-50-C2 (hex) R. L. Drake Company - 5C1000-5C1FFF (base 16) R. L. Drake Company - 230 Industrial Drive - Franklin OH 45005 - UNITED STATES - - 00-50-C2 (hex) Intuitive Surgical - 5C2000-5C2FFF (base 16) Intuitive Surgical - 950 Kifer Road - Sunnyvale CA 94040 - UNITED STATES - - 00-50-C2 (hex) KS System GmbH - 5C3000-5C3FFF (base 16) KS System GmbH - Alexanderstr. 37 - Muelheim NRW 45472 - GERMANY - - 00-50-C2 (hex) ProMik GmbH - 5C4000-5C4FFF (base 16) ProMik GmbH - Suedwestpark 100 - Nuernberg Bayern 90449 - GERMANY - - 00-50-C2 (hex) Radiant Imaging, Inc. - 5C5000-5C5FFF (base 16) Radiant Imaging, Inc. - 15321 Main St NE, Suite 310 - PO Box 5000 - Duvall WA 98019 - UNITED STATES - - 00-50-C2 (hex) Technische Alternative GmbH - 5C6000-5C6FFF (base 16) Technische Alternative GmbH - Langestrasse 124 - Amaliendorf Lower Austria A-3872 - AUSTRIA - - 00-50-C2 (hex) InSync Technology Ltd - 5C7000-5C7FFF (base 16) InSync Technology Ltd - Festival Hall - Heath Road - Petersfield Hampshire GU31 4DZ - UNITED KINGDOM - - 00-50-C2 (hex) Georgia Tech Research Institute - 5C8000-5C8FFF (base 16) Georgia Tech Research Institute - 400 Tenth St. NW - CRB 476 - Atlanta Georgia 30332 - UNITED STATES - - 00-50-C2 (hex) Shenzhen Quanlong Technique Co.Ltd - 5C9000-5C9FFF (base 16) Shenzhen Quanlong Technique Co.Ltd - No.215, Building Langfeng, Road Kefa no.2 - Hong Kong 25175 852 - CHINA - - 00-50-C2 (hex) Buyang Electronics Industrial Co., Ltd. - 5CA000-5CAFFF (base 16) Buyang Electronics Industrial Co., Ltd. - 434-140 Oryu-Dong - Seo-Ku - Incheon 404-300 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Kobold Sistemi s.r.l. - 5CB000-5CBFFF (base 16) Kobold Sistemi s.r.l. - Via Giuseppe Di Vittorio 307/28 - Sesto San Giovanni Milano 20099 - ITALY - - 00-50-C2 (hex) ENSEO - 5CC000-5CCFFF (base 16) ENSEO - 401 International Pkwy - Suite 100 - Richardson TX 75081 - UNITED STATES - - 00-50-C2 (hex) RADA Electronics Industries Ltd. - 5CD000-5CDFFF (base 16) RADA Electronics Industries Ltd. - 7 Gibory Israel St. - Netanya 42504 - ISRAEL - - 00-50-C2 (hex) Roke Manor Research Ltd - 5CE000-5CEFFF (base 16) Roke Manor Research Ltd - Roke Manor - Old Salisbury Lane - ROMSEY Hampshire SO51 0ZN - UNITED KINGDOM - - 00-50-C2 (hex) Innomed Medical Inc - 5CF000-5CFFFF (base 16) Innomed Medical Inc - Szabó József utca 12 - Budapest 1146 - HUNGARY - - 00-50-C2 (hex) Automata Spa - 5D0000-5D0FFF (base 16) Automata Spa - Via Carducci 705 - Caronno Pertusella Varese 21042 - ITALY - - 00-50-C2 (hex) Meucci Solutions - 5D1000-5D1FFF (base 16) Meucci Solutions - Bellevue 5 - UCO Tower - Gent Ledeberg Oost Vlaanderen B9050 - BELGIUM - - 00-50-C2 (hex) DA-Design Oy - 5D2000-5D2FFF (base 16) DA-Design Oy - Keskuskatu 29 - Jokioinen FIN-31600 - FINLAND - - 00-50-C2 (hex) Wexiodisk AB - 5D3000-5D3FFF (base 16) Wexiodisk AB - Mardvagen 4 - Vaxjo Kronoberg 352 45 - SWEDEN - - 00-50-C2 (hex) Buyang Electronics Industrial Co., Ltd. - 5D4000-5D4FFF (base 16) Buyang Electronics Industrial Co., Ltd. - 434-140 Oryu-Dong, Seo-Ku - Incheon 404-300 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Cannon Technologies - 5D5000-5D5FFF (base 16) Cannon Technologies - Queensway - New Milton - Bournmouth Hampshire BH25 5NU - UNITED KINGDOM - - 00-50-C2 (hex) BioAccess Tecnologia em Biometria Ltda. - 5D6000-5D6FFF (base 16) BioAccess Tecnologia em Biometria Ltda. - Av. Pres. Kennedy, 47 - Curitiba PR 80220-200 - BRAZIL - - 00-50-C2 (hex) Synrad, Inc. - 5D7000-5D7FFF (base 16) Synrad, Inc. - 4600 Campus Place - Mukilteo WA 98275 - UNITED STATES - - 00-50-C2 (hex) TECHNIFOR SAS - 5D8000-5D8FFF (base 16) TECHNIFOR SAS - 114 QUAI DU RHONE - MIRIBEL RHONE-ALPES 01708 - FRANCE - - 00-50-C2 (hex) Crimson Microsystems, Inc. - 5D9000-5D9FFF (base 16) Crimson Microsystems, Inc. - 1277 N. Borregas Ave - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) TONNA ELECTRONIQUE - 5DA000-5DAFFF (base 16) TONNA ELECTRONIQUE - 449, route de METZ - MONDELANGE MOSELLE 57303 - FRANCE - - 00-50-C2 (hex) CEGELEC SUD EST - 5DB000-5DBFFF (base 16) CEGELEC SUD EST - ROUTE DE SALON - BP 9 - LES PENNES MIRABEAU 13755 - FRANCE - - 00-50-C2 (hex) RM Michaelides Software & Elektronik GmbH - 5DC000-5DCFFF (base 16) RM Michaelides Software & Elektronik GmbH - Donaustrasse 14 - Fulda Hessen 36043 - GERMANY - - 00-50-C2 (hex) SomerData ltd - 5DD000-5DDFFF (base 16) SomerData ltd - Underwood Business Park - Wookey Hole Road - Wells Somerset BA5 1AF - UNITED KINGDOM - - 00-50-C2 (hex) Magal Senstar Inc. - 5DE000-5DEFFF (base 16) Magal Senstar Inc. - 43180 Osgood Rd. - Fremont CA 94539 - UNITED STATES - - 00-50-C2 (hex) Gnutek Ltd. - 5DF000-5DFFFF (base 16) Gnutek Ltd. - 3, Strathavon Close, - Cranleigh Surrey GU6 8PW - UNITED KINGDOM - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 5E0000-5E0FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Ittiam Systems (P) Ltd - 5E1000-5E1FFF (base 16) Ittiam Systems (P) Ltd - Consulate 1, - 1, Richmond Road - Bangalore Karnataka 560025 - INDIA - - 00-50-C2 (hex) PYRAMID Computer GmbH - 5E2000-5E2FFF (base 16) PYRAMID Computer GmbH - Boetzinger Strasse 60 - Freiburg BW 79111 - GERMANY - - 00-50-C2 (hex) Computechnic AG - 5E3000-5E3FFF (base 16) Computechnic AG - Bachwiesstrasse 24 - Rorschacherberg St. Gallen 9404 - SWITZERLAND - - 00-50-C2 (hex) Buyang Electronics Industrial Co., Ltd. - 5E4000-5E4FFF (base 16) Buyang Electronics Industrial Co., Ltd. - 434-140 oryu-Dong - Seo-Ku - Incheon 404-300 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Stresstech OY - 5E5000-5E5FFF (base 16) Stresstech OY - Tikkutehtaantie 1 - Vaajakoski 40800 - FINLAND - - 00-50-C2 (hex) Musatel - 5E6000-5E6FFF (base 16) Musatel - c/Caridad, 1 BIS - Pozuelo de Alarcón Madrid 28224 - SPAIN - - 00-50-C2 (hex) EADS TEST & SERVICES - 5E7000-5E7FFF (base 16) EADS TEST & SERVICES - 5, avenue guynemer BP 86 - colomiers 31772 - FRANCE - - 00-50-C2 (hex) Info-Chip Communications Ltd. - 5E8000-5E8FFF (base 16) Info-Chip Communications Ltd. - 4403 Rupert Street - Main Floor - Vancouver BC V5R 2J1 - CANADA - - 00-50-C2 (hex) Micro Technology Services Inc. - 5E9000-5E9FFF (base 16) Micro Technology Services Inc. - 1819 Firman Drive - Suite 137 - Richardson Texas 75081 - UNITED STATES - - 00-50-C2 (hex) Micro Elektronische Producten - 5EA000-5EAFFF (base 16) Micro Elektronische Producten - Noordeinde 124F - Landsmeer NH 1121AL - NETHERLANDS - - 00-50-C2 (hex) Garper Telecomunicaciones, S.L. - 5EB000-5EBFFF (base 16) Garper Telecomunicaciones, S.L. - Calle Antoñita Jiménez, 8 Local - Madrid 28019 - SPAIN - - 00-50-C2 (hex) ASiS Technologies Pte Ltd - 5EC000-5ECFFF (base 16) ASiS Technologies Pte Ltd - 71 Ubi Crescent - #08-05 Excalibur Centre - Singapore 408571 - SINGAPORE - - 00-50-C2 (hex) AQUAROTTER A FRANKE COMPANY - 5ED000-5EDFFF (base 16) AQUAROTTER A FRANKE COMPANY - Parkstrasse 1-5 - Ludwigsfelde Brandenburg 14974 - GERMANY - - 00-50-C2 (hex) Condre Corporation - 5EE000-5EEFFF (base 16) Condre Corporation - 15151 Technology Drive - Eden Prairie Minnesota 55344 - UNITED STATES - - 00-50-C2 (hex) pikkerton GmbH - 5EF000-5EFFFF (base 16) pikkerton GmbH - Lessingstrasse 79 - Berlin 13158 - GERMANY - - 00-50-C2 (hex) DIAS Infrared GmbH - 5F0000-5F0FFF (base 16) DIAS Infrared GmbH - Gostritzer Str. 63 - Dresden Saxony 01217 - GERMANY - - 00-50-C2 (hex) Technomarine JSC - 5F1000-5F1FFF (base 16) Technomarine JSC - 3, Gapsalskaja Str. - Saint-Petersburg 198035 - RUSSIAN FEDERATION - - 00-50-C2 (hex) ESEM Grünau GmbH & Co. KG - 5F2000-5F2FFF (base 16) ESEM Grünau GmbH & Co. KG - Dornierstraße 6 - Markdorf Baden-Württemberg 88677 - GERMANY - - 00-50-C2 (hex) POSNET Polska S.A. - 5F3000-5F3FFF (base 16) POSNET Polska S.A. - ul. Municypalna 33 - Warszawa 02-281 - POLAND - - 00-50-C2 (hex) TeamProjects BV - 5F4000-5F4FFF (base 16) TeamProjects BV - Zonnebaan 42 - Utrecht 3542 EG - NETHERLANDS - - 00-50-C2 (hex) Genesis inc - 5F5000-5F5FFF (base 16) Genesis inc - #517 Ilsan-midas,775-1 Janghang-Dong, - Ilsandong-Gu - Goyang Gyeonggi 410-837 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) CAMBRIDGE CONSULTANTS LTD - 5F6000-5F6FFF (base 16) CAMBRIDGE CONSULTANTS LTD - SCIENCE PARK - MILTON ROAD - CAMBRIDGE ENGLAND CB4 0DW - UNITED KINGDOM - - 00-50-C2 (hex) Metrologic Group - 5F7000-5F7FFF (base 16) Metrologic Group - 6 ch du vieux chêne - Meylan Isère 38700 - FRANCE - - 00-50-C2 (hex) Grupo Epelsa S.L. - 5F8000-5F8FFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) ROTHARY Solutions AG - 5F9000-5F9FFF (base 16) ROTHARY Solutions AG - Hauptstrasse 84 - Kreuzlingen TG 8280 - SWITZERLAND - - 00-50-C2 (hex) LEA d.o.o. - 5FA000-5FAFFF (base 16) LEA d.o.o. - Finzgarjeva ulica 1a - Lesce 4248 - SLOVENIA - - 00-50-C2 (hex) All-Systems Electronics Pty Ltd - 5FB000-5FBFFF (base 16) All-Systems Electronics Pty Ltd - 16 Hope Street - SEVEN HILLS New South Wales 2147 - AUSTRALIA - - 00-50-C2 (hex) FilmLight Limited - 5FC000-5FCFFF (base 16) FilmLight Limited - 14-15 Manette Street - London W1D 4AP - UNITED KINGDOM - - 00-50-C2 (hex) MEG Electronic Inc. - 5FD000-5FDFFF (base 16) MEG Electronic Inc. - Bogazici Universitesi Kuzey Kampus - BUN Teknopark Kat:2 No:306 - Bebek Besiktas - TURKEY - - 00-50-C2 (hex) Novacomm - 5FE000-5FEFFF (base 16) Novacomm - R. Benjui , 79 - V. Isa (Interlagos) - São Paulo SP 04689-000 - BRAZIL - - 00-50-C2 (hex) Gazelle Monitoring Systems - 5FF000-5FFFFF (base 16) Gazelle Monitoring Systems - Level 11, Tower B, 821 Pacific Hwy - Chatswood NSW 2067 - AUSTRALIA - - 00-50-C2 (hex) Protec Fire Detection plc - 600000-600FFF (base 16) Protec Fire Detection plc - Protec House - Churchill Way - Nelson Lancashire BB9 6LQ - UNITED KINGDOM - - 00-50-C2 (hex) MedAvant Healthcare - 601000-601FFF (base 16) MedAvant Healthcare - 2533 Centennial Blvd - Suite B - Jeffersonville IN 47130 - UNITED STATES - - 00-50-C2 (hex) CHAUVIN ARNOUX - 602000-602FFF (base 16) CHAUVIN ARNOUX - la queue Devée - REUX PONT L'EVEQUE 14130 - FRANCE - - 00-50-C2 (hex) Cerus Corp - 603000-603FFF (base 16) Cerus Corp - 2411 Stanwell Dr - Concord CA 94520 - UNITED STATES - - 00-50-C2 (hex) HCJB Global - 604000-604FFF (base 16) HCJB Global - 2830 South 17th St. - Elkhart IN 46517-4008 - UNITED STATES - - 00-50-C2 (hex) Swistec GmbH - 605000-605FFF (base 16) Swistec GmbH - Graue-Burg-Strasse 24-26 - Bornheim D-53332 - GERMANY - - 00-50-C2 (hex) Shenzhen Huazhong Technology Inc - 606000-606FFF (base 16) Shenzhen Huazhong Technology Inc - Room 1710,17/F,Tower B,phase 1, - Hi-Tech plaza,Tian An Cyber Park - shenzhen Guangdong 518048 - CHINA - - 00-50-C2 (hex) Telecom FM - 607000-607FFF (base 16) Telecom FM - 895 Plymouth Road - Slough Berkshire SL1 4LP - UNITED KINGDOM - - 00-50-C2 (hex) Silex Industrial Automation Ltd. - 608000-608FFF (base 16) Silex Industrial Automation Ltd. - Gyepsor u. 1. - Budapest Pest megye 1211 - HUNGARY - - 00-50-C2 (hex) Toptech Systems, Inc. - 609000-609FFF (base 16) Toptech Systems, Inc. - 280 Hunt Park Cove - Longwood FL 32750 - UNITED STATES - - 00-50-C2 (hex) Gradual Tecnologia Ltda. - 60A000-60AFFF (base 16) Gradual Tecnologia Ltda. - Rua Attilio Giaretta, 110 - Itatiba SP 13257-584 - BRAZIL - - 00-50-C2 (hex) Shanghai QianJin Electronic Equipment Co. Ltd. - 60B000-60BFFF (base 16) Shanghai QianJin Electronic Equipment Co. Ltd. - 7028 Rockrose Ter - Carlsbad CA 92011 - UNITED STATES - - 00-50-C2 (hex) IDENTIC AB - 60C000-60CFFF (base 16) IDENTIC AB - Box 143 - Vallentuna 18630 - SWEDEN - - 00-50-C2 (hex) Sicon s.r.l. - 60D000-60DFFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) Automation and Control Technology, Inc. - 60E000-60EFFF (base 16) Automation and Control Technology, Inc. - 6141 Avery Rd - PO Box 3667 - Dublin OH 43016 - UNITED STATES - - 00-50-C2 (hex) Kommunikations- & Sicherheitssysteme Gesellschaft m.b.H - 60F000-60FFFF (base 16) Kommunikations- & Sicherheitssysteme Gesellschaft m.b.H - Computerstr. 6 - Vienna 1100 - AUSTRIA - - 00-50-C2 (hex) FDT Manufacturing, LLC - 610000-610FFF (base 16) FDT Manufacturing, LLC - 1005 Alderman Dr - STE 107 - Alpharetta GA 30005 - UNITED STATES - - 00-50-C2 (hex) Brookhaven National Laboratory - 611000-611FFF (base 16) Brookhaven National Laboratory - Bldg 911B - Upton NY 11973 - UNITED STATES - - 00-50-C2 (hex) IHP-GmbH - 612000-612FFF (base 16) IHP-GmbH - Im Technologiepark 25 - Frankfurt (Oder) Brandenburg 15236 - GERMANY - - 00-50-C2 (hex) TATTILE SRL - 613000-613FFF (base 16) TATTILE SRL - VIA TRENTO,127/129 - CAPRIANO DEL COLLE BRESCIA 25020 - ITALY - - 00-50-C2 (hex) Proserv - 614000-614FFF (base 16) Proserv - Strandveien 43 - N-7042 Trondheim - NORWAY - - 00-50-C2 (hex) Axis Electronics - 615000-615FFF (base 16) Axis Electronics - Bedford Heights, - Manton Lane, - Bedford Bedfordshire MK41 7NY - UNITED KINGDOM - - 00-50-C2 (hex) Honeywell - 616000-616FFF (base 16) Honeywell - 13350 U.S. Hwy 19 North - MS/522-4 - Clearwater FL 33764-7290 - UNITED STATES - - 00-50-C2 (hex) NARINET, INC. - 617000-617FFF (base 16) NARINET, INC. - Dept of Comp. Eng. CNU - 220 Gung-dong, Yuseong-gu - Daejeon 305-764 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Intergrated Security Mfg. Ltd - 618000-618FFF (base 16) Intergrated Security Mfg. Ltd - 25-29 The Bell Centre - Newton Road - Crawley West Sussex RH10 9FZ - UNITED KINGDOM - - 00-50-C2 (hex) Linkbit, Inc. - 619000-619FFF (base 16) Linkbit, Inc. - 3180 De La Cruz Blvd., Suite 200 - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) Communication Components Inc. - 61A000-61AFFF (base 16) Communication Components Inc. - 89 Leuning Street - South Hackensack NJ 07606 - UNITED STATES - - 00-50-C2 (hex) NCI Technologies Inc. - 61B000-61BFFF (base 16) NCI Technologies Inc. - 636 Cure Boivin Blvd. - Boisbriand Quebec J7G 2A7 - CANADA - - 00-50-C2 (hex) TestPro Systems, Inc. - 61C000-61CFFF (base 16) TestPro Systems, Inc. - 2119 Metro Circle - Huntsville Alabama 35801 - UNITED STATES - - 00-50-C2 (hex) Sutus Inc - 61D000-61DFFF (base 16) Sutus Inc - 50-1055 West 14th Street - North Vancouver British Columbia V7P 3P2 - CANADA - - 00-50-C2 (hex) LESTER ELECTRONICS LTD - 61E000-61EFFF (base 16) LESTER ELECTRONICS LTD - UNIT 3, WYCLIFFE INDUSTRIAL EST - LUTTERWORTH - LEICESTER UK LE17 4HG - UNITED KINGDOM - - 00-50-C2 (hex) Imagine Communications - 61F000-61FFFF (base 16) Imagine Communications - 45 Hamelacha St. P.O.Box 8447 - Netanya 42504 - ISRAEL - - 00-50-C2 (hex) Harman/Becker Automotive Systems GmbH - 620000-620FFF (base 16) Harman/Becker Automotive Systems GmbH - Becker-Göring-Straße 16 - Karlsbad 76307 - GERMANY - - 00-50-C2 (hex) Version-T - 621000-621FFF (base 16) Version-T - 1 per. Pestelya 50A - Kaluga Kaluga region 248003 - RUSSIAN FEDERATION - - 00-50-C2 (hex) 2N TELEKOMUNIKACE a.s. - 622000-622FFF (base 16) 2N TELEKOMUNIKACE a.s. - Modranska 621 - Prague CZ 143 01 - CZECH REPUBLIC - - 00-50-C2 (hex) SAFELINE SL - 623000-623FFF (base 16) SAFELINE SL - EDIFICIO SAFELINE - COOPERATIVA 24 - MATARO BARCELONA 08302 - SPAIN - - 00-50-C2 (hex) Comtest Networks - 624000-624FFF (base 16) Comtest Networks - 1 Raymond Street - Ottawa Ontario K1R 1A2 - CANADA - - 00-50-C2 (hex) EBNeuro SpA - 625000-625FFF (base 16) EBNeuro SpA - VIA PIETRO FANFANI 97/a - FIRENZE 50127 - ITALY - - 00-50-C2 (hex) Winsys Informatica ltda - 626000-626FFF (base 16) Winsys Informatica ltda - rua luis goes , 672 - Mirandopolis - São Paulo 04043-050 - BRAZIL - - 00-50-C2 (hex) JungleSystem Co., Ltd. - 627000-627FFF (base 16) JungleSystem Co., Ltd. - 4F Naewae Bldg.382-5 - Yatap Bundang - Sungnam Gyeonggi 463-827 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) DARE Development - 628000-628FFF (base 16) DARE Development - Vijzelmolenlaan 7 - Woerden UT 3447 GX - NETHERLANDS - - 00-50-C2 (hex) MacDonald Humfrey (Products) Ltd - 629000-629FFF (base 16) MacDonald Humfrey (Products) Ltd - Progress Manor, - Bolton Road, - Luton Beds LU13HY - UNITED KINGDOM - - 00-50-C2 (hex) Prisma Engineering srl - 62A000-62AFFF (base 16) Prisma Engineering srl - Via Petrocchi, 4 - Milano MI 20127 - ITALY - - 00-50-C2 (hex) First Control Systems AB - 62B000-62BFFF (base 16) First Control Systems AB - Ängsgärdg 4 - VästerÃ¥s Västmanland SE-72130 - SWEDEN - - 00-50-C2 (hex) AirMatrix, Inc. - 62C000-62CFFF (base 16) AirMatrix, Inc. - 12775 LBJ Drive - Brenham Texas 77833 - UNITED STATES - - 00-50-C2 (hex) Procon Electronics - 62D000-62DFFF (base 16) Procon Electronics - PO Box 164 - Seven Hills - Sydney NSW 1730 - AUSTRALIA - - 00-50-C2 (hex) TDM Ingénierie - 62E000-62EFFF (base 16) TDM Ingénierie - 6 av H. Becquerel - Mérignac Aquitaine 33700 - FRANCE - - 00-50-C2 (hex) QES - 62F000-62FFFF (base 16) QES - Joensuunkatu 13 - Salo 24100 - FINLAND - - 00-50-C2 (hex) Aurora Flight Sciences - 630000-630FFF (base 16) Aurora Flight Sciences - 9950 Wakeman Drive - Manassas VA 20110 - UNITED STATES - - 00-50-C2 (hex) Fraunhofer IIS - 631000-631FFF (base 16) Fraunhofer IIS - Am Wolfsmantel 33 - Erlangen Bayern 91058 - GERMANY - - 00-50-C2 (hex) RoseTechnology A/S - 632000-632FFF (base 16) RoseTechnology A/S - EllegÃ¥rdvej 36 - Sønderborg 6400 - DENMARK - - 00-50-C2 (hex) Rice University - 633000-633FFF (base 16) Rice University - 6100 Main Street MS 380 - Houston Texas 77005 - UNITED STATES - - 00-50-C2 (hex) Sohon Inc - 634000-634FFF (base 16) Sohon Inc - 4-12-13-201 chigasaki-minami - tudukiku - yokohama kanagawa-prf 224-0037 - JAPAN - - 00-50-C2 (hex) Shockfish SA - 635000-635FFF (base 16) Shockfish SA - Parc Scientifique - PSE C - Lausanne VD 1015 - SWITZERLAND - - 00-50-C2 (hex) dSPACE GmbH - 636000-636FFF (base 16) dSPACE GmbH - Techologiepark 25 - Paderborn North Rhine-Westphalia 33100 - GERMANY - - 00-50-C2 (hex) Omnitrol Networks, Inc. - 637000-637FFF (base 16) Omnitrol Networks, Inc. - 2063 Landings Drive - Mountainview CA 94043 - UNITED STATES - - 00-50-C2 (hex) HUNGAROCOM Telecommunication Ltd. - 638000-638FFF (base 16) HUNGAROCOM Telecommunication Ltd. - Petzval Jozsef u. 52. - Budapest 1119 - HUNGARY - - 00-50-C2 (hex) Qstreams Networks Inc. - 639000-639FFF (base 16) Qstreams Networks Inc. - 2301 Dorsey Rd. - Suite 108 - Glen Burnie MD 21061 - UNITED STATES - - 00-50-C2 (hex) 3DSP Corporation - 63A000-63AFFF (base 16) 3DSP Corporation - 16271 Laguna Canyon Road - Suite 200 - Irvine California 92618 - UNITED STATES - - 00-50-C2 (hex) Powis Corporation - 63B000-63BFFF (base 16) Powis Corporation - 2301 NW. Jefferson - Blue Springs MO 64015 - UNITED STATES - - 00-50-C2 (hex) dPict Imaging, Inc. - 63C000-63CFFF (base 16) dPict Imaging, Inc. - 3815 River Crossing Pkwy - Suite 100 - Indianapolis IN 46240 - UNITED STATES - - 00-50-C2 (hex) IDERs Inc - 63D000-63DFFF (base 16) IDERs Inc - 100-137 Innovation Drive - Winnipeg Manitoba R3T6B6 - CANADA - - 00-50-C2 (hex) T2 Communication Ltd - 63E000-63EFFF (base 16) T2 Communication Ltd - Unit A, Wellfleet Industrial Park - Waterloo Road, Yardley - Birmingham West Midlands B25 8LH - UNITED KINGDOM - - 00-50-C2 (hex) Speech Technology Center, Ltd. - 63F000-63FFFF (base 16) Speech Technology Center, Ltd. - 4 Krasutskogo st. - St.Petersburg 196084 - RUSSIAN FEDERATION - - 00-50-C2 (hex) IAC - 640000-640FFF (base 16) IAC - 13029 Danielson Suite 201 - Poway Ca. 92064 - UNITED STATES - - 00-50-C2 (hex) NEO Information Systems Co., Ltd. - 641000-641FFF (base 16) NEO Information Systems Co., Ltd. - 609, Junganginduspia, #517-13, Sangdaeweon-Dong, Jungweon-Gu - Seongnam Gyunggi-Do 462-713 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Stanton Technologies Sdn Bhd - 642000-642FFF (base 16) Stanton Technologies Sdn Bhd - Suite 3, 4th Floor, NB Place, - 11-A, Jalan Gottlieb, 10350 - Penang 10350 - MALAYSIA - - 00-50-C2 (hex) Enatel Limited - 643000-643FFF (base 16) Enatel Limited - 66 Treffers Road - Christchurch 8042 - NEW ZEALAND - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 644000-644FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) The Software Group Limited - 645000-645FFF (base 16) The Software Group Limited - 11 Pemberton Lane - Shanty Bay Ontario L0L 2L0 - CANADA - - 00-50-C2 (hex) TRUTOUCH TECHNOLOGIES INC - 646000-646FFF (base 16) TRUTOUCH TECHNOLOGIES INC - 800 BRADBURY DR SE - SUITE 219 - ALBUQUERQUE NM 87106-4310 - UNITED STATES - - 00-50-C2 (hex) R&D Technology Solutionz Limited - 647000-647FFF (base 16) R&D Technology Solutionz Limited - 1st Floor - 156 Broadway Avenue - Palmerston North Manawatu 4440 - NEW ZEALAND - - 00-50-C2 (hex) Fidelity Comtech, Inc. - 648000-648FFF (base 16) Fidelity Comtech, Inc. - 2400 Trade Centre Avenue - Longmont CO 80503 - UNITED STATES - - 00-50-C2 (hex) Pan-STARRS - 649000-649FFF (base 16) Pan-STARRS - 2680 Woodlawn Dr. - Honolulu HI 96822 - UNITED STATES - - 00-50-C2 (hex) CPqD - 64A000-64AFFF (base 16) CPqD - Rod. SP-340 Campinas Mogi-Mirim - Km 118.5 - Campinas SP 13086902 - BRAZIL - - 00-50-C2 (hex) MangoDSP - 64B000-64BFFF (base 16) MangoDSP - Hartom 8 - Jerusalem 45116 - ISRAEL - - 00-50-C2 (hex) CIS Corporation - 64C000-64CFFF (base 16) CIS Corporation - 539-5, Higashiasakawa-machi - Hachioji-shi Tokyo 193-0834 - JAPAN - - 00-50-C2 (hex) Tera Information System Labs - 64D000-64DFFF (base 16) Tera Information System Labs - 198 Allendale Road Suite 401 - King of Prussia PA 19406 - UNITED STATES - - 00-50-C2 (hex) Northern Power - 64E000-64EFFF (base 16) Northern Power - 182 Mad River Park - Waitsfield VT 05673 - UNITED STATES - - 00-50-C2 (hex) MA Lighting Technology GmbH - 64F000-64FFFF (base 16) MA Lighting Technology GmbH - Dachdeckerstr. 16 - Waldbuettelbrunn Bayern 97297 - GERMANY - - 00-50-C2 (hex) Liquid Breaker, LLC - 650000-650FFF (base 16) Liquid Breaker, LLC - 2221 Rutherford Rd. - Carlsbad California 92008 - UNITED STATES - - 00-50-C2 (hex) STAER SPA - 651000-651FFF (base 16) STAER SPA - VIA TIBURTINA,1266 - ROMA 00131 - ITALY - - 00-50-C2 (hex) Wideco Sweden AB - 652000-652FFF (base 16) Wideco Sweden AB - Företagsgatan 7 - BorÃ¥s Viared 50494 - SWEDEN - - 00-50-C2 (hex) Doble Engineering - 653000-653FFF (base 16) Doble Engineering - 85 Walnut St - Watertown MA 02472 - UNITED STATES - - 00-50-C2 (hex) PaloDEx Group Oy - 654000-654FFF (base 16) PaloDEx Group Oy - Nahkelantie 160 - P.O.Box 160 - TUUSULA FIN 04301 - FINLAND - - 00-50-C2 (hex) Physik Instrumente (PI) GmbH&Co.KG - 655000-655FFF (base 16) Physik Instrumente (PI) GmbH&Co.KG - Auf der Roemerstrasse 1 - Karlsruhe 76228 - GERMANY - - 00-50-C2 (hex) LDA Audio Video Profesional - 656000-656FFF (base 16) LDA Audio Video Profesional - C/Severo Ochoa, 31 - Parque Tecnologico de Andalucia - Campanillas Malaga 29590 - SPAIN - - 00-50-C2 (hex) MONYTEL S.A. - 657000-657FFF (base 16) MONYTEL S.A. - Estrada dos Romeiros Km 38,5 n.162 - Santana de Parnaiba São Paulo 06501001 - BRAZIL - - 00-50-C2 (hex) OpenPKG GmbH - 658000-658FFF (base 16) OpenPKG GmbH - Weblinger Weg 28 - Dachau 85221 - GERMANY - - 00-50-C2 (hex) Dorsett Technologies, Inc. - 659000-659FFF (base 16) Dorsett Technologies, Inc. - 100 Woodlyn Drive - Yadkinville North Carolina 27055 - UNITED STATES - - 00-50-C2 (hex) Hisstema AB - 65A000-65AFFF (base 16) Hisstema AB - Hantverksvägen 13 - Södertälje S-151 65 - SWEDEN - - 00-50-C2 (hex) Silverbrook Research - 65B000-65BFFF (base 16) Silverbrook Research - 393 Darling St - Balmain NSW 2041 - AUSTRALIA - - 00-50-C2 (hex) VTZ d.o.o. - 65C000-65CFFF (base 16) VTZ d.o.o. - Koprska 96 - Ljubljana 1000 - SLOVENIA - - 00-50-C2 (hex) Redfone Communications LLC - 65D000-65DFFF (base 16) Redfone Communications LLC - 9941 West Jessamine Street - Miami Fl. 33157 - UNITED STATES - - 00-50-C2 (hex) Cantion A/S - 65E000-65EFFF (base 16) Cantion A/S - Skjernvej 4A - Aalborg DK 9220 - DENMARK - - 00-50-C2 (hex) Invocon, Inc. - 65F000-65FFFF (base 16) Invocon, Inc. - 19221 IH-45 South Ste. 530 - Conroe TX 77385 - UNITED STATES - - 00-50-C2 (hex) IZISOFT - 660000-660FFF (base 16) IZISOFT - 1116 Hanshin IT Tower 235 - Guro-gu Guro-3dong - Seoul 152-768 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) P.C.E. - 661000-661FFF (base 16) P.C.E. - Via Pietro Menis 14 - Treppo Grande UD 33010 - ITALY - - 00-50-C2 (hex) Asia Pacific Card & System Sdn Bhd - 662000-662FFF (base 16) Asia Pacific Card & System Sdn Bhd - No 2, Jalan 1, Bandar Sultan Suleiman, Taiwanese Industrial Park - Port Klang Selangor 42000 - MALAYSIA - - 00-50-C2 (hex) COE Limited - 663000-663FFF (base 16) COE Limited - Photon House - Percy Sreet - Leeds West Yorkshire LS12 1EG - UNITED KINGDOM - - 00-50-C2 (hex) Westel Wireless Systems - 664000-664FFF (base 16) Westel Wireless Systems - Level 5, 25 Bligh St - Sydney NSW 2000 - AUSTRALIA - - 00-50-C2 (hex) NetworkSound, Inc - 665000-665FFF (base 16) NetworkSound, Inc - 2381 Zanker Road, Ste 120 - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) Xworks NZ Limited - 666000-666FFF (base 16) Xworks NZ Limited - Level 1 - 29 Alexandra st - Te Awamutu North Island 3800 - NEW ZEALAND - - 00-50-C2 (hex) Vocality International Ltd - 667000-667FFF (base 16) Vocality International Ltd - Lydling Barn - Puttenham Lane - Shackleford Surrey GU8 6AP - UNITED KINGDOM - - 00-50-C2 (hex) Keith & Koep GmbH - 668000-668FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) DSP DESIGN - 669000-669FFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - 66A000-66AFFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park - Torch Hi-Tech Development Zone - Xiamen Fujian 361005 - CHINA - - 00-50-C2 (hex) flsystem - 66B000-66BFFF (base 16) flsystem - Rm911,RegentOfficetel,547-8,Kuui-dong,Kwangjjin-gu - seoul 143-709 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) DESY - 66C000-66CFFF (base 16) DESY - Notkestrasse 85 - Hamburg Hamburg 22607 - GERMANY - - 00-50-C2 (hex) DIGITEK S.p.A. - 66D000-66DFFF (base 16) DIGITEK S.p.A. - via Romagnoli, 24 - Concordia sulla Secchia MODENA 41033 - ITALY - - 00-50-C2 (hex) Linear Systems Ltd. - 66E000-66EFFF (base 16) Linear Systems Ltd. - Unit# 1 - 1717 Dublin Avenue - Winnipeg MB R3H 0H2 - CANADA - - 00-50-C2 (hex) Nilan A/S - 66F000-66FFFF (base 16) Nilan A/S - Nilanvej 2 - Hedensted Vejle amt 8722 - DENMARK - - 00-50-C2 (hex) Naim Audio - 670000-670FFF (base 16) Naim Audio - Southampton Road - Salisbury Wiltshire SP1 2LN - UNITED KINGDOM - - 00-50-C2 (hex) Skyline Products, Inc - 671000-671FFF (base 16) Skyline Products, Inc - 2903 Delta Drive - Colorado Springs CO 80910 - UNITED STATES - - 00-50-C2 (hex) DDS Elettronica srl - 672000-672FFF (base 16) DDS Elettronica srl - Via Nicolò Biondo 171 - Modena 41100 - ITALY - - 00-50-C2 (hex) Ferrari electronic AG - 673000-673FFF (base 16) Ferrari electronic AG - Ruhlsdorfer Str. 138 - TELTOW Brandenburg 14513 - GERMANY - - 00-50-C2 (hex) Protech Optronics Co., Ltd. - 674000-674FFF (base 16) Protech Optronics Co., Ltd. - 4th Floor, No.82-3, Dongshun Street - Shulin City Taipei county 238 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Kenton Research Ltd - 675000-675FFF (base 16) Kenton Research Ltd - Unit 19 Bourne Industrial Park - Crayford Kent DA1 4BZ - UNITED KINGDOM - - 00-50-C2 (hex) EDS - 676000-676FFF (base 16) EDS - 100 Winchester Cir - Los Gatos Ca 95032 - UNITED STATES - - 00-50-C2 (hex) ProconX Pty Ltd - 677000-677FFF (base 16) ProconX Pty Ltd - PO Box 791 - Sumner Park BC QLD 4074 - AUSTRALIA - - 00-50-C2 (hex) IHM - 678000-678FFF (base 16) IHM - IHM - Soborg Copenhagen 2860 - DENMARK - - 00-50-C2 (hex) Industrial Vacuum Systems - 679000-679FFF (base 16) Industrial Vacuum Systems - 3974 Linden Avenue SE - Grand Rapids Michigan 49548 - UNITED STATES - - 00-50-C2 (hex) CC Systems AB - 67A000-67AFFF (base 16) CC Systems AB - Box 83 - Alfta 82222 - SWEDEN - - 00-50-C2 (hex) Sparton Electronics - 67B000-67BFFF (base 16) Sparton Electronics - 2400 East Ganson Street - Jackson MI 49202 - UNITED STATES - - 00-50-C2 (hex) Aircell - 67C000-67CFFF (base 16) Aircell - 1172 Century Drive - Building B, Suite 280 - Louisville Colorado 80027 - UNITED STATES - - 00-50-C2 (hex) ESA Messtechnik GmbH - 67D000-67DFFF (base 16) ESA Messtechnik GmbH - Schlossstrasse 119 - Olching D-82140 - GERMANY - - 00-50-C2 (hex) SAIA Burgess Controls AG - 67E000-67EFFF (base 16) SAIA Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 67F000-67FFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Honey Network Research Limited - 680000-680FFF (base 16) Honey Network Research Limited - Bedford i-Lab - Stannard Way - Bedford Bedfordshire MK44 3RZ - UNITED KINGDOM - - 00-50-C2 (hex) Owasys Advanced Wireless Devices - 681000-681FFF (base 16) Owasys Advanced Wireless Devices - Parque Tecnologico, 207-B - Zamudio Vizcaya E-48170 - SPAIN - - 00-50-C2 (hex) Commet AB - 682000-682FFF (base 16) Commet AB - Box 706 - Hammarbacken 4B - Sollentuna 19127 - SWEDEN - - 00-50-C2 (hex) MEGGITT Safety System - 683000-683FFF (base 16) MEGGITT Safety System - 1915 Voyager Avenue - Simi Valley Ca. 93063-3349 - UNITED STATES - - 00-50-C2 (hex) REASON Tecnologia S.A. - 684000-684FFF (base 16) REASON Tecnologia S.A. - R. Delminda Silveira, 855 - Bairro: Agronômica - Florianópolis Santa Catarina 88025-500 - BRAZIL - - 00-50-C2 (hex) Datamars SA - 685000-685FFF (base 16) Datamars SA - via ai Prati - Bedano Ticino 6930 - SWITZERLAND - - 00-50-C2 (hex) ANNAX Anzeigesysteme GmbH - 686000-686FFF (base 16) ANNAX Anzeigesysteme GmbH - Wettersteinstrasse 18 - Taufkirchen Deutschland 82024 - GERMANY - - 00-50-C2 (hex) Access Specialties, Inc - 687000-687FFF (base 16) Access Specialties, Inc - 10255 Inver Grove Trail - Inver Grove Heights MN 55077 - UNITED STATES - - 00-50-C2 (hex) Elk Products - 688000-688FFF (base 16) Elk Products - 3266 Highway 70 West - P.O. Box 100 - Hildebran NC 28637 - UNITED STATES - - 00-50-C2 (hex) RF Code, Inc. - 689000-689FFF (base 16) RF Code, Inc. - 1250 S. Clearview Ave. - Suite 104 - Mesa AZ 85209 - UNITED STATES - - 00-50-C2 (hex) Zhuhai Jiahe Electronics Co.,LTD - 68A000-68AFFF (base 16) Zhuhai Jiahe Electronics Co.,LTD - 8/F,BlockA,Tsinghua Science Park,101 College Road,TangJia - Zhuahi Guangdong 519080 - CHINA - - 00-50-C2 (hex) SIMTEK INC. - 68B000-68BFFF (base 16) SIMTEK INC. - 1505 ROYAL PARKWAY - EULESS TEXAS 76040 - UNITED STATES - - 00-50-C2 (hex) Isochron Inc - 68C000-68CFFF (base 16) Isochron Inc - 11044 Research Blvd - Suite C220 - Austin TX 78759 - UNITED STATES - - 00-50-C2 (hex) CXR Larus Corporation - 68D000-68DFFF (base 16) CXR Larus Corporation - 894 Faulstich Court - San Jose CA 95112 - UNITED STATES - - 00-50-C2 (hex) SELCO - 68E000-68EFFF (base 16) SELCO - ZI DU VAL D OMBREE - COMBREE SA 49520 - FRANCE - - 00-50-C2 (hex) BERTRONIC SRL - 68F000-68FFFF (base 16) BERTRONIC SRL - VIA SILVIO PELLICO 26 - STEZZANO BERGAMO 24040 - ITALY - - 00-50-C2 (hex) GHL Systems Berhad - 690000-690FFF (base 16) GHL Systems Berhad - L5-E-7B, Enterprise 4 - Technology Park Malaysia, Bukit Jalil - Kuala Lumpur Wilayah 57000 - MALAYSIA - - 00-50-C2 (hex) Interopix, Inc. - 691000-691FFF (base 16) Interopix, Inc. - 5050 Robert J Mathews Pkwy - El Dorado Hills CA 95762 - UNITED STATES - - 00-50-C2 (hex) Mate Media Access Technologies - 692000-692FFF (base 16) Mate Media Access Technologies - 4, Hachoresh Street - Yahud Center 56470 - ISRAEL - - 00-50-C2 (hex) Tech Comm, Inc. - 693000-693FFF (base 16) Tech Comm, Inc. - 5010 No. Hiatus Road - Sunrise FL 33351 - UNITED STATES - - 00-50-C2 (hex) Initel srl - 694000-694FFF (base 16) Initel srl - Via Battisti 22 - Cesano Maderno Milano 20031 - ITALY - - 00-50-C2 (hex) Purelink Technology, inc. - 695000-695FFF (base 16) Purelink Technology, inc. - 3333 Queen Mary, suite 525 - Montreal Quebec H3V1A2 - CANADA - - 00-50-C2 (hex) Casabyte Inc. - 696000-696FFF (base 16) Casabyte Inc. - POB 10127 - 2801 Prosperity Road - Blacksburg VA 24060 - UNITED STATES - - 00-50-C2 (hex) Monarch Instrument - 697000-697FFF (base 16) Monarch Instrument - 15 Columbia Drive - Amherst NH 03031 - UNITED STATES - - 00-50-C2 (hex) Navtech Radar Ltd - 698000-698FFF (base 16) Navtech Radar Ltd - 16 Home Farm - Ardington - Wantage Oxon OX12 8PD - UNITED KINGDOM - - 00-50-C2 (hex) Bulletendpoints Enterprises Inc - 699000-699FFF (base 16) Bulletendpoints Enterprises Inc - 16 finch ave - Dollars des ormeaux quebec H9a3g8 - CANADA - - 00-50-C2 (hex) StoreTech Limited - 69A000-69AFFF (base 16) StoreTech Limited - 73 - 75 Upper Richmond Road - Putney London SW15 2SR - UNITED KINGDOM - - 00-50-C2 (hex) Tsien (UK) Ltd - 69B000-69BFFF (base 16) Tsien (UK) Ltd - Zion Building - Park Street - Chatteris Cambs PE16 6AE - UNITED KINGDOM - - 00-50-C2 (hex) Bug Labs, Inc. - 69C000-69CFFF (base 16) Bug Labs, Inc. - 915 Broadway - Suite 1100 - New York NY 10010 - UNITED STATES - - 00-50-C2 (hex) Dvation.co.,Ltd - 69D000-69DFFF (base 16) Dvation.co.,Ltd - Room506,5F Solive Bldg,333-2 - Doksan-Dong, Keumchun-Gu - SEOUL 153-010 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Ideus AB - 69E000-69EFFF (base 16) Ideus AB - Box 133 - Skövde SE-54123 - SWEDEN - - 00-50-C2 (hex) Total RF, LLC - 69F000-69FFFF (base 16) Total RF, LLC - 777 American Drive - Bensalem PA 19020 - UNITED STATES - - 00-50-C2 (hex) GFP Lab S.r.l. - 6A0000-6A0FFF (base 16) GFP Lab S.r.l. - via Casalecchio 5 - Rimini RN 47924 - ITALY - - 00-50-C2 (hex) PRICOL LIMITED - 6A1000-6A1FFF (base 16) PRICOL LIMITED - 7-1-59/4, TURNING POINT COMPLEX - AMEERPET - HYDERABAD ANDHRA PRADESH 500016 - INDIA - - 00-50-C2 (hex) Cadi Scientific Pte Ltd - 6A2000-6A2FFF (base 16) Cadi Scientific Pte Ltd - 31 Ubi Road 1 Aztech Building - #03-00 - Singapore 408694 - SINGAPORE - - 00-50-C2 (hex) CreaTech Electronics Co. - 6A3000-6A3FFF (base 16) CreaTech Electronics Co. - 6126 Carlisle Ln. - League City TX 77573 - UNITED STATES - - 00-50-C2 (hex) TELETASK - 6A4000-6A4FFF (base 16) TELETASK - Ottergemsesteenweg-Zuid 729 - GENT Ooost-Vlaanderen 9000 - BELGIUM - - 00-50-C2 (hex) FHF Funke+Huster Fernsig GmbH - 6A5000-6A5FFF (base 16) FHF Funke+Huster Fernsig GmbH - Gewerbeallee 15-19 - Mülheim an der Ruhr NRW D-45478 - GERMANY - - 00-50-C2 (hex) Victory Concept Industries Ltd. - 6A6000-6A6FFF (base 16) Victory Concept Industries Ltd. - 4/F., CAC Tower - 165 Hoi Bun Road, - Kwun Tong Kowloon - HONG KONG - - 00-50-C2 (hex) Hoer GmbH & Co. Industrie-Electronic KG - 6A7000-6A7FFF (base 16) Hoer GmbH & Co. Industrie-Electronic KG - Mistelweg 8 - Berlin 12357 - GERMANY - - 00-50-C2 (hex) Delcan Technologies, Inc - 6A8000-6A8FFF (base 16) Delcan Technologies, Inc - 2055 Sugarloaf Circle, Suite 500 - Duluth GA 30097 - UNITED STATES - - 00-50-C2 (hex) Armida Technologies Corporation - 6A9000-6A9FFF (base 16) Armida Technologies Corporation - 2313 Lockhill Selma Rd #242 - San Antonio TX 78230 - UNITED STATES - - 00-50-C2 (hex) Ifox - Industria e Comercio Ltda - 6AA000-6AAFFF (base 16) Ifox - Industria e Comercio Ltda - Rua Chico Pontes, 329 - Vila Guilherme - São Paulo São Paulo 02067-000 - BRAZIL - - 00-50-C2 (hex) Softwareentwicklung - 6AB000-6ABFFF (base 16) Softwareentwicklung - Bluecherstraße 32 - Pforzheim Baden-Württemberg 75177 - GERMANY - - 00-50-C2 (hex) Thales UK - 6AC000-6ACFFF (base 16) Thales UK - Manor Royal - Crawley - London West Sussex RH10 9PZ - UNITED KINGDOM - - 00-50-C2 (hex) Heim- & Bürokommunikation - 6AD000-6ADFFF (base 16) Heim- & Bürokommunikation - Markt 6 - Altdöbern Brandenburg 03229 - GERMANY - - 00-50-C2 (hex) Qualisys AB - 6AE000-6AEFFF (base 16) Qualisys AB - Packhusgatan 6 - Gothenburg 41113 - SWEDEN - - 00-50-C2 (hex) Nanoradio AB - 6AF000-6AFFFF (base 16) Nanoradio AB - Torshamnsgatan 39 - Kista-Stockholm SE-16482 - SWEDEN - - 00-50-C2 (hex) Smart Key International Limited - 6B0000-6B0FFF (base 16) Smart Key International Limited - Unit F46, 5/F., Wah Lok Ind Ctr - 31-35 Shan Mei Street - Shatin NT HK - HONG KONG - - 00-50-C2 (hex) Burk Technology - 6B1000-6B1FFF (base 16) Burk Technology - 7 Beaver Brook Road - Littleton MA 01460 - UNITED STATES - - 00-50-C2 (hex) Edgeware AB - 6B2000-6B2FFF (base 16) Edgeware AB - Drottninggatan 61 - Stockholm 111 21 - SWEDEN - - 00-50-C2 (hex) 4RF Communications Ltd - 6B3000-6B3FFF (base 16) 4RF Communications Ltd - 26 Glover Street - Ngauranga Wellington 6031 - NEW ZEALAND - - 00-50-C2 (hex) SOMESCA - 6B4000-6B4FFF (base 16) SOMESCA - 80 rue Jean Jaurès - BOIS-COLOMBES 92270 - FRANCE - - 00-50-C2 (hex) TRIUMF - 6B5000-6B5FFF (base 16) TRIUMF - 4004 Wesbrook Mall - University of British Columbia - Vancouver BC V6T 2A3 - CANADA - - 00-50-C2 (hex) CommoDaS GmbH - 6B6000-6B6FFF (base 16) CommoDaS GmbH - Rosengarten 10 - Wedel Schlewig Holstein 22880 - GERMANY - - 00-50-C2 (hex) System LSI CO.Ltd. - 6B7000-6B7FFF (base 16) System LSI CO.Ltd. - Nisso 15 Bld. 4F - 2-17-19 Shinyokohama, Kohoku - Yokohama Kanagawa 222-0033 - JAPAN - - 00-50-C2 (hex) Epec Oy - 6B8000-6B8FFF (base 16) Epec Oy - P.O. Box 194 - Matinkatu 6 - Seinäjoki Etelä-Pohjanmaa 60101 - FINLAND - - 00-50-C2 (hex) unipo GmbH - 6B9000-6B9FFF (base 16) unipo GmbH - Pelarstrasse 21 - Michelstadt Hessen 64720 - GERMANY - - 00-50-C2 (hex) Fertron Controle e Automacao Industrial Ltda. - 6BA000-6BAFFF (base 16) Fertron Controle e Automacao Industrial Ltda. - Av. Cesar Mingossi, 108 - Jd. Palmeiras - Sertaozinho SP 14177-293 - BRAZIL - - 00-50-C2 (hex) Ele.Mag S.r.l. - 6BB000-6BBFFF (base 16) Ele.Mag S.r.l. - via Milano14 - Gorgonzola Milan 20064 - ITALY - - 00-50-C2 (hex) Paraytec Ltd - 6BC000-6BCFFF (base 16) Paraytec Ltd - 1a St George's Place - Tadcaster Road - York N Yorkshire YO24 1GN - UNITED KINGDOM - - 00-50-C2 (hex) Mitron Oy - 6BD000-6BDFFF (base 16) Mitron Oy - P.O. Box 113 - FORSSA HÄME FIN-30101 - FINLAND - - 00-50-C2 (hex) ESTEC Co.,Ltd. - 6BE000-6BEFFF (base 16) ESTEC Co.,Ltd. - 369-1, Kugu, Kasakake-cho - Midori-city Gunma 379-2312 - JAPAN - - 00-50-C2 (hex) Optoplan as - 6BF000-6BFFFF (base 16) Optoplan as - Haakon VII's gt. 17 - Trondheim 7041 - NORWAY - - 00-50-C2 (hex) GLOSTER SANTE EUROPE - 6C0000-6C0FFF (base 16) GLOSTER SANTE EUROPE - Prologue 1 - La Pyrénéenne - BP27201 - LABEGE HAUTE GARONNE 31672 - FRANCE - - 00-50-C2 (hex) RADIUS Sweden AB - 6C1000-6C1FFF (base 16) RADIUS Sweden AB - Tennv. 1 - Karlskrona Blekinge 371 50 - SWEDEN - - 00-50-C2 (hex) HoseoTelnet Inc... - 6C2000-6C2FFF (base 16) HoseoTelnet Inc... - Hoseo B/D 4F 608 Deungchon-3dong - Kangseo-gu - Seoul 157-731 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) iTRACS Corporation - 6C3000-6C3FFF (base 16) iTRACS Corporation - 1501 W. Fountainhead Parkway - Suite 190 - Tempe AZ 85282 - UNITED STATES - - 00-50-C2 (hex) REXXON GmbH - 6C4000-6C4FFF (base 16) REXXON GmbH - Zum Kesselort 53 - Kiel Schleswig-Holstein 24149 - GERMANY - - 00-50-C2 (hex) Oerlikon Contraves AG - 6C5000-6C5FFF (base 16) Oerlikon Contraves AG - Birchstrasse 155 - Zuerich CH-8050 - SWITZERLAND - - 00-50-C2 (hex) MedAvant Healthcare Solutions - 6C6000-6C6FFF (base 16) MedAvant Healthcare Solutions - 2533 Centennial Blvd., Suite B - Jeffersonville IN 47130 - UNITED STATES - - 00-50-C2 (hex) QuickCircuit Ltd. - 6C7000-6C7FFF (base 16) QuickCircuit Ltd. - 2 Piermark Drive - Albany - North Shore City Auckland 0269 - NEW ZEALAND - - 00-50-C2 (hex) B&S MEDIA CO., LTD. - 6C8000-6C8FFF (base 16) B&S MEDIA CO., LTD. - #702 JNK DIGITAL TOWER - 222-3, GURO-3DONG, GURO-GU - Seoul SEOUL 152-848 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) NETAMI - 6C9000-6C9FFF (base 16) NETAMI - 139-6,DORIM 1DONG - SEOUL YOUNG DUNG PO GU 150-081 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Dynamic Hearing Pty Ltd - 6CA000-6CAFFF (base 16) Dynamic Hearing Pty Ltd - 2 Chapel Street - Richmond VIC 3121 - AUSTRALIA - - 00-50-C2 (hex) Stream Processors - 6CB000-6CBFFF (base 16) Stream Processors - 455 DeGuigne Drive - Sunnyvale, CA 94085 - UNITED STATES - - 00-50-C2 (hex) Widmer Time Recorder Co., Inc. - 6CC000-6CCFFF (base 16) Widmer Time Recorder Co., Inc. - p.o. box 588 - hackensack nj 07602 - UNITED STATES - - 00-50-C2 (hex) RGM SPA - 6CD000-6CDFFF (base 16) RGM SPA - VIA BUCCARI 19-21 - GENOVA GE 16156 - ITALY - - 00-50-C2 (hex) EMITALL Surveillance S.A, - 6CE000-6CEFFF (base 16) EMITALL Surveillance S.A, - Rue du Théâtre 5 - Montreux Vaud 1820 - SWITZERLAND - - 00-50-C2 (hex) Microway - 6CF000-6CFFFF (base 16) Microway - 12 Richards Rd - Plymouth MA 02360 - UNITED STATES - - 00-50-C2 (hex) EDS Systemtechnik - 6D0000-6D0FFF (base 16) EDS Systemtechnik - Alexianergraben 23 - Aachen NRW 52064 - GERMANY - - 00-50-C2 (hex) Schnick-Schnack-Systems GmbH - 6D1000-6D1FFF (base 16) Schnick-Schnack-Systems GmbH - Heinrich Pesch Str. 14 - Koeln (Cologne) NRW 50739 - GERMANY - - 00-50-C2 (hex) Lumistar Incorporated - 6D2000-6D2FFF (base 16) Lumistar Incorporated - 2701 Loker Ave West - Suite 230 - Carlsbad CA 92010 - UNITED STATES - - 00-50-C2 (hex) DigiSensory technologies Pty Ltd - 6D3000-6D3FFF (base 16) DigiSensory technologies Pty Ltd - Suite 54, Level 3 - 89-97 Jones st - Ultimo New South Wales 2007 - AUSTRALIA - - 00-50-C2 (hex) Etani Electronics Co.,Ltd. - 6D4000-6D4FFF (base 16) Etani Electronics Co.,Ltd. - 1-10-15,Ohmori-Honcho, - Ohta-ku, Tokyo 143-0011 - JAPAN - - 00-50-C2 (hex) Becker Electronics GmbH - 6D5000-6D5FFF (base 16) Becker Electronics GmbH - Barbarastrasse 3 - Friedrichsthal 66299 - GERMANY - - 00-50-C2 (hex) ADL Electronics Ltd. - 6D6000-6D6FFF (base 16) ADL Electronics Ltd. - Bukharestskaya 31-3-85 - Saint-Petersburg 192071 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Mavenir System, Inc. - 6D7000-6D7FFF (base 16) Mavenir System, Inc. - 1651 N. Glenville Dr., Suite 201 - Richardson TX 75081 - UNITED STATES - - 00-50-C2 (hex) BL Healthcare, Inc. - 6D8000-6D8FFF (base 16) BL Healthcare, Inc. - 33 Commercial Street - Suite # 3 - Foxboro MA 02035 - UNITED STATES - - 00-50-C2 (hex) Ajeco Oy - 6D9000-6D9FFF (base 16) Ajeco Oy - Koronakatu 1A - Espoo Uusimaa Fi-02210 Esp - FINLAND - - 00-50-C2 (hex) Techno Fittings S.r.l. - 6DA000-6DAFFF (base 16) Techno Fittings S.r.l. - Via Michelangelo Tilli 53/A/6 - Rome 00156 - ITALY - - 00-50-C2 (hex) Gebhardt Ventilatoren GmbH - 6DB000-6DBFFF (base 16) Gebhardt Ventilatoren GmbH - Bahnhofstrasse 43 - Netzschkau Sachsen 08491 - GERMANY - - 00-50-C2 (hex) L-3 Communications Mobile-Vision, Inc. - 6DC000-6DCFFF (base 16) L-3 Communications Mobile-Vision, Inc. - 90 Fanny Rd. - Boonton NJ 07005 - UNITED STATES - - 00-50-C2 (hex) Zmicro Systems Inc - 6DD000-6DDFFF (base 16) Zmicro Systems Inc - 9830 Summers Ridge Rd - San Diego CA 92121 - UNITED STATES - - 00-50-C2 (hex) Laser Tools & Technics Corp. - 6DE000-6DEFFF (base 16) Laser Tools & Technics Corp. - No.121, Lane 99 - Pu-Ding Road - Hsin Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) QR Sciences Ltd - 6DF000-6DFFFF (base 16) QR Sciences Ltd - 8-10 Hamilton St - Cannington 6107 - AUSTRALIA - - 00-50-C2 (hex) FIRSTTRUST Co.,Ltd. - 6E0000-6E0FFF (base 16) FIRSTTRUST Co.,Ltd. - 2-10-25 Yokogawa-Cho - Nishi-Ku - Hiroshima 733-0011 - JAPAN - - 00-50-C2 (hex) NewOnSys Ltd. - 6E1000-6E1FFF (base 16) NewOnSys Ltd. - #607 Ilsan TechnoTown 1141-1 - Beakseok-Dong Ilsan-Gu - Goyang Gyunggi-Do 410-722 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) PHYTEC Messtechnik GmbH - 6E2000-6E2FFF (base 16) PHYTEC Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Miros AS - 6E3000-6E3FFF (base 16) Miros AS - Solbraaveien 20 - Asker Akershus 1383 - NORWAY - - 00-50-C2 (hex) MangoDSP - 6E4000-6E4FFF (base 16) MangoDSP - Hartom 8 - Jerusalem 45116 - ISRAEL - - 00-50-C2 (hex) Boeckeler Instruments, Inc. - 6E5000-6E5FFF (base 16) Boeckeler Instruments, Inc. - 4650 S. Butterfield Dr. - Tucson AZ 85714 - UNITED STATES - - 00-50-C2 (hex) Lanetco - 6E6000-6E6FFF (base 16) Lanetco - International Business Park - Archamps Haute savoie 74160 - FRANCE - - 00-50-C2 (hex) Axis Network Technology - 6E7000-6E7FFF (base 16) Axis Network Technology - Unit7, Midshires Business Park - Smeaton Close - Aylesbury Bucks HP19 8HL - UNITED KINGDOM - - 00-50-C2 (hex) Anymax - 6E8000-6E8FFF (base 16) Anymax - 9200 Voie des Clouets - Val de Reuil Eure 27100 - FRANCE - - 00-50-C2 (hex) Bando electronic communication Co.Lltd - 6E9000-6E9FFF (base 16) Bando electronic communication Co.Lltd - 152-4,chuneui-dong,wonmi-gu - buchon kyoungki-do 420-859 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) FIRSTEC SA - 6EA000-6EAFFF (base 16) FIRSTEC SA - CH. DU PONT DU CENTENAIRE 108 - PLAN LES OUATES GENEVA 1228 - SWITZERLAND - - 00-50-C2 (hex) Harrison Audio, LLC - 6EB000-6EBFFF (base 16) Harrison Audio, LLC - 1024 Firestone Pkwy - La Vergne TN 37086 - UNITED STATES - - 00-50-C2 (hex) Netistix Technologies Corporation - 6EC000-6ECFFF (base 16) Netistix Technologies Corporation - 275 Michael Cowpland Drive - Suite 200 - Kanata Ontario K2M 2G2 - CANADA - - 00-50-C2 (hex) Sechan Electronics, Inc. - 6ED000-6EDFFF (base 16) Sechan Electronics, Inc. - 525 Furnace Hills Pike - Lititz PA 17543 - UNITED STATES - - 00-50-C2 (hex) Interactive Electronic Systems - 6EE000-6EEFFF (base 16) Interactive Electronic Systems - 193-23 Salerno Ave. - Jamaica NY 11423 - UNITED STATES - - 00-50-C2 (hex) Pneumopartners LaenneXT SA - 6EF000-6EFFFF (base 16) Pneumopartners LaenneXT SA - 91b route des Romains - STRASBOURG Région Alsace F-67200 - FRANCE - - 00-50-C2 (hex) Stanley Security Solutions, Inc. - 6F0000-6F0FFF (base 16) Stanley Security Solutions, Inc. - 14670 Cumberland Road - Noblesville IN 46060 - UNITED STATES - - 00-50-C2 (hex) ITS Telecom - 6F1000-6F1FFF (base 16) ITS Telecom - 29 Hametzuda Street - Azur 58001 - ISRAEL - - 00-50-C2 (hex) Laser Electronics Ltd - 6F2000-6F2FFF (base 16) Laser Electronics Ltd - Gunby Road - Orby - Skegness Lincolnshire PE24 5HT - UNITED KINGDOM - - 00-50-C2 (hex) E3Switch LLC - 6F3000-6F3FFF (base 16) E3Switch LLC - 80 Coronado Ave - San Carlos CA 94070 - UNITED STATES - - 00-50-C2 (hex) Cryogenic Control Systems, Inc. - 6F4000-6F4FFF (base 16) Cryogenic Control Systems, Inc. - PO Box 7012 - Rancho Santa Fe CA 92067-7012 - UNITED STATES - - 00-50-C2 (hex) Kitron Microelectronics AB - 6F5000-6F5FFF (base 16) Kitron Microelectronics AB - P.O. Box 1052 - Jönköping SE-551 10 - SWEDEN - - 00-50-C2 (hex) AV SatCom AS - 6F6000-6F6FFF (base 16) AV SatCom AS - Martin Linges v 25 - P.O.Box 1 - Fornebu Bærum 1364 - NORWAY - - 00-50-C2 (hex) infoplan Gesellschaftfür Informationssysteme mbH - 6F7000-6F7FFF (base 16) infoplan Gesellschaftfür Informationssysteme mbH - Wallbergstraße 1 - Taufkirchen Bayern D-82024 - GERMANY - - 00-50-C2 (hex) RV Technology Limited - 6F8000-6F8FFF (base 16) RV Technology Limited - 12/F, Wilson House - 19 Wyndham Street Central - HONG KONG - - 00-50-C2 (hex) Revox GmbH - 6F9000-6F9FFF (base 16) Revox GmbH - Am Krebsgraben 15 - VS-Villingen Baden-Württemberg 78048 - GERMANY - - 00-50-C2 (hex) DCN - 6FA000-6FAFFF (base 16) DCN - DCNS SCCC/SIS Le Mourillon - TOULON 83000 - FRANCE - - 00-50-C2 (hex) WaveIP - 6FB000-6FBFFF (base 16) WaveIP - Teradion Industrial Park - Misgav 20179 - ISRAEL - - 00-50-C2 (hex) Acte Sp. z o.o. - 6FC000-6FCFFF (base 16) Acte Sp. z o.o. - ul. Krancowa 49 - Warsaw 02-493 - POLAND - - 00-50-C2 (hex) SAIA Burgess Controls AG - 6FD000-6FDFFF (base 16) SAIA Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Blue Origin - 6FE000-6FEFFF (base 16) Blue Origin - 21218 76th Ave. S - Kent WA 98032 - UNITED STATES - - 00-50-C2 (hex) St. Michael Strategies Inc. - 6FF000-6FFFFF (base 16) St. Michael Strategies Inc. - 701 Salaberry - Suite 201 - Chambly Quebec J3L 1R2 - CANADA - - 00-50-C2 (hex) GEM-MED SL - 700000-700FFF (base 16) GEM-MED SL - C/ Cartagena 245 5e Of. 5-6 - Barcelona ES08025 - SPAIN - - 00-50-C2 (hex) Keith & Koep GmbH - 701000-701FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) SPM Instrument AB - 702000-702FFF (base 16) SPM Instrument AB - Box 504 - Strängnäs SE-64525 - SWEDEN - - 00-50-C2 (hex) SAE IT-systems GmbH & Co. KG - 703000-703FFF (base 16) SAE IT-systems GmbH & Co. KG - Im Gewerbegebiet Pesch 14 - Köln NRW 50767 - GERMANY - - 00-50-C2 (hex) The Dini Group, La Jolla inc. - 704000-704FFF (base 16) The Dini Group, La Jolla inc. - 7469 Draper Ave. - La Jolla CA 92037 - UNITED STATES - - 00-50-C2 (hex) Hauch & Bach ApS - 705000-705FFF (base 16) Hauch & Bach ApS - Femstykket 6 - Lynge 3540 - DENMARK - - 00-50-C2 (hex) DioDigiWorks. CO., LTD. - 706000-706FFF (base 16) DioDigiWorks. CO., LTD. - 12F, 1208, Byucksan/Kyungin Digital Valley II, - 481-10, Kasan-Dong, Kumchon-Gu, - SEOUL 153-803 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) DTech Labs Inc - 707000-707FFF (base 16) DTech Labs Inc - 22876 Shaw Road - Sterling VA 20166 - UNITED STATES - - 00-50-C2 (hex) Smartek d.o.o. - 708000-708FFF (base 16) Smartek d.o.o. - Ziskovec 141 - Cakovec Medjimurje 40000 - CROATIA - - 00-50-C2 (hex) RO.VE.R. Laboratories S.p.A - 709000-709FFF (base 16) RO.VE.R. Laboratories S.p.A - Via Parini 2/4 - Colombare di SIrmione BS 25019 - ITALY - - 00-50-C2 (hex) Efficient Channel Coding - 70A000-70AFFF (base 16) Efficient Channel Coding - 4830 E. 49th St. - Cuyahoga Heights Ohio 44125 - UNITED STATES - - 00-50-C2 (hex) B.E.A.R. Solutions (Australasia) Pty, Ltd - 70B000-70BFFF (base 16) B.E.A.R. Solutions (Australasia) Pty, Ltd - Unit 226 - 14 Lexington Drive - Bella Vista NSW - AUSTRALIA - - 00-50-C2 (hex) Exertus - 70C000-70CFFF (base 16) Exertus - Kampusranta 9 - Seinäjoki FI-60320 - FINLAND - - 00-50-C2 (hex) ela-soft GmbH & Co. KG - 70D000-70DFFF (base 16) ela-soft GmbH & Co. KG - Breitenbachstraye 10 - Berlin 13509 - GERMANY - - 00-50-C2 (hex) AUDICO SYSTEMS OY - 70E000-70EFFF (base 16) AUDICO SYSTEMS OY - RUUNIKKOKATU 2 - P.O.Box 39 - TURKU 20380 - FINLAND - - 00-50-C2 (hex) Zumbach Electronic AG - 70F000-70FFFF (base 16) Zumbach Electronic AG - Hauptstrasse 93 - Orpund Bern 2552 - SWITZERLAND - - 00-50-C2 (hex) Wharton Electronics Ltd - 710000-710FFF (base 16) Wharton Electronics Ltd - Unit 15, Thame Park Business Centre - Wenman Road - Thame Oxfordshire OX9 3XA - UNITED KINGDOM - - 00-50-C2 (hex) LINKIT S.R.L. - 711000-711FFF (base 16) LINKIT S.R.L. - Via Lavoratori Autobianchi, 1 - Desio MI 20033 - ITALY - - 00-50-C2 (hex) Pasan SA - 712000-712FFF (base 16) Pasan SA - Rue Jaquet-Droz 8 - Neuchâtel NE 2000 - SWITZERLAND - - 00-50-C2 (hex) 3DX-Ray Limited - 713000-713FFF (base 16) 3DX-Ray Limited - Pera Innovation park - Nottingham Road - Melton Mowbray Leicestershire LE13 0PB - UNITED KINGDOM - - 00-50-C2 (hex) T.E.AM., S. A. - 714000-714FFF (base 16) T.E.AM., S. A. - PARQUE TECNOLOGICO EDIFICIO 108 - ZAMUDIO BIZKAIA 48170 - SPAIN - - 00-50-C2 (hex) RIEXINGER Elektronik - 715000-715FFF (base 16) RIEXINGER Elektronik - Horschelweg 15 - Oberrot Baden-Württemberg D-74420 - GERMANY - - 00-50-C2 (hex) MITROL S.R.L. - 716000-716FFF (base 16) MITROL S.R.L. - VIA G. MATTEOTTI, 19 - GAZZADA SCHIANNO VARESE 21045 - ITALY - - 00-50-C2 (hex) MB Connect Line GmbH - 717000-717FFF (base 16) MB Connect Line GmbH - Winnettener Str.6 - Dinkelsbuehl bavaria 91550 - GERMANY - - 00-50-C2 (hex) illunis LLC - 718000-718FFF (base 16) illunis LLC - 14700 Excelsior Blvd - Minnetonka MN 55345 - UNITED STATES - - 00-50-C2 (hex) ennovatis GmbH - 719000-719FFF (base 16) ennovatis GmbH - Dechwitzer Straße 11 - Großpösna Sachsen 04463 - GERMANY - - 00-50-C2 (hex) Logus Broadband Wireless Solutions Inc. - 71A000-71AFFF (base 16) Logus Broadband Wireless Solutions Inc. - 1501 Ellesmere Road - Toronto Ontario M1P 4T6 - CANADA - - 00-50-C2 (hex) ADVA Optical Networking - 71B000-71BFFF (base 16) ADVA Optical Networking - One Technology Parkway South - Norcross Ga 30092 - UNITED STATES - - 00-50-C2 (hex) Elmec Inc. - 71C000-71CFFF (base 16) Elmec Inc. - 229 Billerica Road - Chelmsford MA 01824 - UNITED STATES - - 00-50-C2 (hex) MG s.r.l. - 71D000-71DFFF (base 16) MG s.r.l. - via Monte Bianco, 1 - Solbiate Olona VA 21058 - ITALY - - 00-50-C2 (hex) ASKI Industrie Elektronik Ges.m.b.H. - 71E000-71EFFF (base 16) ASKI Industrie Elektronik Ges.m.b.H. - Irrseeblick 47 - 4893 Zell am Moos - AUSTRIA - - 00-50-C2 (hex) ASC telecom AG - 71F000-71FFFF (base 16) ASC telecom AG - Seibelstraße 2 - Hösbach Bavaria 63768 - GERMANY - - 00-50-C2 (hex) Colorado Engineering Inc. - 720000-720FFF (base 16) Colorado Engineering Inc. - 1915 Jamboree Drive - Suite 165 - Colorado Springs CO 80920 - UNITED STATES - - 00-50-C2 (hex) Spectrum Communications FZE - 721000-721FFF (base 16) Spectrum Communications FZE - A4-42 - Saif Zone - Sharjah - UNITED ARAB EMIRATES - - 00-50-C2 (hex) Centric TSolve BV - 722000-722FFF (base 16) Centric TSolve BV - Science Park Eindhoven 5644 - SON Noord-Brabant 5692 EN - NETHERLANDS - - 00-50-C2 (hex) Power Electronics - 723000-723FFF (base 16) Power Electronics - C/ Leonardo Da Vinci, 24-26 - Paterna Valencia 46980 - SPAIN - - 00-50-C2 (hex) HSC-Regelungstechnik GmbH - 724000-724FFF (base 16) HSC-Regelungstechnik GmbH - An der Lehmkaute 13 - Bad Marienberg Rheinland Pfalz 56470 - GERMANY - - 00-50-C2 (hex) DSP DESIGN - 725000-725FFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) eta systemi CKB - 726000-726FFF (base 16) eta systemi CKB - Via Arno 108, - Sesto Fiorentino FI 50019 - ITALY - - 00-50-C2 (hex) Pelweckyj Videotechnik GmbH - 727000-727FFF (base 16) Pelweckyj Videotechnik GmbH - Gueterstrasse 2 - Dieburg 64807 - GERMANY - - 00-50-C2 (hex) InterDigital Canada Ltd - 728000-728FFF (base 16) InterDigital Canada Ltd - 1000 Sherbrooke West, 10th floor - Montreal Quebec H3A 3G4 - CANADA - - 00-50-C2 (hex) SP Controls, Inc - 729000-729FFF (base 16) SP Controls, Inc - 930 Linden Avenue - San Francisco CA 94080 - UNITED STATES - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 72A000-72AFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Sequestered Solutions - 72B000-72BFFF (base 16) Sequestered Solutions - 801 B Street - Suite 102 - Anchorage Alaska 99501 - UNITED STATES - - 00-50-C2 (hex) Richard Griessbach Feinmechanik GmbH - 72C000-72CFFF (base 16) Richard Griessbach Feinmechanik GmbH - Im Biotechnologiepark - Luckenwalde Brandenburg 14943 - GERMANY - - 00-50-C2 (hex) Physical Acoustics Corporation - 72D000-72DFFF (base 16) Physical Acoustics Corporation - 195 Clarksville Road - Princeton Junction NJ 08550 - UNITED STATES - - 00-50-C2 (hex) SNCF EIM PAYS DE LOIRE - 72E000-72EFFF (base 16) SNCF EIM PAYS DE LOIRE - 2 AVENUE DE BRETAGNE - LE MANS SARTHE 72100 - FRANCE - - 00-50-C2 (hex) Priority Electronics Ltd - 72F000-72FFFF (base 16) Priority Electronics Ltd - 55 Trottier Bay - Winnipeg Manitoba R3T 3R3 - CANADA - - 00-50-C2 (hex) haber & koenig electronics gmbh - 730000-730FFF (base 16) haber & koenig electronics gmbh - Rechtes Salzachufer 42 - Bergheim Salzburg 5101 - AUSTRIA - - 00-50-C2 (hex) Spirent Communications - 731000-731FFF (base 16) Spirent Communications - 541 Industrial Way West - Eatontown New Jersey 07724 - UNITED STATES - - 00-50-C2 (hex) Schlumberger K.K. - 732000-732FFF (base 16) Schlumberger K.K. - 2-2-1 Fuchinobe, Chuo - Sagamihara Kanagawa 252-0206 - JAPAN - - 00-50-C2 (hex) Cimetrics Research Pty Ltd - 733000-733FFF (base 16) Cimetrics Research Pty Ltd - 36 Bushland Close - Tolmie VIC 3723 - AUSTRALIA - - 00-50-C2 (hex) CardioMEMS Inc. - 734000-734FFF (base 16) CardioMEMS Inc. - 75 Fifth St NW - Suite 440 - Atlanta Ga 30308 - UNITED STATES - - 00-50-C2 (hex) Ant Lamp, Inc - 735000-735FFF (base 16) Ant Lamp, Inc - 16420 SE McGillivray - #103-333 - Vancouver WA 98683-3461 - UNITED STATES - - 00-50-C2 (hex) Nika Ltd - 736000-736FFF (base 16) Nika Ltd - Kievskaja 14B - Vinnitsa 21009 - UKRAINE - - 00-50-C2 (hex) Teradici Corporation - 737000-737FFF (base 16) Teradici Corporation - 101 4621 Canada Way, - Burnaby BC V6G 4X8 - CANADA - - 00-50-C2 (hex) Miracom Technology Co., Ltd. - 738000-738FFF (base 16) Miracom Technology Co., Ltd. - 401, 4F. COREBUILDING, 8-1, SUNAE-DONG - SUNGNAM-SI GYUNGGI-DO 463-825 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Tattile srl - 739000-739FFF (base 16) Tattile srl - via gaetano donizetti,1/3/5 - capriano del colle brescia 25020 - ITALY - - 00-50-C2 (hex) Naturela Ltd. - 73A000-73AFFF (base 16) Naturela Ltd. - Ana Feliksova 13 - Varna 9020 - BULGARIA - - 00-50-C2 (hex) On Air Networks - 73B000-73BFFF (base 16) On Air Networks - 302,Ansan Software Center - Wonkok-Dong,Danwon-Gu - Ansan-Si Gyenonggi-Do 425-130 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Simicon - 73C000-73CFFF (base 16) Simicon - Mendeleevskay str. 8 - Saint-Petersburg 194044 - RUSSIAN FEDERATION - - 00-50-C2 (hex) cryptiris - 73D000-73DFFF (base 16) cryptiris - 235 avenue du coulins - gemenos bdr 13420 - FRANCE - - 00-50-C2 (hex) Quantec Networks GmbH - 73E000-73EFFF (base 16) Quantec Networks GmbH - Rieselwiese 1 - Vienenburg Niedersachsen 38690 - GERMANY - - 00-50-C2 (hex) MEDAV GmbH - 73F000-73FFFF (base 16) MEDAV GmbH - Graefenberger Strasse 32 - 34 - Uttenreuth Bayern 91080 - GERMANY - - 00-50-C2 (hex) McQuay China - 740000-740FFF (base 16) McQuay China - Pinghu Village,Pinghu Town,Shenzhen,Guangdong Province,Peoples Republic of China - Shenzhen Guangdong 518111 - CHINA - - 00-50-C2 (hex) Dain - 741000-741FFF (base 16) Dain - Dongmun Vision Building, Sinjeong 6-dong, Yangcheon-gu, - Seoul Yangcheon-gu, 158-740 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Fantuzzi Reggiane - 742000-742FFF (base 16) Fantuzzi Reggiane - Via Renata Bianchi, 40 - Third floor - Genoa GE 16152 - ITALY - - 00-50-C2 (hex) Elektro-Top 3000 Ltd. - 743000-743FFF (base 16) Elektro-Top 3000 Ltd. - Bartók Béla út 75. - Budapest 1114 - HUNGARY - - 00-50-C2 (hex) Avonaco Systems, Inc. - 744000-744FFF (base 16) Avonaco Systems, Inc. - A305, International Tech Park - 328 Airport Road - Suzhou Jiangsu 215021 - CHINA - - 00-50-C2 (hex) ACISA - 745000-745FFF (base 16) ACISA - Isaac Newton s/n - Pabellon de Italia - Sevilla 41092 - SPAIN - - 00-50-C2 (hex) Realtronix Company - 746000-746FFF (base 16) Realtronix Company - FLT A 16/F BLK 8 JUBILEE GARDEN - FOTAN SHATIN NT - HONG KONG - - 00-50-C2 (hex) CDSA Dam Neck - 747000-747FFF (base 16) CDSA Dam Neck - 1922 Regulus Avenue - Virginia Beach VA 23461-2097 - UNITED STATES - - 00-50-C2 (hex) Letechnic Ltd - 748000-748FFF (base 16) Letechnic Ltd - 143 Ladies Mile - Ellerslie - Auckland 1051 - NEW ZEALAND - - 00-50-C2 (hex) Affolter Technologies SA - 749000-749FFF (base 16) Affolter Technologies SA - Grand-Rue 76 - Malleray BE 2735 - SWITZERLAND - - 00-50-C2 (hex) MONITOR ELECTRONICS LTD - 74A000-74AFFF (base 16) MONITOR ELECTRONICS LTD - VOULIAGMENIS AV. 403, ILIOUPOLI - ATHENS ATTIKI 16346 - GREECE - - 00-50-C2 (hex) STAR-Dundee Ltd - 74B000-74BFFF (base 16) STAR-Dundee Ltd - C/o School of Computing - University of Dundee - Dundee Tayside DD1 4HN - UNITED KINGDOM - - 00-50-C2 (hex) Saia-Burgess Controls AG - 74C000-74CFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Beceem Communications, Inc. - 74D000-74DFFF (base 16) Beceem Communications, Inc. - 3960 Freedom Cir., 1st Floor - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) TRONICO - 74E000-74EFFF (base 16) TRONICO - 26 rue du Bocage - St Philbert de Bouaine Vendée 85660 - FRANCE - - 00-50-C2 (hex) German Technologies - 74F000-74FFFF (base 16) German Technologies - Chaqiao Industrial District, Shiqi - Zhongshan City Guangdong Province 528404 - CHINA - - 00-50-C2 (hex) Brightlights Intellectual Property Ltd - 750000-750FFF (base 16) Brightlights Intellectual Property Ltd - Unit 19A Perseverance Works - 38 Kingsland Road - London E2 8DD - UNITED KINGDOM - - 00-50-C2 (hex) e&s Engineering & Software GmbH - 751000-751FFF (base 16) e&s Engineering & Software GmbH - Schmücker Straße 82a - MANEBACH Thueringen D98693 - GERMANY - - 00-50-C2 (hex) LOBER, S.A. - 752000-752FFF (base 16) LOBER, S.A. - MARIA TUBAU, 4 - MADRID 28050 - SPAIN - - 00-50-C2 (hex) ABB - 753000-753FFF (base 16) ABB - Service - Automiehenkatu 2 - Tampere 33840 - FINLAND - - 00-50-C2 (hex) Abeo Corporation - 754000-754FFF (base 16) Abeo Corporation - 13611 Legacy Circle - Suite A - Herndon VA 20171-4701 - UNITED STATES - - 00-50-C2 (hex) Teletek Electronics - 755000-755FFF (base 16) Teletek Electronics - 14A Srebarna Str. - Sofia 1407 - BULGARIA - - 00-50-C2 (hex) Chesapeake Sciences Corp - 756000-756FFF (base 16) Chesapeake Sciences Corp - 1127 B Benfield Blvd - Millersville MD 21108 - UNITED STATES - - 00-50-C2 (hex) E S P Technologies Ltd - 757000-757FFF (base 16) E S P Technologies Ltd - The Stables Deans Farm Estate - Wickham Road - Fareham Hampshire SO30 2DX - UNITED KINGDOM - - 00-50-C2 (hex) AixSolve GmbH - 758000-758FFF (base 16) AixSolve GmbH - Kaiserstrasse 100 - Herzogenrath NRW 52134 - GERMANY - - 00-50-C2 (hex) Sequentric Energy Systems, LLC - 759000-759FFF (base 16) Sequentric Energy Systems, LLC - 4651 Woodstock Rd 208-150 - Roswell GA 30075 - UNITED STATES - - 00-50-C2 (hex) Gaisler Research AB - 75A000-75AFFF (base 16) Gaisler Research AB - Forsta Langgatan 19 - Goteborg VG 41327 - SWEDEN - - 00-50-C2 (hex) DMT System S.p.A. - 75B000-75BFFF (base 16) DMT System S.p.A. - Via Zanella 21 - Lissone Milan 20035 - ITALY - - 00-50-C2 (hex) STÖRK-TRONIC Störk GmbH&Co. KG - 75C000-75CFFF (base 16) STÖRK-TRONIC Störk GmbH&Co. KG - Untere Waldplätze 6 - Stuttgart Baden-Württemberg D-70569 - GERMANY - - 00-50-C2 (hex) Fluid Analytics, Inc. - 75D000-75DFFF (base 16) Fluid Analytics, Inc. - 3525 SE 17th Ave. - Portland OR 97202 - UNITED STATES - - 00-50-C2 (hex) Sky-Skan, Incorporated - 75E000-75EFFF (base 16) Sky-Skan, Incorporated - 51 Lake Street - Nashua NH 03060-4513 - UNITED STATES - - 00-50-C2 (hex) B. Rexroth the identity company GmbH - 75F000-75FFFF (base 16) B. Rexroth the identity company GmbH - Im Gruendchen 14 - Bessenbach Bavaria 63856 - GERMANY - - 00-50-C2 (hex) AR'S CO., LTD. - 760000-760FFF (base 16) AR'S CO., LTD. - Yokohama Creation Square, - 5-1, sakaecho, kanagawa-ku - Yokohama Kanagawa 221-0052 - JAPAN - - 00-50-C2 (hex) Elbit Systems of America - Fort Worth Operations - 761000-761FFF (base 16) Elbit Systems of America - Fort Worth Operations - 4700 Marine Creek Parkway - Fort Worth TX 76179 - UNITED STATES - - 00-50-C2 (hex) Assembly Contracts Limited - 762000-762FFF (base 16) Assembly Contracts Limited - Ledson Road - Roundthorn Industrial Estate - Wythenshawe Manchester M23 9GP - UNITED KINGDOM - - 00-50-C2 (hex) XtendWave - 763000-763FFF (base 16) XtendWave - 8111 LBJ Freeway - Suite 1250 - Dallas Texas 75251 - UNITED STATES - - 00-50-C2 (hex) ARGUS-SPECTRUM - 764000-764FFF (base 16) ARGUS-SPECTRUM - 65, Serdobolskaya str. - St-Peterburg 197342 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 765000-765FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Gutermann Technology GmbH - 766000-766FFF (base 16) Gutermann Technology GmbH - Gottlieb-Daimler-Strasse 10 - Ravensburg 88214 - GERMANY - - 00-50-C2 (hex) EID - 767000-767FFF (base 16) EID - Quinta dos Medronheiros - Lazarim - Caparica 2826-851 - PORTUGAL - - 00-50-C2 (hex) Control Service do Brasil Ltda - 768000-768FFF (base 16) Control Service do Brasil Ltda - Rua Funchal, 551 cj. 62 - Vila Olimpia - São Paulo 04551060 - BRAZIL - - 00-50-C2 (hex) BES GmbH - 769000-769FFF (base 16) BES GmbH - Spitzenmeer 1 - Westerstede D 26655 - GERMANY - - 00-50-C2 (hex) Digidrive Audio Limited - 76A000-76AFFF (base 16) Digidrive Audio Limited - Spenglerstrasse 6 - Hamm NRW 59067 - GERMANY - - 00-50-C2 (hex) Putercom Enterprise Co., LTD. - 76B000-76BFFF (base 16) Putercom Enterprise Co., LTD. - 5F-3, No. 130, Jian Kang Road - Chung-Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) EFG CZ spol. s r.o. - 76C000-76CFFF (base 16) EFG CZ spol. s r.o. - Na JarovÄ› 4 - Praha 3 Czech republic 13000 - CZECH REPUBLIC - - 00-50-C2 (hex) Mobilisme - 76D000-76DFFF (base 16) Mobilisme - RN536, Sungwoo Starus, 189-1 - Gumi-dong, Bundang-gu - Sungnam-si Gyunggi-do 463-860 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Crinia Corporation - 76E000-76EFFF (base 16) Crinia Corporation - PO Box 364 - Cherrybrook NSW 2126 - AUSTRALIA - - 00-50-C2 (hex) Control and Robotics Solutions - 76F000-76FFFF (base 16) Control and Robotics Solutions - 5 Mazal Eliezer St. - Rishon Le-Zion 75653 - ISRAEL - - 00-50-C2 (hex) Cadex Electronics Inc. - 770000-770FFF (base 16) Cadex Electronics Inc. - 22000 Fraserwood Way - Richmond BC V6W 1J6 - CANADA - - 00-50-C2 (hex) ZigBee Alliance - 771000-771FFF (base 16) ZigBee Alliance - 2400 Camino Ramon, Suite 375 - San Ramon California 94583 - UNITED STATES - - 00-50-C2 (hex) IES Elektronikentwicklung - 772000-772FFF (base 16) IES Elektronikentwicklung - Osterholzweg 26 - Braunschweig Niedersachsen 38110 - GERMANY - - 00-50-C2 (hex) Pointe Conception Medical Inc. - 773000-773FFF (base 16) Pointe Conception Medical Inc. - 121 East Mason Street - Santa Barbara California 93101 - UNITED STATES - - 00-50-C2 (hex) GeoSIG Ltd. - 774000-774FFF (base 16) GeoSIG Ltd. - Europastrasse 11 - Glattbrugg Zürich 8152 - SWITZERLAND - - 00-50-C2 (hex) Laserdyne Technologies - 775000-775FFF (base 16) Laserdyne Technologies - PO Box 6541 - Bundall - GOLD COAST QLD 9726 - AUSTRALIA - - 00-50-C2 (hex) Integrated Security Corporation - 776000-776FFF (base 16) Integrated Security Corporation - 46755 Magellan Drive - Novi MI 48377 - UNITED STATES - - 00-50-C2 (hex) Euro Display Srl - 777000-777FFF (base 16) Euro Display Srl - Via Gandhi, 21 - Avigliana Torino 10051 - ITALY - - 00-50-C2 (hex) SunGard Vivista - 778000-778FFF (base 16) SunGard Vivista - Tormarton Road - Marshfield - Chippenham Wiltshire SN14 8SR - UNITED KINGDOM - - 00-50-C2 (hex) Coral Telecom Ltd - 779000-779FFF (base 16) Coral Telecom Ltd - E-02 Sector 63 - Noida UP 201301 - INDIA - - 00-50-C2 (hex) Smith Meter, Inc - 77A000-77AFFF (base 16) Smith Meter, Inc - 1602 Wagner Ave - Erie PA 16514 - UNITED STATES - - 00-50-C2 (hex) Itibia Technologies, Inc. - 77B000-77BFFF (base 16) Itibia Technologies, Inc. - 100 Menlo Park, Suite 212 - Edison NJ 08837 - UNITED STATES - - 00-50-C2 (hex) ATEC SRL - 77C000-77CFFF (base 16) ATEC SRL - VIA NOBEL No. 8 - NOVENTA DI PIAVE VENICE 30020 - ITALY - - 00-50-C2 (hex) Lincoln Industrial - 77D000-77DFFF (base 16) Lincoln Industrial - One Lincoln Way - Saint Louis MO 63120 - UNITED STATES - - 00-50-C2 (hex) Cominfo Inc. - 77E000-77EFFF (base 16) Cominfo Inc. - Nabrezi 695 - Zlin Czech Republic 76001 - CZECH REPUBLIC - - 00-50-C2 (hex) ACD Elektronik GmbH - 77F000-77FFFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten Bawu 88480 - GERMANY - - 00-50-C2 (hex) IQ Solutions GmbH & Co. KG - 780000-780FFF (base 16) IQ Solutions GmbH & Co. KG - Gewerbepark 7A - Bisssendorf Niedersachsen 49143 - GERMANY - - 00-50-C2 (hex) Starling Advanced Communications - 781000-781FFF (base 16) Starling Advanced Communications - 2 Tavor House - Yoqneam 20692 - ISRAEL - - 00-50-C2 (hex) Phytec Mestechnik GmbH - 782000-782FFF (base 16) Phytec Mestechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) NORMA systems GmbH - 783000-783FFF (base 16) NORMA systems GmbH - Eidersteder Str.24 - Bordesholm Schl.-Holstein 24582 - GERMANY - - 00-50-C2 (hex) Lewis Controls Inc. - 784000-784FFF (base 16) Lewis Controls Inc. - 260 N. 26th Ave - Corneliu OR 97229 - UNITED STATES - - 00-50-C2 (hex) Icon Time Systems - 785000-785FFF (base 16) Icon Time Systems - 15201 NW Greenbrier Pkwy, Suite A1 - Beaverton Oregon 97006 - UNITED STATES - - 00-50-C2 (hex) Keith & Koep GmbH - 786000-786FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Austco Communication Systems Pty Ltd - 787000-787FFF (base 16) Austco Communication Systems Pty Ltd - 40 O'Malley Street - Osborne Park Western Australia 6017 - AUSTRALIA - - 00-50-C2 (hex) HOSA TECHNOLOGY, INC. - 788000-788FFF (base 16) HOSA TECHNOLOGY, INC. - 6650 CABALLERO BLVD. - BUENA PARK CA 90620 - UNITED STATES - - 00-50-C2 (hex) Rosslare Enterprises Limited - 789000-789FFF (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road, - Kowloon Bay, Kowloon - HONG KONG - - 00-50-C2 (hex) LEVEL TELECOM - 78A000-78AFFF (base 16) LEVEL TELECOM - Parque Empresarial NovoMilladoiro - Rúa das Hedras, 47-B2 - Milladoiro - Ames A Coruña 15895 - SPAIN - - 00-50-C2 (hex) OMICRON electronics GmbH - 78B000-78BFFF (base 16) OMICRON electronics GmbH - Oberes Ried 1 - Klaus 6833 - AUSTRIA - - 00-50-C2 (hex) Giga-tronics, Inc. - 78C000-78CFFF (base 16) Giga-tronics, Inc. - 4650 Norris Canyon Road - San Ramon CA 94583 - UNITED STATES - - 00-50-C2 (hex) Telairity - 78D000-78DFFF (base 16) Telairity - 3375 Scott Blvd. #300 - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) GLOBALCOM ENGINEERING SRL - 78E000-78EFFF (base 16) GLOBALCOM ENGINEERING SRL - Via Volta 9 - MORNAGO VA 21020 - ITALY - - 00-50-C2 (hex) ELMAR electronic - 78F000-78FFFF (base 16) ELMAR electronic - Hrvatske mornarice 1F - Split 21000 - CROATIA - - 00-50-C2 (hex) GE Security-Kampro - 790000-790FFF (base 16) GE Security-Kampro - 2F, No.8, Lane97, Wugong Rd., - Wu-Ku Ind.Park, - Hsin-Chuang City Taipei County 248 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) M Squared Lasers Limited - 791000-791FFF (base 16) M Squared Lasers Limited - 1 Technology Terrace - Todd Campus, Maryhill Road - Glasgow Scotland G20 0XA - UNITED KINGDOM - - 00-50-C2 (hex) SMARTRO Co.,Ltd. - 792000-792FFF (base 16) SMARTRO Co.,Ltd. - B-dong,SK TwinTechTower,#345-9,Gasan-dong,Geumcheon-gu - Seoul 153-773 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Enertex Bayern GmbH - 793000-793FFF (base 16) Enertex Bayern GmbH - Erlachstrasse 13 - Forchheim Bayern 91301 - GERMANY - - 00-50-C2 (hex) COMSONICS, INC. - 794000-794FFF (base 16) COMSONICS, INC. - 1350 PORT REPUBLIC ROAD - P.O. BOX 1106 - HARRISONBURG VA 22801 - UNITED STATES - - 00-50-C2 (hex) Ameli Spa - 795000-795FFF (base 16) Ameli Spa - Via Guido Rossa, 10 - Loc. Cascine del Riccio - Impruneta (FI) 50023 - ITALY - - 00-50-C2 (hex) DORLET S.A. - 796000-796FFF (base 16) DORLET S.A. - Albert Einstein 34 - MIÑANO Mayor - Vitoria-gasteiz Alava 01510 - SPAIN - - 00-50-C2 (hex) Tiefenbach Control Systems GmbH - 797000-797FFF (base 16) Tiefenbach Control Systems GmbH - Brückenstraße 8 - Erlangen Bayern 91056 - GERMANY - - 00-50-C2 (hex) Indefia - 798000-798FFF (base 16) Indefia - Sehit Ismet Armagan sokak No:4/12 - Nisantasi - Istanbul 34363 - TURKEY - - 00-50-C2 (hex) AAVD - 799000-799FFF (base 16) AAVD - parc de gavaniere - rue - saint egreve isere 38120 - FRANCE - - 00-50-C2 (hex) JMC America, LLC - 79A000-79AFFF (base 16) JMC America, LLC - 520 E 770 N - Orem Utah 84097 - UNITED STATES - - 00-50-C2 (hex) Schniewindt GmbH & Co. KG - 79B000-79BFFF (base 16) Schniewindt GmbH & Co. KG - Schoentaler Weg 46 - Neuenrade NRW 58809 - GERMANY - - 00-50-C2 (hex) Vital Systems Inc - 79C000-79CFFF (base 16) Vital Systems Inc - 21630 N 19th Ave. Suite B8 - Phoenix AZ 85027 - UNITED STATES - - 00-50-C2 (hex) MiraTrek - 79D000-79DFFF (base 16) MiraTrek - 7985 Raytheon Road #200 - San Diego CA 92111 - UNITED STATES - - 00-50-C2 (hex) Benshaw Canada Controls, Inc. - 79E000-79EFFF (base 16) Benshaw Canada Controls, Inc. - 550 Bright Street - Listowel Ontario N4W 3W3 - CANADA - - 00-50-C2 (hex) ZAO NPC - 79F000-79FFFF (base 16) ZAO NPC - Ostrovskogo, 65 - Perm Perm region 614007 - RUSSIAN FEDERATION - - 00-50-C2 (hex) MedAvant Healthcare - 7A0000-7A0FFF (base 16) MedAvant Healthcare - 2533 Centennial Blvd - Jeffersonville IN 47130 - UNITED STATES - - 00-50-C2 (hex) Field Design Service - 7A1000-7A1FFF (base 16) Field Design Service - 4-5-40, Showa-cho - Akishima Tokyo 196-0015 - JAPAN - - 00-50-C2 (hex) RaySat Israel LTD - 7A2000-7A2FFF (base 16) RaySat Israel LTD - Bareket 1 Building, 1st Golan street - Airport City Lod 70100 - ISRAEL - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - 7A3000-7A3FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park, Torch Hi-Tech Industrial Development Zone - Xiao Dong Shan, Xiamen - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) Calibre UK LTD - 7A4000-7A4FFF (base 16) Calibre UK LTD - Cornwall House - Cornwall Terrace - Bradford West Yorkshire BD8 7JS - UNITED KINGDOM - - 00-50-C2 (hex) Quantum Medical Imaging - 7A5000-7A5FFF (base 16) Quantum Medical Imaging - 2002 Orville Drive, North - Ronkonkoma NY 11779 - UNITED STATES - - 00-50-C2 (hex) ASIANA IDT - 7A6000-7A6FFF (base 16) ASIANA IDT - 5th Fl., B-Dong, Asiana Town - #47, Osoe-Dong, Gangseo-Gu - Seoul 157-713 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Guidance Navigation Limited - 7A7000-7A7FFF (base 16) Guidance Navigation Limited - 5 Tiber Way - Meridian Business Park - Leicester Leicestershire LE19 1QP - UNITED KINGDOM - - 00-50-C2 (hex) Integrated Design Tools, Inc. - 7A8000-7A8FFF (base 16) Integrated Design Tools, Inc. - 1804 Miccosukee Commons Drive Suite 208 - Tallahassee FL 32308 - UNITED STATES - - 00-50-C2 (hex) Delta Tau Data Systems, Inc - 7A9000-7A9FFF (base 16) Delta Tau Data Systems, Inc - 21314 Lassen St - Chatsworth CA 91311 - UNITED STATES - - 00-50-C2 (hex) Grupo Epelsa S.L. - 7AA000-7AAFFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) General Microsystems Sdn Bhd - 7AB000-7ABFFF (base 16) General Microsystems Sdn Bhd - 3-17, Jalan USJ 7/3B - UEP Subang Jaya Selangor D. E. 47610 - MALAYSIA - - 00-50-C2 (hex) IUSA SA DE CV - 7AC000-7ACFFF (base 16) IUSA SA DE CV - Km 109 CARRETERA PANAMERICANA MEX-QRO - PASTEJE JOCOTITLAN ESTADO DE MEXICO 50700 - MEXICO - - 00-50-C2 (hex) Turun Turvatekniikka Oy - 7AD000-7ADFFF (base 16) Turun Turvatekniikka Oy - Orikedonkatu 22 B - Turku 20380 - FINLAND - - 00-50-C2 (hex) Global Tel-Link - 7AE000-7AEFFF (base 16) Global Tel-Link - 6612 E. 75th Street - Indianapolis IN 46250 - UNITED STATES - - 00-50-C2 (hex) C2 Microsystems - 7AF000-7AFFFF (base 16) C2 Microsystems - 2833 Junction Ave - Suite 101 - San Jose CA 95134-1224 - UNITED STATES - - 00-50-C2 (hex) IMP Telekom - 7B0000-7B0FFF (base 16) IMP Telekom - Vojkova 58 - Ljubljana 1000 - SLOVENIA - - 00-50-C2 (hex) ATEME - 7B1000-7B1FFF (base 16) ATEME - 26 Burospace - route de GIZY - - Bievres cedex Bievres 91570 - FRANCE - - 00-50-C2 (hex) A.D.I Video technologies - 7B2000-7B2FFF (base 16) A.D.I Video technologies - 7 Hamarpe st, - Har Hotzvim - Jerusalem 45190 - ISRAEL - - 00-50-C2 (hex) Elmec, Inc. - 7B3000-7B3FFF (base 16) Elmec, Inc. - 229 Billerica Road - Chelmsford Mass 01824 - UNITED STATES - - 00-50-C2 (hex) T 1 Engineering - 7B4000-7B4FFF (base 16) T 1 Engineering - 5923 Thorntree Drive - San Jose CA 95120 - UNITED STATES - - 00-50-C2 (hex) DIT-MCO International - 7B5000-7B5FFF (base 16) DIT-MCO International - 5612 Brighton Terrace - Kansas City Missouri 64130 - UNITED STATES - - 00-50-C2 (hex) Alstom (Schweiz) AG - 7B6000-7B6FFF (base 16) Alstom (Schweiz) AG - - Brown Boveri Str. 7 - Baden AG 5401 - SWITZERLAND - - 00-50-C2 (hex) TATTILE SRL - 7B7000-7B7FFF (base 16) TATTILE SRL - VIA G. DONIZETTI,1/3/5 - MAIRANO BRESCIA 25030 - ITALY - - 00-50-C2 (hex) Design 2000 Pty Ltd - 7B8000-7B8FFF (base 16) Design 2000 Pty Ltd - 9-11 Rose Street - Upper Ferntree Gully - Melbourne Victoria 3156 - AUSTRALIA - - 00-50-C2 (hex) Technovare Systems, Inc. - 7B9000-7B9FFF (base 16) Technovare Systems, Inc. - 1675 Scenic Ave., Suite 200 - Costa Mesa CA 92626 - UNITED STATES - - 00-50-C2 (hex) Infodev Electronic Designers Intl. - 7BA000-7BAFFF (base 16) Infodev Electronic Designers Intl. - CP 1222 HV - Quebec G1R 5A7 - CANADA - - 00-50-C2 (hex) InRay Solutions Ltd. - 7BB000-7BBFFF (base 16) InRay Solutions Ltd. - 125 Tzarigradsko shosse blvd., - bl. 2, room 510 - Sofia 1113 - BULGARIA - - 00-50-C2 (hex) EIDOS SPA - 7BC000-7BCFFF (base 16) EIDOS SPA - CORSO MATTEOTTI, 25 - CHIERI TORINO 10023 - ITALY - - 00-50-C2 (hex) PROMATE ELECTRONIC CO.LTD - 7BD000-7BDFFF (base 16) PROMATE ELECTRONIC CO.LTD - 4F 32,SEC.1 HUAN SHAN RD.,NEI HU, - TAIPEI 114 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Powerlinx, Inc. - 7BE000-7BEFFF (base 16) Powerlinx, Inc. - 10901-A Roosevelt Blvd. North - Suite 200 - St Petersburg Florida 33716 - UNITED STATES - - 00-50-C2 (hex) Zoe Medical - 7BF000-7BFFFF (base 16) Zoe Medical - 460 Boston Street - Topsfield MA 01983 - UNITED STATES - - 00-50-C2 (hex) European Industrial Electronics B.V. - 7C0000-7C0FFF (base 16) European Industrial Electronics B.V. - De Run 5116B - Veldhoven Noord-Brabant 5503 LV - NETHERLANDS - - 00-50-C2 (hex) Primary Integration Encorp LLC - 7C1000-7C1FFF (base 16) Primary Integration Encorp LLC - 1825 Sharp Point Drive, Suite 118 - Fort Collins CO 80525 - UNITED STATES - - 00-50-C2 (hex) DSR Information Technologies Ltd. - 7C2000-7C2FFF (base 16) DSR Information Technologies Ltd. - Fehérvári út. 50-52 - Budapest 1117 - HUNGARY - - 00-50-C2 (hex) AST INCORPORATED - 7C3000-7C3FFF (base 16) AST INCORPORATED - 4150 GRANGE HALL ROAD - HOLLY MICHIGAN 48442 - UNITED STATES - - 00-50-C2 (hex) MoBaCon - 7C4000-7C4FFF (base 16) MoBaCon - Ludwig-Wilhelm-Str. 6 - Karlsruhe BW 76131 - GERMANY - - 00-50-C2 (hex) Venture Research Inc. - 7C5000-7C5FFF (base 16) Venture Research Inc. - 3001 Summit Ave - Suite 100 - Plano TX 75074 - UNITED STATES - - 00-50-C2 (hex) Lyngdorf Audio Aps - 7C6000-7C6FFF (base 16) Lyngdorf Audio Aps - Ulvevej 28 - Skive Jylland DK-7800 - DENMARK - - 00-50-C2 (hex) Pyrosequencing AB - 7C7000-7C7FFF (base 16) Pyrosequencing AB - Kungsgatan 76 - Uppsala Uppsala län SE-753 18 - SWEDEN - - 00-50-C2 (hex) Fr. Sauter AG - 7C8000-7C8FFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS CH4016 - SWITZERLAND - - 00-50-C2 (hex) Bluebell Opticom Limited - 7C9000-7C9FFF (base 16) Bluebell Opticom Limited - Unit 2 The Quadrant - Howarth Road - Maidenhead Berkshire SL6 1AP - UNITED KINGDOM - - 00-50-C2 (hex) CEDAR Audio Limited - 7CA000-7CAFFF (base 16) CEDAR Audio Limited - 20 Home End - Fulbourn - Cambridge CB21 5BS - UNITED KINGDOM - - 00-50-C2 (hex) ViewPlus Technologies, Inc. - 7CB000-7CBFFF (base 16) ViewPlus Technologies, Inc. - 1853 SW Airport Ave. - Corvallis OR 97333 - UNITED STATES - - 00-50-C2 (hex) SWECO JAPS AB - 7CC000-7CCFFF (base 16) SWECO JAPS AB - Metallverksgatan 8 - VästerÃ¥s SE-721 30 - SWEDEN - - 00-50-C2 (hex) Precision MicroControl Corporation - 7CD000-7CDFFF (base 16) Precision MicroControl Corporation - 2075 Corte del Nogal - Suite N - Carlsbad CA 92011 - UNITED STATES - - 00-50-C2 (hex) Aircell - 7CE000-7CEFFF (base 16) Aircell - 303 S. Technology Dr. - Bldg A - Broomfield CO 80021 - UNITED STATES - - 00-50-C2 (hex) Emitech Corporation - 7CF000-7CFFFF (base 16) Emitech Corporation - 2F, No.7-1, Industry. Er.9 - Science-Based Industrial Park, - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Radar Tronic ltd. - 7D0000-7D0FFF (base 16) Radar Tronic ltd. - Törökkö u. 5-7. - Budapest Pest 1037 - HUNGARY - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 7D1000-7D1FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Bittitalo Oy - 7D2000-7D2FFF (base 16) Bittitalo Oy - Lausmaentie 14 - RAISIO Finland 21210 - FINLAND - - 00-50-C2 (hex) Highrail Systems Limited - 7D3000-7D3FFF (base 16) Highrail Systems Limited - 4 Morfa Lodge - Porthmadog GWYNEDD LL49 9PF - UNITED KINGDOM - - 00-50-C2 (hex) WR Systems, Ltd. - 7D4000-7D4FFF (base 16) WR Systems, Ltd. - 2500 Almeda Ave. - Suite 214 - Norfolk VA 23513 - UNITED STATES - - 00-50-C2 (hex) Deuta-Werke GmbH - 7D5000-7D5FFF (base 16) Deuta-Werke GmbH - Paffrather Strasse 140 - Bergisch-Gladbach NRW 51465 - GERMANY - - 00-50-C2 (hex) International Mining Technologies - 7D6000-7D6FFF (base 16) International Mining Technologies - 19 Collingwood St. - Osborne Park Western Australia 6916 - AUSTRALIA - - 00-50-C2 (hex) Newtec A/S - 7D7000-7D7FFF (base 16) Newtec A/S - StærmosegÃ¥rdsvej 18 - Odense SV Region Syd 5230 - DENMARK - - 00-50-C2 (hex) InnoScan K/S - 7D8000-7D8FFF (base 16) InnoScan K/S - Sødalsparken 11 - Brabrand 8220 - DENMARK - - 00-50-C2 (hex) Volumatic Limited - 7D9000-7D9FFF (base 16) Volumatic Limited - Taurus House - Endmere Road - Coventry Warwickshire CV6 5PY - UNITED KINGDOM - - 00-50-C2 (hex) HTEC Limited - 7DA000-7DAFFF (base 16) HTEC Limited - Southampton International Park - George Curl Way - Southampton Hampshire SO18 2RX - UNITED KINGDOM - - 00-50-C2 (hex) Mueller Elektronik - 7DB000-7DBFFF (base 16) Mueller Elektronik - Hauptstraße 86 - Spaichingen Baden-Württemberg 78549 - GERMANY - - 00-50-C2 (hex) aiXtrusion GmbH - 7DC000-7DCFFF (base 16) aiXtrusion GmbH - Pirolweg 21 - Aachen NRW 52076 - GERMANY - - 00-50-C2 (hex) LS Elektronik AB - 7DD000-7DDFFF (base 16) LS Elektronik AB - Avestagatan 35 - Box 8301 - SpÃ¥nga 163 08 - SWEDEN - - 00-50-C2 (hex) Cascade Technologies Ltd - 7DE000-7DEFFF (base 16) Cascade Technologies Ltd - Unit A Logie Court - Stirling Innovation Park - Stirling Stirlingshire FK9 4NF - UNITED KINGDOM - - 00-50-C2 (hex) PRIVATE - 7DF000-7DFFFF (base 16) - - 00-50-C2 (hex) C&D Technologies, Inc - 7E0000-7E0FFF (base 16) C&D Technologies, Inc - 65 Industrial Park Rd - Dunlap TN 37327 - UNITED STATES - - 00-50-C2 (hex) Zeltiq Aesthetics, Inc. - 7E1000-7E1FFF (base 16) Zeltiq Aesthetics, Inc. - 4698 Willow Road - Pleasanton CA 94588 - UNITED STATES - - 00-50-C2 (hex) DIGITROL LTD - 7E2000-7E2FFF (base 16) DIGITROL LTD - CORONET WAY - ENTERPRISE PARK - SWANSEA WALES SA6 8RH - UNITED KINGDOM - - 00-50-C2 (hex) Progentech Limited - 7E3000-7E3FFF (base 16) Progentech Limited - Shenergy International Building - 1 Mid Fuxing Road, Room 1603 - Shanghai 200021 - CHINA - - 00-50-C2 (hex) Meta Vision Systems Ltd. - 7E4000-7E4FFF (base 16) Meta Vision Systems Ltd. - Oakfield House - Oakfield Industrial Estate - Eynsham Oxfordshire OX29 4TH - UNITED KINGDOM - - 00-50-C2 (hex) Nystrom Engineering - 7E5000-7E5FFF (base 16) Nystrom Engineering - 211 NE 365th Ave - Corbett OR 97019 - UNITED STATES - - 00-50-C2 (hex) Empirix Italy S.p.A. - 7E6000-7E6FFF (base 16) Empirix Italy S.p.A. - Via Giorgio Perlasca, 20 - Modena 41126 - ITALY - - 00-50-C2 (hex) V2Green, Inc. - 7E7000-7E7FFF (base 16) V2Green, Inc. - 1725 Westlake Ave. N - Suite 202 - Seattle WA 98109 - UNITED STATES - - 00-50-C2 (hex) Mistral Solutions Pvt. Ltd - 7E8000-7E8FFF (base 16) Mistral Solutions Pvt. Ltd - #60, Adarsh Regent, 100 Ft. Ring Road - Domlur Extension - BANGALORE KARNATAKA 560071 - INDIA - - 00-50-C2 (hex) Sicon s.r.l. - 7E9000-7E9FFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) Monitor Business Machines Ltd. - 7EA000-7EAFFF (base 16) Monitor Business Machines Ltd. - PO Box 108 042 - Symonds Street - Auckland - NEW ZEALAND - - 00-50-C2 (hex) Sesol Industrial Computer - 7EB000-7EBFFF (base 16) Sesol Industrial Computer - #509 High-End Tower, Seoul Digital - Industrial Park 1, 235-2 Guro-Dong - Guro-Gu Seoul 152-848 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Lyngsoe Systems - 7EC000-7ECFFF (base 16) Lyngsoe Systems - 5570 Kennedy RD - Unit B - Mississauga Ontario L4Z 2A9 - CANADA - - 00-50-C2 (hex) Genesis Automation Inc. - 7ED000-7EDFFF (base 16) Genesis Automation Inc. - 3480 Swenson Ave. - Saint Charles IL 60174 - UNITED STATES - - 00-50-C2 (hex) NH Research - 7EE000-7EEFFF (base 16) NH Research - 16601 Hale Ave. - Irvine CA 92606 - UNITED STATES - - 00-50-C2 (hex) GFI Chrono Time - 7EF000-7EFFFF (base 16) GFI Chrono Time - 121 rue des Guillees - CHAURAY 79180 - FRANCE - - 00-50-C2 (hex) Network Harbor, Inc. - 7F0000-7F0FFF (base 16) Network Harbor, Inc. - 5607 South Washington Street - Bartonville IL 61607 - UNITED STATES - - 00-50-C2 (hex) STUHL Regelsysteme GmbH - 7F1000-7F1FFF (base 16) STUHL Regelsysteme GmbH - Am Wasserturm 1 - Spalt BY 91174 - GERMANY - - 00-50-C2 (hex) Logotherm Regelsysteme GmbH - 7F2000-7F2FFF (base 16) Logotherm Regelsysteme GmbH - Erlauftalstraße 28 - Purgstall Lower Austria AT-3251 - AUSTRIA - - 00-50-C2 (hex) SOREC - 7F3000-7F3FFF (base 16) SOREC - ZA Le Patureau de la Grange - PRUNIERS EN SOLOGNE LOIR ET CHER 41200 - FRANCE - - 00-50-C2 (hex) Wireless Cables Inc - 7F4000-7F4FFF (base 16) Wireless Cables Inc - 1414 Soquel Ave, Ste 212 - Santa Cruz CA 95062 - UNITED STATES - - 00-50-C2 (hex) ACE Carwash Systems - 7F5000-7F5FFF (base 16) ACE Carwash Systems - Gouwzeestraat 11 - Weesp NH 1382 KD - NETHERLANDS - - 00-50-C2 (hex) Saia-Burgess Controls AG - 7F6000-7F6FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) MangoDSP - 7F7000-7F7FFF (base 16) MangoDSP - Hartom 8 - Jerusalem 45116 - ISRAEL - - 00-50-C2 (hex) Wise Industria de Telecomunicações Ldta. - 7F8000-7F8FFF (base 16) Wise Industria de Telecomunicações Ldta. - SIBS Quadra 01 conjunto - Núcleo Bandeirante Distrito Federal 71736-104 - BRAZIL - - 00-50-C2 (hex) Karl DUNGS GmbH & Co. KG - 7F9000-7F9FFF (base 16) Karl DUNGS GmbH & Co. KG - Siemensstrasse 6-10 - Urbach BW 73660 - GERMANY - - 00-50-C2 (hex) AutomationX GmbH - 7FA000-7FAFFF (base 16) AutomationX GmbH - Teslastraße 8 - Grambach Stmk 8074 - AUSTRIA - - 00-50-C2 (hex) Qtron Pty Ltd - 7FB000-7FBFFF (base 16) Qtron Pty Ltd - Unit 3/59 Township Drive - West Burleigh Queensland 4219 - AUSTRALIA - - 00-50-C2 (hex) TIS Dialog LLC - 7FC000-7FCFFF (base 16) TIS Dialog LLC - ul. Gen. Tolstikova 75 - Kaliningrad 236011 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Adeneo - 7FD000-7FDFFF (base 16) Adeneo - 2 chemin du ruisseau - Ecully 69136 - FRANCE - - 00-50-C2 (hex) Wireless Cables Inc. - 7FE000-7FEFFF (base 16) Wireless Cables Inc. - 1414 Soquel Ave, Ste 212 - Santa Cruz CA 95062 - UNITED STATES - - 00-50-C2 (hex) Shenzhen MaiWei Cable TV Equipment CO.,LTD. - 7FF000-7FFFFF (base 16) Shenzhen MaiWei Cable TV Equipment CO.,LTD. - 13/F,Fiyta Hi-tech Building,GaoXinnanyi Avenue,Southern District of Hi-tech Park,Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - 00-50-C2 (hex) Delphi Display Systems, Inc. - 800000-800FFF (base 16) Delphi Display Systems, Inc. - 3160 Pullman Street - Costa Mesa CA 92626 - UNITED STATES - - 00-50-C2 (hex) JANUS srl - 801000-801FFF (base 16) JANUS srl - Via Palu', 70 - San Vendemiano TV 31020 - ITALY - - 00-50-C2 (hex) PRIVATE - 802000-802FFF (base 16) - - 00-50-C2 (hex) dB Broadcast Limited - 803000-803FFF (base 16) dB Broadcast Limited - Kestrel House - Sedgeway Business Park - Witchford Cambridgeshire CB6 2HY - UNITED KINGDOM - - 00-50-C2 (hex) SoftSwitching Technologies - 804000-804FFF (base 16) SoftSwitching Technologies - 8155 Forsythia Street - Middleton WI 53562 - UNITED STATES - - 00-50-C2 (hex) MultimediaLED - 805000-805FFF (base 16) MultimediaLED - 11370 Sunrise Park Drive - Rancho Cordova California 95742 - UNITED STATES - - 00-50-C2 (hex) CET - 806000-806FFF (base 16) CET - via Enrico Fermi 1 - Zenson di Piave Treviso 31050 - ITALY - - 00-50-C2 (hex) TECHNOMARK - 807000-807FFF (base 16) TECHNOMARK - Parc d'activités STELYTEC - Saint-Chamond RA F-42400 - FRANCE - - 00-50-C2 (hex) ITB CompuPhase - 808000-808FFF (base 16) ITB CompuPhase - Eerste Industriestraat 19-21 - Bussum NH NL-1401VL - NETHERLANDS - - 00-50-C2 (hex) Varma Electronics Oy - 809000-809FFF (base 16) Varma Electronics Oy - Jarrumiehenkatu, 2B - Helsinki FIN-00520 - FINLAND - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 80A000-80AFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Str. 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Open Video, Inc. - 80B000-80BFFF (base 16) Open Video, Inc. - 65 Enterprise - Aliso Viejo CA 92656 - UNITED STATES - - 00-50-C2 (hex) Luxpert Technologies Co., Ltd. - 80C000-80CFFF (base 16) Luxpert Technologies Co., Ltd. - #812 Hanshin IT Tower, 235, Gurodong, Gurogu, - Seoul 152-768 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Acube Systems s.r.l. - 80D000-80DFFF (base 16) Acube Systems s.r.l. - via Tabacco, 58 - Bassano del Grappa Vicenza 36061 - ITALY - - 00-50-C2 (hex) Bruno International Ltd. - 80E000-80EFFF (base 16) Bruno International Ltd. - 14 Bar Kochva st. - Bney Berak TA 51261 - ISRAEL - - 00-50-C2 (hex) Selekron Microcontrol s.l. - 80F000-80FFFF (base 16) Selekron Microcontrol s.l. - C/ Peru, 8 - Guadalajara 19005 - SPAIN - - 00-50-C2 (hex) Alphion Corporation - 810000-810FFF (base 16) Alphion Corporation - 196 Princeton Hightstown Rd. - Building 1A - Princeton Junction NJ 08550 - UNITED STATES - - 00-50-C2 (hex) Open System Solutions Limited - 811000-811FFF (base 16) Open System Solutions Limited - Saltmakers House - Hamble Point Marina - Southampton Hampshire SO31 4NB - UNITED KINGDOM - - 00-50-C2 (hex) Femto SA - 812000-812FFF (base 16) Femto SA - Rue des Pres 137 - Biel/Bienne BE 2503 - SWITZERLAND - - 00-50-C2 (hex) Intelleflex Corporation - 813000-813FFF (base 16) Intelleflex Corporation - 2465 Augustine Dr - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) Telvent - 814000-814FFF (base 16) Telvent - Tamarguillo, 29 - Seville Seville 41006 - SPAIN - - 00-50-C2 (hex) microC Design SRL - 815000-815FFF (base 16) microC Design SRL - Str. Laptari Tei, Nr. 1 - Bl. 26, Sc.A, Ap. 48, Sector 2 - Bucuresti 023626 - ROMANIA - - 00-50-C2 (hex) Intelight Inc. - 816000-816FFF (base 16) Intelight Inc. - 3450 S Broadmont Drive #126 - Tucson Arizona 85713 - UNITED STATES - - 00-50-C2 (hex) Odin TeleSystems Inc - 817000-817FFF (base 16) Odin TeleSystems Inc - 800 E. Campbell Rd - Suite 334 - Richardson TX 75081-1873 - UNITED STATES - - 00-50-C2 (hex) Wireless Value BV - 818000-818FFF (base 16) Wireless Value BV - Waanderweg 30A - Emmen Dr. 7827 KJ - NETHERLANDS - - 00-50-C2 (hex) Cabinplant A/S - 819000-819FFF (base 16) Cabinplant A/S - Roesbjergvej 9 - Haarby Fyn 5683 - DENMARK - - 00-50-C2 (hex) InfoGLOBAL - 81A000-81AFFF (base 16) InfoGLOBAL - Manuel Pombo Angulo, 20 - Madrid 28050 - SPAIN - - 00-50-C2 (hex) Brain Tech Co., Ltd - 81B000-81BFFF (base 16) Brain Tech Co., Ltd - 5th Floor, Dong-Young Bldg., 580, - Pajang-Dong, Jangan-Gu - Suwon-City Kyunggi-Do 440-853 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Telcom - 81C000-81CFFF (base 16) Telcom - Svetog Nikole 27 - Beograd Serbia 11060 - YUGOSLAVIA - - 00-50-C2 (hex) IT SALUX CO., LTD. - 81D000-81DFFF (base 16) IT SALUX CO., LTD. - Suite 201, Woorim e-Biz center, 170-5, - Guro-dong, Guro-gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Channelot Ltd. - 81E000-81EFFF (base 16) Channelot Ltd. - 24 Raoul Wallenberg - Tel Aviv 69719 - ISRAEL - - 00-50-C2 (hex) 2N TELEKOMUNIKACE a.s. - 81F000-81FFFF (base 16) 2N TELEKOMUNIKACE a.s. - Modranska 621 - Prague 143 01 - CZECH REPUBLIC - - 00-50-C2 (hex) TESCAN, s.r.o. - 820000-820FFF (base 16) TESCAN, s.r.o. - Libusina tr. 21 - Brno 623 00 - CZECH REPUBLIC - - 00-50-C2 (hex) MISCO Refractometer - 821000-821FFF (base 16) MISCO Refractometer - 3401 Virginia Rd. - Cleveland OH 44122 - UNITED STATES - - 00-50-C2 (hex) Winner Technology Co, Ltd. - 822000-822FFF (base 16) Winner Technology Co, Ltd. - Rm707 GITEC 1121-9 Jungri - Naeseo - Masan Gyeng-Nam GN 630-857 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Robot Visual Systems GmbH - 823000-823FFF (base 16) Robot Visual Systems GmbH - Opladener Strasse 202 - Monheim 40789 - GERMANY - - 00-50-C2 (hex) SMT d.o.o. - 824000-824FFF (base 16) SMT d.o.o. - Liminjanska 96 - Portoroz Slovenia 6320 - SLOVENIA - - 00-50-C2 (hex) Funkwerk Information Technologies Karlsfeld GmbH - 825000-825FFF (base 16) Funkwerk Information Technologies Karlsfeld GmbH - Dieselstr. 8 - Karlsfeld 85757 - GERMANY - - 00-50-C2 (hex) HEWI Heinrich Wilke GmbH - 826000-826FFF (base 16) HEWI Heinrich Wilke GmbH - Prof.-Bier-Str. 1-5 - Bad Arolsen Hessen 34454 - GERMANY - - 00-50-C2 (hex) Enero Solutions inc. - 827000-827FFF (base 16) Enero Solutions inc. - 5764 Monkland Ave., Suite 100, - Montreal Quebec H4A 1E9 - CANADA - - 00-50-C2 (hex) SLICAN sp. z o.o. - 828000-828FFF (base 16) SLICAN sp. z o.o. - ul.M.Konopnickiej 18 - Bydgoszcz Kujawsko-Pomorskie 85-124 - POLAND - - 00-50-C2 (hex) Intellectronika - 829000-829FFF (base 16) Intellectronika - Semchenko st., 6 - Perm Perm region 614022 - RUSSIAN FEDERATION - - 00-50-C2 (hex) VDC Display Systems - 82A000-82AFFF (base 16) VDC Display Systems - 7177 N. Atlantic Avenue - Cape Canaveral FL 32920 - UNITED STATES - - 00-50-C2 (hex) Keith & Koep GmbH - 82B000-82BFFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Vitel Net - 82C000-82CFFF (base 16) Vitel Net - 8701 Greensboro Dr. - Ste 600 - McLean VA 22102 - UNITED STATES - - 00-50-C2 (hex) Elmec, Inc. - 82D000-82DFFF (base 16) Elmec, Inc. - 61 Hayotzrim Street - Karmiel Haifa 20101 - ISRAEL - - 00-50-C2 (hex) LogiCom GmbH - 82E000-82EFFF (base 16) LogiCom GmbH - Gautinger Strasse 51 - Krailling Bayern 82152 - GERMANY - - 00-50-C2 (hex) Momentum Data Systems - 82F000-82FFFF (base 16) Momentum Data Systems - 17330 Brookhurst Street - Suite 230 - Fountain Valley CA 92708 - UNITED STATES - - 00-50-C2 (hex) CompuShop Services LLC - 830000-830FFF (base 16) CompuShop Services LLC - 7517 Washington Ave S - Edina MN 55439 - UNITED STATES - - 00-50-C2 (hex) St Jude Medical, Inc. - 831000-831FFF (base 16) St Jude Medical, Inc. - One St Jude Medical Dr - St Paul MN 55117 - UNITED STATES - - 00-50-C2 (hex) S1nn GmbH & Co. KG - 832000-832FFF (base 16) S1nn GmbH & Co. KG - Entennest 1 - Esslingen Baden-Württemberg 73730 - GERMANY - - 00-50-C2 (hex) LaserLinc, Inc. - 833000-833FFF (base 16) LaserLinc, Inc. - 777 Zapata Drive - Fairborn OH 45324 - UNITED STATES - - 00-50-C2 (hex) ANTEK GmbH - 834000-834FFF (base 16) ANTEK GmbH - Im Koechersgrund 3 - Beilstein Baden-Württemberg 71717 - GERMANY - - 00-50-C2 (hex) Communications Laboratories Inc - 835000-835FFF (base 16) Communications Laboratories Inc - 750 North Drive - Melbourne Florida 32934-9281 - UNITED STATES - - 00-50-C2 (hex) DSP DESIGN - 836000-836FFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) ID-KARTA s.r.o. - 837000-837FFF (base 16) ID-KARTA s.r.o. - Hlavni 3 - Opava 747 70 - CZECH REPUBLIC - - 00-50-C2 (hex) T PROJE MUHENDISLIK DIS. TIC. LTD. STI. - 838000-838FFF (base 16) T PROJE MUHENDISLIK DIS. TIC. LTD. STI. - RIHTIM CAD. NEMLIZADE SOK. DUYGU APT. - NO: 35 / 2 KADIKOY - ISTANBUL 34716 - TURKEY - - 00-50-C2 (hex) IMS Röntgensysteme GmbH - 839000-839FFF (base 16) IMS Röntgensysteme GmbH - Dieselstraße 52 - Heiligenhaus Nordrhein-Westfalen 42579 - GERMANY - - 00-50-C2 (hex) Syr-Tec Engineering & Marketing - 83A000-83AFFF (base 16) Syr-Tec Engineering & Marketing - 13 Hayahalom St. - Holon Tel-Aviv 58678 - ISRAEL - - 00-50-C2 (hex) O. Bay AG - 83B000-83BFFF (base 16) O. Bay AG - Luzernstrasse 45 - Subingen Solothurn 4553 - SWITZERLAND - - 00-50-C2 (hex) hema electronic GmbH - 83C000-83CFFF (base 16) hema electronic GmbH - Röntgenstraße 31 - Aalen Baden-Württemberg 73431 - GERMANY - - 00-50-C2 (hex) beroNet GmbH - 83D000-83DFFF (base 16) beroNet GmbH - Friedrichstr. 231 - Berlin 10969 - GERMANY - - 00-50-C2 (hex) KPE spol. s r.o. - 83E000-83EFFF (base 16) KPE spol. s r.o. - Blattného 2313 - Praha CZ 15800 - CZECH REPUBLIC - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 83F000-83FFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - UNITED STATES - - 00-50-C2 (hex) Residential Control Systems - 840000-840FFF (base 16) Residential Control Systems - 11460 Sunrise Gold Circle - Suite A - Rancho Cordova CA 95742 - UNITED STATES - - 00-50-C2 (hex) Connection Electronics Ltd. - 841000-841FFF (base 16) Connection Electronics Ltd. - Unit 6A, 28/F, Cable TV Tower, - 9 Hoi Shing Road, - Tsuen Wan, NT - HONG KONG - - 00-50-C2 (hex) Quantum Controls BV - 842000-842FFF (base 16) Quantum Controls BV - Industriestraat 5 - Nuth Limburg 6361 HD - NETHERLANDS - - 00-50-C2 (hex) Xtensor Systems Inc. - 843000-843FFF (base 16) Xtensor Systems Inc. - 2624 Citronella Ct. - Simi Valley California 93063-2232 - UNITED STATES - - 00-50-C2 (hex) Prodigy Electronics Limited - 844000-844FFF (base 16) Prodigy Electronics Limited - 808 Futura Plaza, 111-113 How Ming St. - Kwun Tong, Kowloon - Guangdong - HONG KONG - - 00-50-C2 (hex) VisualSonics Inc. - 845000-845FFF (base 16) VisualSonics Inc. - 3080 Yonge St - Suite 6100, Box 66 - Toronto Ontario M4N3N1 - CANADA - - 00-50-C2 (hex) ESP-Planning Co. - 846000-846FFF (base 16) ESP-Planning Co. - Hukujucho Hirakata 2-51 - WorkShop GifuHasjima 2F - Hashima-shi Gifu-ken 501-6257 - JAPAN - - 00-50-C2 (hex) Lars Morich Kommunikationstechnik GmbH - 847000-847FFF (base 16) Lars Morich Kommunikationstechnik GmbH - Friedrich-Ebert-Str. 27 - 65604 Elz - GERMANY - - 00-50-C2 (hex) DASA ROBOT Co., Ltd. - 848000-848FFF (base 16) DASA ROBOT Co., Ltd. - 11th Floor Bucheon Techno Park Bldg. 401 Yakdae0dong, Wonmi-gu, Bucheon-city Gyunggi-do, Republic of Korea - Bucheon Gyunggi-do 420-734 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Design Analysis Associates, Inc. - 849000-849FFF (base 16) Design Analysis Associates, Inc. - 75 West 100 South - Logan UT 84321 - UNITED STATES - - 00-50-C2 (hex) Keystone Electronic Solutions - 84A000-84AFFF (base 16) Keystone Electronic Solutions - 103 Club Avenue - Waterkloof Heights - Pretoria Gauteng 0181 - SOUTH AFRICA - - 00-50-C2 (hex) TASK SISTEMAS DE COMPUTACAO LTDA - 84B000-84BFFF (base 16) TASK SISTEMAS DE COMPUTACAO LTDA - Rua Visconde de Ouro Preto - numero 5, 8 andar - rio de janeiro 22250-180 - BRAZIL - - 00-50-C2 (hex) Performance Motion Devices - 84C000-84CFFF (base 16) Performance Motion Devices - 80 Central St. - Boxborough MA 01719 - UNITED STATES - - 00-50-C2 (hex) BMTI - 84D000-84DFFF (base 16) BMTI - ZI Camp Laurent - La Seyne Var 83500 - FRANCE - - 00-50-C2 (hex) DRACO SYSTEMS - 84E000-84EFFF (base 16) DRACO SYSTEMS - Edifici CIM Valles of. 61-62 - Sta. Perpetua de Mogoda Barcelona 08130 - SPAIN - - 00-50-C2 (hex) Gamber-Johnson LLC - 84F000-84FFFF (base 16) Gamber-Johnson LLC - 3001 Borham Avenue - Stevens Point WI 54481 - UNITED STATES - - 00-50-C2 (hex) K.K. Rocky - 850000-850FFF (base 16) K.K. Rocky - NK bldg. 2F - 1-16-7, Kamiochiai, - Shinjyuku-Ku, Tokyo, 161-0034 - JAPAN - - 00-50-C2 (hex) SPJ Embedded Technologies Pvt. Ltd. - 851000-851FFF (base 16) SPJ Embedded Technologies Pvt. Ltd. - 101, Beaver Grandeur, Baner Road - Pune Maharashtra 411045 - INDIA - - 00-50-C2 (hex) eInfochips Ltd. - 852000-852FFF (base 16) eInfochips Ltd. - 11 A/B, Karmabhumi, Off C.G. Road, - Behind Cargo Motors - Ahmedabad Gujarat 380006 - INDIA - - 00-50-C2 (hex) Ettus Research LLC - 853000-853FFF (base 16) Ettus Research LLC - 1043 N Shoreline Blvd - Suite 100 - Mountain View CA 94043 - UNITED STATES - - 00-50-C2 (hex) Ratioplast-Optoelectronics GmbH - 854000-854FFF (base 16) Ratioplast-Optoelectronics GmbH - Jockweg 66 - Lübbecke NRW D-32312 - GERMANY - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - 855000-855FFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu Street, district 1, - DISTRICT 1, CODE - Bucharest 014186 - ROMANIA - - 00-50-C2 (hex) CT Company - 856000-856FFF (base 16) CT Company - Nizhni Krasnoselsky st., 35. - Moscow 140070 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Grupo Epelsa S.L. - 857000-857FFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) Wireless Acquisition LLC - 858000-858FFF (base 16) Wireless Acquisition LLC - 1215 S. Park Lane - Suite #4 - Tempe, AZ 85281 - UNITED STATES - - 00-50-C2 (hex) Nuvation - 859000-859FFF (base 16) Nuvation - 3590 North First St. - San Jose CA 95134 - UNITED STATES - - 00-50-C2 (hex) ART Spa - 85A000-85AFFF (base 16) ART Spa - Voc.Pischiello - 20 06065 Passignano sul Trasimeno (PG) - ITALY - - 00-50-C2 (hex) Boreste - 85B000-85BFFF (base 16) Boreste - Rua Lauro Linhares, 589 - Trindade - Florianopolis SC 88036-001 - BRAZIL - - 00-50-C2 (hex) B S E - 85C000-85CFFF (base 16) B S E - BP 87 - 616 AVENUE DE L EUROPE - LE CREUSOT 71200 - FRANCE - - 00-50-C2 (hex) Ing. Knauseder Mechatronik GmbH - 85D000-85DFFF (base 16) Ing. Knauseder Mechatronik GmbH - Maierhof 12 - Aurolzmuenster AUSTRIA 4971 - AUSTRIA - - 00-50-C2 (hex) Radiometer Medical ApS - 85E000-85EFFF (base 16) Radiometer Medical ApS - Aakandevej 21 - Broenshoej Copenhagen 2700 - DENMARK - - 00-50-C2 (hex) General Dynamics C4 Systems - 85F000-85FFFF (base 16) General Dynamics C4 Systems - 8220 East Roosevelt Street - MD: R1122 - Scottsdale Arizona 85257 - UNITED STATES - - 00-50-C2 (hex) Eutron S.p.A. - 860000-860FFF (base 16) Eutron S.p.A. - Via Gandhi, 12 (Head office) - Treviolo Bergamo 24048 - ITALY - - 00-50-C2 (hex) Grantronics Pty Ltd - 861000-861FFF (base 16) Grantronics Pty Ltd - 45 Monash Street - PO Box 275 - Wentworthville NSW 2145 - AUSTRALIA - - 00-50-C2 (hex) Elsys AG - 862000-862FFF (base 16) Elsys AG - Mellingerstrasse 12 - Niederrohrdorf AG 5443 - SWITZERLAND - - 00-50-C2 (hex) Advanced Technology Solutions - 863000-863FFF (base 16) Advanced Technology Solutions - Seybelgasse 13 - Vienna 1100 - AUSTRIA - - 00-50-C2 (hex) ATG Automatisierungstechnik GERA GmbH - 864000-864FFF (base 16) ATG Automatisierungstechnik GERA GmbH - Keplerstr. 10-12 - Gera Thuringia 07549 - GERMANY - - 00-50-C2 (hex) Persy Control Services B.v. - 865000-865FFF (base 16) Persy Control Services B.v. - Veldoven 4a - Hendrik Ido Ambacht Zuid Holland 3223PJ - NETHERLANDS - - 00-50-C2 (hex) Saia Burgess Controls AG - 866000-866FFF (base 16) Saia Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Syntronics - 867000-867FFF (base 16) Syntronics - 3500 Shannon Park Dr. - Fredericksburg VA 22408 - UNITED STATES - - 00-50-C2 (hex) Aethon, Inc. - 868000-868FFF (base 16) Aethon, Inc. - 100 Business Center Drive - Pittsburgh PA 15205 - UNITED STATES - - 00-50-C2 (hex) Funkwerk plettac electronic GmbH - 869000-869FFF (base 16) Funkwerk plettac electronic GmbH - Wuerzburger Strasse 150 - Fuerth Bavaria 90760 - GERMANY - - 00-50-C2 (hex) USM Systems, Ltd - 86A000-86AFFF (base 16) USM Systems, Ltd - Suite 1 - 3500 West Eleven Mile Road - Berkley Michigan 48072 - UNITED STATES - - 00-50-C2 (hex) OMB Sistemas Electronicos S.A. - 86B000-86BFFF (base 16) OMB Sistemas Electronicos S.A. - Avd San Antonio - Cuarte de Huerva Zaragoza 50410 - SPAIN - - 00-50-C2 (hex) Condigi Televagt A/S - 86C000-86CFFF (base 16) Condigi Televagt A/S - Niels Bohrs vej 42, Stilling - Skanderborg jylland 8660 - DENMARK - - 00-50-C2 (hex) Tieline Research Pty Ltd - 86D000-86DFFF (base 16) Tieline Research Pty Ltd - PO Box 2092 - Malaga Western Australia 6944 - AUSTRALIA - - 00-50-C2 (hex) HANYANG ELECTRIC CP., LTD - 86E000-86EFFF (base 16) HANYANG ELECTRIC CP., LTD - 603-2, Janggok-ri, Jori-eup - Paju Gyeonggi-do 413-825 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) b-plus GmbH - 86F000-86FFFF (base 16) b-plus GmbH - Ulrichsbergerstr. 17 - Deggendorf Bavaria 94469 - GERMANY - - 00-50-C2 (hex) LOGEL S.R.L. - 870000-870FFF (base 16) LOGEL S.R.L. - VIA DELLA TECNICA 13/A-13/B - CASTELNUOVO RANGONE MODENA 41051 - ITALY - - 00-50-C2 (hex) R-S-I Elektrotechnik GmbH & Co. KG - 871000-871FFF (base 16) R-S-I Elektrotechnik GmbH & Co. KG - Woelkestrasse 11 - Schweitenkirchen Bayern 85301 - GERMANY - - 00-50-C2 (hex) Oliotalo Oy - 872000-872FFF (base 16) Oliotalo Oy - Sinikalliontie 18 B - 02630 Espoo - FINLAND - - 00-50-C2 (hex) XRONET Corporation - 873000-873FFF (base 16) XRONET Corporation - 3rd flr., Sunae Bldg., 6-4, Sunae-dong, - Bundang-gu - Seongnam Gyeonggi 463-020 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Arcos Technologies Ltd. - 874000-874FFF (base 16) Arcos Technologies Ltd. - 26 Hasivim St. - P.O.B 7041 - Petakh-Tikva 49517 - ISRAEL - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 875000-875FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Privatquelle Gruber GmbH & CO KG - 876000-876FFF (base 16) Privatquelle Gruber GmbH & CO KG - Innsbrucker Strasse 38 - Brixlegg Austria/Tirol 6230 - AUSTRIA - - 00-50-C2 (hex) Motion Analysis Corp - 877000-877FFF (base 16) Motion Analysis Corp - 3617 Westwind Blvd - Santa Rosa CA 95403 - UNITED STATES - - 00-50-C2 (hex) Acoustic Research Laboratories Pty Ltd - 878000-878FFF (base 16) Acoustic Research Laboratories Pty Ltd - Level 7, Building 2, 423 Pennant Hills Road - Pennant Hills NSW 2120 - AUSTRALIA - - 00-50-C2 (hex) MILESYS - 879000-879FFF (base 16) MILESYS - 7 Ter rue de la porte de buc - VERSAILLES YVELINES 78000 - FRANCE - - 00-50-C2 (hex) Spectrum Management, LC - 87A000-87AFFF (base 16) Spectrum Management, LC - 1020 Hoosier Dr. - Larkspur CO 80118 - UNITED STATES - - 00-50-C2 (hex) UAVNavigation S.L. - 87B000-87BFFF (base 16) UAVNavigation S.L. - Av. Doctor Severo Ochoa - Nº 45, 1º A - Alcobendas Madrid 28100 - SPAIN - - 00-50-C2 (hex) Arcontia AB - 87C000-87CFFF (base 16) Arcontia AB - Gruvgatan 35A - Gothenburg Vastra Frolunda S-421 30 - SWEDEN - - 00-50-C2 (hex) AT&T Government Solutions - 87D000-87DFFF (base 16) AT&T Government Solutions - 11301 Corporate Blvd. - Suite 110 - Orlando FL 32817 - UNITED STATES - - 00-50-C2 (hex) SCM PRODUCTS, INC. - 87E000-87EFFF (base 16) SCM PRODUCTS, INC. - 155 RICEFIELD LANE - HAUPPAUGE NEW YORK 11788 - UNITED STATES - - 00-50-C2 (hex) Optoelettronica Italia S.r.l. - 87F000-87FFFF (base 16) Optoelettronica Italia S.r.l. - via Vienna 8 - settore D - Trento Trento 38121 - ITALY - - 00-50-C2 (hex) Creation Technologies Chicago - 880000-880FFF (base 16) Creation Technologies Chicago - 1475 S. Wheeling Rd. - Wheeling IL 60090 - UNITED STATES - - 00-50-C2 (hex) InnoTrans Communications, Inc. - 881000-881FFF (base 16) InnoTrans Communications, Inc. - 22 Great Oaks Blvd - #100 - San Jose CA 95119 - UNITED STATES - - 00-50-C2 (hex) WARECUBE,INC. - 882000-882FFF (base 16) WARECUBE,INC. - 36-12 - Dang-Dong - Gunpo-Si Gyeonggi-Do 435-010 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Neocontrol Soluções em Automação - 883000-883FFF (base 16) Neocontrol Soluções em Automação - Rua Alagoas 1160, 10. andar - Belo Horizonte Minas Gerais 30130-912 - BRAZIL - - 00-50-C2 (hex) IP Thinking A/S - 884000-884FFF (base 16) IP Thinking A/S - Karl Bjarnhofsvej 13 - Vejle Jylland 7120 - DENMARK - - 00-50-C2 (hex) OOO "NTK "IMOS" - 885000-885FFF (base 16) OOO "NTK "IMOS" - Politekhnicheskaia str. 22 - Saint-Petersburg Nord-West 194021 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Transas Scandinavia AB - 886000-886FFF (base 16) Transas Scandinavia AB - Datavagen 37 - Askim Vastra Gotaland 436 32 - SWEDEN - - 00-50-C2 (hex) Inventis Technology Pty Limited - 887000-887FFF (base 16) Inventis Technology Pty Limited - Block A, Unit 40 - 1-3 Endeavour Road - Caringbah NSW 2229 - AUSTRALIA - - 00-50-C2 (hex) IADEA CORPORATION - 888000-888FFF (base 16) IADEA CORPORATION - 3F, NO.33, LANE 77, XING-AI ROAD - TAIPEI 114 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) ACS Motion Control Ltd. - 889000-889FFF (base 16) ACS Motion Control Ltd. - SHAUL AMOR BLV RAMAT GABRIEL - MIGDAL HA'EMEQ ISRAEL 10500 - ISRAEL - - 00-50-C2 (hex) Continental Electronics Corp. - 88A000-88AFFF (base 16) Continental Electronics Corp. - 4212 S. Buckner Blvd. - Dallas TX 75227 - UNITED STATES - - 00-50-C2 (hex) Hollis Electronics Company LLC - 88B000-88BFFF (base 16) Hollis Electronics Company LLC - 5 Northern Blvd., Unit #13 - Amherst NH 03031 - UNITED STATES - - 00-50-C2 (hex) Z-App Systems - 88C000-88CFFF (base 16) Z-App Systems - 2210 North First St - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) L3 Communications Nova Engineering - 88D000-88DFFF (base 16) L3 Communications Nova Engineering - 5 Circle Freeway Drive - Cincinnati OH 45246 - UNITED STATES - - 00-50-C2 (hex) Cardinal Scale Mfg Co - 88E000-88EFFF (base 16) Cardinal Scale Mfg Co - 203 E. Daugherty - Webb City MO 64870 - UNITED STATES - - 00-50-C2 (hex) Keynote SIGOS GmbH - 88F000-88FFFF (base 16) Keynote SIGOS GmbH - Klingenhofstraße 50d - Nürnberg Bayern 90411 - GERMANY - - 00-50-C2 (hex) BAE Systems Hägglunds AB - 890000-890FFF (base 16) BAE Systems Hägglunds AB - Björnavägen 41 - Örnsköldsvik Västernorrland 891 82 - SWEDEN - - 00-50-C2 (hex) Admiral Secure Products, Ltd. - 891000-891FFF (base 16) Admiral Secure Products, Ltd. - 15-6400 Millcreek Drive - Unit 361 - Mississauga Ontario L5N 3E7 - CANADA - - 00-50-C2 (hex) Trakce a.s. - 892000-892FFF (base 16) Trakce a.s. - Hlavkova 3 - Ostrava Privoz 70200 - CZECH REPUBLIC - - 00-50-C2 (hex) EIZO Technologies GmbH - 893000-893FFF (base 16) EIZO Technologies GmbH - BGM-Seidl-Strasse 8 - Wolfratshausen Bavaria / Bayern 82515 - GERMANY - - 00-50-C2 (hex) Shockfish SA - 894000-894FFF (base 16) Shockfish SA - Parc Scientifique - PSE-C - Lausanne VD 1015 - SWITZERLAND - - 00-50-C2 (hex) Marine Communications Limited - 895000-895FFF (base 16) Marine Communications Limited - 59, Bownham Park - Rodborough Common - Stroud Glos GL5 5BZ - UNITED KINGDOM - - 00-50-C2 (hex) Blankom - 896000-896FFF (base 16) Blankom - Hermann-Petersilge-Str. 1 - Bad Blankenburg Thuringia 07422 - GERMANY - - 00-50-C2 (hex) ODF Optronics, Inc. - 897000-897FFF (base 16) ODF Optronics, Inc. - 6112 Trotter Ridge Road - Summerfield NC 27358 - UNITED STATES - - 00-50-C2 (hex) Veeco Process Equipment, Inc. - 898000-898FFF (base 16) Veeco Process Equipment, Inc. - 2330 E. Prospect Rd. - Fort Collins Colorado 80526 - UNITED STATES - - 00-50-C2 (hex) Inico Technologies Ltd. - 899000-899FFF (base 16) Inico Technologies Ltd. - #119 - 3553 31st Street NW - Calgary Alberta T2L 2K7 - CANADA - - 00-50-C2 (hex) Neptune Technology Group, Inc. - 89A000-89AFFF (base 16) Neptune Technology Group, Inc. - 1600 AL HWY 229 S - Tallassee Alabama 36078 - UNITED STATES - - 00-50-C2 (hex) Sensata Technologies, Inc. - 89B000-89BFFF (base 16) Sensata Technologies, Inc. - 4467 White Bear Parkway - White Bear Lake MN 55110 - UNITED STATES - - 00-50-C2 (hex) Mediana - 89C000-89CFFF (base 16) Mediana - Wonju Medical Industry Park, 1650-1 Donghwa-Ri, - Wonju-Si Gangwon-Do 220-801 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Systemtechnik GmbH - 89D000-89DFFF (base 16) Systemtechnik GmbH - Wielandstraße 12 - Sömmerda Thuringia 99610 - GERMANY - - 00-50-C2 (hex) Broadcast Electronics - 89E000-89EFFF (base 16) Broadcast Electronics - 4100 N. 24th - Quincy IL 62305 - UNITED STATES - - 00-50-C2 (hex) Datalink Technologies Gateways Inc. - 89F000-89FFFF (base 16) Datalink Technologies Gateways Inc. - 3888 Sound Way - Bellingham WA 98226 - UNITED STATES - - 00-50-C2 (hex) Specialized Communications Corp. - 8A0000-8A0FFF (base 16) Specialized Communications Corp. - 20940 Twin Springs Drive - Smithsburg Maryland 21783 - UNITED STATES - - 00-50-C2 (hex) Intune Networks Limited - 8A1000-8A1FFF (base 16) Intune Networks Limited - 9b Beckett Way - Park West - Dublin 12 - IRELAND - - 00-50-C2 (hex) UAVISION Engenharia de Sistemas - 8A2000-8A2FFF (base 16) UAVISION Engenharia de Sistemas - Ed Inovisa Inst. Sup. Agro Tapada da Ajuda - Lisbon 1349-017 - PORTUGAL - - 00-50-C2 (hex) RTW GmbH & Co.KG - 8A3000-8A3FFF (base 16) RTW GmbH & Co.KG - Elbeallee 19 - Köln NRW 50765 - GERMANY - - 00-50-C2 (hex) BALOGH T.A.G Corporation - 8A4000-8A4FFF (base 16) BALOGH T.A.G Corporation - 7699 Kensington Court - Brighton Michigan 48116-8561 - UNITED STATES - - 00-50-C2 (hex) Mocon, Inc. - 8A5000-8A5FFF (base 16) Mocon, Inc. - 7500 Boone Avenue North - Minneapolis MN 55428 - UNITED STATES - - 00-50-C2 (hex) SELCO - 8A6000-8A6FFF (base 16) SELCO - ZI DU VAL D'OMBREE - COMBREE SA 49520 - FRANCE - - 00-50-C2 (hex) PIXEYE LTD - 8A7000-8A7FFF (base 16) PIXEYE LTD - #75 Dondukov blvd. - Sofia 1504 - BULGARIA - - 00-50-C2 (hex) ALTEK ELECTRONICS - 8A8000-8A8FFF (base 16) ALTEK ELECTRONICS - 89 Commercial Blvd - PO BOX 1128 - Torrington CT 06790 - UNITED STATES - - 00-50-C2 (hex) Intelligent Security Systems - 8A9000-8A9FFF (base 16) Intelligent Security Systems - Office 102, str. 77, vl. 1, Leninskie Gory, MSU Science Park - Moscow 119234 - RUSSIAN FEDERATION - - 00-50-C2 (hex) ATS Elektronik GmbH - 8AA000-8AAFFF (base 16) ATS Elektronik GmbH - Albert-Einstein-Straße 3 - Wunstorf Lower saxony 31515 - GERMANY - - 00-50-C2 (hex) Nanomotion Ltd. - 8AB000-8ABFFF (base 16) Nanomotion Ltd. - Mordot HaCarmel Industrial Park - 3 HaYetsira St. - Yokneam 20692 - ISRAEL - - 00-50-C2 (hex) Telsa s.r.l - 8AC000-8ACFFF (base 16) Telsa s.r.l - Via C.Colombo 29\31 - Osio Sotto Bergamo 24046 - ITALY - - 00-50-C2 (hex) Thales Communications, Inc - 8AD000-8ADFFF (base 16) Thales Communications, Inc - 22605 Gateway Center Drive - Clarksburg MD 20871 - UNITED STATES - - 00-50-C2 (hex) DESARROLLO DE SISTEMAS INTEGRADOS DE CONTROL S.A. - 8AE000-8AEFFF (base 16) DESARROLLO DE SISTEMAS INTEGRADOS DE CONTROL S.A. - C/FEDANCI 8-10, 3º-3ª - SANT CUGAT DEL VALLES BARCELONA 08174 - SPAIN - - 00-50-C2 (hex) Xelerated - 8AF000-8AFFFF (base 16) Xelerated - Olof Palmes gata 29 - Stockholm SE-11122 - SWEDEN - - 00-50-C2 (hex) BK Innovation, Inc. - 8B0000-8B0FFF (base 16) BK Innovation, Inc. - 1016 Morse Ave - Suite 14 - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) RingCube Technologies, Inc. - 8B1000-8B1FFF (base 16) RingCube Technologies, Inc. - 3990 Freedom Circle, Suite 200 - Santa Clara CA 95050 - UNITED STATES - - 00-50-C2 (hex) SERVAIND SA. - 8B2000-8B2FFF (base 16) SERVAIND SA. - Colombres 873 - Capital Federal Buenos Aires C1218ABI - ARGENTINA - - 00-50-C2 (hex) VTQ Videtronik GmbH - 8B3000-8B3FFF (base 16) VTQ Videtronik GmbH - Gruene Str. 2 - Querfurt Saxon-Anhalt 06268 - GERMANY - - 00-50-C2 (hex) Sandar Telecast AS - 8B4000-8B4FFF (base 16) Sandar Telecast AS - Borgeskogen - Stokke 3160 - NORWAY - - 00-50-C2 (hex) Keith & Koep GmbH - 8B5000-8B5FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Shadrinskiy Telefonny Zavod - 8B6000-8B6FFF (base 16) Shadrinskiy Telefonny Zavod - 16, Komsomolskaya str. - Shadrinsk Kurganskaya obl. 641870 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Calnex Solutions Limited - 8B7000-8B7FFF (base 16) Calnex Solutions Limited - Springfield - Linlithgow West Lothian EH49 7NX - UNITED KINGDOM - - 00-50-C2 (hex) DSS Networks, Inc. - 8B8000-8B8FFF (base 16) DSS Networks, Inc. - 23 Spectrum Pointe Drive - Suite 202 - Lake Forest CA 92630 - UNITED STATES - - 00-50-C2 (hex) ACD Elektronik Gmbh - 8B9000-8B9FFF (base 16) ACD Elektronik Gmbh - Engelberg 2 - Achstetten Bawu 88480 - GERMANY - - 00-50-C2 (hex) Fr. Sauter AG - 8BA000-8BAFFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS CH 4016 - SWITZERLAND - - 00-50-C2 (hex) smtag international ag - 8BB000-8BBFFF (base 16) smtag international ag - Bahnhofstrasse 198 - Wetzikon Zürich 8620 - SWITZERLAND - - 00-50-C2 (hex) Honeywell Sensotec - 8BC000-8BCFFF (base 16) Honeywell Sensotec - 2080 Arlingate Ln. - Columbus Ohio 43228 - UNITED STATES - - 00-50-C2 (hex) Matrix Switch Corporation - 8BD000-8BDFFF (base 16) Matrix Switch Corporation - 17720 Retrac Way - Grass Valley CA 95949 - UNITED STATES - - 00-50-C2 (hex) The Pennsylvania State University - 8BE000-8BEFFF (base 16) The Pennsylvania State University - 0165 ARL Building - PO Box 30 - State College PA 16804-0030 - UNITED STATES - - 00-50-C2 (hex) ARISTO Graphic Systeme GmbH & Co. KG - 8BF000-8BFFFF (base 16) ARISTO Graphic Systeme GmbH & Co. KG - Schnackenburgallee 117 - Hamburg 22525 - GERMANY - - 00-50-C2 (hex) S.C.E. s.r.l. - 8C0000-8C0FFF (base 16) S.C.E. s.r.l. - Via Giardini 1271/A - Modena Mo 41100 - ITALY - - 00-50-C2 (hex) Heraeus Noblelight GmbH - 8C1000-8C1FFF (base 16) Heraeus Noblelight GmbH - Heraeusstrasse 12-14 - Hanau Hessen 63450 - GERMANY - - 00-50-C2 (hex) Access Control Systems JSC - 8C2000-8C2FFF (base 16) Access Control Systems JSC - 65, Serdobolskaya st. - St-Petersburg 197342 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Byte Paradigm - 8C3000-8C3FFF (base 16) Byte Paradigm - Chaussée de Namur, 119 - Nivelles (Thines) Brabant 1402 - BELGIUM - - 00-50-C2 (hex) Soldig Industria e Comercio de Equipamentos Eletronicos LTDA - 8C4000-8C4FFF (base 16) Soldig Industria e Comercio de Equipamentos Eletronicos LTDA - Av. Ipiranga 6681 Building 94 Room 7 - Porto Alegre RS 90619-900 - BRAZIL - - 00-50-C2 (hex) Vortex Engineering pvt ltd - 8C5000-8C5FFF (base 16) Vortex Engineering pvt ltd - no 14, Palayakaran street,Ekkaduthangal - Chennai Tamilnadu 600097 - INDIA - - 00-50-C2 (hex) Gradual Tecnologia Ltda. - 8C6000-8C6FFF (base 16) Gradual Tecnologia Ltda. - Rua Attilio Giaretta, 110 - Itatiba SP 13257-584 - BRAZIL - - 00-50-C2 (hex) Tattile srl - 8C7000-8C7FFF (base 16) Tattile srl - via G.Donizetti 1/3/5 - Mairano - Brescia Italy 25030 - ITALY - - 00-50-C2 (hex) Pumatronix Equipamentos Eletrônicos Ltda - 8C8000-8C8FFF (base 16) Pumatronix Equipamentos Eletrônicos Ltda - Rua Algacyr Munhoz Mader, 3775 - CIC - Curitiba Paraná 81350-010 - BRAZIL - - 00-50-C2 (hex) A+S Aktuatorik und Sensorik GmbH - 8C9000-8C9FFF (base 16) A+S Aktuatorik und Sensorik GmbH - Franz-Wienholz-Str. 16 - Prenzlau Brandenburg 17291 - GERMANY - - 00-50-C2 (hex) Altair semiconductor Ltd - 8CA000-8CAFFF (base 16) Altair semiconductor Ltd - 6 Ha'arash St. - Hod Hasharon 45240 - ISRAEL - - 00-50-C2 (hex) Beonic Corporation - 8CB000-8CBFFF (base 16) Beonic Corporation - 141 Gilbert Street - Adelaide S.A. 5000 - AUSTRALIA - - 00-50-C2 (hex) LyconSys GmbH & Co.KG - 8CC000-8CCFFF (base 16) LyconSys GmbH & Co.KG - Schleusenstr. 9 - Frankfurt am Main Hesse 60327 - GERMANY - - 00-50-C2 (hex) Cambridge Sound Management, LLC - 8CD000-8CDFFF (base 16) Cambridge Sound Management, LLC - 27 Moulton Street - Cambridge MA 02138 - UNITED STATES - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 8CE000-8CEFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - UNITED STATES - - 00-50-C2 (hex) GigaLinx Ltd. - 8CF000-8CFFFF (base 16) GigaLinx Ltd. - 6A Massada St. - Hod Hasharon 45294 - ISRAEL - - 00-50-C2 (hex) Saia-Burgess Controls AG - 8D0000-8D0FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Bachmann Monitoring GmbH - 8D1000-8D1FFF (base 16) Bachmann Monitoring GmbH - Weimarische Strasse 10 - Rudolstadt Thueringen 07407 - GERMANY - - 00-50-C2 (hex) TTi Ltd - 8D2000-8D2FFF (base 16) TTi Ltd - Glebe Road - Huntingdon Cambridgeshire PE29 7DR - UNITED KINGDOM - - 00-50-C2 (hex) IFAM GmbH - 8D3000-8D3FFF (base 16) IFAM GmbH - Parselvalstr. 2 - Erfurt Thuringia 99092 - GERMANY - - 00-50-C2 (hex) Internet Protocolo Lógica SL - 8D4000-8D4FFF (base 16) Internet Protocolo Lógica SL - Ramón y Cajal 5 - Centro de Empresas, Local 25 - Alcobendas Madrid 28100 - SPAIN - - 00-50-C2 (hex) Peek Traffic Corp - 8D5000-8D5FFF (base 16) Peek Traffic Corp - 2511 Corporate Way - Palmetto Fl 34221 - UNITED STATES - - 00-50-C2 (hex) UltraVision Security Systems, Inc. - 8D6000-8D6FFF (base 16) UltraVision Security Systems, Inc. - 88 Stiles Road - Suite 103 - Salem NH 03079 - UNITED STATES - - 00-50-C2 (hex) Polygon Informatics Ltd. - 8D7000-8D7FFF (base 16) Polygon Informatics Ltd. - Kalvaria sgt. 24. - Szeged H-6722 - HUNGARY - - 00-50-C2 (hex) Array Technologies Inc - 8D8000-8D8FFF (base 16) Array Technologies Inc - 160 Oak Street - Building 5, Unit 512 - Glastonbury CT 06033 - UNITED STATES - - 00-50-C2 (hex) Industrial Control and Communication Limited - 8D9000-8D9FFF (base 16) Industrial Control and Communication Limited - Unit 1 Manor Park - West End - Nailsea Bristol BS48 4DD - UNITED KINGDOM - - 00-50-C2 (hex) DOCUTEMP, INC - 8DA000-8DAFFF (base 16) DOCUTEMP, INC - 19 CROSBY DRIVE - SUITE 30 - BEDFORD MA 01730 - UNITED STATES - - 00-50-C2 (hex) DCOM Network Technology (Pty) Ltd - 8DB000-8DBFFF (base 16) DCOM Network Technology (Pty) Ltd - Unit A18, Bellville Business Park - Cnr Voortrekker en Mike Pienaar - Cape Town Western Province 7530 - SOUTH AFRICA - - 00-50-C2 (hex) Frame Systems Limited - 8DC000-8DCFFF (base 16) Frame Systems Limited - The Yard - Townview - Hungerford Berkshire RG17 0BP - UNITED KINGDOM - - 00-50-C2 (hex) GIMCON - 8DD000-8DDFFF (base 16) GIMCON - Reininghausstraße 5 - Graz Styria 8020 - AUSTRIA - - 00-50-C2 (hex) Coherix, Inc - 8DE000-8DEFFF (base 16) Coherix, Inc - 3980 Ranchero Dr - Ann Arbor MI 48108 - UNITED STATES - - 00-50-C2 (hex) Dipl.-Ing. W. Nophut GmbH - 8DF000-8DFFFF (base 16) Dipl.-Ing. W. Nophut GmbH - Steigerwaldstrasse 11 - Viereth/Trunstadt Bayern 96191 - GERMANY - - 00-50-C2 (hex) Shenzhen Pennda Technologies Co., Ltd. - 8E0000-8E0FFF (base 16) Shenzhen Pennda Technologies Co., Ltd. - Room 1801, Overseas Chinese Scholar Venture Building - Keyuan Rd. S. High-tech Industrial Park - Shenzhen Guangdong 518057 - CHINA - - 00-50-C2 (hex) Deutscher Weterdienst - 8E1000-8E1FFF (base 16) Deutscher Weterdienst - Kaiserleistrasse 44 - Offenbach 63067 - GERMANY - - 00-50-C2 (hex) Wireless Cables Inc - 8E2000-8E2FFF (base 16) Wireless Cables Inc - 1414 Soquel Ave, Ste 212 - Santa Cruz CA 95062 - UNITED STATES - - 00-50-C2 (hex) bioMérieux Italia S.p.A. - 8E3000-8E3FFF (base 16) bioMérieux Italia S.p.A. - Via di Campigliano, 58 - Ponte a Ema FI 50015 - ITALY - - 00-50-C2 (hex) MaCaPS International Limited - 8E4000-8E4FFF (base 16) MaCaPS International Limited - Rm. 1408, Block B, Hoi Luen Industrial Centre - 55 Hoi Yuen Road, Kwun Tong - HONG KONG - - 00-50-C2 (hex) Berthel GmbH - 8E5000-8E5FFF (base 16) Berthel GmbH - Karl-Zucker-Str. 12 - Erlangen GERMANY D-91052 - GERMANY - - 00-50-C2 (hex) Sandel Avionics, Inc. - 8E6000-8E6FFF (base 16) Sandel Avionics, Inc. - 2401 Dogwood Way - Vista CA 92081 - UNITED STATES - - 00-50-C2 (hex) MKT Systemtechnik - 8E7000-8E7FFF (base 16) MKT Systemtechnik - Hasskampstraße 75-77 - Bünde NRW 32257 - GERMANY - - 00-50-C2 (hex) Friedrich Kuhnt GmbH - 8E8000-8E8FFF (base 16) Friedrich Kuhnt GmbH - Stubbenweg 15 - Oldenburg Niedersachsen 26125 - GERMANY - - 00-50-C2 (hex) UNIDATA - 8E9000-8E9FFF (base 16) UNIDATA - Office 610, Antonova 5 - Kiev 03186 - UKRAINE - - 00-50-C2 (hex) ATEME - 8EA000-8EAFFF (base 16) ATEME - 26 BUROSPACE - Route de Gisy - BIEVRES Ile-de-France 91570 - FRANCE - - 00-50-C2 (hex) C-COM Satellite Systems Inc. - 8EB000-8EBFFF (base 16) C-COM Satellite Systems Inc. - 2574 Sheffield Road - Ottawa Ontario K1B3V7 - CANADA - - 00-50-C2 (hex) Balfour Beatty Rail GmbH - 8EC000-8ECFFF (base 16) Balfour Beatty Rail GmbH - Garmischer Str. 35 - Munich Germany 81373 - GERMANY - - 00-50-C2 (hex) AT-Automation Technology GmbH - 8ED000-8EDFFF (base 16) AT-Automation Technology GmbH - Hermann-Boessow-Str. 6-8 - Bad Oldesloe D-23843 - GERMANY - - 00-50-C2 (hex) PCSC - 8EE000-8EEFFF (base 16) PCSC - 3541 Challenger Street - Torrance CA 90503 - UNITED STATES - - 00-50-C2 (hex) Technologies Sensio Inc - 8EF000-8EFFFF (base 16) Technologies Sensio Inc - 1751 Richardson, Suite 4.206 - Montréal Québec H3K 1G6 - CANADA - - 00-50-C2 (hex) Xentras Communications - 8F0000-8F0FFF (base 16) Xentras Communications - 1381 S Central Dr. - Chandler AZ 85248 - UNITED STATES - - 00-50-C2 (hex) Detection Technologies Ltd. - 8F1000-8F1FFF (base 16) Detection Technologies Ltd. - Fairview Building - Heage Road Industrial Estate - Ripley Derbyshire DE5 3GH - UNITED KINGDOM - - 00-50-C2 (hex) Schneider Electric GmbH - 8F2000-8F2FFF (base 16) Schneider Electric GmbH - Gothaer Str. 29 - Ratingen 40880 - GERMANY - - 00-50-C2 (hex) Curtis Door Systems Inc - 8F3000-8F3FFF (base 16) Curtis Door Systems Inc - 104 Sharron Avenue - Plattsburgh NY 12901 - UNITED STATES - - 00-50-C2 (hex) Critical Link - 8F4000-8F4FFF (base 16) Critical Link - 6712 Brooklawn Parkway - Syracuse NY 13211 - UNITED STATES - - 00-50-C2 (hex) tec5 AG - 8F5000-8F5FFF (base 16) tec5 AG - In der Au 27 - Oberursel 61440 - GERMANY - - 00-50-C2 (hex) K-MAC Corp. - 8F6000-8F6FFF (base 16) K-MAC Corp. - 104-11, Munji-Dong - Yuseong-Gu - Daejeon 305-380 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) TGE Co., Ltd. - 8F7000-8F7FFF (base 16) TGE Co., Ltd. - 204-3, Anyang-7Dong, Manan-Gu, - Anyang-City Gyeonggi-Do 430-017 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) RMSD LTD - 8F8000-8F8FFF (base 16) RMSD LTD - 30A Uppingham Cres - Hillcrest - North Shore City Auckland 0627 - NEW ZEALAND - - 00-50-C2 (hex) Honeywell International - 8F9000-8F9FFF (base 16) Honeywell International - 13350 US Hwy 19 N - M.S. 522-4 - Clearwater Fl 33764-7290 - UNITED STATES - - 00-50-C2 (hex) TELIUM s.c. - 8FA000-8FAFFF (base 16) TELIUM s.c. - ul. Plochocinska 19 - Warszawa Mazowieckie 03-191 - POLAND - - 00-50-C2 (hex) Alfred Kuhse GmbH - 8FB000-8FBFFF (base 16) Alfred Kuhse GmbH - An der Kleinbahn 39 - Winsen (Luhe) Niedersachsen 21423 - GERMANY - - 00-50-C2 (hex) Symetrics Industries - 8FC000-8FCFFF (base 16) Symetrics Industries - 1615 West Nasa Blvd - West Melbourne Fl 32901 - UNITED STATES - - 00-50-C2 (hex) Sindoma Müh Mim Ãnþ Elk San Tic Ltd. - 8FD000-8FDFFF (base 16) Sindoma Müh Mim Ãnþ Elk San Tic Ltd. - Dereboyu cad. Þair Necati sok. - No:8/2 Ortaköy Beþiktaþ - ÃÂstanbul TR 34347 - TURKEY - - 00-50-C2 (hex) Cross Country Systems AB - 8FE000-8FEFFF (base 16) Cross Country Systems AB - Box 83 - Alfta 822 22 - SWEDEN - - 00-50-C2 (hex) Luceat - 8FF000-8FFFFF (base 16) Luceat - Via A. Canossi 18 - Torbole Casaglia BS 25030 - ITALY - - 00-50-C2 (hex) Magor Communications Corp - 900000-900FFF (base 16) Magor Communications Corp - 350 Legget Drive - Ottawa ON K2K 2W7 - CANADA - - 00-50-C2 (hex) Research Applications Incorp - 901000-901FFF (base 16) Research Applications Incorp - 650 South 79th Street - Chandler Arizona 85226 - UNITED STATES - - 00-50-C2 (hex) China Railway Signal & Communication Corp. - 902000-902FFF (base 16) China Railway Signal & Communication Corp. - B49 Xisihuan Nanlu,Fengtai District, - Beijing 100071 - CHINA - - 00-50-C2 (hex) EcoAxis Systems Pvt. Ltd. - 903000-903FFF (base 16) EcoAxis Systems Pvt. Ltd. - 3, Shreeniwas Classic, - Baner Road, - Pune Maharashtra 411045 - INDIA - - 00-50-C2 (hex) R2Sonic, LLC - 904000-904FFF (base 16) R2Sonic, LLC - 1503-A Cook Place - Santa Barbara CA 93117 - UNITED STATES - - 00-50-C2 (hex) Link Communications, Inc - 905000-905FFF (base 16) Link Communications, Inc - 1035 Cerise Road - Billings Montana 59101 - UNITED STATES - - 00-50-C2 (hex) Gidel - 906000-906FFF (base 16) Gidel - Hailan St 2 - Or Akiva Israel 30600 - ISRAEL - - 00-50-C2 (hex) Cristal Controles Ltee - 907000-907FFF (base 16) Cristal Controles Ltee - 2025 Lavoisier #135 - Quebec G1N 4L6 - CANADA - - 00-50-C2 (hex) Codex Digital Ltd - 908000-908FFF (base 16) Codex Digital Ltd - 60 Poland Street - London W1F 7NT - UNITED KINGDOM - - 00-50-C2 (hex) Elisra Electronic Systems - 909000-909FFF (base 16) Elisra Electronic Systems - 48, Mivtza Kadesh - Bene Beraq 51203 - ISRAEL - - 00-50-C2 (hex) Board Level Limited - 90A000-90AFFF (base 16) Board Level Limited - Finches - Lower Cousley Wood - Wadhurst East Sussex TN5 6HE - UNITED KINGDOM - - 00-50-C2 (hex) E.ON ES Sverige AB - 90B000-90BFFF (base 16) E.ON ES Sverige AB - Box 50529 - Malmö 20250 - SWEDEN - - 00-50-C2 (hex) LSS GmbH - 90C000-90CFFF (base 16) LSS GmbH - Am Eichenberg 1 - Altenburg Thuringia D-04610 - GERMANY - - 00-50-C2 (hex) EVK DI Kerschhaggl GmbH - 90D000-90DFFF (base 16) EVK DI Kerschhaggl GmbH - Josef Krainer Str. 35 - Graz Styria A8074 - AUSTRIA - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 90E000-90EFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) INTEGRA Biosciences AG - 90F000-90FFFF (base 16) INTEGRA Biosciences AG - Schoenbuehlstrasse 8 - Chur Graubuenden 7000 - SWITZERLAND - - 00-50-C2 (hex) Autotank AB - 910000-910FFF (base 16) Autotank AB - P.O. Box 11059 - Johannesfredsvagen 11A - BROMMA STOCKHOLM SE-16111 - SWEDEN - - 00-50-C2 (hex) Vapor Rail - 911000-911FFF (base 16) Vapor Rail - 10655 Henri-Bourassa West - Saint-Laurent Quebec H4S 1A1 - CANADA - - 00-50-C2 (hex) ASSET InterTech, Inc. - 912000-912FFF (base 16) ASSET InterTech, Inc. - 2201 N. Central Expressway - Suite 105 - Richardson TX 75080 - UNITED STATES - - 00-50-C2 (hex) Selex Ex Ltd - 913000-913FFF (base 16) Selex Ex Ltd - A Finmeccanica Company - Christopher Martin Road - Basildon Essex SS14 3EL - UNITED KINGDOM - - 00-50-C2 (hex) IO-Connect - 914000-914FFF (base 16) IO-Connect - Ahlmannsvej 41B - Sonderborg 6400 - DENMARK - - 00-50-C2 (hex) Verint Systems Ltd. - 915000-915FFF (base 16) Verint Systems Ltd. - 33 Maskit St. - Herzliya Israel 46733 - ISRAEL - - 00-50-C2 (hex) CHK GridSense P/L - 916000-916FFF (base 16) CHK GridSense P/L - Unit 3, 20 36 Nancarrow Avenue - MEADOWBANK NSW 2114 - AUSTRALIA - - 00-50-C2 (hex) CIRTEM - 917000-917FFF (base 16) CIRTEM - 4, avenue Louis Bleriot - ZA du SICOLAN - 31570 Ste FOY D'AIGREFEUILLE - FRANCE - - 00-50-C2 (hex) Design Lightning Corp - 918000-918FFF (base 16) Design Lightning Corp - 1006 W. College Ave Suite 204 - State College PA 16801 - UNITED STATES - - 00-50-C2 (hex) AHV Systems, Inc. - 919000-919FFF (base 16) AHV Systems, Inc. - 27 Ichabod Ln - Marion MA 02738 - UNITED STATES - - 00-50-C2 (hex) Xtone Networks - 91A000-91AFFF (base 16) Xtone Networks - 11190 Sunrise Valley Dr - Suite 301 - Reston VA 20191 - UNITED STATES - - 00-50-C2 (hex) Embedded Data Systems, LLC - 91B000-91BFFF (base 16) Embedded Data Systems, LLC - 1446 Gilberts Creek Rd - Lawrenceburg KY 40342 - UNITED STATES - - 00-50-C2 (hex) MangoDSP - 91C000-91CFFF (base 16) MangoDSP - Hartom 8 - Jerusalem ISRAEL 45116 - ISRAEL - - 00-50-C2 (hex) Rosendahl Studiotechnik GmbH - 91D000-91DFFF (base 16) Rosendahl Studiotechnik GmbH - Andechser Str. 5 - Utting am Ammersee Bayern 86919 - GERMANY - - 00-50-C2 (hex) Automation Tec - 91E000-91EFFF (base 16) Automation Tec - 1970 Hwy 265 - Hollister MO 65672 - UNITED STATES - - 00-50-C2 (hex) 2NCOMM DESIGN SRL - 91F000-91FFFF (base 16) 2NCOMM DESIGN SRL - Str. Amiral I. Murgescu, Nr. 1 - bl. 401, sc. A, et. 1, ap. 6 - Bucuresti sector 2 021753 - ROMANIA - - 00-50-C2 (hex) Rogue Engineering Inc. - 920000-920FFF (base 16) Rogue Engineering Inc. - 3860 S. Jason St - Englewood Colorado 80110 - UNITED STATES - - 00-50-C2 (hex) iQue RFID Technologies BV - 921000-921FFF (base 16) iQue RFID Technologies BV - Hogerwoerdstraat 30 - Haarlem NH 2023 VD - NETHERLANDS - - 00-50-C2 (hex) Metrum Sweden AB - 922000-922FFF (base 16) Metrum Sweden AB - Vestagatan 2A - Göteborg Vastra Götland 41664 - SWEDEN - - 00-50-C2 (hex) Amicus Wireless - 923000-923FFF (base 16) Amicus Wireless - 295 Santa Ana Court - Sunnyvale CA 94085 - UNITED STATES - - 00-50-C2 (hex) Link Electric & Safety Control Co. - 924000-924FFF (base 16) Link Electric & Safety Control Co. - 444 McNally Drive - Nashville TN 37211 - UNITED STATES - - 00-50-C2 (hex) PHB Eletronica Ltda. - 925000-925FFF (base 16) PHB Eletronica Ltda. - Aroaba St., 129 - São Paulo 05315-020 - BRAZIL - - 00-50-C2 (hex) DITEST FAHRZEUGDIAGNOSE GMBH - 926000-926FFF (base 16) DITEST FAHRZEUGDIAGNOSE GMBH - ALTE POSTSTRASSE 152 - A-8020 GRAZ STEIERMARK - AUSTRIA - - 00-50-C2 (hex) ATIS group s.r.o. - 927000-927FFF (base 16) ATIS group s.r.o. - Za StraÅ¡nickou vozovnou 7 - Praha 10 - Prague Czech Republic 110 00 - CZECH REPUBLIC - - 00-50-C2 (hex) Cinetix GmbH - 928000-928FFF (base 16) Cinetix GmbH - Gemuendener Str. 27 - D-60599 Frankfurt/Main - GERMANY - - 00-50-C2 (hex) Flight Deck Resources - 929000-929FFF (base 16) Flight Deck Resources - 16 Technology Drive - Suite 142 - Irvine California 92618 - UNITED STATES - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - 92A000-92AFFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu Street, district 1, - BUCHAREST 014186 - ROMANIA - - 00-50-C2 (hex) DSP DESIGN - 92B000-92BFFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) Exatrol Corporation - 92C000-92CFFF (base 16) Exatrol Corporation - 1308 West 635 South - Orem UT 84058 - UNITED STATES - - 00-50-C2 (hex) APProSoftware.com - 92D000-92DFFF (base 16) APProSoftware.com - Bulwar Ikara 29A/2 - Wroclaw Dolnoslaskie 54-130 - POLAND - - 00-50-C2 (hex) Goanna Technologies Pty Ltd - 92E000-92EFFF (base 16) Goanna Technologies Pty Ltd - 204 / 396 Scarborough Beach Rd - Osborne Park WA 6017 - AUSTRALIA - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 92F000-92FFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) NETA Elektronik AS - 930000-930FFF (base 16) NETA Elektronik AS - Yukari Dudullu Organize Sanayi Bolgesi - And Sitesi No:18 Umraniye - Istanbul 34775 - TURKEY - - 00-50-C2 (hex) Korea Telecom Internet Solutions (KTIS) - 931000-931FFF (base 16) Korea Telecom Internet Solutions (KTIS) - Room 208, Lotte Gold Rose Tower II, 890-59, - Daechi-dong, Kangnam-gu, - Seoul 135-280 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) SMAVIS Inc. - 932000-932FFF (base 16) SMAVIS Inc. - 914 JEI Platz, 459-11 Gasan-dong, - Geumcheon-gu - Seoul 153-803 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Saia-Burgess Controls AG - 933000-933FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Xilar Corp. - 934000-934FFF (base 16) Xilar Corp. - 2160 South M-15 Hwy. - Ortonville MI 48462 - UNITED STATES - - 00-50-C2 (hex) Image Video - 935000-935FFF (base 16) Image Video - 1620 Midland Ave. - Toronto Ontario M1P 3C2 - CANADA - - 00-50-C2 (hex) Margaritis Engineering - 936000-936FFF (base 16) Margaritis Engineering - 370 Verano Drive - Los Altos CA 94022 - UNITED STATES - - 00-50-C2 (hex) BigBear - 937000-937FFF (base 16) BigBear - Borgerdiget 130 - Herlev 2730 - DENMARK - - 00-50-C2 (hex) Postec Data Systems Ltd - 938000-938FFF (base 16) Postec Data Systems Ltd - P O Box 302 230 - North Harbour - North Shore Auckland 0632 - NEW ZEALAND - - 00-50-C2 (hex) Mosaic Dynamic Solutions - 939000-939FFF (base 16) Mosaic Dynamic Solutions - 1259 Route 113 Suite 203 - Perkasie PA 18917 - UNITED STATES - - 00-50-C2 (hex) ALPHATRONICS nv - 93A000-93AFFF (base 16) ALPHATRONICS nv - Brandstraat 8a - Industrial area E17/3 - Lokeren Oost Vlaanderen B-9160 - BELGIUM - - 00-50-C2 (hex) Reliatronics Inc. - 93B000-93BFFF (base 16) Reliatronics Inc. - 1858 Ranch Road 3232 - Johnson City TX 78636 - UNITED STATES - - 00-50-C2 (hex) FractureCode Corporation - 93C000-93CFFF (base 16) FractureCode Corporation - Amager Strandvej 390, 2. etage - Kastrup 2770 - DENMARK - - 00-50-C2 (hex) Lighting Science Group Corporation - 93D000-93DFFF (base 16) Lighting Science Group Corporation - 11390 Sunrise Gold Circle #800 - Rancho Cordova CA 95742 - UNITED STATES - - 00-50-C2 (hex) RCS Communication Test Systems Ltd. - 93E000-93EFFF (base 16) RCS Communication Test Systems Ltd. - 4 Nahal Yavniel Str. - POBox 103 - Modiin 71700 - ISRAEL - - 00-50-C2 (hex) TSB Solutions Inc. - 93F000-93FFFF (base 16) TSB Solutions Inc. - 5399 Eglinton Ave. West - Suite 115 - Toronto Ontario M9C 5K6 - CANADA - - 00-50-C2 (hex) Phitek Systems Ltd. - 940000-940FFF (base 16) Phitek Systems Ltd. - Level 4 - 2 Kingdon St, Newmarket, - Auckland --- 1141 - NEW ZEALAND - - 00-50-C2 (hex) Rolbit - 941000-941FFF (base 16) Rolbit - Shoham 21 - Barkan Israel 44820 - ISRAEL - - 00-50-C2 (hex) Keith & Koep GmbH - 942000-942FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) QuanZhou TDX Electronics Co., Ltd. - 943000-943FFF (base 16) QuanZhou TDX Electronics Co., Ltd. - Hi-tech Park, Quanzhou Economic and Tech Development Zone, - QuanZhou FuJian 362000 - CHINA - - 00-50-C2 (hex) Wireonair A/S - 944000-944FFF (base 16) Wireonair A/S - Skudehavnsvej 17 - Copenhagen 2100 - DENMARK - - 00-50-C2 (hex) Ex-i Flow Measurement Ltd. - 945000-945FFF (base 16) Ex-i Flow Measurement Ltd. - Hawthorn Road - Littlehampton West Sussex BN17 7LT - UNITED KINGDOM - - 00-50-C2 (hex) MEGWARE Computer GmbH - 946000-946FFF (base 16) MEGWARE Computer GmbH - Nordstrasse 19 - Chemnitz-Roehrsdorf Sachsen 09247 - GERMANY - - 00-50-C2 (hex) IMEXHIGHWAY cvba - 947000-947FFF (base 16) IMEXHIGHWAY cvba - Port Arthurlaan 15 - GHENT Oost-Vlaanderen 9000 - BELGIUM - - 00-50-C2 (hex) ELECTRONIA - 948000-948FFF (base 16) ELECTRONIA - P.O. 180 - King Abdul Aziz Road, 16th Cross - Alkhobar Eastern Province 31952 - SAUDI ARABIA - - 00-50-C2 (hex) taskit GmbH - 949000-949FFF (base 16) taskit GmbH - Seelenbinder Strasse 33 - Berlin 12555 - GERMANY - - 00-50-C2 (hex) TRUMEDIA TECHNOLOGIES - 94A000-94AFFF (base 16) TRUMEDIA TECHNOLOGIES - 24 SHABAZI ST - YEHUD 56231 - ISRAEL - - 00-50-C2 (hex) Piller engineering Ltd. - 94B000-94BFFF (base 16) Piller engineering Ltd. - Stauffenbergstraße 15 - Ostfildern Baden-Württemberg 73760 - GERMANY - - 00-50-C2 (hex) TEMIX - 94C000-94CFFF (base 16) TEMIX - Corso Michelangelo Buonarroti, 61B - Trecastagni Catania 95039 - ITALY - - 00-50-C2 (hex) C&H technology ltd. - 94D000-94DFFF (base 16) C&H technology ltd. - No.108, Fuzhong Rd - Banqiao Taipei 220 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Zynix Original Sdn. Bhd. - 94E000-94EFFF (base 16) Zynix Original Sdn. Bhd. - 43-1, Jalan 1/149J, Sri Petaling, - Kuala Lumpur Wilayah Persekutuan 57000 - MALAYSIA - - 00-50-C2 (hex) IT-Designers GmbH - 94F000-94FFFF (base 16) IT-Designers GmbH - Entennest 2 - Esslingen 73730 - GERMANY - - 00-50-C2 (hex) Tele and Radio Research Institute - 950000-950FFF (base 16) Tele and Radio Research Institute - Ratuszowa 11 - Warsaw 03-450 - POLAND - - 00-50-C2 (hex) EL.C.A. soc. coop. - 951000-951FFF (base 16) EL.C.A. soc. coop. - 61, Via delle Industrie - Fonte TV 31010 - ITALY - - 00-50-C2 (hex) Tech Fass s.r.o. - 952000-952FFF (base 16) Tech Fass s.r.o. - Plavecka 503 - Jesenice 252 42 - CZECH REPUBLIC - - 00-50-C2 (hex) Grupo Epelsa S.L. - 953000-953FFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 954000-954FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Roessmann Engineering - 955000-955FFF (base 16) Roessmann Engineering - Pachernweg 11 - Hart bei Graz Steiermark 8075 - AUSTRIA - - 00-50-C2 (hex) Sicon s.r.l. - 956000-956FFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) STRATEC Control Systems - 957000-957FFF (base 16) STRATEC Control Systems - Ankerstraße 73 - Koenigsbach Baden-Württemberg 75203 - GERMANY - - 00-50-C2 (hex) Sensoptics Ltd - 958000-958FFF (base 16) Sensoptics Ltd - 3 Gordano Court - Serbert Close - Portishead Bristol BS20 7FS - UNITED KINGDOM - - 00-50-C2 (hex) DECTRIS Ltd. - 959000-959FFF (base 16) DECTRIS Ltd. - Neuenhoferstrasse 107 - Baden 5400 - SWITZERLAND - - 00-50-C2 (hex) TechnoAP - 95A000-95AFFF (base 16) TechnoAP - Takaba 2247-4 - Hitachinaka Ibaraki 312-0062 - JAPAN - - 00-50-C2 (hex) AS Solar GmbH - 95B000-95BFFF (base 16) AS Solar GmbH - Am Toenniesberg 4A - Hanover Lower Saxony 30453 - GERMANY - - 00-50-C2 (hex) Resurgent Health & Medical - 95C000-95CFFF (base 16) Resurgent Health & Medical - 600 Corporate Circle - Suite H - Golden CO 80401 - UNITED STATES - - 00-50-C2 (hex) full electronic system - 95D000-95DFFF (base 16) full electronic system - parc des ruires - 3 rue Irène joliot curie - eybens 38320 - FRANCE - - 00-50-C2 (hex) BEEcube Inc. - 95E000-95EFFF (base 16) BEEcube Inc. - 39465 Paseo Padre Pkwy - Suite 3700 - Fremont CA 94538 - UNITED STATES - - 00-50-C2 (hex) METRONIC APARATURA KONTROLNO - POMIAROWA - 95F000-95FFFF (base 16) METRONIC APARATURA KONTROLNO - POMIAROWA - WYBICKIEGO 7 - KRAKOW MALOPOLSKA 31-261 - POLAND - - 00-50-C2 (hex) kuroneko dennnou kenkyuushitsu - 960000-960FFF (base 16) kuroneko dennnou kenkyuushitsu - 671-1 obinata minakamimachi - tonegun gunma 379-1612 - JAPAN - - 00-50-C2 (hex) Picsolve International Limited - 961000-961FFF (base 16) Picsolve International Limited - Woodlands Lodge - 107-111 Uttoxeter New Road - Derby Derbyshire DE223NL - UNITED KINGDOM - - 00-50-C2 (hex) Shockfish SA - 962000-962FFF (base 16) Shockfish SA - PSE-C - Parc Scientifique - Lausanne VD 1015 - SWITZERLAND - - 00-50-C2 (hex) Lécureux SA - 963000-963FFF (base 16) Lécureux SA - Rue des Pres 137 - Biel/Bienne BE 2503 - SWITZERLAND - - 00-50-C2 (hex) IQ Automation GmbH - 964000-964FFF (base 16) IQ Automation GmbH - Breslauer Str. 3 - Eching 85386 - GERMANY - - 00-50-C2 (hex) Emitech Corporation - 965000-965FFF (base 16) Emitech Corporation - 2F,NO.7-1,Industry E.Rd.9,Science-Based Industrial Park, - Hsinchu Taiwan 308 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) PCM Industries - 966000-966FFF (base 16) PCM Industries - 46 Shaggy Mt. Drive - Herriman Utah 84096 - UNITED STATES - - 00-50-C2 (hex) Watthour Engineering Co., Inc. - 967000-967FFF (base 16) Watthour Engineering Co., Inc. - 333 Crosspark Dr - Pearl MS 39208 - UNITED STATES - - 00-50-C2 (hex) BuLogics, Inc. - 968000-968FFF (base 16) BuLogics, Inc. - 70 E Swedesford Rd, Suite 120 - Malvern PA 19355 - UNITED STATES - - 00-50-C2 (hex) Gehrke Kommunikationssysteme GmbH - 969000-969FFF (base 16) Gehrke Kommunikationssysteme GmbH - Seligenportenerstr. 30 - Allersberg 90584 - GERMANY - - 00-50-C2 (hex) Elektrobit Wireless Communications Ltd - 96A000-96AFFF (base 16) Elektrobit Wireless Communications Ltd - Tutkijantie 8 - Oulu FIN-90570 - FINLAND - - 00-50-C2 (hex) Electronic Media Services Ltd - 96B000-96BFFF (base 16) Electronic Media Services Ltd - Passfield Business Centre - Lynchborough Road - Liphook Hampshire GU30 7SB - UNITED KINGDOM - - 00-50-C2 (hex) Aqua Cooler Pty Ltd - 96C000-96CFFF (base 16) Aqua Cooler Pty Ltd - 161 Orchard Rd - Chester Hill NSW 2162 - AUSTRALIA - - 00-50-C2 (hex) Keene Electronics Ltd. - 96D000-96DFFF (base 16) Keene Electronics Ltd. - unit 9 old hall mills business park - little eaton - derby de21 5dz - UNITED KINGDOM - - 00-50-C2 (hex) Peek Traffic Corporation - 96E000-96EFFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) Varec Inc. - 96F000-96FFFF (base 16) Varec Inc. - 5834 Peachtree Corners East - Norcross GA 30092 - UNITED STATES - - 00-50-C2 (hex) Tsuji Electronics Co.,Ltd - 970000-970FFF (base 16) Tsuji Electronics Co.,Ltd - 3739 Kandatsu-machi - Tsuchiura-city Ibafaki Pref. 3000013 - JAPAN - - 00-50-C2 (hex) Ipitek - 971000-971FFF (base 16) Ipitek - 2330 Faraday Avenue - Carlsbad CA 92008 - UNITED STATES - - 00-50-C2 (hex) Switch Science (Panini Keikaku) - 972000-972FFF (base 16) Switch Science (Panini Keikaku) - 2-12-1 Kohjimachi, #805 - Chiyoda-ku Tokyo 1020083 - JAPAN - - 00-50-C2 (hex) Systèmes Pran - 973000-973FFF (base 16) Systèmes Pran - 2245, Rue Léon Harmel - Québec G1N4J6 - CANADA - - 00-50-C2 (hex) EMAC, INC. - 974000-974FFF (base 16) EMAC, INC. - 2390 EMAC WAY - PO BOX 2042 - CARBONDALE IL 62902 - UNITED STATES - - 00-50-C2 (hex) Pyramid Technical Consultants - 975000-975FFF (base 16) Pyramid Technical Consultants - 1050 Waltham St - Suite 200 - Lexington MA 02421 - UNITED STATES - - 00-50-C2 (hex) SANDS INSTRUMENTATION INDIA PVT LTD - 976000-976FFF (base 16) SANDS INSTRUMENTATION INDIA PVT LTD - MF-7 CIPET HOSTEL ROAD, TVK INDUS ESTATE - EKKADUTHANGAL - CHENNAI TAMIL NADU 600097 - INDIA - - 00-50-C2 (hex) Saia-Burgess Controls AG - 977000-977FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) LOGITAL DIGITAL MEDIA srl - 978000-978FFF (base 16) LOGITAL DIGITAL MEDIA srl - via Palazzetti, 5/f - San Lazzaro di Savena Bologna 40068 - ITALY - - 00-50-C2 (hex) Far South Networks (Pty) Ltd - 979000-979FFF (base 16) Far South Networks (Pty) Ltd - 3 Milagro Lane - Noordhoek Western Cape 7975 - SOUTH AFRICA - - 00-50-C2 (hex) KST Technology Co., Ltd - 97A000-97AFFF (base 16) KST Technology Co., Ltd - # 506, ACE TWIN TOWER I - 212-1, KURO-DONG, KURO-KU - SEOUL 152-779 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) SMARTQUANTUM SA - 97B000-97BFFF (base 16) SMARTQUANTUM SA - 4 rue Louis de Broglie - Lannion 22300 - FRANCE - - 00-50-C2 (hex) Creacon Technologies B.V. - 97C000-97CFFF (base 16) Creacon Technologies B.V. - Cornelis Houtmanstraat 26 - Emmen 7825 VG - NETHERLANDS - - 00-50-C2 (hex) Soehnle Professional GmbH & Co.KG - 97D000-97DFFF (base 16) Soehnle Professional GmbH & Co.KG - Manfred-von-Ardenne-Allee 12 - Backnang 71522 - GERMANY - - 00-50-C2 (hex) RF Industries - 97E000-97EFFF (base 16) RF Industries - PO Box 5 - Welland SA 5007 - AUSTRALIA - - 00-50-C2 (hex) C&I Co.Ltd - 97F000-97FFFF (base 16) C&I Co.Ltd - Shinkawa 2-24-4 - ChyuouKu Tokyo 104-0033 - JAPAN - - 00-50-C2 (hex) Digital Payment Technologies - 980000-980FFF (base 16) Digital Payment Technologies - 4105 Grandview Highway - Burnaby BC V5C 6B4 - CANADA - - 00-50-C2 (hex) Novotronik GmbH - 981000-981FFF (base 16) Novotronik GmbH - Baeumenheimer Strasse 3 - Mertingen Bavaria 86690 - GERMANY - - 00-50-C2 (hex) Triple Ring Technologies, Inc. - 982000-982FFF (base 16) Triple Ring Technologies, Inc. - 39655 Eureka Ave - Newark Ca 94560 - UNITED STATES - - 00-50-C2 (hex) Bogart Engineering - 983000-983FFF (base 16) Bogart Engineering - 19020 Two Bar Road - Boulder Creek CA 95006 - UNITED STATES - - 00-50-C2 (hex) Atel Corporation - 984000-984FFF (base 16) Atel Corporation - 2-18-10, NISHISHINGAI-CHO - FUKUYAMA-SHI HIROSHIMA 721-0958 - JAPAN - - 00-50-C2 (hex) Earnestcom Sdn Bhd - 985000-985FFF (base 16) Earnestcom Sdn Bhd - 57B, JLN PU 7/4, Bandar Puchong Utama, - 47100 Selangor - MALAYSIA - - 00-50-C2 (hex) DSCI - 986000-986FFF (base 16) DSCI - 12249 Science Drive - Suite 135 - Orlando FL 32826 - UNITED STATES - - 00-50-C2 (hex) Joinsoon Electronics MFG. Co., Ltd - 987000-987FFF (base 16) Joinsoon Electronics MFG. Co., Ltd - 19F., No. 79, Sec. 1, Sintai 5th Rd., Sijhih City - Taipei County Taiwan 221 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Pantel International - 988000-988FFF (base 16) Pantel International - 125 Joseph Zatzma Drive - Dartmouth Nova Scotia B3B1W1 - CANADA - - 00-50-C2 (hex) Psigenics Corporation - 989000-989FFF (base 16) Psigenics Corporation - PO Box 2160 - Gainesville FL 32602 - UNITED STATES - - 00-50-C2 (hex) MEV Limited - 98A000-98AFFF (base 16) MEV Limited - Unit 8, Baxall Business Centre - Adswood Road - STOCKPORT Cheshire SK3 8LF - UNITED KINGDOM - - 00-50-C2 (hex) TI2000 TECNOLOGIA INFORMATICA 2000 - 98B000-98BFFF (base 16) TI2000 TECNOLOGIA INFORMATICA 2000 - CARDENAL HERRERA ORIA 165 - MADRID 28034 - SPAIN - - 00-50-C2 (hex) MGM-Devices Oy - 98C000-98CFFF (base 16) MGM-Devices Oy - Länsikatuu 15 - Joensuu Pohjois-Karjala 80110 - FINLAND - - 00-50-C2 (hex) Mecos AG - 98D000-98DFFF (base 16) Mecos AG - Industriestrasse 26 - Winterthur 8404 - SWITZERLAND - - 00-50-C2 (hex) Link Technologies, Inc - 98E000-98EFFF (base 16) Link Technologies, Inc - 6560 Satke Drive - House Springs MO 63051 - UNITED STATES - - 00-50-C2 (hex) BELIK S.P.R.L. - 98F000-98FFFF (base 16) BELIK S.P.R.L. - Rue du Roussart 147 - Waterloo Brabant 1410 - BELGIUM - - 00-50-C2 (hex) Keith & Koep GmbH - 990000-990FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) UGL Limited - 991000-991FFF (base 16) UGL Limited - 3 Bridge Street - Level 3 - Pymble NSW 2073 - AUSTRALIA - - 00-50-C2 (hex) IDT Sound Processing Corporation - 992000-992FFF (base 16) IDT Sound Processing Corporation - 917 chemin Pierre Drevet - CALUIRE Rhone 69300 - FRANCE - - 00-50-C2 (hex) UNETCONVERGENCE CO., LTD - 993000-993FFF (base 16) UNETCONVERGENCE CO., LTD - 101-511 DIGITAL EMPIRE 2 - 486, SHIN-DONG, YOUNG TONG-GU - SUWON-SI KYUNGGI-DO, 443-390 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Xafax Nederland bv - 994000-994FFF (base 16) Xafax Nederland bv - Postbus 107 - Alkmaar NH 1800AC - NETHERLANDS - - 00-50-C2 (hex) Inter Control Hermann Köhler Elektrik GmbH&Co.KG - 995000-995FFF (base 16) Inter Control Hermann Köhler Elektrik GmbH&Co.KG - Schafhofstraße 30 - Nürnberg Bavaria 90411 - GERMANY - - 00-50-C2 (hex) Commercial Timesharing Inc. - 996000-996FFF (base 16) Commercial Timesharing Inc. - 2740 Cory Ave. - Akron OH 44314 - UNITED STATES - - 00-50-C2 (hex) Depro Électronique - 997000-997FFF (base 16) Depro Électronique - 755 Curé-Boivin - Boisbriand Québec J7G2J2 - CANADA - - 00-50-C2 (hex) Phytec Messtechnik GmbH - 998000-998FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Cambustion Ltd - 999000-999FFF (base 16) Cambustion Ltd - J6, The Paddocks - 347 Cherry Hinton Road - Cambridge Cambridgeshire CB1 8DH - UNITED KINGDOM - - 00-50-C2 (hex) Miromico AG - 99A000-99AFFF (base 16) Miromico AG - Sonneggstrasse 76 - Zuerich ZH 8006 - SWITZERLAND - - 00-50-C2 (hex) Bettini srl - 99B000-99BFFF (base 16) Bettini srl - Via Cesare Battisti 22 - Cesano Maderno Milano I - 20031 - ITALY - - 00-50-C2 (hex) CaTs3 Limited - 99C000-99CFFF (base 16) CaTs3 Limited - 21 Lindisfarne Drive - Kenilworth Warwickshire CV8 2PQ - UNITED KINGDOM - - 00-50-C2 (hex) Powersense A/S - 99D000-99DFFF (base 16) Powersense A/S - Skovlytoften 33 - Holte Rudersdal 2840 - DENMARK - - 00-50-C2 (hex) Engage Technologies - 99E000-99EFFF (base 16) Engage Technologies - 7041 Boone Avenue North - Brooklyn Park MN 55428 - UNITED STATES - - 00-50-C2 (hex) Sietron Elektronik - 99F000-99FFFF (base 16) Sietron Elektronik - Mittere Feldstrasse 5 - Freilassing 83395 - GERMANY - - 00-50-C2 (hex) Trs Systems, Inc. - 9A0000-9A0FFF (base 16) Trs Systems, Inc. - 601 Carlson Parkway, #1050 - Minnetonka MN 55305 - UNITED STATES - - 00-50-C2 (hex) ComAp s.r.o - 9A1000-9A1FFF (base 16) ComAp s.r.o - Kundratka 17 - Prague 18000 - CZECH REPUBLIC - - 00-50-C2 (hex) SAMsystems GmbH - 9A2000-9A2FFF (base 16) SAMsystems GmbH - Bannwaldallee 46 - Karlsruhe 76139 - GERMANY - - 00-50-C2 (hex) Computerwise, Inc. - 9A3000-9A3FFF (base 16) Computerwise, Inc. - 302 N. Winchester - Olathe Ks 66062 - UNITED STATES - - 00-50-C2 (hex) Entwicklung Hard- & Software - 9A4000-9A4FFF (base 16) Entwicklung Hard- & Software - Berlinerstr. 9 - Schoenaich BW 71101 - GERMANY - - 00-50-C2 (hex) Conolog Corporation - 9A5000-9A5FFF (base 16) Conolog Corporation - 5 Columbia Road - Somerville NJ 08876 - UNITED STATES - - 00-50-C2 (hex) Metodo2 - 9A6000-9A6FFF (base 16) Metodo2 - Via IV Novembre 11 - Cologno Monzese MI 20093 - ITALY - - 00-50-C2 (hex) Thales Communications & Security S.A. - 9A7000-9A7FFF (base 16) Thales Communications & Security S.A. - 20-22 Rue Grange Dame Rose - CS 90519 - Vélizy 78141 - FRANCE - - 00-50-C2 (hex) DOMIS SA - 9A8000-9A8FFF (base 16) DOMIS SA - 10 AV jean Moulin - RUMILLY 74150 - FRANCE - - 00-50-C2 (hex) General Dynamics C4 Systems - 9A9000-9A9FFF (base 16) General Dynamics C4 Systems - 8220 East Roosevelt St. - MD: R1122 - Scottsdale Arizona 85257 - UNITED STATES - - 00-50-C2 (hex) TEKO TELECOM SpA - 9AA000-9AAFFF (base 16) TEKO TELECOM SpA - Via dell' Industria, 5 - San Lazzaro di Savena Bologna 40068 - ITALY - - 00-50-C2 (hex) Electrodata Inc. - 9AB000-9ABFFF (base 16) Electrodata Inc. - P.O. Box 31780 - Independence OHIO 44131 - UNITED STATES - - 00-50-C2 (hex) Questek Australia Pty Ltd - 9AC000-9ACFFF (base 16) Questek Australia Pty Ltd - 22 Brodie St - Rydalmere NSW 2116 - AUSTRALIA - - 00-50-C2 (hex) Chronos Technology Ltd. - 9AD000-9ADFFF (base 16) Chronos Technology Ltd. - Stowfield House - Upper Stowfield - Lydbrook Gloucestershire GL17 9PD - UNITED KINGDOM - - 00-50-C2 (hex) Esensors, Inc. - 9AE000-9AEFFF (base 16) Esensors, Inc. - 4240 Ridge Lea Road - Ste. 37 - Amherst NY 14226 - UNITED STATES - - 00-50-C2 (hex) KRESS-NET Krzysztof Rutecki - 9AF000-9AFFFF (base 16) KRESS-NET Krzysztof Rutecki - Stawowa 8a - Gaszowice 44-293 - POLAND - - 00-50-C2 (hex) Ebru GmbH - 9B0000-9B0FFF (base 16) Ebru GmbH - In den Kreuzwiesen - Schönau 69250 - GERMANY - - 00-50-C2 (hex) Bon Hora GmbH - 9B1000-9B1FFF (base 16) Bon Hora GmbH - Steinbuehlstrasse 15b - Wetzlar Hessen 35578 - GERMANY - - 00-50-C2 (hex) TempSys - 9B2000-9B2FFF (base 16) TempSys - 160 Arlingtoin Ave - Kensington CA 94707 - UNITED STATES - - 00-50-C2 (hex) Kahler Automation - 9B3000-9B3FFF (base 16) Kahler Automation - 808 Timberlake Rd - Fairmont MN 56031 - UNITED STATES - - 00-50-C2 (hex) EUKREA ELECTROMATIQUE SARL - 9B4000-9B4FFF (base 16) EUKREA ELECTROMATIQUE SARL - 74 AVENUE JEAN JAURES - PESSAC GIRONDE 33600 - FRANCE - - 00-50-C2 (hex) Telegamma srl - 9B5000-9B5FFF (base 16) Telegamma srl - Via Noalese, 63/B - Treviso TV 31100 - ITALY - - 00-50-C2 (hex) ACTECH - 9B6000-9B6FFF (base 16) ACTECH - Parc d'activités Angers-Beaucouzé - 4, rue Olivier de Serres - Beaucouzé 49070 - FRANCE - - 00-50-C2 (hex) St. Michael Strategies - 9B7000-9B7FFF (base 16) St. Michael Strategies - 701 Salaberry - Suite 201 - Chambly Quebec J3L 1R2 - CANADA - - 00-50-C2 (hex) Sound Player Systems e.K. - 9B8000-9B8FFF (base 16) Sound Player Systems e.K. - Max-Volmer-Strasse 27 - Hilden NRW 40721 - GERMANY - - 00-50-C2 (hex) ISA - Intelligent Sensing Anywhere, S.A. - 9B9000-9B9FFF (base 16) ISA - Intelligent Sensing Anywhere, S.A. - Estádio Cidade de Coimbra - Rua D. Manuel I, n.º92 - Coimbra 3030-320 - PORTUGAL - - 00-50-C2 (hex) Connor-Winfield - 9BA000-9BAFFF (base 16) Connor-Winfield - 2111 Comprehensive Dr - Aurora Illinois 60505 - UNITED STATES - - 00-50-C2 (hex) OMICRON electronics GmbH - 9BB000-9BBFFF (base 16) OMICRON electronics GmbH - Oberes Ried 1 - Klaus 6833 - AUSTRIA - - 00-50-C2 (hex) Vester Elektronik GmbH - 9BC000-9BCFFF (base 16) Vester Elektronik GmbH - Otto-Hahn-Straße 14 - Straubenhardt Baden-Württemberg 75334 - GERMANY - - 00-50-C2 (hex) Sensitron Semiconductor - 9BD000-9BDFFF (base 16) Sensitron Semiconductor - 221 West Industry Court - Deer Park New York 11729 - UNITED STATES - - 00-50-C2 (hex) Xad Communications Ltd - 9BE000-9BEFFF (base 16) Xad Communications Ltd - Weir House - 93 Whitby Road - Bristol UK BS4 4AR - UNITED KINGDOM - - 00-50-C2 (hex) 2N TELEKOMUNIKACE a.s. - 9BF000-9BFFFF (base 16) 2N TELEKOMUNIKACE a.s. - Modranska 621 - Prague Czech Republic 143 01 - CZECH REPUBLIC - - 00-50-C2 (hex) Stuyts Engineering Haarlem BV - 9C0000-9C0FFF (base 16) Stuyts Engineering Haarlem BV - Hogeweg 40 - Zandvoort Noord-Holland 2042GH - NETHERLANDS - - 00-50-C2 (hex) Tattile srl - 9C1000-9C1FFF (base 16) Tattile srl - via Donizetti 1/3/5 - Mairano BS 25030 - ITALY - - 00-50-C2 (hex) Team Enginers - 9C2000-9C2FFF (base 16) Team Enginers - 3-18-3, First floor Pragati Nagar - Ramanthapur,Hyderabad - Hyderabad Andrapradesh 500013 - INDIA - - 00-50-C2 (hex) GE Security-Kampro - 9C3000-9C3FFF (base 16) GE Security-Kampro - 2F, No.8, Lane97, Wugong Rd., - Wu-Ku Ind.Park, - Hsin-Chuang City Taipei County 248 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Vitel Net - 9C4000-9C4FFF (base 16) Vitel Net - 8201 Greensboro Dr. - Ste 600 - McLean VA 22102 - UNITED STATES - - 00-50-C2 (hex) Scansonic MI GmbH - 9C5000-9C5FFF (base 16) Scansonic MI GmbH - Rudolf-Baschant-Straße 2 - Berlin 13086 - GERMANY - - 00-50-C2 (hex) Protronic GmbH - 9C6000-9C6FFF (base 16) Protronic GmbH - Am Schwarzwasser 2b - Bennewitz Sachsen 04828 - GERMANY - - 00-50-C2 (hex) Kumera Drives Oy - 9C7000-9C7FFF (base 16) Kumera Drives Oy - Kumerankatu 2 - Riihimäki Häme 11100 - FINLAND - - 00-50-C2 (hex) ethermetrics - 9C8000-9C8FFF (base 16) ethermetrics - 1223 peoples ave - Troy New York 12180 - UNITED STATES - - 00-50-C2 (hex) LUMINEX Lighting Control Equipment - 9C9000-9C9FFF (base 16) LUMINEX Lighting Control Equipment - Berkenlaan 8 A - Hechtel - Eksel Limburg 3940 - BELGIUM - - 00-50-C2 (hex) ESAB-ATAS GmbH - 9CA000-9CAFFF (base 16) ESAB-ATAS GmbH - Liebigstraße 16 - Seligenstadt Hessen 63500 - GERMANY - - 00-50-C2 (hex) NIS-time GmbH - 9CB000-9CBFFF (base 16) NIS-time GmbH - Valterweg 10 - Bremthal 65817 - GERMANY - - 00-50-C2 (hex) Hirotech, Inc - 9CC000-9CCFFF (base 16) Hirotech, Inc - Shinyokohama I.O Bldg. #602, 1-3-10, Shinyokohama, Kohoku-ku - Yokohama City Kanagawa 222-0033 - JAPAN - - 00-50-C2 (hex) Uwe Schneider GmbH - 9CD000-9CDFFF (base 16) Uwe Schneider GmbH - Heegwaldring 12 - Limeshain 63694 - GERMANY - - 00-50-C2 (hex) Ronan Engineering - 9CE000-9CEFFF (base 16) Ronan Engineering - 21200 Oxnard St. - Woodland Hills CA 91367 - UNITED STATES - - 00-50-C2 (hex) Intuitive Surgical, Inc - 9CF000-9CFFFF (base 16) Intuitive Surgical, Inc - 950 Kifer Road - Sunnyvale CA 94040 - UNITED STATES - - 00-50-C2 (hex) J. DITTRICH ELEKTRONIC GmbH & Co. KG - 9D0000-9D0FFF (base 16) J. DITTRICH ELEKTRONIC GmbH & Co. KG - Bahnhofstraße 67 - Baden-Baden / Haueneberstein Baden-Württemberg 76532 - GERMANY - - 00-50-C2 (hex) Bladelius Design Group AB - 9D1000-9D1FFF (base 16) Bladelius Design Group AB - Kallakersvagen 10 - Alingsas 44196 - SWEDEN - - 00-50-C2 (hex) Saia-Burgess Controls AG - 9D2000-9D2FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Telemetrie Elektronik GmbH - 9D3000-9D3FFF (base 16) Telemetrie Elektronik GmbH - Berliner Allee 42 - Langenhagen Niedersachsen 30855 - GERMANY - - 00-50-C2 (hex) FIRST - 9D4000-9D4FFF (base 16) FIRST - 200 Bedford Street - Manchester New Hampshire 03101 - UNITED STATES - - 00-50-C2 (hex) Netpower Labs AB - 9D5000-9D5FFF (base 16) Netpower Labs AB - Stubbsundsv 17 - Stockholm 13141 - SWEDEN - - 00-50-C2 (hex) Innovation, Institute, Inc - 9D6000-9D6FFF (base 16) Innovation, Institute, Inc - P.O. Box 9359 - Caguas Puerto Rico 00726-9359 - PUERTO RICO - - 00-50-C2 (hex) Melex Inc. - 9D7000-9D7FFF (base 16) Melex Inc. - 1417-27 Toke-cho Midori-ku - CHIBA 2670061 - JAPAN - - 00-50-C2 (hex) SAMSUNG HEAVY INDUSTRIES CO.,LTD. - 9D8000-9D8FFF (base 16) SAMSUNG HEAVY INDUSTRIES CO.,LTD. - Institute of industrial Technology - 103-28, Munji-dong, Yuseong-gu - Daejeon 305-380 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) CNS Systems, Inc. - 9D9000-9D9FFF (base 16) CNS Systems, Inc. - 363 Hawick Court - Severna Park Maryland 21146 - UNITED STATES - - 00-50-C2 (hex) NEUTRONIK e.K. - 9DA000-9DAFFF (base 16) NEUTRONIK e.K. - Taitinger Str. 14 - Dasing Bayern 86453 - GERMANY - - 00-50-C2 (hex) Walter Grotkasten - 9DB000-9DBFFF (base 16) Walter Grotkasten - Grabäckerstraße 14 - Schorndorf BW 73614 - GERMANY - - 00-50-C2 (hex) FTM Marketing Limited - 9DC000-9DCFFF (base 16) FTM Marketing Limited - Unit 26 Enterprise Estate - Moorfield Road - Guildford Surrey GU1 1RB - UNITED KINGDOM - - 00-50-C2 (hex) Institut Dr. Foerster - 9DD000-9DDFFF (base 16) Institut Dr. Foerster - In Laisen 70 - Reutlingen 72766 - GERMANY - - 00-50-C2 (hex) CHAUVIN ARNOUX - 9DE000-9DEFFF (base 16) CHAUVIN ARNOUX - LA QUEUE DEVEE - REUX 14130 - FRANCE - - 00-50-C2 (hex) CODEC Co., Ltd. - 9DF000-9DFFFF (base 16) CODEC Co., Ltd. - 1021-1 Kuriki Asao-ward - Kawasaki Kanagawa 215-0033 - JAPAN - - 00-50-C2 (hex) DST Swiss AG - 9E0000-9E0FFF (base 16) DST Swiss AG - Schuebelbachstrasse 3 - Eglisau ZH 8193 - SWITZERLAND - - 00-50-C2 (hex) Enreduce Energy Control AB - 9E1000-9E1FFF (base 16) Enreduce Energy Control AB - Box 459 - 751 06 - UPPSALA 751 06 - SWEDEN - - 00-50-C2 (hex) E-ViEWS SAFETY SYSTEMS, INC - 9E2000-9E2FFF (base 16) E-ViEWS SAFETY SYSTEMS, INC - 5331 DERRY AVE - SUITE J - AGOURA HILLS CA 91301 - UNITED STATES - - 00-50-C2 (hex) SAI Informationstechnik - 9E3000-9E3FFF (base 16) SAI Informationstechnik - Hackhofergasse 1 - Vienna 1190 - AUSTRIA - - 00-50-C2 (hex) Pyxis Controls WLL - 9E4000-9E4FFF (base 16) Pyxis Controls WLL - Kingdom Tower - Manama Bahrain 0000 - BAHRAIN - - 00-50-C2 (hex) Halliburton Far East Pte Ltd - 9E5000-9E5FFF (base 16) Halliburton Far East Pte Ltd - 315 Jalan Ahmad Ibrahim - 639940 - SINGAPORE - - 00-50-C2 (hex) Kumho Electric, Inc. - 9E6000-9E6FFF (base 16) Kumho Electric, Inc. - 211-1, Jangji-Ri, Dongtan-myun, - Hwasung City Kyonggi-Do 445-812 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) DORLET S.A. - 9E7000-9E7FFF (base 16) DORLET S.A. - Albert Einstein 34 - MIÑANO Mayor - Vitoria-gasteiz Ãlava 01510 - SPAIN - - 00-50-C2 (hex) Hammock Corporation - 9E8000-9E8FFF (base 16) Hammock Corporation - 7-8-F 30SANKYO-Building - 1-30-4 TAKADANOBABA - SHINJUKU-WARD TOKYO 169-0075 - JAPAN - - 00-50-C2 (hex) Ciemme Sistemi Spa - 9E9000-9E9FFF (base 16) Ciemme Sistemi Spa - Viale Ariosto, 492/A - Sesto Fiorentino (FIRENZE) 50019 - ITALY - - 00-50-C2 (hex) SISMODULAR - Engenharia, Lda - 9EA000-9EAFFF (base 16) SISMODULAR - Engenharia, Lda - Lrg. S. Paulo Nº13, 1º - E2 - Braga 4700-042 - PORTUGAL - - 00-50-C2 (hex) AFORE Solutions Inc. - 9EB000-9EBFFF (base 16) AFORE Solutions Inc. - 2680 Queensview Drive - Suite 150 - Ottawa Ontario K2B 8J9 - CANADA - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - 9EC000-9ECFFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu Street, district 1, - BUCHAREST 014186 - ROMANIA - - 00-50-C2 (hex) Picell B.V. - 9ED000-9EDFFF (base 16) Picell B.V. - Liede 35 - Rotterdam 3068GP - NETHERLANDS - - 00-50-C2 (hex) Michael Stevens & Partners Ltd - 9EE000-9EEFFF (base 16) Michael Stevens & Partners Ltd - Invicta Works - Elliott Road - Bromley Kent BR2 9NT - UNITED KINGDOM - - 00-50-C2 (hex) WoKa-Elektronik GmbH - 9EF000-9EFFFF (base 16) WoKa-Elektronik GmbH - Zeller-Str.7 - Romrod Hessen 36329 - GERMANY - - 00-50-C2 (hex) Veracity UK Ltd - 9F0000-9F0FFF (base 16) Veracity UK Ltd - 6 Barns Street - Ayr South Ayrshire KA7 1XA - UNITED KINGDOM - - 00-50-C2 (hex) IDEAS s.r.l. - 9F1000-9F1FFF (base 16) IDEAS s.r.l. - Via XXV Aprile 9/A - Cassina de pecchi Milan 20060 - ITALY - - 00-50-C2 (hex) Keith & Koep GmbH - 9F2000-9F2FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Vision Technologies, Inc. - 9F3000-9F3FFF (base 16) Vision Technologies, Inc. - 609 W Dyke Rd - Rogers AR 72756 - UNITED STATES - - 00-50-C2 (hex) FSR Inc. - 9F4000-9F4FFF (base 16) FSR Inc. - 244 Bergen Blvd - West Paterson NJ 07424 - UNITED STATES - - 00-50-C2 (hex) Commex Technologies - 9F5000-9F5FFF (base 16) Commex Technologies - 4 Hanechoshet St. - Tel Aviv 69719 - ISRAEL - - 00-50-C2 (hex) Ion Sense Inc. - 9F6000-9F6FFF (base 16) Ion Sense Inc. - 999 Broadway - Suite 404 - Saugus MA 01906 - UNITED STATES - - 00-50-C2 (hex) Dave Jones Design - 9F7000-9F7FFF (base 16) Dave Jones Design - 34 Lake St. - Owego NY 13827 - UNITED STATES - - 00-50-C2 (hex) Austco Communication Systems Pty Ltd - 9F8000-9F8FFF (base 16) Austco Communication Systems Pty Ltd - 40 O'Malley Street - Osborne Park Western Australia 6017 - AUSTRALIA - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - 9F9000-9F9FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park, Torch Hi-Tech Development Zone.Xiamen.China - Xiao Dong Shan, Xiamen - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) Teranex A Division of Silicon Optix - 9FA000-9FAFFF (base 16) Teranex A Division of Silicon Optix - 12600 Challenger Parkway - Suite 100 - Orlando FL 32826-2700 - UNITED STATES - - 00-50-C2 (hex) Villbau Kft. - 9FB000-9FBFFF (base 16) Villbau Kft. - ÜllÅ‘i út 611. - BUdapest H-1182 - HUNGARY - - 00-50-C2 (hex) ECTEC INC. - 9FC000-9FCFFF (base 16) ECTEC INC. - 632 Rancho Vista Blvd - Suite A - Palmdale California 93550 - UNITED STATES - - 00-50-C2 (hex) Bitt technology-A Ltd. - 9FD000-9FDFFF (base 16) Bitt technology-A Ltd. - Wiener Strasse 70 - Spillern Lower Austria 2104 - AUSTRIA - - 00-50-C2 (hex) SPECTRA EMBEDDED SYSTEMS - 9FE000-9FEFFF (base 16) SPECTRA EMBEDDED SYSTEMS - Khasra No. 24, Village Ghumman,1st Floor, Chawla Mansion, - B/h. Sant Vihar, Uncha Parwanoo,Sector-1, - Parwanoo Himachal Pradesh 173 220 - INDIA - - 00-50-C2 (hex) Humphrey Products - 9FF000-9FFFFF (base 16) Humphrey Products - 5070 East 'N' Ave - Kalamazoo MI 49048 - UNITED STATES - - 00-50-C2 (hex) Technovare Systems - A00000-A00FFF (base 16) Technovare Systems - 1675 Scenic Ave. Suite 200 - Costa Mesa CA 92626 - UNITED STATES - - 00-50-C2 (hex) Patronics International LTD - A01000-A01FFF (base 16) Patronics International LTD - Eurotech House - Burrington Way - Plymouth Devon PL5 3LZ - UNITED KINGDOM - - 00-50-C2 (hex) Reference, LLC. - A02000-A02FFF (base 16) Reference, LLC. - 690 E Bridge St. - P.O. Box 158 - Elkader IA 52043-0158 - UNITED STATES - - 00-50-C2 (hex) EEG Enterprises Inc - A03000-A03FFF (base 16) EEG Enterprises Inc - 586 Main Street - Farmingdale NY 11735 - UNITED STATES - - 00-50-C2 (hex) TP Radio - A04000-A04FFF (base 16) TP Radio - Agenavej 37 - Greve . 2670 - DENMARK - - 00-50-C2 (hex) Adgil Design Inc. - A05000-A05FFF (base 16) Adgil Design Inc. - 12915 Brault - Mirabel Quebec J7J 1P3 - CANADA - - 00-50-C2 (hex) Cloos Schweisstechnik GmbH - A06000-A06FFF (base 16) Cloos Schweisstechnik GmbH - Industriestraße 34-36 - Haiger Hessen 35708 - GERMANY - - 00-50-C2 (hex) Dynon Instruments - A07000-A07FFF (base 16) Dynon Instruments - 19825 141st PL NE - Woodinville WA 98072 - UNITED STATES - - 00-50-C2 (hex) LabJack Corporation - A08000-A08FFF (base 16) LabJack Corporation - 3232 S Vance St STE 100 - Lakewood CO 80227 - UNITED STATES - - 00-50-C2 (hex) Innovative American Technology - A09000-A09FFF (base 16) Innovative American Technology - 4800 Lyons Technology Pkwy, Ste 3 - Coconut Creek FL 33073 - UNITED STATES - - 00-50-C2 (hex) ACD Elektronik GmbH - A0A000-A0AFFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) I.D.S. Ingegneria Dei Sistemi S.p.A. - A0B000-A0BFFF (base 16) I.D.S. Ingegneria Dei Sistemi S.p.A. - via Enrica Calabresi, 24 - PISA PI 56121 - ITALY - - 00-50-C2 (hex) Phytec Messtechnik GmbH - A0C000-A0CFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) CHARLYROBOT - A0D000-A0DFFF (base 16) CHARLYROBOT - 192, route de l'usine - BP 22 - CRUSEILLES HAUTE-SAVOIE 74350 - FRANCE - - 00-50-C2 (hex) Engicam srl - A0E000-A0EFFF (base 16) Engicam srl - Via dei pratoni, 16 int. 13 - Scandicci Firenze 50018 - ITALY - - 00-50-C2 (hex) Visualware Inc - A0F000-A0FFFF (base 16) Visualware Inc - PO Box 668 - 937 Sierra Drive - Turlock California 95381 - UNITED STATES - - 00-50-C2 (hex) Essential Design & Integration P/L - A10000-A10FFF (base 16) Essential Design & Integration P/L - PO Box 3110 - Narellan DC NSW 2567 - AUSTRALIA - - 00-50-C2 (hex) OJSC Rawenstvo - A11000-A11FFF (base 16) OJSC Rawenstvo - 19, Promyshlennaya str, - Saint-Petersburg 198099 - RUSSIAN FEDERATION - - 00-50-C2 (hex) HCE Engineering S.r.l. - A12000-A12FFF (base 16) HCE Engineering S.r.l. - Via Lamarmora 2L - Livorno LI 57122 - ITALY - - 00-50-C2 (hex) Talyst, Inc. - A13000-A13FFF (base 16) Talyst, Inc. - 13555 SE 36th Avenue - Suite 150 - Bellevue WA 98006 - UNITED STATES - - 00-50-C2 (hex) Elbit Systems of America - Tallahassee Operations - A14000-A14FFF (base 16) Elbit Systems of America - Tallahassee Operations - 1721 W. Paul Dirac Drive - Tallahassee Florida 32310 - UNITED STATES - - 00-50-C2 (hex) Industrial Computing Ltd - A15000-A15FFF (base 16) Industrial Computing Ltd - Elmcroft - Wyke Road - Gillingham Dorset SP8 4NG - UNITED KINGDOM - - 00-50-C2 (hex) Baudisch Electronic GmbH - A16000-A16FFF (base 16) Baudisch Electronic GmbH - Im Gewerbegebiet 7-9 - Wäschenbeuren Baden-Württemberg 73116 - GERMANY - - 00-50-C2 (hex) Winners Satellite Electronics Corp. - A17000-A17FFF (base 16) Winners Satellite Electronics Corp. - 3F, NO. 4, LANE 263, CHUNG YANG RD., TAIPEI 115, TAIWAN - TAIPEI 115 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Eoslink - A18000-A18FFF (base 16) Eoslink - #602, 900-1 - Gwanyang-Dong, Dongan-Gu - Anyang-City Kyonggi-Do 431-060 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Icon Time Systems - A19000-A19FFF (base 16) Icon Time Systems - 15201 NW Greenbrier Parkway #A1 - Beaverton OR 97006 - UNITED STATES - - 00-50-C2 (hex) DDL - A1A000-A1AFFF (base 16) DDL - 6F AFT BLDG. - 1, KITA 5-JYO HIGASHI 2-CHOUME - SAPPORO HOKKAIDO 060-0035 - JAPAN - - 00-50-C2 (hex) Realtime Systems Ltd. - A1B000-A1BFFF (base 16) Realtime Systems Ltd. - A-49, Okhla Industrial Area - Okhla Phase-1 - New Delhi 110020 - INDIA - - 00-50-C2 (hex) Microtechnica - A1C000-A1CFFF (base 16) Microtechnica - 1-3-10-501 Tamagawa - Setagayaku Tokyo 1580094 - JAPAN - - 00-50-C2 (hex) SAMH Engineering Services - A1D000-A1DFFF (base 16) SAMH Engineering Services - 1 Leopardstown Drive - Blackrock - Dublin Co. - IRELAND - - 00-50-C2 (hex) MAMAC Systems, Inc. - A1E000-A1EFFF (base 16) MAMAC Systems, Inc. - 8189 Century Blvd. - Chanhassen Minnesota 55317-8002 - UNITED STATES - - 00-50-C2 (hex) Flight Data Systems Pty Ltd - A1F000-A1FFFF (base 16) Flight Data Systems Pty Ltd - 31 Mc Gregors Drive - Keilor Park Victoria 3042 - AUSTRALIA - - 00-50-C2 (hex) Quorum Technologies Ltd - A20000-A20FFF (base 16) Quorum Technologies Ltd - South Stour Avenue - Ashford Kent TN23 7RS - UNITED KINGDOM - - 00-50-C2 (hex) ISAC SRL - A21000-A21FFF (base 16) ISAC SRL - via Maestri del Lavoro 30 - CASCINA PISA 56021 - ITALY - - 00-50-C2 (hex) Nippon Manufacturing Service Corporation (abbreviated as 'nms') - A22000-A22FFF (base 16) Nippon Manufacturing Service Corporation (abbreviated as 'nms') - Tokyo Opera City Tower 11F - 3-20-2 Nishi-shinjuku - Shinjuku-ku Tokyo 163-1411 - JAPAN - - 00-50-C2 (hex) Agility Mfg, Inc. - A23000-A23FFF (base 16) Agility Mfg, Inc. - 279 Locust Street - Dover NH 03820 - UNITED STATES - - 00-50-C2 (hex) Grupo Epelsa S.L. - A24000-A24FFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) Saia-Burgess Controls AG - A25000-A25FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Preferred Oil, LLC - A26000-A26FFF (base 16) Preferred Oil, LLC - 1819 Moen Ave - Joliet IL 60436 - UNITED STATES - - 00-50-C2 (hex) meconet e. K. - A27000-A27FFF (base 16) meconet e. K. - Bottenbacher Str. 78 - Kreuztal NRW 57223 - GERMANY - - 00-50-C2 (hex) KENDA ELECTRONIC SYSTEMS LIMITED - A28000-A28FFF (base 16) KENDA ELECTRONIC SYSTEMS LIMITED - NUTSEY LANE - TOTTON - SOUTHAMPTON HAMPSHIRE SO40 3NB - UNITED KINGDOM - - 00-50-C2 (hex) Luminex Corporation - A29000-A29FFF (base 16) Luminex Corporation - 12212 Technology Blvd. - Austin Texas 78727 - UNITED STATES - - 00-50-C2 (hex) Custom Control Concepts - A2A000-A2AFFF (base 16) Custom Control Concepts - 6020 S 190th St - Kent WA 98032 - UNITED STATES - - 00-50-C2 (hex) APRILIA RACING S.R.L. - A2B000-A2BFFF (base 16) APRILIA RACING S.R.L. - VIA MARCONI, 9 - REPARTO CORSE APRILIA - NOALE VENEZIA 30033 - ITALY - - 00-50-C2 (hex) KWS-Electronic GmbH - A2C000-A2CFFF (base 16) KWS-Electronic GmbH - Sportplatzstrasse 1 - Grosskarolinenfeld D-83109 - GERMANY - - 00-50-C2 (hex) Inventure Inc. - A2D000-A2DFFF (base 16) Inventure Inc. - 3-1-1, Shin-yokohama, Kouhoku-ku - Yokohama Kanagawa-ken 222-8505 - JAPAN - - 00-50-C2 (hex) Yuyama Mfg. Co., Ltd. - A2E000-A2EFFF (base 16) Yuyama Mfg. Co., Ltd. - 3-3-1 Meishinguchi - Toyonaka Osaka 561-0841 - JAPAN - - 00-50-C2 (hex) DragonFly Scientific LLC - A2F000-A2FFFF (base 16) DragonFly Scientific LLC - RR2 Box 467A - Harveys Lake PA 18618 - UNITED STATES - - 00-50-C2 (hex) D-TA Systems - A30000-A30FFF (base 16) D-TA Systems - 2500 Lancaster Road - Ottawa ON K1B 4S5 - CANADA - - 00-50-C2 (hex) Coolit Systems, Inc. - A31000-A31FFF (base 16) Coolit Systems, Inc. - 3920 - 29th St. N.E. - Calgary AB T1Y6B6 - CANADA - - 00-50-C2 (hex) Harris Designs of NRV, Inc. - A32000-A32FFF (base 16) Harris Designs of NRV, Inc. - 4034 Pepperell Way - Dublin VA 24084 - UNITED STATES - - 00-50-C2 (hex) Fuji Firmware - A33000-A33FFF (base 16) Fuji Firmware - 535-211 Nakayamacyou-Nishi - 4-Cyoume - Nara-City Nara-Prefecture 6310013 - JAPAN - - 00-50-C2 (hex) Casabyte Inc. - A34000-A34FFF (base 16) Casabyte Inc. - 200 Country Club Drive - Blacksburg VA 24060 - UNITED STATES - - 00-50-C2 (hex) Appareo Systems, LLC - A35000-A35FFF (base 16) Appareo Systems, LLC - 1854 NDSU Research Circle North - Fargo ND 58102 - UNITED STATES - - 00-50-C2 (hex) Shenzhen Shangji electronic Co.Ltd - A36000-A36FFF (base 16) Shenzhen Shangji electronic Co.Ltd - Room 2017, Tianan Digital Era Building, Futian District, - Shenzhen Guangdong 518048 - CHINA - - 00-50-C2 (hex) Software Systems Plus - A37000-A37FFF (base 16) Software Systems Plus - 9924 N. Ash Avenue - Kansas City Missouri 64157 - UNITED STATES - - 00-50-C2 (hex) Tred Displays - A38000-A38FFF (base 16) Tred Displays - 5201 Eagle Rock Rd NE - Suite 2B - Albuquerque NM 87113 - UNITED STATES - - 00-50-C2 (hex) Industrial Data Products Ltd - A39000-A39FFF (base 16) Industrial Data Products Ltd - The Studio - Oldbury Business Centre - Cwmbran Gwent NP44 3JU - UNITED KINGDOM - - 00-50-C2 (hex) Telecor Inc. - A3A000-A3AFFF (base 16) Telecor Inc. - 1114 Westport Crescent - Mississauga Ontario L5T 1G1 - CANADA - - 00-50-C2 (hex) IPcontrols GmbH - A3B000-A3BFFF (base 16) IPcontrols GmbH - Neue Kasseler Str. 50 - Marburg 35039 - GERMANY - - 00-50-C2 (hex) Brähler ICS Konferenztechnik AG - A3C000-A3CFFF (base 16) Brähler ICS Konferenztechnik AG - Auf der Alten Burg 6 - Koenigswinter NRW 53639 - GERMANY - - 00-50-C2 (hex) OWANDY - A3D000-A3DFFF (base 16) OWANDY - 6 Allée Kepler - Champs sur Marne 77420 - FRANCE - - 00-50-C2 (hex) DUEVI SNC DI MORA E SANTESE - A3E000-A3EFFF (base 16) DUEVI SNC DI MORA E SANTESE - Via Gioberti 7 - Piossasco Torino 10045 - ITALY - - 00-50-C2 (hex) LHA Systems CC - A3F000-A3FFFF (base 16) LHA Systems CC - 1 Innovation Centre 2 - Technopark - Stellenbosch Western Cape 7600 - SOUTH AFRICA - - 00-50-C2 (hex) Mosberger Consulting LLC - A40000-A40FFF (base 16) Mosberger Consulting LLC - 1935 Stony Hill Rd - Boulder CO 80305 - UNITED STATES - - 00-50-C2 (hex) Meiryo Denshi Corp. - A41000-A41FFF (base 16) Meiryo Denshi Corp. - 38-23 higashi maeda - Asada cho - Nishin City Aichi 470-0124 - JAPAN - - 00-50-C2 (hex) RealVision Inc. - A42000-A42FFF (base 16) RealVision Inc. - 3-1-4 Shin-Yokohama, Kouhoku-Ku - Yokohama Kanagawa 222-0033 - JAPAN - - 00-50-C2 (hex) NKS Co.Ltd. - A43000-A43FFF (base 16) NKS Co.Ltd. - Yodogawa-ku Niitaka - 1-8-17 - Osaka 532-0033 - JAPAN - - 00-50-C2 (hex) TORC Technologies - A44000-A44FFF (base 16) TORC Technologies - 2200 Kraft Dr, Ste 1325 - Blacksburg VA 24060 - UNITED STATES - - 00-50-C2 (hex) Sofradir-EC - A45000-A45FFF (base 16) Sofradir-EC - 373 Route 46 West - Fairfield NJ 07004 - UNITED STATES - - 00-50-C2 (hex) Softronics Ltd. - A46000-A46FFF (base 16) Softronics Ltd. - 6920 Bowman Lane NE - Cedar Rapids IA 52402 - UNITED STATES - - 00-50-C2 (hex) PRIMETECH ENGINEERING CORP. - A47000-A47FFF (base 16) PRIMETECH ENGINEERING CORP. - 1-21-15,Kitakoujiya, - Ota-ku Tokyo 144-0032 - JAPAN - - 00-50-C2 (hex) Thales Optronics Limited - A48000-A48FFF (base 16) Thales Optronics Limited - 1 Linthouse Road - Glasgow G51 4BZ - UNITED KINGDOM - - 00-50-C2 (hex) Wayne Dalton Corp. - A49000-A49FFF (base 16) Wayne Dalton Corp. - 3395 addison Dr. - Pensacola FL 32514 - UNITED STATES - - 00-50-C2 (hex) DITRON S.r.l. - A4A000-A4AFFF (base 16) DITRON S.r.l. - Via Antiniana, 115 - Pozzuoli Napoli 80078 - ITALY - - 00-50-C2 (hex) L-3 Communications Mobile-Vision, Inc. - A4B000-A4BFFF (base 16) L-3 Communications Mobile-Vision, Inc. - 90 Fanny Rd. - Boonton NJ 07005 - UNITED STATES - - 00-50-C2 (hex) VasoNova, Inc. - A4C000-A4CFFF (base 16) VasoNova, Inc. - 1368 Bordeaux Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) LevelStar LLC. - A4D000-A4DFFF (base 16) LevelStar LLC. - 685 S. Arthur Ave. - Louisville CO 80027 - UNITED STATES - - 00-50-C2 (hex) Conduant Corporation - A4E000-A4EFFF (base 16) Conduant Corporation - 1501 S. Sunset St. - Suite C - Longmont CO 80501 - UNITED STATES - - 00-50-C2 (hex) Deuta GmbH - A4F000-A4FFFF (base 16) Deuta GmbH - Paffrather Str. 140 - Bergisch Gladbach Northrhine Westfalia 51465 - GERMANY - - 00-50-C2 (hex) i-RED Infrarot Systeme GmbH - A50000-A50FFF (base 16) i-RED Infrarot Systeme GmbH - Hafenstr. 47-51 - Linz Upper Austria 4020 - AUSTRIA - - 00-50-C2 (hex) Y-products co.ltd. - A51000-A51FFF (base 16) Y-products co.ltd. - Yamato-higashi1-11-24 - Yamato-city Kanagawa-pref 242-0017 - JAPAN - - 00-50-C2 (hex) The VON Corporation - A52000-A52FFF (base 16) The VON Corporation - 1038 Lomb Ave. SW - Birmingham AL 35211 - UNITED STATES - - 00-50-C2 (hex) Quality & Design - A53000-A53FFF (base 16) Quality & Design - Bergweg 32 - Rhenen 3911 VB - NETHERLANDS - - 00-50-C2 (hex) Diamond Point International (Europe) Ltd - A54000-A54FFF (base 16) Diamond Point International (Europe) Ltd - 13 Ashford House, Beaufort Court - Sir Thomas Longley Road - Rochester Kent ME2 4FA - UNITED KINGDOM - - 00-50-C2 (hex) Arrowvale Electronics - A55000-A55FFF (base 16) Arrowvale Electronics - Shawbank Road - Lakeside - Redditch Worcestershire B98 8YN - UNITED KINGDOM - - 00-50-C2 (hex) ReaMetrix, Inc. - A56000-A56FFF (base 16) ReaMetrix, Inc. - 1585 Industrial Road - San Carlos CA 94070 - UNITED STATES - - 00-50-C2 (hex) Juice Technologies, LLC - A57000-A57FFF (base 16) Juice Technologies, LLC - 930 Kinnear Rd - Columbus OH 43212 - UNITED STATES - - 00-50-C2 (hex) EPL - A58000-A58FFF (base 16) EPL - 4 IMPASSE DES SAULES - ZA DE LA PITANCERIE - FAREMOUTIERS SEINE ET MARNE 77515 - FRANCE - - 00-50-C2 (hex) GSP Sprachtechnologie GmbH - A59000-A59FFF (base 16) GSP Sprachtechnologie GmbH - Teltowkanalstr. 1 - Berlin 12247 - GERMANY - - 00-50-C2 (hex) ITAS A/S - A5A000-A5AFFF (base 16) ITAS A/S - Klosterport 4A - Ã…rhus C DK-8000 - DENMARK - - 00-50-C2 (hex) Phytec Messtechnik GmbH - A5B000-A5BFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) JSC "Component-ASU" - A5C000-A5CFFF (base 16) JSC "Component-ASU" - Severnyi proezd 1, k.5/6 - Chernogolovka Moscow Region 142432 - RUSSIAN FEDERATION - - 00-50-C2 (hex) MECC CO., LTD. - A5D000-A5DFFF (base 16) MECC CO., LTD. - 196-1 FUKUDO - OGORI-SHI FUKUOKA 838-0137 - JAPAN - - 00-50-C2 (hex) Ansen Investment Holdings Ltd. - A5E000-A5EFFF (base 16) Ansen Investment Holdings Ltd. - Room 78, 2/F, Sino Industrial Plaza, - 9 Kai Cheung Road, - Kowloon Bay - HONG KONG - - 00-50-C2 (hex) Alga Microwave Inc - A5F000-A5FFFF (base 16) Alga Microwave Inc - 2109 St Regis - Dollard-des-Ormeaux QC H9B 2M9 - CANADA - - 00-50-C2 (hex) Arrow Central Europe GmbH - Division Spoerle - A60000-A60FFF (base 16) Arrow Central Europe GmbH - Division Spoerle - Max-Planck-Str. 1-3 - Dreieich D-63303 - GERMANY - - 00-50-C2 (hex) Fr. Sauter AG - A61000-A61FFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel CH4016 - SWITZERLAND - - 00-50-C2 (hex) Grossenbacher Systeme AG - A62000-A62FFF (base 16) Grossenbacher Systeme AG - Spinnereistrasse 10 - St. Gallen 9008 - SWITZERLAND - - 00-50-C2 (hex) EMS Industries - A63000-A63FFF (base 16) EMS Industries - PO Box 38822 - Faerie Glen - Pretoria Gauteng 0043 - SOUTH AFRICA - - 00-50-C2 (hex) tetronik GmbH AEN - A64000-A64FFF (base 16) tetronik GmbH AEN - Silberbachstr.10 - Taunusstein Hessen 65232 - GERMANY - - 00-50-C2 (hex) Mark-O-Print GmbH - A65000-A65FFF (base 16) Mark-O-Print GmbH - Reepschlaeger Strasse 11a - Luebeck Schleswig-Holstein 23556 - GERMANY - - 00-50-C2 (hex) DVTech - A66000-A66FFF (base 16) DVTech - 10 Kehilat Venezia st. - Tel Aviv Israel 69400 - ISRAEL - - 00-50-C2 (hex) GSS Avionics Limited - A67000-A67FFF (base 16) GSS Avionics Limited - Thorne House - Eastville - Yeovil Somerset BA214JD - UNITED KINGDOM - - 00-50-C2 (hex) X-Pert Paint Mixing Systems - A68000-A68FFF (base 16) X-Pert Paint Mixing Systems - 2715 Lincoln Drive - Roseville MN 55113 - UNITED STATES - - 00-50-C2 (hex) Advanced Integrated Systems - A69000-A69FFF (base 16) Advanced Integrated Systems - 81 David Love Pl. - Suite J - Goleta CA 93117 - UNITED STATES - - 00-50-C2 (hex) Infocrossing - A6A000-A6AFFF (base 16) Infocrossing - 11800 Ridge Parkway - Broomfield CO 80021 - UNITED STATES - - 00-50-C2 (hex) Explorer Inc. - A6B000-A6BFFF (base 16) Explorer Inc. - 379-22 - kikyou-cho - Hakodateshi Hokkaido 041-0801 - JAPAN - - 00-50-C2 (hex) Figment Design Laboratories - A6C000-A6CFFF (base 16) Figment Design Laboratories - 113 11th Avenue - Fairland - Johannesburg Guateng 2170 - SOUTH AFRICA - - 00-50-C2 (hex) DTV Innovations - A6D000-A6DFFF (base 16) DTV Innovations - 1252 W. Northwest Highway - Palatine IL 60067 - UNITED STATES - - 00-50-C2 (hex) Screen Technics Pty Limited - A6E000-A6EFFF (base 16) Screen Technics Pty Limited - Corner Vale & Suttor Roads - PO Box 745 - Moss Vale NSW 2577 - AUSTRALIA - - 00-50-C2 (hex) Saia-Burgess Controls AG - A6F000-A6FFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Reliable System Services Corp - A70000-A70FFF (base 16) Reliable System Services Corp - 746 North Drive - Suite B - Melbourne Florida 32934 - UNITED STATES - - 00-50-C2 (hex) Purite Ltd - A71000-A71FFF (base 16) Purite Ltd - Bandet Way - Thame Oxfordshire OX9 3SJ - UNITED KINGDOM - - 00-50-C2 (hex) Gamber-Johnson LLC. - A72000-A72FFF (base 16) Gamber-Johnson LLC. - 3001 Borham Avenue - Stevens Point WI 54481 - UNITED STATES - - 00-50-C2 (hex) KYOEI ENGINEERING Co.,Ltd. - A73000-A73FFF (base 16) KYOEI ENGINEERING Co.,Ltd. - 1-3-35 ATSUBETSU HIGASHI 5 JYO - ATSUBETSU-KU - SAPPORO-SHI HOKKAIDO 004-0005 - JAPAN - - 00-50-C2 (hex) DSP DESIGN LTD - A74000-A74FFF (base 16) DSP DESIGN LTD - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) JTL Systems Ltd. - A75000-A75FFF (base 16) JTL Systems Ltd. - 41 Kingfisher Court - Hambridge Road - Newbury Berks RG14 5SJ - UNITED KINGDOM - - 00-50-C2 (hex) Roesch & Walter Industrie-Elektronik GmbH - A76000-A76FFF (base 16) Roesch & Walter Industrie-Elektronik GmbH - Woertelweg 2b/c - Schwanau 77963 - GERMANY - - 00-50-C2 (hex) Keith & Koep GmbH - A77000-A77FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Apantac LLC - A78000-A78FFF (base 16) Apantac LLC - 13500 SW Pacific HWY - #117 - Portland OR 97223 - UNITED STATES - - 00-50-C2 (hex) Saintronic - A79000-A79FFF (base 16) Saintronic - Parc Atlantique - Ormeau de Pied - Saintes France 17100 - FRANCE - - 00-50-C2 (hex) DetNet South Africa PTY (LTD) - A7A000-A7AFFF (base 16) DetNet South Africa PTY (LTD) - 1 Platinum Drive - Longmeadow Business Estate - Modderfontein Gauteng 1645 - SOUTH AFRICA - - 00-50-C2 (hex) Orange Tree Technologies - A7B000-A7BFFF (base 16) Orange Tree Technologies - Harwell Innovation Centre - 173 Curie Avenue - Didcot Oxfordshire OX110QG - UNITED KINGDOM - - 00-50-C2 (hex) Pneu-Logic Corporation - A7C000-A7CFFF (base 16) Pneu-Logic Corporation - 6650 SW Redwood Lane - Suite 390 - Portland OR 97224 - UNITED STATES - - 00-50-C2 (hex) Vitel Net - A7D000-A7DFFF (base 16) Vitel Net - 8201 Greensboro Dr. - Ste 600 - McLean VA 22102 - UNITED STATES - - 00-50-C2 (hex) Independent Project Engineering Ltd - A7E000-A7EFFF (base 16) Independent Project Engineering Ltd - Saxon Way - Melbourn - Royston Herts SG8 6DN - UNITED KINGDOM - - 00-50-C2 (hex) Phytec Messtechnik GmbH - A7F000-A7FFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) ARD SA - A80000-A80FFF (base 16) ARD SA - Micropolis BP 169 - GAP 05005 - FRANCE - - 00-50-C2 (hex) BPC circuits Ltd - A81000-A81FFF (base 16) BPC circuits Ltd - Omni House - Sheene Road - Leicester LE4 1BF - UNITED KINGDOM - - 00-50-C2 (hex) CT Company - A82000-A82FFF (base 16) CT Company - Godovikova 9, Moscow - Moscow RUSSIA 129085 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Techno Sobi Co. Ltd. - A83000-A83FFF (base 16) Techno Sobi Co. Ltd. - Tsurunoso 6-11 - Takarazuka-shi Hyogo-ken 6650833 - JAPAN - - 00-50-C2 (hex) Lino Manfrotto +Co spa - A84000-A84FFF (base 16) Lino Manfrotto +Co spa - via sasso rosso 19 - Bassano del Grappa Vicenza 36061 - ITALY - - 00-50-C2 (hex) JOYSYSTEM - A85000-A85FFF (base 16) JOYSYSTEM - 2-3-21 DAIKAIDORI - HYOGO-KU - KOBE HYOUGO 652-0803 - JAPAN - - 00-50-C2 (hex) LIMAB AB - A86000-A86FFF (base 16) LIMAB AB - Almedalsvägen 15 - Göteborg 41263 - SWEDEN - - 00-50-C2 (hex) Littlemore Scientific - A87000-A87FFF (base 16) Littlemore Scientific - Gutchpool Farm - Gillingham Dorset SP8 5QP - UNITED KINGDOM - - 00-50-C2 (hex) S-SYS - A88000-A88FFF (base 16) S-SYS - Dijkstraat 8 - Ham Limburg 3945 - BELGIUM - - 00-50-C2 (hex) CA Traffic Ltd - A89000-A89FFF (base 16) CA Traffic Ltd - Griffin Lane - Aylesbury Buckinghamshire HP198BP - UNITED KINGDOM - - 00-50-C2 (hex) Audio Engineering Ltd. - A8A000-A8AFFF (base 16) Audio Engineering Ltd. - 75 Parnell Rise - Parnell - Auckland 1052 - NEW ZEALAND - - 00-50-C2 (hex) Navicron Oy - A8B000-A8BFFF (base 16) Navicron Oy - Teknologiantie 7A - Oulu 90570 - FINLAND - - 00-50-C2 (hex) Redwire, LLC - A8C000-A8CFFF (base 16) Redwire, LLC - 8 Thorndike St - Everett MA 02149 - UNITED STATES - - 00-50-C2 (hex) Frontier Electronic Systems Corp. - A8D000-A8DFFF (base 16) Frontier Electronic Systems Corp. - 4500 W 6th Ave - Stillwater OK 74074 - UNITED STATES - - 00-50-C2 (hex) BFI Industrie-Elektronik GmbH & Co.KG - A8E000-A8EFFF (base 16) BFI Industrie-Elektronik GmbH & Co.KG - Winchenbachstrasse 3b - Wuppertal NRW 42281 - GERMANY - - 00-50-C2 (hex) Quantum3D, Inc. - A8F000-A8FFFF (base 16) Quantum3D, Inc. - 6330 San Igancio Ave - San Jose CA 95119 - UNITED STATES - - 00-50-C2 (hex) S.two Corporation - A90000-A90FFF (base 16) S.two Corporation - 9475 Double R Blvd. - Reno NV 89521 - UNITED STATES - - 00-50-C2 (hex) Ceron Tech Co.,LTD - A91000-A91FFF (base 16) Ceron Tech Co.,LTD - #809-1, Kranz Techno, 5442-1, - Sangdaewon-dong, Jungwon-gu - Seongnam-si 462-819 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Sicon s.r.l. - A92000-A92FFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) SPX Dehydration & Filtration - A93000-A93FFF (base 16) SPX Dehydration & Filtration - 4647 S.W. 40th Ave. - Ocala FL 34474 - UNITED STATES - - 00-50-C2 (hex) Par-Tech, Inc. - A94000-A94FFF (base 16) Par-Tech, Inc. - 139 Premier Dr. - Lake Orion MI 48359 - UNITED STATES - - 00-50-C2 (hex) INNOVACIONES Microelectrónicas SL (AnaFocus) - A95000-A95FFF (base 16) INNOVACIONES Microelectrónicas SL (AnaFocus) - C/Isaac Newton, nº 4-Pabellón de Italia-7ªPlanta çtico - Parque Tecnologico Isla de la Cartuja - Sevilla 41092 - SPAIN - - 00-50-C2 (hex) FEP SRL - A96000-A96FFF (base 16) FEP SRL - VIA MODENA, 68 - SAN GIOVANNI IN PERSICETO BOLOGNA 40017 - ITALY - - 00-50-C2 (hex) MICROSYSTEMES - A97000-A97FFF (base 16) MICROSYSTEMES - 14 rue Jean Perrin - ZI du Chapitre - TOULOUSE 31100 - FRANCE - - 00-50-C2 (hex) Sentry 360 Security - A98000-A98FFF (base 16) Sentry 360 Security - 1280 Iroquois Ave - Suite 108 - Naperville IL 60563 - UNITED STATES - - 00-50-C2 (hex) Haivision Systems Inc - A99000-A99FFF (base 16) Haivision Systems Inc - 4445 Garand - Montreal QC H4R 2H9 - CANADA - - 00-50-C2 (hex) Absolutron. LLC - A9A000-A9AFFF (base 16) Absolutron. LLC - 1107 Fair Oaks Ave. #476 - South Pasadena CA 91030 - UNITED STATES - - 00-50-C2 (hex) PDQ Manufacturing Inc. - A9B000-A9BFFF (base 16) PDQ Manufacturing Inc. - 1698 Scheuring Road - De Pere WI 54115 - UNITED STATES - - 00-50-C2 (hex) Eberspächer Electronics GmbH & Co. KG - A9C000-A9CFFF (base 16) Eberspächer Electronics GmbH & Co. KG - Robert-Bosch-Straße 6 - Göppingen BW 73037 - GERMANY - - 00-50-C2 (hex) Joehl & Koeferli AG - A9D000-A9DFFF (base 16) Joehl & Koeferli AG - Wittenwilerstrasse 31 - Aadorf TG 8355 - SWITZERLAND - - 00-50-C2 (hex) Procon Engineering Limited - A9E000-A9EFFF (base 16) Procon Engineering Limited - Vestry Estate - Otford Road - Sevenoaks Kent TN14 5EL - UNITED KINGDOM - - 00-50-C2 (hex) YellowSoft Co., Ltd. - A9F000-A9FFFF (base 16) YellowSoft Co., Ltd. - 624-7 Takahagi - Hidaka Saitama 350-1213 - JAPAN - - 00-50-C2 (hex) Smith Meter, Inc. - AA0000-AA0FFF (base 16) Smith Meter, Inc. - 1602 Wagner Ave. - Erie PA 16514 - UNITED STATES - - 00-50-C2 (hex) ELREM ELECTRONIC AG - AA1000-AA1FFF (base 16) ELREM ELECTRONIC AG - Unterstrasse 35 - Herzogenbuchsee Bern 3360 - SWITZERLAND - - 00-50-C2 (hex) ELPA sas - AA2000-AA2FFF (base 16) ELPA sas - via Rocciamelone 3 - Caprie TO 10040 - ITALY - - 00-50-C2 (hex) Peek Traffic Corporation - AA3000-AA3FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) PSi Printer Systems international GmbH - AA4000-AA4FFF (base 16) PSi Printer Systems international GmbH - Eiserfelder Strasse 316 - Siegen 57080 - GERMANY - - 00-50-C2 (hex) Tampere University of Technology - AA5000-AA5FFF (base 16) Tampere University of Technology - Korkeakoulunkatu 10 - Tampere Pirkanmaa 33720 - FINLAND - - 00-50-C2 (hex) Bassett Electronic Systems ltd - AA6000-AA6FFF (base 16) Bassett Electronic Systems ltd - Unit 24 Whitehill Ind Park - Wootton Bassett Wiltshire SN4 7DB - UNITED KINGDOM - - 00-50-C2 (hex) Endeas Oy - AA7000-AA7FFF (base 16) Endeas Oy - Heimolantie 6 - Espoo 02330 - FINLAND - - 00-50-C2 (hex) Nexans Cabling Solutions - AA8000-AA8FFF (base 16) Nexans Cabling Solutions - Alsembergsesteenweg 2 B3 - Buizingen 1501 - BELGIUM - - 00-50-C2 (hex) SAN GIORGIO S.E.I.N. srl - AA9000-AA9FFF (base 16) SAN GIORGIO S.E.I.N. srl - Via Pedulla' 59 - Genova 16165 - ITALY - - 00-50-C2 (hex) Flexible Picture Systems - AAA000-AAAFFF (base 16) Flexible Picture Systems - 174 West Beaver Creek Road - Richmond Hill Ontario L4B 1B4 - CANADA - - 00-50-C2 (hex) BRS Sistemas Eletrônicos - AAB000-AABFFF (base 16) BRS Sistemas Eletrônicos - Rua Gomes de Freitas, 491 / 204 - Porto Alegre RS 91380-000 - BRAZIL - - 00-50-C2 (hex) VisiCon GmbH - AAC000-AACFFF (base 16) VisiCon GmbH - Gottf.-Aug.-Buerger-Str. 30 - Gleichen Lower Saxony D-37130 - GERMANY - - 00-50-C2 (hex) Update Systems Inc. - AAD000-AADFFF (base 16) Update Systems Inc. - 10545 Baur Blvd. - Saint Louis MO 63132 - UNITED STATES - - 00-50-C2 (hex) OUTLINE srl - AAE000-AAEFFF (base 16) OUTLINE srl - VIA LEONARDO DA VINCI N°56 - FLERO BRESCIA 25020 - ITALY - - 00-50-C2 (hex) Santa Barbara Instrument Group - AAF000-AAFFFF (base 16) Santa Barbara Instrument Group - 147A Castilian Drive - Santa Barbara CA 93117 - UNITED STATES - - 00-50-C2 (hex) FRAKO Kondensatoren- und Anlagenbau GmbH - AB0000-AB0FFF (base 16) FRAKO Kondensatoren- und Anlagenbau GmbH - Tscheulinstrasse 21 a - Teningen 79331 - GERMANY - - 00-50-C2 (hex) Bitmanufaktur GmbH - AB1000-AB1FFF (base 16) Bitmanufaktur GmbH - Schwedter Str. 23 - Berlin 10119 - GERMANY - - 00-50-C2 (hex) ProCom Systems, Inc. - AB2000-AB2FFF (base 16) ProCom Systems, Inc. - 5100 Coachman Road - Bettendorf IA 52722 - UNITED STATES - - 00-50-C2 (hex) Compañía de Instrumentacion y control, S.L. - AB3000-AB3FFF (base 16) Compañía de Instrumentacion y control, S.L. - C/Maria Auxiliadora 5, 1ºI - Madrid 28040 - SPAIN - - 00-50-C2 (hex) n3k Informatik GmbH - AB4000-AB4FFF (base 16) n3k Informatik GmbH - Ferdinand-Braun-Straße 3 - Heilbronn Baden-Württemberg 74074 - GERMANY - - 00-50-C2 (hex) METTLER-TOLEDO HI-SPEED - AB5000-AB5FFF (base 16) METTLER-TOLEDO HI-SPEED - 5 BARR ROAD - ITHACA NY 14850 - UNITED STATES - - 00-50-C2 (hex) Gygax Embedded Engineering GEE.ch - AB6000-AB6FFF (base 16) Gygax Embedded Engineering GEE.ch - Nuovo AG - Greuter Elektrotechnik - Dorfstr. 26 - Wetzikon CH-8620 - SWITZERLAND - - 00-50-C2 (hex) Twinfalls Technologies - AB7000-AB7FFF (base 16) Twinfalls Technologies - 604 - 500 W 10th Ave - Vancouver BC V5Z4P1 - CANADA - - 00-50-C2 (hex) AHM Limited (CLiKAPAD) - AB8000-AB8FFF (base 16) AHM Limited (CLiKAPAD) - Arlington House, Dittons Bus. Pk - Dittons Road - POLEGATE East Sussex BN266HY - UNITED KINGDOM - - 00-50-C2 (hex) Showtacle - AB9000-AB9FFF (base 16) Showtacle - Pecnianska 21 - Bratislava 85101 - SLOVAKIA - - 00-50-C2 (hex) Saia-Burgess Controls AG - ABA000-ABAFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Volantic AB - ABB000-ABBFFF (base 16) Volantic AB - Gymnasievagen 16 - Skelleftea Vasterbotten 931 53 - SWEDEN - - 00-50-C2 (hex) Barrick - ABC000-ABCFFF (base 16) Barrick - Balsamos Norte 324B y calle quinta - Urdesa Central - Guayaquil Guayas 593 - ECUADOR - - 00-50-C2 (hex) Monitor Business Machines Ltd. - ABD000-ABDFFF (base 16) Monitor Business Machines Ltd. - PO Box 108 042 - Symonds Street - Auckland - NEW ZEALAND - - 00-50-C2 (hex) AP Labs - ABE000-ABEFFF (base 16) AP Labs - 10864 THORNMINT ROAD - SAN DIEGO CALIFORNIA 92127 - UNITED STATES - - 00-50-C2 (hex) MCC Computer Company - ABF000-ABFFFF (base 16) MCC Computer Company - 505 E. Palm Valley Blvd - Suite 250 - Round Rock Texas 78664 - UNITED STATES - - 00-50-C2 (hex) DS PRO Audio Ltda - AC0000-AC0FFF (base 16) DS PRO Audio Ltda - Rua Washington Luiz 675 sala 1116 - Centro - Porto Alegre RS 90.010-460 - BRAZIL - - 00-50-C2 (hex) DAISHIN-DENSHI Co., Ltd - AC1000-AC1FFF (base 16) DAISHIN-DENSHI Co., Ltd - 2-38-14 - Hongo - Bunkyou-ku Tokyo 113-0033 - JAPAN - - 00-50-C2 (hex) OpenXS B.V. - AC2000-AC2FFF (base 16) OpenXS B.V. - Koaibosk 3 - Terwispel Friesland 8407ED - NETHERLANDS - - 00-50-C2 (hex) Diversified Control, Inc. - AC3000-AC3FFF (base 16) Diversified Control, Inc. - 3333 California Rd. - Orchard Park New York 14127 - UNITED STATES - - 00-50-C2 (hex) Orion Technologies, Incorporated - AC4000-AC4FFF (base 16) Orion Technologies, Incorporated - 690 Cone Park Court - Suite A - Merritt Island FL 32952 - UNITED STATES - - 00-50-C2 (hex) E-Motion System, Inc. - AC5000-AC5FFF (base 16) E-Motion System, Inc. - 5-21-3. Nishi-Gotanda Shinagawa-ku - Tokyo 141-0031 - JAPAN - - 00-50-C2 (hex) Marathon Products, Inc. - AC6000-AC6FFF (base 16) Marathon Products, Inc. - P.O. Box 21579 - Oakland CA 94620-1579 - UNITED STATES - - 00-50-C2 (hex) WaveIP - AC7000-AC7FFF (base 16) WaveIP - Teradion Ind Park - Misgav Israel 20692 - ISRAEL - - 00-50-C2 (hex) Palladio Systeme GmbH - AC8000-AC8FFF (base 16) Palladio Systeme GmbH - Thalkirchner Str. 76 - 80337 BY 80337 - GERMANY - - 00-50-C2 (hex) Steinbeis-Transferzentrum Embedded Design und Networking - AC9000-AC9FFF (base 16) Steinbeis-Transferzentrum Embedded Design und Networking - Poststraße 35 - Heitersheim Baden-Württemberg 79423 - GERMANY - - 00-50-C2 (hex) Soft & Control Technology s.r.o. - ACA000-ACAFFF (base 16) Soft & Control Technology s.r.o. - Magnezitarska 10 - Kosice Kosice mesto 04013 - SLOVAKIA - - 00-50-C2 (hex) U-CARE INC. - ACB000-ACBFFF (base 16) U-CARE INC. - Room no. 407, Medical industry venture center - 1272 Maeji-ri, Huengup-myun - Kangwon-do 220-842 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) StockerYale - ACC000-ACCFFF (base 16) StockerYale - 3020 Euro Business Park - Little Island - Cork - IRELAND - - 00-50-C2 (hex) MeshWorks Wireless Oy - ACD000-ACDFFF (base 16) MeshWorks Wireless Oy - Hermiankatu 6-8 H - Tampere Suomi 33720 - FINLAND - - 00-50-C2 (hex) ChronoLogic Pty. Ltd. - ACE000-ACEFFF (base 16) ChronoLogic Pty. Ltd. - 227 Gouger Street - Adelaide South Australia 5000 - AUSTRALIA - - 00-50-C2 (hex) SP Controls, Inc - ACF000-ACFFFF (base 16) SP Controls, Inc - 930 Linden Ave - South San Francisco CA 94086 - UNITED STATES - - 00-50-C2 (hex) Geonautics Australia Pty Ltd - AD0000-AD0FFF (base 16) Geonautics Australia Pty Ltd - 60 Morley Street - Coorparoo - Brisbane Queensland 4151 - AUSTRALIA - - 00-50-C2 (hex) Phytec Messtechnik GmbH - AD1000-AD1FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Rafael - AD2000-AD2FFF (base 16) Rafael - P.o.b. 962 31009 - Library dep. C0-900 - Haifa 31009 31009 - ISRAEL - - 00-50-C2 (hex) Peek Traffic Corporation - AD3000-AD3FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) Global Rainmakers Inc. - AD4000-AD4FFF (base 16) Global Rainmakers Inc. - 10 East 53rd St. - Floor 33 - New York NY 10022 - UNITED STATES - - 00-50-C2 (hex) Mighty Lube Systematic Lubrication, Inc. - AD5000-AD5FFF (base 16) Mighty Lube Systematic Lubrication, Inc. - 9569 West 40th Street - Fremont MI 49412 - UNITED STATES - - 00-50-C2 (hex) Unisensor A/S - AD6000-AD6FFF (base 16) Unisensor A/S - Gydevang 42 - Alleroed 3450 - DENMARK - - 00-50-C2 (hex) Air Monitors Ltd - AD7000-AD7FFF (base 16) Air Monitors Ltd - Unit 2 Bredon Court - Brockeridge Park Twyning - Tewkesbury Gloucestershire GL20 6FF - UNITED KINGDOM - - 00-50-C2 (hex) Incyma - AD8000-AD8FFF (base 16) Incyma - Victor-Duret 18 - Onex GE 1213 - SWITZERLAND - - 00-50-C2 (hex) elettrondata srl - AD9000-AD9FFF (base 16) elettrondata srl - via del canaletto 77/79 - spezzano di fiorano modena 41042 - ITALY - - 00-50-C2 (hex) Essepie Srl - ADA000-ADAFFF (base 16) Essepie Srl - Via Artigianato,5 - DALMINE BERGAMO 24044 - ITALY - - 00-50-C2 (hex) GO engineering GmbH - ADB000-ADBFFF (base 16) GO engineering GmbH - Stolzenbergstraße 13/IV - Baden-Württemberg 76532 - GERMANY - - 00-50-C2 (hex) Synthesechemie Dr. Penth GmbH - ADC000-ADCFFF (base 16) Synthesechemie Dr. Penth GmbH - Lebacher Strasse 60 - Heusweiler Saarland 66822 - GERMANY - - 00-50-C2 (hex) General Dynamics C4 Sysems - ADD000-ADDFFF (base 16) General Dynamics C4 Sysems - 8220 East Rooseevelt St. - MD: R1122 - Scottsdale Arizona 85157-3812 - UNITED STATES - - 00-50-C2 (hex) Neoptix Inc. - ADE000-ADEFFF (base 16) Neoptix Inc. - 1415 Frank-Carrel - Suite 220 - Quebec G1N4N7 - CANADA - - 00-50-C2 (hex) Altinex, Inc - ADF000-ADFFFF (base 16) Altinex, Inc - 592 Apollo Street - Brea CA 92821 - UNITED STATES - - 00-50-C2 (hex) AT4 wireless.S.A - AE0000-AE0FFF (base 16) AT4 wireless.S.A - c/ Severo Ochoa 2 - P.T.A - Campanillas Málaga 29590 - SPAIN - - 00-50-C2 (hex) EVERCARE - AE1000-AE1FFF (base 16) EVERCARE - 4fl., 620-1 Shinsa-dong - Gangnam-Gu - Seoul 135-890 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Power Medical Interventions - AE2000-AE2FFF (base 16) Power Medical Interventions - 2021 Cabot Blvd. West - Langhorne PA 19047 - UNITED STATES - - 00-50-C2 (hex) PSD - AE3000-AE3FFF (base 16) PSD - Boerkensleen 31 - Roosendaal 4705 RL - NETHERLANDS - - 00-50-C2 (hex) Advanced Electronic Designs, Inc. - AE4000-AE4FFF (base 16) Advanced Electronic Designs, Inc. - 233 Enterprise Blvd - Bozeman MT 59718 - UNITED STATES - - 00-50-C2 (hex) ABS Gesellschaft f. Automatisierung, Bildverarbeitung und Software mbH - AE5000-AE5FFF (base 16) ABS Gesellschaft f. Automatisierung, Bildverarbeitung und Software mbH - Erlanger Alle 103 - Jena Thueringen 07747 - GERMANY - - 00-50-C2 (hex) VECOM USA - AE6000-AE6FFF (base 16) VECOM USA - 4803 George Road - Unit 300 - Tampa FL 33634 - UNITED STATES - - 00-50-C2 (hex) Redwood Systems - AE7000-AE7FFF (base 16) Redwood Systems - 3839 Spinnaker Ct. - Fremont CA 94538 - UNITED STATES - - 00-50-C2 (hex) Bit-Lab PTY LTD - AE8000-AE8FFF (base 16) Bit-Lab PTY LTD - 4 Ferrer Place - Woodlands WA 6018 - AUSTRALIA - - 00-50-C2 (hex) ClearCorp Enterprises, Inc - AE9000-AE9FFF (base 16) ClearCorp Enterprises, Inc - 7485 Park Lane Rd - Longmont CO 80503 - UNITED STATES - - 00-50-C2 (hex) EMBEDIA - AEA000-AEAFFF (base 16) EMBEDIA - 11 Avenue Albert EINSTEIN - VILLEURBANNE 69100 - FRANCE - - 00-50-C2 (hex) UMLogics Corporation - AEB000-AEBFFF (base 16) UMLogics Corporation - EXPOTEL 924, 381 Manyeon-dong, Seo-gu - Daejeon 302-150 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Fritz Pauker Ingenieure GmbH - AEC000-AECFFF (base 16) Fritz Pauker Ingenieure GmbH - Paul-Lenz-Str. 5 - Friedberg Bayern 86316 - GERMANY - - 00-50-C2 (hex) 3Roam - AED000-AEDFFF (base 16) 3Roam - Parc Haute Technologie, Bat 6 - 694 Avenue Maurice Donat - Mougins 06250 - FRANCE - - 00-50-C2 (hex) IPtec, Inc. - AEE000-AEEFFF (base 16) IPtec, Inc. - 5673 W. Las Positas Blvd. - Suite 207 - Pleasanton CA 94588 - UNITED STATES - - 00-50-C2 (hex) National CineMedia - AEF000-AEFFFF (base 16) National CineMedia - 9110 East Nichols Ave. - Suite 200 - Centennial CO 80112 - UNITED STATES - - 00-50-C2 (hex) Fr. Sauter AG - AF0000-AF0FFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel 4016 - SWITZERLAND - - 00-50-C2 (hex) Green Goose - AF1000-AF1FFF (base 16) Green Goose - 6025 SW Taylor St. - Portland OR 97221 - UNITED STATES - - 00-50-C2 (hex) ACD Elektronik GmbH - AF2000-AF2FFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) Palomar Products, Inc. - AF3000-AF3FFF (base 16) Palomar Products, Inc. - 23042 Arroyo Vista - Rancho Santa Margarita California 92688 - UNITED STATES - - 00-50-C2 (hex) Dixell S.p.A. - AF4000-AF4FFF (base 16) Dixell S.p.A. - Via dell'Industria, 27 - Pieve d'Alpago Belluno 32010 - ITALY - - 00-50-C2 (hex) Kramara s.r.o. - AF5000-AF5FFF (base 16) Kramara s.r.o. - Cisovicka 246 - Mnisek pod Brdy Stredocesky kraj 25210 - CZECH REPUBLIC - - 00-50-C2 (hex) Energid - AF6000-AF6FFF (base 16) Energid - One Mifflin Place - Suite 400 - Cambridge MA 02138 - UNITED STATES - - 00-50-C2 (hex) Midwest Microwave Solutions Inc. - AF7000-AF7FFF (base 16) Midwest Microwave Solutions Inc. - 4150 Oak Valley Drive NE - Cedar Rapids Iowa 52411 - UNITED STATES - - 00-50-C2 (hex) Global Satellite Engineering - AF8000-AF8FFF (base 16) Global Satellite Engineering - 1831 Cordova Road - Fort Lauderdale FL 33316 - UNITED STATES - - 00-50-C2 (hex) Ingenieurbuero Bickele und Buehler GmbH - AF9000-AF9FFF (base 16) Ingenieurbuero Bickele und Buehler GmbH - St.Poeltener Str. 70 - Stuttgart BW 70469 - GERMANY - - 00-50-C2 (hex) Absolute Fire Solutions Inc. - AFA000-AFAFFF (base 16) Absolute Fire Solutions Inc. - 1338 - 36 Ave NE - Calgary Alberta T2E 6T6 - CANADA - - 00-50-C2 (hex) Vocality International Ltd - AFB000-AFBFFF (base 16) Vocality International Ltd - Lydling Barn - Puttenham Lane - Shackleford Surrey GU8 6AP - UNITED KINGDOM - - 00-50-C2 (hex) Odus Technologies SA - AFC000-AFCFFF (base 16) Odus Technologies SA - Rue des bosquets 18 - VEVEY VAUD 1800 - SWITZERLAND - - 00-50-C2 (hex) HomeScenario, Inc. - AFD000-AFDFFF (base 16) HomeScenario, Inc. - 5F No. 9 Sec. 2 Ho-Ping W. Rd. - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Trolex Limited - AFE000-AFEFFF (base 16) Trolex Limited - Newby Road, - Hazel Grove, - Stockport. Cheshire SK7 5DY - UNITED KINGDOM - - 00-50-C2 (hex) XoByte LLC - AFF000-AFFFFF (base 16) XoByte LLC - 235 Peconic Street - Ronkonkoma New York 11779 - UNITED STATES - - 00-50-C2 (hex) Saia-Burgess Controls AG - B00000-B00FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) HSR Harald L. Reuter - B01000-B01FFF (base 16) HSR Harald L. Reuter - Entwicklung - Reparatur - Fertigung - Kammermühlenweg 24 - Bielefeld NRW 33607 - GERMANY - - 00-50-C2 (hex) MASTER CO LTD - B02000-B02FFF (base 16) MASTER CO LTD - 42-20, Palyong-Dong - Changwon-City Gyeongnam 641-847 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Spider Tecnologia Ind. e Com. Ltda. - B03000-B03FFF (base 16) Spider Tecnologia Ind. e Com. Ltda. - Rua Alencar Araripe, 1440 - Sacoma - São Paulo 04253-000 - BRAZIL - - 00-50-C2 (hex) Ubiquiti Networks - B04000-B04FFF (base 16) Ubiquiti Networks - 91 E Tasman Dr - San Jose CA 95134 - UNITED STATES - - 00-50-C2 (hex) POLA s.r.l. - B05000-B05FFF (base 16) POLA s.r.l. - via Del Perolo 13 - Soncino CR 26029 - ITALY - - 00-50-C2 (hex) CompuDesigns, Inc. - B06000-B06FFF (base 16) CompuDesigns, Inc. - 1655 Redbourne Drive - Sandy Springs GA 30350-5640 - UNITED STATES - - 00-50-C2 (hex) FARECO - B07000-B07FFF (base 16) FARECO - 8 EUROPARC de la Sainte Victoire - Le Canet - MEYREUIL 13590 - FRANCE - - 00-50-C2 (hex) Goerlitz AG - B08000-B08FFF (base 16) Goerlitz AG - August-Thyssen-Str. 32 - Koblenz Rheinland-Pfalz 56077 - GERMANY - - 00-50-C2 (hex) Harper Chalice Group Limited - B09000-B09FFF (base 16) Harper Chalice Group Limited - 8 Binns Close - Tile Hill - Coventry West Midlands CV4 9TB - UNITED KINGDOM - - 00-50-C2 (hex) Indutherm Giesstechnologie GmbH - B0A000-B0AFFF (base 16) Indutherm Giesstechnologie GmbH - Brettener Straße 32 - Walzbachtal Baden-Württemberg 75045 - GERMANY - - 00-50-C2 (hex) Honeywell - B0B000-B0BFFF (base 16) Honeywell - 13350 US Hwy 19 North - MS/522-4 - Clearwater FL 33764-7290 - UNITED STATES - - 00-50-C2 (hex) SMARTB TECHNOLOGIES - B0C000-B0CFFF (base 16) SMARTB TECHNOLOGIES - #625 1ST FLOOR 3 RD CROSS CBI MAIN ROAD HMT LAYOUT RT NAGAR - BANAGALORE KARNATAKA 560032 - INDIA - - 00-50-C2 (hex) Japan Electronics System, Inc - B0D000-B0DFFF (base 16) Japan Electronics System, Inc - Sanno 3-45-3 - Sanno Hills 2F - Ota ku Tokyo 143-0023 - JAPAN - - 00-50-C2 (hex) KYAB Lulea AB - B0E000-B0EFFF (base 16) KYAB Lulea AB - Aurorum 6 - Lulea Norrbotten 97775 - SWEDEN - - 00-50-C2 (hex) NARA Controls Inc. - B0F000-B0FFFF (base 16) NARA Controls Inc. - Nara Bldg. 71-22 Chungdamdong Kangnamku - Seoul 135-100 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Marine Entertainment Systems Ltd - B10000-B10FFF (base 16) Marine Entertainment Systems Ltd - LSC House - Murray Road - Orpington Kent BR5 3QY - UNITED KINGDOM - - 00-50-C2 (hex) EXEL s.r.l - B11000-B11FFF (base 16) EXEL s.r.l - Via di Corticella 201 - Bologna 40128 - ITALY - - 00-50-C2 (hex) CM Elektronik GmbH - B12000-B12FFF (base 16) CM Elektronik GmbH - Im Kleinfeldele 17 - Riegel a.K. Baden-Württemberg 79359 - GERMANY - - 00-50-C2 (hex) Measy Electronics Co., Ltd. - B13000-B13FFF (base 16) Measy Electronics Co., Ltd. - Rm 1506, Block B, Haisong Bldg, Tairan 9th Rd, Chegongmiao, Futian - Shenzhen Guangdong 518040 - CHINA - - 00-50-C2 (hex) Keith & Koep GmbH - B14000-B14FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) PhotoTelesis LP - B15000-B15FFF (base 16) PhotoTelesis LP - 4801 NW Loop 410 - Suite 203 - San Antonio Texas 78229 - UNITED STATES - - 00-50-C2 (hex) Neothings, Inc. - B16000-B16FFF (base 16) Neothings, Inc. - 1594 Fayette St - El Cajon CA 92020 - UNITED STATES - - 00-50-C2 (hex) Elcoteq Design Center Oy - B17000-B17FFF (base 16) Elcoteq Design Center Oy - Joensuunkatu 13 - Salo 24100 - FINLAND - - 00-50-C2 (hex) Rosslare Enterprises Limited - B18000-B18FFF (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon - HONG KONG - - 00-50-C2 (hex) Polytron Corporation - B19000-B19FFF (base 16) Polytron Corporation - 4400 Wyland Dr, - Elkhart IN 46516 - UNITED STATES - - 00-50-C2 (hex) ELCUS - B1A000-B1AFFF (base 16) ELCUS - Varshavskaia st. 5a, liter 'L' - St. Petersburg 196128 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Integrated Control Corp. - B1B000-B1BFFF (base 16) Integrated Control Corp. - 748 Park Ave - Huntington NY 11743 - UNITED STATES - - 00-50-C2 (hex) Phytec Messtechnik GmbH - B1C000-B1CFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Telegenix - B1D000-B1DFFF (base 16) Telegenix - 71 Indel Ave. - Rancocas NJ 08073 - UNITED STATES - - 00-50-C2 (hex) Abbott Medical Optics - B1E000-B1EFFF (base 16) Abbott Medical Optics - 1700 East St. Andrew Place - Santa Ana CA 92705 - UNITED STATES - - 00-50-C2 (hex) SCA Schucker GmbH & Co. - B1F000-B1FFFF (base 16) SCA Schucker GmbH & Co. - Gewerbestraße 52 - Bretten-Gölshausen Baden-Württemberg 75015 - GERMANY - - 00-50-C2 (hex) FIVE9 NETWORK SYSTEMS LLC - B20000-B20FFF (base 16) FIVE9 NETWORK SYSTEMS LLC - 3600 W. Bayshore Road - Suite 101 - Palo Alto CA 94303 - UNITED STATES - - 00-50-C2 (hex) Phytron-Elektronik GmbH - B21000-B21FFF (base 16) Phytron-Elektronik GmbH - Industriestraße 12 - Gröbenzell Bavaria 82194 - GERMANY - - 00-50-C2 (hex) FarSite Communications Limited - B22000-B22FFF (base 16) FarSite Communications Limited - Tempus Business Centre - 60 Kingsclere Road - Basingstoke Hampshire RG21 6XG - UNITED KINGDOM - - 00-50-C2 (hex) Ronyo Technologies s.r.o. - B23000-B23FFF (base 16) Ronyo Technologies s.r.o. - Martinovska 3168/48 - Ostrava Moravskoslezský kraj 72300 - CZECH REPUBLIC - - 00-50-C2 (hex) Teledyne Defence Limited - B24000-B24FFF (base 16) Teledyne Defence Limited - Airedale House, Acorn Park - Charlestown - Shipley West Yorkshire BD17 7SW - UNITED KINGDOM - - 00-50-C2 (hex) Triax A/S - B25000-B25FFF (base 16) Triax A/S - Bjørnkærvej 3 - Hornsyld DK-8783 - DENMARK - - 00-50-C2 (hex) Elko Systems - B26000-B26FFF (base 16) Elko Systems - 11 clair road Lynnwood Glen - Pretoria Gauteng 0081 - SOUTH AFRICA - - 00-50-C2 (hex) ATEME - B27000-B27FFF (base 16) ATEME - 26 BUROSPACE - Route de Gizy - BIEVRES CEDEX 91573 - FRANCE - - 00-50-C2 (hex) Micromax Pty. Ltd. - B28000-B28FFF (base 16) Micromax Pty. Ltd. - 5 Orangegrove Ave - Unanderra NSW 2526 - AUSTRALIA - - 00-50-C2 (hex) Integra LifeSciences (Ireland) Ltd - B29000-B29FFF (base 16) Integra LifeSciences (Ireland) Ltd - Sragh Industrial Estate - Tullamore Co Offaly IRELAND - IRELAND - - 00-50-C2 (hex) Trench Austria GmbH - B2A000-B2AFFF (base 16) Trench Austria GmbH - Paschinger Straße 49 - Leonding Austria 4060 - AUSTRIA - - 00-50-C2 (hex) CosmoData Informatica Ltda. - B2B000-B2BFFF (base 16) CosmoData Informatica Ltda. - Rua Artur de Azevedo, 2103 - São Paulo 05404-015 - BRAZIL - - 00-50-C2 (hex) Concepteers, LLC - B2C000-B2CFFF (base 16) Concepteers, LLC - 880 Bergen Ave - Suite 403 - Jersey City NJ 07306 - UNITED STATES - - 00-50-C2 (hex) Datasat Digital Entertainment - B2D000-B2DFFF (base 16) Datasat Digital Entertainment - 9361 Topanga Cyn. Place - Chatsworth California 91311 - UNITED STATES - - 00-50-C2 (hex) ACT - B2E000-B2EFFF (base 16) ACT - Unit C1, South City Business Center - Tallaght - Dublin - IRELAND - - 00-50-C2 (hex) IntelliVision Technologies, Corp - B2F000-B2FFFF (base 16) IntelliVision Technologies, Corp - 5225 Hellyer Ave, Suite 200 - San Jose CA 95138 - UNITED STATES - - 00-50-C2 (hex) Applied Micro Electronics "AME" BV - B30000-B30FFF (base 16) Applied Micro Electronics "AME" BV - ESP 100 - Eindhoven NoordBrabant 5633 AA - NETHERLANDS - - 00-50-C2 (hex) Shop Safe AG - B31000-B31FFF (base 16) Shop Safe AG - Businesspark Giessenmatt 2 - Sins AG CH-5643 - SWITZERLAND - - 00-50-C2 (hex) Byres Security Inc - B32000-B32FFF (base 16) Byres Security Inc - #5-7217 Lantzville Road - Lantzville BC V0R 2H0 - CANADA - - 00-50-C2 (hex) Numcore Ltd - B33000-B33FFF (base 16) Numcore Ltd - Microkatu 1 - Kuopio 70211 - FINLAND - - 00-50-C2 (hex) Meisol co.,ltd - B34000-B34FFF (base 16) Meisol co.,ltd - NAKA-KU YAMASHITA-CHO 74-1 - DAIWACHISYO.bld 1005 - YOKOHAMA-SHI KANAGAWA-KEN 231-0023 - JAPAN - - 00-50-C2 (hex) haneron - B35000-B35FFF (base 16) haneron - 2-22 ota - yao oosaka 581-0037 - JAPAN - - 00-50-C2 (hex) CRDE - B36000-B36FFF (base 16) CRDE - ZI DES GRANDS CAMPS - BP9 - MERCUES 46090 - FRANCE - - 00-50-C2 (hex) IAdea Corporation - B37000-B37FFF (base 16) IAdea Corporation - 3F, NO.33, Lane 77, Xing-ai Road, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Grenmore Ltd - B38000-B38FFF (base 16) Grenmore Ltd - Unit 12, Northpoint Business Park - New Mallow Road - Cork - IRELAND - - 00-50-C2 (hex) siXis, Inc. - B39000-B39FFF (base 16) siXis, Inc. - PO Box 14245 - Research Triangle Park NC 27709-4245 - UNITED STATES - - 00-50-C2 (hex) Nikon Systems Inc. - B3A000-B3AFFF (base 16) Nikon Systems Inc. - 16F Queen's Tower-B, 3-3 - Minatomirai 2-chome,Nishi-ku - Yokohama Kanagawa 220-6116 - JAPAN - - 00-50-C2 (hex) Sportvision Inc. - B3B000-B3BFFF (base 16) Sportvision Inc. - 1240 La Avenida - Mountain View CA 94043 - UNITED STATES - - 00-50-C2 (hex) JanasCard - B3C000-B3CFFF (base 16) JanasCard - 1. pluku 12 - Praha 8 CR 18600 - CZECH REPUBLIC - - 00-50-C2 (hex) AMS - B3D000-B3DFFF (base 16) AMS - 2-4-3,Kikawahigashi,Yodogawaku - Osaka City 532-0012 - JAPAN - - 00-50-C2 (hex) Sage Consultants - B3E000-B3EFFF (base 16) Sage Consultants - Level 1, 169 Kelvin Grove Rd - Kelvin Grove QLD 4059 - AUSTRALIA - - 00-50-C2 (hex) M-Tronic Design and Technology GmbH - B3F000-B3FFFF (base 16) M-Tronic Design and Technology GmbH - Im Großen Gunterstal 8 - Blieskastel Saarland 66440 - GERMANY - - 00-50-C2 (hex) Tecnint HTE SRL - B40000-B40FFF (base 16) Tecnint HTE SRL - Via della Tecnica 16/18 - Osnago Lecco 23875 - ITALY - - 00-50-C2 (hex) Tata Power Company, Strategic Electronics Division - B41000-B41FFF (base 16) Tata Power Company, Strategic Electronics Division - 42/43, Electronics City, - Electronics City PO, Hosur Road, - Bangalore Karnataka 560100 - INDIA - - 00-50-C2 (hex) ETM Electromatic Incorporated - B42000-B42FFF (base 16) ETM Electromatic Incorporated - 35451 Dumbarton Court - NEWARK CA 94560 - UNITED STATES - - 00-50-C2 (hex) J-Systems Inc. - B43000-B43FFF (base 16) J-Systems Inc. - 1S678 School Ave. - Lombard IL 60148 - UNITED STATES - - 00-50-C2 (hex) Ampcontrol Pty Ltd - B44000-B44FFF (base 16) Ampcontrol Pty Ltd - 7 Billbrooke Close - Cameron Park NSW 2285 - AUSTRALIA - - 00-50-C2 (hex) Efftronics Systems (P) Ltd - B45000-B45FFF (base 16) Efftronics Systems (P) Ltd - 40-15-9 - Brundavan Colony - Vijayawada Andhra Pradesh 520010 - INDIA - - 00-50-C2 (hex) Mobileye - B46000-B46FFF (base 16) Mobileye - 13 Hartom st. - Jerusalem 91450 - ISRAEL - - 00-50-C2 (hex) MCS MICRONIC Computer Systeme GmbH - B47000-B47FFF (base 16) MCS MICRONIC Computer Systeme GmbH - Ullsteinstr. 114, Turm C - Berlin 12109 - GERMANY - - 00-50-C2 (hex) MTD GmbH - B48000-B48FFF (base 16) MTD GmbH - Bahnhofstr. 24 - Uffing am Staffelsee Bavaria 82449 - GERMANY - - 00-50-C2 (hex) Aplex Technology Inc. - B49000-B49FFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) Saia-Burgess Controls AG - B4A000-B4AFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Chitose Co.,Ltd - B4B000-B4BFFF (base 16) Chitose Co.,Ltd - Fiato202 - 5-1-1,Tenjin - Koga-City Fukuoka 8113101 - JAPAN - - 00-50-C2 (hex) ElectroCom - B4C000-B4CFFF (base 16) ElectroCom - Torvet 5 - Svendborg Fyn 5700 - DENMARK - - 00-50-C2 (hex) Troll Systems Corporation - B4D000-B4DFFF (base 16) Troll Systems Corporation - 24950 Anza Drive - Valencia CA 91355 - UNITED STATES - - 00-50-C2 (hex) AixControl GmbH - B4E000-B4EFFF (base 16) AixControl GmbH - Jaegerstr. 17-19 - Aachen NRW 52066 - GERMANY - - 00-50-C2 (hex) Sencon UK Ltd. - B4F000-B4FFFF (base 16) Sencon UK Ltd. - Stonebridge Cross Business Park - Droitwich Worcestershire WR9 0LW - UNITED KINGDOM - - 00-50-C2 (hex) SELCO - B50000-B50FFF (base 16) SELCO - ZI DU VAL D'OMBREE - COMBREE SA 49520 - FRANCE - - 00-50-C2 (hex) Aeroflex GmbH - B51000-B51FFF (base 16) Aeroflex GmbH - Gutenbergstrasse 2-4 - Ismaning Bavaria 85737 - GERMANY - - 00-50-C2 (hex) SMH Technologies - B52000-B52FFF (base 16) SMH Technologies - Via Giovanni Agnelli, 1 - Villotta di Chions Pordenone 33083 - ITALY - - 00-50-C2 (hex) Prodco - B53000-B53FFF (base 16) Prodco - 4529 De castille - Montreal Quebec H1H 1Y3 - CANADA - - 00-50-C2 (hex) APG CASH DRAWER - B54000-B54FFF (base 16) APG CASH DRAWER - 5250 Industrial Blvd NE - Minneapolis MN 55421 - UNITED STATES - - 00-50-C2 (hex) SANYO ELECTRONIC INDUSTRIES CO.,LTD - B55000-B55FFF (base 16) SANYO ELECTRONIC INDUSTRIES CO.,LTD - Nagaoka4-73,Nakaku - Okayama 703-8221 - JAPAN - - 00-50-C2 (hex) SINOVIA SA - B56000-B56FFF (base 16) SINOVIA SA - 3 RUE DE CHEVILLY - FRESNES VAL DE MARNE 94260 - FRANCE - - 00-50-C2 (hex) Phytec Messtechnik GmbH - B57000-B57FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Real D - B58000-B58FFF (base 16) Real D - 5335 Sterling Drive - Boulder CO 80301 - UNITED STATES - - 00-50-C2 (hex) SLICAN sp. z o.o. - B59000-B59FFF (base 16) SLICAN sp. z o.o. - ul.M.Konopnickiej 18 - Bydgoszcz Kujawsko-Pomorskie 85-124 - POLAND - - 00-50-C2 (hex) GREEN Center s.r.o. - B5A000-B5AFFF (base 16) GREEN Center s.r.o. - Zenklova 39 - Praha 8 180 00 - CZECH REPUBLIC - - 00-50-C2 (hex) Timberline Mfg Company - B5B000-B5BFFF (base 16) Timberline Mfg Company - 1050 Lyons Lane - Marion IA 52302 - UNITED STATES - - 00-50-C2 (hex) ADI Video Technologies - B5C000-B5CFFF (base 16) ADI Video Technologies - 13a Hamelacha st, - Lod 71520 - ISRAEL - - 00-50-C2 (hex) Plitron Manufacturing Inc. - B5D000-B5DFFF (base 16) Plitron Manufacturing Inc. - 8-601 Magnetic Drive - Toronto Ontario M3J 3J2 - CANADA - - 00-50-C2 (hex) Palgiken Co.,Ltd. - B5E000-B5EFFF (base 16) Palgiken Co.,Ltd. - 2217-2 Hayashicho - Takamatsu Kagawa 761-0301 - JAPAN - - 00-50-C2 (hex) North Bridge Technologies - B5F000-B5FFFF (base 16) North Bridge Technologies - Jean Ave 84 - Centurion Gauteng 0157 - SOUTH AFRICA - - 00-50-C2 (hex) OOO NPF ATIS - B60000-B60FFF (base 16) OOO NPF ATIS - ul. Rangeva, 11-24 - Kovrov Vladimir region 601916 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Nayos LTD - B61000-B61FFF (base 16) Nayos LTD - 7 Golda Meir - Nes Ziona 74036 - ISRAEL - - 00-50-C2 (hex) Measurement Technology NW - B62000-B62FFF (base 16) Measurement Technology NW - 4211 24th Avenue West - Seattle WA 98199 - UNITED STATES - - 00-50-C2 (hex) RO.VE.R. Laboratories S.p.A - B63000-B63FFF (base 16) RO.VE.R. Laboratories S.p.A - Via Parini 2 - Sirmione BS 25019 - ITALY - - 00-50-C2 (hex) FEW Bauer GmbH - B64000-B64FFF (base 16) FEW Bauer GmbH - Silvanastr. 3 - Muenchen Bayern D-81927 - GERMANY - - 00-50-C2 (hex) Peek Traffic Corporation - B65000-B65FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) Deuta-Werke GmbH - B66000-B66FFF (base 16) Deuta-Werke GmbH - Paffrather Str. 140 - Bergisch Gladbach Northrhine Westfalia 51465 - GERMANY - - 00-50-C2 (hex) RC Systems Co. Inc. - B67000-B67FFF (base 16) RC Systems Co. Inc. - 8621 Hwy. 6 - Hitchcock TX 77563 - UNITED STATES - - 00-50-C2 (hex) Electronic Systems Protection, Inc. - B68000-B68FFF (base 16) Electronic Systems Protection, Inc. - 8001 Knightdale Blvd. - Suite 121 - Knightdale NC 27545 - UNITED STATES - - 00-50-C2 (hex) Thetis S.p.A. - B69000-B69FFF (base 16) Thetis S.p.A. - Castello, 2737/f - Venezia VE 30122 - ITALY - - 00-50-C2 (hex) Phytec Messtechnik GmbH - B6A000-B6AFFF (base 16) Phytec Messtechnik GmbH - Robert-koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Phytec Messtechnik GmbH - B6B000-B6BFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Drinelec - B6C000-B6CFFF (base 16) Drinelec - Les Chovets - Barbières 26300 - FRANCE - - 00-50-C2 (hex) Sound Metrics Corp - B6D000-B6DFFF (base 16) Sound Metrics Corp - 15029 Bothell Way NE - Suite 100 - Lake Forest Park WA 98155 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - B6E000-B6EFFF (base 16) - - 00-50-C2 (hex) CT Company - B6F000-B6FFFF (base 16) CT Company - Godovikova 9, Moscow - Moscow RUSSIA 129085 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Nisshin Electronics co.,ltd. - B70000-B70FFF (base 16) Nisshin Electronics co.,ltd. - 2-1-7 Taiho - Atsuta-ku - Nagoya-shi Aichi-ken 4560062 - JAPAN - - 00-50-C2 (hex) Digitale Analoge COMponenten West Electronic Vertriebs GmbH - B71000-B71FFF (base 16) Digitale Analoge COMponenten West Electronic Vertriebs GmbH - Schallbruch 19-21 - Haan NRW 42781 - GERMANY - - 00-50-C2 (hex) Advanced Desktop Systems Ltd - B72000-B72FFF (base 16) Advanced Desktop Systems Ltd - 36 Haldan Road - Highams Park - London E4 9JJ - UNITED KINGDOM - - 00-50-C2 (hex) ARKRAY, Inc. Kyoto Laboratory - B73000-B73FFF (base 16) ARKRAY, Inc. Kyoto Laboratory - Yousuien-nai - Gansuin-cho 59 - Kyoto Kamigyo-ku 602-0008 - JAPAN - - 00-50-C2 (hex) AXED Jakubowski Wojciechowski sp.j. - B74000-B74FFF (base 16) AXED Jakubowski Wojciechowski sp.j. - ul. Fredry 7 - PoznaÅ„ Wielkopolska 61-701 - POLAND - - 00-50-C2 (hex) Blankom - B75000-B75FFF (base 16) Blankom - Hermann-Petersilge-Str. 1 - Bad Blankenburg TH 07422 - GERMANY - - 00-50-C2 (hex) ITF Fröschl GmbH - B76000-B76FFF (base 16) ITF Fröschl GmbH - Hauserbachstraße 9 - Walderbach Bavaria 93194 - GERMANY - - 00-50-C2 (hex) KRISTECH - B77000-B77FFF (base 16) KRISTECH - Porzeczkowa 12 - Ustron Slaskie 43-450 - POLAND - - 00-50-C2 (hex) Folink - B78000-B78FFF (base 16) Folink - 4F 647-39Deungchon-Dong Kangseo-Gu - Seoul 157-840 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) MITSUYA LABORATORIES INC. - B79000-B79FFF (base 16) MITSUYA LABORATORIES INC. - 6-31-18 - KAMIASAO,ASAO-KU - KAWASAKI-CITY KANAGAWA 215-0021 - JAPAN - - 00-50-C2 (hex) Schnoor Industrieelektronik GmbH & Co. KG - B7A000-B7AFFF (base 16) Schnoor Industrieelektronik GmbH & Co. KG - Fehmarnstr. 6 - Buedelsdorf Schleswig-Holstein 24782 - GERMANY - - 00-50-C2 (hex) QUARTECH CORPORATION - B7B000-B7BFFF (base 16) QUARTECH CORPORATION - 15923 ANGELO DRIVE - MACOMB TWP. MI 48042-4050 - UNITED STATES - - 00-50-C2 (hex) Bettini srl - B7C000-B7CFFF (base 16) Bettini srl - Via Cesare Battisti 22 - Cesano Maderno Milano 20031 - ITALY - - 00-50-C2 (hex) ELETECH Srl - B7D000-B7DFFF (base 16) ELETECH Srl - S.P.231 Km 3,500 - BITONTO BARI 70032 - ITALY - - 00-50-C2 (hex) NARETRENDS - B7E000-B7EFFF (base 16) NARETRENDS - #406, Hyunhaetop B/D, 1144-4 - JUNG-DONG, WONMI-GU - BUCHEON GYEONGGI-DO 420-852 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Enatel - B7F000-B7FFFF (base 16) Enatel - 321 Tuam Street - Christchurch 8032 - NEW ZEALAND - - 00-50-C2 (hex) iScreen LLC - B80000-B80FFF (base 16) iScreen LLC - 3181 Poplar Avenue, Ste. 200 - Memphis TN 38111-4717 - UNITED STATES - - 00-50-C2 (hex) GHL Advanced Technolgy GmbH & Co. KG - B81000-B81FFF (base 16) GHL Advanced Technolgy GmbH & Co. KG - Wilhelm-Raabe-Str. 9 - Kaiserslautern Rheinland-Pfalz 67663 - GERMANY - - 00-50-C2 (hex) TANABIKI Inc. - B82000-B82FFF (base 16) TANABIKI Inc. - 1-4-6-305 - Higashi - Kunitachi Tokyo 1860002 - JAPAN - - 00-50-C2 (hex) Advanced Storage Concepts, Inc. - B83000-B83FFF (base 16) Advanced Storage Concepts, Inc. - 2200 Market Street - Suite 810 - Galveston TX 77550 - UNITED STATES - - 00-50-C2 (hex) Innovate Software Solutions Pvt Ltd - B84000-B84FFF (base 16) Innovate Software Solutions Pvt Ltd - #333 ,18th G Main Road,6th Block - Bangalore Karnataka 560095 - INDIA - - 00-50-C2 (hex) SilverNet - B85000-B85FFF (base 16) SilverNet - 16 Cochran Close - Crownhill - Milton Keynes Bucks MK8 0AJ - UNITED KINGDOM - - 00-50-C2 (hex) ASTO - B86000-B86FFF (base 16) ASTO - 22 Mei Hwan Drive - Singapore 568357 - SINGAPORE - - 00-50-C2 (hex) EMAC, Inc. - B87000-B87FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 00-50-C2 (hex) Gigatronik Köln GmbH - B88000-B88FFF (base 16) Gigatronik Köln GmbH - Ruth-Hallensleben-Straße 4 - Köln 50739 - GERMANY - - 00-50-C2 (hex) ENTEC Electric & Electronic Co., LTD. - B89000-B89FFF (base 16) ENTEC Electric & Electronic Co., LTD. - 78-2 Buncheon-ri, Bongdam-eup - Hwaseong-city Gyungki-do 445-894 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) MicroPoise - B8A000-B8AFFF (base 16) MicroPoise - 1624 Englewood Ave - Akron Ohio 44305 - UNITED STATES - - 00-50-C2 (hex) FBB - B8B000-B8BFFF (base 16) FBB - Hei en Boeicopseweg 118 - Hei en Boeicop 4126RL - NETHERLANDS - - 00-50-C2 (hex) Keith & Koep GmbH - B8C000-B8CFFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) CEMSI - B8D000-B8DFFF (base 16) CEMSI - 780 Keezletown Road - Suite 102 - Weyers Cave VA 24486 - UNITED STATES - - 00-50-C2 (hex) WAC (Israel) Ltd. - B8E000-B8EFFF (base 16) WAC (Israel) Ltd. - Shefa Tal 12 - Tel-Aviv 61070 - ISRAEL - - 00-50-C2 (hex) Gentec - B8F000-B8FFFF (base 16) Gentec - 2625 Dalton - Quebec G1P 3S9 - CANADA - - 00-50-C2 (hex) NAONWORKS Co., Ltd - B90000-B90FFF (base 16) NAONWORKS Co., Ltd - Rm710, Byucksan Digitalvalley 3, - 212-13, Guro-Dong, Guro-Gu - Seoul 152-775 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Finnet-Service Ltd. - B91000-B91FFF (base 16) Finnet-Service Ltd. - Serebrianicheskyi per., b.2/5 str. 4. - Moscow 109028 - RUSSIAN FEDERATION - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - B92000-B92FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park Torch Hi-tech Development Zone, - Xiao Dong Shan, - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) EMC PARTNER AG - B93000-B93FFF (base 16) EMC PARTNER AG - Baselstrasse 160 - Laufen Baselland 4242 - SWITZERLAND - - 00-50-C2 (hex) Tritech International Ltd - B94000-B94FFF (base 16) Tritech International Ltd - Morecambe Road - Ulverston Cumbria LA12 0BH - UNITED KINGDOM - - 00-50-C2 (hex) Rx Monitoring Services - B95000-B95FFF (base 16) Rx Monitoring Services - 22A Eastman Ave - Bedford NH 03110 - UNITED STATES - - 00-50-C2 (hex) Onix Electronic Systems Inc - B96000-B96FFF (base 16) Onix Electronic Systems Inc - 205 Travelers Rest Blvd - Summerville SC 29485 - UNITED STATES - - 00-50-C2 (hex) ikerlan - B97000-B97FFF (base 16) ikerlan - jm arizmendiarrieta, 2 - mondragon guipuzcoa 20500 - SPAIN - - 00-50-C2 (hex) Southwest Research Institute - B98000-B98FFF (base 16) Southwest Research Institute - 6220 Culebra Road - San Antonio TX 78238 - UNITED STATES - - 00-50-C2 (hex) Greenlight Innovation Corp. - B99000-B99FFF (base 16) Greenlight Innovation Corp. - Unit 104A - 3430 Brighton Avenue - Burnaby, B.C. V5A 3H4 - CANADA - - 00-50-C2 (hex) Talo, NV Inc - B9A000-B9AFFF (base 16) Talo, NV Inc - 1930 Village Center Cir #3 - 454 - Las Vegas Nevada 89134 - UNITED STATES - - 00-50-C2 (hex) Telventy Energia S.A. - B9B000-B9BFFF (base 16) Telventy Energia S.A. - Valgrande, 6 - Alcobendas Madrid 28108 - SPAIN - - 00-50-C2 (hex) Dave srl - B9C000-B9CFFF (base 16) Dave srl - Via Talponedo 29 - Porcia PN A-33080 - ITALY - - 00-50-C2 (hex) W. Vershoven GmbH - B9D000-B9DFFF (base 16) W. Vershoven GmbH - Riedinger Strasse 10 - Essen 45141 - GERMANY - - 00-50-C2 (hex) Saia-Burgess Controls AG - B9E000-B9EFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) AUDIOSCOPE 2K SRL - B9F000-B9FFFF (base 16) AUDIOSCOPE 2K SRL - 31, VIA CAIANELLO - ROMA 00177 - ITALY - - 00-50-C2 (hex) txtr GmbH - BA0000-BA0FFF (base 16) txtr GmbH - Rosenthaler Str. 13 - Berlin 10119 - GERMANY - - 00-50-C2 (hex) Transtechnik GmbH & Co.KG - BA1000-BA1FFF (base 16) Transtechnik GmbH & Co.KG - Ohmstraße 1 - Holzkirchen Bavaria 83607 - GERMANY - - 00-50-C2 (hex) Logical Tools s.r.l. - BA2000-BA2FFF (base 16) Logical Tools s.r.l. - Via Giorgio Scalia, 46 - Rome 00136 - ITALY - - 00-50-C2 (hex) DSP DESIGN LTD - BA3000-BA3FFF (base 16) DSP DESIGN LTD - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) CUSTOS MOBILE S.L. - BA4000-BA4FFF (base 16) CUSTOS MOBILE S.L. - SOCIEDAD DE CONDUENOS 21 - ALCALA DE HENARES MADRID 28804 - SPAIN - - 00-50-C2 (hex) InterCel Pty Ltd - BA5000-BA5FFF (base 16) InterCel Pty Ltd - 33 Glenvale Crescent - Mulgrave Victoria 3170 - AUSTRALIA - - 00-50-C2 (hex) Jomitek - BA6000-BA6FFF (base 16) Jomitek - Skovlytoften 22 - Holte DK-2840 - DENMARK - - 00-50-C2 (hex) RaumComputer Entwicklungs- und Vertriebs GmbH - BA7000-BA7FFF (base 16) RaumComputer Entwicklungs- und Vertriebs GmbH - Augartenstraße 1 - Karlsruhe Baden-Württemberg 76137 - GERMANY - - 00-50-C2 (hex) Peek Traffic Corporation - BA8000-BA8FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) SISS Technology Inc. - BA9000-BA9FFF (base 16) SISS Technology Inc. - 601 Ace-Technotower, 684-1 Deungchon-dong, Gangseo-gu - Seoul 157-030 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) NetworkFX Communications, LLC - BAA000-BAAFFF (base 16) NetworkFX Communications, LLC - 95-1036 Auina St. - Mililani HI 96789 - UNITED STATES - - 00-50-C2 (hex) iDeal Teknoloji Bilisim Cozumleri A.S. - BAB000-BABFFF (base 16) iDeal Teknoloji Bilisim Cozumleri A.S. - Cumhuriyet Cad. Yeni Parseller Sok. B Blok Giris Kat KAVACIK - ISTANBUL 34805 - TURKEY - - 00-50-C2 (hex) VITECO VNPT JSC - BAC000-BACFFF (base 16) VITECO VNPT JSC - No35, Lane 61, lac Trung Streets - Ha Noi 10000 - VIETNAM - - 00-50-C2 (hex) Prediktor AS - BAD000-BADFFF (base 16) Prediktor AS - Habornveien 48B - Gamle Fredrikstad . 1630 - NORWAY - - 00-50-C2 (hex) Fiber Connections Inc. - BAE000-BAEFFF (base 16) Fiber Connections Inc. - 5878 Highway # 9 - Schomberg ON L0G 1T0 - CANADA - - 00-50-C2 (hex) MangoDSP - BAF000-BAFFFF (base 16) MangoDSP - Hartom 8 - Jerusalem Israel 45116 - ISRAEL - - 00-50-C2 (hex) Gainbrain - BB0000-BB0FFF (base 16) Gainbrain - Auweg 32 - Senden 89250 - GERMANY - - 00-50-C2 (hex) Pro4tech - BB1000-BB1FFF (base 16) Pro4tech - Kochav Yokneam bldg 5 floor - Yokneam Illit 20692 - ISRAEL - - 00-50-C2 (hex) St Michael Strategies Inc - BB2000-BB2FFF (base 16) St Michael Strategies Inc - 701 Salaberry suite 201 - Chambly Quebec J3L 1R2 - CANADA - - 00-50-C2 (hex) ClimateWell AB (publ) - BB3000-BB3FFF (base 16) ClimateWell AB (publ) - Instrumentvagen 20 - Hagersten 12653 - SWEDEN - - 00-50-C2 (hex) JSC Electrical Equipment Factory - BB4000-BB4FFF (base 16) JSC Electrical Equipment Factory - Otradnaya str, 6 - Moscow 129626 - RUSSIAN FEDERATION - - 00-50-C2 (hex) MROAD INFORMATION SYSTEM - BB5000-BB5FFF (base 16) MROAD INFORMATION SYSTEM - 3F, SUNGDO BD. 689-1 - Bokjeong-dong,Sujeong-gu - Seongnam-si GYeongi-do 461-200 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Quarch Technology Ltd - BB6000-BB6FFF (base 16) Quarch Technology Ltd - 4C Dalfaber Industrial Estate - Aviemore Inverness-Shire PH22 1ST - UNITED KINGDOM - - 00-50-C2 (hex) General Dynamics C4 Systems - BB7000-BB7FFF (base 16) General Dynamics C4 Systems - 8220 East Roosevelt St. - MD: R1122 - Scottsdale Arizona 85257 - UNITED STATES - - 00-50-C2 (hex) MoeTronix - BB8000-BB8FFF (base 16) MoeTronix - 3342 Canary Trl - Duluth GA 30096 - UNITED STATES - - 00-50-C2 (hex) Toptech Systems, Inc. - BB9000-BB9FFF (base 16) Toptech Systems, Inc. - 280 Hunt Park Cove - Longwood FL 32750 - UNITED STATES - - 00-50-C2 (hex) Systemteq Limited - BBA000-BBAFFF (base 16) Systemteq Limited - Unit B, Lynwood House - Sandown Road - Watford Hertfordshire WD24 7UF - UNITED KINGDOM - - 00-50-C2 (hex) GHL Systems Berhad - BBB000-BBBFFF (base 16) GHL Systems Berhad - L5-E-7B, Enterprise 4 - Technology Park Malaysia - Bukit Jalil Kuala Lumpur 57000 - MALAYSIA - - 00-50-C2 (hex) ImpactSystems - BBC000-BBCFFF (base 16) ImpactSystems - 15-10-206 Satsukigaoka-Minami - Suita Osaka 565-0832 - JAPAN - - 00-50-C2 (hex) ITS Telecom - BBD000-BBDFFF (base 16) ITS Telecom - 29 Hametzuda st. - Azur 58001 - ISRAEL - - 00-50-C2 (hex) Onlinepizza Norden AB - BBE000-BBEFFF (base 16) Onlinepizza Norden AB - Strandbergsgatan 61 - Stockholm 112 51 - SWEDEN - - 00-50-C2 (hex) Phytec Messtechnik GmbH - BBF000-BBFFFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Galaxia Electronics - BC0000-BC0FFF (base 16) Galaxia Electronics - #1307 Tech Center, SK Technopark - 190-1 Sangdewondong, Jungwongu - Seongnamsi Gyeonggido 462-721 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Sentec Ltd - BC1000-BC1FFF (base 16) Sentec Ltd - Brunswick House - 61-69 Newmarket Rd - Cambridge Cambridgeshire CB5 8EG - UNITED KINGDOM - - 00-50-C2 (hex) XSLENT Energy Technologies LLC - BC2000-BC2FFF (base 16) XSLENT Energy Technologies LLC - 7428 Redwood Blvd Suite 102 - Novato CA 94945 - UNITED STATES - - 00-50-C2 (hex) Phytec Messtechnik GmbH - BC3000-BC3FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Strasse 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Wheatstone Corporation - BC4000-BC4FFF (base 16) Wheatstone Corporation - 600 Industrial Drive - New Nern NC 28562 - UNITED STATES - - 00-50-C2 (hex) Toptechnology SRL - BC5000-BC5FFF (base 16) Toptechnology SRL - Guise 1774 2B - Ciudad de Buenos Aires Capital Federal C1425DPD - ARGENTINA - - 00-50-C2 (hex) MireroTack - BC6000-BC6FFF (base 16) MireroTack - dodang-dong,wonmi-gu, bucheon-si, gyeonggi-do - A-1011 DAEWOO TECHNO PARK 187-7 - dodang-dong,wonmi-gu bucheon-si/gyeonggi-do 420-806 - KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF - - 00-50-C2 (hex) PTS GmbH - BC7000-BC7FFF (base 16) PTS GmbH - Gottfried-Schenker-Str. 2 - Lichtenau Saxony 09244 - GERMANY - - 00-50-C2 (hex) AGWTech Ltd - BC8000-BC8FFF (base 16) AGWTech Ltd - 22 Nederdale Close - Yarm Stockton-on-Tees TS15 9UE - UNITED KINGDOM - - 00-50-C2 (hex) Nextmove Technologies - BC9000-BC9FFF (base 16) Nextmove Technologies - 38 Taylor Drive - Brookline New Hampshire 03033 - UNITED STATES - - 00-50-C2 (hex) Aitecsystem Co.,Ltd. - BCA000-BCAFFF (base 16) Aitecsystem Co.,Ltd. - 1532,Shinohara-Cho, - Kouhoku-Ku, - Yokohama Kanagawa 222-0026 - JAPAN - - 00-50-C2 (hex) ARTEIXO TELECOM - BCB000-BCBFFF (base 16) ARTEIXO TELECOM - P.E. Penapurreira - As Pontes A Coruña 15320 - SPAIN - - 00-50-C2 (hex) VVDN TECHNOLOGIES PVT. LTD. - BCC000-BCCFFF (base 16) VVDN TECHNOLOGIES PVT. LTD. - 1241/36,ATUL KATARIA CHOWK - OPP. PAYAL CINEMA - GURGAON HARYANA 122001 - INDIA - - 00-50-C2 (hex) Highlight Parking Systems Ltd - BCD000-BCDFFF (base 16) Highlight Parking Systems Ltd - 14 Ullathorne Road - London SW16 1SN - UNITED KINGDOM - - 00-50-C2 (hex) TV Portal Co., Ltd. - BCE000-BCEFFF (base 16) TV Portal Co., Ltd. - 5F TATENO, 6-4-13 Kiba Koto - Tokyo 135-0042 - JAPAN - - 00-50-C2 (hex) Epiko, elektronski sistemi d.o.o. - BCF000-BCFFFF (base 16) Epiko, elektronski sistemi d.o.o. - Izanska cesta 146a - Ljubljana Slovenija 1108 - SLOVENIA - - 00-50-C2 (hex) EDC wifi - BD0000-BD0FFF (base 16) EDC wifi - Bao An Nan Lu - ShenZhen GuangDong 518001 - CHINA - - 00-50-C2 (hex) Ariem Technologies Pvt Ltd - BD1000-BD1FFF (base 16) Ariem Technologies Pvt Ltd - 201/202, Trump Towers - 5/2, Eagle Street, Langford Town - Bangalore Karnataka 560025 - INDIA - - 00-50-C2 (hex) Percello Ltd. - BD2000-BD2FFF (base 16) Percello Ltd. - 14 Hatidhar St. - Raanana 43650 - ISRAEL - - 00-50-C2 (hex) Postjet Systems Ltd - BD3000-BD3FFF (base 16) Postjet Systems Ltd - 6B Beechwood - Chineham Business Park, Chineham - Basingstoke Hants RG24 8WA - UNITED KINGDOM - - 00-50-C2 (hex) Global Security Devices - BD4000-BD4FFF (base 16) Global Security Devices - S12-S14 Synergy Centre - ITT Dublin, Tallaght - Dublin D24 - IRELAND - - 00-50-C2 (hex) RF-Embedded GmbH - BD5000-BD5FFF (base 16) RF-Embedded GmbH - Salzburger Straße 60 - Stephanskirchen Bayern 83071 - GERMANY - - 00-50-C2 (hex) BG Systems, Inc. - BD6000-BD6FFF (base 16) BG Systems, Inc. - 931 Commercial St. - Palo Alto CA 94303 - UNITED STATES - - 00-50-C2 (hex) SLAT - BD7000-BD7FFF (base 16) SLAT - 11 Rue Jean-Elysée DUPUY - Champagne au Mont d'Or Rhône 69543 - FRANCE - - 00-50-C2 (hex) b.a.b-technologie gmbh - BD8000-BD8FFF (base 16) b.a.b-technologie gmbh - Rosemeyerstraße 14 - Dortmund NRW 44139 - GERMANY - - 00-50-C2 (hex) AMS Controls, Inc. - BD9000-BD9FFF (base 16) AMS Controls, Inc. - 12180 Prichard Farm Road - Maryland Heights MO 63043 - UNITED STATES - - 00-50-C2 (hex) Digital Lumens - BDA000-BDAFFF (base 16) Digital Lumens - 129 Portland Street - 4th Floor - Boston Massachusetts 02114 - UNITED STATES - - 00-50-C2 (hex) GasTOPS Ltd. - BDB000-BDBFFF (base 16) GasTOPS Ltd. - 1011 Polytek Street - Ottawa Ontario K1J9J3 - CANADA - - 00-50-C2 (hex) SS Systems LLC - BDC000-BDCFFF (base 16) SS Systems LLC - 104 Kurtner Ct - Morrisville NC 27560 - UNITED STATES - - 00-50-C2 (hex) Evo-Teh d.o.o. - BDE000-BDEFFF (base 16) Evo-Teh d.o.o. - Mariborska cesta 3 - SI-2370 Dravograd - Dravograd Slovenija SI2370 - SLOVENIA - - 00-50-C2 (hex) Euro-Konsult Sp. z o.o. - BDF000-BDFFFF (base 16) Euro-Konsult Sp. z o.o. - Swidnicka 19/315 - Wroclaw dolnoslaskie 50-066 - POLAND - - 00-50-C2 (hex) Phaedrus Limited - BE0000-BE0FFF (base 16) Phaedrus Limited - 5 Marsh House Mill - Brussels Road, - Darwen Lancashire BB3 3JJ - UNITED KINGDOM - - 00-50-C2 (hex) TATTILE SRL - BE1000-BE1FFF (base 16) TATTILE SRL - VIA DONIZETTI 1/3/5 - MAIRANO BRESCIA 25030 - ITALY - - 00-50-C2 (hex) Convergent Bioscience Ltd. - BE2000-BE2FFF (base 16) Convergent Bioscience Ltd. - 27 Coronet Road - Toronto ON M8Z 2L8 - CANADA - - 00-50-C2 (hex) Jiskoot Ltd - BE3000-BE3FFF (base 16) Jiskoot Ltd - 85 Goods Station Road - Tunbridge Wells Kent TN1 2DJ - UNITED KINGDOM - - 00-50-C2 (hex) Grupo Epelsa S.L. - BE4000-BE4FFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) RF Code, Inc - BE5000-BE5FFF (base 16) RF Code, Inc - 9229 Waterford Centre - Suite 500 - Austin TX 78758 - UNITED STATES - - 00-50-C2 (hex) Docobo Ltd - BE6000-BE6FFF (base 16) Docobo Ltd - The Old Granary - 21 High Street - Bookham Surrey KT23 4AA - UNITED KINGDOM - - 00-50-C2 (hex) Genetec Inc. - BE7000-BE7FFF (base 16) Genetec Inc. - 2280 Alfred-Nobel Blvd., Suite 400 - Saint-Laurent Quebec H4S 2A4 - CANADA - - 00-50-C2 (hex) VEHICLE TESTING EQUIPMENT, S.L. - BE8000-BE8FFF (base 16) VEHICLE TESTING EQUIPMENT, S.L. - C/ Conca de Barberá  19 - Castellar del Vallès Barcelona 08211 - SPAIN - - 00-50-C2 (hex) ZUCCHETTI SPA - BE9000-BE9FFF (base 16) ZUCCHETTI SPA - Via Adriatica, 282 - Campoformido UDINE 33030 - ITALY - - 00-50-C2 (hex) Daeyoung inc. - BEA000-BEAFFF (base 16) Daeyoung inc. - 596-1, Baegun-dong, Nam-gu - Gwang-Ju 503-300 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Peek Traffic Corporation - BEB000-BEBFFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Fl 34221 - UNITED STATES - - 00-50-C2 (hex) DRS Laruel Technologies - BEC000-BECFFF (base 16) DRS Laruel Technologies - 246 Airport Road - Johnstown Pa 15904 - UNITED STATES - - 00-50-C2 (hex) Touch Revolution Inc. - BED000-BEDFFF (base 16) Touch Revolution Inc. - 101 California St. - Suite 4225 - San Francisco CA 94065 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - BEE000-BEEFFF (base 16) - - 00-50-C2 (hex) SOCIEDAD IBERICA DE CONSTRUCCIONES ELECTRICAS, S.A. (SICE) - BEF000-BEFFFF (base 16) SOCIEDAD IBERICA DE CONSTRUCCIONES ELECTRICAS, S.A. (SICE) - C/Sepulveda, 6 - Poligono Industrial de Alcobendas - ALCOBENDAS MADRID 28108 - SPAIN - - 00-50-C2 (hex) AIM - BF0000-BF0FFF (base 16) AIM - 21, avenue de la Plaine Fleurie - MEYLAN 38240 - FRANCE - - 00-50-C2 (hex) Amatic Industries GmbH - BF1000-BF1FFF (base 16) Amatic Industries GmbH - Traunsteinstrasse 12 - Rutzenmoos Upper Austria 4845 - AUSTRIA - - 00-50-C2 (hex) Saia-Burgess Controls AG - BF2000-BF2FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Wanco Inc. - BF3000-BF3FFF (base 16) Wanco Inc. - 5870 Tennyson St. - Arvada CO 80003 - UNITED STATES - - 00-50-C2 (hex) Monarch Innovative Technologies Pvt Ltd - BF4000-BF4FFF (base 16) Monarch Innovative Technologies Pvt Ltd - Monarch House, Master Mind II, - Royal Palms, Aarey Colony, Goregaon(E), - Mumbai Maharashtra 400065 - INDIA - - 00-50-C2 (hex) AILES ELECTRONICS CO., LTD. - BF5000-BF5FFF (base 16) AILES ELECTRONICS CO., LTD. - 840 ASSO - KAINAN CITY WAKAYAMA 642-0015 - JAPAN - - 00-50-C2 (hex) NOLAM EMBEDDED SYSTEMS - BF6000-BF6FFF (base 16) NOLAM EMBEDDED SYSTEMS - 8 Rue d'estienne d'orves - CRETEIL 94000 - FRANCE - - 00-50-C2 (hex) Phytec Messtechnik GmbH - BF7000-BF7FFF (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 00-50-C2 (hex) Crtiical Link - BF8000-BF8FFF (base 16) Crtiical Link - 6712 Brooklawn Parkway - Syracuse NY 13211 - UNITED STATES - - 00-50-C2 (hex) Vitel Net - BF9000-BF9FFF (base 16) Vitel Net - 1951 Kidwell Drive - Suite 200 - Vienna VA 22182 - UNITED STATES - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - BFA000-BFAFFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu street, district 1, - Bucharest 014186 - ROMANIA - - 00-50-C2 (hex) ECS Srl - BFB000-BFBFFF (base 16) ECS Srl - Via del Candel 55/d - Belluno 32100 - ITALY - - 00-50-C2 (hex) Altronix Corporation - BFC000-BFCFFF (base 16) Altronix Corporation - 140 58th street - Brooklyn NY 11220 - UNITED STATES - - 00-50-C2 (hex) Ernemann Cine Tec GmbH - BFD000-BFDFFF (base 16) Ernemann Cine Tec GmbH - Mecklenburger Str. 32 - 36 - Kiel Schleswig Holstein 24106 - GERMANY - - 00-50-C2 (hex) Ingeteam Paneles S.A.U. - BFE000-BFEFFF (base 16) Ingeteam Paneles S.A.U. - Pol Ind El Juncarillo, nave 1 - Sesma Navarra 31293 - SPAIN - - 00-50-C2 (hex) I.S.A. S.r.l. - BFF000-BFFFFF (base 16) I.S.A. S.r.l. - Via Prati Bassi ,22 - TAINO VA 21020 - ITALY - - 00-50-C2 (hex) ACD Elektronik GmbH - C00000-C00FFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten BW 88480 - GERMANY - - 00-50-C2 (hex) QUERCUS TECHNOLOGIES, S.L. - C01000-C01FFF (base 16) QUERCUS TECHNOLOGIES, S.L. - Antoni Isern 4 baixos - Reus Tarragona 43205 - SPAIN - - 00-50-C2 (hex) Hanning Elektro-Werke GmbH & Co. KG - C02000-C02FFF (base 16) Hanning Elektro-Werke GmbH & Co. KG - Holter Strasse 90 - Oerlinghausen NRW 33813 - GERMANY - - 00-50-C2 (hex) Volumatic Limited. - C03000-C03FFF (base 16) Volumatic Limited. - Taurus House - Endemere Road - Coventry West Midlands CV6 5PY - UNITED KINGDOM - - 00-50-C2 (hex) SoGEME - C04000-C04FFF (base 16) SoGEME - 1 rue Jules Michelet - BEAUVAIS 60000 - FRANCE - - 00-50-C2 (hex) Doppler Systems LLC - C05000-C05FFF (base 16) Doppler Systems LLC - 37202 N Bloody Basin Road - P.O. Box 2780 - Carefree Arizona 85377 - UNITED STATES - - 00-50-C2 (hex) ANALOG WAY - C06000-C06FFF (base 16) ANALOG WAY - 2 rue Georges Besse - Antony 92160 - FRANCE - - 00-50-C2 (hex) CIO Informatique Industrielle - C07000-C07FFF (base 16) CIO Informatique Industrielle - 1 Rue de la Presse - BP 710 - Cedex 9 - SAINT-ETIENNE LOIRE 42950 - FRANCE - - 00-50-C2 (hex) juiceboss - C08000-C08FFF (base 16) juiceboss - 1946 Pescadero Creek Road - Pescadero CA 94060 - UNITED STATES - - 00-50-C2 (hex) Globe Wireless - C09000-C09FFF (base 16) Globe Wireless - 1571 Robert J Conlan Blvd - Palm Bay Florida 32905 - UNITED STATES - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - C0A000-C0AFFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park Torch Hi-tech Development Zone - Xiao Dong Shan, Xiamen - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) ProSourcing GmbH - C0B000-C0BFFF (base 16) ProSourcing GmbH - Dorfmatt 1 - Muntelier Freiburg 3286 - SWITZERLAND - - 00-50-C2 (hex) Altierre - C0C000-C0CFFF (base 16) Altierre - 1980 Concourse Drive - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) Fr. SauterAG - C0D000-C0DFFF (base 16) Fr. SauterAG - Im Surinam 55 - Basel BS 4016 - SWITZERLAND - - 00-50-C2 (hex) AVItronic GmbH - C0E000-C0EFFF (base 16) AVItronic GmbH - Kreischaer Str. 1a - Bannewitz Sachsen 01728 - GERMANY - - 00-50-C2 (hex) DYCEC, S.A. - C0F000-C0FFFF (base 16) DYCEC, S.A. - Torres Quevedo, 1-P.T.M. - Tres Cantos Madrid 28760 - SPAIN - - 00-50-C2 (hex) Keith & Koep GmbH - C10000-C10FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) ART Antriebs- und Regeltechnik GmbH - C11000-C11FFF (base 16) ART Antriebs- und Regeltechnik GmbH - 2.Industriestrasse 8 - Hockenheim 68766 - GERMANY - - 00-50-C2 (hex) OKI DENKI BOHSAI CO.,LTD. - C12000-C12FFF (base 16) OKI DENKI BOHSAI CO.,LTD. - Oomori-Hinoshita 9-1 - Fukushima-City Fukushima 960-1101 - JAPAN - - 00-50-C2 (hex) Dantec Dynamics A/S - C13000-C13FFF (base 16) Dantec Dynamics A/S - Tonsbakken 16-18 - Skovlunde 2740 - DENMARK - - 00-50-C2 (hex) Spectronix Corporation - C14000-C14FFF (base 16) Spectronix Corporation - Kunisato-bldg 5F,8-8,Eidai-cho - Ibaraki Osaka 567-0816 - JAPAN - - 00-50-C2 (hex) INO - Institut National d'Optique - C15000-C15FFF (base 16) INO - Institut National d'Optique - 2740, Einstein Street - Quebec G1P 4S4 - CANADA - - 00-50-C2 (hex) OMICRON electronics GmbH - C16000-C16FFF (base 16) OMICRON electronics GmbH - Oberes Ried 1 - Klaus 6833 - AUSTRIA - - 00-50-C2 (hex) Axis-Shield PoC AS - C17000-C17FFF (base 16) Axis-Shield PoC AS - KjelsÃ¥sveien 161 - P O Box 6863 Rodeløkka - Oslo 0504 - NORWAY - - 00-50-C2 (hex) Linuxstamp Designs, LLC - C18000-C18FFF (base 16) Linuxstamp Designs, LLC - 3807 S Jewel Dr - Flagstaff AZ 86001 - UNITED STATES - - 00-50-C2 (hex) Ibercomp SA - C19000-C19FFF (base 16) Ibercomp SA - C/Lluis Alemany i Pujol 4 - Palma de Mallorca Baleares 07010 - SPAIN - - 00-50-C2 (hex) SAM Co., Ltd. - C1A000-C1AFFF (base 16) SAM Co., Ltd. - Meguro F2 Building - 1-8-8 Nakameguro - Meguro-ku Tokyo 153-0061 - JAPAN - - 00-50-C2 (hex) Graesslin GmbH - C1B000-C1BFFF (base 16) Graesslin GmbH - Bundesstraße 36 - St. Georgen Baden-Württemberg 78112 - GERMANY - - 00-50-C2 (hex) Becton Dickinson - C1C000-C1CFFF (base 16) Becton Dickinson - 7 Loveton Circle - MC688 - Sparks MD 21152 - UNITED STATES - - 00-50-C2 (hex) Powerbase Energy Systems Inc. - C1D000-C1DFFF (base 16) Powerbase Energy Systems Inc. - 150 Rosamond Street - Carleton Place Ontario K7C 1V2 - CANADA - - 00-50-C2 (hex) Peperoni-Light - C1E000-C1EFFF (base 16) Peperoni-Light - Wiesenrautenstieg 42 - Hamburg 22607 - GERMANY - - 00-50-C2 (hex) Specialist Electronics Services Ltd - C1F000-C1FFFF (base 16) Specialist Electronics Services Ltd - Craven Court - Stanhope Road - Camberley Surrey GU15 3BS - UNITED KINGDOM - - 00-50-C2 (hex) SRC Computers, LLC - C20000-C20FFF (base 16) SRC Computers, LLC - 4240 N. Nevada Avenue - Colorado Springs CO 80907 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - C21000-C21FFF (base 16) - - 00-50-C2 (hex) Audient Ltd - C22000-C22FFF (base 16) Audient Ltd - 1 Stable Court - Herriard Park - Herriard Hampshire RG25 2PL - UNITED KINGDOM - - 00-50-C2 (hex) Vidicon LLC - C23000-C23FFF (base 16) Vidicon LLC - 300 Harvestore Drive - DeKalb IL 60115 - UNITED STATES - - 00-50-C2 (hex) Qualnetics Corporation - C24000-C24FFF (base 16) Qualnetics Corporation - 2183 Alpine Way - Bellingham WA 98226 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - C25000-C25FFF (base 16) - - 00-50-C2 (hex) Austco Communication Systems Pty Ltd - C26000-C26FFF (base 16) Austco Communication Systems Pty Ltd - 40 O'Malley Street - Osborne Park Western Australia 6017 - AUSTRALIA - - 00-50-C2 (hex) Qtechnology A/S - C27000-C27FFF (base 16) Qtechnology A/S - Valby Langgade 142, 1. - Valby DK 2500 - DENMARK - - 00-50-C2 (hex) ELREHA GmbH - C28000-C28FFF (base 16) ELREHA GmbH - Schwetzinger Straße 104 - Hockenheim Baden-Württemberg 68766 - GERMANY - - 00-50-C2 (hex) Newtel Engineering S.r.l. - C29000-C29FFF (base 16) Newtel Engineering S.r.l. - via Strecciola, 7 - Malgrate LC 23864 - ITALY - - 00-50-C2 (hex) RealTime Systems Ltd - C2A000-C2AFFF (base 16) RealTime Systems Ltd - A-49 Okhla Industrial area Phase -1 - New Delhi Delhi 110020 - INDIA - - 00-50-C2 (hex) Z-App Systems, Inc. - C2B000-C2BFFF (base 16) Z-App Systems, Inc. - 1732 N. First St. - Suite #150 - San Jose CA 95112 - UNITED STATES - - 00-50-C2 (hex) bach-messtechnik gmbh - C2C000-C2CFFF (base 16) bach-messtechnik gmbh - Gotzweg 103 - Monchengladbach 41238 - GERMANY - - 00-50-C2 (hex) Digitale Analoge COMponenten West Electronic Vertriebs GmbH - C2D000-C2DFFF (base 16) Digitale Analoge COMponenten West Electronic Vertriebs GmbH - Schallbruch 19-21 - Haan NRW 42781 - GERMANY - - 00-50-C2 (hex) DISMUNTEL SAL - C2E000-C2EFFF (base 16) DISMUNTEL SAL - Pol ind cotes - c/aiguaders, 15 - Algemesi Valencia 46680 - SPAIN - - 00-50-C2 (hex) REFLEX CES - C2F000-C2FFFF (base 16) REFLEX CES - 2 RUE DU GEVAUDAN - SILIC 1743-LISSES - EVRY 91047 - FRANCE - - 00-50-C2 (hex) Wagner Group GmbH - C30000-C30FFF (base 16) Wagner Group GmbH - Schleswigstrasse 1-5 - Langenhagen 30853 - GERMANY - - 00-50-C2 (hex) 4D Technology Corporation - C31000-C31FFF (base 16) 4D Technology Corporation - 3280 E. Hemisphere Loop, - Suite 146 - Tucson Arizona 85706 - UNITED STATES - - 00-50-C2 (hex) Procon Electronics - C32000-C32FFF (base 16) Procon Electronics - PO Box 164 - Seven Hills - Sydney NSW 1730 - AUSTRALIA - - 00-50-C2 (hex) Kyuhen - C34000-C34FFF (base 16) Kyuhen - hanamigahama2-1-1 - fukutsu fukuoka 811-3216 - JAPAN - - 00-50-C2 (hex) Insitu, Inc. - C35000-C35FFF (base 16) Insitu, Inc. - 118 E Columbia River Way - Bingen WA 98605 - UNITED STATES - - 00-50-C2 (hex) SET GmbH - C36000-C36FFF (base 16) SET GmbH - August-Braun-Str. 1 - Wangen i.A. 88239 - GERMANY - - 00-50-C2 (hex) B.E.A.R. Solutions (Australasia) Pty, Ltd - C37000-C37FFF (base 16) B.E.A.R. Solutions (Australasia) Pty, Ltd - Unit 226 - 14 Lexington Drive - Bella Vista NSW - AUSTRALIA - - 00-50-C2 (hex) Computer Automation Technology Inc - C38000-C38FFF (base 16) Computer Automation Technology Inc - 3397 NW 23 Court - Boca Raton Florida 33431 - UNITED STATES - - 00-50-C2 (hex) SECAD SA - C39000-C39FFF (base 16) SECAD SA - Zac des Pellants - St Martin du Fresne 01430 - FRANCE - - 00-50-C2 (hex) Sicon s.r.l. - C3A000-C3AFFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) ELEKTRO-AUTOMATIK GmbH & Co. KG - C3B000-C3BFFF (base 16) ELEKTRO-AUTOMATIK GmbH & Co. KG - Helmholtzstraße 31-33 - Viersen NRW 41747 - GERMANY - - 00-50-C2 (hex) ELSIST S.r.l. - C3C000-C3CFFF (base 16) ELSIST S.r.l. - Via Giacomo Brodolini, 15 - CASALE MONFERRATO 15033 - ITALY - - 00-50-C2 (hex) PLA ELECTRO APPLIANCES PVT. LTD. - C3D000-C3DFFF (base 16) PLA ELECTRO APPLIANCES PVT. LTD. - THAKOR IND. ESTATE - KURLA - KIROL ROAD, VIDYAVIHAR (WEST) - MUMBAI MAHARASHTRA 400086 - INDIA - - 00-50-C2 (hex) Sysacom - C3E000-C3EFFF (base 16) Sysacom - 324 St-Paul - Le Gardeur Québec J5Z4H9 - CANADA - - 00-50-C2 (hex) ANXeBusiness Corporation - C3F000-C3FFFF (base 16) ANXeBusiness Corporation - 4106 Reas Lane - Suite 3 - New Albany IN 47150 - UNITED STATES - - 00-50-C2 (hex) BAE Systems Bofors AB - C40000-C40FFF (base 16) BAE Systems Bofors AB - SE-69180 Karlskoga - Karlskoga Värmland 69180 - SWEDEN - - 00-50-C2 (hex) COMPRION GmbH - C41000-C41FFF (base 16) COMPRION GmbH - Technologiepark 25 - Paderborn 33100 - GERMANY - - 00-50-C2 (hex) Saia-Burgess Controls AG - C42000-C42FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Cammegh Limited - C43000-C43FFF (base 16) Cammegh Limited - Old Surrenden Manor - Bethersden Kent TN263DL - UNITED KINGDOM - - 00-50-C2 (hex) Beijing Zhongherongzhi Elec.&Tech.Co.,Ltd. - C44000-C44FFF (base 16) Beijing Zhongherongzhi Elec.&Tech.Co.,Ltd. - Rm.605 Astronautic Exactitude Plaza No.30 South Haidian Rd. - Beijing 100080 - CHINA - - 00-50-C2 (hex) Galvamat & Unican Technologies SA - C45000-C45FFF (base 16) Galvamat & Unican Technologies SA - Alexis-Marie-Piaget 71-73 - La Chaux-de-Fonds NE 2300 - SWITZERLAND - - 00-50-C2 (hex) QNE GmbH & Co. KG - C46000-C46FFF (base 16) QNE GmbH & Co. KG - Alexanderstraße 124 - Oldenburg Niedersachsen 26121 - GERMANY - - 00-50-C2 (hex) Weltek Technologies Co. Ltd. - C47000-C47FFF (base 16) Weltek Technologies Co. Ltd. - Flat A-B, 12/F, Block 1, Wah Fung Ind. Centre, 33-39 Kwai Fung Crescent, Kwai Chung, N.T. - 852 - HONG KONG - - 00-50-C2 (hex) Cytek Media Systems, INC. - C48000-C48FFF (base 16) Cytek Media Systems, INC. - 126 NW Jackson - Topeka KS 66603 - UNITED STATES - - 00-50-C2 (hex) Elektronic Thoma GmbH - C49000-C49FFF (base 16) Elektronic Thoma GmbH - Friedhofweg 5 - Dentlein a/F. 91599 - GERMANY - - 00-50-C2 (hex) Herrick Technology Laboratories, Inc. - C4A000-C4AFFF (base 16) Herrick Technology Laboratories, Inc. - 670 North Commercial Street - Suite 400 - Manchester New Hampshire 03101 - UNITED STATES - - 00-50-C2 (hex) R.V.R. elettronica s.p.a. - C4B000-C4BFFF (base 16) R.V.R. elettronica s.p.a. - via del Fonditore 2/2c - Bologna 40138 - ITALY - - 00-50-C2 (hex) Lancier Monitoring GmbH - C4C000-C4CFFF (base 16) Lancier Monitoring GmbH - Gustav-Stresemann-Weg 11 - Muenster NRW 48155 - GERMANY - - 00-50-C2 (hex) Industrial Automation Systems - C4D000-C4DFFF (base 16) Industrial Automation Systems - 32 Almanac Way - West Boylston MA 01583 - UNITED STATES - - 00-50-C2 (hex) Elaso AG - C4E000-C4EFFF (base 16) Elaso AG - Gewerbestrasse 14 - Zuchwil Solothurn 4528 - SWITZERLAND - - 00-50-C2 (hex) Powersense A/S - C4F000-C4FFFF (base 16) Powersense A/S - Skovlytoften 33 - Holte Sealand 2840 - DENMARK - - 00-50-C2 (hex) Beceem Communications, Inc. - C50000-C50FFF (base 16) Beceem Communications, Inc. - 3960 Freecom Cir. - 1st Floor - Santa Clara CA 95054 - UNITED STATES - - 00-50-C2 (hex) InForce Computing, Inc. - C51000-C51FFF (base 16) InForce Computing, Inc. - 48860 Milmont Drive, Suite 101C - Fremont CA 94538 - UNITED STATES - - 00-50-C2 (hex) Smartfield, Inc. - C52000-C52FFF (base 16) Smartfield, Inc. - 2601 SE Loop 289 - Suite B - Lubbock TX 79404 - UNITED STATES - - 00-50-C2 (hex) Eilersen Electric A/S - C53000-C53FFF (base 16) Eilersen Electric A/S - Kokkedal Industripark 4 - Kokkedal 2980 - DENMARK - - 00-50-C2 (hex) HPC Platform - C54000-C54FFF (base 16) HPC Platform - 63 rue Madeleine Michelis - Neuilly Sur Seine 92200 - FRANCE - - 00-50-C2 (hex) Watterott electronic - C55000-C55FFF (base 16) Watterott electronic - Winkelstr. 12a - Hausen Thueringen 37327 - GERMANY - - 00-50-C2 (hex) Spirent Communications - C56000-C56FFF (base 16) Spirent Communications - 541 Industrial Way West - Eatontown NJ 07724 - UNITED STATES - - 00-50-C2 (hex) High Speed Design, Inc. - C57000-C57FFF (base 16) High Speed Design, Inc. - 11929 NW Old Quarry Rd - Portland OR 97229 - UNITED STATES - - 00-50-C2 (hex) Foerster-Technik GmbH - C58000-C58FFF (base 16) Foerster-Technik GmbH - Gerwigstraße 25 - Engen Baden-Württemberg 78234 - GERMANY - - 00-50-C2 (hex) SKD System AB - C59000-C59FFF (base 16) SKD System AB - Rädisvägen 46 - Hässelby 16573 - SWEDEN - - 00-50-C2 (hex) Commotive A/S - C5A000-C5AFFF (base 16) Commotive A/S - Rebildskovhusevej 17 - Skørping DK-9520 - DENMARK - - 00-50-C2 (hex) MICRO TECHNICA - C5B000-C5BFFF (base 16) MICRO TECHNICA - 5-12-1 - Suneori-cho - Tsurugasima SAITAMA 350-2211 - JAPAN - - 00-50-C2 (hex) WAVECOM ELEKTRONIK AG - C5C000-C5CFFF (base 16) WAVECOM ELEKTRONIK AG - Hammerstrasse 8 - Bülach Zürich 8180 - SWITZERLAND - - 00-50-C2 (hex) SweMet AB - C5D000-C5DFFF (base 16) SweMet AB - Östgötagatan 19 - Linköping 58232 - SWEDEN - - 00-50-C2 (hex) CellPlus technologies, Inc. - C5E000-C5EFFF (base 16) CellPlus technologies, Inc. - 3959 Idaho Street - Suite 1 - San Diego California 92104 - UNITED STATES - - 00-50-C2 (hex) Icon Time Systems - C5F000-C5FFFF (base 16) Icon Time Systems - 15201 NW Greenbrier Parkway - Suite A1 - Beaverton OR 97006 - UNITED STATES - - 00-50-C2 (hex) Integration Technologies Limited - C60000-C60FFF (base 16) Integration Technologies Limited - Level 4 City Council Building - 32 The Square - Palmerston North Manawatu 4410 - NEW ZEALAND - - 00-50-C2 (hex) HaiVision Systems Incorporated - C61000-C61FFF (base 16) HaiVision Systems Incorporated - 4445 Garand - Montreal QC H4R 2H9 - CANADA - - 00-50-C2 (hex) Zeus Systems Private Limited - C62000-C62FFF (base 16) Zeus Systems Private Limited - B1 201 Center Point - 243A Delisle Road Lower Parel - Mumbai Maharashtra 400013 - INDIA - - 00-50-C2 (hex) Potter Electric Signal Company - C63000-C63FFF (base 16) Potter Electric Signal Company - 11790 Troy Lane North - Maple Grove MN 55369 - UNITED STATES - - 00-50-C2 (hex) Pal Software Service Co.,Ltd. - C64000-C64FFF (base 16) Pal Software Service Co.,Ltd. - 2ND TSUKUNA BULD. 3-10-31 AMAYAMA - MATSUYAMA EHIME 7900951 - JAPAN - - 00-50-C2 (hex) Micro I/O Servicos de Electronica, Lda - C65000-C65FFF (base 16) Micro I/O Servicos de Electronica, Lda - Zona Industrial da Taboeira, Lote 31D - Aveiro 3800-055 - AVEIRO - PORTUGAL - - 00-50-C2 (hex) KS Beschallungstechnik GmbH - C66000-C66FFF (base 16) KS Beschallungstechnik GmbH - Westendstr.1 - Hettenleidelheim Rhineland-Palatinate 67310 - GERMANY - - 00-50-C2 (hex) Practical Control Ltd - C67000-C67FFF (base 16) Practical Control Ltd - 443 Brightside Lane - Sheffield South Yorkshire S9 2RS - UNITED KINGDOM - - 00-50-C2 (hex) Broadsoft PacketSmart, Inc. - C68000-C68FFF (base 16) Broadsoft PacketSmart, Inc. - 10080 N Wolfe Rd, SW 3-300 - Cupertino CA 95014 - UNITED STATES - - 00-50-C2 (hex) REBO CO.,LTD. - C69000-C69FFF (base 16) REBO CO.,LTD. - 310 AceMill #1146 JangRim-Dong - Saho-KU - BUSAN 604-842 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) ELECTRONICA KELD - C6A000-C6AFFF (base 16) ELECTRONICA KELD - C/Lentisco 15 - Poligono Empresarium - LA CARTUJA BAJA ZARAGOZA 50720 - SPAIN - - 00-50-C2 (hex) SiGarden Sp z o.o. - C6B000-C6BFFF (base 16) SiGarden Sp z o.o. - ul. Trzy Lipy 3 - GdaÅ„sk woj. Pomorskie 80-034 - POLAND - - 00-50-C2 (hex) DORLET S.A. - C6C000-C6CFFF (base 16) DORLET S.A. - Albert Einstein 34 - Parque Tecnologico de Alava - Miñano Mayor Alava 01510 - SPAIN - - 00-50-C2 (hex) Deansoft CO., Ltd. - C6D000-C6DFFF (base 16) Deansoft CO., Ltd. - 3f,No.25,Alley 15, Lane 120, Neihu Rd., - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) TBS Holding AG - C6E000-C6EFFF (base 16) TBS Holding AG - Rietbrunnen 2 - Pfaeffikon SZ 8808 - SWITZERLAND - - 00-50-C2 (hex) MSB Elektronik und Geraetebau GmbH - C6F000-C6FFFF (base 16) MSB Elektronik und Geraetebau GmbH - Hofwiesenstr. 23 - Crailsheim BaWue 74564 - GERMANY - - 00-50-C2 (hex) Wilke Technology GmbH - C70000-C70FFF (base 16) Wilke Technology GmbH - Krefelder Strasse 147 - Aachen 52070 - GERMANY - - 00-50-C2 (hex) Sequoia Technology Group Ltd - C71000-C71FFF (base 16) Sequoia Technology Group Ltd - Tekelec House - Basingstoke Rd - Reading Berkshire RG7 1PW - UNITED KINGDOM - - 00-50-C2 (hex) Quail - C72000-C72FFF (base 16) Quail - 92 Lots Road - London SW10 0QD - UNITED KINGDOM - - 00-50-C2 (hex) Industry Controls, Inc. - C73000-C73FFF (base 16) Industry Controls, Inc. - 16124 Rosecrans Ave. Suite E5 - La Mirada CA 90638 - UNITED STATES - - 00-50-C2 (hex) Wapice Ltd. - C74000-C74FFF (base 16) Wapice Ltd. - Yliopistonranta 5 - P.O.Box 8 - Vaasa 65200 - FINLAND - - 00-50-C2 (hex) Rovsing A/S - C75000-C75FFF (base 16) Rovsing A/S - Dyregaardsvej 2 - Skovlunde Copenhagen 2740 - DENMARK - - 00-50-C2 (hex) GridManager A/S - C76000-C76FFF (base 16) GridManager A/S - Livovej 21 - Viborg 8800 - DENMARK - - 00-50-C2 (hex) AIM Co.,Ltd - C77000-C77FFF (base 16) AIM Co.,Ltd - 333-9 Nishi Miyukicho Hamachi - Toyohashi science core 304 - Toyohashi Aichi 441-8113 - JAPAN - - 00-50-C2 (hex) 9Solutions Oy - C78000-C78FFF (base 16) 9Solutions Oy - Teknologiantie 2 - Oulu 90590 - FINLAND - - 00-50-C2 (hex) CODESYSTEM Co.,Ltd - C79000-C79FFF (base 16) CODESYSTEM Co.,Ltd - #705 Ace Techno Tower-9th 345-30 - Gasan-Dong, Kumchon-Gu - Seoul 153-802 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Protonic Holland - C7A000-C7AFFF (base 16) Protonic Holland - Factorij 36 - Zwaag NH 1689 AL - NETHERLANDS - - 00-50-C2 (hex) Honeywell - C7B000-C7BFFF (base 16) Honeywell - 13350 US Highway North - MS/522-4 - Clearwater FL 33764 - UNITED STATES - - 00-50-C2 (hex) Scienlab Electronic Systems GmbH - C7C000-C7CFFF (base 16) Scienlab Electronic Systems GmbH - Lise-Meitner-Allee 27 - Bochum 44801 - GERMANY - - 00-50-C2 (hex) TAE Antriebstechnik GmbH - C7D000-C7DFFF (base 16) TAE Antriebstechnik GmbH - Am Kappengraben 20 - Wehrheim Hessen 61273 - GERMANY - - 00-50-C2 (hex) Buerkert Werke GmbH - C7E000-C7EFFF (base 16) Buerkert Werke GmbH - Christian-Buerkert-Strasse 13-17 - Ingelfingen 74653 - GERMANY - - 00-50-C2 (hex) Kinects Solutions Inc - C7F000-C7FFFF (base 16) Kinects Solutions Inc - 800 Kipling Avenue - Unit 3 - Toronto Ontario M8Z 6C4 - CANADA - - 00-50-C2 (hex) Reko-vek - C80000-C80FFF (base 16) Reko-vek - Gornaya str. 17"A" - Nizhni Novgorod Region 603062 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Odyssee Systemes SAS - C81000-C81FFF (base 16) Odyssee Systemes SAS - 840 Route de la Roquette - La Nartassiere - MOUANS-SARTOUX 06370 - FRANCE - - 00-50-C2 (hex) Kyosha Industries - C82000-C82FFF (base 16) Kyosha Industries - 11 rue parmentier - Bezons Val d'Oise 95870 - FRANCE - - 00-50-C2 (hex) Gronic Systems GmbH - C83000-C83FFF (base 16) Gronic Systems GmbH - Hilpertswiese 7 - Birstein 63633 - GERMANY - - 00-50-C2 (hex) DOMIS - C84000-C84FFF (base 16) DOMIS - 10 avenue Jean Moulin - RUMILLY 74150 - FRANCE - - 00-50-C2 (hex) Peek Traffic Corporation - C85000-C85FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) Bruckner & Jarosch Ingenieurgesellschaft mbH - C86000-C86FFF (base 16) Bruckner & Jarosch Ingenieurgesellschaft mbH - Nonnengasse 5a - Erfurt Thuringia 99084 - GERMANY - - 00-50-C2 (hex) LECO Corporation - C87000-C87FFF (base 16) LECO Corporation - 3000 Lakeview Ave. - St. Joseph Michigan 49085 - UNITED STATES - - 00-50-C2 (hex) CSI Controles e Sistemas Industriais Ltda. - C88000-C88FFF (base 16) CSI Controles e Sistemas Industriais Ltda. - Av. Piraporinha, 506 - Diadema São Paulo 09950000 - BRAZIL - - 00-50-C2 (hex) Creative Micro Design - C89000-C89FFF (base 16) Creative Micro Design - 645B Dawson drive - Newark DE 19713 - UNITED STATES - - 00-50-C2 (hex) Automated Media Services, Inc. - C8A000-C8AFFF (base 16) Automated Media Services, Inc. - 110 Commerce Drive - Allendale NJ 07401 - UNITED STATES - - 00-50-C2 (hex) OCAS AS - C8B000-C8BFFF (base 16) OCAS AS - Brobekkvn 80A - Oslo 0582 - NORWAY - - 00-50-C2 (hex) Lanmark Controls Inc. - C8C000-C8CFFF (base 16) Lanmark Controls Inc. - 125 Nagog Park - Suite 305 - Acton MA 01720 - UNITED STATES - - 00-50-C2 (hex) Emergency Message Controls LLC - C8D000-C8DFFF (base 16) Emergency Message Controls LLC - 5 Canterbury Rd - Charlottesville VA 22903 - UNITED STATES - - 00-50-C2 (hex) SDD ITG - C8E000-C8EFFF (base 16) SDD ITG - Volgina 15 - Belgrade 11060 - SERBIA - - 00-50-C2 (hex) Keith & Koep GmbH - C8F000-C8FFFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) REALD - C90000-C90FFF (base 16) REALD - 5335 STERLING DRIVE - BOULDER CO 80301 - UNITED STATES - - 00-50-C2 (hex) Media Technologies Ltd. - C91000-C91FFF (base 16) Media Technologies Ltd. - 361 Mill Road - Mile End - Colchester Essex CO4 5GG - UNITED KINGDOM - - 00-50-C2 (hex) EMAC, Inc. - C92000-C92FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 00-50-C2 (hex) SENSAIR Pty Ltd - C93000-C93FFF (base 16) SENSAIR Pty Ltd - 79 Crooke Road - Castella Victoria 3777 - AUSTRALIA - - 00-50-C2 (hex) ISIS ENGINEERING, S.A. - C94000-C94FFF (base 16) ISIS ENGINEERING, S.A. - C/ JOSE JESUS GARCIA DIAZ, 2 - SEVILLA 41020 - SPAIN - - 00-50-C2 (hex) IPSES S.r.l. - C95000-C95FFF (base 16) IPSES S.r.l. - Via Trieste, 48 - Cesate Milano 20020 - ITALY - - 00-50-C2 (hex) CyberCraft - C96000-C96FFF (base 16) CyberCraft - 20-33 mathuyacho - Neyagawa-Chi Osaka-fu 572-0086 - JAPAN - - 00-50-C2 (hex) MSTRONIC CO., LTD. - C97000-C97FFF (base 16) MSTRONIC CO., LTD. - 2F, No#12 Gongshang Rd. - Wugu, - Taipei County 248 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Criticare Systems, Inc - C98000-C98FFF (base 16) Criticare Systems, Inc - 20925 Crossroads Circle, Suite 100 - Waukesha WI 53186-4054 - UNITED STATES - - 00-50-C2 (hex) HJPC Corporation dba Pactron - C99000-C99FFF (base 16) HJPC Corporation dba Pactron - 1149 Tasman Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) PACOMP Sp. z o.o. - C9A000-C9AFFF (base 16) PACOMP Sp. z o.o. - Pulawska 34 - Piaseczno mazowieckie 05-500 - POLAND - - 00-50-C2 (hex) Sm electronic co. - C9B000-C9BFFF (base 16) Sm electronic co. - 338-2, Gwangpyeong-dong, - Gumi-si Gyeongsangbuk-do, 730-080 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Saia-Burgess Controls AG - C9C000-C9CFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Radius Sweden AB - C9D000-C9DFFF (base 16) Radius Sweden AB - Tennvagen 1 - Karlskrona Blekinge 37150 - SWEDEN - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - C9E000-C9EFFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu Street, district 1, - BUCHAREST 014186 - ROMANIA - - 00-50-C2 (hex) xxter b.v. - C9F000-C9FFFF (base 16) xxter b.v. - Elandsgracht 73 I - Amsterdam NH 1016 TR - NETHERLANDS - - 00-50-C2 (hex) Kiefer technic GmbH - CA0000-CA0FFF (base 16) Kiefer technic GmbH - Feldbacher Strasse 77 - Bad Gleichenberg Styria 8344 - AUSTRIA - - 00-50-C2 (hex) Wayne Kerr Electronics - CA1000-CA1FFF (base 16) Wayne Kerr Electronics - Unit 4, Vinnetrow Business Park - Vinnetrow Road - Chichester West Sussex PO20 1QH - UNITED KINGDOM - - 00-50-C2 (hex) The Logical Company - CA2000-CA2FFF (base 16) The Logical Company - 75 Gateway Blvd. - Cottage Grove OR 97424 - UNITED STATES - - 00-50-C2 (hex) CT Company - CA3000-CA3FFF (base 16) CT Company - Godovikova 9, Moscow - Moscow RUSSIA 129085 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Vox Technologies - CA4000-CA4FFF (base 16) Vox Technologies - 1180 Commerce Dr. - Richardson TX 75081 - UNITED STATES - - 00-50-C2 (hex) YOKOWO CO.,LTD - CA5000-CA5FFF (base 16) YOKOWO CO.,LTD - 5-11 Takinogawa 7-Chome Kita-ku - Tokyo 114-8515 - JAPAN - - 00-50-C2 (hex) Vidisys GmbH - CA6000-CA6FFF (base 16) Vidisys GmbH - Rudolf-Diesel-Ring 30 - Sauerlach Bavaria 82054 - GERMANY - - 00-50-C2 (hex) Thermo Fisher Scientific - CA7000-CA7FFF (base 16) Thermo Fisher Scientific - 1410 Gillingham Lane - Sugar Land Texas 77478 - UNITED STATES - - 00-50-C2 (hex) Systems With Intelligence Inc. - CA8000-CA8FFF (base 16) Systems With Intelligence Inc. - 1215 Meyerside Drive, Unit 7 - Mississauga Ontario L5T 1H3 - CANADA - - 00-50-C2 (hex) Intelligent Devices - CA9000-CA9FFF (base 16) Intelligent Devices - 300 Redland Ct. - Suite 204 - Owings Mills MD 21117 - UNITED STATES - - 00-50-C2 (hex) DSP DESIGN LTD - CAA000-CAAFFF (base 16) DSP DESIGN LTD - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) SAE IT-systems GmbH & Co. KG - CAB000-CABFFF (base 16) SAE IT-systems GmbH & Co. KG - Im Gewerbegebiet Pesch 14 - Köln NRW 50767 - GERMANY - - 00-50-C2 (hex) PURVIS Systems Incorporated - CAC000-CACFFF (base 16) PURVIS Systems Incorporated - 1272 West Main Rd - Middletown Rhode Island 02842 - UNITED STATES - - 00-50-C2 (hex) Pacific Coast Engineering - CAD000-CADFFF (base 16) Pacific Coast Engineering - 1524 Fernwood Drive - Oakland CA 94611 - UNITED STATES - - 00-50-C2 (hex) Campbell Scientific Canada Corp. - CAE000-CAEFFF (base 16) Campbell Scientific Canada Corp. - 11564 149 Street - Edmonton Alberta T5M 1W7 - CANADA - - 00-50-C2 (hex) Fr. Sauter AG - CAF000-CAFFFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS CH4016 - SWITZERLAND - - 00-50-C2 (hex) Konsmetal S.A. - CB0000-CB0FFF (base 16) Konsmetal S.A. - Bracka 25 St. - Warsaw 00-028 - POLAND - - 00-50-C2 (hex) ZK Celltest Inc - CB1000-CB1FFF (base 16) ZK Celltest Inc - 256 Gibraltar Drive - Suite 109 - Sunnyvale CA 94089 - UNITED STATES - - 00-50-C2 (hex) Moravian Instruments - CB2000-CB2FFF (base 16) Moravian Instruments - Masarykova 1148 - Zlin 763 02 - CZECH REPUBLIC - - 00-50-C2 (hex) Deuta-Werke GmbH - CB3000-CB3FFF (base 16) Deuta-Werke GmbH - Paffrather Str. 140 - Bergisch Gladbach Northrhine Westfalia 51465 - GERMANY - - 00-50-C2 (hex) GEA Farm Technologies GmbH - CB4000-CB4FFF (base 16) GEA Farm Technologies GmbH - Siemensstr. 25-27 - Bonen NRW 59199 - GERMANY - - 00-50-C2 (hex) PRIVATE - CB5000-CB5FFF (base 16) - - 00-50-C2 (hex) Krontek Pty Ltd - CB6000-CB6FFF (base 16) Krontek Pty Ltd - 2 Carinya Close - Allambie NSW 2100 - AUSTRALIA - - 00-50-C2 (hex) inotech GmbH - CB7000-CB7FFF (base 16) inotech GmbH - Siemensallee 84 - Karlsruhe BW 76187 - GERMANY - - 00-50-C2 (hex) Raith GmbH - CB8000-CB8FFF (base 16) Raith GmbH - Konrad-Adenauer-Allee 8 - Dortmund 44263 - GERMANY - - 00-50-C2 (hex) Micro Technic A/S - CB9000-CB9FFF (base 16) Micro Technic A/S - Smedevaenget 5 - Aarup 5560 - DENMARK - - 00-50-C2 (hex) DELTA TAU DATA SYSTEMS - CBA000-CBAFFF (base 16) DELTA TAU DATA SYSTEMS - 21314 LASSEN ST - CHATSWORTH CA 91311 - UNITED STATES - - 00-50-C2 (hex) Coptonix GmbH - CBB000-CBBFFF (base 16) Coptonix GmbH - Luxemburger Str. 31 - Berlin 13353 - GERMANY - - 00-50-C2 (hex) CP ELETRONICA SA - CBC000-CBCFFF (base 16) CP ELETRONICA SA - RUA VARZEA, 379 - PORTO ALEGRE RIO GRANDE DO SUL 91040600 - BRAZIL - - 00-50-C2 (hex) Hi Tech Electronics Ltd - CBD000-CBDFFF (base 16) Hi Tech Electronics Ltd - 93 Osvobozdenie Blvd. - Plovdiv 4023 - BULGARIA - - 00-50-C2 (hex) CODE BLUE CORPORATION - CBE000-CBEFFF (base 16) CODE BLUE CORPORATION - 259 Hedcor St - HOLLAND MI 49423 - UNITED STATES - - 00-50-C2 (hex) Megacon AB - CBF000-CBFFFF (base 16) Megacon AB - Ranhammarsvägen 20 - Bromma Stockholm 168 67 - SWEDEN - - 00-50-C2 (hex) World Time Solutions Limited - CC0000-CC0FFF (base 16) World Time Solutions Limited - 6 Clinton Crescent - Aylesbury Buckinghamshire HP21 7JW - UNITED KINGDOM - - 00-50-C2 (hex) Level 3 Communications - CC1000-CC1FFF (base 16) Level 3 Communications - 1025 Eldorado Blvd - Broomfield Colorado 80021 - UNITED STATES - - 00-50-C2 (hex) ConectaIP Tecnologia S.L. - CC2000-CC2FFF (base 16) ConectaIP Tecnologia S.L. - Novell 58 - Barcelona 08014 - SPAIN - - 00-50-C2 (hex) viscount systems inc. - CC3000-CC3FFF (base 16) viscount systems inc. - 4585 tillicum street - burnaby bc v5j5k9 - CANADA - - 00-50-C2 (hex) General Dynamics C4S - CC4000-CC4FFF (base 16) General Dynamics C4S - 8220 East Roosevelt St. R1122 - Scottsdale AZ 85257 - UNITED STATES - - 00-50-C2 (hex) Tecnovum AG - CC5000-CC5FFF (base 16) Tecnovum AG - Nobelring 26 - Frankfurt Main Hessen 60598 - GERMANY - - 00-50-C2 (hex) KDT - CC6000-CC6FFF (base 16) KDT - 203-902, Bucheon Techno-Park - Yakdae-dong, Wonmi-gu - Bucheon-si Gyeonggi-do 420-733 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) TOPROOT Technology Corp. Ltd., - CC7000-CC7FFF (base 16) TOPROOT Technology Corp. Ltd., - 10F , No. 192, Sec. 3, Datong Rd., Sijhih City, , - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) PRIVATE - CC8000-CC8FFF (base 16) - - 00-50-C2 (hex) Promess GmbH - CC9000-CC9FFF (base 16) Promess GmbH - Schaffhausener Str. 44 - Berlin 12099 - GERMANY - - 00-50-C2 (hex) SANMINA SHENZHEN - CCA000-CCAFFF (base 16) SANMINA SHENZHEN - 1 NAN LING ROAD - XIN ER CUN, SHA JIN ZHEN, BAO AN - SHENZHEN 518125 - CHINA - - 00-50-C2 (hex) CaptiveAire Systems Inc. - CCB000-CCBFFF (base 16) CaptiveAire Systems Inc. - 4641 Paragon Park - Raleigh NC 27616 - UNITED STATES - - 00-50-C2 (hex) Smartech-technology - CCC000-CCCFFF (base 16) Smartech-technology - Stachek 107-J office 16H - Saint-Petersburg 198303 - RUSSIAN FEDERATION - - 00-50-C2 (hex) FUJI DATA SYSTEM Co.,Ltd. - CCD000-CCDFFF (base 16) FUJI DATA SYSTEM Co.,Ltd. - 5-21-14 - HIGASHINANIWA-Cho - AMAGASAKI-Shi HYOGO-Prf. 660-0892 - JAPAN - - 00-50-C2 (hex) Mac-Gray Corporation - CCE000-CCEFFF (base 16) Mac-Gray Corporation - 404 Wyman Street - Suite 400 - Waltham MA 02451 - UNITED STATES - - 00-50-C2 (hex) TASK SISTEMAS DE COMPUTACAO LTDA - CCF000-CCFFFF (base 16) TASK SISTEMAS DE COMPUTACAO LTDA - Rua 2 / 112 Jardim Itatiaia - Itatiaia Rio de Janeiro 27580-000 - BRAZIL - - 00-50-C2 (hex) MME Mueller Mikroelektronik - CD0000-CD0FFF (base 16) MME Mueller Mikroelektronik - Hauptstr. 8 - Gew. H. 2 - Berlin 10827 - GERMANY - - 00-50-C2 (hex) ACD Elektronik GmbH - CD1000-CD1FFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) SIM2 Multimedia S.p.A. - CD2000-CD2FFF (base 16) SIM2 Multimedia S.p.A. - Viale Lino Zanussi 11 - PORDENONE 33170 - ITALY - - 00-50-C2 (hex) Covidence A/S - CD3000-CD3FFF (base 16) Covidence A/S - Strandvejen 2A - Roende 8410 - DENMARK - - 00-50-C2 (hex) SCHRAML GmbH - CD4000-CD4FFF (base 16) SCHRAML GmbH - Herxheimer Str. 7 - Vagen Bavaria 83620 - GERMANY - - 00-50-C2 (hex) Arcos Technologies Ltd. - CD5000-CD5FFF (base 16) Arcos Technologies Ltd. - 26 Hasivim St. - Petach-Tikva 49517 - ISRAEL - - 00-50-C2 (hex) Arktan Systems - CD6000-CD6FFF (base 16) Arktan Systems - 580 California Street, Suite 1200 - San Francisco CA 94104 - UNITED STATES - - 00-50-C2 (hex) Saia-Burgess Controls AG - CD7000-CD7FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) IT-IS International Ltd. - CD8000-CD8FFF (base 16) IT-IS International Ltd. - 1 Wainstones Court - Stokesley Business Park - Stokesley North Yorkshire TS95JY - UNITED KINGDOM - - 00-50-C2 (hex) NDC Infrared Engineering, Inc. - CD9000-CD9FFF (base 16) NDC Infrared Engineering, Inc. - 5314 N. Irwindale Avenue - Irwindale CA 91706 - UNITED STATES - - 00-50-C2 (hex) taskit GmbH - CDA000-CDAFFF (base 16) taskit GmbH - Seelenbinderstrasse 33 - Berlin 12555 - GERMANY - - 00-50-C2 (hex) RUTTER INC - CDB000-CDBFFF (base 16) RUTTER INC - 63 THORBURN ROAD - ST. JOHN'S NEWFOUNDLAND A1B 3M2 - CANADA - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - CDC000-CDCFFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park Torch Hi-tech Development Zone - Xiao Dong Shan, - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) K.C.C. SHOKAI LIMITED - CDD000-CDDFFF (base 16) K.C.C. SHOKAI LIMITED - 1-2-1 - Murotani, Nishi-ku - Kobe Hyougo-ken 651-2241 - JAPAN - - 00-50-C2 (hex) Axotec Technologies GmbH - CDE000-CDEFFF (base 16) Axotec Technologies GmbH - Sudetenstrasse 88 - Geretsried Bavaria 82538 - GERMANY - - 00-50-C2 (hex) CoreEL TEchnologies (I) Pvt Ltd - CDF000-CDFFFF (base 16) CoreEL TEchnologies (I) Pvt Ltd - No.21,7th Main - 1st Block Koramangala - Bangalore Karntaka 560034 - INDIA - - 00-50-C2 (hex) Industrial Control Links, Inc. - CE0000-CE0FFF (base 16) Industrial Control Links, Inc. - 12840 Earhart Ave. - Auburn CA 95602 - UNITED STATES - - 00-50-C2 (hex) Satellink Inc. - CE1000-CE1FFF (base 16) Satellink Inc. - 3525 Miller Park Dr. - Garland TX 75042 - UNITED STATES - - 00-50-C2 (hex) Sicon s.r.l. - CE2000-CE2FFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) Industrial Automatics Design Bureau - CE3000-CE3FFF (base 16) Industrial Automatics Design Bureau - 239 Bolshaya Sadovaya St - Saratov Saratovskaya oblast 410005 - RUSSIAN FEDERATION - - 00-50-C2 (hex) TEKTRONIK - CE4000-CE4FFF (base 16) TEKTRONIK - 44-48 Rocco Drive - Scoresby - Melbourne VICTORIA 3179 - AUSTRALIA - - 00-50-C2 (hex) Maretron, LLP - CE5000-CE5FFF (base 16) Maretron, LLP - 9014 N. 23rd Ave #10 - Phoenix AZ 85021 - UNITED STATES - - 00-50-C2 (hex) APLICA TECHNOLOGIES - CE6000-CE6FFF (base 16) APLICA TECHNOLOGIES - 10 HALAPID - 13 HASILOCH - PETECH- TIKVA 49170 - ISRAEL - - 00-50-C2 (hex) Echola Systems - CE7000-CE7FFF (base 16) Echola Systems - 1971 Wayne Cir - San Jose CA 95131 - UNITED STATES - - 00-50-C2 (hex) Thomas & Betts - CE8000-CE8FFF (base 16) Thomas & Betts - 5900 Eastport Blvd - Richmond Virginia 23231 - UNITED STATES - - 00-50-C2 (hex) PRIVATE - CE9000-CE9FFF (base 16) - - 00-50-C2 (hex) Keith & Koep GmbH - CEA000-CEAFFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Toyon Research Corporation - CEB000-CEBFFF (base 16) Toyon Research Corporation - 6800 Cortona Drive - Goleta CA 93117 - UNITED STATES - - 00-50-C2 (hex) Erhardt+Leimer GmbH - CEC000-CECFFF (base 16) Erhardt+Leimer GmbH - Albert-Leimer-Platz 1 - Stadtbergen Bavaria 86391 - GERMANY - - 00-50-C2 (hex) AeroMechanical Services Ltd, FLYHT - CED000-CEDFFF (base 16) AeroMechanical Services Ltd, FLYHT - Suite 200W - 1144-29th Avenue N.E - Calgary Alberta T2E7P1 - CANADA - - 00-50-C2 (hex) EMBED-IT OG - CEE000-CEEFFF (base 16) EMBED-IT OG - Phorusgasse 8 - Vienna 1040 - AUSTRIA - - 00-50-C2 (hex) Lupatecnologia e Sistemas Ltda - CEF000-CEFFFF (base 16) Lupatecnologia e Sistemas Ltda - Rua Viscondessa Di Cavalcante, 75/301 - Bairro Poço Rico - Juiz de Fora Minas Gerais 36020-070 - BRAZIL - - 00-50-C2 (hex) Inviso B.V. - CF0000-CF0FFF (base 16) Inviso B.V. - Kouter 106 - Gemert Noord Brabant 5422AD - NETHERLANDS - - 00-50-C2 (hex) TelGaAs, Inc. - CF1000-CF1FFF (base 16) TelGaAs, Inc. - 125 N. Central Dr. - O'Fallon MO 63366 - UNITED STATES - - 00-50-C2 (hex) Weiss Robotics GmbH & Co. KG - CF2000-CF2FFF (base 16) Weiss Robotics GmbH & Co. KG - In der Gerste 2 - Ludwigsburg Baden-Württemberg 71636 - GERMANY - - 00-50-C2 (hex) Daiken Automacao Ltda - CF3000-CF3FFF (base 16) Daiken Automacao Ltda - Av Sao Gabriel 481 - Campo Pequeno - Colombo Pr 83404000 - BRAZIL - - 00-50-C2 (hex) Baudisch Electronic GmbH - CF4000-CF4FFF (base 16) Baudisch Electronic GmbH - Im Gewerbegebiet 7-9 - Wäschenbeuren Baden-Württemberg 73116 - GERMANY - - 00-50-C2 (hex) Aircell - CF5000-CF5FFF (base 16) Aircell - 303 S. Technology Dr. - Bldg A - Broomfield CO 80021 - UNITED STATES - - 00-50-C2 (hex) Epec Oy - CF6000-CF6FFF (base 16) Epec Oy - P.L. Box 194 - Tiedekatu 6 - Seinäjoki 60101 - FINLAND - - 00-50-C2 (hex) Armour Home Electronics LTD - CF7000-CF7FFF (base 16) Armour Home Electronics LTD - Unit B3 Kingswey Business Park - Forsythe Road - Woking Surrey GU21 5SA - UNITED KINGDOM - - 00-50-C2 (hex) beks Kommunikacios Technika kft - CF8000-CF8FFF (base 16) beks Kommunikacios Technika kft - Rakoczi utca 21 - Debrecen 4024 - HUNGARY - - 00-50-C2 (hex) Elbit Systems of America - CF9000-CF9FFF (base 16) Elbit Systems of America - 4700 Marine Creek Parkway - Fort Worth TX 76179 - UNITED STATES - - 00-50-C2 (hex) Grupo Epelsa S.L. - CFA000-CFAFFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) New Embedded Technology - CFB000-CFBFFF (base 16) New Embedded Technology - 204 N El Camino Real - Suite E-440 - Encinitas Ca 92024 - UNITED STATES - - 00-50-C2 (hex) Tritium Pty Ltd - CFC000-CFCFFF (base 16) Tritium Pty Ltd - Unit 1 / 30 Walker St - Tennyson QLD 4105 - AUSTRALIA - - 00-50-C2 (hex) AIRFOLC,INC. - CFD000-CFDFFF (base 16) AIRFOLC,INC. - 4F CHOYO-BLDG.,225 SANMONJI-CHO - NAKAGYO-KU - KYOTO 604-8135 - JAPAN - - 00-50-C2 (hex) Techleader - CFE000-CFEFFF (base 16) Techleader - HYEON BLDG 4TH FL 157-1 CHUNUI-DONG - BUCHEON-SHI KYONGGI-DO 420-859 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Infrasafe, Inc. - CFF000-CFFFFF (base 16) Infrasafe, Inc. - 12612 Challenger Pkwy - Suite 300 - Orlando FL 32826 - UNITED STATES - - 00-50-C2 (hex) Bodensee Gravitymeter Geosystem GmbH - D00000-D00FFF (base 16) Bodensee Gravitymeter Geosystem GmbH - Im Gehren 15 - Uberlingen Baden-Württemberg 88662 - GERMANY - - 00-50-C2 (hex) Aanderaa Data Instruments - D01000-D01FFF (base 16) Aanderaa Data Instruments - Sandalsringen 5B - P.O.Box 103 - Midtun Hordaland 5828 - NORWAY - - 00-50-C2 (hex) SURVALENT TECHNOLOGY CORP - D02000-D02FFF (base 16) SURVALENT TECHNOLOGY CORP - 2600 ARGENTIA ROAD - MISSISSAUGA ONTARIO L5N 5V4 - CANADA - - 00-50-C2 (hex) Peekel Instruments B.V. - D03000-D03FFF (base 16) Peekel Instruments B.V. - Industrieweg 161 - Rotterdam ZH 3044 AS - NETHERLANDS - - 00-50-C2 (hex) Tehama Wireless - D04000-D04FFF (base 16) Tehama Wireless - 423 Tehama Street - San Francisco CA 94103 - UNITED STATES - - 00-50-C2 (hex) nCk Research LLC - D06000-D06FFF (base 16) nCk Research LLC - 106 Cobblestone Court Drive - #189 - Victor NY 14564 - UNITED STATES - - 00-50-C2 (hex) IAF GmbH - D07000-D07FFF (base 16) IAF GmbH - Berliner Str. 52j - Braunschweig 38104 - GERMANY - - 00-50-C2 (hex) Reimesch Kommunikationssysteme GmbH - D08000-D08FFF (base 16) Reimesch Kommunikationssysteme GmbH - Friedrich-Ebert-Str. - Bergisch Gladbach NRW 51429 - GERMANY - - 00-50-C2 (hex) Guardtec, Inc. - D09000-D09FFF (base 16) Guardtec, Inc. - #1203, Hansin IT Tower, 235, - Guro-dong, Guro-gu - Seoul 152-768 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Airpoint Co., Ltd. - D0A000-D0AFFF (base 16) Airpoint Co., Ltd. - 3rd fl. KDB Bldg. 946 unsan-dong - Seo-gu - Daejeon 302-120 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) CODACO ELECTRONIC s.r.o. - D0B000-D0BFFF (base 16) CODACO ELECTRONIC s.r.o. - Hemy 825 - Valasske Mezirici 75701 - CZECH REPUBLIC - - 00-50-C2 (hex) JVL Industri Elektronik - D0C000-D0CFFF (base 16) JVL Industri Elektronik - Blokken 42 - Birkeroed Sjaelland DK-3460 - DENMARK - - 00-50-C2 (hex) DECA Card Engineering GmbH - D0D000-D0DFFF (base 16) DECA Card Engineering GmbH - Bahnstrasse 29-31 - Ratingen NW 40878 - GERMANY - - 00-50-C2 (hex) Weinert Engineering GmbH - D0E000-D0EFFF (base 16) Weinert Engineering GmbH - An den Kolonaten 27 - Bad Zwischenahn Niedersachsen 26160 - GERMANY - - 00-50-C2 (hex) Saia-Burgess Controls AG - D0F000-D0FFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Rosslare Enterprises Ltd. - D10000-D10FFF (base 16) Rosslare Enterprises Ltd. - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon 00000 - HONG KONG - - 00-50-C2 (hex) Aplex Technology Inc. - D11000-D11FFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn Industrial Park Tower4 , - Nanshan District,ShenZhen - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) Tokyo Weld Co.,Ltd. - D12000-D12FFF (base 16) Tokyo Weld Co.,Ltd. - 2-28-1, Kitamagome - Ota-ku Tokyo 143-0021 - JAPAN - - 00-50-C2 (hex) GUNMA ELECTRONICS CO LTD - D13000-D13FFF (base 16) GUNMA ELECTRONICS CO LTD - 760 OOMAMA - MIDORI-CITY GUNMA 376-0101 - JAPAN - - 00-50-C2 (hex) SAET I.S. - D14000-D14FFF (base 16) SAET I.S. - Via Leinì 1/b - San maurizio Canavese TO 10077 - ITALY - - 00-50-C2 (hex) MSR-Office GmbH - D15000-D15FFF (base 16) MSR-Office GmbH - Ravensburger Straße 71 - Wangen Baden-Württemberg 88239 - GERMANY - - 00-50-C2 (hex) Imricor Medical Systems, Inc. - D16000-D16FFF (base 16) Imricor Medical Systems, Inc. - 400 Gateway Boulevard - Burnsville MN 55337 - UNITED STATES - - 00-50-C2 (hex) CUE, a.s. - D17000-D17FFF (base 16) CUE, a.s. - K Nouzovu 2090/6 - Praha 143 00 - CZECH REPUBLIC - - 00-50-C2 (hex) Glyn GmbH & Co.KG - D18000-D18FFF (base 16) Glyn GmbH & Co.KG - Am Wörtzgarten 8 - Idstein Hessen 65510 - GERMANY - - 00-50-C2 (hex) Applied Medical Technologies, Inc DBA AirClean Systems - D19000-D19FFF (base 16) Applied Medical Technologies, Inc DBA AirClean Systems - 3248 Lake Woodard Dr. - Raleigh NC 27604 - UNITED STATES - - 00-50-C2 (hex) GILLAM-FEI S.A. - D1A000-D1AFFF (base 16) GILLAM-FEI S.A. - Mont St Martin 58 - LIEGE B4000 - BELGIUM - - 00-50-C2 (hex) TECHKON GmbH - D1B000-D1BFFF (base 16) TECHKON GmbH - Wiesbadener Str. 27 - Koenigstein Hessen 61462 - GERMANY - - 00-50-C2 (hex) Recon Dynamics, LLC - D1C000-D1CFFF (base 16) Recon Dynamics, LLC - 2300 Carillon Point - Kirkland WA 98033 - UNITED STATES - - 00-50-C2 (hex) Moco Media Pty Ltd - D1D000-D1DFFF (base 16) Moco Media Pty Ltd - Ground Floor - 156 George St. - Fitzroy VIC 3065 - AUSTRALIA - - 00-50-C2 (hex) Tobila Systems, Inc. - D1E000-D1EFFF (base 16) Tobila Systems, Inc. - 1-8-23-6A - Marunouchi Naka-ku - Nagoya Aichi 4600002 - JAPAN - - 00-50-C2 (hex) Olympus NDT Canada Inc. - D1F000-D1FFFF (base 16) Olympus NDT Canada Inc. - 505, boul Parc Technologique - Quebec G1P 4S9 - CANADA - - 00-50-C2 (hex) 7+ Kft - D20000-D20FFF (base 16) 7+ Kft - Homorod 17 - Budapest 1118 - HUNGARY - - 00-50-C2 (hex) Innovative Circuit Technology - D21000-D21FFF (base 16) Innovative Circuit Technology - 26921 Gloucester Way - Langley BC V4W 3Y3 - CANADA - - 00-50-C2 (hex) eMDee Technology, Inc. - D22000-D22FFF (base 16) eMDee Technology, Inc. - 4450 Pet Lane - Suite 114 - Lutz FL 33559 - UNITED STATES - - 00-50-C2 (hex) Bluestone Technology GmbH - D23000-D23FFF (base 16) Bluestone Technology GmbH - Mikroforum Ring 2 - Wendelsheim Rhineland-Palatinate 55234 - GERMANY - - 00-50-C2 (hex) Expro North Sea - D24000-D24FFF (base 16) Expro North Sea - Units 4-6, 9 Bessemer Close - Ebblake Industrial Estate - Verwood Dorset BH31 6AZ - UNITED KINGDOM - - 00-50-C2 (hex) VAF Instruments BV - D25000-D25FFF (base 16) VAF Instruments BV - PO Box 40 - Dordrecht 3300 AA - NETHERLANDS - - 00-50-C2 (hex) RCH GROUP - D26000-D26FFF (base 16) RCH GROUP - VIA CENDON, 39 - SILEA TREVISO 31057 - ITALY - - 00-50-C2 (hex) Fr.Sauter AG - D27000-D27FFF (base 16) Fr.Sauter AG - Im Surinam 55 - Basel BS CH4016 - SWITZERLAND - - 00-50-C2 (hex) Digitale Analoge COMponenten West Electronic Vertriebs GmbH - D28000-D28FFF (base 16) Digitale Analoge COMponenten West Electronic Vertriebs GmbH - Schallbruch 19-21 - Haan NRW 42781 - GERMANY - - 00-50-C2 (hex) Axible Technologies - D29000-D29FFF (base 16) Axible Technologies - 425 rue Jean Rostand - Labège 31670 - FRANCE - - 00-50-C2 (hex) Millennium Electronics Pty.Ltd. - D2A000-D2AFFF (base 16) Millennium Electronics Pty.Ltd. - 12 Webber Parade - East Keilor Victoria 3033 - AUSTRALIA - - 00-50-C2 (hex) Video Tech Laboratories, Inc. - D2B000-D2BFFF (base 16) Video Tech Laboratories, Inc. - 2761-1 Togo, Shimokanuki - Numazu Shizuoka Prefecture 410-0822 - JAPAN - - 00-50-C2 (hex) Schneider Electric Motion USA - D2C000-D2CFFF (base 16) Schneider Electric Motion USA - 370 N. Main St. - Marlborough CT 06447 - UNITED STATES - - 00-50-C2 (hex) CADI SCIENTIFIC PTE LTD - D2D000-D2DFFF (base 16) CADI SCIENTIFIC PTE LTD - 31 UBI ROAD 1 #03-00 AZTECH BUILDING - 408694 - SINGAPORE - - 00-50-C2 (hex) RS Gesellschaft fur Informationstechnik mbH & Co KG - D2E000-D2EFFF (base 16) RS Gesellschaft fur Informationstechnik mbH & Co KG - Bergische Fachbuchhandlung - Konrad-Adenauer-Strasse 6 - Remscheid NRW 42853 - GERMANY - - 00-50-C2 (hex) Key Systems, Inc. - D2F000-D2FFFF (base 16) Key Systems, Inc. - PO Box G - Fishers New York 14453 - UNITED STATES - - 00-50-C2 (hex) ACTIV Financial Systems, Inc. - D30000-D30FFF (base 16) ACTIV Financial Systems, Inc. - 120 East Liberty Drive - Suite 200 - Wheaton IL 60187 - UNITED STATES - - 00-50-C2 (hex) UNGAVA Technologies Inc. - D31000-D31FFF (base 16) UNGAVA Technologies Inc. - 2750 rue Einstein - Bureau 360 - Quebec G1P 4R1 - CANADA - - 00-50-C2 (hex) RealTime Systems Ltd - D32000-D32FFF (base 16) RealTime Systems Ltd - A-49 Okhla Ind Area - Phase-1 - New Delhi Delhi 110020 - INDIA - - 00-50-C2 (hex) Maddalena S.p.A - D33000-D33FFF (base 16) Maddalena S.p.A - via G.B. Maddalena 2/4 - Povoletto UD 33040 - ITALY - - 00-50-C2 (hex) GAON TECH corp. - D34000-D34FFF (base 16) GAON TECH corp. - #509, 199 Tekeuno2(i)-ro, Yuseong-gu - Daejeon 305-500, Korea - Daejeon Yuseong-gu 305-500 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) UG Systems GmbH & Co. KG - D35000-D35FFF (base 16) UG Systems GmbH & Co. KG - Kronacher Str. 41 - Bamberg Bayern 96052 - GERMANY - - 00-50-C2 (hex) Enatel Limited - D36000-D36FFF (base 16) Enatel Limited - 66 Treffers Road - Christchurch Canterbury 8042 - NEW ZEALAND - - 00-50-C2 (hex) LJT & Associates, Inc. - D37000-D37FFF (base 16) LJT & Associates, Inc. - 9881 Brokenland Pkwy, Suite 400 - Columbia MD 21046 - UNITED STATES - - 00-50-C2 (hex) Kyowa Electronics Co.,Ltd. - D38000-D38FFF (base 16) Kyowa Electronics Co.,Ltd. - 4-3-31 Takatsukasa - Takarazuka Hyogo 665-0051 - JAPAN - - 00-50-C2 (hex) Apex NV - D39000-D39FFF (base 16) Apex NV - Schoebroekstraat, 62 - Beringen Limburg 3583 - BELGIUM - - 00-50-C2 (hex) WellSense Technologies - D3A000-D3AFFF (base 16) WellSense Technologies - Communication Center - Neve Ilan 90850 - ISRAEL - - 00-50-C2 (hex) Gitsn Inc. - D3B000-D3BFFF (base 16) Gitsn Inc. - #811, Woolim Ebiz Center First, 170-5 - Guro 3-Dong, Guro-Gu - Seoul 152-769 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) ASSYSTEM France - D3C000-D3CFFF (base 16) ASSYSTEM France - 13 rue Marie Louise Dissard - ZAC Saint-Martin du Touch - BP 13015 - TOULOUSE 31024 - FRANCE - - 00-50-C2 (hex) Tellabs Operations Inc. - D3D000-D3DFFF (base 16) Tellabs Operations Inc. - One Tellabs Center - 1415 west Diehl Road - Naperville Illinois 60563 - UNITED STATES - - 00-50-C2 (hex) Synatec Electronic GmbH - D3E000-D3EFFF (base 16) Synatec Electronic GmbH - Bruehlhofstraße 4 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-50-C2 (hex) CSS, LLC - D3F000-D3FFFF (base 16) CSS, LLC - 6030 S 58th St, STE C - Lincoln NE 68516 - UNITED STATES - - 00-50-C2 (hex) demmel products - D40000-D40FFF (base 16) demmel products - Radnitzkygasse 43 - Vienna 1100 - AUSTRIA - - 00-50-C2 (hex) AREA ENERGY, INC. - D41000-D41FFF (base 16) AREA ENERGY, INC. - 4F-3, No.2 , Lane 258, Rui Guang Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Hagenuk KMT GmbH - D42000-D42FFF (base 16) Hagenuk KMT GmbH - Röderaue 41 - Radeburg Sachsen 01471 - GERMANY - - 00-50-C2 (hex) DSP4YOU Ltd - D43000-D43FFF (base 16) DSP4YOU Ltd - 17 Hung To Road - Unit 305, - Kwun Tong - HONG KONG - - 00-50-C2 (hex) Saia-Burgess Controls AG - D44000-D44FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Technagon GmbH - D45000-D45FFF (base 16) Technagon GmbH - Grafenauer Str. 22 - Freyung Bavaria 94078 - GERMANY - - 00-50-C2 (hex) Thales Nederland BV - D46000-D46FFF (base 16) Thales Nederland BV - Haaksbergerstraat 49 - P.O. Box 42 - Hengelo Overijssel 7554PA - NETHERLANDS - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - D47000-D47FFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu Street, district 1, - Bucharest 014186 - ROMANIA - - 00-50-C2 (hex) Watermark Estate Management Services, LLC - D48000-D48FFF (base 16) Watermark Estate Management Services, LLC - 10230 NE Points Dr. - Suite 200 - Kirkland WA 98033 - UNITED STATES - - 00-50-C2 (hex) Smith Meter, Inc - D49000-D49FFF (base 16) Smith Meter, Inc - 1602 Wagner Ave. - Erie PA 16514 - UNITED STATES - - 00-50-C2 (hex) ATH system - D4A000-D4AFFF (base 16) ATH system - Osady Lezaku 498 - Chrast CZ 53851 - CZECH REPUBLIC - - 00-50-C2 (hex) Indra Australia - D4B000-D4BFFF (base 16) Indra Australia - Unit 21 - 38-46 South St - Rydalmere NSW 2116 - AUSTRALIA - - 00-50-C2 (hex) DALOG Diagnosesysteme GmbH - D4C000-D4CFFF (base 16) DALOG Diagnosesysteme GmbH - Siemensstrasse 2a - Neusaess Bavaria 86356 - GERMANY - - 00-50-C2 (hex) Yardney Technical Products Inc. - D4D000-D4DFFF (base 16) Yardney Technical Products Inc. - 82 Mechanic Street - Pawcatuck Connecticut 06379 - UNITED STATES - - 00-50-C2 (hex) Keith & Koep GmbH - D4E000-D4EFFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) SECOM GmbH - D4F000-D4FFFF (base 16) SECOM GmbH - Saseler Bogen 4a - Hamburg 22393 - GERMANY - - 00-50-C2 (hex) Solbrig Electronics, Inc. - D50000-D50FFF (base 16) Solbrig Electronics, Inc. - 1201 Clubhouse Dr. - Broomfield CO 80020 - UNITED STATES - - 00-50-C2 (hex) BETTINI SRL - D51000-D51FFF (base 16) BETTINI SRL - VIA CESARE BATTISTI 22 - CESANO MADERNO MILAN 20031 - ITALY - - 00-50-C2 (hex) F+D Feinwerk- und Drucktechnik GmbH - D52000-D52FFF (base 16) F+D Feinwerk- und Drucktechnik GmbH - Kirchenstr. 38 - Neckarsteinach 69239 - GERMANY - - 00-50-C2 (hex) Telemerkki Oy - D53000-D53FFF (base 16) Telemerkki Oy - Raturinkuja 10-12 - Jokela Tuusula 05400 - FINLAND - - 00-50-C2 (hex) ABtrack s.r.l. - D54000-D54FFF (base 16) ABtrack s.r.l. - Autoporto di Gorizia Pad B - Gorizia 34170 - ITALY - - 00-50-C2 (hex) Sterna Security - D55000-D55FFF (base 16) Sterna Security - 169 West Sambandam Road - RS Puram - Coimbatore TN 641002 - INDIA - - 00-50-C2 (hex) SELEX Communications Limited - D56000-D56FFF (base 16) SELEX Communications Limited - Lambda House - Christopher Martin Road - Basildon Essex SS14 3EL - UNITED KINGDOM - - 00-50-C2 (hex) Hijikata Denki Corp. - D57000-D57FFF (base 16) Hijikata Denki Corp. - 1-13-1 Minami Denen - Fussa Tokyo 197-0004 - JAPAN - - 00-50-C2 (hex) NIK-ELEKTRONIKA Ltd - D58000-D58FFF (base 16) NIK-ELEKTRONIKA Ltd - L.Kurbasa Ave 2-B - Kiev 03148 - UKRAINE - - 00-50-C2 (hex) BUANCO SYSTEM A/S - D59000-D59FFF (base 16) BUANCO SYSTEM A/S - Agerhatten 25 - Odense SØ 5220 - DENMARK - - 00-50-C2 (hex) Embedded Monitoring Systems Ltd. - D5A000-D5AFFF (base 16) Embedded Monitoring Systems Ltd. - Suite 103, LEO - Enterprise Crescent - Lisburn Co Antrim BT28 2BP - UNITED KINGDOM - - 00-50-C2 (hex) Infinition Inc. - D5B000-D5BFFF (base 16) Infinition Inc. - 3630 Jean Talon - Trois-Rivieres QC G8Y 2G7 - CANADA - - 00-50-C2 (hex) Ibetor S.L. - D5C000-D5CFFF (base 16) Ibetor S.L. - Belgrado, 26. - Poligono Industrial Europolis - Las Rozas Madrid 28232 - SPAIN - - 00-50-C2 (hex) GLOBALCOM ENGINEERING SRL - D5D000-D5DFFF (base 16) GLOBALCOM ENGINEERING SRL - Via Volta 9 - MORNAGO VA 21020 - ITALY - - 00-50-C2 (hex) infinitec co., ltd. - D5E000-D5EFFF (base 16) infinitec co., ltd. - 2-6-35, Honcho - Yonezawasi Yamagata 992-0037 - JAPAN - - 00-50-C2 (hex) Embedded Solution Co., Ltd. - D5F000-D5FFFF (base 16) Embedded Solution Co., Ltd. - #905 A, Woolim Lions Valley, 144-3 - Sangdaewon-dong - Seongnam-Si Kyungi-Do 462-120 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Nihon Kessho Koogaku Co., Ltd. - D60000-D60FFF (base 16) Nihon Kessho Koogaku Co., Ltd. - 318-19 Kondo-cho - Tatebayashi Gunma 374-0042 - JAPAN - - 00-50-C2 (hex) system2 GmbH - D61000-D61FFF (base 16) system2 GmbH - Gewerbering 8 - Dorfen Bavaria 84405 - GERMANY - - 00-50-C2 (hex) EMAC, Inc. - D62000-D62FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 00-50-C2 (hex) DATAREGIS S.A. - D63000-D63FFF (base 16) DATAREGIS S.A. - Rua Dom Aguirre, 190 - São Paulo SP 04671-245 - BRAZIL - - 00-50-C2 (hex) TV1 GmbH - D64000-D64FFF (base 16) TV1 GmbH - Betastr. 9a - Unterfoehring Bavaria 85774 - GERMANY - - 00-50-C2 (hex) TX Technology Corp - D65000-D65FFF (base 16) TX Technology Corp - 7 Emery Ave - Randolph New Jersey 07869 - UNITED STATES - - 00-50-C2 (hex) Uvax Concepts - D66000-D66FFF (base 16) Uvax Concepts - Parque Empresarial Tactica - Calle Corretger 71-2 - Paterna Valencia 46980 - SPAIN - - 00-50-C2 (hex) KLING & FREITAG GmbH - D67000-D67FFF (base 16) KLING & FREITAG GmbH - Junkersstrasse 14 - Hannover NDS 30179 - GERMANY - - 00-50-C2 (hex) HiSpeed Data, Inc. - D68000-D68FFF (base 16) HiSpeed Data, Inc. - 4 Dakota Trail - Branchburg NJ 08876 - UNITED STATES - - 00-50-C2 (hex) GHL Systems Bhd - D69000-D69FFF (base 16) GHL Systems Bhd - L5-E-7B, Enterprise 4 - Technology Park Malaysia - Bukit Jalil Kuala Lumpur 57000 - MALAYSIA - - 00-50-C2 (hex) A&T Corporation, Electrics Group , LAS R&D Unit, - D6A000-D6AFFF (base 16) A&T Corporation, Electrics Group , LAS R&D Unit, - 2023-1 Endo - Fujisawa-shi Kanagawa-Pref. 252-0816 - JAPAN - - 00-50-C2 (hex) Nemec Automation - D6B000-D6BFFF (base 16) Nemec Automation - Waldkircher Str. 12 - Freiburg BW 79106 - GERMANY - - 00-50-C2 (hex) ALPHA Corporation - D6C000-D6CFFF (base 16) ALPHA Corporation - Product Development Department, Housing Hardware Devision - 1-6-8, Fukuura, Kanazawa-ku - Yokohama Kanagawa 236-0004 - JAPAN - - 00-50-C2 (hex) Pro-Digital Industria Eletronica - D6D000-D6DFFF (base 16) Pro-Digital Industria Eletronica - Rua Senador Saraiva, 200 - Curitiba Parana 80510300 - BRAZIL - - 00-50-C2 (hex) BC Illumination, Inc. - D6E000-D6EFFF (base 16) BC Illumination, Inc. - 209 Westbury Lane - Georgetown Texas 78633 - UNITED STATES - - 00-50-C2 (hex) Imtron Messtechnik GmbH - D6F000-D6FFFF (base 16) Imtron Messtechnik GmbH - Carl-Benz-Straße 11 - Owingen Baden-Württemberg 88696 - GERMANY - - 00-50-C2 (hex) C. Rob. Hammerstein GmbH & Co. KG - D70000-D70FFF (base 16) C. Rob. Hammerstein GmbH & Co. KG - Merscheider Strasse 167 - Solingen NRW 42699 - GERMANY - - 00-50-C2 (hex) EMAC, Inc. - D71000-D71FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 00-50-C2 (hex) Scale-Tron, Inc. - D72000-D72FFF (base 16) Scale-Tron, Inc. - 6428 Trans-Canada Highway - St-Laurent Quebec H4T 1X4 - CANADA - - 00-50-C2 (hex) Saia-Burgess Controls AG - D73000-D73FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Computech International - D74000-D74FFF (base 16) Computech International - 525 Northern Boulevard - Great Neck NY 11021 - UNITED STATES - - 00-50-C2 (hex) Collectric AB - D75000-D75FFF (base 16) Collectric AB - Regementsvagen 4 - Sundsvall Medelpad 85238 - SWEDEN - - 00-50-C2 (hex) Telvent - D76000-D76FFF (base 16) Telvent - Valgrande, 6 - Alcobendas Madrid 28108 - SPAIN - - 00-50-C2 (hex) Fr.SauterAG - D77000-D77FFF (base 16) Fr.SauterAG - Im Surinam 55 - BASEL BS CH - SWITZERLAND - - 00-50-C2 (hex) P4Q Electronics - D78000-D78FFF (base 16) P4Q Electronics - Alonsotegi Elkartegia, Mód. 27 - Alonsotegi Bizkaia 48810 - SPAIN - - 00-50-C2 (hex) DSI RF Systems, Inc. - D79000-D79FFF (base 16) DSI RF Systems, Inc. - 26H Worlds Fair Drive - Somerset NJ 08873 - UNITED STATES - - 00-50-C2 (hex) Transbit Sp. z o.o. - D7A000-D7AFFF (base 16) Transbit Sp. z o.o. - Przyczolkowa 109A - Warsaw 02-968 - POLAND - - 00-50-C2 (hex) OWITA GmbH - D7B000-D7BFFF (base 16) OWITA GmbH - Langenbruch 6 - Lemgo NRW D-32657 - GERMANY - - 00-50-C2 (hex) Microcubs Systems Pvt Ltd - D7C000-D7CFFF (base 16) Microcubs Systems Pvt Ltd - S.no.25/4/5, Vijaya Chembers, - Hingne(kh), Sinhgad Road, - PUNE Maharastra 411051 - INDIA - - 00-50-C2 (hex) Voltech Instruments - D7D000-D7DFFF (base 16) Voltech Instruments - 148 Sixth Street - Harwell Campus - Didcot Oxon OX11 0TR - UNITED KINGDOM - - 00-50-C2 (hex) LYNX Technik AG - D7E000-D7EFFF (base 16) LYNX Technik AG - Brunnenweg 3 - Weiterstadt Hessen 64331 - GERMANY - - 00-50-C2 (hex) HMI Technologies - D7F000-D7FFFF (base 16) HMI Technologies - PO Box 38164 - Howick Auckland 2145 - NEW ZEALAND - - 00-50-C2 (hex) Keith & Koep GmbH - D80000-D80FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) TATTILE SRL - D81000-D81FFF (base 16) TATTILE SRL - VIA DONIZETTI 1/3/5 - MAIRANO BRESCIA 25030 - ITALY - - 00-50-C2 (hex) Audio Authority Corp - D82000-D82FFF (base 16) Audio Authority Corp - 2048 Mercer Road - Lexington Kentucky 40514 - UNITED STATES - - 00-50-C2 (hex) Blankom - D83000-D83FFF (base 16) Blankom - Hermann-Petersilge-Str. 1 - Bad Blankenburg TH 07422 - GERMANY - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - D84000-D84FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park Torch Hi-tech Development Zone, - Xiao Dong Shan, - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) VITEC - D85000-D85FFF (base 16) VITEC - 99, rue Pierre Semard - CHATILLON 92320 - FRANCE - - 00-50-C2 (hex) ECOMM ERA - D86000-D86FFF (base 16) ECOMM ERA - Flat H, 14/F, Kim Tak Building - 330 Nathan Road - 201203 - HONG KONG - - 00-50-C2 (hex) Electrolight Shivuk (1994) Ltd. - D87000-D87FFF (base 16) Electrolight Shivuk (1994) Ltd. - P.O BOX 258, Moshav Bazra 60944 - Moshav Bazra 60944 - ISRAEL - - 00-50-C2 (hex) T+A elektroakustik GmbH & Co KG - D88000-D88FFF (base 16) T+A elektroakustik GmbH & Co KG - Planckstraße 9-11 - Herford NRW 32052 - GERMANY - - 00-50-C2 (hex) Visual Telecommunication Network, Inc - D89000-D89FFF (base 16) Visual Telecommunication Network, Inc - 2400 Geng Road - Suite 200 - Palo Alto CA 94303 - UNITED STATES - - 00-50-C2 (hex) OptoLink Industria e Comercio Ltda - D8A000-D8AFFF (base 16) OptoLink Industria e Comercio Ltda - R.Alfredo da Costa Figo 280 - Campinas SP 13087-534 - BRAZIL - - 00-50-C2 (hex) Sicon s.r.l. - D8B000-D8BFFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) iRphotonics - D8C000-D8CFFF (base 16) iRphotonics - 627, McCaffrey - St-Laurent Quebec H4T 1N3 - CANADA - - 00-50-C2 (hex) CS-Instruments - D8D000-D8DFFF (base 16) CS-Instruments - Zindelsteiner Straße 15 - VS-Tannheim Baden-Württemberg 78052 - GERMANY - - 00-50-C2 (hex) LSD Science&Technology Co.,Ltd. - D8E000-D8EFFF (base 16) LSD Science&Technology Co.,Ltd. - Lierda Building,No.425 Dengyun Road - Hangzhou Zhejiang 310011 - CHINA - - 00-50-C2 (hex) Syes srl - D8F000-D8FFFF (base 16) Syes srl - Via Zanella 21 - Lissone MB 20035 - ITALY - - 00-50-C2 (hex) Dumps Electronic - D90000-D90FFF (base 16) Dumps Electronic - Passauer Straße 45 - Röhrnbach 94133 - GERMANY - - 00-50-C2 (hex) CHAUVIN ARNOUX - D91000-D91FFF (base 16) CHAUVIN ARNOUX - LA QUEUE DEVEE - REUX 14130 - FRANCE - - 00-50-C2 (hex) Manz - D92000-D92FFF (base 16) Manz - 21D Yagia Kapayim St. - P.O.B. 3938 - Petach-Tikva Israel 49130 - ISRAEL - - 00-50-C2 (hex) Axlon AB - D93000-D93FFF (base 16) Axlon AB - Ulvsundavagen 110 - BROMMA 16867 - SWEDEN - - 00-50-C2 (hex) Software Effect Enterprises, Inc - D94000-D94FFF (base 16) Software Effect Enterprises, Inc - PO Box 1514 - Newnan GA 30264 - UNITED STATES - - 00-50-C2 (hex) Honeywell - D95000-D95FFF (base 16) Honeywell - 13350 US Highway 19 N - Clearwater Fl 33764 - UNITED STATES - - 00-50-C2 (hex) CONTEC GmbH - D96000-D96FFF (base 16) CONTEC GmbH - Wildbichler Strasse 2e - Ebbs TIROL 6341 - AUSTRIA - - 00-50-C2 (hex) ERS electronic GmbH - D97000-D97FFF (base 16) ERS electronic GmbH - Stettiner Str. 3 - Germering Bavaraia 82110 - GERMANY - - 00-50-C2 (hex) Rong Shun Xuan Corp. - D98000-D98FFF (base 16) Rong Shun Xuan Corp. - 1F, No. 5, Aly. 1, Ln 297, Ancing St., Sanchong City, - Taipei 24162 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) T-Industry, s.r.o. - D99000-D99FFF (base 16) T-Industry, s.r.o. - Hostaky 910/49 - Myjava Trenciansky Kraj 90701 - SLOVAKIA - - 00-50-C2 (hex) Saia-Burgess Controls AG - D9A000-D9AFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Intuitive Surgical, Inc - D9B000-D9BFFF (base 16) Intuitive Surgical, Inc - 1266 Kifer Road - Sunnyvale CA 94086 - UNITED STATES - - 00-50-C2 (hex) Gamber Johnson LLC - D9C000-D9CFFF (base 16) Gamber Johnson LLC - 3001 Borham Ave - Stevens Point Wisconsin 54481 - UNITED STATES - - 00-50-C2 (hex) Mistral Solutions Pvt. Ltd - D9D000-D9DFFF (base 16) Mistral Solutions Pvt. Ltd - #60, Adarsh Regent, 100 Ft. Ring Road,Domlur Extension - BANGALORE KARNATAKA 560071 - INDIA - - 00-50-C2 (hex) Vocality International - D9E000-D9EFFF (base 16) Vocality International - Lydling Barn - Puttenham Lane - Guildford Surrey GU86AP - UNITED KINGDOM - - 00-50-C2 (hex) BitWise Controls - D9F000-D9FFFF (base 16) BitWise Controls - 98 Inverness Dr East - Suite 150 - Englewood CO 80112 - UNITED STATES - - 00-50-C2 (hex) Precision Remotes - DA0000-DA0FFF (base 16) Precision Remotes - 860 Harbour Way South, Suite A - Richmond CA 94804 - UNITED STATES - - 00-50-C2 (hex) MangoDSP - DA1000-DA1FFF (base 16) MangoDSP - 8 Hartom St. Beck Science Center - P.O.Box 45116, Har Hozvim - Jerusalem 91450 - ISRAEL - - 00-50-C2 (hex) metraTec GmbH - DA2000-DA2FFF (base 16) metraTec GmbH - Werner-Heisenberg-Str. 1 - Magdeburg Sachsen-Anh. 39106 - GERMANY - - 00-50-C2 (hex) GENERAL DYNAMICS C4 SYSTEMS - DA3000-DA3FFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST - MD: R1115 - SCOTTSDALE, AZ 85257 - UNITED STATES - - 00-50-C2 (hex) Deuta-Werke GmbH - DA4000-DA4FFF (base 16) Deuta-Werke GmbH - Paffrather Str. 140 - Bergisch Gladbach Northrhine Westfalia 51465 - GERMANY - - 00-50-C2 (hex) megatec electronic GmbH - DA5000-DA5FFF (base 16) megatec electronic GmbH - Lehenhammer 14 - Etzelwang Bayern 92268 - GERMANY - - 00-50-C2 (hex) Manitowoc Ice - DA6000-DA6FFF (base 16) Manitowoc Ice - 2110 South 26th Street - Manitowoc Wisconsin 54221-1720 - UNITED STATES - - 00-50-C2 (hex) Capton - DA7000-DA7FFF (base 16) Capton - 3001 Bridgeway - Suite K-354 - Sausalito CA 94965 - UNITED STATES - - 00-50-C2 (hex) Sine Systems, Inc. - DA8000-DA8FFF (base 16) Sine Systems, Inc. - 972 Main St. - Nashville TN 37206-3614 - UNITED STATES - - 00-50-C2 (hex) Tieline Research Pty Ltd - DA9000-DA9FFF (base 16) Tieline Research Pty Ltd - PO Box 2092 - Malaga Western Australia 6944 - AUSTRALIA - - 00-50-C2 (hex) M & PAUL, INC - DAA000-DAAFFF (base 16) M & PAUL, INC - #602, Jugong Bldg., - 42 Macheondong, Songpagu - Seoul 138-120 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Aplex Technology Inc. - DAB000-DABFFF (base 16) Aplex Technology Inc. - 2Q,NanYouTianAn Industrial Park Tower4,Nanshan District, - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) RFL Electronics - DAC000-DACFFF (base 16) RFL Electronics - 353 Powerville Rd - Boonton NJ 07005 - UNITED STATES - - 00-50-C2 (hex) Keith & Koep GmbH - DAD000-DADFFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Spang Power Electronics - DAE000-DAEFFF (base 16) Spang Power Electronics - 9305 Progress Parkway - Mentor Ohio 44060 - UNITED STATES - - 00-50-C2 (hex) eumig industrie-tv GmbH - DAF000-DAFFFF (base 16) eumig industrie-tv GmbH - Gewerbeparkstr.9 - Salzburg Anif 5081 - AUSTRIA - - 00-50-C2 (hex) IMAGO Technologies GmbH - DB0000-DB0FFF (base 16) IMAGO Technologies GmbH - Strassheimer Strasse 45 - Friedberg Hessen D-61169 - GERMANY - - 00-50-C2 (hex) RF Code, Inc - DB1000-DB1FFF (base 16) RF Code, Inc - 9229 Waterford Centre - Suite 500 - Austin TX 78758 - UNITED STATES - - 00-50-C2 (hex) SoftwareCannery - DB2000-DB2FFF (base 16) SoftwareCannery - 1660 Sandalwood Lane - Carlsbad CA 92008 - UNITED STATES - - 00-50-C2 (hex) LAUDA DR. R. WOBSER GMBH & CO. KG - DB3000-DB3FFF (base 16) LAUDA DR. R. WOBSER GMBH & CO. KG - Pfarrstraße 41/43 - Lauda-Koenigshofen Baden-Württemberg 97922 - GERMANY - - 00-50-C2 (hex) ZAO NPC "Kompjuternie Technologii" - DB4000-DB4FFF (base 16) ZAO NPC "Kompjuternie Technologii" - Komsomolskiy av., 90-17 - Perm Perm Region 614010 - RUSSIAN FEDERATION - - 00-50-C2 (hex) DSP DESIGN LTD - DB5000-DB5FFF (base 16) DSP DESIGN LTD - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) PROSOFT-SYSTEMS LTD - DB6000-DB6FFF (base 16) PROSOFT-SYSTEMS LTD - Volgogradskaya, 194 a - Ekaterinburg Sverdlovskaya region 620102 - RUSSIAN FEDERATION - - 00-50-C2 (hex) SOREL GmbH Mikroelektronik - DB7000-DB7FFF (base 16) SOREL GmbH Mikroelektronik - Jahnstrasse 36 - Sprockhovel 45549 - GERMANY - - 00-50-C2 (hex) Comsat VertriebsgmbH - DB8000-DB8FFF (base 16) Comsat VertriebsgmbH - Sonnenhang 29 - Thalheim Steiermark 8754 - AUSTRIA - - 00-50-C2 (hex) Peek Traffic Corporation - DB9000-DB9FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) M.P. Electronics - DBA000-DBAFFF (base 16) M.P. Electronics - 2464 Vulcan Road - Apopka Florida 32703 - UNITED STATES - - 00-50-C2 (hex) Esensors, Inc. - DBB000-DBBFFF (base 16) Esensors, Inc. - 4240 Ridge Lea Road - Suite 37 - Amherst NY 14226 - UNITED STATES - - 00-50-C2 (hex) Nantes Systems Private Limited - DBC000-DBCFFF (base 16) Nantes Systems Private Limited - B-822 SOBHAWINDFALL - 15 AMRUTHAHALLI, YELAHANKA HOBLI - BANGALORE KARNATAKA 560092 - INDIA - - 00-50-C2 (hex) Margento R&D - DBD000-DBDFFF (base 16) Margento R&D - Gosposvetska 84 - Maribor 2000 - SLOVENIA - - 00-50-C2 (hex) WITHSYSTEM Co.,Ltd - DBE000-DBEFFF (base 16) WITHSYSTEM Co.,Ltd - C/603, Digital empire, #980-3 - yeongtong-dong, yeongtong-gu - suwon-si gyeonggi-do 443-470 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) One-Nemoto Engineering Corporation - DBF000-DBFFFF (base 16) One-Nemoto Engineering Corporation - - 2-35-1 Tamagawadai, Setagaya-ku - Tokyo 158-0096 - JAPAN - - 00-50-C2 (hex) Security Services Group (SSG) - DC0000-DC0FFF (base 16) Security Services Group (SSG) - Unit 12, Taurus Business Park - Europa Boulevard - Warrington Cheshire WA5 7ZT - UNITED KINGDOM - - 00-50-C2 (hex) Acrux Technology Limited - DC1000-DC1FFF (base 16) Acrux Technology Limited - Rm 2A6, 3/F, Sing Win Factory Building,15-17 Shing Yip St, - Kwun Tong - HONG KONG - - 00-50-C2 (hex) TESSERA TECHNOLOGY INC. - DC2000-DC2FFF (base 16) TESSERA TECHNOLOGY INC. - 2710-1 4F, Noborito, Tama-ku - Kawasaki-shi Kanagawa 214-0014 - JAPAN - - 00-50-C2 (hex) ZED Ziegler Electronic Devices GmbH - DC3000-DC3FFF (base 16) ZED Ziegler Electronic Devices GmbH - In den Folgen 7 - Langewiesen 98704 - GERMANY - - 00-50-C2 (hex) Keith & Koep GmbH - DC4000-DC4FFF (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 00-50-C2 (hex) Saia-Burgess Controls AG - DC5000-DC5FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Fluid Components International - DC6000-DC6FFF (base 16) Fluid Components International - 1755 La Costa Meadows Dr. - San Marcos CA 92078 - UNITED STATES - - 00-50-C2 (hex) AGT Holdings Limited - DC7000-DC7FFF (base 16) AGT Holdings Limited - Shangling Industrial Area, Hengli Town - Dongguan 523467 - CHINA - - 00-50-C2 (hex) T2M2 GmbH - DC8000-DC8FFF (base 16) T2M2 GmbH - Gruenberger Str. 140 - Giessen Hessen 35394 - GERMANY - - 00-50-C2 (hex) KinotonGmbH - DC9000-DC9FFF (base 16) KinotonGmbH - Industriestrasse 20a - Germering Bavaria 82110 - GERMANY - - 00-50-C2 (hex) Tele Data Control - DCA000-DCAFFF (base 16) Tele Data Control - Pod Jarovem 2236 - Praha 13000 - CZECH REPUBLIC - - 00-50-C2 (hex) CT Company - DCB000-DCBFFF (base 16) CT Company - Godovikova 9, Moscow - Moscow RUSSIA 129085 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Instrumentel Limited - DCC000-DCCFFF (base 16) Instrumentel Limited - Leeds Innovation center - 103 Clarendon Road - Leeds West Yorkshire LS2 9DF - UNITED KINGDOM - - 00-50-C2 (hex) dilitronics GmbH - DCD000-DCDFFF (base 16) dilitronics GmbH - Felsbachstr. 5 - Jena Thuringia 07745 - GERMANY - - 00-50-C2 (hex) Mecsel Oy - DCE000-DCEFFF (base 16) Mecsel Oy - Laitilankuja 5 - Helsinki 00420 - FINLAND - - 00-50-C2 (hex) MCS Engenharia ltda - DCF000-DCFFFF (base 16) MCS Engenharia ltda - Al. Caiapos, 596 - Tamboré - Barueri São Paulo 06460-110 - BRAZIL - - 00-50-C2 (hex) IDC Solutions Pty Ltd - DD0000-DD0FFF (base 16) IDC Solutions Pty Ltd - Suite 8, 21 Regent Street - Redfern - Sydney NSW 2016 - AUSTRALIA - - 00-50-C2 (hex) Brankamp GmbH - DD1000-DD1FFF (base 16) Brankamp GmbH - Max.-Plank Str. 9-13 - Erkrath NRW 40699 - GERMANY - - 00-50-C2 (hex) Electronic Applications, Inc. - DD2000-DD2FFF (base 16) Electronic Applications, Inc. - 2513 W via de Pedro Miguel - Phoenix AZ 85086 - UNITED STATES - - 00-50-C2 (hex) Rohde & Schwarz Topex SA - DD3000-DD3FFF (base 16) Rohde & Schwarz Topex SA - 10 Feleacu Street, district 1, - Bucharest 014186 - ROMANIA - - 00-50-C2 (hex) SYSTECH - DD4000-DD4FFF (base 16) SYSTECH - 1004 - Ishimori-cyo - Fukui-si Fukui-ken 910-0122 - JAPAN - - 00-50-C2 (hex) Friend Spring Industrial Co., Ltd. - DD5000-DD5FFF (base 16) Friend Spring Industrial Co., Ltd. - 4F., No. 8, Lane 50, Sec. 3 - Nan-Kang Road - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Transas Marine International AB - DD6000-DD6FFF (base 16) Transas Marine International AB - Datavagen 37 - Askim Vastra Gotaland 436 32 - SWEDEN - - 00-50-C2 (hex) Tornado Modular Systems - DD7000-DD7FFF (base 16) Tornado Modular Systems - Inzhenernaya str. 4a - Novosibirsk 630090 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Selex Systems Integration Inc - DD8000-DD8FFF (base 16) Selex Systems Integration Inc - 11300 W 89th St - Overland Park Kansas 66214 - UNITED STATES - - 00-50-C2 (hex) Metraware - DD9000-DD9FFF (base 16) Metraware - Quartier Cime de Vieres - CABRIERES D AIGUES 84240 - FRANCE - - 00-50-C2 (hex) rbz robot design s.l. - DDA000-DDAFFF (base 16) rbz robot design s.l. - avda via lactea 4, local 1 - san fernando de henares madrid 28830 - SPAIN - - 00-50-C2 (hex) LUCEO - DDB000-DDBFFF (base 16) LUCEO - 16 Rue Laënnec - Vern Sur Seiche 35770 - FRANCE - - 00-50-C2 (hex) Vision & Control GmbH - DDC000-DDCFFF (base 16) Vision & Control GmbH - Mittelbergstrasse 16 - Suhl 98527 - GERMANY - - 00-50-C2 (hex) A&A GENERAL SRL - DDD000-DDDFFF (base 16) A&A GENERAL SRL - Calea Victoriei 85, bl.1, ap.30 - Sector 1 - Bucuresti 010066 - ROMANIA - - 00-50-C2 (hex) DRS ITS - DDE000-DDEFFF (base 16) DRS ITS - 100 N. Babcock St. - Melbourne Florida 32935 - UNITED STATES - - 00-50-C2 (hex) Device GmbH - DDF000-DDFFFF (base 16) Device GmbH - Thieshoper Strasse 16 - Brackel 21438 - GERMANY - - 00-50-C2 (hex) INTERNET PROTOCOLO LOGICA SL - DE0000-DE0FFF (base 16) INTERNET PROTOCOLO LOGICA SL - Sector Foresta 43. Edificio Oficentro - Local 26 - Tres Cantos Madrid 28760 - SPAIN - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - DE1000-DE1FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park Torch Hi-tech Development Zone, - Xiao Dong Shan, - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) SEQUTEC INC - DE2000-DE2FFF (base 16) SEQUTEC INC - 2958 SCOTT BLVD - SANTA CLARA CA 95054 - UNITED STATES - - 00-50-C2 (hex) Breakaway Systems LLC - DE3000-DE3FFF (base 16) Breakaway Systems LLC - 10307 Sugar Hill Dr - Houston TX 77042 - UNITED STATES - - 00-50-C2 (hex) EGS Technologies Ltd - DE4000-DE4FFF (base 16) EGS Technologies Ltd - 6 Waterside Business Park - Wheelhouse Road - Rugeley Staffordshire WS15 1LJ - UNITED KINGDOM - - 00-50-C2 (hex) Neets - DE5000-DE5FFF (base 16) Neets - Langballe 4 - Horsens 8700 - DENMARK - - 00-50-C2 (hex) Fr. Sauter AG - DE6000-DE6FFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS CH4016 - SWITZERLAND - - 00-50-C2 (hex) Elan Systems - DE7000-DE7FFF (base 16) Elan Systems - 10 Ihasz utca - BUDAPEST 1105 - HUNGARY - - 00-50-C2 (hex) Visual Productions - DE8000-DE8FFF (base 16) Visual Productions - Rollandstraat 55ZW - Haarlem 2013SM - NETHERLANDS - - 00-50-C2 (hex) Dacom West GmbH - DE9000-DE9FFF (base 16) Dacom West GmbH - Schallbruch 19-21 - Haan NRW 42781 - GERMANY - - 00-50-C2 (hex) Cerner Corporation - DEA000-DEAFFF (base 16) Cerner Corporation - 2800 Rockcreek Parkway - Kansas City MO 64117 - UNITED STATES - - 00-50-C2 (hex) Ruwisch & Kollegen GmbH - DEB000-DEBFFF (base 16) Ruwisch & Kollegen GmbH - Ostendstr. 25 - Berlin 12459 - GERMANY - - 00-50-C2 (hex) VendNovation LLC - DEC000-DECFFF (base 16) VendNovation LLC - 13400 NE 20th Street - Suite 32 - Bellevue WA 98005 - UNITED STATES - - 00-50-C2 (hex) Lee Laser - DED000-DEDFFF (base 16) Lee Laser - 7605 Presidents Drive - Orlando FL 32809 - UNITED STATES - - 00-50-C2 (hex) Powersense A/S - DEF000-DEFFFF (base 16) Powersense A/S - Skovlytoften 33 - Holte 2840 - DENMARK - - 00-50-C2 (hex) Koncar Electrical Engineering Institute - DF0000-DF0FFF (base 16) Koncar Electrical Engineering Institute - Fallerovo setaliste 22 - Zagreb 10000 - CROATIA - - 00-50-C2 (hex) Saia-Burgess Controls AG - DF1000-DF1FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Ocean Sonics - DF2000-DF2FFF (base 16) Ocean Sonics - Hill House - 11 Lornevale Road - Great Village Nova Scotia B0M 1L0 - CANADA - - 00-50-C2 (hex) INSEVIS GmbH - DF3000-DF3FFF (base 16) INSEVIS GmbH - Am Weichselgarten 7 - Erlangen D-91058 - GERMANY - - 00-50-C2 (hex) Potter Electric Signal - DF4000-DF4FFF (base 16) Potter Electric Signal - 1609 Park 370 Place - Hazelwood Missouri 63042 - UNITED STATES - - 00-50-C2 (hex) EtherLight - DF5000-DF5FFF (base 16) EtherLight - 12/11 Soi Prommitr - Sukhumvit 39 - Bangkok 10110 - THAILAND - - 00-50-C2 (hex) HINO ENGINEERING, INC - DF6000-DF6FFF (base 16) HINO ENGINEERING, INC - 60-7 Takakuramachi - Hachiouji Tokyo 192-0033 - JAPAN - - 00-50-C2 (hex) Combilent - DF7000-DF7FFF (base 16) Combilent - Gydevang 21D - Alleroed 3450 - DENMARK - - 00-50-C2 (hex) Tommotek (WA) Pty Ltd. - DF8000-DF8FFF (base 16) Tommotek (WA) Pty Ltd. - 72 Achievement Way - Wangara Western Australia 6065 - AUSTRALIA - - 00-50-C2 (hex) Jenny Science AG - DF9000-DF9FFF (base 16) Jenny Science AG - D4 Platz 4 - Root 6039 - SWITZERLAND - - 00-50-C2 (hex) MAC Valves, Inc. - DFA000-DFAFFF (base 16) MAC Valves, Inc. - 30569 Beck Rd - Wixom MI 48393 - UNITED STATES - - 00-50-C2 (hex) BETTINI SRL - DFB000-DFBFFF (base 16) BETTINI SRL - Via E. H. Grieg, 23 - Saronno Varese 21047 - ITALY - - 00-50-C2 (hex) I-Evo Ltd - DFC000-DFCFFF (base 16) I-Evo Ltd - Henson House - George Stephenson Ind Est - Newcastle Upon Tyne Tyne & Wear NE12 6RZ - UNITED KINGDOM - - 00-50-C2 (hex) Wotbox ltd - DFD000-DFDFFF (base 16) Wotbox ltd - Unit 75 Joseph Wilson Ind Est - Millstrood Road - Whitstable Kent CT5 3PS - UNITED KINGDOM - - 00-50-C2 (hex) Xitek Design Limited - DFE000-DFEFFF (base 16) Xitek Design Limited - 54 Henaghans Road - RD10 - Palmerston North Manawatu 4470 - NEW ZEALAND - - 00-50-C2 (hex) TANTAL ELECTRONICA, SL - DFF000-DFFFFF (base 16) TANTAL ELECTRONICA, SL - Major, 306 - SALT GIRONA 17190 - SPAIN - - 00-50-C2 (hex) Aplex Technology Inc. - E00000-E00FFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn Industrial Park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) Tyco Traffic & Transportation - E01000-E01FFF (base 16) Tyco Traffic & Transportation - 137 McCredie Rd - Guildford NSW 2161 - AUSTRALIA - - 00-50-C2 (hex) Cleverscope - E02000-E02FFF (base 16) Cleverscope - 28 Ranfurly Rd - Epsom - Auckland NI 1023 - NEW ZEALAND - - 00-50-C2 (hex) ICU Scandinavia Schweiz GmbH - E03000-E03FFF (base 16) ICU Scandinavia Schweiz GmbH - Bahnhofstrasse 2 - Signau Bern 3534 - SWITZERLAND - - 00-50-C2 (hex) Sec.Eng Systems Pty Ltd - E04000-E04FFF (base 16) Sec.Eng Systems Pty Ltd - 20/65-75 Captain Cook drive - Caringbah - Sydney NSW 2229 - AUSTRALIA - - 00-50-C2 (hex) NOCOSIUM - E05000-E05FFF (base 16) NOCOSIUM - 15 rue Jules Romains - Vaulx-en-Velin 69120 - FRANCE - - 00-50-C2 (hex) Ebner Electronic GmbH - E06000-E06FFF (base 16) Ebner Electronic GmbH - Neuhofenstrasse 35 - Gmunden Upper 4810 - AUSTRIA - - 00-50-C2 (hex) Protagon Process Technologies GmbH - E07000-E07FFF (base 16) Protagon Process Technologies GmbH - Ringstrasse 11 - Rengsdorf RLP 56579 - GERMANY - - 00-50-C2 (hex) KST Technology - E08000-E08FFF (base 16) KST Technology - KST B/D 164-1,Bangi-dong,Songpa-gu, - Seoul 138-050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) ATEME - E09000-E09FFF (base 16) ATEME - 26 BUROSPACE - Route de Gisy - BIEVRES Cedex 91570 - FRANCE - - 00-50-C2 (hex) Sicon s.r.l. - E0A000-E0AFFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) Seartech - E0B000-E0BFFF (base 16) Seartech - C2 Newlands Plaza - Cnr Lois & Dely Avenue - Newlands Gauteng 0049 - SOUTH AFRICA - - 00-50-C2 (hex) YOUHO ELECTRIC IND.,LTD. - E0C000-E0CFFF (base 16) YOUHO ELECTRIC IND.,LTD. - 800-8,DEOKDO-RI,GWANGJEOK-MYEON, - YANGJOO-SI GYEONGGI-DO 482-843 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Unixmedia Srl - E0D000-E0DFFF (base 16) Unixmedia Srl - Via Cosimo del Fante, 4 - Milano 20122 - ITALY - - 00-50-C2 (hex) PMAC JAPAN - E0E000-E0EFFF (base 16) PMAC JAPAN - Ningyoucho Bldg. 6F - 3-6-7,Nihonbashi Ningyocho - Chuo-ku Tokyo 103-0013 - JAPAN - - 00-50-C2 (hex) Trentino Systems - E0F000-E0FFFF (base 16) Trentino Systems - Damgade 71 - Sonderborg 6400 - DENMARK - - 00-50-C2 (hex) Radinetworks Co., Ltd - E10000-E10FFF (base 16) Radinetworks Co., Ltd - 7F-5, No.229, Fuhsing 2nd Rd - Jubei Hsinchu County 30271 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) RadioMobile Inc - E11000-E11FFF (base 16) RadioMobile Inc - 8801 Kenamar Drive - San Diego CA 92121 - UNITED STATES - - 00-50-C2 (hex) Kago Electronics BV - E12000-E12FFF (base 16) Kago Electronics BV - Molenlei 2-A - Akersloot Noord Holland 1921 CZ - NETHERLANDS - - 00-50-C2 (hex) Automation Assist Japan Company - E13000-E13FFF (base 16) Automation Assist Japan Company - 2-8-20 Kamatahonmachi - Ota Tokyo 144-0053 - JAPAN - - 00-50-C2 (hex) Calixto Systems Pvt Ltd - E14000-E14FFF (base 16) Calixto Systems Pvt Ltd - #111, First Floor, 2H Main Road - Kasturi Nagar - Bangalore Karnataka 560043 - INDIA - - 00-50-C2 (hex) IHI Scube Co.,Ltd - E15000-E15FFF (base 16) IHI Scube Co.,Ltd - Takamatsu-cyo 1-100 - Tachikawa-shi Tokyo 190-0011 - JAPAN - - 00-50-C2 (hex) Jetstream Ltd. - E16000-E16FFF (base 16) Jetstream Ltd. - 97 Granby Street - SAINT VINCENT AND THE GRENADINES - - 00-50-C2 (hex) Gall Tankdatensysteme GmbH - E17000-E17FFF (base 16) Gall Tankdatensysteme GmbH - Schuetzenweg 6 - Knittlingen 75438 - GERMANY - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - E18000-E18FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park, Torch Hi-Tech Development Zone. - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) Zoe Medical - E19000-E19FFF (base 16) Zoe Medical - 460 Boston Street - Topsfield MA 01983 - UNITED STATES - - 00-50-C2 (hex) Rosslare Enterprises Limited - E1A000-E1AFFF (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon 00000 - HONG KONG - - 00-50-C2 (hex) Embedded Labs - E1B000-E1BFFF (base 16) Embedded Labs - Unit 31 Waterford Business Park - Cork Road - Waterford - IRELAND - - 00-50-C2 (hex) Saia-Burgess Controls AG - E1C000-E1CFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Holdline Tecnologia e Sistemas Ltda - E1D000-E1DFFF (base 16) Holdline Tecnologia e Sistemas Ltda - Rua Turfa, 1257 - Barroca - Belo Horizonte Minas Gerais 30430380 - BRAZIL - - 00-50-C2 (hex) Lo-Q plc - E1E000-E1EFFF (base 16) Lo-Q plc - Unit 2, The Pavilions - Ruscombe Park - Twyford RG10 9NN - UNITED KINGDOM - - 00-50-C2 (hex) ELVEES - E1F000-E1FFFF (base 16) ELVEES - Proezd 4922, dom 4, str. 2 - Zelenograd Moscow 124498 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Divelbiss Corporation - E20000-E20FFF (base 16) Divelbiss Corporation - 9778 Mount Gilead Road - Fredericktown OH 43019 - UNITED STATES - - 00-50-C2 (hex) Norwia AS - E21000-E21FFF (base 16) Norwia AS - PO Box 14 - Sandefjord 3201 - NORWAY - - 00-50-C2 (hex) Michael Riedel Transformatorenbau GmbH - E22000-E22FFF (base 16) Michael Riedel Transformatorenbau GmbH - Max-Eyth-Str. 10 - Ilshofen BW 74532 - GERMANY - - 00-50-C2 (hex) VITEC - E23000-E23FFF (base 16) VITEC - 99, rue Pierre Semard - CHATILLON 92320 - FRANCE - - 00-50-C2 (hex) DiTEST Fahrzeugdiagnose GmbH - E24000-E24FFF (base 16) DiTEST Fahrzeugdiagnose GmbH - Alte Poststrasse 152 - Graz Steiermark 8020 - AUSTRIA - - 00-50-C2 (hex) ACD Elektronik GmbH - E25000-E25FFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) Cinetix s.r.l. - E26000-E26FFF (base 16) Cinetix s.r.l. - Via LIsbona 1 - Padova PD 35127 - ITALY - - 00-50-C2 (hex) CONTROL SYSTEMS Srl - E27000-E27FFF (base 16) CONTROL SYSTEMS Srl - Via del Brolo, 14 - Cremona CR 26100 - ITALY - - 00-50-C2 (hex) Teplovodokhran - E28000-E28FFF (base 16) Teplovodokhran - Novaya, 51v - Ryazan 390027 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Fr. Sauter AG - E29000-E29FFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS 4016 - SWITZERLAND - - 00-50-C2 (hex) Rohde&Schwarz Topex SA - E2A000-E2AFFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacu Street, district 1, - Bucharest Romania 014186 - ROMANIA - - 00-50-C2 (hex) Plant Integrity Limited - E2B000-E2BFFF (base 16) Plant Integrity Limited - Granta Park - Great Abington - Cambridge Cambridgeshire CB21 6AL - UNITED KINGDOM - - 00-50-C2 (hex) EN ElectronicNetwork Hamburg GmbH - E2C000-E2CFFF (base 16) EN ElectronicNetwork Hamburg GmbH - Meiendorfer Strasse 205 - Hamburg 22145 - GERMANY - - 00-50-C2 (hex) Funkwerk IT Karlsfeld GmbH - E2D000-E2DFFF (base 16) Funkwerk IT Karlsfeld GmbH - Liebigstrasse 1a - Karlsfeld Bavaria 85757 - GERMANY - - 00-50-C2 (hex) DS! Ingenieurbuero - E2E000-E2EFFF (base 16) DS! Ingenieurbuero - Fuchsweg 17 - Elchingen 89275 - GERMANY - - 00-50-C2 (hex) Beam Ltd - E2F000-E2FFFF (base 16) Beam Ltd - Northavon Buisness Centre - Dean Road - Yate South Gloucestershire BS37 5NH - UNITED KINGDOM - - 00-50-C2 (hex) Goennheimer Elektronic GmbH - E30000-E30FFF (base 16) Goennheimer Elektronic GmbH - Dr. Julius leber Str. 2 - Neustadt 67433 - GERMANY - - 00-50-C2 (hex) ENSIS Co., Ltd. - E31000-E31FFF (base 16) ENSIS Co., Ltd. - 506-508 Doosanventuredigm, 1307-37 - Gwanyang-2dong - Dongan-gu Anyang 431-810 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Oshoksh Corporation - E32000-E32FFF (base 16) Oshoksh Corporation - 2307 Oregon Street - Oshkosh WI 54902 - UNITED STATES - - 00-50-C2 (hex) Morita Technical Center Company - E33000-E33FFF (base 16) Morita Technical Center Company - 3-8-1, Kurigidai, Asao-ku, Kawasaki-shi, - Kanagawa 215-0032 - JAPAN - - 00-50-C2 (hex) HGL Dynamics - E34000-E34FFF (base 16) HGL Dynamics - Hamilton Barr House - Bridge Mews - GODALMING Surrey GU7 1HZ - UNITED KINGDOM - - 00-50-C2 (hex) Omnica Corporation - E35000-E35FFF (base 16) Omnica Corporation - 15560-D Rockfield Blvd. - Irvine CA 92618 - UNITED STATES - - 00-50-C2 (hex) Saia-Burgess Controls AG - E36000-E36FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) FUJI DATA SYSTEM Co., Ltd - E37000-E37FFF (base 16) FUJI DATA SYSTEM Co., Ltd - 5-21-14 - HIGASHINANIWA-Cho - AMAGASAKI-Shi HYOGO Pref. 660-0892 - JAPAN - - 00-50-C2 (hex) Aesir Copenhagen - E38000-E38FFF (base 16) Aesir Copenhagen - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - 00-50-C2 (hex) Telemetrics Inc. - E39000-E39FFF (base 16) Telemetrics Inc. - 6 LEIGHTON PL - MAHWAH NJ 074303198 - UNITED STATES - - 00-50-C2 (hex) Vocality International - E3A000-E3AFFF (base 16) Vocality International - Lydling Barn - Puttenham lane - Shackleford Surrey gu86ap - UNITED KINGDOM - - 00-50-C2 (hex) Nanosolution Inc. - E3B000-E3BFFF (base 16) Nanosolution Inc. - Room 110, Woolim Lions Valley - 311-3 Sangdaewon-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-806 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Grupo Epelsa S.L. - E3C000-E3CFFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) Baudisch Electronic GmbH - E3D000-E3DFFF (base 16) Baudisch Electronic GmbH - Im Gewerbegebiet 7-9 - Wäschenbeuren Baden-Württemberg 73116 - GERMANY - - 00-50-C2 (hex) Monnit Corp. - E3E000-E3EFFF (base 16) Monnit Corp. - 450 South Simmons Way - Suite 670 - Kaysville UT 84037 - UNITED STATES - - 00-50-C2 (hex) VISITO S.R.L. - E3F000-E3FFFF (base 16) VISITO S.R.L. - Corso Duca Degli Abruzzi 2 - 10128 - TORINO - ITALY - - 00-50-C2 (hex) Ecrin Systems - E40000-E40FFF (base 16) Ecrin Systems - 143 Rue Louis Neel - Crolles Isère 38920 - FRANCE - - 00-50-C2 (hex) Higeco S.r.l. - E41000-E41FFF (base 16) Higeco S.r.l. - Via Cal De Formiga 12 - Santa Giustina Veneto 32035 - ITALY - - 00-50-C2 (hex) Wings for Media SL - E42000-E42FFF (base 16) Wings for Media SL - C/Rosari 47 4º 1ª - Barcelona 08017 - SPAIN - - 00-50-C2 (hex) Technica Engineering GmbH - E43000-E43FFF (base 16) Technica Engineering GmbH - Olschewskibogen 18 - Munich Bayern 80935 - GERMANY - - 00-50-C2 (hex) DEUTA-WERKE GmbH - E44000-E44FFF (base 16) DEUTA-WERKE GmbH - Paffrather Strasse 140 - Bergisch Gladbach Northrhine Westfalia 51465 - GERMANY - - 00-50-C2 (hex) Stichting Sunrise - E45000-E45FFF (base 16) Stichting Sunrise - Daltonstraat 51 - DEN Haag Zuid Holland 2561 SR - NETHERLANDS - - 00-50-C2 (hex) Industrea Mining Technology - E46000-E46FFF (base 16) Industrea Mining Technology - 3 Co-Wyn Close - Fountaindale NSW 2258 - AUSTRALIA - - 00-50-C2 (hex) ENIKA.CZ - E47000-E47FFF (base 16) ENIKA.CZ - Nadrazni 609 - Nova Paka 50901 - CZECH REPUBLIC - - 00-50-C2 (hex) ITW Reyflex North America - E48000-E48FFF (base 16) ITW Reyflex North America - 195 E Algonquin Road - Des Plaines IL 60090 - UNITED STATES - - 00-50-C2 (hex) CTF TECHNOLOGIES DO BRASIL LTDA - E49000-E49FFF (base 16) CTF TECHNOLOGIES DO BRASIL LTDA - AV. IMPERATRIZ LEOPOLDINA, 1661 - VILA HAMBURGUESA - São Paulo 05305-007 - BRAZIL - - 00-50-C2 (hex) GHL Systems Bhd - E4A000-E4AFFF (base 16) GHL Systems Bhd - L5-E-7B, Enterprise 4 - Technology Park Malaysia - Bukit Jalil Kuala Lumpur 57000 - MALAYSIA - - 00-50-C2 (hex) Rohde&Schwarz Topex SA - E4B000-E4BFFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacu Street, district 1, - Bucharest Romania 014186 - ROMANIA - - 00-50-C2 (hex) Applied Micro Electronics "AME" BV - E4C000-E4CFFF (base 16) Applied Micro Electronics "AME" BV - Esp 100 - Eindhoven Noord Brabant 5633 AA - NETHERLANDS - - 00-50-C2 (hex) PCSC - E4D000-E4DFFF (base 16) PCSC - 3541 Challenger St - Torrance CA 90503 - UNITED STATES - - 00-50-C2 (hex) Institute For Information Industry - E4E000-E4EFFF (base 16) Institute For Information Industry - 7F., No.133, Sec. 4, Minsheng E. Rd. - Songshan Dist. - Taipei City 105 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Wine Technology Marlborough - E4F000-E4FFFF (base 16) Wine Technology Marlborough - 28 High Street - PO Box 87 - Renwick Marlborough 7204 - NEW ZEALAND - - 00-50-C2 (hex) Tattile srl - E50000-E50FFF (base 16) Tattile srl - via Donizetti 1/3/5 - Mairano BS 25030 - ITALY - - 00-50-C2 (hex) Motec Pty Ltd - E51000-E51FFF (base 16) Motec Pty Ltd - 121 Merrindale Drive - Croydon South Victoria 3136 - AUSTRALIA - - 00-50-C2 (hex) Famas System S.p.A. - E52000-E52FFF (base 16) Famas System S.p.A. - Via degli artigiani sud, 19 - Egna BZ 39044 - ITALY - - 00-50-C2 (hex) NEXT video systems Hard- and Software Development GmbH - E53000-E53FFF (base 16) NEXT video systems Hard- and Software Development GmbH - Oderstr. 47 - Neumuenster SH 24539 - GERMANY - - 00-50-C2 (hex) Arcos Technologies LTD - E54000-E54FFF (base 16) Arcos Technologies LTD - 26 Hasivim St. - Petach-Tikva Israel 49517 - ISRAEL - - 00-50-C2 (hex) TTi Ltd - E55000-E55FFF (base 16) TTi Ltd - Glebe Road - Huntingdon Cambridgeshire PE29 7DR - UNITED KINGDOM - - 00-50-C2 (hex) RFENGINE CO., LTD. - E56000-E56FFF (base 16) RFENGINE CO., LTD. - 2/809, ITCASTLE, 550-1 GASAN-DONG - GEUMCHEON-GU - SEOUL 153-768 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) EOLANE MONTCEAU - E57000-E57FFF (base 16) EOLANE MONTCEAU - ZI STE ELIZABETH - MONTCEAU LES MINES SA 71300 - FRANCE - - 00-50-C2 (hex) Agri-hitech LLC - E58000-E58FFF (base 16) Agri-hitech LLC - 599-20 - Matoba - Kawagoe Saitama 3501101 - JAPAN - - 00-50-C2 (hex) Saia-Burgess Controls AG - E59000-E59FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) FUTEC INC. - E5A000-E5AFFF (base 16) FUTEC INC. - 1217 Hayashi-cho - Takamatushi Kagawa 7610301 - JAPAN - - 00-50-C2 (hex) CAIPO Automazione Industriale s.r.l. - E5B000-E5BFFF (base 16) CAIPO Automazione Industriale s.r.l. - Fraz. Violetto, 39 - Valle Mosso Biella 13825 - ITALY - - 00-50-C2 (hex) MCOPIA Co., Ltd - E5C000-E5CFFF (base 16) MCOPIA Co., Ltd - 4th Floor, Jinhyun Building, Neong-dong, 246-2, Kwangjin-Gu - SEOUL 143-849 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) T8 Ltd - E5D000-E5DFFF (base 16) T8 Ltd - Krasnobogatyrskaya str., 44/1 - Moscow Moscow 107076 - RUSSIAN FEDERATION - - 00-50-C2 (hex) OREP - E5E000-E5EFFF (base 16) OREP - 39 AVENUE SIDOINE APOLLINAIRE - LYON 69009 - FRANCE - - 00-50-C2 (hex) Pantec Engineering AG - E5F000-E5FFFF (base 16) Pantec Engineering AG - Inustriering 21 - Ruggell Principality of Liechtenstein 9491 - LIECHTENSTEIN - - 00-50-C2 (hex) TAIYO SEIKI CO.,LTD. - E60000-E60FFF (base 16) TAIYO SEIKI CO.,LTD. - 1600 Aza-Shironoshita Asahi - Shin Asahi-cho Takashima, Shiga 520-1501 - JAPAN - - 00-50-C2 (hex) Detech Electronics ApS - E61000-E61FFF (base 16) Detech Electronics ApS - Oestervej 11 - Ullerslev Funen 5540 - DENMARK - - 00-50-C2 (hex) SAE IT-systems GmbH & Co. KG - E62000-E62FFF (base 16) SAE IT-systems GmbH & Co. KG - Im Gewerbegebiet Pesch 14 - Köln NRW 50767 - GERMANY - - 00-50-C2 (hex) Prima sistemi - E63000-E63FFF (base 16) Prima sistemi - Å orlijeva 7 - Kranj Gorenjska 4000 - SLOVENIA - - 00-50-C2 (hex) Edgeware AB - E64000-E64FFF (base 16) Edgeware AB - Master Samuelsgatan 56 - Stockholm 11121 - SWEDEN - - 00-50-C2 (hex) IB Elektronik GmbH - E65000-E65FFF (base 16) IB Elektronik GmbH - Daimlerstraße 51 - Karlsruhe Baden-Württemberg 76185 - GERMANY - - 00-50-C2 (hex) EMAC, Inc. - E66000-E66FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 00-50-C2 (hex) Critical Link, LLC - E67000-E67FFF (base 16) Critical Link, LLC - 6712 Brooklawn Parkway - Syracuse NY 13211 - UNITED STATES - - 00-50-C2 (hex) Kyoritsu Electric Corporation - E68000-E68FFF (base 16) Kyoritsu Electric Corporation - 61-1 NAKADAHONCHO - SURUGA-KU - SHIZUOKA-SHI SHIZUOKA-KEN 422-8686 - JAPAN - - 00-50-C2 (hex) Netmaker - E69000-E69FFF (base 16) Netmaker - Mega Valley SB111,Gwanyang2,Dongan, - Anyang Gyeonggi 431-767 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Aplex Technology Inc. - E6A000-E6AFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn Industrial Park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) Sika Technology AG - E6B000-E6BFFF (base 16) Sika Technology AG - Tüffenwies 16 - Zürich ZH 8048 - SWITZERLAND - - 00-50-C2 (hex) SAMSUNG Electronics Co.,Ltd.(LED Division) - E6C000-E6CFFF (base 16) SAMSUNG Electronics Co.,Ltd.(LED Division) - San #24 Nongseo-Dong - Giheung-Gu - Yongin-City, Suwon-City Gyeonggi-do 446-711 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Allerta Inc - E6D000-E6DFFF (base 16) Allerta Inc - 314 Batavia Pl - Waterloo ON N2L3W2 - CANADA - - 00-50-C2 (hex) Power-One Italia S.p.A - E6E000-E6EFFF (base 16) Power-One Italia S.p.A - Via San Giorgio 642 - Terranuova Bracciolini Arezzo 52028 - ITALY - - 00-50-C2 (hex) Leyden Engineering - E6F000-E6FFFF (base 16) Leyden Engineering - PO Box 1193 - San Luis Obispo CA 93406 - UNITED STATES - - 00-50-C2 (hex) DORLET S.A. - E70000-E70FFF (base 16) DORLET S.A. - C/ Albert Einstein 34 - Parque Tecnologico de Alava - Miñano Mayor Alava 01510 - SPAIN - - 00-50-C2 (hex) traffic network solutions s.l - E71000-E71FFF (base 16) traffic network solutions s.l - Bruc 120, pral 1ºB - 08009 - Barcelona 08009 - SPAIN - - 00-50-C2 (hex) ACS Motion Control Ltd. - E73000-E73FFF (base 16) ACS Motion Control Ltd. - Ramat Gabriel Industrial Park - POB 5668 - Migdal Ha'Emek 10500 - ISRAEL - - 00-50-C2 (hex) Will corp. - E74000-E74FFF (base 16) Will corp. - 3-1-47 - Fukaminishi - Yamato city Kanagawa pref. 242-0018 - JAPAN - - 00-50-C2 (hex) FSM AG - E75000-E75FFF (base 16) FSM AG - Scheffelstraße 49 - Kirchzarten Baden-Württemberg 79199 - GERMANY - - 00-50-C2 (hex) Embedded Solution Bank Co., Ltd. - E76000-E76FFF (base 16) Embedded Solution Bank Co., Ltd. - #905 A, Woolim Lions Valley 5, 144-3 - Sangdaewon-dong - Seongnam-Si Kyunggi-Do 462-120 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Fr. Sauter AG - E77000-E77FFF (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS 4016 - SWITZERLAND - - 00-50-C2 (hex) TASK SISTEMAS DE COMPUTACAO LTDA - E78000-E78FFF (base 16) TASK SISTEMAS DE COMPUTACAO LTDA - Rua 2 / 112 Jardim - Itatiaia Rio de Janeiro 27580-000 - BRAZIL - - 00-50-C2 (hex) MCS MICRONIC Computer Systeme GmbH - E79000-E79FFF (base 16) MCS MICRONIC Computer Systeme GmbH - Ullsteinstrasse 114, Tower C - Berlin 12109 - GERMANY - - 00-50-C2 (hex) Lightel - E7A000-E7AFFF (base 16) Lightel - 2210 Lind Ave SW. Suite 100 - Renton WA 98057 - UNITED STATES - - 00-50-C2 (hex) ATOM GIKEN Co.,Ltd. - E7B000-E7BFFF (base 16) ATOM GIKEN Co.,Ltd. - 92-2 KATASE - FUJISAWA KANAGAWA 251-0032 - JAPAN - - 00-50-C2 (hex) sp controls, inc - E7C000-E7CFFF (base 16) sp controls, inc - 930 linden ave - south san francisco ca 94080 - UNITED STATES - - 00-50-C2 (hex) AEL Microsystems Limited - E7D000-E7DFFF (base 16) AEL Microsystems Limited - 12 Pixiefield - Cradley - Malvern Worcestershire WR13 5ND - UNITED KINGDOM - - 00-50-C2 (hex) Swareflex GmbH - E7E000-E7EFFF (base 16) Swareflex GmbH - Josef-Heiss-Straße 1 - Vomp Tyrol 6134 - AUSTRIA - - 00-50-C2 (hex) LS Control A/S - E7F000-E7FFFF (base 16) LS Control A/S - Indrustivej 12 - Gelsted Herlufmagle DK-4160 - DENMARK - - 00-50-C2 (hex) Saia-Burgess Controls AG - E80000-E80FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Adaptive Technologies, Inc. - E81000-E81FFF (base 16) Adaptive Technologies, Inc. - 2020 Kraft Drive - Suite 3040 - Blacksburg VA 24060 - UNITED STATES - - 00-50-C2 (hex) Xplore Technologies Corp - E82000-E82FFF (base 16) Xplore Technologies Corp - 14000 Sumit Dr - Suite 900 - Austin TX 78728 - UNITED STATES - - 00-50-C2 (hex) Witree Co.,Ltd - E83000-E83FFF (base 16) Witree Co.,Ltd - 621 Hyundai venture ville, 713 Suseo-dong, Gangnam-gu - Seoul 135-539 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - E84000-E84FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industrial Park, Torch Hi-Tech Development Zone. - Xiao Dong Shan,Xiamen - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) Cosmo Life Co.,Ltd - E85000-E85FFF (base 16) Cosmo Life Co.,Ltd - Kounan2-16-7 - Shinagawa V-Tower 519 - Minato-ku Tokyo 108-0075 - JAPAN - - 00-50-C2 (hex) Multisuns Corporation - E86000-E86FFF (base 16) Multisuns Corporation - 12F, No. 19-3, San Chung Road, - Nankang Dist. - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Lamson Safes & Security - E87000-E87FFF (base 16) Lamson Safes & Security - 3-5 Awun Court - Springvale Victoria - AUSTRALIA - - 00-50-C2 (hex) Pivitec, LLC - E88000-E88FFF (base 16) Pivitec, LLC - 116 Research Dr. - Ste. 2208 - Bethlehem PA 18015 - UNITED STATES - - 00-50-C2 (hex) PROTEQSEN - E89000-E89FFF (base 16) PROTEQSEN - Av. Gov. Amaral Peixoto, 800 - Centro - Nova Iguacu Rio de Janeiro 26210-060 - BRAZIL - - 00-50-C2 (hex) Macronet s.r.l. - E8A000-E8AFFF (base 16) Macronet s.r.l. - Alsina 2965 - Buenos Aires 1207 - ARGENTINA - - 00-50-C2 (hex) RPA Electronic Solutions, Inc. - E8B000-E8BFFF (base 16) RPA Electronic Solutions, Inc. - 1285 Chenango St. - Binghamton New York 13901 - UNITED STATES - - 00-50-C2 (hex) Epec Oy - E8C000-E8CFFF (base 16) Epec Oy - P.O. Box 194 - Tiedekatu 6 - Seinäjoki 60101 - FINLAND - - 00-50-C2 (hex) SystemAdvanced Co,Ltd - E8D000-E8DFFF (base 16) SystemAdvanced Co,Ltd - Adachi 1-9-3 - Adachi-Ku Tokyo 1200015 - JAPAN - - 00-50-C2 (hex) GENERAL DYNAMICS C4 SYSTEMS - E8E000-E8EFFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST. MD: R1115 - SCOTTSDALE AZ 85257 - UNITED STATES - - 00-50-C2 (hex) STT Condigi A/S - E8F000-E8FFFF (base 16) STT Condigi A/S - Niels Bohrs vej 42, - Stilling Skanderborg 8660 - DENMARK - - 00-50-C2 (hex) GS Elektromedizinische Geraete G. Stemple GmbH - E90000-E90FFF (base 16) GS Elektromedizinische Geraete G. Stemple GmbH - Hauswiesenstr. 26 - Kaufering Bayern 86916 - GERMANY - - 00-50-C2 (hex) DSP DESIGN LTD - E91000-E91FFF (base 16) DSP DESIGN LTD - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) CT Company - E92000-E92FFF (base 16) CT Company - Nizhni Krasnoselsky st.,35 - Moscow 140070 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Perceptive Pixel Inc. - E93000-E93FFF (base 16) Perceptive Pixel Inc. - 102 Madison Ave. - 12th Floor - New York NY 10016 - UNITED STATES - - 00-50-C2 (hex) ANA-U GmbH - E94000-E94FFF (base 16) ANA-U GmbH - Moosgrabenstrasse 32 - Gleisdorf Steiermark 8200 - AUSTRIA - - 00-50-C2 (hex) Dlite Comercio, Importadora e Serviços de Automação Ltda - E95000-E95FFF (base 16) Dlite Comercio, Importadora e Serviços de Automação Ltda - 423, Rocio Street cj1811 - São Paulo 04552 000 - BRAZIL - - 00-50-C2 (hex) PROYECSON S.A. - E96000-E96FFF (base 16) PROYECSON S.A. - RONDA GUGLIELMO MARCONI Nº4 - PARQUE TECNOLOGICO - PATERNA VALENCIA 46980 - SPAIN - - 00-50-C2 (hex) Arista Systems Corporation - E97000-E97FFF (base 16) Arista Systems Corporation - 5th Floor,No.82-8,GuangFu Road,Sec. 1 - San Chung Taipei 241 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) i3 International Inc. - E98000-E98FFF (base 16) i3 International Inc. - 780 Birchmount Road - Unit 16 - Toronto Ontario M1K5H4 - CANADA - - 00-50-C2 (hex) UV Networks, Inc. - E99000-E99FFF (base 16) UV Networks, Inc. - 20370 Town Center Lane, Suite 150 - Cupertino CA 95014 - UNITED STATES - - 00-50-C2 (hex) Solace Systems - E9A000-E9AFFF (base 16) Solace Systems - 535 Legget Drive - 3rd Floor - Kanata, Ontario K2K 3B8 - CANADA - - 00-50-C2 (hex) Hentschel System GmbH - E9B000-E9BFFF (base 16) Hentschel System GmbH - Carl-Buderus-Str. 5 - Hannover Lower Saxony 30455 - GERMANY - - 00-50-C2 (hex) SPARQ systems - E9C000-E9CFFF (base 16) SPARQ systems - 166 barrie st - kingston ontario k7l3n6 - CANADA - - 00-50-C2 (hex) nicai-systems - E9D000-E9DFFF (base 16) nicai-systems - Am Denkmal 8 - Stolberg NRW 52223 - GERMANY - - 00-50-C2 (hex) American Microsystems, Ltd. - E9E000-E9EFFF (base 16) American Microsystems, Ltd. - 2190 Regal Parkway - Euless TX 76040 - UNITED STATES - - 00-50-C2 (hex) DataSoft Corporation - E9F000-E9FFFF (base 16) DataSoft Corporation - 1475 N. Scottsdale Road - Suite 460 - Scottsdale AZ 85257 - UNITED STATES - - 00-50-C2 (hex) Robert Bosch Healthcare, Inc. - EA0000-EA0FFF (base 16) Robert Bosch Healthcare, Inc. - 2400 Geng Road - Suite. 200 - Palo Alto CA 94303 - UNITED STATES - - 00-50-C2 (hex) TEX COMPUTER SRL - EA1000-EA1FFF (base 16) TEX COMPUTER SRL - VIA MERCADANTE 35 - CATTOLICA RIMINI 47841 - ITALY - - 00-50-C2 (hex) ThinkRF Corp - EA2000-EA2FFF (base 16) ThinkRF Corp - 390 Legget Drive - Suite 110 - Ottawa Ontario K2K 0G7 - CANADA - - 00-50-C2 (hex) Subsea Systems, Inc. - EA3000-EA3FFF (base 16) Subsea Systems, Inc. - 2290 Eastman Avenue - Suite 111 - Ventura CA 93003 - UNITED STATES - - 00-50-C2 (hex) head - EA4000-EA4FFF (base 16) head - kita-ku tenjinbashi 2-2-25 - taniguchi bld 302 - Osaka-shi Osaka 5300041 - JAPAN - - 00-50-C2 (hex) Aerodata AG - EA5000-EA5FFF (base 16) Aerodata AG - Hermann-Blenk-Strasse 36 - Braunschweig Niedersachsen 38108 - GERMANY - - 00-50-C2 (hex) Powersense A/S - EA6000-EA6FFF (base 16) Powersense A/S - Skovlytoften 33 - Holte 2840 - DENMARK - - 00-50-C2 (hex) Saia-Burgess Controls AG - EA7000-EA7FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) MB Connect Line GmbH - EA8000-EA8FFF (base 16) MB Connect Line GmbH - Winnettener Straße 5 - Dinkelsbühl Bavaria 91550 - GERMANY - - 00-50-C2 (hex) METTLER-TOLEDO HI-SPEED - EA9000-EA9FFF (base 16) METTLER-TOLEDO HI-SPEED - 5 BARR ROAD - ITHACA NY 14850 - UNITED STATES - - 00-50-C2 (hex) BAE Systems - EAA000-EAAFFF (base 16) BAE Systems - 65 Spir Brook Rd. - Nashua New Hamshire 03060 - UNITED STATES - - 00-50-C2 (hex) Warp9 Tech Design, Inc. - EAB000-EABFFF (base 16) Warp9 Tech Design, Inc. - 3650 Pheasant Run N.E. - Blaine MN 55449 - UNITED STATES - - 00-50-C2 (hex) Alias ip - EAC000-EACFFF (base 16) Alias ip - 300 ROUTE DES CRETES - ESPACES ANTIPOLIS - SOPHIA ANTIPOLIS ALPES-MARITIMES 06560 - FRANCE - - 00-50-C2 (hex) Rohde&Schwarz Topex SA - EAD000-EADFFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacu Street, district 1, code 014186 - Bucharest Romania 014186 - ROMANIA - - 00-50-C2 (hex) Alyrica Networks - EAE000-EAEFFF (base 16) Alyrica Networks - 521B N 19th ST - Philomath OREGON 97370 - UNITED STATES - - 00-50-C2 (hex) Aircell - EAF000-EAFFFF (base 16) Aircell - 303 S. Technology Ct. - Building A - Broomfield Co 80021 - UNITED STATES - - 00-50-C2 (hex) Pulse Communication Systems Pvt. Ltd. - EB0000-EB0FFF (base 16) Pulse Communication Systems Pvt. Ltd. - F-90/22 - Okhla Phase 1 - New Delhi Delhi 110020 - INDIA - - 00-50-C2 (hex) PDU EXPERT UK LTD - EB1000-EB1FFF (base 16) PDU EXPERT UK LTD - 11 b THE CHERRIES - SLOUGH SL2 5TS - UNITED KINGDOM - - 00-50-C2 (hex) Otaki Electric Corporation - EB2000-EB2FFF (base 16) Otaki Electric Corporation - 6-6,Aza-Kamibukuro,Syakanai - Ohdate Akita 017-0012 - JAPAN - - 00-50-C2 (hex) AR RF/Microwave Instrumentation - EB3000-EB3FFF (base 16) AR RF/Microwave Instrumentation - 160 School House Road - Souderton PA 18964 - UNITED STATES - - 00-50-C2 (hex) Wishtek Technology, Inc. - EB4000-EB4FFF (base 16) Wishtek Technology, Inc. - 10F., No. 178-1, Syuecin Rd., Sansia Dist., - New Taipei 23741 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Covidence A/S - EB5000-EB5FFF (base 16) Covidence A/S - Strandvejen 2A - Roende 8410 - DENMARK - - 00-50-C2 (hex) Monsoon Solutions, Inc. - EB6000-EB6FFF (base 16) Monsoon Solutions, Inc. - 2405 140th Ave NE - Suite A115 - Bellevue WA 98005 - UNITED STATES - - 00-50-C2 (hex) Saab AB - EB7000-EB7FFF (base 16) Saab AB - Nobymalmsvägen - Linköping Östergötland 58182 - SWEDEN - - 00-50-C2 (hex) dspnor - EB8000-EB8FFF (base 16) dspnor - Vaagsgaten 22 - Bergen Hordaland 5162 - NORWAY - - 00-50-C2 (hex) ALPHA-MOS - EB9000-EB9FFF (base 16) ALPHA-MOS - 20 Avenue Didier Daurat - Toulouse 31400 - FRANCE - - 00-50-C2 (hex) West-Com Nurse Call Systems, Inc. - EBA000-EBAFFF (base 16) West-Com Nurse Call Systems, Inc. - 2200 Cordelia Road - Fairfield CA 94534 - UNITED STATES - - 00-50-C2 (hex) TimeTerminal Adductor Group AB - EBB000-EBBFFF (base 16) TimeTerminal Adductor Group AB - Hammarbacken 4 A - Sollentuna SE-19149 - SWEDEN - - 00-50-C2 (hex) Diehl AKO Stiftung & Co. KG - EBC000-EBCFFF (base 16) Diehl AKO Stiftung & Co. KG - Pfannerstr. 75 - Wangen 88239 - GERMANY - - 00-50-C2 (hex) Droplet Measurement Technologies - EBD000-EBDFFF (base 16) Droplet Measurement Technologies - 2545 Central Avenue - Boulder CO 80301 - UNITED STATES - - 00-50-C2 (hex) Global Tecnologia LTDA. - EBE000-EBEFFF (base 16) Global Tecnologia LTDA. - Av. das Araucárias, n.2558 - Araucária PR 81530-020 - BRAZIL - - 00-50-C2 (hex) CIVOLUTION - EBF000-EBFFFF (base 16) CIVOLUTION - HIGH TECH CAMPUS 9 - EINDHOVEN 5656 AE - NETHERLANDS - - 00-50-C2 (hex) UgMO Technologies - EC0000-EC0FFF (base 16) UgMO Technologies - 840 First Avenue - Suite 300 - King of Prussia PA 19406 - UNITED STATES - - 00-50-C2 (hex) ANT Group s.r.l - EC1000-EC1FFF (base 16) ANT Group s.r.l - Via Giroli 76 - Gavardo (BS) 25085 - ITALY - - 00-50-C2 (hex) Ixonos Plc - EC2000-EC2FFF (base 16) Ixonos Plc - Hitsaajankatu 24 - P.O.Box 284 - Helsinki FI-00811 - FINLAND - - 00-50-C2 (hex) Aplex Technology Inc. - EC3000-EC3FFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn Industrial Park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) Logical Electromechanical Sys Inc. - EC4000-EC4FFF (base 16) Logical Electromechanical Sys Inc. - 885 Freemanwood Lane - Alpharetta GA 30004 - UNITED STATES - - 00-50-C2 (hex) RSUPPORT Co., Ltd. - EC5000-EC5FFF (base 16) RSUPPORT Co., Ltd. - 45, Bangi2-dong, Songpa-gu - 15/16F, Hanmi Bldg - Seoul Soul-t|ukpyolsi 138724 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) INFRONICS SYSTEMS LIMITED - EC6000-EC6FFF (base 16) INFRONICS SYSTEMS LIMITED - PLOT NO: 2 & 3, EKTHA TOWERS - WHITE FIELDS, KONDAPUR - HYDERABAD ANDHRA PRADESH 500084 - INDIA - - 00-50-C2 (hex) LIQUID ROBOTICS, INC - EC7000-EC7FFF (base 16) LIQUID ROBOTICS, INC - 1329 MOFFETT PARK DRIVE - SUNNYVALE CA 94089 - UNITED STATES - - 00-50-C2 (hex) IBERNEX INGENIERIA, S.L. - EC8000-EC8FFF (base 16) IBERNEX INGENIERIA, S.L. - Carretera de Cogullada, 11 - ZARAGOZA Zaragoza 50011 - SPAIN - - 00-50-C2 (hex) Amsterdam Scientific Instruments BV - EC9000-EC9FFF (base 16) Amsterdam Scientific Instruments BV - Science Park 105 - Amsterdam 1098XG - NETHERLANDS - - 00-50-C2 (hex) BitWise Controls - ECA000-ECAFFF (base 16) BitWise Controls - 98 Inverness Dr East - Englewood CO 80112 - UNITED STATES - - 00-50-C2 (hex) FAL Corp - ECB000-ECBFFF (base 16) FAL Corp - 205 3-7-2 - Higashitateishi - Katsushikaku Tokyo 124-0013 - JAPAN - - 00-50-C2 (hex) Saia-Burgess Controls AG - ECC000-ECCFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Peek Traffic Corporation - ECD000-ECDFFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Florida 34221 - UNITED STATES - - 00-50-C2 (hex) easii ic adiis - ECE000-ECEFFF (base 16) easii ic adiis - 90 avenue leon blum - bp2612 - grenoble isere 38036 - FRANCE - - 00-50-C2 (hex) TAIWAN HIPLUS CORPORATION - ECF000-ECFFFF (base 16) TAIWAN HIPLUS CORPORATION - 13F-9 NO.2 CHENG PA RD. ZHONGHE DIST., - NEW TAIPEI 23511 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Nippon Systemware Co.,Ltd. - ED0000-ED0FFF (base 16) Nippon Systemware Co.,Ltd. - Shibuya Office 9F - 2-15, Nanpeidai-cho - Shibuya-ku Tokyo 150-0036 - JAPAN - - 00-50-C2 (hex) Arcontia Technology AB - ED1000-ED1FFF (base 16) Arcontia Technology AB - Gruvgatan 35A - Vastra Frolunda 42130 - SWEDEN - - 00-50-C2 (hex) Klangspektrum GmbH - ED2000-ED2FFF (base 16) Klangspektrum GmbH - Postweg 14 - Erwitte NRW 59597 - GERMANY - - 00-50-C2 (hex) ECO MONITORING UTILITY SYSTEMS LTD - ED3000-ED3FFF (base 16) ECO MONITORING UTILITY SYSTEMS LTD - ST BEDES CHAMBERS - ALBERT ROAD - JARROW TYNE AND WEAR NE32 5JU - UNITED KINGDOM - - 00-50-C2 (hex) TAMAGAWA ELECTRONICS CO.,LTD. - ED4000-ED4FFF (base 16) TAMAGAWA ELECTRONICS CO.,LTD. - 3-11-23 Kamitsuchidana-naka - Ayase-shi Kanagawa 252-1113 - JAPAN - - 00-50-C2 (hex) RFL Electronics Inc. - ED5000-ED5FFF (base 16) RFL Electronics Inc. - 353 Powerville Road - Boonton Township NJ 07005 - UNITED STATES - - 00-50-C2 (hex) Cat AB - ED6000-ED6FFF (base 16) Cat AB - P.o. box 2038 - Skvadronsbacken 64B - Sundbyberg SE-174 02 - SWEDEN - - 00-50-C2 (hex) FBT Elettronica spa - ED7000-ED7FFF (base 16) FBT Elettronica spa - Via P. Soprani 1 - Recanati Macerata 62019 - ITALY - - 00-50-C2 (hex) AVocation Systems, Inc. - ED8000-ED8FFF (base 16) AVocation Systems, Inc. - 7130 W. 117th Ave. - Suite D-3 - Broomfield CO 80020 - UNITED STATES - - 00-50-C2 (hex) Plasmatronics pty ltd - ED9000-ED9FFF (base 16) Plasmatronics pty ltd - 75 Newman Street - Thornbury Victoria 3071 - AUSTRALIA - - 00-50-C2 (hex) Joint Stock Company "Svyaz Inginiring M" - EDA000-EDAFFF (base 16) Joint Stock Company "Svyaz Inginiring M" - 42, Varshavskoye Shosse, - Moscow region 115230 - RUSSIAN FEDERATION - - 00-50-C2 (hex) BELIK S.P.R.L. - EDB000-EDBFFF (base 16) BELIK S.P.R.L. - Rue du Roussart 147 - Waterloo Brabant 1410 - BELGIUM - - 00-50-C2 (hex) Eyelock Corporation - EDC000-EDCFFF (base 16) Eyelock Corporation - 355 Lexington Ave - Fl 12 - New York New York 10017 - UNITED STATES - - 00-50-C2 (hex) EBNEURO SPA - EDD000-EDDFFF (base 16) EBNEURO SPA - VIA PIETRO FANFANI 97/A - FIRENZE 50127 - ITALY - - 00-50-C2 (hex) Smart Grid Networks - EDE000-EDEFFF (base 16) Smart Grid Networks - Rombvagen 7 - Lyckeby Blekinge 37165 - SWEDEN - - 00-50-C2 (hex) Monitor Business Machines - EDF000-EDFFFF (base 16) Monitor Business Machines - 56-58 Grafton Road - Grafton - Auckland 1035 - NEW ZEALAND - - 00-50-C2 (hex) osf Hansjuergen Meier GmbH & Co. KG - EE0000-EE0FFF (base 16) osf Hansjuergen Meier GmbH & Co. KG - Eichendorffstraße 6 - Espelkamp 32339 - GERMANY - - 00-50-C2 (hex) Procon Electronics - EE1000-EE1FFF (base 16) Procon Electronics - PO Box 164 - Seven Hills - Sydney NSW 1730 - AUSTRALIA - - 00-50-C2 (hex) System Industrie Electronic GmbH - EE2000-EE2FFF (base 16) System Industrie Electronic GmbH - Millennium Park 12 - Lustenau Vorarlberg 6890 - AUSTRIA - - 00-50-C2 (hex) Tecnint HTE Srl - EE3000-EE3FFF (base 16) Tecnint HTE Srl - Via della Tecnica 16/18 - Osnago Lecco 23875 - ITALY - - 00-50-C2 (hex) Rohde&Schwarz Topex SA - EE4000-EE4FFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacu Street, district 1 - Bucharest 014186 - ROMANIA - - 00-50-C2 (hex) Cytec Zylindertechnik GmbH - EE5000-EE5FFF (base 16) Cytec Zylindertechnik GmbH - Steffensrott 1 - Jülich NRW 52428 - GERMANY - - 00-50-C2 (hex) B:TECH, a. s. - EE6000-EE6FFF (base 16) B:TECH, a. s. - U Borove 69 - Havlickuv Brod 580 01 - CZECH REPUBLIC - - 00-50-C2 (hex) Syes srl - EE7000-EE7FFF (base 16) Syes srl - via zanella,21 - lissone (MB ) Monza Brianza 20851 - ITALY - - 00-50-C2 (hex) Kamacho Scale Co., Ltd. - EE8000-EE8FFF (base 16) Kamacho Scale Co., Ltd. - 2246 Mure - Mure-Cho - Takamatsu-shi Kagawa-ken 761-0196 - JAPAN - - 00-50-C2 (hex) QUANTA S.r.l. - EE9000-EE9FFF (base 16) QUANTA S.r.l. - Via A. Ferrarin, 19-23 - Firenze FI 50145 - ITALY - - 00-50-C2 (hex) Positioneering Limited - EEA000-EEAFFF (base 16) Positioneering Limited - Gordon House - Greenbank Road - Aberdeen Aberdeenshire AB12 3BR - UNITED KINGDOM - - 00-50-C2 (hex) fibrisTerre GmbH - EEB000-EEBFFF (base 16) fibrisTerre GmbH - Köpenicker Str. 154 - Berlin Deutschland 10997 - GERMANY - - 00-50-C2 (hex) Yuyama Mfg. Co., Ltd. - EEC000-EECFFF (base 16) Yuyama Mfg. Co., Ltd. - 3-3-1 Meishinguchi - Toyonaka Osaka 561-0841 - JAPAN - - 00-50-C2 (hex) Future Design Controls, Inc - EED000-EEDFFF (base 16) Future Design Controls, Inc - 7524 W 98th Place - P.O. Box 1196 - Bridgeview IL 60455 - UNITED STATES - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd - EEE000-EEEFFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd - ABB Industrial Park, Torch Hi-Tech Development Zone. - Xiao Dong Shan, - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) IDTRONIC GmbH - EEF000-EEFFFF (base 16) IDTRONIC GmbH - Donnersbergweg 1 - Ludwigshafen NonUS D67059 - GERMANY - - 00-50-C2 (hex) Homaetrix Ltd - EF0000-EF0FFF (base 16) Homaetrix Ltd - St Johns Innovation Centre - Cowley Rd - Cambridge Cambs CB4 0WS - UNITED KINGDOM - - 00-50-C2 (hex) Saia-Burgess Controls AG - EF1000-EF1FFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) Specialty Microwave Corp - EF2000-EF2FFF (base 16) Specialty Microwave Corp - 120 Raynor Ave - Ronkonkoma New York 11779 - UNITED STATES - - 00-50-C2 (hex) Smart Power Electronics GmbH & Co. KG - EF3000-EF3FFF (base 16) Smart Power Electronics GmbH & Co. KG - Lise-Meitner-Straße 21 - Itzehoe Schleswig-Holstein 25524 - GERMANY - - 00-50-C2 (hex) RO.VE.R. Laboratories S.p.A - EF4000-EF4FFF (base 16) RO.VE.R. Laboratories S.p.A - Via Parini 2 - Sirmione BS 25019 - ITALY - - 00-50-C2 (hex) Human Network Labs, Inc. - EF5000-EF5FFF (base 16) Human Network Labs, Inc. - 4548 Market St. M19 - PHILADELPHIA Pennsylvania 19139 - UNITED STATES - - 00-50-C2 (hex) Netline Communication Technologies - EF6000-EF6FFF (base 16) Netline Communication Technologies - Azrieli Circular Tower, 132 Menachem Begin Rd - Tel Aviv Israel 67021 - ISRAEL - - 00-50-C2 (hex) Amstelland Electronic BV - EF7000-EF7FFF (base 16) Amstelland Electronic BV - Amsteldijk Noord 194 - Uithoorn Noord Holland 1422 XZ - NETHERLANDS - - 00-50-C2 (hex) HCL Technologies - EF8000-EF8FFF (base 16) HCL Technologies - A5, Sector 24 - Noida Uttar Pradesh 201301 - INDIA - - 00-50-C2 (hex) HORIBA ABX - EF9000-EF9FFF (base 16) HORIBA ABX - rue du caducee - Montpellier 34000 - FRANCE - - 00-50-C2 (hex) Predictive Sensor Technology - EFA000-EFAFFF (base 16) Predictive Sensor Technology - 316 N Main St - Lynchburg Ohio 45142 - UNITED STATES - - 00-50-C2 (hex) Norbit ODM AS - EFB000-EFBFFF (base 16) Norbit ODM AS - Stiklestadveien 1 - Trondheim 7041 - NORWAY - - 00-50-C2 (hex) PRIVATE - EFC000-EFCFFF (base 16) - - 00-50-C2 (hex) Sanmina - EFD000-EFDFFF (base 16) Sanmina - PO 106 - Ornskoldsvik 89123 - SWEDEN - - 00-50-C2 (hex) PLR Information Systems Ltd. - EFE000-EFEFFF (base 16) PLR Information Systems Ltd. - POB 8130, Poleg Industrial Zone - H'Aomanut str.9 - Netanya 42160 - ISRAEL - - 00-50-C2 (hex) Zephyrus Electronics LTD. - EFF000-EFFFFF (base 16) Zephyrus Electronics LTD. - 168 S. 122nd E. Ave. - Tulsa Oklahoma 74128 - UNITED STATES - - 00-50-C2 (hex) Syscom Instruments - F00000-F00FFF (base 16) Syscom Instruments - Rue de l'Industrie 21 - Sainte-Croix VD 1450 - SWITZERLAND - - 00-50-C2 (hex) Mango DSP, Inc - F01000-F01FFF (base 16) Mango DSP, Inc - 83 East Ave - Suite#115 - Norwalk CT 06851 - UNITED STATES - - 00-50-C2 (hex) BMR - F02000-F02FFF (base 16) BMR - Balbinova 252 - Rychnov nad Kneznou 51601 - CZECH REPUBLIC - - 00-50-C2 (hex) Wren Sound Systems - F03000-F03FFF (base 16) Wren Sound Systems - 169 Gateshead Way - Phoenixville PA 19460 - UNITED STATES - - 00-50-C2 (hex) KINKI ROENTGEN INDUSTRIAL CO.,LTD - F04000-F04FFF (base 16) KINKI ROENTGEN INDUSTRIAL CO.,LTD - 259 Kamidachiuri-Agaru Muromachidori, - kamikyo-ku - Kyoto 6020029 - JAPAN - - 00-50-C2 (hex) ESI Ventures - F05000-F05FFF (base 16) ESI Ventures - 902 Incentive Drive - Fort Wayne Indiana 46825 - UNITED STATES - - 00-50-C2 (hex) Micro-Key BV - F06000-F06FFF (base 16) Micro-Key BV - Industrieweg 28 - Noordhorn Groningen 9804 TG - NETHERLANDS - - 00-50-C2 (hex) Icon Research Ltd - F07000-F07FFF (base 16) Icon Research Ltd - 3 Raw Holdings - East Calder West Lothian EH53 0HY - UNITED KINGDOM - - 00-50-C2 (hex) Aplex Technology Inc. - F08000-F08FFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn Industrial Park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) Wheatstone Corporation - F09000-F09FFF (base 16) Wheatstone Corporation - 600 Industrial Drive - New Bern NC 28562 - UNITED STATES - - 00-50-C2 (hex) HASCOM International Pty Ltd - F0A000-F0AFFF (base 16) HASCOM International Pty Ltd - 15 Marloo Lane - Quinns Rocks Western Australia 6030 - AUSTRALIA - - 00-50-C2 (hex) Treehaven Technologies, Inc. - F0B000-F0BFFF (base 16) Treehaven Technologies, Inc. - 24 Village Pointe Drive - Powell OH 43065 - UNITED STATES - - 00-50-C2 (hex) SKYCHANNEL LTD - F0C000-F0CFFF (base 16) SKYCHANNEL LTD - 567 - 5 TH FLOOR BUILDING 1 - CHUANGYE ROAD NANSHAN - SHENZHEN GUANGDONG 518054 - CHINA - - 00-50-C2 (hex) Bluetest AB - F0D000-F0DFFF (base 16) Bluetest AB - Gotaverksgatan 1 - Gothenburg SE-41755 - SWEDEN - - 00-50-C2 (hex) Micro Technic A/S - F0E000-F0EFFF (base 16) Micro Technic A/S - Smedevaenget 5 - Aarup 5560 - DENMARK - - 00-50-C2 (hex) AeroVision Avionics, Inc. - F0F000-F0FFFF (base 16) AeroVision Avionics, Inc. - 2F, 30 R&D Rd. II, - Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Wincor Nixdorf Sp. z o.o. - F10000-F10FFF (base 16) Wincor Nixdorf Sp. z o.o. - ul. Popularna 82 - Warszawa Poland 02-226 - POLAND - - 00-50-C2 (hex) Organis GmbH - F11000-F11FFF (base 16) Organis GmbH - Schulstrasse 76 - Landquart 7302 - SWITZERLAND - - 00-50-C2 (hex) General Industrial Controls Pvt Ltd - F12000-F12FFF (base 16) General Industrial Controls Pvt Ltd - T107, M.I.D.C. - Bhosari - Pune Maharashtra 411026 - INDIA - - 00-50-C2 (hex) Packet Plus, Inc. - F13000-F13FFF (base 16) Packet Plus, Inc. - 1320 SW Hall St - Suite 103 - Portland OR 97201 - UNITED STATES - - 00-50-C2 (hex) VISION SYSTEMS AERONAUTIC - F14000-F14FFF (base 16) VISION SYSTEMS AERONAUTIC - ROUTE D'IRIGNY - BRIGNAIS 69530 - FRANCE - - 00-50-C2 (hex) Sascal Displays Ltd - F15000-F15FFF (base 16) Sascal Displays Ltd - 16 The Metro Centre - Springfield Rd - Hayes London UB4 0LE - UNITED KINGDOM - - 00-50-C2 (hex) Peter Huber Kältemaschinenbau GmbH - F16000-F16FFF (base 16) Peter Huber Kältemaschinenbau GmbH - Werner-von-Siemens-Str. 1 - Offenburg Baden-Württemberg 77656 - GERMANY - - 00-50-C2 (hex) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - F17000-F17FFF (base 16) ABB Transmission and Distribution Automation Equipment (Xiamen) Co., Ltd. - ABB Industry Park,Torch Hi-tech Development Zone - Xiao Dong Shan, - Xiamen Fujian 361006 - CHINA - - 00-50-C2 (hex) Vitec Multimedia - F18000-F18FFF (base 16) Vitec Multimedia - 99 rue Pierre Sémard - CHATILLON 92320 - FRANCE - - 00-50-C2 (hex) Netlink Bilisim Sistemleri San. ve Tic. Ltd. Sti. - F19000-F19FFF (base 16) Netlink Bilisim Sistemleri San. ve Tic. Ltd. Sti. - Caferaða mah. Sakiz sk. no:8/10 Kadikoy - Istanbul 34710 - TURKEY - - 00-50-C2 (hex) Aqua Management - F1A000-F1AFFF (base 16) Aqua Management - 6280 S Valley View BLVD - STE 212 - Las Vegas NV 89118 - UNITED STATES - - 00-50-C2 (hex) Saia-Burgess Controls AG - F1B000-F1BFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) GENERAL DYNAMICS C4 SYSTEMS - F1C000-F1CFFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT MD:R1115 - SCOTTSDALE AZ 85257 - UNITED STATES - - 00-50-C2 (hex) Grossenbacher Systeme AG - F1D000-F1DFFF (base 16) Grossenbacher Systeme AG - Spinnereistrasse 10 - St. Gallen 9008 - SWITZERLAND - - 00-50-C2 (hex) Dell'Orto S.P.A. - F1E000-F1EFFF (base 16) Dell'Orto S.P.A. - Via Kennedy, 7 - Cabiate Como 22060 - ITALY - - 00-50-C2 (hex) Verified Energy, LLC. - F1F000-F1FFFF (base 16) Verified Energy, LLC. - PO Box 111 - Oneida New York 13421 - UNITED STATES - - 00-50-C2 (hex) Unfors Instruments AB - F20000-F20FFF (base 16) Unfors Instruments AB - Uggledalsvagen 29 - Gothenburg Billdal 42740 - SWEDEN - - 00-50-C2 (hex) SEITEC Co. Ltd - F21000-F21FFF (base 16) SEITEC Co. Ltd - 580 kamashimo - akaiwa-city okayama-pref. 709-0732 - JAPAN - - 00-50-C2 (hex) Harland Simon plc - F22000-F22FFF (base 16) Harland Simon plc - Bond Avenue - Bletchley - Milton Keynes Bucks MK1 1TJ - UNITED KINGDOM - - 00-50-C2 (hex) Electro-Motive Diesel - F23000-F23FFF (base 16) Electro-Motive Diesel - 9301 West 55th St - LaGrange IL 60525 - UNITED STATES - - 00-50-C2 (hex) CT Company - F24000-F24FFF (base 16) CT Company - Nizhni Krasnoselsky st.,35 - Moscow RUSSIA 140070 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Samway Electronic SRL - F25000-F25FFF (base 16) Samway Electronic SRL - Campia Libertatii 46, ap 33 - Bucuresti 030375 - ROMANIA - - 00-50-C2 (hex) WaveIP - F26000-F26FFF (base 16) WaveIP - 1 Sky Street - Teradion Industrial park - Misgav 20179 - ISRAEL - - 00-50-C2 (hex) ELAN SYSTEMS - F27000-F27FFF (base 16) ELAN SYSTEMS - 10 IHASZ STR - BUDAPEST 1105 - HUNGARY - - 00-50-C2 (hex) Vertex Antennentechnik GmbH - F28000-F28FFF (base 16) Vertex Antennentechnik GmbH - Baumstrasse 50 - Duisburg NRW 47198 - GERMANY - - 00-50-C2 (hex) RADYNE CORPORATION - F29000-F29FFF (base 16) RADYNE CORPORATION - 211 West Boden Street - Milwaukee Wisconsin 53207 - UNITED STATES - - 00-50-C2 (hex) ACD Elektronik GmbH - F2A000-F2AFFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) Bio Guard component & technologies - F2B000-F2BFFF (base 16) Bio Guard component & technologies - 4 Ha'harash St. - Hod Hasharon 45240 - ISRAEL - - 00-50-C2 (hex) Terratel Technology s.r.o. - F2C000-F2CFFF (base 16) Terratel Technology s.r.o. - Dukelska 2192 - Benesov CZ 25601 - CZECH REPUBLIC - - 00-50-C2 (hex) Robert Bosch Healthcare Systems, Inc. - F2D000-F2DFFF (base 16) Robert Bosch Healthcare Systems, Inc. - 2400 Geng Road - Ste. 200 - Palo Alto CA 94303 - UNITED STATES - - 00-50-C2 (hex) H&L Instruments, LLC - F2E000-F2EFFF (base 16) H&L Instruments, LLC - 34 Post Road - North Hampton NH 03862 - UNITED STATES - - 00-50-C2 (hex) Arcos Technologies LTD - F2F000-F2FFFF (base 16) Arcos Technologies LTD - 26 Hasivim - Petach Tikva 49517 - ISRAEL - - 00-50-C2 (hex) Miris AB - F30000-F30FFF (base 16) Miris AB - Kungsgatan 115 - UPPSALA 75318 - SWEDEN - - 00-50-C2 (hex) Ruetz Technologies GmbH - F31000-F31FFF (base 16) Ruetz Technologies GmbH - Walter Gropius Str. 17 - Munich Bayern 80807 - GERMANY - - 00-50-C2 (hex) Net4Things - F32000-F32FFF (base 16) Net4Things - Paseo de la Florida, nº 2 - Madrid 28008 - SPAIN - - 00-50-C2 (hex) Applied Micro Electronics "AME" BV - F33000-F33FFF (base 16) Applied Micro Electronics "AME" BV - Esp 100 - Eindhoven Noord Brabant 5633AA - NETHERLANDS - - 00-50-C2 (hex) Sequip S+E GmbH - F34000-F34FFF (base 16) Sequip S+E GmbH - Angermunder Straße 22 - Düsseldorf NRW 40489 - GERMANY - - 00-50-C2 (hex) Grupo Epelsa S.L. - F35000-F35FFF (base 16) Grupo Epelsa S.L. - C/ Albasanz, 6 y 8 - Madrid 28037 - SPAIN - - 00-50-C2 (hex) Visitech AS - F36000-F36FFF (base 16) Visitech AS - Kjellstadveien 5 - Lier Lier 3400 - NORWAY - - 00-50-C2 (hex) Rosslare Enterprises Limited - F37000-F37FFF (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon - HONG KONG - - 00-50-C2 (hex) AeroControl, Inc. - F38000-F38FFF (base 16) AeroControl, Inc. - 595 Utica Ave. - Boulder CO 80304 - UNITED STATES - - 00-50-C2 (hex) Inforce Computing, Inc. - F39000-F39FFF (base 16) Inforce Computing, Inc. - 48820 Kato Road - 600B - Fremont CA 94538 - UNITED STATES - - 00-50-C2 (hex) Saia-Burgess Controls AG - F3A000-F3AFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) TAMS firmware co. - F3B000-F3BFFF (base 16) TAMS firmware co. - aota5-15-26 - yamagata 990-2435 - JAPAN - - 00-50-C2 (hex) Vemco Sp. z o. o. - F3C000-F3CFFF (base 16) Vemco Sp. z o. o. - ul. Broniewskiego 3 - Sopot pomorskie 81-837 - POLAND - - 00-50-C2 (hex) Project service S.a.s - F3D000-F3DFFF (base 16) Project service S.a.s - Via Paderno 31/C - Seriate Bergamo 24100 - ITALY - - 00-50-C2 (hex) Vtron Pty Ltd - F3E000-F3EFFF (base 16) Vtron Pty Ltd - 6/59 Township Drive - West Burleigh QLD 4219 - AUSTRALIA - - 00-50-C2 (hex) DENSEI COMMUNICATION Inc. - F3F000-F3FFFF (base 16) DENSEI COMMUNICATION Inc. - 8-13,Koei-cho - Ebetsu-shi Hokkaido 067-0051 - JAPAN - - 00-50-C2 (hex) iBWorld co.,ltd. - F40000-F40FFF (base 16) iBWorld co.,ltd. - 5-2-15 - Higashi-Tokorozawa - Tokorozawa Saitama 359-0021 - JAPAN - - 00-50-C2 (hex) FairyDevices Inc. - F41000-F41FFF (base 16) FairyDevices Inc. - Entrepreneur Plaza Bldg 5F - 7-3-1 Hongo - Bunkyou-ku Tokyo 113-0033 - JAPAN - - 00-50-C2 (hex) DSPCon - F42000-F42FFF (base 16) DSPCon - 380 Foothill Road - Bridgewater NJ 08807 - UNITED STATES - - 00-50-C2 (hex) Special Systems Engineering Center LLC - F43000-F43FFF (base 16) Special Systems Engineering Center LLC - 33 VARSHAVSKOE SHOSSE - Moscow 117105 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Steinbichler Optotechnik GmbH - F44000-F44FFF (base 16) Steinbichler Optotechnik GmbH - Georg-Wiesboeck-Ring 12 - Neubeuern Bavaria 83115 - GERMANY - - 00-50-C2 (hex) HUSTY M.Styczen J.Hupert Sp.J. - F45000-F45FFF (base 16) HUSTY M.Styczen J.Hupert Sp.J. - Rzepakowa 5e - Krakow malopolska 31-989 - POLAND - - 00-50-C2 (hex) Reason Tecnologia S.A. - F46000-F46FFF (base 16) Reason Tecnologia S.A. - Rua Delminda Silveira, 855 - Florianopolis Santa Catarina 88025-500 - BRAZIL - - 00-50-C2 (hex) cadac,inc. - F47000-F47FFF (base 16) cadac,inc. - Ho10-3,Ouramachi - Kanazawa-shi Ishikawa 920-0205 - JAPAN - - 00-50-C2 (hex) Midas Technology DBA Phoenix Audio Technologies - F48000-F48FFF (base 16) Midas Technology DBA Phoenix Audio Technologies - 2934 N. Naomi Street - Burbank CA 91504 - UNITED STATES - - 00-50-C2 (hex) Green Instruments A/S - F49000-F49FFF (base 16) Green Instruments A/S - Erhvervsparken 29 - Broenderslev 9700 - DENMARK - - 00-50-C2 (hex) Z-App Systems, Inc. - F4A000-F4AFFF (base 16) Z-App Systems, Inc. - 1732 North First St., #150 - San Jose CA 95112 - UNITED STATES - - 00-50-C2 (hex) Supranet - F4B000-F4BFFF (base 16) Supranet - Majstorska 5 - Zagreb 10000 - CROATIA - - 00-50-C2 (hex) Enistic Limited - F4C000-F4CFFF (base 16) Enistic Limited - Unit 4, Isis Business Centre - Pony Road - Oxford Oxfordshire OX4 2RD - UNITED KINGDOM - - 00-50-C2 (hex) KNOWHOW INFOCOM INC. - F4D000-F4DFFF (base 16) KNOWHOW INFOCOM INC. - 32-1, YOUNGMUN-DONG, - YONGSAN-GU - SEOUL 140-832 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Heinzinger electronic GmbH - F4E000-F4EFFF (base 16) Heinzinger electronic GmbH - Anton Jakob Str.4 - Rosenheim BY 83026 - GERMANY - - 00-50-C2 (hex) BAP Precision Ltd. - F4F000-F4FFFF (base 16) BAP Precision Ltd. - 1F., No.5, Ln. 147, Chengzhang 1st St. - Zhongli City Taoyuan County 320 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Moritex Corporation - F50000-F50FFF (base 16) Moritex Corporation - 9-21-4 - sakuraku tajima - saitama city saitama prefecture 3380837 - JAPAN - - 00-50-C2 (hex) NDC Infrared Engineering, Inc. - F51000-F51FFF (base 16) NDC Infrared Engineering, Inc. - 5314 N. Irwindale Avenue - Irwindale CA 91706 - UNITED STATES - - 00-50-C2 (hex) Rohde&Schwarz Topex SA - F52000-F52FFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacu street, district 1, code 014186 - Bucharest 014186 - ROMANIA - - 00-50-C2 (hex) BAYCOM OPTO-ELECTRONICS TECHNOLOGY CO.,LTD. - F53000-F53FFF (base 16) BAYCOM OPTO-ELECTRONICS TECHNOLOGY CO.,LTD. - 1F,NO.9, INDUSTRIAL EAST 9th RD., - HSINCHU SCIENCE PARK, - HSINCHU TAIWAN 30075 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Hella Gutmann Solutions GmbH - F54000-F54FFF (base 16) Hella Gutmann Solutions GmbH - Am Krebsbach 2 - Ihringen 79241 - GERMANY - - 00-50-C2 (hex) Honeywell International Inc. - F55000-F55FFF (base 16) Honeywell International Inc. - 13350 US Hwy 19 N - Clearwater Fl 33764 - UNITED STATES - - 00-50-C2 (hex) Monsoon Solutions, Inc. - F56000-F56FFF (base 16) Monsoon Solutions, Inc. - 2405 140th Ave NE - Suite A115 - Bellevue WA 98005 - UNITED STATES - - 00-50-C2 (hex) Reach Technologies Inc. - F57000-F57FFF (base 16) Reach Technologies Inc. - 106 - 3025 Shakespeare Street - Victoria BC V8R 4H6 - CANADA - - 00-50-C2 (hex) IEEE-SA - F58000-F58FFF (base 16) IEEE-SA - 445 Hoes Lane - Piscataway NJ 08854 - UNITED STATES - - 00-50-C2 (hex) G3 Technologies - F59000-F59FFF (base 16) G3 Technologies - 2904 Back Acre Circle - Mount Airy MD 21771 - UNITED STATES - - 00-50-C2 (hex) Sentry 360 Security - F5A000-F5AFFF (base 16) Sentry 360 Security - 24012 W. Renwick Road - Suite 206 - Plainfield ILLINOIS 60544 - UNITED STATES - - 00-50-C2 (hex) Saia-Burgess Controls AG - F5B000-F5BFFF (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 00-50-C2 (hex) DSP DESIGN LTD - F5C000-F5CFFF (base 16) DSP DESIGN LTD - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 00-50-C2 (hex) SMARTB TECHNOLOGIES - F5D000-F5DFFF (base 16) SMARTB TECHNOLOGIES - #625 1ST FLOOR 3 RD CROSS CBI MAIN ROAD HMT LAYOUT RT NAGAR - BANGALORE KARNATAKA 560032 - INDIA - - 00-50-C2 (hex) Y-cam Solutions Ltd - F5E000-F5EFFF (base 16) Y-cam Solutions Ltd - Vision House - 3 Dee Road - Richmond Surrey TW9 2JN - UNITED KINGDOM - - 00-50-C2 (hex) BORYEU TECHNOLOGY CO.,LTD - F5F000-F5FFFF (base 16) BORYEU TECHNOLOGY CO.,LTD - 2F.,No756,Zhongzheng Road - Zhonghe City Taipei Hsien23586 23586 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) Deckma GmbH - F60000-F60FFF (base 16) Deckma GmbH - Bahnhofstr.79 - Rosengarten-Klecken Lower Saxonie 21224 - GERMANY - - 00-50-C2 (hex) Brauch Elektronik GmbH&Co.KG - F61000-F61FFF (base 16) Brauch Elektronik GmbH&Co.KG - Hirschbachstrasse 47 - Reinheim Hessen 64354 - GERMANY - - 00-50-C2 (hex) EMAC, Inc. - F62000-F62FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 00-50-C2 (hex) Triax A/S - F63000-F63FFF (base 16) Triax A/S - Bjørnkærvej 3 - Hornsyld 8783 - DENMARK - - 00-50-C2 (hex) Chrisso Technologies LLC - F64000-F64FFF (base 16) Chrisso Technologies LLC - 700 E Firmin Street - Suite 249 - Kokomo Indiana 46902 - UNITED STATES - - 00-50-C2 (hex) Telebyte Inc. - F65000-F65FFF (base 16) Telebyte Inc. - 355 Marcus Blvd. - Hauppauge NY 11788 - UNITED STATES - - 00-50-C2 (hex) GWT LLC - F66000-F66FFF (base 16) GWT LLC - 101 Gibraltar Drive - Suite 3F - Morris Plains NJ 07950 - UNITED STATES - - 00-50-C2 (hex) Celestial Audio - F67000-F67FFF (base 16) Celestial Audio - 4441 Albert St. - Oakland CA 94619 - UNITED STATES - - 00-50-C2 (hex) NEWTEC A/S - F68000-F68FFF (base 16) NEWTEC A/S - StærmosegÃ¥rdssvej 18 - Odense SV Region Syd 5230 - DENMARK - - 00-50-C2 (hex) Safe Place Solutions Ltd - F69000-F69FFF (base 16) Safe Place Solutions Ltd - Eden House - Enterprise Way - Edenbridge Kent TN8 6HF - UNITED KINGDOM - - 00-50-C2 (hex) OFI Inc. (dba 2D2C) - F6A000-F6AFFF (base 16) OFI Inc. (dba 2D2C) - 100 Hanson Avenue - Kitchener Ontario N2C2E2 - CANADA - - 00-50-C2 (hex) Algodue Elettronica Srl - F6B000-F6BFFF (base 16) Algodue Elettronica Srl - Via Passerina 3/a - Fontaneto d'Agogna 28010 - ITALY - - 00-50-C2 (hex) Pro Design Electronic GmbH - F6C000-F6CFFF (base 16) Pro Design Electronic GmbH - Albert-Mayer-Str. 14-16 - Bruckmuehl Bavaria 83052 - GERMANY - - 00-50-C2 (hex) Pro Design Electronic GmbH - F6D000-F6DFFF (base 16) Pro Design Electronic GmbH - Albert-Mayer-Straße 14-16 - Bruckmuehl Bavaria 83052 - GERMANY - - 00-50-C2 (hex) Smith Meter, Inc. - F6E000-F6EFFF (base 16) Smith Meter, Inc. - 1602 Wagner Ave - Erie PA 16514 - UNITED STATES - - 00-50-C2 (hex) Aplex Technology Inc. - F6F000-F6FFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn Industrial Park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) Noralta Technologies Inc - F70000-F70FFF (base 16) Noralta Technologies Inc - 2350, 444 - 5 Ave S.W. - Calgary Alberta T2P 2T8 - CANADA - - 00-50-C2 (hex) RF CODE, INC - F71000-F71FFF (base 16) RF CODE, INC - 9229 WATERFORD CENTRE - SUITE 500 - AUSTIN TX 78758 - UNITED STATES - - 00-50-C2 (hex) MaxDeTec AG - F72000-F72FFF (base 16) MaxDeTec AG - Dorfstrasse 54 - Thalwil Zurich 8800 - SWITZERLAND - - 00-50-C2 (hex) DELTACAST.TV - F73000-F73FFF (base 16) DELTACAST.TV - Rue Gilles Magnee 92/6 - ANS 4430 - BELGIUM - - 00-50-C2 (hex) Thor Technologies Pty Ltd - F74000-F74FFF (base 16) Thor Technologies Pty Ltd - PO Box 95 - Karrinyup Western Australia 6921 - AUSTRALIA - - 00-50-C2 (hex) PumpWell Solutions Ltd. - F75000-F75FFF (base 16) PumpWell Solutions Ltd. - 10, 2150-29th St. NE - Calgary AB T1Y 7G4 - CANADA - - 00-50-C2 (hex) Rong Jie(FuZhou)Electronics Co.,Ltd - F76000-F76FFF (base 16) Rong Jie(FuZhou)Electronics Co.,Ltd - No. 38, Jinqiao Road, Wuhan City, - wuhan hubei 430000 - CHINA - - 00-50-C2 (hex) SYSTEMTECHNIK GmbH - F77000-F77FFF (base 16) SYSTEMTECHNIK GmbH - Wielandstrasse 12 - Soemmerda Thueringia 99610 - GERMANY - - 00-50-C2 (hex) Gets MSS S.A. - F78000-F78FFF (base 16) Gets MSS S.A. - Avenue des Boveresses n°52 - Lausanne Vaud 1010 - SWITZERLAND - - 00-50-C2 (hex) Tattile SRL - F79000-F79FFF (base 16) Tattile SRL - via Donizetti 1/3/5 - Mariano BS 25030 - ITALY - - 00-50-C2 (hex) C3 LLC - F7A000-F7AFFF (base 16) C3 LLC - 1305 N Savannah Terrace - Mustang OK 73064 - UNITED STATES - - 00-50-C2 (hex) MCM Electronics - F7B000-F7BFFF (base 16) MCM Electronics - Unit 3 / 10 Abel St - Penrith - Sydney NSW 2750 - AUSTRALIA - - 00-50-C2 (hex) Atonometrics, Inc. - F7C000-F7CFFF (base 16) Atonometrics, Inc. - 8900 Shoal Creek Blvd Ste 116 - Austin Texas 78757 - UNITED STATES - - 00-50-C2 (hex) D-Hike Electroncs Technology Co.,Ltd - F7D000-F7DFFF (base 16) D-Hike Electroncs Technology Co.,Ltd - Room 5277, Block A, Building 2, - No,499, Kangyi Road - Shanghai Shanghai 201315 - CHINA - - 00-50-C2 (hex) TruTeq Wireless (Pty) Ltd - F7E000-F7EFFF (base 16) TruTeq Wireless (Pty) Ltd - Ameton House - 1028 Clifton Avenue, Lyttelton Manor Ext 3 - Centurion Gauteng 0157 - SOUTH AFRICA - - 00-50-C2 (hex) Dynamic Design - F7F000-F7FFFF (base 16) Dynamic Design - 500 W Harbor Dr Unit 311 - San Diego California 92101 - UNITED STATES - - 00-50-C2 (hex) SYS TEC electronic GmbH - F80000-F80FFF (base 16) SYS TEC electronic GmbH - August-Bebel-Str. 29 - Greiz Thuringia 07973 - GERMANY - - 00-50-C2 (hex) PLDA - F81000-F81FFF (base 16) PLDA - Parc du Golf Bat 11A, Rue Guillibert - Aix en Provence PACA 13856 - FRANCE - - 00-50-C2 (hex) Sincair Systems International - F82000-F82FFF (base 16) Sincair Systems International - 3115 S. Willow Avenue - Fresno CA 93725 - UNITED STATES - - 00-50-C2 (hex) GSP Sprachtechnologie GmbH - F83000-F83FFF (base 16) GSP Sprachtechnologie GmbH - Teltowkanalstr. 1 - Berlin 12247 - GERMANY - - 00-50-C2 (hex) Dynon Instruments - F84000-F84FFF (base 16) Dynon Instruments - 19825 141st PL NE - Woodinville WA 98072 - UNITED STATES - - 00-50-C2 (hex) Enetics, Inc. - F85000-F85FFF (base 16) Enetics, Inc. - 830 Canning Parkway - Victor NY 14564 - UNITED STATES - - 00-50-C2 (hex) Audio Power Labs - F86000-F86FFF (base 16) Audio Power Labs - 7020 Huntley Road - Suite A - Columbus Ohio 43229 - UNITED STATES - - 00-50-C2 (hex) Vaisala Oyj - F87000-F87FFF (base 16) Vaisala Oyj - Vanha Nurmijarventie 21 - Fin-01670 Vantaa 01670 - FINLAND - - 00-50-C2 (hex) RTC Manufacturing Inc. - F88000-F88FFF (base 16) RTC Manufacturing Inc. - 1016 Enterprise Place - Arlington TX 76001 - UNITED STATES - - 00-50-C2 (hex) CSA Engineering AG - F89000-F89FFF (base 16) CSA Engineering AG - Hans Huber-Strasse 38 - Solothurn SO 4500 - SWITZERLAND - - 00-50-C2 (hex) EMAC, Inc. - F8A000-F8AFFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 00-50-C2 (hex) comlet Verteilte Systeme GmbH - F8B000-F8BFFF (base 16) comlet Verteilte Systeme GmbH - Amerikastr. 27 - Zweibruecken Rheinland-Pfalz 66482 - GERMANY - - 00-50-C2 (hex) UBSTechnology Co., Ltd - F8C000-F8CFFF (base 16) UBSTechnology Co., Ltd - 505-Ho, Changmi B/D - Seongdong-gu, Seongsu-dong 2(i)-ga, 284-67 Bunji - Seoul City 133-120 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) GUANGDONG EAST POWER CO.,LTD. - F8D000-F8DFFF (base 16) GUANGDONG EAST POWER CO.,LTD. - No 6 Northern Industry Road,Songshan lake SCI&TECH Industry Park - DongGuan GuangDong P.R.China 523808 - CHINA - - 00-50-C2 (hex) GPO - F8E000-F8EFFF (base 16) GPO - SK-Technopark B/D D-1007,8 #1345 - Soha-Dong - Gwangmyeong-Si Gyeonggi-Do 423-050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Computerwise, Inc. - F8F000-F8FFFF (base 16) Computerwise, Inc. - 302 N Winchester Street - Olathe KS 66062 - UNITED STATES - - 00-50-C2 (hex) SecureTech Systems, Inc. - F90000-F90FFF (base 16) SecureTech Systems, Inc. - 4108 Amon Carter Blvd, ste 206 - Fort Worth TX 76155 - UNITED STATES - - 00-50-C2 (hex) RE2 Inc - F91000-F91FFF (base 16) RE2 Inc - 4925 Harrison St - Pittsburgh Pennsylvania 15201 - UNITED STATES - - 00-50-C2 (hex) CONET Solutions GmbH - F92000-F92FFF (base 16) CONET Solutions GmbH - Theodor-Heuss-Allee 19 - Hennef NRW 53773 - GERMANY - - 00-50-C2 (hex) Baudisch Electronic GmbH - F93000-F93FFF (base 16) Baudisch Electronic GmbH - Im Gewerbegebiet 7-9 - Wäschenbeuren Baden-Württemberg 73116 - GERMANY - - 00-50-C2 (hex) Digital Barriers - F94000-F94FFF (base 16) Digital Barriers - Photon House - Percy Street - Leeds West Yorkshire LS121EG - UNITED KINGDOM - - 00-50-C2 (hex) TTi LTD (Thurlby Thandar Instruments LTD) - F95000-F95FFF (base 16) TTi LTD (Thurlby Thandar Instruments LTD) - Glebe Road - Huntingdon - Cambridge Cambridgeshire PE29 7DR - UNITED KINGDOM - - 00-50-C2 (hex) JLCooper Electronics - F96000-F96FFF (base 16) JLCooper Electronics - 142 Arena St - El Segundo CA 90245 - UNITED STATES - - 00-50-C2 (hex) Sicon s.r.l. - F97000-F97FFF (base 16) Sicon s.r.l. - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 00-50-C2 (hex) Infotech North America - F98000-F98FFF (base 16) Infotech North America - 109 E. 17th Street - Suite 4044 - Cheyenne WY 82001 - UNITED STATES - - 00-50-C2 (hex) Dr. Neumann elektronik GmbH - F99000-F99FFF (base 16) Dr. Neumann elektronik GmbH - Schiffgesweg 9 - Pulheim North Rhine-Westphalia 50259 - GERMANY - - 00-50-C2 (hex) Telvent - F9A000-F9AFFF (base 16) Telvent - Valgrande, 6 - Alcobendas Madrid 28108 - SPAIN - - 00-50-C2 (hex) NEWELL TECHNOLOGIES LIMITED - F9B000-F9BFFF (base 16) NEWELL TECHNOLOGIES LIMITED - Unit 13, 4/F, New City Centre, - 2 Lei Yue Mun Road, Kwun Tong, - Kowloon - HONG KONG - - 00-50-C2 (hex) R&D KOMETEH - F9C000-F9CFFF (base 16) R&D KOMETEH - Lermontovsky pr. 54 - Saint-Petersburg 190103 - RUSSIAN FEDERATION - - 00-50-C2 (hex) JSC "Kaluga Teletypes Manufacturing Plant" - F9D000-F9DFFF (base 16) JSC "Kaluga Teletypes Manufacturing Plant" - 141, Saltykova-Schedrina Street - Kaluga Kaluga region 248002 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Matsusada Precision Inc. - F9E000-F9EFFF (base 16) Matsusada Precision Inc. - 745 Aoji - Kusatsu Shiga 525-0041 - JAPAN - - 00-50-C2 (hex) Nanjing SAC Power Grid Automation Co., Ltd. - F9F000-F9FFFF (base 16) Nanjing SAC Power Grid Automation Co., Ltd. - No.11 Phoenix Road - Jiangning Development Zone - Nanjing Jiangsu Provience 211100 - CHINA - - 00-50-C2 (hex) Amplus Communication Pte Ltd - FA0000-FA0FFF (base 16) Amplus Communication Pte Ltd - 19A Serangoon North Ave 5 - Singapore 554859 - SINGAPORE - - 00-50-C2 (hex) N-Hands GmbH und Co KG - FA1000-FA1FFF (base 16) N-Hands GmbH und Co KG - Kreuzgaerten 2 - Idstein 65510 - GERMANY - - 00-50-C2 (hex) Power-One - FA2000-FA2FFF (base 16) Power-One - Via San Giorgio 642 - Terranuova Bracciolini Arezzo 52028 - ITALY - - 00-50-C2 (hex) Xemex NV - FA3000-FA3FFF (base 16) Xemex NV - Metropoolstraat 11a - Schoten Antwerp BE-2900 - BELGIUM - - 00-50-C2 (hex) Intuitive Surgical, Inc. - FA5000-FA5FFF (base 16) Intuitive Surgical, Inc. - 1250 Kifer Road, Building 103 - Sunnyvale CA 94086 - UNITED STATES - - 00-50-C2 (hex) Hilkom digital GmbH - FA6000-FA6FFF (base 16) Hilkom digital GmbH - TecCenter 1 - Bad Salzdetfurth Niedersachsen D-31162 - GERMANY - - 00-50-C2 (hex) Exelis Inc. - FA7000-FA7FFF (base 16) Exelis Inc. - 430 W 5th Street - Suite 600 - Panama City FL 32401 - UNITED STATES - - 00-50-C2 (hex) Yash SiQure Technologies India Pvt. Ltd. - FA8000-FA8FFF (base 16) Yash SiQure Technologies India Pvt. Ltd. - C 262, Sector - 63, - Noida, UP 201307 - INDIA - - 00-50-C2 (hex) Hijet Print d.o.o. - FA9000-FA9FFF (base 16) Hijet Print d.o.o. - Majstorska 3 - Zagreb Croatia 10000 - CROATIA - - 00-50-C2 (hex) YJSYSTEM - FAA000-FAAFFF (base 16) YJSYSTEM - #902, E&C Venture Tower - GuroDong, GuroGu Seoul 152-719 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Aplex Technology Inc. - FAB000-FABFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-50-C2 (hex) ADETEL GROUP - FAC000-FACFFF (base 16) ADETEL GROUP - 4, Chemin du Ruisseau - ECULLY 69130 - FRANCE - - 00-50-C2 (hex) Finishing Brands - FAD000-FADFFF (base 16) Finishing Brands - 1910 North Wayne Street - Angola IN 46703 - UNITED STATES - - 00-50-C2 (hex) ATI Automacao Telecomunicacoes e Informatica Ltda - FAE000-FAEFFF (base 16) ATI Automacao Telecomunicacoes e Informatica Ltda - Rua Professor José Vieira de Mendonça, 770 - Bairro Engenho Nogueira - Belo Horizonte Minas Gerais 31130-20 - BRAZIL - - 00-50-C2 (hex) Vremya-CH JSC - FAF000-FAFFFF (base 16) Vremya-CH JSC - 67, Osharskaya Str - Nizhny Novgorod Nizhny Novgorod region 603105 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Tateishi Kobisha Co.LTD - FB0000-FB0FFF (base 16) Tateishi Kobisha Co.LTD - 114 Kana-cho - Fuchu-city HIroshima 726-0025 - JAPAN - - 00-50-C2 (hex) MATELEX - FB1000-FB1FFF (base 16) MATELEX - 2 RUE GUSTAVE EIFFEL - ROSIERE PRES TROYES - TROYES 10430 - FRANCE - - 00-50-C2 (hex) Preston Industries dba PolyScience - FB2000-FB2FFF (base 16) Preston Industries dba PolyScience - 6600 W. Touhy Ave - Niles IL 60714-4588 - UNITED STATES - - 00-50-C2 (hex) CT Company - FB3000-FB3FFF (base 16) CT Company - Godovikova 9, Moscow - Moscow RUSSIA 129085 - RUSSIAN FEDERATION - - 00-50-C2 (hex) MC-monitoring SA - FB4000-FB4FFF (base 16) MC-monitoring SA - Route des Daillettes 6 - Fribourg FR 1709 - SWITZERLAND - - 00-50-C2 (hex) Assembly Contracts Limited - FB5000-FB5FFF (base 16) Assembly Contracts Limited - Ledson Road - Roundthorn Industrial Estate - Manchester Lancashire M23 9GP - UNITED KINGDOM - - 00-50-C2 (hex) ARGUS-SPECTRUM - FB6000-FB6FFF (base 16) ARGUS-SPECTRUM - Serdobolskaya street 65A - St.Petersburg 197342 - RUSSIAN FEDERATION - - 00-50-C2 (hex) Pounce Consulting - FB7000-FB7FFF (base 16) Pounce Consulting - Av 8 de Julio 1295 - Guadalajara Jalisco 44190 - MEXICO - - 00-50-C2 (hex) TECHNO CO.,LTD. - FB8000-FB8FFF (base 16) TECHNO CO.,LTD. - 1304-5 - Shimofujisawa - Iruma City Saitama Pref. 358-0011 - JAPAN - - 00-50-C2 (hex) Coral Telecom Ltd - FB9000-FB9FFF (base 16) Coral Telecom Ltd - E-02 Sector 63 - Noida UP 201301 - INDIA - - 00-50-C2 (hex) Elbit Systems of America - FBA000-FBAFFF (base 16) Elbit Systems of America - 4700 Marine Creek Parkway - Fort Worth TX 76179 - UNITED STATES - - 00-50-C2 (hex) ACIDA GmbH - FBB000-FBBFFF (base 16) ACIDA GmbH - Uersfeld 24 - Aachen 52072 - GERMANY - - 00-50-C2 (hex) Leroy Somer - FBC000-FBCFFF (base 16) Leroy Somer - Usine des Agriers - RDE - Boulevard M. Leroy - Angoulême Cedex 9 16915 - FRANCE - - 00-50-C2 (hex) FHF Funke+Huster Fernsig GmbH - FBD000-FBDFFF (base 16) FHF Funke+Huster Fernsig GmbH - Gewerbeallee 15-19 - Mülheim an der Ruhr NRW D-45478 - GERMANY - - 00-50-C2 (hex) senTec Elektronik GmbH - FBE000-FBEFFF (base 16) senTec Elektronik GmbH - Werner-von-Siemens-Strasse 6 - Ilmenau 98693 - GERMANY - - 00-50-C2 (hex) MYLOGIC - FBF000-FBFFFF (base 16) MYLOGIC - #106 Deayoung golden vally,290-2 - Gocheon-dong - Uiwang-si Gyeonggi-do 437-801 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Rohde&Schwarz Topex SA - FC0000-FC0FFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacu street, district 1, code 014186 - Bucharest Romania 014186 - ROMANIA - - 00-50-C2 (hex) Motec Pty Ltd - FC1000-FC1FFF (base 16) Motec Pty Ltd - 121 Merrindale Drive - Croydon South Victoria 3136 - AUSTRALIA - - 00-50-C2 (hex) ELTA - FC2000-FC2FFF (base 16) ELTA - 14 place Marcel Dassault - Blagnac 31700 - FRANCE - - 00-50-C2 (hex) HSDC Sp. z o.o. - FC3000-FC3FFF (base 16) HSDC Sp. z o.o. - SNIADECKICH 10 VP - NIP:PL5272616864 - Warszawa Mazowieckie 00-656 - POLAND - - 00-50-C2 (hex) Kyowadensi - FC4000-FC4FFF (base 16) Kyowadensi - Saiwai-cyo 2-1-17 - Chikusei Ibaraki 308-0848 - JAPAN - - 00-50-C2 (hex) Sakura Seiki Co.,Ltd. - FC5000-FC5FFF (base 16) Sakura Seiki Co.,Ltd. - 75-5, Imojiya - Chikuma-city Nagano Prefecture 387-0015 - JAPAN - - 00-50-C2 (hex) Critical Link - FC6000-FC6FFF (base 16) Critical Link - 6712 Brooklawn Parkway - Syracuse New York 13211 - UNITED STATES - - 00-50-C2 (hex) SERCOM Regeltechniek - FC7000-FC7FFF (base 16) SERCOM Regeltechniek - Heerweg 9 - Lisse ZN 2161 AB` - NETHERLANDS - - 00-50-C2 (hex) Far South Networks - FC8000-FC8FFF (base 16) Far South Networks - 49 Bell Crescent - Westlake Business Park - Westlake Western Cape 7945 - SOUTH AFRICA - - 00-50-C2 (hex) Mehta Tech, Inc. - FC9000-FC9FFF (base 16) Mehta Tech, Inc. - 208 N. 12th Avenue - Eldridge IA 52748 - UNITED STATES - - 00-50-C2 (hex) Telemisis Ltd - FCA000-FCAFFF (base 16) Telemisis Ltd - 7 Blenheim Court - Beaufort Park - Almondsbury Bristol BS32 4NE - UNITED KINGDOM - - 00-50-C2 (hex) Propagation Systems Limited - FCB000-FCBFFF (base 16) Propagation Systems Limited - Unit219A, 2/F, Enterprise Place, No.5 Science Park Science Park, - Hong Kong Science Park - Shatin - HONG KONG - - 00-50-C2 (hex) Soudronic AG - FCC000-FCCFFF (base 16) Soudronic AG - Industriestrasse 35 - Bergdietikon CH-8962 - SWITZERLAND - - 00-50-C2 (hex) Jinyoung Contech - FCD000-FCDFFF (base 16) Jinyoung Contech - #501 , MARIO TOWER, 222-12 - GURO 3-DONG, GURO-GU - Seoul 152 050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) KOYO ELECTRIC - FCE000-FCEFFF (base 16) KOYO ELECTRIC - 2-11-7 Hacchobori - 6F MC-Hacchobori-Bldg - Chuo-ku TOKYO 104-0032 - JAPAN - - 00-50-C2 (hex) DINTEK Shanghai Electronic Ltd - FCF000-FCFFFF (base 16) DINTEK Shanghai Electronic Ltd - Room 404 Tianlin Road NO 142 - Xuhui district - Shanghai 200233 - CHINA - - 00-50-C2 (hex) Simple Solutions - FD0000-FD0FFF (base 16) Simple Solutions - Alleenstr. 18 - Kirchheim unter Teck Baden-Württemberg 73230 - GERMANY - - 00-50-C2 (hex) Enyx SA - FD1000-FD1FFF (base 16) Enyx SA - 21, rue le Peletier - Paris Ile de France 75009 - FRANCE - - 00-50-C2 (hex) Autonomic Controls. Inc - FD2000-FD2FFF (base 16) Autonomic Controls. Inc - 28 Kaysal Court - Armonk NY 10504 - UNITED STATES - - 00-50-C2 (hex) Aster Electric Co.,Ltd. - FD3000-FD3FFF (base 16) Aster Electric Co.,Ltd. - 6-40 Minamiyamata3-chome,Tudukiku - Yokohama Kanagawa 2240029 - JAPAN - - 00-50-C2 (hex) Insitu, Inc. - FD4000-FD4FFF (base 16) Insitu, Inc. - 118 East Columbia River Way - Bingen WA 98605 - UNITED STATES - - 00-50-C2 (hex) American Microsystems, Ltd. - FD5000-FD5FFF (base 16) American Microsystems, Ltd. - 2190 Regal Pkwy - Euless TX 76040 - UNITED STATES - - 00-50-C2 (hex) City Computing Ltd - FD6000-FD6FFF (base 16) City Computing Ltd - City House - Sutton Park Road - Sutton Surrey SM1 2AE - UNITED KINGDOM - - 00-50-C2 (hex) Deuta-Werke GmbH - FD7000-FD7FFF (base 16) Deuta-Werke GmbH - Paffrather str. 140 - Bergisch Gladbach NRW 51465 - GERMANY - - 00-50-C2 (hex) Ease Inc. - FD8000-FD8FFF (base 16) Ease Inc. - Feliceappear 1F - 954-9 Akasaka-cho - Sano-shi Tochigi 327-0004 - JAPAN - - 00-50-C2 (hex) Figment Design Laboratories - FD9000-FD9FFF (base 16) Figment Design Laboratories - 113 11th Avenue - Fairland Johannesburg Guateng 2170 - SOUTH AFRICA - - 00-50-C2 (hex) ELAN SYSTEMS - FDA000-FDAFFF (base 16) ELAN SYSTEMS - 10 IHASZ STR - BUDAPEST 1105 - HUNGARY - - 00-50-C2 (hex) The Security Center Inc - FDB000-FDBFFF (base 16) The Security Center Inc - 10750 Forest Lane - Dallas TX 75243 - UNITED STATES - - 00-50-C2 (hex) QUERCUS TECHNOLOGIES, S.L. - FDC000-FDCFFF (base 16) QUERCUS TECHNOLOGIES, S.L. - Antoni Isern 4 bajos - Reus Tarragona 43205 - SPAIN - - 00-50-C2 (hex) Toptech Systems, Inc. - FDD000-FDDFFF (base 16) Toptech Systems, Inc. - 1124 Florida Central Parkway - Longwood FL 32750 - UNITED STATES - - 00-50-C2 (hex) Peek Traffic - FDE000-FDEFFF (base 16) Peek Traffic - 2906 Corporate Way - Palmetto FL 34235 - UNITED STATES - - 00-50-C2 (hex) ACD Elektronik GmbH - FDF000-FDFFFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 00-50-C2 (hex) Azurtest - FE0000-FE0FFF (base 16) Azurtest - 4-11-17 Hatiman Kawajima - Hikigun Saitama 3500151 - JAPAN - - 00-50-C2 (hex) dotOcean - FE1000-FE1FFF (base 16) dotOcean - Lieven Bauwensstraat 20 - Brugge West-Vlaanderen 8200 - BELGIUM - - 00-50-C2 (hex) Pulsotronic Anlagentechnik GmbH - FE2000-FE2FFF (base 16) Pulsotronic Anlagentechnik GmbH - Neue Schichtstrasse 7 - Niederdorf Saxony 09366 - GERMANY - - 00-50-C2 (hex) PRIVATE - FE3000-FE3FFF (base 16) - - 00-50-C2 (hex) RTT Mobile Interpretation - FE4000-FE4FFF (base 16) RTT Mobile Interpretation - 1107 Hazeltine Blvd. - Suite 535 - Chaska MN 55318 - UNITED STATES - - 00-50-C2 (hex) Scandinova Systems AB - FE5000-FE5FFF (base 16) Scandinova Systems AB - Ulltunaallen 2A - UPPSALA 75651 - SWEDEN - - 00-50-C2 (hex) Exibea AB - FE6000-FE6FFF (base 16) Exibea AB - Ekmansgatan 3 - Gothenburg Sweden 411 32 - SWEDEN - - 00-50-C2 (hex) Erhardt+Leimer GmbH - FE7000-FE7FFF (base 16) Erhardt+Leimer GmbH - Albert-Leimer-Platz 1 - Stadtbergen 86391 - GERMANY - - 00-50-C2 (hex) Mango DSP, Inc. - FE8000-FE8FFF (base 16) Mango DSP, Inc. - 83 East Ave. - Suite#115 - Norwalk CT 06877 - UNITED STATES - - 00-50-C2 (hex) MB Connect Line GmbH - FE9000-FE9FFF (base 16) MB Connect Line GmbH - Winnettener Straße 5 - Dinkelsbühl Bavaria 91550 - GERMANY - - 00-50-C2 (hex) Brunel GmbH Section Communications - FEA000-FEAFFF (base 16) Brunel GmbH Section Communications - Daimlerring 9 - Hildesheim Niedersachsen 31135 - GERMANY - - 00-50-C2 (hex) Axible Technologies - FEB000-FEBFFF (base 16) Axible Technologies - 425 Rue Jean Rostand - Labège 31670 - FRANCE - - 00-50-C2 (hex) First System Technology Co., Ltd. - FEC000-FECFFF (base 16) First System Technology Co., Ltd. - 1F., No.8, Alley 6, Lane 19, Fuhe Rd - Yonghe Dist. - New Taipei City 23449 - TAIWAN, PROVINCE OF CHINA - - 00-50-C2 (hex) LOGISOL Kft. - FED000-FEDFFF (base 16) LOGISOL Kft. - Bocskai u. 21. - Tinnye Pest-megye H-2086 - HUNGARY - - 00-50-C2 (hex) Sparks Instruments SA - FEE000-FEEFFF (base 16) Sparks Instruments SA - Bodematta 12 - Heitenried FR 1714 - SWITZERLAND - - 00-50-C2 (hex) Task Sistemas de Computacao - FEF000-FEFFFF (base 16) Task Sistemas de Computacao - Rua Visconde de Ouro Preto, 5 - oitavo andar - Rio de Janeiro RJ 22250-180 - BRAZIL - - 00-50-C2 (hex) GENERAL DYNAMICS C4 SYSTEMS - FF0000-FF0FFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST - SCOTTSDALE AZ 85257 - UNITED STATES - - 00-50-C2 (hex) DiTEST FAHRZEUGDIAGNOSE GMBH - FF1000-FF1FFF (base 16) DiTEST FAHRZEUGDIAGNOSE GMBH - ALTE POSTSTRASSE 152 - GRAZ STEIERMARK 8020 - AUSTRIA - - 00-50-C2 (hex) GLOBALCOM ENGINEERING SRL - FF2000-FF2FFF (base 16) GLOBALCOM ENGINEERING SRL - Via Volta 9 - MORNAGO VA 21020 - ITALY - - 00-50-C2 (hex) CONTROL SYSTEMS Srl - FF3000-FF3FFF (base 16) CONTROL SYSTEMS Srl - Via del Brolo, 14 - Cremona CR 26100 - ITALY - - 00-50-C2 (hex) Burk Technology - FF4000-FF4FFF (base 16) Burk Technology - 7 Beaver Brook Road - Littleton MA 01460 - UNITED STATES - - 00-50-C2 (hex) Flexkom Internet Pazarlama Bilipim ve Eoitim Hiz.Inp.Mim.Muh.Oto.Enerji San. Tic. A.p. - FF5000-FF5FFF (base 16) Flexkom Internet Pazarlama Bilipim ve Eoitim Hiz.Inp.Mim.Muh.Oto.Enerji San. Tic. A.p. - Aþkan Mh. Atakent Sk. No:15 Meram - Konya 42090 - TURKEY - - 00-50-C2 (hex) Booyco Electronics - FF6000-FF6FFF (base 16) Booyco Electronics - Unit 9, Innes Park - 38 Jansen Road - Jetpark Ext 14 Gauteng 1549 - SOUTH AFRICA - - 00-50-C2 (hex) Human Intech - FF7000-FF7FFF (base 16) Human Intech - #1213 JnK Dijital Tower, 222-3 - Guro-dong, Guro-gu Seoul 152-053 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) KST technology - FF8000-FF8FFF (base 16) KST technology - Bangi-dong, songpa-gu - kst b/d 164-1 - Seoul 138-050 - KOREA, REPUBLIC OF - - 00-50-C2 (hex) Penttech AB - FF9000-FF9FFF (base 16) Penttech AB - Vadursgatan 6 - Goteborg Vastra gotaland 412 50 - SWEDEN - - 00-50-C2 (hex) Nupoint Systems Inc. - FFA000-FFAFFF (base 16) Nupoint Systems Inc. - 4821 Colbrook Court - Burnaby BC V5G 3Y3 - CANADA - - 00-50-C2 (hex) SEFRAM - FFB000-FFBFFF (base 16) SEFRAM - 32 rue E MARTEL - BP 55 - SAINT-ETIENNE FRANCE 42009 - FRANCE - - 00-50-C2 (hex) Spirent Communications - FFC000-FFCFFF (base 16) Spirent Communications - 541 Industrial Way West - Eatontown New Jersey 07724 - UNITED STATES - - 00-50-C2 (hex) Touchless Biometric Systems AG - FFD000-FFDFFF (base 16) Touchless Biometric Systems AG - Rietbrunnen 2 - Pfaeffikon SZ 8808 - SWITZERLAND - - 00-50-C2 (hex) Sensata Technologies - FFE000-FFEFFF (base 16) Sensata Technologies - 4467 White Bear Parkway - White Bear Lake MN 55110 - UNITED STATES - - 00-50-C2 (hex) MSR-Solutions GmbH - FFF000-FFFFFF (base 16) MSR-Solutions GmbH - Friedrich-Ebert-Straße 20/2 - Wangen Baden-Württemberg 88239 - GERMANY - - 40-D8-55 (hex) XRONOS.INC - 000000-000FFF (base 16) XRONOS.INC - SENDAGAYA1-9-6 - SHIBUYAKU - TOKYO 151-0051 - JAPAN - - 40-D8-55 (hex) Vemotion - 001000-001FFF (base 16) Vemotion - Teleware House - York Road - Thirsk North Yorkshire YO7 3BX - UNITED KINGDOM - - 40-D8-55 (hex) Hangzhou Chenxiao Technologies Co. Ltd. - 002000-002FFF (base 16) Hangzhou Chenxiao Technologies Co. Ltd. - 7th Floor,No51,Huanxing Road,Bingjiang - Hangzhou Zhejiang 310052 - CHINA - - 40-D8-55 (hex) AlphaNavigation coltd - 003000-003FFF (base 16) AlphaNavigation coltd - 3-1-22 hitahonmachi - YAO OSAKA 581-0802 - JAPAN - - 40-D8-55 (hex) CR Magnetics, Inc. - 004000-004FFF (base 16) CR Magnetics, Inc. - 3500 Scarlet Oak Blvd - Saint Louis Missouri 63122 - UNITED STATES - - 40-D8-55 (hex) Monarch Instrument - 005000-005FFF (base 16) Monarch Instrument - 15 Columbia drive - Amherst NH 03031 - UNITED STATES - - 40-D8-55 (hex) Bactest Limited - 006000-006FFF (base 16) Bactest Limited - St John's Innovation Centre - Cowley Road - Cambridge Cambridgeshire CB4 0WS - UNITED KINGDOM - - 40-D8-55 (hex) Digital Audio SA - 007000-007FFF (base 16) Digital Audio SA - 3, chemin du Pre-Fleuri - PLAN-LES-OUATES GENEVA 1228 - SWITZERLAND - - 40-D8-55 (hex) Kaori Industria Eletronica Ltda - 008000-008FFF (base 16) Kaori Industria Eletronica Ltda - 1021, Dr. Reynaldo Machado - Prado Velho - Curitiba Parana 80215010 - BRAZIL - - 40-D8-55 (hex) ClearSite Communications Inc. - 009000-009FFF (base 16) ClearSite Communications Inc. - 6004 Clark Center Ave. - Sarasota Florida 34238 - UNITED STATES - - 40-D8-55 (hex) Sarana Sistem Mikro - 00A000-00AFFF (base 16) Sarana Sistem Mikro - JL.KEJAKSAAN NO 18 - PONDOK BAMBU - JAKARTA Click to Select 13430 - INDONESIA - - 40-D8-55 (hex) Aircell - 00B000-00BFFF (base 16) Aircell - 303 S Technology Ct - Building A - Broomfield CO 80021 - UNITED STATES - - 40-D8-55 (hex) Aplex Technology Inc. - 00C000-00CFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) HuNS - 00D000-00DFFF (base 16) HuNS - Pyeongchon-dong, Dongan-gu - Doosan Venture Digm, 311 - Anyang-si Gyeonggi-do 431-755 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Brightwell Dispensers - 00E000-00EFFF (base 16) Brightwell Dispensers - Brightwell Industrial Estate - Norton Road - Newhaven East Sussex BN9 0JF - UNITED KINGDOM - - 40-D8-55 (hex) DIGITAL DYNAMICS, INC. - 00F000-00FFFF (base 16) DIGITAL DYNAMICS, INC. - 5 VICTOR SQUARE - SCOTTS VALLEY CA. 95066 - UNITED STATES - - 40-D8-55 (hex) APG CASH DRAWER - 010000-010FFF (base 16) APG CASH DRAWER - 5250 INDUSTRIAL BLVD NE - MINNEAPOLIS Minnesota 55421 - UNITED STATES - - 40-D8-55 (hex) Flexim Security Oy - 011000-011FFF (base 16) Flexim Security Oy - P.O.Box 700 - Kornetintie 3 - Helsinki Southern Finland 00381 - FINLAND - - 40-D8-55 (hex) Sencon Inc. - 012000-012FFF (base 16) Sencon Inc. - 6385 W. 74th Street - Bedford Park IL 60638 - UNITED STATES - - 40-D8-55 (hex) Grande Vitesse Systems - 013000-013FFF (base 16) Grande Vitesse Systems - 390 Fremont St. - San Francisco CA 94105 - UNITED STATES - - 40-D8-55 (hex) Toni Studio - 014000-014FFF (base 16) Toni Studio - 2F., No.10, Aly. 4, Ln. 198 - Anle Rd., Yonghe Dist. - New Taipei City 234 - TAIWAN, PROVINCE OF CHINA - - 40-D8-55 (hex) BITMILL srl - 015000-015FFF (base 16) BITMILL srl - Corso Vercelli 125A - IVREA 10015 - ITALY - - 40-D8-55 (hex) Par-Tech, Inc. - 016000-016FFF (base 16) Par-Tech, Inc. - 139 Premier Drive - Lake Orion MI 48359 - UNITED STATES - - 40-D8-55 (hex) Franke Aquarotter GmbH - 017000-017FFF (base 16) Franke Aquarotter GmbH - Parkstra - Ludwigsfelde 14974 - GERMANY - - 40-D8-55 (hex) STANEO SAS - 018000-018FFF (base 16) STANEO SAS - 90 rue des trente-six ponts - Toulouse 31400 - FRANCE - - 40-D8-55 (hex) Nautel Limited - 019000-019FFF (base 16) Nautel Limited - 10089 Peggy's Cove Road - Hackett's Cove Nova Scotia B3Z 3J4 - CANADA - - 40-D8-55 (hex) MEGGITT DEFENSE SYSTEMS INC. - 01A000-01AFFF (base 16) MEGGITT DEFENSE SYSTEMS INC. - 9801 MUIRLANDS BLVD. - IRVINE CA 92618 - UNITED STATES - - 40-D8-55 (hex) Audio Enhancement - 01B000-01BFFF (base 16) Audio Enhancement - 14241 S. Redwood Road - Bluffdale UT 84065 - UNITED STATES - - 40-D8-55 (hex) BERG Cloud Limited - 01C000-01CFFF (base 16) BERG Cloud Limited - Epworth House - 25 City Road - London EC1Y 1AA - UNITED KINGDOM - - 40-D8-55 (hex) Scharco Elektronik GmbH - 01D000-01DFFF (base 16) Scharco Elektronik GmbH - Tilsiter Strasse 8 - Wuppertal NRW 42277 - GERMANY - - 40-D8-55 (hex) A2S - 01E000-01EFFF (base 16) A2S - ZA Le Rival 2 - Lafran 82130 - FRANCE - - 40-D8-55 (hex) Sitep Italia Spa - 01F000-01FFFF (base 16) Sitep Italia Spa - Via Vincinella 14 - Santo Stefano Magra La Spezia 19037 - ITALY - - 40-D8-55 (hex) ENTEC Electric & Electronic CO., LTD. - 020000-020FFF (base 16) ENTEC Electric & Electronic CO., LTD. - 225-38 Choirubaekro, Bongdam-eup - Hwaseong-city Gyeonggi-do 445-894 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) SMT D.O.O. - 021000-021FFF (base 16) SMT D.O.O. - LIMINJANSKA 96 - PORTORO PORTORO 6320 - SLOVENIA - - 40-D8-55 (hex) Digimerge Technology Inc - 022000-022FFF (base 16) Digimerge Technology Inc - 250 Royal Crest Court - Markham Ontario L3R 3S1 - CANADA - - 40-D8-55 (hex) Shanghai o-solution electronics & Technology Co., Ltd. - 023000-023FFF (base 16) Shanghai o-solution electronics & Technology Co., Ltd. - 4226 Duzhuang Rd, Minhang District - Building D,Room 405 - Shanghai Shanghai 201108 - CHINA - - 40-D8-55 (hex) Electrical Geodesics Incorporated - 024000-024FFF (base 16) Electrical Geodesics Incorporated - 1600 Millrace Drive - Eugene Oregon 97403-1995 - UNITED STATES - - 40-D8-55 (hex) Rosemount Analytical - 025000-025FFF (base 16) Rosemount Analytical - 10241 West Little York - Suite 200 - Houston TX 77040 - UNITED STATES - - 40-D8-55 (hex) Symetrics Industries - 026000-026FFF (base 16) Symetrics Industries - 1615 W. Nasa Blvd - Melbourne FL 32901 - UNITED STATES - - 40-D8-55 (hex) GRUPO EPELSA S.L. - 027000-027FFF (base 16) GRUPO EPELSA S.L. - CALLE PUNTO NET, 3 - ALCALA DE HENARES MADRID 28805 - SPAIN - - 40-D8-55 (hex) Integrated Control Corp. - 028000-028FFF (base 16) Integrated Control Corp. - 748 Park Ave - Huntington NY 11743 - UNITED STATES - - 40-D8-55 (hex) Depro Electronique - 029000-029FFF (base 16) Depro Electronique - 755 cure-boivin - suite 101 - Boisbriand Quebec J7G 2J2 - CANADA - - 40-D8-55 (hex) Tinkerforge GmbH - 02A000-02AFFF (base 16) Tinkerforge GmbH - Roemerstr. 18 - Stukenbrock NRW 33758 - GERMANY - - 40-D8-55 (hex) Nomatronics - 02B000-02BFFF (base 16) Nomatronics - Kastanienweg 35E - Diedrichshagen M/V 17498 - GERMANY - - 40-D8-55 (hex) InventLab s.c. - 02C000-02CFFF (base 16) InventLab s.c. - ul. Czarodziejska 22 - Wolka Kozodawska Masovian 05-502 - POLAND - - 40-D8-55 (hex) Elgama Sistemos - 02D000-02DFFF (base 16) Elgama Sistemos - Visoriu g. 2 - Vilniaus LT-08300 - LITHUANIA - - 40-D8-55 (hex) Circuitec Ind. Equip. Eletr. Ltda - 02E000-02EFFF (base 16) Circuitec Ind. Equip. Eletr. Ltda - Rua Gustavo Zimmermann, 2431 - Itoupava Central - Blumenau Santa Catarina 89062-100 - BRAZIL - - 40-D8-55 (hex) Adva Technologies - 02F000-02FFFF (base 16) Adva Technologies - 1 Bowen Road - Lilydale Victoria 3140 - AUSTRALIA - - 40-D8-55 (hex) Tecnologias Plexus - 030000-030FFF (base 16) Tecnologias Plexus - Rua Jose Villar Granjel, 22-24 - Poligono De Boisaca - Santiago de Compostela A Coruna 15890 - SPAIN - - 40-D8-55 (hex) Dommel GmbH - 031000-031FFF (base 16) Dommel GmbH - Westring 15 - Wassertruedingen bavaria 91717 - GERMANY - - 40-D8-55 (hex) BETTINI SRL - 032000-032FFF (base 16) BETTINI SRL - VIA GRIEG 23 - SARONNO VARESE 21047 - ITALY - - 40-D8-55 (hex) Ermes Elettronica s.r.l. - 033000-033FFF (base 16) Ermes Elettronica s.r.l. - Via Treviso, 36 - San Vendemiano TV 31020 - ITALY - - 40-D8-55 (hex) Dacom West GmbH - 034000-034FFF (base 16) Dacom West GmbH - Schallbruch 19-21 - Haan NRW 42781 - GERMANY - - 40-D8-55 (hex) Mesotech International, Inc. - 035000-035FFF (base 16) Mesotech International, Inc. - 4531 Harlin Drive - Sacramento CA 95826 - UNITED STATES - - 40-D8-55 (hex) Schweers informationstechnologie GmbH - 036000-036FFF (base 16) Schweers informationstechnologie GmbH - Rudolf-Diesel-Str. 18 - Meerbusch 40670 - GERMANY - - 40-D8-55 (hex) Software Workshop - 037000-037FFF (base 16) Software Workshop - 402B Steel Chambers - Devji Ratansey Marg - Mumbai Maharashtra 400009 - INDIA - - 40-D8-55 (hex) Special Measurements Labs LLC - 038000-038FFF (base 16) Special Measurements Labs LLC - ul. Nartova, 6 - Nizhny Novgorod 603104 - RUSSIAN FEDERATION - - 40-D8-55 (hex) CI Systems Ltd - 039000-039FFF (base 16) CI Systems Ltd - HaMehkar 6 Str. - POBox 147 - Migdal HaEmek IL 10551 - ISRAEL - - 40-D8-55 (hex) Socus networks - 03A000-03AFFF (base 16) Socus networks - 2F.-2, No.215, Sec. 2, Chengde Rd. - Datong Dist. - Taipei City 103 - TAIWAN, PROVINCE OF CHINA - - 40-D8-55 (hex) Telcomkorea - 03B000-03BFFF (base 16) Telcomkorea - #710-8, Lee-Dong, Sanglok-Gu, - 2'nd - Ansan-Si Kyunggi-Do 426863 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Computer System Co.,Ltd - 03C000-03CFFF (base 16) Computer System Co.,Ltd - Matsuyama-Daiichi-Seimei Bldg 8F - Ichiban-cho 3-2-11 - Matsuyama EHIME 790-0001 - JAPAN - - 40-D8-55 (hex) Tekelek Europe Ltd - 03D000-03DFFF (base 16) Tekelek Europe Ltd - Unit 118 Shannon Free zone - Shannon Co. Clare - IRELAND - - 40-D8-55 (hex) Vishay Celtron Technologies, Inc. - 03E000-03EFFF (base 16) Vishay Celtron Technologies, Inc. - 8F, No. 171-1, Sec. 2, Datong Rd., Sijhih City, - Taipei 22183 - TAIWAN, PROVINCE OF CHINA - - 40-D8-55 (hex) UniSVR Global Information Technology Corp. - 03F000-03FFFF (base 16) UniSVR Global Information Technology Corp. - 3F., No.6, Gongye E. 3rd Rd., Hsinchu Science Park. - Hsinchu 30075 - TAIWAN, PROVINCE OF CHINA - - 40-D8-55 (hex) GHL Systems Berhad - 040000-040FFF (base 16) GHL Systems Berhad - L5-E-7B Enterprise 4 - Technology Park Malaysia - Bukit Jalil Kuala Lumpur 57000 - MALAYSIA - - 40-D8-55 (hex) T.Q.M. Itaca Technology s.r.l. - 041000-041FFF (base 16) T.Q.M. Itaca Technology s.r.l. - Via E. Mattei 1 - Mazzano Brescia 25080 - ITALY - - 40-D8-55 (hex) Mango Communicaitons Inc. - 042000-042FFF (base 16) Mango Communicaitons Inc. - 4606 Morningside Dr. - Suite B - Houston TX 77005 - UNITED STATES - - 40-D8-55 (hex) SchulerControl GmbH - 043000-043FFF (base 16) SchulerControl GmbH - Richard-Schirrmannstr. 29 - Titisee-Neustadt BW 79822 - GERMANY - - 40-D8-55 (hex) An Chen Computer Co. Ltd. - 044000-044FFF (base 16) An Chen Computer Co. Ltd. - 2F.,No.37,Sec. 2, San Min Rd., - Ban Chiao District - New Taipei City 220 - TAIWAN, PROVINCE OF CHINA - - 40-D8-55 (hex) Genadsystem - 045000-045FFF (base 16) Genadsystem - #522 Innoplex Bldg. 1-613, Wonchen-dong - Yeongtong-gu - Suwon Gyeonggi-do 443-380 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Circuitlink Pty Ltd - 046000-046FFF (base 16) Circuitlink Pty Ltd - 7a / 30 Foundry Rd - Seven Hills NSW 2147 - AUSTRALIA - - 40-D8-55 (hex) Dos&Donts SRL - 047000-047FFF (base 16) Dos&Donts SRL - Via Italo Calvino,7 - Rho Milano 20017 - ITALY - - 40-D8-55 (hex) GENERAL DYNAMICS C4 SYSTEMS - 048000-048FFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT STREET MD: R2121 - SCOTTSDALE AZ 85257 - UNITED STATES - - 40-D8-55 (hex) Thermo Fisher Scientific - 049000-049FFF (base 16) Thermo Fisher Scientific - 1410 Gillingham Lane - Sugar Land Texas 77478 - UNITED STATES - - 40-D8-55 (hex) Gateway Technologies SA de CV - 04A000-04AFFF (base 16) Gateway Technologies SA de CV - 40 North Central Ave, Suite 1400 - Phoenix Arizona 85004 - UNITED STATES - - 40-D8-55 (hex) Vital Tech Industria e Comercio Ltda - 04B000-04BFFF (base 16) Vital Tech Industria e Comercio Ltda - Rua Jose Villar Granjel, 22-24 - Bairro Sao Bernardo - Camipnas - San Paulo 13030680 - BRAZIL - - 40-D8-55 (hex) Serveron Corporation - 04C000-04CFFF (base 16) Serveron Corporation - 20325 NW Von Neumann Dr - Suite 120 - Beaverton Oregon 97006 - UNITED STATES - - 40-D8-55 (hex) MACHINEPERFORMANCE ApS - 04D000-04DFFF (base 16) MACHINEPERFORMANCE ApS - Firskovej 23,1 - Kgs. Lyngby Denmark DK-2800 - DENMARK - - 40-D8-55 (hex) Honeywell Aerospace/Intelligent Automation Corp. - 04E000-04EFFF (base 16) Honeywell Aerospace/Intelligent Automation Corp. - 13125 Danielson Street - Poway California 92064 - UNITED STATES - - 40-D8-55 (hex) Haein S&S Co., Ltd - 04F000-04FFFF (base 16) Haein S&S Co., Ltd - #1213 12th FL Daeryoung Teco town - gasandong gumchungu - Seoul 153-802 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) ATG UV Technology - 050000-050FFF (base 16) ATG UV Technology - Genesis House - Richmond Hill - Wigan WN5 8AA - UNITED KINGDOM - - 40-D8-55 (hex) CS Instruments Asia - 051000-051FFF (base 16) CS Instruments Asia - Room 31, Cambridge Plaza, Tower B - 188 San Wan Road, Sheung Shui, N.T - Hong Kong 000008 - HONG KONG - - 40-D8-55 (hex) DAN ELECTRONICS SYSTEM (P) LIMITED - 052000-052FFF (base 16) DAN ELECTRONICS SYSTEM (P) LIMITED - 546A, SECTOR - 37 - PACE CITY - 2, UDYOG VIHAR PHASE - 6 - GURGAON HARYANA 122001 - INDIA - - 40-D8-55 (hex) Amantys Ltd - 053000-053FFF (base 16) Amantys Ltd - Platinum Building, St John's Innovation Park - Cowley Road - Cambridge Cambridgeshire CB4 0WS - UNITED KINGDOM - - 40-D8-55 (hex) VITEC - 054000-054FFF (base 16) VITEC - 99, rue Pierre Semard - Chatillon Ile de France 92324 - FRANCE - - 40-D8-55 (hex) Helmholtz Zentrum Dresden Rossendorf e.V. - 055000-055FFF (base 16) Helmholtz Zentrum Dresden Rossendorf e.V. - Bautzner Landstrasse 400 - Dresden Sachsen 01328 - GERMANY - - 40-D8-55 (hex) GROUP 57 - 056000-056FFF (base 16) GROUP 57 - Burgemeestersrand 37 - Delft ZH 2625 NV - NETHERLANDS - - 40-D8-55 (hex) Tammermatic Group Oy - 057000-057FFF (base 16) Tammermatic Group Oy - Tesomanvaltatie 28 - Tampere 33300 - FINLAND - - 40-D8-55 (hex) Energy Team S.p.A. - 058000-058FFF (base 16) Energy Team S.p.A. - Via della Repubblica, 9 - Trezzano sul Naviglio Milano 20090 - ITALY - - 40-D8-55 (hex) COLONIAL ASSEMBLY and DESIGN - 059000-059FFF (base 16) COLONIAL ASSEMBLY and DESIGN - 3361 SHANNON AIRPORT CIRCLE - FREDERICKSBURG VIRGINIA 22408 - UNITED STATES - - 40-D8-55 (hex) Ultra Electronics Flightline Systems - 05A000-05AFFF (base 16) Ultra Electronics Flightline Systems - 7625 Omnitech Place - Victor NY 14564-9795 - UNITED STATES - - 40-D8-55 (hex) Data Flow Systems, Inc. - 05B000-05BFFF (base 16) Data Flow Systems, Inc. - 605 N. John Rodes Blvd. - Melbourne Fl 32934 - UNITED STATES - - 40-D8-55 (hex) Rosslare Enterprises Limited - 05C000-05CFFF (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon 00000 - HONG KONG - - 40-D8-55 (hex) Leica Biosystems - 05D000-05DFFF (base 16) Leica Biosystems - 5205 Route 12 - Richmond Illinois 60071 - UNITED STATES - - 40-D8-55 (hex) inoage GmbH - 05E000-05EFFF (base 16) inoage GmbH - Fetscherplatz 5 - Dresden Sachsen 01307 - GERMANY - - 40-D8-55 (hex) EPSa GmbH - 05F000-05FFFF (base 16) EPSa GmbH - Remschuetzer Strasse 1 - Saalfeld/Saale Thuringia 07318 - GERMANY - - 40-D8-55 (hex) Aplex Technology Inc. - 060000-060FFF (base 16) Aplex Technology Inc. - NanYouTianAn industrial park Tower4 - Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) Cominfo, Inc. - 061000-061FFF (base 16) Cominfo, Inc. - Nabrezi 695 - Zlin 760 01 - CZECH REPUBLIC - - 40-D8-55 (hex) Tech Source Inc - 062000-062FFF (base 16) Tech Source Inc - 442 Northlake Blvd - Suite 1008 - Altamonte Springs FL 32701 - UNITED STATES - - 40-D8-55 (hex) Protonic Holland - 063000-063FFF (base 16) Protonic Holland - Factorij 36 - Zwaag NH Netherlands 1689 AL - NETHERLANDS - - 40-D8-55 (hex) HIPODROMO DE AGUA CALIENTE, S.A. DE C.V. - 064000-064FFF (base 16) HIPODROMO DE AGUA CALIENTE, S.A. DE C.V. - BLVD. AGUA CALIENTE 12027 - COL. HIPODROMO - TIJUANA BAJA CALIFORNIA 22420 - MEXICO - - 40-D8-55 (hex) Parallel Wireless - 065000-065FFF (base 16) Parallel Wireless - 1 Tara Blvd - Suite LL8 - Nashua NH 03062 - UNITED STATES - - 40-D8-55 (hex) TeraTron GmbH - 066000-066FFF (base 16) TeraTron GmbH - Bunsenstr. 10 - Windhagen - Gummersbach DE 51647 - GERMANY - - 40-D8-55 (hex) Tronic Control ltd. - 067000-067FFF (base 16) Tronic Control ltd. - Nad Safinou I, 449 - Vestec u Prahy 25242 - CZECH REPUBLIC - - 40-D8-55 (hex) Oki Seatec Co., Ltd. - 068000-068FFF (base 16) Oki Seatec Co., Ltd. - UchiuraMito 537-5 - Numazu Shizuoka 410-0223 - JAPAN - - 40-D8-55 (hex) Smartcom-Bulgaria AD - 069000-069FFF (base 16) Smartcom-Bulgaria AD - Tsarigradsko shosse 7th km - BIC IZOT, Office 317 - Sofia 1784 - BULGARIA - - 40-D8-55 (hex) elgris - 06A000-06AFFF (base 16) elgris - Krantzstr 7 - Halle 6 - Aachen NRW 52070 - GERMANY - - 40-D8-55 (hex) BRS Sistemas Eletronicos - 06B000-06BFFF (base 16) BRS Sistemas Eletronicos - Rua Gomes de Freitas, 491/204 - Porto Alegre RS 91380-000 - BRAZIL - - 40-D8-55 (hex) Rohde&Schwarz Topex SA - 06C000-06CFFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacu street, district 1 - Bucharest 014186 - ROMANIA - - 40-D8-55 (hex) BroadSoft, INC - 06D000-06DFFF (base 16) BroadSoft, INC - 550 S Winchester Blvd - STE 250 - San Jose CA 95128 - UNITED STATES - - 40-D8-55 (hex) C-COM Satellite Systems Inc. - 06E000-06EFFF (base 16) C-COM Satellite Systems Inc. - 2574 Sheffield Road - Ottawa ONTARIO K1B3V7 - CANADA - - 40-D8-55 (hex) DORLET SA - 06F000-06FFFF (base 16) DORLET SA - Albert Eistein 34 - Parque Tecnologico de Alava - Miñano Mayor Alava 01510 - SPAIN - - 40-D8-55 (hex) JSC Electrical Equipment Factory - 070000-070FFF (base 16) JSC Electrical Equipment Factory - Otradnaya str, 6 - Moscow 129626 - RUSSIAN FEDERATION - - 40-D8-55 (hex) TATTILE SRL - 071000-071FFF (base 16) TATTILE SRL - via Donizetti 1/3/5 - Mairano Brescia 25030 - ITALY - - 40-D8-55 (hex) CT Company - 072000-072FFF (base 16) CT Company - Nizhni Krasnoselsky st.,35 - Moscow RUSSIA 140070 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Diamond Technologies, Inc - 073000-073FFF (base 16) Diamond Technologies, Inc - 6 Clock Tower Place, Suite 100 - Maynard MA 01754 - UNITED STATES - - 40-D8-55 (hex) Sphere Medical Ltd - 074000-074FFF (base 16) Sphere Medical Ltd - Harston Mill - Cambridge CB22 7GG - UNITED KINGDOM - - 40-D8-55 (hex) Teraflops - 075000-075FFF (base 16) Teraflops - 1326 Monde - Sojya city Okayama prefecture 7191156 - JAPAN - - 40-D8-55 (hex) INTERNET PROTOCOLO LOGICA SL - 076000-076FFF (base 16) INTERNET PROTOCOLO LOGICA SL - Sector Foresta 43. local 26 - Edificio OfiCentro - Tres Cantos Madrid 28760 - SPAIN - - 40-D8-55 (hex) TOEC TECHNOLOGY CO.,LTD - 077000-077FFF (base 16) TOEC TECHNOLOGY CO.,LTD - 6 Taishan Road Hexi District - Tianjin 300211 - CHINA - - 40-D8-55 (hex) NACHI-FUJIKOSHI CORP - 078000-078FFF (base 16) NACHI-FUJIKOSHI CORP - 1-1-1 Fujikoshi honmachi - Toyama 930-8511 - JAPAN - - 40-D8-55 (hex) DelfiSolutions A/S - 079000-079FFF (base 16) DelfiSolutions A/S - Augustenborglandevej 7 - Sønderborg Denmark 6400 - DENMARK - - 40-D8-55 (hex) 4embedded - 07A000-07AFFF (base 16) 4embedded - 1679 N 850 W - Orem UT 84057 - UNITED STATES - - 40-D8-55 (hex) IPS Technology Limited - 07B000-07BFFF (base 16) IPS Technology Limited - 7 Floor,E block,Dong Hai Wang Building,BuLong Road, - LongGang District - Shenzhen Guangdong 518000 - CHINA - - 40-D8-55 (hex) Agramkow Fluid Systems A/S - 07C000-07CFFF (base 16) Agramkow Fluid Systems A/S - Augustenborg Landevej 19 - Soenderborg DK 6400 - DENMARK - - 40-D8-55 (hex) Wuxi SiNeng New Energy Co., Ltd. - 07D000-07DFFF (base 16) Wuxi SiNeng New Energy Co., Ltd. - No.1 Wind power Road, Wind Power Technology Industrial Park - Wuxi Huishan Economic Development Zone - Wuxi Jiangsu Province 214000 - CHINA - - 40-D8-55 (hex) TESCOM CORPORATION - 07E000-07EFFF (base 16) TESCOM CORPORATION - 29-8 Teramachi - Hachioji Tokyo 192-0073 - JAPAN - - 40-D8-55 (hex) Wheatstone Corporation - 07F000-07FFFF (base 16) Wheatstone Corporation - 600 Industrial Drive - New Bern NC 28562 - UNITED STATES - - 40-D8-55 (hex) Honeywell - 080000-080FFF (base 16) Honeywell - 13350 US Highway 19 N - Clearwater FL 33764 - UNITED STATES - - 40-D8-55 (hex) Sicon srl - 081000-081FFF (base 16) Sicon srl - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 40-D8-55 (hex) ARD SA - 082000-082FFF (base 16) ARD SA - Micropolis Bat Clematis - Gap France 05000 - FRANCE - - 40-D8-55 (hex) DELOPT - 083000-083FFF (base 16) DELOPT - #3&4, 1st Cross, 7th Main - J C Industrial Area - Bangalore Karnataka 560062 - INDIA - - 40-D8-55 (hex) Papendorf Software Engineering GmbH - 084000-084FFF (base 16) Papendorf Software Engineering GmbH - Robert-Bosch-Str. 10 - Gaertringen Baden-Wuerttemberg 71116 - GERMANY - - 40-D8-55 (hex) Peek Traffic Corporation - 085000-085FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Fl 34221 - UNITED STATES - - 40-D8-55 (hex) DSP DESIGN - 086000-086FFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 OTZ - UNITED KINGDOM - - 40-D8-55 (hex) Bestel China - 087000-087FFF (base 16) Bestel China - GaoLiangQia 19th - Haidian District - Beijing 100081 - CHINA - - 40-D8-55 (hex) JEL SYSTEM CO., LTD. - 088000-088FFF (base 16) JEL SYSTEM CO., LTD. - 14-1, IKENOIRIYAMA, FUMASE - IZUMIZAKI-MURA, NISHISHIRAKAWA-GUN FUKUSHIMA 969-0105 - JAPAN - - 40-D8-55 (hex) WUHAN XINGTUXINKE ELECTRONIC CO.,LTD - 089000-089FFF (base 16) WUHAN XINGTUXINKE ELECTRONIC CO.,LTD - NO.C3-8F,SOFTWARE PARK - OPTICS VALLEY - Wuhan Hubei 430074 - CHINA - - 40-D8-55 (hex) Leder Elektronik Design - 08A000-08AFFF (base 16) Leder Elektronik Design - Bruchweg 10 - Ketsch Baden-Wuerttemberg 68775 - GERMANY - - 40-D8-55 (hex) MeshWorks Wireless Oy - 08B000-08BFFF (base 16) MeshWorks Wireless Oy - Haarlankatu 1 J - Tampere Suomi 33230 - FINLAND - - 40-D8-55 (hex) Magnescale Co.,Ltd - 08C000-08CFFF (base 16) Magnescale Co.,Ltd - 45,Suzukawa - Isehara Kanagawa 259-1146 - JAPAN - - 40-D8-55 (hex) Boehme Nachrichtentechnik - 08D000-08DFFF (base 16) Boehme Nachrichtentechnik - Hauptstrasse 32 - Siek Schleswig-Holstein 22962 - GERMANY - - 40-D8-55 (hex) Lyngsoe Systems - 08E000-08EFFF (base 16) Lyngsoe Systems - 5570 Kennedy Rd - Unit B - Mississauga On L4Z 2A9 - CANADA - - 40-D8-55 (hex) Excelitas - 08F000-08FFFF (base 16) Excelitas - 1330 E Cypress St - Covina CA 91724 - UNITED STATES - - 40-D8-55 (hex) Axxess Identification Ltd - 090000-090FFF (base 16) Axxess Identification Ltd - 27-28 Shrivenham Hundred Business Park - Majors Road - Swindon Wiltshire SN6 8TZ - UNITED KINGDOM - - 40-D8-55 (hex) KDT - 091000-091FFF (base 16) KDT - 203-902, bucheon Techno-park 192, Yakdae-dong, Wonmi-gu - Bucheon-si Gyeonggi-do 420-733 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Wasserbauer GmbH - 092000-092FFF (base 16) Wasserbauer GmbH - Gewerbestraße 1 - Waldneukirchen 4595 - AUSTRIA - - 40-D8-55 (hex) Sentry 360 Security - 093000-093FFF (base 16) Sentry 360 Security - 24012 W Renwick Road - Plainfield IL 60544 - UNITED STATES - - 40-D8-55 (hex) Nomad Digital Limited - 094000-094FFF (base 16) Nomad Digital Limited - 3 Broad Chare - Newcastle Tye & Wear NE1 3DQ - UNITED KINGDOM - - 40-D8-55 (hex) Heart Force Medical - 095000-095FFF (base 16) Heart Force Medical - 212 - 2112 West Broadway - Vancouver BC V6K 2C8 - CANADA - - 40-D8-55 (hex) Comtel Electronics GmbH - 096000-096FFF (base 16) Comtel Electronics GmbH - Bretonischer Ring 11 - Grasbrunn 85630 - GERMANY - - 40-D8-55 (hex) Burton Technical Services LLC - 097000-097FFF (base 16) Burton Technical Services LLC - 1214 Metro Park Blvd - Suite 101 - Lewisville Texas 75057 - UNITED STATES - - 40-D8-55 (hex) Dave Srl - 098000-098FFF (base 16) Dave Srl - Via Talponedo 29a - Porcia Pordenone 33080 - ITALY - - 40-D8-55 (hex) idcell co.ltd - 099000-099FFF (base 16) idcell co.ltd - 565 Iteco, Deokpung 3-dong - Gyeonggi-do - Hanam-si 465-736 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) CoherentPlus Sdn Bhd - 09A000-09AFFF (base 16) CoherentPlus Sdn Bhd - B-8-9, Megan Avenue 2 - 12 Jalan Yap Kwan Seng - Kuala Lumpur Kuala Lumpur 50450 - MALAYSIA - - 40-D8-55 (hex) Tokyo Denki Gijutsu Kogyo - 09B000-09BFFF (base 16) Tokyo Denki Gijutsu Kogyo - 2-12-2 Nakane Meguro-ku - TOKYO 152-0031 - JAPAN - - 40-D8-55 (hex) Keyware Solutions Inc. - 09C000-09CFFF (base 16) Keyware Solutions Inc. - 5-37-18 Kamikitazawa - Setagaya-ku Tokyo 156-8588 - JAPAN - - 40-D8-55 (hex) EMAC, Inc. - 09D000-09DFFF (base 16) EMAC, Inc. - 2309 EMAC Way - Carbondale Illinois 62902 - UNITED STATES - - 40-D8-55 (hex) NanoPulse, Inc. - 09E000-09EFFF (base 16) NanoPulse, Inc. - 1 Krasnoselskiy per., 3 pom. I, of. 75 - Moscow 107140 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Bascules Robbe nv - 09F000-09FFFF (base 16) Bascules Robbe nv - Noordlaan 7 - Torhout West-Vlaanderen 8820 - BELGIUM - - 40-D8-55 (hex) Quantronix, Inc. - 0A0000-0A0FFF (base 16) Quantronix, Inc. - 380 S. 200 W. - Farmington Utah 84025 - UNITED STATES - - 40-D8-55 (hex) ADVALY SYSTEM Inc. - 0A1000-0A1FFF (base 16) ADVALY SYSTEM Inc. - 7 KITA2 NISHI2 CYUO-KU - KAMIYAMA No.2 BUILDING - SAPPORO HOKKAIDO 060-0002 - JAPAN - - 40-D8-55 (hex) Xemex NV - 0A2000-0A2FFF (base 16) Xemex NV - Metropoolstraat 11 - Schoten Antwerp 2900 - BELGIUM - - 40-D8-55 (hex) Telefrank GmbH - 0A3000-0A3FFF (base 16) Telefrank GmbH - Am Wildengrund 1 - Altenambach TH 98553 - GERMANY - - 40-D8-55 (hex) Resch Electronic Innovation GmbH - 0A4000-0A4FFF (base 16) Resch Electronic Innovation GmbH - Neustadter Ring 5 - Wernigerode Sachsen-Anhalt 38855 - GERMANY - - 40-D8-55 (hex) WooshCom Corporation - 0A5000-0A5FFF (base 16) WooshCom Corporation - 16095 Ridge Tee Dr. - Suite 100 - Morrison CO 80465-2140 - UNITED STATES - - 40-D8-55 (hex) Alumbra Produtos Elétricos e Eletrônicos Ltda - 0A6000-0A6FFF (base 16) Alumbra Produtos Elétricos e Eletrônicos Ltda - Rua Guimarães Rosa, 450 - São Bernardo do Campo São Paulo 09851-380 - BRAZIL - - 40-D8-55 (hex) First Design System Inc. - 0A7000-0A7FFF (base 16) First Design System Inc. - Tachibana Shinjyuku Bldg. 4F - 3-2-26, Nishishinjyuku, - Shinjyuku-ku, Tokyo 1600023 - JAPAN - - 40-D8-55 (hex) Baudisch Electronic GmbH - 0A8000-0A8FFF (base 16) Baudisch Electronic GmbH - Im Gewerbegebiet 7-9 - Wäschenbeuren Baden Würrtemberg 73116 - GERMANY - - 40-D8-55 (hex) Apantac LLC - 0A9000-0A9FFF (base 16) Apantac LLC - 7556 SW Bridgeport Road - Durham OR 97224 - UNITED STATES - - 40-D8-55 (hex) Thermal Imaging Radar, LLC - 0AA000-0AAFFF (base 16) Thermal Imaging Radar, LLC - 1304 N. Redwood Rd. Unit 122 - Saratoga Springs Utah 84045 - UNITED STATES - - 40-D8-55 (hex) Enel doo Belgrade - 0AB000-0ABFFF (base 16) Enel doo Belgrade - Petrovaradinska no. 26, 11000 Belgrade, Serbia - Belgrade Serbia 11000 - SERBIA - - 40-D8-55 (hex) Fraunhofer HHI - 0AC000-0ACFFF (base 16) Fraunhofer HHI - Einsteinufer 37 - Berlin 10587 - GERMANY - - 40-D8-55 (hex) Space Micro - 0AD000-0ADFFF (base 16) Space Micro - 10237 Flanders Court - San Diego California 92121 - UNITED STATES - - 40-D8-55 (hex) GENERAL DYNAMICS C4 SYSTEMS - 0AE000-0AEFFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST. R2121 - SCOTTSDALE AZ 85257 - UNITED STATES - - 40-D8-55 (hex) EnVerv Inc. - 0AF000-0AFFFF (base 16) EnVerv Inc. - 680 N. McCarthy Blvd., Suite 220 - MILPITAS CA 95035 - UNITED STATES - - 40-D8-55 (hex) Micrologic - 0B0000-0B0FFF (base 16) Micrologic - Via Brodolini, 6 - Crevoladossola Verbania 28865 - ITALY - - 40-D8-55 (hex) Nanjing TIANSU Automation Control System Co., Ltd. - 0B1000-0B1FFF (base 16) Nanjing TIANSU Automation Control System Co., Ltd. - Building 5, New Town Science & Technology Park - No.69 Olympic Stadium Street - Nanjing China 210019 - CHINA - - 40-D8-55 (hex) Ever Trend Technology Development Limited - 0B2000-0B2FFF (base 16) Ever Trend Technology Development Limited - Pokfulam 86D Floor 1 Room D - Hong Kong Hong Kong 000 - HONG KONG - - 40-D8-55 (hex) T.W.S. srl - 0B3000-0B3FFF (base 16) T.W.S. srl - Viale Zaccagna 6 - Carrara MS 54033 - ITALY - - 40-D8-55 (hex) MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. - 0B4000-0B4FFF (base 16) MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. - 26-43,1-Chome,Yata,Higashi-ku - Nagoya Aichi 461-0040 - JAPAN - - 40-D8-55 (hex) DATA SHARING CONSULTING - 0B5000-0B5FFF (base 16) DATA SHARING CONSULTING - 815 AV IRENE ET FREDERIC JOLIOT CURIE - ZI TOUON EST - LA GARDE PACA 83130 - FRANCE - - 40-D8-55 (hex) Telvent - 0B6000-0B6FFF (base 16) Telvent - P.I. Alcobendas C/ Valgrande, 6 - Alcobendas Madrid 28108 - SPAIN - - 40-D8-55 (hex) ACD Elektronik GmbH - 0B7000-0B7FFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 40-D8-55 (hex) Ferlin Trading BV - 0B8000-0B8FFF (base 16) Ferlin Trading BV - Galileistraat 29 - Dedemsvaart Overijssel 7701 SK - NETHERLANDS - - 40-D8-55 (hex) WxBR Sistemas de Telecomunicacoes Ltda - 0B9000-0B9FFF (base 16) WxBR Sistemas de Telecomunicacoes Ltda - Rua Dr Ricardo Benetton Martins, S/N - Cond. Polis II, Predio 12C mesanino - Campinas São Paulo 13086902 - BRAZIL - - 40-D8-55 (hex) PCH Engineering A/S - 0BA000-0BAFFF (base 16) PCH Engineering A/S - Ved Klaedebo 4 - Horsholm 2970 - DENMARK - - 40-D8-55 (hex) Whiptail - 0BB000-0BBFFF (base 16) Whiptail - 9 Whippany Rd - B2, Suites 6 & 7 - Whippany NJ 07981 - UNITED STATES - - 40-D8-55 (hex) Aplex Technology Inc. - 0BC000-0BCFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 - Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) iCOGNIZE GmbH - 0BD000-0BDFFF (base 16) iCOGNIZE GmbH - Justus-von-Liebig Str. 9 - Dietzenbach Hesse 63128 - GERMANY - - 40-D8-55 (hex) Manufacturing System Insights Inc - 0BE000-0BEFFF (base 16) Manufacturing System Insights Inc - 2560 Ninth Street, Suite 123A - Berkeley CA 94710 - UNITED STATES - - 40-D8-55 (hex) Shenzhen SETEC Power Co.,Ltd - 0BF000-0BFFFF (base 16) Shenzhen SETEC Power Co.,Ltd - #199, Setec Industrial Park - Dakan, Xili Town - Nanshan District, Shenzhen Guangdong 518055 - CHINA - - 40-D8-55 (hex) ACT - 0C0000-0C0FFF (base 16) ACT - Unit C1 - South City Business Center - Tallaght Dublin - IRELAND - - 40-D8-55 (hex) Xepto Computing Inc - 0C1000-0C1FFF (base 16) Xepto Computing Inc - Unit 2202, 22F Asian Star Building - Filinvest Corporate City - Alabang Muntinlupa 1781 - PHILIPPINES - - 40-D8-55 (hex) SC Techswarm SRL - 0C2000-0C2FFF (base 16) SC Techswarm SRL - Lapusului Street, Nr. 17, Sc. A, - 10 th Floor, Ap. 108, Room 2 - Oradea Bihor 410271 - ROMANIA - - 40-D8-55 (hex) APG CASH DRAWER - 0C3000-0C3FFF (base 16) APG CASH DRAWER - 5250 INDUSTRIAL BLVD NE - MINNEAPOLIS Minnesota 55421 - UNITED STATES - - 40-D8-55 (hex) Inspired Systems - 0C4000-0C4FFF (base 16) Inspired Systems - 70 Mordaunt Cct - Canning Vale WA 6155 - AUSTRALIA - - 40-D8-55 (hex) M.M. Elektrolab - 0C5000-0C5FFF (base 16) M.M. Elektrolab - Dzona Kenedija 11 - Beograd Srbija 11000 - SERBIA - - 40-D8-55 (hex) comtime GmbH - 0C6000-0C6FFF (base 16) comtime GmbH - Gutenbergring 22 - Norderstedt 22848 - GERMANY - - 40-D8-55 (hex) insensiv GmbH - 0C7000-0C7FFF (base 16) insensiv GmbH - Heidsieker Heide 114 - Bielefeld Nordrhein-Westfalen 33739 - GERMANY - - 40-D8-55 (hex) Mettler Toledo Hispeed - 0C8000-0C8FFF (base 16) Mettler Toledo Hispeed - 5 Barr Rd - Ithaca NY 14850 - UNITED STATES - - 40-D8-55 (hex) QUANTAFLOW - 0C9000-0C9FFF (base 16) QUANTAFLOW - AVENUE DUPONT GRAVE - HONFLEUR 14600 - FRANCE - - 40-D8-55 (hex) NEUTRIK AG - 0CA000-0CAFFF (base 16) NEUTRIK AG - Im Alten Riet 143 - SCHAAN 9494 - LIECHTENSTEIN - - 40-D8-55 (hex) ReliOn Inc - 0CB000-0CBFFF (base 16) ReliOn Inc - 15913 E Euclid Ave - Spokane Wa 99216 - UNITED STATES - - 40-D8-55 (hex) ATEME - 0CC000-0CCFFF (base 16) ATEME - 26 Burospace - Route de Gisy - Bievres 91570 - FRANCE - - 40-D8-55 (hex) Logical Product - 0CD000-0CDFFF (base 16) Logical Product - 2-25-5,matoba,minamiku - 2F NAKAHARA BLDG - Fukuoka Fukuoka 811-1314 - JAPAN - - 40-D8-55 (hex) EST Analytical - 0CE000-0CEFFF (base 16) EST Analytical - 503 Commercial Dr - Fairfield OH 45014 - UNITED STATES - - 40-D8-55 (hex) Clark-MXR, Inc. - 0CF000-0CFFFF (base 16) Clark-MXR, Inc. - 7300 W. Huron River Dr. - Dexter MI 48130 - UNITED STATES - - 40-D8-55 (hex) Icraft Oy - 0D0000-0D0FFF (base 16) Icraft Oy - AÌŠkerlundinkatu 3 - Tampere 33100 - FINLAND - - 40-D8-55 (hex) Cantada Inc - 0D1000-0D1FFF (base 16) Cantada Inc - 5742 Oakton Court - Sarasota Florida 34233 - UNITED STATES - - 40-D8-55 (hex) ELAN SYSTEMS - 0D2000-0D2FFF (base 16) ELAN SYSTEMS - 10 IHASZ STR - BUDAPEST 1105 - HUNGARY - - 40-D8-55 (hex) LECO Corporation - 0D3000-0D3FFF (base 16) LECO Corporation - 3000 Lakeview Ave. - St. Joseph Michigan 49085 - UNITED STATES - - 40-D8-55 (hex) Mitsubishi Heavy Industries, Ltd. - 0D4000-0D4FFF (base 16) Mitsubishi Heavy Industries, Ltd. - 3-1, ASAHI, NISHIBIWAJIMA-CHO - KIYOSU AICHI 452-8561 - JAPAN - - 40-D8-55 (hex) Shimizu Electric Co., Ltd. - 0D5000-0D5FFF (base 16) Shimizu Electric Co., Ltd. - Nakayabe-cho 10-10 Shimizu-ku - Shizuoka-shi Shizuoka-ken 424-0854 - JAPAN - - 40-D8-55 (hex) deskontrol electronics - 0D6000-0D6FFF (base 16) deskontrol electronics - Avinguda del port 158 - 9 - Valencia Comunidad Valenciana 46023 - SPAIN - - 40-D8-55 (hex) Avant Technologies,Inc - 0D7000-0D7FFF (base 16) Avant Technologies,Inc - Road 156 Caguas West Ind. Park - Building 39 - Caguas 00726 - PUERTO RICO - - 40-D8-55 (hex) NEXT! s.c. S.Piela B.Dryja - 0D8000-0D8FFF (base 16) NEXT! s.c. S.Piela B.Dryja - Cieszynska 365 - Bielsko-Biala Slask 43-300 - POLAND - - 40-D8-55 (hex) YUKO ELECTRIC CO.,LTD - 0D9000-0D9FFF (base 16) YUKO ELECTRIC CO.,LTD - ICHIGAYA BUILDING 2002-12 - NIIZOASHIHARA - TODA CITY SAITAMA 335-0021 - JAPAN - - 40-D8-55 (hex) Devialet SA - 0DA000-0DAFFF (base 16) Devialet SA - 126 rue Réaumur - Paris 75002 - FRANCE - - 40-D8-55 (hex) Top Connect OU - 0DB000-0DBFFF (base 16) Top Connect OU - Veike-Paala 1 - Tallinn 11415 - ESTONIA - - 40-D8-55 (hex) NVS Technologies Inc - 0DC000-0DCFFF (base 16) NVS Technologies Inc - 1505 Adams Dr Suite D - Menlo Park CA 94025 - UNITED STATES - - 40-D8-55 (hex) Embed Limited - 0DD000-0DDFFF (base 16) Embed Limited - Sovereign Court One - University of Warwick Science Park - Coventry West Midlands CV4 7EZ - UNITED KINGDOM - - 40-D8-55 (hex) VPG - 0DE000-0DEFFF (base 16) VPG - Box 423 - Karlskoga SE-691 27 - SWEDEN - - 40-D8-55 (hex) Xadi Inc - 0DF000-0DFFFF (base 16) Xadi Inc - 100 - 321 McDermot Ave - Winnipeg Manitoba R3A 0A3 - CANADA - - 40-D8-55 (hex) Richter - 0E0000-0E0FFF (base 16) Richter - Griesborner Str. 13 - Ensdorf - Sarland 66806 - GERMANY - - 40-D8-55 (hex) STV Electronic GmbH - 0E1000-0E1FFF (base 16) STV Electronic GmbH - Hellweg 203-205 - Schloss Holte Nordrhein Westfalen 33758 - GERMANY - - 40-D8-55 (hex) Keocko International - 0E2000-0E2FFF (base 16) Keocko International - Paulay Ede utca 6. - Budapest 1061 - HUNGARY - - 40-D8-55 (hex) Medigus Ltd - 0E3000-0E3FFF (base 16) Medigus Ltd - Omer Industrial Park,Building 7A - POB 3030 - Omer 8496500 - ISRAEL - - 40-D8-55 (hex) ARAGO SYSTEMS - 0E4000-0E4FFF (base 16) ARAGO SYSTEMS - 5, rue Soutrane - Sophia Antipolis France métropolitaine 06560 - FRANCE - - 40-D8-55 (hex) Triton Electronics LTD - 0E5000-0E5FFF (base 16) Triton Electronics LTD - Hanarkisim 225 st. - Bitzaron Israel 60946 - ISRAEL - - 40-D8-55 (hex) Kyoritsu Electric Corp. - 0E6000-0E6FFF (base 16) Kyoritsu Electric Corp. - 60 Granton Drive - Unit 8 - Richmond Hill Ontario L4B 2N6 - CANADA - - 40-D8-55 (hex) LIGHTSTAR - 0E7000-0E7FFF (base 16) LIGHTSTAR - 18,CHASEONGDONGRO, 142BEONGIL - GIJANGEUP, GIJANGGUN - BUSAN 619-905 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) HEITEC AG - 0E8000-0E8FFF (base 16) HEITEC AG - Dr.-Otto-Leich-Str. 16 - Eckental Bavaria 90542 - GERMANY - - 40-D8-55 (hex) HAMEG GmbH - 0E9000-0E9FFF (base 16) HAMEG GmbH - Industriestr. 6 - Mainhausen 63533 - GERMANY - - 40-D8-55 (hex) A-Z-E - 0EA000-0EAFFF (base 16) A-Z-E - Brendelweg 98 - Delmenhorst Niedersachsen 27755 - GERMANY - - 40-D8-55 (hex) WANTECH Networks - 0EB000-0EBFFF (base 16) WANTECH Networks - 7, rue Jemmapes - MARSEILLE Bouches-du-Rhône 13001 - FRANCE - - 40-D8-55 (hex) Sentry 360 Security - 0EC000-0ECFFF (base 16) Sentry 360 Security - 24012 W Renwick - Suite 206 - Plainfield Illinois 60544 - UNITED STATES - - 40-D8-55 (hex) IntelliDesign Pty Ltd - 0ED000-0EDFFF (base 16) IntelliDesign Pty Ltd - 99 Bluestone Circuit - Seventeen Mile Rocks Qld 4073 - AUSTRALIA - - 40-D8-55 (hex) Siegmar Zander HuSWare - 0EE000-0EEFFF (base 16) Siegmar Zander HuSWare - Wilmsstr.12 - Berlin 10961 - GERMANY - - 40-D8-55 (hex) GeneSys Elektronik GmbH - 0EF000-0EFFFF (base 16) GeneSys Elektronik GmbH - In der Spoeck 10 - 77656 Offenburg - GERMANY - - 40-D8-55 (hex) Redwood Systems - 0F0000-0F0FFF (base 16) Redwood Systems - 3839 Spinnaker Ct. - Fremont California 94538 - UNITED STATES - - 40-D8-55 (hex) Grossenbacher Systeme AG - 0F1000-0F1FFF (base 16) Grossenbacher Systeme AG - Spinnereistrasse 10 - St. Gallen 9008 - SWITZERLAND - - 40-D8-55 (hex) SigmaPhi Electronics - 0F2000-0F2FFF (base 16) SigmaPhi Electronics - 34 rue de l’Industrie - WISSEMBOURG ALSACE 67160 - FRANCE - - 40-D8-55 (hex) ECON Systems Inc. - 0F3000-0F3FFF (base 16) ECON Systems Inc. - 5414 Lamco Street - Unit 5 - Montgomery Alabama 36117 - UNITED STATES - - 40-D8-55 (hex) MB Connect Line GmbH - 0F4000-0F4FFF (base 16) MB Connect Line GmbH - Winnettener Straße 6 - Dinkelsbühl 91550 - GERMANY - - 40-D8-55 (hex) CST Group - 0F5000-0F5FFF (base 16) CST Group - 3012 Rodgerdale Road - Houston TX 77042 - UNITED STATES - - 40-D8-55 (hex) PRIVATE - 0F6000-0F6FFF (base 16) - - 40-D8-55 (hex) Comline Elektronik Elektrotechnik GmbH - 0F7000-0F7FFF (base 16) Comline Elektronik Elektrotechnik GmbH - Karl-Rapp-Straße 1 - Wackersdorf Bayern 92442 - GERMANY - - 40-D8-55 (hex) Better Place - 0F8000-0F8FFF (base 16) Better Place - Amal 13B, Afek Industrial park - Rosh Ha'ain, 48092 - ISRAEL - - 40-D8-55 (hex) Invisua Lighting BV - 0F9000-0F9FFF (base 16) Invisua Lighting BV - Nuenenseweg 167 - B23 - Geldrop NB 5667KP - NETHERLANDS - - 40-D8-55 (hex) Marmitek BV - 0FA000-0FAFFF (base 16) Marmitek BV - Postbus 4257 - Eindhoven NB 5604 EG - NETHERLANDS - - 40-D8-55 (hex) InfoMac Sp. z o. o. Sp. k. - 0FB000-0FBFFF (base 16) InfoMac Sp. z o. o. Sp. k. - ul Wojska Polskiego 6 - Szczecinek Zachodniopomorskie 78-400 - POLAND - - 40-D8-55 (hex) eumig industrie-tv GmbH - 0FC000-0FCFFF (base 16) eumig industrie-tv GmbH - Gewerbeparkstr.9 - Salzburg Anif 5081 - AUSTRIA - - 40-D8-55 (hex) MONOGRAM technologies ltd - 0FD000-0FDFFF (base 16) MONOGRAM technologies ltd - Ilkovicova 6276 - Bratislava 84216 - SLOVAKIA - - 40-D8-55 (hex) Cytech Technology Pte Ltd - 0FE000-0FEFFF (base 16) Cytech Technology Pte Ltd - 55 Ubi Avenue 1 #07-04 - Singapore 408935 - SINGAPORE - - 40-D8-55 (hex) YUYAMA MFG.CO.,LTD. - 0FF000-0FFFFF (base 16) YUYAMA MFG.CO.,LTD. - 3-3-1 - toyonaka osaka 561-0841 - JAPAN - - 40-D8-55 (hex) TASK SISTEMAS DE COMPUTACAO S.A. - 100000-100FFF (base 16) TASK SISTEMAS DE COMPUTACAO S.A. - RUA VISCONDE DE OURO PRETO - 5, 8 ANDAR - RIO DE JANEIRO 22621-100 - BRAZIL - - 40-D8-55 (hex) e.p.g. Elettronica Srl - 101000-101FFF (base 16) e.p.g. Elettronica Srl - Via Ungaretti 2 - BULGAROGRASSO COMO 22070 - ITALY - - 40-D8-55 (hex) Power Electronics - 102000-102FFF (base 16) Power Electronics - Leonardo Da Vinci, 24-26 - Paterna Valencia 46980 - SPAIN - - 40-D8-55 (hex) Peek Traffic Corporation - 103000-103FFF (base 16) Peek Traffic Corporation - 2906 Corporate Way - Palmetto Fl 34221 - UNITED STATES - - 40-D8-55 (hex) IMPLE SISTEMAS ELETRONICOS EMBARCADOS LTDA - 104000-104FFF (base 16) IMPLE SISTEMAS ELETRONICOS EMBARCADOS LTDA - RUA DIVA GARVIA 1663 - BAIRRO LINHARES - JUIZ DE FORA MINAS GERIAS 36060-300 - BRAZIL - - 40-D8-55 (hex) Tieline Research Pty Ltd - 105000-105FFF (base 16) Tieline Research Pty Ltd - PO Box 2092 - Malaga Western Australia 6944 - AUSTRALIA - - 40-D8-55 (hex) Orbital A/S - 106000-106FFF (base 16) Orbital A/S - Trykkerivej 5 - Skjern 6900 - DENMARK - - 40-D8-55 (hex) Smith Meter, Inc - 107000-107FFF (base 16) Smith Meter, Inc - 1602 Wagner Ave. - Erie PA 16514 - UNITED STATES - - 40-D8-55 (hex) ALPHA DESIGN CO.,LTD. - 108000-108FFF (base 16) ALPHA DESIGN CO.,LTD. - 1963-4 - higashi - itoshima-city Fukuoka 819-1122 - JAPAN - - 40-D8-55 (hex) Rosslare Enterprises Limited - 109000-109FFF (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon 00000 - HONG KONG - - 40-D8-55 (hex) DAVIS DERBY LIMITED - 10A000-10AFFF (base 16) DAVIS DERBY LIMITED - Chequers Lane - Derby Derby DE21 6AW - UNITED KINGDOM - - 40-D8-55 (hex) So-Cool Corporation. - 10B000-10BFFF (base 16) So-Cool Corporation. - 1F., No.130, Shipin Rd., East Dist. - Hsinchu City Taiwan 30062 - TAIWAN, PROVINCE OF CHINA - - 40-D8-55 (hex) Contrans TI sp. z o.o. - 10C000-10CFFF (base 16) Contrans TI sp. z o.o. - Polanowicka 66 - WrocÅ‚aw dolnoÅ›lÄ…skie 51-180 - POLAND - - 40-D8-55 (hex) Rite-Tech Industrial CO., Ltd. - 10D000-10DFFF (base 16) Rite-Tech Industrial CO., Ltd. - 10F, No. 5, Sec. 1, Tun-Hua S. Rd., - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 40-D8-55 (hex) HKS-Prozesstechnik GmbH - 10E000-10EFFF (base 16) HKS-Prozesstechnik GmbH - Heinrich-Damerow-Str. 2 - Halle Sachsen-Anhalt 06120 - GERMANY - - 40-D8-55 (hex) CAVALRY STORAGE INC - 10F000-10FFFF (base 16) CAVALRY STORAGE INC - 4251 E BRICKELL ST - ONTARIO CA 91761 - UNITED STATES - - 40-D8-55 (hex) Aplex Technology Inc. - 110000-110FFF (base 16) Aplex Technology Inc. - NanYouTianAn industrial park Tower4 - Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) Grupo Epelsa S.L. - 111000-111FFF (base 16) Grupo Epelsa S.L. - C/ Punto Net,3 - Alcala de Henares Madrid 28805 - SPAIN - - 40-D8-55 (hex) Halliburton - Sperry Drilling Service - 112000-112FFF (base 16) Halliburton - Sperry Drilling Service - 3000 N. Sam Houston Pkwy E. - Houston Texas 77032 - UNITED STATES - - 40-D8-55 (hex) Testbook Ltd - 113000-113FFF (base 16) Testbook Ltd - 7 Midshires Business Park - Smeaton Close - Alyesbury Bucks HP19 8HL - UNITED KINGDOM - - 40-D8-55 (hex) GENERAL DYNAMICS C4 SYSTEMS - 114000-114FFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST. MD: R1115 - SCOTTSDALE AZ 85257 - UNITED STATES - - 40-D8-55 (hex) MESA Electronic GmbH - 115000-115FFF (base 16) MESA Electronic GmbH - Leitenstr. 26 - Geretsried Bayern 82538 - GERMANY - - 40-D8-55 (hex) Uniscan LLC - 116000-116FFF (base 16) Uniscan LLC - Arbyzova st. 4/26 - Novosibirsk NSO 630117 - RUSSIAN FEDERATION - - 40-D8-55 (hex) RCS Energy Management Limited - 117000-117FFF (base 16) RCS Energy Management Limited - RMS House - Kennet Side - Newbury Berkshire RG14 5PX - UNITED KINGDOM - - 40-D8-55 (hex) University of Nebraska -- Lincoln - 118000-118FFF (base 16) University of Nebraska -- Lincoln - UNL Department of Physics and Astronomy - 208 Jorgensen Hall - Lincoln NE 68588-0299 - UNITED STATES - - 40-D8-55 (hex) OOO Group of Industrial Technologies - 119000-119FFF (base 16) OOO Group of Industrial Technologies - Profsoyuznaya st. 124A - Moscow 117321 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Sicon srl - 11A000-11AFFF (base 16) Sicon srl - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 40-D8-55 (hex) nanoTRONIC GmbH - 11B000-11BFFF (base 16) nanoTRONIC GmbH - Werkstrasse 27 - Lyss Bern 3250 - SWITZERLAND - - 40-D8-55 (hex) DEUTA-WERKE GmbH - 11C000-11CFFF (base 16) DEUTA-WERKE GmbH - Paffrather Strasse 140 - Bergisch Gladbach Northrhine Westfalia 51465 - GERMANY - - 40-D8-55 (hex) ACD Elektronik GmbH - 11D000-11DFFF (base 16) ACD Elektronik GmbH - Engelberg 2 - Achstetten 88480 - GERMANY - - 40-D8-55 (hex) CEMSI, Inc. - 11E000-11EFFF (base 16) CEMSI, Inc. - 780 Keezletown Road - Suite 102 - Weyers Cave VA 24486 - UNITED STATES - - 40-D8-55 (hex) KOMPAN Pawel Sokolowski - 11F000-11FFFF (base 16) KOMPAN Pawel Sokolowski - Radomska 29 - Starachowice Swietokrzyskie 27-200 - POLAND - - 40-D8-55 (hex) ObjectFab GmbH - 120000-120FFF (base 16) ObjectFab GmbH - Pohlandstrasse 19 - Dresden D-01309 - GERMANY - - 40-D8-55 (hex) shanghai Anjian Information technology co. , ltd. - 121000-121FFF (base 16) shanghai Anjian Information technology co. , ltd. - Room 413,Block B , - No. 1919,Zhongshan West Road - shanghai 200235 - CHINA - - 40-D8-55 (hex) ATX Networks Ltd. - 122000-122FFF (base 16) ATX Networks Ltd. - 12 Halapid St. - POB 7041 - Petach-Tikva 49517 - ISRAEL - - 40-D8-55 (hex) ZAO NPC Kompjuternie Technologii - 123000-123FFF (base 16) ZAO NPC Kompjuternie Technologii - Komsomolsky avenue, 90-17 - Perm Perm Region 614010 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Debug s.r.l. - 124000-124FFF (base 16) Debug s.r.l. - Via della Meccanica,14 - Vicenza ITALY 36100 - ITALY - - 40-D8-55 (hex) Scandyna A/S - 125000-125FFF (base 16) Scandyna A/S - Jegindoevej 4 - Viborg 8800 - DENMARK - - 40-D8-55 (hex) TTI LTD - 126000-126FFF (base 16) TTI LTD - Glebe Road - Huntingdon - Cambridge Cambridgeshire PE29 7DR - UNITED KINGDOM - - 40-D8-55 (hex) LIGHTSTAR - 127000-127FFF (base 16) LIGHTSTAR - 18, CHASEONGDONGRO, 142BEONGIL GIJANGEUP, GIJANGGUN - BUSAN 619-905 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Akse srl - 128000-128FFF (base 16) Akse srl - Via Aldo Moro, 39 - Reggio Emilia Italy 42124 - ITALY - - 40-D8-55 (hex) DSP DESIGN - 129000-129FFF (base 16) DSP DESIGN - TAPTON PARK INNOVATION CENTRE - BRIMINGTON ROAD - CHESTERFIELD DERBYSHIRE S41 0TZ - UNITED KINGDOM - - 40-D8-55 (hex) Jadpod Communication Company Limited - 12A000-12AFFF (base 16) Jadpod Communication Company Limited - Buidling B2, Xujingchang Industrial Park, Haoye Road - Shenzhen Guangdong 518000 - CHINA - - 40-D8-55 (hex) Mango DSP, Inc. - 12B000-12BFFF (base 16) Mango DSP, Inc. - 83 East Ave. - Suite#115 - Norwalk CT 06851 - UNITED STATES - - 40-D8-55 (hex) NSP Europe Ltd - 12C000-12CFFF (base 16) NSP Europe Ltd - Unit 5, Devonshire Business Park - 4 Chester Road - Borehamwood Hert WD6 1NA - UNITED KINGDOM - - 40-D8-55 (hex) Biotage Sweden AB - 12D000-12DFFF (base 16) Biotage Sweden AB - Vimpelgatan 5 - Uppsala 753 18 - SWEDEN - - 40-D8-55 (hex) Canfield Scientific, Inc. - 12E000-12EFFF (base 16) Canfield Scientific, Inc. - 253 Passaic Avenue - Fairfield NJ 07004 - UNITED STATES - - 40-D8-55 (hex) PRIVATE - 12F000-12FFFF (base 16) - - 40-D8-55 (hex) GSP Sprachtechnologie GmbH - 130000-130FFF (base 16) GSP Sprachtechnologie GmbH - Teltowkanalstr.1 - Berlin 12247 - GERMANY - - 40-D8-55 (hex) EMAC, INC. - 131000-131FFF (base 16) EMAC, INC. - 2390 EMAC WAY - CARBONDALE IL 62902 - UNITED STATES - - 40-D8-55 (hex) AeroVision Avionics, Inc - 132000-132FFF (base 16) AeroVision Avionics, Inc - 2F, No.30, R&D Rd. II, - Science Park - Hsinchu Taiwan, R.O.C 30076 - UNITED STATES - - 40-D8-55 (hex) Tattile srl - 133000-133FFF (base 16) Tattile srl - Via Donizetti 1/3/5 - Mairano BS 25030 - ITALY - - 40-D8-55 (hex) digitech GmbH & Co. KG - 134000-134FFF (base 16) digitech GmbH & Co. KG - Martinsplatz 3 - Patersdorf Bavaria 94265 - GERMANY - - 40-D8-55 (hex) GLOBALCOM ENGINEERING SRL - 135000-135FFF (base 16) GLOBALCOM ENGINEERING SRL - VIA VOLTA 9 - MORNAGO VA 21020 - ITALY - - 40-D8-55 (hex) Devriecom B.V. - 136000-136FFF (base 16) Devriecom B.V. - Oosteinde 219 - Vriezenveen Ov 7671AX - NETHERLANDS - - 40-D8-55 (hex) GDE Polska - 137000-137FFF (base 16) GDE Polska - Swiatnicka 88 Str. - Wlosan 32-031 Mogilany - POLAND - - 40-D8-55 (hex) Calon Associates Limited - 138000-138FFF (base 16) Calon Associates Limited - 2 Whitworth Court - Runcorn Cheshire WA7 1WA - UNITED KINGDOM - - 40-D8-55 (hex) WOW System - 139000-139FFF (base 16) WOW System - #411, MEGA Center, SKn Techno Park, Sangdaewon 1-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-721 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Supplier Ind. e Com de Eletroeletrônicos - 13A000-13AFFF (base 16) Supplier Ind. e Com de Eletroeletrônicos - Av. Edgar Nelson Meister, 1242, Bloco i Sala 402 - Joinville Santa Catarina 89219501 - BRAZIL - - 40-D8-55 (hex) Davin Technologies Co.,Ltd - 13B000-13BFFF (base 16) Davin Technologies Co.,Ltd - 1203-Ho, World Merdiang 1 Cha - Gasan-dong, Geumcheon-gu - Seoul Seoul 153-781 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) shanghai anjian Information technology co. , ltd. - 13C000-13CFFF (base 16) shanghai anjian Information technology co. , ltd. - Room 413,Block B ,No. 1919,Zhongshan West Road, Shanghai - Shanghai Shanghai 200235 - CHINA - - 40-D8-55 (hex) Perm Scientific-Industrial Instrument Making Company JSC - 13D000-13DFFF (base 16) Perm Scientific-Industrial Instrument Making Company JSC - 25th of October Str, 106 - Perm Privolgsky Federal District 614990 - RUSSIAN FEDERATION - - 40-D8-55 (hex) hanatech - 13E000-13EFFF (base 16) hanatech - D-1412 gwangmyeong techno park - 1345 soha-dong - gwangmyeong-si gyeonggi-do 423-795 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Zhejiang Wellsun Electric Meter Co.,Ltd - 13F000-13FFFF (base 16) Zhejiang Wellsun Electric Meter Co.,Ltd - No 189 East Xixia Road - Tiantai County, - Taizhou Zhejiang 317200 - CHINA - - 40-D8-55 (hex) InnoTrans Communications, Inc - 140000-140FFF (base 16) InnoTrans Communications, Inc - 22 Great Oaks Blvd, Ste #100 - San Jose CA 95119 - UNITED STATES - - 40-D8-55 (hex) Key Systems, Inc. - 141000-141FFF (base 16) Key Systems, Inc. - Po Box G - Fishers New York 14453 - UNITED STATES - - 40-D8-55 (hex) Tetracore, Inc. - 142000-142FFF (base 16) Tetracore, Inc. - 9901 Belward Campus Drive - Suite 300 - Rockville Maryland 20850 - UNITED STATES - - 40-D8-55 (hex) Tokyo Drawing Ltd. - 143000-143FFF (base 16) Tokyo Drawing Ltd. - 103 Ni Terai-machi - Nomi-shi Ishikawa 923-1121 - JAPAN - - 40-D8-55 (hex) Venco - 144000-144FFF (base 16) Venco - Carretera del Mig 75 - Hospitalet de Llobregat Barcelona 08907 - SPAIN - - 40-D8-55 (hex) Weber Marking Systems GmbH - 145000-145FFF (base 16) Weber Marking Systems GmbH - Taschenmacherstrasse 2 - Lübeck Schleswig-Holstein 23556 - GERMANY - - 40-D8-55 (hex) Pleiger Elektronik GmbH and Co. KG - 146000-146FFF (base 16) Pleiger Elektronik GmbH and Co. KG - Im Hammertal 51 - Witten NRW 58456 - GERMANY - - 40-D8-55 (hex) Aplex Technology Inc. - 147000-147FFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 - Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) SEIKO TIME SYSTEMS INC. - 148000-148FFF (base 16) SEIKO TIME SYSTEMS INC. - 2-4-3 Fukuzumi - Koto-ku TOKYO 135-8610 - JAPAN - - 40-D8-55 (hex) Engage Technologies - 149000-149FFF (base 16) Engage Technologies - 7041 Boone Ave. N - Brooklyn Park MN 55428 - UNITED STATES - - 40-D8-55 (hex) GENERAL DYNAMICS C4 SYSTEMS - 14A000-14AFFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST. MD: R1115 - SCOTTSDALE AZ 85257 - UNITED STATES - - 40-D8-55 (hex) Vocality International - 14B000-14BFFF (base 16) Vocality International - Lydling Barn - Puttenham lane - Guildford Surrey GU86AP - UNITED KINGDOM - - 40-D8-55 (hex) PLT - 14C000-14CFFF (base 16) PLT - Partiyniy pereulok d.1 build. 58 - Moscow 115093 - RUSSIAN FEDERATION - - 40-D8-55 (hex) SOMFY SAS - 14D000-14DFFF (base 16) SOMFY SAS - 400, avenue de la République - BP 250 - CLUSES - 74307 - FRANCE - - 40-D8-55 (hex) Marposs S.p.A - 14E000-14EFFF (base 16) Marposs S.p.A - Via Saliceto 13 - Bentivoglio Bologna 40010 - ITALY - - 40-D8-55 (hex) TDS Software Solutions Pty Ltd - 14F000-14FFFF (base 16) TDS Software Solutions Pty Ltd - 5 The Crest - Chandlers Hill South Australia 5160 - AUSTRALIA - - 40-D8-55 (hex) SHIKINO HIGH-TECH - 150000-150FFF (base 16) SHIKINO HIGH-TECH - Shibakoen Denki Bldg, 9F - 1-1-12, Shibakoen - Minato-ku Tokyo 1050011 - JAPAN - - 40-D8-55 (hex) Progress Rail Services, Inspection and Information Systems - 151000-151FFF (base 16) Progress Rail Services, Inspection and Information Systems - 3801-1 South Selsa Road - Independence Missouri 64057 - UNITED STATES - - 40-D8-55 (hex) Home Automation Europe - 152000-152FFF (base 16) Home Automation Europe - Joan Muyskenweg 22 - Amsterdam 1096CJ - NETHERLANDS - - 40-D8-55 (hex) BlinkPipe Ltd - 153000-153FFF (base 16) BlinkPipe Ltd - Wellington House - East Road - Cambridge Cambs CB11BH - UNITED KINGDOM - - 40-D8-55 (hex) iart - 154000-154FFF (base 16) iart - Muelhauserstrasse 111 - Basel Basel-Stadt 4056 - SWITZERLAND - - 40-D8-55 (hex) Telefrang AB - 155000-155FFF (base 16) Telefrang AB - Victor Hasselblads gata 9 - Västra Frölunda Västra Götaland 42131 - SWEDEN - - 40-D8-55 (hex) Emphysys, Inc. - 156000-156FFF (base 16) Emphysys, Inc. - 2X Gill Street - Woburn MA 01801 - UNITED STATES - - 40-D8-55 (hex) Hitachi Power Solutions Co., Ltd. - 157000-157FFF (base 16) Hitachi Power Solutions Co., Ltd. - 38 shinkoutyou - hitachinaka ibaraki 312-0005 - JAPAN - - 40-D8-55 (hex) Exibea AB - 158000-158FFF (base 16) Exibea AB - Ekmansgatan 3 - 411 SE- 41132 - SWEDEN - - 40-D8-55 (hex) PLATINUM GmbH - 159000-159FFF (base 16) PLATINUM GmbH - Pfannerstrasse 75 - Wangen 88239 - GERMANY - - 40-D8-55 (hex) DORLET S.A.U - 15A000-15AFFF (base 16) DORLET S.A.U - Albert Einstein 34 - Parque TecnoloÌgico de AÌlava - Miñano Mayor Alava 01510 - SPAIN - - 40-D8-55 (hex) SQF Spezialelektronik GmbH - 15B000-15BFFF (base 16) SQF Spezialelektronik GmbH - Achimer Str.56 - Oyten 28876 - GERMANY - - 40-D8-55 (hex) Spectratech Inc. - 15C000-15CFFF (base 16) Spectratech Inc. - 4-22-3-101 Kaminoge - Setagayaku Tokyo 158-0093 - JAPAN - - 40-D8-55 (hex) Actronic Technologies - 15D000-15DFFF (base 16) Actronic Technologies - 45 Patiki Rd - Avondale - Auckland 1026 - NEW ZEALAND - - 40-D8-55 (hex) Prodco International Inc. - 15E000-15EFFF (base 16) Prodco International Inc. - 9408 boul. du Gulf - Montreal Quebec H1J3A1 - CANADA - - 40-D8-55 (hex) CT COMPANY - 15F000-15FFFF (base 16) CT COMPANY - Nizhni Krasnoselsky st.,35 - MOSCOW RUSSIA 140070 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Thermo Fisher Sceintific - 160000-160FFF (base 16) Thermo Fisher Sceintific - 1410 Gillingham Lane - Sugar Land Texas 77478 - UNITED STATES - - 40-D8-55 (hex) Solidscape Inc - 161000-161FFF (base 16) Solidscape Inc - 316 Daniel Webster Hwy - Merrimack NH 03054 - UNITED STATES - - 40-D8-55 (hex) LUNA-NEXUS - 162000-162FFF (base 16) LUNA-NEXUS - Terasaki 2nd 6F, 1-8-29 - Nishimiyahara, Yodogawa-Ku - Osaka 532-0004 - JAPAN - - 40-D8-55 (hex) KMtronic LTD - 163000-163FFF (base 16) KMtronic LTD - Dobry Czintulov 28A - Gorna Oriahovitca VT 5100 - BULGARIA - - 40-D8-55 (hex) NFT Automatisierungssysteme GmbH - 164000-164FFF (base 16) NFT Automatisierungssysteme GmbH - Ignatz-Wiemeler-Str. 16 - Ibbenbueren NRW 49477 - GERMANY - - 40-D8-55 (hex) TECHBOARD SRL - 165000-165FFF (base 16) TECHBOARD SRL - VIA DELLA SCIENZA 50 - MODENA Modena 41122 - ITALY - - 40-D8-55 (hex) Anhui Jiante Network Technology Co., Ltd. - 166000-166FFF (base 16) Anhui Jiante Network Technology Co., Ltd. - 513 Room, new Bai Sha business center,NO.9 ,LiuAn Road ,LuYang District, Hefei City ,Anhui Province,China - Hefei Anhui 230000 - CHINA - - 40-D8-55 (hex) Assembly Contracts Ltd - 167000-167FFF (base 16) Assembly Contracts Ltd - Ledson Road - Roundthorn Industrial Estate - Manchester Lancashire M23 9GP - UNITED KINGDOM - - 40-D8-55 (hex) OPASCA Systems GmbH - 168000-168FFF (base 16) OPASCA Systems GmbH - Julius-Hatry-Str. 1 - Mannheim 68163 - GERMANY - - 40-D8-55 (hex) Photop Koncent - 169000-169FFF (base 16) Photop Koncent - 5 Houyu Rd.,P.O.Box 206 - fuzhou fujian 350001 - CHINA - - 40-D8-55 (hex) Aplex Technology Inc. - 16A000-16AFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 - Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) TECHWAY - 16B000-16BFFF (base 16) TECHWAY - 19 avenue de Norvege - ZI COURTABOEUF - Villebon sur Yvette France 91140 - FRANCE - - 40-D8-55 (hex) PRIVATE - 16C000-16CFFF (base 16) - - 40-D8-55 (hex) GENERAL DYNAMICS C4 SYSTEMS - 16D000-16DFFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST - SCOTTSDALE AZ 85257 - UNITED STATES - - 40-D8-55 (hex) Secuinfo Co.Ltd - 16E000-16EFFF (base 16) Secuinfo Co.Ltd - 1411, Kranz Techno, 5442-1, Sangdaewon dong - Jungwon-gu, - Seongnam Gyeonggi-do 462-729 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) BrightLeaf Power - 16F000-16FFFF (base 16) BrightLeaf Power - 121 Apollo Road - Montrose Colorado 81401 - UNITED STATES - - 40-D8-55 (hex) ICS Eletronics - 170000-170FFF (base 16) ICS Eletronics - 7034 Commerce Circle - Suite A - Pleasanton CA 94588 - UNITED STATES - - 40-D8-55 (hex) Sicon srl - 171000-171FFF (base 16) Sicon srl - Via Sila 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - 40-D8-55 (hex) YAWATA ELECTRIC INDUSTRIAL CO.,LTD. - 172000-172FFF (base 16) YAWATA ELECTRIC INDUSTRIAL CO.,LTD. - 1-17-1 Ohmorihigashi - Ohta-ku Tokyo 143-0012 - JAPAN - - 40-D8-55 (hex) Contec Steuerungstechnik & Automation GmbH - 173000-173FFF (base 16) Contec Steuerungstechnik & Automation GmbH - Wildbichler Straße 2E - Ebbs 6341 - AUSTRIA - - 40-D8-55 (hex) EcoGuard AB - 174000-174FFF (base 16) EcoGuard AB - Radiatorvägen 11 - OREBRO 70227 - SWEDEN - - 40-D8-55 (hex) AHB Systeme GmbH - 175000-175FFF (base 16) AHB Systeme GmbH - Julius-Hatry-Str. 1 - Mannheim Baden-Wurttemberg 68163 - GERMANY - - 40-D8-55 (hex) Schneider Electric Motion, Inc. USA - 176000-176FFF (base 16) Schneider Electric Motion, Inc. USA - 370 N. Main St. - P.O. Box 457 - Marlborough CT 06447 - UNITED STATES - - 40-D8-55 (hex) TRI Engineering co.,ltd. - 177000-177FFF (base 16) TRI Engineering co.,ltd. - 23-30 Goban-cho - Ageo Saitama 362-0024 - JAPAN - - 40-D8-55 (hex) REDER Domotic GmbH - 178000-178FFF (base 16) REDER Domotic GmbH - Gutensteinerstrasse 42 - Pottenstein Austria 2563 - AUSTRIA - - 40-D8-55 (hex) Servo-Robot Inc. - 179000-179FFF (base 16) Servo-Robot Inc. - 1370 Hocquart - St-Bruno QC J3V 6E1 - CANADA - - 40-D8-55 (hex) ARGUS-SPECTRUM - 17A000-17AFFF (base 16) ARGUS-SPECTRUM - Serdobolskaya str.,65A - Saint-Petersburg 197342 - RUSSIAN FEDERATION - - 40-D8-55 (hex) LUCEO - 17B000-17BFFF (base 16) LUCEO - 16 Rue Laënnec - Vern Sur Seiche 35770 - FRANCE - - 40-D8-55 (hex) Critical Link - 17C000-17CFFF (base 16) Critical Link - 6712 Brooklawn Parkway - Syracuse NY 13211 - UNITED STATES - - 40-D8-55 (hex) Kiwigrid GmbH - 17D000-17DFFF (base 16) Kiwigrid GmbH - Kleiststrasse 10c - Dresden Sachsen 01129 - GERMANY - - 40-D8-55 (hex) TOKHATEC - 17E000-17EFFF (base 16) TOKHATEC - 2 Rue Georges Melies - Bat. B - Bois D'Arcy 78390 - FRANCE - - 40-D8-55 (hex) Telvent - 17F000-17FFFF (base 16) Telvent - P.I. Alcobendas C/ Valgrande, 6 - Alcobendas Madrid 28108 - SPAIN - - 40-D8-55 (hex) BroadSoft Inc - 180000-180FFF (base 16) BroadSoft Inc - 550 S Winchester Blvd - STE 250 - San Jose CA 95128 - UNITED STATES - - 40-D8-55 (hex) eROCCA - 181000-181FFF (base 16) eROCCA - 196A rue du Rocher de Lorzier - MOIRANS 38430 - FRANCE - - 40-D8-55 (hex) Georg Neumann GmbH - 182000-182FFF (base 16) Georg Neumann GmbH - Ollenhauerstrasse 98 - Berlin 13403 - GERMANY - - 40-D8-55 (hex) EMAC, Inc. - 183000-183FFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 40-D8-55 (hex) Satkirit Ltd - 184000-184FFF (base 16) Satkirit Ltd - 5 Chance St - London E1 6GT - UNITED KINGDOM - - 40-D8-55 (hex) Standard Change Makers - 185000-185FFF (base 16) Standard Change Makers - 3130 North Mitthoeffer - Indianapolis Indiana 46235-0550 - UNITED STATES - - 40-D8-55 (hex) KST technology - 186000-186FFF (base 16) KST technology - 164-1, KST b/d., Bangi-dong, songpa-gu - SEOUL 138-050 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) CDEX Corp. - 187000-187FFF (base 16) CDEX Corp. - Pastoral Heim Inagi Bldg. 2F - 1623-1, Momura - Inagi Tokyo 206-0804 - JAPAN - - 40-D8-55 (hex) Array Corporation - 188000-188FFF (base 16) Array Corporation - 3-42-10 Yoyogi - Shibuya-ku Tokyo 151-0053 - JAPAN - - 40-D8-55 (hex) Yoozma Corporation - 189000-189FFF (base 16) Yoozma Corporation - Shinkawa - 2-1 Marukyousinkawa Bld.2F - Chuo-ku Tokyo 104-0033 - JAPAN - - 40-D8-55 (hex) Aplex Technology Inc. - 18A000-18AFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 - Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) Diagnosys Test Systems Ltd - 18B000-18BFFF (base 16) Diagnosys Test Systems Ltd - Riverside One - Sir John Rogersons Quay - Dublin 2 - IRELAND - - 40-D8-55 (hex) EOS S.r.l. - 18C000-18CFFF (base 16) EOS S.r.l. - Via Monte Aquila 2 - Parma 43124 - ITALY - - 40-D8-55 (hex) Zoe Medical - 18D000-18DFFF (base 16) Zoe Medical - 460 Boston Street - Topsfield Massachusetts 01983 - UNITED STATES - - 40-D8-55 (hex) Kerun Visual Technology Co., Ltd.(Shenzhen) - 18E000-18EFFF (base 16) Kerun Visual Technology Co., Ltd.(Shenzhen) - Bldg 2, F/6, Zone S2 - Honghualing Industrial park, - Shenzhen 518000 - CHINA - - 40-D8-55 (hex) Beat Sensing co. , ltd. - 18F000-18FFFF (base 16) Beat Sensing co. , ltd. - 1072-1 - Tokura , Shimizu-cho - Sunto-gun Shizuoka 411-0917 - JAPAN - - 40-D8-55 (hex) Spider Tecnologia Ind. e Com Ltda - 190000-190FFF (base 16) Spider Tecnologia Ind. e Com Ltda - Rua Alencar Araripe,1440 - Sacomã - São Paulo SP 04253-000 - BRAZIL - - 40-D8-55 (hex) Soukai Electric - 191000-191FFF (base 16) Soukai Electric - 316-9 kubara - Hisayama-tyou - Kasuya-gun Fukuoka 811-2501 - JAPAN - - 40-D8-55 (hex) GENERAL DYNAMICS C4 SYSTEMS - 192000-192FFF (base 16) GENERAL DYNAMICS C4 SYSTEMS - 8220 EAST ROOSEVELT ST - R1115 - SCOTTSDALE, AZ 85257 - UNITED STATES - - 40-D8-55 (hex) FORZA SILICON CORP. - 193000-193FFF (base 16) FORZA SILICON CORP. - 2947 BRADLEY ST. - SUITE 130 - PASADENA CALIFORNIA 91107 - UNITED STATES - - 40-D8-55 (hex) RF Code - 194000-194FFF (base 16) RF Code - 9229 Waterford Centre - Suite 500 - Austin Tx 78758 - UNITED STATES - - 40-D8-55 (hex) TONNA ELECTRONIQUE - 195000-195FFF (base 16) TONNA ELECTRONIQUE - 36 Avenue Hoche - REIMS Champagne-Ardenne 51100 - FRANCE - - 40-D8-55 (hex) Advanced Micro Controls Inc. - 196000-196FFF (base 16) Advanced Micro Controls Inc. - 20 Gear Dr. - Terryville CT 06786 - UNITED STATES - - 40-D8-55 (hex) Berg Cloud Limited - 197000-197FFF (base 16) Berg Cloud Limited - Epworth House - 25 City Road - London EC1Y 1AA - UNITED KINGDOM - - 40-D8-55 (hex) devboards GmbH - 198000-198FFF (base 16) devboards GmbH - Birkerstrasse 67 - Lohmar NRW 33106 - GERMANY - - 40-D8-55 (hex) PRESSOL Schmiergeraete GmbH - 199000-199FFF (base 16) PRESSOL Schmiergeraete GmbH - Parkstrasse 7 - Falkenstein Bavaria 93167 - GERMANY - - 40-D8-55 (hex) Rohde&Schwarz Topex SA - 19A000-19AFFF (base 16) Rohde&Schwarz Topex SA - 10 Feleacului Street, district 1 - Bucharest Romania 014186 - ROMANIA - - 40-D8-55 (hex) Northern Star Technologies - 19B000-19BFFF (base 16) Northern Star Technologies - 5211 Harris Trace Court - Mint Hill NC 28227 - UNITED STATES - - 40-D8-55 (hex) Parris Service Corporation - 19C000-19CFFF (base 16) Parris Service Corporation - 14841 N Hwy 41 - Rathdrum ID 83858 - UNITED STATES - - 40-D8-55 (hex) EMAC, Inc. - 19D000-19DFFF (base 16) EMAC, Inc. - 2390 EMAC Way - Carbondale IL 62902 - UNITED STATES - - 40-D8-55 (hex) Thirdwayv Inc. - 19E000-19EFFF (base 16) Thirdwayv Inc. - 8218 Torrey Gardens Place - San Diego CA 92129 - UNITED STATES - - 40-D8-55 (hex) Patria Aviation Oy - 19F000-19FFFF (base 16) Patria Aviation Oy - Naulakatu 3 - Tampere 33100 - FINLAND - - 40-D8-55 (hex) Futaba Corporation - 1A0000-1A0FFF (base 16) Futaba Corporation - 1080 Yabutsuka,Chosei-mura, - Chosei-gun Chiba-ken 299-4395 - JAPAN - - 40-D8-55 (hex) KRONOTECH SRL - 1A1000-1A1FFF (base 16) KRONOTECH SRL - VIALE UNGHERIA 125 - UDINE - VIA ADRIATICA 284 - CAMPOFORMIDO UDINE 33030 - ITALY - - 40-D8-55 (hex) HIPODROMO DE AGUA CALIENTE, S.A. DE C.V. - 1A2000-1A2FFF (base 16) HIPODROMO DE AGUA CALIENTE, S.A. DE C.V. - BLVD. AGUA CALIENTE 120027 - COL. HIPODROMO - TIJUANA BAJA CALIFORNIA 22420 - MEXICO - - 40-D8-55 (hex) Noritake Itron Corporation - 1A3000-1A3FFF (base 16) Noritake Itron Corporation - 670-5 Uchimi Taiki-cho - Watarai-gun Mie-ken 519-2736 - JAPAN - - 40-D8-55 (hex) cibite AG - 1A4000-1A4FFF (base 16) cibite AG - Posthof 4 - Donauwoerth BY D-86609 - GERMANY - - 40-D8-55 (hex) DemoPad - 1A5000-1A5FFF (base 16) DemoPad - Unit 5 Albert Edward House - The Pavilions - Preston Lancashire PR2 2YB - UNITED KINGDOM - - 40-D8-55 (hex) RB-LINK Wireless - 1A6000-1A6FFF (base 16) RB-LINK Wireless - Parque Comercial Europa Loja 20 - Travasso - Pombal 3100-371 - PORTUGAL - - 40-D8-55 (hex) ENTEC Electric & Electronic CO., LTD - 1A7000-1A7FFF (base 16) ENTEC Electric & Electronic CO., LTD - 78-2 Buncheon-ri - Bongdam-eup - Hwaseong-city Gyungki-do 445-894 - KOREA, REPUBLIC OF - - 40-D8-55 (hex) Multiobrabotka - 1A8000-1A8FFF (base 16) Multiobrabotka - Lermontova,74 - Kamensk-Uralsky Sverdlovsk region 623400 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Lubino s.r.o. - 1A9000-1A9FFF (base 16) Lubino s.r.o. - Podnikatelska 553 - Praha 9 - Bechovice Czech Republic 190 11 - CZECH REPUBLIC - - 40-D8-55 (hex) Broachlink Technology Co.,Limited - 1AA000-1AAFFF (base 16) Broachlink Technology Co.,Limited - Room B402,Building No.28,Danhebei Road - Nanwan Street,Longgang District - Shenzhen GuangDong 518100 - CHINA - - 40-D8-55 (hex) Rosslare Enterprises Limited - 1AB000-1ABFFF (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon 00000 - HONG KONG - - 40-D8-55 (hex) ELAN SYSTEMS - 1AC000-1ACFFF (base 16) ELAN SYSTEMS - 10 IHASZ STR - BUDAPEST 1105 - HUNGARY - - 40-D8-55 (hex) WICHER DIGITAL TECHNIK - 1AD000-1ADFFF (base 16) WICHER DIGITAL TECHNIK - Am Huettberg 38 - Floersbachtal Hessen 63639 - GERMANY - - 40-D8-55 (hex) Autonomous Solutions, Inc - 1AE000-1AEFFF (base 16) Autonomous Solutions, Inc - 990 North 8000 West - Petersboro Utah 84325 - UNITED STATES - - 40-D8-55 (hex) Vigitron Inc. - 1AF000-1AFFFF (base 16) Vigitron Inc. - 7620 Miramar Road, Suite 4100 - Suite 4100 - San Diego California 92126 - UNITED STATES - - 40-D8-55 (hex) Shin-ei Electronic Measuring Co.,Ltd. - 1B0000-1B0FFF (base 16) Shin-ei Electronic Measuring Co.,Ltd. - 2636 - Endo - Fujisawa-shi Kanagawa 252-0816 - JAPAN - - 40-D8-55 (hex) Logos 01 S.r.l. - 1B1000-1B1FFF (base 16) Logos 01 S.r.l. - Via Parini, 8 - Porto Mantovano MN 46047 - ITALY - - 40-D8-55 (hex) AGE A. Gilg Elektronik - 1B2000-1B2FFF (base 16) AGE A. Gilg Elektronik - Wellenburger Str. 53 - Augsburg Bayern D-86199 - GERMANY - - 40-D8-55 (hex) BETTINI SRL - 1B3000-1B3FFF (base 16) BETTINI SRL - VIA GRIEG 23 - SARONNO VARESE 20147 - ITALY - - 40-D8-55 (hex) Inforce Computing Inc. - 1B4000-1B4FFF (base 16) Inforce Computing Inc. - 48820 Kato Road - 600B - Fremont CA 94538 - UNITED STATES - - 40-D8-55 (hex) A+EC Klein Ingenieurbuero - 1B5000-1B5FFF (base 16) A+EC Klein Ingenieurbuero - Eppsteiner Strasse 13 - Eppstein Hessen 65817 - GERMANY - - 40-D8-55 (hex) Magic Systems - 1B6000-1B6FFF (base 16) Magic Systems - Mendeleevskaya 2 - Saint-Petersburg 194044 - RUSSIAN FEDERATION - - 40-D8-55 (hex) TEWS Elektronik GmbH & Co. KG - 1B7000-1B7FFF (base 16) TEWS Elektronik GmbH & Co. KG - Sperberhorst 10 - Hamburg 22459 - GERMANY - - 40-D8-55 (hex) Orion Systems, Inc - 1B8000-1B8FFF (base 16) Orion Systems, Inc - 3401 Masons Mill Rd - Building 2 - Huntingdon Valley PA 19006 - UNITED STATES - - 40-D8-55 (hex) Beking Industrieele automatisering - 1B9000-1B9FFF (base 16) Beking Industrieele automatisering - Kraaienjagersweg 8 - Beemte-Broekland 7341PS - NETHERLANDS - - 40-D8-55 (hex) Creative Lighting And Sound Systems Pty Ltd - 1BA000-1BAFFF (base 16) Creative Lighting And Sound Systems Pty Ltd - 4 Pine Street - Crnr Lowry Street, Lowry Street entry - North Ipswich QLD 4305 - AUSTRALIA - - 40-D8-55 (hex) Micromega Dynamics SA - 1BB000-1BBFFF (base 16) Micromega Dynamics SA - 10 rue du Trou du Sart - Parc Industriel de Noville-les-Bois - FERNELMONT Namur B-5380 - BELGIUM - - 40-D8-55 (hex) KbDevice,Inc. - 1BC000-1BCFFF (base 16) KbDevice,Inc. - Takakura building F3 465-2 Senshouji-chou - takatujitouri yanaginobannba nishiiru shimogyou-ku - kyoto-shi kyoto-fu 600-8076 - JAPAN - - 40-D8-55 (hex) HORIBA ABX - 1BD000-1BDFFF (base 16) HORIBA ABX - rue du caducee - Montpellier 34000 - FRANCE - - 40-D8-55 (hex) PEEK TRAFFIC - 1BE000-1BEFFF (base 16) PEEK TRAFFIC - 2906 CORPORATE WAY - PALMETTO FL 34221 - UNITED STATES - - 40-D8-55 (hex) shanghai mingding information tech co.Ltd - 1BF000-1BFFFF (base 16) shanghai mingding information tech co.Ltd - Room 304 building 3, No 439 Jinglian road, - Minhang district - Shanghai 201018 - CHINA - - 40-D8-55 (hex) NPB Automation AB - 1C0000-1C0FFF (base 16) NPB Automation AB - Industrigatan 14B - Joenkoeping 55302 - SWEDEN - - 40-D8-55 (hex) Triamec Motion AG - 1C1000-1C1FFF (base 16) Triamec Motion AG - Industriestr. 49 - Zug 6300 - SWITZERLAND - - 40-D8-55 (hex) Digital Display Systems - 1C2000-1C2FFF (base 16) Digital Display Systems - 780 Montague expy. Suite 502 - Suite 502 - San Jose California 95131 - UNITED STATES - - 40-D8-55 (hex) Cornfed Systems LLC - 1C3000-1C3FFF (base 16) Cornfed Systems LLC - 3476 Dayton Street - Denver CO 80238 - UNITED STATES - - 40-D8-55 (hex) QED Advanced Systems Limited - 1C4000-1C4FFF (base 16) QED Advanced Systems Limited - 8 Oakwood Business Park - Oldmixon Crescent - Weston-s-Mare Somerset BS249AY - UNITED KINGDOM - - 40-D8-55 (hex) PRIVATE - 1C5000-1C5FFF (base 16) - - 40-D8-55 (hex) Device Solutions Ltd - 1C6000-1C6FFF (base 16) Device Solutions Ltd - PO Box 131 - Rolleston Canterbury 7614 - NEW ZEALAND - - 40-D8-55 (hex) Wexiödisk AB - 1C7000-1C7FFF (base 16) Wexiödisk AB - MÃ¥rdvägen 4 - Växjö Kronoberg 35245 - SWEDEN - - 40-D8-55 (hex) Sensata Technologies - 1C8000-1C8FFF (base 16) Sensata Technologies - 4467 White Bear Parkway - St. Paul Minnesota 55110 - UNITED STATES - - 40-D8-55 (hex) Andy-L Ltd. - 1C9000-1C9FFF (base 16) Andy-L Ltd. - 16B Karlovsko Shosse Str. - Plovdiv Plovdiv 4003 - BULGARIA - - 40-D8-55 (hex) Rigel Engineering - 1CA000-1CAFFF (base 16) Rigel Engineering - 1690 S Tropical Trail - Merritt Island FL 32952 - UNITED STATES - - 40-D8-55 (hex) MG S.r.l. - 1CB000-1CBFFF (base 16) MG S.r.l. - via Monte Bianco, 1 - SOlbiate Olona VA 21058 - ITALY - - 40-D8-55 (hex) NKT Photonics A/S - 1CC000-1CCFFF (base 16) NKT Photonics A/S - Blokken 84 - Birkerod 3460 - DENMARK - - 40-D8-55 (hex) YXLON International A/S - 1CD000-1CDFFF (base 16) YXLON International A/S - Helgeshoej Alle 38 - Taastrup 2630 - DENMARK - - 40-D8-55 (hex) Peter Huber - 1CE000-1CEFFF (base 16) Peter Huber - Kaeltemaschinenbau GmbH - Werner-von-Siemens-Str. 1 - Offenburg Ba-Wue 77656 - GERMANY - - 40-D8-55 (hex) Omnik New Energy Co., Ltd - 1CF000-1CFFFF (base 16) Omnik New Energy Co., Ltd - A4-414 No.218 Xinghu Road - bioBAY Park - suzhou jiangsu 215123 - CHINA - - 40-D8-55 (hex) Webeasy BV - 1D0000-1D0FFF (base 16) Webeasy BV - Sportlaan 53 - Sliedrecht ZH 3364DK - NETHERLANDS - - 40-D8-55 (hex) Founder Broadband Network Service Co.,Ltd. - 1D1000-1D1FFF (base 16) Founder Broadband Network Service Co.,Ltd. - 5/F, Building B, 15 Xueyuan South Rd, - Haidian District Beijing 100088 - CHINA - - 40-D8-55 (hex) InventLab s.c. - 1D2000-1D2FFF (base 16) InventLab s.c. - Czarodziejska 22 - Wólka Kozodawska Mazowieckie 05-502 - POLAND - - 40-D8-55 (hex) Kaluga Teletypes Manufacturing Plant - 1D3000-1D3FFF (base 16) Kaluga Teletypes Manufacturing Plant - 141, Saltykova-Schedrina Street - Kaluga Kaluga region 248002 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Prisma Engineering srl - 1D4000-1D4FFF (base 16) Prisma Engineering srl - Via P. Petrocchi, 4 - MILANO MI 20127 - ITALY - - 40-D8-55 (hex) FST21 Ltd. - 1D5000-1D5FFF (base 16) FST21 Ltd. - 33 Lazarov St. - Rishon Le Zion Israel 75654 - ISRAEL - - 40-D8-55 (hex) EMS Computers Pty Ltd - 1D6000-1D6FFF (base 16) EMS Computers Pty Ltd - Unit 9 / 171 Power St - Glendenning NSW 2177 - AUSTRALIA - - 40-D8-55 (hex) Wheatstone Corporation - 1D7000-1D7FFF (base 16) Wheatstone Corporation - 600 Industrial Drive - New Bern NC 28562 - UNITED STATES - - 40-D8-55 (hex) Owl Computing Technologies, Inc. - 1D8000-1D8FFF (base 16) Owl Computing Technologies, Inc. - 38A Grove Street - Suite 101 - Ridgefield CT 06877 - UNITED STATES - - 40-D8-55 (hex) Commercial Wireless Systems International LLC. - 1D9000-1D9FFF (base 16) Commercial Wireless Systems International LLC. - 10798 N.W. 53 Street - Sunrise Florida 33351 - UNITED STATES - - 40-D8-55 (hex) Energy Technology and Control Ltd. - 1DA000-1DAFFF (base 16) Energy Technology and Control Ltd. - 25 North Street - Lewes East Sussex BN7 2PE - UNITED KINGDOM - - 40-D8-55 (hex) NIPPON TECHNO LAB.,INC, - 1DB000-1DBFFF (base 16) NIPPON TECHNO LAB.,INC, - Hirakawacho Daiichi Seimai Building 5F - 1-2-10 Hirakawa-cho - Chiyoda-ku Tokyo 102-0093 - JAPAN - - 40-D8-55 (hex) Aplex Technology Inc. - 1DC000-1DCFFF (base 16) Aplex Technology Inc. - 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 40-D8-55 (hex) BaOpt Benelux bv - 1DD000-1DDFFF (base 16) BaOpt Benelux bv - Wilhelminastraat 51 - Haarlem 2011 VL - NETHERLANDS - - 40-D8-55 (hex) Vidisys GmbH - 1DE000-1DEFFF (base 16) Vidisys GmbH - Rudolf-Diesel-Ring 30 - Sauerlach Bavaria 82054 - GERMANY - - 40-D8-55 (hex) Chengdu Meihuan Technology Co.,Ltd - 1DF000-1DFFFF (base 16) Chengdu Meihuan Technology Co.,Ltd - Floor 17,Building D6,Tianfu Software Park, - Tianfu Wide Road. - Chengdu Sichuan 610041 - CHINA - - 40-D8-55 (hex) Embedded Technology Corporation - 1E0000-1E0FFF (base 16) Embedded Technology Corporation - Uryudou 3-8-13 - Okuda Bldg - Higashiosaka city Osakafu 578-0946 - JAPAN - - 40-D8-55 (hex) AD QUALITE - 1E1000-1E1FFF (base 16) AD QUALITE - 75, allée Louis Blériot - BOOS Haute Normandie 76520 - FRANCE - - 40-D8-55 (hex) ELNEC s.r.o. - 1E2000-1E2FFF (base 16) ELNEC s.r.o. - Jana Bottu 5 - Presov 08001 - SLOVAKIA - - 40-D8-55 (hex) Mega Electronics Ltd - 1E3000-1E3FFF (base 16) Mega Electronics Ltd - Pioneerinkatu 6 - Kuopio Pohjois-Savo 70800 - FINLAND - - 40-D8-55 (hex) STEK Ltd - 1E4000-1E4FFF (base 16) STEK Ltd - Metallistov pr. 23-4-10 - Saint-Petersburg - 195176 - RUSSIAN FEDERATION - - 40-D8-55 (hex) Shenzhen MaiWei Cable TV Equipment CO.,LTD. - 50D000-50DFFF (base 16) Shenzhen MaiWei Cable TV Equipment CO.,LTD. - 13/F,Fiyta Hi-tech Building,GaoXinnanyi Avenue,Southern District of Hi-tech Park,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 40-D8-55 (hex) Narinet, Inc. - EE6000-EE6FFF (base 16) Narinet, Inc. - C-303, Bundang Techno-Park - 280 Yatapnam-ro, Bundang-Gu - Seongnam Gyunggi-Do 463-816 - KOREA, REPUBLIC OF - diff --git a/awx/lib/site-packages/netaddr/eui/ieee.py b/awx/lib/site-packages/netaddr/eui/ieee.py deleted file mode 100755 index 2b62c7eaad..0000000000 --- a/awx/lib/site-packages/netaddr/eui/ieee.py +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/env python -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -# -# DISCLAIMER -# -# netaddr is not sponsored nor endorsed by the IEEE. -# -# Use of data from the IEEE (Institute of Electrical and Electronics -# Engineers) is subject to copyright. See the following URL for -# details :- -# -# - http://www.ieee.org/web/publications/rights/legal.html -# -# IEEE data files included with netaddr are not modified in any way but are -# parsed and made available to end users through an API. There is no -# guarantee that referenced files are not out of date. -# -# See README file and source code for URLs to latest copies of the relevant -# files. -# -#----------------------------------------------------------------------------- -""" -Provides access to public OUI and IAB registration data published by the IEEE. - -More details can be found at the following URLs :- - - - IEEE Home Page - http://www.ieee.org/ - - Registration Authority Home Page - http://standards.ieee.org/regauth/ -""" - -import os.path as _path -import csv as _csv - -from netaddr.core import Subscriber, Publisher - - -#: Path to local copy of IEEE OUI Registry data file. -OUI_REGISTRY = _path.join(_path.dirname(__file__), 'oui.txt') -#: Path to netaddr OUI index file. -OUI_METADATA = _path.join(_path.dirname(__file__), 'oui.idx') - -#: OUI index lookup dictionary. -OUI_INDEX = {} - -#: Path to local copy of IEEE IAB Registry data file. -IAB_REGISTRY = _path.join(_path.dirname(__file__), 'iab.txt') - -#: Path to netaddr IAB index file. -IAB_METADATA = _path.join(_path.dirname(__file__), 'iab.idx') - -#: IAB index lookup dictionary. -IAB_INDEX = {} - - -class FileIndexer(Subscriber): - """ - A concrete Subscriber that receives OUI record offset information that is - written to an index data file as a set of comma separated records. - """ - def __init__(self, index_file): - """ - Constructor. - - :param index_file: a file-like object or name of index file where - index records will be written. - """ - if hasattr(index_file, 'readline') and hasattr(index_file, 'tell'): - self.fh = index_file - else: - self.fh = open(index_file, 'w') - - self.writer = _csv.writer(self.fh, lineterminator="\n") - - def update(self, data): - """ - Receives and writes index data to a CSV data file. - - :param data: record containing offset record information. - """ - self.writer.writerow(data) - - -class OUIIndexParser(Publisher): - """ - A concrete Publisher that parses OUI (Organisationally Unique Identifier) - records from IEEE text-based registration files - - It notifies registered Subscribers as each record is encountered, passing - on the record's position relative to the start of the file (offset) and - the size of the record (in bytes). - - The file processed by this parser is available online from this URL :- - - - http://standards.ieee.org/regauth/oui/oui.txt - - This is a sample of the record structure expected:: - - 00-CA-FE (hex) ACME CORPORATION - 00CAFE (base 16) ACME CORPORATION - 1 MAIN STREET - SPRINGFIELD - UNITED STATES - """ - def __init__(self, ieee_file): - """ - Constructor. - - :param ieee_file: a file-like object or name of file containing OUI - records. When using a file-like object always open it in binary - mode otherwise offsets will probably misbehave. - """ - super(OUIIndexParser, self).__init__() - - if hasattr(ieee_file, 'readline') and hasattr(ieee_file, 'tell'): - self.fh = ieee_file - else: - self.fh = open(ieee_file) - - def parse(self): - """ - Starts the parsing process which detects records and notifies - registered subscribers as it finds each OUI record. - """ - skip_header = True - record = None - size = 0 - - while True: - line = self.fh.readline() # unbuffered to obtain correct offsets - - if not line: - break # EOF, we're done - - if skip_header and '(hex)' in line: - skip_header = False - - if skip_header: - # ignoring header section - continue - - if '(hex)' in line: - # record start - if record is not None: - # a complete record. - record.append(size) - self.notify(record) - - size = len(line) - offset = (self.fh.tell() - len(line)) - oui = line.split()[0] - index = int(oui.replace('-', ''), 16) - record = [index, offset] - else: - # within record - size += len(line) - - # process final record on loop exit - record.append(size) - self.notify(record) - - -class IABIndexParser(Publisher): - """ - A concrete Publisher that parses IAB (Individual Address Block) records - from IEEE text-based registration files - - It notifies registered Subscribers as each record is encountered, passing - on the record's position relative to the start of the file (offset) and - the size of the record (in bytes). - - The file processed by this parser is available online from this URL :- - - - http://standards.ieee.org/regauth/oui/iab.txt - - This is a sample of the record structure expected:: - - 00-50-C2 (hex) ACME CORPORATION - ABC000-ABCFFF (base 16) ACME CORPORATION - 1 MAIN STREET - SPRINGFIELD - UNITED STATES - """ - def __init__(self, ieee_file): - """ - Constructor. - - :param ieee_file: a file-like object or name of file containing IAB - records. When using a file-like object always open it in binary - mode otherwise offsets will probably misbehave. - """ - super(IABIndexParser, self).__init__() - - if hasattr(ieee_file, 'readline') and hasattr(ieee_file, 'tell'): - self.fh = ieee_file - else: - self.fh = open(ieee_file) - - def parse(self): - """ - Starts the parsing process which detects records and notifies - registered subscribers as it finds each IAB record. - """ - skip_header = True - record = None - size = 0 - while True: - line = self.fh.readline() # unbuffered - - if not line: - break # EOF, we're done - - if skip_header and '(hex)' in line: - skip_header = False - - if skip_header: - # ignoring header section - continue - - if '(hex)' in line: - # record start - if record is not None: - record.append(size) - self.notify(record) - - offset = (self.fh.tell() - len(line)) - iab_prefix = line.split()[0] - index = iab_prefix - record = [index, offset] - size = len(line) - elif '(base 16)' in line: - # within record - size += len(line) - prefix = record[0].replace('-', '') - suffix = line.split()[0] - suffix = suffix.split('-')[0] - record[0] = (int(prefix + suffix, 16)) >> 12 - else: - # within record - size += len(line) - - # process final record on loop exit - record.append(size) - self.notify(record) - - -def create_indices(): - """Create indices for OUI and IAB file based lookups""" - oui_parser = OUIIndexParser(OUI_REGISTRY) - oui_parser.attach(FileIndexer(OUI_METADATA)) - oui_parser.parse() - - iab_parser = IABIndexParser(IAB_REGISTRY) - iab_parser.attach(FileIndexer(IAB_METADATA)) - iab_parser.parse() - - -def load_indices(): - """Load OUI and IAB lookup indices into memory""" - fp = open(OUI_METADATA) - try: - for row in _csv.reader(fp): - (key, offset, size) = [int(_) for _ in row] - OUI_INDEX.setdefault(key, []) - OUI_INDEX[key].append((offset, size)) - finally: - fp.close() - - fp = open(IAB_METADATA) - try: - for row in _csv.reader(fp): - (key, offset, size) = [int(_) for _ in row] - IAB_INDEX.setdefault(key, []) - IAB_INDEX[key].append((offset, size)) - finally: - fp.close() - - -if __name__ == '__main__': - # Generate indices when module is executed as a script. - create_indices() -else: - # On module load read indices in memory to enable lookups. - load_indices() diff --git a/awx/lib/site-packages/netaddr/eui/oui.idx b/awx/lib/site-packages/netaddr/eui/oui.idx deleted file mode 100644 index 3e16fad5a6..0000000000 --- a/awx/lib/site-packages/netaddr/eui/oui.idx +++ /dev/null @@ -1,20508 +0,0 @@ -0,120,160 -1,280,184 -2,464,184 -3,648,193 -4,841,185 -5,1026,184 -6,1210,185 -7,1395,184 -8,1579,185 -9,1764,148 -10,1912,211 -11,2123,158 -12,2281,158 -13,2439,132 -14,2571,189 -15,2760,135 -16,2895,139 -17,3034,134 -18,3168,180 -19,3348,120 -20,3468,129 -21,3597,171 -22,3768,196 -23,3964,128 -24,4092,180 -25,4272,182 -26,4454,163 -27,4617,148 -28,4765,144 -29,4909,176 -30,5085,194 -31,5279,150 -32,5429,135 -33,5564,211 -34,5775,157 -35,5932,153 -36,6085,117 -37,6202,138 -38,6340,146 -39,6486,153 -40,6639,169 -41,6808,152 -42,6960,162 -43,7122,153 -44,7275,147 -45,7422,149 -46,7571,146 -47,7717,149 -48,7866,186 -49,8052,175 -50,8227,167 -51,8394,162 -52,8556,173 -53,8729,200 -54,8929,149 -55,9078,182 -56,9260,129 -57,9389,164 -58,9553,147 -59,9700,189 -60,9889,158 -61,10047,136 -62,10183,128 -63,10311,144 -64,10455,165 -65,10620,154 -66,10774,194 -67,10968,142 -68,11110,159 -69,11269,211 -70,11480,158 -71,11638,159 -72,11797,166 -73,11963,178 -74,12141,174 -75,12315,148 -76,12463,145 -77,12608,170 -78,12778,146 -79,12924,136 -80,13060,161 -81,13221,164 -82,13385,136 -83,13521,136 -84,13657,147 -85,13804,165 -86,13969,157 -87,14126,143 -88,14269,178 -89,14447,149 -90,14596,133 -91,14729,161 -92,14890,179 -93,15069,152 -94,15221,214 -95,15435,165 -96,15600,154 -97,15754,153 -98,15907,174 -99,16081,154 -100,16235,173 -101,16408,163 -102,16571,163 -103,16734,163 -104,16897,150 -105,17047,166 -106,17213,187 -107,17400,213 -108,17613,55 -109,17668,211 -110,17879,139 -111,18018,153 -112,18171,152 -113,18323,145 -114,18468,155 -115,18623,156 -116,18779,151 -117,18930,198 -118,19128,155 -119,19283,148 -120,19431,153 -121,19584,155 -122,19739,149 -123,19888,162 -124,20050,178 -125,20228,178 -126,20406,151 -127,20557,157 -128,20714,143 -129,20857,182 -130,21039,156 -131,21195,166 -132,21361,129 -133,21490,154 -134,21644,167 -135,21811,174 -136,21985,185 -137,22170,152 -138,22322,219 -139,22541,126 -140,22667,210 -141,22877,133 -142,23010,162 -143,23172,146 -144,23318,135 -145,23453,143 -146,23596,164 -147,23760,129 -148,23889,144 -149,24033,146 -150,24179,200 -151,24379,141 -152,24520,165 -153,24685,130 -154,24815,131 -155,24946,201 -156,25147,156 -157,25303,164 -158,25467,123 -159,25590,163 -160,25753,174 -161,25927,161 -162,26088,166 -163,26254,170 -164,26424,182 -165,26606,134 -166,26740,177 -167,26917,177 -168,27094,154 -169,27248,167 -170,27415,184 -171,27599,167 -172,27766,160 -173,27926,153 -174,28079,150 -175,28229,163 -176,28392,156 -177,28548,155 -178,28703,163 -179,28866,146 -180,29012,203 -181,29215,171 -182,29386,149 -183,29535,168 -184,29703,162 -185,29865,213 -186,30078,132 -187,30210,145 -188,30355,164 -189,30519,160 -190,30679,160 -191,30839,176 -192,31015,170 -193,31185,153 -194,31338,190 -195,31528,187 -196,31715,156 -197,31871,148 -198,32019,155 -199,32174,170 -200,32344,158 -201,32502,149 -202,32651,162 -203,32813,160 -204,32973,143 -205,33116,166 -206,33282,137 -207,33419,179 -208,33598,170 -209,33768,170 -210,33938,135 -211,34073,98 -212,34171,159 -213,34330,186 -214,34516,156 -215,34672,149 -216,34821,163 -217,34984,202 -218,35186,116 -219,35302,180 -220,35482,164 -221,35646,144 -222,35790,129 -223,35919,166 -224,36085,132 -225,36217,164 -226,36381,156 -227,36537,209 -228,36746,151 -229,36897,169 -230,37066,184 -231,37250,152 -232,37402,163 -233,37565,145 -234,37710,111 -235,37821,179 -236,38000,141 -237,38141,127 -238,38268,213 -239,38481,131 -240,38612,202 -241,38814,161 -242,38975,152 -243,39127,158 -244,39285,153 -245,39438,178 -246,39616,190 -247,39806,193 -248,39999,196 -249,40195,155 -250,40350,169 -251,40519,147 -252,40666,137 -253,40803,177 -254,40980,181 -255,41161,168 -256,41329,129 -257,41458,55 -258,41513,160 -259,41673,159 -260,41832,197 -261,42029,147 -262,42176,145 -263,42321,119 -264,42440,193 -265,42633,173 -266,42806,194 -267,43000,188 -268,43188,174 -269,43362,153 -270,43515,188 -271,43703,185 -272,43888,137 -273,44025,164 -274,44189,162 -275,44351,153 -276,44504,188 -277,44692,162 -278,44854,182 -279,45036,136 -280,45172,184 -281,45356,143 -282,45499,163 -283,45662,192 -284,45854,188 -285,46042,163 -286,46205,161 -287,46366,160 -288,46526,146 -289,46672,186 -290,46858,201 -291,47059,168 -292,47227,185 -293,47412,195 -294,47607,133 -295,47740,162 -296,47902,146 -297,48048,151 -298,48199,168 -299,48367,88 -300,48455,166 -301,48621,146 -302,48767,174 -303,48941,209 -304,49150,147 -305,49297,170 -306,49467,138 -307,49605,158 -308,49763,142 -309,49905,159 -310,50064,204 -311,50268,182 -312,50450,220 -313,50670,222 -314,50892,172 -315,51064,135 -316,51199,135 -317,51334,164 -318,51498,122 -319,51620,203 -320,51823,176 -321,51999,133 -322,52132,170 -323,52302,170 -324,52472,138 -325,52610,144 -326,52754,156 -327,52910,148 -328,53058,158 -329,53216,163 -330,53379,166 -331,53545,161 -332,53706,158 -333,53864,214 -334,54078,164 -335,54242,139 -336,54381,165 -337,54546,172 -338,54718,159 -339,54877,207 -340,55084,160 -341,55244,212 -342,55456,172 -343,55628,182 -344,55810,169 -345,55979,183 -346,56162,201 -347,56363,134 -348,56497,144 -349,56641,177 -350,56818,197 -351,57015,135 -352,57150,140 -353,57290,177 -354,57467,167 -355,57634,170 -356,57804,170 -357,57974,154 -358,58128,124 -359,58252,155 -360,58407,161 -361,58568,186 -362,58754,124 -363,58878,137 -364,59015,120 -365,59135,158 -366,59293,160 -367,59453,146 -368,59599,175 -369,59774,163 -370,59937,160 -371,60097,122 -372,60219,168 -373,60387,174 -374,60561,173 -375,60734,129 -376,60863,162 -377,61025,203 -378,61228,202 -379,61430,172 -380,61602,120 -381,61722,138 -382,61860,180 -383,62040,174 -384,62214,192 -385,62406,151 -386,62557,138 -387,62695,164 -388,62859,139 -389,62998,163 -390,63161,132 -391,63293,126 -392,63419,141 -393,63560,176 -394,63736,138 -395,63874,175 -396,64049,134 -397,64183,154 -398,64337,142 -399,64479,133 -400,64612,126 -401,64738,147 -402,64885,165 -403,65050,197 -404,65247,185 -405,65432,195 -406,65627,170 -407,65797,170 -408,65967,174 -409,66141,183 -410,66324,130 -411,66454,162 -412,66616,145 -413,66761,166 -414,66927,152 -415,67079,141 -416,67220,169 -417,67389,139 -418,67528,162 -419,67690,174 -420,67864,167 -421,68031,155 -422,68186,172 -423,68358,201 -424,68559,217 -425,68776,108 -426,68884,188 -427,69072,171 -428,69243,151 -429,69394,233 -430,69627,154 -431,69781,186 -432,69967,226 -433,70193,150 -434,70343,188 -435,70531,182 -436,70713,154 -437,70867,159 -438,71026,196 -439,71222,187 -440,71409,140 -441,71549,159 -442,71708,173 -443,71881,126 -444,72007,151 -445,72158,198 -446,72356,187 -447,72543,156 -448,72699,121 -449,72820,162 -450,72982,153 -451,73135,136 -452,73271,187 -453,73458,174 -454,73632,162 -455,73794,170 -456,73964,148 -456,74112,78 -457,74190,170 -458,74360,176 -459,74536,113 -460,74649,226 -461,74875,107 -462,74982,200 -463,75182,203 -464,75385,141 -465,75526,160 -466,75686,175 -467,75861,180 -468,76041,155 -469,76196,238 -470,76434,127 -471,76561,152 -472,76713,163 -473,76876,136 -474,77012,214 -475,77226,156 -476,77382,135 -477,77517,148 -478,77665,149 -479,77814,204 -480,78018,157 -481,78175,212 -482,78387,163 -483,78550,120 -484,78670,138 -485,78808,182 -486,78990,172 -487,79162,172 -488,79334,157 -489,79491,187 -490,79678,138 -491,79816,188 -492,80004,151 -493,80155,155 -494,80310,187 -495,80497,222 -496,80719,155 -497,80874,177 -498,81051,168 -499,81219,132 -500,81351,148 -501,81499,126 -502,81625,220 -503,81845,181 -504,82026,222 -505,82248,195 -506,82443,111 -507,82554,190 -508,82744,166 -509,82910,166 -510,83076,202 -511,83278,167 -512,83445,202 -513,83647,138 -514,83785,185 -515,83970,180 -516,84150,178 -517,84328,159 -518,84487,125 -519,84612,182 -520,84794,167 -521,84961,227 -522,85188,133 -523,85321,142 -524,85463,126 -525,85589,133 -526,85722,135 -527,85857,116 -528,85973,187 -529,86160,241 -530,86401,128 -531,86529,138 -532,86667,173 -533,86840,167 -534,87007,170 -535,87177,170 -536,87347,223 -537,87570,158 -538,87728,141 -539,87869,142 -540,88011,160 -541,88171,200 -542,88371,130 -543,88501,157 -544,88658,149 -545,88807,201 -546,89008,143 -547,89151,168 -548,89319,124 -549,89443,163 -550,89606,145 -551,89751,174 -552,89925,152 -553,90077,167 -554,90244,175 -555,90419,148 -556,90567,166 -557,90733,131 -558,90864,123 -559,90987,121 -560,91108,137 -561,91245,159 -562,91404,195 -563,91599,184 -564,91783,162 -565,91945,173 -566,92118,123 -567,92241,163 -568,92404,197 -569,92601,129 -570,92730,155 -571,92885,124 -572,93009,186 -573,93195,153 -574,93348,158 -575,93506,175 -576,93681,177 -577,93858,128 -578,93986,171 -579,94157,172 -580,94329,214 -581,94543,188 -582,94731,209 -583,94940,229 -584,95169,141 -585,95310,204 -586,95514,170 -587,95684,170 -588,95854,144 -589,95998,171 -590,96169,155 -591,96324,150 -592,96474,155 -593,96629,167 -594,96796,156 -595,96952,139 -596,97091,130 -597,97221,170 -598,97391,156 -599,97547,151 -600,97698,188 -601,97886,233 -602,98119,149 -603,98268,196 -604,98464,196 -605,98660,147 -606,98807,191 -607,98998,158 -608,99156,167 -609,99323,119 -610,99442,223 -611,99665,163 -612,99828,142 -613,99970,195 -614,100165,162 -615,100327,146 -616,100473,202 -617,100675,180 -618,100855,211 -619,101066,215 -620,101281,150 -621,101431,145 -622,101576,170 -623,101746,217 -624,101963,184 -625,102147,148 -626,102295,202 -627,102497,149 -628,102646,192 -629,102838,164 -630,103002,187 -631,103189,157 -632,103346,217 -633,103563,156 -634,103719,219 -635,103938,148 -636,104086,147 -637,104233,170 -638,104403,170 -639,104573,185 -640,104758,147 -641,104905,153 -642,105058,143 -643,105201,151 -644,105352,131 -645,105483,161 -646,105644,144 -647,105788,129 -648,105917,172 -649,106089,145 -650,106234,219 -651,106453,128 -652,106581,173 -653,106754,211 -654,106965,160 -655,107125,162 -656,107287,175 -657,107462,180 -658,107642,161 -659,107803,159 -660,107962,164 -661,108126,198 -662,108324,210 -663,108534,152 -664,108686,158 -665,108844,134 -666,108978,138 -667,109116,153 -668,109269,120 -669,109389,171 -670,109560,210 -671,109770,179 -672,109949,128 -673,110077,141 -674,110218,129 -675,110347,179 -676,110526,209 -677,110735,175 -678,110910,198 -679,111108,144 -680,111252,189 -681,111441,158 -682,111599,181 -683,111780,189 -684,111969,132 -685,112101,146 -686,112247,185 -687,112432,157 -688,112589,197 -689,112786,171 -690,112957,145 -691,113102,166 -692,113268,114 -693,113382,134 -694,113516,211 -695,113727,185 -696,113912,148 -697,114060,170 -698,114230,170 -699,114400,168 -700,114568,159 -701,114727,188 -702,114915,176 -703,115091,149 -704,115240,232 -705,115472,187 -706,115659,202 -707,115861,119 -708,115980,150 -709,116130,169 -710,116299,195 -711,116494,168 -712,116662,238 -713,116900,156 -714,117056,138 -715,117194,173 -716,117367,128 -717,117495,170 -718,117665,152 -719,117817,186 -720,118003,158 -721,118161,165 -722,118326,143 -723,118469,155 -724,118624,167 -725,118791,121 -726,118912,130 -727,119042,148 -728,119190,189 -729,119379,145 -730,119524,171 -731,119695,148 -732,119843,185 -733,120028,216 -734,120244,163 -735,120407,169 -736,120576,121 -737,120697,174 -738,120871,163 -739,121034,171 -740,121205,190 -741,121395,163 -742,121558,175 -743,121733,142 -744,121875,123 -745,121998,166 -746,122164,144 -747,122308,173 -748,122481,169 -749,122650,172 -750,122822,138 -751,122960,221 -752,123181,214 -753,123395,175 -754,123570,155 -755,123725,187 -756,123912,138 -757,124050,179 -758,124229,147 -759,124376,137 -760,124513,163 -761,124676,139 -762,124815,142 -763,124957,172 -764,125129,170 -765,125299,170 -766,125469,153 -767,125622,186 -768,125808,165 -769,125973,135 -770,126108,166 -771,126274,203 -772,126477,178 -773,126655,163 -774,126818,191 -775,127009,161 -776,127170,160 -777,127330,165 -778,127495,155 -779,127650,200 -780,127850,189 -781,128039,199 -782,128238,236 -783,128474,220 -784,128694,187 -785,128881,188 -786,129069,143 -787,129212,144 -788,129356,210 -789,129566,152 -790,129718,176 -791,129894,168 -792,130062,152 -793,130214,122 -794,130336,208 -795,130544,186 -796,130730,161 -797,130891,204 -798,131095,159 -799,131254,137 -800,131391,148 -801,131539,188 -802,131727,165 -803,131892,177 -804,132069,182 -805,132251,173 -806,132424,183 -807,132607,124 -808,132731,147 -809,132878,178 -810,133056,215 -811,133271,163 -812,133434,152 -813,133586,172 -814,133758,213 -815,133971,201 -816,134172,157 -817,134329,170 -818,134499,170 -819,134669,161 -820,134830,150 -821,134980,166 -822,135146,140 -823,135286,173 -824,135459,143 -825,135602,166 -826,135768,165 -827,135933,181 -828,136114,151 -829,136265,156 -830,136421,204 -831,136625,144 -832,136769,180 -833,136949,149 -834,137098,158 -835,137256,151 -836,137407,138 -837,137545,211 -838,137756,166 -839,137922,167 -840,138089,167 -841,138256,165 -842,138421,144 -843,138565,156 -844,138721,223 -845,138944,158 -846,139102,187 -847,139289,165 -848,139454,122 -849,139576,141 -850,139717,149 -851,139866,151 -852,140017,218 -853,140235,169 -854,140404,175 -855,140579,157 -856,140736,190 -857,140926,152 -858,141078,133 -859,141211,163 -860,141374,191 -861,141565,190 -862,141755,204 -863,141959,205 -864,142164,218 -865,142382,153 -866,142535,204 -867,142739,179 -868,142918,169 -869,143087,217 -870,143304,167 -871,143471,154 -872,143625,195 -873,143820,175 -874,143995,124 -875,144119,170 -876,144289,170 -877,144459,178 -878,144637,174 -879,144811,142 -880,144953,142 -881,145095,196 -882,145291,187 -883,145478,144 -884,145622,148 -885,145770,143 -886,145913,160 -887,146073,146 -888,146219,173 -889,146392,224 -890,146616,151 -891,146767,167 -892,146934,149 -893,147083,153 -894,147236,197 -895,147433,179 -896,147612,170 -897,147782,153 -898,147935,155 -899,148090,171 -900,148261,145 -901,148406,158 -902,148564,186 -903,148750,155 -904,148905,215 -905,149120,133 -906,149253,152 -907,149405,183 -908,149588,146 -909,149734,183 -910,149917,150 -911,150067,156 -912,150223,195 -913,150418,223 -914,150641,226 -915,150867,120 -916,150987,123 -917,151110,154 -918,151264,194 -919,151458,148 -920,151606,129 -921,151735,243 -922,151978,137 -923,152115,162 -924,152277,181 -925,152458,161 -926,152619,204 -927,152823,170 -928,152993,170 -929,153163,221 -930,153384,163 -931,153547,120 -932,153667,159 -933,153826,174 -934,154000,169 -935,154169,193 -936,154362,216 -937,154578,134 -938,154712,120 -939,154832,165 -940,154997,166 -941,155163,148 -942,155311,207 -943,155518,159 -944,155677,184 -945,155861,137 -946,155998,109 -947,156107,224 -948,156331,205 -949,156536,216 -950,156752,156 -951,156908,153 -952,157061,170 -953,157231,169 -954,157400,177 -955,157577,191 -956,157768,115 -957,157883,190 -958,158073,148 -959,158221,215 -960,158436,170 -961,158606,167 -962,158773,146 -963,158919,144 -964,159063,140 -965,159203,126 -966,159329,155 -967,159484,149 -968,159633,161 -969,159794,177 -970,159971,143 -971,160114,195 -972,160309,176 -973,160485,144 -974,160629,228 -975,160857,199 -976,161056,163 -977,161219,165 -978,161384,159 -979,161543,166 -980,161709,162 -981,161871,178 -982,162049,136 -983,162185,174 -984,162359,164 -985,162523,123 -986,162646,191 -987,162837,168 -988,163005,148 -989,163153,129 -990,163282,134 -991,163416,142 -992,163558,147 -993,163705,193 -994,163898,164 -995,164062,170 -996,164232,170 -997,164402,132 -998,164534,142 -999,164676,198 -1000,164874,215 -1001,165089,157 -1002,165246,219 -1003,165465,148 -1004,165613,155 -1005,165768,170 -1006,165938,146 -1007,166084,123 -1008,166207,189 -1009,166396,180 -1010,166576,155 -1011,166731,160 -1012,166891,147 -1013,167038,127 -1014,167165,161 -1015,167326,144 -1016,167470,187 -1017,167657,175 -1018,167832,144 -1019,167976,144 -1020,168120,133 -1021,168253,170 -1022,168423,170 -1023,168593,150 -1024,168743,179 -1025,168922,174 -1026,169096,173 -1027,169269,148 -1028,169417,185 -1029,169602,186 -1030,169788,132 -1031,169920,185 -1032,170105,151 -1033,170256,157 -1034,170413,154 -1035,170567,176 -1036,170743,161 -1037,170904,166 -1038,171070,112 -1039,171182,220 -1040,171402,159 -1041,171561,158 -1042,171719,157 -1043,171876,141 -1044,172017,196 -1045,172213,167 -1046,172380,181 -1047,172561,117 -1048,172678,148 -1049,172826,183 -1050,173009,182 -1051,173191,156 -1052,173347,157 -1053,173504,144 -1054,173648,180 -1055,173828,179 -1056,174007,162 -1057,174169,161 -1058,174330,146 -1059,174476,165 -1060,174641,120 -1061,174761,199 -1062,174960,164 -1063,175124,170 -1064,175294,170 -1065,175464,216 -1066,175680,160 -1067,175840,169 -1068,176009,172 -1069,176181,206 -1070,176387,191 -1071,176578,224 -1072,176802,120 -1073,176922,176 -1074,177098,176 -1075,177274,131 -1076,177405,168 -1077,177573,159 -1078,177732,191 -1079,177923,221 -1080,178144,154 -1081,178298,184 -1082,178482,213 -1083,178695,167 -1084,178862,213 -1085,179075,117 -1086,179192,132 -1087,179324,173 -1088,179497,158 -1089,179655,166 -1090,179821,113 -1091,179934,197 -1092,180131,187 -1093,180318,163 -1094,180481,195 -1095,180676,201 -1096,180877,149 -1097,181026,151 -1098,181177,156 -1099,181333,124 -1100,181457,153 -1101,181610,170 -1102,181780,170 -1103,181950,170 -1104,182120,140 -1105,182260,135 -1106,182395,166 -1107,182561,139 -1108,182700,163 -1109,182863,141 -1110,183004,198 -1111,183202,233 -1112,183435,197 -1113,183632,149 -1114,183781,158 -1115,183939,203 -1116,184142,146 -1117,184288,132 -1118,184420,176 -1119,184596,213 -1120,184809,205 -1121,185014,223 -1122,185237,249 -1123,185486,163 -1124,185649,141 -1125,185790,161 -1126,185951,188 -1127,186139,217 -1128,186356,135 -1129,186491,171 -1130,186662,155 -1131,186817,155 -1132,186972,213 -1133,187185,170 -1134,187355,170 -1135,187525,205 -1136,187730,134 -1137,187864,117 -1138,187981,171 -1139,188152,149 -1140,188301,117 -1141,188418,164 -1142,188582,164 -1143,188746,157 -1144,188903,233 -1145,189136,158 -1146,189294,141 -1147,189435,172 -1148,189607,132 -1149,189739,116 -1150,189855,130 -1151,189985,152 -1152,190137,178 -1153,190315,178 -1154,190493,163 -1155,190656,210 -1156,190866,122 -1157,190988,136 -1158,191124,166 -1159,191290,173 -1160,191463,147 -1161,191610,149 -1162,191759,147 -1163,191906,177 -1164,192083,147 -1165,192230,159 -1166,192389,152 -1167,192541,173 -1168,192714,124 -1169,192838,166 -1170,193004,209 -1171,193213,191 -1172,193404,158 -1173,193562,198 -1174,193760,144 -1175,193904,165 -1176,194069,142 -1177,194211,159 -1178,194370,170 -1179,194540,170 -1180,194710,179 -1181,194889,155 -1182,195044,186 -1183,195230,171 -1184,195401,163 -1185,195564,150 -1186,195714,155 -1187,195869,168 -1188,196037,142 -1189,196179,148 -1190,196327,133 -1191,196460,222 -1192,196682,171 -1193,196853,170 -1194,197023,166 -1195,197189,163 -1196,197352,170 -1197,197522,141 -1198,197663,160 -1199,197823,158 -1200,197981,189 -1201,198170,187 -1202,198357,134 -1203,198491,140 -1204,198631,120 -1205,198751,152 -1206,198903,161 -1207,199064,138 -1208,199202,167 -1209,199369,150 -1210,199519,167 -1211,199686,153 -1212,199839,206 -1213,200045,147 -1214,200192,153 -1215,200345,140 -1216,200485,170 -1217,200655,170 -1218,200825,165 -1219,200990,154 -1220,201144,178 -1221,201322,150 -1222,201472,192 -1223,201664,109 -1224,201773,144 -1225,201917,162 -1226,202079,181 -1227,202260,159 -1228,202419,147 -1229,202566,171 -1230,202737,123 -1231,202860,159 -1232,203019,156 -1233,203175,176 -1234,203351,146 -1235,203497,151 -1236,203648,193 -1237,203841,242 -1238,204083,211 -1239,204294,204 -1240,204498,177 -1241,204675,208 -1242,204883,182 -1243,205065,211 -1244,205276,155 -1245,205431,170 -1246,205601,170 -1247,205771,181 -1248,205952,145 -1249,206097,195 -1250,206292,136 -1251,206428,189 -1252,206617,172 -1253,206789,191 -1254,206980,183 -1255,207163,181 -1256,207344,148 -1257,207492,162 -1258,207654,172 -1259,207826,167 -1260,207993,128 -1261,208121,226 -1262,208347,170 -1263,208517,192 -1264,208709,185 -1265,208894,135 -1266,209029,144 -1267,209173,144 -1268,209317,183 -1269,209500,162 -1270,209662,125 -1271,209787,170 -1272,209957,207 -1273,210164,162 -1274,210326,167 -1275,210493,145 -1276,210638,166 -1277,210804,189 -1278,210993,153 -1279,211146,177 -1280,211323,170 -1281,211493,170 -1282,211663,120 -1283,211783,111 -1284,211894,238 -1285,212132,199 -1286,212331,140 -1287,212471,176 -1288,212647,145 -1289,212792,156 -1290,212948,116 -1291,213064,151 -1292,213215,164 -1293,213379,187 -1294,213566,152 -1295,213718,152 -1296,213870,202 -1297,214072,202 -1298,214274,173 -1299,214447,196 -1300,214643,177 -1301,214820,195 -1302,215015,162 -1303,215177,179 -1304,215356,157 -1305,215513,197 -1306,215710,161 -1307,215871,212 -1308,216083,195 -1309,216278,136 -1310,216414,180 -1311,216594,175 -1312,216769,149 -1313,216918,142 -1314,217060,167 -1315,217227,124 -1316,217351,182 -1317,217533,206 -1318,217739,119 -1319,217858,167 -1320,218025,142 -1321,218167,254 -1322,218421,164 -1323,218585,148 -1324,218733,200 -1325,218933,181 -1326,219114,145 -1327,219259,165 -1328,219424,154 -1329,219578,170 -1330,219748,170 -1331,219918,185 -1332,220103,170 -1333,220273,174 -1334,220447,191 -1335,220638,206 -1336,220844,141 -1337,220985,153 -1338,221138,176 -1339,221314,207 -1340,221521,136 -1341,221657,139 -1342,221796,139 -1343,221935,139 -1344,222074,149 -1345,222223,171 -1346,222394,136 -1347,222530,137 -1348,222667,185 -1349,222852,157 -1350,223009,168 -1351,223177,149 -1352,223326,148 -1353,223474,174 -1354,223648,169 -1355,223817,146 -1356,223963,147 -1357,224110,194 -1358,224304,136 -1359,224440,55 -1360,224495,201 -1361,224696,166 -1362,224862,153 -1363,225015,142 -1364,225157,155 -1365,225312,183 -1366,225495,141 -1367,225636,173 -1368,225809,147 -1369,225956,145 -1370,226101,170 -1371,226271,164 -1372,226435,151 -1373,226586,148 -1374,226734,170 -1375,226904,170 -1376,227074,185 -1377,227259,163 -1378,227422,173 -1379,227595,140 -1380,227735,187 -1381,227922,228 -1382,228150,204 -1383,228354,159 -1384,228513,151 -1385,228664,139 -1386,228803,169 -1387,228972,207 -1388,229179,164 -1389,229343,148 -1390,229491,212 -1391,229703,187 -1392,229890,150 -1393,230040,177 -1394,230217,177 -1395,230394,170 -1396,230564,170 -1397,230734,143 -1398,230877,168 -1399,231045,188 -1400,231233,55 -1401,231288,188 -1402,231476,146 -1403,231622,208 -1404,231830,125 -1405,231955,176 -1406,232131,170 -1407,232301,150 -1408,232451,139 -1409,232590,154 -1410,232744,172 -1411,232916,169 -1412,233085,164 -1413,233249,162 -1414,233411,154 -1415,233565,176 -1416,233741,158 -1417,233899,155 -1418,234054,168 -1419,234222,158 -1420,234380,174 -1421,234554,151 -1422,234705,190 -1423,234895,175 -1424,235070,138 -1425,235208,155 -1426,235363,149 -1427,235512,167 -1428,235679,146 -1429,235825,150 -1430,235975,176 -1431,236151,167 -1432,236318,126 -1433,236444,192 -1434,236636,170 -1435,236806,170 -1436,236976,157 -1437,237133,180 -1438,237313,179 -1439,237492,144 -1440,237636,129 -1441,237765,170 -1442,237935,154 -1443,238089,128 -1444,238217,137 -1445,238354,155 -1446,238509,142 -1447,238651,155 -1448,238806,152 -1449,238958,169 -1450,239127,187 -1451,239314,162 -1452,239476,156 -1453,239632,171 -1454,239803,150 -1455,239953,149 -1456,240102,197 -1457,240299,133 -1458,240432,165 -1459,240597,180 -1460,240777,198 -1461,240975,184 -1462,241159,165 -1463,241324,183 -1464,241507,197 -1465,241704,140 -1466,241844,159 -1467,242003,120 -1468,242123,195 -1469,242318,129 -1470,242447,135 -1471,242582,178 -1472,242760,234 -1473,242994,163 -1474,243157,160 -1475,243317,157 -1476,243474,141 -1477,243615,115 -1478,243730,190 -1479,243920,124 -1480,244044,165 -1481,244209,203 -1482,244412,213 -1483,244625,194 -1484,244819,190 -1485,245009,152 -1486,245161,195 -1487,245356,192 -1488,245548,144 -1489,245692,156 -1490,245848,157 -1491,246005,175 -1492,246180,183 -1493,246363,160 -1494,246523,141 -1495,246664,148 -1496,246812,137 -1497,246949,191 -1498,247140,149 -1499,247289,137 -1500,247426,170 -1501,247596,170 -1502,247766,182 -1503,247948,166 -1504,248114,136 -1505,248250,145 -1506,248395,188 -1507,248583,172 -1508,248755,158 -1509,248913,155 -1510,249068,134 -1511,249202,184 -1512,249386,149 -1513,249535,158 -1514,249693,170 -1515,249863,181 -1516,250044,149 -1517,250193,146 -1518,250339,276 -1519,250615,187 -1520,250802,114 -1521,250916,166 -1522,251082,132 -1523,251214,118 -1524,251332,164 -1525,251496,148 -1526,251644,149 -1527,251793,158 -1528,251951,171 -1529,252122,152 -1530,252274,157 -1531,252431,160 -1532,252591,148 -1533,252739,168 -1534,252907,128 -1535,253035,178 -1536,253213,159 -1537,253372,162 -1538,253534,203 -1539,253737,142 -1540,253879,162 -1541,254041,177 -1542,254218,155 -1543,254373,230 -1544,254603,129 -1545,254732,159 -1546,254891,121 -1547,255012,177 -1548,255189,154 -1549,255343,159 -1550,255502,150 -1551,255652,145 -1552,255797,152 -1553,255949,150 -1554,256099,174 -1555,256273,190 -1556,256463,147 -1557,256610,167 -1558,256777,168 -1559,256945,148 -1560,257093,213 -1561,257306,206 -1562,257512,154 -1563,257666,213 -1564,257879,184 -1565,258063,190 -1566,258253,142 -1567,258395,144 -1568,258539,156 -1569,258695,160 -1570,258855,216 -1571,259071,179 -1572,259250,173 -1573,259423,158 -1574,259581,121 -1575,259702,207 -1576,259909,170 -1577,260079,170 -1578,260249,170 -1579,260419,161 -1580,260580,141 -1581,260721,186 -1582,260907,174 -1583,261081,172 -1584,261253,141 -1585,261394,134 -1586,261528,146 -1587,261674,151 -1588,261825,142 -1589,261967,178 -1590,262145,190 -1591,262335,228 -1592,262563,169 -1593,262732,114 -1594,262846,141 -1595,262987,163 -1596,263150,196 -1597,263346,168 -1598,263514,132 -1599,263646,162 -1600,263808,163 -1601,263971,127 -1602,264098,179 -1603,264277,198 -1604,264475,184 -1605,264659,177 -1606,264836,229 -1607,265065,142 -1608,265207,140 -1609,265347,141 -1610,265488,191 -1611,265679,139 -1612,265818,173 -1613,265991,127 -1614,266118,201 -1615,266319,202 -1616,266521,167 -1617,266688,172 -1618,266860,170 -1619,267030,170 -1620,267200,193 -1621,267393,158 -1622,267551,121 -1623,267672,166 -1624,267838,227 -1625,268065,150 -1626,268215,163 -1627,268378,146 -1628,268524,190 -1629,268714,154 -1630,268868,148 -1631,269016,147 -1632,269163,173 -1633,269336,217 -1634,269553,163 -1635,269716,198 -1636,269914,148 -1637,270062,148 -1638,270210,146 -1639,270356,132 -1640,270488,151 -1641,270639,200 -1642,270839,178 -1643,271017,156 -1644,271173,176 -1645,271349,146 -1646,271495,193 -1647,271688,161 -1648,271849,124 -1649,271973,125 -1650,272098,143 -1651,272241,177 -1652,272418,154 -1653,272572,165 -1654,272737,164 -1655,272901,119 -1656,273020,186 -1657,273206,146 -1658,273352,169 -1659,273521,219 -1660,273740,156 -1661,273896,142 -1662,274038,174 -1663,274212,136 -1664,274348,168 -1665,274516,148 -1666,274664,132 -1667,274796,174 -1668,274970,149 -1669,275119,151 -1670,275270,157 -1671,275427,186 -1672,275613,208 -1673,275821,167 -1674,275988,190 -1675,276178,175 -1676,276353,162 -1677,276515,140 -1678,276655,145 -1679,276800,147 -1680,276947,155 -1681,277102,133 -1682,277235,179 -1683,277414,229 -1684,277643,167 -1685,277810,176 -1686,277986,157 -1687,278143,164 -1688,278307,129 -1689,278436,161 -1690,278597,135 -1691,278732,173 -1692,278905,148 -1693,279053,159 -1694,279212,130 -1695,279342,156 -1696,279498,134 -1697,279632,167 -1698,279799,152 -1699,279951,131 -1700,280082,183 -1701,280265,167 -1702,280432,206 -1703,280638,131 -1704,280769,165 -1705,280934,160 -1706,281094,149 -1707,281243,197 -1708,281440,177 -1709,281617,157 -1710,281774,219 -1711,281993,154 -1712,282147,148 -1713,282295,130 -1714,282425,162 -1715,282587,163 -1716,282750,160 -1717,282910,158 -1718,283068,135 -1719,283203,119 -1720,283322,153 -1721,283475,136 -1722,283611,160 -1723,283771,151 -1724,283922,141 -1725,284063,182 -1726,284245,140 -1727,284385,172 -1728,284557,172 -1729,284729,156 -1730,284885,170 -1731,285055,161 -1732,285216,193 -1733,285409,188 -1734,285597,109 -1735,285706,192 -1736,285898,195 -1737,286093,220 -1738,286313,220 -1739,286533,135 -1740,286668,194 -1741,286862,137 -1742,286999,141 -1743,287140,194 -1744,287334,160 -1745,287494,152 -1746,287646,160 -1747,287806,165 -1748,287971,175 -1749,288146,153 -1750,288299,170 -1751,288469,170 -1752,288639,156 -1753,288795,133 -1754,288928,182 -1755,289110,185 -1756,289295,171 -1757,289466,201 -1758,289667,141 -1759,289808,147 -1760,289955,171 -1761,290126,144 -1762,290270,192 -1763,290462,166 -1764,290628,195 -1765,290823,218 -1766,291041,180 -1767,291221,174 -1768,291395,182 -1769,291577,155 -1770,291732,165 -1771,291897,139 -1772,292036,163 -1773,292199,151 -1774,292350,280 -1775,292630,155 -1776,292785,135 -1777,292920,115 -1778,293035,157 -1779,293192,160 -1780,293352,201 -1781,293553,147 -1782,293700,170 -1783,293870,147 -1784,294017,174 -1785,294191,186 -1786,294377,175 -1787,294552,188 -1788,294740,173 -1789,294913,197 -1790,295110,168 -1791,295278,203 -1792,295481,197 -1793,295678,171 -1794,295849,161 -1795,296010,140 -1796,296150,147 -1797,296297,168 -1798,296465,162 -1799,296627,147 -1800,296774,158 -1801,296932,143 -1802,297075,178 -1803,297253,172 -1804,297425,188 -1805,297613,170 -1806,297783,170 -1807,297953,163 -1808,298116,130 -1809,298246,128 -1810,298374,206 -1811,298580,166 -1812,298746,120 -1813,298866,182 -1814,299048,166 -1815,299214,148 -1816,299362,203 -1817,299565,174 -1818,299739,184 -1819,299923,149 -1820,300072,168 -1821,300240,222 -1822,300462,185 -1823,300647,162 -1824,300809,160 -1825,300969,146 -1826,301115,154 -1827,301269,161 -1828,301430,190 -1829,301620,182 -1830,301802,264 -1831,302066,176 -1832,302242,175 -1833,302417,153 -1834,302570,147 -1835,302717,197 -1836,302914,124 -1837,303038,120 -1838,303158,124 -1839,303282,147 -1840,303429,186 -1841,303615,145 -1842,303760,192 -1843,303952,144 -1844,304096,138 -1845,304234,171 -1846,304405,222 -1847,304627,176 -1848,304803,224 -1849,305027,154 -1850,305181,132 -1851,305313,142 -1852,305455,141 -1853,305596,211 -1854,305807,258 -1855,306065,193 -1856,306258,164 -1857,306422,157 -1858,306579,133 -1859,306712,185 -1860,306897,137 -1861,307034,189 -1862,307223,133 -1863,307356,113 -1864,307469,152 -1865,307621,134 -1866,307755,148 -1867,307903,144 -1868,308047,133 -1869,308180,173 -1870,308353,156 -1871,308509,170 -1872,308679,170 -1873,308849,161 -1874,309010,185 -1875,309195,231 -1876,309426,179 -1877,309605,119 -1878,309724,180 -1879,309904,142 -1880,310046,149 -1881,310195,158 -1882,310353,203 -1883,310556,142 -1884,310698,157 -1885,310855,139 -1886,310994,165 -1887,311159,172 -1888,311331,238 -1889,311569,193 -1890,311762,168 -1891,311930,202 -1892,312132,200 -1893,312332,185 -1894,312517,197 -1895,312714,228 -1896,312942,113 -1897,313055,151 -1898,313206,188 -1899,313394,122 -1900,313516,166 -1901,313682,137 -1902,313819,191 -1903,314010,157 -1904,314167,191 -1905,314358,177 -1906,314535,189 -1907,314724,168 -1908,314892,198 -1909,315090,158 -1910,315248,131 -1911,315379,131 -1912,315510,170 -1913,315680,182 -1914,315862,184 -1915,316046,154 -1916,316200,141 -1917,316341,170 -1918,316511,127 -1919,316638,173 -1920,316811,147 -1921,316958,134 -1922,317092,177 -1923,317269,181 -1924,317450,170 -1925,317620,170 -1926,317790,166 -1927,317956,158 -1928,318114,184 -1929,318298,176 -1930,318474,211 -1931,318685,171 -1932,318856,172 -1933,319028,158 -1934,319186,137 -1935,319323,179 -1936,319502,198 -1937,319700,190 -1938,319890,150 -1939,320040,190 -1940,320230,161 -1941,320391,222 -1942,320613,165 -1943,320778,180 -1944,320958,122 -1945,321080,184 -1946,321264,151 -1947,321415,153 -1948,321568,219 -1949,321787,156 -1950,321943,186 -1951,322129,159 -1952,322288,150 -1953,322438,154 -1954,322592,149 -1955,322741,177 -1956,322918,191 -1957,323109,130 -1958,323239,157 -1959,323396,127 -1960,323523,165 -1961,323688,132 -1962,323820,149 -1963,323969,175 -1964,324144,115 -1965,324259,174 -1966,324433,192 -1967,324625,156 -1968,324781,161 -1969,324942,153 -1970,325095,167 -1971,325262,170 -1972,325432,170 -1973,325602,184 -1974,325786,179 -1975,325965,208 -1976,326173,162 -1977,326335,190 -1978,326525,143 -1979,326668,142 -1980,326810,132 -1981,326942,120 -1982,327062,155 -1983,327217,174 -1984,327391,146 -1985,327537,159 -1986,327696,178 -1987,327874,132 -1988,328006,157 -1989,328163,129 -1990,328292,140 -1991,328432,185 -1992,328617,165 -1993,328782,160 -1994,328942,207 -1995,329149,128 -1996,329277,147 -1997,329424,172 -1998,329596,154 -1999,329750,113 -2000,329863,208 -2001,330071,175 -2002,330246,161 -2003,330407,169 -2004,330576,230 -2005,330806,186 -2006,330992,123 -2007,331115,140 -2008,331255,177 -2009,331432,169 -2010,331601,185 -2011,331786,181 -2012,331967,185 -2013,332152,152 -2014,332304,124 -2015,332428,151 -2016,332579,136 -2017,332715,191 -2018,332906,142 -2019,333048,183 -2020,333231,179 -2021,333410,162 -2022,333572,151 -2023,333723,166 -2024,333889,134 -2025,334023,163 -2026,334186,154 -2027,334340,170 -2028,334510,170 -2029,334680,162 -2030,334842,161 -2031,335003,175 -2032,335178,142 -2033,335320,158 -2034,335478,141 -2035,335619,155 -2036,335774,147 -2037,335921,132 -2038,336053,160 -2039,336213,156 -2040,336369,141 -2041,336510,126 -2042,336636,137 -2043,336773,178 -2044,336951,146 -2045,337097,153 -2046,337250,158 -2047,337408,143 -2048,337551,161 -2049,337712,173 -2050,337885,175 -2051,338060,166 -2052,338226,114 -2053,338340,171 -2054,338511,197 -2055,338708,172 -2056,338880,151 -2057,339031,133 -2058,339164,139 -2059,339303,154 -2060,339457,144 -2061,339601,129 -2062,339730,147 -2063,339877,150 -2064,340027,150 -2065,340177,193 -2066,340370,166 -2067,340536,178 -2068,340714,151 -2069,340865,148 -2070,341013,126 -2071,341139,181 -2072,341320,147 -2073,341467,118 -2074,341585,218 -2075,341803,146 -2076,341949,133 -2077,342082,168 -2078,342250,116 -2079,342366,195 -2080,342561,170 -2081,342731,170 -2082,342901,150 -2083,343051,156 -2084,343207,159 -2085,343366,145 -2086,343511,143 -2087,343654,136 -2088,343790,164 -2089,343954,159 -2090,344113,172 -2091,344285,185 -2092,344470,130 -2093,344600,194 -2094,344794,180 -2095,344974,170 -2096,345144,170 -2097,345314,170 -2098,345484,136 -2126,345620,141 -2127,345761,161 -2128,345922,157 -2129,346079,171 -2130,346250,192 -2131,346442,181 -2132,346623,171 -2133,346794,167 -2134,346961,175 -2135,347136,161 -2136,347297,181 -2137,347478,208 -2138,347686,176 -2139,347862,201 -2140,348063,224 -2141,348287,127 -2142,348414,108 -2143,348522,118 -2144,348640,178 -2145,348818,164 -2146,348982,178 -2147,349160,162 -2148,349322,127 -2149,349449,178 -2150,349627,158 -2151,349785,142 -2152,349927,144 -2153,350071,196 -2154,350267,134 -2155,350401,127 -2156,350528,145 -2157,350673,151 -2158,350824,122 -2159,350946,194 -2160,351140,169 -2161,351309,188 -2162,351497,171 -2163,351668,145 -2164,351813,146 -2165,351959,187 -2166,352146,187 -2167,352333,161 -2168,352494,171 -2169,352665,136 -2170,352801,137 -2171,352938,132 -2172,353070,170 -2173,353240,170 -2174,353410,199 -2175,353609,163 -2176,353772,192 -2177,353964,192 -2178,354156,146 -2179,354302,177 -2180,354479,127 -2181,354606,148 -2182,354754,183 -2183,354937,177 -2184,355114,224 -2185,355338,166 -2186,355504,141 -2187,355645,157 -2188,355802,181 -2189,355983,159 -2190,356142,163 -2191,356305,186 -2192,356491,173 -2193,356664,149 -2194,356813,134 -2195,356947,235 -2196,357182,197 -2197,357379,163 -2198,357542,172 -2199,357714,160 -2200,357874,167 -2201,358041,138 -2202,358179,155 -2203,358334,203 -2204,358537,170 -2205,358707,134 -2206,358841,177 -2207,359018,196 -2208,359214,160 -2209,359374,201 -2210,359575,159 -2211,359734,170 -2212,359904,170 -2213,360074,169 -2214,360243,196 -2215,360439,158 -2216,360597,139 -2217,360736,187 -2218,360923,136 -2219,361059,156 -2220,361215,161 -2221,361376,147 -2222,361523,183 -2223,361706,154 -2224,361860,167 -2225,362027,142 -2226,362169,267 -2227,362436,128 -2228,362564,148 -2229,362712,214 -2230,362926,151 -2231,363077,173 -2232,363250,150 -2233,363400,181 -2234,363581,195 -2235,363776,137 -2236,363913,121 -2237,364034,128 -2238,364162,183 -2239,364345,142 -2240,364487,181 -2241,364668,193 -2242,364861,170 -2243,365031,117 -2244,365148,153 -2245,365301,202 -2246,365503,173 -2247,365676,162 -2248,365838,170 -2249,366008,160 -2250,366168,198 -2251,366366,154 -2252,366520,142 -2253,366662,176 -2254,366838,155 -2255,366993,186 -2256,367179,174 -2257,367353,159 -2258,367512,180 -2259,367692,167 -2260,367859,175 -2261,368034,176 -2262,368210,169 -2263,368379,142 -2264,368521,144 -2265,368665,150 -2266,368815,151 -2267,368966,133 -2268,369099,154 -2269,369253,183 -2270,369436,130 -2271,369566,166 -2272,369732,185 -2273,369917,125 -2274,370042,170 -2275,370212,170 -2276,370382,143 -2277,370525,145 -2278,370670,137 -2279,370807,152 -2280,370959,188 -2281,371147,134 -2282,371281,183 -2283,371464,159 -2284,371623,166 -2285,371789,191 -2286,371980,185 -2287,372165,125 -2288,372290,167 -2289,372457,116 -2290,372573,178 -2291,372751,150 -2292,372901,233 -2293,373134,179 -2294,373313,212 -2295,373525,222 -2296,373747,146 -2297,373893,177 -2298,374070,150 -2299,374220,140 -2300,374360,139 -2301,374499,187 -2302,374686,175 -2303,374861,188 -2304,375049,117 -2305,375166,228 -2306,375394,176 -2307,375570,158 -2308,375728,151 -2309,375879,168 -2310,376047,138 -2311,376185,164 -2312,376349,185 -2313,376534,145 -2314,376679,193 -2315,376872,155 -2316,377027,155 -2317,377182,183 -2318,377365,182 -2319,377547,136 -2320,377683,150 -2321,377833,170 -2322,378003,170 -2323,378173,168 -2324,378341,136 -2325,378477,160 -2326,378637,198 -2327,378835,174 -2328,379009,170 -2329,379179,149 -2330,379328,203 -2331,379531,189 -2332,379720,146 -2333,379866,203 -2334,380069,190 -2335,380259,135 -2336,380394,203 -2337,380597,130 -2338,380727,137 -2339,380864,179 -2340,381043,146 -2341,381189,141 -2342,381330,228 -2343,381558,162 -2344,381720,146 -2345,381866,173 -2346,382039,143 -2347,382182,167 -2348,382349,166 -2349,382515,175 -2350,382690,165 -2351,382855,181 -2352,383036,147 -2353,383183,214 -2354,383397,124 -2355,383521,194 -2356,383715,157 -2357,383872,150 -2358,384022,167 -2359,384189,227 -2360,384416,143 -2361,384559,150 -2362,384709,154 -2363,384863,176 -2364,385039,160 -2365,385199,166 -2366,385365,201 -2367,385566,210 -2368,385776,155 -2369,385931,191 -2370,386122,191 -2371,386313,170 -2372,386483,170 -2373,386653,162 -2374,386815,155 -2375,386970,150 -2376,387120,171 -2377,387291,159 -2378,387450,174 -2379,387624,138 -2380,387762,203 -2381,387965,186 -2382,388151,194 -2383,388345,181 -2384,388526,182 -2385,388708,171 -2386,388879,167 -2387,389046,199 -2388,389245,140 -2389,389385,214 -2390,389599,192 -2391,389791,149 -2392,389940,135 -2393,390075,178 -2394,390253,175 -2395,390428,149 -2396,390577,243 -2397,390820,198 -2398,391018,175 -2399,391193,144 -2400,391337,142 -2401,391479,188 -2402,391667,171 -2403,391838,163 -2404,392001,153 -2405,392154,185 -2406,392339,149 -2407,392488,156 -2408,392644,154 -2409,392798,178 -2410,392976,175 -2411,393151,170 -2412,393321,173 -2413,393494,180 -2414,393674,193 -2415,393867,214 -2416,394081,184 -2417,394265,159 -2418,394424,164 -2419,394588,192 -2420,394780,218 -2421,394998,177 -2422,395175,168 -2423,395343,148 -2424,395491,189 -2425,395680,213 -2426,395893,191 -2427,396084,170 -2428,396254,170 -2429,396424,154 -2430,396578,205 -2431,396783,141 -2432,396924,155 -2433,397079,174 -2434,397253,134 -2435,397387,206 -2436,397593,154 -2437,397747,198 -2438,397945,139 -2439,398084,187 -2440,398271,176 -2441,398447,148 -2442,398595,135 -2443,398730,174 -2444,398904,159 -2445,399063,186 -2446,399249,127 -2447,399376,164 -2448,399540,196 -2449,399736,222 -2450,399958,204 -2451,400162,175 -2452,400337,160 -2453,400497,186 -2454,400683,114 -2455,400797,153 -2456,400950,170 -2457,401120,145 -2458,401265,165 -2459,401430,146 -2460,401576,185 -2461,401761,149 -2462,401910,207 -2463,402117,134 -2464,402251,177 -2465,402428,172 -2466,402600,156 -2467,402756,198 -2468,402954,173 -2469,403127,234 -2470,403361,155 -2471,403516,137 -2472,403653,160 -2473,403813,153 -2474,403966,173 -2475,404139,130 -2476,404269,161 -2477,404430,177 -2478,404607,160 -2479,404767,132 -2480,404899,140 -2481,405039,167 -2482,405206,129 -2483,405335,135 -2484,405470,183 -2485,405653,174 -2486,405827,170 -2487,405997,170 -2488,406167,140 -2489,406307,205 -2490,406512,161 -2491,406673,145 -2492,406818,188 -2493,407006,177 -2494,407183,159 -2495,407342,161 -2496,407503,135 -2497,407638,129 -2498,407767,136 -2499,407903,127 -2500,408030,183 -2501,408213,195 -2502,408408,169 -2503,408577,149 -2504,408726,202 -2505,408928,208 -2506,409136,239 -2507,409375,167 -2508,409542,127 -2509,409669,176 -2510,409845,167 -2511,410012,152 -2512,410164,157 -2513,410321,171 -2514,410492,154 -2515,410646,161 -2516,410807,157 -2517,410964,176 -2518,411140,137 -2519,411277,165 -2520,411442,144 -2521,411586,158 -2522,411744,148 -2523,411892,129 -2524,412021,181 -2525,412202,208 -2526,412410,220 -2527,412630,208 -2528,412838,151 -2529,412989,176 -2530,413165,203 -2531,413368,160 -2532,413528,193 -2533,413721,177 -2534,413898,158 -2535,414056,159 -2536,414215,170 -2537,414385,170 -2538,414555,129 -2539,414684,140 -2540,414824,155 -2541,414979,169 -2542,415148,157 -2543,415305,170 -2544,415475,192 -2545,415667,165 -2546,415832,179 -2547,416011,190 -2548,416201,162 -2549,416363,236 -2550,416599,225 -2551,416824,197 -2552,417021,182 -2553,417203,168 -2555,417371,161 -2556,417532,152 -2557,417684,169 -2558,417853,195 -2559,418048,137 -2560,418185,168 -2561,418353,144 -2562,418497,197 -2563,418694,148 -2564,418842,182 -2565,419024,133 -2566,419157,139 -2567,419296,169 -2568,419465,170 -2569,419635,176 -2570,419811,163 -2571,419974,157 -2572,420131,199 -2573,420330,147 -2574,420477,160 -2575,420637,184 -2576,420821,168 -2577,420989,229 -2578,421218,190 -2579,421408,148 -2580,421556,125 -2581,421681,159 -2582,421840,140 -2583,421980,175 -2584,422155,158 -2585,422313,151 -2586,422464,168 -2587,422632,143 -2588,422775,207 -2589,422982,183 -2590,423165,204 -2591,423369,222 -2592,423591,148 -2593,423739,188 -2594,423927,136 -2595,424063,148 -2596,424211,156 -2597,424367,143 -2598,424510,140 -2599,424650,120 -2600,424770,130 -2601,424900,157 -2602,425057,163 -2603,425220,136 -2604,425356,184 -2605,425540,195 -2606,425735,195 -2607,425930,154 -2608,426084,161 -2609,426245,161 -2610,426406,155 -2611,426561,165 -2612,426726,183 -2613,426909,122 -2614,427031,177 -2615,427208,157 -2616,427365,152 -2617,427517,195 -2618,427712,233 -2619,427945,158 -2620,428103,129 -2621,428232,173 -2622,428405,136 -2623,428541,159 -2624,428700,185 -2625,428885,170 -2626,429055,170 -2627,429225,200 -2628,429425,158 -2629,429583,143 -2630,429726,172 -2631,429898,162 -2632,430060,181 -2633,430241,146 -2634,430387,175 -2635,430562,165 -2636,430727,171 -2637,430898,162 -2638,431060,159 -2639,431219,207 -2640,431426,189 -2641,431615,201 -2642,431816,182 -2643,431998,172 -2644,432170,149 -2645,432319,146 -2646,432465,164 -2647,432629,202 -2648,432831,201 -2649,433032,136 -2650,433168,215 -2651,433383,120 -2652,433503,136 -2653,433639,193 -2654,433832,166 -2655,433998,151 -2656,434149,176 -2657,434325,203 -2658,434528,169 -2659,434697,126 -2660,434823,156 -2661,434979,183 -2662,435162,199 -2663,435361,129 -2664,435490,181 -2665,435671,204 -2666,435875,146 -2667,436021,191 -2668,436212,147 -2669,436359,169 -2670,436528,143 -2671,436671,183 -2672,436854,150 -2673,437004,167 -2674,437171,134 -2675,437305,171 -2676,437476,164 -2677,437640,171 -2678,437811,207 -2679,438018,154 -2680,438172,130 -2681,438302,160 -2682,438462,170 -2683,438632,133 -2684,438765,156 -2685,438921,130 -2686,439051,166 -2687,439217,157 -2688,439374,147 -2689,439521,141 -2690,439662,189 -2691,439851,149 -2692,440000,218 -2693,440218,131 -2694,440349,119 -2695,440468,173 -2696,440641,131 -2697,440772,176 -2698,440948,170 -2699,441118,170 -2700,441288,144 -2701,441432,169 -2702,441601,180 -2703,441781,169 -2704,441950,173 -2705,442123,126 -2706,442249,162 -2707,442411,159 -2708,442570,175 -2709,442745,120 -2710,442865,192 -2711,443057,153 -2712,443210,146 -2713,443356,183 -2714,443539,206 -2715,443745,161 -2716,443906,159 -2717,444065,200 -2718,444265,210 -2719,444475,166 -2720,444641,163 -2721,444804,166 -2722,444970,168 -2723,445138,198 -2724,445336,189 -2725,445525,187 -2726,445712,141 -2727,445853,158 -2728,446011,152 -2729,446163,158 -2730,446321,166 -2731,446487,194 -2732,446681,150 -2733,446831,149 -2734,446980,171 -2735,447151,158 -2736,447309,156 -2737,447465,177 -2738,447642,176 -2739,447818,139 -2740,447957,165 -2741,448122,180 -2742,448302,145 -2743,448447,170 -2744,448617,170 -2745,448787,166 -2746,448953,202 -2747,449155,190 -2748,449345,155 -2749,449500,163 -2750,449663,197 -2751,449860,135 -2752,449995,198 -2753,450193,148 -2754,450341,223 -2755,450564,194 -2756,450758,179 -2757,450937,159 -2758,451096,148 -2759,451244,170 -2760,451414,210 -2761,451624,140 -2762,451764,157 -2763,451921,178 -2764,452099,167 -2765,452266,177 -2766,452443,193 -2767,452636,230 -2768,452866,233 -2769,453099,104 -2770,453203,178 -2771,453381,184 -2772,453565,188 -2773,453753,208 -2774,453961,161 -2775,454122,166 -2776,454288,180 -2777,454468,176 -2778,454644,181 -2779,454825,153 -2780,454978,140 -2781,455118,154 -2782,455272,200 -2783,455472,157 -2784,455629,154 -2785,455783,149 -2786,455932,199 -2787,456131,207 -2788,456338,178 -2789,456516,161 -2790,456677,212 -2791,456889,128 -2792,457017,222 -2793,457239,202 -2794,457441,174 -2795,457615,213 -2796,457828,167 -2797,457995,171 -2798,458166,157 -2799,458323,114 -2800,458437,251 -2801,458688,172 -2802,458860,146 -2803,459006,170 -2804,459176,170 -2805,459346,153 -2806,459499,230 -2807,459729,139 -2808,459868,168 -2809,460036,212 -2810,460248,177 -2811,460425,136 -2812,460561,186 -2813,460747,167 -2814,460914,148 -2815,461062,155 -2816,461217,207 -2817,461424,168 -2818,461592,155 -2819,461747,197 -2820,461944,176 -2821,462120,167 -2822,462287,147 -2823,462434,180 -2824,462614,151 -2825,462765,171 -2826,462936,139 -2827,463075,169 -2828,463244,145 -2829,463389,170 -2830,463559,152 -2831,463711,150 -2832,463861,192 -2833,464053,172 -2834,464225,210 -2835,464435,125 -2836,464560,162 -2837,464722,146 -2838,464868,189 -2839,465057,140 -2840,465197,55 -2841,465252,166 -2842,465418,178 -2843,465596,146 -2844,465742,125 -2845,465867,180 -2846,466047,172 -2847,466219,169 -2848,466388,149 -2849,466537,198 -2850,466735,185 -2851,466920,164 -2852,467084,186 -2853,467270,140 -2854,467410,185 -2855,467595,163 -2856,467758,136 -2857,467894,195 -2858,468089,174 -2859,468263,191 -2860,468454,151 -2861,468605,136 -2862,468741,251 -2863,468992,133 -2864,469125,210 -2865,469335,263 -2866,469598,141 -2867,469739,164 -2868,469903,186 -2869,470089,199 -2870,470288,170 -2871,470458,175 -2872,470633,140 -2873,470773,179 -2874,470952,174 -2875,471126,117 -2876,471243,191 -2877,471434,147 -2878,471581,137 -2879,471718,174 -2880,471892,134 -2881,472026,149 -2882,472175,180 -2883,472355,152 -2884,472507,151 -2885,472658,170 -2886,472828,170 -2887,472998,156 -2888,473154,135 -2889,473289,176 -2890,473465,168 -2891,473633,160 -2892,473793,149 -2893,473942,137 -2894,474079,216 -2895,474295,162 -2896,474457,144 -2897,474601,189 -2898,474790,225 -2899,475015,179 -2900,475194,164 -2901,475358,132 -2902,475490,143 -2903,475633,180 -2904,475813,146 -2905,475959,139 -2906,476098,136 -2907,476234,177 -2908,476411,148 -2909,476559,189 -2910,476748,191 -2911,476939,170 -2912,477109,170 -2913,477279,190 -2914,477469,122 -2915,477591,150 -2916,477741,158 -2917,477899,120 -2918,478019,190 -2919,478209,220 -2920,478429,177 -2921,478606,148 -2922,478754,189 -2923,478943,178 -2924,479121,148 -2925,479269,175 -2926,479444,157 -2927,479601,192 -2928,479793,158 -2929,479951,172 -2930,480123,130 -2931,480253,174 -2932,480427,193 -2933,480620,139 -2934,480759,172 -2935,480931,158 -2936,481089,160 -2937,481249,146 -2938,481395,141 -2939,481536,134 -2940,481670,155 -2941,481825,205 -2942,482030,159 -2943,482189,160 -2944,482349,154 -2945,482503,148 -2946,482651,179 -2947,482830,158 -2948,482988,126 -2949,483114,170 -2950,483284,143 -2951,483427,154 -2952,483581,131 -2953,483712,207 -2954,483919,136 -2955,484055,142 -2956,484197,140 -2957,484337,134 -2958,484471,168 -2959,484639,199 -2960,484838,179 -2961,485017,231 -2962,485248,142 -2963,485390,165 -2964,485555,198 -2965,485753,168 -2966,485921,146 -2967,486067,199 -2968,486266,166 -2969,486432,165 -2970,486597,213 -2971,486810,149 -2972,486959,184 -2973,487143,191 -2974,487334,185 -2975,487519,124 -2976,487643,175 -2977,487818,136 -2978,487954,173 -2979,488127,152 -2980,488279,189 -2981,488468,159 -2982,488627,172 -2983,488799,144 -2984,488943,181 -2985,489124,175 -2986,489299,152 -2987,489451,195 -2988,489646,183 -2989,489829,141 -2990,489970,187 -2991,490157,192 -2992,490349,140 -2993,490489,221 -2994,490710,177 -2995,490887,150 -2996,491037,187 -2997,491224,176 -2998,491400,199 -2999,491599,159 -3000,491758,183 -3001,491941,130 -3002,492071,143 -3003,492214,192 -3004,492406,164 -3005,492570,151 -3006,492721,170 -3007,492891,170 -3008,493061,215 -3009,493276,172 -3010,493448,171 -3011,493619,144 -3012,493763,137 -3013,493900,136 -3014,494036,123 -3015,494159,143 -3016,494302,158 -3017,494460,155 -3018,494615,219 -3019,494834,170 -3020,495004,113 -3021,495117,181 -3022,495298,132 -3023,495430,144 -3024,495574,174 -3025,495748,158 -3026,495906,180 -3027,496086,117 -3028,496203,257 -3029,496460,166 -3030,496626,171 -3031,496797,169 -3032,496966,164 -3033,497130,153 -3034,497283,156 -3035,497439,127 -3036,497566,178 -3037,497744,155 -3038,497899,128 -3039,498027,204 -3040,498231,145 -3041,498376,182 -3042,498558,155 -3043,498713,171 -3044,498884,158 -3045,499042,199 -3046,499241,153 -3047,499394,208 -3048,499602,142 -3049,499744,162 -3050,499906,149 -3051,500055,131 -3052,500186,179 -3053,500365,136 -3054,500501,153 -3055,500654,156 -3056,500810,183 -3057,500993,162 -3058,501155,217 -3059,501372,133 -3060,501505,55 -3061,501560,200 -3062,501760,164 -3063,501924,147 -3064,502071,130 -3065,502201,186 -3066,502387,130 -3067,502517,208 -3068,502725,170 -3069,502895,170 -3070,503065,177 -3071,503242,169 -3072,503411,164 -3073,503575,127 -3074,503702,109 -3075,503811,168 -3076,503979,130 -3077,504109,188 -3078,504297,167 -3079,504464,130 -3080,504594,188 -3081,504782,202 -3082,504984,295 -3083,505279,166 -3084,505445,180 -3085,505625,220 -3086,505845,150 -3087,505995,152 -3088,506147,146 -3089,506293,167 -3090,506460,176 -3091,506636,128 -3092,506764,172 -3093,506936,202 -3094,507138,176 -3095,507314,170 -3096,507484,151 -3097,507635,148 -3098,507783,178 -3099,507961,180 -3100,508141,187 -3101,508328,142 -3102,508470,161 -3103,508631,166 -3104,508797,189 -3105,508986,220 -3106,509206,185 -3107,509391,209 -3108,509600,135 -3109,509735,189 -3110,509924,182 -3111,510106,167 -3112,510273,167 -3113,510440,139 -3114,510579,196 -3115,510775,180 -3116,510955,181 -3117,511136,190 -3118,511326,277 -3119,511603,186 -3120,511789,170 -3121,511959,170 -3122,512129,165 -3123,512294,202 -3124,512496,150 -3125,512646,173 -3126,512819,207 -3127,513026,160 -3128,513186,142 -3129,513328,160 -3130,513488,129 -3131,513617,158 -3132,513775,181 -3133,513956,179 -3134,514135,136 -3135,514271,225 -3136,514496,152 -3137,514648,132 -3138,514780,124 -3139,514904,215 -3140,515119,175 -3141,515294,207 -3142,515501,167 -3143,515668,206 -3144,515874,171 -3145,516045,182 -3146,516227,196 -3147,516423,146 -3148,516569,141 -3149,516710,220 -3150,516930,181 -3151,517111,193 -3152,517304,159 -3153,517463,170 -3154,517633,145 -3155,517778,55 -3156,517833,158 -3157,517991,195 -3158,518186,172 -3159,518358,193 -3160,518551,135 -3161,518686,156 -3162,518842,194 -3163,519036,196 -3164,519232,143 -3165,519375,192 -3166,519567,153 -3167,519720,131 -3168,519851,143 -3169,519994,195 -3170,520189,157 -3171,520346,184 -3172,520530,176 -3173,520706,166 -3174,520872,162 -3175,521034,161 -3176,521195,135 -3177,521330,175 -3178,521505,127 -3179,521632,186 -3180,521818,153 -3181,521971,146 -3182,522117,164 -3183,522281,197 -3184,522478,122 -3185,522600,142 -3186,522742,184 -3187,522926,199 -3188,523125,147 -3189,523272,208 -3190,523480,205 -3191,523685,174 -3192,523859,204 -3193,524063,169 -3194,524232,166 -3195,524398,168 -3196,524566,221 -3197,524787,176 -3198,524963,159 -3199,525122,147 -3200,525269,146 -3201,525415,169 -3202,525584,157 -3203,525741,149 -3204,525890,185 -3205,526075,170 -3206,526245,170 -3207,526415,138 -3208,526553,172 -3209,526725,150 -3210,526875,195 -3211,527070,137 -3212,527207,188 -3213,527395,158 -3214,527553,170 -3215,527723,125 -3216,527848,146 -3217,527994,172 -3218,528166,126 -3219,528292,184 -3220,528476,186 -3221,528662,152 -3222,528814,137 -3223,528951,172 -3224,529123,214 -3225,529337,200 -3226,529537,193 -3227,529730,176 -3228,529906,208 -3229,530114,164 -3230,530278,167 -3231,530445,163 -3232,530608,168 -3233,530776,201 -3234,530977,157 -3235,531134,164 -3236,531298,175 -3237,531473,138 -3238,531611,147 -3239,531758,219 -3240,531977,166 -3241,532143,131 -3242,532274,184 -3243,532458,150 -3244,532608,164 -3245,532772,148 -3246,532920,154 -3247,533074,166 -3248,533240,221 -3249,533461,193 -3250,533654,181 -3251,533835,140 -3252,533975,196 -3253,534171,172 -3254,534343,233 -3255,534576,226 -3256,534802,118 -3257,534920,128 -3258,535048,134 -3259,535182,125 -3260,535307,158 -3261,535465,172 -3262,535637,173 -3263,535810,224 -3264,536034,132 -3265,536166,159 -3266,536325,205 -3267,536530,168 -3268,536698,122 -3269,536820,192 -3270,537012,146 -3271,537158,179 -3272,537337,186 -3273,537523,217 -3274,537740,175 -3275,537915,146 -3276,538061,140 -3277,538201,144 -3278,538345,170 -3279,538515,170 -3280,538685,135 -3281,538820,201 -3282,539021,138 -3283,539159,176 -3284,539335,174 -3285,539509,134 -3286,539643,163 -3287,539806,172 -3288,539978,158 -3289,540136,175 -3290,540311,165 -3291,540476,178 -3292,540654,175 -3293,540829,157 -3294,540986,172 -3295,541158,151 -3296,541309,169 -3297,541478,154 -3298,541632,139 -3299,541771,162 -3300,541933,171 -3301,542104,147 -3302,542251,144 -3303,542395,191 -3304,542586,173 -3305,542759,145 -3306,542904,189 -3307,543093,170 -3308,543263,164 -3309,543427,165 -3310,543592,122 -3311,543714,207 -3312,543921,130 -3313,544051,164 -3314,544215,149 -3315,544364,133 -3316,544497,171 -3317,544668,149 -3318,544817,143 -3319,544960,152 -3320,545112,165 -3321,545277,140 -3322,545417,178 -3323,545595,198 -3324,545793,162 -3325,545955,193 -3326,546148,174 -3327,546322,161 -3328,546483,147 -3329,546630,174 -3330,546804,146 -3331,546950,153 -3332,547103,186 -3333,547289,155 -3334,547444,194 -3335,547638,160 -3336,547798,157 -3337,547955,198 -3338,548153,146 -3339,548299,166 -3340,548465,159 -3341,548624,160 -3342,548784,188 -3343,548972,124 -3344,549096,128 -3345,549224,158 -3346,549382,177 -3347,549559,166 -3348,549725,221 -3349,549946,130 -3350,550076,171 -3351,550247,171 -3352,550418,202 -3353,550620,155 -3354,550775,178 -3355,550953,239 -3356,551192,194 -3357,551386,247 -3358,551633,157 -3359,551790,133 -3360,551923,178 -3361,552101,159 -3362,552260,170 -3363,552430,158 -3364,552588,165 -3365,552753,146 -3366,552899,214 -3367,553113,155 -3368,553268,170 -3369,553438,170 -3370,553608,114 -3371,553722,143 -3372,553865,178 -3373,554043,153 -3374,554196,195 -3375,554391,175 -3376,554566,165 -3377,554731,180 -3378,554911,177 -3379,555088,142 -3380,555230,222 -3381,555452,176 -3382,555628,211 -3383,555839,158 -3384,555997,130 -3385,556127,143 -3386,556270,141 -3387,556411,221 -3388,556632,151 -3389,556783,170 -3390,556953,183 -3391,557136,177 -3392,557313,180 -3393,557493,169 -3394,557662,189 -3395,557851,163 -3396,558014,172 -3397,558186,185 -3398,558371,157 -3399,558528,154 -3400,558682,196 -3401,558878,179 -3402,559057,137 -3403,559194,133 -3404,559327,175 -3405,559502,165 -3406,559667,179 -3407,559846,156 -3408,560002,136 -3409,560138,148 -3410,560286,198 -3411,560484,179 -3412,560663,182 -3413,560845,176 -3414,561021,127 -3415,561148,191 -3416,561339,55 -3417,561394,148 -3418,561542,144 -3419,561686,195 -3420,561881,157 -3421,562038,155 -3422,562193,168 -3423,562361,147 -3424,562508,170 -3425,562678,199 -3426,562877,162 -3427,563039,152 -3428,563191,159 -3429,563350,170 -3430,563520,170 -3431,563690,122 -3432,563812,164 -3433,563976,147 -3434,564123,183 -3435,564306,141 -3436,564447,125 -3437,564572,163 -3438,564735,138 -3439,564873,155 -3440,565028,157 -3441,565185,141 -3442,565326,137 -3443,565463,163 -3444,565626,172 -3445,565798,206 -3446,566004,171 -3447,566175,145 -3448,566320,156 -3449,566476,171 -3450,566647,172 -3451,566819,151 -3452,566970,138 -3453,567108,135 -3454,567243,161 -3455,567404,278 -3456,567682,155 -3457,567837,143 -3458,567980,119 -3459,568099,170 -3460,568269,161 -3461,568430,159 -3462,568589,144 -3463,568733,212 -3464,568945,179 -3465,569124,157 -3466,569281,198 -3467,569479,139 -3468,569618,170 -3469,569788,175 -3470,569963,175 -3471,570138,165 -3472,570303,159 -3473,570462,199 -3474,570661,204 -3475,570865,120 -3476,570985,176 -3477,571161,158 -3478,571319,174 -3479,571493,170 -3480,571663,204 -3481,571867,200 -3482,572067,171 -3483,572238,181 -3484,572419,140 -3485,572559,181 -3486,572740,181 -3487,572921,142 -3488,573063,139 -3489,573202,177 -3490,573379,173 -3491,573552,198 -3492,573750,156 -3493,573906,173 -3494,574079,180 -3495,574259,55 -3496,574314,191 -3497,574505,147 -3498,574652,185 -3499,574837,236 -3500,575073,150 -3501,575223,139 -3502,575362,209 -3503,575571,158 -3504,575729,169 -3505,575898,188 -3506,576086,135 -3507,576221,204 -3508,576425,125 -3509,576550,209 -3510,576759,150 -3511,576909,164 -3512,577073,121 -3513,577194,138 -3514,577332,174 -3515,577506,154 -3516,577660,170 -3517,577830,170 -3518,578000,186 -3519,578186,183 -3520,578369,127 -3521,578496,141 -3522,578637,55 -3523,578692,214 -3524,578906,161 -3525,579067,158 -3526,579225,198 -3527,579423,158 -3528,579581,143 -3529,579724,164 -3530,579888,166 -3531,580054,191 -3532,580245,168 -3533,580413,177 -3534,580590,147 -3535,580737,138 -3536,580875,158 -3537,581033,146 -3538,581179,161 -3539,581340,195 -3540,581535,144 -3541,581679,193 -3542,581872,178 -3543,582050,126 -3544,582176,146 -3545,582322,132 -3546,582454,143 -3547,582597,213 -3548,582810,140 -3549,582950,231 -3550,583181,171 -3551,583352,158 -3552,583510,169 -3553,583679,160 -3554,583839,171 -3555,584010,155 -3556,584165,152 -3557,584317,160 -3558,584477,204 -3559,584681,154 -3560,584835,190 -3561,585025,126 -3562,585151,198 -3563,585349,161 -3564,585510,170 -3565,585680,170 -3566,585850,173 -3567,586023,151 -3568,586174,179 -3569,586353,198 -3570,586551,55 -3571,586606,124 -3572,586730,179 -3573,586909,189 -3574,587098,179 -3575,587277,158 -3576,587435,168 -3577,587603,170 -3578,587773,156 -3579,587929,125 -3580,588054,156 -3581,588210,186 -3582,588396,175 -3583,588571,190 -3584,588761,190 -3585,588951,179 -3586,589130,140 -3587,589270,149 -3588,589419,144 -3589,589563,159 -3590,589722,166 -3591,589888,181 -3592,590069,147 -3593,590216,218 -3594,590434,140 -3595,590574,245 -3596,590819,166 -3597,590985,153 -3598,591138,157 -3599,591295,115 -3600,591410,159 -3601,591569,193 -3602,591762,168 -3603,591930,158 -3604,592088,180 -3605,592268,133 -3606,592401,141 -3607,592542,55 -3608,592597,139 -3609,592736,141 -3610,592877,149 -3611,593026,115 -3612,593141,138 -3613,593279,197 -3614,593476,158 -3615,593634,185 -3616,593819,176 -3617,593995,172 -3618,594167,55 -3619,594222,151 -3620,594373,193 -3621,594566,203 -3622,594769,195 -3623,594964,185 -3624,595149,190 -3625,595339,173 -3626,595512,55 -3627,595567,143 -3628,595710,168 -3629,595878,219 -3630,596097,209 -3631,596306,203 -3632,596509,157 -3633,596666,174 -3634,596840,136 -3635,596976,218 -3636,597194,157 -3637,597351,143 -3638,597494,180 -3639,597674,155 -3640,597829,170 -3641,597999,170 -3642,598169,132 -3643,598301,167 -3644,598468,162 -3645,598630,124 -3646,598754,155 -3647,598909,153 -3648,599062,153 -3649,599215,182 -3650,599397,191 -3651,599588,213 -3652,599801,163 -3653,599964,209 -3654,600173,179 -3655,600352,205 -3656,600557,158 -3657,600715,144 -3658,600859,199 -3659,601058,158 -3660,601216,148 -3661,601364,139 -3662,601503,183 -3663,601686,128 -3664,601814,160 -3665,601974,163 -3666,602137,158 -3667,602295,183 -3668,602478,146 -3669,602624,118 -3670,602742,149 -3671,602891,185 -3672,603076,144 -3673,603220,145 -3674,603365,172 -3675,603537,183 -3676,603720,147 -3677,603867,160 -3678,604027,214 -3679,604241,148 -3680,604389,203 -3681,604592,177 -3682,604769,150 -3683,604919,157 -3684,605076,131 -3685,605207,135 -3686,605342,200 -3687,605542,201 -3688,605743,179 -3689,605922,207 -3690,606129,182 -3691,606311,158 -3692,606469,163 -3693,606632,185 -3694,606817,182 -3695,606999,210 -3696,607209,140 -3697,607349,230 -3698,607579,135 -3699,607714,134 -3700,607848,199 -3701,608047,160 -3702,608207,169 -3703,608376,150 -3704,608526,126 -3705,608652,159 -3706,608811,211 -3707,609022,116 -3708,609138,150 -3709,609288,164 -3710,609452,123 -3711,609575,181 -3712,609756,145 -3713,609901,176 -3714,610077,165 -3715,610242,170 -3716,610412,170 -3717,610582,164 -3718,610746,155 -3719,610901,142 -3720,611043,135 -3721,611178,127 -3722,611305,176 -3723,611481,186 -3724,611667,139 -3725,611806,174 -3726,611980,207 -3727,612187,166 -3728,612353,164 -3729,612517,147 -3730,612664,184 -3731,612848,209 -3732,613057,172 -3733,613229,200 -3734,613429,201 -3735,613630,202 -3736,613832,169 -3737,614001,167 -3738,614168,192 -3739,614360,210 -3740,614570,158 -3741,614728,140 -3742,614868,186 -3743,615054,131 -3744,615185,190 -3745,615375,192 -3746,615567,141 -3747,615708,197 -3748,615905,146 -3749,616051,131 -3750,616182,167 -3751,616349,142 -3752,616491,224 -3753,616715,240 -3754,616955,158 -3755,617113,140 -3756,617253,196 -3757,617449,181 -3758,617630,198 -3759,617828,137 -3760,617965,146 -3761,618111,191 -3762,618302,158 -3763,618460,139 -3764,618599,211 -3765,618810,201 -3766,619011,180 -3767,619191,164 -3768,619355,144 -3769,619499,187 -3770,619686,183 -3771,619869,141 -3772,620010,150 -3773,620160,164 -3774,620324,196 -3775,620520,169 -3776,620689,150 -3777,620839,155 -3778,620994,164 -3779,621158,156 -3780,621314,142 -3781,621456,171 -3782,621627,203 -3783,621830,167 -3784,621997,143 -3785,622140,202 -3786,622342,144 -3787,622486,164 -3788,622650,152 -3789,622802,126 -3790,622928,140 -3791,623068,191 -3792,623259,168 -3793,623427,153 -3794,623580,161 -3795,623741,150 -3796,623891,147 -3797,624038,164 -3798,624202,170 -3799,624372,170 -3800,624542,153 -3801,624695,136 -3802,624831,191 -3803,625022,137 -3804,625159,191 -3805,625350,145 -3806,625495,148 -3807,625643,138 -3808,625781,168 -3809,625949,170 -3810,626119,144 -3811,626263,179 -3812,626442,181 -3813,626623,172 -3814,626795,143 -3815,626938,217 -3816,627155,238 -3817,627393,178 -3818,627571,198 -3819,627769,206 -3820,627975,124 -3821,628099,138 -3822,628237,143 -3823,628380,55 -3824,628435,137 -3825,628572,143 -3826,628715,174 -3827,628889,129 -3828,629018,203 -3829,629221,183 -3830,629404,207 -3831,629611,157 -3832,629768,179 -3833,629947,150 -3834,630097,228 -3835,630325,138 -3836,630463,151 -3837,630614,158 -3838,630772,165 -3839,630937,137 -3840,631074,158 -3841,631232,134 -3842,631366,186 -3843,631552,168 -3844,631720,138 -3845,631858,151 -3846,632009,150 -3847,632159,159 -3848,632318,126 -3849,632444,55 -3850,632499,153 -3851,632652,170 -3852,632822,150 -3853,632972,205 -3854,633177,179 -3855,633356,199 -3856,633555,134 -3857,633689,129 -3858,633818,144 -3859,633962,155 -3860,634117,205 -3861,634322,144 -3862,634466,217 -3863,634683,147 -3864,634830,174 -3865,635004,147 -3866,635151,146 -3867,635297,195 -3868,635492,182 -3869,635674,156 -3870,635830,277 -3871,636107,127 -3872,636234,181 -3873,636415,185 -3874,636600,148 -3875,636748,170 -3876,636918,170 -3877,637088,139 -3878,637227,152 -3879,637379,173 -3880,637552,155 -3881,637707,179 -3882,637886,170 -3883,638056,185 -3884,638241,152 -3885,638393,240 -3886,638633,214 -3887,638847,196 -3888,639043,181 -3889,639224,187 -3890,639411,196 -3891,639607,192 -3892,639799,170 -3893,639969,170 -3894,640139,170 -3895,640309,166 -3896,640475,152 -3897,640627,131 -3898,640758,156 -3899,640914,181 -3900,641095,147 -3901,641242,202 -3902,641444,155 -3903,641599,153 -3904,641752,181 -3905,641933,193 -3906,642126,126 -3907,642252,164 -3908,642416,138 -3909,642554,139 -3910,642693,124 -3911,642817,131 -3912,642948,177 -3913,643125,188 -3914,643313,178 -3915,643491,169 -3916,643660,150 -3917,643810,142 -3918,643952,132 -3919,644084,159 -3920,644243,177 -3921,644420,163 -3922,644583,175 -3923,644758,182 -3924,644940,179 -3925,645119,192 -3926,645311,156 -3927,645467,190 -3928,645657,191 -3929,645848,150 -3930,645998,144 -3931,646142,183 -3932,646325,187 -3933,646512,126 -3934,646638,117 -3935,646755,180 -3936,646935,164 -3937,647099,162 -3938,647261,157 -3939,647418,153 -3940,647571,150 -3941,647721,171 -3942,647892,132 -3943,648024,171 -3944,648195,203 -3945,648398,161 -3946,648559,150 -3947,648709,178 -3948,648887,143 -3949,649030,183 -3950,649213,110 -3951,649323,171 -3952,649494,159 -3953,649653,159 -3954,649812,139 -3955,649951,189 -3956,650140,151 -3957,650291,157 -3958,650448,171 -3959,650619,178 -3960,650797,152 -3961,650949,215 -3962,651164,224 -3963,651388,154 -3964,651542,204 -3965,651746,138 -3966,651884,199 -3967,652083,201 -3968,652284,205 -3969,652489,141 -3970,652630,159 -3971,652789,172 -3972,652961,166 -3973,653127,184 -3974,653311,164 -3975,653475,161 -3976,653636,137 -3977,653773,220 -3978,653993,168 -3979,654161,166 -3980,654327,170 -3981,654497,150 -3982,654647,188 -3983,654835,170 -3984,655005,170 -3985,655175,164 -3986,655339,149 -3987,655488,130 -3988,655618,135 -3989,655753,213 -3990,655966,150 -3991,656116,154 -3992,656270,169 -3993,656439,208 -3994,656647,146 -3995,656793,158 -3996,656951,146 -3997,657097,189 -3998,657286,160 -3999,657446,147 -4000,657593,193 -4001,657786,196 -4002,657982,127 -4003,658109,190 -4004,658299,160 -4005,658459,143 -4006,658602,154 -4007,658756,167 -4008,658923,155 -4009,659078,129 -4010,659207,146 -4011,659353,205 -4012,659558,142 -4013,659700,158 -4014,659858,169 -4015,660027,142 -4016,660169,170 -4017,660339,157 -4018,660496,231 -4019,660727,165 -4020,660892,167 -4021,661059,145 -4022,661204,166 -4023,661370,155 -4024,661525,166 -4025,661691,147 -4026,661838,121 -4027,661959,208 -4028,662167,186 -4029,662353,161 -4030,662514,157 -4031,662671,133 -4032,662804,116 -4033,662920,137 -4034,663057,151 -4035,663208,176 -4036,663384,138 -4037,663522,154 -4038,663676,142 -4039,663818,153 -4040,663971,163 -4041,664134,128 -4042,664262,171 -4043,664433,182 -4044,664615,170 -4045,664785,150 -4046,664935,180 -4047,665115,164 -4048,665279,129 -4049,665408,211 -4050,665619,159 -4051,665778,144 -4052,665922,165 -4053,666087,137 -4054,666224,179 -4055,666403,147 -4056,666550,137 -4057,666687,168 -4058,666855,151 -4059,667006,150 -4060,667156,174 -4061,667330,128 -4062,667458,176 -4063,667634,182 -4064,667816,215 -4065,668031,245 -4066,668276,255 -4067,668531,154 -4068,668685,182 -4069,668867,170 -4070,669037,166 -4071,669203,172 -4072,669375,150 -4073,669525,167 -4074,669692,202 -4075,669894,153 -4076,670047,124 -4077,670171,191 -4078,670362,168 -4079,670530,173 -4080,670703,130 -4081,670833,146 -4082,670979,162 -4083,671141,217 -4084,671358,156 -4085,671514,175 -4086,671689,190 -4087,671879,170 -4088,672049,170 -4089,672219,193 -4090,672412,153 -4091,672565,173 -4092,672738,159 -4093,672897,176 -4094,673073,191 -4095,673264,131 -4096,673395,187 -4097,673582,155 -4098,673737,132 -4099,673869,151 -4100,674020,170 -4101,674190,147 -4102,674337,169 -4103,674506,164 -4104,674670,182 -4105,674852,145 -4106,674997,189 -4107,675186,163 -4108,675349,136 -4109,675485,160 -4110,675645,160 -4111,675805,157 -4112,675962,154 -4113,676116,156 -4114,676272,162 -4115,676434,150 -4116,676584,156 -4117,676740,123 -4118,676863,145 -4119,677008,161 -4120,677169,151 -4121,677320,173 -4122,677493,150 -4123,677643,166 -4124,677809,173 -4125,677982,206 -4126,678188,203 -4127,678391,154 -4128,678545,169 -4129,678714,177 -4130,678891,163 -4131,679054,183 -4132,679237,174 -4133,679411,137 -4134,679548,177 -4135,679725,166 -4136,679891,172 -4137,680063,156 -4138,680219,159 -4139,680378,197 -4140,680575,132 -4141,680707,161 -4142,680868,215 -4143,681083,154 -4144,681237,133 -4145,681370,184 -4146,681554,151 -4147,681705,172 -4148,681877,142 -4149,682019,217 -4150,682236,171 -4151,682407,192 -4152,682599,180 -4153,682779,142 -4154,682921,146 -4155,683067,158 -4156,683225,159 -4157,683384,129 -4158,683513,162 -4159,683675,168 -4160,683843,174 -4161,684017,159 -4162,684176,160 -4163,684336,139 -4164,684475,207 -4165,684682,172 -4166,684854,154 -4167,685008,164 -4168,685172,162 -4169,685334,138 -4170,685472,165 -4171,685637,167 -4172,685804,153 -4173,685957,201 -4174,686158,139 -4175,686297,177 -4176,686474,143 -4177,686617,150 -4178,686767,162 -4179,686929,167 -4180,687096,156 -4181,687252,182 -4182,687434,154 -4183,687588,155 -4184,687743,162 -4185,687905,158 -4186,688063,168 -4187,688231,138 -4188,688369,194 -4189,688563,139 -4190,688702,210 -4191,688912,137 -4192,689049,183 -4193,689232,172 -4194,689404,146 -4195,689550,172 -4196,689722,140 -4197,689862,148 -4198,690010,177 -4199,690187,124 -4200,690311,161 -4201,690472,177 -4202,690649,172 -4203,690821,149 -4204,690970,129 -4205,691099,171 -4206,691270,134 -4207,691404,164 -4208,691568,164 -4209,691732,116 -4210,691848,171 -4211,692019,158 -4212,692177,188 -4213,692365,157 -4214,692522,125 -4215,692647,158 -4216,692805,173 -4217,692978,154 -4218,693132,145 -4219,693277,159 -4220,693436,140 -4221,693576,183 -4222,693759,154 -4223,693913,159 -4224,694072,161 -4225,694233,131 -4226,694364,164 -4227,694528,177 -4228,694705,144 -4229,694849,171 -4230,695020,155 -4231,695175,189 -4232,695364,165 -4233,695529,129 -4234,695658,150 -4235,695808,161 -4236,695969,228 -4237,696197,181 -4238,696378,211 -4239,696589,136 -4240,696725,137 -4241,696862,142 -4242,697004,158 -4243,697162,153 -4244,697315,204 -4245,697519,148 -4246,697667,163 -4247,697830,211 -4248,698041,163 -4249,698204,168 -4250,698372,116 -4251,698488,149 -4252,698637,161 -4253,698798,159 -4254,698957,127 -4255,699084,126 -4256,699210,188 -4257,699398,176 -4258,699574,127 -4259,699701,144 -4260,699845,136 -4261,699981,168 -4262,700149,156 -4263,700305,176 -4264,700481,178 -4265,700659,147 -4266,700806,144 -4267,700950,186 -4268,701136,165 -4269,701301,157 -4270,701458,165 -4271,701623,158 -4272,701781,175 -4273,701956,145 -4274,702101,159 -4275,702260,188 -4276,702448,152 -4277,702600,216 -4278,702816,167 -4279,702983,173 -4280,703156,160 -4281,703316,140 -4282,703456,170 -4283,703626,206 -4284,703832,144 -4285,703976,219 -4286,704195,165 -4287,704360,147 -4288,704507,143 -4289,704650,153 -4290,704803,156 -4291,704959,157 -4292,705116,214 -4293,705330,165 -4294,705495,239 -4295,705734,169 -4296,705903,225 -4297,706128,222 -4298,706350,151 -4299,706501,164 -4300,706665,175 -4301,706840,138 -4302,706978,173 -4303,707151,164 -4304,707315,119 -4305,707434,163 -4306,707597,158 -4307,707755,146 -4308,707901,167 -4309,708068,182 -4310,708250,136 -4311,708386,173 -4312,708559,141 -4313,708700,160 -4314,708860,146 -4315,709006,162 -4316,709168,203 -4317,709371,182 -4318,709553,188 -4319,709741,186 -4320,709927,154 -4321,710081,134 -4322,710215,140 -4323,710355,175 -4324,710530,139 -4325,710669,151 -4326,710820,180 -4327,711000,149 -4328,711149,160 -4329,711309,168 -4330,711477,146 -4331,711623,157 -4332,711780,135 -4333,711915,185 -4334,712100,150 -4335,712250,163 -4336,712413,173 -4337,712586,150 -4338,712736,141 -4339,712877,213 -4340,713090,172 -4341,713262,149 -4342,713411,156 -4343,713567,153 -4344,713720,167 -4345,713887,151 -4346,714038,120 -4347,714158,201 -4348,714359,163 -4349,714522,117 -4350,714639,205 -4351,714844,156 -4352,715000,150 -4353,715150,188 -4354,715338,176 -4355,715514,149 -4356,715663,164 -4357,715827,204 -4358,716031,144 -4359,716175,160 -4360,716335,170 -4361,716505,179 -4362,716684,175 -4363,716859,161 -4364,717020,182 -4365,717202,162 -4366,717364,173 -4367,717537,171 -4368,717708,171 -4369,717879,148 -4370,718027,139 -4371,718166,141 -4372,718307,203 -4373,718510,183 -4374,718693,149 -4375,718842,113 -4376,718955,186 -4377,719141,150 -4378,719291,147 -4379,719438,204 -4380,719642,165 -4381,719807,180 -4382,719987,239 -4383,720226,146 -4384,720372,170 -4385,720542,170 -4386,720712,183 -4387,720895,158 -4388,721053,120 -4389,721173,168 -4390,721341,140 -4391,721481,128 -4392,721609,125 -4393,721734,157 -4394,721891,127 -4395,722018,131 -4396,722149,128 -4397,722277,177 -4398,722454,138 -4399,722592,167 -4400,722759,222 -4401,722981,182 -4402,723163,172 -4403,723335,145 -4404,723480,154 -4405,723634,164 -4406,723798,173 -4407,723971,165 -4408,724136,137 -4409,724273,184 -4410,724457,172 -4411,724629,195 -4412,724824,137 -4413,724961,195 -4414,725156,155 -4415,725311,120 -4416,725431,140 -4417,725571,201 -4418,725772,171 -4419,725943,127 -4420,726070,171 -4421,726241,161 -4422,726402,147 -4423,726549,168 -4424,726717,158 -4425,726875,133 -4426,727008,204 -4427,727212,161 -4428,727373,167 -4429,727540,172 -4430,727712,152 -4431,727864,172 -4432,728036,156 -4433,728192,128 -4434,728320,151 -4435,728471,152 -4436,728623,203 -4437,728826,150 -4438,728976,167 -4439,729143,161 -4440,729304,150 -4441,729454,157 -4442,729611,144 -4443,729755,218 -4444,729973,170 -4445,730143,170 -4446,730313,170 -4447,730483,204 -4448,730687,186 -4449,730873,155 -4450,731028,157 -4451,731185,179 -4452,731364,188 -4453,731552,138 -4454,731690,193 -4455,731883,232 -4456,732115,136 -4457,732251,157 -4458,732408,158 -4459,732566,230 -4460,732796,183 -4461,732979,159 -4462,733138,165 -4463,733303,184 -4464,733487,126 -4465,733613,210 -4466,733823,191 -4467,734014,152 -4468,734166,163 -4469,734329,156 -4470,734485,180 -4471,734665,162 -4472,734827,174 -4473,735001,221 -4474,735222,198 -4475,735420,154 -4476,735574,115 -4477,735689,164 -4478,735853,186 -4479,736039,212 -4480,736251,147 -4481,736398,201 -4482,736599,168 -4483,736767,142 -4484,736909,156 -4485,737065,181 -4486,737246,150 -4487,737396,155 -4488,737551,130 -4489,737681,134 -4490,737815,217 -4491,738032,199 -4492,738231,192 -4493,738423,184 -4494,738607,175 -4495,738782,173 -4496,738955,173 -4497,739128,186 -4498,739314,170 -4499,739484,170 -4500,739654,201 -4501,739855,181 -4502,740036,174 -4503,740210,212 -4504,740422,201 -4505,740623,138 -4506,740761,129 -4507,740890,176 -4508,741066,146 -4509,741212,193 -4510,741405,168 -4511,741573,138 -4512,741711,169 -4513,741880,193 -4514,742073,174 -4515,742247,195 -4516,742442,201 -4517,742643,182 -4518,742825,140 -4519,742965,184 -4520,743149,166 -4521,743315,194 -4522,743509,202 -4523,743711,202 -4524,743913,155 -4525,744068,159 -4526,744227,147 -4527,744374,170 -4528,744544,150 -4529,744694,199 -4530,744893,188 -4531,745081,160 -4532,745241,139 -4533,745380,241 -4534,745621,183 -4535,745804,133 -4536,745937,182 -4537,746119,155 -4538,746274,150 -4539,746424,170 -4540,746594,170 -4541,746764,170 -4542,746934,174 -4543,747108,134 -4544,747242,191 -4545,747433,157 -4546,747590,210 -4547,747800,211 -4548,748011,213 -4549,748224,158 -4550,748382,159 -4551,748541,169 -4552,748710,170 -4553,748880,140 -4554,749020,176 -4555,749196,121 -4556,749317,200 -4557,749517,146 -4558,749663,176 -4559,749839,153 -4560,749992,131 -4561,750123,153 -4562,750276,168 -4563,750444,162 -4564,750606,152 -4565,750758,335 -4566,751093,136 -4567,751229,142 -4568,751371,167 -4569,751538,118 -4570,751656,198 -4571,751854,164 -4572,752018,128 -4573,752146,191 -4574,752337,159 -4575,752496,146 -4576,752642,179 -4577,752821,156 -4578,752977,197 -4579,753174,145 -4580,753319,152 -4581,753471,206 -4582,753677,179 -4583,753856,195 -4584,754051,117 -4585,754168,181 -4586,754349,152 -4587,754501,158 -4588,754659,142 -4589,754801,161 -4590,754962,134 -4591,755096,158 -4592,755254,179 -4593,755433,162 -4594,755595,203 -4595,755798,167 -4596,755965,169 -4597,756134,178 -4598,756312,212 -4599,756524,205 -4600,756729,134 -4601,756863,150 -4602,757013,153 -4603,757166,180 -4604,757346,188 -4605,757534,129 -4606,757663,201 -4607,757864,218 -4608,758082,170 -4609,758252,170 -4610,758422,210 -4611,758632,152 -4612,758784,145 -4613,758929,192 -4614,759121,152 -4615,759273,208 -4616,759481,161 -4617,759642,119 -4618,759761,171 -4619,759932,185 -4620,760117,157 -4621,760274,234 -4622,760508,150 -4623,760658,142 -4624,760800,153 -4625,760953,179 -4626,761132,143 -4627,761275,128 -4628,761403,151 -4629,761554,170 -4630,761724,181 -4631,761905,142 -4632,762047,171 -4633,762218,190 -4634,762408,169 -4635,762577,147 -4636,762724,125 -4637,762849,167 -4638,763016,162 -4639,763178,137 -4640,763315,137 -4641,763452,158 -4642,763610,177 -4643,763787,129 -4644,763916,146 -4645,764062,147 -4646,764209,183 -4647,764392,173 -4648,764565,134 -4649,764699,222 -4650,764921,196 -4651,765117,155 -4652,765272,149 -4653,765421,155 -4654,765576,177 -4655,765753,178 -4656,765931,239 -4657,766170,182 -4658,766352,164 -4659,766516,165 -4660,766681,129 -4661,766810,149 -4662,766959,149 -4663,767108,160 -4664,767268,194 -4665,767462,177 -4666,767639,204 -4667,767843,129 -4668,767972,160 -4669,768132,198 -4670,768330,196 -4671,768526,127 -4672,768653,170 -4673,768823,188 -4674,769011,143 -4675,769154,170 -4676,769324,170 -4677,769494,171 -4678,769665,186 -4679,769851,185 -4680,770036,159 -4681,770195,143 -4682,770338,170 -4683,770508,164 -4684,770672,167 -4685,770839,126 -4686,770965,185 -4687,771150,161 -4688,771311,181 -4689,771492,112 -4690,771604,169 -4691,771773,121 -4692,771894,215 -4693,772109,179 -4694,772288,168 -4695,772456,229 -4696,772685,137 -4697,772822,170 -4698,772992,165 -4699,773157,190 -4700,773347,170 -4701,773517,196 -4702,773713,113 -4703,773826,171 -4704,773997,158 -4705,774155,151 -4706,774306,138 -4707,774444,168 -4708,774612,151 -4709,774763,166 -4710,774929,171 -4711,775100,156 -4712,775256,135 -4713,775391,182 -4714,775573,175 -4715,775748,198 -4716,775946,124 -4717,776070,182 -4718,776252,183 -4719,776435,204 -4720,776639,159 -4721,776798,159 -4722,776957,140 -4723,777097,136 -4724,777233,129 -4725,777362,157 -4726,777519,173 -4727,777692,199 -4728,777891,155 -4729,778046,181 -4730,778227,173 -4731,778400,201 -4732,778601,131 -4733,778732,144 -4734,778876,184 -4735,779060,170 -4736,779230,170 -4737,779400,165 -4738,779565,140 -4739,779705,150 -4740,779855,119 -4741,779974,196 -4742,780170,152 -4743,780322,209 -4744,780531,137 -4745,780668,179 -4746,780847,147 -4747,780994,156 -4748,781150,149 -4749,781299,148 -4750,781447,125 -4751,781572,114 -4752,781686,175 -4753,781861,154 -4754,782015,150 -4755,782165,140 -4756,782305,210 -4757,782515,142 -4758,782657,116 -4759,782773,147 -4760,782920,226 -4761,783146,179 -4762,783325,152 -4763,783477,183 -4764,783660,157 -4765,783817,229 -4766,784046,229 -4767,784275,139 -4768,784414,191 -4769,784605,211 -4770,784816,120 -4771,784936,175 -4772,785111,152 -4773,785263,144 -4774,785407,154 -4775,785561,159 -4776,785720,130 -4777,785850,182 -4778,786032,131 -4779,786163,142 -4780,786305,190 -4781,786495,137 -4782,786632,163 -4783,786795,153 -4784,786948,166 -4785,787114,168 -4786,787282,135 -4787,787417,210 -4788,787627,147 -4789,787774,136 -4790,787910,191 -4791,788101,130 -4792,788231,137 -4793,788368,220 -4794,788588,149 -4795,788737,233 -4796,788970,145 -4797,789115,212 -4798,789327,168 -4799,789495,222 -4800,789717,153 -4801,789870,167 -4802,790037,211 -4803,790248,144 -4804,790392,154 -4805,790546,218 -4806,790764,157 -4807,790921,205 -4808,791126,157 -4809,791283,147 -4810,791430,137 -4811,791567,147 -4812,791714,175 -4813,791889,117 -4814,792006,184 -4815,792190,212 -4816,792402,161 -4817,792563,168 -4818,792731,159 -4819,792890,168 -4820,793058,180 -4821,793238,168 -4822,793406,175 -4823,793581,159 -4824,793740,215 -4825,793955,170 -4826,794125,170 -4827,794295,189 -4828,794484,179 -4829,794663,234 -4830,794897,157 -4831,795054,153 -4832,795207,132 -4833,795339,155 -4834,795494,183 -4835,795677,141 -4836,795818,189 -4837,796007,148 -4838,796155,187 -4839,796342,232 -4840,796574,133 -4841,796707,165 -4842,796872,127 -4843,796999,144 -4844,797143,147 -4845,797290,167 -4846,797457,176 -4847,797633,139 -4848,797772,166 -4849,797938,122 -4850,798060,178 -4851,798238,133 -4852,798371,192 -4853,798563,215 -4854,798778,139 -4855,798917,257 -4856,799174,160 -4857,799334,157 -4858,799491,151 -4859,799642,181 -4860,799823,198 -4861,800021,141 -4862,800162,263 -4863,800425,158 -4864,800583,157 -4865,800740,136 -4866,800876,166 -4867,801042,126 -4868,801168,191 -4869,801359,129 -4870,801488,157 -4871,801645,178 -4872,801823,149 -4873,801972,176 -4874,802148,132 -4875,802280,137 -4876,802417,182 -4877,802599,135 -4878,802734,216 -4879,802950,205 -4880,803155,138 -4881,803293,165 -4882,803458,156 -4883,803614,189 -4884,803803,171 -4885,803974,178 -4886,804152,189 -4887,804341,149 -4888,804490,246 -4889,804736,170 -4890,804906,170 -4891,805076,195 -4892,805271,152 -4893,805423,166 -4894,805589,175 -4895,805764,144 -4896,805908,166 -4897,806074,175 -4898,806249,165 -4899,806414,159 -4900,806573,170 -4901,806743,164 -4902,806907,163 -4903,807070,155 -4904,807225,162 -4905,807387,192 -4906,807579,175 -4907,807754,153 -4908,807907,147 -4909,808054,185 -4910,808239,174 -4911,808413,176 -4912,808589,158 -4913,808747,132 -4914,808879,245 -4915,809124,184 -4916,809308,141 -4917,809449,152 -4918,809601,214 -4919,809815,190 -4920,810005,127 -4921,810132,155 -4922,810287,148 -4923,810435,211 -4924,810646,168 -4925,810814,174 -4926,810988,151 -4927,811139,170 -4928,811309,133 -4929,811442,215 -4930,811657,145 -4931,811802,210 -4932,812012,165 -4933,812177,158 -4934,812335,174 -4935,812509,156 -4936,812665,222 -4937,812887,204 -4938,813091,126 -4939,813217,176 -4940,813393,203 -4941,813596,130 -4942,813726,185 -4943,813911,193 -4944,814104,171 -4945,814275,158 -4946,814433,136 -4947,814569,162 -4948,814731,170 -4949,814901,186 -4950,815087,145 -4951,815232,252 -4952,815484,164 -4953,815648,170 -4954,815818,190 -4955,816008,154 -4956,816162,175 -4957,816337,166 -4958,816503,123 -4959,816626,170 -4960,816796,170 -4961,816966,187 -4962,817153,204 -4963,817357,154 -4964,817511,190 -4965,817701,132 -4966,817833,164 -4967,817997,182 -4968,818179,130 -4969,818309,186 -4970,818495,154 -4971,818649,154 -4972,818803,125 -4973,818928,140 -4974,819068,176 -4975,819244,165 -4976,819409,138 -4977,819547,147 -4978,819694,127 -4979,819821,222 -4980,820043,179 -4981,820222,171 -4982,820393,144 -4983,820537,225 -4984,820762,177 -4985,820939,223 -4986,821162,188 -4987,821350,183 -4988,821533,180 -4989,821713,142 -4990,821855,171 -4991,822026,170 -4992,822196,170 -4993,822366,171 -4994,822537,181 -4995,822718,258 -4996,822976,168 -4997,823144,193 -4998,823337,155 -4999,823492,143 -5000,823635,158 -5001,823793,181 -5002,823974,217 -5003,824191,168 -5004,824359,179 -5005,824538,148 -5006,824686,143 -5007,824829,192 -5008,825021,192 -5009,825213,173 -5010,825386,160 -5011,825546,180 -5012,825726,200 -5013,825926,127 -5014,826053,171 -5015,826224,152 -5016,826376,177 -5017,826553,144 -5018,826697,169 -5019,826866,134 -5020,827000,186 -5021,827186,177 -5022,827363,169 -5023,827532,187 -5024,827719,151 -5025,827870,153 -5026,828023,148 -5027,828171,156 -5028,828327,149 -5029,828476,162 -5030,828638,116 -5031,828754,162 -5032,828916,172 -5033,829088,166 -5034,829254,159 -5035,829413,144 -5036,829557,211 -5037,829768,161 -5038,829929,167 -5039,830096,164 -5040,830260,135 -5041,830395,203 -5042,830598,170 -5043,830768,244 -5044,831012,143 -5045,831155,145 -5046,831300,162 -5047,831462,137 -5048,831599,209 -5049,831808,111 -5050,831919,163 -5051,832082,171 -5052,832253,163 -5053,832416,155 -5054,832571,158 -5055,832729,186 -5056,832915,175 -5057,833090,167 -5058,833257,156 -5059,833413,170 -5060,833583,170 -5061,833753,193 -5062,833946,154 -5063,834100,139 -5064,834239,137 -5065,834376,216 -5066,834592,138 -5067,834730,144 -5068,834874,158 -5069,835032,160 -5070,835192,160 -5071,835352,168 -5072,835520,140 -5073,835660,131 -5074,835791,152 -5075,835943,203 -5076,836146,192 -5077,836338,143 -5078,836481,171 -5079,836652,166 -5080,836818,157 -5081,836975,181 -5082,837156,159 -5083,837315,157 -5084,837472,147 -5085,837619,157 -5086,837776,148 -5087,837924,145 -5088,838069,185 -5089,838254,118 -5090,838372,173 -5091,838545,189 -5092,838734,183 -5093,838917,167 -5094,839084,134 -5095,839218,149 -5096,839367,160 -5097,839527,137 -5098,839664,123 -5099,839787,170 -5100,839957,185 -5101,840142,154 -5102,840296,141 -5103,840437,200 -5104,840637,169 -5105,840806,220 -5106,841026,126 -5107,841152,198 -5108,841350,188 -5109,841538,161 -5110,841699,124 -5111,841823,136 -5112,841959,192 -5113,842151,147 -5114,842298,182 -5115,842480,152 -5116,842632,151 -5117,842783,138 -5118,842921,203 -5119,843124,157 -5120,843281,202 -5121,843483,208 -5122,843691,129 -5123,843820,143 -5124,843963,147 -5125,844110,204 -5126,844314,125 -5127,844439,185 -5128,844624,160 -5129,844784,173 -5130,844957,194 -5131,845151,221 -5132,845372,196 -5133,845568,132 -5134,845700,132 -5135,845832,240 -5136,846072,166 -5137,846238,182 -5138,846420,142 -5139,846562,236 -5140,846798,174 -5141,846972,161 -5142,847133,151 -5143,847284,179 -5144,847463,162 -5145,847625,125 -5146,847750,144 -5147,847894,170 -5148,848064,170 -5149,848234,138 -5150,848372,152 -5151,848524,231 -5152,848755,210 -5153,848965,215 -5154,849180,127 -5155,849307,153 -5156,849460,193 -5157,849653,167 -5158,849820,156 -5159,849976,132 -5160,850108,137 -5161,850245,197 -5162,850442,219 -5163,850661,200 -5164,850861,174 -5165,851035,124 -5166,851159,140 -5167,851299,154 -5168,851453,170 -5169,851623,151 -5170,851774,178 -5171,851952,198 -5172,852150,142 -5173,852292,184 -5174,852476,144 -5175,852620,161 -5176,852781,181 -5177,852962,189 -5178,853151,155 -5179,853306,149 -5180,853455,177 -5181,853632,159 -5182,853791,169 -5183,853960,208 -5184,854168,162 -5185,854330,229 -5186,854559,144 -5187,854703,167 -5188,854870,143 -5189,855013,166 -5190,855179,162 -5191,855341,217 -5192,855558,209 -5193,855767,181 -5194,855948,213 -5195,856161,147 -5196,856308,165 -5197,856473,154 -5198,856627,128 -5199,856755,174 -5200,856929,175 -5201,857104,120 -5202,857224,152 -5203,857376,216 -5204,857592,151 -5205,857743,181 -5206,857924,141 -5207,858065,116 -5208,858181,133 -5209,858314,198 -5210,858512,151 -5211,858663,145 -5212,858808,149 -5213,858957,162 -5214,859119,170 -5215,859289,168 -5216,859457,163 -5217,859620,150 -5218,859770,190 -5219,859960,123 -5220,860083,138 -5221,860221,127 -5222,860348,148 -5223,860496,157 -5224,860653,182 -5225,860835,170 -5226,861005,170 -5227,861175,142 -5228,861317,147 -5229,861464,145 -5230,861609,151 -5231,861760,139 -5232,861899,156 -5233,862055,214 -5234,862269,223 -5235,862492,127 -5236,862619,144 -5237,862763,153 -5238,862916,197 -5239,863113,128 -5240,863241,226 -5241,863467,174 -5242,863641,148 -5243,863789,140 -5244,863929,182 -5245,864111,181 -5246,864292,147 -5247,864439,160 -5248,864599,210 -5249,864809,132 -5250,864941,148 -5251,865089,151 -5252,865240,197 -5253,865437,147 -5254,865584,176 -5255,865760,172 -5256,865932,125 -5257,866057,158 -5258,866215,147 -5259,866362,174 -5260,866536,159 -5261,866695,178 -5262,866873,149 -5263,867022,188 -5264,867210,148 -5265,867358,207 -5266,867565,206 -5267,867771,155 -5268,867926,118 -5269,868044,139 -5270,868183,148 -5271,868331,225 -5272,868556,205 -5273,868761,154 -5274,868915,147 -5275,869062,185 -5276,869247,127 -5277,869374,152 -5278,869526,189 -5279,869715,187 -5280,869902,162 -5281,870064,206 -5282,870270,187 -5283,870457,145 -5284,870602,219 -5285,870821,207 -5286,871028,165 -5287,871193,136 -5288,871329,170 -5289,871499,170 -5290,871669,140 -5291,871809,209 -5292,872018,145 -5293,872163,180 -5294,872343,187 -5295,872530,155 -5296,872685,163 -5297,872848,184 -5298,873032,186 -5299,873218,163 -5300,873381,201 -5301,873582,150 -5302,873732,173 -5303,873905,184 -5304,874089,132 -5305,874221,157 -5306,874378,176 -5307,874554,174 -5308,874728,211 -5309,874939,145 -5310,875084,218 -5311,875302,140 -5312,875442,180 -5313,875622,171 -5314,875793,173 -5315,875966,159 -5316,876125,204 -5317,876329,167 -5318,876496,155 -5319,876651,132 -5320,876783,172 -5321,876955,185 -5322,877140,185 -5323,877325,179 -5324,877504,139 -5325,877643,199 -5326,877842,163 -5327,878005,143 -5328,878148,141 -5329,878289,131 -5330,878420,175 -5331,878595,145 -5332,878740,171 -5333,878911,304 -5334,879215,215 -5335,879430,197 -5336,879627,124 -5337,879751,165 -5338,879916,210 -5339,880126,165 -5340,880291,203 -5341,880494,155 -5342,880649,152 -5343,880801,163 -5344,880964,165 -5345,881129,141 -5346,881270,154 -5347,881424,141 -5348,881565,139 -5349,881704,168 -5350,881872,150 -5351,882022,169 -5352,882191,147 -5353,882338,191 -5354,882529,210 -5355,882739,166 -5356,882905,166 -5357,883071,157 -5358,883228,186 -5359,883414,162 -5360,883576,163 -5361,883739,170 -5362,883909,170 -5363,884079,161 -5364,884240,163 -5365,884403,160 -5366,884563,162 -5367,884725,166 -5368,884891,172 -5369,885063,141 -5370,885204,142 -5371,885346,154 -5372,885500,154 -5373,885654,198 -5374,885852,186 -5375,886038,165 -5376,886203,166 -5377,886369,120 -5378,886489,117 -5379,886606,146 -5380,886752,177 -5381,886929,165 -5382,887094,142 -5383,887236,190 -5384,887426,210 -5385,887636,207 -5386,887843,152 -5387,887995,207 -5388,888202,113 -5389,888315,166 -5390,888481,222 -5391,888703,167 -5392,888870,181 -5393,889051,149 -5394,889200,188 -5395,889388,105 -5396,889493,196 -5397,889689,138 -5398,889827,191 -5399,890018,166 -5400,890184,228 -5401,890412,164 -5402,890576,171 -5403,890747,150 -5404,890897,189 -5405,891086,224 -5406,891310,252 -5407,891562,241 -5408,891803,123 -5409,891926,126 -5410,892052,137 -5411,892189,179 -5412,892368,139 -5413,892507,169 -5414,892676,162 -5415,892838,141 -5416,892979,202 -5417,893181,201 -5418,893382,124 -5419,893506,170 -5420,893676,170 -5421,893846,155 -5422,894001,163 -5423,894164,147 -5424,894311,141 -5425,894452,158 -5426,894610,171 -5427,894781,165 -5428,894946,219 -5429,895165,114 -5430,895279,209 -5431,895488,161 -5432,895649,147 -5433,895796,158 -5434,895954,220 -5435,896174,186 -5436,896360,225 -5437,896585,194 -5438,896779,130 -5439,896909,168 -5440,897077,132 -5441,897209,193 -5442,897402,150 -5443,897552,186 -5444,897738,129 -5445,897867,181 -5446,898048,201 -5447,898249,179 -5448,898428,163 -5449,898591,189 -5450,898780,220 -5451,899000,215 -5452,899215,157 -5453,899372,180 -5454,899552,131 -5455,899683,189 -5456,899872,201 -5457,900073,181 -5458,900254,153 -5459,900407,146 -5460,900553,142 -5461,900695,132 -5462,900827,163 -5463,900990,116 -5464,901106,190 -5465,901296,172 -5466,901468,194 -5467,901662,185 -5468,901847,137 -5469,901984,157 -5470,902141,136 -5471,902277,143 -5472,902420,181 -5473,902601,166 -5474,902767,170 -5475,902937,170 -5476,903107,188 -5477,903295,225 -5478,903520,204 -5479,903724,133 -5480,903857,150 -5481,904007,137 -5482,904144,232 -5483,904376,168 -5484,904544,191 -5485,904735,157 -5486,904892,199 -5487,905091,168 -5488,905259,173 -5489,905432,142 -5490,905574,158 -5491,905732,193 -5492,905925,167 -5493,906092,168 -5494,906260,192 -5495,906452,153 -5496,906605,167 -5497,906772,169 -5498,906941,127 -5499,907068,175 -5500,907243,162 -5501,907405,180 -5502,907585,176 -5503,907761,247 -5504,908008,187 -5505,908195,161 -5506,908356,156 -5507,908512,150 -5508,908662,156 -5509,908818,208 -5510,909026,226 -5511,909252,166 -5512,909418,208 -5513,909626,193 -5514,909819,198 -5515,910017,169 -5516,910186,118 -5517,910304,139 -5518,910443,165 -5519,910608,208 -5520,910816,149 -5521,910965,129 -5522,911094,197 -5523,911291,170 -5524,911461,203 -5525,911664,169 -5526,911833,165 -5527,911998,174 -5528,912172,122 -5529,912294,191 -5530,912485,147 -5531,912632,132 -5532,912764,183 -5533,912947,131 -5534,913078,219 -5535,913297,138 -5536,913435,138 -5537,913573,134 -5538,913707,165 -5539,913872,165 -5540,914037,165 -5541,914202,174 -5542,914376,213 -5543,914589,123 -5544,914712,147 -5545,914859,185 -5546,915044,198 -5547,915242,151 -5548,915393,141 -5549,915534,163 -5550,915697,155 -5551,915852,189 -5552,916041,184 -5553,916225,143 -5554,916368,190 -5555,916558,121 -5556,916679,164 -5557,916843,163 -5558,917006,163 -5559,917169,115 -5560,917284,113 -5561,917397,188 -5562,917585,126 -5563,917711,152 -5564,917863,119 -5565,917982,196 -5566,918178,128 -5567,918306,136 -5568,918442,219 -5569,918661,186 -5570,918847,124 -5571,918971,139 -5572,919110,181 -5573,919291,127 -5574,919418,170 -5575,919588,170 -5576,919758,123 -5577,919881,158 -5578,920039,153 -5579,920192,189 -5580,920381,168 -5581,920549,199 -5582,920748,165 -5583,920913,165 -5584,921078,165 -5585,921243,147 -5586,921390,172 -5587,921562,199 -5588,921761,122 -5589,921883,130 -5590,922013,129 -5591,922142,174 -5592,922316,151 -5593,922467,135 -5594,922602,133 -5595,922735,148 -5596,922883,168 -5597,923051,214 -5598,923265,140 -5599,923405,131 -5600,923536,117 -5601,923653,158 -5602,923811,152 -5603,923963,186 -5604,924149,149 -5605,924298,183 -5606,924481,193 -5607,924674,142 -5608,924816,132 -5609,924948,174 -5610,925122,171 -5611,925293,201 -5612,925494,148 -5613,925642,164 -5614,925806,166 -5615,925972,157 -5616,926129,133 -5617,926262,216 -5618,926478,188 -5619,926666,126 -5620,926792,125 -5621,926917,164 -5622,927081,192 -5623,927273,182 -5624,927455,204 -5625,927659,170 -5626,927829,170 -5627,927999,188 -5628,928187,141 -5629,928328,183 -5630,928511,150 -5631,928661,179 -5632,928840,180 -5633,929020,164 -5634,929184,220 -5635,929404,166 -5636,929570,138 -5637,929708,168 -5638,929876,153 -5639,930029,159 -5640,930188,194 -5641,930382,212 -5642,930594,142 -5643,930736,144 -5644,930880,183 -5645,931063,164 -5646,931227,177 -5647,931404,147 -5648,931551,150 -5649,931701,132 -5650,931833,170 -5651,932003,186 -5652,932189,151 -5653,932340,163 -5654,932503,211 -5655,932714,141 -5656,932855,170 -5657,933025,168 -5658,933193,128 -5659,933321,164 -5660,933485,122 -5661,933607,199 -5662,933806,140 -5663,933946,180 -5664,934126,176 -5665,934302,134 -5666,934436,149 -5667,934585,138 -5668,934723,148 -5669,934871,149 -5670,935020,147 -5671,935167,174 -5672,935341,229 -5673,935570,134 -5674,935704,178 -5675,935882,164 -5676,936046,127 -5677,936173,198 -5678,936371,228 -5679,936599,132 -5680,936731,164 -5681,936895,191 -5682,937086,198 -5683,937284,182 -5684,937466,173 -5685,937639,181 -5686,937820,184 -5687,938004,124 -5688,938128,175 -5689,938303,175 -5690,938478,182 -5691,938660,173 -5692,938833,143 -5693,938976,215 -5694,939191,152 -5695,939343,190 -5696,939533,214 -5697,939747,238 -5698,939985,144 -5699,940129,161 -5700,940290,184 -5701,940474,158 -5702,940632,170 -5703,940802,170 -5704,940972,153 -5705,941125,150 -5706,941275,207 -5707,941482,158 -5708,941640,189 -5709,941829,187 -5710,942016,138 -5711,942154,197 -5712,942351,178 -5713,942529,144 -5714,942673,192 -5715,942865,178 -5716,943043,196 -5717,943239,190 -5718,943429,161 -5719,943590,145 -5720,943735,203 -5721,943938,136 -5722,944074,153 -5723,944227,144 -5724,944371,154 -5725,944525,161 -5726,944686,154 -5727,944840,162 -5728,945002,132 -5729,945134,202 -5730,945336,188 -5731,945524,179 -5732,945703,123 -5733,945826,146 -5734,945972,220 -5735,946192,191 -5736,946383,162 -5737,946545,159 -5738,946704,137 -5739,946841,179 -5740,947020,233 -5741,947253,262 -5742,947515,145 -5743,947660,166 -5744,947826,183 -5745,948009,188 -5746,948197,190 -5747,948387,147 -5748,948534,177 -5749,948711,147 -5750,948858,166 -5751,949024,145 -5752,949169,230 -5753,949399,162 -5754,949561,198 -5755,949759,130 -5756,949889,182 -5757,950071,191 -5758,950262,151 -5759,950413,150 -5760,950563,151 -5761,950714,169 -5762,950883,151 -5763,951034,197 -5764,951231,159 -5765,951390,118 -5766,951508,143 -5767,951651,151 -5768,951802,152 -5769,951954,191 -5770,952145,149 -5771,952294,149 -5772,952443,121 -5773,952564,183 -5774,952747,180 -5775,952927,151 -5776,953078,182 -5777,953260,133 -5778,953393,182 -5779,953575,219 -5780,953794,169 -5781,953963,209 -5782,954172,208 -5783,954380,142 -5784,954522,194 -5785,954716,189 -5786,954905,136 -5787,955041,150 -5788,955191,170 -5789,955361,170 -5790,955531,176 -5791,955707,219 -5792,955926,136 -5793,956062,142 -5794,956204,156 -5795,956360,205 -5796,956565,144 -5797,956709,134 -5798,956843,167 -5799,957010,128 -5800,957138,157 -5801,957295,142 -5802,957437,165 -5803,957602,128 -5804,957730,169 -5805,957899,177 -5806,958076,115 -5807,958191,242 -5808,958433,171 -5809,958604,139 -5810,958743,157 -5811,958900,172 -5812,959072,55 -5813,959127,147 -5814,959274,128 -5815,959402,159 -5816,959561,173 -5817,959734,164 -5818,959898,130 -5819,960028,223 -5820,960251,138 -5821,960389,177 -5822,960566,177 -5823,960743,148 -5824,960891,153 -5825,961044,149 -5826,961193,162 -5827,961355,138 -5828,961493,150 -5829,961643,253 -5830,961896,159 -5831,962055,170 -5832,962225,170 -5833,962395,144 -5834,962539,132 -5835,962671,120 -5836,962791,181 -5837,962972,155 -5838,963127,197 -5839,963324,197 -5840,963521,155 -5841,963676,124 -5842,963800,125 -5843,963925,185 -5844,964110,190 -5845,964300,195 -5846,964495,156 -5847,964651,142 -5848,964793,121 -5849,964914,156 -5850,965070,212 -5851,965282,185 -5852,965467,114 -5853,965581,165 -5854,965746,127 -5855,965873,128 -5856,966001,182 -5857,966183,147 -5858,966330,170 -5859,966500,177 -5860,966677,203 -5861,966880,198 -5862,967078,171 -5863,967249,168 -5864,967417,151 -5865,967568,142 -5866,967710,166 -5867,967876,166 -5868,968042,223 -5869,968265,190 -5870,968455,188 -5871,968643,148 -5872,968791,117 -5873,968908,144 -5874,969052,202 -5875,969254,193 -5876,969447,203 -5877,969650,207 -5878,969857,159 -5879,970016,187 -5880,970203,185 -5881,970388,144 -5882,970532,134 -5883,970666,170 -5884,970836,135 -5885,970971,179 -5886,971150,166 -5887,971316,184 -5888,971500,147 -5889,971647,153 -5890,971800,176 -5891,971976,178 -5892,972154,174 -5893,972328,145 -5894,972473,252 -5895,972725,142 -5896,972867,162 -5897,973029,153 -5898,973182,202 -5899,973384,196 -5900,973580,123 -5901,973703,149 -5902,973852,170 -5903,974022,170 -5904,974192,176 -5905,974368,158 -5906,974526,159 -5907,974685,181 -5908,974866,160 -5909,975026,149 -5910,975175,169 -5911,975344,162 -5912,975506,144 -5913,975650,153 -5914,975803,148 -5915,975951,179 -5916,976130,154 -5917,976284,125 -5918,976409,163 -5919,976572,150 -5920,976722,185 -5921,976907,124 -5922,977031,169 -5923,977200,180 -5924,977380,178 -5925,977558,157 -5926,977715,200 -5927,977915,165 -5928,978080,141 -5929,978221,169 -5930,978390,240 -5931,978630,183 -5932,978813,179 -5933,978992,194 -5934,979186,143 -5935,979329,156 -5936,979485,152 -5937,979637,188 -5938,979825,183 -5939,980008,141 -5940,980149,169 -5941,980318,55 -5942,980373,133 -5943,980506,164 -5944,980670,163 -5945,980833,213 -5946,981046,157 -5947,981203,156 -5948,981359,182 -5949,981541,131 -5950,981672,200 -5951,981872,154 -5952,982026,188 -5953,982214,121 -5954,982335,196 -5955,982531,114 -5956,982645,128 -5957,982773,176 -5958,982949,156 -5959,983105,125 -5960,983230,162 -5961,983392,188 -5962,983580,120 -5963,983700,138 -5964,983838,154 -5965,983992,173 -5966,984165,152 -5967,984317,181 -5968,984498,154 -5969,984652,175 -5970,984827,175 -5971,985002,169 -5972,985171,211 -5973,985382,138 -5974,985520,143 -5975,985663,187 -5976,985850,169 -5977,986019,170 -5978,986189,170 -5979,986359,172 -5980,986531,166 -5981,986697,164 -5982,986861,118 -5983,986979,217 -5984,987196,178 -5985,987374,55 -5986,987429,157 -5987,987586,146 -5988,987732,143 -5989,987875,135 -5990,988010,156 -5991,988166,112 -5992,988278,169 -5993,988447,151 -5994,988598,149 -5995,988747,150 -5996,988897,152 -5997,989049,149 -5998,989198,139 -5999,989337,268 -6000,989605,194 -6001,989799,183 -6002,989982,189 -6003,990171,232 -6004,990403,134 -6005,990537,174 -6006,990711,168 -6007,990879,179 -6008,991058,193 -6009,991251,122 -6010,991373,154 -6011,991527,165 -6012,991692,188 -6013,991880,194 -6014,992074,154 -6015,992228,149 -6016,992377,179 -6017,992556,171 -6018,992727,146 -6019,992873,153 -6020,993026,147 -6021,993173,189 -6022,993362,157 -6023,993519,163 -6024,993682,163 -6025,993845,189 -6026,994034,187 -6027,994221,188 -6028,994409,180 -6029,994589,157 -6030,994746,154 -6031,994900,219 -6032,995119,206 -6033,995325,132 -6034,995457,179 -6035,995636,162 -6036,995798,170 -6037,995968,170 -6038,996138,152 -6039,996290,148 -6040,996438,187 -6041,996625,163 -6042,996788,175 -6043,996963,196 -6044,997159,162 -6045,997321,181 -6046,997502,144 -6047,997646,131 -6048,997777,128 -6049,997905,160 -6050,998065,173 -6051,998238,118 -6052,998356,175 -6053,998531,201 -6054,998732,190 -6055,998922,189 -6056,999111,139 -6057,999250,131 -6058,999381,173 -6059,999554,161 -6060,999715,161 -6061,999876,169 -6062,1000045,170 -6063,1000215,115 -6064,1000330,138 -6065,1000468,189 -6066,1000657,179 -6067,1000836,172 -6068,1001008,179 -6069,1001187,184 -6070,1001371,124 -6071,1001495,194 -6072,1001689,196 -6073,1001885,128 -6074,1002013,193 -6075,1002206,174 -6076,1002380,184 -6077,1002564,162 -6078,1002726,154 -6079,1002880,194 -6080,1003074,174 -6081,1003248,204 -6082,1003452,133 -6083,1003585,213 -6084,1003798,192 -6085,1003990,130 -6086,1004120,189 -6087,1004309,158 -6088,1004467,183 -6089,1004650,196 -6090,1004846,163 -6091,1005009,166 -6092,1005175,149 -6093,1005324,192 -6094,1005516,138 -6095,1005654,136 -6096,1005790,192 -6097,1005982,135 -6098,1006117,151 -6099,1006268,163 -6100,1006431,176 -6101,1006607,185 -6102,1006792,184 -6103,1006976,188 -6104,1007164,164 -6105,1007328,145 -6106,1007473,152 -6107,1007625,200 -6108,1007825,196 -6109,1008021,162 -6110,1008183,154 -6111,1008337,170 -6112,1008507,170 -6113,1008677,210 -6114,1008887,147 -6115,1009034,153 -6116,1009187,153 -6117,1009340,153 -6118,1009493,153 -6119,1009646,153 -6120,1009799,153 -6121,1009952,153 -6122,1010105,153 -6123,1010258,153 -6124,1010411,153 -6125,1010564,188 -6126,1010752,147 -6127,1010899,138 -6128,1011037,258 -6129,1011295,173 -6130,1011468,120 -6131,1011588,150 -6132,1011738,175 -6133,1011913,163 -6134,1012076,147 -6135,1012223,175 -6136,1012398,205 -6137,1012603,130 -6138,1012733,180 -6139,1012913,130 -6140,1013043,187 -6141,1013230,175 -6142,1013405,158 -6143,1013563,149 -6144,1013712,172 -6145,1013884,165 -6146,1014049,195 -6147,1014244,190 -6148,1014434,211 -6149,1014645,274 -6150,1014919,159 -6151,1015078,152 -6152,1015230,145 -6153,1015375,134 -6154,1015509,143 -6155,1015652,184 -6156,1015836,160 -6157,1015996,191 -6158,1016187,140 -6159,1016327,143 -6160,1016470,175 -6161,1016645,194 -6162,1016839,265 -6163,1017104,173 -6164,1017277,164 -6165,1017441,191 -6166,1017632,184 -6167,1017816,169 -6168,1017985,170 -6169,1018155,170 -6170,1018325,206 -6171,1018531,172 -6172,1018703,187 -6173,1018890,180 -6174,1019070,173 -6175,1019243,206 -6176,1019449,145 -6177,1019594,154 -6178,1019748,171 -6179,1019919,173 -6180,1020092,190 -6181,1020282,55 -6182,1020337,122 -6183,1020459,184 -6184,1020643,173 -6185,1020816,140 -6186,1020956,173 -6187,1021129,139 -6188,1021268,190 -6189,1021458,124 -6190,1021582,155 -6191,1021737,153 -6192,1021890,153 -6193,1022043,153 -6194,1022196,153 -6195,1022349,153 -6196,1022502,153 -6197,1022655,139 -6198,1022794,171 -6199,1022965,179 -6200,1023144,215 -6201,1023359,136 -6202,1023495,150 -6203,1023645,180 -6204,1023825,183 -6205,1024008,200 -6206,1024208,146 -6207,1024354,137 -6208,1024491,164 -6209,1024655,162 -6210,1024817,140 -6211,1024957,148 -6212,1025105,189 -6213,1025294,146 -6214,1025440,124 -6215,1025564,152 -6216,1025716,148 -6217,1025864,179 -6218,1026043,149 -6219,1026192,175 -6220,1026367,145 -6221,1026512,147 -6222,1026659,198 -6223,1026857,181 -6224,1027038,125 -6225,1027163,142 -6226,1027305,198 -6227,1027503,158 -6228,1027661,146 -6229,1027807,163 -6230,1027970,138 -6231,1028108,154 -6232,1028262,135 -6233,1028397,165 -6234,1028562,157 -6235,1028719,158 -6236,1028877,142 -6237,1029019,260 -6238,1029279,136 -6239,1029415,146 -6240,1029561,228 -6241,1029789,136 -6242,1029925,145 -6243,1030070,198 -6244,1030268,168 -6245,1030436,241 -6246,1030677,140 -6247,1030817,154 -6248,1030971,191 -6249,1031162,142 -6250,1031304,220 -6251,1031524,214 -6252,1031738,138 -6253,1031876,210 -6254,1032086,183 -6255,1032269,204 -6256,1032473,170 -6257,1032643,175 -6258,1032818,171 -6259,1032989,170 -6260,1033159,170 -6261,1033329,176 -6262,1033505,161 -6263,1033666,119 -6264,1033785,144 -6265,1033929,110 -6266,1034039,130 -6267,1034169,165 -6268,1034334,146 -6269,1034480,157 -6270,1034637,140 -6271,1034777,131 -6272,1034908,172 -6273,1035080,203 -6274,1035283,206 -6275,1035489,181 -6276,1035670,161 -6277,1035831,163 -6278,1035994,187 -6279,1036181,133 -6280,1036314,123 -6281,1036437,166 -6282,1036603,161 -6283,1036764,127 -6284,1036891,207 -6285,1037098,135 -6286,1037233,128 -6287,1037361,174 -6288,1037535,133 -6289,1037668,235 -6290,1037903,163 -6291,1038066,236 -6292,1038302,178 -6293,1038480,191 -6294,1038671,187 -6295,1038858,200 -6296,1039058,231 -6297,1039289,266 -6298,1039555,198 -6299,1039753,148 -6300,1039901,148 -6301,1040049,148 -6302,1040197,138 -6303,1040335,174 -6304,1040509,155 -6305,1040664,158 -6306,1040822,143 -6307,1040965,183 -6308,1041148,147 -6309,1041295,203 -6310,1041498,162 -6311,1041660,155 -6312,1041815,181 -6313,1041996,192 -6314,1042188,183 -6315,1042371,195 -6316,1042566,218 -6317,1042784,163 -6318,1042947,185 -6319,1043132,185 -6320,1043317,135 -6321,1043452,138 -6322,1043590,121 -6323,1043711,198 -6324,1043909,179 -6325,1044088,141 -6326,1044229,137 -6327,1044366,148 -6328,1044514,160 -6329,1044674,170 -6330,1044844,170 -6331,1045014,159 -6332,1045173,156 -6333,1045329,251 -6334,1045580,183 -6335,1045763,213 -6336,1045976,147 -6337,1046123,183 -6338,1046306,145 -6339,1046451,217 -6340,1046668,170 -6341,1046838,135 -6342,1046973,173 -6343,1047146,159 -6344,1047305,147 -6345,1047452,190 -6346,1047642,136 -6347,1047778,199 -6348,1047977,121 -6349,1048098,194 -6350,1048292,181 -6351,1048473,157 -6352,1048630,174 -6353,1048804,179 -6354,1048983,161 -6355,1049144,132 -6356,1049276,184 -6357,1049460,171 -6358,1049631,123 -6359,1049754,184 -6360,1049938,196 -6361,1050134,171 -6362,1050305,141 -6363,1050446,156 -6364,1050602,174 -6365,1050776,166 -6366,1050942,166 -6367,1051108,152 -6368,1051260,166 -6369,1051426,169 -6370,1051595,187 -6371,1051782,162 -6372,1051944,159 -6373,1052103,141 -6374,1052244,153 -6375,1052397,182 -6376,1052579,183 -6377,1052762,167 -6378,1052929,149 -6379,1053078,167 -6380,1053245,183 -6381,1053428,217 -6382,1053645,195 -6383,1053840,187 -6384,1054027,180 -6385,1054207,174 -6386,1054381,244 -6387,1054625,161 -6388,1054786,180 -6389,1054966,286 -6390,1055252,160 -6391,1055412,143 -6392,1055555,142 -6393,1055697,153 -6394,1055850,192 -6395,1056042,176 -6396,1056218,157 -6397,1056375,206 -6398,1056581,175 -6399,1056756,133 -6400,1056889,192 -6401,1057081,189 -6402,1057270,179 -6403,1057449,153 -6404,1057602,177 -6405,1057779,148 -6406,1057927,170 -6407,1058097,170 -6408,1058267,165 -6409,1058432,132 -6410,1058564,131 -6411,1058695,179 -6412,1058874,165 -6413,1059039,182 -6414,1059221,186 -6415,1059407,163 -6416,1059570,190 -6417,1059760,284 -6418,1060044,182 -6419,1060226,201 -6420,1060427,168 -6421,1060595,175 -6422,1060770,133 -6423,1060903,158 -6424,1061061,152 -6425,1061213,150 -6426,1061363,156 -6427,1061519,150 -6428,1061669,157 -6429,1061826,161 -6430,1061987,198 -6431,1062185,210 -6432,1062395,148 -6433,1062543,203 -6434,1062746,179 -6435,1062925,166 -6436,1063091,157 -6437,1063248,174 -6438,1063422,184 -6439,1063606,123 -6440,1063729,183 -6441,1063912,215 -6442,1064127,154 -6443,1064281,151 -6444,1064432,147 -6445,1064579,138 -6446,1064717,160 -6447,1064877,170 -6448,1065047,170 -6449,1065217,131 -6450,1065348,177 -6451,1065525,150 -6452,1065675,214 -6453,1065889,170 -6454,1066059,200 -6455,1066259,133 -6456,1066392,205 -6457,1066597,167 -6458,1066764,164 -6459,1066928,187 -6460,1067115,183 -6461,1067298,168 -6462,1067466,137 -6463,1067603,260 -6464,1067863,144 -6465,1068007,159 -6466,1068166,198 -6467,1068364,140 -6468,1068504,161 -6469,1068665,160 -6470,1068825,213 -6471,1069038,207 -6472,1069245,157 -6473,1069402,194 -6474,1069596,136 -6475,1069732,134 -6476,1069866,238 -6477,1070104,180 -6478,1070284,219 -6479,1070503,138 -6480,1070641,147 -6481,1070788,146 -6482,1070934,180 -6483,1071114,193 -6484,1071307,172 -6485,1071479,170 -6486,1071649,170 -6487,1071819,154 -6488,1071973,174 -6489,1072147,166 -6490,1072313,163 -6491,1072476,178 -6492,1072654,170 -6493,1072824,235 -6494,1073059,147 -6495,1073206,177 -6496,1073383,191 -6497,1073574,167 -6498,1073741,153 -6499,1073894,180 -6500,1074074,137 -6501,1074211,205 -6502,1074416,202 -6503,1074618,167 -6504,1074785,212 -6505,1074997,135 -6506,1075132,119 -6507,1075251,158 -6508,1075409,221 -6509,1075630,194 -6510,1075824,186 -6511,1076010,147 -6512,1076157,187 -6513,1076344,237 -6514,1076581,184 -6515,1076765,153 -6516,1076918,185 -6517,1077103,205 -6518,1077308,158 -6519,1077466,164 -6520,1077630,150 -6521,1077780,138 -6522,1077918,124 -6523,1078042,164 -6524,1078206,163 -6525,1078369,194 -6526,1078563,194 -6527,1078757,156 -6528,1078913,156 -6529,1079069,143 -6530,1079212,147 -6531,1079359,174 -6532,1079533,153 -6533,1079686,152 -6534,1079838,172 -6535,1080010,219 -6536,1080229,146 -6537,1080375,173 -6538,1080548,180 -6539,1080728,178 -6540,1080906,119 -6541,1081025,144 -6542,1081169,117 -6543,1081286,137 -6544,1081423,185 -6545,1081608,164 -6546,1081772,141 -6547,1081913,229 -6548,1082142,198 -6549,1082340,193 -6550,1082533,193 -6551,1082726,168 -6552,1082894,158 -6553,1083052,175 -6554,1083227,133 -6555,1083360,207 -6556,1083567,173 -6557,1083740,122 -6558,1083862,107 -6559,1083969,113 -6560,1084082,177 -6561,1084259,167 -6562,1084426,207 -6563,1084633,199 -6564,1084832,219 -6565,1085051,175 -6566,1085226,147 -6567,1085373,120 -6568,1085493,172 -6569,1085665,170 -6570,1085835,170 -6571,1086005,182 -6572,1086187,217 -6573,1086404,155 -6574,1086559,164 -6575,1086723,191 -6576,1086914,196 -6577,1087110,147 -6578,1087257,177 -6579,1087434,164 -6580,1087598,124 -6581,1087722,138 -6582,1087860,148 -6583,1088008,138 -6584,1088146,141 -6585,1088287,138 -6586,1088425,171 -6587,1088596,175 -6588,1088771,176 -6589,1088947,170 -6590,1089117,231 -6591,1089348,182 -6592,1089530,147 -6593,1089677,164 -6594,1089841,159 -6595,1090000,153 -6596,1090153,174 -6597,1090327,186 -6598,1090513,199 -6599,1090712,184 -6600,1090896,148 -6601,1091044,150 -6602,1091194,171 -6603,1091365,228 -6604,1091593,138 -6605,1091731,239 -6606,1091970,173 -6607,1092143,145 -6608,1092288,147 -6609,1092435,166 -6610,1092601,166 -6611,1092767,139 -6612,1092906,155 -6613,1093061,144 -6614,1093205,191 -6615,1093396,199 -6616,1093595,183 -6617,1093778,137 -6618,1093915,234 -6619,1094149,186 -6620,1094335,180 -6621,1094515,141 -6622,1094656,149 -6623,1094805,148 -6624,1094953,228 -6625,1095181,135 -6626,1095316,148 -6627,1095464,120 -6628,1095584,137 -6629,1095721,170 -6630,1095891,149 -6631,1096040,170 -6632,1096210,170 -6633,1096380,211 -6634,1096591,204 -6635,1096795,159 -6636,1096954,179 -6637,1097133,150 -6638,1097283,189 -6639,1097472,264 -6640,1097736,178 -6641,1097914,236 -6642,1098150,161 -6643,1098311,136 -6644,1098447,145 -6645,1098592,191 -6646,1098783,162 -6647,1098945,159 -6648,1099104,184 -6649,1099288,127 -6650,1099415,213 -6651,1099628,134 -6652,1099762,210 -6653,1099972,161 -6654,1100133,189 -6655,1100322,147 -6656,1100469,144 -6657,1100613,157 -6658,1100770,159 -6659,1100929,193 -6660,1101122,170 -6661,1101292,128 -6662,1101420,152 -6663,1101572,141 -6664,1101713,148 -6665,1101861,195 -6666,1102056,164 -6667,1102220,191 -6668,1102411,165 -6669,1102576,183 -6670,1102759,219 -6671,1102978,177 -6672,1103155,196 -6673,1103351,146 -6674,1103497,120 -6675,1103617,150 -6676,1103767,182 -6677,1103949,137 -6678,1104086,138 -6679,1104224,169 -6680,1104393,186 -6681,1104579,170 -6682,1104749,201 -6683,1104950,147 -6684,1105097,178 -6685,1105275,167 -6686,1105442,139 -6687,1105581,173 -6688,1105754,179 -6689,1105933,139 -6690,1106072,156 -6691,1106228,136 -6692,1106364,182 -6693,1106546,125 -6694,1106671,141 -6695,1106812,165 -6696,1106977,199 -6697,1107176,212 -6698,1107388,226 -6699,1107614,204 -6700,1107818,166 -6701,1107984,141 -6702,1108125,149 -6703,1108274,170 -6704,1108444,170 -6705,1108614,153 -6706,1108767,142 -6707,1108909,158 -6708,1109067,165 -6709,1109232,132 -6710,1109364,167 -6711,1109531,142 -6712,1109673,146 -6713,1109819,135 -6714,1109954,172 -6715,1110126,178 -6716,1110304,162 -6717,1110466,182 -6718,1110648,162 -6719,1110810,143 -6720,1110953,180 -6721,1111133,168 -6722,1111301,228 -6723,1111529,175 -6724,1111704,175 -6725,1111879,151 -6726,1112030,219 -6727,1112249,161 -6728,1112410,170 -6729,1112580,168 -6730,1112748,161 -6731,1112909,175 -6732,1113084,162 -6733,1113246,166 -6734,1113412,142 -6735,1113554,113 -6736,1113667,207 -6737,1113874,160 -6738,1114034,160 -6739,1114194,145 -6740,1114339,201 -6741,1114540,201 -6742,1114741,204 -6743,1114945,159 -6744,1115104,200 -6745,1115304,132 -6746,1115436,238 -6747,1115674,159 -6748,1115833,161 -6749,1115994,156 -6750,1116150,199 -6751,1116349,133 -6752,1116482,212 -6753,1116694,152 -6754,1116846,169 -6755,1117015,158 -6756,1117173,170 -6757,1117343,130 -6758,1117473,147 -6759,1117620,212 -6760,1117832,196 -6761,1118028,187 -6762,1118215,172 -6763,1118387,244 -6764,1118631,170 -6765,1118801,170 -6766,1118971,153 -6767,1119124,141 -6768,1119265,152 -6769,1119417,191 -6770,1119608,204 -6771,1119812,205 -6772,1120017,189 -6773,1120206,173 -6774,1120379,214 -6775,1120593,147 -6776,1120740,149 -6777,1120889,167 -6778,1121056,212 -6779,1121268,150 -6780,1121418,168 -6781,1121586,184 -6782,1121770,181 -6783,1121951,183 -6784,1122134,165 -6785,1122299,136 -6786,1122435,212 -6787,1122647,167 -6788,1122814,159 -6789,1122973,162 -6790,1123135,160 -6791,1123295,223 -6792,1123518,212 -6793,1123730,138 -6794,1123868,185 -6795,1124053,217 -6796,1124270,165 -6797,1124435,152 -6798,1124587,187 -6799,1124774,135 -6800,1124909,301 -6801,1125210,173 -6802,1125383,161 -6803,1125544,152 -6804,1125696,142 -6805,1125838,206 -6806,1126044,119 -6807,1126163,200 -6808,1126363,215 -6809,1126578,235 -6810,1126813,249 -6811,1127062,146 -6812,1127208,169 -6813,1127377,188 -6814,1127565,200 -6815,1127765,123 -6816,1127888,139 -6817,1128027,170 -6818,1128197,170 -6819,1128367,126 -6820,1128493,169 -6821,1128662,150 -6822,1128812,224 -6823,1129036,147 -6824,1129183,199 -6825,1129382,237 -6826,1129619,139 -6827,1129758,143 -6828,1129901,124 -6829,1130025,147 -6830,1130172,159 -6831,1130331,209 -6832,1130540,216 -6833,1130756,241 -6834,1130997,170 -6835,1131167,185 -6836,1131352,164 -6837,1131516,209 -6838,1131725,148 -6839,1131873,161 -6840,1132034,163 -6841,1132197,123 -6842,1132320,188 -6843,1132508,217 -6844,1132725,162 -6845,1132887,139 -6846,1133026,150 -6847,1133176,162 -6848,1133338,221 -6849,1133559,182 -6850,1133741,128 -6851,1133869,180 -6852,1134049,137 -6853,1134186,188 -6854,1134374,153 -6855,1134527,158 -6856,1134685,248 -6857,1134933,175 -6858,1135108,167 -6859,1135275,190 -6860,1135465,222 -6861,1135687,167 -6862,1135854,173 -6863,1136027,160 -6864,1136187,155 -6865,1136342,177 -6866,1136519,199 -6867,1136718,111 -6868,1136829,192 -6869,1137021,195 -6870,1137216,208 -6871,1137424,182 -6872,1137606,132 -6873,1137738,233 -6874,1137971,160 -6875,1138131,147 -6876,1138278,138 -6877,1138416,164 -6878,1138580,147 -6879,1138727,184 -6880,1138911,205 -6881,1139116,160 -6882,1139276,170 -6883,1139446,170 -6884,1139616,185 -6885,1139801,172 -6886,1139973,224 -6887,1140197,151 -6888,1140348,164 -6889,1140512,161 -6890,1140673,192 -6891,1140865,174 -6892,1141039,196 -6893,1141235,134 -6894,1141369,153 -6895,1141522,197 -6896,1141719,147 -6897,1141866,140 -6898,1142006,157 -6899,1142163,187 -6900,1142350,168 -6901,1142518,198 -6902,1142716,169 -6903,1142885,144 -6904,1143029,157 -6905,1143186,173 -6906,1143359,173 -6907,1143532,145 -6908,1143677,158 -6909,1143835,146 -6910,1143981,136 -6911,1144117,162 -6912,1144279,149 -6913,1144428,174 -6914,1144602,155 -6915,1144757,221 -6916,1144978,166 -6917,1145144,126 -6918,1145270,176 -6919,1145446,146 -6920,1145592,130 -6921,1145722,161 -6922,1145883,219 -6923,1146102,140 -6924,1146242,170 -6925,1146412,170 -6926,1146582,180 -6927,1146762,127 -6928,1146889,221 -6929,1147110,178 -6930,1147288,185 -6931,1147473,175 -6932,1147648,212 -6933,1147860,154 -6934,1148014,157 -6935,1148171,154 -6936,1148325,173 -6937,1148498,173 -6938,1148671,173 -6939,1148844,180 -6940,1149024,133 -6941,1149157,204 -6942,1149361,182 -6943,1149543,194 -6944,1149737,151 -6945,1149888,166 -6946,1150054,218 -6947,1150272,163 -6948,1150435,189 -6949,1150624,135 -6950,1150759,167 -6951,1150926,146 -6952,1151072,159 -6953,1151231,175 -6954,1151406,170 -6955,1151576,170 -6956,1151746,157 -6957,1151903,154 -6958,1152057,148 -6959,1152205,147 -6960,1152352,140 -6961,1152492,181 -6962,1152673,158 -6963,1152831,138 -6964,1152969,182 -6965,1153151,266 -6966,1153417,202 -6967,1153619,134 -6968,1153753,237 -6969,1153990,146 -6970,1154136,161 -6971,1154297,169 -6972,1154466,197 -6973,1154663,139 -6974,1154802,154 -6975,1154956,173 -6976,1155129,144 -6977,1155273,191 -6978,1155464,189 -6979,1155653,215 -6980,1155868,154 -6981,1156022,187 -6982,1156209,196 -6983,1156405,118 -6984,1156523,228 -6985,1156751,183 -6986,1156934,180 -6987,1157114,187 -6988,1157301,181 -6989,1157482,187 -6990,1157669,157 -6991,1157826,156 -6992,1157982,245 -6993,1158227,178 -6994,1158405,147 -6995,1158552,170 -6996,1158722,170 -6997,1158892,185 -6998,1159077,140 -6999,1159217,231 -7000,1159448,206 -7001,1159654,176 -7002,1159830,176 -7003,1160006,139 -7004,1160145,206 -7005,1160351,160 -7006,1160511,149 -7007,1160660,152 -7008,1160812,131 -7009,1160943,159 -7010,1161102,198 -7011,1161300,120 -7012,1161420,216 -7013,1161636,186 -7014,1161822,179 -7015,1162001,188 -7016,1162189,191 -7017,1162380,185 -7018,1162565,177 -7019,1162742,156 -7020,1162898,157 -7021,1163055,144 -7022,1163199,162 -7023,1163361,142 -7024,1163503,180 -7025,1163683,156 -7026,1163839,124 -7027,1163963,171 -7028,1164134,163 -7029,1164297,161 -7030,1164458,156 -7031,1164614,166 -7032,1164780,175 -7033,1164955,174 -7034,1165129,161 -7035,1165290,167 -7036,1165457,162 -7037,1165619,143 -7038,1165762,131 -7039,1165893,183 -7040,1166076,146 -7041,1166222,159 -7042,1166381,201 -7043,1166582,135 -7044,1166717,161 -7045,1166878,129 -7046,1167007,161 -7047,1167168,203 -7048,1167371,207 -7049,1167578,174 -7050,1167752,130 -7051,1167882,146 -7052,1168028,202 -7053,1168230,175 -7054,1168405,136 -7055,1168541,170 -7056,1168711,170 -7057,1168881,125 -7058,1169006,147 -7059,1169153,138 -7060,1169291,155 -7061,1169446,154 -7062,1169600,159 -7063,1169759,147 -7064,1169906,180 -7065,1170086,136 -7066,1170222,169 -7067,1170391,183 -7068,1170574,137 -7069,1170711,167 -7070,1170878,175 -7071,1171053,158 -7072,1171211,143 -7073,1171354,153 -7074,1171507,176 -7075,1171683,146 -7076,1171829,127 -7077,1171956,202 -7078,1172158,199 -7079,1172357,148 -7080,1172505,167 -7081,1172672,229 -7082,1172901,133 -7083,1173034,171 -7084,1173205,215 -7085,1173420,176 -7086,1173596,176 -7087,1173772,138 -7088,1173910,145 -7089,1174055,186 -7090,1174241,176 -7091,1174417,129 -7092,1174546,160 -7093,1174706,158 -7094,1174864,152 -7095,1175016,183 -7096,1175199,200 -7097,1175399,207 -7098,1175606,135 -7099,1175741,182 -7100,1175923,165 -7101,1176088,158 -7102,1176246,134 -7103,1176380,147 -7104,1176527,149 -7105,1176676,202 -7106,1176878,202 -7107,1177080,167 -7108,1177247,138 -7109,1177385,287 -7110,1177672,148 -7111,1177820,208 -7112,1178028,138 -7113,1178166,239 -7114,1178405,186 -7115,1178591,161 -7116,1178752,197 -7117,1178949,166 -7118,1179115,176 -7119,1179291,153 -7120,1179444,135 -7121,1179579,145 -7122,1179724,160 -7123,1179884,171 -7124,1180055,170 -7125,1180225,170 -7126,1180395,159 -7127,1180554,207 -7128,1180761,110 -7129,1180871,165 -7130,1181036,139 -7131,1181175,155 -7132,1181330,177 -7133,1181507,147 -7134,1181654,150 -7135,1181804,140 -7136,1181944,166 -7137,1182110,124 -7138,1182234,151 -7139,1182385,180 -7140,1182565,124 -7141,1182689,164 -7142,1182853,118 -7143,1182971,197 -7144,1183168,132 -7145,1183300,151 -7146,1183451,161 -7147,1183612,192 -7148,1183804,200 -7149,1184004,178 -7150,1184182,138 -7151,1184320,213 -7152,1184533,206 -7153,1184739,272 -7154,1185011,184 -7155,1185195,168 -7156,1185363,177 -7157,1185540,194 -7158,1185734,221 -7159,1185955,135 -7160,1186090,157 -7161,1186247,206 -7162,1186453,133 -7163,1186586,163 -7164,1186749,161 -7165,1186910,182 -7166,1187092,171 -7167,1187263,155 -7168,1187418,142 -7169,1187560,126 -7170,1187686,161 -7171,1187847,149 -7172,1187996,156 -7173,1188152,152 -7174,1188304,216 -7175,1188520,188 -7176,1188708,151 -7177,1188859,216 -7178,1189075,244 -7179,1189319,178 -7180,1189497,152 -7181,1189649,154 -7182,1189803,170 -7183,1189973,170 -7184,1190143,152 -7185,1190295,147 -7186,1190442,147 -7187,1190589,225 -7188,1190814,137 -7189,1190951,164 -7190,1191115,160 -7191,1191275,135 -7192,1191410,133 -7193,1191543,163 -7194,1191706,174 -7195,1191880,152 -7196,1192032,173 -7197,1192205,202 -7198,1192407,149 -7199,1192556,170 -7200,1192726,137 -7201,1192863,148 -7202,1193011,161 -7203,1193172,139 -7204,1193311,188 -7205,1193499,193 -7206,1193692,193 -7207,1193885,185 -7208,1194070,165 -7209,1194235,237 -7210,1194472,172 -7211,1194644,163 -7212,1194807,127 -7213,1194934,143 -7214,1195077,146 -7215,1195223,142 -7216,1195365,184 -7217,1195549,221 -7218,1195770,180 -7219,1195950,124 -7220,1196074,219 -7221,1196293,139 -7222,1196432,133 -7223,1196565,147 -7224,1196712,173 -7225,1196885,180 -7226,1197065,169 -7227,1197234,186 -7228,1197420,144 -7229,1197564,147 -7230,1197711,144 -7231,1197855,191 -7232,1198046,143 -7233,1198189,172 -7234,1198361,153 -7235,1198514,175 -7236,1198689,166 -7237,1198855,193 -7238,1199048,177 -7239,1199225,208 -7240,1199433,151 -7241,1199584,171 -7242,1199755,113 -7243,1199868,143 -7244,1200011,153 -7245,1200164,202 -7246,1200366,210 -7247,1200576,119 -7248,1200695,239 -7249,1200934,143 -7250,1201077,141 -7251,1201218,159 -7252,1201377,174 -7253,1201551,187 -7254,1201738,197 -7255,1201935,170 -7256,1202105,170 -7257,1202275,148 -7258,1202423,160 -7259,1202583,195 -7260,1202778,179 -7261,1202957,187 -7262,1203144,141 -7263,1203285,159 -7264,1203444,168 -7265,1203612,212 -7266,1203824,164 -7267,1203988,157 -7268,1204145,147 -7269,1204292,146 -7270,1204438,172 -7271,1204610,186 -7272,1204796,183 -7273,1204979,161 -7274,1205140,147 -7275,1205287,151 -7276,1205438,260 -7277,1205698,201 -7278,1205899,155 -7279,1206054,122 -7280,1206176,147 -7281,1206323,187 -7282,1206510,173 -7283,1206683,170 -7284,1206853,189 -7285,1207042,145 -7286,1207187,175 -7287,1207362,132 -7288,1207494,129 -7289,1207623,198 -7290,1207821,189 -7291,1208010,184 -7292,1208194,182 -7293,1208376,192 -7294,1208568,115 -7295,1208683,187 -7296,1208870,237 -7297,1209107,170 -7298,1209277,208 -7299,1209485,202 -7300,1209687,210 -7301,1209897,150 -7302,1210047,153 -7303,1210200,171 -7304,1210371,183 -7305,1210554,156 -7306,1210710,162 -7307,1210872,160 -7308,1211032,203 -7309,1211235,132 -7310,1211367,157 -7311,1211524,198 -7312,1211722,152 -7313,1211874,137 -7314,1212011,132 -7315,1212143,132 -7316,1212275,149 -7317,1212424,154 -7318,1212578,192 -7319,1212770,174 -7320,1212944,224 -7321,1213168,141 -7322,1213309,138 -7323,1213447,147 -7324,1213594,135 -7325,1213729,141 -7326,1213870,148 -7327,1214018,151 -7328,1214169,177 -7329,1214346,163 -7330,1214509,137 -7331,1214646,117 -7332,1214763,173 -7333,1214936,148 -7334,1215084,162 -7335,1215246,211 -7336,1215457,173 -7337,1215630,134 -7338,1215764,148 -7339,1215912,173 -7340,1216085,200 -7341,1216285,200 -7342,1216485,150 -7343,1216635,164 -7344,1216799,170 -7345,1216969,170 -7346,1217139,130 -7347,1217269,120 -7348,1217389,154 -7349,1217543,201 -7350,1217744,199 -7351,1217943,189 -7352,1218132,136 -7353,1218268,214 -7354,1218482,162 -7355,1218644,132 -7356,1218776,156 -7357,1218932,195 -7358,1219127,161 -7359,1219288,166 -7360,1219454,166 -7361,1219620,147 -7362,1219767,156 -7363,1219923,154 -7364,1220077,175 -7365,1220252,199 -7366,1220451,162 -7367,1220613,222 -7368,1220835,217 -7369,1221052,215 -7370,1221267,224 -7371,1221491,219 -7372,1221710,164 -7373,1221874,166 -7374,1222040,140 -7375,1222180,181 -7376,1222361,143 -7377,1222504,169 -7378,1222673,224 -7379,1222897,160 -7380,1223057,138 -7381,1223195,148 -7382,1223343,138 -7383,1223481,203 -7384,1223684,153 -7385,1223837,211 -7386,1224048,175 -7387,1224223,178 -7388,1224401,176 -7389,1224577,162 -7390,1224739,198 -7391,1224937,172 -7392,1225109,176 -7393,1225285,164 -7394,1225449,165 -7395,1225614,153 -7396,1225767,142 -7397,1225909,167 -7398,1226076,146 -7399,1226222,148 -7400,1226370,131 -7401,1226501,194 -7402,1226695,180 -7403,1226875,135 -7404,1227010,187 -7405,1227197,142 -7406,1227339,169 -7407,1227508,171 -7408,1227679,178 -7409,1227857,199 -7410,1228056,198 -7411,1228254,176 -7412,1228430,187 -7413,1228617,217 -7414,1228834,170 -7415,1229004,157 -7416,1229161,205 -7417,1229366,170 -7418,1229536,143 -7419,1229679,147 -7420,1229826,252 -7421,1230078,161 -7422,1230239,152 -7423,1230391,163 -7424,1230554,166 -7425,1230720,151 -7426,1230871,174 -7427,1231045,153 -7428,1231198,164 -7429,1231362,151 -7430,1231513,148 -7431,1231661,284 -7432,1231945,193 -7433,1232138,138 -7434,1232276,155 -7435,1232431,163 -7436,1232594,167 -7437,1232761,186 -7438,1232947,197 -7439,1233144,212 -7440,1233356,156 -7441,1233512,188 -7442,1233700,156 -7443,1233856,177 -7444,1234033,198 -7445,1234231,236 -7446,1234467,147 -7447,1234614,157 -7448,1234771,147 -7449,1234918,226 -7450,1235144,135 -7451,1235279,195 -7452,1235474,146 -7453,1235620,163 -7454,1235783,165 -7455,1235948,164 -7456,1236112,198 -7457,1236310,136 -7458,1236446,147 -7459,1236593,130 -7460,1236723,171 -7461,1236894,175 -7462,1237069,188 -7463,1237257,153 -7464,1237410,176 -7465,1237586,115 -7466,1237701,238 -7467,1237939,256 -7468,1238195,250 -7469,1238445,156 -7470,1238601,158 -7471,1238759,161 -7472,1238920,176 -7473,1239096,197 -7474,1239293,234 -7475,1239527,196 -7476,1239723,186 -7477,1239909,161 -7478,1240070,228 -7479,1240298,201 -7480,1240499,159 -7481,1240658,210 -7482,1240868,138 -7483,1241006,138 -7484,1241144,142 -7485,1241286,144 -7486,1241430,179 -7487,1241609,152 -7488,1241761,194 -7489,1241955,149 -7490,1242104,135 -7491,1242239,260 -7492,1242499,153 -7493,1242652,170 -7494,1242822,170 -7495,1242992,136 -7496,1243128,167 -7497,1243295,175 -7498,1243470,159 -7499,1243629,146 -7500,1243775,149 -7501,1243924,175 -7502,1244099,159 -7503,1244258,120 -7504,1244378,153 -7505,1244531,213 -7506,1244744,145 -7507,1244889,212 -7508,1245101,193 -7509,1245294,144 -7510,1245438,151 -7511,1245589,145 -7512,1245734,147 -7513,1245881,165 -7514,1246046,146 -7515,1246192,185 -7516,1246377,194 -7517,1246571,164 -7518,1246735,186 -7519,1246921,154 -7520,1247075,161 -7521,1247236,176 -7522,1247412,154 -7523,1247566,139 -7524,1247705,207 -7525,1247912,186 -7526,1248098,187 -7527,1248285,137 -7528,1248422,162 -7529,1248584,163 -7530,1248747,179 -7531,1248926,147 -7532,1249073,178 -7533,1249251,176 -7534,1249427,137 -7535,1249564,210 -7536,1249774,170 -7537,1249944,170 -7538,1250114,184 -7539,1250298,161 -7540,1250459,250 -7541,1250709,150 -7542,1250859,176 -7543,1251035,138 -7544,1251173,213 -7545,1251386,152 -7546,1251538,180 -7547,1251718,166 -7548,1251884,157 -7549,1252041,188 -7550,1252229,152 -7551,1252381,193 -7552,1252574,190 -7553,1252764,235 -7554,1252999,163 -7555,1253162,199 -7556,1253361,173 -7557,1253534,218 -7558,1253752,230 -7559,1253982,199 -7560,1254181,137 -7561,1254318,155 -7562,1254473,143 -7563,1254616,137 -7564,1254753,163 -7565,1254916,128 -7566,1255044,163 -7567,1255207,150 -7568,1255357,145 -7569,1255502,149 -7570,1255651,182 -7571,1255833,159 -7572,1255992,207 -7573,1256199,137 -7574,1256336,139 -7575,1256475,181 -7576,1256656,138 -7577,1256794,163 -7578,1256957,203 -7579,1257160,166 -7580,1257326,164 -7581,1257490,196 -7582,1257686,155 -7583,1257841,165 -7584,1258006,248 -7585,1258254,170 -7586,1258424,170 -7587,1258594,134 -7588,1258728,212 -7589,1258940,135 -7590,1259075,155 -7591,1259230,161 -7592,1259391,185 -7593,1259576,200 -7594,1259776,192 -7595,1259968,147 -7596,1260115,151 -7597,1260266,254 -7598,1260520,220 -7599,1260740,135 -7600,1260875,248 -7601,1261123,142 -7602,1261265,191 -7603,1261456,146 -7604,1261602,180 -7605,1261782,147 -7606,1261929,169 -7607,1262098,177 -7608,1262275,146 -7609,1262421,152 -7610,1262573,167 -7611,1262740,222 -7612,1262962,161 -7613,1263123,140 -7614,1263263,147 -7615,1263410,167 -7616,1263577,147 -7617,1263724,138 -7618,1263862,132 -7619,1263994,142 -7620,1264136,176 -7621,1264312,233 -7622,1264545,161 -7623,1264706,209 -7624,1264915,196 -7625,1265111,135 -7626,1265246,202 -7627,1265448,146 -7628,1265594,160 -7629,1265754,147 -7630,1265901,147 -7631,1266048,147 -7632,1266195,147 -7633,1266342,147 -7634,1266489,147 -7635,1266636,147 -7636,1266783,147 -7637,1266930,147 -7638,1267077,147 -7639,1267224,120 -7640,1267344,165 -7641,1267509,190 -7642,1267699,171 -7643,1267870,163 -7644,1268033,231 -7645,1268264,189 -7646,1268453,240 -7647,1268693,202 -7648,1268895,166 -7649,1269061,166 -7650,1269227,158 -7651,1269385,141 -7652,1269526,179 -7653,1269705,170 -7654,1269875,170 -7655,1270045,217 -7656,1270262,188 -7657,1270450,138 -7658,1270588,176 -7659,1270764,162 -7660,1270926,160 -7661,1271086,159 -7662,1271245,241 -7663,1271486,133 -7664,1271619,156 -7665,1271775,154 -7666,1271929,142 -7667,1272071,193 -7668,1272264,171 -7669,1272435,156 -7670,1272591,175 -7671,1272766,173 -7672,1272939,206 -7673,1273145,195 -7674,1273340,239 -7675,1273579,194 -7676,1273773,180 -7677,1273953,138 -7678,1274091,131 -7679,1274222,194 -7680,1274416,198 -7681,1274614,180 -7682,1274794,191 -7683,1274985,168 -7684,1275153,166 -7685,1275319,180 -7686,1275499,159 -7687,1275658,222 -7688,1275880,204 -7689,1276084,154 -7690,1276238,177 -7691,1276415,175 -7692,1276590,193 -7693,1276783,146 -7694,1276929,192 -7695,1277121,152 -7696,1277273,248 -7697,1277521,201 -7698,1277722,155 -7699,1277877,170 -7700,1278047,170 -7701,1278217,189 -7702,1278406,123 -7703,1278529,120 -7704,1278649,137 -7705,1278786,109 -7706,1278895,204 -7707,1279099,220 -7708,1279319,159 -7709,1279478,168 -7710,1279646,156 -7711,1279802,135 -7712,1279937,192 -7713,1280129,147 -7714,1280276,153 -7715,1280429,177 -7716,1280606,190 -7717,1280796,219 -7718,1281015,187 -7719,1281202,207 -7720,1281409,156 -7721,1281565,155 -7722,1281720,147 -7723,1281867,170 -7724,1282037,180 -7725,1282217,144 -7726,1282361,127 -7727,1282488,140 -7728,1282628,135 -7729,1282763,174 -7730,1282937,116 -7731,1283053,199 -7732,1283252,141 -7733,1283393,161 -7734,1283554,108 -7735,1283662,242 -7736,1283904,217 -7737,1284121,150 -7738,1284271,137 -7739,1284408,138 -7740,1284546,137 -7741,1284683,161 -7742,1284844,156 -7743,1285000,184 -7744,1285184,217 -7745,1285401,239 -7746,1285640,120 -7747,1285760,150 -7748,1285910,136 -7749,1286046,176 -7750,1286222,147 -7751,1286369,193 -7752,1286562,116 -7753,1286678,170 -7754,1286848,170 -7755,1287018,147 -7756,1287165,192 -7757,1287357,168 -7758,1287525,192 -7759,1287717,140 -7760,1287857,153 -7761,1288010,143 -7762,1288153,120 -7763,1288273,186 -7764,1288459,169 -7765,1288628,187 -7766,1288815,161 -7767,1288976,155 -7768,1289131,178 -7769,1289309,174 -7770,1289483,147 -7771,1289630,151 -7772,1289781,157 -7773,1289938,122 -7774,1290060,153 -7775,1290213,136 -7776,1290349,174 -7777,1290523,122 -7778,1290645,130 -7779,1290775,137 -7780,1290912,166 -7781,1291078,166 -7782,1291244,178 -7783,1291422,166 -7784,1291588,183 -7785,1291771,144 -7786,1291915,205 -7787,1292120,143 -7788,1292263,136 -7789,1292399,155 -7790,1292554,221 -7791,1292775,167 -7792,1292942,187 -7793,1293129,162 -7794,1293291,140 -7795,1293431,196 -7796,1293627,140 -7797,1293767,151 -7798,1293918,168 -7799,1294086,122 -7800,1294208,210 -7801,1294418,170 -7802,1294588,170 -7803,1294758,136 -7804,1294894,196 -7805,1295090,175 -7806,1295265,135 -7807,1295400,164 -7808,1295564,160 -7809,1295724,185 -7810,1295909,162 -7811,1296071,217 -7812,1296288,166 -7813,1296454,153 -7814,1296607,157 -7815,1296764,174 -7816,1296938,175 -7817,1297113,177 -7818,1297290,123 -7819,1297413,215 -7820,1297628,161 -7821,1297789,147 -7822,1297936,127 -7823,1298063,133 -7824,1298196,190 -7825,1298386,180 -7826,1298566,135 -7827,1298701,158 -7828,1298859,200 -7829,1299059,190 -7830,1299249,161 -7831,1299410,249 -7832,1299659,198 -7833,1299857,198 -7834,1300055,149 -7835,1300204,143 -7836,1300347,169 -7837,1300516,175 -7838,1300691,192 -7839,1300883,187 -7840,1301070,113 -7841,1301183,121 -7842,1301304,151 -7843,1301455,138 -7844,1301593,138 -7845,1301731,210 -7846,1301941,231 -7847,1302172,165 -7848,1302337,214 -7849,1302551,161 -7850,1302712,154 -7851,1302866,129 -7852,1302995,179 -7853,1303174,174 -7854,1303348,180 -7855,1303528,133 -7856,1303661,142 -7857,1303803,153 -7858,1303956,169 -7859,1304125,143 -7860,1304268,191 -7861,1304459,207 -7862,1304666,153 -7863,1304819,186 -7864,1305005,192 -7865,1305197,248 -7866,1305445,154 -7867,1305599,172 -7868,1305771,214 -7869,1305985,170 -7870,1306155,170 -7871,1306325,147 -7872,1306472,167 -7873,1306639,174 -7874,1306813,120 -7875,1306933,151 -7876,1307084,138 -7877,1307222,169 -7878,1307391,168 -7879,1307559,137 -7880,1307696,222 -7881,1307918,138 -7882,1308056,135 -7883,1308191,178 -7884,1308369,134 -7885,1308503,186 -7886,1308689,207 -7887,1308896,196 -7888,1309092,122 -7889,1309214,145 -7890,1309359,206 -7891,1309565,191 -7892,1309756,156 -7893,1309912,146 -7894,1310058,135 -7895,1310193,178 -7896,1310371,164 -7897,1310535,184 -7898,1310719,176 -7899,1310895,163 -7900,1311058,176 -7901,1311234,125 -7902,1311359,183 -7903,1311542,191 -7904,1311733,133 -7905,1311866,175 -7906,1312041,175 -7907,1312216,213 -7908,1312429,159 -7909,1312588,152 -7910,1312740,223 -7911,1312963,143 -7912,1313106,126 -7913,1313232,164 -7914,1313396,152 -7915,1313548,144 -7916,1313692,237 -7917,1313929,161 -7918,1314090,171 -7919,1314261,261 -7920,1314522,157 -7921,1314679,144 -7922,1314823,147 -7923,1314970,145 -7924,1315115,197 -7925,1315312,178 -7926,1315490,170 -7927,1315660,170 -7928,1315830,149 -7929,1315979,183 -7930,1316162,164 -7931,1316326,176 -7932,1316502,174 -7933,1316676,122 -7934,1316798,129 -7935,1316927,175 -7936,1317102,139 -7937,1317241,139 -7938,1317380,182 -7939,1317562,120 -7940,1317682,163 -7941,1317845,170 -7942,1318015,167 -7943,1318182,148 -7944,1318330,126 -7945,1318456,194 -7946,1318650,144 -7947,1318794,223 -7948,1319017,200 -7949,1319217,178 -7950,1319395,158 -7951,1319553,162 -7952,1319715,249 -7953,1319964,169 -7954,1320133,149 -7955,1320282,153 -7956,1320435,151 -7957,1320586,137 -7958,1320723,183 -7959,1320906,164 -7960,1321070,197 -7961,1321267,180 -7962,1321447,173 -7963,1321620,193 -7964,1321813,168 -7965,1321981,190 -7966,1322171,186 -7967,1322357,205 -7968,1322562,193 -7969,1322755,262 -7970,1323017,161 -7971,1323178,128 -7972,1323306,208 -7973,1323514,136 -7974,1323650,170 -7975,1323820,170 -7976,1323990,146 -7977,1324136,175 -7978,1324311,145 -7979,1324456,180 -7980,1324636,165 -7981,1324801,185 -7982,1324986,179 -7983,1325165,146 -7984,1325311,134 -7985,1325445,126 -7986,1325571,161 -7987,1325732,144 -7988,1325876,210 -7989,1326086,133 -7990,1326219,193 -7991,1326412,187 -7992,1326599,188 -7993,1326787,211 -7994,1326998,193 -7995,1327191,166 -7996,1327357,166 -7997,1327523,131 -7998,1327654,149 -7999,1327803,113 -8000,1327916,147 -8001,1328063,144 -8002,1328207,142 -8003,1328349,183 -8004,1328532,159 -8005,1328691,128 -8006,1328819,129 -8007,1328948,182 -8008,1329130,155 -8009,1329285,179 -8010,1329464,133 -8011,1329597,136 -8012,1329733,154 -8013,1329887,152 -8014,1330039,140 -8015,1330179,180 -8016,1330359,129 -8017,1330488,154 -8018,1330642,211 -8019,1330853,236 -8020,1331089,155 -8021,1331244,262 -8022,1331506,212 -8023,1331718,183 -8024,1331901,155 -8025,1332056,159 -8026,1332215,155 -8027,1332370,120 -8028,1332490,138 -8029,1332628,138 -8030,1332766,196 -8031,1332962,137 -8032,1333099,186 -8033,1333285,223 -8034,1333508,142 -8035,1333650,154 -8036,1333804,210 -8037,1334014,190 -8038,1334204,137 -8039,1334341,137 -8040,1334478,153 -8041,1334631,226 -8042,1334857,164 -8043,1335021,151 -8044,1335172,170 -8045,1335342,170 -8046,1335512,181 -8047,1335693,350 -8048,1336043,177 -8049,1336220,169 -8050,1336389,179 -8051,1336568,229 -8052,1336797,138 -8053,1336935,159 -8054,1337094,156 -8055,1337250,126 -8056,1337376,179 -8057,1337555,146 -8058,1337701,155 -8059,1337856,166 -8060,1338022,120 -8061,1338142,149 -8062,1338291,147 -8063,1338438,173 -8064,1338611,132 -8065,1338743,164 -8066,1338907,234 -8067,1339141,219 -8068,1339360,172 -8069,1339532,159 -8070,1339691,126 -8071,1339817,157 -8072,1339974,168 -8073,1340142,131 -8074,1340273,210 -8075,1340483,142 -8076,1340625,154 -8077,1340779,186 -8078,1340965,141 -8079,1341106,207 -8080,1341313,165 -8081,1341478,169 -8082,1341647,152 -8083,1341799,159 -8084,1341958,180 -8085,1342138,140 -8086,1342278,190 -8087,1342468,135 -8088,1342603,137 -8089,1342740,182 -8090,1342922,149 -8091,1343071,178 -8092,1343249,124 -8093,1343373,170 -8094,1343543,170 -8095,1343713,160 -8096,1343873,139 -8097,1344012,133 -8098,1344145,186 -8099,1344331,189 -8100,1344520,212 -8101,1344732,163 -8102,1344895,113 -8103,1345008,178 -8104,1345186,186 -8105,1345372,149 -8106,1345521,139 -8107,1345660,180 -8108,1345840,147 -8109,1345987,172 -8110,1346159,180 -8111,1346339,155 -8112,1346494,137 -8113,1346631,146 -8114,1346777,185 -8115,1346962,127 -8116,1347089,141 -8117,1347230,155 -8118,1347385,183 -8119,1347568,204 -8120,1347772,189 -8121,1347961,136 -8122,1348097,212 -8123,1348309,175 -8124,1348484,149 -8125,1348633,163 -8126,1348796,224 -8127,1349020,242 -8128,1349262,158 -8129,1349420,259 -8130,1349679,201 -8131,1349880,155 -8132,1350035,147 -8133,1350182,161 -8134,1350343,172 -8135,1350515,209 -8136,1350724,218 -8137,1350942,170 -8138,1351112,170 -8139,1351282,144 -8140,1351426,175 -8141,1351601,159 -8142,1351760,157 -8143,1351917,166 -8144,1352083,187 -8145,1352270,132 -8146,1352402,220 -8147,1352622,148 -8148,1352770,138 -8149,1352908,154 -8150,1353062,142 -8151,1353204,136 -8152,1353340,206 -8153,1353546,200 -8154,1353746,144 -8155,1353890,151 -8156,1354041,138 -8157,1354179,151 -8158,1354330,138 -8159,1354468,138 -8160,1354606,151 -8161,1354757,196 -8162,1354953,196 -8163,1355149,152 -8164,1355301,173 -8165,1355474,141 -8166,1355615,192 -8167,1355807,124 -8168,1355931,190 -8169,1356121,140 -8170,1356261,194 -8171,1356455,154 -8172,1356609,154 -8173,1356763,146 -8174,1356909,154 -8175,1357063,163 -8176,1357226,157 -8177,1357383,157 -8178,1357540,178 -8179,1357718,120 -8180,1357838,165 -8181,1358003,165 -8182,1358168,156 -8183,1358324,197 -8184,1358521,259 -8185,1358780,185 -8186,1358965,184 -8187,1359149,233 -8188,1359382,134 -8189,1359516,230 -8190,1359746,146 -8191,1359892,155 -8192,1360047,181 -8193,1360228,153 -8194,1360381,221 -8195,1360602,174 -8196,1360776,162 -8197,1360938,146 -8198,1361084,172 -8199,1361256,132 -8200,1361388,171 -8201,1361559,163 -8202,1361722,165 -8203,1361887,161 -8204,1362048,163 -8205,1362211,131 -8206,1362342,174 -8207,1362516,154 -8208,1362670,171 -8209,1362841,160 -8210,1363001,158 -8211,1363159,170 -8212,1363329,205 -8213,1363534,147 -8214,1363681,184 -8215,1363865,126 -8216,1363991,190 -8217,1364181,125 -8218,1364306,162 -8219,1364468,186 -8220,1364654,143 -8221,1364797,156 -8222,1364953,164 -8223,1365117,159 -8224,1365276,189 -8225,1365465,181 -8226,1365646,154 -8227,1365800,158 -8228,1365958,173 -8229,1366131,164 -8230,1366295,155 -8231,1366450,228 -8232,1366678,165 -8233,1366843,197 -8234,1367040,133 -8235,1367173,221 -8236,1367394,199 -8237,1367593,138 -8238,1367731,150 -8239,1367881,195 -8240,1368076,151 -8241,1368227,131 -8242,1368358,193 -8243,1368551,172 -8244,1368723,160 -8245,1368883,170 -8246,1369053,144 -8247,1369197,173 -8248,1369370,205 -8249,1369575,130 -8250,1369705,169 -8251,1369874,167 -8252,1370041,112 -8253,1370153,157 -8254,1370310,168 -8255,1370478,138 -8256,1370616,147 -8257,1370763,151 -8258,1370914,148 -8259,1371062,186 -8260,1371248,133 -8261,1371381,158 -8262,1371539,148 -8263,1371687,147 -8264,1371834,160 -8265,1371994,162 -8266,1372156,138 -8267,1372294,208 -8268,1372502,165 -8269,1372667,129 -8270,1372796,183 -8271,1372979,198 -8272,1373177,162 -8273,1373339,151 -8274,1373490,149 -8275,1373639,168 -8276,1373807,141 -8277,1373948,164 -8278,1374112,141 -8279,1374253,155 -8280,1374408,139 -8281,1374547,160 -8282,1374707,140 -8283,1374847,143 -8284,1374990,173 -8285,1375163,127 -8286,1375290,168 -8287,1375458,147 -8288,1375605,147 -8289,1375752,147 -8290,1375899,169 -8291,1376068,162 -8292,1376230,163 -8293,1376393,157 -8294,1376550,155 -8295,1376705,55 -8296,1376760,121 -8297,1376881,178 -8298,1377059,142 -8299,1377201,175 -8300,1377376,165 -8301,1377541,151 -8302,1377692,123 -8303,1377815,163 -8304,1377978,146 -8305,1378124,117 -8306,1378241,156 -8307,1378397,166 -8308,1378563,177 -8309,1378740,179 -8310,1378919,145 -8311,1379064,156 -8312,1379220,196 -8313,1379416,124 -8314,1379540,162 -8315,1379702,160 -8316,1379862,124 -8317,1379986,168 -8318,1380154,151 -8319,1380305,182 -8320,1380487,172 -8321,1380659,151 -8322,1380810,152 -8323,1380962,176 -8324,1381138,150 -8325,1381288,145 -8326,1381433,201 -8327,1381634,140 -8328,1381774,174 -8329,1381948,168 -8330,1382116,182 -8331,1382298,180 -8332,1382478,157 -8333,1382635,132 -8334,1382767,199 -8335,1382966,137 -8336,1383103,183 -8337,1383286,176 -8338,1383462,150 -8339,1383612,184 -8340,1383796,148 -8341,1383944,203 -8342,1384147,164 -8343,1384311,161 -8344,1384472,119 -8345,1384591,162 -8346,1384753,147 -8347,1384900,142 -8348,1385042,158 -8349,1385200,156 -8350,1385356,214 -8351,1385570,174 -8352,1385744,151 -8353,1385895,150 -8354,1386045,149 -8355,1386194,143 -8356,1386337,150 -8357,1386487,143 -8358,1386630,142 -8359,1386772,172 -8360,1386944,178 -8361,1387122,197 -8362,1387319,222 -8363,1387541,166 -8364,1387707,178 -8365,1387885,130 -8366,1388015,156 -8367,1388171,148 -8368,1388319,154 -8369,1388473,152 -8370,1388625,215 -8371,1388840,130 -8372,1388970,138 -8373,1389108,177 -8374,1389285,149 -8375,1389434,147 -8376,1389581,155 -8377,1389736,144 -8378,1389880,203 -8379,1390083,146 -8380,1390229,173 -8381,1390402,160 -8382,1390562,156 -8383,1390718,153 -8384,1390871,162 -8385,1391033,153 -8386,1391186,173 -8387,1391359,160 -8388,1391519,138 -8389,1391657,142 -8390,1391799,119 -8391,1391918,180 -8392,1392098,161 -8393,1392259,130 -8394,1392389,144 -8395,1392533,174 -8396,1392707,172 -8397,1392879,157 -8398,1393036,166 -8399,1393202,170 -8400,1393372,155 -8401,1393527,196 -8402,1393723,163 -8403,1393886,188 -8404,1394074,184 -8405,1394258,119 -8406,1394377,133 -8407,1394510,190 -8408,1394700,151 -8409,1394851,184 -8410,1395035,167 -8411,1395202,157 -8412,1395359,166 -8413,1395525,154 -8414,1395679,216 -8415,1395895,169 -8416,1396064,169 -8417,1396233,149 -8418,1396382,179 -8419,1396561,169 -8420,1396730,203 -8421,1396933,142 -8422,1397075,145 -8423,1397220,203 -8424,1397423,150 -8425,1397573,150 -8426,1397723,184 -8427,1397907,167 -8428,1398074,173 -8429,1398247,172 -8430,1398419,151 -8431,1398570,145 -8432,1398715,211 -8433,1398926,161 -8434,1399087,154 -8435,1399241,154 -8436,1399395,166 -8437,1399561,122 -8438,1399683,203 -8439,1399886,150 -8440,1400036,173 -8441,1400209,171 -8442,1400380,159 -8443,1400539,166 -8444,1400705,122 -8445,1400827,167 -8446,1400994,217 -8447,1401211,163 -8448,1401374,203 -8449,1401577,213 -8450,1401790,156 -8451,1401946,173 -8452,1402119,155 -8453,1402274,149 -8454,1402423,147 -8455,1402570,168 -8456,1402738,138 -8457,1402876,138 -8458,1403014,163 -8459,1403177,177 -8460,1403354,170 -8461,1403524,166 -8462,1403690,139 -8463,1403829,150 -8464,1403979,161 -8465,1404140,140 -8466,1404280,154 -8467,1404434,152 -8468,1404586,183 -8469,1404769,177 -8470,1404946,196 -8471,1405142,155 -8472,1405297,170 -8473,1405467,174 -8474,1405641,160 -8475,1405801,170 -8476,1405971,170 -8477,1406141,126 -8478,1406267,147 -8479,1406414,190 -8480,1406604,153 -8481,1406757,128 -8482,1406885,167 -8483,1407052,155 -8484,1407207,167 -8485,1407374,181 -8486,1407555,236 -8487,1407791,235 -8488,1408026,177 -8489,1408203,152 -8490,1408355,150 -8491,1408505,117 -8492,1408622,233 -8493,1408855,165 -8494,1409020,152 -8495,1409172,140 -8496,1409312,190 -8497,1409502,150 -8498,1409652,149 -8499,1409801,160 -8500,1409961,157 -8501,1410118,128 -8502,1410246,147 -8503,1410393,146 -8504,1410539,128 -8505,1410667,144 -8506,1410811,183 -8507,1410994,150 -8508,1411144,153 -8509,1411297,176 -8510,1411473,138 -8511,1411611,195 -8512,1411806,182 -8513,1411988,116 -8514,1412104,163 -8515,1412267,147 -8516,1412414,155 -8517,1412569,202 -8518,1412771,146 -8519,1412917,161 -8520,1413078,176 -8521,1413254,187 -8522,1413441,168 -8523,1413609,253 -8524,1413862,198 -8525,1414060,259 -8526,1414319,185 -8527,1414504,157 -8528,1414661,173 -8529,1414834,195 -8530,1415029,245 -8531,1415274,138 -8532,1415412,179 -8533,1415591,170 -8534,1415761,170 -8535,1415931,170 -8536,1416101,207 -8537,1416308,147 -8538,1416455,175 -8539,1416630,131 -8540,1416761,166 -8541,1416927,166 -8542,1417093,170 -8543,1417263,144 -8544,1417407,213 -8545,1417620,163 -8546,1417783,144 -8547,1417927,170 -8548,1418097,228 -8549,1418325,147 -8550,1418472,133 -8551,1418605,198 -8552,1418803,147 -8553,1418950,154 -8554,1419104,166 -8555,1419270,166 -8556,1419436,138 -8557,1419574,164 -8558,1419738,251 -8559,1419989,142 -8560,1420131,138 -8561,1420269,229 -8562,1420498,150 -8563,1420648,172 -8564,1420820,159 -8565,1420979,203 -8566,1421182,160 -8567,1421342,152 -8568,1421494,168 -8569,1421662,125 -8570,1421787,204 -8571,1421991,118 -8572,1422109,127 -8573,1422236,180 -8574,1422416,167 -8575,1422583,169 -8576,1422752,147 -8577,1422899,193 -8578,1423092,152 -8579,1423244,142 -8580,1423386,132 -8581,1423518,183 -8582,1423701,244 -8583,1423945,139 -8584,1424084,152 -8585,1424236,143 -8586,1424379,195 -8587,1424574,179 -8588,1424753,134 -8589,1424887,194 -8590,1425081,173 -8591,1425254,218 -8592,1425472,153 -8593,1425625,176 -8594,1425801,260 -8595,1426061,130 -8596,1426191,133 -8597,1426324,157 -8598,1426481,142 -8599,1426623,184 -8600,1426807,205 -8601,1427012,111 -8602,1427123,182 -8603,1427305,138 -8604,1427443,169 -8605,1427612,135 -8606,1427747,173 -8607,1427920,133 -8608,1428053,170 -8609,1428223,170 -8610,1428393,138 -8611,1428531,128 -8612,1428659,136 -8613,1428795,177 -8614,1428972,124 -8615,1429096,220 -8616,1429316,170 -8617,1429486,182 -8618,1429668,138 -8619,1429806,140 -8620,1429946,212 -8621,1430158,126 -8622,1430284,174 -8623,1430458,144 -8624,1430602,168 -8625,1430770,180 -8626,1430950,141 -8627,1431091,131 -8628,1431222,178 -8629,1431400,125 -8630,1431525,177 -8631,1431702,171 -8632,1431873,173 -8633,1432046,159 -8634,1432205,153 -8635,1432358,151 -8636,1432509,118 -8637,1432627,161 -8638,1432788,235 -8639,1433023,200 -8640,1433223,207 -8641,1433430,160 -8642,1433590,176 -8643,1433766,177 -8644,1433943,141 -8645,1434084,149 -8646,1434233,196 -8647,1434429,124 -8648,1434553,142 -8649,1434695,218 -8650,1434913,198 -8651,1435111,175 -8652,1435286,202 -8653,1435488,142 -8654,1435630,150 -8655,1435780,142 -8656,1435922,193 -8657,1436115,175 -8658,1436290,175 -8659,1436465,193 -8660,1436658,155 -8661,1436813,134 -8662,1436947,137 -8663,1437084,170 -8664,1437254,170 -8665,1437424,160 -8666,1437584,173 -8667,1437757,228 -8668,1437985,144 -8669,1438129,167 -8670,1438296,175 -8671,1438471,158 -8672,1438629,148 -8673,1438777,149 -8674,1438926,171 -8675,1439097,137 -8676,1439234,140 -8677,1439374,142 -8678,1439516,178 -8679,1439694,206 -8680,1439900,185 -8681,1440085,120 -8682,1440205,146 -8683,1440351,150 -8684,1440501,131 -8685,1440632,131 -8686,1440763,171 -8687,1440934,165 -8688,1441099,151 -8689,1441250,133 -8690,1441383,223 -8691,1441606,115 -8692,1441721,159 -8693,1441880,181 -8694,1442061,149 -8695,1442210,146 -8696,1442356,157 -8697,1442513,153 -8698,1442666,149 -8699,1442815,152 -8700,1442967,138 -8701,1443105,119 -8702,1443224,138 -8703,1443362,138 -8704,1443500,138 -8705,1443638,146 -8706,1443784,157 -8707,1443941,169 -8708,1444110,138 -8709,1444248,174 -8710,1444422,139 -8711,1444561,166 -8712,1444727,148 -8713,1444875,173 -8714,1445048,149 -8715,1445197,212 -8716,1445409,170 -8717,1445579,170 -8718,1445749,189 -8719,1445938,191 -8720,1446129,147 -8721,1446276,140 -8722,1446416,170 -8723,1446586,179 -8724,1446765,189 -8725,1446954,162 -8726,1447116,184 -8727,1447300,144 -8728,1447444,133 -8729,1447577,138 -8730,1447715,145 -8731,1447860,161 -8732,1448021,55 -8733,1448076,220 -8734,1448296,203 -8735,1448499,206 -8736,1448705,182 -8737,1448887,144 -8738,1449031,187 -8739,1449218,174 -8740,1449392,200 -8741,1449592,162 -8742,1449754,145 -8743,1449899,164 -8744,1450063,165 -8745,1450228,151 -8746,1450379,141 -8747,1450520,136 -8748,1450656,150 -8749,1450806,134 -8750,1450940,129 -8751,1451069,172 -8752,1451241,155 -8753,1451396,176 -8754,1451572,214 -8755,1451786,137 -8756,1451923,158 -8757,1452081,145 -8758,1452226,128 -8759,1452354,164 -8760,1452518,152 -8761,1452670,187 -8762,1452857,193 -8763,1453050,164 -8764,1453214,157 -8765,1453371,172 -8766,1453543,143 -8767,1453686,143 -8768,1453829,166 -8769,1453995,120 -8770,1454115,147 -8771,1454262,190 -8772,1454452,245 -8773,1454697,142 -8774,1454839,234 -8775,1455073,173 -8776,1455246,165 -8777,1455411,164 -8778,1455575,134 -8779,1455709,200 -8780,1455909,161 -8781,1456070,186 -8782,1456256,151 -8783,1456407,194 -8784,1456601,177 -8785,1456778,157 -8786,1456935,161 -8787,1457096,155 -8788,1457251,153 -8789,1457404,170 -8790,1457574,170 -8791,1457744,174 -8792,1457918,156 -8793,1458074,235 -8794,1458309,129 -8795,1458438,148 -8796,1458586,232 -8797,1458818,231 -8798,1459049,174 -8799,1459223,193 -8800,1459416,166 -8801,1459582,187 -8802,1459769,149 -8803,1459918,187 -8804,1460105,175 -8805,1460280,138 -8806,1460418,138 -8807,1460556,152 -8808,1460708,196 -8809,1460904,196 -8810,1461100,140 -8811,1461240,152 -8812,1461392,175 -8813,1461567,229 -8814,1461796,222 -8815,1462018,222 -8816,1462240,158 -8817,1462398,192 -8818,1462590,176 -8819,1462766,178 -8820,1462944,129 -8821,1463073,172 -8822,1463245,133 -8823,1463378,158 -8824,1463536,297 -8825,1463833,156 -8826,1463989,140 -8827,1464129,145 -8828,1464274,172 -8829,1464446,125 -8830,1464571,203 -8831,1464774,158 -8832,1464932,128 -8833,1465060,152 -8834,1465212,161 -8835,1465373,149 -8836,1465522,198 -8837,1465720,172 -8838,1465892,132 -8839,1466024,170 -8840,1466194,134 -8841,1466328,151 -8842,1466479,188 -8843,1466667,204 -8844,1466871,160 -8845,1467031,156 -8846,1467187,124 -8847,1467311,136 -8848,1467447,170 -8849,1467617,170 -8850,1467787,128 -8851,1467915,195 -8852,1468110,166 -8853,1468276,166 -8854,1468442,162 -8855,1468604,161 -8856,1468765,173 -8857,1468938,160 -8858,1469098,139 -8859,1469237,212 -8860,1469449,172 -8861,1469621,186 -8862,1469807,214 -8863,1470021,154 -8864,1470175,163 -8865,1470338,231 -8866,1470569,186 -8867,1470755,181 -8868,1470936,127 -8869,1471063,153 -8870,1471216,203 -8871,1471419,161 -8872,1471580,115 -8873,1471695,163 -8874,1471858,161 -8875,1472019,222 -8876,1472241,190 -8877,1472431,168 -8878,1472599,139 -8879,1472738,153 -8880,1472891,178 -8881,1473069,115 -8882,1473184,160 -8883,1473344,123 -8884,1473467,147 -8885,1473614,159 -8886,1473773,169 -8887,1473942,170 -8888,1474112,177 -8889,1474289,180 -8890,1474469,172 -8891,1474641,157 -8892,1474798,138 -8893,1474936,170 -8894,1475106,170 -8895,1475276,222 -8896,1475498,286 -8897,1475784,153 -8898,1475937,198 -8899,1476135,179 -8900,1476314,117 -8901,1476431,197 -8902,1476628,142 -8903,1476770,175 -8904,1476945,162 -8905,1477107,149 -8906,1477256,174 -8907,1477430,139 -8908,1477569,164 -8909,1477733,207 -8910,1477940,213 -8911,1478153,176 -8912,1478329,137 -8913,1478466,162 -8914,1478628,233 -8915,1478861,157 -8916,1479018,145 -8917,1479163,232 -8918,1479395,138 -8919,1479533,161 -8920,1479694,301 -8921,1479995,203 -8922,1480198,153 -8923,1480351,162 -8924,1480513,163 -8925,1480676,155 -8926,1480831,154 -8927,1480985,137 -8928,1481122,176 -8929,1481298,141 -8930,1481439,158 -8931,1481597,151 -8932,1481748,205 -8933,1481953,187 -8934,1482140,269 -8935,1482409,156 -8936,1482565,212 -8937,1482777,159 -8938,1482936,150 -8939,1483086,125 -8940,1483211,210 -8941,1483421,157 -8942,1483578,168 -8943,1483746,143 -8944,1483889,168 -8945,1484057,55 -8946,1484112,142 -8947,1484254,169 -8948,1484423,176 -8949,1484599,167 -8950,1484766,181 -8951,1484947,138 -8952,1485085,152 -8953,1485237,148 -8954,1485385,166 -8955,1485551,166 -8956,1485717,138 -8957,1485855,138 -8958,1485993,163 -8959,1486156,143 -8960,1486299,203 -8961,1486502,193 -8962,1486695,159 -8963,1486854,185 -8964,1487039,170 -8965,1487209,170 -8966,1487379,157 -8967,1487536,226 -8968,1487762,232 -8969,1487994,175 -8970,1488169,145 -8971,1488314,147 -8972,1488461,182 -8973,1488643,152 -8974,1488795,130 -8975,1488925,176 -8976,1489101,192 -8977,1489293,187 -8978,1489480,120 -8979,1489600,187 -8980,1489787,166 -8981,1489953,166 -8982,1490119,178 -8983,1490297,155 -8984,1490452,115 -8985,1490567,134 -8986,1490701,141 -8987,1490842,163 -8988,1491005,143 -8989,1491148,170 -8990,1491318,205 -8991,1491523,269 -8992,1491792,145 -8993,1491937,165 -8994,1492102,175 -8995,1492277,117 -8996,1492394,196 -8997,1492590,133 -8998,1492723,198 -8999,1492921,190 -9000,1493111,229 -9001,1493340,134 -9002,1493474,184 -9003,1493658,117 -9004,1493775,144 -9005,1493919,144 -9006,1494063,179 -9007,1494242,205 -9008,1494447,190 -9009,1494637,161 -9010,1494798,120 -9011,1494918,170 -9012,1495088,170 -9013,1495258,183 -9014,1495441,144 -9015,1495585,156 -9016,1495741,136 -9017,1495877,159 -9018,1496036,175 -9019,1496211,173 -9020,1496384,124 -9021,1496508,145 -9022,1496653,157 -9023,1496810,140 -9024,1496950,191 -9025,1497141,276 -9026,1497417,156 -9027,1497573,111 -9028,1497684,192 -9029,1497876,173 -9030,1498049,121 -9031,1498170,172 -9032,1498342,140 -9033,1498482,219 -9034,1498701,55 -9035,1498756,194 -9036,1498950,137 -9037,1499087,202 -9038,1499289,201 -9039,1499490,220 -9040,1499710,122 -9041,1499832,127 -9042,1499959,146 -9043,1500105,189 -9044,1500294,168 -9045,1500462,214 -9046,1500676,145 -9047,1500821,194 -9048,1501015,126 -9049,1501141,258 -9050,1501399,225 -9051,1501624,146 -9052,1501770,134 -9053,1501904,170 -9054,1502074,170 -9055,1502244,172 -9056,1502416,191 -9057,1502607,152 -9058,1502759,149 -9059,1502908,222 -9060,1503130,175 -9061,1503305,149 -9062,1503454,229 -9063,1503683,140 -9064,1503823,173 -9065,1503996,152 -9066,1504148,158 -9067,1504306,153 -9068,1504459,120 -9069,1504579,141 -9070,1504720,159 -9071,1504879,210 -9072,1505089,135 -9073,1505224,171 -9074,1505395,260 -9075,1505655,154 -9076,1505809,147 -9077,1505956,147 -9078,1506103,173 -9079,1506276,180 -9080,1506456,145 -9081,1506601,237 -9082,1506838,118 -9083,1506956,153 -9084,1507109,144 -9085,1507253,175 -9086,1507428,124 -9087,1507552,156 -9088,1507708,159 -9089,1507867,236 -9090,1508103,226 -9091,1508329,156 -9092,1508485,143 -9093,1508628,125 -9094,1508753,129 -9095,1508882,139 -9096,1509021,160 -9097,1509181,292 -9098,1509473,149 -9099,1509622,201 -9100,1509823,55 -9101,1509878,176 -9102,1510054,135 -9103,1510189,156 -9104,1510345,210 -9105,1510555,180 -9106,1510735,160 -9107,1510895,138 -9108,1511033,165 -9109,1511198,147 -9110,1511345,227 -9111,1511572,162 -9112,1511734,130 -9113,1511864,221 -9114,1512085,155 -9115,1512240,168 -9116,1512408,149 -9117,1512557,202 -9118,1512759,212 -9119,1512971,160 -9120,1513131,185 -9121,1513316,175 -9122,1513491,147 -9123,1513638,147 -9124,1513785,171 -9125,1513956,154 -9126,1514110,133 -9127,1514243,181 -9128,1514424,152 -9129,1514576,231 -9130,1514807,177 -9131,1514984,170 -9132,1515154,170 -9133,1515324,143 -9134,1515467,140 -9135,1515607,147 -9136,1515754,199 -9137,1515953,218 -9138,1516171,180 -9139,1516351,135 -9140,1516486,138 -9141,1516624,166 -9142,1516790,203 -9143,1516993,180 -9144,1517173,202 -9145,1517375,160 -9146,1517535,189 -9147,1517724,152 -9148,1517876,159 -9149,1518035,157 -9150,1518192,140 -9151,1518332,144 -9152,1518476,168 -9153,1518644,134 -9154,1518778,249 -9155,1519027,151 -9156,1519178,130 -9157,1519308,204 -9158,1519512,153 -9159,1519665,129 -9160,1519794,142 -9161,1519936,248 -9162,1520184,149 -9163,1520333,226 -9164,1520559,161 -9165,1520720,239 -9166,1520959,199 -9167,1521158,161 -9168,1521319,156 -9169,1521475,146 -9170,1521621,181 -9171,1521802,223 -9172,1522025,153 -9173,1522178,155 -9174,1522333,175 -9175,1522508,159 -9176,1522667,118 -9177,1522785,147 -9178,1522932,197 -9179,1523129,134 -9180,1523263,191 -9181,1523454,156 -9182,1523610,163 -9183,1523773,120 -9184,1523893,149 -9185,1524042,159 -9186,1524201,173 -9187,1524374,145 -9188,1524519,179 -9189,1524698,203 -9190,1524901,139 -9191,1525040,123 -9192,1525163,193 -9193,1525356,146 -9194,1525502,170 -9195,1525672,170 -9196,1525842,146 -9197,1525988,147 -9198,1526135,147 -9199,1526282,156 -9200,1526438,242 -9201,1526680,173 -9202,1526853,167 -9203,1527020,160 -9204,1527180,124 -9205,1527304,135 -9206,1527439,203 -9207,1527642,55 -9208,1527697,215 -9209,1527912,188 -9210,1528100,135 -9211,1528235,154 -9212,1528389,162 -9213,1528551,162 -9214,1528713,135 -9215,1528848,208 -9216,1529056,144 -9217,1529200,173 -9218,1529373,140 -9219,1529513,138 -9220,1529651,138 -9221,1529789,139 -9222,1529928,185 -9223,1530113,130 -9224,1530243,150 -9225,1530393,146 -9226,1530539,153 -9227,1530692,147 -9228,1530839,135 -9229,1530974,139 -9230,1531113,199 -9231,1531312,176 -9232,1531488,182 -9233,1531670,162 -9234,1531832,230 -9235,1532062,170 -9236,1532232,170 -9237,1532402,152 -9238,1532554,178 -9239,1532732,163 -9240,1532895,160 -9241,1533055,55 -9242,1533110,151 -9243,1533261,186 -9244,1533447,201 -9245,1533648,187 -9246,1533835,161 -9247,1533996,164 -9248,1534160,142 -9249,1534302,190 -9250,1534492,181 -9251,1534673,224 -9252,1534897,193 -9253,1535090,284 -9254,1535374,156 -9255,1535530,176 -9256,1535706,127 -9257,1535833,187 -9258,1536020,165 -9259,1536185,197 -9260,1536382,195 -9262,1536577,152 -9263,1536729,121 -9264,1536850,174 -9265,1537024,170 -9266,1537194,200 -9267,1537394,161 -9268,1537555,145 -9269,1537700,182 -9270,1537882,120 -9271,1538002,157 -9272,1538159,178 -9273,1538337,213 -9274,1538550,156 -9275,1538706,139 -9276,1538845,138 -9277,1538983,179 -9279,1539162,124 -9280,1539286,154 -9281,1539440,170 -9282,1539610,194 -9283,1539804,144 -9284,1539948,161 -9285,1540109,153 -9286,1540262,148 -9287,1540410,136 -9288,1540546,177 -9289,1540723,270 -9290,1540993,152 -9291,1541145,154 -9292,1541299,169 -9293,1541468,193 -9294,1541661,165 -9295,1541826,200 -9296,1542026,170 -9297,1542196,170 -9298,1542366,163 -9299,1542529,125 -9300,1542654,225 -9301,1542879,138 -9302,1543017,127 -9304,1543144,160 -9305,1543304,166 -9306,1543470,196 -9307,1543666,215 -9308,1543881,176 -9309,1544057,181 -9310,1544238,182 -9311,1544420,185 -9312,1544605,200 -9313,1544805,191 -9314,1544996,188 -9315,1545184,147 -9316,1545331,144 -9317,1545475,150 -9318,1545625,126 -9319,1545751,161 -9320,1545912,224 -9321,1546136,133 -9322,1546269,191 -9323,1546460,176 -9324,1546636,155 -9325,1546791,163 -9326,1546954,146 -9327,1547100,145 -9328,1547245,143 -9329,1547388,192 -9330,1547580,144 -9331,1547724,175 -9332,1547899,158 -9333,1548057,210 -9334,1548267,148 -9335,1548415,183 -9336,1548598,211 -9337,1548809,167 -9338,1548976,204 -9339,1549180,165 -9340,1549345,139 -9341,1549484,138 -9342,1549622,241 -9343,1549863,149 -9344,1550012,146 -9345,1550158,175 -9346,1550333,158 -9347,1550491,152 -9348,1550643,160 -9349,1550803,148 -9350,1550951,155 -9351,1551106,160 -9352,1551266,211 -9353,1551477,142 -9354,1551619,160 -9355,1551779,188 -9356,1551967,162 -9357,1552129,178 -9358,1552307,124 -9359,1552431,189 -9360,1552620,175 -9361,1552795,159 -9362,1552954,204 -9363,1553158,147 -9364,1553305,207 -9365,1553512,147 -9366,1553659,173 -9367,1553832,170 -9368,1554002,170 -9369,1554172,160 -9370,1554332,283 -9371,1554615,214 -9372,1554829,237 -9373,1555066,192 -9374,1555258,143 -9375,1555401,152 -9376,1555553,147 -9377,1555700,147 -9378,1555847,211 -9379,1556058,169 -9380,1556227,151 -9381,1556378,164 -9382,1556542,150 -9383,1556692,190 -9384,1556882,172 -9385,1557054,166 -9386,1557220,154 -9387,1557374,159 -9388,1557533,233 -9389,1557766,153 -9390,1557919,116 -9391,1558035,156 -9392,1558191,134 -9393,1558325,147 -9394,1558472,131 -9395,1558603,170 -9396,1558773,145 -9397,1558918,149 -9398,1559067,145 -9399,1559212,159 -9400,1559371,169 -9401,1559540,249 -9402,1559789,153 -9403,1559942,185 -9404,1560127,158 -9405,1560285,184 -9406,1560469,167 -9407,1560636,116 -9408,1560752,191 -9409,1560943,147 -9410,1561090,145 -9411,1561235,170 -9412,1561405,170 -9413,1561575,161 -9414,1561736,149 -9415,1561885,153 -9416,1562038,170 -9417,1562208,170 -9418,1562378,139 -9419,1562517,149 -9420,1562666,201 -9421,1562867,147 -9422,1563014,147 -9423,1563161,164 -9424,1563325,223 -9425,1563548,143 -9426,1563691,174 -9427,1563865,134 -9428,1563999,131 -9429,1564130,189 -9430,1564319,166 -9431,1564485,166 -9432,1564651,176 -9433,1564827,144 -9434,1564971,186 -9435,1565157,183 -9436,1565340,149 -9437,1565489,134 -9438,1565623,173 -9439,1565796,144 -9440,1565940,151 -9441,1566091,159 -9442,1566250,189 -9443,1566439,138 -9444,1566577,140 -9445,1566717,172 -9446,1566889,168 -9447,1567057,152 -9448,1567209,140 -9449,1567349,251 -9450,1567600,182 -9451,1567782,179 -9452,1567961,246 -9453,1568207,197 -9454,1568404,179 -9455,1568583,167 -9456,1568750,140 -9457,1568890,240 -9458,1569130,239 -9459,1569369,161 -9460,1569530,182 -9461,1569712,152 -9462,1569864,181 -9463,1570045,170 -9464,1570215,167 -9465,1570382,170 -9466,1570552,169 -9467,1570721,55 -9468,1570776,206 -9469,1570982,173 -9470,1571155,113 -9471,1571268,158 -9472,1571426,120 -9473,1571546,154 -9474,1571700,130 -9475,1571830,138 -9476,1571968,168 -9477,1572136,161 -9478,1572297,162 -9479,1572459,131 -9480,1572590,158 -9481,1572748,156 -9482,1572904,178 -9483,1573082,169 -9484,1573251,133 -9485,1573384,164 -9486,1573548,151 -9487,1573699,178 -9488,1573877,178 -9489,1574055,210 -9490,1574265,171 -9491,1574436,133 -9492,1574569,214 -9493,1574783,128 -9494,1574911,173 -9495,1575084,135 -9496,1575219,178 -9497,1575397,138 -9498,1575535,166 -9499,1575701,163 -9500,1575864,130 -9501,1575994,138 -9502,1576132,151 -9503,1576283,139 -9504,1576422,158 -9505,1576580,179 -9506,1576759,195 -9507,1576954,140 -9508,1577094,216 -9509,1577310,140 -9510,1577450,210 -9511,1577660,153 -9512,1577813,158 -9513,1577971,158 -9514,1578129,169 -9515,1578298,200 -9516,1578498,181 -9517,1578679,187 -9518,1578866,140 -9519,1579006,139 -9520,1579145,170 -9521,1579315,158 -9522,1579473,158 -9523,1579631,143 -9525,1579774,154 -9526,1579928,170 -9527,1580098,184 -9528,1580282,235 -9529,1580517,133 -9530,1580650,139 -9531,1580789,194 -9532,1580983,127 -9533,1581110,163 -9534,1581273,177 -9536,1581450,186 -9537,1581636,148 -9538,1581784,179 -9539,1581963,157 -9540,1582120,138 -9541,1582258,170 -9542,1582428,170 -9543,1582598,138 -9544,1582736,138 -9545,1582874,241 -9546,1583115,183 -9547,1583298,120 -9548,1583418,155 -9549,1583573,190 -9550,1583763,215 -9551,1583978,146 -9552,1584124,157 -9553,1584281,138 -9554,1584419,142 -9555,1584561,135 -9556,1584696,153 -9557,1584849,160 -9558,1585009,205 -9559,1585214,148 -9560,1585362,176 -9561,1585538,188 -9562,1585726,152 -9563,1585878,142 -9564,1586020,157 -9565,1586177,175 -9566,1586352,201 -9567,1586553,120 -9568,1586673,192 -9569,1586865,173 -9570,1587038,174 -9571,1587212,153 -9572,1587365,140 -9573,1587505,143 -9574,1587648,175 -9575,1587823,159 -9576,1587982,285 -9577,1588267,140 -9578,1588407,177 -9579,1588584,140 -9580,1588724,196 -9581,1588920,160 -9582,1589080,144 -9583,1589224,126 -9584,1589350,229 -9585,1589579,214 -9586,1589793,140 -9587,1589933,214 -9588,1590147,180 -9589,1590327,179 -9590,1590506,153 -9591,1590659,149 -9592,1590808,168 -9593,1590976,140 -9594,1591116,261 -9595,1591377,187 -9596,1591564,211 -9597,1591775,204 -9598,1591979,226 -9599,1592205,192 -9600,1592397,159 -9601,1592556,172 -9602,1592728,162 -9603,1592890,170 -9604,1593060,170 -9605,1593230,149 -9606,1593379,229 -9607,1593608,150 -9608,1593758,153 -9609,1593911,169 -9610,1594080,163 -9611,1594243,165 -9612,1594408,249 -9613,1594657,117 -9614,1594774,174 -9615,1594948,167 -9616,1595115,169 -9617,1595284,136 -9618,1595420,218 -9619,1595638,169 -9620,1595807,157 -9621,1595964,168 -9622,1596132,131 -9623,1596263,237 -9624,1596500,264 -9625,1596764,148 -9626,1596912,135 -9627,1597047,261 -9628,1597308,152 -9629,1597460,55 -9630,1597515,220 -9631,1597735,172 -9632,1597907,161 -9633,1598068,138 -9634,1598206,165 -9635,1598371,167 -9636,1598538,195 -9637,1598733,149 -9638,1598882,207 -9639,1599089,157 -9640,1599246,215 -9641,1599461,248 -9642,1599709,230 -9643,1599939,188 -9644,1600127,153 -9645,1600280,191 -9646,1600471,165 -9647,1600636,162 -9648,1600798,137 -9649,1600935,182 -9650,1601117,159 -9651,1601276,182 -9652,1601458,170 -9653,1601628,170 -9654,1601798,135 -9655,1601933,192 -9656,1602125,174 -9657,1602299,147 -9658,1602446,157 -9659,1602603,232 -9660,1602835,120 -9661,1602955,179 -9662,1603134,162 -9663,1603296,157 -9664,1603453,152 -9665,1603605,195 -9666,1603800,142 -9667,1603942,148 -9668,1604090,158 -9669,1604248,221 -9670,1604469,151 -9671,1604620,188 -9672,1604808,146 -9673,1604954,264 -9674,1605218,150 -9675,1605368,164 -9676,1605532,263 -9677,1605795,129 -9678,1605924,129 -9679,1606053,138 -9680,1606191,139 -9681,1606330,214 -9682,1606544,168 -9683,1606712,185 -9684,1606897,156 -9685,1607053,180 -9686,1607233,139 -9687,1607372,109 -9688,1607481,178 -9689,1607659,181 -9690,1607840,134 -9691,1607974,240 -9692,1608214,189 -9693,1608403,210 -9694,1608613,189 -9695,1608802,55 -9696,1608857,164 -9697,1609021,241 -9698,1609262,215 -9699,1609477,167 -9700,1609644,142 -9701,1609786,164 -9702,1609950,168 -9703,1610118,167 -9704,1610285,146 -9705,1610431,208 -9706,1610639,126 -9707,1610765,201 -9708,1610966,139 -9709,1611105,151 -9710,1611256,153 -9711,1611409,165 -9712,1611574,207 -9713,1611781,147 -9714,1611928,147 -9715,1612075,211 -9716,1612286,134 -9717,1612420,205 -9718,1612625,170 -9719,1612795,182 -9721,1612977,172 -9722,1613149,147 -9723,1613296,146 -9724,1613442,210 -9725,1613652,163 -9726,1613815,220 -9727,1614035,228 -9728,1614263,161 -9729,1614424,132 -9730,1614556,153 -9731,1614709,224 -9732,1614933,218 -9733,1615151,120 -9734,1615271,132 -9735,1615403,181 -9736,1615584,120 -9737,1615704,191 -9738,1615895,170 -9739,1616065,170 -9740,1616235,142 -9741,1616377,149 -9742,1616526,159 -9743,1616685,154 -9744,1616839,164 -9745,1617003,120 -9746,1617123,168 -9747,1617291,180 -9748,1617471,161 -9749,1617632,145 -9750,1617777,145 -9751,1617922,135 -9752,1618057,167 -9753,1618224,128 -9754,1618352,215 -9755,1618567,181 -9756,1618748,178 -9757,1618926,207 -9758,1619133,214 -9759,1619347,222 -9760,1619569,140 -9761,1619709,178 -9762,1619887,219 -9763,1620106,188 -9764,1620294,143 -9765,1620437,144 -9766,1620581,172 -9767,1620753,162 -9768,1620915,205 -9769,1621120,220 -9770,1621340,139 -9771,1621479,182 -9772,1621661,172 -9773,1621833,191 -9774,1622024,272 -9775,1622296,168 -9776,1622464,134 -9777,1622598,134 -9778,1622732,174 -9779,1622906,176 -9780,1623082,164 -9781,1623246,134 -9782,1623380,147 -9783,1623527,172 -9784,1623699,208 -9785,1623907,148 -9786,1624055,164 -9787,1624219,164 -9788,1624383,176 -9789,1624559,154 -9790,1624713,163 -9791,1624876,170 -9792,1625046,196 -9793,1625242,147 -9794,1625389,147 -9795,1625536,160 -9796,1625696,160 -9797,1625856,132 -9798,1625988,253 -9799,1626241,167 -9800,1626408,175 -9802,1626583,120 -9804,1626703,184 -9805,1626887,225 -9806,1627112,153 -9807,1627265,161 -9808,1627426,127 -9809,1627553,170 -9810,1627723,170 -9811,1627893,173 -9812,1628066,185 -9813,1628251,181 -9814,1628432,168 -9815,1628600,158 -9816,1628758,176 -9817,1628934,161 -9818,1629095,166 -9819,1629261,195 -9820,1629456,199 -9821,1629655,159 -9822,1629814,199 -9823,1630013,175 -9824,1630188,120 -9825,1630308,215 -9826,1630523,165 -9827,1630688,199 -9828,1630887,150 -9829,1631037,161 -9830,1631198,186 -9831,1631384,140 -9832,1631524,138 -9833,1631662,138 -9834,1631800,135 -9835,1631935,226 -9836,1632161,172 -9837,1632333,171 -9838,1632504,143 -9839,1632647,213 -9840,1632860,141 -9841,1633001,193 -9842,1633194,161 -9843,1633355,155 -9844,1633510,166 -9845,1633676,175 -9846,1633851,134 -9847,1633985,114 -9848,1634099,156 -9849,1634255,173 -9850,1634428,250 -9851,1634678,210 -9852,1634888,145 -9853,1635033,271 -9854,1635304,120 -9855,1635424,125 -9856,1635549,180 -9857,1635729,116 -9858,1635845,203 -9859,1636048,193 -9860,1636241,192 -9861,1636433,136 -9862,1636569,170 -9863,1636739,160 -9864,1636899,149 -9865,1637048,176 -9866,1637224,166 -9867,1637390,264 -9868,1637654,167 -9869,1637821,132 -9870,1637953,175 -9871,1638128,124 -9872,1638252,145 -9873,1638397,140 -9874,1638537,156 -9875,1638693,171 -9876,1638864,183 -9877,1639047,153 -9878,1639200,186 -9879,1639386,182 -9880,1639568,170 -9881,1639738,170 -9882,1639908,164 -9883,1640072,132 -9884,1640204,159 -9885,1640363,189 -9886,1640552,194 -9887,1640746,55 -9888,1640801,161 -9889,1640962,122 -9890,1641084,191 -9891,1641275,213 -9892,1641488,199 -9893,1641687,185 -9894,1641872,118 -9895,1641990,118 -9896,1642108,214 -9897,1642322,164 -9898,1642486,211 -9899,1642697,152 -9900,1642849,216 -9901,1643065,150 -9902,1643215,156 -9903,1643371,149 -9904,1643520,120 -9905,1643640,213 -9906,1643853,136 -9907,1643989,172 -9908,1644161,172 -9909,1644333,165 -9910,1644498,160 -9911,1644658,184 -9912,1644842,165 -9913,1645007,138 -9914,1645145,147 -9915,1645292,120 -9916,1645412,206 -9917,1645618,218 -9918,1645836,201 -9919,1646037,241 -9920,1646278,127 -9921,1646405,166 -9922,1646571,164 -9923,1646735,175 -9924,1646910,156 -9925,1647066,250 -9926,1647316,166 -9927,1647482,166 -9928,1647648,141 -9929,1647789,176 -9930,1647965,170 -9931,1648135,170 -9932,1648305,140 -9933,1648445,157 -9934,1648602,150 -9935,1648752,133 -9936,1648885,119 -9937,1649004,156 -9938,1649160,149 -9939,1649309,227 -9940,1649536,148 -9941,1649684,201 -9942,1649885,193 -9943,1650078,222 -9944,1650300,208 -9945,1650508,154 -9946,1650662,201 -9947,1650863,163 -9948,1651026,150 -9949,1651176,220 -9950,1651396,154 -9951,1651550,209 -9952,1651759,176 -9953,1651935,220 -9954,1652155,152 -9955,1652307,113 -9956,1652420,149 -9957,1652569,150 -9958,1652719,195 -9959,1652914,217 -9960,1653131,185 -9961,1653316,156 -9962,1653472,254 -9963,1653726,210 -9964,1653936,177 -9965,1654113,195 -9966,1654308,131 -9967,1654439,178 -9968,1654617,170 -9969,1654787,173 -9970,1654960,139 -9971,1655099,124 -9972,1655223,158 -9973,1655381,173 -9974,1655554,166 -9975,1655720,180 -9976,1655900,328 -9977,1656228,131 -9978,1656359,165 -9979,1656524,209 -9980,1656733,187 -9981,1656920,166 -9982,1657086,169 -9983,1657255,148 -9984,1657403,217 -9985,1657620,138 -9986,1657758,158 -9987,1657916,182 -9988,1658098,174 -9989,1658272,137 -9990,1658409,145 -9991,1658554,161 -9992,1658715,116 -9993,1658831,161 -9994,1658992,145 -9995,1659137,165 -9996,1659302,170 -9997,1659472,170 -9998,1659642,166 -9999,1659808,152 -10000,1659960,166 -10001,1660126,128 -10002,1660254,137 -10003,1660391,243 -10004,1660634,181 -10005,1660815,179 -10006,1660994,162 -10007,1661156,188 -10008,1661344,209 -10009,1661553,229 -10010,1661782,197 -10011,1661979,173 -10012,1662152,163 -10013,1662315,179 -10014,1662494,154 -10015,1662648,170 -10016,1662818,186 -10017,1663004,213 -10018,1663217,144 -10232,1663361,180 -10858,1663541,170 -10927,1663711,149 -11638,1663860,133 -12288,1663993,207 -12289,1664200,113 -12290,1664313,160 -12291,1664473,138 -12292,1664611,185 -12293,1664796,162 -12294,1664958,204 -12295,1665162,133 -12296,1665295,151 -12297,1665446,154 -12298,1665600,164 -12299,1665764,187 -12300,1665951,151 -12301,1666102,208 -12302,1666310,144 -12303,1666454,166 -12304,1666620,222 -12305,1666842,150 -12306,1666992,171 -12307,1667163,137 -12308,1667300,137 -12309,1667437,141 -12310,1667578,139 -12311,1667717,158 -12312,1667875,193 -12313,1668068,170 -12314,1668238,156 -12315,1668394,172 -12316,1668566,167 -12317,1668733,148 -12318,1668881,172 -12319,1669053,159 -12320,1669212,132 -12321,1669344,211 -12322,1669555,210 -12323,1669765,177 -12324,1669942,170 -12325,1670112,213 -12326,1670325,146 -12327,1670471,153 -12328,1670624,158 -12329,1670782,172 -12330,1670954,208 -12331,1671162,146 -12332,1671308,166 -12333,1671474,172 -12334,1671646,141 -12335,1671787,159 -12336,1671946,157 -12337,1672103,173 -12338,1672276,143 -12339,1672419,190 -12340,1672609,157 -12341,1672766,163 -12342,1672929,179 -12343,1673108,168 -12344,1673276,123 -12345,1673399,142 -12346,1673541,116 -12347,1673657,213 -12348,1673870,171 -12349,1674041,141 -12350,1674182,129 -12351,1674311,162 -12352,1674473,170 -12353,1674643,198 -12354,1674841,161 -12355,1675002,173 -12356,1675175,142 -12357,1675317,177 -12358,1675494,189 -12359,1675683,177 -12360,1675860,164 -12361,1676024,168 -12362,1676192,137 -12363,1676329,156 -12364,1676485,167 -12365,1676652,118 -12366,1676770,155 -12367,1676925,207 -12368,1677132,154 -12369,1677286,181 -12370,1677467,158 -12371,1677625,128 -12372,1677753,211 -12373,1677964,172 -12374,1678136,131 -12375,1678267,144 -12376,1678411,131 -12377,1678542,163 -12378,1678705,154 -12379,1678859,146 -12380,1679005,172 -12381,1679177,174 -12382,1679351,124 -12383,1679475,123 -12384,1679598,148 -12385,1679746,148 -12386,1679894,166 -12387,1680060,163 -12388,1680223,182 -12389,1680405,120 -12390,1680525,130 -12391,1680655,206 -12392,1680861,189 -12393,1681050,222 -12394,1681272,199 -12395,1681471,159 -12396,1681630,144 -12397,1681774,164 -12398,1681938,141 -12399,1682079,200 -12400,1682279,158 -12401,1682437,170 -12402,1682607,183 -12403,1682790,168 -12404,1682958,151 -12405,1683109,126 -12406,1683235,152 -12407,1683387,142 -12408,1683529,170 -12409,1683699,135 -12410,1683834,217 -12411,1684051,170 -12412,1684221,135 -12413,1684356,143 -12414,1684499,179 -12415,1684678,132 -12416,1684810,170 -12417,1684980,172 -12418,1685152,214 -12419,1685366,139 -12420,1685505,189 -12421,1685694,170 -12422,1685864,163 -12423,1686027,139 -12424,1686166,124 -12425,1686290,169 -12426,1686459,150 -12427,1686609,137 -12428,1686746,159 -12429,1686905,155 -12430,1687060,182 -12431,1687242,167 -12432,1687409,157 -12433,1687566,209 -12434,1687775,139 -12435,1687914,148 -12436,1688062,170 -12437,1688232,211 -12438,1688443,170 -12439,1688613,113 -12440,1688726,189 -12441,1688915,150 -12442,1689065,155 -12443,1689220,127 -12444,1689347,171 -12445,1689518,173 -12446,1689691,148 -12447,1689839,143 -12448,1689982,174 -12449,1690156,178 -12450,1690334,157 -12451,1690491,170 -12452,1690661,187 -12453,1690848,144 -12454,1690992,158 -12455,1691150,181 -12456,1691331,160 -12457,1691491,163 -12458,1691654,225 -12459,1691879,203 -12460,1692082,168 -12461,1692250,174 -12462,1692424,155 -12463,1692579,155 -12464,1692734,167 -12465,1692901,126 -12466,1693027,139 -12467,1693166,173 -12468,1693339,158 -12469,1693497,167 -12470,1693664,170 -12471,1693834,183 -12472,1694017,158 -12473,1694175,124 -12474,1694299,212 -12475,1694511,142 -12476,1694653,131 -12477,1694784,149 -12478,1694933,169 -12479,1695102,134 -12480,1695236,159 -12481,1695395,141 -12482,1695536,112 -12483,1695648,159 -12484,1695807,171 -12485,1695978,165 -12486,1696143,161 -12487,1696304,195 -12488,1696499,129 -12489,1696628,124 -12490,1696752,141 -12491,1696893,174 -12492,1697067,144 -12493,1697211,161 -12494,1697372,133 -12495,1697505,151 -12496,1697656,146 -12497,1697802,149 -12498,1697951,201 -12499,1698152,159 -12500,1698311,154 -12501,1698465,133 -12502,1698598,140 -12503,1698738,167 -12504,1698905,129 -12505,1699034,186 -12506,1699220,190 -12507,1699410,176 -12508,1699586,209 -12509,1699795,169 -12510,1699964,148 -12511,1700112,193 -12512,1700305,164 -12513,1700469,189 -12514,1700658,183 -12515,1700841,161 -12516,1701002,147 -12517,1701149,151 -12518,1701300,163 -12519,1701463,165 -12520,1701628,141 -12521,1701769,212 -12522,1701981,180 -12523,1702161,184 -12524,1702345,120 -12525,1702465,183 -12526,1702648,185 -12527,1702833,163 -12528,1702996,169 -12529,1703165,178 -12530,1703343,170 -12531,1703513,141 -12532,1703654,161 -12533,1703815,151 -12534,1703966,158 -12535,1704124,131 -12536,1704255,190 -12537,1704445,188 -12538,1704633,157 -12539,1704790,147 -12540,1704937,172 -12541,1705109,171 -12542,1705280,117 -12543,1705397,207 -12858,1705604,122 -13164,1705726,167 -13553,1705893,155 -13618,1706048,174 -13664,1706222,144 -14072,1706366,166 -14078,1706532,131 -14189,1706663,178 -14263,1706841,145 -15000,1706986,170 -15001,1707156,170 -15002,1707326,170 -15003,1707496,170 -15004,1707666,170 -15005,1707836,146 -15023,1707982,153 -15557,1708135,236 -15681,1708371,144 -16097,1708515,120 -16384,1708635,182 -16385,1708817,219 -16386,1709036,162 -16387,1709198,222 -16388,1709420,131 -16389,1709551,145 -16390,1709696,235 -16391,1709931,147 -16392,1710078,210 -16393,1710288,190 -16394,1710478,175 -16395,1710653,158 -16396,1710811,169 -16397,1710980,174 -16398,1711154,140 -16399,1711294,154 -16400,1711448,159 -16401,1711607,170 -16402,1711777,137 -16403,1711914,214 -16404,1712128,127 -16405,1712255,163 -16406,1712418,203 -16407,1712621,167 -16408,1712788,157 -16409,1712945,157 -16410,1713102,173 -16411,1713275,162 -16412,1713437,158 -16413,1713595,161 -16414,1713756,122 -16415,1713878,193 -16416,1714071,154 -16417,1714225,142 -16418,1714367,159 -16419,1714526,152 -16420,1714678,133 -16421,1714811,158 -16422,1714969,164 -16423,1715133,161 -16424,1715294,190 -16425,1715484,108 -16426,1715592,148 -16427,1715740,192 -16428,1715932,190 -16429,1716122,169 -16430,1716291,175 -16431,1716466,166 -16432,1716632,126 -16433,1716758,169 -16434,1716927,183 -16435,1717110,173 -16436,1717283,150 -16437,1717433,124 -16438,1717557,146 -16439,1717703,146 -16440,1717849,212 -16441,1718061,191 -16442,1718252,162 -16443,1718414,199 -16444,1718613,132 -16445,1718745,154 -16446,1718899,158 -16447,1719057,199 -16448,1719256,151 -16449,1719407,124 -16450,1719531,127 -16451,1719658,208 -16452,1719866,217 -16453,1720083,158 -16454,1720241,181 -16455,1720422,149 -16456,1720571,173 -16457,1720744,176 -16458,1720920,198 -16459,1721118,161 -16460,1721279,146 -16461,1721425,185 -16462,1721610,143 -16463,1721753,188 -16464,1721941,149 -16465,1722090,137 -16466,1722227,153 -16467,1722380,144 -16468,1722524,172 -16469,1722696,152 -16470,1722848,147 -16471,1722995,178 -16472,1723173,133 -16473,1723306,176 -16474,1723482,193 -16475,1723675,177 -16476,1723852,215 -16477,1724067,138 -16478,1724205,132 -16479,1724337,188 -16480,1724525,185 -16481,1724710,251 -16482,1724961,188 -16483,1725149,155 -16484,1725304,167 -16485,1725471,136 -16486,1725607,162 -16487,1725769,161 -16488,1725930,147 -16489,1726077,156 -16490,1726233,174 -16491,1726407,125 -16492,1726532,141 -16493,1726673,154 -16494,1726827,133 -16495,1726960,140 -16496,1727100,187 -16497,1727287,149 -16498,1727436,164 -16499,1727600,152 -16500,1727752,175 -16501,1727927,178 -16502,1728105,177 -16503,1728282,201 -16504,1728483,162 -16505,1728645,212 -16506,1728857,173 -16507,1729030,202 -16508,1729232,157 -16509,1729389,164 -16510,1729553,161 -16511,1729714,115 -16512,1729829,151 -16513,1729980,161 -16514,1730141,173 -16515,1730314,176 -16516,1730490,150 -16517,1730640,139 -16518,1730779,154 -16519,1730933,175 -16520,1731108,163 -16521,1731271,181 -16522,1731452,168 -16523,1731620,154 -16524,1731774,142 -16525,1731916,174 -16526,1732090,138 -16527,1732228,147 -16528,1732375,153 -16529,1732528,173 -16530,1732701,170 -16531,1732871,193 -16532,1733064,156 -16533,1733220,208 -16534,1733428,139 -16535,1733567,157 -16536,1733724,140 -16537,1733864,161 -16538,1734025,158 -16539,1734183,160 -16540,1734343,123 -16541,1734466,151 -16542,1734617,211 -16543,1734828,151 -16544,1734979,160 -16545,1735139,145 -16546,1735284,199 -16547,1735483,177 -16548,1735660,145 -16549,1735805,155 -16550,1735960,130 -16551,1736090,168 -16552,1736258,198 -16553,1736456,147 -16554,1736603,131 -16555,1736734,161 -16556,1736895,158 -16557,1737053,150 -16558,1737203,158 -16559,1737361,158 -16560,1737519,175 -16561,1737694,147 -16562,1737841,128 -16563,1737969,142 -16564,1738111,129 -16565,1738240,208 -16566,1738448,155 -16567,1738603,160 -16568,1738763,139 -16569,1738902,146 -16570,1739048,172 -16571,1739220,186 -16572,1739406,151 -16573,1739557,168 -16574,1739725,175 -16575,1739900,178 -16576,1740078,165 -16577,1740243,213 -16578,1740456,184 -16579,1740640,163 -16580,1740803,156 -16581,1740959,170 -16582,1741129,159 -16583,1741288,199 -16584,1741487,175 -16585,1741662,145 -16586,1741807,217 -16587,1742024,153 -16588,1742177,193 -16589,1742370,183 -16590,1742553,162 -16591,1742715,157 -16592,1742872,174 -16593,1743046,177 -16594,1743223,152 -16595,1743375,191 -16596,1743566,148 -16597,1743714,172 -16598,1743886,144 -16599,1744030,138 -16600,1744168,210 -16601,1744378,162 -16602,1744540,173 -16603,1744713,191 -16604,1744904,148 -16605,1745052,146 -16606,1745198,150 -16607,1745348,161 -16608,1745509,155 -16609,1745664,161 -16610,1745825,181 -16611,1746006,193 -16612,1746199,161 -16613,1746360,155 -16614,1746515,127 -16615,1746642,214 -16616,1746856,174 -16617,1747030,148 -16618,1747178,177 -16619,1747355,167 -16620,1747522,168 -16621,1747690,171 -16622,1747861,140 -16623,1748001,144 -16624,1748145,172 -16625,1748317,163 -16626,1748480,170 -16627,1748650,121 -16628,1748771,172 -16629,1748943,138 -16630,1749081,203 -16631,1749284,149 -16632,1749433,163 -16633,1749596,140 -16634,1749736,153 -16635,1749889,208 -16636,1750097,169 -16637,1750266,118 -16638,1750384,155 -16639,1750539,161 -16820,1750700,245 -16978,1750945,167 -17407,1751112,135 -17665,1751247,167 -17995,1751414,192 -19762,1751606,176 -20480,1751782,179 -20481,1751961,143 -20482,1752104,128 -20483,1752232,138 -20484,1752370,148 -20486,1752518,113 -20487,1752631,215 -20488,1752846,172 -20489,1753018,169 -20490,1753187,189 -20491,1753376,170 -20492,1753546,150 -20493,1753696,166 -20494,1753862,165 -20495,1754027,164 -20496,1754191,169 -20498,1754360,129 -20499,1754489,169 -20500,1754658,171 -20501,1754829,155 -20502,1754984,163 -20503,1755147,138 -20504,1755285,163 -20505,1755448,163 -20506,1755611,146 -20507,1755757,150 -20508,1755907,162 -20510,1756069,175 -20511,1756244,170 -20512,1756414,181 -20513,1756595,161 -20514,1756756,201 -20515,1756957,174 -20516,1757131,143 -20518,1757274,145 -20519,1757419,164 -20520,1757583,163 -20521,1757746,160 -20522,1757906,170 -20523,1758076,179 -20524,1758255,202 -20525,1758457,177 -20526,1758634,150 -20527,1758784,170 -20528,1758954,150 -20529,1759104,170 -20530,1759274,164 -20531,1759438,152 -20534,1759590,138 -20535,1759728,166 -20536,1759894,185 -20537,1760079,153 -20538,1760232,172 -20539,1760404,160 -20540,1760564,189 -20542,1760753,170 -20543,1760923,142 -20544,1761065,188 -20545,1761253,188 -20546,1761441,177 -20547,1761618,167 -20548,1761785,154 -20549,1761939,210 -20550,1762149,218 -20551,1762367,55 -20552,1762422,146 -20553,1762568,142 -20554,1762710,134 -20555,1762844,127 -20556,1762971,151 -20557,1763122,186 -20558,1763308,150 -20559,1763458,162 -20560,1763620,163 -20561,1763783,170 -20562,1763953,151 -20563,1764104,162 -20564,1764266,170 -20565,1764436,118 -20566,1764554,139 -20567,1764693,164 -20568,1764857,190 -20569,1765047,150 -20570,1765197,159 -20571,1765356,181 -20572,1765537,142 -20574,1765679,154 -20575,1765833,137 -20576,1765970,144 -20578,1766114,185 -20579,1766299,144 -20580,1766443,142 -20581,1766585,170 -20582,1766755,197 -20583,1766952,140 -20584,1767092,178 -20585,1767270,163 -20586,1767433,145 -20587,1767578,127 -20588,1767705,154 -20589,1767859,171 -20590,1768030,184 -20591,1768214,117 -20592,1768331,224 -20593,1768555,160 -20594,1768715,148 -20595,1768863,170 -20596,1769033,160 -20597,1769193,148 -20598,1769341,168 -20599,1769509,187 -20600,1769696,164 -20601,1769860,55 -20602,1769915,158 -20603,1770073,180 -20604,1770253,132 -20605,1770385,110 -20606,1770495,150 -20607,1770645,175 -20608,1770820,170 -20609,1770990,167 -20610,1771157,180 -20611,1771337,133 -20612,1771470,139 -20614,1771609,148 -20615,1771757,166 -20616,1771923,153 -20617,1772076,169 -20619,1772245,175 -20620,1772420,141 -20621,1772561,202 -20622,1772763,142 -20623,1772905,165 -20624,1773070,134 -20625,1773204,139 -20626,1773343,175 -20627,1773518,130 -20628,1773648,167 -20629,1773815,157 -20630,1773972,176 -20631,1774148,177 -20632,1774325,133 -20633,1774458,160 -20634,1774618,185 -20635,1774803,126 -20636,1774929,128 -20637,1775057,149 -20638,1775206,197 -20639,1775403,160 -20640,1775563,183 -20641,1775746,160 -20642,1775906,164 -20643,1776070,181 -20644,1776251,138 -20645,1776389,213 -20646,1776602,127 -20647,1776729,170 -20648,1776899,151 -20649,1777050,167 -20650,1777217,175 -20651,1777392,151 -20652,1777543,173 -20653,1777716,185 -20654,1777901,141 -20655,1778042,142 -20656,1778184,187 -20657,1778371,148 -20658,1778519,124 -20659,1778643,158 -20660,1778801,198 -20661,1778999,134 -20662,1779133,211 -20663,1779344,201 -20664,1779545,163 -20665,1779708,165 -20666,1779873,156 -20667,1780029,146 -20668,1780175,159 -20669,1780334,164 -20670,1780498,143 -20671,1780641,210 -20672,1780851,136 -20673,1780987,170 -20674,1781157,278 -20676,1781435,108 -20677,1781543,157 -20678,1781700,244 -20680,1781944,167 -20681,1782111,134 -20682,1782245,167 -20683,1782412,118 -20684,1782530,167 -20685,1782697,118 -20686,1782815,191 -20687,1783006,245 -20688,1783251,149 -20689,1783400,170 -20690,1783570,156 -20691,1783726,177 -20692,1783903,206 -20693,1784109,147 -20694,1784256,130 -20695,1784386,118 -20696,1784504,175 -20697,1784679,220 -20698,1784899,161 -20699,1785060,176 -20700,1785236,190 -20701,1785426,173 -20702,1785599,158 -20703,1785757,143 -20705,1785900,217 -20706,1786117,164 -20707,1786281,147 -20708,1786428,120 -20710,1786548,155 -20711,1786703,197 -20712,1786900,152 -20714,1787052,159 -20715,1787211,185 -20716,1787396,117 -20717,1787513,139 -20718,1787652,166 -20719,1787818,141 -20720,1787959,170 -20721,1788129,170 -20722,1788299,145 -20723,1788444,217 -20724,1788661,159 -20726,1788820,192 -20727,1789012,203 -20728,1789215,189 -20729,1789404,164 -20730,1789568,145 -20731,1789713,129 -20732,1789842,204 -20733,1790046,184 -20734,1790230,123 -20735,1790353,177 -21016,1790530,179 -21679,1790709,187 -22791,1790896,176 -23097,1791072,234 -23729,1791306,221 -23811,1791527,132 -24576,1791659,124 -24577,1791783,143 -24578,1791926,194 -24579,1792120,166 -24580,1792286,181 -24581,1792467,161 -24582,1792628,164 -24583,1792792,148 -24584,1792940,148 -24585,1793088,156 -24586,1793244,175 -24587,1793419,125 -24588,1793544,143 -24589,1793687,143 -24590,1793830,171 -24591,1794001,141 -24592,1794142,173 -24593,1794315,160 -24594,1794475,164 -24595,1794639,148 -24596,1794787,164 -24597,1794951,149 -24598,1795100,141 -24599,1795241,132 -24600,1795373,169 -24601,1795542,167 -24602,1795709,151 -24603,1795860,149 -24604,1796009,169 -24605,1796178,172 -24606,1796350,134 -24607,1796484,153 -24608,1796637,162 -24609,1796799,175 -24610,1796974,156 -24611,1797130,165 -24612,1797295,168 -24613,1797463,182 -24614,1797645,157 -24615,1797802,193 -24616,1797995,168 -24617,1798163,165 -24618,1798328,219 -24619,1798547,138 -24620,1798685,167 -24621,1798852,165 -24622,1799017,153 -24623,1799170,156 -24624,1799326,149 -24625,1799475,126 -24626,1799601,140 -24627,1799741,147 -24628,1799888,134 -24629,1800022,176 -24630,1800198,185 -24631,1800383,160 -24632,1800543,199 -24633,1800742,175 -24634,1800917,189 -24635,1801106,132 -24636,1801238,164 -24637,1801402,129 -24638,1801531,156 -24639,1801687,146 -24640,1801833,135 -24641,1801968,172 -24642,1802140,139 -24643,1802279,158 -24644,1802437,162 -24645,1802599,151 -24646,1802750,145 -24647,1802895,156 -24648,1803051,139 -24649,1803190,152 -24650,1803342,153 -24651,1803495,150 -24652,1803645,142 -24653,1803787,159 -24654,1803946,184 -24655,1804130,139 -24656,1804269,136 -24657,1804405,156 -24658,1804561,222 -24659,1804783,166 -24660,1804949,136 -24661,1805085,148 -24662,1805233,164 -24663,1805397,168 -24664,1805565,192 -24665,1805757,169 -24666,1805926,157 -24667,1806083,173 -24668,1806256,156 -24669,1806412,151 -24670,1806563,173 -24671,1806736,187 -24672,1806923,190 -24673,1807113,177 -24674,1807290,149 -24675,1807439,177 -24676,1807616,136 -24677,1807752,190 -24678,1807942,136 -24679,1808078,161 -24680,1808239,163 -24681,1808402,187 -24682,1808589,192 -24683,1808781,140 -24684,1808921,137 -24685,1809058,175 -24686,1809233,171 -24687,1809404,199 -24688,1809603,156 -24689,1809759,137 -24690,1809896,190 -24691,1810086,172 -24692,1810258,152 -24693,1810410,138 -24694,1810548,219 -24695,1810767,158 -24696,1810925,163 -24697,1811088,166 -24698,1811254,120 -24699,1811374,147 -24700,1811521,154 -24701,1811675,163 -24702,1811838,142 -24703,1811980,160 -24704,1812140,161 -24705,1812301,153 -24706,1812454,176 -24707,1812630,156 -24708,1812786,157 -24709,1812943,142 -24710,1813085,190 -24711,1813275,165 -24712,1813440,167 -24713,1813607,131 -24714,1813738,137 -24715,1813875,171 -24716,1814046,153 -24717,1814199,150 -24718,1814349,207 -24719,1814556,197 -24720,1814753,186 -24721,1814939,162 -24722,1815101,145 -24723,1815246,127 -24724,1815373,168 -24725,1815541,156 -24726,1815697,151 -24727,1815848,148 -24728,1815996,149 -24729,1816145,144 -24730,1816289,128 -24731,1816417,151 -24732,1816568,162 -24733,1816730,154 -24734,1816884,233 -24735,1817117,163 -24736,1817280,191 -24737,1817471,147 -24738,1817618,172 -24739,1817790,165 -24740,1817955,154 -24741,1818109,165 -24742,1818274,163 -24743,1818437,147 -24744,1818584,109 -24745,1818693,124 -24746,1818817,176 -24747,1818993,155 -24748,1819148,169 -24749,1819317,155 -24750,1819472,151 -24751,1819623,161 -24752,1819784,161 -24753,1819945,157 -24754,1820102,151 -24755,1820253,184 -24756,1820437,147 -24757,1820584,120 -24758,1820704,151 -24759,1820855,153 -24760,1821008,139 -24761,1821147,150 -24762,1821297,153 -24763,1821450,185 -24764,1821635,214 -24765,1821849,144 -24766,1821993,143 -24767,1822136,160 -24768,1822296,129 -24769,1822425,159 -24770,1822584,121 -24771,1822705,163 -24772,1822868,147 -24773,1823015,138 -24774,1823153,116 -24775,1823269,166 -24776,1823435,182 -24777,1823617,144 -24778,1823761,178 -24779,1823939,166 -24780,1824105,169 -24781,1824274,142 -24782,1824416,165 -24783,1824581,155 -24784,1824736,179 -24785,1824915,161 -24786,1825076,265 -24787,1825341,160 -24788,1825501,154 -24789,1825655,150 -24790,1825805,193 -24791,1825998,195 -24792,1826193,172 -24793,1826365,154 -24794,1826519,156 -24795,1826675,133 -24796,1826808,219 -24797,1827027,143 -24798,1827170,144 -24799,1827314,185 -24800,1827499,201 -24801,1827700,163 -24802,1827863,179 -24803,1828042,154 -24804,1828196,172 -24805,1828368,159 -24806,1828527,179 -24807,1828706,118 -24808,1828824,196 -24809,1829020,219 -24810,1829239,139 -24811,1829378,171 -24812,1829549,169 -24813,1829718,168 -24814,1829886,138 -24815,1830024,195 -24816,1830219,166 -24817,1830385,143 -24818,1830528,136 -24819,1830664,204 -24820,1830868,193 -24821,1831061,149 -24822,1831210,206 -24823,1831416,145 -24824,1831561,209 -24825,1831770,171 -24826,1831941,188 -24827,1832129,151 -24828,1832280,193 -24829,1832473,128 -24830,1832601,170 -24831,1832771,152 -24945,1832923,120 -25664,1833043,170 -25766,1833213,153 -26187,1833366,243 -27534,1833609,219 -27550,1833828,118 -27552,1833946,230 -28155,1834176,196 -28848,1834372,162 -28851,1834534,163 -29122,1834697,166 -29132,1834863,241 -29581,1835104,243 -29664,1835347,175 -30002,1835522,120 -30177,1835642,143 -30878,1835785,131 -32250,1835916,166 -32342,1836082,231 -32552,1836313,165 -32768,1836478,161 -32769,1836639,175 -32770,1836814,190 -32771,1837004,169 -32772,1837173,175 -32773,1837348,171 -32774,1837519,170 -32775,1837689,145 -32776,1837834,191 -32777,1838025,165 -32778,1838190,160 -32779,1838350,164 -32780,1838514,164 -32781,1838678,128 -32782,1838806,161 -32783,1838967,154 -32784,1839121,161 -32785,1839282,186 -32786,1839468,175 -32787,1839643,160 -32788,1839803,191 -32789,1839994,159 -32790,1840153,171 -32791,1840324,143 -32792,1840467,165 -32793,1840632,179 -32794,1840811,153 -32795,1840964,143 -32796,1841107,183 -32797,1841290,168 -32798,1841458,143 -32799,1841601,156 -32800,1841757,180 -32801,1841937,149 -32802,1842086,134 -32803,1842220,224 -32804,1842444,144 -32805,1842588,135 -32806,1842723,174 -32807,1842897,176 -32808,1843073,177 -32809,1843250,166 -32810,1843416,188 -32811,1843604,173 -32812,1843777,188 -32813,1843965,135 -32814,1844100,157 -32815,1844257,177 -32816,1844434,167 -32817,1844601,136 -32818,1844737,160 -32819,1844897,165 -32820,1845062,121 -32821,1845183,157 -32822,1845340,213 -32823,1845553,151 -32824,1845704,193 -32825,1845897,154 -32826,1846051,147 -32827,1846198,163 -32828,1846361,139 -32829,1846500,153 -32830,1846653,139 -32831,1846792,166 -32832,1846958,172 -32833,1847130,153 -32834,1847283,167 -32835,1847450,157 -32836,1847607,161 -32837,1847768,168 -32838,1847936,161 -32839,1848097,149 -32840,1848246,158 -32841,1848404,162 -32842,1848566,131 -32843,1848697,159 -32844,1848856,144 -32845,1849000,162 -32846,1849162,156 -32847,1849318,189 -32848,1849507,157 -32849,1849664,137 -32850,1849801,177 -32851,1849978,149 -32852,1850127,175 -32853,1850302,129 -32854,1850431,177 -32855,1850608,128 -32856,1850736,169 -32857,1850905,173 -32858,1851078,181 -32859,1851259,155 -32860,1851414,175 -32861,1851589,147 -32862,1851736,171 -32863,1851907,175 -32864,1852082,170 -32865,1852252,174 -32866,1852426,136 -32867,1852562,197 -32868,1852759,159 -32869,1852918,170 -32870,1853088,188 -32871,1853276,169 -32872,1853445,163 -32873,1853608,165 -32874,1853773,164 -32875,1853937,152 -32876,1854089,175 -32877,1854264,157 -32878,1854421,156 -32879,1854577,168 -32880,1854745,145 -32881,1854890,151 -32882,1855041,159 -32883,1855200,148 -32884,1855348,145 -32885,1855493,137 -32886,1855630,111 -32887,1855741,175 -32888,1855916,176 -32889,1856092,190 -32890,1856282,168 -32891,1856450,168 -32892,1856618,142 -32893,1856760,152 -32894,1856912,178 -32895,1857090,155 -32896,1857245,158 -32897,1857403,171 -32898,1857574,173 -32899,1857747,161 -32900,1857908,171 -32901,1858079,191 -32902,1858270,166 -32903,1858436,170 -32904,1858606,167 -32905,1858773,170 -32906,1858943,166 -32907,1859109,176 -32908,1859285,169 -32909,1859454,151 -32910,1859605,167 -32911,1859772,157 -32912,1859929,176 -32913,1860105,166 -32914,1860271,158 -32915,1860429,144 -32916,1860573,135 -32917,1860708,170 -32918,1860878,174 -32919,1861052,155 -32920,1861207,184 -32921,1861391,150 -32922,1861541,182 -32923,1861723,149 -32924,1861872,138 -32925,1862010,131 -32926,1862141,138 -32927,1862279,157 -32928,1862436,174 -32929,1862610,147 -32930,1862757,182 -32931,1862939,132 -32932,1863071,157 -32933,1863228,149 -32934,1863377,157 -32935,1863534,204 -32936,1863738,157 -32937,1863895,145 -32938,1864040,127 -32939,1864167,166 -32940,1864333,179 -32941,1864512,152 -32942,1864664,162 -32943,1864826,137 -32944,1864963,165 -32945,1865128,131 -32946,1865259,177 -32947,1865436,177 -32948,1865613,140 -32949,1865753,152 -32950,1865905,142 -32951,1866047,139 -32952,1866186,193 -32953,1866379,175 -32954,1866554,188 -32955,1866742,155 -32956,1866897,179 -32957,1867076,178 -32958,1867254,140 -32959,1867394,193 -32960,1867587,153 -32961,1867740,149 -32962,1867889,197 -32963,1868086,197 -32964,1868283,173 -32965,1868456,179 -32966,1868635,237 -32967,1868872,124 -32968,1868996,147 -32969,1869143,172 -32970,1869315,168 -32971,1869483,156 -32972,1869639,172 -32973,1869811,166 -32974,1869977,187 -32975,1870164,168 -32976,1870332,173 -32977,1870505,168 -32978,1870673,157 -32979,1870830,134 -32980,1870964,174 -32981,1871138,157 -32982,1871295,148 -32983,1871443,148 -32984,1871591,168 -32985,1871759,159 -32986,1871918,195 -32987,1872113,154 -32988,1872267,149 -32989,1872416,143 -32990,1872559,147 -32991,1872706,174 -32992,1872880,156 -32993,1873036,157 -32994,1873193,167 -32995,1873360,212 -32996,1873572,167 -32997,1873739,137 -32998,1873876,160 -32999,1874036,199 -33000,1874235,156 -33001,1874391,153 -33002,1874544,179 -33003,1874723,147 -33004,1874870,177 -33005,1875047,171 -33006,1875218,155 -33007,1875373,133 -33008,1875506,176 -33009,1875682,140 -33010,1875822,152 -33011,1875974,157 -33012,1876131,171 -33013,1876302,139 -33014,1876441,167 -33015,1876608,151 -33016,1876759,133 -33017,1876892,153 -33018,1877045,131 -33019,1877176,143 -33020,1877319,146 -33021,1877465,160 -33022,1877625,163 -33023,1877788,211 -34464,1877999,55 -34917,1878054,120 -35651,1878174,163 -35856,1878337,139 -35924,1878476,142 -36090,1878618,183 -36174,1878801,146 -36314,1878947,172 -36594,1879119,151 -36864,1879270,168 -36865,1879438,196 -36866,1879634,117 -36867,1879751,118 -36868,1879869,172 -36869,1880041,191 -36870,1880232,148 -36871,1880380,200 -36872,1880580,167 -36873,1880747,193 -36874,1880940,224 -36875,1881164,199 -36876,1881363,164 -36877,1881527,162 -36878,1881689,223 -36879,1881912,188 -36880,1882100,174 -36881,1882274,140 -36882,1882414,168 -36883,1882582,194 -36884,1882776,179 -36885,1882955,174 -36886,1883129,112 -36887,1883241,155 -36888,1883396,183 -36889,1883579,167 -36890,1883746,147 -36891,1883893,150 -36892,1884043,134 -36893,1884177,140 -36894,1884317,150 -36895,1884467,159 -36896,1884626,158 -36897,1884784,162 -36898,1884946,136 -36899,1885082,136 -36900,1885218,152 -36901,1885370,218 -36902,1885588,199 -36903,1885787,168 -36904,1885955,167 -36905,1886122,114 -36906,1886236,168 -36907,1886404,166 -36908,1886570,199 -36909,1886769,184 -36910,1886953,164 -36911,1887117,160 -36912,1887277,147 -36913,1887424,122 -36914,1887546,164 -36915,1887710,137 -36916,1887847,136 -36917,1887983,193 -36918,1888176,125 -36919,1888301,152 -36920,1888453,164 -36921,1888617,148 -36922,1888765,158 -36923,1888923,164 -36924,1889087,179 -36925,1889266,153 -36926,1889419,180 -36927,1889599,142 -36928,1889741,186 -36929,1889927,157 -36930,1890084,134 -36931,1890218,131 -36932,1890349,155 -36933,1890504,160 -36934,1890664,157 -36935,1890821,184 -36936,1891005,149 -36937,1891154,175 -36938,1891329,174 -36939,1891503,218 -36940,1891721,140 -36941,1891861,116 -36942,1891977,127 -36943,1892104,168 -36944,1892272,122 -36945,1892394,157 -36946,1892551,157 -36947,1892708,219 -36948,1892927,196 -36949,1893123,216 -36950,1893339,155 -36951,1893494,157 -36952,1893651,269 -36953,1893920,172 -36954,1894092,162 -36955,1894254,179 -36956,1894433,118 -36957,1894551,156 -36958,1894707,158 -36959,1894865,166 -36960,1895031,156 -36961,1895187,199 -36962,1895386,167 -36963,1895553,201 -36964,1895754,148 -36965,1895902,153 -36966,1896055,178 -36967,1896233,179 -36968,1896412,141 -36969,1896553,167 -36970,1896720,163 -36971,1896883,159 -36972,1897042,153 -36973,1897195,163 -36974,1897358,134 -36975,1897492,162 -36976,1897654,152 -36977,1897806,164 -36978,1897970,112 -36979,1898082,174 -36980,1898256,149 -36981,1898405,190 -36982,1898595,182 -36983,1898777,187 -36984,1898964,174 -36985,1899138,141 -36986,1899279,141 -36987,1899420,153 -36988,1899573,175 -36989,1899748,146 -36990,1899894,151 -36991,1900045,184 -36992,1900229,161 -36993,1900390,184 -36994,1900574,132 -36995,1900706,175 -36996,1900881,174 -36997,1901055,194 -36998,1901249,162 -36999,1901411,156 -37000,1901567,212 -37001,1901779,166 -37002,1901945,159 -37003,1902104,149 -37004,1902253,184 -37005,1902437,171 -37006,1902608,174 -37007,1902782,138 -37008,1902920,124 -37009,1903044,148 -37010,1903192,170 -37011,1903362,147 -37012,1903509,176 -37013,1903685,155 -37014,1903840,194 -37015,1904034,141 -37016,1904175,154 -37017,1904329,172 -37018,1904501,164 -37019,1904665,125 -37020,1904790,147 -37021,1904937,195 -37022,1905132,161 -37023,1905293,163 -37024,1905456,139 -37025,1905595,193 -37026,1905788,201 -37027,1905989,171 -37028,1906160,145 -37029,1906305,138 -37030,1906443,162 -37031,1906605,169 -37032,1906774,168 -37033,1906942,144 -37034,1907086,208 -37035,1907294,164 -37036,1907458,147 -37037,1907605,158 -37038,1907763,132 -37039,1907895,162 -37040,1908057,118 -37041,1908175,162 -37042,1908337,150 -37043,1908487,139 -37044,1908626,172 -37045,1908798,194 -37046,1908992,144 -37047,1909136,171 -37048,1909307,174 -37049,1909481,182 -37050,1909663,147 -37051,1909810,216 -37052,1910026,182 -37053,1910208,167 -37054,1910375,187 -37055,1910562,164 -37056,1910726,161 -37057,1910887,137 -37058,1911024,153 -37059,1911177,173 -37060,1911350,151 -37061,1911501,162 -37062,1911663,160 -37063,1911823,123 -37064,1911946,171 -37065,1912117,148 -37066,1912265,196 -37067,1912461,167 -37068,1912628,179 -37069,1912807,238 -37070,1913045,130 -37071,1913175,126 -37072,1913301,154 -37073,1913455,197 -37074,1913652,150 -37075,1913802,161 -37076,1913963,168 -37077,1914131,139 -37078,1914270,134 -37079,1914404,148 -37080,1914552,177 -37081,1914729,171 -37082,1914900,142 -37083,1915042,169 -37084,1915211,185 -37085,1915396,160 -37086,1915556,160 -37087,1915716,174 -37088,1915890,136 -37089,1916026,124 -37090,1916150,176 -37091,1916326,157 -37092,1916483,149 -37093,1916632,142 -37094,1916774,156 -37095,1916930,155 -37096,1917085,212 -37097,1917297,139 -37098,1917436,158 -37099,1917594,152 -37100,1917746,118 -37101,1917864,182 -37102,1918046,177 -37103,1918223,153 -37104,1918376,202 -37105,1918578,169 -37106,1918747,164 -37107,1918911,163 -37108,1919074,153 -37109,1919227,166 -37110,1919393,146 -37111,1919539,160 -37112,1919699,147 -37113,1919846,125 -37114,1919971,149 -37115,1920120,169 -37116,1920289,168 -37117,1920457,156 -37118,1920613,182 -37119,1920795,165 -37334,1920960,146 -37370,1921106,173 -37626,1921279,214 -37731,1921493,205 -38249,1921698,197 -38911,1921895,149 -39938,1922044,167 -40334,1922211,174 -40648,1922385,262 -40960,1922647,168 -40961,1922815,166 -40962,1922981,181 -40963,1923162,251 -40964,1923413,142 -40965,1923555,158 -40966,1923713,178 -40967,1923891,162 -40968,1924053,148 -40969,1924201,167 -40970,1924368,148 -40971,1924516,171 -40972,1924687,192 -40973,1924879,156 -40974,1925035,164 -40975,1925199,172 -40976,1925371,155 -40977,1925526,160 -40978,1925686,151 -40979,1925837,174 -40980,1926011,126 -40981,1926137,123 -40982,1926260,149 -40983,1926409,147 -40984,1926556,163 -40985,1926719,154 -40986,1926873,141 -40987,1927014,170 -40988,1927184,176 -40989,1927360,156 -40990,1927516,139 -40991,1927655,165 -40992,1927820,143 -40993,1927963,163 -40994,1928126,213 -40995,1928339,186 -40996,1928525,148 -40997,1928673,146 -40998,1928819,147 -40999,1928966,164 -41000,1929130,151 -41001,1929281,150 -41002,1929431,163 -41003,1929594,162 -41004,1929756,181 -41005,1929937,157 -41006,1930094,187 -41007,1930281,121 -41008,1930402,118 -41009,1930520,174 -41010,1930694,155 -41011,1930849,139 -41012,1930988,129 -41013,1931117,148 -41014,1931265,179 -41015,1931444,151 -41016,1931595,138 -41017,1931733,163 -41018,1931896,157 -41019,1932053,195 -41020,1932248,159 -41021,1932407,131 -41022,1932538,169 -41023,1932707,259 -41024,1932966,120 -41025,1933086,129 -41026,1933215,151 -41027,1933366,193 -41028,1933559,150 -41029,1933709,152 -41030,1933861,130 -41031,1933991,155 -41032,1934146,153 -41033,1934299,176 -41034,1934475,188 -41035,1934663,191 -41036,1934854,213 -41037,1935067,164 -41038,1935231,165 -41039,1935396,142 -41040,1935538,159 -41041,1935697,163 -41042,1935860,173 -41043,1936033,154 -41044,1936187,55 -41045,1936242,155 -41046,1936397,118 -41047,1936515,167 -41048,1936682,131 -41049,1936813,145 -41050,1936958,152 -41051,1937110,142 -41052,1937252,198 -41053,1937450,151 -41054,1937601,151 -41055,1937752,166 -41056,1937918,177 -41057,1938095,143 -41058,1938238,147 -41059,1938385,142 -41060,1938527,132 -41061,1938659,160 -41062,1938819,153 -41063,1938972,170 -41064,1939142,129 -41065,1939271,149 -41066,1939420,151 -41067,1939571,163 -41068,1939734,181 -41069,1939915,165 -41070,1940080,137 -41071,1940217,157 -41072,1940374,137 -41073,1940511,174 -41074,1940685,190 -41075,1940875,140 -41076,1941015,154 -41077,1941169,176 -41078,1941345,153 -41079,1941498,150 -41080,1941648,160 -41081,1941808,165 -41082,1941973,214 -41083,1942187,174 -41084,1942361,214 -41085,1942575,156 -41086,1942731,183 -41087,1942914,187 -41088,1943101,153 -41089,1943254,160 -41090,1943414,133 -41091,1943547,173 -41092,1943720,161 -41093,1943881,55 -41094,1943936,178 -41095,1944114,153 -41096,1944267,172 -41097,1944439,173 -41098,1944612,175 -41099,1944787,211 -41100,1944998,179 -41101,1945177,157 -41102,1945334,191 -41103,1945525,156 -41104,1945681,154 -41105,1945835,155 -41106,1945990,198 -41107,1946188,149 -41108,1946337,155 -41109,1946492,155 -41110,1946647,161 -41111,1946808,163 -41112,1946971,127 -41113,1947098,158 -41114,1947256,149 -41115,1947405,158 -41116,1947563,135 -41117,1947698,174 -41118,1947872,125 -41119,1947997,145 -41120,1948142,147 -41121,1948289,147 -41122,1948436,136 -41123,1948572,163 -41124,1948735,158 -41125,1948893,164 -41126,1949057,152 -41127,1949209,158 -41128,1949367,150 -41129,1949517,164 -41130,1949681,143 -41131,1949824,169 -41132,1949993,164 -41133,1950157,132 -41134,1950289,208 -41135,1950497,139 -41136,1950636,155 -41137,1950791,174 -41138,1950965,127 -41139,1951092,132 -41140,1951224,161 -41141,1951385,144 -41142,1951529,166 -41143,1951695,146 -41144,1951841,151 -41145,1951992,170 -41146,1952162,165 -41147,1952327,130 -41148,1952457,153 -41149,1952610,144 -41150,1952754,225 -41151,1952979,170 -41152,1953149,149 -41153,1953298,125 -41154,1953423,160 -41155,1953583,146 -41156,1953729,178 -41157,1953907,204 -41158,1954111,155 -41159,1954266,153 -41160,1954419,141 -41161,1954560,173 -41162,1954733,148 -41163,1954881,175 -41164,1955056,171 -41165,1955227,172 -41166,1955399,137 -41167,1955536,139 -41168,1955675,172 -41169,1955847,211 -41170,1956058,189 -41171,1956247,189 -41172,1956436,149 -41173,1956585,149 -41174,1956734,130 -41175,1956864,178 -41176,1957042,162 -41177,1957204,197 -41178,1957401,198 -41179,1957599,180 -41180,1957779,152 -41181,1957931,163 -41182,1958094,183 -41183,1958277,180 -41184,1958457,187 -41185,1958644,175 -41186,1958819,182 -41187,1959001,145 -41188,1959146,132 -41189,1959278,149 -41190,1959427,149 -41191,1959576,160 -41192,1959736,162 -41193,1959898,197 -41194,1960095,141 -41195,1960236,175 -41196,1960411,168 -41197,1960579,160 -41198,1960739,145 -41199,1960884,170 -41200,1961054,181 -41201,1961235,122 -41202,1961357,172 -41203,1961529,123 -41204,1961652,131 -41205,1961783,133 -41206,1961916,147 -41207,1962063,155 -41208,1962218,173 -41209,1962391,155 -41210,1962546,156 -41211,1962702,168 -41212,1962870,150 -41213,1963020,169 -41214,1963189,165 -41215,1963354,177 -41438,1963531,235 -41690,1963766,129 -41717,1963895,252 -41727,1964147,133 -42249,1964280,149 -42884,1964429,213 -43520,1964642,155 -43521,1964797,106 -43522,1964903,106 -43580,1965009,179 -43632,1965188,154 -44256,1965342,148 -44794,1965490,179 -45065,1965669,153 -45079,1965822,166 -45081,1965988,141 -45084,1966129,153 -45086,1966282,149 -45098,1966431,126 -45101,1966557,178 -45107,1966735,183 -45115,1966918,141 -45128,1967059,177 -45130,1967236,170 -45138,1967406,163 -45156,1967569,170 -45161,1967739,123 -45165,1967862,147 -45184,1968009,156 -45190,1968165,151 -45198,1968316,170 -45201,1968486,146 -45204,1968632,140 -45210,1968772,167 -45213,1968939,175 -45228,1969114,179 -45230,1969293,136 -45235,1969429,159 -45250,1969588,170 -45255,1969758,187 -45262,1969945,146 -45264,1970091,146 -45275,1970237,139 -45279,1970376,175 -45287,1970551,158 -45292,1970709,122 -45294,1970831,163 -45296,1970994,141 -45301,1971135,189 -45880,1971324,243 -45890,1971567,218 -46445,1971785,220 -46550,1972005,135 -46989,1972140,222 -47606,1972362,240 -47808,1972602,163 -47873,1972765,147 -47930,1972912,55 -48014,1972967,166 -48112,1973133,154 -48423,1973287,127 -48442,1973414,135 -48917,1973549,158 -49152,1973707,150 -49153,1973857,184 -49154,1974041,178 -49155,1974219,173 -49156,1974392,176 -49157,1974568,181 -49158,1974749,183 -49159,1974932,170 -49160,1975102,115 -49161,1975217,176 -49162,1975393,141 -49163,1975534,126 -49164,1975660,216 -49165,1975876,163 -49166,1976039,149 -49167,1976188,192 -49168,1976380,179 -49169,1976559,182 -49170,1976741,169 -49171,1976910,134 -49172,1977044,177 -49173,1977221,169 -49174,1977390,164 -49175,1977554,144 -49176,1977698,148 -49177,1977846,140 -49178,1977986,181 -49179,1978167,166 -49180,1978333,200 -49181,1978533,175 -49182,1978708,153 -49183,1978861,123 -49184,1978984,182 -49185,1979166,161 -49186,1979327,177 -49187,1979504,160 -49188,1979664,170 -49189,1979834,171 -49190,1980005,181 -49191,1980186,158 -49192,1980344,145 -49193,1980489,174 -49194,1980663,169 -49195,1980832,180 -49196,1981012,175 -49197,1981187,171 -49198,1981358,110 -49199,1981468,135 -49200,1981603,174 -49201,1981777,193 -49202,1981970,190 -49203,1982160,153 -49204,1982313,195 -49205,1982508,150 -49206,1982658,213 -49207,1982871,137 -49208,1983008,178 -49209,1983186,175 -49210,1983361,159 -49211,1983520,178 -49212,1983698,128 -49213,1983826,148 -49214,1983974,150 -49215,1984124,169 -49216,1984293,128 -49217,1984421,172 -49218,1984593,139 -49219,1984732,132 -49220,1984864,135 -49221,1984999,168 -49222,1985167,181 -49223,1985348,159 -49224,1985507,184 -49225,1985691,161 -49226,1985852,146 -49227,1985998,192 -49228,1986190,178 -49229,1986368,149 -49230,1986517,148 -49231,1986665,174 -49232,1986839,170 -49233,1987009,174 -49234,1987183,131 -49235,1987314,157 -49236,1987471,204 -49237,1987675,169 -49238,1987844,119 -49239,1987963,131 -49240,1988094,155 -49241,1988249,144 -49242,1988393,178 -49243,1988571,155 -49244,1988726,144 -49245,1988870,160 -49246,1989030,135 -49247,1989165,199 -49248,1989364,130 -49249,1989494,164 -49250,1989658,150 -49251,1989808,173 -49252,1989981,185 -49253,1990166,162 -49254,1990328,141 -49255,1990469,170 -49256,1990639,169 -49257,1990808,174 -49258,1990982,182 -49259,1991164,147 -49260,1991311,199 -49261,1991510,154 -49262,1991664,173 -49263,1991837,133 -49264,1991970,160 -49265,1992130,179 -49266,1992309,175 -49267,1992484,152 -49268,1992636,168 -49269,1992804,145 -49270,1992949,153 -49271,1993102,205 -49272,1993307,168 -49273,1993475,157 -49274,1993632,128 -49275,1993760,170 -49276,1993930,178 -49277,1994108,175 -49278,1994283,191 -49279,1994474,158 -49280,1994632,173 -49281,1994805,190 -49282,1994995,149 -49283,1995144,173 -49284,1995317,153 -49285,1995470,170 -49286,1995640,157 -49287,1995797,173 -49288,1995970,137 -49289,1996107,145 -49290,1996252,151 -49291,1996403,174 -49292,1996577,174 -49293,1996751,174 -49294,1996925,177 -49295,1997102,191 -49296,1997293,126 -49297,1997419,155 -49298,1997574,154 -49299,1997728,164 -49300,1997892,126 -49301,1998018,120 -49302,1998138,170 -49303,1998308,130 -49304,1998438,236 -49305,1998674,173 -49306,1998847,164 -49307,1999011,187 -49308,1999198,167 -49309,1999365,182 -49310,1999547,156 -49311,1999703,200 -49312,1999903,170 -49313,2000073,155 -49314,2000228,128 -49315,2000356,209 -49316,2000565,114 -49317,2000679,163 -49318,2000842,162 -49319,2001004,144 -49320,2001148,148 -49321,2001296,184 -49322,2001480,168 -49323,2001648,151 -49324,2001799,178 -49325,2001977,170 -49326,2002147,172 -49327,2002319,161 -49328,2002480,152 -49329,2002632,175 -49330,2002807,151 -49331,2002958,174 -49332,2003132,212 -49333,2003344,182 -49334,2003526,169 -49335,2003695,179 -49336,2003874,167 -49337,2004041,149 -49338,2004190,146 -49339,2004336,144 -49340,2004480,166 -49341,2004646,172 -49342,2004818,123 -49343,2004941,184 -49344,2005125,163 -49345,2005288,147 -49346,2005435,196 -49347,2005631,194 -49348,2005825,212 -49349,2006037,169 -49350,2006206,154 -49351,2006360,177 -49352,2006537,175 -49353,2006712,176 -49354,2006888,184 -49355,2007072,170 -49356,2007242,177 -49357,2007419,156 -49358,2007575,208 -49359,2007783,130 -49360,2007913,169 -49361,2008082,183 -49362,2008265,145 -49363,2008410,173 -49364,2008583,150 -49365,2008733,161 -49366,2008894,149 -49367,2009043,194 -49368,2009237,164 -49369,2009401,203 -49370,2009604,139 -49371,2009743,163 -49372,2009906,170 -49373,2010076,146 -49374,2010222,141 -49375,2010363,169 -49376,2010532,163 -49377,2010695,149 -49378,2010844,170 -49379,2011014,179 -49380,2011193,176 -49381,2011369,131 -49382,2011500,151 -49383,2011651,122 -49384,2011773,144 -49385,2011917,181 -49386,2012098,174 -49387,2012272,163 -49388,2012435,154 -49389,2012589,172 -49390,2012761,152 -49391,2012913,146 -49392,2013059,171 -49393,2013230,200 -49394,2013430,157 -49395,2013587,181 -49396,2013768,191 -49397,2013959,141 -49398,2014100,172 -49399,2014272,165 -49400,2014437,145 -49401,2014582,177 -49402,2014759,169 -49403,2014928,190 -49404,2015118,153 -49405,2015271,114 -49406,2015385,168 -49407,2015553,169 -49487,2015722,165 -49862,2015887,166 -50651,2016053,186 -50704,2016239,120 -52157,2016359,226 -52624,2016585,135 -53020,2016720,169 -53248,2016889,181 -53249,2017070,149 -53250,2017219,158 -53251,2017377,203 -53252,2017580,142 -53253,2017722,178 -53254,2017900,170 -53255,2018070,160 -53256,2018230,147 -53257,2018377,220 -53258,2018597,164 -53259,2018761,150 -53260,2018911,155 -53261,2019066,187 -53262,2019253,138 -53263,2019391,139 -53264,2019530,161 -53265,2019691,157 -53266,2019848,141 -53267,2019989,186 -53268,2020175,155 -53269,2020330,212 -53270,2020542,156 -53271,2020698,219 -53272,2020917,152 -53273,2021069,197 -53274,2021266,139 -53275,2021405,173 -53276,2021578,186 -53277,2021764,171 -53278,2021935,139 -53279,2022074,144 -53280,2022218,188 -53281,2022406,173 -53282,2022579,174 -53283,2022753,210 -53284,2022963,206 -53285,2023169,171 -53286,2023340,162 -53287,2023502,164 -53288,2023666,143 -53289,2023809,168 -53290,2023977,190 -53291,2024167,149 -53292,2024316,160 -53293,2024476,119 -53294,2024595,178 -53295,2024773,152 -53296,2024925,160 -53297,2025085,176 -53298,2025261,165 -53299,2025426,167 -53300,2025593,147 -53301,2025740,218 -53302,2025958,178 -53303,2026136,126 -53304,2026262,196 -53305,2026458,146 -53306,2026604,162 -53307,2026766,184 -53308,2026950,147 -53309,2027097,147 -53310,2027244,150 -53311,2027394,215 -53312,2027609,173 -53313,2027782,235 -53314,2028017,142 -53315,2028159,165 -53316,2028324,167 -53317,2028491,112 -53318,2028603,170 -53319,2028773,134 -53320,2028907,141 -53321,2029048,200 -53322,2029248,167 -53323,2029415,134 -53324,2029549,183 -53325,2029732,206 -53326,2029938,126 -53327,2030064,148 -53328,2030212,116 -53329,2030328,152 -53330,2030480,196 -53331,2030676,155 -53332,2030831,146 -53333,2030977,147 -53334,2031124,146 -53335,2031270,143 -53336,2031413,170 -53337,2031583,219 -53338,2031802,166 -53339,2031968,170 -53340,2032138,170 -53341,2032308,158 -53342,2032466,172 -53343,2032638,137 -53344,2032775,157 -53345,2032932,227 -53346,2033159,121 -53347,2033280,170 -53348,2033450,158 -53349,2033608,136 -53350,2033744,165 -53351,2033909,163 -53352,2034072,177 -53353,2034249,167 -53354,2034416,172 -53355,2034588,153 -53356,2034741,152 -53357,2034893,136 -53358,2035029,187 -53359,2035216,166 -53360,2035382,231 -53361,2035613,139 -53362,2035752,135 -53363,2035887,179 -53364,2036066,158 -53365,2036224,197 -53366,2036421,144 -53367,2036565,203 -53368,2036768,125 -53369,2036893,170 -53370,2037063,202 -53371,2037265,176 -53372,2037441,168 -53373,2037609,159 -53374,2037768,127 -53375,2037895,197 -53376,2038092,147 -53377,2038239,181 -53378,2038420,139 -53379,2038559,148 -53380,2038707,221 -53381,2038928,156 -53382,2039084,146 -53383,2039230,141 -53384,2039371,147 -53385,2039518,166 -53386,2039684,157 -53387,2039841,179 -53388,2040020,154 -53389,2040174,149 -53390,2040323,143 -53391,2040466,162 -53392,2040628,170 -53393,2040798,168 -53394,2040966,167 -53395,2041133,149 -53396,2041282,150 -53397,2041432,199 -53398,2041631,171 -53399,2041802,170 -53400,2041972,171 -53401,2042143,167 -53402,2042310,151 -53403,2042461,146 -53404,2042607,157 -53405,2042764,142 -53406,2042906,132 -53407,2043038,150 -53408,2043188,132 -53409,2043320,165 -53410,2043485,179 -53411,2043664,150 -53412,2043814,167 -53413,2043981,139 -53414,2044120,214 -53415,2044334,189 -53416,2044523,154 -53417,2044677,186 -53418,2044863,180 -53419,2045043,150 -53420,2045193,146 -53421,2045339,136 -53422,2045475,173 -53423,2045648,169 -53424,2045817,178 -53425,2045995,150 -53426,2046145,159 -53427,2046304,178 -53428,2046482,151 -53429,2046633,167 -53430,2046800,160 -53431,2046960,166 -53432,2047126,101 -53433,2047227,245 -53434,2047472,170 -53435,2047642,170 -53436,2047812,170 -53437,2047982,147 -53438,2048129,128 -53439,2048257,163 -53440,2048420,170 -53441,2048590,170 -53442,2048760,145 -53443,2048905,164 -53444,2049069,160 -53445,2049229,169 -53446,2049398,195 -53447,2049593,142 -53448,2049735,117 -53449,2049852,200 -53450,2050052,196 -53451,2050248,207 -53452,2050455,180 -53453,2050635,203 -53454,2050838,135 -53455,2050973,136 -53456,2051109,174 -53457,2051283,141 -53458,2051424,155 -53459,2051579,170 -53460,2051749,154 -53461,2051903,131 -53462,2052034,149 -53463,2052183,150 -53464,2052333,150 -53465,2052483,203 -53466,2052686,204 -53467,2052890,164 -53468,2053054,171 -53469,2053225,155 -53470,2053380,167 -53471,2053547,174 -53472,2053721,204 -53473,2053925,146 -53474,2054071,151 -53475,2054222,232 -53476,2054454,153 -53477,2054607,158 -53478,2054765,154 -53479,2054919,155 -53480,2055074,204 -53481,2055278,199 -53482,2055477,174 -53483,2055651,156 -53484,2055807,175 -53485,2055982,118 -53486,2056100,165 -53487,2056265,116 -53488,2056381,153 -53489,2056534,163 -53490,2056697,153 -53491,2056850,135 -53492,2056985,155 -53493,2057140,150 -53494,2057290,139 -53495,2057429,169 -53496,2057598,197 -53497,2057795,216 -53498,2058011,217 -53499,2058228,172 -53500,2058400,157 -53501,2058557,153 -53502,2058710,172 -53503,2058882,170 -53532,2059052,172 -54157,2059224,193 -54834,2059417,167 -55761,2059584,168 -56094,2059752,137 -56133,2059889,141 -56287,2060030,166 -56576,2060196,154 -56577,2060350,154 -56578,2060504,154 -56579,2060658,154 -56580,2060812,154 -56581,2060966,154 -56582,2061120,154 -56583,2061274,154 -56584,2061428,154 -56585,2061582,154 -56586,2061736,154 -56587,2061890,154 -56588,2062044,154 -56589,2062198,154 -56590,2062352,154 -56591,2062506,154 -57083,2062660,170 -57344,2062830,192 -57345,2063022,173 -57346,2063195,175 -57347,2063370,219 -57348,2063589,144 -57349,2063733,156 -57350,2063889,209 -57351,2064098,166 -57352,2064264,157 -57353,2064421,175 -57354,2064596,131 -57355,2064727,165 -57356,2064892,134 -57357,2065026,143 -57358,2065169,165 -57359,2065334,189 -57360,2065523,162 -57361,2065685,145 -57362,2065830,183 -57363,2066013,207 -57364,2066220,156 -57365,2066376,156 -57366,2066532,163 -57367,2066695,128 -57368,2066823,160 -57369,2066983,157 -57370,2067140,174 -57371,2067314,164 -57372,2067478,156 -57373,2067634,150 -57374,2067784,156 -57375,2067940,167 -57376,2068107,121 -57377,2068228,144 -57378,2068372,160 -57379,2068532,104 -57380,2068636,145 -57381,2068781,165 -57382,2068946,159 -57383,2069105,130 -57384,2069235,148 -57385,2069383,154 -57386,2069537,151 -57387,2069688,146 -57388,2069834,135 -57389,2069969,159 -57390,2070128,161 -57391,2070289,182 -57392,2070471,175 -57393,2070646,178 -57394,2070824,178 -57395,2071002,137 -57396,2071139,156 -57397,2071295,167 -57398,2071462,174 -57399,2071636,139 -57400,2071775,161 -57401,2071936,142 -57402,2072078,170 -57403,2072248,165 -57404,2072413,129 -57405,2072542,166 -57406,2072708,165 -57407,2072873,152 -57408,2073025,167 -57409,2073192,117 -57410,2073309,151 -57411,2073460,126 -57412,2073586,149 -57413,2073735,144 -57414,2073879,140 -57415,2074019,163 -57416,2074182,153 -57417,2074335,149 -57418,2074484,163 -57419,2074647,186 -57420,2074833,220 -57421,2075053,166 -57422,2075219,154 -57423,2075373,156 -57424,2075529,186 -57425,2075715,144 -57426,2075859,178 -57427,2076037,149 -57428,2076186,145 -57429,2076331,188 -57430,2076519,156 -57431,2076675,210 -57432,2076885,150 -57433,2077035,162 -57434,2077197,170 -57435,2077367,167 -57436,2077534,196 -57437,2077730,150 -57438,2077880,200 -57439,2078080,151 -57440,2078231,128 -57441,2078359,163 -57442,2078522,160 -57443,2078682,195 -57444,2078877,150 -57445,2079027,175 -57446,2079202,162 -57447,2079364,165 -57448,2079529,154 -57449,2079683,130 -57450,2079813,118 -57451,2079931,153 -57452,2080084,236 -57453,2080320,153 -57454,2080473,138 -57455,2080611,147 -57456,2080758,146 -57457,2080904,164 -57458,2081068,138 -57459,2081206,179 -57460,2081385,168 -57461,2081553,151 -57462,2081704,166 -57463,2081870,138 -57464,2082008,150 -57465,2082158,111 -57466,2082269,127 -57467,2082396,129 -57468,2082525,156 -57469,2082681,132 -57470,2082813,157 -57471,2082970,141 -57472,2083111,172 -57473,2083283,148 -57474,2083431,113 -57475,2083544,168 -57476,2083712,147 -57477,2083859,162 -57478,2084021,194 -57479,2084215,199 -57480,2084414,167 -57481,2084581,158 -57482,2084739,173 -57483,2084912,143 -57484,2085055,166 -57485,2085221,154 -57486,2085375,128 -57487,2085503,156 -57488,2085659,167 -57489,2085826,168 -57490,2085994,148 -57491,2086142,145 -57492,2086287,111 -57493,2086398,205 -57494,2086603,157 -57495,2086760,163 -57496,2086923,178 -57497,2087101,124 -57498,2087225,153 -57499,2087378,167 -57500,2087545,145 -57501,2087690,145 -57502,2087835,154 -57503,2087989,128 -57504,2088117,135 -57505,2088252,184 -57506,2088436,142 -57507,2088578,156 -57508,2088734,130 -57509,2088864,177 -57510,2089041,157 -57511,2089198,186 -57512,2089384,128 -57513,2089512,158 -57514,2089670,159 -57515,2089829,122 -57516,2089951,136 -57517,2090087,153 -57518,2090240,152 -57519,2090392,220 -57520,2090612,156 -57521,2090768,199 -57522,2090967,168 -57523,2091135,157 -57524,2091292,150 -57525,2091442,174 -57526,2091616,155 -57527,2091771,157 -57528,2091928,140 -57529,2092068,146 -57530,2092214,166 -57531,2092380,144 -57532,2092524,175 -57533,2092699,166 -57534,2092865,163 -57535,2093028,206 -57536,2093234,174 -57537,2093408,174 -57538,2093582,121 -57539,2093703,201 -57540,2093904,162 -57541,2094066,171 -57542,2094237,143 -57543,2094380,133 -57544,2094513,179 -57545,2094692,173 -57546,2094865,153 -57547,2095018,128 -57548,2095146,193 -57549,2095339,166 -57550,2095505,123 -57551,2095628,191 -57552,2095819,142 -57553,2095961,164 -57554,2096125,179 -57555,2096304,137 -57556,2096441,146 -57557,2096587,149 -57558,2096736,213 -57559,2096949,175 -57560,2097124,177 -57561,2097301,134 -57562,2097435,167 -57563,2097602,187 -57564,2097789,145 -57565,2097934,175 -57566,2098109,114 -57567,2098223,129 -57568,2098352,147 -57569,2098499,157 -57570,2098656,140 -57571,2098796,144 -57572,2098940,192 -57573,2099132,176 -57574,2099308,142 -57575,2099450,159 -57576,2099609,166 -57577,2099775,167 -57578,2099942,170 -57579,2100112,168 -57580,2100280,145 -57581,2100425,144 -57582,2100569,114 -57583,2100683,123 -57584,2100806,180 -57585,2100986,146 -57586,2101132,167 -57587,2101299,173 -57588,2101472,147 -57589,2101619,113 -57590,2101732,159 -57591,2101891,156 -57592,2102047,134 -57593,2102181,156 -57594,2102337,169 -57595,2102506,138 -57596,2102644,206 -57597,2102850,214 -57598,2103064,156 -57599,2103220,180 -57709,2103400,136 -57717,2103536,154 -58290,2103690,175 -58982,2103865,209 -59091,2104074,166 -59112,2104240,263 -59563,2104503,167 -60205,2104670,158 -61117,2104828,176 -61521,2105004,134 -62427,2105138,150 -62467,2105288,127 -62575,2105415,161 -62649,2105576,120 -63343,2105696,120 -63584,2105816,181 -64059,2105997,147 -64600,2106144,132 -64624,2106276,184 -64653,2106460,203 -64844,2106663,108 -132865,2106771,171 -138364,2106942,181 -155782,2107123,190 -155788,2107313,153 -159745,2107466,171 -159920,2107637,162 -159923,2107799,161 -171406,2107960,169 -174652,2108129,181 -178945,2108310,147 -180364,2108457,167 -184092,2108624,169 -190163,2108793,208 -264835,2109001,129 -264928,2109130,158 -265422,2109288,120 -265922,2109408,216 -267602,2109624,120 -268303,2109744,175 -268470,2109919,55 -268502,2109974,152 -268804,2110126,136 -269204,2110262,156 -269242,2110418,175 -269584,2110593,150 -269924,2110743,120 -270490,2110863,170 -270900,2111033,179 -271877,2111212,224 -271973,2111436,120 -273339,2111556,159 -274262,2111715,161 -275188,2111876,145 -275972,2112021,172 -277912,2112193,201 -279713,2112394,179 -280165,2112573,179 -280730,2112752,120 -281168,2112872,274 -281599,2113146,218 -281839,2113364,216 -282118,2113580,128 -282507,2113708,158 -282538,2113866,144 -283731,2114010,120 -284106,2114130,235 -284463,2114365,179 -284783,2114544,245 -285333,2114789,132 -285702,2114921,169 -285838,2115090,196 -286038,2115286,186 -286631,2115472,250 -287081,2115722,185 -287447,2115907,142 -287712,2116049,125 -288645,2116174,245 -290114,2116419,155 -290377,2116574,266 -291004,2116840,143 -292001,2116983,181 -292341,2117164,183 -292462,2117347,147 -294267,2117494,184 -295342,2117678,145 -296074,2117823,222 -297100,2118045,166 -297186,2118211,186 -297493,2118397,138 -297794,2118535,207 -297987,2118742,228 -298296,2118970,198 -299758,2119168,121 -300193,2119289,153 -301299,2119442,154 -301542,2119596,285 -301980,2119881,277 -302178,2120158,154 -302854,2120312,208 -302977,2120520,180 -303441,2120700,151 -304115,2120851,130 -305194,2120981,132 -308150,2121113,180 -308326,2121293,160 -310640,2121453,195 -310664,2121648,140 -311208,2121788,154 -311387,2121942,131 -311407,2122073,285 -311452,2122358,144 -311737,2122502,221 -312740,2122723,170 -313472,2122893,134 -313745,2123027,191 -313817,2123218,169 -314141,2123387,154 -314900,2123541,164 -315173,2123705,163 -316471,2123868,184 -317315,2124052,203 -318162,2124255,136 -318294,2124391,132 -318346,2124523,211 -318796,2124734,123 -319195,2124857,154 -319337,2125011,172 -319684,2125183,137 -319944,2125320,195 -320248,2125515,160 -320593,2125675,144 -320822,2125819,120 -320840,2125939,174 -321122,2126113,143 -321142,2126256,195 -322021,2126451,142 -323217,2126593,125 -323617,2126718,175 -323902,2126893,120 -323965,2127013,168 -324796,2127181,145 -325604,2127326,120 -325826,2127446,193 -325944,2127639,200 -327217,2127839,175 -327295,2128014,170 -327505,2128184,165 -524289,2128349,167 -524290,2128516,170 -524291,2128686,166 -524292,2128852,160 -524293,2129012,140 -524294,2129152,181 -524295,2129333,120 -524296,2129453,168 -524297,2129621,176 -524298,2129797,172 -524299,2129969,149 -524300,2130118,154 -524301,2130272,197 -524302,2130469,140 -524303,2130609,168 -524305,2130777,187 -524306,2130964,171 -524307,2131135,64 -524308,2131199,130 -524309,2131329,191 -524310,2131520,178 -524311,2131698,165 -524312,2131863,177 -524313,2132040,170 -524314,2132210,166 -524315,2132376,141 -524316,2132517,206 -524317,2132723,166 -524318,2132889,154 -524319,2133043,179 -524320,2133222,177 -524321,2133399,164 -524322,2133563,145 -524323,2133708,176 -524324,2133884,186 -524325,2134070,145 -524326,2134215,125 -524327,2134340,152 -524328,2134492,157 -524329,2134649,151 -524330,2134800,163 -524331,2134963,189 -524332,2135152,148 -524333,2135300,140 -524334,2135440,167 -524335,2135607,152 -524336,2135759,167 -524336,2135926,112 -524336,2136038,160 -524337,2136198,153 -524338,2136351,158 -524339,2136509,166 -524340,2136675,154 -524341,2136829,174 -524342,2137003,167 -524343,2137170,175 -524344,2137345,141 -524345,2137486,179 -524346,2137665,150 -524347,2137815,180 -524348,2137995,196 -524349,2138191,154 -524350,2138345,166 -524351,2138511,104 -524352,2138615,208 -524353,2138823,180 -524354,2139003,102 -524355,2139105,150 -524356,2139255,147 -524357,2139402,161 -524358,2139563,167 -524359,2139730,202 -524360,2139932,175 -524361,2140107,138 -524362,2140245,149 -524363,2140394,183 -524364,2140577,160 -524365,2140737,149 -524366,2140886,180 -524367,2141066,142 -524368,2141208,148 -524369,2141356,122 -524370,2141478,132 -524371,2141610,171 -524373,2141781,154 -524374,2141935,172 -524375,2142107,171 -524376,2142278,147 -524377,2142425,114 -524378,2142539,170 -524379,2142709,156 -524380,2142865,151 -524381,2143016,166 -524382,2143182,166 -524383,2143348,160 -524384,2143508,168 -524385,2143676,163 -524386,2143839,163 -524387,2144002,151 -524388,2144153,128 -524389,2144281,148 -524390,2144429,150 -524391,2144579,138 -524392,2144717,153 -524393,2144870,196 -524394,2145066,164 -524395,2145230,158 -524396,2145388,160 -524397,2145548,162 -524398,2145710,129 -524399,2145839,157 -524400,2145996,170 -524401,2146166,138 -524402,2146304,208 -524403,2146512,130 -524404,2146642,172 -524405,2146814,147 -524406,2146961,163 -524407,2147124,196 -524408,2147320,147 -524409,2147467,142 -524410,2147609,113 -524411,2147722,161 -524412,2147883,166 -524414,2148049,195 -524415,2148244,188 -524416,2148432,157 -524417,2148589,145 -524418,2148734,155 -524419,2148889,164 -524420,2149053,160 -524421,2149213,120 -524422,2149333,175 -524423,2149508,124 -524424,2149632,185 -524425,2149817,143 -524426,2149960,154 -524427,2150114,167 -524428,2150281,167 -524429,2150448,140 -524430,2150588,147 -524431,2150735,182 -524432,2150917,163 -525169,2151080,125 -525773,2151205,232 -526530,2151437,159 -526570,2151596,126 -526774,2151722,123 -527371,2151845,146 -527561,2151991,179 -527748,2152170,126 -528040,2152296,144 -528378,2152440,163 -528734,2152603,185 -528790,2152788,166 -529475,2152954,132 -530001,2153086,281 -530229,2153367,170 -530420,2153537,138 -530458,2153675,160 -530508,2153835,148 -530854,2153983,192 -531963,2154175,268 -532287,2154443,185 -532459,2154628,134 -532467,2154762,170 -533794,2154932,131 -534297,2155063,157 -535248,2155220,153 -535728,2155373,160 -536159,2155533,151 -537969,2155684,168 -538429,2155852,175 -538524,2156027,191 -538789,2156218,175 -539228,2156393,254 -539320,2156647,173 -540040,2156820,175 -540172,2156995,165 -540302,2157160,187 -540478,2157347,124 -540534,2157471,203 -540711,2157674,144 -542294,2157818,167 -542764,2157985,208 -544284,2158193,162 -544447,2158355,156 -545070,2158511,143 -545344,2158654,199 -546560,2158853,260 -547552,2159113,198 -547598,2159311,146 -548317,2159457,159 -548974,2159616,180 -549478,2159796,168 -549729,2159964,243 -551120,2160207,170 -551146,2160377,163 -552434,2160540,226 -553029,2160766,120 -554230,2160886,183 -554354,2161069,117 -554520,2161186,193 -554645,2161379,200 -554751,2161579,151 -555417,2161730,122 -555596,2161852,243 -555946,2162095,159 -556222,2162254,141 -556321,2162395,227 -557113,2162622,143 -557500,2162765,228 -557556,2162993,149 -558651,2163142,176 -560584,2163318,175 -560719,2163493,166 -560940,2163659,177 -562474,2163836,163 -562903,2163999,112 -563032,2164111,268 -564737,2164379,223 -565143,2164602,163 -565547,2164765,248 -566728,2165013,194 -567642,2165207,161 -568485,2165368,154 -569208,2165522,167 -570019,2165689,146 -570575,2165835,190 -571192,2166025,178 -571372,2166203,158 -572364,2166361,164 -572739,2166525,151 -572937,2166676,173 -576069,2166849,206 -576616,2167055,136 -576923,2167191,211 -577695,2167402,170 -577719,2167572,195 -578202,2167767,134 -578379,2167901,265 -578572,2168166,166 -578603,2168332,159 -579008,2168491,233 -579635,2168724,248 -581407,2168972,145 -583130,2169117,252 -583282,2169369,174 -583759,2169543,195 -584260,2169738,160 -584489,2169898,191 -584564,2170089,166 -584685,2170255,239 -584873,2170494,175 -585145,2170669,200 -585355,2170869,161 -585531,2171030,184 -585643,2171214,203 -586167,2171417,157 -586484,2171574,181 -587512,2171755,137 -587560,2171892,183 -588512,2172075,135 -588882,2172210,129 -588936,2172339,175 -589070,2172514,175 -787456,2172689,134 -787765,2172823,136 -790789,2172959,261 -791138,2173220,160 -791307,2173380,133 -791584,2173513,175 -791865,2173688,120 -792005,2173808,155 -792561,2173963,130 -792863,2174093,167 -794031,2174260,257 -794050,2174517,176 -794662,2174693,137 -796452,2174830,136 -796501,2174966,215 -797289,2175181,183 -797415,2175364,266 -798089,2175630,185 -798753,2175815,120 -800732,2175935,238 -800830,2176173,238 -801110,2176411,168 -801893,2176579,151 -802463,2176730,130 -803134,2176860,158 -804509,2177018,134 -804669,2177152,223 -804997,2177375,152 -805945,2177527,185 -806377,2177712,120 -806746,2177832,134 -807415,2177966,123 -808101,2178089,166 -808225,2178255,144 -808540,2178399,237 -808939,2178636,149 -809497,2178785,191 -810200,2178976,145 -811126,2179121,199 -812028,2179320,210 -813059,2179530,136 -814671,2179666,175 -815453,2179841,175 -815660,2180016,265 -816322,2180281,120 -816419,2180401,188 -816922,2180589,120 -818556,2180709,219 -819474,2180928,55 -819760,2180983,233 -819816,2181216,242 -819818,2181458,241 -820241,2181699,152 -820356,2181851,164 -820444,2182015,201 -820517,2182216,170 -821520,2182386,189 -822269,2182575,166 -822415,2182741,202 -822492,2182943,120 -822680,2183063,213 -823886,2183276,166 -824065,2183442,177 -824315,2183619,129 -825023,2183748,243 -826131,2183991,255 -826710,2184246,160 -827025,2184406,181 -827704,2184587,145 -828148,2184732,241 -828418,2184973,142 -828458,2185115,220 -829076,2185335,182 -830469,2185517,196 -831322,2185713,202 -832281,2185915,161 -832751,2186076,265 -832990,2186341,134 -834719,2186475,120 -834897,2186595,185 -835349,2186780,146 -835776,2186926,215 -836519,2187141,126 -836730,2187267,158 -836734,2187425,184 -837205,2187609,226 -837226,2187835,132 -837292,2187967,143 -837663,2188110,164 -838086,2188274,197 -838541,2188471,148 -839123,2188619,193 -839163,2188812,163 -839633,2188975,203 -840338,2189178,166 -840373,2189344,187 -840962,2189531,124 -841366,2189655,132 -841666,2189787,178 -842134,2189965,170 -842177,2190135,161 -842305,2190296,217 -842956,2190513,177 -843247,2190690,135 -843684,2190825,175 -844004,2191000,154 -845267,2191154,132 -845577,2191286,133 -845871,2191419,159 -846134,2191578,136 -847590,2191714,199 -847740,2191913,128 -847791,2192041,278 -847897,2192319,221 -848052,2192540,241 -848737,2192781,207 -848878,2192988,154 -848901,2193142,229 -849316,2193371,136 -850067,2193507,166 -851075,2193673,196 -851525,2193869,169 -1048576,2194038,55 -1048666,2194093,170 -1048808,2194263,165 -1048829,2194428,192 -1049034,2194620,146 -1050058,2194766,136 -1050403,2194902,278 -1050801,2195180,219 -1050892,2195399,175 -1051561,2195574,166 -1051684,2195740,141 -1051951,2195881,160 -1051954,2196041,162 -1052031,2196203,151 -1052203,2196354,193 -1052286,2196547,150 -1052440,2196697,231 -1052854,2196928,129 -1053202,2197057,184 -1053208,2197241,178 -1053256,2197419,149 -1053678,2197568,203 -1054878,2197771,139 -1055572,2197910,192 -1055756,2198102,120 -1056081,2198222,175 -1056192,2198397,175 -1056628,2198572,167 -1057401,2198739,166 -1058750,2198905,155 -1058865,2199060,151 -1059971,2199211,107 -1060246,2199318,151 -1060527,2199469,152 -1060715,2199621,158 -1060935,2199779,175 -1061752,2199954,196 -1062673,2200150,127 -1063769,2200277,175 -1064426,2200452,228 -1065203,2200680,120 -1065343,2200800,128 -1065833,2200928,193 -1066074,2201121,175 -1066430,2201296,121 -1066488,2201417,170 -1066880,2201587,192 -1067185,2201779,214 -1067645,2201993,166 -1067846,2202159,176 -1068407,2202335,180 -1068551,2202515,226 -1069426,2202741,194 -1070794,2202935,187 -1072187,2203122,138 -1072319,2203260,150 -1072902,2203410,165 -1072969,2203575,143 -1073227,2203718,153 -1073865,2203871,155 -1074402,2204026,154 -1074595,2204180,162 -1074639,2204342,145 -1074818,2204487,146 -1075263,2204633,154 -1077055,2204787,164 -1077231,2204951,159 -1077753,2205110,174 -1078922,2205284,128 -1079217,2205412,189 -1079411,2205601,251 -1079502,2205852,182 -1079506,2206034,204 -1079942,2206238,193 -1080303,2206431,191 -1082322,2206622,170 -1083407,2206792,239 -1083598,2207031,221 -1083931,2207252,200 -1084623,2207452,170 -1086054,2207622,175 -1086441,2207797,120 -1087542,2207917,144 -1088185,2208061,119 -1088221,2208180,120 -1089449,2208300,165 -1089851,2208465,145 -1091024,2208610,176 -1091161,2208786,142 -1091395,2208928,173 -1091890,2209101,249 -1093216,2209350,55 -1093496,2209405,232 -1094251,2209637,179 -1095443,2209816,55 -1095670,2209871,198 -1096190,2210069,123 -1096357,2210192,180 -1096984,2210372,170 -1097544,2210542,167 -1097852,2210709,174 -1098426,2210883,166 -1098619,2211049,163 -1099142,2211212,239 -1099295,2211451,238 -1099390,2211689,251 -1099516,2211940,154 -1099583,2212094,201 -1100417,2212295,123 -1101019,2212418,194 -1101230,2212612,140 -1102300,2212752,169 -1102730,2212921,175 -1103170,2213096,175 -1105329,2213271,120 -1105396,2213391,231 -1105636,2213622,150 -1105803,2213772,356 -1106645,2214128,150 -1106887,2214278,162 -1107119,2214440,129 -1107630,2214569,168 -1108088,2214737,132 -1108206,2214869,140 -1108569,2215009,143 -1109721,2215152,168 -1110801,2215320,136 -1111003,2215456,151 -1111194,2215607,136 -1111681,2215743,198 -1112431,2215941,155 -1112558,2216096,134 -1112782,2216230,237 -1113072,2216467,181 -1113172,2216648,186 -1113837,2216834,271 -1114282,2217105,55 -1312520,2217160,55 -1312736,2217215,133 -1313910,2217348,131 -1314127,2217479,159 -1314975,2217638,120 -1315632,2217758,162 -1315915,2217920,234 -1316220,2218154,164 -1317457,2218318,175 -1317539,2218493,173 -1317821,2218666,144 -1317872,2218810,187 -1318842,2218997,278 -1319643,2219275,128 -1319895,2219403,199 -1321329,2219602,246 -1321938,2219848,148 -1321942,2219996,237 -1322279,2220233,241 -1322379,2220474,157 -1322485,2220631,130 -1323130,2220761,138 -1323206,2220899,163 -1323729,2221062,175 -1324427,2221237,191 -1324467,2221428,152 -1324549,2221580,134 -1324742,2221714,300 -1324859,2222014,199 -1325802,2222213,163 -1326578,2222376,259 -1326688,2222635,134 -1327430,2222769,184 -1327586,2222953,162 -1327897,2223115,233 -1328868,2223348,134 -1329291,2223482,256 -1329528,2223738,177 -1329632,2223915,227 -1330202,2224142,148 -1332242,2224290,169 -1332805,2224459,167 -1333456,2224626,151 -1333765,2224777,120 -1333891,2224897,133 -1334225,2225030,147 -1335424,2225177,160 -1336072,2225337,174 -1337867,2225511,231 -1338226,2225742,268 -1338890,2226010,55 -1340275,2226065,130 -1340433,2226195,118 -1340816,2226313,258 -1342899,2226571,201 -1342917,2226772,178 -1344091,2226950,264 -1345170,2227214,264 -1345854,2227478,197 -1346045,2227675,159 -1346160,2227834,125 -1347361,2227959,148 -1347526,2228107,120 -1347728,2228227,196 -1348680,2228423,139 -1350114,2228562,130 -1350160,2228692,158 -1351656,2228850,276 -1352548,2229126,175 -1353260,2229301,173 -1353835,2229474,240 -1354211,2229714,170 -1354736,2229884,165 -1355483,2230049,225 -1356070,2230274,167 -1356232,2230441,151 -1356932,2230592,175 -1357629,2230767,166 -1358184,2230933,243 -1360009,2231176,175 -1360166,2231351,145 -1360413,2231496,156 -1362976,2231652,264 -1363853,2231916,179 -1363858,2232095,281 -1363938,2232376,165 -1365246,2232541,148 -1365581,2232689,172 -1365870,2232861,169 -1366761,2233030,162 -1366917,2233192,168 -1367465,2233360,188 -1369324,2233548,147 -1369828,2233695,270 -1370931,2233965,192 -1371557,2234157,181 -1371620,2234338,152 -1371805,2234490,179 -1372357,2234669,118 -1372814,2234787,217 -1373226,2235004,159 -1373786,2235163,203 -1374355,2235366,215 -1375919,2235581,168 -1375925,2235749,138 -1572909,2235887,158 -1573083,2236045,141 -1573347,2236186,171 -1573747,2236357,138 -1573882,2236495,136 -1574517,2236631,136 -1575762,2236767,149 -1575956,2236916,147 -1576055,2237063,209 -1576108,2237272,133 -1577038,2237405,148 -1578016,2237553,123 -1578070,2237676,137 -1578697,2237813,190 -1578772,2238003,169 -1578789,2238172,219 -1579327,2238391,131 -1580011,2238522,165 -1580664,2238687,140 -1580720,2238827,175 -1581074,2239002,153 -1581106,2239155,120 -1581222,2239275,166 -1581694,2239441,175 -1582694,2239616,175 -1583201,2239791,215 -1583739,2240006,160 -1583877,2240166,162 -1584273,2240328,166 -1585161,2240494,211 -1585826,2240705,229 -1586077,2240934,170 -1586257,2241104,120 -1586940,2241224,178 -1587237,2241402,171 -1587300,2241573,224 -1587481,2241797,162 -1587757,2241959,175 -1588178,2242134,200 -1588642,2242334,166 -1589063,2242500,175 -1589789,2242675,55 -1589807,2242730,129 -1590370,2242859,165 -1590502,2243024,178 -1590807,2243202,159 -1591512,2243361,167 -1591919,2243528,199 -1592980,2243727,161 -1593138,2243888,241 -1593939,2244129,194 -1594336,2244323,200 -1594639,2244523,143 -1595699,2244666,140 -1595702,2244806,204 -1596136,2245010,183 -1596826,2245193,146 -1597996,2245339,139 -1598578,2245478,150 -1598833,2245628,241 -1599203,2245869,154 -1599295,2246023,187 -1599313,2246210,175 -1599408,2246385,190 -1599618,2246575,186 -1600921,2246761,205 -1601815,2246966,151 -1604002,2247117,185 -1604243,2247302,232 -1604737,2247534,147 -1605333,2247681,182 -1605838,2247863,165 -1605877,2248028,198 -1606169,2248226,237 -1606449,2248463,175 -1606591,2248638,225 -1606672,2248863,187 -1607226,2249050,152 -1607340,2249202,138 -1607574,2249340,156 -1607767,2249496,253 -1608159,2249749,174 -1609429,2249923,204 -1609465,2250127,184 -1610284,2250311,169 -1611775,2250480,216 -1612391,2250696,151 -1612893,2250847,136 -1613564,2250983,120 -1614824,2251103,221 -1616133,2251324,167 -1616216,2251491,180 -1616283,2251671,127 -1616453,2251798,148 -1616885,2251946,186 -1617229,2252132,189 -1617595,2252321,233 -1617761,2252554,130 -1617807,2252684,120 -1617823,2252804,178 -1618281,2252982,133 -1618441,2253115,169 -1618874,2253284,135 -1618992,2253419,131 -1619345,2253550,181 -1619870,2253731,147 -1621421,2253878,167 -1622150,2254045,154 -1623121,2254199,172 -1623434,2254371,194 -1624295,2254565,241 -1625123,2254806,211 -1625950,2255017,206 -1626225,2255223,204 -1627574,2255427,158 -1627754,2255585,122 -1627855,2255707,145 -1628489,2255852,147 -1629270,2255999,307 -1630856,2256306,132 -1630914,2256438,159 -1632040,2256597,136 -1632244,2256733,120 -1632271,2256853,156 -1632477,2257009,232 -1633897,2257241,120 -1634147,2257361,170 -1634629,2257531,167 -1635434,2257698,199 -1635907,2257897,120 -1635920,2258017,198 -1636474,2258215,169 -1636975,2258384,154 -1637243,2258538,141 -1637535,2258679,229 -1637940,2258908,153 -1638159,2259061,166 -1638190,2259227,283 -1836630,2259510,168 -1837249,2259678,155 -1837906,2259833,155 -1839055,2259988,148 -1839585,2260136,149 -1839773,2260285,188 -1840200,2260473,147 -1840307,2260620,142 -1841107,2260762,170 -1841226,2260932,243 -1841630,2261175,133 -1841856,2261308,120 -1842024,2261428,148 -1842429,2261576,276 -1842535,2261852,285 -1842566,2262137,136 -1848141,2262273,126 -1848439,2262399,153 -1848817,2262552,216 -1849279,2262768,157 -1849671,2262925,219 -1849935,2263144,170 -1850855,2263314,144 -1851012,2263458,201 -1851736,2263659,144 -1852396,2263803,193 -1852819,2263996,144 -1853504,2264140,148 -1853689,2264288,144 -1854199,2264432,163 -1854393,2264595,152 -1854422,2264747,164 -1855925,2264911,120 -1856022,2265031,214 -1856214,2265245,209 -1858110,2265454,241 -1858155,2265695,170 -1858645,2265865,156 -1858656,2266021,204 -1859583,2266225,316 -1860280,2266541,175 -1860535,2266716,147 -1861021,2266863,200 -1861229,2267063,187 -1861290,2267250,159 -1862053,2267409,148 -1862266,2267557,136 -1862602,2267693,158 -1863525,2267851,179 -1864968,2268030,219 -1865418,2268249,210 -1865785,2268459,255 -1866529,2268714,157 -1866769,2268871,135 -1866821,2269006,190 -1866951,2269196,133 -1867042,2269329,160 -1867345,2269489,175 -1867493,2269664,169 -1868609,2269833,277 -1868720,2270110,140 -1868900,2270250,216 -1869485,2270466,171 -1871452,2270637,239 -1871502,2270876,213 -1871754,2271089,148 -1872249,2271237,210 -1873042,2271447,158 -1873245,2271605,165 -1873311,2271770,192 -1873498,2271962,193 -1873725,2272155,132 -1874252,2272287,181 -1874982,2272468,178 -1875659,2272646,270 -1876657,2272916,158 -1877298,2273074,192 -1877872,2273266,239 -1878535,2273505,170 -1878785,2273675,159 -1878951,2273834,120 -1879505,2273954,189 -1879813,2274143,175 -1880055,2274318,200 -1880212,2274518,171 -1880447,2274689,146 -1880643,2274835,113 -1881900,2274948,168 -1882764,2275116,144 -1883048,2275260,185 -1883406,2275445,161 -1883577,2275606,196 -1884442,2275802,129 -1884638,2275931,167 -1884950,2276098,192 -1885574,2276290,161 -1885756,2276451,216 -1885997,2276667,239 -1886947,2276906,278 -1889292,2277184,183 -1892007,2277367,136 -1892111,2277503,170 -1892709,2277673,177 -1892754,2277850,161 -1893068,2278011,144 -1893931,2278155,120 -1894087,2278275,136 -1894493,2278411,136 -1896168,2278547,164 -1896510,2278711,151 -1896545,2278862,133 -1897674,2278995,55 -1897959,2279050,164 -1899112,2279214,242 -1899707,2279456,136 -1900199,2279592,156 -2097487,2279748,185 -2097839,2279933,178 -2098437,2280111,200 -2098664,2280311,146 -2099437,2280457,244 -2099806,2280701,260 -2100167,2280961,194 -2100424,2281155,151 -2100885,2281306,157 -2101370,2281463,233 -2101847,2281696,183 -2101973,2281879,196 -2102240,2282075,175 -2103000,2282250,208 -2103310,2282458,239 -2103814,2282697,242 -2104579,2282939,130 -2105765,2283069,160 -2106724,2283229,172 -2106776,2283401,158 -2107580,2283559,186 -2108353,2283745,285 -2108599,2284030,281 -2109931,2284311,132 -2111238,2284443,170 -2111420,2284613,191 -2112007,2284804,136 -2113541,2284940,128 -2113882,2285068,127 -2114618,2285195,217 -2115233,2285412,182 -2115321,2285594,189 -2115399,2285783,129 -2116266,2285912,147 -2116717,2286059,180 -2116766,2286239,125 -2117227,2286364,132 -2117247,2286496,139 -2118602,2286635,190 -2118774,2286825,153 -2119457,2286978,198 -2120096,2287176,176 -2120192,2287352,121 -2120490,2287473,55 -2120542,2287528,249 -2120954,2287777,233 -2122356,2288010,158 -2122591,2288168,127 -2122802,2288295,205 -2123697,2288500,128 -2123933,2288628,206 -2124426,2288834,233 -2124543,2289067,216 -2125468,2289283,175 -2125804,2289458,138 -2126677,2289596,166 -2127055,2289762,243 -2127360,2290005,165 -2127507,2290170,208 -2129039,2290378,173 -2129268,2290551,120 -2131340,2290671,142 -2131884,2290813,159 -2132356,2290972,230 -2132358,2291202,160 -2134344,2291362,139 -2134410,2291501,126 -2134489,2291627,122 -2134861,2291749,237 -2136809,2291986,250 -2136997,2292236,244 -2138852,2292480,120 -2138855,2292600,168 -2140039,2292768,219 -2140571,2292987,152 -2140709,2293139,132 -2140747,2293271,152 -2142455,2293423,139 -2143129,2293562,126 -2143686,2293688,157 -2144192,2293845,143 -2145216,2293988,136 -2145222,2294124,161 -2146267,2294285,123 -2146413,2294408,252 -2146735,2294660,217 -2147215,2294877,147 -2147853,2295024,226 -2148075,2295250,194 -2148531,2295444,213 -2148816,2295657,120 -2149689,2295777,149 -2150084,2295926,155 -2150192,2296081,162 -2150943,2296243,187 -2151312,2296430,175 -2151851,2296605,182 -2151871,2296787,191 -2151943,2296978,137 -2152282,2297115,186 -2152710,2297301,142 -2153619,2297443,181 -2153702,2297624,279 -2154303,2297903,226 -2155527,2298129,126 -2155818,2298255,151 -2155876,2298406,147 -2156433,2298553,180 -2157255,2298733,275 -2157940,2299008,196 -2158278,2299204,213 -2158594,2299417,168 -2159523,2299585,239 -2159643,2299824,258 -2160734,2300082,196 -2161339,2300278,206 -2162161,2300484,181 -2162381,2300665,181 -2162395,2300846,174 -2359751,2301020,136 -2360591,2301156,223 -2361623,2301379,182 -2361749,2301561,239 -2361873,2301800,219 -2361956,2302019,202 -2362154,2302221,174 -2362289,2302395,187 -2363492,2302582,206 -2363685,2302788,200 -2363720,2302988,153 -2363856,2303141,275 -2366092,2303416,148 -2366227,2303564,229 -2366276,2303793,225 -2366468,2304018,286 -2367276,2304304,157 -2367915,2304461,167 -2368526,2304628,120 -2369090,2304748,171 -2371578,2304919,190 -2372460,2305109,55 -2373452,2305164,143 -2373615,2305307,187 -2374688,2305494,160 -2376380,2305654,195 -2377111,2305849,186 -2377486,2306035,118 -2378107,2306153,177 -2378499,2306330,190 -2378625,2306520,175 -2379549,2306695,127 -2383839,2306822,167 -2384504,2306989,202 -2385135,2307191,229 -2385169,2307420,113 -2386238,2307533,200 -2386250,2307733,171 -2386341,2307904,241 -2386603,2308145,179 -2388361,2308324,142 -2389590,2308466,260 -2389629,2308726,143 -2389763,2308869,166 -2391868,2309035,239 -2392064,2309274,126 -2392490,2309400,202 -2392714,2309602,163 -2393844,2309765,151 -2393863,2309916,198 -2397130,2310114,190 -2397250,2310304,173 -2397444,2310477,143 -2398189,2310620,251 -2399915,2310871,194 -2400372,2311065,120 -2400993,2311185,130 -2401324,2311315,134 -2401340,2311449,162 -2401429,2311611,161 -2402429,2311772,264 -2402615,2312036,143 -2403201,2312179,120 -2404170,2312299,154 -2404180,2312453,179 -2404521,2312632,219 -2405975,2312851,170 -2406072,2313021,119 -2406141,2313140,138 -2406540,2313278,172 -2406610,2313450,201 -2406960,2313651,174 -2407361,2313825,165 -2407554,2313990,164 -2407941,2314154,153 -2408308,2314307,55 -2408627,2314362,131 -2410134,2314493,175 -2410568,2314668,151 -2410606,2314819,155 -2410913,2314974,144 -2410974,2315118,191 -2411495,2315309,146 -2412321,2315455,260 -2412863,2315715,182 -2413260,2315897,173 -2414881,2316070,138 -2415286,2316208,224 -2415532,2316432,285 -2415533,2316717,182 -2415597,2316899,175 -2416326,2317074,141 -2417265,2317215,241 -2417428,2317456,120 -2418090,2317576,176 -2418362,2317752,171 -2419123,2317923,136 -2419264,2318059,153 -2419557,2318212,141 -2419865,2318353,172 -2419926,2318525,211 -2420282,2318736,210 -2420991,2318946,160 -2421469,2319106,161 -2422186,2319267,190 -2424146,2319457,195 -2622688,2319652,149 -2623006,2319801,218 -2623117,2320019,125 -2624348,2320144,120 -2624696,2320264,197 -2625020,2320461,168 -2625659,2320629,169 -2626673,2320798,179 -2627118,2320977,127 -2627534,2321104,188 -2627704,2321292,158 -2627837,2321450,165 -2630214,2321615,177 -2631334,2321792,164 -2631773,2321956,225 -2632140,2322181,164 -2632153,2322345,224 -2632882,2322569,265 -2634066,2322834,194 -2634437,2323028,181 -2634768,2323209,202 -2634914,2323411,136 -2635575,2323547,120 -2635983,2323667,182 -2636263,2323849,213 -2636694,2324062,138 -2637028,2324200,238 -2637850,2324438,153 -2638113,2324591,156 -2638896,2324747,200 -2639786,2324947,130 -2639942,2325077,140 -2640979,2325217,152 -2641298,2325369,126 -2641623,2325495,160 -2641870,2325655,260 -2642226,2325915,254 -2642656,2326169,306 -2643815,2326475,169 -2644715,2326644,120 -2645979,2326764,285 -2646086,2327049,227 -2646164,2327276,129 -2646838,2327405,193 -2647403,2327598,229 -2648760,2327827,120 -2648762,2327947,120 -2649495,2328067,173 -2649812,2328240,192 -2650500,2328432,183 -2650821,2328615,164 -2650864,2328779,106 -2651664,2328885,178 -2652564,2329063,239 -2654243,2329302,151 -2655482,2329453,169 -2655533,2329622,146 -2656533,2329768,138 -2656796,2329906,149 -2658768,2330055,243 -2658890,2330298,153 -2659326,2330451,170 -2659343,2330621,170 -2659503,2330791,156 -2660475,2330947,175 -2660939,2331122,150 -2661114,2331272,195 -2662111,2331467,191 -2662790,2331658,163 -2662802,2331821,140 -2662891,2331961,419 -2662977,2332380,138 -2663796,2332518,166 -2663918,2332684,194 -2666250,2332878,174 -2666700,2333052,129 -2667197,2333181,166 -2667435,2333347,146 -2669080,2333493,138 -2669237,2333631,175 -2669401,2333806,179 -2670235,2333985,159 -2670810,2334144,149 -2671325,2334293,213 -2672241,2334506,130 -2672270,2334636,151 -2672408,2334787,141 -2672590,2334928,136 -2672677,2335064,253 -2672916,2335317,166 -2673643,2335483,118 -2673665,2335601,175 -2673919,2335776,160 -2673948,2335936,123 -2673996,2336059,153 -2674076,2336212,258 -2674650,2336470,120 -2674665,2336590,120 -2675119,2336710,134 -2675268,2336844,244 -2676086,2337088,158 -2677054,2337246,142 -2677130,2337388,193 -2677143,2337581,169 -2677633,2337750,220 -2678518,2337970,140 -2678828,2338110,120 -2679116,2338230,132 -2679447,2338362,229 -2679583,2338591,230 -2679623,2338821,215 -2679926,2339036,163 -2680328,2339199,121 -2680553,2339320,184 -2680724,2339504,183 -2680783,2339687,120 -2682200,2339807,132 -2682412,2339939,171 -2682625,2340110,55 -2683736,2340165,180 -2684210,2340345,144 -2684422,2340489,131 -2685907,2340620,250 -2686033,2340870,237 -2686198,2341107,271 -2686336,2341378,278 -2883628,2341656,110 -2883635,2341766,140 -2883831,2341906,138 -2883851,2342044,177 -2885155,2342221,153 -2885436,2342374,179 -2887873,2342553,161 -2889902,2342714,207 -2890116,2342921,150 -2890289,2343071,207 -2891498,2343278,129 -2891555,2343407,120 -2892146,2343527,149 -2892895,2343676,120 -2893407,2343796,278 -2893509,2344074,164 -2893783,2344238,188 -2893869,2344426,195 -2894231,2344621,158 -2895176,2344779,144 -2895976,2344923,170 -2896762,2345093,219 -2896935,2345312,150 -2897239,2345462,182 -2897568,2345644,146 -2897656,2345790,170 -2897713,2345960,273 -2897814,2346233,179 -2898326,2346412,132 -2898369,2346544,142 -2898472,2346686,149 -2898941,2346835,227 -2899663,2347062,136 -2899768,2347198,170 -2899774,2347368,135 -2900280,2347503,188 -2900993,2347691,175 -2901019,2347866,201 -2901245,2348067,151 -2904201,2348218,243 -2904906,2348461,220 -2905133,2348681,170 -2905295,2348851,173 -2905404,2349024,144 -2906597,2349168,151 -2906629,2349319,130 -2906787,2349449,183 -2907105,2349632,185 -2907539,2349817,150 -2908147,2349967,148 -2908172,2350115,207 -2908762,2350322,197 -2908809,2350519,192 -2910203,2350711,274 -2910650,2350985,165 -2910831,2351150,278 -2911221,2351428,147 -2912597,2351575,169 -2912963,2351744,142 -2913551,2351886,234 -2913930,2352120,167 -2915162,2352287,122 -2915204,2352409,164 -2916047,2352573,132 -2916453,2352705,170 -2916696,2352875,197 -2919026,2353072,177 -2919410,2353249,162 -2920743,2353411,157 -2921004,2353568,186 -2921572,2353754,202 -2921855,2353956,151 -2922263,2354107,137 -2923172,2354244,129 -2924127,2354373,147 -2924284,2354520,133 -2924887,2354653,183 -2925236,2354836,188 -2925326,2355024,227 -2926464,2355251,197 -2926645,2355448,118 -2927397,2355566,304 -2927524,2355870,143 -2927891,2356013,240 -2928733,2356253,139 -2928863,2356392,193 -2929722,2356585,120 -2930323,2356705,122 -2930333,2356827,162 -2932232,2356989,120 -2932375,2357109,187 -2933344,2357296,140 -2934088,2357436,172 -2934227,2357608,144 -2935829,2357752,130 -2936103,2357882,138 -2936131,2358020,157 -2936169,2358177,135 -2936922,2358312,207 -2937153,2358519,278 -2937306,2358797,149 -2937575,2358946,137 -2937924,2359083,199 -2940172,2359282,133 -2941608,2359415,194 -2941970,2359609,148 -2942668,2359757,142 -2943089,2359899,156 -2944491,2360055,224 -2944550,2360279,174 -2945262,2360453,120 -2945539,2360573,164 -2946245,2360737,138 -2947057,2360875,216 -2947746,2361091,143 -3147100,2361234,166 -3148700,2361400,186 -3149098,2361586,253 -3149525,2361839,187 -3149539,2362026,150 -3150003,2362176,210 -3150052,2362386,132 -3150893,2362518,134 -3150922,2362652,177 -3151128,2362829,219 -3151501,2363048,114 -3151816,2363162,176 -3152079,2363338,152 -3152230,2363490,175 -3152424,2363665,155 -3154267,2363820,288 -3157480,2364108,151 -3158676,2364259,159 -3158740,2364418,209 -3158837,2364627,129 -3159974,2364756,170 -3160149,2364926,137 -3160358,2365063,178 -3160405,2365241,276 -3160562,2365517,137 -3160676,2365654,166 -3161352,2365820,166 -3161773,2365986,149 -3162484,2366135,145 -3162661,2366280,136 -3163209,2366416,119 -3163802,2366535,139 -3164475,2366674,218 -3165310,2366892,225 -3165891,2367117,214 -3166712,2367331,147 -3166810,2367478,185 -3167725,2367663,208 -3168172,2367871,184 -3168603,2368055,136 -3168695,2368191,134 -3169592,2368325,122 -3170339,2368447,166 -3170578,2368613,126 -3170584,2368739,163 -3171820,2368902,204 -3172492,2369106,163 -3172683,2369269,118 -3173566,2369387,212 -3173980,2369599,164 -3174834,2369763,253 -3175248,2370016,130 -3175698,2370146,157 -3176047,2370303,153 -3176395,2370456,230 -3176555,2370686,240 -3176642,2370926,234 -3177520,2371160,118 -3178187,2371278,145 -3179945,2371423,160 -3180336,2371583,285 -3180953,2371868,208 -3181011,2372076,244 -3181819,2372320,144 -3182763,2372464,120 -3182991,2372584,146 -3183350,2372730,238 -3185581,2372968,192 -3188955,2373160,157 -3189437,2373317,251 -3190395,2373568,182 -3190518,2373750,139 -3191318,2373889,152 -3191714,2374041,259 -3192258,2374300,260 -3192305,2374560,220 -3196752,2374780,148 -3196846,2374928,175 -3196970,2375103,149 -3198375,2375252,224 -3199358,2375476,199 -3199831,2375675,179 -3200106,2375854,160 -3200391,2376014,200 -3200713,2376214,175 -3202694,2376389,161 -3204238,2376550,158 -3204315,2376708,170 -3205925,2376878,198 -3207121,2377076,234 -3207965,2377310,160 -3207989,2377470,194 -3207994,2377664,127 -3208239,2377791,149 -3208973,2377940,138 -3209157,2378078,120 -3209175,2378198,203 -3209709,2378401,168 -3209911,2378569,190 -3210513,2378759,171 -3408035,2378930,194 -3408518,2379124,166 -3408539,2379290,213 -3409915,2379503,128 -3409924,2379631,174 -3410466,2379805,215 -3410687,2380020,232 -3410752,2380252,160 -3412632,2380412,120 -3412904,2380532,180 -3412968,2380712,166 -3413406,2380878,120 -3413995,2380998,141 -3414604,2381139,216 -3414818,2381355,237 -3416329,2381592,140 -3416967,2381732,202 -3417018,2381934,227 -3417437,2382161,211 -3418352,2382372,203 -3418602,2382575,154 -3420014,2382729,151 -3420433,2382880,175 -3420612,2383055,119 -3421755,2383174,120 -3422383,2383294,151 -3423640,2383445,220 -3424437,2383665,134 -3425903,2383799,146 -3427133,2383945,221 -3427152,2384166,177 -3427492,2384343,226 -3427818,2384569,160 -3427831,2384729,160 -3428159,2384889,207 -3428188,2385096,129 -3428201,2385225,132 -3428778,2385357,231 -3428809,2385588,120 -3431185,2385708,117 -3431488,2385825,153 -3431696,2385978,113 -3432824,2386091,180 -3433096,2386271,136 -3433641,2386407,151 -3434570,2386558,183 -3434645,2386741,217 -3435475,2386958,239 -3435535,2387197,184 -3436170,2387381,169 -3436432,2387550,136 -3436434,2387686,178 -3438023,2387864,141 -3438277,2388005,157 -3438711,2388162,224 -3439200,2388386,139 -3440185,2388525,138 -3440819,2388663,204 -3440951,2388867,135 -3441092,2389002,113 -3441374,2389115,150 -3441410,2389265,155 -3441734,2389420,138 -3442218,2389558,160 -3442493,2389718,208 -3442781,2389926,181 -3443374,2390107,145 -3446235,2390252,148 -3446779,2390400,174 -3447151,2390574,154 -3447255,2390728,175 -3447309,2390903,165 -3447643,2391068,142 -3448208,2391210,163 -3448372,2391373,226 -3449219,2391599,137 -3449749,2391736,120 -3449791,2391856,207 -3450205,2392063,184 -3450337,2392247,133 -3450508,2392380,206 -3450633,2392586,125 -3450810,2392711,210 -3450947,2392921,169 -3450958,2393090,125 -3451531,2393215,175 -3451545,2393390,134 -3451630,2393524,155 -3452388,2393679,198 -3452716,2393877,166 -3453431,2394043,144 -3454321,2394187,120 -3454973,2394307,273 -3455569,2394580,160 -3455642,2394740,205 -3455775,2394945,148 -3455782,2395093,173 -3456166,2395266,217 -3456456,2395483,138 -3456505,2395621,189 -3456506,2395810,143 -3456512,2395953,175 -3456912,2396128,221 -3457113,2396349,120 -3457964,2396469,158 -3458512,2396627,183 -3458714,2396810,162 -3458865,2396972,147 -3459075,2397119,134 -3459485,2397253,220 -3460136,2397473,210 -3460461,2397683,167 -3460542,2397850,244 -3460756,2398094,207 -3461275,2398301,195 -3461828,2398496,158 -3463092,2398654,173 -3464189,2398827,136 -3464730,2398963,166 -3464756,2399129,151 -3465002,2399280,224 -3465423,2399504,156 -3465431,2399660,225 -3465981,2399885,120 -3466282,2400005,163 -3466925,2400168,166 -3466967,2400334,129 -3469124,2400463,124 -3469195,2400587,204 -3469514,2400791,293 -3470235,2401084,116 -3470893,2401200,169 -3471058,2401369,200 -3471720,2401569,148 -3471936,2401717,254 -3472495,2401971,157 -3472623,2402128,154 -3670423,2402282,289 -3671732,2402571,127 -3672317,2402698,133 -3672484,2402831,149 -3672586,2402980,282 -3672724,2403262,175 -3672896,2403437,175 -3673556,2403612,180 -3673723,2403792,171 -3673930,2403963,120 -3674084,2404083,156 -3675857,2404239,175 -3676006,2404414,145 -3676463,2404559,134 -3677210,2404693,136 -3677258,2404829,231 -3678877,2405060,135 -3678934,2405195,189 -3679787,2405384,176 -3679949,2405560,127 -3680490,2405687,212 -3681144,2405899,218 -3681354,2406117,162 -3681745,2406279,175 -3682732,2406454,147 -3685320,2406601,127 -3686160,2406728,199 -3686963,2406927,156 -3687078,2407083,156 -3687273,2407239,177 -3687820,2407416,234 -3687944,2407650,159 -3688524,2407809,120 -3689334,2407929,135 -3690480,2408064,209 -3691034,2408273,143 -3692556,2408416,147 -3693048,2408563,149 -3693049,2408712,199 -3693224,2408911,220 -3694531,2409131,190 -3694711,2409321,167 -3695547,2409488,151 -3695606,2409639,235 -3696197,2409874,179 -3696531,2410053,206 -3697595,2410259,147 -3697819,2410406,153 -3698209,2410559,202 -3699392,2410761,186 -3701575,2410947,156 -3703621,2411103,269 -3705308,2411372,172 -3705527,2411544,160 -3706599,2411704,141 -3707387,2411845,144 -3708054,2411989,161 -3708306,2412150,211 -3710851,2412361,130 -3712316,2412491,155 -3712438,2412646,270 -3713105,2412916,133 -3713131,2413049,122 -3713375,2413171,136 -3713596,2413307,187 -3715373,2413494,153 -3715547,2413647,230 -3716541,2413877,158 -3716941,2414035,151 -3717923,2414186,154 -3717948,2414340,144 -3718170,2414484,189 -3718959,2414673,155 -3718963,2414828,193 -3719318,2415021,160 -3720970,2415181,154 -3721146,2415335,161 -3721308,2415496,155 -3721641,2415651,192 -3721879,2415843,148 -3723573,2415991,201 -3725359,2416192,159 -3726267,2416351,203 -3726944,2416554,148 -3727502,2416702,173 -3728789,2416875,222 -3729368,2417097,173 -3729631,2417270,166 -3729804,2417436,134 -3730087,2417570,151 -3730449,2417721,211 -3730660,2417932,159 -3731101,2418091,128 -3731608,2418219,160 -3732287,2418379,147 -3732887,2418526,134 -3733256,2418660,186 -3733641,2418846,239 -3733687,2419085,174 -3734218,2419259,249 -3735237,2419508,135 -3932849,2419643,157 -3933375,2419800,189 -3933611,2419989,157 -3934036,2420146,120 -3934065,2420266,141 -3934238,2420407,219 -3934454,2420626,136 -3934573,2420762,145 -3935304,2420907,139 -3935779,2421046,136 -3936193,2421182,157 -3936320,2421339,161 -3936367,2421500,156 -3937730,2421656,120 -3937770,2421776,171 -3938463,2421947,130 -3938464,2422077,245 -3938581,2422322,134 -3938685,2422456,138 -3938831,2422594,149 -3938903,2422743,149 -3938937,2422892,222 -3939518,2423114,141 -3939844,2423255,168 -3939859,2423423,232 -3941847,2423655,149 -3942101,2423804,143 -3942243,2423947,189 -3943572,2424136,308 -3943863,2424444,155 -3944250,2424599,132 -3944460,2424731,159 -3944824,2424890,132 -3946045,2425022,132 -3946212,2425154,148 -3946632,2425302,154 -3946947,2425456,179 -3946983,2425635,278 -3947123,2425913,138 -3948623,2426051,227 -3949454,2426278,147 -3950296,2426425,258 -3950353,2426683,194 -3950903,2426877,162 -3951250,2427039,167 -3951721,2427206,189 -3952199,2427395,136 -3954621,2427531,157 -3954645,2427688,121 -3955255,2427809,159 -3955380,2427968,158 -3956419,2428126,136 -3956481,2428262,179 -3956996,2428441,149 -3957248,2428590,200 -3957368,2428790,268 -3958572,2429058,137 -3959421,2429195,173 -3959453,2429368,186 -3960419,2429554,131 -3960645,2429685,148 -3960823,2429833,157 -3960921,2429990,145 -3961911,2430135,118 -3962186,2430253,147 -3962854,2430400,201 -3964337,2430601,144 -3965400,2430745,148 -3965813,2430893,158 -3965877,2431051,216 -3966632,2431267,179 -3967398,2431446,163 -3967664,2431609,149 -3967717,2431758,218 -3967998,2431976,159 -3968064,2432135,204 -3969323,2432339,142 -3969367,2432481,211 -3969396,2432692,242 -3970261,2432934,149 -3970830,2433083,210 -3970942,2433293,212 -3971263,2433505,157 -3971575,2433662,140 -3972993,2433802,261 -3973389,2434063,175 -3973909,2434238,215 -3973914,2434453,178 -3974955,2434631,161 -3975210,2434792,148 -3975668,2434940,166 -3975743,2435106,150 -3976078,2435256,120 -3976809,2435376,176 -3977563,2435552,138 -3977599,2435690,149 -3979154,2435839,203 -3979386,2436042,55 -3979686,2436097,165 -3980760,2436262,178 -3981510,2436440,166 -3981612,2436606,137 -3981814,2436743,176 -3981891,2436919,147 -3982049,2437066,186 -3983774,2437252,208 -3984007,2437460,146 -3984252,2437606,171 -3984730,2437777,170 -3984787,2437947,178 -3984917,2438125,156 -3985011,2438281,170 -3985656,2438451,120 -3985774,2438571,234 -3986646,2438805,158 -3987418,2438963,236 -3987755,2439199,188 -3987918,2439387,147 -3988010,2439534,159 -3989278,2439693,170 -3989417,2439863,148 -3989437,2440011,244 -3989618,2440255,120 -3990950,2440375,255 -3990964,2440630,227 -3991076,2440857,177 -3992143,2441034,127 -3992315,2441161,121 -3994514,2441282,182 -3994924,2441464,137 -3995434,2441601,135 -3995464,2441736,259 -3995656,2441995,199 -3996566,2442194,170 -3997182,2442364,166 -4194567,2442530,140 -4194758,2442670,173 -4195340,2442843,165 -4196288,2443008,156 -4197991,2443164,127 -4198021,2443291,227 -4198876,2443518,142 -4199140,2443660,122 -4199385,2443782,117 -4199831,2443899,162 -4200062,2444061,188 -4200095,2444249,248 -4200186,2444497,136 -4200625,2444633,158 -4200663,2444791,147 -4201817,2444938,172 -4203245,2445110,173 -4203970,2445283,166 -4204299,2445449,223 -4204564,2445672,144 -4205473,2445816,176 -4205812,2445992,249 -4206596,2446241,120 -4206695,2446361,169 -4207468,2446530,260 -4208557,2446790,225 -4209916,2447015,120 -4210722,2447135,130 -4210795,2447265,114 -4212186,2447379,277 -4213251,2447656,206 -4213272,2447862,150 -4214158,2448012,285 -4214507,2448297,199 -4215008,2448496,178 -4215148,2448674,214 -4215309,2448888,198 -4216121,2449086,170 -4216332,2449256,175 -4217499,2449431,135 -4218814,2449566,118 -4218818,2449684,144 -4218970,2449828,184 -4219270,2450012,180 -4219278,2450192,138 -4219574,2450330,176 -4220538,2450506,171 -4220966,2450677,152 -4221611,2450829,118 -4222095,2450947,120 -4222762,2451067,148 -4222985,2451215,166 -4223050,2451381,206 -4223092,2451587,262 -4224150,2451849,184 -4225130,2452033,173 -4225141,2452206,231 -4225664,2452437,134 -4225819,2452571,158 -4227040,2452729,239 -4227670,2452968,163 -4228062,2453131,173 -4228243,2453304,124 -4229344,2453428,316 -4229786,2453744,171 -4229895,2453915,165 -4230134,2454080,223 -4230492,2454303,203 -4232536,2454506,165 -4233169,2454671,166 -4233292,2454837,146 -4233294,2454983,144 -4233339,2455127,161 -4233997,2455288,284 -4235207,2455572,184 -4236783,2455756,330 -4236919,2456086,149 -4236964,2456235,172 -4237017,2456407,120 -4237032,2456527,136 -4237552,2456663,151 -4238477,2456814,154 -4239610,2456968,159 -4240072,2457127,148 -4240277,2457275,120 -4240333,2457395,166 -4240380,2457561,184 -4240624,2457745,149 -4241073,2457894,193 -4241395,2458087,147 -4241463,2458234,157 -4241562,2458391,219 -4242017,2458610,205 -4242547,2458815,176 -4242571,2458991,143 -4242846,2459134,150 -4243223,2459284,185 -4244037,2459469,223 -4244694,2459692,266 -4245034,2459958,269 -4245449,2460227,136 -4246440,2460363,244 -4246842,2460607,136 -4248202,2460743,166 -4248365,2460909,120 -4248590,2461029,134 -4248921,2461163,190 -4249685,2461353,276 -4252208,2461629,216 -4253488,2461845,163 -4253587,2462008,254 -4254414,2462262,248 -4254968,2462510,122 -4255564,2462632,216 -4255791,2462848,208 -4256076,2463056,122 -4256257,2463178,145 -4256489,2463323,151 -4256520,2463474,181 -4256775,2463655,161 -4257004,2463816,170 -4257070,2463986,181 -4258953,2464167,147 -4457383,2464314,136 -4459773,2464450,174 -4460994,2464624,179 -4461337,2464803,174 -4462671,2464977,148 -4463030,2465125,227 -4464273,2465352,212 -4464289,2465564,167 -4465578,2465731,169 -4466107,2465900,186 -4467000,2466086,241 -4467296,2466327,120 -4467455,2466447,171 -4467459,2466618,170 -4469138,2466788,151 -4469290,2466939,138 -4469448,2467077,159 -4469580,2467236,168 -4469903,2467404,179 -4470127,2467583,147 -4470553,2467730,194 -4470639,2467924,148 -4470758,2468072,187 -4470841,2468259,173 -4471236,2468432,240 -4471964,2468672,157 -4472097,2468829,127 -4472498,2468956,175 -4475025,2469131,160 -4475493,2469291,174 -4475916,2469465,120 -4476442,2469585,175 -4476766,2469760,202 -4477403,2469962,162 -4478144,2470124,155 -4478385,2470279,194 -4478605,2470473,215 -4478647,2470688,139 -4479017,2470827,160 -4479391,2470987,161 -4480717,2471148,146 -4480755,2471294,164 -4480890,2471458,261 -4481330,2471719,139 -4481436,2471858,198 -4482670,2472056,157 -4482901,2472213,141 -4483243,2472354,185 -4484132,2472539,204 -4484439,2472743,192 -4484460,2472935,161 -4485131,2473096,164 -4485272,2473260,272 -4486252,2473532,157 -4488132,2473689,240 -4488319,2473929,172 -4488613,2474101,263 -4488822,2474364,193 -4488853,2474557,150 -4489451,2474707,217 -4490002,2474924,119 -4490496,2475043,166 -4490945,2475209,175 -4491260,2475384,204 -4491467,2475588,147 -4491867,2475735,183 -4492370,2475918,206 -4492818,2476124,148 -4492929,2476272,156 -4493787,2476428,240 -4494588,2476668,151 -4494842,2476819,391 -4494891,2477210,125 -4496248,2477335,150 -4496565,2477485,138 -4498477,2477623,195 -4499081,2477818,172 -4499173,2477990,233 -4499407,2478223,185 -4499522,2478408,126 -4499650,2478534,167 -4500007,2478701,190 -4500200,2478891,174 -4500953,2479065,136 -4502402,2479201,256 -4505948,2479457,144 -4506163,2479601,281 -4506374,2479882,156 -4506523,2480038,146 -4506793,2480184,191 -4506991,2480375,310 -4507291,2480685,270 -4508066,2480955,153 -4509309,2481108,109 -4510046,2481217,203 -4510276,2481420,173 -4510410,2481593,121 -4510666,2481714,170 -4510944,2481884,157 -4511293,2482041,156 -4511794,2482197,192 -4511876,2482389,120 -4512231,2482509,160 -4512913,2482669,184 -4512971,2482853,224 -4513934,2483077,143 -4514103,2483220,148 -4514970,2483368,144 -4515033,2483512,170 -4516005,2483682,205 -4516317,2483887,159 -4517207,2484046,196 -4517424,2484242,176 -4518966,2484418,159 -4519001,2484577,159 -4519031,2484736,149 -4520009,2484885,161 -4520770,2485046,120 -4719146,2485166,231 -4719458,2485397,195 -4720234,2485592,186 -4721737,2485778,180 -4722639,2485958,148 -4723273,2486106,157 -4723699,2486263,178 -4724556,2486441,180 -4724802,2486621,221 -4725380,2486842,161 -4725714,2487003,200 -4726128,2487203,143 -4728552,2487346,148 -4728879,2487494,155 -4730090,2487649,193 -4731869,2487842,171 -4731965,2488013,135 -4734258,2488148,170 -4735868,2488318,120 -4736135,2488438,155 -4736247,2488593,194 -4736753,2488787,109 -4736763,2488896,194 -4739187,2489090,158 -4739511,2489248,166 -4739681,2489414,121 -4740117,2489535,187 -4740447,2489722,221 -4741085,2489943,132 -4741417,2490075,160 -4741695,2490235,137 -4741814,2490372,201 -4741945,2490573,162 -4742454,2490735,128 -4742496,2490863,200 -4743356,2491063,120 -4743587,2491183,168 -4743798,2491351,194 -4746028,2491545,188 -4746129,2491733,169 -4746867,2491902,145 -4747003,2492047,210 -4747218,2492257,165 -4747545,2492422,174 -4748398,2492596,120 -4748804,2492716,55 -4751940,2492771,183 -4753128,2492954,159 -4755010,2493113,127 -4755795,2493240,188 -4755958,2493428,277 -4758498,2493705,184 -4758808,2493889,171 -4758820,2494060,148 -4760109,2494208,249 -4760247,2494457,136 -4761298,2494593,253 -4762066,2494846,181 -4762205,2495027,153 -4764243,2495180,170 -4765095,2495350,230 -4765918,2495580,212 -4766071,2495792,125 -4766146,2495917,137 -4767277,2496054,171 -4767891,2496225,148 -4768172,2496373,156 -4769890,2496529,180 -4769974,2496709,142 -4770670,2496851,188 -4772047,2497039,184 -4772238,2497223,218 -4772388,2497441,206 -4773196,2497647,163 -4773637,2497810,120 -4773887,2497930,176 -4773973,2498106,137 -4774142,2498243,197 -4775163,2498440,132 -4775708,2498572,211 -4776367,2498783,115 -4778481,2498898,120 -4778595,2499018,204 -4778800,2499222,176 -4779392,2499398,177 -4779527,2499575,187 -4779532,2499762,178 -4779654,2499940,245 -4780592,2500185,199 -4780823,2500384,55 -4781181,2500439,236 -4782065,2500675,134 -4782259,2500809,152 -4782305,2500961,141 -4782373,2501102,147 -4783288,2501249,155 -4783850,2501404,122 -4980866,2501526,136 -4981294,2501662,171 -4981385,2501833,191 -4982410,2502024,161 -4982729,2502185,162 -4983220,2502347,174 -4983252,2502521,225 -4983610,2502746,195 -4983742,2502941,134 -4984302,2503075,172 -4984686,2503247,199 -4984775,2503446,240 -4985279,2503686,217 -4985984,2503903,168 -4986019,2504071,219 -4986609,2504290,160 -4986859,2504450,131 -4987450,2504581,209 -4987541,2504790,200 -4988876,2504990,192 -4989392,2505182,163 -4989528,2505345,157 -4990328,2505502,126 -4990695,2505628,181 -4992128,2505809,195 -4992131,2506004,263 -4992925,2506267,147 -4993161,2506414,172 -4993581,2506586,138 -4993753,2506724,185 -4994184,2506909,166 -4995337,2507075,187 -4995344,2507262,217 -4995956,2507479,195 -4996118,2507674,175 -4999386,2507849,251 -5000040,2508100,194 -5000757,2508294,136 -5002279,2508430,149 -5002393,2508579,285 -5002629,2508864,148 -5002680,2509012,163 -5002700,2509175,146 -5004749,2509321,189 -5004812,2509510,142 -5005266,2509652,152 -5005525,2509804,165 -5005534,2509969,139 -5005909,2510108,217 -5006315,2510325,240 -5006553,2510565,219 -5009006,2510784,213 -5010105,2510997,172 -5010279,2511169,175 -5010341,2511344,133 -5010435,2511477,168 -5010981,2511645,129 -5011279,2511774,204 -5011607,2511978,182 -5011898,2512160,166 -5012575,2512326,120 -5013346,2512446,149 -5013583,2512595,158 -5013651,2512753,166 -5014223,2512919,159 -5014494,2513078,143 -5016368,2513221,165 -5016405,2513386,155 -5016559,2513541,239 -5016953,2513780,120 -5017509,2513900,222 -5019156,2514122,149 -5019887,2514271,125 -5021312,2514396,168 -5021412,2514564,177 -5021439,2514741,211 -5022997,2514952,239 -5023085,2515191,175 -5023563,2515366,129 -5024040,2515495,137 -5024278,2515632,215 -5024563,2515847,167 -5024778,2516014,159 -5025329,2516173,255 -5026156,2516428,192 -5026201,2516620,120 -5027050,2516740,171 -5027693,2516911,128 -5027868,2517039,139 -5028296,2517178,143 -5028515,2517321,202 -5028696,2517523,206 -5028930,2517729,265 -5029029,2517994,175 -5030994,2518169,211 -5031426,2518380,142 -5032271,2518522,134 -5032531,2518656,138 -5032949,2518794,160 -5033012,2518954,160 -5034122,2519114,185 -5035575,2519299,210 -5035958,2519509,158 -5036484,2519667,272 -5037885,2519939,214 -5038523,2520153,241 -5038833,2520394,118 -5039734,2520512,164 -5040435,2520676,161 -5040962,2520837,166 -5041630,2521003,172 -5041840,2521175,168 -5042222,2521343,134 -5042879,2521477,193 -5043291,2521670,160 -5043616,2521830,198 -5044023,2522028,178 -5243020,2522206,199 -5243323,2522405,159 -5244221,2522564,171 -5244420,2522735,136 -5245746,2522871,332 -5246573,2523203,173 -5247467,2523376,160 -5248181,2523536,234 -5249023,2523770,136 -5249733,2523906,128 -5250239,2524034,136 -5251179,2524170,210 -5251687,2524380,124 -5252395,2524504,166 -5252752,2524670,199 -5253063,2524869,140 -5253453,2525009,223 -5253758,2525232,148 -5253771,2525380,229 -5254429,2525609,134 -5254562,2525743,166 -5254644,2525909,166 -5254748,2526075,176 -5254862,2526251,184 -5255797,2526435,175 -5257557,2526610,143 -5258436,2526753,282 -5258725,2527035,170 -5259094,2527205,233 -5260893,2527438,162 -5261547,2527600,262 -5261918,2527862,145 -5261934,2528007,151 -5263252,2528158,168 -5263402,2528326,137 -5263461,2528463,139 -5264679,2528602,155 -5264995,2528757,144 -5265064,2528901,122 -5265087,2529023,186 -5265320,2529209,170 -5265408,2529379,176 -5266118,2529555,184 -5267496,2529739,153 -5267844,2529892,141 -5267926,2530033,135 -5268243,2530168,199 -5268545,2530367,121 -5268979,2530488,151 -5269383,2530639,134 -5269422,2530773,136 -5269488,2530909,214 -5270019,2531123,131 -5271450,2531254,160 -5271781,2531414,238 -5272100,2531652,142 -5272141,2531794,175 -5273233,2531969,164 -5273254,2532133,179 -5273947,2532312,203 -5274882,2532515,148 -5275229,2532663,224 -5277033,2532887,189 -5277577,2533076,136 -5277624,2533212,142 -5278274,2533354,203 -5278411,2533557,243 -5278839,2533800,183 -5279087,2533983,168 -5280591,2534151,163 -5281650,2534314,173 -5281905,2534487,214 -5283623,2534701,243 -5283924,2534944,135 -5284031,2535079,162 -5285064,2535241,175 -5285603,2535416,149 -5285653,2535565,136 -5285683,2535701,157 -5286847,2535858,181 -5287381,2536039,148 -5287795,2536187,301 -5289621,2536488,189 -5289923,2536677,225 -5290120,2536902,186 -5290146,2537088,169 -5291359,2537257,258 -5292038,2537515,140 -5292657,2537655,173 -5293453,2537828,149 -5294015,2537977,253 -5294449,2538230,144 -5294496,2538374,137 -5295352,2538511,186 -5295410,2538697,280 -5295733,2538977,218 -5296756,2539195,154 -5297879,2539349,148 -5300423,2539497,165 -5300554,2539662,55 -5301577,2539717,193 -5302998,2539910,120 -5303066,2540030,180 -5303672,2540210,195 -5303700,2540405,171 -5304323,2540576,193 -5304531,2540769,175 -5305404,2540944,127 -5305632,2541071,175 -5305882,2541246,243 -5307051,2541489,127 -5307440,2541616,157 -5307551,2541773,175 -5308146,2541948,196 -5506037,2542144,194 -5506198,2542338,180 -5506214,2542518,163 -5506358,2542681,121 -5506399,2542802,129 -5507469,2542931,173 -5509423,2543104,175 -5509471,2543279,129 -5510259,2543408,211 -5512029,2543619,135 -5512699,2543754,160 -5513173,2543914,147 -5513240,2544061,148 -5513568,2544209,148 -5513976,2544357,160 -5514902,2544517,120 -5515038,2544637,208 -5515932,2544845,165 -5515938,2545010,197 -5516522,2545207,126 -5517193,2545333,167 -5517617,2545500,178 -5518640,2545678,201 -5518815,2545879,140 -5519003,2546019,247 -5519720,2546266,166 -5519839,2546432,198 -5520695,2546630,144 -5521581,2546774,175 -5521993,2546949,168 -5522440,2547117,134 -5523051,2547251,235 -5523968,2547486,136 -5523973,2547622,142 -5523990,2547764,142 -5525830,2547906,188 -5526509,2548094,168 -5526548,2548262,202 -5529277,2548464,131 -5529513,2548595,144 -5529609,2548739,144 -5529970,2548883,151 -5530090,2549034,109 -5530841,2549143,159 -5531102,2549302,148 -5534287,2549450,120 -5534616,2549570,168 -5534950,2549738,139 -5535184,2549877,170 -5535770,2550047,136 -5536117,2550183,147 -5536873,2550330,136 -5537620,2550466,157 -5537704,2550623,170 -5537774,2550793,170 -5538221,2550963,177 -5538939,2551140,139 -5539854,2551279,229 -5540130,2551508,147 -5540248,2551655,192 -5542590,2551847,175 -5542745,2552022,251 -5543032,2552273,186 -5544465,2552459,278 -5544470,2552737,163 -5544722,2552900,159 -5545349,2553059,140 -5545747,2553199,120 -5545781,2553319,129 -5546063,2553448,182 -5546064,2553630,168 -5546612,2553798,152 -5546779,2553950,273 -5547291,2554223,285 -5547339,2554508,175 -5547545,2554683,201 -5548500,2554884,143 -5549607,2555027,120 -5551648,2555147,203 -5551955,2555350,248 -5552138,2555598,168 -5553911,2555766,166 -5556239,2555932,253 -5557520,2556185,204 -5557671,2556389,210 -5557742,2556599,239 -5558509,2556838,198 -5558627,2557036,170 -5558704,2557206,171 -5559407,2557377,140 -5562112,2557517,185 -5562211,2557702,165 -5562418,2557867,149 -5562688,2558016,151 -5563080,2558167,288 -5563104,2558455,139 -5563312,2558594,145 -5563450,2558739,132 -5563581,2558871,228 -5563967,2559099,230 -5564156,2559329,248 -5565096,2559577,132 -5566069,2559709,231 -5566354,2559940,227 -5567926,2560167,208 -5568102,2560375,182 -5568630,2560557,126 -5569086,2560683,189 -5569368,2560872,195 -5569983,2561067,161 -5570511,2561228,152 -5768395,2561380,257 -5768488,2561637,154 -5768534,2561791,141 -5769466,2561932,204 -5769539,2562136,55 -5769701,2562191,172 -5769760,2562363,136 -5771404,2562499,143 -5771843,2562642,183 -5772838,2562825,138 -5773068,2562963,176 -5774525,2563139,148 -5774737,2563287,235 -5775144,2563522,239 -5775207,2563761,190 -5775274,2563951,120 -5775343,2564071,123 -5775670,2564194,163 -5776268,2564357,166 -5778167,2564523,241 -5779198,2564764,169 -5779266,2564933,175 -5780539,2565108,187 -5780953,2565295,170 -5782726,2565465,166 -5783380,2565631,202 -5784292,2565833,209 -5785231,2566042,181 -5785313,2566223,157 -5785348,2566380,268 -5785792,2566648,155 -5785915,2566803,159 -5786042,2566962,198 -5786649,2567160,289 -5786862,2567449,194 -5787766,2567643,187 -5787819,2567830,143 -5787878,2567973,161 -5789130,2568134,120 -5789416,2568254,147 -5789453,2568401,152 -5792666,2568553,127 -5793254,2568680,188 -5793466,2568868,207 -5793562,2569075,160 -5793663,2569235,167 -5794156,2569402,217 -5794297,2569619,158 -5794481,2569777,217 -5795215,2569994,152 -5795542,2570146,55 -5796038,2570201,264 -5797153,2570465,138 -5797493,2570603,192 -5797573,2570795,133 -5798477,2570928,145 -5798889,2571073,191 -5799521,2571264,161 -5799782,2571425,241 -5799863,2571666,183 -5799880,2571849,111 -5801188,2571960,143 -5801326,2572103,119 -5801804,2572222,208 -5801954,2572430,234 -5803273,2572664,170 -5804495,2572834,166 -5804557,2573000,165 -5804950,2573165,157 -5805163,2573322,166 -5805263,2573488,159 -5805854,2573647,136 -5806133,2573783,129 -5806191,2573912,145 -5806859,2574057,210 -5807356,2574267,149 -5808821,2574416,153 -5810031,2574569,149 -5810233,2574718,166 -5812277,2574884,120 -5812436,2575004,185 -5814625,2575189,159 -5814753,2575348,173 -5815335,2575521,170 -5815715,2575691,161 -5815801,2575852,171 -5816298,2576023,170 -5816882,2576193,155 -5817227,2576348,159 -5820235,2576507,156 -5820529,2576663,161 -5820559,2576824,161 -5822163,2576985,145 -5823373,2577130,170 -5824556,2577300,130 -5825318,2577430,225 -5825654,2577655,247 -5826102,2577902,170 -5826375,2578072,130 -5826568,2578202,168 -5827348,2578370,178 -5827809,2578548,153 -5828302,2578701,169 -5829511,2578870,120 -5829532,2578990,136 -5830267,2579126,235 -5830335,2579361,144 -5831054,2579505,130 -5831899,2579635,278 -5831968,2579913,141 -6029930,2580054,168 -6031215,2580222,171 -6031963,2580393,207 -6032571,2580600,187 -6033035,2580787,173 -6033811,2580960,139 -6034487,2581099,171 -6034709,2581270,170 -6034913,2581440,170 -6035143,2581610,161 -6035255,2581771,148 -6035411,2581919,136 -6035637,2582055,173 -6037712,2582228,226 -6038212,2582454,192 -6038649,2582646,130 -6038860,2582776,167 -6039050,2582943,140 -6040303,2583083,160 -6040565,2583243,115 -6041177,2583358,175 -6041298,2583533,241 -6041918,2583774,142 -6042407,2583916,147 -6042460,2584063,159 -6042510,2584222,179 -6042939,2584401,208 -6043098,2584609,140 -6043320,2584749,281 -6043872,2585030,225 -6044469,2585255,147 -6044711,2585402,175 -6045784,2585577,205 -6046183,2585782,221 -6046674,2586003,126 -6047015,2586129,146 -6048294,2586275,183 -6048937,2586458,285 -6049813,2586743,170 -6050127,2586913,166 -6051565,2587079,230 -6051610,2587309,147 -6051784,2587456,135 -6052168,2587591,120 -6052661,2587711,150 -6052802,2587861,201 -6053547,2588062,149 -6054847,2588211,253 -6056324,2588464,137 -6056573,2588601,199 -6056754,2588800,144 -6056783,2588944,55 -6057248,2588999,200 -6057807,2589199,174 -6059863,2589373,146 -6061406,2589519,238 -6063238,2589757,189 -6063690,2589946,144 -6063992,2590090,192 -6064538,2590282,270 -6064596,2590552,212 -6064696,2590764,151 -6065486,2590915,120 -6066144,2591035,156 -6067106,2591191,207 -6067630,2591398,120 -6067818,2591518,139 -6067869,2591657,120 -6068211,2591777,120 -6068952,2591897,198 -6070648,2592095,182 -6071197,2592277,206 -6071275,2592483,153 -6071434,2592636,136 -6073085,2592772,147 -6073420,2592919,199 -6075285,2593118,194 -6075454,2593312,194 -6075684,2593506,171 -6076108,2593677,173 -6076619,2593850,203 -6076673,2594053,148 -6077854,2594201,240 -6078995,2594441,129 -6079956,2594570,166 -6080208,2594736,249 -6080979,2594985,227 -6081074,2595212,143 -6081791,2595355,178 -6082221,2595533,159 -6082869,2595692,166 -6083300,2595858,166 -6083611,2596024,213 -6083755,2596237,130 -6084127,2596367,144 -6085016,2596511,179 -6085332,2596690,185 -6085782,2596875,209 -6086000,2597084,206 -6086853,2597290,166 -6086858,2597456,254 -6086902,2597710,239 -6087203,2597949,149 -6087302,2598098,148 -6087412,2598246,182 -6088639,2598428,274 -6088939,2598702,159 -6089550,2598861,160 -6089576,2599021,230 -6090361,2599251,196 -6091271,2599447,153 -6091632,2599600,166 -6091772,2599766,168 -6091947,2599934,194 -6092045,2600128,192 -6092250,2600320,120 -6092508,2600440,189 -6092739,2600629,244 -6092961,2600873,181 -6093112,2601054,130 -6093162,2601184,239 -6093277,2601423,124 -6093296,2601547,156 -6093926,2601703,136 -6094645,2601839,185 -6094847,2602024,295 -6292114,2602319,183 -6292148,2602502,185 -6292232,2602687,120 -6292295,2602807,214 -6292503,2603021,190 -6295415,2603211,144 -6295961,2603355,165 -6296195,2603520,294 -6296203,2603814,136 -6297031,2603950,121 -6297868,2604071,121 -6297897,2604192,279 -6297968,2604471,263 -6298895,2604734,141 -6299138,2604875,130 -6299907,2605005,187 -6300096,2605192,178 -6300865,2605370,216 -6302292,2605586,150 -6302416,2605736,140 -6304496,2605876,157 -6304587,2606033,120 -6305107,2606153,200 -6305430,2606353,157 -6305501,2606510,166 -6305806,2606676,149 -6306079,2606825,140 -6307781,2606965,176 -6309109,2607141,151 -6309214,2607292,131 -6309309,2607423,153 -6309398,2607576,201 -6309844,2607777,210 -6309926,2607987,191 -6310428,2608178,167 -6312129,2608345,160 -6312236,2608505,223 -6312656,2608728,155 -6313060,2608883,178 -6313752,2609061,166 -6314932,2609227,214 -6316063,2609441,224 -6317053,2609665,218 -6317217,2609883,128 -6317856,2610011,166 -6318404,2610177,130 -6318491,2610307,136 -6319037,2610443,196 -6319206,2610639,166 -6319559,2610805,241 -6320988,2611046,136 -6321293,2611182,164 -6321800,2611346,130 -6322146,2611476,175 -6324523,2611651,159 -6324729,2611810,166 -6325170,2611976,125 -6325307,2612101,142 -6325829,2612243,160 -6326588,2612403,172 -6326705,2612575,152 -6326711,2612727,298 -6327339,2613025,148 -6327575,2613173,215 -6328156,2613388,175 -6328452,2613563,128 -6328855,2613691,120 -6329888,2613811,55 -6330833,2613866,161 -6331044,2614027,158 -6331551,2614185,188 -6332004,2614373,140 -6332317,2614513,132 -6332682,2614645,175 -6333516,2614820,174 -6334718,2614994,158 -6334896,2615152,177 -6336365,2615329,175 -6336901,2615504,129 -6337476,2615633,124 -6338054,2615757,138 -6338071,2615895,221 -6338867,2616116,186 -6338946,2616302,160 -6339340,2616462,235 -6339660,2616697,176 -6339985,2616873,133 -6340277,2617006,163 -6341067,2617169,229 -6341527,2617398,135 -6341959,2617533,120 -6342056,2617653,241 -6342552,2617894,153 -6343040,2618047,177 -6343675,2618224,134 -6344105,2618358,153 -6344133,2618511,193 -6344873,2618704,175 -6345130,2618879,206 -6345401,2619085,202 -6345482,2619287,200 -6346777,2619487,198 -6347168,2619685,284 -6347207,2619969,120 -6347299,2620089,182 -6347562,2620271,201 -6348356,2620472,194 -6348814,2620666,171 -6349607,2620837,253 -6350524,2621090,214 -6350593,2621304,239 -6351190,2621543,147 -6351721,2621690,175 -6353213,2621865,145 -6353289,2622010,179 -6353537,2622189,200 -6353647,2622389,193 -6353882,2622582,157 -6354068,2622739,198 -6354332,2622937,158 -6354547,2623095,164 -6354973,2623259,120 -6355661,2623379,120 -6355778,2623499,120 -6356510,2623619,209 -6356512,2623828,129 -6356677,2623957,120 -6356729,2624077,151 -6356957,2624228,153 -6553645,2624381,178 -6553706,2624559,143 -6553841,2624702,170 -6555070,2624872,167 -6555980,2625039,241 -6556032,2625280,199 -6556490,2625479,197 -6557238,2625676,119 -6557332,2625795,168 -6557480,2625963,127 -6557828,2626090,174 -6558245,2626264,136 -6559359,2626400,133 -6559373,2626533,170 -6559472,2626703,266 -6560290,2626969,169 -6560871,2627138,192 -6561409,2627330,166 -6561804,2627496,120 -6562180,2627616,191 -6562326,2627807,216 -6562816,2628023,133 -6563639,2628156,199 -6565303,2628355,177 -6566224,2628532,167 -6566270,2628699,185 -6566921,2628884,143 -6568625,2629027,263 -6569612,2629290,194 -6569823,2629484,130 -6570516,2629614,163 -6570822,2629777,223 -6572995,2630000,233 -6573040,2630233,141 -6573424,2630374,127 -6573940,2630501,158 -6574000,2630659,169 -6574342,2630828,151 -6574462,2630979,272 -6574745,2631251,167 -6574941,2631418,169 -6575138,2631587,164 -6575459,2631751,153 -6575487,2631904,215 -6575537,2632119,148 -6575617,2632267,262 -6576632,2632529,137 -6576644,2632666,201 -6577623,2632867,330 -6577854,2633197,148 -6578175,2633345,136 -6578723,2633481,192 -6579355,2633673,149 -6579648,2633822,162 -6579891,2633984,262 -6579975,2634246,243 -6580236,2634489,185 -6580668,2634674,212 -6580818,2634886,143 -6581426,2635029,175 -6581868,2635204,141 -6581994,2635345,134 -6582274,2635479,270 -6583000,2635749,201 -6583266,2635950,180 -6583895,2636130,180 -6583994,2636310,120 -6584209,2636430,175 -6585300,2636605,144 -6585396,2636749,191 -6585729,2636940,179 -6586330,2637119,168 -6586507,2637287,144 -6586521,2637431,166 -6586661,2637597,155 -6588296,2637752,149 -6588375,2637901,135 -6588671,2638036,194 -6588826,2638230,160 -6589854,2638390,205 -6592861,2638595,136 -6592872,2638731,142 -6592928,2638873,131 -6593214,2639004,120 -6593316,2639124,193 -6593665,2639317,157 -6593678,2639474,144 -6594291,2639618,170 -6594551,2639788,121 -6594791,2639909,170 -6595122,2640079,142 -6595393,2640221,246 -6595531,2640467,120 -6596457,2640587,157 -6596573,2640744,143 -6596663,2640887,192 -6598156,2641079,170 -6598280,2641249,130 -6599197,2641379,167 -6599440,2641546,175 -6599536,2641721,171 -6599795,2641892,230 -6600266,2642122,143 -6600787,2642265,161 -6601192,2642426,120 -6601405,2642546,159 -6601745,2642705,136 -6604202,2642841,221 -6604391,2643062,152 -6604463,2643214,155 -6605124,2643369,176 -6606893,2643545,174 -6607267,2643719,153 -6607425,2643872,145 -6608061,2644017,160 -6608090,2644177,166 -6608916,2644343,170 -6609170,2644513,163 -6609236,2644676,179 -6609289,2644855,170 -6609688,2645025,145 -6609793,2645170,178 -6609921,2645348,189 -6610460,2645537,158 -6611297,2645695,158 -6612377,2645853,174 -6612517,2646027,164 -6612610,2646191,120 -6613071,2646311,245 -6613138,2646556,147 -6613222,2646703,190 -6613328,2646893,136 -6613701,2647029,190 -6613900,2647219,173 -6614359,2647392,147 -6614370,2647539,192 -6615618,2647731,162 -6616334,2647893,201 -6616733,2648094,136 -6617456,2648230,226 -6617479,2648456,126 -6617985,2648582,278 -6618252,2648860,142 -6817137,2649002,175 -6817226,2649177,166 -6818087,2649343,120 -6818519,2649463,254 -6820397,2649717,237 -6821264,2649954,177 -6821331,2650131,203 -6821381,2650334,244 -6821673,2650578,166 -6822207,2650744,142 -6822578,2650886,159 -6823074,2651045,146 -6823268,2651191,199 -6823563,2651390,156 -6823896,2651546,164 -6824779,2651710,162 -6826170,2651872,108 -6826230,2651980,157 -6827484,2652137,285 -6829749,2652422,156 -6830878,2652578,155 -6831229,2652733,233 -6831852,2652966,122 -6832978,2653088,151 -6834328,2653239,175 -6835080,2653414,175 -6835368,2653589,212 -6836663,2653801,162 -6837485,2653963,164 -6837493,2654127,152 -6838655,2654279,129 -6839093,2654408,120 -6839094,2654528,213 -6839619,2654741,166 -6839915,2654907,200 -6841177,2655107,173 -6841419,2655280,120 -6842670,2655400,143 -6842866,2655543,127 -6843939,2655670,140 -6843976,2655810,214 -6845009,2656024,152 -6845148,2656176,219 -6846031,2656395,157 -6846536,2656552,179 -6846540,2656731,148 -6846756,2656879,136 -6846957,2657015,169 -6847688,2657184,187 -6847701,2657371,169 -6848372,2657540,152 -6849306,2657692,206 -6849648,2657898,179 -6849856,2658077,181 -6849898,2658258,168 -6850215,2658426,136 -6850279,2658562,150 -6850411,2658712,152 -6851253,2658864,148 -6852484,2659012,194 -6853172,2659206,158 -6853667,2659364,199 -6854267,2659563,120 -6854475,2659683,258 -6854632,2659941,219 -6855117,2660160,136 -6855774,2660296,182 -6855792,2660478,120 -6855906,2660598,136 -6856217,2660734,139 -6856950,2660873,239 -6857143,2661112,267 -6857592,2661379,134 -6857668,2661513,187 -6857742,2661700,196 -6858861,2661896,120 -6859474,2662016,136 -6859658,2662152,134 -6860320,2662286,120 -6860563,2662406,150 -6860948,2662556,152 -6861882,2662708,181 -6862233,2662889,167 -6862588,2663056,223 -6863065,2663279,151 -6863235,2663430,138 -6863884,2663568,170 -6864299,2663738,170 -6867211,2663908,142 -6867456,2664050,153 -6868124,2664203,150 -6868239,2664353,204 -6868558,2664557,184 -6869501,2664741,262 -6869575,2665003,144 -6871333,2665147,190 -6871356,2665337,120 -6871911,2665457,201 -6871958,2665658,219 -6872296,2665877,161 -6873053,2666038,207 -6873446,2666245,55 -6874143,2666300,157 -6876078,2666457,175 -6876101,2666632,181 -6876258,2666813,201 -6876483,2667014,148 -6876580,2667162,230 -6876822,2667392,143 -6877117,2667535,170 -6877293,2667705,219 -6877372,2667924,228 -6877477,2668152,138 -6879016,2668290,265 -6879381,2668555,168 -6880149,2668723,206 -6880435,2668929,194 -7078515,2669123,234 -7079008,2669357,179 -7080406,2669536,176 -7080836,2669712,241 -7081485,2669953,176 -7081834,2670129,175 -7083255,2670304,147 -7083513,2670451,166 -7084049,2670617,148 -7084431,2670765,177 -7085680,2670942,221 -7086166,2671163,125 -7086763,2671288,169 -7087033,2671457,176 -7087545,2671633,186 -7088533,2671819,166 -7089158,2671985,195 -7089715,2672180,165 -7089778,2672345,201 -7089797,2672546,131 -7089964,2672677,175 -7090910,2672852,198 -7091113,2673050,144 -7092509,2673194,238 -7092868,2673432,231 -7093221,2673663,151 -7093331,2673814,159 -7093869,2673973,120 -7093916,2674093,166 -7094280,2674259,120 -7094470,2674379,183 -7094634,2674562,136 -7095320,2674698,119 -7095704,2674817,190 -7097215,2675007,163 -7098445,2675170,170 -7100281,2675340,162 -7100736,2675502,270 -7100980,2675772,274 -7101109,2676046,219 -7101662,2676265,145 -7101795,2676410,253 -7102074,2676663,231 -7102236,2676894,287 -7102758,2677181,171 -7103085,2677352,186 -7103514,2677538,152 -7106302,2677690,200 -7106328,2677890,163 -7106617,2678053,147 -7106719,2678200,120 -7107033,2678320,200 -7108192,2678520,166 -7111166,2678686,150 -7111478,2678836,175 -7111526,2679011,226 -7112326,2679237,163 -7112724,2679400,166 -7113519,2679566,160 -7113947,2679726,163 -7114085,2679889,184 -7114929,2680073,146 -7115455,2680219,202 -7116024,2680421,120 -7117035,2680541,129 -7117193,2680670,136 -7117513,2680806,161 -7117570,2680967,137 -7118057,2681104,138 -7118061,2681242,170 -7119104,2681412,166 -7120514,2681578,221 -7120735,2681799,159 -7120768,2681958,132 -7120890,2682090,192 -7120969,2682282,143 -7121158,2682425,187 -7121263,2682612,140 -7121587,2682752,150 -7121741,2682902,162 -7122016,2683064,132 -7122239,2683196,196 -7122415,2683392,201 -7122424,2683593,219 -7122571,2683812,147 -7123150,2683959,131 -7123729,2684090,239 -7123792,2684329,169 -7124331,2684498,182 -7124980,2684680,175 -7126761,2684855,154 -7126965,2685009,200 -7127506,2685209,147 -7127575,2685356,151 -7127659,2685507,120 -7129608,2685627,148 -7131186,2685775,152 -7131462,2685927,136 -7131568,2686063,243 -7132810,2686306,160 -7134314,2686466,167 -7135262,2686633,118 -7135408,2686751,114 -7136462,2686865,158 -7137395,2687023,271 -7137543,2687294,134 -7137667,2687428,178 -7138465,2687606,221 -7138539,2687827,142 -7139401,2687969,187 -7140211,2688156,175 -7140223,2688331,141 -7140840,2688472,191 -7141756,2688663,129 -7141976,2688792,142 -7142025,2688934,136 -7142055,2689070,195 -7142841,2689265,256 -7143358,2689521,158 -7340342,2689679,224 -7340632,2689903,144 -7341332,2690047,155 -7343040,2690202,189 -7344071,2690391,237 -7344108,2690628,196 -7344220,2690824,136 -7344420,2690960,120 -7345156,2691080,185 -7345318,2691265,132 -7346315,2691397,201 -7346692,2691598,160 -7346925,2691758,185 -7347583,2691943,219 -7349139,2692162,136 -7349542,2692298,134 -7349593,2692432,201 -7350909,2692633,118 -7351069,2692751,180 -7351327,2692931,126 -7351761,2693057,221 -7352139,2693278,162 -7352215,2693440,128 -7352344,2693568,138 -7352413,2693706,191 -7352414,2693897,255 -7352711,2694152,129 -7353045,2694281,191 -7354385,2694472,155 -7354548,2694627,163 -7354606,2694790,138 -7355096,2694928,303 -7355449,2695231,139 -7356076,2695370,120 -7356855,2695490,155 -7358018,2695645,225 -7359150,2695870,198 -7359204,2696068,139 -7359725,2696207,147 -7360001,2696354,220 -7360102,2696574,230 -7361221,2696804,145 -7361343,2696949,195 -7361746,2697144,166 -7361781,2697310,194 -7362177,2697504,120 -7362578,2697624,165 -7362903,2697789,179 -7362950,2697968,141 -7363254,2698109,219 -7363374,2698328,196 -7363757,2698524,155 -7364266,2698679,139 -7364830,2698818,151 -7364979,2698969,139 -7365304,2699108,194 -7365655,2699302,161 -7366018,2699463,222 -7366777,2699685,219 -7368577,2699904,55 -7368780,2699959,154 -7369139,2700113,159 -7369148,2700272,167 -7369229,2700439,300 -7369276,2700739,239 -7369423,2700978,134 -7369675,2701112,120 -7370288,2701232,141 -7370461,2701373,151 -7370480,2701524,235 -7370495,2701759,139 -7370625,2701898,219 -7371752,2702117,192 -7371800,2702309,206 -7372355,2702515,147 -7372510,2702662,151 -7373061,2702813,170 -7373326,2702983,164 -7373454,2703147,143 -7374278,2703290,122 -7375736,2703412,212 -7376137,2703624,130 -7377795,2703754,269 -7377912,2704023,167 -7378774,2704190,208 -7379467,2704398,159 -7379877,2704557,246 -7379964,2704803,166 -7380111,2704969,121 -7380521,2705090,167 -7380614,2705257,149 -7380781,2705406,163 -7381393,2705569,173 -7382044,2705742,222 -7382634,2705964,137 -7383267,2706101,199 -7383730,2706300,148 -7384404,2706448,167 -7384869,2706615,160 -7385141,2706775,269 -7385228,2707044,222 -7385422,2707266,139 -7385701,2707405,144 -7386069,2707549,282 -7386521,2707831,161 -7387425,2707992,218 -7387887,2708210,216 -7390892,2708426,166 -7391087,2708592,137 -7391899,2708729,170 -7392608,2708899,120 -7394546,2709019,118 -7394686,2709137,156 -7394791,2709293,164 -7394998,2709457,163 -7395456,2709620,150 -7395633,2709770,187 -7395996,2709957,177 -7396769,2710134,159 -7397090,2710293,120 -7397415,2710413,254 -7397689,2710667,130 -7397964,2710797,166 -7398020,2710963,257 -7399212,2711220,120 -7399491,2711340,246 -7401040,2711586,131 -7401846,2711717,137 -7401878,2711854,165 -7401889,2712019,199 -7401957,2712218,145 -7402389,2712363,242 -7403815,2712605,159 -7403885,2712764,217 -7404684,2712981,148 -7405404,2713129,268 -7405430,2713397,139 -7603133,2713536,170 -7603243,2713706,265 -7604924,2713971,199 -7605979,2714170,201 -7607433,2714371,144 -7607778,2714515,177 -7608824,2714692,278 -7610003,2714970,221 -7610186,2715191,204 -7611786,2715395,217 -7612076,2715612,136 -7612220,2715748,228 -7612394,2715976,213 -7612847,2716189,219 -7613199,2716408,166 -7613282,2716574,199 -7613706,2716773,151 -7614204,2716924,188 -7614312,2717112,192 -7614832,2717304,218 -7615062,2717522,156 -7616303,2717678,272 -7616649,2717950,167 -7618251,2718117,178 -7619585,2718295,139 -7619978,2718434,175 -7620256,2718609,148 -7621609,2718757,200 -7622009,2718957,158 -7623098,2719115,204 -7623463,2719319,169 -7623805,2719488,143 -7624210,2719631,147 -7624600,2719778,160 -7625887,2719938,176 -7626268,2720114,175 -7626496,2720289,164 -7626670,2720453,160 -7627743,2720613,129 -7628241,2720742,114 -7628336,2720856,125 -7629370,2720981,159 -7629449,2721140,151 -7629455,2721291,163 -7629698,2721454,125 -7630653,2721579,131 -7631602,2721710,197 -7632200,2721907,150 -7632920,2722057,196 -7633786,2722253,164 -7634358,2722417,204 -7634458,2722621,191 -7634477,2722812,274 -7635220,2723086,120 -7636266,2723206,172 -7636602,2723378,127 -7637034,2723505,191 -7637131,2723696,135 -7638536,2723831,185 -7638776,2724016,180 -7638811,2724196,196 -7638861,2724392,164 -7639120,2724556,187 -7639322,2724743,144 -7639485,2724887,160 -7639972,2725047,178 -7640125,2725225,145 -7640631,2725370,252 -7641461,2725622,147 -7642194,2725769,252 -7642339,2726021,158 -7642588,2726179,127 -7643183,2726306,136 -7643235,2726442,194 -7643878,2726636,136 -7643978,2726772,182 -7644327,2726954,164 -7644341,2727118,265 -7644962,2727383,156 -7646647,2727539,197 -7646838,2727736,166 -7647244,2727902,177 -7649771,2728079,230 -7650011,2728309,276 -7650824,2728585,148 -7651233,2728733,182 -7651910,2728915,150 -7652897,2729065,211 -7653786,2729276,128 -7653925,2729404,159 -7654668,2729563,208 -7654998,2729771,232 -7655467,2730003,164 -7655644,2730167,126 -7656501,2730293,203 -7657077,2730496,162 -7657194,2730658,142 -7657552,2730800,148 -7658040,2730948,204 -7658449,2731152,126 -7659051,2731278,212 -7659630,2731490,135 -7659850,2731625,278 -7659958,2731903,120 -7660151,2732023,134 -7660172,2732157,150 -7660277,2732307,120 -7660580,2732427,151 -7660811,2732578,166 -7660855,2732744,173 -7660867,2732917,201 -7661282,2733118,129 -7661510,2733247,147 -7662138,2733394,230 -7662833,2733624,165 -7663725,2733789,196 -7663741,2733985,188 -7663874,2734173,222 -7664659,2734395,142 -7665170,2734537,147 -7665446,2734684,151 -7665757,2734835,171 -7667104,2735006,170 -7667272,2735176,194 -7667581,2735370,161 -7864975,2735531,224 -7866168,2735755,139 -7868805,2735894,172 -7869112,2736066,217 -7870593,2736283,191 -7870766,2736474,147 -7870967,2736621,149 -7871578,2736770,169 -7871930,2736939,187 -7871997,2737126,173 -7872475,2737299,175 -7873085,2737474,138 -7873711,2737612,162 -7873860,2737774,194 -7873965,2737968,197 -7875531,2738165,138 -7876335,2738303,132 -7876667,2738435,222 -7876833,2738657,159 -7876907,2738816,179 -7877057,2738995,120 -7877199,2739115,164 -7879300,2739279,120 -7879907,2739399,179 -7880027,2739578,206 -7880275,2739784,139 -7880469,2739923,179 -7880932,2740102,175 -7881733,2740277,237 -7881846,2740514,253 -7882081,2740767,186 -7882180,2740953,138 -7882436,2741091,212 -7882525,2741303,175 -7882841,2741478,151 -7883037,2741629,153 -7883528,2741782,171 -7883655,2741953,177 -7885068,2742130,120 -7885338,2742250,175 -7885410,2742425,264 -7885870,2742689,205 -7886103,2742894,142 -7886610,2743036,177 -7887091,2743213,189 -7887166,2743402,158 -7887198,2743560,175 -7887208,2743735,297 -7887986,2744032,237 -7888716,2744269,217 -7889276,2744486,160 -7890606,2744646,160 -7891593,2744806,242 -7891996,2745048,120 -7893404,2745168,148 -7896673,2745316,120 -7896930,2745436,113 -7897487,2745549,171 -7898172,2745720,149 -7898350,2745869,140 -7899507,2746009,136 -7900244,2746145,167 -7900663,2746312,207 -7901758,2746519,134 -7901852,2746653,166 -7902852,2746819,156 -7903485,2746975,166 -7903580,2747141,255 -7903590,2747396,229 -7903631,2747625,157 -7904487,2747782,232 -7904976,2748014,159 -7905100,2748173,178 -7905136,2748351,128 -7905159,2748479,160 -7905361,2748639,150 -7905542,2748789,265 -7905667,2749054,131 -7905952,2749185,161 -7906129,2749346,244 -7906276,2749590,120 -7906564,2749710,144 -7906781,2749854,234 -7906947,2750088,128 -7907005,2750216,213 -7907092,2750429,129 -7907443,2750558,175 -7908192,2750733,121 -7908283,2750854,189 -7908543,2751043,149 -7908544,2751192,188 -7908876,2751380,181 -7910329,2751561,250 -7910350,2751811,155 -7910866,2751966,209 -7911105,2752175,181 -7911450,2752356,134 -7912144,2752490,198 -7912185,2752688,136 -7912892,2752824,190 -7913142,2753014,156 -7913149,2753170,126 -7914510,2753296,120 -7914667,2753416,262 -7914981,2753678,144 -7915195,2753822,127 -7916036,2753949,132 -7916089,2754081,120 -7916126,2754201,117 -7916339,2754318,176 -7916942,2754494,132 -7917572,2754626,193 -7917865,2754819,117 -7918415,2754936,164 -7918477,2755100,221 -7919029,2755321,137 -7919215,2755458,232 -7919344,2755690,186 -7919442,2755876,191 -7920031,2756067,169 -7920238,2756236,136 -7920307,2756372,148 -7920904,2756520,200 -7921110,2756720,116 -7921380,2756836,144 -7922613,2756980,188 -7922688,2757168,199 -7923665,2757367,167 -7923894,2757534,160 -7924096,2757694,213 -7924500,2757907,230 -7924770,2758137,210 -7924852,2758347,135 -7925580,2758482,210 -7927269,2758692,154 -7927293,2758846,239 -7927742,2759085,175 -7927760,2759260,158 -7928132,2759418,55 -7928852,2759473,153 -7929236,2759626,120 -7929405,2759746,149 -7929409,2759895,182 -7929570,2760077,182 -7929687,2760259,166 -8126855,2760425,158 -8127164,2760583,205 -8127308,2760788,144 -8127448,2760932,148 -8127751,2761080,166 -8127774,2761246,123 -8128035,2761369,166 -8128729,2761535,181 -8128811,2761716,118 -8129104,2761834,175 -8130254,2762009,136 -8131006,2762145,120 -8131021,2762265,139 -8131702,2762404,161 -8132109,2762565,154 -8133123,2762719,184 -8133372,2762903,222 -8134105,2763125,183 -8134226,2763308,134 -8134323,2763442,162 -8134728,2763604,152 -8134756,2763756,142 -8136071,2763898,179 -8137971,2764077,193 -8138253,2764270,165 -8138624,2764435,168 -8139630,2764603,205 -8140908,2764808,156 -8141088,2764964,189 -8141781,2765153,139 -8142006,2765292,258 -8142493,2765550,137 -8143759,2765687,179 -8143948,2765866,208 -8145337,2766074,186 -8145538,2766260,154 -8145576,2766414,257 -8145784,2766671,164 -8146008,2766835,181 -8146085,2767016,134 -8146869,2767150,217 -8147786,2767367,134 -8148455,2767501,137 -8150264,2767638,166 -8151191,2767804,201 -8151443,2768005,175 -8152733,2768180,139 -8153590,2768319,136 -8153779,2768455,164 -8153795,2768619,156 -8153819,2768775,191 -8153907,2768966,199 -8153938,2769165,142 -8154169,2769307,130 -8154255,2769437,144 -8154466,2769581,120 -8154616,2769701,120 -8154886,2769821,193 -8155128,2770014,262 -8155324,2770276,278 -8155876,2770554,160 -8156787,2770714,136 -8157779,2770850,182 -8157841,2771032,166 -8158180,2771198,207 -8158529,2771405,217 -8159789,2771622,112 -8159860,2771734,233 -8160006,2771967,143 -8162705,2772110,223 -8163044,2772333,144 -8164530,2772477,154 -8164851,2772631,136 -8165219,2772767,164 -8166043,2772931,164 -8167773,2773095,133 -8168091,2773228,141 -8168989,2773369,134 -8170674,2773503,176 -8170868,2773679,136 -8171582,2773815,129 -8171895,2773944,132 -8172059,2774076,148 -8172082,2774224,222 -8172866,2774446,184 -8173363,2774630,196 -8173435,2774826,156 -8174447,2774982,209 -8174854,2775191,141 -8175496,2775332,121 -8175537,2775453,147 -8176545,2775600,120 -8176879,2775720,120 -8176951,2775840,120 -8177417,2775960,203 -8177835,2776163,163 -8177872,2776326,189 -8177879,2776515,134 -8178445,2776649,165 -8178872,2776814,167 -8178961,2776981,113 -8179004,2777094,225 -8179663,2777319,203 -8180163,2777522,120 -8180490,2777642,200 -8181602,2777842,176 -8181828,2778018,132 -8182270,2778150,183 -8182404,2778333,168 -8183057,2778501,243 -8183072,2778744,163 -8183184,2778907,262 -8183876,2779169,131 -8184319,2779300,218 -8185002,2779518,55 -8185124,2779573,149 -8185195,2779722,210 -8186323,2779932,200 -8186858,2780132,167 -8187001,2780299,139 -8187277,2780438,133 -8187672,2780571,182 -8187786,2780753,189 -8187999,2780942,120 -8188056,2781062,177 -8188090,2781239,196 -8188969,2781435,162 -8190036,2781597,197 -8190222,2781794,175 -8190687,2781969,120 -8191528,2782089,144 -8191566,2782233,264 -8191842,2782497,227 -8388619,2782724,166 -8388624,2782890,164 -8388718,2783054,120 -8388996,2783174,165 -8390111,2783339,184 -8390562,2783523,228 -8390914,2783751,189 -8391174,2783940,152 -8391505,2784092,221 -8392228,2784313,128 -8393792,2784441,193 -8393896,2784634,271 -8394423,2784905,187 -8394621,2785092,148 -8394919,2785240,191 -8395060,2785431,166 -8395111,2785597,241 -8396202,2785838,136 -8396546,2785974,206 -8396975,2786180,133 -8397429,2786313,207 -8399528,2786520,160 -8399610,2786680,151 -8400353,2786831,192 -8400404,2787023,136 -8400862,2787159,147 -8402007,2787306,162 -8402803,2787468,139 -8403132,2787607,244 -8403197,2787851,165 -8403429,2788016,150 -8403754,2788166,203 -8403866,2788369,145 -8404829,2788514,217 -8404950,2788731,141 -8405326,2788872,186 -8405628,2789058,177 -8406833,2789235,169 -8407205,2789404,250 -8407409,2789654,120 -8407840,2789774,172 -8408705,2789946,175 -8408920,2790121,147 -8409115,2790268,135 -8409191,2790403,214 -8410866,2790617,201 -8410905,2790818,175 -8411333,2790993,189 -8411645,2791182,130 -8413191,2791312,118 -8413583,2791430,296 -8414297,2791726,181 -8414697,2791907,151 -8414761,2792058,217 -8415920,2792275,242 -8416283,2792517,173 -8416395,2792690,157 -8416444,2792847,174 -8417567,2793021,146 -8417658,2793167,239 -8418393,2793406,138 -8418963,2793544,134 -8419758,2793678,217 -8419967,2793895,243 -8420126,2794138,150 -8420229,2794288,278 -8420635,2794566,146 -8420835,2794712,211 -8421797,2794923,254 -8422023,2795177,224 -8423064,2795401,170 -8423154,2795571,166 -8423703,2795737,270 -8424284,2796007,262 -8425770,2796269,225 -8425920,2796494,163 -8426143,2796657,120 -8426387,2796777,132 -8426604,2796909,176 -8427185,2797085,147 -8427210,2797232,244 -8427291,2797476,178 -8428320,2797654,166 -8429483,2797820,221 -8430039,2798041,209 -8431709,2798250,165 -8432292,2798415,125 -8432999,2798540,191 -8434201,2798731,202 -8434313,2798933,193 -8434474,2799126,147 -8435334,2799273,238 -8436060,2799511,194 -8436396,2799705,154 -8436454,2799859,112 -8436715,2799971,173 -8437253,2800144,120 -8438126,2800264,151 -8439270,2800415,158 -8439359,2800573,180 -8439467,2800753,159 -8439498,2800912,128 -8439906,2801040,146 -8441521,2801186,170 -8441665,2801356,277 -8441881,2801633,129 -8442011,2801762,239 -8442251,2802001,186 -8442397,2802187,206 -8442931,2802393,148 -8443699,2802541,161 -8444721,2802702,238 -8447194,2802940,278 -8447568,2803218,120 -8448662,2803338,120 -8448714,2803458,184 -8449651,2803642,152 -8450654,2803794,105 -8451331,2803899,139 -8451475,2804038,183 -8451630,2804221,217 -8452331,2804438,169 -8452699,2804607,167 -8452870,2804774,192 -8454056,2804966,170 -8650962,2805136,175 -8651175,2805311,171 -8653613,2805482,205 -8654661,2805687,239 -8655262,2805926,175 -8656661,2806101,191 -8656742,2806292,229 -8656934,2806521,131 -8656954,2806652,141 -8657032,2806793,149 -8657720,2806942,231 -8657758,2807173,139 -8658470,2807312,184 -8659265,2807496,196 -8660109,2807692,173 -8660287,2807865,150 -8660388,2808015,145 -8660443,2808160,175 -8660501,2808335,143 -8660523,2808478,134 -8660624,2808612,236 -8660942,2808848,326 -8661268,2809174,211 -8661401,2809385,120 -8661803,2809505,140 -8661840,2809645,165 -8661948,2809810,143 -8662567,2809953,175 -8662901,2810128,131 -8663269,2810259,174 -8663786,2810433,200 -8664215,2810633,153 -8664593,2810786,209 -8665141,2810995,120 -8665144,2811115,229 -8665675,2811344,166 -8666958,2811510,169 -8668260,2811679,132 -8669219,2811811,187 -8669461,2811998,181 -8670135,2812179,256 -8670197,2812435,200 -8670979,2812635,191 -8671617,2812826,175 -8672677,2813001,161 -8672924,2813162,152 -8673159,2813314,191 -8674451,2813505,156 -8674775,2813661,221 -8675744,2813882,148 -8675875,2814030,234 -8676006,2814264,175 -8676310,2814439,153 -8678125,2814592,164 -8679089,2814756,153 -8679943,2814909,241 -8680195,2815150,410 -8680490,2815560,163 -8680982,2815723,136 -8681611,2815859,120 -8681644,2815979,136 -8682120,2816115,170 -8683072,2816285,144 -8683565,2816429,136 -8684276,2816565,260 -8684342,2816825,224 -8684401,2817049,143 -8684595,2817192,158 -8684806,2817350,120 -8684810,2817470,196 -8685299,2817666,181 -8686980,2817847,149 -8687047,2817996,143 -8687116,2818139,120 -8687254,2818259,161 -8687327,2818420,157 -8687465,2818577,140 -8687616,2818717,166 -8688396,2818883,152 -8688780,2819035,229 -8689281,2819264,216 -8689368,2819480,139 -8689592,2819619,144 -8690854,2819763,209 -8691141,2819972,174 -8692838,2820146,190 -8693448,2820336,166 -8693635,2820502,129 -8693988,2820631,285 -8694161,2820916,167 -8694948,2821083,264 -8695583,2821347,189 -8696147,2821536,120 -8697244,2821656,150 -8697858,2821806,136 -8700644,2821942,183 -8700904,2822125,139 -8701735,2822264,136 -8701865,2822400,152 -8702129,2822552,174 -8702386,2822726,169 -8703935,2822895,141 -8704810,2823036,153 -8706504,2823189,177 -8706863,2823366,144 -8706988,2823510,239 -8707068,2823749,134 -8707360,2823883,144 -8707511,2824027,151 -8707645,2824178,194 -8707852,2824372,131 -8707865,2824503,235 -8708184,2824738,139 -8709337,2824877,249 -8709673,2825126,155 -8709908,2825281,242 -8710809,2825523,173 -8710936,2825696,142 -8711475,2825838,200 -8712489,2826038,140 -8713363,2826178,131 -8713804,2826309,137 -8715518,2826446,120 -8715934,2826566,155 -8913749,2826721,203 -8915205,2826924,176 -8916752,2827100,247 -8916918,2827347,218 -8917046,2827565,257 -8917582,2827822,147 -8918059,2827969,143 -8918340,2828112,137 -8919214,2828249,151 -8920572,2828400,136 -8920993,2828536,120 -8921106,2828656,152 -8921571,2828808,195 -8921956,2829003,149 -8922110,2829152,155 -8922412,2829307,215 -8922515,2829522,250 -8923472,2829772,200 -8924762,2829972,121 -8925322,2830093,178 -8925851,2830271,224 -8925972,2830495,144 -8926142,2830639,133 -8926540,2830772,115 -8926738,2830887,155 -8928139,2831042,208 -8929623,2831250,242 -8929729,2831492,215 -8929788,2831707,216 -8930273,2831923,170 -8930550,2832093,130 -8930858,2832223,173 -8932153,2832396,167 -8933883,2832563,151 -8934190,2832714,166 -8934293,2832880,120 -8934356,2833000,238 -8935277,2833238,194 -8936082,2833432,136 -8936413,2833568,158 -8936519,2833726,129 -8937818,2833855,147 -8938463,2834002,120 -8939612,2834122,321 -8940406,2834443,390 -8941619,2834833,182 -8941708,2835015,285 -8941807,2835300,187 -8942468,2835487,115 -8942488,2835602,202 -8942934,2835804,136 -8943772,2835940,140 -8947203,2836080,194 -8947360,2836274,189 -8947479,2836463,133 -8947677,2836596,159 -8947988,2836755,186 -8948068,2836941,154 -8948573,2837095,189 -8948761,2837284,155 -8949901,2837439,136 -8950118,2837575,182 -8950237,2837757,124 -8950897,2837881,180 -8951033,2838061,210 -8951225,2838271,198 -8951414,2838469,146 -8951775,2838615,233 -8951841,2838848,157 -8952633,2839005,175 -8952998,2839180,178 -8953850,2839358,200 -8954462,2839558,149 -8954583,2839707,194 -8954828,2839901,136 -8955325,2840037,144 -8955708,2840181,182 -8957121,2840363,172 -8957469,2840535,211 -8958312,2840746,149 -8958433,2840895,178 -8959527,2841073,147 -8960639,2841220,172 -8962005,2841392,178 -8962926,2841570,256 -8963622,2841826,163 -8963683,2841989,120 -8964560,2842109,154 -8964999,2842263,120 -8965029,2842383,243 -8965882,2842626,239 -8967035,2842865,152 -8968124,2843017,140 -8968546,2843157,205 -8969366,2843362,211 -8969593,2843573,114 -8970400,2843687,237 -8970483,2843924,149 -8970593,2844073,291 -8971179,2844364,243 -8971779,2844607,177 -8972050,2844784,179 -8972198,2844963,207 -8972536,2845170,214 -8972567,2845384,140 -8973596,2845524,198 -8974385,2845722,136 -8974455,2845858,170 -8975496,2846028,274 -8975504,2846302,163 -8976327,2846465,159 -8977685,2846624,181 -8978134,2846805,258 -9175149,2847063,120 -9176319,2847183,159 -9176401,2847342,134 -9176972,2847476,147 -9177227,2847623,163 -9177588,2847786,165 -9178256,2847951,157 -9178275,2848108,117 -9178851,2848225,228 -9179595,2848453,191 -9181401,2848644,230 -9183124,2848874,174 -9183498,2849048,267 -9185053,2849315,123 -9185162,2849438,135 -9185591,2849573,120 -9186730,2849693,120 -9187129,2849813,144 -9188144,2849957,185 -9188183,2850142,266 -9188605,2850408,242 -9190115,2850650,155 -9190407,2850805,156 -9190474,2850961,182 -9191922,2851143,192 -9192501,2851335,240 -9194222,2851575,181 -9194329,2851756,182 -9194716,2851938,188 -9194937,2852126,128 -9194986,2852254,181 -9195781,2852435,233 -9196535,2852668,185 -9196573,2852853,136 -9197213,2852989,170 -9197253,2853159,161 -9197565,2853320,135 -9197687,2853455,120 -9197963,2853575,138 -9198320,2853713,171 -9198753,2853884,147 -9198944,2854031,188 -9199583,2854219,193 -9199695,2854412,170 -9200651,2854582,163 -9200674,2854745,176 -9201784,2854921,117 -9202404,2855038,171 -9203802,2855209,166 -9204216,2855375,175 -9204590,2855550,198 -9205441,2855748,171 -9205522,2855919,175 -9205526,2856094,200 -9206119,2856294,159 -9206685,2856453,120 -9206930,2856573,120 -9206965,2856693,199 -9207039,2856892,180 -9207475,2857072,153 -9207611,2857225,156 -9208488,2857381,168 -9208833,2857549,55 -9209659,2857604,136 -9210277,2857740,189 -9210478,2857929,206 -9210755,2858135,142 -9211510,2858277,128 -9212115,2858405,130 -9212169,2858535,214 -9212470,2858749,221 -9213135,2858970,175 -9216072,2859145,236 -9218434,2859381,166 -9219660,2859547,170 -9219721,2859717,149 -9220244,2859866,175 -9221711,2860041,170 -9222135,2860211,252 -9222188,2860463,181 -9222244,2860644,172 -9223870,2860816,217 -9224093,2861033,226 -9224102,2861259,175 -9224481,2861434,189 -9225697,2861623,243 -9226154,2861866,205 -9226192,2862071,188 -9226445,2862259,194 -9227682,2862453,139 -9227752,2862592,160 -9228124,2862752,137 -9228667,2862889,168 -9229218,2863057,119 -9229864,2863176,149 -9231141,2863325,137 -9231572,2863462,151 -9231757,2863613,191 -9231954,2863804,202 -9232025,2864006,133 -9232285,2864139,146 -9232513,2864285,155 -9234248,2864440,55 -9234316,2864495,184 -9234355,2864679,182 -9236166,2864861,163 -9237032,2865024,265 -9238547,2865289,137 -9238853,2865426,163 -9238985,2865589,223 -9239226,2865812,120 -9240048,2865932,157 -9437262,2866089,200 -9437403,2866289,175 -9437499,2866464,131 -9437834,2866595,259 -9437865,2866854,199 -9438135,2867053,113 -9439511,2867166,200 -9439801,2867366,145 -9439802,2867511,153 -9440436,2867664,202 -9440614,2867866,193 -9440715,2868059,165 -9443227,2868224,127 -9443244,2868351,194 -9443422,2868545,164 -9443452,2868709,207 -9443502,2868916,216 -9443584,2869132,111 -9444042,2869243,165 -9444110,2869408,191 -9444647,2869599,160 -9445085,2869759,202 -9445434,2869961,202 -9445507,2870163,196 -9445638,2870359,134 -9445717,2870493,173 -9445761,2870666,268 -9447396,2870934,120 -9448244,2871054,179 -9448647,2871233,182 -9448988,2871415,166 -9449095,2871581,131 -9449933,2871712,199 -9450539,2871911,152 -9450748,2872063,199 -9450862,2872262,161 -9451743,2872423,200 -9452192,2872623,134 -9452690,2872757,120 -9452718,2872877,242 -9452890,2873119,242 -9452907,2873361,209 -9453227,2873570,165 -9454854,2873735,159 -9455287,2873894,169 -9455382,2874063,159 -9455770,2874222,241 -9456122,2874463,170 -9456869,2874633,199 -9457195,2874832,242 -9457787,2875074,181 -9457983,2875255,160 -9458758,2875415,164 -9459118,2875579,139 -9459330,2875718,166 -9459346,2875884,121 -9460143,2876005,144 -9461550,2876149,192 -9461645,2876341,123 -9462028,2876464,172 -9463575,2876636,220 -9463580,2876856,241 -9463733,2877097,163 -9463795,2877260,129 -9464003,2877389,173 -9465004,2877562,145 -9465288,2877707,217 -9465531,2877924,199 -9465893,2878123,205 -9466432,2878328,120 -9468304,2878448,176 -9468426,2878624,149 -9468456,2878773,246 -9468657,2879019,171 -9469626,2879190,247 -9469793,2879437,214 -9470560,2879651,160 -9470842,2879811,209 -9470989,2880020,120 -9472162,2880140,184 -9473033,2880324,132 -9473092,2880456,215 -9473123,2880671,226 -9473309,2880897,153 -9473388,2881050,120 -9473999,2881170,191 -9474108,2881361,232 -9474144,2881593,202 -9474740,2881795,186 -9475300,2881981,206 -9476196,2882187,153 -9476374,2882340,172 -9477600,2882512,170 -9477939,2882682,172 -9477955,2882854,167 -9478672,2883021,193 -9478874,2883214,120 -9479390,2883334,179 -9480067,2883513,201 -9480129,2883714,177 -9481279,2883891,152 -9481755,2884043,253 -9482524,2884296,143 -9482548,2884439,147 -9482783,2884586,120 -9483910,2884706,179 -9484496,2884885,160 -9484593,2885045,130 -9484669,2885175,211 -9486613,2885386,171 -9487199,2885557,221 -9488002,2885778,278 -9488274,2886056,156 -9489444,2886212,141 -9490197,2886353,132 -9490287,2886485,185 -9490301,2886670,187 -9490715,2886857,168 -9492303,2887025,117 -9492459,2887142,156 -9492562,2887298,179 -9492780,2887477,142 -9493070,2887619,143 -9493098,2887762,210 -9493318,2887972,194 -9494455,2888166,179 -9494768,2888345,159 -9495226,2888504,166 -9496250,2888670,162 -9496516,2888832,177 -9497184,2889009,166 -9498472,2889175,203 -9499050,2889378,189 -9499056,2889567,212 -9499256,2889779,136 -9499575,2889915,263 -9499841,2890178,132 -9500242,2890310,269 -9500463,2890579,184 -9501531,2890763,138 -9501606,2890901,187 -9502049,2891088,120 -9502585,2891208,185 -9699440,2891393,132 -9699657,2891525,139 -9699778,2891664,175 -9700508,2891839,194 -9700790,2892033,248 -9701687,2892281,189 -9702189,2892470,212 -9702357,2892682,182 -9702509,2892864,228 -9703486,2893092,175 -9703898,2893267,153 -9705075,2893420,161 -9706780,2893581,151 -9707603,2893732,135 -9707927,2893867,218 -9708398,2894085,218 -9711127,2894303,177 -9711203,2894480,121 -9712027,2894601,139 -9712605,2894740,176 -9712906,2894916,175 -9713376,2895091,311 -9714149,2895402,199 -9714416,2895601,134 -9714609,2895735,189 -9715874,2895924,214 -9716804,2896138,144 -9716818,2896282,172 -9717398,2896454,175 -9718281,2896629,147 -9718284,2896776,173 -9719879,2896949,161 -9720067,2897110,159 -9720255,2897269,173 -9720979,2897442,137 -9722157,2897579,169 -9722750,2897748,147 -9724196,2897895,140 -9724521,2898035,156 -9724881,2898191,175 -9725340,2898366,166 -9728210,2898532,188 -9728428,2898720,200 -9729390,2898920,153 -9729835,2899073,241 -9731134,2899314,148 -9732516,2899462,151 -9733498,2899613,159 -9733844,2899772,222 -9734012,2899994,165 -9734228,2900159,144 -9734915,2900303,230 -9735504,2900533,134 -9735817,2900667,220 -9736174,2900887,170 -9737254,2901057,120 -9738402,2901177,169 -9739261,2901346,175 -9739349,2901521,170 -9740095,2901691,250 -9740212,2901941,259 -9740706,2902200,194 -9742263,2902394,178 -9742268,2902572,174 -9743032,2902746,201 -9743562,2902947,153 -9743969,2903100,129 -9744099,2903229,203 -9745423,2903432,140 -9746629,2903572,143 -9746868,2903715,195 -9746993,2903910,224 -9747030,2904134,234 -9748254,2904368,257 -9748373,2904625,223 -9748500,2904848,224 -9748536,2905072,142 -9748816,2905214,135 -9749476,2905349,152 -9749737,2905501,219 -9750251,2905720,177 -9750447,2905897,181 -9750882,2906078,130 -9751055,2906208,145 -9751737,2906353,147 -9751980,2906500,124 -9752108,2906624,163 -9752113,2906787,159 -9752601,2906946,184 -9753623,2907130,193 -9754126,2907323,229 -9754403,2907552,216 -9754481,2907768,175 -9754940,2907943,125 -9755465,2908068,107 -9755593,2908175,163 -9755967,2908338,208 -9756174,2908546,122 -9756288,2908668,166 -9756494,2908834,211 -9756504,2909045,187 -9756880,2909232,190 -9757222,2909422,171 -9757437,2909593,196 -9758481,2909789,159 -9758792,2909948,152 -9759082,2910100,128 -9759116,2910228,134 -9759532,2910362,154 -9759693,2910516,163 -9761182,2910679,208 -9762405,2910887,143 -9762450,2911030,209 -9762592,2911239,211 -9763560,2911450,274 -9763762,2911724,223 -9764125,2911947,151 -9764142,2912098,206 -9764596,2912304,131 -9962116,2912435,149 -9962200,2912584,278 -9962400,2912862,162 -9962456,2913024,120 -9964674,2913144,186 -9964846,2913330,176 -9965284,2913506,55 -9965716,2913561,234 -9967340,2913795,137 -9969146,2913932,190 -9969806,2914122,171 -9971242,2914293,204 -9971997,2914497,197 -9972031,2914694,208 -9972926,2914902,124 -9973078,2915026,150 -9973564,2915176,191 -9973760,2915367,231 -9973873,2915598,169 -9974941,2915767,167 -9975153,2915934,163 -9975224,2916097,171 -9975571,2916268,209 -9976598,2916477,193 -9977759,2916670,238 -9978438,2916908,176 -9978842,2917084,163 -9979708,2917247,239 -9980487,2917486,139 -9980746,2917625,147 -9980897,2917772,167 -9980932,2917939,262 -9981139,2918201,184 -9981591,2918385,195 -9981934,2918580,166 -9982641,2918746,159 -9983955,2918905,211 -9984138,2919116,190 -9984325,2919306,144 -9984747,2919450,132 -9985171,2919582,162 -9985350,2919744,164 -9985563,2919908,216 -9986082,2920124,163 -9987818,2920287,205 -9988925,2920492,148 -9989365,2920640,160 -9989576,2920800,252 -9991108,2921052,182 -9991862,2921234,137 -9992048,2921371,242 -9993203,2921613,139 -9993798,2921752,181 -9994775,2921933,174 -9995145,2922107,189 -9995953,2922296,233 -9996781,2922529,186 -9997149,2922715,153 -9997229,2922868,166 -9997876,2923034,194 -9997898,2923228,229 -9998045,2923457,213 -9998464,2923670,234 -9998486,2923904,124 -9999308,2924028,221 -9999433,2924249,216 -10004400,2924465,148 -10005207,2924613,194 -10006585,2924807,134 -10008803,2924941,120 -10009687,2925061,154 -10009753,2925215,179 -10010260,2925394,134 -10010859,2925528,189 -10012741,2925717,140 -10014132,2925857,168 -10015537,2926025,219 -10016390,2926244,191 -10016443,2926435,120 -10016503,2926555,153 -10016908,2926708,148 -10017426,2926856,167 -10018009,2927023,163 -10019033,2927186,120 -10019173,2927306,131 -10020762,2927437,210 -10021989,2927647,124 -10022603,2927771,255 -10023083,2928026,120 -10023280,2928146,179 -10024247,2928325,160 -10024361,2928485,177 -10025153,2928662,203 -10025179,2928865,207 -10025699,2929072,230 -10025746,2929302,217 -10026001,2929519,152 -10026499,2929671,156 -10026644,2929827,120 -10026858,2929947,194 -10026960,2930141,281 -10223889,2930422,242 -10224280,2930664,175 -10224542,2930839,266 -10224755,2931105,215 -10224875,2931320,120 -10225262,2931440,237 -10227116,2931677,173 -10228837,2931850,224 -10229876,2932074,138 -10230802,2932212,140 -10231773,2932352,184 -10231931,2932536,120 -10232170,2932656,264 -10232334,2932920,144 -10233920,2933064,253 -10234047,2933317,209 -10234095,2933526,194 -10234480,2933720,202 -10236006,2933922,138 -10236280,2934060,314 -10236342,2934374,174 -10237315,2934548,165 -10237419,2934713,132 -10237940,2934845,194 -10238639,2935039,175 -10239658,2935214,207 -10240380,2935421,238 -10241085,2935659,195 -10241190,2935854,173 -10241379,2936027,137 -10242683,2936164,137 -10243246,2936301,126 -10243616,2936427,170 -10243638,2936597,166 -10243726,2936763,124 -10243775,2936887,130 -10245069,2937017,140 -10245148,2937157,253 -10245322,2937410,276 -10245556,2937686,145 -10245905,2937831,292 -10247062,2938123,160 -10247309,2938283,262 -10247442,2938545,156 -10247573,2938701,191 -10247795,2938892,172 -10248477,2939064,146 -10249310,2939210,154 -10249648,2939364,175 -10249721,2939539,172 -10249808,2939711,225 -10250331,2939936,148 -10250942,2940084,132 -10251285,2940216,158 -10253588,2940374,120 -10254250,2940494,190 -10254764,2940684,205 -10255314,2940889,175 -10256509,2941064,176 -10256607,2941240,227 -10258138,2941467,168 -10258568,2941635,139 -10259441,2941774,186 -10259738,2941960,170 -10260121,2942130,167 -10260188,2942297,125 -10261326,2942422,168 -10261476,2942590,55 -10262008,2942645,166 -10262310,2942811,137 -10262545,2942948,232 -10263581,2943180,155 -10264842,2943335,137 -10264884,2943472,131 -10265530,2943603,155 -10265975,2943758,148 -10267108,2943906,151 -10268055,2944057,220 -10268143,2944277,163 -10268618,2944440,170 -10268680,2944610,201 -10269190,2944811,138 -10270292,2944949,151 -10270416,2945100,154 -10270477,2945254,194 -10270611,2945448,193 -10271640,2945641,218 -10272157,2945859,176 -10272480,2946035,232 -10272887,2946267,138 -10272978,2946405,180 -10273138,2946585,239 -10274726,2946824,112 -10274769,2946936,169 -10275545,2947105,134 -10276226,2947239,238 -10277406,2947477,241 -10277451,2947718,160 -10277723,2947878,175 -10277741,2948053,151 -10278467,2948204,168 -10279191,2948372,173 -10280707,2948545,203 -10281230,2948748,149 -10281430,2948897,174 -10281520,2949071,188 -10282549,2949259,166 -10282727,2949425,175 -10282941,2949600,193 -10284008,2949793,215 -10285959,2950008,120 -10286618,2950128,156 -10286717,2950284,147 -10287323,2950431,236 -10287416,2950667,162 -10288113,2950829,147 -10288129,2950976,128 -10289086,2951104,151 -10486492,2951255,150 -10486627,2951405,178 -10487335,2951583,180 -10487704,2951763,154 -10487734,2951917,179 -10488511,2952096,212 -10488762,2952308,168 -10488993,2952476,149 -10490512,2952625,143 -10490587,2952768,161 -10490683,2952929,205 -10490827,2953134,221 -10490941,2953355,121 -10491484,2953476,129 -10491944,2953605,128 -10491993,2953733,240 -10492183,2953973,150 -10492933,2954123,196 -10493256,2954319,151 -10494357,2954470,216 -10494391,2954686,131 -10494747,2954817,157 -10496952,2954974,151 -10497779,2955125,215 -10499743,2955340,166 -10499824,2955506,161 -10499834,2955667,170 -10500725,2955837,131 -10500891,2955968,220 -10502181,2956188,157 -10502209,2956345,163 -10502567,2956508,163 -10502719,2956671,151 -10504220,2956822,151 -10505409,2956973,176 -10505732,2957149,135 -10506196,2957284,137 -10506694,2957421,138 -10507599,2957559,136 -10507742,2957695,154 -10507954,2957849,203 -10508602,2958052,169 -10508964,2958221,166 -10509089,2958387,124 -10509761,2958511,177 -10509799,2958688,142 -10509931,2958830,188 -10511249,2959018,141 -10511640,2959159,132 -10512318,2959291,135 -10512774,2959426,185 -10512896,2959611,151 -10513644,2959762,118 -10513673,2959880,183 -10514000,2960063,216 -10514857,2960279,135 -10515250,2960414,176 -10515452,2960590,218 -10515857,2960808,175 -10516337,2960983,139 -10516666,2961122,174 -10519071,2961296,175 -10519239,2961471,142 -10520093,2961613,222 -10520262,2961835,204 -10520300,2962039,183 -10520681,2962222,166 -10520756,2962388,166 -10521060,2962554,249 -10521223,2962803,207 -10521621,2963010,137 -10521755,2963147,157 -10522846,2963304,152 -10523463,2963456,228 -10524677,2963684,225 -10524909,2963909,285 -10525083,2964194,120 -10525274,2964314,146 -10525629,2964460,182 -10527024,2964642,209 -10527292,2964851,113 -10527714,2964964,165 -10528348,2965129,158 -10528611,2965287,170 -10528973,2965457,166 -10529533,2965623,174 -10530209,2965797,166 -10531072,2965963,266 -10531788,2966229,151 -10531895,2966380,176 -10532005,2966556,161 -10532314,2966717,222 -10532450,2966939,221 -10533357,2967160,127 -10533560,2967287,156 -10533694,2967443,278 -10534736,2967721,172 -10534821,2967893,155 -10535646,2968048,159 -10535902,2968207,213 -10536290,2968420,139 -10536684,2968559,240 -10538696,2968799,182 -10538843,2968981,170 -10539306,2969151,202 -10539969,2969353,151 -10541714,2969504,190 -10542084,2969694,169 -10542487,2969863,182 -10542565,2970045,169 -10542597,2970214,139 -10543617,2970353,223 -10543706,2970576,145 -10543765,2970721,192 -10544211,2970913,157 -10544331,2971070,208 -10544436,2971278,164 -10544617,2971442,139 -10544888,2971581,147 -10545627,2971728,224 -10546038,2971952,137 -10546304,2972089,160 -10546425,2972249,136 -10546637,2972385,120 -10547076,2972505,171 -10547735,2972676,178 -10548161,2972854,263 -10548196,2973117,135 -10548249,2973252,132 -10548304,2973384,177 -10548313,2973561,228 -10548989,2973789,139 -10549321,2973928,136 -10550382,2974064,132 -10550929,2974196,149 -10748208,2974345,175 -10749342,2974520,179 -10750186,2974699,179 -10750411,2974878,201 -10750957,2975079,197 -10751171,2975276,170 -10752578,2975446,146 -10752846,2975592,137 -10753382,2975729,197 -10753841,2975926,202 -10754165,2976128,170 -10755008,2976298,188 -10755954,2976486,140 -10756490,2976626,148 -10756869,2976774,181 -10757299,2976955,154 -10757341,2977109,180 -10757403,2977289,143 -10758464,2977432,250 -10758583,2977682,174 -10759052,2977856,139 -10759176,2977995,173 -10760501,2978168,128 -10761169,2978296,210 -10761433,2978506,166 -10762492,2978672,150 -10762857,2978822,120 -10763258,2978942,278 -10763640,2979220,233 -10765931,2979453,187 -10766074,2979640,149 -10767059,2979789,214 -10767125,2980003,198 -10767377,2980201,170 -10767917,2980371,171 -10767921,2980542,166 -10768169,2980708,278 -10768469,2980986,140 -10769007,2981126,135 -10769922,2981261,242 -10769947,2981503,159 -10769968,2981662,170 -10770972,2981832,168 -10771495,2982000,161 -10771766,2982161,151 -10771873,2982312,142 -10772064,2982454,120 -10772530,2982574,184 -10774278,2982758,120 -10775594,2982878,136 -10775745,2983014,162 -10776185,2983176,179 -10776790,2983355,173 -10778419,2983528,143 -10778464,2983671,130 -10779108,2983801,152 -10779300,2983953,147 -10779343,2984100,174 -10779436,2984274,129 -10779525,2984403,159 -10779668,2984562,132 -10779679,2984694,143 -10780217,2984837,179 -10781166,2985016,134 -10782059,2985150,182 -10783067,2985332,180 -10783963,2985512,125 -10784773,2985637,253 -10785612,2985890,170 -10786747,2986060,219 -10787143,2986279,243 -10787201,2986522,233 -10787416,2986755,175 -10787603,2986930,181 -10788169,2987111,156 -10788571,2987267,141 -10788741,2987408,155 -10788745,2987563,245 -10789314,2987808,150 -10789348,2987958,200 -10789450,2988158,143 -10790099,2988301,209 -10790927,2988510,232 -10792192,2988742,168 -10792376,2988910,213 -10792602,2989123,189 -10793249,2989312,160 -10793367,2989472,120 -10793449,2989592,137 -10793454,2989729,144 -10793639,2989873,151 -10793834,2990024,172 -10795032,2990196,245 -10795392,2990441,153 -10795739,2990594,140 -10795951,2990734,145 -10796641,2990879,174 -10797255,2991053,276 -10797281,2991329,161 -10797739,2991490,222 -10797921,2991712,120 -10798228,2991832,166 -10799070,2991998,192 -10801300,2992190,171 -10801551,2992361,285 -10801617,2992646,155 -10801618,2992801,120 -10802101,2992921,151 -10803286,2993072,153 -10803775,2993225,167 -10804014,2993392,171 -10804016,2993563,204 -10804816,2993767,139 -10805478,2993906,203 -10806062,2994109,181 -10806161,2994290,137 -10806456,2994427,148 -10807089,2994575,132 -10807268,2994707,123 -10807697,2994830,211 -10807715,2995041,203 -10808275,2995244,175 -10808654,2995419,147 -10808919,2995566,152 -10809170,2995718,185 -10810305,2995903,193 -10810658,2996096,174 -10811344,2996270,220 -10812301,2996490,196 -10812622,2996686,180 -11010432,2996866,159 -11011584,2997025,175 -11013133,2997200,136 -11015028,2997336,194 -11015501,2997530,265 -11015858,2997795,154 -11016024,2997949,180 -11016984,2998129,140 -11017050,2998269,228 -11017053,2998497,185 -11017494,2998682,212 -11018159,2998894,146 -11018342,2999040,120 -11019499,2999160,174 -11019993,2999334,170 -11020620,2999504,186 -11021270,2999690,250 -11022509,2999940,197 -11023002,3000137,194 -11024708,3000331,165 -11026497,3000496,202 -11027585,3000698,147 -11027945,3000845,229 -11028901,3001074,180 -11031730,3001254,212 -11031914,3001466,206 -11032398,3001672,261 -11033464,3001933,120 -11033520,3002053,219 -11033587,3002272,131 -11035050,3002403,177 -11035298,3002580,196 -11035615,3002776,169 -11035634,3002945,155 -11035653,3003100,155 -11036082,3003255,288 -11036287,3003543,132 -11037295,3003675,118 -11038885,3003793,177 -11040214,3003970,208 -11040226,3004178,165 -11040623,3004343,122 -11041593,3004465,135 -11041793,3004600,161 -11042355,3004761,138 -11042872,3004899,271 -11043313,3005170,128 -11043455,3005298,283 -11044573,3005581,132 -11044754,3005713,198 -11044845,3005911,157 -11044872,3006068,120 -11046126,3006188,175 -11046267,3006363,221 -11046436,3006584,120 -11046920,3006704,233 -11047468,3006937,155 -11047910,3007092,274 -11048368,3007366,160 -11048586,3007526,120 -11048924,3007646,123 -11049158,3007769,173 -11049308,3007942,119 -11049744,3008061,174 -11050273,3008235,136 -11050450,3008371,224 -11050938,3008595,175 -11052648,3008770,179 -11054397,3008949,218 -11055278,3009167,148 -11055572,3009315,170 -11057587,3009485,162 -11058127,3009647,120 -11058458,3009767,214 -11058490,3009981,178 -11059746,3010159,162 -11062165,3010321,175 -11062469,3010496,132 -11062928,3010628,135 -11063523,3010763,199 -11063525,3010962,149 -11063862,3011111,158 -11064264,3011269,180 -11064329,3011449,155 -11065482,3011604,109 -11067416,3011713,132 -11068398,3011845,177 -11068729,3012022,182 -11071270,3012204,154 -11071544,3012358,315 -11072116,3012673,159 -11072624,3012832,268 -11073504,3013100,216 -11073867,3013316,162 -11074264,3013478,120 -11074416,3013598,127 -11074743,3013725,175 -11141120,3013900,189 -11141121,3014089,189 -11141122,3014278,189 -11141123,3014467,189 -11141124,3014656,189 -11272514,3014845,144 -11272906,3014989,160 -11272911,3015149,263 -11272943,3015412,109 -11273747,3015521,201 -11274849,3015722,123 -11275774,3015845,154 -11276755,3015999,243 -11277409,3016242,200 -11277522,3016442,153 -11277869,3016595,151 -11278082,3016746,142 -11278374,3016888,152 -11278751,3017040,214 -11280554,3017254,178 -11280907,3017432,162 -11282746,3017594,128 -11283875,3017722,121 -11284392,3017843,164 -11284893,3018007,280 -11285707,3018287,220 -11286035,3018507,199 -11286640,3018706,286 -11287162,3018992,140 -11287563,3019132,120 -11287732,3019252,114 -11287813,3019366,174 -11287925,3019540,252 -11288484,3019792,148 -11288810,3019940,193 -11288866,3020133,177 -11289842,3020310,128 -11290403,3020438,108 -11291390,3020546,236 -11291592,3020782,149 -11292305,3020931,201 -11292668,3021132,136 -11292726,3021268,149 -11292981,3021417,119 -11293166,3021536,210 -11293932,3021746,177 -11294252,3021923,206 -11294779,3022129,157 -11295252,3022286,175 -11296016,3022461,143 -11296396,3022604,187 -11297059,3022791,172 -11297293,3022963,183 -11298566,3023146,158 -11299756,3023304,136 -11300378,3023440,303 -11300687,3023743,166 -11300795,3023909,175 -11300825,3024084,198 -11301430,3024282,211 -11301513,3024493,166 -11303490,3024659,140 -11303501,3024799,160 -11303841,3024959,166 -11304766,3025125,120 -11305174,3025245,128 -11305234,3025373,233 -11305459,3025606,134 -11305751,3025740,254 -11305968,3025994,181 -11306301,3026175,194 -11306612,3026369,144 -11306622,3026513,246 -11306915,3026759,120 -11307725,3026879,169 -11308308,3027048,156 -11309871,3027204,132 -11310083,3027336,167 -11311766,3027503,152 -11311882,3027655,136 -11312004,3027791,189 -11312356,3027980,198 -11312663,3028178,163 -11313174,3028341,170 -11313683,3028511,230 -11313708,3028741,183 -11313950,3028924,142 -11314224,3029066,141 -11315481,3029207,135 -11315616,3029342,149 -11316109,3029491,135 -11316159,3029626,183 -11318035,3029809,165 -11318653,3029974,208 -11319119,3030182,140 -11319385,3030322,175 -11320587,3030497,141 -11320949,3030638,196 -11321014,3030834,219 -11322092,3031053,163 -11322773,3031216,158 -11323032,3031374,172 -11323199,3031546,194 -11323701,3031740,158 -11323988,3031898,145 -11324046,3032043,193 -11324075,3032236,147 -11324090,3032383,184 -11324169,3032567,160 -11324558,3032727,140 -11325071,3032867,208 -11325219,3033075,194 -11325276,3033269,120 -11325556,3033389,193 -11325824,3033582,192 -11325880,3033774,241 -11326308,3034015,153 -11327063,3034168,237 -11327958,3034405,136 -11328474,3034541,221 -11329096,3034762,55 -11329552,3034817,204 -11329641,3035021,138 -11330069,3035159,239 -11330376,3035398,136 -11330606,3035534,171 -11331147,3035705,262 -11331707,3035967,238 -11331710,3036205,198 -11331967,3036403,147 -11332010,3036550,165 -11332202,3036715,198 -11333179,3036913,148 -11333810,3037061,200 -11334111,3037261,198 -11334341,3037459,136 -11335667,3037595,191 -11336062,3037786,152 -11337107,3037938,195 -11337166,3038133,166 -11337196,3038299,130 -11534516,3038429,136 -11535764,3038565,206 -11536575,3038771,163 -11536851,3038934,138 -11538497,3039072,221 -11538947,3039293,211 -11539046,3039504,136 -11539464,3039640,202 -11540291,3039842,178 -11541372,3040020,141 -11541649,3040161,174 -11542401,3040335,278 -11543795,3040613,145 -11543978,3040758,55 -11547797,3040813,120 -11548045,3040933,134 -11548713,3041067,221 -11548752,3041288,212 -11551581,3041500,149 -11552021,3041649,161 -11552025,3041810,171 -11552069,3041981,149 -11552508,3042130,204 -11552890,3042334,248 -11553119,3042582,164 -11553797,3042746,178 -11555004,3042924,257 -11555214,3043181,217 -11556614,3043398,120 -11557060,3043518,181 -11557663,3043699,172 -11557735,3043871,239 -11558117,3044110,134 -11559367,3044244,222 -11560291,3044466,188 -11560381,3044654,120 -11561142,3044774,211 -11561329,3044985,132 -11562175,3045117,161 -11564300,3045278,136 -11564365,3045414,127 -11564501,3045541,159 -11564972,3045700,147 -11565320,3045847,158 -11565372,3046005,131 -11565460,3046136,159 -11566434,3046295,163 -11567244,3046458,156 -11567576,3046614,162 -11568126,3046776,124 -11568798,3046900,146 -11569159,3047046,148 -11569553,3047194,136 -11570714,3047330,197 -11571316,3047527,197 -11571508,3047724,140 -11571511,3047864,183 -11572844,3048047,186 -11573050,3048233,156 -11573407,3048389,160 -11573544,3048549,199 -11573986,3048748,147 -11574228,3048895,216 -11575226,3049111,120 -11575562,3049231,168 -11576190,3049399,198 -11577130,3049597,159 -11577143,3049756,144 -11577454,3049900,149 -11577910,3050049,232 -11577975,3050281,136 -11578618,3050417,191 -11578794,3050608,141 -11580124,3050749,225 -11580203,3050974,157 -11580488,3051131,144 -11581653,3051275,201 -11582829,3051476,181 -11582881,3051657,169 -11583385,3051826,164 -11584135,3051990,163 -11584743,3052153,159 -11584852,3052312,177 -11584857,3052489,175 -11585178,3052664,149 -11585349,3052813,164 -11585599,3052977,189 -11585709,3053166,149 -11585883,3053315,214 -11587096,3053529,219 -11587405,3053748,206 -11587740,3053954,175 -11588341,3054129,160 -11589021,3054289,309 -11589573,3054598,126 -11590144,3054724,181 -11591482,3054905,175 -11591740,3055080,171 -11592421,3055251,221 -11592605,3055472,164 -11592974,3055636,140 -11593556,3055776,135 -11593874,3055911,152 -11594110,3056063,209 -11594865,3056272,175 -11594895,3056447,111 -11594977,3056558,55 -11595333,3056613,207 -11596220,3056820,172 -11598571,3056992,136 -11599549,3057128,55 -11796636,3057183,130 -11796802,3057313,185 -11797528,3057498,199 -11797862,3057697,198 -11798521,3057895,185 -11798578,3058080,147 -11799238,3058227,139 -11799364,3058366,208 -11799418,3058574,147 -11799589,3058721,151 -11800214,3058872,153 -11800284,3059025,208 -11801737,3059233,170 -11801875,3059403,200 -11802496,3059603,148 -11802833,3059751,120 -11804143,3059871,160 -11804957,3060031,253 -11805066,3060284,137 -11805927,3060421,198 -11806961,3060619,186 -11807289,3060805,161 -11807890,3060966,248 -11807934,3061214,168 -11808850,3061382,239 -11809208,3061621,119 -11809900,3061740,241 -11810148,3061981,281 -11810295,3062262,199 -11810625,3062461,156 -11811124,3062617,211 -11811286,3062828,172 -11811368,3063000,175 -11812274,3063175,140 -11812411,3063315,156 -11813242,3063471,211 -11813645,3063682,196 -11814750,3063878,140 -11816130,3064018,161 -11817465,3064179,143 -11817555,3064322,145 -11817597,3064467,170 -11817598,3064637,157 -11818352,3064794,106 -11819105,3064900,135 -11820196,3065035,252 -11821567,3065287,136 -11821624,3065423,133 -11821715,3065556,175 -11821741,3065731,143 -11822744,3065874,125 -11823081,3065999,239 -11824437,3066238,291 -11824515,3066529,166 -11826006,3066695,229 -11826335,3066924,173 -11826446,3067097,175 -11827623,3067272,229 -11828265,3067501,392 -11829086,3067893,191 -11829845,3068084,173 -11829883,3068257,137 -11829957,3068394,153 -11830014,3068547,170 -11830599,3068717,159 -11831568,3068876,161 -11834446,3069037,178 -11835458,3069215,182 -11835724,3069397,144 -11835834,3069541,188 -11836852,3069729,212 -11837100,3069941,147 -11837158,3070088,177 -11838645,3070265,178 -11838691,3070443,170 -11838889,3070613,128 -11839528,3070741,303 -11839531,3071044,214 -11839834,3071258,143 -11839998,3071401,220 -11840077,3071621,151 -11840300,3071772,199 -11841135,3071971,197 -11841559,3072168,138 -11842149,3072306,196 -11842402,3072502,159 -11842863,3072661,151 -11842882,3072812,163 -11842991,3072975,198 -11843190,3073173,166 -11843673,3073339,134 -11843725,3073473,152 -11846734,3073625,176 -11847577,3073801,173 -11847696,3073974,133 -11848937,3074107,142 -11849462,3074249,177 -11849691,3074426,248 -11851945,3074674,138 -11851998,3074812,177 -11853077,3074989,158 -11853627,3075147,133 -11853818,3075280,187 -11854029,3075467,147 -11854315,3075614,55 -11856304,3075669,136 -11857177,3075805,163 -11857236,3075968,152 -11857588,3076120,198 -11857620,3076318,144 -11857721,3076462,175 -11858091,3076637,120 -11858664,3076757,139 -11858723,3076896,166 -11861109,3077062,185 -11861644,3077247,162 -12059397,3077409,166 -12059669,3077575,167 -12060879,3077742,166 -12061066,3077908,120 -12061597,3078028,191 -12063763,3078219,226 -12064281,3078445,147 -12064706,3078592,120 -12064879,3078712,154 -12065177,3078866,125 -12067047,3078991,312 -12067856,3079303,171 -12067866,3079474,174 -12068460,3079648,143 -12068564,3079791,244 -12068843,3080035,176 -12069003,3080211,175 -12069367,3080386,150 -12069490,3080536,141 -12069596,3080677,189 -12070048,3080866,162 -12071080,3081028,185 -12072664,3081213,171 -12073057,3081384,136 -12073162,3081520,177 -12073595,3081697,164 -12074318,3081861,264 -12074585,3082125,143 -12075359,3082268,123 -12076004,3082391,129 -12076998,3082520,196 -12079061,3082716,158 -12080400,3082874,275 -12080829,3083149,139 -12081168,3083288,143 -12081779,3083431,175 -12081911,3083606,151 -12081918,3083757,234 -12082811,3083991,175 -12083345,3084166,238 -12083567,3084404,228 -12083743,3084632,170 -12084156,3084802,191 -12084369,3084993,172 -12084539,3085165,156 -12086051,3085321,115 -12086504,3085436,175 -12087540,3085611,219 -12088356,3085830,155 -12088391,3085985,170 -12088768,3086155,147 -12088895,3086302,199 -12089283,3086501,156 -12089390,3086657,120 -12089465,3086777,169 -12089726,3086946,189 -12090057,3087135,136 -12090610,3087271,158 -12093214,3087429,200 -12093352,3087629,181 -12093667,3087810,240 -12093898,3088050,179 -12094048,3088229,166 -12094738,3088395,120 -12095034,3088515,205 -12095174,3088720,167 -12095252,3088887,150 -12096029,3089037,159 -12096722,3089196,155 -12097140,3089351,142 -12097370,3089493,212 -12097712,3089705,130 -12097783,3089835,257 -12097817,3090092,168 -12097968,3090260,168 -12098253,3090428,254 -12098285,3090682,164 -12098505,3090846,132 -12098532,3090978,181 -12100486,3091159,186 -12100576,3091345,217 -12101807,3091562,133 -12102767,3091695,135 -12102974,3091830,139 -12103278,3091969,166 -12103405,3092135,206 -12103527,3092341,167 -12104135,3092508,190 -12104668,3092698,187 -12104750,3092885,253 -12105687,3093138,152 -12105758,3093290,166 -12106062,3093456,229 -12106344,3093685,261 -12106354,3093946,111 -12106605,3094057,161 -12106779,3094218,243 -12107129,3094461,162 -12107455,3094623,170 -12107651,3094793,166 -12108194,3094959,217 -12108735,3095176,273 -12108911,3095449,196 -12109454,3095645,175 -12109590,3095820,222 -12109661,3096042,120 -12109909,3096162,228 -12110394,3096390,141 -12111251,3096531,167 -12111271,3096698,156 -12111983,3096854,270 -12113053,3097124,188 -12113938,3097312,278 -12114382,3097590,159 -12114673,3097749,223 -12114679,3097972,189 -12115079,3098161,156 -12115819,3098317,186 -12117385,3098503,136 -12117541,3098639,127 -12117881,3098766,129 -12118102,3098895,120 -12118327,3099015,149 -12119653,3099164,213 -12119673,3099377,150 -12120192,3099527,140 -12120855,3099667,249 -12121296,3099916,202 -12121575,3100118,158 -12121777,3100276,120 -12121906,3100396,168 -12122152,3100564,236 -12122420,3100800,176 -12123442,3100976,202 -12124001,3101178,120 -12124015,3101298,218 -12124158,3101516,156 -12321280,3101672,161 -12322115,3101833,113 -12324261,3101946,144 -12324651,3102090,167 -12324708,3102257,166 -12325470,3102423,208 -12325889,3102631,208 -12326021,3102839,190 -12326127,3103029,221 -12326310,3103250,231 -12326501,3103481,136 -12326645,3103617,136 -12327527,3103753,203 -12329124,3103956,159 -12329146,3104115,206 -12330464,3104321,241 -12330480,3104562,223 -12330525,3104785,202 -12331078,3104987,203 -12331222,3105190,198 -12331883,3105388,236 -12331991,3105624,202 -12332117,3105826,153 -12332440,3105979,140 -12333147,3106119,140 -12333181,3106259,184 -12334080,3106443,278 -12334565,3106721,162 -12335314,3106883,229 -12335526,3107112,192 -12335850,3107304,228 -12336047,3107532,120 -12336659,3107652,180 -12337408,3107832,164 -12338039,3107996,222 -12338310,3108218,175 -12339040,3108393,175 -12340089,3108568,166 -12340420,3108734,120 -12340731,3108854,229 -12340796,3109083,186 -12340829,3109269,184 -12341758,3109453,186 -12341940,3109639,129 -12341943,3109768,120 -12342521,3109888,233 -12344396,3110121,165 -12345332,3110286,190 -12345360,3110476,236 -12346015,3110712,178 -12346945,3110890,278 -12347164,3111168,136 -12347256,3111304,120 -12347268,3111424,123 -12347926,3111547,165 -12347945,3111712,144 -12347951,3111856,149 -12348237,3112005,134 -12349028,3112139,157 -12349046,3112296,203 -12349889,3112499,152 -12350129,3112651,175 -12350679,3112826,229 -12351054,3113055,148 -12351088,3113203,285 -12351287,3113488,166 -12351391,3113654,177 -12351917,3113831,175 -12352977,3114006,164 -12353823,3114170,129 -12353945,3114299,156 -12354471,3114455,239 -12354847,3114694,159 -12354902,3114853,201 -12355731,3115054,129 -12356437,3115183,193 -12356813,3115376,227 -12356878,3115603,134 -12358251,3115737,120 -12359296,3115857,304 -12359817,3116161,221 -12360124,3116382,192 -12360901,3116574,274 -12361125,3116848,143 -12362977,3116991,111 -12364246,3117102,159 -12365509,3117261,162 -12366209,3117423,151 -12366323,3117574,159 -12366600,3117733,261 -12367954,3117994,154 -12368609,3118148,168 -12368841,3118316,161 -12368966,3118477,173 -12370280,3118650,137 -12370490,3118787,157 -12370754,3118944,194 -12371091,3119138,136 -12371482,3119274,251 -12371675,3119525,131 -12371984,3119656,140 -12372661,3119796,156 -12373317,3119952,119 -12373964,3120071,171 -12374373,3120242,143 -12374391,3120385,242 -12374483,3120627,234 -12375478,3120861,153 -12376384,3121014,134 -12378269,3121148,166 -12379551,3121314,234 -12380007,3121548,215 -12380715,3121763,127 -12380922,3121890,151 -12381023,3122041,239 -12381219,3122280,243 -12381819,3122523,162 -12382706,3122685,125 -12382895,3122810,127 -12383660,3122937,155 -12383772,3123092,239 -12383877,3123331,184 -12384273,3123515,223 -12385932,3123738,136 -12386220,3123874,149 -12584386,3124023,156 -12586366,3124179,150 -12587430,3124329,141 -12587586,3124470,168 -12588093,3124638,200 -12589189,3124838,199 -12589786,3125037,120 -12590747,3125157,118 -12591696,3125275,55 -12592390,3125330,113 -12592476,3125443,136 -12592487,3125579,146 -12593081,3125725,308 -12593523,3126033,178 -12593651,3126211,169 -12594172,3126380,161 -12594298,3126541,193 -12596062,3126734,135 -12596404,3126869,169 -12596608,3127038,118 -12596669,3127156,137 -12596677,3127293,172 -12597398,3127465,220 -12597497,3127685,138 -12598159,3127823,146 -12598598,3127969,228 -12598799,3128197,134 -12599054,3128331,139 -12599082,3128470,164 -12599253,3128634,219 -12599798,3128853,176 -12600065,3129029,130 -12600547,3129159,248 -12601661,3129407,179 -12601856,3129586,264 -12602871,3129850,135 -12604967,3129985,174 -12605155,3130159,227 -12605372,3130386,144 -12605607,3130530,152 -12607087,3130682,165 -12607097,3130847,235 -12607768,3131082,253 -12608107,3131335,170 -12608404,3131505,120 -12608710,3131625,130 -12608921,3131755,175 -12609455,3131930,136 -12610575,3132066,143 -12610669,3132209,152 -12611593,3132361,238 -12614588,3132599,136 -12615232,3132735,241 -12616048,3132976,162 -12616458,3133138,124 -12616826,3133262,120 -12617819,3133382,200 -12618462,3133582,143 -12618607,3133725,202 -12618848,3133927,136 -12620082,3134063,134 -12620084,3134197,173 -12621945,3134370,166 -12622053,3134536,184 -12622449,3134720,213 -12622994,3134933,206 -12623142,3135139,180 -12623682,3135319,120 -12624059,3135439,173 -12624071,3135612,159 -12624094,3135771,133 -12624098,3135904,147 -12624493,3136051,156 -12624740,3136207,158 -12624798,3136365,149 -12626536,3136514,151 -12627028,3136665,129 -12628793,3136794,120 -12628823,3136914,205 -12630193,3137119,172 -12630758,3137291,240 -12631362,3137531,148 -12631505,3137679,229 -12632512,3137908,152 -12633014,3138060,140 -12633376,3138200,158 -12633449,3138358,205 -12633735,3138563,143 -12634438,3138706,178 -12634936,3138884,199 -12635853,3139083,120 -12636067,3139203,187 -12636228,3139390,132 -12638562,3139522,189 -12638836,3139711,207 -12639338,3139918,248 -12640119,3140166,152 -12641314,3140318,152 -12641614,3140470,160 -12643044,3140630,133 -12644091,3140763,207 -12644804,3140970,218 -12645115,3141188,120 -12646301,3141308,139 -12646618,3141447,199 -12646801,3141646,182 -12648404,3141828,139 -12845062,3141967,176 -12845378,3142143,208 -12845436,3142351,157 -12845489,3142508,143 -12845518,3142651,172 -12846101,3142823,151 -12846376,3142974,244 -12846895,3143218,241 -12847178,3143459,127 -12847232,3143586,245 -12847416,3143831,232 -12847819,3144063,170 -12848709,3144233,179 -12848905,3144412,149 -12849290,3144561,157 -12849909,3144718,177 -12850146,3144895,156 -12850236,3145051,136 -12850938,3145187,151 -12851198,3145338,199 -12851595,3145537,195 -12851692,3145732,123 -12852942,3145855,179 -12853704,3146034,167 -12854138,3146201,146 -12854318,3146347,170 -12854824,3146517,151 -12855189,3146668,159 -12855581,3146827,205 -12856323,3147032,120 -12857232,3147152,227 -12858475,3147379,151 -12858988,3147530,149 -12859098,3147679,168 -12859603,3147847,213 -12859706,3148060,132 -12860063,3148192,138 -12860094,3148330,157 -12860476,3148487,135 -12860871,3148622,139 -12861954,3148761,175 -12862351,3148936,152 -12862823,3149088,205 -12862956,3149293,189 -12863001,3149482,199 -12863544,3149681,151 -12864208,3149832,138 -12864324,3149970,143 -12864465,3150113,244 -12865055,3150357,147 -12865196,3150504,250 -12865542,3150754,199 -12866628,3150953,200 -12866982,3151153,152 -12867010,3151305,128 -12867072,3151433,176 -12867326,3151609,227 -12867438,3151836,186 -12867778,3152022,266 -12867958,3152288,166 -12869080,3152454,149 -12869700,3152603,170 -12870251,3152773,144 -12870378,3152917,175 -12870484,3153092,127 -12870675,3153219,170 -12871605,3153389,127 -12871998,3153516,164 -12872375,3153680,229 -12872628,3153909,132 -12873201,3154041,126 -12873247,3154167,263 -12874032,3154430,161 -12874238,3154591,170 -12874389,3154761,136 -12874526,3154897,180 -12876591,3155077,234 -12876707,3155311,138 -12877126,3155449,199 -12877135,3155648,170 -12877260,3155818,173 -12877310,3155991,143 -12877649,3156134,142 -12878399,3156276,226 -12878414,3156502,203 -12879112,3156705,166 -12880101,3156871,175 -12881551,3157046,219 -12882234,3157265,258 -12882508,3157523,160 -12882688,3157683,119 -12882707,3157802,183 -12882816,3157985,207 -12883362,3158192,268 -12883973,3158460,175 -12884482,3158635,200 -12888093,3158835,179 -12888737,3159014,178 -12889377,3159192,213 -12891410,3159405,173 -12892825,3159578,217 -12892835,3159795,245 -12893546,3160040,134 -12893828,3160174,144 -12894382,3160318,160 -12894623,3160478,274 -12896085,3160752,233 -12896537,3160985,158 -12896748,3161143,184 -12896985,3161327,207 -12897605,3161534,239 -12899465,3161773,216 -12899925,3161989,209 -12900743,3162198,166 -12900902,3162364,145 -12902450,3162509,160 -12902780,3162669,172 -12904382,3162841,187 -12904751,3163028,129 -12904836,3163157,260 -12904989,3163417,146 -12905443,3163563,128 -12905914,3163691,144 -12906158,3163835,149 -12906229,3163984,152 -12907620,3164136,142 -12907900,3164278,180 -12909796,3164458,143 -13107332,3164601,136 -13107728,3164737,148 -13107800,3164885,124 -13107878,3165009,177 -13109016,3165186,148 -13109481,3165334,165 -13109929,3165499,174 -13110804,3165673,209 -13110903,3165882,290 -13110933,3166172,136 -13112441,3166308,175 -13113021,3166483,197 -13113847,3166680,175 -13114110,3166855,143 -13114219,3166998,160 -13115022,3167158,143 -13115111,3167301,128 -13115238,3167429,127 -13115534,3167556,134 -13117738,3167690,175 -13117972,3167865,120 -13119124,3167985,197 -13119848,3168182,218 -13120050,3168400,152 -13120331,3168552,120 -13120654,3168672,166 -13120952,3168838,142 -13122101,3168980,219 -13122373,3169199,125 -13122967,3169324,134 -13123225,3169458,144 -13123239,3169602,125 -13123508,3169727,148 -13124905,3169875,194 -13124932,3170069,238 -13125007,3170307,124 -13125877,3170431,181 -13126773,3170612,170 -13129285,3170782,137 -13129315,3170919,146 -13131776,3171065,163 -13132999,3171228,160 -13134878,3171388,156 -13134983,3171544,192 -13135030,3171736,139 -13135645,3171875,120 -13136456,3171995,137 -13138779,3172132,161 -13139132,3172293,181 -13139319,3172474,303 -13139573,3172777,175 -13141049,3172952,153 -13141063,3173105,189 -13141328,3173294,120 -13141819,3173414,138 -13142659,3173552,250 -13142855,3173802,186 -13144126,3173988,139 -13144569,3174127,151 -13144902,3174278,186 -13144963,3174464,154 -13145298,3174618,205 -13146015,3174823,135 -13147165,3174958,170 -13147356,3175128,204 -13147933,3175332,273 -13147970,3175605,148 -13148208,3175753,144 -13148598,3175897,282 -13148602,3176179,168 -13149728,3176347,145 -13149962,3176492,143 -13149993,3176635,219 -13150243,3176854,175 -13150753,3177029,147 -13150924,3177176,55 -13151900,3177231,195 -13152064,3177426,194 -13153139,3177620,152 -13153719,3177772,120 -13154964,3177892,229 -13155283,3178121,146 -13155528,3178267,120 -13155865,3178387,222 -13156646,3178609,164 -13156668,3178773,228 -13157646,3179001,273 -13158289,3179274,134 -13159352,3179408,153 -13159794,3179561,131 -13160473,3179692,229 -13160715,3179921,146 -13160798,3180067,239 -13160913,3180306,220 -13161153,3180526,221 -13161379,3180747,210 -13161513,3180957,141 -13161872,3181098,154 -13161982,3181252,280 -13162265,3181532,171 -13162361,3181703,204 -13163977,3181907,283 -13164113,3182190,156 -13164412,3182346,135 -13164779,3182481,120 -13164848,3182601,193 -13164967,3182794,178 -13165615,3182972,206 -13166552,3183178,269 -13168136,3183447,192 -13168245,3183639,203 -13168294,3183842,230 -13168430,3184072,205 -13169515,3184277,151 -13169542,3184428,260 -13169670,3184688,138 -13170256,3184826,120 -13170317,3184946,188 -13170436,3185134,159 -13170483,3185293,166 -13171073,3185459,124 -13171193,3185583,170 -13171494,3185753,143 -13172272,3185896,267 -13172599,3186163,145 -13369472,3186308,139 -13370362,3186447,167 -13370492,3186614,157 -13370548,3186771,140 -13370651,3186911,175 -13371307,3187086,175 -13371364,3187261,285 -13371616,3187546,120 -13371848,3187666,142 -13372634,3187808,129 -13372908,3187937,143 -13373603,3188080,233 -13374630,3188313,169 -13375611,3188482,159 -13375912,3188641,183 -13376250,3188824,160 -13377279,3188984,162 -13378072,3189146,208 -13379117,3189354,137 -13380085,3189491,120 -13380224,3189611,224 -13381004,3189835,177 -13381760,3190012,138 -13382587,3190150,177 -13382697,3190327,264 -13382871,3190591,136 -13382976,3190727,159 -13384076,3190886,163 -13384289,3191049,207 -13384767,3191256,151 -13385090,3191407,166 -13385311,3191573,151 -13385501,3191724,154 -13386723,3191878,125 -13387523,3192003,209 -13388513,3192212,175 -13388795,3192387,140 -13389348,3192527,180 -13389548,3192707,189 -13389852,3192896,161 -13389942,3193057,184 -13390511,3193241,243 -13390773,3193484,194 -13390937,3193678,127 -13391277,3193805,118 -13392190,3193923,157 -13393013,3194080,270 -13393230,3194350,204 -13393239,3194554,235 -13394107,3194789,150 -13395373,3194939,156 -13396400,3195095,202 -13396888,3195297,161 -13396977,3195458,154 -13397408,3195612,145 -13397487,3195757,123 -13398543,3195880,164 -13399192,3196044,150 -13399657,3196194,143 -13400159,3196337,120 -13400624,3196457,185 -13400885,3196642,160 -13401399,3196802,147 -13401831,3196949,170 -13403500,3197119,250 -13404669,3197369,130 -13405411,3197499,144 -13406355,3197643,180 -13406507,3197823,201 -13407306,3198024,146 -13407703,3198170,128 -13407797,3198298,173 -13407904,3198471,285 -13409792,3198756,161 -13410101,3198917,139 -13410533,3199056,154 -13410851,3199210,239 -13411188,3199449,256 -13411426,3199705,147 -13411503,3199852,220 -13411860,3200072,203 -13414264,3200275,199 -13414997,3200474,169 -13415416,3200643,171 -13415770,3200814,158 -13416081,3200972,178 -13416584,3201150,133 -13416689,3201283,200 -13417781,3201483,140 -13417939,3201623,173 -13418097,3201796,137 -13418756,3201933,159 -13419498,3202092,163 -13419786,3202255,236 -13420075,3202491,176 -13420759,3202667,144 -13421646,3202811,182 -13421697,3202993,192 -13421924,3203185,141 -13422144,3203326,146 -13423259,3203472,232 -13423929,3203704,136 -13424657,3203840,212 -13424833,3204052,136 -13425129,3204188,134 -13427071,3204322,149 -13427157,3204471,162 -13428632,3204633,136 -13428703,3204769,159 -13428908,3204928,204 -13429276,3205132,189 -13430489,3205321,139 -13430600,3205460,170 -13431717,3205630,215 -13431815,3205845,163 -13432120,3206008,174 -13432442,3206182,161 -13432897,3206343,125 -13433072,3206468,325 -13433172,3206793,138 -13433320,3206931,175 -13433344,3207106,155 -13433701,3207261,160 -13433965,3207421,149 -13434033,3207570,170 -13434428,3207740,159 -13632331,3207899,128 -13632658,3208027,221 -13633424,3208248,144 -13634219,3208392,185 -13635236,3208577,177 -13635289,3208754,182 -13636162,3208936,142 -13636382,3209078,186 -13636938,3209264,160 -13637482,3209424,175 -13638311,3209599,129 -13638843,3209728,238 -13640210,3209966,278 -13640382,3210244,227 -13640667,3210471,120 -13640982,3210591,265 -13641112,3210856,132 -13641608,3210988,187 -13642821,3211175,167 -13643187,3211342,239 -13644048,3211581,248 -13645665,3211829,144 -13646194,3211973,139 -13646259,3212112,156 -13648670,3212268,143 -13649628,3212411,173 -13650163,3212584,130 -13651137,3212714,238 -13651244,3212952,142 -13651838,3213094,120 -13652121,3213214,197 -13652322,3213411,157 -13652648,3213568,183 -13652809,3213751,199 -13653037,3213950,193 -13653836,3214143,170 -13653893,3214313,174 -13653921,3214487,180 -13654133,3214667,184 -13654467,3214851,224 -13654500,3215075,175 -13654543,3215250,188 -13654769,3215438,244 -13654952,3215682,179 -13655162,3215861,122 -13655992,3215983,142 -13656014,3216125,159 -13656736,3216284,281 -13656909,3216565,174 -13657012,3216739,130 -13657723,3216869,196 -13658085,3217065,138 -13658526,3217203,178 -13658576,3217381,182 -13658655,3217563,153 -13659978,3217716,234 -13660892,3217950,136 -13661055,3218086,152 -13661070,3218238,199 -13661141,3218437,162 -13661630,3218599,131 -13661776,3218730,278 -13662901,3219008,243 -13663717,3219251,172 -13663784,3219423,153 -13663797,3219576,166 -13665236,3219742,137 -13665456,3219879,151 -13666713,3220030,140 -13666901,3220170,145 -13667198,3220315,174 -13667509,3220489,144 -13667583,3220633,115 -13669022,3220748,158 -13669368,3220906,176 -13669831,3221082,174 -13671173,3221256,142 -13671472,3221398,178 -13671690,3221576,121 -13671851,3221697,171 -13672662,3221868,202 -13673233,3222070,185 -13673894,3222255,136 -13674039,3222391,120 -13676268,3222511,201 -13676470,3222712,178 -13677375,3222890,272 -13677720,3223162,194 -13677859,3223356,204 -13677885,3223560,158 -13678018,3223718,139 -13679488,3223857,168 -13679873,3224025,185 -13680172,3224210,211 -13680540,3224421,148 -13680831,3224569,232 -13681073,3224801,175 -13681282,3224976,170 -13681711,3225146,179 -13682569,3225325,136 -13682624,3225461,253 -13684193,3225714,205 -13684574,3225919,129 -13684989,3226048,170 -13685266,3226218,174 -13685382,3226392,173 -13685756,3226565,149 -13685778,3226714,142 -13685873,3226856,176 -13686476,3227032,135 -13687602,3227167,132 -13688730,3227299,188 -13688754,3227487,187 -13688775,3227674,175 -13689152,3227849,130 -13689671,3227979,117 -13689867,3228096,138 -13690189,3228234,152 -13690754,3228386,214 -13691651,3228600,309 -13691806,3228909,166 -13693147,3229075,124 -13693567,3229199,181 -13694779,3229380,139 -13695517,3229519,204 -13696848,3229723,149 -13893645,3229872,206 -13893719,3230078,137 -13893929,3230215,152 -13893997,3230367,264 -13894218,3230631,157 -13895064,3230788,148 -13896474,3230936,180 -13896633,3231116,144 -13897650,3231260,166 -13897872,3231426,141 -13897935,3231567,218 -13898198,3231785,154 -13898390,3231939,171 -13898427,3232110,204 -13898607,3232314,162 -13900828,3232476,137 -13901365,3232613,171 -13901580,3232784,113 -13901933,3232897,163 -13902114,3233060,167 -13902399,3233227,280 -13902414,3233507,129 -13903697,3233636,163 -13904050,3233799,160 -13904362,3233959,135 -13904957,3234094,210 -13905699,3234304,146 -13906333,3234450,142 -13906534,3234592,148 -13907927,3234740,160 -13908581,3234900,202 -13908713,3235102,207 -13909351,3235309,149 -13909374,3235458,184 -13910952,3235642,206 -13912926,3235848,152 -13913124,3236000,225 -13913244,3236225,261 -13913255,3236486,212 -13913984,3236698,169 -13914234,3236867,144 -13914666,3237011,131 -13914705,3237142,178 -13914775,3237320,204 -13915055,3237524,159 -13915478,3237683,149 -13916850,3237832,177 -13917296,3238009,161 -13917506,3238170,132 -13918514,3238302,220 -13919479,3238522,212 -13919912,3238734,146 -13920097,3238880,179 -13920231,3239059,221 -13920333,3239280,143 -13920359,3239423,174 -13920442,3239597,262 -13920913,3239859,156 -13920936,3240015,194 -13921471,3240209,136 -13921498,3240345,143 -13921616,3240488,136 -13921884,3240624,243 -13922114,3240867,157 -13924803,3241024,158 -13925173,3241182,135 -13925237,3241317,179 -13926858,3241496,148 -13926974,3241644,167 -13927780,3241811,188 -13928408,3241999,159 -13928592,3242158,175 -13929653,3242333,170 -13929945,3242503,152 -13930291,3242655,158 -13930410,3242813,174 -13930927,3242987,175 -13931416,3243162,134 -13931424,3243296,135 -13931610,3243431,153 -13931681,3243584,144 -13931812,3243728,173 -13932255,3243901,158 -13932299,3244059,203 -13933088,3244262,120 -13933608,3244382,165 -13933710,3244547,139 -13934189,3244686,255 -13934634,3244941,170 -13935653,3245111,193 -13935769,3245304,185 -13936936,3245489,151 -13937407,3245640,134 -13937742,3245774,145 -13937965,3245919,221 -13938258,3246140,138 -13938960,3246278,200 -13939774,3246478,163 -13942489,3246641,138 -13942573,3246779,201 -13942655,3246980,126 -13943292,3247106,132 -13944678,3247238,132 -13945327,3247370,151 -13945453,3247521,143 -13945454,3247664,124 -13945775,3247788,135 -13946552,3247923,139 -13946873,3248062,229 -13947268,3248291,135 -13947465,3248426,174 -13948173,3248600,155 -13948744,3248755,170 -13948841,3248925,194 -13949080,3249119,199 -13949209,3249318,123 -13950807,3249441,188 -13951118,3249629,221 -13951788,3249850,137 -13951807,3249987,134 -13953202,3250121,159 -13953550,3250280,143 -13954060,3250423,181 -13954182,3250604,241 -13954567,3250845,196 -13955111,3251041,211 -13955252,3251252,165 -13955395,3251417,181 -13956207,3251598,120 -13956371,3251718,142 -13956671,3251860,132 -13957537,3251992,194 -14155853,3252186,120 -14157102,3252306,183 -14157521,3252489,206 -14158069,3252695,157 -14158275,3252852,135 -14159055,3252987,171 -14159331,3253158,140 -14161165,3253298,260 -14161418,3253558,169 -14161963,3253727,175 -14162382,3253902,183 -14162942,3254085,189 -14162964,3254274,181 -14163314,3254455,120 -14163678,3254575,137 -14165181,3254712,170 -14165282,3254882,139 -14165689,3255021,220 -14165772,3255241,217 -14166217,3255458,204 -14166294,3255662,200 -14166406,3255862,181 -14166549,3256043,128 -14166654,3256171,135 -14167451,3256306,289 -14167521,3256595,145 -14168162,3256740,120 -14168527,3256860,175 -14168959,3257035,158 -14171241,3257193,242 -14172844,3257435,219 -14173702,3257654,177 -14174475,3257831,199 -14174511,3258030,136 -14174855,3258166,164 -14175018,3258330,173 -14176486,3258503,188 -14177338,3258691,144 -14177442,3258835,156 -14177699,3258991,159 -14178287,3259150,159 -14178519,3259309,133 -14179660,3259442,228 -14179716,3259670,134 -14179810,3259804,219 -14179823,3260023,163 -14179835,3260186,55 -14180756,3260241,189 -14181083,3260430,127 -14181781,3260557,192 -14182086,3260749,253 -14182126,3261002,235 -14182361,3261237,170 -14182752,3261407,127 -14183415,3261534,161 -14183657,3261695,148 -14184791,3261843,277 -14185621,3262120,163 -14185779,3262283,135 -14185994,3262418,145 -14186725,3262563,122 -14186888,3262685,210 -14187741,3262895,179 -14188209,3263074,158 -14188601,3263232,180 -14189006,3263412,175 -14189670,3263587,140 -14191163,3263727,121 -14191964,3263848,163 -14192872,3264011,175 -14193473,3264186,176 -14193967,3264362,159 -14194309,3264521,123 -14194325,3264644,120 -14194400,3264764,237 -14194491,3265001,198 -14194528,3265199,144 -14194556,3265343,136 -14194618,3265479,166 -14195252,3265645,194 -14196071,3265839,151 -14196153,3265990,214 -14196287,3266204,120 -14197342,3266324,120 -14200285,3266444,170 -14200464,3266614,148 -14200635,3266762,258 -14200817,3267020,172 -14200878,3267192,250 -14200908,3267442,196 -14201130,3267638,206 -14201719,3267844,156 -14202551,3268000,221 -14202561,3268221,180 -14202582,3268401,171 -14203126,3268572,144 -14203150,3268716,228 -14203692,3268944,120 -14204748,3269064,202 -14205032,3269266,194 -14205947,3269460,164 -14206609,3269624,195 -14206920,3269819,141 -14207389,3269960,148 -14207882,3270108,200 -14208924,3270308,120 -14209483,3270428,120 -14209660,3270548,145 -14209925,3270693,167 -14210108,3270860,141 -14210489,3271001,173 -14210686,3271174,192 -14211666,3271366,144 -14212329,3271510,266 -14212447,3271776,133 -14212605,3271909,144 -14212814,3272053,207 -14212877,3272260,128 -14214062,3272388,156 -14214509,3272544,202 -14214955,3272746,168 -14214979,3272914,171 -14215506,3273085,128 -14216087,3273213,143 -14216824,3273356,149 -14217458,3273505,156 -14219024,3273661,194 -14220049,3273855,133 -14220435,3273988,166 -14220943,3274154,181 -14221027,3274335,171 -14418533,3274506,125 -14418574,3274631,155 -14419247,3274786,155 -14419317,3274941,181 -14419437,3275122,155 -14419905,3275277,252 -14420244,3275529,143 -14420762,3275672,135 -14421665,3275807,241 -14423515,3276048,246 -14423714,3276294,151 -14423898,3276445,203 -14423954,3276648,168 -14425503,3276816,192 -14425556,3277008,153 -14425763,3277161,154 -14426120,3277315,225 -14428692,3277540,183 -14429025,3277723,120 -14429030,3277843,186 -14429130,3278029,128 -14429222,3278157,200 -14429802,3278357,168 -14429955,3278525,235 -14430364,3278760,158 -14431056,3278918,124 -14432020,3279042,132 -14432210,3279174,296 -14432481,3279470,150 -14432633,3279620,144 -14432862,3279764,143 -14433326,3279907,192 -14433412,3280099,165 -14433873,3280264,158 -14434040,3280422,130 -14435607,3280552,147 -14436809,3280699,139 -14438110,3280838,182 -14439292,3281020,210 -14440166,3281230,214 -14440230,3281444,128 -14442038,3281572,148 -14442657,3281720,184 -14443644,3281904,176 -14444090,3282080,208 -14446336,3282288,164 -14446344,3282452,179 -14446612,3282631,55 -14446916,3282686,188 -14449556,3282874,170 -14451291,3283044,155 -14452190,3283199,201 -14452440,3283400,130 -14457630,3283530,156 -14457756,3283686,120 -14457938,3283806,227 -14458788,3284033,132 -14458843,3284165,165 -14460404,3284330,136 -14460605,3284466,214 -14460889,3284680,163 -14461135,3284843,155 -14461297,3284998,166 -14461321,3285164,133 -14462366,3285297,163 -14462468,3285460,133 -14463064,3285593,174 -14464196,3285767,134 -14466960,3285901,252 -14467291,3286153,286 -14467329,3286439,217 -14468130,3286656,185 -14468642,3286841,182 -14469011,3287023,134 -14470056,3287157,166 -14470721,3287323,205 -14470844,3287528,275 -14471060,3287803,244 -14471415,3288047,149 -14471932,3288196,194 -14471969,3288390,182 -14472490,3288572,185 -14473343,3288757,240 -14473807,3288997,177 -14474096,3289174,214 -14474954,3289388,158 -14475302,3289546,153 -14475693,3289699,352 -14475948,3290051,193 -14476664,3290244,299 -14477084,3290543,156 -14478342,3290699,249 -14479453,3290948,173 -14479632,3291121,134 -14481237,3291255,159 -14481496,3291414,228 -14482133,3291642,135 -14482178,3291777,166 -14680944,3291943,279 -14681541,3292222,228 -14681830,3292450,203 -14682920,3292653,126 -14683263,3292779,161 -14683577,3292940,55 -14684287,3292995,141 -14685246,3293136,185 -14686327,3293321,191 -14686493,3293512,238 -14687297,3293750,158 -14687470,3293908,149 -14687544,3294057,232 -14687547,3294289,193 -14687751,3294482,157 -14688010,3294639,185 -14689407,3294824,192 -14689592,3295016,157 -14689840,3295173,177 -14689846,3295350,148 -14690074,3295498,195 -14690946,3295693,243 -14691506,3295936,246 -14692205,3296182,136 -14692357,3296318,173 -14692816,3296491,220 -14693728,3296711,197 -14694115,3296908,230 -14694871,3297138,160 -14695515,3297298,273 -14696004,3297571,153 -14696010,3297724,177 -14696061,3297901,153 -14696265,3298054,163 -14698138,3298217,139 -14699333,3298356,208 -14701975,3298564,199 -14702324,3298763,151 -14702750,3298914,136 -14703472,3299050,186 -14704038,3299236,192 -14704569,3299428,170 -14705074,3299598,231 -14705296,3299829,236 -14705637,3300065,157 -14705851,3300222,131 -14706296,3300353,120 -14706611,3300473,230 -14707093,3300703,167 -14710026,3300870,162 -14710141,3301032,163 -14710480,3301195,204 -14711906,3301399,169 -14712659,3301568,129 -14712712,3301697,134 -14713207,3301831,148 -14714801,3301979,164 -14714973,3302143,171 -14715293,3302314,136 -14715518,3302450,134 -14716476,3302584,165 -14716908,3302749,182 -14717267,3302931,185 -14717429,3303116,139 -14718055,3303255,166 -14718329,3303421,182 -14718870,3303603,199 -14718962,3303802,152 -14719345,3303954,175 -14720305,3304129,166 -14720440,3304295,184 -14721432,3304479,167 -14721495,3304646,144 -14721807,3304790,123 -14722672,3304913,135 -14723760,3305048,276 -14724094,3305324,158 -14724337,3305482,136 -14724702,3305618,147 -14724786,3305765,159 -14724845,3305924,167 -14724939,3306091,169 -14725873,3306260,232 -14726445,3306492,120 -14726922,3306612,148 -14727089,3306760,139 -14727589,3306899,154 -14727610,3307053,120 -14728259,3307173,178 -14729862,3307351,220 -14729911,3307571,137 -14730227,3307708,179 -14730931,3307887,120 -14731165,3308007,144 -14731370,3308151,211 -14731554,3308362,223 -14731642,3308585,120 -14731853,3308705,227 -14731924,3308932,174 -14732061,3309106,55 -14732110,3309161,162 -14732270,3309323,175 -14732995,3309498,178 -14733101,3309676,185 -14733578,3309861,165 -14733683,3310026,136 -14733798,3310162,177 -14734106,3310339,203 -14735290,3310542,159 -14735778,3310701,139 -14736092,3310840,173 -14736144,3311013,175 -14736213,3311188,142 -14736264,3311330,231 -14736544,3311561,221 -14738895,3311782,139 -14738993,3311921,215 -14739281,3312136,161 -14739688,3312297,185 -14740762,3312482,187 -14740935,3312669,277 -14741019,3312946,219 -14741285,3313165,209 -14742033,3313374,127 -14742393,3313501,131 -14742982,3313632,120 -14742986,3313752,263 -14743623,3314015,120 -14743998,3314135,181 -14744300,3314316,154 -14745591,3314470,156 -14943289,3314626,174 -14946651,3314800,151 -14946840,3314951,216 -14946845,3315167,199 -14946953,3315366,156 -14949451,3315522,175 -14949677,3315697,187 -14950163,3315884,168 -14951252,3316052,235 -14951911,3316287,120 -14951913,3316407,155 -14952305,3316562,137 -14953171,3316699,166 -14953558,3316865,161 -14953730,3317026,182 -14954278,3317208,221 -14954486,3317429,197 -14955211,3317626,175 -14955923,3317801,206 -14956027,3318007,202 -14956503,3318209,148 -14956786,3318357,151 -14958498,3318508,201 -14958818,3318709,175 -14959078,3318884,151 -14960317,3319035,200 -14960839,3319235,145 -14961772,3319380,217 -14962200,3319597,183 -14962473,3319780,174 -14962527,3319954,202 -14964202,3320156,165 -14964244,3320321,145 -14964648,3320466,177 -14964967,3320643,175 -14965410,3320818,198 -14966098,3321016,143 -14967881,3321159,147 -14968762,3321306,173 -14968995,3321479,194 -14969178,3321673,161 -14969889,3321834,135 -14971269,3321969,159 -14972190,3322128,138 -14972707,3322266,151 -14972779,3322417,128 -14972884,3322545,225 -14974201,3322770,209 -14974298,3322979,211 -14974898,3323190,199 -14975364,3323389,134 -14975411,3323523,249 -14975897,3323772,147 -14976257,3323919,153 -14977749,3324072,187 -14977919,3324259,120 -14978063,3324379,140 -14978444,3324519,146 -14979177,3324665,164 -14979198,3324829,202 -14979815,3325031,195 -14979835,3325226,175 -14980462,3325401,278 -14980782,3325679,182 -14981104,3325861,206 -14981334,3326067,130 -14984687,3326197,227 -14985213,3326424,157 -14986054,3326581,130 -14986621,3326711,135 -14987169,3326846,136 -14987297,3326982,175 -14990041,3327157,155 -14991686,3327312,170 -14992939,3327482,150 -14992957,3327632,132 -14993126,3327764,149 -14993186,3327913,136 -14993414,3328049,227 -14995056,3328276,188 -14995087,3328464,120 -14996274,3328584,253 -14996465,3328837,136 -14996797,3328973,199 -14997277,3329172,156 -14998905,3329328,152 -14999749,3329480,193 -15000585,3329673,136 -15002640,3329809,137 -15003389,3329946,155 -15004517,3330101,144 -15004643,3330245,197 -15004870,3330442,139 -15005601,3330581,141 -15005852,3330722,166 -15005935,3330888,161 -15006009,3331049,194 -15006237,3331243,175 -15006461,3331418,166 -15007449,3331584,186 -15007709,3331770,173 -15205274,3331943,225 -15205387,3332168,120 -15205392,3332288,55 -15205474,3332343,170 -15205619,3332513,186 -15205741,3332699,148 -15206024,3332847,120 -15206335,3332967,233 -15206539,3333200,243 -15207187,3333443,179 -15207480,3333622,198 -15207541,3333820,135 -15208494,3333955,168 -15208754,3334123,225 -15209252,3334348,220 -15209742,3334568,166 -15210027,3334734,201 -15210492,3334935,180 -15210595,3335115,278 -15214711,3335393,155 -15214805,3335548,205 -15215338,3335753,166 -15216164,3335919,180 -15217537,3336099,148 -15218554,3336247,209 -15218997,3336456,151 -15219167,3336607,160 -15219351,3336767,154 -15220406,3336921,118 -15220475,3337039,185 -15220476,3337224,147 -15220800,3337371,170 -15220978,3337541,167 -15221686,3337708,183 -15221886,3337891,187 -15222815,3338078,177 -15224326,3338255,218 -15224452,3338473,175 -15224526,3338648,161 -15224971,3338809,229 -15225198,3339038,182 -15225245,3339220,214 -15225988,3339434,241 -15226582,3339675,149 -15227559,3339824,168 -15227739,3339992,178 -15227888,3340170,131 -15228267,3340301,164 -15228499,3340465,156 -15229215,3340621,187 -15229310,3340808,213 -15229315,3341021,187 -15229374,3341208,138 -15230281,3341346,152 -15230660,3341498,165 -15232218,3341663,229 -15232338,3341892,147 -15232340,3342039,196 -15232366,3342235,220 -15233421,3342455,208 -15234278,3342663,137 -15234431,3342800,257 -15235233,3343057,146 -15235827,3343203,124 -15237166,3343327,120 -15237336,3343447,221 -15239075,3343668,173 -15239468,3343841,147 -15240488,3343988,120 -15240693,3344108,150 -15240800,3344258,143 -15241504,3344401,202 -15241752,3344603,156 -15241892,3344759,153 -15242316,3344912,178 -15242486,3345090,265 -15242758,3345355,298 -15243610,3345653,191 -15243716,3345844,177 -15243919,3346021,182 -15244031,3346203,235 -15244679,3346438,115 -15246180,3346553,205 -15246529,3346758,205 -15248378,3346963,306 -15249916,3347269,166 -15250606,3347435,254 -15251272,3347689,170 -15252080,3347859,170 -15252285,3348029,200 -15252392,3348229,253 -15253121,3348482,144 -15254057,3348626,176 -15254304,3348802,198 -15255375,3349000,213 -15256481,3349213,132 -15256600,3349345,177 -15256626,3349522,119 -15256877,3349641,239 -15257094,3349880,172 -15257850,3350052,162 -15258755,3350214,206 -15258848,3350420,212 -15260310,3350632,254 -15260330,3350886,202 -15261223,3351088,265 -15261682,3351353,185 -15261839,3351538,165 -15261879,3351703,115 -15262178,3351818,124 -15263190,3351942,175 -15263538,3352117,145 -15263600,3352262,160 -15263606,3352422,256 -15263861,3352678,157 -15264362,3352835,131 -15264474,3352966,172 -15265029,3353138,156 -15265267,3353294,136 -15265673,3353430,179 -15266224,3353609,158 -15266342,3353767,182 -15266531,3353949,217 -15268136,3354166,122 -15268960,3354288,205 -15269039,3354493,151 -15470276,3354644,221 -15470294,3354865,185 -15470880,3355050,171 -15470887,3355221,142 -15471538,3355363,119 -15471862,3355482,126 -15472431,3355608,283 -15472486,3355891,170 -15473241,3356061,175 -15474047,3356236,160 -15475103,3356396,145 -15475287,3356541,273 -15475328,3356814,180 -15475517,3356994,239 -15475560,3357233,169 -15475896,3357402,142 -15476426,3357544,261 -15477488,3357805,129 -15477833,3357934,229 -15478350,3358163,198 -15478929,3358361,170 -15480198,3358531,120 -15481840,3358651,110 -15481946,3358761,289 -15481992,3359050,175 -15482377,3359225,206 -15482629,3359431,276 -15483632,3359707,182 -15483878,3359889,193 -15483894,3360082,237 -15484022,3360319,170 -15484484,3360489,118 -15484528,3360607,168 -15484732,3360775,131 -15485331,3360906,212 -15486029,3361118,154 -15486850,3361272,143 -15488046,3361415,206 -15488505,3361621,199 -15489511,3361820,158 -15489670,3361978,307 -15490153,3362285,220 -15491296,3362505,133 -15491684,3362638,182 -15492069,3362820,171 -15492817,3362991,137 -15494303,3363128,225 -15495643,3363353,279 -15496378,3363632,213 -15498356,3363845,235 -15498653,3364080,135 -15499273,3364215,134 -15500140,3364349,208 -15500591,3364557,120 -15501455,3364677,262 -15501458,3364939,173 -15501813,3365112,281 -15501900,3365393,179 -15503021,3365572,153 -15503923,3365725,159 -15504167,3365884,169 -15505025,3366053,148 -15505516,3366201,189 -15505601,3366390,228 -15506036,3366618,151 -15506267,3366769,138 -15507149,3366907,182 -15508123,3367089,134 -15509611,3367223,206 -15511814,3367429,159 -15512023,3367588,148 -15512897,3367736,156 -15513863,3367892,160 -15514366,3368052,145 -15514542,3368197,202 -15514889,3368399,161 -15516554,3368560,166 -15517826,3368726,170 -15518512,3368896,239 -15519085,3369135,162 -15519758,3369297,209 -15519808,3369506,176 -15520154,3369682,225 -15522085,3369907,122 -15522128,3370029,118 -15522257,3370147,263 -15523389,3370410,149 -15523995,3370559,200 -15524265,3370759,136 -15524605,3370895,249 -15525138,3371144,124 -15525205,3371268,179 -15525700,3371447,141 -15526155,3371588,206 -15526165,3371794,125 -15526392,3371919,282 -15526403,3372201,169 -15527950,3372370,155 -15528502,3372525,154 -15528795,3372679,134 -15529147,3372813,141 -15529771,3372954,182 -15530666,3373136,158 -15531093,3373294,158 -15531646,3373452,165 -15728767,3373617,187 -15729195,3373804,137 -15729224,3373941,150 -15730566,3374091,185 -15730929,3374276,175 -15733699,3374451,209 -15734176,3374660,185 -15735827,3374845,155 -15735853,3375000,149 -15736372,3375149,233 -15736751,3375382,127 -15737245,3375509,269 -15737641,3375778,160 -15737861,3375938,203 -15737864,3376141,145 -15737973,3376286,120 -15738226,3376406,170 -15738295,3376576,229 -15738444,3376805,137 -15738725,3376942,178 -15739177,3377120,136 -15739427,3377256,180 -15739489,3377436,174 -15740888,3377610,148 -15741466,3377758,169 -15742881,3377927,258 -15743563,3378185,148 -15743573,3378333,139 -15744297,3378472,127 -15745016,3378599,131 -15745845,3378730,155 -15747627,3378885,151 -15747946,3379036,242 -15748082,3379278,166 -15748514,3379444,140 -15748988,3379584,55 -15751241,3379639,181 -15751689,3379820,175 -15752585,3379995,178 -15752648,3380173,150 -15753050,3380323,194 -15753520,3380517,196 -15753741,3380713,211 -15753857,3380924,173 -15754717,3381097,173 -15755347,3381270,189 -15756234,3381459,175 -15757964,3381634,175 -15758254,3381809,148 -15758876,3381957,219 -15759205,3382176,155 -15759312,3382331,165 -15759382,3382496,136 -15759705,3382632,162 -15760331,3382794,200 -15760744,3382994,179 -15761158,3383173,136 -15761164,3383309,168 -15761839,3383477,224 -15762017,3383701,151 -15762479,3383852,142 -15762633,3383994,161 -15764008,3384155,249 -15764478,3384404,175 -15764731,3384579,221 -15765211,3384800,150 -15766044,3384950,151 -15766330,3385101,126 -15766469,3385227,147 -15767999,3385374,120 -15768763,3385494,192 -15768809,3385686,156 -15769187,3385842,136 -15769538,3385978,160 -15770149,3386138,55 -15771492,3386193,169 -15772500,3386362,159 -15772836,3386521,150 -15773006,3386671,238 -15773265,3386909,146 -15773778,3387055,141 -15774841,3387196,120 -15775467,3387316,201 -15776968,3387517,160 -15777265,3387677,147 -15777687,3387824,168 -15778289,3387992,132 -15778380,3388124,236 -15778428,3388360,248 -15779980,3388608,140 -15780769,3388748,120 -15782223,3388868,146 -15782313,3389014,120 -15782823,3389134,196 -15782887,3389330,137 -15783511,3389467,131 -15783783,3389598,145 -15784572,3389743,145 -15784752,3389888,155 -15784930,3390043,120 -15784952,3390163,120 -15785186,3390283,120 -15785585,3390403,214 -15785657,3390617,243 -15785713,3390860,151 -15787459,3391011,166 -15787902,3391177,175 -15789008,3391352,221 -15789113,3391573,117 -15789342,3391690,225 -15789755,3391915,146 -15790082,3392061,201 -15790688,3392262,115 -15790902,3392377,268 -15791534,3392645,144 -15791644,3392789,120 -15791684,3392909,225 -15791721,3393134,169 -15791957,3393303,170 -15792051,3393473,120 -15792194,3393593,145 -15792631,3393738,141 -15793568,3393879,156 -15793771,3394035,273 -15991556,3394308,128 -15991585,3394436,132 -15991599,3394568,133 -15991884,3394701,188 -15992425,3394889,166 -15992461,3395055,130 -15992485,3395185,262 -15993304,3395447,229 -15993747,3395676,148 -15994385,3395824,278 -15994651,3396102,136 -15994779,3396238,192 -15996259,3396430,155 -15996413,3396585,268 -15997857,3396853,120 -15998502,3396973,174 -15998731,3397147,154 -15998914,3397301,136 -15998994,3397437,125 -16001075,3397562,155 -16001107,3397717,273 -16001174,3397990,217 -16001409,3398207,198 -16002134,3398405,183 -16004833,3398588,161 -16005047,3398749,120 -16005140,3398869,189 -16006528,3399058,166 -16006753,3399224,224 -16006813,3399448,160 -16007719,3399608,147 -16008272,3399755,179 -16008685,3399934,205 -16008979,3400139,272 -16009002,3400411,231 -16009288,3400642,185 -16010757,3400827,136 -16011005,3400963,241 -16011499,3401204,166 -16011796,3401370,187 -16012339,3401557,164 -16012693,3401721,210 -16012700,3401931,238 -16012768,3402169,256 -16013118,3402425,221 -16013378,3402646,162 -16015209,3402808,287 -16015316,3403095,140 -16015351,3403235,150 -16015373,3403385,178 -16016201,3403563,183 -16016477,3403746,115 -16018066,3403861,235 -16018108,3404096,192 -16018692,3404288,162 -16018914,3404450,174 -16020426,3404624,158 -16021030,3404782,133 -16022094,3404915,159 -16022220,3405074,160 -16022366,3405234,191 -16023349,3405425,170 -16023865,3405595,136 -16025457,3405731,145 -16027145,3405876,134 -16027850,3406010,139 -16027882,3406149,153 -16028769,3406302,144 -16028774,3406446,164 -16030124,3406610,173 -16031572,3406783,159 -16031731,3406942,239 -16032404,3407181,200 -16033066,3407381,161 -16035009,3407542,170 -16036196,3407712,253 -16036737,3407965,129 -16037167,3408094,150 -16037193,3408244,192 -16037605,3408436,193 -16037674,3408629,170 -16037858,3408799,198 -16037982,3408997,142 -16039292,3409139,268 -16041031,3409407,218 -16041687,3409625,131 -16041748,3409756,285 -16041877,3410041,151 -16042725,3410192,131 -16043408,3410323,150 -16043590,3410473,188 -16044002,3410661,136 -16044082,3410797,264 -16044641,3411061,207 -16046587,3411268,230 -16047181,3411498,266 -16047322,3411764,236 -16047353,3412000,244 -16047518,3412244,123 -16048450,3412367,146 -16049147,3412513,241 -16049879,3412754,189 -16050644,3412943,166 -16050791,3413109,170 -16051256,3413279,248 -16051732,3413527,265 -16052570,3413792,120 -16052705,3413912,173 -16052845,3414085,258 -16053669,3414343,130 -16053736,3414473,144 -16053830,3414617,205 -16054609,3414822,120 -16055346,3414942,144 -16055595,3415086,175 -16253203,3415261,241 -16253560,3415502,278 -16253746,3415780,155 -16253998,3415935,229 -16254236,3416164,182 -16255934,3416346,147 -16255952,3416493,277 -16256243,3416770,155 -16256323,3416925,175 -16256490,3417100,195 -16256833,3417295,217 -16256900,3417512,144 -16257079,3417656,163 -16258375,3417819,143 -16258644,3417962,166 -16259223,3418128,127 -16259687,3418255,283 -16260325,3418538,155 -16260499,3418693,238 -16260831,3418931,120 -16261765,3419051,208 -16262209,3419259,182 -16263059,3419441,130 -16264136,3419571,215 -16264923,3419786,138 -16265051,3419924,152 -16265128,3420076,202 -16265364,3420278,195 -16265534,3420473,133 -16266102,3420606,213 -16266579,3420819,158 -16266717,3420977,249 -16268622,3421226,225 -16268799,3421451,238 -16270075,3421689,150 -16270176,3421839,55 -16270765,3421894,165 -16270893,3422059,169 -16271149,3422228,189 -16271511,3422417,148 -16271987,3422565,154 -16271999,3422719,146 -16272063,3422865,194 -16273239,3423059,136 -16273507,3423195,127 -16273773,3423322,167 -16274143,3423489,132 -16274607,3423621,134 -16275246,3423755,151 -16276425,3423906,119 -16276549,3424025,191 -16277290,3424216,132 -16278186,3424348,164 -16279041,3424512,245 -16279249,3424757,175 -16279282,3424932,170 -16279921,3425102,147 -16281295,3425249,124 -16282110,3425373,199 -16282346,3425572,136 -16282516,3425708,151 -16283291,3425859,185 -16284399,3426044,210 -16284514,3426254,253 -16284538,3426507,147 -16284556,3426654,147 -16285978,3426801,127 -16286841,3426928,227 -16286962,3427155,175 -16288796,3427330,249 -16289263,3427579,127 -16289413,3427706,218 -16289738,3427924,166 -16290090,3428090,166 -16290803,3428256,152 -16291152,3428408,153 -16291271,3428561,202 -16291791,3428763,224 -16292181,3428987,166 -16293133,3429153,166 -16293816,3429319,175 -16293949,3429494,216 -16294580,3429710,203 -16295007,3429913,265 -16296291,3430178,245 -16296400,3430423,155 -16296414,3430578,168 -16296586,3430746,203 -16297069,3430949,169 -16298326,3431118,127 -16298739,3431245,219 -16299417,3431464,304 -16301074,3431768,127 -16301121,3431895,212 -16302081,3432107,149 -16302225,3432256,154 -16302728,3432410,136 -16302999,3432546,160 -16303736,3432706,138 -16304492,3432844,221 -16306117,3433065,217 -16306348,3433282,168 -16306365,3433450,175 -16306449,3433625,253 -16307113,3433878,161 -16307298,3434039,210 -16308054,3434249,188 -16308159,3434437,127 -16308959,3434564,150 -16308962,3434714,140 -16308980,3434854,220 -16309068,3435074,166 -16309119,3435240,173 -16309128,3435413,127 -16309370,3435540,136 -16310184,3435676,160 -16310393,3435836,163 -16311547,3435999,165 -16312245,3436164,203 -16312337,3436367,199 -16312579,3436566,177 -16312680,3436743,118 -16312842,3436861,158 -16313765,3437019,166 -16314373,3437185,189 -16314388,3437374,138 -16314498,3437512,193 -16314806,3437705,163 -16314970,3437868,128 -16316371,3437996,198 -16316415,3438194,156 -16317231,3438350,162 -16318044,3438512,164 -16318120,3438676,174 -16318303,3438850,277 -16515090,3439127,289 -16515486,3439416,117 -16515533,3439533,143 -16516679,3439676,172 -16517024,3439848,143 -16517239,3439991,149 -16517592,3440140,156 -16517622,3440296,211 -16517761,3440507,173 -16519142,3440680,168 -16519357,3440848,162 -16519558,3441010,138 -16520009,3441148,187 -16520628,3441335,151 -16520711,3441486,173 -16521108,3441659,186 -16521488,3441845,175 -16521680,3442020,208 -16522239,3442228,118 -16522585,3442346,179 -16522628,3442525,213 -16522774,3442738,140 -16523033,3442878,207 -16523200,3443085,138 -16523932,3443223,196 -16524069,3443419,219 -16524607,3443638,120 -16525218,3443758,179 -16525908,3443937,164 -16526893,3444101,179 -16527168,3444280,159 -16528008,3444439,216 -16528792,3444655,167 -16528870,3444822,158 -16530835,3444980,201 -16531371,3445181,283 -16532579,3445464,161 -16532633,3445625,131 -16532831,3445756,247 -16533743,3446003,192 -16534249,3446195,201 -16534300,3446396,167 -16534460,3446563,215 -16534996,3446778,249 -16535696,3447027,141 -16536270,3447168,143 -16537850,3447311,298 -16538404,3447609,137 -16538406,3447746,136 -16538425,3447882,136 -16539672,3448018,212 -16540056,3448230,179 -16540270,3448409,153 -16540345,3448562,158 -16541758,3448720,167 -16542769,3448887,145 -16543168,3449032,132 -16543671,3449164,139 -16545046,3449303,169 -16545254,3449472,169 -16546059,3449641,192 -16547047,3449833,132 -16548649,3449965,162 -16548761,3450127,138 -16550807,3450265,303 -16551550,3450568,153 -16551824,3450721,190 -16551876,3450911,207 -16552507,3451118,134 -16553068,3451252,164 -16553187,3451416,159 -16554311,3451575,136 -16554746,3451711,161 -16555950,3451872,158 -16556001,3452030,207 -16556350,3452237,159 -16556586,3452396,195 -16558145,3452591,138 -16558512,3452729,239 -16558612,3452968,203 -16559375,3453171,160 -16559978,3453331,122 -16560044,3453453,152 -16560324,3453605,216 -16561382,3453821,187 -16561816,3454008,198 -16563105,3454206,235 -16564797,3454441,160 -16564958,3454601,179 -16566068,3454780,175 -16566423,3454955,157 -16567524,3455112,147 -16568162,3455259,138 -16569586,3455397,154 -16569590,3455551,168 -16569817,3455719,206 -16570045,3455925,150 -16570391,3456075,244 -16571286,3456319,204 -16571315,3456523,179 -16571466,3456702,195 -16571733,3456897,215 -16572806,3457112,173 -16572818,3457285,245 -16572889,3457530,172 -16572923,3457702,148 -16572991,3457850,133 -16573244,3457983,194 -16573783,3458177,137 -16574610,3458314,233 -16574872,3458547,120 -16575929,3458667,141 -16576850,3458808,136 -16576973,3458944,154 -16577832,3459098,217 -16578119,3459315,221 -16578734,3459536,166 -16578743,3459702,154 -16579319,3459856,218 -16579579,3460074,170 -16580215,3460244,175 -16580522,3460419,278 diff --git a/awx/lib/site-packages/netaddr/eui/oui.txt b/awx/lib/site-packages/netaddr/eui/oui.txt deleted file mode 100644 index 6d7a0f9657..0000000000 --- a/awx/lib/site-packages/netaddr/eui/oui.txt +++ /dev/null @@ -1,129811 +0,0 @@ - Generated: Tue, 31 Mar 2015 05:00:03 -0400 - - OUI/MA-L Organization - company_id Organization - Address - - - 00-00-00 (hex) XEROX CORPORATION - 000000 (base 16) XEROX CORPORATION - M/S 105-50C - 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-01 (hex) XEROX CORPORATION - 000001 (base 16) XEROX CORPORATION - ZEROX SYSTEMS INSTITUTE - M/S 105-50C 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-02 (hex) XEROX CORPORATION - 000002 (base 16) XEROX CORPORATION - XEROX SYSTEMS INSTITUTE - M/S 105-50C 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-03 (hex) XEROX CORPORATION - 000003 (base 16) XEROX CORPORATION - ZEROX SYSTEMS INSTITUTE - M/S 105-50CEW AVENUE 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-04 (hex) XEROX CORPORATION - 000004 (base 16) XEROX CORPORATION - OFFICE SYSTEMS DIVISION - M/S 105-50C 800 PHILLIPS ROAD4 - WEBSTER NY 14580 - UNITED STATES - - 00-00-05 (hex) XEROX CORPORATION - 000005 (base 16) XEROX CORPORATION - OFFICE SYSTEMS DIVISION - M/S 105-50C 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-06 (hex) XEROX CORPORATION - 000006 (base 16) XEROX CORPORATION - OFFICE SYSTEMS DIVISION - M/S 105-50C 800 PHILLIPS ROAD4 - WEBSTER NY 14580 - UNITED STATES - - 00-00-07 (hex) XEROX CORPORATION - 000007 (base 16) XEROX CORPORATION - OFFICE SYSTEMS DIVISION - M/S 105-50C 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-08 (hex) XEROX CORPORATION - 000008 (base 16) XEROX CORPORATION - OFFICE SYSTEMS DIVISION - M/S/ 105-50C 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-09 (hex) XEROX CORPORATION - 000009 (base 16) XEROX CORPORATION - 1350 JEFFERSON ROAD - ROCHESTER NY 14623 - UNITED STATES - - 00-00-0A (hex) OMRON TATEISI ELECTRONICS CO. - 00000A (base 16) OMRON TATEISI ELECTRONICS CO. - SECTION NFF, SYSTEM R&D LABS. - RESEARCH & TECH. ASSESSMNT DIV SHIMOKAII - KYOTO 617 - JAPAN - - 00-00-0B (hex) MATRIX CORPORATION - 00000B (base 16) MATRIX CORPORATION - 1203 NEW HOPE ROAD - RALEIGH NORTH CAROLINA 276 - UNITED STATES - - 00-00-0C (hex) CISCO SYSTEMS, INC. - 00000C (base 16) CISCO SYSTEMS, INC. - 170 WEST TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-00-0D (hex) FIBRONICS LTD. - 00000D (base 16) FIBRONICS LTD. - MATAM TECHNOLOGY CENTER - HAIFA 31905 - ISRAEL - - 00-00-0E (hex) FUJITSU LIMITED - 00000E (base 16) FUJITSU LIMITED - Musashi-kosugi Tower Place Bldg., - Kosugi-cho 1-chome,Nakahara-ku - KAWASAKI 211 Kanagawa - JAPAN - - 00-00-0F (hex) NEXT, INC. - 00000F (base 16) NEXT, INC. - 3475 DEER CREEK ROAD - PALO ALTO CA 94304 - UNITED STATES - - 00-00-10 (hex) SYTEK INC. - 000010 (base 16) SYTEK INC. - 1225 CHARLESTON ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-00-11 (hex) NORMEREL SYSTEMES - 000011 (base 16) NORMEREL SYSTEMES - 58 RUE POTTIER - 78150 LE CHESNAY - FRANCE - - 00-00-12 (hex) INFORMATION TECHNOLOGY LIMITED - 000012 (base 16) INFORMATION TECHNOLOGY LIMITED - MAYLANDS AVE. HEMEL HEMPSTEAD - HERTS ENGLAND - UNITED KINGDOM - - 00-00-13 (hex) CAMEX - 000013 (base 16) CAMEX - 75 KNEELAND STREET - BOSTON MA 02111 - UNITED STATES - - 00-00-14 (hex) NETRONIX - 000014 (base 16) NETRONIX - 1372 MCDOWELL BLVD. - PETULAMA CA 94952 - UNITED STATES - - 00-00-15 (hex) DATAPOINT CORPORATION - 000015 (base 16) DATAPOINT CORPORATION - 9725 DATAPOINT DRIVE - MS S-37 - SAN ANTONIO TX 78284 - UNITED STATES - - 00-00-16 (hex) DU PONT PIXEL SYSTEMS . - 000016 (base 16) DU PONT PIXEL SYSTEMS . - MEADLAKE PLACE - THORPE LEA ROAD EGHAM, SURREY TW20 8HE - ENGLAND - UNITED KINGDOM - - 00-00-17 (hex) Oracle - 000017 (base 16) Oracle - 4200 Network Circle - Santa Clara CA 95054 - UNITED STATES - - 00-00-18 (hex) WEBSTER COMPUTER CORPORATION - 000018 (base 16) WEBSTER COMPUTER CORPORATION - 16040 REDWOOD LODGE ROAD - LOS GATOS CA 95033-9260 - UNITED STATES - - 00-00-19 (hex) APPLIED DYNAMICS INTERNATIONAL - 000019 (base 16) APPLIED DYNAMICS INTERNATIONAL - 3800 STONE SCHOOL ROAD - ANN ARBOR MI 48104-2499 - UNITED STATES - - 00-00-1A (hex) ADVANCED MICRO DEVICES - 00001A (base 16) ADVANCED MICRO DEVICES - P.O. BOX 3453 - M/S 26 - SUNNYVALE CA 94088 - UNITED STATES - - 00-00-1B (hex) NOVELL INC. - 00001B (base 16) NOVELL INC. - 122 EAST 1700 SOUTH - M/S: E-12-1 - PROVO UT 84606 - UNITED STATES - - 00-00-1C (hex) BELL TECHNOLOGIES - 00001C (base 16) BELL TECHNOLOGIES - 330 WARREN AVENUE - FREMONT CA 94539 - UNITED STATES - - 00-00-1D (hex) CABLETRON SYSTEMS, INC. - 00001D (base 16) CABLETRON SYSTEMS, INC. - 35 INDUSTRIAL WAY - P.O. BOX 5005 - ROCHESTER NH 03867 - UNITED STATES - - 00-00-1E (hex) TELSIST INDUSTRIA ELECTRONICA - 00001E (base 16) TELSIST INDUSTRIA ELECTRONICA - RUA VILHENA DE MORAES, 380 - BARRA DA TIJUCA RIO DE JANEIRO, RJ CEP 2 - BRAZIL - - 00-00-1F (hex) Telco Systems, Inc. - 00001F (base 16) Telco Systems, Inc. - 15 Berkshire Road - Mansfield MA 02048 - UNITED STATES - - 00-00-20 (hex) DATAINDUSTRIER DIAB AB - 000020 (base 16) DATAINDUSTRIER DIAB AB - BOX 2029 - S-183 02 TABY - SWEDEN - - 00-00-21 (hex) SUREMAN COMP. & COMMUN. CORP. - 000021 (base 16) SUREMAN COMP. & COMMUN. CORP. - 10F-5 NO. 7, SEC. 3 - HSIN SHENG N. RD., - TAIPEI TAIWAN, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-00-22 (hex) VISUAL TECHNOLOGY INC. - 000022 (base 16) VISUAL TECHNOLOGY INC. - 1703 MIDDLESEX STREET - LOWELL MA 01851 - UNITED STATES - - 00-00-23 (hex) ABB INDUSTRIAL SYSTEMS AB - 000023 (base 16) ABB INDUSTRIAL SYSTEMS AB - DEPT. SEISY/LKSB - S-721 67 VASTERAS - SWEDEN - - 00-00-24 (hex) CONNECT AS - 000024 (base 16) CONNECT AS - HOERKAER 7-9 - DK 2730 HERLEV - DENMARK - - 00-00-25 (hex) RAMTEK CORP. - 000025 (base 16) RAMTEK CORP. - 810 W. MAUDE AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-00-26 (hex) SHA-KEN CO., LTD. - 000026 (base 16) SHA-KEN CO., LTD. - MINAMI-OTSUKA - 2-26-13, TOSHIMA-KU - TOKYO - JAPAN - - 00-00-27 (hex) JAPAN RADIO COMPANY - 000027 (base 16) JAPAN RADIO COMPANY - LABORATORY - 5-1-1 SHIMORENJAKU MITAKA-SHI, TOKYO - JAPAN - - 00-00-28 (hex) PRODIGY SYSTEMS CORPORATION - 000028 (base 16) PRODIGY SYSTEMS CORPORATION - 2601 CASEY DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-00-29 (hex) IMC NETWORKS CORP. - 000029 (base 16) IMC NETWORKS CORP. - 16931 MILLIKEN AVE. - IRVINE CA 92714-5013 - UNITED STATES - - 00-00-2A (hex) TRW - SEDD/INP - 00002A (base 16) TRW - SEDD/INP - 1800 GLENN CURTISS STREET - M/S DH6/2826 - CARSON CA 90746 - UNITED STATES - - 00-00-2B (hex) CRISP AUTOMATION, INC - 00002B (base 16) CRISP AUTOMATION, INC - 5160 BLAZER PARKWAY - DUBLIN OH 43017 - UNITED STATES - - 00-00-2C (hex) AUTOTOTE LIMITED - 00002C (base 16) AUTOTOTE LIMITED - 100 BELLEVUE ROAD - NEWARK DELAWARE 19714 - UNITED STATES - - 00-00-2D (hex) CHROMATICS INC - 00002D (base 16) CHROMATICS INC - 2558 MOUNTAIN INDUSTRIAL BLVD - TUCKER GA 30084 - UNITED STATES - - 00-00-2E (hex) SOCIETE EVIRA - 00002E (base 16) SOCIETE EVIRA - ZONE PORTUAIRE DE BREGAILLON - 83500 LA SEYNE SUR MER - FRANCE - - 00-00-2F (hex) TIMEPLEX INC. - 00002F (base 16) TIMEPLEX INC. - 530 CHESTNUT RIDGE ROAD - WOODCLIFF LAKE NJ 07675 - UNITED STATES - - 00-00-30 (hex) VG LABORATORY SYSTEMS LTD - 000030 (base 16) VG LABORATORY SYSTEMS LTD - TRIBUNE AVENUE - ALTRINCHAM, MANCHESTER, WA14 5TP - ENGLAND - UNITED KINGDOM - - 00-00-31 (hex) QPSX COMMUNICATIONS PTY LTD - 000031 (base 16) QPSX COMMUNICATIONS PTY LTD - 33 RICHARDSON STREET - WEST PERTH 6005 - WESTERN - AUSTRALIA - - 00-00-32 (hex) Marconi plc - 000032 (base 16) Marconi plc - 28 ELSTREE WAY, BOREHAMWOOD - HERTFORDSHIRE WD6 1RX - UNITED KINGDOM - UNITED KINGDOM - - 00-00-33 (hex) EGAN MACHINERY COMPANY - 000033 (base 16) EGAN MACHINERY COMPANY - SOUTH ADAMSVILLE ROAD - SOMMERVILLE NJ 08876 - UNITED STATES - - 00-00-34 (hex) NETWORK RESOURCES CORPORATION - 000034 (base 16) NETWORK RESOURCES CORPORATION - 61 EAST DAGGETT DRIVE - SAN JOSE CA 95134 - UNITED STATES - - 00-00-35 (hex) SPECTRAGRAPHICS CORPORATION - 000035 (base 16) SPECTRAGRAPHICS CORPORATION - OR - LAN MANUFACTURING ENGINEER 9707 WAPLES S - SAN DIEGO CA 92121 - UNITED STATES - - 00-00-36 (hex) ATARI CORPORATION - 000036 (base 16) ATARI CORPORATION - 1196 BORREGAS AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-00-37 (hex) OXFORD METRICS LIMITED - 000037 (base 16) OXFORD METRICS LIMITED - UNIT 8, 7 WEST WAY, - BOTLEY,OXFORD, OX2 OJB - UNITED KINGDOM - UNITED KINGDOM - - 00-00-38 (hex) CSS LABS - 000038 (base 16) CSS LABS - 2134 SOUTH RIPCHEY - SANTA ANA CA 92705 - UNITED STATES - - 00-00-39 (hex) TOSHIBA CORPORATION - 000039 (base 16) TOSHIBA CORPORATION - COMPUTER DIVISION - 1-1-1 SHIBAURA, MINATO-KU - TOKYO 105 - JAPAN - - 00-00-3A (hex) CHYRON CORPORATION - 00003A (base 16) CHYRON CORPORATION - 265 SPAGNOLI ROAD - MELVILLE NY 11747 - UNITED STATES - - 00-00-3B (hex) i Controls, Inc. - 00003B (base 16) i Controls, Inc. - 12F Doonsan building, 105-7 - Nonhyun-dong, Gangnam-gu Seoul - KOREA 135-714 - KOREA, REPUBLIC OF - - 00-00-3C (hex) AUSPEX SYSTEMS INC. - 00003C (base 16) AUSPEX SYSTEMS INC. - 5200 GREAT AMERICA PKWY - SANTA CLARA CA 95054 - UNITED STATES - - 00-00-3D (hex) UNISYS - 00003D (base 16) UNISYS - MS8-010 - P.O. BOX 6685 - SAN JOSE CA 95150-6685 - UNITED STATES - - 00-00-3E (hex) SIMPACT - 00003E (base 16) SIMPACT - 9210 SKY PARK COURT - SAN DIEGO CA 92123 - UNITED STATES - - 00-00-3F (hex) SYNTREX, INC. - 00003F (base 16) SYNTREX, INC. - 246 INDUSTRIAL WAY WEST - EATONTOWN NJ 07724 - UNITED STATES - - 00-00-40 (hex) APPLICON, INC. - 000040 (base 16) APPLICON, INC. - 4251 PLYMOUTH RD 48015 - PO BOX 986 - ANN ARBOR MI 48106-0986 - UNITED STATES - - 00-00-41 (hex) ICE CORPORATION - 000041 (base 16) ICE CORPORATION - 17945 SKYPARK CIRCLE - SUITE E - IRVINE CA 92714 - UNITED STATES - - 00-00-42 (hex) METIER MANAGEMENT SYSTEMS LTD. - 000042 (base 16) METIER MANAGEMENT SYSTEMS LTD. - 3 FOUNDATION STREET - IPSWICH SUFFOLK IP4 1BG - ENGLAND - UNITED KINGDOM - - 00-00-43 (hex) MICRO TECHNOLOGY - 000043 (base 16) MICRO TECHNOLOGY - 4905 EAST LAPALMA - ANAHEIM CA 92807 - UNITED STATES - - 00-00-44 (hex) CASTELLE CORPORATION - 000044 (base 16) CASTELLE CORPORATION - 3255-3 SCOTT BOULEVARD - SANTA CLARA CA 95054 - UNITED STATES - - 00-00-45 (hex) FORD AEROSPACE & COMM. CORP. - 000045 (base 16) FORD AEROSPACE & COMM. CORP. - COLORADO SPRINGS OPERATION - 10440 STATE HIGHWAY 83 - COLORADO SPRINGS CO 80908 - UNITED STATES - - 00-00-46 (hex) OLIVETTI NORTH AMERICA - 000046 (base 16) OLIVETTI NORTH AMERICA - E 22425 APPLEWAY - LIBERTY LAKE WA 99019 - UNITED STATES - - 00-00-47 (hex) NICOLET INSTRUMENTS CORP. - 000047 (base 16) NICOLET INSTRUMENTS CORP. - 5225 VERONA ROAD - MADISON WI 53711 - UNITED STATES - - 00-00-48 (hex) SEIKO EPSON CORPORATION - 000048 (base 16) SEIKO EPSON CORPORATION - 80 HIROOKA SHIOJIRI-CITY - NAGANO-KEN - JAPAN 399-07 - JAPAN - - 00-00-49 (hex) APRICOT COMPUTERS, LTD - 000049 (base 16) APRICOT COMPUTERS, LTD - 90 VINCENT DRIVE - EDGBASTON, BIRMINGHAM B152SP - ENGLAND - UNITED KINGDOM - - 00-00-4A (hex) ADC CODENOLL TECHNOLOGY CORP. - 00004A (base 16) ADC CODENOLL TECHNOLOGY CORP. - 200 CORPORATE BLVD. SO. - YONKERS NY 10701 - UNITED STATES - - 00-00-4B (hex) ICL DATA OY - 00004B (base 16) ICL DATA OY - KUTOMOTIE 16-18 - 00380 HELSINKI P.O. BOX 458 SF-00101 HE - FINLAND - - 00-00-4C (hex) NEC CORPORATION - 00004C (base 16) NEC CORPORATION - 7-1 SHIBA 5-CHOME - MINATO-KU - TOKYO 108-01 - JAPAN - - 00-00-4D (hex) DCI CORPORATION - 00004D (base 16) DCI CORPORATION - 64J PRINCETON-HIGHTSTOWN RD - #121 - PRINCETON JUNCTION NJ 08550 - UNITED STATES - - 00-00-4E (hex) AMPEX CORPORATION - 00004E (base 16) AMPEX CORPORATION - 581 CONFERENCE PLACE - GOLDEN CO 80401 - UNITED STATES - - 00-00-4F (hex) LOGICRAFT, INC. - 00004F (base 16) LOGICRAFT, INC. - 22 COTTON ROAD - NASHUA NH 03063 - UNITED STATES - - 00-00-50 (hex) RADISYS CORPORATION - 000050 (base 16) RADISYS CORPORATION - 15025 S.W. KOLL PARKWAY - BEAVERTON OR 97006-6056 - UNITED STATES - - 00-00-51 (hex) HOB ELECTRONIC GMBH & CO. KG - 000051 (base 16) HOB ELECTRONIC GMBH & CO. KG - BRANDSSTATTER-STR.2-10 - D-8502 ZIRNDORF - GERMANY - - 00-00-52 (hex) Intrusion.com, Inc. - 000052 (base 16) Intrusion.com, Inc. - 1101 E. ARAPAHO ROAD - RICHARDSON TX 75081 - - 00-00-53 (hex) COMPUCORP - 000053 (base 16) COMPUCORP - 2211 MICHIGAN AVENUE - SANTA MONICA CA 90404 - UNITED STATES - - 00-00-54 (hex) Schnieder Electric - 000054 (base 16) Schnieder Electric - 35 rue Joseph Monier - 92500 Rueil Malmaison - FRANCE - - 00-00-55 (hex) COMMISSARIAT A L`ENERGIE ATOM. - 000055 (base 16) COMMISSARIAT A L`ENERGIE ATOM. - 31, RUE DE LA FEDERATION - PARIS 75015 - FRANCE - - 00-00-56 (hex) DR. B. STRUCK - 000056 (base 16) DR. B. STRUCK - POB 1147 BAECKERBARG 6 - D-2000 TANGSTEDT/HAMBURG - W-GERMANY - GERMANY - - 00-00-57 (hex) SCITEX CORPORATION LTD. - 000057 (base 16) SCITEX CORPORATION LTD. - P.O. BOX 330 - 46103 HERZLIA B - ISRAEL - - 00-00-58 (hex) RACORE COMPUTER PRODUCTS INC. - 000058 (base 16) RACORE COMPUTER PRODUCTS INC. - 2355 SOUTH 1070 WEST - SALT LAKE CITY UT 84119 - UNITED STATES - - 00-00-59 (hex) HELLIGE GMBH - 000059 (base 16) HELLIGE GMBH - E-SW - HEINRICH-VON-STEFAN-STR.4 D-7800 FREIBUR - WEST - GERMANY - - 00-00-5A (hex) SysKonnect GmbH - 00005A (base 16) SysKonnect GmbH - SIEMENSSTRAßE 23 - 76275 ETTLINGEN - GERMANY - - 00-00-5B (hex) ELTEC ELEKTRONIK AG - 00005B (base 16) ELTEC ELEKTRONIK AG - Galileo-Galilei-Strasse 11 - POB 42 13 63 D-55071 MAINZ - GERMANY - - 00-00-5C (hex) TELEMATICS INTERNATIONAL INC. - 00005C (base 16) TELEMATICS INTERNATIONAL INC. - 1201 CYPRESS CREEK RD - FT. LAUDERDALE FL 33309 - UNITED STATES - - 00-00-5D (hex) CS TELECOM - 00005D (base 16) CS TELECOM - 4-16 AVENUE DU GENERAL LECLERC - BP 74 - 92263 FONTENAY AUX ROSES - FRANCE - - 00-00-5E (hex) ICANN, IANA Department - 00005E (base 16) ICANN, IANA Department - INTERNET ASS'NED NOS.AUTHORITY - 12025 Waterfront Drive, Suite 300 - Los Angeles CA 90094-2536 - UNITED STATES - - 00-00-5F (hex) SUMITOMO ELECTRIC IND., LTD. - 00005F (base 16) SUMITOMO ELECTRIC IND., LTD. - 1-1-3, SHIMAYA - KONOHANA-KU OSAKA - 554 - JAPAN - - 00-00-60 (hex) KONTRON ELEKTRONIK GMBH - 000060 (base 16) KONTRON ELEKTRONIK GMBH - OSKAR-VON-MILLER-STR. 1 - D-85385 ECHING - GERMANY - - 00-00-61 (hex) GATEWAY COMMUNICATIONS - 000061 (base 16) GATEWAY COMMUNICATIONS - 2941 ALTON AVENUE - IRVINE CA 92714 - UNITED STATES - - 00-00-62 (hex) BULL HN INFORMATION SYSTEMS - 000062 (base 16) BULL HN INFORMATION SYSTEMS - 300 CONCORD ROAD M/S 864A - BILLERICA MA 01821 - UNITED STATES - - 00-00-63 (hex) BARCO CONTROL ROOMS GMBH - 000063 (base 16) BARCO CONTROL ROOMS GMBH - An der Rossweid 5 - Karlsruhe D-76229 - GERMANY - - 00-00-64 (hex) Yokogawa Electric Corporation - 000064 (base 16) Yokogawa Electric Corporation - 2-9-32 Nakacho Musashino-shi - Tokyo - 180-8750 - JAPAN - - 00-00-65 (hex) Network General Corporation - 000065 (base 16) Network General Corporation - 178 E Tsaman Dr - San Jose CA 95134 - UNITED STATES - - 00-00-66 (hex) TALARIS SYSTEMS, INC. - 000066 (base 16) TALARIS SYSTEMS, INC. - 11339 SORRENTO VALLEY ROAD - SAN DIEGO CA 92121 - UNITED STATES - - 00-00-67 (hex) SOFT * RITE, INC. - 000067 (base 16) SOFT * RITE, INC. - 15392 ASSEMBLY LANE, UNIT A - HUNTINGTON BEACH CA 92649 - UNITED STATES - - 00-00-68 (hex) ROSEMOUNT CONTROLS - 000068 (base 16) ROSEMOUNT CONTROLS - 1300 E. LAMBERT ROAD - LA HABRA CA 90632 - UNITED STATES - - 00-00-69 (hex) CONCORD COMMUNICATIONS INC - 000069 (base 16) CONCORD COMMUNICATIONS INC - 753 FOREST STREET - MARLBOROUGH MA 01752 - UNITED STATES - - 00-00-6A (hex) COMPUTER CONSOLES INC. - 00006A (base 16) COMPUTER CONSOLES INC. - COMPUTER PRODUCTS DIVISION - 9801 MUIRLANDS BLVD. - IRVINE CA 92718 - UNITED STATES - - 00-00-6B (hex) SILICON GRAPHICS INC./MIPS - 00006B (base 16) SILICON GRAPHICS INC./MIPS - 2011 NORTH SHORELINE BLVD. - P.O. BOX 7311 - BLDG. #10 - MOUNTAIN VIEW CA 94039-7311 - UNITED STATES - - 00-00-6C (hex) PRIVATE - 00006C (base 16) - - 00-00-6D (hex) CRAY COMMUNICATIONS, LTD. - 00006D (base 16) CRAY COMMUNICATIONS, LTD. - P.O. BOX 254, CAXTON WAY - WATFORD BUSINESS PARK WATFORD HERTS WD1 - UNITED KINGDOM - UNITED KINGDOM - - 00-00-6E (hex) ARTISOFT, INC. - 00006E (base 16) ARTISOFT, INC. - 691 EAST RIVER ROAD - TUCSON AZ 85704 - UNITED STATES - - 00-00-6F (hex) Madge Ltd. - 00006F (base 16) Madge Ltd. - Madge House - Priors Way - Maindenhead Berkshire SL6 2HP - UNITED KINGDOM - - 00-00-70 (hex) HCL LIMITED - 000070 (base 16) HCL LIMITED - RESEARCH & DEVELOPMENT UNIT - 72, LUZ CHURCH ROAD MADRSA-600 004 - INDIA - - 00-00-71 (hex) ADRA SYSTEMS INC. - 000071 (base 16) ADRA SYSTEMS INC. - 59 TECHNOLOGY DRIVE - LOWELL MA 01851 - UNITED STATES - - 00-00-72 (hex) MINIWARE TECHNOLOGY - 000072 (base 16) MINIWARE TECHNOLOGY - BEEMDENSTRAAT 38 - 5004 CT WEERT (L) - THE - NETHERLANDS - - 00-00-73 (hex) SIECOR CORPORATION - 000073 (base 16) SIECOR CORPORATION - P.O. BOX 13625 - RESEARCH TRIANGLE PK NC 27709 - UNITED STATES - - 00-00-74 (hex) RICOH COMPANY LTD. - 000074 (base 16) RICOH COMPANY LTD. - 2446 TODA, ATSUGI CITY - KANAGAWA PREF., - 243 - JAPAN - - 00-00-75 (hex) Nortel Networks - 000075 (base 16) Nortel Networks - Global Operations Engineering - Dep 6800 Program Manager 8200 Dixie Road - Brampton ON l6T 5P6 Cana - CANADA - - 00-00-76 (hex) ABEKAS VIDEO SYSTEM - 000076 (base 16) ABEKAS VIDEO SYSTEM - 101 GALVESTON DRIVE - REDWOOD CITY CA 94063 - UNITED STATES - - 00-00-77 (hex) INTERPHASE CORPORATION - 000077 (base 16) INTERPHASE CORPORATION - 13800 SENLAC - DALLAS TX 75234 - UNITED STATES - - 00-00-78 (hex) LABTAM LIMITED - 000078 (base 16) LABTAM LIMITED - 43 MALCOLM ROAD P.O. BOX297 - BRAESIDE, VICTORIA 3195 - AUSTRALIA - - 00-00-79 (hex) NETWORTH INCORPORATED - 000079 (base 16) NETWORTH INCORPORATED - 8404 ESTERS BOULEVARD - IRVING TX 75063 - UNITED STATES - - 00-00-7A (hex) DANA COMPUTER INC. - 00007A (base 16) DANA COMPUTER INC. - 550 DEL REY AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-00-7B (hex) RESEARCH MACHINES - 00007B (base 16) RESEARCH MACHINES - P.O. BOX 75 - MILL STREET OXFORD OX2 0BW - ENGLAND - UNITED KINGDOM - - 00-00-7C (hex) AMPERE INCORPORATED - 00007C (base 16) AMPERE INCORPORATED - SHINJUKU ASAHI BLDG. - 5-20 7-CHOME NISHI-SHINJUKU SHINJUKU-K - TOKYO - JAPAN - - 00-00-7D (hex) Oracle Corporation - 00007D (base 16) Oracle Corporation - 17 Network Circle - Building 17, UMPK17-131 - Santa Clara CA 95025 - UNITED STATES - - 00-00-7E (hex) CLUSTRIX CORPORATION - 00007E (base 16) CLUSTRIX CORPORATION - 960 HAMLIN COURT - SUNNYVALE CA 94089 - UNITED STATES - - 00-00-7F (hex) LINOTYPE-HELL AG - 00007F (base 16) LINOTYPE-HELL AG - POSTFACH 56 60 - MERGENTHALER ALLEE 55-75 6236 ESCHBORN B - GERMANY - - 00-00-80 (hex) CRAY COMMUNICATIONS A/S - 000080 (base 16) CRAY COMMUNICATIONS A/S - SMEDEHOLM 12-14 - 2730 HERLEV - DENMARK - - 00-00-81 (hex) BAY NETWORKS - 000081 (base 16) BAY NETWORKS - 4401 GREAT AMERICAN PARKWAY - PO BOX 58185 M/S SC01-05 - SANTA CLARA CA 95052-8185 - UNITED STATES - - 00-00-82 (hex) LECTRA SYSTEMES SA - 000082 (base 16) LECTRA SYSTEMES SA - CHEMIN DE MARTICOT - RESEARCH DEPARTMENT 33610 CESTAS - FRANCE - - 00-00-83 (hex) TADPOLE TECHNOLOGY PLC - 000083 (base 16) TADPOLE TECHNOLOGY PLC - 137 DITTON WALK - CAMBRIDGE CB5 8FN - ENGLAND - UNITED KINGDOM - - 00-00-84 (hex) SUPERNET - 000084 (base 16) SUPERNET - 846 DEL REY AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-00-85 (hex) CANON INC. - 000085 (base 16) CANON INC. - DVTECH. DEV. CENTER DEPT.12 - 3-30-2, SHIMOMARUKO, OHTA-KU TOKYO 146 - JAPAN - - 00-00-86 (hex) MEGAHERTZ CORPORATION - 000086 (base 16) MEGAHERTZ CORPORATION - 605 NORTH--5600 WEST - SALT LAKE CITY UT 84116-3738 - UNITED STATES - - 00-00-87 (hex) HITACHI, LTD. - 000087 (base 16) HITACHI, LTD. - NETWORK ENGINEERING DIV. - HITACHI OMORI 2ND BLDG., 27-18 MINAMI OI - TOKYO 140 - JAPAN - - 00-00-88 (hex) Brocade Communications Systems, Inc. - 000088 (base 16) Brocade Communications Systems, Inc. - 1745 Technology Dr. - San Jose CA 95110 - UNITED STATES - - 00-00-89 (hex) CAYMAN SYSTEMS INC. - 000089 (base 16) CAYMAN SYSTEMS INC. - 26 LANSDOWNE STREET - CAMBRIDGE MA 02139 - UNITED STATES - - 00-00-8A (hex) DATAHOUSE INFORMATION SYSTEMS - 00008A (base 16) DATAHOUSE INFORMATION SYSTEMS - DIRECTOR OF OPERATIONS - MEON HOUSE, EAST TISTED NR. ALTON, HAMPS - GU34 3QW ENGLAND - UNITED KINGDOM - - 00-00-8B (hex) INFOTRON - 00008B (base 16) INFOTRON - 9 NORTH OLNEY - CHERRY HILL NJ 08003 - UNITED STATES - - 00-00-8C (hex) Alloy Computer Products (Australia) Pty Ltd - 00008C (base 16) Alloy Computer Products (Australia) Pty Ltd - Unit 4/585 Blackburn Road - Notting Hill Victoria 3168 - AUSTRALIA - - 00-00-8D (hex) Cryptek Inc. - 00008D (base 16) Cryptek Inc. - 1501 Moran Road - Sterling VA 20166 - UNITED STATES - - 00-00-8E (hex) SOLBOURNE COMPUTER, INC. - 00008E (base 16) SOLBOURNE COMPUTER, INC. - 1900 PIKE ROAD - LONGMONT COLORADO 80501 - UNITED STATES - - 00-00-8F (hex) Raytheon - 00008F (base 16) Raytheon - M/S 1-1-1119 - 1001 Boston Post Rd - Marlboro MA 01752 - UNITED STATES - - 00-00-90 (hex) MICROCOM - 000090 (base 16) MICROCOM - 500 RIVER RIDGE DRIVE - NORWOOD MA 02062-5028 - UNITED STATES - - 00-00-91 (hex) ANRITSU CORPORATION - 000091 (base 16) ANRITSU CORPORATION - 1800, ONNA - ATUGI-SHI KANAGAWA-KEN 243 - JAPAN - - 00-00-92 (hex) COGENT DATA TECHNOLOGIES - 000092 (base 16) COGENT DATA TECHNOLOGIES - 640 MULLIS STREET - FRIDAY HARBOR WA 98250 - UNITED STATES - - 00-00-93 (hex) PROTEON INC. - 000093 (base 16) PROTEON INC. - 4 TECH CIRCLE - NATICK MA 01760 - UNITED STATES - - 00-00-94 (hex) ASANTE TECHNOLOGIES - 000094 (base 16) ASANTE TECHNOLOGIES - 821 FOX LANE - SAN JOSE CA 95131 - UNITED STATES - - 00-00-95 (hex) SONY TEKTRONIX CORP. - 000095 (base 16) SONY TEKTRONIX CORP. - P.O. BOX 5209 TOKYO INT'L - TOKYO 100-31 - JAPAN - - 00-00-96 (hex) MARCONI ELECTRONICS LTD. - 000096 (base 16) MARCONI ELECTRONICS LTD. - BROWNS LANE, THE AIRPORT - PORTSMOUTH -- HAMPSHIRE P03 5PH - UNITED KINGDOM - UNITED KINGDOM - - 00-00-97 (hex) EMC Corporation - 000097 (base 16) EMC Corporation - 176 South Street - Hopkinton MA 01748 - UNITED STATES - - 00-00-98 (hex) CROSSCOMM CORPORATION - 000098 (base 16) CROSSCOMM CORPORATION - 450 DONALD LYNCH BOULEVARD - MARLBOROUGH MA 01752 - UNITED STATES - - 00-00-99 (hex) MTX, INC. - 000099 (base 16) MTX, INC. - 3301 TERMINAL DRIVE - RALEIGH NC 27604 - UNITED STATES - - 00-00-9A (hex) RC COMPUTER A/S - 00009A (base 16) RC COMPUTER A/S - LAUTRUPBJERG 1 - DK-2750 BALLERUP - DENMARK - - 00-00-9B (hex) INFORMATION INTERNATIONAL, INC - 00009B (base 16) INFORMATION INTERNATIONAL, INC - 5F., THE 7TH INDUSTRY BLDG. - 1-20-14 JINNAN SHIBUYA-KU TOKYO - JAPAN 150 - JAPAN - - 00-00-9C (hex) ROLM MIL-SPEC COMPUTERS - 00009C (base 16) ROLM MIL-SPEC COMPUTERS - 3151 ZANKER ROAD - SAN JOSE CA 95148 - UNITED STATES - - 00-00-9D (hex) LOCUS COMPUTING CORPORATION - 00009D (base 16) LOCUS COMPUTING CORPORATION - 9800 LA CIENEGA - INGLEWOOD CA 90301 - UNITED STATES - - 00-00-9E (hex) MARLI S.A. - 00009E (base 16) MARLI S.A. - CHEMIN TAVERNEY 3 - 1218 GENEVA - SWITZERLAND - - 00-00-9F (hex) AMERISTAR TECHNOLOGIES INC. - 00009F (base 16) AMERISTAR TECHNOLOGIES INC. - 47 WHITTIER AVE. - MEDFORD NY 11763 - UNITED STATES - - 00-00-A0 (hex) SANYO Electric Co., Ltd. - 0000A0 (base 16) SANYO Electric Co., Ltd. - 5-5, Keihan-hondori 2-chome, - Moriguchi City Osaka 570-8677 - JAPAN - - 00-00-A1 (hex) MARQUETTE ELECTRIC CO. - 0000A1 (base 16) MARQUETTE ELECTRIC CO. - 8200 WEST TOWER AVENUE - MILWAUKEE WI 53223 - UNITED STATES - - 00-00-A2 (hex) BAY NETWORKS - 0000A2 (base 16) BAY NETWORKS - 4401 GREAT AMERICAN PKWY - M/S:SC01-05 - SANTA CLARA CA 95052-8185 - UNITED STATES - - 00-00-A3 (hex) NETWORK APPLICATION TECHNOLOGY - 0000A3 (base 16) NETWORK APPLICATION TECHNOLOGY - 1686 DELL AVENUE - CAMPBELL CA 95008 - UNITED STATES - - 00-00-A4 (hex) ACORN COMPUTERS LIMITED - 0000A4 (base 16) ACORN COMPUTERS LIMITED - FULBOURN ROAD, CHERRY HINTON - CAMBRIDGE CB1 4JN, - ENGLAND - UNITED KINGDOM - - 00-00-A5 (hex) Tattile SRL - 0000A5 (base 16) Tattile SRL - P.O. BOX 17220 - BOULDER CO 80308-7220 - UNITED STATES - - 00-00-A6 (hex) NETWORK GENERAL CORPORATION - 0000A6 (base 16) NETWORK GENERAL CORPORATION - 1296 B LAWRENCE STATION ROAD - SUNNYVALE CA 94089 - UNITED STATES - - 00-00-A7 (hex) NETWORK COMPUTING DEVICES INC. - 0000A7 (base 16) NETWORK COMPUTING DEVICES INC. - 350 NORTH BERNARDO - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-00-A8 (hex) STRATUS COMPUTER INC. - 0000A8 (base 16) STRATUS COMPUTER INC. - 111 Powdermill Road - Maynard MA 01754 - UNITED STATES - - 00-00-A9 (hex) NETWORK SYSTEMS CORP. - 0000A9 (base 16) NETWORK SYSTEMS CORP. - 7600 BOONE AVENUE NORTH - MINNEAPOLIS MN 55428-1099 - UNITED STATES - - 00-00-AA (hex) XEROX CORPORATION - 0000AA (base 16) XEROX CORPORATION - OFFICE SYSTEMS DIVISION - M/S 105-50C 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 00-00-AB (hex) LOGIC MODELING CORPORATION - 0000AB (base 16) LOGIC MODELING CORPORATION - 1520 MCCANDLESS DRIVE - MILPITAS CA 95035 - UNITED STATES - - 00-00-AC (hex) CONWARE COMPUTER CONSULTING - 0000AC (base 16) CONWARE COMPUTER CONSULTING - KILLISFELDSTRAßE 64 - 76227 KARLSRUHE - GERMANY - - 00-00-AD (hex) BRUKER INSTRUMENTS INC. - 0000AD (base 16) BRUKER INSTRUMENTS INC. - MANNING PARK - BILLERICA MA 01821 - UNITED STATES - - 00-00-AE (hex) DASSAULT ELECTRONIQUE - 0000AE (base 16) DASSAULT ELECTRONIQUE - 55, QUAI MARCEL DASSAULT - 92214 ST CLOUD - FRANCE - - 00-00-AF (hex) Canberra Industries, Inc. - 0000AF (base 16) Canberra Industries, Inc. - 800 Research Parkway - Meriden CT 06450 - UNITED STATES - - 00-00-B0 (hex) RND-RAD NETWORK DEVICES - 0000B0 (base 16) RND-RAD NETWORK DEVICES - ATIDIM TECHNOL'CL BLDG. 1 - TEL AVIV 61131 - ISRAEL - - 00-00-B1 (hex) ALPHA MICROSYSTEMS INC. - 0000B1 (base 16) ALPHA MICROSYSTEMS INC. - 3501 SUNFLOWER - SANTA ANA CA 92704 - UNITED STATES - - 00-00-B2 (hex) TELEVIDEO SYSTEMS, INC. - 0000B2 (base 16) TELEVIDEO SYSTEMS, INC. - 550 E. BROKAW ROAD - SAN JOSE CA 95161-9048 - UNITED STATES - - 00-00-B3 (hex) CIMLINC INCORPORATED - 0000B3 (base 16) CIMLINC INCORPORATED - 1957 CROOKS ROAD - TROY MI 48084 - UNITED STATES - - 00-00-B4 (hex) EDIMAX COMPUTER COMPANY - 0000B4 (base 16) EDIMAX COMPUTER COMPANY - No. 3, Wu-Chuan 3rd Road, - Wu-Ku Industrial Park - Taipei Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 00-00-B5 (hex) DATABILITY SOFTWARE SYS. INC. - 0000B5 (base 16) DATABILITY SOFTWARE SYS. INC. - ONE PALMER TERRACE - CARLSTADT NJ 07072 - UNITED STATES - - 00-00-B6 (hex) MICRO-MATIC RESEARCH - 0000B6 (base 16) MICRO-MATIC RESEARCH - AMBACHTENLAAN 21 B5 - B - 3030 HEVERLEE - BELGIUM - - 00-00-B7 (hex) DOVE COMPUTER CORPORATION - 0000B7 (base 16) DOVE COMPUTER CORPORATION - 1200 NORTH 23RD STREET - WILMINGTON NC 28405 - UNITED STATES - - 00-00-B8 (hex) SEIKOSHA CO., LTD. - 0000B8 (base 16) SEIKOSHA CO., LTD. - SYSTEM EQUIPMENT DIVISION - 4-1-1 TAIHEI SUMIDA-KU TOKYO 130 - JAPAN - - 00-00-B9 (hex) MCDONNELL DOUGLAS COMPUTER SYS - 0000B9 (base 16) MCDONNELL DOUGLAS COMPUTER SYS - DIV MCDONNELL DOUGLAS INF SYS - BOUNDARY WAY HEMEL HEMPSTEAD HERTS - ENGLAND - UNITED KINGDOM - - 00-00-BA (hex) SIIG, INC. - 0000BA (base 16) SIIG, INC. - 6078 STEWART AVENUE - FREMONT CA 94538 - UNITED STATES - - 00-00-BB (hex) TRI-DATA - 0000BB (base 16) TRI-DATA - 505 EAST MIDDLEFIELD ROAD - MOUNTAIN VIEW CA 94043-4082 - UNITED STATES - - 00-00-BC (hex) Rockwell Automation - 0000BC (base 16) Rockwell Automation - 1 Allen-Bradley Dr. - Mayfield Heights OH 44124-6118 - UNITED STATES - - 00-00-BD (hex) MITSUBISHI CABLE COMPANY - 0000BD (base 16) MITSUBISHI CABLE COMPANY - 520 MADISON AVENUE - NEW YORK NY 10022 - UNITED STATES - - 00-00-BE (hex) THE NTI GROUP - 0000BE (base 16) THE NTI GROUP - 4701 PATRICK HENRY DRIVE - SUITE 24 - SANTA CLARA CA 95054 - UNITED STATES - - 00-00-BF (hex) SYMMETRIC COMPUTER SYSTEMS - 0000BF (base 16) SYMMETRIC COMPUTER SYSTEMS - 1620 OAKLAND ROAD SUITE D-200 - SAN JOSE CA 95131 - UNITED STATES - - 00-00-C0 (hex) WESTERN DIGITAL CORPORATION - 0000C0 (base 16) WESTERN DIGITAL CORPORATION - 8105 IRVINE CENTER DRIVE - IRVINE CA 92718 - UNITED STATES - - 00-00-C1 (hex) Madge Ltd. - 0000C1 (base 16) Madge Ltd. - Madge House - Priors Way - Maindenhead Berkshire SL6 2HP - UNITED KINGDOM - - 00-00-C2 (hex) INFORMATION PRESENTATION TECH. - 0000C2 (base 16) INFORMATION PRESENTATION TECH. - 23801 CALABASAS ROAD - SUITE 2011 - CALABASAS CA 91302 - UNITED STATES - - 00-00-C3 (hex) HARRIS CORP COMPUTER SYS DIV - 0000C3 (base 16) HARRIS CORP COMPUTER SYS DIV - M/S 75 - 1025 W. NASA BLVD.L 33309 - MELBOURNE FL 32919 - UNITED STATES - - 00-00-C4 (hex) WATERS DIV. OF MILLIPORE - 0000C4 (base 16) WATERS DIV. OF MILLIPORE - 34 MAPLE STREET - MILFORD MA 01757 - UNITED STATES - - 00-00-C5 (hex) ARRIS Group, Inc. - 0000C5 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 00-00-C6 (hex) EON SYSTEMS - 0000C6 (base 16) EON SYSTEMS - 10601 SOUTH DEANZA BLVD. - SUITE 303 - CUPERTINO CA 95014 - UNITED STATES - - 00-00-C7 (hex) ARIX CORPORATION - 0000C7 (base 16) ARIX CORPORATION - ENGINEERING MAIL STOP - 1152 MORSE AVENUE - SUNNYVALE CA 94089 - UNITED STATES - - 00-00-C8 (hex) ALTOS COMPUTER SYSTEMS - 0000C8 (base 16) ALTOS COMPUTER SYSTEMS - 2641 ORCHARD PARKWAY - SAN JOSE CA 95134 - UNITED STATES - - 00-00-C9 (hex) Emulex Corporation - 0000C9 (base 16) Emulex Corporation - 3333 Susan Street - Costa Mesa CA 92626 - UNITED STATES - - 00-00-CA (hex) ARRIS International - 0000CA (base 16) ARRIS International - 3871 Lakefield Drive, Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-00-CB (hex) COMPU-SHACK ELECTRONIC GMBH - 0000CB (base 16) COMPU-SHACK ELECTRONIC GMBH - RINGSTR. 56 - 58, 5450 NEUWIED - WEST - GERMANY - - 00-00-CC (hex) DENSAN CO., LTD. - 0000CC (base 16) DENSAN CO., LTD. - 1-23-11, KAMITAKAIDO - SUGINAMI-KU, TOKYO 168 - JAPAN - - 00-00-CD (hex) Allied Telesis Labs Ltd - 0000CD (base 16) Allied Telesis Labs Ltd - 27 Nazareth Avenue - Middleton Christchurch 8024 - NEW ZEALAND - - 00-00-CE (hex) MEGADATA CORP. - 0000CE (base 16) MEGADATA CORP. - 35 ORVILLE DRIVE - BOHEMIA NY 11716 - UNITED STATES - - 00-00-CF (hex) HAYES MICROCOMPUTER PRODUCTS - 0000CF (base 16) HAYES MICROCOMPUTER PRODUCTS - (CANADA) LTD. - 295 PHILLIP STREET WATERLOO, ONTARIO N2L - CANADA - - 00-00-D0 (hex) DEVELCON ELECTRONICS LTD. - 0000D0 (base 16) DEVELCON ELECTRONICS LTD. - 856-51ST STREET EAST - SASKATOON SASKATCHEWAN S7K 5C7 - CANADA - - 00-00-D1 (hex) ADAPTEC INCORPORATED - 0000D1 (base 16) ADAPTEC INCORPORATED - M/S 180 - 691 SOUTH MILPITAS BLVD. - MILPITAS CA 95035 - UNITED STATES - - 00-00-D2 (hex) SBE, INC. - 0000D2 (base 16) SBE, INC. - 4550 NORTH CANYON ROAD - SAN RAMON CA 94583 - UNITED STATES - - 00-00-D3 (hex) WANG LABORATORIES INC. - 0000D3 (base 16) WANG LABORATORIES INC. - - - 00-00-D4 (hex) PURE DATA LTD. - 0000D4 (base 16) PURE DATA LTD. - 200 WEST BEAVER CREEK ROAD - RICHMOND HILL ONTARIO - L4B 1B4 - CANADA - - 00-00-D5 (hex) MICROGNOSIS INTERNATIONAL - 0000D5 (base 16) MICROGNOSIS INTERNATIONAL - 63 QUEEN VICTORIA STREET - LONDON EC4N 4UD - UNITED KINGDOM - UNITED KINGDOM - - 00-00-D6 (hex) PUNCH LINE HOLDING - 0000D6 (base 16) PUNCH LINE HOLDING - P.O. BOX 391708 - BRAMLEY 2018 - SOUTH AFRICA - SOUTH AFRICA - - 00-00-D7 (hex) DARTMOUTH COLLEGE - 0000D7 (base 16) DARTMOUTH COLLEGE - KIEWIT COMPUTER CENTER - HANOVER NH 03755 - UNITED STATES - - 00-00-D8 (hex) NOVELL, INC. - 0000D8 (base 16) NOVELL, INC. - 122 EAST 1700 SOUTH M/S:E-12-1 - P.O. BOX 5900 - PROVO UT 84601 - UNITED STATES - - 00-00-D9 (hex) NIPPON TELEGRAPH & TELEPHONE - 0000D9 (base 16) NIPPON TELEGRAPH & TELEPHONE - CORPORATION (NTT) - TEISHIN BLDG. 3-1 OOTEMACHI 2 CHOME, CHI - TOKYO 100-8116 - JAPAN - - 00-00-DA (hex) ATEX - 0000DA (base 16) ATEX - 15 CROSBY DRIVE - BEDFORD MA 01730 - UNITED STATES - - 00-00-DB (hex) British Telecommunications plc - 0000DB (base 16) British Telecommunications plc - 81 New Gate St - London, EC1A 7AJ - England - UNITED KINGDOM - - 00-00-DC (hex) HAYES MICROCOMPUTER PRODUCTS - 0000DC (base 16) HAYES MICROCOMPUTER PRODUCTS - P.O. BOX 105203 - ATLANTA GA 30348 - UNITED STATES - - 00-00-DD (hex) TCL INCORPORATED - 0000DD (base 16) TCL INCORPORATED - 41829 ALBRAE STREET - FREMONT CA 94538 - UNITED STATES - - 00-00-DE (hex) CETIA - 0000DE (base 16) CETIA - 150 RUE BERTHELOT - ZI TOULON EST 83088 TOULON CEDEX - FRANCE - - 00-00-DF (hex) BELL & HOWELL PUB SYS DIV - 0000DF (base 16) BELL & HOWELL PUB SYS DIV - OLD MANSFIELD ROAD - WOOSTER OH 44691-9050 - UNITED STATES - - 00-00-E0 (hex) QUADRAM CORP. - 0000E0 (base 16) QUADRAM CORP. - ONE QUAD WAY - NORCROSS GA 30093 - UNITED STATES - - 00-00-E1 (hex) GRID SYSTEMS - 0000E1 (base 16) GRID SYSTEMS - 47211 LAKEVIEW BOULEVARD - P.O. BOX 5003 - FREMONT CA 94537-5003 - UNITED STATES - - 00-00-E2 (hex) ACER TECHNOLOGIES CORP. - 0000E2 (base 16) ACER TECHNOLOGIES CORP. - 401 CHARCOT AVE. - SAN JOSE CA 95131 - UNITED STATES - - 00-00-E3 (hex) INTEGRATED MICRO PRODUCTS LTD - 0000E3 (base 16) INTEGRATED MICRO PRODUCTS LTD - IMP, NO. 1 INDUSTRIAL ESTATE - CONSETT, CO DUKHAM - ENGLAND ENGLAND DH86TJ - UNITED KINGDOM - - 00-00-E4 (hex) IN2 GROUPE INTERTECHNIQUE - 0000E4 (base 16) IN2 GROUPE INTERTECHNIQUE - IN2 - B.P.63 - 78373 PLAISIR CEDEX - FRANCE - - 00-00-E5 (hex) SIGMEX LTD. - 0000E5 (base 16) SIGMEX LTD. - SIGMA HOUSE - NORTH HEATH LANE HORSHAM, WEST SUSSEX - RH12 4UZ ENGLAND - UNITED KINGDOM - - 00-00-E6 (hex) APTOR PRODUITS DE COMM INDUST - 0000E6 (base 16) APTOR PRODUITS DE COMM INDUST - 61, CHEMIN DU VIEUX-CHENE - ZIRST-BP 177 38244 MEYLAN CEDEX - FRANCE - - 00-00-E7 (hex) STAR GATE TECHNOLOGIES - 0000E7 (base 16) STAR GATE TECHNOLOGIES - 29300 AURORA ROAD - SOLON OH 44139 - UNITED STATES - - 00-00-E8 (hex) ACCTON TECHNOLOGY CORP. - 0000E8 (base 16) ACCTON TECHNOLOGY CORP. - 46750 FREMONT BLVD. #104 - FREMONT CA 94538 - UNITED STATES - - 00-00-E9 (hex) ISICAD, INC. - 0000E9 (base 16) ISICAD, INC. - 1920 WEST CORPORATE WAY - ANAHEIM CA 92803-6122 - UNITED STATES - - 00-00-EA (hex) UPNOD AB - 0000EA (base 16) UPNOD AB - BOX 23051 - S-750 23 UPPSALA - SWEDEN - - 00-00-EB (hex) MATSUSHITA COMM. IND. CO. LTD. - 0000EB (base 16) MATSUSHITA COMM. IND. CO. LTD. - 3-1 4-CHOME - TSUNASHIMA-HIGASHI KOHOKU-KU YOKOHAMA - JAPAN - - 00-00-EC (hex) MICROPROCESS - 0000EC (base 16) MICROPROCESS - 97 BIS, RUE DE COLOMBES - B.P. 87 92400 COURBEVOIE - FRANCE - - 00-00-ED (hex) APRIL - 0000ED (base 16) APRIL - 60, RUE DE CARTALE - BP 38 38170 SEYSSINET-PARISET - FRANCE - - 00-00-EE (hex) NETWORK DESIGNERS, LTD. - 0000EE (base 16) NETWORK DESIGNERS, LTD. - UNIT 1A, HORNBEAM PARK - HOOKSTONE ROAD HARROGATE, NORTH YORKSHIR - UNITED KINGDOM HG2 8QT - UNITED KINGDOM - - 00-00-EF (hex) KTI - 0000EF (base 16) KTI - 2157 O'TOOLE AVENUE - SUITE H - SAN JOSE CA 95131 - UNITED STATES - - 00-00-F0 (hex) SAMSUNG ELECTRONICS CO., LTD. - 0000F0 (base 16) SAMSUNG ELECTRONICS CO., LTD. - 416, MAETAN-3DONG, PALDAL-GU - SUWON CITY, KYUNGKI-DO - 442-742 - KOREA, REPUBLIC OF - - 00-00-F1 (hex) MAGNA COMPUTER CORPORATION - 0000F1 (base 16) MAGNA COMPUTER CORPORATION - 22 KEEWAYDIN DRIVE - SALEM NH 03079 - UNITED STATES - - 00-00-F2 (hex) SPIDER COMMUNICATIONS - 0000F2 (base 16) SPIDER COMMUNICATIONS - 7491 BRIAR ROAD - MONTREAL, QUEBEC H4W 1K4 - CANADA - - 00-00-F3 (hex) GANDALF DATA LIMITED - 0000F3 (base 16) GANDALF DATA LIMITED - 130 COLONNADE ROAD SOUTH - NEPEAN ONTARIO K2E 7M4 - CANADA - - 00-00-F4 (hex) Allied Telesis - 0000F4 (base 16) Allied Telesis - CORPORATION - 950 KIFER ROAD - SUNNYVALE CA 94086 - UNITED STATES - - 00-00-F5 (hex) DIAMOND SALES LIMITED - 0000F5 (base 16) DIAMOND SALES LIMITED - 17, CHARTERHOUSE STREET - LONDON, ECIN 6RA - UNITED KINGDOM - UNITED KINGDOM - - 00-00-F6 (hex) APPLIED MICROSYSTEMS CORP. - 0000F6 (base 16) APPLIED MICROSYSTEMS CORP. - 5020 148 AVENUE, N.E. - P.O. BOX 97002 - REDMOND WA 98073-9702 - UNITED STATES - - 00-00-F7 (hex) YOUTH KEEP ENTERPRISE CO LTD - 0000F7 (base 16) YOUTH KEEP ENTERPRISE CO LTD - 3/F NO. 712 MINTSU E. ROAD - TAIPEI, TAIWAN - ROC - TAIWAN, PROVINCE OF CHINA - - 00-00-F8 (hex) DIGITAL EQUIPMENT CORPORATION - 0000F8 (base 16) DIGITAL EQUIPMENT CORPORATION - LKG 1-2/A19 - 550 KING STREET LITTLETON MA 01460-128 - 01460 - UNITED STATES - - 00-00-F9 (hex) QUOTRON SYSTEMS INC. - 0000F9 (base 16) QUOTRON SYSTEMS INC. - 5454 BEETHOVEN ST. - LOS ANGELES CA 90066 - UNITED STATES - - 00-00-FA (hex) MICROSAGE COMPUTER SYSTEMS INC - 0000FA (base 16) MICROSAGE COMPUTER SYSTEMS INC - 680 SOUTH ROCK BLVD - RENO NE 89502 - UNITED STATES - - 00-00-FB (hex) RECHNER ZUR KOMMUNIKATION - 0000FB (base 16) RECHNER ZUR KOMMUNIKATION - BITZENSTR. 11 - F-5464 ASBACH - GERMANY - - 00-00-FC (hex) MEIKO - 0000FC (base 16) MEIKO - 650 AZTEC WEST - BRISTOL BS12 4SD - UNITED KINGDOM - UNITED KINGDOM - - 00-00-FD (hex) HIGH LEVEL HARDWARE - 0000FD (base 16) HIGH LEVEL HARDWARE - PO BOX 170 WINDMILL ROAD - HEADINGTON OXFORD OX3 7BN - ENGLAND - UNITED KINGDOM - - 00-00-FE (hex) ANNAPOLIS MICRO SYSTEMS - 0000FE (base 16) ANNAPOLIS MICRO SYSTEMS - 190 ADMIRAL COCHRANE DRIVE - SUITE 130 - ANNAPOLIS MD 21401 - UNITED STATES - - 00-00-FF (hex) CAMTEC ELECTRONICS LTD. - 0000FF (base 16) CAMTEC ELECTRONICS LTD. - 101 VAUGHAN WAY - LEICESTER LE1 4SA - ENGLAND - UNITED KINGDOM - - 00-01-00 (hex) EQUIP'TRANS - 000100 (base 16) EQUIP'TRANS - 31 rue Paul Cezanne - LA ROCHETTE 77000 - FRANCE - - 00-01-01 (hex) PRIVATE - 000101 (base 16) - - 00-01-02 (hex) 3COM CORPORATION - 000102 (base 16) 3COM CORPORATION - 5400 Bayfront Plaza - MS: 4220 - Santa Clara CA 95052 - UNITED STATES - - 00-01-03 (hex) 3COM CORPORATION - 000103 (base 16) 3COM CORPORATION - 5400 Bayfront Plaza - MS: 4220 - Santa Clara CA 95052 - UNITED STATES - - 00-01-04 (hex) DVICO Co., Ltd. - 000104 (base 16) DVICO Co., Ltd. - Kookmin Card B/D 6F 267-2 - Seohyun-Dong Boondang-Gu - Sungnam-si Kyungki-do 463-050 - KOREA, REPUBLIC OF - - 00-01-05 (hex) Beckhoff Automation GmbH - 000105 (base 16) Beckhoff Automation GmbH - Eiserstraße 5 - Verl NRW 33415 - GERMANY - - 00-01-06 (hex) Tews Datentechnik GmbH - 000106 (base 16) Tews Datentechnik GmbH - Am Bahnhof 7 - 25469 Halstenbek - GERMANY - - 00-01-07 (hex) Leiser GmbH - 000107 (base 16) Leiser GmbH - Ilmstr. 7 - 85579 Neubiberg - GERMANY - - 00-01-08 (hex) AVLAB Technology, Inc. - 000108 (base 16) AVLAB Technology, Inc. - 3F-1, No. 134, Sec. 3 - Chung Shin Road - Hsin Tien, Taipei - TAIWAN, PROVINCE OF CHINA - - 00-01-09 (hex) Nagano Japan Radio Co., Ltd. - 000109 (base 16) Nagano Japan Radio Co., Ltd. - Shimohigano 1163, Inasato-machi - Nagano 381-2288 - JAPAN - - 00-01-0A (hex) CIS TECHNOLOGY INC. - 00010A (base 16) CIS TECHNOLOGY INC. - 16F, No. 75 Hsin Tai Wu Road - Sec. 1, Hsi Chih - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-01-0B (hex) Space CyberLink, Inc. - 00010B (base 16) Space CyberLink, Inc. - 5th Fl. Guppyung Town B - 203 Nonhnyun-Dong, Kangham-Gu - Seoul - KOREA, REPUBLIC OF - - 00-01-0C (hex) System Talks Inc. - 00010C (base 16) System Talks Inc. - 4F, PrimeNihonbashi Bld. - 3-35-6, Nihonbashi Hama-cho - Chuo-ku Tokyo - JAPAN - - 00-01-0D (hex) CORECO, INC. - 00010D (base 16) CORECO, INC. - 6969 Route Transcanadianne - Ville St. Laurent H4T 1V8 Quebec - CANADA - - 00-01-0E (hex) Bri-Link Technologies Co., Ltd - 00010E (base 16) Bri-Link Technologies Co., Ltd - 2F, No. 63, Chow-Tze Street - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-01-0F (hex) Brocade Communications Systems, Inc. - 00010F (base 16) Brocade Communications Systems, Inc. - 1745 Technology Dr. - San Jose CA 95110 - UNITED STATES - - 00-01-10 (hex) Gotham Networks - 000110 (base 16) Gotham Networks - 15 Discovery Way - Acton MA 01720 - UNITED STATES - - 00-01-11 (hex) iDigm Inc. - 000111 (base 16) iDigm Inc. - 7FL Sindo B/D 1604-22 Seocho-Dong - Seocho-Gu - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-01-12 (hex) Shark Multimedia Inc. - 000112 (base 16) Shark Multimedia Inc. - 48890 Milmont Drive #101-D - Fremont CA 94538 - UNITED STATES - - 00-01-13 (hex) OLYMPUS CORPORATION - 000113 (base 16) OLYMPUS CORPORATION - 2-3 Kuboyama-cho, Hachioji-shi - Tokyo 192-8512 - JAPAN - - 00-01-14 (hex) KANDA TSUSHIN KOGYO CO., LTD. - 000114 (base 16) KANDA TSUSHIN KOGYO CO., LTD. - 23-2, Nishi-Gotanda 2-chome, - Shinagawa-ku - Tokyo 141-8533 - JAPAN - - 00-01-15 (hex) EXTRATECH CORPORATION - 000115 (base 16) EXTRATECH CORPORATION - 760 Thornton St., Unit 2 - Post Falls ID 83854 - UNITED STATES - - 00-01-16 (hex) Netspect Technologies, Inc. - 000116 (base 16) Netspect Technologies, Inc. - 3945 Freedom Circle - Ste. #360 - Santa Clara CA 95054 - UNITED STATES - - 00-01-17 (hex) CANAL + - 000117 (base 16) CANAL + - 23 Rue LeBlanc - Le Ponant C - 75906 Paris Cedex 15 - FRANCE - - 00-01-18 (hex) EZ Digital Co., Ltd. - 000118 (base 16) EZ Digital Co., Ltd. - Bitville Bldg. Room 703 - #1327 Seocho-Dong Seocho-Gu - Seoul - KOREA, REPUBLIC OF - - 00-01-19 (hex) RTUnet (Australia) - 000119 (base 16) RTUnet (Australia) - 8/3-5 Gilda Court - Mulgrave Vic 3170 - AUSTRALIA - - 00-01-1A (hex) Hoffmann und Burmeister GbR - 00011A (base 16) Hoffmann und Burmeister GbR - Niederberger Str. 75 - D-53909 Zuelpich - GERMANY - - 00-01-1B (hex) Unizone Technologies, Inc. - 00011B (base 16) Unizone Technologies, Inc. - 5Floor HaeSung Bldg. - 67-2-YangJae-Dong - SeoCho-Ku Seoul - KOREA, REPUBLIC OF - - 00-01-1C (hex) Universal Talkware Corporation - 00011C (base 16) Universal Talkware Corporation - 10 Second St. NE - Suite #400 - Minneapolis MN 55413 - UNITED STATES - - 00-01-1D (hex) Centillium Communications - 00011D (base 16) Centillium Communications - 47211 Lakeview Blvd. - Fremont CA 94538 - UNITED STATES - - 00-01-1E (hex) Precidia Technologies, Inc. - 00011E (base 16) Precidia Technologies, Inc. - 10A Hearst Way - Kanata Ontario K2M-2C4 - CANADA - - 00-01-1F (hex) RC Networks, Inc. - 00011F (base 16) RC Networks, Inc. - 6727 Flanders Drive - Ste. #212 - San Diego CA 92121 - UNITED STATES - - 00-01-20 (hex) OSCILLOQUARTZ S.A. - 000120 (base 16) OSCILLOQUARTZ S.A. - Rue Des Brevards 16 - 2002 Neuchatel - SWITZERLAND - - 00-01-21 (hex) Watchguard Technologies, Inc. - 000121 (base 16) Watchguard Technologies, Inc. - 605 Fifth Ave. S - Suite 500 - Seattle WA 98104-3892 - UNITED STATES - - 00-01-22 (hex) Trend Communications, Ltd. - 000122 (base 16) Trend Communications, Ltd. - Knaves Beech Estate - Loudwater, High Wycombe - Bucks, HP10 9QZ England - UNITED KINGDOM - - 00-01-23 (hex) DIGITAL ELECTRONICS CORP. - 000123 (base 16) DIGITAL ELECTRONICS CORP. - 8-2-52 Nanko Higashi, Suminoe-ku - Osaka, 559-0031 - JAPAN - - 00-01-24 (hex) Acer Incorporated - 000124 (base 16) Acer Incorporated - 21F, 88, Sec.1 - Hsin Tai Wu Road, Hsichih - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-01-25 (hex) YAESU MUSEN CO., LTD. - 000125 (base 16) YAESU MUSEN CO., LTD. - Tennozu Parkside Building - 2-5-8, Higashi-Shinagawa - Shinagawa-ku, Tokyo 140-0002 - JAPAN - - 00-01-26 (hex) PAC Labs - 000126 (base 16) PAC Labs - 3079 Kilgore Road - Rancho Cordova CA 95670 - UNITED STATES - - 00-01-27 (hex) OPEN Networks Pty Ltd - 000127 (base 16) OPEN Networks Pty Ltd - Level 5, 342 Flinders Street - Melbourne VIC 3000 - AUSTRALIA - - 00-01-28 (hex) EnjoyWeb, Inc. - 000128 (base 16) EnjoyWeb, Inc. - 3000 Scott Blvd. #107 - Santa Clara CA 95054 - UNITED STATES - - 00-01-29 (hex) DFI Inc. - 000129 (base 16) DFI Inc. - 100, Huan-Ho Street - Hsi-Chih City Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-01-2A (hex) Telematica Sistems Inteligente - 00012A (base 16) Telematica Sistems Inteligente - Rua Miguel Casagrande, 200 - São Paulo - BRAZIL - - 00-01-2B (hex) TELENET Co., Ltd. - 00012B (base 16) TELENET Co., Ltd. - - - 00-01-2C (hex) Aravox Technologies, Inc. - 00012C (base 16) Aravox Technologies, Inc. - 16725 40th Place North - Plymouth MN 55446 - UNITED STATES - - 00-01-2D (hex) Komodo Technology - 00012D (base 16) Komodo Technology - 170 Knowles Drive - Los Gatos CA 95032 - UNITED STATES - - 00-01-2E (hex) PC Partner Ltd. - 00012E (base 16) PC Partner Ltd. - Rm 1901-1908, 19/F, Shatin Galleria - 18-24 Shan Mei Street, Fo Tan Shatin, H - CHINA - - 00-01-2F (hex) Twinhead International Corp - 00012F (base 16) Twinhead International Corp - 2FL, 2, Lane 235, Bao-Chiao Road - Hsin-Tien - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-30 (hex) Extreme Networks - 000130 (base 16) Extreme Networks - 3585 Monroe Street - Santa Clara CA 95051 - UNITED STATES - - 00-01-31 (hex) Bosch Security Systems, Inc. - 000131 (base 16) Bosch Security Systems, Inc. - 130 Perinton Parkway - Fairport NY 14450 - UNITED STATES - - 00-01-32 (hex) Dranetz - BMI - 000132 (base 16) Dranetz - BMI - 1000 New Durham Road - Edison NJ 08817 - UNITED STATES - - 00-01-33 (hex) KYOWA Electronic Instruments C - 000133 (base 16) KYOWA Electronic Instruments C - 3-5-1, Cyofugaoka - Cyofu Tokyo - JAPAN - - 00-01-34 (hex) Selectron Systems AG - 000134 (base 16) Selectron Systems AG - Bernstreasse 70 - CH-3250 Lyss - SWITZERLAND - - 00-01-35 (hex) KDC Corp. - 000135 (base 16) KDC Corp. - 200-11 AnYang 7 dong - ManAn-Gu AnYane-Si Kyunggi-do - KOREA - KOREA, REPUBLIC OF - - 00-01-36 (hex) CyberTAN Technology, Inc. - 000136 (base 16) CyberTAN Technology, Inc. - 99, Park Avenue III - Science-Based Industrial Park - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 00-01-37 (hex) IT Farm Corporation - 000137 (base 16) IT Farm Corporation - Asashiseimei Fuchu Bldg. 11F - 1-14-1 Fuchu-cho, Fuchu-shi Tokyo - 183-0055 - JAPAN - - 00-01-38 (hex) XAVi Technologies Corp. - 000138 (base 16) XAVi Technologies Corp. - 9F, No. 129, Hsing Te Rd, - Sanchung City Taipei Hsien - 241 TAIWAN 241 TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-39 (hex) Point Multimedia Systems - 000139 (base 16) Point Multimedia Systems - 4Ra 507, Shihwa Industrial Complex - 669-8 Sungkog-Dong, Ansan-City, Kyunggi- - Korea 425-110 - KOREA, REPUBLIC OF - - 00-01-3A (hex) SHELCAD COMMUNICATIONS, LTD. - 00013A (base 16) SHELCAD COMMUNICATIONS, LTD. - P.O. Box 8513 - New Industrial Zone Netanya 42504 - ISRAEL - - 00-01-3B (hex) BNA SYSTEMS - 00013B (base 16) BNA SYSTEMS - 1637 S. Main Street - Milpitas CA 95035 - UNITED STATES - - 00-01-3C (hex) TIW SYSTEMS - 00013C (base 16) TIW SYSTEMS - 2211 Lawson Lane - Santa Clara CA 95054 - UNITED STATES - - 00-01-3D (hex) RiscStation Ltd. - 00013D (base 16) RiscStation Ltd. - 168 Elliott Street - Tyldesley M29 805 - UNITED KINGDOM - UNITED KINGDOM - - 00-01-3E (hex) Ascom Tateco AB - 00013E (base 16) Ascom Tateco AB - Box 8783 - 40276 Goteborg - SWEDEN - - 00-01-3F (hex) Neighbor World Co., Ltd. - 00013F (base 16) Neighbor World Co., Ltd. - 114A YERC, 134, Shinchon_dong - Seodaemun_ku Seoul - 120-749 120-749 KOREA - KOREA, REPUBLIC OF - - 00-01-40 (hex) Sendtek Corporation - 000140 (base 16) Sendtek Corporation - 12F-3, 333, Sec.1 - Kuang-Fu Road Hsinchu - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-01-41 (hex) CABLE PRINT - 000141 (base 16) CABLE PRINT - Jozef Cardynstraat 16 - B - 9420 Erpe-Mere - BELGIUM - - 00-01-42 (hex) CISCO SYSTEMS, INC. - 000142 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-43 (hex) CISCO SYSTEMS, INC. - 000143 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-44 (hex) EMC Corporation - 000144 (base 16) EMC Corporation - 228 South St. - Hopkinton MA 01748 - UNITED STATES - - 00-01-45 (hex) WINSYSTEMS, INC. - 000145 (base 16) WINSYSTEMS, INC. - 715 Stadium Drive - Arlington TX 76011 - UNITED STATES - - 00-01-46 (hex) Tesco Controls, Inc. - 000146 (base 16) Tesco Controls, Inc. - P.O. Box 239012 - Sacramento CA 95823-9012 - UNITED STATES - - 00-01-47 (hex) Zhone Technologies - 000147 (base 16) Zhone Technologies - 7001 Oakport Street - Oakland CA 94621 - UNITED STATES - - 00-01-48 (hex) X-traWeb Inc. - 000148 (base 16) X-traWeb Inc. - 6750 West 93rd Street - Ste. #210 - Overland Park KS 66212 - UNITED STATES - - 00-01-49 (hex) T.D.T. Transfer Data Test GmbH - 000149 (base 16) T.D.T. Transfer Data Test GmbH - Siemensstraße 18 - 84051 Essenbach - GERMANY - - 00-01-4A (hex) Sony Corporation - 00014A (base 16) Sony Corporation - Gotenyama Tec 5-1-2 - Kitashinagawa, - Tokyo Shinagawa-ku 141-0001 - JAPAN - - 00-01-4B (hex) Ennovate Networks, Inc. - 00014B (base 16) Ennovate Networks, Inc. - 60 Codman Hill Road - Boxborough MA 01719 - UNITED STATES - - 00-01-4C (hex) Berkeley Process Control - 00014C (base 16) Berkeley Process Control - 4124 Lakeside Dr - Richmond CA 94806 - UNITED STATES - - 00-01-4D (hex) Shin Kin Enterprises Co., Ltd - 00014D (base 16) Shin Kin Enterprises Co., Ltd - 7, FU Hsing St. Tue Cheng Ind. - Dist. Taipei - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-4E (hex) WIN Enterprises, Inc. - 00014E (base 16) WIN Enterprises, Inc. - 300 Willow Street South - North Andover MA 01845 - UNITED STATES - - 00-01-4F (hex) ADTRAN INC - 00014F (base 16) ADTRAN INC - 901 Explorer Blvd. - Huntsville AL 35806-2807 - UNITED STATES - - 00-01-50 (hex) GILAT COMMUNICATIONS, LTD. - 000150 (base 16) GILAT COMMUNICATIONS, LTD. - 21/D Yegia Kapayim Street - Petach-Tikva 49130 - ISRAEL - - 00-01-51 (hex) Ensemble Communications - 000151 (base 16) Ensemble Communications - 6256 Greenman Drive - Ste. #400 - San Diego CA 92122 - UNITED STATES - - 00-01-52 (hex) CHROMATEK INC. - 000152 (base 16) CHROMATEK INC. - 6-10, Miyazaki 2-Chome - Miyamae-Ku, Kawasaki-shi Kanagawa, 216-0 - JAPAN - - 00-01-53 (hex) ARCHTEK TELECOM CORPORATION - 000153 (base 16) ARCHTEK TELECOM CORPORATION - 4F, No.9 Lane 130, Min-Chyuan Rd. - Hsin-Tien Taipei - 231 TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-01-54 (hex) G3M Corporation - 000154 (base 16) G3M Corporation - 4320 Stevens Creek Blvd. - Ste. #275 - San Jose CA 95129 - UNITED STATES - - 00-01-55 (hex) Promise Technology, Inc. - 000155 (base 16) Promise Technology, Inc. - 4F, 1, Prosperity 1st Road - Science-Based Industrial Park Hsin-Chu - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-01-56 (hex) FIREWIREDIRECT.COM, INC. - 000156 (base 16) FIREWIREDIRECT.COM, INC. - 4132 Spicewood Springs Rd - #I-4 - Austin TX 78759 - UNITED STATES - - 00-01-57 (hex) SYSWAVE CO., LTD - 000157 (base 16) SYSWAVE CO., LTD - Dongho B/D 5F, 221-2 - Nonhyun-Dong, Kangnam-Gu Seoul - KOREA 135-010 - KOREA, REPUBLIC OF - - 00-01-58 (hex) Electro Industries/Gauge Tech - 000158 (base 16) Electro Industries/Gauge Tech - 1800 Shames Drive - Westbury NY 11590 - UNITED STATES - - 00-01-59 (hex) S1 Corporation - 000159 (base 16) S1 Corporation - R&D Center, S1 Bldg. - 59-8, Nonhyun-Dong Kangnam-Ku Seoul - KOREA 135-010 - KOREA, REPUBLIC OF - - 00-01-5A (hex) Digital Video Broadcasting - 00015A (base 16) Digital Video Broadcasting - DVB, % European Broadcasting Union - 17A Ancienne Route CH-1218 Grand Saconne - SWITZERLAND - - 00-01-5B (hex) ITALTEL S.p.A/RF-UP-I - 00015B (base 16) ITALTEL S.p.A/RF-UP-I - 20019 Cast.Settimo M.se (MI) - ITALY - - 00-01-5C (hex) CADANT INC. - 00015C (base 16) CADANT INC. - 4343 Commerce Court - Ste. #207 - Lisle IL 60532 - UNITED STATES - - 00-01-5D (hex) Oracle Corporation - 00015D (base 16) Oracle Corporation - 17 Network Circle - Building 17, UMPK17-131 - Menlo Park CA 95025 - UNITED STATES - - 00-01-5E (hex) BEST TECHNOLOGY CO., LTD. - 00015E (base 16) BEST TECHNOLOGY CO., LTD. - 7F, Haesung B/D - 115-12 Nonhyun-dong Kangnam-Ku Seoul, 13 - KOREA - KOREA, REPUBLIC OF - - 00-01-5F (hex) DIGITAL DESIGN GmbH - 00015F (base 16) DIGITAL DESIGN GmbH - Rauchstr. 21 - Berlin D-10787 - GERMANY - - 00-01-60 (hex) ELMEX Co., LTD. - 000160 (base 16) ELMEX Co., LTD. - 16-30 Kimachi - Aobaku Sendai-Shi Miyagi-Ken - JAPAN - - 00-01-61 (hex) Meta Machine Technology - 000161 (base 16) Meta Machine Technology - 400 Silver Cedar Court - ste. #220 - Chapel Hill NC 27514 - UNITED STATES - - 00-01-62 (hex) Cygnet Technologies, Inc. - 000162 (base 16) Cygnet Technologies, Inc. - 1411 LeMay Drive #301 - Carrollton TX 75007 - UNITED STATES - - 00-01-63 (hex) CISCO SYSTEMS, INC. - 000163 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-64 (hex) CISCO SYSTEMS, INC. - 000164 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-65 (hex) AirSwitch Corporation - 000165 (base 16) AirSwitch Corporation - 37East 200South - Springville UT 84663 - UNITED STATES - - 00-01-66 (hex) TC GROUP A/S - 000166 (base 16) TC GROUP A/S - Sindalsvej 34 - Risskov DK-8240 - DENMARK - - 00-01-67 (hex) HIOKI E.E. CORPORATION - 000167 (base 16) HIOKI E.E. CORPORATION - 81 Koizumi, Ueda, Nagano - 386-1192 386-1192 - JAPAN - - 00-01-68 (hex) VITANA CORPORATION - 000168 (base 16) VITANA CORPORATION - 2500 Don Reid Drive - Ottawa, Ontario - K1H 1E1 K1H 1E1 - CANADA - - 00-01-69 (hex) Celestix Networks Pte Ltd. - 000169 (base 16) Celestix Networks Pte Ltd. - 18 Tannery Lane #05-03 - Lian Tong Building - SINGAPORE 347780 - SINGAPORE - - 00-01-6A (hex) ALITEC - 00016A (base 16) ALITEC - Laval Technopole B.P. 102 - 53001 LAVAL Cedex - FRANCE - - 00-01-6B (hex) LightChip, Inc. - 00016B (base 16) LightChip, Inc. - 5 Industrial Way - Salem NH 03079 - UNITED STATES - - 00-01-6C (hex) FOXCONN - 00016C (base 16) FOXCONN - 105 S Puente St. - Brea CA 92821 - UNITED STATES - - 00-01-6D (hex) CarrierComm Inc. - 00016D (base 16) CarrierComm Inc. - 539 Encintas Blvd. - Suite 201 - Encintas CA 92024 - UNITED STATES - - 00-01-6E (hex) Conklin Corporation - 00016E (base 16) Conklin Corporation - 6141 Crooked Creek Road - Norcross GA 30092-3193 - UNITED STATES - - 00-01-6F (hex) Inkel Corp. - 00016F (base 16) Inkel Corp. - CheongCheon-Dong, BuPyeong-Gu, - Incheon-Si - KOREA, REPUBLIC OF - - 00-01-70 (hex) ESE Embedded System Engineer'g - 000170 (base 16) ESE Embedded System Engineer'g - Mühlbachstraße 20 - 78351 Bodman-Ludwigshafen - GERMANY - - 00-01-71 (hex) Allied Data Technologies - 000171 (base 16) Allied Data Technologies - Pascalweg 1, - 3208 KL Spijkenisse - THE - NETHERLANDS - - 00-01-72 (hex) TechnoLand Co., LTD. - 000172 (base 16) TechnoLand Co., LTD. - 3-17-11 Akebono-cho - Fukuyama-city Hiroshima 721-0925 - JAPAN - - 00-01-73 (hex) AMCC - 000173 (base 16) AMCC - 6290 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 00-01-74 (hex) CyberOptics Corporation - 000174 (base 16) CyberOptics Corporation - 5900 Golden Hills Drive - Golden Valley MN 55416 - UNITED STATES - - 00-01-75 (hex) Radiant Communications Corp. - 000175 (base 16) Radiant Communications Corp. - 5001 Hadley Road - South Plainfield NJ 07080 - UNITED STATES - - 00-01-76 (hex) Orient Silver Enterprises - 000176 (base 16) Orient Silver Enterprises - 8740 White Oak Avenue - Rancho Cucamonga CA 91730 - UNITED STATES - - 00-01-77 (hex) EDSL - 000177 (base 16) EDSL - Habarzel 1 st - Ramat Ahayal Tel-Aviv - ISRAEL 69710 - ISRAEL - - 00-01-78 (hex) MARGI Systems, Inc. - 000178 (base 16) MARGI Systems, Inc. - 3155 Kearney Street. - Ste.#200 - Fremont CA 94538 - UNITED STATES - - 00-01-79 (hex) WIRELESS TECHNOLOGY, INC. - 000179 (base 16) WIRELESS TECHNOLOGY, INC. - Anam Bldg. 2Fl, 154-17 - Samsung-Dong, Kangnam-Ku Seoul, 135-090 - KOREA - KOREA, REPUBLIC OF - - 00-01-7A (hex) Chengdu Maipu Electric Industrial Co., Ltd. - 00017A (base 16) Chengdu Maipu Electric Industrial Co., Ltd. - NANYI BUILDING, CONSULATE RD., - CHENGDU - P.R. - CHINA - - 00-01-7B (hex) Heidelberger Druckmaschinen AG - 00017B (base 16) Heidelberger Druckmaschinen AG - Kurfürsten-Anlage 52-60 - 69115 Heidelberg - GERMANY - - 00-01-7C (hex) AG-E GmbH - 00017C (base 16) AG-E GmbH - Dennewartstraße 27 - 52068 Aachen - GERMANY - - 00-01-7D (hex) ThermoQuest - 00017D (base 16) ThermoQuest - 355 River Oaks Parkway - San Jose CA 95134 - UNITED STATES - - 00-01-7E (hex) ADTEK System Science Co., Ltd. - 00017E (base 16) ADTEK System Science Co., Ltd. - YBP West Tower - 134 Gohdo-cho, - Hodogaya Yokohama - JAPAN - - 00-01-7F (hex) Experience Music Project - 00017F (base 16) Experience Music Project - 110 -110th Avenue NE - Ste. #400 - Bellevue WA 98004 - UNITED STATES - - 00-01-80 (hex) AOpen, Inc. - 000180 (base 16) AOpen, Inc. - 6F, 88, Sec.1, Hsin Tai - Wu Road, Hsichih Taipei Hsien 221 - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-81 (hex) Nortel Networks - 000181 (base 16) Nortel Networks - 1100 Technology Park Drive - Billerica MA 01821 - UNITED STATES - - 00-01-82 (hex) DICA TECHNOLOGIES AG - 000182 (base 16) DICA TECHNOLOGIES AG - Rotherstr, 19 - D-10245 Berlin - GERMANY - - 00-01-83 (hex) ANITE TELECOMS - 000183 (base 16) ANITE TELECOMS - 127 Fleet Road, Fleet - Hampshire, GUB 8PD - UNITED KINGDOM - UNITED KINGDOM - - 00-01-84 (hex) SIEB & MEYER AG - 000184 (base 16) SIEB & MEYER AG - Auf dem Schmaarkamp 21 - D-21339 Luneburg - GERMANY - - 00-01-85 (hex) Hitachi Aloka Medical, Ltd. - 000185 (base 16) Hitachi Aloka Medical, Ltd. - 3-7-19, Imai Ome-city - Tokyo - 198-8577 - JAPAN - - 00-01-86 (hex) Uwe Disch - 000186 (base 16) Uwe Disch - Eichenhainstraße 14 - 91207 Lauf a.d. Pegnitz - GERMANY - - 00-01-87 (hex) I2SE GmbH - 000187 (base 16) I2SE GmbH - Friedrich-Ebert-Str. 61 - Leipzig 04109 - GERMANY - - 00-01-88 (hex) LXCO Technologies ag - 000188 (base 16) LXCO Technologies ag - Gimmerstraße 69 - D-10117 Berlin - GERMANY - - 00-01-89 (hex) Refraction Technology, Inc. - 000189 (base 16) Refraction Technology, Inc. - 2626 Lombardy Lane - Ste. #105 - Dallas TX 75220 - UNITED STATES - - 00-01-8A (hex) ROI COMPUTER AG - 00018A (base 16) ROI COMPUTER AG - Werner-von-Siemens-Str. 1 - 93426 Roding - GERMANY - - 00-01-8B (hex) NetLinks Co., Ltd. - 00018B (base 16) NetLinks Co., Ltd. - 3F Dscom Bldg., 238-3 - Poi-dong, Kangnam-Ku Seoul - KOREA - KOREA, REPUBLIC OF - - 00-01-8C (hex) Mega Vision - 00018C (base 16) Mega Vision - 5765 Thornwood Drive - Goleta CA 93117 - UNITED STATES - - 00-01-8D (hex) AudeSi Technologies - 00018D (base 16) AudeSi Technologies - Suite 180, 6815 - 8th Street N.E. Calgary - AB - CANADA - - 00-01-8E (hex) Logitec Corporation - 00018E (base 16) Logitec Corporation - 8268 Rokudouhara, Misuzu - Ina, Nagano - JAPAN - - 00-01-8F (hex) Kenetec, Inc. - 00018F (base 16) Kenetec, Inc. - 115 Hurley Road - Oxford CT 06748 - UNITED STATES - - 00-01-90 (hex) SMK-M - 000190 (base 16) SMK-M - 1055 Tierra Del Rey - Chula Vista CA 91910 - UNITED STATES - - 00-01-91 (hex) SYRED Data Systems - 000191 (base 16) SYRED Data Systems - 272 Lanes Mill Road - Howell NJ 07731 - UNITED STATES - - 00-01-92 (hex) Texas Digital Systems - 000192 (base 16) Texas Digital Systems - 400 Technology Parkway - College Station TX 77845 - UNITED STATES - - 00-01-93 (hex) Hanbyul Telecom Co., Ltd. - 000193 (base 16) Hanbyul Telecom Co., Ltd. - 5th Fl. Oksan Bldg. - 157-33 Samsung-Dong Kangnam-ku Seoul - KOREA - KOREA, REPUBLIC OF - - 00-01-94 (hex) Capital Equipment Corporation - 000194 (base 16) Capital Equipment Corporation - 900 Middlesex Turnpike - Bldg. 2 - Billerica MA 01821 - UNITED STATES - - 00-01-95 (hex) Sena Technologies, Inc. - 000195 (base 16) Sena Technologies, Inc. - 116-23 Shinlim-dong - Onsung Bldg. 8th Floor Kwanak-ku Seoul - KOREA - KOREA, REPUBLIC OF - - 00-01-96 (hex) CISCO SYSTEMS, INC. - 000196 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-97 (hex) CISCO SYSTEMS, INC. - 000197 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-98 (hex) Darim Vision - 000198 (base 16) Darim Vision - Taejon Expo Venture Town - 3-1 Doryong-dong, Yusung-gu Taejon - KOREA - KOREA, REPUBLIC OF - - 00-01-99 (hex) HeiSei Electronics - 000199 (base 16) HeiSei Electronics - 5/7 Alley 8, Lane 45 - Poaltsin Road Hsintien City - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-01-9A (hex) LEUNIG GmbH - 00019A (base 16) LEUNIG GmbH - Wilhelm-Ostwald-Str. 17 - 53721 Siegburg - GERMANY - - 00-01-9B (hex) Kyoto Microcomputer Co., Ltd. - 00019B (base 16) Kyoto Microcomputer Co., Ltd. - 2-44 nakayama oe nishikyo-ku - kyoto - JAPAN - - 00-01-9C (hex) JDS Uniphase Inc. - 00019C (base 16) JDS Uniphase Inc. - 570 West Hunt Club Road - Napeon, ON K1R 7T7 - CANADA - - 00-01-9D (hex) E-Control Systems, Inc. - 00019D (base 16) E-Control Systems, Inc. - 9420 Lurline Ave., Unite - Chatsworth CA 91311 - UNITED STATES - - 00-01-9E (hex) ESS Technology, Inc. - 00019E (base 16) ESS Technology, Inc. - 48401 Fremont Blvd. - Fremont CA 94538 - UNITED STATES - - 00-01-9F (hex) ReadyNet - 00019F (base 16) ReadyNet - 6952 High Tech Drive - Suite B - Midvale UT 84047 - UNITED STATES - - 00-01-A0 (hex) Infinilink Corporation - 0001A0 (base 16) Infinilink Corporation - 1740 E. Garry Ave. - Ste. #206 - Santa Ana CA 92705 - UNITED STATES - - 00-01-A1 (hex) Mag-Tek, Inc. - 0001A1 (base 16) Mag-Tek, Inc. - 1710 Apollo Court - Seal Beach CA 90740 - UNITED STATES - - 00-01-A2 (hex) Logical Co., Ltd. - 0001A2 (base 16) Logical Co., Ltd. - 4598 Murakushi-cho - Hamamatsu-shi, Shizuoka-ken - 431-1207 - JAPAN - - 00-01-A3 (hex) GENESYS LOGIC, INC. - 0001A3 (base 16) GENESYS LOGIC, INC. - 10F, No. 11, Ln.3., - Tsao Ti Wei, Shenkeng Taipei - TAIWAN, PROVINCE OF CHINA - - 00-01-A4 (hex) Microlink Corporation - 0001A4 (base 16) Microlink Corporation - 11110 Ohio Ave., - Ste. #108 - Los Angeles CA 90034 - UNITED STATES - - 00-01-A5 (hex) Nextcomm, Inc. - 0001A5 (base 16) Nextcomm, Inc. - 12413 Willows Road NE - Ste. #210 - Kirkland WA 98034 - UNITED STATES - - 00-01-A6 (hex) Scientific-Atlanta Arcodan A/S - 0001A6 (base 16) Scientific-Atlanta Arcodan A/S - Avgustenborg Landevej 7 - DK-6400 Sonderborg - DENMARK - - 00-01-A7 (hex) UNEX TECHNOLOGY CORPORATION - 0001A7 (base 16) UNEX TECHNOLOGY CORPORATION - 8F-5, NO. 130 SZE WEI ROAD - HSINCHU - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-A8 (hex) Welltech Computer Co., Ltd. - 0001A8 (base 16) Welltech Computer Co., Ltd. - 13F-4, no. 150, Jian Yi Road - Chung-Ho 235, Taipei - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-A9 (hex) BMW AG - 0001A9 (base 16) BMW AG - Dept. FG-322 - 80788 Munich - GERMANY - - 00-01-AA (hex) Airspan Communications, Ltd. - 0001AA (base 16) Airspan Communications, Ltd. - Cambridge House, Oxford Rd., - Uxbridge, Middlesex UB1UN, - UNITED KINGDOM - - 00-01-AB (hex) Main Street Networks - 0001AB (base 16) Main Street Networks - 4030 Moorpark Ave. - Suite 200 - San Jose CA 95117-1849 - UNITED STATES - - 00-01-AC (hex) Sitara Networks, Inc. - 0001AC (base 16) Sitara Networks, Inc. - 60 Hickory Drive - Waltham MA 02451 - UNITED STATES - - 00-01-AD (hex) Coach Master International d.b.a. CMI Worldwide, Inc. - 0001AD (base 16) Coach Master International d.b.a. CMI Worldwide, Inc. - 600 Stewart Street - Suite 700 - Seattle WA 98101 - UNITED STATES - - 00-01-AE (hex) Trex Enterprises - 0001AE (base 16) Trex Enterprises - 590 Lipoa Parkway - Suite 222 - Kihei HI 96753 - UNITED STATES - - 00-01-AF (hex) Artesyn Embedded Technologies - 0001AF (base 16) Artesyn Embedded Technologies - 2900 S. Diablo Way - Suite 190 - Tempe Arizona 85282 - UNITED STATES - - 00-01-B0 (hex) Fulltek Technology Co., Ltd. - 0001B0 (base 16) Fulltek Technology Co., Ltd. - 3F No. 8, Lane 130, Min Chuan Rd., Hsint - City, Taipei Hsein 231, - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-B1 (hex) General Bandwidth - 0001B1 (base 16) General Bandwidth - 12303-B Technology Blvd. - Austin TX 78727 - UNITED STATES - - 00-01-B2 (hex) Digital Processing Systems, Inc. - 0001B2 (base 16) Digital Processing Systems, Inc. - 70 Valleywood Drive - Markham, Ontario CANADA - L3R 4T5 - CANADA - - 00-01-B3 (hex) Precision Electronic Manufacturing - 0001B3 (base 16) Precision Electronic Manufacturing - P0187, P.O. 527948 - Miami FL 33152-7948 - UNITED STATES - - 00-01-B4 (hex) Wayport, Inc. - 0001B4 (base 16) Wayport, Inc. - 1609 Shoal Creek Blvd. - Suite 301 - Austin TX 78701 - UNITED STATES - - 00-01-B5 (hex) Turin Networks, Inc. - 0001B5 (base 16) Turin Networks, Inc. - 1415 North McDowell Blvd. - Petaluma CA 94954 - UNITED STATES - - 00-01-B6 (hex) SAEJIN T&M Co., Ltd. - 0001B6 (base 16) SAEJIN T&M Co., Ltd. - 2nd Fl., Saejin Bldg., 689 - Ilwon-Dong, Kangnam-Gu. Seoul, 135-230 - KOREA - KOREA, REPUBLIC OF - - 00-01-B7 (hex) Centos, Inc. - 0001B7 (base 16) Centos, Inc. - 6F-1, NO. 15, LANE 360 - NEI-HU RD., SECT. 1, TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-B8 (hex) Netsensity, Inc. - 0001B8 (base 16) Netsensity, Inc. - PO Box 1060 - Lake Forest CA 92630 - UNITED STATES - - 00-01-B9 (hex) SKF Condition Monitoring - 0001B9 (base 16) SKF Condition Monitoring - 4141 Ruffin Road - San Diego CA 92123 - UNITED STATES - - 00-01-BA (hex) IC-Net, Inc. - 0001BA (base 16) IC-Net, Inc. - 5 Fl. Seasung Bldg., 311-27 Noryangjin-D - Dongjak-Gu Seoul, - KOREA - KOREA, REPUBLIC OF - - 00-01-BB (hex) Frequentis - 0001BB (base 16) Frequentis - SPITTELBREITENGASSE 34 - A-1120 VIENNA - AUSTRIA - - 00-01-BC (hex) Brains Corporation - 0001BC (base 16) Brains Corporation - 2-27-8-4Fl TAMAGAWA - SETAGAYA-KU, TOKYO 158-0094 - JAPAN - - 00-01-BD (hex) Peterson Electro-Musical Products, Inc. - 0001BD (base 16) Peterson Electro-Musical Products, Inc. - 11601 S. Mayfield Avenue - Alsip IL 60803-2476 - UNITED STATES - - 00-01-BE (hex) Gigalink Co., Ltd. - 0001BE (base 16) Gigalink Co., Ltd. - 6th F/L Diplomatic Center 1376-1 - Seocho-dong Seocho-ku Seoul - KOREA - KOREA, REPUBLIC OF - - 00-01-BF (hex) Teleforce Co., Ltd. - 0001BF (base 16) Teleforce Co., Ltd. - 721 yoshioka-cho kanonji-city - Kagawa-prf. 768-0021 - JAPAN - - 00-01-C0 (hex) CompuLab, Ltd. - 0001C0 (base 16) CompuLab, Ltd. - P.O. Box 66 - Nesher 36770 - ISRAEL - - 00-01-C1 (hex) Vitesse Semiconductor Corporation - 0001C1 (base 16) Vitesse Semiconductor Corporation - Hoerkaer 18 - DK-2730 Herlev - DENMARK - - 00-01-C2 (hex) ARK Research Corp. - 0001C2 (base 16) ARK Research Corp. - 1198 Saratoga Ave. #11D - San Jose CA 95129 - UNITED STATES - - 00-01-C3 (hex) Acromag, Inc. - 0001C3 (base 16) Acromag, Inc. - 30765 S. Wixom Road - Wixom MI 48393 - UNITED STATES - - 00-01-C4 (hex) NeoWave, Inc. - 0001C4 (base 16) NeoWave, Inc. - 10th KRIHS Bldg. 1591-6 - Kwan Yang-Dong, Dong An-Gu, Anyong-Si, K - SOUTH KOREA - KOREA, REPUBLIC OF - - 00-01-C5 (hex) Simpler Networks - 0001C5 (base 16) Simpler Networks - 555 Dr Frederick Philips - Suite 210 St. Laurent, QUEBEC CANADA - H4M 2X4 - CANADA - - 00-01-C6 (hex) Quarry Technologies - 0001C6 (base 16) Quarry Technologies - 8 New England Executive Park - Burlington MA 01803 - UNITED STATES - - 00-01-C7 (hex) CISCO SYSTEMS, INC. - 0001C7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-C8 (hex) THOMAS CONRAD CORP. - 0001C8 (base 16) THOMAS CONRAD CORP. - 1908-R KRAMER LANE - AUSTIN TX 78758 - UNITED STATES - - 00-01-C8 (hex) CONRAD CORP. - 0001C8 (base 16) CONRAD CORP. - - - 00-01-C9 (hex) CISCO SYSTEMS, INC. - 0001C9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-01-CA (hex) Geocast Network Systems, Inc. - 0001CA (base 16) Geocast Network Systems, Inc. - 190 Independence Drive - Menlo Park CA 94025 - UNITED STATES - - 00-01-CB (hex) EVR - 0001CB (base 16) EVR - 12 Raul Wallenberg St. - Tel Aviv 69719 - ISRAEL - - 00-01-CC (hex) Japan Total Design Communication Co., Ltd. - 0001CC (base 16) Japan Total Design Communication Co., Ltd. - Enesta Suginamihigashi Build., 3F, - 3-7-1, Asagayaminami Suginami-ku, Tokyo - JAPAN - - 00-01-CD (hex) ARtem - 0001CD (base 16) ARtem - Olgastraße 152 - D-89073 ULM - GERMANY - - 00-01-CE (hex) Custom Micro Products, Ltd. - 0001CE (base 16) Custom Micro Products, Ltd. - 450 Blandford Road - Hamworthy Poole Dorset BHIL 5BN - UNITED KINGDOM - UNITED KINGDOM - - 00-01-CF (hex) Alpha Data Parallel Systems, Ltd. - 0001CF (base 16) Alpha Data Parallel Systems, Ltd. - 58 Timber Bush - Edinburgh EH6 6QH Scotland - UNITED KINGDOM - UNITED KINGDOM - - 00-01-D0 (hex) VitalPoint, Inc. - 0001D0 (base 16) VitalPoint, Inc. - 15770 Hopper Road - Peyton CO 80831 - UNITED STATES - - 00-01-D1 (hex) CoNet Communications, Inc. - 0001D1 (base 16) CoNet Communications, Inc. - 25 Mauchly, #320 - Irvine CA 92618 - UNITED STATES - - 00-01-D2 (hex) inXtron, Inc. - 0001D2 (base 16) inXtron, Inc. - 8F, No.52, MinQuan Road, Xindian Dist. - New Taipei City 23141 - TAIWAN, PROVINCE OF CHINA - - 00-01-D3 (hex) PAXCOMM, Inc. - 0001D3 (base 16) PAXCOMM, Inc. - 7th F The Corp. Center - Chungnam National University 220 Kung-Do - KOREA - KOREA, REPUBLIC OF - - 00-01-D4 (hex) Leisure Time, Inc. - 0001D4 (base 16) Leisure Time, Inc. - 4258 Communications Drive - Norcross GA 30093 - UNITED STATES - - 00-01-D5 (hex) HAEDONG INFO & COMM CO., LTD - 0001D5 (base 16) HAEDONG INFO & COMM CO., LTD - #801 The Corporation Center for Universi - 220 Kung-Dong, Yuseong-Gu, - Taejeon Republic of Korea 305 - KOREA, REPUBLIC OF - - 00-01-D6 (hex) manroland AG - 0001D6 (base 16) manroland AG - Stadtbachstraße 1 - 86219 Augsburg - GERMANY - - 00-01-D7 (hex) F5 Networks, Inc. - 0001D7 (base 16) F5 Networks, Inc. - 1322 N. Whitman Lane - Liberty Lake WA 99019 - UNITED STATES - - 00-01-D8 (hex) Teltronics, Inc. - 0001D8 (base 16) Teltronics, Inc. - 4125 Keller Springs Road - Suite 166 - Addison TX 25001 - UNITED STATES - - 00-01-D9 (hex) Sigma, Inc. - 0001D9 (base 16) Sigma, Inc. - 32-3 Seijyo 9 Chome - Setagaya-ku Tokyo 157-0066 - JAPAN - - 00-01-DA (hex) WINCOMM Corporation - 0001DA (base 16) WINCOMM Corporation - 2F, No. 3, Prosperity Road 1, - Science-Based Industrial Park, Hsinchu, - Hsinchu Taiwan - TAIWAN, PROVINCE OF CHINA - - 00-01-DB (hex) Freecom Technologies GmbH - 0001DB (base 16) Freecom Technologies GmbH - Obentrautstraße 72 - D-10963, Berlin, - GERMANY - - 00-01-DC (hex) Activetelco - 0001DC (base 16) Activetelco - 43222 Christy Street - Fremont CA 94538 - UNITED STATES - - 00-01-DD (hex) Avail Networks - 0001DD (base 16) Avail Networks - 305 E. Eisenhower Parkway - Ann Arbor MI 48108 - UNITED STATES - - 00-01-DE (hex) Trango Systems, Inc. - 0001DE (base 16) Trango Systems, Inc. - 9939 V/A Pasar - San Diego CA 92126 - UNITED STATES - - 00-01-DF (hex) ISDN Communications, Ltd. - 0001DF (base 16) ISDN Communications, Ltd. - The Stable Block, Ronans - Chavey Down Road, Winkfield Row Berkshir - ENGLAND - UNITED KINGDOM - - 00-01-E0 (hex) Fast Systems, Inc. - 0001E0 (base 16) Fast Systems, Inc. - 87-9 Yang-Jae, Seo-Cho, - Seoul, - KOREA - KOREA, REPUBLIC OF - - 00-01-E1 (hex) Kinpo Electronics, Inc. - 0001E1 (base 16) Kinpo Electronics, Inc. - TSAC TI WEI, WAN SHUN TSUN, - SHEN KENG HSIANG, TAIPEI HSIEN TAIWAN (2 - CHINA - TAIWAN, PROVINCE OF CHINA - - 00-01-E2 (hex) Ando Electric Corporation - 0001E2 (base 16) Ando Electric Corporation - 19-7, Kamata 4-Chrome, Ota-ku - Tokyo, 144-0052 - JAPAN - - 00-01-E3 (hex) Siemens AG - 0001E3 (base 16) Siemens AG - Schlavenhorst 88 - 46395 Bocholt - GERMANY - - 00-01-E4 (hex) Sitera, Inc. - 0001E4 (base 16) Sitera, Inc. - 1820 Lefthand Circle - Longmont CO 80501 - UNITED STATES - - 00-01-E5 (hex) Supernet, Inc. - 0001E5 (base 16) Supernet, Inc. - 135-080 Daemeong Bldg. - 2nd Floor, 650-2, Yeoksam-dong Kangnam-k - KOREA - KOREA, REPUBLIC OF - - 00-01-E6 (hex) Hewlett-Packard Company - 0001E6 (base 16) Hewlett-Packard Company - 11000 Wolfe Road, Mailstop 42LE - Cupertino CA 95014 - UNITED STATES - - 00-01-E7 (hex) Hewlett-Packard Company - 0001E7 (base 16) Hewlett-Packard Company - 11000 Wolfe Road, Mailstop 42LE - Cupertino CA 95014 - UNITED STATES - - 00-01-E8 (hex) Force10 Networks, Inc. - 0001E8 (base 16) Force10 Networks, Inc. - 1440 McCarthy Blvd. - Milpitas CA 95035 - UNITED STATES - - 00-01-E9 (hex) Litton Marine Systems B.V. - 0001E9 (base 16) Litton Marine Systems B.V. - 118 Burlington Road - New Malden, Surrey - ENGLAND KT3 4NR - UNITED KINGDOM - - 00-01-EA (hex) Cirilium Corp. - 0001EA (base 16) Cirilium Corp. - 1615 S. 52nd Street - Tempe AZ 85281 - UNITED STATES - - 00-01-EB (hex) C-COM Corporation - 0001EB (base 16) C-COM Corporation - 3F, No. 48, Park Ave. II SBIP - Hsinchu Taiwan Hsinchu Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-EC (hex) Ericsson Group - 0001EC (base 16) Ericsson Group - Telefonaktiebolaget - LM Ericsson Corp. 126 25 STOCKHOLM - SWEDEN - - 00-01-ED (hex) SETA Corp. - 0001ED (base 16) SETA Corp. - Ariake Frontier Bldg. B - Ariake, Koutou Ku Tokyo, - JAPAN 135-0063 - JAPAN - - 00-01-EE (hex) Comtrol Europe, Ltd. - 0001EE (base 16) Comtrol Europe, Ltd. - The Courtyard Studio - Grange Farm, Station Road Launton Oxon O - U.K. - UNITED KINGDOM - - 00-01-EF (hex) Camtel Technology Corp. - 0001EF (base 16) Camtel Technology Corp. - No. 2, Wu-Kung 5 Rd., Wu-Ku - Ind. Park, Hsinchuang, Taipei Shien - Taiwan Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-01-F0 (hex) Tridium, Inc. - 0001F0 (base 16) Tridium, Inc. - 3951 Westerre Parkway - Suite 350 - Richmond VA 23233 - UNITED STATES - - 00-01-F1 (hex) Innovative Concepts, Inc. - 0001F1 (base 16) Innovative Concepts, Inc. - 8200 Greensboro Drive - Suite 801 - McLean VA 22102 - UNITED STATES - - 00-01-F2 (hex) Mark of the Unicorn, Inc. - 0001F2 (base 16) Mark of the Unicorn, Inc. - 1280 Massachusetts Ave. - Cambridge MA 02138 - UNITED STATES - - 00-01-F3 (hex) QPS, Inc. - 0001F3 (base 16) QPS, Inc. - 8015 E. Crystal Drive - Anaheim CA 92807 - UNITED STATES - - 00-01-F4 (hex) Enterasys Networks - 0001F4 (base 16) Enterasys Networks - 35 Industrial Way - Rochester NH 03867 - UNITED STATES - - 00-01-F5 (hex) ERIM S.A. - 0001F5 (base 16) ERIM S.A. - 11 Av Republique - 69692 Venissieux Cedex - FRANCE - - 00-01-F6 (hex) Association of Musical Electronics Industry - 0001F6 (base 16) Association of Musical Electronics Industry - Ito Bldg. 4th Floor 2-16-9 Misaki-cho, - Chiyoda-ku, Tokyo, 101-0061 - JAPAN - - 00-01-F7 (hex) Image Display Systems, Inc. - 0001F7 (base 16) Image Display Systems, Inc. - 46560 Fremont Blvd. - Suite #406 - Fremont CA 94538 - UNITED STATES - - 00-01-F8 (hex) Texio Technology Corporation - 0001F8 (base 16) Texio Technology Corporation - 7F Towa Fudosan Shin Yokohama BLdg 2-18-13 - Shin Yokohama - Kohoku-ku Yokohama, Kanagawa 222-0033 - JAPAN - - 00-01-F9 (hex) TeraGlobal Communications Corp. - 0001F9 (base 16) TeraGlobal Communications Corp. - 9171 Towne Centre Drive - Suite #600 - San Diego CA 92122 - UNITED STATES - - 00-01-FA (hex) HOROSCAS - 0001FA (base 16) HOROSCAS - 26, LOUIS BLANC - 69006 LYON - FRANCE - - 00-01-FB (hex) DoTop Technology, Inc. - 0001FB (base 16) DoTop Technology, Inc. - 10F, No. 100, Min-Chyuan Road - Hsin-Tien, Taipei - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-01-FC (hex) Keyence Corporation - 0001FC (base 16) Keyence Corporation - 1-3-14, Higashi-Nakajima, - Higashi-Yodogawa-ku Osaka 533-8555 - JAPAN - - 00-01-FD (hex) Digital Voice Systems, Inc. - 0001FD (base 16) Digital Voice Systems, Inc. - 234 Littleton Road - Westford MA 01886 - UNITED STATES - - 00-01-FE (hex) DIGITAL EQUIPMENT CORPORATION - 0001FE (base 16) DIGITAL EQUIPMENT CORPORATION - M/S CX01-2/N26 - 301 ROCKRIMMON BLVD., S - COLORADO SPRINGS CO 80919 - UNITED STATES - - 00-01-FF (hex) Data Direct Networks, Inc. - 0001FF (base 16) Data Direct Networks, Inc. - 9320 Lurline Avenue - Chatsworth CA 91311 - UNITED STATES - - 00-02-00 (hex) Net & Sys Co., Ltd. - 000200 (base 16) Net & Sys Co., Ltd. - Kuro Hitech Industrial Complex 304, - 402-3, Shindorim-dong, Kuro-gu Seoul, - KOREA - KOREA, REPUBLIC OF - - 00-02-01 (hex) IFM Electronic gmbh - 000201 (base 16) IFM Electronic gmbh - Bechlingen 34 - D-88069 Tettnang - GERMANY - - 00-02-02 (hex) Amino Communications, Ltd. - 000202 (base 16) Amino Communications, Ltd. - Times House - Fen End Willingham, Cambridge - UK CB4 5LH - UNITED KINGDOM - - 00-02-03 (hex) Woonsang Telecom, Inc. - 000203 (base 16) Woonsang Telecom, Inc. - 104-9, Munji-Dong, Yusong-Gu - Taejon, 305-380, - KOREA - KOREA, REPUBLIC OF - - 00-02-04 (hex) Bodmann Industries Elektronik GmbH - 000204 (base 16) Bodmann Industries Elektronik GmbH - Messerschmittring 33 - D-86343 Konigsbrunn - GERMANY - - 00-02-05 (hex) Hitachi Denshi, Ltd. - 000205 (base 16) Hitachi Denshi, Ltd. - 32 Miyaki-cho Kodaira-shi - Toyko, - JAPAN 187-8511 - JAPAN - - 00-02-06 (hex) Telital R&D Denmark A/S - 000206 (base 16) Telital R&D Denmark A/S - 9530 Stouring - DENMARK - - 00-02-07 (hex) VisionGlobal Network Corp. - 000207 (base 16) VisionGlobal Network Corp. - 826 E. Stale Road - Suite 200 - American Fork UT 84003 - UNITED STATES - - 00-02-08 (hex) Unify Networks, Inc. - 000208 (base 16) Unify Networks, Inc. - 3160 De La Cruz Blvd. - #201 - Santa Clara CA 95054 - UNITED STATES - - 00-02-09 (hex) Shenzhen SED Information Technology Co., Ltd. - 000209 (base 16) Shenzhen SED Information Technology Co., Ltd. - 4/F., West Block, Block 414, Zhenhua Rd. - Futian Shenzhen, 518031 P.R. - CHINA - - 00-02-0A (hex) Gefran Spa - 00020A (base 16) Gefran Spa - Via Sebina, 74 - Provaglio D'Iseo 25050 Brescia - ITALY - - 00-02-0B (hex) Native Networks, Inc. - 00020B (base 16) Native Networks, Inc. - P.O. Box 7165 - Petah Tikva 49170 - ISRAEL - - 00-02-0C (hex) Metro-Optix - 00020C (base 16) Metro-Optix - 2201 Avenue K - Plano TX 75074 - UNITED STATES - - 00-02-0D (hex) Micronpc.com - 00020D (base 16) Micronpc.com - 900 E. Karcher Rd. - Nampa IA 83687 - UNITED STATES - - 00-02-0E (hex) ECI Telecom, Ltd - 00020E (base 16) ECI Telecom, Ltd - 30 Hasivim St - Petach-Tikva 49133 - ISRAEL - - 00-02-0F (hex) AATR - 00020F (base 16) AATR - 306 Chemin des Miroirs - 13330 Pelissanne - FRANCE - - 00-02-10 (hex) Fenecom - 000210 (base 16) Fenecom - 7/F Kon-kuk University Alumni - Association Building NO: 227-336 Jayang - Seoul Seoul Korea - KOREA, REPUBLIC OF - - 00-02-11 (hex) Nature Worldwide Technology Corp. - 000211 (base 16) Nature Worldwide Technology Corp. - No. 1, Min-Chuan Street - Tu-Cheng Industrial Park Taipei Hsien, - Taiwan Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-12 (hex) SierraCom - 000212 (base 16) SierraCom - 99 South Street - Hopkinton Ma 01748 - UNITED STATES - - 00-02-13 (hex) S.D.E.L. - 000213 (base 16) S.D.E.L. - Aeropole D2A - Rue Nungerrer et Coli 44860 St Aignan de - FRANCE - - 00-02-14 (hex) DTVRO - 000214 (base 16) DTVRO - 813 Daegong Bldg., - 823-21 Yeoksam-Dong, Kangnam-Gu, Seoul, - KOREA KOREA 135-080 - KOREA, REPUBLIC OF - - 00-02-15 (hex) Cotas Computer Technology A/B - 000215 (base 16) Cotas Computer Technology A/B - Paludan-Mullers Vej 82 - DK-8200 Aarhus N - DENMARK - - 00-02-16 (hex) CISCO SYSTEMS, INC. - 000216 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-17 (hex) CISCO SYSTEMS, INC. - 000217 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-18 (hex) Advanced Scientific Corp - 000218 (base 16) Advanced Scientific Corp - 1 Fl., No. 26, Industry East 9th Road - Science-based Industrial Park Hsin-Chu - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-02-19 (hex) Paralon Technologies - 000219 (base 16) Paralon Technologies - 700 Fifth Ave, Suite 6101 - Seattle WA 98104 - UNITED STATES - - 00-02-1A (hex) Zuma Networks - 00021A (base 16) Zuma Networks - 8403 Fallbrook Ave. - West Hills CA 91304 - UNITED STATES - - 00-02-1B (hex) Kollmorgen-Servotronix - 00021B (base 16) Kollmorgen-Servotronix - POB 3919, Petach Tikya - 49130 - ISRAEL - - 00-02-1C (hex) Network Elements, Inc. - 00021C (base 16) Network Elements, Inc. - 9782 SW Nimbus Avenue - Beaverton OR 97008 - UNITED STATES - - 00-02-1D (hex) Data General Communication Ltd. - 00021D (base 16) Data General Communication Ltd. - Rm. 18C, Bldg. C, CEIEC Tower - No. 2070, Rd. ShenNanZhong ShenZhen City - CHINA - - 00-02-1E (hex) SIMTEL S.R.L. - 00021E (base 16) SIMTEL S.R.L. - Via Bonifacio Lupi, 25 - 50129 Firenze - ITALY - - 00-02-1F (hex) Aculab PLC - 00021F (base 16) Aculab PLC - Lakeside, Bramley Road - Mount Farm - Milton Keynes MK1 1PT - UNITED KINGDOM - - 00-02-20 (hex) CANON FINETECH INC. - 000220 (base 16) CANON FINETECH INC. - 717, Yaguchi, Misato-shi, - Saitama 341-8527 - JAPAN - - 00-02-21 (hex) DSP Application, Ltd. - 000221 (base 16) DSP Application, Ltd. - 12F-12, No. 79, Sec. 1 Hsin Tai Wu Rd. - HSICHI, Taipei County - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-02-22 (hex) Chromisys, Inc. - 000222 (base 16) Chromisys, Inc. - 1012 Stewart Drive - Sunnyvale CA 94086 - UNITED STATES - - 00-02-23 (hex) ClickTV - 000223 (base 16) ClickTV - Kemong Bldg., 4th Fl., - 772 Yoksam-Dong Kangnam-Ku - Seoul Korea 135-010 - KOREA, REPUBLIC OF - - 00-02-24 (hex) C-COR - 000224 (base 16) C-COR - 15 Sterling Drive - Wallingford CT 06492 - UNITED STATES - - 00-02-25 (hex) One Stop Systems - 000225 (base 16) One Stop Systems - 2235 Enterprise Street - Suite 110 - Escondido CA 92029 - UNITED STATES - - 00-02-26 (hex) XESystems, Inc. - 000226 (base 16) XESystems, Inc. - 317 Main Street - East Rochester NY 14445 - UNITED STATES - - 00-02-27 (hex) ESD Electronic System Design GmbH - 000227 (base 16) ESD Electronic System Design GmbH - Vahrenwalder Str. 207 - 30 165 Hannover - GERMANY - - 00-02-28 (hex) Necsom, Ltd. - 000228 (base 16) Necsom, Ltd. - Necsom Ltd. c/o Koirsto - Saunamaentie 4 A 1 FIN-02770 ESP00 - FINLAND - - 00-02-29 (hex) Adtec Corporation - 000229 (base 16) Adtec Corporation - 3F Megurohigashiyama Blg - 1 4 4 Higashiyama, Meguro Ku Tokyo 153 0 - JAPAN - - 00-02-2A (hex) Asound Electronic - 00022A (base 16) Asound Electronic - Xianxi Industries Zone Changan Town - Dong Guon City, Guong Dong Providence - CHINA - - 00-02-2B (hex) SAXA, Inc. - 00022B (base 16) SAXA, Inc. - NBF Platinum Tower 1-17-3 Shirokane - Minato-ku Tokyo 108-8050 - JAPAN - - 00-02-2C (hex) ABB Bomem, Inc. - 00022C (base 16) ABB Bomem, Inc. - 585, boul. Charest Est - Suite 300 Quebec City, PQ - Canada G1K 9H4 - CANADA - - 00-02-2D (hex) Agere Systems - 00022D (base 16) Agere Systems - P.O. Box 755 - 3430 At Nieuwegein - NETHERLANDS - - 00-02-2E (hex) TEAC Corp. R& D - 00022E (base 16) TEAC Corp. R& D - 857 Koyata, Iruma - Saitama - JAPAN - - 00-02-2F (hex) P-Cube, Ltd. - 00022F (base 16) P-Cube, Ltd. - P.O. Box 12331 - Herzlia 46766 - ISRAEL - - 00-02-30 (hex) Intersoft Electronics - 000230 (base 16) Intersoft Electronics - Lammerdries 27 - B2250 Olen - BELGIUM - - 00-02-31 (hex) Ingersoll-Rand - 000231 (base 16) Ingersoll-Rand - 1467 Route 31 South - P.O. Box 970 - Annandale NJ 08801 - UNITED STATES - - 00-02-32 (hex) Avision, Inc. - 000232 (base 16) Avision, Inc. - No. 20, Creation Rd. 1, - Science-Based Industrial Park, - Hsinchu Taiwan, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-33 (hex) Mantra Communications, Inc. - 000233 (base 16) Mantra Communications, Inc. - 12850 Middlebrook Road - Suite 1 - Germantown MD 20874 - UNITED STATES - - 00-02-34 (hex) Imperial Technology, Inc. - 000234 (base 16) Imperial Technology, Inc. - 2305 Utah Avenue - El Segundo CA 90245 - UNITED STATES - - 00-02-35 (hex) Paragon Networks International - 000235 (base 16) Paragon Networks International - 61 Commerce Drive - Brookfield CT 06804 - UNITED STATES - - 00-02-36 (hex) INIT GmbH - 000236 (base 16) INIT GmbH - Kaeppelestraße 6 - D-76131 Karlsruhe - GERMANY - - 00-02-37 (hex) Cosmo Research Corp. - 000237 (base 16) Cosmo Research Corp. - Cosmo Bldg, 3-148-5 - Miyaharacho, Omiya Saitama 330-0038 - JAPAN - - 00-02-38 (hex) Serome Technology, Inc. - 000238 (base 16) Serome Technology, Inc. - 555-14, Baekang B/D 7F - Shinsa-dong, Kangnam-gu - Seoul Korea 135-120 - KOREA, REPUBLIC OF - - 00-02-39 (hex) Visicom - 000239 (base 16) Visicom - 10052 Mesa Ridge Ct. - San Diego CA 92121 - UNITED STATES - - 00-02-3A (hex) ZSK Stickmaschinen GmbH - 00023A (base 16) ZSK Stickmaschinen GmbH - Magdeburger Straße 38-40 - 47800 Krefeld - GERMANY - - 00-02-3B (hex) Ericsson - 00023B (base 16) Ericsson - 250 Holger Way - SAN JOSE CA 95134 - UNITED STATES - - 00-02-3C (hex) Creative Technology, Ltd. - 00023C (base 16) Creative Technology, Ltd. - 31 International Business Park - Singapore 609921 - Republic of - SINGAPORE - - 00-02-3D (hex) Cisco Systems, Inc. - 00023D (base 16) Cisco Systems, Inc. - 170 West Tasman Drive - San Jose CA 95134 - UNITED STATES - - 00-02-3E (hex) Selta Telematica S.p.a - 00023E (base 16) Selta Telematica S.p.a - Via Nazionale km 404.5 - 64019 Tortoreto Lido TE - ITALY - - 00-02-3F (hex) Compal Electronics, Inc. - 00023F (base 16) Compal Electronics, Inc. - 581, Juikuang Rd., - Neihu, Taipei, (114) - TAIWAN, PROVINCE OF CHINA - - 00-02-40 (hex) Seedek Co., Ltd. - 000240 (base 16) Seedek Co., Ltd. - #709, 1638-32, Sammo - Shinrimbon-Dong, Kwanak-Gu, Seoul - KOREA - KOREA, REPUBLIC OF - - 00-02-41 (hex) Amer.com - 000241 (base 16) Amer.com - 7259 Bryan Dairy Road - Largo FL 33777 - UNITED STATES - - 00-02-42 (hex) Videoframe Systems - 000242 (base 16) Videoframe Systems - 101 Providence Mine Road - Suite 103 - Nevada City CA 95959 - UNITED STATES - - 00-02-43 (hex) Raysis Co., Ltd. - 000243 (base 16) Raysis Co., Ltd. - 997-10, Daechi-Dong, Kangnam-Ku, - Seoul 135-280, South Korea - KOREA, REPUBLIC OF - - 00-02-44 (hex) SURECOM Technology Co. - 000244 (base 16) SURECOM Technology Co. - 6F, No. 125, Sec. 2, Datung Rd. - Shijr, Taipei County, 221 - Taiwan Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-45 (hex) Lampus Co, Ltd. - 000245 (base 16) Lampus Co, Ltd. - 6th Bldg., Samgong, - 58-7 Ranpo 4dong Scoch-go, Seoul, - Korea Korea 137-044 - KOREA, REPUBLIC OF - - 00-02-46 (hex) All-Win Tech Co., Ltd. - 000246 (base 16) All-Win Tech Co., Ltd. - 11F, No. 111-7, Hsing De Rd., - San Chung City, - Taipei Hsien Taiwan, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-47 (hex) Great Dragon Information Technology (Group) Co., Ltd. - 000247 (base 16) Great Dragon Information Technology (Group) Co., Ltd. - 169 Beiyuan Rd., - Chaoyang District - Beijing 100101, - CHINA - - 00-02-48 (hex) Pilz GmbH & Co. - 000248 (base 16) Pilz GmbH & Co. - Felix-Wankel-Straße 2 - D-73760 Ostfildern - GERMANY - - 00-02-49 (hex) Aviv Infocom Co, Ltd. - 000249 (base 16) Aviv Infocom Co, Ltd. - 962-5, Kwanyang-Dong, Dongan-Gu, - Anyang-City, Kyungki-Do, 431-060 - Korea (ROK) - KOREA, REPUBLIC OF - - 00-02-4A (hex) CISCO SYSTEMS, INC. - 00024A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-4B (hex) CISCO SYSTEMS, INC. - 00024B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-4C (hex) SiByte, Inc. - 00024C (base 16) SiByte, Inc. - 2805 Bowers Avenue - Santa Clara CA 95051-0917 - UNITED STATES - - 00-02-4D (hex) Mannesman Dematic Colby Pty. Ltd. - 00024D (base 16) Mannesman Dematic Colby Pty. Ltd. - 24 Narabang Way - Belrose, NSW 2085 - AUSTRALIA - - 00-02-4E (hex) Datacard Group - 00024E (base 16) Datacard Group - 11111 Bren Road West - MS 202 - Minnetonka MN 55343 - UNITED STATES - - 00-02-4F (hex) IPM Datacom S.R.L. - 00024F (base 16) IPM Datacom S.R.L. - Via Roma, 231 - 80027 Frattamaggiore - Naples - ITALY - - 00-02-50 (hex) Geyser Networks, Inc. - 000250 (base 16) Geyser Networks, Inc. - 535 Del Rey Avenue - Sunnyvale CA 94086 - UNITED STATES - - 00-02-51 (hex) Soma Networks, Inc. - 000251 (base 16) Soma Networks, Inc. - 650 Townsend St. - Suite 305 - San Francisco CA 94103 - UNITED STATES - - 00-02-52 (hex) Carrier Corporation - 000252 (base 16) Carrier Corporation - One Carrier Place - Farmington CT 06034-4015 - UNITED STATES - - 00-02-53 (hex) Televideo, Inc. - 000253 (base 16) Televideo, Inc. - 2345 Harris Way - San Jose CA 95131 - UNITED STATES - - 00-02-54 (hex) WorldGate - 000254 (base 16) WorldGate - 3190 Tremont Avenue - Trevose PA 19053 - UNITED STATES - - 00-02-55 (hex) IBM Corp - 000255 (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. Box 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-02-56 (hex) Alpha Processor, Inc. - 000256 (base 16) Alpha Processor, Inc. - 130 C Baker Ave. Ext. - Concord MA 01742 - UNITED STATES - - 00-02-57 (hex) Microcom Corp. - 000257 (base 16) Microcom Corp. - 8333A Green Meadows Dr. N. - Westerville OH 43081 - UNITED STATES - - 00-02-58 (hex) Flying Packets Communications - 000258 (base 16) Flying Packets Communications - 388 Market Street - Suite 380 - San Francisco CA 94111 - UNITED STATES - - 00-02-59 (hex) Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group - 000259 (base 16) Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group - 8F, #99, Huaihai Rd, East, - Shanghai, - CHINA 200021 - CHINA - - 00-02-5A (hex) Catena Networks - 00025A (base 16) Catena Networks - 307 Legget Drive - Kanata Ontario - Canada K2K 3C8 - CANADA - - 00-02-5B (hex) Cambridge Silicon Radio - 00025B (base 16) Cambridge Silicon Radio - Unit 400, Science Park, - Milton Road, Cambridge,CB4 OXL - United Kingdom - UNITED KINGDOM - - 00-02-5C (hex) SCI Systems (Kunshan) Co., Ltd. - 00025C (base 16) SCI Systems (Kunshan) Co., Ltd. - 312 QING YANG ROAD - KUNSHAN, JIANGSU PROVICC - CHINA CHINA 215300 - CHINA - - 00-02-5D (hex) Calix Networks - 00025D (base 16) Calix Networks - 1035 North McDowell Blvd. - Petaluma CA 94954 - UNITED STATES - - 00-02-5E (hex) High Technology Ltd - 00025E (base 16) High Technology Ltd - Chongqing Jinghong - A2-10-3 California Garden Yubei District - People's Republic of - CHINA - - 00-02-5F (hex) Nortel Networks - 00025F (base 16) Nortel Networks - 9300 trans-CANADA Highway - St. Laurenet, Quebec - H4S 1KS - CANADA - - 00-02-60 (hex) Accordion Networks, Inc. - 000260 (base 16) Accordion Networks, Inc. - 39899 Balentine Drive, #335 - Newark CA 94560 - UNITED STATES - - 00-02-61 (hex) Tilgin AB - 000261 (base 16) Tilgin AB - Finlandsgatan 40 - SE-164 74 Kista - SWEDEN - - 00-02-62 (hex) Soyo Group Soyo Com Tech Co., Ltd - 000262 (base 16) Soyo Group Soyo Com Tech Co., Ltd - 5H. No. 21 Wu-gong 5 Rd, - Hsing Chuang, - Taipei Hsien Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-63 (hex) UPS Manufacturing SRL - 000263 (base 16) UPS Manufacturing SRL - Via Giordano, 54 - 37050 Vallese Di Oppeano - Verona - ITALY - - 00-02-64 (hex) AudioRamp.com - 000264 (base 16) AudioRamp.com - 15941 Red Hill Suite 205 - Tustin CA 92780 - UNITED STATES - - 00-02-65 (hex) Virditech Co. Ltd. - 000265 (base 16) Virditech Co. Ltd. - Hyundai Topics Blgd., 11th Fl - 44-3 Pangi-dong, Songpa-Gu - Seoul Seoul KOREA - KOREA, REPUBLIC OF - - 00-02-66 (hex) Thermalogic Corporation - 000266 (base 16) Thermalogic Corporation - 22 Kane Industrial Drive - Hudson MA 01749 - UNITED STATES - - 00-02-67 (hex) NODE RUNNER, INC. - 000267 (base 16) NODE RUNNER, INC. - 2202 N. FORBES BLVD. - TUCSON AZ 85745 - UNITED STATES - - 00-02-68 (hex) Harris Government Communications - 000268 (base 16) Harris Government Communications - Systems Division - P.O. Box 37 MS: 1-5856 - Melbourne FL 32902 - UNITED STATES - - 00-02-69 (hex) Nadatel Co., Ltd - 000269 (base 16) Nadatel Co., Ltd - 9F CoWell Bldg, 66-1 Banpo-Dong - Seocho-Gu, Seoul, - KOREA 137-040 - KOREA, REPUBLIC OF - - 00-02-6A (hex) Cocess Telecom Co., Ltd. - 00026A (base 16) Cocess Telecom Co., Ltd. - Research & Development Dept. - 43, Yoido-Dong, Youngdeungpo-Ku - Seoul Seoul KOREA - KOREA, REPUBLIC OF - - 00-02-6B (hex) BCM Computers Co., Ltd. - 00026B (base 16) BCM Computers Co., Ltd. - 6F-6, No. 66, Sec 2, - Nan Kan Rd., Lu-Chu Hsing, Tao Yuan - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-6C (hex) Philips CFT - 00026C (base 16) Philips CFT - Building SAN 6 - P.O. Box 218 5600 MD Eindhoven - The - NETHERLANDS - - 00-02-6D (hex) Adept Telecom - 00026D (base 16) Adept Telecom - Avenue de l'Europe - BP 161 F-71204 Le Creusot Cedex - FRANCE - - 00-02-6E (hex) NeGeN Access, Inc. - 00026E (base 16) NeGeN Access, Inc. - 33 Boston Post Rd. West - Suite 360 - Marlborough MA 01752 - UNITED STATES - - 00-02-6F (hex) Senao International Co., Ltd. - 00026F (base 16) Senao International Co., Ltd. - 2F, No. 531, Chung-Cheng Rd., - Hsin-Tien City, Taipei County, - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-02-70 (hex) Crewave Co., Ltd. - 000270 (base 16) Crewave Co., Ltd. - F7, Pureun Bldg., 28-1 - Jamwon-dong, Seocho-gu - Seoul KOREA 137-030 - KOREA, REPUBLIC OF - - 00-02-71 (hex) Zhone Technologies - 000271 (base 16) Zhone Technologies - 7001 Oakport Street - Oakland CA 94621 - UNITED STATES - - 00-02-72 (hex) CC&C Technologies, Inc. - 000272 (base 16) CC&C Technologies, Inc. - 8F, 150, Chien I Rd., Chung Ho City, - Taipei County 235 Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-73 (hex) Coriolis Networks - 000273 (base 16) Coriolis Networks - 330 Codmanhill Road - Boxborough MA 01719 - UNITED STATES - - 00-02-74 (hex) Tommy Technologies Corp. - 000274 (base 16) Tommy Technologies Corp. - #407 Heehoon Bld - 110-1 Kuro-dong, Kuro-ku - Seoul Seoul KOREA - KOREA, REPUBLIC OF - - 00-02-75 (hex) SMART Technologies, Inc. - 000275 (base 16) SMART Technologies, Inc. - 3636 Research Road NW - Calgary, Alberta T2L1Y1 - CANADA - - 00-02-76 (hex) Primax Electronics Ltd. - 000276 (base 16) Primax Electronics Ltd. - No. 669, Ruey Kuang Road, Neihu - Taipei Taiwan, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-77 (hex) Cash Systemes Industrie - 000277 (base 16) Cash Systemes Industrie - Technoparc Epsilon - Rd 100 83700 St Raphael - FRANCE - - 00-02-78 (hex) Samsung Electro-Mechanics Co., Ltd. - 000278 (base 16) Samsung Electro-Mechanics Co., Ltd. - 314, Mae-tan-dong, - Pai-dal-gu, Kyoung-gi-do, - Suwon Suwon KOREA - KOREA, REPUBLIC OF - - 00-02-79 (hex) Control Applications, Ltd. - 000279 (base 16) Control Applications, Ltd. - 3 Tevuot Haarets St. - Tel-Aviv 69546 - ISRAEL - - 00-02-7A (hex) IOI Technology Corporation - 00027A (base 16) IOI Technology Corporation - 4F-3 No. 125 Lane 235, - Pao Chiao Road Hsin Tien City, - Taipei TAIWAN, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-7B (hex) Amplify Net, Inc. - 00027B (base 16) Amplify Net, Inc. - 47381 Bayside Parkway - Fremont CA 94538 - UNITED STATES - - 00-02-7C (hex) Trilithic, Inc. - 00027C (base 16) Trilithic, Inc. - 9202 E. 33rd Street - Indianapolis IN 46235 - UNITED STATES - - 00-02-7D (hex) CISCO SYSTEMS, INC. - 00027D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-7E (hex) CISCO SYSTEMS, INC. - 00027E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-7F (hex) ask-technologies.com - 00027F (base 16) ask-technologies.com - 36 Wellington Business Park - Dukes Ride, Crowthorne Berkshire RG45 6L - UNITED KINGDOM - - 00-02-80 (hex) Mu Net, Inc. - 000280 (base 16) Mu Net, Inc. - 442 Marrett Road - Suite 9 - Lexington MA 02421 - UNITED STATES - - 00-02-81 (hex) Madge Ltd. - 000281 (base 16) Madge Ltd. - Madge House - Priors Way - Maindenhead Berkshire SL6 2HP - UNITED KINGDOM - - 00-02-82 (hex) ViaClix, Inc. - 000282 (base 16) ViaClix, Inc. - 1400 Dell Ave., Suite B - Campbell CA 95008 - UNITED STATES - - 00-02-83 (hex) Spectrum Controls, Inc. - 000283 (base 16) Spectrum Controls, Inc. - PO Box 5533 - Bellevue WA 98006 - UNITED STATES - - 00-02-84 (hex) AREVA T&D - 000284 (base 16) AREVA T&D - Avenue de Figuieres BP 75 - 34975 LATTES Cedex - FRANCE - - 00-02-85 (hex) Riverstone Networks - 000285 (base 16) Riverstone Networks - 5200 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-02-86 (hex) Occam Networks - 000286 (base 16) Occam Networks - 4183 State Street - Santa Barbara CA 93110 - UNITED STATES - - 00-02-87 (hex) Adapcom - 000287 (base 16) Adapcom - 172-A Component Drive - San Jose CA 95131 - UNITED STATES - - 00-02-88 (hex) GLOBAL VILLAGE COMMUNICATION - 000288 (base 16) GLOBAL VILLAGE COMMUNICATION - 1144 EAST ARQUES AVE. - SUNNYVALE CA 94086 - UNITED STATES - - 00-02-89 (hex) DNE Technologies - 000289 (base 16) DNE Technologies - 50 Barnes Park N - Wallingford CT 06492 - UNITED STATES - - 00-02-8A (hex) Ambit Microsystems Corporation - 00028A (base 16) Ambit Microsystems Corporation - 5F-1, 5 Hsin-An Road Hsinchu, - Science Based Industrial Park, - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-02-8B (hex) VDSL Systems OY - 00028B (base 16) VDSL Systems OY - Tekniikantie 12 - 02 150 Espoo - FINLAND - - 00-02-8C (hex) Micrel-Synergy Semiconductor - 00028C (base 16) Micrel-Synergy Semiconductor - 3250 Scott Boulevard - Santa Clara CA 95054 - UNITED STATES - - 00-02-8D (hex) Movita Technologies, Inc. - 00028D (base 16) Movita Technologies, Inc. - No. 26 Wu-Chuan 7th Road, - Wu-Ku Industrial Park - Taipei Taiwan, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-8E (hex) Rapid 5 Networks, Inc. - 00028E (base 16) Rapid 5 Networks, Inc. - 180 Baytech Drive - San Jose CA 95134-2302 - UNITED STATES - - 00-02-8F (hex) Globetek, Inc. - 00028F (base 16) Globetek, Inc. - 1607 Akron Peninsula Rd. - Suite 103 - Akron OH 44313-5190 - UNITED STATES - - 00-02-90 (hex) Woorigisool, Inc. - 000290 (base 16) Woorigisool, Inc. - Yoopoong Bldg. - 1595-1, Bongchum-7dong, - Seoul Seoul KOREA - KOREA, REPUBLIC OF - - 00-02-91 (hex) Open Network Co., Ltd. - 000291 (base 16) Open Network Co., Ltd. - Seishin Bldg., 2-5-10 Shinjuku - Shinjuku-ku, Tokyo - JAPAN 160-0022 - JAPAN - - 00-02-92 (hex) Logic Innovations, Inc. - 000292 (base 16) Logic Innovations, Inc. - 6205 Lusk Blvd. - San Diego CA 92121-2731 - UNITED STATES - - 00-02-93 (hex) Solid Data Systems - 000293 (base 16) Solid Data Systems - 2945 Oakmead Village Court - Santa Clara CA 95051 - UNITED STATES - - 00-02-94 (hex) Tokyo Sokushin Co., Ltd. - 000294 (base 16) Tokyo Sokushin Co., Ltd. - 5-16-12 Nishi-Nippori - Arakawa-ku, Tokyo 116-0013 - JAPAN - - 00-02-95 (hex) IP.Access Limited - 000295 (base 16) IP.Access Limited - Melbourn Science Park - Cambridge Road, Melbourn Royston, Hartfo - SG8 6EE SG8 6EE U.K. - UNITED KINGDOM - - 00-02-96 (hex) Lectron Co,. Ltd. - 000296 (base 16) Lectron Co,. Ltd. - 9F, No.171, Sec. 2, Tatung Rd., - Hsichih City, Taipei Hsien 221, - Taiwan Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-97 (hex) C-COR.net - 000297 (base 16) C-COR.net - 60 Decibel Road - BMS Engineering - State College PA 16801 - UNITED STATES - - 00-02-98 (hex) Broadframe Corporation - 000298 (base 16) Broadframe Corporation - 5828 Moonstone Ave. - Alta Loma CA 91701 - UNITED STATES - - 00-02-99 (hex) Apex, Inc. - 000299 (base 16) Apex, Inc. - 9911 Willows Rd. N.E. - Redmond WA 95052 - UNITED STATES - - 00-02-9A (hex) Storage Apps - 00029A (base 16) Storage Apps - 3 Princess Road - Lawrenceville NJ 08648 - UNITED STATES - - 00-02-9B (hex) Kreatel Communications AB - 00029B (base 16) Kreatel Communications AB - Teknikringen 4C - SE-58330 Linkoping - SWEDEN - - 00-02-9C (hex) 3COM - 00029C (base 16) 3COM - 405 SPRING HILL ROAD - SHARON NH 03458 - UNITED STATES - - 00-02-9D (hex) Merix Corp. - 00029D (base 16) Merix Corp. - Jin-Su Building, 49-16 - Machum-Dong, Song-Pa-ku - Seoul Seoul KOREA - KOREA, REPUBLIC OF - - 00-02-9E (hex) Information Equipment Co., Ltd. - 00029E (base 16) Information Equipment Co., Ltd. - 740-1 Eaho Bldg., Yeok Sam-Dong - Kangnam-ku - Seoul Korea #135-080 - KOREA, REPUBLIC OF - - 00-02-9F (hex) L-3 Communication Aviation Recorders - 00029F (base 16) L-3 Communication Aviation Recorders - P.O. Box 3041 - Sarasota FL 34230 - UNITED STATES - - 00-02-A0 (hex) Flatstack Ltd. - 0002A0 (base 16) Flatstack Ltd. - 1112 Budapest - Peterhegyi UT 98 - HUNGARY - - 00-02-A1 (hex) World Wide Packets - 0002A1 (base 16) World Wide Packets - PO Box 14645 - Spokane WA 99214 - UNITED STATES - - 00-02-A2 (hex) Hilscher GmbH - 0002A2 (base 16) Hilscher GmbH - Rheinstraße 15 - 65795 Hattersheim - GERMANY - - 00-02-A3 (hex) ABB Switzerland Ltd, Power Systems - 0002A3 (base 16) ABB Switzerland Ltd, Power Systems - Bruggerstrasse 72 - CH-5400 - Baden - SWITZERLAND - - 00-02-A4 (hex) AddPac Technology Co., Ltd. - 0002A4 (base 16) AddPac Technology Co., Ltd. - 3F Jeoung Am Bldg., 769-12 - Yeoksam-dong, Kangnam-gu, - Seoul Seoul Korea - KOREA, REPUBLIC OF - - 00-02-A5 (hex) Hewlett-Packard Company - 0002A5 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-02-A6 (hex) Effinet Systems Co., Ltd. - 0002A6 (base 16) Effinet Systems Co., Ltd. - Yugong Bldg. 502 - 1144-1, Sanbon-Dong Kunpo-shi, Kyonggi-D - Korea - KOREA, REPUBLIC OF - - 00-02-A7 (hex) Vivace Networks - 0002A7 (base 16) Vivace Networks - 2730 Orchard Parkway - San Jose CA 95134 - UNITED STATES - - 00-02-A8 (hex) Air Link Technology - 0002A8 (base 16) Air Link Technology - Bethel Bldg. 303 - 324-1 Yangjee-Dong, Seocho-Gu - Seoul KOREA 137-130 - KOREA, REPUBLIC OF - - 00-02-A9 (hex) RACOM, s.r.o. - 0002A9 (base 16) RACOM, s.r.o. - Mirova 1283, Nove Mesto na Morave - 592 31 Czech republic - CZECH REPUBLIC - - 00-02-AA (hex) PLcom Co., Ltd. - 0002AA (base 16) PLcom Co., Ltd. - Hosung B/D, #1083-1, Hogye-Dong - Dongan-Ku, Anyang-City - South Korea - KOREA, REPUBLIC OF - - 00-02-AB (hex) CTC Union Technologies Co., Ltd. - 0002AB (base 16) CTC Union Technologies Co., Ltd. - 8F No. 60 Zhouzi St. - Neihu Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-02-AC (hex) 3PAR data - 0002AC (base 16) 3PAR data - 4209 Technology Drive - Fremont CA 94538 - UNITED STATES - - 00-02-AD (hex) HOYA Corporation - 0002AD (base 16) HOYA Corporation - 2-7-5 Naka-Ochiai, Shinjuku-ku, - Tokyo 161-8525 - JAPAN - - 00-02-AE (hex) Scannex Electronics Ltd. - 0002AE (base 16) Scannex Electronics Ltd. - Unit 8 English Business Park - English Close - Hove BN3 7ET - UNITED KINGDOM - - 00-02-AF (hex) TeleCruz Technology, Inc. - 0002AF (base 16) TeleCruz Technology, Inc. - 2391 Qume Dr. - San Jose CA 95131 - UNITED STATES - - 00-02-B0 (hex) Hokubu Communication & Industrial Co., Ltd. - 0002B0 (base 16) Hokubu Communication & Industrial Co., Ltd. - Fushiogami-aza-oki 27-1 - Fukushima 960-8514 - JAPAN - - 00-02-B1 (hex) Anritsu, Ltd. - 0002B1 (base 16) Anritsu, Ltd. - Rutherford Close - Stevenage, Herts England, SG12EF - UNITED KINGDOM - UNITED KINGDOM - - 00-02-B2 (hex) Cablevision - 0002B2 (base 16) Cablevision - 420 Crossways Park Drive West - Woodbury NY 11787 - UNITED STATES - - 00-02-B3 (hex) Intel Corporation - 0002B3 (base 16) Intel Corporation - M/S: JF3-420 - 2111 N.E. 25th Ave. - Hillsboro OR 97124 - UNITED STATES - - 00-02-B4 (hex) DAPHNE - 0002B4 (base 16) DAPHNE - 101 Chaussee De Binche - 7000 Hons - BELGIUM - - 00-02-B5 (hex) Avnet, Inc. - 0002B5 (base 16) Avnet, Inc. - 2211 S. 47th Street - Phoenix AZ 85034 - UNITED STATES - - 00-02-B6 (hex) Acrosser Technology Co., Ltd. - 0002B6 (base 16) Acrosser Technology Co., Ltd. - No. 116-2 Guang-Fu Rd. - Sea 1, San Chung, - Taipei Taipei R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-B7 (hex) Watanabe Electric Industry Co., Ltd. - 0002B7 (base 16) Watanabe Electric Industry Co., Ltd. - 6-16-19, Jingumae, Shibuya-ku - Tokyo 150-0001, - JAPAN - - 00-02-B8 (hex) WHI KONSULT AB - 0002B8 (base 16) WHI KONSULT AB - Scheelegatan 11 - 12040 Arsta - Stockholm SE-112 28 - SWEDEN - - 00-02-B9 (hex) CISCO SYSTEMS, INC. - 0002B9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-BA (hex) CISCO SYSTEMS, INC. - 0002BA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-BB (hex) Continuous Computing Corp - 0002BB (base 16) Continuous Computing Corp - 9380 Carroll Park Drive - San Diego CA 92121 - UNITED STATES - - 00-02-BC (hex) LVL 7 Systems, Inc. - 0002BC (base 16) LVL 7 Systems, Inc. - 13000 Weston Pkwy - Suite 105 - Cary NC 27513 - UNITED STATES - - 00-02-BD (hex) Bionet Co., Ltd. - 0002BD (base 16) Bionet Co., Ltd. - 3F, Medison Venture Tower, - 997-4, Daechi-dong, Kangnam-gu, Seoul, - KOREA - KOREA, REPUBLIC OF - - 00-02-BE (hex) Totsu Engineering, Inc. - 0002BE (base 16) Totsu Engineering, Inc. - 5-16-20 Roppongi Minato-ku - Zip: 106-0032 - Tokyo 106-8551 - JAPAN - - 00-02-BF (hex) dotRocket, Inc. - 0002BF (base 16) dotRocket, Inc. - 1901 S. Bascom, Suite 300 - Campbell CA 95008 - UNITED STATES - - 00-02-C0 (hex) Bencent Tzeng Industry Co., Ltd. - 0002C0 (base 16) Bencent Tzeng Industry Co., Ltd. - 3rd fl., No. 3 Ruey Kuang Rd., - Nei Hu Dist., Taipei 114 - Taiwan Taiwan R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-02-C1 (hex) Innovative Electronic Designs, Inc. - 0002C1 (base 16) Innovative Electronic Designs, Inc. - 9701 Taylorsville Rd. - Louisville KY 40299 - UNITED STATES - - 00-02-C2 (hex) Net Vision Telecom - 0002C2 (base 16) Net Vision Telecom - #206 Software Support Center - 48 Jang-Dong Yusong-Gu, Taejon - 305-343 Rep. of Korea - KOREA, REPUBLIC OF - - 00-02-C3 (hex) Arelnet Ltd. - 0002C3 (base 16) Arelnet Ltd. - 3 Hayarden St. - Yavne 70600 - ISRAEL - - 00-02-C4 (hex) Vector International BVBA - 0002C4 (base 16) Vector International BVBA - Technologielaan 4 - 3001 Leuven - BELGIUM - - 00-02-C5 (hex) Evertz Microsystems Ltd. - 0002C5 (base 16) Evertz Microsystems Ltd. - 5292 John Lucas Drive - Burlington - Ontario L7L 5Z9 - CANADA - - 00-02-C6 (hex) Data Track Technology PLC - 0002C6 (base 16) Data Track Technology PLC - 153 Somerford Road - Christchurch, Dorset BH23 3TY, - UNITED KINGDOM - UNITED KINGDOM - - 00-02-C7 (hex) ALPS ELECTRIC Co., Ltd. - 0002C7 (base 16) ALPS ELECTRIC Co., Ltd. - 1-2-1, Okinouchi, Sama-City, - Fukushima-pref, 976-8501, - JAPAN - - 00-02-C8 (hex) Technocom Communications Technology (pte) Ltd - 0002C8 (base 16) Technocom Communications Technology (pte) Ltd - 189 Kaki Buckit Avenue 1 - #03-03 Shun Li Industrial Park - Singapore 416029 - SINGAPORE - - 00-02-C9 (hex) Mellanox Technologies - 0002C9 (base 16) Mellanox Technologies - 350 Oakmead Parkway - Sunnyvale CA 94085 - UNITED STATES - - 00-02-CA (hex) EndPoints, Inc. - 0002CA (base 16) EndPoints, Inc. - 4 Preston Court - Bedford MA 01730 - UNITED STATES - - 00-02-CB (hex) TriState Ltd. - 0002CB (base 16) TriState Ltd. - Shinonaga Blg. 4-11-19 Hokko-cho - Tomakomai-shi, Hokkaido - 053-0852 053-0852 - JAPAN - - 00-02-CC (hex) M.C.C.I - 0002CC (base 16) M.C.C.I - 3520 Krums Corners Rd. - Ithaca NY 14850 - UNITED STATES - - 00-02-CD (hex) TeleDream, Inc. - 0002CD (base 16) TeleDream, Inc. - Shinhwa Bldg., 940-10 Daechi-Dong - Kangnam-ku, Seoul 135-280 - KOREA, REPUBLIC OF - - 00-02-CE (hex) FoxJet, Inc. - 0002CE (base 16) FoxJet, Inc. - 2016 E. Randal Mill Rd. #409 - Arlington TX 76011-8223 - UNITED STATES - - 00-02-CF (hex) ZyGate Communications, Inc. - 0002CF (base 16) ZyGate Communications, Inc. - 2F, No.48, Lung-Chin Road - Lung-Tan, Tanyuan, - TAIWAN, PROVINCE OF CHINA - - 00-02-D0 (hex) Comdial Corporation - 0002D0 (base 16) Comdial Corporation - 1180 Seminole Trail - Charlottesville VA 22901 - UNITED STATES - - 00-02-D1 (hex) Vivotek, Inc. - 0002D1 (base 16) Vivotek, Inc. - 5F-1, 168-1, Lien-Chen Rd, - Chung-Ho, Taipei County, - TAIWAN, PROVINCE OF CHINA - - 00-02-D2 (hex) Workstation AG - 0002D2 (base 16) Workstation AG - Schaffhauserstrasse 55 - CH-8152 Glattbrugg - SWITZERLAND - - 00-02-D3 (hex) NetBotz, Inc. - 0002D3 (base 16) NetBotz, Inc. - 110044 Research Blvd. - Suite C-100 - Austin TX 78759 - UNITED STATES - - 00-02-D4 (hex) PDA Peripherals, Inc. - 0002D4 (base 16) PDA Peripherals, Inc. - 205 Orange St. - Third Floor - New Haven CT 06510 - UNITED STATES - - 00-02-D5 (hex) ACR - 0002D5 (base 16) ACR - Cardoulines B2 - 1360 rte Dolinis 06560 Valbonne - FRANCE - - 00-02-D6 (hex) NICE Systems - 0002D6 (base 16) NICE Systems - 8 Hapnina St., POB 690 - Ra'Anana 43107 - ISRAEL - - 00-02-D7 (hex) EMPEG Ltd - 0002D7 (base 16) EMPEG Ltd - 1 Signet Court - Swann's Road Cambridge, UK - CB5 8LA - UNITED KINGDOM - - 00-02-D8 (hex) BRECIS Communications Corporation - 0002D8 (base 16) BRECIS Communications Corporation - 2025 Gateway Place, Suite 132 - San Jose CA 95110 - UNITED STATES - - 00-02-D9 (hex) Reliable Controls - 0002D9 (base 16) Reliable Controls - 120 Hallowell Road - Victoria, B.C. V9A 7K2 - CANADA - - 00-02-DA (hex) ExiO Communications, Inc. - 0002DA (base 16) ExiO Communications, Inc. - 2362 Qume Drive - Suite C - San Jose CA 95131 - UNITED STATES - - 00-02-DB (hex) NETSEC - 0002DB (base 16) NETSEC - 13505 Dulles Technology Drive - Suite 1 - Hernandon VA 20171 - UNITED STATES - - 00-02-DC (hex) Fujitsu General Limited - 0002DC (base 16) Fujitsu General Limited - 1116, Suenaga, Takatsu-Ku, - Kawasaki-City, Kanagawa-Pref., - 213-8502 - JAPAN - - 00-02-DD (hex) Bromax Communications, Ltd. - 0002DD (base 16) Bromax Communications, Ltd. - No. 20 Kuang Fu Road, - Hsin Chu Industrial Park, Hu Kou, - Hsin Chu 303 - TAIWAN, PROVINCE OF CHINA - - 00-02-DE (hex) Astrodesign, Inc. - 0002DE (base 16) Astrodesign, Inc. - 2-22-12 Kamikodana Ka - Nakaharaku, Kawasai-City - Kanagawa - JAPAN - - 00-02-DF (hex) Net Com Systems, Inc. - 0002DF (base 16) Net Com Systems, Inc. - 15-3, Yoido-Dong, - Yeoungdongpo-ku, - Seoul - KOREA, REPUBLIC OF - - 00-02-E0 (hex) ETAS GmbH - 0002E0 (base 16) ETAS GmbH - Borsigstraße 10 - D70469 Stuttgart - GERMANY - - 00-02-E1 (hex) Integrated Network Corporation - 0002E1 (base 16) Integrated Network Corporation - 757 Route 202/206 - Bridgewater NJ 08807 - UNITED STATES - - 00-02-E2 (hex) NDC Infared Engineering - 0002E2 (base 16) NDC Infared Engineering - 5314 N. Irwindale Ave. - Irwindale CA 91706 - UNITED STATES - - 00-02-E3 (hex) LITE-ON Communications, Inc. - 0002E3 (base 16) LITE-ON Communications, Inc. - 736 S. Hillview Drive - Milpitas CA 95035 - UNITED STATES - - 00-02-E4 (hex) JC HYUN Systems, Inc. - 0002E4 (base 16) JC HYUN Systems, Inc. - Shinbong Bldg, 736-6, - Yoksam-Dong, Kangnam-Ku, - Seoul (135-080) - KOREA, REPUBLIC OF - - 00-02-E5 (hex) Timeware Ltd. - 0002E5 (base 16) Timeware Ltd. - Brookfield Grange - 79 Falinge Rd, Rockdale - Lancs 042 GLB - UNITED KINGDOM - - 00-02-E6 (hex) Gould Instrument Systems, Inc. - 0002E6 (base 16) Gould Instrument Systems, Inc. - 8333 Rockside Road - Valley View OH 44125 - UNITED STATES - - 00-02-E7 (hex) CAB GmbH & Co KG - 0002E7 (base 16) CAB GmbH & Co KG - Wilhelm-Schickard-Str 14 - 76131 Karlsruhe - GERMANY - - 00-02-E8 (hex) E.D.&A. - 0002E8 (base 16) E.D.&A. - Energielaan 16 - IZ Bosduin 2950 Kapellen - BELGIUM - - 00-02-E9 (hex) CS Systemes De Securite - C3S - 0002E9 (base 16) CS Systemes De Securite - C3S - 23, rue de Schwobsheim - 67600 Baldenheim - FRANCE - - 00-02-EA (hex) Focus Enhancements - 0002EA (base 16) Focus Enhancements - 1370 Dell Ave. - Campbell CA 95008 - UNITED STATES - - 00-02-EB (hex) Pico Communications - 0002EB (base 16) Pico Communications - 20085 Stevens Creek Blvd. - Suite #100 - Cupertino CA 95014 - UNITED STATES - - 00-02-EC (hex) Maschoff Design Engineering - 0002EC (base 16) Maschoff Design Engineering - 1325 Kenilworth Drive - Woodbury MN 55125 - UNITED STATES - - 00-02-ED (hex) DXO Telecom Co., Ltd. - 0002ED (base 16) DXO Telecom Co., Ltd. - 8F, 300-11, Yumgok-Dong, - Seocho-Ku, Seoul 137-789 - KOREA, REPUBLIC OF - - 00-02-EE (hex) Nokia Danmark A/S - 0002EE (base 16) Nokia Danmark A/S - Frederikskaj, Copenhagen V - DK-1790 - DENMARK - - 00-02-EF (hex) CCC Network Systems Group Ltd. - 0002EF (base 16) CCC Network Systems Group Ltd. - 13 Farnborough Business Centre - Eelmoor Road, Farnborough, Hants, GU14 7 - ENGLAND - UNITED KINGDOM - - 00-02-F0 (hex) AME Optimedia Technology Co., Ltd. - 0002F0 (base 16) AME Optimedia Technology Co., Ltd. - 17F-2, 79 Hsin Tai Wu Road, Sec. 1, - Hsi-Chih, Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-02-F1 (hex) Pinetron Co., Ltd. - 0002F1 (base 16) Pinetron Co., Ltd. - Bldg. #1599-11, - Seocho-Dong, Seocho-Ku, - Seoul 137-073 - KOREA, REPUBLIC OF - - 00-02-F2 (hex) eDevice, Inc. - 0002F2 (base 16) eDevice, Inc. - 420 Lexington Avenue - Suite 2300 - New York NY 10170 - UNITED STATES - - 00-02-F3 (hex) Media Serve Co., Ltd. - 0002F3 (base 16) Media Serve Co., Ltd. - Dongsung Bldg. #17-8, Youido-dong, - Youngdeoungpo-ku, - Seoul - KOREA, REPUBLIC OF - - 00-02-F4 (hex) PCTEL, Inc. - 0002F4 (base 16) PCTEL, Inc. - 1331 California Circle - Milpitas CA 95035 - UNITED STATES - - 00-02-F5 (hex) VIVE Synergies, Inc. - 0002F5 (base 16) VIVE Synergies, Inc. - 30 West Beaver Creek Road, Unit 101 - Richmond Hill, Ontario - L4B 3K1 - CANADA - - 00-02-F6 (hex) Equipe Communications - 0002F6 (base 16) Equipe Communications - 100 Nagog Park - Acton MA 01720 - UNITED STATES - - 00-02-F7 (hex) ARM - 0002F7 (base 16) ARM - 110, Fulbourn Road - Cherry Hinton Cambridge - CB1 9NJ - UNITED KINGDOM - - 00-02-F8 (hex) SEAKR Engineering, Inc. - 0002F8 (base 16) SEAKR Engineering, Inc. - 12847 E. Peakview Ave. - Englewood CO 80111 - UNITED STATES - - 00-02-F9 (hex) MIMOS Berhad - 0002F9 (base 16) MIMOS Berhad - Technology Park Malaysia - Kuala Lumpur 57000 - MALAYSIA - - 00-02-FA (hex) DX Antenna Co., Ltd. - 0002FA (base 16) DX Antenna Co., Ltd. - 2-15 Hamazaki-Dori, - Hyogo-ku, Kobe - JAPAN - - 00-02-FB (hex) Baumuller Aulugen-Systemtechnik GmbH - 0002FB (base 16) Baumuller Aulugen-Systemtechnik GmbH - Ostendsts. 84 - D-90482 Nuruberg - GERMANY - - 00-02-FC (hex) CISCO SYSTEMS, INC. - 0002FC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-FD (hex) CISCO SYSTEMS, INC. - 0002FD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-02-FE (hex) Viditec, Inc. - 0002FE (base 16) Viditec, Inc. - 520 Central Parkway E. - Suite 115 - Plano TX 75074 - UNITED STATES - - 00-02-FF (hex) Handan BroadInfoCom - 0002FF (base 16) Handan BroadInfoCom - 5th Fl. Shinsung Plaza #697-11 - Yeogsam-dong, Kangnam-gu - Seoul - KOREA, REPUBLIC OF - - 00-03-00 (hex) Barracuda Networks, Inc. - 000300 (base 16) Barracuda Networks, Inc. - 3175 S. Winchester Blvd - Campbell CA 95008 - UNITED STATES - - 00-03-01 (hex) EXFO - 000301 (base 16) EXFO - 400 Godin Avenue - St-Laurent, Quebec - Quebec G1M 2K2 - CANADA - - 00-03-02 (hex) Charles Industries, Ltd. - 000302 (base 16) Charles Industries, Ltd. - 5600 Apollo Drive - Rolling Meadows IL 60008 - UNITED STATES - - 00-03-03 (hex) JAMA Electronics Co., Ltd. - 000303 (base 16) JAMA Electronics Co., Ltd. - 10F, No. 222-1, Sec. 3 - Ta-Tung Rd., Hsi-Chih - Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-03-04 (hex) Pacific Broadband Communications - 000304 (base 16) Pacific Broadband Communications - 3103 North First St. - San Jose CA 95134 - UNITED STATES - - 00-03-05 (hex) MSC Vertriebs GmbH - 000305 (base 16) MSC Vertriebs GmbH - Design Center Aachen - Pascalstraße 21 - AACHEN D-52076 - GERMANY - - 00-03-06 (hex) Fusion In Tech Co., Ltd. - 000306 (base 16) Fusion In Tech Co., Ltd. - 6Fl, Daeyoon Bldg. 1688-5, Seocho-dong - Seocho-ku, - Seoul, - KOREA, REPUBLIC OF - - 00-03-07 (hex) Secure Works, Inc. - 000307 (base 16) Secure Works, Inc. - 11 Executive Drive - Suite 200 - Atlanta GA 30329 - UNITED STATES - - 00-03-08 (hex) AM Communications, Inc. - 000308 (base 16) AM Communications, Inc. - 100 Commerce Blvd. - Quakertown PA 18951 - UNITED STATES - - 00-03-09 (hex) Texcel Technology PLC - 000309 (base 16) Texcel Technology PLC - Thames Road - Crayford Kent DA1 4SB - ENGLAND - UNITED KINGDOM - - 00-03-0A (hex) Argus Technologies - 00030A (base 16) Argus Technologies - 8F, No. 183, Kang Chien Rd. - 114 - TAIWAN, PROVINCE OF CHINA - - 00-03-0B (hex) Hunter Technology, Inc. - 00030B (base 16) Hunter Technology, Inc. - 1408, Woolim e-biz Center, - 170-5, Guro-3dong, Guro-gu, - Seoul 135-270 - KOREA, REPUBLIC OF - - 00-03-0C (hex) Telesoft Technologies Ltd. - 00030C (base 16) Telesoft Technologies Ltd. - Observatory House, Stour Park, - Blandforum, Dorset, DT11 9LQ, - UNITED KINGDOM - - 00-03-0D (hex) Uniwill Computer Corp. - 00030D (base 16) Uniwill Computer Corp. - No. 24, Pei Yuan Rd., Chung - Li Industrial Park, Chung - Li City - TAIWAN, PROVINCE OF CHINA - - 00-03-0E (hex) Core Communications Co., Ltd. - 00030E (base 16) Core Communications Co., Ltd. - 3F Shopping Center Bd. of - SSang Young Hwang-geum APT, #253 Mapo-Do - Seoul (121-050) (121-050) - KOREA, REPUBLIC OF - - 00-03-0F (hex) Digital China (Shanghai) Networks Ltd. - 00030F (base 16) Digital China (Shanghai) Networks Ltd. - 602-23, Haitai Building, 351 Guo Shoujin - Pudong New District, - Shanghai - CHINA - - 00-03-10 (hex) E-Globaledge Corporation - 000310 (base 16) E-Globaledge Corporation - 7F Nakameguro GT Tower - 2-1-1 Kamimeguro - Meduro-ku, Tokyo 153-0051 - JAPAN - - 00-03-11 (hex) Micro Technology Co., Ltd. - 000311 (base 16) Micro Technology Co., Ltd. - Suehiro Bldg. - 1-2, Soto Kanda 5 Chome Chiyoda-ku, Toky - 101-0021 - JAPAN - - 00-03-12 (hex) TR-Systemtechnik GmbH - 000312 (base 16) TR-Systemtechnik GmbH - Eglishalde 6 - D-78647 Trossingen - GERMANY - - 00-03-13 (hex) Access Media SPA - 000313 (base 16) Access Media SPA - Via delle Industrie, 4/g - 24035 LALLIO (BG) - ITALY - - 00-03-14 (hex) Teleware Network Systems - 000314 (base 16) Teleware Network Systems - #7806 7th Dongil Technotown, - Kinanyang Dong 823, Dongahn Gu, Anyang C - 431-062 - KOREA, REPUBLIC OF - - 00-03-15 (hex) Cidco Incorporated - 000315 (base 16) Cidco Incorporated - 220 Cochrane Circle - Morgan Hill CA 95037 - UNITED STATES - - 00-03-16 (hex) Nobell Communications, Inc. - 000316 (base 16) Nobell Communications, Inc. - 3410 Far West Blvd., Suite 240 - Austin TX 78731 - UNITED STATES - - 00-03-17 (hex) Merlin Systems, Inc. - 000317 (base 16) Merlin Systems, Inc. - 3900 New Park Mall Rd. - 3rd Floor - Newark CA 94560 - UNITED STATES - - 00-03-18 (hex) Cyras Systems, Inc. - 000318 (base 16) Cyras Systems, Inc. - 47100 Bayside Parkway - Fremont CA 94538 - UNITED STATES - - 00-03-19 (hex) Infineon AG - 000319 (base 16) Infineon AG - P.O. Box 800949 - D-81609 Munich - GERMANY - - 00-03-1A (hex) Beijing Broad Telecom Ltd., China - 00031A (base 16) Beijing Broad Telecom Ltd., China - P.O. Box #147 - Beijing University of Posts and Telecom - Beijing 100876 - CHINA - - 00-03-1B (hex) Cellvision Systems, Inc. - 00031B (base 16) Cellvision Systems, Inc. - 3F-1, 75, Hsin Taiwu Road, Sec. 1 - Hsichih, Taipei, - TAIWAN, PROVINCE OF CHINA - - 00-03-1C (hex) Svenska Hardvarufabriken AB - 00031C (base 16) Svenska Hardvarufabriken AB - Ole Romersvag 16, Ideon - SE-223 70 Lund - SWEDEN - - 00-03-1D (hex) Taiwan Commate Computer, Inc. - 00031D (base 16) Taiwan Commate Computer, Inc. - 8F, No. 94, Sec 1, - Shin Tai Wu Rd. Hsi Chih, Taipei Hsien, - TAIWAN, PROVINCE OF CHINA - - 00-03-1E (hex) Optranet, Inc. - 00031E (base 16) Optranet, Inc. - 7041 Koll Center Pkwy - Suite 135 - Pleasanton CA 94566 - UNITED STATES - - 00-03-1F (hex) Condev Ltd. - 00031F (base 16) Condev Ltd. - 200-1626 West 2nd Ave. - Vancouver, B.C. V6J 1H4 - CANADA - - 00-03-20 (hex) Xpeed, Inc. - 000320 (base 16) Xpeed, Inc. - 99 W. Tasman Drive - Suite 110 - San Jose CA 95134 - UNITED STATES - - 00-03-21 (hex) Reco Research Co., Ltd. - 000321 (base 16) Reco Research Co., Ltd. - No. 47-1, Sec. 2, - Kuang Fu Rd.,San Chung City, Taipei, - TAIWAN, PROVINCE OF CHINA - - 00-03-22 (hex) IDIS Co., Ltd. - 000322 (base 16) IDIS Co., Ltd. - 7th Floor, 646-7 Yuksam-Dong, - Kangnam-Gu, Seoul 135-280, - KOREA, REPUBLIC OF - - 00-03-23 (hex) Cornet Technology, Inc. - 000323 (base 16) Cornet Technology, Inc. - 6800 Versar Center, Suite 216 - Springfield VA 22151-4147 - UNITED STATES - - 00-03-24 (hex) SANYO Consumer Electronics Co., Ltd. - 000324 (base 16) SANYO Consumer Electronics Co., Ltd. - 7-101 Tachikawa-cho - Tottori City 680-8634 - JAPAN - - 00-03-25 (hex) Arima Computer Corp. - 000325 (base 16) Arima Computer Corp. - 6th Fl., No. 327, - Sung-lung Rd., Taipei City, - TAIWAN, PROVINCE OF CHINA - - 00-03-26 (hex) Iwasaki Information Systems Co., Ltd. - 000326 (base 16) Iwasaki Information Systems Co., Ltd. - 3361 Oshi - Fukiage-machi, Saitama 369-0113 - JAPAN - - 00-03-27 (hex) ACT'L - 000327 (base 16) ACT'L - Avenue de Artisanat 10A - 1924 Braine l'Allard - BELGIUM - - 00-03-28 (hex) Mace Group, Inc. - 000328 (base 16) Mace Group, Inc. - 5101 Commerce Dr. - Baldwin Park CA 91706 - UNITED STATES - - 00-03-29 (hex) F3, Inc. - 000329 (base 16) F3, Inc. - 2F, No. 7, Industry E. Rd. 9, - Science Based Industrial Park, - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-03-2A (hex) UniData Communication Systems, Inc. - 00032A (base 16) UniData Communication Systems, Inc. - 2F, OhSung-Bldg, 82-15, - NonHyun-Dong, GangNam-Gu, Seoul,135-101 - KOREA, REPUBLIC OF - - 00-03-2B (hex) GAI Datenfunksysteme GmbH - 00032B (base 16) GAI Datenfunksysteme GmbH - Riedleparkstraße 28 - Friedrichshafen 88045 - GERMANY - - 00-03-2C (hex) ABB Switzerland Ltd - 00032C (base 16) ABB Switzerland Ltd - Dept. ATEP - CH-5300 Turgi - Austrasse - SWITZERLAND - - 00-03-2D (hex) IBASE Technology, Inc. - 00032D (base 16) IBASE Technology, Inc. - 5F, No. 221, - Chung Yang Rd. - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-03-2E (hex) Scope Information Management, Ltd. - 00032E (base 16) Scope Information Management, Ltd. - 2F Chanwoo b/o 736 Youksang-dong, - Kangnam-gu, - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-03-2F (hex) Global Sun Technology, Inc. - 00032F (base 16) Global Sun Technology, Inc. - No. 13, Tung Yuan Rd., - Jung Li Industrial Park Jung Li City - TAIWAN, PROVINCE OF CHINA - - 00-03-30 (hex) Imagenics, Co., Ltd. - 000330 (base 16) Imagenics, Co., Ltd. - 1-31-5 Kokuryo-Cho - Chofu-City Tokyo - 182-0022 - JAPAN - - 00-03-31 (hex) CISCO SYSTEMS, INC. - 000331 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-32 (hex) CISCO SYSTEMS, INC. - 000332 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-33 (hex) Digitel Co., Ltd. - 000333 (base 16) Digitel Co., Ltd. - 835-6, Yoksam-dong - Kangnam-gu, 135-080, Seoul, - KOREA, REPUBLIC OF - - 00-03-34 (hex) Newport Electronics - 000334 (base 16) Newport Electronics - 2229 So. Yale St. - Santa Ana CA 92704 - UNITED STATES - - 00-03-35 (hex) Mirae Technology - 000335 (base 16) Mirae Technology - 211-15, Hon Hyun-dong, - Kangnam-ku 135-010 - Seoul - KOREA, REPUBLIC OF - - 00-03-36 (hex) Zetes Technologies - 000336 (base 16) Zetes Technologies - 3 Rue De Stras Bourg - 1130 Brussels - BELGIUM - - 00-03-37 (hex) Vaone, Inc. - 000337 (base 16) Vaone, Inc. - 6F Kyemong Art Center, - 772 Yuksan2-Dong Kang HamGu, Seoul, - 135-082 - KOREA, REPUBLIC OF - - 00-03-38 (hex) Oak Technology - 000338 (base 16) Oak Technology - 139 Kifer Court - Sunnyvale CA 94086-5160 - UNITED STATES - - 00-03-39 (hex) Eurologic Systems, Ltd. - 000339 (base 16) Eurologic Systems, Ltd. - Clonshaugh Industrial Estate - Clonshaugh Dublin 17 - IRELAND - - 00-03-3A (hex) Silicon Wave, Inc. - 00033A (base 16) Silicon Wave, Inc. - 6256 Greenwich Drive - Suite 300 - San Diego CA 92122 - UNITED STATES - - 00-03-3B (hex) TAMI Tech Co., Ltd. - 00033B (base 16) TAMI Tech Co., Ltd. - 4F, Chungdo Bencher Town - 606 Tanbang-Dong, Seo-Gu - Taejon - KOREA, REPUBLIC OF - - 00-03-3C (hex) Daiden Co., Ltd. - 00033C (base 16) Daiden Co., Ltd. - 2100-19 Tutumi, Kamimine-machi - Miyaki-gun, Saga-ken - JAPAN - - 00-03-3D (hex) ILSHin Lab - 00033D (base 16) ILSHin Lab - KCS B/D 228-13 Young Dap-Dong - SUNG DONG-GU, - Seoul - KOREA, REPUBLIC OF - - 00-03-3E (hex) Tateyama System Laboratory Co., Ltd. - 00033E (base 16) Tateyama System Laboratory Co., Ltd. - 30 Shimonoban Oyama-cho - Kaminikawa-gun Toyama Prof. - 930-1305 - JAPAN - - 00-03-3F (hex) BigBand Networks, Ltd. - 00033F (base 16) BigBand Networks, Ltd. - 3 Azrieli Towers - Tel-Aviv 67023 - ISRAEL - - 00-03-40 (hex) Floware Wireless Systems, Ltd. - 000340 (base 16) Floware Wireless Systems, Ltd. - 28 Hacharoshet Steet - P.O.B. 812 Or-Yehuda - 60250 - ISRAEL - - 00-03-41 (hex) Axon Digital Design - 000341 (base 16) Axon Digital Design - Lange Wagenstraat 55 - NL-5126 BB GILZE - NETHERLANDS - - 00-03-42 (hex) Nortel Networks - 000342 (base 16) Nortel Networks - 8200 Dixie Road - Ste #100 - Dept. 6800 Brampton ON L6T 5P6 - CANADA - - 00-03-43 (hex) Martin Professional A/S - 000343 (base 16) Martin Professional A/S - Olof Palmes Alle 18 - DK-8200 Aarhusn - DENMARK - - 00-03-44 (hex) Tietech.Co., Ltd. - 000344 (base 16) Tietech.Co., Ltd. - 2-13-1 Chikamatoori Minamiku - Nagoya, - JAPAN - - 00-03-45 (hex) Routrek Networks Corporation - 000345 (base 16) Routrek Networks Corporation - Nilssei Shin Mizonokuchi Bldg. 1F - 3-5-7 Hisamoto, Takatsu-Ku Kawasaki-shi, - 23-0011 - JAPAN - - 00-03-46 (hex) Hitachi Kokusai Electric, Inc. - 000346 (base 16) Hitachi Kokusai Electric, Inc. - 1-6-10 Uchikanda - Chiyoda-Ku Tokyo l101 - JAPAN - - 00-03-47 (hex) Intel Corporation - 000347 (base 16) Intel Corporation - MS: LF3-420 - 2111 N.E. 25th Avenue - Hillsboro OR 97124 - UNITED STATES - - 00-03-48 (hex) Norscan Instruments, Ltd. - 000348 (base 16) Norscan Instruments, Ltd. - 7 Terracon Place - Winnipeg, Manitoba, - R2J 4B3 - CANADA - - 00-03-49 (hex) Vidicode Datacommunicatie B.V. - 000349 (base 16) Vidicode Datacommunicatie B.V. - Postbus 7164 - 2701 AD Zoetermeer - NETHERLANDS - - 00-03-4A (hex) RIAS Corporation - 00034A (base 16) RIAS Corporation - 46600 Fremont Blvd. - Fremont CA 94538 - UNITED STATES - - 00-03-4B (hex) Nortel Networks - 00034B (base 16) Nortel Networks - 8200 Dixie Road Suite 100 - Dept. 6800 Brampton ON L6T 5 P6 - CANADA - - 00-03-4C (hex) Shanghai DigiVision Technology Co., Ltd. - 00034C (base 16) Shanghai DigiVision Technology Co., Ltd. - 11F, Heng Tong - International Building, 865 Chang Ning R - Shanghai 200050 - CHINA - - 00-03-4D (hex) Chiaro Networks, Ltd. - 00034D (base 16) Chiaro Networks, Ltd. - P.O. Box 832427 - Richardson TX 75083-2427 - UNITED STATES - - 00-03-4E (hex) Pos Data Company, Ltd. - 00034E (base 16) Pos Data Company, Ltd. - 276-2, Seo-Hyun Dong, - Bun-Dang Gu, Sung-nam City, Kyoung-Gi Pr - KOREA, REPUBLIC OF - - 00-03-4F (hex) Sur-Gard Security - 00034F (base 16) Sur-Gard Security - 401 Magnetic Drive - Units 24-28, Downsview - Ontario M3J 3H9 - CANADA - - 00-03-50 (hex) BTICINO SPA - 000350 (base 16) BTICINO SPA - Via L. Manara, 4 - 22036 Erba (CO) - ITALY - - 00-03-51 (hex) Diebold, Inc. - 000351 (base 16) Diebold, Inc. - 5995 Mayfair Road - North Canton OH 44720 - UNITED STATES - - 00-03-52 (hex) Colubris Networks - 000352 (base 16) Colubris Networks - 440 Armand-Frappier - Laval (Quebec) - H7V 4B4 - CANADA - - 00-03-53 (hex) Mitac, Inc. - 000353 (base 16) Mitac, Inc. - No. 2, Chung-Hsiao Street - Chitu Keelung, - TAIWAN, PROVINCE OF CHINA - - 00-03-54 (hex) Fiber Logic Communications - 000354 (base 16) Fiber Logic Communications - 5F-3, No. 9, Prosperity Road One, - Science-Based Industrial Park, - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-03-55 (hex) TeraBeam Internet Systems - 000355 (base 16) TeraBeam Internet Systems - 14833 NE 87th St., Bldg. C - Redmond WA 98052 - UNITED STATES - - 00-03-56 (hex) Wincor Nixdorf International GmbH - 000356 (base 16) Wincor Nixdorf International GmbH - Heinz-Nixdorf Ring 1 - D-33106 Paderborn - GERMANY - - 00-03-57 (hex) Intervoice-Brite, Inc. - 000357 (base 16) Intervoice-Brite, Inc. - 17811 Waterview Pkwy. - Dallas TX 75252 - UNITED STATES - - 00-03-58 (hex) Hanyang Digitech Co., Ltd. - 000358 (base 16) Hanyang Digitech Co., Ltd. - 13F, Acetwintower2, 212-30, Guro-Dong - Guro-Gu - Seoul - KOREA, REPUBLIC OF - - 00-03-59 (hex) DigitalSis - 000359 (base 16) DigitalSis - B-1405 Samho Bldg. - 275-6 Yangjae - Seocho Seoul, - KOREA, REPUBLIC OF - - 00-03-5A (hex) Photron Limited - 00035A (base 16) Photron Limited - 1-1-8, Fujimi, - Chiyoda-ku 102-0071 - JAPAN - - 00-03-5B (hex) BridgeWave Communications - 00035B (base 16) BridgeWave Communications - 3350 Thomad Road - Santa Clara CA 95054 - UNITED STATES - - 00-03-5C (hex) Saint Song Corp. - 00035C (base 16) Saint Song Corp. - 4F, No. 12, Lane 94, Tsao Ti Wzi - Shen Keng Hsiang, Taipei Hsien - 222 - TAIWAN, PROVINCE OF CHINA - - 00-03-5D (hex) Bosung Hi-Net Co., Ltd. - 00035D (base 16) Bosung Hi-Net Co., Ltd. - Youngil B/O 2F, - YangJae-dong 12-7, Seocho-gu, Seoul - 137-130 - KOREA, REPUBLIC OF - - 00-03-5E (hex) Metropolitan Area Networks, Inc. - 00035E (base 16) Metropolitan Area Networks, Inc. - 1299 Pennsylvania Avenue, NW - Ninth Floor - Washington DC 20004 - UNITED STATES - - 00-03-5F (hex) Prüftechnik Condition Monitoring GmbH & Co. KG - 00035F (base 16) Prüftechnik Condition Monitoring GmbH & Co. KG - Franz-Bayer-Straße 14 - D-88213 Ravensburg - GERMANY - - 00-03-60 (hex) PAC Interactive Technology, Inc. - 000360 (base 16) PAC Interactive Technology, Inc. - 6F, No. 30, Alley 18, Lane 478 - Jai Guang Road, Nei-Hu - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-03-61 (hex) Widcomm, Inc. - 000361 (base 16) Widcomm, Inc. - 9645 Scranton Road - Suite 205 - San Diego CA 92121 - UNITED STATES - - 00-03-62 (hex) Vodtel Communications, Inc. - 000362 (base 16) Vodtel Communications, Inc. - 12F, No 166 Chien-Yi Road - Chung-Ho City, Taipei County - 235 - TAIWAN, PROVINCE OF CHINA - - 00-03-63 (hex) Miraesys Co., Ltd. - 000363 (base 16) Miraesys Co., Ltd. - 650-2 4 Fl. Daemyung Bldg. - Yuksam, Kangnam, Seoul, - 135-080 - KOREA, REPUBLIC OF - - 00-03-64 (hex) Scenix Semiconductor, Inc. - 000364 (base 16) Scenix Semiconductor, Inc. - 1330 Charleston Rd. - Mountainview CA 94043 - UNITED STATES - - 00-03-65 (hex) Kira Information & Communications, Ltd. - 000365 (base 16) Kira Information & Communications, Ltd. - 6th Fl. Anam Tower, - 702-10 Yeoksam-dong, Kangnam-ku, Seoul - KOREA, REPUBLIC OF - - 00-03-66 (hex) ASM Pacific Technology - 000366 (base 16) ASM Pacific Technology - 12/F Watson Centre - 16 Kung Yip St. - Kwai Chung - HONG KONG - - 00-03-67 (hex) Jasmine Networks, Inc. - 000367 (base 16) Jasmine Networks, Inc. - 1940 Zanker Road - San Jose CA 95112 - UNITED STATES - - 00-03-68 (hex) Embedone Co., Ltd. - 000368 (base 16) Embedone Co., Ltd. - Fl. 9 Annex Samhwan B/D. 17-26 - Yeoido-Dong, Youngdeungpo-ku, - Seoul 150-01 - KOREA, REPUBLIC OF - - 00-03-69 (hex) Nippon Antenna Co., Ltd. - 000369 (base 16) Nippon Antenna Co., Ltd. - No. 49-8, Nishiogu, - 7-Chome Arakawa-ku, - Tokyo 116-8561 - JAPAN - - 00-03-6A (hex) Mainnet, Ltd. - 00036A (base 16) Mainnet, Ltd. - P.O. Box 2324 - Kfar Saba 44641 - ISRAEL - - 00-03-6B (hex) CISCO SYSTEMS, INC. - 00036B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-6C (hex) CISCO SYSTEMS, INC. - 00036C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-6D (hex) Runtop, Inc. - 00036D (base 16) Runtop, Inc. - 1, Lane 21, Hsin Hua Road, Kueishan - Industrial Park, Taoyuan City, - TAIWAN, PROVINCE OF CHINA - - 00-03-6E (hex) Nicon Systems (Pty) Limited - 00036E (base 16) Nicon Systems (Pty) Limited - 11 Termo Street - Technopark Stellenbosch, 7600 - SOUTH AFRICA - - 00-03-6F (hex) Telsey SPA - 00036F (base 16) Telsey SPA - Viale Dell Industria, 1 - 31 055 Quinto - DiTreviso- - ITALY - - 00-03-70 (hex) NXTV, Inc. - 000370 (base 16) NXTV, Inc. - 5955 De Soto Ave, #160 - Woodland Hills CA 91367 - UNITED STATES - - 00-03-71 (hex) Acomz Networks Corp. - 000371 (base 16) Acomz Networks Corp. - 7th Fl., Wooseok Bldg., 1007-37 - Sadang1-dong, Dongjak-gu, - Seoul 156-09 - KOREA, REPUBLIC OF - - 00-03-72 (hex) ULAN - 000372 (base 16) ULAN - 5F-3, No. 31-1, Lane 169, - Kang Ning St., Hsi-Chin City, Taipei Hsi - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-73 (hex) Aselsan A.S - 000373 (base 16) Aselsan A.S - Mehmet Akif Ersoy Mah. - 16 Cad. No. 16 Macunkoy/Ankara - TURKEY - - 00-03-74 (hex) Control Microsystems - 000374 (base 16) Control Microsystems - 48 Steacie Drive - Ottawa Ontario K2K 2A9 - CANADA - - 00-03-75 (hex) NetMedia, Inc. - 000375 (base 16) NetMedia, Inc. - 10940 N. Stallard Place - Tuscon AZ 85737 - UNITED STATES - - 00-03-76 (hex) Graphtec Technology, Inc. - 000376 (base 16) Graphtec Technology, Inc. - 45 Parker, Suite A - Irvine CA 92618 - UNITED STATES - - 00-03-77 (hex) Gigabit Wireless - 000377 (base 16) Gigabit Wireless - 3099 N. First Street - San Jose CA 95134 - UNITED STATES - - 00-03-78 (hex) HUMAX Co., Ltd. - 000378 (base 16) HUMAX Co., Ltd. - 271-2, Suh-hyun-Dong, - Bundang-Gu, Sungnam-City, Kyonggi-Do, 46 - KOREA, REPUBLIC OF - - 00-03-79 (hex) Proscend Communications, Inc. - 000379 (base 16) Proscend Communications, Inc. - 2F, No.36, Industry E. Rd. IV, - Science-Based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-03-7A (hex) Taiyo Yuden Co., Ltd. - 00037A (base 16) Taiyo Yuden Co., Ltd. - 8-1 Sakae-Cho - Takasaki-Shi Gunma 370-8522 - JAPAN - - 00-03-7B (hex) IDEC IZUMI Corporation - 00037B (base 16) IDEC IZUMI Corporation - 7-31, Nishimiyahara - 1-Chome Yodogawa-ku. Osaka 532-8550 - JAPAN - - 00-03-7C (hex) Coax Media - 00037C (base 16) Coax Media - 1220 Oak Industrial Lane - Suite B - Cumming GA 30041 - UNITED STATES - - 00-03-7D (hex) Stellcom - 00037D (base 16) Stellcom - 10525 Vista Sorrento Parkway - Suite 100 - San Diego CA 92121 - UNITED STATES - - 00-03-7E (hex) PORTech Communications, Inc. - 00037E (base 16) PORTech Communications, Inc. - 150, Shiang-Shung N. Rd., - Taichung Taiwan 403, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-7F (hex) Atheros Communications, Inc. - 00037F (base 16) Atheros Communications, Inc. - 5480 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-03-80 (hex) SSH Communications Security Corp. - 000380 (base 16) SSH Communications Security Corp. - Fredrikinkatu 42 - Fin 0100 Helsinki - FINLAND - - 00-03-81 (hex) Ingenico International - 000381 (base 16) Ingenico International - 1/9 Apollo Street - Warriewood NSW 2102 - AUSTRALIA - - 00-03-82 (hex) A-One Co., Ltd. - 000382 (base 16) A-One Co., Ltd. - 6-9-20, Shimoichiba-cho, - Kasugai-shi, Aichi-ken, 486-0852 - JAPAN - - 00-03-83 (hex) Metera Networks, Inc. - 000383 (base 16) Metera Networks, Inc. - 1202 Richardson Dr. - Suite 100 - Richardson TX 75080 - UNITED STATES - - 00-03-84 (hex) AETA - 000384 (base 16) AETA - Kepler 6 - 18-22 avenue Edouard Herriot - Le Plessis Robinson 92350 - FRANCE - - 00-03-85 (hex) Actelis Networks, Inc. - 000385 (base 16) Actelis Networks, Inc. - 1 Bazel St., P.O.B. 10173 - Petah - Tikva 49103 - ISRAEL - - 00-03-86 (hex) Ho Net, Inc. - 000386 (base 16) Ho Net, Inc. - Venture Company Center - San 94-6 Yiui-Dong, Paldal-Gu, Suwon-si, - KOREA 442-760 - KOREA, REPUBLIC OF - - 00-03-87 (hex) Blaze Network Products - 000387 (base 16) Blaze Network Products - 5180 Hacienda Drive - Dublin CA 94568 - UNITED STATES - - 00-03-88 (hex) Fastfame Technology Co., Ltd. - 000388 (base 16) Fastfame Technology Co., Ltd. - 7F, No. 111, Hsing De Rd., - Sanchung, Taipei, - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-89 (hex) Plantronics - 000389 (base 16) Plantronics - 345 Encinal St. - Santa Cruz CA 95060 - UNITED STATES - - 00-03-8A (hex) America Online, Inc. - 00038A (base 16) America Online, Inc. - 44900 Prentice Drive - Dulles VA 20166 - UNITED STATES - - 00-03-8B (hex) PLUS-ONE I&T, Inc. - 00038B (base 16) PLUS-ONE I&T, Inc. - 7F, A-San Venture Tower, - YangJae-dong, Seocho-ku, Seoul, - KOREA - KOREA, REPUBLIC OF - - 00-03-8C (hex) Total Impact - 00038C (base 16) Total Impact - 295 Willis Ave. - Suite E - Camarillo CA 93010 - UNITED STATES - - 00-03-8D (hex) PCS Revenue Control Systems, Inc. - 00038D (base 16) PCS Revenue Control Systems, Inc. - 560 Sylvan Ave. - Englewood Cliffs NJ 07632 - UNITED STATES - - 00-03-8E (hex) Atoga Systems, Inc. - 00038E (base 16) Atoga Systems, Inc. - 49026 Milmont Drive - Fremont CA 94538 - UNITED STATES - - 00-03-8F (hex) Weinschel Corporation - 00038F (base 16) Weinschel Corporation - 5305 Spectrum Drive - Frederick MD 21703 - UNITED STATES - - 00-03-90 (hex) Digital Video Communications, Inc. - 000390 (base 16) Digital Video Communications, Inc. - 500 W. Cummings Park - Suite 2000 - Woburn MA 07801 - UNITED STATES - - 00-03-91 (hex) Advanced Digital Broadcast, Ltd. - 000391 (base 16) Advanced Digital Broadcast, Ltd. - 8F, 145 Chung Shan N. Rd. Sec. 2, - Taipei, 104, - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-92 (hex) Hyundai Teletek Co., Ltd. - 000392 (base 16) Hyundai Teletek Co., Ltd. - B-501, Techno Park, 148 Yatap-dong, - Boondang-gu, Sungnam-si, Kyunggi-do, 463 - KOREA Republic - KOREA, REPUBLIC OF - - 00-03-93 (hex) Apple - 000393 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-03-94 (hex) Connect One - 000394 (base 16) Connect One - 2 Hanagar Street - Kfar Saba 44425 - ISRAEL - - 00-03-95 (hex) California Amplifier - 000395 (base 16) California Amplifier - 460 Calle San Pablo - Camarillo CA 93012 - UNITED STATES - - 00-03-96 (hex) EZ Cast Co., Ltd. - 000396 (base 16) EZ Cast Co., Ltd. - 6th Floor, JungAng Building, - 99-1, Nonhyun-Dong (135-010) Kangnam-ku, - KOREA - KOREA, REPUBLIC OF - - 00-03-97 (hex) Watchfront Limited - 000397 (base 16) Watchfront Limited - 3 Victoria Walk - Wokingham RG40 5YL - UNITED KINGDOM - - 00-03-98 (hex) WISI - 000398 (base 16) WISI - Wilhelm-Sihn-Str. 5-7 - D-75223 Niefern-Oeschelbronn - GERMANY - - 00-03-99 (hex) Dongju Informations & Communications Co., Ltd. - 000399 (base 16) Dongju Informations & Communications Co., Ltd. - #305, Eunsuk Bldg. Samsung-dong - Kangnam-gu Seoul - Republic of KOREA - KOREA, REPUBLIC OF - - 00-03-9A (hex) SiConnect - 00039A (base 16) SiConnect - Delta 100 - Welton Road - Swindon SN5 7XP - UNITED KINGDOM - - 00-03-9B (hex) NetChip Technology, Inc. - 00039B (base 16) NetChip Technology, Inc. - 335 Pioneer Way - Mountain View CA 94041 - UNITED STATES - - 00-03-9C (hex) OptiMight Communications, Inc. - 00039C (base 16) OptiMight Communications, Inc. - 980 Linda Vista Avenue - Mountain View CA 94043 - UNITED STATES - - 00-03-9D (hex) Qisda Corporation - 00039D (base 16) Qisda Corporation - 157 Shan Ying Road - GueiShan Taoyuan 333 - TAIWAN, PROVINCE OF CHINA - - 00-03-9E (hex) Tera System Co., Ltd. - 00039E (base 16) Tera System Co., Ltd. - Doosung B/F Rm 302 - 766-1 Shinchungdong Shihung City Kyungki - Republic of Korea - KOREA, REPUBLIC OF - - 00-03-9F (hex) CISCO SYSTEMS, INC. - 00039F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-A0 (hex) CISCO SYSTEMS, INC. - 0003A0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-A1 (hex) HIPER Information & Communication, Inc. - 0003A1 (base 16) HIPER Information & Communication, Inc. - 1675-7, Sinil-dong, - Taeduk-gu, Taejon, - 306-230 South Korea - KOREA, REPUBLIC OF - - 00-03-A2 (hex) Catapult Communications - 0003A2 (base 16) Catapult Communications - 160 S. Whisman Rd. - Mountain View CA 94041 - UNITED STATES - - 00-03-A3 (hex) MAVIX, Ltd. - 0003A3 (base 16) MAVIX, Ltd. - POB 217, Yokneam Illit, - 20692 - ISRAEL - - 00-03-A4 (hex) Imation Corp. - 0003A4 (base 16) Imation Corp. - 1 Imation Place - Discovery 2B-50 - Oakdale MN 55128-3414 - UNITED STATES - - 00-03-A5 (hex) Medea Corporation - 0003A5 (base 16) Medea Corporation - 5701 Lindero Canyon Rd. - Bldg. 3-100 - Wetlake Village CA 91362 - UNITED STATES - - 00-03-A6 (hex) Traxit Technology, Inc. - 0003A6 (base 16) Traxit Technology, Inc. - 256 Great Road, - Suite 16 - Littleton MA 01461 - UNITED STATES - - 00-03-A7 (hex) Unixtar Technology, Inc. - 0003A7 (base 16) Unixtar Technology, Inc. - 13F No. 100 Ming Chuan Road - Hsin Tien, Taipei, - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-03-A8 (hex) IDOT Computers, Inc. - 0003A8 (base 16) IDOT Computers, Inc. - 3F., No. 137, Lane 235 - Pao-Chiao Road, Hsin-Tien Taipei Country - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-A9 (hex) AXCENT Media AG - 0003A9 (base 16) AXCENT Media AG - Technologiepark 13 - 33100 Paderborn - GERMANY - - 00-03-AA (hex) Watlow - 0003AA (base 16) Watlow - 1241 Bundy Blvd. - Winona MN 55987 - UNITED STATES - - 00-03-AB (hex) Bridge Information Systems - 0003AB (base 16) Bridge Information Systems - 717 Office Parkway - St. Louis MO 63141 - UNITED STATES - - 00-03-AC (hex) Fronius Schweissmaschinen - 0003AC (base 16) Fronius Schweissmaschinen - Günter Fronius-Straße 1 - A-4600 Weis-Thalheim - AUSTRIA - - 00-03-AD (hex) Emerson Energy Systems AB - 0003AD (base 16) Emerson Energy Systems AB - PO Box 92113 - 120 07 Stockholm - SWEDEN - - 00-03-AE (hex) Allied Advanced Manufacturing Pte, Ltd. - 0003AE (base 16) Allied Advanced Manufacturing Pte, Ltd. - 7 International Business Park - #02-00 - Singapore 609919 - SINGAPORE - - 00-03-AF (hex) Paragea Communications - 0003AF (base 16) Paragea Communications - 207 Perry Parkway - Gaithersburg MD 20877 - UNITED STATES - - 00-03-B0 (hex) Xsense Technology Corp. - 0003B0 (base 16) Xsense Technology Corp. - 11 F, 232, Sec. 3, ChengTeh Rd. - Taipei TAIWAN, 103 - TAIWAN, PROVINCE OF CHINA - - 00-03-B1 (hex) Hospira Inc. - 0003B1 (base 16) Hospira Inc. - 755 Jarvis Drive - Morgan Hill CA 95037 - UNITED STATES - - 00-03-B2 (hex) Radware - 0003B2 (base 16) Radware - 8 Hamrpe Hochvim - Jerusalem - ISRAEL - - 00-03-B3 (hex) IA Link Systems Co., Ltd. - 0003B3 (base 16) IA Link Systems Co., Ltd. - 6F-4, No. 81 Hsin Tai - Wu Rd., Sec. 1 Hsih-Chih, Taipei Hsien, - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-B4 (hex) Macrotek International Corp. - 0003B4 (base 16) Macrotek International Corp. - 2F, No. 28, Lane 46 - Kwang Fu 6 Road, - Taipei Taipei TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-03-B5 (hex) Entra Technology Co. - 0003B5 (base 16) Entra Technology Co. - Fl. 3, No. 5, Alley 2, - Su-Wei Lane, Chung-Cheng Rd., Hsin-Dien, - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-B6 (hex) QSI Corporation - 0003B6 (base 16) QSI Corporation - 2212 South West Temple #50 - Salt Lake City UT 84115 - UNITED STATES - - 00-03-B7 (hex) ZACCESS Systems - 0003B7 (base 16) ZACCESS Systems - 275 Shoreline Drive, #110 - Redwood City CA 94065 - UNITED STATES - - 00-03-B8 (hex) NetKit Solutions, LLC - 0003B8 (base 16) NetKit Solutions, LLC - 1125-A Business Center Circle - Thousand Oaks CA 91320 - UNITED STATES - - 00-03-B9 (hex) Hualong Telecom Co., Ltd. - 0003B9 (base 16) Hualong Telecom Co., Ltd. - 9 Guanghua St. - Changzhou, Jiangsu, 213003 - P.R. - CHINA - - 00-03-BA (hex) Oracle Corporation - 0003BA (base 16) Oracle Corporation - 17 Network Circle - Building 17, UMPK17-131 - Menlo Park CA 94025 - UNITED STATES - - 00-03-BB (hex) Signal Communications Limited - 0003BB (base 16) Signal Communications Limited - Unit 217, 2/F, HKITC, - 72 Tat Chee Avenue, KLN., - HONG KONG - HONG KONG - - 00-03-BC (hex) COT GmbH - 0003BC (base 16) COT GmbH - Güterstraße 5 - 64807 Dieburg - GERMANY - - 00-03-BD (hex) OmniCluster Technologies, Inc. - 0003BD (base 16) OmniCluster Technologies, Inc. - 4950 Blue Lake Drive - Suite 900 - Boca Raton FL 33431 - UNITED STATES - - 00-03-BE (hex) Netility - 0003BE (base 16) Netility - 298 South Sunnyvale Ave. - Suie 102 - Sunnyvale CA 94086 - UNITED STATES - - 00-03-BF (hex) Centerpoint Broadband Technologies, Inc. - 0003BF (base 16) Centerpoint Broadband Technologies, Inc. - 1741 Technology Drive, - Suite 400 - San Jose CA 95110-1310 - UNITED STATES - - 00-03-C0 (hex) RFTNC Co., Ltd. - 0003C0 (base 16) RFTNC Co., Ltd. - 3F, 1624-24, Bongchen-dong - Kionak-gu, Seoul - SOUTH KOREA - KOREA, REPUBLIC OF - - 00-03-C1 (hex) Packet Dynamics Ltd - 0003C1 (base 16) Packet Dynamics Ltd - 2 Buckstane Park - Edinburgh, Scotland - UK EH10 GPA - UNITED KINGDOM - - 00-03-C2 (hex) Solphone K.K. - 0003C2 (base 16) Solphone K.K. - 2-11-1 Kandatsukasa-cho - Chiyada, Tokyo - 101-0048 - JAPAN - - 00-03-C3 (hex) Micronik Multimedia - 0003C3 (base 16) Micronik Multimedia - Brückenstraße 2 - D-51379 Leverkusen - GERMANY - - 00-03-C4 (hex) Tomra Systems ASA - 0003C4 (base 16) Tomra Systems ASA - Drengsrudhagen 2 - Box 278 N-1371 Asker - NORWAY - - 00-03-C5 (hex) Mobotix AG - 0003C5 (base 16) Mobotix AG - Wingertsweilerhof 6 - D-67724 Horingen - GERMANY - - 00-03-C6 (hex) ICUE Systems, Inc. - 0003C6 (base 16) ICUE Systems, Inc. - 17489 Gale Avenue - City of Industry CA 91748 - UNITED STATES - - 00-03-C7 (hex) hopf Elektronik GmbH - 0003C7 (base 16) hopf Elektronik GmbH - Nottebohmstraße 41 - 58511 Lüdenscheid - GERMANY - - 00-03-C8 (hex) CML Emergency Services - 0003C8 (base 16) CML Emergency Services - 75 Boulevard la Technologies - Hull, Quebec JE23G4 - CANADA - - 00-03-C9 (hex) TECOM Co., Ltd. - 0003C9 (base 16) TECOM Co., Ltd. - 23, R&D Road 2 - Science-Based Industrial Park - Hsin-Chu - TAIWAN, PROVINCE OF CHINA - - 00-03-CA (hex) MTS Systems Corp. - 0003CA (base 16) MTS Systems Corp. - 3001 Sheldon Drive - Cary, NC 27513 - UNITED STATES - - 00-03-CB (hex) Nippon Systems Development Co., Ltd. - 0003CB (base 16) Nippon Systems Development Co., Ltd. - 30-12, Komyo-cho, - Takarabuka-city, Hyogo, - 665-0045 - JAPAN - - 00-03-CC (hex) Momentum Computer, Inc. - 0003CC (base 16) Momentum Computer, Inc. - 1815 Aston Avenue - Suite 107 - Carlsbad CA 92008-7310 - UNITED STATES - - 00-03-CD (hex) Clovertech, Inc. - 0003CD (base 16) Clovertech, Inc. - 3-1-5 Naka-cho Musashino-shi - Tokyo 180-0006 - JAPAN - - 00-03-CE (hex) ETEN Technologies, Inc. - 0003CE (base 16) ETEN Technologies, Inc. - 2F, No. 9, Lane 235, Pao-Chiao Rd., - Hsien Tien City, Taipei Hsien 231 - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-03-CF (hex) Muxcom, Inc. - 0003CF (base 16) Muxcom, Inc. - D 602, Bundang Technopark #151 - Yatap Dong, Bundag Gu, Sungnam Si, - Kyungki Do KOREA 463-070 - KOREA, REPUBLIC OF - - 00-03-D0 (hex) KOANKEISO Co., Ltd. - 0003D0 (base 16) KOANKEISO Co., Ltd. - Zip Code 791-8042 - 2798 36minamiyoshida-Mati Matuyama-City - JAPAN - - 00-03-D1 (hex) Takaya Corporation - 0003D1 (base 16) Takaya Corporation - Development Division - 661-1, Ibara-cho Ibara-City Okayama, 715 - JAPAN - - 00-03-D2 (hex) Crossbeam Systems, Inc. - 0003D2 (base 16) Crossbeam Systems, Inc. - 80 Central Street - Boxborough MA 01719 - UNITED STATES - - 00-03-D3 (hex) Internet Energy Systems, Inc. - 0003D3 (base 16) Internet Energy Systems, Inc. - 4218 Trumbo Ct. - Fairfax VA 22033 - UNITED STATES - - 00-03-D4 (hex) Alloptic, Inc. - 0003D4 (base 16) Alloptic, Inc. - 6960 Koll Center Parkway - Suite 300 - Pleasanton CA 94566 - UNITED STATES - - 00-03-D5 (hex) Advanced Communications Co., Ltd. - 0003D5 (base 16) Advanced Communications Co., Ltd. - 2876-1 Ooka - Numazu-shi - Shizuoka 41-0022 - JAPAN - - 00-03-D6 (hex) RADVision, Ltd. - 0003D6 (base 16) RADVision, Ltd. - 24 Raul Wallenberg St. - Tel-Aviv 69719 - ISRAEL - - 00-03-D7 (hex) NextNet Wireless, Inc. - 0003D7 (base 16) NextNet Wireless, Inc. - 9555 James Ave. So. - Suite 270 - Bloomington MN 55431 - UNITED STATES - - 00-03-D8 (hex) iMPath Networks, Inc. - 0003D8 (base 16) iMPath Networks, Inc. - 1431 Merivale Rd. - Nepean, Ontario, - CANADA K2E 1B9 - CANADA - - 00-03-D9 (hex) Secheron SA - 0003D9 (base 16) Secheron SA - Untermattweg 8 - Ch-3027 Bern - SWITZERLAND - - 00-03-DA (hex) Takamisawa Cybernetics Co., Ltd. - 0003DA (base 16) Takamisawa Cybernetics Co., Ltd. - Nakano Heiwa Bldg. - 48 5-2-Chome Chuo, Nakano-ku Tokyo 164-0 - JAPAN - - 00-03-DB (hex) Apogee Electronics Corp. - 0003DB (base 16) Apogee Electronics Corp. - 1715 Berkeley St. - Santa Monica CA 90405-3210 - UNITED STATES - - 00-03-DC (hex) Lexar Media, Inc. - 0003DC (base 16) Lexar Media, Inc. - 47421 Bayside Parkway - Fremont CA 94538 - UNITED STATES - - 00-03-DD (hex) Comark Corp. - 0003DD (base 16) Comark Corp. - 93 West St. - Medfield MA 02052 - UNITED STATES - - 00-03-DE (hex) OTC Wireless - 0003DE (base 16) OTC Wireless - 602 Charlot Ave. - San Jose CA 95131 - UNITED STATES - - 00-03-DF (hex) Desana Systems - 0003DF (base 16) Desana Systems - 1805 McCandless Ave. - Milpitas CA 95035 - UNITED STATES - - 00-03-E0 (hex) ARRIS Group, Inc. - 0003E0 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-03-E1 (hex) Winmate Communication, Inc. - 0003E1 (base 16) Winmate Communication, Inc. - 9F,No.111-6,Shing-De Rd - San-Chung, - Taipei 241 - TAIWAN, PROVINCE OF CHINA - - 00-03-E2 (hex) Comspace Corporation - 0003E2 (base 16) Comspace Corporation - 955 Freeport Pkwy - Suite 100 - Coppell TX 75019 - UNITED STATES - - 00-03-E3 (hex) CISCO SYSTEMS, INC. - 0003E3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-E4 (hex) CISCO SYSTEMS, INC. - 0003E4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-E5 (hex) Hermstedt SG - 0003E5 (base 16) Hermstedt SG - Carl-Reuther - Str. 3 - D-68305 Mannheim - GERMANY - - 00-03-E6 (hex) Entone, Inc. - 0003E6 (base 16) Entone, Inc. - 2755 Campus Dr Ste 235 - San Mateo CA 94403 - UNITED STATES - - 00-03-E7 (hex) Logostek Co. Ltd. - 0003E7 (base 16) Logostek Co. Ltd. - 19th 15 Sunusu-Academy Tower - 277-17 Sungsu-2ga, Sungdong-gu - Seoul KOREA 133-123 - KOREA, REPUBLIC OF - - 00-03-E8 (hex) Wavelength Digital Limited - 0003E8 (base 16) Wavelength Digital Limited - 12 Vincent Avenue - Crownhill Business Park Milton Keynes, B - MK8 0AB MK8 0AB ENGLAND - UNITED KINGDOM - - 00-03-E9 (hex) Akara Canada, Inc. - 0003E9 (base 16) Akara Canada, Inc. - 150 Katimavik Road - Kanata Ontario - CANADA K2L 2N2 - CANADA - - 00-03-EA (hex) Mega System Technologies, Inc. - 0003EA (base 16) Mega System Technologies, Inc. - 2F, No. 41, Lane 76, - Rui Kuang Rd., Nei Hu 114 - Taipei Taipei TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-03-EB (hex) Atrica - 0003EB (base 16) Atrica - 5 Shenkar St. P.O.B. 12231 - Hezelia Industrial Area - 46733 46733 - ISRAEL - - 00-03-EC (hex) ICG Research, Inc. - 0003EC (base 16) ICG Research, Inc. - 775 B The Queens Way - Toronto, Ontario - M8Z 1N1 - CANADA - - 00-03-ED (hex) Shinkawa Electric Co., Ltd. - 0003ED (base 16) Shinkawa Electric Co., Ltd. - 3-2-24 3 chome - Konan Nakaku Hiroshima, 730-0825, - JAPAN - - 00-03-EE (hex) MKNet Corporation - 0003EE (base 16) MKNet Corporation - 711-B Charcot Ave. - San Jose CA 95131 - UNITED STATES - - 00-03-EF (hex) Oneline AG - 0003EF (base 16) Oneline AG - Steinfeldstraße 3 - 39179 Barleben - GERMANY - - 00-03-F0 (hex) Redfern Broadband Networks - 0003F0 (base 16) Redfern Broadband Networks - Level 1, 1 Central Ave., - Australian Technology Park Eveleigh, NSW - AUSTRALIA - - 00-03-F1 (hex) Cicada Semiconductor, Inc. - 0003F1 (base 16) Cicada Semiconductor, Inc. - 811 Barton Springs Rd. - Suite 550 - Austin TX 78704 - UNITED STATES - - 00-03-F2 (hex) Seneca Networks - 0003F2 (base 16) Seneca Networks - 30 West Gude Dr. - Suite 200 - Rockville MD 20850 - UNITED STATES - - 00-03-F3 (hex) Dazzle Multimedia, Inc. - 0003F3 (base 16) Dazzle Multimedia, Inc. - 47211 Bayside Parkway - Fremont CA 94538 - UNITED STATES - - 00-03-F4 (hex) NetBurner - 0003F4 (base 16) NetBurner - 5405 Morehouse Drive - Suite 200 - San Diego CA 92121 - UNITED STATES - - 00-03-F5 (hex) Chip2Chip - 0003F5 (base 16) Chip2Chip - 2249 Zanker Rd. - San Jose CA 95131 - UNITED STATES - - 00-03-F6 (hex) Allegro Networks, Inc. - 0003F6 (base 16) Allegro Networks, Inc. - 6399 San Ignacio Avenue - San Jose CA 95119 - UNITED STATES - - 00-03-F7 (hex) Plast-Control GmbH - 0003F7 (base 16) Plast-Control GmbH - Walter-Freitag-Str. 15 - 42899 Remscheid - GERMANY - - 00-03-F8 (hex) SanCastle Technologies, Inc. - 0003F8 (base 16) SanCastle Technologies, Inc. - 2107 North First Street - Suite 500 - San Jose CA 95131 - UNITED STATES - - 00-03-F9 (hex) Pleiades Communications, Inc. - 0003F9 (base 16) Pleiades Communications, Inc. - 2830 Market Loop #104 - South Lake TX 76092 - UNITED STATES - - 00-03-FA (hex) TiMetra Networks - 0003FA (base 16) TiMetra Networks - 500 Ellis St. - Mountain View CA 94043 - UNITED STATES - - 00-03-FB (hex) ENEGATE Co.,Ltd. - 0003FB (base 16) ENEGATE Co.,Ltd. - 3-14-40 Senrioka, - Settsu-city Osaka 566-8686 - JAPAN - - 00-03-FC (hex) Intertex Data AB - 0003FC (base 16) Intertex Data AB - Rissneleden 45 - 174 44 Sundbyberg - SWEDEN - - 00-03-FD (hex) CISCO SYSTEMS, INC. - 0003FD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-FE (hex) CISCO SYSTEMS, INC. - 0003FE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-03-FF (hex) Microsoft Corporation - 0003FF (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond WA 98052 - UNITED STATES - - 00-04-00 (hex) LEXMARK INTERNATIONAL, INC. - 000400 (base 16) LEXMARK INTERNATIONAL, INC. - 740 NEW CIRCLE RD - BLDG. #035 - LEXINGTON KY 40550 - UNITED STATES - - 00-04-01 (hex) Osaki Electric Co., Ltd. - 000401 (base 16) Osaki Electric Co., Ltd. - 1131, Fujikubo, Miyoshimachi, - Iruma-gun, Saitama 354-8501, - JAPAN - - 00-04-02 (hex) Nexsan Technologies, Ltd. - 000402 (base 16) Nexsan Technologies, Ltd. - Parker Centre - Mansfield Rd - Derby DE21 4SZ - UNITED KINGDOM - - 00-04-03 (hex) Nexsi Corporation - 000403 (base 16) Nexsi Corporation - 1959 Concourse Drive - San Jose CA 95131 - UNITED STATES - - 00-04-04 (hex) Makino Milling Machine Co., Ltd. - 000404 (base 16) Makino Milling Machine Co., Ltd. - 4023 Nakatsu, Aikawa-machi - Aiko-gun Kanagawa 243-0303 - JAPAN - - 00-04-05 (hex) ACN Technologies - 000405 (base 16) ACN Technologies - 9F, HeyKang B/D, 157-36 - Sansung-dong, Kangnamgu, - Seoul KOREA #135-090 - KOREA, REPUBLIC OF - - 00-04-06 (hex) Fa. Metabox AG - 000406 (base 16) Fa. Metabox AG - Daimlerring 37, - D-31135 Hildsheim, - GERMANY - - 00-04-07 (hex) Topcon Positioning Systems, Inc. - 000407 (base 16) Topcon Positioning Systems, Inc. - 5758 W. Las Positas Blvd. - Pleasanton CA 94588 - UNITED STATES - - 00-04-08 (hex) Sanko Electronics Co., Ltd. - 000408 (base 16) Sanko Electronics Co., Ltd. - 3-802 ueda tenpaku-ku - nagoya - JAPAN - - 00-04-09 (hex) Cratos Networks - 000409 (base 16) Cratos Networks - 313 Littleton Road - Suite 20 - Chelmsford MA 01824 - UNITED STATES - - 00-04-0A (hex) Sage Systems - 00040A (base 16) Sage Systems - 1420 Harbor Bay Parkway - Suite 160 - Alameda CA 94502 - UNITED STATES - - 00-04-0B (hex) 3com Europe Ltd. - 00040B (base 16) 3com Europe Ltd. - 3com Centre - Boundary Way, Hemel Hempstead Hertfordsh - HP2 7YU UK - UNITED KINGDOM - - 00-04-0C (hex) Kanno Works, Ltd. - 00040C (base 16) Kanno Works, Ltd. - 1-5-25 Kamitomino, - Kokurakita-ku, Kitakyusyu-city, Fukuoka- - JAPAN - - 00-04-0D (hex) Avaya, Inc. - 00040D (base 16) Avaya, Inc. - Office 1A325 - 307 Middletown Lincroft Road - Lincroft NJ 07738-1526 - UNITED STATES - - 00-04-0E (hex) AVM GmbH - 00040E (base 16) AVM GmbH - Alt-Moabit 95 - 10559 Berlin - GERMANY - - 00-04-0F (hex) Asus Network Technologies, Inc. - 00040F (base 16) Asus Network Technologies, Inc. - 11-1, No. 675, Sec. 1, King-kuo Rd., - Hsinchu, - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-10 (hex) Spinnaker Networks, Inc. - 000410 (base 16) Spinnaker Networks, Inc. - 107 Gamma Drive - Pittsburgh PA 15238 - UNITED STATES - - 00-04-11 (hex) Inkra Networks, Inc. - 000411 (base 16) Inkra Networks, Inc. - 40971 Encyclopedia Circle - Fremont CA 94538 - UNITED STATES - - 00-04-12 (hex) WaveSmith Networks, Inc. - 000412 (base 16) WaveSmith Networks, Inc. - 40 Nagog Park - Acton MA 01720-3425 - UNITED STATES - - 00-04-13 (hex) SNOM Technology AG - 000413 (base 16) SNOM Technology AG - Helmholtzstraße 2-9 - D-10587 Berlin - GERMANY - - 00-04-14 (hex) Umezawa Musen Denki Co., Ltd. - 000414 (base 16) Umezawa Musen Denki Co., Ltd. - 14-3, Minami 1, Nishi 8, - Chuo-ku, Sapporo, - Hokkaido JAPAN 060-0061 - JAPAN - - 00-04-15 (hex) Rasteme Systems Co., Ltd. - 000415 (base 16) Rasteme Systems Co., Ltd. - 886-2 Nihongi Nakagou-mura - Nakakubiki-gun Niigata - JAPAN - - 00-04-16 (hex) Parks S/A Comunicacoes Digitais - 000416 (base 16) Parks S/A Comunicacoes Digitais - Av. Pernambuco, 1001 - Porto-Alegre-RS CEP 90240-004 - BRAZIL - - 00-04-17 (hex) ELAU AG - 000417 (base 16) ELAU AG - Dillberg 12 - 97828 Marktheidenfeld - GERMANY - - 00-04-18 (hex) Teltronic S.A.U. - 000418 (base 16) Teltronic S.A.U. - Poligono de Malpica - Calle F Oeste 50057 Zaragoza - SPAIN - - 00-04-19 (hex) Fibercycle Networks, Inc. - 000419 (base 16) Fibercycle Networks, Inc. - 20 South Santa Cruz Ave. - Suite 112 - Los Gatos CA 95030 - UNITED STATES - - 00-04-1A (hex) Ines Test and Measurement GmbH & CoKG - 00041A (base 16) Ines Test and Measurement GmbH & CoKG - An der Mühlenaue 5 - Bad Nenndorf 31542 - GERMANY - - 00-04-1B (hex) Bridgeworks Ltd. - 00041B (base 16) Bridgeworks Ltd. - 135 Somerford Road - Christchurch DORSET BH23 3PY - UNITED KINGDOM - - 00-04-1C (hex) ipDialog, Inc. - 00041C (base 16) ipDialog, Inc. - 1762 Technology Drive - Suite 124 - San Jose CA 95110 - UNITED STATES - - 00-04-1D (hex) Corega of America - 00041D (base 16) Corega of America - P.O. Box 159 - Bothell WA 98041-0159 - UNITED STATES - - 00-04-1E (hex) Shikoku Instrumentation Co., Ltd. - 00041E (base 16) Shikoku Instrumentation Co., Ltd. - 777, Oosachou, Zentsuujishi, - Kagawa, 765-0052, - JAPAN - - 00-04-1F (hex) Sony Computer Entertainment, Inc. - 00041F (base 16) Sony Computer Entertainment, Inc. - 2-6-21 Minami-Aoyama - Minato-ku Tokyo 107-0062 - JAPAN - - 00-04-20 (hex) Slim Devices, Inc. - 000420 (base 16) Slim Devices, Inc. - 12 South First St. - Suite 103 - San Jose CA 95113 - UNITED STATES - - 00-04-21 (hex) Ocular Networks - 000421 (base 16) Ocular Networks - 12700, Fair Lakes Circle - Suite 100 - Fairfax VA 22033 - UNITED STATES - - 00-04-22 (hex) Gordon Kapes, Inc. - 000422 (base 16) Gordon Kapes, Inc. - 5520 W. Touhy Ave. - Skokie IL 60077 - UNITED STATES - - 00-04-23 (hex) Intel Corporation - 000423 (base 16) Intel Corporation - MS: JF3-420 - 2111 NE 25th Avenue - Hillsboro OR 97124 - UNITED STATES - - 00-04-24 (hex) TMC s.r.l. - 000424 (base 16) TMC s.r.l. - 202 Via A. Costa - 40134 - Bologna - ITALY - - 00-04-25 (hex) Atmel Corporation - 000425 (base 16) Atmel Corporation - Multimedia & Communications Group - 2200 Gateway Centre, Suite 201 - Morrisville NC 27560 - UNITED STATES - - 00-04-26 (hex) Autosys - 000426 (base 16) Autosys - 202 Ilsinpastel, - 721-2 MOK3-Dong Yang Cheon-ku, - Seoul Seoul KOREA - KOREA, REPUBLIC OF - - 00-04-27 (hex) CISCO SYSTEMS, INC. - 000427 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-28 (hex) CISCO SYSTEMS, INC. - 000428 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-29 (hex) Pixord Corporation - 000429 (base 16) Pixord Corporation - 6F, No. 12, Innovation 1st Rd., - Hsinchu Science Park, Hsinchu 30076 - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-2A (hex) Wireless Networks, Inc. - 00042A (base 16) Wireless Networks, Inc. - 2322 El Camino Real - San Mateo CA 94403 - UNITED STATES - - 00-04-2B (hex) IT Access Co., Ltd. - 00042B (base 16) IT Access Co., Ltd. - 3-17-6, Shinyokohama, Kouhoku-ku - Yokohama-shi Kanagawa 222-8545 - JAPAN - - 00-04-2C (hex) Minet, Inc. - 00042C (base 16) Minet, Inc. - 3F Se-A Venture Tower - 946-12 Daechi-dong, Gangnam-gu, Seoul - KOREA - KOREA, REPUBLIC OF - - 00-04-2D (hex) Sarian Systems, Ltd. - 00042D (base 16) Sarian Systems, Ltd. - Beacon House - Riverside Business Park Leeds Road, Ilk - West Yorkshire ENGLAND LS29 8JZ - UNITED KINGDOM - - 00-04-2E (hex) Netous Technologies, Ltd. - 00042E (base 16) Netous Technologies, Ltd. - 1006, Block A, - GoodView Industrial Building, Kin Fat St - HONG KONG - HONG KONG - - 00-04-2F (hex) International Communications Products, Inc. - 00042F (base 16) International Communications Products, Inc. - 4325 Woodland Park Drive - Suite 101 - West Melbourne FL 32904 - UNITED STATES - - 00-04-30 (hex) Netgem - 000430 (base 16) Netgem - 27 rue d'Orleans - 92 200 Neuillt s/Seine - FRANCE - - 00-04-31 (hex) GlobalStreams, Inc. - 000431 (base 16) GlobalStreams, Inc. - 2882 Prospect Park Drive - Suite 350 - Rancho Cordova CA 95670 - UNITED STATES - - 00-04-32 (hex) Voyetra Turtle Beach, Inc. - 000432 (base 16) Voyetra Turtle Beach, Inc. - 150 Clearbrook Road, Suite 162 - Elmsford NY 10523 - UNITED STATES - - 00-04-33 (hex) Cyberboard A/S - 000433 (base 16) Cyberboard A/S - Kloevermarken 120 - DK-7190 Billund - DENMARK - - 00-04-34 (hex) Accelent Systems, Inc. - 000434 (base 16) Accelent Systems, Inc. - 2620 Ridgewood Rd., - Suite 300 - Akron OH 44313 - UNITED STATES - - 00-04-35 (hex) Comptek International, Inc. - 000435 (base 16) Comptek International, Inc. - 11 Beacon St. - Boston MA 02108 - UNITED STATES - - 00-04-36 (hex) ELANsat Technologies, Inc. - 000436 (base 16) ELANsat Technologies, Inc. - No. 11, Lane 19, Pateh Road, - Hsinchu TAIWAN, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-37 (hex) Powin Information Technology, Inc. - 000437 (base 16) Powin Information Technology, Inc. - 8F, No. 70, Zhou-Z St. - 114 Nei-Hu Taipei - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-38 (hex) Nortel Networks - 000438 (base 16) Nortel Networks - Department 6800 - 8200 Dixie Road, Suite 100 Brampton, ON - CANADA - - 00-04-39 (hex) Rosco Entertainment Technology, Inc. - 000439 (base 16) Rosco Entertainment Technology, Inc. - 2181 NW Front Ave. - Portland OR 97209 - UNITED STATES - - 00-04-3A (hex) Intelligent Telecommunications, Inc. - 00043A (base 16) Intelligent Telecommunications, Inc. - 1687-2, Sinil-dong - Daedok-gu, Taejon - SOUTH KOREA 306-230 - KOREA, REPUBLIC OF - - 00-04-3B (hex) Lava Computer Mfg., Inc. - 00043B (base 16) Lava Computer Mfg., Inc. - 2 Vulcan St. - Etobicoke, Ontario - CANADA M9W-1L2 - CANADA - - 00-04-3C (hex) SONOS Co., Ltd. - 00043C (base 16) SONOS Co., Ltd. - #725 Pungsan Apt. Factory - 1141-2 Baikseok, ilsan, Goyang, Gyeonggi - Rep. of KOREA Zip Code: 411-815 - KOREA, REPUBLIC OF - - 00-04-3D (hex) INDEL AG - 00043D (base 16) INDEL AG - Tufiwis 26 - CH-8332 Russikon - SWITZERLAND - - 00-04-3E (hex) Telencomm - 00043E (base 16) Telencomm - 2551 Walsh Avenue - Santa Clara CA 95051 - UNITED STATES - - 00-04-3F (hex) ESTeem Wireless Modems, Inc - 00043F (base 16) ESTeem Wireless Modems, Inc - 415 N. Quay St., Suite 4 - Kennewick WA 99336 - UNITED STATES - - 00-04-40 (hex) cyberPIXIE, Inc. - 000440 (base 16) cyberPIXIE, Inc. - 68 E. Wacker Place, - Suite 600 - Chicago IL 60601 - UNITED STATES - - 00-04-41 (hex) Half Dome Systems, Inc. - 000441 (base 16) Half Dome Systems, Inc. - 155 B-1 Moffet Park Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-04-42 (hex) NACT - 000442 (base 16) NACT - 191 W. 5200 N. - Provo UT 84604 - UNITED STATES - - 00-04-43 (hex) Agilent Technologies, Inc. - 000443 (base 16) Agilent Technologies, Inc. - 5301 Stevens Creek Boulevard - Mailstop 54L-SQ - Santa Clara CA 95051 - UNITED STATES - - 00-04-44 (hex) Western Multiplex Corporation - 000444 (base 16) Western Multiplex Corporation - 1196 Borregas Avenue - Suite 500 - Sunnyvale CA 94089 - UNITED STATES - - 00-04-45 (hex) LMS Skalar Instruments GmbH - 000445 (base 16) LMS Skalar Instruments GmbH - Willi-Eichler-Str 11 - D-37079 Goettingen - GERMANY - - 00-04-46 (hex) CYZENTECH Co., Ltd. - 000446 (base 16) CYZENTECH Co., Ltd. - 601 Eunkyeong B/D 141-31, - Samsung-dong, Gangnam-gu, Seoul, - 135-876 KOREA - KOREA, REPUBLIC OF - - 00-04-47 (hex) Acrowave Systems Co., Ltd. - 000447 (base 16) Acrowave Systems Co., Ltd. - Maru B/D 86-6, Nonhyun-Dong - Gangnam-gu, Seoul - KOREA zip: 135-818 - KOREA, REPUBLIC OF - - 00-04-48 (hex) Polaroid Corporation - 000448 (base 16) Polaroid Corporation - 300 Baker Avenue - Concord MA 01742 - UNITED STATES - - 00-04-49 (hex) Mapletree Networks - 000449 (base 16) Mapletree Networks - 315 Norwood Park South - Norwood MA 02062 - UNITED STATES - - 00-04-4A (hex) iPolicy Networks, Inc. - 00044A (base 16) iPolicy Networks, Inc. - 47467 Fremont Blvd. - Fremont CA 94538 - UNITED STATES - - 00-04-4B (hex) NVIDIA - 00044B (base 16) NVIDIA - 3535 Monroe St. - Santa Clara CA 95051 - UNITED STATES - - 00-04-4C (hex) JENOPTIK - 00044C (base 16) JENOPTIK - Laser, Optik, Systeme GmbH - Einkauf, Prussingstraße 41 D-07745 Jena - GERMANY - - 00-04-4D (hex) CISCO SYSTEMS, INC. - 00044D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-4E (hex) CISCO SYSTEMS, INC. - 00044E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-4F (hex) Leukhardt Systemelektronik GmbH - 00044F (base 16) Leukhardt Systemelektronik GmbH - Rudolf-Diesel-Str. 17 - 78532 Tuttlingen - GERMANY - - 00-04-50 (hex) DMD Computers SRL - 000450 (base 16) DMD Computers SRL - Via Monviso, 14 - 10090 Villarbasse (To) - ITALY - - 00-04-51 (hex) Medrad, Inc. - 000451 (base 16) Medrad, Inc. - One Medrad Drive - Indianola PA 15051 - UNITED STATES - - 00-04-52 (hex) RocketLogix, Inc. - 000452 (base 16) RocketLogix, Inc. - 6504 International Parkway - Suite 1200 - Plano TX 75093 - UNITED STATES - - 00-04-53 (hex) YottaYotta, Inc. - 000453 (base 16) YottaYotta, Inc. - 6020- 104 Street - Edmonton, AB T6H 5S4 - CANADA - - 00-04-54 (hex) Quadriga UK - 000454 (base 16) Quadriga UK - Baird House - Arlington Business Park Theale Reading R - ENGLAND - UNITED KINGDOM - - 00-04-55 (hex) ANTARA.net - 000455 (base 16) ANTARA.net - 747 Camden Ave. - Suite A - Campbell CA 95008 - UNITED STATES - - 00-04-56 (hex) Cambium Networks Limited - 000456 (base 16) Cambium Networks Limited - Unit B2, Linhay Business Park, - Eastern Road, - Ashburton Devon TQ13 7UP - UNITED KINGDOM - - 00-04-57 (hex) Universal Access Technology, Inc. - 000457 (base 16) Universal Access Technology, Inc. - 2 Fl., No. 5, Alley 22, - Lane 513, Jui Kuang Road, - Nei Hu Taipei, TAIWAN 114 - TAIWAN, PROVINCE OF CHINA - - 00-04-58 (hex) Fusion X Co., Ltd. - 000458 (base 16) Fusion X Co., Ltd. - #905 Hansol Techno Town - 16-1 Dang-Jung Dong Kun-Po Kyung-Ki do K - Zip 435-030 - KOREA, REPUBLIC OF - - 00-04-59 (hex) Veristar Corporation - 000459 (base 16) Veristar Corporation - 727 Allston Way - Berkeley CA 94710 - UNITED STATES - - 00-04-5A (hex) The Linksys Group, Inc. - 00045A (base 16) The Linksys Group, Inc. - 17401 Armstrong Ave. - Irvine CA 92614 - UNITED STATES - - 00-04-5B (hex) Techsan Electronics Co., Ltd. - 00045B (base 16) Techsan Electronics Co., Ltd. - North Wing - 43 High Street Fareham, Hants P016 7BQ - UNITED KINGDOM - UNITED KINGDOM - - 00-04-5C (hex) Mobiwave Pte Ltd - 00045C (base 16) Mobiwave Pte Ltd - Blk 16, Kallang Place - #07-01/04 - 339156 - SINGAPORE - - 00-04-5D (hex) BEKA Elektronik - 00045D (base 16) BEKA Elektronik - Siemenstraße 29 - Erftstadt 50374 - GERMANY - - 00-04-5E (hex) PolyTrax Information Technology AG - 00045E (base 16) PolyTrax Information Technology AG - Martin-Kollar - Str. 5 - D-81829 Munchen - GERMANY - - 00-04-5F (hex) Avalue Technology, Inc. - 00045F (base 16) Avalue Technology, Inc. - 7F, 228, Lian-Cheng Road - Chung Ho City, Taipei, Taiwan - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-60 (hex) Knilink Technology, Inc. - 000460 (base 16) Knilink Technology, Inc. - 10F, #96, Hsin Tai Wu Rd., - Sec. 1, Hsi Chih, Taipei Hsien, - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-04-61 (hex) EPOX Computer Co., Ltd. - 000461 (base 16) EPOX Computer Co., Ltd. - 11F, #346, Chung San Rd. - Sec. 2, Chung Ho City, Taipei Hsien 235 - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-62 (hex) DAKOS Data & Communication Co., Ltd. - 000462 (base 16) DAKOS Data & Communication Co., Ltd. - 2nd Floor Bethel Building 324-1 - Yangjae-dong Seocho-gu Seoul R.O.K. - Zip code: 137-130 - TAIWAN, PROVINCE OF CHINA - - 00-04-63 (hex) Bosch Security Systems - 000463 (base 16) Bosch Security Systems - 850 Greenfield Road - Lancaster PA 17601-5874 - UNITED STATES - - 00-04-64 (hex) Pulse-Link Inc - 000464 (base 16) Pulse-Link Inc - 1934 Kellogg Avenue - Carlsbad CA 92008 - UNITED STATES - - 00-04-65 (hex) i.s.t isdn-support technik GmbH - 000465 (base 16) i.s.t isdn-support technik GmbH - Rhein Strasse 7E - 14513 Teltow - GERMANY - - 00-04-66 (hex) ARMITEL Co. - 000466 (base 16) ARMITEL Co. - F5, Doman Plaza 353-4, - Yatap-Dong, Pudang-ku, Seong-Name Si, Ky - Republic of KOREA - KOREA, REPUBLIC OF - - 00-04-67 (hex) Wuhan Research Institute of MII - 000467 (base 16) Wuhan Research Institute of MII - 88 Youkeyuan Road, - Hangshan District,Wuhan, Hubei Province, - 430074 430074 P.R.CHINA - CHINA - - 00-04-68 (hex) Vivity, Inc. - 000468 (base 16) Vivity, Inc. - 3360 Mitchell Lane - Boulder CO 80301 - UNITED STATES - - 00-04-69 (hex) Innocom, Inc. - 000469 (base 16) Innocom, Inc. - 655-2 Naebalsan-Dong - Kangseo-Gu, Seoul - 157-280 157-280 KOREA - KOREA, REPUBLIC OF - - 00-04-6A (hex) Navini Networks - 00046A (base 16) Navini Networks - 3605 E. Plano Pkwy, - Suite 400, - Plano TX 75074 - UNITED STATES - - 00-04-6B (hex) Palm Wireless, Inc. - 00046B (base 16) Palm Wireless, Inc. - 48933 Warm Springs Blvd. - Fremont CA 94539 - UNITED STATES - - 00-04-6C (hex) Cyber Technology Co., Ltd. - 00046C (base 16) Cyber Technology Co., Ltd. - 1-45 Yeo Wol-Dong - Oh Jung-Em, Bu Cheon City, - Kyeong Gi-Do Kyeong Gi-Do KOREA - KOREA, REPUBLIC OF - - 00-04-6D (hex) CISCO SYSTEMS, INC. - 00046D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-6E (hex) CISCO SYSTEMS, INC. - 00046E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-6F (hex) Digitel S/A Industria Eletronica - 00046F (base 16) Digitel S/A Industria Eletronica - R. Doutor Joao Ignacio, 1165 - Porto Alegre, RS. Brazil - Zip: 90230.181 - BRAZIL - - 00-04-70 (hex) ipUnplugged AB - 000470 (base 16) ipUnplugged AB - Box 10160 - SE 121 28 Stockholm-Globsen - SWEDEN - - 00-04-71 (hex) IPrad - 000471 (base 16) IPrad - 24 Raoul Wallenberg St. - Tel-Aviv 69719 - ISRAEL - - 00-04-72 (hex) Telelynx, Inc. - 000472 (base 16) Telelynx, Inc. - 3F-1, 66 Nankan Rd., - Sec. 2 Lu Chu, Tao-Yuan - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-04-73 (hex) Photonex Corporation - 000473 (base 16) Photonex Corporation - 8C Preston Court - Bedford MA 01730 - UNITED STATES - - 00-04-74 (hex) LEGRAND - 000474 (base 16) LEGRAND - 145 Avenue De Lattre - 57045 Limoges - FRANCE - - 00-04-75 (hex) 3 Com Corporation - 000475 (base 16) 3 Com Corporation - 5400 Bayfront Plaza - MS: 4220 - Santa Clara CA 95052 - UNITED STATES - - 00-04-76 (hex) 3 Com Corporation - 000476 (base 16) 3 Com Corporation - 5400 Bayfront Plaza - MS: 4220 - Santa Clara CA 95052 - UNITED STATES - - 00-04-77 (hex) Scalant Systems, Inc. - 000477 (base 16) Scalant Systems, Inc. - 2040 Martin Avenue - Santa Clara CA 95050 - UNITED STATES - - 00-04-78 (hex) G. Star Technology Corporation - 000478 (base 16) G. Star Technology Corporation - 4th Floor, No. 118, Sector 2 - Chung Hsiao East Road - Taipei City Taipei City TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-04-79 (hex) Radius Co., Ltd. - 000479 (base 16) Radius Co., Ltd. - 1-48-11, Itabashi - Roje Bldg., No. 3, 6F Itabashi-ku, Tokyo - JAPAN - - 00-04-7A (hex) AXXESSIT ASA - 00047A (base 16) AXXESSIT ASA - AXXESSIT ASA HALDEN - Box 1053 1787 Berg i Ostfold - NORWAY - - 00-04-7B (hex) Schlumberger - 00047B (base 16) Schlumberger - Sugar Land Product Center - 110 Schlumberger Drive - Sugar Land TX 77478 - UNITED STATES - - 00-04-7C (hex) Skidata AG - 00047C (base 16) Skidata AG - T-697553 Untersbergstr. 40 - A-5083 Gartenau - AUSTRIA - - 00-04-7D (hex) Pelco - 00047D (base 16) Pelco - 3500 Pelco Way - Clovis CA 93612 - UNITED STATES - - 00-04-7E (hex) Siqura B.V. - 00047E (base 16) Siqura B.V. - Zuidelijk Halfrond 4 - 2801 DD Gouda - NETHERLANDS - - 00-04-7F (hex) Chr. Mayr GmbH & Co. KG - 00047F (base 16) Chr. Mayr GmbH & Co. KG - Eichenstraße 1 - D-87665 Mauerstetten - GERMANY - - 00-04-80 (hex) Brocade Communications Systems, Inc - 000480 (base 16) Brocade Communications Systems, Inc - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-04-81 (hex) Econolite Control Products, Inc. - 000481 (base 16) Econolite Control Products, Inc. - 3360 E. La Palma Ave. - Anaheim CA 92806 - UNITED STATES - - 00-04-82 (hex) Medialogic Corp. - 000482 (base 16) Medialogic Corp. - 0-3, Toyamaken-Sangyou - Koudoka-Center, 5, Office Park, Takaoka- - JAPAN - - 00-04-83 (hex) Deltron Technology, Inc. - 000483 (base 16) Deltron Technology, Inc. - 8F-3, No. 125, Lane 235 - Pao-Chiao Rd., Hsintien, - Taipei TAIWAN, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-84 (hex) Amann GmbH - 000484 (base 16) Amann GmbH - Unteranger 6 - D-82041 Oberhaching - GERMANY - - 00-04-85 (hex) PicoLight - 000485 (base 16) PicoLight - 4665 Nautilus Court South - Boulder CO 80301 - UNITED STATES - - 00-04-86 (hex) ITTC, University of Kansas - 000486 (base 16) ITTC, University of Kansas - 2335 Irving Hill Rd. - Lawrence KS 66045 - UNITED STATES - - 00-04-87 (hex) Cogency Semiconductor, Inc. - 000487 (base 16) Cogency Semiconductor, Inc. - 362 Terry Fox Drive, Suite 210 - Kanata, ON, K2K 2P5 - CANADA - - 00-04-88 (hex) Eurotherm Controls - 000488 (base 16) Eurotherm Controls - 741F Miller Drive - Lessburg VA 20175 - UNITED STATES - - 00-04-89 (hex) YAFO Networks, Inc. - 000489 (base 16) YAFO Networks, Inc. - 1340F Charwood Rd. - Hanover MD 21076 - UNITED STATES - - 00-04-8A (hex) Temia Vertriebs GmbH - 00048A (base 16) Temia Vertriebs GmbH - Landsbergerstraße 320 - D-80687 Munich - GERMANY - - 00-04-8B (hex) Poscon Corporation - 00048B (base 16) Poscon Corporation - #606 Ho-Dong, Nam Gu, - Pohang City, Kyungbuk, - SOUTH KOREA - KOREA, REPUBLIC OF - - 00-04-8C (hex) Nayna Networks, Inc. - 00048C (base 16) Nayna Networks, Inc. - 157 Topaz St. - Milpitas CA 95035 - UNITED STATES - - 00-04-8D (hex) Teo Technologies, Inc - 00048D (base 16) Teo Technologies, Inc - 11609 49th Place West - Mukilteo WA 98275 - UNITED STATES - - 00-04-8E (hex) Ohm Tech Labs, Inc. - 00048E (base 16) Ohm Tech Labs, Inc. - 141 Lanza Ave., B-12 - Garfield NJ 07026 - UNITED STATES - - 00-04-8F (hex) TD Systems Corporation - 00048F (base 16) TD Systems Corporation - 100 Bearfoot Rd. - 64 Ontario Drive - Hudson MA 01749 - UNITED STATES - - 00-04-90 (hex) Optical Access - 000490 (base 16) Optical Access - P.O. Box 114 - Yokneam, 20692 - ISRAEL - - 00-04-91 (hex) Technovision, Inc. - 000491 (base 16) Technovision, Inc. - 5155 Spectrum Way, Unit #31 - Mississauga, Ontario - L4W 5A1 - CANADA - - 00-04-92 (hex) Hive Internet, Ltd. - 000492 (base 16) Hive Internet, Ltd. - Unit 2, Church View Business Centre - Louth Road - Binbrook Market Rasen, Lincolnshire LN8 6BY - UNITED KINGDOM - - 00-04-93 (hex) Tsinghua Unisplendour Co., Ltd. - 000493 (base 16) Tsinghua Unisplendour Co., Ltd. - Th-Unis Building Tsinghua - University, Bejing 100084 - P.R. - CHINA - - 00-04-94 (hex) Breezecom, Ltd. - 000494 (base 16) Breezecom, Ltd. - Atidim Technology Park - Bldg. 1, P.O.B. 13139 Tel-Aviv 61131 - ISRAEL - - 00-04-95 (hex) Tejas Networks India Limited - 000495 (base 16) Tejas Networks India Limited - #58, 1st Main Road, J.P. Nagar, - 3rd Phase, Karnataka - Bangalore 560078 - INDIA - - 00-04-96 (hex) Extreme Networks - 000496 (base 16) Extreme Networks - 3585 Monroe St. - Santa Clara CA 95051 - UNITED STATES - - 00-04-97 (hex) MacroSystem Digital Video AG - 000497 (base 16) MacroSystem Digital Video AG - Schoellinger Feld 28 - 58300 Wetter, F.R. - GERMANY - - 00-04-98 (hex) Mahi Networks - 000498 (base 16) Mahi Networks - 1039 N. McDowell Blvd. - Petaluma CA 94954 - UNITED STATES - - 00-04-99 (hex) Chino Corporation - 000499 (base 16) Chino Corporation - 1 Mori, Fujioka City, - Gunma Pref. JAPAN - Zip: 375-8505 - JAPAN - - 00-04-9A (hex) CISCO SYSTEMS, INC. - 00049A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-9B (hex) CISCO SYSTEMS, INC. - 00049B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-9C (hex) Surgient Networks, Inc. - 00049C (base 16) Surgient Networks, Inc. - 3520 Executive Center Drive - Suite 300 - Austin TX 78731 - UNITED STATES - - 00-04-9D (hex) Ipanema Technologies - 00049D (base 16) Ipanema Technologies - 28, Rue De La Redoute - 92260 Fontenay Aux Roses - FRANCE - - 00-04-9E (hex) Wirelink Co., Ltd. - 00049E (base 16) Wirelink Co., Ltd. - 11F, Geoseong B/D 541, Dowha-Dong, - Mapo-Gu, Seoul, 121-701, - KOREA - KOREA, REPUBLIC OF - - 00-04-9F (hex) Freescale Semiconductor - 00049F (base 16) Freescale Semiconductor - 7700 West Parmer Lane - MD PL59 - Austin TX 78729 - UNITED STATES - - 00-04-A0 (hex) Verity Instruments, Inc. - 0004A0 (base 16) Verity Instruments, Inc. - 2901 Eisenhower St. - Carrollton TX 75007 - UNITED STATES - - 00-04-A1 (hex) Pathway Connectivity - 0004A1 (base 16) Pathway Connectivity - 1439-17 Avenue SE - Calgary Alberta T2G 1J9 - CANADA - - 00-04-A2 (hex) L.S.I. Japan Co., Ltd. - 0004A2 (base 16) L.S.I. Japan Co., Ltd. - 1-8-14 Sendagaya Shibuya-Ku - Tokyo 151-0051 - JAPAN - - 00-04-A3 (hex) Microchip Technology, Inc. - 0004A3 (base 16) Microchip Technology, Inc. - 2355 W. Chandler Blvd. - Chandler AZ 85224 - UNITED STATES - - 00-04-A4 (hex) NetEnabled, Inc. - 0004A4 (base 16) NetEnabled, Inc. - 1275 Kinnear Rd. - Columbus OH 43212 - UNITED STATES - - 00-04-A5 (hex) Barco Projection Systems NV - 0004A5 (base 16) Barco Projection Systems NV - Noordlaan 5 - B8520 Kuurne - BELGIUM - - 00-04-A6 (hex) SAF Tehnika Ltd. - 0004A6 (base 16) SAF Tehnika Ltd. - 91 Dzirnavu Str., - Riga, LV-1011, - LATVIA - - 00-04-A7 (hex) FabiaTech Corporation - 0004A7 (base 16) FabiaTech Corporation - 4F-3, No. 18, Lane 609 - Chung-Hsin Rd., Sec. 5 San Chung City, - Taipei Hsien, TAIWAN R.O.C - TAIWAN, PROVINCE OF CHINA - - 00-04-A8 (hex) Broadmax Technologies, Inc. - 0004A8 (base 16) Broadmax Technologies, Inc. - 180, Wai Yip Street, - Hwun Tong, - HONG KONG - HONG KONG - - 00-04-A9 (hex) SandStream Technologies, Inc. - 0004A9 (base 16) SandStream Technologies, Inc. - 1955 Lakeway Dr. - Lewisville TX 75057 - UNITED STATES - - 00-04-AA (hex) Jetstream Communications - 0004AA (base 16) Jetstream Communications - 5400 Hellyer Avenue - San Jose CA 95138-1005 - UNITED STATES - - 00-04-AB (hex) Comverse Network Systems, Inc. - 0004AB (base 16) Comverse Network Systems, Inc. - 29 Habarzel Street. - Tel-Aviv 69710 - ISRAEL - - 00-04-AC (hex) IBM Corp - 0004AC (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-04-AD (hex) Malibu Networks - 0004AD (base 16) Malibu Networks - 26637 Agoura Rd. - Calabasas CA 91302 - UNITED STATES - - 00-04-AE (hex) Sullair Corporation - 0004AE (base 16) Sullair Corporation - 3700 East Michigan Blvd - Michigan City IN 46360 - UNITED STATES - - 00-04-AF (hex) Digital Fountain, Inc. - 0004AF (base 16) Digital Fountain, Inc. - 600 Alabama St. - San Francisco CA 94110 - UNITED STATES - - 00-04-B0 (hex) ELESIGN Co., Ltd. - 0004B0 (base 16) ELESIGN Co., Ltd. - 9Fl. TaeKyoung Bldg., - 42-42 BongChun-dong KwanAk-gu, Seoul, - R.O. KOREA - KOREA, REPUBLIC OF - - 00-04-B1 (hex) Signal Technology, Inc. - 0004B1 (base 16) Signal Technology, Inc. - 3rd. Fl. Dabo Bldg. - 37-2 koyo songpa - Seoul KOREA 138-110 - KOREA, REPUBLIC OF - - 00-04-B2 (hex) ESSEGI SRL - 0004B2 (base 16) ESSEGI SRL - Via Del Cavaratori, 17 - 20092 Cinisello B. (M1) - ITALY - - 00-04-B3 (hex) Videotek, Inc. - 0004B3 (base 16) Videotek, Inc. - 243 Shoemaker Rd. - Pottstown PA 19464 - UNITED STATES - - 00-04-B4 (hex) CIAC - 0004B4 (base 16) CIAC - 18 rue Joseph BARA - 92130 Issy-les-Molineaux - FRANCE - - 00-04-B5 (hex) Equitrac Corporation - 0004B5 (base 16) Equitrac Corporation - 1905 N.W. 82nd Avenue - Miami FL 33126 - UNITED STATES - - 00-04-B6 (hex) Stratex Networks, Inc. - 0004B6 (base 16) Stratex Networks, Inc. - 64 White Road - Retreat, - Cape Town 7945 - SOUTH AFRICA - - 00-04-B7 (hex) AMB i.t. Holding - 0004B7 (base 16) AMB i.t. Holding - Zuiderhoutlaan 4 - PJ Haarlem 2012 - NETHERLANDS - - 00-04-B8 (hex) Kumahira Co., Ltd. - 0004B8 (base 16) Kumahira Co., Ltd. - 4-34 Ujinahigashi 2-Chome - Minamiku Hiroshima - JAPAN 734-8567 - JAPAN - - 00-04-B9 (hex) S.I. Soubou, Inc. - 0004B9 (base 16) S.I. Soubou, Inc. - 4-2586-8 - Hanazono - Tokorozawa Sitama 359-0047 - JAPAN - - 00-04-BA (hex) KDD Media Will Corporation - 0004BA (base 16) KDD Media Will Corporation - 2-1-23 Nakameguro - Meguro-Ku Tokyo - 153-0061 - JAPAN - - 00-04-BB (hex) Bardac Corporation - 0004BB (base 16) Bardac Corporation - 40 Log Canoe Circle - Stevensville MD 21666 - UNITED STATES - - 00-04-BC (hex) Giantec, Inc. - 0004BC (base 16) Giantec, Inc. - 4F, No. 3, Lane 123, - Pao Chung Rd., Hsien Tien City, Taipei - TAIWAN 231 TAIWAN 231 R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-04-BD (hex) ARRIS Group, Inc. - 0004BD (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-04-BE (hex) OptXCon, Inc. - 0004BE (base 16) OptXCon, Inc. - P.O. Box 13449 - Research Triangle Park NC 27709-3449 - UNITED STATES - - 00-04-BF (hex) VersaLogic Corp. - 0004BF (base 16) VersaLogic Corp. - 3888 Stewart Rd. - Eugene OR 97402 - UNITED STATES - - 00-04-C0 (hex) CISCO SYSTEMS, INC. - 0004C0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-C1 (hex) CISCO SYSTEMS, INC. - 0004C1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-C2 (hex) Magnipix, Inc. - 0004C2 (base 16) Magnipix, Inc. - 3539 St-Charles Blvd., Suite 212 - Kirkland (Quebec) - CANADA H9H3C4 - CANADA - - 00-04-C3 (hex) CASTOR Informatique - 0004C3 (base 16) CASTOR Informatique - 2, Rue Du Kefir - Senia 343 - 94537 Orly Cedex - FRANCE - - 00-04-C4 (hex) Allen & Heath Limited - 0004C4 (base 16) Allen & Heath Limited - Kernick Industrial Estate, Penryn - Cornwall England TR10 9LU - UNITED KINGDOM - - 00-04-C5 (hex) ASE Technologies, USA - 0004C5 (base 16) ASE Technologies, USA - 6721 Baum Dr. - Knoxville TN 37919 - UNITED STATES - - 00-04-C6 (hex) Yamaha Motor Co., Ltd. - 0004C6 (base 16) Yamaha Motor Co., Ltd. - Information System Division - 2500 Shingai Iwata, Shizuoka - Japan Zip: 438-8501 - JAPAN - - 00-04-C7 (hex) NetMount - 0004C7 (base 16) NetMount - P.O.B. 2325 - Kadima 60920 - ISRAEL - - 00-04-C8 (hex) LIBA Maschinenfabrik GmbH - 0004C8 (base 16) LIBA Maschinenfabrik GmbH - PO Box 1120 - D95112 Naila - GERMANY - - 00-04-C9 (hex) Micro Electron Co., Ltd. - 0004C9 (base 16) Micro Electron Co., Ltd. - 13-1-205 Aobaokakita - Suita-city Osaka 565-0801 - JAPAN - - 00-04-CA (hex) FreeMs Corp. - 0004CA (base 16) FreeMs Corp. - Shinhan Bldg. 6F, - 45-11 Yoido-Dong, Youngdeungpo-ku, - Seoul 150-736 KOREA - KOREA, REPUBLIC OF - - 00-04-CB (hex) Tdsoft Communication, Ltd. - 0004CB (base 16) Tdsoft Communication, Ltd. - 60 Medinat Hayehudim St. - Herzlia 46766 - ISRAEL - - 00-04-CC (hex) Peek Traffic B.V. - 0004CC (base 16) Peek Traffic B.V. - Postbus 2542 - 3800 GB Amersfoot - The - NETHERLANDS - - 00-04-CD (hex) Extenway Solutions Inc - 0004CD (base 16) Extenway Solutions Inc - 500 boul. Morgan - Suite 100 - Baie-d'Urfe Quebec H9X 3V1 - CANADA - - 00-04-CE (hex) Patria Ailon - 0004CE (base 16) Patria Ailon - Naulakatu 3 - FIN-33100 Tampere - FINLAND - - 00-04-CF (hex) Seagate Technology - 0004CF (base 16) Seagate Technology - M/S NW1F01 - 389 Disc Drive - Longmont CO 80503 - UNITED STATES - - 00-04-D0 (hex) Softlink s.r.o. - 0004D0 (base 16) Softlink s.r.o. - Tomkova 409 - Kralupy n. Vltavou - Czech Republic - CZECH REPUBLIC - - 00-04-D1 (hex) Drew Technologies, Inc. - 0004D1 (base 16) Drew Technologies, Inc. - 3915 Research Park Dr - Suite A10 - Ann Arbor MI 48108 - UNITED STATES - - 00-04-D2 (hex) Adcon Telemetry GmbH - 0004D2 (base 16) Adcon Telemetry GmbH - Inkustraße 24 - A-3400 Klosterneuburg - AUSTRIA - - 00-04-D3 (hex) Toyokeiki Co., Ltd. - 0004D3 (base 16) Toyokeiki Co., Ltd. - Wada 3967-10, Matsumoto-City - Nagano 390-1298, - JAPAN - - 00-04-D4 (hex) Proview Electronics Co., Ltd. - 0004D4 (base 16) Proview Electronics Co., Ltd. - 6F, No. 1, Pau-Sheng Road - Yung Ho City, Taipei, - TAIWAN, PROVINCE OF CHINA - - 00-04-D5 (hex) Hitachi Information & Communication Engineering, Ltd. - 0004D5 (base 16) Hitachi Information & Communication Engineering, Ltd. - Queen's Tower B21F, 2-3-3, Minatomirai, - Nishi-ku, Yokohama, 220-6121 - JAPAN - - 00-04-D6 (hex) Takagi Industrial Co., Ltd. - 0004D6 (base 16) Takagi Industrial Co., Ltd. - Electronic Instrument Div. - 3508, Kamiide-Mikaeshi, Eujinomiya-shi, - 418-0103 418-0103 - JAPAN - - 00-04-D7 (hex) Omitec Instrumentation Ltd. - 0004D7 (base 16) Omitec Instrumentation Ltd. - Hopton Industrial Est. - London Rd., Devizes Wiltshire SN10 2EU - ENGLAND - UNITED KINGDOM - - 00-04-D8 (hex) IPWireless, Inc. - 0004D8 (base 16) IPWireless, Inc. - 4 Landsowne Court - Bumpers Way Chippenham, Wiltshire, - SN14 GRZ UK - UNITED KINGDOM - - 00-04-D9 (hex) Titan Electronics, Inc. - 0004D9 (base 16) Titan Electronics, Inc. - Rm 7, 11 Fl., No. 398, - Huan-Pei Road, Chung-Li, - Taoyuan Taoyuan TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-04-DA (hex) Relax Technology, Inc. - 0004DA (base 16) Relax Technology, Inc. - DBA/ Granite Digital - 3101 Whipple Road - Union City CA 94587 - UNITED STATES - - 00-04-DB (hex) Tellus Group Corp. - 0004DB (base 16) Tellus Group Corp. - 4F, No. 15 Industry E. Rd., IX - Science-Based Industrial Park - Hsinchu Hsinchu Taiwan - TAIWAN, PROVINCE OF CHINA - - 00-04-DC (hex) Nortel Networks - 0004DC (base 16) Nortel Networks - Department 6800 - 8200 Dixie Road, Suite 100 Brapton ON L6 - CANADA - - 00-04-DD (hex) CISCO SYSTEMS, INC. - 0004DD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-DE (hex) CISCO SYSTEMS, INC. - 0004DE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-04-DF (hex) Teracom Telematica Ltda. - 0004DF (base 16) Teracom Telematica Ltda. - R. Felipe Neri, 246 CJ. 301 - 90440-150 Porto Allegre RS - Bazil - BRAZIL - - 00-04-E0 (hex) Procket Networks - 0004E0 (base 16) Procket Networks - 1100 Cadillac Court - Milpitas CA 95035 - UNITED STATES - - 00-04-E1 (hex) Infinior Microsystems - 0004E1 (base 16) Infinior Microsystems - 2F, Accufar Bldg, 234-10, - Jamsil-Dong, Songpa-Gu - Seoul KOREA 138-220 - KOREA, REPUBLIC OF - - 00-04-E2 (hex) SMC Networks, Inc. - 0004E2 (base 16) SMC Networks, Inc. - 6 Hughes - Irvine CA 92618 - UNITED STATES - - 00-04-E3 (hex) Accton Technology Corp. - 0004E3 (base 16) Accton Technology Corp. - No. 1 Creation Rd. III, - SBIP - Hsinchu Hsinchu TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-04-E4 (hex) Daeryung Ind., Inc. - 0004E4 (base 16) Daeryung Ind., Inc. - #219-6, Kasan Dong, - Kumchun ku, - Seoul Seoul KOREA - KOREA, REPUBLIC OF - - 00-04-E5 (hex) Glonet Systems, Inc. - 0004E5 (base 16) Glonet Systems, Inc. - 11Fl., Jeil Bldg., 94-46, 7Ka - Youngdungpo-dong Yongdungpo-Ku Seoul, 15 - KOREA, REPUBLIC OF - - 00-04-E6 (hex) Banyan Network Private Limited - 0004E6 (base 16) Banyan Network Private Limited - 443, 8th Floor, Guna Complex - Annasalai, Chennai-600 018 - INDIA - - 00-04-E7 (hex) Lightpointe Communications, Inc - 0004E7 (base 16) Lightpointe Communications, Inc - 10140 Barnes Canyon Road - San Diego CA 92121 - UNITED STATES - - 00-04-E8 (hex) IER, Inc. - 0004E8 (base 16) IER, Inc. - 4501 So. General Bruce Dr - Suite 50 - Temple TX 76502 - UNITED STATES - - 00-04-E9 (hex) Infiniswitch Corporation - 0004E9 (base 16) Infiniswitch Corporation - 134 Flanders Road - Westborough MA 01581 - UNITED STATES - - 00-04-EA (hex) Hewlett-Packard Company - 0004EA (base 16) Hewlett-Packard Company - 11000 Wolfe Road, Mailstop 42LE - Cupertino CA 95014 - UNITED STATES - - 00-04-EB (hex) Paxonet Communications, Inc. - 0004EB (base 16) Paxonet Communications, Inc. - 4046 Clipper Court - Fremont CA 94538 - UNITED STATES - - 00-04-EC (hex) Memobox SA - 0004EC (base 16) Memobox SA - 1, Place Dame Suzanne - 91190 Saint Aubin - FRANCE - - 00-04-ED (hex) Billion Electric Co., Ltd. - 0004ED (base 16) Billion Electric Co., Ltd. - 8F, No.192, Sec.2, Chung Hsing Rd., - Hsin Tien City, Taipei Hsien - Taiwan Taiwan ROC - TAIWAN, PROVINCE OF CHINA - - 00-04-EE (hex) Lincoln Electric Company - 0004EE (base 16) Lincoln Electric Company - 22801 St. Clair Avenue - Cleveland OH 44117-1199 - UNITED STATES - - 00-04-EF (hex) Polestar Corp. - 0004EF (base 16) Polestar Corp. - RM #802 SeoGeon B/D, 1480, - GwanYang-Dong, DongAn-Gu, AnYang City, 4 - Korea (ROK) - KOREA, REPUBLIC OF - - 00-04-F0 (hex) International Computers, Ltd - 0004F0 (base 16) International Computers, Ltd - 1 Wenlock Way - West Gorton Manchester, M12 5DR - UK - UNITED KINGDOM - - 00-04-F1 (hex) WhereNet - 0004F1 (base 16) WhereNet - 107 W. McKinney Avenue - Rogersville TN 37857 - UNITED STATES - - 00-04-F2 (hex) Polycom - 0004F2 (base 16) Polycom - 1000 West 14th Street - North Vancouver, B.C. - Canada V7P3P3 - CANADA - - 00-04-F3 (hex) FS FORTH-SYSTEME GmbH - 0004F3 (base 16) FS FORTH-SYSTEME GmbH - Küferstraße 8 - D-79206 Breisach - GERMANY - - 00-04-F4 (hex) Infinite Electronics Inc. - 0004F4 (base 16) Infinite Electronics Inc. - No.478-1, Sec 2 - Ching Hai Road 407, Tai Chung - TAIWAN, PROVINCE OF CHINA - - 00-04-F5 (hex) SnowShore Networks, Inc. - 0004F5 (base 16) SnowShore Networks, Inc. - 285 Billerica Road - Chelmsford MA 01824 - UNITED STATES - - 00-04-F6 (hex) Amphus - 0004F6 (base 16) Amphus - 2372 Qume Drive, #F - San Jose CA 95131 - UNITED STATES - - 00-04-F7 (hex) Omega Band, Inc. - 0004F7 (base 16) Omega Band, Inc. - 9020-I Capital of Texas Hghwy N - Suite #270 - Austin TX 78759 - UNITED STATES - - 00-04-F8 (hex) QUALICABLE TV Industria E Com., Ltda - 0004F8 (base 16) QUALICABLE TV Industria E Com., Ltda - Av. Joao Paulo Ablas, 308 - Jardim Da Gloria - Cotia -SP CEP 06711-2 - BRAZIL - - 00-04-F9 (hex) Xtera Communications, Inc. - 0004F9 (base 16) Xtera Communications, Inc. - 500 W Bethany Drive - Allen TX 75013 - UNITED STATES - - 00-04-FA (hex) NBS Technologies Inc. - 0004FA (base 16) NBS Technologies Inc. - 703 Evans Avenue, Suite 400 - Toronto - Ontario M9C 5E9 - CANADA - - 00-04-FB (hex) Commtech, Inc. - 0004FB (base 16) Commtech, Inc. - 9011 E. 37th Street - Wichita KS 67226-2006 - UNITED STATES - - 00-04-FC (hex) Stratus Computer (DE), Inc. - 0004FC (base 16) Stratus Computer (DE), Inc. - 111 Powdermill Road - Maynard MA 01754 - UNITED STATES - - 00-04-FD (hex) Japan Control Engineering Co., Ltd. - 0004FD (base 16) Japan Control Engineering Co., Ltd. - 1-5-1, Higashiamagawa, Takatsuki-shi - Osaka 569-0012 - JAPAN - - 00-04-FE (hex) Pelago Networks - 0004FE (base 16) Pelago Networks - 701 E. Plano Parkway - Ste. #205 - Plano TX 75074 - UNITED STATES - - 00-04-FF (hex) Acronet Co., Ltd. - 0004FF (base 16) Acronet Co., Ltd. - Saman B/D 2Fl - 811-15 Bangbae-Dong Seocho-ku, Seoul - 137-064 - KOREA, REPUBLIC OF - - 00-05-00 (hex) CISCO SYSTEMS, INC. - 000500 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-01 (hex) CISCO SYSTEMS, INC. - 000501 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-02 (hex) Apple - 000502 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-05-03 (hex) ICONAG - 000503 (base 16) ICONAG - AM Bahnhof 2 - 55765 Birkenfeld - GERMANY - - 00-05-04 (hex) Naray Information & Communication Enterprise - 000504 (base 16) Naray Information & Communication Enterprise - 3F San Woo Bldg., 1543-11 - Seocho-Dong, Seocho-Ku, - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-05-05 (hex) Systems Integration Solutions, Inc. - 000505 (base 16) Systems Integration Solutions, Inc. - 3922 Coconut Palm Drive, - Suite 106 - Tampa FL 33619 - UNITED STATES - - 00-05-06 (hex) Reddo Networks AB - 000506 (base 16) Reddo Networks AB - Livdjursgatan 4 - SE 121 62 Johanneshov - SWEDEN - - 00-05-07 (hex) Fine Appliance Corp. - 000507 (base 16) Fine Appliance Corp. - 7Fl., No. 499, - Chung-Cheng Rd., Hsintien, Taipei - TAIWAN, PROVINCE OF CHINA - - 00-05-08 (hex) Inetcam, Inc. - 000508 (base 16) Inetcam, Inc. - 10171 Pacific Mesa Blvd. - San Diego CA 92121 - UNITED STATES - - 00-05-09 (hex) AVOC Nishimura Ltd. - 000509 (base 16) AVOC Nishimura Ltd. - Jogasaki 4-16-14 - Miyazaki-city, Miyazaki 880-0917, - JAPAN - - 00-05-0A (hex) ICS Spa - 00050A (base 16) ICS Spa - Via Romano AL - 10010 Scarmagno (TO) - ITALY - - 00-05-0B (hex) SICOM Systems, Inc. - 00050B (base 16) SICOM Systems, Inc. - 4140 Skyron Drive - Doylestown PA 18901 - UNITED STATES - - 00-05-0C (hex) Network Photonics, Inc. - 00050C (base 16) Network Photonics, Inc. - 451 Aviation Boulevard - Santa Rosa CA 95403 - UNITED STATES - - 00-05-0D (hex) Midstream Technologies, Inc. - 00050D (base 16) Midstream Technologies, Inc. - 777 108th Ave. NE - Suite 1700 - Bellevue WA 98004-5140 - UNITED STATES - - 00-05-0E (hex) 3ware, Inc. - 00050E (base 16) 3ware, Inc. - 701 E. Middlefield Rd. - Suite 300 - Mt. View CA 94043 - UNITED STATES - - 00-05-0F (hex) Tanaka S/S Ltd. - 00050F (base 16) Tanaka S/S Ltd. - 1942 Nomura Hirooka - Shiojiri-City - Nagano 399-0702 - JAPAN - - 00-05-10 (hex) Infinite Shanghai Communication Terminals Ltd. - 000510 (base 16) Infinite Shanghai Communication Terminals Ltd. - 777 Chungiao Road, Pudong - Shanghai 201206, - CHINA - - 00-05-11 (hex) Complementary Technologies Ltd - 000511 (base 16) Complementary Technologies Ltd - Comtech House, 28 Manchester Road - Westhoughton BOLTON - BL5 3QJ - UNITED KINGDOM - - 00-05-12 (hex) Zebra Technologies Inc - 000512 (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - 00-05-13 (hex) VTLinx Multimedia Systems, Inc. - 000513 (base 16) VTLinx Multimedia Systems, Inc. - 8401 Colesville Road, - Suite 750 - Silver Spring MD 20910 - UNITED STATES - - 00-05-14 (hex) KDT Systems Co., Ltd. - 000514 (base 16) KDT Systems Co., Ltd. - 102-6, Chobu-Li, Mohyun-Myun, - Yongin-City, Kyungki-Do, - KOREA, REPUBLIC OF - - 00-05-15 (hex) Nuark Co., Ltd. - 000515 (base 16) Nuark Co., Ltd. - 12F, Anyang K center, 1591-9, Burim-dong - Dongan-gu, Anyang-si, - Gunggi-do 431-065 - KOREA, REPUBLIC OF - - 00-05-16 (hex) SMART Modular Technologies - 000516 (base 16) SMART Modular Technologies - 4305 Cushing Pkwy - Fremont CA 94538 - UNITED STATES - - 00-05-17 (hex) Shellcomm, Inc. - 000517 (base 16) Shellcomm, Inc. - Rm #6122 ETRI TBI Center, 1, - Eoeun-Dong, Yusong-Gu, Taejon, 305-333, - KOREA, REPUBLIC OF - - 00-05-18 (hex) Jupiters Technology - 000518 (base 16) Jupiters Technology - PO Box 12693 - Elizabeth Street Brisbane QLD 4002 - AUSTRALIA - - 00-05-19 (hex) Siemens Building Technologies AG, - 000519 (base 16) Siemens Building Technologies AG, - Cerberus Division - alte Landstrasse 411 CH-8708 Maennedorf - SWITZERLAND - - 00-05-1A (hex) 3Com Europe Ltd. - 00051A (base 16) 3Com Europe Ltd. - 3Com Centre, Boundary Way, - Hempstead, Herts, HP2 7YU - UNITED KINGDOM - - 00-05-1B (hex) Magic Control Technology Corporation - 00051B (base 16) Magic Control Technology Corporation - 6F, No. 120-11 Chung Shan Rd. - Sec 3, Chung Ho Taipei - TAIWAN, PROVINCE OF CHINA - - 00-05-1C (hex) Xnet Technology Corp. - 00051C (base 16) Xnet Technology Corp. - 9F-16, No. 12, Lane 609, - Sec. 5, Chung Hsin Road, San Chung City, - TAIWAN, PROVINCE OF CHINA - - 00-05-1D (hex) Airocon, Inc. - 00051D (base 16) Airocon, Inc. - 116 Houghton Lane - Boxboro MA 01719 - UNITED STATES - - 00-05-1E (hex) Brocade Communications Systems, Inc. - 00051E (base 16) Brocade Communications Systems, Inc. - 110 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-05-1F (hex) Taijin Media Co., Ltd. - 00051F (base 16) Taijin Media Co., Ltd. - 640-8 Tungchon-Dong - Kangseo-Gu, - Seoul 157-030 - KOREA, REPUBLIC OF - - 00-05-20 (hex) Smartronix, Inc. - 000520 (base 16) Smartronix, Inc. - 22685 Three Notch Rd. - California MD 20619 - UNITED STATES - - 00-05-21 (hex) Control Microsystems - 000521 (base 16) Control Microsystems - 48 Steacie Drive - Ontario K2K 2A9 - CANADA - - 00-05-22 (hex) LEA*D Corporation, Inc. - 000522 (base 16) LEA*D Corporation, Inc. - Advatech Bldg. - Teradion Ind. Park D.N. Misgav, 20179 - ISRAEL - - 00-05-23 (hex) AVL List GmbH - 000523 (base 16) AVL List GmbH - Hans List Platz 1 - Graz 8020 - AUSTRIA - - 00-05-24 (hex) BTL System (HK) Limited - 000524 (base 16) BTL System (HK) Limited - 14/F., Blk. B, Vita Tower, - 29 Wong Chuk Hang Rd., - Aberdeen - HONG KONG - - 00-05-25 (hex) Puretek Industrial Co., Ltd. - 000525 (base 16) Puretek Industrial Co., Ltd. - No. 14, 4 Flr. Lane 235 - Pao Chiao Road Hsin Tien, Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-05-26 (hex) IPAS GmbH - 000526 (base 16) IPAS GmbH - Hölscherstr. 27 - 47167 Duisburg - GERMANY - - 00-05-27 (hex) SJ Tek Co. Ltd - 000527 (base 16) SJ Tek Co. Ltd - Ho gae Dong 976-5, Dong An Ku, - An yang City, Kyung Kee Do, - KOREA, REPUBLIC OF - - 00-05-28 (hex) New Focus, Inc. - 000528 (base 16) New Focus, Inc. - 2630 Walsh Ave. - Santa Clara CA 95051 - UNITED STATES - - 00-05-29 (hex) Shanghai Broadan Communication Technology Co., Ltd - 000529 (base 16) Shanghai Broadan Communication Technology Co., Ltd - 15F, Suntime International Mansion - No. 450 Fushan Road, Pudong District, Sh - 200122 - CHINA - - 00-05-2A (hex) Ikegami Tsushinki Co., Ltd. - 00052A (base 16) Ikegami Tsushinki Co., Ltd. - 5-6-16 Ikegami Ohta-ku, - Tokyo - 146-8567 - JAPAN - - 00-05-2B (hex) HORIBA, Ltd. - 00052B (base 16) HORIBA, Ltd. - 2 Miyanohigashi, Kisshoin, - Minami-ku, Kyoto - 601-8510 - JAPAN - - 00-05-2C (hex) Supreme Magic Corporation - 00052C (base 16) Supreme Magic Corporation - Sun Towers Center Bldg., 13F - 2-11-22, Sangen-jaya, Setagaya-ku, Tokyo - 154-0024 - JAPAN - - 00-05-2D (hex) Zoltrix International Limited - 00052D (base 16) Zoltrix International Limited - Room 701 Po Hing Centre, - 18 Wan Chiu Road, Kowloon, - HONG KONG - - 00-05-2E (hex) Cinta Networks - 00052E (base 16) Cinta Networks - 3010 North First Street - San Jose CA 95134 - UNITED STATES - - 00-05-2F (hex) Leviton Network Solutions - 00052F (base 16) Leviton Network Solutions - 2222 222nd Street S.E. - Bothell WA 98021 - UNITED STATES - - 00-05-30 (hex) Andiamo Systems, Inc. - 000530 (base 16) Andiamo Systems, Inc. - 14171 Teerlink Way - Saratoga CA 95070 - UNITED STATES - - 00-05-31 (hex) CISCO SYSTEMS, INC. - 000531 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-32 (hex) CISCO SYSTEMS, INC. - 000532 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-33 (hex) Brocade Communications Systems, Inc. - 000533 (base 16) Brocade Communications Systems, Inc. - 1745 Technology Dr. - San Jose CA 95110 - UNITED STATES - - 00-05-34 (hex) Northstar Engineering Ltd. - 000534 (base 16) Northstar Engineering Ltd. - P.O. Box 40 - Henley-on-Thames Oxon RG9 6AE - UNITED KINGDOM - - 00-05-35 (hex) Chip PC Ltd. - 000535 (base 16) Chip PC Ltd. - 20 A.L. Motzkin St. - Topaz House, Nahum Hat 5 , P.O. Box 4 - Tirat Carmel 39100 - ISRAEL - - 00-05-36 (hex) Danam Communications, Inc. - 000536 (base 16) Danam Communications, Inc. - 900-3, Hokye-dong, Dongan-gu, - Anyang, Kyungki-do, 431-082, - KOREA, REPUBLIC OF - - 00-05-37 (hex) Nets Technology Co., Ltd. - 000537 (base 16) Nets Technology Co., Ltd. - #B1 YungJun Bldg. - 154-10 Sansung-Dong Kangnam-Gu - Seoul 135-090 135-090 - KOREA, REPUBLIC OF - - 00-05-38 (hex) Merilus, Inc. - 000538 (base 16) Merilus, Inc. - #307-46165 Yale Road - Chiliwack, BC - V2P 2P2 - CANADA - - 00-05-39 (hex) A Brand New World in Sweden AB - 000539 (base 16) A Brand New World in Sweden AB - Box 1223 - SE-164 28 KISTA - SWEDEN - - 00-05-3A (hex) Willowglen Services Pte Ltd - 00053A (base 16) Willowglen Services Pte Ltd - 151 Lorong Chuan, - New Tech Park #05-07, - 556741 - SINGAPORE - - 00-05-3B (hex) Harbour Networks Ltd., Co. Beijing - 00053B (base 16) Harbour Networks Ltd., Co. Beijing - 13/F, JiuLing Building, No. 21, - XiSanHuan North Rd., Beijing - 100089 - CHINA - - 00-05-3C (hex) Xircom - 00053C (base 16) Xircom - 2300 Corporate Center Dr. - Thousand Oaks CA 91320 - UNITED STATES - - 00-05-3D (hex) Agere Systems - 00053D (base 16) Agere Systems - 1371 McCarthy Blvd. - Milpitas CA 95035 - UNITED STATES - - 00-05-3E (hex) KID Systeme GmbH - 00053E (base 16) KID Systeme GmbH - Luneburger Schanze 30 - 21614 Buxtehude - GERMANY - - 00-05-3F (hex) VisionTek, Inc. - 00053F (base 16) VisionTek, Inc. - 1175 Lakeside Dr. - Gurnee IL 60031 - UNITED STATES - - 00-05-40 (hex) FAST Corporation - 000540 (base 16) FAST Corporation - 2791-5 Shimo-Tsuruma - Yamato Kanagawa - 242-0001 - JAPAN - - 00-05-41 (hex) Advanced Systems Co., Ltd. - 000541 (base 16) Advanced Systems Co., Ltd. - 2-9-7 Nishikicho, - Tachikawa-shi, Tokyo - 190-0022 - JAPAN - - 00-05-42 (hex) Otari, Inc. - 000542 (base 16) Otari, Inc. - 4-33-3 Kokuryo-cho, - Chofu-shi, Tokyo 182-0022, - JAPAN - - 00-05-43 (hex) IQ Wireless GmbH - 000543 (base 16) IQ Wireless GmbH - Carl-Scheele-Str. 14 - D-12489 Berlin - GERMANY - - 00-05-44 (hex) Valley Technologies, Inc. - 000544 (base 16) Valley Technologies, Inc. - 1006 West College Ave. - Suite 200 - State College PA 16801 - UNITED STATES - - 00-05-45 (hex) Internet Photonics - 000545 (base 16) Internet Photonics - 1030 Broad St., 2nd Floor - Shrewsbury NJ 07702 - UNITED STATES - - 00-05-46 (hex) KDDI Network & Solultions Inc. - 000546 (base 16) KDDI Network & Solultions Inc. - 2-3-1, Nishishinjunku-ku, - Tokyo 163-0907 - JAPAN - - 00-05-47 (hex) Starent Networks - 000547 (base 16) Starent Networks - 30 International Place - Tewksbury MA 01876 - UNITED STATES - - 00-05-48 (hex) Disco Corporation - 000548 (base 16) Disco Corporation - 13-11 Omori-Kita 2-chome - Ota-ku Tokyo 143-8580 - JAPAN - - 00-05-49 (hex) Salira Optical Network Systems - 000549 (base 16) Salira Optical Network Systems - 2694 Orchard Parkway - San Jose CA 95134 - UNITED STATES - - 00-05-4A (hex) Ario Data Networks, Inc. - 00054A (base 16) Ario Data Networks, Inc. - 2890 Zanker Road, Suite 203 - San Jose CA 95134 - UNITED STATES - - 00-05-4B (hex) Eaton Automation AG - 00054B (base 16) Eaton Automation AG - Spinnereistrasse 8 - St.Gallen 9008 - SWITZERLAND - - 00-05-4C (hex) RF Innovations Pty Ltd - 00054C (base 16) RF Innovations Pty Ltd - 22 Boulder Road - Malaga WA 6090 - AUSTRALIA - - 00-05-4D (hex) Brans Technologies, Inc. - 00054D (base 16) Brans Technologies, Inc. - 501 Boramae Academy Tower - 395-69 Shinaebang-Dong Tongjak-Gu Seoul - KOREA, REPUBLIC OF - - 00-05-4E (hex) Philips - 00054E (base 16) Philips - 1000 West Maude Avenue - Sunnyvale CA 94085-2810 - UNITED STATES - - 00-05-4F (hex) PRIVATE - 00054F (base 16) - - 00-05-50 (hex) Vcomms Connect Limited - 000550 (base 16) Vcomms Connect Limited - 75 The Esplanade, Level 3 - PO Box 38-920 - Wellington Mail Centre 5045 Wellington - NEW ZEALAND - - 00-05-51 (hex) F & S Elektronik Systeme GmbH - 000551 (base 16) F & S Elektronik Systeme GmbH - Untere Waldplaetze 23 - Stuttgart 70569 - GERMANY - - 00-05-52 (hex) Xycotec Computer GmbH - 000552 (base 16) Xycotec Computer GmbH - Karl-Heinz-Beckurts-Str. 4 - D-52428 Julich - GERMANY - - 00-05-53 (hex) DVC Company, Inc. - 000553 (base 16) DVC Company, Inc. - 10200 Hwy 290 W. - Austin TX 78236 - UNITED STATES - - 00-05-54 (hex) Rangestar Wireless - 000554 (base 16) Rangestar Wireless - 9565 Soquel Drive, Suite 100 - Aptos CA 95003 - UNITED STATES - - 00-05-55 (hex) Japan Cash Machine Co., Ltd. - 000555 (base 16) Japan Cash Machine Co., Ltd. - No. 3-15, 2-chome, Nishiwaki, - Hirano-ku, Osaka - 547-0035 - JAPAN - - 00-05-56 (hex) 360 Systems - 000556 (base 16) 360 Systems - 31355 Agoura Road - Westlake Village CA 91361 - UNITED STATES - - 00-05-57 (hex) Agile TV Corporation - 000557 (base 16) Agile TV Corporation - 333 Ravenswood Ave., - Building 202 - Menlo Park CA 94025 - UNITED STATES - - 00-05-58 (hex) Synchronous, Inc. - 000558 (base 16) Synchronous, Inc. - 77 Las Colinas Lane - San Jose CA 95119 - UNITED STATES - - 00-05-59 (hex) Intracom S.A. - 000559 (base 16) Intracom S.A. - 19 5 KM Markopoulou Ave. - 19002 Peania - Attika - GREECE - - 00-05-5A (hex) Power Dsine Ltd. - 00055A (base 16) Power Dsine Ltd. - 1 Hanagar St., P.O. Box 7220 - Neve Ne'eman Industrial Zone Hod Hasharo - ISRAEL - - 00-05-5B (hex) Charles Industries, Ltd. - 00055B (base 16) Charles Industries, Ltd. - 5600 Apollo Dr. - Rolling Meadows IL 60008 - UNITED STATES - - 00-05-5C (hex) Kowa Company, Ltd. - 00055C (base 16) Kowa Company, Ltd. - Chofugaoka 3-3-1, - Chofu-si, Tokyo, - 182-0021 - JAPAN - - 00-05-5D (hex) D-Link Systems, Inc. - 00055D (base 16) D-Link Systems, Inc. - 53 Discovery Dr. - Irvine CA 92618 - UNITED STATES - - 00-05-5E (hex) CISCO SYSTEMS, INC. - 00055E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-5F (hex) CISCO SYSTEMS, INC. - 00055F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-60 (hex) LEADER COMM.CO., LTD - 000560 (base 16) LEADER COMM.CO., LTD - 234, Komae-ri, Kiheung-eup, - Youngsin-si, Kyungki-do, - 449-900 - KOREA, REPUBLIC OF - - 00-05-61 (hex) nac Image Technology, Inc. - 000561 (base 16) nac Image Technology, Inc. - 8-7 Sanban-cho, Chiyoda-ku, - Tokyo, 102-0075 - JAPAN - - 00-05-62 (hex) Digital View Limited - 000562 (base 16) Digital View Limited - 2201 Nan Yang Plaza, - 57 Hungto Road, Kwun Tong, - Kowloon - HONG KONG - - 00-05-63 (hex) J-Works, Inc. - 000563 (base 16) J-Works, Inc. - 12328 Gladstone St. #1 - Sylmor CA 91342 - UNITED STATES - - 00-05-64 (hex) Tsinghua Bitway Co., Ltd. - 000564 (base 16) Tsinghua Bitway Co., Ltd. - 12 Floor, Tower C, Corporate - Square, No. 35, Financial Street, Xichen - CHINA - - 00-05-65 (hex) Tailyn Communication Company Ltd. - 000565 (base 16) Tailyn Communication Company Ltd. - No. 62, Lane 205, Nan-San Road, - Sec. 2, Lu-Chu Hsiang, - Taoyuan Hsien - TAIWAN, PROVINCE OF CHINA - - 00-05-66 (hex) Secui.com Corporation - 000566 (base 16) Secui.com Corporation - 17th Fl. Samsung Yeoksam Bldg. - 647-9, Yeoksam-dong, Kangnam-gu - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-05-67 (hex) Etymonic Design, Inc. - 000567 (base 16) Etymonic Design, Inc. - 41 Byron Avenue - Dorchester, Ontario, - NOL 1GO - CANADA - - 00-05-68 (hex) Piltofish Networks AB - 000568 (base 16) Piltofish Networks AB - Stora Badhusgatan 18-20 - S-41121 Goteborg - SWEDEN - - 00-05-69 (hex) VMware, Inc. - 000569 (base 16) VMware, Inc. - 3401 Hillview Avenue - Palo Alto CA 94304 - UNITED STATES - - 00-05-6A (hex) Heuft Systemtechnik GmbH - 00056A (base 16) Heuft Systemtechnik GmbH - Brohltalstr 31-33 - 56659 Burgbrohl - Deutschland - GERMANY - - 00-05-6B (hex) C.P. Technology Co., Ltd. - 00056B (base 16) C.P. Technology Co., Ltd. - 12F, No. 86, Hsin Tai Wu Rd., - Sec. 1, Hsi-Chih, Taipei Hsien, - 221 - TAIWAN, PROVINCE OF CHINA - - 00-05-6C (hex) Hung Chang Co., Ltd. - 00056C (base 16) Hung Chang Co., Ltd. - 1385-14, Juan-Dong, - Nam-ku, Inchom, 402-200 - KOREA, REPUBLIC OF - - 00-05-6D (hex) Pacific Corporation - 00056D (base 16) Pacific Corporation - 2-23-3 Ebisu-Minami Shibuya - Tokyo 150-0022 - JAPAN - - 00-05-6E (hex) National Enhance Technology, Inc. - 00056E (base 16) National Enhance Technology, Inc. - 2F, No. 196-3, Tatung Rd., Sec. 3, - Hsi Chih, Taipei Hsien, - TAIWAN, PROVINCE OF CHINA - - 00-05-6F (hex) Innomedia Technologies Pvt. Ltd. - 00056F (base 16) Innomedia Technologies Pvt. Ltd. - #3278, 12th Main Road - HAL 2nd Stage Bangalore - 560 008 - INDIA - - 00-05-70 (hex) Baydel Ltd. - 000570 (base 16) Baydel Ltd. - Baydel House - Brook Way Leatherhead, Surrey KT22 7NA - UNITED KINGDOM - - 00-05-71 (hex) Seiwa Electronics Co. - 000571 (base 16) Seiwa Electronics Co. - 757 Amabouki, Kukizaki-Machi - Inashiki-Gun, Ibaraki-Ken - 300-1253 - JAPAN - - 00-05-72 (hex) Deonet Co., Ltd. - 000572 (base 16) Deonet Co., Ltd. - #127-5 Jinyoung B/D 3th F, - NonIyun-Dong, KangNam-Gu, - Seoul - KOREA, REPUBLIC OF - - 00-05-73 (hex) CISCO SYSTEMS, INC. - 000573 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-74 (hex) CISCO SYSTEMS, INC. - 000574 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-75 (hex) CDS-Electronics BV - 000575 (base 16) CDS-Electronics BV - Mozart laan 330 - 3144 NH Maassluis - NETHERLANDS - - 00-05-76 (hex) NSM Technology Ltd. - 000576 (base 16) NSM Technology Ltd. - 22 Floor, Times Tower - 928 Cheung Sha Wan Road - Koloon - HONG KONG - - 00-05-77 (hex) SM Information & Communication - 000577 (base 16) SM Information & Communication - 330-1 Yangjaedong - Seoucho-Gu, Seoul - 137-130 - KOREA, REPUBLIC OF - - 00-05-78 (hex) PRIVATE - 000578 (base 16) - - 00-05-79 (hex) Universal Control Solution Corp. - 000579 (base 16) Universal Control Solution Corp. - 12843 Foothill Blvd. - Unit #C - Sylmar CA 91342 - UNITED STATES - - 00-05-7A (hex) Overture Networks - 00057A (base 16) Overture Networks - 637 Davis Drive - Morrisville NC 27560 - UNITED STATES - - 00-05-7B (hex) Chung Nam Electronic Co., Ltd. - 00057B (base 16) Chung Nam Electronic Co., Ltd. - Unit 3, 1/F, Festigood Centre - No. 8 Lok Yip Road, On Lok - Tsuen Fanling, - HONG KONG - - 00-05-7C (hex) RCO Security AB - 00057C (base 16) RCO Security AB - Box 705 - SE 176 27 Jarfalla - SWEDEN - - 00-05-7D (hex) Sun Communications, Inc. - 00057D (base 16) Sun Communications, Inc. - Gloria Bldg 6th - 1-3 Ageba-Cho Shinjuku-ku - Tokyo 162-082 - JAPAN - - 00-05-7E (hex) Eckelmann Steuerungstechnik GmbH - 00057E (base 16) Eckelmann Steuerungstechnik GmbH - Berliner Strasse 161 - 65205 Wiesbaden - GERMANY - - 00-05-7F (hex) Acqis Technology - 00057F (base 16) Acqis Technology - 1621 West El Camino Real - Mt. View CA 94040 - UNITED STATES - - 00-05-80 (hex) FibroLAN Ltd. - 000580 (base 16) FibroLAN Ltd. - 2 Hacarmel st., POB 544 - Yokneam Illit 20692 - ISRAEL - - 00-05-81 (hex) Snell - 000581 (base 16) Snell - Southleigh Park House - Eastleigh Road, Havant - Hampshire P09 2PE - UNITED KINGDOM - - 00-05-82 (hex) ClearCube Technology - 000582 (base 16) ClearCube Technology - 8834 Capital of Texas Hwy, - Suite 140 - Austin TX 78759 - UNITED STATES - - 00-05-83 (hex) ImageCom Limited - 000583 (base 16) ImageCom Limited - Cedars Park, Cedars Road, - Maidenhead, Berkshire, - SL6 1RZ - UNITED KINGDOM - - 00-05-84 (hex) AbsoluteValue Systems, Inc. - 000584 (base 16) AbsoluteValue Systems, Inc. - 715-D North Dr. - Melbourne FL 32934 - UNITED STATES - - 00-05-85 (hex) Juniper Networks, Inc. - 000585 (base 16) Juniper Networks, Inc. - 1194 N. Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-05-86 (hex) Lucent Technologies - 000586 (base 16) Lucent Technologies - 1701 Harbor Bay Parkway - Alameda CA 94502 - UNITED STATES - - 00-05-87 (hex) Locus, Incorporated - 000587 (base 16) Locus, Incorporated - 5540 Research Park Drive - Fitchburg Center - Madison WI 53711 - UNITED STATES - - 00-05-88 (hex) Sensoria Corp. - 000588 (base 16) Sensoria Corp. - 15950 Bernardo Ctr. Dr. - Suite J - San Diego CA 92127 - UNITED STATES - - 00-05-89 (hex) National Datacomputer - 000589 (base 16) National Datacomputer - 900 Middlesex Tpk. - Billerica MA 01821 - UNITED STATES - - 00-05-8A (hex) Netcom Co., Ltd. - 00058A (base 16) Netcom Co., Ltd. - 1F, No. 7, Lane 242, - Hu Liin Street - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-05-8B (hex) IPmental, Inc. - 00058B (base 16) IPmental, Inc. - 8F-9, No. 35, Hsin Tai Rd. - Juibei, Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-05-8C (hex) Opentech Inc. - 00058C (base 16) Opentech Inc. - 6F, DongWon Bldg., 275 - Youngjae-Dong, Seocho-Gu, - Seoul 137-130 - KOREA, REPUBLIC OF - - 00-05-8D (hex) Lynx Photonic Networks, Inc. - 00058D (base 16) Lynx Photonic Networks, Inc. - 13 Hamelaha St. - Rosh-Heayn - ISRAEL - - 00-05-8E (hex) Flextronics International GmbH & Co. Nfg. KG - 00058E (base 16) Flextronics International GmbH & Co. Nfg. KG - Schrackgasse 9-15 - Kindberg 8650 - AUSTRIA - - 00-05-8F (hex) CLCsoft co. - 00058F (base 16) CLCsoft co. - Dept. of Electrical Engineering - KAIST, 373-1 Kuseong-dong, Yuseong-gu, D - KOREA, REPUBLIC OF - - 00-05-90 (hex) Swissvoice Ltd. - 000590 (base 16) Swissvoice Ltd. - Ziegelmattstrasse 1 - 4503 Solothurn - SWITZERLAND - - 00-05-91 (hex) Active Silicon Ltd - 000591 (base 16) Active Silicon Ltd - Pinewood Mews - Bond Close - Iver SL0 0NA - UNITED KINGDOM - - 00-05-92 (hex) Pultek Corp. - 000592 (base 16) Pultek Corp. - 74-1, Yamashita-cho, - Naka-ku, Tokohama-city, - 231-0023 - JAPAN - - 00-05-93 (hex) Grammar Engine Inc. - 000593 (base 16) Grammar Engine Inc. - 921 Eastwind Drive - Suite 122 - Westerville OH 43081 - UNITED STATES - - 00-05-94 (hex) IXXAT Automation GmbH - 000594 (base 16) IXXAT Automation GmbH - Leibnizstraße 15 - 88250 Weingarten - GERMANY - - 00-05-95 (hex) Alesis Corporation - 000595 (base 16) Alesis Corporation - 1633 26th Street - Santa Monica CA 90404 - UNITED STATES - - 00-05-96 (hex) Genotech Co., Ltd. - 000596 (base 16) Genotech Co., Ltd. - #308 Gunkook Bldg., - 288-1 Doksan-Dong - Gumchon-Gu Seoul - KOREA, REPUBLIC OF - - 00-05-97 (hex) Eagle Traffic Control Systems - 000597 (base 16) Eagle Traffic Control Systems - 8004 Cameron Road - Austin TX 78754 - UNITED STATES - - 00-05-98 (hex) CRONOS S.r.l. - 000598 (base 16) CRONOS S.r.l. - Via cavour 58/A - 23900 LECCO (LC) - ITALY - - 00-05-99 (hex) DRS Test and Energy Management or DRS-TEM - 000599 (base 16) DRS Test and Energy Management or DRS-TEM - 110 Wynn Drive - Huntsville AL 35805 - UNITED STATES - - 00-05-9A (hex) CISCO SYSTEMS, INC. - 00059A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-9B (hex) CISCO SYSTEMS, INC. - 00059B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-9C (hex) Kleinknecht GmbH, Ing. Büro - 00059C (base 16) Kleinknecht GmbH, Ing. Büro - Bachstraße 30 - D-82541 Münsing - GERMANY - - 00-05-9D (hex) Daniel Computing Systems, Inc. - 00059D (base 16) Daniel Computing Systems, Inc. - 3208 8th Avenue NE #118 - Calgary Alberta - T2A 7V8 - CANADA - - 00-05-9E (hex) Zinwell Corporation - 00059E (base 16) Zinwell Corporation - 7F, No.512, Yuan-Shan Road - Chang-ho city Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-05-9F (hex) Yotta Networks, Inc. - 00059F (base 16) Yotta Networks, Inc. - 2201 Avenue K - Plano TX 75074 - UNITED STATES - - 00-05-A0 (hex) MOBILINE Kft. - 0005A0 (base 16) MOBILINE Kft. - Lehel Utca 14 - BUDAPEST - H-1134 - HUNGARY - - 00-05-A1 (hex) Zenocom - 0005A1 (base 16) Zenocom - No.402, 4th floor, Wongok Bldg. - 830-38, Yoksam-Dong, Gangnam-Gu - Seoul - KOREA, REPUBLIC OF - - 00-05-A2 (hex) CELOX Networks - 0005A2 (base 16) CELOX Networks - 940 West Port Plaza - Ste. #300 - St. Louis MO 63146 - UNITED STATES - - 00-05-A3 (hex) QEI, Inc. - 0005A3 (base 16) QEI, Inc. - 60 Fadem Road - Springfield NJ 07081 - UNITED STATES - - 00-05-A4 (hex) Lucid Voice Ltd. - 0005A4 (base 16) Lucid Voice Ltd. - 5 Jabotinski Street - Ramat-Gan, 52520 - ISRAEL - - 00-05-A5 (hex) KOTT - 0005A5 (base 16) KOTT - Suite 305 Daeha B/D - 680 Yeoksam-Dong, KangNam-Gu Seoul - 135-080 - KOREA, REPUBLIC OF - - 00-05-A6 (hex) Extron Electronics - 0005A6 (base 16) Extron Electronics - 1230 S. Lewis - Anahiem CA 92805 - UNITED STATES - - 00-05-A7 (hex) Hyperchip, Inc. - 0005A7 (base 16) Hyperchip, Inc. - 180 Peel Street - Ste. #333 - Montreal, Quebec - H3C 2G7 - CANADA - - 00-05-A8 (hex) WYLE ELECTRONICS - 0005A8 (base 16) WYLE ELECTRONICS - 3000 BOWERS AVENUE - SANTA CLARA CA 95051-0919 - UNITED STATES - - 00-05-A9 (hex) Princeton Networks, Inc. - 0005A9 (base 16) Princeton Networks, Inc. - 100 Century Center Ct. #100 - San Jose CA 95112 - UNITED STATES - - 00-05-AA (hex) Moore Industries International Inc. - 0005AA (base 16) Moore Industries International Inc. - 16650 Schoenborn St. - North Hills CA 91343 - UNITED STATES - - 00-05-AB (hex) Cyber Fone, Inc. - 0005AB (base 16) Cyber Fone, Inc. - 989 Old Eagle School Road - Suite 800 - Wayne PA 19087 - UNITED STATES - - 00-05-AC (hex) Northern Digital, Inc. - 0005AC (base 16) Northern Digital, Inc. - 103 Randall Drive - Waterloo Ontario N2V 1C5 - CANADA - - 00-05-AD (hex) Topspin Communications, Inc. - 0005AD (base 16) Topspin Communications, Inc. - 515 Ellis Street - Mountain View CA 94043 - UNITED STATES - - 00-05-AE (hex) Mediaport USA - 0005AE (base 16) Mediaport USA - 17151 Newhope Ave. #202 - Fountain Valley CA 92708 - UNITED STATES - - 00-05-AF (hex) InnoScan Computing A/S - 0005AF (base 16) InnoScan Computing A/S - Soren Frichsvej 42R - DK-8230 Aabyhoj - DENMARK - - 00-05-B0 (hex) Korea Computer Technology Co., Ltd. - 0005B0 (base 16) Korea Computer Technology Co., Ltd. - KCT Bldg, 111-3 Yangjae-Dong, - Seocho-Gu, Seoul - KOREA, REPUBLIC OF - - 00-05-B1 (hex) ASB Technology BV - 0005B1 (base 16) ASB Technology BV - De Ronde 15A - 5683 CZ Best - NETHERLANDS - - 00-05-B2 (hex) Medison Co., Ltd. - 0005B2 (base 16) Medison Co., Ltd. - 997-4, Saechi-Dong, - Kangnam-ku, Souel, - 135-280 - KOREA, REPUBLIC OF - - 00-05-B3 (hex) Asahi-Engineering Co., Ltd. - 0005B3 (base 16) Asahi-Engineering Co., Ltd. - 3-6-12-2 Gakuenhigashi-cho - Kodaira-shi - Tokyo 187-0043 - JAPAN - - 00-05-B4 (hex) Aceex Corporation - 0005B4 (base 16) Aceex Corporation - 2F, No. 2, Alley 1, Sze-Wei Lane - Chung-Cheng Rd., Hsintien, Taipei - 23138 - TAIWAN, PROVINCE OF CHINA - - 00-05-B5 (hex) Broadcom Technologies - 0005B5 (base 16) Broadcom Technologies - 137-060 - 858-31 Yujeong BLD, Bangbae-Dong - Secho-Gu Seoul, - KOREA, REPUBLIC OF - - 00-05-B6 (hex) INSYS Microelectronics GmbH - 0005B6 (base 16) INSYS Microelectronics GmbH - Hermann-Köhl-Straße 22 - 93049 Regensburg - GERMANY - - 00-05-B7 (hex) Arbor Technology Corp. - 0005B7 (base 16) Arbor Technology Corp. - 5F, No. 738, Zhong Zheng Rd., - Zhong Ho 235, Taipei, - TAIWAN, PROVINCE OF CHINA - - 00-05-B8 (hex) Electronic Design Associates, Inc. - 0005B8 (base 16) Electronic Design Associates, Inc. - 331 Arcado Rd. NW - Suite C-1 - Lilburn GA 30047-2841 - UNITED STATES - - 00-05-B9 (hex) Airvana, Inc. - 0005B9 (base 16) Airvana, Inc. - 25 Industrial Ave. - Chlemsford MA 01824 - UNITED STATES - - 00-05-BA (hex) Area Netwoeks, Inc. - 0005BA (base 16) Area Netwoeks, Inc. - 1148 Euclid Ave., Suite 400 - Cleveland OH 4415 - UNITED STATES - - 00-05-BB (hex) Myspace AB - 0005BB (base 16) Myspace AB - Sveavagen 33 - SE-11134 Stockholm - SWEDEN - - 00-05-BC (hex) Resource Data Management Ltd - 0005BC (base 16) Resource Data Management Ltd - 80 Johnstone Avenue, - Hilington, Glasgow, - Scotland G52 4NZ - UNITED KINGDOM - - 00-05-BD (hex) ROAX BV - 0005BD (base 16) ROAX BV - Sterrenbergweg 29 - NL-3769 BS SOESTERBERG - NETHERLANDS - - 00-05-BE (hex) Kongsberg Seatex AS - 0005BE (base 16) Kongsberg Seatex AS - Pirsenteret - N-7562 Trondheim - NORWAY - - 00-05-BF (hex) JustEzy Technology, Inc. - 0005BF (base 16) JustEzy Technology, Inc. - 5F, No. 324, Sec. 1, Junghua Rd. - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-05-C0 (hex) Digital Network Alacarte Co., Ltd. - 0005C0 (base 16) Digital Network Alacarte Co., Ltd. - A104, Seoul Business Incubator - 647-26, DeungChun-Dong, Kangseo-Gu - Seoul 157-030, - KOREA, REPUBLIC OF - - 00-05-C1 (hex) A-Kyung Motion, Inc. - 0005C1 (base 16) A-Kyung Motion, Inc. - 54-10, Munjung-Dong - Songpa-Ku, - Seoul - KOREA, REPUBLIC OF - - 00-05-C2 (hex) Soronti, Inc. - 0005C2 (base 16) Soronti, Inc. - 12257 South Business Park Drive - #160 - Draper Utah 84020 - UNITED STATES - - 00-05-C3 (hex) Pacific Instruments, Inc. - 0005C3 (base 16) Pacific Instruments, Inc. - 4080 Pike Lane - Concord CA 94520 - UNITED STATES - - 00-05-C4 (hex) Telect, Inc. - 0005C4 (base 16) Telect, Inc. - 2111 N. Molter Road - Liberty Lake WA 99019 - UNITED STATES - - 00-05-C5 (hex) Flaga HF - 0005C5 (base 16) Flaga HF - Vesturhlid 7 - IS-105 Reykjavik - ICELAND - - 00-05-C6 (hex) Triz Communications - 0005C6 (base 16) Triz Communications - Anwon Bldg. 7th Fl. - 14-15 Yoido-Dong Youngdeungpo-Gu - Seoul 150-010 - KOREA, REPUBLIC OF - - 00-05-C7 (hex) I/F-COM A/S - 0005C7 (base 16) I/F-COM A/S - Ellegaardvej 36 - 6400 Soenderborg - DENMARK - - 00-05-C8 (hex) VERYTECH - 0005C8 (base 16) VERYTECH - #402, Jang Young Shil Kwan, - Venture Town, 1688-5 Shinil-Dong, Daedeo - KOREA, REPUBLIC OF - - 00-05-C9 (hex) LG Innotek Co., Ltd. - 0005C9 (base 16) LG Innotek Co., Ltd. - LG Component R&D Center - 1271, Sa-Dong, Sangrok-gu - Ansan-si Gyeonggi-do 426-791 - KOREA, REPUBLIC OF - - 00-05-CA (hex) Hitron Technology, Inc. - 0005CA (base 16) Hitron Technology, Inc. - HSINCHU SBIP SUBSIDIARY - No. 25 R&D 1st Rd. Science-Based Industr - Hsin-chu - TAIWAN, PROVINCE OF CHINA - - 00-05-CB (hex) ROIS Technologies, Inc. - 0005CB (base 16) ROIS Technologies, Inc. - 6th F Changhyun B/D, 960-1 - Hogye-Dong Dongan-Ku Anyang, - 431-080 - KOREA, REPUBLIC OF - - 00-05-CC (hex) Sumtel Communications, Inc. - 0005CC (base 16) Sumtel Communications, Inc. - 1F, No. 173, Gung Yuan Road, - Hsinchu City 30054 - TAIWAN, PROVINCE OF CHINA - - 00-05-CD (hex) Denon, Ltd. - 0005CD (base 16) Denon, Ltd. - 35-1, Sagamiono 7-chome, - Sagamihara-shi - Kanagawa 228-8505 - JAPAN - - 00-05-CE (hex) Prolink Microsystems Corporation - 0005CE (base 16) Prolink Microsystems Corporation - 6F, No. 349, Yang-Kuang St. - Nei-Hu Taipei, - TAIWAN, PROVINCE OF CHINA - - 00-05-CF (hex) Thunder River Technologies, Inc. - 0005CF (base 16) Thunder River Technologies, Inc. - 23 Corporate Plaza, Suite 250 - Newport Beach CA 92660 - UNITED STATES - - 00-05-D0 (hex) Solinet Systems - 0005D0 (base 16) Solinet Systems - 1200-180 Elgin St. - Ottawa Ontario - K2P 2K3 - CANADA - - 00-05-D1 (hex) Metavector Technologies - 0005D1 (base 16) Metavector Technologies - Steenweg Op Gierle, 100 - B-2300 Turnhout, - BELGIUM - - 00-05-D2 (hex) DAP Technologies - 0005D2 (base 16) DAP Technologies - 955 Fernand Dufour, - Ville De Vanier, Quebec, - G1M 3B2 - CANADA - - 00-05-D3 (hex) eProduction Solutions, Inc. - 0005D3 (base 16) eProduction Solutions, Inc. - 22001 North Park Drive - Kingwood TX 77339-3804 - UNITED STATES - - 00-05-D4 (hex) FutureSmart Networks, Inc. - 0005D4 (base 16) FutureSmart Networks, Inc. - 6155 Almaden Expressway - Suite 100 - San Jose CA 95120 - UNITED STATES - - 00-05-D5 (hex) Speedcom Wireless - 0005D5 (base 16) Speedcom Wireless - 7020 Professional Pkwy East - Sarasota FL 34240-8514 - UNITED STATES - - 00-05-D6 (hex) L-3 Linkabit - 0005D6 (base 16) L-3 Linkabit - 9890 Town Center Drive - San Diego CA 92121 - UNITED STATES - - 00-05-D7 (hex) Vista Imaging, Inc. - 0005D7 (base 16) Vista Imaging, Inc. - 521 Taylor Way - San Carlos CA 94070 - UNITED STATES - - 00-05-D8 (hex) Arescom, Inc. - 0005D8 (base 16) Arescom, Inc. - 3541 Gateway Blvd. - Fremont CA 94538 - UNITED STATES - - 00-05-D9 (hex) Techno Valley, Inc. - 0005D9 (base 16) Techno Valley, Inc. - ASIC Venture Town 5F, - 1330-3 Seocho2-Dong, Seocho-Ku, - Seoul 135-072 - KOREA, REPUBLIC OF - - 00-05-DA (hex) Apex Automationstechnik - 0005DA (base 16) Apex Automationstechnik - Vossenkamp 4 - D-38104 Braunschweig - GERMANY - - 00-05-DB (hex) PSI Nentec GmbH - 0005DB (base 16) PSI Nentec GmbH - Greschbachstraße 12 - Karlsruhe 76229 - GERMANY - - 00-05-DC (hex) CISCO SYSTEMS, INC. - 0005DC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-DD (hex) CISCO SYSTEMS, INC. - 0005DD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-05-DE (hex) Gi Fone Korea, Inc. - 0005DE (base 16) Gi Fone Korea, Inc. - Twin Bldg. 4th Fl, - 902-124 Togok-dong, Kangnam-gu, - Seoul, - KOREA, REPUBLIC OF - - 00-05-DF (hex) Electronic Innovation, Inc. - 0005DF (base 16) Electronic Innovation, Inc. - 12731 Cannington Way SW - Calgary, AB T2W 1Z7 - CANADA - - 00-05-E0 (hex) Empirix Corp. - 0005E0 (base 16) Empirix Corp. - 205 Lowell St. - Wilmington MA 01887 - UNITED STATES - - 00-05-E1 (hex) Trellis Photonics, Ltd. - 0005E1 (base 16) Trellis Photonics, Ltd. - P.O.B. 36 - Yogneam Elite, 20692 - ISRAEL - - 00-05-E2 (hex) Creativ Network Technologies - 0005E2 (base 16) Creativ Network Technologies - 1755 St. Regis Suite 240 - Dollard-des-Ormeaux - Quebec H9B-2M9 - CANADA - - 00-05-E3 (hex) LightSand Communications, Inc. - 0005E3 (base 16) LightSand Communications, Inc. - 375 Los Coches St. - Milpitas CA 94539 - UNITED STATES - - 00-05-E4 (hex) Red Lion Controls Inc. - 0005E4 (base 16) Red Lion Controls Inc. - 20 Willow Springs Circle - York PA 17402 - UNITED STATES - - 00-05-E5 (hex) Renishaw PLC - 0005E5 (base 16) Renishaw PLC - New Mills, Wotton-under-Edge - Gloucestershure, GL12 8JR - UNITED KINGDOM - - 00-05-E6 (hex) Egenera, Inc. - 0005E6 (base 16) Egenera, Inc. - 165 Forest St. - Marlboro MA 01752 - UNITED STATES - - 00-05-E7 (hex) Netrake an AudioCodes Company - 0005E7 (base 16) Netrake an AudioCodes Company - 3000 Technology Drive - Suite 100 - Plano TX 75074 - UNITED STATES - - 00-05-E8 (hex) TurboWave, Inc. - 0005E8 (base 16) TurboWave, Inc. - 555 South State - Suite 302 - Orem UT 84058 - UNITED STATES - - 00-05-E9 (hex) Unicess Network, Inc. - 0005E9 (base 16) Unicess Network, Inc. - 870 Dorothy Dr. #708 - Richardson TX 75081 - UNITED STATES - - 00-05-EA (hex) Rednix - 0005EA (base 16) Rednix - 502, Dong-A Resort Officetel - 538-8 Bongmyung-Dong Yusung, - Taejon 305-709 - KOREA, REPUBLIC OF - - 00-05-EB (hex) Blue Ridge Networks, Inc. - 0005EB (base 16) Blue Ridge Networks, Inc. - 14120 Parke Long Court - Suite 201 - Chantilly VA 20151 - UNITED STATES - - 00-05-EC (hex) Mosaic Systems Inc. - 0005EC (base 16) Mosaic Systems Inc. - 7 Campbell Park - Somerville MA 02144 - UNITED STATES - - 00-05-ED (hex) Technikum Joanneum GmbH - 0005ED (base 16) Technikum Joanneum GmbH - Alte Poststrasse 149 - 8020 Graz - AUSTRIA - - 00-05-EE (hex) Siemens AB, Infrastructure & Cities, Building Technologies Division, IC BT SSP SP BA PR - 0005EE (base 16) Siemens AB, Infrastructure & Cities, Building Technologies Division, IC BT SSP SP BA PR - Englundavaegen 7 - Solna SE-171 41 - SWEDEN - - 00-05-EF (hex) ADOIR Digital Technology - 0005EF (base 16) ADOIR Digital Technology - 28 Fl, ZhaoFeng World Trade Bldg. - 369 JiangSu Rd. - Shanghai 200050, - CHINA - - 00-05-F0 (hex) SATEC - 0005F0 (base 16) SATEC - P.O. Box 45022 - Jerusalem - 91450 - ISRAEL - - 00-05-F1 (hex) Vrcom, Inc. - 0005F1 (base 16) Vrcom, Inc. - 401, Songam Bldg, 479-1, - Bangbae 3-dong, Seocho-ku, - Seoul - KOREA, REPUBLIC OF - - 00-05-F2 (hex) Power R, Inc. - 0005F2 (base 16) Power R, Inc. - 756 Aloha St. - Seattle WA 98109 - UNITED STATES - - 00-05-F3 (hex) Webyn - 0005F3 (base 16) Webyn - 26 Rue Oes Gaudines - 78100 Saint-Germain - FRANCE - - 00-05-F4 (hex) System Base Co., Ltd. - 0005F4 (base 16) System Base Co., Ltd. - 475-22, BangBae 2 dong, - Seocho gu, Seoul, - KOREA, REPUBLIC OF - - 00-05-F5 (hex) Geospace Technologies - 0005F5 (base 16) Geospace Technologies - 7007 Pinemont - Houston TX 77040 - UNITED STATES - - 00-05-F6 (hex) Young Chang Co. Ltd. - 0005F6 (base 16) Young Chang Co. Ltd. - 1432 Main Street - Waltham MA 02451 - UNITED STATES - - 00-05-F7 (hex) Analog Devices, Inc. - 0005F7 (base 16) Analog Devices, Inc. - 804 Woburn St., MS 111 - Wilmington MA 01887 - UNITED STATES - - 00-05-F8 (hex) Real Time Access, Inc. - 0005F8 (base 16) Real Time Access, Inc. - 455 N. Canyons Pkwy. - Suite B - Livermore CA 94550 - UNITED STATES - - 00-05-F9 (hex) TOA Corporation - 0005F9 (base 16) TOA Corporation - 2-1 Takamatsu-cho, - Takarazuka-city - Hyogo 665-0043 - JAPAN - - 00-05-FA (hex) IPOptical, Inc. - 0005FA (base 16) IPOptical, Inc. - 45940 Horseshoe Drive - Suite 150 - Dulles VA 20166 - UNITED STATES - - 00-05-FB (hex) ShareGate, Inc. - 0005FB (base 16) ShareGate, Inc. - 9805 Double R Blvd. - Third Floor - Reno NV 89511-5917 - UNITED STATES - - 00-05-FC (hex) Schenck Pegasus Corp. - 0005FC (base 16) Schenck Pegasus Corp. - 2890 John R Road - Troy MI 48083 - UNITED STATES - - 00-05-FD (hex) PacketLight Networks Ltd. - 0005FD (base 16) PacketLight Networks Ltd. - 27 Habarzel St. - Ramat Hahayal - Tel-Aviv 69710 - ISRAEL - - 00-05-FE (hex) Traficon N.V. - 0005FE (base 16) Traficon N.V. - Bissegemsestraat 45 - B-8501 Heule - BELGIUM - - 00-05-FF (hex) SNS Solutions, Inc. - 0005FF (base 16) SNS Solutions, Inc. - 2nd Fl. Hill House, - 99-2 Sohyun, Bundang, Sungnam, Kyunggi, - KOREA, REPUBLIC OF - - 00-06-00 (hex) Toshiba Teli Corporation - 000600 (base 16) Toshiba Teli Corporation - 4-7-1 Asahigaoka, Hino-Shi, - Tokyo 191-0065 - JAPAN - - 00-06-01 (hex) Otanikeiki Co., Ltd. - 000601 (base 16) Otanikeiki Co., Ltd. - 2-10-23 Hikari-Machi - Higashi-Ku Hiroshima - 732-0052 - JAPAN - - 00-06-02 (hex) Cirkitech Electronics Co. - 000602 (base 16) Cirkitech Electronics Co. - B1-2, No. 361, Fu-Xing First Road - Guei-Shan Hsiang, - Tao-Yuan - TAIWAN, PROVINCE OF CHINA - - 00-06-03 (hex) Baker Hughes Inc. - 000603 (base 16) Baker Hughes Inc. - 2001 Rankin Rd. - Houston TX 77073 - UNITED STATES - - 00-06-04 (hex) @Track Communications, Inc. - 000604 (base 16) @Track Communications, Inc. - 1155 Kas Dr. - Richardson TX 75081 - UNITED STATES - - 00-06-05 (hex) Inncom International, Inc. - 000605 (base 16) Inncom International, Inc. - P.O. Box 1060 - 83 Halls Road - Old Lyme CT 06371 - UNITED STATES - - 00-06-06 (hex) RapidWAN, Inc. - 000606 (base 16) RapidWAN, Inc. - 2085 Hamilton Ave. - Suite #220 - San Jose CA 95125 - UNITED STATES - - 00-06-07 (hex) Omni Directional Control Technology Inc. - 000607 (base 16) Omni Directional Control Technology Inc. - 8F-2, No. 94, Pao-Chung Rd. - Hsin-Tien City, - Taipei Hsien, - TAIWAN, PROVINCE OF CHINA - - 00-06-08 (hex) At-Sky SAS - 000608 (base 16) At-Sky SAS - ZI Athelia 3, Voi Atlas - 13600- La Ciotat - FRANCE - - 00-06-09 (hex) Crossport Systems - 000609 (base 16) Crossport Systems - 10940 NE 33rd Pl. - Suite 101 - Bellevue WA 98005 - UNITED STATES - - 00-06-0A (hex) Blue2space - 00060A (base 16) Blue2space - Arstaangsv. 9 - SE-11748 Stockholm - SWEDEN - - 00-06-0B (hex) Artesyn Embedded Technologies - 00060B (base 16) Artesyn Embedded Technologies - 2900 S. Diablo Way Suite 190 - Tempe AZ 85282 - UNITED STATES - - 00-06-0C (hex) Melco Industries, Inc. - 00060C (base 16) Melco Industries, Inc. - 1575 W. 124th Ave. - Denver CO 80234 - UNITED STATES - - 00-06-0D (hex) Wave7 Optics - 00060D (base 16) Wave7 Optics - 1075 Windward Ridge Pkwy. - Suite 170 - Alpharetta GA 30005 - UNITED STATES - - 00-06-0E (hex) IGYS Systems, Inc. - 00060E (base 16) IGYS Systems, Inc. - 7373 Lincoln Way - Garden Grove CA 92841 - UNITED STATES - - 00-06-0F (hex) Narad Networks Inc - 00060F (base 16) Narad Networks Inc - 515 Groton Road - Westford MA 01886 - UNITED STATES - - 00-06-10 (hex) Abeona Networks Inc - 000610 (base 16) Abeona Networks Inc - 46117 Landing Parkway - Fremont CA 94539 - UNITED STATES - - 00-06-11 (hex) Zeus Wireless, Inc. - 000611 (base 16) Zeus Wireless, Inc. - 8325 Guilford Road - Columbia MD 21046 - UNITED STATES - - 00-06-12 (hex) Accusys, Inc. - 000612 (base 16) Accusys, Inc. - 5F, No. 38, Taiyuan St - Jhubei City - Hsinchu County 30265 - TAIWAN, PROVINCE OF CHINA - - 00-06-13 (hex) Kawasaki Microelectronics Incorporated - 000613 (base 16) Kawasaki Microelectronics Incorporated - MTG B-5, 1-3, Nakase, - Mihama-ku Chiba 261-8501 - JAPAN - - 00-06-14 (hex) Prism Holdings - 000614 (base 16) Prism Holdings - P.O. Box 901, - Witkoppen, 2068, - Gauteng - SOUTH AFRICA - - 00-06-15 (hex) Kimoto Electric Co., Ltd. - 000615 (base 16) Kimoto Electric Co., Ltd. - 3-1 Funahashi-Cho, - Tennoji-Ku, Osaka - 543-0024 - JAPAN - - 00-06-16 (hex) Tel Net Co., Ltd. - 000616 (base 16) Tel Net Co., Ltd. - 3F BOF Bldg 730-15 Goje Song - Yeonje Gu Pusam 611-073, - KOREA, REPUBLIC OF - - 00-06-17 (hex) Redswitch Inc. - 000617 (base 16) Redswitch Inc. - 1815 McCandless Drive - Milpitas CA 95035-8046 - UNITED STATES - - 00-06-18 (hex) DigiPower Manufacturing Inc. - 000618 (base 16) DigiPower Manufacturing Inc. - No. 114, Floor 13, Sec. 1, - Hsin Tai Wu Road, Shijr City, - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-06-19 (hex) Connection Technology Systems - 000619 (base 16) Connection Technology Systems - 18F-6, No. 79, Sec. 1, - Hsin Tai Wu Rd. - Hsinchih Taipei, - TAIWAN, PROVINCE OF CHINA - - 00-06-1A (hex) Zetari Inc. - 00061A (base 16) Zetari Inc. - 411 Waverly Oaks Rd. - Suite 323 - Waltham MA 02452-8401 - UNITED STATES - - 00-06-1B (hex) Notebook Development Lab. Lenovo Japan Ltd. - 00061B (base 16) Notebook Development Lab. Lenovo Japan Ltd. - 1623-14 Shimotsuruma - Yamato-shi Kanagawa-ken - 242-8502 - JAPAN - - 00-06-1C (hex) Hoshino Metal Industries, Ltd. - 00061C (base 16) Hoshino Metal Industries, Ltd. - 645 Yamanokami, Yabutsuka, - Nitta-gun, Gunma - 379-2302 - JAPAN - - 00-06-1D (hex) MIP Telecom, Inc. - 00061D (base 16) MIP Telecom, Inc. - 3rd Floor, Sangil BLDG, - 948-16, Bongcheondong, Gwanakku, - Seoul 151-069 - KOREA, REPUBLIC OF - - 00-06-1E (hex) Maxan Systems - 00061E (base 16) Maxan Systems - 1-84, Woulam-dong - Salseo-gu, DAEGU, - KOREA, REPUBLIC OF - - 00-06-1F (hex) Vision Components GmbH - 00061F (base 16) Vision Components GmbH - Ottostraße 2 - Ettlingen, 76275 - GERMANY - - 00-06-20 (hex) Serial System Ltd. - 000620 (base 16) Serial System Ltd. - 76 Playfair Road - #04-03 LHK2 Building - 367996 - SINGAPORE - - 00-06-21 (hex) Hinox, Co., Ltd. - 000621 (base 16) Hinox, Co., Ltd. - 15-7 3-chome, Sennin-cho, - Hachioji-City, Tokyo, - 193-0835 - JAPAN - - 00-06-22 (hex) Chung Fu Chen Yeh Enterprise Corp. - 000622 (base 16) Chung Fu Chen Yeh Enterprise Corp. - 2F No. 666 Jing Ping Road, - Chung Ho City, - Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-06-23 (hex) MGE UPS Systems France - 000623 (base 16) MGE UPS Systems France - 140 Avenue Jean Kuntzmann - Zirst Montbonnot St Martin 38334 St Ismi - FRANCE - - 00-06-24 (hex) Gentner Communications Corp. - 000624 (base 16) Gentner Communications Corp. - 1825 Research Way - Salt Lake City UT 84119 - UNITED STATES - - 00-06-25 (hex) The Linksys Group, Inc. - 000625 (base 16) The Linksys Group, Inc. - 17401 Armstrong Ave. - Irvine CA 92614 - UNITED STATES - - 00-06-26 (hex) MWE GmbH - 000626 (base 16) MWE GmbH - Olbrichtstraße 21 - D-69469 Weinheim - GERMANY - - 00-06-27 (hex) Uniwide Technologies, Inc. - 000627 (base 16) Uniwide Technologies, Inc. - Korea Development Bank B/D 5th Flr - Dunsandong, Seogu, - Taejon 302-122, - KOREA, REPUBLIC OF - - 00-06-28 (hex) CISCO SYSTEMS, INC. - 000628 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-29 (hex) IBM Corp - 000629 (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-06-2A (hex) CISCO SYSTEMS, INC. - 00062A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-2B (hex) INTRASERVER TECHNOLOGY - 00062B (base 16) INTRASERVER TECHNOLOGY - SEVEN OCTOBER HILL RD. - HOLLISTON MA 01746 - UNITED STATES - - 00-06-2C (hex) Bivio Networks - 00062C (base 16) Bivio Networks - 4457 Willow Road, - Pleasanton CA 94588 - UNITED STATES - - 00-06-2D (hex) TouchStar Technologies, L.L.C. - 00062D (base 16) TouchStar Technologies, L.L.C. - 5147 South Garnett Road - Suite A - Tulsa OK 74146 - UNITED STATES - - 00-06-2E (hex) Aristos Logic Corp. - 00062E (base 16) Aristos Logic Corp. - 27051 Towne Centre Dr. - Suite 290 - Foothill Ranch CA 92610 - UNITED STATES - - 00-06-2F (hex) Pivotech Systems Inc. - 00062F (base 16) Pivotech Systems Inc. - 200 Centennial Ave., - Suite 222 - Piscataway NJ 08854 - UNITED STATES - - 00-06-30 (hex) Adtranz Sweden - 000630 (base 16) Adtranz Sweden - Dept. TCC/TH - Ostraringvagen 2 72173 Vasteras - SWEDEN - - 00-06-31 (hex) Calix - 000631 (base 16) Calix - 16305 36th Ave N - Suite 300 - Plymouth MN 55446 - UNITED STATES - - 00-06-32 (hex) Mesco Engineering GmbH - 000632 (base 16) Mesco Engineering GmbH - Wiesentalstraße74 - 79539 Lorrach - GERMANY - - 00-06-33 (hex) Cross Match Technologies GmbH - 000633 (base 16) Cross Match Technologies GmbH - Unstrutweg 4 - Jena 07743 - GERMANY - - 00-06-34 (hex) GTE Airfone Inc. - 000634 (base 16) GTE Airfone Inc. - 2809 Butterfield - Oakbrook IL 60522 - UNITED STATES - - 00-06-35 (hex) PacketAir Networks, Inc. - 000635 (base 16) PacketAir Networks, Inc. - 11545 W. Bernardo Ct. - Suite 100 - San Diego CA 92127 - UNITED STATES - - 00-06-36 (hex) Jedai Broadband Networks - 000636 (base 16) Jedai Broadband Networks - 331 Newman Springs Rd. - Building 1, 2nd Floor - Red Bank NJ 07701 - UNITED STATES - - 00-06-37 (hex) Toptrend-Meta Information (ShenZhen) Inc. - 000637 (base 16) Toptrend-Meta Information (ShenZhen) Inc. - 2/F, Bldg. 3, Section A, Nor-East Zone - Eastern Industrial Area, Overseas City, - CHINA - - 00-06-38 (hex) Sungjin C&C Co., Ltd. - 000638 (base 16) Sungjin C&C Co., Ltd. - 1543-6, Seocho-dong, Seocho-gu, - Seoul 137-073 - KOREA, REPUBLIC OF - - 00-06-39 (hex) Newtec - 000639 (base 16) Newtec - Laarstraat 5 - B-9100 Sint-Niklaas - BELGIUM - - 00-06-3A (hex) Dura Micro, Inc. - 00063A (base 16) Dura Micro, Inc. - 13580 Fifth Street - Chino CA 91710 - UNITED STATES - - 00-06-3B (hex) Arcturus Networks Inc. - 00063B (base 16) Arcturus Networks Inc. - 701 Evans Ave. - Suite 300 - Toronto Ontario M9C 1A3 - CANADA - - 00-06-3C (hex) Intrinsyc Software International Inc. - 00063C (base 16) Intrinsyc Software International Inc. - 885 Dunsmuir Street, Suite 380 - Vancouver B.C. V6C 1N5 - CANADA - - 00-06-3D (hex) Microwave Data Systems Inc. - 00063D (base 16) Microwave Data Systems Inc. - 175 Science Parkway - Rochester NY 14620 - UNITED STATES - - 00-06-3E (hex) Opthos Inc. - 00063E (base 16) Opthos Inc. - 590 Taylor Way - San Carlos CA 94070 - UNITED STATES - - 00-06-3F (hex) Everex Communications Inc. - 00063F (base 16) Everex Communications Inc. - 5020A Brandin Ct. - Fremont CA 94538 - UNITED STATES - - 00-06-40 (hex) White Rock Networks - 000640 (base 16) White Rock Networks - Suite #900 - 18111 Preston Road - Dallas TX 75252 - UNITED STATES - - 00-06-41 (hex) ITCN - 000641 (base 16) ITCN - 8571 Gander Creek Drive - Miamisburg OH 45342 - UNITED STATES - - 00-06-42 (hex) Genetel Systems Inc. - 000642 (base 16) Genetel Systems Inc. - Mockwoo B/D, 912 Walpyoung-Dong - Seo-Gu Taejon, - 302-852 - KOREA, REPUBLIC OF - - 00-06-43 (hex) SONO Computer Co., Ltd. - 000643 (base 16) SONO Computer Co., Ltd. - 1F., No. 8, Alley 35, Lane 91, - Sec. 1, Nei-Hu Road, - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-06-44 (hex) neix,Inc - 000644 (base 16) neix,Inc - KKS Higashi-Sapporo Bldg. - 3-5-3-24, Higashi-Sapporo - Shiroishi-ku, Sapporo-city Hokkaido 003-0003 - JAPAN - - 00-06-45 (hex) Meisei Electric Co. Ltd. - 000645 (base 16) Meisei Electric Co. Ltd. - 249-1, Moriya-kou, Moriya - Kitasouma-Gun, Ibaraki - 302-0192 - JAPAN - - 00-06-46 (hex) ShenZhen XunBao Network Technology Co Ltd - 000646 (base 16) ShenZhen XunBao Network Technology Co Ltd - F3, R2-A Building, South District - of High-Tech Industrial Park, - Shen Zhen - CHINA - - 00-06-47 (hex) Etrali S.A. - 000647 (base 16) Etrali S.A. - 221, Rue La Fontaine - 94132 Fontenay Sous Bois Cedex - FRANCE - - 00-06-48 (hex) Seedsware, Inc. - 000648 (base 16) Seedsware, Inc. - 3-7-16 Technostage, - Izumi, Osaka 594-1144 - JAPAN - - 00-06-49 (hex) 3M Deutschland GmbH - 000649 (base 16) 3M Deutschland GmbH - Carl-Schurz-Str. 1 - Neuss D-41453 - GERMANY - - 00-06-4A (hex) Honeywell Co., Ltd. (KOREA) - 00064A (base 16) Honeywell Co., Ltd. (KOREA) - 56, Chaam-dong, Chonan-city - Choongcheongnam-do, 330-200, - KOREA, REPUBLIC OF - - 00-06-4B (hex) Alexon Co., Ltd. - 00064B (base 16) Alexon Co., Ltd. - 3-207-1 Teramoto, - Itami, Hyogo 664-0026 - JAPAN - - 00-06-4C (hex) Invicta Networks, Inc. - 00064C (base 16) Invicta Networks, Inc. - 13873 Park Center Road - Suite 400 - Herndon VA 20171 - UNITED STATES - - 00-06-4D (hex) Sencore - 00064D (base 16) Sencore - 3200 Sencore Dr. - Sioux Falls SD 57107 - UNITED STATES - - 00-06-4E (hex) Broad Net Technology Inc. - 00064E (base 16) Broad Net Technology Inc. - 5F, No.58, Lane 188, Rui Kuang Road - Neihu District, Taipei 114, - TAIWAN, PROVINCE OF CHINA - - 00-06-4F (hex) PRO-NETS Technology Corporation - 00064F (base 16) PRO-NETS Technology Corporation - Pao-Chung Road, - No. 92, 10F-1 - Hsin Tien Taipei, - TAIWAN, PROVINCE OF CHINA - - 00-06-50 (hex) Tiburon Networks, Inc. - 000650 (base 16) Tiburon Networks, Inc. - 200 Minuteman Rd. - Suite 2B - Andover MA 01810 - UNITED STATES - - 00-06-51 (hex) Aspen Networks Inc. - 000651 (base 16) Aspen Networks Inc. - 3777 Stevens Creek Blvd - Suite 330 - Santa Clara CA 95051 - UNITED STATES - - 00-06-52 (hex) CISCO SYSTEMS, INC. - 000652 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-53 (hex) CISCO SYSTEMS, INC. - 000653 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-54 (hex) Winpresa Building Automation Technologies GmbH - 000654 (base 16) Winpresa Building Automation Technologies GmbH - Vivenotgasse 53/2 - A-1120 Vienna - AUSTRIA - - 00-06-55 (hex) Yipee, Inc. - 000655 (base 16) Yipee, Inc. - 555 International Drive - Suite 800 - Williamsville NY 14221 - UNITED STATES - - 00-06-56 (hex) Tactel AB - 000656 (base 16) Tactel AB - Norra Vallgatan 64 - SE-211 22 Malmo - SWEDEN - - 00-06-57 (hex) Market Central, Inc. - 000657 (base 16) Market Central, Inc. - 500 Business Center Drive - Pittsburgh PA 15205-1333 - UNITED STATES - - 00-06-58 (hex) Helmut Fischer GmbH Institut für Elektronik und Messtechnik - 000658 (base 16) Helmut Fischer GmbH Institut für Elektronik und Messtechnik - Industriestraße 21 - 71069 Sindefingen - GERMANY - - 00-06-59 (hex) EAL (Apeldoorn) B.V. - 000659 (base 16) EAL (Apeldoorn) B.V. - Molenmakershoek 14 - Apeldoorn 7328JK - NETHERLANDS - - 00-06-5A (hex) Strix Systems - 00065A (base 16) Strix Systems - 310 N. Westlake Blvd. - Suite 150 - Westlake Village CA 91362 - UNITED STATES - - 00-06-5B (hex) Dell Computer Corp. - 00065B (base 16) Dell Computer Corp. - One Dell Way - Round Rock TX 78682 - UNITED STATES - - 00-06-5C (hex) Malachite Technologies, Inc. - 00065C (base 16) Malachite Technologies, Inc. - 195 New Hampshire Avenue - Suite 150 - Portsmouth NH 03801 - UNITED STATES - - 00-06-5D (hex) Heidelberg Web Systems - 00065D (base 16) Heidelberg Web Systems - 121 Technology Dr. - Durham NH 03824 - UNITED STATES - - 00-06-5E (hex) Photuris, Inc. - 00065E (base 16) Photuris, Inc. - 20 Corporate Place South - Piscataway NJ 08854 - UNITED STATES - - 00-06-5F (hex) ECI Telecom - NGTS Ltd. - 00065F (base 16) ECI Telecom - NGTS Ltd. - 30 Hasivim St. - Petah-Tikva 49130 - ISRAEL - - 00-06-60 (hex) NADEX Co., Ltd. - 000660 (base 16) NADEX Co., Ltd. - 1 Omiyamae, Tokushige, - Nishiharu-cyo, Nishikasugai-gun, - Aichi 481-0038 - JAPAN - - 00-06-61 (hex) NIA Home Technologies Corp. - 000661 (base 16) NIA Home Technologies Corp. - Innovation Incubator, NTHU, - 101, Sec. 2, Kuang Fu Road, - Hsinchu 30013, - TAIWAN, PROVINCE OF CHINA - - 00-06-62 (hex) MBM Technology Ltd. - 000662 (base 16) MBM Technology Ltd. - Victoria Rd. - Portslade, Brighton Sussex BN4l 1YH - UNITED KINGDOM - - 00-06-63 (hex) Human Technology Co., Ltd. - 000663 (base 16) Human Technology Co., Ltd. - 3rd Fl, Hyungok Bldg., - 836-25, Yuksam-Dong, - Kangnam-ku Seoul - KOREA, REPUBLIC OF - - 00-06-64 (hex) Fostex Corporation - 000664 (base 16) Fostex Corporation - 3-2-35, Musashino, Akishima, - Tokyo 196-0021 - JAPAN - - 00-06-65 (hex) Sunny Giken, Inc. - 000665 (base 16) Sunny Giken, Inc. - 3-1-9 Nishidai Itami-shi - Hyogo-pref. 664-0858 - JAPAN - - 00-06-66 (hex) Roving Networks - 000666 (base 16) Roving Networks - 809 University Avenue - Los Gatos CA 95032 - UNITED STATES - - 00-06-67 (hex) Tripp Lite - 000667 (base 16) Tripp Lite - 1111 W. 35th Street - Chicago IL 60609 - UNITED STATES - - 00-06-68 (hex) Vicon Industries Inc. - 000668 (base 16) Vicon Industries Inc. - 89 Arkay Drive - Hauppauge NY 11788 - UNITED STATES - - 00-06-69 (hex) Datasound Laboratories Ltd - 000669 (base 16) Datasound Laboratories Ltd - 5 Business Park West, Avenue One - Letchworth, Herts SG6 24B - ENGLAND - UNITED KINGDOM - - 00-06-6A (hex) InfiniCon Systems, Inc. - 00066A (base 16) InfiniCon Systems, Inc. - 700 American Ave. - Suite 101 - King of Prussia PA 19406 - UNITED STATES - - 00-06-6B (hex) Sysmex Corporation - 00066B (base 16) Sysmex Corporation - 4-4-4 Takatsukadai, - Nishi-ku, Kobe-City - 651-2271 - JAPAN - - 00-06-6C (hex) Robinson Corporation - 00066C (base 16) Robinson Corporation - 12F, No. 278 Ho Ping E. Rd., - Sec. 3 - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-06-6D (hex) Compuprint S.P.A. - 00066D (base 16) Compuprint S.P.A. - Via Martiri D'Italia 26 - 10014 Caluso (Turin) - ITALY - - 00-06-6E (hex) Delta Electronics, Inc. - 00066E (base 16) Delta Electronics, Inc. - 11F, 266 Wen-Hwa 2nd Road, - Sec. 1, Linkou, Taipei Hsien 244 - TAIWAN, PROVINCE OF CHINA - - 00-06-6F (hex) Korea Data Systems - 00066F (base 16) Korea Data Systems - 170, Gongdan-Dong, Gumi-Si - Kyungbuk 730-030 - KOREA, REPUBLIC OF - - 00-06-70 (hex) Upponetti Oy - 000670 (base 16) Upponetti Oy - Tykistokatu 4D - FIN-20520 Turku - FINLAND - - 00-06-71 (hex) Softing AG - 000671 (base 16) Softing AG - Richard-Reitzner-Allee 6 - 85540 Haar - GERMANY - - 00-06-72 (hex) Netezza - 000672 (base 16) Netezza - 1671 Worcester Road - Suite 100 - Framingham MA 01701 - UNITED STATES - - 00-06-73 (hex) TKH Security Solutions USA - 000673 (base 16) TKH Security Solutions USA - 12920 Cloverleaf Center Drive - Germantown MD 20874 - UNITED STATES - - 00-06-74 (hex) Spectrum Control, Inc. - 000674 (base 16) Spectrum Control, Inc. - 8061 Avonia Road - Fairview PA 16415 - UNITED STATES - - 00-06-75 (hex) Banderacom, Inc. - 000675 (base 16) Banderacom, Inc. - 9211 Waterford Centre Blvd. - Suite 100 - Austin TX 78758 - UNITED STATES - - 00-06-76 (hex) Novra Technologies Inc. - 000676 (base 16) Novra Technologies Inc. - 900-330 St. Mary Avenue - Winnipeg Manitoba R3C 3Z5 - CANADA - - 00-06-77 (hex) SICK AG - 000677 (base 16) SICK AG - Erwin-Sick Str.1 - Waldkirch D-79183 - GERMANY - - 00-06-78 (hex) Marantz Brand Company - 000678 (base 16) Marantz Brand Company - D&M Building, 2-1 Nisshin-cho - Kawasaki-ku - Kawasaki-shi Kawagawa 210-8569 - JAPAN - - 00-06-79 (hex) Konami Corporation - 000679 (base 16) Konami Corporation - 11-14-5 Akasaka, Minato-ku, - Tokyo 107-0052 - JAPAN - - 00-06-7A (hex) JMP Systems - 00067A (base 16) JMP Systems - 3rd Fl. Shinwha Bldg., - 1451-19, Seocho-dong, - Seocho-ku Seoul, - KOREA, REPUBLIC OF - - 00-06-7B (hex) Toplink C&C Corporation - 00067B (base 16) Toplink C&C Corporation - 6F-15, No. 12, Lane 609, Sec. 5 - Chung Hsin Rd., San Chung City - Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 00-06-7C (hex) CISCO SYSTEMS, INC. - 00067C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-7D (hex) Takasago Ltd. - 00067D (base 16) Takasago Ltd. - 1-24-16 Mizonokuchi Takatsu-ku - Kawasaki Kanagawa - JAPAN - - 00-06-7E (hex) WinCom Systems, Inc. - 00067E (base 16) WinCom Systems, Inc. - 10900 World Trade Blvd. - Suite 250 - Morrisville NC 27560 - UNITED STATES - - 00-06-7F (hex) Digeo, Inc. - 00067F (base 16) Digeo, Inc. - 8815 122nd Avenue NE - Kirkland WA 98033 - UNITED STATES - - 00-06-80 (hex) Card Access, Inc. - 000680 (base 16) Card Access, Inc. - 11778 S. Election Rd - Suite 260 - Salt Lake City UT 80420 - UNITED STATES - - 00-06-81 (hex) Goepel Electronic GmbH - 000681 (base 16) Goepel Electronic GmbH - Goeschwitzer Str. 58-60 - 07745 Jena - GERMANY - - 00-06-82 (hex) Convedia - 000682 (base 16) Convedia - 4190 Still Creek Dr. - Vancouver B.C. - V5C 6C6 - CANADA - - 00-06-83 (hex) Bravara Communications, Inc. - 000683 (base 16) Bravara Communications, Inc. - 2650 East Bayshore Road - Palo Alto CA 94303 - UNITED STATES - - 00-06-84 (hex) Biacore AB - 000684 (base 16) Biacore AB - Software, Electronics and Optics - Rapsgatan 7, 754 50 Uppsala - SWEDEN - - 00-06-85 (hex) NetNearU Corporation - 000685 (base 16) NetNearU Corporation - 2908 Finfeather Road - Bryan TX 77801 - UNITED STATES - - 00-06-86 (hex) ZARDCOM Co., Ltd. - 000686 (base 16) ZARDCOM Co., Ltd. - 4F, 1548-1, Seocho Dong, Seocho-Gu - Seoul - KOREA, REPUBLIC OF - - 00-06-87 (hex) Omnitron Systems Technology, Inc. - 000687 (base 16) Omnitron Systems Technology, Inc. - 140 Technology - Suite 500 - Irvine CA 92618 - UNITED STATES - - 00-06-88 (hex) Telways Communication Co., Ltd. - 000688 (base 16) Telways Communication Co., Ltd. - 3F, No. 53, Lane 258 - Zui-Kuang Rd., Nei-Hu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-06-89 (hex) yLez Technologies Pte Ltd - 000689 (base 16) yLez Technologies Pte Ltd - No. 1, Tannery Road, Cencon 1, - #09-03, 347719 - SINGAPORE - - 00-06-8A (hex) NeuronNet Co. Ltd. R&D Center - 00068A (base 16) NeuronNet Co. Ltd. R&D Center - 735-34 Dasung Bldg., Yuksam-dong, - Kangnam-gu, Seoul - KOREA, REPUBLIC OF - - 00-06-8B (hex) AirRunner Technologies, Inc. - 00068B (base 16) AirRunner Technologies, Inc. - 2401 Lupine Trail - South Lake Tahoe CA 96150 - UNITED STATES - - 00-06-8C (hex) 3Com Corporation - 00068C (base 16) 3Com Corporation - 5400 Bayfront Plaza - MS: 5116 - Santa Clara CA 95052 - UNITED STATES - - 00-06-8D (hex) SEPATON, Inc. - 00068D (base 16) SEPATON, Inc. - 400 Nickerson Rd. - Marlborough MA 01752 - UNITED STATES - - 00-06-8E (hex) HID Corporation - 00068E (base 16) HID Corporation - 9292 Jeronimo Road - Irvine CA 92618-1905 - UNITED STATES - - 00-06-8F (hex) Telemonitor, Inc. - 00068F (base 16) Telemonitor, Inc. - 9055F Guilford Road - Columbia MD 21046 - UNITED STATES - - 00-06-90 (hex) Euracom Communication GmbH - 000690 (base 16) Euracom Communication GmbH - Franklinstraße 14 - D-10587 Berlin - GERMANY - - 00-06-91 (hex) PT Inovacao - 000691 (base 16) PT Inovacao - Rua Eng. Jose F. Pinto Basto - 3810 Aveiro - PORTUGAL - - 00-06-92 (hex) Intruvert Networks, Inc. - 000692 (base 16) Intruvert Networks, Inc. - Suite 102 - 2290 North First Street - San Jose CA 95131 - UNITED STATES - - 00-06-93 (hex) Flexus Computer Technology, Inc. - 000693 (base 16) Flexus Computer Technology, Inc. - 8F-2, No.5, Alley22, Lane 513, - Ruei-Guang Rd., Nei-Hu Dist., - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-06-94 (hex) Mobillian Corporation - 000694 (base 16) Mobillian Corporation - 11031 Via Frontera - Suite C - San Diego CA 92127 - UNITED STATES - - 00-06-95 (hex) Ensure Technologies, Inc. - 000695 (base 16) Ensure Technologies, Inc. - 3526 West Liberty - Suite 100 - Ann Arbor MI 48103 - UNITED STATES - - 00-06-96 (hex) Advent Networks - 000696 (base 16) Advent Networks - 9600 Great Hills Tr. - Suite 300E - Austin TX 78759 - UNITED STATES - - 00-06-97 (hex) R & D Center - 000697 (base 16) R & D Center - 5F, Seungwon B/D, 810-9 - Bangbae-Dong, Seocho-Gu - Seoul - KOREA, REPUBLIC OF - - 00-06-98 (hex) egnite GmbH - 000698 (base 16) egnite GmbH - Erinstraße 9 - Castrop-Rauxel D-44575 - GERMANY - - 00-06-99 (hex) Vida Design Co. - 000699 (base 16) Vida Design Co. - 10F, No. 278 Ho Ping E. Rd., - Sec. 3, Taipei - TAIWAN, PROVINCE OF CHINA - - 00-06-9A (hex) e & Tel - 00069A (base 16) e & Tel - 100 Sejong-no Chongno-gu, - Seoul 110-777, - KOREA, REPUBLIC OF - - 00-06-9B (hex) AVT Audio Video Technologies GmbH - 00069B (base 16) AVT Audio Video Technologies GmbH - Rathsbergstraße 17 - D-90411 Nürnberg - GERMANY - - 00-06-9C (hex) Transmode Systems AB - 00069C (base 16) Transmode Systems AB - Jakobsdalsvagen 17 - Hägersten SE-126 53 - SWEDEN - - 00-06-9D (hex) Petards Ltd - 00069D (base 16) Petards Ltd - 390 Princesway, Team Valley - Gateshead Tyne and Wear NE11 OTU - UNITED KINGDOM - - 00-06-9E (hex) UNIQA, Inc. - 00069E (base 16) UNIQA, Inc. - 477 Valley Way - Milpitas CA 95035 - UNITED STATES - - 00-06-9F (hex) Kuokoa Networks - 00069F (base 16) Kuokoa Networks - 2901 Tasman Dr. - Suite 202 - Santa Clara CA 95054 - UNITED STATES - - 00-06-A0 (hex) Mx Imaging - 0006A0 (base 16) Mx Imaging - 2894 Columbia Street - Torrance CA 90503 - UNITED STATES - - 00-06-A1 (hex) Celsian Technologies, Inc. - 0006A1 (base 16) Celsian Technologies, Inc. - 3002 Dow Ave., Unit 138 - Tustin CA 92780 - UNITED STATES - - 00-06-A2 (hex) Microtune, Inc. - 0006A2 (base 16) Microtune, Inc. - 6440 Lusk Blvd., Suite D205 - San Diego CA 92121 - UNITED STATES - - 00-06-A3 (hex) Bitran Corporation - 0006A3 (base 16) Bitran Corporation - 2213 Mochida - Gyouda Saitama - JAPAN - - 00-06-A4 (hex) INNOWELL Corp. - 0006A4 (base 16) INNOWELL Corp. - #717 ChongGu Bluevill - 11-1, Sunae-1 Dong, Bundang-Gu, Sungnam- - 463-825 - KOREA, REPUBLIC OF - - 00-06-A5 (hex) PINON Corp. - 0006A5 (base 16) PINON Corp. - Axis Gotanda Bldg.7F-701 - 8-7-11 Nishigotanda Shinagawa-ku - Tokyo 141-0031 - JAPAN - - 00-06-A6 (hex) Artistic Licence Engineering Ltd - 0006A6 (base 16) Artistic Licence Engineering Ltd - 24 Forward Drive - Christchurch Avenue - Harrow Middlesex HA3 8NT - UNITED KINGDOM - - 00-06-A7 (hex) Primarion - 0006A7 (base 16) Primarion - 3450 Torrance Blvd. - Torrance CA 90503 - UNITED STATES - - 00-06-A8 (hex) KC Technology, Inc. - 0006A8 (base 16) KC Technology, Inc. - 1900 McCarthy Blvd. - Suite 300 - Milpitas CA 95035 - UNITED STATES - - 00-06-A9 (hex) Universal Instruments Corp. - 0006A9 (base 16) Universal Instruments Corp. - PO Box 825 - Binghamton NY 13902 - UNITED STATES - - 00-06-AA (hex) VT Miltope - 0006AA (base 16) VT Miltope - 4900 Pearl East Circle - Suite 106 - Boulder CO 80301 - UNITED STATES - - 00-06-AB (hex) W-Link Systems, Inc. - 0006AB (base 16) W-Link Systems, Inc. - No. 20, Park Ave. II, - Science Based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-06-AC (hex) Intersoft Co. - 0006AC (base 16) Intersoft Co. - #1803 sun-kyoung Officetel - 106-4 Bunzi, Guro5Dong, Guro Gu - Seoul - KOREA, REPUBLIC OF - - 00-06-AD (hex) KB Electronics Ltd. - 0006AD (base 16) KB Electronics Ltd. - 150 Bluewater Rd. - Bedford, Nova Scotia - B4B 1G9 - CANADA - - 00-06-AE (hex) Himachal Futuristic Communications Ltd - 0006AE (base 16) Himachal Futuristic Communications Ltd - 8, Commercial Complex - Masjid Moth, Greater Kailash II - New Dehli 110048 - INDIA - - 00-06-AF (hex) Xalted Networks - 0006AF (base 16) Xalted Networks - 2901 Dallas Parkway - Suite 200 - Plano TX 75093 - UNITED STATES - - 00-06-B0 (hex) Comtech EF Data Corp. - 0006B0 (base 16) Comtech EF Data Corp. - 2114 W. 7th St. - Tempe AZ 85281 - UNITED STATES - - 00-06-B1 (hex) Sonicwall - 0006B1 (base 16) Sonicwall - 1160 Bordeaux Dr. - Sunnyvale CA 94089 - UNITED STATES - - 00-06-B2 (hex) Linxtek Co. - 0006B2 (base 16) Linxtek Co. - 2F Kum-a B/D 31-3 Karak-dong, - Songpa-ku, Seoul, - 138-160 - KOREA, REPUBLIC OF - - 00-06-B3 (hex) Diagraph Corporation - 0006B3 (base 16) Diagraph Corporation - 3401 Rider Trail South - Earth City MO 63045-1110 - UNITED STATES - - 00-06-B4 (hex) Vorne Industries, Inc. - 0006B4 (base 16) Vorne Industries, Inc. - 1445 Industrial Dr. - Itasca IL 60143-1849 - UNITED STATES - - 00-06-B5 (hex) Source Photonics, Inc. - 0006B5 (base 16) Source Photonics, Inc. - 20550 Nordhoff St. - Chatsworth CA 91311 - UNITED STATES - - 00-06-B6 (hex) Nir-Or Israel Ltd. - 0006B6 (base 16) Nir-Or Israel Ltd. - 11 Amal St. - Rosh Ha'ayin 48092 - ISRAEL - - 00-06-B7 (hex) TELEM GmbH - 0006B7 (base 16) TELEM GmbH - Lise-Meitner-Allee 31 - D 44801 - GERMANY - - 00-06-B8 (hex) Bandspeed Pty Ltd - 0006B8 (base 16) Bandspeed Pty Ltd - Level 9, 5000 Collins Street - Melbourne Vic 3000 - AUSTRALIA - - 00-06-B9 (hex) A5TEK Corp. - 0006B9 (base 16) A5TEK Corp. - 1233 Alderwood Ave. - Sunnyvale CA 94089 - UNITED STATES - - 00-06-BA (hex) Westwave Communications - 0006BA (base 16) Westwave Communications - 463 Aviation Blvd. - Santa Rosa CA 95403 - UNITED STATES - - 00-06-BB (hex) ATI Technologies Inc. - 0006BB (base 16) ATI Technologies Inc. - 75 Tiverton Court - Unionville, ON L3R 953 - CANADA - - 00-06-BC (hex) Macrolink, Inc. - 0006BC (base 16) Macrolink, Inc. - 1500 N Kellogg Dr. - Anaheim CA 92807 - UNITED STATES - - 00-06-BD (hex) BNTECHNOLOGY Co., Ltd. - 0006BD (base 16) BNTECHNOLOGY Co., Ltd. - 602 Youngshin Bldg. 238-8 - Poi-Dong Kangnam-Gu - Seoul - KOREA, REPUBLIC OF - - 00-06-BE (hex) Baumer Optronic GmbH - 0006BE (base 16) Baumer Optronic GmbH - Badstraße 30 - D-01454 Radeberg - GERMANY - - 00-06-BF (hex) Accella Technologies Co., Ltd. - 0006BF (base 16) Accella Technologies Co., Ltd. - Rm 512 No. 680 Gui Ping Rd. - Shanghai 200233 - CHINA - - 00-06-C0 (hex) United Internetworks, Inc. - 0006C0 (base 16) United Internetworks, Inc. - 5072 North 300 West, Suite 2N - Provo UT 84604 - UNITED STATES - - 00-06-C1 (hex) CISCO SYSTEMS, INC. - 0006C1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-C2 (hex) Smartmatic Corporation - 0006C2 (base 16) Smartmatic Corporation - 6400 Congress Ave., Suite 1300 - Boca Raton FL 33487 - UNITED STATES - - 00-06-C3 (hex) Schindler Elevator Ltd. - 0006C3 (base 16) Schindler Elevator Ltd. - R&D-CO - Zugerstrasse 13 - Ebikon CH-6030 - SWITZERLAND - - 00-06-C4 (hex) Piolink Inc. - 0006C4 (base 16) Piolink Inc. - IT Castle 1-401, 550-1 Gasan-dong, - 1656-2 Seocho-Gu, Seoul - Seoul Geumchon-Gu 153-803 - KOREA, REPUBLIC OF - - 00-06-C5 (hex) INNOVI Technologies Limited - 0006C5 (base 16) INNOVI Technologies Limited - 31st Floor, China Online Centre - 333 Lockhart Road - Wanchai - HONG KONG - - 00-06-C6 (hex) lesswire AG - 0006C6 (base 16) lesswire AG - Im Technologiepark 25 - GERMANY - - 00-06-C7 (hex) RFNET Technologies Pte Ltd (S) - 0006C7 (base 16) RFNET Technologies Pte Ltd (S) - Unit 233 Innovation Centre Blk 2 - 18 Nanyang Drive - 637722 - SINGAPORE - - 00-06-C8 (hex) Sumitomo Metal Micro Devices, Inc. - 0006C8 (base 16) Sumitomo Metal Micro Devices, Inc. - 1, Higashimukojima Higashino-cho - Amagasaki, Hyogo, 660-8660 - JAPAN - - 00-06-C9 (hex) Technical Marketing Research, Inc. - 0006C9 (base 16) Technical Marketing Research, Inc. - Shin Nihon Gijutsu Bldg. - 1-1-32, Shibadaimon, Minato-ku - Tokyo 105-0012 105-0012 - JAPAN - - 00-06-CA (hex) American Computer & Digital Components, Inc. (ACDC) - 0006CA (base 16) American Computer & Digital Components, Inc. (ACDC) - 440 Cloverleaf Drive - Baldwin Park CA 91706 - UNITED STATES - - 00-06-CB (hex) Jotron Electronics A/S - 0006CB (base 16) Jotron Electronics A/S - Pob 54 - N3280 Tjodalyng - NORWAY - - 00-06-CC (hex) JMI Electronics Co., Ltd. - 0006CC (base 16) JMI Electronics Co., Ltd. - Nanyang B/D 3F, 25-4 - Yonmun-dong, Yongsan-gu - Seoul 140-080 - KOREA, REPUBLIC OF - - 00-06-CD (hex) Leaf Imaging Ltd. - 0006CD (base 16) Leaf Imaging Ltd. - 7th Hatnufa st - Petach-Tikva 49002 - ISRAEL - - 00-06-CE (hex) DATENO - 0006CE (base 16) DATENO - Rue Amiral Berenger - Zac Es Passants II BP 90145, 35801 Dinar - FRANCE - - 00-06-CF (hex) Thales Avionics In-Flight Systems, LLC - 0006CF (base 16) Thales Avionics In-Flight Systems, LLC - 17481 Red Hill Avenue - Irvine CA 92614-5630 - UNITED STATES - - 00-06-D0 (hex) Elgar Electronics Corp. - 0006D0 (base 16) Elgar Electronics Corp. - 9250 Brown Deer Rd. - San Diego CA 92121 - UNITED STATES - - 00-06-D1 (hex) Tahoe Networks, Inc. - 0006D1 (base 16) Tahoe Networks, Inc. - 3052 Orchard Drive - San Jose CA 95134 - UNITED STATES - - 00-06-D2 (hex) Tundra Semiconductor Corp. - 0006D2 (base 16) Tundra Semiconductor Corp. - 603 March Road - Kanata, Ont. - K2K-2M5 - CANADA - - 00-06-D3 (hex) Alpha Telecom, Inc. U.S.A. - 0006D3 (base 16) Alpha Telecom, Inc. U.S.A. - 1394 Borregor Ave. - Sunnyvale CA 94089 - UNITED STATES - - 00-06-D4 (hex) Interactive Objects, Inc. - 0006D4 (base 16) Interactive Objects, Inc. - 12600 SE 38th St. - Suite 150 - Bellevue WA 98006 - UNITED STATES - - 00-06-D5 (hex) Diamond Systems Corp. - 0006D5 (base 16) Diamond Systems Corp. - 8430-D Central Ave. - Newark CA 94560 - UNITED STATES - - 00-06-D6 (hex) CISCO SYSTEMS, INC. - 0006D6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-D7 (hex) CISCO SYSTEMS, INC. - 0006D7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-D8 (hex) Maple Optical Systems - 0006D8 (base 16) Maple Optical Systems - 3200 North First St. - San Jose CA 95134 - UNITED STATES - - 00-06-D9 (hex) IPM-Net S.p.A. - 0006D9 (base 16) IPM-Net S.p.A. - Via Remo De Feo - 80022 Arzano (Naples) - ITALY - - 00-06-DA (hex) ITRAN Communications Ltd. - 0006DA (base 16) ITRAN Communications Ltd. - 1 Azrieli Center, - The round building - Tel Aviv 67021 67021 - ISRAEL - - 00-06-DB (hex) ICHIPS Co., Ltd. - 0006DB (base 16) ICHIPS Co., Ltd. - 3F, Samjeon Bldg., 236-3 - Nonhyun-Dong, Kangnam-ku - Seoul-City 135-01 - KOREA, REPUBLIC OF - - 00-06-DC (hex) Syabas Technology (Amquest) - 0006DC (base 16) Syabas Technology (Amquest) - 4727 Paseo Padre Parkway - Fremont CA 94555 - UNITED STATES - - 00-06-DD (hex) AT & T Laboratories - Cambridge Ltd - 0006DD (base 16) AT & T Laboratories - Cambridge Ltd - 24a Trumpington Street - Cambridge, CB2 1QA - ENGLAND - UNITED KINGDOM - - 00-06-DE (hex) Flash Technology - 0006DE (base 16) Flash Technology - P.O. Box 681509 - Franklin TN 37068 - UNITED STATES - - 00-06-DF (hex) AIDONIC Corporation - 0006DF (base 16) AIDONIC Corporation - 2-7-10 Otsuka, Bunkyo-ku, - Tokyo, 112-0012 - JAPAN - - 00-06-E0 (hex) MAT Co., Ltd. - 0006E0 (base 16) MAT Co., Ltd. - 864-3 Kwanyang-dong - Dongan-gu, Anyang-si - Kyunggi-do 431-060 - KOREA, REPUBLIC OF - - 00-06-E1 (hex) Techno Trade s.a - 0006E1 (base 16) Techno Trade s.a - 732a Chaussee de Bruxelles - B-1410 Waterloo - BELGIUM - - 00-06-E2 (hex) Ceemax Technology Co., Ltd. - 0006E2 (base 16) Ceemax Technology Co., Ltd. - 5f-7, 736, Chung Cheng Rd., - Chung Ho Taipei Hsien, - TAIWAN, PROVINCE OF CHINA - - 00-06-E3 (hex) Quantitative Imaging Corporation - 0006E3 (base 16) Quantitative Imaging Corporation - 8081 Lougheed Highway - Burnaby, BC - CANADA - - 00-06-E4 (hex) Citel Technologies Ltd. - 0006E4 (base 16) Citel Technologies Ltd. - Wheatcroft Business Park - Landmere Lane, Edwalton - Nottigham NG12 4DG - UNITED KINGDOM - - 00-06-E5 (hex) Fujian Newland Computer Ltd. Co. - 0006E5 (base 16) Fujian Newland Computer Ltd. Co. - 141F Sunshine Holiday Hotel - No. 26 Gao Qiao Rd., WuYi Square - Fuzhou Fujian 350005 - CHINA - - 00-06-E6 (hex) DongYang Telecom Co., Ltd. - 0006E6 (base 16) DongYang Telecom Co., Ltd. - 642-7 Deung Chon-Dong, KangSeo-Gu - Seoul 157-841 - KOREA, REPUBLIC OF - - 00-06-E7 (hex) Bit Blitz Communications Inc. - 0006E7 (base 16) Bit Blitz Communications Inc. - 830 Hillview Ct., #290 - Milpitas CA 95035 - UNITED STATES - - 00-06-E8 (hex) Optical Network Testing, Inc. - 0006E8 (base 16) Optical Network Testing, Inc. - 55 Merchant St. - 28th Floor - Honolulu HI 96813 - UNITED STATES - - 00-06-E9 (hex) Intime Corp. - 0006E9 (base 16) Intime Corp. - 324-4, Yangjae-dong, 2F - Seocho-ku, Seoul, 137-130, - KOREA, REPUBLIC OF - - 00-06-EA (hex) ELZET80 Mikrocomputer GmbH&Co. KG - 0006EA (base 16) ELZET80 Mikrocomputer GmbH&Co. KG - Theaterplatz 9 - D-52062 Aachen - GERMANY - - 00-06-EB (hex) Global Data - 0006EB (base 16) Global Data - 2250 Obispo Ave #105 - Signal Hill CA 90806 - UNITED STATES - - 00-06-EC (hex) Harris Corporation - 0006EC (base 16) Harris Corporation - 1025 West NASA Blvd - MS D-21B - Melbourne FL 32919 - UNITED STATES - - 00-06-ED (hex) Inara Networks - 0006ED (base 16) Inara Networks - 3031 Tisch Way, - Suite 100 - San Jose CA 95128 - UNITED STATES - - 00-06-EE (hex) Shenyang Neu-era Information & Technology Stock Co., Ltd - 0006EE (base 16) Shenyang Neu-era Information & Technology Stock Co., Ltd - 8/F, the 21st Century Building, - No. 1 Shiji Road, Hunnan Industrial Dist - Dvlpmnt Zone Shenyang, - CHINA - - 00-06-EF (hex) Maxxan Systems, Inc. - 0006EF (base 16) Maxxan Systems, Inc. - 107 Bonaventura Drive - San Jose CA 95134 - UNITED STATES - - 00-06-F0 (hex) Digeo, Inc. - 0006F0 (base 16) Digeo, Inc. - 8815 122nd Ave., NE - Kirkland WA 98033 - UNITED STATES - - 00-06-F1 (hex) Optillion - 0006F1 (base 16) Optillion - Kronborgsgr.9 - SE-16487 Kista - SWEDEN - - 00-06-F2 (hex) Platys Communications - 0006F2 (base 16) Platys Communications - 3150A Coronado Dr. - Santa Clara CA 95054 - UNITED STATES - - 00-06-F3 (hex) AcceLight Networks - 0006F3 (base 16) AcceLight Networks - 70 Abele Road, Building 1200 - Pittsburgh PA 15017 - UNITED STATES - - 00-06-F4 (hex) Prime Electronics & Satellitics Inc. - 0006F4 (base 16) Prime Electronics & Satellitics Inc. - 69, Tung-Yuan Rd., - Chung-Li City, Taoyuan - TAIWAN, PROVINCE OF CHINA - - 00-06-F5 (hex) ALPS Co,. Ltd. - 0006F5 (base 16) ALPS Co,. Ltd. - 6-3-36 Furukawanakazato, - Osaki Miyagi-pref 989-6181 - JAPAN - - 00-06-F6 (hex) CISCO SYSTEMS, INC. - 0006F6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-06-F7 (hex) ALPS Co,. Ltd. - 0006F7 (base 16) ALPS Co,. Ltd. - 6-3-36 Furukawanakazato, - Osaki Miyagi-pref 989-6181 - JAPAN - - 00-06-F8 (hex) The Boeing Company - 0006F8 (base 16) The Boeing Company - 5731 W. Las Positas Blvd. - MC 1520-0553 - Pleasanton CA 94588 - UNITED STATES - - 00-06-F9 (hex) Mitsui Zosen Systems Research Inc. - 0006F9 (base 16) Mitsui Zosen Systems Research Inc. - 11-1, Uno 1-chome - Tamano-shi, Okayama - 706-0011 - JAPAN - - 00-06-FA (hex) IP SQUARE Co, Ltd. - 0006FA (base 16) IP SQUARE Co, Ltd. - 1-9-11, Hakataekihigashi, - Hakata-ku, Fukuoka-shi, - Fukuoka 812-0013 - JAPAN - - 00-06-FB (hex) Hitachi Printing Solutions, Ltd. - 0006FB (base 16) Hitachi Printing Solutions, Ltd. - 1060, Takeda Hitachinaka-City - Ibaraki-Pref. - 312-8502 - JAPAN - - 00-06-FC (hex) Fnet Co., Ltd. - 0006FC (base 16) Fnet Co., Ltd. - KFSB Bldg. 10th F. 16-2 - Yoido-Dong, Youngdeungpo-ku, - Seoul - KOREA, REPUBLIC OF - - 00-06-FD (hex) Comjet Information Systems Corp. - 0006FD (base 16) Comjet Information Systems Corp. - 7Fl., No. 103, Fen Liao Street - Nei-Hu, Taipei - TAIWAN, PROVINCE OF CHINA - - 00-06-FE (hex) Ambrado, Inc - 0006FE (base 16) Ambrado, Inc - 11301 W. President George Bush Fwy. - Suite150 - Richardson TX 75080 - UNITED STATES - - 00-06-FF (hex) Sheba Systems Co., Ltd. - 0006FF (base 16) Sheba Systems Co., Ltd. - 5th Fl. Hyundai Jad B/D - 460-1 Seongnae-Dong, Kangdong-Ku, - Seoul 134-030 - KOREA, REPUBLIC OF - - 00-07-00 (hex) Zettamedia Korea - 000700 (base 16) Zettamedia Korea - Suite 1008, Kumkang Venturetel, 1108 - Bisandong, Dongangu, Anyangsi - Kyounggido, - KOREA, REPUBLIC OF - - 00-07-01 (hex) RACAL-DATACOM - 000701 (base 16) RACAL-DATACOM - LAN INTERNETWORKING DIVISION - 155 SWANSON ROAD - BOXBOROUGH MA 01719 - UNITED STATES - - 00-07-02 (hex) Varian Medical Systems - 000702 (base 16) Varian Medical Systems - 2599 Garcia Avenue - Mountain View CA 94043 - UNITED STATES - - 00-07-03 (hex) CSEE Transport - 000703 (base 16) CSEE Transport - 4, avenue du CANADA - B.P. 243-91944 Les Ulis - FRANCE - - 00-07-04 (hex) ALPS Co,. Ltd. - 000704 (base 16) ALPS Co,. Ltd. - 6-3-36 Furukawanakazato, - Osaki Miyagi-pref 989-6181 - JAPAN - - 00-07-05 (hex) Endress & Hauser GmbH & Co - 000705 (base 16) Endress & Hauser GmbH & Co - Hauptstrabe 1 - Postfach 1261 - D-79689 Maulberg - GERMANY - - 00-07-06 (hex) Sanritz Corporation - 000706 (base 16) Sanritz Corporation - 199-1, Shimooibukuro, - Kawagoe-city, Saitama - 350-0848 - JAPAN - - 00-07-07 (hex) Interalia Inc. - 000707 (base 16) Interalia Inc. - 4110-79th Street N.W. - Calgary, Alberta - T3B 5C2 - CANADA - - 00-07-08 (hex) Bitrage Inc. - 000708 (base 16) Bitrage Inc. - 100 Southpark Blvd. - Suite 400 - Saint Augustine FL 32086 - UNITED STATES - - 00-07-09 (hex) Westerstrand Urfabrik AB - 000709 (base 16) Westerstrand Urfabrik AB - Box 133 - SE-545 23 Toreboda - SWEDEN - - 00-07-0A (hex) Unicom Automation Co., Ltd. - 00070A (base 16) Unicom Automation Co., Ltd. - Silk Bldg 3-31-11 - Honcho, Nakano-ku, - Tokyo 164-0012 - JAPAN - - 00-07-0B (hex) Novabase SGPS, SA - 00070B (base 16) Novabase SGPS, SA - Av. D Joao II, Lote 1.03.2.3 - Parque das Nacoes - Lisboa 1998-031 - PORTUGAL - - 00-07-0C (hex) SVA-Intrusion.com Co. Ltd. - 00070C (base 16) SVA-Intrusion.com Co. Ltd. - The 4th Floor, No. 28 Building - 140 Tian Lin Road - Shanghai 20233 - CHINA - - 00-07-0D (hex) CISCO SYSTEMS, INC. - 00070D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-0E (hex) CISCO SYSTEMS, INC. - 00070E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-0F (hex) Fujant, Inc. - 00070F (base 16) Fujant, Inc. - 6305 Carpinteria Avenue - Suite 300 - Carpinteria CA 93013-2901 - UNITED STATES - - 00-07-10 (hex) Adax, Inc. - 000710 (base 16) Adax, Inc. - 614 Bancroft Way - Berkeley CA 94556 - UNITED STATES - - 00-07-11 (hex) Acterna - 000711 (base 16) Acterna - 6620 Network Way - Indianapolis IN 46278 - UNITED STATES - - 00-07-12 (hex) JAL Information Technology - 000712 (base 16) JAL Information Technology - Network Solution Dep. JAL-Tamachi Bldg. - 15-1, Shibura, 4-chome, Minato-ku, - Tokyo - JAPAN - - 00-07-13 (hex) IP One, Inc. - 000713 (base 16) IP One, Inc. - Sammi Bldg., 1004 - Daechi-dong Gangnam-gu, - Seoul, 135-083 - KOREA, REPUBLIC OF - - 00-07-14 (hex) Brightcom - 000714 (base 16) Brightcom - 6 Hanechoshet St., - Tel Aviv 69710 - ISRAEL - - 00-07-15 (hex) General Research of Electronics, Inc. - 000715 (base 16) General Research of Electronics, Inc. - 3-12-17, Mita, Minato-ku - Tokyo 108-0073 - JAPAN - - 00-07-16 (hex) J & S Marine Ltd. - 000716 (base 16) J & S Marine Ltd. - Pottington Business Park - Barnstaple - Devon EX31 1LY - UNITED KINGDOM - - 00-07-17 (hex) Wieland Electric GmbH - 000717 (base 16) Wieland Electric GmbH - Brennerstraße 10-14 - D-96052 Bamberg - GERMANY - - 00-07-18 (hex) iCanTek Co., Ltd. - 000718 (base 16) iCanTek Co., Ltd. - 2nd Fl. DK Plaza II, 376-5, - Keumgok-dong, Bumdag-ku, - Sungman-si, Kyonggi-do 463-805 - KOREA, REPUBLIC OF - - 00-07-19 (hex) Mobiis Co., Ltd. - 000719 (base 16) Mobiis Co., Ltd. - 277-1, Shinhwa Bldg. 4F - Yangjae-dong, Seocho-gu, - Seoul, - KOREA, REPUBLIC OF - - 00-07-1A (hex) Finedigital Inc. - 00071A (base 16) Finedigital Inc. - 4th Fl. Bomi Bldg., 661 Deungchon 3 Dong - Kangseo ku, - Seoul 157-033 - KOREA, REPUBLIC OF - - 00-07-1B (hex) CDVI Americas Ltd - 00071B (base 16) CDVI Americas Ltd - 1637 Autoroute Laval West - Laval Quebec H7L 3W3 - CANADA - - 00-07-1C (hex) AT&T Fixed Wireless Services - 00071C (base 16) AT&T Fixed Wireless Services - P.O. Box 90759 - Redmond WA 98073-9759 - UNITED STATES - - 00-07-1D (hex) Satelsa Sistemas Y Aplicaciones De Telecomunicaciones, S.A. - 00071D (base 16) Satelsa Sistemas Y Aplicaciones De Telecomunicaciones, S.A. - c/, Alejandro Moran, 56 - 28025-Madrid - SPAIN - - 00-07-1E (hex) Tri-M Engineering / Nupak Dev. Corp. - 00071E (base 16) Tri-M Engineering / Nupak Dev. Corp. - 6-1301 Ketch Court - Coquitcaut BC - V3K 6X7 - CANADA - - 00-07-1F (hex) European Systems Integration - 00071F (base 16) European Systems Integration - 455 Promenade Des Anglas - F-06200 Nice - FRANCE - - 00-07-20 (hex) Trutzschler GmbH & Co. KG - 000720 (base 16) Trutzschler GmbH & Co. KG - Duvenstraße 82-92 - 41199 Monchengladbach - GERMANY - - 00-07-21 (hex) Formac Elektronik GmbH - 000721 (base 16) Formac Elektronik GmbH - Dofstraße 33 - 15827 Blankentelde - GERMANY - - 00-07-22 (hex) The Nielsen Company - 000722 (base 16) The Nielsen Company - 501 Brooker Creek Blvd. - Oldsmar FL 34677 - UNITED STATES - - 00-07-23 (hex) ELCON Systemtechnik GmbH - 000723 (base 16) ELCON Systemtechnik GmbH - Obere Hauptstraße 10 - D-09232 Hartmannsdorf - GERMANY - - 00-07-24 (hex) Telemax Co., Ltd. - 000724 (base 16) Telemax Co., Ltd. - 6th Fl. Sungwoo B/D, 1099-1 - Sanbon-Dong, Kunpo-shi - Kyungki-Do, 435-040 - KOREA, REPUBLIC OF - - 00-07-25 (hex) Bematech International Corp. - 000725 (base 16) Bematech International Corp. - 5895 Shiloh Road - Suite 111 - Alpharetta GA 30005 - UNITED STATES - - 00-07-26 (hex) Shenzhen Gongjin Electronics Co., Ltd. - 000726 (base 16) Shenzhen Gongjin Electronics Co., Ltd. - A211-A213 & B201-B210, 2F, Baiying Building, 1019#, Nanhai RD, Shekou Party, Nanshan District, - Shenzhen Guangdong 518067 - CHINA - - 00-07-27 (hex) Zi Corporation (HK) Ltd. - 000727 (base 16) Zi Corporation (HK) Ltd. - 30/F, China Resources Building - 26 Harbour Road, Waichai, - HONG KONG - - 00-07-28 (hex) Neo Telecom - 000728 (base 16) Neo Telecom - East Building 9F, 1T - Venture Tower, 78 Garag-dong - Songpa-gu, Seoul - KOREA, REPUBLIC OF - - 00-07-29 (hex) Kistler Instrumente AG - 000729 (base 16) Kistler Instrumente AG - Eulachstrasse 22 - CH-8408 Winterthur - SWITZERLAND - - 00-07-2A (hex) Innovance Networks - 00072A (base 16) Innovance Networks - 19 Fairmont Avenue - Ottawa, Ontario K1Y 1X4 - CANADA - - 00-07-2B (hex) Jung Myung Telecom Co., Ltd. - 00072B (base 16) Jung Myung Telecom Co., Ltd. - 5Fl Silla Technovil., 39-3 Dang-Dong - Koonpo-shi, Kyung Ki-Do - KOREA, REPUBLIC OF - - 00-07-2C (hex) Fabricom - 00072C (base 16) Fabricom - Rue Gatti De Gamond 254 - 1190 Bruxelles - BELGIUM - - 00-07-2D (hex) CNSystems - 00072D (base 16) CNSystems - Baumkircherstrasse 1 - A-8020 Graz - AUSTRIA - - 00-07-2E (hex) North Node AB - 00072E (base 16) North Node AB - Skeppsloron 42 - 1130 Stockholm - SWEDEN - - 00-07-2F (hex) Intransa, Inc. - 00072F (base 16) Intransa, Inc. - 2670 Zanker - Suite 200 - San Jose CA 95134 - UNITED STATES - - 00-07-30 (hex) Hutchison OPTEL Telecom Technology Co., Ltd. - 000730 (base 16) Hutchison OPTEL Telecom Technology Co., Ltd. - No. 28 Xinwai Street - Beijing - CHINA - - 00-07-31 (hex) Ophir-Spiricon LLC - 000731 (base 16) Ophir-Spiricon LLC - 3050 N 300 W - North Logan UT 84341 - UNITED STATES - - 00-07-32 (hex) AAEON Technology Inc. - 000732 (base 16) AAEON Technology Inc. - 5F, #135, Lane 235, Pao Chiao Road - Hsin-Tien City - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-07-33 (hex) DANCONTROL Engineering - 000733 (base 16) DANCONTROL Engineering - Italiensvej 1-5 - DK-8450 Hammel - DENMARK - - 00-07-34 (hex) ONStor, Inc. - 000734 (base 16) ONStor, Inc. - 130-B Knowles Drive - Los Gatos CA 95032 - UNITED STATES - - 00-07-35 (hex) Flarion Technologies, Inc. - 000735 (base 16) Flarion Technologies, Inc. - 135 Route 202/206 South - Bedminster NJ 07921 - UNITED STATES - - 00-07-36 (hex) Data Video Technologies Co., Ltd. - 000736 (base 16) Data Video Technologies Co., Ltd. - 7F, No. 352, Sec. 2 - Chung-Shan Rd., Chung-Ho City - Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-07-37 (hex) Soriya Co. Ltd. - 000737 (base 16) Soriya Co. Ltd. - 2, 8th Floor Hanshin B/O, 136-1, - Hapo-dong, Mapo-gu, - Seoul, - KOREA, REPUBLIC OF - - 00-07-38 (hex) Young Technology Co., Ltd. - 000738 (base 16) Young Technology Co., Ltd. - D-604, Sigma-II Officetel, - #18, Gumi-dong, Bundgang-gu, - Sungnam-si, Kyeonggi-do 763-741 - KOREA, REPUBLIC OF - - 00-07-39 (hex) Scotty Group Austria Gmbh - 000739 (base 16) Scotty Group Austria Gmbh - Teslastrasse 4 - 8074 Grambach 8074 - AUSTRIA - - 00-07-3A (hex) Inventel Systemes - 00073A (base 16) Inventel Systemes - 35, rue Toumefort - 75005 Paris - FRANCE - - 00-07-3B (hex) Tenovis GmbH & Co KG - 00073B (base 16) Tenovis GmbH & Co KG - Kleyerstraße 94 - 60326 Frankfurt - GERMANY - - 00-07-3C (hex) Telecom Design - 00073C (base 16) Telecom Design - Voie Romaine, Zone de Remora - 33170 Gradignan - FRANCE - - 00-07-3D (hex) Nanjing Postel Telecommunications Co., Ltd. - 00073D (base 16) Nanjing Postel Telecommunications Co., Ltd. - No. 187, ShengZhou Road, - Nanjing City, Jiangsu - 210004 - CHINA - - 00-07-3E (hex) China Great-Wall Computer Shenzhen Co., Ltd. - 00073E (base 16) China Great-Wall Computer Shenzhen Co., Ltd. - Research & Development Center, Kefa Road - Science Industry Park, Nanshan Disctrict - Shenzhen 518057 - CHINA - - 00-07-3F (hex) Woojyun Systec Co., Ltd. - 00073F (base 16) Woojyun Systec Co., Ltd. - 4F Han Yang B/D, Yoido-dong - Young Deong Po-ku - Seoul 150-010 - KOREA, REPUBLIC OF - - 00-07-40 (hex) Buffalo Inc. - 000740 (base 16) Buffalo Inc. - AKAMONDORI Bldg., 30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref. 460-8315 - JAPAN - - 00-07-41 (hex) Sierra Automated Systems - 000741 (base 16) Sierra Automated Systems - 2821 Burton Ave. - Burbank CA 91504 - UNITED STATES - - 00-07-42 (hex) Ormazabal - 000742 (base 16) Ormazabal - Parque Tecnologico 104 - 48170 Zamudio, Bizkaia - SPAIN - - 00-07-43 (hex) Chelsio Communications - 000743 (base 16) Chelsio Communications - 170 S. Whismon Rd. - Bldg. D, Ste A - Mountain View CA 94041-1512 - UNITED STATES - - 00-07-44 (hex) Unico, Inc. - 000744 (base 16) Unico, Inc. - 3725 Nicholson Rd. - Franksville WI 53126 - UNITED STATES - - 00-07-45 (hex) Radlan Computer Communications Ltd. - 000745 (base 16) Radlan Computer Communications Ltd. - Atidim Technology Park - Bldg. 4 - Tel Aviv 61131 - ISRAEL - - 00-07-46 (hex) TURCK, Inc. - 000746 (base 16) TURCK, Inc. - 3000 Campus Drive - Plymouth MN 55441 - UNITED STATES - - 00-07-47 (hex) Mecalc - 000747 (base 16) Mecalc - PO Box 7958 - Centurion 0046 - SOUTH AFRICA - - 00-07-48 (hex) The Imaging Source Europe - 000748 (base 16) The Imaging Source Europe - Sommerstraße 34-36 - 28215 Breman - GERMANY - - 00-07-49 (hex) CENiX Inc. - 000749 (base 16) CENiX Inc. - 5141 California Avenue - Irvine CA 92612 - UNITED STATES - - 00-07-4A (hex) Carl Valentin GmbH - 00074A (base 16) Carl Valentin GmbH - Neckarstrabe 78-80 - D-78056 VS-Schwenningen - GERMANY - - 00-07-4B (hex) Daihen Corporation - 00074B (base 16) Daihen Corporation - 2-1-11 Tagawa Yodogawa-ku - Osaka 532-8512 - JAPAN - - 00-07-4C (hex) Beicom Inc. - 00074C (base 16) Beicom Inc. - 114 King Street - Alexandria VA 22314 - UNITED STATES - - 00-07-4D (hex) Zebra Technologies Corp. - 00074D (base 16) Zebra Technologies Corp. - 333 Corporate Woods Parkway - Vernon Hills IL 60061 - UNITED STATES - - 00-07-4E (hex) IPFRONT Inc - 00074E (base 16) IPFRONT Inc - 4F ALT Bldg., - 2-8-13 Higashikanda, Chiyoda-ku, - Tokyo 101-0021 - JAPAN - - 00-07-4F (hex) CISCO SYSTEMS, INC. - 00074F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-50 (hex) CISCO SYSTEMS, INC. - 000750 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-51 (hex) m-u-t AG - 000751 (base 16) m-u-t AG - Messgeräte für Medizin- und Umwelttechnik - Am Marienhof 2 - Wedel 22880 - GERMANY - - 00-07-52 (hex) Rhythm Watch Co., Ltd. - 000752 (base 16) Rhythm Watch Co., Ltd. - 321 Shinshukushinden, Showa-Machi, - Kitakatshika-Gun, Saitama - 344-0196 - JAPAN - - 00-07-53 (hex) Beijing Qxcomm Technology Co., Ltd. - 000753 (base 16) Beijing Qxcomm Technology Co., Ltd. - 4F Tower B, TongTai Building No. 33, - Financial Street, Xicheng District, - Beijing 100032 - CHINA - - 00-07-54 (hex) Xyterra Computing, Inc. - 000754 (base 16) Xyterra Computing, Inc. - 14505 Hayden Rd., - Suite B340 - Scottsdale AZ 85260-6953 - UNITED STATES - - 00-07-55 (hex) Lafon - 000755 (base 16) Lafon - 44 Avenue Victor Meunier - Bassens 33530 - FRANCE - - 00-07-56 (hex) Juyoung Telecom - 000756 (base 16) Juyoung Telecom - #201, Dunsan Building - 218-1 Walpyeng-Dong, Seogu, - Taejon 302-846 - KOREA, REPUBLIC OF - - 00-07-57 (hex) Topcall International AG - 000757 (base 16) Topcall International AG - Talpagasse 1 - 1230 Vienna - AUSTRIA - - 00-07-58 (hex) Dragonwave - 000758 (base 16) Dragonwave - 600-411 Leggett Drive, - Suite 600 - Kanata, Ontario K2K 3C9 - CANADA - - 00-07-59 (hex) Boris Manufacturing Corp. - 000759 (base 16) Boris Manufacturing Corp. - PO Box 601 - Castle Point NY 12511 - UNITED STATES - - 00-07-5A (hex) Air Products and Chemicals, Inc. - 00075A (base 16) Air Products and Chemicals, Inc. - 7201 Hamilton Blvd. - Mail Stop C1307 - Allentown PA 18195-1501 - UNITED STATES - - 00-07-5B (hex) Gibson Guitars - 00075B (base 16) Gibson Guitars - 309 Park Plus Blvd. - Nashville TN 37217 - UNITED STATES - - 00-07-5C (hex) Eastman Kodak Company - 00075C (base 16) Eastman Kodak Company - 343 State Street - Rochester NY 146501245 - UNITED STATES - - 00-07-5D (hex) Celleritas Inc. - 00075D (base 16) Celleritas Inc. - c/o Celeritas Ltd. - Bezalel 29, Ramat-Gan - ISRAEL - - 00-07-5E (hex) Ametek Power Instruments - 00075E (base 16) Ametek Power Instruments - 4050 NW 121 Avenue - Coral Springs FL 33065 - UNITED STATES - - 00-07-5F (hex) VCS Video Communication Systems AG - 00075F (base 16) VCS Video Communication Systems AG - Forchheimer Str. 4 - 90425 Nürnberg - GERMANY - - 00-07-60 (hex) TOMIS Information & Telecom Corp. - 000760 (base 16) TOMIS Information & Telecom Corp. - Youngdeungpo telephone office - extensio - Youngdeungpodong 35-1, Youngdeungpo-gu - Seoul - KOREA, REPUBLIC OF - - 00-07-61 (hex) Logitech Europe SA - 000761 (base 16) Logitech Europe SA - EPFL - Quartier de l'Innovation - Daniel Borel Innovation Center - Lausanne CH 1015 - SWITZERLAND - - 00-07-62 (hex) Group Sense Limited - 000762 (base 16) Group Sense Limited - 27/F, Wu Chung House, - 213 Queen's Road East, - Wanchai - HONG KONG - - 00-07-63 (hex) Sunniwell Cyber Tech. Co., Ltd. - 000763 (base 16) Sunniwell Cyber Tech. Co., Ltd. - 17th Floor Haitai Building #229 - Beisihuan Hong Road, - Beijing 100083 - CHINA - - 00-07-64 (hex) YoungWoo Telecom Co. Ltd. - 000764 (base 16) YoungWoo Telecom Co. Ltd. - 3F, Sehwa B/D, 355-1 - Yatap-Dong, Bundag-ku - Sungnam-Si Kyungki-Do - KOREA, REPUBLIC OF - - 00-07-65 (hex) Jade Quantum Technologies, Inc. - 000765 (base 16) Jade Quantum Technologies, Inc. - 5F, No. 116, Hsien Fu Rd., - Taoyuan, - TAIWAN, PROVINCE OF CHINA - - 00-07-66 (hex) Chou Chin Industrial Co., Ltd. - 000766 (base 16) Chou Chin Industrial Co., Ltd. - 9F, #35, Chiau An St. Chung Ho City, - Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-07-67 (hex) Yuxing Electronics Company Limited - 000767 (base 16) Yuxing Electronics Company Limited - Unit 1808, 18/F Tower 3, - Enterprise Square, 9 Sheung Yuet Road - Kowloon Bay, Kowloon - HONG KONG - - 00-07-68 (hex) Danfoss A/S - 000768 (base 16) Danfoss A/S - E16-N12, DK-6430 Nordborg - DENMARK - - 00-07-69 (hex) Italiana Macchi SpA - 000769 (base 16) Italiana Macchi SpA - Via Matteotti 1 - 21040 Oggiona S. Stefano (VA) - ITALY - - 00-07-6A (hex) NEXTEYE Co., Ltd. - 00076A (base 16) NEXTEYE Co., Ltd. - Shinsegi Plaza 4F, 900-9, - Pyungchon, Dongan, Anyang, - Kyunggi 431-070 - KOREA, REPUBLIC OF - - 00-07-6B (hex) Stralfors AB - 00076B (base 16) Stralfors AB - Langgatan 21 - S-341 84 Ljungby - SWEDEN - - 00-07-6C (hex) Daehanet, Inc. - 00076C (base 16) Daehanet, Inc. - #8-2 Chung Jung Rd 2- Ga - Sur Dae Moon, - Seoul 120-012 - KOREA, REPUBLIC OF - - 00-07-6D (hex) Flexlight Networks - 00076D (base 16) Flexlight Networks - 15 Atir Yeda St. - Kfar Saba 44643 - ISRAEL - - 00-07-6E (hex) Sinetica Corporation Limited - 00076E (base 16) Sinetica Corporation Limited - Willow House - Llancayo Court - Monmouthshire Usk NP15 1HY - UNITED KINGDOM - - 00-07-6F (hex) Synoptics Limited - 00076F (base 16) Synoptics Limited - Beacon House, Nuffield Road, - Cambridge CB4 1TF - UNITED KINGDOM - - 00-07-70 (hex) Ubiquoss Inc - 000770 (base 16) Ubiquoss Inc - Ubiquoss B/D, 68, Pangyo-ro 255beon-gil, - Bundang-gu, Seongnam-si, Gyeonggi-do, 464-400 - KOREA, REPUBLIC OF - - 00-07-71 (hex) Embedded System Corporation - 000771 (base 16) Embedded System Corporation - 13-5, Takadanobaba 3-chome, - Shinjuku-ku, Tokyo 169-0075 - JAPAN - - 00-07-72 (hex) Alcatel Shanghai Bell Co., Ltd. - 000772 (base 16) Alcatel Shanghai Bell Co., Ltd. - No. 388, Ningqiao Road, - Pudong Jinqiao, Shanghai - 201206 - CHINA - - 00-07-73 (hex) Ascom Powerline Communications Ltd. - 000773 (base 16) Ascom Powerline Communications Ltd. - Belpstr. 37 - 3000 Bern 14 - SWITZERLAND - - 00-07-74 (hex) GuangZhou Thinker Technology Co. Ltd. - 000774 (base 16) GuangZhou Thinker Technology Co. Ltd. - 109 Zhongshan Ave., Tianhe District - Guangzhou - 510630 - CHINA - - 00-07-75 (hex) Valence Semiconductor, Inc. - 000775 (base 16) Valence Semiconductor, Inc. - 41 Discovery - Irvine CA 92618 - UNITED STATES - - 00-07-76 (hex) Federal APD - 000776 (base 16) Federal APD - 42775 Nine Mile Rd. - Novi MI 48375 - UNITED STATES - - 00-07-77 (hex) Motah Ltd. - 000777 (base 16) Motah Ltd. - 4-4-5 Koishikawa - Bunkyo, Tokyo - 112-0002 - JAPAN - - 00-07-78 (hex) GERSTEL GmbH & Co. KG - 000778 (base 16) GERSTEL GmbH & Co. KG - Eberhard-Gerstel-Platz 1 - D45473 - Mülheim an der Ruhr - GERMANY - - 00-07-79 (hex) Sungil Telecom Co., Ltd. - 000779 (base 16) Sungil Telecom Co., Ltd. - #321, Gongdan-Dong, - Gumi-City, Kyoung-Buk - 730-030 - KOREA, REPUBLIC OF - - 00-07-7A (hex) Infoware System Co., Ltd. - 00077A (base 16) Infoware System Co., Ltd. - Mizorogi Daiichi Bldg 4 F - 1-5-13 Shinjuku, Shinjuku-ku - Tokyo - JAPAN - - 00-07-7B (hex) Millimetrix Broadband Networks - 00077B (base 16) Millimetrix Broadband Networks - Kibutz Givat Hashelosha 48800 - ISRAEL - - 00-07-7C (hex) Westermo Teleindustri AB - 00077C (base 16) Westermo Teleindustri AB - SE-640 40 - Stora Sundby - SWEDEN - - 00-07-7D (hex) CISCO SYSTEMS, INC. - 00077D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-7E (hex) Elrest GmbH - 00077E (base 16) Elrest GmbH - Leibnizstraße 10 - D-73230 Kirchheim - GERMANY - - 00-07-7F (hex) J Communications Co., Ltd. - 00077F (base 16) J Communications Co., Ltd. - 124-4 Ojeon-Dong, Ulwang-City - Kyungki-Do - KOREA, REPUBLIC OF - - 00-07-80 (hex) Bluegiga Technologies OY - 000780 (base 16) Bluegiga Technologies OY - P.O. BOX 120 - FIN-02631 Espoo - FINLAND - - 00-07-81 (hex) Itron Inc. - 000781 (base 16) Itron Inc. - 2818 N. Sullivan Road - Spokane WA 99216 - UNITED STATES - - 00-07-82 (hex) Oracle Corporation - 000782 (base 16) Oracle Corporation - 17 Network Circle - Building 17, UMPK17-131 - Menlo Park CA 95025 - UNITED STATES - - 00-07-83 (hex) SynCom Network, Inc. - 000783 (base 16) SynCom Network, Inc. - 4F, No. 31, Hsintai Road, Chupei City, - Hsinchu Hsien, - TAIWAN, PROVINCE OF CHINA - - 00-07-84 (hex) CISCO SYSTEMS, INC. - 000784 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-85 (hex) CISCO SYSTEMS, INC. - 000785 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-86 (hex) Wireless Networks Inc. - 000786 (base 16) Wireless Networks Inc. - #300, 3016 Fifth Ave. NE - Calgary, Alberta - T2A 6K4 - CANADA - - 00-07-87 (hex) Idea System Co., Ltd. - 000787 (base 16) Idea System Co., Ltd. - 4-1-21 Shinmei-cho Okaya-shi - Nagano-ken 394-0004 - JAPAN - - 00-07-88 (hex) Clipcomm, Inc. - 000788 (base 16) Clipcomm, Inc. - 5th Fl, Ssangyang Bldg. - 935-1 Bongcheon-dong, Kwamak-gu, - Seoul 151-827 - KOREA, REPUBLIC OF - - 00-07-89 (hex) DONGWON SYSTEMS - 000789 (base 16) DONGWON SYSTEMS - 861-5, Gwanyang-Dong, Dongan-Gu, - Anyang-si, Gyeonggi-do, 430-803 - KOREA, REPUBLIC OF - - 00-07-8A (hex) Mentor Data System Inc. - 00078A (base 16) Mentor Data System Inc. - No. 24-1, Industry East 4 Rd., - Science Based Industrial Park, - Hsin-Chu, - TAIWAN, PROVINCE OF CHINA - - 00-07-8B (hex) Wegener Communications, Inc. - 00078B (base 16) Wegener Communications, Inc. - 11350 Technology Circle - Duluth GA 30097 - UNITED STATES - - 00-07-8C (hex) Elektronikspecialisten i Borlange AB - 00078C (base 16) Elektronikspecialisten i Borlange AB - Box 50 - 40 MOCKFJÄRD - SE 780 - SWEDEN - - 00-07-8D (hex) NetEngines Ltd. - 00078D (base 16) NetEngines Ltd. - 146 Walnut Tree Close - Guildford, Surrey - GUI 4UB - UNITED KINGDOM - - 00-07-8E (hex) Garz & Friche GmbH - 00078E (base 16) Garz & Friche GmbH - Tempowerhving 4 - D-21079 Hamburg - GERMANY - - 00-07-8F (hex) Emkay Innovative Products - 00078F (base 16) Emkay Innovative Products - 53, Pao Hsing Rd., Hsintien City - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-07-90 (hex) Tri-M Technologies (s) Limited - 000790 (base 16) Tri-M Technologies (s) Limited - Blk 25, Kallang Avenue #07-01/04 - Kallang Basin Ind. Est - 339416 - SINGAPORE - - 00-07-91 (hex) International Data Communications, Inc. - 000791 (base 16) International Data Communications, Inc. - 47873 Fremont Blvd. - Fremont CA 04538 - UNITED STATES - - 00-07-92 (hex) Sütron Electronic GmbH - 000792 (base 16) Sütron Electronic GmbH - Kurze Straße 29 - 70794 Filderstadt - GERMANY - - 00-07-93 (hex) Shin Satellite Public Company Limited - 000793 (base 16) Shin Satellite Public Company Limited - 41/103 Rattanathibet Road, - Nonthaburi 11000, - THAILAND - - 00-07-94 (hex) Simple Devices, Inc. - 000794 (base 16) Simple Devices, Inc. - 111 Anza Blvd., Suite 120 - Burlingame CA 94010 - UNITED STATES - - 00-07-95 (hex) Elitegroup Computer System Co. (ECS) - 000795 (base 16) Elitegroup Computer System Co. (ECS) - No. 22, Alley 38, Lane 91, - Sec. 1, Nei Hu Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-07-96 (hex) LSI Systems, Inc. - 000796 (base 16) LSI Systems, Inc. - 10-1 Minami-kurokawa, - Asao-ku, kawasaki, - Kanagawa 215-0034 - JAPAN - - 00-07-97 (hex) Netpower Co., Ltd. - 000797 (base 16) Netpower Co., Ltd. - Baekam Bldg., 6F - 123, Karak-Dong, Song-pa Gu - Seoul 138-162 - KOREA, REPUBLIC OF - - 00-07-98 (hex) Selea SRL - 000798 (base 16) Selea SRL - Via A. Moro No. 69 - 46015 - Cicognara - ITALY - - 00-07-99 (hex) Tipping Point Technologies, Inc. - 000799 (base 16) Tipping Point Technologies, Inc. - 7501 B N. Capital of TX Hwy. - Austin TX 78731 - UNITED STATES - - 00-07-9A (hex) Verint Systems Inc - 00079A (base 16) Verint Systems Inc - 1800 Berlier, Suite 440 - Laval, Quebec H7L 4S4 - CANADA - - 00-07-9B (hex) Aurora Networks - 00079B (base 16) Aurora Networks - 2803 Mission College Blvd. - Santa Clara CA 95054 - UNITED STATES - - 00-07-9C (hex) Golden Electronics Technology Co., Ltd. - 00079C (base 16) Golden Electronics Technology Co., Ltd. - No. 29, 21st Road, - Taichung Industrial Park, Taichung - TAIWAN, PROVINCE OF CHINA - - 00-07-9D (hex) Musashi Co., Ltd. - 00079D (base 16) Musashi Co., Ltd. - 3-21-1, Shimo-ochiai, - Shinjuku-ku, - Tokyo 161-0033 - JAPAN - - 00-07-9E (hex) Ilinx Co., Ltd. - 00079E (base 16) Ilinx Co., Ltd. - 4th Floor Korea Telecom, Yangjae Branch - Dogok-Dong, Kangnam-ku, - Seoul - KOREA, REPUBLIC OF - - 00-07-9F (hex) Action Digital Inc. - 00079F (base 16) Action Digital Inc. - 10650 Main St. - Suite 102 - Fairfax VA 22030 - UNITED STATES - - 00-07-A0 (hex) e-Watch Inc. - 0007A0 (base 16) e-Watch Inc. - 7800 IH 10 West - Suite 700 - San Antonio TX 78229 - UNITED STATES - - 00-07-A1 (hex) VIASYS Healthcare GmbH - 0007A1 (base 16) VIASYS Healthcare GmbH - Leibnizstraße 7 - Hoechberg Bavaria 97204 - GERMANY - - 00-07-A2 (hex) Opteon Corporation - 0007A2 (base 16) Opteon Corporation - 70 Hastings Street - Wellesley MA 02481 - UNITED STATES - - 00-07-A3 (hex) Ositis Software, Inc. - 0007A3 (base 16) Ositis Software, Inc. - 6120 Stoneridge Mall Road - Suite 210 - Pleasanton CA 94588 - UNITED STATES - - 00-07-A4 (hex) GN Netcom Ltd. - 0007A4 (base 16) GN Netcom Ltd. - 12-13 Sedling Road, Wear Est., District - Washington, Tyne and Wear - England NE38 9BZ - UNITED KINGDOM - - 00-07-A5 (hex) Y.D.K Co. Ltd. - 0007A5 (base 16) Y.D.K Co. Ltd. - 1705, Oshitate, Inagi-City, - Tokyo, - JAPAN - - 00-07-A6 (hex) Home Automation, Inc. - 0007A6 (base 16) Home Automation, Inc. - 4330 Michoud Blvd. - New Orleans LA 70129 - UNITED STATES - - 00-07-A7 (hex) A-Z Inc. - 0007A7 (base 16) A-Z Inc. - 5-5-17 Kamikoushien - Nishinomiya City, Hyogo - JAPAN - - 00-07-A8 (hex) Haier Group Technologies Ltd. - 0007A8 (base 16) Haier Group Technologies Ltd. - No. 1 Haier Road, Hi-tech Zone - Qingdao, - CHINA - - 00-07-A9 (hex) Novasonics - 0007A9 (base 16) Novasonics - 1390 Willow Road - Menlo Park CA 94025 - UNITED STATES - - 00-07-AA (hex) Quantum Data Inc. - 0007AA (base 16) Quantum Data Inc. - 2111 Big Timber Rd. - Elgin IL 60123-1100 - UNITED STATES - - 00-07-AB (hex) Samsung Electronics Co.,Ltd - 0007AB (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-07-AC (hex) Eolring - 0007AC (base 16) Eolring - 10 Rue Alfred Kastler - 14000 Caen - FRANCE - - 00-07-AD (hex) Pentacon GmbH Foto-und Feinwerktechnik - 0007AD (base 16) Pentacon GmbH Foto-und Feinwerktechnik - Enderstrabe 94 - 01277 Dresden - GERMANY - - 00-07-AE (hex) Britestream Networks, Inc. - 0007AE (base 16) Britestream Networks, Inc. - 12401 Research Blvd. - Building Two, Suite 275 - Austin TX 78759 - UNITED STATES - - 00-07-AF (hex) Red Lion Controls, LP - 0007AF (base 16) Red Lion Controls, LP - 20 Willow Springs Circle - York PA 17402 - UNITED STATES - - 00-07-B0 (hex) Office Details, Inc. - 0007B0 (base 16) Office Details, Inc. - 25 Ottawa - 4th Floor - Grand Rapids MI 49503 - UNITED STATES - - 00-07-B1 (hex) Equator Technologies - 0007B1 (base 16) Equator Technologies - 1300 White Oaks Rd. - Campbell CA 95008 - UNITED STATES - - 00-07-B2 (hex) Transaccess S.A. - 0007B2 (base 16) Transaccess S.A. - R. Galeno De Castro, 1445 - Turubatuba 04696-040 - São Paulo SP - BRAZIL - - 00-07-B3 (hex) CISCO SYSTEMS, INC. - 0007B3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-B4 (hex) CISCO SYSTEMS, INC. - 0007B4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-B5 (hex) Any One Wireless Ltd. - 0007B5 (base 16) Any One Wireless Ltd. - Namseoul Bd., 8F, 1304-3 - Seocho 4-Dong, Seocho-Gu - Seoul - KOREA, REPUBLIC OF - - 00-07-B6 (hex) Telecom Technology Ltd. - 0007B6 (base 16) Telecom Technology Ltd. - Docklands Innovation Park - 128-130 East Wall Road - Dublin 3 - IRELAND - - 00-07-B7 (hex) Samurai Ind. Prods Eletronicos Ltda - 0007B7 (base 16) Samurai Ind. Prods Eletronicos Ltda - R-Nebraska, 443 S/2 2o Andar - Brooklin Novo - São Paulo - 04560-011 - BRAZIL - - 00-07-B8 (hex) Corvalent Corporation - 0007B8 (base 16) Corvalent Corporation - 1101 Arrow Point Dr #501 - Cedar Park TX 78613 - UNITED STATES - - 00-07-B9 (hex) Ginganet Corporation - 0007B9 (base 16) Ginganet Corporation - Kintetsu Shin Namba Building - Minato Machi 1-4-38 Naniwaku - Osaka Shi 1556-0017 - JAPAN - - 00-07-BA (hex) UTStarcom, Inc. - 0007BA (base 16) UTStarcom, Inc. - 1275 Barbor Bay PKWY - Alameda CA 94502 - UNITED STATES - - 00-07-BB (hex) Candera Inc. - 0007BB (base 16) Candera Inc. - 673 South Milpitas Blvd. - Milpitas CA 95035 - UNITED STATES - - 00-07-BC (hex) Identix Inc. - 0007BC (base 16) Identix Inc. - 6591 Sierra Lane - Dublin CA 94568 - UNITED STATES - - 00-07-BD (hex) Radionet Ltd. - 0007BD (base 16) Radionet Ltd. - Keilaranta 6 - 02150 ESP00 - FINLAND - - 00-07-BE (hex) DataLogic SpA - 0007BE (base 16) DataLogic SpA - Via Candini, 2 - 40012 Lippo di Calderara di Reno - Bologna - ITALY - - 00-07-BF (hex) Armillaire Technologies, Inc. - 0007BF (base 16) Armillaire Technologies, Inc. - 10411 Motor City Drive - Bethesda MD 20817 - UNITED STATES - - 00-07-C0 (hex) NetZerver Inc. - 0007C0 (base 16) NetZerver Inc. - 26 West Lone Cactus Drive - Phoenix AZ 85027 - UNITED STATES - - 00-07-C1 (hex) Overture Networks, Inc. - 0007C1 (base 16) Overture Networks, Inc. - 637 Davis Drive - Morrisville NC 227560 - UNITED STATES - - 00-07-C2 (hex) Netsys Telecom - 0007C2 (base 16) Netsys Telecom - 4F, KyungNam B/D, 830-48, YeokSam-Dong - Kangnam-Gu, - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-07-C3 (hex) Thomson - 0007C3 (base 16) Thomson - 5-7, rue Salomon de Rothschild - Suresnes - 92150 - FRANCE - - 00-07-C4 (hex) JEAN Co. Ltd. - 0007C4 (base 16) JEAN Co. Ltd. - 7F, 2, Rei Kuang Road, - Nei Hu, - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-07-C5 (hex) Gcom, Inc. - 0007C5 (base 16) Gcom, Inc. - 1800 Woodfield Dr. - Savoy IL 61874 - UNITED STATES - - 00-07-C6 (hex) VDS Vosskuhler GmbH - 0007C6 (base 16) VDS Vosskuhler GmbH - Weibe Breite 7 - D-49084 Osnabruck - GERMANY - - 00-07-C7 (hex) Synectics Systems Limited - 0007C7 (base 16) Synectics Systems Limited - 3 Acorn Business Park - Wooseats Close, Sheffield - S8 OTB - UNITED KINGDOM - - 00-07-C8 (hex) Brain21, Inc. - 0007C8 (base 16) Brain21, Inc. - 19F Mesa B/D, 204 Hoihyun-Dong - Joong-Gu - Seoul 100-051 - KOREA, REPUBLIC OF - - 00-07-C9 (hex) Technol Seven Co., Ltd. - 0007C9 (base 16) Technol Seven Co., Ltd. - 25-16 Tobehon-cho, Nisi-ku, - Yokohama, 220-0041 - JAPAN - - 00-07-CA (hex) Creatix Polymedia Ges Fur Kommunikaitonssysteme - 0007CA (base 16) Creatix Polymedia Ges Fur Kommunikaitonssysteme - Heinrich-Barth-Straße 3 - 66115 Saarbrücken - GERMANY - - 00-07-CB (hex) Freebox SA - 0007CB (base 16) Freebox SA - 8 rue de la Ville l'Eveque - Paris 75008 - FRANCE - - 00-07-CC (hex) Kaba Benzing GmbH - 0007CC (base 16) Kaba Benzing GmbH - Albertistrabe 3 - 78056 Villigen-Schwenningen - GERMANY - - 00-07-CD (hex) Kumoh Electronic Co, Ltd - 0007CD (base 16) Kumoh Electronic Co, Ltd - 154-2 Chunui-dong - Bucheon - Gyeonggi-do - KOREA, REPUBLIC OF - - 00-07-CE (hex) Cabletime Limited - 0007CE (base 16) Cabletime Limited - 64 Greenham Road - Newbury Berkshire RG14 7HX - UNITED KINGDOM - - 00-07-CF (hex) Anoto AB - 0007CF (base 16) Anoto AB - Solvegatan 41 - SE-223 70 Lund - SWEDEN - - 00-07-D0 (hex) Automat Engenharia de Automação Ltda. - 0007D0 (base 16) Automat Engenharia de Automação Ltda. - Rua Santo Antonio, 917 - Reboucas - Curitiba - PR - 80230-120 - BRAZIL - - 00-07-D1 (hex) Spectrum Signal Processing Inc. - 0007D1 (base 16) Spectrum Signal Processing Inc. - #200-2700 Production Way - Burnaby, BC V5A 4X1 - CANADA - - 00-07-D2 (hex) Logopak Systeme GmbH & Co. KG - 0007D2 (base 16) Logopak Systeme GmbH & Co. KG - Dorfstraße 40 - D-24628 Hartenholm - GERMANY - - 00-07-D3 (hex) SPGPrints B.V. - 0007D3 (base 16) SPGPrints B.V. - Raamstraat 1-3, 5831 AT Boxmeer - P. O. Box 67, 5830 AB - Boxmeer - NETHERLANDS - - 00-07-D4 (hex) Zhejiang Yutong Network Communication Co Ltd. - 0007D4 (base 16) Zhejiang Yutong Network Communication Co Ltd. - 805 HuaXing Technical Building - 477# WenSan Road, HangZhou - Zhejiang - CHINA - - 00-07-D5 (hex) 3e Technologies Int;., Inc. - 0007D5 (base 16) 3e Technologies Int;., Inc. - 15800 Crabbs Branch Way - Suite 290 - Rockville MD 20855 - UNITED STATES - - 00-07-D6 (hex) Commil Ltd. - 0007D6 (base 16) Commil Ltd. - P.O. Box 10050 - Petah Tikva 49001 - ISRAEL - - 00-07-D7 (hex) Caporis Networks AG - 0007D7 (base 16) Caporis Networks AG - Süggelstraße 31 - D-44532 Lünen - GERMANY - - 00-07-D8 (hex) Hitron Systems Inc. - 0007D8 (base 16) Hitron Systems Inc. - 135-220 Hitron B/D 726-5 - Suso-Dong, Kangnam Gu - Seoul - KOREA, REPUBLIC OF - - 00-07-D9 (hex) Splicecom - 0007D9 (base 16) Splicecom - Little Gillions, The Green - Croxley Green, Rickmansworth - Herts WD3 3HY - UNITED KINGDOM - - 00-07-DA (hex) Neuro Telecom Co., Ltd. - 0007DA (base 16) Neuro Telecom Co., Ltd. - 2F Misung B/D, 938-7 - Hoge-dong, Dongan-gu - Kyunggi-do - KOREA, REPUBLIC OF - - 00-07-DB (hex) Kirana Networks, Inc. - 0007DB (base 16) Kirana Networks, Inc. - 331 Newman Springs Road - Bldg. 1 4th Floor - Red Bank NJ 07701 - UNITED STATES - - 00-07-DC (hex) Atek Co, Ltd. - 0007DC (base 16) Atek Co, Ltd. - B dong #205 hanyang venture park - 685-20 songsu1gadong song donggu, - Seoul - KOREA, REPUBLIC OF - - 00-07-DD (hex) Cradle Technologies - 0007DD (base 16) Cradle Technologies - 3130 West Warren Ave. - Fremont CA 94538 - UNITED STATES - - 00-07-DE (hex) eCopilt AB - 0007DE (base 16) eCopilt AB - Veddestavagen 24 - SE-175 62 Jarfalla - SWEDEN - - 00-07-DF (hex) Vbrick Systems Inc. - 0007DF (base 16) Vbrick Systems Inc. - 12 Beaumont Road - Wallingford CT 06492 - UNITED STATES - - 00-07-E0 (hex) Palm Inc. - 0007E0 (base 16) Palm Inc. - 950 West Maude Ave - Sunnyvale CA 94085-2801 - UNITED STATES - - 00-07-E1 (hex) WIS Communications Co. Ltd. - 0007E1 (base 16) WIS Communications Co. Ltd. - 4/F Building 533 - Bugua Sixth Road - Shenzhen Guangdong Providence - CHINA - - 00-07-E2 (hex) Bitworks, Inc. - 0007E2 (base 16) Bitworks, Inc. - #1 Bitworks Way - Prairie Grove AR 72753 - UNITED STATES - - 00-07-E3 (hex) Navcom Technology, Inc. - 0007E3 (base 16) Navcom Technology, Inc. - 123 West Torrance Blvd., - Suite 101 - Redondo Beach CA 90277 - UNITED STATES - - 00-07-E4 (hex) SoftRadio Co., Ltd. - 0007E4 (base 16) SoftRadio Co., Ltd. - 2F, Dong-Bok B/D 645-18 - Yeoksam-Dong, Kangnam-Gu - Seoul - KOREA, REPUBLIC OF - - 00-07-E5 (hex) Coup Corporation - 0007E5 (base 16) Coup Corporation - 1-24-4 Marusen 2nd Bld. 4F, - Higashi-Ueno, Taito-ku - Tokyo - JAPAN - - 00-07-E6 (hex) edgeflow Canada Inc. - 0007E6 (base 16) edgeflow Canada Inc. - 329 March Road - Kanata, Ontario - K2K 2E1 - CANADA - - 00-07-E7 (hex) FreeWave Technologies - 0007E7 (base 16) FreeWave Technologies - 1880 S. Flaitron Ct. - Ste. F - Boulder CO 80301 - UNITED STATES - - 00-07-E8 (hex) EdgeWave - 0007E8 (base 16) EdgeWave - 15333 Avenue of Science - San Diego CA 92128 - UNITED STATES - - 00-07-E9 (hex) Intel Corporation - 0007E9 (base 16) Intel Corporation - MS: JF3-420 - 2111 NE 25th Ave. - Hillsboro OR 97124 - UNITED STATES - - 00-07-EA (hex) Massana, Inc. - 0007EA (base 16) Massana, Inc. - 2901 Tasman Drive - Suite 106 - Santa Clara CA 95054 - UNITED STATES - - 00-07-EB (hex) CISCO SYSTEMS, INC. - 0007EB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-EC (hex) CISCO SYSTEMS, INC. - 0007EC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-07-ED (hex) Altera Corporation - 0007ED (base 16) Altera Corporation - 101 Innovation Drive - MS 2305 - San Jose CA 95134 - UNITED STATES - - 00-07-EE (hex) telco Informationssysteme GmbH - 0007EE (base 16) telco Informationssysteme GmbH - Schulstrasse 38 - D 0912 Chemnitz - GERMANY - - 00-07-EF (hex) Lockheed Martin Tactical Systems - 0007EF (base 16) Lockheed Martin Tactical Systems - 3333 Pilot Knob Road - Eagan MN 55121 - UNITED STATES - - 00-07-F0 (hex) LogiSync LLC - 0007F0 (base 16) LogiSync LLC - 1313 Lear Industrial Parkway - Avon OH 44011 - UNITED STATES - - 00-07-F1 (hex) TeraBurst Networks Inc. - 0007F1 (base 16) TeraBurst Networks Inc. - 985 Stewart Drive - Sunnyvale CA 94086 - UNITED STATES - - 00-07-F2 (hex) IOA Corporation - 0007F2 (base 16) IOA Corporation - 350 Potrero Ave. - Sunnyvale CA 94085 - UNITED STATES - - 00-07-F3 (hex) Thinkengine Networks - 0007F3 (base 16) Thinkengine Networks - 100 Nickerson Road - Marlborough MA 01752 - UNITED STATES - - 00-07-F4 (hex) Eletex Co., Ltd. - 0007F4 (base 16) Eletex Co., Ltd. - 8-2-56 Nankou-Higashi Suminoe-ku - Osaka 559-0031 - JAPAN - - 00-07-F5 (hex) Bridgeco Co AG - 0007F5 (base 16) Bridgeco Co AG - Ringstr. 14 - CH 8600 Duebendorf - SWITZERLAND - - 00-07-F6 (hex) Qqest Software Systems - 0007F6 (base 16) Qqest Software Systems - 860 East 4500 South #200 - Murray UT 84107 - UNITED STATES - - 00-07-F7 (hex) Galtronics - 0007F7 (base 16) Galtronics - 4645 East Cotton Center Blvd. - Bldg. Two - Phoenix AZ 85040 - UNITED STATES - - 00-07-F8 (hex) ITDevices, Inc. - 0007F8 (base 16) ITDevices, Inc. - 606 110th Ave. NE - Bellevue WA 98004 - UNITED STATES - - 00-07-F9 (hex) Sensaphone - 0007F9 (base 16) Sensaphone - 901 Tryens Road - Aston PA 19014 - UNITED STATES - - 00-07-FA (hex) ITT Co., Ltd. - 0007FA (base 16) ITT Co., Ltd. - 1-14-7, Mukohjyuku, - Hamamatsu, Shizuoka 430 - JAPAN - - 00-07-FB (hex) Giga Stream UMTS Technologies GmbH - 0007FB (base 16) Giga Stream UMTS Technologies GmbH - Konrad-Zuse-Strabe 7 - D-66115 Saarbrucken - GERMANY - - 00-07-FC (hex) Adept Systems Inc. - 0007FC (base 16) Adept Systems Inc. - 242 East 600 North - Lindon UT 84057 - UNITED STATES - - 00-07-FD (hex) LANergy Ltd. - 0007FD (base 16) LANergy Ltd. - Imperial House, Imperial Way - Newport, Gwent NP10 8UH - UNITED KINGDOM - - 00-07-FE (hex) Rigaku Corporation - 0007FE (base 16) Rigaku Corporation - 3-9-12, Matsubara-cho - Akishima-shi - Tokyo 196-8666 - JAPAN - - 00-07-FF (hex) Gluon Networks - 0007FF (base 16) Gluon Networks - 5401 Old Redwood Hwy. - Petaluma CA 94954 - UNITED STATES - - 00-08-00 (hex) MULTITECH SYSTEMS, INC. - 000800 (base 16) MULTITECH SYSTEMS, INC. - 2205 WOODALE DRIVE - MOUNDS VIEW MN 55112 - UNITED STATES - - 00-08-01 (hex) HighSpeed Surfing Inc. - 000801 (base 16) HighSpeed Surfing Inc. - 44790 S. Grimmer Blvd. - Suite 100 - Fremont CA 94538 - UNITED STATES - - 00-08-02 (hex) Hewlett-Packard Company - 000802 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-08-03 (hex) Cos Tron - 000803 (base 16) Cos Tron - 3F Boolim B/D, 1431-22, - Kwanyang-Dong, Dongon-Gu, - Anyang 431-061 - KOREA, REPUBLIC OF - - 00-08-04 (hex) ICA Inc. - 000804 (base 16) ICA Inc. - 542-1 Noguki - Kuki-shi, Saitamn - JAPAN - - 00-08-05 (hex) Techno-Holon Corporation - 000805 (base 16) Techno-Holon Corporation - 3-19-2, Takamatsu-cho - Tachikawa-shi - Tokyo 190-0011 - JAPAN - - 00-08-06 (hex) Raonet Systems, Inc. - 000806 (base 16) Raonet Systems, Inc. - West Wing 14F, IT Venture Tower 78 - Garakbon-dong, Songpa, - Seoul 138-803 - KOREA, REPUBLIC OF - - 00-08-07 (hex) Access Devices Limited - 000807 (base 16) Access Devices Limited - Sixth Floor, 58 Oxbridge Road - Ealing, London W5 2ST - UNITED KINGDOM - - 00-08-08 (hex) PPT Vision, Inc. - 000808 (base 16) PPT Vision, Inc. - 12988 Valley View Rd. - Eden Prairie MN 55344 - UNITED STATES - - 00-08-09 (hex) Systemonic AG - 000809 (base 16) Systemonic AG - Am Waldschloesschen 1 - D-01099 Dresden - GERMANY - - 00-08-0A (hex) Espera-Werke GmbH - 00080A (base 16) Espera-Werke GmbH - Moltkestrasse 17- 33 - 47058 Duisburg - GERMANY - - 00-08-0B (hex) Birka BPA Informationssystem AB - 00080B (base 16) Birka BPA Informationssystem AB - Box 20100 - 161 02 Bromma - SWEDEN - - 00-08-0C (hex) VDA Elettronica spa - 00080C (base 16) VDA Elettronica spa - Viale Lino Zanussi, 3 - 33170 Pordenone - ITALY - - 00-08-0D (hex) Toshiba - 00080D (base 16) Toshiba - 2-9, Suehiro-cho, - Ome-city, - Tokyo 198-8710 - JAPAN - - 00-08-0E (hex) ARRIS Group, Inc. - 00080E (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-08-0F (hex) Proximion Fiber Optics AB - 00080F (base 16) Proximion Fiber Optics AB - Isafjordsgatan 9 - SE-16440 Kista - SWEDEN - - 00-08-10 (hex) Key Technology, Inc. - 000810 (base 16) Key Technology, Inc. - 150 Avery St. - Walla Walla WA 99362 - UNITED STATES - - 00-08-11 (hex) VOIX Corporation - 000811 (base 16) VOIX Corporation - 1991-3 4th Floor Top's Venture Tower - Seo Cho-Dong, Seo cho-gu - Seoul 138-090 - KOREA, REPUBLIC OF - - 00-08-12 (hex) GM-2 Corporation - 000812 (base 16) GM-2 Corporation - Shiba-Matushira-Bldg. - 6F 3-3-12,Shiba - Tokyo Minato-ku 105-0014 - JAPAN - - 00-08-13 (hex) Diskbank, Inc. - 000813 (base 16) Diskbank, Inc. - 3F Focus Building, 725-25 - Yeoksam-dong, Kangnam-gu - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-08-14 (hex) TIL Technologies - 000814 (base 16) TIL Technologies - Europark DePichaury, BAT 9 - 13856 AIX en Providence - FRANCE - - 00-08-15 (hex) CATS Co., Ltd. - 000815 (base 16) CATS Co., Ltd. - 751-2 Kachida-cho, - Tsuzuki-ku, Yokohama - 224-0034 - JAPAN - - 00-08-16 (hex) Bluelon ApS - 000816 (base 16) Bluelon ApS - Nattergalevej 6 - 2400 Copenhagen NV - DENMARK - - 00-08-17 (hex) EmergeCore Networks LLC - 000817 (base 16) EmergeCore Networks LLC - 10542 S. Jordan Gateway - Suite 150 - South Jordan UT 84095 - UNITED STATES - - 00-08-18 (hex) Pixelworks, Inc. - 000818 (base 16) Pixelworks, Inc. - 7700 SW Mohawk Street - Tualatin OR 97062 - UNITED STATES - - 00-08-19 (hex) Banksys - 000819 (base 16) Banksys - Haachtsesteenweg 1442 - 1130 Brussel - BELGIUM - - 00-08-1A (hex) Sanrad Intelligence Storage Communications (2000) Ltd. - 00081A (base 16) Sanrad Intelligence Storage Communications (2000) Ltd. - 32 Habarzel St., Entrace B - Tel-Aviv 69710 - ISRAEL - - 00-08-1B (hex) Windigo Systems - 00081B (base 16) Windigo Systems - 2210 O'Toole Ave. #200 - San Jose CA 95131 - UNITED STATES - - 00-08-1C (hex) @pos.com - 00081C (base 16) @pos.com - 3051 North First Street - San Jose CA 95134 - UNITED STATES - - 00-08-1D (hex) Ipsil, Incorporated - 00081D (base 16) Ipsil, Incorporated - 7945 MacArthur Blvd. - Suite 212 - Cabin John MD 20818 - UNITED STATES - - 00-08-1E (hex) Repeatit AB - 00081E (base 16) Repeatit AB - Farogatan 7 - SE16440 Kista - SWEDEN - - 00-08-1F (hex) Pou Yuen Tech Corp. Ltd. - 00081F (base 16) Pou Yuen Tech Corp. Ltd. - 16F, No. 107, Sect. 3, Taichung Keng Rd. - Taichung City 407, - TAIWAN, PROVINCE OF CHINA - - 00-08-20 (hex) CISCO SYSTEMS, INC. - 000820 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-21 (hex) CISCO SYSTEMS, INC. - 000821 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-22 (hex) InPro Comm - 000822 (base 16) InPro Comm - 11F, No. 93 Shuei-Yuan Street - Hsinchu, 300 - TAIWAN, PROVINCE OF CHINA - - 00-08-23 (hex) Texa Corp. - 000823 (base 16) Texa Corp. - Nara Bldg. 3F, 2-2-8 Shin-Yokohama, - Kohoku-ku, Yokohama - 222-0033 - JAPAN - - 00-08-24 (hex) Nuance Document Imaging - 000824 (base 16) Nuance Document Imaging - 8390 Mayrand Street - Montreal Quebec H4P 2C9 - CANADA - - 00-08-25 (hex) Acme Packet - 000825 (base 16) Acme Packet - 71 Third Avenue - Burllington - Woburn MA 01803 - UNITED STATES - - 00-08-26 (hex) Colorado Med Tech - 000826 (base 16) Colorado Med Tech - 6175 Longbow Dr. - Boulder CO 80301 - UNITED STATES - - 00-08-27 (hex) ADB Broadband Italia - 000827 (base 16) ADB Broadband Italia - Viale Sarca 222 - Milano 20126 - ITALY - - 00-08-28 (hex) Koei Engineering Ltd. - 000828 (base 16) Koei Engineering Ltd. - 3-40, 5-Chome - Kire-nishi Hirano-ku - Osaku 547-0026 - JAPAN - - 00-08-29 (hex) Aval Nagasaki Corporation - 000829 (base 16) Aval Nagasaki Corporation - 6-42 Tukuba Isahaya - Nagasaki - 854-0065 - JAPAN - - 00-08-2A (hex) Powerwallz Network Security - 00082A (base 16) Powerwallz Network Security - 120-13160 Vanier Place, - Richmond, BC, - V6V 2J2 - CANADA - - 00-08-2B (hex) Wooksung Electronics, Inc. - 00082B (base 16) Wooksung Electronics, Inc. - Jaho-Bldg. 6F, Tanbang-Dong, - Seo-Gu, Taejon, 302-223 - KOREA, REPUBLIC OF - - 00-08-2C (hex) Homag AG - 00082C (base 16) Homag AG - Abt. Est., Homag Str. 3-5 - D-72296 Schopfloch - GERMANY - - 00-08-2D (hex) Indus Teqsite Private Limited - 00082D (base 16) Indus Teqsite Private Limited - #7, Arya Gowder Road, - West Mambalam, Chennai, - Tamil Nadu 600033 - INDIA - - 00-08-2E (hex) Multitone Electronics PLC - 00082E (base 16) Multitone Electronics PLC - Multitone House, Beggarwood Lane - Basingstoke RG23 7LL - UNITED KINGDOM - - 00-08-2F (hex) CISCO SYSTEMS, INC. - 00082F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-30 (hex) CISCO SYSTEMS, INC. - 000830 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-31 (hex) CISCO SYSTEMS, INC. - 000831 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-32 (hex) Cisco - 000832 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 00-08-4E (hex) DivergeNet, Inc. - 00084E (base 16) DivergeNet, Inc. - 2142 Bering Dr. - San Jose CA 95131 - UNITED STATES - - 00-08-4F (hex) Qualstar Corporation - 00084F (base 16) Qualstar Corporation - 3990B Heritage Oak Court - Simi Valley CA 93063 - UNITED STATES - - 00-08-50 (hex) Arizona Instrument Corp. - 000850 (base 16) Arizona Instrument Corp. - 1912 W. 4th Street - Tempe AZ 85281 - UNITED STATES - - 00-08-51 (hex) Canadian Bank Note Company, Ltd. - 000851 (base 16) Canadian Bank Note Company, Ltd. - 18 Auriga Dr. - Nepean, Ont. - K2E 7T9 - CANADA - - 00-08-52 (hex) Davolink Co. Inc. - 000852 (base 16) Davolink Co. Inc. - Room-604, Kumhwa Plaza, - 1142-5, Sanbon-Dong, Kunpo-Si - Kyunggi-Do 435-040 - KOREA, REPUBLIC OF - - 00-08-53 (hex) Schleicher GmbH & Co. Relaiswerke KG - 000853 (base 16) Schleicher GmbH & Co. Relaiswerke KG - Pichelswerderstrasse 3-5 - D-13597 Berlin - GERMANY - - 00-08-54 (hex) Netronix, Inc. - 000854 (base 16) Netronix, Inc. - 3F-1, No. 31, Hsin-Tai Road, - Chupei City, Hsinchu Hsien - TAIWAN, PROVINCE OF CHINA - - 00-08-55 (hex) NASA-Goddard Space Flight Center - 000855 (base 16) NASA-Goddard Space Flight Center - Code 561 - Greenbelt MD 20771 - UNITED STATES - - 00-08-56 (hex) Gamatronic Electronic Industries Ltd. - 000856 (base 16) Gamatronic Electronic Industries Ltd. - Hartum Street 14 - Jerusalem 97774 - ISRAEL - - 00-08-57 (hex) Polaris Networks, Inc. - 000857 (base 16) Polaris Networks, Inc. - 6810 Santa Teresa Blvd. - San Jose CA 95119 - UNITED STATES - - 00-08-58 (hex) Novatechnology Inc. - 000858 (base 16) Novatechnology Inc. - Nova Bldg. 4F 641 03 - Yuksam-Dong Kangnam-ku - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-08-59 (hex) ShenZhen Unitone Electronics Co., Ltd. - 000859 (base 16) ShenZhen Unitone Electronics Co., Ltd. - 2 Southern Floor 702 Building - BaGuaLing Industrial Zone Shenzhen - CHINA - - 00-08-5A (hex) IntiGate Inc. - 00085A (base 16) IntiGate Inc. - 309E IT Venture Tower - 78, Garakbon-Dong, Songpa-Gu - Seoul 138-803 - KOREA, REPUBLIC OF - - 00-08-5B (hex) Hanbit Electronics Co., Ltd. - 00085B (base 16) Hanbit Electronics Co., Ltd. - 414-5, Woncheon-Dong, Paldal-Gu - Suwon-City, Kyoungki-Do, 442-823 - KOREA, REPUBLIC OF - - 00-08-5C (hex) Shanghai Dare Technologies Co. Ltd. - 00085C (base 16) Shanghai Dare Technologies Co. Ltd. - 23F, China Merchants Tower, - No. 161, East LujiaZui Road - Pudong New Area, Shanghai - CHINA - - 00-08-5D (hex) Aastra - 00085D (base 16) Aastra - 1160 Route 22 East - Bridgewater NJ 08807 - UNITED STATES - - 00-08-5E (hex) PCO AG - 00085E (base 16) PCO AG - Donaupark 11 - 93309 Kelheim - GERMANY - - 00-08-5F (hex) Picanol N.V. - 00085F (base 16) Picanol N.V. - Polenlaan 3-7 - 8900 Ieper - BELGIUM - - 00-08-60 (hex) LodgeNet Entertainment Corp. - 000860 (base 16) LodgeNet Entertainment Corp. - 3900 W. Innovation Street - Sioux Falls SD 57107 - UNITED STATES - - 00-08-61 (hex) SoftEnergy Co., Ltd. - 000861 (base 16) SoftEnergy Co., Ltd. - 346 Sangwangsipli-Dong, - Sung Dong-Gu, Seoul - KOREA, REPUBLIC OF - - 00-08-62 (hex) NEC Eluminant Technologies, Inc. - 000862 (base 16) NEC Eluminant Technologies, Inc. - 14700 Avion Parkway - Chantilly VA 20151 - UNITED STATES - - 00-08-63 (hex) Entrisphere Inc. - 000863 (base 16) Entrisphere Inc. - 1601 S. De Anza Blvd. - Suite 250 - Cupertino CA 95014 - UNITED STATES - - 00-08-64 (hex) Fasy S.p.A. - 000864 (base 16) Fasy S.p.A. - Via Tognasca 7 - Gallarate Varese 21013 - ITALY - - 00-08-65 (hex) JASCOM CO., LTD - 000865 (base 16) JASCOM CO., LTD - JUAN INDUSTRIAL COMPLEX 330, 17-1, - JUAN-DONG NAM-GU INCHEON 402-200 - KOREA, REPUBLIC OF - - 00-08-66 (hex) DSX Access Systems, Inc. - 000866 (base 16) DSX Access Systems, Inc. - 10731 Rockwall Rd. - Dallas TX 75238 - UNITED STATES - - 00-08-67 (hex) Uptime Devices - 000867 (base 16) Uptime Devices - 11724 Dunfries Lane - Austin Texas 78754 - UNITED STATES - - 00-08-68 (hex) PurOptix - 000868 (base 16) PurOptix - 1945 Camino Vida Roble - Suite C - Carlsbad CA 92008 - UNITED STATES - - 00-08-69 (hex) Command-e Technology Co.,Ltd. - 000869 (base 16) Command-e Technology Co.,Ltd. - Suite 709, Zhongsheng Mansion, - No.2 Bei FengWo Rd. - Beijing 100038 - CHINA - - 00-08-6A (hex) Securiton Gmbh - 00086A (base 16) Securiton Gmbh - Von-Drais-Strasse 33 - Achern D-77855 - GERMANY - - 00-08-6B (hex) MIPSYS - 00086B (base 16) MIPSYS - 19C, Avenue des Indes - LES ULIS Cedex FR-91969 - FRANCE - - 00-08-6C (hex) Plasmon LMS - 00086C (base 16) Plasmon LMS - 4425 ArrowsWest Drive - Colorado Springs CO 80907 - UNITED STATES - - 00-08-6D (hex) Missouri FreeNet - 00086D (base 16) Missouri FreeNet - PO Box 771026 - St. Louis Missouri 63177-1026 - UNITED STATES - - 00-08-6E (hex) Hyglo AB - 00086E (base 16) Hyglo AB - Vastberga alle 60 - SE-126 75 Stockholm - SWEDEN - - 00-08-6F (hex) Resources Computer Network Ltd. - 00086F (base 16) Resources Computer Network Ltd. - Rm 324, Tech Centre, 72 Tat Chee Ave., - Kowloon Tong, Kowloon - HONG KONG - - 00-08-70 (hex) Rasvia Systems, Inc. - 000870 (base 16) Rasvia Systems, Inc. - 3255-3 Scott Blvd. - Suite 102 - Santa Clara CA 95054 - UNITED STATES - - 00-08-71 (hex) NORTHDATA Co., Ltd. - 000871 (base 16) NORTHDATA Co., Ltd. - #302 KayangTechno-Town 1487 - Kayang3-Dong - Kangseo-Gu Seoul 157-810 - KOREA, REPUBLIC OF - - 00-08-72 (hex) Sorenson Communications - 000872 (base 16) Sorenson Communications - 4192 South Riverboat Road - Salt Lake City UT 84123 - UNITED STATES - - 00-08-73 (hex) DapTechnology B.V. - 000873 (base 16) DapTechnology B.V. - Zutphenstraat 67 - EJ Oldenzaal 7575 - NETHERLANDS - - 00-08-74 (hex) Dell Computer Corp. - 000874 (base 16) Dell Computer Corp. - One Dell Way - Round Rock TX 78682 - UNITED STATES - - 00-08-75 (hex) Acorp Electronics Corp. - 000875 (base 16) Acorp Electronics Corp. - 8F, No.111-6,Shing Teh Rd, - San Chung Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 00-08-76 (hex) SDSystem - 000876 (base 16) SDSystem - 613,Hyundai I Valley,223-12, - Sangdaiwon 1-Dong,Jungwon-Gu - Seongnam Gyeonggi-Do 462-807 - KOREA, REPUBLIC OF - - 00-08-77 (hex) Liebert-Hiross Spa - 000877 (base 16) Liebert-Hiross Spa - Via Leonardo da Vinci 8 - Piove di Sacco Z.I. Tognana 35020 - ITALY - - 00-08-78 (hex) Benchmark Storage Innovations - 000878 (base 16) Benchmark Storage Innovations - 3122 Sterling Circle - Boulder CO 80301 - UNITED STATES - - 00-08-79 (hex) CEM Corporation - 000879 (base 16) CEM Corporation - P.O. Box 200 - Matthews NC 28106 - UNITED STATES - - 00-08-7A (hex) Wipotec GmbH - 00087A (base 16) Wipotec GmbH - Adam-Hoffman Str. 26 - D-67657 Kaiserslauterm - GERMANY - - 00-08-7B (hex) RTX Telecom A/S - 00087B (base 16) RTX Telecom A/S - Stroemmen 6 - DK 9400 Noerresundby - DENMARK - - 00-08-7C (hex) CISCO SYSTEMS, INC. - 00087C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-7D (hex) CISCO SYSTEMS, INC. - 00087D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-7E (hex) Bon Electro-Telecom Inc. - 00087E (base 16) Bon Electro-Telecom Inc. - Gayang 1st Factory 701, 14-81 - Gayang-Dong Gangso-Gu - Seoul 157-808 - KOREA, REPUBLIC OF - - 00-08-7F (hex) SPAUN electronic GmbH & Co. KG - 00087F (base 16) SPAUN electronic GmbH & Co. KG - Byk-Gulden - Str. 22 - 78224 Singen - GERMANY - - 00-08-80 (hex) BroadTel Canada Communications inc. - 000880 (base 16) BroadTel Canada Communications inc. - 3700 Griffith, Suite 389 - Saint-Laurent Quebec H4T 2B3 - CANADA - - 00-08-81 (hex) DIGITAL HANDS CO.,LTD. - 000881 (base 16) DIGITAL HANDS CO.,LTD. - KAKiYA Building 2F - 2-7-17 Shinyokohama Kouhoku-ku - Yokohama Kanagawa 222-0033 - JAPAN - - 00-08-82 (hex) SIGMA CORPORATION - 000882 (base 16) SIGMA CORPORATION - 2-3-15 Iwato-minami - Komae-shi Tokyo 201-8630 - JAPAN - - 00-08-83 (hex) Hewlett-Packard Company - 000883 (base 16) Hewlett-Packard Company - 10955 Tantau Avenue, Mailstop 45SL-G - Cupertino CA 95014 - UNITED STATES - - 00-08-84 (hex) Index Braille AB - 000884 (base 16) Index Braille AB - Box 155 - S-95423 Gammelstad - SWEDEN - - 00-08-85 (hex) EMS Dr. Thomas Wünsche - 000885 (base 16) EMS Dr. Thomas Wünsche - Sonnenhang 3 - D-85304 Ilmmünster - GERMANY - - 00-08-86 (hex) Hansung Teliann, Inc. - 000886 (base 16) Hansung Teliann, Inc. - 195-1, Neungpyung-ri, Opo-eub - Kwangju-si, Kyoggi-do, 464-890 - KOREA, REPUBLIC OF - - 00-08-87 (hex) Maschinenfabrik Reinhausen GmbH - 000887 (base 16) Maschinenfabrik Reinhausen GmbH - Falkensteinstraße 8 - Regensburg Bavaria 93059 - GERMANY - - 00-08-88 (hex) OULLIM Information Technology Inc,. - 000888 (base 16) OULLIM Information Technology Inc,. - a-10th FL,. IT Venture Tower, - 78 Garak-Dong, Songpa-Ku - Seoul 138-803 - KOREA, REPUBLIC OF - - 00-08-89 (hex) Echostar Technologies Corp - 000889 (base 16) Echostar Technologies Corp - 94 Inverness Circle - Englewood CO 80112 - UNITED STATES - - 00-08-8A (hex) Minds@Work - 00088A (base 16) Minds@Work - 15550 Rockfield Blvd. Suite C - Irvine CA 92618 - UNITED STATES - - 00-08-8B (hex) Tropic Networks Inc. - 00088B (base 16) Tropic Networks Inc. - 135 Micheal Cowpland Drive - Ottawa Ontario K2M2E9 - CANADA - - 00-08-8C (hex) Quanta Network Systems Inc. - 00088C (base 16) Quanta Network Systems Inc. - 13, 13F, Sec. 2, Pei-Tou Rd - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-08-8D (hex) Sigma-Links Inc. - 00088D (base 16) Sigma-Links Inc. - 550-1 Higashiasakawa-cho, - Hachioji-shi, - Tokyo 193-8550 - JAPAN - - 00-08-8E (hex) Nihon Computer Co., Ltd. - 00088E (base 16) Nihon Computer Co., Ltd. - 36-8 Higashitamachi - Hamamatsu Shizuoka 430-0915 - JAPAN - - 00-08-8F (hex) ADVANCED DIGITAL TECHNOLOGY - 00088F (base 16) ADVANCED DIGITAL TECHNOLOGY - ADT BLDG.,3-3, YANGJAE-DONG, - SEOCHO-GU, - SEOUL - KOREA, REPUBLIC OF - - 00-08-90 (hex) AVILINKS SA - 000890 (base 16) AVILINKS SA - Etic Center - CS 77 729 - 9 rue des Charmilles - Cesson Sevigne Cedex FRANCE 35577 - FRANCE - - 00-08-91 (hex) Lyan Inc. - 000891 (base 16) Lyan Inc. - 5F-1, NO.51, SEC.2, KEELUNG RD. - TAIPEI 110 - TAIWAN, PROVINCE OF CHINA - - 00-08-92 (hex) EM Solutions - 000892 (base 16) EM Solutions - 101 Hyde Rd - Yeronga Brisbane, QLD 4104 - AUSTRALIA - - 00-08-93 (hex) LE INFORMATION COMMUNICATION INC. - 000893 (base 16) LE INFORMATION COMMUNICATION INC. - Rm, 4501, DA-Dong Chungang Circulation C - 1258 Kuro Bon-Dong, Kuro-Ku, - Seoul 152-721 - KOREA, REPUBLIC OF - - 00-08-94 (hex) InnoVISION Multimedia Ltd. - 000894 (base 16) InnoVISION Multimedia Ltd. - Rm 608, 6/F Tins Enterprises Centre, - 777 Lai Chi Kok Road, - Kowloon, - HONG KONG - - 00-08-95 (hex) DIRC Technologie GmbH & Co.KG - 000895 (base 16) DIRC Technologie GmbH & Co.KG - Borsigstraße 13 - Ratingen NRW 40880 - GERMANY - - 00-08-96 (hex) Printronix, Inc. - 000896 (base 16) Printronix, Inc. - 14600 Myford Rd. - P.O. Box 19559 - Irvine California 92623-9559 - UNITED STATES - - 00-08-97 (hex) Quake Technologies - 000897 (base 16) Quake Technologies - 2880 Zanker Road - Suite 104 - San Jose CA 95134 - UNITED STATES - - 00-08-98 (hex) Gigabit Optics Corporation - 000898 (base 16) Gigabit Optics Corporation - 1156 Aster Ave. - Sunnyvale CA 94086-6810 - UNITED STATES - - 00-08-99 (hex) Netbind, Inc. - 000899 (base 16) Netbind, Inc. - 5 Marine View Plaza - Hoboken NJ 07030 - UNITED STATES - - 00-08-9A (hex) Alcatel Microelectronics - 00089A (base 16) Alcatel Microelectronics - Excelsiorlaan 44-46 - B-1930 Zavantem - BELGIUM - - 00-08-9B (hex) ICP Electronics Inc. - 00089B (base 16) ICP Electronics Inc. - 4F, No. 22, Chung-Hsing Rd. Shi-Chi City - Taipei Hsien, 221, - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-08-9C (hex) Elecs Industry Co., Ltd. - 00089C (base 16) Elecs Industry Co., Ltd. - 1-22-23,Shinsaku,Takatsu-Ku - Kawasaki Kanagawa 213-0014 - JAPAN - - 00-08-9D (hex) UHD-Elektronik - 00089D (base 16) UHD-Elektronik - Zuercherstrasse 12 - Baden AG 5400 - SWITZERLAND - - 00-08-9E (hex) Beijing Enter-Net co.LTD - 00089E (base 16) Beijing Enter-Net co.LTD - NO 1 courtyard, - shuangquanpu jia 1,chaoya - Beijing 100085 - CHINA - - 00-08-9F (hex) EFM Networks - 00089F (base 16) EFM Networks - 403, 4th floor Elegance 1 Bldg. - 25-2 Gumi-dong Pundang-gu - Sungnam-si Kyunggi-do 463-808 - KOREA, REPUBLIC OF - - 00-08-A0 (hex) Stotz Feinmesstechnik GmbH - 0008A0 (base 16) Stotz Feinmesstechnik GmbH - Hermann-Dreher Str. 6 - Gerlingen 70839 - GERMANY - - 00-08-A1 (hex) CNet Technology Inc. - 0008A1 (base 16) CNet Technology Inc. - No.15, Park Avenue II, Science-Based Ind - Hsin-Chu City, - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-08-A2 (hex) ADI Engineering, Inc. - 0008A2 (base 16) ADI Engineering, Inc. - 1769A Worth Park - Charlottesville VA 22911 - UNITED STATES - - 00-08-A3 (hex) CISCO SYSTEMS, INC. - 0008A3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-A4 (hex) CISCO SYSTEMS, INC. - 0008A4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-A5 (hex) Peninsula Systems Inc. - 0008A5 (base 16) Peninsula Systems Inc. - 6902 Verde Ridge Rd. - Rancho Palos Verdes CA 90275 - UNITED STATES - - 00-08-A6 (hex) Multiware & Image Co., Ltd. - 0008A6 (base 16) Multiware & Image Co., Ltd. - Saedong Bldg. 65-25, - 2ka, Namhang, Youngdo - Pusan 606-032 - KOREA, REPUBLIC OF - - 00-08-A7 (hex) iLogic Inc. - 0008A7 (base 16) iLogic Inc. - Rm#318, TechnoComplex Bldg., 126-16, 5-g - Seoul 136-701 - KOREA, REPUBLIC OF - - 00-08-A8 (hex) Systec Co., Ltd. - 0008A8 (base 16) Systec Co., Ltd. - 19 Nochidori, Nawa - Tokai Aichi 476-0002 - JAPAN - - 00-08-A9 (hex) SangSang Technology, Inc. - 0008A9 (base 16) SangSang Technology, Inc. - 64-8, Nogok-ri, Docheok-myun, - Gwangju Kyonggi-do 464-882 - KOREA, REPUBLIC OF - - 00-08-AA (hex) KARAM - 0008AA (base 16) KARAM - 98-3, Hankangro 2-KA, Yongsan - Seoul 140-012 - KOREA, REPUBLIC OF - - 00-08-AB (hex) EnerLinx.com, Inc. - 0008AB (base 16) EnerLinx.com, Inc. - 3965 South Woodhill Lane - New Berlin WI 53151 - UNITED STATES - - 00-08-AC (hex) Eltromat GmbH - 0008AC (base 16) Eltromat GmbH - Herforder Straße 249-251 - Leopoldshöhe Nordrhein-Westfalen 33818 - GERMANY - - 00-08-AD (hex) Toyo-Linx Co., Ltd. - 0008AD (base 16) Toyo-Linx Co., Ltd. - Hirakawa-Cho, Chiyada-ku, - Tokyo 102-0093 - JAPAN - - 00-08-AE (hex) PacketFront Network Products AB - 0008AE (base 16) PacketFront Network Products AB - PO 1217 - Kistagangen 2, IV Kista Stockholm SE -16428 - SWEDEN - - 00-08-AF (hex) Novatec Corporation - 0008AF (base 16) Novatec Corporation - 2-19-2 Nishi-Gotanda - Shinagawa-ku Tokyo 141-0031 - JAPAN - - 00-08-B0 (hex) BKtel communications GmbH - 0008B0 (base 16) BKtel communications GmbH - Benzstraße 4 - 41836 Hückelhoven-Baal NRW 41836 - GERMANY - - 00-08-B1 (hex) ProQuent Systems - 0008B1 (base 16) ProQuent Systems - 67 Forest Street - Marlboro MA 01752 - UNITED STATES - - 00-08-B2 (hex) SHENZHEN COMPASS TECHNOLOGY DEVELOPMENT CO.,LTD - 0008B2 (base 16) SHENZHEN COMPASS TECHNOLOGY DEVELOPMENT CO.,LTD - 4th Floor,Building 205,TaiRan Industry - &Trade Park,Futian District,Shenzhen - Shenzhen GUANGDONG 518040 - CHINA - - 00-08-B3 (hex) Fastwel - 0008B3 (base 16) Fastwel - Profsoyuznaya 108, - Moscow 117313 - RUSSIAN FEDERATION - - 00-08-B4 (hex) SYSPOL - 0008B4 (base 16) SYSPOL - 4th Fl,SYSPOL B/D, Bangbae 4 Dong, Seoch - Seoul 137-064 - KOREA, REPUBLIC OF - - 00-08-B5 (hex) TAI GUEN ENTERPRISE CO., LTD - 0008B5 (base 16) TAI GUEN ENTERPRISE CO., LTD - N0.400, 10F-7 HUANPEI RD., - CHUNG LI CITY TW, ROC. - CHUNG LI 320-61 - TAIWAN, PROVINCE OF CHINA - - 00-08-B6 (hex) RouteFree, Inc. - 0008B6 (base 16) RouteFree, Inc. - 3400 Hillview Ave. Bldg. 5 - Palo Alto CA 94306 - UNITED STATES - - 00-08-B7 (hex) HIT Incorporated - 0008B7 (base 16) HIT Incorporated - 4F, 8, Lane 235, Pao-Chiao Road, - Shin Tien Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-08-B8 (hex) E.F. Johnson - 0008B8 (base 16) E.F. Johnson - 299 Johnson Ave. - P.O. Box 1249 - Waseca MN 56093 - UNITED STATES - - 00-08-B9 (hex) KAON MEDIA Co., Ltd. - 0008B9 (base 16) KAON MEDIA Co., Ltd. - #113 Imae 1-Dong, Bundang-Gu - Sungnam-City Kyungki-Do 463-829 - KOREA, REPUBLIC OF - - 00-08-BA (hex) Erskine Systems Ltd - 0008BA (base 16) Erskine Systems Ltd - Salter Road - Eastfield Industrial Estate - Scarborough North Yorkshire YO11 3DU - UNITED KINGDOM - - 00-08-BB (hex) NetExcell - 0008BB (base 16) NetExcell - 15375 Barranca Pkwy, #E-106 - Irvine CA 92679 - UNITED STATES - - 00-08-BC (hex) Ilevo AB - 0008BC (base 16) Ilevo AB - Box 1561 - Karlstad Värmland S-651 21 - SWEDEN - - 00-08-BD (hex) TEPG-US - 0008BD (base 16) TEPG-US - 100 Simplex Drive - Westminster MA 01441 - UNITED STATES - - 00-08-BE (hex) XENPAK MSA Group - 0008BE (base 16) XENPAK MSA Group - Care of: Agilent Technologies - White House Road - Ipswich Suffolk Ip1 5PB - UNITED KINGDOM - - 00-08-BF (hex) Aptus Elektronik AB - 0008BF (base 16) Aptus Elektronik AB - FO Petersons G 6 - 421 31 V. Frolunda - SWEDEN - - 00-08-C0 (hex) ASA SYSTEMS - 0008C0 (base 16) ASA SYSTEMS - S245 Korea Maritime University, 1 Dongsa - Busan Busan Metropolitan City 606-791 - KOREA, REPUBLIC OF - - 00-08-C1 (hex) Avistar Communications Corporation - 0008C1 (base 16) Avistar Communications Corporation - 15851 Dallas Pkwy. - Suite 600 - Addison TX 75001 - UNITED STATES - - 00-08-C2 (hex) CISCO SYSTEMS, INC. - 0008C2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-C3 (hex) Contex A/S - 0008C3 (base 16) Contex A/S - Svanevang 2 - Allerod DK 3450 - DENMARK - - 00-08-C4 (hex) Hikari Co.,Ltd. - 0008C4 (base 16) Hikari Co.,Ltd. - 418-4 Minaminoda Chigenobu-cho - Onsen-gun Ehime 791-0297 - JAPAN - - 00-08-C5 (hex) Liontech Co., Ltd. - 0008C5 (base 16) Liontech Co., Ltd. - 306, Wooyoung Techno Center, 273-15, - Sungsu2ga-3dong, Sungdong-ku, - Seoul 133-831 - KOREA, REPUBLIC OF - - 00-08-C6 (hex) Philips Consumer Communications - 0008C6 (base 16) Philips Consumer Communications - Route d'Angers - 72081 Le Mans - Cedex 9 - FRANCE - - 00-08-C7 (hex) Hewlett-Packard Company - 0008C7 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - Houston TX 77070 - UNITED STATES - - 00-08-C8 (hex) Soneticom, Inc. - 0008C8 (base 16) Soneticom, Inc. - 4325 Woodland Park Drive, Suite 102 - West Melbourne Florida 32904 - UNITED STATES - - 00-08-C9 (hex) TechniSat Digital GmbH - 0008C9 (base 16) TechniSat Digital GmbH - Gewerbepark Merbitz Nr. 5 - Dresden Saxony 01156 - GERMANY - - 00-08-CA (hex) TwinHan Technology Co.,Ltd - 0008CA (base 16) TwinHan Technology Co.,Ltd - 13F-6,No 79,Sec 1,Hsin Tai Wu RD.,Hsi-Ch - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-08-CB (hex) Zeta Broadband Inc. - 0008CB (base 16) Zeta Broadband Inc. - 660 Vista Way, Suite B - Milpitas CA 95035 - UNITED STATES - - 00-08-CC (hex) Remotec, Inc. - 0008CC (base 16) Remotec, Inc. - 114 Union Valley Road - Oak Ridge TN 37830 - UNITED STATES - - 00-08-CD (hex) With-Net Inc - 0008CD (base 16) With-Net Inc - 4FL B&B B/D 1403-4 - Kwangyang1-dong Dongan-ku - Anyang Kyonggi 431-061 - KOREA, REPUBLIC OF - - 00-08-CE (hex) IPMobileNet Inc. - 0008CE (base 16) IPMobileNet Inc. - 11909 E Telegraph Rd. - Santa Fe Springs CA 90670 - UNITED STATES - - 00-08-CF (hex) Nippon Koei Power Systems Co., Ltd. - 0008CF (base 16) Nippon Koei Power Systems Co., Ltd. - 2940 Shinyoshida-cho - Kohoku-ku Yokohama 223-8506 - JAPAN - - 00-08-D0 (hex) Musashi Engineering Co., LTD. - 0008D0 (base 16) Musashi Engineering Co., LTD. - 3-11-7, Nishi-shimbashi - Minato-ku Tokyo 105-0003 - JAPAN - - 00-08-D1 (hex) KAREL INC. - 0008D1 (base 16) KAREL INC. - ORGANIZE SANAYI BOLGESI - GAZNELILER CAD NO:10 SINCAN - ANKARA 06935 - TURKEY - - 00-08-D2 (hex) ZOOM Networks Inc. - 0008D2 (base 16) ZOOM Networks Inc. - 13F,XinLuDao Building,No.1175,Nanshan Ro - Shen Zhen GuangDong Province 518052 - CHINA - - 00-08-D3 (hex) Hercules Technologies S.A.S. - 0008D3 (base 16) Hercules Technologies S.A.S. - 6,place des colombes - Rennes Bretagne 35000 - FRANCE - - 00-08-D4 (hex) IneoQuest Technologies, Inc - 0008D4 (base 16) IneoQuest Technologies, Inc - 1931 Washington St - Canton Massachusetts 02021 - UNITED STATES - - 00-08-D5 (hex) Vanguard Networks Solutions, LLC - 0008D5 (base 16) Vanguard Networks Solutions, LLC - 25 Forbes Boulevard - Foxboro MA 02035 - UNITED STATES - - 00-08-D6 (hex) HASSNET Inc. - 0008D6 (base 16) HASSNET Inc. - 2F Missy2000 B/D 725, SooSeo-Dong, - Kangnam-Ku - Seoul 135-757 - KOREA, REPUBLIC OF - - 00-08-D7 (hex) HOW CORPORATION - 0008D7 (base 16) HOW CORPORATION - 1-11-17 Chiyoda - Sagamihara Kanagawa 229-0037 - JAPAN - - 00-08-D8 (hex) Dowkey Microwave - 0008D8 (base 16) Dowkey Microwave - 4822 McGrath Street - Ventura Ca 93003 - UNITED STATES - - 00-08-D9 (hex) Mitadenshi Co.,LTD - 0008D9 (base 16) Mitadenshi Co.,LTD - 1-8-6 Furuichi Asaminamiku - Hiroshima 731-0123 - JAPAN - - 00-08-DA (hex) SofaWare Technologies Ltd. - 0008DA (base 16) SofaWare Technologies Ltd. - 3 Hilazon St. - Ramat-Gan 52522 - ISRAEL - - 00-08-DB (hex) Corrigent Systems - 0008DB (base 16) Corrigent Systems - 126 Yigal Alon - Tel Aviv 67443 - ISRAEL - - 00-08-DC (hex) Wiznet - 0008DC (base 16) Wiznet - 5F Simmtech bldg., 228-3, - Nonyhun, Kangnam - Seoul 135-830 - KOREA, REPUBLIC OF - - 00-08-DD (hex) Telena Communications, Inc. - 0008DD (base 16) Telena Communications, Inc. - 6725 Mesa Ridge Road - Suite 226 - San Diego CA 92121 - UNITED STATES - - 00-08-DE (hex) 3UP Systems - 0008DE (base 16) 3UP Systems - 6 Results Way - Cupertino CA 95014 - UNITED STATES - - 00-08-DF (hex) Alistel Inc. - 0008DF (base 16) Alistel Inc. - Midori Bldg. 2F - 1-5-20 Nakagawa, Tsuzuki-ku - Yokohama Kanagawa 222-0001 - JAPAN - - 00-08-E0 (hex) ATO Technology Ltd. - 0008E0 (base 16) ATO Technology Ltd. - Rm. 1314-1346, Block B1, Yau Tong Ind. C - Yau Tong, Kowloon, - Hong Kong - HONG KONG - - 00-08-E1 (hex) Barix AG - 0008E1 (base 16) Barix AG - Seefeld Strasse 303 - Zürich ZH 8008 - SWITZERLAND - - 00-08-E2 (hex) CISCO SYSTEMS, INC. - 0008E2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-E3 (hex) CISCO SYSTEMS, INC. - 0008E3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-08-E4 (hex) Envenergy Inc - 0008E4 (base 16) Envenergy Inc - 6307 Carpinteria Ave - Carpinteria CA 93013 - UNITED STATES - - 00-08-E5 (hex) IDK Corporation - 0008E5 (base 16) IDK Corporation - 6-7-10 - Chuo-Rinkan - Yamato Kanagawa 242-0007 - JAPAN - - 00-08-E6 (hex) Littlefeet - 0008E6 (base 16) Littlefeet - 13000 Gregg Street - Poway California 92064 - UNITED STATES - - 00-08-E7 (hex) SHI ControlSystems,Ltd. - 0008E7 (base 16) SHI ControlSystems,Ltd. - 19,Natusima - Yokosuka Kanagawa 237-8555 - JAPAN - - 00-08-E8 (hex) Excel Master Ltd. - 0008E8 (base 16) Excel Master Ltd. - Room D, 3/F., Yeung Yiu Chung (No. 8) Ind. Bldg. - 20 Wang Hoi Road - Kowloon Bay - HONG KONG - - 00-08-E9 (hex) NextGig - 0008E9 (base 16) NextGig - 9820-B Towne Centre Drive - San Diego CA 92121 - UNITED STATES - - 00-08-EA (hex) Motion Control Engineering, Inc - 0008EA (base 16) Motion Control Engineering, Inc - 11380 White Rock Road - Rancho Cordova CA 95742 - UNITED STATES - - 00-08-EB (hex) ROMWin Co.,Ltd. - 0008EB (base 16) ROMWin Co.,Ltd. - 406 OmiyaOhtaka Bldg. 1-103 - Kishiki-cho - Saitama 330-0843 - JAPAN - - 00-08-EC (hex) Optical Zonu Corporation - 0008EC (base 16) Optical Zonu Corporation - 15028 Delano Street - Van Nuys CA 91411-2016 - UNITED STATES - - 00-08-ED (hex) ST&T Instrument Corp. - 0008ED (base 16) ST&T Instrument Corp. - 16 Shing-Gong Road, Yung-Kung Industrial - Yung-Kung Tainan 710 - TAIWAN, PROVINCE OF CHINA - - 00-08-EE (hex) Logic Product Development - 0008EE (base 16) Logic Product Development - 411 Washington Ave N. Suite 101 - Minneapolis Minnesota 55401 - UNITED STATES - - 00-08-EF (hex) DIBAL,S.A. - 0008EF (base 16) DIBAL,S.A. - Astintze Kalea 24 - Derio Vizcaya 48160 - SPAIN - - 00-08-F0 (hex) Next Generation Systems, Inc. - 0008F0 (base 16) Next Generation Systems, Inc. - PO BOX 31205 - Dayton OH 45437-0205 - UNITED STATES - - 00-08-F1 (hex) Voltaire - 0008F1 (base 16) Voltaire - 9 Hamenofim st. - Herzelia 46725 - ISRAEL - - 00-08-F2 (hex) C&S Technology - 0008F2 (base 16) C&S Technology - C&S Venture Bldg., NonHyun-Dong, - 221-1, GangNam-Gu - SEOUL 135-829 - KOREA, REPUBLIC OF - - 00-08-F3 (hex) WANY - 0008F3 (base 16) WANY - CEEI Cap Alpha - Avenue de l'Europe, Clapiers - Montpellier Herault 34940 - FRANCE - - 00-08-F4 (hex) Bluetake Technology Co., Ltd. - 0008F4 (base 16) Bluetake Technology Co., Ltd. - 6F, No. 33, Lane 155, Sec. 3, Pei Shen R - Saen Keng Shiang, Taipei - Taipei Taiwan 222 - TAIWAN, PROVINCE OF CHINA - - 00-08-F5 (hex) YESTECHNOLOGY Co.,Ltd. - 0008F5 (base 16) YESTECHNOLOGY Co.,Ltd. - 4th FL Kyung-Am B/D 157-27 Samsung-Dong, - Seoul 135-090 - KOREA, REPUBLIC OF - - 00-08-F6 (hex) Sumitomo Electric System Solutions Co., Ltd. - 0008F6 (base 16) Sumitomo Electric System Solutions Co., Ltd. - 1-1-3, Shimaya, Konohana-ku, - Osaka City, Osaka, 554-0024 - JAPAN - - 00-08-F7 (hex) Hitachi Ltd, Semiconductor & Integrated Circuits Gr - 0008F7 (base 16) Hitachi Ltd, Semiconductor & Integrated Circuits Gr - 20-1 Josuihon-chou 5chome - Kodaira-shi Tokyo 187-8588 - JAPAN - - 00-08-F8 (hex) UTC CCS - 0008F8 (base 16) UTC CCS - 791 Commerce Blvd - Suite 100 - Boca Raton Florida 33487 - UNITED STATES - - 00-08-F9 (hex) Artesyn Embedded Technologies - 0008F9 (base 16) Artesyn Embedded Technologies - 2900 S. Diablo Way Suite 190 - Tempe AZ 85282 - UNITED STATES - - 00-08-FA (hex) Karl E.Brinkmann GmbH - 0008FA (base 16) Karl E.Brinkmann GmbH - Foersterweg 36-38 - Barntrup NRW D-32683 - GERMANY - - 00-08-FB (hex) SonoSite, Inc. - 0008FB (base 16) SonoSite, Inc. - 21919 30th Drive SE - Bothell WA 98021 - UNITED STATES - - 00-08-FC (hex) Gigaphoton Inc. - 0008FC (base 16) Gigaphoton Inc. - YOKOKURA SHINDEN400 - OYAMA TOTIGI 323-8558 - JAPAN - - 00-08-FD (hex) BlueKorea Co., Ltd. - 0008FD (base 16) BlueKorea Co., Ltd. - 3F, sejong Building, 379-15, Seokyo-Dong - Mapo-Ku, - Seoul 121-839 - KOREA, REPUBLIC OF - - 00-08-FE (hex) UNIK C&C Co.,Ltd. - 0008FE (base 16) UNIK C&C Co.,Ltd. - 706-13 UNIK BLDG 17F - YEOK-SAM KANG-NAM GU - SEOUL 135-080 - KOREA, REPUBLIC OF - - 00-08-FF (hex) Trilogy Communications Ltd - 0008FF (base 16) Trilogy Communications Ltd - 26 Focus Way - Walworth Estate - Andover Hampshire SP10 5NY - UNITED KINGDOM - - 00-09-00 (hex) TMT - 000900 (base 16) TMT - 11 Kiryat Mada, POB 45199 - Jerusalem 91450 - ISRAEL - - 00-09-01 (hex) Shenzhen Shixuntong Information & Technoligy Co - 000901 (base 16) Shenzhen Shixuntong Information & Technoligy Co - Room 403,617 Bldg;Bagua 1 Road ,Shenzhen - Shenzhen Guangdong 518029 - CHINA - - 00-09-02 (hex) Redline Communications Inc. - 000902 (base 16) Redline Communications Inc. - 302 Town Centre Blvd - Suite 100 - Markham ON L3R 0E8 - CANADA - - 00-09-03 (hex) Panasas, Inc - 000903 (base 16) Panasas, Inc - 15333 John F Kennedy Blvd, Suite 400 - Houston TX 77032-2351 - UNITED STATES - - 00-09-04 (hex) MONDIAL electronic - 000904 (base 16) MONDIAL electronic - Eggelsberg 73 - Eggelsberg Oberoesterreich 5142 - AUSTRIA - - 00-09-05 (hex) iTEC Technologies Ltd. - 000905 (base 16) iTEC Technologies Ltd. - 160-1, Karak-Dong, Songpa-Gu - Seoul 138-809 - KOREA, REPUBLIC OF - - 00-09-06 (hex) Esteem Networks - 000906 (base 16) Esteem Networks - 4F, No.900, Yishan Road - Shanghai 200233 - CHINA - - 00-09-07 (hex) Chrysalis Development - 000907 (base 16) Chrysalis Development - 8125 River Dr. Suite 100 - Morton Grove IL 60053 - UNITED STATES - - 00-09-08 (hex) VTech Technology Corp. - 000908 (base 16) VTech Technology Corp. - 2F-2, No. 124, Chung Cheng Rd., Shihlin - Taipei 11141 - TAIWAN, PROVINCE OF CHINA - - 00-09-09 (hex) Telenor Connect A/S - 000909 (base 16) Telenor Connect A/S - Ellegaardvej 25L - Sønderborg Als 6400 - DENMARK - - 00-09-0A (hex) SnedFar Technology Co., Ltd. - 00090A (base 16) SnedFar Technology Co., Ltd. - 15FL., No.866-2, Jung Jeng Rd., - Junghe Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-09-0B (hex) MTL Instruments PLC - 00090B (base 16) MTL Instruments PLC - Power Court - Luton Bedfordshire LU1 3JJ - UNITED KINGDOM - - 00-09-0C (hex) Mayekawa Mfg. Co. Ltd. - 00090C (base 16) Mayekawa Mfg. Co. Ltd. - 16825 IH 35 North - Selma Texas 78154 - UNITED STATES - - 00-09-0D (hex) LEADER ELECTRONICS CORP. - 00090D (base 16) LEADER ELECTRONICS CORP. - 2-6-33, TSUNASHIMA-HIGASHI - KOHOKU-KU - YOKOHAMA KANAGAWA 223-8505 - JAPAN - - 00-09-0E (hex) Helix Technology Inc. - 00090E (base 16) Helix Technology Inc. - 5F, No. 6, Sec 1, Jung-Shing Rd., Wugu-S - Taipei 248 - TAIWAN, PROVINCE OF CHINA - - 00-09-0F (hex) Fortinet Inc. - 00090F (base 16) Fortinet Inc. - 1090 Kifer Road - Sunnyvale CA 94086 - UNITED STATES - - 00-09-10 (hex) Simple Access Inc. - 000910 (base 16) Simple Access Inc. - 600 McCaffrey Street - St-Laurent Quebec H4T1N1 - CANADA - - 00-09-11 (hex) CISCO SYSTEMS, INC. - 000911 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-12 (hex) CISCO SYSTEMS, INC. - 000912 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-13 (hex) SystemK Corporation - 000913 (base 16) SystemK Corporation - 238-9 Higashi 1, Kita 15, Higashi-ku - Sapporo Hokkaido 065-0015 - JAPAN - - 00-09-14 (hex) COMPUTROLS INC. - 000914 (base 16) COMPUTROLS INC. - 221 Bark Drive - Harvey LA 70058 - UNITED STATES - - 00-09-15 (hex) CAS Corp. - 000915 (base 16) CAS Corp. - #19, Ganap-Ri - Kwangguk-Myun - Yangju-Gun Kyunggi-Do 482-841 - KOREA, REPUBLIC OF - - 00-09-16 (hex) Listman Home Technologies, Inc. - 000916 (base 16) Listman Home Technologies, Inc. - 1100 Northmeadow Parkway - Suite 108 - Roswell Georgia 30076 - UNITED STATES - - 00-09-17 (hex) WEM Technology Inc - 000917 (base 16) WEM Technology Inc - 8F-2, No 386, Sec 5 Nanjing East Road. - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-09-18 (hex) SAMSUNG TECHWIN CO.,LTD - 000918 (base 16) SAMSUNG TECHWIN CO.,LTD - 42 - SUNGJUDONG - CHANGWON KYONGNAM 641-716 - KOREA, REPUBLIC OF - - 00-09-19 (hex) MDS Gateways - 000919 (base 16) MDS Gateways - Clonshaugh Industrial Estate - Clonshaugh - Dublin 17 - IRELAND - - 00-09-1A (hex) Macat Optics & Electronics Co., Ltd. - 00091A (base 16) Macat Optics & Electronics Co., Ltd. - 15/F., Macat Center, No. 63 Macat Road - Huizhou Guangdong 516001 - CHINA - - 00-09-1B (hex) Digital Generation Inc. - 00091B (base 16) Digital Generation Inc. - 5F, Ho-Sam B/D, #30-3, Bongchun6-Dong - Kwanak-Ku, Seoul 151-089 - KOREA, REPUBLIC OF - - 00-09-1C (hex) CacheVision, Inc - 00091C (base 16) CacheVision, Inc - 1990 Concourse Drive - San Jose CA 95131 - UNITED STATES - - 00-09-1D (hex) Proteam Computer Corporation - 00091D (base 16) Proteam Computer Corporation - 7F, No. 157. Section 2 Ta-Tung Rd - Hsi-Chih Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-09-1E (hex) Firstech Technology Corp. - 00091E (base 16) Firstech Technology Corp. - 8fl.,No.267,section 4,Hsin-Yi Rd. ,Da-An - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-09-1F (hex) A&D Co., Ltd. - 00091F (base 16) A&D Co., Ltd. - 1-243 Asahi - Kitamoto-shi Saitama 364-8585 - JAPAN - - 00-09-20 (hex) EpoX COMPUTER CO.,LTD. - 000920 (base 16) EpoX COMPUTER CO.,LTD. - 10th Floor, No.346,Chung San Rd.,Sec.2, - Chung Ho City,Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-09-21 (hex) Planmeca Oy - 000921 (base 16) Planmeca Oy - Asentajankatu 6 - HELSINKI 00810 HELSIN - FINLAND - - 00-09-22 (hex) TST Biometrics GmbH - 000922 (base 16) TST Biometrics GmbH - Moehlstraße 39 - 81675 Munich - GERMANY - - 00-09-23 (hex) Heaman System Co., Ltd - 000923 (base 16) Heaman System Co., Ltd - Building M6,National Hi-tech & Indus - Changsha Hunan Province 410013 - CHINA - - 00-09-24 (hex) Telebau GmbH - 000924 (base 16) Telebau GmbH - Am Kraehenberg 1 - Waldeck-Sachsenhausen Germany 34513 - GERMANY - - 00-09-25 (hex) VSN Systemen BV - 000925 (base 16) VSN Systemen BV - Keizersveld 83 - Venray Limburg 5803 AP - NETHERLANDS - - 00-09-26 (hex) YODA COMMUNICATIONS, INC. - 000926 (base 16) YODA COMMUNICATIONS, INC. - 2F, No.3-1, Industry East Road IX, - Hsinchu Science Based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-09-27 (hex) TOYOKEIKI CO.,LTD. - 000927 (base 16) TOYOKEIKI CO.,LTD. - 17-10-3,Shimosinjyo - Higashiyodogawa-Ku - Osaka 533-0021 - JAPAN - - 00-09-28 (hex) Telecore - 000928 (base 16) Telecore - 1800 North Glenville - Suite 116 - Richardson TX 75081 - UNITED STATES - - 00-09-29 (hex) Sanyo Industries (UK) Limited - 000929 (base 16) Sanyo Industries (UK) Limited - School Road - Lowestoft Suffolk NR33 9NA - UNITED KINGDOM - - 00-09-2A (hex) MYTECS Co.,Ltd. - 00092A (base 16) MYTECS Co.,Ltd. - 1-12-39, Taishidou - Setagaya-ku Tokyo 154-0004 - JAPAN - - 00-09-2B (hex) iQstor Networks, Inc. - 00092B (base 16) iQstor Networks, Inc. - 2001 Corporate Center Drive - Newbury Park CA 91320 - UNITED STATES - - 00-09-2C (hex) Hitpoint Inc. - 00092C (base 16) Hitpoint Inc. - No.7, Fenliao, 2nd Industrial Park, Link - Taipei 244 - TAIWAN, PROVINCE OF CHINA - - 00-09-2D (hex) HTC Corporation - 00092D (base 16) HTC Corporation - No.23 Xinghua Road, - Taoyuan City, - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 00-09-2E (hex) B&Tech System Inc. - 00092E (base 16) B&Tech System Inc. - #601, Seo-Jung B/D, 830-24, Youksam-Dong - Seoul - KOREA, REPUBLIC OF - - 00-09-2F (hex) Akom Technology Corporation - 00092F (base 16) Akom Technology Corporation - 5F, No. 323, Yang-Guang St. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-09-30 (hex) AeroConcierge Inc. - 000930 (base 16) AeroConcierge Inc. - 10256 Yonge St. - Richmond Hill Ont. L4C 3B7 - CANADA - - 00-09-31 (hex) Future Internet, Inc. - 000931 (base 16) Future Internet, Inc. - 11'th Floor Samhomoolsan Bldg, B/Bldg, 2 - Yangjea Dong, Seocho Ku - Seoul Kyung-Ki 137-130 - KOREA, REPUBLIC OF - - 00-09-32 (hex) Omnilux - 000932 (base 16) Omnilux - 130 W. Union St. - Pasadena CA 91103 - UNITED STATES - - 00-09-33 (hex) Ophit Co.Ltd. - 000933 (base 16) Ophit Co.Ltd. - 3F. Suntechnovil, 5-27 Mangpo-Dong , - Yeongtong-Gu, Suwon-City, - Kyungki-Do 137-070 - KOREA, REPUBLIC OF - - 00-09-34 (hex) Dream-Multimedia-Tv GmbH - 000934 (base 16) Dream-Multimedia-Tv GmbH - Brückstraße 29 - Menden Sauerland 58706 - GERMANY - - 00-09-35 (hex) Sandvine Incorporated - 000935 (base 16) Sandvine Incorporated - 170 Columbia St. W. - Waterloo ON N2L 3L3 - CANADA - - 00-09-36 (hex) Ipetronik GmbH & Co. KG - 000936 (base 16) Ipetronik GmbH & Co. KG - Im Rollfeld 28 - Baden-Baden Baden-Württemberg 76532 - GERMANY - - 00-09-37 (hex) Inventec Appliance Corp - 000937 (base 16) Inventec Appliance Corp - 113, Wugung 1 RD., WuKu Industrial nPark - WuKu Shiang, Taipei Hsien 248, Taiwan , - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-09-38 (hex) Allot Communications - 000938 (base 16) Allot Communications - Hanagar 22 st' - Hod-Hasharon 45800 - ISRAEL - - 00-09-39 (hex) ShibaSoku Co.,Ltd. - 000939 (base 16) ShibaSoku Co.,Ltd. - 6-8 Shinbashi 4-chome - Minato-ku Tokyo 105-0004 - JAPAN - - 00-09-3A (hex) Molex Fiber Optics - 00093A (base 16) Molex Fiber Optics - 5224 Katrine Avenue - Downers Grove IL 60515 - UNITED STATES - - 00-09-3B (hex) HYUNDAI NETWORKS INC. - 00093B (base 16) HYUNDAI NETWORKS INC. - SAN 136-1 AMI-RI BUBAL_EUP - ICHON KYUNGKI-DO 467-701 - KOREA, REPUBLIC OF - - 00-09-3C (hex) Jacques Technologies P/L - 00093C (base 16) Jacques Technologies P/L - 268 Montague Rd - West End Queensland 4101 - AUSTRALIA - - 00-09-3D (hex) Newisys,Inc. - 00093D (base 16) Newisys,Inc. - 6200 Bridgepoint Parkway - Buiding IV, Suite 100 - Austin TX 78730 - UNITED STATES - - 00-09-3E (hex) C&I Technologies - 00093E (base 16) C&I Technologies - #303 Kwanbo Plaza B/D, 1467-2 - Kwanyang-Dong, Dongan-Ku - Anyang-Shi Kyunggi-Do 431-808 - KOREA, REPUBLIC OF - - 00-09-3F (hex) Double-Win Enterpirse CO., LTD - 00093F (base 16) Double-Win Enterpirse CO., LTD - NO.300, Sec 1, Chung Feng Rd. - Ping Chen City Taoyuan Hsien 324 - TAIWAN, PROVINCE OF CHINA - - 00-09-40 (hex) AGFEO GmbH & Co. KG - 000940 (base 16) AGFEO GmbH & Co. KG - Postfach 140107 - Bielefeld Rhine Westfalia 33621 - GERMANY - - 00-09-41 (hex) Allied Telesis K.K. - 000941 (base 16) Allied Telesis K.K. - Technical Center/No.2 TOC Bldg. - 7-21-11 Nishi-Gotanda - Shinagawa-ku Tokyo 141-0031 - JAPAN - - 00-09-42 (hex) Wireless Technologies, Inc - 000942 (base 16) Wireless Technologies, Inc - Ohmori Mitsubishi Bldg., 7F, Sannoh 2-chome - Ohta-ku - Tokyo 143-0023 - JAPAN - - 00-09-43 (hex) CISCO SYSTEMS, INC. - 000943 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-44 (hex) CISCO SYSTEMS, INC. - 000944 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-45 (hex) Palmmicro Communications Inc - 000945 (base 16) Palmmicro Communications Inc - 630 Alder Dr - Milpitas CA 95035 - UNITED STATES - - 00-09-46 (hex) Cluster Labs GmbH - 000946 (base 16) Cluster Labs GmbH - Dauerwaldweg 1 - 14055 Berlin - Berlin Berlin 14055 - GERMANY - - 00-09-47 (hex) Aztek, Inc. - 000947 (base 16) Aztek, Inc. - 23 Spectrum Pointe #209 - Lake Forest California 92630 - UNITED STATES - - 00-09-48 (hex) Vista Control Systems, Corp. - 000948 (base 16) Vista Control Systems, Corp. - 2001 West Melinda Lane - Phoenix AZ 85027 - UNITED STATES - - 00-09-49 (hex) Glyph Technologies Inc. - 000949 (base 16) Glyph Technologies Inc. - 735 W. Clinton Street - Ithaca NY 14850 - UNITED STATES - - 00-09-4A (hex) Homenet Communications - 00094A (base 16) Homenet Communications - Innovation Centre - National Technological Park - Limerick - IRELAND - - 00-09-4B (hex) FillFactory NV - 00094B (base 16) FillFactory NV - Schalienhoevedreef 20B - B-2800 Mechelen - BELGIUM - - 00-09-4C (hex) Communication Weaver Co.,Ltd. - 00094C (base 16) Communication Weaver Co.,Ltd. - 1~3 COWEAVER B/D 446-19, - SEOGYO-DONG, MAPO-GU - SEOUL 121-841 - KOREA, REPUBLIC OF - - 00-09-4D (hex) Braintree Communications Pty Ltd - 00094D (base 16) Braintree Communications Pty Ltd - Unit 3 - 25 Randall Street - Slacks Creek QLD 4127 - AUSTRALIA - - 00-09-4E (hex) BARTECH SYSTEMS INTERNATIONAL, INC - 00094E (base 16) BARTECH SYSTEMS INTERNATIONAL, INC - 251 Najoles Rd Suite A - Millersville Maryland 21108 - UNITED STATES - - 00-09-4F (hex) elmegt GmbH & Co. KG - 00094F (base 16) elmegt GmbH & Co. KG - Kommunikationstechnik - Voehrumer Str. 30 - Peine Niedersachsen D-31228 - GERMANY - - 00-09-50 (hex) Independent Storage Corporation - 000950 (base 16) Independent Storage Corporation - 6273 Monarch Park Place - Niwot Colorado 80503 - UNITED STATES - - 00-09-51 (hex) Apogee Imaging Systems - 000951 (base 16) Apogee Imaging Systems - 151 Sunrise Avenue - Suite 902 - Roseville CA 95661 - UNITED STATES - - 00-09-52 (hex) Auerswald GmbH & Co. KG - 000952 (base 16) Auerswald GmbH & Co. KG - Vor den Grashoefen 1 - Cremlingen Niedersachsen 38162 - GERMANY - - 00-09-53 (hex) Linkage System Integration Co.Ltd. - 000953 (base 16) Linkage System Integration Co.Ltd. - 40 Gongjianfang - South Zhongshan Road - Nanjing Jiangsu 210006 - CHINA - - 00-09-54 (hex) AMiT spol. s. r. o. - 000954 (base 16) AMiT spol. s. r. o. - Naskove 3 - 150 00 Praha 5 - CZECH REPUBLIC - - 00-09-55 (hex) Young Generation International Corp. - 000955 (base 16) Young Generation International Corp. - 4F.,No. 188, Minchuan Rd., Shindian City - Shindian 231 - TAIWAN, PROVINCE OF CHINA - - 00-09-56 (hex) Network Systems Group, Ltd. (NSG) - 000956 (base 16) Network Systems Group, Ltd. (NSG) - 39 Kirpichnaya St., Suite 1302 - Moscow 105187 - RUSSIAN FEDERATION - - 00-09-57 (hex) Supercaller, Inc. - 000957 (base 16) Supercaller, Inc. - 101 Saginaw Drive - Redwood City CA 94063 - UNITED STATES - - 00-09-58 (hex) INTELNET S.A. - 000958 (base 16) INTELNET S.A. - FRANCISCO OLIVAN BAYLE, 4 - ZARAGOZA 50015 - SPAIN - - 00-09-59 (hex) Sitecsoft - 000959 (base 16) Sitecsoft - 7th Gugu BD. 145-18 Samsung-Dong - KangNam-Gu Seoul Korea - Seoul Seoul 135-090 - KOREA, REPUBLIC OF - - 00-09-5A (hex) RACEWOOD TECHNOLOGY - 00095A (base 16) RACEWOOD TECHNOLOGY - 5F-2,NO.6,CHUNG-HSING RD.,SEC.1,WU-GU - TAIPEI 248 - TAIWAN, PROVINCE OF CHINA - - 00-09-5B (hex) Netgear, Inc. - 00095B (base 16) Netgear, Inc. - 4500 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-09-5C (hex) Philips Medical Systems - Cardiac and Monitoring Systems (CM - 00095C (base 16) Philips Medical Systems - Cardiac and Monitoring Systems (CM - 3000 Minuteman Road - Andover Massachusetts 01810 - UNITED STATES - - 00-09-5D (hex) Dialogue Technology Corp. - 00095D (base 16) Dialogue Technology Corp. - 10F, No. 196, Sec. 2, Jungshing Rd. - Shindian City Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-09-5E (hex) Masstech Group Inc. - 00095E (base 16) Masstech Group Inc. - 2 East Beaver Creek Rd. - Building 3 - Richmond Hill Ontario L4B 2N3 - CANADA - - 00-09-5F (hex) Telebyte, Inc. - 00095F (base 16) Telebyte, Inc. - 270 Pulaski Road - Greenlawn NY 11740-1616 - UNITED STATES - - 00-09-60 (hex) YOZAN Inc. - 000960 (base 16) YOZAN Inc. - YOZAN Bld.,3-5-18, Kitazawa - Setagaya-ku Tokyo 155-0031 - JAPAN - - 00-09-61 (hex) Switchgear and Instrumentation Ltd - 000961 (base 16) Switchgear and Instrumentation Ltd - Ripley Road - Bradford West Yorkshire BD4 7EH - UNITED KINGDOM - - 00-09-62 (hex) Sonitor Technologies AS - 000962 (base 16) Sonitor Technologies AS - Forskningsveien 1B - P.O. Box 124 - Oslo Blindern N-0134 - NORWAY - - 00-09-63 (hex) Dominion Lasercom Inc. - 000963 (base 16) Dominion Lasercom Inc. - 1716 Briarcrest Dr. Ste. 210 - Bryan TX 77802 - UNITED STATES - - 00-09-64 (hex) Hi-Techniques, Inc. - 000964 (base 16) Hi-Techniques, Inc. - 2515 Frazier Ave. - Madison WI 53713-1505 - UNITED STATES - - 00-09-65 (hex) HyunJu Computer Co., Ltd. - 000965 (base 16) HyunJu Computer Co., Ltd. - 222-22, Hyunju B/D, Guro 3 Dong, Gurogu - Seoul 152-848 - KOREA, REPUBLIC OF - - 00-09-66 (hex) Thales Navigation - 000966 (base 16) Thales Navigation - 471 El Camino Real - Santa Clara CA 95050 - UNITED STATES - - 00-09-67 (hex) Tachyon, Inc - 000967 (base 16) Tachyon, Inc - 9339 Carroll Park Drive - Suite 150 - San Diego CA 92121 - UNITED STATES - - 00-09-68 (hex) TECHNOVENTURE, INC. - 000968 (base 16) TECHNOVENTURE, INC. - P. O. Box 5641 - Pasadena Texas 77508-5641 - UNITED STATES - - 00-09-69 (hex) Meret Optical Communications - 000969 (base 16) Meret Optical Communications - 10070 Mesa Rim Road - San Diego California 92121 - UNITED STATES - - 00-09-6A (hex) Cloverleaf Communications Inc. - 00096A (base 16) Cloverleaf Communications Inc. - 2 Willow St. - Southborough MA 01745-1027 - UNITED STATES - - 00-09-6B (hex) IBM Corp - 00096B (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-09-6C (hex) Imedia Semiconductor Corp. - 00096C (base 16) Imedia Semiconductor Corp. - 4988 Great America Pkwy. - Santa Clara CA 95054 - UNITED STATES - - 00-09-6D (hex) Powernet Technologies Corp. - 00096D (base 16) Powernet Technologies Corp. - 371-51, Gasan-Dong Kumchon-Gu, - Seoul 153-803 - KOREA, REPUBLIC OF - - 00-09-6E (hex) GIANT ELECTRONICS LTD. - 00096E (base 16) GIANT ELECTRONICS LTD. - 7/F., ELITE INDUSTRIAL BUILDING, - 135-137 HOI BUN ROAD, - KWUN TONG KOWLOON - HONG KONG - - 00-09-6F (hex) Beijing Zhongqing Elegant Tech. Corp.,Limited - 00096F (base 16) Beijing Zhongqing Elegant Tech. Corp.,Limited - Rm.508, A-Building, Shangdi Digital Scie - Beijing 100084 - CHINA - - 00-09-70 (hex) Vibration Research Corporation - 000970 (base 16) Vibration Research Corporation - 2385 Wilshere Drive - Suite A - Jenison MI 49428 - UNITED STATES - - 00-09-71 (hex) Time Management, Inc. - 000971 (base 16) Time Management, Inc. - 11 Lake Gatlin Road - Orlando Florida 32806 - UNITED STATES - - 00-09-72 (hex) Securebase,Inc - 000972 (base 16) Securebase,Inc - 2nd Fl,Seungseung-Bldg,Dokok 2-Dong,Kang - Seoul 135-854 - KOREA, REPUBLIC OF - - 00-09-73 (hex) Lenten Technology Co., Ltd. - 000973 (base 16) Lenten Technology Co., Ltd. - 16F, No.51, Sec.2, Gungyi Road, - Taichung City 408 - TAIWAN, PROVINCE OF CHINA - - 00-09-74 (hex) Innopia Technologies, Inc. - 000974 (base 16) Innopia Technologies, Inc. - 5F., Institute of Technology - Hanyang University, 17 Haengdang-Dong - Seoul 133-791 - KOREA, REPUBLIC OF - - 00-09-75 (hex) fSONA Communications Corporation - 000975 (base 16) fSONA Communications Corporation - #140-11120 Horseshoe Way - Richmond BC V7A 5H7 - CANADA - - 00-09-76 (hex) Datasoft ISDN Systems GmbH - 000976 (base 16) Datasoft ISDN Systems GmbH - Schillerplatz 3 - St. Poelten Lower Austria 3100 - AUSTRIA - - 00-09-77 (hex) Brunner Elektronik AG - 000977 (base 16) Brunner Elektronik AG - Müllerwis 1 - Hittnau Zurich 8335 - SWITZERLAND - - 00-09-78 (hex) AIJI System Co., Ltd. - 000978 (base 16) AIJI System Co., Ltd. - #208 Samho-Park-Tower Bldg. 1122-10, Ing - Suwon Gyeonggi-do 442-835 - KOREA, REPUBLIC OF - - 00-09-79 (hex) Advanced Television Systems Committee, Inc. - 000979 (base 16) Advanced Television Systems Committee, Inc. - 1750 K Street NW - Suite 1200 - Washington DC 20006 - UNITED STATES - - 00-09-7A (hex) Louis Design Labs. - 00097A (base 16) Louis Design Labs. - 2F,NO 4, Lane 497, Chung-Cheng Rd.,Hsin- - Hsin-Tien Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-09-7B (hex) CISCO SYSTEMS, INC. - 00097B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-7C (hex) CISCO SYSTEMS, INC. - 00097C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-7D (hex) SecWell Networks Oy - 00097D (base 16) SecWell Networks Oy - P.O.BOX 174 - Hämeenpuisto21 - Tampere 33101 - FINLAND - - 00-09-7E (hex) IMI TECHNOLOGY CO., LTD - 00097E (base 16) IMI TECHNOLOGY CO., LTD - 2nd floor, Eun Seok Building, 729-1 - Yeoksam-dong, - Gangnam-gu Seoul 135-080 - KOREA, REPUBLIC OF - - 00-09-7F (hex) Vsecure 2000 LTD. - 00097F (base 16) Vsecure 2000 LTD. - 11 Moshe Levi St. - Rishon LeZion 75658 - ISRAEL - - 00-09-80 (hex) Power Zenith Inc. - 000980 (base 16) Power Zenith Inc. - Tsujido Nishikaigan 1-10-7 - Fujisawa Kanagawa 251-0046 - JAPAN - - 00-09-81 (hex) Newport Networks - 000981 (base 16) Newport Networks - Enterprise House - Station Road - Chepstow Monmouthshire NP16 5PB - UNITED KINGDOM - - 00-09-82 (hex) Loewe Opta GmbH - 000982 (base 16) Loewe Opta GmbH - Industriestrasse 11 - Kronach 96317 - GERMANY - - 00-09-83 (hex) GlobalTop Technology, Inc. - 000983 (base 16) GlobalTop Technology, Inc. - #16 Nan-Ke 9th Road - Science-Based Industrial Park - Tainan 741 - TAIWAN, PROVINCE OF CHINA - - 00-09-84 (hex) MyCasa Network Inc. - 000984 (base 16) MyCasa Network Inc. - 200 Sheridan Ave #103 - Palo Alto CA 94306 - UNITED STATES - - 00-09-85 (hex) Auto Telecom Company - 000985 (base 16) Auto Telecom Company - 10F, No.3,Lane 16, Sec.2, Sichuan Rd. - Banqiao City Taipei County 22061 - TAIWAN, PROVINCE OF CHINA - - 00-09-86 (hex) Metalink LTD. - 000986 (base 16) Metalink LTD. - Yakum Business Park - Yakum HOF HASHARON 60972 - ISRAEL - - 00-09-87 (hex) NISHI NIPPON ELECTRIC WIRE & CABLE CO.,LTD. - 000987 (base 16) NISHI NIPPON ELECTRIC WIRE & CABLE CO.,LTD. - Kasugaura - Oita-City OITA 870-8632 - JAPAN - - 00-09-88 (hex) Nudian Electron Co., Ltd. - 000988 (base 16) Nudian Electron Co., Ltd. - 797-28 Bangbae-Dong, Seocho-Gu - Seoul 137-060 - KOREA, REPUBLIC OF - - 00-09-89 (hex) VividLogic Inc. - 000989 (base 16) VividLogic Inc. - 40994 Encyclopedia Circle - Fremont CA 94538 - UNITED STATES - - 00-09-8A (hex) EqualLogic Inc - 00098A (base 16) EqualLogic Inc - 9 Townsend West - Nashua NH 03062 - UNITED STATES - - 00-09-8B (hex) Entropic Communications, Inc. - 00098B (base 16) Entropic Communications, Inc. - 9276 Scranton Rd #200 - San Diego CA 92121 - UNITED STATES - - 00-09-8C (hex) Option Wireless Sweden - 00098C (base 16) Option Wireless Sweden - Sturegatan 2 - 11th fl. - Sundbyberg SE-172 24 - SWEDEN - - 00-09-8D (hex) Velocity Semiconductor - 00098D (base 16) Velocity Semiconductor - Suite 32 Wey House - 15 Church Street - Weybridge Surrey KT13 8NA - UNITED KINGDOM - - 00-09-8E (hex) ipcas GmbH - 00098E (base 16) ipcas GmbH - Wetterkreuz 17 - Erlangen Bavaria 91058 - GERMANY - - 00-09-8F (hex) Cetacean Networks - 00098F (base 16) Cetacean Networks - 110 Corporate Drive - Building 2 - Portsmouth NH 03801 - UNITED STATES - - 00-09-90 (hex) ACKSYS Communications & systems - 000990 (base 16) ACKSYS Communications & systems - ZA du Val Joyeux - 10 rue des Entrepreneurs - VILLEPREUX F-78450 - FRANCE - - 00-09-91 (hex) GE Fanuc Automation Manufacturing, Inc. - 000991 (base 16) GE Fanuc Automation Manufacturing, Inc. - Route 606 & Route 29N - PO Box 8106 - Charlottesville Virginia 22911 - UNITED STATES - - 00-09-92 (hex) InterEpoch Technology,INC. - 000992 (base 16) InterEpoch Technology,INC. - 7F,No.3,Alley 6,Lane 235,Pao-Chiao Rd - Hsin-Tien Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-09-93 (hex) Visteon Corporation - 000993 (base 16) Visteon Corporation - 16630 Southfield Road - St. 41E10 - Allen Park Michigan 48101 - UNITED STATES - - 00-09-94 (hex) Cronyx Engineering - 000994 (base 16) Cronyx Engineering - Marshala Sokolovskogo str. 4 - Moscow 123063 - RUSSIAN FEDERATION - - 00-09-95 (hex) Castle Technology Ltd - 000995 (base 16) Castle Technology Ltd - Ore Trading Estate - Woodbridge Road - Framlingham Suffolk IP13 9LL - UNITED KINGDOM - - 00-09-96 (hex) RDI - 000996 (base 16) RDI - 20406 Earl St. - Torrance CA 90503 - UNITED STATES - - 00-09-97 (hex) Nortel Networks - 000997 (base 16) Nortel Networks - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-09-98 (hex) Capinfo Company Limited - 000998 (base 16) Capinfo Company Limited - 7th Floor A Corporate Square, NO. 35 Fin - Beijing 100032 - CHINA - - 00-09-99 (hex) CP GEORGES RENAULT - 000999 (base 16) CP GEORGES RENAULT - 38 Rue Bobby Sands - 44800 Saint Herblain - FRANCE - - 00-09-9A (hex) ELMO COMPANY, LIMITED - 00099A (base 16) ELMO COMPANY, LIMITED - 6-14, MEIZEN-CHO, MIZUHO-KU - NAGOYA AICHI-Pref. 467-8567 - JAPAN - - 00-09-9B (hex) Western Telematic Inc. - 00099B (base 16) Western Telematic Inc. - 5 Sterling - Irvine CA 92618 - UNITED STATES - - 00-09-9C (hex) Naval Research Laboratory - 00099C (base 16) Naval Research Laboratory - Code 5592 - 4555 Overlook Avenue - Washington DC 20375-5000 - UNITED STATES - - 00-09-9D (hex) Haliplex Communications - 00099D (base 16) Haliplex Communications - PO Box 147 - Mooroolbark Vic 3138 - AUSTRALIA - - 00-09-9E (hex) Testech, Inc. - 00099E (base 16) Testech, Inc. - Bundang-Technopark, C-Dong, 702-Ho, #145 - Yatap-Dong, Bundang-Gu, - Sungnam-City Kyungki-Do 463-070 - KOREA, REPUBLIC OF - - 00-09-9F (hex) VIDEX INC. - 00099F (base 16) VIDEX INC. - 1105 NE Circle Blvd - Corvallis OR 97330 - UNITED STATES - - 00-09-A0 (hex) Microtechno Corporation - 0009A0 (base 16) Microtechno Corporation - 2-33-36 Shimoodanaka - Nakahara-ku - Kawasaki Kanagawa 211-0041 - JAPAN - - 00-09-A1 (hex) Telewise Communications, Inc. - 0009A1 (base 16) Telewise Communications, Inc. - 2050 Ringwood Avenue - San Jose CA 95131 - UNITED STATES - - 00-09-A2 (hex) Interface Co., Ltd. - 0009A2 (base 16) Interface Co., Ltd. - 2-5-12-201 Kyonancho - Musashino-city Tokyo 180-0023 - JAPAN - - 00-09-A3 (hex) Leadfly Techologies Corp. Ltd. - 0009A3 (base 16) Leadfly Techologies Corp. Ltd. - 9Fl, No.260, Bade Rd., - 104, R.O.C. - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-09-A4 (hex) HARTEC Corporation - 0009A4 (base 16) HARTEC Corporation - KOUHOKUKU SHIN-YOKOHAMA - 3-19-5 - YOKOHAMA-SHI KANAGAWA-KEN 222-0033 - JAPAN - - 00-09-A5 (hex) HANSUNG ELETRONIC INDUSTRIES DEVELOPMENT CO., LTD - 0009A5 (base 16) HANSUNG ELETRONIC INDUSTRIES DEVELOPMENT CO., LTD - HEUNGJIN BLDG 3F, #217-3 POI-DONG, KANGN - SEOUL 135-963 - KOREA, REPUBLIC OF - - 00-09-A6 (hex) Ignis Optics, Inc. - 0009A6 (base 16) Ignis Optics, Inc. - 482 W. San Carlos - San Jose California 95110 - UNITED STATES - - 00-09-A7 (hex) Bang & Olufsen A/S - 0009A7 (base 16) Bang & Olufsen A/S - Peter Bangs Vej 15 - Struer 7600 - DENMARK - - 00-09-A8 (hex) Eastmode Pte Ltd - 0009A8 (base 16) Eastmode Pte Ltd - 30 Loyang Way #07-06 - Loyang Industrial Estate - 508769 - SINGAPORE - - 00-09-A9 (hex) Ikanos Communications - 0009A9 (base 16) Ikanos Communications - 47709 Fremont Blvd - Fremont CA 94538 - UNITED STATES - - 00-09-AA (hex) Data Comm for Business, Inc. - 0009AA (base 16) Data Comm for Business, Inc. - 2949 County Road 1000 East - Dewey IL 61853 - UNITED STATES - - 00-09-AB (hex) Netcontrol Oy - 0009AB (base 16) Netcontrol Oy - Karvaamokuja 3 - Helsinki FIN 00380 - FINLAND - - 00-09-AC (hex) LANVOICE - 0009AC (base 16) LANVOICE - 1364-39 SeochoDong, #201 Jihun Bldg - Seocho-Gu - Seoul 137-072 - KOREA, REPUBLIC OF - - 00-09-AD (hex) HYUNDAI SYSCOMM, INC. - 0009AD (base 16) HYUNDAI SYSCOMM, INC. - SAN 136-1, AMI-RI, BUBAL-EUB - ICHON KYOUNGKI-DO 467-701 - KOREA, REPUBLIC OF - - 00-09-AE (hex) OKANO ELECTRIC CO.,LTD - 0009AE (base 16) OKANO ELECTRIC CO.,LTD - 2-8-18 KANAYAMA-CHO - HIGASHIKURUME TOKYO 203-0003 - JAPAN - - 00-09-AF (hex) e-generis - 0009AF (base 16) e-generis - 13 rue du chene germain - cesson sevigne 35510 - FRANCE - - 00-09-B0 (hex) Onkyo Corporation - 0009B0 (base 16) Onkyo Corporation - 2-1 Nisshin-cho - Neyagawa Osaka 5728540 - JAPAN - - 00-09-B1 (hex) Kanematsu Electronics, Ltd. - 0009B1 (base 16) Kanematsu Electronics, Ltd. - 17-5, Kyobashi 2-chome - Chuo-ku Tokyo 104-8338 - JAPAN - - 00-09-B2 (hex) L&F Inc. - 0009B2 (base 16) L&F Inc. - 4-2-9 - TOKUMARU - ITABASHI-KU Tokyo 175-0083 - JAPAN - - 00-09-B3 (hex) MCM Systems Ltd - 0009B3 (base 16) MCM Systems Ltd - Kolomban 9F - Ankaran Slovenija 6280 - SLOVENIA - - 00-09-B4 (hex) KISAN TELECOM CO., LTD. - 0009B4 (base 16) KISAN TELECOM CO., LTD. - 9F, Teawon Bldg., 65 Bangyi-Dong - Songpa-Gu Seoul 138-828 - KOREA, REPUBLIC OF - - 00-09-B5 (hex) 3J Tech. Co., Ltd. - 0009B5 (base 16) 3J Tech. Co., Ltd. - 342 Fushing N. Rd., 2F, Taipei, Taiwan - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-09-B6 (hex) CISCO SYSTEMS, INC. - 0009B6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-B7 (hex) CISCO SYSTEMS, INC. - 0009B7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-B8 (hex) Entise Systems - 0009B8 (base 16) Entise Systems - 10095 Judy Avenue - Cupertino CA 95014 - UNITED STATES - - 00-09-B9 (hex) Action Imaging Solutions - 0009B9 (base 16) Action Imaging Solutions - Kings Hall, St Ives Business Park - St Ives - Huntingdon Cambridgeshire PE27 4WY - UNITED KINGDOM - - 00-09-BA (hex) MAKU Informationstechik GmbH - 0009BA (base 16) MAKU Informationstechik GmbH - Gewerbehofstraße 7 - Essen NRW 45145 - GERMANY - - 00-09-BB (hex) MathStar, Inc. - 0009BB (base 16) MathStar, Inc. - 5900 Green Oak Drive - Minneapolis MN 55343 - UNITED STATES - - 00-09-BC (hex) Digital Safety Technologies, Inc - 0009BC (base 16) Digital Safety Technologies, Inc - 511 Davis Dr. - Suite 300 - Morrisville NC 27560 - UNITED STATES - - 00-09-BD (hex) Epygi Technologies, Ltd. - 0009BD (base 16) Epygi Technologies, Ltd. - 5040 Addison Circle - Suite 225 - Addison Texas 75001 - UNITED STATES - - 00-09-BE (hex) Mamiya-OP Co.,Ltd. - 0009BE (base 16) Mamiya-OP Co.,Ltd. - 3-23-10, Negishi Minami-ku - Saitama-shi Saitama 336-8581 - JAPAN - - 00-09-BF (hex) Nintendo Co., Ltd. - 0009BF (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-09-C0 (hex) 6WIND - 0009C0 (base 16) 6WIND - 1, place Charles de Gaulle - Montigny-le-Bretonneux 78180 - FRANCE - - 00-09-C1 (hex) PROCES-DATA A/S - 0009C1 (base 16) PROCES-DATA A/S - Navervej 8 - Silkeborg DK-8600 - DENMARK - - 00-09-C2 (hex) Onity, Inc. - 0009C2 (base 16) Onity, Inc. - 2232 Northmont Parkway - Duluth GA 30096 - UNITED STATES - - 00-09-C3 (hex) NETAS - 0009C3 (base 16) NETAS - Alemdag Cad. No 171 - UMRANIYE - ISTANBUL 81244 - TURKEY - - 00-09-C4 (hex) Medicore Co., Ltd - 0009C4 (base 16) Medicore Co., Ltd - 72-3 5th Fl., Luna Bldg, Chungdam-dong - Kangnam-gu - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-09-C5 (hex) KINGENE Technology Corporation - 0009C5 (base 16) KINGENE Technology Corporation - 7F, No. 144, Minchuan E. Rd. Sec. 3 - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-09-C6 (hex) Visionics Corporation - 0009C6 (base 16) Visionics Corporation - 5600 Rowland Road - Suite 205 - Minnetonka MN 55343 - UNITED STATES - - 00-09-C7 (hex) Movistec - 0009C7 (base 16) Movistec - 110-5 Maryoung -ri Seosu-myun - Kunsan Chonbuk 573-940 - KOREA, REPUBLIC OF - - 00-09-C8 (hex) SINAGAWA TSUSHIN KEISOU SERVICE - 0009C8 (base 16) SINAGAWA TSUSHIN KEISOU SERVICE - 13-5 Fuke , Sumiyoshi , Onahama - Iwaki City Fukushima Prefecture 971-8124 - JAPAN - - 00-09-C9 (hex) BlueWINC Co., Ltd. - 0009C9 (base 16) BlueWINC Co., Ltd. - 401 Korea Design Center - 344-1 Yatap1-dong, Bundang-gu - Seongnam City Kyonggiæo 463-828 - KOREA, REPUBLIC OF - - 00-09-CA (hex) iMaxNetworks(Shenzhen)Limited. - 0009CA (base 16) iMaxNetworks(Shenzhen)Limited. - 4/B,South Bldg of 29th,South District of - Shenzhen Hi-Tech Industrial Park, Shenna - Shenzhen GuangDong 518057 - CHINA - - 00-09-CB (hex) HBrain - 0009CB (base 16) HBrain - #705 Kwanglim Bldg 179 KumiDong - Bundang Gu - Seongnam GyeonggiDo 463-810 - KOREA, REPUBLIC OF - - 00-09-CC (hex) Moog GmbH - 0009CC (base 16) Moog GmbH - Hanns-Klemm-Str. 28 - Boeblingen D-71034 - GERMANY - - 00-09-CD (hex) HUDSON SOFT CO.,LTD. - 0009CD (base 16) HUDSON SOFT CO.,LTD. - C62,Geijutsu-no-mori - 3-chome,Minami-ku - Sapporo Hokkaido 005-0864 - JAPAN - - 00-09-CE (hex) SpaceBridge Semiconductor Corp. - 0009CE (base 16) SpaceBridge Semiconductor Corp. - 115 rue Champlain - Hull Quebec J8X3R1 - CANADA - - 00-09-CF (hex) iAd GmbH - 0009CF (base 16) iAd GmbH - Unterschlauersbacher Hauptstraße 10 - Grosshabersdorf Bavaria 90613 - GERMANY - - 00-09-D0 (hex) Solacom Technologies Inc. - 0009D0 (base 16) Solacom Technologies Inc. - 80 Jean-Proulx - Gatineau Quebec J8Z 1W1 - CANADA - - 00-09-D1 (hex) SERANOA NETWORKS INC - 0009D1 (base 16) SERANOA NETWORKS INC - CONCORD OFFICE CENTER - 2352 MAIN ST - CONCORD MA 01742 - UNITED STATES - - 00-09-D2 (hex) Mai Logic Inc. - 0009D2 (base 16) Mai Logic Inc. - 47697 Westinghouse Dr., Suite 200 - Fremont CA 94539 - UNITED STATES - - 00-09-D3 (hex) Western DataCom Co., Inc. - 0009D3 (base 16) Western DataCom Co., Inc. - 925-D Bassett Rd. - Westlake OH 44145 - UNITED STATES - - 00-09-D4 (hex) Transtech Networks - 0009D4 (base 16) Transtech Networks - 100 Wood Avenue - Suite 204 - Iselin NJ 08830 - UNITED STATES - - 00-09-D5 (hex) Signal Communication, Inc. - 0009D5 (base 16) Signal Communication, Inc. - 100 Wood Ave South - Suite 103 - Iselin NJ 08830 - UNITED STATES - - 00-09-D6 (hex) KNC One GmbH - 0009D6 (base 16) KNC One GmbH - Hohe Welle 10 B - Evessen Niedersachsen 38173 - GERMANY - - 00-09-D7 (hex) DC Security Products - 0009D7 (base 16) DC Security Products - One Lindsay Circle - San Francisco California 94124 - UNITED STATES - - 00-09-D8 (hex) Fält Communications AB - 0009D8 (base 16) Fält Communications AB - Kylgränd 6a - SE 906 20 UmeÃ¥ - SWEDEN - - 00-09-D9 (hex) Neoscale Systems, Inc - 0009D9 (base 16) Neoscale Systems, Inc - 1500 Mc Candless Drive - Milpitas CA 95035 - UNITED STATES - - 00-09-DA (hex) Control Module Inc. - 0009DA (base 16) Control Module Inc. - 227 Brainard Road - Enfield CT 06082 - UNITED STATES - - 00-09-DB (hex) eSpace - 0009DB (base 16) eSpace - 9623 Simsbury Ct. - Twinsburg OH 44087-3220 - UNITED STATES - - 00-09-DC (hex) Galaxis Technology AG - 0009DC (base 16) Galaxis Technology AG - Steinmetzstraße 7 - P.O. Box 3364 - Lübeck Schleswig-Holstein 23556 - GERMANY - - 00-09-DD (hex) Mavin Technology Inc. - 0009DD (base 16) Mavin Technology Inc. - Room 305, Bldg. 52 No. 195-28 - Sec. 4 Chung-Hsing Rd. - Chutung, Hsinchu 310 - TAIWAN, PROVINCE OF CHINA - - 00-09-DE (hex) Samjin Information & Communications Co., Ltd. - 0009DE (base 16) Samjin Information & Communications Co., Ltd. - MajangMyun DukPyungRi 235-2 - Ichon KyongGi 467-812 - KOREA, REPUBLIC OF - - 00-09-DF (hex) Vestel Komunikasyon Sanayi ve Ticaret A.S. - 0009DF (base 16) Vestel Komunikasyon Sanayi ve Ticaret A.S. - Ege Serbest Bolgesi No:144/1 - Gaziemir - Izmir - 35410 - TURKEY - - 00-09-E0 (hex) XEMICS S.A. - 0009E0 (base 16) XEMICS S.A. - Rue de la Maladiere 71 - CH-2007 Neuchatel Neuchatel 2007 - SWITZERLAND - - 00-09-E1 (hex) Gemtek Technology Co., Ltd. - 0009E1 (base 16) Gemtek Technology Co., Ltd. - No.1 Jen Ai Road - Hukou Hsinchu 303 - TAIWAN, PROVINCE OF CHINA - - 00-09-E2 (hex) Sinbon Electronics Co., Ltd. - 0009E2 (base 16) Sinbon Electronics Co., Ltd. - 4F-13, No. 79, Sec 1, Hsin Tai Wu Rd. - Hsi-Chih, Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-09-E3 (hex) Angel Iglesias S.A. - 0009E3 (base 16) Angel Iglesias S.A. - Polígono 27 Martutene - San Sebastián Guipúzcoa 20014 - SPAIN - - 00-09-E4 (hex) K Tech Infosystem Inc. - 0009E4 (base 16) K Tech Infosystem Inc. - B-405, Bundang Techno-Park 148, Yatap-do - Seongnam Kyonggi-Do 464-070 - KOREA, REPUBLIC OF - - 00-09-E5 (hex) Hottinger Baldwin Messtechnik GmbH - 0009E5 (base 16) Hottinger Baldwin Messtechnik GmbH - Im Tiefen See 45 - Darmstadt Hessen 64293 - GERMANY - - 00-09-E6 (hex) Cyber Switching Inc. - 0009E6 (base 16) Cyber Switching Inc. - 1800 De La Cruz Blvd. - Santa Clara CA 95050 - UNITED STATES - - 00-09-E7 (hex) ADC Techonology - 0009E7 (base 16) ADC Techonology - Sakae Members Office Bld. 4-16-8, Sakae, - Nagoya Aichi 4600008 - JAPAN - - 00-09-E8 (hex) CISCO SYSTEMS, INC. - 0009E8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-E9 (hex) CISCO SYSTEMS, INC. - 0009E9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-09-EA (hex) YEM Inc. - 0009EA (base 16) YEM Inc. - 1-3-33 - Okata - Atsugi-shi Kanagawa 243-0021 - JAPAN - - 00-09-EB (hex) HuMANDATA LTD. - 0009EB (base 16) HuMANDATA LTD. - 1-2-10 - Nakahozumi - Ibaraki Osaka 567-0034 - JAPAN - - 00-09-EC (hex) Daktronics, Inc. - 0009EC (base 16) Daktronics, Inc. - 315 32nd Ave - Building #2 - Brookings SD 57006 - UNITED STATES - - 00-09-ED (hex) CipherOptics - 0009ED (base 16) CipherOptics - 701 Corporate Center Drive - Suite 150 - Raleigh North Carolina 27607 - UNITED STATES - - 00-09-EE (hex) MEIKYO ELECTRIC CO.,LTD - 0009EE (base 16) MEIKYO ELECTRIC CO.,LTD - 4-27-2 Higashiogu - Arakawa-ku Tokyo 116-0012 - JAPAN - - 00-09-EF (hex) Vocera Communications - 0009EF (base 16) Vocera Communications - 525 Race St. - Suite 150 - San Jose California 95126 - UNITED STATES - - 00-09-F0 (hex) Shimizu Technology Inc. - 0009F0 (base 16) Shimizu Technology Inc. - 15-6, No.107, Chung Shan Rd., Sec.1 - Hsin Chuan, Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 00-09-F1 (hex) Yamaki Electric Corporation - 0009F1 (base 16) Yamaki Electric Corporation - 3-7-22 Shimomeguro - Meguro-ku Tokyo 153-0064 - JAPAN - - 00-09-F2 (hex) Cohu, Inc., Electronics Division - 0009F2 (base 16) Cohu, Inc., Electronics Division - 3912 Calle Fortunada - San Diego CA 92123 - UNITED STATES - - 00-09-F3 (hex) WELL Communication Corp. - 0009F3 (base 16) WELL Communication Corp. - 11F, No.778, Chung Cheng Rd., Chung Ho C - Chung Ho 235 - TAIWAN, PROVINCE OF CHINA - - 00-09-F4 (hex) Alcon Laboratories, Inc. - 0009F4 (base 16) Alcon Laboratories, Inc. - 6201 South Freeway - Fort Worth Tx 76134 - UNITED STATES - - 00-09-F5 (hex) Emerson Network Power Co.,Ltd - 0009F5 (base 16) Emerson Network Power Co.,Ltd - 1/F,3/F Electric Building Huawei Base,Ba - Longgang,Shenzhen Municipality,People's - ShenZhen GuangDong 518029 - CHINA - - 00-09-F6 (hex) Shenzhen Eastern Digital Tech Ltd. - 0009F6 (base 16) Shenzhen Eastern Digital Tech Ltd. - Shenzhen Futian Chegongmiao Tairan - Technology Park 210 - 3C - Shenzhen Guangdong 518048 - CHINA - - 00-09-F7 (hex) SED, a division of Calian - 0009F7 (base 16) SED, a division of Calian - 18 Innnovation Boulevard - P.O. Box 1464 - Saskatoon Saskatchewan (SK) S7K 3P7 - CANADA - - 00-09-F8 (hex) UNIMO TECHNOLOGY CO., LTD. - 0009F8 (base 16) UNIMO TECHNOLOGY CO., LTD. - BANGBAE DONG 479-12 - SEOCHO-GU, - SEOUL 137-820 - KOREA, REPUBLIC OF - - 00-09-F9 (hex) ART JAPAN CO., LTD. - 0009F9 (base 16) ART JAPAN CO., LTD. - 322-7, Ichinotsubo, - Nakahara-ku - Kawasaki Kanagawa 211-0016 - JAPAN - - 00-09-FB (hex) Philips Patient Monitoring - 0009FB (base 16) Philips Patient Monitoring - Hewlett-Packard-Str.2 - Boeblingen 71034 - GERMANY - - 00-09-FC (hex) IPFLEX Inc. - 0009FC (base 16) IPFLEX Inc. - Mowa-Bldg 3F, 1-16-6 - Ebisu-nishi - Shibuya-ku Tokyo 150-0021 - JAPAN - - 00-09-FD (hex) Ubinetics Limited - 0009FD (base 16) Ubinetics Limited - Cambridge Technology Centre - Melbourn Hertfordshire SG8 6DP - UNITED KINGDOM - - 00-09-FE (hex) Daisy Technologies, Inc. - 0009FE (base 16) Daisy Technologies, Inc. - 1209 Orange Street - County of New Castle - City of Wilmington DE 19801 - UNITED STATES - - 00-09-FF (hex) X.net 2000 GmbH - 0009FF (base 16) X.net 2000 GmbH - Koenigsberger Str. 2c - Reinheim 64354 - GERMANY - - 00-0A-00 (hex) Mediatek Corp. - 000A00 (base 16) Mediatek Corp. - 8F, No 69-5, Sec.2, Chung Cheng East Rd. - Taipei 251 - TAIWAN, PROVINCE OF CHINA - - 00-0A-01 (hex) SOHOware, Inc. - 000A01 (base 16) SOHOware, Inc. - 3050 Coronado Drive - Santa Clara CA 95054 - UNITED STATES - - 00-0A-02 (hex) ANNSO CO., LTD. - 000A02 (base 16) ANNSO CO., LTD. - 5F, No. 100, Min-Chuan Road, Shing-Tien - Shing-Tien City Taipei Hsien Taiwan 221 - TAIWAN, PROVINCE OF CHINA - - 00-0A-03 (hex) ENDESA SERVICIOS, S.L. - 000A03 (base 16) ENDESA SERVICIOS, S.L. - AVGDA PARAL.LEL, 51 - BARCELONA 08004 - SPAIN - - 00-0A-04 (hex) 3Com Ltd - 000A04 (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-0A-05 (hex) Widax Corp. - 000A05 (base 16) Widax Corp. - 269 Stevens Street - Hyannis MA 02668 - UNITED STATES - - 00-0A-06 (hex) Teledex LLC - 000A06 (base 16) Teledex LLC - 6311 San Ignacio Avenue - San Jose CA 95119 - UNITED STATES - - 00-0A-07 (hex) WebWayOne Ltd - 000A07 (base 16) WebWayOne Ltd - 11 Kingfisher Court, - Hambridge Road - Newbury Berkshire RG14 5SJ - UNITED KINGDOM - - 00-0A-08 (hex) ALPINE ELECTRONICS, INC. - 000A08 (base 16) ALPINE ELECTRONICS, INC. - 20-1 Yoshima-Kogyodanchi - iwaki-city Fukushima 970-1192 - JAPAN - - 00-0A-09 (hex) TaraCom Integrated Products, Inc. - 000A09 (base 16) TaraCom Integrated Products, Inc. - 830 Stewart Dr. - Sunnyvale CA 94085 - UNITED STATES - - 00-0A-0A (hex) SUNIX Co., Ltd. - 000A0A (base 16) SUNIX Co., Ltd. - 3Fl., No. 76, Baugau Rd., - Shindian Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-0A-0B (hex) Sealevel Systems, Inc. - 000A0B (base 16) Sealevel Systems, Inc. - 155 Technology Place - Liberty SC 29657 - UNITED STATES - - 00-0A-0C (hex) Scientific Research Corporation - 000A0C (base 16) Scientific Research Corporation - 2300 Windy Ridge Parkway - Suite 400 South - Atlanta GA 30339 - UNITED STATES - - 00-0A-0D (hex) FCI Deutschland GmbH - 000A0D (base 16) FCI Deutschland GmbH - Holzhauser Strasse 175 - 13509 Berlin - GERMANY - - 00-0A-0E (hex) Invivo Research Inc. - 000A0E (base 16) Invivo Research Inc. - 12601 Research Parkway - Orlando Florida 32826 - UNITED STATES - - 00-0A-0F (hex) Ilryung Telesys, Inc - 000A0F (base 16) Ilryung Telesys, Inc - Ilryung bldg, 34-2, Cheonho-dong - Gangdong-gu - SEOUL 134-861 - KOREA, REPUBLIC OF - - 00-0A-10 (hex) FAST media integrations AG - 000A10 (base 16) FAST media integrations AG - Schöngrund 26 - Rotkreuz Canton of Zug 6343 - SWITZERLAND - - 00-0A-11 (hex) ExPet Technologies, Inc - 000A11 (base 16) ExPet Technologies, Inc - 6F, Kyonggi Small Business Center - #111-8, Iui-dong, Paldal-gu, - Suwon, Kyonggi-do, 442-270 442-770 - KOREA, REPUBLIC OF - - 00-0A-12 (hex) Azylex Technology, Inc - 000A12 (base 16) Azylex Technology, Inc - 7-2Fl., No. 738 Chung Cheng Road, - Chung Ho City Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-0A-13 (hex) Honeywell Video Systems - 000A13 (base 16) Honeywell Video Systems - 6554 176 Street - Surrey BC V3S 4G5 - CANADA - - 00-0A-14 (hex) TECO a.s. - 000A14 (base 16) TECO a.s. - Havlickova 260 - KOLIN CZ 280 58 - CZECH REPUBLIC - - 00-0A-15 (hex) Silicon Data, Inc - 000A15 (base 16) Silicon Data, Inc - 4699 Old Ironsides Dr., #150 - Santa Clara CA 95054 - UNITED STATES - - 00-0A-16 (hex) Lassen Research - 000A16 (base 16) Lassen Research - 31695 Forward Road - Manton CA 96059 - UNITED STATES - - 00-0A-17 (hex) NESTAR COMMUNICATIONS, INC - 000A17 (base 16) NESTAR COMMUNICATIONS, INC - No.6,19 Lane Bade Road - HSINCHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-0A-18 (hex) Vichel Inc. - 000A18 (base 16) Vichel Inc. - 3F Jang Bldg. 92-6 Yangjae-dong, Secho-g - Seoul 137-130 - KOREA, REPUBLIC OF - - 00-0A-19 (hex) Valere Power, Inc. - 000A19 (base 16) Valere Power, Inc. - 661 N. Plano Rd. - Richardson Texas 75081 - UNITED STATES - - 00-0A-1A (hex) Imerge Ltd - 000A1A (base 16) Imerge Ltd - Unit 6, Bar Hill Business Park - Saxon Way - Bar Hill Cambridge CB3 8SL - UNITED KINGDOM - - 00-0A-1B (hex) Stream Labs - 000A1B (base 16) Stream Labs - Leninskie gori 1, bild 77 - Moskow 119992 - RUSSIAN FEDERATION - - 00-0A-1C (hex) Bridge Information Co., Ltd. - 000A1C (base 16) Bridge Information Co., Ltd. - No.3, Lane 106, Wu-Kung 2 Rd., - Wu-Ku Ind. Park, - Taipei 248 - TAIWAN, PROVINCE OF CHINA - - 00-0A-1D (hex) Optical Communications Products Inc. - 000A1D (base 16) Optical Communications Products Inc. - 20961 Knapp St. - Chatsworth CA 91311 - UNITED STATES - - 00-0A-1E (hex) Red-M Products Limited - 000A1E (base 16) Red-M Products Limited - Neptune House - Mercury Park, Wycombe Lane - Wooburn Green Buckinghamshire HP10 0HH - UNITED KINGDOM - - 00-0A-1F (hex) ART WARE Telecommunication Co., Ltd. - 000A1F (base 16) ART WARE Telecommunication Co., Ltd. - 806 Ace Techno Tower #1, 197-17 - Guro-dong, Guro-Gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-0A-20 (hex) SVA Networks, Inc. - 000A20 (base 16) SVA Networks, Inc. - 840 F Ave., Suite 104 - Plano TX 75074 - UNITED STATES - - 00-0A-21 (hex) Integra Telecom Co. Ltd - 000A21 (base 16) Integra Telecom Co. Ltd - 7th floor Hwayoung Bld. 112-2 - Karak-dong Sonpa-gu - Seoul - KOREA, REPUBLIC OF - - 00-0A-22 (hex) Amperion Inc - 000A22 (base 16) Amperion Inc - 250 Apollo Drive - Chelmsford MA 01824 - UNITED STATES - - 00-0A-23 (hex) Parama Networks Inc - 000A23 (base 16) Parama Networks Inc - 1955 The Alameda - San Jose CA 95126 - UNITED STATES - - 00-0A-24 (hex) Octave Communications - 000A24 (base 16) Octave Communications - 85 Northwest Boulevard - Nashua NH 03063 - UNITED STATES - - 00-0A-25 (hex) CERAGON NETWORKS - 000A25 (base 16) CERAGON NETWORKS - 24 RAUEL WALLENBERG STREET - TEL-AVIV 96719 - ISRAEL - - 00-0A-26 (hex) CEIA S.p.A. - 000A26 (base 16) CEIA S.p.A. - Zona Industriale di Viciomaggio 54 - Arezzo AR 52040 - ITALY - - 00-0A-27 (hex) Apple - 000A27 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-0A-28 (hex) Motorola - 000A28 (base 16) Motorola - 600 N. US Hwy 45 - Libertyville IL 60048 - UNITED STATES - - 00-0A-29 (hex) Pan Dacom Networking AG - 000A29 (base 16) Pan Dacom Networking AG - Dreieich Plaza 1B - Dreieich Hessen D-63303 - GERMANY - - 00-0A-2A (hex) QSI Systems Inc. - 000A2A (base 16) QSI Systems Inc. - 7 Raymond Avenue - Building B, Unit 11 - Salem NH 03079 - UNITED STATES - - 00-0A-2B (hex) Etherstuff - 000A2B (base 16) Etherstuff - 208 W. Mimosa Circle - San Marcos TX 78666 - UNITED STATES - - 00-0A-2C (hex) Active Tchnology Corporation - 000A2C (base 16) Active Tchnology Corporation - 16-23, Shibaura 2-Chome, - Minato-ku, - Tokyo Tokyo 108-0023 - JAPAN - - 00-0A-2D (hex) Cabot Communications Limited - 000A2D (base 16) Cabot Communications Limited - Verona House - Filwood Road - Bristol Gloucestershire BS16 3RY - UNITED KINGDOM - - 00-0A-2E (hex) MAPLE NETWORKS CO., LTD - 000A2E (base 16) MAPLE NETWORKS CO., LTD - 602, Dongwha - 349-24, Shindaebang-Dong, Dongjak-Gu - SEOUL 156-010 - KOREA, REPUBLIC OF - - 00-0A-2F (hex) Artnix Inc. - 000A2F (base 16) Artnix Inc. - Chungjin B/D, 475-22 Bangbae, Seocho - Seoul 137-819 - KOREA, REPUBLIC OF - - 00-0A-30 (hex) Visteon Corporation - 000A30 (base 16) Visteon Corporation - One Village Center Drive - Van Buren Twp MI 48111 - UNITED STATES - - 00-0A-31 (hex) HCV Consulting - 000A31 (base 16) HCV Consulting - P O Box 3692 - Helensvale Town Centre 4212 - Queensland 4212 - AUSTRALIA - - 00-0A-32 (hex) Xsido Corporation - 000A32 (base 16) Xsido Corporation - 3F,2-8-13,Shiba-Daimon, - Minato-ku - Tokyo 105-0012 - JAPAN - - 00-0A-33 (hex) Emulex Corporation - 000A33 (base 16) Emulex Corporation - 2021 Opportunity Drive - Suite 1 - Roseville CA 95678 - UNITED STATES - - 00-0A-34 (hex) Identicard Systems Incorporated - 000A34 (base 16) Identicard Systems Incorporated - 40 Citation Lane - Lancaster Pennsylvania 17606 - UNITED STATES - - 00-0A-35 (hex) Xilinx - 000A35 (base 16) Xilinx - 2100 Logic Drive - San Jose CA 94110 - UNITED STATES - - 00-0A-36 (hex) Synelec Telecom Multimedia - 000A36 (base 16) Synelec Telecom Multimedia - Zone Industrielle - Saint Sernin sur Rance Aveyron F-12380 - FRANCE - - 00-0A-37 (hex) Procera Networks, Inc. - 000A37 (base 16) Procera Networks, Inc. - 1299 Orleans Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-0A-38 (hex) Apani Networks - 000A38 (base 16) Apani Networks - 1800 E. Imperial Hwy - Suite 210 - Brea CA 92821 - UNITED STATES - - 00-0A-39 (hex) LoPA Information Technology - 000A39 (base 16) LoPA Information Technology - 710-9, Dae Lim 3-Dong - Young Deung po-gu Seoul, Korea 150-814 - KOREA, REPUBLIC OF - - 00-0A-3A (hex) J-THREE INTERNATIONAL Holding Co., Ltd. - 000A3A (base 16) J-THREE INTERNATIONAL Holding Co., Ltd. - No. 1, Yu-3 Rd., Youth Industrial Park - Yang-mei, Taoyuan Hsien 326 - TAIWAN, PROVINCE OF CHINA - - 00-0A-3B (hex) GCT Semiconductor, Inc - 000A3B (base 16) GCT Semiconductor, Inc - 2121 Ringwood Avenue - San Jose CA 95131 - UNITED STATES - - 00-0A-3C (hex) Enerpoint Ltd. - 000A3C (base 16) Enerpoint Ltd. - Kaivopuistontie 33 - Rauma 26100 - FINLAND - - 00-0A-3D (hex) Elo Sistemas Eletronicos S.A. - 000A3D (base 16) Elo Sistemas Eletronicos S.A. - Rua Edu Chaves, 547 - Porto Alegre RS 90.240-620 - BRAZIL - - 00-0A-3E (hex) EADS Telecom - 000A3E (base 16) EADS Telecom - Landshuter Strasse 26 - Munich Bavaria 85716 - GERMANY - - 00-0A-3F (hex) Data East Corporation - 000A3F (base 16) Data East Corporation - 4-41-10 Minami-Ogikubo - Suginami-ku TOKYO 167-0052 - JAPAN - - 00-0A-40 (hex) Crown Audio -- Harmanm International - 000A40 (base 16) Crown Audio -- Harmanm International - 1718 W. Mishawaka Rd - Elkhart IN 46517 - UNITED STATES - - 00-0A-41 (hex) CISCO SYSTEMS, INC. - 000A41 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-42 (hex) CISCO SYSTEMS, INC. - 000A42 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-43 (hex) Chunghwa Telecom Co., Ltd. - 000A43 (base 16) Chunghwa Telecom Co., Ltd. - 12, Lane 551, Min-Tsu Road - Sec. 5 Yang-Mei, - Taoyuan 326 - TAIWAN, PROVINCE OF CHINA - - 00-0A-44 (hex) Avery Dennison Deutschland GmbH - 000A44 (base 16) Avery Dennison Deutschland GmbH - Ohmstraße 3 - Eching 85386 - GERMANY - - 00-0A-45 (hex) Audio-Technica Corp. - 000A45 (base 16) Audio-Technica Corp. - Naruse 1,348 - Machida Tokyo 194-8566 - JAPAN - - 00-0A-46 (hex) ARO WELDING TECHNOLOGIES SAS - 000A46 (base 16) ARO WELDING TECHNOLOGIES SAS - 1, avenue de Tours - Chateau du Loir sarthe 72500 - FRANCE - - 00-0A-47 (hex) Allied Vision Technologies - 000A47 (base 16) Allied Vision Technologies - Taschenweg 2a - Stadtroda Thüringen 07646 - GERMANY - - 00-0A-48 (hex) Albatron Technology - 000A48 (base 16) Albatron Technology - 6F, No 716, Chung Cheng, - Chung-Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-0A-49 (hex) F5 Networks, Inc. - 000A49 (base 16) F5 Networks, Inc. - 401 Elliott Ave. W. - Seattle WA 98119 - UNITED STATES - - 00-0A-4A (hex) Targa Systems Ltd. - 000A4A (base 16) Targa Systems Ltd. - 1905 Grandtech Centre, - 8 On Ping St. Siu Lek Yuen - Shatin N.T. - HONG KONG - - 00-0A-4B (hex) DataPower Technology, Inc. - 000A4B (base 16) DataPower Technology, Inc. - One Alewife Center - Cambridge MA 02140 - UNITED STATES - - 00-0A-4C (hex) Molecular Devices Corporation - 000A4C (base 16) Molecular Devices Corporation - 1311 Orleans Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-0A-4D (hex) Noritz Corporation - 000A4D (base 16) Noritz Corporation - 5 Minami-Futami, - Futami-cho, - Akashi-shi Hyogo 674-0093 - JAPAN - - 00-0A-4E (hex) UNITEK Electronics INC. - 000A4E (base 16) UNITEK Electronics INC. - 1-18-4 - Ohmori-kita - Ohta-ku Tokyo 143-0016 - JAPAN - - 00-0A-4F (hex) Brain Boxes Limited - 000A4F (base 16) Brain Boxes Limited - Unit 3c, Wavertree Boulevard South - Wavertree Technology Park - Liverpool Merseyside L7 9PF - UNITED KINGDOM - - 00-0A-50 (hex) REMOTEK CORPORATION - 000A50 (base 16) REMOTEK CORPORATION - 6F-6, No 77, Sec 1, HSIN TAI WU ROAD, - HSI-CHIH TAIPEI HSIEN 221 - TAIWAN, PROVINCE OF CHINA - - 00-0A-51 (hex) GyroSignal Technology Co., Ltd. - 000A51 (base 16) GyroSignal Technology Co., Ltd. - 5F,No. 77,Lide St. - Zhonghe City Taipei County 23556 - TAIWAN, PROVINCE OF CHINA - - 00-0A-52 (hex) AsiaRF Ltd. - 000A52 (base 16) AsiaRF Ltd. - 3F, No.176, Yongzhen Road - Yonghe District - New Taipei City Taipei 234 - TAIWAN, PROVINCE OF CHINA - - 00-0A-53 (hex) Intronics, Incorporated - 000A53 (base 16) Intronics, Incorporated - 2020 Lafayette Blvd. - Fredericksburg Virginia 22401 - UNITED STATES - - 00-0A-54 (hex) Laguna Hills, Inc. - 000A54 (base 16) Laguna Hills, Inc. - 3-5-2 - Kojimachi - Chiyoda-ku Tokyo 102-0083 - JAPAN - - 00-0A-55 (hex) MARKEM Corporation - 000A55 (base 16) MARKEM Corporation - 150 Congress Street - Keene NH 03431 - UNITED STATES - - 00-0A-56 (hex) HITACHI Maxell Ltd. - 000A56 (base 16) HITACHI Maxell Ltd. - 6-20-1 Kinunodai - Yawara-mura, Tsukuba-gun IBARAKI 300-2496 - JAPAN - - 00-0A-57 (hex) Hewlett-Packard Company - Standards - 000A57 (base 16) Hewlett-Packard Company - Standards - 10955 Tantau Avenue - Mailstop 4138 - Cupertino CA 95014 - UNITED STATES - - 00-0A-58 (hex) Freyer & Siegel Elektronik GmbH & Co. KG - 000A58 (base 16) Freyer & Siegel Elektronik GmbH & Co. KG - Neuendorfstraße 18 b - Hennigsdorf Brandenburg 16761 - GERMANY - - 00-0A-59 (hex) HW server - 000A59 (base 16) HW server - Italska 15 - Prague 2 Czech Republic 120 00 - CZECH REPUBLIC - - 00-0A-5A (hex) GreenNET Technologies Co.,Ltd. - 000A5A (base 16) GreenNET Technologies Co.,Ltd. - No.10, Qiongyu Road,Sciences-based Indus - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-0A-5B (hex) Power-One as - 000A5B (base 16) Power-One as - P.O. Box 1543 - Drammen 3007 - NORWAY - - 00-0A-5C (hex) Carel s.p.a. - 000A5C (base 16) Carel s.p.a. - Via dell' Industria, 11 - Brugine Padova 35020 - ITALY - - 00-0A-5D (hex) FingerTec Worldwide Sdn Bhd - 000A5D (base 16) FingerTec Worldwide Sdn Bhd - No 6, 8 & 10 - Jalan BK 3/2 - Bandar Kinrara 47100 PUchong Selangor - MALAYSIA - - 00-0A-5E (hex) 3COM Corporation - 000A5E (base 16) 3COM Corporation - 5400 Bayfront Plaza - M/S 5119 - Santa Clara CA 95052-8145 - UNITED STATES - - 00-0A-5F (hex) almedio inc. - 000A5F (base 16) almedio inc. - 32-13, sakae-cho 2 chome - higashimurayama-shi tokyo 189-0013 - JAPAN - - 00-0A-60 (hex) Autostar Technology Pte Ltd - 000A60 (base 16) Autostar Technology Pte Ltd - Unit 04-10 TECHplace II - Singapore Singapore 569876 - SINGAPORE - - 00-0A-61 (hex) Cellinx Systems Inc. - 000A61 (base 16) Cellinx Systems Inc. - 408 Woosung Character199 officetel - 467-24 dogok-dong kangnam-gu - Seoul 135-856 - KOREA, REPUBLIC OF - - 00-0A-62 (hex) Crinis Networks, Inc. - 000A62 (base 16) Crinis Networks, Inc. - 2099 N. Collins Blvd, Suite 200 - Richardson TX 75080 - UNITED STATES - - 00-0A-63 (hex) DHD GmbH - 000A63 (base 16) DHD GmbH - Haferkornstrasse 5 - Leipzig Sachsen 04129 - GERMANY - - 00-0A-64 (hex) Eracom Technologies - 000A64 (base 16) Eracom Technologies - 28 Greg Chappell Drive - Burleigh Heads Qld 4220 - AUSTRALIA - - 00-0A-65 (hex) GentechMedia.co.,ltd. - 000A65 (base 16) GentechMedia.co.,ltd. - solvit bldg 2f, 402-8, yangjae-don, - seocho-gu, seoul 137-899 - KOREA, REPUBLIC OF - - 00-0A-66 (hex) MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. - 000A66 (base 16) MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. - 1-4-13 OOYODONAKA,KITA-KU - OSAKA 531-0076 - JAPAN - - 00-0A-67 (hex) OngCorp - 000A67 (base 16) OngCorp - 481 Hackensack Ave. - Hackensack NJ 07601 - UNITED STATES - - 00-0A-68 (hex) SolarFlare Communications, Inc. - 000A68 (base 16) SolarFlare Communications, Inc. - 9501 Jeronimo - Suite 100 - Irvine CA 92618 - UNITED STATES - - 00-0A-69 (hex) SUNNY bell Technology Co., Ltd. - 000A69 (base 16) SUNNY bell Technology Co., Ltd. - #502 BUWON B/D 107-45 BANPO-DONG - SEOCHO-KU - SEOUL 137-806 - KOREA, REPUBLIC OF - - 00-0A-6A (hex) SVM Microwaves s.r.o. - 000A6A (base 16) SVM Microwaves s.r.o. - U Mrazovky 5 - Praha 5 15000 - CZECH REPUBLIC - - 00-0A-6B (hex) Tadiran Telecom Business Systems LTD - 000A6B (base 16) Tadiran Telecom Business Systems LTD - 18 Hasivim St. - P.O.Box 450 - Petach Tikva 49105 - ISRAEL - - 00-0A-6C (hex) Walchem Corporation - 000A6C (base 16) Walchem Corporation - 5 Boynton Road - Holliston MA 01746 - UNITED STATES - - 00-0A-6D (hex) EKS Elektronikservice GmbH - 000A6D (base 16) EKS Elektronikservice GmbH - Enzstr. 9 - Kornwestheim Baden-Württemberg 70806 - GERMANY - - 00-0A-6E (hex) Harmonic, Inc - 000A6E (base 16) Harmonic, Inc - 4300 North First Street - San Jose CA 95134 - UNITED STATES - - 00-0A-6F (hex) ZyFLEX Technologies Inc - 000A6F (base 16) ZyFLEX Technologies Inc - 2Fl. No. 58 Park Ave. II - S.B.I.P., Hsinchu 30077 - TAIWAN, PROVINCE OF CHINA - - 00-0A-70 (hex) MPLS Forum - 000A70 (base 16) MPLS Forum - 39355 California Street - Suite 307 - Fremont CA 94538 - UNITED STATES - - 00-0A-71 (hex) Avrio Technologies, Inc - 000A71 (base 16) Avrio Technologies, Inc - 2655 A Park Center Drive - Simi Valley CA 91356 - UNITED STATES - - 00-0A-72 (hex) STEC, INC. - 000A72 (base 16) STEC, INC. - 3001 Daimler Street - Santa Ana CA 92705 - UNITED STATES - - 00-0A-73 (hex) Scientific Atlanta - 000A73 (base 16) Scientific Atlanta - 5030 Sugarloaf Parkway - MS 5.2425 - Lawrenceville Ga 30042 - UNITED STATES - - 00-0A-74 (hex) Manticom Networks Inc. - 000A74 (base 16) Manticom Networks Inc. - 14016-C Sullyfield Circle - Chantilly VA 20151 - UNITED STATES - - 00-0A-75 (hex) Caterpillar, Inc - 000A75 (base 16) Caterpillar, Inc - Mailstop Location AC6130 - PO Box 610 - Mossville IL 61552-0610 - UNITED STATES - - 00-0A-76 (hex) Beida Jade Bird Huaguang Technology Co.,Ltd - 000A76 (base 16) Beida Jade Bird Huaguang Technology Co.,Ltd - No.207 Chengfu Road, Haidian District - Beijing 100871 - CHINA - - 00-0A-77 (hex) Bluewire Technologies LLC - 000A77 (base 16) Bluewire Technologies LLC - 420 N. O St. - Tulare Ca 93274 - UNITED STATES - - 00-0A-78 (hex) OLITEC - 000A78 (base 16) OLITEC - B.P. 592 - 87, rue Mac Mahon - NANCY cedex 54009 - FRANCE - - 00-0A-79 (hex) corega K.K - 000A79 (base 16) corega K.K - 1-19-20, Shinyokohama - Kouhoku-ku - Yokohama-city Kanagawa-ken 222-0033 - JAPAN - - 00-0A-7A (hex) Kyoritsu Electric Co., Ltd. - 000A7A (base 16) Kyoritsu Electric Co., Ltd. - 2-3-17 - Iwato-minami - Komae-shi Tokyo 201-0005 - JAPAN - - 00-0A-7B (hex) Cornelius Consult - 000A7B (base 16) Cornelius Consult - Am Siepen 17 - Bochum NRW 44803 - GERMANY - - 00-0A-7C (hex) Tecton Ltd - 000A7C (base 16) Tecton Ltd - Fishers Court - Fishers Pond - Eastleigh Hampshire SO50 7HG - UNITED KINGDOM - - 00-0A-7D (hex) Valo, Inc. - 000A7D (base 16) Valo, Inc. - 1351 Redwood Way - Petaluma CA 94954 - UNITED STATES - - 00-0A-7E (hex) The Advantage Group - 000A7E (base 16) The Advantage Group - 1610 Des Peres Road - Suite 370 - St. Louis MO 63131 - UNITED STATES - - 00-0A-7F (hex) Teradon Industries, Inc - 000A7F (base 16) Teradon Industries, Inc - 7500 2nd ST NW - Albuquerque NM 87120 - UNITED STATES - - 00-0A-80 (hex) Telkonet Inc. - 000A80 (base 16) Telkonet Inc. - 20374 Seneca Meadows Pkwy - Germantown MD 20786 - UNITED STATES - - 00-0A-81 (hex) TEIMA Audiotex S.L. - 000A81 (base 16) TEIMA Audiotex S.L. - C/ Tirvia, 6, local B - Madrid 28040 - SPAIN - - 00-0A-82 (hex) TATSUTA SYSTEM ELECTRONICS CO.,LTD. - 000A82 (base 16) TATSUTA SYSTEM ELECTRONICS CO.,LTD. - IWATATYOU2-3-1 - HIGASHIOOSAKA-SHI OOSAKA-FU 578-8585 - JAPAN - - 00-0A-83 (hex) SALTO SYSTEMS S.L. - 000A83 (base 16) SALTO SYSTEMS S.L. - Arkotz, 9 - Polígonoo Lanbarren Oiartzun 20180 - SPAIN - - 00-0A-84 (hex) Rainsun Enterprise Co., Ltd. - 000A84 (base 16) Rainsun Enterprise Co., Ltd. - No.14-3 , Lane 235, Ho-Chen Road - BaoCiao Road - ShinDian City TAIPEI 231 - TAIWAN, PROVINCE OF CHINA - - 00-0A-85 (hex) PLAT'C2,Inc - 000A85 (base 16) PLAT'C2,Inc - 2-3-6 SOTOKANDA - CHIYODA-KU TOKYO 101-0021 - JAPAN - - 00-0A-86 (hex) Lenze - 000A86 (base 16) Lenze - PO box 101352 - Hameln Lower Saxony 31763 - GERMANY - - 00-0A-87 (hex) Integrated Micromachines Inc. - 000A87 (base 16) Integrated Micromachines Inc. - 1400 S. Shamrock Ave. - Monrovia CA 91016 - UNITED STATES - - 00-0A-88 (hex) InCypher S.A. - 000A88 (base 16) InCypher S.A. - 18 rue de l'Eau - Luxembourg 1449 - LUXEMBOURG - - 00-0A-89 (hex) Creval Systems, Inc. - 000A89 (base 16) Creval Systems, Inc. - 2F,24-4,Sanwolgok-Dong,Sungbuk-Ku,Seoul, - Seoul 136-120 - KOREA, REPUBLIC OF - - 00-0A-8A (hex) CISCO SYSTEMS, INC. - 000A8A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-8B (hex) CISCO SYSTEMS, INC. - 000A8B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-8C (hex) Guardware Systems Ltd. - 000A8C (base 16) Guardware Systems Ltd. - Ulloi ut 102. - Budapest H-1089 - HUNGARY - - 00-0A-8D (hex) EUROTHERM LIMITED - 000A8D (base 16) EUROTHERM LIMITED - FARADAY CLOSE - DURRINGTON - WORTHING WEST SUSSEX BN13 3PL - UNITED KINGDOM - - 00-0A-8E (hex) Invacom Ltd - 000A8E (base 16) Invacom Ltd - Business and Technology Centre - Bessemer Drive - Stevenage Hertfordshire SG1 2DX - UNITED KINGDOM - - 00-0A-8F (hex) Aska International Inc. - 000A8F (base 16) Aska International Inc. - 306 Riverseven - 4-18 Haregi-Honmachi - Kochi 780-8088 - JAPAN - - 00-0A-90 (hex) Bayside Interactive, Inc. - 000A90 (base 16) Bayside Interactive, Inc. - 330 Biscayne Blvd. - Suite 801 - Miami FL 33132 - UNITED STATES - - 00-0A-91 (hex) HemoCue AB - 000A91 (base 16) HemoCue AB - Box 1204 - Ängelholm SkÃ¥ne län 26223 - SWEDEN - - 00-0A-92 (hex) Presonus Corporation - 000A92 (base 16) Presonus Corporation - 7257 Florida Blvd. - Baton Rouge Louisiana 70806 - UNITED STATES - - 00-0A-93 (hex) W2 Networks, Inc. - 000A93 (base 16) W2 Networks, Inc. - 5808 NW Lac Leman Drive - Issaquah Washington 98027 - UNITED STATES - - 00-0A-94 (hex) ShangHai cellink CO., LTD - 000A94 (base 16) ShangHai cellink CO., LTD - C3 MeiLong ZhongXin Industrial Park,No.1 - ShangHai 200237 - CHINA - - 00-0A-95 (hex) Apple - 000A95 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-0A-96 (hex) MEWTEL TECHNOLOGY INC. - 000A96 (base 16) MEWTEL TECHNOLOGY INC. - E15FL. IT VENTURE TOWER - 78 KARAK-DONG, SONGPA-GU - SEOUL 138-803 - KOREA, REPUBLIC OF - - 00-0A-97 (hex) SONICblue, Inc. - 000A97 (base 16) SONICblue, Inc. - 2841 Mission College Blvd. - Santa Clara CA 95054 - UNITED STATES - - 00-0A-98 (hex) M+F Gwinner GmbH & Co - 000A98 (base 16) M+F Gwinner GmbH & Co - Weidenbaumsweg 91 a - Hamburg 21029 - GERMANY - - 00-0A-99 (hex) Calamp Wireless Networks Inc - 000A99 (base 16) Calamp Wireless Networks Inc - 101-5540 Ferrier Street - Town of Mount-Royal Quebec H4P 1M2 - CANADA - - 00-0A-9A (hex) Aiptek International Inc - 000A9A (base 16) Aiptek International Inc - No 5-1 Innovation Rd 1 - Science-Based Industrial Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0A-9B (hex) TB Group Inc - 000A9B (base 16) TB Group Inc - 4F NREG Hongo 3-chome Bldg., 3-26-6, Hngo, Bunkyo-ku, - Tokyo 113-003 - JAPAN - - 00-0A-9C (hex) Server Technology, Inc. - 000A9C (base 16) Server Technology, Inc. - 1040 Sandhill Drive - Reno Nevada 89521 - UNITED STATES - - 00-0A-9D (hex) King Young Technology Co. Ltd. - 000A9D (base 16) King Young Technology Co. Ltd. - 1Fl., No. 9, Lane 26, Gangchi Rd., Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0A-9E (hex) BroadWeb Corportation - 000A9E (base 16) BroadWeb Corportation - 3F, 24-1, Industry East Rd., IV, - Science Based, Industrial Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0A-9F (hex) Pannaway Technologies, Inc. - 000A9F (base 16) Pannaway Technologies, Inc. - 215 Commerce Way - Portsmouth NH 03801 - UNITED STATES - - 00-0A-A0 (hex) Cedar Point Communications - 000AA0 (base 16) Cedar Point Communications - 16 Route 111, Bldg 3 - Derry NH 03038 - UNITED STATES - - 00-0A-A1 (hex) V V S Limited - 000AA1 (base 16) V V S Limited - HPIC, 1. Ainslie Road , - Hillington - Glasgow Scotland G52 4RU - UNITED KINGDOM - - 00-0A-A2 (hex) SYSTEK INC. - 000AA2 (base 16) SYSTEK INC. - JCOM BUILDING 402, OJEON-DONG 124-4, - UIWANG-SI GYUNGGI-DO 437-070 - KOREA, REPUBLIC OF - - 00-0A-A3 (hex) SHIMAFUJI ELECTRIC CO.,LTD. - 000AA3 (base 16) SHIMAFUJI ELECTRIC CO.,LTD. - Daihyaku-seimei Kamata Bldg.3F - 8-11-11 Nishikamata,Ota-ku - Tokyo 144-0051 - JAPAN - - 00-0A-A4 (hex) SHANGHAI SURVEILLANCE TECHNOLOGY CO,LTD - 000AA4 (base 16) SHANGHAI SURVEILLANCE TECHNOLOGY CO,LTD - FL.25A,NO.8 CHANGYANG ROAD - SHANGHAI 200082 - CHINA - - 00-0A-A5 (hex) MAXLINK INDUSTRIES LIMITED - 000AA5 (base 16) MAXLINK INDUSTRIES LIMITED - 29A SHENZHEN SPECIAL ZONE - PRESS TOWER - SHENZHEN GUANGDONG 518009 - CHINA - - 00-0A-A6 (hex) Hochiki Corporation - 000AA6 (base 16) Hochiki Corporation - 246, TSURUMA - MACHIDA TOKYO 194-8577 - JAPAN - - 00-0A-A7 (hex) FEI Electron Optics - 000AA7 (base 16) FEI Electron Optics - Achtseweg Noord 5 - AAE 30 - Eindhoven 5651GG - NETHERLANDS - - 00-0A-A8 (hex) ePipe Pty. Ltd. - 000AA8 (base 16) ePipe Pty. Ltd. - P.O. Box 1428 - Toowong - Brisbane Queensland 4066 - AUSTRALIA - - 00-0A-A9 (hex) Brooks Automation GmbH - 000AA9 (base 16) Brooks Automation GmbH - Goeschwitzer Strasse 25 - Jena Thuringia 07745 - GERMANY - - 00-0A-AA (hex) AltiGen Communications Inc. - 000AAA (base 16) AltiGen Communications Inc. - 47427 Fremont Blvd. - Fremont CA 94538 - UNITED STATES - - 00-0A-AB (hex) Toyota Technical Development Corporation - 000AAB (base 16) Toyota Technical Development Corporation - 1-21, Imae, Hanamoto-cho - Toyota Aichi 470-0334 - JAPAN - - 00-0A-AC (hex) TerraTec Electronic GmbH - 000AAC (base 16) TerraTec Electronic GmbH - Herrenpfad 38 - Nettetal NRW 41334 - GERMANY - - 00-0A-AD (hex) Stargames Corporation - 000AAD (base 16) Stargames Corporation - 13 Sheridan Close - Milperra NSW 2031 - AUSTRALIA - - 00-0A-AE (hex) Rosemount Process Analytical - 000AAE (base 16) Rosemount Process Analytical - 6573A Cochran Rd. - Solon Ohio 44139-3922 - UNITED STATES - - 00-0A-AF (hex) Pipal Systems - 000AAF (base 16) Pipal Systems - 2903 Bunker Hill Lane - Suite 210 - Santa Clara CA 95054 - UNITED STATES - - 00-0A-B0 (hex) LOYTEC electronics GmbH - 000AB0 (base 16) LOYTEC electronics GmbH - Stolzenthalergasse 24/3 - Vienna Wien 1080 - AUSTRIA - - 00-0A-B1 (hex) GENETEC Corporation - 000AB1 (base 16) GENETEC Corporation - BYGS Shinjyuku Bldg. 5F - 2-19-1 Shinjyuku - Shinjuku-ku Tokyo 162-0022 - JAPAN - - 00-0A-B2 (hex) Fresnel Wireless Systems - 000AB2 (base 16) Fresnel Wireless Systems - 1333 Gateway Drive - Suite 1007 - Melbourne FL 32901 - UNITED STATES - - 00-0A-B3 (hex) Fa. GIRA - 000AB3 (base 16) Fa. GIRA - Dahlienstraße - Radevormwald Nordrhein-Westfalen 42477 - GERMANY - - 00-0A-B4 (hex) ETIC Telecommunications - 000AB4 (base 16) ETIC Telecommunications - 13, chemin du vieux-chene ZIRST - MEYLAN Isere 38240 - FRANCE - - 00-0A-B5 (hex) Digital Electronic Network - 000AB5 (base 16) Digital Electronic Network - 8 rue du sacré coeur - Saint Laurent sur Sevre Vendee 85290 - FRANCE - - 00-0A-B6 (hex) COMPUNETIX, INC - 000AB6 (base 16) COMPUNETIX, INC - 2420 MOSSIDE BLVD. - MONROEVILLE PA 15146 - UNITED STATES - - 00-0A-B7 (hex) CISCO SYSTEMS, INC. - 000AB7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-B8 (hex) CISCO SYSTEMS, INC. - 000AB8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-B9 (hex) Astera Technologies Corp. - 000AB9 (base 16) Astera Technologies Corp. - 2380 Waverley Street - Palo Alto CA 94301 - UNITED STATES - - 00-0A-BA (hex) Arcon Technology Limited - 000ABA (base 16) Arcon Technology Limited - Rm. 3711-12, 37/F., Cable TV Tower , - 9 Hoi Shing Rd., Tsuen Wan , N.T - Hong Kong - CHINA - - 00-0A-BB (hex) Taiwan Secom Co,. Ltd - 000ABB (base 16) Taiwan Secom Co,. Ltd - 13F, 108, Sec1, Shin-Tai 5th Road - Hsi-Chih Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-0A-BC (hex) Seabridge Ltd. - 000ABC (base 16) Seabridge Ltd. - 3 Hanagar St. - Neve-Neeman B' - Hod-Hasharon Israel 45241 - ISRAEL - - 00-0A-BD (hex) Rupprecht & Patashnick Co. - 000ABD (base 16) Rupprecht & Patashnick Co. - 25 Corporate Circle - Albany NY 12203 - UNITED STATES - - 00-0A-BE (hex) OPNET Technologies CO., LTD. - 000ABE (base 16) OPNET Technologies CO., LTD. - 3F, NO.5, Industry E. Rd. IX, Science-Ba - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0A-BF (hex) HIROTA SS - 000ABF (base 16) HIROTA SS - Matukawa-Kougyoudanchi - Suzaka-shi Nagano 382-0005 - JAPAN - - 00-0A-C0 (hex) Fuyoh Video Industry CO., LTD. - 000AC0 (base 16) Fuyoh Video Industry CO., LTD. - 7-25 Higashi Kibogaoka - Asahi-ku - Yokohama-shi Kanagawa-ken 246-0008 - JAPAN - - 00-0A-C1 (hex) Futuretel - 000AC1 (base 16) Futuretel - 21580 Stevens Creek Blvd, Suite 208 - Cupertino CA 95014 - UNITED STATES - - 00-0A-C2 (hex) FiberHome Telecommunication Technologies CO.,LTD - 000AC2 (base 16) FiberHome Telecommunication Technologies CO.,LTD - No.88 YouKeyuan Road,Hongshan District,W - Wuhan Hubei 430074 - CHINA - - 00-0A-C3 (hex) eM Technics Co., Ltd. - 000AC3 (base 16) eM Technics Co., Ltd. - 7F., IT Venture Tower., 78, - Garakbon-Dong, Songpa-Gu - Seoul 138-803 - KOREA, REPUBLIC OF - - 00-0A-C4 (hex) Daewoo Teletech Co., Ltd - 000AC4 (base 16) Daewoo Teletech Co., Ltd - 265-3, Seohyeon, Bundang - Seongnam Gyeonggi 463-769 - KOREA, REPUBLIC OF - - 00-0A-C5 (hex) Color Kinetics - 000AC5 (base 16) Color Kinetics - 10 Milk Street - Suite 1100 - Boston Masachusetts 02108 - UNITED STATES - - 00-0A-C6 (hex) Overture Networks. - 000AC6 (base 16) Overture Networks. - 637 Davis Drive - Morrisville NC 27560 - UNITED STATES - - 00-0A-C7 (hex) Unication Group - 000AC7 (base 16) Unication Group - 3F., No. 6, Wu-Kung 5Rd., Hsinchuang Cit - Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 00-0A-C8 (hex) ZPSYS CO.,LTD. (Planning&Management) - 000AC8 (base 16) ZPSYS CO.,LTD. (Planning&Management) - 106 Ace Techno Tower1 - 197-17 Kuro-Dong - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-0A-C9 (hex) Zambeel Inc - 000AC9 (base 16) Zambeel Inc - 45700 Northport Loop East - Fremont CA 94538 - UNITED STATES - - 00-0A-CA (hex) YOKOYAMA SHOKAI CO.,Ltd. - 000ACA (base 16) YOKOYAMA SHOKAI CO.,Ltd. - 6-96 Matsumura - Kanazawa Ishikawa 920-0348 - JAPAN - - 00-0A-CB (hex) XPAK MSA Group - 000ACB (base 16) XPAK MSA Group - Care of: Molex Fiber Optics - 5224 Katrine Avenue - Downers Grove IL 60515 - UNITED STATES - - 00-0A-CC (hex) Winnow Networks, Inc. - 000ACC (base 16) Winnow Networks, Inc. - 701 Emerson Road - Suite 244 - St. Louis MO 63141 - UNITED STATES - - 00-0A-CD (hex) Sunrich Technology Limited - 000ACD (base 16) Sunrich Technology Limited - Unit 1301, Eastern Centre, 1065 King's R - Quarry Bay - HONG KONG - - 00-0A-CE (hex) RADIANTECH, INC. - 000ACE (base 16) RADIANTECH, INC. - 2-1, INDUSTRY EAST RD. 1, SCIENCE-BASED - INDUSTRIAL PARK - HSIN CHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-0A-CF (hex) PROVIDEO Multimedia Co. Ltd. - 000ACF (base 16) PROVIDEO Multimedia Co. Ltd. - 5F, NO.8, ALLEY 2, TZU-WEI LANE, - CHUNG CHENG RD., - HSIN TIEN CITY TAIPEI HSIEN, 231 - TAIWAN, PROVINCE OF CHINA - - 00-0A-D0 (hex) Niigata Develoment Center, F.I.T. Co., Ltd. - 000AD0 (base 16) Niigata Develoment Center, F.I.T. Co., Ltd. - Akane-Niigata Building 2F - 1-6-7 Atago - Niigata Niigata Prefecture 950-0944 - JAPAN - - 00-0A-D1 (hex) MWS - 000AD1 (base 16) MWS - 12, quai Papacino - NICE 06300 - FRANCE - - 00-0A-D2 (hex) JEPICO Corporation - 000AD2 (base 16) JEPICO Corporation - Nishi-shinjyuku2-7-1 - Dai-ichi Seimei BLDG. - Shinjyuku-ku Tokyo 163-0729 - JAPAN - - 00-0A-D3 (hex) INITECH Co., Ltd - 000AD3 (base 16) INITECH Co., Ltd - 3F, INITECH Bldg, 559-5, - Geoyo-Dong, Songpa-Gu - Seoul Songpa 138-816 - KOREA, REPUBLIC OF - - 00-0A-D4 (hex) CoreBell Systems Inc. - 000AD4 (base 16) CoreBell Systems Inc. - HTVC 2317 KAIST - 373-1 Guseong-dong - Yuseong-Gu Daejeon 305-701 - KOREA, REPUBLIC OF - - 00-0A-D5 (hex) Brainchild Electronic Co., Ltd. - 000AD5 (base 16) Brainchild Electronic Co., Ltd. - No.209, Chung Yang Rd., - Nan Kang District, - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-0A-D6 (hex) BeamReach Networks - 000AD6 (base 16) BeamReach Networks - 755 North Mathilda Ave - Sunnyvale California 94086 - UNITED STATES - - 00-0A-D7 (hex) Origin ELECTRIC CO.,LTD. - 000AD7 (base 16) Origin ELECTRIC CO.,LTD. - 1-18-1 - TAKADA - TOSHIMA WARD TOKYO MET. 171-8555 - JAPAN - - 00-0A-D8 (hex) IPCserv Technology Corp. - 000AD8 (base 16) IPCserv Technology Corp. - 6f,No.107,Pan-Hsin Rd - Pan-Chiao Taipei 22046 - TAIWAN, PROVINCE OF CHINA - - 00-0A-D9 (hex) Sony Ericsson Mobile Communications AB - 000AD9 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-0A-DA (hex) Vindicator Technologies - 000ADA (base 16) Vindicator Technologies - 5307 Industrial Oaks Blvd. - Suite 130 - Austin Texas 78735 - UNITED STATES - - 00-0A-DB (hex) SkyPilot Network, Inc - 000ADB (base 16) SkyPilot Network, Inc - 1301 Shoreway Road - Belmont CA 94002 - UNITED STATES - - 00-0A-DC (hex) RuggedCom Inc. - 000ADC (base 16) RuggedCom Inc. - 30 Whitmore Road - Woodbridge Ontario L4L 7Z4 - CANADA - - 00-0A-DD (hex) Allworx Corp. - 000ADD (base 16) Allworx Corp. - 300 Main Street - Suite 11 - East Rochester NY 14445 - UNITED STATES - - 00-0A-DE (hex) Happy Communication Co., Ltd. - 000ADE (base 16) Happy Communication Co., Ltd. - 42-11 WonMi-Dong - WonMi-Gu - Bucheon-City KyungGi-Do 420-110 - KOREA, REPUBLIC OF - - 00-0A-DF (hex) Gennum Corporation - 000ADF (base 16) Gennum Corporation - P.O Box 489 - Station A - Burlington Ontario L7R 3Y3 - CANADA - - 00-0A-E0 (hex) Fujitsu Softek - 000AE0 (base 16) Fujitsu Softek - 1250 East Arques Ave - MS 729 - Sunnyvale Ca 94085 - UNITED STATES - - 00-0A-E1 (hex) EG Technology - 000AE1 (base 16) EG Technology - 250 15th Street - Suite 4007 - Atlanta GA 30318 - UNITED STATES - - 00-0A-E2 (hex) Binatone Electronics International, Ltd - 000AE2 (base 16) Binatone Electronics International, Ltd - Floor 23A, 9 Des Voeux Road West - Hong Kong China - HONG KONG - - 00-0A-E3 (hex) YANG MEI TECHNOLOGY CO., LTD - 000AE3 (base 16) YANG MEI TECHNOLOGY CO., LTD - 21, Alley 1, Lane 342 - Fude 1st Road, Shijr City - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0A-E4 (hex) Wistron Corp. - 000AE4 (base 16) Wistron Corp. - 21F, No. 88, Section 1, Hsin Tai Wu Rd. - Hsichih - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-0A-E5 (hex) ScottCare Corporation - 000AE5 (base 16) ScottCare Corporation - 4791 West 150th Street - Cleveland Ohio 44135 - UNITED STATES - - 00-0A-E6 (hex) Elitegroup Computer System Co. (ECS) - 000AE6 (base 16) Elitegroup Computer System Co. (ECS) - No.22, Alley 38, Lane 91, Sec. 1, Nei Hu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0A-E7 (hex) ELIOP S.A. - 000AE7 (base 16) ELIOP S.A. - Avenida de Manoteras, 30 - Madrid E-28050 - SPAIN - - 00-0A-E8 (hex) Cathay Roxus Information Technology Co. LTD - 000AE8 (base 16) Cathay Roxus Information Technology Co. LTD - Fuhua mansion building A/B 4F - dongcheng district - Beijing 100027 - CHINA - - 00-0A-E9 (hex) AirVast Technology Inc. - 000AE9 (base 16) AirVast Technology Inc. - 3F.-5, No.6, Lane 609, Sec. 5, Chongsin Rd. - Sanchong City Taipei 241 - TAIWAN, PROVINCE OF CHINA - - 00-0A-EA (hex) ADAM ELEKTRONIK LTD. ÅžTI - 000AEA (base 16) ADAM ELEKTRONIK LTD. ÅžTI - UZUNAYNA CAD. CELENK SOK. NO:1 Çakmak - İstanbul 81260 - TURKEY - - 00-0A-EB (hex) Shenzhen Tp-Link Technology Co; Ltd. - 000AEB (base 16) Shenzhen Tp-Link Technology Co; Ltd. - Hi-Tech Park R1-B3 - 3/F, Bldg, Shennan Road - Shenzhen Guangdong 518057 - CHINA - - 00-0A-EC (hex) Koatsu Gas Kogyo Co., Ltd. - 000AEC (base 16) Koatsu Gas Kogyo Co., Ltd. - 1-5, Doyama-cho, Kita-ku, Osaka - Osaka 530-8411 - JAPAN - - 00-0A-ED (hex) HARTING Systems GmbH & Co KG - 000AED (base 16) HARTING Systems GmbH & Co KG - Wilhelm Harting Str.1 - Espelkamp NRW/OWL 32339 - GERMANY - - 00-0A-EE (hex) GCD Hard- & Software GmbH - 000AEE (base 16) GCD Hard- & Software GmbH - Henkestraße 79 - Erlangen Bayern 91052 - GERMANY - - 00-0A-EF (hex) OTRUM ASA - 000AEF (base 16) OTRUM ASA - Brattekleiv - Færvik N-4818 - NORWAY - - 00-0A-F0 (hex) SHIN-OH ELECTRONICS CO., LTD. R&D - 000AF0 (base 16) SHIN-OH ELECTRONICS CO., LTD. R&D - #729-5, Bonoh-Dong, Ansan-City, Kyunggi- - SHIN-OH ELECTRONICS CO., LTD. - Ansan-City Kyunggi-Do 425-180 - KOREA, REPUBLIC OF - - 00-0A-F1 (hex) Clarity Design, Inc. - 000AF1 (base 16) Clarity Design, Inc. - 13029 Danielson Street - Suite 100 - Poway CA 92064-8810 - UNITED STATES - - 00-0A-F2 (hex) NeoAxiom Corp. - 000AF2 (base 16) NeoAxiom Corp. - 1520 Montague Expressway - San Jose CA 95131 - UNITED STATES - - 00-0A-F3 (hex) CISCO SYSTEMS, INC. - 000AF3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-F4 (hex) CISCO SYSTEMS, INC. - 000AF4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0A-F5 (hex) Airgo Networks, Inc. - 000AF5 (base 16) Airgo Networks, Inc. - 900 Arastradero Rd - Palo Alto CA 94304 - UNITED STATES - - 00-0A-F6 (hex) Emerson Climate Technologies Retail Solutions, Inc. - 000AF6 (base 16) Emerson Climate Technologies Retail Solutions, Inc. - 1640 Airport Rd - Suite 104 - Kennesaw GA 30144-7038 - UNITED STATES - - 00-0A-F7 (hex) Broadcom Corp. - 000AF7 (base 16) Broadcom Corp. - 16215 Alton Parkway - Irvine CA 92618 - UNITED STATES - - 00-0A-F8 (hex) American Telecare Inc. - 000AF8 (base 16) American Telecare Inc. - 7640 Golden Triangle Drive - Eden Prairie MN 55344 - UNITED STATES - - 00-0A-F9 (hex) HiConnect, Inc. - 000AF9 (base 16) HiConnect, Inc. - Rm #906, Haksan Cosmostel, 110 - Kwangjang-Dong, Kwangjin-Gu, Seoul, Kore - Kwangjin-Gu Seoul 143-802 - KOREA, REPUBLIC OF - - 00-0A-FA (hex) Traverse Technologies Australia - 000AFA (base 16) Traverse Technologies Australia - Unit 13, 240 Sydney Rd - Coburg Victoria 3058 - AUSTRALIA - - 00-0A-FB (hex) Ambri Limited - 000AFB (base 16) Ambri Limited - 126 Greville Street - Chatswood NSW 2067 - AUSTRALIA - - 00-0A-FC (hex) Core Tec Communications, LLC - 000AFC (base 16) Core Tec Communications, LLC - 49 Leavenworth Street - Suite 200 - Waterbury CT 06702 - UNITED STATES - - 00-0A-FD (hex) Kentec Electronics - 000AFD (base 16) Kentec Electronics - 620 Allendale Rd - Suite 175 - King of Prussia PA 19406 - UNITED STATES - - 00-0A-FE (hex) NovaPal Ltd - 000AFE (base 16) NovaPal Ltd - Floor 6 - 58 Uxbridge Road - Ealing London W5 2ST - UNITED KINGDOM - - 00-0A-FF (hex) Kilchherr Elektronik AG - 000AFF (base 16) Kilchherr Elektronik AG - Aeschistrasse 25 - Muensingen BE 3110 - SWITZERLAND - - 00-0B-00 (hex) FUJIAN START COMPUTER EQUIPMENT CO.,LTD - 000B00 (base 16) FUJIAN START COMPUTER EQUIPMENT CO.,LTD - HONG SHAN YUAN ROAD NO.68 HONGSHAN,GULOU - FUZHOU FUJIAN 350002 - CHINA - - 00-0B-01 (hex) DAIICHI ELECTRONICS CO., LTD. - 000B01 (base 16) DAIICHI ELECTRONICS CO., LTD. - 1-11-13 - Hitotsuya Adachi-ku Tokyo 121-8639 - JAPAN - - 00-0B-02 (hex) Dallmeier electronic - 000B02 (base 16) Dallmeier electronic - Würzburgerstraße 5 - Regensburg Bavaria 93059 - GERMANY - - 00-0B-03 (hex) Taekwang Industrial Co., Ltd - 000B03 (base 16) Taekwang Industrial Co., Ltd - #191-1, Anyang-7Dong, Manan-Gu - Anyang-Si South Korea 430-017 - KOREA, REPUBLIC OF - - 00-0B-04 (hex) Volktek Corporation - 000B04 (base 16) Volktek Corporation - 4F., No.192, Lian-Chang Road, Chang-Ho - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-0B-05 (hex) Pacific Broadband Networks - 000B05 (base 16) Pacific Broadband Networks - 8-10 Keith Campbell Court - SCORESBY VIC 3179 - AUSTRALIA - - 00-0B-06 (hex) ARRIS Group, Inc. - 000B06 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-0B-07 (hex) Voxpath Networks - 000B07 (base 16) Voxpath Networks - 7600B Capital of Texas Highway - North - Suite 220 - Austin Texas 78731 - UNITED STATES - - 00-0B-08 (hex) Pillar Data Systems - 000B08 (base 16) Pillar Data Systems - 1371 McCarthy Blvd. - Milpitas CA 95035 - UNITED STATES - - 00-0B-09 (hex) Ifoundry Systems Singapore - 000B09 (base 16) Ifoundry Systems Singapore - Block 1, Unit 101B, Innovation Centre, 1 - 637722 - SINGAPORE - - 00-0B-0A (hex) dBm Optics - 000B0A (base 16) dBm Optics - 300 S. Public Road - Lafayette Colorado 80026 - UNITED STATES - - 00-0B-0B (hex) Corrent Corporation - 000B0B (base 16) Corrent Corporation - 1711 W. Greentree Dr. - Suite 201 - Tempe AZ 85284-2717 - UNITED STATES - - 00-0B-0C (hex) Agile Systems Inc. - 000B0C (base 16) Agile Systems Inc. - 575 Kumpf Drive - Waterloo Ontario N2V 1K3 - CANADA - - 00-0B-0D (hex) Air2U, Inc. - 000B0D (base 16) Air2U, Inc. - No. 5-1 Innovation Rd 1, Science-based P - Hsin-Chu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-0B-0E (hex) Trapeze Networks - 000B0E (base 16) Trapeze Networks - 5753 W. Las Positas Blvd - Pleasanton CA 94588 - UNITED STATES - - 00-0B-0F (hex) Bosch Rexroth - 000B0F (base 16) Bosch Rexroth - Luchthavenweg 20 - Eindhoven Noord Brabant NL5657 EB - NETHERLANDS - - 00-0B-10 (hex) 11wave Technonlogy Co.,Ltd - 000B10 (base 16) 11wave Technonlogy Co.,Ltd - 10F,no.285 sec.2 ,Ti-Ding Ave,NaiHu.Taip - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0B-11 (hex) HIMEJI ABC TRADING CO.,LTD. - 000B11 (base 16) HIMEJI ABC TRADING CO.,LTD. - 1-8-22 - JYOUHOKUSHINMACHI - HJMEJI HYOGO 670-0883 - JAPAN - - 00-0B-12 (hex) NURI Telecom Co., Ltd. - 000B12 (base 16) NURI Telecom Co., Ltd. - Woolim Lion's Valley Bldg-B 10th F - #371-28 Kasan-dong - Keum-cheun-gu Seoul 153-803 - KOREA, REPUBLIC OF - - 00-0B-13 (hex) ZETRON INC - 000B13 (base 16) ZETRON INC - PO Box 97004 - REDMOND WA 98073 - UNITED STATES - - 00-0B-14 (hex) ViewSonic Corporation - 000B14 (base 16) ViewSonic Corporation - 381 Brea Canyon Road - Walnut California 91789 - UNITED STATES - - 00-0B-15 (hex) Platypus Technology - 000B15 (base 16) Platypus Technology - 4/1 Atchison St - St Leonards NSW 2065 - AUSTRALIA - - 00-0B-16 (hex) Communication Machinery Corporation - 000B16 (base 16) Communication Machinery Corporation - 402 E. Gutierrez St. - Santa Barbara CA 93101 - UNITED STATES - - 00-0B-17 (hex) MKS Instruments - 000B17 (base 16) MKS Instruments - 651 Lowell Street - Methuen MA 01844 - UNITED STATES - - 00-0B-18 (hex) PRIVATE - 000B18 (base 16) - - 00-0B-19 (hex) Vernier Networks, Inc. - 000B19 (base 16) Vernier Networks, Inc. - 490 E. Middlefield Road - Mountain View CA 94043 - UNITED STATES - - 00-0B-1A (hex) Industrial Defender, Inc. - 000B1A (base 16) Industrial Defender, Inc. - 16 Chestnut Street - Suite 300 - Foxborough MA 02035 - UNITED STATES - - 00-0B-1B (hex) Systronix, Inc. - 000B1B (base 16) Systronix, Inc. - 939 Edison St. - Salt Lake City Utah 84111 - UNITED STATES - - 00-0B-1C (hex) SIBCO bv - 000B1C (base 16) SIBCO bv - Schoonhout 46 - Etten-Leur NB 4872 ME - NETHERLANDS - - 00-0B-1D (hex) LayerZero Power Systems, Inc. - 000B1D (base 16) LayerZero Power Systems, Inc. - 3559 Townley Road - Shaker Heights OH 44122-5156 - UNITED STATES - - 00-0B-1E (hex) KAPPA opto-electronics GmbH - 000B1E (base 16) KAPPA opto-electronics GmbH - Kleines Feld 6 - 37130 - Gleichen Niedersachsen - GERMANY - - 00-0B-1F (hex) I CON Computer Co. - 000B1F (base 16) I CON Computer Co. - 3F, No. 142 , Hsin Ming Road - Neihu Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0B-20 (hex) Hirata corporation - 000B20 (base 16) Hirata corporation - 111 Hitotsugi, Ueki, - Kamoto Kumamoto 861-0198 - JAPAN - - 00-0B-21 (hex) G-Star Communications Inc. - 000B21 (base 16) G-Star Communications Inc. - 5F, 69-10, Sec. 2, Chung Cheng East Road - Taipei Hsien 251 - TAIWAN, PROVINCE OF CHINA - - 00-0B-22 (hex) Environmental Systems and Services - 000B22 (base 16) Environmental Systems and Services - 20 Council Street - Hawthorn East Victoria 3123 - AUSTRALIA - - 00-0B-23 (hex) Siemens Subscriber Networks - 000B23 (base 16) Siemens Subscriber Networks - 4849 Alpha Road - Dallas Texas 74244 - UNITED STATES - - 00-0B-24 (hex) AirLogic - 000B24 (base 16) AirLogic - 807-1, Bundangtechnopark D, 151, - Yatap-Dong, Bundang-Ku - Sungnam-Si Kyungki-Do 463-760 - KOREA, REPUBLIC OF - - 00-0B-25 (hex) Aeluros - 000B25 (base 16) Aeluros - 201 San Antonio Circle #172 - Mountain View CA 94040 - UNITED STATES - - 00-0B-26 (hex) Wetek Corporation - 000B26 (base 16) Wetek Corporation - 4F, NO.17, Kuanfu N. Road - Hsin Chu Industrial Park Hsin Chu 303 - TAIWAN, PROVINCE OF CHINA - - 00-0B-27 (hex) Scion Corporation - 000B27 (base 16) Scion Corporation - 82 Worman's Mill Court - Suite H - Frederick MD 21701 - UNITED STATES - - 00-0B-28 (hex) Quatech Inc. - 000B28 (base 16) Quatech Inc. - 662 Wolf Ledges Pkwy. - Akron OH 44311 - UNITED STATES - - 00-0B-29 (hex) LS(LG) Industrial Systems co.,Ltd - 000B29 (base 16) LS(LG) Industrial Systems co.,Ltd - 533 Hogye-dong, Dongan-gu - Anyang-si Gyeonggi-do - KOREA, REPUBLIC OF - - 00-0B-2A (hex) HOWTEL Co., Ltd. - 000B2A (base 16) HOWTEL Co., Ltd. - J-COM Bd. 4F, 124-4 OJEON-DONG - UIWANG-SHI KYOUNGGI-DO 437-070 - KOREA, REPUBLIC OF - - 00-0B-2B (hex) HOSTNET CORPORATION - 000B2B (base 16) HOSTNET CORPORATION - 10F-12,No. 12 Lane 609, Sec.5,Chunghsin - Sanchung Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 00-0B-2C (hex) Eiki Industrial Co. Ltd. - 000B2C (base 16) Eiki Industrial Co. Ltd. - 4-12 Manzai-cho, Kita-ku - Osaka 530 - JAPAN - - 00-0B-2D (hex) Danfoss Inc. - 000B2D (base 16) Danfoss Inc. - 7941 Corporate Dr - Baltimore MD 21236 - UNITED STATES - - 00-0B-2E (hex) Cal-Comp Electronics (Thailand) Public Company Limited Taipe - 000B2E (base 16) Cal-Comp Electronics (Thailand) Public Company Limited Taipe - 9F, 99, Nan-King E Rd., Sec. 5. - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-0B-2F (hex) bplan GmbH - 000B2F (base 16) bplan GmbH - Industriestrasse 23b - Steinbach Hessen 61449 - GERMANY - - 00-0B-30 (hex) Beijing Gongye Science & Technology Co.,Ltd - 000B30 (base 16) Beijing Gongye Science & Technology Co.,Ltd - Unit D.17/E,Shenlanhuating mid Road No.6 - Beijing 100029 - CHINA - - 00-0B-31 (hex) Yantai ZhiYang Scientific and technology industry CO., LTD - 000B31 (base 16) Yantai ZhiYang Scientific and technology industry CO., LTD - 5F-4, NO. 64, Gong-Jian Rd. - Hsi-Chih City Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-0B-32 (hex) VORMETRIC, INC. - 000B32 (base 16) VORMETRIC, INC. - 2060 CORPORATE CT - SAN JOSE CA 95131 - UNITED STATES - - 00-0B-33 (hex) Vivato Technologies - 000B33 (base 16) Vivato Technologies - 444 Cedros Ave - Suite 175 - Solana Beach CA 92027 - UNITED STATES - - 00-0B-34 (hex) ShangHai Broadband Technologies CO.LTD - 000B34 (base 16) ShangHai Broadband Technologies CO.LTD - 17F,No.122,HuangXing Road - ShangHai 200090 - CHINA - - 00-0B-35 (hex) Quad Bit System co., Ltd. - 000B35 (base 16) Quad Bit System co., Ltd. - 402 Gayang Technotown - 1487 Gayang 3 dong - Seoul Kangseogu 157-810 - KOREA, REPUBLIC OF - - 00-0B-36 (hex) Productivity Systems, Inc. - 000B36 (base 16) Productivity Systems, Inc. - 1711 Analog Drive - Richardson TX 75081-1944 - UNITED STATES - - 00-0B-37 (hex) MANUFACTURE DES MONTRES ROLEX SA - 000B37 (base 16) MANUFACTURE DES MONTRES ROLEX SA - LA HAUTE-ROUTE 82 - BIEL-BIENNE BE 2502 - SWITZERLAND - - 00-0B-38 (hex) Knürr GmbH - 000B38 (base 16) Knürr GmbH - Mariakirchener Straße 38 - Arnstorf Bavaria 94424 - GERMANY - - 00-0B-39 (hex) Keisoku Giken Co.,Ltd. - 000B39 (base 16) Keisoku Giken Co.,Ltd. - 2-12-2 , Chigasaki-minami - Tsuzuki-ku - Yokohama Kanagawa 224-0037 - JAPAN - - 00-0B-3A (hex) QuStream Corporation - 000B3A (base 16) QuStream Corporation - 3305 Breckinridge Blvd. - Suite 118 - Duluth Georgia 30096 - UNITED STATES - - 00-0B-3B (hex) devolo AG - 000B3B (base 16) devolo AG - Sonnenweg 11 - Aachen NRW 52070 - GERMANY - - 00-0B-3C (hex) Cygnal Integrated Products, Inc. - 000B3C (base 16) Cygnal Integrated Products, Inc. - 4301 Westbank Drive - Suite B-100 - Austin TX 78746 - UNITED STATES - - 00-0B-3D (hex) CONTAL OK Ltd. - 000B3D (base 16) CONTAL OK Ltd. - Frana Mraza 2/289 - P.O.Box B-34 - Zilina 01124 - SLOVAKIA - - 00-0B-3E (hex) BittWare, Inc - 000B3E (base 16) BittWare, Inc - 31 B South Main St - Concord NH 03301 - UNITED STATES - - 00-0B-3F (hex) Anthology Solutions Inc. - 000B3F (base 16) Anthology Solutions Inc. - 1722 Ringwood Ave. - Suite 250 - San Jose CA 95131 - UNITED STATES - - 00-0B-40 (hex) Oclaro - 000B40 (base 16) Oclaro - 2560 Junction Avenue - San Jose New Jersey 95134 - UNITED STATES - - 00-0B-41 (hex) Ing. Büro Dr. Beutlhauser - 000B41 (base 16) Ing. Büro Dr. Beutlhauser - Roemerweg 4 - Grassau D-83224 - GERMANY - - 00-0B-42 (hex) commax Co., Ltd. - 000B42 (base 16) commax Co., Ltd. - 513-11, Sangdaewon-Dong, Jungwon-Ku - Sungnam-City Kyunggi-Do 462-120 - KOREA, REPUBLIC OF - - 00-0B-43 (hex) Microscan Systems, Inc. - 000B43 (base 16) Microscan Systems, Inc. - 700 SW 39th St - Renton WA 98057 - UNITED STATES - - 00-0B-44 (hex) Concord IDea Corp. - 000B44 (base 16) Concord IDea Corp. - 4118 14th Ave., Unit 4 - Markham Ontario L3R 0J3 - CANADA - - 00-0B-45 (hex) CISCO SYSTEMS, INC. - 000B45 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-46 (hex) CISCO SYSTEMS, INC. - 000B46 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-47 (hex) Advanced Energy - 000B47 (base 16) Advanced Energy - 1625 Sharp Point Drive - Fort Collins Colorado 80525 - UNITED STATES - - 00-0B-48 (hex) sofrel - 000B48 (base 16) sofrel - 2 rue du plessis - vern sur seiche ille et vilaine 35770 - FRANCE - - 00-0B-49 (hex) RF-Link System Inc. - 000B49 (base 16) RF-Link System Inc. - No.6, Nan-Ke 5th Rd., Hsin-Shi, - Tainan County 744 - TAIWAN, PROVINCE OF CHINA - - 00-0B-4A (hex) Visimetrics (UK) Ltd - 000B4A (base 16) Visimetrics (UK) Ltd - Skye House - Skye Road - Prestwick Ayrshire KA9 2TA - UNITED KINGDOM - - 00-0B-4B (hex) VISIOWAVE SA - 000B4B (base 16) VISIOWAVE SA - Route de la Pierre 22 - VICTORIA HOUSE - ECUBLENS VAUD CH-1024 - SWITZERLAND - - 00-0B-4C (hex) Clarion (M) Sdn Bhd - 000B4C (base 16) Clarion (M) Sdn Bhd - Phase 3 - FIZ - Bayan Lepas Penang 11900 - MALAYSIA - - 00-0B-4D (hex) Emuzed - 000B4D (base 16) Emuzed - 46750 Lakeview Boulevard - Fremont California 94538 - UNITED STATES - - 00-0B-4E (hex) VertexRSI, General Dynamics SatCOM Technologies, Inc. - 000B4E (base 16) VertexRSI, General Dynamics SatCOM Technologies, Inc. - 3750 W. Loop 281 - Longview TX 75604 - UNITED STATES - - 00-0B-4F (hex) Verifone, INC. - 000B4F (base 16) Verifone, INC. - 2099 Gateway Place - Suite 600 - San Jose California 95110 - UNITED STATES - - 00-0B-50 (hex) Oxygnet - 000B50 (base 16) Oxygnet - 402 E. Carrillo St. - Suite C - Santa Barbara CA 93101 - UNITED STATES - - 00-0B-51 (hex) Micetek International Inc. - 000B51 (base 16) Micetek International Inc. - 7F-1, #237, Sec. 1, wu Chuan W. Rd. - Taichung 403 - TAIWAN, PROVINCE OF CHINA - - 00-0B-52 (hex) JOYMAX ELECTRONICS CO. LTD. - 000B52 (base 16) JOYMAX ELECTRONICS CO. LTD. - No.5 Dong-Yuan Road 2, Jhong-Li Industrial Park, - Jhong-Li City, - Tao-Yuan 32063 - TAIWAN, PROVINCE OF CHINA - - 00-0B-53 (hex) INITIUM Co., Ltd. - 000B53 (base 16) INITIUM Co., Ltd. - 8F. Gongduck Bldg. 272-6 Seohyun Bundang - Sungnam Kyunggi 463-824 - KOREA, REPUBLIC OF - - 00-0B-54 (hex) BiTMICRO Networks, Inc. - 000B54 (base 16) BiTMICRO Networks, Inc. - 45550 Northport Loop East - Fremont CA 94538 - UNITED STATES - - 00-0B-55 (hex) ADInstruments - 000B55 (base 16) ADInstruments - P. O. Box 587 - Dunedin Otago 9001 - NEW ZEALAND - - 00-0B-56 (hex) Cybernetics - 000B56 (base 16) Cybernetics - 111 Cybernetics Way STE 300 - Yorktown VA 23693 - UNITED STATES - - 00-0B-57 (hex) Silicon Laboratories - 000B57 (base 16) Silicon Laboratories - 7000 W. William Cannon Dr. - Bldg.1, Suite 200 - Austin TX 78735 - UNITED STATES - - 00-0B-58 (hex) Astronautics C.A LTD - 000B58 (base 16) Astronautics C.A LTD - 23 hayarkon street - Bnei Brak 51261 - ISRAEL - - 00-0B-59 (hex) ScriptPro, LLC - 000B59 (base 16) ScriptPro, LLC - 5828 Reeds Rd. - Mission Kansas 66202 - UNITED STATES - - 00-0B-5A (hex) HyperEdge - 000B5A (base 16) HyperEdge - 333 Pierce Road Suite #200 - Itasca IL 60143 - UNITED STATES - - 00-0B-5B (hex) Rincon Research Corporation - 000B5B (base 16) Rincon Research Corporation - 101 N. Wilmot Rd. - Suite 101 - Tucson AZ 85711 - UNITED STATES - - 00-0B-5C (hex) Newtech Co.,Ltd - 000B5C (base 16) Newtech Co.,Ltd - K-Bldg 1-7-7 Shibadaimon Minato-ku - Tokyo 105-0012 - JAPAN - - 00-0B-5D (hex) FUJITSU LIMITED - 000B5D (base 16) FUJITSU LIMITED - Musashi-kosugi Tower Place Bldg., 403 - Kosugi-cho 1-chome,Nakahara-ku - Kawasaki Kanagawa - JAPAN - - 00-0B-5E (hex) Audio Engineering Society Inc. - 000B5E (base 16) Audio Engineering Society Inc. - 60 East 42nd Street, Suite #2520 - New York NY 10165-2520 - UNITED STATES - - 00-0B-5F (hex) CISCO SYSTEMS, INC. - 000B5F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-60 (hex) CISCO SYSTEMS, INC. - 000B60 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-61 (hex) Friedrich Lütze GmbH & Co. KG - 000B61 (base 16) Friedrich Lütze GmbH & Co. KG - Bruckwiesenstraße 17 - 19 - Weinstadt (Großheppach) BW 71384 - GERMANY - - 00-0B-62 (hex) ib-mohnen KG - 000B62 (base 16) ib-mohnen KG - Stich 30 e - 52249 Eschweiler - GERMANY - - 00-0B-63 (hex) Kaleidescape - 000B63 (base 16) Kaleidescape - One First Street, Suite Sixteen - Los Altos CA 94022 - UNITED STATES - - 00-0B-64 (hex) Kieback & Peter GmbH & Co KG - 000B64 (base 16) Kieback & Peter GmbH & Co KG - Tempelhofer Weg 50 - Berlin 12347 - GERMANY - - 00-0B-65 (hex) Sy.A.C. srl - 000B65 (base 16) Sy.A.C. srl - via Caboto 19/1 - Trieste 34147 - ITALY - - 00-0B-66 (hex) Teralink Communications - 000B66 (base 16) Teralink Communications - Capital Tower 15F, - 931 Doonsan-dong, Seo-gu - Daejeon 302120 - KOREA, REPUBLIC OF - - 00-0B-67 (hex) Topview Technology Corporation - 000B67 (base 16) Topview Technology Corporation - No. 8,Wu-Chuan Road,Wu Ku Industrial Par - Wu Ku Hsiang,Taipei Hsien, 248 - TAIWAN, PROVINCE OF CHINA - - 00-0B-68 (hex) Addvalue Communications Pte Ltd - 000B68 (base 16) Addvalue Communications Pte Ltd - 28,TAI SENG STREET #06-02 - Singapore 534106 - SINGAPORE - - 00-0B-69 (hex) Franke Finland Oy - 000B69 (base 16) Franke Finland Oy - Vartiokuja 1 - NAARAJARVI NAARAJARVI FIN-76850 - FINLAND - - 00-0B-6A (hex) Asiarock Incorporation - 000B6A (base 16) Asiarock Incorporation - P.O. Box957, Offshore Incorporations Cen - Road Town Tortola - VIRGIN ISLANDS, BRITISH - - 00-0B-6B (hex) Wistron Neweb Corp. - 000B6B (base 16) Wistron Neweb Corp. - No. 10-1, Li-Hsin Road I, Science-based - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0B-6C (hex) Sychip Inc. - 000B6C (base 16) Sychip Inc. - 2805 N. Dallas Parkway Suite 400 - Plano Texas 75093 - UNITED STATES - - 00-0B-6D (hex) SOLECTRON JAPAN NAKANIIDA - 000B6D (base 16) SOLECTRON JAPAN NAKANIIDA - 325 GANBARA - NAKANIIDAMACHI - KAMIGUN MIYAGIKEN 981-4263 - JAPAN - - 00-0B-6E (hex) Neff Instrument Corp. - 000B6E (base 16) Neff Instrument Corp. - 700 South Myrtle Ave. - Monrovia CA 91016 - UNITED STATES - - 00-0B-6F (hex) Media Streaming Networks Inc - 000B6F (base 16) Media Streaming Networks Inc - 1905 Anam Tower, 702-10, Yeoksam dong, K - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-0B-70 (hex) Load Technology, Inc. - 000B70 (base 16) Load Technology, Inc. - 4225 Production Court - Las Vegas NV 89115 - UNITED STATES - - 00-0B-71 (hex) Litchfield Communications Inc. - 000B71 (base 16) Litchfield Communications Inc. - 27 Princeton Road - Watertown CT 06795 - UNITED STATES - - 00-0B-72 (hex) Lawo AG - 000B72 (base 16) Lawo AG - Am Oberwald 8 - Rastatt Baden-Württemberg 76437 - GERMANY - - 00-0B-73 (hex) Kodeos Communications - 000B73 (base 16) Kodeos Communications - 111 Corporate Blvd - Suite A - South Plainfield NJ 07080 - UNITED STATES - - 00-0B-74 (hex) Kingwave Technology Co., Ltd. - 000B74 (base 16) Kingwave Technology Co., Ltd. - 18F-3, No. 186, Jian-Yi Rd. - Chung-Ho Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-0B-75 (hex) Iosoft Ltd. - 000B75 (base 16) Iosoft Ltd. - 5 Woodlark Road - Cambridge Cambs. CB3 0HT - UNITED KINGDOM - - 00-0B-76 (hex) ET&T Technology Co. Ltd. - 000B76 (base 16) ET&T Technology Co. Ltd. - 6F No.101, SongJiang Rd. - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-0B-77 (hex) Cogent Systems, Inc. - 000B77 (base 16) Cogent Systems, Inc. - 209 Fair Oaks Ave. - South Pasadena CA 91030 - UNITED STATES - - 00-0B-78 (hex) TAIFATECH INC. - 000B78 (base 16) TAIFATECH INC. - 8F-1 No.289, Sec.2 Guangfu Rd. - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0B-79 (hex) X-COM, Inc. - 000B79 (base 16) X-COM, Inc. - 8809 Sudley Road - Suite 202 - Manassas VA 20110 - UNITED STATES - - 00-0B-7A (hex) L-3 Linkabit - 000B7A (base 16) L-3 Linkabit - 9890 Town Center Drive - San Diego CA 92121 - UNITED STATES - - 00-0B-7B (hex) Test-Um Inc. - 000B7B (base 16) Test-Um Inc. - 808 Calle Plano - Camarillo CA 93012 - UNITED STATES - - 00-0B-7C (hex) Telex Communications - 000B7C (base 16) Telex Communications - 8601 E. Cornhusker Hwy - Lincoln NE 68505 - UNITED STATES - - 00-0B-7D (hex) SOLOMON EXTREME INTERNATIONAL LTD. - 000B7D (base 16) SOLOMON EXTREME INTERNATIONAL LTD. - 3F, No.20, Lane 165, Duenhua N. Rd., Sun - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-0B-7E (hex) SAGINOMIYA Seisakusho Inc. - 000B7E (base 16) SAGINOMIYA Seisakusho Inc. - 535 Sasai - Sayamashi Saitamaken 350-1395 - JAPAN - - 00-0B-7F (hex) Align Engineering LLC - 000B7F (base 16) Align Engineering LLC - 245 Highlands Drive - Friday Harbor WA 98250 - UNITED STATES - - 00-0B-80 (hex) Lycium Networks - 000B80 (base 16) Lycium Networks - 9 Hamenofim St. - P.O.Box 12256 - Herzliya Israel 46733 - ISRAEL - - 00-0B-81 (hex) Kaparel Corporation - 000B81 (base 16) Kaparel Corporation - 97 Randall Drive - Waterloo Ontario N2V-1C5 - CANADA - - 00-0B-82 (hex) Grandstream Networks, Inc. - 000B82 (base 16) Grandstream Networks, Inc. - 1297 Beacon Street - 2nd Floor - Brookline MA 02446 - UNITED STATES - - 00-0B-83 (hex) DATAWATT B.V. - 000B83 (base 16) DATAWATT B.V. - HOUTSTRAAT 5 - P.O. BOX 108 - WOLVEGA FRIESLAND NL-8471-ZX - NETHERLANDS - - 00-0B-84 (hex) BODET - 000B84 (base 16) BODET - Route de la Tourlandry - TREMENTINES FRANCE 49340 - FRANCE - - 00-0B-85 (hex) CISCO SYSTEMS, INC. - 000B85 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-86 (hex) Aruba Networks - 000B86 (base 16) Aruba Networks - 1322 Crossman Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-0B-87 (hex) American Reliance Inc. - 000B87 (base 16) American Reliance Inc. - 11801 Goldring Rd - Arcadia CA 91006 - UNITED STATES - - 00-0B-88 (hex) Vidisco ltd. - 000B88 (base 16) Vidisco ltd. - 17 Yechiel Dresner - Petach-Tikva 49277 - ISRAEL - - 00-0B-89 (hex) Top Global Technology, Ltd. - 000B89 (base 16) Top Global Technology, Ltd. - Room 3310, China World Tower No. 1 - Jian Guo Men Wai Avenue - Beijing Beijing 100004 - CHINA - - 00-0B-8A (hex) MITEQ Inc. - 000B8A (base 16) MITEQ Inc. - 100 Davids Drive - Hauppauge NY 11788-2034 - UNITED STATES - - 00-0B-8B (hex) KERAJET, S.A. - 000B8B (base 16) KERAJET, S.A. - Avda. del Boverot, 24 - Almazora Castellon E-12550 - SPAIN - - 00-0B-8C (hex) Flextronics - 000B8C (base 16) Flextronics - Migdal HaEmek - Ramat Gavriel - 23108 Hataasia 1 - ISRAEL - - 00-0B-8D (hex) Avvio Networks - 000B8D (base 16) Avvio Networks - 11 Donovan Dr - Bedford MA 01730 - UNITED STATES - - 00-0B-8E (hex) Ascent Corporation - 000B8E (base 16) Ascent Corporation - 2-16-19, Kawaraya-machi, Chuo-Ku, - Osaka-City Osaka-Pref 542-0066 - JAPAN - - 00-0B-8F (hex) AKITA ELECTRONICS SYSTEMS CO.,LTD. - 000B8F (base 16) AKITA ELECTRONICS SYSTEMS CO.,LTD. - 85,AZA USHIRONO,AIKAWA,YUWA-MACHI - KAWABE-GUN AKITA-KEN 010-1231 - JAPAN - - 00-0B-90 (hex) ADVA Optical Networking Ltd. - 000B90 (base 16) ADVA Optical Networking Ltd. - ADVAntage House - Tribune Way - York YO30 4RY - UNITED KINGDOM - - 00-0B-91 (hex) Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH - 000B91 (base 16) Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH - Tiniusstraße 12-15 - Berlin D-13089 - GERMANY - - 00-0B-92 (hex) Ascom Danmark A/S - 000B92 (base 16) Ascom Danmark A/S - Fabriksparken 42 - Glostrup Denmark 2600 - DENMARK - - 00-0B-93 (hex) Ritter Elektronik - 000B93 (base 16) Ritter Elektronik - Leverkuser Straße 65 - P.O. Box 110240 - Remscheid NRW 42897 - GERMANY - - 00-0B-94 (hex) Digital Monitoring Products, Inc. - 000B94 (base 16) Digital Monitoring Products, Inc. - 2500 N. Partnership Boulevard - Springfield Missouri 65803 - UNITED STATES - - 00-0B-95 (hex) eBet Gaming Systems Pty Ltd - 000B95 (base 16) eBet Gaming Systems Pty Ltd - Suite D, 255 Rawson Street - Auburn NSW 2144 - AUSTRALIA - - 00-0B-96 (hex) Innotrac Diagnostics Oy - 000B96 (base 16) Innotrac Diagnostics Oy - Kalevantie 25 - Turku Ã…bo 20520 - FINLAND - - 00-0B-97 (hex) Matsushita Electric Industrial Co.,Ltd. - 000B97 (base 16) Matsushita Electric Industrial Co.,Ltd. - 3-1-1 Yagumo-Naka-Machi - Moriguchi City Osaka 570-8501 - JAPAN - - 00-0B-98 (hex) NiceTechVision - 000B98 (base 16) NiceTechVision - IntelZone 703 - YongIn Gugal-ri Ki Heung KyoungKiDo 354-2 - KOREA, REPUBLIC OF - - 00-0B-99 (hex) SensAble Technologies, Inc. - 000B99 (base 16) SensAble Technologies, Inc. - 15 Constitution Way - Woburn MA 01801 - UNITED STATES - - 00-0B-9A (hex) Shanghai Ulink Telecom Equipment Co. Ltd. - 000B9A (base 16) Shanghai Ulink Telecom Equipment Co. Ltd. - 6 Floor, Building 3 - 230 West Jiangwan Road - Shanghai 200083 - CHINA - - 00-0B-9B (hex) Sirius System Co, Ltd. - 000B9B (base 16) Sirius System Co, Ltd. - 3-27 Funado-cho - Ashiya Hyogo 659-0093 - JAPAN - - 00-0B-9C (hex) TriBeam Technologies, Inc. - 000B9C (base 16) TriBeam Technologies, Inc. - 116 W. Eastman St., suite 208 - Arlington Heights IL 60004 - UNITED STATES - - 00-0B-9D (hex) TwinMOS Technologies Inc. - 000B9D (base 16) TwinMOS Technologies Inc. - 303 No.3, Tzu Chiang Rd., Hu Kou Xiang, - Hsin Chu 303 - TAIWAN, PROVINCE OF CHINA - - 00-0B-9E (hex) Yasing Technology Corp. - 000B9E (base 16) Yasing Technology Corp. - No. 50, Ta Hsueh Road, HsinChu, Taiwan - HsinChu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0B-9F (hex) Neue ELSA GmbH - 000B9F (base 16) Neue ELSA GmbH - Sonnenweg 11 - Aachen 52070 - GERMANY - - 00-0B-A0 (hex) T&L Information Inc. - 000BA0 (base 16) T&L Information Inc. - 898-44 Hokye-Dong, Dongan-Gu - Anyang Kyungki-Do 431-836 - KOREA, REPUBLIC OF - - 00-0B-A1 (hex) SYSCOM Ltd. - 000BA1 (base 16) SYSCOM Ltd. - 4-10 HAKODA, KUMAGAYA-SHI - SAITAMA-KEN 360-8515 - JAPAN - - 00-0B-A2 (hex) Sumitomo Electric Networks, Inc - 000BA2 (base 16) Sumitomo Electric Networks, Inc - 1-1-3, Shimaya, Konohana-ku - Osaka 554-0024 - JAPAN - - 00-0B-A3 (hex) Siemens AG, I&S - 000BA3 (base 16) Siemens AG, I&S - Werner-von-Siemens-Straße 65 - Erlangen Bavaria 91052 - GERMANY - - 00-0B-A4 (hex) Shiron Satellite Communications Ltd. (1996) - 000BA4 (base 16) Shiron Satellite Communications Ltd. (1996) - 23 Hasivim St. - Petach Tikva 49170 - ISRAEL - - 00-0B-A5 (hex) Quasar Cipta Mandiri, PT - 000BA5 (base 16) Quasar Cipta Mandiri, PT - Jl. Palasari 9A - Bandung West Java 40262 - INDONESIA - - 00-0B-A6 (hex) Miyakawa Electric Works Ltd. - 000BA6 (base 16) Miyakawa Electric Works Ltd. - 2-1-6, - Kohhoku-ku - Yokohama Kanagawa 222-0001 - JAPAN - - 00-0B-A7 (hex) Maranti Networks - 000BA7 (base 16) Maranti Networks - 3061-B Zanker Road - San Jose CA 95134 - UNITED STATES - - 00-0B-A8 (hex) HANBACK ELECTRONICS CO., LTD. - 000BA8 (base 16) HANBACK ELECTRONICS CO., LTD. - 306-7, Galma-dong, Seo-gu - Daejeon 302-171 - KOREA, REPUBLIC OF - - 00-0B-A9 (hex) CloudShield Technologies, Inc. - 000BA9 (base 16) CloudShield Technologies, Inc. - 212 Gilbraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-0B-AA (hex) Aiphone co.,Ltd - 000BAA (base 16) Aiphone co.,Ltd - 2-18 Jinno-Cho - Atsuta-ku - Nagoya Aichi-ken 456-8666 - JAPAN - - 00-0B-AB (hex) Advantech Technology (CHINA) Co., Ltd. - 000BAB (base 16) Advantech Technology (CHINA) Co., Ltd. - No.666, Han-Pu Rd. Yu-Shan - Kun-Shan Jiang Su 215316 - CHINA - - 00-0B-AC (hex) 3Com Ltd - 000BAC (base 16) 3Com Ltd - Peoplebuilding 2, Peoplebuilding Estate - Maylands Avenue - Hemel Hempstead Herts. HP2 4NW - UNITED KINGDOM - - 00-0B-AD (hex) PC-PoS Inc. - 000BAD (base 16) PC-PoS Inc. - 309 Commissioners Road West - London Ontario N6J 1Y4 - CANADA - - 00-0B-AE (hex) Vitals System Inc. - 000BAE (base 16) Vitals System Inc. - Jooheung B/D 4FL. 1005-1, Youngtong-Dong - Suwon City Kyonggi-Do 442-813 - KOREA, REPUBLIC OF - - 00-0B-AF (hex) WOOJU COMMUNICATIONS Co,.Ltd - 000BAF (base 16) WOOJU COMMUNICATIONS Co,.Ltd - B-713, SK Twin Tech Tower, 345-9, Ga-San - Seoul 153-802 - KOREA, REPUBLIC OF - - 00-0B-B0 (hex) Sysnet Telematica srl - 000BB0 (base 16) Sysnet Telematica srl - Viale Berbera, 49 - Milan 20162 - ITALY - - 00-0B-B1 (hex) Super Star Technology Co., Ltd. - 000BB1 (base 16) Super Star Technology Co., Ltd. - No. 7 Lane 306,Sec. 2,Tai-Lin Rd. - Tai-Shan Shiang - Taipei Hsien 243 - TAIWAN, PROVINCE OF CHINA - - 00-0B-B2 (hex) SMALLBIG TECHNOLOGY - 000BB2 (base 16) SMALLBIG TECHNOLOGY - 3F Dongsung Bldg. 720-9 Yoksamdong - Gangnamgu Seoul 135-080 - KOREA, REPUBLIC OF - - 00-0B-B3 (hex) RiT technologies Ltd. - 000BB3 (base 16) RiT technologies Ltd. - 24 Raoul Walenberg St. - Tel Aviv 69719 - ISRAEL - - 00-0B-B4 (hex) RDC Semiconductor Inc., - 000BB4 (base 16) RDC Semiconductor Inc., - 6F-1 , No.2-1, Lihsin Rd, Science-Based - Hsin Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0B-B5 (hex) nStor Technologies, Inc. - 000BB5 (base 16) nStor Technologies, Inc. - 100 Technology Park - Suite 175 - Lake Mary FL 32746 - UNITED STATES - - 00-0B-B6 (hex) Metalligence Technology Corp. - 000BB6 (base 16) Metalligence Technology Corp. - 9, Park Avenue II, Science-Based Industr - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0B-B7 (hex) Micro Systems Co.,Ltd. - 000BB7 (base 16) Micro Systems Co.,Ltd. - 2-15-34 Nishikubo - Musashino-City Tokyo 180-0013 - JAPAN - - 00-0B-B8 (hex) Kihoku Electronic Co. - 000BB8 (base 16) Kihoku Electronic Co. - Marukatubiru 3F 4-9-6 - Nihonbashi Naniwa-ku - Osakashi Osaka-hu 556-0005 - JAPAN - - 00-0B-B9 (hex) Imsys AB - 000BB9 (base 16) Imsys AB - Johanneslundsvagen 3 - Upplands Vasby SE-19461 - SWEDEN - - 00-0B-BA (hex) Harmonic, Inc - 000BBA (base 16) Harmonic, Inc - 4300 North First Street - San Jose CA 95134 - UNITED STATES - - 00-0B-BB (hex) Etin Systems Co., Ltd - 000BBB (base 16) Etin Systems Co., Ltd - 12F, IT Venture Tower, - 78 GarakBon-Dong, Songpa-Ku - Seoul 138-803 - KOREA, REPUBLIC OF - - 00-0B-BC (hex) En Garde Systems, Inc. - 000BBC (base 16) En Garde Systems, Inc. - 2101 White Cloud St. NE - Albuquerque NM 87112 - UNITED STATES - - 00-0B-BD (hex) Connexionz Limited - 000BBD (base 16) Connexionz Limited - 1 Show Place - Christchurch Canterbury 8004 - NEW ZEALAND - - 00-0B-BE (hex) CISCO SYSTEMS, INC. - 000BBE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-BF (hex) CISCO SYSTEMS, INC. - 000BBF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-C0 (hex) China IWNComm Co., Ltd. - 000BC0 (base 16) China IWNComm Co., Ltd. - 4F.C Xietong Building,No.12 Gaoxin 2nd r - Hi-tech industries development zone - Xi'an shaanxi 710075 - CHINA - - 00-0B-C1 (hex) Bay Microsystems, Inc. - 000BC1 (base 16) Bay Microsystems, Inc. - 2055 Gateway Place - Suite 650 - Santa Jose CA 95110 - UNITED STATES - - 00-0B-C2 (hex) Corinex Communication Corp. - 000BC2 (base 16) Corinex Communication Corp. - #308 1168 Hamilton Street - Vancouver B.C. V6B 2S2 - CANADA - - 00-0B-C3 (hex) Multiplex, Inc. - 000BC3 (base 16) Multiplex, Inc. - 5000 Hadley Rd. - S. Plainfield NJ 07040 - UNITED STATES - - 00-0B-C4 (hex) BIOTRONIK GmbH & Co - 000BC4 (base 16) BIOTRONIK GmbH & Co - Woermannkehre 1 - Berlin 12359 - GERMANY - - 00-0B-C5 (hex) SMC Networks, Inc. - 000BC5 (base 16) SMC Networks, Inc. - 38 Tesla - Irvine CA 92618 - UNITED STATES - - 00-0B-C6 (hex) ISAC, Inc. - 000BC6 (base 16) ISAC, Inc. - PO Box 7682 - Auburn CA 95604 - UNITED STATES - - 00-0B-C7 (hex) ICET S.p.A. - 000BC7 (base 16) ICET S.p.A. - Via Quarto Negroni, 63 - Cecchina di Ariccia Roma 00040 - ITALY - - 00-0B-C8 (hex) AirFlow Networks - 000BC8 (base 16) AirFlow Networks - 444 Castro St - Suite 320 - Mountain View Ca 94041 - UNITED STATES - - 00-0B-C9 (hex) Electroline Equipment - 000BC9 (base 16) Electroline Equipment - 8265 boul. St-Michel - Montreal Quebec H1Z 3E4 - CANADA - - 00-0B-CA (hex) DATAVAN International Corporation - 000BCA (base 16) DATAVAN International Corporation - 4FL,#120-12,Chung Shan Rd, Sec.3 - Chung Ho City, Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-0B-CB (hex) Fagor Automation , S. Coop - 000BCB (base 16) Fagor Automation , S. Coop - San Andres s/n - 20500 Mondragon - Guipuzcoa 20500 - SPAIN - - 00-0B-CC (hex) JUSAN, S.A. - 000BCC (base 16) JUSAN, S.A. - Vivero, 5 - MADRID 28040 - SPAIN - - 00-0B-CD (hex) Hewlett-Packard Company - 000BCD (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS040801 - Houston TX 77070 - UNITED STATES - - 00-0B-CE (hex) Free2move AB - 000BCE (base 16) Free2move AB - Sperlingsgatan 7 - Halmstad Halland 30248 - SWEDEN - - 00-0B-CF (hex) AGFA NDT INC. - 000BCF (base 16) AGFA NDT INC. - 50 Industrial Park Road - Lewistown PA 17044 - UNITED STATES - - 00-0B-D0 (hex) XiMeta Technology Americas Inc. - 000BD0 (base 16) XiMeta Technology Americas Inc. - 54 Ray Street - New Brunswick NJ 08901 - UNITED STATES - - 00-0B-D1 (hex) Aeronix, Inc. - 000BD1 (base 16) Aeronix, Inc. - 1775 W. Hibiscus Blvd, - Suite #304 - Melbourne FL 32901 - UNITED STATES - - 00-0B-D2 (hex) Remopro Technology Inc. - 000BD2 (base 16) Remopro Technology Inc. - No. 443, Huannan RD., - Pingjen City Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 00-0B-D3 (hex) cd3o - 000BD3 (base 16) cd3o - 402 W Broadway - San Deigo CA 92101 - UNITED STATES - - 00-0B-D4 (hex) Beijing Wise Technology & Science Development Co.Ltd - 000BD4 (base 16) Beijing Wise Technology & Science Development Co.Ltd - 3rd Floor Caihong Building, No.2,1st Wes - Madian, Haidian District - Beijing 100088 - CHINA - - 00-0B-D5 (hex) Nvergence, Inc. - 000BD5 (base 16) Nvergence, Inc. - Jeil Bldg. 4th, Samsung-dong 168-26, Kan - Seoul 135-090 - KOREA, REPUBLIC OF - - 00-0B-D6 (hex) Paxton Access Ltd - 000BD6 (base 16) Paxton Access Ltd - Paxton House - Home Farm Road - Brighton East Sussex BN1 9HU - UNITED KINGDOM - - 00-0B-D7 (hex) DORMA Time + Access GmbH - 000BD7 (base 16) DORMA Time + Access GmbH - Mainzer Straße 36-52 - Bonn Nordrheinwestfalen 53179 - GERMANY - - 00-0B-D8 (hex) Industrial Scientific Corp. - 000BD8 (base 16) Industrial Scientific Corp. - 1001 Oakdale Road - Oakdale PA 15071 - UNITED STATES - - 00-0B-D9 (hex) General Hydrogen - 000BD9 (base 16) General Hydrogen - 13120 Vanier Place - Richmond British Columbia V6V 2J2 - CANADA - - 00-0B-DA (hex) EyeCross Co.,Inc. - 000BDA (base 16) EyeCross Co.,Inc. - 3F Iioka-Building - Tokyo Ueno Taitoh-ku 3-4-1 110-0005 - JAPAN - - 00-0B-DB (hex) Dell Inc - 000BDB (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-0B-DC (hex) AKCP - 000BDC (base 16) AKCP - 67/285 Muangake Village #8 - Moo 3 Vipawadee Road, Tambol Lughook - Amphur Muang Patomthanee 12000 - THAILAND - - 00-0B-DD (hex) TOHOKU RICOH Co., LTD. - 000BDD (base 16) TOHOKU RICOH Co., LTD. - 3-1 Shinmeido - Shibata Miyagi pref. 989-1695 - JAPAN - - 00-0B-DE (hex) TELDIX GmbH - 000BDE (base 16) TELDIX GmbH - Grenzhoefer Weg 36 - Heidelberg 69123 - GERMANY - - 00-0B-DF (hex) Shenzhen RouterD Networks Limited - 000BDF (base 16) Shenzhen RouterD Networks Limited - 8/F, Building A, Tsinghua Hi-Tech Park - Nanshan District - Shenzhen - CHINA - - 00-0B-E0 (hex) SercoNet Ltd. - 000BE0 (base 16) SercoNet Ltd. - 16 Ha'haroshet st. - P.O.B. 2009 - Ra'anana 43657 - ISRAEL - - 00-0B-E1 (hex) Nokia NET Product Operations - 000BE1 (base 16) Nokia NET Product Operations - 313 Fairchild Drive - Mountain View California 94043 - UNITED STATES - - 00-0B-E2 (hex) Lumenera Corporation - 000BE2 (base 16) Lumenera Corporation - 2520B St. Laurent Blvd. - Ottawa Ontario K1B 4R8 - CANADA - - 00-0B-E3 (hex) Key Stream Co., Ltd. - 000BE3 (base 16) Key Stream Co., Ltd. - No. 2 Nagaoka Bldg. 4F, 2-8-5 Hatchobor - Chuo-ku Tokyo 104-0032 - JAPAN - - 00-0B-E4 (hex) Hosiden Corporation - 000BE4 (base 16) Hosiden Corporation - 4-33 - Kitakyuhoji 1-chome - Yao-city Osaka 581-0071 - JAPAN - - 00-0B-E5 (hex) HIMS International Corporation - 000BE5 (base 16) HIMS International Corporation - 139-9, - Gajung-dong, Yuseong-gu - Daejeon Daejeon 305-350 - KOREA, REPUBLIC OF - - 00-0B-E6 (hex) Datel Electronics - 000BE6 (base 16) Datel Electronics - Stafford Road - Stone Staffordshire ST15 0DG - UNITED KINGDOM - - 00-0B-E7 (hex) COMFLUX TECHNOLOGY INC. - 000BE7 (base 16) COMFLUX TECHNOLOGY INC. - Room 131,Bldg. 53,195-58,Sec.4, - Chung Hsing Rd.,Chutung, - Hsinchu 310 - TAIWAN, PROVINCE OF CHINA - - 00-0B-E8 (hex) AOIP - 000BE8 (base 16) AOIP - 6 rue Maryse BASTIE - ZI de St Guenault - COURCOURONNES Idf 91080 - FRANCE - - 00-0B-E9 (hex) Actel Corporation - 000BE9 (base 16) Actel Corporation - 200 Valley Road - Suite 300 - Mt. Arlington NJ 07856 - UNITED STATES - - 00-0B-EA (hex) Zultys Technologies - 000BEA (base 16) Zultys Technologies - 785 Lucern Drive - Sunnyvale CA 94085 - UNITED STATES - - 00-0B-EB (hex) Systegra AG - 000BEB (base 16) Systegra AG - Burgunderstrasse 15 - Bellach SO 4512 - SWITZERLAND - - 00-0B-EC (hex) NIPPON ELECTRIC INSTRUMENT, INC. - 000BEC (base 16) NIPPON ELECTRIC INSTRUMENT, INC. - 3-56-21 Hirado - Totsuka-ku Yokohama-shi 244-0802 - JAPAN - - 00-0B-ED (hex) ELM Inc. - 000BED (base 16) ELM Inc. - 2398 Kasedamiyahara - Minamisatsuma Kagoshima 897-1123 - JAPAN - - 00-0B-EE (hex) inc.jet, Incorporated - 000BEE (base 16) inc.jet, Incorporated - One Winnenden Road - Norwich CT 06360 - UNITED STATES - - 00-0B-EF (hex) Code Corporation - 000BEF (base 16) Code Corporation - 11814 S. Election Rd., Ste 200 - Draper Utah 84020 - UNITED STATES - - 00-0B-F0 (hex) MoTEX Products Co., Ltd. - 000BF0 (base 16) MoTEX Products Co., Ltd. - C.P.O.Box 6912 - Ye Kwan-dong 19-1 - Chong-gu Seoul 82 - KOREA, REPUBLIC OF - - 00-0B-F1 (hex) LAP Laser Applikations - 000BF1 (base 16) LAP Laser Applikations - Zeppelinstraße 23 - Lüneburg Niedersachsen 21337 - GERMANY - - 00-0B-F2 (hex) Chih-Kan Technology Co., Ltd. - 000BF2 (base 16) Chih-Kan Technology Co., Ltd. - No. 24-1, Pei Shih Chou, Ming Ho Vill. - Shan Sun Hsiang Tainan Hsien 180 - TAIWAN, PROVINCE OF CHINA - - 00-0B-F3 (hex) BAE SYSTEMS - 000BF3 (base 16) BAE SYSTEMS - 6500 Tracor Lane - Austin Texas 78725 - UNITED STATES - - 00-0B-F4 (hex) PRIVATE - 000BF4 (base 16) - - 00-0B-F5 (hex) Shanghai Sibo Telecom Technology Co.,Ltd - 000BF5 (base 16) Shanghai Sibo Telecom Technology Co.,Ltd - Floor 6 Building 18,300 Tianlin Rd. - Shanghai 200233 - CHINA - - 00-0B-F6 (hex) Nitgen Co., Ltd - 000BF6 (base 16) Nitgen Co., Ltd - 4th FL. 1337-31 Seocho-dong, Seocho-ku - Seoul 137-860 - KOREA, REPUBLIC OF - - 00-0B-F7 (hex) NIDEK CO.,LTD - 000BF7 (base 16) NIDEK CO.,LTD - 34-14 Maehama - Hiroishi-cho - Gamagori Aich 443-0038 - JAPAN - - 00-0B-F8 (hex) Infinera - 000BF8 (base 16) Infinera - 1322 Bordeaux Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-0B-F9 (hex) Gemstone communications, Inc. - 000BF9 (base 16) Gemstone communications, Inc. - 6Fl., No. 102, Hengyang Rd. - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-0B-FA (hex) EXEMYS SRL - 000BFA (base 16) EXEMYS SRL - LOYOLA 680 - CAPITAL FEDERAL BS AS C1414 - ARGENTINA - - 00-0B-FB (hex) D-NET International Corporation - 000BFB (base 16) D-NET International Corporation - 15, Wu-Chuan 5th Road, Wu-Ku Industrial - Taipei Hsieh 248 - TAIWAN, PROVINCE OF CHINA - - 00-0B-FC (hex) CISCO SYSTEMS, INC. - 000BFC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-FD (hex) CISCO SYSTEMS, INC. - 000BFD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0B-FE (hex) CASTEL Broadband Limited - 000BFE (base 16) CASTEL Broadband Limited - 9/F., Sui Ying Industrial Building., - Tokwawan Kowloon 150 - HONG KONG - - 00-0B-FF (hex) Berkeley Camera Engineering - 000BFF (base 16) Berkeley Camera Engineering - 127 National Street - Santa Cruz CA 95060 - UNITED STATES - - 00-0C-00 (hex) BEB Industrie-Elektronik AG - 000C00 (base 16) BEB Industrie-Elektronik AG - Progressastrasse 31 - Oberburg BE 3414 - SWITZERLAND - - 00-0C-01 (hex) Abatron AG - 000C01 (base 16) Abatron AG - Lettenstrasse 9 - Rotkreuz CH-6343 - SWITZERLAND - - 00-0C-02 (hex) ABB Oy - 000C02 (base 16) ABB Oy - P.O.Box 89 - Turku FIN-20521 - FINLAND - - 00-0C-03 (hex) HDMI Licensing, LLC - 000C03 (base 16) HDMI Licensing, LLC - 1060 East Arques Ave. - Suite 100 - Sunnyvale CA 94085 - UNITED STATES - - 00-0C-04 (hex) Tecnova - 000C04 (base 16) Tecnova - 1486 St. Paul Ave. - Gurnee Illinois 60031 - UNITED STATES - - 00-0C-05 (hex) RPA Reserch Co., Ltd. - 000C05 (base 16) RPA Reserch Co., Ltd. - 4F, 90-7, Yangjae-Dong, Seocho-Ku - Seoul, Korea - Seoul 137-130 - KOREA, REPUBLIC OF - - 00-0C-06 (hex) Nixvue Systems Pte Ltd - 000C06 (base 16) Nixvue Systems Pte Ltd - 30 Loyang Way, #07-02 - Singapore Singapore S508769 - SINGAPORE - - 00-0C-07 (hex) Iftest AG - 000C07 (base 16) Iftest AG - Schwimmbadstrasse 43 - Wettingen AG 5430 - SWITZERLAND - - 00-0C-08 (hex) HUMEX Technologies Corp. - 000C08 (base 16) HUMEX Technologies Corp. - 5F, No.5, Lane 44, Szu Wei Rd. Taan Taip - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-0C-09 (hex) Hitachi IE Systems Co., Ltd - 000C09 (base 16) Hitachi IE Systems Co., Ltd - Saiwai-cho 120-1,Inazawa-shi - Aichi 492-8622,Japan - Inazawa-shi Aichi 492-8622 - JAPAN - - 00-0C-0A (hex) Guangdong Province Electronic Technology Research Institute - 000C0A (base 16) Guangdong Province Electronic Technology Research Institute - Electronic Technology Building,NO.61-65, - West Zhongshan Avenue,Tianhe District - Guangzhou Guangdong 510630 - CHINA - - 00-0C-0B (hex) Broadbus Technologies - 000C0B (base 16) Broadbus Technologies - 80 Central Street - Boxborough Massachusetts 01719 - UNITED STATES - - 00-0C-0C (hex) APPRO TECHNOLOGY INC. - 000C0C (base 16) APPRO TECHNOLOGY INC. - 13F, No. 66 Chung-Cheng Rd, - Hsin-Chuang Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 00-0C-0D (hex) Communications & Power Industries / Satcom Division - 000C0D (base 16) Communications & Power Industries / Satcom Division - 811 Hansen Way MS S-600 - Palo Alto CA 94303 - UNITED STATES - - 00-0C-0E (hex) XtremeSpectrum, Inc. - 000C0E (base 16) XtremeSpectrum, Inc. - 8133 Leesburg Pike - Vienna VA 22182 - UNITED STATES - - 00-0C-0F (hex) Techno-One Co., Ltd - 000C0F (base 16) Techno-One Co., Ltd - 9-17-1 Higashi Sonoda - Amagasaki Hyogo 661-0953 - JAPAN - - 00-0C-10 (hex) PNI Corporation - 000C10 (base 16) PNI Corporation - 5464 Skylane Blvd #A - Santa Rosa CA 95403 - UNITED STATES - - 00-0C-11 (hex) NIPPON DEMPA CO.,LTD. - 000C11 (base 16) NIPPON DEMPA CO.,LTD. - 1-4-8 - kamenokou - kakegawa city shizuoka pref. 436-0028 - JAPAN - - 00-0C-12 (hex) Micro-Optronic-Messtechnik GmbH - 000C12 (base 16) Micro-Optronic-Messtechnik GmbH - Lessingstrasse 14 - Langebrück Saxony D-01465 - GERMANY - - 00-0C-13 (hex) MediaQ - 000C13 (base 16) MediaQ - 2975 San Ysidro Way - Santa Clara CA 95051 - UNITED STATES - - 00-0C-14 (hex) Diagnostic Instruments, Inc. - 000C14 (base 16) Diagnostic Instruments, Inc. - 6540 Burroughs - Sterling Heights MI 48314 - UNITED STATES - - 00-0C-15 (hex) CyberPower Systems, Inc. - 000C15 (base 16) CyberPower Systems, Inc. - 6F, No. 32, Sec. 1, Chenggong Rd. - Nanhang District - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-0C-16 (hex) Concorde Microsystems Inc. - 000C16 (base 16) Concorde Microsystems Inc. - 10427 Cogdill Road, Suite 500 - Knoxville TN 37932 - UNITED STATES - - 00-0C-17 (hex) AJA Video Systems Inc - 000C17 (base 16) AJA Video Systems Inc - 443 Crown Point Circle - Grass Valley California 95945 - UNITED STATES - - 00-0C-18 (hex) Zenisu Keisoku Inc. - 000C18 (base 16) Zenisu Keisoku Inc. - 2-13-37 - Honmachi - Fuchu-shi Tokyo 183-0027 - JAPAN - - 00-0C-19 (hex) Telio Communications GmbH - 000C19 (base 16) Telio Communications GmbH - Elbchaussee 1 - Hamburg 22765 - GERMANY - - 00-0C-1A (hex) Quest Technical Solutions Inc. - 000C1A (base 16) Quest Technical Solutions Inc. - 4110 Mourning Dove Crt. - Melbourne FL 32934 - UNITED STATES - - 00-0C-1B (hex) ORACOM Co, Ltd. - 000C1B (base 16) ORACOM Co, Ltd. - 3rd Fl, A-Sung Bldg, 999-3 - Deachi-Dong, Kangnam-Gu - Seoul 135-280 - KOREA, REPUBLIC OF - - 00-0C-1C (hex) MicroWeb Co., Ltd. - 000C1C (base 16) MicroWeb Co., Ltd. - 403 T/S/S/C, 23-14 Jang-dong, Yusong-gu, - Daejeon ChoongChungDo 305-343 - KOREA, REPUBLIC OF - - 00-0C-1D (hex) Mettler & Fuchs AG - 000C1D (base 16) Mettler & Fuchs AG - Querstrasse 17 - CH-8951 Fahrweid - SWITZERLAND - - 00-0C-1E (hex) Global Cache - 000C1E (base 16) Global Cache - 160 East California Street - POB 1659 - Jacksonville OR 97530 - UNITED STATES - - 00-0C-1F (hex) Glimmerglass Networks - 000C1F (base 16) Glimmerglass Networks - 26142 Eden Landing Road - Hayward California 94545 - UNITED STATES - - 00-0C-20 (hex) Fi WIn, Inc. - 000C20 (base 16) Fi WIn, Inc. - 8F, No. 10, Prosperity Rd. 1, - Science Based Industrial Park - Hsin Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0C-21 (hex) Faculty of Science and Technology, Keio University - 000C21 (base 16) Faculty of Science and Technology, Keio University - 3-14-1 Hiyoshi, Kohoku-ku - Yokohama Kanagawa 223-8522 - JAPAN - - 00-0C-22 (hex) Double D Electronics Ltd - 000C22 (base 16) Double D Electronics Ltd - Unit 6, Robins Wharf - Grove Road - Northfleet Kent DA11 9AX - UNITED KINGDOM - - 00-0C-23 (hex) Beijing Lanchuan Tech. Co., Ltd. - 000C23 (base 16) Beijing Lanchuan Tech. Co., Ltd. - Rm220,No.30 Shangyuancun, - Gaoliangqiaolu,Haidian District - Beijing 100044 - CHINA - - 00-0C-24 (hex) ANATOR - 000C24 (base 16) ANATOR - 44, rue d'Estienne d'Orves - sartrouville yvelines 78500 - FRANCE - - 00-0C-25 (hex) Allied Telesis Labs, Inc. - 000C25 (base 16) Allied Telesis Labs, Inc. - Suite 450 - 900 Main Campus Drive, Suite 301 - Raleigh NC 27606 - UNITED STATES - - 00-0C-26 (hex) Weintek Labs. Inc. - 000C26 (base 16) Weintek Labs. Inc. - 3F, No.910, Chung Cheng Rd. - Chung Ho city Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-0C-27 (hex) Sammy Corporation - 000C27 (base 16) Sammy Corporation - SUN SHINE60 45F,3-1-1,HIGASHI-IKEBUKURO - TOSHIMA-KU TOKYO 170-6045 - JAPAN - - 00-0C-28 (hex) RIFATRON - 000C28 (base 16) RIFATRON - 9th FL, SHINTAEYANG BLDG - 736-8, BANPO-DONG - SEOUL SEOCHO-GU 137-041 - KOREA, REPUBLIC OF - - 00-0C-29 (hex) VMware, Inc. - 000C29 (base 16) VMware, Inc. - 3401 Hillview Avenue - Palo Alto CA 94304 - UNITED STATES - - 00-0C-2A (hex) OCTTEL Communication Co., Ltd. - 000C2A (base 16) OCTTEL Communication Co., Ltd. - 7F-1, No.300, Daduen 10th St. - Taichung City 408 - TAIWAN, PROVINCE OF CHINA - - 00-0C-2B (hex) ELIAS Technology, Inc. - 000C2B (base 16) ELIAS Technology, Inc. - 3F, 1015, Yung-An Road, - Taoyuan City Taoyuan 330 - TAIWAN, PROVINCE OF CHINA - - 00-0C-2C (hex) Enwiser Inc. - 000C2C (base 16) Enwiser Inc. - 4F, Cheongseok B/D - 135-11, Nonhyeon-dong, Kangnam-ku - Seoul Seoul 135-010 - KOREA, REPUBLIC OF - - 00-0C-2D (hex) FullWave Technology Co., Ltd. - 000C2D (base 16) FullWave Technology Co., Ltd. - 7F-6, No.26, TaiYuan St., - JuBei Hsin Chu 302 - TAIWAN, PROVINCE OF CHINA - - 00-0C-2E (hex) Openet information technology(shenzhen) Co., Ltd. - 000C2E (base 16) Openet information technology(shenzhen) Co., Ltd. - 2/F,A tower,international tech-innovatio - high-tech industrial park ,shenzhen, P.R - shenzhen guangdong 518057 - CHINA - - 00-0C-2F (hex) SeorimTechnology Co.,Ltd. - 000C2F (base 16) SeorimTechnology Co.,Ltd. - 2F DIPLOMATIC CENTER B/D 1376-1 SEOCHO2- - SEOUL 137-072 - KOREA, REPUBLIC OF - - 00-0C-30 (hex) CISCO SYSTEMS, INC. - 000C30 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0C-31 (hex) CISCO SYSTEMS, INC. - 000C31 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0C-32 (hex) Avionic Design Development GmbH - 000C32 (base 16) Avionic Design Development GmbH - Sthamerstrasse 24a - Hamburg 22397 - GERMANY - - 00-0C-33 (hex) Compucase Enterprise Co. Ltd. - 000C33 (base 16) Compucase Enterprise Co. Ltd. - 225 Lane 54, An Ho Road, Section 2nd. - Tainan City 70942 - TAIWAN, PROVINCE OF CHINA - - 00-0C-34 (hex) Vixen Co., Ltd. - 000C34 (base 16) Vixen Co., Ltd. - 5-17-3 Higashitokorozawa - Tokorozawa Saitama 359-0021 - JAPAN - - 00-0C-35 (hex) KaVo Dental GmbH & Co. KG - 000C35 (base 16) KaVo Dental GmbH & Co. KG - Bismarkring 39 - Biberach/Riss Baden-Württemberg 88400 - GERMANY - - 00-0C-36 (hex) SHARP TAKAYA ELECTRONICS INDUSTRY CO.,LTD. - 000C36 (base 16) SHARP TAKAYA ELECTRONICS INDUSTRY CO.,LTD. - 3121-1 Satomi Satosho-cho - Asakuchi-gun Okayama 719-0301 - JAPAN - - 00-0C-37 (hex) Geomation, Inc. - 000C37 (base 16) Geomation, Inc. - 25188 Genesee Trail Road - Suite 100 - Golden CO 80401 - UNITED STATES - - 00-0C-38 (hex) TelcoBridges Inc. - 000C38 (base 16) TelcoBridges Inc. - 586 Du Chenal - Repentigny Quebec J6A 7C5 - CANADA - - 00-0C-39 (hex) Sentinel Wireless Inc. - 000C39 (base 16) Sentinel Wireless Inc. - 439 S. Union St. - South Lawrence MA 01843 - UNITED STATES - - 00-0C-3A (hex) Oxance - 000C3A (base 16) Oxance - 75-85 rue Richelieu - les Lucs sur Boulogne 85170 - FRANCE - - 00-0C-3B (hex) Orion Electric Co., Ltd. - 000C3B (base 16) Orion Electric Co., Ltd. - 41-1, Iehisa-cho - Takefu-shi Fukui 915-8555 - JAPAN - - 00-0C-3C (hex) MediaChorus, Inc. - 000C3C (base 16) MediaChorus, Inc. - #205, ETRI TBI 2 Center - Ueun-Dong, Yusong-Gu - Daejon DJ 305-333 - KOREA, REPUBLIC OF - - 00-0C-3D (hex) Glsystech Co., Ltd. - 000C3D (base 16) Glsystech Co., Ltd. - Song Bo B/D 3F - 212-10, Kung-Dong, Kuro Gu - Seoul 152-883 - KOREA, REPUBLIC OF - - 00-0C-3E (hex) Crest Audio - 000C3E (base 16) Crest Audio - 16-00 Pollitt Drive - Fair Lawn NJ 07410 - UNITED STATES - - 00-0C-3F (hex) Cogent Defence & Security Networks, - 000C3F (base 16) Cogent Defence & Security Networks, - Meadows Road, - Queensway Meadows Ind Estate, - Newport, South Wales, NP19 4SS - UNITED KINGDOM - - 00-0C-40 (hex) Altech Controls - 000C40 (base 16) Altech Controls - 1545 Industial Drive - Missouri City Texas 77489 - UNITED STATES - - 00-0C-41 (hex) Cisco-Linksys - 000C41 (base 16) Cisco-Linksys - 121 Theory Dr. - Irvine CA 92612 - UNITED STATES - - 00-0C-42 (hex) Routerboard.com - 000C42 (base 16) Routerboard.com - Pernavas 46 - Riga LV-1009 - LATVIA - - 00-0C-43 (hex) Ralink Technology, Corp. - 000C43 (base 16) Ralink Technology, Corp. - 4F, No.2, Technology 5th Road, - Science-Based Industrial Park, - Hsin-Chu 200 - TAIWAN, PROVINCE OF CHINA - - 00-0C-44 (hex) Automated Interfaces, Inc. - 000C44 (base 16) Automated Interfaces, Inc. - 120 Confederate Lane - Greer South Carolina 29651 - UNITED STATES - - 00-0C-45 (hex) Animation Technologies Inc. - 000C45 (base 16) Animation Technologies Inc. - 8F,No.138,Lane 235,Paochiao Road, - Hsin Tien - Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-0C-46 (hex) Allied Telesyn Inc. - 000C46 (base 16) Allied Telesyn Inc. - 960 Stewart Drive, Suite B - Sunnyvale California 94085 - UNITED STATES - - 00-0C-47 (hex) SK Teletech(R&D Planning Team) - 000C47 (base 16) SK Teletech(R&D Planning Team) - 21th FL Startower 737, Yeoksam-dong - Kangnam-Ku - Seoul 135-984 - KOREA, REPUBLIC OF - - 00-0C-48 (hex) QoStek Corporation - 000C48 (base 16) QoStek Corporation - 7F, 22, Taiyuen Street - Chupei Hsinchu Hsien 302 - TAIWAN, PROVINCE OF CHINA - - 00-0C-49 (hex) Dangaard Telecom RTC Division A/S - 000C49 (base 16) Dangaard Telecom RTC Division A/S - Industrivej 1 - DK 26154553 - Padborg DK-6330 - DENMARK - - 00-0C-4A (hex) Cygnus Microsystems (P) Limited - 000C4A (base 16) Cygnus Microsystems (P) Limited - 93, Phase II, - IDA, Cherlapally - Hyderabad Andhra Pradesh 500051 - INDIA - - 00-0C-4B (hex) Cheops Elektronik - 000C4B (base 16) Cheops Elektronik - Jeschkenstrasse 32 - Geretsried Bayern 82538 - GERMANY - - 00-0C-4C (hex) Arcor AG&Co. - 000C4C (base 16) Arcor AG&Co. - Alfred-Herrhausen-Allee 1 - Eschborn Hessen 65760 - GERMANY - - 00-0C-4D (hex) Curtiss-Wright Controls Avionics & Electronics - 000C4D (base 16) Curtiss-Wright Controls Avionics & Electronics - Landscape House, - Landscape Road, - Churchtown, Dublin 14 - IRELAND - - 00-0C-4E (hex) Winbest Technology CO,LT - 000C4E (base 16) Winbest Technology CO,LT - 7F-5No.736 Chung ChengRd.,ChungHo - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-0C-4F (hex) UDTech Japan Corporation - 000C4F (base 16) UDTech Japan Corporation - Hamacho Hanacho Bldg, 2F - 2-17-8 Nihonbashi-Hamacho - Chuo-ku Tokyo 103-0007 - JAPAN - - 00-0C-50 (hex) Seagate Technology - 000C50 (base 16) Seagate Technology - M/S NW1F01 - 389 Disc Drive - Longmont CO 80503 - UNITED STATES - - 00-0C-51 (hex) Scientific Technologies Inc. - 000C51 (base 16) Scientific Technologies Inc. - 6550 Dumbarton Circle - Fremont CA 94560 - UNITED STATES - - 00-0C-52 (hex) Roll Systems Inc. - 000C52 (base 16) Roll Systems Inc. - 53 Third Avenue - Burlington MA 01803 - UNITED STATES - - 00-0C-53 (hex) PRIVATE - 000C53 (base 16) - - 00-0C-54 (hex) Pedestal Networks, Inc - 000C54 (base 16) Pedestal Networks, Inc - 6503 Dumbarton Circle - Fremont CA 94555 - UNITED STATES - - 00-0C-55 (hex) Microlink Communications Inc. - 000C55 (base 16) Microlink Communications Inc. - 8F, 31, Hsintai Road - Chupei City - Hsinchu 302 - TAIWAN, PROVINCE OF CHINA - - 00-0C-56 (hex) Megatel Computer (1986) Corp. - 000C56 (base 16) Megatel Computer (1986) Corp. - 586 Main Street - Glen Williams Ontario L7G 3T6 - CANADA - - 00-0C-57 (hex) MACKIE Engineering Services Belgium BVBA - 000C57 (base 16) MACKIE Engineering Services Belgium BVBA - Industriepark Noord 10 - Sint Niklaas B-9100 - BELGIUM - - 00-0C-58 (hex) M&S Systems - 000C58 (base 16) M&S Systems - 2861 Congressman Lane - Dallas TX 75220 - UNITED STATES - - 00-0C-59 (hex) Indyme Electronics, Inc. - 000C59 (base 16) Indyme Electronics, Inc. - 9085 Aero Dr. - San Diego CA 92123 - UNITED STATES - - 00-0C-5A (hex) IBSmm Embedded Electronics Consulting - 000C5A (base 16) IBSmm Embedded Electronics Consulting - Teufelsgrabenweg 1 - Grub - Valley Bavaria D-83626 - GERMANY - - 00-0C-5B (hex) HANWANG TECHNOLOGY CO.,LTD - 000C5B (base 16) HANWANG TECHNOLOGY CO.,LTD - 8F,Automation Building,95 Zhongguancun, - Haidian District - Beijing 100080 - CHINA - - 00-0C-5C (hex) GTN Systems B.V. - 000C5C (base 16) GTN Systems B.V. - Postbus 12236 - 1100 AE - Amsterdam - NETHERLANDS - - 00-0C-5D (hex) CHIC TECHNOLOGY (CHINA) CORP. - 000C5D (base 16) CHIC TECHNOLOGY (CHINA) CORP. - 7th Building,Shi'ao Ind.Zone,Longhua Tow - Shenzhen Guangdong 518109 - CHINA - - 00-0C-5E (hex) Calypso Medical - 000C5E (base 16) Calypso Medical - 2101 Fourth Avenue, Suite 1550 - Seattle WA 98121 - UNITED STATES - - 00-0C-5F (hex) Avtec, Inc. - 000C5F (base 16) Avtec, Inc. - 4335 Augusta Hwy - Gilbert SC 29054 - UNITED STATES - - 00-0C-60 (hex) ACM Systems - 000C60 (base 16) ACM Systems - 3034 Gold Canal Drive - Rancho Cordova CA 95670 - UNITED STATES - - 00-0C-61 (hex) AC Tech corporation DBA Advanced Digital - 000C61 (base 16) AC Tech corporation DBA Advanced Digital - 1250-G Avenida Acaso - Camarillo CA 93010 - UNITED STATES - - 00-0C-62 (hex) ABB AB, Cewe-Control - 000C62 (base 16) ABB AB, Cewe-Control - Dept. LPCC/RE - Motorgrand 20 - Vasteras 721 61 - SWEDEN - - 00-0C-63 (hex) Zenith Electronics Corporation - 000C63 (base 16) Zenith Electronics Corporation - 2000 Millbrook Drive - Lincolnshire Illinois 60069 - UNITED STATES - - 00-0C-64 (hex) X2 MSA Group - 000C64 (base 16) X2 MSA Group - Care of: Agilent Technologies - White House Road - Ipswich, Suffolk IP1 5PB - UNITED KINGDOM - - 00-0C-65 (hex) Sunin Telecom - 000C65 (base 16) Sunin Telecom - 1025-5 Dokok-Ri, Wabu-Eub - Namyangju-City Kyunggi-Do 472-900 - KOREA, REPUBLIC OF - - 00-0C-66 (hex) Pronto Networks Inc - 000C66 (base 16) Pronto Networks Inc - 4637 Chabot Dr - Suite 300 - Pleasanton CA 94588 - UNITED STATES - - 00-0C-67 (hex) OYO ELECTRIC CO.,LTD - 000C67 (base 16) OYO ELECTRIC CO.,LTD - 63-1 Nakamichi Omote - Hirakawa - Joyo Kyoto 610-0101 - JAPAN - - 00-0C-68 (hex) SigmaTel, Inc. - 000C68 (base 16) SigmaTel, Inc. - 201 Jones Road - Waltham MA 02451 - UNITED STATES - - 00-0C-69 (hex) National Radio Astronomy Observatory - 000C69 (base 16) National Radio Astronomy Observatory - P.O. Box O - Socorro NM 87801 - UNITED STATES - - 00-0C-6A (hex) MBARI - 000C6A (base 16) MBARI - 7700 Sandholdt Road - Moss Landing CA 95039 - UNITED STATES - - 00-0C-6B (hex) Kurz Industrie-Elektronik GmbH - 000C6B (base 16) Kurz Industrie-Elektronik GmbH - Foehrenbachstraße 3 - Remshalden Baden-Württemberg 73630 - GERMANY - - 00-0C-6C (hex) Elgato Systems LLC - 000C6C (base 16) Elgato Systems LLC - 900 Kearny St #750 - San Francisco CA 94133 - UNITED STATES - - 00-0C-6D (hex) Edwards Ltd. - 000C6D (base 16) Edwards Ltd. - Marshall Road - Eastbourne East Sussex BN22 9BA - UNITED KINGDOM - - 00-0C-6E (hex) ASUSTEK COMPUTER INC. - 000C6E (base 16) ASUSTEK COMPUTER INC. - 150, Li-Te Rd., PeiTou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-0C-6F (hex) Amtek system co.,LTD. - 000C6F (base 16) Amtek system co.,LTD. - 14F-11,No.79,Sec. 1 ,Hsin Tai Wu Rd., - Hsi Chih City - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-0C-70 (hex) ACC GmbH - 000C70 (base 16) ACC GmbH - Am Sandfeld 15 - Karlsruhe Baden 76149 - GERMANY - - 00-0C-71 (hex) Wybron, Inc - 000C71 (base 16) Wybron, Inc - 4830 LIst Dr - Colorado Springs Colorado 80919 - UNITED STATES - - 00-0C-72 (hex) Tempearl Industrial Co., Ltd. - 000C72 (base 16) Tempearl Industrial Co., Ltd. - 3-1-42 Ohzu - Minami-ku - Hiroshima-shi Hiroshima 732-0802 - JAPAN - - 00-0C-73 (hex) TELSON ELECTRONICS CO., LTD - 000C73 (base 16) TELSON ELECTRONICS CO., LTD - Telson Venture Tower., 949-3 Dogok-Dong - Seoul Kangnam-Ku 135-739 - KOREA, REPUBLIC OF - - 00-0C-74 (hex) RIVERTEC CORPORATION - 000C74 (base 16) RIVERTEC CORPORATION - 882-5 MIYAGASAKI - IMABARI EHIME 799-1537 - JAPAN - - 00-0C-75 (hex) Oriental integrated electronics. LTD - 000C75 (base 16) Oriental integrated electronics. LTD - 281-34 Dondang-dong Wonmi-Gu - Bucheon Kyoungkido 420-808 - KOREA, REPUBLIC OF - - 00-0C-76 (hex) MICRO-STAR INTERNATIONAL CO., LTD. - 000C76 (base 16) MICRO-STAR INTERNATIONAL CO., LTD. - No 69, Li-De Street, Jung-He City, Taipe - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-0C-77 (hex) Life Racing Ltd - 000C77 (base 16) Life Racing Ltd - Unit 6 Repton Close - Burnt Mills Ind Est - Basildon Essex SS13 1LE - UNITED KINGDOM - - 00-0C-78 (hex) In-Tech Electronics Limited - 000C78 (base 16) In-Tech Electronics Limited - Unit A, 13th Floor., Wing Tai Centre - 12 Hing Yip Street - Kwun Tong Kowloon - HONG KONG - - 00-0C-79 (hex) Extel Communications P/L - 000C79 (base 16) Extel Communications P/L - 399 Ferntree Gully Road - Mt Waverley Victoria 3149 - AUSTRALIA - - 00-0C-7A (hex) DaTARIUS Technologies GmbH - 000C7A (base 16) DaTARIUS Technologies GmbH - Anton Maria Schyrle Str. 7 - Reutte Tirol 6600 - AUSTRIA - - 00-0C-7B (hex) ALPHA PROJECT Co.,Ltd. - 000C7B (base 16) ALPHA PROJECT Co.,Ltd. - 834 Sekishi,Higashi-ku,Hamamatsu-city - Shizuoka 431-3114 - JAPAN - - 00-0C-7C (hex) Internet Information Image Inc. - 000C7C (base 16) Internet Information Image Inc. - Fl. 6, No. 1, Alley 20, Lane 26, Rueigua - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0C-7D (hex) TEIKOKU ELECTRIC MFG. CO., LTD - 000C7D (base 16) TEIKOKU ELECTRIC MFG. CO., LTD - 60, HIRANO - SHINGU-CHO - IBO-GUN HYOGO 679-4395 - JAPAN - - 00-0C-7E (hex) Tellium Incorporated - 000C7E (base 16) Tellium Incorporated - 2 Crescent Place - Oceanport New Jersey 07757 - UNITED STATES - - 00-0C-7F (hex) synertronixx GmbH - 000C7F (base 16) synertronixx GmbH - Lange Laube 22 - Hannover Niedersachsen 30159 - GERMANY - - 00-0C-80 (hex) Opelcomm Inc. - 000C80 (base 16) Opelcomm Inc. - 46750 Fremont Blvd. Ste 210 - Fremont CA 94538 - UNITED STATES - - 00-0C-81 (hex) Schneider Electric (Australia) - 000C81 (base 16) Schneider Electric (Australia) - 80 Schneider Road - Eagle Farm Qld 4009 - AUSTRALIA - - 00-0C-82 (hex) NETWORK TECHNOLOGIES INC - 000C82 (base 16) NETWORK TECHNOLOGIES INC - 1275 DANNER DRIVE - AURORA OH 44202 - UNITED STATES - - 00-0C-83 (hex) Logical Solutions - 000C83 (base 16) Logical Solutions - 100T Washington Street - Milford CT 06460 - UNITED STATES - - 00-0C-84 (hex) Eazix, Inc. - 000C84 (base 16) Eazix, Inc. - Unit 301 Plaza Building B - 6530 Northgate Avenue, Filinvest - Muntinlupa City Rizal 1770 - PHILIPPINES - - 00-0C-85 (hex) CISCO SYSTEMS, INC. - 000C85 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0C-86 (hex) CISCO SYSTEMS, INC. - 000C86 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0C-87 (hex) AMD - 000C87 (base 16) AMD - 4555 Great America Pkwy - Ste 501 - Santa Clara CA 95054 - UNITED STATES - - 00-0C-88 (hex) Apache Micro Peripherals, Inc. - 000C88 (base 16) Apache Micro Peripherals, Inc. - 17526 Von Karman Ave - Irvine CA 92614 - UNITED STATES - - 00-0C-89 (hex) AC Electric Vehicles, Ltd. - 000C89 (base 16) AC Electric Vehicles, Ltd. - Markkinakuja 3 - Jokela 05400 - FINLAND - - 00-0C-8A (hex) Bose Corporation - 000C8A (base 16) Bose Corporation - Automotive Systems Division (ASD) - 688 Great Road (Mailstop: 1W2) - Stow MA 01775-9102 - UNITED STATES - - 00-0C-8B (hex) Connect Tech Inc - 000C8B (base 16) Connect Tech Inc - 42 Arrow Road - Guelph Ontario N1K 1S6 - CANADA - - 00-0C-8C (hex) KODICOM CO.,LTD. - 000C8C (base 16) KODICOM CO.,LTD. - A-Dong 5FI.,SK Twin Tower 345-9, - Gasan-Dong, Guemchun-Gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-0C-8D (hex) MATRIX VISION GmbH - 000C8D (base 16) MATRIX VISION GmbH - Talstrasse 16 - Oppenweiler Baden-Württemberg D-71570 - GERMANY - - 00-0C-8E (hex) Mentor Engineering Inc - 000C8E (base 16) Mentor Engineering Inc - 2891 Sunridge Way NE - Suite 230 - Calgary Alberta T1Y7K7 - CANADA - - 00-0C-8F (hex) Nergal s.r.l. - 000C8F (base 16) Nergal s.r.l. - Viale Bardanzellu,8 - Roma 00155 - ITALY - - 00-0C-90 (hex) Octasic Inc. - 000C90 (base 16) Octasic Inc. - 4101 Molson St. - Suite 300 - Montreal Quebec H1Y 3L1 - CANADA - - 00-0C-91 (hex) Riverhead Networks Inc. - 000C91 (base 16) Riverhead Networks Inc. - 20195 Stevens Creek Blvd. # 110 - Cupertino CA 95014 - UNITED STATES - - 00-0C-92 (hex) WolfVision Gmbh - 000C92 (base 16) WolfVision Gmbh - Oberes Ried 14 - 6833 Klaus - AUSTRIA - - 00-0C-93 (hex) Xeline Co., Ltd. - 000C93 (base 16) Xeline Co., Ltd. - 7F. Chungjin Bldg., 475-22 - Bangbae 2 dong, Seocho-gu - Seoul 137-819 - KOREA, REPUBLIC OF - - 00-0C-94 (hex) United Electronic Industries, Inc. (EUI) - 000C94 (base 16) United Electronic Industries, Inc. (EUI) - 27 Renmar Ave - Walpole MA 02081 - UNITED STATES - - 00-0C-95 (hex) PrimeNet - 000C95 (base 16) PrimeNet - Hongik University, 72-1, Sangsu-Dong, Ma - Seoul 121-791 - KOREA, REPUBLIC OF - - 00-0C-96 (hex) OQO, Inc. - 000C96 (base 16) OQO, Inc. - 1800 Illinois Street - San Francisco CA 94124 - UNITED STATES - - 00-0C-97 (hex) NV ADB TTV Technologies SA - 000C97 (base 16) NV ADB TTV Technologies SA - LEUVENSESTEENWEG,585 - ZAVENTEM Vlaamse brabant 1930 - BELGIUM - - 00-0C-98 (hex) LETEK Communications Inc. - 000C98 (base 16) LETEK Communications Inc. - Taeyang Bd. 2nd Floor, 2486 - SongNam-Dong, Jungwon-Ku - SongNam Kyunggi-do 462-824 - KOREA, REPUBLIC OF - - 00-0C-99 (hex) HITEL LINK Co.,Ltd - 000C99 (base 16) HITEL LINK Co.,Ltd - Samsung Omni Tower 4th Fl., 395-62 - Shindaebang-dong, Dongjac-ku, - Seoul 156-010 - KOREA, REPUBLIC OF - - 00-0C-9A (hex) Hitech Electronics Corp. - 000C9A (base 16) Hitech Electronics Corp. - 4f, No. 501-15 Chung-Cheng Rd. - Shin-tien Taipei Shien 231 - TAIWAN, PROVINCE OF CHINA - - 00-0C-9B (hex) EE Solutions, Inc - 000C9B (base 16) EE Solutions, Inc - 8F, No. 9, Park II Ave., Science-Based I - Hsin Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0C-9C (hex) Chongho information & communications - 000C9C (base 16) Chongho information & communications - Chongho Bldg, #7-61 Yangjae-dong, Seocho - Seoul 137-130 - KOREA, REPUBLIC OF - - 00-0C-9D (hex) UbeeAirWalk, Inc. - 000C9D (base 16) UbeeAirWalk, Inc. - 1850 N. GreenVille Ave., Suite 164 - Richardson TX 75081 - UNITED STATES - - 00-0C-9E (hex) MemoryLink Corp. - 000C9E (base 16) MemoryLink Corp. - 36 Jewelers Park Drive - Suite 200 - Neenah Wisconsin 54957 - UNITED STATES - - 00-0C-9F (hex) NKE Corporation - 000C9F (base 16) NKE Corporation - 366-1 Hishikawa-cho Hazukashi Fushimi-ku - Kyoto-shi Kyoto 612-8487 - JAPAN - - 00-0C-A0 (hex) StorCase Technology, Inc. - 000CA0 (base 16) StorCase Technology, Inc. - 17600 Newhope St. - Fountain Valley CA 92708 - UNITED STATES - - 00-0C-A1 (hex) SIGMACOM Co., LTD. - 000CA1 (base 16) SIGMACOM Co., LTD. - DacomBldg 7F 200-12 Anyang-dong - Manan-Ku, Anyang-city, KyungKi-Do, Korea - 430-817 - KOREA, REPUBLIC OF - - 00-0C-A2 (hex) Harmonic Video Network - 000CA2 (base 16) Harmonic Video Network - 10 Ha'amal st. Park Afek - Rosh Ha'ayin 48092 - ISRAEL - - 00-0C-A3 (hex) Rancho Technology, Inc. - 000CA3 (base 16) Rancho Technology, Inc. - 10783 Bell Court - Rancho Cucamonga CA 19730 - UNITED STATES - - 00-0C-A4 (hex) Prompttec Product Management GmbH - 000CA4 (base 16) Prompttec Product Management GmbH - Mariatrosterstr. 41 - Graz AUSTRIA A-8043 - AUSTRIA - - 00-0C-A5 (hex) Naman NZ LTd - 000CA5 (base 16) Naman NZ LTd - 13/17 Kawana St - Northcote - Auckland - NEW ZEALAND - - 00-0C-A6 (hex) Mintera Corporation - 000CA6 (base 16) Mintera Corporation - 847 Rogers Street - Lowell MA 01852 - UNITED STATES - - 00-0C-A7 (hex) Metro (Suzhou) Technologies Co., Ltd. - 000CA7 (base 16) Metro (Suzhou) Technologies Co., Ltd. - No.221 Xinghai Street, Suzhou Industrial Park - Suzhou Jiang Su Province 215021 - CHINA - - 00-0C-A8 (hex) Garuda Networks Corporation - 000CA8 (base 16) Garuda Networks Corporation - 48499 Milmont Drive - Fremont CA 94538 - UNITED STATES - - 00-0C-A9 (hex) Ebtron Inc. - 000CA9 (base 16) Ebtron Inc. - 1663 Hwy 701 South - Loris SC 29569 - UNITED STATES - - 00-0C-AA (hex) Cubic Transportation Systems Inc - 000CAA (base 16) Cubic Transportation Systems Inc - 1308 S. Washington Street - Tullahoma TN 37388 - UNITED STATES - - 00-0C-AB (hex) COMMEND International - 000CAB (base 16) COMMEND International - Hoelzlstrasse 561 - Wals Salzburg A-5071 - AUSTRIA - - 00-0C-AC (hex) Citizen Watch Co., Ltd. - 000CAC (base 16) Citizen Watch Co., Ltd. - 6-1-12, Tanashi-cho - Nishi-Tokyo-shi Tokyo 188-8511 - JAPAN - - 00-0C-AD (hex) BTU International - 000CAD (base 16) BTU International - 23 Esquire Rd - North Billerica MA 01862 - UNITED STATES - - 00-0C-AE (hex) Ailocom Oy - 000CAE (base 16) Ailocom Oy - Hatanpaan valtatie 24 - Dynamo Business Park - TAMPERE FIN 33950 - FINLAND - - 00-0C-AF (hex) TRI TERM CO.,LTD. - 000CAF (base 16) TRI TERM CO.,LTD. - 21-5 HIRAIDE KOUGIYO DANCHI - UTSUNOMIYA-SHI - TOCHIGI 321-0905 - JAPAN - - 00-0C-B0 (hex) Star Semiconductor Corporation - 000CB0 (base 16) Star Semiconductor Corporation - 6F, No.17, Li-Hsin Rd - Science-Based Industrial Park - Hsinchu City 300 - TAIWAN, PROVINCE OF CHINA - - 00-0C-B1 (hex) Salland Engineering (Europe) BV - 000CB1 (base 16) Salland Engineering (Europe) BV - Bedrijvenpark Berkum - Schrevenweg 12 - Zwolle OV 8024 HA - NETHERLANDS - - 00-0C-B2 (hex) UNION co., ltd. - 000CB2 (base 16) UNION co., ltd. - 14Beon-Gil 17, UiChang-Gu, - ChangWon-City - GyeongSnagNam-Do 641-846 - KOREA, REPUBLIC OF - - 00-0C-B3 (hex) ROUND Co.,Ltd. - 000CB3 (base 16) ROUND Co.,Ltd. - 3-9 Gokashou-Shibahigashi - Uji Kyoto 611-0011 - JAPAN - - 00-0C-B4 (hex) AutoCell Laboratories, Inc. - 000CB4 (base 16) AutoCell Laboratories, Inc. - 174 Concord Street - Suite 310 - Peterborough, New Hampshire 03458 - UNITED STATES - - 00-0C-B5 (hex) Premier Technolgies, Inc - 000CB5 (base 16) Premier Technolgies, Inc - PO Box 159 - One Premier Dr - Long Lake MN 55356 - UNITED STATES - - 00-0C-B6 (hex) NANJING SEU MOBILE & INTERNET TECHNOLOGY CO.,LTD - 000CB6 (base 16) NANJING SEU MOBILE & INTERNET TECHNOLOGY CO.,LTD - 5th floor,Building 5,ChangJiangHou Street No.6 - Nanjing Jiangsu 210018 - CHINA - - 00-0C-B7 (hex) Nanjing Huazhuo Electronics Co., Ltd. - 000CB7 (base 16) Nanjing Huazhuo Electronics Co., Ltd. - No.77 Gaohu Road - Jiangning Economic & Technology Developm - Nanjing Jiangsu 211100 - CHINA - - 00-0C-B8 (hex) MEDION AG - 000CB8 (base 16) MEDION AG - Am Zehnthof 77 - Essen NRW 45307 - GERMANY - - 00-0C-B9 (hex) LEA - 000CB9 (base 16) LEA - Bat LA FAYETTE - 2 place des Vosges - Paris RP 924051 - FRANCE - - 00-0C-BA (hex) Jamex, Inc. - 000CBA (base 16) Jamex, Inc. - 2415 N Triphammer Rd - Ithaca NY 14850 - UNITED STATES - - 00-0C-BB (hex) ISKRAEMECO - 000CBB (base 16) ISKRAEMECO - Savska loka 4 - Kranj Gorenjska 4000 - SLOVENIA - - 00-0C-BC (hex) Iscutum - 000CBC (base 16) Iscutum - #899-6 Ho-Gye Dong, Dong-An Gu - An-Yang City Kyong-Gi Do 431-080 - KOREA, REPUBLIC OF - - 00-0C-BD (hex) Interface Masters, Inc - 000CBD (base 16) Interface Masters, Inc - 2381 Zanker Rd., Suite 130 - San Jose California 95131 - UNITED STATES - - 00-0C-BE (hex) Innominate Security Technologies AG - 000CBE (base 16) Innominate Security Technologies AG - Rudower Chaussee 13 - 12489 Berlin - GERMANY - - 00-0C-BF (hex) Holy Stone Ent. Co., Ltd. - 000CBF (base 16) Holy Stone Ent. Co., Ltd. - 1F, No.62, Sec.2, Huang Shan Rd., - Nei Hu Dist., Taipei, Taiwan, R.O.C. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0C-C0 (hex) Genera Oy - 000CC0 (base 16) Genera Oy - Niittylanpolku 16 - Box 16 - Helsinki 00621 - FINLAND - - 00-0C-C1 (hex) Cooper Industries Inc. - 000CC1 (base 16) Cooper Industries Inc. - 600 Travis, Suite 5800 - Houston TX 77002 - UNITED STATES - - 00-0C-C2 (hex) ControlNet (India) Private Limited - 000CC2 (base 16) ControlNet (India) Private Limited - L-44, Unit - I - Verna Industrial Estate - Verna, Salcete Goa 403 722 - INDIA - - 00-0C-C3 (hex) BeWAN systems - 000CC3 (base 16) BeWAN systems - 16 rue du Moulin des Bruyères Courbevoie - Courbevoie Hauts de Seine 92400 - FRANCE - - 00-0C-C4 (hex) Tiptel AG - 000CC4 (base 16) Tiptel AG - Halskestrasse 1 - Ratingen NRW 40880 - GERMANY - - 00-0C-C5 (hex) Nextlink Co., Ltd. - 000CC5 (base 16) Nextlink Co., Ltd. - C 605, Technopark #145 Yatop-dong, - Seongnam-si Bundang-gu, Gyeonggi 463-760 - KOREA, REPUBLIC OF - - 00-0C-C6 (hex) Ka-Ro electronics GmbH - 000CC6 (base 16) Ka-Ro electronics GmbH - Pascalstraße 22 - Aachen NW 52076 - GERMANY - - 00-0C-C7 (hex) Intelligent Computer Solutions Inc. - 000CC7 (base 16) Intelligent Computer Solutions Inc. - 9350 Eton St. - Chatsworth CA 91301 - UNITED STATES - - 00-0C-C8 (hex) Xytronix Research & Design, Inc. - 000CC8 (base 16) Xytronix Research & Design, Inc. - 1488 East 2300 North - North Logan UT 84341-1627 - UNITED STATES - - 00-0C-C9 (hex) ILWOO DATA & TECHNOLOGY CO.,LTD - 000CC9 (base 16) ILWOO DATA & TECHNOLOGY CO.,LTD - 1475-10,HWA HYUN BLD. 2nd Floor, - SEOCHO-DONG,SEOCHO-GU, - SEOUL 137-071 - KOREA, REPUBLIC OF - - 00-0C-CA (hex) HGST a Western Digital Company - 000CCA (base 16) HGST a Western Digital Company - 3403 Yerba Buena Road - San Jose CA 95135 - UNITED STATES - - 00-0C-CB (hex) Design Combus Ltd - 000CCB (base 16) Design Combus Ltd - Hatanapaan valtatie 34A - Tampere FIN-33100 - FINLAND - - 00-0C-CC (hex) Aeroscout Ltd. - 000CCC (base 16) Aeroscout Ltd. - 3 Pekeris St. - Park Tamar - Rehovot 76701 - ISRAEL - - 00-0C-CD (hex) IEC - TC57 - 000CCD (base 16) IEC - TC57 - 3, rue de Varembé - P.O. Box 131 - Geneva GE 1211 - SWITZERLAND - - 00-0C-CE (hex) CISCO SYSTEMS, INC. - 000CCE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0C-CF (hex) CISCO SYSTEMS, INC. - 000CCF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0C-D0 (hex) Symetrix - 000CD0 (base 16) Symetrix - 6408 216th St SW - Mountlake Terrace WA 98043 - UNITED STATES - - 00-0C-D1 (hex) SFOM Technology Corp. - 000CD1 (base 16) SFOM Technology Corp. - No.18, Lane 32, Wufu 1st Rd., Luju shian - Luju Shiang Tauyuan County 338 - TAIWAN, PROVINCE OF CHINA - - 00-0C-D2 (hex) Schaffner EMV AG - 000CD2 (base 16) Schaffner EMV AG - Nordstrasse 1 - Luterbach CH-4542 - SWITZERLAND - - 00-0C-D3 (hex) Prettl Elektronik Radeberg GmbH - 000CD3 (base 16) Prettl Elektronik Radeberg GmbH - Robert-Bosch-Str. 10 - Radeberg Saxony D-01454 - GERMANY - - 00-0C-D4 (hex) Positron Public Safety Systems inc. - 000CD4 (base 16) Positron Public Safety Systems inc. - 5101 Buchan - Montreal Quebec H4P 2R9 - CANADA - - 00-0C-D5 (hex) Passave Inc. - 000CD5 (base 16) Passave Inc. - 1557 Jasper Dr. - Sunnyvale CA 94087 - UNITED STATES - - 00-0C-D6 (hex) PARTNER TECH - 000CD6 (base 16) PARTNER TECH - 10F, NO.233-2,PAO CHIAO ROAD, SHIN TIEN - TAIPEI 231 - TAIWAN, PROVINCE OF CHINA - - 00-0C-D7 (hex) Nallatech Ltd - 000CD7 (base 16) Nallatech Ltd - Boolean House - 1 Napier Park, Cumbernauld - Glasgow Scotland G68 0BH - UNITED KINGDOM - - 00-0C-D8 (hex) M. K. Juchheim GmbH & Co - 000CD8 (base 16) M. K. Juchheim GmbH & Co - Moltkestraße 13 - 31 - Fulda Hessen 36039 - GERMANY - - 00-0C-D9 (hex) Itcare Co., Ltd - 000CD9 (base 16) Itcare Co., Ltd - 408 KT Seocho, 1001-1 Bangbae-dong, - Seocho-ku - Seoul 137-850 - KOREA, REPUBLIC OF - - 00-0C-DA (hex) FreeHand Systems, Inc. - 000CDA (base 16) FreeHand Systems, Inc. - 95 First St. - Suite 200 - Los Altos CA 94022 - UNITED STATES - - 00-0C-DB (hex) Brocade Communications Systems, Inc - 000CDB (base 16) Brocade Communications Systems, Inc - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-0C-DC (hex) BECS Technology, Inc - 000CDC (base 16) BECS Technology, Inc - 9487 Dielman Rock Island Industrial Driv - St. Louis MO 63132 - UNITED STATES - - 00-0C-DD (hex) AOS Technologies AG - 000CDD (base 16) AOS Technologies AG - Taefernstrasse 20 - Baden - Daettwil AG CH-5405 - SWITZERLAND - - 00-0C-DE (hex) ABB STOTZ-KONTAKT GmbH - 000CDE (base 16) ABB STOTZ-KONTAKT GmbH - Eppelheimer Straße 82 - Heidelberg Baden-Württemberg 69123 - GERMANY - - 00-0C-DF (hex) PULNiX America, Inc - 000CDF (base 16) PULNiX America, Inc - 1330 Orleans Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-0C-E0 (hex) Trek Diagnostics Inc. - 000CE0 (base 16) Trek Diagnostics Inc. - 982 Keynote Circle - Suite 6 - Cleveland Ohio 44131 - UNITED STATES - - 00-0C-E1 (hex) The Open Group - 000CE1 (base 16) The Open Group - Apex Plaza - Forbury Road - Reading Berks RG1 1AX - UNITED KINGDOM - - 00-0C-E2 (hex) Rolls-Royce - 000CE2 (base 16) Rolls-Royce - 105 N. Sandusky St. - Mt. Vernon Ohio 43050 - UNITED STATES - - 00-0C-E3 (hex) Option International N.V. - 000CE3 (base 16) Option International N.V. - Kolonel Begaultlaan 45 - Leuven Brabant 3012 - BELGIUM - - 00-0C-E4 (hex) NeuroCom International, Inc. - 000CE4 (base 16) NeuroCom International, Inc. - 9570 SE Lawnfield Rd - Clackamas OR 97015 - UNITED STATES - - 00-0C-E5 (hex) ARRIS Group, Inc. - 000CE5 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-0C-E6 (hex) Meru Networks Inc - 000CE6 (base 16) Meru Networks Inc - 894 Ross Drive, - Sunnyvale CA 94089 - UNITED STATES - - 00-0C-E7 (hex) MediaTek Inc. - 000CE7 (base 16) MediaTek Inc. - 1F, No. 13, Innovation Road 1, - Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0C-E8 (hex) GuangZhou AnJuBao Co., Ltd - 000CE8 (base 16) GuangZhou AnJuBao Co., Ltd - HeiQiaoTang TangXia TianHe - GuangZhou GuangDong 510665 - CHINA - - 00-0C-E9 (hex) BLOOMBERG L.P. - 000CE9 (base 16) BLOOMBERG L.P. - 731 Lexington Ave - NEW YORK NEW YORK 10022 - UNITED STATES - - 00-0C-EA (hex) aphona Kommunikationssysteme - 000CEA (base 16) aphona Kommunikationssysteme - Entwicklungs- und VertriebsgmbH - Deutschstrasse 4 - Wien 1230 - AUSTRIA - - 00-0C-EB (hex) CNMP Networks, Inc. - 000CEB (base 16) CNMP Networks, Inc. - 1245 S. Winchester Blvd. - Suite 208 - San Jose CA 95128 - UNITED STATES - - 00-0C-EC (hex) Spectracom Corp. - 000CEC (base 16) Spectracom Corp. - 95 Methodist Hill Drive - Suite 500 - Rochester NY 14623 - UNITED STATES - - 00-0C-ED (hex) Real Digital Media - 000CED (base 16) Real Digital Media - 485 North Keller Road - Suite 140 - Maitland FL 32751 - UNITED STATES - - 00-0C-EE (hex) jp-embedded - 000CEE (base 16) jp-embedded - Buen 21, Nr. Dalby - Borup 4140 - DENMARK - - 00-0C-EF (hex) Open Networks Engineering Ltd - 000CEF (base 16) Open Networks Engineering Ltd - Classic House - Raynham Road - Bishop's Stortford Hertfordshire CM23 5PD - UNITED KINGDOM - - 00-0C-F0 (hex) M & N GmbH - 000CF0 (base 16) M & N GmbH - Dieselstr 18 - Rosbach v.d.H. Hessen 61191 - GERMANY - - 00-0C-F1 (hex) Intel Corporation - 000CF1 (base 16) Intel Corporation - MS: JF3-420 - 2111 NE 25th Avenue - Hillsboro OR 97124 - UNITED STATES - - 00-0C-F2 (hex) GAMESA Eólica - 000CF2 (base 16) GAMESA Eólica - Polígono Agustinos. C/ A s/n. - Pamplona NAVARRA 31013 - SPAIN - - 00-0C-F3 (hex) CALL IMAGE SA - 000CF3 (base 16) CALL IMAGE SA - 867 Route Imperiale - BAILLARGUES 34670 - FRANCE - - 00-0C-F4 (hex) AKATSUKI ELECTRIC MFG.CO.,LTD. - 000CF4 (base 16) AKATSUKI ELECTRIC MFG.CO.,LTD. - 593-1,aoji­ cho - kusatsu shi shiga 525-0041 - JAPAN - - 00-0C-F5 (hex) InfoExpress - 000CF5 (base 16) InfoExpress - 170 S. Whisman Road, Suite B - Mountain View CA 94041 - UNITED STATES - - 00-0C-F6 (hex) Sitecom Europe BV - 000CF6 (base 16) Sitecom Europe BV - Sevillaweg 122 - Rotterdam ZH 3047 AL - NETHERLANDS - - 00-0C-F7 (hex) Nortel Networks - 000CF7 (base 16) Nortel Networks - 8200 Dixie Rd. - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-0C-F8 (hex) Nortel Networks - 000CF8 (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - 036 CC 101 - Brampton Ontario L6T 5P6 - CANADA - - 00-0C-F9 (hex) Xylem Water Solutions - 000CF9 (base 16) Xylem Water Solutions - Gesallvagen - 174 87 Sundbyberg - SWEDEN - - 00-0C-FA (hex) Digital Systems Corp - 000CFA (base 16) Digital Systems Corp - 3 North Main Street - PO Box 158 - Walkersville Maryland 21793 - UNITED STATES - - 00-0C-FB (hex) Korea Network Systems - 000CFB (base 16) Korea Network Systems - 206 JangYoungSil Bldg, 1688-5 - Shinil-Dong, Taedeok-Gu - Taejeon 306-230 - KOREA, REPUBLIC OF - - 00-0C-FC (hex) S2io Technologies Corp - 000CFC (base 16) S2io Technologies Corp - 505 March Rd - Suite 120 - Ottawa Ontario K2K 2M5 - CANADA - - 00-0C-FD (hex) Hyundai ImageQuest Co.,Ltd. - 000CFD (base 16) Hyundai ImageQuest Co.,Ltd. - San 136-1, Ami-ri, Bubal-eub - Ichon-si Kyoung ki-do 467-701 - KOREA, REPUBLIC OF - - 00-0C-FE (hex) Grand Electronic Co., Ltd - 000CFE (base 16) Grand Electronic Co., Ltd - Room 1710, Block B Lucky tower, No.3 Don - Beijing 100027 - CHINA - - 00-0C-FF (hex) MRO-TEK LIMITED - 000CFF (base 16) MRO-TEK LIMITED - 14, 1ST D MAIN ROAD, - GANGA NAGAR - BANGALORE KARNATAKA 560032 - INDIA - - 00-0D-00 (hex) Seaway Networks Inc. - 000D00 (base 16) Seaway Networks Inc. - 1 Chrysalis Way - Ottawa Ontario K2G 6P9 - CANADA - - 00-0D-01 (hex) P&E Microcomputer Systems, Inc. - 000D01 (base 16) P&E Microcomputer Systems, Inc. - 710 Commonwealth Ave - Boston Ma 02215 - UNITED STATES - - 00-0D-02 (hex) NEC Platforms, Ltd. - 000D02 (base 16) NEC Platforms, Ltd. - 800 Shimomata - Kakegawa Shizuoka 436-8501 - JAPAN - - 00-0D-03 (hex) Matrics, Inc. - 000D03 (base 16) Matrics, Inc. - 8850 Stanford Blvd - Suite 3000 - Columbia MD 21045 - UNITED STATES - - 00-0D-04 (hex) Foxboro Eckardt Development GmbH - 000D04 (base 16) Foxboro Eckardt Development GmbH - Glockenstrasse 52 - Stuttgart Baden-Württemberg 70376 - GERMANY - - 00-0D-05 (hex) cybernet manufacturing inc. - 000D05 (base 16) cybernet manufacturing inc. - 5 holland - irvine ca 92618 - UNITED STATES - - 00-0D-06 (hex) Compulogic Limited - 000D06 (base 16) Compulogic Limited - Unit W3, MK TWO Business Centre - Barton Road - Water Eaton Milton Keynes MK2 3HU - UNITED KINGDOM - - 00-0D-07 (hex) Calrec Audio Ltd - 000D07 (base 16) Calrec Audio Ltd - Nutclough Mill - Hebden Bridge West Yorkshire HX7 8EZ - UNITED KINGDOM - - 00-0D-08 (hex) AboveCable, Inc. - 000D08 (base 16) AboveCable, Inc. - 8403 Colesville Road, #825 - Silver Spring MD 20910 - UNITED STATES - - 00-0D-09 (hex) Yuehua(Zhuhai) Electronic CO. LTD - 000D09 (base 16) Yuehua(Zhuhai) Electronic CO. LTD - 4Rd Pingdong,Nanping Science & Technolog - Zhuhai Guangdong 519070 - CHINA - - 00-0D-0A (hex) Projectiondesign as - 000D0A (base 16) Projectiondesign as - Habornveien 53 - Gamle Fredrikstad N-1630 - NORWAY - - 00-0D-0B (hex) Buffalo Inc. - 000D0B (base 16) Buffalo Inc. - MELCO HI-TECH CENTER, - SHIBATA HONDORI 4-15 MINAMI-KU, - NAGOYA 457-8520 - JAPAN - - 00-0D-0C (hex) MDI Security Systems - 000D0C (base 16) MDI Security Systems - 9518 Ninth Street - Rancho Cucamonga CA 91730 - UNITED STATES - - 00-0D-0D (hex) ITSupported, LLC - 000D0D (base 16) ITSupported, LLC - 4989 Peachtree Parkway - STE 200 - Norcross GA 30092 - UNITED STATES - - 00-0D-0E (hex) Inqnet Systems, Inc. - 000D0E (base 16) Inqnet Systems, Inc. - 321 NKIC Center - 48-84 Hongeun-dong, Seodaemun-ku - Seoul 120-100 - KOREA, REPUBLIC OF - - 00-0D-0F (hex) Finlux Ltd - 000D0F (base 16) Finlux Ltd - Radiomiehenkatu 3 - Turku FIN-20321 - FINLAND - - 00-0D-10 (hex) Embedtronics Oy - 000D10 (base 16) Embedtronics Oy - Leväsentie 23 - Kuopio 70780 - FINLAND - - 00-0D-11 (hex) DENTSPLY - Gendex - 000D11 (base 16) DENTSPLY - Gendex - 901 West Oakton Street - Des Plaines IL 60018-1884 - UNITED STATES - - 00-0D-12 (hex) AXELL Corporation - 000D12 (base 16) AXELL Corporation - Akihabara UDX South Wing 10F - 4-14-1 Sotokanda - Chiyoda-ku Tokyo 101-8973 - JAPAN - - 00-0D-13 (hex) Wilhelm Rutenbeck GmbH&Co.KG - 000D13 (base 16) Wilhelm Rutenbeck GmbH&Co.KG - Niederworth 1-10 - Schalksmühle NRW 58579 - GERMANY - - 00-0D-14 (hex) Vtech Innovation LP dba Advanced American Telephones - 000D14 (base 16) Vtech Innovation LP dba Advanced American Telephones - 203-600 Parsippany Rd - Parsippany NJ 07054 - UNITED STATES - - 00-0D-15 (hex) Voipac s.r.o. - 000D15 (base 16) Voipac s.r.o. - Ul. Janka Krala 3 - Trencin 911 01 - SLOVAKIA - - 00-0D-16 (hex) UHS Systems Pty Ltd - 000D16 (base 16) UHS Systems Pty Ltd - PO Box 6264 - South Sydney Business Hub - Alexandria NSW 2015 - AUSTRALIA - - 00-0D-17 (hex) Turbo Networks Co.Ltd - 000D17 (base 16) Turbo Networks Co.Ltd - 2F,No 1223, Chung Cheng Rd. - Tao Yuan 330 - TAIWAN, PROVINCE OF CHINA - - 00-0D-18 (hex) Mega-Trend Electronics CO., LTD. - 000D18 (base 16) Mega-Trend Electronics CO., LTD. - Tong Fu Yu Ind., Ku Keng Village, Guan Lan - Shengzhen Guang Dong 518110 - CHINA - - 00-0D-19 (hex) ROBE Show lighting - 000D19 (base 16) ROBE Show lighting - Hazovice 2090 - Roznov pod Radhostem 756 61 - CZECH REPUBLIC - - 00-0D-1A (hex) Mustek System Inc. - 000D1A (base 16) Mustek System Inc. - No. 25, R&D Road, Science-Based Industri - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0D-1B (hex) Kyoto Electronics Manufacturing Co., Ltd. - 000D1B (base 16) Kyoto Electronics Manufacturing Co., Ltd. - 56-2, Ninodan-cho, Shinden, - Kisshoin, Minami-ku, - Kyoto-City Kyoto Prefecture 601-8317 - JAPAN - - 00-0D-1C (hex) Amesys Defense - 000D1C (base 16) Amesys Defense - 1030 Av de la LAUZIERE - ZAC de Pichaury II Les Milles BP 20 140 - AIX en PROVENCE Cedex 03 13794 - FRANCE - - 00-0D-1D (hex) HIGH-TEK HARNESS ENT. CO., LTD. - 000D1D (base 16) HIGH-TEK HARNESS ENT. CO., LTD. - 4F-6, No18, Pu-Ting Rd. Hsinchu, Taiwan - 4F, No16, Lane50, Sec3, Nan-Kang Rd, Nan - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0D-1E (hex) Control Techniques - 000D1E (base 16) Control Techniques - The Gro - Pool Road - Newtown Powys SY16 3BE - UNITED KINGDOM - - 00-0D-1F (hex) AV Digital - 000D1F (base 16) AV Digital - Pottendorfer Strasse 25-27/4/1/1 - Wien 1120 - AUSTRIA - - 00-0D-20 (hex) ASAHIKASEI TECHNOSYSTEM CO.,LTD. - 000D20 (base 16) ASAHIKASEI TECHNOSYSTEM CO.,LTD. - Kanda Jinbocho 1-105 - Chiyoda-ku Tokyo 101-8101 - JAPAN - - 00-0D-21 (hex) WISCORE Inc. - 000D21 (base 16) WISCORE Inc. - 6F, No. 180, Sec. 2, Duenhua S. Rd, - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-0D-22 (hex) Unitronics LTD - 000D22 (base 16) Unitronics LTD - Unitronics Building - Airport City, P.O.B 300 - Ben Gurion Airport 70100 - ISRAEL - - 00-0D-23 (hex) Smart Solution, Inc - 000D23 (base 16) Smart Solution, Inc - 465 West Lawndale #B - Salt Lake City UT 84115 - UNITED STATES - - 00-0D-24 (hex) SENTEC E&E CO., LTD. - 000D24 (base 16) SENTEC E&E CO., LTD. - No. 32. Gong5 Rd. - Lungtan Taoyuan 325 - TAIWAN, PROVINCE OF CHINA - - 00-0D-25 (hex) SANDEN CORPORATION - 000D25 (base 16) SANDEN CORPORATION - 20 Kotobuki-cho - Isesaki-shi Gunma 372-8502 - JAPAN - - 00-0D-26 (hex) Primagraphics Limited - 000D26 (base 16) Primagraphics Limited - Cambridge House, No.2 Focus Four - Fourth Avenue - Letchworth Garden City Hertfordshire SG6 2TU - UNITED KINGDOM - - 00-0D-27 (hex) MICROPLEX Printware AG - 000D27 (base 16) MICROPLEX Printware AG - Panzerstraße 5 - Varel Niedersachsen 26316 - GERMANY - - 00-0D-28 (hex) CISCO SYSTEMS, INC. - 000D28 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-29 (hex) CISCO SYSTEMS, INC. - 000D29 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-2A (hex) Scanmatic AS - 000D2A (base 16) Scanmatic AS - Kilsund - Staubø 4920 - NORWAY - - 00-0D-2B (hex) Racal Instruments - 000D2B (base 16) Racal Instruments - 4 Goodyear Street - Irvine CA 92618 - UNITED STATES - - 00-0D-2C (hex) Patapsco Designs Ltd - 000D2C (base 16) Patapsco Designs Ltd - The Passfield Oak - Passfield - Nr Liphook Hampshire GU30 7RL - UNITED KINGDOM - - 00-0D-2D (hex) NCT Deutschland GmbH - 000D2D (base 16) NCT Deutschland GmbH - Wildenbruchstraße 15 - Jena Thüringen 07745 - GERMANY - - 00-0D-2E (hex) Matsushita Avionics Systems Corporation - 000D2E (base 16) Matsushita Avionics Systems Corporation - 26200 Enterprise Way - Lake Forest CA 92630 - UNITED STATES - - 00-0D-2F (hex) AIN Comm.Tech.Co., LTD - 000D2F (base 16) AIN Comm.Tech.Co., LTD - 4F, No.76, Sec2 Mintzu Rd - Jung-Li City 320 - TAIWAN, PROVINCE OF CHINA - - 00-0D-30 (hex) IceFyre Semiconductor - 000D30 (base 16) IceFyre Semiconductor - Suite 300 - 411 Leggett Drive - Kanata Ontario K2K 3C9 - CANADA - - 00-0D-31 (hex) Compellent Technologies, Inc. - 000D31 (base 16) Compellent Technologies, Inc. - 7625 Smetana Lane - Eden Prairie Minnesota 55344 - UNITED STATES - - 00-0D-32 (hex) DispenseSource, Inc. - 000D32 (base 16) DispenseSource, Inc. - 29801 Santa Margarita Parkway - Rancho Santa Margarita CA 92688 - UNITED STATES - - 00-0D-33 (hex) Prediwave Corp. - 000D33 (base 16) Prediwave Corp. - 48431 Milmont Drive - Fremont CA 94538 - UNITED STATES - - 00-0D-34 (hex) Shell International Exploration and Production, Inc. - 000D34 (base 16) Shell International Exploration and Production, Inc. - BTC-Gasmer - PO Box 481 - Houston TX 77001 - UNITED STATES - - 00-0D-35 (hex) PAC International Ltd - 000D35 (base 16) PAC International Ltd - 1 Park Gate Close - Bredbury - Stockport Cheshire SK6 2SZ - UNITED KINGDOM - - 00-0D-36 (hex) Wu Han Routon Electronic Co., Ltd - 000D36 (base 16) Wu Han Routon Electronic Co., Ltd - Miao Shan District, East Lake Hi-Tech - Development Park - Wuhan Hubei 430223 - CHINA - - 00-0D-37 (hex) WIPLUG - 000D37 (base 16) WIPLUG - RUA DR. AGOSTINHO GOULAO - BAIRRO: CORREAS - PETROPOLIS RIO JANEIRO 25730050 - BRAZIL - - 00-0D-38 (hex) NISSIN INC. - 000D38 (base 16) NISSIN INC. - 10-7 KAMEI-CHO - TAKARAZUKA HYOGO 665-0047 - JAPAN - - 00-0D-39 (hex) Network Electronics - 000D39 (base 16) Network Electronics - Box 1020 - Sandefjord Sandefjord N3204 - NORWAY - - 00-0D-3A (hex) Microsoft Corp. - 000D3A (base 16) Microsoft Corp. - One Microsoft Way - Redmond Wa. 98052 - UNITED STATES - - 00-0D-3B (hex) Microelectronics Technology Inc. - 000D3B (base 16) Microelectronics Technology Inc. - No1, Innovation Road II - Hsinchu Science-Based Industrial Park - 300 - TAIWAN, PROVINCE OF CHINA - - 00-0D-3C (hex) i.Tech Dynamic Ltd - 000D3C (base 16) i.Tech Dynamic Ltd - Room 1112, Metroplaza Tower 2, 223 Hing - 852 - HONG KONG - - 00-0D-3D (hex) Hammerhead Systems, Inc. - 000D3D (base 16) Hammerhead Systems, Inc. - 640 Clyde Court - Mountain View California 94043 - UNITED STATES - - 00-0D-3E (hex) APLUX Communications Ltd. - 000D3E (base 16) APLUX Communications Ltd. - 10F, No. 166, Dah-Yeh Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-0D-3F (hex) VTI Instruments Corporation - 000D3F (base 16) VTI Instruments Corporation - 5425 Warner Road, Suite 13 - Valley View OH 44125 - UNITED STATES - - 00-0D-40 (hex) Verint Loronix Video Solutions - 000D40 (base 16) Verint Loronix Video Solutions - 12526 High Bluff Dr. #170 - San DIego CA 92130 - UNITED STATES - - 00-0D-41 (hex) Siemens AG ICM MP UC RD IT KLF1 - 000D41 (base 16) Siemens AG ICM MP UC RD IT KLF1 - Suedstrasse 9 - Kamp-Lintfort NRW 47475 - GERMANY - - 00-0D-42 (hex) Newbest Development Limited - 000D42 (base 16) Newbest Development Limited - 3/F Unit 311-312 - No.1 Science Park East Avenue - Shatin NT - HONG KONG - - 00-0D-43 (hex) DRS Tactical Systems Inc. - 000D43 (base 16) DRS Tactical Systems Inc. - 3520 U.S. Highway 1 - Palm Bay FL 32905 - UNITED STATES - - 00-0D-44 (hex) Audio BU - Logitech - 000D44 (base 16) Audio BU - Logitech - 1499 SE Tech Center Place - Suite 350 - Vancouver WA 98683 - UNITED STATES - - 00-0D-45 (hex) Tottori SANYO Electric Co., Ltd. - 000D45 (base 16) Tottori SANYO Electric Co., Ltd. - 3-201, Minami Yoshikata - Tottori City Tottori 680-8634 - JAPAN - - 00-0D-46 (hex) Parker SSD Drives - 000D46 (base 16) Parker SSD Drives - 9225 Forsyth Park Drive - Charlotte NC 28273-3884 - UNITED STATES - - 00-0D-47 (hex) Collex - 000D47 (base 16) Collex - 13F-3,No.142,Sec.1,Huamei W,St.,Shi Chiu - Taichung 403 - TAIWAN, PROVINCE OF CHINA - - 00-0D-48 (hex) AEWIN Technologies Co., Ltd. - 000D48 (base 16) AEWIN Technologies Co., Ltd. - 7F, No. 2, Lane 47, Sec. 3, Nan-Gang Rd. - TAIPEI 115 - TAIWAN, PROVINCE OF CHINA - - 00-0D-49 (hex) Triton Systems of Delaware, Inc. - 000D49 (base 16) Triton Systems of Delaware, Inc. - 522 E. Railroad St. - Long Beach MS 39560 - UNITED STATES - - 00-0D-4A (hex) Steag ETA-Optik - 000D4A (base 16) Steag ETA-Optik - Borsigstrasse 78.-80 - Heinsberg 52525 - GERMANY - - 00-0D-4B (hex) Roku, LLC - 000D4B (base 16) Roku, LLC - 399 Sherman Ave. #12 - Palo Alto CA 94306 - UNITED STATES - - 00-0D-4C (hex) Outline Electronics Ltd. - 000D4C (base 16) Outline Electronics Ltd. - 7/F Benson Tower - 74 Hung To Road - Kwun Tong Kowloon - HONG KONG - - 00-0D-4D (hex) Ninelanes - 000D4D (base 16) Ninelanes - #405 4F Diplomatic Center - Seocho-gu, Seocho-dong - Seoul 1376-1 - KOREA, REPUBLIC OF - - 00-0D-4E (hex) NDR Co.,LTD. - 000D4E (base 16) NDR Co.,LTD. - Sumitomo seimei minatomachi MT BLDG - 1-18-2 Minamihorie Nishi-ku - Osak Kinki 550-0015 - JAPAN - - 00-0D-4F (hex) Kenwood Corporation - 000D4F (base 16) Kenwood Corporation - 2967-3, Ishikawa-machi - Hachioji-shi Tokyo 192-8525 - JAPAN - - 00-0D-50 (hex) Galazar Networks - 000D50 (base 16) Galazar Networks - 35 Fitzgerald Ave - Ottawa ON K2H 1E6 - CANADA - - 00-0D-51 (hex) DIVR Systems, Inc. - 000D51 (base 16) DIVR Systems, Inc. - 2161 Saturn Ct. - Bakersfield CA 93308 - UNITED STATES - - 00-0D-52 (hex) Comart system - 000D52 (base 16) Comart system - No. 211, Ace Techno Tower III, 197-48 - Gu-ro Dong, Gu-ro Gu, Seoul, Korea - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-0D-53 (hex) Beijing 5w Communication Corp. - 000D53 (base 16) Beijing 5w Communication Corp. - NO.4,Zhong-Guan-Cun South 4 street, - Beijing 100080 - CHINA - - 00-0D-54 (hex) 3Com Ltd - 000D54 (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-0D-55 (hex) SANYCOM Technology Co.,Ltd - 000D55 (base 16) SANYCOM Technology Co.,Ltd - 6F,Beijing Capital Times Square,88# Xich - Beijing 100031 - CHINA - - 00-0D-56 (hex) Dell Inc - 000D56 (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-0D-57 (hex) Fujitsu I-Network Systems Limited. - 000D57 (base 16) Fujitsu I-Network Systems Limited. - 1-403 kosugi-cho nakahara-ku - kawasaki kanagawa 211-0063 - JAPAN - - 00-0D-58 (hex) PRIVATE - 000D58 (base 16) - - 00-0D-59 (hex) Amity Systems, Inc. - 000D59 (base 16) Amity Systems, Inc. - 888 Tasman Drive - Milpitas CA 95035 - UNITED STATES - - 00-0D-5A (hex) Tiesse SpA - 000D5A (base 16) Tiesse SpA - Via Asti - Zona Industrial San Bernardo - Ivrea TO 10015 - ITALY - - 00-0D-5B (hex) Smart Empire Investments Limited - 000D5B (base 16) Smart Empire Investments Limited - Suite 2001-2006,Level 20 Landmark North - Xin Jie Hong Kong 00852 - CHINA - - 00-0D-5C (hex) Robert Bosch GmbH, VT-ATMO - 000D5C (base 16) Robert Bosch GmbH, VT-ATMO - Wernerstrasse 51 - Stuttgart BW 70469 - GERMANY - - 00-0D-5D (hex) Raritan Computer, Inc - 000D5D (base 16) Raritan Computer, Inc - 400 Cottontail Lane - Somerset NJ 08873 - UNITED STATES - - 00-0D-5E (hex) NEC Personal Products - 000D5E (base 16) NEC Personal Products - 6-80, Shimohanazawa 2-Chome - Yonezawa-shi Yamagata 992-8520 - JAPAN - - 00-0D-5F (hex) Minds Inc - 000D5F (base 16) Minds Inc - 1919 boul lionel bertrand - #202 - Boisbriand Quebec J7H 1N8 - CANADA - - 00-0D-60 (hex) IBM Corp - 000D60 (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-0D-61 (hex) Giga-Byte Technology Co., Ltd. - 000D61 (base 16) Giga-Byte Technology Co., Ltd. - No 6, Bau Chiang Road, Hsin-Tien - Taipei Hsien 9999 - TAIWAN, PROVINCE OF CHINA - - 00-0D-62 (hex) Funkwerk Dabendorf GmbH - 000D62 (base 16) Funkwerk Dabendorf GmbH - Maerkische Strasse - Dabendorf Brandenburg 15806 - GERMANY - - 00-0D-63 (hex) DENT Instruments, Inc. - 000D63 (base 16) DENT Instruments, Inc. - 64 NW Franklin Ave - Bend OR 97701 - UNITED STATES - - 00-0D-64 (hex) COMAG Handels AG - 000D64 (base 16) COMAG Handels AG - Zillenhardtstraße 41 - Goeppingen Baden-Württemberg 73037 - GERMANY - - 00-0D-65 (hex) CISCO SYSTEMS, INC. - 000D65 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-66 (hex) CISCO SYSTEMS, INC. - 000D66 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-67 (hex) Ericsson - 000D67 (base 16) Ericsson - 603 March Road - Kanata Ontario K2K 2M5 - CANADA - - 00-0D-68 (hex) Vinci Systems, Inc. - 000D68 (base 16) Vinci Systems, Inc. - 8330 Boone Boulevard - Suite 500 - Vienna VA 22182 - UNITED STATES - - 00-0D-69 (hex) TMT&D Corporation - 000D69 (base 16) TMT&D Corporation - 2-24-1 - Harumi-cho - Fuchu-si Tokyo 183-0057 - JAPAN - - 00-0D-6A (hex) Redwood Technologies LTD - 000D6A (base 16) Redwood Technologies LTD - Amber House - Market Street - Bracknell Berkshire RG12 1JB - UNITED KINGDOM - - 00-0D-6B (hex) Mita-Teknik A/S - 000D6B (base 16) Mita-Teknik A/S - Haandvaerkervej 1 - Roedkaersbro DK DK-8840 - DENMARK - - 00-0D-6C (hex) M-Audio - 000D6C (base 16) M-Audio - 45 E ST Joseph St. - Arcadia CA 91006 - UNITED STATES - - 00-0D-6D (hex) K-Tech Devices Corp. - 000D6D (base 16) K-Tech Devices Corp. - 14016-30 - nakaminowa minowamachi kamiina nagano 399-4601 - JAPAN - - 00-0D-6E (hex) K-Patents Oy - 000D6E (base 16) K-Patents Oy - P.O. Box 77 - Elannontie 5 - VANTAA FI 01511 - FINLAND - - 00-0D-6F (hex) Ember Corporation - 000D6F (base 16) Ember Corporation - 343 Congress St - 5th Floor - Boston Ma 02210 - UNITED STATES - - 00-0D-70 (hex) Datamax Corporation - 000D70 (base 16) Datamax Corporation - 4501 Parkway Commerce Blvd - Orlando FL 32808 - UNITED STATES - - 00-0D-71 (hex) boca systems - 000D71 (base 16) boca systems - 1065 s. rogers circle - boca raton fl 33487 - UNITED STATES - - 00-0D-72 (hex) 2Wire, Inc - 000D72 (base 16) 2Wire, Inc - 1704 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-0D-73 (hex) Technical Support, Inc. - 000D73 (base 16) Technical Support, Inc. - 11253 John Galt Blvd - Omaha Nebraska 68137 - UNITED STATES - - 00-0D-74 (hex) Sand Network Systems, Inc. - 000D74 (base 16) Sand Network Systems, Inc. - 434 Payran Street, Suite B - Petaluma CA 94952 - UNITED STATES - - 00-0D-75 (hex) Kobian Pte Ltd - Taiwan Branch - 000D75 (base 16) Kobian Pte Ltd - Taiwan Branch - 2F, No.580, Rueikuang Rd.,Nei Hu,Taipei, - Taipei Nei Hu 114 - TAIWAN, PROVINCE OF CHINA - - 00-0D-76 (hex) Hokuto Denshi Co,. Ltd. - 000D76 (base 16) Hokuto Denshi Co,. Ltd. - 3-7 Odori Nishi 16-Chome Chuoku - Sapporo Hokkaido 060-0042 - JAPAN - - 00-0D-77 (hex) FalconStor Software - 000D77 (base 16) FalconStor Software - 125 Baylis Rd - Melville NY 11747 - UNITED STATES - - 00-0D-78 (hex) Engineering & Security - 000D78 (base 16) Engineering & Security - Martiri della Libertà   32/4 - Genova 16155 - ITALY - - 00-0D-79 (hex) Dynamic Solutions Co,.Ltd. - 000D79 (base 16) Dynamic Solutions Co,.Ltd. - 17-8 Nihonbashi Hakozaki-cho - Chuo-ku Tokyo 103-0015 - JAPAN - - 00-0D-7A (hex) DiGATTO Asia Pacific Pte Ltd - 000D7A (base 16) DiGATTO Asia Pacific Pte Ltd - 190 Mddle Road, #19-05 Fortune Center - 188979 - SINGAPORE - - 00-0D-7B (hex) Consensys Computers Inc. - 000D7B (base 16) Consensys Computers Inc. - 215 Shields Ct. - Markham ON L3R 8V2 - CANADA - - 00-0D-7C (hex) Codian Ltd - 000D7C (base 16) Codian Ltd - 14 Waterside Drive - Langley Slough SL3 6EZ - UNITED KINGDOM - - 00-0D-7D (hex) Afco Systems - 000D7D (base 16) Afco Systems - 200 Finn Court - Farmingdale NY 11735 - UNITED STATES - - 00-0D-7E (hex) Axiowave Networks, Inc. - 000D7E (base 16) Axiowave Networks, Inc. - 200 Nickerson Road - Marlborough MA 01752 - UNITED STATES - - 00-0D-7F (hex) MIDAS COMMUNICATION TECHNOLOGIES PTE LTD ( Foreign Branch) - 000D7F (base 16) MIDAS COMMUNICATION TECHNOLOGIES PTE LTD ( Foreign Branch) - 04-12, Phase Z.Ro Technoprenuer Park - #151, North Buona Vista Road - Singapore 139 347 - SINGAPORE - - 00-0D-80 (hex) Online Development Inc - 000D80 (base 16) Online Development Inc - 7209 Chapman Hwy - Knoxville Tn 37920 - UNITED STATES - - 00-0D-81 (hex) Pepperl+Fuchs GmbH - 000D81 (base 16) Pepperl+Fuchs GmbH - Lilienthalstraße 200 - Mannheim 68307 - GERMANY - - 00-0D-82 (hex) PHS srl - 000D82 (base 16) PHS srl - Via Palù, 17 - Arcugnano Vicenza 36057 - ITALY - - 00-0D-83 (hex) Sanmina-SCI Hungary Ltd. - 000D83 (base 16) Sanmina-SCI Hungary Ltd. - Kota Jozsef u. 2. - Tatabanya Komarom-Esztergom 2800 - HUNGARY - - 00-0D-84 (hex) Makus Inc. - 000D84 (base 16) Makus Inc. - 4F Daedo Bldg., 748-14 Yeoksam-dong - Kangnam-gu Seoul 135-080 - KOREA, REPUBLIC OF - - 00-0D-85 (hex) Tapwave, Inc. - 000D85 (base 16) Tapwave, Inc. - 1901 Landings Drive - Building G - Mountain View CA 94043 - UNITED STATES - - 00-0D-86 (hex) Huber + Suhner AG - 000D86 (base 16) Huber + Suhner AG - Degersheimerstrasse 14 - 9100 Herisau - SWITZERLAND - - 00-0D-87 (hex) Elitegroup Computer System Co. (ECS) - 000D87 (base 16) Elitegroup Computer System Co. (ECS) - No.22, Alley 38, Lane 91, Sec. 1, Nei Hu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0D-88 (hex) D-Link Corporation - 000D88 (base 16) D-Link Corporation - No.8, Li-Hsing 7 Road, Science-Based Ind - Hsinchu 30077 - TAIWAN, PROVINCE OF CHINA - - 00-0D-89 (hex) Bils Technology Inc - 000D89 (base 16) Bils Technology Inc - 508 S River Oaks Drive - Indialantic FL 32903 - UNITED STATES - - 00-0D-8A (hex) Winners Electronics Co., Ltd. - 000D8A (base 16) Winners Electronics Co., Ltd. - #340-5,Wonchun-Dong,Paldal-Gu - Suwon-City Kyungki-Do 442-823 - KOREA, REPUBLIC OF - - 00-0D-8B (hex) T&D Corporation - 000D8B (base 16) T&D Corporation - 5652-169 Sasaga - Matsumoto Nagano 399-0033 - JAPAN - - 00-0D-8C (hex) Shanghai Wedone Digital Ltd. CO. - 000D8C (base 16) Shanghai Wedone Digital Ltd. CO. - 893-899 Huashan Road, - Shanghai 200031 - CHINA - - 00-0D-8D (hex) Prosoft Technology, Inc - 000D8D (base 16) Prosoft Technology, Inc - 5201 Truxtun Ave - Third Floor - Bakersfield CA 93300 - UNITED STATES - - 00-0D-8E (hex) Koden Electronics Co., Ltd. - 000D8E (base 16) Koden Electronics Co., Ltd. - 5278 Uenohara - Uenohara-Shi - Yamanashi-Ken 409-0112 - JAPAN - - 00-0D-8F (hex) King Tsushin Kogyo Co., LTD. - 000D8F (base 16) King Tsushin Kogyo Co., LTD. - 1-10-1 Edanishi Aobaku - Yokohama 225-0014 - JAPAN - - 00-0D-90 (hex) Factum Electronics AB - 000D90 (base 16) Factum Electronics AB - Teknikringen 1H - Linköping Östergötland 583 30 - SWEDEN - - 00-0D-91 (hex) Eclipse (HQ Espana) S.L. - 000D91 (base 16) Eclipse (HQ Espana) S.L. - CC de Negocios - Officina No. 46. C.N. 340, Km 175 - Puerto de Banus Marbella 29660 - SPAIN - - 00-0D-92 (hex) Arima Communication Corporation - 000D92 (base 16) Arima Communication Corporation - 16, lane 658, Ying-Tao Road - Yingko Taipei County 23943 - TAIWAN, PROVINCE OF CHINA - - 00-0D-93 (hex) Apple - 000D93 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-0D-94 (hex) AFAR Communications,Inc - 000D94 (base 16) AFAR Communications,Inc - 81 David Love Place - Suite A - Santa Barbara CA 93117 - UNITED STATES - - 00-0D-95 (hex) Opti-cell, Inc. - 000D95 (base 16) Opti-cell, Inc. - 100 High Tower Blvd., Suite 301 - Pittsburgh PA 15205 - UNITED STATES - - 00-0D-96 (hex) Vtera Technology Inc. - 000D96 (base 16) Vtera Technology Inc. - No 34, Industrial East. 4th Rd. - HsinChu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0D-97 (hex) Tropos Networks, Inc. - 000D97 (base 16) Tropos Networks, Inc. - 1710 S. Amphlett Blvd, Suite 304 - San Mateo CA 94402 - UNITED STATES - - 00-0D-98 (hex) S.W.A.C. Schmitt-Walter Automation Consult GmbH - 000D98 (base 16) S.W.A.C. Schmitt-Walter Automation Consult GmbH - Oedenpullach 1 - Oberhaching Bavaria 82041 - GERMANY - - 00-0D-99 (hex) Orbital Sciences Corp.; Launch Systems Group - 000D99 (base 16) Orbital Sciences Corp.; Launch Systems Group - 3380 S. Price Rd. - Chandler, AZ 85248 - UNITED STATES - - 00-0D-9A (hex) INFOTEC LTD - 000D9A (base 16) INFOTEC LTD - The Maltings - Tamworth Road - Ashby-de-la-Zouch Leicestershire LE65 2PS - UNITED KINGDOM - - 00-0D-9B (hex) Heraeus Electro-Nite International N.V. - 000D9B (base 16) Heraeus Electro-Nite International N.V. - Centrum Zuid 1105 - Houthalen 3530 - BELGIUM - - 00-0D-9C (hex) Elan GmbH & Co KG - 000D9C (base 16) Elan GmbH & Co KG - Im Ostpark 2 - Wettenberg Hessen 35435 - GERMANY - - 00-0D-9D (hex) Hewlett-Packard Company - 000D9D (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - mx070405 - Houston TX 77070 - UNITED STATES - - 00-0D-9E (hex) TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd. - 000D9E (base 16) TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd. - Yoshida 1221 - Ouragun Ohizumi Gunma 370-0523 - JAPAN - - 00-0D-9F (hex) RF Micro Devices - 000D9F (base 16) RF Micro Devices - 2191 Zanker Road - San Jose CA 95131 - UNITED STATES - - 00-0D-A0 (hex) NEDAP N.V. - 000DA0 (base 16) NEDAP N.V. - P.O.Box 103 - P.O.Box 6 - GROENLO GLD 7141 AC - NETHERLANDS - - 00-0D-A1 (hex) MIRAE ITS Co.,LTD. - 000DA1 (base 16) MIRAE ITS Co.,LTD. - 7F, ChangHyun B/D,960-1,HoGye1Dong - AnYang KyongiGiDo 431-840 - KOREA, REPUBLIC OF - - 00-0D-A2 (hex) Infrant Technologies, Inc. - 000DA2 (base 16) Infrant Technologies, Inc. - 48820 Kato Road - Ste 110B - Fremont CA 94538 - UNITED STATES - - 00-0D-A3 (hex) Emerging Technologies Limited - 000DA3 (base 16) Emerging Technologies Limited - Wong's Industrial Centre, 180 Wai Yip St - Kwun Tong, Kowloon - Nil - HONG KONG - - 00-0D-A4 (hex) DOSCH & AMAND SYSTEMS AG - 000DA4 (base 16) DOSCH & AMAND SYSTEMS AG - Scheinerstrasse 9 - Munich Bavaria 81679 - GERMANY - - 00-0D-A5 (hex) Fabric7 Systems, Inc - 000DA5 (base 16) Fabric7 Systems, Inc - 1300 Crittenden Lane - Suite 302 - Mountain View CA 94043 - UNITED STATES - - 00-0D-A6 (hex) Universal Switching Corporation - 000DA6 (base 16) Universal Switching Corporation - 7671 San Fernando Rd - Burbank CA 91505-1073 - UNITED STATES - - 00-0D-A7 (hex) PRIVATE - 000DA7 (base 16) - - 00-0D-A8 (hex) Teletronics Technology Corporation - 000DA8 (base 16) Teletronics Technology Corporation - 2525 Pearl Buck Road - Bristol Pennsylvania 19007 - UNITED STATES - - 00-0D-A9 (hex) T.E.A.M. S.L. - 000DA9 (base 16) T.E.A.M. S.L. - Parque Tecnologico Edificio 108 - ZAMUDIO Bizkaia 48170 - SPAIN - - 00-0D-AA (hex) S.A.Tehnology co.,Ltd. - 000DAA (base 16) S.A.Tehnology co.,Ltd. - 80-12 Yangjae 1 Dong - Seocho Gu - Seoul South Korea 137-890 - KOREA, REPUBLIC OF - - 00-0D-AB (hex) Parker Hannifin GmbH Electromechanical Division Europe - 000DAB (base 16) Parker Hannifin GmbH Electromechanical Division Europe - Robert-Bosch-Straße 22 - Offenburg Baden-Württemberg 77656 - GERMANY - - 00-0D-AC (hex) Japan CBM Corporation - 000DAC (base 16) Japan CBM Corporation - 5-68-10 Nakano, - Nakano-Ku Tokyo 164-0001 - JAPAN - - 00-0D-AD (hex) Dataprobe, Inc. - 000DAD (base 16) Dataprobe, Inc. - 1B Pearl Court - Allendale NJ 07401 - UNITED STATES - - 00-0D-AE (hex) SAMSUNG HEAVY INDUSTRIES CO., LTD. - 000DAE (base 16) SAMSUNG HEAVY INDUSTRIES CO., LTD. - 493, Banweol-Ri, Taean-Eup - Hwaseong-City Kyeonggi-Do 445-973 - KOREA, REPUBLIC OF - - 00-0D-AF (hex) Plexus Corp (UK) Ltd - 000DAF (base 16) Plexus Corp (UK) Ltd - Pinnacle Hill - Kelso Roxburghshire TD5 8XX - UNITED KINGDOM - - 00-0D-B0 (hex) Olym-tech Co.,Ltd. - 000DB0 (base 16) Olym-tech Co.,Ltd. - Room 401/402,No.1,Songling Road,Hi-tech - Shenzhen Guangdong 518031 - CHINA - - 00-0D-B1 (hex) Japan Network Service Co., Ltd. - 000DB1 (base 16) Japan Network Service Co., Ltd. - Matoba Bldg. 6F, - 3-7-7 Irifune - Chuo-ku Tokyo 104-0042 - JAPAN - - 00-0D-B2 (hex) Ammasso, Inc. - 000DB2 (base 16) Ammasso, Inc. - 345 Summer Street - Boston MA 02210 - UNITED STATES - - 00-0D-B3 (hex) SDO Communication Corperation - 000DB3 (base 16) SDO Communication Corperation - 6F, No.112, Shin Min Street - Chung Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-0D-B4 (hex) NETASQ - 000DB4 (base 16) NETASQ - 3 rue Archimede - Villeneuve d'Ascq nord 59650 - FRANCE - - 00-0D-B5 (hex) GLOBALSAT TECHNOLOGY CORPORATION - 000DB5 (base 16) GLOBALSAT TECHNOLOGY CORPORATION - Far East Century Park - Chung Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-0D-B6 (hex) Broadcom Corporation - 000DB6 (base 16) Broadcom Corporation - 1363 Redwood Way - Petaluma CA 94954 - UNITED STATES - - 00-0D-B7 (hex) SANKO ELECTRIC CO,.LTD - 000DB7 (base 16) SANKO ELECTRIC CO,.LTD - 7-23 Tamanoi-cho Atsuta-ku - Nagoya-shi Aichi 456-0025 - JAPAN - - 00-0D-B8 (hex) SCHILLER AG - 000DB8 (base 16) SCHILLER AG - Altgasse 68 - Baar Zug 6300 - SWITZERLAND - - 00-0D-B9 (hex) PC Engines GmbH - 000DB9 (base 16) PC Engines GmbH - Flughofstrasse 58 - 8152 Glattbrugg - SWITZERLAND - - 00-0D-BA (hex) Océ Document Technologies GmbH - 000DBA (base 16) Océ Document Technologies GmbH - Max-Stromeyer-Straße 116 - Konstanz 78467 - GERMANY - - 00-0D-BB (hex) Nippon Dentsu Co.,Ltd. - 000DBB (base 16) Nippon Dentsu Co.,Ltd. - 2-21-1,Isoji - Minato-Ku - Osaka 552-0003 - JAPAN - - 00-0D-BC (hex) CISCO SYSTEMS, INC. - 000DBC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-BD (hex) CISCO SYSTEMS, INC. - 000DBD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-BE (hex) Bel Fuse Europe Ltd.,UK - 000DBE (base 16) Bel Fuse Europe Ltd.,UK - 45/46 Riverside 2 - Medway City Estate - Rochester Kent ME2 4DP - UNITED KINGDOM - - 00-0D-BF (hex) TekTone Sound & Signal Mfg., Inc. - 000DBF (base 16) TekTone Sound & Signal Mfg., Inc. - 277 Industrial Park Rd. - Franklin NC 28734 - UNITED STATES - - 00-0D-C0 (hex) Spagat AS - 000DC0 (base 16) Spagat AS - Tonne Hutifeldtpl. 2 - Halden Ostfold 1767 - NORWAY - - 00-0D-C1 (hex) SafeWeb Inc - 000DC1 (base 16) SafeWeb Inc - 2200 Powell St. Ste 590 - Emeryville CA 94608 - UNITED STATES - - 00-0D-C2 (hex) PRIVATE - 000DC2 (base 16) - - 00-0D-C3 (hex) First Communication, Inc. - 000DC3 (base 16) First Communication, Inc. - 1F, No.36, Industry E. Rd. IV., - Science-based Industrial Park - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-0D-C4 (hex) Emcore Corporation - 000DC4 (base 16) Emcore Corporation - 1600 Eubank Blvd, SE - Albuquerque New Mexico 87123 - UNITED STATES - - 00-0D-C5 (hex) EchoStar Global B.V. - 000DC5 (base 16) EchoStar Global B.V. - Schuilenburglaan 5a - Almelo Overijssel 7604BJ - NETHERLANDS - - 00-0D-C6 (hex) DigiRose Technology Co., Ltd. - 000DC6 (base 16) DigiRose Technology Co., Ltd. - No. 1, Alley 20, Lane 26 Rueiguang Road, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0D-C7 (hex) COSMIC ENGINEERING INC. - 000DC7 (base 16) COSMIC ENGINEERING INC. - 1-3-5, Nishihirayama - Hino-shi TOKYO 191-0055 - JAPAN - - 00-0D-C8 (hex) AirMagnet, Inc - 000DC8 (base 16) AirMagnet, Inc - 830 E. Arques Avenue - Sunnyvale CA 94085 - UNITED STATES - - 00-0D-C9 (hex) THALES Elektronik Systeme GmbH - 000DC9 (base 16) THALES Elektronik Systeme GmbH - Fritz-Ludwig-Str. 1 - Koblenz 56070 - GERMANY - - 00-0D-CA (hex) Tait Electronics - 000DCA (base 16) Tait Electronics - 535 Wairakei Rd - PO Box 1645 - Christchurch Canterbury 8005 - NEW ZEALAND - - 00-0D-CB (hex) Petcomkorea Co., Ltd. - 000DCB (base 16) Petcomkorea Co., Ltd. - 5F,689-47,Geumjeong-dong,Gunpo-si,Kyungg - Kyunggi-do gunpo-si 435-050 - KOREA, REPUBLIC OF - - 00-0D-CC (hex) NEOSMART Corp. - 000DCC (base 16) NEOSMART Corp. - Yoon-B/D 4F, 475-31, Bangbae 2-dong - Seoul Seocho-gu 147-819 - KOREA, REPUBLIC OF - - 00-0D-CD (hex) GROUPE TXCOM - 000DCD (base 16) GROUPE TXCOM - ZI DU PETIT CLAMART - 10 AVENUE DESCARTES - LE PLESSIS ROBINSON HAUTS-DE-SEINE 92350 - FRANCE - - 00-0D-CE (hex) Dynavac Technology Pte Ltd - 000DCE (base 16) Dynavac Technology Pte Ltd - 30 Tuas Avenue 9 - 639183 - SINGAPORE - - 00-0D-CF (hex) Cidra Corp. - 000DCF (base 16) Cidra Corp. - 50 Barns Park North - Wallingford CT 06492 - UNITED STATES - - 00-0D-D0 (hex) TetraTec Instruments GmbH - 000DD0 (base 16) TetraTec Instruments GmbH - Gewerbestrasse 8 - Steinenbronn BW 71144 - GERMANY - - 00-0D-D1 (hex) Stryker Corporation - 000DD1 (base 16) Stryker Corporation - 4100 E Milham - Kalamazoo MI 49001 - UNITED STATES - - 00-0D-D2 (hex) Simrad Optronics ASA - 000DD2 (base 16) Simrad Optronics ASA - Ensjøveienn 23B - PO Box 6114 Etterstad NO-0602 Oslo - NORWAY - - 00-0D-D3 (hex) SAMWOO Telecommunication Co.,Ltd. - 000DD3 (base 16) SAMWOO Telecommunication Co.,Ltd. - - 171, Dangjung-Dong, - Gunpo Kyoung-Gi 435-831 - KOREA, REPUBLIC OF - - 00-0D-D4 (hex) Symantec Corporation - 000DD4 (base 16) Symantec Corporation - 275 2nd Ave - Waltham MA 02541 - UNITED STATES - - 00-0D-D5 (hex) O'RITE TECHNOLOGY CO.,LTD - 000DD5 (base 16) O'RITE TECHNOLOGY CO.,LTD - 4f-8,NO 80,GUANGFU RD.SEC 2,SANCHUNG - TAIPEI COUNTY 241 - TAIWAN, PROVINCE OF CHINA - - 00-0D-D6 (hex) ITI LTD - 000DD6 (base 16) ITI LTD - R&D,ITI Bangalore Complex - F-86 Bldg. - Dooravani Nagar, Bangalore Karnataka State 560016 - INDIA - - 00-0D-D7 (hex) Bright - 000DD7 (base 16) Bright - 1-12-44 Aobadai - Kashiwa-shi Chiba-ken 277-0055 - JAPAN - - 00-0D-D8 (hex) BBN - 000DD8 (base 16) BBN - 7F-3,NO.186, Jian Yi Rd ., Chung Ho City - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-0D-D9 (hex) Anton Paar GmbH - 000DD9 (base 16) Anton Paar GmbH - Anton-Paar-Strasse 20 - Graz 8054 - AUSTRIA - - 00-0D-DA (hex) ALLIED TELESIS K.K. - 000DDA (base 16) ALLIED TELESIS K.K. - PIAZZA TIRANA N. 24/4 B - MILANO 20147 - ITALY - - 00-0D-DB (hex) AIRWAVE TECHNOLOGIES INC. - 000DDB (base 16) AIRWAVE TECHNOLOGIES INC. - 3F,No.9,Industry E. 9th Road - Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0D-DC (hex) VAC - 000DDC (base 16) VAC - 20F, N0. 456, Sec. 4, Hsin Yi Rd., - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-0D-DD (hex) Profilo Telra Elektronik Sanayi ve Ticaret. A.Åž - 000DDD (base 16) Profilo Telra Elektronik Sanayi ve Ticaret. A.Åž - Cemal Sahir Sokak NO:26-28 - Mecidiyeköy - İstanbul TURKEY 34255 - TURKEY - - 00-0D-DE (hex) Joyteck Co., Ltd. - 000DDE (base 16) Joyteck Co., Ltd. - 19F, No.4, Sec. 3, Min Chuan East Rd. - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-0D-DF (hex) Japan Image & Network Inc. - 000DDF (base 16) Japan Image & Network Inc. - 5-29-12 Shiba - Minato-ku Tokyo 108-0014 - JAPAN - - 00-0D-E0 (hex) ICPDAS Co.,LTD - 000DE0 (base 16) ICPDAS Co.,LTD - No. 111, Kuang-Fu N. Rd., Hsin-Chu Indu - HSINCHU 303 - TAIWAN, PROVINCE OF CHINA - - 00-0D-E1 (hex) Control Products, Inc. - 000DE1 (base 16) Control Products, Inc. - 1724 Lake Drive West - Chanhassen MN 55317 - UNITED STATES - - 00-0D-E2 (hex) CMZ Sistemi Elettronici - 000DE2 (base 16) CMZ Sistemi Elettronici - Via dell'Artiginato, 21 - Vascon di Carbonera Treviso 31050 - ITALY - - 00-0D-E3 (hex) AT Sweden AB - 000DE3 (base 16) AT Sweden AB - P.O. Box 1166 - Isafjordsgatan 30B - Kista Stockholm SE-164 26 - SWEDEN - - 00-0D-E4 (hex) DIGINICS, Inc. - 000DE4 (base 16) DIGINICS, Inc. - 178-7 - Poi-dong - Kangnam-gu Seoul 135-961 - KOREA, REPUBLIC OF - - 00-0D-E5 (hex) Samsung Thales - 000DE5 (base 16) Samsung Thales - 259 Gongdan-Dong - Gumi-City Gyeongsangbuk-do 730-904 - KOREA, REPUBLIC OF - - 00-0D-E6 (hex) YOUNGBO ENGINEERING CO.,LTD - 000DE6 (base 16) YOUNGBO ENGINEERING CO.,LTD - Mt.22, Jaeunga-ri, Jigsan-Eup, - Cheonan-shi Chungcheongnam-do #330-810 - KOREA, REPUBLIC OF - - 00-0D-E7 (hex) Snap-on OEM Group - 000DE7 (base 16) Snap-on OEM Group - 2333 East Walton Blvd. - Auburn Hills MI 48326 - UNITED STATES - - 00-0D-E8 (hex) Nasaco Electronics Pte. Ltd - 000DE8 (base 16) Nasaco Electronics Pte. Ltd - Level 4, Nasaco Tech Centre - 49, Changi South Avenue 2 - 486056 - SINGAPORE - - 00-0D-E9 (hex) Napatech Aps - 000DE9 (base 16) Napatech Aps - Rundofrbivej 271, 1 - Naerum 2850 - DENMARK - - 00-0D-EA (hex) Kingtel Telecommunication Corp. - 000DEA (base 16) Kingtel Telecommunication Corp. - 147 Kang Ning St. - Hsi Chih City Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-0D-EB (hex) CompXs Limited - 000DEB (base 16) CompXs Limited - Robert Denholm House - Nutfield - Redhill Surrey RH1 4HW - UNITED KINGDOM - - 00-0D-EC (hex) CISCO SYSTEMS, INC. - 000DEC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-ED (hex) CISCO SYSTEMS, INC. - 000DED (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0D-EE (hex) Andrew RF Power Amplifier Group - 000DEE (base 16) Andrew RF Power Amplifier Group - 40 Technology Drive - Warren NJ 07059 - UNITED STATES - - 00-0D-EF (hex) Soc. Coop. Bilanciai - 000DEF (base 16) Soc. Coop. Bilanciai - via S.Ferrari 16 - Campogalliano Modena 41011 - ITALY - - 00-0D-F0 (hex) QCOM TECHNOLOGY INC. - 000DF0 (base 16) QCOM TECHNOLOGY INC. - 7F., NO 178, MING CHUAN E. RD., SEC. 3, - TAIPEI 105 - TAIWAN, PROVINCE OF CHINA - - 00-0D-F1 (hex) IONIX INC. - 000DF1 (base 16) IONIX INC. - Ssangyong IT Twin Tower 604, 442-17, Sangdaewon-dong, Jungwon-gu, - Seongnam-si Gyeonggi-do 462-120 - KOREA, REPUBLIC OF - - 00-0D-F2 (hex) PRIVATE - 000DF2 (base 16) - - 00-0D-F3 (hex) Asmax Solutions - 000DF3 (base 16) Asmax Solutions - Tatarska 5 - Cracow 30-103 - POLAND - - 00-0D-F4 (hex) Watertek Co. - 000DF4 (base 16) Watertek Co. - Room 1006,Haitai building,north si Huan - Zhong Road,Haidian District - Beijing 100083 - CHINA - - 00-0D-F5 (hex) Teletronics International Inc. - 000DF5 (base 16) Teletronics International Inc. - 2 Choke Cherry Road - Suite #101 - Rockville MD 20850 - UNITED STATES - - 00-0D-F6 (hex) Technology Thesaurus Corp. - 000DF6 (base 16) Technology Thesaurus Corp. - NO. 6, East 4th St. KEPZ - KAOHSIUNG 806 - TAIWAN, PROVINCE OF CHINA - - 00-0D-F7 (hex) Space Dynamics Lab - 000DF7 (base 16) Space Dynamics Lab - 1695 N. Research Park Way - North Logan UT 84341 - UNITED STATES - - 00-0D-F8 (hex) ORGA Kartensysteme GmbH - 000DF8 (base 16) ORGA Kartensysteme GmbH - Konrad-Zuse-Ring 1 - Flintbek Schleswig-Holstein 24220 - GERMANY - - 00-0D-F9 (hex) NDS Limited - 000DF9 (base 16) NDS Limited - One Heathrow Boulevard - 286 Bath Road - West Drayton Middlesex UB7 0DQ - UNITED KINGDOM - - 00-0D-FA (hex) Micro Control Systems Ltd. - 000DFA (base 16) Micro Control Systems Ltd. - 8-7 Sakurai - Saku-shi Nagano 385-0056 - JAPAN - - 00-0D-FB (hex) Komax AG - 000DFB (base 16) Komax AG - Industriestrasse 6 - Dierikon LU 6036 - SWITZERLAND - - 00-0D-FC (hex) ITFOR Inc. - 000DFC (base 16) ITFOR Inc. - Ichibancho Tokyu Bidg., - 21 Ichibanncyo,Chiyoda-ku - Tokyo 102-0082 - JAPAN - - 00-0D-FD (hex) Huges Hi-Tech Inc., - 000DFD (base 16) Huges Hi-Tech Inc., - 7F, 188, Sec.2, Chung Hsing Road. - Hsin Tien Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-0D-FE (hex) Hauppauge Computer Works, Inc. - 000DFE (base 16) Hauppauge Computer Works, Inc. - 91 Cabot Court - Hauppauge New York 11788 - UNITED STATES - - 00-0D-FF (hex) CHENMING MOLD INDUSTRY CORP. - 000DFF (base 16) CHENMING MOLD INDUSTRY CORP. - 2F No. 26, Lane 513, Rei Kuang Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0E-00 (hex) Atrie - 000E00 (base 16) Atrie - 10th Floor, 14, Lane 609, Sec. 5, Chung Hsin Rd., San Chung City, - Taipei Hsien San Chung 241 - TAIWAN, PROVINCE OF CHINA - - 00-0E-01 (hex) ASIP Technologies Inc. - 000E01 (base 16) ASIP Technologies Inc. - 10F-2, NO.322, Sec.1, Guangfu Rd., - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0E-02 (hex) Advantech AMT Inc. - 000E02 (base 16) Advantech AMT Inc. - 657 Orly Ave. - Dorval Quebec H9P 1G1 - CANADA - - 00-0E-03 (hex) Emulex Corporation - 000E03 (base 16) Emulex Corporation - 3333 Susan Street - Costa Mesa CA 92626 - UNITED STATES - - 00-0E-04 (hex) CMA/Microdialysis AB - 000E04 (base 16) CMA/Microdialysis AB - Dalvägen 10 / Box 2 - Solna 171 18 - SWEDEN - - 00-0E-05 (hex) WIRELESS MATRIX CORP. - 000E05 (base 16) WIRELESS MATRIX CORP. - UNIT 1A-3751 NORTH FRASER WAY - BURNABY BC V5J 5G4 - CANADA - - 00-0E-06 (hex) Team Simoco Ltd - 000E06 (base 16) Team Simoco Ltd - Field House - Uttoxeter Old Road - Derby Derbyshire DE1 1NH - UNITED KINGDOM - - 00-0E-07 (hex) Sony Ericsson Mobile Communications AB - 000E07 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 Lund - SWEDEN - - 00-0E-08 (hex) Cisco Linksys LLC - 000E08 (base 16) Cisco Linksys LLC - 170 West Tasman Dr. - San Jose CA 95134 - UNITED STATES - - 00-0E-09 (hex) Shenzhen Coship Software Co.,LTD. - 000E09 (base 16) Shenzhen Coship Software Co.,LTD. - 7/F,Block A,W2 Bldg,Hi-Tech Industrial Park,Shenzhen,China - Shenzhen Guangdong 518057 - CHINA - - 00-0E-0A (hex) SAKUMA DESIGN OFFICE - 000E0A (base 16) SAKUMA DESIGN OFFICE - 674-11 - KUKI-SHI SAITAMA 346-0029 - JAPAN - - 00-0E-0B (hex) Netac Technology Co., Ltd. - 000E0B (base 16) Netac Technology Co., Ltd. - 6F, Incubator Building, China Academy of Science &Tech Development, - No.1 High-tech South Street - ShenZhen GuangDong 518057 - CHINA - - 00-0E-0C (hex) Intel Corporation - 000E0C (base 16) Intel Corporation - 2111 NE 25th Avenue - MS: JF3-420 - Hillsboro OR 97124 - UNITED STATES - - 00-0E-0D (hex) Hesch Schröder GmbH - 000E0D (base 16) Hesch Schröder GmbH - Boschstraße 8 - Neustadt Niedersachsen 31535 - GERMANY - - 00-0E-0E (hex) ESA elettronica S.P.A. - 000E0E (base 16) ESA elettronica S.P.A. - Via P. Masciadri 4/A - Mariano Comense CO 22066 - ITALY - - 00-0E-0F (hex) ERMME - 000E0F (base 16) ERMME - 9 rue Lavoisier - Vert-Le-Petit 91710 - FRANCE - - 00-0E-10 (hex) C-guys, Inc. - 000E10 (base 16) C-guys, Inc. - Izumi Garden Wing 1F, 1-6-3 - Roppongi, Minato-ku - Tokyo 106-0032 - JAPAN - - 00-0E-11 (hex) BDT Büro und Datentechnik GmbH & Co.KG - 000E11 (base 16) BDT Büro und Datentechnik GmbH & Co.KG - Saline 29 - Rottweil Baden-Württemberg D-78628 - GERMANY - - 00-0E-12 (hex) Adaptive Micro Systems Inc. - 000E12 (base 16) Adaptive Micro Systems Inc. - 7840 North 86th St. - Milwaukee WI 53224 - UNITED STATES - - 00-0E-13 (hex) Accu-Sort Systems inc. - 000E13 (base 16) Accu-Sort Systems inc. - 511 School House Road - Telford PA 18969 - UNITED STATES - - 00-0E-14 (hex) Visionary Solutions, Inc. - 000E14 (base 16) Visionary Solutions, Inc. - 4193 Carpinteria Ave - Suite 11 - Carpinteria CA 93013 - UNITED STATES - - 00-0E-15 (hex) Tadlys LTD - 000E15 (base 16) Tadlys LTD - ISRAELI SHIMON 3 - RISHON lEZYYON ISRAEL 75654 - ISRAEL - - 00-0E-16 (hex) SouthWing S.L. - 000E16 (base 16) SouthWing S.L. - C/Avila, 48-50 - 3rd floor - Barcelona 08005 - SPAIN - - 00-0E-17 (hex) PRIVATE - 000E17 (base 16) - - 00-0E-18 (hex) MyA Technology - 000E18 (base 16) MyA Technology - 2100 Muirwood Way - San Jose CA 95132 - UNITED STATES - - 00-0E-19 (hex) LogicaCMG Pty Ltd - 000E19 (base 16) LogicaCMG Pty Ltd - 17-19 Orion Road - Lane Cove NSW 2066 - AUSTRALIA - - 00-0E-1A (hex) JPS Communications - 000E1A (base 16) JPS Communications - 5800 Departure Drive - Raleigh NC 27616 - UNITED STATES - - 00-0E-1B (hex) IAV GmbH - 000E1B (base 16) IAV GmbH - Carnotstraße 1 - Berlin 10587 - GERMANY - - 00-0E-1C (hex) Hach Company - 000E1C (base 16) Hach Company - 5600 Lindbergh Drive - Loveland CO 80538 - UNITED STATES - - 00-0E-1D (hex) ARION Technology Inc. - 000E1D (base 16) ARION Technology Inc. - 3F, Pica Bldg, 894-2, Hogye 2 Dong - Dongan-Gu - An-Yang City Gyeonggi-Do - KOREA, REPUBLIC OF - - 00-0E-1E (hex) QLogic Corporation - 000E1E (base 16) QLogic Corporation - 26650 Aliso Viejo Parkway - Aliso Viejo CA 92656 - UNITED STATES - - 00-0E-1F (hex) TCL Networks Equipment Co., Ltd. - 000E1F (base 16) TCL Networks Equipment Co., Ltd. - No.5 Industrial Road,Shekou - ShenZhen GuangDong 518067 - CHINA - - 00-0E-20 (hex) ACCESS Systems Americas, Inc. - 000E20 (base 16) ACCESS Systems Americas, Inc. - 1188 East Arques Avenue - Sunnyvale CA 94085 - UNITED STATES - - 00-0E-21 (hex) MTU Friedrichshafen GmbH - 000E21 (base 16) MTU Friedrichshafen GmbH - Maybachplatz 1 - Friedrichshafen Baden Wuertemberg 88040 - GERMANY - - 00-0E-22 (hex) PRIVATE - 000E22 (base 16) - - 00-0E-23 (hex) Incipient, Inc. - 000E23 (base 16) Incipient, Inc. - 230 Third Ave. - 4th Floor - Waltham MA 02451 - UNITED STATES - - 00-0E-24 (hex) Huwell Technology Inc. - 000E24 (base 16) Huwell Technology Inc. - 1F 82-21, Majin Building - Nonhyun-dong, Gangnam-gu - Seoul 135-010 - KOREA, REPUBLIC OF - - 00-0E-25 (hex) Hannae Technology Co., Ltd - 000E25 (base 16) Hannae Technology Co., Ltd - 4F, Hyunjin Bldg., #798-30, Yeoksam-Dong - Kangnam-Ku - SEOUL 135-080 - KOREA, REPUBLIC OF - - 00-0E-26 (hex) Gincom Technology Corp. - 000E26 (base 16) Gincom Technology Corp. - 15F., No. 284, Sec.3, Sanmin Rd., Taoyuan City, - Taoyuan, 330 - TAIWAN, PROVINCE OF CHINA - - 00-0E-27 (hex) Crere Networks, Inc. - 000E27 (base 16) Crere Networks, Inc. - Room 110 ETRI TBI, 52 Eoeun-dong - Yuseong-gu - Daejeon 305-333 - KOREA, REPUBLIC OF - - 00-0E-28 (hex) Dynamic Ratings P/L - 000E28 (base 16) Dynamic Ratings P/L - C/O Wilson Transformer Co. - Wilson Rd. (PO Box 5) - Glen Waverley Victoria 3150 - AUSTRALIA - - 00-0E-29 (hex) Shester Communications Inc - 000E29 (base 16) Shester Communications Inc - 159 S. Lincoln - Suite 221 - Spokane WA 99201 - UNITED STATES - - 00-0E-2A (hex) PRIVATE - 000E2A (base 16) - - 00-0E-2B (hex) Safari Technologies - 000E2B (base 16) Safari Technologies - 63855 M40 Hwy - Lawton MI 49065 - UNITED STATES - - 00-0E-2C (hex) Netcodec co. - 000E2C (base 16) Netcodec co. - 401 Daeion S/W Center, 48 Jangdong - Yusonggu - Daejon 305-715 - KOREA, REPUBLIC OF - - 00-0E-2D (hex) Hyundai Digital Technology Co.,Ltd. - 000E2D (base 16) Hyundai Digital Technology Co.,Ltd. - 223-22, Sangdaewon-1dong, Jungwon-gu - Seongnam-si Kyoungki-do 462-807 - KOREA, REPUBLIC OF - - 00-0E-2E (hex) Edimax Technology Co., Ltd. - 000E2E (base 16) Edimax Technology Co., Ltd. - 3, Wu-Chuan 3rd Road, - Wu-Ku Industrial Park, - Taipei Hsien, 248 - TAIWAN, PROVINCE OF CHINA - - 00-0E-2F (hex) Roche Diagnostics GmbH - 000E2F (base 16) Roche Diagnostics GmbH - Roche Diabetes Care Insulin Delivery Systems - Sandhofer Strasse 116 - D-68305 Mannheim - GERMANY - - 00-0E-30 (hex) AERAS Networks, Inc. - 000E30 (base 16) AERAS Networks, Inc. - P.O. Box 7330 - Laguna Niguel CA 92607-7330 - UNITED STATES - - 00-0E-31 (hex) Olympus Soft Imaging Solutions GmbH - 000E31 (base 16) Olympus Soft Imaging Solutions GmbH - Johann-Krane-Weg 39 - Münster 48149 - GERMANY - - 00-0E-32 (hex) Kontron Medical - 000E32 (base 16) Kontron Medical - Reinacherstrasse 131 - Basel 4002 - SWITZERLAND - - 00-0E-33 (hex) Shuko Electronics Co.,Ltd - 000E33 (base 16) Shuko Electronics Co.,Ltd - TOHSHIN HIGASHI-IKEBUKURO Building 3F - 5-44-15,HIGASHI-IKEBUKURO,TOSHIMA-KU - TOKYO KANTOH 170-0063 - JAPAN - - 00-0E-34 (hex) NexGen City, LP - 000E34 (base 16) NexGen City, LP - 1680 Glenville - Suite 100 - Richardson Texas 75081 - UNITED STATES - - 00-0E-35 (hex) Intel Corp - 000E35 (base 16) Intel Corp - 2111 NE 25th Ave - JF3-420 - Hillsboro OR 97123 - UNITED STATES - - 00-0E-36 (hex) HEINESYS, Inc. - 000E36 (base 16) HEINESYS, Inc. - 3F, Sungkwang Bldg. 456-13, Sungnae-dong - Kangdong-gu - Seoul 134-848 - KOREA, REPUBLIC OF - - 00-0E-37 (hex) Harms & Wende GmbH & Co.KG - 000E37 (base 16) Harms & Wende GmbH & Co.KG - Grossmoorkehre 9 - Hamburg D-21079 - GERMANY - - 00-0E-38 (hex) CISCO SYSTEMS, INC. - 000E38 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0E-39 (hex) CISCO SYSTEMS, INC. - 000E39 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0E-3A (hex) Cirrus Logic - 000E3A (base 16) Cirrus Logic - 2901 Via Fortuna - Austin TX 78746 - UNITED STATES - - 00-0E-3B (hex) Hawking Technologies, Inc. - 000E3B (base 16) Hawking Technologies, Inc. - 15281A Barranca Parkway - Irvine CA 92618 - UNITED STATES - - 00-0E-3C (hex) Transact Technologies Inc - 000E3C (base 16) Transact Technologies Inc - 20 Bomax Drive - Ithaca New York 14850 - UNITED STATES - - 00-0E-3D (hex) Televic N.V. - 000E3D (base 16) Televic N.V. - Leo Bekaertlaan 1 - Izegem 8870 - BELGIUM - - 00-0E-3E (hex) Sun Optronics Inc - 000E3E (base 16) Sun Optronics Inc - 4-38-4 Fuchinobe-honchou - Sagamihara Kanagawa 229-0002 - JAPAN - - 00-0E-3F (hex) Soronti, Inc. - 000E3F (base 16) Soronti, Inc. - 12159 Business Park Dr, Suite 140 - Draper Utah 84020 - UNITED STATES - - 00-0E-40 (hex) Nortel Networks - 000E40 (base 16) Nortel Networks - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-0E-41 (hex) NIHON MECHATRONICS CO.,LTD. - 000E41 (base 16) NIHON MECHATRONICS CO.,LTD. - 9-6 SHIOMIDAI, MIYAMAE-KU - KAWASAKI-SHI KANAGAWA-KEN 216-0013 - JAPAN - - 00-0E-42 (hex) Motic Incoporation Ltd. - 000E42 (base 16) Motic Incoporation Ltd. - Room 2907-8, Windsor House - 311 Gloucester Road, Causeway Bay - Hong Kong - CHINA - - 00-0E-43 (hex) G-Tek Electronics Sdn. Bhd. - 000E43 (base 16) G-Tek Electronics Sdn. Bhd. - 2493 Mukim 1, Lorong Perusahaan Lapan - Kawasan Perindustrian Perai - Perai Penang 13600 - MALAYSIA - - 00-0E-44 (hex) Digital 5, Inc. - 000E44 (base 16) Digital 5, Inc. - 101 Grovers Mill Rd. - Suite 200 - Lawrenceville NJ 08648 - UNITED STATES - - 00-0E-45 (hex) Beijing Newtry Electronic Technology Ltd - 000E45 (base 16) Beijing Newtry Electronic Technology Ltd - PO Box 95, No. 1 Bei Sha Tan, - Chao Yang Qu - Beijing 10083 - CHINA - - 00-0E-46 (hex) Niigata Seimitsu Co.,Ltd. - 000E46 (base 16) Niigata Seimitsu Co.,Ltd. - 3335-2, Shimonaka, Sanwa-mura - Nakakubiki-gun Niigata 943-0222 - JAPAN - - 00-0E-47 (hex) NCI System Co.,Ltd. - 000E47 (base 16) NCI System Co.,Ltd. - #206, Kayang Techno-Town, 1487, Kayang 3 dong, Kangseo-Ku, Seoul, Korea - Seoul 157-810 - KOREA, REPUBLIC OF - - 00-0E-48 (hex) Lipman TransAction Solutions - 000E48 (base 16) Lipman TransAction Solutions - 11 Haamal St. - Rosh-Haayin 48092 - ISRAEL - - 00-0E-49 (hex) Forsway Scandinavia AB - 000E49 (base 16) Forsway Scandinavia AB - Kanikegränd 3B - 541 34 Skövde - SWEDEN - - 00-0E-4A (hex) Changchun Huayu WEBPAD Co.,LTD - 000E4A (base 16) Changchun Huayu WEBPAD Co.,LTD - 4370 Gaoxin Road, High-Tech - Development Area - Changchun Jilin 130012 - CHINA - - 00-0E-4B (hex) atrium c and i - 000E4B (base 16) atrium c and i - 124-4, Ojeon-dong, - Uiwang-city Kyunggi-Do 437-819 - KOREA, REPUBLIC OF - - 00-0E-4C (hex) Bermai Inc. - 000E4C (base 16) Bermai Inc. - 410 Cambridge Ave - 2nd Floor - Palo Alto CA 94306 - UNITED STATES - - 00-0E-4D (hex) Numesa Inc. - 000E4D (base 16) Numesa Inc. - 4444 Westgrove Suite 300 - Addison TX 75001 - UNITED STATES - - 00-0E-4E (hex) Waveplus Technology Co., Ltd. - 000E4E (base 16) Waveplus Technology Co., Ltd. - 347 HsinHu 2nd Rd., NeiHu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0E-4F (hex) Trajet GmbH - 000E4F (base 16) Trajet GmbH - Rebenring 33 - Braunschweig Nds. 38106 - GERMANY - - 00-0E-50 (hex) Thomson Telecom Belgium - 000E50 (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - Edegem Antwerp B-2650 - BELGIUM - - 00-0E-51 (hex) tecna elettronica srl - 000E51 (base 16) tecna elettronica srl - via miglioli 30 - castel san pietro terme bologna 40024 - ITALY - - 00-0E-52 (hex) Optium Corporation - 000E52 (base 16) Optium Corporation - 500 Horizon Dr - Suite 505 - Chalfont PA 18914 - UNITED STATES - - 00-0E-53 (hex) AV TECH CORPORATION - 000E53 (base 16) AV TECH CORPORATION - 10F,E Building,No.19-11 San Chung Rd.,NanKang - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-0E-54 (hex) AlphaCell Wireless Ltd. - 000E54 (base 16) AlphaCell Wireless Ltd. - 22 Zarhin street - Raanana 43662 - ISRAEL - - 00-0E-55 (hex) AUVITRAN - 000E55 (base 16) AUVITRAN - 7c chemin des Prés - MEYLAN 38410 - FRANCE - - 00-0E-56 (hex) 4G Systems GmbH & Co. KG - 000E56 (base 16) 4G Systems GmbH & Co. KG - Jarrestrasse 2-6 - 22303 Hamburg - GERMANY - - 00-0E-57 (hex) Iworld Networking, Inc. - 000E57 (base 16) Iworld Networking, Inc. - 125 Hanju Bldg, Nonhyun-Dong - Kang-Nam Gu - Seoul 135010 - KOREA, REPUBLIC OF - - 00-0E-58 (hex) Sonos, Inc. - 000E58 (base 16) Sonos, Inc. - 223 E. De La Guerra St. - Santa Barbara CA 93101 - UNITED STATES - - 00-0E-59 (hex) SAGEM SA - 000E59 (base 16) SAGEM SA - 2, rue du petit Albi - CERGY SAINT CHRISTOPHE val d'Oise 95800 - FRANCE - - 00-0E-5A (hex) TELEFIELD inc. - 000E5A (base 16) TELEFIELD inc. - 3F, Kumbo Bldg, 2-9, Seokchon-Dong - Songpa-Gu - Seoul 138-190 - KOREA, REPUBLIC OF - - 00-0E-5B (hex) ParkerVision - Direct2Data - 000E5B (base 16) ParkerVision - Direct2Data - 9432 Baymeadows Way - Suite 150 - Jacksonville FL 32246 - UNITED STATES - - 00-0E-5C (hex) ARRIS Group, Inc. - 000E5C (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-0E-5D (hex) Triple Play Technologies A/S - 000E5D (base 16) Triple Play Technologies A/S - Herstedvang 8 - Albertslund DK-2620 - DENMARK - - 00-0E-5E (hex) Raisecom Technology - 000E5E (base 16) Raisecom Technology - 2 Floor, South Building of Rainbow Plaza - No. 11 Shangdi Information Road - Haidian District Beijing 100085 - CHINA - - 00-0E-5F (hex) activ-net GmbH & Co. KG - 000E5F (base 16) activ-net GmbH & Co. KG - Konrad-Zuse-Str. 4 - Bochum 44801 - GERMANY - - 00-0E-60 (hex) 360SUN Digital Broadband Corporation - 000E60 (base 16) 360SUN Digital Broadband Corporation - 2F-2, No.2, Jianba Rd., - Chung Ho Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-0E-61 (hex) MICROTROL LIMITED - 000E61 (base 16) MICROTROL LIMITED - 16 ELGAR BUSINESS CENTRE - MOSELEY ROAD - HALLOW WORCESTER WR2 6NJ - UNITED KINGDOM - - 00-0E-62 (hex) Nortel Networks - 000E62 (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-0E-63 (hex) Lemke Diagnostics GmbH - 000E63 (base 16) Lemke Diagnostics GmbH - Radeburger Str. 47 - Volkersdorf Saxony 01468 - GERMANY - - 00-0E-64 (hex) Elphel, Inc - 000E64 (base 16) Elphel, Inc - 3200 S. Elpmer St. - Magna UT 84044 - UNITED STATES - - 00-0E-65 (hex) TransCore - 000E65 (base 16) TransCore - 8600 Jefferson St NE - Albuquerque NM 87113 - UNITED STATES - - 00-0E-66 (hex) Hitachi Industry & Control Solutions, Ltd. - 000E66 (base 16) Hitachi Industry & Control Solutions, Ltd. - 5-1-26, Omika-cho, Hitachi-shi, Ibaraki - 319-1221 - JAPAN - - 00-0E-67 (hex) Eltis Microelectronics Ltd. - 000E67 (base 16) Eltis Microelectronics Ltd. - Unit 902B, 9/F., Sunbeam Centre - 27, Shing Yip Street - Kwun Tong Kowloon - HONG KONG - - 00-0E-68 (hex) E-TOP Network Technology Inc. - 000E68 (base 16) E-TOP Network Technology Inc. - No. 7, Shin Shin Rd., - Tainan 702 - TAIWAN, PROVINCE OF CHINA - - 00-0E-69 (hex) China Electric Power Research Institute - 000E69 (base 16) China Electric Power Research Institute - No.15 Xiaoying East Road,Qinghe,Beijing,China - Beijing 100085 - CHINA - - 00-0E-6A (hex) 3Com Ltd - 000E6A (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-0E-6B (hex) Janitza electronics GmbH - 000E6B (base 16) Janitza electronics GmbH - Vor dem Polstück 1 - Lahnau Hessen 35633 - GERMANY - - 00-0E-6C (hex) Device Drivers Limited - 000E6C (base 16) Device Drivers Limited - 1-5-1-103 - Wakamatsu-cho - Fuchu-shi Tokyo 1830005 - JAPAN - - 00-0E-6D (hex) Murata Manufacturing Co., Ltd. - 000E6D (base 16) Murata Manufacturing Co., Ltd. - 2288, Oaza-Ohshinohara, Yasu-cho, - Yasu-gun Shiga 520-2393 - JAPAN - - 00-0E-6E (hex) MAT S.A. (Mircrelec Advanced Technology) - 000E6E (base 16) MAT S.A. (Mircrelec Advanced Technology) - Mousounitsis 15 - Peristeri Athens - GREECE - - 00-0E-6F (hex) IRIS Corporation Berhad - 000E6F (base 16) IRIS Corporation Berhad - IRIS Smart Technology Complex - Technology Park Malaysia, Bukit Jalil - Kuala Lumpur WP 57000 - MALAYSIA - - 00-0E-70 (hex) in2 Networks - 000E70 (base 16) in2 Networks - 320 W 200 S - Suite #380 - SLC UT 84101 - UNITED STATES - - 00-0E-71 (hex) Gemstar Technology Development Ltd. - 000E71 (base 16) Gemstar Technology Development Ltd. - Unit 201, Stulex house, 698 prince edward road east, san po kong, Kolwoon - Hong Kong 852 - HONG KONG - - 00-0E-72 (hex) CTS electronics - 000E72 (base 16) CTS electronics - Corso Vercelli 332 - Ivrea Torino 10015 - ITALY - - 00-0E-73 (hex) Tpack A/S - 000E73 (base 16) Tpack A/S - Lautrupbjerg 7 - 11 - DK 2750 Ballerup DK 2750 - DENMARK - - 00-0E-74 (hex) Solar Telecom. Tech - 000E74 (base 16) Solar Telecom. Tech - B B/D, 4F, Samho Venture Tower - #275-6, Yangjae-Dong, Secho-Gu - Seoul 137-941 - KOREA, REPUBLIC OF - - 00-0E-75 (hex) New York Air Brake Corp. - 000E75 (base 16) New York Air Brake Corp. - 748 Starbuck Ave. - Watertown NY 13601 - UNITED STATES - - 00-0E-76 (hex) GEMSOC INNOVISION INC. - 000E76 (base 16) GEMSOC INNOVISION INC. - 9F,No.516,Sec,1Neihu Rd., - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0E-77 (hex) Decru, Inc. - 000E77 (base 16) Decru, Inc. - 275 Shoreline Dr - Suite 450 - Redwood City CA 94065 - UNITED STATES - - 00-0E-78 (hex) Amtelco - 000E78 (base 16) Amtelco - 4800 Curtin Drive - McFarland WI 53558 - UNITED STATES - - 00-0E-79 (hex) Ample Communications Inc. - 000E79 (base 16) Ample Communications Inc. - 4034 Clipper Ct. - Fremont CA 94538 - UNITED STATES - - 00-0E-7A (hex) GemWon Communications Co., Ltd. - 000E7A (base 16) GemWon Communications Co., Ltd. - 3FL.,NO.32,Lane 135,Shianjeng 9th Rd.,Jubei City - Hsinchu 302 - TAIWAN, PROVINCE OF CHINA - - 00-0E-7B (hex) Toshiba - 000E7B (base 16) Toshiba - 2-9, Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - 00-0E-7C (hex) Televes S.A. - 000E7C (base 16) Televes S.A. - Rua Benefica Conxo 17 - Santiago de Compostela Coruña 15706 - SPAIN - - 00-0E-7D (hex) Electronics Line 3000 Ltd. - 000E7D (base 16) Electronics Line 3000 Ltd. - 2 Granit St. - Petah Tikva Kiryar Arie 449130 - ISRAEL - - 00-0E-7E (hex) ionSign Oy - 000E7E (base 16) ionSign Oy - P.O.BOX 246 - FI-26101 - Rauma - FINLAND - - 00-0E-7F (hex) Hewlett-Packard Company - 000E7F (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS070405 - Houston TX 77070 - UNITED STATES - - 00-0E-80 (hex) Thomson Technology Inc - 000E80 (base 16) Thomson Technology Inc - 9087A 198th ST - Surrey BC V1M-3B1 - CANADA - - 00-0E-81 (hex) Devicescape Software, Inc. - 000E81 (base 16) Devicescape Software, Inc. - 1000 Marina Blvd - Suite 400 - Brisbane CA 94005 - UNITED STATES - - 00-0E-82 (hex) Commtech Wireless - 000E82 (base 16) Commtech Wireless - 115/396 Scarborough Beach Rd - Osborne Park - Perth WA 6017 - AUSTRALIA - - 00-0E-83 (hex) CISCO SYSTEMS, INC. - 000E83 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0E-84 (hex) CISCO SYSTEMS, INC. - 000E84 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0E-85 (hex) Catalyst Enterprises, Inc. - 000E85 (base 16) Catalyst Enterprises, Inc. - 3385 Scott Blvd - Santa Clara CA 95054 - UNITED STATES - - 00-0E-86 (hex) Alcatel North America - 000E86 (base 16) Alcatel North America - 2301 Sugar Bush Road - Raleigh NC 27612 - UNITED STATES - - 00-0E-87 (hex) adp Gauselmann GmbH - 000E87 (base 16) adp Gauselmann GmbH - Boschstraße 8 - Luebbecke NRW 32312 - GERMANY - - 00-0E-88 (hex) VIDEOTRON CORP. - 000E88 (base 16) VIDEOTRON CORP. - 17-16,2-CHOME - HACHIOJI TOKYO 193-0835 - JAPAN - - 00-0E-89 (hex) CLEMATIC - 000E89 (base 16) CLEMATIC - 101 rue Pierre SEMARD - CHATILLON R.P. 92320 - FRANCE - - 00-0E-8A (hex) Avara Technologies Pty. Ltd. - 000E8A (base 16) Avara Technologies Pty. Ltd. - 9 Business Park Drive - Notting Hill Victoria 3168 - AUSTRALIA - - 00-0E-8B (hex) Astarte Technology Co, Ltd. - 000E8B (base 16) Astarte Technology Co, Ltd. - 11F, No. 166 Dah-Yeh Rd. - Peitou, Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-0E-8C (hex) Siemens AG A&D ET - 000E8C (base 16) Siemens AG A&D ET - Siemensstraße 10 - Regensburg 93055 - GERMANY - - 00-0E-8D (hex) Systems in Progress Holding GmbH - 000E8D (base 16) Systems in Progress Holding GmbH - Exerzierplatzstrasse 85 - Graz Styria 8051 - AUSTRIA - - 00-0E-8E (hex) SparkLAN Communications, Inc. - 000E8E (base 16) SparkLAN Communications, Inc. - 3Fl . , No. 246, Sec. 1, Neihu Road., Neihu Chiu, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0E-8F (hex) Sercomm Corp. - 000E8F (base 16) Sercomm Corp. - 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen - Miao-Lih Hsuan 350 - TAIWAN, PROVINCE OF CHINA - - 00-0E-90 (hex) PONICO CORP. - 000E90 (base 16) PONICO CORP. - 602, Ace Twin Tower 1, 212-1 Guro-dong - Gurogu Seoul 152-766 - KOREA, REPUBLIC OF - - 00-0E-91 (hex) Navico Auckland Ltd - 000E91 (base 16) Navico Auckland Ltd - 17-21 Kawana St - Northcote Auckland - NEW ZEALAND - - 00-0E-92 (hex) Open Telecom - 000E92 (base 16) Open Telecom - 803-804 Daeryung Techno-town II - 569-21 Gasa-dong - Keuncheon-Ku Seoul 153-771 - KOREA, REPUBLIC OF - - 00-0E-93 (hex) Milénio 3 Sistemas Electrónicos, Lda. - 000E93 (base 16) Milénio 3 Sistemas Electrónicos, Lda. - Edifício Via Norte, R. Espido 164C S403 - Maia Minho 4470-177 - PORTUGAL - - 00-0E-94 (hex) Maas International BV - 000E94 (base 16) Maas International BV - Science Park Eindhoven 5051 - Son Noord Brabant NL-5692 EB - NETHERLANDS - - 00-0E-95 (hex) Fujiya Denki Seisakusho Co.,Ltd. - 000E95 (base 16) Fujiya Denki Seisakusho Co.,Ltd. - 8F Fukushima BLDG. 6-25-11,Nishi-Gotanda - Shinagawa-Ku Tokyo 141-0031 - JAPAN - - 00-0E-96 (hex) Cubic Defense Applications, Inc. - 000E96 (base 16) Cubic Defense Applications, Inc. - P.O. Box 85587 - 9333 Balboa Avenue - San Diego CA 92186-5587 - UNITED STATES - - 00-0E-97 (hex) Ultracker Technology CO., Inc - 000E97 (base 16) Ultracker Technology CO., Inc - 14F-1, No. 888, Jingguo Road, Taoyuan City, - Taoyuan 330 - TAIWAN, PROVINCE OF CHINA - - 00-0E-98 (hex) HME Clear-Com LTD. - 000E98 (base 16) HME Clear-Com LTD. - 7400 Beach Drive - Waterbeach - Cambridgeshire CB25 9TP - UNITED KINGDOM - - 00-0E-99 (hex) Spectrum Digital, Inc - 000E99 (base 16) Spectrum Digital, Inc - 12502 Exchange Drive, Suite 440 - Stafford TX 77477 - UNITED STATES - - 00-0E-9A (hex) BOE TECHNOLOGY GROUP CO.,LTD - 000E9A (base 16) BOE TECHNOLOGY GROUP CO.,LTD - No.10 Jiuxianqiao Road,Chaoyang District,Beijing,PRC - Beijing 100016 - CHINA - - 00-0E-9B (hex) Ambit Microsystems Corporation - 000E9B (base 16) Ambit Microsystems Corporation - 5F-1, 5 Hsin-An Rd. Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0E-9C (hex) Benchmark Electronics - 000E9C (base 16) Benchmark Electronics - 3535 Technology Drive - Rochester MN 55901 - UNITED STATES - - 00-0E-9D (hex) Tiscali UK Ltd - 000E9D (base 16) Tiscali UK Ltd - 20 Broadwick Street - London W1F 8HT - UNITED KINGDOM - - 00-0E-9E (hex) Topfield Co., Ltd - 000E9E (base 16) Topfield Co., Ltd - 4th floor, Deoksan Bldg 260-4, Seohyun-dong - Seongnam Bundang-Ku 463-824 - KOREA, REPUBLIC OF - - 00-0E-9F (hex) TEMIC SDS GmbH - 000E9F (base 16) TEMIC SDS GmbH - Soeflinger Strasse 100 - Ulm 89077 - GERMANY - - 00-0E-A0 (hex) NetKlass Technology Inc. - 000EA0 (base 16) NetKlass Technology Inc. - 2F-1, No.30,Tai Yuen Street, - Chupei City, Hsinchu, 302 - TAIWAN, PROVINCE OF CHINA - - 00-0E-A1 (hex) Formosa Teletek Corporation - 000EA1 (base 16) Formosa Teletek Corporation - 358,Huaya 2nd Rd. - Gueishan Shiang - Taoyuan 333 - TAIWAN, PROVINCE OF CHINA - - 00-0E-A2 (hex) McAfee, Inc - 000EA2 (base 16) McAfee, Inc - 350 SW 12th Avenue - Deerfield Beach FL 33442 - UNITED STATES - - 00-0E-A3 (hex) CNCR-IT CO.,LTD,HangZhou P.R.CHINA - 000EA3 (base 16) CNCR-IT CO.,LTD,HangZhou P.R.CHINA - XuanTan road NO1.department room504, - HangZhou ZheJiang 310003 - CHINA - - 00-0E-A4 (hex) Certance Inc. - 000EA4 (base 16) Certance Inc. - 1650 Sunflower Ave. - Costa Mesa CA 92626-1513 - UNITED STATES - - 00-0E-A5 (hex) BLIP Systems - 000EA5 (base 16) BLIP Systems - Haekken 2 - Vodskov Vester Hassing 9310 - DENMARK - - 00-0E-A6 (hex) ASUSTEK COMPUTER INC. - 000EA6 (base 16) ASUSTEK COMPUTER INC. - No. 150, Li-Te Rd.,Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-0E-A7 (hex) Endace Technology - 000EA7 (base 16) Endace Technology - 85 Alexandra Street - Hamilton 3204 - NEW ZEALAND - - 00-0E-A8 (hex) United Technologists Europe Limited - 000EA8 (base 16) United Technologists Europe Limited - UTEL Laboratories, Wolves Farm Lane - Ipswich Road - Hadleigh Suffolk IP7 6BH - UNITED KINGDOM - - 00-0E-A9 (hex) Shanghai Xun Shi Communications Equipment Ltd. Co. - 000EA9 (base 16) Shanghai Xun Shi Communications Equipment Ltd. Co. - Hi-Tech King World, Unit C603 - #666 Beijing Road (E) - Shanghai 200001 - CHINA - - 00-0E-AA (hex) Scalent Systems, Inc. - 000EAA (base 16) Scalent Systems, Inc. - 490 S. California Ave - Palo Alto CA 94306 - UNITED STATES - - 00-0E-AB (hex) Cray Inc - 000EAB (base 16) Cray Inc - 901 Fifth Avenue - Suite 1000 - Seattle WA 98164 - UNITED STATES - - 00-0E-AC (hex) MINTRON ENTERPRISE CO., LTD. - 000EAC (base 16) MINTRON ENTERPRISE CO., LTD. - NO.3,Wu-Kung 5Rd., Wu-Ku Ind Park - Taipei County 248 - TAIWAN, PROVINCE OF CHINA - - 00-0E-AD (hex) Metanoia Technologies, Inc. - 000EAD (base 16) Metanoia Technologies, Inc. - 5918 W. courtyard Dr. - Suite 330 - Austin TX 78730 - UNITED STATES - - 00-0E-AE (hex) GAWELL TECHNOLOGIES CORP. - 000EAE (base 16) GAWELL TECHNOLOGIES CORP. - 2F,NO.102,SEC.3,JUNG SHAN RD, - JUNG HO CITY, TAIPEI HSIEN 235 - TAIWAN, PROVINCE OF CHINA - - 00-0E-AF (hex) CASTEL - 000EAF (base 16) CASTEL - ZI Saint Lambert des Levées - SAUMUR Maine et Loire 49412 - FRANCE - - 00-0E-B0 (hex) Solutions Radio BV - 000EB0 (base 16) Solutions Radio BV - Prinsegracht 82 - The Hague ZH 2512 GC - NETHERLANDS - - 00-0E-B1 (hex) Newcotech,Ltd - 000EB1 (base 16) Newcotech,Ltd - Anyang Megavally 715-3 - Kwanyang-Dong, Dongan-Gu, - Anyang City Gueonggi-Do 431-160 - KOREA, REPUBLIC OF - - 00-0E-B2 (hex) Micro-Research Finland Oy - 000EB2 (base 16) Micro-Research Finland Oy - Välitalontie 83 C - Helsinki FIN-00660 - FINLAND - - 00-0E-B3 (hex) Hewlett-Packard - 000EB3 (base 16) Hewlett-Packard - 2580 55th Street - Boulder CO 80301 - UNITED STATES - - 00-0E-B4 (hex) GUANGZHOU GAOKE COMMUNICATIONS TECHNOLOGY CO.LTD. - 000EB4 (base 16) GUANGZHOU GAOKE COMMUNICATIONS TECHNOLOGY CO.LTD. - AVE. 398 ZHONGSHAN - GUANGZHOU GUANGDONG 510660 - CHINA - - 00-0E-B5 (hex) Ecastle Electronics Co., Ltd. - 000EB5 (base 16) Ecastle Electronics Co., Ltd. - #502, Namjang B/D, Bangbae-dong, - Seocho-ku, - Seoul 137-818 - KOREA, REPUBLIC OF - - 00-0E-B6 (hex) Riverbed Technology, Inc. - 000EB6 (base 16) Riverbed Technology, Inc. - 501 Second Street - Suite 410 - San Francisco CA 94107 - UNITED STATES - - 00-0E-B7 (hex) Knovative, Inc. - 000EB7 (base 16) Knovative, Inc. - 11245 West Bernardo Court - Suite 100 - San Diego CA 92127 - UNITED STATES - - 00-0E-B8 (hex) Iiga co.,Ltd - 000EB8 (base 16) Iiga co.,Ltd - 3F TKBldg. 3-5-2 Sotokanda - Chiyoda-Ku Tokyo 101-0021 - JAPAN - - 00-0E-B9 (hex) HASHIMOTO Electronics Industry Co.,Ltd. - 000EB9 (base 16) HASHIMOTO Electronics Industry Co.,Ltd. - 3866-12 Takasu-cho - Matsusaka Mie 515-0104 - JAPAN - - 00-0E-BA (hex) HANMI SEMICONDUCTOR CO., LTD. - 000EBA (base 16) HANMI SEMICONDUCTOR CO., LTD. - #532-2, Gajwa-Dong, Seo-Ku, - Incheon 404 250 - KOREA, REPUBLIC OF - - 00-0E-BB (hex) Everbee Networks - 000EBB (base 16) Everbee Networks - 41, Boulevard des Capucines - Paris 75002 - FRANCE - - 00-0E-BC (hex) Paragon Fidelity GmbH - 000EBC (base 16) Paragon Fidelity GmbH - Schwadermühlstraße - Cadolzburg 90556 - GERMANY - - 00-0E-BD (hex) Burdick, a Quinton Compny - 000EBD (base 16) Burdick, a Quinton Compny - 500 Burdick Parkway - Deerfield WI 53531 - UNITED STATES - - 00-0E-BE (hex) B&B Electronics Manufacturing Co. - 000EBE (base 16) B&B Electronics Manufacturing Co. - 707 Dayton Road - P.O. Box 1040 - Ottawa Ilinois 61350 - UNITED STATES - - 00-0E-BF (hex) Remsdaq Limited - 000EBF (base 16) Remsdaq Limited - Parkway - Deeside Industrial Park - Deeside Flintshire CH5 2NL - UNITED KINGDOM - - 00-0E-C0 (hex) Nortel Networks - 000EC0 (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-0E-C1 (hex) MYNAH Technologies - 000EC1 (base 16) MYNAH Technologies - 504 Trade Center Blvd - Chesterfield MO 63005 - UNITED STATES - - 00-0E-C2 (hex) Lowrance Electronics, Inc. - 000EC2 (base 16) Lowrance Electronics, Inc. - 12000 E. Skelly Drive - Tulsa OK 74128 - UNITED STATES - - 00-0E-C3 (hex) Logic Controls, Inc. - 000EC3 (base 16) Logic Controls, Inc. - 355 Denton Avenue - New Hyde Park NY 11040 - UNITED STATES - - 00-0E-C4 (hex) Iskra Transmission d.d. - 000EC4 (base 16) Iskra Transmission d.d. - Stegne 11 - Ljubljana 1000 - SLOVENIA - - 00-0E-C5 (hex) Digital Multitools Inc - 000EC5 (base 16) Digital Multitools Inc - 9005 Leslie Street Unit 205 - Richmond Hill Ontario L4B 1G7 - CANADA - - 00-0E-C6 (hex) ASIX ELECTRONICS CORP. - 000EC6 (base 16) ASIX ELECTRONICS CORP. - 4F, NO.8, HSIN ANN RD., - SCIENCE-BASED INDUSTRIAL PARK, - HSINCHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-0E-C7 (hex) Motorola Korea - 000EC7 (base 16) Motorola Korea - Hibrand B/D 17F SW Team Motorola Korea - Yangjaedong Seocho - KOREA, REPUBLIC OF - - 00-0E-C8 (hex) Zoran Corporation - 000EC8 (base 16) Zoran Corporation - 1390 Kifer Rd. - Sunnyvale CA 94086 - UNITED STATES - - 00-0E-C9 (hex) YOKO Technology Corp. - 000EC9 (base 16) YOKO Technology Corp. - 6F, No.10, Lane16, Sec2, Sze-Chuan Rd., Pan- - Chiao City, - Taipei 886 - TAIWAN, PROVINCE OF CHINA - - 00-0E-CA (hex) WTSS Inc - 000ECA (base 16) WTSS Inc - 5999 Avenida Encinas - Suite 150 - Carlsbad CA 92008 - UNITED STATES - - 00-0E-CB (hex) VineSys Technology - 000ECB (base 16) VineSys Technology - 3350 Scott Blvd. building 15-03 - Santa Clara CA 95054 - UNITED STATES - - 00-0E-CC (hex) Tableau, LLC - 000ECC (base 16) Tableau, LLC - N8 W22195 Johnson Drive, Suite 100 - Waukesha WI 53186 - UNITED STATES - - 00-0E-CD (hex) SKOV A/S - 000ECD (base 16) SKOV A/S - Hedelund 4 - Glyngoere - Roslev DK-7870 - DENMARK - - 00-0E-CE (hex) S.I.T.T.I. S.p.A. - 000ECE (base 16) S.I.T.T.I. S.p.A. - Via Cadorna 69 - Vimodrone Milan I-20090 - ITALY - - 00-0E-CF (hex) PROFIBUS Nutzerorganisation e.V. - 000ECF (base 16) PROFIBUS Nutzerorganisation e.V. - Haid-und-Neu-Straße 7 - Karlsruhe Baden-Württemberg 76131 - GERMANY - - 00-0E-D0 (hex) Privaris, Inc. - 000ED0 (base 16) Privaris, Inc. - 650 Peter Jefferson Pkwy, Ste 330 - Charlottesville Virginia 22911 - UNITED STATES - - 00-0E-D1 (hex) Osaka Micro Computer. - 000ED1 (base 16) Osaka Micro Computer. - Isonokamicyo 3-11-7 - Kishiwada Osaka 5960001 - JAPAN - - 00-0E-D2 (hex) Filtronic plc - 000ED2 (base 16) Filtronic plc - The Waterfront - Salts Mill Rd - Saltaire W Yorks BD18 3TT - UNITED KINGDOM - - 00-0E-D3 (hex) Epicenter, Inc. - 000ED3 (base 16) Epicenter, Inc. - 211 B Calle Pintoresco - San Clemente CA 92672 - UNITED STATES - - 00-0E-D4 (hex) CRESITT INDUSTRIE - 000ED4 (base 16) CRESITT INDUSTRIE - 12 rue de Blois - Orleans BP 6744 45067 cedex - FRANCE - - 00-0E-D5 (hex) COPAN Systems Inc. - 000ED5 (base 16) COPAN Systems Inc. - 2605 Trade Centre Ave. - Suite D - Longmont CO 80503 - UNITED STATES - - 00-0E-D6 (hex) CISCO SYSTEMS, INC. - 000ED6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0E-D7 (hex) CISCO SYSTEMS, INC. - 000ED7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0E-D8 (hex) Aktino, Inc. - 000ED8 (base 16) Aktino, Inc. - 18551 Von Karman Avenue - Suite 201 - Irvine CA 92612 - UNITED STATES - - 00-0E-D9 (hex) Aksys, Ltd. - 000ED9 (base 16) Aksys, Ltd. - 2 Marriott Drive - Lincolnshire IL 60069 - UNITED STATES - - 00-0E-DA (hex) C-TECH UNITED CORP. - 000EDA (base 16) C-TECH UNITED CORP. - 5F, No 665, CHUNG CHEN RD. - HSIN CHUANG CITT of TAIPEI HSIEN 242 - TAIWAN, PROVINCE OF CHINA - - 00-0E-DB (hex) XiNCOM Corp. - 000EDB (base 16) XiNCOM Corp. - 2840 Industrial Ave. - Hubbard OR 97032 - UNITED STATES - - 00-0E-DC (hex) Tellion INC. - 000EDC (base 16) Tellion INC. - 5th Fl. BONA Venture Town - 1586-1 Seocho 3-dong, Seocho-gu - Seoul Seocho-gu. 137-719 - KOREA, REPUBLIC OF - - 00-0E-DD (hex) SHURE INCORPORATED - 000EDD (base 16) SHURE INCORPORATED - 5800 W. TOUHY AVE. - NILES IL 60714 - UNITED STATES - - 00-0E-DE (hex) REMEC, Inc. - 000EDE (base 16) REMEC, Inc. - 2144 Franklin Drive NE - Palm Bay Florida 32905-4021 - UNITED STATES - - 00-0E-DF (hex) PLX Technology - 000EDF (base 16) PLX Technology - 870 Maude Ave., - Sunnyvale CA 94085 - UNITED STATES - - 00-0E-E0 (hex) Mcharge - 000EE0 (base 16) Mcharge - Firstec Bldg,. 15-4 Youido-Dong - Youngdeungpo-Gu, - seoul Youido 150-010 - KOREA, REPUBLIC OF - - 00-0E-E1 (hex) ExtremeSpeed Inc. - 000EE1 (base 16) ExtremeSpeed Inc. - PO Box 600 - 4634-46th Street Suite 201 - Mannville Alberta T0B 2W0 - CANADA - - 00-0E-E2 (hex) Custom Engineering - 000EE2 (base 16) Custom Engineering - Via Beretttine 2/b - Fontevivo Parma 43010 - ITALY - - 00-0E-E3 (hex) Chiyu Technology Co.,Ltd - 000EE3 (base 16) Chiyu Technology Co.,Ltd - No. 28, Renai Road, Chiayi, 600 - Chiayi 600 - TAIWAN, PROVINCE OF CHINA - - 00-0E-E4 (hex) BOE TECHNOLOGY GROUP CO.,LTD - 000EE4 (base 16) BOE TECHNOLOGY GROUP CO.,LTD - No.10 Jiuxianqiao Road,Chaoyang District, - Beijing 100016 - CHINA - - 00-0E-E5 (hex) bitWallet, Inc. - 000EE5 (base 16) bitWallet, Inc. - Gate City Ohsaki West Tower 18F, 1-11-1 Osaki, Shinagawa-ku - Tokyo 1410032 - JAPAN - - 00-0E-E6 (hex) Adimos Systems LTD - 000EE6 (base 16) Adimos Systems LTD - 17 Atirey-Yeda Street - Kfar-Saba 44643 - ISRAEL - - 00-0E-E7 (hex) AAC ELECTRONICS CORP. - 000EE7 (base 16) AAC ELECTRONICS CORP. - FLOOR 7,SIXTH BUILDING OF NAIANYOU TNAN INDUSTRIAL AREA,NANSHAN DISTRICT - SHENZHEN PROVINCE GUANGDONG 518054 - CHINA - - 00-0E-E8 (hex) zioncom - 000EE8 (base 16) zioncom - West wing 5/F ., Block 1, GaoXin South Ring Rd/Keji South Rd, - Vision(ShenZhen)Business Park, Shenzhen Hi-Tech Industrial Park, - Shenzhen Guangdong 518057 - CHINA - - 00-0E-E9 (hex) WayTech Development, Inc. - 000EE9 (base 16) WayTech Development, Inc. - 11Floor, 253 Min-Sheng Road - HsinChu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0E-EA (hex) Shadong Luneng Jicheng Electronics,Co.,Ltd - 000EEA (base 16) Shadong Luneng Jicheng Electronics,Co.,Ltd - No.188,east,Huayuan Road - Jinan Shandong 250100 - CHINA - - 00-0E-EB (hex) Sandmartin(zhong shan)Electronics Co.,Ltd - 000EEB (base 16) Sandmartin(zhong shan)Electronics Co.,Ltd - 3st Industrial Area,Tan Zhou, - Zhongshan Guangdong 528467 - CHINA - - 00-0E-EC (hex) Orban - 000EEC (base 16) Orban - 1525 Alvarado St. - San Leandro CA 94577 - UNITED STATES - - 00-0E-ED (hex) Nokia Danmark A/S - 000EED (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-0E-EE (hex) Muco Industrie BV - 000EEE (base 16) Muco Industrie BV - Pleimuiden 12e - Amsterdam NH 1046 AG - NETHERLANDS - - 00-0E-EF (hex) PRIVATE - 000EEF (base 16) - - 00-0E-F0 (hex) Festo AG & Co. KG - 000EF0 (base 16) Festo AG & Co. KG - Ruiterstraße 82 - Esslingen 73734 - GERMANY - - 00-0E-F1 (hex) EZQUEST INC. - 000EF1 (base 16) EZQUEST INC. - 21133 E. LA PALMA AVE. - YORBA LINDA CA 92887 - UNITED STATES - - 00-0E-F2 (hex) Infinico Corporation - 000EF2 (base 16) Infinico Corporation - 4F, F-1 Bldg., 1-2-12, - Hamamatsucho, Mitano-ku - Tokyo 105-0013 - JAPAN - - 00-0E-F3 (hex) Smarthome - 000EF3 (base 16) Smarthome - 16542 Millikan Ave. - Irvine CA 92606 - UNITED STATES - - 00-0E-F4 (hex) Kasda Networks Inc - 000EF4 (base 16) Kasda Networks Inc - B-31 Building, Tanglang Industry Zone - Xili, Nanshan District - Shenzhen Guangdong Province 518055 - CHINA - - 00-0E-F5 (hex) iPAC Technology Co., Ltd. - 000EF5 (base 16) iPAC Technology Co., Ltd. - 6F, No. 30, Shingjung Road, Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0E-F6 (hex) E-TEN Information Systems Co., Ltd. - 000EF6 (base 16) E-TEN Information Systems Co., Ltd. - No. 256, Yangguang Street, Neihu Chiu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0E-F7 (hex) Vulcan Portals Inc - 000EF7 (base 16) Vulcan Portals Inc - 505 5th Ave South, Suite 900 - Seattle WA 98104 - UNITED STATES - - 00-0E-F8 (hex) SBC ASI - 000EF8 (base 16) SBC ASI - Network & Infrastructure Technical Support - 1010 N Saint Marys - San Antonio Texas 78215 - UNITED STATES - - 00-0E-F9 (hex) REA Elektronik GmbH - 000EF9 (base 16) REA Elektronik GmbH - Teichwiesenstraße 1 - Muehltal Hessen 64367 - GERMANY - - 00-0E-FA (hex) Optoway Technology Incorporation - 000EFA (base 16) Optoway Technology Incorporation - No. 38, Kuang Fu South Road - Hsin Chu Industrial Park - Hu Kou Hsin Chu 303 - TAIWAN, PROVINCE OF CHINA - - 00-0E-FB (hex) Macey Enterprises - 000EFB (base 16) Macey Enterprises - P.O. Box 7267 - Tempe AZ 85281 - UNITED STATES - - 00-0E-FC (hex) JTAG Technologies B.V. - 000EFC (base 16) JTAG Technologies B.V. - Boschdijk 50 - Eindhoven NB 5612 AN - NETHERLANDS - - 00-0E-FD (hex) FUJINON CORPORATION - 000EFD (base 16) FUJINON CORPORATION - 1-324 UETAKE, KITA-KU, - SAITAMA CITY SAITAMA 331-9624 - JAPAN - - 00-0E-FE (hex) EndRun Technologies LLC - 000EFE (base 16) EndRun Technologies LLC - 2270 Northpoint Parkway - Santa Rosa CA 95407 - UNITED STATES - - 00-0E-FF (hex) Megasolution,Inc. - 000EFF (base 16) Megasolution,Inc. - 2-7-10 Shitaya - Taito TOKYO 110-0004 - JAPAN - - 00-0F-00 (hex) Legra Systems, Inc. - 000F00 (base 16) Legra Systems, Inc. - 3 Burlington Woods Drive - Burlington MA 01803 - UNITED STATES - - 00-0F-01 (hex) DIGITALKS INC - 000F01 (base 16) DIGITALKS INC - 14 MARSHALL LANE - WESTON CT 06883 - UNITED STATES - - 00-0F-02 (hex) Digicube Technology Co., Ltd - 000F02 (base 16) Digicube Technology Co., Ltd - 8F,No. 51, Lane 35, Jihu Rd., - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0F-03 (hex) COM&C CO., LTD - 000F03 (base 16) COM&C CO., LTD - 2F Woojin BLD 1445-2 Secho-Dong - Secho-Gu - SEOUL 137-070 - KOREA, REPUBLIC OF - - 00-0F-04 (hex) cim-usa inc - 000F04 (base 16) cim-usa inc - 10813 nw 30th street - miami florida 33172 - UNITED STATES - - 00-0F-05 (hex) 3B SYSTEM INC. - 000F05 (base 16) 3B SYSTEM INC. - 1727, SANKYUK2-DONG, BUK-GU - DAEGU 702-845 - KOREA, REPUBLIC OF - - 00-0F-06 (hex) Nortel Networks - 000F06 (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-0F-07 (hex) Mangrove Systems, Inc. - 000F07 (base 16) Mangrove Systems, Inc. - 10 Fairfield Blvd. - Wallingford CT 06492 - UNITED STATES - - 00-0F-08 (hex) Indagon Oy - 000F08 (base 16) Indagon Oy - Nuijamiestentie 5 A - Helsinki - 00400 - FINLAND - - 00-0F-09 (hex) PRIVATE - 000F09 (base 16) - - 00-0F-0A (hex) Clear Edge Networks - 000F0A (base 16) Clear Edge Networks - 11250 El Camino Real - San Diego CA 92130 - UNITED STATES - - 00-0F-0B (hex) Kentima Technologies AB - 000F0B (base 16) Kentima Technologies AB - Box 174 - Kastanjevägen 2 - Staffanstorp SkÃ¥ne 245 44 - SWEDEN - - 00-0F-0C (hex) SYNCHRONIC ENGINEERING - 000F0C (base 16) SYNCHRONIC ENGINEERING - 25 CAP DARNETAL - DARNETAL FRANCE 76160 - FRANCE - - 00-0F-0D (hex) Hunt Electronic Co., Ltd. - 000F0D (base 16) Hunt Electronic Co., Ltd. - 6FI, NO. 57-59, Jiun H Sien Rd., Chi Tu District - Keelung Taiwan 206 - TAIWAN, PROVINCE OF CHINA - - 00-0F-0E (hex) WaveSplitter Technologies, Inc. - 000F0E (base 16) WaveSplitter Technologies, Inc. - 2248 North First Street - San Jose CA 95131 - UNITED STATES - - 00-0F-0F (hex) Real ID Technology Co., Ltd. - 000F0F (base 16) Real ID Technology Co., Ltd. - 9F Hanmi B/D 192-19 - Nonhyeon-Dong - Gangnam-Gu Seoul 135-010 - KOREA, REPUBLIC OF - - 00-0F-10 (hex) RDM Corporation - 000F10 (base 16) RDM Corporation - 608 Weber St. N - Waterloo ON N2V 1K4 - CANADA - - 00-0F-11 (hex) Prodrive B.V. - 000F11 (base 16) Prodrive B.V. - P.O. 28030 - Eindhoven 5602 JA - NETHERLANDS - - 00-0F-12 (hex) Panasonic Europe Ltd. - 000F12 (base 16) Panasonic Europe Ltd. - Hesebergweg 49-51 - Peine D-31228 - GERMANY - - 00-0F-13 (hex) Nisca corporation - 000F13 (base 16) Nisca corporation - 430-1 - Kobayashi - Masuho-Cho Yamanashi-Ken 400-0593 - JAPAN - - 00-0F-14 (hex) Mindray Co., Ltd. - 000F14 (base 16) Mindray Co., Ltd. - Mindray Building, Keji 12th Road South - High-tech Industrial Park, Nanshan - Shenzhen Guangdong 518057 - CHINA - - 00-0F-15 (hex) Kjaerulff1 A/S - 000F15 (base 16) Kjaerulff1 A/S - C.F. Tietgens Boulevard 19 - Odense SØ Fyn 5220 - DENMARK - - 00-0F-16 (hex) JAY HOW TECHNOLOGY CO., - 000F16 (base 16) JAY HOW TECHNOLOGY CO., - NO.486,SEC. 1, WAN SHOU RD., KUEI - SHAN HSIANG, TAOYUAN HSIEN - TAOYUAN HSIEN 333 - TAIWAN, PROVINCE OF CHINA - - 00-0F-17 (hex) Insta Elektro GmbH - 000F17 (base 16) Insta Elektro GmbH - Hohe Steinert 10 - Luedenscheid NRW D-58809 - GERMANY - - 00-0F-18 (hex) Industrial Control Systems - 000F18 (base 16) Industrial Control Systems - Houtschelf 1 - Hardinxveld Zuid-Holland NL-3371 KB - NETHERLANDS - - 00-0F-19 (hex) Boston Scientific - 000F19 (base 16) Boston Scientific - 4100 Hamline Ave N. - St. Paul MN 55112 - UNITED STATES - - 00-0F-1A (hex) Gaming Support B.V. - 000F1A (base 16) Gaming Support B.V. - Industrie weg 29 - Rotterdam 3044 AS - NETHERLANDS - - 00-0F-1B (hex) Ego Systems Inc. - 000F1B (base 16) Ego Systems Inc. - 1206 Woolim e-Biz Center II - 16 Yangpyongdong3ga, Youngdungpo-gu - Seoul 150-834 - KOREA, REPUBLIC OF - - 00-0F-1C (hex) DigitAll World Co., Ltd - 000F1C (base 16) DigitAll World Co., Ltd - Sejin Bld 2F, 689 ilwon2-dong, - gangnam-gu Seoul 135-946 - KOREA, REPUBLIC OF - - 00-0F-1D (hex) Cosmo Techs Co., Ltd. - 000F1D (base 16) Cosmo Techs Co., Ltd. - 2-6-1, Matsue - Atsugi-shi Kanagawa-ken 243-0005 - JAPAN - - 00-0F-1E (hex) Chengdu KT Electric Co.of High & New Technology - 000F1E (base 16) Chengdu KT Electric Co.of High & New Technology - No.2 Gaopeng Dong Road,High & New Development Zone, - No.9 Wuke East No.3 Road,Wuhou Zone, - Chengdu Sichuan 610041 - CHINA - - 00-0F-1F (hex) Dell Inc - 000F1F (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-0F-20 (hex) Hewlett-Packard Company - 000F20 (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS070405 - Houston TX 77070 - UNITED STATES - - 00-0F-21 (hex) Scientific Atlanta, Inc - 000F21 (base 16) Scientific Atlanta, Inc - 5030 Sugarloaf Parkway - PO Box 465447 - Lawrenceville Ga 30042 - UNITED STATES - - 00-0F-22 (hex) Helius, Inc. - 000F22 (base 16) Helius, Inc. - 333 South 520 West - Suite 330 - Lindon UT 84042 - UNITED STATES - - 00-0F-23 (hex) CISCO SYSTEMS, INC. - 000F23 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-24 (hex) CISCO SYSTEMS, INC. - 000F24 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-25 (hex) AimValley B.V. - 000F25 (base 16) AimValley B.V. - Utrechtseweg 38, - Hilversum NH 1223 TV - NETHERLANDS - - 00-0F-26 (hex) WorldAccxx LLC - 000F26 (base 16) WorldAccxx LLC - 4035 Tampa Rd. - Suite 6000 - Oldsmar FL 34667 - UNITED STATES - - 00-0F-27 (hex) TEAL Electronics, Inc. - 000F27 (base 16) TEAL Electronics, Inc. - 10350 Sorrento Valley Road - San Diego California 92121 - UNITED STATES - - 00-0F-28 (hex) Itronix Corporation - 000F28 (base 16) Itronix Corporation - South 801 Stevens Street - Spokane WA 99204 - UNITED STATES - - 00-0F-29 (hex) Augmentix Corporation - 000F29 (base 16) Augmentix Corporation - 4030 W Braker Ln - Building 2, Suite 100 - Austin Texas 78759 - UNITED STATES - - 00-0F-2A (hex) Cableware Electronics - 000F2A (base 16) Cableware Electronics - 1702 Western Ave. - Suite G - Las Vegas Nevada 89102 - UNITED STATES - - 00-0F-2B (hex) GREENBELL SYSTEMS - 000F2B (base 16) GREENBELL SYSTEMS - 2TH Floor, Doonam Bldg, 236-11 Nonhyun-Dong, Kangnam-Ku - Seoul 135-010 - KOREA, REPUBLIC OF - - 00-0F-2C (hex) Uplogix, Inc. - 000F2C (base 16) Uplogix, Inc. - Bldg 1, Suite 235 - 8601 RR 2222 - Austin TX 78730 - UNITED STATES - - 00-0F-2D (hex) CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. - 000F2D (base 16) CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. - NO. 25, Wen-Te Rd., Lo-Shan Village - Kwei Shan Hsiang Taoyuan Hsien 330 - TAIWAN, PROVINCE OF CHINA - - 00-0F-2E (hex) Megapower International Corp. - 000F2E (base 16) Megapower International Corp. - Rm. 403, No 24 , Wu-Chuan 2nd Rd., - Hsin-Chuang - Taipei Hsien 242 - TAIWAN, PROVINCE OF CHINA - - 00-0F-2F (hex) W-LINX TECHNOLOGY CO., LTD. - 000F2F (base 16) W-LINX TECHNOLOGY CO., LTD. - 2F,ELLEN L. SKELTON BUILDING,FISHER LANE ROAD - TORTOLA - VIRGIN ISLANDS, BRITISH - - 00-0F-30 (hex) Raza Microelectronics Inc - 000F30 (base 16) Raza Microelectronics Inc - 3080 North First Street - 5th Floor - San Jose CA 95134 - UNITED STATES - - 00-0F-31 (hex) Allied Vision Technologies Canada Inc - 000F31 (base 16) Allied Vision Technologies Canada Inc - 101-3750 North Fraser Way - Burnaby BC V5J 5E9 - CANADA - - 00-0F-32 (hex) Lootom Telcovideo Network Wuxi Co Ltd - 000F32 (base 16) Lootom Telcovideo Network Wuxi Co Ltd - 5F, 9Building, - 100# Dicui Road - WuXi JiangSu 214072 - CHINA - - 00-0F-33 (hex) DUALi Inc. - 000F33 (base 16) DUALi Inc. - #505 Samsung Techno Park Bldg 471 - Woncheon-dong, Youngtong-gu - Suwon Gyeonggi-do 442-824 - KOREA, REPUBLIC OF - - 00-0F-34 (hex) CISCO SYSTEMS, INC. - 000F34 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-35 (hex) CISCO SYSTEMS, INC. - 000F35 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-36 (hex) Accurate Techhnologies, Inc. - 000F36 (base 16) Accurate Techhnologies, Inc. - 47199 Cartier Dr. - Wixom Michigan 48393 - UNITED STATES - - 00-0F-37 (hex) Xambala Incorporated - 000F37 (base 16) Xambala Incorporated - 2674 N. 1st Street - Suite 215 - San Jose CA 95134 - UNITED STATES - - 00-0F-38 (hex) Netstar - 000F38 (base 16) Netstar - 3F,No.347, Yang-kuang St.,Nei-Hu Dis., - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0F-39 (hex) IRIS SENSORS - 000F39 (base 16) IRIS SENSORS - ZA les Ufernets - TOULAUD Ardeche F07130 - FRANCE - - 00-0F-3A (hex) HISHARP - 000F3A (base 16) HISHARP - NO.673,CHANG HSING ROAD PATE CITY,TAOYUAN, - TAIPEI 334 - TAIWAN, PROVINCE OF CHINA - - 00-0F-3B (hex) Fuji System Machines Co., Ltd. - 000F3B (base 16) Fuji System Machines Co., Ltd. - 5-8-10 - Hibarigaoka - Zama-Shi Kanagawa-Ken 228-0003 - JAPAN - - 00-0F-3C (hex) Endeleo Limited - 000F3C (base 16) Endeleo Limited - 78 Cannon Street - London England EC4N 6NQ - UNITED KINGDOM - - 00-0F-3D (hex) D-Link Corporation - 000F3D (base 16) D-Link Corporation - No.8,Li-shing Seventh Road,Science-based Industrial Park,Hsimchu, - Hsimchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0F-3E (hex) CardioNet, Inc - 000F3E (base 16) CardioNet, Inc - 1010 Second Avenue - Suite 700 - San Diego CA 92101 - UNITED STATES - - 00-0F-3F (hex) Big Bear Networks - 000F3F (base 16) Big Bear Networks - 345 Potrero Ave - Sunny Vale California 94085 - UNITED STATES - - 00-0F-40 (hex) Optical Internetworking Forum - 000F40 (base 16) Optical Internetworking Forum - 48377 Fremont Blvd - Ste 117 - Fremont CA 94538 - UNITED STATES - - 00-0F-41 (hex) Zipher Ltd - 000F41 (base 16) Zipher Ltd - 7 Faraday Building - Nottingham Science and Technology Park - Nottingham Nottinghamshire NG7 2QP - UNITED KINGDOM - - 00-0F-42 (hex) Xalyo Systems - 000F42 (base 16) Xalyo Systems - Grenier 9 - Commugny VD 1291 - SWITZERLAND - - 00-0F-43 (hex) Wasabi Systems Inc. - 000F43 (base 16) Wasabi Systems Inc. - 500 E. Main Street - Suite 1520 - Norfolk VA 23510 - UNITED STATES - - 00-0F-44 (hex) Tivella Inc. - 000F44 (base 16) Tivella Inc. - 795 Main Street - Half Moon Bay CA 94019 - UNITED STATES - - 00-0F-45 (hex) Stretch, Inc. - 000F45 (base 16) Stretch, Inc. - 1322 Orleans Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-0F-46 (hex) SINAR AG - 000F46 (base 16) SINAR AG - Stadtweg 24 - Feuerthalen ZH CH-8245 - SWITZERLAND - - 00-0F-47 (hex) ROBOX SPA - 000F47 (base 16) ROBOX SPA - via Sempione 82 - Castelletto S.Ticino NO 28053 - ITALY - - 00-0F-48 (hex) Polypix Inc. - 000F48 (base 16) Polypix Inc. - 1Fl, Sungdo Venture Tower, 165-2 Samsung-Dong, Kangnam-Ku - Seoul 135-881 - KOREA, REPUBLIC OF - - 00-0F-49 (hex) Northover Solutions Limited - 000F49 (base 16) Northover Solutions Limited - Heath Cottage - Illington Road - Larling Norfolk NR16 2RB - UNITED KINGDOM - - 00-0F-4A (hex) Kyushu-kyohan co.,ltd - 000F4A (base 16) Kyushu-kyohan co.,ltd - 2-6-3,Koganemachi - Kokurakita-ku - Kitakyushu-city Fukuoka 802-0071 - JAPAN - - 00-0F-4B (hex) Oracle Corporation - 000F4B (base 16) Oracle Corporation - 900 Chelmsford Street - Tower 1 Floor 2 - Lowell MA 01851 - UNITED STATES - - 00-0F-4C (hex) Elextech INC - 000F4C (base 16) Elextech INC - 554-2, Gasan-Dong, Gumcheon-Gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-0F-4D (hex) TalkSwitch - 000F4D (base 16) TalkSwitch - 1545 Carling Ave - Suite 510 - Ottawa Ontario K1Z 8P9 - CANADA - - 00-0F-4E (hex) Cellink - 000F4E (base 16) Cellink - Catherinalaan 37 - Rotselaar Vlaams Brabant B-3110 - BELGIUM - - 00-0F-4F (hex) Cadmus Technology Ltd - 000F4F (base 16) Cadmus Technology Ltd - 66 Hillside Rd - Glenfield - Auckland 1310 - NEW ZEALAND - - 00-0F-50 (hex) StreamScale Limited - 000F50 (base 16) StreamScale Limited - The Court, Alexandra Park - Prescot Road - St Helens WA10 3TP - UNITED KINGDOM - - 00-0F-51 (hex) Azul Systems, Inc. - 000F51 (base 16) Azul Systems, Inc. - 1600 Plymouth Street - Mountain View California 94043 - UNITED STATES - - 00-0F-52 (hex) YORK Refrigeration, Marine & Controls - 000F52 (base 16) YORK Refrigeration, Marine & Controls - Jens Juulsvej 28 - Viby J DK 8362 - DENMARK - - 00-0F-53 (hex) Solarflare Communications Inc - 000F53 (base 16) Solarflare Communications Inc - 9501 Jeronimo Road - Suite 250 - Irvine CA 92618 - UNITED STATES - - 00-0F-54 (hex) Entrelogic Corporation - 000F54 (base 16) Entrelogic Corporation - 33 Boston Post Rd. West. - Suite 160 - Marlborough MA 01752 - UNITED STATES - - 00-0F-55 (hex) Datawire Communication Networks Inc. - 000F55 (base 16) Datawire Communication Networks Inc. - 10 Carlson Court, Suite 300 - Toronto Ontario M9W 6L2 - CANADA - - 00-0F-56 (hex) Continuum Photonics Inc - 000F56 (base 16) Continuum Photonics Inc - 5 Fortune Drive - Billerica MA 01821 - UNITED STATES - - 00-0F-57 (hex) CABLELOGIC Co., Ltd. - 000F57 (base 16) CABLELOGIC Co., Ltd. - 3F., Hwain Bldg., 1559-12 Seocho 3-dong, - Secho-gu, - Seoul 137-873 - KOREA, REPUBLIC OF - - 00-0F-58 (hex) Adder Technology Limited - 000F58 (base 16) Adder Technology Limited - Technology House - Trafalgar Way - Bar Hill Cambridgeshire CB3 8SQ - UNITED KINGDOM - - 00-0F-59 (hex) Phonak Communications AG - 000F59 (base 16) Phonak Communications AG - Länggasse 17 - Murten FR 3280 - SWITZERLAND - - 00-0F-5A (hex) Peribit Networks - 000F5A (base 16) Peribit Networks - 2855 Bowers Ave - Santa Clara CA 95051 - UNITED STATES - - 00-0F-5B (hex) Delta Information Systems, Inc. - 000F5B (base 16) Delta Information Systems, Inc. - 300 Welsh Road, Bldg. 3 - Horsham PA 19044-2273 - UNITED STATES - - 00-0F-5C (hex) Day One Digital Media Limited - 000F5C (base 16) Day One Digital Media Limited - 197 Archers Rd - Glenfield - Auckland North Island 1310 - NEW ZEALAND - - 00-0F-5D (hex) Genexis BV - 000F5D (base 16) Genexis BV - Lodewijktraat 1A - 5652 AC Eindhoven - SWEDEN - - 00-0F-5E (hex) Veo - 000F5E (base 16) Veo - 910 Rincon Circle - San Jose CA 95131 - UNITED STATES - - 00-0F-5F (hex) Nicety Technologies Inc. (NTS) - 000F5F (base 16) Nicety Technologies Inc. (NTS) - 792-3 Tomioka Toyoda-cho - Iwata-gun Shizuoka 438-0803 - JAPAN - - 00-0F-60 (hex) Lifetron Co.,Ltd - 000F60 (base 16) Lifetron Co.,Ltd - 6-7,Tenjinnishimachi - Kita-Ku - Osaka Osaka Prefecture 530-0045 - JAPAN - - 00-0F-61 (hex) Hewlett-Packard Company - 000F61 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - Houston TX 77070 - UNITED STATES - - 00-0F-62 (hex) Alcatel Bell Space N.V. - 000F62 (base 16) Alcatel Bell Space N.V. - Berkenrodelei 33 - Hoboken Antwerpen B-2660 - BELGIUM - - 00-0F-63 (hex) Obzerv Technologies - 000F63 (base 16) Obzerv Technologies - 400 Jean Lesage - suite 201 - Quebec QC G1K8W1 - CANADA - - 00-0F-64 (hex) D&R Electronica Weesp BV - 000F64 (base 16) D&R Electronica Weesp BV - Rijnkade 15B - WEESP NH 1382GS - NETHERLANDS - - 00-0F-65 (hex) icube Corp. - 000F65 (base 16) icube Corp. - Olympia Center 2F,828-10,Yeoksam-dong,Kangnam-ku - Seoul South 135-935 - KOREA, REPUBLIC OF - - 00-0F-66 (hex) Cisco-Linksys - 000F66 (base 16) Cisco-Linksys - 121 Theory Dr. - Irvine CA 92612 - UNITED STATES - - 00-0F-67 (hex) West Instruments - 000F67 (base 16) West Instruments - Unit 5, The Hyde, Lower Bevendean - Brighton East Sussex BN2 4JU - UNITED KINGDOM - - 00-0F-68 (hex) Vavic Network Technology, Inc. - 000F68 (base 16) Vavic Network Technology, Inc. - 1st Floor, 15 Jiangong Road - Tianhe S&T Zone - Guangzhou Guangdong 510665 - CHINA - - 00-0F-69 (hex) SEW Eurodrive GmbH & Co. KG - 000F69 (base 16) SEW Eurodrive GmbH & Co. KG - Ernst Blickle Str. 42 - Bruchsal 76646 - GERMANY - - 00-0F-6A (hex) Nortel Networks - 000F6A (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-0F-6B (hex) GateWare Communications GmbH - 000F6B (base 16) GateWare Communications GmbH - Allersberger Strasse 185 F - Nuernberg Bavaria D-90461 - GERMANY - - 00-0F-6C (hex) ADDI-DATA GmbH - 000F6C (base 16) ADDI-DATA GmbH - Airport Boulevard B210 - RHEINMUENSTER BW 77836 - GERMANY - - 00-0F-6D (hex) Midas Engineering - 000F6D (base 16) Midas Engineering - Ace Techno-Tower V #906 197-22 - Kuro-Dong, Kuro-Gu - Seoul 152-848 - KOREA, REPUBLIC OF - - 00-0F-6E (hex) BBox - 000F6E (base 16) BBox - Gyar u. 2. (115) - Budaors H-2040 - HUNGARY - - 00-0F-6F (hex) FTA Communication Technologies - 000F6F (base 16) FTA Communication Technologies - 11, rue Pierre Werner - Betzdorf L-6832 - LUXEMBOURG - - 00-0F-70 (hex) Wintec Industries, inc. - 000F70 (base 16) Wintec Industries, inc. - 675 Sycamore Drive - Milpitas, CA 95035 - UNITED STATES - - 00-0F-71 (hex) Sanmei Electronics Co.,Ltd - 000F71 (base 16) Sanmei Electronics Co.,Ltd - 2-2-1,Seikai,Shimizu - Shizuoka 424-0924 - JAPAN - - 00-0F-72 (hex) Sandburst - 000F72 (base 16) Sandburst - 600 Federal St - 2nd Floor - Andover MA 01810 - UNITED STATES - - 00-0F-73 (hex) RS Automation Co., Ltd - 000F73 (base 16) RS Automation Co., Ltd - 447-6, Gongse-Dong , Giheung-Gu - Youngin-City Gyeonggi-Do 449-902 - KOREA, REPUBLIC OF - - 00-0F-74 (hex) Qamcom Technology AB - 000F74 (base 16) Qamcom Technology AB - Gruvgatan 8 - SE-421 30 - Vastra Frolunda - SWEDEN - - 00-0F-75 (hex) First Silicon Solutions - 000F75 (base 16) First Silicon Solutions - 13939 Forest Lane - Larkspur CO 80118 - UNITED STATES - - 00-0F-76 (hex) Digital Keystone, Inc. - 000F76 (base 16) Digital Keystone, Inc. - 1975 El Camino Real - #306 - Mountain View CA 94040 - UNITED STATES - - 00-0F-77 (hex) DENTUM CO.,LTD - 000F77 (base 16) DENTUM CO.,LTD - Wookyung B/D 602 #678-6 - Deungchon-Dong ,Kangseo-Gu - Seoul 157-030 - KOREA, REPUBLIC OF - - 00-0F-78 (hex) Datacap Systems Inc - 000F78 (base 16) Datacap Systems Inc - 100 New Britain Blvd - Chalfont PA 18914 - UNITED STATES - - 00-0F-79 (hex) Bluetooth Interest Group Inc. - 000F79 (base 16) Bluetooth Interest Group Inc. - 4F, No. 9, Alley 2, Lane 35, Ji-Hu Rd. - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0F-7A (hex) BeiJing NuQX Technology CO.,LTD - 000F7A (base 16) BeiJing NuQX Technology CO.,LTD - Room 812,8F Tower B,YinWang Center, No.113,Zhi Chun Road, - HaiDian District - Beijing 100086 - CHINA - - 00-0F-7B (hex) Arce Sistemas, S.A. - 000F7B (base 16) Arce Sistemas, S.A. - C/Padre Larramendi, 3 - 2º - Bilbao Vizcaya 48012 - SPAIN - - 00-0F-7C (hex) ACTi Corporation - 000F7C (base 16) ACTi Corporation - 7F., No. 1, Alley 20, Lane 407, Sec. 2, Tiding Blvd., - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0F-7D (hex) Xirrus - 000F7D (base 16) Xirrus - 310 North Westlake Blvd. - Westlake Village CA 91362 - UNITED STATES - - 00-0F-7E (hex) Ablerex Electronics Co., LTD - 000F7E (base 16) Ablerex Electronics Co., LTD - 1F, No.3 Lane 7, Paokao Rd. - Hsintien Taipei Hsien 23114 - TAIWAN, PROVINCE OF CHINA - - 00-0F-7F (hex) UBSTORAGE Co.,Ltd. - 000F7F (base 16) UBSTORAGE Co.,Ltd. - #A-108, Seoul_Sanup_Jiwon_Center - 647-26, Deungchong-dong - Ganseo-gu Seoul 157-840 - KOREA, REPUBLIC OF - - 00-0F-80 (hex) Trinity Security Systems,Inc. - 000F80 (base 16) Trinity Security Systems,Inc. - Alte Building Higashi Kanda 8F - 1-7-8 Higashikanda - Chiyoda-ku Tokyo 101-0031 - JAPAN - - 00-0F-81 (hex) PAL Pacific Inc. - 000F81 (base 16) PAL Pacific Inc. - PO Box 2187 - Palm Springs CA 92263 - UNITED STATES - - 00-0F-82 (hex) Mortara Instrument, Inc. - 000F82 (base 16) Mortara Instrument, Inc. - 7865 N. 86th St. - Milwaukee WI 53224 - UNITED STATES - - 00-0F-83 (hex) Brainium Technologies Inc. - 000F83 (base 16) Brainium Technologies Inc. - #201 - 11491 Kingston Street - Maple Ridge BC V2X 0Y6 - CANADA - - 00-0F-84 (hex) Astute Networks, Inc. - 000F84 (base 16) Astute Networks, Inc. - 15015 Ave of Science - #150 - San Diego CA 92128 - UNITED STATES - - 00-0F-85 (hex) ADDO-Japan Corporation - 000F85 (base 16) ADDO-Japan Corporation - Shin Edobashi Bldg. 4F, 8-6 Nihombashi Kobuna-cho - Chuo-ku Tokyo 103-0024 - JAPAN - - 00-0F-86 (hex) Research In Motion Limited - 000F86 (base 16) Research In Motion Limited - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 00-0F-87 (hex) Maxcess International - 000F87 (base 16) Maxcess International - 222 W. Memorial Road - Oklahoma City OK 73114 - UNITED STATES - - 00-0F-88 (hex) AMETEK, Inc. - 000F88 (base 16) AMETEK, Inc. - 150 Freeport Road - Pittsburgh PA 15238 - UNITED STATES - - 00-0F-89 (hex) Winnertec System Co., Ltd. - 000F89 (base 16) Winnertec System Co., Ltd. - #405, 4th Floor. Ace-Techno Tower III, 197-48, - Kuro 3-Dong, Kuro-Ku. - Seoul 152-766 - KOREA, REPUBLIC OF - - 00-0F-8A (hex) WideView - 000F8A (base 16) WideView - F. 6, No. 8, Wu-chuan 2 Rd, Hsin-Chuang City - Taipei Country 242 - TAIWAN, PROVINCE OF CHINA - - 00-0F-8B (hex) Orion MultiSystems Inc - 000F8B (base 16) Orion MultiSystems Inc - 3375 Scott Blvd Suite 338 - Santa Clara CA 95054 - UNITED STATES - - 00-0F-8C (hex) Gigawavetech Pte Ltd - 000F8C (base 16) Gigawavetech Pte Ltd - 1 Jalan Kilang Timor - #07-02 Pacific Tech Centre - 159303 - SINGAPORE - - 00-0F-8D (hex) FAST TV-Server AG - 000F8D (base 16) FAST TV-Server AG - Ruedesheimerstraße 11-13 - Munich Germany 80686 - GERMANY - - 00-0F-8E (hex) DONGYANG TELECOM CO.,LTD. - 000F8E (base 16) DONGYANG TELECOM CO.,LTD. - 642-7, DEUNGCHON-DONG, KANGSEO-GU - SEOUL KANGSE-GU 157-841 - KOREA, REPUBLIC OF - - 00-0F-8F (hex) CISCO SYSTEMS, INC. - 000F8F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-90 (hex) CISCO SYSTEMS, INC. - 000F90 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-91 (hex) Aerotelecom Co.,Ltd. - 000F91 (base 16) Aerotelecom Co.,Ltd. - 195-58 Anyang 7 Dong - Anyang Kyunggi 430-817 - KOREA, REPUBLIC OF - - 00-0F-92 (hex) Microhard Systems Inc. - 000F92 (base 16) Microhard Systems Inc. - #17, 2135-32Ave NE - Calgary AB T2E6Z3 - CANADA - - 00-0F-93 (hex) Landis+Gyr Ltd. - 000F93 (base 16) Landis+Gyr Ltd. - Feldstrasse 1 - Zug CH-6301 - SWITZERLAND - - 00-0F-94 (hex) Genexis BV - 000F94 (base 16) Genexis BV - Lodewijkstraat 1A - 5652 AC - Eindhoven - NETHERLANDS - - 00-0F-95 (hex) ELECOM Co.,LTD Laneed Division - 000F95 (base 16) ELECOM Co.,LTD Laneed Division - 8F Kanda-Muromachi Bldg. - 1 Kanda-Ogawamachi 1 Chome, - Chiyoda-Ku, Tokyo. 101-0052 - JAPAN - - 00-0F-96 (hex) Telco Systems, Inc. - 000F96 (base 16) Telco Systems, Inc. - 15 Berkshire Road - Mansfield MA 02048 - UNITED STATES - - 00-0F-97 (hex) Avanex Corporation - 000F97 (base 16) Avanex Corporation - 40919 Encyclopedia Circle - Fremont CA 94538 - UNITED STATES - - 00-0F-98 (hex) Avamax Co. Ltd. - 000F98 (base 16) Avamax Co. Ltd. - B1, No. 51, Section 2, ChongQing S. Rd. - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-0F-99 (hex) APAC opto Electronics Inc. - 000F99 (base 16) APAC opto Electronics Inc. - 3 Tzu Chiang Road, Hsinchu Industrial Park - Hukow, Hsinchu Hsien 303 - TAIWAN, PROVINCE OF CHINA - - 00-0F-9A (hex) Synchrony, Inc. - 000F9A (base 16) Synchrony, Inc. - 6410 Commonwealth Drive - Roanoke VA 24018 - UNITED STATES - - 00-0F-9B (hex) Ross Video Limited - 000F9B (base 16) Ross Video Limited - 8 John Street - PO Box 220 - Iroquois Ontario K0E 1K0 - CANADA - - 00-0F-9C (hex) Panduit Corp - 000F9C (base 16) Panduit Corp - 17301 Ridgeland Ave - Tinley Park Illinois 60477 - UNITED STATES - - 00-0F-9D (hex) DisplayLink (UK) Ltd - 000F9D (base 16) DisplayLink (UK) Ltd - Mount Pleasant House - Mount Pleasant - Cambridge Cambridgeshire CB3 0RN - UNITED KINGDOM - - 00-0F-9E (hex) Murrelektronik GmbH - 000F9E (base 16) Murrelektronik GmbH - Falkenstraße 3 - Oppenweiler Baden-Württemberg 71570 - GERMANY - - 00-0F-9F (hex) ARRIS Group, Inc. - 000F9F (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-0F-A0 (hex) CANON KOREA BUSINESS SOLUTIONS INC. - 000FA0 (base 16) CANON KOREA BUSINESS SOLUTIONS INC. - 736 Wonsi-Dong - Ansan-si Kyunggi-do 425-090 - KOREA, REPUBLIC OF - - 00-0F-A1 (hex) Gigabit Systems Inc. - 000FA1 (base 16) Gigabit Systems Inc. - Fuyoh Video Building 3F - 7-25 Higashi-Kibougaoka, Asahi-Ku - Yokohama Kanagawa 241-0826 - JAPAN - - 00-0F-A2 (hex) 2xWireless - 000FA2 (base 16) 2xWireless - 1065 Maurader St - Chico CA 95973 - UNITED STATES - - 00-0F-A3 (hex) Alpha Networks Inc. - 000FA3 (base 16) Alpha Networks Inc. - No.8 Li-shing 7th Rd.,Science-based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0F-A4 (hex) Sprecher Automation GmbH - 000FA4 (base 16) Sprecher Automation GmbH - Franckstrasse 51 - Linz Oberösterreich 4018 - AUSTRIA - - 00-0F-A5 (hex) BWA Technology GmbH - 000FA5 (base 16) BWA Technology GmbH - Johann-Krane-Weg 21 - Muenster 48149 - GERMANY - - 00-0F-A6 (hex) S2 Security Corporation - 000FA6 (base 16) S2 Security Corporation - 6 Abbott Road - Wellesley MA 02481 - UNITED STATES - - 00-0F-A7 (hex) Raptor Networks Technology - 000FA7 (base 16) Raptor Networks Technology - 65 Enterprise Road - Aliso Viejo CA 92656 - UNITED STATES - - 00-0F-A8 (hex) Photometrics, Inc. - 000FA8 (base 16) Photometrics, Inc. - 3440 E Britannia Drive - Tucson AZ 85706-5006 - UNITED STATES - - 00-0F-A9 (hex) PC Fabrik - 000FA9 (base 16) PC Fabrik - Buchenstrasse 13-15 - Dresden Sachsen 01097 - GERMANY - - 00-0F-AA (hex) Nexus Technologies - 000FAA (base 16) Nexus Technologies - 10 National Ave. - Fletcher NC 28732 - UNITED STATES - - 00-0F-AB (hex) Kyushu Electronics Systems Inc. - 000FAB (base 16) Kyushu Electronics Systems Inc. - 3-3, Kongo 2-Chome, Yahatanishi Ward - Kitakyushu City Fukuoka Pref. 807-1263 - JAPAN - - 00-0F-AC (hex) IEEE 802.11 - 000FAC (base 16) IEEE 802.11 - 4125 Highlander Parkway - Richfield Ohio 44286 - UNITED STATES - - 00-0F-AD (hex) FMN communications GmbH - 000FAD (base 16) FMN communications GmbH - Grimmelallee 4 - Nordhausen Thüringen 99734 - GERMANY - - 00-0F-AE (hex) E2O Communications - 000FAE (base 16) E2O Communications - 52 Serangoon North Ave 4 - #06-02 Ever Tech Building - 555853 - SINGAPORE - - 00-0F-AF (hex) Dialog Inc. - 000FAF (base 16) Dialog Inc. - 1-47-9 - Higashiikebukuro - Toshima-ku Tokyo 1700013 - JAPAN - - 00-0F-B0 (hex) Compal Electronics,INC. - 000FB0 (base 16) Compal Electronics,INC. - 581 Juikuang Road,Neihu, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0F-B1 (hex) Cognio Inc. - 000FB1 (base 16) Cognio Inc. - 101 Orchard Ridge Drive - Suite 350 - Gaithersburg MD 20878 - UNITED STATES - - 00-0F-B2 (hex) Broadband Pacenet (India) Pvt. Ltd. - 000FB2 (base 16) Broadband Pacenet (India) Pvt. Ltd. - 7-B, Shah Industrial Estate, Off Veera Desai Road - Andheri West - Mumbai Maharashtra 400 053 - INDIA - - 00-0F-B3 (hex) Actiontec Electronics, Inc - 000FB3 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94086 - UNITED STATES - - 00-0F-B4 (hex) Timespace Technology - 000FB4 (base 16) Timespace Technology - Blackstone Road - Huntingdon Cambridgeshire PE29 6TT - UNITED KINGDOM - - 00-0F-B5 (hex) NETGEAR Inc - 000FB5 (base 16) NETGEAR Inc - 4500 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-0F-B6 (hex) Europlex Technologies - 000FB6 (base 16) Europlex Technologies - Clonshaugh Business & Tech. Park - Clonshaugh Dublin 17 - IRELAND - - 00-0F-B7 (hex) Cavium Networks - 000FB7 (base 16) Cavium Networks - 2610 Augustine Drive - Santa Clara California 95054 - UNITED STATES - - 00-0F-B8 (hex) CallURL Inc. - 000FB8 (base 16) CallURL Inc. - 3F-11, No. 508 Sec. 5, Chung-Hsiao E. Rd. - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-0F-B9 (hex) Adaptive Instruments - 000FB9 (base 16) Adaptive Instruments - 577 Main Street - Hudson MA 01749 - UNITED STATES - - 00-0F-BA (hex) Tevebox AB - 000FBA (base 16) Tevebox AB - Berglinds vag 13 - warmdo S-13900 - SWEDEN - - 00-0F-BB (hex) Nokia Siemens Networks GmbH & Co. KG. - 000FBB (base 16) Nokia Siemens Networks GmbH & Co. KG. - Werner-von-Siemens Straße 2-6 - Bruchsal Baden-Württemberg 76646 - GERMANY - - 00-0F-BC (hex) Onkey Technologies, Inc. - 000FBC (base 16) Onkey Technologies, Inc. - 780 Montague Expressway, Inc. - Suite #306 - San Jose CA 95131 - UNITED STATES - - 00-0F-BD (hex) MRV Communications (Networks) LTD - 000FBD (base 16) MRV Communications (Networks) LTD - P.O Box 614 - Yokneam 20692 - ISRAEL - - 00-0F-BE (hex) e-w/you Inc. - 000FBE (base 16) e-w/you Inc. - 3F FINE Bldg. 6-17-17 - Minamiooi, - Shinagawa-ku, Tokyo 140-0013 - JAPAN - - 00-0F-BF (hex) DGT Sp. z o.o. - 000FBF (base 16) DGT Sp. z o.o. - ul. Jaskowa Dolina 15 - Gdansk 80-252 - POLAND - - 00-0F-C0 (hex) DELCOMp - 000FC0 (base 16) DELCOMp - Technologielaan 3 - Leuven B-3000 - BELGIUM - - 00-0F-C1 (hex) WAVE Corporation - 000FC1 (base 16) WAVE Corporation - 3-25-5 Chidori - Ohta-ku Tokyo 146-0083 - JAPAN - - 00-0F-C2 (hex) Uniwell Corporation - 000FC2 (base 16) Uniwell Corporation - 5-25, 3-chome, Tenma, Kita-ku - Osaka 530-0043 - JAPAN - - 00-0F-C3 (hex) PalmPalm Technology, Inc. - 000FC3 (base 16) PalmPalm Technology, Inc. - Samsung-dong 156-3, Gangnam-gu - Seoul 135-091 - KOREA, REPUBLIC OF - - 00-0F-C4 (hex) NST co.,LTD. - 000FC4 (base 16) NST co.,LTD. - 4-3-1 SHINMIYAKODA - HAMAMATSU SHIZUOKA 431-2103 - JAPAN - - 00-0F-C5 (hex) KeyMed Ltd - 000FC5 (base 16) KeyMed Ltd - KeyMed House - Stock Road - Southend on Sea Essex SS2 5QH - UNITED KINGDOM - - 00-0F-C6 (hex) Eurocom Industries A/S - 000FC6 (base 16) Eurocom Industries A/S - porsvej 2 - Aalborg NV DK-9200 - DENMARK - - 00-0F-C7 (hex) Dionica R&D Ltd. - 000FC7 (base 16) Dionica R&D Ltd. - Bologna Centre, F11 - Mosta Technopark - Mosta MST13 - MALTA - - 00-0F-C8 (hex) Chantry Networks - 000FC8 (base 16) Chantry Networks - 1900 Minnesota Court - Suite 125 - Mississauga Ontario L5N 3C9 - CANADA - - 00-0F-C9 (hex) Allnet GmbH - 000FC9 (base 16) Allnet GmbH - Maistraße 2 - Germering Bavaria 82110 - GERMANY - - 00-0F-CA (hex) A-JIN TECHLINE CO, LTD - 000FCA (base 16) A-JIN TECHLINE CO, LTD - 327-35 - Kasan-Dong - Kumchun-Ku Seoul 153-802 - KOREA, REPUBLIC OF - - 00-0F-CB (hex) 3Com Ltd - 000FCB (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-0F-CC (hex) ARRIS Group, Inc. - 000FCC (base 16) ARRIS Group, Inc. - 6450 Sequence Drive6001 Shellmound Street - San Diego CA 92128 - UNITED STATES - - 00-0F-CD (hex) Nortel Networks - 000FCD (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-0F-CE (hex) Kikusui Electronics Corp. - 000FCE (base 16) Kikusui Electronics Corp. - 1-1-3,Higashi yamata - Tsuzuki-ku - Yokohama Kanagawa 224-0023 - JAPAN - - 00-0F-CF (hex) Datawind Research - 000FCF (base 16) Datawind Research - 555 Rene-Levesque West - Suite 1130 - Montreal Quebec H2Z 1B1 - CANADA - - 00-0F-D0 (hex) ASTRI - 000FD0 (base 16) ASTRI - 18/F Tower 6, Gateway, 9 Canton Rd - TST, Kowloon - HONG KONG - - 00-0F-D1 (hex) Applied Wireless Identifications Group, Inc. - 000FD1 (base 16) Applied Wireless Identifications Group, Inc. - 382 Route 59, Section 292 - Monsey New York 10952 - UNITED STATES - - 00-0F-D2 (hex) EWA Technologies, Inc. - 000FD2 (base 16) EWA Technologies, Inc. - 13873 Park Center Road - Herndon VA 20171 - UNITED STATES - - 00-0F-D3 (hex) Digium - 000FD3 (base 16) Digium - 445 Jan Davis Drive NW - Suite 100 - Huntsville AL 35806 - UNITED STATES - - 00-0F-D4 (hex) Soundcraft - 000FD4 (base 16) Soundcraft - Cranborne House - Cranborne Road - Potters Bar Hertfordshire EN6 3JN - UNITED KINGDOM - - 00-0F-D5 (hex) Schwechat - RISE - 000FD5 (base 16) Schwechat - RISE - Am Concorde Park 2A - Schwechat 2320 - AUSTRIA - - 00-0F-D6 (hex) Sarotech Co., Ltd - 000FD6 (base 16) Sarotech Co., Ltd - HanGang Bldg, 1549-7, Seocho-Dong, - Seocho-ku, - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-0F-D7 (hex) Harman Music Group - 000FD7 (base 16) Harman Music Group - 8760 Sandy Parkway - Sandy Utah 84070 - UNITED STATES - - 00-0F-D8 (hex) Force, Inc. - 000FD8 (base 16) Force, Inc. - 825 Park Street - Christiansburg Va 24073 - UNITED STATES - - 00-0F-D9 (hex) FlexDSL Telecommunications AG - 000FD9 (base 16) FlexDSL Telecommunications AG - Haus zum Engel - Altendorf Schwyz 8852 - SWITZERLAND - - 00-0F-DA (hex) YAZAKI CORPORATION - 000FDA (base 16) YAZAKI CORPORATION - 1500 MISHUKU - SUSONO-CITY SHIZUOKA-PREF 410-1194 - JAPAN - - 00-0F-DB (hex) Westell Technologies - 000FDB (base 16) Westell Technologies - 750 N. Commons Dr. - Aurora IL 60504 - UNITED STATES - - 00-0F-DC (hex) Ueda Japan Radio Co., Ltd. - 000FDC (base 16) Ueda Japan Radio Co., Ltd. - Fumiiri 2-10-19 - Ueda city Nagano prefecture 386-8608 - JAPAN - - 00-0F-DD (hex) SORDIN AB - 000FDD (base 16) SORDIN AB - Rorlaggarvagen 8 - Varnamo Smaland S-331 34 - SWEDEN - - 00-0F-DE (hex) Sony Ericsson Mobile Communications AB - 000FDE (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-0F-DF (hex) SOLOMON Technology Corp. - 000FDF (base 16) SOLOMON Technology Corp. - No.42,Sing Zhong Rd.,Nei Hu Dist., - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-0F-E0 (hex) NComputing Co.,Ltd. - 000FE0 (base 16) NComputing Co.,Ltd. - 6th Fl, JEI-Platz B/D - 1423-6, Gwanyang1-Dong, Dongan-Gu - Seoul Gasan-dong Geumcheon-Gu 459-11 - KOREA, REPUBLIC OF - - 00-0F-E1 (hex) ID DIGITAL CORPORATION - 000FE1 (base 16) ID DIGITAL CORPORATION - 6th Fl., Mirae Bldg., 271-1, Seohyun-dong, Bundang-ku, Sungnam-si, Keongki-do, South Korea - Sungnam-Si Keongki-do 463-050 - KOREA, REPUBLIC OF - - 00-0F-E2 (hex) Hangzhou H3C Technologies Co., Ltd. - 000FE2 (base 16) Hangzhou H3C Technologies Co., Ltd. - Oriental Electronic Bld., NO.2,Chuangye Road - Shang-Di Informaiton Industry Base, - Hai-Dian District Beijing 100085 - CHINA - - 00-0F-E3 (hex) Damm Cellular Systems A/S - 000FE3 (base 16) Damm Cellular Systems A/S - Moellegade 68 - Soenderborg DK-6400 - DENMARK - - 00-0F-E4 (hex) Pantech Co.,Ltd - 000FE4 (base 16) Pantech Co.,Ltd - Shinsong B/D 3F, 25-12, - Yeouido-Dong, - Youngdeungpo-GU Seoul 150-711 - KOREA, REPUBLIC OF - - 00-0F-E5 (hex) MERCURY SECURITY CORPORATION - 000FE5 (base 16) MERCURY SECURITY CORPORATION - 2355 MIRA MAR AVE. - LONG BEACH CA 90815 - UNITED STATES - - 00-0F-E6 (hex) MBTech Systems, Inc. - 000FE6 (base 16) MBTech Systems, Inc. - 412 1st Ave SE - Suite 100 - Cullman Alabama 35055 - UNITED STATES - - 00-0F-E7 (hex) Lutron Electronics Co., Inc. - 000FE7 (base 16) Lutron Electronics Co., Inc. - 7200 Suter Rd. - Coopersburg PA 18036-1299 - UNITED STATES - - 00-0F-E8 (hex) Lobos, Inc. - 000FE8 (base 16) Lobos, Inc. - U&T Bldg 3F, 1-2-3 Sarugaku-cho, Chiyoda-ku, - Tokyo 101-0064 - JAPAN - - 00-0F-E9 (hex) GW TECHNOLOGIES CO.,LTD. - 000FE9 (base 16) GW TECHNOLOGIES CO.,LTD. - No.38 Shangdi Xilu,Haidian District - Beijing 100085 - CHINA - - 00-0F-EA (hex) Giga-Byte Technology Co.,LTD. - 000FEA (base 16) Giga-Byte Technology Co.,LTD. - No.215,Nan-Ping Road,Ping-Jen City, - Ping-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 00-0F-EB (hex) Cylon Controls - 000FEB (base 16) Cylon Controls - Clonshaugh Industrial Estate - Clonshaugh - Dublin 17 - IRELAND - - 00-0F-EC (hex) ARKUS Inc. - 000FEC (base 16) ARKUS Inc. - 3-8 Noda, Kitaa-Ku - Okayama 700-0971 - JAPAN - - 00-0F-ED (hex) Anam Electronics Co., Ltd - 000FED (base 16) Anam Electronics Co., Ltd - 645 Sungkok-dong - Danwon-gu - Ansan-city Kyungki-do 425-834 - KOREA, REPUBLIC OF - - 00-0F-EE (hex) XTec, Incorporated - 000FEE (base 16) XTec, Incorporated - 5775 Blue Lagoon Drive - Suite 280 - Miami Florida 33126 - UNITED STATES - - 00-0F-EF (hex) Thales e-Transactions GmbH - 000FEF (base 16) Thales e-Transactions GmbH - Konrad-Zuse-Straße 19-21 - Bad Hersfeld Hessen 36251 - GERMANY - - 00-0F-F0 (hex) Sunray Co. Ltd. - 000FF0 (base 16) Sunray Co. Ltd. - Osawa2-5-5 Mitaka - Tokyo 181-0015 - JAPAN - - 00-0F-F1 (hex) nex-G Systems Pte.Ltd - 000FF1 (base 16) nex-G Systems Pte.Ltd - 25 Kallang Ave - #07-05 - 339416 - SINGAPORE - - 00-0F-F2 (hex) Loud Technologies Inc. - 000FF2 (base 16) Loud Technologies Inc. - 16220 Wood-Red Rd. NE - Woodinville WA 98072 - UNITED STATES - - 00-0F-F3 (hex) Jung Myoung Communications&Technology - 000FF3 (base 16) Jung Myoung Communications&Technology - 1th FL., Dong IL Bldg.107 Yangjae-Dong - Seocho-Ku Seoul 137-130 - KOREA, REPUBLIC OF - - 00-0F-F4 (hex) Guntermann & Drunck GmbH - 000FF4 (base 16) Guntermann & Drunck GmbH - Dortmunder Str. 4a - Wilnsdorf NRW 57234 - GERMANY - - 00-0F-F5 (hex) GN&S company - 000FF5 (base 16) GN&S company - 301 Ansan S/W center, 643-7 wongok-dong - Ansan city Gyeonggi-do 425-130 - KOREA, REPUBLIC OF - - 00-0F-F6 (hex) Darfon Electronics Corp. - 000FF6 (base 16) Darfon Electronics Corp. - 31, Lane17, Zihciang N. Road - Gueishan - Taoyuan 333 - TAIWAN, PROVINCE OF CHINA - - 00-0F-F7 (hex) CISCO SYSTEMS, INC. - 000FF7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-F8 (hex) CISCO SYSTEMS, INC. - 000FF8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-0F-F9 (hex) Valcretec, Inc. - 000FF9 (base 16) Valcretec, Inc. - Byucksan Digital Valley II 15F - 481-10, Gasan-Dong, Geumcheon-Gu - Seoul 153-803 - KOREA, REPUBLIC OF - - 00-0F-FA (hex) Optinel Systems, Inc. - 000FFA (base 16) Optinel Systems, Inc. - 6835 Deerpath Rd. - Elkridge MD 21075 - UNITED STATES - - 00-0F-FB (hex) Nippon Denso Industry Co., Ltd. - 000FFB (base 16) Nippon Denso Industry Co., Ltd. - 3-14-19 - Shibaura, Minato-ku Tokyo, 108-8560 - JAPAN - - 00-0F-FC (hex) Merit Li-Lin Ent. - 000FFC (base 16) Merit Li-Lin Ent. - No. 20 Wu-Long 6 Rd. - Wu-Ku Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 00-0F-FD (hex) Glorytek Network Inc. - 000FFD (base 16) Glorytek Network Inc. - 5F.-3, No.16, Sec. 1, Dongda Rd., - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-0F-FE (hex) G-PRO COMPUTER - 000FFE (base 16) G-PRO COMPUTER - first arrange C YingHu industrial estate QingXi country DongGuan city - DongGuan GuangDong 523648 - CHINA - - 00-0F-FF (hex) Control4 - 000FFF (base 16) Control4 - 11734 S. Election Drive - Draper UT 84020 - UNITED STATES - - 00-10-00 (hex) CABLE TELEVISION LABORATORIES, INC. - 001000 (base 16) CABLE TELEVISION LABORATORIES, INC. - 858 Coal Creek Circle - Louisville CO 80027 - UNITED STATES - - 00-10-01 (hex) Citel - 001001 (base 16) Citel - Loughborough Innovation Centre - Epinal Way - Loughborough LE11 3EH - UNITED KINGDOM - - 00-10-02 (hex) ACTIA - 001002 (base 16) ACTIA - 25 CHEMIN DE POUVOURVILLE - 31432 TOULOUSE, CEDEX 04 - FRANCE - - 00-10-03 (hex) IMATRON, INC. - 001003 (base 16) IMATRON, INC. - 389 OYSTER POINT BLVD. - SO. SAN FRANCISCO CA 94080 - UNITED STATES - - 00-10-04 (hex) THE BRANTLEY COILE COMPANY,INC - 001004 (base 16) THE BRANTLEY COILE COMPANY,INC - 545 RESEARCH DRIVE - ATHENS GA 30605 - UNITED STATES - - 00-10-05 (hex) UEC COMMERCIAL - 001005 (base 16) UEC COMMERCIAL - P.O. BOX 54, - MT. EDGECOMBE - 4300 DURBAN - SOUTH AFRICA - - 00-10-06 (hex) Thales Contact Solutions Ltd. - 001006 (base 16) Thales Contact Solutions Ltd. - Tolbar Way - Southampton, SO30 2ZP - UNITED KINGDOM - - 00-10-07 (hex) CISCO SYSTEMS, INC. - 001007 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-08 (hex) VIENNA SYSTEMS CORPORATION - 001008 (base 16) VIENNA SYSTEMS CORPORATION - 6651 FRASERWOOD PLACE - SUITE #250 - RICHMOND, B.C. V6W 1J3 - CANADA - - 00-10-09 (hex) HORO QUARTZ - 001009 (base 16) HORO QUARTZ - Z.I. ROUTE DE NIORT - 85200 - FONTENAY LE COMTE - FRENCH GUIANA - - 00-10-0A (hex) WILLIAMS COMMUNICATIONS GROUP - 00100A (base 16) WILLIAMS COMMUNICATIONS GROUP - ADVANCED TECHNOLOGIES - 111 EAST FIRST - TULSA OK 74103 - UNITED STATES - - 00-10-0B (hex) CISCO SYSTEMS, INC. - 00100B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-0C (hex) ITO CO., LTD. - 00100C (base 16) ITO CO., LTD. - 8-2 MIYANOSHITA-CHO - HIRAKATA-CITY, OSAKA - JAPAN - - 00-10-0D (hex) CISCO SYSTEMS, INC. - 00100D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR.-SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-0E (hex) MICRO LINEAR COPORATION - 00100E (base 16) MICRO LINEAR COPORATION - 2092 CONCOURSE DRIVE - SAN JOSE CA 95131 - UNITED STATES - - 00-10-0F (hex) INDUSTRIAL CPU SYSTEMS - 00100F (base 16) INDUSTRIAL CPU SYSTEMS - 111-D W. DYER ROAD - SANTA ANA CA 92707 - UNITED STATES - - 00-10-10 (hex) INITIO CORPORATION - 001010 (base 16) INITIO CORPORATION - 2188 B DEL FRANCO STREET - SAN JOSE CA 95118 - UNITED STATES - - 00-10-11 (hex) CISCO SYSTEMS, INC. - 001011 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-12 (hex) PROCESSOR SYSTEMS (I) PVT LTD - 001012 (base 16) PROCESSOR SYSTEMS (I) PVT LTD - 24 RICHMOND ROAD - BANGALORE 560 025 - INDIA - - 00-10-13 (hex) Kontron America, Inc. - 001013 (base 16) Kontron America, Inc. - 14118 Stowe Drive - Poway, CA 9206 - UNITED STATES - - 00-10-14 (hex) CISCO SYSTEMS, INC. - 001014 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-15 (hex) OOmon Inc. - 001015 (base 16) OOmon Inc. - PO BOX 8241 - COBURG OR 97408 - UNITED STATES - - 00-10-16 (hex) T.SQWARE - 001016 (base 16) T.SQWARE - 6, PARC ARIANE - IMMEUBLE MERCURE - 78284 GUYANCOURT CEDEX - FRANCE - - 00-10-17 (hex) Bosch Access Systems GmbH - 001017 (base 16) Bosch Access Systems GmbH - Charlottenburger Allee 50 - AACHEN D-52068 - GERMANY - - 00-10-18 (hex) BROADCOM CORPORATION - 001018 (base 16) BROADCOM CORPORATION - 5300 California Ave - IRVINE CA 92617 - UNITED STATES - - 00-10-19 (hex) SIRONA DENTAL SYSTEMS GmbH & Co. KG - 001019 (base 16) SIRONA DENTAL SYSTEMS GmbH & Co. KG - FABRIKSTRASSE 31 - 64625 BENSHEIM - GERMANY - - 00-10-1A (hex) PictureTel Corp. - 00101A (base 16) PictureTel Corp. - 100 MINUTEMAN ROAD, MS641 - ANDOVER MA 01810 - UNITED STATES - - 00-10-1B (hex) CORNET TECHNOLOGY, INC. - 00101B (base 16) CORNET TECHNOLOGY, INC. - 7F-4, NO. 46 CHUNG SHAN N.ROAD - SEC. 2, TAIPEI - TAJIKISTAN - - 00-10-1C (hex) OHM TECHNOLOGIES INTL, LLC - 00101C (base 16) OHM TECHNOLOGIES INTL, LLC - 4 EXECUTIVE CIRCLE, Suite 185 - IRVINE CA 92614 - UNITED STATES - - 00-10-1D (hex) WINBOND ELECTRONICS CORP. - 00101D (base 16) WINBOND ELECTRONICS CORP. - NO. 4, CREATION RD. III - SCIENCE-BASED INDUSTRIAL PARK - HSIN CHU - TAIWAN, PROVINCE OF CHINA - - 00-10-1E (hex) MATSUSHITA ELECTRONIC INSTRUMENTS CORP. - 00101E (base 16) MATSUSHITA ELECTRONIC INSTRUMENTS CORP. - 23-9 KIYOHARA INDUSTRIAL PARK - UTSUNOMIYA Tochigi 321-32 - JAPAN - - 00-10-1F (hex) CISCO SYSTEMS, INC. - 00101F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-20 (hex) Hand Held Products Inc - 001020 (base 16) Hand Held Products Inc - 700 Visions Drive - Skaneateles Falls NY 13153-0208 - UNITED STATES - - 00-10-21 (hex) ENCANTO NETWORKS, INC. - 001021 (base 16) ENCANTO NETWORKS, INC. - 2953 BUNKER HILL LANE - SUITE #400 - SANTA CLARA CA 95054 - UNITED STATES - - 00-10-22 (hex) SatCom Media Corporation - 001022 (base 16) SatCom Media Corporation - 3255-7 SCOTT BLVD. - SANTA CLARA CA 95054 - UNITED STATES - - 00-10-23 (hex) Network Equipment Technologies - 001023 (base 16) Network Equipment Technologies - 6900 Paseo Padre Parkway - Freemont CA 94555-3660 - UNITED STATES - - 00-10-24 (hex) NAGOYA ELECTRIC WORKS CO., LTD - 001024 (base 16) NAGOYA ELECTRIC WORKS CO., LTD - 29-1 SHINODA, MIWA-CHO - AMA-GUN, AICHI 490-12 - JAPAN - - 00-10-25 (hex) Grayhill, Inc - 001025 (base 16) Grayhill, Inc - 561 Hillgrove Ave - LaGrange IL 60525 - UNITED STATES - - 00-10-26 (hex) ACCELERATED NETWORKS, INC. - 001026 (base 16) ACCELERATED NETWORKS, INC. - 31238 VIA COLINAS, UNIT - WESTLAKE VILLAGE CA 91362 - UNITED STATES - - 00-10-27 (hex) L-3 COMMUNICATIONS EAST - 001027 (base 16) L-3 COMMUNICATIONS EAST - ONE FEDERAL STREET - A&E-3ES - CAMDEN NJ 08102 - UNITED STATES - - 00-10-28 (hex) COMPUTER TECHNICA, INC. - 001028 (base 16) COMPUTER TECHNICA, INC. - 3-5-19 HIGASHINAKA HAKATA-KU - FUKUOKA-SI - FUKUOKA 816 - JAPAN - - 00-10-29 (hex) CISCO SYSTEMS, INC. - 001029 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-2A (hex) ZF MICROSYSTEMS, INC. - 00102A (base 16) ZF MICROSYSTEMS, INC. - 1052 ELWELL COURT - PALO ALTO CA 94303-4307 - UNITED STATES - - 00-10-2B (hex) UMAX DATA SYSTEMS, INC. - 00102B (base 16) UMAX DATA SYSTEMS, INC. - NO. 1-1, R&D ROAD 2 - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-10-2C (hex) Lasat Networks A/S - 00102C (base 16) Lasat Networks A/S - Skalhuse 13 - SK-9240 Nibe - DENMARK - - 00-10-2D (hex) HITACHI SOFTWARE ENGINEERING - 00102D (base 16) HITACHI SOFTWARE ENGINEERING - 5-79, ONOECHO, NAKA-KU - YOKOHAMA 231 - JAPAN - - 00-10-2E (hex) NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD. - 00102E (base 16) NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD. - PLOT NO. 2, COCHIN EXPORT PROCESSING ZO - KAKKANAD, COCHIN 682 030 - INDIA - - 00-10-2F (hex) CISCO SYSTEMS, INC. - 00102F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-30 (hex) EION Inc. - 001030 (base 16) EION Inc. - 320 March Road - Suite 500 - Ottawa ON K2K 2E3 - CANADA - - 00-10-31 (hex) OBJECTIVE COMMUNICATIONS, INC. - 001031 (base 16) OBJECTIVE COMMUNICATIONS, INC. - 75 ROCHESTER AVE. - UNIT 1 - PORTSMOUTH NH 03801 - UNITED STATES - - 00-10-32 (hex) ALTA TECHNOLOGY - 001032 (base 16) ALTA TECHNOLOGY - 9500 SOUTH 500 WEST - STE #212 - SANDY UT 84070 - UNITED STATES - - 00-10-33 (hex) ACCESSLAN COMMUNICATIONS, INC. - 001033 (base 16) ACCESSLAN COMMUNICATIONS, INC. - 44 AIRPORT PARKWAY - SAN JOSE CA 95110 - UNITED STATES - - 00-10-34 (hex) GNP Computers - 001034 (base 16) GNP Computers - 555 E.Huntington Drive - Monrovia CA 91016 - UNITED STATES - - 00-10-35 (hex) ELITEGROUP COMPUTER SYSTEMS CO., LTD - 001035 (base 16) ELITEGROUP COMPUTER SYSTEMS CO., LTD - 6F, NO. 88, SEC. 6 - CHUNG SHAN N. RD. - Shih Lin TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-10-36 (hex) INTER-TEL INTEGRATED SYSTEMS - 001036 (base 16) INTER-TEL INTEGRATED SYSTEMS - 7300 W. BOSTON STREET - CHANDLER AZ 85226 - UNITED STATES - - 00-10-37 (hex) CYQ've Technology Co., Ltd. - 001037 (base 16) CYQ've Technology Co., Ltd. - COSMO BLDG. 10F, NO.1-7 - SHINJUKU 1-CHOME - SHINJUKU-KU, TOKYO 160 - JAPAN - - 00-10-38 (hex) MICRO RESEARCH INSTITUTE, INC. - 001038 (base 16) MICRO RESEARCH INSTITUTE, INC. - 2F, 2L-2-5 MINAMI SHINAGAWA - SHINAGAWA-KU - TOKYO - JAPAN - - 00-10-39 (hex) Vectron Systems AG - 001039 (base 16) Vectron Systems AG - Willy-Brandt-Weg 41 - 48155 Muenster - GERMANY - - 00-10-3A (hex) DIAMOND NETWORK TECH - 00103A (base 16) DIAMOND NETWORK TECH - P.O. BOX 84525 - GREENSIDE 2034 - SOUTH AFRICA - - 00-10-3B (hex) HIPPI NETWORKING FORUM - 00103B (base 16) HIPPI NETWORKING FORUM - PO BOX 10173 - ALBUQUERQUE NM 87184-0173 - UNITED STATES - - 00-10-3C (hex) IC ENSEMBLE, INC. - 00103C (base 16) IC ENSEMBLE, INC. - 3255-2 SCOTT BLVD.--STE.#105 - SANTA CLARA CA 95054 - UNITED STATES - - 00-10-3D (hex) PHASECOM, LTD. - 00103D (base 16) PHASECOM, LTD. - P.O. BOX 45017 - JERUSALEM 91450 - ISRAEL - - 00-10-3E (hex) NETSCHOOLS CORPORATION - 00103E (base 16) NETSCHOOLS CORPORATION - 2003 LANDINGS DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-10-3F (hex) TOLLGRADE COMMUNICATIONS, INC. - 00103F (base 16) TOLLGRADE COMMUNICATIONS, INC. - 493 NIXON ROAD - CHESWICK PA 15024 - UNITED STATES - - 00-10-40 (hex) INTERMEC CORPORATION - 001040 (base 16) INTERMEC CORPORATION - 6001 36TH AVE WEST - P.O. BOX 4280 - EVERETT WA 98203-9280 - UNITED STATES - - 00-10-41 (hex) BRISTOL BABCOCK, INC. - 001041 (base 16) BRISTOL BABCOCK, INC. - 1100 BUCKINGHAM STREET - WATERTOWN CT 06795 - UNITED STATES - - 00-10-42 (hex) Alacritech, Inc. - 001042 (base 16) Alacritech, Inc. - 1995 N. First Street - Suite 200 - San Jose CA 95112 - UNITED STATES - - 00-10-43 (hex) A2 CORPORATION - 001043 (base 16) A2 CORPORATION - 6-14-11 YUTAKA-CHO - SHINAGAWA-KU - TOKYO - JAPAN - - 00-10-44 (hex) InnoLabs Corporation - 001044 (base 16) InnoLabs Corporation - 2F-4, NO. 16, LANE 609, CHUNG-HSIN RD. - SEC. 5 SAN-CHUNG CITY - Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-10-45 (hex) Nortel Networks - 001045 (base 16) Nortel Networks - OPTera Solutions Division - 340 Terry Fox Drive - Kanata Ontario K2K-2X3 - CANADA - - 00-10-46 (hex) ALCORN MCBRIDE INC. - 001046 (base 16) ALCORN MCBRIDE INC. - 3300 S. HIAWASSEE #105 - ORLANDO FL 32835 - UNITED STATES - - 00-10-47 (hex) ECHO ELETRIC CO. LTD. - 001047 (base 16) ECHO ELETRIC CO. LTD. - NO.1800 ICHIGAO CHO - MIDORI WARD - YOKOHAMA CITY 225 - JAPAN - - 00-10-48 (hex) HTRC AUTOMATION, INC. - 001048 (base 16) HTRC AUTOMATION, INC. - 285 LAVAL STREET - BROMPTONVILLE - QUEBEC J0B 1H0 - CANADA - - 00-10-49 (hex) ShoreTel, Inc - 001049 (base 16) ShoreTel, Inc - 960 Stewart Drive - Sunnyvale CA 94085 - UNITED STATES - - 00-10-4A (hex) The Parvus Corporation - 00104A (base 16) The Parvus Corporation - 3222 S Washington St. - Salt Lake City UT 84115 - UNITED STATES - - 00-10-4B (hex) 3COM CORPORATION - 00104B (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - MAILSTOP: 4220 - SANTA CLARA CA 95052 - UNITED STATES - - 00-10-4C (hex) Teledyne LeCroy, Inc - 00104C (base 16) Teledyne LeCroy, Inc - 3385 Scott Blvd. - Santa Clara CA 95054 - UNITED STATES - - 00-10-4D (hex) SURTEC INDUSTRIES, INC. - 00104D (base 16) SURTEC INDUSTRIES, INC. - NO.11, ALLEY 16, LANE 337 - TA-TUNG ROAD SEC.1, SHI-CHIH - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-10-4E (hex) CEOLOGIC - 00104E (base 16) CEOLOGIC - ZA DE PISSALOOP - RUE EDOUARD BRANLY - 78192 TRAPPES - FRANCE - - 00-10-4F (hex) Oracle Corporation - 00104F (base 16) Oracle Corporation - 17 Network Circle - Building 17, UMPK17-131 - Menlo Park CA 95025 - UNITED STATES - - 00-10-50 (hex) RION CO., LTD. - 001050 (base 16) RION CO., LTD. - 3-20-41 HIGASHIMOTOMACHI - KOKUBUNJI, TOKYO 185 - JAPAN - - 00-10-51 (hex) CMICRO CORPORATION - 001051 (base 16) CMICRO CORPORATION - 17-20-2 KAMINO-CHO - TAKAMATSU-SHI, KAGAWA 761 - JAPAN - - 00-10-52 (hex) METTLER-TOLEDO (ALBSTADT) GMBH - 001052 (base 16) METTLER-TOLEDO (ALBSTADT) GMBH - P.O. BOX 2 50 - D-72423 ALBSTADT - GERMANY - - 00-10-53 (hex) COMPUTER TECHNOLOGY CORP. - 001053 (base 16) COMPUTER TECHNOLOGY CORP. - 50 W. TECHNECENTER DRIVE - MILFORD OH 45150 - UNITED STATES - - 00-10-54 (hex) CISCO SYSTEMS, INC. - 001054 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-55 (hex) FUJITSU MICROELECTRONICS, INC. - 001055 (base 16) FUJITSU MICROELECTRONICS, INC. - 3545 NORTH FIRST STREET - SAN JOSE CA 95134-1806 - UNITED STATES - - 00-10-56 (hex) SODICK CO., LTD. - 001056 (base 16) SODICK CO., LTD. - 3-12-1 NAKAMACHIDAI - TSUZUKI-KU, YOKOHAMA KANAGAWA 224 - JAPAN - - 00-10-57 (hex) Rebel.com, Inc. - 001057 (base 16) Rebel.com, Inc. - 150 ISABELLA STREET--STE. 1000 - OTTAWA, ONTARIO K1S 1V7 - CANADA - - 00-10-58 (hex) ArrowPoint Communications - 001058 (base 16) ArrowPoint Communications - 235 LITTLETON ROAD - WESTFORD MA 01886 - UNITED STATES - - 00-10-59 (hex) DIABLO RESEARCH CO. LLC - 001059 (base 16) DIABLO RESEARCH CO. LLC - 825 STEWART DRIVE - SUNNYVALE CA 94086 - UNITED STATES - - 00-10-5A (hex) 3COM CORPORATION - 00105A (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - MAILSTOP: 4220 - SANTA CLARA CA 95052 - UNITED STATES - - 00-10-5B (hex) NET INSIGHT AB - 00105B (base 16) NET INSIGHT AB - Västberga Allé 9 - SE-1260 30 Hägersten - SWEDEN - - 00-10-5C (hex) QUANTUM DESIGNS (H.K.) LTD. - 00105C (base 16) QUANTUM DESIGNS (H.K.) LTD. - 5/F., SOMERSET HOUSE, TAIKOO PLACE - 979 KING'S ROAD, - QUARRY BAY - HONG KONG - - 00-10-5D (hex) Draeger Medical - 00105D (base 16) Draeger Medical - Moislinger Allee 53-55 - Luebeck D-23542 - GERMANY - - 00-10-5E (hex) Spirent plc, Service Assurance Broadband - 00105E (base 16) Spirent plc, Service Assurance Broadband - 5280 Corporate Dr - Suite A - Ballenger Creek MD 21703 - UNITED STATES - - 00-10-5F (hex) ZODIAC DATA SYSTEMS - 00105F (base 16) ZODIAC DATA SYSTEMS - 5 Av Des Andes - Les Ulis 91940 - FRANCE - - 00-10-60 (hex) BILLIONTON SYSTEMS, INC. - 001060 (base 16) BILLIONTON SYSTEMS, INC. - 3F-1, NO. 8, LANE 99 - PU-DING RD. - HSIN-CHU - TAIWAN, PROVINCE OF CHINA - - 00-10-61 (hex) HOSTLINK CORP. - 001061 (base 16) HOSTLINK CORP. - 10F-1, NO. 181 - SEC.1, TA-TUNG RD. - HSI-CHIH, TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-10-62 (hex) NX SERVER, ILNC. - 001062 (base 16) NX SERVER, ILNC. - 5401 E. LA PALMA AVE. - ANAHEIM CA 92807 - UNITED STATES - - 00-10-63 (hex) STARGUIDE DIGITAL NETWORKS - 001063 (base 16) STARGUIDE DIGITAL NETWORKS - 5754 PACIFIC CENTER BLVD. - SAN DIEGO CA 92121 - UNITED STATES - - 00-10-64 (hex) DNPG, LLC - 001064 (base 16) DNPG, LLC - 20 North Wentworth Avenue - Londonderry NH 03053 - UNITED STATES - - 00-10-65 (hex) RADYNE CORPORATION - 001065 (base 16) RADYNE CORPORATION - 5225 S. 37TH STREET - PHOENIX AZ 85040 - UNITED STATES - - 00-10-66 (hex) ADVANCED CONTROL SYSTEMS, INC. - 001066 (base 16) ADVANCED CONTROL SYSTEMS, INC. - 2755 NORTHWOODS PARKWAY - NORCROSS GA 30071 - UNITED STATES - - 00-10-67 (hex) Ericsson - 001067 (base 16) Ericsson - 250 Holger Way - SAN JOSE CA 95134 - UNITED STATES - - 00-10-68 (hex) COMOS TELECOM - 001068 (base 16) COMOS TELECOM - SAEHAN B/D/, 27-1 SUPYO-DONG - CHUNG-GU, SEOUL 100-230 - KOREA, REPUBLIC OF - - 00-10-69 (hex) HELIOSS COMMUNICATIONS, INC. - 001069 (base 16) HELIOSS COMMUNICATIONS, INC. - 391 TOTTEM POND RD.- STE#303 - WALTHAM MA 02154 - UNITED STATES - - 00-10-6A (hex) DIGITAL MICROWAVE CORPORATION - 00106A (base 16) DIGITAL MICROWAVE CORPORATION - 170 ROSE ORCHARD WAY - SAN JOSE CA 95134 - UNITED STATES - - 00-10-6B (hex) SONUS NETWORKS, INC. - 00106B (base 16) SONUS NETWORKS, INC. - 5 CARLISLE ROAD - WESTFORD MA 01886 - UNITED STATES - - 00-10-6C (hex) EDNT GmbH - 00106C (base 16) EDNT GmbH - Werner-von-Siemens-Str. 7 - 64625 Bensheim - GERMANY - - 00-10-6D (hex) Axxcelera Broadband Wireless - 00106D (base 16) Axxcelera Broadband Wireless - 1600 East Parham Road - Richmond VA 23228 - UNITED STATES - - 00-10-6E (hex) TADIRAN COM. LTD. - 00106E (base 16) TADIRAN COM. LTD. - 26 HASHOFTIM ST. - HOLON 58102 - ISRAEL - - 00-10-6F (hex) TRENTON TECHNOLOGY INC. - 00106F (base 16) TRENTON TECHNOLOGY INC. - 2350 CENTENNIAL DRIVE - GAINESVILLE GA 30504 - UNITED STATES - - 00-10-70 (hex) CARADON TREND LTD. - 001070 (base 16) CARADON TREND LTD. - P.O. BOX 34, HORSHAM - WEST SUSSEX, RH12 2YF ENGLAND - UNITED KINGDOM - - 00-10-71 (hex) ADVANET INC. - 001071 (base 16) ADVANET INC. - 3-20-8 NODA - OKAYAMI 700 - JAPAN - - 00-10-72 (hex) GVN TECHNOLOGIES, INC. - 001072 (base 16) GVN TECHNOLOGIES, INC. - 8200 BRYAN DAIRY ROAD - SUITE #100 - LARGO FL 33777 - UNITED STATES - - 00-10-73 (hex) Technobox, Inc. - 001073 (base 16) Technobox, Inc. - 140 Mount Holly Bypass - Unit 1 - Lumberton NJ 08048 - UNITED STATES - - 00-10-74 (hex) ATEN INTERNATIONAL CO., LTD. - 001074 (base 16) ATEN INTERNATIONAL CO., LTD. - 12F, NO.101, SUNG CHIANG RD. - TAIPEI, 10428 - TAIWAN, PROVINCE OF CHINA - - 00-10-75 (hex) Segate Technology LLC - 001075 (base 16) Segate Technology LLC - 10200 S De Anza Blvd - Cupertino CA 95014 - UNITED STATES - - 00-10-76 (hex) EUREM GmbH - 001076 (base 16) EUREM GmbH - JULICHER STR. 338B - D-52070 AACHEN - GERMANY - - 00-10-77 (hex) SAF DRIVE SYSTEMS, LTD. - 001077 (base 16) SAF DRIVE SYSTEMS, LTD. - 88 ARDELT AVE. - KITCHENER, ONTARIO N2C 2C9 - CANADA - - 00-10-78 (hex) NUERA COMMUNICATIONS, INC. - 001078 (base 16) NUERA COMMUNICATIONS, INC. - 10445 PACIFIC CENTER COURT - SAN DIEGO CA 92121 - UNITED STATES - - 00-10-79 (hex) CISCO SYSTEMS, INC. - 001079 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-7A (hex) AmbiCom, Inc. - 00107A (base 16) AmbiCom, Inc. - 2450 SCOTT BLVD., #305 - SANTA CLARA CA 95050 - UNITED STATES - - 00-10-7B (hex) CISCO SYSTEMS, INC. - 00107B (base 16) CISCO SYSTEMS, INC. - 170 W.TASMAN DR.-SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-7C (hex) P-COM, INC. - 00107C (base 16) P-COM, INC. - 3175 S. WINCHESTER BLVD. - CAMPBELL CA 95008 - UNITED STATES - - 00-10-7D (hex) AURORA COMMUNICATIONS, LTD. - 00107D (base 16) AURORA COMMUNICATIONS, LTD. - P.O. BOX 1942 - MACQUARIE CENTRE, NORTH RYDE - NSW 2113 - AUSTRALIA - - 00-10-7E (hex) BACHMANN ELECTRONIC GmbH - 00107E (base 16) BACHMANN ELECTRONIC GmbH - KREUZAECKERWEG 33 - A 6806 FELDKIRCH - AUSTRIA - - 00-10-7F (hex) CRESTRON ELECTRONICS, INC. - 00107F (base 16) CRESTRON ELECTRONICS, INC. - 101 BROADWAY - CRESSKILL NJ 07626 - UNITED STATES - - 00-10-80 (hex) METAWAVE COMMUNICATIONS - 001080 (base 16) METAWAVE COMMUNICATIONS - 8700 148TH AVENUE N.E. - REDMOND WA 98052 - UNITED STATES - - 00-10-81 (hex) DPS, INC. - 001081 (base 16) DPS, INC. - 4922 EAST YALE AVENUE - FRESNO CA 93727 - UNITED STATES - - 00-10-82 (hex) JNA TELECOMMUNICATIONS LIMITED - 001082 (base 16) JNA TELECOMMUNICATIONS LIMITED - 16 SMITH ST, CHATSWOOD - NSW 2067 - AUSTRALIA - - 00-10-83 (hex) HEWLETT-PACKARD COMPANY - 001083 (base 16) HEWLETT-PACKARD COMPANY - MAIL STOP 42LE - 110000 WOLFE ROAD - CUPERTINO CA 95014 - UNITED STATES - - 00-10-84 (hex) K-BOT COMMUNICATIONS - 001084 (base 16) K-BOT COMMUNICATIONS - P.O. BOX 410 - NORTON MA 02766 - UNITED STATES - - 00-10-85 (hex) POLARIS COMMUNICATIONS, INC. - 001085 (base 16) POLARIS COMMUNICATIONS, INC. - 10200 SW ALLEN BLVD. - BEAVERTON OR 97005 - UNITED STATES - - 00-10-86 (hex) ATTO Technology, Inc. - 001086 (base 16) ATTO Technology, Inc. - 155 Crosspoint Pkwy. - Amherst NY 14068 - UNITED STATES - - 00-10-87 (hex) Xstreamis PLC - 001087 (base 16) Xstreamis PLC - OXFORD SCIENCE PARK - G10. 2 MAGDALEN CENTRE ROBERT ROBINSON - OXFORD 0X4 4GA England - UNITED STATES - - 00-10-88 (hex) AMERICAN NETWORKS INC. - 001088 (base 16) AMERICAN NETWORKS INC. - 6800 ORANGETHORPE AVE. #A - BUENA PARK CA 90620 - UNITED STATES - - 00-10-89 (hex) WebSonic - 001089 (base 16) WebSonic - 3466 EDWARD AVE. - SANTA CLARA CA 95054 - UNITED STATES - - 00-10-8A (hex) TeraLogic, Inc. - 00108A (base 16) TeraLogic, Inc. - 707 CALIFORNIA STREET - MOUNTAIN VIEW CA 94041 - UNITED STATES - - 00-10-8B (hex) LASERANIMATION SOLLINGER GmbH - 00108B (base 16) LASERANIMATION SOLLINGER GmbH - CRELLESTR. 19/20 - D 10827 BERLIN - GERMANY - - 00-10-8C (hex) FUJITSU TELECOMMUNICATIONS EUROPE, LTD. - 00108C (base 16) FUJITSU TELECOMMUNICATIONS EUROPE, LTD. - SOLIHULL PARKWAY - BIRMINGHAM BUSINESS PARK - BIRMINGHAM B37 7YU England - UNITED KINGDOM - - 00-10-8D (hex) Johnson Controls, Inc. - 00108D (base 16) Johnson Controls, Inc. - 507 E. Michigan St. - P.O. Box 423 / M73 - Milwaukee WI 53201 - UNITED STATES - - 00-10-8E (hex) HUGH SYMONS CONCEPT Technologies Ltd. - 00108E (base 16) HUGH SYMONS CONCEPT Technologies Ltd. - Alder Hills Park - 16 Alder Hills - Poole, Dorset BM12 4AR - UNITED KINGDOM - - 00-10-8F (hex) RAPTOR SYSTEMS - 00108F (base 16) RAPTOR SYSTEMS - 69 HICKORY AVE. - WALTHAM MA 02154 - UNITED STATES - - 00-10-90 (hex) CIMETRICS, INC. - 001090 (base 16) CIMETRICS, INC. - 55 TEMPLE PLACE - BOSTON MA 02111 - UNITED STATES - - 00-10-91 (hex) NO WIRES NEEDED BV - 001091 (base 16) NO WIRES NEEDED BV - P.O. BOX 343 - 3720 AH BILTHOVEN - NETHERLANDS - - 00-10-92 (hex) NETCORE INC. - 001092 (base 16) NETCORE INC. - 12F-2, 537, SEC.2 - KUANG-FU ROAD, - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-10-93 (hex) CMS COMPUTERS, LTD. - 001093 (base 16) CMS COMPUTERS, LTD. - 201 ARCADIA - NARIMAN POINT - MUMBAI 400 0021 - INDIA - - 00-10-94 (hex) Performance Analysis Broadband, Spirent plc - 001094 (base 16) Performance Analysis Broadband, Spirent plc - 27349 Agoura Road - Calabasas Hills CA 91301 - UNITED STATES - - 00-10-95 (hex) Thomson Inc. - 001095 (base 16) Thomson Inc. - 101 West 103rd Street - Indianapolis IN 46290-1102 - UNITED STATES - - 00-10-96 (hex) TRACEWELL SYSTEMS, INC. - 001096 (base 16) TRACEWELL SYSTEMS, INC. - 567 ENTERPRISE DRIVE - WESTERVILLE OH 43081 - UNITED STATES - - 00-10-97 (hex) WinNet Metropolitan Communications Systems, Inc. - 001097 (base 16) WinNet Metropolitan Communications Systems, Inc. - 661 EAST ARQUES AVE. - SUNNYVALE CA 94086 - UNITED STATES - - 00-10-98 (hex) STARNET TECHNOLOGIES, INC. - 001098 (base 16) STARNET TECHNOLOGIES, INC. - 2210 O'TOOLE AVE. - SAN JOSE CA 95131 - UNITED STATES - - 00-10-99 (hex) InnoMedia, Inc. - 001099 (base 16) InnoMedia, Inc. - 4800 GREAT AMERICA PARKWAY - SUITE #400 - SANTA CLARA CA 95054 - UNITED STATES - - 00-10-9A (hex) NETLINE - 00109A (base 16) NETLINE - 7, Rue de Bievres - 92140 CLAMART - FRANCE - - 00-10-9B (hex) Emulex Corporation - 00109B (base 16) Emulex Corporation - 3333 Susan Street - Costa Mesa CA 92626 - UNITED STATES - - 00-10-9C (hex) M-SYSTEM CO., LTD. - 00109C (base 16) M-SYSTEM CO., LTD. - 1-1-25 SHIN URASHIMA CHOU - KANAGAWA-KU - YOKOHAMA 221 - JAPAN - - 00-10-9D (hex) CLARINET SYSTEMS, INC. - 00109D (base 16) CLARINET SYSTEMS, INC. - 1415 KOLL CIRCLE #101 - SAN JOSE CA 95112 - UNITED STATES - - 00-10-9E (hex) AWARE, INC. - 00109E (base 16) AWARE, INC. - ONE OAK PARK - BEDFORD MA 01730 - UNITED STATES - - 00-10-9F (hex) PAVO, INC. - 00109F (base 16) PAVO, INC. - 95 YESLER WAY - SEATTLE WA 98104 - UNITED STATES - - 00-10-A0 (hex) INNOVEX TECHNOLOGIES, INC. - 0010A0 (base 16) INNOVEX TECHNOLOGIES, INC. - KEYSTONE COMMONS - 526 BRADDOCK AVE. - TURTLE CREEK PA 15145 - UNITED STATES - - 00-10-A1 (hex) KENDIN SEMICONDUCTOR, INC. - 0010A1 (base 16) KENDIN SEMICONDUCTOR, INC. - 1550 S. BASCOM AVE., STE. #250 - CAMPBELL CA 95008 - UNITED STATES - - 00-10-A2 (hex) TNS - 0010A2 (base 16) TNS - 800 Third Street, Suite B100 - HERNDON VA 20170 - UNITED STATES - - 00-10-A3 (hex) OMNITRONIX, INC. - 0010A3 (base 16) OMNITRONIX, INC. - 760 HARRISON STREET - SEATTLE WA 98109 - UNITED STATES - - 00-10-A4 (hex) XIRCOM - 0010A4 (base 16) XIRCOM - 2300 CORPORATE CENTER DR. - THOUSAND OAKS CA 91320 - UNITED STATES - - 00-10-A5 (hex) OXFORD INSTRUMENTS - 0010A5 (base 16) OXFORD INSTRUMENTS - Halifax Road - High Wycombe - Buckinghamshire HP12 3SE - UNITED KINGDOM - - 00-10-A6 (hex) CISCO SYSTEMS, INC. - 0010A6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-A7 (hex) UNEX TECHNOLOGY CORPORATION - 0010A7 (base 16) UNEX TECHNOLOGY CORPORATION - 8F-5, #130, SZE WEI RD., - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-10-A8 (hex) RELIANCE COMPUTER CORP. - 0010A8 (base 16) RELIANCE COMPUTER CORP. - 3032 BUNKER HILL LANE - SUITE 201 - SANTA CLARA CA 95054 - UNITED STATES - - 00-10-A9 (hex) ADHOC TECHNOLOGIES - 0010A9 (base 16) ADHOC TECHNOLOGIES - 1150 FIRST STREET - SAN JOSE CA 95112 - UNITED STATES - - 00-10-AA (hex) MEDIA4, INC. - 0010AA (base 16) MEDIA4, INC. - 250 14TH ST. NW - STE #4002 - ATLANTA GA 30318 - UNITED STATES - - 00-10-AB (hex) KOITO ELECTRIC INDUSTRIES, LTD. - 0010AB (base 16) KOITO ELECTRIC INDUSTRIES, LTD. - 100 MAEDA-CHO, TOTSUKA-KU - YOKOHAMA 244 KANAGAWA 244-8569 - JAPAN - - 00-10-AC (hex) IMCI TECHNOLOGIES - 0010AC (base 16) IMCI TECHNOLOGIES - 8401 OLD COURT HKOUSE RD - SUITE #200 - VIENNA VA 22182 - UNITED STATES - - 00-10-AD (hex) SOFTRONICS USB, INC. - 0010AD (base 16) SOFTRONICS USB, INC. - 5085 LIST DRIVE - COLORADO SPRINGS CO 80919 - UNITED STATES - - 00-10-AE (hex) SHINKO ELECTRIC INDUSTRIES CO. - 0010AE (base 16) SHINKO ELECTRIC INDUSTRIES CO. - 80 OSHIMADA-MACHI - NAGANO-SHI 381-22 - JAPAN - - 00-10-AF (hex) TAC SYSTEMS, INC. - 0010AF (base 16) TAC SYSTEMS, INC. - 1035 PUTMAN DRIVE--STE. - HUNTSVILLE AL 35816-2271 - UNITED STATES - - 00-10-B0 (hex) MERIDIAN TECHNOLOGY CORP. - 0010B0 (base 16) MERIDIAN TECHNOLOGY CORP. - 11 MCBRIDE CORP. CENTER DR. - CHESTERFIELD MD 63005 - UNITED STATES - - 00-10-B1 (hex) FOR-A CO., LTD. - 0010B1 (base 16) FOR-A CO., LTD. - 2-3-3 OOSAKU - SAKURA CITY, - CHIBA PREF. 285 - JAPAN - - 00-10-B2 (hex) COACTIVE AESTHETICS - 0010B2 (base 16) COACTIVE AESTHETICS - 4000 BRIDGEWAY - STE. #303 - SAUSALITA CA 94965 - UNITED STATES - - 00-10-B3 (hex) NOKIA MULTIMEDIA TERMINALS - 0010B3 (base 16) NOKIA MULTIMEDIA TERMINALS - NOKIA HOME COMMUNICATIONS - DISKETTGATAN 11 - SE-583 35 LINKOPING - SWEDEN - - 00-10-B4 (hex) ATMOSPHERE NETWORKS - 0010B4 (base 16) ATMOSPHERE NETWORKS - 10460 BANDLEY DRIVE - CUPERTINO CA 95014 - UNITED STATES - - 00-10-B5 (hex) ACCTON TECHNOLOGY CORPORATION - 0010B5 (base 16) ACCTON TECHNOLOGY CORPORATION - NO.1, CREATION RD. III - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-10-B6 (hex) ENTRATA COMMUNICATIONS CORP. - 0010B6 (base 16) ENTRATA COMMUNICATIONS CORP. - 574 HERITAGE RD. - SOUTHBURY CT 06488 - UNITED STATES - - 00-10-B7 (hex) COYOTE TECHNOLOGIES, LLC - 0010B7 (base 16) COYOTE TECHNOLOGIES, LLC - 4360 PARK TERRACE DRIVE - WESTLAKE VILLAGE CA 91361 - UNITED STATES - - 00-10-B8 (hex) ISHIGAKI COMPUTER SYSTEM CO. - 0010B8 (base 16) ISHIGAKI COMPUTER SYSTEM CO. - 1-1-1, KYOBASHI, - CHUO-KU - Tokyo - JAPAN - - 00-10-B9 (hex) MAXTOR CORP. - 0010B9 (base 16) MAXTOR CORP. - 2190 MILLER DRIVE - LONGMONT CO 80501-6744 - UNITED STATES - - 00-10-BA (hex) MARTINHO-DAVIS SYSTEMS, INC. - 0010BA (base 16) MARTINHO-DAVIS SYSTEMS, INC. - 1260 OLD INNES ROAD - OTTAWA, ONTARIO K1B 3V3 - CANADA - - 00-10-BB (hex) DATA & INFORMATION TECHNOLOGY - 0010BB (base 16) DATA & INFORMATION TECHNOLOGY - TECHNOLOGY HOUSE - 1 NORMANTON LANE - BOTTESFORD, NOTTINGHAM NG13 OEL - UNITED KINGDOM - - 00-10-BC (hex) Aastra Telecom - 0010BC (base 16) Aastra Telecom - 8 Federal Street - Billerica MA 01821-3570 - UNITED STATES - - 00-10-BD (hex) THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) - 0010BD (base 16) THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) - 1-1-12 Shiba Kouen, Minato-ku - MINATO-KU, TOKYO 105-0011 - JAPAN - - 00-10-BE (hex) MARCH NETWORKS CORPORATION - 0010BE (base 16) MARCH NETWORKS CORPORATION - 303 Terry Fox Drive - OTTAWA, ONTARIO K2K 3J1 - CANADA - - 00-10-BF (hex) InterAir Wireless - 0010BF (base 16) InterAir Wireless - 485 CAYUGA ROAD - BUFFALO NY 14225-0222 - UNITED STATES - - 00-10-C0 (hex) ARMA, Inc. - 0010C0 (base 16) ARMA, Inc. - 4851 Northshore Lane - North Little Rock AR 72118 - UNITED STATES - - 00-10-C1 (hex) OI ELECTRIC CO., LTD. - 0010C1 (base 16) OI ELECTRIC CO., LTD. - 7-3-16 KIKUNA - KOHOKU-KU - YOKOHAMA 222 - JAPAN - - 00-10-C2 (hex) WILLNET, INC. - 0010C2 (base 16) WILLNET, INC. - JOWA-TAKANAWA BLDG. 8F - TAKANAWA 1-5-4, MINATO-KU, - TOKYO - JAPAN - - 00-10-C3 (hex) CSI-CONTROL SYSTEMS - 0010C3 (base 16) CSI-CONTROL SYSTEMS - INTERNATIONAL - POB 59469 - DALLAS TX 75229 - UNITED STATES - - 00-10-C4 (hex) MEDIA GLOBAL LINKS CO., LTD. - 0010C4 (base 16) MEDIA GLOBAL LINKS CO., LTD. - 580-16, horikawa-cho,saiwai-ku - TAKATSU-KU KAWASAKI-SHI, - Kawasaki, Kanagawa 212-0013 - JAPAN - - 00-10-C5 (hex) PROTOCOL TECHNOLOGIES, INC. - 0010C5 (base 16) PROTOCOL TECHNOLOGIES, INC. - 4 FIRST STREET - BRIDGEWATER MA 02324 - UNITED STATES - - 00-10-C6 (hex) Universal Global Scientific Industrial Co., Ltd. - 0010C6 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351,SEC.1, TAIPING RD. - TSAOTUEN, NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 00-10-C7 (hex) DATA TRANSMISSION NETWORK - 0010C7 (base 16) DATA TRANSMISSION NETWORK - 9110 W. DODGE RD. - STE.#200 - OMAHA NE 68114 - UNITED STATES - - 00-10-C8 (hex) COMMUNICATIONS ELECTRONICS SECURITY GROUP - 0010C8 (base 16) COMMUNICATIONS ELECTRONICS SECURITY GROUP - 10/4W22 FIDDLERS GREEN LANE - Benhall, Cheltenham Glouster GL52 5AJ - UNITED KINGDOM - - 00-10-C9 (hex) MITSUBISHI ELECTRONICS LOGISTIC SUPPORT CO. - 0010C9 (base 16) MITSUBISHI ELECTRONICS LOGISTIC SUPPORT CO. - - SHONAN Works, 730-11, KAMIMACHIYA - Kamakura-city, Kanagawa 247 - JAPAN - - 00-10-CA (hex) Telco Systems, Inc. - 0010CA (base 16) Telco Systems, Inc. - 15 Berkshire Road - Mansfield, MA 02048 - UNITED STATES - - 00-10-CB (hex) FACIT K.K. - 0010CB (base 16) FACIT K.K. - HIMEI NIHOMBASHI BLDG. 3F - 12-3-NIHOMBASHI-KOBUNACHO - CHUO-KU, TOKYO 103 - JAPAN - - 00-10-CC (hex) CLP COMPUTER LOGISTIK PLANUNG GmbH - 0010CC (base 16) CLP COMPUTER LOGISTIK PLANUNG GmbH - BASSERMANNSTR. 21 - D-81245 MUENCHEN - GERMANY - - 00-10-CD (hex) INTERFACE CONCEPT - 0010CD (base 16) INTERFACE CONCEPT - 3 VENELLE de KERGOS - 29000 QUIMPER - FRANCE - - 00-10-CE (hex) VOLAMP, LTD. - 0010CE (base 16) VOLAMP, LTD. - UNIT 3 RIVERSIDE BUSINESS PARK - DOGFLUD WAY, - FARNHAM, SURREY ENGLAND - UNITED KINGDOM - - 00-10-CF (hex) FIBERLANE COMMUNICATIONS - 0010CF (base 16) FIBERLANE COMMUNICATIONS - 1318 REDWOOD WAY, #200 - PETALUMA CA 94954 - UNITED STATES - - 00-10-D0 (hex) WITCOM, LTD. - 0010D0 (base 16) WITCOM, LTD. - P.O.B. 2250 - HAIFA 31021 - ISRAEL - - 00-10-D1 (hex) Top Layer Networks, Inc. - 0010D1 (base 16) Top Layer Networks, Inc. - 4 MECHANIC ST.- STE#212 - NATICK MA 01760 - UNITED STATES - - 00-10-D2 (hex) NITTO TSUSHINKI CO., LTD - 0010D2 (base 16) NITTO TSUSHINKI CO., LTD - 7-27-11, TODOROKI, SETAGAYA-KU - TOKYO 151 - JAPAN - - 00-10-D3 (hex) GRIPS ELECTRONIC GMBH - 0010D3 (base 16) GRIPS ELECTRONIC GMBH - NIESENBERGERGASSE 37 - A-8020 GRAZ - AUSTRIA - - 00-10-D4 (hex) STORAGE COMPUTER CORPORATION - 0010D4 (base 16) STORAGE COMPUTER CORPORATION - 11 RIVERSIDE STREET - NASHUA NH 03062 - UNITED STATES - - 00-10-D5 (hex) IMASDE CANARIAS, S.A. - 0010D5 (base 16) IMASDE CANARIAS, S.A. - URB. EL CEBADAL - C/DR. JUAN DGUEZ.PEREZ, 39-2 - 35008 LAS PALMAS G.C. - SPAIN - - 00-10-D6 (hex) Exelis - 0010D6 (base 16) Exelis - 7310 Innovation Blvd., M/S 536 - Ft Wayne IN 46818 - UNITED STATES - - 00-10-D7 (hex) ARGOSY RESEARCH INC. - 0010D7 (base 16) ARGOSY RESEARCH INC. - NO. 44, LANE 411, CHUNG HUA RD - SEC.4, HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-10-D8 (hex) CALISTA - 0010D8 (base 16) CALISTA - 98 HIGH STREET, THAME - OXFORDSHIRE OX9 3EH ENGLAND - UNITED KINGDOM - - 00-10-D9 (hex) IBM JAPAN, FUJISAWA MT+D - 0010D9 (base 16) IBM JAPAN, FUJISAWA MT+D - KIRIHARA-CHO 1, FUJISAWA CITY - KANAGAWA 252 - JAPAN - - 00-10-DA (hex) Kollmorgen Corp - 0010DA (base 16) Kollmorgen Corp - 33 S.LA PATERA LN - SANTA BARBARA CA 93117 - UNITED STATES - - 00-10-DB (hex) Juniper Networks, Inc. - 0010DB (base 16) Juniper Networks, Inc. - 1194 N. Mathilda Avenue - Sunnyvale CA 94010 - UNITED STATES - - 00-10-DC (hex) MICRO-STAR INTERNATIONAL CO., LTD. - 0010DC (base 16) MICRO-STAR INTERNATIONAL CO., LTD. - NO. 69, LI-DE ST., JUNG-HE CITY - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-10-DD (hex) ENABLE SEMICONDUCTOR, INC. - 0010DD (base 16) ENABLE SEMICONDUCTOR, INC. - 1740 TECHNOLOGY DRIVE - SUITE #110 - SAN JOSE CA 95110 - UNITED STATES - - 00-10-DE (hex) INTERNATIONAL DATACASTING CORPORATION - 0010DE (base 16) INTERNATIONAL DATACASTING CORPORATION - 2680 QUEENSVIEW DRIVE - OTTAWA, ONTARIO K2B 8H6 - CANADA - - 00-10-DF (hex) RISE COMPUTER INC. - 0010DF (base 16) RISE COMPUTER INC. - 9F, NO. 306-3, TATUNG RD. - SEC. 1, HSI CHIH, - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-10-E0 (hex) Oracle Corporation - 0010E0 (base 16) Oracle Corporation - 500 Oracle Parkway - Redwood Shores CA 94065 - UNITED STATES - - 00-10-E1 (hex) S.I. TECH, INC. - 0010E1 (base 16) S.I. TECH, INC. - P.O. BOX 609 - GENEVA IL 60134 - UNITED STATES - - 00-10-E2 (hex) ArrayComm, Inc. - 0010E2 (base 16) ArrayComm, Inc. - 3141 ZANKER ROAD - SAN JOSE CA 95134 - UNITED STATES - - 00-10-E3 (hex) Hewlett-Packard Company - 0010E3 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-10-E4 (hex) NSI CORPORATION - 0010E4 (base 16) NSI CORPORATION - P.O. BOX 635 - WILSONVILLE OR 97070 - UNITED STATES - - 00-10-E5 (hex) SOLECTRON TEXAS - 0010E5 (base 16) SOLECTRON TEXAS - 12455 RESEARCH BLVD. M/S 2205 - AUSTIN TX 78759 - UNITED STATES - - 00-10-E6 (hex) APPLIED INTELLIGENT SYSTEMS, INC. - 0010E6 (base 16) APPLIED INTELLIGENT SYSTEMS, INC. - 3923 RANCHERO DRIVE - ANN ARBOR MI 48108 - UNITED STATES - - 00-10-E7 (hex) BreezeCom - 0010E7 (base 16) BreezeCom - PO Box 13139 - Atidim Technological Park, Bldg. 1 - Tel-Aviv - ISRAEL - - 00-10-E8 (hex) TELOCITY, INCORPORATED - 0010E8 (base 16) TELOCITY, INCORPORATED - 992 SOUTH DE ANZA BLVD - SAN JOSE CA 95129 - UNITED STATES - - 00-10-E9 (hex) RAIDTEC LTD. - 0010E9 (base 16) RAIDTEC LTD. - CASTLE ROAD - LITTLE ISLAND INDUSTRIAL ESTATE - Little Island County Cork - IRELAND - - 00-10-EA (hex) ADEPT TECHNOLOGY - 0010EA (base 16) ADEPT TECHNOLOGY - 150 ROSE ORCHARD WAY - SAN JOSE CA 95134 - UNITED STATES - - 00-10-EB (hex) SELSIUS SYSTEMS, INC. - 0010EB (base 16) SELSIUS SYSTEMS, INC. - 5057 KELLER SPRINGS RD. - DALLAS TX 75248 - UNITED STATES - - 00-10-EC (hex) RPCG, LLC - 0010EC (base 16) RPCG, LLC - 749 MINER ROAD - HIGHLAND HTS OH 44143-2117 - UNITED STATES - - 00-10-ED (hex) SUNDANCE TECHNOLOGY, INC. - 0010ED (base 16) SUNDANCE TECHNOLOGY, INC. - 20111 STEVENS CREEK BLVD. - SUITE #138 - CUPERTINO CA 95014 - UNITED STATES - - 00-10-EE (hex) CTI PRODUCTS, INC. - 0010EE (base 16) CTI PRODUCTS, INC. - 1211 W. SHARON RD. - CINCINNATI OH 45240 - UNITED STATES - - 00-10-EF (hex) DBTEL INCORPORATED - 0010EF (base 16) DBTEL INCORPORATED - NO.29 TZU-CHIANG ST., - TU-CHENG TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-10-F0 (hex) RITTAL-WERK RUDOLF LOH GmbH & Co. - 0010F0 (base 16) RITTAL-WERK RUDOLF LOH GmbH & Co. - AUF DEM STUTZELBERG - D-35745 HERBORN - GERMANY - - 00-10-F1 (hex) I-O CORPORATION - 0010F1 (base 16) I-O CORPORATION - 2256 SOUTH 3600 WEST - SALT LAKE CITY UT 84119 - UNITED STATES - - 00-10-F2 (hex) ANTEC - 0010F2 (base 16) ANTEC - 4920 AVALON RIDGE PKWY - SUITE #600 - NORCROSS GA 30071 - UNITED STATES - - 00-10-F3 (hex) Nexcom International Co., Ltd. - 0010F3 (base 16) Nexcom International Co., Ltd. - 18F, No. 716, Chung-Cheng Road, - Chung Ho, - Taipei Hsien 235, - TAIWAN, PROVINCE OF CHINA - - 00-10-F4 (hex) Vertical Communications - 0010F4 (base 16) Vertical Communications - 3979 Freedom Circle #400 - Santa Clara CA 95054-1247 - UNITED STATES - - 00-10-F5 (hex) AMHERST SYSTEMS, INC. - 0010F5 (base 16) AMHERST SYSTEMS, INC. - 30 WILSON ROAD - BUFFALO NY 14221 - UNITED STATES - - 00-10-F6 (hex) CISCO SYSTEMS, INC. - 0010F6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-10-F7 (hex) IRIICHI TECHNOLOGIES Inc. - 0010F7 (base 16) IRIICHI TECHNOLOGIES Inc. - 1-26-7 CHUO, NAKANA-KU - TOKYO 164 - JAPAN - - 00-10-F8 (hex) TEXIO TECHNOLOGY CORPORATION - 0010F8 (base 16) TEXIO TECHNOLOGY CORPORATION - 1850-1 Tsuruma, Machida-shi - Tokyo 194-0004 - JAPAN - - 00-10-F9 (hex) UNIQUE SYSTEMS, INC. - 0010F9 (base 16) UNIQUE SYSTEMS, INC. - 181 DON PARK RD - MARKHAM, ONTARIO L3R 1C2 - CANADA - - 00-10-FA (hex) Apple - 0010FA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-10-FB (hex) ZIDA TECHNOLOGIES LIMITED - 0010FB (base 16) ZIDA TECHNOLOGIES LIMITED - 8/F BLOCK A GOODVIEW INDUSTRIAL BUILDIN - KIN FAT STR TMTL 213 - TUEN MUN NT - HONG KONG - - 00-10-FC (hex) BROADBAND NETWORKS, INC. - 0010FC (base 16) BROADBAND NETWORKS, INC. - 37 STEVENSON ROAD - WINNIPEG, MANITOBA R3H 0H9 - CANADA - - 00-10-FD (hex) COCOM A/S - 0010FD (base 16) COCOM A/S - TELETONVEJ 8 - DK 2860 SOBORG - DENMARK - - 00-10-FE (hex) DIGITAL EQUIPMENT CORPORATION - 0010FE (base 16) DIGITAL EQUIPMENT CORPORATION - 301 ROCKRIMMON BLVD, SOUTH - M/S CXO1-2/N26 - COLORADO SPRINGS CO 80919 - UNITED STATES - - 00-10-FF (hex) CISCO SYSTEMS, INC. - 0010FF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-00 (hex) Schneider Electric - 001100 (base 16) Schneider Electric - 5460 Pottsville Pike - Leesport PA 19533 - UNITED STATES - - 00-11-01 (hex) CET Technologies Pte Ltd - 001101 (base 16) CET Technologies Pte Ltd - 100 Jurong East Street 21 - Singapore Technologies Building - 609602 - SINGAPORE - - 00-11-02 (hex) Aurora Multimedia Corp. - 001102 (base 16) Aurora Multimedia Corp. - 205 Commercial Court - Morganville New Jersey 07751-1070 - UNITED STATES - - 00-11-03 (hex) kawamura electric inc. - 001103 (base 16) kawamura electric inc. - 3-86 akatsuki-cho - seto aichi 489-0071 - JAPAN - - 00-11-04 (hex) TELEXY - 001104 (base 16) TELEXY - 1116, HYUNDAI 41 TOWER, 917-9 - MOK-DONG, YANGCHUN-KU, - SEOUL 158-723 - KOREA, REPUBLIC OF - - 00-11-05 (hex) Sunplus Technology Co., Ltd. - 001105 (base 16) Sunplus Technology Co., Ltd. - 19, Innovation First Road, Hsinchu Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-11-06 (hex) Siemens NV (Belgium) - 001106 (base 16) Siemens NV (Belgium) - Atealaan 34 - Herentals Antwerp 2200 - BELGIUM - - 00-11-07 (hex) RGB Networks Inc. - 001107 (base 16) RGB Networks Inc. - 2929 Campus Drive - Suite 165 - San Mateo CA 94403 - UNITED STATES - - 00-11-08 (hex) Orbital Data Corporation - 001108 (base 16) Orbital Data Corporation - 1900 S. Norfolk St. Ste 320 - San Mateo CA 94403 - UNITED STATES - - 00-11-09 (hex) Micro-Star International - 001109 (base 16) Micro-Star International - No 69, Li-De Street, Jung-He City, - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-11-0A (hex) Hewlett-Packard Company - 00110A (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS070405 - Houston TX 77070 - UNITED STATES - - 00-11-0B (hex) Franklin Technology Systems - 00110B (base 16) Franklin Technology Systems - 20406 Earl St - Torrance CA 90503 - UNITED STATES - - 00-11-0C (hex) Atmark Techno, Inc. - 00110C (base 16) Atmark Techno, Inc. - 2F SD BLDG, 2-2-3-14 Atsubetsu-nishi, Atsubetsu-ku - Sapporo Hokkaido 004-0062 - JAPAN - - 00-11-0D (hex) SANBlaze Technology, Inc. - 00110D (base 16) SANBlaze Technology, Inc. - 2 Clock Tower Place - Maynard MA 01748 - UNITED STATES - - 00-11-0E (hex) Tsurusaki Sealand Transportation Co. Ltd. - 00110E (base 16) Tsurusaki Sealand Transportation Co. Ltd. - 1000 Misa - Oita 8700196 - JAPAN - - 00-11-0F (hex) netplat,Inc. - 00110F (base 16) netplat,Inc. - 2F Olympia Center, 828-10, Yeoksam-dong, Gangnam-gu - SEOUL 135-935 - KOREA, REPUBLIC OF - - 00-11-10 (hex) Maxanna Technology Co., Ltd. - 001110 (base 16) Maxanna Technology Co., Ltd. - Room201, No.42-3, Luyuan Road - Guangzhou 510095 - CHINA - - 00-11-11 (hex) Intel Corporation - 001111 (base 16) Intel Corporation - 2111 NE 25th Avenue - Hillsboro OR 97123 - UNITED STATES - - 00-11-12 (hex) Honeywell CMSS - 001112 (base 16) Honeywell CMSS - 8323 Lindbergh Ct - Sarasota FL 34243 - UNITED STATES - - 00-11-13 (hex) Fraunhofer FOKUS - 001113 (base 16) Fraunhofer FOKUS - Kaiserin-Augusta-Allee 31 - Berlin 10589 - GERMANY - - 00-11-14 (hex) EverFocus Electronics Corp. - 001114 (base 16) EverFocus Electronics Corp. - 12F, No. 79, Sec. 1, Shin-Tai Wu Rd. - Hsi-Chi Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-11-15 (hex) EPIN Technologies, Inc. - 001115 (base 16) EPIN Technologies, Inc. - Acorn Campus - 6th Result Way, Suite 248 - Cupertino CA 95014 - UNITED STATES - - 00-11-16 (hex) COTEAU VERT CO., LTD. - 001116 (base 16) COTEAU VERT CO., LTD. - 3-3-19 KACHIDOKI - CHUO-KU TOKYO 104-0054 - JAPAN - - 00-11-17 (hex) CESNET - 001117 (base 16) CESNET - Zikova 4 - Praha 6 160 00 - CZECH REPUBLIC - - 00-11-18 (hex) BLX IC Design Corp., Ltd. - 001118 (base 16) BLX IC Design Corp., Ltd. - Rm 1006, Quantum Plaza - No.27, Zhichun Rd, Haidan - Beijing 100083 - CHINA - - 00-11-19 (hex) Solteras, Inc. - 001119 (base 16) Solteras, Inc. - 900 W. Santa Anita Street - San Gabriel CA 91776 - UNITED STATES - - 00-11-1A (hex) ARRIS Group, Inc. - 00111A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-11-1B (hex) Targa Systems Div L-3 Communications Canada - 00111B (base 16) Targa Systems Div L-3 Communications Canada - 2081 Merivale Rd - Suite 200 - Ottawa Ont K2G 1G9 - CANADA - - 00-11-1C (hex) Pleora Technologies Inc. - 00111C (base 16) Pleora Technologies Inc. - 359 Terry Fox Drive, Suite 230 - Kanata ON K2K 2E7 - CANADA - - 00-11-1D (hex) Hectrix Limited - 00111D (base 16) Hectrix Limited - Unit 906-911, 9/F, Stanhope Hosue, - 734-738 King's Road, - North Point Hong Kong - CHINA - - 00-11-1E (hex) EPSG (Ethernet Powerlink Standardization Group) - 00111E (base 16) EPSG (Ethernet Powerlink Standardization Group) - c/o University of Applied Sciences - PO Box 805 - Winterthur ZH CH-8401 - SWITZERLAND - - 00-11-1F (hex) Doremi Labs, Inc. - 00111F (base 16) Doremi Labs, Inc. - 306 E. Alameda Ave. - Burbank CA 91502 - UNITED STATES - - 00-11-20 (hex) CISCO SYSTEMS, INC. - 001120 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-21 (hex) CISCO SYSTEMS, INC. - 001121 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-22 (hex) CIMSYS Inc - 001122 (base 16) CIMSYS Inc - #301,Sinsung-clean BLDG,140, Nongseo-Ri,Kiheung-Eup - Yongin-City Kyunggi-Do 449-711 - KOREA, REPUBLIC OF - - 00-11-23 (hex) Appointech, Inc. - 001123 (base 16) Appointech, Inc. - 6F-2 No.192 Tung-Kuan Rd. - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-11-24 (hex) Apple - 001124 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-11-25 (hex) IBM Corp - 001125 (base 16) IBM Corp - 3039 E Cornwallis Rd - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-11-26 (hex) Venstar Inc. - 001126 (base 16) Venstar Inc. - 9250 Owensmouth Ave. - Chatsworth CA 91311 - UNITED STATES - - 00-11-27 (hex) TASI, Inc - 001127 (base 16) TASI, Inc - 5551 Dry Fork Road - Cleves OH 45002 - UNITED STATES - - 00-11-28 (hex) Streamit - 001128 (base 16) Streamit - Flight Forum 3543 - Eindhoven 5657 DW - NETHERLANDS - - 00-11-29 (hex) Paradise Datacom Ltd. - 001129 (base 16) Paradise Datacom Ltd. - 1 Wheaton Road - Witham Essex UK CM8 1UJ - UNITED KINGDOM - - 00-11-2A (hex) Niko NV - 00112A (base 16) Niko NV - Industriepark West 40 - Sint-Niklaas O/V 9100 - BELGIUM - - 00-11-2B (hex) NetModule AG - 00112B (base 16) NetModule AG - Meriedweg 11 - Niederwangen CH 3172 - SWITZERLAND - - 00-11-2C (hex) IZT GmbH - 00112C (base 16) IZT GmbH - Am Weichselgarten 5 - Erlangen Bavaria 91058 - GERMANY - - 00-11-2D (hex) iPulse Systems - 00112D (base 16) iPulse Systems - Unit 3, Riverside Industrial Park - Ossewa street - Chloorkop Gauteng 1618 - SOUTH AFRICA - - 00-11-2E (hex) CEICOM - 00112E (base 16) CEICOM - 17 rue Gaston Evrard - Toulouse Cedex 1 Haute-Garonne 31094 - FRANCE - - 00-11-2F (hex) ASUSTek Computer Inc. - 00112F (base 16) ASUSTek Computer Inc. - No.150, Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-11-30 (hex) Allied Telesis (Hong Kong) Ltd. - 001130 (base 16) Allied Telesis (Hong Kong) Ltd. - Room F, 3/F, Yeung Yiu Chong (no. 8) Industrial building, - 20 Wang Hoi Road, Kowloon Bay, - HONG KONG - - 00-11-31 (hex) UNATECH. CO.,LTD - 001131 (base 16) UNATECH. CO.,LTD - A-727 ,GEOPYUNG TOWN,203-1 - NONHYUNG-DONG - KANGNAM-GU SEOUL 135-010 - KOREA, REPUBLIC OF - - 00-11-32 (hex) Synology Incorporated - 001132 (base 16) Synology Incorporated - 6F-2, No.106, Chang An W. Rd., - Taipei 103 - TAIWAN, PROVINCE OF CHINA - - 00-11-33 (hex) Siemens Austria SIMEA - 001133 (base 16) Siemens Austria SIMEA - Siemensstrasse 90-92 - Vienna 1210 - AUSTRIA - - 00-11-34 (hex) MediaCell, Inc. - 001134 (base 16) MediaCell, Inc. - 600 17th St - Suite 2800 South - Denver CO 80202 - UNITED STATES - - 00-11-35 (hex) Grandeye Ltd - 001135 (base 16) Grandeye Ltd - 6 Huxley Road - Surrey Research Park - Guildford Surrey GU2 7RE - UNITED KINGDOM - - 00-11-36 (hex) Goodrich Sensor Systems - 001136 (base 16) Goodrich Sensor Systems - 14300 Judicial Road - Burnsville Minnesota 55306-4898 - UNITED STATES - - 00-11-37 (hex) AICHI ELECTRIC CO., LTD. - 001137 (base 16) AICHI ELECTRIC CO., LTD. - 1 - aichi-cho - kasugai city aichi pref. 486-8666 - JAPAN - - 00-11-38 (hex) TAISHIN CO., LTD. - 001138 (base 16) TAISHIN CO., LTD. - 200-7 Nakano - Nakano Nagano 383-0013 - JAPAN - - 00-11-39 (hex) STOEBER ANTRIEBSTECHNIK GmbH + Co. KG. - 001139 (base 16) STOEBER ANTRIEBSTECHNIK GmbH + Co. KG. - Kieselbronner Str. 12 - Pforzheim 75177 - GERMANY - - 00-11-3A (hex) SHINBORAM - 00113A (base 16) SHINBORAM - 4F DAHNWORLD BUILDING, 154-11 SAMSUNG-DONG - KANGNAM-GU, - SEOUL 135-879 - KOREA, REPUBLIC OF - - 00-11-3B (hex) Micronet Communications Inc. - 00113B (base 16) Micronet Communications Inc. - 12F-1, No. 100, Min-Chuan Road - Hsin-Tien Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-11-3C (hex) Micronas GmbH - 00113C (base 16) Micronas GmbH - Hans-Bunte-Strasse 19 - Freiburg BW D-79108 - GERMANY - - 00-11-3D (hex) KN SOLTEC CO.,LTD. - 00113D (base 16) KN SOLTEC CO.,LTD. - 98B-5L NAMDONG INDUSTRIAL COMPLEX #662-4 GOJAN-DONG - NAMDONG-GU INCHEON 405-818 - KOREA, REPUBLIC OF - - 00-11-3E (hex) JL Corporation - 00113E (base 16) JL Corporation - 4-4-17 SUGE - TAMA-KU - KAWASAKI-CITY KANAGAWA-KEN 214-0001 - JAPAN - - 00-11-3F (hex) Alcatel DI - 00113F (base 16) Alcatel DI - ZI lavoisier - EU Normandie 76260 - FRANCE - - 00-11-40 (hex) Nanometrics Inc. - 001140 (base 16) Nanometrics Inc. - 250 Herzberg Rd. - Kanata Ontario K2K 2A1 - CANADA - - 00-11-41 (hex) GoodMan Corporation - 001141 (base 16) GoodMan Corporation - 2F, No.572, Sec.1, Ming-Sheng N Road, Kwei-Shan Hsiang - Taoyuan Hsien 33300 - TAIWAN, PROVINCE OF CHINA - - 00-11-42 (hex) e-SMARTCOM INC. - 001142 (base 16) e-SMARTCOM INC. - 3F, 216, Imok-Dong - JangAn-Ku - Suwon Kyoungki-Do 440-310 - KOREA, REPUBLIC OF - - 00-11-43 (hex) Dell Inc - 001143 (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-11-44 (hex) Assurance Technology Corp - 001144 (base 16) Assurance Technology Corp - 6304 Potomac Avenue - Alexandria Virginia 22307 - UNITED STATES - - 00-11-45 (hex) ValuePoint Networks - 001145 (base 16) ValuePoint Networks - 350 Townsend St Ste 320 - San Francisco, CA 94107 - UNITED STATES - - 00-11-46 (hex) Telecard-Pribor Ltd - 001146 (base 16) Telecard-Pribor Ltd - Lustdorfskaya doroga, 162 - Odessa 65115 - UKRAINE - - 00-11-47 (hex) Secom-Industry co.LTD. - 001147 (base 16) Secom-Industry co.LTD. - Fukuo kaKuramoto Ichihonki 3-3 - Shiroishi Miyagi 989-0295 - JAPAN - - 00-11-48 (hex) Prolon Control Systems - 001148 (base 16) Prolon Control Systems - Herstedvesterstraede 56 - Albertslund DK-2620 - DENMARK - - 00-11-49 (hex) Proliphix Inc. - 001149 (base 16) Proliphix Inc. - 3 Lan Drive - Westford MA 01886 - UNITED STATES - - 00-11-4A (hex) KAYABA INDUSTRY Co,.Ltd. - 00114A (base 16) KAYABA INDUSTRY Co,.Ltd. - World Trade Center Bldg., 4-1 - Hamamatsu-cho 2-chome, - Minato-ku, Tokyo Meto. 105-6111 - JAPAN - - 00-11-4B (hex) Francotyp-Postalia GmbH - 00114B (base 16) Francotyp-Postalia GmbH - Triftweg 21-26 - Birkenwerder Brandenburg 16547 - GERMANY - - 00-11-4C (hex) caffeina applied research ltd. - 00114C (base 16) caffeina applied research ltd. - 125 baird ave - cochrane alberta t4c 1c7 - CANADA - - 00-11-4D (hex) Atsumi Electric Co.,LTD. - 00114D (base 16) Atsumi Electric Co.,LTD. - 4-2-2 Shin-Miyakoda, Kita-ku - Hamamatsu Shizuoka 431-2103 - JAPAN - - 00-11-4E (hex) 690885 Ontario Inc. - 00114E (base 16) 690885 Ontario Inc. - 205 Annagem Blvd. - Mississauga Ontario L5T 2V1 - CANADA - - 00-11-4F (hex) US Digital Television, Inc - 00114F (base 16) US Digital Television, Inc - 5807 N. Andrews Way - Fort Lauderdale FL 33309 - UNITED STATES - - 00-11-50 (hex) Belkin Corporation - 001150 (base 16) Belkin Corporation - 501 West Walnut Street - Compton CA 90220-5221 - UNITED STATES - - 00-11-51 (hex) Mykotronx - 001151 (base 16) Mykotronx - 359 Van Ness Way - Torrance CA 90501 - UNITED STATES - - 00-11-52 (hex) Eidsvoll Electronics AS - 001152 (base 16) Eidsvoll Electronics AS - Nedre Vilberg vei 8 - Eidsvoll N-2080 - NORWAY - - 00-11-53 (hex) Trident Tek, Inc. - 001153 (base 16) Trident Tek, Inc. - 8041 Cessna Ave #200 - Gaithersburg MD 20879 - UNITED STATES - - 00-11-54 (hex) Webpro Technologies Inc. - 001154 (base 16) Webpro Technologies Inc. - 2F-1, No.81, Sec. 4, Chungching N. Rd., - Shrlin Chiu - Taipei 111 - TAIWAN, PROVINCE OF CHINA - - 00-11-55 (hex) Sevis Systems - 001155 (base 16) Sevis Systems - 2805 N Dallas Parkway, STE 530 - Plano Texas 75093 - UNITED STATES - - 00-11-56 (hex) Pharos Systems NZ - 001156 (base 16) Pharos Systems NZ - Level 3, 123 Carlton Gore Road - Grafton - Auckland NZ 1001 - NEW ZEALAND - - 00-11-57 (hex) OF Networks Co., Ltd. - 001157 (base 16) OF Networks Co., Ltd. - 1-3-Cb4 Nakase, Mihama-ku - Chiba City Chiba 261-8501 - JAPAN - - 00-11-58 (hex) Nortel Networks - 001158 (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-11-59 (hex) MATISSE NETWORKS INC - 001159 (base 16) MATISSE NETWORKS INC - 339 N BERNARDO AVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-11-5A (hex) Ivoclar Vivadent AG - 00115A (base 16) Ivoclar Vivadent AG - Bendererstrasse 2 - Schaan 9494 - LIECHTENSTEIN - - 00-11-5B (hex) Elitegroup Computer System Co. (ECS) - 00115B (base 16) Elitegroup Computer System Co. (ECS) - No.22, Alley 38, Lane 91, Sec. 1, Nei Hu Road, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-11-5C (hex) CISCO SYSTEMS, INC. - 00115C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-5D (hex) CISCO SYSTEMS, INC. - 00115D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-5E (hex) ProMinent Dosiertechnik GmbH - 00115E (base 16) ProMinent Dosiertechnik GmbH - Im Schumachergewann 5-11 - Heidelberg BW 69123 - GERMANY - - 00-11-5F (hex) ITX Security Co., Ltd. - 00115F (base 16) ITX Security Co., Ltd. - 9F Kolon Digital Tower Aston Bldg. 505-14 - Gasan-dong Geumcheon-gu SEOUL 153-803 - KOREA, REPUBLIC OF - - 00-11-60 (hex) ARTDIO Company Co., LTD - 001160 (base 16) ARTDIO Company Co., LTD - 7th FL.., No.476, Min-Hu RD., Hsin-Chu, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-11-61 (hex) NetStreams, LLC - 001161 (base 16) NetStreams, LLC - 3600 W. Parmer Lane - Suite 100 - Austin TX 78727 - UNITED STATES - - 00-11-62 (hex) STAR MICRONICS CO.,LTD. - 001162 (base 16) STAR MICRONICS CO.,LTD. - 536 Shimizunanatsushinya - Shizuoka 424-0066 - JAPAN - - 00-11-63 (hex) SYSTEM SPA DEPT. ELECTRONICS - 001163 (base 16) SYSTEM SPA DEPT. ELECTRONICS - VIA GHIAROLA VECCHIA 73 - FIORANO MODENESE MODENA I-41042 - ITALY - - 00-11-64 (hex) ACARD Technology Corp. - 001164 (base 16) ACARD Technology Corp. - 6F No.78 Sec1 Kwang Fu Road, Sanchung, - Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 00-11-65 (hex) Znyx Networks - 001165 (base 16) Znyx Networks - 48421 Milmont Drive - Fremont CA 94538 - UNITED STATES - - 00-11-66 (hex) Taelim Electronics Co., Ltd. - 001166 (base 16) Taelim Electronics Co., Ltd. - 196-5, ANYANG7-DONG MANAN-GU - ANYANG-SI KYUGGI-DO 430-817 - KOREA, REPUBLIC OF - - 00-11-67 (hex) Integrated System Solution Corp. - 001167 (base 16) Integrated System Solution Corp. - 3F, No. 2-1, industry East Rd., I - Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-11-68 (hex) HomeLogic LLC - 001168 (base 16) HomeLogic LLC - 100 Hoods Lane - Marblehead MA 01945 - UNITED STATES - - 00-11-69 (hex) EMS Satcom - 001169 (base 16) EMS Satcom - Green Lane - Ashchurch - Tewkesbury Gloucestershire GL20 8HD - UNITED KINGDOM - - 00-11-6A (hex) Domo Ltd - 00116A (base 16) Domo Ltd - Wessex House - Upper Market Street - Eastleigh Hampshire SO50 9FD - UNITED KINGDOM - - 00-11-6B (hex) Digital Data Communications Asia Co.,Ltd - 00116B (base 16) Digital Data Communications Asia Co.,Ltd - 8F,No.41,Lane 221,Kang-Chien RD.,Nei-Hu Dis., - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-11-6C (hex) Nanwang Multimedia Inc.,Ltd - 00116C (base 16) Nanwang Multimedia Inc.,Ltd - Floor 12,Tianyuan Bldg,Wensan Rd#508 - Hangzhou Zhejiang 310013 - CHINA - - 00-11-6D (hex) American Time and Signal - 00116D (base 16) American Time and Signal - 140 Third St. South - Dassel MN 55325 - UNITED STATES - - 00-11-6E (hex) PePLink Ltd. - 00116E (base 16) PePLink Ltd. - 17/F., Park Building - 476 Castle Peak Road - Cheung Sha Wan Kowloon - HONG KONG - - 00-11-6F (hex) Netforyou Co., LTD. - 00116F (base 16) Netforyou Co., LTD. - 1121-4 3F, Kwanyang-dong, Dongan-gu - Anyang-si Kyunggi-do 431-804 - KOREA, REPUBLIC OF - - 00-11-70 (hex) GSC SRL - 001170 (base 16) GSC SRL - VIA PER VIMERCATE - USMATE VELATE MILANO 20040 - ITALY - - 00-11-71 (hex) DEXTER Communications, Inc. - 001171 (base 16) DEXTER Communications, Inc. - 2F Shinsung B/D 404-1 - Backhyun-Dong, Bundang-Gu - Sungnam Gyunggi 463-420 - KOREA, REPUBLIC OF - - 00-11-72 (hex) COTRON CORPORATION - 001172 (base 16) COTRON CORPORATION - 12FL,No.150,Sec.4,Cheng-De Rd - ShihLin District - Taipei City 111 - TAIWAN, PROVINCE OF CHINA - - 00-11-73 (hex) SMART Storage Systems - 001173 (base 16) SMART Storage Systems - 39870 Eureka Drive - Newark CA 94560 - UNITED STATES - - 00-11-74 (hex) Wibhu Technologies, Inc. - 001174 (base 16) Wibhu Technologies, Inc. - 1561 Blackhawk Drive - Sunnyvale CA 94087 - UNITED STATES - - 00-11-75 (hex) Intel Corporation - 001175 (base 16) Intel Corporation - 5200 NE ELAM YOUNG PARKWAY - HIllsboro OR 97124 - UNITED STATES - - 00-11-76 (hex) Intellambda Systems, Inc. - 001176 (base 16) Intellambda Systems, Inc. - 48501 Warm Springs Blvd, #107 - Fremont California 94539 - UNITED STATES - - 00-11-77 (hex) Coaxial Networks, Inc. - 001177 (base 16) Coaxial Networks, Inc. - 4633 Old Ironsides Dr - Santa Clara CA 95054 - UNITED STATES - - 00-11-78 (hex) Chiron Technology Ltd - 001178 (base 16) Chiron Technology Ltd - Wyvols Court - Swallowfield - Reading Berkshire RG7 1WY - UNITED KINGDOM - - 00-11-79 (hex) Singular Technology Co. Ltd. - 001179 (base 16) Singular Technology Co. Ltd. - 21F, No.37, Sec.2, San Min Rd., - Pan Chiao City, Taipei County - Taipei 220 - TAIWAN, PROVINCE OF CHINA - - 00-11-7A (hex) Singim International Corp. - 00117A (base 16) Singim International Corp. - 6F-2, No. 190, Sec. 2 Chung Hsin Road, - Hsin Tien City 231 - TAIWAN, PROVINCE OF CHINA - - 00-11-7B (hex) Büchi Labortechnik AG - 00117B (base 16) Büchi Labortechnik AG - Meierseggstrasse 40 - Flawil 9230 SG - SWITZERLAND - - 00-11-7C (hex) e-zy.net - 00117C (base 16) e-zy.net - Smirnis 14 - Veria Imathia 59100 - GREECE - - 00-11-7D (hex) ZMD America, Inc. - 00117D (base 16) ZMD America, Inc. - 15373 Innovation Drive - Suite 115 - San Dieo CA 92128 - UNITED STATES - - 00-11-7E (hex) Progeny, A division of Midmark Corp - 00117E (base 16) Progeny, A division of Midmark Corp - 675 Heathrow Drive - Lincolnshire IL 60089 - UNITED STATES - - 00-11-7F (hex) Neotune Information Technology Corporation,.LTD - 00117F (base 16) Neotune Information Technology Corporation,.LTD - 1703# No.737 North of Caoxi Rd. - Shanghai 200030 - CHINA - - 00-11-80 (hex) ARRIS Group, Inc. - 001180 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-11-81 (hex) InterEnergy Co.Ltd, - 001181 (base 16) InterEnergy Co.Ltd, - 3F Shinyokohama Bosei Bldg. - 3-20-13 Shinyokohama Kohhoku-ku - Yokohama city Kanagawa 222-0033 - JAPAN - - 00-11-82 (hex) IMI Norgren Ltd - 001182 (base 16) IMI Norgren Ltd - PO Box 22 - Eastern Avenue - Lichfield Staffordshire WS13 6SB - UNITED KINGDOM - - 00-11-83 (hex) Datalogic ADC, Inc. - 001183 (base 16) Datalogic ADC, Inc. - 959 Terry St - Eugene OR 97402 - UNITED STATES - - 00-11-84 (hex) Humo Laboratory,Ltd. - 001184 (base 16) Humo Laboratory,Ltd. - Nishiogi-Kita 5-19-11 - Suginami-ku Tokyo 167-0042 - JAPAN - - 00-11-85 (hex) Hewlett-Packard Company - 001185 (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS070405 - Houston TX 77070 - UNITED STATES - - 00-11-86 (hex) Prime Systems, Inc. - 001186 (base 16) Prime Systems, Inc. - 16267-333 - Suwa-gun Hara-mura Nagano 391-0100 - JAPAN - - 00-11-87 (hex) Category Solutions, Inc - 001187 (base 16) Category Solutions, Inc - 1021 W. Adams St - Chicago IL 60607 - UNITED STATES - - 00-11-88 (hex) Enterasys - 001188 (base 16) Enterasys - 35 Industrial Way - Rochester NH 03867 - UNITED STATES - - 00-11-89 (hex) Aerotech Inc - 001189 (base 16) Aerotech Inc - 101 Zeta Drive - Pittsburgh PA 15238 - UNITED STATES - - 00-11-8A (hex) Viewtran Technology Limited - 00118A (base 16) Viewtran Technology Limited - 3/F, R2-A builiding, High Tech Industrial Park, - Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - 00-11-8B (hex) Alcatel-Lucent, Enterprise Business Group - 00118B (base 16) Alcatel-Lucent, Enterprise Business Group - 26801 West Agoura Road - Calabasas CA 91301 - UNITED STATES - - 00-11-8C (hex) Missouri Department of Transportation - 00118C (base 16) Missouri Department of Transportation - P.O. Box 270 - Jefferson City Missouri 65102 - UNITED STATES - - 00-11-8D (hex) Hanchang System Corp. - 00118D (base 16) Hanchang System Corp. - 1058-2, Shinkil-dong, Danwon-gu, - Ansan-si Gyeonggi-do 425-839 - KOREA, REPUBLIC OF - - 00-11-8E (hex) Halytech Mace - 00118E (base 16) Halytech Mace - Unit 11, 22 Lexington Drive - Norwest Business Park - Baulkham Hills NSW 2153 - AUSTRALIA - - 00-11-8F (hex) EUTECH INSTRUMENTS PTE. LTD. - 00118F (base 16) EUTECH INSTRUMENTS PTE. LTD. - Blk 55,Ayer Rajah Crescent, #04-16/24. - 139949 - SINGAPORE - - 00-11-90 (hex) Digital Design Corporation - 001190 (base 16) Digital Design Corporation - 3820 Ventura Drive - Arlington Heights IL 60004 - UNITED STATES - - 00-11-91 (hex) CTS-Clima Temperatur Systeme GmbH - 001191 (base 16) CTS-Clima Temperatur Systeme GmbH - Lotzenäcker 21 - Hechingen Baden-Württemberg 72379 - GERMANY - - 00-11-92 (hex) CISCO SYSTEMS, INC. - 001192 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-93 (hex) CISCO SYSTEMS, INC. - 001193 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-94 (hex) Chi Mei Communication Systems, Inc. - 001194 (base 16) Chi Mei Communication Systems, Inc. - 11F, No.39, Chung Hua RD. Sec 1 - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-11-95 (hex) D-Link Corporation - 001195 (base 16) D-Link Corporation - 2F No. 233-2, Pao-Chiao Road - Hsin-Tien - Taipei Taiwan - TAIWAN, PROVINCE OF CHINA - - 00-11-96 (hex) Actuality Systems, Inc. - 001196 (base 16) Actuality Systems, Inc. - 25 Corporate Drive - Suite 300 - Burlington MA 01803 - UNITED STATES - - 00-11-97 (hex) Monitoring Technologies Limited - 001197 (base 16) Monitoring Technologies Limited - 14 Attenburys Park Estate - Attenburys Lane - Timperley Cheshire WA14 5QE - UNITED KINGDOM - - 00-11-98 (hex) Prism Media Products Limited - 001198 (base 16) Prism Media Products Limited - William James House - Cowley Road - Cambridge Cambridgeshire CB4 0WX - UNITED KINGDOM - - 00-11-99 (hex) 2wcom Systems GmbH - 001199 (base 16) 2wcom Systems GmbH - Am Sophienhof 8 - Flensburg 24941 - GERMANY - - 00-11-9A (hex) Alkeria srl - 00119A (base 16) Alkeria srl - 25 Via Giuntini - Navacchio (PI) I-56023 - ITALY - - 00-11-9B (hex) Telesynergy Research Inc. - 00119B (base 16) Telesynergy Research Inc. - 4F, No. 49, Tung Hsin Rd., - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-11-9C (hex) EP&T Energy - 00119C (base 16) EP&T Energy - 358 Eastern Valley Way - Chatswood - Sydney NSW 2067 - AUSTRALIA - - 00-11-9D (hex) Diginfo Technology Corporation - 00119D (base 16) Diginfo Technology Corporation - 10Fl., No.82, Fu Hsing North Road - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-11-9E (hex) Solectron Brazil - 00119E (base 16) Solectron Brazil - Rod. Campinas Mogi Mirim - Bairro Roseira - Jaguariuna SP 13820-000 - BRAZIL - - 00-11-9F (hex) Nokia Danmark A/S - 00119F (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-11-A0 (hex) Vtech Engineering Canada Ltd - 0011A0 (base 16) Vtech Engineering Canada Ltd - 200-7671 Alderbridge Way - Richmond BC V6X 1Z9 - CANADA - - 00-11-A1 (hex) VISION NETWARE CO.,LTD - 0011A1 (base 16) VISION NETWARE CO.,LTD - Ace Twin Tower (2), #709 - 212-30, Guro-Dong - Seoul Guro-Gu 152-050 - KOREA, REPUBLIC OF - - 00-11-A2 (hex) Manufacturing Technology Inc - 0011A2 (base 16) Manufacturing Technology Inc - 70 Ready Ave NW - Fort Walton Beach FL 32548 - UNITED STATES - - 00-11-A3 (hex) LanReady Technologies Inc. - 0011A3 (base 16) LanReady Technologies Inc. - 4F, No. 337, SinHu 2nd Road., NeiHu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-11-A4 (hex) JStream Technologies Inc. - 0011A4 (base 16) JStream Technologies Inc. - Bldg.53, R405, 195 Sec.4, Chung Hsing Rd. - Chutung, Hsinchu 310 - TAIWAN, PROVINCE OF CHINA - - 00-11-A5 (hex) Fortuna Electronic Corp. - 0011A5 (base 16) Fortuna Electronic Corp. - 3F, No.9, Sec.1, ChangAn East Rd., - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-11-A6 (hex) Sypixx Networks - 0011A6 (base 16) Sypixx Networks - 108 Bank Street - Waterbury CT 06702 - UNITED STATES - - 00-11-A7 (hex) Infilco Degremont Inc. - 0011A7 (base 16) Infilco Degremont Inc. - 8007 Discovery Dr. - PO Box 71390 - Richmond Virginia 23255-1390 - UNITED STATES - - 00-11-A8 (hex) Quest Technologies - 0011A8 (base 16) Quest Technologies - 1060 Corporate Center Drive - Oconomowoc Wisconsin 53066 - UNITED STATES - - 00-11-A9 (hex) MOIMSTONE Co., LTD - 0011A9 (base 16) MOIMSTONE Co., LTD - 7th Floor JoongPyung Building 64-1 - Woomyun-Dong, Seocho-Gu - Seoul 137-900 - KOREA, REPUBLIC OF - - 00-11-AA (hex) Uniclass Technology, Co., LTD - 0011AA (base 16) Uniclass Technology, Co., LTD - 4F, No. 98, Ming chuan Rd - Hsintien City Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-11-AB (hex) TRUSTABLE TECHNOLOGY CO.,LTD. - 0011AB (base 16) TRUSTABLE TECHNOLOGY CO.,LTD. - 12FL.-1,NO.167,Fu-Shing N.Rd.,Sung-Shan area - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-11-AC (hex) Simtec Electronics - 0011AC (base 16) Simtec Electronics - Avondale Drive - Tarleton Lancashire PR4 6AX - UNITED KINGDOM - - 00-11-AD (hex) Shanghai Ruijie Technology - 0011AD (base 16) Shanghai Ruijie Technology - 27F, 420 Jiangning Rd. - Shanghai 200041 - CHINA - - 00-11-AE (hex) ARRIS Group, Inc. - 0011AE (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-11-AF (hex) Medialink-i,Inc - 0011AF (base 16) Medialink-i,Inc - 1-9-10 Hamamatsu-Cho - BELIEVE A HAMAMATSUCHO - Minato-Ku Tokyo 105-0013 - JAPAN - - 00-11-B0 (hex) Fortelink Inc. - 0011B0 (base 16) Fortelink Inc. - 42501 Albrae street suite 202 - Fremont CA 94538 - UNITED STATES - - 00-11-B1 (hex) BlueExpert Technology Corp. - 0011B1 (base 16) BlueExpert Technology Corp. - 8F,No.16,Lane 77,Xing-Ai Rd,Nei-Hu District - Taipei 11494 - TAIWAN, PROVINCE OF CHINA - - 00-11-B2 (hex) 2001 Technology Inc. - 0011B2 (base 16) 2001 Technology Inc. - 7F-10, 79 Hsin Tai 5th. Rd. Sec.1 - Hsi Chih Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-11-B3 (hex) YOSHIMIYA CO.,LTD. - 0011B3 (base 16) YOSHIMIYA CO.,LTD. - 2-3-24 Bainan - Nishinari-ku - OSAKA OSAKA-Pref 557-0033 - JAPAN - - 00-11-B4 (hex) Westermo Teleindustri AB - 0011B4 (base 16) Westermo Teleindustri AB - Stora Sundby - SE-640 40 - SWEDEN - - 00-11-B5 (hex) Shenzhen Powercom Co.,Ltd - 0011B5 (base 16) Shenzhen Powercom Co.,Ltd - Floor 16,Tower B,Zhongyin Building,North Caitian Road,Futian District,Shenzhen,P.R.China - Shenzhen Guangdong province 518028 - CHINA - - 00-11-B6 (hex) Open Systems International - 0011B6 (base 16) Open Systems International - 3600 Holly Lane North - Suite 40 - Minneapolis MN 55447 - UNITED STATES - - 00-11-B7 (hex) Octalix B.V. - 0011B7 (base 16) Octalix B.V. - Molensteijn 60 - De Meern NL-3454 PT - NETHERLANDS - - 00-11-B8 (hex) Liebherr - Elektronik GmbH - 0011B8 (base 16) Liebherr - Elektronik GmbH - Peter - Dornier - Strasse 11 - Lindau (Bodensee) Bavaria 88131 - GERMANY - - 00-11-B9 (hex) Inner Range Pty. Ltd. - 0011B9 (base 16) Inner Range Pty. Ltd. - 1 Millenium Court - Knoxfield Victoria 3180 - AUSTRALIA - - 00-11-BA (hex) Elexol Pty Ltd - 0011BA (base 16) Elexol Pty Ltd - Level 2 / 146 Bundall Road - Bundall Queensland 4217 - AUSTRALIA - - 00-11-BB (hex) CISCO SYSTEMS, INC. - 0011BB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-BC (hex) CISCO SYSTEMS, INC. - 0011BC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-11-BD (hex) Bombardier Transportation - 0011BD (base 16) Bombardier Transportation - 1501 Lebanon Church Road - Pittsburgh PA 15236 - UNITED STATES - - 00-11-BE (hex) AGP Telecom Co. Ltd - 0011BE (base 16) AGP Telecom Co. Ltd - 9F, 134 Chung-Hsiao E. RD - Sec. 4 - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-11-BF (hex) AESYS S.p.A. - 0011BF (base 16) AESYS S.p.A. - Via Artigiani, 41 - Brusaporto Bergamo 24060 - ITALY - - 00-11-C0 (hex) Aday Technology Inc - 0011C0 (base 16) Aday Technology Inc - 9F.-3, No. 247, Sec. 1, Taichung Port Rd., - Taichung City Taiw 403 - TAIWAN, PROVINCE OF CHINA - - 00-11-C1 (hex) 4P MOBILE DATA PROCESSING - 0011C1 (base 16) 4P MOBILE DATA PROCESSING - VIALE REGIONE VENETO 26 - PADOVA PD 35127 - ITALY - - 00-11-C2 (hex) United Fiber Optic Communication - 0011C2 (base 16) United Fiber Optic Communication - 13-1,NO.700,Jungjeng RD,Junghe City - Junghe City Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-11-C3 (hex) Transceiving System Technology Corporation - 0011C3 (base 16) Transceiving System Technology Corporation - NO.85,Sec.2,Gongdaowu Rd., - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-11-C4 (hex) Terminales de Telecomunicacion Terrestre, S.L. - 0011C4 (base 16) Terminales de Telecomunicacion Terrestre, S.L. - Poligono Europolis, Calle C 26 - Las Rozas Madrid 28230 - SPAIN - - 00-11-C5 (hex) TEN Technology - 0011C5 (base 16) TEN Technology - 555 East Ocean Blvd. - 9th Floor - Long Beach CA 90802 - UNITED STATES - - 00-11-C6 (hex) Seagate Technology - 0011C6 (base 16) Seagate Technology - M/S NW1F01 - 389 Disc Drive - Longmont CO 80503 - UNITED STATES - - 00-11-C7 (hex) Raymarine UK Ltd - 0011C7 (base 16) Raymarine UK Ltd - Marine House - Cartwright Drive - Fareham Hampshire PO15 5RJ - UNITED KINGDOM - - 00-11-C8 (hex) Powercom Co., Ltd. - 0011C8 (base 16) Powercom Co., Ltd. - 8F, No. 246, Lien Chen Rd. - Chung Ho Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-11-C9 (hex) MTT Corporation - 0011C9 (base 16) MTT Corporation - 2-7-12 - Murotani - Nishi-ku Kobe 651-2241 - JAPAN - - 00-11-CA (hex) Long Range Systems, Inc. - 0011CA (base 16) Long Range Systems, Inc. - 4550 Excel Parkway - Suite 200 - Addison Texas 75001 - UNITED STATES - - 00-11-CB (hex) Jacobsons AB - 0011CB (base 16) Jacobsons AB - Nedralid s 32 - Motala 591 97 - SWEDEN - - 00-11-CC (hex) Guangzhou Jinpeng Group Co.,Ltd. - 0011CC (base 16) Guangzhou Jinpeng Group Co.,Ltd. - No.9 Shenzhou Road,Guangzhou Science City - Guangzhou Guangdong 510663 - CHINA - - 00-11-CD (hex) Axsun Technologies - 0011CD (base 16) Axsun Technologies - 1 Fortune Drive - Billerica MA 02460 - UNITED STATES - - 00-11-CE (hex) Ubisense Limited - 0011CE (base 16) Ubisense Limited - St. Andrews House - St. Andrews Road - Chesterton Cambridge CB4 1DL - UNITED KINGDOM - - 00-11-CF (hex) Thrane & Thrane A/S - 0011CF (base 16) Thrane & Thrane A/S - LundtoftegÃ¥rdsvej 93D - Lyngby København 2800 - DENMARK - - 00-11-D0 (hex) Tandberg Data ASA - 0011D0 (base 16) Tandberg Data ASA - KjelsÃ¥sveien 161 - Oslo 0411 - NORWAY - - 00-11-D1 (hex) Soft Imaging System GmbH - 0011D1 (base 16) Soft Imaging System GmbH - Johann-Krane-Weg 39 - Muenster 48149 - GERMANY - - 00-11-D2 (hex) Perception Digital Ltd - 0011D2 (base 16) Perception Digital Ltd - Flat A, 8/F, Shaw House - RM A - Clear Water Bay NT - HONG KONG - - 00-11-D3 (hex) NextGenTel Holding ASA - 0011D3 (base 16) NextGenTel Holding ASA - Sandslimarka 31 - Sandsli - Bergen Hordaland 5861 - NORWAY - - 00-11-D4 (hex) NetEnrich, Inc - 0011D4 (base 16) NetEnrich, Inc - 890 Hillview Ct. - Suite 150 - Milpitas CA 95035 - UNITED STATES - - 00-11-D5 (hex) Hangzhou Sunyard System Engineering Co.,Ltd. - 0011D5 (base 16) Hangzhou Sunyard System Engineering Co.,Ltd. - Sunyard Science & Technology Building Hi-Tech Software Park(Second Land Consolidation) - Hangzhou Hi-Tech Industrial Development Zone(Binjiang District) - Hangzhou Zhejiang 310053 - CHINA - - 00-11-D6 (hex) HandEra, Inc. - 0011D6 (base 16) HandEra, Inc. - 2859 104th St. - Des Moines IA 50322 - UNITED STATES - - 00-11-D7 (hex) eWerks Inc - 0011D7 (base 16) eWerks Inc - 420-2166 Mountain Grove Ave - Burlington Ontario L7P4X4 - CANADA - - 00-11-D8 (hex) ASUSTek Computer Inc. - 0011D8 (base 16) ASUSTek Computer Inc. - No. 15, Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-11-D9 (hex) TiVo - 0011D9 (base 16) TiVo - 2160 Gold Ave - Alviso CA 95002-2160 - UNITED STATES - - 00-11-DA (hex) Vivaas Technology Inc. - 0011DA (base 16) Vivaas Technology Inc. - 15F, No. 10, Sec 1, Pei-Hsin Rd., - Hsin-Tien city Taipei Hsien, 231 - TAIWAN, PROVINCE OF CHINA - - 00-11-DB (hex) Land-Cellular Corporation - 0011DB (base 16) Land-Cellular Corporation - 12054 Miramar Parkway - Miramar FL 33025 - UNITED STATES - - 00-11-DC (hex) Glunz & Jensen - 0011DC (base 16) Glunz & Jensen - Selandia Park 1 - Ringsted 4100 - DENMARK - - 00-11-DD (hex) FROMUS TEC. Co., Ltd. - 0011DD (base 16) FROMUS TEC. Co., Ltd. - 2F 896-8 Hogye2-dong Dongan-Gu - Anyang-City, Gyeonggi-do, - 431-836 - KOREA, REPUBLIC OF - - 00-11-DE (hex) EURILOGIC - 0011DE (base 16) EURILOGIC - Centrale Parc Bât 7 - Avenue sully prud'homme - Chatenay Malabry 92298 - FRANCE - - 00-11-DF (hex) Current Energy - 0011DF (base 16) Current Energy - 5440 Harvest Hill, Ste 100 - Dallas TX 75230 - UNITED STATES - - 00-11-E0 (hex) U-MEDIA Communications, Inc. - 0011E0 (base 16) U-MEDIA Communications, Inc. - 9F, No.1 Jin-Shan St. - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-11-E1 (hex) Arcelik A.S - 0011E1 (base 16) Arcelik A.S - Cumhuriyet Mah., E5 Yan Yol, No:1, - Beylikduzu - Istanbul 34520 - TURKEY - - 00-11-E2 (hex) Hua Jung Components Co., Ltd. - 0011E2 (base 16) Hua Jung Components Co., Ltd. - 5F, No.13, Lane 120, Sec.1, Nei Hu Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-11-E3 (hex) Thomson, Inc. - 0011E3 (base 16) Thomson, Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 00-11-E4 (hex) Danelec Electronics A/S - 0011E4 (base 16) Danelec Electronics A/S - Blokken 44 - Birkeroed Copenhagen 3460 - DENMARK - - 00-11-E5 (hex) KCodes Corporation - 0011E5 (base 16) KCodes Corporation - Floor 2, Number 501, Section 2 - Tiding Boulevard - Neihu District Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-11-E6 (hex) Scientific Atlanta - 0011E6 (base 16) Scientific Atlanta - 5030 Sugarloaf Parkway - Mail Stop 5.2.428 - Lawrenceville Ga 30042 - UNITED STATES - - 00-11-E7 (hex) WORLDSAT - Texas de France - 0011E7 (base 16) WORLDSAT - Texas de France - 220, rue Gustave Eiffel - cedex 3 - Aix en Provence Bouches du Rhone 13854 - FRANCE - - 00-11-E8 (hex) Tixi.Com - 0011E8 (base 16) Tixi.Com - Karmeliterweg 114 - Berlin 13465 - GERMANY - - 00-11-E9 (hex) STARNEX CO., LTD. - 0011E9 (base 16) STARNEX CO., LTD. - 4th Floor, C&C Bldg, 228-2 - Guui-dong - Kwangjin-gu Seoul 143-200 - KOREA, REPUBLIC OF - - 00-11-EA (hex) IWICS Inc. - 0011EA (base 16) IWICS Inc. - 19125 North Creek Parkway - Suite 120 - Bothell WA 98011 - UNITED STATES - - 00-11-EB (hex) Innovative Integration - 0011EB (base 16) Innovative Integration - 2390A Ward Avenue - Simi Valley CA 93065 - UNITED STATES - - 00-11-EC (hex) AVIX INC. - 0011EC (base 16) AVIX INC. - 1-1, Fukuura, Kanazawa-ku - Yokohama-shi Kanagawa 236-0004 - JAPAN - - 00-11-ED (hex) 802 Global - 0011ED (base 16) 802 Global - Studio 11,Intec 2,Wade Road - Basingstoke, - Hampshire RG24 BNE - UNITED KINGDOM - - 00-11-EE (hex) Estari, Inc. - 0011EE (base 16) Estari, Inc. - 1800 Paxton St - Harrisburg PA 17104 - UNITED STATES - - 00-11-EF (hex) Conitec Datensysteme GmbH - 0011EF (base 16) Conitec Datensysteme GmbH - Dieselstraße 11c - Dieburg Hessen 64807 - GERMANY - - 00-11-F0 (hex) Wideful Limited - 0011F0 (base 16) Wideful Limited - F5, 3/F., Phase II, Superluck Industrial Centre, - 57 Sha Tsui Road, Tsuen Wan, - HONG KONG - - 00-11-F1 (hex) QinetiQ Ltd - 0011F1 (base 16) QinetiQ Ltd - Room E601 - St. Andrew's Road - Malvern Worcestershire WR14 3PS - UNITED KINGDOM - - 00-11-F2 (hex) Institute of Network Technologies - 0011F2 (base 16) Institute of Network Technologies - 17-th Line Vasilevsky Ostrov, 54-1 - St.Petersburg 199178 - RUSSIAN FEDERATION - - 00-11-F3 (hex) NeoMedia Europe AG - 0011F3 (base 16) NeoMedia Europe AG - Jens-Otto-Krag-Straße 11 - Würselen Nordrhein-Westfalen 52146 - GERMANY - - 00-11-F4 (hex) woori-net - 0011F4 (base 16) woori-net - #508, Hankook Moolyu, 853-1 Dongchun-Dong - Yongin-Si Kyungki-Do 449-843 - KOREA, REPUBLIC OF - - 00-11-F5 (hex) ASKEY COMPUTER CORP. - 0011F5 (base 16) ASKEY COMPUTER CORP. - 10F, NO.119, CHIENKANG RD., - CHUNG-HO, TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - 00-11-F6 (hex) Asia Pacific Microsystems , Inc. - 0011F6 (base 16) Asia Pacific Microsystems , Inc. - No.2,R&D Road 6 ,Science-Based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-11-F7 (hex) Shenzhen Forward Industry Co., Ltd - 0011F7 (base 16) Shenzhen Forward Industry Co., Ltd - 4b1 F5.8, Tian An Cyber Park, Chengongmiao, - Shenzhen Guangdong 518040 - CHINA - - 00-11-F8 (hex) AIRAYA Corp - 0011F8 (base 16) AIRAYA Corp - 637 Adair Court - Morgan Hill CA 95037 - UNITED STATES - - 00-11-F9 (hex) Nortel Networks - 0011F9 (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-11-FA (hex) Rane Corporation - 0011FA (base 16) Rane Corporation - 10802 47th Avenue West - Mukilteo WA 98275-5098 - UNITED STATES - - 00-11-FB (hex) Heidelberg Engineering GmbH - 0011FB (base 16) Heidelberg Engineering GmbH - Tiergartenstraße 15 - Heidelberg Baden-Württemberg 69121 - GERMANY - - 00-11-FC (hex) HARTING Electric Gmbh & Co.KG - 0011FC (base 16) HARTING Electric Gmbh & Co.KG - Wilhelm Harting Str. 1 - Espelkamp Nordrhein Westfalen D-32339 - GERMANY - - 00-11-FD (hex) KORG INC. - 0011FD (base 16) KORG INC. - 4015-2, Yanokuchi - Inagi-City TOKYO 206-0812 - JAPAN - - 00-11-FE (hex) Keiyo System Research, Inc. - 0011FE (base 16) Keiyo System Research, Inc. - Hamada park Bldg. 6F - 17-3 Shinmachi Chuou-ku - Chiba-city Chiba-pref 260-0028 - JAPAN - - 00-11-FF (hex) Digitro Tecnologia Ltda - 0011FF (base 16) Digitro Tecnologia Ltda - Rua: Professora Sofia Quint de Souza, 167 - Bairro: Capoeiras - Florianópolis Santa Catarina 88085-040 - BRAZIL - - 00-12-00 (hex) CISCO SYSTEMS, INC. - 001200 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-01 (hex) CISCO SYSTEMS, INC. - 001201 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-02 (hex) Decrane Aerospace - Audio International Inc. - 001202 (base 16) Decrane Aerospace - Audio International Inc. - 7300 Industry Drive - North Little Rock AR 72117 - UNITED STATES - - 00-12-03 (hex) ActivNetworks - 001203 (base 16) ActivNetworks - BAT L - 1 rue de Terre Neuve - BP127 - COURTABOEUF 91944 - FRANCE - - 00-12-04 (hex) u10 Networks, Inc. - 001204 (base 16) u10 Networks, Inc. - 2-2-14 Kakinokizaka - Meguro Tokyo 152-0022 - JAPAN - - 00-12-05 (hex) Terrasat Communications, Inc. - 001205 (base 16) Terrasat Communications, Inc. - 235 Vineyard Court, suite 100 - Morgan Hill California 95037 - UNITED STATES - - 00-12-06 (hex) iQuest (NZ) Ltd - 001206 (base 16) iQuest (NZ) Ltd - P.O.Box 15169 - Dinsdale - Hamilton Waikato 3243 - NEW ZEALAND - - 00-12-07 (hex) Head Strong International Limited - 001207 (base 16) Head Strong International Limited - Unit 9, 20/F, Metropole Square, - 2 On Yiu Street, Shatin - Guangdong - HONG KONG - - 00-12-08 (hex) Gantner Instruments GmbH - 001208 (base 16) Gantner Instruments GmbH - Montafonerstrasse 8 - Schruns Vorarlberg 6780 - AUSTRIA - - 00-12-09 (hex) Fastrax Ltd - 001209 (base 16) Fastrax Ltd - Valimotie 7 - Vantaa FI 01510 - FINLAND - - 00-12-0A (hex) Emerson Climate Technologies GmbH - 00120A (base 16) Emerson Climate Technologies GmbH - Heerstrasse 111 - Waiblingen BW 71332 - GERMANY - - 00-12-0B (hex) Chinasys Technologies Limited - 00120B (base 16) Chinasys Technologies Limited - 10/F,CAGW Building,No.30 Haidian South Road - Beijing 100080 - CHINA - - 00-12-0C (hex) CE-Infosys Pte Ltd - 00120C (base 16) CE-Infosys Pte Ltd - 390 Havelock Road - #08-02 King's Centre - 169662 - SINGAPORE - - 00-12-0D (hex) Advanced Telecommunication Technologies, Inc. - 00120D (base 16) Advanced Telecommunication Technologies, Inc. - 10390 Wilshire Boulevard - Suite 1803 - Los Angeles California 90024 - UNITED STATES - - 00-12-0E (hex) AboCom - 00120E (base 16) AboCom - 1F , No. 21, Yanfa 2nd Rd., SBIP - Hsinchu City 300 - TAIWAN, PROVINCE OF CHINA - - 00-12-0F (hex) IEEE 802.3 - 00120F (base 16) IEEE 802.3 - - Argyll Villa, Albert Road - Oban PA34 5EJ - UNITED KINGDOM - - 00-12-10 (hex) WideRay Corp - 001210 (base 16) WideRay Corp - 25 Kearny Street - 6th Floor - San Francisco CA 94108 - UNITED STATES - - 00-12-11 (hex) Protechna Herbst GmbH & Co. KG - 001211 (base 16) Protechna Herbst GmbH & Co. KG - Otto Hahn Str. 26 - Ottobrunn Germany/Bavaria 85521 - GERMANY - - 00-12-12 (hex) PLUS Corporation - 001212 (base 16) PLUS Corporation - 1033-1, Oshitate - Inagi-shi Tokyo 206-0811 - JAPAN - - 00-12-13 (hex) Metrohm AG - 001213 (base 16) Metrohm AG - Oberdorfstrasse 68 - Herisau AR 9101 - SWITZERLAND - - 00-12-14 (hex) Koenig & Bauer AG - 001214 (base 16) Koenig & Bauer AG - Friedrich-Koenig-Str. 4 - Wuerzburg Bavaria 97080 - GERMANY - - 00-12-15 (hex) iStor Networks, Inc. - 001215 (base 16) iStor Networks, Inc. - 7585 Irvine Center Drive - Suite 250 - Irvine CA 92618 - UNITED STATES - - 00-12-16 (hex) ICP Internet Communication Payment AG - 001216 (base 16) ICP Internet Communication Payment AG - Wilhelm-Stein-Weg 24 - Hamburg D-22339 - GERMANY - - 00-12-17 (hex) Cisco-Linksys, LLC - 001217 (base 16) Cisco-Linksys, LLC - 121 Theory Dr. - Irvine CA 92612 - UNITED STATES - - 00-12-18 (hex) ARUZE Corporation - 001218 (base 16) ARUZE Corporation - Ariake Frontier Building A - 3-1-25 Ariake - Kohtoh-ku Tokyo 135-0063 - JAPAN - - 00-12-19 (hex) Ahead Communication Systems Inc - 001219 (base 16) Ahead Communication Systems Inc - 199 Park Road Ext - PO Box 929 - Middlebury CT 06762 - UNITED STATES - - 00-12-1A (hex) Techno Soft Systemnics Inc. - 00121A (base 16) Techno Soft Systemnics Inc. - 2-5-17, Ebisu-nishi, Naniwa-ku, - Osaka 556-0003 - JAPAN - - 00-12-1B (hex) Sound Devices, LLC - 00121B (base 16) Sound Devices, LLC - 300 Wengel Drive - Reedsburg WI 53959 - UNITED STATES - - 00-12-1C (hex) PARROT S.A. - 00121C (base 16) PARROT S.A. - 174, quai de Jemmapes - PARIS 75010 - FRANCE - - 00-12-1D (hex) Netfabric Corporation - 00121D (base 16) Netfabric Corporation - 67 Federal Road - Suite 300 - Brookfield CT 06804 - UNITED STATES - - 00-12-1E (hex) Juniper Networks, Inc. - 00121E (base 16) Juniper Networks, Inc. - 1194 N. Mathilda Avenue - Sunnyvale CA 94010 - UNITED STATES - - 00-12-1F (hex) Harding Instruments - 00121F (base 16) Harding Instruments - 9431-41Ave - Edmonton AB T6E 5X7 - CANADA - - 00-12-20 (hex) Cadco Systems - 001220 (base 16) Cadco Systems - 2363 Merritt Dr - Garland Texas 75041 - UNITED STATES - - 00-12-21 (hex) B.Braun Melsungen AG - 001221 (base 16) B.Braun Melsungen AG - Schwarzenberger Weg 73-79 - Melsungen Hessen 34212 - GERMANY - - 00-12-22 (hex) Skardin (UK) Ltd - 001222 (base 16) Skardin (UK) Ltd - No. 5 Greenway (RO24) - Harlow Business Park - Harlow Essex CM19 5QB - UNITED KINGDOM - - 00-12-23 (hex) Pixim - 001223 (base 16) Pixim - 915 Linda Vista Ave. - Mountain View CA 94043 - UNITED STATES - - 00-12-24 (hex) NexQL Corporation - 001224 (base 16) NexQL Corporation - 12250 Inwood Road #6 - Dallas TX 75244 - UNITED STATES - - 00-12-25 (hex) ARRIS Group, Inc. - 001225 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-12-26 (hex) Japan Direx Corporation - 001226 (base 16) Japan Direx Corporation - Kyocera Harajuku Bldg. - 6-27-8, Jingumae - Shibuya-ku Tokyo 150-0001 - JAPAN - - 00-12-27 (hex) Franklin Electric Co., Inc. - 001227 (base 16) Franklin Electric Co., Inc. - 400 E. Spring Street - Bluffton Indiana 46714 - UNITED STATES - - 00-12-28 (hex) Data Ltd. - 001228 (base 16) Data Ltd. - J. Hagaru 9 - P.O. Box 7 - Bratislava 830 05 - SLOVAKIA - - 00-12-29 (hex) BroadEasy Technologies Co.,Ltd - 001229 (base 16) BroadEasy Technologies Co.,Ltd - 24th Floor,Tower A,JinShan Mansion, - NO.8 ShanXi Road,Nanjing,P.R.C. - Nanjing Jiangsu 210009 - CHINA - - 00-12-2A (hex) VTech Telecommunications Ltd. - 00122A (base 16) VTech Telecommunications Ltd. - 23/F, Tai Ping Industrial Centre, Block 1 - 57 Ting Kok Road, Tai Po - HONG KONG - - 00-12-2B (hex) Virbiage Pty Ltd - 00122B (base 16) Virbiage Pty Ltd - Level 4 - 8 Market Street - Melbourne Victoria 3000 - AUSTRALIA - - 00-12-2C (hex) Soenen Controls N.V. - 00122C (base 16) Soenen Controls N.V. - Wijnedalestraat 190 - Roeselare W-VL 8800 - BELGIUM - - 00-12-2D (hex) SiNett Corporation - 00122D (base 16) SiNett Corporation - 640 W. California Avenue - Sunnyvale CA 94086 - UNITED STATES - - 00-12-2E (hex) Signal Technology - AISD - 00122E (base 16) Signal Technology - AISD - 1820 Preston Park Blvd. - Suite 2800 - Plano TX 75093 - UNITED STATES - - 00-12-2F (hex) Sanei Electric Inc. - 00122F (base 16) Sanei Electric Inc. - 5F Taisou-Ikebukuro Bldg. - 2-61-1 Ikebukuro - Toshima-ku Tokyo 171-0014 - JAPAN - - 00-12-30 (hex) Picaso Infocommunication CO., LTD. - 001230 (base 16) Picaso Infocommunication CO., LTD. - 3F, Suntechcity, Sangdaewon 1-dong, - 513-15, Jungwon-gu - Sungnam-city Kyunggi-do 462-725 - KOREA, REPUBLIC OF - - 00-12-31 (hex) Motion Control Systems, Inc. - 001231 (base 16) Motion Control Systems, Inc. - PO Box 115 - 6701 Viscoe Road - New River VA 24129 - UNITED STATES - - 00-12-32 (hex) LeWiz Communications Inc. - 001232 (base 16) LeWiz Communications Inc. - 1376 N. 4th St. #300 - San Jose CA 95112 - UNITED STATES - - 00-12-33 (hex) JRC TOKKI Co.,Ltd. - 001233 (base 16) JRC TOKKI Co.,Ltd. - 3-2-1 Shinyoshidahigashi Kohoku-ku - Yokohama Kanagawa 223-8572 - JAPAN - - 00-12-34 (hex) Camille Bauer - 001234 (base 16) Camille Bauer - Aargauerstr. 7 - Wohlen AG 5610 - SWITZERLAND - - 00-12-35 (hex) Andrew Corporation - 001235 (base 16) Andrew Corporation - 2601 Telecom Pkwy - Richardson TX 75082 - UNITED STATES - - 00-12-36 (hex) ConSentry Networks - 001236 (base 16) ConSentry Networks - 1690 McCandless Dr - Milipitas CA 95035 - UNITED STATES - - 00-12-37 (hex) Texas Instruments - 001237 (base 16) Texas Instruments - 12500 TI Boulevard, - MS 8723 - Dallas Texas 75243 - UNITED STATES - - 00-12-38 (hex) SetaBox Technology Co., Ltd. - 001238 (base 16) SetaBox Technology Co., Ltd. - 9F-1, No. 293-3, Sec2, Fu-Hsing S. Rd. - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-12-39 (hex) S Net Systems Inc. - 001239 (base 16) S Net Systems Inc. - 10F Sungwon Bldg. Samsung-dong - Gangnam-gu - Seoul 135-090 - KOREA, REPUBLIC OF - - 00-12-3A (hex) Posystech Inc., Co. - 00123A (base 16) Posystech Inc., Co. - Room 407, Daeryung Techno Town 6, - 493-6, Gasan-Dong, Geumcheon-Gu, - Seoul 153-771 - KOREA, REPUBLIC OF - - 00-12-3B (hex) KeRo Systems ApS - 00123B (base 16) KeRo Systems ApS - Allikevej 3 - Hørsholm 2970 - DENMARK - - 00-12-3C (hex) Second Rule LLC - 00123C (base 16) Second Rule LLC - 4119 Walnut Street - Suite 200 - Philadelphia PA 19104 - UNITED STATES - - 00-12-3D (hex) GES Co, Ltd - 00123D (base 16) GES Co, Ltd - Room 710, Bundang Technopark, 700 - Pangyo-Ro, Bundang-Gu, Seongnam-Si - Gyeonggi-Do 463-400 - KOREA, REPUBLIC OF - - 00-12-3E (hex) ERUNE technology Co., Ltd. - 00123E (base 16) ERUNE technology Co., Ltd. - No. 429, Chin-San 2nd street, - Yang-Mei - Tao Yuan 326 - TAIWAN, PROVINCE OF CHINA - - 00-12-3F (hex) Dell Inc - 00123F (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-12-40 (hex) AMOI ELECTRONICS CO.,LTD - 001240 (base 16) AMOI ELECTRONICS CO.,LTD - 295 Lane,Zuchongzhi Road,Zhang jiang, - Shanghai 201203 - CHINA - - 00-12-41 (hex) a2i marketing center - 001241 (base 16) a2i marketing center - 1024-4 Duksan Bldg Bangbaedong Seochogu Seoul Korea - SEOUL 137-060 - KOREA, REPUBLIC OF - - 00-12-42 (hex) Millennial Net - 001242 (base 16) Millennial Net - 285 Billerica Road - Chelmsford MA 01803 - UNITED STATES - - 00-12-43 (hex) CISCO SYSTEMS, INC. - 001243 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-44 (hex) CISCO SYSTEMS, INC. - 001244 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-45 (hex) Zellweger Analytics, Inc. - 001245 (base 16) Zellweger Analytics, Inc. - 405 Barclay Blvd. - Lincolnshire Illinois 60069 - UNITED STATES - - 00-12-46 (hex) T.O.M TECHNOLOGY INC.. - 001246 (base 16) T.O.M TECHNOLOGY INC.. - 906 Woolim E-biz Center 2, - Guro-3Dong - Seoul Guro-Gu 184-1 - KOREA, REPUBLIC OF - - 00-12-47 (hex) Samsung Electronics Co., Ltd. - 001247 (base 16) Samsung Electronics Co., Ltd. - #94-1, Imsoo-Dong - Gumi-City Gyeong-Buk 730-350 - KOREA, REPUBLIC OF - - 00-12-48 (hex) EMC Corporation (Kashya) - 001248 (base 16) EMC Corporation (Kashya) - 176 South Street - Hopkinton MA 01748 - UNITED STATES - - 00-12-49 (hex) Delta Elettronica S.p.A. - 001249 (base 16) Delta Elettronica S.p.A. - Via Astico 41 - Varese 21100 - ITALY - - 00-12-4A (hex) Dedicated Devices, Inc. - 00124A (base 16) Dedicated Devices, Inc. - 5680 E. Franklin - Suite 250 - Nampa Idaho 83687 - UNITED STATES - - 00-12-4B (hex) Texas Instruments - 00124B (base 16) Texas Instruments - Gaustadalleen 21 - Texas Instruments Norway AS - Oslo N-0349 - NORWAY - - 00-12-4C (hex) BBWM Corporation - 00124C (base 16) BBWM Corporation - 6F, No. 578, Rui Guang Road, Nei Hu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-12-4D (hex) Inducon BV - 00124D (base 16) Inducon BV - Kerklaan 26 - Leimuiden ZH 2541 CG - NETHERLANDS - - 00-12-4E (hex) XAC AUTOMATION CORP. - 00124E (base 16) XAC AUTOMATION CORP. - 4F, 30 Industry E. Road IX - Science Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-12-4F (hex) Pentair Thermal Management - 00124F (base 16) Pentair Thermal Management - 11004 - 174 St. - Edmonton Alberta T5S 2P3 - CANADA - - 00-12-50 (hex) Tokyo Aircaft Instrument Co., Ltd. - 001250 (base 16) Tokyo Aircaft Instrument Co., Ltd. - 1-35-1, Izumi-Honcho - Komae-Shi Tokyo 201-8555 - JAPAN - - 00-12-51 (hex) SILINK - 001251 (base 16) SILINK - 13 RUE POMEYS - LE TAILLAN 33320 - FRANCE - - 00-12-52 (hex) Citronix, LLC - 001252 (base 16) Citronix, LLC - 2214 South Watson Road - Bldg 200 Suite 111 - Arlington Texas 76010 - UNITED STATES - - 00-12-53 (hex) AudioDev AB - 001253 (base 16) AudioDev AB - Kabingatan 9 - Malmö SE-212 39 - SWEDEN - - 00-12-54 (hex) Spectra Technologies Holdings Company Ltd - 001254 (base 16) Spectra Technologies Holdings Company Ltd - Unit 1301-09, Tower II - Pacific Century Place, Mongkok - 852 - HONG KONG - - 00-12-55 (hex) NetEffect Incorporated - 001255 (base 16) NetEffect Incorporated - 9211 Waterford Centre Blvd - Suite 100 - Austin Texas 78758 - UNITED STATES - - 00-12-56 (hex) LG INFORMATION & COMM. - 001256 (base 16) LG INFORMATION & COMM. - 459-9,KASAN-DONG,KUMCHON-GU, - SEOUL 153-023 - KOREA, REPUBLIC OF - - 00-12-57 (hex) LeapComm Communication Technologies Inc. - 001257 (base 16) LeapComm Communication Technologies Inc. - RM1804-05 South Tower Hong Kong Plaza, No.283 Huaihai Zhong Road - Shanghai 200021 - CHINA - - 00-12-58 (hex) Activis Polska - 001258 (base 16) Activis Polska - Swierzawska 5 - Poznan Wielkopolska 60-321 - POLAND - - 00-12-59 (hex) THERMO ELECTRON KARLSRUHE - 001259 (base 16) THERMO ELECTRON KARLSRUHE - DIESELSTRAßE 4 - KARLSRUHE Baden-Württemberg 76227 - GERMANY - - 00-12-5A (hex) Microsoft Corporation - 00125A (base 16) Microsoft Corporation - One Microsoft Way - Redmond Washington 98052-6399 - UNITED STATES - - 00-12-5B (hex) KAIMEI ELECTRONI - 00125B (base 16) KAIMEI ELECTRONI - 14-3F, NO.81,SEC. 1,HSIN-TAI-WU ROAD,HSICHIH, - TAIPEI HSIEN HSICHIH 221 - TAIWAN, PROVINCE OF CHINA - - 00-12-5C (hex) Green Hills Software, Inc. - 00125C (base 16) Green Hills Software, Inc. - 30 West Sola Street - Santa Barbara CA 93101 - UNITED STATES - - 00-12-5D (hex) CyberNet Inc. - 00125D (base 16) CyberNet Inc. - #205, Lotte Suntech City, 513-15 - Sangdaewon-dong, Chungwon-gu - Sungnam Kyunggi 462-806 - KOREA, REPUBLIC OF - - 00-12-5E (hex) CAEN - 00125E (base 16) CAEN - via Vetraia, 11 - Viareggio LUCCA 55049 - ITALY - - 00-12-5F (hex) AWIND Inc. - 00125F (base 16) AWIND Inc. - 17F., No. 886-5, Jungjeng Rd - Junghe City - Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-12-60 (hex) Stanton Magnetics,inc. - 001260 (base 16) Stanton Magnetics,inc. - 3000 SW 42nd Street - Hollywood FL 33312 - UNITED STATES - - 00-12-61 (hex) Adaptix, Inc - 001261 (base 16) Adaptix, Inc - 1407 116th Ave. NE - Suite E210 - Bellevue WA 98004 - UNITED STATES - - 00-12-62 (hex) Nokia Danmark A/S - 001262 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-12-63 (hex) Data Voice Technologies GmbH - 001263 (base 16) Data Voice Technologies GmbH - Stockholmer Allee 32b - Dortmund NRW D-44269 - GERMANY - - 00-12-64 (hex) daum electronic gmbh - 001264 (base 16) daum electronic gmbh - flugplatzstraße 100 - Fuerth Bavaria 90768 - GERMANY - - 00-12-65 (hex) Enerdyne Technologies, Inc. - 001265 (base 16) Enerdyne Technologies, Inc. - 1935 Cordell Court - El Cajon CA 92020 - UNITED STATES - - 00-12-66 (hex) Swisscom Hospitality Services SA - 001266 (base 16) Swisscom Hospitality Services SA - Chemin de l'Etang 65 - 1211 Geneva - SWITZERLAND - - 00-12-67 (hex) Panasonic Corporation - 001267 (base 16) Panasonic Corporation - 2460-1, Uegawa-Cho - Matsusaka-City Mie 571-8506 - JAPAN - - 00-12-68 (hex) IPS d.o.o. - 001268 (base 16) IPS d.o.o. - C. Ljubljanske brigade 17 - Ljubljana SI-1000 - SLOVENIA - - 00-12-69 (hex) Value Electronics - 001269 (base 16) Value Electronics - Dong-kwan B/D, 5F, 1566-2 - Seocho-dong, Seocho-gu - seoul 137-874 - KOREA, REPUBLIC OF - - 00-12-6A (hex) OPTOELECTRONICS Co., Ltd. - 00126A (base 16) OPTOELECTRONICS Co., Ltd. - 3-1Kamiaokinishi 1-chome - Kawaguchi Saitama Pref. 333-0845 - JAPAN - - 00-12-6B (hex) Ascalade Communications Limited - 00126B (base 16) Ascalade Communications Limited - Unit 10-11, 35/F, Cable TV Tower, - No.9 Hoi Shing Road, Tsuen Wan - HONG KONG - - 00-12-6C (hex) Visonic Ltd. - 00126C (base 16) Visonic Ltd. - 24 Habarzel St. - Tel Aviv 69710 - ISRAEL - - 00-12-6D (hex) University of California, Berkeley - 00126D (base 16) University of California, Berkeley - EECS Department - Berkeley CA 94720-1776 - UNITED STATES - - 00-12-6E (hex) Seidel Elektronik GmbH Nfg.KG - 00126E (base 16) Seidel Elektronik GmbH Nfg.KG - Frauentalerstrasse 100 - Deutschlandsberg Steiermark 8530 - AUSTRIA - - 00-12-6F (hex) Rayson Technology Co., Ltd. - 00126F (base 16) Rayson Technology Co., Ltd. - 1F No.9 R&D Rd.II, Science-Based Industrial Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-12-70 (hex) NGES Denro Systems - 001270 (base 16) NGES Denro Systems - 7055 Troy Hill Dr - MS 8865 - Elkridge MD 21075 - UNITED STATES - - 00-12-71 (hex) Measurement Computing Corp - 001271 (base 16) Measurement Computing Corp - 10 Commerce Way - Norton MA 02766 - UNITED STATES - - 00-12-72 (hex) Redux Communications Ltd. - 001272 (base 16) Redux Communications Ltd. - POB 101 - Modiin 71700 - ISRAEL - - 00-12-73 (hex) Stoke Inc - 001273 (base 16) Stoke Inc - 2189 Leghorn Street - Mountain View CA 94043 - UNITED STATES - - 00-12-74 (hex) NIT lab - 001274 (base 16) NIT lab - Skoriny str., 65-3 - Minsk Minskaya obl. 220013 - BELARUS - - 00-12-75 (hex) Sentilla Corporation - 001275 (base 16) Sentilla Corporation - 201 Marshall Street - Redwood City CA 94063 - UNITED STATES - - 00-12-76 (hex) CG Power Systems Ireland Limited - 001276 (base 16) CG Power Systems Ireland Limited - Herbert House., Harmony Row, - Dublin D2 - IRELAND - - 00-12-77 (hex) Korenix Technologies Co., Ltd. - 001277 (base 16) Korenix Technologies Co., Ltd. - 11F-1, No. 108, MinQuan Rd. - Xindian City Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-12-78 (hex) International Bar Code - 001278 (base 16) International Bar Code - 160 Oak Street - Glastonbury CT 06033 - UNITED STATES - - 00-12-79 (hex) Hewlett-Packard Company - 001279 (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS070405 - Houston TX 77070 - UNITED STATES - - 00-12-7A (hex) Sanyu Industry Co.,Ltd. - 00127A (base 16) Sanyu Industry Co.,Ltd. - Midori-ku Hakusan1-11-11 - Yokohama-shi Kanagawa-ken 226-0006 - JAPAN - - 00-12-7B (hex) VIA Networking Technologies, Inc. - 00127B (base 16) VIA Networking Technologies, Inc. - 8F,533, Chung-Cheng Road, Hsin-Tien - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-12-7C (hex) SWEGON AB - 00127C (base 16) SWEGON AB - Box 300 - KVÄNUM VÄSTRA GÖTALAND SE 535 23 - SWEDEN - - 00-12-7D (hex) MobileAria - 00127D (base 16) MobileAria - 800 W El Camino Real #240 - Mountain View CA 94040 - UNITED STATES - - 00-12-7E (hex) Digital Lifestyles Group, Inc. - 00127E (base 16) Digital Lifestyles Group, Inc. - 801 South Sentous Ave. - City of Industry CA 91748 - UNITED STATES - - 00-12-7F (hex) CISCO SYSTEMS, INC. - 00127F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-80 (hex) CISCO SYSTEMS, INC. - 001280 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-81 (hex) March Networks S.p.A. - 001281 (base 16) March Networks S.p.A. - Via Dei Lavoratori Autobianchi n. 1, - Desio Milano 20033 - ITALY - - 00-12-82 (hex) Qovia - 001282 (base 16) Qovia - 7470 New Technology Way - Suite E - Frederick MD 21703 - UNITED STATES - - 00-12-83 (hex) Nortel Networks - 001283 (base 16) Nortel Networks - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-12-84 (hex) Lab33 Srl - 001284 (base 16) Lab33 Srl - C.so F. Perrone 24 - Genoa GE 16152 - ITALY - - 00-12-85 (hex) Gizmondo Europe Ltd - 001285 (base 16) Gizmondo Europe Ltd - 1 Meadow Gate Avenue - Farnborough Business Park - Farnborough Hampshire GU14 6FG - UNITED KINGDOM - - 00-12-86 (hex) ENDEVCO CORP - 001286 (base 16) ENDEVCO CORP - 30700 RANCHO VIEJO ROAD - SAN JUAN CAPISTRANO CA 92675 - UNITED STATES - - 00-12-87 (hex) Digital Everywhere Unterhaltungselektronik GmbH - 001287 (base 16) Digital Everywhere Unterhaltungselektronik GmbH - Maria Gailer Strasse 16 - Villach Kärnten 9500 - AUSTRIA - - 00-12-88 (hex) 2Wire, Inc - 001288 (base 16) 2Wire, Inc - 1704 Automation Parkway - San Jose CA 94538 - UNITED STATES - - 00-12-89 (hex) Advance Sterilization Products - 001289 (base 16) Advance Sterilization Products - 33 Technology Drive - Irvine California 92618 - UNITED STATES - - 00-12-8A (hex) ARRIS Group, Inc. - 00128A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-12-8B (hex) Sensory Networks Inc - 00128B (base 16) Sensory Networks Inc - Level 6, 140 William St - East Sydney NSW 2011 - AUSTRALIA - - 00-12-8C (hex) Woodward Governor - 00128C (base 16) Woodward Governor - 1000 E. Drake Road - Ft. Collins CO 80525 - UNITED STATES - - 00-12-8D (hex) STB Datenservice GmbH - 00128D (base 16) STB Datenservice GmbH - Weinsbergstraße 190 - Köln NRW 50825 - GERMANY - - 00-12-8E (hex) Q-Free ASA - 00128E (base 16) Q-Free ASA - Th. Owesensgt. 35c - Trondheim ST 7443 - NORWAY - - 00-12-8F (hex) Montilio - 00128F (base 16) Montilio - 1 maskit st. - Hertzelia 46763 - ISRAEL - - 00-12-90 (hex) KYOWA Electric & Machinery Corp. - 001290 (base 16) KYOWA Electric & Machinery Corp. - 4-8-16,Masuizumi - Kanazawa Ishikawa 921-8025 - JAPAN - - 00-12-91 (hex) KWS Computersysteme GmbH - 001291 (base 16) KWS Computersysteme GmbH - Carl Zeiss Str. 1 - Ettlingen BW 76275 - GERMANY - - 00-12-92 (hex) Griffin Technology - 001292 (base 16) Griffin Technology - 1930 Air Lane Drive - Nashville TN 37210 - UNITED STATES - - 00-12-93 (hex) GE Energy - 001293 (base 16) GE Energy - 1501 Roanoke Blvd. - Room 283 - Salem VA 24153 - UNITED STATES - - 00-12-94 (hex) SUMITOMO ELECTRIC DEVICE INNOVATIONS, INC - 001294 (base 16) SUMITOMO ELECTRIC DEVICE INNOVATIONS, INC - 1000 Kamisukiawara,Showa-cho - Nakakoma-gun Yamanashi 409-3883 - JAPAN - - 00-12-95 (hex) Aiware Inc. - 001295 (base 16) Aiware Inc. - J-Tower 2F - 1-1 Nikkocho - Fuchu-shi Tokyo 183-0044 - JAPAN - - 00-12-96 (hex) Addlogix - 001296 (base 16) Addlogix - 459 Wald - Irvine CA 92618 - UNITED STATES - - 00-12-97 (hex) O2Micro, Inc. - 001297 (base 16) O2Micro, Inc. - 3118 Patrick Henry Drive - Santa Clara CA 95054 - UNITED STATES - - 00-12-98 (hex) MICO ELECTRIC(SHENZHEN) LIMITED - 001298 (base 16) MICO ELECTRIC(SHENZHEN) LIMITED - 21/F Block A, Hailrun Complex, 6021 ShenNan Blvd., ShenZhen, PR China. - SHENZHEN GUANGDONG 518040 - CHINA - - 00-12-99 (hex) Ktech Telecommunications Inc - 001299 (base 16) Ktech Telecommunications Inc - 21540 Prairie Street Unit B - Chatsworth CA 91311 - UNITED STATES - - 00-12-9A (hex) IRT Electronics Pty Ltd - 00129A (base 16) IRT Electronics Pty Ltd - 26 Hotham Parade - Artarmon NSW 2064 - AUSTRALIA - - 00-12-9B (hex) E2S Electronic Engineering Solutions, S.L. - 00129B (base 16) E2S Electronic Engineering Solutions, S.L. - Sant Ferran 10 - Barcelona 08031 - SPAIN - - 00-12-9C (hex) Yulinet - 00129C (base 16) Yulinet - 11F, Samhomoolsan B/D 275-6, Yangjae-dong - Seocho Seoul 137-941 - KOREA, REPUBLIC OF - - 00-12-9D (hex) First International Computer do Brasil - 00129D (base 16) First International Computer do Brasil - Rodovia BR 459 - km 121 - Distrito Industrial - Santa Rita do Sapucaí Minas Gerais - BRAZIL - - 00-12-9E (hex) Surf Communications Inc. - 00129E (base 16) Surf Communications Inc. - Room 313, 3F, Bldg.52, No. 195, Chung Hsing Rd., Sec 4, Chutung, HsinChu, Taiwan - HsinChu 310 - TAIWAN, PROVINCE OF CHINA - - 00-12-9F (hex) RAE Systems - 00129F (base 16) RAE Systems - 3775 North First Street - San Jose CA 95134 - UNITED STATES - - 00-12-A0 (hex) NeoMeridian Sdn Bhd - 0012A0 (base 16) NeoMeridian Sdn Bhd - 3A-1, Perdana The Place - Jalan PJU 8/5G - Bandar Damansara Perdana Selangor 47820 - MALAYSIA - - 00-12-A1 (hex) BluePacket Communications Co., Ltd. - 0012A1 (base 16) BluePacket Communications Co., Ltd. - 10F-1, No. 420, Sec. 1, Keelung Rd., 110, - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-12-A2 (hex) VITA - 0012A2 (base 16) VITA - PO Box 19658 - Fountain Hills AZ 85269 - UNITED STATES - - 00-12-A3 (hex) Trust International B.V. - 0012A3 (base 16) Trust International B.V. - Laan van Barcelona 600 - Dordrecht Zuid holland 3317 DD - NETHERLANDS - - 00-12-A4 (hex) ThingMagic, LLC - 0012A4 (base 16) ThingMagic, LLC - One Broadway - 14th Floor - Cambridge MA 02142 - UNITED STATES - - 00-12-A5 (hex) Stargen, Inc. - 0012A5 (base 16) Stargen, Inc. - 225 Cedar Hill Street - Marlborough MA 01752 - UNITED STATES - - 00-12-A6 (hex) Dolby Australia - 0012A6 (base 16) Dolby Australia - Level 6 - 136 Chalmers Street - Surry Hills NSW 2010 - AUSTRALIA - - 00-12-A7 (hex) ISR TECHNOLOGIES Inc - 0012A7 (base 16) ISR TECHNOLOGIES Inc - 1100, rue Notre-Dame Ouest - Montreal Quebec H3C 1K3 - CANADA - - 00-12-A8 (hex) intec GmbH - 0012A8 (base 16) intec GmbH - Rahmedestraße 90 - Luedenscheid NRW 58507 - GERMANY - - 00-12-A9 (hex) 3Com Ltd - 0012A9 (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-12-AA (hex) IEE, Inc. - 0012AA (base 16) IEE, Inc. - 7740 Lemona Avenue - Van Nuys, CA 91405 - UNITED STATES - - 00-12-AB (hex) WiLife, Inc. - 0012AB (base 16) WiLife, Inc. - 132 E. 13065 S., Suite 150 - Draper UT 84020 - UNITED STATES - - 00-12-AC (hex) ONTIMETEK INC. - 0012AC (base 16) ONTIMETEK INC. - 9Fl.,Owner's Tower - 16-5, Sunae-Dong, Bundang-Gu - Sungnam-Si Kyunggi-Do 463-825 - KOREA, REPUBLIC OF - - 00-12-AD (hex) IDS GmbH - 0012AD (base 16) IDS GmbH - Nobelstraße, 18 - Ettlingen Baden-Württemberg 76275 - GERMANY - - 00-12-AE (hex) HLS HARD-LINE Solutions Inc. - 0012AE (base 16) HLS HARD-LINE Solutions Inc. - 53 Main Street - Dowling Ontario P0M 1R0 - CANADA - - 00-12-AF (hex) ELPRO Technologies - 0012AF (base 16) ELPRO Technologies - 9 / 12 Billabong St. - Stafford Queensland 4053 - AUSTRALIA - - 00-12-B0 (hex) Efore Oyj (Plc) - 0012B0 (base 16) Efore Oyj (Plc) - Quartetto Business Park - Linnoitustie 4 B - Espoo FI - 02600 - FINLAND - - 00-12-B1 (hex) Dai Nippon Printing Co., Ltd - 0012B1 (base 16) Dai Nippon Printing Co., Ltd - 2-8-21,Akabane-minami - Kita-ku Tokyo 115-0044 - JAPAN - - 00-12-B2 (hex) AVOLITES LTD. - 0012B2 (base 16) AVOLITES LTD. - 184 PARK AVENUE - LONDON NW10 7XL - UNITED KINGDOM - - 00-12-B3 (hex) Advance Wireless Technology Corp. - 0012B3 (base 16) Advance Wireless Technology Corp. - 12F No. 27-6, Sec. 2, Chung Cheng East Road - Tamshui 251 - TAIWAN, PROVINCE OF CHINA - - 00-12-B4 (hex) Work Microwave GmbH - 0012B4 (base 16) Work Microwave GmbH - Raiffeisenstrasse 12 - Holzkirchen 83607 - GERMANY - - 00-12-B5 (hex) Vialta, Inc. - 0012B5 (base 16) Vialta, Inc. - 48461 Fremont Blvd. - Fremont CA 94538 - UNITED STATES - - 00-12-B6 (hex) Santa Barbara Infrared, Inc. - 0012B6 (base 16) Santa Barbara Infrared, Inc. - 30 S. Calle Cesar Chavez - Suite D - Santa Barbara CA 93103 - UNITED STATES - - 00-12-B7 (hex) PTW Freiburg - 0012B7 (base 16) PTW Freiburg - Loerracher Strasse 7 - Freiburg 79115 - GERMANY - - 00-12-B8 (hex) G2 Microsystems - 0012B8 (base 16) G2 Microsystems - 408 Euclid Ave - Oakland CA 94610 - UNITED STATES - - 00-12-B9 (hex) Fusion Digital Technology - 0012B9 (base 16) Fusion Digital Technology - Victoria Mews, 23 Millfield Road - Cottingley Business Park - Bingley West Yorkshire BD16 1PY - UNITED KINGDOM - - 00-12-BA (hex) FSI Systems, Inc. - 0012BA (base 16) FSI Systems, Inc. - 5847 County Road 41 - Farmington NY 14425 - UNITED STATES - - 00-12-BB (hex) Telecommunications Industry Association TR-41 Committee - 0012BB (base 16) Telecommunications Industry Association TR-41 Committee - 2500 Wilson Blvd., Suite 300 - Arlington VA 22201 - UNITED STATES - - 00-12-BC (hex) Echolab LLC - 0012BC (base 16) Echolab LLC - 267 Boston Road - Suite 11 - Billerica MA 01862 - UNITED STATES - - 00-12-BD (hex) Avantec Manufacturing Limited - 0012BD (base 16) Avantec Manufacturing Limited - Unit L, 7/F, Camelpaint Bldg, Block 3 - 60 Hoi Yuen Road, Kwun Tong, Kowloon - 852 - HONG KONG - - 00-12-BE (hex) Astek Corporation - 0012BE (base 16) Astek Corporation - 5055 Corporate Plaza Drive - Colorado Springs Colorado 80919 - UNITED STATES - - 00-12-BF (hex) Arcadyan Technology Corporation - 0012BF (base 16) Arcadyan Technology Corporation - 4F, No. 9, Park Avenue II - Science-based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-12-C0 (hex) HotLava Systems, Inc. - 0012C0 (base 16) HotLava Systems, Inc. - 6329 Chelton Drive - Oakland CA 94611 - UNITED STATES - - 00-12-C1 (hex) Check Point Software Technologies - 0012C1 (base 16) Check Point Software Technologies - 5 Ha'solelim St. - Tel Aviv 67897 - ISRAEL - - 00-12-C2 (hex) Apex Electronics Factory - 0012C2 (base 16) Apex Electronics Factory - No.3 Industrial Zone, No.4 Block, - Fu'yong Town, Bao'an District - Shen Zhen Guang Dong 518103 - CHINA - - 00-12-C3 (hex) WIT S.A. - 0012C3 (base 16) WIT S.A. - 138 avenue Léon Bérenger - Saint Laurent du Var PACA 06700 - FRANCE - - 00-12-C4 (hex) Viseon, Inc. - 0012C4 (base 16) Viseon, Inc. - 8445 Freeport Parkway - Suite 245 - Irving Texas 75063 - UNITED STATES - - 00-12-C5 (hex) V-Show Technology (China) Co.,Ltd - 0012C5 (base 16) V-Show Technology (China) Co.,Ltd - 7F, Tengda Plaza, No.168 - Xizhimen Wai Street, - HaiDian District, Beijing 100089 - CHINA - - 00-12-C6 (hex) TGC America, Inc - 0012C6 (base 16) TGC America, Inc - 2901 Tasman Drive, Suite 111 - Santa Clara CA 95054 - UNITED STATES - - 00-12-C7 (hex) SECURAY Technologies Ltd.Co. - 0012C7 (base 16) SECURAY Technologies Ltd.Co. - Tianjin Haitai Industrial Base ErWei Road - No. 6 Block F 8-401 - Tianjin 300384 - CHINA - - 00-12-C8 (hex) Perfect tech - 0012C8 (base 16) Perfect tech - 3F,No.9,LANE175,NANKAN RD., - LUJHU TAOYUAN 338 - TAIWAN, PROVINCE OF CHINA - - 00-12-C9 (hex) ARRIS Group, Inc. - 0012C9 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-12-CA (hex) Mechatronic Brick Aps - 0012CA (base 16) Mechatronic Brick Aps - Alsion 2 - 6400 Sonderborg - DENMARK - - 00-12-CB (hex) CSS Inc. - 0012CB (base 16) CSS Inc. - 151 Superior Blvd. - Unit 13 & 14 - Mississauga Ontario L5T2L1 - CANADA - - 00-12-CC (hex) Bitatek CO., LTD - 0012CC (base 16) Bitatek CO., LTD - 6F-1,190,Ta-Tung Road,SEC. 3, - Hsichih Taipei county 221 - TAIWAN, PROVINCE OF CHINA - - 00-12-CD (hex) ASEM SpA - 0012CD (base 16) ASEM SpA - Via Buia, 4 - ARTEGNA Udine I-33011 - ITALY - - 00-12-CE (hex) Advanced Cybernetics Group - 0012CE (base 16) Advanced Cybernetics Group - 2953 Bunker Hill Lane - Suite 400 - Santa Clara CA 95054 - UNITED STATES - - 00-12-CF (hex) Accton Technology Corporation - 0012CF (base 16) Accton Technology Corporation - No. 1 Creation Rd. III, Science-based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-12-D0 (hex) Gossen-Metrawatt-GmbH - 0012D0 (base 16) Gossen-Metrawatt-GmbH - Thomas-Mann-Straße 16-20 - Nürnberg Bavaria 90471 - GERMANY - - 00-12-D1 (hex) Texas Instruments Inc - 0012D1 (base 16) Texas Instruments Inc - 12500 TI Boulevard, - MS 8723 - Dallas Texas 75243 - UNITED STATES - - 00-12-D2 (hex) Texas Instruments - 0012D2 (base 16) Texas Instruments - 12500 TI Boulevard - MS 8723 - Dallas Texas 75243 - UNITED STATES - - 00-12-D3 (hex) Zetta Systems, Inc. - 0012D3 (base 16) Zetta Systems, Inc. - 17311 135th AVE NE - Suite B900 - Woodinville WA 98072 - UNITED STATES - - 00-12-D4 (hex) Princeton Technology, Ltd - 0012D4 (base 16) Princeton Technology, Ltd - K.A.I. Bldg. 3F - 3-9-5 Iwamoto-cho - Chiyodaku Tokyo 101-0032 - JAPAN - - 00-12-D5 (hex) Motion Reality Inc. - 0012D5 (base 16) Motion Reality Inc. - 200 North Cobb Parkway - Suite 140 - Marietta GA 30062 - UNITED STATES - - 00-12-D6 (hex) Jiangsu Yitong High-Tech Co.,Ltd - 0012D6 (base 16) Jiangsu Yitong High-Tech Co.,Ltd - No 216 Huanghe Road - Changshu Jiangsu 215500 - CHINA - - 00-12-D7 (hex) Invento Networks, Inc. - 0012D7 (base 16) Invento Networks, Inc. - 377 Simarano Drive - Marlborough MA 01752 - UNITED STATES - - 00-12-D8 (hex) International Games System Co., Ltd. - 0012D8 (base 16) International Games System Co., Ltd. - No.130, Wu-Gung Rd., Wu-Gu Industrial Park, - Taipei 248 - TAIWAN, PROVINCE OF CHINA - - 00-12-D9 (hex) CISCO SYSTEMS, INC. - 0012D9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-DA (hex) CISCO SYSTEMS, INC. - 0012DA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-12-DB (hex) ZIEHL industrie-elektronik GmbH + Co KG - 0012DB (base 16) ZIEHL industrie-elektronik GmbH + Co KG - Daimlerstraße 13 - Schwäbisch Hall 74523 - GERMANY - - 00-12-DC (hex) SunCorp Industrial Limited - 0012DC (base 16) SunCorp Industrial Limited - No.68 Guowei Road, - Liantang Industrial District, Shenzhen, - CHINA - - 00-12-DD (hex) Shengqu Information Technology (Shanghai) Co., Ltd. - 0012DD (base 16) Shengqu Information Technology (Shanghai) Co., Ltd. - No.1 Building,No. 690 Bibo Road,Pudong New Area - Shanghai 201203 - CHINA - - 00-12-DE (hex) Radio Components Sweden AB - 0012DE (base 16) Radio Components Sweden AB - Viderogatan 3B - Kista Stockholm 16422 - SWEDEN - - 00-12-DF (hex) Novomatic AG - 0012DF (base 16) Novomatic AG - Wiener Strasse 158 - Gumpoldskirchen Niederösterreich A-2352 - AUSTRIA - - 00-12-E0 (hex) Codan Limited - 0012E0 (base 16) Codan Limited - 81 Graves Street - Newton South 5074 - AUSTRALIA - - 00-12-E1 (hex) Alliant Networks, Inc - 0012E1 (base 16) Alliant Networks, Inc - 1259 Birchwood Dr. - Sunnyvale CA 94089 - UNITED STATES - - 00-12-E2 (hex) ALAXALA Networks Corporation - 0012E2 (base 16) ALAXALA Networks Corporation - 890 Kashimada, Saiwai-ku - Kawasaki-shi Kanagawa-ken 212-0058 - JAPAN - - 00-12-E3 (hex) Agat-RT, Ltd. - 0012E3 (base 16) Agat-RT, Ltd. - 101 pr. Mira #1220, - Moscow 129085 - RUSSIAN FEDERATION - - 00-12-E4 (hex) ZIEHL industrie-electronik GmbH + Co KG - 0012E4 (base 16) ZIEHL industrie-electronik GmbH + Co KG - Daimlerstraße 13 - Schwaebisch Hall 74523 - GERMANY - - 00-12-E5 (hex) Time America, Inc. - 0012E5 (base 16) Time America, Inc. - 51 W. 3rd Street #310 - Tempe AZ 85281 - UNITED STATES - - 00-12-E6 (hex) SPECTEC COMPUTER CO., LTD. - 0012E6 (base 16) SPECTEC COMPUTER CO., LTD. - 6F., No. 92, Nanking E. Rd. Sec. 5, - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-12-E7 (hex) Projectek Networking Electronics Corp. - 0012E7 (base 16) Projectek Networking Electronics Corp. - 5F-9, No. 16, Lane 609, Sec. 5, Chungshin Rd., - Sanchung, Taipei 241 - TAIWAN, PROVINCE OF CHINA - - 00-12-E8 (hex) Fraunhofer IMS - 0012E8 (base 16) Fraunhofer IMS - Finkenstrasse 61 - Duisburg NRW 47057 - GERMANY - - 00-12-E9 (hex) Abbey Systems Ltd - 0012E9 (base 16) Abbey Systems Ltd - Level 4, 220 Willis St - PO Box 27-497 - Wellington 6030 - NEW ZEALAND - - 00-12-EA (hex) Trane - 0012EA (base 16) Trane - 4833 White Bear Parkway - St. Paul MN 55110 - UNITED STATES - - 00-12-EB (hex) PDH Solutions, LLC - 0012EB (base 16) PDH Solutions, LLC - 34154 Bennett Rd - Warren OR 97053 - UNITED STATES - - 00-12-EC (hex) Movacolor b.v. - 0012EC (base 16) Movacolor b.v. - Koperslagersstraat 31 - Sneek Friesland 8601 WL - NETHERLANDS - - 00-12-ED (hex) AVG Advanced Technologies - 0012ED (base 16) AVG Advanced Technologies - 4140 Utica Ridge Road - Bettendorf IA 52722 - UNITED STATES - - 00-12-EE (hex) Sony Ericsson Mobile Communications AB - 0012EE (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-12-EF (hex) OneAccess SA - 0012EF (base 16) OneAccess SA - 28 rue de la Redoute - Fontenay aux Roses 92260 - FRANCE - - 00-12-F0 (hex) Intel Corporate - 0012F0 (base 16) Intel Corporate - Lot 8, Jalan Hi-tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-12-F1 (hex) IFOTEC - 0012F1 (base 16) IFOTEC - ZAC Champfeuillet - BP247 - VOIRON 38507 - FRANCE - - 00-12-F2 (hex) Brocade Communications Systems, Inc - 0012F2 (base 16) Brocade Communications Systems, Inc - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-12-F3 (hex) connectBlue AB - 0012F3 (base 16) connectBlue AB - Norra Vallgatan 64 - Malmoe SE-211 22 - SWEDEN - - 00-12-F4 (hex) Belco International Co.,Ltd. - 0012F4 (base 16) Belco International Co.,Ltd. - 212, Yeokok-Dong, Wonmi-gu - Puchun-Si Kyongki-Do 420-100 - KOREA, REPUBLIC OF - - 00-12-F5 (hex) Imarda New Zealand Limited - 0012F5 (base 16) Imarda New Zealand Limited - Suite G16, National Innovation Centre, - Australian Technology Park, - Eveleigh NSW 2015 - NEW ZEALAND - - 00-12-F6 (hex) MDK CO.,LTD. - 0012F6 (base 16) MDK CO.,LTD. - 2-6-27 Ibarame - Kashiwazaki City Niigata 9451341 - JAPAN - - 00-12-F7 (hex) Xiamen Xinglian Electronics Co., Ltd. - 0012F7 (base 16) Xiamen Xinglian Electronics Co., Ltd. - Xinglian Electronics (Xingtel) Building,Chuangxin Road, - Torch Hi-Tech Industrial District, - Xiamen Fujian 361006 - CHINA - - 00-12-F8 (hex) WNI Resources, LLC - 0012F8 (base 16) WNI Resources, LLC - 2146 Bering Drive - San Jose California 95131-2013 - UNITED STATES - - 00-12-F9 (hex) URYU SEISAKU, LTD. - 0012F9 (base 16) URYU SEISAKU, LTD. - 1-2-11 - FUKAE-MINAMI - HIGASHINARI-KU OSAKA 537-0002 - JAPAN - - 00-12-FA (hex) THX LTD - 0012FA (base 16) THX LTD - 5201 Great America Parkway - Suite 320 - Santa Clara CA 95054 - UNITED STATES - - 00-12-FB (hex) Samsung Electronics - 0012FB (base 16) Samsung Electronics - 416, Maetan-3Dong, Yeongtong-Gu - Suwon-City Gyeonggi-Do 443-742 - KOREA, REPUBLIC OF - - 00-12-FC (hex) PLANET System Co.,LTD - 0012FC (base 16) PLANET System Co.,LTD - 4th Floor, Daehan B/D, 873-29, - Bangbae4-Dong, Seocho-Ku, - Seoul 137-064 - KOREA, REPUBLIC OF - - 00-12-FD (hex) OPTIMUS IC S.A. - 0012FD (base 16) OPTIMUS IC S.A. - NAWOJOWSKA 118 - NOWY SACZ MALOPOLSKA 33-300 - POLAND - - 00-12-FE (hex) Lenovo Mobile Communication Technology Ltd. - 0012FE (base 16) Lenovo Mobile Communication Technology Ltd. - Xiamen Overseas Chinese Electronic Science Park,Huoju High Technology Development Zone - XIA MEN FU JIAN 361009 - CHINA - - 00-12-FF (hex) Lely Industries N.V. - 0012FF (base 16) Lely Industries N.V. - Weverskade 110 - Maassluis Zuid-Holland 3147PA - NETHERLANDS - - 00-13-00 (hex) IT-FACTORY, INC. - 001300 (base 16) IT-FACTORY, INC. - 1-16-26 TAKAGI MINAMI-KU - FUKUOKA-SHI FUKUOKA-KEN 815-0004 - JAPAN - - 00-13-01 (hex) IronGate S.L. - 001301 (base 16) IronGate S.L. - C\Alcala 268, primera planta - Madrid 28027 - SPAIN - - 00-13-02 (hex) Intel Corporate - 001302 (base 16) Intel Corporate - Lot 8, Jalan Hi-tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-13-03 (hex) GateConnect - 001303 (base 16) GateConnect - Eisenhutweg 69 - 12487 Berlin 12487 - GERMANY - - 00-13-04 (hex) Flaircomm Technologies Co. LTD - 001304 (base 16) Flaircomm Technologies Co. LTD - 2088 Huashan Road - South Huiyin Bldg. #2306 - Shanghai 200030 - CHINA - - 00-13-05 (hex) Epicom, Inc. - 001305 (base 16) Epicom, Inc. - PO Box 16130 - Oakland CA 94610 - UNITED STATES - - 00-13-06 (hex) Always On Wireless - 001306 (base 16) Always On Wireless - 3701 Kirby Dr - Suite 1090 - Houston TX 77098 - UNITED STATES - - 00-13-07 (hex) Paravirtual Corporation - 001307 (base 16) Paravirtual Corporation - 2953 Bunker Hill Lane - Suite 406 - Santa Clara CA 95054 - UNITED STATES - - 00-13-08 (hex) Nuvera Fuel Cells - 001308 (base 16) Nuvera Fuel Cells - 129 Concord Road, #1 - Billerica MA 01821 - UNITED STATES - - 00-13-09 (hex) Ocean Broadband Networks - 001309 (base 16) Ocean Broadband Networks - 2078 Walsh Ave, Suite B - Santa Clara California 95050 - UNITED STATES - - 00-13-0A (hex) Nortel - 00130A (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-13-0B (hex) Mextal B.V. - 00130B (base 16) Mextal B.V. - De Tienden 48 - Nuenen Noord Brabant 5674TB - NETHERLANDS - - 00-13-0C (hex) HF System Corporation - 00130C (base 16) HF System Corporation - 1520-1 Ayukai - Shirataka-Machi - Nishiokitama-Gun Yamagata-Ken 992-0771 - JAPAN - - 00-13-0D (hex) GALILEO AVIONICA - 00130D (base 16) GALILEO AVIONICA - VIALE EUROPA - NERVIANO MILANO 20014 - ITALY - - 00-13-0E (hex) Focusrite Audio Engineering Limited - 00130E (base 16) Focusrite Audio Engineering Limited - 19 Lincoln Road - Cressex Business Park - High Wycombe Bucks HP12 3FX - UNITED KINGDOM - - 00-13-0F (hex) EGEMEN Bilgisayar Muh San ve Tic LTD STI - 00130F (base 16) EGEMEN Bilgisayar Muh San ve Tic LTD STI - Fevzi Cakmak 2 Sok 31/A - KIZILAY - ANKARA CANKAYA 06440 - TURKEY - - 00-13-10 (hex) Cisco-Linksys, LLC - 001310 (base 16) Cisco-Linksys, LLC - 121 Theory - Irvine CA 92612 - UNITED STATES - - 00-13-11 (hex) ARRIS International - 001311 (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-13-12 (hex) Amedia Networks Inc. - 001312 (base 16) Amedia Networks Inc. - 101 Crawfords Corner Rd - Holmdel NJ 07733 - UNITED STATES - - 00-13-13 (hex) GuangZhou Post & Telecom Equipment ltd - 001313 (base 16) GuangZhou Post & Telecom Equipment ltd - 139# Zhongshan Ave - Guangzhou Guangdong 510630 - CHINA - - 00-13-14 (hex) Asiamajor Inc. - 001314 (base 16) Asiamajor Inc. - 6F-9, No. 268, Lian-Cheng Rd., Junghe City, - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-13-15 (hex) SONY Computer Entertainment inc, - 001315 (base 16) SONY Computer Entertainment inc, - 2-6-21 Minami-Aoyama, - Minato-Ku Tokyo 107-0062 - JAPAN - - 00-13-16 (hex) L-S-B Broadcast Technologies GmbH - 001316 (base 16) L-S-B Broadcast Technologies GmbH - Gustav-Stresemann-Str. 8 - Bingen Rheinland-Pfalz 55411 - GERMANY - - 00-13-17 (hex) GN Netcom as - 001317 (base 16) GN Netcom as - Metalbuen 66 - P.O.Box 201 - Ballerup Skovlunde DK-2750 - DENMARK - - 00-13-18 (hex) DGSTATION Co., Ltd. - 001318 (base 16) DGSTATION Co., Ltd. - Rm.401, Bldg.A, Bundang Techno Park 150, Yatap-Dong, Bundang-Gu, Sungnam-Si, Gyunggi-Do, 463-760, Korea - Sungnam Gyunggi 463-760 - KOREA, REPUBLIC OF - - 00-13-19 (hex) CISCO SYSTEMS, INC. - 001319 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-1A (hex) CISCO SYSTEMS, INC. - 00131A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-1B (hex) BeCell Innovations Corp. - 00131B (base 16) BeCell Innovations Corp. - 12F-9, No. 79, Shin-Tai 5th Rd Sec 1, - Shih-chih, Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-13-1C (hex) LiteTouch, Inc. - 00131C (base 16) LiteTouch, Inc. - 3400 South West Temple - Salt Lake City UT 84115 - UNITED STATES - - 00-13-1D (hex) Scanvaegt International A/S - 00131D (base 16) Scanvaegt International A/S - P.O.Pedersens vej 18 - Aarhus Jylland 8200 N - DENMARK - - 00-13-1E (hex) Peiker acustic GmbH & Co. KG - 00131E (base 16) Peiker acustic GmbH & Co. KG - Max-Planck-Straße 32 - Friedrichsdorf Hessen 61381 - GERMANY - - 00-13-1F (hex) NxtPhase T&D, Corp. - 00131F (base 16) NxtPhase T&D, Corp. - 3040 E. Broadway - Vancouver BC V5M 1Z4 - CANADA - - 00-13-20 (hex) Intel Corporate - 001320 (base 16) Intel Corporate - Lot 8, Jalan Hi-tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-13-21 (hex) Hewlett-Packard Company - 001321 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS070405 - Houston TX 77070 - UNITED STATES - - 00-13-22 (hex) DAQ Electronics, Inc. - 001322 (base 16) DAQ Electronics, Inc. - 262B Old New Brunswick Road - Piscataway NJ 08854 - UNITED STATES - - 00-13-23 (hex) Cap Co., Ltd. - 001323 (base 16) Cap Co., Ltd. - 11F,684-2,deungchon 3-dong,gangseo-gu - Seoul 157-754 - KOREA, REPUBLIC OF - - 00-13-24 (hex) Schneider Electric Ultra Terminal - 001324 (base 16) Schneider Electric Ultra Terminal - Industriparken 32 - Copenhagen 2750 - DENMARK - - 00-13-25 (hex) Cortina Systems Inc - 001325 (base 16) Cortina Systems Inc - 840 W California Ave, Suite 100 - Sunnyvale CA 94086 - UNITED STATES - - 00-13-26 (hex) ECM Systems Ltd - 001326 (base 16) ECM Systems Ltd - Ellifoot Park - Burstwick - HULL East Yorkshire HU12 9DZ - UNITED KINGDOM - - 00-13-27 (hex) Data Acquisitions limited - 001327 (base 16) Data Acquisitions limited - 84 Gasson street - Christchurch - NEW ZEALAND - - 00-13-28 (hex) Westech Korea Inc., - 001328 (base 16) Westech Korea Inc., - 548-9, Gajwa3-Dong,Seo-ku, - Incheon 404-817 - KOREA, REPUBLIC OF - - 00-13-29 (hex) VSST Co., LTD - 001329 (base 16) VSST Co., LTD - suit 3202, Korea World Trade Center 159-1 - Samsung-Dong, Kangnam-Gu - Seoul 135-729 - KOREA, REPUBLIC OF - - 00-13-2A (hex) Sitronics Telecom Solutions - 00132A (base 16) Sitronics Telecom Solutions - Michelska 60 - Prague Prague 4 - Michle 140 00 - CZECH REPUBLIC - - 00-13-2B (hex) Phoenix Digital - 00132B (base 16) Phoenix Digital - 7650 East Evans Rd. Bldg. A - Scottsdale Az 85260 - UNITED STATES - - 00-13-2C (hex) MAZ Brandenburg GmbH - 00132C (base 16) MAZ Brandenburg GmbH - Pascalstraße 10a - Berlin Berlin 10587 - GERMANY - - 00-13-2D (hex) iWise Communications - 00132D (base 16) iWise Communications - Unit 3C, Arden Grove - Racecourse Rd,Montagu Gardens - Cape Town 7441 - SOUTH AFRICA - - 00-13-2E (hex) ITian Coporation - 00132E (base 16) ITian Coporation - 4F Youngho Bd.1605-1 Seocho-dong - Seocho-gu - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-13-2F (hex) Interactek - 00132F (base 16) Interactek - Sigmal 2 BLDG #C-319, 18 Kumi-dong - Pundang-ku - Seongnam Kyung-gi 463-741 - KOREA, REPUBLIC OF - - 00-13-30 (hex) EURO PROTECTION SURVEILLANCE - 001330 (base 16) EURO PROTECTION SURVEILLANCE - 30 Rue du Doubs - STRASBOURG 67100 - FRANCE - - 00-13-31 (hex) CellPoint Connect - 001331 (base 16) CellPoint Connect - Billedvej 4 - Copenhagen 2100 - DENMARK - - 00-13-32 (hex) Beijing Topsec Network Security Technology Co., Ltd. - 001332 (base 16) Beijing Topsec Network Security Technology Co., Ltd. - Huakong Tower - No. 1 Shangdi East Road - Haidian District Beijing 100085 - CHINA - - 00-13-33 (hex) BaudTec Corporation - 001333 (base 16) BaudTec Corporation - 12F, NO.181, Sec. 1. Tatung Rd., - Hsichih Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-13-34 (hex) Arkados, Inc. - 001334 (base 16) Arkados, Inc. - 948 US HWY 22 - North Plainfield NJ 07060 - UNITED STATES - - 00-13-35 (hex) VS Industry Berhad - 001335 (base 16) VS Industry Berhad - Plo 47, Senai Ind. Est. II, - Senai Johor 81400 - MALAYSIA - - 00-13-36 (hex) Tianjin 712 Communication Broadcasting co., ltd. - 001336 (base 16) Tianjin 712 Communication Broadcasting co., ltd. - No.185, Xinda Road, Hebei District - Tianjin 300140 - CHINA - - 00-13-37 (hex) Orient Power Home Network Ltd. - 001337 (base 16) Orient Power Home Network Ltd. - 307 Harbour Centre, Tower 1, - 1 Hok Cheung Street, Hung Hom - HONG KONG - - 00-13-38 (hex) FRESENIUS-VIAL - 001338 (base 16) FRESENIUS-VIAL - Le Grand Chemin - BREZINS 38590 - FRANCE - - 00-13-39 (hex) CCV Deutschland GmbH - 001339 (base 16) CCV Deutschland GmbH - Gewerbering 1 - Au i. d. Hallertau Bayern 84072 - GERMANY - - 00-13-3A (hex) VadaTech Inc. - 00133A (base 16) VadaTech Inc. - 11540 S. Eastern Avenue - Henderson Nevada 89052 - UNITED STATES - - 00-13-3B (hex) Speed Dragon Multimedia Limited - 00133B (base 16) Speed Dragon Multimedia Limited - Room 1312, Vanta Industrial Centre, - 33 Tai Lin Pai Road, - Kwai Chung N.T. - HONG KONG - - 00-13-3C (hex) QUINTRON SYSTEMS INC. - 00133C (base 16) QUINTRON SYSTEMS INC. - 2105 SO. BLOSSER ROAD - SANTA MARIA CALIFORNIA 93458 - UNITED STATES - - 00-13-3D (hex) Micro Memory Curtiss Wright Co - 00133D (base 16) Micro Memory Curtiss Wright Co - 9540 Vassar Avenue - Chatsworth CA 91311 - UNITED STATES - - 00-13-3E (hex) MetaSwitch - 00133E (base 16) MetaSwitch - 1411 Harbor Bay Parkway - Suite 1003 - Alameda CA 94502 - UNITED STATES - - 00-13-3F (hex) Eppendorf Instrumente GmbH - 00133F (base 16) Eppendorf Instrumente GmbH - Barkhausenweg 1 - Abtl. IH-FE - Hamburg DE 22339 - GERMANY - - 00-13-40 (hex) AD.EL s.r.l. - 001340 (base 16) AD.EL s.r.l. - via S. Pertini,5 - Martellago VENEZIA 30030 - ITALY - - 00-13-41 (hex) Shandong New Beiyang Information Technology Co.,Ltd - 001341 (base 16) Shandong New Beiyang Information Technology Co.,Ltd - NO.11 Xinwei Road - Weihai city Shandong 264200 - CHINA - - 00-13-42 (hex) Vision Research, Inc. - 001342 (base 16) Vision Research, Inc. - 100 Dey Road - Wayne NJ 07470 - UNITED STATES - - 00-13-43 (hex) Matsushita Electronic Components (Europe) GmbH - 001343 (base 16) Matsushita Electronic Components (Europe) GmbH - Zeppelinstraße 19 - Lueneburg Niedersachsen 21337 - GERMANY - - 00-13-44 (hex) Fargo Electronics Inc. - 001344 (base 16) Fargo Electronics Inc. - 6533 Flying Cloud Drive - Eden Prairie MN 55344 - UNITED STATES - - 00-13-45 (hex) Eaton Corporation - 001345 (base 16) Eaton Corporation - 4201 North 27th Street - Milwaukee Wisconsin 53216 - UNITED STATES - - 00-13-46 (hex) D-Link Corporation - 001346 (base 16) D-Link Corporation - 2F, No.233-2, Pao-Chiao Road - Hsin-Tien, Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-13-47 (hex) Red Lion Controls, LP - 001347 (base 16) Red Lion Controls, LP - 20 Willow Springs Circle - York PA 17402 - UNITED STATES - - 00-13-48 (hex) Artila Electronics Co., Ltd. - 001348 (base 16) Artila Electronics Co., Ltd. - 2F., No.1, Alley 8, Siwei Lane, Zhongzheng Rd., - Xindian City Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 00-13-49 (hex) ZyXEL Communications Corporation - 001349 (base 16) ZyXEL Communications Corporation - No. 6, Innovation Road II Science Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-13-4A (hex) Engim, Inc. - 00134A (base 16) Engim, Inc. - 40 Nagog Park - Acton MA 01720 - UNITED STATES - - 00-13-4B (hex) ToGoldenNet Technology Inc. - 00134B (base 16) ToGoldenNet Technology Inc. - 5F-1 No.25,Pu-ding., - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-13-4C (hex) YDT Technology International - 00134C (base 16) YDT Technology International - 2F., No.218, Rueiguang Rd., - Neihu District - Taipei, 114 - TAIWAN, PROVINCE OF CHINA - - 00-13-4D (hex) Inepro BV - 00134D (base 16) Inepro BV - Pondweg 7 - NL-2153PK - Nieuw- Vennep - NETHERLANDS - - 00-13-4E (hex) Valox Systems, Inc. - 00134E (base 16) Valox Systems, Inc. - #704, Ace Twin tower 2, 212-30, Guro-3dong, Guro-gu - Seoul 152-779 - KOREA, REPUBLIC OF - - 00-13-4F (hex) Tranzeo Wireless Technologies Inc. - 00134F (base 16) Tranzeo Wireless Technologies Inc. - 20155 Stewart Cres. - Maple Ridge British Columbia V2X 0T6 - CANADA - - 00-13-50 (hex) Silver Spring Networks, Inc - 001350 (base 16) Silver Spring Networks, Inc - 575 Broadway Street - Redwood City CA 94063 - UNITED STATES - - 00-13-51 (hex) Niles Audio Corporation - 001351 (base 16) Niles Audio Corporation - 12331 SW 130th Street - Miami FL 33186 - UNITED STATES - - 00-13-52 (hex) Naztec, Inc. - 001352 (base 16) Naztec, Inc. - 820 Park Two Dr. - Sugar Land TX 77478 - UNITED STATES - - 00-13-53 (hex) HYDAC Filtertechnik GMBH - 001353 (base 16) HYDAC Filtertechnik GMBH - Industriegebiet - Sulzbach/Saar Saarland 66280 - GERMANY - - 00-13-54 (hex) Zcomax Technologies, Inc. - 001354 (base 16) Zcomax Technologies, Inc. - 98 Ford Road - Suite 3-F - Denville NJ 07834 - UNITED STATES - - 00-13-55 (hex) TOMEN Cyber-business Solutions, Inc. - 001355 (base 16) TOMEN Cyber-business Solutions, Inc. - 2-11-19 Kohnan - Minatoku-ku - TOKYO 108-0075 - JAPAN - - 00-13-56 (hex) FLIR Radiation Inc - 001356 (base 16) FLIR Radiation Inc - 100 Midland Rd - Oak Ridge TN 37830 - UNITED STATES - - 00-13-57 (hex) Soyal Technology Co., Ltd. - 001357 (base 16) Soyal Technology Co., Ltd. - 10F, No. 27, Lane 169, Kangning St., Shijr City, - 2F, No. 27, Lane 169, Kangning St., Shijr City, - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-13-58 (hex) Realm Systems, Inc. - 001358 (base 16) Realm Systems, Inc. - 9350 South 535 East - 9th Floor - Sandy Utah 84070 - UNITED STATES - - 00-13-59 (hex) ProTelevision Technologies A/S - 001359 (base 16) ProTelevision Technologies A/S - Marielundvej 16,2 - Herlev Copenhagen 2730 - DENMARK - - 00-13-5A (hex) Project T&E Limited - 00135A (base 16) Project T&E Limited - Room 3C, 2/F. Wah Shing Center, - 11 Shing Yip Street, - Kwun Tong, Kowloon, 852 - HONG KONG - - 00-13-5B (hex) PanelLink Cinema, LLC - 00135B (base 16) PanelLink Cinema, LLC - 1070 E Arques Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-13-5C (hex) OnSite Systems, Inc. - 00135C (base 16) OnSite Systems, Inc. - 3900 Freedom Circle - Suite 102 - Santa Clara CA 95054-1222 - UNITED STATES - - 00-13-5D (hex) NTTPC Communications, Inc. - 00135D (base 16) NTTPC Communications, Inc. - 3-25 Kanda Jinbo-cho - Chiyoda-ku Tokyo 101-0051 - JAPAN - - 00-13-5E (hex) EAB/RWI/K - 00135E (base 16) EAB/RWI/K - Färögatan 6 - Stockholm Kista 164 80 - SWEDEN - - 00-13-5F (hex) CISCO SYSTEMS, INC. - 00135F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-60 (hex) CISCO SYSTEMS, INC. - 001360 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-61 (hex) Biospace Co., Ltd. - 001361 (base 16) Biospace Co., Ltd. - 10th Floor, Poonglim Bldg, 823 Yeoksam 1-dong - Gangnam-gu Seoul 135-784 - KOREA, REPUBLIC OF - - 00-13-62 (hex) ShinHeung Precision Co., Ltd. - 001362 (base 16) ShinHeung Precision Co., Ltd. - DaeHa Bldg. 401 - 101-7 ShingilDong - YoungDungPoGu Seoul 150-050 - KOREA, REPUBLIC OF - - 00-13-63 (hex) Verascape, Inc. - 001363 (base 16) Verascape, Inc. - 1101 31st St., Suite #190 - Downers Grove IL 60515 - UNITED STATES - - 00-13-64 (hex) Paradigm Technology Inc.. - 001364 (base 16) Paradigm Technology Inc.. - 3F, No. 285, Sec.2, Ti-Ding Blvd Nei-Hu, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-13-65 (hex) Nortel - 001365 (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-13-66 (hex) Neturity Technologies Inc. - 001366 (base 16) Neturity Technologies Inc. - 830 Stewart Drive - Sunnyvale CA 94085 - UNITED STATES - - 00-13-67 (hex) Narayon. Co., Ltd. - 001367 (base 16) Narayon. Co., Ltd. - #502 Hyochang T/W 181-3 - Jamsil-dong, Songpa-gu - Seoul 138-220 - KOREA, REPUBLIC OF - - 00-13-68 (hex) Saab Danmark A/S - 001368 (base 16) Saab Danmark A/S - Alsion 2 - Soenderborg DK 6400 - DENMARK - - 00-13-69 (hex) Honda Electron Co., LED. - 001369 (base 16) Honda Electron Co., LED. - Kanematsu Building 3 Floor - 2-14-1, Kyobashi - Chuo-ku Tokyo 104-0031 - JAPAN - - 00-13-6A (hex) Hach Lange Sarl - 00136A (base 16) Hach Lange Sarl - 6, route de Compois - CP 212 - VESENAZ GENEVA 1222 - SWITZERLAND - - 00-13-6B (hex) E-TEC - 00136B (base 16) E-TEC - 2-17-14-503 Hakataekimae - Hakataku Fukuokashi - Fukuoka Fukuokaken 812-0011 - JAPAN - - 00-13-6C (hex) TomTom - 00136C (base 16) TomTom - Oosterdoksstraat 114 - 1011 DK Amsterdam - NETHERLANDS - - 00-13-6D (hex) Tentaculus AB - 00136D (base 16) Tentaculus AB - Studiegangen 3 - Ostersund Jamtland SE - 831 40 - SWEDEN - - 00-13-6E (hex) Techmetro Corp. - 00136E (base 16) Techmetro Corp. - 4F. Dongam B/D., 264-5, YangJae-Dong - Seocho-Ku - Seoul 137-130 - KOREA, REPUBLIC OF - - 00-13-6F (hex) PacketMotion, Inc. - 00136F (base 16) PacketMotion, Inc. - 2121 El Camino Real - 10th Floor - San Mateo CA 94403 - UNITED STATES - - 00-13-70 (hex) Nokia Danmark A/S - 001370 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-13-71 (hex) ARRIS Group, Inc. - 001371 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-13-72 (hex) Dell Inc - 001372 (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-13-73 (hex) BLwave Electronics Co., Ltd - 001373 (base 16) BLwave Electronics Co., Ltd - 23FGH, Block A,ZhenYe Building , BaoAn Nan Road , LuoHu , Shenzhen , China - ShenZhen GuangDong 518000 - CHINA - - 00-13-74 (hex) Atheros Communications, Inc. - 001374 (base 16) Atheros Communications, Inc. - 5480 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-13-75 (hex) American Security Products Co. - 001375 (base 16) American Security Products Co. - 11925 Pacific ave. - Fontana CA 92335 - UNITED STATES - - 00-13-76 (hex) Tabor Electronics Ltd. - 001376 (base 16) Tabor Electronics Ltd. - 9 Hatatsia St. - Tel Hanan 20302 - ISRAEL - - 00-13-77 (hex) Samsung Electronics CO., LTD - 001377 (base 16) Samsung Electronics CO., LTD - 416, Maetan 3Dong, Yeongtong-Gu - Suwon City, Geyonggi Do, Korea - Suwon Geyonggi 443742 - KOREA, REPUBLIC OF - - 00-13-78 (hex) Qsan Technology, Inc. - 001378 (base 16) Qsan Technology, Inc. - 4F., No.103, Ruihu St., Neihu Dist. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-13-79 (hex) PONDER INFORMATION INDUSTRIES LTD. - 001379 (base 16) PONDER INFORMATION INDUSTRIES LTD. - 14F,No.77,lane700, Chung-Cheng Road - Hsin-Tien City Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-13-7A (hex) Netvox Technology Co., Ltd. - 00137A (base 16) Netvox Technology Co., Ltd. - No.21-1 Sec. 1 Chung Hua West Road - Tainan 702 - TAIWAN, PROVINCE OF CHINA - - 00-13-7B (hex) Movon Corporation - 00137B (base 16) Movon Corporation - 5th, Hyunjuk B/D - 140-28, Samsung-dong, Kangnam-ku - Seoul 135-092 - KOREA, REPUBLIC OF - - 00-13-7C (hex) Kaicom co., Ltd. - 00137C (base 16) Kaicom co., Ltd. - #109, Gayang Techno Town 1487, Gayang-dong,Kangso-gu - Seoul 157-810 - KOREA, REPUBLIC OF - - 00-13-7D (hex) Dynalab, Inc. - 00137D (base 16) Dynalab, Inc. - 555 Lancaster Ave. - Reynoldsburg OH 43068 - UNITED STATES - - 00-13-7E (hex) CorEdge Networks, Inc. - 00137E (base 16) CorEdge Networks, Inc. - 7600 Boone Ave N - Suite 1 - Brooklyn Park MN 55428 - UNITED STATES - - 00-13-7F (hex) CISCO SYSTEMS, INC. - 00137F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-80 (hex) CISCO SYSTEMS, INC. - 001380 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-81 (hex) CHIPS & Systems, Inc. - 001381 (base 16) CHIPS & Systems, Inc. - 4750 Patrick Henry Drive - Santa Clara California 95054 - UNITED STATES - - 00-13-82 (hex) Cetacea Networks Corporation - 001382 (base 16) Cetacea Networks Corporation - 3708 West 36th Avenue - Vancouver British Columbia V6N 2S4 - CANADA - - 00-13-83 (hex) Application Technologies and Engineering Research Laboratory - 001383 (base 16) Application Technologies and Engineering Research Laboratory - Shinjuku 1-chome Bldg. - 1-10-4, Shinjuku - Shinjuku-ku Tokyo 160-0022 - JAPAN - - 00-13-84 (hex) Advanced Motion Controls - 001384 (base 16) Advanced Motion Controls - 3805 Calle Tecate - Camarillo California 93012 - UNITED STATES - - 00-13-85 (hex) Add-On Technology Co., LTD. - 001385 (base 16) Add-On Technology Co., LTD. - 1F, No.11, Lane 206, Da-An Road Sec. 1, - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-13-86 (hex) ABB Inc./Totalflow - 001386 (base 16) ABB Inc./Totalflow - 7051 Industrial Blvd. - Bartlesville OK 74006 - UNITED STATES - - 00-13-87 (hex) 27M Technologies AB - 001387 (base 16) 27M Technologies AB - Diskettgatan 11 - Linköping S-583 35 - SWEDEN - - 00-13-88 (hex) WiMedia Alliance - 001388 (base 16) WiMedia Alliance - 2400 Camino Ramon - Suite 375 - San Ramon CA 94583 - UNITED STATES - - 00-13-89 (hex) Redes de Telefonía Móvil S.A. - 001389 (base 16) Redes de Telefonía Móvil S.A. - C/Puerto de la Morcuera 14 B4 - Leganés Madrid 28918 - SPAIN - - 00-13-8A (hex) QINGDAO GOERTEK ELECTRONICS CO.,LTD. - 00138A (base 16) QINGDAO GOERTEK ELECTRONICS CO.,LTD. - Room 605,Innovation Building,Hi-tech Industrial Park, - QINGDAO SHANDONG 266061 - CHINA - - 00-13-8B (hex) Phantom Technologies LLC - 00138B (base 16) Phantom Technologies LLC - 7825 Fay Avenue, Suite 200 - La Jolla CA 92037 - UNITED STATES - - 00-13-8C (hex) Kumyoung.Co.Ltd - 00138C (base 16) Kumyoung.Co.Ltd - Seoul KY building, 40-17 Hangang Ro, 3Ga, Youngsan-Gu - Seoul 140-880 - KOREA, REPUBLIC OF - - 00-13-8D (hex) Kinghold - 00138D (base 16) Kinghold - 11F, No. 965, Jungjeng Rd. - Junghe Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-13-8E (hex) FOAB Elektronik AB - 00138E (base 16) FOAB Elektronik AB - Sankt Jorgens Vag 8 - Gothenburg 422 49 - SWEDEN - - 00-13-8F (hex) Asiarock Incorporation - 00138F (base 16) Asiarock Incorporation - P.O. Box957, Offshore Incorporations Centre - Road Town Tortola - VIRGIN ISLANDS, BRITISH - - 00-13-90 (hex) Termtek Computer Co., Ltd - 001390 (base 16) Termtek Computer Co., Ltd - 2F, No. 100, Li De St., - Chung Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-13-91 (hex) OUEN CO.,LTD. - 001391 (base 16) OUEN CO.,LTD. - Gotanda NT Bldg.7F, - 5-2 Higashi Gotanda 4-chome - Shinagawa-ku Tokyo 141-0022 - JAPAN - - 00-13-92 (hex) Ruckus Wireless - 001392 (base 16) Ruckus Wireless - 880 West Maude Avenue - Suite 101 - Sunnyvale CA 94045 - UNITED STATES - - 00-13-93 (hex) Panta Systems, Inc. - 001393 (base 16) Panta Systems, Inc. - 20450 Stevens Creek Blvd. - Suite 400 - Cupertino California 95014 - UNITED STATES - - 00-13-94 (hex) Infohand Co.,Ltd - 001394 (base 16) Infohand Co.,Ltd - Kranz-Techno #1207, 5442-1, Sangdaewon-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-819 - KOREA, REPUBLIC OF - - 00-13-95 (hex) congatec AG - 001395 (base 16) congatec AG - Auwiesenstrasse 5 - Deggendorf 94469 - GERMANY - - 00-13-96 (hex) Acbel Polytech Inc. - 001396 (base 16) Acbel Polytech Inc. - No.159,Sec.3, Tam-King Rd., - Tamsui Taipei 251 - TAIWAN, PROVINCE OF CHINA - - 00-13-97 (hex) Oracle Corporation - 001397 (base 16) Oracle Corporation - 4200 Network Circle - Santa Clara CA 95054 - UNITED STATES - - 00-13-98 (hex) TrafficSim Co.,Ltd - 001398 (base 16) TrafficSim Co.,Ltd - 23-9 Mita-biru 2F, Chiyoda 3-chome - Naka-ku, Nagoya - Aichi Non 460-0012 - JAPAN - - 00-13-99 (hex) STAC Corporation. - 001399 (base 16) STAC Corporation. - 2-16-37,fujimi - sayama-shi saitama 350-1306 - JAPAN - - 00-13-9A (hex) K-ubique ID Corp. - 00139A (base 16) K-ubique ID Corp. - Yamasan Bldg.8F, - Nihonbashi Honcho2-6-13 - Chuo-ku Tokyo 103-0023 - JAPAN - - 00-13-9B (hex) ioIMAGE Ltd. - 00139B (base 16) ioIMAGE Ltd. - 3 Maskit Street - Herzliya Pituach IL 46733 - ISRAEL - - 00-13-9C (hex) Exavera Technologies, Inc. - 00139C (base 16) Exavera Technologies, Inc. - 195 New Hampshire Avenue - Suite 155 - Portsmouth NH 03801 - UNITED STATES - - 00-13-9D (hex) Marvell Hispana S.L. - 00139D (base 16) Marvell Hispana S.L. - C/Charles Robert Darwin, 2 - Parc Tecnologic - Valencia Paterna 46980 - SPAIN - - 00-13-9E (hex) Ciara Technologies Inc. - 00139E (base 16) Ciara Technologies Inc. - 9300 Trans Canada Highway - Saint-Laurent Quebec H4S 1K5 - CANADA - - 00-13-9F (hex) Electronics Design Services, Co., Ltd. - 00139F (base 16) Electronics Design Services, Co., Ltd. - 5-10-20 Tokumaru - Itabashi-ku Tokyo 175-0083 - JAPAN - - 00-13-A0 (hex) ALGOSYSTEM Co., Ltd. - 0013A0 (base 16) ALGOSYSTEM Co., Ltd. - 656 kobirao mihara-cho - sakai osaka 587-0021 - JAPAN - - 00-13-A1 (hex) Crow Electronic Engeneering - 0013A1 (base 16) Crow Electronic Engeneering - 12 Kinneret st. - Airport City - ISRAEL - - 00-13-A2 (hex) MaxStream, Inc - 0013A2 (base 16) MaxStream, Inc - 355 South 520 West Suite 180 - Lindon Ut 84042 - UNITED STATES - - 00-13-A3 (hex) Siemens Com CPE Devices - 0013A3 (base 16) Siemens Com CPE Devices - 4849 Alpha Road - Dallas Texas 75244 - UNITED STATES - - 00-13-A4 (hex) KeyEye Communications - 0013A4 (base 16) KeyEye Communications - 9785 Goethe - Sacramento CA 95827 - UNITED STATES - - 00-13-A5 (hex) General Solutions, LTD. - 0013A5 (base 16) General Solutions, LTD. - 5902 Sovereign Drive - Houston Texas 77036 - UNITED STATES - - 00-13-A6 (hex) Extricom Ltd - 0013A6 (base 16) Extricom Ltd - Glil Yam - Herzlia 46905 - ISRAEL - - 00-13-A7 (hex) BATTELLE MEMORIAL INSTITUTE - 0013A7 (base 16) BATTELLE MEMORIAL INSTITUTE - 505 KING AVE - COLUMBUS OHIO 43201 - UNITED STATES - - 00-13-A8 (hex) Tanisys Technology - 0013A8 (base 16) Tanisys Technology - 11001 Lakeline blvd - Building 1 Suite 150 - Austin TX 78717 - UNITED STATES - - 00-13-A9 (hex) Sony Corporation - 0013A9 (base 16) Sony Corporation - Gotenyama Tec 5-1-2 - Kitashinagawa, - Shinagawa-ku Tokyo 141-0001 - JAPAN - - 00-13-AA (hex) ALS & TEC Ltd. - 0013AA (base 16) ALS & TEC Ltd. - 6 B. Kazachya str. - Saratov Saratov region 410600 - RUSSIAN FEDERATION - - 00-13-AB (hex) Telemotive AG - 0013AB (base 16) Telemotive AG - Breitwiesen - Muehlhausen Baden Wuerttemberg 73347 - GERMANY - - 00-13-AC (hex) Sunmyung Electronics Co., LTD - 0013AC (base 16) Sunmyung Electronics Co., LTD - LARGO-PLAZA 8F, Janghang-Dong - 857-1, Ilsan-Ku - Koyang Kyungki 411-837 - KOREA, REPUBLIC OF - - 00-13-AD (hex) Sendo Ltd - 0013AD (base 16) Sendo Ltd - Hatchford Brook - Hatchford Way - Birmingham West Midlands B26 3RZ - UNITED KINGDOM - - 00-13-AE (hex) Radiance Technologies, Inc. - 0013AE (base 16) Radiance Technologies, Inc. - 350 Wynn Dr. - Huntsville Alabama 35805 - UNITED STATES - - 00-13-AF (hex) NUMA Technology,Inc. - 0013AF (base 16) NUMA Technology,Inc. - 4F,No778,Sec 4,Patch Rd. - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-13-B0 (hex) Jablotron - 0013B0 (base 16) Jablotron - Pod Skalkou 33 - Jablonec nad Nisou 46601 - CZECH REPUBLIC - - 00-13-B1 (hex) Intelligent Control Systems (Asia) Pte Ltd - 0013B1 (base 16) Intelligent Control Systems (Asia) Pte Ltd - 70 Ubi Crescent #01-12 - Ubi Tech Park - 408570 - SINGAPORE - - 00-13-B2 (hex) Carallon Limited - 0013B2 (base 16) Carallon Limited - Studio G20 Shepherds Building - Rockley Road - London W14 0DA - UNITED KINGDOM - - 00-13-B3 (hex) Ecom Communications Technology Co., Ltd. - 0013B3 (base 16) Ecom Communications Technology Co., Ltd. - Floor 7, Machinery Industry Building, No.22, - Baiwanzhuang Street, Xicheng District - Beijing - CHINA - - 00-13-B4 (hex) Appear TV - 0013B4 (base 16) Appear TV - Lilleakerveien 2B - P.O. Box 8 Lilleaker - NO-0216 Oslo - NORWAY - - 00-13-B5 (hex) Wavesat - 0013B5 (base 16) Wavesat - 1375, Trans-Canada Highway - Suite 300 - Dorval Quebec H9P 2W8 - CANADA - - 00-13-B6 (hex) Sling Media, Inc. - 0013B6 (base 16) Sling Media, Inc. - 1840 Gateway Center - 2nd Floor - San Mateo CA 94404 - UNITED STATES - - 00-13-B7 (hex) Scantech ID - 0013B7 (base 16) Scantech ID - Vanadiumweg 22 - Amersfoort Utrecht 3812 PZ - NETHERLANDS - - 00-13-B8 (hex) RyCo Electronic Systems Limited - 0013B8 (base 16) RyCo Electronic Systems Limited - Unit E, Cartel Business Estate - Edinburgh Way - Harlow Essex CM20 2TT - UNITED KINGDOM - - 00-13-B9 (hex) BM SPA - 0013B9 (base 16) BM SPA - VIA MILANO 54/56 - Rozzano 20089 - ITALY - - 00-13-BA (hex) ReadyLinks Inc - 0013BA (base 16) ReadyLinks Inc - 6595 Edenvale Boulevard - Suite 180 - Eden Prairie MN 55346 - UNITED STATES - - 00-13-BB (hex) Smartvue Corporation - 0013BB (base 16) Smartvue Corporation - 102 Woodmont Boulevard - Suite 200 - Nashville TN 37205 - UNITED STATES - - 00-13-BC (hex) Artimi Ltd - 0013BC (base 16) Artimi Ltd - Betjeman House - 104 Hills Road - Cambridge Cambridgeshire CB2 1LQ - UNITED KINGDOM - - 00-13-BD (hex) HYMATOM SA - 0013BD (base 16) HYMATOM SA - Zone Industrielle - 175 rue de Massacan - VENDARGUES HERAULT 34740 - FRANCE - - 00-13-BE (hex) Virtual Conexions - 0013BE (base 16) Virtual Conexions - 410 rue St-Nicolas, suite 600 - Montréal QUÉBEC H2Y 2P5 - CANADA - - 00-13-BF (hex) Media System Planning Corp. - 0013BF (base 16) Media System Planning Corp. - 4F Velco-Kuromon Bldg. - 3-14-5 Ueno, - Taito-ku, Tokyo 110-0005 - JAPAN - - 00-13-C0 (hex) Trix Tecnologia Ltda. - 0013C0 (base 16) Trix Tecnologia Ltda. - Rua da Paz, 1957 - Chácara Santo Antônio - São Paulo 04713-002 - BRAZIL - - 00-13-C1 (hex) Asoka USA Corporation - 0013C1 (base 16) Asoka USA Corporation - 558 Pilgrim Drive - Unit H - Foster City CA 94404 - UNITED STATES - - 00-13-C2 (hex) WACOM Co.,Ltd - 0013C2 (base 16) WACOM Co.,Ltd - 2-510-1 Toyonodai Otone-machi - Kitasaitama-gun Saitama 349-1148 - JAPAN - - 00-13-C3 (hex) CISCO SYSTEMS, INC. - 0013C3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-C4 (hex) CISCO SYSTEMS, INC. - 0013C4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-13-C5 (hex) LIGHTRON FIBER-OPTIC DEVICES INC. - 0013C5 (base 16) LIGHTRON FIBER-OPTIC DEVICES INC. - 51-1 Moonpyung-Dong, Taeduck-Gu - Taejon 306-220 - KOREA, REPUBLIC OF - - 00-13-C6 (hex) OpenGear, Inc - 0013C6 (base 16) OpenGear, Inc - 7984 South Welby Park #101 - Salt Lake City UTAH 84088 - UNITED STATES - - 00-13-C7 (hex) IONOS Co.,Ltd. - 0013C7 (base 16) IONOS Co.,Ltd. - 1-36-18 Miyasaka - Setagaya-ku Tokyo 156-0051 - JAPAN - - 00-13-C8 (hex) ADB Broadband Italia - 0013C8 (base 16) ADB Broadband Italia - VIALE SARCA 222 - MILANO 20126 - ITALY - - 00-13-C9 (hex) Beyond Achieve Enterprises Ltd. - 0013C9 (base 16) Beyond Achieve Enterprises Ltd. - - P.O. Box 957, Offshore Incorporations Centre - Road Town Tortola - VIRGIN ISLANDS, BRITISH - - 00-13-CA (hex) Pico Digital - 0013CA (base 16) Pico Digital - 6260 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 00-13-CB (hex) Zenitel Norway AS - 0013CB (base 16) Zenitel Norway AS - Sandaker v 24 c - PO Box 4498 - Oslo 0403 - NORWAY - - 00-13-CC (hex) Tall Maple Systems - 0013CC (base 16) Tall Maple Systems - 85 Saratoga Ave Suite 139 - Santa Clara CA 95051 - UNITED STATES - - 00-13-CD (hex) MTI co. LTD - 0013CD (base 16) MTI co. LTD - 166-10 Karak-dong - R&D Group 3 - Songpa-ku Seoul 138-810 - KOREA, REPUBLIC OF - - 00-13-CE (hex) Intel Corporate - 0013CE (base 16) Intel Corporate - Lot 8, Jalan Hi-tech 2/3 - Kulim Hi-Tech Park - Kedah 09000 - MALAYSIA - - 00-13-CF (hex) 4Access Communications - 0013CF (base 16) 4Access Communications - 1 N. LaSalle St. - Suite 2015 - Chicago IL 60602 - UNITED STATES - - 00-13-D0 (hex) t+ Medical Ltd - 0013D0 (base 16) t+ Medical Ltd - 174E Milton Park - Abingdon OX14 4SE - UNITED KINGDOM - - 00-13-D1 (hex) KIRK telecom A/S - 0013D1 (base 16) KIRK telecom A/S - Langmarksvej 34 - Horsens 8700 - DENMARK - - 00-13-D2 (hex) PAGE IBERICA, S.A. - 0013D2 (base 16) PAGE IBERICA, S.A. - AV. DE LA INDUSTRIA, 24 - TRES CANTOS MADRID 28760 - SPAIN - - 00-13-D3 (hex) MICRO-STAR INTERNATIONAL CO., LTD. - 0013D3 (base 16) MICRO-STAR INTERNATIONAL CO., LTD. - NO. 69, LI-DE ST. - JUNG-HE CITY TAIPEI HSIEN 235 - TAIWAN, PROVINCE OF CHINA - - 00-13-D4 (hex) ASUSTek COMPUTER INC. - 0013D4 (base 16) ASUSTek COMPUTER INC. - No.5 Shing Yeh Street - Kwei Shan Hsiang - Tao Yuan Hsien 333 - TAIWAN, PROVINCE OF CHINA - - 00-13-D5 (hex) RuggedCom - 0013D5 (base 16) RuggedCom - 300 Applewood Crescent (Unit 1) - Concord, Ontario L4K 5C7 - CANADA - - 00-13-D6 (hex) TII NETWORK TECHNOLOGIES, INC. - 0013D6 (base 16) TII NETWORK TECHNOLOGIES, INC. - 1385 AKRON STREET - COPIAGUE NY 11726 - UNITED STATES - - 00-13-D7 (hex) SPIDCOM Technologies SA - 0013D7 (base 16) SPIDCOM Technologies SA - 137 avenue du General LECLERC - BOURG LA REINE 92340 - FRANCE - - 00-13-D8 (hex) Princeton Instruments - 0013D8 (base 16) Princeton Instruments - 3660 Quakerbridge Road - Trenton NJ 08619 - UNITED STATES - - 00-13-D9 (hex) Matrix Product Development, Inc. - 0013D9 (base 16) Matrix Product Development, Inc. - 13 North Bird Street - Sun Prairie WI 53590 - UNITED STATES - - 00-13-DA (hex) Diskware Co., Ltd - 0013DA (base 16) Diskware Co., Ltd - 1-4-12 Kiba - Nakojikiba Bldg.5F - Koto-ku Tokyo 135-0042 - JAPAN - - 00-13-DB (hex) SHOEI Electric Co.,Ltd - 0013DB (base 16) SHOEI Electric Co.,Ltd - 1-29-2,Wakabayashi - Setagaya-ku Tokyo 154-0023 - JAPAN - - 00-13-DC (hex) IBTEK INC. - 0013DC (base 16) IBTEK INC. - 16F, 30, Pei-Ping East Rd., - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-13-DD (hex) Abbott Diagnostics - 0013DD (base 16) Abbott Diagnostics - 5440 Patrick Henry Drive - Santa Clara CA 95054 - UNITED STATES - - 00-13-DE (hex) Adapt4, LLC - 0013DE (base 16) Adapt4, LLC - 1050 W Nasa Blvd, - Suite 134 - Melbourne FL 32901 - UNITED STATES - - 00-13-DF (hex) Ryvor Corp. - 0013DF (base 16) Ryvor Corp. - 15145 Red Hill Ave. - Suite B - Tustin CA 92780 - UNITED STATES - - 00-13-E0 (hex) Murata Manufacturing Co., Ltd. - 0013E0 (base 16) Murata Manufacturing Co., Ltd. - 2288, Oaza-Ohshinohara, Yasu-cho, - Yasu-gun Shiga 520-2393 - JAPAN - - 00-13-E1 (hex) Iprobe AB - 0013E1 (base 16) Iprobe AB - Finlandsgatan 12 - Kista SE-16474 - SWEDEN - - 00-13-E2 (hex) GeoVision Inc. - 0013E2 (base 16) GeoVision Inc. - 9F.,No.246,Sec.1, - Neihu Rd,Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-13-E3 (hex) CoVi Technologies, Inc. - 0013E3 (base 16) CoVi Technologies, Inc. - 6300 Bridgepoint Parkway - Suite 300, Bldg. II - Austin Texas 78730 - UNITED STATES - - 00-13-E4 (hex) YANGJAE SYSTEMS CORP. - 0013E4 (base 16) YANGJAE SYSTEMS CORP. - 1202. HANSHIN IT TOWER Guro-3Dong, - Guro-Gu - Seoul 152-848 - KOREA, REPUBLIC OF - - 00-13-E5 (hex) TENOSYS, INC. - 0013E5 (base 16) TENOSYS, INC. - Seojin B/D, 1564-1, Seocho-dong, - Seocho-gu - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-13-E6 (hex) Technolution - 0013E6 (base 16) Technolution - Zuidelijkhalfrond 1 - GOUDA ZH 2801 DD - NETHERLANDS - - 00-13-E7 (hex) Halcro - 0013E7 (base 16) Halcro - Suite 1, Level 1 - 8 Greenhill Rd - Wayville South Australia 5034 - AUSTRALIA - - 00-13-E8 (hex) Intel Corporate - 0013E8 (base 16) Intel Corporate - Lot 8, Jalan Hi-tech 2/3 - Kulim Hi-Tech Park - Kedah 09000 - MALAYSIA - - 00-13-E9 (hex) VeriWave, Inc. - 0013E9 (base 16) VeriWave, Inc. - 9600 SW Oak St. - Portland OR 97223 - UNITED STATES - - 00-13-EA (hex) Kamstrup A/S - 0013EA (base 16) Kamstrup A/S - Industrivej 28 - Stilling 8660 - DENMARK - - 00-13-EB (hex) Sysmaster Corporation - 0013EB (base 16) Sysmaster Corporation - 5801 Christie Ave. - Suite 400 - Emeryville CA 94608 - UNITED STATES - - 00-13-EC (hex) Netsnapper Technologies SARL - 0013EC (base 16) Netsnapper Technologies SARL - 2160 Century Park East 1806 - Los Angeles CA 90067-2236 - UNITED STATES - - 00-13-ED (hex) PSIA - 0013ED (base 16) PSIA - 517-13 Induspis 5th - SangDaeWonDong JungWonGu - SungNam KyungGi - KOREA, REPUBLIC OF - - 00-13-EE (hex) JBX Designs Inc. - 0013EE (base 16) JBX Designs Inc. - PO Box 970158 - Boca Raton FL 33497 - UNITED STATES - - 00-13-EF (hex) Kingjon Digital Technology Co.,Ltd - 0013EF (base 16) Kingjon Digital Technology Co.,Ltd - Room 827,Huanan Dianli Bulding,No.2050 - Shenzhen GuangDong 518031 - CHINA - - 00-13-F0 (hex) Wavefront Semiconductor - 0013F0 (base 16) Wavefront Semiconductor - 4746 44th Ave SW - Suite 201 - Seattle WA 98116 - UNITED STATES - - 00-13-F1 (hex) AMOD Technology Co., Ltd. - 0013F1 (base 16) AMOD Technology Co., Ltd. - 2F., No. 16, Prosperity Road II - Science-Based Industrial Park, - Hsinchu, 30078 - TAIWAN, PROVINCE OF CHINA - - 00-13-F2 (hex) Klas Ltd - 0013F2 (base 16) Klas Ltd - Bracetown Business Park - Clonee Co Meath - IRELAND - - 00-13-F3 (hex) Giga-byte Communications Inc. - 0013F3 (base 16) Giga-byte Communications Inc. - 8F, No.43, Fu-Hsin Road. Hsin-Tien - Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-13-F4 (hex) Psitek (Pty) Ltd - 0013F4 (base 16) Psitek (Pty) Ltd - The Vineyards Office Estate - 99 Jip de Jager Drive - Tyger Valley Cape Town 7530 - SOUTH AFRICA - - 00-13-F5 (hex) Akimbi Systems - 0013F5 (base 16) Akimbi Systems - 1400 Fashion Island Blvd - Suite 900 - San Mateo CA 94404 - UNITED STATES - - 00-13-F6 (hex) Cintech - 0013F6 (base 16) Cintech - 21a route de la wantzenau - Hoenheim 67800 - FRANCE - - 00-13-F7 (hex) SMC Networks, Inc. - 0013F7 (base 16) SMC Networks, Inc. - 38 Tesla - Irvine CA 92618 - UNITED STATES - - 00-13-F8 (hex) Dex Security Solutions - 0013F8 (base 16) Dex Security Solutions - 10 Junction Road Parktown - 2nd Floor BP House - Johannesburg Guteng 2000 - SOUTH AFRICA - - 00-13-F9 (hex) Cavera Systems - 0013F9 (base 16) Cavera Systems - 2355 Oakland Rd, Suite#33 - San Jose CA 95131 - UNITED STATES - - 00-13-FA (hex) LifeSize Communications, Inc - 0013FA (base 16) LifeSize Communications, Inc - 901 S. Mopac - Bldg 3, Suite 300 - Austin TX 78746 - UNITED STATES - - 00-13-FB (hex) RKC INSTRUMENT INC. - 0013FB (base 16) RKC INSTRUMENT INC. - 16-6, Kugahara 5-chome, - Ohta-ku Tokyo 146-8515 - JAPAN - - 00-13-FC (hex) SiCortex, Inc - 0013FC (base 16) SiCortex, Inc - 3 Clocktower Place - Suite 210 - Maynard MA 01754 - UNITED STATES - - 00-13-FD (hex) Nokia Danmark A/S - 0013FD (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-13-FE (hex) GRANDTEC ELECTRONIC CORP. - 0013FE (base 16) GRANDTEC ELECTRONIC CORP. - 8F,NO.268,Lian Cheng Rd.,Chung Ho City, - Hsien 235 - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-13-FF (hex) Dage-MTI of MC, Inc. - 0013FF (base 16) Dage-MTI of MC, Inc. - 701 N. Roeske Ave. - Michigan City IN 46360 - UNITED STATES - - 00-14-00 (hex) MINERVA KOREA CO., LTD - 001400 (base 16) MINERVA KOREA CO., LTD - #203, SH Sienne, Seohyeon-Dong - Bundang-Gu - Seongnam-Si Gyeonggi-Do 463-821 - KOREA, REPUBLIC OF - - 00-14-01 (hex) Rivertree Networks Corp. - 001401 (base 16) Rivertree Networks Corp. - R#304, K-Center, 1591-9 - Burim-dong, Dongahn-gu - Anyang-si Kyunggi-do 431-815 - KOREA, REPUBLIC OF - - 00-14-02 (hex) kk-electronic a/s - 001402 (base 16) kk-electronic a/s - Cypresvej 6 - Herning 7400 - DENMARK - - 00-14-03 (hex) Renasis, LLC - 001403 (base 16) Renasis, LLC - 1530 N. State St. - Suite E - Lehi UT 84043 - UNITED STATES - - 00-14-04 (hex) ARRIS Group, Inc. - 001404 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-14-05 (hex) OpenIB, Inc. - 001405 (base 16) OpenIB, Inc. - OpenFabrics, Inc., c/o QLogic Corporation - 2071 Stierlin Court, Suite 200 - Mountain View CA 94043-4655 - UNITED STATES - - 00-14-06 (hex) Go Networks - 001406 (base 16) Go Networks - 126 Yigal Alon st. - Tel Aviv 67443 - ISRAEL - - 00-14-07 (hex) Sperian Protection Instrumentation - 001407 (base 16) Sperian Protection Instrumentation - 651 South Main Street - Middletown CT 06457 - UNITED STATES - - 00-14-08 (hex) Eka Systems Inc. - 001408 (base 16) Eka Systems Inc. - 20251 Century Blvd - Suite 120 - Germantown MD 20874 - UNITED STATES - - 00-14-09 (hex) MAGNETI MARELLI S.E. S.p.A. - 001409 (base 16) MAGNETI MARELLI S.E. S.p.A. - ZI Nord, Allee d'Argenson - CHATELLERAULT 86100 - FRANCE - - 00-14-0A (hex) WEPIO Co., Ltd. - 00140A (base 16) WEPIO Co., Ltd. - #1125, Opus1, Gurodongcomplex building - 611-26,Guro-dong,Guro-gu, - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-14-0B (hex) FIRST INTERNATIONAL COMPUTER, INC. - 00140B (base 16) FIRST INTERNATIONAL COMPUTER, INC. - FIC BUILDING, NO.300, YANG GUANG ST., - NEIHU - TAIPEI COUNTY 114 - TAIWAN, PROVINCE OF CHINA - - 00-14-0C (hex) GKB CCTV CO., LTD. - 00140C (base 16) GKB CCTV CO., LTD. - 7F, No. 1, Lane 641, - Shen Ling South Rd., - Ta Ya Hsiang, TAICHUNG 428 - TAIWAN, PROVINCE OF CHINA - - 00-14-0D (hex) Nortel - 00140D (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-14-0E (hex) Nortel - 00140E (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-14-0F (hex) Federal State Unitary Enterprise Leningrad R&D Institute of - 00140F (base 16) Federal State Unitary Enterprise Leningrad R&D Institute of - 11 Warshawskaya St. - St. Petersburg 196128 - RUSSIAN FEDERATION - - 00-14-10 (hex) Suzhou Keda Technology CO.,Ltd - 001410 (base 16) Suzhou Keda Technology CO.,Ltd - 131,Jinshan Road - Suzhou JiangSu 215011 - CHINA - - 00-14-11 (hex) Deutschmann Automation GmbH & Co. KG - 001411 (base 16) Deutschmann Automation GmbH & Co. KG - Carl-Zeiss-Str. 8 - Bad Camberg D - 65520 - GERMANY - - 00-14-12 (hex) S-TEC electronics AG - 001412 (base 16) S-TEC electronics AG - Industriestrasse 49 - Zug 6300 - SWITZERLAND - - 00-14-13 (hex) Trebing & Himstedt Prozeßautomation GmbH & Co. KG - 001413 (base 16) Trebing & Himstedt Prozeßautomation GmbH & Co. KG - Wilhelm-Hennemann-Straße 13 - Schwerin Mecklenburg-Vorpommern 19061 - GERMANY - - 00-14-14 (hex) Jumpnode Systems LLC. - 001414 (base 16) Jumpnode Systems LLC. - 800 Washington Ave N. - Suite 309 - Minneapolis MN 55041 - UNITED STATES - - 00-14-15 (hex) Intec Automation Inc. - 001415 (base 16) Intec Automation Inc. - 2751 Arbutus Rd. - Victoria British Columbia V8N 5X7 - CANADA - - 00-14-16 (hex) Scosche Industries, Inc. - 001416 (base 16) Scosche Industries, Inc. - PO Box 2901 - Oxnard CA 93034 - UNITED STATES - - 00-14-17 (hex) RSE Informations Technologie GmbH - 001417 (base 16) RSE Informations Technologie GmbH - Silberbergstrasse 9 - Wolfsberg Kärnten 9400 - AUSTRIA - - 00-14-18 (hex) C4Line - 001418 (base 16) C4Line - 1001 Hyundai Parisian, - 907-10 Mok5-Dong - Yangchun-Gu Seoul 158-050 - KOREA, REPUBLIC OF - - 00-14-19 (hex) SIDSA - 001419 (base 16) SIDSA - PTM - TORRES QUEVEDO 1 - TRES CANTOS MADRID 28760 - SPAIN - - 00-14-1A (hex) DEICY CORPORATION - 00141A (base 16) DEICY CORPORATION - 3-3-6,Sakae-cho,Hamura-shi, - Tokyo 205-0002 - JAPAN - - 00-14-1B (hex) CISCO SYSTEMS, INC. - 00141B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-1C (hex) CISCO SYSTEMS, INC. - 00141C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-1D (hex) LTi DRIVES GmbH - 00141D (base 16) LTi DRIVES GmbH - Gewerbestrasse 5-9 - Lahnau Hessen 35633 - GERMANY - - 00-14-1E (hex) P.A. Semi, Inc. - 00141E (base 16) P.A. Semi, Inc. - 3965 Freedom Circle, Fl 8 - Santa Clara CA 95054 - UNITED STATES - - 00-14-1F (hex) SunKwang Electronics Co., Ltd - 00141F (base 16) SunKwang Electronics Co., Ltd - #365(Techno-park, 301 dong, 901 ho,) Samjung-dong, Ohjung-ku, - Bucheon-shi Kyunggi-do 421-809 - KOREA, REPUBLIC OF - - 00-14-20 (hex) G-Links networking company - 001420 (base 16) G-Links networking company - 1FL. NO.15-49, MING DER SECOND ROAD, - CHI DU DISTRICT, - Keelung 206 - TAIWAN, PROVINCE OF CHINA - - 00-14-21 (hex) Total Wireless Technologies Pte. Ltd. - 001421 (base 16) Total Wireless Technologies Pte. Ltd. - Blk 1003, Bukit Merah Central, #04-18 - Technopreneur Centre - 159836 - SINGAPORE - - 00-14-22 (hex) Dell Inc - 001422 (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-14-23 (hex) J-S Co. NEUROCOM - 001423 (base 16) J-S Co. NEUROCOM - Energeticheskii proezd, 6 - Moscow 111250 - RUSSIAN FEDERATION - - 00-14-24 (hex) Merry Electrics CO., LTD. - 001424 (base 16) Merry Electrics CO., LTD. - NO.22,23rd ROAD - PARK TAICHUNG, - TAICHUNG CITY 40850 - TAIWAN, PROVINCE OF CHINA - - 00-14-25 (hex) Galactic Computing Corp. - 001425 (base 16) Galactic Computing Corp. - 1/F - 12 Lee Chung Street - Chai Wan District - HONG KONG - - 00-14-26 (hex) NL Technology - 001426 (base 16) NL Technology - 800 Turnpike Street - STE 100 - North Andover MA 01845 - UNITED STATES - - 00-14-27 (hex) JazzMutant - 001427 (base 16) JazzMutant - 2 allee du Doyen Georges Brus - Pessac 33600 - FRANCE - - 00-14-28 (hex) Vocollect, Inc - 001428 (base 16) Vocollect, Inc - 703 Rodi Road - Pittsburgh PA 15235 - UNITED STATES - - 00-14-29 (hex) V Center Technologies Co., Ltd. - 001429 (base 16) V Center Technologies Co., Ltd. - 7F-7, NO.35, Hsintai Rd. - Jubei City Hsinchu 302 - TAIWAN, PROVINCE OF CHINA - - 00-14-2A (hex) Elitegroup Computer System Co., Ltd - 00142A (base 16) Elitegroup Computer System Co., Ltd - No.22, Alley 38, Lane 91, Sec. 1, - Nei Hu Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-14-2B (hex) Edata Communication Inc. - 00142B (base 16) Edata Communication Inc. - 2F-1, No. 872, Chung-Cheng Rd - Chung-Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-14-2C (hex) Koncept International, Inc. - 00142C (base 16) Koncept International, Inc. - 2500 E Foothill Blvd. #407 - Pasadena CA 91107 - UNITED STATES - - 00-14-2D (hex) Toradex AG - 00142D (base 16) Toradex AG - Altsagenstrasse 5 - Horw LU 6048 - SWITZERLAND - - 00-14-2E (hex) 77 Elektronika Kft. - 00142E (base 16) 77 Elektronika Kft. - Fehervari ut 98. - Budapest H-1163 - HUNGARY - - 00-14-2F (hex) WildPackets - 00142F (base 16) WildPackets - 1340 Treat Boulevard - Suite 500 - Walnut Creek CA 94597 - UNITED STATES - - 00-14-30 (hex) ViPowER, Inc - 001430 (base 16) ViPowER, Inc - 9F., No.205-3, Sec. 3, Beisin Rd - Sindian Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 00-14-31 (hex) PDL Electronics Ltd - 001431 (base 16) PDL Electronics Ltd - 81 Austin Street - Napier Hawkes Bay 4015 - NEW ZEALAND - - 00-14-32 (hex) Tarallax Wireless, Inc. - 001432 (base 16) Tarallax Wireless, Inc. - 10 West 100 South, - Suite 600 - Salt Lake City UT 84101 - UNITED STATES - - 00-14-33 (hex) Empower Technologies(Canada) Inc. - 001433 (base 16) Empower Technologies(Canada) Inc. - Unit 405 - 5600 Parkwood Way, - Richmond British Columbia V6V 2M2 - CANADA - - 00-14-34 (hex) Keri Systems, Inc - 001434 (base 16) Keri Systems, Inc - 2305 Bering Dr - San Jose CA 95131 - UNITED STATES - - 00-14-35 (hex) CityCom Corp. - 001435 (base 16) CityCom Corp. - 3F., No.532, Sec. 2, - Jhongshan Rd. - Jhonghe City Taipei Hsien 23557 - TAIWAN, PROVINCE OF CHINA - - 00-14-36 (hex) Qwerty Elektronik AB - 001436 (base 16) Qwerty Elektronik AB - Gryt 44 - SE-148 92 - Ösmo 610 60 - SWEDEN - - 00-14-37 (hex) GSTeletech Co.,Ltd. - 001437 (base 16) GSTeletech Co.,Ltd. - 1385-14, Juan-Dong, Nam-gu - Incheon 402-200 - KOREA, REPUBLIC OF - - 00-14-38 (hex) Hewlett-Packard Company - 001438 (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS070405 - Houston TX 77070 - UNITED STATES - - 00-14-39 (hex) Blonder Tongue Laboratories, Inc. - 001439 (base 16) Blonder Tongue Laboratories, Inc. - One Jake Brown Road - Old Bridge New Jersey 08857 - UNITED STATES - - 00-14-3A (hex) RAYTALK INTERNATIONAL SRL - 00143A (base 16) RAYTALK INTERNATIONAL SRL - St. Marecchia 79 - Verucchio (RN) 47826 - ITALY - - 00-14-3B (hex) Sensovation AG - 00143B (base 16) Sensovation AG - Markhallen -Str - Radolfzell Baden-Württemberg 78315 - GERMANY - - 00-14-3C (hex) Rheinmetall Canada Inc. - 00143C (base 16) Rheinmetall Canada Inc. - 225 boul du seminaire sud - St-Jean-sur-Richelieu Quebec J3B 8E9 - CANADA - - 00-14-3D (hex) Aevoe Inc. - 00143D (base 16) Aevoe Inc. - 11F, No 23, Keelung Road - Taipei HsinYi District 110 - TAIWAN, PROVINCE OF CHINA - - 00-14-3E (hex) AirLink Communications, Inc. - 00143E (base 16) AirLink Communications, Inc. - 3159 Corporate Place - Hayward CA 94545 - UNITED STATES - - 00-14-3F (hex) Hotway Technology Corporation - 00143F (base 16) Hotway Technology Corporation - No. 81, Hsin Tai 5th Road Section 1 - 11F-3 - ShiJr Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-14-40 (hex) ATOMIC Corporation - 001440 (base 16) ATOMIC Corporation - MAMPO BLDG - 1-3-11,ASAKUSABASHI - TAITO-KU TOKYO 111-0053 - JAPAN - - 00-14-41 (hex) Innovation Sound Technology Co., LTD. - 001441 (base 16) Innovation Sound Technology Co., LTD. - Building 2th.,Cuihai Industrial Area, - Huaide, Fuyong Town - Shenzhen Guangdong 518103 - CHINA - - 00-14-42 (hex) ATTO CORPORATION - 001442 (base 16) ATTO CORPORATION - 1-25-23 Hongo, - Bunkyo-ku, - Tokyo 113-8425 - JAPAN - - 00-14-43 (hex) Consultronics Europe Ltd - 001443 (base 16) Consultronics Europe Ltd - Electron Way - Chandlers Ford Hants SO53 4SE - UNITED KINGDOM - - 00-14-44 (hex) Grundfos Holding - 001444 (base 16) Grundfos Holding - Poul Due Jensensvej 7 - Bjerringbro DK8850 - DENMARK - - 00-14-45 (hex) Telefon-Gradnja d.o.o. - 001445 (base 16) Telefon-Gradnja d.o.o. - Plesivicka 3 - Sveta Nedelja Zupanija Zagrebacka 10431 - CROATIA - - 00-14-46 (hex) SuperVision Solutions LLC - 001446 (base 16) SuperVision Solutions LLC - 762 Industrial Dr. - Elmhurst IL 60126 - UNITED STATES - - 00-14-47 (hex) BOAZ Inc. - 001447 (base 16) BOAZ Inc. - 282 Pukok-ri SongSan-myon Dangzin-gun Chungcheongnam-do, 343-834 - #301, 1429-7 SeoCho-dong - Seoul SeoCho-gu 137-070 - KOREA, REPUBLIC OF - - 00-14-48 (hex) Inventec Multimedia & Telecom Corporation - 001448 (base 16) Inventec Multimedia & Telecom Corporation - 5F,NO.396,Sec.1 Nei-Hu Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-14-49 (hex) Sichuan Changhong Electric Ltd. - 001449 (base 16) Sichuan Changhong Electric Ltd. - No.35,East MianXin Road - MianYang SiChuan PRC 621000 - CHINA - - 00-14-4A (hex) Taiwan Thick-Film Ind. Corp. - 00144A (base 16) Taiwan Thick-Film Ind. Corp. - NO.126,Wuu Gong 2nd RD, - Wuu Guu Industrial Zone - Taipei Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 00-14-4B (hex) Hifn, Inc. - 00144B (base 16) Hifn, Inc. - 750 University Ave - Suite 200 - Los Gatos CA 95032 - UNITED STATES - - 00-14-4C (hex) General Meters Corp. - 00144C (base 16) General Meters Corp. - 1935 Dominion Way - Colorado Springs Colorado 80918 - UNITED STATES - - 00-14-4D (hex) Intelligent Systems - 00144D (base 16) Intelligent Systems - 11101 Johns Hopkins Road - Laurel MD 20723 - UNITED STATES - - 00-14-4E (hex) SRISA - 00144E (base 16) SRISA - 36/1, Nakhimovskiy pr-t - Moscow 117218 - RUSSIAN FEDERATION - - 00-14-4F (hex) Oracle Corporation - 00144F (base 16) Oracle Corporation - 17 Network Circle - Bldg. 17, UMPK17-131 - Menlo Park CA 94025 - UNITED STATES - - 00-14-50 (hex) Heim Systems GmbH - 001450 (base 16) Heim Systems GmbH - Friedrich Ebert Strasse - TechnologiePark - Bergisch Gladbach NRW 51429 - GERMANY - - 00-14-51 (hex) Apple - 001451 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-14-52 (hex) CALCULEX,INC. - 001452 (base 16) CALCULEX,INC. - 132 W. LAS CRUCES AVE. - LAS CRUCES NEW MEXICO 88001 - UNITED STATES - - 00-14-53 (hex) ADVANTECH TECHNOLOGIES CO.,LTD - 001453 (base 16) ADVANTECH TECHNOLOGIES CO.,LTD - #1202 ACE TECHNO TOWER, 684-1 - Deungchon-3Dong, Kangseo-Ku - Seoul 157-721 - KOREA, REPUBLIC OF - - 00-14-54 (hex) Symwave - 001454 (base 16) Symwave - 10251 Vista Sorrento Parkway - Suite 100 - San Diego CA 92121 - UNITED STATES - - 00-14-55 (hex) Coder Electronics Corporation - 001455 (base 16) Coder Electronics Corporation - Takeda Bldg, 1-30-6 Shirasagi, - Nakano-ku Tokyo 165-0035 - JAPAN - - 00-14-56 (hex) Edge Products - 001456 (base 16) Edge Products - 1080 South Depot Drive - Ogden Utah 84404 - UNITED STATES - - 00-14-57 (hex) T-VIPS AS - 001457 (base 16) T-VIPS AS - Ostensjoveien 18 - Oslo NO-0661 - NORWAY - - 00-14-58 (hex) HS Automatic ApS - 001458 (base 16) HS Automatic ApS - Bjerringbrovej 70 - Rodovre 2610 - DENMARK - - 00-14-59 (hex) Moram Co., Ltd. - 001459 (base 16) Moram Co., Ltd. - 3F, Manwol Bldg., 1022-4 - Youngtong-dong, Youngtong-gu - Suwon-shi Gyounggi-do 443-813 - KOREA, REPUBLIC OF - - 00-14-5A (hex) Neratec Solutions AG - 00145A (base 16) Neratec Solutions AG - Rosswiesstrasse 29 - CH-8608 Bubikon ZH - SWITZERLAND - - 00-14-5B (hex) SeekerNet Inc. - 00145B (base 16) SeekerNet Inc. - 300 Satellite Blvd. - Suwanee Georgia 30024 - UNITED STATES - - 00-14-5C (hex) Intronics B.V. - 00145C (base 16) Intronics B.V. - Koolhovenstraat 1E - Barneveld Gelderland 3772 MT - NETHERLANDS - - 00-14-5D (hex) WJ Communications, Inc. - 00145D (base 16) WJ Communications, Inc. - 401 River Oaks Parkway - San Jose CA 95134 - UNITED STATES - - 00-14-5E (hex) IBM Corp - 00145E (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-14-5F (hex) ADITEC CO. LTD - 00145F (base 16) ADITEC CO. LTD - 4F Hyowon B/D, 99-5, - Karak-dong,Songpa-gu - Seoul 138-805 - KOREA, REPUBLIC OF - - 00-14-60 (hex) Kyocera Wireless Corp. - 001460 (base 16) Kyocera Wireless Corp. - 10300 Campus Point Drive - San Diego CA 92121 - UNITED STATES - - 00-14-61 (hex) CORONA CORPORATION - 001461 (base 16) CORONA CORPORATION - 7-7, HIGASHI-SHINBO - SANJO-SHI NIIGATA 955-8510 - JAPAN - - 00-14-62 (hex) Digiwell Technology, inc - 001462 (base 16) Digiwell Technology, inc - 4F, No.1, Prosperity 1st Road - Hsinchu Science Park 300 - TAIWAN, PROVINCE OF CHINA - - 00-14-63 (hex) IDCS N.V. - 001463 (base 16) IDCS N.V. - Hellebeemden 9 - Hasselt Limburg 3500 - BELGIUM - - 00-14-64 (hex) Cryptosoft - 001464 (base 16) Cryptosoft - Lermontova str, 3 - Penza region 440026 - RUSSIAN FEDERATION - - 00-14-65 (hex) Novo Nordisk A/S - 001465 (base 16) Novo Nordisk A/S - Novo Alle - Bagsvaerd 2880 - DENMARK - - 00-14-66 (hex) Kleinhenz Elektronik GmbH - 001466 (base 16) Kleinhenz Elektronik GmbH - Greinerberg 14 - Munich 81371 - GERMANY - - 00-14-67 (hex) ArrowSpan Inc. - 001467 (base 16) ArrowSpan Inc. - 4699 Old Ironsides Dr. Suite 100 - Santa Clara CA 95054 - UNITED STATES - - 00-14-68 (hex) CelPlan International, Inc. - 001468 (base 16) CelPlan International, Inc. - 1920 Association Drive - 4th floor - Reston VA 20191 - UNITED STATES - - 00-14-69 (hex) CISCO SYSTEMS, INC. - 001469 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-6A (hex) CISCO SYSTEMS, INC. - 00146A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-6B (hex) Anagran, Inc. - 00146B (base 16) Anagran, Inc. - 580 North Pastoria Av - Sunnyvale CA 94085 - UNITED STATES - - 00-14-6C (hex) Netgear Inc. - 00146C (base 16) Netgear Inc. - 4500 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-14-6D (hex) RF Technologies - 00146D (base 16) RF Technologies - 3125 N 126th Street - Brookfield WI 53005 - UNITED STATES - - 00-14-6E (hex) H. Stoll GmbH & Co. KG - 00146E (base 16) H. Stoll GmbH & Co. KG - Stollweg - Reutlingen Deutschland 72760 - GERMANY - - 00-14-6F (hex) Kohler Co - 00146F (base 16) Kohler Co - 444 Highland Drive - MS 072 - Kohler WI 53044 - UNITED STATES - - 00-14-70 (hex) Prokom Software SA - 001470 (base 16) Prokom Software SA - Al. Jerozolimskie 65/79 - Warszawa Mazowieckie 00-697 - POLAND - - 00-14-71 (hex) Eastern Asia Technology Limited - 001471 (base 16) Eastern Asia Technology Limited - 8F-1, No. 188, Baoqiao Rd., Xindian Dist. - New Taipei City 23145 - TAIWAN, PROVINCE OF CHINA - - 00-14-72 (hex) China Broadband Wireless IP Standard Group - 001472 (base 16) China Broadband Wireless IP Standard Group - P.O.BOX 88,West High-tech - Development Center, - Xi'an Shaan Xi 710075 - CHINA - - 00-14-73 (hex) Bookham Inc - 001473 (base 16) Bookham Inc - 10 Brewer Hunt Way - Kanata ON K2K 2B5 - CANADA - - 00-14-74 (hex) K40 Electronics - 001474 (base 16) K40 Electronics - 600 Tollgate Rd. Unit A - Elgin IL 60123 - UNITED STATES - - 00-14-75 (hex) Wiline Networks, Inc. - 001475 (base 16) Wiline Networks, Inc. - 741 Alexander Rd - Princeton NJ 08540 - UNITED STATES - - 00-14-76 (hex) MultiCom Industries Limited - 001476 (base 16) MultiCom Industries Limited - Room 1206-7, Manhattan Center, - 8 Kwai Cheong Rd. - Kwai Chung, N.T. - HONG KONG - - 00-14-77 (hex) Nertec Inc. - 001477 (base 16) Nertec Inc. - 950 Cowie st. - Granby Quebec J2J 1P2 - CANADA - - 00-14-78 (hex) ShenZhen TP-LINK Technologies Co., Ltd. - 001478 (base 16) ShenZhen TP-LINK Technologies Co., Ltd. - 3/F,Bldg.R1-B,Hi-tech Industrial Park, - Shennan Rd. - ShenZhen GuangDong 518057 - CHINA - - 00-14-79 (hex) NEC Magnus Communications,Ltd. - 001479 (base 16) NEC Magnus Communications,Ltd. - 4-28 - Mita 1-Chome - Minato-ku Tokyo 108-0073 - JAPAN - - 00-14-7A (hex) Eubus GmbH - 00147A (base 16) Eubus GmbH - Gollierstraße 70 Aufgang E 4.Stock - Munich Bavaria 80339 - GERMANY - - 00-14-7B (hex) Iteris, Inc. - 00147B (base 16) Iteris, Inc. - 1515 S. Manchester Ave. - Anaheim CA 92802 - UNITED STATES - - 00-14-7C (hex) 3Com Ltd - 00147C (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-14-7D (hex) Aeon Digital International - 00147D (base 16) Aeon Digital International - 31-6, The Bund Center - 222 Yan An E. Rd - Shanghai SH 200002 - CHINA - - 00-14-7E (hex) InnerWireless - 00147E (base 16) InnerWireless - 1155 Kas Drive, Suite 200 - Richardson TX 75081 - UNITED STATES - - 00-14-7F (hex) Thomson Telecom Belgium - 00147F (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - Edegem Antwerp B-2650 - BELGIUM - - 00-14-80 (hex) Hitachi-LG Data Storage Korea, Inc - 001480 (base 16) Hitachi-LG Data Storage Korea, Inc - 19-1,Cheongho-ri - Jinwuy-Myun - Pyungtaik Kyunggi-Do 451-713 - KOREA, REPUBLIC OF - - 00-14-81 (hex) Multilink Inc - 001481 (base 16) Multilink Inc - 580 Ternes Ave - Elyria OH 44035 - UNITED STATES - - 00-14-82 (hex) Aurora Networks - 001482 (base 16) Aurora Networks - 5400 Betsy Ross Drive - Santa Clara CA 95054 - UNITED STATES - - 00-14-83 (hex) eXS Inc. - 001483 (base 16) eXS Inc. - 1900 Alameda de las Pulgas - Suite 103 - San Mateo CA 94403 - UNITED STATES - - 00-14-84 (hex) Cermate Technologies Inc. - 001484 (base 16) Cermate Technologies Inc. - 7F-1, No 168 Lien-Chen Rd. - Chung-Ho Dist New Taipei County - TAIWAN, PROVINCE OF CHINA - - 00-14-85 (hex) Giga-Byte - 001485 (base 16) Giga-Byte - No.215,Nan-Ping Road, - Pin-Jen Taoyuan 326 - TAIWAN, PROVINCE OF CHINA - - 00-14-86 (hex) Echo Digital Audio Corporation - 001486 (base 16) Echo Digital Audio Corporation - 402 E Carrillo St - Santa Barbara CA 93101 - UNITED STATES - - 00-14-87 (hex) American Technology Integrators - 001487 (base 16) American Technology Integrators - 1358 Rosalia Ave - San Jose CA 95130 - UNITED STATES - - 00-14-88 (hex) Akorri - 001488 (base 16) Akorri - 11 Falcon Ridge Dr - Hopkinton MA 01748 - UNITED STATES - - 00-14-89 (hex) B15402100 - JANDEI, S.L. - 001489 (base 16) B15402100 - JANDEI, S.L. - POL. IND. POCOMACO, E-28 - LA Coruña 15190 - SPAIN - - 00-14-8A (hex) Elin Ebg Traction Gmbh - 00148A (base 16) Elin Ebg Traction Gmbh - Cumberlandstrasse 32 - Vienna 1140 - AUSTRIA - - 00-14-8B (hex) Globo Electronic GmbH & Co. KG - 00148B (base 16) Globo Electronic GmbH & Co. KG - Industriestrasse 4a - Niederlauer Bayern 97618 - GERMANY - - 00-14-8C (hex) Fortress Technologies - 00148C (base 16) Fortress Technologies - 2 Technology Park Drive - Westford MA 01886 - UNITED STATES - - 00-14-8D (hex) Cubic Defense Simulation Systems - 00148D (base 16) Cubic Defense Simulation Systems - 2001 W. Oakridge Road - Orlando FL 32809 - UNITED STATES - - 00-14-8E (hex) Tele Power Inc. - 00148E (base 16) Tele Power Inc. - 1-46-15#B1F - Asahigaoka - Nerima-ku Tokyo 176-0005 - JAPAN - - 00-14-8F (hex) Protronic (Far East) Ltd. - 00148F (base 16) Protronic (Far East) Ltd. - Rm. 2504, Nanyang Plaza, - 57 Hung To Road - Kwun Tong Kowloon 852 - HONG KONG - - 00-14-90 (hex) ASP Corporation - 001490 (base 16) ASP Corporation - 465 Industrial Park Road - Hartwell GA 30643 - UNITED STATES - - 00-14-91 (hex) Daniels Electronics Ltd. dbo Codan Rado Communications - 001491 (base 16) Daniels Electronics Ltd. dbo Codan Rado Communications - 43 Erie St - Victoria BC V8V 1P8 - CANADA - - 00-14-92 (hex) Liteon, Mobile Media Solution SBU - 001492 (base 16) Liteon, Mobile Media Solution SBU - 4F, 3, Lane 768, Sec. 4, - Pateh Road, - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-14-93 (hex) Systimax Solutions - 001493 (base 16) Systimax Solutions - 1300 E Lookout Drive - Richardson Texas 75082 - UNITED STATES - - 00-14-94 (hex) ESU AG - 001494 (base 16) ESU AG - Lukasstrasse 29 - St. Gallen 9008 - SWITZERLAND - - 00-14-95 (hex) 2Wire, Inc. - 001495 (base 16) 2Wire, Inc. - 1704 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-14-96 (hex) Phonic Corp. - 001496 (base 16) Phonic Corp. - 12thFl, 59 Tung Hsing Rd - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-14-97 (hex) ZHIYUAN Eletronics co.,ltd. - 001497 (base 16) ZHIYUAN Eletronics co.,ltd. - 2 Floor, NO.3 Building, Huangzhou Industrial Estate, Chebei Road, - Tianhe - Guangzhou Guangdong 510660 - CHINA - - 00-14-98 (hex) Viking Design Technology - 001498 (base 16) Viking Design Technology - 2F, No.2, Lane 42, - Hou-Gang Street, Shih-Lin District - Taipei 111 - TAIWAN, PROVINCE OF CHINA - - 00-14-99 (hex) Helicomm Inc - 001499 (base 16) Helicomm Inc - 1947 Camino Vida Roble - Suite 109 - Carlsbad CA 92008 - UNITED STATES - - 00-14-9A (hex) ARRIS Group, Inc. - 00149A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-14-9B (hex) Nokota Communications, LLC - 00149B (base 16) Nokota Communications, LLC - 200 Galleria Parkway - Suite 1820 - Atlanta Georgia 30339 - UNITED STATES - - 00-14-9C (hex) HF Company - 00149C (base 16) HF Company - Node Park Touraine - BP1 Tauxigny 37310 - FRANCE - - 00-14-9D (hex) Sound ID Inc. - 00149D (base 16) Sound ID Inc. - 3430 West Bayshore Road - Palo Alto California 94303 - UNITED STATES - - 00-14-9E (hex) UbONE Co., Ltd - 00149E (base 16) UbONE Co., Ltd - Shinyoung B.D. 602, SeoHyeon2-Dong - Bundang-Gu - Seongnam-si Gyeongg-do 463-824 - KOREA, REPUBLIC OF - - 00-14-9F (hex) System and Chips, Inc. - 00149F (base 16) System and Chips, Inc. - 4F,No. 1, Lane 50, NanKang Road, Section 3, - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-14-A0 (hex) Accsense, Inc. - 0014A0 (base 16) Accsense, Inc. - 460 Ward Drive - Suite E2 - Santa Barbara California 93111 - UNITED STATES - - 00-14-A1 (hex) Synchronous Communication Corp - 0014A1 (base 16) Synchronous Communication Corp - 9 floor, No168, Rueiguang Road, Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-14-A2 (hex) Core Micro Systems Inc. - 0014A2 (base 16) Core Micro Systems Inc. - Wacore Kaname-cho Bldg. 9F, 11-2, Nakamaru-cho - Itabashi-ku Tokyo 173-0026 - JAPAN - - 00-14-A3 (hex) Vitelec BV - 0014A3 (base 16) Vitelec BV - kapittelweg 18 - P.O.Box 6543 - Breda NB NL 4827 HG - NETHERLANDS - - 00-14-A4 (hex) Hon Hai Precision Ind. Co., Ltd. - 0014A4 (base 16) Hon Hai Precision Ind. Co., Ltd. - 5F-1, 5 HSIN-AN ROAD - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-14-A5 (hex) Gemtek Technology Co., Ltd. - 0014A5 (base 16) Gemtek Technology Co., Ltd. - No. 1 Jen Ai Road - Hsinchu Industrial Park - Hukou, Hsinchu 303 - TAIWAN, PROVINCE OF CHINA - - 00-14-A6 (hex) Teranetics, Inc. - 0014A6 (base 16) Teranetics, Inc. - 3965 Freedom Circle - Sixth Floor - Santa Clara CA 95054 - UNITED STATES - - 00-14-A7 (hex) Nokia Danmark A/S - 0014A7 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V 1790V - DENMARK - - 00-14-A8 (hex) CISCO SYSTEMS, INC. - 0014A8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-A9 (hex) CISCO SYSTEMS, INC. - 0014A9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-AA (hex) Ashly Audio, Inc. - 0014AA (base 16) Ashly Audio, Inc. - 847 Holt Road - Webster NY 14580 - UNITED STATES - - 00-14-AB (hex) Senhai Electronic Technology Co., Ltd. - 0014AB (base 16) Senhai Electronic Technology Co., Ltd. - Rm.10A. 28/F.SEGPlaza Huaqiangbei Road - Shengzhen Guangdong 518031 - CHINA - - 00-14-AC (hex) Bountiful WiFi - 0014AC (base 16) Bountiful WiFi - 707 West 700 South - Woods Cross Utah 84087 - UNITED STATES - - 00-14-AD (hex) Gassner Wiege- und Meßtechnik GmbH - 0014AD (base 16) Gassner Wiege- und Meßtechnik GmbH - Münchner Bundesstraße - Salzburg A-5020 - AUSTRIA - - 00-14-AE (hex) Wizlogics Co., Ltd. - 0014AE (base 16) Wizlogics Co., Ltd. - Rm#1321, Samchang Plaza, 173, - Dowha-Dong Mapo-Gu, - Seoul 121-745 - KOREA, REPUBLIC OF - - 00-14-AF (hex) Datasym POS Inc. - 0014AF (base 16) Datasym POS Inc. - 45 Dalkeith Drive - Unit 18 - Brantford Ontario N3P1M1 - CANADA - - 00-14-B0 (hex) Naeil Community - 0014B0 (base 16) Naeil Community - #506 AceTwin Tower 1, Guro-Dong - Seoul Guro-Gu 152779 - KOREA, REPUBLIC OF - - 00-14-B1 (hex) Axell Wireless Limited - 0014B1 (base 16) Axell Wireless Limited - Aerial HOuse - Asheridge Road - Chesham Buckinghamshire HP5 2QD - UNITED KINGDOM - - 00-14-B2 (hex) mCubelogics Corporation - 0014B2 (base 16) mCubelogics Corporation - 4F, Unibooks B/D, 514-1, Dogok-Dong, KangNam - Seoul 135-270 - KOREA, REPUBLIC OF - - 00-14-B3 (hex) CoreStar International Corp - 0014B3 (base 16) CoreStar International Corp - 1044 Sandy Hill Rd - Irwin PA 15642 - UNITED STATES - - 00-14-B4 (hex) General Dynamics United Kingdom Ltd - 0014B4 (base 16) General Dynamics United Kingdom Ltd - Castleham Road - St Leonards on Sea East Sussex TN38 9NJ - UNITED KINGDOM - - 00-14-B5 (hex) PHYSIOMETRIX,INC - 0014B5 (base 16) PHYSIOMETRIX,INC - 101 BILLERICA AVE #5 - N. BILLERICA MA 01862 - UNITED STATES - - 00-14-B6 (hex) Enswer Technology Inc. - 0014B6 (base 16) Enswer Technology Inc. - 1F No.70 Sec.2 Chung Shun St. - Taipei 116 - TAIWAN, PROVINCE OF CHINA - - 00-14-B7 (hex) AR Infotek Inc. - 0014B7 (base 16) AR Infotek Inc. - 9F, No.185, GangQian Road - NeiHu Technology Park, - Taipei 11494 - TAIWAN, PROVINCE OF CHINA - - 00-14-B8 (hex) Hill-Rom - 0014B8 (base 16) Hill-Rom - 1125 E. Pearl Street - Batesville IN 47006 - UNITED STATES - - 00-14-B9 (hex) MSTAR SEMICONDUCTOR - 0014B9 (base 16) MSTAR SEMICONDUCTOR - 11-13 rue René Jacques - Issy les Moulineaux 92130 - FRANCE - - 00-14-BA (hex) Carvers SA de CV - 0014BA (base 16) Carvers SA de CV - Alvarez del Castillo 1550 - Chapultepec Country - Guadalajara Jalisco 44620 - MEXICO - - 00-14-BB (hex) Open Interface North America - 0014BB (base 16) Open Interface North America - 506 2nd Avenue, Suite 420 - Seattle WA 98104 - UNITED STATES - - 00-14-BC (hex) SYNECTIC TELECOM EXPORTS PVT. LTD. - 0014BC (base 16) SYNECTIC TELECOM EXPORTS PVT. LTD. - 196, 1st Main, 3rd Stage, 4th Block - Basaveshwar Nagar - BANGALORE 560079 - INDIA - - 00-14-BD (hex) incNETWORKS, Inc - 0014BD (base 16) incNETWORKS, Inc - 198 Brighton Ave - Long Branch NJ 07740 - UNITED STATES - - 00-14-BE (hex) Wink communication technology CO.LTD - 0014BE (base 16) Wink communication technology CO.LTD - Huijiang Ind Blding Dashi Town - Panyu District - Guang zhou Guang dong 511430 - CHINA - - 00-14-BF (hex) Cisco-Linksys LLC - 0014BF (base 16) Cisco-Linksys LLC - 121 Theory Dr. - Irvine CA 92612 - UNITED STATES - - 00-14-C0 (hex) Symstream Technology Group Ltd - 0014C0 (base 16) Symstream Technology Group Ltd - Level 1, 3 Chester Street - Oakleigh Victoria 3166 - AUSTRALIA - - 00-14-C1 (hex) U.S. Robotics Corporation - 0014C1 (base 16) U.S. Robotics Corporation - 935 National Parkway - Schaumburg IL 60173-5157 - UNITED STATES - - 00-14-C2 (hex) Hewlett-Packard Company - 0014C2 (base 16) Hewlett-Packard Company - 20555 Tomball Parkway - MS070405 - Houston TX 77070 - UNITED STATES - - 00-14-C3 (hex) Seagate Technology - 0014C3 (base 16) Seagate Technology - M/S NW1F01 - 389 Disc Drive - Longmont CO 80503 - UNITED STATES - - 00-14-C4 (hex) Vitelcom Mobile Technology - 0014C4 (base 16) Vitelcom Mobile Technology - PTA, Avda, Juan López Peñalver, nº 7 - 29590, Campanillas - Campanillas. Malaga. - SPAIN - - 00-14-C5 (hex) Alive Technologies Pty Ltd - 0014C5 (base 16) Alive Technologies Pty Ltd - 11 Technology Drive - Arundel Queensland 4214 - AUSTRALIA - - 00-14-C6 (hex) Quixant Ltd - 0014C6 (base 16) Quixant Ltd - 61A Mount Pleasant - Biggin Hill - England Kent TN16 3TP - UNITED KINGDOM - - 00-14-C7 (hex) Nortel - 0014C7 (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-14-C8 (hex) Contemporary Research Corp - 0014C8 (base 16) Contemporary Research Corp - 4355 Excel Pkwy - STE 600 - Addison TX 75001 - UNITED STATES - - 00-14-C9 (hex) Brocade Communications Systems, Inc. - 0014C9 (base 16) Brocade Communications Systems, Inc. - 1745 Technology Dr. - San Jose CA 95110 - UNITED STATES - - 00-14-CA (hex) Key Radio Systems Limited - 0014CA (base 16) Key Radio Systems Limited - Venus House - Calleva Park - Aldermaston Berkshire RG7 8DA - UNITED KINGDOM - - 00-14-CB (hex) LifeSync Corporation - 0014CB (base 16) LifeSync Corporation - 1 E Broward Boulevard, Suite 1701 - Fort Lauderdale Florida 33301 - UNITED STATES - - 00-14-CC (hex) Zetec, Inc. - 0014CC (base 16) Zetec, Inc. - 8226 Bracken Place SE - Snoqualmie WA 98065 - UNITED STATES - - 00-14-CD (hex) DigitalZone Co., Ltd. - 0014CD (base 16) DigitalZone Co., Ltd. - No. 1001 E&C VentureDreamTower2 - 197-10 Guro-dong, Guro-gu - Seoul 152-848 - KOREA, REPUBLIC OF - - 00-14-CE (hex) NF CORPORATION - 0014CE (base 16) NF CORPORATION - 6-3-20, Tsunashima-higashi - Kohoku-ku - Yokohama Kanagawa 223-8508 - JAPAN - - 00-14-CF (hex) INVISIO Communications - 0014CF (base 16) INVISIO Communications - Stamholmen 157 - Hvidovre 2650 - DENMARK - - 00-14-D0 (hex) BTI Systems Inc. - 0014D0 (base 16) BTI Systems Inc. - 50 Northside Road - Ottawa Ontario K2H 5Z6 - CANADA - - 00-14-D1 (hex) TRENDnet - 0014D1 (base 16) TRENDnet - 20675 Manhattan Place - Torrance CA 90501 - UNITED STATES - - 00-14-D2 (hex) Kyuden Technosystems Corporation - 0014D2 (base 16) Kyuden Technosystems Corporation - 4-19-18 SHIMIZU,MINAMI-KU - FUKUOKA 815-0031 - JAPAN - - 00-14-D3 (hex) SEPSA - 0014D3 (base 16) SEPSA - calle Albatros, 7 y 9 - Pol. Ind. La Estación - PINTO Madrid 28320 - SPAIN - - 00-14-D4 (hex) K Technology Corporation - 0014D4 (base 16) K Technology Corporation - 325 Ganbara - Kami-machi - Kami-gun Miyagi-ken 981-4263 - JAPAN - - 00-14-D5 (hex) Datang Telecom Technology CO. , LCD,Optical Communication Br - 0014D5 (base 16) Datang Telecom Technology CO. , LCD,Optical Communication Br - 3rd Floor,Building 8,Hi-Tech Incubation Park, - Nanyanxian,Tianfu Ave,chengdu Hi-Tech Zone, - ChengDu SiChuan 610041 - CHINA - - 00-14-D6 (hex) Jeongmin Electronics Co.,Ltd. - 0014D6 (base 16) Jeongmin Electronics Co.,Ltd. - #710, Byuksan Digital Valley 2, - Kasan-Dong, Keumcheon-Gu, - Seoul 153 783 - KOREA, REPUBLIC OF - - 00-14-D7 (hex) Datastore Technology Corp - 0014D7 (base 16) Datastore Technology Corp - 9F, NO.10, SEC.1, Chung Hsing RD., Wu-Ku - Taipei Hsien, 248 - TAIWAN, PROVINCE OF CHINA - - 00-14-D8 (hex) bio-logic SA - 0014D8 (base 16) bio-logic SA - 1, rue de l'Europe - CLAIX 38640 - FRANCE - - 00-14-D9 (hex) IP Fabrics, Inc. - 0014D9 (base 16) IP Fabrics, Inc. - 3720 SW 141st Avenue - Suite 201 - Beaverton Oregon 97006 - UNITED STATES - - 00-14-DA (hex) Huntleigh Healthcare - 0014DA (base 16) Huntleigh Healthcare - Huntleigh Healthcare - Diagnostic Products Division - 35 Portmanmoor Road - Cardiff CF24 5HN - UNITED KINGDOM - - 00-14-DB (hex) Elma Trenew Electronic GmbH - 0014DB (base 16) Elma Trenew Electronic GmbH - Stuttgarter Straße 11 - Pforzheim BW 75179 - GERMANY - - 00-14-DC (hex) Communication System Design & Manufacturing (CSDM) - 0014DC (base 16) Communication System Design & Manufacturing (CSDM) - Postbus 181 - Bussum NH 1400 AD - NETHERLANDS - - 00-14-DD (hex) Covergence Inc. - 0014DD (base 16) Covergence Inc. - One Clock Tower Place, Suite 200 - Maynard MA 01754 - UNITED STATES - - 00-14-DE (hex) Sage Instruments Inc. - 0014DE (base 16) Sage Instruments Inc. - 240 Airport Blvd. - Freedom CA 95019 - UNITED STATES - - 00-14-DF (hex) HI-P Tech Corporation - 0014DF (base 16) HI-P Tech Corporation - 1-27-23 Higashitokorozawa - Tokorozawa Saitama 359-0021 - JAPAN - - 00-14-E0 (hex) LET'S Corporation - 0014E0 (base 16) LET'S Corporation - Bancho Bldg. 4F, 2-18-20 Marunouchi, Naka - Nagoya Aichi 460-0002 - JAPAN - - 00-14-E1 (hex) Data Display AG - 0014E1 (base 16) Data Display AG - Industriestraße 1 - Germering Bayern 82110 - GERMANY - - 00-14-E2 (hex) datacom systems inc. - 0014E2 (base 16) datacom systems inc. - 9 adler drive - east syracuse n.y. 13057 - UNITED STATES - - 00-14-E3 (hex) mm-lab GmbH - 0014E3 (base 16) mm-lab GmbH - Stammheimer Strasse 10 - D-70806 - Kornwestheim - GERMANY - - 00-14-E4 (hex) infinias, LLC - 0014E4 (base 16) infinias, LLC - 857 West Carmel Drive - Carmel IN 46032 - UNITED STATES - - 00-14-E5 (hex) Alticast - 0014E5 (base 16) Alticast - 16th floor, Nara Bldg, 1328-3 - Seocho-dong, Seocho-gu, - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-14-E6 (hex) AIM Infrarotmodule GmbH - 0014E6 (base 16) AIM Infrarotmodule GmbH - Soeflingerstraße 100 - Ulm BW 89077 - GERMANY - - 00-14-E7 (hex) Stolinx,. Inc - 0014E7 (base 16) Stolinx,. Inc - 3F Ohchang Bldg., 61 Yangjae-dong - Seocho-gu - Seoul 137-889 - KOREA, REPUBLIC OF - - 00-14-E8 (hex) ARRIS Group, Inc. - 0014E8 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-14-E9 (hex) Nortech International - 0014E9 (base 16) Nortech International - 32A Wiganthorpe Road - Willowton Hub - Pietermartizburg KwaZulu Natal 3201 - SOUTH AFRICA - - 00-14-EA (hex) S Digm Inc. (Safe Paradigm Inc.) - 0014EA (base 16) S Digm Inc. (Safe Paradigm Inc.) - 5F, Shin-an Bldg. 89-8, - Moonjung-Dong - Songpa-Gu Seoul 138-201 - KOREA, REPUBLIC OF - - 00-14-EB (hex) AwarePoint Corporation - 0014EB (base 16) AwarePoint Corporation - 8899 University Center Lane - San Diego CA 92122 - UNITED STATES - - 00-14-EC (hex) Acro Telecom - 0014EC (base 16) Acro Telecom - 714 Woolim e-Biz Center 170-5 Guro-dong - Guro-Gu Seoul 152-769 - KOREA, REPUBLIC OF - - 00-14-ED (hex) Airak, Inc. - 0014ED (base 16) Airak, Inc. - 21641 Beaumeade Circle - Suite 300 - Ashburn Virginia 20147 - UNITED STATES - - 00-14-EE (hex) Western Digital Technologies, Inc. - 0014EE (base 16) Western Digital Technologies, Inc. - 20511 Lake Forest Dr. - Lake Forest Ca 92630 - UNITED STATES - - 00-14-EF (hex) TZero Technologies, Inc. - 0014EF (base 16) TZero Technologies, Inc. - 455 W. Maude Avenue - Sunnyvale CA 94085 - UNITED STATES - - 00-14-F0 (hex) Business Security OL AB - 0014F0 (base 16) Business Security OL AB - Box 110 65 - Stora Raby Byavag 88 - Lund 220 11 - SWEDEN - - 00-14-F1 (hex) CISCO SYSTEMS, INC. - 0014F1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-F2 (hex) CISCO SYSTEMS, INC. - 0014F2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-14-F3 (hex) ViXS Systems Inc - 0014F3 (base 16) ViXS Systems Inc - 2235 Sheppard Ave East - Suite1705 - TORONTO ONTARIO M2J 5B5 - CANADA - - 00-14-F4 (hex) DekTec Digital Video B.V. - 0014F4 (base 16) DekTec Digital Video B.V. - Van Riebeeckweg 43A - Hilversum NH 1212AE - NETHERLANDS - - 00-14-F5 (hex) OSI Security Devices - 0014F5 (base 16) OSI Security Devices - 1580 Jayken Way - Chula Vista California 91911 - UNITED STATES - - 00-14-F6 (hex) Juniper Networks, Inc. - 0014F6 (base 16) Juniper Networks, Inc. - 1194 N. Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-14-F7 (hex) CREVIS Co., LTD - 0014F7 (base 16) CREVIS Co., LTD - 157-1, Hagal-Dong - Giheung-Gu - Youngin Kyungki 446930 - KOREA, REPUBLIC OF - - 00-14-F8 (hex) Scientific Atlanta - 0014F8 (base 16) Scientific Atlanta - 5030 Sugarloaf Parkway - MS 5.2.428 - Lawrenceville Ga 30042 - UNITED STATES - - 00-14-F9 (hex) Vantage Controls - 0014F9 (base 16) Vantage Controls - 1061 South 800 East - Orem UT 84097 - UNITED STATES - - 00-14-FA (hex) AsGa S.A. - 0014FA (base 16) AsGa S.A. - Rod Roberto Moreira Km 04 - Paulinia São Paulo 13140-000 - BRAZIL - - 00-14-FB (hex) Technical Solutions Inc. - 0014FB (base 16) Technical Solutions Inc. - 101-7311 Vantage Way - Delta BC V4G 1C9 - CANADA - - 00-14-FC (hex) Extandon, Inc. - 0014FC (base 16) Extandon, Inc. - 39350 Civic Center Drive Ste. 160 - Fremont CA 94538 - UNITED STATES - - 00-14-FD (hex) Thecus Technology Corp. - 0014FD (base 16) Thecus Technology Corp. - 15F.,No. 79,Sec. 1,Sintai 5th RD., - Sijhih City Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-14-FE (hex) Artech Electronics - 0014FE (base 16) Artech Electronics - #301, Yangjae Bldg., 276-2 - Yangjae-Dong, Seocho-Ku - Seoul 137-895 - KOREA, REPUBLIC OF - - 00-14-FF (hex) Precise Automation, Inc. - 0014FF (base 16) Precise Automation, Inc. - 1402 Alexandra Blvd - Crystal Lake IL 60014 - UNITED STATES - - 00-15-00 (hex) Intel Corporate - 001500 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-15-01 (hex) LexBox - 001501 (base 16) LexBox - 3, avenue Didier Daurat - TOULOUSE 31400 - FRANCE - - 00-15-02 (hex) BETA tech - 001502 (base 16) BETA tech - 15 rue d'apollo - L'UNION 31240 - FRANCE - - 00-15-03 (hex) PROFIcomms s.r.o. - 001503 (base 16) PROFIcomms s.r.o. - Turgenevova 5 - Brno EU/Europe 618 00 - CZECH REPUBLIC - - 00-15-04 (hex) GAME PLUS CO., LTD. - 001504 (base 16) GAME PLUS CO., LTD. - 164-57, Yeonghwa-dong, Jangan-gu - Suwon Gyeonggi-do 440-818 - KOREA, REPUBLIC OF - - 00-15-05 (hex) Actiontec Electronics, Inc - 001505 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94086 - UNITED STATES - - 00-15-06 (hex) Neo Photonics - 001506 (base 16) Neo Photonics - 910 E. California St. - Sunnyvale CA 94085 - UNITED STATES - - 00-15-07 (hex) Renaissance Learning Inc - 001507 (base 16) Renaissance Learning Inc - 2911 Peach Street - PO Box 8036 - Wisconsin Rapids Wisconsin 54494 - UNITED STATES - - 00-15-08 (hex) Global Target Enterprise Inc - 001508 (base 16) Global Target Enterprise Inc - 5F, No. 186, Sec. 2, Chung-Hsing Rd., - Hsin Tien, Taipei county 231 - TAIWAN, PROVINCE OF CHINA - - 00-15-09 (hex) Plus Technology Co., Ltd - 001509 (base 16) Plus Technology Co., Ltd - Office #205, Gayang Techno-town, - Gayang 3- dong, Gangseo-ku - Seoul 157-810 - KOREA, REPUBLIC OF - - 00-15-0A (hex) Sonoa Systems, Inc - 00150A (base 16) Sonoa Systems, Inc - 3900 Freedom Circle - Santa Clara CA 95054 - UNITED STATES - - 00-15-0B (hex) SAGE INFOTECH LTD. - 00150B (base 16) SAGE INFOTECH LTD. - 3F, No30, INDUSTRY E. 9TH RD.,SCIENCE-BASED - INDUSTRIAL PARK - HSIN-CHU TAIWAN 300 - TAIWAN, PROVINCE OF CHINA - - 00-15-0C (hex) AVM GmbH - 00150C (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 00-15-0D (hex) Hoana Medical, Inc. - 00150D (base 16) Hoana Medical, Inc. - 828 Fort Street Mall - Suite 620 - Honolulu HI 96813 - UNITED STATES - - 00-15-0E (hex) OPENBRAIN TECHNOLOGIES CO., LTD. - 00150E (base 16) OPENBRAIN TECHNOLOGIES CO., LTD. - #804,ANYANG K-CENTER,1591-9 , BURIM-DONG,DONGAN-GU, - ANYANG KYUNGGI-DO 431-815 - KOREA, REPUBLIC OF - - 00-15-0F (hex) mingjong - 00150F (base 16) mingjong - 8F,NO.1,LANE 16,SZE CHUAN ROAD,SEC.2,PANCHIAO CITY. - TAIPEI 220 - TAIWAN, PROVINCE OF CHINA - - 00-15-10 (hex) Techsphere Co., Ltd - 001510 (base 16) Techsphere Co., Ltd - 4F, Wonil Bldg., 980-54, Bangbae-dong, SeoCho-gu - Seoul 137-060 - KOREA, REPUBLIC OF - - 00-15-11 (hex) Data Center Systems - 001511 (base 16) Data Center Systems - 14802 Venture Drive - Dallas TX 75234 - UNITED STATES - - 00-15-12 (hex) Zurich University of Applied Sciences - 001512 (base 16) Zurich University of Applied Sciences - Technikumstrasse 9 - Winterthur ZH CH-8401 - SWITZERLAND - - 00-15-13 (hex) EFS sas - 001513 (base 16) EFS sas - BP 34 - MILLERY F-69390 - FRANCE - - 00-15-14 (hex) Hu Zhou NAVA Networks&Electronics Ltd. - 001514 (base 16) Hu Zhou NAVA Networks&Electronics Ltd. - 3/F,No.328-4,Guang Yuan Rd. - Hu Zhou Zhe Jiang 313000 - CHINA - - 00-15-15 (hex) Leipold+Co.GmbH - 001515 (base 16) Leipold+Co.GmbH - Kreuzwiese 12 - Rockenhausen RLP D-67806 - GERMANY - - 00-15-16 (hex) URIEL SYSTEMS INC. - 001516 (base 16) URIEL SYSTEMS INC. - #204 Byucksan Digitalvalley 1st, 212-16, Guro-dong, Guro-gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-15-17 (hex) Intel Corporate - 001517 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-15-18 (hex) Shenzhen 10MOONS Technology Development CO.,Ltd - 001518 (base 16) Shenzhen 10MOONS Technology Development CO.,Ltd - Add:3F,Huaxing building, QiaoXiang road, - shenzhen guangdong 518053 - CHINA - - 00-15-19 (hex) StoreAge Networking Technologies - 001519 (base 16) StoreAge Networking Technologies - 63 Bar-Yehuda st. - Nesher 36651 - ISRAEL - - 00-15-1A (hex) Hunter Engineering Company - 00151A (base 16) Hunter Engineering Company - 11250 Hunter Drive - Bridgeton Missouri 63044 - UNITED STATES - - 00-15-1B (hex) Isilon Systems Inc. - 00151B (base 16) Isilon Systems Inc. - 3101 Western Avenue - Seattle WA 98121 - UNITED STATES - - 00-15-1C (hex) LENECO - 00151C (base 16) LENECO - 6th.,Dong Moon Good Morning Tower - 1323 Beakseok-Dong Ilsan-Gu - Kyeong Ki-Do GoYang-Si 411-817 - KOREA, REPUBLIC OF - - 00-15-1D (hex) M2I CORPORATION - 00151D (base 16) M2I CORPORATION - Kyonggi Venture Anyang technical center, 13th Floor, 572-5, Anyang 8-Dong, Manan-Gu - Anyang-Shi Kyonggi-Do 430-731 - KOREA, REPUBLIC OF - - 00-15-1E (hex) Ethernet Powerlink Standardization Group (EPSG) - 00151E (base 16) Ethernet Powerlink Standardization Group (EPSG) - c/o Zurich University of Applied Sciences - Technikumstrasse 9 - CH-8401 Winterthur - SWITZERLAND - - 00-15-1F (hex) Multivision Intelligent Surveillance (Hong Kong) Ltd - 00151F (base 16) Multivision Intelligent Surveillance (Hong Kong) Ltd - 26/F, Aitken Vanson Centre, - 61 Hoi Yuen Road, Kwun Tong, Kowloon, - HONG KONG - - 00-15-20 (hex) Radiocrafts AS - 001520 (base 16) Radiocrafts AS - Sandakerveien 64 - Oslo 0484 - NORWAY - - 00-15-21 (hex) Horoquartz - 001521 (base 16) Horoquartz - BP 251 - FONTENAY LE COMTE VENDEE 85205 - FRANCE - - 00-15-22 (hex) Dea Security - 001522 (base 16) Dea Security - Galleria Leonardo da Vinci, 20 - Massa MS 54100 - ITALY - - 00-15-23 (hex) Meteor Communications Corporation - 001523 (base 16) Meteor Communications Corporation - 22614 66th Avenue South - Kent WA 98032 - UNITED STATES - - 00-15-24 (hex) Numatics, Inc. - 001524 (base 16) Numatics, Inc. - 46280 Dylan Dr. - Novi Michigan 48377 - UNITED STATES - - 00-15-25 (hex) Chamberlain Access Solutions - 001525 (base 16) Chamberlain Access Solutions - 9160 E. Bahia Dr. - Scottsdale AZ 85260 - UNITED STATES - - 00-15-26 (hex) Remote Technologies Inc - 001526 (base 16) Remote Technologies Inc - 7651 Anagram Drive - Eden Prairie MN 55344 - UNITED STATES - - 00-15-27 (hex) Balboa Instruments - 001527 (base 16) Balboa Instruments - 1382 Bell Ave - Tustin CA 92780 - UNITED STATES - - 00-15-28 (hex) Beacon Medical Products LLC d.b.a. BeaconMedaes - 001528 (base 16) Beacon Medical Products LLC d.b.a. BeaconMedaes - 14408 W 105TH ST - LENEXA KS 66215 - UNITED STATES - - 00-15-29 (hex) N3 Corporation - 001529 (base 16) N3 Corporation - #402 GwangMyeong Techno Town - 626-3 Clulsan 1-Dong, GwangMyeong-City - GyeongGi-Do 423-031 - KOREA, REPUBLIC OF - - 00-15-2A (hex) Nokia GmbH - 00152A (base 16) Nokia GmbH - Rensingstraße 15 - Bochum NRW 44807 - GERMANY - - 00-15-2B (hex) CISCO SYSTEMS, INC. - 00152B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-2C (hex) CISCO SYSTEMS, INC. - 00152C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-2D (hex) TenX Networks, LLC - 00152D (base 16) TenX Networks, LLC - 4855 Wiley Post Way - Salt Lake City UT 84116 - UNITED STATES - - 00-15-2E (hex) PacketHop, Inc. - 00152E (base 16) PacketHop, Inc. - 1301 Shoreway Road - Suite 200 - Belmont California 94002 - UNITED STATES - - 00-15-2F (hex) ARRIS Group, Inc. - 00152F (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-15-30 (hex) EMC Corporation - 001530 (base 16) EMC Corporation - 176 South Street - Hopkinton MA 01748 - UNITED STATES - - 00-15-31 (hex) KOCOM - 001531 (base 16) KOCOM - 5F, KOCOM Bldg., 260-7 - Yumchang-Dong, Kangseo-Gu - SEOUL 157-040 - KOREA, REPUBLIC OF - - 00-15-32 (hex) Consumer Technologies Group, LLC - 001532 (base 16) Consumer Technologies Group, LLC - 801 Brookhollow - Efland NC 27243 - UNITED STATES - - 00-15-33 (hex) NADAM.CO.,LTD - 001533 (base 16) NADAM.CO.,LTD - #91-3 Wangrim-Li - Bongdam-Eup - Hwaseong Gyeonggi 445-895 - KOREA, REPUBLIC OF - - 00-15-34 (hex) A Beltrónica-Companhia de Comunicações, Lda - 001534 (base 16) A Beltrónica-Companhia de Comunicações, Lda - Rua Dr. José Baptista de Sousa, 27 - Lisbon 1549-002 Lis - PORTUGAL - - 00-15-35 (hex) OTE Spa - 001535 (base 16) OTE Spa - via Barsanti 8 - Florence FI 50127 - ITALY - - 00-15-36 (hex) Powertech co.,Ltd - 001536 (base 16) Powertech co.,Ltd - #705, dongyoung Venturestel, 199-32 - Anyang7-dong, Manan-gu - Anyang City Kyoungki-do 430-010 - KOREA, REPUBLIC OF - - 00-15-37 (hex) Ventus Networks - 001537 (base 16) Ventus Networks - 800 Connecticut Ave - 1st floor west - Norwalk CT 06854 - UNITED STATES - - 00-15-38 (hex) RFID, Inc. - 001538 (base 16) RFID, Inc. - 14100 East Jewell Ave. - Suite 12 - Aurora CO 80012 - UNITED STATES - - 00-15-39 (hex) Technodrive SRL - 001539 (base 16) Technodrive SRL - Via Leonardo da Vinci 162 - Trezzano sul Naviglio Milano 20090 - ITALY - - 00-15-3A (hex) Shenzhen Syscan Technology Co.,Ltd. - 00153A (base 16) Shenzhen Syscan Technology Co.,Ltd. - 13F, Olympic Plaza, - Shang bao Road, Futian District, - Shenzhen Guangdong 518034 - CHINA - - 00-15-3B (hex) EMH metering GmbH & Co. KG - 00153B (base 16) EMH metering GmbH & Co. KG - Neu- Galliner Weg 1 - 19243 Wittenburg - Mecklenburg-Vorpommern - GERMANY - - 00-15-3C (hex) Kprotech Co., Ltd. - 00153C (base 16) Kprotech Co., Ltd. - 2nd Floor, # 202, Myoung-ji e-Space II - 218, An-yang 7 Dong, Man-an Gu, - An-yang City Gyeong-gi Do 430-817 - KOREA, REPUBLIC OF - - 00-15-3D (hex) ELIM PRODUCT CO. - 00153D (base 16) ELIM PRODUCT CO. - 602-2 GAYANG TECHNO TOWN, GAYANG, 3-DONG - KANGSEO-GU SEOUL KOREA - SEOUL 157-793 - KOREA, REPUBLIC OF - - 00-15-3E (hex) Q-Matic Sweden AB - 00153E (base 16) Q-Matic Sweden AB - Neongatan 8 - Molndal 431 53 - SWEDEN - - 00-15-3F (hex) Alcatel Alenia Space Italia - 00153F (base 16) Alcatel Alenia Space Italia - Strada Padana Superiore 290 - Vimodrone MI 20090 - ITALY - - 00-15-40 (hex) Nortel - 001540 (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-15-41 (hex) StrataLight Communications, Inc. - 001541 (base 16) StrataLight Communications, Inc. - 2105 S. Bascom Avenue - Suite 300 - Campbell CA 95008 - UNITED STATES - - 00-15-42 (hex) MICROHARD S.R.L. - 001542 (base 16) MICROHARD S.R.L. - Via Primo Maggio 36 - San Vittore Olona Milano 20028 - ITALY - - 00-15-43 (hex) Aberdeen Test Center - 001543 (base 16) Aberdeen Test Center - 400 Colleran Road - Bldg. 350 - Aberdeen Proving Grounds MD 21005-5059 - UNITED STATES - - 00-15-44 (hex) coM.s.a.t. AG - 001544 (base 16) coM.s.a.t. AG - Besselstraße 3 - Mannheim D-68219 - GERMANY - - 00-15-45 (hex) SEECODE Co., Ltd. - 001545 (base 16) SEECODE Co., Ltd. - 4th Floor, Amin Bldg., 110-1, Yangjaedong, Seochogu - Seoul 137-891 - KOREA, REPUBLIC OF - - 00-15-46 (hex) ITG Worldwide Sdn Bhd - 001546 (base 16) ITG Worldwide Sdn Bhd - 2, Jalan AstakaU8/83 - Seksyen U8, Bukit Jelutong - Shah Alam Selangor Darul Ehsan 40150 - MALAYSIA - - 00-15-47 (hex) AiZen Solutions Inc. - 001547 (base 16) AiZen Solutions Inc. - 10F-1, No.29, Puding Rd. - Hsinchu Hsinchu County 300 - TAIWAN, PROVINCE OF CHINA - - 00-15-48 (hex) CUBE TECHNOLOGIES - 001548 (base 16) CUBE TECHNOLOGIES - 10, rue des Rosiéristes - CHAMPAGNE AU MONT D'OR FRANCE 69410 - FRANCE - - 00-15-49 (hex) Dixtal Biomedica Ind. Com. Ltda - 001549 (base 16) Dixtal Biomedica Ind. Com. Ltda - R. Eng. Francisco Pitta Brito, 703 - São Paulo SP 04753-080 - BRAZIL - - 00-15-4A (hex) WANSHIH ELECTRONIC CO., LTD - 00154A (base 16) WANSHIH ELECTRONIC CO., LTD - 3F 72, WU KONG 6th RD., - WU KU INDUSTRIAL DISTRICT, - TAIPEI HSIEN TAIWAN 248 - TAIWAN, PROVINCE OF CHINA - - 00-15-4B (hex) Wonde Proud Technology Co., Ltd - 00154B (base 16) Wonde Proud Technology Co., Ltd - 21F., No.100, Sec.1, Shintai 5th Rd - Sijhih city Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-15-4C (hex) Saunders Electronics - 00154C (base 16) Saunders Electronics - 192 Gannett Drive - South Portland ME 04106 - UNITED STATES - - 00-15-4D (hex) Netronome Systems, Inc. - 00154D (base 16) Netronome Systems, Inc. - 3159 Unionville Road - Suite 100 - Cranberry Twp. PA 16066 - UNITED STATES - - 00-15-4E (hex) IEC - 00154E (base 16) IEC - 3, rue de Varembé - P.O. Box 131 - CH - 1211 GENEVA 20 - GERMANY - - 00-15-4F (hex) one RF Technology - 00154F (base 16) one RF Technology - 1360 Route des Dolines - Bat B4 Les Cardoulines - Valbonne Sophia-Antipolis PACA 06560 - FRANCE - - 00-15-50 (hex) Nits Technology Inc - 001550 (base 16) Nits Technology Inc - 2FL. No. 8 Alley 16, Lane 235, Bauchiau Rd., - Shindian City Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-15-51 (hex) RadioPulse Inc. - 001551 (base 16) RadioPulse Inc. - 2nd fl. Hans B/D, 111-55 - Seongnae-dong, Gangdong-gu - Seoul 134-883 - KOREA, REPUBLIC OF - - 00-15-52 (hex) Wi-Gear Inc. - 001552 (base 16) Wi-Gear Inc. - 340 Church Street - Suite 10 - San Francisco CA 94114 - UNITED STATES - - 00-15-53 (hex) Cytyc Corporation - 001553 (base 16) Cytyc Corporation - 250 Campus Dive - Marlborough MA 01752 - UNITED STATES - - 00-15-54 (hex) Atalum Wireless S.A. - 001554 (base 16) Atalum Wireless S.A. - C/ Orellana 5, 1º I - Madrid 28004 - SPAIN - - 00-15-55 (hex) DFM GmbH - 001555 (base 16) DFM GmbH - Lahrer Strasse 6 - Lahr Baden-Württemberg 77933 - GERMANY - - 00-15-56 (hex) SAGEM COMMUNICATION - 001556 (base 16) SAGEM COMMUNICATION - Le Ponnant de Paris - 27 Rue Leblanc - CEDEX Paris 75512 - FRANCE - - 00-15-57 (hex) Olivetti - 001557 (base 16) Olivetti - Via Jervis 77 - Ivrea Torino 10015 - ITALY - - 00-15-58 (hex) FOXCONN - 001558 (base 16) FOXCONN - No.2,2nd DongHuan Road,10th YouSong - Industrial District,LongHua Street,Bao'an, - ShenZhen GuangDong 518109 - CHINA - - 00-15-59 (hex) Securaplane Technologies, Inc. - 001559 (base 16) Securaplane Technologies, Inc. - 10800 N. Mavinee Dr. - Tucson AZ 85737 - UNITED STATES - - 00-15-5A (hex) DAINIPPON PHARMACEUTICAL CO., LTD. - 00155A (base 16) DAINIPPON PHARMACEUTICAL CO., LTD. - 2-6-8, DOSHOMACHI, CHUO-KU - OSAKA CITY OSAKA PREF. 541-8524 - JAPAN - - 00-15-5B (hex) Sampo Corporation - 00155B (base 16) Sampo Corporation - 216 Chung Shan Road, - Sec. 1, Panchiao City - Taipei Hsien 220 - TAIWAN, PROVINCE OF CHINA - - 00-15-5C (hex) Dresser Wayne - 00155C (base 16) Dresser Wayne - 3814 Jarrett Way - Austin Texas 78728 - UNITED STATES - - 00-15-5D (hex) Microsoft Corporation - 00155D (base 16) Microsoft Corporation - One Microsoft Way - Redmond WA 98052-8300 - UNITED STATES - - 00-15-5E (hex) Morgan Stanley - 00155E (base 16) Morgan Stanley - 750 7th Avenue - New York NY 10019 - UNITED STATES - - 00-15-5F (hex) GreenPeak Technologies - 00155F (base 16) GreenPeak Technologies - Spinnerijstraat 14 - Zele 9240 - BELGIUM - - 00-15-60 (hex) Hewlett-Packard Company - 001560 (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS070405 - Houston TX 77070 - UNITED STATES - - 00-15-61 (hex) JJPlus Corporation - 001561 (base 16) JJPlus Corporation - 678 Massachusetts Ave - Suite 503 - Cambridge MA 02139 - UNITED STATES - - 00-15-62 (hex) CISCO SYSTEMS, INC. - 001562 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-63 (hex) CISCO SYSTEMS, INC. - 001563 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-64 (hex) BEHRINGER Spezielle Studiotechnik GmbH - 001564 (base 16) BEHRINGER Spezielle Studiotechnik GmbH - Hanns-Martin-Schleyer-Str. 36-38 - Willich - GERMANY - - 00-15-65 (hex) XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD - 001565 (base 16) XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD - 7F Hualian Electronic BLDG.580 Jiahe Road,Xiamen China - Xiamen Fujian 361006 - CHINA - - 00-15-66 (hex) A-First Technology Co., Ltd. - 001566 (base 16) A-First Technology Co., Ltd. - 5F, No. 111-2, Shin-Teh Rd., - San-Chung City Taipei Shien 241 - TAIWAN, PROVINCE OF CHINA - - 00-15-67 (hex) RADWIN Inc. - 001567 (base 16) RADWIN Inc. - 900 Corporate Drive - Mahwah NJ 07430 - UNITED STATES - - 00-15-68 (hex) Dilithium Networks - 001568 (base 16) Dilithium Networks - 5401 Old Redwood Hwy - Petaluma CA 94954 - UNITED STATES - - 00-15-69 (hex) PECO II, Inc. - 001569 (base 16) PECO II, Inc. - 7060 Huntley Road - Columbus OH 43229 - UNITED STATES - - 00-15-6A (hex) DG2L Technologies Pvt. Ltd. - 00156A (base 16) DG2L Technologies Pvt. Ltd. - AML Center 1, Gnd. Floor, 8 Mahal Indl. Est. - Off. Mahakali Caves Road, Andheri E - Mumbai Maharashtra 400093 - INDIA - - 00-15-6B (hex) Perfisans Networks Corp. - 00156B (base 16) Perfisans Networks Corp. - 4118 14th Avenue - Unit 4 - Markham Ontario L3R 0J3 - CANADA - - 00-15-6C (hex) SANE SYSTEM CO., LTD - 00156C (base 16) SANE SYSTEM CO., LTD - 20-2 Heungan-daero 439 beon-gil Dongan-gu - Anyang-si Kyunggi-do 431-804 - KOREA, REPUBLIC OF - - 00-15-6D (hex) Ubiquiti Networks Inc. - 00156D (base 16) Ubiquiti Networks Inc. - 495 Montague Expwy. - Milpitas CA 95035 - UNITED STATES - - 00-15-6E (hex) A. W. Communication Systems Ltd - 00156E (base 16) A. W. Communication Systems Ltd - Crook Barn - The Crook, Roweltown - Carlisle Cumbria CA6 6LH - UNITED KINGDOM - - 00-15-6F (hex) Xiranet Communications GmbH - 00156F (base 16) Xiranet Communications GmbH - Bertolt-Brecht-Allee 24 - Dresden Saxony 01309 - GERMANY - - 00-15-70 (hex) Zebra Technologies Inc - 001570 (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - 00-15-71 (hex) Nolan Systems - 001571 (base 16) Nolan Systems - 1595 Cleo Springs Dr. - San Jose Ca. 95131 - UNITED STATES - - 00-15-72 (hex) Red-Lemon - 001572 (base 16) Red-Lemon - Unit 4, 9/F, Paramount Building - No. 12, Ka Yip Street - Chai Wan - HONG KONG - - 00-15-73 (hex) NewSoft Technology Corporation - 001573 (base 16) NewSoft Technology Corporation - 3F, 19-3, SanChong RD, NanKang, - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-15-74 (hex) Horizon Semiconductors Ltd. - 001574 (base 16) Horizon Semiconductors Ltd. - 9 Hamenofim St. - POB 2192 - Herzliya 46120 - ISRAEL - - 00-15-75 (hex) Nevis Networks Inc. - 001575 (base 16) Nevis Networks Inc. - 3945 Freedom Circle - Suite 720 - Santa Clara CA 95054 - UNITED STATES - - 00-15-76 (hex) LABiTec - Labor Biomedical Technologies GmbH - 001576 (base 16) LABiTec - Labor Biomedical Technologies GmbH - An der Strusbek 6 - 22926 Ahrensburg - GERMANY - - 00-15-77 (hex) Allied Telesis - 001577 (base 16) Allied Telesis - 3200 North First Street - San Jose California 95134 - UNITED STATES - - 00-15-78 (hex) Audio / Video Innovations - 001578 (base 16) Audio / Video Innovations - A3-3375 North Service Road - Burlington ON L7N 3G2 - CANADA - - 00-15-79 (hex) Lunatone Industrielle Elektronik GmbH - 001579 (base 16) Lunatone Industrielle Elektronik GmbH - Rennbahnweg 55 - Wien 1220 - AUSTRIA - - 00-15-7A (hex) Telefin S.p.A. - 00157A (base 16) Telefin S.p.A. - Via Albere 87/A - Verona VR 37138 - ITALY - - 00-15-7B (hex) Leuze electronic GmbH + Co. KG - 00157B (base 16) Leuze electronic GmbH + Co. KG - In der Braike 1 - Owen Baden-Württemberg 73277 - GERMANY - - 00-15-7C (hex) Dave Networks, Inc. - 00157C (base 16) Dave Networks, Inc. - 2151 O'tool Avenue - Suite H - San Jose CA 95131 - UNITED STATES - - 00-15-7D (hex) POSDATA CO., LTD. - 00157D (base 16) POSDATA CO., LTD. - 276-2,Seohyeon-dong,Bundang-gu, - Seongnam-City Kyeonggi-Do 463-775 - KOREA, REPUBLIC OF - - 00-15-7E (hex) Weidmüller Interface GmbH & Co. KG - 00157E (base 16) Weidmüller Interface GmbH & Co. KG - Klingenbergstraße 16 - Detmold 32758 - GERMANY - - 00-15-7F (hex) ChuanG International Holding CO.,LTD. - 00157F (base 16) ChuanG International Holding CO.,LTD. - 1F, NO.12, Alley 1, Lane 125, Guolian Street 4Lirn, Wuhan Village - Taoyuan Longtan 325 - TAIWAN, PROVINCE OF CHINA - - 00-15-80 (hex) U-WAY CORPORATION - 001580 (base 16) U-WAY CORPORATION - 3F-2, NO. 125, LANE 235, PAO-CHIAO - HSINTIEN CITY TAIPEI HSIEN 231 - TAIWAN, PROVINCE OF CHINA - - 00-15-81 (hex) MAKUS Inc. - 001581 (base 16) MAKUS Inc. - 4F Daedo Bldg. 748-14 Yeoksam-dong, Kangnam-gu - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-15-82 (hex) Pulse Eight Limited - 001582 (base 16) Pulse Eight Limited - 13 The Metro Centre - Peterbourugh PE2 7UH - UNITED KINGDOM - - 00-15-83 (hex) IVT corporation - 001583 (base 16) IVT corporation - Shangdi Xinxi road, Haidian District - Beijing 100085 - CHINA - - 00-15-84 (hex) Schenck Process GmbH - 001584 (base 16) Schenck Process GmbH - Pallaswiesenstraße 100 - Darmstadt Hessen 64293 - GERMANY - - 00-15-85 (hex) Aonvision Technolopy Corp. - 001585 (base 16) Aonvision Technolopy Corp. - 2F, No. 58, Park 2nd Ave. Science-Based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-15-86 (hex) Xiamen Overseas Chinese Electronic Co., Ltd. - 001586 (base 16) Xiamen Overseas Chinese Electronic Co., Ltd. - No. 22, Huli Street, - Huli Industrial District - Xiamen Fujian 361006 - CHINA - - 00-15-87 (hex) Takenaka Seisakusho Co.,Ltd - 001587 (base 16) Takenaka Seisakusho Co.,Ltd - 178 HISHIE - HIGASHI-OSAKA CITY OSAKA 578-0984 - JAPAN - - 00-15-88 (hex) Salutica Allied Solutions Sdn Bhd - 001588 (base 16) Salutica Allied Solutions Sdn Bhd - 3 Jalan Zarib 6 - Kawasan Perindustrian Zarib - Lahat, Ipoh Perak 31500 - MALAYSIA - - 00-15-89 (hex) D-MAX Technology Co.,Ltd - 001589 (base 16) D-MAX Technology Co.,Ltd - 7F-6,NO.26,Lian Cheng RD.,Chung-Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-15-8A (hex) SURECOM Technology Corp. - 00158A (base 16) SURECOM Technology Corp. - 6F, No. 125, Sec. 2, Datung Rd. - Shijr City, Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-15-8B (hex) Park Air Systems Ltd - 00158B (base 16) Park Air Systems Ltd - Northfields - Market Deeping - Peterborough PE6 8UE - UNITED KINGDOM - - 00-15-8C (hex) Liab ApS - 00158C (base 16) Liab ApS - Oestre Alle 6 - Stoevring DK-9530 - DENMARK - - 00-15-8D (hex) Jennic Ltd - 00158D (base 16) Jennic Ltd - Furnival Street - Sheffield Yorkshire S1 4QT - UNITED KINGDOM - - 00-15-8E (hex) Plustek.INC - 00158E (base 16) Plustek.INC - 13F-1,No3(Building F) Yuan Qu Street - Taipei Yuan Qu 115 - TAIWAN, PROVINCE OF CHINA - - 00-15-8F (hex) NTT Advanced Technology Corporation - 00158F (base 16) NTT Advanced Technology Corporation - Shinjuku Mitsui Bldg. 2-1-1, Nishi-shinjuku - Shinjuku-ku Tokyo 163-0431 - JAPAN - - 00-15-90 (hex) Hectronic GmbH - 001590 (base 16) Hectronic GmbH - Allmendstraße 15 - Bonndorf Baden-Württemberg 79848 - GERMANY - - 00-15-91 (hex) RLW Inc. - 001591 (base 16) RLW Inc. - 2029 Cato Ave. - State College PA 16801 - UNITED STATES - - 00-15-92 (hex) Facom UK Ltd (Melksham) - 001592 (base 16) Facom UK Ltd (Melksham) - Lancaster House - Bowerhill Industrial Estate - Melksham Wiltshire SN104FB - UNITED KINGDOM - - 00-15-93 (hex) U4EA Technologies Inc. - 001593 (base 16) U4EA Technologies Inc. - 48860 Milmont Drive - Suite107C - Fremont CA 94538 - UNITED STATES - - 00-15-94 (hex) BIXOLON CO.,LTD - 001594 (base 16) BIXOLON CO.,LTD - 502-508,Digital Empire Bldg. - 980-3 Yeongtong-Dong - Yeongtong-Gu,Suwon Gyeonggi-Do 443-813 - KOREA, REPUBLIC OF - - 00-15-95 (hex) Quester Tangent Corporation - 001595 (base 16) Quester Tangent Corporation - 201 - 9865 West Saanich Road - Sidney BC V8L 5Y8 - CANADA - - 00-15-96 (hex) ARRIS International - 001596 (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-15-97 (hex) AETA AUDIO SYSTEMS - 001597 (base 16) AETA AUDIO SYSTEMS - 18-22, avenue Edouard Herriot - Kepler 4 - Le Plessis Robinson 92350 - FRANCE - - 00-15-98 (hex) Kolektor group - 001598 (base 16) Kolektor group - Vojkova 10 - Idrija 5280 - SLOVENIA - - 00-15-99 (hex) Samsung Electronics Co., LTD - 001599 (base 16) Samsung Electronics Co., LTD - 416, Maetan-3Dong, Yeongtong-Gu - Suwon Gyeonggi 443-742 - KOREA, REPUBLIC OF - - 00-15-9A (hex) ARRIS Group, Inc. - 00159A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-15-9B (hex) Nortel - 00159B (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-15-9C (hex) B-KYUNG SYSTEM Co.,Ltd. - 00159C (base 16) B-KYUNG SYSTEM Co.,Ltd. - #812,WOOLIM E-BIZ CENTER,170-5 - GURO-DONG GURO-GU 152-847 - KOREA, REPUBLIC OF - - 00-15-9D (hex) Tripp Lite - 00159D (base 16) Tripp Lite - 1111 W 35th Street - Chicago IL 60609 - UNITED STATES - - 00-15-9E (hex) Mad Catz Interactive Inc - 00159E (base 16) Mad Catz Interactive Inc - Units 3+4 West Point Row - Great Park Rd, Almondsbury - Bristol South Gloucestershire BS32 4QG - UNITED KINGDOM - - 00-15-9F (hex) Terascala, Inc. - 00159F (base 16) Terascala, Inc. - 145 Bodwell Street - Avon MA 02322 - UNITED STATES - - 00-15-A0 (hex) Nokia Danmark A/S - 0015A0 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-15-A1 (hex) ECA-SINTERS - 0015A1 (base 16) ECA-SINTERS - 5, rue Paul Mesplé - TOULOUSE Cedex 01 31106 - FRANCE - - 00-15-A2 (hex) ARRIS International - 0015A2 (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-15-A3 (hex) ARRIS International - 0015A3 (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-15-A4 (hex) ARRIS International - 0015A4 (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-15-A5 (hex) DCI Co., Ltd. - 0015A5 (base 16) DCI Co., Ltd. - 4th Fl. Susung B/D, 893-4 - Jijok-dong - Yuseong-gu Daejeon 305-330 - KOREA, REPUBLIC OF - - 00-15-A6 (hex) Digital Electronics Products Ltd. - 0015A6 (base 16) Digital Electronics Products Ltd. - Room 301, 3 rd Floor, Tsun Yip Centre - 41 Tsun Yip Street - Kwun Tong 852 - HONG KONG - - 00-15-A7 (hex) Robatech AG - 0015A7 (base 16) Robatech AG - Pilatusring 10 - Muri AG 5630 - SWITZERLAND - - 00-15-A8 (hex) ARRIS Group, Inc. - 0015A8 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-15-A9 (hex) KWANG WOO I&C CO.,LTD - 0015A9 (base 16) KWANG WOO I&C CO.,LTD - 898-23, Hogye-dong,Dongan-gu - Anyang-si,Gyeonggi-do - 431-080 - KOREA, REPUBLIC OF - - 00-15-AA (hex) Rextechnik International Co., - 0015AA (base 16) Rextechnik International Co., - Room 5-3, No.51, Section 2, Keelung Road - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-15-AB (hex) PRO CO SOUND INC - 0015AB (base 16) PRO CO SOUND INC - 225 PARSONS STREET - KALAMAZOO MICHIGAN 49008 - UNITED STATES - - 00-15-AC (hex) Capelon AB - 0015AC (base 16) Capelon AB - Jägerhorns väg 1 - Kungens Kurva Stockholm S-141 75 - SWEDEN - - 00-15-AD (hex) Accedian Networks - 0015AD (base 16) Accedian Networks - 4878 Levy, suite 202 - suite 202 - St-Laurent Quebec H9P 2V4 - CANADA - - 00-15-AE (hex) kyung il - 0015AE (base 16) kyung il - woar rong-myn yougate-ri 101-2 - paju-city gyeong gi 413-813 - KOREA, REPUBLIC OF - - 00-15-AF (hex) AzureWave Technologies, Inc. - 0015AF (base 16) AzureWave Technologies, Inc. - 8F., No.94, Baozhong Rd., Xindian - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-15-B0 (hex) AUTOTELENET CO.,LTD - 0015B0 (base 16) AUTOTELENET CO.,LTD - 2F, 898-24, Hogye2-dong, Dongan-gu - Anyang-City Kyunggi-do 431-836 - KOREA, REPUBLIC OF - - 00-15-B1 (hex) Ambient Corporation - 0015B1 (base 16) Ambient Corporation - 79 Chapel St. - Newton MA 02458 - UNITED STATES - - 00-15-B2 (hex) Advanced Industrial Computer, Inc. - 0015B2 (base 16) Advanced Industrial Computer, Inc. - 17970 E. Ajax Circle - City of Industry CA 91748 - UNITED STATES - - 00-15-B3 (hex) Caretech AB - 0015B3 (base 16) Caretech AB - Nyborgsvägen 197 - Kalix 95291 - SWEDEN - - 00-15-B4 (hex) Polymap Wireless LLC - 0015B4 (base 16) Polymap Wireless LLC - 310 S. Williams Blvd. Ste. 350 - Tucson AZ 85711 - UNITED STATES - - 00-15-B5 (hex) CI Network Corp. - 0015B5 (base 16) CI Network Corp. - 2F Daini Inoue Bldg - 1-6-6 Akasaka Minato-ku - Tokyo 107-0052 - JAPAN - - 00-15-B6 (hex) ShinMaywa Industries, Ltd. - 0015B6 (base 16) ShinMaywa Industries, Ltd. - 1-1 Shinmeiwa-cho - Takarazuka Hyogo 665-8550 - JAPAN - - 00-15-B7 (hex) Toshiba - 0015B7 (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - 00-15-B8 (hex) Tahoe - 0015B8 (base 16) Tahoe - ul. Uniwersytecka 1 - Wroclaw 50951 - POLAND - - 00-15-B9 (hex) Samsung Electronics Co., Ltd. - 0015B9 (base 16) Samsung Electronics Co., Ltd. - #94-1 - Imsoo-Dong - Gumi-City Gyeong-Buk 730-350 - KOREA, REPUBLIC OF - - 00-15-BA (hex) iba AG - 0015BA (base 16) iba AG - Koenigswarterstrasse 44 - Fuerth Bavaria 90762 - GERMANY - - 00-15-BB (hex) SMA Solar Technology AG - 0015BB (base 16) SMA Solar Technology AG - Sonnenallee 1 - Niestetal Hessen 34266 - GERMANY - - 00-15-BC (hex) Develco - 0015BC (base 16) Develco - Olof Palmes Allé 40 - Aarhus N 8200 - DENMARK - - 00-15-BD (hex) Group 4 Technology Ltd - 0015BD (base 16) Group 4 Technology Ltd - Challenge House - International Drive - Tewkesbury Gloucestershire GL20 8UQ - UNITED KINGDOM - - 00-15-BE (hex) Iqua Ltd. - 0015BE (base 16) Iqua Ltd. - Hyvoninkatu 1 - Salo Varsinais-Suomi 24240 - FINLAND - - 00-15-BF (hex) technicob - 0015BF (base 16) technicob - 4 Rue Camille Saint-Saens - LANESTER Morbihan 56602 - FRANCE - - 00-15-C0 (hex) DIGITAL TELEMEDIA CO.,LTD. - 0015C0 (base 16) DIGITAL TELEMEDIA CO.,LTD. - 17TH FLOOR, CHINA YUSE BUILDING, - NO 6013 SHENNAN ROAD,FUTIAN DISTRICT - SHENZHEN GUANGDONG 518040 - CHINA - - 00-15-C1 (hex) SONY Computer Entertainment inc, - 0015C1 (base 16) SONY Computer Entertainment inc, - 6-21,2Chome - Minami-Aoyama - Minato-ku Tokyo 107-0062 - JAPAN - - 00-15-C2 (hex) 3M Germany - 0015C2 (base 16) 3M Germany - Carl Schurz Str. 1 - Neuss NRW 41453 - GERMANY - - 00-15-C3 (hex) Ruf Telematik AG - 0015C3 (base 16) Ruf Telematik AG - Ruetistrasse 13 - Schlieren ZH 8952 - SWITZERLAND - - 00-15-C4 (hex) FLOVEL CO., LTD. - 0015C4 (base 16) FLOVEL CO., LTD. - The Tachihi building No,3 hall, 6-1, Sakae-cho, - Tachikawa-shi - Tokyo 190-0003 - JAPAN - - 00-15-C5 (hex) Dell Inc - 0015C5 (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-15-C6 (hex) CISCO SYSTEMS, INC. - 0015C6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-C7 (hex) CISCO SYSTEMS, INC. - 0015C7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-C8 (hex) FlexiPanel Ltd - 0015C8 (base 16) FlexiPanel Ltd - 7 bis rue Lalo - Paris 75016 - FRANCE - - 00-15-C9 (hex) Gumstix, Inc - 0015C9 (base 16) Gumstix, Inc - 3130 Alpine Road - Suite 288-606 - Portola Valley CA 94028 - UNITED STATES - - 00-15-CA (hex) TeraRecon, Inc. - 0015CA (base 16) TeraRecon, Inc. - 2955 Campus Drive, Suite 325 - San Mateo CA 94403 - UNITED STATES - - 00-15-CB (hex) Surf Communication Solutions Ltd. - 0015CB (base 16) Surf Communication Solutions Ltd. - P.O. Box 343 - Soltam Industrial Zone - Yokneam 20164 - ISRAEL - - 00-15-CC (hex) UQUEST, LTD. - 0015CC (base 16) UQUEST, LTD. - Sannomiya Intes Bldg. 8F - 7-1-8 Isogami-dori, Chuo-ku - Kobe HYOGO 651-0086 - JAPAN - - 00-15-CD (hex) Exartech International Corp. - 0015CD (base 16) Exartech International Corp. - 3/F, No.62, Lane 188, Ruei Guang Rd., Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-15-CE (hex) ARRIS International - 0015CE (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-15-CF (hex) ARRIS International - 0015CF (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-15-D0 (hex) ARRIS International - 0015D0 (base 16) ARRIS International - 3871 Lakefield Drive - Suite 300 - Suwanee GA 30024 - UNITED STATES - - 00-15-D1 (hex) ARRIS Group, Inc. - 0015D1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-15-D2 (hex) Xantech Corporation - 0015D2 (base 16) Xantech Corporation - 13100 Telfair Avenue - Second Floor - Sylmar CA 91342-3573 - UNITED STATES - - 00-15-D3 (hex) Pantech&Curitel Communications, Inc. - 0015D3 (base 16) Pantech&Curitel Communications, Inc. - 1451-34, Seocho-dong, Seocho-Gu - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-15-D4 (hex) Emitor AB - 0015D4 (base 16) Emitor AB - Sjöviksbacken 14 - Stockholm 117 43 - SWEDEN - - 00-15-D5 (hex) NICEVT - 0015D5 (base 16) NICEVT - Warshawskoe shosse 125 - Moscow 117405 - RUSSIAN FEDERATION - - 00-15-D6 (hex) OSLiNK Sp. z o.o. - 0015D6 (base 16) OSLiNK Sp. z o.o. - ul. Marsa 27 - Gdansk 80299 - POLAND - - 00-15-D7 (hex) Reti Corporation - 0015D7 (base 16) Reti Corporation - 6F,No 13, Lane 120, Sec 1, Neihu Rd., - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-15-D8 (hex) Interlink Electronics - 0015D8 (base 16) Interlink Electronics - 546 Flynn Road - Camarillo CA 93012 - UNITED STATES - - 00-15-D9 (hex) PKC Electronics Oy - 0015D9 (base 16) PKC Electronics Oy - Pajuniityntie 43 - RAAHE 92120 - FINLAND - - 00-15-DA (hex) IRITEL A.D. - 0015DA (base 16) IRITEL A.D. - Batajnicki put 23 - Beograd Serbia 11080 - YUGOSLAVIA - - 00-15-DB (hex) Canesta Inc. - 0015DB (base 16) Canesta Inc. - 965 West Maude Avenue - Sunnyvale California 94085 - UNITED STATES - - 00-15-DC (hex) KT&C Co., Ltd. - 0015DC (base 16) KT&C Co., Ltd. - 487-4, KT&C Bldg. - BangHwa-Dong - GangSeo-Ku Seoul 157-849 - KOREA, REPUBLIC OF - - 00-15-DD (hex) IP Control Systems Ltd. - 0015DD (base 16) IP Control Systems Ltd. - Unit 15, Hi-Tech Village, - Witney Way, Boldon Business Park, - Boldon Tyne & Wear NE35 9PE - UNITED KINGDOM - - 00-15-DE (hex) Nokia Danmark A/S - 0015DE (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 V - DENMARK - - 00-15-DF (hex) Clivet S.p.A. - 0015DF (base 16) Clivet S.p.A. - via Camp Lonc 25 - Feltre Belluno 32030 - ITALY - - 00-15-E0 (hex) Ericsson - 0015E0 (base 16) Ericsson - Nya Vattentornet - Lund SE-221 83 - SWEDEN - - 00-15-E1 (hex) Picochip Ltd - 0015E1 (base 16) Picochip Ltd - Upper Borough Court - Upper Borough Walls - Bath BA1 1RG - UNITED KINGDOM - - 00-15-E2 (hex) Dr.Ing. Herbert Knauer GmbH - 0015E2 (base 16) Dr.Ing. Herbert Knauer GmbH - Hegauer Weg 38 - Berlin 14163 - GERMANY - - 00-15-E3 (hex) Dream Technologies Corporation - 0015E3 (base 16) Dream Technologies Corporation - Ebisu Prime Square, 1-1-39 Hiroo - Shibuya-ku Tokyo 150-0012 - JAPAN - - 00-15-E4 (hex) Zimmer Elektromedizin - 0015E4 (base 16) Zimmer Elektromedizin - Junkersstrasse 9 - Neu-Ulm Bayern 89231 - GERMANY - - 00-15-E5 (hex) Cheertek Inc. - 0015E5 (base 16) Cheertek Inc. - No.2, Du-Sing First Road, Science-Based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-15-E6 (hex) MOBILE TECHNIKA Inc. - 0015E6 (base 16) MOBILE TECHNIKA Inc. - Sotobori Sky Bld. 5th Floor - 2-11 Ichigaya Honmura-cho, - Shinjuku-ku Tokyo 162-0845 - JAPAN - - 00-15-E7 (hex) Quantec Tontechnik - 0015E7 (base 16) Quantec Tontechnik - Mittenwalderstr.63 - München D-81377 - GERMANY - - 00-15-E8 (hex) Nortel - 0015E8 (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-15-E9 (hex) D-Link Corporation - 0015E9 (base 16) D-Link Corporation - 2F, No.233-2, Pao-Chiao Road - Hsin-Tien, Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-15-EA (hex) Tellumat (Pty) Ltd - 0015EA (base 16) Tellumat (Pty) Ltd - 64/74 White Road - Retreat - Cape Town Western Province 7945 - SOUTH AFRICA - - 00-15-EB (hex) ZTE CORPORATION - 0015EB (base 16) ZTE CORPORATION - 5/F,A Wing,ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-15-EC (hex) Boca Devices LLC - 0015EC (base 16) Boca Devices LLC - 7647 Sierra Ter - Boca Raton Florida 33433 - UNITED STATES - - 00-15-ED (hex) Fulcrum Microsystems, Inc. - 0015ED (base 16) Fulcrum Microsystems, Inc. - 26630 Agoura Road - Calabasas CA 91302 - UNITED STATES - - 00-15-EE (hex) Omnex Control Systems - 0015EE (base 16) Omnex Control Systems - #74 - 1833 Coast Meridian Rd. - Port Coquitlam BC V3C 6G5 - CANADA - - 00-15-EF (hex) NEC TOKIN Corporation - 0015EF (base 16) NEC TOKIN Corporation - 1-1,Asahi-Cho 7-chome,Shiroishi - Miyagi 989-0223 - JAPAN - - 00-15-F0 (hex) EGO BV - 0015F0 (base 16) EGO BV - Parade 15 - 's-Hertogenbosch Noord-Brabant 5211KL - NETHERLANDS - - 00-15-F1 (hex) KYLINK Communications Corp. - 0015F1 (base 16) KYLINK Communications Corp. - 8F-8, No. 351, Sec. 2, Zhongshan Rd., Zhonghe City - Taipei County - 23504 - TAIWAN, PROVINCE OF CHINA - - 00-15-F2 (hex) ASUSTek COMPUTER INC. - 0015F2 (base 16) ASUSTek COMPUTER INC. - No.5 Shing Yeh Street,Kwei Shan Hsiang,Taoyuan - Taipei 333 - TAIWAN, PROVINCE OF CHINA - - 00-15-F3 (hex) PELTOR AB - 0015F3 (base 16) PELTOR AB - Box 2341 - SE-331 02 Värnamo SE-331 02 - SWEDEN - - 00-15-F4 (hex) Eventide - 0015F4 (base 16) Eventide - 1 Alsan Way - Little Ferry NJ 07643 - UNITED STATES - - 00-15-F5 (hex) Sustainable Energy Systems - 0015F5 (base 16) Sustainable Energy Systems - #500, 609 14th Street NW - Calgary Ab T2T 1P3 - CANADA - - 00-15-F6 (hex) SCIENCE AND ENGINEERING SERVICES, INC. - 0015F6 (base 16) SCIENCE AND ENGINEERING SERVICES, INC. - 4015 PULASKI PIKE NW - HUNTSVILLE AL 35810 - UNITED STATES - - 00-15-F7 (hex) Wintecronics Ltd. - 0015F7 (base 16) Wintecronics Ltd. - No. 716, 11F-3, Jung Jeng Rd. - Chung Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-15-F8 (hex) Kingtronics Industrial Co. Ltd. - 0015F8 (base 16) Kingtronics Industrial Co. Ltd. - Penthouse, Century Centre, - 44-46 Hung To Road, Kwun Tong - Kowloon - HONG KONG - - 00-15-F9 (hex) CISCO SYSTEMS, INC. - 0015F9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-FA (hex) CISCO SYSTEMS, INC. - 0015FA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-15-FB (hex) setex schermuly textile computer gmbh - 0015FB (base 16) setex schermuly textile computer gmbh - Hauptsttraße 25 - Mengerskirchen Hessen 35794 - GERMANY - - 00-15-FC (hex) Littelfuse Startco - 0015FC (base 16) Littelfuse Startco - 3714 Kinnear Pl - Saskatoon SK S7P 0A6 - CANADA - - 00-15-FD (hex) Complete Media Systems - 0015FD (base 16) Complete Media Systems - Grove Place - Cuckfield Lane - Warninglid West sussex RH17 5SN - UNITED KINGDOM - - 00-15-FE (hex) SCHILLING ROBOTICS LLC - 0015FE (base 16) SCHILLING ROBOTICS LLC - 260 COUSTEAU PL - DAVIS CA 95618 - UNITED STATES - - 00-15-FF (hex) Novatel Wireless, Inc. - 0015FF (base 16) Novatel Wireless, Inc. - 9645 Scranton Road - Suite 205 - San Diego California 92121 - UNITED STATES - - 00-16-00 (hex) CelleBrite Mobile Synchronization - 001600 (base 16) CelleBrite Mobile Synchronization - 25 Basel St. - POB 7565 - Petach Tikva 49170 - ISRAEL - - 00-16-01 (hex) Buffalo Inc. - 001601 (base 16) Buffalo Inc. - AKAMONDORI Bldg., 30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref. 460-8315 - JAPAN - - 00-16-02 (hex) CEYON TECHNOLOGY CO.,LTD. - 001602 (base 16) CEYON TECHNOLOGY CO.,LTD. - 13F Samsung Insurance B/D. #942-9 - Ingye-Dong,Paldal-Gu - Suwon-City Gyeonggi-Do 442-832 - KOREA, REPUBLIC OF - - 00-16-03 (hex) COOLKSKY Co., LTD - 001603 (base 16) COOLKSKY Co., LTD - Shingsung offcetel A511, 1588-1 - Secho Seoul 137-070 - KOREA, REPUBLIC OF - - 00-16-04 (hex) Sigpro - 001604 (base 16) Sigpro - 655 W Evelyn ST - Suite 2 - Mountain View CA 94041 - UNITED STATES - - 00-16-05 (hex) YORKVILLE SOUND INC. - 001605 (base 16) YORKVILLE SOUND INC. - 4625 WITMER INDUSTRIAL ESTATE - NIAGARA FALLS NY 14305 - UNITED STATES - - 00-16-06 (hex) Ideal Industries - 001606 (base 16) Ideal Industries - 15070 Ave. of Science #200 - San Diego CA 92128 - UNITED STATES - - 00-16-07 (hex) Curves International Inc. - 001607 (base 16) Curves International Inc. - 100 Ritchie Road - Waco Texas 76712 - UNITED STATES - - 00-16-08 (hex) Sequans Communications - 001608 (base 16) Sequans Communications - 19 Le Parvis de la Défense - Bâtiment CitiCenter - PARIS LA DEFENSE CEDEX 92073 - FRANCE - - 00-16-09 (hex) Unitech electronics co., ltd. - 001609 (base 16) Unitech electronics co., ltd. - 5F,No.136,Lane 235 ,Pao-chiao Rd., - Hsin-Tien city Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-16-0A (hex) SWEEX Europe BV - 00160A (base 16) SWEEX Europe BV - Ampereweg 3 - Delft Zuid-Holland 2627 BG - NETHERLANDS - - 00-16-0B (hex) TVWorks LLC - 00160B (base 16) TVWorks LLC - Two Belvedere Place, #200 - Mill Valley CA 94941 - UNITED STATES - - 00-16-0C (hex) LPL DEVELOPMENT S.A. DE C.V - 00160C (base 16) LPL DEVELOPMENT S.A. DE C.V - LAGO GINEBRA 380 P3 - COL. FRANCISCO I MADERO - D.F. 11480 - MEXICO - - 00-16-0D (hex) Be Here Corporation - 00160D (base 16) Be Here Corporation - 39300 Civic Center Dr., Suite 180 - Fremont CA 94538 - UNITED STATES - - 00-16-0E (hex) Optica Technologies Inc. - 00160E (base 16) Optica Technologies Inc. - 2051 Dogwood Street - Suite 210 - Louisville CO 80027 - UNITED STATES - - 00-16-0F (hex) BADGER METER INC - 00160F (base 16) BADGER METER INC - 4545 W BROWN DEER RD - MILWAUKEE WI 53223 - UNITED STATES - - 00-16-10 (hex) Carina Technology - 001610 (base 16) Carina Technology - 690A Discovery Drive - Huntsville AL 35806 - UNITED STATES - - 00-16-11 (hex) Altecon Srl - 001611 (base 16) Altecon Srl - Via F.lli Cairoli, 17 - Lissone Milano 20035 - ITALY - - 00-16-12 (hex) Otsuka Electronics Co., Ltd. - 001612 (base 16) Otsuka Electronics Co., Ltd. - 1-10 Sasagaoka, Minakuchi - kouka shiga 528-0061 - JAPAN - - 00-16-13 (hex) LibreStream Technologies Inc. - 001613 (base 16) LibreStream Technologies Inc. - 895 Waverley Street - Suite 110 - Winnipeg Manitoba R3T 5P4 - CANADA - - 00-16-14 (hex) Picosecond Pulse Labs - 001614 (base 16) Picosecond Pulse Labs - 2500 55th Street - Boulder CO 80301 - UNITED STATES - - 00-16-15 (hex) Nittan Company, Limited - 001615 (base 16) Nittan Company, Limited - 11-6, 1-chome, Hatagaya - Shibuya-ku Tokyo 151-8535 - JAPAN - - 00-16-16 (hex) BROWAN COMMUNICATION INC. - 001616 (base 16) BROWAN COMMUNICATION INC. - No.1 Jen-Ai Road, HsinChu Industrial Park, - HuKou Hsiang HsinChu Hsien 303 - TAIWAN, PROVINCE OF CHINA - - 00-16-17 (hex) MSI - 001617 (base 16) MSI - No.69, Li-De St, Jung-Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-16-18 (hex) HIVION Co., Ltd. - 001618 (base 16) HIVION Co., Ltd. - 2F., Akyung Bldg., 54-10, Munjeong-dong, - Songpa-Gu Seoul - KOREA, REPUBLIC OF - - 00-16-19 (hex) Lancelan Technologies S.L. - 001619 (base 16) Lancelan Technologies S.L. - C/Angel Guimera 208 bis - Terrassa Barcelona 08223 - SPAIN - - 00-16-1A (hex) Dametric AB - 00161A (base 16) Dametric AB - Box 120 - Skarholmen Stockholm SE-12723 - SWEDEN - - 00-16-1B (hex) Micronet Corporation - 00161B (base 16) Micronet Corporation - 1788-388 Nomura Hirooka - Shiojiri-shi Nagano-ken 399-0702 - JAPAN - - 00-16-1C (hex) e:cue - 00161C (base 16) e:cue - Friedrich-List-Strasse 23 - Paderborn 33100 - GERMANY - - 00-16-1D (hex) Innovative Wireless Technologies, Inc. - 00161D (base 16) Innovative Wireless Technologies, Inc. - 1047 Vista Park Dr. - Suite A - Forest VA 24551 - UNITED STATES - - 00-16-1E (hex) Woojinnet - 00161E (base 16) Woojinnet - 292 osan dongtan - hwaseong kyonggi 445-813 - KOREA, REPUBLIC OF - - 00-16-1F (hex) SUNWAVETEC Co., Ltd. - 00161F (base 16) SUNWAVETEC Co., Ltd. - #823, Kwanyang-dong, Dongan-ku - Anyang-si Kyungki-do 431-060 - KOREA, REPUBLIC OF - - 00-16-20 (hex) Sony Ericsson Mobile Communications AB - 001620 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-16-21 (hex) Colorado Vnet - 001621 (base 16) Colorado Vnet - 255 E. 6th St. - Loveland CO 80537 - UNITED STATES - - 00-16-22 (hex) BBH SYSTEMS GMBH - 001622 (base 16) BBH SYSTEMS GMBH - Böttgerstraße 40 - Weiden i.d.OPf. Bayern 92637 - GERMANY - - 00-16-23 (hex) Interval Media - 001623 (base 16) Interval Media - 3200 Ash Street - Palo Alto CA 94306 - UNITED STATES - - 00-16-24 (hex) Teneros, Inc. - 001624 (base 16) Teneros, Inc. - 215 Castro St. - 3rd Floor - Mt. View CA 94041 - UNITED STATES - - 00-16-25 (hex) Impinj, Inc. - 001625 (base 16) Impinj, Inc. - 701 N. 34th Street - Suite 300 - Seattle WA 98103 - UNITED STATES - - 00-16-26 (hex) ARRIS Group, Inc. - 001626 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-16-27 (hex) embedded-logic DESIGN AND MORE GmbH - 001627 (base 16) embedded-logic DESIGN AND MORE GmbH - Hansestrasse 24 - Muenster NRW 48153 - GERMANY - - 00-16-28 (hex) Ultra Electronics Manufacturing and Card Systems - 001628 (base 16) Ultra Electronics Manufacturing and Card Systems - Hampshire Road - Granby Estate - Weymouth Dorset DT4 9XD - UNITED KINGDOM - - 00-16-29 (hex) Nivus GmbH - 001629 (base 16) Nivus GmbH - Im Täle 2 - Eppingen Baden-Württemberg 75031 - GERMANY - - 00-16-2A (hex) Antik computers & communications s.r.o. - 00162A (base 16) Antik computers & communications s.r.o. - Razusova 2 - Kosice SK SK-04001 - SLOVAKIA - - 00-16-2B (hex) Togami Electric Mfg.co.,Ltd. - 00162B (base 16) Togami Electric Mfg.co.,Ltd. - 1-1 Ohtakara-Kitamachi - Saga.PRF 840-0802 - JAPAN - - 00-16-2C (hex) Xanboo - 00162C (base 16) Xanboo - 115 West 30th, 6th Fl - New York NY 10001 - UNITED STATES - - 00-16-2D (hex) STNet Co., Ltd. - 00162D (base 16) STNet Co., Ltd. - Shin-wha Building 4F, 954-25 - Kwanyang-dong, Dongan-gu - Anyang-si Kyungki-do 431-060 - KOREA, REPUBLIC OF - - 00-16-2E (hex) Space Shuttle Hi-Tech Co., Ltd. - 00162E (base 16) Space Shuttle Hi-Tech Co., Ltd. - No. 226, Wu-Ho St., Wu-Lung Village, - Chiung-Lin Hsiang, - Hsinchu Hsien 307 - TAIWAN, PROVINCE OF CHINA - - 00-16-2F (hex) Geutebrück GmbH - 00162F (base 16) Geutebrück GmbH - Im Nassen 7-9 - Windhagen 53578 - GERMANY - - 00-16-30 (hex) Vativ Technologies - 001630 (base 16) Vativ Technologies - 9339 Genesee Avenue - Suite 130 - San Diego CA 92121 - UNITED STATES - - 00-16-31 (hex) Xteam - 001631 (base 16) Xteam - room 801, No.102 international Science & Techology Park - No.2 ShangDi Info Road, HaiDian District - Beijing 8610 - CHINA - - 00-16-32 (hex) SAMSUNG ELECTRONICS CO., LTD. - 001632 (base 16) SAMSUNG ELECTRONICS CO., LTD. - 416, METAN-3DONG, - YOUNGTONG-GU - SUWON KYUNGKI-DO 442-742 - KOREA, REPUBLIC OF - - 00-16-33 (hex) Oxford Diagnostics Ltd. - 001633 (base 16) Oxford Diagnostics Ltd. - Sandybrae - Whitebarn Dr, Boars Hill - Oxford Oxon. OX1 5HJ - UNITED KINGDOM - - 00-16-34 (hex) Mathtech, Inc. - 001634 (base 16) Mathtech, Inc. - 6402 Arlington Blvd., - Suite 1200 - Falls Church Virginia 22042-2356 - UNITED STATES - - 00-16-35 (hex) Hewlett-Packard Company - 001635 (base 16) Hewlett-Packard Company - 20555 State Highway 249 South - MS070405 - Houston TX 77070 - UNITED STATES - - 00-16-36 (hex) Quanta Computer Inc. - 001636 (base 16) Quanta Computer Inc. - No. 211, Wen Hwa 2Rd., Kuei Shan Hsiang - Tao Yuan Shien - TAIWAN, PROVINCE OF CHINA - - 00-16-37 (hex) CITEL SpA - 001637 (base 16) CITEL SpA - Via L. G. Columella, 36 - Milan MI 20128 - ITALY - - 00-16-38 (hex) TECOM Co., Ltd. - 001638 (base 16) TECOM Co., Ltd. - 23 R&D Road 2 Science Based Industrial Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-16-39 (hex) UBIQUAM Co.,Ltd - 001639 (base 16) UBIQUAM Co.,Ltd - Technovill 4F,272-3 Yatap3 - Bundang - Seongnam Kyeonggi 463-836 - KOREA, REPUBLIC OF - - 00-16-3A (hex) YVES TECHNOLOGY CO., LTD. - 00163A (base 16) YVES TECHNOLOGY CO., LTD. - No.74, Fusing 2nd Rd. - Gueishan Taoyuan 33377 - TAIWAN, PROVINCE OF CHINA - - 00-16-3B (hex) VertexRSI/General Dynamics - 00163B (base 16) VertexRSI/General Dynamics - 2120 Old Gatesburg Rd. - State college PA 16803 - UNITED STATES - - 00-16-3C (hex) Rebox B.V. - 00163C (base 16) Rebox B.V. - Hendrik Figeeweg 1X - Haarlem Noord-Holland 2031 BJ - NETHERLANDS - - 00-16-3D (hex) Tsinghua Tongfang Legend Silicon Tech. Co., Ltd. - 00163D (base 16) Tsinghua Tongfang Legend Silicon Tech. Co., Ltd. - 26F TSINGHUA TONGFANG HI-TECH PLAZA - BEIJING 100083 - CHINA - - 00-16-3E (hex) Xensource, Inc. - 00163E (base 16) Xensource, Inc. - 2300 Geng Rd. - Suite 250 - Palo Alto CA 94303 - UNITED STATES - - 00-16-3F (hex) CReTE SYSTEMS Inc. - 00163F (base 16) CReTE SYSTEMS Inc. - 7F,No.250,Sec.3,Pei Shen Rd.,Shen Keng Hsiang - Taipei County 22204 - TAIWAN, PROVINCE OF CHINA - - 00-16-40 (hex) Asmobile Communication Inc. - 001640 (base 16) Asmobile Communication Inc. - No.11 Lane 120, Li-Te Rd., Peitou 112, Taipei, Taiwan, R.O.C - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-16-41 (hex) Universal Global Scientific Industrial Co., Ltd. - 001641 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351, SEC.1,TAIPING RD. - TSAOTUEN NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 00-16-42 (hex) Pangolin - 001642 (base 16) Pangolin - 9501 Satellite Boulevard, Suite 109 - Orlando FL 32837 - UNITED STATES - - 00-16-43 (hex) Sunhillo Corporation - 001643 (base 16) Sunhillo Corporation - 444 Kelley Drive - West Berlin New Jersey 08091 - UNITED STATES - - 00-16-44 (hex) LITE-ON Technology Corp. - 001644 (base 16) LITE-ON Technology Corp. - 18F, No.392, Ruey Kuang Road, Niehu, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-16-45 (hex) Power Distribution, Inc. - 001645 (base 16) Power Distribution, Inc. - 4200 Oakleys Ct. - Richmond VA 23223 - UNITED STATES - - 00-16-46 (hex) CISCO SYSTEMS, INC. - 001646 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-16-47 (hex) CISCO SYSTEMS, INC. - 001647 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-16-48 (hex) SSD Company Limited - 001648 (base 16) SSD Company Limited - 3-3-4 Higashiyagura - Kusatsu-city Shiga 525-0054 - JAPAN - - 00-16-49 (hex) SetOne GmbH - 001649 (base 16) SetOne GmbH - Hegenheimer Str. 2 - Weil am Rhein Baden Wuertemberg D-79576 - GERMANY - - 00-16-4A (hex) Vibration Technology Limited - 00164A (base 16) Vibration Technology Limited - Vibtech House, Central Boulevard - Central Park - Larbert Scotland FK5 4RU - UNITED KINGDOM - - 00-16-4B (hex) Quorion Data Systems GmbH - 00164B (base 16) Quorion Data Systems GmbH - An der Klinge 6 - Erfurt Thuringia 99095 - GERMANY - - 00-16-4C (hex) PLANET INT Co., Ltd - 00164C (base 16) PLANET INT Co., Ltd - 8th Floor, Saeum B/D, 1361-5 - Seocho-Dong, Seocho-Ku - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-16-4D (hex) Alcatel North America IP Division - 00164D (base 16) Alcatel North America IP Division - 701 E. Middlefield RD. - Mountain View CA 94043 - UNITED STATES - - 00-16-4E (hex) Nokia Danmark A/S - 00164E (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-16-4F (hex) World Ethnic Broadcastin Inc. - 00164F (base 16) World Ethnic Broadcastin Inc. - 50 California Street, Suite 1500 - San Francisco California 94111 - UNITED STATES - - 00-16-50 (hex) Herley General Microwave Israel. - 001650 (base 16) Herley General Microwave Israel. - KIBBUTZ EYAL - D.N. HASHARON HATICHON - 45840 - ISRAEL - - 00-16-51 (hex) Exeo Systems - 001651 (base 16) Exeo Systems - 1650, rue Michelin, suite 201 - Laval Québec H7L 4R3 - CANADA - - 00-16-52 (hex) Hoatech Technologies, Inc. - 001652 (base 16) Hoatech Technologies, Inc. - 1F., No.224, Guosheng St. - Zhubei HsinChu Hsien 30244 - TAIWAN, PROVINCE OF CHINA - - 00-16-53 (hex) LEGO System A/S IE Electronics Division - 001653 (base 16) LEGO System A/S IE Electronics Division - Aastvej 1 - Billund Kommune 7190 - DENMARK - - 00-16-54 (hex) Flex-P Industries Sdn. Bhd. - 001654 (base 16) Flex-P Industries Sdn. Bhd. - No.128-12-2, Menara UMNO, - Jalan Macalister, - Georgetown Penang 10400 - MALAYSIA - - 00-16-55 (hex) FUHO TECHNOLOGY Co., LTD - 001655 (base 16) FUHO TECHNOLOGY Co., LTD - No. 30, Lane 726, Jinma Rd, Sec. 3 - Chang Hua Taiwa 500 - TAIWAN, PROVINCE OF CHINA - - 00-16-56 (hex) Nintendo Co., Ltd. - 001656 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-16-57 (hex) Aegate Ltd - 001657 (base 16) Aegate Ltd - Technology Centre - Melbourn Hertfordshire SG8 6DP - UNITED KINGDOM - - 00-16-58 (hex) Fusiontech Technologies Inc. - 001658 (base 16) Fusiontech Technologies Inc. - 6F, No.78, Cheng Kung Rd., Sec. 1, - Nan Kang - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - 00-16-59 (hex) Z.M.P. RADWAG - 001659 (base 16) Z.M.P. RADWAG - Bracka 28 street - RADOM Mazowieckie 26-600 - POLAND - - 00-16-5A (hex) Harman Specialty Group - 00165A (base 16) Harman Specialty Group - 3 Oak Park Drive - Bedford MA 01730 - UNITED STATES - - 00-16-5B (hex) Grip Audio - 00165B (base 16) Grip Audio - 6345 W. Louise Drive - Glendale Arizona 85310-4243 - UNITED STATES - - 00-16-5C (hex) Trackflow Ltd - 00165C (base 16) Trackflow Ltd - 167-169 Kensington High Street - London England W86SH - UNITED KINGDOM - - 00-16-5D (hex) AirDefense, Inc. - 00165D (base 16) AirDefense, Inc. - 4800 North Point Pkwy - Ste 100 - Alpharetta GA 30022 - UNITED STATES - - 00-16-5E (hex) Precision I/O - 00165E (base 16) Precision I/O - 4005 Miranda Ave., Suite 210 - Palo Alto CA 94304-1232 - UNITED STATES - - 00-16-5F (hex) Fairmount Automation - 00165F (base 16) Fairmount Automation - 4621 West Chester Pike - Newtown Square PA 19073 - UNITED STATES - - 00-16-60 (hex) Nortel - 001660 (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-16-61 (hex) Novatium Solutions (P) Ltd - 001661 (base 16) Novatium Solutions (P) Ltd - 3rd Floor, Temple Towers, #672 - Anna Salai, Nandanam, - Chennai Tamil Nadu 600035 - INDIA - - 00-16-62 (hex) Liyuh Technology Ltd. - 001662 (base 16) Liyuh Technology Ltd. - 4F, No.19, Ln.221, Ganqian Rd., Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-16-63 (hex) KBT Mobile - 001663 (base 16) KBT Mobile - 4F, Polaris I, 15-3, Jeongja-dong, Bundang-gu - Seongnam-si, Gyeonggi-do 463-811 - KOREA, REPUBLIC OF - - 00-16-64 (hex) Prod-El SpA - 001664 (base 16) Prod-El SpA - Via Palmanova 185 - Milano MI 20132 - ITALY - - 00-16-65 (hex) Cellon France - 001665 (base 16) Cellon France - Route d'Angers Le Mans cedex 9 - Le Mans Sarthe 72081 - FRANCE - - 00-16-66 (hex) Quantier Communication Inc. - 001666 (base 16) Quantier Communication Inc. - 1F, No. 36, Industry E. Rd IV, - Science-Based Industrial park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-16-67 (hex) A-TEC Subsystem INC. - 001667 (base 16) A-TEC Subsystem INC. - 4F, No. 86, Chung-Hsing Road, Shijr City, - Taipei County - 221 - TAIWAN, PROVINCE OF CHINA - - 00-16-68 (hex) Eishin Electronics - 001668 (base 16) Eishin Electronics - Nishiku Miyashita 1-19 - Kobe City Hyogo Prefecture 651-2146 - JAPAN - - 00-16-69 (hex) MRV Communication (Networks) LTD - 001669 (base 16) MRV Communication (Networks) LTD - P.O Box 614 - Yokneam 20692 - ISRAEL - - 00-16-6A (hex) TPS - 00166A (base 16) TPS - 145 quai de Stalingrad - Issy Les Moulineaux Ile de France 92137 - FRANCE - - 00-16-6B (hex) Samsung Electronics - 00166B (base 16) Samsung Electronics - 416,Maetan-3Dong,Yeongtong-Gu - Suwon-City Kyeonggi-Do 443-742 - KOREA, REPUBLIC OF - - 00-16-6C (hex) Samsung Electonics Digital Video System Division - 00166C (base 16) Samsung Electonics Digital Video System Division - 416, Maetan-3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443-742 - KOREA, REPUBLIC OF - - 00-16-6D (hex) Yulong Computer Telecommunication Scientific(shenzhen)Co.,Lt - 00166D (base 16) Yulong Computer Telecommunication Scientific(shenzhen)Co.,Lt - 8/F.high Tech Plaza,TianAn Cyberpark,Chegongmiao - Shenzhen Guangdong 518040 - CHINA - - 00-16-6E (hex) Arbitron Inc. - 00166E (base 16) Arbitron Inc. - 9705 Patuxent Woods Drive - Columbia MD 21046 - UNITED STATES - - 00-16-6F (hex) Intel Corporate - 00166F (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-16-70 (hex) SKNET Corporation - 001670 (base 16) SKNET Corporation - Fontana Shinyokohama - Shinyokohama 2,17,2 kohoku-ku - Yokohama Kanagawa 222-0033 - JAPAN - - 00-16-71 (hex) Symphox Information Co. - 001671 (base 16) Symphox Information Co. - 15F, No. 51, Sec. 3, Minsheng E. Road - Taipei City 104 - TAIWAN, PROVINCE OF CHINA - - 00-16-72 (hex) Zenway enterprise ltd - 001672 (base 16) Zenway enterprise ltd - 6F., No.20, Lane 150, Jhongsing Rd., Sijhih City - Taipei 886 - TAIWAN, PROVINCE OF CHINA - - 00-16-73 (hex) Bury GmbH & Co. KG - 001673 (base 16) Bury GmbH & Co. KG - Robert-Koch-Str. 1-7 - Loehne Germany 32584 - GERMANY - - 00-16-74 (hex) EuroCB (Phils.), Inc. - 001674 (base 16) EuroCB (Phils.), Inc. - SFB No.2 - Mactan Economic Zone - I - Lapulapu City Cebu 6015 - PHILIPPINES - - 00-16-75 (hex) ARRIS Group, Inc. - 001675 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-16-76 (hex) Intel Corporate - 001676 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-16-77 (hex) Bihl + Wiedemann GmbH - 001677 (base 16) Bihl + Wiedemann GmbH - Flosswoerthstr 41 - Mannheim 68199 - GERMANY - - 00-16-78 (hex) SHENZHEN BAOAN GAOKE ELECTRONICS CO., LTD - 001678 (base 16) SHENZHEN BAOAN GAOKE ELECTRONICS CO., LTD - GAOKE INDUSTRIAL PARK, NO.8 TANGKENG ROAD, SHIYAN TOWN - SHENZHEN GUANGDONG 518108 - CHINA - - 00-16-79 (hex) eOn Communications - 001679 (base 16) eOn Communications - 4105 Royal Drive, Suite 100 - Kennesaw Georgia 30144 - UNITED STATES - - 00-16-7A (hex) Skyworth Overseas Dvelopment Ltd. - 00167A (base 16) Skyworth Overseas Dvelopment Ltd. - Room 1505-06,Westlands Centre - 20 Westlands Road, Quarry Bay, - HONG KONG - - 00-16-7B (hex) Haver&Boecker - 00167B (base 16) Haver&Boecker - Carl-Haver-Platz 3 - Oelde NRW 59302 - GERMANY - - 00-16-7C (hex) iRex Technologies BV - 00167C (base 16) iRex Technologies BV - HighTech Campus - Building 46, room p-005 - Eindhoven Brabant 5656AE - NETHERLANDS - - 00-16-7D (hex) Sky-Line Information Co., Ltd. - 00167D (base 16) Sky-Line Information Co., Ltd. - 8F.,No.38,Sihyuan Rd., - Sinihuang Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 00-16-7E (hex) DIBOSS.CO.,LTD - 00167E (base 16) DIBOSS.CO.,LTD - 126-1, Gongdan-dong - Gumi Gyeongbuk 730-902 - KOREA, REPUBLIC OF - - 00-16-7F (hex) Bluebird Soft Inc. - 00167F (base 16) Bluebird Soft Inc. - 562-21 Gangnam-gu, - Seoul 135-890 - KOREA, REPUBLIC OF - - 00-16-80 (hex) Bally Gaming + Systems - 001680 (base 16) Bally Gaming + Systems - 950 Sandhill Road - Reno NV 89521 - UNITED STATES - - 00-16-81 (hex) Vector Informatik GmbH - 001681 (base 16) Vector Informatik GmbH - Ingersheimer Str. 24 - Stuttgart Baden-Württemberg 70499 - GERMANY - - 00-16-82 (hex) Pro Dex, Inc - 001682 (base 16) Pro Dex, Inc - 1800 NW 169th Place - C100 - Beaverton Oregon 97006 - UNITED STATES - - 00-16-83 (hex) WEBIO International Co.,.Ltd. - 001683 (base 16) WEBIO International Co.,.Ltd. - 21F.,No.171 Songde Rd.,Sinyi District - Taipei 11085 - TAIWAN, PROVINCE OF CHINA - - 00-16-84 (hex) Donjin Co.,Ltd. - 001684 (base 16) Donjin Co.,Ltd. - 21F,Cangsong Building,Tairan,Futian - Shenzhen Guangdong 518040 - CHINA - - 00-16-85 (hex) Elisa Oyj - 001685 (base 16) Elisa Oyj - Elektroniikkatie 4 - 90570 Oulu - FINLAND - - 00-16-86 (hex) Karl Storz Imaging - 001686 (base 16) Karl Storz Imaging - 175 Cremona Dr. - Goleta CA 93117 - UNITED STATES - - 00-16-87 (hex) Chubb CSC-Vendor AP - 001687 (base 16) Chubb CSC-Vendor AP - Ottawa STN - P.O. BOX 9832 - Ottawa K1G 6W6 - CANADA - - 00-16-88 (hex) ServerEngines LLC - 001688 (base 16) ServerEngines LLC - 209 N. Fair Oaks Avenue - Sunnyvale CA 94085 - UNITED STATES - - 00-16-89 (hex) Pilkor Electronics Co., Ltd - 001689 (base 16) Pilkor Electronics Co., Ltd - 381,Wonchun-Dong,Yeoungtong-Gu - Suwon Kyung Ki-Do 442-380 - KOREA, REPUBLIC OF - - 00-16-8A (hex) id-Confirm Inc - 00168A (base 16) id-Confirm Inc - 1800 Boulder St - Suite 400 - Denver CO 80211 - UNITED STATES - - 00-16-8B (hex) Paralan Corporation - 00168B (base 16) Paralan Corporation - 4655 Ruffner St. - San Diego CA 92111 - UNITED STATES - - 00-16-8C (hex) DSL Partner AS - 00168C (base 16) DSL Partner AS - Havreveien 49 - Oslo 0680 - NORWAY - - 00-16-8D (hex) KORWIN CO., Ltd. - 00168D (base 16) KORWIN CO., Ltd. - 3rd Floor, Hana Bldg, 123-7 Nonhyun-dong - Kangnam-gu - Seoul 135-010 - KOREA, REPUBLIC OF - - 00-16-8E (hex) Vimicro corporation - 00168E (base 16) Vimicro corporation - 15/F,Shining Tower,No.35,xueyuan - Road,Haidian District - Beijing 100083 - CHINA - - 00-16-8F (hex) GN Netcom as - 00168F (base 16) GN Netcom as - Metalbuen 66 - P.O.Box 201 - Ballerup Skovlunde DK - 2750 - DENMARK - - 00-16-90 (hex) J-TEK INCORPORATION - 001690 (base 16) J-TEK INCORPORATION - 2F-1, No. 83, Sec. 2, GongDaoWu Rd., - Hsinchu City 30070 - TAIWAN, PROVINCE OF CHINA - - 00-16-91 (hex) Moser-Baer AG - 001691 (base 16) Moser-Baer AG - Spitalstrasse 7 - Sumiswald BE 3454 - SWITZERLAND - - 00-16-92 (hex) Scientific-Atlanta, Inc. - 001692 (base 16) Scientific-Atlanta, Inc. - 5030 Sugarloaf Pkwy - ATL 1.3.473 - Lawrenceville GA 30044 - UNITED STATES - - 00-16-93 (hex) PowerLink Technology Inc. - 001693 (base 16) PowerLink Technology Inc. - N0. 18, Alley 1, Lane 151, Sec. 1, Jhongsing Rd., Wugu Township - Taipei Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 00-16-94 (hex) Sennheiser Communications A/S - 001694 (base 16) Sennheiser Communications A/S - Langager 6 - Solrød Strand Copenhagen 2680 - DENMARK - - 00-16-95 (hex) AVC Technology (International) Limited - 001695 (base 16) AVC Technology (International) Limited - 6/F Enterprise Square III - 39 Wang Chiu Road - Kowloon Bay - HONG KONG - - 00-16-96 (hex) QDI Technology (H.K.) Limited - 001696 (base 16) QDI Technology (H.K.) Limited - 16/F, Standard Chartered Bank Building 4-4A - Des Voeux Road Central - Hong Kong - CHINA - - 00-16-97 (hex) NEC Corporation - 001697 (base 16) NEC Corporation - 7-1, Shiba 5-chome Minato-ku, - Tokyo 108-8001 - JAPAN - - 00-16-98 (hex) T&A Mobile Phones - 001698 (base 16) T&A Mobile Phones - 4/F, South Building,No.2966, Jinke Road - Zhangjiang High-Teck Park - Pudong Shanghai 201203 - CHINA - - 00-16-99 (hex) Tonic DVB Marketing Ltd - 001699 (base 16) Tonic DVB Marketing Ltd - Unit B, 10/F, Summit Building, - 30 Man Yue Street, - Hung Hom Kowloon - HONG KONG - - 00-16-9A (hex) Quadrics Ltd - 00169A (base 16) Quadrics Ltd - 1 Bridewell Street - Bristol BS1 2AA - UNITED KINGDOM - - 00-16-9B (hex) Alstom Transport - 00169B (base 16) Alstom Transport - 11, 13 avenue de Bel Air - Villeurbanne Rhone 69100 - FRANCE - - 00-16-9C (hex) CISCO SYSTEMS, INC. - 00169C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-16-9D (hex) CISCO SYSTEMS, INC. - 00169D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-16-9E (hex) TV One Ltd - 00169E (base 16) TV One Ltd - Unit V Continental Approach - Westwood Industrial Estate - Margate Kent CT9 4JG - UNITED KINGDOM - - 00-16-9F (hex) Vimtron Electronics Co., Ltd. - 00169F (base 16) Vimtron Electronics Co., Ltd. - 7F., No.9, Alley 2, Lane 35 - Jihu Rd. - Neihu District Taipei City 11492 - TAIWAN, PROVINCE OF CHINA - - 00-16-A0 (hex) Auto-Maskin - 0016A0 (base 16) Auto-Maskin - Sophie Radichs Vei 7 - LILLESTROM Akershus 2003 - NORWAY - - 00-16-A1 (hex) 3Leaf Networks - 0016A1 (base 16) 3Leaf Networks - 3255-1 Scott Blvd - Santa Clara CA 95054 - UNITED STATES - - 00-16-A2 (hex) CentraLite Systems, Inc. - 0016A2 (base 16) CentraLite Systems, Inc. - 6420 Wall Street - Mobile AL 36695 - UNITED STATES - - 00-16-A3 (hex) Ingeteam Transmission&Distribution, S.A. - 0016A3 (base 16) Ingeteam Transmission&Distribution, S.A. - C/ Usausuaga, 7 - Pol. Artunduaga - Basauri Bizkaia 48970 - SPAIN - - 00-16-A4 (hex) Ezurio Ltd - 0016A4 (base 16) Ezurio Ltd - Unit 2 - 126 Colindale Avenue - London NW9 5HD - UNITED KINGDOM - - 00-16-A5 (hex) Tandberg Storage ASA - 0016A5 (base 16) Tandberg Storage ASA - Postboks 191 - 1325 Lysaker - NORWAY - - 00-16-A6 (hex) Dovado FZ-LLC - 0016A6 (base 16) Dovado FZ-LLC - Al-Thuraya Tower 1, office 504 - P.O. Box 500422 - Dubai - UNITED ARAB EMIRATES - - 00-16-A7 (hex) AWETA G&P - 0016A7 (base 16) AWETA G&P - Burg. Winkellaan 3 - Nootdorp 2631 HG - NETHERLANDS - - 00-16-A8 (hex) CWT CO., LTD. - 0016A8 (base 16) CWT CO., LTD. - 10F No. 74 Sec. 1 Chung-Hua Rd. - Taipei 108 - TAIWAN, PROVINCE OF CHINA - - 00-16-A9 (hex) 2EI - 0016A9 (base 16) 2EI - Rua dos Rubis, 77 - Assumpcao - Aguas de Lindoia São Paulo 13940-000 - BRAZIL - - 00-16-AA (hex) Kei Communication Technology Inc. - 0016AA (base 16) Kei Communication Technology Inc. - 8-BAN CHUOU - KOBE HYOGO 650-0024 - JAPAN - - 00-16-AB (hex) Dansensor A/S - 0016AB (base 16) Dansensor A/S - Roennedevej 18 - Ringsted DK-4100 - DENMARK - - 00-16-AC (hex) Toho Technology Corp. - 0016AC (base 16) Toho Technology Corp. - HIGASHI 5-1 - ORIZUSHIMOMACHI - INAZAWA-CITY AICHI 492-8501 - JAPAN - - 00-16-AD (hex) BT-Links Company Limited - 0016AD (base 16) BT-Links Company Limited - Rm 802, Nan Fung Centre, 264-298 Castle Peak Rd - Tsuen Wan - HONG KONG - - 00-16-AE (hex) INVENTEL - 0016AE (base 16) INVENTEL - 35 rue Tournefort - PARIS 75005 - FRANCE - - 00-16-AF (hex) Shenzhen Union Networks Equipment Co.,Ltd. - 0016AF (base 16) Shenzhen Union Networks Equipment Co.,Ltd. - Yihai Square east building 2307, Chuangye road, Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-16-B0 (hex) VK Corporation - 0016B0 (base 16) VK Corporation - VK B/D, 548-6, Anyang 8dong, Manan-gu - Anyang Kyounggi 430-8903 - KOREA, REPUBLIC OF - - 00-16-B1 (hex) KBS - 0016B1 (base 16) KBS - 88 rue Pierre Sémard - BP 55 - Moissy cedex Ile de France 77552 - FRANCE - - 00-16-B2 (hex) DriveCam Inc - 0016B2 (base 16) DriveCam Inc - 3954 Murphy Canyon Road - Suite D205 - San Diego CA 92123 - UNITED STATES - - 00-16-B3 (hex) Photonicbridges (China) Co., Ltd. - 0016B3 (base 16) Photonicbridges (China) Co., Ltd. - No. 900, Yishan road, - Shanghai 200233 - CHINA - - 00-16-B4 (hex) PRIVATE - 0016B4 (base 16) - - 00-16-B5 (hex) ARRIS Group, Inc. - 0016B5 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-16-B6 (hex) Cisco-Linksys - 0016B6 (base 16) Cisco-Linksys - 121 Theory - Irvine CA 92612 - UNITED STATES - - 00-16-B7 (hex) Seoul Commtech - 0016B7 (base 16) Seoul Commtech - 448-11, Seongnae 3dong. Gangdong gu, - Seoul 134033 - KOREA, REPUBLIC OF - - 00-16-B8 (hex) Sony Ericsson Mobile Communications - 0016B8 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-16-B9 (hex) ProCurve Networking - 0016B9 (base 16) ProCurve Networking - 8000 Foothills Blvd - MS 5662 - Roseville CA 95747 - UNITED STATES - - 00-16-BA (hex) WEATHERNEWS INC. - 0016BA (base 16) WEATHERNEWS INC. - NAKASE 1-3 MTG - CHIBA 262-0032 - JAPAN - - 00-16-BB (hex) Law-Chain Computer Technology Co Ltd - 0016BB (base 16) Law-Chain Computer Technology Co Ltd - 7F-2, 286-4, hsin ya road, chien chen district - Kaohsiung 80673 - TAIWAN, PROVINCE OF CHINA - - 00-16-BC (hex) Nokia Danmark A/S - 0016BC (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-16-BD (hex) ATI Industrial Automation - 0016BD (base 16) ATI Industrial Automation - 1031 Goodworth Drive - Apex North Carolina 27539-3869 - UNITED STATES - - 00-16-BE (hex) INFRANET, Inc. - 0016BE (base 16) INFRANET, Inc. - 8th Floor, Cowell B/D, 66-1 - Banpo-Dong, Seocho-Gu - Seoul 137-040 - KOREA, REPUBLIC OF - - 00-16-BF (hex) PaloDEx Group Oy - 0016BF (base 16) PaloDEx Group Oy - P.O. Box 64 - Nahkelantie 160 - Tuusula 04301 - FINLAND - - 00-16-C0 (hex) Semtech Corporation - 0016C0 (base 16) Semtech Corporation - 200 Flynn Rd - Camarillo California 93012 - UNITED STATES - - 00-16-C1 (hex) Eleksen Ltd - 0016C1 (base 16) Eleksen Ltd - Pinewood Studios - Iver Heath - Iver Bucks SL0 0NH - UNITED KINGDOM - - 00-16-C2 (hex) Avtec Systems Inc - 0016C2 (base 16) Avtec Systems Inc - 14432 Albemarle Point Place - Chantilly Virginia 20151 - UNITED STATES - - 00-16-C3 (hex) BA Systems Inc - 0016C3 (base 16) BA Systems Inc - 6895 Via Del Oro - San Jose CA 95119 - UNITED STATES - - 00-16-C4 (hex) SiRF Technology, Inc. - 0016C4 (base 16) SiRF Technology, Inc. - 217 Devcon Dr. - San Jose CA 95112 - UNITED STATES - - 00-16-C5 (hex) Shenzhen Xing Feng Industry Co.,Ltd - 0016C5 (base 16) Shenzhen Xing Feng Industry Co.,Ltd - Floor 1 - 4, Block 25, Hongtian Jinyuan Industrial, - Hongtian Road Huangpu, Shajin, Baoan, - Shenzhen GuangDong 86 - CHINA - - 00-16-C6 (hex) North Atlantic Industries - 0016C6 (base 16) North Atlantic Industries - 170 Wilbur Place - Bohemia NY 11716 - UNITED STATES - - 00-16-C7 (hex) CISCO SYSTEMS, INC. - 0016C7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-16-C8 (hex) CISCO SYSTEMS, INC. - 0016C8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-16-C9 (hex) NAT Seattle, Inc. - 0016C9 (base 16) NAT Seattle, Inc. - 22125 17th Ave SE - Bothell WA 98021 - UNITED STATES - - 00-16-CA (hex) Nortel - 0016CA (base 16) Nortel - 8200 Dixie Road, Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-16-CB (hex) Apple - 0016CB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-16-CC (hex) Xcute Mobile Corp. - 0016CC (base 16) Xcute Mobile Corp. - 3F. No.25, Ally15, Lane 120, Sec.1, Neihu Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-16-CD (hex) HIJI HIGH-TECH CO., LTD. - 0016CD (base 16) HIJI HIGH-TECH CO., LTD. - Ohga 8133 - Hiji - Hayami Oita 879-1504 - JAPAN - - 00-16-CE (hex) Hon Hai Precision Ind. Co., Ltd. - 0016CE (base 16) Hon Hai Precision Ind. Co., Ltd. - 66, Chung Shan Rd. Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-16-CF (hex) Hon Hai Precision Ind. Co., Ltd. - 0016CF (base 16) Hon Hai Precision Ind. Co., Ltd. - 66, Chung Shan Rd. Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-16-D0 (hex) ATech elektronika d.o.o. - 0016D0 (base 16) ATech elektronika d.o.o. - Bac pri Materiji 30 - Materija SI 6242 - SLOVENIA - - 00-16-D1 (hex) ZAT a.s. - 0016D1 (base 16) ZAT a.s. - K Podlesi 541 - Pribram VI 26180 - CZECH REPUBLIC - - 00-16-D2 (hex) Caspian - 0016D2 (base 16) Caspian - 170 Baytech Drive - San Jose CA 95134 - UNITED STATES - - 00-16-D3 (hex) Wistron Corporation - 0016D3 (base 16) Wistron Corporation - 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-16-D4 (hex) Compal Communications, Inc. - 0016D4 (base 16) Compal Communications, Inc. - 7th, FL, No. 319, Sec. 4, Pa-Teh rd. - Taipei 886 - TAIWAN, PROVINCE OF CHINA - - 00-16-D5 (hex) Synccom Co., Ltd - 0016D5 (base 16) Synccom Co., Ltd - #306 Myungi e-space 218-20 - Anyang7-dong Manan-gu - Anyang-si Kyungki-do 430-817 - KOREA, REPUBLIC OF - - 00-16-D6 (hex) TDA Tech Pty Ltd - 0016D6 (base 16) TDA Tech Pty Ltd - 210 / 54 Currie Street - Adelaide South Australia 5000 - AUSTRALIA - - 00-16-D7 (hex) Sunways AG - 0016D7 (base 16) Sunways AG - Macairestraße 3-5 - Konstanz Baden-Württemberg 78467 - GERMANY - - 00-16-D8 (hex) Senea AB - 0016D8 (base 16) Senea AB - Företagsallen 12 - Ã…kersberga 18484 - SWEDEN - - 00-16-D9 (hex) NINGBO BIRD CO.,LTD. - 0016D9 (base 16) NINGBO BIRD CO.,LTD. - No.999 Dacheng East Road - Fenghua Zhejiang 315500 - CHINA - - 00-16-DA (hex) Futronic Technology Co. Ltd. - 0016DA (base 16) Futronic Technology Co. Ltd. - Room 1016A, 10/F., Profit Ind. Bldg., - 1-15 Kwai Fung Crescent, - Kwai Chung 00000 - HONG KONG - - 00-16-DB (hex) Samsung Electronics Co., Ltd. - 0016DB (base 16) Samsung Electronics Co., Ltd. - #94-1, Imsoo-Dong - Gumi-City Gyeong-Buk 730-350 - KOREA, REPUBLIC OF - - 00-16-DC (hex) ARCHOS - 0016DC (base 16) ARCHOS - 12 rue AMPERE - IGNY ESSONNES 91430 - FRANCE - - 00-16-DD (hex) Gigabeam Corporation - 0016DD (base 16) Gigabeam Corporation - 407 Springpark Place - Ste 900 - Herndon VA 20170 - UNITED STATES - - 00-16-DE (hex) FAST Inc - 0016DE (base 16) FAST Inc - 905 Honeyspot Rd - Stratford CT 06615 - UNITED STATES - - 00-16-DF (hex) Lundinova AB - 0016DF (base 16) Lundinova AB - Dalbyvägen 1 - Lund SkÃ¥ne SE-224 60 - SWEDEN - - 00-16-E0 (hex) 3Com Ltd - 0016E0 (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-16-E1 (hex) SiliconStor, Inc. - 0016E1 (base 16) SiliconStor, Inc. - 48430 Lakeview Blvd. - Fremont CA 94538 - UNITED STATES - - 00-16-E2 (hex) American Fibertek, Inc. - 0016E2 (base 16) American Fibertek, Inc. - 120 Belmont Drive - Somerset New Jersey 08873-1204 - UNITED STATES - - 00-16-E3 (hex) ASKEY COMPUTER CORP. - 0016E3 (base 16) ASKEY COMPUTER CORP. - 10F, NO.119, CHIENKANG RD., - CHUNG-HO, TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - 00-16-E4 (hex) VANGUARD SECURITY ENGINEERING CORP. - 0016E4 (base 16) VANGUARD SECURITY ENGINEERING CORP. - 3, LANE 32, KSO CHING RD. - YANGMEI TAOYUAN 326 - TAIWAN, PROVINCE OF CHINA - - 00-16-E5 (hex) FORDLEY DEVELOPMENT LIMITED - 0016E5 (base 16) FORDLEY DEVELOPMENT LIMITED - ROOM 706, 7TH FLOOR, YU SUNG BOON BUILDING, 107-111 DES VOEUX ROAD, CENTRAL, - HONG KONG - - 00-16-E6 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 0016E6 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - Pin-Jen City, Taoyuan - 324 - TAIWAN, PROVINCE OF CHINA - - 00-16-E7 (hex) Dynamix Promotions Limited - 0016E7 (base 16) Dynamix Promotions Limited - 788-790, Finchley Road - London NW11 7TJ - UNITED KINGDOM - - 00-16-E8 (hex) Sigma Designs, Inc. - 0016E8 (base 16) Sigma Designs, Inc. - 1778 McCarthy Blvd. - Milpitas CA 95035 - UNITED STATES - - 00-16-E9 (hex) Tiba Medical Inc - 0016E9 (base 16) Tiba Medical Inc - 5024 Lakewood Drive - Plano TX 75093 - UNITED STATES - - 00-16-EA (hex) Intel Corporate - 0016EA (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-16-EB (hex) Intel Corporate - 0016EB (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-16-EC (hex) Elitegroup Computer Systems Co., Ltd. - 0016EC (base 16) Elitegroup Computer Systems Co., Ltd. - No. 22, Alley 38, Lane 91, Sec. 1, Nei Hu Road, - Taipei 11441 - TAIWAN, PROVINCE OF CHINA - - 00-16-ED (hex) Digital Safety Technologies, Inc - 0016ED (base 16) Digital Safety Technologies, Inc - 511 Davis Drive - Suite 300 - Morrisville NC 27560 - UNITED STATES - - 00-16-EE (hex) RoyalDigital Inc. - 0016EE (base 16) RoyalDigital Inc. - 8F., No.308, Sec.1, Neihu Rd. - Neihu District, - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-16-EF (hex) Koko Fitness, Inc. - 0016EF (base 16) Koko Fitness, Inc. - 136 Longwater Drive - Norwell MA 02061 - UNITED STATES - - 00-16-F0 (hex) Dell - 0016F0 (base 16) Dell - 909 Hermosa Ct - Sunnyvale CA 94085 - UNITED STATES - - 00-16-F1 (hex) OmniSense, LLC - 0016F1 (base 16) OmniSense, LLC - 72 sams point road - Ladys Island SC 29907 - UNITED STATES - - 00-16-F2 (hex) Dmobile System Co., Ltd. - 0016F2 (base 16) Dmobile System Co., Ltd. - 2F, No.13-20, Sec.6, Mincyuan E.Rd, - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-16-F3 (hex) CAST Information Co., Ltd - 0016F3 (base 16) CAST Information Co., Ltd - 5F MSA Bldg. 891-43 Dacchi-Dong, - gangnam-Gu - SEOUL 135-280 - KOREA, REPUBLIC OF - - 00-16-F4 (hex) Eidicom Co., Ltd. - 0016F4 (base 16) Eidicom Co., Ltd. - Polychem B/D 4th Floor, 900-1 - Kwanyang-dong, Dongan-ku - Anyang-si Kyeonggi-do 431-060 - KOREA, REPUBLIC OF - - 00-16-F5 (hex) Dalian Golden Hualu Digital Technology Co.,Ltd - 0016F5 (base 16) Dalian Golden Hualu Digital Technology Co.,Ltd - No.1 Hua Road,Qixianling - Dalian LiaoNing 116023 - CHINA - - 00-16-F6 (hex) Video Products Group - 0016F6 (base 16) Video Products Group - 1600 Emerson Avenue - Oxnard California 93033 - UNITED STATES - - 00-16-F7 (hex) L-3 Communications, Aviation Recorders - 0016F7 (base 16) L-3 Communications, Aviation Recorders - 100 Cattlemen Rd. - Sarasota FL 34232 - UNITED STATES - - 00-16-F8 (hex) AVIQTECH TECHNOLOGY CO., LTD. - 0016F8 (base 16) AVIQTECH TECHNOLOGY CO., LTD. - 6F 12, Li-hsin Road, SBIP - Hsin-chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-16-F9 (hex) CETRTA POT, d.o.o., Kranj - 0016F9 (base 16) CETRTA POT, d.o.o., Kranj - Planina 3 - Kranj SI 4000 - SLOVENIA - - 00-16-FA (hex) ECI Telecom Ltd. - 0016FA (base 16) ECI Telecom Ltd. - 30 Hasivim St. - Petah Tikva 49133 - ISRAEL - - 00-16-FB (hex) SHENZHEN MTC CO.,LTD. - 0016FB (base 16) SHENZHEN MTC CO.,LTD. - 5/F BenYuan Bldg,6015 ShenNan Road - ShenZhen GuangDong 518040 - CHINA - - 00-16-FC (hex) TOHKEN CO.,LTD. - 0016FC (base 16) TOHKEN CO.,LTD. - 2-16-20 Tamagawa - Chofu Tokyo 182-0025 - JAPAN - - 00-16-FD (hex) Jaty Electronics - 0016FD (base 16) Jaty Electronics - Jaty Bldg 10F, 1659-5 Bongchun11-Dong - Kwanak-Ku - Seoul 151-832 - KOREA, REPUBLIC OF - - 00-16-FE (hex) Alps Electric Co., Ltd - 0016FE (base 16) Alps Electric Co., Ltd - 1-2-1, Okinouchi, - Soma-city, Fukushima-pref., 976-8501 - JAPAN - - 00-16-FF (hex) Wamin Optocomm Mfg Corp - 0016FF (base 16) Wamin Optocomm Mfg Corp - No. 239 Qiaohe Road - Zhonghe City Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-17-00 (hex) ARRIS Group, Inc. - 001700 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-17-01 (hex) KDE, Inc. - 001701 (base 16) KDE, Inc. - KDE TOWN, 42-7, Mangwol-dong - Hanam Gyeonggi-do 465-150 - KOREA, REPUBLIC OF - - 00-17-02 (hex) Osung Midicom Co., Ltd - 001702 (base 16) Osung Midicom Co., Ltd - 231-18, Dorim2-dong, - Seoul, Youngdeungpo-gu 150-832 - KOREA, REPUBLIC OF - - 00-17-03 (hex) MOSDAN Internation Co.,Ltd - 001703 (base 16) MOSDAN Internation Co.,Ltd - No.216 Xiwei,Shanhua Dist, - Tainan 741 - TAIWAN, PROVINCE OF CHINA - - 00-17-04 (hex) Shinco Electronics Group Co.,Ltd - 001704 (base 16) Shinco Electronics Group Co.,Ltd - No.5 Waihuan Road - Changzhou Jiangsu 213022 - CHINA - - 00-17-05 (hex) Methode Electronics - 001705 (base 16) Methode Electronics - 7401 W. Wilson - Chicago IL 60706 - UNITED STATES - - 00-17-06 (hex) Techfaith Wireless Communication Technology Limited. - 001706 (base 16) Techfaith Wireless Communication Technology Limited. - 2/F M8 West No.1 Jiu Xian Qiao Dong Road, - Chao Yang District - Beijing 100016 - CHINA - - 00-17-07 (hex) InGrid, Inc - 001707 (base 16) InGrid, Inc - 920 Cassatt Rd - Suite 220 - Berwyn Pa 19312 - UNITED STATES - - 00-17-08 (hex) Hewlett-Packard Company - 001708 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - Houston TX 77070 - UNITED STATES - - 00-17-09 (hex) Exalt Communications - 001709 (base 16) Exalt Communications - 580 Division Street - Campbell CA 95008 - UNITED STATES - - 00-17-0A (hex) INEW DIGITAL COMPANY - 00170A (base 16) INEW DIGITAL COMPANY - Supply Bureau 3th floor KT&G 203-1, - Pyong chon-dong, Daedeog - Daejeon 306-712 - KOREA, REPUBLIC OF - - 00-17-0B (hex) Contela, Inc. - 00170B (base 16) Contela, Inc. - 6-8 Soonae-dong, Bundang-gu, - 5th Floor, Korea First Bldg., - Sungnam Kyunggi-do 463-825 - KOREA, REPUBLIC OF - - 00-17-0C (hex) Twig Com Ltd. - 00170C (base 16) Twig Com Ltd. - Meriniitynkatu 11 - Salo 2400 - FINLAND - - 00-17-0D (hex) Dust Networks Inc. - 00170D (base 16) Dust Networks Inc. - 30695 Huntwood Ave. - Hayward Ca. 94544 - UNITED STATES - - 00-17-0E (hex) CISCO SYSTEMS, INC. - 00170E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-0F (hex) CISCO SYSTEMS, INC. - 00170F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-10 (hex) Casa Systems Inc. - 001710 (base 16) Casa Systems Inc. - 10, New England Business Center Dr. - Suite 110 - Andover MA 01810 - UNITED STATES - - 00-17-11 (hex) GE Healthcare Bio-Sciences AB - 001711 (base 16) GE Healthcare Bio-Sciences AB - Björkgatan 30 - Uppsala SE 75184 - SWEDEN - - 00-17-12 (hex) ISCO International - 001712 (base 16) ISCO International - 1001 Cambridge Drive - Elk Grove Village IL 60007 - UNITED STATES - - 00-17-13 (hex) Tiger NetCom - 001713 (base 16) Tiger NetCom - J-15 Mudan Cun, Yijing Huayuan, - Aiguo Road, Luohu District, - Shenzhen Guangdong 518003 - CHINA - - 00-17-14 (hex) BR Controls Nederland bv - 001714 (base 16) BR Controls Nederland bv - Branderweg 1 - Zwolle Overijssel 8042 PD - NETHERLANDS - - 00-17-15 (hex) Qstik - 001715 (base 16) Qstik - Cartel Business Estate - Edinburgh Way - Harlow Essex CM20 2TT - UNITED KINGDOM - - 00-17-16 (hex) Qno Technology Inc. - 001716 (base 16) Qno Technology Inc. - 6F-2, No.25, Puding Road - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-17-17 (hex) Leica Geosystems AG - 001717 (base 16) Leica Geosystems AG - Heinrich Wild Strasse - Heerbrugg St. Gallen CH-9435 - SWITZERLAND - - 00-17-18 (hex) Vansco Electronics Oy - 001718 (base 16) Vansco Electronics Oy - Tiilenlyojankatu 5 - FORSSA 30101 - FINLAND - - 00-17-19 (hex) AudioCodes USA, Inc - 001719 (base 16) AudioCodes USA, Inc - 27 World's Fair Drive - Somerset NJ 08873 - UNITED STATES - - 00-17-1A (hex) Winegard Company - 00171A (base 16) Winegard Company - 3000 Kirkwood Street - Burlington IA 52601 - UNITED STATES - - 00-17-1B (hex) Innovation Lab Corp. - 00171B (base 16) Innovation Lab Corp. - 12FL., No. 285, Sec. 2, TiDing Blvd., - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 00-17-1C (hex) NT MicroSystems, Inc. - 00171C (base 16) NT MicroSystems, Inc. - 1-5-3-2F Tamagawadai - Setagaya Tokyo 158-0096 - JAPAN - - 00-17-1D (hex) DIGIT - 00171D (base 16) DIGIT - Via Pasteur , 1/3 - S.Pietro Mosezzo NOVARA 28060 - ITALY - - 00-17-1E (hex) Theo Benning GmbH & Co. KG - 00171E (base 16) Theo Benning GmbH & Co. KG - Muensterstraße 135-137 - Bocholt NRW 46397 - GERMANY - - 00-17-1F (hex) IMV Corporation - 00171F (base 16) IMV Corporation - 2-6-10 Takejima - Nishiyodogawa-ku - Osaka 555-0011 - JAPAN - - 00-17-20 (hex) Image Sensing Systems, Inc. - 001720 (base 16) Image Sensing Systems, Inc. - 1600 University Ave. W. - Suite 500 - St. Paul MN 55104 - UNITED STATES - - 00-17-21 (hex) FITRE S.p.A. - 001721 (base 16) FITRE S.p.A. - Via Valsolda, 15 - MILANO MI 20142 - ITALY - - 00-17-22 (hex) Hanazeder Electronic GmbH - 001722 (base 16) Hanazeder Electronic GmbH - J.M. Dimmelstr 10 - Ried i. I. Oberösterreich 4910 - AUSTRIA - - 00-17-23 (hex) Summit Data Communications - 001723 (base 16) Summit Data Communications - 526 South Main Street - Suite 805 - Akron Ohio 44311 - UNITED STATES - - 00-17-24 (hex) Studer Professional Audio GmbH - 001724 (base 16) Studer Professional Audio GmbH - Althardstrasse 30 - Regensdorf Zürich CH-8105 - SWITZERLAND - - 00-17-25 (hex) Liquid Computing - 001725 (base 16) Liquid Computing - 340 Terry Fox Drive - Suite 300 - Ottawa Ontario K2K 3A2 - CANADA - - 00-17-26 (hex) m2c Electronic Technology Ltd. - 001726 (base 16) m2c Electronic Technology Ltd. - 2403, 24/F, Nanyang Plaza - 57 Hung To Road - Kwuntong Hong Kong 999 999 - CHINA - - 00-17-27 (hex) Thermo Ramsey Italia s.r.l. - 001727 (base 16) Thermo Ramsey Italia s.r.l. - Strada Rivoltana km 6/7 - Rodano Milano 20090 - ITALY - - 00-17-28 (hex) Selex Communications - 001728 (base 16) Selex Communications - Via Pieragostini 80 - Genova 16151 - ITALY - - 00-17-29 (hex) Ubicod Co.LTD - 001729 (base 16) Ubicod Co.LTD - 7F Chun-gin Bldg, 53-5 Wonhyo-ro - Yongsan-gu - Seoul 140-719 - KOREA, REPUBLIC OF - - 00-17-2A (hex) Proware Technology Corp.(By Unifosa) - 00172A (base 16) Proware Technology Corp.(By Unifosa) - 6Fl., No. 4, Alley 1, Lane 235, PaoChao Rd., Sindian Dist., - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 00-17-2B (hex) Global Technologies Inc. - 00172B (base 16) Global Technologies Inc. - 4/F Kicox Bldg.,188-5,Guro-Dong,Guro-gu, - Seoul 152-848 - KOREA, REPUBLIC OF - - 00-17-2C (hex) TAEJIN INFOTECH - 00172C (base 16) TAEJIN INFOTECH - 6F Woolim e-Biz Center, 170-5 - Guro-Dong, Guro-Gu, - Seoul 152-769 - KOREA, REPUBLIC OF - - 00-17-2D (hex) Axcen Photonics Corporation - 00172D (base 16) Axcen Photonics Corporation - 6F, No. 119, Baujung Rd., - Shindian City, Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-17-2E (hex) FXC Inc. - 00172E (base 16) FXC Inc. - 10-16 6F, Nihonbashi Tomizawa-Chou, Chuo-ku - Tokyo 103-0006 - JAPAN - - 00-17-2F (hex) NeuLion Incorporated - 00172F (base 16) NeuLion Incorporated - 1600 Old Country Road - Plainview NY 11803 - UNITED STATES - - 00-17-30 (hex) Automation Electronics - 001730 (base 16) Automation Electronics - 111 Big Horn Rd. - Casper Wy 82601 - UNITED STATES - - 00-17-31 (hex) ASUSTek COMPUTER INC. - 001731 (base 16) ASUSTek COMPUTER INC. - No.5 Shing Yeh Street,Kwei Shan Hsiang,Taoyuan - Taipei 333 - TAIWAN, PROVINCE OF CHINA - - 00-17-32 (hex) Science-Technical Center "RISSA" - 001732 (base 16) Science-Technical Center "RISSA" - st. Abramtsevskaja, h.9 - Moscow 128572 - RUSSIAN FEDERATION - - 00-17-33 (hex) SFR - 001733 (base 16) SFR - 42 Quai du point du jour - Boulogne Billancourt Hauts de Seine 92659 - FRANCE - - 00-17-34 (hex) ADC Telecommunications - 001734 (base 16) ADC Telecommunications - 541 E Trimble Road - San Jose California 95134-1224 - UNITED STATES - - 00-17-35 (hex) PRIVATE - 001735 (base 16) - - 00-17-36 (hex) iiTron Inc. - 001736 (base 16) iiTron Inc. - 88 Mercy St. - Mountain View CA 94041 - UNITED STATES - - 00-17-37 (hex) Industrie Dial Face S.p.A. - 001737 (base 16) Industrie Dial Face S.p.A. - via Canzo, 4 - Peschiera Borromeo Milano 20068 - ITALY - - 00-17-38 (hex) International Business Machines - 001738 (base 16) International Business Machines - 1 Azrieli Center - Tel Aviv 67021 - ISRAEL - - 00-17-39 (hex) Bright Headphone Electronics Company - 001739 (base 16) Bright Headphone Electronics Company - 8F, 109, Li De Street - Chung Ho City Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-17-3A (hex) Reach Systems Inc. - 00173A (base 16) Reach Systems Inc. - 1330 Broadway - Suite 1201 - Oakland CA 94612 - UNITED STATES - - 00-17-3B (hex) Cisco Systems, Inc. - 00173B (base 16) Cisco Systems, Inc. - 170 West Tasman Dr. - San Jose CA 95134-1706 - UNITED STATES - - 00-17-3C (hex) Extreme Engineering Solutions - 00173C (base 16) Extreme Engineering Solutions - 3225 Deming Way - Suite 120 - Middleton WI 53562 - UNITED STATES - - 00-17-3D (hex) Neology - 00173D (base 16) Neology - 13000 Gregg Street Suite A - Poway CA 92064 - UNITED STATES - - 00-17-3E (hex) LeucotronEquipamentos Ltda. - 00173E (base 16) LeucotronEquipamentos Ltda. - Rua Jorge Dionisio Barbosa, 312 - Santa Rita do Sapucai Minas Gerais 37.540-000 - BRAZIL - - 00-17-3F (hex) Belkin Corporation - 00173F (base 16) Belkin Corporation - 501 W. Walnut Street - Compton CA 90220-5221 - UNITED STATES - - 00-17-40 (hex) Bluberi Gaming Technologies Inc - 001740 (base 16) Bluberi Gaming Technologies Inc - 2125, rue Letendre Suite 420 - Drummondville Quebec J2C 7G1 - CANADA - - 00-17-41 (hex) DEFIDEV - 001741 (base 16) DEFIDEV - 20 rue Raymond Marcheron - Vanves 92170 - FRANCE - - 00-17-42 (hex) FUJITSU LIMITED - 001742 (base 16) FUJITSU LIMITED - Musashi-kosugi Tower Place Bldg.,403 - Kosugi-cho 1-chome,Nakahara-ku - Kawasaki Kanagawa 211-8588 - JAPAN - - 00-17-43 (hex) Deck Srl - 001743 (base 16) Deck Srl - Via Fabio Filzi 2 - Milan 20124 - ITALY - - 00-17-44 (hex) Araneo Ltd. - 001744 (base 16) Araneo Ltd. - 103 Medinat Hayehudim - Herzliya 46733 - ISRAEL - - 00-17-45 (hex) INNOTZ CO., Ltd - 001745 (base 16) INNOTZ CO., Ltd - 14F, Prime Center 546-4 Guui-Dong Kwanggin-Gu - Seoul Seoul 143-200 - KOREA, REPUBLIC OF - - 00-17-46 (hex) Freedom9 Inc. - 001746 (base 16) Freedom9 Inc. - 4140B SLADEVIEW CRE., - UNIT 4, - MISSISSAUGA, Ontario L5L6A1 - CANADA - - 00-17-47 (hex) Trimble - 001747 (base 16) Trimble - 345 SW Avery Ave - Corvallis OR 97333 - UNITED STATES - - 00-17-48 (hex) Neokoros Brasil Ltda - 001748 (base 16) Neokoros Brasil Ltda - Rua 86, numero 501, Setor Sul - Goiania Goias 74083-330 - BRAZIL - - 00-17-49 (hex) HYUNDAE YONG-O-SA CO.,LTD - 001749 (base 16) HYUNDAE YONG-O-SA CO.,LTD - 448-10, Hyuckjae B/D Seongnae, Kangdong-gu - Seoul 134-847 - KOREA, REPUBLIC OF - - 00-17-4A (hex) SOCOMEC - 00174A (base 16) SOCOMEC - rue de Westhouse - BENFELD CEDEX 67235 - FRANCE - - 00-17-4B (hex) Nokia Danmark A/S - 00174B (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-17-4C (hex) Millipore - 00174C (base 16) Millipore - 1, rue Jacques Monod - Rond-point des Sangliers - Guyancourt 78280 - FRANCE - - 00-17-4D (hex) DYNAMIC NETWORK FACTORY, INC. - 00174D (base 16) DYNAMIC NETWORK FACTORY, INC. - 26250 EDEN LANDING RD. - HAYWARD CA 94545 - UNITED STATES - - 00-17-4E (hex) Parama-tech Co.,Ltd. - 00174E (base 16) Parama-tech Co.,Ltd. - 2-19-8, Sharyo, Higashi-ku - Fukuoka 812-0068 - JAPAN - - 00-17-4F (hex) iCatch Inc. - 00174F (base 16) iCatch Inc. - 10F-2, No. 109, Sec. 6, Mincyuan E. Rd., - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-17-50 (hex) GSI Group, MicroE Systems - 001750 (base 16) GSI Group, MicroE Systems - 8 Erie Drive - Natick MA 01760 - UNITED STATES - - 00-17-51 (hex) Online Corporation - 001751 (base 16) Online Corporation - 22F-3, No. 398, Huan Pei Road, - Chung Li Taoyuan 320 - TAIWAN, PROVINCE OF CHINA - - 00-17-52 (hex) DAGS, Inc - 001752 (base 16) DAGS, Inc - C-510, Woolim Lion's Valley, 371-28, Gasan Dong, Geumcheon Ku - Seoul 153-786 - KOREA, REPUBLIC OF - - 00-17-53 (hex) nFore Technology Inc. - 001753 (base 16) nFore Technology Inc. - 10F, 41 Dong Xing Rd, - Taipei Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-17-54 (hex) Arkino HiTOP Corporation Limited - 001754 (base 16) Arkino HiTOP Corporation Limited - 5F., No.437, Tao Ying Rd - Taoyuan City Taoyuan County 33068, - TAIWAN, PROVINCE OF CHINA - - 00-17-55 (hex) GE Security - 001755 (base 16) GE Security - 12345 SW Leveton Drive - Tualatin OR 97062 - UNITED STATES - - 00-17-56 (hex) Vinci Labs Oy - 001756 (base 16) Vinci Labs Oy - Finlaysoninkuja 21 A - Tampere Länsi-Suomi 33210 - FINLAND - - 00-17-57 (hex) RIX TECHNOLOGY LIMITED - 001757 (base 16) RIX TECHNOLOGY LIMITED - 17 DAI WANG STREET - TAI PO INDUSTRIAL ESTATE - TAI PO NEW TERRITORIES - HONG KONG - - 00-17-58 (hex) ThruVision Ltd - 001758 (base 16) ThruVision Ltd - Central 127, No.18 - Milton Park - Abingdon Oxfordshire OX14 4SA - UNITED KINGDOM - - 00-17-59 (hex) CISCO SYSTEMS, INC. - 001759 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-5A (hex) CISCO SYSTEMS, INC. - 00175A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-5B (hex) ACS Solutions Switzerland Ltd. - 00175B (base 16) ACS Solutions Switzerland Ltd. - Frankenstrasse 70 - Bern- Buempliz 3018 - SWITZERLAND - - 00-17-5C (hex) SHARP CORPORATION - 00175C (base 16) SHARP CORPORATION - 1, Takumi-Cho, - Sakai-KU - Sakai city Osaka Prefecture 590-8522 - JAPAN - - 00-17-5D (hex) Dongseo system. - 00175D (base 16) Dongseo system. - 974-21 Mansu-dong Namdong-gu - Incheon In-Cheon 405-865 - KOREA, REPUBLIC OF - - 00-17-5E (hex) Zed-3 - 00175E (base 16) Zed-3 - 501 Valley Way - Milpitas CA 95035 - UNITED STATES - - 00-17-5F (hex) XENOLINK Communications Co., Ltd. - 00175F (base 16) XENOLINK Communications Co., Ltd. - 2nd Fl., Jungyou B/D 797-22 - Yeoksam-dong Gangnam-gu - Seoul 135-930 - KOREA, REPUBLIC OF - - 00-17-60 (hex) Naito Densei Machida MFG.CO.,LTD - 001760 (base 16) Naito Densei Machida MFG.CO.,LTD - 2-17-28 Fuchinobe - Sagamihara Kanagawa 229-0006 - JAPAN - - 00-17-61 (hex) PRIVATE - 001761 (base 16) - - 00-17-62 (hex) Solar Technology, Inc. - 001762 (base 16) Solar Technology, Inc. - 7620 Cetronia Road - Allentown PA 18106 - UNITED STATES - - 00-17-63 (hex) Essentia S.p.A. - 001763 (base 16) Essentia S.p.A. - Via G.B. Vico, 29 - Cella (RE) Reggio Emilia 42040 - ITALY - - 00-17-64 (hex) ATMedia GmbH - 001764 (base 16) ATMedia GmbH - Stuhlsatzenhausweg 69 - Saarbruecken Saarland 66123 - GERMANY - - 00-17-65 (hex) Nortel - 001765 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-17-66 (hex) Accense Technology, Inc. - 001766 (base 16) Accense Technology, Inc. - 35 Tansumachi - Shinjyuku-ku Tokyo 1620833 - JAPAN - - 00-17-67 (hex) Earforce AS - 001767 (base 16) Earforce AS - P.O.Box 4 - Bryne 4349 - NORWAY - - 00-17-68 (hex) Zinwave Ltd - 001768 (base 16) Zinwave Ltd - Zinwave Ltd, Harston Mill - Harston - Cambridge Cambridgeshire CB2 5GG - UNITED KINGDOM - - 00-17-69 (hex) Cymphonix Corp - 001769 (base 16) Cymphonix Corp - 8871 S. Sandy Parkway, Suite 150 - Sandy UT 84070 - UNITED STATES - - 00-17-6A (hex) Avago Technologies - 00176A (base 16) Avago Technologies - 350 West Trimble Rd - San Jose CA 95131 - UNITED STATES - - 00-17-6B (hex) Kiyon, Inc. - 00176B (base 16) Kiyon, Inc. - 9381 Judicial Drive - Suite 160 - San Diego CA 92121 - UNITED STATES - - 00-17-6C (hex) Pivot3, Inc. - 00176C (base 16) Pivot3, Inc. - 6605 Cypresswood Drive, Ste 350 - Spring TX 77379-7741 - UNITED STATES - - 00-17-6D (hex) CORE CORPORATION - 00176D (base 16) CORE CORPORATION - 1-22-3, Sangenjaya, - Setagaya-ku Tokyo-to 154-8552 - JAPAN - - 00-17-6E (hex) DUCATI SISTEMI - 00176E (base 16) DUCATI SISTEMI - VIA MARCO EMILIO LEPIDO, 182 - BOLOGNA 40132 - ITALY - - 00-17-6F (hex) PAX Computer Technology(Shenzhen) Ltd. - 00176F (base 16) PAX Computer Technology(Shenzhen) Ltd. - 4/F, No.3 Building, Software Park, Second Central Science-Tech Road, High-Tech - industrial Park - Shenzhen GuangDong 518057 - CHINA - - 00-17-70 (hex) Arti Industrial Electronics Ltd. - 001770 (base 16) Arti Industrial Electronics Ltd. - Ger-San Sitesi, 657. Sokak - No: 80, Ergazi - Ankara TR 06370 - TURKEY - - 00-17-71 (hex) APD Communications Ltd - 001771 (base 16) APD Communications Ltd - Newlands Centre - Inglemire Lane - HULL East Yorkshire HU6 7TQ - UNITED KINGDOM - - 00-17-72 (hex) ASTRO Strobel Kommunikationssysteme GmbH - 001772 (base 16) ASTRO Strobel Kommunikationssysteme GmbH - Olefant 1-3 - Bergisch Gladbach NRW 51427 - GERMANY - - 00-17-73 (hex) Laketune Technologies Co. Ltd - 001773 (base 16) Laketune Technologies Co. Ltd - No. 38 Zijinghua Rd. Westlake District - Gudang Industrial Zone Building 11, 5F - Hangzhou Zhejiang 310013 - CHINA - - 00-17-74 (hex) Elesta GmbH - 001774 (base 16) Elesta GmbH - Gottlieb Daimler Strasse 1 - Konstanz 78467 - GERMANY - - 00-17-75 (hex) TTE Germany GmbH - 001775 (base 16) TTE Germany GmbH - Hermann-Schwer-Straße 3 - Villingen-Schwenningen Baden-Württemberg 78048 - GERMANY - - 00-17-76 (hex) Meso Scale Diagnostics, LLC - 001776 (base 16) Meso Scale Diagnostics, LLC - 9238 Gaither Rd. - Gaithersburg MD 20877 - UNITED STATES - - 00-17-77 (hex) Obsidian Research Corporation - 001777 (base 16) Obsidian Research Corporation - 120 - 4445 Calgary Trail NW - Edmonton Alberta T6H 5R7 - CANADA - - 00-17-78 (hex) Central Music Co. - 001778 (base 16) Central Music Co. - 0711-0712 Tower D, SOHO New Town - No. 88 Jianguo Road, Chaoyang District - Beijing 100022 - CHINA - - 00-17-79 (hex) QuickTel - 001779 (base 16) QuickTel - Cornishe El-Nile, Maasara - Cairo 11743 - EGYPT - - 00-17-7A (hex) ASSA ABLOY AB - 00177A (base 16) ASSA ABLOY AB - Theres Svenssons gata 15 - 41755 Goteborg - Goteborg 41755 - SWEDEN - - 00-17-7B (hex) Azalea Networks inc - 00177B (base 16) Azalea Networks inc - 673 S Milpitas Blvd - Suite 105 - Milpitas CA 95035 - UNITED STATES - - 00-17-7C (hex) Smartlink Network Systems Limited - 00177C (base 16) Smartlink Network Systems Limited - L-7, Verna Electronic city - Verna - Nagoa Goa 403 722 - INDIA - - 00-17-7D (hex) IDT International Limited - 00177D (base 16) IDT International Limited - Block C, 9/F, Kaiser Estate, Phase I - 41 Man Yue Street, Hunghom, Kowloon - HONG KONG - - 00-17-7E (hex) Meshcom Technologies Inc. - 00177E (base 16) Meshcom Technologies Inc. - Meritullinkatu 1 C - Helsinki 00170 - FINLAND - - 00-17-7F (hex) Worldsmart Retech - 00177F (base 16) Worldsmart Retech - 23 Hi-Tech Court - Eight Mile Plains QLD 4113 - AUSTRALIA - - 00-17-80 (hex) Applied Biosystems B.V. - 001780 (base 16) Applied Biosystems B.V. - Blk 33, Marsiling Industrial Estate Road 3, - #05-03 - 739256 - SINGAPORE - - 00-17-81 (hex) Greystone Data System, Inc. - 001781 (base 16) Greystone Data System, Inc. - 40800 Encycopedia Circle - Fremont CA 94538 - UNITED STATES - - 00-17-82 (hex) LoBenn Inc. - 001782 (base 16) LoBenn Inc. - 150 Katimavik Road - Suite 202 - Ottawa Ontario K2L 2N2 - CANADA - - 00-17-83 (hex) Texas Instruments - 001783 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-84 (hex) ARRIS Group, Inc. - 001784 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-17-85 (hex) Sparr Electronics Ltd - 001785 (base 16) Sparr Electronics Ltd - Sparr Electronics Ltd - 43 HMT Main Road Mathikere - Bangalore Karnataka 560054 - INDIA - - 00-17-86 (hex) wisembed - 001786 (base 16) wisembed - 808, hansin IT tower, 235 guro3-dong, guro-gu - Seoul 152-768 - KOREA, REPUBLIC OF - - 00-17-87 (hex) Brother, Brother & Sons ApS - 001787 (base 16) Brother, Brother & Sons ApS - Ved Amagerbanen 9 - Copenhagen S DK-2300 - DENMARK - - 00-17-88 (hex) Philips Lighting BV - 001788 (base 16) Philips Lighting BV - High Tech Campus 45 - Eindhoven Noord Brabant 5656 AE - NETHERLANDS - - 00-17-89 (hex) Zenitron Corporation - 001789 (base 16) Zenitron Corporation - No. 8, Lane 250, Sinhu 2nd Rd., Neihu District, - Taipei 11494 - TAIWAN, PROVINCE OF CHINA - - 00-17-8A (hex) DARTS TECHNOLOGIES CORP. - 00178A (base 16) DARTS TECHNOLOGIES CORP. - 2F,No.119,Chien Kang Rd., - Chung-Ho Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-17-8B (hex) Teledyne Technologies Incorporated - 00178B (base 16) Teledyne Technologies Incorporated - 12333 West Olympic Blvd - Los Angeles CA 90064 - UNITED STATES - - 00-17-8C (hex) Independent Witness, Inc - 00178C (base 16) Independent Witness, Inc - 1515 West 2200 South - Suite E - Salt Lake City UT 84119 - UNITED STATES - - 00-17-8D (hex) Checkpoint Systems, Inc. - 00178D (base 16) Checkpoint Systems, Inc. - 101 Wolf Drive - Thorofare NJ 08086 - UNITED STATES - - 00-17-8E (hex) Gunnebo Cash Automation AB - 00178E (base 16) Gunnebo Cash Automation AB - Fabriksgatan 10 - Göteborg 402 27 - SWEDEN - - 00-17-8F (hex) NINGBO YIDONG ELECTRONIC CO.,LTD. - 00178F (base 16) NINGBO YIDONG ELECTRONIC CO.,LTD. - No.65 Siming East Rd - Yuyao City, Zhejiang Province Zhejiang Province China P.C 315400 - CHINA - - 00-17-90 (hex) HYUNDAI DIGITECH Co, Ltd. - 001790 (base 16) HYUNDAI DIGITECH Co, Ltd. - 13th Fl, Choung-Jin Bldg, 53-5 - Wonhyo-ro 3Ga, Yongsan-Gu - Seoul 140-719 - KOREA, REPUBLIC OF - - 00-17-91 (hex) LinTech GmbH - 001791 (base 16) LinTech GmbH - Friedrich-Engels-Str. 35 - Berlin 13156 - GERMANY - - 00-17-92 (hex) Falcom Wireless Comunications Gmbh - 001792 (base 16) Falcom Wireless Comunications Gmbh - Gewerbering 6 - Langewiesen Thuringia 98704 - GERMANY - - 00-17-93 (hex) Tigi Corporation - 001793 (base 16) Tigi Corporation - 2070 Chain Bridge road - Suite G-100 - Vienna Va 22182 - UNITED STATES - - 00-17-94 (hex) CISCO SYSTEMS, INC. - 001794 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-95 (hex) CISCO SYSTEMS, INC. - 001795 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-96 (hex) Rittmeyer AG - 001796 (base 16) Rittmeyer AG - Inwilerriedstrasse 57 - Postfach 464 - Baar ZG CH-6341 - SWITZERLAND - - 00-17-97 (hex) Telsy Elettronica S.p.A. - 001797 (base 16) Telsy Elettronica S.p.A. - Corso Svizzera 185 - Torino 10149 - ITALY - - 00-17-98 (hex) Azonic Technology Co., LTD - 001798 (base 16) Azonic Technology Co., LTD - 15F-3, No. 163, Sec., 1 Keelung Rd. - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-17-99 (hex) SmarTire Systems Inc. - 001799 (base 16) SmarTire Systems Inc. - Suite 150 - 13151 Vanier Place - Richmond BC V6V 2J1 - CANADA - - 00-17-9A (hex) D-Link Corporation - 00179A (base 16) D-Link Corporation - No. 289, Sinhu 3rd Rd., Neihu District, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-17-9B (hex) Chant Sincere CO., LTD. - 00179B (base 16) Chant Sincere CO., LTD. - 7F-2,NO.188,Sec 3,Ta Tung Rood, - Hsi Chih City Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-17-9C (hex) DEPRAG SCHULZ GMBH u. CO. - 00179C (base 16) DEPRAG SCHULZ GMBH u. CO. - Kurfürstenringg 12.18 - Amberg Bayern 92224 - GERMANY - - 00-17-9D (hex) Kelman Limited - 00179D (base 16) Kelman Limited - Rathdown Close - Lissue East Industrial Estate - Lisburn Co. Antrim BT28 2RB - UNITED KINGDOM - - 00-17-9E (hex) Sirit Inc - 00179E (base 16) Sirit Inc - 2525 Meridian Parkway - Suite 60 - Durham NC 27713 - UNITED STATES - - 00-17-9F (hex) Apricorn - 00179F (base 16) Apricorn - 12191 Kirkham RD - Poway California 92064 - UNITED STATES - - 00-17-A0 (hex) RoboTech srl - 0017A0 (base 16) RoboTech srl - Via Mazzini 82 - Sarzana (SP) I-19038 - ITALY - - 00-17-A1 (hex) 3soft inc. - 0017A1 (base 16) 3soft inc. - shinyoung bldg 4f, chungdam-dong, gangnam-gu - seoul 135-100 - KOREA, REPUBLIC OF - - 00-17-A2 (hex) Camrivox Ltd. - 0017A2 (base 16) Camrivox Ltd. - The Jeffreys Building - Cowley Road - Cambridge Cambridgeshire CB4 0WS - UNITED KINGDOM - - 00-17-A3 (hex) MIX s.r.l. - 0017A3 (base 16) MIX s.r.l. - Via Caldera, 21 - Milan I-20153 - ITALY - - 00-17-A4 (hex) Hewlett-Packard Company - 0017A4 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-17-A5 (hex) Ralink Technology Corp - 0017A5 (base 16) Ralink Technology Corp - Suite 215, Bldg 53. 195-61 Sec.4, Chung Hsing Rd, - Chutung Hsinchu 310 - TAIWAN, PROVINCE OF CHINA - - 00-17-A6 (hex) YOSIN ELECTRONICS CO., LTD. - 0017A6 (base 16) YOSIN ELECTRONICS CO., LTD. - 6F-2, No.17, Lan 174, Shin-Ming Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-17-A7 (hex) Mobile Computing Promotion Consortium - 0017A7 (base 16) Mobile Computing Promotion Consortium - 3-5-12 Shiba-Koen - Minato-ku - Tokyo 105-0011 - JAPAN - - 00-17-A8 (hex) EDM Corporation - 0017A8 (base 16) EDM Corporation - 3-5-2 Itabashi - Itabashi-ku Tokyo 173-0004 - JAPAN - - 00-17-A9 (hex) Sentivision - 0017A9 (base 16) Sentivision - Marynarska 19a - Warsaw Mazowieckie 02-674 - POLAND - - 00-17-AA (hex) elab-experience inc. - 0017AA (base 16) elab-experience inc. - 104 Anotsupia - Anotsudai 4-6-1 - Tsu-shi mie prefecture 514-0131 - JAPAN - - 00-17-AB (hex) Nintendo Co., Ltd. - 0017AB (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-17-AC (hex) O'Neil Product Development Inc. - 0017AC (base 16) O'Neil Product Development Inc. - 8 Mason - Irvine CA 92618 - UNITED STATES - - 00-17-AD (hex) AceNet Corporation - 0017AD (base 16) AceNet Corporation - 7F-4, No.146, Wen-Shin Road - Gueishan TAOYUAN - TAIWAN, PROVINCE OF CHINA - - 00-17-AE (hex) GAI-Tronics - 0017AE (base 16) GAI-Tronics - Brunel Drive - Stretton Park - Burton Upon Trent Staffordshire DE13 0BZ - UNITED KINGDOM - - 00-17-AF (hex) Enermet - 0017AF (base 16) Enermet - Salvesenintie - Jyskä FIN-40420 - FINLAND - - 00-17-B0 (hex) Nokia Danmark A/S - 0017B0 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-17-B1 (hex) ACIST Medical Systems, Inc. - 0017B1 (base 16) ACIST Medical Systems, Inc. - 7450 Flying Cloud Drive - Suite 150 - Eden Prairie MN 55344 - UNITED STATES - - 00-17-B2 (hex) SK Telesys - 0017B2 (base 16) SK Telesys - 4F, Kyungdong bldg, 4-4, Sunae-Dong, Pundang-Gu - Sungnam-City Kunggi-Do 463-825 - KOREA, REPUBLIC OF - - 00-17-B3 (hex) Aftek Infosys Limited - 0017B3 (base 16) Aftek Infosys Limited - Pawan Complex - Sheela Vihar Colony - Pune Maharashtra 411 038 - INDIA - - 00-17-B4 (hex) Remote Security Systems, LLC - 0017B4 (base 16) Remote Security Systems, LLC - 4806 Upper Brandon Place - Marietta Georgia 30068 - UNITED STATES - - 00-17-B5 (hex) Peerless Systems Corporation - 0017B5 (base 16) Peerless Systems Corporation - 2381 Rosecrans Avenue, Suite 400 - El Segundo CA 90245 - UNITED STATES - - 00-17-B6 (hex) Aquantia - 0017B6 (base 16) Aquantia - 700 Tasman Dr. - Milpitas CA 95035 - UNITED STATES - - 00-17-B7 (hex) Tonze Technology Co. - 0017B7 (base 16) Tonze Technology Co. - 5F-10, No.6, Lane 180, - Sec 6, Mincyuan East Road - Taipei 11490 - TAIWAN, PROVINCE OF CHINA - - 00-17-B8 (hex) NOVATRON CO., LTD. - 0017B8 (base 16) NOVATRON CO., LTD. - #601 polaris bldg., 15-3 jeongja-dong, bundang-gu - Seong Nam Gyeonggi Do 463-811 - KOREA, REPUBLIC OF - - 00-17-B9 (hex) Gambro Lundia AB - 0017B9 (base 16) Gambro Lundia AB - BOX 10101 - LUND SkÃ¥ne 22010 - SWEDEN - - 00-17-BA (hex) SEDO CO., LTD. - 0017BA (base 16) SEDO CO., LTD. - 302, KT Bldg, 1ANNEX, 35-1 - Yeongdeungpo-dong 8ga, Yeongdeungpo-gu - Seoul 150-038 - KOREA, REPUBLIC OF - - 00-17-BB (hex) Syrinx Industrial Electronics - 0017BB (base 16) Syrinx Industrial Electronics - De Factorij 13 - Zwaag Noord Holland 1689 AK - NETHERLANDS - - 00-17-BC (hex) Touchtunes Music Corporation - 0017BC (base 16) Touchtunes Music Corporation - 3 Place du Commerce - 4th Floor - Montréal Québec H3E 1H7 - CANADA - - 00-17-BD (hex) Tibetsystem - 0017BD (base 16) Tibetsystem - 6F IT Castle II 550-1 Gasan-dong - Seoul Geumcheon-gu 153-803 - KOREA, REPUBLIC OF - - 00-17-BE (hex) Tratec Telecom B.V. - 0017BE (base 16) Tratec Telecom B.V. - De Smalle Zijde 12 - Veenendaal NL0-3903 LP - NETHERLANDS - - 00-17-BF (hex) Coherent Research Limited - 0017BF (base 16) Coherent Research Limited - 8 Princess Mews - Horace Road - Kingston upon Thames Surrey KT1 2SZ - UNITED KINGDOM - - 00-17-C0 (hex) PureTech Systems, Inc. - 0017C0 (base 16) PureTech Systems, Inc. - 1950 W Rose Garden Lane - Suite 140 - Phoenix AZ 85027 - UNITED STATES - - 00-17-C1 (hex) CM Precision Technology LTD. - 0017C1 (base 16) CM Precision Technology LTD. - 2 Fl, No. 177, Chien-E Road, Chung-Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-17-C2 (hex) ADB Broadband Italia - 0017C2 (base 16) ADB Broadband Italia - v.Sarca 222 - Milano 20126 - ITALY - - 00-17-C3 (hex) KTF Technologies Inc. - 0017C3 (base 16) KTF Technologies Inc. - 4th Fl., Central Tower, 265-3, Seohyun-Dong - Bundnag-Gu - Sungnam-City Kyunggi-Do 463-769 - KOREA, REPUBLIC OF - - 00-17-C4 (hex) Quanta Microsystems, INC. - 0017C4 (base 16) Quanta Microsystems, INC. - 188 Wenhwa 2nd RD., Kueishan Hsiang - Taoyuan Shien 333 - TAIWAN, PROVINCE OF CHINA - - 00-17-C5 (hex) SonicWALL - 0017C5 (base 16) SonicWALL - 1143 Borregas Ave - Sunnyvale CA 95126 - UNITED STATES - - 00-17-C6 (hex) Cross Match Technologies Inc - 0017C6 (base 16) Cross Match Technologies Inc - 400, boul. Jean-Lesage - Hall Ouest, Suite 30 - Québec G1K 8W1 - CANADA - - 00-17-C7 (hex) MARA Systems Consulting AB - 0017C7 (base 16) MARA Systems Consulting AB - Instrumentvägen 45 - Stockholm 126 53 - SWEDEN - - 00-17-C8 (hex) KYOCERA Document Solutions Inc. - 0017C8 (base 16) KYOCERA Document Solutions Inc. - 2-14-9, Tamagawadai - Setagaya-Ward - Tokyo 158-8610 - JAPAN - - 00-17-C9 (hex) Samsung Electronics Co., Ltd. - 0017C9 (base 16) Samsung Electronics Co., Ltd. - 416, Maetan-3Dong, Yeongtong-Gu - Suwon Geyonggi-Do 443-742 - KOREA, REPUBLIC OF - - 00-17-CA (hex) Qisda Corporation - 0017CA (base 16) Qisda Corporation - 157 Shan Ying Road, - GueiShan Taoyuan, 333 - TAIWAN, PROVINCE OF CHINA - - 00-17-CB (hex) Juniper Networks - 0017CB (base 16) Juniper Networks - 1194 North Mathilda Avenue - Sunnyvale California 94089-1206 - UNITED STATES - - 00-17-CC (hex) Alcatel-Lucent - 0017CC (base 16) Alcatel-Lucent - 601 Data Dr. - M/S 601-TSGTD - Plano TX 75075 - UNITED STATES - - 00-17-CD (hex) CEC Wireless R&D Ltd. - 0017CD (base 16) CEC Wireless R&D Ltd. - West M5 Building,No.1 East Road - Jiuxianqiao Chao Yang District - Beijing 100016 - CHINA - - 00-17-CE (hex) Screen Service Spa - 0017CE (base 16) Screen Service Spa - Via G.Di Vittorio 17 - Brescia 25125 - ITALY - - 00-17-CF (hex) iMCA-GmbH - 0017CF (base 16) iMCA-GmbH - Dorfstrasse 28b - Itzehoe Schleswig-Holstein 25524 - GERMANY - - 00-17-D0 (hex) Opticom Communications, LLC - 0017D0 (base 16) Opticom Communications, LLC - 1050 Connecticut Avenue, NW - Suite 1000 - Washington DC 20036 - UNITED STATES - - 00-17-D1 (hex) Nortel - 0017D1 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-17-D2 (hex) THINLINX PTY LTD - 0017D2 (base 16) THINLINX PTY LTD - 31 Carwoola Crescent - Mooloolaba Queensland 4557 - AUSTRALIA - - 00-17-D3 (hex) Etymotic Research, Inc. - 0017D3 (base 16) Etymotic Research, Inc. - 61 Martin Lane - Elk Grove Village IL 60061 - UNITED STATES - - 00-17-D4 (hex) Monsoon Multimedia, Inc - 0017D4 (base 16) Monsoon Multimedia, Inc - 1730 South Amphlett blvd. Suite 101 - San Mateo CA 94402 - UNITED STATES - - 00-17-D5 (hex) Samsung Electronics Co., Ltd. - 0017D5 (base 16) Samsung Electronics Co., Ltd. - #94-1, Imsoo-Dong - Gumi-City Gyeong-Buk 730-350 - KOREA, REPUBLIC OF - - 00-17-D6 (hex) Bluechips Microhouse Co.,Ltd. - 0017D6 (base 16) Bluechips Microhouse Co.,Ltd. - 212/2 M.10 Tambol Umong - Amphur Muang - Lamphun 51150 - THAILAND - - 00-17-D7 (hex) ION Geophysical Corporation Inc. - 0017D7 (base 16) ION Geophysical Corporation Inc. - 850 Dorothy - Suite 510 - Richardson Texas 75081 - UNITED STATES - - 00-17-D8 (hex) Magnum Semiconductor, Inc. - 0017D8 (base 16) Magnum Semiconductor, Inc. - 591 Yosemite Drive - Milpitas CA 95035 - UNITED STATES - - 00-17-D9 (hex) AAI Corporation - 0017D9 (base 16) AAI Corporation - P.O. Box 126 - Hunt Valley Maryland 21030 - UNITED STATES - - 00-17-DA (hex) Spans Logic - 0017DA (base 16) Spans Logic - 201 San Antonio Circle - #280 - Mountain View CA 94040 - UNITED STATES - - 00-17-DB (hex) CANKO TECHNOLOGIES INC. - 0017DB (base 16) CANKO TECHNOLOGIES INC. - 5 FL. DONG SUNG BLDG. 17-8 - YOIDO-DONG, YEONGDEUNGPO-KU - SEOUL 150-874 - KOREA, REPUBLIC OF - - 00-17-DC (hex) DAEMYUNG ZERO1 - 0017DC (base 16) DAEMYUNG ZERO1 - #809,Hyosung Intellian - 1594-1 Gwanyang-dong,Dongan-gu - Anyang-si Gyeonggi-do 431-060 - KOREA, REPUBLIC OF - - 00-17-DD (hex) Clipsal Australia - 0017DD (base 16) Clipsal Australia - 33-37 Port Wakefield Rd - Gepps Cross South Australia 5094 - AUSTRALIA - - 00-17-DE (hex) Advantage Six Ltd - 0017DE (base 16) Advantage Six Ltd - 208 George St - Shaw - OLDHAM Lancs OL2 8DR - UNITED KINGDOM - - 00-17-DF (hex) CISCO SYSTEMS, INC. - 0017DF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-E0 (hex) CISCO SYSTEMS, INC. - 0017E0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-17-E1 (hex) DACOS Technologies Co., Ltd. - 0017E1 (base 16) DACOS Technologies Co., Ltd. - 104 Daeryung-Technotown III 448 - Gasan-Dong - SEOUL Keumcheon-Gu 153-772 - KOREA, REPUBLIC OF - - 00-17-E2 (hex) ARRIS Group, Inc. - 0017E2 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-17-E3 (hex) Texas Instruments - 0017E3 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-E4 (hex) Texas Instruments - 0017E4 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-E5 (hex) Texas Instruments - 0017E5 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-E6 (hex) Texas Instruments - 0017E6 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-E7 (hex) Texas Instruments - 0017E7 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-E8 (hex) Texas Instruments - 0017E8 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-E9 (hex) Texas Instruments - 0017E9 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-EA (hex) Texas Instruments - 0017EA (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-EB (hex) Texas Instruments - 0017EB (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-EC (hex) Texas Instruments - 0017EC (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-17-ED (hex) WooJooIT Ltd. - 0017ED (base 16) WooJooIT Ltd. - Hankooktire B/D 4th floor, 501-19, - Sinwol2 -dong, - Yangcheon-gu, Seoul 158-839 - KOREA, REPUBLIC OF - - 00-17-EE (hex) ARRIS Group, Inc. - 0017EE (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-17-EF (hex) IBM Corp - 0017EF (base 16) IBM Corp - 2051 Mission College Blvd - Santa Clara CA 95054 - UNITED STATES - - 00-17-F0 (hex) SZCOM Broadband Network Technology Co.,Ltd - 0017F0 (base 16) SZCOM Broadband Network Technology Co.,Ltd - Room 602 No.8 Building ,Shenzhen Software Park, - Hi-Tech C.Zone ,Nanshan Area - Shenzhen Guangdong 518057 - CHINA - - 00-17-F1 (hex) Renu Electronics Pvt Ltd - 0017F1 (base 16) Renu Electronics Pvt Ltd - Sr No 2/6, Baner Road, - Baner, - Pune Maharashtra 411045 - INDIA - - 00-17-F2 (hex) Apple - 0017F2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-17-F3 (hex) Harris Corparation - 0017F3 (base 16) Harris Corparation - 1025 West NASA Blvd - Melbourne FL 32919 - UNITED STATES - - 00-17-F4 (hex) ZERON ALLIANCE - 0017F4 (base 16) ZERON ALLIANCE - 3F DOORI BUILD. 244-14 bunji, Poi-dong, Gangnam-gu - SEOUL 135-965 - KOREA, REPUBLIC OF - - 00-17-F5 (hex) LIG NEOPTEK - 0017F5 (base 16) LIG NEOPTEK - 926 Gosaek-dong - Gwonseon-gu - Suwon-si Gyeonggi-do 441-813 - KOREA, REPUBLIC OF - - 00-17-F6 (hex) Pyramid Meriden Inc. - 0017F6 (base 16) Pyramid Meriden Inc. - 45 Gracey Ave. - Meriden CT 06451 - UNITED STATES - - 00-17-F7 (hex) CEM Solutions Pvt Ltd - 0017F7 (base 16) CEM Solutions Pvt Ltd - 49,Kanija Bhavan - Race Course Road - Bangalore Karnataka 560 001 - INDIA - - 00-17-F8 (hex) Motech Industries Inc. - 0017F8 (base 16) Motech Industries Inc. - 6F, No. 248, Sec. 3, Pei-Shen Rd., - Shen-Keng Hsiang - Taipei Hsien 222 - TAIWAN, PROVINCE OF CHINA - - 00-17-F9 (hex) Forcom Sp. z o.o. - 0017F9 (base 16) Forcom Sp. z o.o. - Gajowa 6 - Poznan WLKP 60-815 - POLAND - - 00-17-FA (hex) Microsoft Corporation - 0017FA (base 16) Microsoft Corporation - One Microsoft Way - RED-B/1072 - Redmond Washington 98052-6399 - UNITED STATES - - 00-17-FB (hex) FA - 0017FB (base 16) FA - 628-7, Dungchon-Dong - Seoul Kangseo-Ku 157-838 - KOREA, REPUBLIC OF - - 00-17-FC (hex) Suprema Inc. - 0017FC (base 16) Suprema Inc. - 16F Parkview Office Tower, - Jeongja-dong, Bundang-gu, - Seongnam Gyeonggi 463-863 - KOREA, REPUBLIC OF - - 00-17-FD (hex) Amulet Hotkey - 0017FD (base 16) Amulet Hotkey - Cavalier Road - Heathfield Industrial Estate - Heathfield Devon TQ12 6TQ - UNITED KINGDOM - - 00-17-FE (hex) TALOS SYSTEM INC. - 0017FE (base 16) TALOS SYSTEM INC. - 6191 CORNERSTONE CT. STE #109 - SAN DIEGO CA 92121 - UNITED STATES - - 00-17-FF (hex) PLAYLINE Co.,Ltd. - 0017FF (base 16) PLAYLINE Co.,Ltd. - 1-4-21 MOTOAKASAKA - MINATOKU - TOKYO 107-0051 - JAPAN - - 00-18-00 (hex) UNIGRAND LTD - 001800 (base 16) UNIGRAND LTD - 7F-2, No.45, Jingde St., Jhonghe City, - Taipei County - 235 - TAIWAN, PROVINCE OF CHINA - - 00-18-01 (hex) Actiontec Electronics, Inc - 001801 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94086 - UNITED STATES - - 00-18-02 (hex) Alpha Networks Inc. - 001802 (base 16) Alpha Networks Inc. - No.8 Li-shing Seventh Road,Science-based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-18-03 (hex) ArcSoft Shanghai Co. LTD - 001803 (base 16) ArcSoft Shanghai Co. LTD - 20th Floor, Suite (EAST) 2008, China Merchants Plaza, 333 - Shanghai 200041 - CHINA - - 00-18-04 (hex) E-TEK DIGITAL TECHNOLOGY LIMITED - 001804 (base 16) E-TEK DIGITAL TECHNOLOGY LIMITED - UNIT1520,15/F.,TOWER 2,GRAND CENTURY PLACE,193 PRINCE EDWARD ROAD WEST,KOWLOON, - HONG KONG - - 00-18-05 (hex) Beijing InHand Networking Technology Co.,Ltd. - 001805 (base 16) Beijing InHand Networking Technology Co.,Ltd. - West Wing 11th Floor of Qiming International Mansion - No. 101 Lize Center Park, Chaoyang District - Beijing 100102 - CHINA - - 00-18-06 (hex) Hokkei Industries Co., Ltd. - 001806 (base 16) Hokkei Industries Co., Ltd. - Imahira 432 - Hakusan Ishikawa 924-0827 - JAPAN - - 00-18-07 (hex) Fanstel Corp. - 001807 (base 16) Fanstel Corp. - 7466 E. Monte Cristo Ave. - Scottsdale Arizona 85260 - UNITED STATES - - 00-18-08 (hex) SightLogix, Inc. - 001808 (base 16) SightLogix, Inc. - 745 Alexander Road - Princeton NJ 08540 - UNITED STATES - - 00-18-09 (hex) CRESYN - 001809 (base 16) CRESYN - 8-22,Jamwon-dong - Seoul Seocho-Gu #137-902 - KOREA, REPUBLIC OF - - 00-18-0A (hex) Meraki, Inc. - 00180A (base 16) Meraki, Inc. - 99 Rhode Island St. - San Francisco, CA 94103 - UNITED STATES - - 00-18-0B (hex) Brilliant Telecommunications - 00180B (base 16) Brilliant Telecommunications - 307 Orchard City Dr. - Suite 102 - Campbell CA 95008 - UNITED STATES - - 00-18-0C (hex) Optelian Access Networks - 00180C (base 16) Optelian Access Networks - 22A-1051 Baxter Road - Ottawa Ontario K2C 3P2 - CANADA - - 00-18-0D (hex) Terabytes Server Storage Tech Corp - 00180D (base 16) Terabytes Server Storage Tech Corp - 14257 E Don Julian Rd - City of Industry CA 91746 - UNITED STATES - - 00-18-0E (hex) Avega Systems - 00180E (base 16) Avega Systems - 59 Victoria Street - McMahons Point NSW 2060 - AUSTRALIA - - 00-18-0F (hex) Nokia Danmark A/S - 00180F (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V Denmark 1790V - DENMARK - - 00-18-10 (hex) IPTrade S.A. - 001810 (base 16) IPTrade S.A. - Parc Scientifique - Avenue des Chasseurs Ardennais, 4 - Sart-Tilman Wallonie 4031 - BELGIUM - - 00-18-11 (hex) Neuros Technology International, LLC. - 001811 (base 16) Neuros Technology International, LLC. - 650 W Lake St - Suite 330 - Chicago IL 60661 - UNITED STATES - - 00-18-12 (hex) Beijing Xinwei Telecom Technology Co., Ltd. - 001812 (base 16) Beijing Xinwei Telecom Technology Co., Ltd. - Xinwei Bldg., No. 7 Zhongguancun Software Park, - No. 8 Dongbeiwang West Road - Haidian District Beijing 100094 - CHINA - - 00-18-13 (hex) Sony Ericsson Mobile Communications - 001813 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-18-14 (hex) Mitutoyo Corporation - 001814 (base 16) Mitutoyo Corporation - 20-1, Sakado 1-chome, Takatsu-ku, - Kawasaki-shi 213-8533 - JAPAN - - 00-18-15 (hex) GZ Technologies, Inc. - 001815 (base 16) GZ Technologies, Inc. - Room 1, 5F., No.94, Baojhong Rd. - Sindian City - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-18-16 (hex) Ubixon Co., Ltd. - 001816 (base 16) Ubixon Co., Ltd. - Cheongdong Building 2F - 1344-29 Seocho dong Seocho ku - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-18-17 (hex) D. E. Shaw Research, LLC - 001817 (base 16) D. E. Shaw Research, LLC - 120 W. 45th St., 33rd Floor - New York NY 10036 - UNITED STATES - - 00-18-18 (hex) CISCO SYSTEMS, INC. - 001818 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-18-19 (hex) CISCO SYSTEMS, INC. - 001819 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-18-1A (hex) AVerMedia Information Inc. - 00181A (base 16) AVerMedia Information Inc. - 5F., No. 135, Jian 1st Rd., - ZhongHe Dist., - New Taipei City 235 - TAIWAN, PROVINCE OF CHINA - - 00-18-1B (hex) TaiJin Metal Co., Ltd. - 00181B (base 16) TaiJin Metal Co., Ltd. - #95-9, Hangdong7-Ga, Joong-Gu - In Cheon 400-037 - KOREA, REPUBLIC OF - - 00-18-1C (hex) Exterity Limited - 00181C (base 16) Exterity Limited - Ridge Way, Hillend Industrial Estate - Dalgety Bay - Dunfermline Fife KY11 9JD - UNITED KINGDOM - - 00-18-1D (hex) ASIA ELECTRONICS CO.,LTD - 00181D (base 16) ASIA ELECTRONICS CO.,LTD - 620-3 DOCHEON-DONG - GWANGSAN-GU - GWANGJU 506-301 - KOREA, REPUBLIC OF - - 00-18-1E (hex) GDX Technologies Ltd. - 00181E (base 16) GDX Technologies Ltd. - 61-63 Back Sneddon Street - Paisley Renfrewshire PA3 2DD - UNITED KINGDOM - - 00-18-1F (hex) Palmmicro Communications - 00181F (base 16) Palmmicro Communications - Room 0611, Bldg.B Tsinghua Tongfang Technology Plaza - 1 Wangzhuang Road - Beijing 100083 - CHINA - - 00-18-20 (hex) w5networks - 001820 (base 16) w5networks - 48389 Fremont Blvd - Suite 106 - Fremont CA 94538 - UNITED STATES - - 00-18-21 (hex) SINDORICOH - 001821 (base 16) SINDORICOH - 277-22, 2ga, Sungsu-dong, Sungdong-gu, - Seoul 133-120 - KOREA, REPUBLIC OF - - 00-18-22 (hex) CEC TELECOM CO.,LTD. - 001822 (base 16) CEC TELECOM CO.,LTD. - 10thFL.CEC Building,6 Zhongguancun South Street - Beijing 100086 - CHINA - - 00-18-23 (hex) Delta Electronics, Inc. - 001823 (base 16) Delta Electronics, Inc. - 186 Ruey Kuang Road, Neihu, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-18-24 (hex) Kimaldi Electronics, S.L. - 001824 (base 16) Kimaldi Electronics, S.L. - Ctra. de Rubí, 292 B - Pol. Ind. Can Guitard - Terrassa Barcelona 08228 - SPAIN - - 00-18-25 (hex) PRIVATE - 001825 (base 16) - - 00-18-26 (hex) Cale Access AB - 001826 (base 16) Cale Access AB - Box 1031 - Kista SE-164 21 - SWEDEN - - 00-18-27 (hex) NEC UNIFIED SOLUTIONS NEDERLAND B.V. - 001827 (base 16) NEC UNIFIED SOLUTIONS NEDERLAND B.V. - ANTON PHILIPSWEG 1 - HILVERSUM NH 1223KZ - NETHERLANDS - - 00-18-28 (hex) e2v technologies (UK) ltd. - 001828 (base 16) e2v technologies (UK) ltd. - 106 Waterhouse Lane - Chelmsford Essex CM1 2QU - UNITED KINGDOM - - 00-18-29 (hex) Gatsometer - 001829 (base 16) Gatsometer - Claes Tillyweg 2 - Haarlem Noord-Holland 2031 CW - NETHERLANDS - - 00-18-2A (hex) Taiwan Video & Monitor - 00182A (base 16) Taiwan Video & Monitor - 3F, 141 Jen Ai Rd Sec. 3 - Taipei City 106 - TAIWAN, PROVINCE OF CHINA - - 00-18-2B (hex) Softier - 00182B (base 16) Softier - Tidhar 3 - Millenium bldg floor 11 - Ra'anana none 43665 - ISRAEL - - 00-18-2C (hex) Ascend Networks, Inc. - 00182C (base 16) Ascend Networks, Inc. - No. 4 - 4, Lane 413, ChungChan Road, - BenQuao City Taipei 220 - TAIWAN, PROVINCE OF CHINA - - 00-18-2D (hex) Artec Design - 00182D (base 16) Artec Design - Teaduspargi 6/1 - Tallinn 12618 - ESTONIA - - 00-18-2E (hex) XStreamHD, LLC - 00182E (base 16) XStreamHD, LLC - 7900B Westpark Drive - Suite 200T - McLean VA 22102 - UNITED STATES - - 00-18-2F (hex) Texas Instruments - 00182F (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-18-30 (hex) Texas Instruments - 001830 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-18-31 (hex) Texas Instruments - 001831 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-18-32 (hex) Texas Instruments - 001832 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-18-33 (hex) Texas Instruments - 001833 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-18-34 (hex) Texas Instruments - 001834 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-18-35 (hex) Thoratec / ITC - 001835 (base 16) Thoratec / ITC - 2656 Patton Road - Roseville MN 55113 - UNITED STATES - - 00-18-36 (hex) Reliance Electric Limited - 001836 (base 16) Reliance Electric Limited - 2-3-2 Fukuura, Kanazawa-ku - Yokohama Kanagawa 236-8641 - JAPAN - - 00-18-37 (hex) Universal ABIT Co., Ltd. - 001837 (base 16) Universal ABIT Co., Ltd. - 7F, No. 323 Yangguang St., - Neihu Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-18-38 (hex) PanAccess Communications,Inc. - 001838 (base 16) PanAccess Communications,Inc. - Floor 8,Tower B,Global Trade Center,36 Beisanhuandonglu,Dongcheng District - Beijing 100013 - CHINA - - 00-18-39 (hex) Cisco-Linksys LLC - 001839 (base 16) Cisco-Linksys LLC - 121 Theory - Irvine CA 92612 - UNITED STATES - - 00-18-3A (hex) Westell Technologies - 00183A (base 16) Westell Technologies - 750 N. Commons Dr. - Aurora IL 60504 - UNITED STATES - - 00-18-3B (hex) CENITS Co., Ltd. - 00183B (base 16) CENITS Co., Ltd. - 3F, Yangjae Bldg., 264-3 - Yangjae-Dong, Seocho-Gu - Seoul 137-130 - KOREA, REPUBLIC OF - - 00-18-3C (hex) Encore Software Limited - 00183C (base 16) Encore Software Limited - 6F Leo Complex - 44 Residency Cross Road - Bangalore Karnataka 560025 - INDIA - - 00-18-3D (hex) Vertex Link Corporation - 00183D (base 16) Vertex Link Corporation - Meitetsu Fudosan Takebashi Bldg 6F - 3-15 Kanda Nishikicho - Chiyoda-ku Tokyo 101-0054 - JAPAN - - 00-18-3E (hex) Digilent, Inc - 00183E (base 16) Digilent, Inc - 215 E. Main St. - Suite D - Pullman WA 99163 - UNITED STATES - - 00-18-3F (hex) 2Wire, Inc - 00183F (base 16) 2Wire, Inc - 1704 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-18-40 (hex) 3 Phoenix, Inc. - 001840 (base 16) 3 Phoenix, Inc. - 13135 Lee Jackson Hwy - Suite 330 - Fairfax Virginia 22033 - UNITED STATES - - 00-18-41 (hex) High Tech Computer Corp - 001841 (base 16) High Tech Computer Corp - 23 Hsin Hua Rd. - Taoyuan 330 - TAIWAN, PROVINCE OF CHINA - - 00-18-42 (hex) Nokia Danmark A/S - 001842 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 V - DENMARK - - 00-18-43 (hex) Dawevision Ltd - 001843 (base 16) Dawevision Ltd - 197 High Street - Cottenham Cambridge CB4 8RX - UNITED KINGDOM - - 00-18-44 (hex) Heads Up Technologies, Inc. - 001844 (base 16) Heads Up Technologies, Inc. - 2033 Chennault Drive, Suite 100 - Carrollton Texas 75006-5119 - UNITED STATES - - 00-18-45 (hex) Pulsar-Telecom LLC. - 001845 (base 16) Pulsar-Telecom LLC. - Zaharova, 18a - Penza 440044 - RUSSIAN FEDERATION - - 00-18-46 (hex) Crypto S.A. - 001846 (base 16) Crypto S.A. - V. Ipirou 45 - Marousi Athens 15125 - GREECE - - 00-18-47 (hex) AceNet Technology Inc. - 001847 (base 16) AceNet Technology Inc. - 133 Vienna Dr. - Milpitas CA 95035 - UNITED STATES - - 00-18-48 (hex) Vecima Networks Inc. - 001848 (base 16) Vecima Networks Inc. - 150 Cardinal Place - Saskatoon Sk S7L 6H7 - CANADA - - 00-18-49 (hex) Pigeon Point Systems LLC - 001849 (base 16) Pigeon Point Systems LLC - 2191 S. El Camino Real - Suite 209 - Oceanside CA 95054 - UNITED STATES - - 00-18-4A (hex) Catcher, Inc. - 00184A (base 16) Catcher, Inc. - 5864 Owens Ave. - Suite 101 - Carlsbad CA 92008 - UNITED STATES - - 00-18-4B (hex) Las Vegas Gaming, Inc. - 00184B (base 16) Las Vegas Gaming, Inc. - 4000 West Ali Baba Lane, Suite D - Las Vegas Nevada 89118 - UNITED STATES - - 00-18-4C (hex) Bogen Communications - 00184C (base 16) Bogen Communications - 50 Spring St. - Ramsey NJ 07446 - UNITED STATES - - 00-18-4D (hex) Netgear Inc. - 00184D (base 16) Netgear Inc. - 4500 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-18-4E (hex) Lianhe Technologies, Inc. - 00184E (base 16) Lianhe Technologies, Inc. - 3F, #119, DaHu ShanZhuang St. - Neihu District Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-18-4F (hex) 8 Ways Technology Corp. - 00184F (base 16) 8 Ways Technology Corp. - 2F-1, No. 216, Sec. 3, Roosevelt Rd. - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-18-50 (hex) Secfone Kft - 001850 (base 16) Secfone Kft - 51 Bercsenyi str - Jaszbereny 5100 - HUNGARY - - 00-18-51 (hex) SWsoft - 001851 (base 16) SWsoft - 13755 Sunrise Valley Drive, Suite 600 - Herndon VA 20171 - UNITED STATES - - 00-18-52 (hex) StorLink Semiconductors, Inc. - 001852 (base 16) StorLink Semiconductors, Inc. - 1804 N. Shoreline Boulevard - Suite 240 - Mountain View CA 94043 - UNITED STATES - - 00-18-53 (hex) Atera Networks LTD. - 001853 (base 16) Atera Networks LTD. - 31, Habarzel St. - Ramat Hachayal - Tel-Aviv 69710 - ISRAEL - - 00-18-54 (hex) Argard Co., Ltd - 001854 (base 16) Argard Co., Ltd - 2571 Lardprao Rd. - wangthonglang Bangkok 10310 - THAILAND - - 00-18-55 (hex) Aeromaritime Systembau GmbH - 001855 (base 16) Aeromaritime Systembau GmbH - Ludwig-Erhard-Str. 16 - D-85375 Neufahrn - GERMANY - - 00-18-56 (hex) EyeFi, Inc - 001856 (base 16) EyeFi, Inc - 149 Commonwealth Drive - Menlo Park CA 94025 - UNITED STATES - - 00-18-57 (hex) Unilever R&D - 001857 (base 16) Unilever R&D - Bldg. 50 - Sharnbrook - Bedford Bedfordshire MK44 1LQ - UNITED KINGDOM - - 00-18-58 (hex) TagMaster AB - 001858 (base 16) TagMaster AB - Kronborgsgréind 1 - Kista Stockholm S-16487 - SWEDEN - - 00-18-59 (hex) Strawberry Linux Co.,Ltd. - 001859 (base 16) Strawberry Linux Co.,Ltd. - 1-28-8-204 Higashiayase - Adachiku Tokyo 120-0004 - JAPAN - - 00-18-5A (hex) uControl, Inc. - 00185A (base 16) uControl, Inc. - 5914 W. Courtyard Drive - Suite 210 - Austin TX 78730 - UNITED STATES - - 00-18-5B (hex) Network Chemistry, Inc - 00185B (base 16) Network Chemistry, Inc - 1804 Embarcadero Rd - Palo Alto CA 94303 - UNITED STATES - - 00-18-5C (hex) EDS Lab Pte Ltd - 00185C (base 16) EDS Lab Pte Ltd - 20 Ayer Rajah Crescent - #08-26 - 139964 - SINGAPORE - - 00-18-5D (hex) TAIGUEN TECHNOLOGY (SHEN-ZHEN) CO., LTD. - 00185D (base 16) TAIGUEN TECHNOLOGY (SHEN-ZHEN) CO., LTD. - No. 23, The Third Industrial Park of Xia Village, - Gongming, Baoan District, - Shenzhen City, Guangdong, 815106 - CHINA - - 00-18-5E (hex) Nexterm Inc. - 00185E (base 16) Nexterm Inc. - 1-12-3, Shibaura, Minato-ku, - Tokyo 105-0023 - JAPAN - - 00-18-5F (hex) TAC Inc. - 00185F (base 16) TAC Inc. - 66 Nishiishigatsubocho Nishinanajyo Shimogyoku - Kyoto 600-8896 - JAPAN - - 00-18-60 (hex) SIM Technology Group Shanghai Simcom Ltd., - 001860 (base 16) SIM Technology Group Shanghai Simcom Ltd., - SIM Technology building, - 700 Yishan Rd, Shanghai 200233 - Shanghai 200233 - CHINA - - 00-18-61 (hex) Ooma, Inc. - 001861 (base 16) Ooma, Inc. - 555 University Avenue - Palo Alto CA 94301 - UNITED STATES - - 00-18-62 (hex) Seagate Technology - 001862 (base 16) Seagate Technology - 1280 Disc Drive - Shakopee MN 55379 - UNITED STATES - - 00-18-63 (hex) Veritech Electronics Limited - 001863 (base 16) Veritech Electronics Limited - 8F, 67, Sec. 1, Zhongshan Road, Xinzhuang, - Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 00-18-64 (hex) Eaton Corporation - 001864 (base 16) Eaton Corporation - 730, rue Commerciale - Suite 200 - St-Jean-Chrysostome QC G6Z 2C5 - CANADA - - 00-18-65 (hex) Siemens Healthcare Diagnostics Manufacturing Ltd - 001865 (base 16) Siemens Healthcare Diagnostics Manufacturing Ltd - Northern Road - Chilton Industrial Estate - Sudbury Suffolk C010 2XQ - UNITED KINGDOM - - 00-18-66 (hex) Leutron Vision - 001866 (base 16) Leutron Vision - Industriestrasse 57 - Glattbrugg ZH 8152 - SWITZERLAND - - 00-18-67 (hex) Datalogic ADC - 001867 (base 16) Datalogic ADC - 433 N. Fair Oaks Ave - Suite 100 - Pasadena CA 91103 - UNITED STATES - - 00-18-68 (hex) Scientific Atlanta, A Cisco Company - 001868 (base 16) Scientific Atlanta, A Cisco Company - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 00-18-69 (hex) KINGJIM - 001869 (base 16) KINGJIM - No.10-18,2-Chome - Higashi-Kanda - Chiyoda-ku Tokyo 101-0031 - JAPAN - - 00-18-6A (hex) Global Link Digital Technology Co,.LTD - 00186A (base 16) Global Link Digital Technology Co,.LTD - Qibaoyiding Ind.Area - Liuchongwei Wanjiang town - Dongguan Guangdong 523051 - CHINA - - 00-18-6B (hex) Sambu Communics CO., LTD. - 00186B (base 16) Sambu Communics CO., LTD. - 38B-1L Namdong Industrial Complex - 626 Namchon-dong, Namdong-gu - Incheon 405-100 - KOREA, REPUBLIC OF - - 00-18-6C (hex) Neonode AB - 00186C (base 16) Neonode AB - Biblioteksgatan 11, 1st floor - Stockholm S-111 46 - SWEDEN - - 00-18-6D (hex) Zhenjiang Sapphire Electronic Industry CO. - 00186D (base 16) Zhenjiang Sapphire Electronic Industry CO. - Wei San Road,Dingmao Develop Area - zhenjiang jiangsu 212009 - CHINA - - 00-18-6E (hex) 3Com Ltd - 00186E (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts. HP2 4NW - UNITED KINGDOM - - 00-18-6F (hex) Setha Industria Eletronica LTDA - 00186F (base 16) Setha Industria Eletronica LTDA - Rua Alvaro de Macedo 134 - Parada de Lucas - Rio de Janeiro RJ 21.250-620 - BRAZIL - - 00-18-70 (hex) E28 Shanghai Limited - 001870 (base 16) E28 Shanghai Limited - 2/F Eastern Tower - 689 Beijing Road (East) - Shanghai 200001 - CHINA - - 00-18-71 (hex) Hewlett-Packard Company - 001871 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-18-72 (hex) Expertise Engineering - 001872 (base 16) Expertise Engineering - 4186 Sorrento Valley Blvd Suite -J - San Diego CA 92121 - UNITED STATES - - 00-18-73 (hex) CISCO SYSTEMS, INC. - 001873 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-18-74 (hex) CISCO SYSTEMS, INC. - 001874 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-18-75 (hex) AnaCise Testnology Pte Ltd - 001875 (base 16) AnaCise Testnology Pte Ltd - 3 Bishan Place #02-06 - CPF Bishan Building - 579838 - SINGAPORE - - 00-18-76 (hex) WowWee Ltd. - 001876 (base 16) WowWee Ltd. - 92 Granville Rd. Suite 301A-C - Energy Plaza - T.S.T. East Kowloon - HONG KONG - - 00-18-77 (hex) Amplex A/S - 001877 (base 16) Amplex A/S - Silkeborgvej 2 - Aarhus C 8000 - DENMARK - - 00-18-78 (hex) Mackware GmbH - 001878 (base 16) Mackware GmbH - Schänzle 13 - Waiblingen Baden-Württemberg 71332 - GERMANY - - 00-18-79 (hex) dSys - 001879 (base 16) dSys - Soeflinger Str. 100 - Ulm BW 89077 - GERMANY - - 00-18-7A (hex) Wiremold - 00187A (base 16) Wiremold - 60 Woodlawn St. - West Hartford CT 06110 - UNITED STATES - - 00-18-7B (hex) 4NSYS Co. Ltd. - 00187B (base 16) 4NSYS Co. Ltd. - 3F, Hana Bldg - 118-2, Oryu-Dong - Guro-Gu Seoul 152-100 - KOREA, REPUBLIC OF - - 00-18-7C (hex) INTERCROSS, LLC - 00187C (base 16) INTERCROSS, LLC - Novoselov str., 58/7 - Ryazan 390049 - RUSSIAN FEDERATION - - 00-18-7D (hex) Armorlink shanghai Co. Ltd - 00187D (base 16) Armorlink shanghai Co. Ltd - NO 515, Shengfu road - Shanghai 201108 - CHINA - - 00-18-7E (hex) RGB Spectrum - 00187E (base 16) RGB Spectrum - 950 Marina Village Pkwy - Alameda CA 94501 - UNITED STATES - - 00-18-7F (hex) ZODIANET - 00187F (base 16) ZODIANET - 23, rue des Fraisettes - PALAISEAU ESSONNE 91120 - FRANCE - - 00-18-80 (hex) Maxim Integrated Products - 001880 (base 16) Maxim Integrated Products - 160 Rio Robles - M/S: C2-1 - San Jose CA 95134 - UNITED STATES - - 00-18-81 (hex) Buyang Electronics Industrial Co., Ltd - 001881 (base 16) Buyang Electronics Industrial Co., Ltd - 434-140, Oryu-Dong - Seo-Ku - Incheon 404-300 - KOREA, REPUBLIC OF - - 00-18-82 (hex) Huawei Technologies Co., Ltd. - 001882 (base 16) Huawei Technologies Co., Ltd. - F1-20,Section F,Huawei Base,Bantian, Longgang District - ShenZhen GuangDong 518129 - CHINA - - 00-18-83 (hex) FORMOSA21 INC. - 001883 (base 16) FORMOSA21 INC. - 8F-6, NO.351, CHUNG SHAN RD., SEC.2 - CHUNG HO CITY - TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - 00-18-84 (hex) Fon Technology S.L. - 001884 (base 16) Fon Technology S.L. - Avda. Bruselas, n. 7, Planta 3, Alcobendas - Madrid 28100 - SPAIN - - 00-18-85 (hex) Avigilon Corporation - 001885 (base 16) Avigilon Corporation - Box 378, 101 - 1001 West Broadway - Vancouver BC V6H 4E4 - CANADA - - 00-18-86 (hex) EL-TECH, INC. - 001886 (base 16) EL-TECH, INC. - A-711, WOOLIM LION'S VALLEY, 371-28 - GASAN-DONG, GEUMCHEON-GU, - SEOUL 150-834 - KOREA, REPUBLIC OF - - 00-18-87 (hex) Metasystem SpA - 001887 (base 16) Metasystem SpA - Via Oberdan 16 - Reggio Emilia RE 42100 - ITALY - - 00-18-88 (hex) GOTIVE a.s. - 001888 (base 16) GOTIVE a.s. - Zámocká 34 - Bratislava 81101 - SLOVAKIA - - 00-18-89 (hex) WinNet Solutions Limited - 001889 (base 16) WinNet Solutions Limited - Rm804, Kornhill Metro Tower, Quarry Bay - HK 852 - HONG KONG - - 00-18-8A (hex) Infinova LLC - 00188A (base 16) Infinova LLC - 51 Stouts Lane, Unit 1 & 2 - Monmouth Junction New Jersey 08852 - UNITED STATES - - 00-18-8B (hex) Dell Inc - 00188B (base 16) Dell Inc - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 00-18-8C (hex) Mobile Action Technology Inc. - 00188C (base 16) Mobile Action Technology Inc. - 5F, No. 205-3, Sec. 3, Beishin Rd. - Shindian City, Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-18-8D (hex) Nokia Danmark A/S - 00188D (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V 1790 - DENMARK - - 00-18-8E (hex) Ekahau, Inc. - 00188E (base 16) Ekahau, Inc. - Hiilikatu 3 - HELSINKI UUSIMAA 00180 - FINLAND - - 00-18-8F (hex) Montgomery Technology, Inc. - 00188F (base 16) Montgomery Technology, Inc. - 800 East Commerce Street - Greenville AL 36037 - UNITED STATES - - 00-18-90 (hex) RadioCOM, s.r.o. - 001890 (base 16) RadioCOM, s.r.o. - Misikova 22 - Bratislava 811 06 - SLOVAKIA - - 00-18-91 (hex) Zhongshan General K-mate Electronics Co., Ltd - 001891 (base 16) Zhongshan General K-mate Electronics Co., Ltd - 3/F B1 Building, Fuwan Ind. Zone Sun Wen East Road - Zhongshan Guangdong 528403 - CHINA - - 00-18-92 (hex) ads-tec GmbH - 001892 (base 16) ads-tec GmbH - Raiffeisenstraße 14 - Leinfelden-Echterdingen Baden-Württemberg 70771 - GERMANY - - 00-18-93 (hex) SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD - 001893 (base 16) SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD - 2/F Hivac BLD,2th Langshan Rd,North Hi-Tech Industrial - Shenzhen Guangdong 518057 - CHINA - - 00-18-94 (hex) NPCore, Inc. - 001894 (base 16) NPCore, Inc. - 1001, ISBIZ Tower - YangpyungRo 21 Gil, 26 - Youngdungpo Gu Seoul 150-105 - KOREA, REPUBLIC OF - - 00-18-95 (hex) Hansun Technologies Inc. - 001895 (base 16) Hansun Technologies Inc. - Room 301, Building 103, Wangjingkejiyuan, Chaoyang District - Beijing 100102 - CHINA - - 00-18-96 (hex) Great Well Electronic LTD - 001896 (base 16) Great Well Electronic LTD - The Third Industrial Area - Guanlan Town - Shenzhen Guangdong 518110 - CHINA - - 00-18-97 (hex) JESS-LINK PRODUCTS Co., LTD - 001897 (base 16) JESS-LINK PRODUCTS Co., LTD - 9F, No. 176, Jian-Yi Rd., Chung Ho City - Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-18-98 (hex) KINGSTATE ELECTRONICS CORPORATION - 001898 (base 16) KINGSTATE ELECTRONICS CORPORATION - 10F, No.69-11, Sec.2, Chung Cheng E. Rd., - Tamshui Town - Taipei County 251 - TAIWAN, PROVINCE OF CHINA - - 00-18-99 (hex) ShenZhen jieshun Science&Technology Industry CO,LTD. - 001899 (base 16) ShenZhen jieshun Science&Technology Industry CO,LTD. - China GuangDong state Shenzhen City Futian section NO17. Meilin Road - Shenzhen GuangDong 518049 - CHINA - - 00-18-9A (hex) HANA Micron Inc. - 00189A (base 16) HANA Micron Inc. - #95-1 Wonnam-Li, Umbong-Myeon - Chung-Nam, South Korea. - Asan-City Chung-Nam 336-864 - KOREA, REPUBLIC OF - - 00-18-9B (hex) Thomson Inc. - 00189B (base 16) Thomson Inc. - 101 West 103rd Street - Indianapolis IN 46290-1102 - UNITED STATES - - 00-18-9C (hex) Weldex Corporation - 00189C (base 16) Weldex Corporation - 6751 Katella Avenue - Cypress CA 90630 - UNITED STATES - - 00-18-9D (hex) Navcast Inc. - 00189D (base 16) Navcast Inc. - Suite 612, 6711 Mississauga Road - Mississauga ON m2r 1a3 - CANADA - - 00-18-9E (hex) OMNIKEY GmbH. - 00189E (base 16) OMNIKEY GmbH. - Ferihumerstrasse 13 - Linz Upperaustria 4040 - AUSTRIA - - 00-18-9F (hex) Lenntek Corporation - 00189F (base 16) Lenntek Corporation - 4F, 125 GuangMing 3rd. Road - Jhu Bei Hsin Chu 302 - TAIWAN, PROVINCE OF CHINA - - 00-18-A0 (hex) Cierma Ascenseurs - 0018A0 (base 16) Cierma Ascenseurs - 17 avenue guiglionda de saint agathe - Nice PACA 06300 - FRANCE - - 00-18-A1 (hex) Tiqit Computers, Inc. - 0018A1 (base 16) Tiqit Computers, Inc. - 2215 Old Page Mill Rd - Palo Alto CA 94304 - UNITED STATES - - 00-18-A2 (hex) XIP Technology AB - 0018A2 (base 16) XIP Technology AB - PO Box 437 - Jönköping Sweden SE- 551 16 - SWEDEN - - 00-18-A3 (hex) ZIPPY TECHNOLOGY CORP. - 0018A3 (base 16) ZIPPY TECHNOLOGY CORP. - 10F, No. 50, Mincyuan Rd., Sindian City - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-18-A4 (hex) ARRIS Group, Inc. - 0018A4 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-18-A5 (hex) ADigit Technologies Corp. - 0018A5 (base 16) ADigit Technologies Corp. - Rm D302E,No.185 3F-2,Kur-Wong Road, - Lung-Tang, - Tao-yuan, 325 - TAIWAN, PROVINCE OF CHINA - - 00-18-A6 (hex) Persistent Systems, LLC - 0018A6 (base 16) Persistent Systems, LLC - 118 N. Howard St. #72 - Baltimore MD 21201 - UNITED STATES - - 00-18-A7 (hex) Yoggie Security Systems LTD. - 0018A7 (base 16) Yoggie Security Systems LTD. - P.P.Box 156 - Beth Halevy 42870 - ISRAEL - - 00-18-A8 (hex) AnNeal Technology Inc. - 0018A8 (base 16) AnNeal Technology Inc. - Room 106, No. 47 Science Park Rd. II - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-18-A9 (hex) Ethernet Direct Corporation - 0018A9 (base 16) Ethernet Direct Corporation - 19F,No.345 Chung Ho Road, Yung Ho City - Taipei 234 - TAIWAN, PROVINCE OF CHINA - - 00-18-AA (hex) Protec Fire Detection plc - 0018AA (base 16) Protec Fire Detection plc - Protec House - Churchill Way - Nelson Lancashire BB9 6RT - UNITED KINGDOM - - 00-18-AB (hex) BEIJING LHWT MICROELECTRONICS INC. - 0018AB (base 16) BEIJING LHWT MICROELECTRONICS INC. - 18/F,QUANTUM PLAZA,NO.27 ZHI CHUN RD.,HAI DIAN DISTRICT,BEIJING - CHINA - - 00-18-AC (hex) Shanghai Jiao Da HISYS Technology Co. Ltd. - 0018AC (base 16) Shanghai Jiao Da HISYS Technology Co. Ltd. - 7F Haoran HiTech Bldg., No.1954 Huashan Road - shanghai xuhui 200030 - CHINA - - 00-18-AD (hex) NIDEC SANKYO CORPORATION - 0018AD (base 16) NIDEC SANKYO CORPORATION - 5329, Shimosuwa-machi, Suwa-gun - Nagano 393-8511 - JAPAN - - 00-18-AE (hex) TVT CO.,LTD - 0018AE (base 16) TVT CO.,LTD - 5/F,North Block,CE Lighting House - Hi-tech Park, Nanshan District, - shenzhen guangdong 518026 - CHINA - - 00-18-AF (hex) Samsung Electronics Co., Ltd. - 0018AF (base 16) Samsung Electronics Co., Ltd. - #94-1, Imsoo-Dong - Gumi-City Gyeong-Buk 730-350 - KOREA, REPUBLIC OF - - 00-18-B0 (hex) Nortel - 0018B0 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-18-B1 (hex) IBM Corp - 0018B1 (base 16) IBM Corp - 2051 Mission College Blvd - Santa Clara CA 95054 - UNITED STATES - - 00-18-B2 (hex) ADEUNIS RF - 0018B2 (base 16) ADEUNIS RF - 283 Rue NEEL - CROLLES ISERE 38920 - FRANCE - - 00-18-B3 (hex) TEC WizHome Co., Ltd. - 0018B3 (base 16) TEC WizHome Co., Ltd. - 18fl., In-Song bldg., 194-15, - Heohyun-Dong, 1Ga, Jung-Gu - Seoul 100-952 - KOREA, REPUBLIC OF - - 00-18-B4 (hex) Dawon Media Inc. - 0018B4 (base 16) Dawon Media Inc. - Rm503. woolim e-biz center 170-5, Guro3dong Gurogu, - Seoul 152-769 - KOREA, REPUBLIC OF - - 00-18-B5 (hex) Magna Carta - 0018B5 (base 16) Magna Carta - Naritaweg 126 - Amsterdam Noord Holland 1043 CA - NETHERLANDS - - 00-18-B6 (hex) S3C, Inc. - 0018B6 (base 16) S3C, Inc. - 1010 Stewart Dr. - Sunnyvale California 94085 - UNITED STATES - - 00-18-B7 (hex) D3 LED, LLC - 0018B7 (base 16) D3 LED, LLC - 380 Mountain Rd - Suite 1412 - Union City NJ 07087 - UNITED STATES - - 00-18-B8 (hex) New Voice International AG - 0018B8 (base 16) New Voice International AG - St. Gallerstrasse 8 - Lachen SZ 8853 - SWITZERLAND - - 00-18-B9 (hex) CISCO SYSTEMS, INC. - 0018B9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-18-BA (hex) CISCO SYSTEMS, INC. - 0018BA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-18-BB (hex) Eliwell Controls srl - 0018BB (base 16) Eliwell Controls srl - Via dell'Industria, 15 - Pieve d'Alpago Belluno 32010 - ITALY - - 00-18-BC (hex) ZAO NVP Bolid - 0018BC (base 16) ZAO NVP Bolid - Pionerskaya str., 4 - Korolyov Moscow region 141070 - RUSSIAN FEDERATION - - 00-18-BD (hex) SHENZHEN DVBWORLD TECHNOLOGY CO., LTD. - 0018BD (base 16) SHENZHEN DVBWORLD TECHNOLOGY CO., LTD. - 2ND FLOOR, BUILDING A, QINGHU XINQIAO INDUSTRY AREA, - LONGHUA, BAO AN DISTRICT - SHENZHEN GUANGDONG 518000 - CHINA - - 00-18-BE (hex) ANSA Corporation - 0018BE (base 16) ANSA Corporation - 17F., No.738, Chung Cheng Rd. - Chung Ho City, Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-18-BF (hex) Essence Technology Solution, Inc. - 0018BF (base 16) Essence Technology Solution, Inc. - B1, No. 207, Beisin Rd., Sec. 3 - Sindian, Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 00-18-C0 (hex) ARRIS Group, Inc. - 0018C0 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-18-C1 (hex) Almitec Informática e Comércio - 0018C1 (base 16) Almitec Informática e Comércio - 461, Francisco de Morais St. - São Paulo 04714-010 - BRAZIL - - 00-18-C2 (hex) Firetide, Inc - 0018C2 (base 16) Firetide, Inc - 16795 Lark Av, Suite 200 - Los Gatos CA 95032 - UNITED STATES - - 00-18-C3 (hex) CS Corporation - 0018C3 (base 16) CS Corporation - CS-building, Pangyo seven venture valley 625 - Sampyeong-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - 00-18-C4 (hex) Raba Technologies LLC - 0018C4 (base 16) Raba Technologies LLC - 8830 Stanford Blvd Suite 205 - Columbia Maryland 21045 - UNITED STATES - - 00-18-C5 (hex) Nokia Danmark A/S - 0018C5 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V 1790 - DENMARK - - 00-18-C6 (hex) OPW Fuel Management Systems - 0018C6 (base 16) OPW Fuel Management Systems - 6900 Santa Fe Drive - Hodgkins Illinois 60525 - UNITED STATES - - 00-18-C7 (hex) Real Time Automation - 0018C7 (base 16) Real Time Automation - 2825 N Mayfair Rd Ste 11 - Wauwatosa WI 53222 - UNITED STATES - - 00-18-C8 (hex) ISONAS Inc. - 0018C8 (base 16) ISONAS Inc. - 6325 Gunpark Drive - Suite 101 - Boulder CO 80301 - UNITED STATES - - 00-18-C9 (hex) EOps Technology Limited - 0018C9 (base 16) EOps Technology Limited - Room 2001, Fairmont House, - 8 Cotton Tree Drive, Central, - Hong Kong - HONG KONG - - 00-18-CA (hex) Viprinet GmbH - 0018CA (base 16) Viprinet GmbH - Basilikastraße 3 - Bingen am Rhein 55411 - GERMANY - - 00-18-CB (hex) Tecobest Technology Limited - 0018CB (base 16) Tecobest Technology Limited - 53/F.,Block A,United Plaza, - No.5022,Bin He Road - Shenzhen Guangdong 518026 - CHINA - - 00-18-CC (hex) AXIOHM SAS - 0018CC (base 16) AXIOHM SAS - 1 RUE D'ARCUEIL - MONTROUGE 92120 - FRANCE - - 00-18-CD (hex) Erae Electronics Industry Co., Ltd - 0018CD (base 16) Erae Electronics Industry Co., Ltd - #371-51, Gasan-dong - Geumchen-gu Seoul 153-803 - KOREA, REPUBLIC OF - - 00-18-CE (hex) Dreamtech Co., Ltd - 0018CE (base 16) Dreamtech Co., Ltd - #340-5, Yang-dang Ri, Jik-san Myeon - Cheon-an si Chung-Nam 330810 - KOREA, REPUBLIC OF - - 00-18-CF (hex) Baldor Electric Company - 0018CF (base 16) Baldor Electric Company - 600 S. Zero St. - Fort Smith AR 72901 - UNITED STATES - - 00-18-D0 (hex) AtRoad, A Trimble Company - 0018D0 (base 16) AtRoad, A Trimble Company - 47071 Bayside Parkway - Fremont California 94538 - UNITED STATES - - 00-18-D1 (hex) Siemens Home & Office Comm. Devices - 0018D1 (base 16) Siemens Home & Office Comm. Devices - 4849 Alpha Rd. - Dallas Texas 75244 - UNITED STATES - - 00-18-D2 (hex) High-Gain Antennas LLC - 0018D2 (base 16) High-Gain Antennas LLC - 11679 S. Cormorant Circle - Parker CO 80134 - UNITED STATES - - 00-18-D3 (hex) TEAMCAST - 0018D3 (base 16) TEAMCAST - Centre Espace Performance - Saint Gregoire 35769 - FRANCE - - 00-18-D4 (hex) Unified Display Interface SIG - 0018D4 (base 16) Unified Display Interface SIG - 15201 SW Greenbrier Parkway - Beaverton Oregon 97006 - UNITED STATES - - 00-18-D5 (hex) REIGNCOM - 0018D5 (base 16) REIGNCOM - 14F Kamco Yanjae Tower, 949-3 - Dogok 1-dongm, Gangnam-gu - Seoul 135-739 - KOREA, REPUBLIC OF - - 00-18-D6 (hex) Swirlnet A/S - 0018D6 (base 16) Swirlnet A/S - Diplomvej 381 - Lyngby DK-2800 - DENMARK - - 00-18-D7 (hex) Javad Navigation Systems Inc. - 0018D7 (base 16) Javad Navigation Systems Inc. - 1731 Technology Drive, Suite 680 - San Jose CA 95110 - UNITED STATES - - 00-18-D8 (hex) ARCH METER Corporation - 0018D8 (base 16) ARCH METER Corporation - 4F, No.3-2, Industry E. Rd. - 9,Hsinchu Science Park - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-18-D9 (hex) Santosha Internatonal, Inc - 0018D9 (base 16) Santosha Internatonal, Inc - 3843 S. Bristol St. #242 - Santa Ana CA 92704 - UNITED STATES - - 00-18-DA (hex) AMBER wireless GmbH - 0018DA (base 16) AMBER wireless GmbH - Albin-Koebis-Str. 18 - Koeln 51147 - GERMANY - - 00-18-DB (hex) EPL Technology Ltd - 0018DB (base 16) EPL Technology Ltd - LongDong,Longgang District - ShenZhen GuangDong 518116 - CHINA - - 00-18-DC (hex) Prostar Co., Ltd. - 0018DC (base 16) Prostar Co., Ltd. - A-703 Technotown, 250-3 Hagye-dong, Nowon-gu - Seoul 139-230 - KOREA, REPUBLIC OF - - 00-18-DD (hex) Silicondust Engineering Ltd - 0018DD (base 16) Silicondust Engineering Ltd - PO Box 74-299 - Market Rd - Auckland - NEW ZEALAND - - 00-18-DE (hex) Intel Corporate - 0018DE (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-18-DF (hex) The Morey Corporation - 0018DF (base 16) The Morey Corporation - 100 Morey Drive - Woodridge IL 60517 - UNITED STATES - - 00-18-E0 (hex) ANAVEO - 0018E0 (base 16) ANAVEO - Les Carrés du parc - 10 rue des Rosiéristes - CHAMPAGNE au MONT D'OR Rhône F-69410 - FRANCE - - 00-18-E1 (hex) Verkerk Service Systemen - 0018E1 (base 16) Verkerk Service Systemen - Molenvliet 1 - Zwijndrecht Zuid-Holland NL-3335LH - NETHERLANDS - - 00-18-E2 (hex) Topdata Sistemas de Automacao Ltda - 0018E2 (base 16) Topdata Sistemas de Automacao Ltda - Rua Dr Carvalho Chaves, 662 - Curitiba PR 80.220-010 - BRAZIL - - 00-18-E3 (hex) Visualgate Systems, Inc. - 0018E3 (base 16) Visualgate Systems, Inc. - 64 Bakersfield Street - Toronto Ontario M3J 2W7 - CANADA - - 00-18-E4 (hex) YIGUANG - 0018E4 (base 16) YIGUANG - 3/FL.Industry zone,Fuxinlin,Hangcheng,Xixiang,Baoan - Shenzhen Guangdong 518126 - CHINA - - 00-18-E5 (hex) Adhoco AG - 0018E5 (base 16) Adhoco AG - Technopark - Jaegerstr. 2 - Winterthur ZH CH-8406 - SWITZERLAND - - 00-18-E6 (hex) Computer Hardware Design SIA - 0018E6 (base 16) Computer Hardware Design SIA - Dzelzavas 120i - Riga LV-1021 - LATVIA - - 00-18-E7 (hex) Cameo Communications, INC. - 0018E7 (base 16) Cameo Communications, INC. - NO.42, Sec. 6, Mincyuan E. Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-18-E8 (hex) Hacetron Corporation - 0018E8 (base 16) Hacetron Corporation - No. 542, - Sec.1, Yang-HU Rd, - Yang-Mei, Tao-Yuan, 326 - TAIWAN, PROVINCE OF CHINA - - 00-18-E9 (hex) Numata Corporation - 0018E9 (base 16) Numata Corporation - 8-2-39 nanko-higashi - Suminoe-ku - Osaka-shi Osaka-fu 559-0031 - JAPAN - - 00-18-EA (hex) Alltec GmbH - 0018EA (base 16) Alltec GmbH - An der Trave 27-31 - Selmsdorf Mecklenburg-Vorpommern 23923 - GERMANY - - 00-18-EB (hex) BroVis Wireless Networks - 0018EB (base 16) BroVis Wireless Networks - 19925 Stevens Creek Blvd - Cupertino CA 95014 - UNITED STATES - - 00-18-EC (hex) Welding Technology Corporation - 0018EC (base 16) Welding Technology Corporation - 24775 Crestview Court - Farmington Hills MI 48335 - UNITED STATES - - 00-18-ED (hex) Accutech Ultrasystems Co., Ltd. - 0018ED (base 16) Accutech Ultrasystems Co., Ltd. - 11F-4, No. 150, - CHIEN-YI ROAD, - CHUNG-HO CITY, TAIPEI HSIEN, 235 - TAIWAN, PROVINCE OF CHINA - - 00-18-EE (hex) Videology Imaging Solutions, Inc. - 0018EE (base 16) Videology Imaging Solutions, Inc. - 37 M Lark Industrial Parkway - Greenville RI 02828-3001 - UNITED STATES - - 00-18-EF (hex) Escape Communications, Inc. - 0018EF (base 16) Escape Communications, Inc. - 2615 Pacific Coast Hwy - Ste 329 - Hermosa Beach CA 90254 - UNITED STATES - - 00-18-F0 (hex) JOYTOTO Co., Ltd. - 0018F0 (base 16) JOYTOTO Co., Ltd. - 3F Sungwoo Bldg. 717-3, Sooseo-Dong - Kangnam-Gu - Seoul 135-220 - KOREA, REPUBLIC OF - - 00-18-F1 (hex) Chunichi Denshi Co.,LTD. - 0018F1 (base 16) Chunichi Denshi Co.,LTD. - 1 Denjiyama - Narumi cho Midori ku - Nagoya Aichi 458-8525 - JAPAN - - 00-18-F2 (hex) Beijing Tianyu Communication Equipment Co., Ltd - 0018F2 (base 16) Beijing Tianyu Communication Equipment Co., Ltd - 27th Floor, Tengda Plaza - Xizhimengwai Street, Haidian District - Beijing 100044 - CHINA - - 00-18-F3 (hex) ASUSTek COMPUTER INC. - 0018F3 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-18-F4 (hex) EO TECHNICS Co., Ltd. - 0018F4 (base 16) EO TECHNICS Co., Ltd. - 91, Dongpyeon-ro - Dongan-Gu - Anyang Kyeonggi-Do 431-803 - KOREA, REPUBLIC OF - - 00-18-F5 (hex) Shenzhen Streaming Video Technology Company Limited - 0018F5 (base 16) Shenzhen Streaming Video Technology Company Limited - 5/F, Block 3, Software Part No.1, Keji Middle 2 Road, - Shenzhen Hi-Tech Industrial Park - Shenzhen GaungDong 518057 - CHINA - - 00-18-F6 (hex) Thomson Telecom Belgium - 0018F6 (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - Edegem Antwerp B-2650 - BELGIUM - - 00-18-F7 (hex) Kameleon Technologies - 0018F7 (base 16) Kameleon Technologies - 217, rue St Honoré - Paris 75001 - FRANCE - - 00-18-F8 (hex) Cisco-Linksys LLC - 0018F8 (base 16) Cisco-Linksys LLC - 121 Theory Drive - Irvine CA 92612 - UNITED STATES - - 00-18-F9 (hex) VVOND, Inc. - 0018F9 (base 16) VVOND, Inc. - 3000 Bridge Parkway - Suite 102 - Redwood City CA 94065 - UNITED STATES - - 00-18-FA (hex) Yushin Precision Equipment Co.,Ltd. - 0018FA (base 16) Yushin Precision Equipment Co.,Ltd. - 11-260 KOGAHONMACHI - FUSHIMI-KU - KYOTO 612-8492 JAP - JAPAN - - 00-18-FB (hex) Compro Technology - 0018FB (base 16) Compro Technology - 3/F No 12, Alley 6, Lane 45, Pao Shin Rd - Hsintien 231 - TAIWAN, PROVINCE OF CHINA - - 00-18-FC (hex) Altec Electronic AG - 0018FC (base 16) Altec Electronic AG - Lenggenbachstrasse 3 - Fahrweid Zürich CH-8951 - SWITZERLAND - - 00-18-FD (hex) Optimal Technologies International Inc. - 0018FD (base 16) Optimal Technologies International Inc. - 12 Spanish Main Drive - PO Box F-42409/359 - Freeport GBI - BAHAMAS - - 00-18-FE (hex) Hewlett-Packard Company - 0018FE (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS060308 - Houston TX 77070 - UNITED STATES - - 00-18-FF (hex) PowerQuattro Co. - 0018FF (base 16) PowerQuattro Co. - János u. 175. - Budapest H-1161 - HUNGARY - - 00-19-00 (hex) Intelliverese - DBA Voicecom - 001900 (base 16) Intelliverese - DBA Voicecom - 5900 Windward Parkway - Suite 500 - Alpharetta Georgia 30005 - UNITED STATES - - 00-19-01 (hex) F1MEDIA - 001901 (base 16) F1MEDIA - 610, Keumkang Hightech ¥±, 138-1 Sangdaewon-Dong, Jungwon-Gu - Seongnam-Si Gyeonggi-Do 462-707 - KOREA, REPUBLIC OF - - 00-19-02 (hex) Cambridge Consultants Ltd - 001902 (base 16) Cambridge Consultants Ltd - Science Park - Milton Road - Cambridge Cambs CB4 0DW - UNITED KINGDOM - - 00-19-03 (hex) Bigfoot Networks Inc - 001903 (base 16) Bigfoot Networks Inc - 3925 West Braker Lane - Austin TX 78759 - UNITED STATES - - 00-19-04 (hex) WB Electronics Sp. z o.o. - 001904 (base 16) WB Electronics Sp. z o.o. - ul. Poznanska 129/133 - Ozarow Mazowiecki Mazowieckie 05-850 - POLAND - - 00-19-05 (hex) SCHRACK Seconet AG - 001905 (base 16) SCHRACK Seconet AG - Eibesbrunnergasse 18 - Wien Österreich 1122 - AUSTRIA - - 00-19-06 (hex) CISCO SYSTEMS, INC. - 001906 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-07 (hex) CISCO SYSTEMS, INC. - 001907 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-08 (hex) Duaxes Corporation - 001908 (base 16) Duaxes Corporation - 2-5, Kasumigaseki 3-chome, Chiyoda-ku. - Tokyo Foreign 100-6014 - JAPAN - - 00-19-09 (hex) DEVI - Danfoss A/S - 001909 (base 16) DEVI - Danfoss A/S - Ulvehavevej 61 - Vejle 7100 - DENMARK - - 00-19-0A (hex) HASWARE INC. - 00190A (base 16) HASWARE INC. - 4-12-3 HIGASHI - KUNITACHI TOKYO 186-0002 - JAPAN - - 00-19-0B (hex) Southern Vision Systems, Inc. - 00190B (base 16) Southern Vision Systems, Inc. - 8215 Madison Blvd, Suite 150 - Madison AL 35758 - UNITED STATES - - 00-19-0C (hex) Encore Electronics, Inc. - 00190C (base 16) Encore Electronics, Inc. - 16483 Old Valley Blvd. - La Puente CA 91744 - UNITED STATES - - 00-19-0D (hex) IEEE 1394c - 00190D (base 16) IEEE 1394c - c/o 1394 Trade Association - 1560 East Southlake Blvd., Suite 220 - Southlake TX 76092 - UNITED STATES - - 00-19-0E (hex) Atech Technology Co., Ltd. - 00190E (base 16) Atech Technology Co., Ltd. - 4 Fl., No. 103, Sec 2, Jiuzong Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-19-0F (hex) Advansus Corp. - 00190F (base 16) Advansus Corp. - No.5 Shing Yeh Street, Kwei Hsiang - Taoyuan 333 - TAIWAN, PROVINCE OF CHINA - - 00-19-10 (hex) Knick Elektronische Messgeraete GmbH & Co. KG - 001910 (base 16) Knick Elektronische Messgeraete GmbH & Co. KG - Beuckestraße 22 - Berlin 14163 - GERMANY - - 00-19-11 (hex) Just In Mobile Information Technologies (Shanghai) Co., Ltd. - 001911 (base 16) Just In Mobile Information Technologies (Shanghai) Co., Ltd. - 5th Floor, 2nd Area, Haiwangxing Building, 62 Xingguang Ave., N.High-Tech Park - Chongqing 401121 - CHINA - - 00-19-12 (hex) Welcat Inc - 001912 (base 16) Welcat Inc - East Tower 6F, Shinagawa Seaside, 4-12-8, Higashi Shinagawa, Shinagawa Section - Tokyo 140-0002 - JAPAN - - 00-19-13 (hex) Chuang-Yi Network Equipment Co.Ltd. - 001913 (base 16) Chuang-Yi Network Equipment Co.Ltd. - 238 TianMuShan Rd., West Lake district - HangZhou ZheJiang 310000 - CHINA - - 00-19-14 (hex) Winix Co., Ltd - 001914 (base 16) Winix Co., Ltd - 363 Angade Bldg., Yangjae-dong - Seocho-gu - Seoul 137-898 - KOREA, REPUBLIC OF - - 00-19-15 (hex) TECOM Co., Ltd. - 001915 (base 16) TECOM Co., Ltd. - 23 R&D Road 2 Science Based Industrial Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-19-16 (hex) PayTec AG - 001916 (base 16) PayTec AG - Rosengartenstrasse 3 - Zollikerberg ZH 8125 - SWITZERLAND - - 00-19-17 (hex) Posiflex Inc. - 001917 (base 16) Posiflex Inc. - 6, Wu-Chuan Road - Wu Ku - Taipei Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 00-19-18 (hex) Interactive Wear AG - 001918 (base 16) Interactive Wear AG - Petersbrunner Str. 3 - Starnberg Bavaria 82319 - GERMANY - - 00-19-19 (hex) ASTEL Inc. - 001919 (base 16) ASTEL Inc. - 59-7 Jang-dong Yusung-Gu - Daejeon Chungnam 305-343 - KOREA, REPUBLIC OF - - 00-19-1A (hex) IRLINK - 00191A (base 16) IRLINK - HanYoung B/D 6F, 4-6 - Munjeong-dong, Sonpa-ku - SEOUL 138-824 - KOREA, REPUBLIC OF - - 00-19-1B (hex) Sputnik Engineering AG - 00191B (base 16) Sputnik Engineering AG - Höheweg 85 - Biel-Bienne BE 2502 - SWITZERLAND - - 00-19-1C (hex) Sensicast Systems - 00191C (base 16) Sensicast Systems - 200 Reservoir St - Suite 100 - Needham MA 02494 - UNITED STATES - - 00-19-1D (hex) Nintendo Co., Ltd. - 00191D (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-19-1E (hex) Beyondwiz Co., Ltd. - 00191E (base 16) Beyondwiz Co., Ltd. - 3F, Daechang Bldg., - 8-2, Soonae-dong, Bundang-gu - Sungnam Kyungki-do 463-825 - KOREA, REPUBLIC OF - - 00-19-1F (hex) Microlink communications Inc. - 00191F (base 16) Microlink communications Inc. - 8F , 31 , Hsintai Road , Chupei City , Hsinchu - Chupei Taiwan 302 - TAIWAN, PROVINCE OF CHINA - - 00-19-20 (hex) KUME electric Co.,Ltd. - 001920 (base 16) KUME electric Co.,Ltd. - 4-2-24 Kitakawara - Itami-city Hyougo - JAPAN - - 00-19-21 (hex) Elitegroup Computer System Co. - 001921 (base 16) Elitegroup Computer System Co. - No.22,Alley 38,Lane 91, Sec. 1,Nei Hu Road. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-19-22 (hex) CM Comandos Lineares - 001922 (base 16) CM Comandos Lineares - Av Eng Alberto de Zagottis, 760 - Jurubatuba - São Paulo SP 04675-085 - BRAZIL - - 00-19-23 (hex) Phonex Korea Co., LTD. - 001923 (base 16) Phonex Korea Co., LTD. - 33-3, Geoyeo-Dong - Seoul Songpa-Gu 138-814 - KOREA, REPUBLIC OF - - 00-19-24 (hex) LBNL Engineering - 001924 (base 16) LBNL Engineering - 1 Cyclotron Rd. - MS46R0125 - Berkeley CA 94720 - UNITED STATES - - 00-19-25 (hex) Intelicis Corporation - 001925 (base 16) Intelicis Corporation - 4633 Old Ironsides Drive, Suite 150 - Santa Clara CA 95054 - UNITED STATES - - 00-19-26 (hex) BitsGen Co., Ltd. - 001926 (base 16) BitsGen Co., Ltd. - #502, Owner's Tower, #16-5, Sunea-dong - Bundang-gu Seongnam-si 463-825 - KOREA, REPUBLIC OF - - 00-19-27 (hex) ImCoSys Ltd - 001927 (base 16) ImCoSys Ltd - Bundesstrasse 5 - Zug ZG 6300 - SWITZERLAND - - 00-19-28 (hex) Siemens AG, Transportation Systems - 001928 (base 16) Siemens AG, Transportation Systems - Werner-von-Siemens-Straße 67 - Erlangen 91052 - GERMANY - - 00-19-29 (hex) 2M2B Montadora de Maquinas Bahia Brasil LTDA - 001929 (base 16) 2M2B Montadora de Maquinas Bahia Brasil LTDA - Rua Djalma dutra, 668, Sete Portas - Salvador Bahia 40240080 - BRAZIL - - 00-19-2A (hex) Antiope Associates - 00192A (base 16) Antiope Associates - 18 Clay Street - Fair Haven New Jersey 07704 - UNITED STATES - - 00-19-2B (hex) Aclara RF Systems Inc. - 00192B (base 16) Aclara RF Systems Inc. - 30400 Solon Road - Solon OH 44139 - UNITED STATES - - 00-19-2C (hex) ARRIS Group, Inc. - 00192C (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-19-2D (hex) Nokia Corporation - 00192D (base 16) Nokia Corporation - Rensingstraße 15 - Bochum NRW 44807 - GERMANY - - 00-19-2E (hex) Spectral Instruments, Inc. - 00192E (base 16) Spectral Instruments, Inc. - 420 N Bonita Ave - Tucson AZ 85745 - UNITED STATES - - 00-19-2F (hex) CISCO SYSTEMS, INC. - 00192F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-30 (hex) CISCO SYSTEMS, INC. - 001930 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-31 (hex) Balluff GmbH - 001931 (base 16) Balluff GmbH - Schurwaldstraße 9 - Neuhausen BW 73765 - GERMANY - - 00-19-32 (hex) Gude Analog- und Digialsysteme GmbH - 001932 (base 16) Gude Analog- und Digialsysteme GmbH - Eintrachstrasse 113 - Cologne NRW 50668 - GERMANY - - 00-19-33 (hex) Strix Systems, Inc. - 001933 (base 16) Strix Systems, Inc. - 26610 Agoura Road - Calabasas CA 91302 - UNITED STATES - - 00-19-34 (hex) TRENDON TOUCH TECHNOLOGY CORP. - 001934 (base 16) TRENDON TOUCH TECHNOLOGY CORP. - 2F No.5, Alley 22, Lane 513, Rueiguang Rd., Neihu - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-19-35 (hex) DUERR DENTAL AG - 001935 (base 16) DUERR DENTAL AG - Hoepfigheimer Strasse 17 - Bietigheim-Bissingen Baden-Wuerttemberg 74321 - GERMANY - - 00-19-36 (hex) STERLITE OPTICAL TECHNOLOGIES LIMITED - 001936 (base 16) STERLITE OPTICAL TECHNOLOGIES LIMITED - E-1,E-2,&E-3 - MIDC , WALUJ - AURANGABAD MAHARASTRA 431136 - INDIA - - 00-19-37 (hex) CommerceGuard AB - 001937 (base 16) CommerceGuard AB - Gustavslundsv 151A - BROMMA 16714 - SWEDEN - - 00-19-38 (hex) UMB Communications Co., Ltd. - 001938 (base 16) UMB Communications Co., Ltd. - 1010, 5, ACE Techno Tower, 197-22, Guro-dong, Guro-gu - Seoul 151-766 - KOREA, REPUBLIC OF - - 00-19-39 (hex) Gigamips - 001939 (base 16) Gigamips - 5th Floor, Yangjae Building, 261, Yangjae-Dong - Seocho-Gu Seoul 137-130 - KOREA, REPUBLIC OF - - 00-19-3A (hex) OESOLUTIONS - 00193A (base 16) OESOLUTIONS - Technopark, 958-3 Daechon-Dong, Buk-Gu - Gwangju Buk-Gu 500-706 - KOREA, REPUBLIC OF - - 00-19-3B (hex) Wilibox Deliberant Group LLC - 00193B (base 16) Wilibox Deliberant Group LLC - 1440 Dutch Valley Place - Suite 1155 - Atlanta GA 30324 - UNITED STATES - - 00-19-3C (hex) HighPoint Technologies Incorporated - 00193C (base 16) HighPoint Technologies Incorporated - 1161 Cadillac Court - Milpitas CA 95035 - UNITED STATES - - 00-19-3D (hex) GMC Guardian Mobility Corp. - 00193D (base 16) GMC Guardian Mobility Corp. - Suite 200 - 43 Auriga Dr. - Ottawa ON K2E 7Y8 - CANADA - - 00-19-3E (hex) ADB Broadband Italia - 00193E (base 16) ADB Broadband Italia - VIALE SARCA 222 - MILANO 20126 - ITALY - - 00-19-3F (hex) RDI technology(Shenzhen) Co.,LTD - 00193F (base 16) RDI technology(Shenzhen) Co.,LTD - Building C1&C2, Xin Tang Industrial Zone,East BaiShiXia Village, Fuyong Town, Baoan District - SHENZHEN GUANGDONG province 518103 - CHINA - - 00-19-40 (hex) Rackable Systems - 001940 (base 16) Rackable Systems - 1933 Milmont Drive - Milpitas CA 95035 - UNITED STATES - - 00-19-41 (hex) Pitney Bowes, Inc - 001941 (base 16) Pitney Bowes, Inc - 35 Waterview Drive - MSC 26-21 - Shelton CT 06484 - UNITED STATES - - 00-19-42 (hex) ON SOFTWARE INTERNATIONAL LIMITED - 001942 (base 16) ON SOFTWARE INTERNATIONAL LIMITED - 9F, NO. 17, SEC. 1, CHENG-TE RD. - TAIPEI 103 - TAIWAN, PROVINCE OF CHINA - - 00-19-43 (hex) Belden - 001943 (base 16) Belden - 793 Fort Mill Highway - Fort Mill South Carolina 29715 - UNITED STATES - - 00-19-44 (hex) Fossil Partners, L.P. - 001944 (base 16) Fossil Partners, L.P. - 2280 N. Greenville Ave. - Richardson TX 75082 - UNITED STATES - - 00-19-45 (hex) RF COncepts, LLC - 001945 (base 16) RF COncepts, LLC - 1148 Wagner Drive - Suite 202 - Sevierville TN 37862 - UNITED STATES - - 00-19-46 (hex) Cianet Industria e Comercio S/A - 001946 (base 16) Cianet Industria e Comercio S/A - rod SC401, km01 Tecnopolis/Alfama 4o. Andar - Florianopolis Santa Catarina 88030-902 - BRAZIL - - 00-19-47 (hex) Scientific Atlanta, A Cisco Company - 001947 (base 16) Scientific Atlanta, A Cisco Company - 5030 Sugarloaf Parkway - ATL 1.3.473 - Lawrenceville GA 30044 - UNITED STATES - - 00-19-48 (hex) AireSpider Networks - 001948 (base 16) AireSpider Networks - 1171 Montague Express Way - Milpitas CA 95035 - UNITED STATES - - 00-19-49 (hex) TENTEL COMTECH CO., LTD. - 001949 (base 16) TENTEL COMTECH CO., LTD. - 3/F., NO. 42, LANE 80, SEC. 3, NAN-KANG RD., - TAIPEI 115 - TAIWAN, PROVINCE OF CHINA - - 00-19-4A (hex) TESTO AG - 00194A (base 16) TESTO AG - Testo Straße 1 - Lenzkirch Baden-Württemberg 79853 - GERMANY - - 00-19-4B (hex) SAGEM COMMUNICATION - 00194B (base 16) SAGEM COMMUNICATION - 27 RUE LEBLANC - PARIS 75512 - FRANCE - - 00-19-4C (hex) Fujian Stelcom information & Technology CO.,Ltd - 00194C (base 16) Fujian Stelcom information & Technology CO.,Ltd - 4F,Building A,Start Science Park, No.68,Hongshanyuan Rd - Fuzhou Fujian 350002 - CHINA - - 00-19-4D (hex) Avago Technologies Sdn Bhd - 00194D (base 16) Avago Technologies Sdn Bhd - Bayan Lepas Free Industrial Zone - Bayan Lepas Penang 11900 - MALAYSIA - - 00-19-4E (hex) Ultra Electronics - TCS (Tactical Communication Systems) - 00194E (base 16) Ultra Electronics - TCS (Tactical Communication Systems) - 5990 Cote De Liesse - TMR Quebec H4T 1V7 - CANADA - - 00-19-4F (hex) Nokia Danmark A/S - 00194F (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-19-50 (hex) Harman Multimedia - 001950 (base 16) Harman Multimedia - 8400 Balboa Blvd. - Northridge CA 91329 - UNITED STATES - - 00-19-51 (hex) NETCONS, s.r.o. - 001951 (base 16) NETCONS, s.r.o. - Stara Vajnorska 37 - Bratislava Slovakia 831 04 - SLOVAKIA - - 00-19-52 (hex) ACOGITO Co., Ltd - 001952 (base 16) ACOGITO Co., Ltd - #501 Shinyoung Palace Tower, 246-2, Seohyun - Sungnam Kyunggi 463-824 - KOREA, REPUBLIC OF - - 00-19-53 (hex) Chainleader Communications Corp. - 001953 (base 16) Chainleader Communications Corp. - 5F, No. 400, Sec. 2 Bade Rd., - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-19-54 (hex) Leaf Corporation. - 001954 (base 16) Leaf Corporation. - Amuze 1F - Higashi Naruse 35-10 - Isehara City Kanagawa-Pref. 259-1117 - JAPAN - - 00-19-55 (hex) CISCO SYSTEMS, INC. - 001955 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-56 (hex) CISCO SYSTEMS, INC. - 001956 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-57 (hex) Saafnet Canada Inc. - 001957 (base 16) Saafnet Canada Inc. - 107-1089 East Kent Ave (N) - Vancouver BC V5X 4V9 - CANADA - - 00-19-58 (hex) Bluetooth SIG, Inc. - 001958 (base 16) Bluetooth SIG, Inc. - 5209 Lake Washington Blvd NE - Suite 350 - Kirkland WA 98033 - UNITED STATES - - 00-19-59 (hex) Staccato Communications Inc. - 001959 (base 16) Staccato Communications Inc. - 6195 Lusk Blvd. - San Diego CA 92121 - UNITED STATES - - 00-19-5A (hex) Jenaer Antriebstechnik GmbH - 00195A (base 16) Jenaer Antriebstechnik GmbH - Buchaer Strasse 1 - Jena Thueringen 07745 - GERMANY - - 00-19-5B (hex) D-Link Corporation - 00195B (base 16) D-Link Corporation - NO.289, Sinhu 3rd Rd., - Neihu District, Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-19-5C (hex) Innotech Corporation - 00195C (base 16) Innotech Corporation - 3-17-6 - Shin-Yokohama, Kohoku-ku - Yokohama Kanagawa 222-8580 - JAPAN - - 00-19-5D (hex) ShenZhen XinHuaTong Opto Electronics Co.,Ltd - 00195D (base 16) ShenZhen XinHuaTong Opto Electronics Co.,Ltd - 5F,BaodaZhou,Shancheng Industrial Zone,BaoAn District - ShenZhen GuangDong 518108 - CHINA - - 00-19-5E (hex) ARRIS Group, Inc. - 00195E (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-19-5F (hex) Valemount Networks Corporation - 00195F (base 16) Valemount Networks Corporation - 1201- 5th Ave - PO Box 687 - Valemount BC V0E2Z0 - CANADA - - 00-19-60 (hex) DoCoMo Systems, Inc. - 001960 (base 16) DoCoMo Systems, Inc. - Meguro Techno Bldg. 2nd Floor - 4-31-18 Nishi-Gotanda - Shinagawa-ku Tokyo 141-0031 - JAPAN - - 00-19-61 (hex) Blaupunkt Embedded Systems GmbH - 001961 (base 16) Blaupunkt Embedded Systems GmbH - Bahnhofsstrasse 16 - Schlitz 36110 - GERMANY - - 00-19-62 (hex) Commerciant, LP - 001962 (base 16) Commerciant, LP - 2901 Wilcrest - Suite 250 - Houston Texas 77042 - UNITED STATES - - 00-19-63 (hex) Sony Ericsson Mobile Communications AB - 001963 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SkÃ¥ne 221 88 - SWEDEN - - 00-19-64 (hex) Doorking Inc. - 001964 (base 16) Doorking Inc. - 120 Glasgow St. - Inglewood CA. 90301 - UNITED STATES - - 00-19-65 (hex) YuHua TelTech (ShangHai) Co., Ltd. - 001965 (base 16) YuHua TelTech (ShangHai) Co., Ltd. - YuHua R&D Building,27 xin jin qiao road, - Pudong, - SHANGHAI 201206 - CHINA - - 00-19-66 (hex) Asiarock Technology Limited - 001966 (base 16) Asiarock Technology Limited - P.O. Box957, Offshore Incorporations Centre - Road Town Tortola - VIRGIN ISLANDS, BRITISH - - 00-19-67 (hex) TELDAT Sp.J. - 001967 (base 16) TELDAT Sp.J. - Kijowska 44 - NIP 554 19 26 042 - Bydgoszcz woj. kujawsko-pomorskie 85-703 - POLAND - - 00-19-68 (hex) Digital Video Networks(Shanghai) CO. LTD. - 001968 (base 16) Digital Video Networks(Shanghai) CO. LTD. - 9th Floor,Hechuan Building, No.1026 YiShan Rd - Shanghai 201103 - CHINA - - 00-19-69 (hex) Nortel - 001969 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-19-6A (hex) MikroM GmbH - 00196A (base 16) MikroM GmbH - Dovestraße 1 - Berlin 10587 - GERMANY - - 00-19-6B (hex) Danpex Corporation - 00196B (base 16) Danpex Corporation - 2114 Ringwood Avenue - San Jose California 95131 - UNITED STATES - - 00-19-6C (hex) ETROVISION TECHNOLOGY - 00196C (base 16) ETROVISION TECHNOLOGY - 2F, 19-5 San Chung Rd., - Block C, Nan Kang Software Park, Nan Kang District, - TAIPEI 115 - TAIWAN, PROVINCE OF CHINA - - 00-19-6D (hex) Raybit Systems Korea, Inc - 00196D (base 16) Raybit Systems Korea, Inc - Dream Tower 1221 - 923-14, Mokdong, Yangchunku - Seoul 158-718 - KOREA, REPUBLIC OF - - 00-19-6E (hex) Metacom (Pty) Ltd. - 00196E (base 16) Metacom (Pty) Ltd. - 6 Ndabeni Business Park - Inyoni Str, Ndabeni - Cape Town Western Cape 7405 - SOUTH AFRICA - - 00-19-6F (hex) SensoPart GmbH - 00196F (base 16) SensoPart GmbH - Am Wiedenbach 1 - Wieden Baden-Württemberg D-79695 - GERMANY - - 00-19-70 (hex) Z-Com, Inc. - 001970 (base 16) Z-Com, Inc. - 7F-2, NO.9, PROSPERITY 1ST RD. - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-19-71 (hex) Guangzhou Unicomp Technology Co.,Ltd - 001971 (base 16) Guangzhou Unicomp Technology Co.,Ltd - 7/F,North Tower,Jinshan Building.No.248 - Rd Wushan, Tianhe District - Guangzhou Guangdong 510630 - CHINA - - 00-19-72 (hex) Plexus (Xiamen) Co.,ltd - 001972 (base 16) Plexus (Xiamen) Co.,ltd - No.6 Xiangxing 2 Road - Xiangyu Free Trade Zone - Xiamen Fujian 361006 - CHINA - - 00-19-73 (hex) Zeugma Systems - 001973 (base 16) Zeugma Systems - Suite 250 - 13571 Commerce Parkway - Richmond BC V6V 2R2 - CANADA - - 00-19-74 (hex) AboCom Systems, Inc. - 001974 (base 16) AboCom Systems, Inc. - 1F , No. 21, Yanfa 2nd Rd., SBIP - Hsinchu City Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-19-75 (hex) Beijing Huisen networks technology Inc - 001975 (base 16) Beijing Huisen networks technology Inc - Jia#2 of Xili of Baiyun road,Xicheng district - Beijing 100045 - CHINA - - 00-19-76 (hex) Xipher Technologies, LLC - 001976 (base 16) Xipher Technologies, LLC - 156 River Road - Willington CT 06279 - UNITED STATES - - 00-19-77 (hex) Aerohive Networks, Inc. - 001977 (base 16) Aerohive Networks, Inc. - 3150-C Coronado Drive - Santa Clara CA 95054 - UNITED STATES - - 00-19-78 (hex) Datum Systems, Inc. - 001978 (base 16) Datum Systems, Inc. - 3666 Tiffani Ct. - Santa Cruz CA 95065 - UNITED STATES - - 00-19-79 (hex) Nokia Danmark A/S - 001979 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-19-7A (hex) MAZeT GmbH - 00197A (base 16) MAZeT GmbH - Goeschwitzer Str. 32 - Jena D-07745 - GERMANY - - 00-19-7B (hex) Picotest Corp. - 00197B (base 16) Picotest Corp. - 8F-1, 286-9, Hsin-Ya Rd., 80673 - Kaohsiung 80673 - TAIWAN, PROVINCE OF CHINA - - 00-19-7C (hex) Riedel Communications GmbH - 00197C (base 16) Riedel Communications GmbH - Uellendahler Str. 353 - Wuppertal NRW 42109 - GERMANY - - 00-19-7D (hex) Hon Hai Precision Ind. Co., Ltd - 00197D (base 16) Hon Hai Precision Ind. Co., Ltd - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-19-7E (hex) Hon Hai Precision Ind. Co., Ltd - 00197E (base 16) Hon Hai Precision Ind. Co., Ltd - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-19-7F (hex) PLANTRONICS, INC. - 00197F (base 16) PLANTRONICS, INC. - 345 ENCINAL STREET - SANTA CRUZ CALIFORNIA 95060 - UNITED STATES - - 00-19-80 (hex) Gridpoint Systems - 001980 (base 16) Gridpoint Systems - 4043 Carling Avenue, Suite 200 - Ottawa Ontario K2K 2A3 - CANADA - - 00-19-81 (hex) Vivox Inc - 001981 (base 16) Vivox Inc - 40 Speen Street - Suite 402 - Framingham MA 01701 - UNITED STATES - - 00-19-82 (hex) SmarDTV - 001982 (base 16) SmarDTV - 531 Avenue du Serpolet - ZE Athélia 2 - La Ciotat France 13 704 - FRANCE - - 00-19-83 (hex) CCT R&D Limited - 001983 (base 16) CCT R&D Limited - 18/F CCT Telecom Building - 11 Wo Shing Street - Fotan, Shatin N.T. 0000 - HONG KONG - - 00-19-84 (hex) ESTIC Corporation - 001984 (base 16) ESTIC Corporation - 2-5-9 Hashibahigashino-cho - Moriguchi Osaka 570-0031 - JAPAN - - 00-19-85 (hex) IT Watchdogs, Inc - 001985 (base 16) IT Watchdogs, Inc - 12885 Research, Suite 210B - Austin TX 78750 - UNITED STATES - - 00-19-86 (hex) Cheng Hongjian - 001986 (base 16) Cheng Hongjian - Rm.2305B.Sege Plaza,Huaqiang North Rd., - Futian - Shenzhen Guangdong 518057 - CHINA - - 00-19-87 (hex) Panasonic Mobile Communications Co., Ltd. - 001987 (base 16) Panasonic Mobile Communications Co., Ltd. - 600 Saedo-cho, Tsuzuki-ku, - Yokohama City Kanagawa Prefecture 224-8539 - JAPAN - - 00-19-88 (hex) Wi2Wi, Inc - 001988 (base 16) Wi2Wi, Inc - 2107 N. 1st Street - Suite 540 - San Jose CA 95131 - UNITED STATES - - 00-19-89 (hex) Sonitrol Corporation - 001989 (base 16) Sonitrol Corporation - 1707 Orlando Central Pkwy. - Suite 500 - Orlando FL 32809 - UNITED STATES - - 00-19-8A (hex) Northrop Grumman Systems Corp. - 00198A (base 16) Northrop Grumman Systems Corp. - 7055 Troy Hill Drive - Elkridge Maryland 21075 - UNITED STATES - - 00-19-8B (hex) Novera Optics Korea, Inc. - 00198B (base 16) Novera Optics Korea, Inc. - 463-1 Jeon Min Dong Yuseong Gu - Deajeon 305-811 - KOREA, REPUBLIC OF - - 00-19-8C (hex) iXSea - 00198C (base 16) iXSea - 55 av auguste Renoir - Marly le Roi 78160 - FRANCE - - 00-19-8D (hex) Ocean Optics, Inc. - 00198D (base 16) Ocean Optics, Inc. - 830 Douglas Ave - Dunedin FL 34698 - UNITED STATES - - 00-19-8E (hex) Oticon A/S - 00198E (base 16) Oticon A/S - Kongebakken 9 - Smørum 2765 - DENMARK - - 00-19-8F (hex) Alcatel Bell N.V. - 00198F (base 16) Alcatel Bell N.V. - Copernicuslaan 50 - Antwerp B-2018 - BELGIUM - - 00-19-90 (hex) ELM DATA Co., Ltd. - 001990 (base 16) ELM DATA Co., Ltd. - 2-15 TECHNO-PARK 1-CHOME - SHIMONOPPORO, ATSUBETSU-KU - SAPPORO HOKKAIDO 004-0015 - JAPAN - - 00-19-91 (hex) avinfo - 001991 (base 16) avinfo - Jiahuiyuan 703,Huaao Center,31# Zizhuyuan Road, - Haidian District - Beijing 100089 - CHINA - - 00-19-92 (hex) ADTRAN INC. - 001992 (base 16) ADTRAN INC. - 901 Explorer Blvd. - Huntsville AL 35806-2807 - UNITED STATES - - 00-19-93 (hex) Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea - 001993 (base 16) Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea - No. 8 Jianye Road - Changshu Jiangsu 215500 - CHINA - - 00-19-94 (hex) Jorjin Technologies Inc. - 001994 (base 16) Jorjin Technologies Inc. - 5F, No.28, Lane141, Sing-ai Rd. - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-19-95 (hex) Jurong Hi-Tech (Suzhou)Co.ltd - 001995 (base 16) Jurong Hi-Tech (Suzhou)Co.ltd - 275,Xing Long Street, Suzhou Indudtrial Park - Suzhou Jiang Su 215021 - CHINA - - 00-19-96 (hex) TurboChef Technologies Inc. - 001996 (base 16) TurboChef Technologies Inc. - 4240 International Parkway - Suite 105 - Carrollton Texas 75007 - UNITED STATES - - 00-19-97 (hex) Soft Device Sdn Bhd - 001997 (base 16) Soft Device Sdn Bhd - 67-2 Jalan 2/27F - KLSC Wangsa Maju - Kuala Lumpur WP 53300 - MALAYSIA - - 00-19-98 (hex) SATO CORPORATION - 001998 (base 16) SATO CORPORATION - 1-207,ONARI-CHO, - OMIYA-KU - SAITAMA-SHI SAITAMA 330-0852 - JAPAN - - 00-19-99 (hex) Fujitsu Technology Solutions - 001999 (base 16) Fujitsu Technology Solutions - Buergermeister-Ulrich-Strasse 100 - Augsburg 86199 - GERMANY - - 00-19-9A (hex) EDO-EVI - 00199A (base 16) EDO-EVI - 7065 Columbia Gateway Dr. - Columbia MD 21046 - UNITED STATES - - 00-19-9B (hex) Diversified Technical Systems, Inc. - 00199B (base 16) Diversified Technical Systems, Inc. - 909 Electric Avenue - Suite 206 - Seal Beach California 90740 - UNITED STATES - - 00-19-9C (hex) CTRING - 00199C (base 16) CTRING - #514, World Meridian Venture Center II - Gasna-dong - Keumcheon-gu Seoul 153-803 - KOREA, REPUBLIC OF - - 00-19-9D (hex) VIZIO, Inc. - 00199D (base 16) VIZIO, Inc. - 39 Tesla - Irvine CA 92618 - UNITED STATES - - 00-19-9E (hex) Nifty - 00199E (base 16) Nifty - miwa4-2-22-105 - Nagano 3800803 - JAPAN - - 00-19-9F (hex) DKT A/S - 00199F (base 16) DKT A/S - Fanoevej 6 - Kr. Saaby DK-4060 - DENMARK - - 00-19-A0 (hex) NIHON DATA SYSTENS, INC. - 0019A0 (base 16) NIHON DATA SYSTENS, INC. - 6-9, Koyo-cho naka - Higashinada-ku - Kobe-shi Hyogo 658-0032 - JAPAN - - 00-19-A1 (hex) LG INFORMATION & COMM. - 0019A1 (base 16) LG INFORMATION & COMM. - 60-39,Kasan-dong,Kumchon-ku - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-19-A2 (hex) ORDYN TECHNOLOGIES - 0019A2 (base 16) ORDYN TECHNOLOGIES - Ozone Manay Tech Park, - 2nd Floor, Tower B, Begur Hobli, Hongasandra, Hosur Road, - Bangalore 560 068 - INDIA - - 00-19-A3 (hex) asteel electronique atlantique - 0019A3 (base 16) asteel electronique atlantique - za de la lande de saint jean - bp 90111 - sainte marie de redon 35600 - FRANCE - - 00-19-A4 (hex) Austar Technology (hang zhou) Co.,Ltd - 0019A4 (base 16) Austar Technology (hang zhou) Co.,Ltd - 7-402,West Lake Software Part - No 1,Jiagong Rd. - Hang Zhou Zhe Jiang 310012 - CHINA - - 00-19-A5 (hex) RadarFind Corporation - 0019A5 (base 16) RadarFind Corporation - 2100 Gateway Centre Blvd., Suite 150 - Morrisville NC 27560 - UNITED STATES - - 00-19-A6 (hex) ARRIS Group, Inc. - 0019A6 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-19-A7 (hex) ITU-T - 0019A7 (base 16) ITU-T - Place des Nations - Geneva 20 CH-1211 - SWITZERLAND - - 00-19-A8 (hex) WiQuest Communications - 0019A8 (base 16) WiQuest Communications - 915 Enterprise Blvd. - Suite 200 - Allen Texas 75013 - UNITED STATES - - 00-19-A9 (hex) CISCO SYSTEMS, INC. - 0019A9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-AA (hex) CISCO SYSTEMS, INC. - 0019AA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-AB (hex) Raycom CO ., LTD - 0019AB (base 16) Raycom CO ., LTD - A,3-4/FL, Building 1,27 Chuangxin Road, - Changping Science Park - Beijing 102200 - CHINA - - 00-19-AC (hex) GSP SYSTEMS Inc. - 0019AC (base 16) GSP SYSTEMS Inc. - 13FL, 101 Dong, Chunui Techno Park 1, - 200-1, Chunui-Dong, Wonmi-GU, - Bucheon-City Gyeonggi-Do 420-857 - KOREA, REPUBLIC OF - - 00-19-AD (hex) BOBST SA - 0019AD (base 16) BOBST SA - rte des flumeaux 50 - Case Postale 1001 Lausanne - PRILLY VD 1008 - SWITZERLAND - - 00-19-AE (hex) Hopling Technologies b.v. - 0019AE (base 16) Hopling Technologies b.v. - Camerastraat 10 - Almere Flevoland 1322 BC - NETHERLANDS - - 00-19-AF (hex) Rigol Technologies, Inc. - 0019AF (base 16) Rigol Technologies, Inc. - No. 156 Cai He Village, Sha He Town - Chang Ping District - Beijing 102206 - CHINA - - 00-19-B0 (hex) HanYang System - 0019B0 (base 16) HanYang System - 701Ho, Kofomo Techno Center II, 1289-5 - Jungwang-Dong - Shihung-Shi Kyunggi-Do 429-850 - KOREA, REPUBLIC OF - - 00-19-B1 (hex) Arrow7 Corporation - 0019B1 (base 16) Arrow7 Corporation - Kamijima 3-27-7 - Hamamatsu Shizuoka 433-8122 - JAPAN - - 00-19-B2 (hex) XYnetsoft Co.,Ltd - 0019B2 (base 16) XYnetsoft Co.,Ltd - NO.158Zhenyu Street High Industries Development area - ChangChun JiLin 130000 - CHINA - - 00-19-B3 (hex) Stanford Research Systems - 0019B3 (base 16) Stanford Research Systems - 1290-D Reamwood Ave - Sunnyvale CA 94089 - UNITED STATES - - 00-19-B4 (hex) Intellio Ltd - 0019B4 (base 16) Intellio Ltd - Gyarmat u. 99/B - Budapest 1147 - HUNGARY - - 00-19-B5 (hex) Famar Fueguina S.A. - 0019B5 (base 16) Famar Fueguina S.A. - Rodney 70 - Buenos Aires 1427 - ARGENTINA - - 00-19-B6 (hex) Euro Emme s.r.l. - 0019B6 (base 16) Euro Emme s.r.l. - Via Belvedere, 24 - Galliate Lombardo Varese 21020 - ITALY - - 00-19-B7 (hex) Nokia Danmark A/S - 0019B7 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-19-B8 (hex) Boundary Devices - 0019B8 (base 16) Boundary Devices - 7200 W. Oakland - Chandler AZ 85226 - UNITED STATES - - 00-19-B9 (hex) Dell Inc. - 0019B9 (base 16) Dell Inc. - One Dell Way - MS 8545 - Round Rock TX 78682 - UNITED STATES - - 00-19-BA (hex) Paradox Security Systems Ltd - 0019BA (base 16) Paradox Security Systems Ltd - 780 Industrial Blvd - St-Eustache Quebec J7R 5V3 - CANADA - - 00-19-BB (hex) Hewlett-Packard Company - 0019BB (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS060308 - Houston TX 77070 - UNITED STATES - - 00-19-BC (hex) ELECTRO CHANCE SRL - 0019BC (base 16) ELECTRO CHANCE SRL - CARHUE 3179 - AV. EVA PERON 7049 - CAPITAL FEDERAL BUENOS AIRES 1440 - ARGENTINA - - 00-19-BD (hex) New Media Life - 0019BD (base 16) New Media Life - Hea Ju Bild, 5F, 837-7, Yeoksam-dong - Kangnam-gu Seoul 135-080 - KOREA, REPUBLIC OF - - 00-19-BE (hex) Altai Technologies Limited - 0019BE (base 16) Altai Technologies Limited - 2/F, East Wing, Lakeside 2, 10 Science Park West Avenue, - Hong Kong Science Park - Shatin New Territories - HONG KONG - - 00-19-BF (hex) Citiway technology Co.,ltd - 0019BF (base 16) Citiway technology Co.,ltd - No.2 Building,Jia 32,Beiheyan Avenue,East City - Peijing 100006 - CHINA - - 00-19-C0 (hex) ARRIS Group, Inc. - 0019C0 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-19-C1 (hex) Alps Electric Co., Ltd - 0019C1 (base 16) Alps Electric Co., Ltd - 1-2-1, Okinouchi, - Soma-city Fukushima-pref. 976-8501 - JAPAN - - 00-19-C2 (hex) Equustek Solutions, Inc. - 0019C2 (base 16) Equustek Solutions, Inc. - #286 - 5489 Byrne Road, - Burnaby BC V5J 3J1 - CANADA - - 00-19-C3 (hex) Qualitrol - 0019C3 (base 16) Qualitrol - Wildflower Way - Apollo Road - Belfast Co. Antrim BT12 6TA - UNITED KINGDOM - - 00-19-C4 (hex) Infocrypt Inc. - 0019C4 (base 16) Infocrypt Inc. - 711, BYUCKSAN DIGITAL VALLEY 1 212-16, - Guro-gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-19-C5 (hex) SONY Computer Entertainment inc, - 0019C5 (base 16) SONY Computer Entertainment inc, - 6-21,2Chome - Minami-Aoyama - Minato-ku Tokyo 107-0062 - JAPAN - - 00-19-C6 (hex) ZTE Corporation - 0019C6 (base 16) ZTE Corporation - Technology Management Department, - 12/F., ZTE R&D Building, Kejinan Road - Shenzhen Guangdong 518057 - CHINA - - 00-19-C7 (hex) Cambridge Industries(Group) Co.,Ltd. - 0019C7 (base 16) Cambridge Industries(Group) Co.,Ltd. - Room 309,333 Hong Qiao Road - Shanghai 200030 - CHINA - - 00-19-C8 (hex) AnyDATA Corporation - 0019C8 (base 16) AnyDATA Corporation - 18902 Bardeen Ave. - Irvine CA 91612 - UNITED STATES - - 00-19-C9 (hex) S&C ELECTRIC COMPANY - 0019C9 (base 16) S&C ELECTRIC COMPANY - 1135 ATLANTIC AVE - ALAMEDA CA 94501 - UNITED STATES - - 00-19-CA (hex) Broadata Communications, Inc - 0019CA (base 16) Broadata Communications, Inc - 2545 W 237th St Ste K - Torrance Ca 90505 - UNITED STATES - - 00-19-CB (hex) ZyXEL Communications Corporation - 0019CB (base 16) ZyXEL Communications Corporation - No. 6, Innovation Road II - Hsinchu Science Park, Hsinchu 300 - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-19-CC (hex) RCG (HK) Ltd - 0019CC (base 16) RCG (HK) Ltd - 9/F., Core C, Cyberport 3 - 100 Cyberport Rd - HONG KONG - - 00-19-CD (hex) Chengdu ethercom information technology Ltd. - 0019CD (base 16) Chengdu ethercom information technology Ltd. - South Extension of Tianfu Wide Road No.7 department room 201 - Chengdu Sichuan 610041 - CHINA - - 00-19-CE (hex) Progressive Gaming International - 0019CE (base 16) Progressive Gaming International - 920 Pilot Road - Las Vegas NV 89119 - UNITED STATES - - 00-19-CF (hex) SALICRU, S.A. - 0019CF (base 16) SALICRU, S.A. - Av. Serra , 100 - Sta.Ma.Palautordera Barcelona 08460 - SPAIN - - 00-19-D0 (hex) Cathexis - 0019D0 (base 16) Cathexis - PO Box 1091 - Umhlanga Rocks - Durban KwaZulu Natal 4320 - SOUTH AFRICA - - 00-19-D1 (hex) Intel Corporate - 0019D1 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-19-D2 (hex) Intel Corporate - 0019D2 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-19-D3 (hex) TRAK Microwave - 0019D3 (base 16) TRAK Microwave - 4726 Eisenhower Blvd - Tampa FL 33634 - UNITED STATES - - 00-19-D4 (hex) ICX Technologies - 0019D4 (base 16) ICX Technologies - 3440 Francis-Hughes - Suite 120 - Laval Quebec H7L 5A9 - CANADA - - 00-19-D5 (hex) IP Innovations, Inc. - 0019D5 (base 16) IP Innovations, Inc. - 1517 146th Ave - Dorr MI 49323 - UNITED STATES - - 00-19-D6 (hex) LS Cable and System Ltd. - 0019D6 (base 16) LS Cable and System Ltd. - 12F LS Tower, 1026-6, Hogey-dong - Anyang-si Gyeonggi-do 431-080 - KOREA, REPUBLIC OF - - 00-19-D7 (hex) FORTUNETEK CO., LTD - 0019D7 (base 16) FORTUNETEK CO., LTD - 12F, No. 75, Sec 1, Chongqing S. Rd., - Zhongzheng District - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-19-D8 (hex) MAXFOR - 0019D8 (base 16) MAXFOR - #E 809, Bundang, Techno-Park - Yatap-Dong, Bungdang-Gu - Seongnam-City Gyeonggi-Do 463-760 - KOREA, REPUBLIC OF - - 00-19-D9 (hex) Zeutschel GmbH - 0019D9 (base 16) Zeutschel GmbH - Heerweg 2 - Tübingen-Hirschau BW D-72070 - GERMANY - - 00-19-DA (hex) Welltrans O&E Technology Co. , Ltd. - 0019DA (base 16) Welltrans O&E Technology Co. , Ltd. - the 3rd Floor, building C-D, Hi-tech Digital Harbor, Guandong Industrial Park - Wuhan Hubei 430074 - CHINA - - 00-19-DB (hex) MICRO-STAR INTERNATIONAL CO., LTD. - 0019DB (base 16) MICRO-STAR INTERNATIONAL CO., LTD. - NO. 69, LI-DE ST., JUNG-HE CITY - TAIPEI HSIEN 235 - TUVALU - - 00-19-DC (hex) ENENSYS Technologies - 0019DC (base 16) ENENSYS Technologies - Le Germanium - 80 Avenue des buttes de Coësmes - RENNES Brittany 35700 - FRANCE - - 00-19-DD (hex) FEI-Zyfer, Inc. - 0019DD (base 16) FEI-Zyfer, Inc. - 1515 S. Manchester - Anaheim CA 92802 - UNITED STATES - - 00-19-DE (hex) MOBITEK - 0019DE (base 16) MOBITEK - 5F,No.60,Lane 321,Yang-Kwang Street - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-19-DF (hex) Thomson Inc. - 0019DF (base 16) Thomson Inc. - 101 West 103rd Street - Indianapolis IN 46290-1102 - UNITED STATES - - 00-19-E0 (hex) TP-LINK Technologies Co., Ltd. - 0019E0 (base 16) TP-LINK Technologies Co., Ltd. - South Building, No.5 Keyuan Road - Central Zone, Science & Technology Park - Nanshan Shenzhen 518057 - CHINA - - 00-19-E1 (hex) Nortel - 0019E1 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-19-E2 (hex) Juniper Networks - 0019E2 (base 16) Juniper Networks - 1194 N. Mathilda Ave. - Sunnyvale CA 94089 - UNITED STATES - - 00-19-E3 (hex) Apple - 0019E3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-19-E4 (hex) 2Wire, Inc - 0019E4 (base 16) 2Wire, Inc - 1704 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-19-E5 (hex) Lynx Studio Technology, Inc. - 0019E5 (base 16) Lynx Studio Technology, Inc. - 1540 Barton Rd # 268 - Redlands CA 92373 - UNITED STATES - - 00-19-E6 (hex) TOYO MEDIC CO.,LTD. - 0019E6 (base 16) TOYO MEDIC CO.,LTD. - 1-17-22 Kitahorie, Nishi-ku - Osaka 550-0014 - JAPAN - - 00-19-E7 (hex) CISCO SYSTEMS, INC. - 0019E7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-E8 (hex) CISCO SYSTEMS, INC. - 0019E8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-19-E9 (hex) S-Information Technolgy, Co., Ltd. - 0019E9 (base 16) S-Information Technolgy, Co., Ltd. - Sungwoo Bldg, 717-3 Suseo-dong, - Gangnam-gu, - Seoul 135-884 - KOREA, REPUBLIC OF - - 00-19-EA (hex) TeraMage Technologies Co., Ltd. - 0019EA (base 16) TeraMage Technologies Co., Ltd. - Golden Land Building Suite 907 - 32 Liang Ma Bridge Road - Beijing 100016 - CHINA - - 00-19-EB (hex) Pyronix Ltd - 0019EB (base 16) Pyronix Ltd - Braithwell Way - Hellaby - Rotherham South Yorkshire S66 8QY - UNITED KINGDOM - - 00-19-EC (hex) Sagamore Systems, Inc. - 0019EC (base 16) Sagamore Systems, Inc. - 55 Middlesex Street - Suite 217 - North Chelmsford MA 01863 - UNITED STATES - - 00-19-ED (hex) Axesstel Inc. - 0019ED (base 16) Axesstel Inc. - 6815 Flanders Sr. - Ste 210 - San Diego CA 92121 - UNITED STATES - - 00-19-EE (hex) CARLO GAVAZZI CONTROLS SPA-Controls Division - 0019EE (base 16) CARLO GAVAZZI CONTROLS SPA-Controls Division - Via Safforze 8 - BELLUNO BL I-32100 - ITALY - - 00-19-EF (hex) SHENZHEN LINNKING ELECTRONICS CO.,LTD - 0019EF (base 16) SHENZHEN LINNKING ELECTRONICS CO.,LTD - Room 901,B Block,Qinghua Information Center Hi-tec park North District,Nanshan District,Shenzhen - shenzhen guangdong 518057 - CHINA - - 00-19-F0 (hex) UNIONMAN TECHNOLOGY CO.,LTD - 0019F0 (base 16) UNIONMAN TECHNOLOGY CO.,LTD - 18F, HUAYANG TOWER,YANDAYI ROAD - HUIZHOU GUANGDONG 516007 - CHINA - - 00-19-F1 (hex) Star Communication Network Technology Co.,Ltd - 0019F1 (base 16) Star Communication Network Technology Co.,Ltd - 10/F,Tower B,SOHO New Town,No.88 jianguoRoad,Chaoyang District - Beijing 100022 - CHINA - - 00-19-F2 (hex) Teradyne K.K. - 0019F2 (base 16) Teradyne K.K. - 272-13, Heisei, Takaono - Ozu-machi - Kikuchi-gun Kumamoto 869-1232 - JAPAN - - 00-19-F3 (hex) Cetis, Inc - 0019F3 (base 16) Cetis, Inc - 5025 Galley Rd - Colorado Springs CO 80915 - UNITED STATES - - 00-19-F4 (hex) Convergens Oy Ltd - 0019F4 (base 16) Convergens Oy Ltd - Westendintie 99 B - Espoo Uusimaa FIN-02160 - FINLAND - - 00-19-F5 (hex) Imagination Technologies Ltd - 0019F5 (base 16) Imagination Technologies Ltd - Zurich House - Canal Wharf - Leeds West Yorkshire LS11 5DB - UNITED KINGDOM - - 00-19-F6 (hex) Acconet (PTE) Ltd - 0019F6 (base 16) Acconet (PTE) Ltd - No. 16 Ayer Rajah Crescent - # 03-03 - Singapore 139965 - SINGAPORE - - 00-19-F7 (hex) Onset Computer Corporation - 0019F7 (base 16) Onset Computer Corporation - P.O. Box 3450 - Pocasset MA 02559 - UNITED STATES - - 00-19-F8 (hex) Embedded Systems Design, Inc. - 0019F8 (base 16) Embedded Systems Design, Inc. - 6810 Deerpath Road - Suite 300 - Elkridge MD 21075 - UNITED STATES - - 00-19-F9 (hex) TDK-Lambda - 0019F9 (base 16) TDK-Lambda - 405 Essex Road - Neptune NJ 07753 - UNITED STATES - - 00-19-FA (hex) Cable Vision Electronics CO., LTD. - 0019FA (base 16) Cable Vision Electronics CO., LTD. - 12F-3, No.16, Chien Pa Rd. - Chung Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-19-FB (hex) BSkyB Ltd - 0019FB (base 16) BSkyB Ltd - 130 KINGS ROAD - BRENTWOOD ESSEX CM14 4EQ - UNITED KINGDOM - - 00-19-FC (hex) PT. Ufoakses Sukses Luarbiasa - 0019FC (base 16) PT. Ufoakses Sukses Luarbiasa - Jl. Sultan Hasanudin No. 41 - Kebayoran Baru - Jakarta Selatan DKI Jakarta 12160 - INDONESIA - - 00-19-FD (hex) Nintendo Co., Ltd. - 0019FD (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-19-FE (hex) SHENZHEN SEECOMM TECHNOLOGY CO.,LTD. - 0019FE (base 16) SHENZHEN SEECOMM TECHNOLOGY CO.,LTD. - Room 609,404Yannan Road - ShenZhen Guangdong 518031 - CHINA - - 00-19-FF (hex) Finnzymes - 0019FF (base 16) Finnzymes - 800 West Cummings Park - Suite 5550 - Woburn MA 01801 - UNITED STATES - - 00-1A-00 (hex) MATRIX INC. - 001A00 (base 16) MATRIX INC. - AS bld.3-13-20 - Nishi-Temma Kita-Ku - Osaka 530-0047 - JAPAN - - 00-1A-01 (hex) Smiths Medical - 001A01 (base 16) Smiths Medical - 4350 Rivergreen Parkway - Suite 200 - Duluth GA 30096 - UNITED STATES - - 00-1A-02 (hex) SECURE CARE PRODUCTS, INC - 001A02 (base 16) SECURE CARE PRODUCTS, INC - 39 CHENELL DRIVE - CONCORD NH 03301 - UNITED STATES - - 00-1A-03 (hex) Angel Electronics Co., Ltd. - 001A03 (base 16) Angel Electronics Co., Ltd. - 17, Lane 134, Shou Shan Road, Tai Shan, - Taipei 243 - TAIWAN, PROVINCE OF CHINA - - 00-1A-04 (hex) Interay Solutions BV - 001A04 (base 16) Interay Solutions BV - Mr. W.M. Oppedijk van Veenweg 8 - BURGUM Friesland 9251 GA - NETHERLANDS - - 00-1A-05 (hex) OPTIBASE LTD - 001A05 (base 16) OPTIBASE LTD - 7 Shankar St. - Herzliya ISRAEL 46120 - ISRAEL - - 00-1A-06 (hex) OpVista, Inc. - 001A06 (base 16) OpVista, Inc. - 870 North McCarthy Blvd. - Milpitas California 95035 - UNITED STATES - - 00-1A-07 (hex) Arecont Vision - 001A07 (base 16) Arecont Vision - 2400 N. Lincoln Ave - Altadena CA 91001 - UNITED STATES - - 00-1A-08 (hex) Simoco Ltd. - 001A08 (base 16) Simoco Ltd. - Field House - Uttoxeter Old Road - Derby DE1 1NH - UNITED KINGDOM - - 00-1A-09 (hex) Wayfarer Transit Systems Ltd - 001A09 (base 16) Wayfarer Transit Systems Ltd - 10 Willis Way - Fleets Insdustrial Est - Poole Dorset BH15 3SS - UNITED KINGDOM - - 00-1A-0A (hex) Adaptive Micro-Ware Inc. - 001A0A (base 16) Adaptive Micro-Ware Inc. - 6917 Innovation Blvd - Fort Wayne IN 46818 - UNITED STATES - - 00-1A-0B (hex) BONA TECHNOLOGY INC. - 001A0B (base 16) BONA TECHNOLOGY INC. - 4F, E-Place Bldg., 719-24 - Yeoksam-Dong, Gangnam-Gu, - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-1A-0C (hex) Swe-Dish Satellite Systems AB - 001A0C (base 16) Swe-Dish Satellite Systems AB - Torggatan 15 - Solna Stockholm SE-171 06 - SWEDEN - - 00-1A-0D (hex) HandHeld entertainment, Inc. - 001A0D (base 16) HandHeld entertainment, Inc. - 539 Bryant Street, Suite 403 - San Francisco CA 94103 - UNITED STATES - - 00-1A-0E (hex) Cheng Uei Precision Industry Co.,Ltd - 001A0E (base 16) Cheng Uei Precision Industry Co.,Ltd - Junda Industry District, Dongkeng Town,Dongguan City - DongGuan Guang Dong 523455 - CHINA - - 00-1A-0F (hex) Sistemas Avanzados de Control, S.A. - 001A0F (base 16) Sistemas Avanzados de Control, S.A. - calle Colquide 6 - Las Rozas Madrid 28230 - SPAIN - - 00-1A-10 (hex) LUCENT TRANS ELECTRONICS CO.,LTD - 001A10 (base 16) LUCENT TRANS ELECTRONICS CO.,LTD - 9F-1,No.16,Chien Pah Rd. - Chung Ho Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-1A-11 (hex) Google Inc. - 001A11 (base 16) Google Inc. - 1600 Amphitheater Parkway - Mountain View CA 94043 - UNITED STATES - - 00-1A-12 (hex) Essilor - 001A12 (base 16) Essilor - 64 Bis Avenue Aubert - 94300 Vincennes - FRANCE - - 00-1A-13 (hex) Wanlida Group Co., LTD - 001A13 (base 16) Wanlida Group Co., LTD - Jiahe Road No.618 - Xiamen Fujian 361006 - CHINA - - 00-1A-14 (hex) Xin Hua Control Engineering Co.,Ltd. - 001A14 (base 16) Xin Hua Control Engineering Co.,Ltd. - 160 Wenjing Rd., Minhang - Shanghai 2000245 - CHINA - - 00-1A-15 (hex) gemalto e-Payment - 001A15 (base 16) gemalto e-Payment - 6 rue de la Verrerie - Meudon 92197 - FRANCE - - 00-1A-16 (hex) Nokia Danmark A/S - 001A16 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1A-17 (hex) Teak Technologies, Inc. - 001A17 (base 16) Teak Technologies, Inc. - 2901 Tasman Dr., Ste. #210 - Santa Clara CA 95054 - UNITED STATES - - 00-1A-18 (hex) Advanced Simulation Technology inc. - 001A18 (base 16) Advanced Simulation Technology inc. - 500A Huntmar Park Drive - Herndon VA 20170 - UNITED STATES - - 00-1A-19 (hex) Computer Engineering Limited - 001A19 (base 16) Computer Engineering Limited - PO Box 493 - Pukekohe - Auckland AK 2340 - NEW ZEALAND - - 00-1A-1A (hex) Gentex Corporation/Electro-Acoustic Products - 001A1A (base 16) Gentex Corporation/Electro-Acoustic Products - 2456 Brown Avenue - Manchester NH 03103 - UNITED STATES - - 00-1A-1B (hex) ARRIS Group, Inc. - 001A1B (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1A-1C (hex) GT&T Engineering Pte Ltd - 001A1C (base 16) GT&T Engineering Pte Ltd - 2 Ang Mo Kio St.64, Econ Building, #04-00 - Singapore 569084 - SINGAPORE - - 00-1A-1D (hex) PChome Online Inc. - 001A1D (base 16) PChome Online Inc. - 11F, 105, Sec. 2, Tun-Hwa S. Rd. - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 00-1A-1E (hex) Aruba Networks - 001A1E (base 16) Aruba Networks - 1322 Crossman Av - Sunnyvale CA 94089 - UNITED STATES - - 00-1A-1F (hex) Coastal Environmental Systems - 001A1F (base 16) Coastal Environmental Systems - 820 First Avenue South - Seattle wa 98134 - UNITED STATES - - 00-1A-20 (hex) CMOTECH Co. Ltd. - 001A20 (base 16) CMOTECH Co. Ltd. - 5F Etronix Bldg. 17-10 - Yoido-Dong - Youngdungpo-Gu Seoul 150-874 - KOREA, REPUBLIC OF - - 00-1A-21 (hex) Indac B.V. - 001A21 (base 16) Indac B.V. - Institutenweg 15A - Enschede Overijssel 7521 PH - NETHERLANDS - - 00-1A-22 (hex) eQ-3 Entwicklung GmbH - 001A22 (base 16) eQ-3 Entwicklung GmbH - Maiburger Str. 36 - Leer Niedersachsen D-26789 - GERMANY - - 00-1A-23 (hex) Ice Qube, Inc - 001A23 (base 16) Ice Qube, Inc - 141 Wilson Ave - Greensburg Pa 15601 - UNITED STATES - - 00-1A-24 (hex) Galaxy Telecom Technologies Ltd - 001A24 (base 16) Galaxy Telecom Technologies Ltd - No.25, The 1st Gaoxin Road - Xi'an City Shannxi 710075 - CHINA - - 00-1A-25 (hex) DELTA DORE - 001A25 (base 16) DELTA DORE - BONNEMAIN - COMBOURG BRETAGNE 35 35270 - FRANCE - - 00-1A-26 (hex) Deltanode Solutions AB - 001A26 (base 16) Deltanode Solutions AB - Box 92 184 - Stockholm 120 09 - SWEDEN - - 00-1A-27 (hex) Ubistar - 001A27 (base 16) Ubistar - 8F, Seongdo Building, 587-23 - Sinsa-Dong, Gangnam-Gu - Seoul 135-747 - KOREA, REPUBLIC OF - - 00-1A-28 (hex) ASWT Co., LTD. Taiwan Branch H.K. - 001A28 (base 16) ASWT Co., LTD. Taiwan Branch H.K. - 7F., No.3 Lane 91, Dongmei Rd. - Hsinchu 30070 - TAIWAN, PROVINCE OF CHINA - - 00-1A-29 (hex) Johnson Outdoors Marine Electronics, Inc - 001A29 (base 16) Johnson Outdoors Marine Electronics, Inc - 1220 Old Alpharetta Rd - Suite 340 - Alpharetta GA 30041 - UNITED STATES - - 00-1A-2A (hex) Arcadyan Technology Corporation - 001A2A (base 16) Arcadyan Technology Corporation - 4F., No. 9 , Park Avenue II, - Science-based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1A-2B (hex) Ayecom Technology Co., Ltd. - 001A2B (base 16) Ayecom Technology Co., Ltd. - No. 25, R&D Road 2, Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1A-2C (hex) SATEC Co.,LTD - 001A2C (base 16) SATEC Co.,LTD - 358-4, Palgok2-Dong, Sangnok-Gu - Ansan-Si Kyungki-Do 426-190 - KOREA, REPUBLIC OF - - 00-1A-2D (hex) The Navvo Group - 001A2D (base 16) The Navvo Group - 4400 Baker Road - Minnetonka MN 55343 - UNITED STATES - - 00-1A-2E (hex) Ziova Coporation - 001A2E (base 16) Ziova Coporation - Unit 3, 7-9 Sherriffs road - Lonsdale S.A. 5160 - AUSTRALIA - - 00-1A-2F (hex) CISCO SYSTEMS, INC. - 001A2F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-30 (hex) CISCO SYSTEMS, INC. - 001A30 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-31 (hex) SCAN COIN Industries AB - 001A31 (base 16) SCAN COIN Industries AB - Jagershillgatan 26 - Malmö SkÃ¥ne 21375 - SWEDEN - - 00-1A-32 (hex) ACTIVA MULTIMEDIA - 001A32 (base 16) ACTIVA MULTIMEDIA - SICP CSE - SANT JOAN DESPI BARCELONA 08970 - SPAIN - - 00-1A-33 (hex) ASI Communications, Inc. - 001A33 (base 16) ASI Communications, Inc. - 1042 E Guadalupe Rd - Tempe AZ 85283 - UNITED STATES - - 00-1A-34 (hex) Konka Group Co., Ltd. - 001A34 (base 16) Konka Group Co., Ltd. - Oversea Chinese Town,Nanshan, - Shenzhen Guangdong 518053 - CHINA - - 00-1A-35 (hex) BARTEC GmbH - 001A35 (base 16) BARTEC GmbH - Schulstraße 30 - Gotteszell Bavaria 94239 - GERMANY - - 00-1A-36 (hex) Aipermon GmbH & Co. KG - 001A36 (base 16) Aipermon GmbH & Co. KG - Zamdorfer Str. 100 - Munchen - Munich Bavaria D-81677 - GERMANY - - 00-1A-37 (hex) Lear Corporation - 001A37 (base 16) Lear Corporation - Industriestrasse 48 - Kronach Bayern 96317 - GERMANY - - 00-1A-38 (hex) Sanmina-SCI - 001A38 (base 16) Sanmina-SCI - 13000 South Memorial Parkway - Huntsville AL 35803 - UNITED STATES - - 00-1A-39 (hex) Merten GmbH&CoKG - 001A39 (base 16) Merten GmbH&CoKG - Fritz-Kotz-Str. 8 - Wiehl NRW 51674 - GERMANY - - 00-1A-3A (hex) Dongahelecomm - 001A3A (base 16) Dongahelecomm - 678-3,Jeil-ri,Yanggi-myun,Cheoin-gu - Yongin-si Gyeonggi-do 449-821 - KOREA, REPUBLIC OF - - 00-1A-3B (hex) Doah Elecom Inc. - 001A3B (base 16) Doah Elecom Inc. - 8th fl. Century Plaza, 277-40 - Sungsu-2Ga 3Dong - Seoul 133-123 - KOREA, REPUBLIC OF - - 00-1A-3C (hex) Technowave Ltd. - 001A3C (base 16) Technowave Ltd. - Sakurai Bldg.1F, - 1-35-6 Nakacho - Musashino-shi Tokyo 180-0006 - JAPAN - - 00-1A-3D (hex) Ajin Vision Co.,Ltd - 001A3D (base 16) Ajin Vision Co.,Ltd - 1404, Mario-Tower, 222-12 - Guro-dong, Guro-gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-1A-3E (hex) Faster Technology LLC - 001A3E (base 16) Faster Technology LLC - 1812 Avenue D - Suite 202 - Katy Texas 77493 - UNITED STATES - - 00-1A-3F (hex) intelbras - 001A3F (base 16) intelbras - rodovia br 101 km 210 - intelbras - sao jose sc 88104800 - BRAZIL - - 00-1A-40 (hex) A-FOUR TECH CO., LTD. - 001A40 (base 16) A-FOUR TECH CO., LTD. - 6F, No. 108, Min-Chuan Rd., - Hsin-Tien Taipei 23141 - TAIWAN, PROVINCE OF CHINA - - 00-1A-41 (hex) INOCOVA Co.,Ltd - 001A41 (base 16) INOCOVA Co.,Ltd - 5F SEOUL BD.736-17 - Yeoksam-Dong, Kangnam-Ku SEOUL 135-924 - KOREA, REPUBLIC OF - - 00-1A-42 (hex) Techcity Technology co., Ltd. - 001A42 (base 16) Techcity Technology co., Ltd. - 4F, No. 4, Alley 1, Szu Wei Lane, Chung Cheng Rd., - Hsin Tein City Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 00-1A-43 (hex) Logical Link Communications - 001A43 (base 16) Logical Link Communications - 1909 Central Drive Suite 205 - Bedford TX 76021 - UNITED STATES - - 00-1A-44 (hex) JWTrading Co., Ltd - 001A44 (base 16) JWTrading Co., Ltd - 1590 Kwanyang-dong, Dongan-ku - Ahnyang Kyungki - do 431-060 - KOREA, REPUBLIC OF - - 00-1A-45 (hex) GN Netcom as - 001A45 (base 16) GN Netcom as - Metalbuen 66 - P.O.Box 201 - Ballerup Skovlunde DK - 2750 - DENMARK - - 00-1A-46 (hex) Digital Multimedia Technology Co., Ltd - 001A46 (base 16) Digital Multimedia Technology Co., Ltd - Doorim Bldg, 3rd Fl, 164-21 Poi-Dong, - Seoul Kangnam-Gu 135-960 - KOREA, REPUBLIC OF - - 00-1A-47 (hex) Agami Systems, Inc. - 001A47 (base 16) Agami Systems, Inc. - 1269 Innsbruck Drive - Sunnyvale California 94089 - UNITED STATES - - 00-1A-48 (hex) Takacom Corporation - 001A48 (base 16) Takacom Corporation - 304-709 Aza-Nishiyanma - Oroshi-cho - Toki-shi Gifu-ken 509-5202 - JAPAN - - 00-1A-49 (hex) Micro Vision Co.,LTD - 001A49 (base 16) Micro Vision Co.,LTD - 1-9-15 - Kandouji Minami - Niigata-city Niigata-ken 950-0986 - JAPAN - - 00-1A-4A (hex) Qumranet Inc. - 001A4A (base 16) Qumranet Inc. - 530 Lakeside Drive - Suite 220 - Sunnyvale California 94085 - UNITED STATES - - 00-1A-4B (hex) Hewlett-Packard Company - 001A4B (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS060308 - Houston TX 77070 - UNITED STATES - - 00-1A-4C (hex) Crossbow Technology, Inc - 001A4C (base 16) Crossbow Technology, Inc - 4145 N. First Street - San Jose CA 95134 - UNITED STATES - - 00-1A-4D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 001A4D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 00-1A-4E (hex) NTI AG / LinMot - 001A4E (base 16) NTI AG / LinMot - Haerdlistrasse 15 - Spreitenbach AG 8957 - SWITZERLAND - - 00-1A-4F (hex) AVM GmbH - 001A4F (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 00-1A-50 (hex) PheeNet Technology Corp. - 001A50 (base 16) PheeNet Technology Corp. - Rm. 3, 20F, No. 79, Sec. 1 Hsin Tai Wu Rd. - Hsi-Chih New-Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - 00-1A-51 (hex) Alfred Mann Foundation - 001A51 (base 16) Alfred Mann Foundation - P.O. Box 905 - Santa Clarita CA 91380-9005 - UNITED STATES - - 00-1A-52 (hex) Meshlinx Wireless Inc. - 001A52 (base 16) Meshlinx Wireless Inc. - 1410 G Avenue, Suite T - Plano Texas 75074 - UNITED STATES - - 00-1A-53 (hex) Zylaya - 001A53 (base 16) Zylaya - 444 N. Frederick Ave. - Suite 318 - Gaithersburg MD 20877 - UNITED STATES - - 00-1A-54 (hex) Hip Shing Electronics Ltd. - 001A54 (base 16) Hip Shing Electronics Ltd. - Unit 1/2/3, 20/F, New Treasure Center - 10 Ng Fong Street, San Po Kong, Kowloon - HONG KONG - - 00-1A-55 (hex) ACA-Digital Corporation - 001A55 (base 16) ACA-Digital Corporation - 17 F, No. 866-7, Chung Cheng Rd., - Chung Ho City Taipei County 23586 - TAIWAN, PROVINCE OF CHINA - - 00-1A-56 (hex) ViewTel Co,. Ltd. - 001A56 (base 16) ViewTel Co,. Ltd. - #B-502,Bundang Techno Park 148 - YaTap-Dong - BunDang-Ku, SeongNam-Si GyeongGi-Do 463-760 - KOREA, REPUBLIC OF - - 00-1A-57 (hex) Matrix Design Group, LLC - 001A57 (base 16) Matrix Design Group, LLC - 5741 Prospect Dr. - Newburgh IN 47630 - UNITED STATES - - 00-1A-58 (hex) CCV Deutschland GmbH - Celectronic eHealth Div. - 001A58 (base 16) CCV Deutschland GmbH - Celectronic eHealth Div. - Gertraudenstrasse 18 - Berlin D-10178 - GERMANY - - 00-1A-59 (hex) Ircona - 001A59 (base 16) Ircona - Unit 4B-1, Corporate Park - Blanchardstown Dublin 15 - IRELAND - - 00-1A-5A (hex) Korea Electric Power Data Network (KDN) Co., Ltd - 001A5A (base 16) Korea Electric Power Data Network (KDN) Co., Ltd - 665 NAESON-DONG, - GYEONGGI-DO UIWANG-SI, NAESON-DONG 437-082 - KOREA, REPUBLIC OF - - 00-1A-5B (hex) NetCare Service Co., Ltd. - 001A5B (base 16) NetCare Service Co., Ltd. - 5-13-16 Shimizu, Asahi-ku - Osaka 535-0021 - JAPAN - - 00-1A-5C (hex) Euchner GmbH+Co. KG - 001A5C (base 16) Euchner GmbH+Co. KG - Kohlhammerstraße 16 - Leinfelden-Echterdingen BW 70771 - GERMANY - - 00-1A-5D (hex) Mobinnova Corp. - 001A5D (base 16) Mobinnova Corp. - 11F, 845, CHUNG SHAN RD - TAOYUAN 33059 - TAIWAN, PROVINCE OF CHINA - - 00-1A-5E (hex) Thincom Technology Co.,Ltd - 001A5E (base 16) Thincom Technology Co.,Ltd - 17F-3, No.398, Huanbei Rd., - Zhongli City Taoyuan Contry 320 - TAIWAN, PROVINCE OF CHINA - - 00-1A-5F (hex) KitWorks.fi Ltd. - 001A5F (base 16) KitWorks.fi Ltd. - Snowpolis - Vuokatti Kainuu 88610 - FINLAND - - 00-1A-60 (hex) Wave Electronics Co.,Ltd. - 001A60 (base 16) Wave Electronics Co.,Ltd. - 3th Fl.,DaeSan Plaza B/D,Guun-Dong, 12-1,Gwonseon-Gu - Suwon-si Kyeonggi-Do 441-814 - KOREA, REPUBLIC OF - - 00-1A-61 (hex) PacStar Corp. - 001A61 (base 16) PacStar Corp. - 15055 SW Sequoia Pkwy, Suite 100 - Portland OR 97006 - UNITED STATES - - 00-1A-62 (hex) Data Robotics, Incorporated - 001A62 (base 16) Data Robotics, Incorporated - 1881 Landings Dr - Mountain View CA 94043 - UNITED STATES - - 00-1A-63 (hex) Elster Solutions, LLC, - 001A63 (base 16) Elster Solutions, LLC, - 208 South Rogers Lane - Raleigh NC 27610 - UNITED STATES - - 00-1A-64 (hex) IBM Corp - 001A64 (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-1A-65 (hex) Seluxit - 001A65 (base 16) Seluxit - Nyhavnsgade 9, 2.sal - Aalborg Nord Jylland 9000 - DENMARK - - 00-1A-66 (hex) ARRIS Group, Inc. - 001A66 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1A-67 (hex) Infinite QL Sdn Bhd - 001A67 (base 16) Infinite QL Sdn Bhd - G.02, Block A, Dataran Hamodal - No.4, Jalan 13/4, Sect. 13, - Petaling Jaya Selangor Darul Ehsan 46300 - MALAYSIA - - 00-1A-68 (hex) Weltec Enterprise Co., Ltd. - 001A68 (base 16) Weltec Enterprise Co., Ltd. - 2F, No. 351 Yung Ho Rd. - Taipei Hsien - Chung Ho 235 - TAIWAN, PROVINCE OF CHINA - - 00-1A-69 (hex) Wuhan Yangtze Optical Technology CO.,Ltd. - 001A69 (base 16) Wuhan Yangtze Optical Technology CO.,Ltd. - 4#,Guanshan 2 Road - Wuhan Hubei 430073 - CHINA - - 00-1A-6A (hex) Tranzas, Inc. - 001A6A (base 16) Tranzas, Inc. - Queens tower C17 - Minatomirai 2-3-5 Nishi-ku - Yokohama Kanagawa-ken 220-6217 - JAPAN - - 00-1A-6B (hex) Universal Global Scientific Industrial Co., Ltd. - 001A6B (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351,Sec.1, TAIPING RD. - TSAOTUEN, - NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 00-1A-6C (hex) CISCO SYSTEMS, INC. - 001A6C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-6D (hex) CISCO SYSTEMS, INC. - 001A6D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-6E (hex) Impro Technologies - 001A6E (base 16) Impro Technologies - 47B Gillits Rd - Pinetown KwaZulu-Natal 3610 - SOUTH AFRICA - - 00-1A-6F (hex) MI.TEL s.r.l. - 001A6F (base 16) MI.TEL s.r.l. - VIA GUIDO ROSSA, 22 - CORNATE D'ADDA MILANO 20040 - ITALY - - 00-1A-70 (hex) Cisco-Linksys, LLC - 001A70 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 00-1A-71 (hex) Diostech Co., Ltd. - 001A71 (base 16) Diostech Co., Ltd. - 151-21, Buk-ri, Namsa-myeon, - Cheoin-gu - Yongin-city Gyeonggi-do 449 884 - KOREA, REPUBLIC OF - - 00-1A-72 (hex) Mosart Semiconductor Corp. - 001A72 (base 16) Mosart Semiconductor Corp. - 23F., No.33, Sec.1, - Min Sheng Rd., Panchiao City - Taipei 220 - TAIWAN, PROVINCE OF CHINA - - 00-1A-73 (hex) Gemtek Technology Co., Ltd. - 001A73 (base 16) Gemtek Technology Co., Ltd. - No. 1 Jen Ai Road, Hsinchu Industrial Park, Hukou, - Hsinchu 303 - TAIWAN, PROVINCE OF CHINA - - 00-1A-74 (hex) Procare International Co - 001A74 (base 16) Procare International Co - 5F, No.88, Jhouzih Street, Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1A-75 (hex) Sony Ericsson Mobile Communications - 001A75 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-1A-76 (hex) SDT information Technology Co.,LTD. - 001A76 (base 16) SDT information Technology Co.,LTD. - Samil B/B 2F, 5-63 Hyochang-dong - Yongsan-Ku, - Seoul 140-896 - KOREA, REPUBLIC OF - - 00-1A-77 (hex) ARRIS Group, Inc. - 001A77 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1A-78 (hex) ubtos - 001A78 (base 16) ubtos - Rn.213, Woolim Lions Valley, #680 - seoul Gasan-dong 153-803 - KOREA, REPUBLIC OF - - 00-1A-79 (hex) TELECOMUNICATION TECHNOLOGIES LTD. - 001A79 (base 16) TELECOMUNICATION TECHNOLOGIES LTD. - 4D ZHUKOVA BLV. - ODESSA 65121 - UKRAINE - - 00-1A-7A (hex) Lismore Instruments Limited - 001A7A (base 16) Lismore Instruments Limited - Unit 2 Tristar Centre, Star Road - Partridge Green - Horsham West Sussex RH13 8RA - UNITED KINGDOM - - 00-1A-7B (hex) Teleco, Inc. - 001A7B (base 16) Teleco, Inc. - 430 Woodruff Rd. - Suite 300 - Greenville SC 29607 - UNITED STATES - - 00-1A-7C (hex) Hirschmann Multimedia B.V. - 001A7C (base 16) Hirschmann Multimedia B.V. - Pampuslaan 170 - Weesp Noord-Holland 1382 JS - NETHERLANDS - - 00-1A-7D (hex) cyber-blue(HK)Ltd - 001A7D (base 16) cyber-blue(HK)Ltd - Room 1408 block C stars Plaza HongLiRoad,FuTian District - Shenzhen GuangDong 518028 - CHINA - - 00-1A-7E (hex) LN Srithai Comm Ltd. - 001A7E (base 16) LN Srithai Comm Ltd. - 71/12 M.5, Bangna-Trad Rd, KM.52, Thakam - Bangpakong Chachoengsao 24130 - THAILAND - - 00-1A-7F (hex) GCI Science&Technology Co.,Ltd. - 001A7F (base 16) GCI Science&Technology Co.,Ltd. - No.381, Xingangzhong Road, - guangzhou guangdong 510310 - CHINA - - 00-1A-80 (hex) Sony Corporation - 001A80 (base 16) Sony Corporation - Gotenyama Tec 5-1-2 - Kitashinagawa - Shinagawa-ku Tokyo 141-0001 - JAPAN - - 00-1A-81 (hex) Zelax - 001A81 (base 16) Zelax - 2nd buid., 1B, Zavodskaya st., - Moscow 124681 - RUSSIAN FEDERATION - - 00-1A-82 (hex) PROBA Building Automation Co.,LTD - 001A82 (base 16) PROBA Building Automation Co.,LTD - Penghuan Building 501, Shangdi East Road #1, Haidian District, - Beijing 100085 - CHINA - - 00-1A-83 (hex) Pegasus Technologies Inc. - 001A83 (base 16) Pegasus Technologies Inc. - 108 Pawnook Farm Rd. - Lenoir City TN 37771 - UNITED STATES - - 00-1A-84 (hex) V One Multimedia Pte Ltd - 001A84 (base 16) V One Multimedia Pte Ltd - Blk 54, Kallang Bahru - #02-04 - 339336 - SINGAPORE - - 00-1A-85 (hex) NV Michel Van de Wiele - 001A85 (base 16) NV Michel Van de Wiele - M. Vandewielestraat 7 - Marke West-Vlaanderen 8510 - BELGIUM - - 00-1A-86 (hex) AdvancedIO Systems Inc - 001A86 (base 16) AdvancedIO Systems Inc - 595 Howe Street, Suite 502 - Vancouver BC V6C 2T5 - CANADA - - 00-1A-87 (hex) Canhold International Limited - 001A87 (base 16) Canhold International Limited - Flat 4, 13/F., Block 4, Tai Ping Industrial Centre - 51A Ting Kok Road, Tai Po, N.T., - 00852 - HONG KONG - - 00-1A-88 (hex) Venergy,Co,Ltd - 001A88 (base 16) Venergy,Co,Ltd - West 6th Floor,M-8 Building Maqueling Zone, - Shenzhen High-Tech Park, Nanshan district, - shenzhen guangdong 518000 - CHINA - - 00-1A-89 (hex) Nokia Danmark A/S - 001A89 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1A-8A (hex) Samsung Electronics Co., Ltd. - 001A8A (base 16) Samsung Electronics Co., Ltd. - #94-1, Imsoo-Dong - Gumi-City Gyeong-Buk 730-350 - KOREA, REPUBLIC OF - - 00-1A-8B (hex) CHUNIL ELECTRIC IND., CO. - 001A8B (base 16) CHUNIL ELECTRIC IND., CO. - 308,ByuckSan Digital Valley,132-7,Gamjeon-Dong,Sasang-Gu - Busan GyeongSangNamDo 617-800 - KOREA, REPUBLIC OF - - 00-1A-8C (hex) Sophos Ltd - 001A8C (base 16) Sophos Ltd - The Pentagon - Abingdon Science Park - Abingdon Oxfordshire OX14 3YP - UNITED KINGDOM - - 00-1A-8D (hex) AVECS Bergen GmbH - 001A8D (base 16) AVECS Bergen GmbH - Billrothstraße 11 a - Bergen auf Rügen M/V 18528 - GERMANY - - 00-1A-8E (hex) 3Way Networks Ltd - 001A8E (base 16) 3Way Networks Ltd - 7200 Cambridge Research Park - Waterbeach - Cambridge Cambridgeshire CB5 9TL - UNITED KINGDOM - - 00-1A-8F (hex) Nortel - 001A8F (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1A-90 (hex) Trópico Sistemas e Telecomunicações da Amazônia LTDA. - 001A90 (base 16) Trópico Sistemas e Telecomunicações da Amazônia LTDA. - Rod. Campinas-Mogi-Mirim (SP 340) Km 118,5 - Pólis de Tecnologia (CPqD)-Prédio 9A - Campinas São Paulo 13.086-902 - BRAZIL - - 00-1A-91 (hex) FusionDynamic Ltd. - 001A91 (base 16) FusionDynamic Ltd. - 1 B.S.R. towers, 4-th floor - 2 Ben Gurion street - Ramat Gan 52573 - ISRAEL - - 00-1A-92 (hex) ASUSTek COMPUTER INC. - 001A92 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-1A-93 (hex) ERCO Leuchten GmbH - 001A93 (base 16) ERCO Leuchten GmbH - Brockhauser Weg 80-82 - Lüdenscheid NRW D-58507 - GERMANY - - 00-1A-94 (hex) Votronic GmbH - 001A94 (base 16) Votronic GmbH - Saarbruecker Str. 8 - St. Ingbert Saarland 66386 - GERMANY - - 00-1A-95 (hex) Hisense Mobile Communications Technoligy Co.,Ltd. - 001A95 (base 16) Hisense Mobile Communications Technoligy Co.,Ltd. - 11,JiangXi Road, - QingDao ShanDong 266071 - CHINA - - 00-1A-96 (hex) ECLER S.A. - 001A96 (base 16) ECLER S.A. - Motors 166-168 - Barcelona 08038 - SPAIN - - 00-1A-97 (hex) fitivision technology Inc. - 001A97 (base 16) fitivision technology Inc. - 8F, No. 356, Sec. 1, Neihu Rd - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1A-98 (hex) Asotel Communication Limited Taiwan Branch - 001A98 (base 16) Asotel Communication Limited Taiwan Branch - 3G17, No5, Hsin Yi Road, Sec. 5 - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-1A-99 (hex) Smarty (HZ) Information Electronics Co., Ltd - 001A99 (base 16) Smarty (HZ) Information Electronics Co., Ltd - Yonghua Industrial District,Huishen Road,Zhenlong Town - HuiZhou GuangDong 516227 - CHINA - - 00-1A-9A (hex) Skyworth Digital technology(shenzhen)co.ltd. - 001A9A (base 16) Skyworth Digital technology(shenzhen)co.ltd. - 13F,Block A,Skyworth Building,Gaoxin AVE.1.S, - Nanshan District, - ShenZhen GuangDong 518057 - CHINA - - 00-1A-9B (hex) ADEC & Parter AG - 001A9B (base 16) ADEC & Parter AG - Staldenbachstrasse 30 - Pfaeffikon ZH 8808 - SWITZERLAND - - 00-1A-9C (hex) RightHand Technologies, Inc. - 001A9C (base 16) RightHand Technologies, Inc. - 7450 W Wilson Avenue - Chicago IL 60706 - UNITED STATES - - 00-1A-9D (hex) Skipper Wireless, Inc. - 001A9D (base 16) Skipper Wireless, Inc. - Shinjuku-Sumitomo Bldg. 20F - 2-6-1 Nishi-Shinjuku - Shinjuku Tokyo 163-0220 - JAPAN - - 00-1A-9E (hex) ICON Digital International Limited - 001A9E (base 16) ICON Digital International Limited - Suite2209, 22/F., SkyLine Tower, - 39 Wang Kwong Road, Kowloon Bay - CHINA - - 00-1A-9F (hex) A-Link Ltd - 001A9F (base 16) A-Link Ltd - Kylavainiontie 20 - Espoo FI-02760 - FINLAND - - 00-1A-A0 (hex) Dell Inc - 001AA0 (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-1A-A1 (hex) CISCO SYSTEMS, INC. - 001AA1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-A2 (hex) CISCO SYSTEMS, INC. - 001AA2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-A3 (hex) DELORME - 001AA3 (base 16) DELORME - 2 DELORME DRIVE - YARMOUTH MAINE 04096 - UNITED STATES - - 00-1A-A4 (hex) Future University-Hakodate - 001AA4 (base 16) Future University-Hakodate - 116-2 Kamedanakano-cho - Hakodate Hokkaido 041-8655 - JAPAN - - 00-1A-A5 (hex) BRN Phoenix - 001AA5 (base 16) BRN Phoenix - 2500 Augustine Drive, Suite 200 - Santa Clara CA 95054 - UNITED STATES - - 00-1A-A6 (hex) Telefunken Radio Communication Systems GmbH &CO.KG - 001AA6 (base 16) Telefunken Radio Communication Systems GmbH &CO.KG - Eberhard-Finckh-Strasse 55 - Ulm Baden-Wurttemberg 89075 - GERMANY - - 00-1A-A7 (hex) Torian Wireless - 001AA7 (base 16) Torian Wireless - 204 Johnston Street - Collingwood Victoria 3066 - AUSTRALIA - - 00-1A-A8 (hex) Mamiya Digital Imaging Co., Ltd. - 001AA8 (base 16) Mamiya Digital Imaging Co., Ltd. - 2-2, 1-chome, Koraku - kokotaira-Bldg 5F - Bunkyo-ku Tokyo 112-0004 - JAPAN - - 00-1A-A9 (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD - 001AA9 (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD - 19-22# Building, Star-net Science Plaza, Juyuanzhou, - 618 Jinshan Road, - FUZHOU FUJIAN 350002 - CHINA - - 00-1A-AA (hex) Analogic Corp. - 001AAA (base 16) Analogic Corp. - 8 Centennial Drive - Peabody MA 01960 - UNITED STATES - - 00-1A-AB (hex) eWings s.r.l. - 001AAB (base 16) eWings s.r.l. - via S. Quasimodo 46 - Castel Maggiore Bologna 40013 - ITALY - - 00-1A-AC (hex) Corelatus AB - 001AAC (base 16) Corelatus AB - Tegnergatan 37 - Stockholm 11161 - SWEDEN - - 00-1A-AD (hex) ARRIS Group, Inc. - 001AAD (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1A-AE (hex) Savant Systems LLC - 001AAE (base 16) Savant Systems LLC - 45 Perseverance Way - Hyannis Massachusetts 02601 - UNITED STATES - - 00-1A-AF (hex) BLUSENS TECHNOLOGY - 001AAF (base 16) BLUSENS TECHNOLOGY - EDIFICIO CNL,- AV. - FERNANDO CASAS NOVOA ,Nº 37B 2º - 15707 - SANTIAGO DE COMPOSTELA A Coruña - SPAIN - - 00-1A-B0 (hex) Signal Networks Pvt. Ltd., - 001AB0 (base 16) Signal Networks Pvt. Ltd., - No.12, Kalpataru Apartments, - Race Course Cross Road, Madhavnagar, - Bangalore Karnataka 560001 - INDIA - - 00-1A-B1 (hex) Asia Pacific Satellite Industries Co., Ltd. - 001AB1 (base 16) Asia Pacific Satellite Industries Co., Ltd. - 9th FL, IT Castle 2-Dong, #550-1, Gasan-Dong, GeumCheon-Gu, - Seoul 153-768 - KOREA, REPUBLIC OF - - 00-1A-B2 (hex) Cyber Solutions Inc. - 001AB2 (base 16) Cyber Solutions Inc. - 6-6-3, Minami Yoshinari - Aoba-ku - Sendai Miyagi-ken 989-3204 - JAPAN - - 00-1A-B3 (hex) VISIONITE INC. - 001AB3 (base 16) VISIONITE INC. - #707 Daeryung Technotown-2 569-21 - Gasan-Dong Geumcheon-Gu - Seoul 153-771 - KOREA, REPUBLIC OF - - 00-1A-B4 (hex) FFEI Ltd. - 001AB4 (base 16) FFEI Ltd. - Graphics House - Boundary Way - Hemel Hempstead Hertfordshire HP2 7SU - UNITED KINGDOM - - 00-1A-B5 (hex) Home Network System - 001AB5 (base 16) Home Network System - 107, Hyundai I-Vally - Sangdaewon 1(il)-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-714 - KOREA, REPUBLIC OF - - 00-1A-B6 (hex) Texas Instruments - 001AB6 (base 16) Texas Instruments - 108 Wild Basin Ste 350 - Austin TX 78746 - UNITED STATES - - 00-1A-B7 (hex) Ethos Networks LTD. - 001AB7 (base 16) Ethos Networks LTD. - 2 Maskit St. - Building D, POBox 4090 - Herzlia 46766 - ISRAEL - - 00-1A-B8 (hex) Anseri Corporation - 001AB8 (base 16) Anseri Corporation - 35E Industrial Way - Suite 101 - Rochester NH 03867 - UNITED STATES - - 00-1A-B9 (hex) PMC - 001AB9 (base 16) PMC - 56, avenue Raspail - Saint Maur val de marne 94100 - FRANCE - - 00-1A-BA (hex) Caton Overseas Limited - 001ABA (base 16) Caton Overseas Limited - Room 102, No. 101, Lane 91 - E-Shan Road, Pudong District - Shanghai 200127 - CHINA - - 00-1A-BB (hex) Fontal Technology Incorporation - 001ABB (base 16) Fontal Technology Incorporation - Rm.522, Bldg. 52, 195, Sec. 4, ChungHsing Rd., Chutung - Hsinchu 310 - TAIWAN, PROVINCE OF CHINA - - 00-1A-BC (hex) U4EA Technologies Ltd - 001ABC (base 16) U4EA Technologies Ltd - City Point - Temple Gate - Bristol BS1 6PL - UNITED KINGDOM - - 00-1A-BD (hex) Impatica Inc. - 001ABD (base 16) Impatica Inc. - 205-1725 St. Laurent Blvd. - Ottawa ON K1G 3V4 - CANADA - - 00-1A-BE (hex) COMPUTER HI-TECH INC. - 001ABE (base 16) COMPUTER HI-TECH INC. - HigashiUeno3-18-7 - Taitoku Tokyo 110-0015 - JAPAN - - 00-1A-BF (hex) TRUMPF Laser Marking Systems AG - 001ABF (base 16) TRUMPF Laser Marking Systems AG - Ausserfeld - Gruesch GR 7214 - SWITZERLAND - - 00-1A-C0 (hex) JOYBIEN TECHNOLOGIES CO., LTD. - 001AC0 (base 16) JOYBIEN TECHNOLOGIES CO., LTD. - 14F-7, NO.2, JIAN 8TH RD., - ZHONGHE DIST. - NEW TAIPEI CITY TAIWAN 23511 - TAIWAN, PROVINCE OF CHINA - - 00-1A-C1 (hex) 3Com Ltd - 001AC1 (base 16) 3Com Ltd - Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-1A-C2 (hex) YEC Co.,Ltd. - 001AC2 (base 16) YEC Co.,Ltd. - 543-9 Tsuruma - Machida Tokyo 194-0004 - JAPAN - - 00-1A-C3 (hex) Scientific-Atlanta, Inc - 001AC3 (base 16) Scientific-Atlanta, Inc - 5030 Sugarloaf Pkwy - ATL 1.3.473 - Lawrenceville GA 30044 - UNITED STATES - - 00-1A-C4 (hex) 2Wire, Inc - 001AC4 (base 16) 2Wire, Inc - 1704 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-1A-C5 (hex) BreakingPoint Systems, Inc. - 001AC5 (base 16) BreakingPoint Systems, Inc. - 3900 N. Capital of Texas Hwy - Suite 180 - Austin TX 78746 - UNITED STATES - - 00-1A-C6 (hex) Micro Control Designs - 001AC6 (base 16) Micro Control Designs - 17490 Caribou Dr - Monument Co. 80132 - UNITED STATES - - 00-1A-C7 (hex) UNIPOINT - 001AC7 (base 16) UNIPOINT - 7F Gwangsung Bld 831-47 YeokSam-Dong - Kangnam-Gu Seoul 135-936 - KOREA, REPUBLIC OF - - 00-1A-C8 (hex) ISL (Instrumentation Scientifique de Laboratoire) - 001AC8 (base 16) ISL (Instrumentation Scientifique de Laboratoire) - Impasse des 4 vents - Parc d'activité de la Mesnillière - VERSON CALVADOS 14790 - FRANCE - - 00-1A-C9 (hex) SUZUKEN CO.,LTD - 001AC9 (base 16) SUZUKEN CO.,LTD - SUZUKEN TOMEI BLDG. - 26 HIMEWAKA-CHO MEITO-KU - NAGOYA-SI AICHI-KEN 465-0045 - JAPAN - - 00-1A-CA (hex) Tilera Corporation - 001ACA (base 16) Tilera Corporation - 1900 West Park Drive - Suite 290 - Westborough MA 01581 - UNITED STATES - - 00-1A-CB (hex) Autocom Products Ltd - 001ACB (base 16) Autocom Products Ltd - Unit 4 Tachbrook Link, Tachbrook Park Drive - Warwick Warwickshire CV34 6RH - UNITED KINGDOM - - 00-1A-CC (hex) Celestial Semiconductor, Ltd - 001ACC (base 16) Celestial Semiconductor, Ltd - Ugland House, South Church Street, - Cayman Islands - George Town, Cayman Islands 00000 - CAYMAN ISLANDS - - 00-1A-CD (hex) Tidel Engineering LP - 001ACD (base 16) Tidel Engineering LP - 2025 W Belt Line Road Suite 114 - Carrollton TX 75019 - UNITED STATES - - 00-1A-CE (hex) YUPITERU CORPORATION - 001ACE (base 16) YUPITERU CORPORATION - 3, Dannoue, Iwazu-cho, Okazaki-city, Aichi - Okazaki Aichi 444-2144 - JAPAN - - 00-1A-CF (hex) C.T. ELETTRONICA - 001ACF (base 16) C.T. ELETTRONICA - Via Caduti di Nassiriya 5 B - Barberino Val D'Elsa (FI) 50021 - ITALY - - 00-1A-D0 (hex) Albis Technologies AG - 001AD0 (base 16) Albis Technologies AG - Albisriederstrasse 199 - CH 8047 Zuerich - SWITZERLAND - - 00-1A-D1 (hex) FARGO CO., LTD. - 001AD1 (base 16) FARGO CO., LTD. - 4F. KYEMYUNG B/D - 165-4 SAMSUNG-DONG, KANGNAM-KU - SEOUL 135 885 - KOREA, REPUBLIC OF - - 00-1A-D2 (hex) Eletronica Nitron Ltda - 001AD2 (base 16) Eletronica Nitron Ltda - Rua Dr. Ulisses Escobar 415 - Jardim Vista Alegre - Camanducaia Minas Gerais 37650-000 - BRAZIL - - 00-1A-D3 (hex) Vamp Ltd. - 001AD3 (base 16) Vamp Ltd. - PO Box 810 - Vaasa 65101 - FINLAND - - 00-1A-D4 (hex) iPOX Technology Co., Ltd. - 001AD4 (base 16) iPOX Technology Co., Ltd. - 15F-1, No.186, Jian-Yi Rd., Chung-Ho City, - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-1A-D5 (hex) KMC CHAIN INDUSTRIAL CO., LTD. - 001AD5 (base 16) KMC CHAIN INDUSTRIAL CO., LTD. - 7F-8, No. 81, Sui-Lih Rd., Hsinchu - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1A-D6 (hex) JIAGNSU AETNA ELECTRIC CO.,LTD - 001AD6 (base 16) JIAGNSU AETNA ELECTRIC CO.,LTD - NO.571 QIANHU ROAD,QIANQIAO INDUSTRY PARK,WUXI,JIANGSU,CHINA - WUXI JIANGSU 214151 - CHINA - - 00-1A-D7 (hex) Christie Digital Systems, Inc. - 001AD7 (base 16) Christie Digital Systems, Inc. - 809 Wellington Street North - Kitchener Ontario N2G 4Y7 - CANADA - - 00-1A-D8 (hex) AlsterAero GmbH - 001AD8 (base 16) AlsterAero GmbH - Heidenkampsweg 45 - Hamburg 20097 - GERMANY - - 00-1A-D9 (hex) International Broadband Electric Communications, Inc. - 001AD9 (base 16) International Broadband Electric Communications, Inc. - 285 Dunlop Blvd. SW - Suite K - Huntsville AL 35824 - UNITED STATES - - 00-1A-DA (hex) Biz-2-Me Inc. - 001ADA (base 16) Biz-2-Me Inc. - 1301 West Eau Gallie Blvd - Suite 106 - Melbourne FL 32935 - UNITED STATES - - 00-1A-DB (hex) ARRIS Group, Inc. - 001ADB (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1A-DC (hex) Nokia Danmark A/S - 001ADC (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1A-DD (hex) PePWave Ltd - 001ADD (base 16) PePWave Ltd - 17/F., Park Building, - 476 Castle Peak Road - Cheung Sha Wan Kowloon - HONG KONG - - 00-1A-DE (hex) ARRIS Group, Inc. - 001ADE (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1A-DF (hex) Interactivetv Pty Limited - 001ADF (base 16) Interactivetv Pty Limited - Suite 10 Level 3 - 56 Bowman Street - Pyrmont, Sydney NSW 2009 - AUSTRALIA - - 00-1A-E0 (hex) Mythology Tech Express Inc. - 001AE0 (base 16) Mythology Tech Express Inc. - 2F, No.10, Lane 235, Bao Chiao road, - Hsin-Tien. - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-1A-E1 (hex) EDGE ACCESS INC - 001AE1 (base 16) EDGE ACCESS INC - 5440 BEAUMONT CENTER BLVD - SUITE 490 - TAMPA FL 33634 - UNITED STATES - - 00-1A-E2 (hex) CISCO SYSTEMS, INC. - 001AE2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-E3 (hex) CISCO SYSTEMS, INC. - 001AE3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1A-E4 (hex) Medicis Technologies Corporation - 001AE4 (base 16) Medicis Technologies Corporation - 11818 North Creek Parkway N. - Bothell WA 98011 - UNITED STATES - - 00-1A-E5 (hex) Mvox Technologies Inc. - 001AE5 (base 16) Mvox Technologies Inc. - 19050 Pruneridge Ave - Ste. 128 - Cupertino CA 95014 - UNITED STATES - - 00-1A-E6 (hex) Atlanta Advanced Communications Holdings Limited - 001AE6 (base 16) Atlanta Advanced Communications Holdings Limited - 1900 West Oak Circle, Marietta - Atlanta Georgia 30062 - UNITED STATES - - 00-1A-E7 (hex) Aztek Networks, Inc. - 001AE7 (base 16) Aztek Networks, Inc. - 2477 55th St. #202 - Boulder CO 80301 - UNITED STATES - - 00-1A-E8 (hex) Unify GmbH and Co KG - 001AE8 (base 16) Unify GmbH and Co KG - Technical Interface - Hofmannstrasse 51 - Munich 81379 - GERMANY - - 00-1A-E9 (hex) Nintendo Co., Ltd. - 001AE9 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1A-EA (hex) Radio Terminal Systems Pty Ltd - 001AEA (base 16) Radio Terminal Systems Pty Ltd - 1st Floor - 108 Dohertys Road - Laverton North Victoria 3026 - AUSTRALIA - - 00-1A-EB (hex) Allied Telesis K.K. - 001AEB (base 16) Allied Telesis K.K. - No.2 TOC Bldg. - 7-21-11 Nishi-Gotanda - Shinagawa-ku Tokyo 141-0031 - JAPAN - - 00-1A-EC (hex) Keumbee Electronics Co.,Ltd. - 001AEC (base 16) Keumbee Electronics Co.,Ltd. - 3-26, Jangsang-dong, Sangrok-gu - Ansan-si Kyungki-do 426-410 - KOREA, REPUBLIC OF - - 00-1A-ED (hex) INCOTEC GmbH - 001AED (base 16) INCOTEC GmbH - Blomestrasse 25 - 27 - Bielefeld NRW 33609 - GERMANY - - 00-1A-EE (hex) Shenztech Ltd - 001AEE (base 16) Shenztech Ltd - 813, 8F, HOLLYWOOD PLAZA, 610 NATHAN ROAD, - KOWLOON 852 - HONG KONG - - 00-1A-EF (hex) Loopcomm Technology, Inc. - 001AEF (base 16) Loopcomm Technology, Inc. - 18F-1, No. 150, Jian Yi Rd., - Chung-Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-1A-F0 (hex) Alcatel - IPD - 001AF0 (base 16) Alcatel - IPD - 701 E. Middlefield Rd. - Mountain View CA 94043 - UNITED STATES - - 00-1A-F1 (hex) Embedded Artists AB - 001AF1 (base 16) Embedded Artists AB - Davidshallsgatan 16 - Malmoe 21145 - SWEDEN - - 00-1A-F2 (hex) Dynavisions Schweiz AG - 001AF2 (base 16) Dynavisions Schweiz AG - Freisinger Landstraße 21 - D-80939 Muenchen - GERMANY - - 00-1A-F3 (hex) Samyoung Electronics - 001AF3 (base 16) Samyoung Electronics - 146-1, sangdaewon-dong, joongwon-gu - sungnam-shi Gyunggi-do 462-807 - KOREA, REPUBLIC OF - - 00-1A-F4 (hex) Handreamnet - 001AF4 (base 16) Handreamnet - #1209 MarioTower, 28 - Digitalro-30-gil, Guro-Gu - Seoul 152-741 - KOREA, REPUBLIC OF - - 00-1A-F5 (hex) PENTAONE. CO., LTD. - 001AF5 (base 16) PENTAONE. CO., LTD. - Hyo Chang Bldg, 3F, 1013-6, Inkye-dong Paldal-Gu, - Suwon City Gyunggi-Do 422-833 - KOREA, REPUBLIC OF - - 00-1A-F6 (hex) Woven Systems, Inc. - 001AF6 (base 16) Woven Systems, Inc. - 2455 Augustine Drive - Suite 211 - Santa Clara CA 95054 - UNITED STATES - - 00-1A-F7 (hex) dataschalt e+a GmbH - 001AF7 (base 16) dataschalt e+a GmbH - An der Hülshorst 7-9 - Lübeck 23568 - GERMANY - - 00-1A-F8 (hex) Copley Controls Corporation - 001AF8 (base 16) Copley Controls Corporation - 20 Dan Road - Canton MA 02021 - UNITED STATES - - 00-1A-F9 (hex) AeroVIronment (AV Inc) - 001AF9 (base 16) AeroVIronment (AV Inc) - 4685 Industrial St - PO A18271 - Simi Valley CA 93063 - UNITED STATES - - 00-1A-FA (hex) Welch Allyn, Inc. - 001AFA (base 16) Welch Allyn, Inc. - 4619 Jordan Road - PO Box 187 - Skaneateles Falls NY 13153-0187 - UNITED STATES - - 00-1A-FB (hex) Joby Inc. - 001AFB (base 16) Joby Inc. - 1535 Mission St. - Floor 2 - San Francisco CA 94103 - UNITED STATES - - 00-1A-FC (hex) ModusLink Corporation - 001AFC (base 16) ModusLink Corporation - 2905 Prestonwood Drive - Plano Texas 75093 - UNITED STATES - - 00-1A-FD (hex) EVOLIS - 001AFD (base 16) EVOLIS - 29 avenue de la fontaine - ZI Angers beaucouze - Beaucouze 49070 - FRANCE - - 00-1A-FE (hex) SOFACREAL - 001AFE (base 16) SOFACREAL - 149 avenue du MAINE - PARIS Region Parisienne 75014 - FRANCE - - 00-1A-FF (hex) Wizyoung Tech. - 001AFF (base 16) Wizyoung Tech. - 9F, No. 25, Sec. 1, Nanjing E. Rd. - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-1B-00 (hex) Neopost Technologies - 001B00 (base 16) Neopost Technologies - 113 rue Jean-Marin Naudin - Bagneux 92220 - FRANCE - - 00-1B-01 (hex) Applied Radio Technologies - 001B01 (base 16) Applied Radio Technologies - 1124 South Service Road West - Oakville Ontario L6L 5T7 - CANADA - - 00-1B-02 (hex) ED Co.Ltd - 001B02 (base 16) ED Co.Ltd - 517-15 SangDaeWon-Dong - SeongNam-City GyeongGi-Do 462-806 - KOREA, REPUBLIC OF - - 00-1B-03 (hex) Action Technology (SZ) Co., Ltd - 001B03 (base 16) Action Technology (SZ) Co., Ltd - Action Technology Building Baoyuan Road, Xixiang, Bao'an District - Shenzhen Guangdong 518102 - CHINA - - 00-1B-04 (hex) Affinity International S.p.a - 001B04 (base 16) Affinity International S.p.a - C.so Savona 51 - Villastellone Torino I10029 - ITALY - - 00-1B-05 (hex) YMC AG - 001B05 (base 16) YMC AG - Sonnenstrasse 4 - Kreuzlingen Thurgau 8280 - SWITZERLAND - - 00-1B-06 (hex) Ateliers R. LAUMONIER - 001B06 (base 16) Ateliers R. LAUMONIER - Ateliers R. LAUMONIER - BP 1 - Nesles-la-Vallée Val d'Oise 95690 - FRANCE - - 00-1B-07 (hex) Mendocino Software - 001B07 (base 16) Mendocino Software - 47001 Benecia St. - Fremont CA 94538 - UNITED STATES - - 00-1B-08 (hex) Danfoss Drives A/S - 001B08 (base 16) Danfoss Drives A/S - Ulsnaes 1 - Graasten 6300 - DENMARK - - 00-1B-09 (hex) Matrix Telecom Pvt. Ltd. - 001B09 (base 16) Matrix Telecom Pvt. Ltd. - 394, GIDC, Makarpura, - Vadodara Gujarat 390010 - INDIA - - 00-1B-0A (hex) Intelligent Distributed Controls Ltd - 001B0A (base 16) Intelligent Distributed Controls Ltd - Keynes House, Chester Park - Alfreton Road - Derby Derbyshire DE21 4AS - UNITED KINGDOM - - 00-1B-0B (hex) Phidgets Inc. - 001B0B (base 16) Phidgets Inc. - 2715A 16A Street N.W. - Calgary Alberta T2M 3R7 - CANADA - - 00-1B-0C (hex) CISCO SYSTEMS, INC. - 001B0C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-0D (hex) CISCO SYSTEMS, INC. - 001B0D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-0E (hex) InoTec GmbH Organisationssysteme - 001B0E (base 16) InoTec GmbH Organisationssysteme - Biedrichstrasse 11 - Woelfersheim Hessen D-61200 - GERMANY - - 00-1B-0F (hex) Petratec - 001B0F (base 16) Petratec - Derech Ha-Sharon 12 - Kfar Saba Sharon 44271 - ISRAEL - - 00-1B-10 (hex) ShenZhen Kang Hui Technology Co.,ltd - 001B10 (base 16) ShenZhen Kang Hui Technology Co.,ltd - China GuangDong - Two s,floor BaoAn District LongHua - ShenZhen GuangDong 518109 - CHINA - - 00-1B-11 (hex) D-Link Corporation - 001B11 (base 16) D-Link Corporation - NO.289, Sinhu 3rd Rd., - Neihu District, Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-1B-12 (hex) Apprion - 001B12 (base 16) Apprion - Nasa Ames Rerearch Center - P.O. Box 95 Building 19 Suite 1000 - Moffett Field California 94035 - UNITED STATES - - 00-1B-13 (hex) Icron Technologies Corporation - 001B13 (base 16) Icron Technologies Corporation - 221 - 4664 Lougheed Highway - Burnaby BC V5C 5T5 - CANADA - - 00-1B-14 (hex) Carex Lighting Equipment Factory - 001B14 (base 16) Carex Lighting Equipment Factory - 50 Chang Tang Rd., Yan Tian District, - Fungkong, DongGuan - Guangdong province - CHINA - - 00-1B-15 (hex) Voxtel, Inc. - 001B15 (base 16) Voxtel, Inc. - 12725 SW Millikan Way - Suite 230 - Beaverton OR 97005 - UNITED STATES - - 00-1B-16 (hex) Celtro Ltd. - 001B16 (base 16) Celtro Ltd. - Azorim Business Park - 94 Em Hmoshavot Road. - Petach Tikva 49527 - ISRAEL - - 00-1B-17 (hex) Palo Alto Networks - 001B17 (base 16) Palo Alto Networks - 2130 Gold Street Suite 200 - Alviso CA 95022 - UNITED STATES - - 00-1B-18 (hex) Tsuken Electric Ind. Co.,Ltd - 001B18 (base 16) Tsuken Electric Ind. Co.,Ltd - 3-9 Akedouri Izumi-ku - Sendai City Miyagi 981-3206 - JAPAN - - 00-1B-19 (hex) IEEE I&M Society TC9 - 001B19 (base 16) IEEE I&M Society TC9 - 100 Bureau Dr., Mail Stop 8220 - Gaithersburg MD 20899-8220 - UNITED STATES - - 00-1B-1A (hex) e-trees Japan, Inc. - 001B1A (base 16) e-trees Japan, Inc. - Oowada-cho 2-9-2 - Daiwaunyu bldg 3F - Hachioji-city Tokyo 150-0001 - JAPAN - - 00-1B-1B (hex) Siemens AG, - 001B1B (base 16) Siemens AG, - I IA SC MF-K PE 3 - Oestliche Rheinbrueckenstr. 50 - 76187 Karlsruhe Baden Wuerttemberg - GERMANY - - 00-1B-1C (hex) Coherent - 001B1C (base 16) Coherent - 1280 Blues Hills Ave. - Bloomfield CT 06002 - UNITED STATES - - 00-1B-1D (hex) Phoenix International Co., Ltd - 001B1D (base 16) Phoenix International Co., Ltd - 11F. No.42-1, Sec.1, Zhongyang N. Rd. Beitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-1B-1E (hex) HART Communication Foundation - 001B1E (base 16) HART Communication Foundation - STE 1-350 - 9390 Research Blvd - Austin TX 78759 - UNITED STATES - - 00-1B-1F (hex) DELTA - Danish Electronics, Light & Acoustics - 001B1F (base 16) DELTA - Danish Electronics, Light & Acoustics - Venlighedsvej 4 - Hørsholm DK-2970 - DENMARK - - 00-1B-20 (hex) TPine Technology - 001B20 (base 16) TPine Technology - 3F, No.1, AN-I Rd, - Keelung 111 - TAIWAN, PROVINCE OF CHINA - - 00-1B-21 (hex) Intel Corporate - 001B21 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1B-22 (hex) Palit Microsystems ( H.K.) Ltd. - 001B22 (base 16) Palit Microsystems ( H.K.) Ltd. - Room 4-6,11F,Nan Fung Commercial Center - 19 Lam Lok Road,Kowloon Bay - Kowloon 111 - HONG KONG - - 00-1B-23 (hex) SimpleComTools - 001B23 (base 16) SimpleComTools - 598 Indian Trail Rd S. - Suite #102 - Indian Trail NC 28079 - UNITED STATES - - 00-1B-24 (hex) Quanta Computer Inc. - 001B24 (base 16) Quanta Computer Inc. - No. 211, Wen Hwa 2nd Rd., - Kuei Shan Hsiang Tao Yuan Shien 333 - TAIWAN, PROVINCE OF CHINA - - 00-1B-25 (hex) Nortel - 001B25 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1B-26 (hex) RON-Telecom ZAO - 001B26 (base 16) RON-Telecom ZAO - 15 A, Zarechnaya st. - Trehgorny Chelyabinsk region 456080 - RUSSIAN FEDERATION - - 00-1B-27 (hex) Merlin CSI - 001B27 (base 16) Merlin CSI - 12625 Danielson Court - Suite 109 - Poway CA 92064 - UNITED STATES - - 00-1B-28 (hex) POLYGON, JSC - 001B28 (base 16) POLYGON, JSC - 37/1, Karl Marx str., floor 5 - Ufa Bashkortostan 450077 - RUSSIAN FEDERATION - - 00-1B-29 (hex) Avantis.Co.,Ltd - 001B29 (base 16) Avantis.Co.,Ltd - 502 SEOIL BLDG. - 1543-8 SEOCHO-DONG, SEOCHO-GU - SEOUL 132-872 - KOREA, REPUBLIC OF - - 00-1B-2A (hex) CISCO SYSTEMS, INC. - 001B2A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-2B (hex) CISCO SYSTEMS, INC. - 001B2B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-2C (hex) ATRON electronic GmbH - 001B2C (base 16) ATRON electronic GmbH - Am Ziegelstadel 12 + 14 - Markt Schwaben 85570 - GERMANY - - 00-1B-2D (hex) Med-Eng Systems Inc. - 001B2D (base 16) Med-Eng Systems Inc. - 2400 St. Laurent Blvd. - Ottawa Ontario K1G 6C4 - CANADA - - 00-1B-2E (hex) Sinkyo Electron Inc - 001B2E (base 16) Sinkyo Electron Inc - 3-3-21 asahigaoka - hino-city Tokyo 191-0065 - JAPAN - - 00-1B-2F (hex) NETGEAR Inc. - 001B2F (base 16) NETGEAR Inc. - 4500 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-1B-30 (hex) Solitech Inc. - 001B30 (base 16) Solitech Inc. - 1838 Main Street - Stevensville MD 21666 - UNITED STATES - - 00-1B-31 (hex) Neural Image. Co. Ltd. - 001B31 (base 16) Neural Image. Co. Ltd. - A307, CASI, Osaka Univ. - 2-1, Yamada-oka - Suita city Osaka 565-0871 - JAPAN - - 00-1B-32 (hex) QLogic Corporation - 001B32 (base 16) QLogic Corporation - 26650 Aliso Viejo Parkway - Aliso Viejo CA 92656 - UNITED STATES - - 00-1B-33 (hex) Nokia Danmark A/S - 001B33 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1B-34 (hex) Focus System Inc. - 001B34 (base 16) Focus System Inc. - 19F-1, No. 266 Wen Hwa 2nd Rd., Sec. 1 - Linkou Taipei County - TAIWAN, PROVINCE OF CHINA - - 00-1B-35 (hex) ChongQing JINOU Science & Technology Development CO.,Ltd - 001B35 (base 16) ChongQing JINOU Science & Technology Development CO.,Ltd - Chuangyeyuan 208# Keyuan 3rd Road 106# - Hi-Tech Development Zone - Chongqing 400030 - CHINA - - 00-1B-36 (hex) Tsubata Engineering Co.,Ltd. (Head Office) - 001B36 (base 16) Tsubata Engineering Co.,Ltd. (Head Office) - Koyanagi 1-2 - Senju bld. - Ibaraki Osaka 567-0852 - JAPAN - - 00-1B-37 (hex) Computec Oy - 001B37 (base 16) Computec Oy - Juholankatu 8 - PL 66 - Kouvola Kymi 45200 - FINLAND - - 00-1B-38 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - 001B38 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 25, THE 3RD AVENUE - KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN CITY SUZHOU PROVINCE 215300 - CHINA - - 00-1B-39 (hex) Proxicast - 001B39 (base 16) Proxicast - 312 Sunnyfield Drive - Suite 200 - Glenshaw PA 15116 - UNITED STATES - - 00-1B-3A (hex) SIMS Corp. - 001B3A (base 16) SIMS Corp. - RAON Bldg, 9F, 92-8, Wonhyoro-2ga, Yongsan-gu - Seoul 140-847 - KOREA, REPUBLIC OF - - 00-1B-3B (hex) Yi-Qing CO., LTD - 001B3B (base 16) Yi-Qing CO., LTD - 310 ROOM,12F - NO.5-1 HENG YANG RD. - TAIPEI 100 - TAIWAN, PROVINCE OF CHINA - - 00-1B-3C (hex) Software Technologies Group,Inc. - 001B3C (base 16) Software Technologies Group,Inc. - 10330 W. Roosevelt Road - Suite 310 - Weschester IL 60154 - UNITED STATES - - 00-1B-3D (hex) EuroTel Spa - 001B3D (base 16) EuroTel Spa - viale Martiri della Liberta,4 - Lissone Milan 20035 - ITALY - - 00-1B-3E (hex) Curtis, Inc. - 001B3E (base 16) Curtis, Inc. - 2405 Annapolis Lane - Suite 220 - Minneapolis MN 55441 - UNITED STATES - - 00-1B-3F (hex) ProCurve Networking by HP - 001B3F (base 16) ProCurve Networking by HP - 8000 Foothills Blvd. - Roseville California 95747 - UNITED STATES - - 00-1B-40 (hex) Network Automation mxc AB - 001B40 (base 16) Network Automation mxc AB - Box 7294 - Stockholm 10390 - SWEDEN - - 00-1B-41 (hex) General Infinity Co.,Ltd. - 001B41 (base 16) General Infinity Co.,Ltd. - 3F,No.169, Xing-ai Rd, - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1B-42 (hex) Wise & Blue - 001B42 (base 16) Wise & Blue - #715-3 Anyang Megavalley - 799 Gwanyang-Dong, Dongan-Gu - Anyang-Si Gyunggi-Do 431-767 - KOREA, REPUBLIC OF - - 00-1B-43 (hex) Beijing DG Telecommunications equipment Co.,Ltd - 001B43 (base 16) Beijing DG Telecommunications equipment Co.,Ltd - No.5 Jiangtai Road, Chaoyang District - Beijing 100016 - CHINA - - 00-1B-44 (hex) SanDisk Corporation - 001B44 (base 16) SanDisk Corporation - 601 McCarthy Boulevard - Milpitas CA 95035 - UNITED STATES - - 00-1B-45 (hex) ABB AS, Division Automation Products - 001B45 (base 16) ABB AS, Division Automation Products - Bergerveien 12 - POB 90 - Billingstad NO-1375 - NORWAY - - 00-1B-46 (hex) Blueone Technology Co.,Ltd - 001B46 (base 16) Blueone Technology Co.,Ltd - Room 309,3 Floor, 404 Building, ShangBu industrial - Shenzhen Guangdong 518028 - CHINA - - 00-1B-47 (hex) Futarque A/S - 001B47 (base 16) Futarque A/S - Aagade 15B - Aalborg 9000 - DENMARK - - 00-1B-48 (hex) Shenzhen Lantech Electronics Co., Ltd. - 001B48 (base 16) Shenzhen Lantech Electronics Co., Ltd. - 306 Room, Nanshan Water Building, - Nanhai Road, Nanshan - Shenzhen Guangdong 518052 - CHINA - - 00-1B-49 (hex) Roberts Radio limited - 001B49 (base 16) Roberts Radio limited - Swinton Works - Talbot Road - Mexborough South Yorkshire S64 8AJ - UNITED KINGDOM - - 00-1B-4A (hex) W&W Communications, Inc. - 001B4A (base 16) W&W Communications, Inc. - 2903 Bunker Hill Lane - Suite 107 - Santa Clara CA 95054 - UNITED STATES - - 00-1B-4B (hex) SANION Co., Ltd. - 001B4B (base 16) SANION Co., Ltd. - #208 ACETECHNO TOWER, 55-7, MULLAE-DONG 3GA, - YEONGDEUNGPO-GU SEOUL 150-992 - KOREA, REPUBLIC OF - - 00-1B-4C (hex) Signtech - 001B4C (base 16) Signtech - 609 Seonil Technopia 609 - Sangdaewon 1Dong Jungwon gu - Sungnamsi Kyunggido 462-120 - KOREA, REPUBLIC OF - - 00-1B-4D (hex) Areca Technology Corporation - 001B4D (base 16) Areca Technology Corporation - 8F., No. 22, Lane 35, Ji-Hu Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1B-4E (hex) Navman New Zealand - 001B4E (base 16) Navman New Zealand - 7-21 Kawana Street - Northcote - Auckland 0627 - NEW ZEALAND - - 00-1B-4F (hex) Avaya Inc. - 001B4F (base 16) Avaya Inc. - Room 1A 309 - 307 Middletown Lincroft Rd - Lincroft NJ 07738 - UNITED STATES - - 00-1B-50 (hex) Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) - 001B50 (base 16) Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) - 174, Gagarina Avenue - Nizhny Novgorod Russia 603950 - RUSSIAN FEDERATION - - 00-1B-51 (hex) Vector Technology Corp. - 001B51 (base 16) Vector Technology Corp. - No.7, Lane12, Yajou Road. - Tucheng Taipei 236 - TAIWAN, PROVINCE OF CHINA - - 00-1B-52 (hex) ARRIS Group, Inc. - 001B52 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1B-53 (hex) CISCO SYSTEMS, INC. - 001B53 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-54 (hex) CISCO SYSTEMS, INC. - 001B54 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-55 (hex) Hurco Automation Ltd. - 001B55 (base 16) Hurco Automation Ltd. - 6F, No. 31, Shintai Rd. - Jubei City, Hsinchu Hsien 30244 - TAIWAN, PROVINCE OF CHINA - - 00-1B-56 (hex) Tehuti Networks Ltd. - 001B56 (base 16) Tehuti Networks Ltd. - 1, Shenkar St. - Hertzliya 46105 - ISRAEL - - 00-1B-57 (hex) SEMINDIA SYSTEMS PRIVATE LIMITED - 001B57 (base 16) SEMINDIA SYSTEMS PRIVATE LIMITED - #1106/9,A.M.Industrial Estate,Garvebhai palya, - 7th Mile, Hosur Road, - BANGALORE KARNATAKA 560068 - INDIA - - 00-1B-58 (hex) ACE CAD Enterprise Co., Ltd. - 001B58 (base 16) ACE CAD Enterprise Co., Ltd. - 2F, No. 94, Bao Chung Road, - Hsin Tien City, Taipei Hsien 23144 - TAIWAN, PROVINCE OF CHINA - - 00-1B-59 (hex) Sony Ericsson Mobile Communications AB - 001B59 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-1B-5A (hex) Apollo Imaging Technologies, Inc. - 001B5A (base 16) Apollo Imaging Technologies, Inc. - 18545 Rangeland Rd - Ramona CA 92065 - UNITED STATES - - 00-1B-5B (hex) 2Wire, Inc. - 001B5B (base 16) 2Wire, Inc. - 1704 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-1B-5C (hex) Azuretec Co., Ltd. - 001B5C (base 16) Azuretec Co., Ltd. - 3F, No.8, Alley 8, Lane 45, Baoxing Rd., Xindian Dist., - New Taipei City Taiwan 231 - TAIWAN, PROVINCE OF CHINA - - 00-1B-5D (hex) Vololink Pty Ltd - 001B5D (base 16) Vololink Pty Ltd - Level 2, 541 Blackburn Road - Mount Waverley Victoria 3149 - AUSTRALIA - - 00-1B-5E (hex) BPL Limited - 001B5E (base 16) BPL Limited - BPL Towers - 13, Kasturba Road - Bangalore Karnataka 560001 - INDIA - - 00-1B-5F (hex) Alien Technology - 001B5F (base 16) Alien Technology - 18220 Butterfield Blvd. - Morgan Hill CA 95037 - UNITED STATES - - 00-1B-60 (hex) NAVIGON AG - 001B60 (base 16) NAVIGON AG - Berliner Platz 11 - Wuerzburg Bavaria 97080 - GERMANY - - 00-1B-61 (hex) Digital Acoustics, LLC - 001B61 (base 16) Digital Acoustics, LLC - 37 Sherwood Terrace - Lake Bluff IL 60044 - UNITED STATES - - 00-1B-62 (hex) JHT Optoelectronics Co.,Ltd. - 001B62 (base 16) JHT Optoelectronics Co.,Ltd. - Hetian Industrial Park 2rd,Houjie Town, Donguan, - Dongguan Guangdong 523945 - CHINA - - 00-1B-63 (hex) Apple - 001B63 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-1B-64 (hex) IsaacLandKorea Co., Ltd, - 001B64 (base 16) IsaacLandKorea Co., Ltd, - Rm 608, Hangang-Hyundai-Hyel Bldg. 2-36, - Hangangno 2-ga, Yongsan-gu, - Seoul 140-871 - KOREA, REPUBLIC OF - - 00-1B-65 (hex) China Gridcom Co., Ltd - 001B65 (base 16) China Gridcom Co., Ltd - 21/F, Huaneng Building, No. 2068 Shennan Main Road - Shenzhen Guangdong 0086 - CHINA - - 00-1B-66 (hex) Sennheiser electronic GmbH & Co. KG - 001B66 (base 16) Sennheiser electronic GmbH & Co. KG - Am Labor 1 - Wedemark Niedersachsen 30900 - GERMANY - - 00-1B-67 (hex) Cisco Systems Inc - 001B67 (base 16) Cisco Systems Inc - The Stella Building - Windmill Hill Business Park - Swindon Wiltshire SN5 6NX - UNITED KINGDOM - - 00-1B-68 (hex) Modnnet Co., Ltd - 001B68 (base 16) Modnnet Co., Ltd - 2139 Daemyung-Dong DIP main B/D Room#505, Namgu - Daegu Kyungsang Bookdo 705-701 - KOREA, REPUBLIC OF - - 00-1B-69 (hex) Equaline Corporation - 001B69 (base 16) Equaline Corporation - 9F, No. 234, Section 4, Cheng-De Road, - Taipei Hsien 25162 - TAIWAN, PROVINCE OF CHINA - - 00-1B-6A (hex) Powerwave Technologies Sweden AB - 001B6A (base 16) Powerwave Technologies Sweden AB - 164 26 - Kista - Knarrarnäsgatan 7, Kista - SWEDEN - - 00-1B-6B (hex) Swyx Solutions AG - 001B6B (base 16) Swyx Solutions AG - Joseph-von-Fraunhofer-straße 13a - Dortmund NRW 44227 - GERMANY - - 00-1B-6C (hex) LookX Digital Media BV - 001B6C (base 16) LookX Digital Media BV - Roekenveldweg 1 - Brunssum Limburg 6446DK - NETHERLANDS - - 00-1B-6D (hex) Midtronics, Inc. - 001B6D (base 16) Midtronics, Inc. - 7000 Monroe St. - Willowbrook IL 60527 - UNITED STATES - - 00-1B-6E (hex) Anue Systems, Inc. - 001B6E (base 16) Anue Systems, Inc. - 9111 Jollyville Road - Suite 100 - Austin TX 78759 - UNITED STATES - - 00-1B-6F (hex) Teletrak Ltd - 001B6F (base 16) Teletrak Ltd - 214 Kepa Road - Mission Bay - Auckland 1071 - NEW ZEALAND - - 00-1B-70 (hex) IRI Ubiteq, INC. - 001B70 (base 16) IRI Ubiteq, INC. - Shinjuku-Nomura Bldg. 47F, - 1-26-2 Nishi-shinjuku, - Shinjuku-ku Tokyo 163-0547 - JAPAN - - 00-1B-71 (hex) Telular Corp. - 001B71 (base 16) Telular Corp. - 311 South Wacker Drive - Suite 4300 - Chicago IL 60606 - UNITED STATES - - 00-1B-72 (hex) Sicep s.p.a. - 001B72 (base 16) Sicep s.p.a. - Via calabria, 14 - Certaldo 50052 - ITALY - - 00-1B-73 (hex) DTL Broadcast Ltd - 001B73 (base 16) DTL Broadcast Ltd - Johnson's Estate - Silverdale Road - HAYES Middlesex UB3 3BA - UNITED KINGDOM - - 00-1B-74 (hex) MiraLink Corporation - 001B74 (base 16) MiraLink Corporation - 111 SW 5th Ave. - Ste. 1000 - Portland OR 97204 - UNITED STATES - - 00-1B-75 (hex) Hypermedia Systems - 001B75 (base 16) Hypermedia Systems - 2B Bergman St. - Rabbin Industrial Park - Rehovot 76705 - ISRAEL - - 00-1B-76 (hex) Ripcode, Inc. - 001B76 (base 16) Ripcode, Inc. - 1130 E. Arapaho Road - Suite 435 - Richardson TX 75081 - UNITED STATES - - 00-1B-77 (hex) Intel Corporate - 001B77 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1B-78 (hex) Hewlett-Packard Company - 001B78 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - ms040801 - Houston TX 77070 - UNITED STATES - - 00-1B-79 (hex) FAIVELEY TRANSPORT - 001B79 (base 16) FAIVELEY TRANSPORT - ZI du bois de plante - rue amelia earhart - LA VILLE AUX DAMES 37700 - FRANCE - - 00-1B-7A (hex) Nintendo Co., Ltd. - 001B7A (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1B-7B (hex) The Tintometer Ltd - 001B7B (base 16) The Tintometer Ltd - Solar Way - Solstice Park - Amesbury Wiltshire SP4 7SZ - UNITED KINGDOM - - 00-1B-7C (hex) A & R Cambridge - 001B7C (base 16) A & R Cambridge - Pembroke Avenue - Waterbeach - Cambridge CAMBS CB25 9QR - UNITED KINGDOM - - 00-1B-7D (hex) CXR Anderson Jacobson - 001B7D (base 16) CXR Anderson Jacobson - Rue de l'ornette - Abondant 28410 - FRANCE - - 00-1B-7E (hex) Beckmann GmbH - 001B7E (base 16) Beckmann GmbH - Brandtstraße 1 - Hoevelhof NRW 33161 - GERMANY - - 00-1B-7F (hex) TMN Technologies Telecomunicacoes Ltda - 001B7F (base 16) TMN Technologies Telecomunicacoes Ltda - Rua Nilza, 422 - São Paulo SP 03651-120 - BRAZIL - - 00-1B-80 (hex) LORD Corporation - 001B80 (base 16) LORD Corporation - 2000 West Grandview Blvd - Erie Pa 16509 - UNITED STATES - - 00-1B-81 (hex) DATAQ Instruments, Inc. - 001B81 (base 16) DATAQ Instruments, Inc. - 241 Springside Drive - Akron Ohio 44333 - UNITED STATES - - 00-1B-82 (hex) Taiwan Semiconductor Co., Ltd. - 001B82 (base 16) Taiwan Semiconductor Co., Ltd. - 11F, No. 205, Sec. 3, Beishin Rd, - Shindian Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-1B-83 (hex) Finsoft Ltd - 001B83 (base 16) Finsoft Ltd - 16-18 Hatton Garden - London EC1N 8AT - UNITED KINGDOM - - 00-1B-84 (hex) Scan Engineering Telecom - 001B84 (base 16) Scan Engineering Telecom - Svobody str. 75 - Voronezh 394030 - RUSSIAN FEDERATION - - 00-1B-85 (hex) MAN Diesel SE - 001B85 (base 16) MAN Diesel SE - Teglholmsgade 41 - Copenhagen 2450 - DENMARK - - 00-1B-86 (hex) Bosch Access Systems GmbH - 001B86 (base 16) Bosch Access Systems GmbH - Charlottenburger Allee 50 - AACHEN D-52068 - GERMANY - - 00-1B-87 (hex) Deepsound Tech. Co., Ltd - 001B87 (base 16) Deepsound Tech. Co., Ltd - 3F No. 576 Sec. 1, Minsheng N. Rd., Gueishan Township, - Taoyuan 333 - TAIWAN, PROVINCE OF CHINA - - 00-1B-88 (hex) Divinet Access Technologies Ltd - 001B88 (base 16) Divinet Access Technologies Ltd - 4th Floor, Media Center, - Sakaal Nagar, Baner Road - Pune Maharashtra 411007 - INDIA - - 00-1B-89 (hex) EMZA Visual Sense Ltd. - 001B89 (base 16) EMZA Visual Sense Ltd. - 20 Ha'ta'as St., Beith Hapamon - suite 391 - Kfar Saba 44425 - ISRAEL - - 00-1B-8A (hex) 2M Electronic A/S - 001B8A (base 16) 2M Electronic A/S - Malervej 10 - Taastrup 2630 - DENMARK - - 00-1B-8B (hex) NEC Platforms, Ltd. - 001B8B (base 16) NEC Platforms, Ltd. - 800 Shimomata - Kakegawa Shizuoka 436-8501 - JAPAN - - 00-1B-8C (hex) JMicron Technology Corp. - 001B8C (base 16) JMicron Technology Corp. - 1F, No.13, Innovation Road 1 - Hsinchu Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1B-8D (hex) Electronic Computer Systems, Inc. - 001B8D (base 16) Electronic Computer Systems, Inc. - 418 Donegal Drive - Towson MD 21286 - UNITED STATES - - 00-1B-8E (hex) Hulu Sweden AB - 001B8E (base 16) Hulu Sweden AB - Box 12328, 10228 - Kista Stockholm 164 40 - SWEDEN - - 00-1B-8F (hex) CISCO SYSTEMS, INC. - 001B8F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-90 (hex) CISCO SYSTEMS, INC. - 001B90 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-91 (hex) EFKON AG - 001B91 (base 16) EFKON AG - Dietrich-Keller-Strasse 20 - 8074 Raaba - AUSTRIA - - 00-1B-92 (hex) l-acoustics - 001B92 (base 16) l-acoustics - parc de la fontaine de jouvence - marcoussis essonne 91462 - FRANCE - - 00-1B-93 (hex) JC Decaux SA DNT - 001B93 (base 16) JC Decaux SA DNT - 21 rue claude Bernard - MAUREPAS 78310 - FRANCE - - 00-1B-94 (hex) T.E.M.A. S.p.A. - 001B94 (base 16) T.E.M.A. S.p.A. - via della Scienza 21 A/C - Castelnuovo Rangone Modena 41051 - ITALY - - 00-1B-95 (hex) VIDEO SYSTEMS SRL - 001B95 (base 16) VIDEO SYSTEMS SRL - Loc. Gorizzo, 16 - 33030 - CAMINO AL TAGLIAMENTO UD - ITALY - - 00-1B-96 (hex) General Sensing - 001B96 (base 16) General Sensing - Unit 716, Cyberport 1 - 100 Cyberport Road - Pok Fu Lam - HONG KONG - - 00-1B-97 (hex) Violin Technologies - 001B97 (base 16) Violin Technologies - 33 Wood Ave South - Iselin NJ 08830 - UNITED STATES - - 00-1B-98 (hex) Samsung Electronics Co., Ltd. - 001B98 (base 16) Samsung Electronics Co., Ltd. - #94-1, Imsoo-Dong - GUMI Gyeong-Buk 730-350 - KOREA, REPUBLIC OF - - 00-1B-99 (hex) KS System GmbH - 001B99 (base 16) KS System GmbH - Alexanderstraße 37 - Muelheim NRW 45472 - GERMANY - - 00-1B-9A (hex) Apollo Fire Detectors Ltd - 001B9A (base 16) Apollo Fire Detectors Ltd - 36 Brookside Road - Havant Hampshire P09 1JR - UNITED KINGDOM - - 00-1B-9B (hex) Hose-McCann Communications - 001B9B (base 16) Hose-McCann Communications - 1241 West Newport Center Drive - Deerfield Beach FL 33442 - UNITED STATES - - 00-1B-9C (hex) SATEL sp. z o.o. - 001B9C (base 16) SATEL sp. z o.o. - Schuberta 79 - Gdansk pomorskie 80-172 - POLAND - - 00-1B-9D (hex) Novus Security Sp. z o.o. - 001B9D (base 16) Novus Security Sp. z o.o. - ul. PuÅ‚awska 431 - Warsaw woj. mazowieckie 02-801 - POLAND - - 00-1B-9E (hex) ASKEY COMPUTER CORP - 001B9E (base 16) ASKEY COMPUTER CORP - 10F,NO.119,CHIENKANG RD, - CHUNG-HO,TPIPEI 235 - TAIWAN, PROVINCE OF CHINA - - 00-1B-9F (hex) Calyptech Pty Ltd - 001B9F (base 16) Calyptech Pty Ltd - 5/486 Lower Heidelberg Road - Heidelberg Victoria 3084 - AUSTRALIA - - 00-1B-A0 (hex) Awox - 001BA0 (base 16) Awox - 93, Place Pierre Duhem - Les Centuries - Montpellier Herault 34000 - FRANCE - - 00-1B-A1 (hex) Ã…mic AB - 001BA1 (base 16) Ã…mic AB - Uppsala science park - Dag Hammarskjölds väg 52 B - Uppsala 75183 - SWEDEN - - 00-1B-A2 (hex) IDS Imaging Development Systems GmbH - 001BA2 (base 16) IDS Imaging Development Systems GmbH - Dimbacher Str. 6 - Obersulm BW 74182 - GERMANY - - 00-1B-A3 (hex) Flexit Group GmbH - 001BA3 (base 16) Flexit Group GmbH - Bräuhausstraße 14 - Salzburg Salzburg 5020 - AUSTRIA - - 00-1B-A4 (hex) S.A.E Afikim - 001BA4 (base 16) S.A.E Afikim - Kibutz Afikim - Kibutz Afikim 15148 - ISRAEL - - 00-1B-A5 (hex) MyungMin Systems, Inc. - 001BA5 (base 16) MyungMin Systems, Inc. - #410,Doosan Venture Dime 2-cha,1307-37 - Kwanyang-Dong, - Kyungki-do 431-060 - KOREA, REPUBLIC OF - - 00-1B-A6 (hex) intotech inc. - 001BA6 (base 16) intotech inc. - 13F DMC R&D Center E3-2 Building Land Development District Sangam-Dong - Mapogu Seoul 121-270 - KOREA, REPUBLIC OF - - 00-1B-A7 (hex) Lorica Solutions - 001BA7 (base 16) Lorica Solutions - 275 Northpointe Parkway - Amherst NY 14228 - UNITED STATES - - 00-1B-A8 (hex) UBI&MOBI,.Inc - 001BA8 (base 16) UBI&MOBI,.Inc - 3F, Duido Bldg, #288-5, Yangjae-Dong - Seocho-Gu Seoul 137-130 - KOREA, REPUBLIC OF - - 00-1B-A9 (hex) BROTHER INDUSTRIES, LTD. - 001BA9 (base 16) BROTHER INDUSTRIES, LTD. - Printing & Solutions Company, Development Management Dept. - 15-1 Naeshiro-cho, Mizuho-ku - Nagoya Aichi 467-8561 - JAPAN - - 00-1B-AA (hex) XenICs nv - 001BAA (base 16) XenICs nv - Ambachtenlaan 44 - Leuven Vlaams-Brabant B-3001 - BELGIUM - - 00-1B-AB (hex) Telchemy, Incorporated - 001BAB (base 16) Telchemy, Incorporated - 2905 Premiere Parkway - Suite 280 - Duluth GA 30097 - UNITED STATES - - 00-1B-AC (hex) Curtiss Wright Controls Embedded Computing - 001BAC (base 16) Curtiss Wright Controls Embedded Computing - 10201 Wateridge Circle - Suite 300 - San Diego CA 92121 - UNITED STATES - - 00-1B-AD (hex) iControl Incorporated - 001BAD (base 16) iControl Incorporated - 3235 Kifer Road - Suite 260 - Santa Clara California 95051 - UNITED STATES - - 00-1B-AE (hex) Micro Control Systems, Inc - 001BAE (base 16) Micro Control Systems, Inc - 5580 Enterprise Parkway - Fort Myers Florida 33905 - UNITED STATES - - 00-1B-AF (hex) Nokia Danmark A/S - 001BAF (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1B-B0 (hex) BHARAT ELECTRONICS - 001BB0 (base 16) BHARAT ELECTRONICS - JALAHALLI POST - BANGALORE KARNATAKA 560013 - INDIA - - 00-1B-B1 (hex) Wistron Neweb Corp. - 001BB1 (base 16) Wistron Neweb Corp. - No. 10-1, Li-hsin Road I, Hsinchu Science Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1B-B2 (hex) Intellect International NV - 001BB2 (base 16) Intellect International NV - Kleine Kloosterstraat 23 - Zaventem Vlaamse brabant 1932 - BELGIUM - - 00-1B-B3 (hex) Condalo GmbH - 001BB3 (base 16) Condalo GmbH - Kohlstatt 3 - Lichtenau Bavaria 86706 - GERMANY - - 00-1B-B4 (hex) Airvod Limited - 001BB4 (base 16) Airvod Limited - Heather House - Heather Road - Sandyford Ind Est Dublin 18 D18 - IRELAND - - 00-1B-B5 (hex) ZF Electronics GmbH - 001BB5 (base 16) ZF Electronics GmbH - Cherrystraße 1 - Auerbach i. d. Opf. Bayern D-91275 - GERMANY - - 00-1B-B6 (hex) Bird Electronic Corp. - 001BB6 (base 16) Bird Electronic Corp. - 30303 Aurora Road - Solon Ohio 44139 - UNITED STATES - - 00-1B-B7 (hex) Alta Heights Technology Corp. - 001BB7 (base 16) Alta Heights Technology Corp. - 108 Alta Heights Court - Los Gatos California 95030 - UNITED STATES - - 00-1B-B8 (hex) BLUEWAY ELECTRONIC CO;LTD - 001BB8 (base 16) BLUEWAY ELECTRONIC CO;LTD - Workshop B,Dong Feng Village, - Front Baiyun,Gu Tang Ao - HuiZhou GuangDong 516008 - CHINA - - 00-1B-B9 (hex) Elitegroup Computer System Co. - 001BB9 (base 16) Elitegroup Computer System Co. - No.22, Alley 38, Lane 91 , Sec. 1 , Nei Hu Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1B-BA (hex) Nortel - 001BBA (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1B-BB (hex) RFTech Co.,Ltd - 001BBB (base 16) RFTech Co.,Ltd - 339-17 Jwahang-Ri,Wonsam-Myun, - Cheoin-Gu - Yongin-Si Kyungki-Do 449-871 - KOREA, REPUBLIC OF - - 00-1B-BC (hex) Silver Peak Systems, Inc. - 001BBC (base 16) Silver Peak Systems, Inc. - 471 El Camino Real - Santa Clara CA 95050 - UNITED STATES - - 00-1B-BD (hex) FMC Kongsberg Subsea AS - 001BBD (base 16) FMC Kongsberg Subsea AS - Kirkegaardsveien 45 - Kongsberg Buskerud 3601 - NORWAY - - 00-1B-BE (hex) ICOP Digital - 001BBE (base 16) ICOP Digital - 16801 W. 116th St. - Lenexa KS 66219 - UNITED STATES - - 00-1B-BF (hex) SAGEM COMMUNICATION - 001BBF (base 16) SAGEM COMMUNICATION - 14 Rue Paul Dautier - Vélizy 78457 - FRANCE - - 00-1B-C0 (hex) Juniper Networks - 001BC0 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-1B-C1 (hex) HOLUX Technology, Inc. - 001BC1 (base 16) HOLUX Technology, Inc. - 1F, No. 30, R&D Rd. II, - Science-based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1B-C2 (hex) Integrated Control Technology Limitied - 001BC2 (base 16) Integrated Control Technology Limitied - 11 Canaveral Drive - Albany - Auckland Auckland 0735 - NEW ZEALAND - - 00-1B-C3 (hex) Mobisolution Co.,Ltd - 001BC3 (base 16) Mobisolution Co.,Ltd - 848-16 - Guyeong-Dong - Gumi Gyeongbuk 730-300 - KOREA, REPUBLIC OF - - 00-1B-C4 (hex) Ultratec, Inc. - 001BC4 (base 16) Ultratec, Inc. - 450 Science Drive - Madison WI 53711 - UNITED STATES - - 00-1B-C5 (hex) IEEE REGISTRATION AUTHORITY - Please see OUI36/MA-S public listing for more information. - 001BC5 (base 16) IEEE REGISTRATION AUTHORITY - Please see OUI36/MA-S public listing for more information. - 445 Hoes Lane - Piscataway NJ 08854 - UNITED STATES - - 00-1B-C6 (hex) Strato Rechenzentrum AG - 001BC6 (base 16) Strato Rechenzentrum AG - Pascalstrasse 10 - D-10587 Berlin - GERMANY - - 00-1B-C7 (hex) StarVedia Technology Inc. - 001BC7 (base 16) StarVedia Technology Inc. - 3F, No. 247, Done Sec. 1, Guangming 6th Rd. - Jhubei Hsin-Chu County 302 - TAIWAN, PROVINCE OF CHINA - - 00-1B-C8 (hex) MIURA CO.,LTD - 001BC8 (base 16) MIURA CO.,LTD - 620-1,Nakanishisoto - Matsuyama Ehime 799-2425 - JAPAN - - 00-1B-C9 (hex) FSN DISPLAY INC - 001BC9 (base 16) FSN DISPLAY INC - Baeksuk-Dong 1141-1, Ilsan Techno Town 1009 - Koyang-Si, Ilsan-Gu, Kyeonggi-Do, Republic of Korea - Koyang-si Kyeonggi-Do 410722 - KOREA, REPUBLIC OF - - 00-1B-CA (hex) Beijing Run Technology LTD. Company - 001BCA (base 16) Beijing Run Technology LTD. Company - 4/F, Hangtian Technology Building - Beijing 100037 - CHINA - - 00-1B-CB (hex) PEMPEK SYSTEMS PTY LTD - 001BCB (base 16) PEMPEK SYSTEMS PTY LTD - UNIT 3 / 13 HOYLE AVENUE - CASTLE HILL NSW 2154 - AUSTRALIA - - 00-1B-CC (hex) KINGTEK CCTV ALLIANCE CO., LTD. - 001BCC (base 16) KINGTEK CCTV ALLIANCE CO., LTD. - 5F-3, NO. 106, SEC. 3, HSIN YI ROAD - TAIPEI 106 - TAIWAN, PROVINCE OF CHINA - - 00-1B-CD (hex) DAVISCOMMS (S) PTE LTD - 001BCD (base 16) DAVISCOMMS (S) PTE LTD - Blk 70 Ubi Crescent #01-07 - Ubi Techpark - 408570 - SINGAPORE - - 00-1B-CE (hex) Measurement Devices Ltd - 001BCE (base 16) Measurement Devices Ltd - Redwood House - Hackness Road - York Yorkshire YO266Q - UNITED KINGDOM - - 00-1B-CF (hex) Dataupia Corporation - 001BCF (base 16) Dataupia Corporation - One Alewife Center - Cambridge MA 02140 - UNITED STATES - - 00-1B-D0 (hex) IDENTEC SOLUTIONS - 001BD0 (base 16) IDENTEC SOLUTIONS - Hertzstraße 10 - Weinheim 69469 - GERMANY - - 00-1B-D1 (hex) SOGESTMATIC - 001BD1 (base 16) SOGESTMATIC - 409 Route de la Gare - CHATEAUNEUF DE GADAGNE PACA 84470 - FRANCE - - 00-1B-D2 (hex) ULTRA-X ASIA PACIFIC Inc. - 001BD2 (base 16) ULTRA-X ASIA PACIFIC Inc. - 5-1-15 Sotokanda - Tokyo Chiyoda-ku 101-0021 - JAPAN - - 00-1B-D3 (hex) Panasonic Corp. AVC Company - 001BD3 (base 16) Panasonic Corp. AVC Company - 1-15 Matsuo-cho - 678-F66 - Kadoma Osaka 571-8504 - JAPAN - - 00-1B-D4 (hex) CISCO SYSTEMS, INC. - 001BD4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-D5 (hex) CISCO SYSTEMS, INC. - 001BD5 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1B-D6 (hex) Kelvin Hughes Ltd - 001BD6 (base 16) Kelvin Hughes Ltd - New North Road - Hainault - Ilford Essex IG6 2UR - UNITED KINGDOM - - 00-1B-D7 (hex) Scientific Atlanta, A Cisco Company - 001BD7 (base 16) Scientific Atlanta, A Cisco Company - 5030 Sugarloaf Parkway - ATL 1.3.473 - Lawrenceville GA 30044 - UNITED STATES - - 00-1B-D8 (hex) DVTel LTD - 001BD8 (base 16) DVTel LTD - 5 Sapir - 46852 Herzelia - ISRAEL - - 00-1B-D9 (hex) Edgewater Computer Systems - 001BD9 (base 16) Edgewater Computer Systems - 1125 Innovation Drive - Ottawa Ontario K2K-3G6 - CANADA - - 00-1B-DA (hex) UTStarcom Inc - 001BDA (base 16) UTStarcom Inc - 1275 Harbor Bay PKWY - Alameda CA 94502 - UNITED STATES - - 00-1B-DB (hex) Valeo VECS - 001BDB (base 16) Valeo VECS - 2 Avenue Fernand Pouillon - Europarc - CRETEIL Ile de France 94042 - FRANCE - - 00-1B-DC (hex) Vencer Co., Ltd. - 001BDC (base 16) Vencer Co., Ltd. - 20F-1, No.77, Sec.1, Hsin Tai Wu Rd., - Hsi Chih Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-1B-DD (hex) ARRIS Group, Inc. - 001BDD (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1B-DE (hex) Renkus-Heinz, Inc. - 001BDE (base 16) Renkus-Heinz, Inc. - 19201 Cook St. - Foothill Ranch CA 92610 - UNITED STATES - - 00-1B-DF (hex) Iskra Sistemi d.d. - 001BDF (base 16) Iskra Sistemi d.d. - Stegne 21 - Ljubljana Slovenia 1000 - SLOVENIA - - 00-1B-E0 (hex) TELENOT ELECTRONIC GmbH - 001BE0 (base 16) TELENOT ELECTRONIC GmbH - Wiesentalstraße 42 - Aalen Baden-Württemberg 73434 - GERMANY - - 00-1B-E1 (hex) ViaLogy - 001BE1 (base 16) ViaLogy - 2400 Lincoln Ave - Altadena CA 91001 - UNITED STATES - - 00-1B-E2 (hex) AhnLab,Inc. - 001BE2 (base 16) AhnLab,Inc. - 6th Fl, CCMM Bldg, 12 Yeouido-dong - Seoul 150869 - KOREA, REPUBLIC OF - - 00-1B-E3 (hex) Health Hero Network, Inc. - 001BE3 (base 16) Health Hero Network, Inc. - 2000 Seaport Blvd. - Suite 400 - Redwood City CA 94063 - UNITED STATES - - 00-1B-E4 (hex) TOWNET SRL - 001BE4 (base 16) TOWNET SRL - VIA DEI FINALE, 20 - 61043 CAGLI (PU) - ITALY - - 00-1B-E5 (hex) 802automation Limited - 001BE5 (base 16) 802automation Limited - 18 First Avenue - Worthing West Sussex BN14 9NJ - UNITED KINGDOM - - 00-1B-E6 (hex) VR AG - 001BE6 (base 16) VR AG - Rütistrasse 18 - Schlieren CH-8952 - SWITZERLAND - - 00-1B-E7 (hex) Postek Electronics Co., Ltd. - 001BE7 (base 16) Postek Electronics Co., Ltd. - Suite 510, Shanghang Building - Hongli Road - Shen Zhen Guang Dong 518028 - CHINA - - 00-1B-E8 (hex) Ultratronik GmbH - 001BE8 (base 16) Ultratronik GmbH - Dornierstr. 9 - Gilching 822205 - GERMANY - - 00-1B-E9 (hex) Broadcom Corporation - 001BE9 (base 16) Broadcom Corporation - 16215 Alton Parkway - Irvine CA 92618 - UNITED STATES - - 00-1B-EA (hex) Nintendo Co., Ltd. - 001BEA (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1B-EB (hex) DMP Electronics INC. - 001BEB (base 16) DMP Electronics INC. - 8F., No.12, Wucyuan 7th Rd. - Wugu Township - Taipei County 248 - TAIWAN, PROVINCE OF CHINA - - 00-1B-EC (hex) Netio Technologies Co., Ltd - 001BEC (base 16) Netio Technologies Co., Ltd - 4F-1, No. 582, Rueiguang Rd., Neihu District - Taipei 11492 - TAIWAN, PROVINCE OF CHINA - - 00-1B-ED (hex) Brocade Communications Systems, Inc - 001BED (base 16) Brocade Communications Systems, Inc - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-1B-EE (hex) Nokia Danmark A/S - 001BEE (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1B-EF (hex) Blossoms Digital Technology Co.,Ltd. - 001BEF (base 16) Blossoms Digital Technology Co.,Ltd. - BLK25,Hengfeng Ind.City,Hezhou - Xixiang Town - Shenzhen Guangdong 518126 - CHINA - - 00-1B-F0 (hex) Value Platforms Limited - 001BF0 (base 16) Value Platforms Limited - Rm 712-713, Building 9, 5, Science Park West Ave., - Hong Kong Science Park, - Shatin, - HONG KONG - - 00-1B-F1 (hex) Nanjing SilverNet Software Co., Ltd. - 001BF1 (base 16) Nanjing SilverNet Software Co., Ltd. - 3/F, 10 building, Nanjing World Window Technology & Software Park - 12 DingHuaiMen, Gulou District, Nanjing - Nanjing Jiangsu 210013 - CHINA - - 00-1B-F2 (hex) KWORLD COMPUTER CO., LTD - 001BF2 (base 16) KWORLD COMPUTER CO., LTD - No. 113, Jian 2nd Rd., - Jhonghe Taipei county 235 - TAIWAN, PROVINCE OF CHINA - - 00-1B-F3 (hex) TRANSRADIO SenderSysteme Berlin AG - 001BF3 (base 16) TRANSRADIO SenderSysteme Berlin AG - Mertensstrasse 63 - Berlin 13587 - GERMANY - - 00-1B-F4 (hex) KENWIN INDUSTRIAL(HK) LTD. - 001BF4 (base 16) KENWIN INDUSTRIAL(HK) LTD. - RM.1512 15/F SHATIN GALLERIA - 18-24 SHAN MEI ST, FOTAN - HONG KONG - - 00-1B-F5 (hex) Tellink Sistemas de Telecomunicación S.L. - 001BF5 (base 16) Tellink Sistemas de Telecomunicación S.L. - C/ María Tubau Nº 5 Bajo B - Madrid 28050 - SPAIN - - 00-1B-F6 (hex) CONWISE Technology Corporation Ltd. - 001BF6 (base 16) CONWISE Technology Corporation Ltd. - 2F No.44, Park Ave. 2, Hsinchu Science Park - Hsinchu City 30075 - TAIWAN, PROVINCE OF CHINA - - 00-1B-F7 (hex) Lund IP Products AB - 001BF7 (base 16) Lund IP Products AB - Dalbyv. 1 - Lund SkÃ¥ne 224 60 - SWEDEN - - 00-1B-F8 (hex) Digitrax Inc. - 001BF8 (base 16) Digitrax Inc. - 2443 Transmitter Rd, - Suite 206 - Panama City FL 32404 - UNITED STATES - - 00-1B-F9 (hex) Intellitect Water Ltd - 001BF9 (base 16) Intellitect Water Ltd - Suite 19, Basepoint Business Centre - Aviation Park West - Christchurch Dorset BH23 ^NW - UNITED KINGDOM - - 00-1B-FA (hex) G.i.N. mbH - 001BFA (base 16) G.i.N. mbH - Raiffeisenstraße 15 - Griesheim Hessen 64347 - GERMANY - - 00-1B-FB (hex) Alps Electric Co., Ltd - 001BFB (base 16) Alps Electric Co., Ltd - 1-2-1, Okinouchi - Soma-city Fukushima--pref 976-8501 - JAPAN - - 00-1B-FC (hex) ASUSTek COMPUTER INC. - 001BFC (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-1B-FD (hex) Dignsys Inc. - 001BFD (base 16) Dignsys Inc. - 14F, Digital Empire Bldg., B-1408 - Yeongtong-gu, - Suwon Gyeonggi-do 443-813 - KOREA, REPUBLIC OF - - 00-1B-FE (hex) Zavio Inc. - 001BFE (base 16) Zavio Inc. - No.1,Lising 1st Rd. Science Based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1B-FF (hex) Millennia Media inc. - 001BFF (base 16) Millennia Media inc. - 4200 Day Spring CT - Placerville CA 95667 - UNITED STATES - - 00-1C-00 (hex) Entry Point, LLC - 001C00 (base 16) Entry Point, LLC - 735 Robins - Idaho Falls Idaho 83401 - UNITED STATES - - 00-1C-01 (hex) ABB Oy Drives - 001C01 (base 16) ABB Oy Drives - Hiomotie 13 - Helsinki FI-00380 - FINLAND - - 00-1C-02 (hex) Pano Logic - 001C02 (base 16) Pano Logic - 2000 Seaport Drive, Suite 200 - Suite 200 - Redwood City CA 94063 - UNITED STATES - - 00-1C-03 (hex) Betty TV Technology AG - 001C03 (base 16) Betty TV Technology AG - Hardturmstrasse 2 - Zurich 80005 - SWITZERLAND - - 00-1C-04 (hex) Airgain, Inc. - 001C04 (base 16) Airgain, Inc. - 1930 Palomar Point Way - Suite 107 - Carlsbad CA 92008 - UNITED STATES - - 00-1C-05 (hex) Nonin Medical Inc. - 001C05 (base 16) Nonin Medical Inc. - 13700 1st Avenue North - Plymouth MN 55441 - UNITED STATES - - 00-1C-06 (hex) Siemens Numerical Control Ltd., Nanjing - 001C06 (base 16) Siemens Numerical Control Ltd., Nanjing - No. 18 Siemens Road, Jiangning Development Zone - Nanjing JiangSu 211100 - CHINA - - 00-1C-07 (hex) Cwlinux Limited - 001C07 (base 16) Cwlinux Limited - Unit 138, 13/F, Weswick Commercial Building, - 147-151 Queen's Road East, - Wan Chai - HONG KONG - - 00-1C-08 (hex) Echo360, Inc. - 001C08 (base 16) Echo360, Inc. - 11955 Freedom Drive - Suite 700 - Reston VA 20190 - UNITED STATES - - 00-1C-09 (hex) SAE Electronic Co.,Ltd. - 001C09 (base 16) SAE Electronic Co.,Ltd. - 23/F,Ying Long Zhan Ye Building, - No.6025, Shen Nan Road,Futian District - Shenzhen Guang Dong 518040 - CHINA - - 00-1C-0A (hex) Shenzhen AEE Technology Co.,Ltd. - 001C0A (base 16) Shenzhen AEE Technology Co.,Ltd. - 1st Floor B Building, Shenzhen, - Tsinghua Hi-Tech Park, Nanshan Hi-Tech Park North, - Shenzhen Guangdong 518057 - CHINA - - 00-1C-0B (hex) SmartAnt Telecom - 001C0B (base 16) SmartAnt Telecom - 2F, No. 669, Sec. 4, Chung Hsing Rd., Chutung - Hsinchu 310 - TAIWAN, PROVINCE OF CHINA - - 00-1C-0C (hex) TANITA Corporation - 001C0C (base 16) TANITA Corporation - 1-14-2,Maeno-cho - Itabashi-ku - Tokyo 174-8630 - JAPAN - - 00-1C-0D (hex) G-Technology, Inc. - 001C0D (base 16) G-Technology, Inc. - 1653 Stanford Street - Santa Monica CA 90404 - UNITED STATES - - 00-1C-0E (hex) CISCO SYSTEMS, INC. - 001C0E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-0F (hex) CISCO SYSTEMS, INC. - 001C0F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-10 (hex) Cisco-Linksys, LLC - 001C10 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 00-1C-11 (hex) ARRIS Group, Inc. - 001C11 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1C-12 (hex) ARRIS Group, Inc. - 001C12 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1C-13 (hex) OPTSYS TECHNOLOGY CO., LTD. - 001C13 (base 16) OPTSYS TECHNOLOGY CO., LTD. - SUITE B-802 BUNDANG TECHNO PARK - YATAP-DONG, BUNDANG-KU - SEONGNAM-SI GYEONGGI-DO 463-760 - KOREA, REPUBLIC OF - - 00-1C-14 (hex) VMware, Inc - 001C14 (base 16) VMware, Inc - 3401 Hillview Avenue - Palo Alto CA 94304 - UNITED STATES - - 00-1C-15 (hex) iPhotonix LLC - 001C15 (base 16) iPhotonix LLC - 2600 N Central Expressway - Suite 950 - Richardson Texas 75080 - UNITED STATES - - 00-1C-16 (hex) ThyssenKrupp Elevator - 001C16 (base 16) ThyssenKrupp Elevator - 9280 Crestwyn Hills Drive - Memphis TN 38125 - UNITED STATES - - 00-1C-17 (hex) Nortel - 001C17 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1C-18 (hex) Sicert S.r.L. - 001C18 (base 16) Sicert S.r.L. - Via Bernardino Alimena, 128 - Rome 00173 - ITALY - - 00-1C-19 (hex) secunet Security Networks AG - 001C19 (base 16) secunet Security Networks AG - Kronprinzenstraße 30 - Essen NRW 45128 - GERMANY - - 00-1C-1A (hex) Thomas Instrumentation, Inc - 001C1A (base 16) Thomas Instrumentation, Inc - 133 Landing Rd - Cape May Court House NJ 08210 - UNITED STATES - - 00-1C-1B (hex) Hyperstone GmbH - 001C1B (base 16) Hyperstone GmbH - Line-Eid-Straße 3 - Konstanz Baden-Württemberg 78467 - GERMANY - - 00-1C-1C (hex) Center Communication Systems GmbH - 001C1C (base 16) Center Communication Systems GmbH - Ignaz-Koeck-Strasse 19 - Vienna A-1210 - AUSTRIA - - 00-1C-1D (hex) CHENZHOU GOSPELL DIGITAL TECHNOLOGY CO.,LTD - 001C1D (base 16) CHENZHOU GOSPELL DIGITAL TECHNOLOGY CO.,LTD - BAILUTANG,SUXIAN DISTRICT, - CHENZHOU HUNAN 423025 - CHINA - - 00-1C-1E (hex) emtrion GmbH - 001C1E (base 16) emtrion GmbH - Alter Schlachthof 45 - Karlsruhe Baden Wuerttemberg 76131 - GERMANY - - 00-1C-1F (hex) Quest Retail Technology Pty Ltd - 001C1F (base 16) Quest Retail Technology Pty Ltd - 37-39 Walsh Street - Thebarton SA 5031 - AUSTRALIA - - 00-1C-20 (hex) CLB Benelux - 001C20 (base 16) CLB Benelux - Ramgatseweg 17 - Raamsdonksveer NBR 4941 VN - NETHERLANDS - - 00-1C-21 (hex) Nucsafe Inc. - 001C21 (base 16) Nucsafe Inc. - 601 Oak Ridge Turnpike - Oak Ridge Tennessee 37830 - UNITED STATES - - 00-1C-22 (hex) Aeris Elettronica s.r.l. - 001C22 (base 16) Aeris Elettronica s.r.l. - Zona Ind.le Vallecupa - Colonnella Teramo 64010 - ITALY - - 00-1C-23 (hex) Dell Inc - 001C23 (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-1C-24 (hex) Formosa Wireless Systems Corp. - 001C24 (base 16) Formosa Wireless Systems Corp. - No. 408, Guandong Rd., - HsinChu City 300 - TAIWAN, PROVINCE OF CHINA - - 00-1C-25 (hex) Hon Hai Precision Ind. Co.,Ltd. - 001C25 (base 16) Hon Hai Precision Ind. Co.,Ltd. - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-1C-26 (hex) Hon Hai Precision Ind. Co.,Ltd. - 001C26 (base 16) Hon Hai Precision Ind. Co.,Ltd. - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-1C-27 (hex) Sunell Electronics Co. - 001C27 (base 16) Sunell Electronics Co. - 3rd Floor,Bldg.514,BaGua Rd - Futian District - ShenZhen Guangdong 518029 - CHINA - - 00-1C-28 (hex) Sphairon Technologies GmbH - 001C28 (base 16) Sphairon Technologies GmbH - Philipp-Reis-Strasse 1 - Bautzen Saxony 02625 - GERMANY - - 00-1C-29 (hex) CORE DIGITAL ELECTRONICS CO., LTD - 001C29 (base 16) CORE DIGITAL ELECTRONICS CO., LTD - 1006# 102 CHUNUITECHNOPARK 200-1 - CHUNUI-DONG, WONMI-GU - BUCHEON-CITY GYUNGGI-DO 420-857 - KOREA, REPUBLIC OF - - 00-1C-2A (hex) Envisacor Technologies Inc. - 001C2A (base 16) Envisacor Technologies Inc. - 14845-6 Yonge Street, Suite 310 - Aurora ON L4G 6H8 - CANADA - - 00-1C-2B (hex) Alertme.com Limited - 001C2B (base 16) Alertme.com Limited - 30 Station Road - Cambridge Cambridgeshire CB1 2RE - UNITED KINGDOM - - 00-1C-2C (hex) Synapse - 001C2C (base 16) Synapse - 132 Export Circle - Huntsville AL 35806 - UNITED STATES - - 00-1C-2D (hex) FlexRadio Systems - 001C2D (base 16) FlexRadio Systems - 8900 Marybank Dr. - Austin TX 78750 - UNITED STATES - - 00-1C-2E (hex) HPN Supply Chain - 001C2E (base 16) HPN Supply Chain - 8000 Foothills Blvd - Roseville CA 95747 - UNITED STATES - - 00-1C-2F (hex) Pfister GmbH - 001C2F (base 16) Pfister GmbH - Stätzlinger SStraße 70 - Augsburg Bavaria 86165 - GERMANY - - 00-1C-30 (hex) Mode Lighting (UK ) Ltd. - 001C30 (base 16) Mode Lighting (UK ) Ltd. - The Maltings - 63 High Street - Ware Hertfordshire SG12 9AD - UNITED KINGDOM - - 00-1C-31 (hex) Mobile XP Technology Co., LTD - 001C31 (base 16) Mobile XP Technology Co., LTD - Room No.2506,Tri-tower C building,No.66 Zhongguancun East Road,Haidian District - Beijing 100080 - CHINA - - 00-1C-32 (hex) Telian Corporation - 001C32 (base 16) Telian Corporation - 4FL. Namjeon Bldg. 53-3 Haandong - Kwangmyungsi Kyoungkido 423060 - KOREA, REPUBLIC OF - - 00-1C-33 (hex) Sutron - 001C33 (base 16) Sutron - 21300 Ridgetop Cir - Sterling VA 20166 - UNITED STATES - - 00-1C-34 (hex) HUEY CHIAO INTERNATIONAL CO., LTD. - 001C34 (base 16) HUEY CHIAO INTERNATIONAL CO., LTD. - 5F, NO. 649-1, - CHUNG CHENG RD., - HSIN CHUANG CITY TAIPEI 242 - TAIWAN, PROVINCE OF CHINA - - 00-1C-35 (hex) Nokia Danmark A/S - 001C35 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790V - DENMARK - - 00-1C-36 (hex) iNEWiT NV - 001C36 (base 16) iNEWiT NV - Schaliënhoevedreef 20D - Mechelen Antwerp 2800 - BELGIUM - - 00-1C-37 (hex) Callpod, Inc. - 001C37 (base 16) Callpod, Inc. - 850 W. Jackson - Suite 260 - Chicago IL 60607 - UNITED STATES - - 00-1C-38 (hex) Bio-Rad Laboratories, Inc. - 001C38 (base 16) Bio-Rad Laboratories, Inc. - 245 Winter St. - Suite 100 - Waltham MA 02451 - UNITED STATES - - 00-1C-39 (hex) S Netsystems Inc. - 001C39 (base 16) S Netsystems Inc. - 10F Sungwon Bldg., 141 Samsung-Dong - Kangnam-Ku - Seoul 135-716 - KOREA, REPUBLIC OF - - 00-1C-3A (hex) Element Labs, Inc. - 001C3A (base 16) Element Labs, Inc. - 3350 Scott Boulevard - Building #2 - Santa Clara CA 95054 - UNITED STATES - - 00-1C-3B (hex) AmRoad Technology Inc. - 001C3B (base 16) AmRoad Technology Inc. - 18F-3 No. 150 , Chien I Rd - Chung Ho Taipei Hsien 23511 - TAIWAN, PROVINCE OF CHINA - - 00-1C-3C (hex) Seon Design Inc. - 001C3C (base 16) Seon Design Inc. - 111-3B Burbidge Street - Coquitlam BC V3K 7B2 - CANADA - - 00-1C-3D (hex) WaveStorm - 001C3D (base 16) WaveStorm - 40 Rue d'Oradour-sur-Glâne - Paris ÃŽle-de-France 75015 - FRANCE - - 00-1C-3E (hex) ECKey Corporation - 001C3E (base 16) ECKey Corporation - 206A W James St - Lancaster PA 17603 - UNITED STATES - - 00-1C-3F (hex) International Police Technologies, Inc. - 001C3F (base 16) International Police Technologies, Inc. - 4150 S. 87th E. Avenue - Tulsa OK 74145 - UNITED STATES - - 00-1C-40 (hex) VDG-Security bv - 001C40 (base 16) VDG-Security bv - Radonstraat 10-14 - Zoetermeer ZH 2718 TA - NETHERLANDS - - 00-1C-41 (hex) scemtec Transponder Technology GmbH - 001C41 (base 16) scemtec Transponder Technology GmbH - Wehrstr. 1 - Gummersbach NRW 51645 - GERMANY - - 00-1C-42 (hex) Parallels, Inc. - 001C42 (base 16) Parallels, Inc. - 660 SW 39h Street - Suite 205 - Renton WA 98057 - UNITED STATES - - 00-1C-43 (hex) Samsung Electronics Co.,Ltd - 001C43 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1C-44 (hex) Bosch Security Systems BV - 001C44 (base 16) Bosch Security Systems BV - Kapittelweg 10 - 4827 HG Breda Brabant 4827 - NETHERLANDS - - 00-1C-45 (hex) Chenbro Micom Co., Ltd. - 001C45 (base 16) Chenbro Micom Co., Ltd. - 15Fl., No. 150, Jian Yi Road - Chung Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-1C-46 (hex) QTUM - 001C46 (base 16) QTUM - #507 Byucksan/Kyungin Digital Valley 2 481-10 - Gasan-dong Geumcheon-gu - Seoul 153-783 - KOREA, REPUBLIC OF - - 00-1C-47 (hex) Hangzhou Hollysys Automation Co., Ltd - 001C47 (base 16) Hangzhou Hollysys Automation Co., Ltd - No.10 Middle Road, Jiancaicheng, Haidian District, - Beijing 100096 - CHINA - - 00-1C-48 (hex) WiDeFi, Inc. - 001C48 (base 16) WiDeFi, Inc. - 1333 Gateway Blvd - Suite 1012 - Melbourne FL 32901 - UNITED STATES - - 00-1C-49 (hex) Zoltan Technology Inc. - 001C49 (base 16) Zoltan Technology Inc. - 4F, No.30, Wunsi St. - Jhubei Hsinchu 302 - TAIWAN, PROVINCE OF CHINA - - 00-1C-4A (hex) AVM GmbH - 001C4A (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 00-1C-4B (hex) Gener8, Inc. - 001C4B (base 16) Gener8, Inc. - 897 Independence Ave - Mountain View CA 94043 - UNITED STATES - - 00-1C-4C (hex) Petrotest Instruments - 001C4C (base 16) Petrotest Instruments - Ludwig-Erhard-Ring 13 - Dahlewitz BBG 15827 - GERMANY - - 00-1C-4D (hex) Aplix IP Holdings Corporation - 001C4D (base 16) Aplix IP Holdings Corporation - 13F, Shinjuku Eastside Square 6-27-30, Shinjuku - Shinjuku-ku, Tokyo, 160-0022 - JAPAN - - 00-1C-4E (hex) TASA International Limited - 001C4E (base 16) TASA International Limited - 5F£¬Building2£¬No.1295 ,Xin Jinqiao Road, - Shanghai 201206 - CHINA - - 00-1C-4F (hex) MACAB AB - 001C4F (base 16) MACAB AB - Vannhögsgatan 7 - Trelleborg 23166 - SWEDEN - - 00-1C-50 (hex) TCL Technoly Electronics(Huizhou)Co.,Ltd - 001C50 (base 16) TCL Technoly Electronics(Huizhou)Co.,Ltd - 10/F, Block A , TCL Tower - 1 Gaoxin Nan Road, Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-1C-51 (hex) Celeno Communications - 001C51 (base 16) Celeno Communications - 22 Zarhin Street - Ra'anana 43665 - ISRAEL - - 00-1C-52 (hex) VISIONEE SRL - 001C52 (base 16) VISIONEE SRL - VIALE DELLA REPUBBLICA, 22 - VILLORBA TREVISO 31050 - ITALY - - 00-1C-53 (hex) Synergy Lighting Controls - 001C53 (base 16) Synergy Lighting Controls - One Lithonia Way - Conyers GA 30012 - UNITED STATES - - 00-1C-54 (hex) Hillstone Networks Inc - 001C54 (base 16) Hillstone Networks Inc - A-1905 e-Wing Center - Zhichun Road, Haidian - Beijing 100086 - CHINA - - 00-1C-55 (hex) Shenzhen Kaifa Technology Co. - 001C55 (base 16) Shenzhen Kaifa Technology Co. - 7006 Caitian Road, Futian District, - Shenzhen Guangdong 518035 - CHINA - - 00-1C-56 (hex) Pado Systems, Inc. - 001C56 (base 16) Pado Systems, Inc. - #706 Loadland EZ Tower 153 - Gumi-Dong, Bundang-Gu - SungNam Gyung gi-Do 463-810 - KOREA, REPUBLIC OF - - 00-1C-57 (hex) CISCO SYSTEMS, INC. - 001C57 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-58 (hex) CISCO SYSTEMS, INC. - 001C58 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-59 (hex) DEVON IT - 001C59 (base 16) DEVON IT - 1100 FIRST AVENUE - SUITE 100 - KING OF PRUSSIA PA 19406 - UNITED STATES - - 00-1C-5A (hex) Advanced Relay Corporation - 001C5A (base 16) Advanced Relay Corporation - 1896 Columbia St - Eugene OR 97403 - UNITED STATES - - 00-1C-5B (hex) Chubb Electronic Security Systems Ltd - 001C5B (base 16) Chubb Electronic Security Systems Ltd - Shadsworth Road - Blackburn Lancashire BB1 2PR - UNITED KINGDOM - - 00-1C-5C (hex) Integrated Medical Systems, Inc. - 001C5C (base 16) Integrated Medical Systems, Inc. - 1984 Obispo Avenue - Signal Hill CA 90755 - UNITED STATES - - 00-1C-5D (hex) Leica Microsystems - 001C5D (base 16) Leica Microsystems - Lothbury House Cambridge Technopark - Newmarket Road - Cambridge CB5 8PB - UNITED KINGDOM - - 00-1C-5E (hex) ASTON France - 001C5E (base 16) ASTON France - 151 Avenue Gallieni - BAGNOLET ile de france 93177 - FRANCE - - 00-1C-5F (hex) Winland Electronics, Inc. - 001C5F (base 16) Winland Electronics, Inc. - 1950 Excel Drive - Mankato MN 56001 - UNITED STATES - - 00-1C-60 (hex) CSP Frontier Technologies,Inc. - 001C60 (base 16) CSP Frontier Technologies,Inc. - 3-2-3,Sasazuka - Shibuya-ku Tokyo 151-0073 - JAPAN - - 00-1C-61 (hex) Galaxy Microsystems LImited - 001C61 (base 16) Galaxy Microsystems LImited - Room 1101-03, 11/F Enterprise Square Two - 3 Sheung Yuet Road - Kowloon Bay Kowloon - HONG KONG - - 00-1C-62 (hex) LG Electronics Inc - 001C62 (base 16) LG Electronics Inc - 60-39, Gasan-Dong - Kumchon-Gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-1C-63 (hex) TRUEN - 001C63 (base 16) TRUEN - 4F SAMWON BLDG., 451-7 - BANGBAE-DONG, SEOCHO-GU - SEOUL 137-818 - KOREA, REPUBLIC OF - - 00-1C-64 (hex) Landis+Gyr - 001C64 (base 16) Landis+Gyr - 30000 Mill Creek Ave. Suite 100 - Alpharetta GA 30022 - UNITED STATES - - 00-1C-65 (hex) JoeScan, Inc. - 001C65 (base 16) JoeScan, Inc. - 4510 NE 68th Dr, Ste. 124 - Vancouver WA 98661 - UNITED STATES - - 00-1C-66 (hex) UCAMP CO.,LTD - 001C66 (base 16) UCAMP CO.,LTD - #1015, Kolon Science Valley ¥± - Seoul Guro-Dong,Guro-gu, 152-848 - KOREA, REPUBLIC OF - - 00-1C-67 (hex) Pumpkin Networks, Inc. - 001C67 (base 16) Pumpkin Networks, Inc. - 3FL JungHo Bldg, 108-4 Sangdo-Dong, Dongjak-Gu - SEOUL 156-030 - KOREA, REPUBLIC OF - - 00-1C-68 (hex) Anhui Sun Create Electronics Co., Ltd - 001C68 (base 16) Anhui Sun Create Electronics Co., Ltd - NO.199 Xiangzhang Road - Hefei Anhui 230088 - CHINA - - 00-1C-69 (hex) Packet Vision Ltd - 001C69 (base 16) Packet Vision Ltd - SC House - Vanwall Road - Maidenhead Berks SL6 4UB - UNITED KINGDOM - - 00-1C-6A (hex) Weiss Engineering Ltd. - 001C6A (base 16) Weiss Engineering Ltd. - Florastrasse 42 - Uster ZH 8610 - SWITZERLAND - - 00-1C-6B (hex) COVAX Co. Ltd - 001C6B (base 16) COVAX Co. Ltd - 3-27-22 kitahanada-cho kitaku - sakai-shi oosaka 591-8002 - JAPAN - - 00-1C-6C (hex) Jabil Circuit (Guangzhou) Limited - 001C6C (base 16) Jabil Circuit (Guangzhou) Limited - 128, Jun Cheng Road,uangzhou Economic and Technological Development District - Guangdong Province - Guangzhou Guangdong 510530 - CHINA - - 00-1C-6D (hex) KYOHRITSU ELECTRONIC INDUSTRY CO., LTD. - 001C6D (base 16) KYOHRITSU ELECTRONIC INDUSTRY CO., LTD. - 2-5-1, NIPPONBASHI-NISHI, - NANIWA-KU - OSAKA 556-0004 - JAPAN - - 00-1C-6E (hex) Newbury Networks, Inc. - 001C6E (base 16) Newbury Networks, Inc. - 419 Boylston Street - Boston MA 02116 - UNITED STATES - - 00-1C-6F (hex) Emfit Ltd - 001C6F (base 16) Emfit Ltd - Konttisentie 8 B - Vaajakoski 40800 - FINLAND - - 00-1C-70 (hex) NOVACOMM LTDA - 001C70 (base 16) NOVACOMM LTDA - RUA BEIJUI, 70 - SANTO AMARO - São Paulo 04689-000 - BRAZIL - - 00-1C-71 (hex) Emergent Electronics - 001C71 (base 16) Emergent Electronics - Bldg 2 Level 3 Suite 305 - 2591 Wexford-Bayne Road - Sewickley PA 15143 - UNITED STATES - - 00-1C-72 (hex) Mayer & Cie GmbH & Co KG - 001C72 (base 16) Mayer & Cie GmbH & Co KG - Emil Mayer Strasse 10 - Albstadt Baden-Württemberg 72461 - GERMANY - - 00-1C-73 (hex) Arista Networks, Inc. - 001C73 (base 16) Arista Networks, Inc. - 5470 Great America Pkwy - Santa Clara California 95054 - UNITED STATES - - 00-1C-74 (hex) Syswan Technologies Inc. - 001C74 (base 16) Syswan Technologies Inc. - 2050 Beavercreek Road - Suite 101 #388 - Oregon City Oregon 97045 - UNITED STATES - - 00-1C-75 (hex) Segnet Ltd. - 001C75 (base 16) Segnet Ltd. - 146 New London Road - Chelmsford Essex CM2 OAW - UNITED KINGDOM - - 00-1C-76 (hex) The Wandsworth Group Ltd - 001C76 (base 16) The Wandsworth Group Ltd - Albert Drive - Sheerwater - Woking Surrey GU21 5SE - UNITED KINGDOM - - 00-1C-77 (hex) Prodys - 001C77 (base 16) Prodys - C/Trigo 54 Pol. Ind. Polvoranca - Leganes MADRID 28914 - SPAIN - - 00-1C-78 (hex) WYPLAY SAS - 001C78 (base 16) WYPLAY SAS - 200 avenue de Provence - ALLAUCH BdR 13190 - FRANCE - - 00-1C-79 (hex) Cohesive Financial Technologies LLC - 001C79 (base 16) Cohesive Financial Technologies LLC - 200 South Wacker Dr. - Suite 1500 - Chicago IL 60606 - UNITED STATES - - 00-1C-7A (hex) Perfectone Netware Company Ltd - 001C7A (base 16) Perfectone Netware Company Ltd - Unit 815, Sun Fung Centre, - Kwok Shui Rd, - Kwai Chung - HONG KONG - - 00-1C-7B (hex) Castlenet Technology Inc. - 001C7B (base 16) Castlenet Technology Inc. - No.64, Chung-Shan Rd. - Tu-Cheng City Taipei 236 - TAIWAN, PROVINCE OF CHINA - - 00-1C-7C (hex) PERQ SYSTEMS CORPORATION - 001C7C (base 16) PERQ SYSTEMS CORPORATION - 2600 LIBERETY AVENUE - P.O. BOX 2600 - PITTSBURGH PA 15230 - UNITED STATES - - 00-1C-7D (hex) Excelpoint Manufacturing Pte Ltd - 001C7D (base 16) Excelpoint Manufacturing Pte Ltd - 15, Changi Business Park - Central 1, 5th Level - 486057 - SINGAPORE - - 00-1C-7E (hex) Toshiba - 001C7E (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - 00-1C-7F (hex) Check Point Software Technologies - 001C7F (base 16) Check Point Software Technologies - 3A Jabotinsky St. - Diamond Tower - Ramat Gan 52520 - ISRAEL - - 00-1C-80 (hex) New Business Division/Rhea-Information CO., LTD. - 001C80 (base 16) New Business Division/Rhea-Information CO., LTD. - 4F 594 Yeong Pung Bldg, Gueui-Dong - Seoul Gwangjin-Gu 143-200 - KOREA, REPUBLIC OF - - 00-1C-81 (hex) NextGen Venturi LTD - 001C81 (base 16) NextGen Venturi LTD - Technium 2 - Kings Road - Swansea West Glamorgan SA18PJ - UNITED KINGDOM - - 00-1C-82 (hex) Genew Technologies - 001C82 (base 16) Genew Technologies - 3A3 Building B1, Cyber-tech Zone, - Gaoxin Ave. 7S, Hi-tech Industrial Park, - Shenzhen Guangdong 518057 - CHINA - - 00-1C-83 (hex) New Level Telecom Co., Ltd. - 001C83 (base 16) New Level Telecom Co., Ltd. - INNOPLEX 1-703 - 371-47, Gasan-Dong, Geumcheon-Gu - Seoul 153-803 - KOREA, REPUBLIC OF - - 00-1C-84 (hex) STL Solution Co.,Ltd. - 001C84 (base 16) STL Solution Co.,Ltd. - #710, World Meridian Venture Center I - 60-24, Gasan-dong, Geumcheon-gu - Seoul 152781 - KOREA, REPUBLIC OF - - 00-1C-85 (hex) Eunicorn - 001C85 (base 16) Eunicorn - 226-16 unbo b/d suckchon-dong songpa-gu - seoul 138845 - KOREA, REPUBLIC OF - - 00-1C-86 (hex) Cranite Systems, Inc. - 001C86 (base 16) Cranite Systems, Inc. - 121 Albright Way - Los Gatos CA 95032 - UNITED STATES - - 00-1C-87 (hex) Uriver Inc. - 001C87 (base 16) Uriver Inc. - 3rd., Fl., Bogwang Bldg., Poi-dong, 238-7 Gangnam-gu, - Seoul 135-964 - KOREA, REPUBLIC OF - - 00-1C-88 (hex) TRANSYSTEM INC. - 001C88 (base 16) TRANSYSTEM INC. - No. 1-2, Li-Hsin Rd 1, Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1C-89 (hex) Force Communications, Inc. - 001C89 (base 16) Force Communications, Inc. - PO Box 250286 - Plano TX 75025 - UNITED STATES - - 00-1C-8A (hex) Cirrascale Corporation - 001C8A (base 16) Cirrascale Corporation - 9449 Carroll Park Drive - San Diego CA 92121 - UNITED STATES - - 00-1C-8B (hex) MJ Innovations Ltd. - 001C8B (base 16) MJ Innovations Ltd. - 333 Wyecroft Road - Unit 3 - Oakville Ontario L6K 2H2 - CANADA - - 00-1C-8C (hex) DIAL TECHNOLOGY LTD. - 001C8C (base 16) DIAL TECHNOLOGY LTD. - 6F-4, NO.18, LANE.609, SEC.5, CHONGSIN RD., - SANCHONG CITY TAIPEI COUNTY 241 - TAIWAN, PROVINCE OF CHINA - - 00-1C-8D (hex) Mesa Imaging - 001C8D (base 16) Mesa Imaging - Badenerstrasse 569 - Zürich ZH 8048 - SWITZERLAND - - 00-1C-8E (hex) Alcatel-Lucent IPD - 001C8E (base 16) Alcatel-Lucent IPD - 701 E. Middlefield Rd. - Mountain View CA 94043 - UNITED STATES - - 00-1C-8F (hex) Advanced Electronic Design, Inc. - 001C8F (base 16) Advanced Electronic Design, Inc. - 344 John L Dietsch Blvd., Unit #2 - North Attleboro MA 02763 - UNITED STATES - - 00-1C-90 (hex) Empacket Corporation - 001C90 (base 16) Empacket Corporation - 2-6-3 Nishi-Gotanda - Shinagawa Tokyo 141-0031 - JAPAN - - 00-1C-91 (hex) Gefen Inc. - 001C91 (base 16) Gefen Inc. - 20600 Nordhoff Street - Chatsworth CA 91311 - UNITED STATES - - 00-1C-92 (hex) Tervela - 001C92 (base 16) Tervela - 43 Nagog Park - Suite 201 - Acton MA 01720 - UNITED STATES - - 00-1C-93 (hex) ExaDigm Inc - 001C93 (base 16) ExaDigm Inc - 2871 Pullman St - Santa Ana CA 92705 - UNITED STATES - - 00-1C-94 (hex) LI-COR Biosciences - 001C94 (base 16) LI-COR Biosciences - 4647 Superior Street - Lincoln NE 68504 - UNITED STATES - - 00-1C-95 (hex) Opticomm Corporation - 001C95 (base 16) Opticomm Corporation - 6827 Nancy Ridge Dr - San Diego CA 92121 - UNITED STATES - - 00-1C-96 (hex) Linkwise Technology Pte Ltd - 001C96 (base 16) Linkwise Technology Pte Ltd - Blk 3, Ang Mo Kio Industrial Park 2A - #06-08. AMK Tech I - 568050 - SINGAPORE - - 00-1C-97 (hex) Enzytek Technology Inc., - 001C97 (base 16) Enzytek Technology Inc., - 7F, No.35, Hsueh Fu Rd., - Hsinchu 300, - TAIWAN, PROVINCE OF CHINA - - 00-1C-98 (hex) LUCKY TECHNOLOGY (HK) COMPANY LIMITED - 001C98 (base 16) LUCKY TECHNOLOGY (HK) COMPANY LIMITED - FLAT/RM 1503 15/F ISLAND BEVERLEY NO 1 GREAT GEORGE STREET CAUSEWAY BAY - 999077 - HONG KONG - - 00-1C-99 (hex) Shunra Software Ltd. - 001C99 (base 16) Shunra Software Ltd. - 20 Hata'as St. - Kefar-Saba 44425 - ISRAEL - - 00-1C-9A (hex) Nokia Danmark A/S - 001C9A (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1C-9B (hex) FEIG ELECTRONIC GmbH - 001C9B (base 16) FEIG ELECTRONIC GmbH - Lange Straße 4 - Weilburg Hessen 35781 - GERMANY - - 00-1C-9C (hex) Nortel - 001C9C (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1C-9D (hex) Liecthi AG - 001C9D (base 16) Liecthi AG - 10 Unterholz Street - Kriegstetten Solothurn 4566 - SWITZERLAND - - 00-1C-9E (hex) Dualtech IT AB - 001C9E (base 16) Dualtech IT AB - Banehagsgatan 1F - GOTHENBURG Västra Götaland 41451 - SWEDEN - - 00-1C-9F (hex) Razorstream, LLC - 001C9F (base 16) Razorstream, LLC - 2381-C Renaissance Drive - Las Vegas NV 89119 - UNITED STATES - - 00-1C-A0 (hex) Production Resource Group, LLC - 001CA0 (base 16) Production Resource Group, LLC - 539 Temple Hill Road - New Windsor NY 12553 - UNITED STATES - - 00-1C-A1 (hex) AKAMAI TECHNOLOGIES, INC. - 001CA1 (base 16) AKAMAI TECHNOLOGIES, INC. - 8 CAMBRIDGE CENTER - CAMBRIDGE MA 02142 - UNITED STATES - - 00-1C-A2 (hex) ADB Broadband Italia - 001CA2 (base 16) ADB Broadband Italia - VIALE SARCA 222 - MILANO 20126 - ITALY - - 00-1C-A3 (hex) Terra - 001CA3 (base 16) Terra - Draugystes str. 22 - Kaunas LT-51256 - LITHUANIA - - 00-1C-A4 (hex) Sony Ericsson Mobile Communications - 001CA4 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-1C-A5 (hex) Zygo Corporation - 001CA5 (base 16) Zygo Corporation - 21 Laurel Brook Rd. - Middlefield CT 06455 - UNITED STATES - - 00-1C-A6 (hex) Win4NET - 001CA6 (base 16) Win4NET - 1301 KOLON Digital Tower, - 222-7 Kuro-dong - Kuro-gu Seoul 152-848 - KOREA, REPUBLIC OF - - 00-1C-A7 (hex) International Quartz Limited - 001CA7 (base 16) International Quartz Limited - 2nd Floor, 2, Dai Wang Street, - Tai Po Industrial Estate, Tai Po, N.T. - Hong Kong 852 - CHINA - - 00-1C-A8 (hex) AirTies Wireless Networks - 001CA8 (base 16) AirTies Wireless Networks - Buyukdere Cad No 103 Kat 5 - Mecidiyekoy, Istanbul 34460 - TURKEY - - 00-1C-A9 (hex) Audiomatica Srl - 001CA9 (base 16) Audiomatica Srl - Via Manfredi 12 - Florence Italy 50136 - ITALY - - 00-1C-AA (hex) Bellon Pty Ltd - 001CAA (base 16) Bellon Pty Ltd - Unit 12/12-18 Victoria St East - Lidcombe NSW 2000 - AUSTRALIA - - 00-1C-AB (hex) Meyer Sound Laboratories, Inc. - 001CAB (base 16) Meyer Sound Laboratories, Inc. - 2832 San Pablo Ave. - Berkeley CA 94702 - UNITED STATES - - 00-1C-AC (hex) Qniq Technology Corp. - 001CAC (base 16) Qniq Technology Corp. - 5F, No.133, Sec.4, Minsheng E. Rd., - Songshan District, - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 00-1C-AD (hex) Wuhan Telecommunication Devices Co.,Ltd - 001CAD (base 16) Wuhan Telecommunication Devices Co.,Ltd - 88 Youkeyuan Road,Hongshan District - Wuhan Hubei 430074 - CHINA - - 00-1C-AE (hex) WiChorus, Inc. - 001CAE (base 16) WiChorus, Inc. - 3590 N 1st Street, Suite 300 - San Jose CA 95134 - UNITED STATES - - 00-1C-AF (hex) Plato Networks Inc. - 001CAF (base 16) Plato Networks Inc. - 2855 Kifer Road - Suite 204 - Santa Clara CA 95051 - UNITED STATES - - 00-1C-B0 (hex) CISCO SYSTEMS, INC. - 001CB0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-B1 (hex) CISCO SYSTEMS, INC. - 001CB1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-B2 (hex) BPT SPA - 001CB2 (base 16) BPT SPA - Via Stazione,48 - Sesto al Reghena Pordenone 33079 - ITALY - - 00-1C-B3 (hex) Apple - 001CB3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-1C-B4 (hex) Iridium Satellite LLC - 001CB4 (base 16) Iridium Satellite LLC - 8440 S. River Parkway - Tempe AZ 85284 - UNITED STATES - - 00-1C-B5 (hex) Neihua Network Technology Co.,LTD.(NHN) - 001CB5 (base 16) Neihua Network Technology Co.,LTD.(NHN) - Plot Xinmei Road 102-Q,New District - WuXi Jiangsu 214028 - CHINA - - 00-1C-B6 (hex) Duzon CNT Co., Ltd. - 001CB6 (base 16) Duzon CNT Co., Ltd. - 14th Floor, IRE building 2 - Yangpyung-dong 4ga, Youngdungpo-gu - Seoul 150-967 - KOREA, REPUBLIC OF - - 00-1C-B7 (hex) USC DigiArk Corporation - 001CB7 (base 16) USC DigiArk Corporation - 6F Tennoz Central Tower 2-2-24 Higashishinagawa - Tokyo Shinagawa-ku 140-0002 - JAPAN - - 00-1C-B8 (hex) CBC Co., Ltd - 001CB8 (base 16) CBC Co., Ltd - 2-15-13, Tsukishima, Chuo-ku - Tokyo 104-0052 - JAPAN - - 00-1C-B9 (hex) KWANG SUNG ELECTRONICS CO., LTD. - 001CB9 (base 16) KWANG SUNG ELECTRONICS CO., LTD. - 201, WORLD VENTURE TOWN 60-24, GASAN-DONG GEUMCHUN-GU, - SEOUL 153-801 - KOREA, REPUBLIC OF - - 00-1C-BA (hex) VerScient, Inc. - 001CBA (base 16) VerScient, Inc. - 7700 Equitable Drive - Suite 100 - Eden Prairie MN 55344 - UNITED STATES - - 00-1C-BB (hex) MusicianLink - 001CBB (base 16) MusicianLink - 2401 Cory Ave. - San Jose CA 95128 - UNITED STATES - - 00-1C-BC (hex) CastGrabber, LLC - 001CBC (base 16) CastGrabber, LLC - 6507 Wilkins Avenue Ste. 212 - Pittsburgh PA 15217 - UNITED STATES - - 00-1C-BD (hex) Ezze Mobile Tech., Inc. - 001CBD (base 16) Ezze Mobile Tech., Inc. - 3F, Bubmusa Bldg., 151-31 - Nonhyun-dong, Kangnam-ku - Seoul 135-824 - KOREA, REPUBLIC OF - - 00-1C-BE (hex) Nintendo Co., Ltd. - 001CBE (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1C-BF (hex) Intel Corporate - 001CBF (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1C-C0 (hex) Intel Corporate - 001CC0 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1C-C1 (hex) ARRIS Group, Inc. - 001CC1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1C-C2 (hex) Part II Research, Inc. - 001CC2 (base 16) Part II Research, Inc. - 4601 E. Airport Dr. - Ontario CA 91761 - UNITED STATES - - 00-1C-C3 (hex) Pace plc - 001CC3 (base 16) Pace plc - Salts Mill - Victoria Road - Bradford West Yorkshire BD18 3LF - UNITED KINGDOM - - 00-1C-C4 (hex) Hewlett-Packard Company - 001CC4 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - ms040801 - Houston TX 77070 - UNITED STATES - - 00-1C-C5 (hex) 3COM LTD - 001CC5 (base 16) 3COM LTD - 3Com Europe Ltd, Peoplebuilding 2 - Peoplebuilding Estate, Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 00-1C-C6 (hex) ProStor Systems - 001CC6 (base 16) ProStor Systems - 5555 Central Avenue - Suite 100 - Boulder Colorado 80301 - UNITED STATES - - 00-1C-C7 (hex) Rembrandt Technologies, LLC d/b/a REMSTREAM - 001CC7 (base 16) Rembrandt Technologies, LLC d/b/a REMSTREAM - 140 South Beverly Drive - Suite 203 - Beverly Hills CA 90212 - UNITED STATES - - 00-1C-C8 (hex) INDUSTRONIC Industrie-Electronic GmbH & Co. KG - 001CC8 (base 16) INDUSTRONIC Industrie-Electronic GmbH & Co. KG - Carl-Jacob-Kolb-Weg 1 - Wertheim Baden-Württemberg 97877 - GERMANY - - 00-1C-C9 (hex) Kaise Electronic Technology Co., Ltd. - 001CC9 (base 16) Kaise Electronic Technology Co., Ltd. - No.678, Wunsyue Rd., Zuoying District, - Kaohsiung 813 - TAIWAN, PROVINCE OF CHINA - - 00-1C-CA (hex) Shanghai Gaozhi Science & Technology Development Co. - 001CCA (base 16) Shanghai Gaozhi Science & Technology Development Co. - No.283 Qin Jiang Rd. Shanghai,China - Shanghai 200233 - CHINA - - 00-1C-CB (hex) Forth Corporation Public Company Limited - 001CCB (base 16) Forth Corporation Public Company Limited - 226/12,13,16 Paholyothin Road - Samsennai, Payathai - Bangkok 10400 - THAILAND - - 00-1C-CC (hex) Research In Motion Limited - 001CCC (base 16) Research In Motion Limited - 305 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 00-1C-CD (hex) Alektrona Corporation - 001CCD (base 16) Alektrona Corporation - 95 Hathaway Street, Suite 10 - Providence RI 02907 - UNITED STATES - - 00-1C-CE (hex) By Techdesign - 001CCE (base 16) By Techdesign - C/ Tomas Edison 5 - Arganda del Rey Madrid 28500 - SPAIN - - 00-1C-CF (hex) LIMETEK - 001CCF (base 16) LIMETEK - #213-1, Byucksan Digital Valley II, 480-10, Gasan-dong, - Geumchen-gu - Seoul 153-783 - KOREA, REPUBLIC OF - - 00-1C-D0 (hex) Circleone Co.,Ltd. - 001CD0 (base 16) Circleone Co.,Ltd. - 860-1,Noda - Beppu-shi Ooita-ken 874-0016 - JAPAN - - 00-1C-D1 (hex) Waves Audio LTD - 001CD1 (base 16) Waves Audio LTD - Azrilei Center 3, Triangle tower - 32nd floor - Tel Aviv Central 67023 - ISRAEL - - 00-1C-D2 (hex) King Champion (Hong Kong) Limited - 001CD2 (base 16) King Champion (Hong Kong) Limited - Unit 1520, 15/F, Phase 1, Metro Centre, - 32 Lam Hing Street, Kowloon Bay, - Kowloon - HONG KONG - - 00-1C-D3 (hex) ZP Engineering SEL - 001CD3 (base 16) ZP Engineering SEL - via Ardito Desio, 60 - Tecnopolo Tiburtino - ROME 00131 - ITALY - - 00-1C-D4 (hex) Nokia Danmark A/S - 001CD4 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1C-D5 (hex) ZeeVee, Inc. - 001CD5 (base 16) ZeeVee, Inc. - 1 Monarch Drive - Suite 200 - Littleton MA 01460 - UNITED STATES - - 00-1C-D6 (hex) Nokia Danmark A/S - 001CD6 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1C-D7 (hex) Harman/Becker Automotive Systems GmbH - 001CD7 (base 16) Harman/Becker Automotive Systems GmbH - Becker-Göring-Straße 16 - Karlsbad Baden-Württemberg 76307 - GERMANY - - 00-1C-D8 (hex) BlueAnt Wireless - 001CD8 (base 16) BlueAnt Wireless - 245 St.Kilda Rd, St Kilda - Melbourne Victoria 3182 - AUSTRALIA - - 00-1C-D9 (hex) GlobalTop Technology Inc. - 001CD9 (base 16) GlobalTop Technology Inc. - 16 Nan-ke 9th Rd. Science-base Industrial Park, - ShanHua Tainan county 741 - TAIWAN, PROVINCE OF CHINA - - 00-1C-DA (hex) Exegin Technologies Limited - 001CDA (base 16) Exegin Technologies Limited - 401 - 2071 Kingsway Avenue - Port Coquitlam BC V3C 6N2 - CANADA - - 00-1C-DB (hex) CARPOINT CO.,LTD - 001CDB (base 16) CARPOINT CO.,LTD - 1340-6, Namgang Bld 7F, Seocho-Dong - Seocho-Ku, - SEOUL 137-070 - KOREA, REPUBLIC OF - - 00-1C-DC (hex) Custom Computer Services, Inc. - 001CDC (base 16) Custom Computer Services, Inc. - 1020 Spring City Drive - Waukesha WI 53186 - UNITED STATES - - 00-1C-DD (hex) COWBELL ENGINEERING CO., LTD. - 001CDD (base 16) COWBELL ENGINEERING CO., LTD. - 1739-1 Nagatoro - SAKU Nagano 385-0021 - JAPAN - - 00-1C-DE (hex) Interactive Multimedia eXchange Inc. - 001CDE (base 16) Interactive Multimedia eXchange Inc. - NO. 165 Wenlin Road. - Taipei Taiwan 111 - TAIWAN, PROVINCE OF CHINA - - 00-1C-DF (hex) Belkin International Inc. - 001CDF (base 16) Belkin International Inc. - 12045 E. Waterfront Drive - Playa Vista Ca 90094 - UNITED STATES - - 00-1C-E0 (hex) DASAN TPS - 001CE0 (base 16) DASAN TPS - HUMAX Village 6F, 11-4 Sunae-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-825 - KOREA, REPUBLIC OF - - 00-1C-E1 (hex) INDRA SISTEMAS, S.A. - 001CE1 (base 16) INDRA SISTEMAS, S.A. - Ctra. de Loeches, n.º 9 - Torrejón de Ardoz MADRID 28850 - SPAIN - - 00-1C-E2 (hex) Attero Tech, LLC. - 001CE2 (base 16) Attero Tech, LLC. - 1315 Directors Row - Suite 107 - Fort Wayne Indiana 46808 - UNITED STATES - - 00-1C-E3 (hex) Optimedical Systems - 001CE3 (base 16) Optimedical Systems - 235 Hembree Park Drive - Roswell GA 30076 - UNITED STATES - - 00-1C-E4 (hex) EleSy JSC - 001CE4 (base 16) EleSy JSC - Altayskaya street, 161a - Tomsk oblast 634021 - RUSSIAN FEDERATION - - 00-1C-E5 (hex) MBS Electronic Systems GmbH - 001CE5 (base 16) MBS Electronic Systems GmbH - Ringstrasse 3 - 82319 Starnberg Bavaria 82319 - GERMANY - - 00-1C-E6 (hex) INNES - 001CE6 (base 16) INNES - ZAC Atalante Champeaux - 5A rue Pierre Joseph Colin - RENNES 35000 - FRANCE - - 00-1C-E7 (hex) Rocon PLC Research Centre - 001CE7 (base 16) Rocon PLC Research Centre - 21 Vek 56A str. - Sofia 1700 - BULGARIA - - 00-1C-E8 (hex) Cummins Inc - 001CE8 (base 16) Cummins Inc - 1400 73rd Ave NE - Fridley MN 55432 - UNITED STATES - - 00-1C-E9 (hex) Galaxy Technology Limited - 001CE9 (base 16) Galaxy Technology Limited - 9/F Win Full Commerical Building, 172-176 Wing Lok Street, - Sheung Wan, - HONG KONG - - 00-1C-EA (hex) Scientific-Atlanta, Inc - 001CEA (base 16) Scientific-Atlanta, Inc - 5030 Sugarloaf Pkwy - ATL 2.T.603 - Lawrenceville GA 30044 - UNITED STATES - - 00-1C-EB (hex) Nortel - 001CEB (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1C-EC (hex) Mobilesoft (Aust.) Pty Ltd - 001CEC (base 16) Mobilesoft (Aust.) Pty Ltd - Suite 2, 27-35 Grosvenor Street - Neutral Bay - Sydney NSW 2089 - AUSTRALIA - - 00-1C-ED (hex) ENVIRONNEMENT SA - 001CED (base 16) ENVIRONNEMENT SA - 111 bd. Robespierre - POISSY Yvelines 78300 - FRANCE - - 00-1C-EE (hex) SHARP Corporation - 001CEE (base 16) SHARP Corporation - 22-22,Nagaike-cho - Abeno-ku - Osaka city Osaka prefecture 545-8522 - JAPAN - - 00-1C-EF (hex) Primax Electronics LTD - 001CEF (base 16) Primax Electronics LTD - 669, Ruey Kuang Road, Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1C-F0 (hex) D-Link Corporation - 001CF0 (base 16) D-Link Corporation - NO.289, Sinhu 3rd Rd., - Neihu District, Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-1C-F1 (hex) SUPoX Technology Co. , LTD. - 001CF1 (base 16) SUPoX Technology Co. , LTD. - 7F, 419 , Chung San Rd. , Sec 2 - Chung Ho Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-1C-F2 (hex) Tenlon Technology Co.,Ltd. - 001CF2 (base 16) Tenlon Technology Co.,Ltd. - 4/F.,Shenhua Bldg,No.3155,Binhe Road,Futian District - Shenzhen Guangdong 518033 - CHINA - - 00-1C-F3 (hex) EVS BROADCAST EQUIPMENT - 001CF3 (base 16) EVS BROADCAST EQUIPMENT - Liege Science Park - rue Bois St Jean 16 - Ougree Liege 4102 - BELGIUM - - 00-1C-F4 (hex) Media Technology Systems Inc - 001CF4 (base 16) Media Technology Systems Inc - 766 Lakefield Road - Unit F - Westlake Village CA 91377 - UNITED STATES - - 00-1C-F5 (hex) Wiseblue Technology Limited - 001CF5 (base 16) Wiseblue Technology Limited - Rm G5, 5/F, Kingsford Industrial Building Phase II, 26-32 Kwai Hei Street, - Kwai Chung N.T. - HONG KONG - - 00-1C-F6 (hex) CISCO SYSTEMS, INC. - 001CF6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-F7 (hex) AudioScience - 001CF7 (base 16) AudioScience - 729 west 16th st - Suite C2 - Costa Mesa California 92627 - UNITED STATES - - 00-1C-F8 (hex) Parade Technologies, Ltd. - 001CF8 (base 16) Parade Technologies, Ltd. - C/O Parade Technologies, Inc. - 530 Lakeside Dr. Suite 230 - Sunnyvale CA 94085 - UNITED STATES - - 00-1C-F9 (hex) CISCO SYSTEMS, INC. - 001CF9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1C-FA (hex) Alarm.com - 001CFA (base 16) Alarm.com - 8150 Leesburg Pike - Suite 1400 - Vienna VA 22182 - UNITED STATES - - 00-1C-FB (hex) ARRIS Group, Inc. - 001CFB (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1C-FC (hex) Suminet Communication Technologies (Shanghai) Co., Ltd. - 001CFC (base 16) Suminet Communication Technologies (Shanghai) Co., Ltd. - 4F, 3Bld. 647 Long, SongTao Road, ZhangJiang Hi-Tech Park - Shanghai 201203 - CHINA - - 00-1C-FD (hex) Universal Electronics - 001CFD (base 16) Universal Electronics - 6101 Gateway Drive - Cypress California 90630 - UNITED STATES - - 00-1C-FE (hex) Quartics Inc - 001CFE (base 16) Quartics Inc - 15241 Laguna Canyon Road - Ste 200 - Irvine CA 92618 - UNITED STATES - - 00-1C-FF (hex) Napera Networks Inc - 001CFF (base 16) Napera Networks Inc - 7683 SE 27th - Suite 120 - Mercer Island WA 98040 - UNITED STATES - - 00-1D-00 (hex) Brivo Systems, LLC - 001D00 (base 16) Brivo Systems, LLC - 4330 East West Highway - Suite 250 - Bethesda MD 20814 - UNITED STATES - - 00-1D-01 (hex) Neptune Digital - 001D01 (base 16) Neptune Digital - Mednarodni mejni prehod 6 - Vrtojba Nova Gorica 5290 - SLOVENIA - - 00-1D-02 (hex) Cybertech Telecom Development - 001D02 (base 16) Cybertech Telecom Development - Hazenkoog 25 - Alkmaar Noord Holland 1822 BS - NETHERLANDS - - 00-1D-03 (hex) Design Solutions Inc. - 001D03 (base 16) Design Solutions Inc. - 81 David Love Place - Goleta Ca 93117 - UNITED STATES - - 00-1D-04 (hex) Zipit Wireless, Inc. - 001D04 (base 16) Zipit Wireless, Inc. - 49 Salters Road. - Suite 6 - Greenville SC 29607 - UNITED STATES - - 00-1D-05 (hex) Eaton Corporation - 001D05 (base 16) Eaton Corporation - 203 Cooper Circle - Peachtree City GA 30269 - UNITED STATES - - 00-1D-06 (hex) HM Electronics, Inc. - 001D06 (base 16) HM Electronics, Inc. - 14110 Stowe Drive - Poway CA 92064 - UNITED STATES - - 00-1D-07 (hex) Shenzhen Sang Fei Consumer Communications Co.,Ltd - 001D07 (base 16) Shenzhen Sang Fei Consumer Communications Co.,Ltd - 11 Science and Technology Road, - Science and Technology Industrial Park Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - 00-1D-08 (hex) JIANGSU YINHE ELECTRONICS CO., LTD - 001D08 (base 16) JIANGSU YINHE ELECTRONICS CO., LTD - 188 NANHUAN ROAD - TANGQIAO - ZHANGJIAGANG JIANGSU 215611 - CHINA - - 00-1D-09 (hex) Dell Inc - 001D09 (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-1D-0A (hex) Davis Instruments, Inc. - 001D0A (base 16) Davis Instruments, Inc. - 3465 Diablo Ave. - Hayward CA 94545 - UNITED STATES - - 00-1D-0B (hex) Power Standards Lab - 001D0B (base 16) Power Standards Lab - 1201 Marina Village Parkway #101 - Alameda CA 94501 - UNITED STATES - - 00-1D-0C (hex) MobileCompia - 001D0C (base 16) MobileCompia - Dongwon Bldg, 725-30, Yeoksam-dong, Gangnam-gu, - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-1D-0D (hex) Sony Computer Entertainment inc. - 001D0D (base 16) Sony Computer Entertainment inc. - 6-21,2Chome - Minami-Aoyama - Minato-Ku Tokyo 107-0062 - JAPAN - - 00-1D-0E (hex) Agapha Technology co., Ltd. - 001D0E (base 16) Agapha Technology co., Ltd. - 9F No.121, Shingde Rd., - Sanchung City Taipei County 241 - TAIWAN, PROVINCE OF CHINA - - 00-1D-0F (hex) TP-LINK Technologies Co., Ltd. - 001D0F (base 16) TP-LINK Technologies Co., Ltd. - 3/F, Bldg. R1-B, - Hi-tech Industrial Park, Shennan Rd., - Shenzhen Guangdong 518057 - CHINA - - 00-1D-10 (hex) LightHaus Logic, Inc. - 001D10 (base 16) LightHaus Logic, Inc. - 126-1020 Mainland Street - Vancouver BC V6B 2T4 - CANADA - - 00-1D-11 (hex) Analogue & Micro Ltd - 001D11 (base 16) Analogue & Micro Ltd - Lakeside House - Lakeside - Llantarnam Industrial Park Cwmbran NP44 3XS - UNITED KINGDOM - - 00-1D-12 (hex) ROHM CO., LTD. - 001D12 (base 16) ROHM CO., LTD. - 21 Saiin-Mizosaki-cho, - Ukyo-ku, - Kyoto-shi KYOTO 615-8585 - JAPAN - - 00-1D-13 (hex) NextGTV - 001D13 (base 16) NextGTV - 13F Byucksan/Kyungin Digital Valley ll - Gasan-dong, Geumcheon-gu - Seoul 153-803 - KOREA, REPUBLIC OF - - 00-1D-14 (hex) SPERADTONE INFORMATION TECHNOLOGY LIMITED - 001D14 (base 16) SPERADTONE INFORMATION TECHNOLOGY LIMITED - Room 1001 NO.418 Gui Ping Road, - Shanghai 200233 - CHINA - - 00-1D-15 (hex) Shenzhen Dolphin Electronic Co., Ltd - 001D15 (base 16) Shenzhen Dolphin Electronic Co., Ltd - Building21,Baoyuan, No.1 Industrial Zone, - Xixiang, Baoan District, - Shenzhen Guangdong 518103 - CHINA - - 00-1D-16 (hex) SFR - 001D16 (base 16) SFR - 40/42 Quai du point du jour - Boulongne Billancourt Hauts de Seine 92659 - FRANCE - - 00-1D-17 (hex) Digital Sky Corporation - 001D17 (base 16) Digital Sky Corporation - 5-5-15 Sotokanda, - Chiyoda-ku Tokyo 101-0021 - JAPAN - - 00-1D-18 (hex) Power Innovation GmbH - 001D18 (base 16) Power Innovation GmbH - Rehland 2 - Achim Niedersachsen 28832 - GERMANY - - 00-1D-19 (hex) Arcadyan Technology Corporation - 001D19 (base 16) Arcadyan Technology Corporation - 4F., No. 9 , Park Avenue II, - Science-based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1D-1A (hex) OvisLink S.A. - 001D1A (base 16) OvisLink S.A. - C/Andres Obispo, 37. Pl. 4. - Madrid 28043 - SPAIN - - 00-1D-1B (hex) Sangean Electronics Inc. - 001D1B (base 16) Sangean Electronics Inc. - No. 18, Lane 7, Li-De street - Chung Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-1D-1C (hex) Gennet s.a. - 001D1C (base 16) Gennet s.a. - 2 Mesogeion ave. - Pirgos Athinon - Athens Attiki 11527 - GREECE - - 00-1D-1D (hex) Inter-M Corporation - 001D1D (base 16) Inter-M Corporation - 653-5 Banghak-Dong, Dobong-Ku - Seoul 132-846 - KOREA, REPUBLIC OF - - 00-1D-1E (hex) KYUSHU TEN CO.,LTD - 001D1E (base 16) KYUSHU TEN CO.,LTD - 2360 YUNOKIMOTOMACHI - SASEBO-City NAGASAKI Prefecture 857-0115 - JAPAN - - 00-1D-1F (hex) Siauliu Tauro Televizoriai, JSC - 001D1F (base 16) Siauliu Tauro Televizoriai, JSC - Pramones,15 - Siauliai LT-57318 - LITHUANIA - - 00-1D-20 (hex) COMTREND CO. - 001D20 (base 16) COMTREND CO. - 3F-1 10 LANE 609 CHUNG HSIN ROAD, SEC 5, SAN CHUNG CITY, TAIPEI TAIWAN 241 - TAIPEI 241 - TAIWAN, PROVINCE OF CHINA - - 00-1D-21 (hex) Alcad SL - 001D21 (base 16) Alcad SL - Pol. Ind. Arreche-Ugalde, 1 - Irún Guipúzcoa E-20305 - SPAIN - - 00-1D-22 (hex) Foss Analytical A/S - 001D22 (base 16) Foss Analytical A/S - Slangerupgade 69 - Hillerød Seeland 3400 - DENMARK - - 00-1D-23 (hex) SENSUS - 001D23 (base 16) SENSUS - 44 CASTILIAN DRIVE - GOLETA CALIFORNIA 93117 - UNITED STATES - - 00-1D-24 (hex) Aclara Power-Line Systems Inc. - 001D24 (base 16) Aclara Power-Line Systems Inc. - 945 Hornet Drive - Hazelwood MO 63042 - UNITED STATES - - 00-1D-25 (hex) Samsung Electronics Co.,Ltd - 001D25 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1D-26 (hex) Rockridgesound Technology Co. - 001D26 (base 16) Rockridgesound Technology Co. - Fumin Industrial Park, Houjie Town - Dong Guan Guang Dong 523956 - CHINA - - 00-1D-27 (hex) NAC-INTERCOM - 001D27 (base 16) NAC-INTERCOM - AVDA. RICARDO MELLA 123-B - OFICINA 5 - VIGO PONTEVEDRA 36330 - SPAIN - - 00-1D-28 (hex) Sony Ericsson Mobile Communications AB - 001D28 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-1D-29 (hex) Doro AB - 001D29 (base 16) Doro AB - Magistratsvägen 10 - Lund 226 43 - SWEDEN - - 00-1D-2A (hex) SHENZHEN BUL-TECH CO.,LTD. - 001D2A (base 16) SHENZHEN BUL-TECH CO.,LTD. - 4/F, COFCO Bdlg , 3rd District,Baoan District, Shenzhen City, - Guangdong Province,China. - shengzhen guangdong 518101 - CHINA - - 00-1D-2B (hex) Wuhan Pont Technology CO. , LTD - 001D2B (base 16) Wuhan Pont Technology CO. , LTD - Building E, Guandong Science and Technology Industry Park, - East Lake High Technology Development Zone, - Wuhan Hubei 430074 - CHINA - - 00-1D-2C (hex) Wavetrend Technologies (Pty) Limited - 001D2C (base 16) Wavetrend Technologies (Pty) Limited - Wavetrend House, Building 816/3 - Hammets Crossing Office Park,Selbourne road, fourways - Gauteng 2021 - SOUTH AFRICA - - 00-1D-2D (hex) Pylone, Inc. - 001D2D (base 16) Pylone, Inc. - 4F Nakano Bldg. 4-30-8 Kita-Shinjuku - Shinjuku-ku, Tokyo 169-0074 - JAPAN - - 00-1D-2E (hex) Ruckus Wireless - 001D2E (base 16) Ruckus Wireless - 880 West Maude Ave. - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 00-1D-2F (hex) QuantumVision Corporation - 001D2F (base 16) QuantumVision Corporation - 335 Plantation Way - Roswell Ga 30075 - UNITED STATES - - 00-1D-30 (hex) YX Wireless S.A. - 001D30 (base 16) YX Wireless S.A. - Av. Vicuña Mackenna #4860 - Edificio 512, piso 3. Macul - Santiago 8580710 - CHILE - - 00-1D-31 (hex) HIGHPRO INTERNATIONAL R&D CO,.LTD. - 001D31 (base 16) HIGHPRO INTERNATIONAL R&D CO,.LTD. - 3F,No.295,RuiGuang Rd,Nei Hu, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1D-32 (hex) Longkay Communication & Technology (Shanghai) Co. Ltd - 001D32 (base 16) Longkay Communication & Technology (Shanghai) Co. Ltd - No.5 Building, Unit 2, Lane 299 Bisheng Rd, - Shanghai 201204 - CHINA - - 00-1D-33 (hex) Maverick Systems Inc. - 001D33 (base 16) Maverick Systems Inc. - 908, Daerungposttower 2-cha, 182-13 - Guro-dong, Guro-gu - Seoul 152-790 - KOREA, REPUBLIC OF - - 00-1D-34 (hex) SYRIS Technology Corp - 001D34 (base 16) SYRIS Technology Corp - 21 F-2, NO. 12, SEC. 1, Taijunggang Rd. - Taichung 403 - TAIWAN, PROVINCE OF CHINA - - 00-1D-35 (hex) Viconics Electronics Inc. - 001D35 (base 16) Viconics Electronics Inc. - 9245 Langelier - Saint Leonard Quebec H1P3K9 - CANADA - - 00-1D-36 (hex) ELECTRONICS CORPORATION OF INDIA LIMITED - 001D36 (base 16) ELECTRONICS CORPORATION OF INDIA LIMITED - CONTROL AND AUTOMATION DIVISION-3 - ECIL POST - HYDERABAD ANDHRA PRADESH 500 062 - INDIA - - 00-1D-37 (hex) Thales-Panda Transportation System - 001D37 (base 16) Thales-Panda Transportation System - 6th floor, HUIJIE Plaza, 268 Zhongshan Rd. - nanjing jiangsu 210008 - CHINA - - 00-1D-38 (hex) Seagate Technology - 001D38 (base 16) Seagate Technology - M/S NW1F01 - 389 Disc Drive - Longmont CO 80503 - UNITED STATES - - 00-1D-39 (hex) MOOHADIGITAL CO., LTD - 001D39 (base 16) MOOHADIGITAL CO., LTD - Seoul Hightech Venture Center C-307 647-26 - Deungchon-Dong Gangseo-Gu - SEOUL 157-030 - KOREA, REPUBLIC OF - - 00-1D-3A (hex) mh acoustics LLC - 001D3A (base 16) mh acoustics LLC - 25A Summit Ave - Summit NJ 07901 - UNITED STATES - - 00-1D-3B (hex) Nokia Danmark A/S - 001D3B (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1D-3C (hex) Muscle Corporation - 001D3C (base 16) Muscle Corporation - 2-5-35, Kikawa-higashi - Osaka 532-0012 - JAPAN - - 00-1D-3D (hex) Avidyne Corporation - 001D3D (base 16) Avidyne Corporation - 202 West Dr - Melbourne FL 32904 - UNITED STATES - - 00-1D-3E (hex) SAKA TECHNO SCIENCE CO.,LTD - 001D3E (base 16) SAKA TECHNO SCIENCE CO.,LTD - Nishi 105-1 - Kitazuka-machi - Kanazawa Ishikawa 920-0367 - JAPAN - - 00-1D-3F (hex) Mitron Pty Ltd - 001D3F (base 16) Mitron Pty Ltd - Unit 11 - 12-18 Clarendon Street - Artarmon NSW 2065 - AUSTRALIA - - 00-1D-40 (hex) Intel – GE Care Innovations LLC - 001D40 (base 16) Intel – GE Care Innovations LLC - 3721 Douglas Blvd - Suite 100 - Roseville CA 95661 - UNITED STATES - - 00-1D-41 (hex) Hardy Instruments - 001D41 (base 16) Hardy Instruments - 3860 Calle Fortunada - San Diego CA 92123 - UNITED STATES - - 00-1D-42 (hex) Nortel - 001D42 (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1D-43 (hex) Shenzhen G-link Digital Technology Co., Ltd. - 001D43 (base 16) Shenzhen G-link Digital Technology Co., Ltd. - 4F, E Building,Huachuang Da Technology Zone ,Hangcheng Highway,Gushu,Xixiang , - shenzhen GuangDong 518126 - CHINA - - 00-1D-44 (hex) KROHNE Messtechnik GmbH - 001D44 (base 16) KROHNE Messtechnik GmbH - Ludwig-Krohne-Str. 5 - 47058 Duisburg - GERMANY - - 00-1D-45 (hex) CISCO SYSTEMS, INC. - 001D45 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-46 (hex) CISCO SYSTEMS, INC. - 001D46 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-47 (hex) Covote GmbH & Co KG - 001D47 (base 16) Covote GmbH & Co KG - Ritterhufen 30 - Berlin 14165 - GERMANY - - 00-1D-48 (hex) Sensor-Technik Wiedemann GmbH - 001D48 (base 16) Sensor-Technik Wiedemann GmbH - Am Bärenwald 6 - Kaufbeuren Bayern 87600 - GERMANY - - 00-1D-49 (hex) Innovation Wireless Inc. - 001D49 (base 16) Innovation Wireless Inc. - 4F-1, NO.81, SHUEILI RD. - HSINCHU 30059 - TAIWAN, PROVINCE OF CHINA - - 00-1D-4A (hex) Carestream Health, Inc. - 001D4A (base 16) Carestream Health, Inc. - 150 Verona Street - Rochestser NY 14608 - UNITED STATES - - 00-1D-4B (hex) Grid Connect Inc. - 001D4B (base 16) Grid Connect Inc. - 1630 W. Diehl Rd - Naperville IL 60563 - UNITED STATES - - 00-1D-4C (hex) Alcatel-Lucent - 001D4C (base 16) Alcatel-Lucent - 601 Data Dr. - M/S 601-TSGTD - Plano TX 75075 - UNITED STATES - - 00-1D-4D (hex) Adaptive Recognition Hungary, Inc - 001D4D (base 16) Adaptive Recognition Hungary, Inc - Kiralyhago ter 8-9 - Budapest Europe 1126 - HUNGARY - - 00-1D-4E (hex) TCM Mobile LLC - 001D4E (base 16) TCM Mobile LLC - 9218 Metcalf, - Suite #293 - Overland Park Kansas 66212 - UNITED STATES - - 00-1D-4F (hex) Apple - 001D4F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-1D-50 (hex) SPINETIX SA - 001D50 (base 16) SPINETIX SA - Parc Scientifique de l'EPFL, Bâtiment C - Lausanne VD 1015 - SWITZERLAND - - 00-1D-51 (hex) Babcock & Wilcox Power Generation Group, Inc - 001D51 (base 16) Babcock & Wilcox Power Generation Group, Inc - 11864 Canon Blvd, Suite 105 - Newport News VA 23606 - UNITED STATES - - 00-1D-52 (hex) Defzone B.V. - 001D52 (base 16) Defzone B.V. - Transportcentrum 10 - Enschede Overijssel 7547 RW - NETHERLANDS - - 00-1D-53 (hex) S&O Electronics (Malaysia) Sdn. Bhd. - 001D53 (base 16) S&O Electronics (Malaysia) Sdn. Bhd. - Lot 202, Bakar Arang - Industrial Estate - 08000 Sungai Petani Kedah - MALAYSIA - - 00-1D-54 (hex) Sunnic Technology & Merchandise INC. - 001D54 (base 16) Sunnic Technology & Merchandise INC. - 6F, NO.74,ZHOU-Z ST., - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1D-55 (hex) ZANTAZ, Inc - 001D55 (base 16) ZANTAZ, Inc - 5758 W. Las Positas Avenue - Pleasanton CA 94588 - UNITED STATES - - 00-1D-56 (hex) Kramer Electronics Ltd. - 001D56 (base 16) Kramer Electronics Ltd. - 3 Am VeOlamo Street - Jerusalem 95463 - ISRAEL - - 00-1D-57 (hex) CAETEC Messtechnik - 001D57 (base 16) CAETEC Messtechnik - Schlossstraße 95a - Olching Bayern 82140 - GERMANY - - 00-1D-58 (hex) CQ Inc - 001D58 (base 16) CQ Inc - 5F, No. 43, Lane 76, Rui Guang Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1D-59 (hex) Mitra Energy & Infrastructure - 001D59 (base 16) Mitra Energy & Infrastructure - Boulevard de l'Europe 131 - 1301 Wavre - BELGIUM - - 00-1D-5A (hex) 2Wire Inc. - 001D5A (base 16) 2Wire Inc. - 1704 Automation Parkway - San Jose California 95131 - UNITED STATES - - 00-1D-5B (hex) Tecvan Informática Ltda - 001D5B (base 16) Tecvan Informática Ltda - Rua Guaicurus, 145 - Vila Conceição - Diadema São Paulo 09911-630 - BRAZIL - - 00-1D-5C (hex) Tom Communication Industrial Co.,Ltd. - 001D5C (base 16) Tom Communication Industrial Co.,Ltd. - 1173 Nippa-choh Kohoku-ku - Yokohama Kanagawa 223-0057 - JAPAN - - 00-1D-5D (hex) Control Dynamics Pty. Ltd. - 001D5D (base 16) Control Dynamics Pty. Ltd. - PO Box 636 - MORLEY Western Australia 6943 - AUSTRALIA - - 00-1D-5E (hex) COMING MEDIA CORP. - 001D5E (base 16) COMING MEDIA CORP. - BONA Bld. 4th Fl., 548-18 - Dogok-1Dong, Kangnam-Ku, - Seoul 135-158 - KOREA, REPUBLIC OF - - 00-1D-5F (hex) OverSpeed SARL - 001D5F (base 16) OverSpeed SARL - 15, allee du Bois Cailley - Le Thuit-Signol Normandie 27370 - FRANCE - - 00-1D-60 (hex) ASUSTek COMPUTER INC. - 001D60 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-1D-61 (hex) BIJ Corporation - 001D61 (base 16) BIJ Corporation - 7F Takamizawa Building,2-7-10, - Kitasaiwai,Nishi - Yokohama Kanagawa 220-0004 - JAPAN - - 00-1D-62 (hex) InPhase Technologies - 001D62 (base 16) InPhase Technologies - 2000 Pike Road - Longmont Colorado 80501 - UNITED STATES - - 00-1D-63 (hex) Miele & Cie. KG - 001D63 (base 16) Miele & Cie. KG - Carl-Miele-Straße 29 - Gütersloh 33332 - GERMANY - - 00-1D-64 (hex) Adam Communications Systems Int Ltd - 001D64 (base 16) Adam Communications Systems Int Ltd - The Mission - Wellington Street - Stockport Cheshire SK1 3AH - UNITED KINGDOM - - 00-1D-65 (hex) Microwave Radio Communications - 001D65 (base 16) Microwave Radio Communications - 101 Billerica Avemue, Bldg 6 - N. Billerica MA 01862 - UNITED STATES - - 00-1D-66 (hex) Hyundai Telecom - 001D66 (base 16) Hyundai Telecom - Hyundai Telecom Bldg., 4273-12, Shingil-Dong, Youngdungpo-Gu, - Seoul 150-859 - KOREA, REPUBLIC OF - - 00-1D-67 (hex) AMEC - 001D67 (base 16) AMEC - 9F,No.360,Ruel Guang Rd,Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1D-68 (hex) Thomson Telecom Belgium - 001D68 (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 B - Edegem Antwerp B-2650 - BELGIUM - - 00-1D-69 (hex) Knorr-Bremse IT-Services GmbH - 001D69 (base 16) Knorr-Bremse IT-Services GmbH - Moosacher Str. 80 - Muenchen BY 80809 - GERMANY - - 00-1D-6A (hex) Alpha Networks Inc. - 001D6A (base 16) Alpha Networks Inc. - No.8 Li-shing Seventh Road,Science-based - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-1D-6B (hex) ARRIS Group, Inc. - 001D6B (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-6C (hex) ClariPhy Communications, Inc. - 001D6C (base 16) ClariPhy Communications, Inc. - 16 Technology Dr., Suite 165 - Irvine CA 92618 - UNITED STATES - - 00-1D-6D (hex) Confidant International LLC - 001D6D (base 16) Confidant International LLC - 2530 Meridian Pkwy - Durham North Carolina 27713 - UNITED STATES - - 00-1D-6E (hex) Nokia Danmark A/S - 001D6E (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1D-6F (hex) Chainzone Technology Co., Ltd - 001D6F (base 16) Chainzone Technology Co., Ltd - Chainzone Tech. Ind Park, Nanxin 1st Rd. - Guicheng Nanhai - Foshan Guangdong 528200 - CHINA - - 00-1D-70 (hex) CISCO SYSTEMS, INC. - 001D70 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-71 (hex) CISCO SYSTEMS, INC. - 001D71 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-72 (hex) Wistron Corporation - 001D72 (base 16) Wistron Corporation - 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-1D-73 (hex) Buffalo Inc. - 001D73 (base 16) Buffalo Inc. - 15,Shibata Hondori 4-chome, - Minami-ku - Nagoya Aichi Pref. 457-8520 - JAPAN - - 00-1D-74 (hex) Tianjin China-Silicon Microelectronics Co., Ltd. - 001D74 (base 16) Tianjin China-Silicon Microelectronics Co., Ltd. - 301,3F Building 211,No.214 Hongqi Road, Nankai District, Tianjin China - Tianjin 300190 - CHINA - - 00-1D-75 (hex) Radioscape PLC - 001D75 (base 16) Radioscape PLC - 1 Albany Terrace - Regent's Park London NW1 4DS - UNITED KINGDOM - - 00-1D-76 (hex) Eyeheight Ltd. - 001D76 (base 16) Eyeheight Ltd. - Unit 34, Park House - 15-19 Greenhill Crescent - Watford Herts WD18 8PH - UNITED KINGDOM - - 00-1D-77 (hex) NSGate - 001D77 (base 16) NSGate - Rm 1304, 39 Kirpichnaya Street - Moscow 105187 - RUSSIAN FEDERATION - - 00-1D-78 (hex) Invengo Information Technology Co.,Ltd - 001D78 (base 16) Invengo Information Technology Co.,Ltd - 3/F,No.T2-B,High-Tech Industrial Park South - Shenzhen Guangdong 518057 - CHINA - - 00-1D-79 (hex) SIGNAMAX LLC - 001D79 (base 16) SIGNAMAX LLC - 1090 Vermont Avenue - Washington Washington D.C. 20005 - UNITED STATES - - 00-1D-7A (hex) Wideband Semiconductor, Inc. - 001D7A (base 16) Wideband Semiconductor, Inc. - 1350 Pear Ave - Suite C - Mountain View CA 94043 - UNITED STATES - - 00-1D-7B (hex) Ice Energy, Inc. - 001D7B (base 16) Ice Energy, Inc. - 9351 Eastman Park Drive - Suite B - Windsor Colorado 80550 - UNITED STATES - - 00-1D-7C (hex) ABE Elettronica S.p.A. - 001D7C (base 16) ABE Elettronica S.p.A. - Via Leonardo da Vinci, 92 - CARAVAGGIO BG 24043 - ITALY - - 00-1D-7D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 001D7D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - Pin-Jen City, Taoyuan, - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 00-1D-7E (hex) Cisco-Linksys, LLC - 001D7E (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 00-1D-7F (hex) Tekron International Ltd - 001D7F (base 16) Tekron International Ltd - 409 Cuba Street, Alicetown - PO Box 31-285 - Lower Hutt Wellington 5010 - NEW ZEALAND - - 00-1D-80 (hex) Beijing Huahuan Eletronics Co.,Ltd - 001D80 (base 16) Beijing Huahuan Eletronics Co.,Ltd - No.26,Shangdi 6th St.Haidian District, - Beijing 100085 - CHINA - - 00-1D-81 (hex) GUANGZHOU GATEWAY ELECTRONICS CO., LTD - 001D81 (base 16) GUANGZHOU GATEWAY ELECTRONICS CO., LTD - B20#,4F,No.9 Jiangong Road,Tianhe Software Park,Tianhe District, - GUANGZHOU Guangdong 510665 - CHINA - - 00-1D-82 (hex) GN A/S (GN Netcom A/S) - 001D82 (base 16) GN A/S (GN Netcom A/S) - Lautrupbjerg 7 - P.O.Box 99 - Ballerup DK - 2750 - DENMARK - - 00-1D-83 (hex) Emitech Corporation - 001D83 (base 16) Emitech Corporation - 2F,No.7-1,Industry E,Rd.9 - Science-Based Industrial Park, - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 00-1D-84 (hex) Gateway, Inc. - 001D84 (base 16) Gateway, Inc. - 610 Gateway Drive - P.O. Box 2000 - North Sioux City South Dakota 57049 - UNITED STATES - - 00-1D-85 (hex) Call Direct Cellular Solutions - 001D85 (base 16) Call Direct Cellular Solutions - Suite 145, National Innovation Centre - Australian Technology Park - Eveleigh NSW 1430 - AUSTRALIA - - 00-1D-86 (hex) Shinwa Industries(China) Ltd. - 001D86 (base 16) Shinwa Industries(China) Ltd. - 8 Pingnanzhong Road, Pingnan Industrial Park, Zhongkai No.4 Road, - Huizhou City Guangdong Province 516006 - CHINA - - 00-1D-87 (hex) VigTech Labs Sdn Bhd - 001D87 (base 16) VigTech Labs Sdn Bhd - 45-11 The Boulevard Mid Valley City - Lingkaran Syed Putra - Kuala Lumpur Selangor 59200 - MALAYSIA - - 00-1D-88 (hex) Clearwire - 001D88 (base 16) Clearwire - 1475 120th Ave NE - Bellevue Washington 98005 - UNITED STATES - - 00-1D-89 (hex) VaultStor Corporation - 001D89 (base 16) VaultStor Corporation - 1010 Brioso Drive - Costa Mesa CA 92627 - UNITED STATES - - 00-1D-8A (hex) TechTrex Inc - 001D8A (base 16) TechTrex Inc - 6221 Highway 7, Unit 12 - Woodbridge Ontalio L4H 0K8 - CANADA - - 00-1D-8B (hex) ADB Broadband Italia - 001D8B (base 16) ADB Broadband Italia - VIALE SARCA 222 - MILANO 20126 - ITALY - - 00-1D-8C (hex) La Crosse Technology LTD - 001D8C (base 16) La Crosse Technology LTD - 2809 Losey Blvd. So. - La Crosse WI 54601 - UNITED STATES - - 00-1D-8D (hex) Raytek GmbH - 001D8D (base 16) Raytek GmbH - Blankenburger Str. 135 - Berlin 13127 - GERMANY - - 00-1D-8E (hex) Alereon, Inc. - 001D8E (base 16) Alereon, Inc. - 7600 N. Capital of Texas Hwy - Bldg C, #200 - Austin TX 78731 - UNITED STATES - - 00-1D-8F (hex) PureWave Networks - 001D8F (base 16) PureWave Networks - 2660-C Marine Way - Mountain View CA 94043 - UNITED STATES - - 00-1D-90 (hex) EMCO Flow Systems - 001D90 (base 16) EMCO Flow Systems - 2150 Miller Drive - Longmont CO 80501 - UNITED STATES - - 00-1D-91 (hex) Digitize, Inc - 001D91 (base 16) Digitize, Inc - 158 Edison Road - Lake Hopatcong New Jersey 07849 - UNITED STATES - - 00-1D-92 (hex) MICRO-STAR INT'L CO.,LTD. - 001D92 (base 16) MICRO-STAR INT'L CO.,LTD. - No.69,Li-De St,Jung-Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-1D-93 (hex) Modacom - 001D93 (base 16) Modacom - Jinsuk Building 1536-7 - Seocho-Dong, Seocho-Gu - Seoul 137-073 - KOREA, REPUBLIC OF - - 00-1D-94 (hex) Climax Technology Co., Ltd - 001D94 (base 16) Climax Technology Co., Ltd - No. 258, Hsin Hu 2nd Road - Neihu District - Taipei City Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-1D-95 (hex) Flash, Inc. - 001D95 (base 16) Flash, Inc. - 3703 N. 200th St. - Elkhorn NE 68022-2922 - UNITED STATES - - 00-1D-96 (hex) WatchGuard Video - 001D96 (base 16) WatchGuard Video - 3001 Summit Ave. - Plano TX 75074 - UNITED STATES - - 00-1D-97 (hex) Alertus Technologies LLC - 001D97 (base 16) Alertus Technologies LLC - 11785 Beltsville Drive - Suite 1325 - Beltsville MD 20705 - UNITED STATES - - 00-1D-98 (hex) Nokia Danmark A/S - 001D98 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1D-99 (hex) Cyan Optic, Inc. - 001D99 (base 16) Cyan Optic, Inc. - 1390 N. McDowell Blvd - Suite G-327 - Petaluma CA 94954 - UNITED STATES - - 00-1D-9A (hex) GODEX INTERNATIONAL CO., LTD - 001D9A (base 16) GODEX INTERNATIONAL CO., LTD - 4F. NO.168, Lian-Cheng Road Chung-Ho City, - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-1D-9B (hex) Hokuyo Automatic Co., Ltd. - 001D9B (base 16) Hokuyo Automatic Co., Ltd. - Niitaka 1-10-9 - Yodogawa-Ku - Osaka 532-0033 - JAPAN - - 00-1D-9C (hex) Rockwell Automation - 001D9C (base 16) Rockwell Automation - 1 Allen-Bradley Dr. - Mayfield Heights OH 44124-6118 - UNITED STATES - - 00-1D-9D (hex) ARTJOY INTERNATIONAL LIMITED - 001D9D (base 16) ARTJOY INTERNATIONAL LIMITED - Room 1601,No.239 ZhongXing Road,LuoHu District - Shenzhen Guangdong 518001 - CHINA - - 00-1D-9E (hex) AXION TECHNOLOGIES - 001D9E (base 16) AXION TECHNOLOGIES - 151 RUE PARC INNOVATION - LA POCATIERE QUEBEC G0R1Z0 - CANADA - - 00-1D-9F (hex) MATT R.P.Traczynscy Sp.J. - 001D9F (base 16) MATT R.P.Traczynscy Sp.J. - Polnocna 44 - Koscian wielkopolskie PL-64000 - POLAND - - 00-1D-A0 (hex) Heng Yu Electronic Manufacturing Company Limited - 001DA0 (base 16) Heng Yu Electronic Manufacturing Company Limited - Room 1503-5, Nan Fung Com'l Centre, - 19 Lam Lok Street, Kowloon Bay - Kowloon - HONG KONG - - 00-1D-A1 (hex) CISCO SYSTEMS, INC. - 001DA1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-A2 (hex) CISCO SYSTEMS, INC. - 001DA2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-A3 (hex) SabiOso - 001DA3 (base 16) SabiOso - 189 S State Suite #250 - Clearfield Utah 84015 - UNITED STATES - - 00-1D-A4 (hex) Hangzhou System Technology CO., LTD - 001DA4 (base 16) Hangzhou System Technology CO., LTD - ROOM A1505 HuaXing times plaza,NO 478 Wensan Road - Hangzhou Zhejiang 310012 - CHINA - - 00-1D-A5 (hex) WB Electronics - 001DA5 (base 16) WB Electronics - Langelandsvej 1A - Herning Herning 7400 - DENMARK - - 00-1D-A6 (hex) Media Numerics Limited - 001DA6 (base 16) Media Numerics Limited - Rodenbacher Chaussee 6 - Hanau Hessen 63457 - GERMANY - - 00-1D-A7 (hex) Seamless Internet - 001DA7 (base 16) Seamless Internet - 2050 Russett Way Suite 338 - Carson City Nevada 89703 - UNITED STATES - - 00-1D-A8 (hex) Takahata Electronics Co.,Ltd - 001DA8 (base 16) Takahata Electronics Co.,Ltd - 1188,Kubota,Kubota-machi - Yonezawa-shi Yamagata-Pref. 992-0003 - JAPAN - - 00-1D-A9 (hex) Castles Technology, Co., LTD - 001DA9 (base 16) Castles Technology, Co., LTD - 2F, No.205, Sec 3 Beishin Rd., - Hsin-Tien City Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-1D-AA (hex) DrayTek Corp. - 001DAA (base 16) DrayTek Corp. - No. 26, Fu-Shing Road - HuKou County, Hsin-Chu Industrial Park - Hsin-Chu 303 - TAIWAN, PROVINCE OF CHINA - - 00-1D-AB (hex) SwissQual License AG - 001DAB (base 16) SwissQual License AG - Baarerstrasse 78 - Zug Postfach 117 - SWITZERLAND - - 00-1D-AC (hex) Gigamon Systems LLC - 001DAC (base 16) Gigamon Systems LLC - 598 Gibraltar Drive - Milpitas CA 95035 - UNITED STATES - - 00-1D-AD (hex) Sinotech Engineering Consultants, Inc. Geotechnical Enginee - 001DAD (base 16) Sinotech Engineering Consultants, Inc. Geotechnical Enginee - Basement No.7 Lane 26, Yat-Sen Rd. - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-1D-AE (hex) CHANG TSENG TECHNOLOGY CO., LTD - 001DAE (base 16) CHANG TSENG TECHNOLOGY CO., LTD - 2F NO.160 BACK BUILDING, LEN CHENG RD., CHUNG HO CITY - TAIPEI HSIEN 235 - TAIWAN, PROVINCE OF CHINA - - 00-1D-AF (hex) Nortel - 001DAF (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1D-B0 (hex) FuJian HengTong Information Technology Co.,Ltd - 001DB0 (base 16) FuJian HengTong Information Technology Co.,Ltd - No.14-804,Building 2,JinXiuFuCheng,No.338,HuaLin Road - FuZhou City FuJian Province 350001 - CHINA - - 00-1D-B1 (hex) Crescendo Networks - 001DB1 (base 16) Crescendo Networks - 6 Yoni Netanyahu St. - Or-Yehuda 60376 - ISRAEL - - 00-1D-B2 (hex) HOKKAIDO ELECTRIC ENGINEERING CO.,LTD. - 001DB2 (base 16) HOKKAIDO ELECTRIC ENGINEERING CO.,LTD. - Nishinopporo 120-8 - Ebetu-City Hokkaido 069-0832 - JAPAN - - 00-1D-B3 (hex) HPN Supply Chain - 001DB3 (base 16) HPN Supply Chain - 8000 Foothills Blvd - Roseville CA 95747 - UNITED STATES - - 00-1D-B4 (hex) KUMHO ENG CO.,LTD - 001DB4 (base 16) KUMHO ENG CO.,LTD - 498-13, HYUNDAI B/D 5F - PYEONGRI 3-DONG, SEO-GU - DAEGU 703-835 - KOREA, REPUBLIC OF - - 00-1D-B5 (hex) Juniper networks - 001DB5 (base 16) Juniper networks - 1194 N Mathilda Ave. - Sunnyvale CA 94089 - UNITED STATES - - 00-1D-B6 (hex) BestComm Networks, Inc. - 001DB6 (base 16) BestComm Networks, Inc. - 5605 E River Road - Suite 219 - Tucson AZ 85750 - UNITED STATES - - 00-1D-B7 (hex) Tendril Networks, Inc. - 001DB7 (base 16) Tendril Networks, Inc. - 5700-D Flatiron Parkway - Suite 5700-D - Boulder CO 80301 - UNITED STATES - - 00-1D-B8 (hex) Intoto Inc. - 001DB8 (base 16) Intoto Inc. - 3100 De La Cruz Blvd. #300 - Santa Clara CA 95054 - UNITED STATES - - 00-1D-B9 (hex) Wellspring Wireless - 001DB9 (base 16) Wellspring Wireless - 107 Magella Court - North Wales Pa 19454 - UNITED STATES - - 00-1D-BA (hex) Sony Corporation - 001DBA (base 16) Sony Corporation - Gotenyama Tec,5-1-12, - Kitashinagawa - Shinagawa-ku Tokyo 141-0001 - JAPAN - - 00-1D-BB (hex) Dynamic System Electronics Corp. - 001DBB (base 16) Dynamic System Electronics Corp. - 5F,NO,9,LANE 130,SEC 1,KUANGG FU RD.SAN CHUNG CITY, - Taipei Hsien 24158 - TAIWAN, PROVINCE OF CHINA - - 00-1D-BC (hex) Nintendo Co., Ltd. - 001DBC (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1D-BD (hex) Versamed Inc. - 001DBD (base 16) Versamed Inc. - 2 Blue Hill Plaza - Pearl River NY 10965 - UNITED STATES - - 00-1D-BE (hex) ARRIS Group, Inc. - 001DBE (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-BF (hex) Radiient Technologies, Inc. - 001DBF (base 16) Radiient Technologies, Inc. - 2084-A Walsh Ave - Santa Clara CA 95050 - UNITED STATES - - 00-1D-C0 (hex) Enphase Energy - 001DC0 (base 16) Enphase Energy - 201 1st Street, Suite 111 - Petaluma CA 94952 - UNITED STATES - - 00-1D-C1 (hex) Audinate Pty L - 001DC1 (base 16) Audinate Pty L - Level 1, 458 Wattle St - Ultimo NSW 2007 - AUSTRALIA - - 00-1D-C2 (hex) XORTEC OY - 001DC2 (base 16) XORTEC OY - Höytämöntie 6 - Lempäälä Pirkanmaa 33880 - FINLAND - - 00-1D-C3 (hex) RIKOR TV, Ltd - 001DC3 (base 16) RIKOR TV, Ltd - Kostomarovsky per.,3 - Moscow 105120 - RUSSIAN FEDERATION - - 00-1D-C4 (hex) AIOI Systems Co., Ltd. - 001DC4 (base 16) AIOI Systems Co., Ltd. - KDX Omori, Bldg. 8F - 1-6-8 Omori Kita, Ota-ku - Tokyo 143-0016 - JAPAN - - 00-1D-C5 (hex) Beijing Jiaxun Feihong Electricial Co., Ltd. - 001DC5 (base 16) Beijing Jiaxun Feihong Electricial Co., Ltd. - Electrical Building,No. 31 Jiaoda East Road, - Beijing Haidian District, 100044 - CHINA - - 00-1D-C6 (hex) SNR Inc. - 001DC6 (base 16) SNR Inc. - VBIC T223ho, ICU, 103-6 Munji-dong, Youseong-gu - Daejeon 305-732 - KOREA, REPUBLIC OF - - 00-1D-C7 (hex) L-3 Communications Geneva Aerospace - 001DC7 (base 16) L-3 Communications Geneva Aerospace - 4240 International Parkway - Suite 100 - Carrollton Texas 75007 - UNITED STATES - - 00-1D-C8 (hex) Navionics Research Inc., dba SCADAmetrics - 001DC8 (base 16) Navionics Research Inc., dba SCADAmetrics - 1133 Pond Road - Wildwood Missouri 63038 - UNITED STATES - - 00-1D-C9 (hex) GainSpan Corp. - 001DC9 (base 16) GainSpan Corp. - P.O. Box 223580 - Carmel CA 93922 - UNITED STATES - - 00-1D-CA (hex) PAV Electronics Limited - 001DCA (base 16) PAV Electronics Limited - 7 Laverock Road - Stirling Road Industrial Estate - Airdrie Lanarkshire ML6 7UD - UNITED KINGDOM - - 00-1D-CB (hex) Exéns Development Oy - 001DCB (base 16) Exéns Development Oy - Kauppakatu 36 - Kajaani Kainuu 87100 - FINLAND - - 00-1D-CC (hex) Hetra Secure Solutions - 001DCC (base 16) Hetra Secure Solutions - 2350 Commerce Park Dr. - Palm Bay FL 32905 - UNITED STATES - - 00-1D-CD (hex) ARRIS Group, Inc. - 001DCD (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-CE (hex) ARRIS Group, Inc. - 001DCE (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-CF (hex) ARRIS Group, Inc. - 001DCF (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D0 (hex) ARRIS Group, Inc. - 001DD0 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D1 (hex) ARRIS Group, Inc. - 001DD1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D2 (hex) ARRIS Group, Inc. - 001DD2 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D3 (hex) ARRIS Group, Inc. - 001DD3 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D4 (hex) ARRIS Group, Inc. - 001DD4 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D5 (hex) ARRIS Group, Inc. - 001DD5 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D6 (hex) ARRIS Group, Inc. - 001DD6 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1D-D7 (hex) Algolith - 001DD7 (base 16) Algolith - 400 Isabey - Saint-Laurent Qc H4T 1V3 - CANADA - - 00-1D-D8 (hex) Microsoft Corporation - 001DD8 (base 16) Microsoft Corporation - One Microsoft Way - Redmond Washington 98052-6399 - UNITED STATES - - 00-1D-D9 (hex) Hon Hai Precision Ind.Co.,Ltd. - 001DD9 (base 16) Hon Hai Precision Ind.Co.,Ltd. - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-1D-DA (hex) Mikroelektronika spol. s r. o. - 001DDA (base 16) Mikroelektronika spol. s r. o. - Dráby 849 - Vysoké Mýto CZ 566 01 - CZECH REPUBLIC - - 00-1D-DB (hex) C-BEL Corporation - 001DDB (base 16) C-BEL Corporation - Futabacho 35-12 - 6F Okada Bildg - Itabashi-ku Tokyo 173-0011 - JAPAN - - 00-1D-DC (hex) HangZhou DeChangLong Tech&Info Co.,Ltd - 001DDC (base 16) HangZhou DeChangLong Tech&Info Co.,Ltd - Room 1102,KeJi Mansion, - East Software Park,90 WenSan Road. - HangZhou ZheJiang 310012 - CHINA - - 00-1D-DD (hex) DAT H.K. LIMITED - 001DDD (base 16) DAT H.K. LIMITED - Suite 1405 14/F., City Plaza 4, Tai Koo Wan Rd, - Tai Koo Shing Hong Kong Island 064828 - HONG KONG - - 00-1D-DE (hex) Zhejiang Broadcast&Television Technology Co.,Ltd. - 001DDE (base 16) Zhejiang Broadcast&Television Technology Co.,Ltd. - Building No.16,Xidoumen Industry Park,Wenyi Road, - Hangzhou Zhejiang 310012 - CHINA - - 00-1D-DF (hex) Sunitec Enterprise Co., Ltd. - 001DDF (base 16) Sunitec Enterprise Co., Ltd. - 3F., No. 98-1, Mincyuan Rd. - Sindian City Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 00-1D-E0 (hex) Intel Corporate - 001DE0 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1D-E1 (hex) Intel Corporate - 001DE1 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1D-E2 (hex) Radionor Communications - 001DE2 (base 16) Radionor Communications - Ingvald Ystgaards veg 23 - Trondheim TRD 7046 - NORWAY - - 00-1D-E3 (hex) Intuicom - 001DE3 (base 16) Intuicom - 4900 Nautilus CT N - Suite 100 - Boulder CO 80301 - UNITED STATES - - 00-1D-E4 (hex) Visioneered Image Systems - 001DE4 (base 16) Visioneered Image Systems - 10561 Garden Grove Blvd - Garden Grove California 92843 - UNITED STATES - - 00-1D-E5 (hex) CISCO SYSTEMS, INC. - 001DE5 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-E6 (hex) CISCO SYSTEMS, INC. - 001DE6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1D-E7 (hex) Marine Sonic Technology, Ltd. - 001DE7 (base 16) Marine Sonic Technology, Ltd. - 5508 George Washington Memorial Highway - P.O. Box 730 - White Marsh Virginia 23183 - UNITED STATES - - 00-1D-E8 (hex) Nikko Denki Tsushin Corporation(NDTC) - 001DE8 (base 16) Nikko Denki Tsushin Corporation(NDTC) - 440 Kamoshida-town, Aoba-ku - Yokohama 227-0033 - JAPAN - - 00-1D-E9 (hex) Nokia Danmark A/S - 001DE9 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1D-EA (hex) Commtest Instruments Ltd - 001DEA (base 16) Commtest Instruments Ltd - Level 2, 22 Moorhouse Ave - Christchurch Canterbury 8243 - NEW ZEALAND - - 00-1D-EB (hex) DINEC International - 001DEB (base 16) DINEC International - Rue de la Gare, 30 - BRAINE L'ALLEUD BRABANT WALLON 1420 - BELGIUM - - 00-1D-EC (hex) Marusys - 001DEC (base 16) Marusys - Eunsung Bldg. 5F - 53-8 ChungDam-Dong KangNam-Ku - Seoul 135-763 - KOREA, REPUBLIC OF - - 00-1D-ED (hex) Grid Net, Inc. - 001DED (base 16) Grid Net, Inc. - 340 Brannan Street - Suite 501 - San Francisco CA 94107 - UNITED STATES - - 00-1D-EE (hex) NEXTVISION SISTEMAS DIGITAIS DE TELEVISÃO LTDA. - 001DEE (base 16) NEXTVISION SISTEMAS DIGITAIS DE TELEVISÃO LTDA. - Alameda Rio Negro, 1030 - 19o. andar conj. 1904 - Barueri São Paulo 06454-000 - BRAZIL - - 00-1D-EF (hex) TRIMM, INC. - 001DEF (base 16) TRIMM, INC. - 407 RAILROAD STREET - BUTNER NC 27509 - UNITED STATES - - 00-1D-F0 (hex) Vidient Systems, Inc. - 001DF0 (base 16) Vidient Systems, Inc. - 4000 Burton Drive - Santa Clara CA 94054 - UNITED STATES - - 00-1D-F1 (hex) Intego Systems, Inc. - 001DF1 (base 16) Intego Systems, Inc. - 5343 Bowden Road - Jacksonville FL 32216 - UNITED STATES - - 00-1D-F2 (hex) Netflix, Inc. - 001DF2 (base 16) Netflix, Inc. - 100 Winchester Circle - Los Gatos CA 95032 - UNITED STATES - - 00-1D-F3 (hex) SBS Science & Technology Co., Ltd - 001DF3 (base 16) SBS Science & Technology Co., Ltd - W2-B5/6 High-tech industrial park - ShenZhen GuangDong 518057 - CHINA - - 00-1D-F4 (hex) Magellan Technology Pty Limited - 001DF4 (base 16) Magellan Technology Pty Limited - 65 Johnston Street - Annandale NSW 2000 - AUSTRALIA - - 00-1D-F5 (hex) Sunshine Co,LTD - 001DF5 (base 16) Sunshine Co,LTD - 1-3-5 Kojimachi - Chiyoda-ku - TOKYO Kanto region 102-0083 - JAPAN - - 00-1D-F6 (hex) Samsung Electronics Co.,Ltd - 001DF6 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1D-F7 (hex) R. STAHL Schaltgeräte GmbH - 001DF7 (base 16) R. STAHL Schaltgeräte GmbH - am Bahnhof 30 - Waldenburg Baden-Württemberg 74638 - GERMANY - - 00-1D-F8 (hex) Webpro Vision Technology Corporation - 001DF8 (base 16) Webpro Vision Technology Corporation - 4F., No.573, Cingping Rd. - Anping District 708 - TAIWAN, PROVINCE OF CHINA - - 00-1D-F9 (hex) Cybiotronics (Far East) Limited - 001DF9 (base 16) Cybiotronics (Far East) Limited - Unit 1906, Eastern Centre, - 1065 King's Road, - Quarry Bay - HONG KONG - - 00-1D-FA (hex) Fujian LANDI Commercial Equipment Co.,Ltd - 001DFA (base 16) Fujian LANDI Commercial Equipment Co.,Ltd - Building 23,the 1st section,Software Garden - No.89 Software Road, - Fuzhou Fujian 350003 - CHINA - - 00-1D-FB (hex) NETCLEUS Systems Corporation - 001DFB (base 16) NETCLEUS Systems Corporation - 3F, Daiichi-maeda Bldg. - 3-5-3, Yamato-higashi - Yamato-shi 242-0017 - JAPAN - - 00-1D-FC (hex) KSIC - 001DFC (base 16) KSIC - #6F, Korea Federation of Teacher's Associations, 114-1, TaeBong-Ro, - Seoul Seocho-Ku 137-715 - KOREA, REPUBLIC OF - - 00-1D-FD (hex) Nokia Danmark A/S - 001DFD (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1D-FE (hex) Palm, Inc - 001DFE (base 16) Palm, Inc - 950 West Maude Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-1D-FF (hex) Network Critical Solutions Ltd - 001DFF (base 16) Network Critical Solutions Ltd - 12B Southview Park - Caversham - Reading Berkshire RG45AF - UNITED KINGDOM - - 00-1E-00 (hex) Shantou Institute of Ultrasonic Instruments - 001E00 (base 16) Shantou Institute of Ultrasonic Instruments - No.77, Jinsha Road, - Shantou Guangdong 515041 - CHINA - - 00-1E-01 (hex) Renesas Technology Sales Co., Ltd. - 001E01 (base 16) Renesas Technology Sales Co., Ltd. - 2-6-2 - Otemachi - Chiyoda-ku Tokyo 100-0004 - JAPAN - - 00-1E-02 (hex) Sougou Keikaku Kougyou Co.,Ltd. - 001E02 (base 16) Sougou Keikaku Kougyou Co.,Ltd. - HK2 bld. 2-21-10 - Nishiogiminami - Suginamiku Tokyo 167-0053 - JAPAN - - 00-1E-03 (hex) LiComm Co., Ltd. - 001E03 (base 16) LiComm Co., Ltd. - 908-1 SEO-RI, IDONG-MYEON - YONGIN-SI GYEONGGI-DO 449-834 - KOREA, REPUBLIC OF - - 00-1E-04 (hex) Hanson Research Corporation - 001E04 (base 16) Hanson Research Corporation - 9810 Variel Ave. - Chatsworth CA 91311 - UNITED STATES - - 00-1E-05 (hex) Xseed Technologies & Computing - 001E05 (base 16) Xseed Technologies & Computing - Topaz House, MATAM - 5 Nahum Hat St. - Haifa 39100 - ISRAEL - - 00-1E-06 (hex) WIBRAIN - 001E06 (base 16) WIBRAIN - 306 JEI Plats B/D 459-11 Gasan-dong, Geumcheon-gu - SEOUL 153-803 - KOREA, REPUBLIC OF - - 00-1E-07 (hex) Winy Technology Co., Ltd. - 001E07 (base 16) Winy Technology Co., Ltd. - 305-303, Bucheon Techno-park, #365 - Samjeong-dong, Ojeong-gu - Bucheon Gyeonggi-do 421-741 - KOREA, REPUBLIC OF - - 00-1E-08 (hex) Centec Networks Inc - 001E08 (base 16) Centec Networks Inc - Suite 4F-13/16, Building B, No.5 Xing Han Street - Suzhou Industrial Park - Suzhou Jiangsu 215021 - CHINA - - 00-1E-09 (hex) ZEFATEK Co.,LTD - 001E09 (base 16) ZEFATEK Co.,LTD - 326-4 Gasandong, Geumcheongu - Seoul 153-802 - KOREA, REPUBLIC OF - - 00-1E-0A (hex) Syba Tech Limited - 001E0A (base 16) Syba Tech Limited - RM1301, Vanta Industrial Centre, - 21-33 Tai Lin Pai Rd. - Kwai Chung - HONG KONG - - 00-1E-0B (hex) Hewlett-Packard Company - 001E0B (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-1E-0C (hex) Sherwood Information Partners, Inc. - 001E0C (base 16) Sherwood Information Partners, Inc. - 1120 W, 122nd Ave, Ste 300 - Westminster CO 80234 - UNITED STATES - - 00-1E-0D (hex) Micran Ltd. - 001E0D (base 16) Micran Ltd. - Vershinina st. 47 - Tomsk Tomsk Region 634034 - RUSSIAN FEDERATION - - 00-1E-0E (hex) MAXI VIEW HOLDINGS LIMITED - 001E0E (base 16) MAXI VIEW HOLDINGS LIMITED - Suite 2302,23/F Great Eagle Centre, 23 Harbour Road, Wanchai - Hong Kong - CHINA - - 00-1E-0F (hex) Briot International - 001E0F (base 16) Briot International - 2 rue roger Bonnet - Pont de l'Arche Eure 27340 - FRANCE - - 00-1E-10 (hex) ShenZhen Huawei Communication Technologies Co.,Ltd. - 001E10 (base 16) ShenZhen Huawei Communication Technologies Co.,Ltd. - HUAWEI INDUSTRIAL PK BANTIAN, LONGGANG DIST SHENZHEN - SHENZHEN GUANGDONG 518077 - CHINA - - 00-1E-11 (hex) ELELUX INTERNATIONAL LTD - 001E11 (base 16) ELELUX INTERNATIONAL LTD - 3F., NO.103 CHOW TZE STREET - NEI-HU DISTRICT (114) - TAIPEI 114 - TAIWAN, PROVINCE OF CHINA - - 00-1E-12 (hex) Ecolab - 001E12 (base 16) Ecolab - 655 Lone Oak Drive - Research Center Dock -- F4416 - Eagan MN 55121 - UNITED STATES - - 00-1E-13 (hex) CISCO SYSTEMS, INC. - 001E13 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-14 (hex) CISCO SYSTEMS, INC. - 001E14 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-15 (hex) Beech Hill Electronics - 001E15 (base 16) Beech Hill Electronics - Beechcroft, Beech Hill Road - Beech Hill - Reading Berkshire RG7 2AU - UNITED KINGDOM - - 00-1E-16 (hex) Keytronix - 001E16 (base 16) Keytronix - Ungargasse 64-66/1/109 - Vienna 1030 - AUSTRIA - - 00-1E-17 (hex) STN BV - 001E17 (base 16) STN BV - Amerikaweg 4 - Hulst Zeeland 4561 PB - NETHERLANDS - - 00-1E-18 (hex) Radio Activity srl - 001E18 (base 16) Radio Activity srl - Via De Notaris 50 - Milano MI 20128 - ITALY - - 00-1E-19 (hex) GTRI - 001E19 (base 16) GTRI - M/S 0821 - Atlanta GA 30332 - UNITED STATES - - 00-1E-1A (hex) Best Source Taiwan Inc. - 001E1A (base 16) Best Source Taiwan Inc. - 2F, No.16, Lane 56, Jhongjheng W. Rd., - Jhubei City, Hsinchu County 302 - TAIWAN, PROVINCE OF CHINA - - 00-1E-1B (hex) Digital Stream Technology, Inc. - 001E1B (base 16) Digital Stream Technology, Inc. - 4,5,6th Fl., TaeChang B/D, 451-1 - SungNae-Dong, GangDong-Ku - Seoul 134-030 - KOREA, REPUBLIC OF - - 00-1E-1C (hex) SWS Australia Pty Limited - 001E1C (base 16) SWS Australia Pty Limited - 23 Scanlon Drive - Epping Victoria 3076 - AUSTRALIA - - 00-1E-1D (hex) East Coast Datacom, Inc. - 001E1D (base 16) East Coast Datacom, Inc. - 245 Gus Hipp Blvd., STE 3 - Rockledge FL 32955 - UNITED STATES - - 00-1E-1E (hex) Honeywell Life Safety - 001E1E (base 16) Honeywell Life Safety - 12 Clintonville Road - Northford CT 0422 - UNITED STATES - - 00-1E-1F (hex) Nortel - 001E1F (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1E-20 (hex) Intertain Inc. - 001E20 (base 16) Intertain Inc. - Suite 608 LG Eclat-2, 245-4 Seohyun-dong, Bundang-gu - Sungngm-shi Kyunggi-do 463-824 - KOREA, REPUBLIC OF - - 00-1E-21 (hex) Qisda Co. - 001E21 (base 16) Qisda Co. - 157 Shan-Ying Road, Gueishan - Taoyuan 333 - TAIWAN, PROVINCE OF CHINA - - 00-1E-22 (hex) ARVOO Imaging Products BV - 001E22 (base 16) ARVOO Imaging Products BV - PO Box 439 - Woerden UT 3440 AK - NETHERLANDS - - 00-1E-23 (hex) Electronic Educational Devices, Inc - 001E23 (base 16) Electronic Educational Devices, Inc - 1903 S Grant St - Denver CO 80210 - UNITED STATES - - 00-1E-24 (hex) Zhejiang Bell Technology Co.,ltd - 001E24 (base 16) Zhejiang Bell Technology Co.,ltd - 6 Xidoumen Rd. West Lake district - Hangzhou Zhejiang 310012 - CHINA - - 00-1E-25 (hex) Intek Digital Inc - 001E25 (base 16) Intek Digital Inc - 1101, 11th Fl., Anyang K-center building, 1591-9 - Gwanyang-dong, Dongan-gu - Anyang Gyeonggi-do 431-815 - KOREA, REPUBLIC OF - - 00-1E-26 (hex) Digifriends Co. Ltd - 001E26 (base 16) Digifriends Co. Ltd - Joyang B/D 6th Floor - 113 Samsung-dong, Kangnam-gu - Seoul 135-090 - KOREA, REPUBLIC OF - - 00-1E-27 (hex) SBN TECH Co.,Ltd. - 001E27 (base 16) SBN TECH Co.,Ltd. - #706 Industrial Academic Center, Konkuk University, Hwayang-dong, Gwangjin-gu - Seoul 143-701 - KOREA, REPUBLIC OF - - 00-1E-28 (hex) Lumexis Corporation - 001E28 (base 16) Lumexis Corporation - 3184 Airway Ave Bldg D - Costa Mesa CA 92626 - UNITED STATES - - 00-1E-29 (hex) Hypertherm Inc - 001E29 (base 16) Hypertherm Inc - 15 Great Hollow Rd - PO Box 5010 - Hanover NH 03755 - UNITED STATES - - 00-1E-2A (hex) Netgear Inc. - 001E2A (base 16) Netgear Inc. - 4500 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 00-1E-2B (hex) Radio Systems Design, Inc. - 001E2B (base 16) Radio Systems Design, Inc. - 601 Heron Drive - Logan Twp New Jersey 08085 - UNITED STATES - - 00-1E-2C (hex) CyVerse Corporation - 001E2C (base 16) CyVerse Corporation - Shoutou Roukubankan Bldg. 4F - 1-28-4, Shoutou - Shibuya-ku Tokyo 150-0046 - JAPAN - - 00-1E-2D (hex) STIM - 001E2D (base 16) STIM - ZAC les COUSTELLIERS - 6 Rue de L'ABRIVADO - CASTRIES HERAULT 34160 - FRANCE - - 00-1E-2E (hex) SIRTI S.p.A. - 001E2E (base 16) SIRTI S.p.A. - Via Stamira d'Ancona 9 - MILAN 20127 - ITALY - - 00-1E-2F (hex) DiMoto Pty Ltd - 001E2F (base 16) DiMoto Pty Ltd - 7 Meljaren Place - Buderim Queensland 4556 - AUSTRALIA - - 00-1E-30 (hex) Shireen Inc - 001E30 (base 16) Shireen Inc - 8531 Ziggy Lane - Gaithersburg MD 20877 - UNITED STATES - - 00-1E-31 (hex) INFOMARK CO.,LTD. - 001E31 (base 16) INFOMARK CO.,LTD. - 5F.,Geown Bldg.,1360-53 - Seoul Seocho-dong,Seocho-gu 137-863 - KOREA, REPUBLIC OF - - 00-1E-32 (hex) Zensys - 001E32 (base 16) Zensys - Emdrupvej 26 - Copenhagen O DK-2100 - DENMARK - - 00-1E-33 (hex) Inventec Corporation - 001E33 (base 16) Inventec Corporation - Inventec Building, 66 Hou-Kang Street - Shin-Lin District - Taipei 111 - TAIWAN, PROVINCE OF CHINA - - 00-1E-34 (hex) CryptoMetrics - 001E34 (base 16) CryptoMetrics - 160 Michael Cowpland Dr - Ottawa Ontario K2M 1P6 - CANADA - - 00-1E-35 (hex) Nintendo Co., Ltd. - 001E35 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1E-36 (hex) IPTE - 001E36 (base 16) IPTE - Geleenlaan 5 - Genk Limburg 3600 - BELGIUM - - 00-1E-37 (hex) Universal Global Scientific Industrial Co., Ltd. - 001E37 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351, SEC.1,TAIPING RD. - TSAOTUEN - NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 00-1E-38 (hex) Bluecard Software Technology Co., Ltd. - 001E38 (base 16) Bluecard Software Technology Co., Ltd. - D-801 Shangdi Science Building - No.8 Shangdi West Road - Beijing 100085 - CHINA - - 00-1E-39 (hex) Comsys Communication Ltd. - 001E39 (base 16) Comsys Communication Ltd. - 9 Hamenofim st. - Herzelia 46725 - ISRAEL - - 00-1E-3A (hex) Nokia Danmark A/S - 001E3A (base 16) Nokia Danmark A/S - Frederiskaj - Copenhagen V DK-1790 - DENMARK - - 00-1E-3B (hex) Nokia Danmark A/S - 001E3B (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1E-3C (hex) Lyngbox Media AB - 001E3C (base 16) Lyngbox Media AB - Diskettgatan 11B - Linkoping SE-58335 - SWEDEN - - 00-1E-3D (hex) Alps Electric Co., Ltd - 001E3D (base 16) Alps Electric Co., Ltd - 1-2-1, Okinouchi - Soma city Fukushim-pref 976-8501 - JAPAN - - 00-1E-3E (hex) KMW Inc. - 001E3E (base 16) KMW Inc. - 65 Youngchun-ri, Dongtan-myun - Hwasung-si Kyungki-do 445-813 - KOREA, REPUBLIC OF - - 00-1E-3F (hex) TrellisWare Technologies, Inc. - 001E3F (base 16) TrellisWare Technologies, Inc. - 16516 Via Esprillo, Suite 300 - San Diego CA 92127 - UNITED STATES - - 00-1E-40 (hex) Shanghai DareGlobal Technologies Co.,Ltd. - 001E40 (base 16) Shanghai DareGlobal Technologies Co.,Ltd. - 22F, lnfo Tech Building, NO.1555 Kongjiang Road, - Shanghai 200092 - CHINA - - 00-1E-41 (hex) Microwave Communication & Component, Inc. - 001E41 (base 16) Microwave Communication & Component, Inc. - #204, WOOLIM LION`S VALLEY 2, 680 - Gasan-Dong, Geumchon-GU - Seoul 150-787 - KOREA, REPUBLIC OF - - 00-1E-42 (hex) Teltonika - 001E42 (base 16) Teltonika - Zirmunu 27 - Vilnius LT - 09105 - LITHUANIA - - 00-1E-43 (hex) AISIN AW CO.,LTD. - 001E43 (base 16) AISIN AW CO.,LTD. - 6-18 HARAYAMA - OKA-CHO - OKAZAKI AICHI 444-8564 - JAPAN - - 00-1E-44 (hex) SANTEC - 001E44 (base 16) SANTEC - An der Strusbek 31 - Ahrensburg Schleswig Holstein 22926 - GERMANY - - 00-1E-45 (hex) Sony Ericsson Mobile Communications AB - 001E45 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-1E-46 (hex) ARRIS Group, Inc. - 001E46 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1E-47 (hex) PT. Hariff Daya Tunggal Engineering - 001E47 (base 16) PT. Hariff Daya Tunggal Engineering - Jl. Soekarno Hatta No. 450 - Bandung Jawa Barat 40266 - INDONESIA - - 00-1E-48 (hex) Wi-Links - 001E48 (base 16) Wi-Links - 332 Ayiou street - Limassol 3725 - CYPRUS - - 00-1E-49 (hex) CISCO SYSTEMS, INC. - 001E49 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-4A (hex) CISCO SYSTEMS, INC. - 001E4A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-4B (hex) City Theatrical - 001E4B (base 16) City Theatrical - 475 Barell Ave - Carlstadt New Jersey 07072 - UNITED STATES - - 00-1E-4C (hex) Hon Hai Precision Ind.Co., Ltd. - 001E4C (base 16) Hon Hai Precision Ind.Co., Ltd. - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-1E-4D (hex) Welkin Sciences, LLC - 001E4D (base 16) Welkin Sciences, LLC - 102 S. Tejon St, Suite 200 - Colorado Springs CO 80903 - UNITED STATES - - 00-1E-4E (hex) DAKO EDV-Ingenieur- und Systemhaus GmbH - 001E4E (base 16) DAKO EDV-Ingenieur- und Systemhaus GmbH - Ernst-Haeckel-Platz 5/6 - Jena Thuringia 07745 - GERMANY - - 00-1E-4F (hex) Dell Inc. - 001E4F (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-1E-50 (hex) BATTISTONI RESEARCH - 001E50 (base 16) BATTISTONI RESEARCH - IV Trav. PARCO DONICA 12 - FISCIANO SALERNO 84084 - ITALY - - 00-1E-51 (hex) Converter Industry Srl - 001E51 (base 16) Converter Industry Srl - Via Euclide, 12 - Forli' FC 47100 - ITALY - - 00-1E-52 (hex) Apple - 001E52 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-1E-53 (hex) Further Tech Co., LTD - 001E53 (base 16) Further Tech Co., LTD - 8F,NO 421, Sungshan RD.,Taipei, Taiwn,R.O.C. - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-1E-54 (hex) TOYO ELECTRIC Corporation - 001E54 (base 16) TOYO ELECTRIC Corporation - 1-39 HIKISAWA - KAGIYA-CHO - KASUGAI AICHI 480-0393 - JAPAN - - 00-1E-55 (hex) COWON SYSTEMS,Inc. - 001E55 (base 16) COWON SYSTEMS,Inc. - 6th Fl. COWON TOWER,689-3, - Yeoksam-Dong,Gangnam-Gu, - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-1E-56 (hex) Bally Wulff Entertainment GmbH - 001E56 (base 16) Bally Wulff Entertainment GmbH - Maybachufer 48-51 - Berlin 12045 - GERMANY - - 00-1E-57 (hex) ALCOMA, spol. s r.o. - 001E57 (base 16) ALCOMA, spol. s r.o. - Klukovice 313, Praha - 5 - Praha 152 00 - CZECH REPUBLIC - - 00-1E-58 (hex) D-Link Corporation - 001E58 (base 16) D-Link Corporation - NO.289, Sinhu 3rd Rd., - Neihu District, Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-1E-59 (hex) Silicon Turnkey Express, LLC - 001E59 (base 16) Silicon Turnkey Express, LLC - 749 Miner Road - Highland Heights Ohio 44143 - UNITED STATES - - 00-1E-5A (hex) ARRIS Group, Inc. - 001E5A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1E-5B (hex) Unitron Company, Inc. - 001E5B (base 16) Unitron Company, Inc. - 10925 Miller Road - Dallas TX 75238 - UNITED STATES - - 00-1E-5C (hex) RB GeneralEkonomik - 001E5C (base 16) RB GeneralEkonomik - Bulevar despota stefana 59a - Beograd Serbia 11000 - YUGOSLAVIA - - 00-1E-5D (hex) Holosys d.o.o. - 001E5D (base 16) Holosys d.o.o. - Kovinska 4 - Zagreb 10090 - CROATIA - - 00-1E-5E (hex) COmputime Ltd. - 001E5E (base 16) COmputime Ltd. - 17/F Great Eagle Centre - 23 Harbour Road - Wanchai - HONG KONG - - 00-1E-5F (hex) KwikByte, LLC - 001E5F (base 16) KwikByte, LLC - 2430 W. 12th Street - Tempe AZ 85281 - UNITED STATES - - 00-1E-60 (hex) Digital Lighting Systems, Inc - 001E60 (base 16) Digital Lighting Systems, Inc - 12302 Sw 128th ct, #105 - Miami FL 33186 - UNITED STATES - - 00-1E-61 (hex) ITEC GmbH - 001E61 (base 16) ITEC GmbH - Lassnitzthal 300 - A-8200 Gleisdorf - AUSTRIA - - 00-1E-62 (hex) Siemon - 001E62 (base 16) Siemon - 27 Siemon Company Drive - Watertown CT 06795 - UNITED STATES - - 00-1E-63 (hex) Vibro-Meter SA - 001E63 (base 16) Vibro-Meter SA - Route de Moncor 4 - Fribourg CH-1701 - SWITZERLAND - - 00-1E-64 (hex) Intel Corporate - 001E64 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1E-65 (hex) Intel Corporate - 001E65 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1E-66 (hex) RESOL Elektronische Regelungen GmbH - 001E66 (base 16) RESOL Elektronische Regelungen GmbH - Heiskampstraße 10 - Hattingen NRW 45527 - GERMANY - - 00-1E-67 (hex) Intel Corporate - 001E67 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1E-68 (hex) Quanta Computer - 001E68 (base 16) Quanta Computer - NO. 211, WEN HWA 2RD., KUEI SHAN HSIANG - TAIPEI TAO YUAN SHIEN 333 - TAIWAN, PROVINCE OF CHINA - - 00-1E-69 (hex) Thomson Inc. - 001E69 (base 16) Thomson Inc. - 101 West. 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 00-1E-6A (hex) Beijing Bluexon Technology Co.,Ltd - 001E6A (base 16) Beijing Bluexon Technology Co.,Ltd - Jinqiuzhichun 7-301,Zhichun Rd., - Haidian District - Beijing 100088 - CHINA - - 00-1E-6B (hex) Cisco SPVTG - 001E6B (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 00-1E-6C (hex) Opaque Systems - 001E6C (base 16) Opaque Systems - 4820 Fisher Road - Athens OH 45701 - UNITED STATES - - 00-1E-6D (hex) IT R&D Center - 001E6D (base 16) IT R&D Center - 461-25, Jeonmin-dong,Yuseong-Gu - Daejeon 305-811 - KOREA, REPUBLIC OF - - 00-1E-6E (hex) Shenzhen First Mile Communications Ltd - 001E6E (base 16) Shenzhen First Mile Communications Ltd - 5th Floor, Block R3-A - High-Tech Industrial Park - Shenzhen Guangdong 518057 - CHINA - - 00-1E-6F (hex) Magna-Power Electronics, Inc. - 001E6F (base 16) Magna-Power Electronics, Inc. - 39 Royal Road - Flemington NJ 08822 - UNITED STATES - - 00-1E-70 (hex) Cobham Defence Communications Ltd - 001E70 (base 16) Cobham Defence Communications Ltd - Haslingden Road - Blackburn Lancashire BB1 2EE - UNITED KINGDOM - - 00-1E-71 (hex) MIrcom Group of Companies - 001E71 (base 16) MIrcom Group of Companies - 25 Interchange Way - Vaughan, Ontario l4K 5W3 - CANADA - - 00-1E-72 (hex) PCS - 001E72 (base 16) PCS - 2 RUE HENRI FARMAN - BP 20322 - LESCAR PYRENEES ATLANTIQUES 64230 - FRANCE - - 00-1E-73 (hex) ZTE CORPORATION - 001E73 (base 16) ZTE CORPORATION - 12/F ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District, - Shenzhen GUANGDONG 518057 - CHINA - - 00-1E-74 (hex) SAGEM COMMUNICATION - 001E74 (base 16) SAGEM COMMUNICATION - 14 Rue Paul Dautier - Velizy 78457 - FRANCE - - 00-1E-75 (hex) LG Electronics - 001E75 (base 16) LG Electronics - 60-39,Kasan-dong,Kumchon-ku - Seoul 153-801 - KOREA, REPUBLIC OF - - 00-1E-76 (hex) Thermo Fisher Scientific - 001E76 (base 16) Thermo Fisher Scientific - 2215 Grand Avenue Parkway - Austin Texas 78728 - UNITED STATES - - 00-1E-77 (hex) Air2App - 001E77 (base 16) Air2App - 50 Old Forge Rd - Hanover MA 02339 - UNITED STATES - - 00-1E-78 (hex) Owitek Technology Ltd., - 001E78 (base 16) Owitek Technology Ltd., - No.2, Lane 78, Cingshan 6th St., - Yangmei Township, - Taoyuan County 32657 - TAIWAN, PROVINCE OF CHINA - - 00-1E-79 (hex) CISCO SYSTEMS, INC. - 001E79 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-7A (hex) CISCO SYSTEMS, INC. - 001E7A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-7B (hex) R.I.CO. S.r.l. - 001E7B (base 16) R.I.CO. S.r.l. - via Adriatica, 17 - Castelfidardo AN 60022 - ITALY - - 00-1E-7C (hex) Taiwick Limited - 001E7C (base 16) Taiwick Limited - 5/F., Block E, Hing Yip Factory Bldg., - 31 Hing Yip Street., Kwun Tong, Kln., HK. - China 852 - HONG KONG - - 00-1E-7D (hex) Samsung Electronics Co.,Ltd - 001E7D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1E-7E (hex) Nortel - 001E7E (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1E-7F (hex) CBM of America - 001E7F (base 16) CBM of America - 1455 West Newport Center Drive - Deerfield Beach Florida 33442 - UNITED STATES - - 00-1E-80 (hex) Last Mile Ltd. - 001E80 (base 16) Last Mile Ltd. - 12/F VIP Commercial Centre - 120 Canton Road - Tsimshatsui - HONG KONG - - 00-1E-81 (hex) CNB Technology Inc. - 001E81 (base 16) CNB Technology Inc. - #701 Star Valley, 60-11 Gasan-Dong, - Geumcheon-Gu - Seoul 153777 - KOREA, REPUBLIC OF - - 00-1E-82 (hex) SanDisk Corporation - 001E82 (base 16) SanDisk Corporation - 630 Alder Drive, - Suite 202 - Milpitas CA 95035 - UNITED STATES - - 00-1E-83 (hex) LAN/MAN Standards Association (LMSC) - 001E83 (base 16) LAN/MAN Standards Association (LMSC) - C/O IEEE Standards Association - 445 Hoes Lane, - Piscataway NJ 08855 - UNITED STATES - - 00-1E-84 (hex) Pika Technologies Inc. - 001E84 (base 16) Pika Technologies Inc. - 535 Legget Drive - Suite 400 - Ottawa Ontario K2K 3B8 - CANADA - - 00-1E-85 (hex) Lagotek Corporation - 001E85 (base 16) Lagotek Corporation - 11661 SE 1st St. #208 - Bellevue WA 98005 - UNITED STATES - - 00-1E-86 (hex) MEL Co.,Ltd. - 001E86 (base 16) MEL Co.,Ltd. - Tsukagoshi 5-5-1,Warabi-shi,Saitama,Japna - Warabi Saitama 335-0002 - JAPAN - - 00-1E-87 (hex) Realease Limited - 001E87 (base 16) Realease Limited - 15/F, Morrison Commercial Building - 31 Morrison Hill Road - WanChai - HONG KONG - - 00-1E-88 (hex) ANDOR SYSTEM SUPPORT CO., LTD. - 001E88 (base 16) ANDOR SYSTEM SUPPORT CO., LTD. - Minami-Shinagawa 2-15-8 - Sinagawa Tokyo 140-0004 - JAPAN - - 00-1E-89 (hex) CRFS Limited - 001E89 (base 16) CRFS Limited - Building 7200 - Cambridge Research Park - Waterbeach Cambridgeshire CB25 9TL - UNITED KINGDOM - - 00-1E-8A (hex) eCopy, Inc - 001E8A (base 16) eCopy, Inc - 1 Oracle Dr - Nashua NH 03062 - UNITED STATES - - 00-1E-8B (hex) Infra Access Korea Co., Ltd. - 001E8B (base 16) Infra Access Korea Co., Ltd. - #902, Sambo Saving Bank B/D, - 735-11 Boramae-Dong, - Kwanak-gu, Seoul 151-830 - KOREA, REPUBLIC OF - - 00-1E-8C (hex) ASUSTek COMPUTER INC. - 001E8C (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-1E-8D (hex) ARRIS Group, Inc. - 001E8D (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1E-8E (hex) Hunkeler AG - 001E8E (base 16) Hunkeler AG - Bahnhofstrasse 31 - Wikon CH 4806 - SWITZERLAND - - 00-1E-8F (hex) CANON INC. - 001E8F (base 16) CANON INC. - 3-30-2 - Shimomaruko - Ohta-Ku Tokyo 146-8501 - JAPAN - - 00-1E-90 (hex) Elitegroup Computer Systems Co - 001E90 (base 16) Elitegroup Computer Systems Co - No.239, Sec. 2, Ti Ding Blvd - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 00-1E-91 (hex) KIMIN Electronic Co., Ltd. - 001E91 (base 16) KIMIN Electronic Co., Ltd. - 293-4, Dongdan-Dong - Gumi-city GyeongBuk 730-906 - KOREA, REPUBLIC OF - - 00-1E-92 (hex) JEULIN S.A. - 001E92 (base 16) JEULIN S.A. - ZI N°1 - rue Jacques Monod - Evreux F27019 - FRANCE - - 00-1E-93 (hex) CiriTech Systems Inc - 001E93 (base 16) CiriTech Systems Inc - 920 Hillview Ct - #170 - Milpitas CA 95035 - UNITED STATES - - 00-1E-94 (hex) SUPERCOM TECHNOLOGY CORPORATION - 001E94 (base 16) SUPERCOM TECHNOLOGY CORPORATION - 8F, NO 100-1, Ming-Chuan Rd. - Shing Tien Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-1E-95 (hex) SIGMALINK - 001E95 (base 16) SIGMALINK - DooSan VentureDigm 1028, - 126-1 Pyungchon-dong, Dongan-Ku - Anyang-City Kyunggi-do 431-070 - KOREA, REPUBLIC OF - - 00-1E-96 (hex) Sepura Plc - 001E96 (base 16) Sepura Plc - Radio House - St Andrews Road - Cambridge CAMBRIDGESHIRE CB4 1GR - UNITED KINGDOM - - 00-1E-97 (hex) Medium Link System Technology CO., LTD, - 001E97 (base 16) Medium Link System Technology CO., LTD, - 11F.-2, No.7, Alley 92, Lane 77, Sec. 4, Sinhai Rd., - Wunshan District, Taipei 11693 - TAIWAN, PROVINCE OF CHINA - - 00-1E-98 (hex) GreenLine Communications - 001E98 (base 16) GreenLine Communications - Alrabiah, Alrabeea street - Building 8, P.O. Box 921 - Amman Central Region 11953 - JORDAN - - 00-1E-99 (hex) Vantanol Industrial Corporation - 001E99 (base 16) Vantanol Industrial Corporation - 9F, NO 31 . Shin-Tai Road - Jubei City Shinchu 302 - TAIWAN, PROVINCE OF CHINA - - 00-1E-9A (hex) HAMILTON Bonaduz AG - 001E9A (base 16) HAMILTON Bonaduz AG - Via Crusch 8 - Bonaduz Graubuenden 7402 - SWITZERLAND - - 00-1E-9B (hex) San-Eisha, Ltd. - 001E9B (base 16) San-Eisha, Ltd. - 2-1 Ebara 5-chome - Shinagawa-ku Tokyo 142-8611 - JAPAN - - 00-1E-9C (hex) Fidustron INC - 001E9C (base 16) Fidustron INC - NO.770-6, Jhongiheng Rd. - Jhonghe City Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-1E-9D (hex) Recall Technologies, Inc. - 001E9D (base 16) Recall Technologies, Inc. - 130 Enterprise Ave. - Suite F - Palm Bay FL 32909 - UNITED STATES - - 00-1E-9E (hex) ddm hopt + schuler Gmbh + Co. KG - 001E9E (base 16) ddm hopt + schuler Gmbh + Co. KG - Koenigsberger Strasse 12 - Rottweil Baden-Württemberg 78626 - GERMANY - - 00-1E-9F (hex) Visioneering Systems, Inc. - 001E9F (base 16) Visioneering Systems, Inc. - 5931 Sea Lion Place - Suite 109 - Carlsbad California 92010 - UNITED STATES - - 00-1E-A0 (hex) XLN-t - 001EA0 (base 16) XLN-t - Hoogstraat 52 - Putte Antwerp B2580 - BELGIUM - - 00-1E-A1 (hex) Brunata a/s - 001EA1 (base 16) Brunata a/s - Vesterlundvej 14 - Herlev 2730 - DENMARK - - 00-1E-A2 (hex) Symx Systems, Inc. - 001EA2 (base 16) Symx Systems, Inc. - 6320 NW 84th Avenue - Miami Florida 33166 - UNITED STATES - - 00-1E-A3 (hex) Nokia Danmark A/S - 001EA3 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1E-A4 (hex) Nokia Danmark A/S - 001EA4 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1E-A5 (hex) ROBOTOUS, Inc. - 001EA5 (base 16) ROBOTOUS, Inc. - Nex Center-201(Lab.), SK n Technopark - Sangdaewon-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-120 - KOREA, REPUBLIC OF - - 00-1E-A6 (hex) Best IT World (India) Pvt. Ltd. - 001EA6 (base 16) Best IT World (India) Pvt. Ltd. - 87/70/93 Mistry Industrial Complex, - MIDC Cross Road 'A', Andheri (East) - Mumbai Maharashtra 400093 - INDIA - - 00-1E-A7 (hex) ActionTec Electronics, Inc - 001EA7 (base 16) ActionTec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94086 - UNITED STATES - - 00-1E-A8 (hex) Datang Mobile Communications Equipment CO.,LTD - 001EA8 (base 16) Datang Mobile Communications Equipment CO.,LTD - No.29,Xueyuan Rd. - Haidian District - Beijing 100083 - CHINA - - 00-1E-A9 (hex) Nintendo Co., Ltd. - 001EA9 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1E-AA (hex) E-Senza Technologies GmbH - 001EAA (base 16) E-Senza Technologies GmbH - Blarerstrasse 56 - Konstanz BW 78462 - GERMANY - - 00-1E-AB (hex) TeleWell Oy - 001EAB (base 16) TeleWell Oy - Alahotie 14 b - Jarvenpaa Uusimaa 04430 - FINLAND - - 00-1E-AC (hex) Armadeus Systems - 001EAC (base 16) Armadeus Systems - Business Campus - 15 rue des Frères Lumière - MULHOUSE cedex Haut-Rhin 68058 - FRANCE - - 00-1E-AD (hex) Wingtech Group Limited - 001EAD (base 16) Wingtech Group Limited - 6th floor, Unit G, No.668, East Beijing Road, - Shanghai 200001 - CHINA - - 00-1E-AE (hex) Continental Automotive Systems - 001EAE (base 16) Continental Automotive Systems - 21440 West Lake Cook Road - Deer Park IL 60010 - UNITED STATES - - 00-1E-AF (hex) Ophir Optronics Ltd - 001EAF (base 16) Ophir Optronics Ltd - POB 45021 - Jerusalem 91450 - ISRAEL - - 00-1E-B0 (hex) ImesD Electronica S.L. - 001EB0 (base 16) ImesD Electronica S.L. - d'Entença 81 - Barcelona 08015 - SPAIN - - 00-1E-B1 (hex) Cryptsoft Pty Ltd - 001EB1 (base 16) Cryptsoft Pty Ltd - P.O. Box 6389 - Fairfield Gardens Queensland 4103 - AUSTRALIA - - 00-1E-B2 (hex) LG innotek - 001EB2 (base 16) LG innotek - Hanyang Univ. 1271, Sa-dong, Sangrok-gu - Ansan-si Gyeonggi-do 426-791 - KOREA, REPUBLIC OF - - 00-1E-B3 (hex) Primex Wireless - 001EB3 (base 16) Primex Wireless - 965 Wells Street - Lake Geneva WI 53147 - UNITED STATES - - 00-1E-B4 (hex) UNIFAT TECHNOLOGY LTD. - 001EB4 (base 16) UNIFAT TECHNOLOGY LTD. - 7/FLOOR SUI HONG IND. BLDG., - 547-549 CASTLE PEAK ROAD - KWAI CHUNG, N.T. - HONG KONG - - 00-1E-B5 (hex) Ever Sparkle Technologies Ltd - 001EB5 (base 16) Ever Sparkle Technologies Ltd - Unit 403, Nan Fung Commercial Centre - 19, Lam Lok St. - Kowloon Bay Kowloon - HONG KONG - - 00-1E-B6 (hex) TAG Heuer SA - 001EB6 (base 16) TAG Heuer SA - Rue Louis-Joseph Chevrolet 6A - la Chaux-de-Fonds NE 2300 - SWITZERLAND - - 00-1E-B7 (hex) TBTech, Co., Ltd. - 001EB7 (base 16) TBTech, Co., Ltd. - 1109, Hyundai Krim, 1330-18, Seocho-dong, - Seocho-Gu, - Seoul 137-070 - KOREA, REPUBLIC OF - - 00-1E-B8 (hex) Fortis, Inc. - 001EB8 (base 16) Fortis, Inc. - #502 Techno plaza, 149-10 Yatap-dong, - Bundang-gu, - Seongnam-si, Gyeonggi-do, 463-816 - KOREA, REPUBLIC OF - - 00-1E-B9 (hex) Sing Fai Technology Limited - 001EB9 (base 16) Sing Fai Technology Limited - No.700, Kaohsiung University Rd., Nan-Tzu Dist. - NUK Advanced Business Incubation Center - Kaohsiung 811 - TAIWAN, PROVINCE OF CHINA - - 00-1E-BA (hex) High Density Devices AS - 001EBA (base 16) High Density Devices AS - Vestre Strandgate 26 - Kristiansand 4611 - NORWAY - - 00-1E-BB (hex) BLUELIGHT TECHNOLOGY INC. - 001EBB (base 16) BLUELIGHT TECHNOLOGY INC. - 6472 CAMDEN AVE., SUITE 102B - SAN JOSE CA 95120 - UNITED STATES - - 00-1E-BC (hex) WINTECH AUTOMATION CO.,LTD. - 001EBC (base 16) WINTECH AUTOMATION CO.,LTD. - #1115, TAEKWANG BLVD. - YOUNGRONG-DONG, YOUNGTONG-GU - SUWON-SI KYUNGGI 443-816 - KOREA, REPUBLIC OF - - 00-1E-BD (hex) CISCO SYSTEMS, INC. - 001EBD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-BE (hex) CISCO SYSTEMS, INC. - 001EBE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-BF (hex) Haas Automation Inc. - 001EBF (base 16) Haas Automation Inc. - 2800 Sturgis Rd - Oxnard CA 93030 - UNITED STATES - - 00-1E-C0 (hex) Microchip Technology Inc. - 001EC0 (base 16) Microchip Technology Inc. - 2355 W. Chandler Blvd., - Chandler AZ 85224 - UNITED STATES - - 00-1E-C1 (hex) 3COM EUROPE LTD - 001EC1 (base 16) 3COM EUROPE LTD - Peoplebuilding 2 - Maylands Avenue - Hemel Hempstead HERTS. HP2 4NW - UNITED KINGDOM - - 00-1E-C2 (hex) Apple - 001EC2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-1E-C3 (hex) Kozio, Inc. - 001EC3 (base 16) Kozio, Inc. - 2015 Ionosphere Street - Unit 201 - Longmont CO 80504 - UNITED STATES - - 00-1E-C4 (hex) Celio Corp - 001EC4 (base 16) Celio Corp - 265 E 100 S # 280 - Salt Lake City UT 84111 - UNITED STATES - - 00-1E-C5 (hex) Middle Atlantic Products Inc - 001EC5 (base 16) Middle Atlantic Products Inc - 300 Fairfield Road - Fairfield NJ 07004 - UNITED STATES - - 00-1E-C6 (hex) Obvius Holdings LLC - 001EC6 (base 16) Obvius Holdings LLC - 20811 NW Cornell Road - Suite 700 - Hillsboro OR 97124 - UNITED STATES - - 00-1E-C7 (hex) 2Wire, Inc. - 001EC7 (base 16) 2Wire, Inc. - 1704 Automation Prkwy - San Jose Ca 95131 - UNITED STATES - - 00-1E-C8 (hex) Rapid Mobile (Pty) Ltd - 001EC8 (base 16) Rapid Mobile (Pty) Ltd - Building C,D,E Apex Corporate Park - Quintin Brand Street, Persequor Technopark - Pretoria Gauteng 0020 - SOUTH AFRICA - - 00-1E-C9 (hex) Dell Inc - 001EC9 (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-1E-CA (hex) Nortel - 001ECA (base 16) Nortel - 8200 Dixie Road - Suite 100 - Brampton Ontario L6T 5P6 - CANADA - - 00-1E-CB (hex) "RPC "Energoautomatika" Ltd - 001ECB (base 16) "RPC "Energoautomatika" Ltd - Krasnokazarmennaya st., 13/1 - Moscow 111250 - RUSSIAN FEDERATION - - 00-1E-CC (hex) CDVI - 001ECC (base 16) CDVI - 31 Avenue du Général Leclerc - PANTIN Ile de France 93500 - FRANCE - - 00-1E-CD (hex) KYLAND Technology Co. LTD - 001ECD (base 16) KYLAND Technology Co. LTD - Building No.2,Shixing Avenue 30# - Shijingshan District Beijing 100044 - CHINA - - 00-1E-CE (hex) BISA Technologies (Hong Kong) Limited - 001ECE (base 16) BISA Technologies (Hong Kong) Limited - 1102, Trans Asia Centre, - 18 Kin Hong Street, - Kwai Chung - HONG KONG - - 00-1E-CF (hex) PHILIPS ELECTRONICS UK LTD - 001ECF (base 16) PHILIPS ELECTRONICS UK LTD - PHILIPS CENTRE - GUILDFORD BUSINESS PARK - GUILDFORD SURREY GU2 8XH - UNITED KINGDOM - - 00-1E-D0 (hex) Ingespace - 001ED0 (base 16) Ingespace - 6 rue de lourmede - Eurocentre 31621 - FRANCE - - 00-1E-D1 (hex) Keyprocessor B.V. - 001ED1 (base 16) Keyprocessor B.V. - Paasheuvelweg 20 - Amsterdam NH 1105 BJ - NETHERLANDS - - 00-1E-D2 (hex) Ray Shine Video Technology Inc - 001ED2 (base 16) Ray Shine Video Technology Inc - 6F,No.98,Sec.1,Xintai 5th Rd. - Xizhi City Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-1E-D3 (hex) Dot Technology Int'l Co., Ltd. - 001ED3 (base 16) Dot Technology Int'l Co., Ltd. - Unit 1001, Fourseas Building 208-212, Nathan Road - Kowloon - HONG KONG - - 00-1E-D4 (hex) Doble Engineering - 001ED4 (base 16) Doble Engineering - 85 Walnut Street - Watertown Massachusetts 02472 - UNITED STATES - - 00-1E-D5 (hex) Tekon-Automatics - 001ED5 (base 16) Tekon-Automatics - Zelenograd, 512-29 - Moscow 124482 - RUSSIAN FEDERATION - - 00-1E-D6 (hex) Alentec & Orion AB - 001ED6 (base 16) Alentec & Orion AB - Grustagsvägen 4 - 138 40 ÄLTA - SWEDEN - - 00-1E-D7 (hex) H-Stream Wireless, Inc. - 001ED7 (base 16) H-Stream Wireless, Inc. - 2595 East Bayshore Road - Suite 100 - Palo Alto CA 94303 - UNITED STATES - - 00-1E-D8 (hex) Digital United Inc. - 001ED8 (base 16) Digital United Inc. - 9F, No.220, Gangcian Rd. - Taipei 11444 - TAIWAN, PROVINCE OF CHINA - - 00-1E-D9 (hex) Mitsubishi Precision Co.,LTd. - 001ED9 (base 16) Mitsubishi Precision Co.,LTd. - 345 KAMIMACHIYA - KAMAKURA-City KANAGAWA-Prefecture 247-8505 - JAPAN - - 00-1E-DA (hex) Wesemann Elektrotechniek B.V. - 001EDA (base 16) Wesemann Elektrotechniek B.V. - Droogbloem 31 - Rotterdam Zuid-Holland 3068 AW - NETHERLANDS - - 00-1E-DB (hex) Giken Trastem Co., Ltd. - 001EDB (base 16) Giken Trastem Co., Ltd. - 4-1 Takeda Dankawaracho Fushimiku - Kyoto 612-8414 - JAPAN - - 00-1E-DC (hex) Sony Ericsson Mobile Communications AB - 001EDC (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-1E-DD (hex) WASKO S.A. - 001EDD (base 16) WASKO S.A. - Berbeckiego 6 - Gliwice Silesia 44-100 - POLAND - - 00-1E-DE (hex) BYD COMPANY LIMITED - 001EDE (base 16) BYD COMPANY LIMITED - NO.1,Baoping Road,Baolong Industrial Town,Longgang - SHEN ZHEN Guangdong 518116 - CHINA - - 00-1E-DF (hex) Master Industrialization Center Kista - 001EDF (base 16) Master Industrialization Center Kista - Torshamnsgatan 36 - Kista - Stockholm SE-164 80 - SWEDEN - - 00-1E-E0 (hex) Urmet Domus SpA - 001EE0 (base 16) Urmet Domus SpA - Via Bologna 188/C - Torino TO I-10154 - ITALY - - 00-1E-E1 (hex) Samsung Electronics Co.,Ltd - 001EE1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1E-E2 (hex) Samsung Electronics Co.,Ltd - 001EE2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1E-E3 (hex) T&W Electronics (ShenZhen) Co.,Ltd - 001EE3 (base 16) T&W Electronics (ShenZhen) Co.,Ltd - 2F Baiying Building, No.19, NanhaiRd., Nanshan Dist - ShenZhen GuangDong 518052 - CHINA - - 00-1E-E4 (hex) ACS Solutions France - 001EE4 (base 16) ACS Solutions France - Rue Claude Chappe - Guilherand Granges Ardeche 07503 - FRANCE - - 00-1E-E5 (hex) Cisco-Linksys, LLC - 001EE5 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 00-1E-E6 (hex) Shenzhen Advanced Video Info-Tech Co., Ltd. - 001EE6 (base 16) Shenzhen Advanced Video Info-Tech Co., Ltd. - Tianxiang 11A, Tian'an Cyber Park , Futian - Shenzhen Guangdong 518048 - CHINA - - 00-1E-E7 (hex) Epic Systems Inc - 001EE7 (base 16) Epic Systems Inc - 390 S. Abbott Ave - Milpitas CA 95035 - UNITED STATES - - 00-1E-E8 (hex) Mytek - 001EE8 (base 16) Mytek - 151 Lafayette Str 3 Fl - New York NY 10013 - UNITED STATES - - 00-1E-E9 (hex) Stoneridge Electronics AB - 001EE9 (base 16) Stoneridge Electronics AB - GÃ¥rdsfogdevägen 18A - Bromma Stockholm 168 66 - SWEDEN - - 00-1E-EA (hex) Sensor Switch, Inc. - 001EEA (base 16) Sensor Switch, Inc. - 900 Northrop Road - Wallingford CT 06492 - UNITED STATES - - 00-1E-EB (hex) Talk-A-Phone Co. - 001EEB (base 16) Talk-A-Phone Co. - 5013 N. Kedzie Ave. - Chicago IL 60625 - UNITED STATES - - 00-1E-EC (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - 001EEC (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 25, THE 3RD Street - KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN CITY SUZHOU PROVINCE 215300 - CHINA - - 00-1E-ED (hex) Adventiq Ltd. - 001EED (base 16) Adventiq Ltd. - Technology House - Trafalgar Way - Bar Hill Cambs. CB3 8SQ - UNITED KINGDOM - - 00-1E-EE (hex) ETL Systems Ltd - 001EEE (base 16) ETL Systems Ltd - Coldwell Radio Station - Madley - Hereford Herefordshire HR2 9NE - UNITED KINGDOM - - 00-1E-EF (hex) Cantronic International Limited - 001EEF (base 16) Cantronic International Limited - Unit 515-516, Building 15, East Wing, No 8 Science Park West Avenue, Hong Kong Science Park Phase II - Shatin New Territories 852 - HONG KONG - - 00-1E-F0 (hex) Gigafin Networks - 001EF0 (base 16) Gigafin Networks - 19050 Pruneridge - Suite 200 - Cupertino CA 95014 - UNITED STATES - - 00-1E-F1 (hex) Servimat - 001EF1 (base 16) Servimat - ZAET Les Haies - Rue Benoit Frachon - St Maximin Oise 60740 - FRANCE - - 00-1E-F2 (hex) Micro Motion Inc - 001EF2 (base 16) Micro Motion Inc - 7070 Winchester Circle - Boulder CO 80301 - UNITED STATES - - 00-1E-F3 (hex) From2 - 001EF3 (base 16) From2 - 2F, Mester inc - 1687-3, Sinil-dong - Daejeon 306-230 - KOREA, REPUBLIC OF - - 00-1E-F4 (hex) L-3 Communications Display Systems - 001EF4 (base 16) L-3 Communications Display Systems - 1355 Bluegrass Lakes Parkway - Alpharetta GA 30004-8458 - UNITED STATES - - 00-1E-F5 (hex) Hitek Automated Inc. - 001EF5 (base 16) Hitek Automated Inc. - Room C3-901, No.383, Huamen Shijia - Wensanlu Road, - Hangzhou 310012 - CHINA - - 00-1E-F6 (hex) CISCO SYSTEMS, INC. - 001EF6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-F7 (hex) CISCO SYSTEMS, INC. - 001EF7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1E-F8 (hex) Emfinity Inc. - 001EF8 (base 16) Emfinity Inc. - 1305 Kelly Lake Road - Unit 5 - Sudbury Ontario P3E5P5 - CANADA - - 00-1E-F9 (hex) Pascom Kommunikations systeme GmbH. - 001EF9 (base 16) Pascom Kommunikations systeme GmbH. - Technologiestr. 4 - Arbing Upper Austria 4332 - AUSTRIA - - 00-1E-FA (hex) PROTEI Ltd. - 001EFA (base 16) PROTEI Ltd. - 60A B.Sampsonievsky, Business Center - St.Petersburg RU 194044 - RUSSIAN FEDERATION - - 00-1E-FB (hex) Trio Motion Technology Ltd - 001EFB (base 16) Trio Motion Technology Ltd - Shannon Way - Tewkesbury Gloucestershire GL20 8ND - UNITED KINGDOM - - 00-1E-FC (hex) JSC "MASSA-K" - 001EFC (base 16) JSC "MASSA-K" - 15, A, Pirogovskaya nab. - Saint-Petersburg Leningradskiy reg. 194044 - RUSSIAN FEDERATION - - 00-1E-FD (hex) Microbit 2.0 AB - 001EFD (base 16) Microbit 2.0 AB - Nystaden 1 - KALIX 95261 - SWEDEN - - 00-1E-FE (hex) LEVEL s.r.o. - 001EFE (base 16) LEVEL s.r.o. - Plhovska 1997 - Nachod 547 01 - CZECH REPUBLIC - - 00-1E-FF (hex) Mueller-Elektronik GmbH & Co. KG - 001EFF (base 16) Mueller-Elektronik GmbH & Co. KG - Franz-Kleine-Str. 18 - Salzkotten NRW 33154 - GERMANY - - 00-1F-00 (hex) Nokia Danmark A/S - 001F00 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790V - DENMARK - - 00-1F-01 (hex) Nokia Danmark A/S - 001F01 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790v - DENMARK - - 00-1F-02 (hex) Pixelmetrix Corporation Pte Ltd - 001F02 (base 16) Pixelmetrix Corporation Pte Ltd - 31 Kaki Bukit Road 3 - #07-03, Techlink - 417818 - SINGAPORE - - 00-1F-03 (hex) NUM AG - 001F03 (base 16) NUM AG - Battenhusstrasse 16 - Teufen AR 9053 - SWITZERLAND - - 00-1F-04 (hex) Granch Ltd. - 001F04 (base 16) Granch Ltd. - 40 Koroleva str. - 53 Pisareva str. - Novosibirsk NSO 630015 - RUSSIAN FEDERATION - - 00-1F-05 (hex) iTAS Technology Corp. - 001F05 (base 16) iTAS Technology Corp. - No. 75, Shuiyuan St. - Hsinchu City 30069 - TAIWAN, PROVINCE OF CHINA - - 00-1F-06 (hex) Integrated Dispatch Solutions - 001F06 (base 16) Integrated Dispatch Solutions - 645 Mountain Ave - Wyckoff NJ 07481 - UNITED STATES - - 00-1F-07 (hex) AZTEQ Mobile - 001F07 (base 16) AZTEQ Mobile - Suite 210, 525 University Ave - Palo Alto CA 94301 - UNITED STATES - - 00-1F-08 (hex) RISCO LTD - 001F08 (base 16) RISCO LTD - 32 Hacharoshet St - Kiriat Malachi 83101 - ISRAEL - - 00-1F-09 (hex) JASTEC CO., LTD. - 001F09 (base 16) JASTEC CO., LTD. - Jastec B/D, 92-7 - Kum-gok Dong, Boon-Dang Gu - Seong-nam Si Kyung-gi Do 463-804 - KOREA, REPUBLIC OF - - 00-1F-0A (hex) Nortel - 001F0A (base 16) Nortel - 1830 Matheson Boulevard - Suite 1 - Mississauga Ontario L4W 0B3 - CANADA - - 00-1F-0B (hex) Federal State Unitary Enterprise Industrial Union"Electropribor" - 001F0B (base 16) Federal State Unitary Enterprise Industrial Union"Electropribor" - - Penza 440011 - RUSSIAN FEDERATION - - 00-1F-0C (hex) Intelligent Digital Services GmbH - 001F0C (base 16) Intelligent Digital Services GmbH - Grevesmuehlener Strasse 8 - Mallentin Mecklenburg-Vorpommern 23639 - GERMANY - - 00-1F-0D (hex) L3 Communications - Telemetry West - 001F0D (base 16) L3 Communications - Telemetry West - 9020 Balboa Ave - San Diego CA 92123 - UNITED STATES - - 00-1F-0E (hex) Japan Kyastem Co., Ltd - 001F0E (base 16) Japan Kyastem Co., Ltd - 1-4-4 - Nishiki-cho - Tachikawa Tokyo 190-0022 - JAPAN - - 00-1F-0F (hex) Select Engineered Systems - 001F0F (base 16) Select Engineered Systems - 7991 W. 26 Ave - Hialeah Florida 33016 - UNITED STATES - - 00-1F-10 (hex) TOLEDO DO BRASIL INDUSTRIA DE BALANCAS LTDA - 001F10 (base 16) TOLEDO DO BRASIL INDUSTRIA DE BALANCAS LTDA - RUA MANOEL CREMONESI, 1 - ESTRADA SAMUEL AIZEMBERG, 345 - SAO BERNARDO DO CAMPO SP 09851-900 - BRAZIL - - 00-1F-11 (hex) OPENMOKO, INC. - 001F11 (base 16) OPENMOKO, INC. - 7F, No 300, Yang Guang Street - NeiHu - Taipei 11491 - TAIWAN, PROVINCE OF CHINA - - 00-1F-12 (hex) Juniper Networks - 001F12 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-1F-13 (hex) S.& A.S. Ltd. - 001F13 (base 16) S.& A.S. Ltd. - Boutros Bldg. 1st bsmt - Ghabi Street - Beirut 2067 7808 - LEBANON - - 00-1F-14 (hex) NexG - 001F14 (base 16) NexG - 5F Seoul Academy Bldg, Daechi-Dong, Gangnam-Gu, - Seoul 135-280 - KOREA, REPUBLIC OF - - 00-1F-15 (hex) Bioscrypt Inc - 001F15 (base 16) Bioscrypt Inc - 505 Cochrane Drive - Markham Ontario L3R 8E3 - CANADA - - 00-1F-16 (hex) Wistron Corporation - 001F16 (base 16) Wistron Corporation - 21F, 88, Sec.1,Hsin Tai Wu Rd., Hsichih, - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-1F-17 (hex) IDX Company, Ltd. - 001F17 (base 16) IDX Company, Ltd. - 6-28-11 Shukugawara, Tana-ku - Kawasaki-Shi Kanagawa-Ken 2140021 - JAPAN - - 00-1F-18 (hex) Hakusan.Mfg.Co,.Ltd - 001F18 (base 16) Hakusan.Mfg.Co,.Ltd - Tomin-Kougyou-Ikebukuro BLD.5F - 2-26-5 Minami-Ikebukuro - Tosima Ward Tokyo-Met. 171-0022 - JAPAN - - 00-1F-19 (hex) BEN-RI ELECTRONICA S.A. - 001F19 (base 16) BEN-RI ELECTRONICA S.A. - POL. IND. VENTORRO DEL CANO - C/. LOZOYA 8 - ALCORCON MADRID 28925 - SPAIN - - 00-1F-1A (hex) Prominvest - 001F1A (base 16) Prominvest - 7, Bobruiskaya ulica - Saint-Petersburg North-West Federal District 195009 - RUSSIAN FEDERATION - - 00-1F-1B (hex) RoyalTek Company Ltd. - 001F1B (base 16) RoyalTek Company Ltd. - Suite 9F-1, No. 1071, Chung Cheng Rd. - Taoyuan Shien Taoyuan 330 - TAIWAN, PROVINCE OF CHINA - - 00-1F-1C (hex) KOBISHI ELECTRIC Co.,Ltd. - 001F1C (base 16) KOBISHI ELECTRIC Co.,Ltd. - 1805-1 - Kamiya - Kounosu-shi Saitama-ken 365-0027 - JAPAN - - 00-1F-1D (hex) Atlas Material Testing Technology LLC - 001F1D (base 16) Atlas Material Testing Technology LLC - 4114 N. Ravenswood Ave. - Chicago IL 60613 - UNITED STATES - - 00-1F-1E (hex) Astec Technology Co., Ltd - 001F1E (base 16) Astec Technology Co., Ltd - 12F, No.2, Jian Ba Rd. - Chung Ho Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-1F-1F (hex) Edimax Technology Co. Ltd. - 001F1F (base 16) Edimax Technology Co. Ltd. - No. 3, Wu-Chuan 3rd Road, Wu-Ku Industrial Park, - Taipei Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 00-1F-20 (hex) Logitech Europe SA - 001F20 (base 16) Logitech Europe SA - EPFL - Quartier de l'Innovation - Daniel Borel Innovation Center - Lausanne CH 1015 - SWITZERLAND - - 00-1F-21 (hex) Inner Mongolia Yin An Science & Technology Development Co.,L - 001F21 (base 16) Inner Mongolia Yin An Science & Technology Development Co.,L - YinAn Building Yiwei Road.RuYi - Development Zone,Hohhot - Beijing 010010 - CHINA - - 00-1F-22 (hex) Source Photonics, Inc. - 001F22 (base 16) Source Photonics, Inc. - 20550 Nordhoff Street - Chatsworth CA 91311 - UNITED STATES - - 00-1F-23 (hex) Interacoustics - 001F23 (base 16) Interacoustics - Drejervaenget 8 - Assens DK 5610 - DENMARK - - 00-1F-24 (hex) DIGITVIEW TECHNOLOGY CO., LTD. - 001F24 (base 16) DIGITVIEW TECHNOLOGY CO., LTD. - NO. 14-22, TIAN-FU , - SANSIA TOWNSHIP, - TAIPEI COUNTY 237 - TAIWAN, PROVINCE OF CHINA - - 00-1F-25 (hex) MBS GmbH - 001F25 (base 16) MBS GmbH - Römerstraße 15 - Krefeld Nordrhein-Westfalen 47809 - GERMANY - - 00-1F-26 (hex) CISCO SYSTEMS, INC. - 001F26 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-27 (hex) CISCO SYSTEMS, INC. - 001F27 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-28 (hex) HPN Supply Chain - 001F28 (base 16) HPN Supply Chain - 8000 Foothills Blvd - Roseville CA 95747 - UNITED STATES - - 00-1F-29 (hex) Hewlett-Packard Company - 001F29 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040802 - Houston TX 77070 - UNITED STATES - - 00-1F-2A (hex) ACCM - 001F2A (base 16) ACCM - Obour Industrial City, Industrial zone A, lot14, block 12006. - Cairo - EGYPT - - 00-1F-2B (hex) Orange Logic - 001F2B (base 16) Orange Logic - #706 AceTechnoTower 10-cha,470-5 - Gasan-dong Geumcheon-gu - SEOUL 153-789 - KOREA, REPUBLIC OF - - 00-1F-2C (hex) Starbridge Networks - 001F2C (base 16) Starbridge Networks - 3265 Meridian Parkway - Suite 134 - Weston FL 33331 - UNITED STATES - - 00-1F-2D (hex) Electro-Optical Imaging, Inc. - 001F2D (base 16) Electro-Optical Imaging, Inc. - 4300 Fortune Place, Suite C - West Melbourne FL 32904 - UNITED STATES - - 00-1F-2E (hex) Triangle Research Int'l Pte Ltd - 001F2E (base 16) Triangle Research Int'l Pte Ltd - 10 Ubi Crescent #05-83 - Ubi Techpark SG 408664 - SINGAPORE - - 00-1F-2F (hex) Berker GmbH & Co. KG - 001F2F (base 16) Berker GmbH & Co. KG - Klagebach 38 - Schalksmuehle NRW 58579 - GERMANY - - 00-1F-30 (hex) Travelping - 001F30 (base 16) Travelping - - Leipziger Str. 46 - Chemnitz Saxony 09113 - GERMANY - - 00-1F-31 (hex) Radiocomp - 001F31 (base 16) Radiocomp - Krakesvej 17 - Hilleroed Copenhagen 3400 - DENMARK - - 00-1F-32 (hex) Nintendo Co., Ltd. - 001F32 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1F-33 (hex) Netgear Inc. - 001F33 (base 16) Netgear Inc. - 4500 Great America Pkwy - Santa Clara CA 95054 - UNITED STATES - - 00-1F-34 (hex) Lung Hwa Electronics Co., Ltd. - 001F34 (base 16) Lung Hwa Electronics Co., Ltd. - 3F, 248, Pei Sheng Rd. Sec. 3, - Sheng Keng - Taipei Hsien 222 - TAIWAN, PROVINCE OF CHINA - - 00-1F-35 (hex) AIR802 LLC - 001F35 (base 16) AIR802 LLC - 1169 Banyon Court - Naperville IL 60540 - UNITED STATES - - 00-1F-36 (hex) Bellwin Information Co. Ltd., - 001F36 (base 16) Bellwin Information Co. Ltd., - No.336, Beitun Rd., Beitun Dist., - Taichung 406 - TAIWAN, PROVINCE OF CHINA - - 00-1F-37 (hex) Genesis I&C - 001F37 (base 16) Genesis I&C - #515 lisantekeunotaun - 1141-1 Baekseok-Dong, lisandong-Gu - Goyang Gyeonggi 410-722 - KOREA, REPUBLIC OF - - 00-1F-38 (hex) POSITRON - 001F38 (base 16) POSITRON - ESTRADA TELEBRAS-UNICAMP, KM0,97 - CJ.01 - BAIRRO: CIDADE UNIVERSITARIA - CAMPINAS São Paulo 13084-971 - BRAZIL - - 00-1F-39 (hex) Construcciones y Auxiliar de Ferrocarriles, S.A. - 001F39 (base 16) Construcciones y Auxiliar de Ferrocarriles, S.A. - C/ J.M. Iturrioz, 26 - Beasain Guipúzcoa E-20200 - SPAIN - - 00-1F-3A (hex) Hon Hai Precision Ind.Co., Ltd. - 001F3A (base 16) Hon Hai Precision Ind.Co., Ltd. - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-1F-3B (hex) Intel Corporate - 001F3B (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1F-3C (hex) Intel Corporate - 001F3C (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-1F-3D (hex) Qbit GmbH - 001F3D (base 16) Qbit GmbH - Stegwiesenstrasse 32 - Bruchsal Germany 76646 - GERMANY - - 00-1F-3E (hex) RP-Technik e.K. - 001F3E (base 16) RP-Technik e.K. - Hermann-Staudinger-Str. 10-16 - Rodgau Hessen 63110 - GERMANY - - 00-1F-3F (hex) AVM GmbH - 001F3F (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 00-1F-40 (hex) Speakercraft Inc. - 001F40 (base 16) Speakercraft Inc. - 940 Columbia Ave., - Riverside CA 92507 - UNITED STATES - - 00-1F-41 (hex) Ruckus Wireless - 001F41 (base 16) Ruckus Wireless - 880 West Maude Ave. - Sunnyvale CA 94085 - UNITED STATES - - 00-1F-42 (hex) Etherstack plc - 001F42 (base 16) Etherstack plc - 80 Abercrombie Street - Chippendale NSW 2008 - AUSTRALIA - - 00-1F-43 (hex) ENTES ELEKTRONIK - 001F43 (base 16) ENTES ELEKTRONIK - Y. Dudullu Org. San. Bol. And Sanayi Sit. No.6 - Umraniye - Istanbul Dudullu 34775 - TURKEY - - 00-1F-44 (hex) GE Transportation Systems - 001F44 (base 16) GE Transportation Systems - 2901 East Lake Road - Erie PA 16501 - UNITED STATES - - 00-1F-45 (hex) Enterasys - 001F45 (base 16) Enterasys - 50 Minuteman Road - Andover MA 01810 - UNITED STATES - - 00-1F-46 (hex) Nortel - 001F46 (base 16) Nortel - 2221 Lakeside Blvd - Richardson Texas 75082 - UNITED STATES - - 00-1F-47 (hex) MCS Logic Inc. - 001F47 (base 16) MCS Logic Inc. - 6F. Samho Center B Bldg., 275-6 - Yangjae-Dong, Secho-Ku - Seoul 137-941 - KOREA, REPUBLIC OF - - 00-1F-48 (hex) Mojix Inc. - 001F48 (base 16) Mojix Inc. - 11075 Santa Monica Blvd. - Suite 350 - Los Angeles Ca 90025 - UNITED STATES - - 00-1F-49 (hex) Manhattan Technology Limited - 001F49 (base 16) Manhattan Technology Limited - 3 Phoenix Park, - Apsley Way - London NW2 7LN - UNITED KINGDOM - - 00-1F-4A (hex) Albentia Systems S.A. - 001F4A (base 16) Albentia Systems S.A. - Albala 13 - Madrid 28037 - SPAIN - - 00-1F-4B (hex) Lineage Power - 001F4B (base 16) Lineage Power - 3000 Skyline Dr. - Mesquite TX 75149 - UNITED STATES - - 00-1F-4C (hex) Roseman Engineering Ltd - 001F4C (base 16) Roseman Engineering Ltd - 65 Weizman Street - Givataim Israel 53468 - ISRAEL - - 00-1F-4D (hex) Segnetics LLC - 001F4D (base 16) Segnetics LLC - Shkiperski protok 14 - Saint-Petersburg 199106 - RUSSIAN FEDERATION - - 00-1F-4E (hex) ConMed Linvatec - 001F4E (base 16) ConMed Linvatec - 11311 Concept Blvd. - Largo FL 33773 - UNITED STATES - - 00-1F-4F (hex) Thinkware Co. Ltd. - 001F4F (base 16) Thinkware Co. Ltd. - 15FL, Hanmi Tower, 45, - Bangi-Dong, Songpa-gu - Seoul 138-724 - KOREA, REPUBLIC OF - - 00-1F-50 (hex) Swissdis AG - 001F50 (base 16) Swissdis AG - Grasweg 7 - Schwarzhaeusern BE 4911 - SWITZERLAND - - 00-1F-51 (hex) HD Communications Corp - 001F51 (base 16) HD Communications Corp - 2180 Fifth Ave - Ronkonkoma NY 11779 - UNITED STATES - - 00-1F-52 (hex) UVT Unternehmensberatung fur Verkehr und Technik GmbH - 001F52 (base 16) UVT Unternehmensberatung fur Verkehr und Technik GmbH - Josefsstraße 54-56 - Mainz RLP 55118 - GERMANY - - 00-1F-53 (hex) GEMAC Gesellschaft für Mikroelektronikanwendung Chemnitz mbH - 001F53 (base 16) GEMAC Gesellschaft für Mikroelektronikanwendung Chemnitz mbH - Zwickauer Straße 227 - Chemnitz Sachsen 09116 - GERMANY - - 00-1F-54 (hex) Lorex Technology Inc. - 001F54 (base 16) Lorex Technology Inc. - 250 Royal Crest Court - Markham Ontario L3R3S1 - CANADA - - 00-1F-55 (hex) Honeywell Security (China) Co., Ltd. - 001F55 (base 16) Honeywell Security (China) Co., Ltd. - Block 28, Section 2, Huai De Cui Gang Industrial Estate, Fu Yong, Bao An, ShenZhen, P.R. China - ShenZhen GuangDong 518103 - CHINA - - 00-1F-56 (hex) DIGITAL FORECAST - 001F56 (base 16) DIGITAL FORECAST - 5th Fl., 507, E&C Venture Dream Tower III, 197-33 - Guro 3-dong, Guro-gu - Seoul Gyunggi-do 152-719 - KOREA, REPUBLIC OF - - 00-1F-57 (hex) Phonik Innovation Co.,LTD - 001F57 (base 16) Phonik Innovation Co.,LTD - 29/167 Moo2, 345 Rd, Lampo, - Bangbuathong - Nonthaburi 11110 - THAILAND - - 00-1F-58 (hex) EMH Energiemesstechnik GmbH - 001F58 (base 16) EMH Energiemesstechnik GmbH - Vor dem Hassel 2 - Brackel 21438 - GERMANY - - 00-1F-59 (hex) Kronback Tracers - 001F59 (base 16) Kronback Tracers - c/o DTU, R254 - Lautrupvang 15 - Ballerup Copenhagen 2750 - DENMARK - - 00-1F-5A (hex) Beckwith Electric Co. - 001F5A (base 16) Beckwith Electric Co. - 6190 118th Ave No - Largo Florida 33773 - UNITED STATES - - 00-1F-5B (hex) Apple - 001F5B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-1F-5C (hex) Nokia Danmark A/S - 001F5C (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1F-5D (hex) Nokia Danmark A/S - 001F5D (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1F-5E (hex) Dyna Technology Co.,Ltd. - 001F5E (base 16) Dyna Technology Co.,Ltd. - HaoHai Building 1F,No.7,5th Street,Shangdi, - Haidian District - Beijing 100085 - CHINA - - 00-1F-5F (hex) Blatand GmbH - 001F5F (base 16) Blatand GmbH - Lichtenbergstraße 8 - Garching Bavaria 85748 - GERMANY - - 00-1F-60 (hex) COMPASS SYSTEMS CORP. - 001F60 (base 16) COMPASS SYSTEMS CORP. - 6F, No. 413, Sec. 2, Ti-Ding Blvd., - Taipei NeihuDist 114 - TAIWAN, PROVINCE OF CHINA - - 00-1F-61 (hex) Talent Communication Networks Inc. - 001F61 (base 16) Talent Communication Networks Inc. - Rm. 910 R&F Plaza, #76, Huangpu Ave. West, - Guangzhou (Canton) Guangdong Province 510360 - CHINA - - 00-1F-62 (hex) JSC "Stilsoft" - 001F62 (base 16) JSC "Stilsoft" - Mayakovskogo 15 - Stavropol 355000 - RUSSIAN FEDERATION - - 00-1F-63 (hex) JSC Goodwin-Europa - 001F63 (base 16) JSC Goodwin-Europa - 20/5 Marksistskaya st. - Moscow 109147 - RUSSIAN FEDERATION - - 00-1F-64 (hex) Beijing Autelan Technology Inc. - 001F64 (base 16) Beijing Autelan Technology Inc. - Room B-12B01, Keshi Plaza, Xinxi road, - Shangdi park,Haidian, - Beijing 100085 - CHINA - - 00-1F-65 (hex) KOREA ELECTRIC TERMINAL CO., LTD. - 001F65 (base 16) KOREA ELECTRIC TERMINAL CO., LTD. - #7-38 SONGDO-DONG - YEONSU-GU INCHEON 406-840 - KOREA, REPUBLIC OF - - 00-1F-66 (hex) PLANAR LLC - 001F66 (base 16) PLANAR LLC - 32, Elkina str - Chelyabinsk SU 454091 - RUSSIAN FEDERATION - - 00-1F-67 (hex) Hitachi,Ltd. - 001F67 (base 16) Hitachi,Ltd. - Minamioi 6-27-18, Shinagawa-ku - Tokyo 140-8572 - JAPAN - - 00-1F-68 (hex) Martinsson Elektronik AB - 001F68 (base 16) Martinsson Elektronik AB - Box 9060 - Hägersten Stockholm 126 09 - SWEDEN - - 00-1F-69 (hex) Pingood Technology Co., Ltd. - 001F69 (base 16) Pingood Technology Co., Ltd. - Rm1917, South Block, Cangsong Bldg., Tairan Industrial Zone, Futian District - Shenzhen Guangdong 518040 - CHINA - - 00-1F-6A (hex) PacketFlux Technologies, Inc. - 001F6A (base 16) PacketFlux Technologies, Inc. - 50 11th Avenue - Helena MT 59601 - UNITED STATES - - 00-1F-6B (hex) LG Electronics - 001F6B (base 16) LG Electronics - 60-39,Kasan-dong,Kumchon-ku - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-1F-6C (hex) CISCO SYSTEMS, INC. - 001F6C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-6D (hex) CISCO SYSTEMS, INC. - 001F6D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-6E (hex) Vtech Engineering Corporation - 001F6E (base 16) Vtech Engineering Corporation - 20 New England Business Center - Andover MA 01810 - UNITED STATES - - 00-1F-6F (hex) Fujian Sunnada Communication Co.,Ltd. - 001F6F (base 16) Fujian Sunnada Communication Co.,Ltd. - 7/F Main Building,Fujian Torch Hi-Tech Innovation Park No.611 Industrial Road,Fuzhou Fuzhou Fujian China 350002 - 7# Building B District, Software Park, TongPan Road Fuzhou, PRC 350003 - Fuzhou Fujian 350002 - CHINA - - 00-1F-70 (hex) Botik Technologies LTD - 001F70 (base 16) Botik Technologies LTD - Trudovaya, 1 - Pereslavl-Zalessky Yaroslavskaya 152020 - RUSSIAN FEDERATION - - 00-1F-71 (hex) xG Technology, Inc. - 001F71 (base 16) xG Technology, Inc. - 240 S. Pineapple Avenue - Suite 701 - Sarasota FL 34236 - UNITED STATES - - 00-1F-72 (hex) QingDao Hiphone Technology Co,.Ltd - 001F72 (base 16) QingDao Hiphone Technology Co,.Ltd - NO.106,JiangXi Road - QingDao ShanDong 266071 - CHINA - - 00-1F-73 (hex) Teraview Technology Co., Ltd. - 001F73 (base 16) Teraview Technology Co., Ltd. - 23F, No. 29-5, Sec. 2, Jhongjheng E. Road, - Danshui Township, - Taipei County 251 - TAIWAN, PROVINCE OF CHINA - - 00-1F-74 (hex) Eigen Development - 001F74 (base 16) Eigen Development - 1807 W10th Ave - Vancouver BC V6J 2A9 - CANADA - - 00-1F-75 (hex) GiBahn Media - 001F75 (base 16) GiBahn Media - 1816 Rosedale Suseo-dong - Kangnam-gu - Seoul 135-885 - KOREA, REPUBLIC OF - - 00-1F-76 (hex) AirLogic Systems Inc. - 001F76 (base 16) AirLogic Systems Inc. - 3022 Peleke St.Suite 1 - Lihu'e HI 96766 - UNITED STATES - - 00-1F-77 (hex) HEOL DESIGN - 001F77 (base 16) HEOL DESIGN - 1 bd d'armor - LANNION BRETAGNE 22300 - FRANCE - - 00-1F-78 (hex) Blue Fox Porini Textile - 001F78 (base 16) Blue Fox Porini Textile - 1208 Pointe Centre Drive - STE 200 - Chattanooga TN 37421 - UNITED STATES - - 00-1F-79 (hex) Lodam Electronics A/S - 001F79 (base 16) Lodam Electronics A/S - Kærvej 77 - Sønderborg Als DK-6400 - DENMARK - - 00-1F-7A (hex) WiWide Inc. - 001F7A (base 16) WiWide Inc. - 10B10, Hua Jie Plaza - #13 Da Zhong Si, Haidian - Beijing 100089 - CHINA - - 00-1F-7B (hex) TechNexion Ltd. - 001F7B (base 16) TechNexion Ltd. - 17F-1, No. 16, Jian Ba Road, - Chung Ho Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-1F-7C (hex) Witelcom AS - 001F7C (base 16) Witelcom AS - Verftsgt 10 - Moss Ostfold 1511 - NORWAY - - 00-1F-7D (hex) embedded wireless GmbH - 001F7D (base 16) embedded wireless GmbH - Söflinger Straße 100 - Ulm BW 89077 - GERMANY - - 00-1F-7E (hex) ARRIS Group, Inc. - 001F7E (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1F-7F (hex) Phabrix Limited - 001F7F (base 16) Phabrix Limited - Blindmans Gate Cottage - Woolton Hill - Newbury Hampshire RG20 9XB - UNITED KINGDOM - - 00-1F-80 (hex) Lucas Holding bv - 001F80 (base 16) Lucas Holding bv - Domein 28 - Gemert NB 5421AR - NETHERLANDS - - 00-1F-81 (hex) Accel Semiconductor Corp - 001F81 (base 16) Accel Semiconductor Corp - 1F,Mainbldg,149 Chun Xiao Road, - Shanghai 201203 - CHINA - - 00-1F-82 (hex) Cal-Comp Electronics & Communications Co., Ltd - 001F82 (base 16) Cal-Comp Electronics & Communications Co., Ltd - 3F, #205, Sec.3 Peihsin Rd. - Hsintein Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 00-1F-83 (hex) Teleplan Technology Services Sdn Bhd - 001F83 (base 16) Teleplan Technology Services Sdn Bhd - 2580, Tingkat Perusahaan 4B - Zon Perdagangan Bebas Dua - Perai Penang 13600 - MALAYSIA - - 00-1F-84 (hex) Gigle Semiconductor - 001F84 (base 16) Gigle Semiconductor - Barcelona Activa - Vivero Glorias - Llacuna 162 - Barcelona 08018 - SPAIN - - 00-1F-85 (hex) Apriva ISS, LLC - 001F85 (base 16) Apriva ISS, LLC - 6900 E Camelback Rd - Suite 700 - Scottsdale AZ 85251 - UNITED STATES - - 00-1F-86 (hex) digEcor - 001F86 (base 16) digEcor - 1625 N. 1100 W. - Springville UT 84663 - UNITED STATES - - 00-1F-87 (hex) Skydigital Inc. - 001F87 (base 16) Skydigital Inc. - #28-9 Wonhyoro1-ga, Yongsan-gu, - Seoul 140-846 - KOREA, REPUBLIC OF - - 00-1F-88 (hex) FMS Force Measuring Systems AG - 001F88 (base 16) FMS Force Measuring Systems AG - Aspstrasse 6 - Oberglatt Zurich 8154 - SWITZERLAND - - 00-1F-89 (hex) Signalion GmbH - 001F89 (base 16) Signalion GmbH - Sudhausweg 5 - Dresden Saxony 01099 - GERMANY - - 00-1F-8A (hex) Ellion Digital Inc. - 001F8A (base 16) Ellion Digital Inc. - Suite 809, Sicox Tower, 513-14, Sangdaewon-dong, Jungwon-gu - Sungnam-city Kyonggi-do 426-726 - KOREA, REPUBLIC OF - - 00-1F-8B (hex) Cache IQ - 001F8B (base 16) Cache IQ - 8834 North Capital of Texas Hwy - Austin Texas 78759 - UNITED STATES - - 00-1F-8C (hex) CCS Inc. - 001F8C (base 16) CCS Inc. - Shimodachiuri-agaru - Karasuma-dori, Kamigyo-ku - Kyoto Kyoto 602-8011 - JAPAN - - 00-1F-8D (hex) Ingenieurbuero Stark GmbH und Ko. KG - 001F8D (base 16) Ingenieurbuero Stark GmbH und Ko. KG - Rudolf-Diesel-Strasse 44 - Laichingen BW 89150 - GERMANY - - 00-1F-8E (hex) Metris USA Inc. - 001F8E (base 16) Metris USA Inc. - 12701 Grand River - Brighton MI 48116 - UNITED STATES - - 00-1F-8F (hex) Shanghai Bellmann Digital Source Co.,Ltd. - 001F8F (base 16) Shanghai Bellmann Digital Source Co.,Ltd. - 404-408 Main Bd, FDUSP, No.11 Guotai Rd. - Shanghai 200433 - CHINA - - 00-1F-90 (hex) Actiontec Electronics, Inc - 001F90 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-1F-91 (hex) DBS Lodging Technologies, LLC - 001F91 (base 16) DBS Lodging Technologies, LLC - 21196 Limber - Mission Viejo CA 92692 - UNITED STATES - - 00-1F-92 (hex) VideoIQ, Inc. - 001F92 (base 16) VideoIQ, Inc. - 213 Burlington Road - Suite 104 - Bedford MA 01730 - UNITED STATES - - 00-1F-93 (hex) Xiotech Corporation - 001F93 (base 16) Xiotech Corporation - 6455 Flying Cloud Drive - Eden Prairie MN 55344 - UNITED STATES - - 00-1F-94 (hex) Lascar Electronics Ltd - 001F94 (base 16) Lascar Electronics Ltd - Module House - Whiteparish - Nr Salisbury Wiltshire SP5 2SJ - UNITED KINGDOM - - 00-1F-95 (hex) SAGEM COMMUNICATION - 001F95 (base 16) SAGEM COMMUNICATION - 14 Rue Paul Dautier - Velizy 78457 - FRANCE - - 00-1F-96 (hex) APROTECH CO.LTD - 001F96 (base 16) APROTECH CO.LTD - KOLONDIGITAL TOWER ASTON 201, 505-14 - GASAN-DONG,KUMCHON-GU - SEOUL KSXX 0022 - KOREA, REPUBLIC OF - - 00-1F-97 (hex) BERTANA SRL - 001F97 (base 16) BERTANA SRL - VIALE GALILEO FERRARIS 27 - BRUINO TORINO 10090 - ITALY - - 00-1F-98 (hex) DAIICHI-DENTSU LTD. - 001F98 (base 16) DAIICHI-DENTSU LTD. - OOMORI 690-1 - KANI GIFU 509-0238 - JAPAN - - 00-1F-99 (hex) SERONICS co.ltd - 001F99 (base 16) SERONICS co.ltd - #401 Technopolis, - 711Hosan-dong, Dalseo-gu - Daegu Gyeong-buk 704-230 - KOREA, REPUBLIC OF - - 00-1F-9A (hex) Nortel Networks - 001F9A (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson TX 75082-4399 - UNITED STATES - - 00-1F-9B (hex) POSBRO - 001F9B (base 16) POSBRO - ShinyoungGtower 6F, 271-1 - Seohyun-dong, Bundang-gu - Seongnam-si Kyunggi-do 463-824 - KOREA, REPUBLIC OF - - 00-1F-9C (hex) LEDCO - 001F9C (base 16) LEDCO - 47801 W Anchor Court - Plymouth MI 48170 - UNITED STATES - - 00-1F-9D (hex) CISCO SYSTEMS, INC. - 001F9D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-9E (hex) CISCO SYSTEMS, INC. - 001F9E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-9F (hex) Thomson Telecom Belgium - 001F9F (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - Edegem Antwerp B-2650 - BELGIUM - - 00-1F-A0 (hex) A10 Networks - 001FA0 (base 16) A10 Networks - 3 West Plumeria Drive - San Jose CA 95134 - UNITED STATES - - 00-1F-A1 (hex) Gtran Inc - 001FA1 (base 16) Gtran Inc - 2651 Lavery Court - Newbury Park CA 91320 - UNITED STATES - - 00-1F-A2 (hex) Datron World Communications, Inc. - 001FA2 (base 16) Datron World Communications, Inc. - 3030 Enterprise Court - Vista California 92081 - UNITED STATES - - 00-1F-A3 (hex) T&W Electronics(Shenzhen)Co.,Ltd. - 001FA3 (base 16) T&W Electronics(Shenzhen)Co.,Ltd. - 2F,Baiying Building, No.1019, - ShenZhen GuangDong 518067 - CHINA - - 00-1F-A4 (hex) ShenZhen Gongjin Electronics Co.,Ltd - 001FA4 (base 16) ShenZhen Gongjin Electronics Co.,Ltd - 4F,Baiying Building, No.1019,Nanhai RD,Shekou, - ShenZhen GuangDong 518067 - CHINA - - 00-1F-A5 (hex) Blue-White Industries - 001FA5 (base 16) Blue-White Industries - 5300 Business Drive - Huntington Beach CA 92649 - UNITED STATES - - 00-1F-A6 (hex) Stilo srl - 001FA6 (base 16) Stilo srl - Via Besana, 4 - 20122 Milano - ITALY - - 00-1F-A7 (hex) Sony Computer Entertainment Inc. - 001FA7 (base 16) Sony Computer Entertainment Inc. - 2-6-21 Minami-Aoyama, - Minato-ku Tokyo 107-0062 - JAPAN - - 00-1F-A8 (hex) Smart Energy Instruments Inc. - 001FA8 (base 16) Smart Energy Instruments Inc. - 297 Lakeshore Road East - Unit 1 - Oakville Ontario L6J 1J3 - CANADA - - 00-1F-A9 (hex) Atlanta DTH, Inc. - 001FA9 (base 16) Atlanta DTH, Inc. - 5388 New Peachtree Rd - Chamblee GA 30341 - UNITED STATES - - 00-1F-AA (hex) Taseon, Inc. - 001FAA (base 16) Taseon, Inc. - 3099 N. First Street - San Jose CA 95134 - UNITED STATES - - 00-1F-AB (hex) I.S HIGH TECH.INC - 001FAB (base 16) I.S HIGH TECH.INC - 603-1,Sungbon-ri,Daeso-myun - Eumsung-gun Chungcheongbuk-do 369-823 - KOREA, REPUBLIC OF - - 00-1F-AC (hex) Goodmill Systems Ltd - 001FAC (base 16) Goodmill Systems Ltd - Sinikalliontie 10 - Espoo Uusimaa 02630 - FINLAND - - 00-1F-AD (hex) Brown Innovations, Inc - 001FAD (base 16) Brown Innovations, Inc - 369 Congress Street - Fourth Floor - Boston MA 02210 - UNITED STATES - - 00-1F-AE (hex) Blick South Africa (Pty) Ltd - 001FAE (base 16) Blick South Africa (Pty) Ltd - PO Box 1908 - Rivonia - Johannesburg Gauteng 2108 - SOUTH AFRICA - - 00-1F-AF (hex) NextIO, Inc. - 001FAF (base 16) NextIO, Inc. - 8303 N MoPac Expressway - Suite A-210 - Austin TX 78759 - UNITED STATES - - 00-1F-B0 (hex) TimeIPS, Inc. - 001FB0 (base 16) TimeIPS, Inc. - 3522 N Comotara St - Wichita KS 67226 - UNITED STATES - - 00-1F-B1 (hex) Cybertech Inc. - 001FB1 (base 16) Cybertech Inc. - 935 Horsham Rd - Unit I - Horsham PA 19044 - UNITED STATES - - 00-1F-B2 (hex) Sontheim Industrie Elektronik GmbH - 001FB2 (base 16) Sontheim Industrie Elektronik GmbH - Dieselstrasse 7 - Kempten Allgaeu Bavaria D-87437 - GERMANY - - 00-1F-B3 (hex) 2Wire - 001FB3 (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-1F-B4 (hex) SmartShare Systems - 001FB4 (base 16) SmartShare Systems - Tonsbakken 16-18 - Skovlunde DK-2740 - DENMARK - - 00-1F-B5 (hex) I/O Interconnect Inc. - 001FB5 (base 16) I/O Interconnect Inc. - 1202 E Wakeham Ave - Santa Ana CA 92708 - UNITED STATES - - 00-1F-B6 (hex) Chi Lin Technology Co., Ltd. - 001FB6 (base 16) Chi Lin Technology Co., Ltd. - No.18, Sheng Li 1st St., Jen Te Hsiang, - Tainan Taiwan 71758 - CHINA - - 00-1F-B7 (hex) WiMate Technologies Corp. - 001FB7 (base 16) WiMate Technologies Corp. - 14A Building 2, Guimiao Garden, Nanguanglu, Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 00-1F-B8 (hex) Universal Remote Control, Inc. - 001FB8 (base 16) Universal Remote Control, Inc. - 500 Mamaroneck Avenue - Suite 502 - Harrison NY 10528 - UNITED STATES - - 00-1F-B9 (hex) Paltronics - 001FB9 (base 16) Paltronics - 1145 Paltronics Ct - Crystal Lake IL 60014 - UNITED STATES - - 00-1F-BA (hex) BoYoung Tech. & Marketing, Inc. - 001FBA (base 16) BoYoung Tech. & Marketing, Inc. - Youngdeungpo-Gu Munrae3ga 84-2 - Dongguk Mertian 602 - Seoul 150-093 - KOREA, REPUBLIC OF - - 00-1F-BB (hex) Xenatech Co.,LTD - 001FBB (base 16) Xenatech Co.,LTD - 514-2 Ya Tab-Dong Bun Dang Gu - Seong namsi Gyong gi-do 463-839 - KOREA, REPUBLIC OF - - 00-1F-BC (hex) EVGA Corporation - 001FBC (base 16) EVGA Corporation - 2900 Saturn St. - Suite B - Brea CA 92821 - UNITED STATES - - 00-1F-BD (hex) Kyocera Wireless Corp. - 001FBD (base 16) Kyocera Wireless Corp. - 10300 Campus Point Drive - San Diego CA 92121 - UNITED STATES - - 00-1F-BE (hex) Shenzhen Mopnet Industrial Co.,Ltd - 001FBE (base 16) Shenzhen Mopnet Industrial Co.,Ltd - F 3.No.3 Keyuan Rd. - Shenzhen Nanshan Science&Industry Park - Shenzhen Guangdong 518057 - CHINA - - 00-1F-BF (hex) Fulhua Microelectronics Corp. Taiwan Branch - 001FBF (base 16) Fulhua Microelectronics Corp. Taiwan Branch - 1F, No.12, R&D Road, - Science-based Ind. Park, - Hsin-Chu, 300 886 - TAIWAN, PROVINCE OF CHINA - - 00-1F-C0 (hex) Control Express Finland Oy - 001FC0 (base 16) Control Express Finland Oy - Laitaatsillantie 3 - Savonlinna 57170 - FINLAND - - 00-1F-C1 (hex) Hanlong Technology Co.,LTD - 001FC1 (base 16) Hanlong Technology Co.,LTD - 2402 West Tower Building, Fuxin International Building, - 359 Hongwu Road, Baixia District,Nanjing, Jiangsu, China - Nanjing Jiangsu 210002 - CHINA - - 00-1F-C2 (hex) Jow Tong Technology Co Ltd - 001FC2 (base 16) Jow Tong Technology Co Ltd - 46 Lane 337 Chung Cheng Rd - Yung Kang City Tainan County 71066 - TAIWAN, PROVINCE OF CHINA - - 00-1F-C3 (hex) SmartSynch, Inc - 001FC3 (base 16) SmartSynch, Inc - 4400 Old Canton Rd - Suite 300 - Jackson MS 39211 - UNITED STATES - - 00-1F-C4 (hex) ARRIS Group, Inc. - 001FC4 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-1F-C5 (hex) Nintendo Co., Ltd. - 001FC5 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-1F-C6 (hex) ASUSTek COMPUTER INC. - 001FC6 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou,Taipei 112 - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-1F-C7 (hex) Casio Hitachi Mobile Comunications Co., Ltd. - 001FC7 (base 16) Casio Hitachi Mobile Comunications Co., Ltd. - 2-229-1, Sakuragaoka - Higashiyamato-shi Tokyo 207-8501 - JAPAN - - 00-1F-C8 (hex) Up-Today Industrial Co., Ltd. - 001FC8 (base 16) Up-Today Industrial Co., Ltd. - 7/F., Unify Commercial & Industrial Building - 31 Tai Yip Street, Kwun Tong, - Kowloon - HONG KONG - - 00-1F-C9 (hex) CISCO SYSTEMS, INC. - 001FC9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-CA (hex) CISCO SYSTEMS, INC. - 001FCA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-1F-CB (hex) NIW Solutions - 001FCB (base 16) NIW Solutions - P.O. Box 62 - One Tree Hill South Australia 5114 - AUSTRALIA - - 00-1F-CC (hex) Samsung Electronics Co.,Ltd - 001FCC (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1F-CD (hex) Samsung Electronics - 001FCD (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-1F-CE (hex) QTECH LLC - 001FCE (base 16) QTECH LLC - Novozavodskaya st. 18 build. 1 - Moscow Moscow region 121309 - RUSSIAN FEDERATION - - 00-1F-CF (hex) MSI Technology GmbH - 001FCF (base 16) MSI Technology GmbH - Hanauer Landstraße 328-330 - Frankfurt am Main Hessen 60314 - GERMANY - - 00-1F-D0 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 001FD0 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - No.215,Nan-Ping Road, - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 00-1F-D1 (hex) OPTEX CO.,LTD. - 001FD1 (base 16) OPTEX CO.,LTD. - 5-8-12 - Ogoto - Otsu Shiga 520-0101 - JAPAN - - 00-1F-D2 (hex) COMMTECH TECHNOLOGY MACAO COMMERCIAL OFFSHORE LTD. - 001FD2 (base 16) COMMTECH TECHNOLOGY MACAO COMMERCIAL OFFSHORE LTD. - 31,TAI YIP STREET, 7/F KWUN TONG, - KOWLOON, HONGKONG - CHINA - - 00-1F-D3 (hex) RIVA Networks Inc. - 001FD3 (base 16) RIVA Networks Inc. - 555 Riva Ave - East Brunswick NJ 08816 - UNITED STATES - - 00-1F-D4 (hex) 4IPNET, INC. - 001FD4 (base 16) 4IPNET, INC. - 38129 CAMBRIDGE COURT - FREMONT CA 94536 - UNITED STATES - - 00-1F-D5 (hex) MICRORISC s.r.o. - 001FD5 (base 16) MICRORISC s.r.o. - Delnicka 222 - Jicin kralovehradecky kraj 50601 - CZECH REPUBLIC - - 00-1F-D6 (hex) Shenzhen Allywll - 001FD6 (base 16) Shenzhen Allywll - Kejiyuan Nanshan - Shenzhen Guangdong 518057 - CHINA - - 00-1F-D7 (hex) TELERAD SA - 001FD7 (base 16) TELERAD SA - 2, avenue de la butte aux cailles - ANGLET 64600 - FRANCE - - 00-1F-D8 (hex) A-TRUST COMPUTER CORPORATION - 001FD8 (base 16) A-TRUST COMPUTER CORPORATION - 3F., NO.361, FUSING 1ST RD., GUEISHAN TOWNSHIP, - TAOYUAN 33375 - TAIWAN, PROVINCE OF CHINA - - 00-1F-D9 (hex) RSD Communications Ltd - 001FD9 (base 16) RSD Communications Ltd - 8 Borrowmeadow Road - Springkerse Industrial Estate - Stirling Scotland FK7 7UW - UNITED KINGDOM - - 00-1F-DA (hex) Nortel Networks - 001FDA (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson TX 75081 - UNITED STATES - - 00-1F-DB (hex) Network Supply Corp., - 001FDB (base 16) Network Supply Corp., - 1938 NAKADAIRA KANAE - IIDA NAGANO 395-0801 - JAPAN - - 00-1F-DC (hex) Mobile Safe Track Ltd - 001FDC (base 16) Mobile Safe Track Ltd - Niemenkatu 73 - 15149 Lahti - FINLAND - - 00-1F-DD (hex) GDI LLC - 001FDD (base 16) GDI LLC - One MidAmerica Plaza - Suite 1010 - Oakbrook Terrace IL 60181 - UNITED STATES - - 00-1F-DE (hex) Nokia Danmark A/S - 001FDE (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1F-DF (hex) Nokia Danmark A/S - 001FDF (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-1F-E0 (hex) EdgeVelocity Corp - 001FE0 (base 16) EdgeVelocity Corp - 68 Stiles Road - Suite G - Salem NH 03079 - UNITED STATES - - 00-1F-E1 (hex) Hon Hai Precision Ind. Co., Ltd. - 001FE1 (base 16) Hon Hai Precision Ind. Co., Ltd. - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-1F-E2 (hex) Hon Hai Precision Ind. Co., Ltd. - 001FE2 (base 16) Hon Hai Precision Ind. Co., Ltd. - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-1F-E3 (hex) LG Electronics - 001FE3 (base 16) LG Electronics - 60-39,Kasan-dong,Kumchon-ku, - Seoul 153-801 - KOREA, REPUBLIC OF - - 00-1F-E4 (hex) Sony Ericsson Mobile Communications - 001FE4 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-1F-E5 (hex) In-Circuit GmbH - 001FE5 (base 16) In-Circuit GmbH - Königsbrücker Strasse 69 - Dresden 01099 - GERMANY - - 00-1F-E6 (hex) Alphion Corporation - 001FE6 (base 16) Alphion Corporation - 196 Princeton Hightstown Road - Suite 1A - Princeton Junction New Jersey 08550 - UNITED STATES - - 00-1F-E7 (hex) Simet - 001FE7 (base 16) Simet - Strada del Portone 129 - Grugliasco Torino 10095 - ITALY - - 00-1F-E8 (hex) KURUSUGAWA Electronics Industry Inc,. - 001FE8 (base 16) KURUSUGAWA Electronics Industry Inc,. - 2F, 52-5, Nogata 6chome - Nakano-Ku TOKYO 165-0027 - JAPAN - - 00-1F-E9 (hex) Printrex, Inc. - 001FE9 (base 16) Printrex, Inc. - 276 East Gish Road - San Jose CA 95112 - UNITED STATES - - 00-1F-EA (hex) Applied Media Technologies Corporation - 001FEA (base 16) Applied Media Technologies Corporation - 4091 AMTC Center Drive - Clearwater FL 33764 - UNITED STATES - - 00-1F-EB (hex) Trio Datacom Pty Ltd - 001FEB (base 16) Trio Datacom Pty Ltd - 41 Aster Avenue - Carrum Downs Victoria 3201 - AUSTRALIA - - 00-1F-EC (hex) Synapse Électronique - 001FEC (base 16) Synapse Électronique - 1010, 7e Avenue - Grand-Mère Québec G9T 2B8 - CANADA - - 00-1F-ED (hex) Tecan Systems Inc. - 001FED (base 16) Tecan Systems Inc. - 2450 Zanker Road - San Jose CA 95131 - UNITED STATES - - 00-1F-EE (hex) ubisys technologies GmbH - 001FEE (base 16) ubisys technologies GmbH - Am Wehrhahn 45 - Düsseldorf NRW 40211 - GERMANY - - 00-1F-EF (hex) SHINSEI INDUSTRIES CO.,LTD - 001FEF (base 16) SHINSEI INDUSTRIES CO.,LTD - 4-12-15,HORIFUNE, KITA-KU, - TOKOYO 114-0004 - JAPAN - - 00-1F-F0 (hex) Audio Partnership - 001FF0 (base 16) Audio Partnership - Gallery Court - Hankey Place - London SE1 4BB - UNITED KINGDOM - - 00-1F-F1 (hex) Paradox Hellas S.A. - 001FF1 (base 16) Paradox Hellas S.A. - 3 Korinthoy St - Metamorfosi - Athens Attiki 14451 - GREECE - - 00-1F-F2 (hex) VIA Technologies, Inc. - 001FF2 (base 16) VIA Technologies, Inc. - 1F, 531, Chung-Cheng Road - Hsin-Tien Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-1F-F3 (hex) Apple - 001FF3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-1F-F4 (hex) Power Monitors, Inc. - 001FF4 (base 16) Power Monitors, Inc. - 800 North Main Street - Mt. Crawford Virginia 22841 - UNITED STATES - - 00-1F-F5 (hex) Kongsberg Defence & Aerospace - 001FF5 (base 16) Kongsberg Defence & Aerospace - Olav Brunborgs vei 6 - Billingstad 1396 - NORWAY - - 00-1F-F6 (hex) PS Audio International - 001FF6 (base 16) PS Audio International - 4826 Sterling Drive - Boulder CO 80301 - UNITED STATES - - 00-1F-F7 (hex) Nakajima All Precision Co., Ltd. - 001FF7 (base 16) Nakajima All Precision Co., Ltd. - Kami-Gomyo1480 - Sakaki-Machi - Hanishina-Gun Nagano-Ken 389-0606 - JAPAN - - 00-1F-F8 (hex) Siemens AG, Sector Industry, Drive Technologies, Motion Control Systems - 001FF8 (base 16) Siemens AG, Sector Industry, Drive Technologies, Motion Control Systems - Frauenauracherstraße 80 - Erlangen Bavaria 91056 - GERMANY - - 00-1F-F9 (hex) Advanced Knowledge Associates - 001FF9 (base 16) Advanced Knowledge Associates - 3350 Scott Blvd, Suite 40 - Santa Clara CA 95054-3119 - UNITED STATES - - 00-1F-FA (hex) Coretree, Co, Ltd - 001FFA (base 16) Coretree, Co, Ltd - #502 IT Venture Town, 694 - Taprib-dong, Yusung-Gu - Daejeon 305-510 - KOREA, REPUBLIC OF - - 00-1F-FB (hex) Green Packet Bhd - 001FFB (base 16) Green Packet Bhd - Lot 1-4, Incubator 2, Technology Park Malaysia - Lebuhraya Puchong - Sg Besi, Bukit Jalil - Kuala Lumpur Wilayah Persekutuan 57000 - MALAYSIA - - 00-1F-FC (hex) Riccius+Sohn GmbH - 001FFC (base 16) Riccius+Sohn GmbH - Haynauer Str. 49 - Berlin 12249 - GERMANY - - 00-1F-FD (hex) Indigo Mobile Technologies Corp. - 001FFD (base 16) Indigo Mobile Technologies Corp. - 11F, No22, Lan407,TiDing Blvd Section2, Neihu Technology Park - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-1F-FE (hex) HPN Supply Chain - 001FFE (base 16) HPN Supply Chain - 8000 Foothills Blvd - Roseville CA 95747 - UNITED STATES - - 00-1F-FF (hex) Respironics, Inc. - 001FFF (base 16) Respironics, Inc. - 1740 Golden Mile Highway - Monroeville PA 15146 - UNITED STATES - - 00-20-00 (hex) LEXMARK INTERNATIONAL, INC. - 002000 (base 16) LEXMARK INTERNATIONAL, INC. - 740 NEW CIRCLE ROAD - BLDG. 35 - LEXINGTON KY 40550 - UNITED STATES - - 00-20-01 (hex) DSP SOLUTIONS, INC. - 002001 (base 16) DSP SOLUTIONS, INC. - 2464 EMBARCADERO WAY - PALO ALTO CA 94303 - UNITED STATES - - 00-20-02 (hex) SERITECH ENTERPRISE CO., LTD. - 002002 (base 16) SERITECH ENTERPRISE CO., LTD. - FL. 182, NO. 531-1 - CHUNG CHENG ROAD HSIN TIEN CITY - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-03 (hex) PIXEL POWER LTD. - 002003 (base 16) PIXEL POWER LTD. - Unit 5 College Business Park - Coldhams Lane - CAMBRIDGE CB1 3HD - UNITED KINGDOM - - 00-20-04 (hex) YAMATAKE-HONEYWELL CO., LTD. - 002004 (base 16) YAMATAKE-HONEYWELL CO., LTD. - 54 SUZUKAWA, ISEHARA - KANAGAWA 259-11 - JAPAN - - 00-20-05 (hex) SIMPLE TECHNOLOGY - 002005 (base 16) SIMPLE TECHNOLOGY - 3001 DAIMLER ROAD - SANTA ANA CA 92705 - UNITED STATES - - 00-20-06 (hex) GARRETT COMMUNICATIONS, INC. - 002006 (base 16) GARRETT COMMUNICATIONS, INC. - 48531 WARMSPRINGS BLVD. - FREMONT CA 94539 - UNITED STATES - - 00-20-07 (hex) SFA, INC. - 002007 (base 16) SFA, INC. - 1401 MCCORMICK DRIVE - LANDOVER MD 20785 - UNITED STATES - - 00-20-08 (hex) CABLE & COMPUTER TECHNOLOGY - 002008 (base 16) CABLE & COMPUTER TECHNOLOGY - 1555 SO. SINCLAIR STREET - ANAHEIM CA 92806 - UNITED STATES - - 00-20-09 (hex) PACKARD BELL ELEC., INC. - 002009 (base 16) PACKARD BELL ELEC., INC. - 9425 CANOGA AVENUE - CHATSWORTH CA 913211 - UNITED STATES - - 00-20-0A (hex) SOURCE-COMM CORP. - 00200A (base 16) SOURCE-COMM CORP. - 25020 W. AVENUE STANFORD - UNIT 180 - VALENCIA CA 91355 - UNITED STATES - - 00-20-0B (hex) OCTAGON SYSTEMS CORP. - 00200B (base 16) OCTAGON SYSTEMS CORP. - 7403 Church Ranch Blvd - Westminster CO 80021 - UNITED STATES - - 00-20-0C (hex) ADASTRA SYSTEMS CORP. - 00200C (base 16) ADASTRA SYSTEMS CORP. - 28310 INDUSTRIAL BLVD.-STE-K - HAYWARD CA 94545 - UNITED STATES - - 00-20-0D (hex) CARL ZEISS - 00200D (base 16) CARL ZEISS - POSTFACH 1380 - ABT. 1-EL 73444 OBERKOCHEN - GERMANY - - 00-20-0E (hex) SATELLITE TECHNOLOGY MGMT, INC - 00200E (base 16) SATELLITE TECHNOLOGY MGMT, INC - 3530 HYLAND AVENUE - COSTA MESA CA 92626 - UNITED STATES - - 00-20-0F (hex) TANBAC CO., LTD. - 00200F (base 16) TANBAC CO., LTD. - SAKURAI DAI 2 BG - 27-4 IRIYA 1-CHOME TAITO-KU TOKYO 110 - JAPAN - - 00-20-10 (hex) JEOL SYSTEM TECHNOLOGY CO. LTD - 002010 (base 16) JEOL SYSTEM TECHNOLOGY CO. LTD - 3-1-2 Musashino - Akishima-shi Tokyo 196-8558 - JAPAN - - 00-20-11 (hex) CANOPUS CO., LTD. - 002011 (base 16) CANOPUS CO., LTD. - KOBE HI-TECH PARK - 1-2-2 MUROTANI NISHI-KU KOBE - 651-22 - JAPAN - - 00-20-12 (hex) CAMTRONICS MEDICAL SYSTEMS - 002012 (base 16) CAMTRONICS MEDICAL SYSTEMS - P.O. BOX 950 - HARTLAND WI 53029 - UNITED STATES - - 00-20-13 (hex) DIVERSIFIED TECHNOLOGY, INC. - 002013 (base 16) DIVERSIFIED TECHNOLOGY, INC. - 112 E. STATE STREET - RIDGELAND MS 39157 - UNITED STATES - - 00-20-14 (hex) GLOBAL VIEW CO., LTD. - 002014 (base 16) GLOBAL VIEW CO., LTD. - 4F, NO. 23, LANE 306 - FU-TEH 1 RD. HSI-CHIH, TAIPEI, HSIEN - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-15 (hex) ACTIS COMPUTER SA - 002015 (base 16) ACTIS COMPUTER SA - 16 CHEMIN DES AULX - 1228 PLAN LES OVATES - SWITZERLAND - - 00-20-16 (hex) SHOWA ELECTRIC WIRE & CABLE CO - 002016 (base 16) SHOWA ELECTRIC WIRE & CABLE CO - NO. 20-25, SEISHIN 8-CHOME - SAGAMIHARA, KANAGAWA - 229 - JAPAN - - 00-20-17 (hex) ORBOTECH - 002017 (base 16) ORBOTECH - INDUSTRIAL ZONE - P.O. BOX 215 70651 YAVNE - ISRAEL - - 00-20-18 (hex) CIS TECHNOLOGY INC. - 002018 (base 16) CIS TECHNOLOGY INC. - FL. 9-1, NO. 94, PAO CHUNG RD. - HSIN TIEN CITY - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-20-19 (hex) OHLER GmbH - 002019 (base 16) OHLER GmbH - MAYBACHSTRASE 30 - 71332 WAIBLINGEN - GERMANY - - 00-20-1A (hex) MRV Communications, Inc. - 00201A (base 16) MRV Communications, Inc. - 20415 Nordhoff St. - Chatsworth CA 91311 - UNITED STATES - - 00-20-1B (hex) NORTHERN TELECOM/NETWORK - 00201B (base 16) NORTHERN TELECOM/NETWORK - SYSTEMS CORPORATION - 250 SIDNEY STREET BELLEVILLE, ONTARIO - K8N 5B7 - CANADA - - 00-20-1C (hex) EXCEL, INC. - 00201C (base 16) EXCEL, INC. - 355 OLD PLYMOUTH ROAD - SAGAMORE BEACH MA 02562 - UNITED STATES - - 00-20-1D (hex) KATANA PRODUCTS - 00201D (base 16) KATANA PRODUCTS - THE STUDIO, QUARRY HILL BOX, - WILTSHIRE SN14 9HT - UNITED KINGDOM - - 00-20-1E (hex) NETQUEST CORPORATION - 00201E (base 16) NETQUEST CORPORATION - 523 FELLOWSHIP ROAD-STE.#205 - MT. LAUREL NJ 08054 - UNITED STATES - - 00-20-1F (hex) BEST POWER TECHNOLOGY, INC. - 00201F (base 16) BEST POWER TECHNOLOGY, INC. - P.O. BOX 280 - NECEDAH WI 54646 - UNITED STATES - - 00-20-20 (hex) MEGATRON COMPUTER INDUSTRIES PTY, LTD. - 002020 (base 16) MEGATRON COMPUTER INDUSTRIES PTY, LTD. - - UNIT 2, 62-64 CHARTER STREET RINGWOOD V - AUSTRALIA - - 00-20-21 (hex) ALGORITHMS SOFTWARE PVT. LTD. - 002021 (base 16) ALGORITHMS SOFTWARE PVT. LTD. - 83 JOLLY MAKER CHAMBERS II - NARIMAN POINT BOMBAY 400021 - INDIA - - 00-20-22 (hex) NMS Communications - 002022 (base 16) NMS Communications - 100 Crossing Boulevard - Framingham MA 01702 - UNITED STATES - - 00-20-23 (hex) T.C. TECHNOLOGIES PTY. LTD - 002023 (base 16) T.C. TECHNOLOGIES PTY. LTD - 6/60 FAIRFORD RD. - PADSTOW NSW2211 - AUSTRALIA - - 00-20-24 (hex) PACIFIC COMMUNICATION SCIENCES - 002024 (base 16) PACIFIC COMMUNICATION SCIENCES - 9645 SCRANTON ROAD - SAN DIEGO CA 92121 - UNITED STATES - - 00-20-25 (hex) CONTROL TECHNOLOGY, INC. - 002025 (base 16) CONTROL TECHNOLOGY, INC. - 5734 MIDDLEBROOK PIKE - KNOXVILLE TN 37921 - UNITED STATES - - 00-20-26 (hex) AMKLY SYSTEMS, INC. - 002026 (base 16) AMKLY SYSTEMS, INC. - 15801 ROCKFIELD BLVD., #P - IRVINE CA 92718 - UNITED STATES - - 00-20-27 (hex) MING FORTUNE INDUSTRY CO., LTD - 002027 (base 16) MING FORTUNE INDUSTRY CO., LTD - 4F, NO. 800 CHUNG CHENG RD, - CHUNG HO CITY, TAIPEI HSIEN - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-28 (hex) WEST EGG SYSTEMS, INC. - 002028 (base 16) WEST EGG SYSTEMS, INC. - 65 HIGH RIDGE ROAD-STE.#286 - STAMFORD CT 06905 - UNITED STATES - - 00-20-29 (hex) TELEPROCESSING PRODUCTS, INC. - 002029 (base 16) TELEPROCESSING PRODUCTS, INC. - 4565 E. INDUSTRIAL STREET - BUILDING #7K - SIMI VALLEY CA 93063 - UNITED STATES - - 00-20-2A (hex) N.V. DZINE - 00202A (base 16) N.V. DZINE - KONING LEOPOLD III LAAN 2 - B - 8500 KORTRIJK - BELGIUM - - 00-20-2B (hex) ADVANCED TELECOMMUNICATIONS MODULES, LTD. - 00202B (base 16) ADVANCED TELECOMMUNICATIONS MODULES, LTD. - - MOUNT PLEASANT HOUSE HUNTINGDON ROAD, - Cambridge CB3 OBL - UNITED KINGDOM - - 00-20-2C (hex) WELLTRONIX CO., LTD. - 00202C (base 16) WELLTRONIX CO., LTD. - 3F, NO. 36-1, HWANG HSI STREET - SHIN-LIN TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-2D (hex) TAIYO CORPORATION - 00202D (base 16) TAIYO CORPORATION - 1-2-6 SANNOH, OHTA-KU - TOKYO - 143 - JAPAN - - 00-20-2E (hex) DAYSTAR DIGITAL - 00202E (base 16) DAYSTAR DIGITAL - 5556 ATLANTA HIGHWAY - FLOWERY BRANCH GA 30542 - UNITED STATES - - 00-20-2F (hex) ZETA COMMUNICATIONS, LTD. - 00202F (base 16) ZETA COMMUNICATIONS, LTD. - ZENITH HOUSE - GRESFORD INDUSTRIAL PARK - WREXHAM, CLWYD, LL12 8LX - UNITED KINGDOM - - 00-20-30 (hex) ANALOG & DIGITAL SYSTEMS - 002030 (base 16) ANALOG & DIGITAL SYSTEMS - 1/2 LAVELLE ROAD - BANGALORE - 560001 - INDIA - - 00-20-31 (hex) Tattile SRL - 002031 (base 16) Tattile SRL - AM PESTALOZZIRING 24 - D-91058 ERLANGEN - GERMANY - - 00-20-32 (hex) ALCATEL TAISEL - 002032 (base 16) ALCATEL TAISEL - 4, MING SHENG STREET TU-CHENG - INDUSTRIAL DISTRICT TAIPEI HSIEH - TAIWAN ROC - TAIWAN, PROVINCE OF CHINA - - 00-20-33 (hex) SYNAPSE TECHNOLOGIES, INC. - 002033 (base 16) SYNAPSE TECHNOLOGIES, INC. - 4822 ALBEMARLE ROAD, #104 - CHARLOTTE NC 28205 - UNITED STATES - - 00-20-34 (hex) ROTEC INDUSTRIEAUTOMATION GMBH - 002034 (base 16) ROTEC INDUSTRIEAUTOMATION GMBH - GUTENBERGSTR. 15 - 76437 RASTATT - GERMANY - - 00-20-35 (hex) IBM Corp - 002035 (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-20-36 (hex) BMC SOFTWARE - 002036 (base 16) BMC SOFTWARE - 1600 CITY WEST BLVD., #1600 - HOUSTON TX 77042 - UNITED STATES - - 00-20-37 (hex) SEAGATE TECHNOLOGY - 002037 (base 16) SEAGATE TECHNOLOGY - 8001 E. BLOOMINGTON FWY - M/S - MPS043 - BLOOMINGTON MN 55420 - UNITED STATES - - 00-20-38 (hex) VME MICROSYSTEMS INTERNATIONAL CORPORATION - 002038 (base 16) VME MICROSYSTEMS INTERNATIONAL CORPORATION - 12090 S. MEMORIAL PARKWAY - HUNTSVILLE AL 35803 - UNITED STATES - - 00-20-39 (hex) SCINETS - 002039 (base 16) SCINETS - 1575 TENAKA - STE# N8 - SUNNYVALE CA 94087 - UNITED STATES - - 00-20-3A (hex) DIGITAL BI0METRICS INC. - 00203A (base 16) DIGITAL BI0METRICS INC. - 5600 ROWLAND ROAD- STE.#205 - MINNETONKA MN 55364 - UNITED STATES - - 00-20-3B (hex) WISDM LTD. - 00203B (base 16) WISDM LTD. - ST. JOHNS INNOVATION CENTRE - COWLEY ROAD CAMBRIDGE CB4 4WS - ENGLAND - UNITED KINGDOM - - 00-20-3C (hex) EUROTIME AB - 00203C (base 16) EUROTIME AB - BOX 277 - S-53224 SKARA - SWEDEN - - 00-20-3D (hex) Honeywell ECC - 00203D (base 16) Honeywell ECC - 1985 Douglas Drive - MN10-121A - Golden Valley MN 55422 - UNITED STATES - - 00-20-3E (hex) LogiCan Technologies, Inc. - 00203E (base 16) LogiCan Technologies, Inc. - 150 KARL CLARK ROAD - EDMONTON, ALBERTA T6N 1E2 - CANADA - - 00-20-3F (hex) JUKI CORPORATION - 00203F (base 16) JUKI CORPORATION - 8-2-1 KOKURYO-CHO - CHOFU-SHI TOKYO 182 - JAPAN - - 00-20-40 (hex) ARRIS Group, Inc. - 002040 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-20-41 (hex) DATA NET - 002041 (base 16) DATA NET - SUWON P.O. BOX 106, SUWON - KYUNGGI-DO - KOREA 440-600 - KOREA, REPUBLIC OF - - 00-20-42 (hex) DATAMETRICS CORP. - 002042 (base 16) DATAMETRICS CORP. - 8966 COMANCHE AVE. - CHATSWORTH CA 91311 - UNITED STATES - - 00-20-43 (hex) NEURON COMPANY LIMITED - 002043 (base 16) NEURON COMPANY LIMITED - 15 KWAI YI ROAD, BLOCK 2, - 21ST FLOOR, FLAT B - KWAI CHUNG, N.T. - HONG KONG - - 00-20-44 (hex) GENITECH PTY LTD - 002044 (base 16) GENITECH PTY LTD - P.O. BOX 196 - ASQUITH NSW 2077 - AUSTRALIA - - 00-20-45 (hex) ION Networks, Inc. - 002045 (base 16) ION Networks, Inc. - 1551 South Washington Ave. - Piscataway NJ 08854 - UNITED STATES - - 00-20-46 (hex) CIPRICO, INC. - 002046 (base 16) CIPRICO, INC. - 2800 CAMPUS DRIVE--SUITE #60 - PLYMOUTH MN 55441 - UNITED STATES - - 00-20-47 (hex) STEINBRECHER CORP. - 002047 (base 16) STEINBRECHER CORP. - 30 NORTH AVENUE - BURLINGTON MA 01803 - UNITED STATES - - 00-20-48 (hex) Marconi Communications - 002048 (base 16) Marconi Communications - 1000 Fore Drive - Warrendale PA 15086-7502 - UNITED STATES - - 00-20-49 (hex) COMTRON, INC. - 002049 (base 16) COMTRON, INC. - SANCATHERINA BLDG. - 36-12 SHINJUKU 1-CHOME SHINJUKU-KU - TOKYO 160 - JAPAN - - 00-20-4A (hex) PRONET GMBH - 00204A (base 16) PRONET GMBH - KARLSTRASSE 49 - D-7805 F VILLINGEN-SCHWENNINGEN - GERMANY - - 00-20-4B (hex) AUTOCOMPUTER CO., LTD. - 00204B (base 16) AUTOCOMPUTER CO., LTD. - NO. 18, PEI YUAN ROAD - CHUNG-LI CITY, TAO-YUAN HSIEN - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-4C (hex) MITRON COMPUTER PTE LTD. - 00204C (base 16) MITRON COMPUTER PTE LTD. - 1020 HOUGANG AVENUE 1 #03-3504 - SINGAPORE 1953 - SINGAPORE - - 00-20-4D (hex) INOVIS GMBH - 00204D (base 16) INOVIS GMBH - HANNS-BRAUN STRASSE 50 - 85375 NEUFAHRN - GERMANY - - 00-20-4E (hex) NETWORK SECURITY SYSTEMS, INC. - 00204E (base 16) NETWORK SECURITY SYSTEMS, INC. - 9401 WAPLES STREET,STE. #100 - SAN DIEGO CA 92121 - UNITED STATES - - 00-20-4F (hex) DEUTSCHE AEROSPACE AG - 00204F (base 16) DEUTSCHE AEROSPACE AG - GESCHAEFTSFELD - VERTEIDIGUNG UND ZIVILE SYSTEM 81663 MUE - BUNDESREPUBLIK DEUTSCHLAND - GERMANY - - 00-20-50 (hex) KOREA COMPUTER INC. - 002050 (base 16) KOREA COMPUTER INC. - 469, DAEHEUNG-DONG - MAPO-GU, SEOUL - KOREA - KOREA, REPUBLIC OF - - 00-20-51 (hex) Verilink Corporation - 002051 (base 16) Verilink Corporation - 127 Jetplex Circle - Madison AL 35758 - UNITED STATES - - 00-20-52 (hex) RAGULA SYSTEMS - 002052 (base 16) RAGULA SYSTEMS - 4540 S. JUPITER DRIVE - SALT LAKE CITY UT 84124 - UNITED STATES - - 00-20-53 (hex) HUNTSVILLE MICROSYSTEMS, INC. - 002053 (base 16) HUNTSVILLE MICROSYSTEMS, INC. - P.O. BOX 12415 - HUNTSVILLE AL 35815 - UNITED STATES - - 00-20-54 (hex) Sycamore Networks - 002054 (base 16) Sycamore Networks - 220 Mill Rd - Chelmsford MA 01824 - UNITED STATES - - 00-20-55 (hex) ALTECH CO., LTD. - 002055 (base 16) ALTECH CO., LTD. - OHISHI BLDG., 2-23-11 - NISHI-NIPPORI, ARAKAWA-KU - TOKYO 116 - JAPAN - - 00-20-56 (hex) NEOPRODUCTS - 002056 (base 16) NEOPRODUCTS - 25 CHAPMAN STREET - BLACKBURN NORTH VICTORIA 3130 - AUSTRALIA - - 00-20-57 (hex) TITZE DATENTECHNIK GmbH - 002057 (base 16) TITZE DATENTECHNIK GmbH - DIESELSTRASSE 10 - DS-71272 RENNINGEN-2 - GERMANY - - 00-20-58 (hex) ALLIED SIGNAL INC. - 002058 (base 16) ALLIED SIGNAL INC. - ROUTE 46 - TETERBORO NJ 07608 - UNITED STATES - - 00-20-59 (hex) MIRO COMPUTER PRODUCTS AG - 002059 (base 16) MIRO COMPUTER PRODUCTS AG - CARL MIELE STR. 4 - D-38112 BRAUNSCHWEIG - GERMANY - - 00-20-5A (hex) COMPUTER IDENTICS - 00205A (base 16) COMPUTER IDENTICS - 5 SHAWMUT ROAD - CANTON MA 02021 - UNITED STATES - - 00-20-5B (hex) Kentrox, LLC - 00205B (base 16) Kentrox, LLC - 20010 NW Tanasbourne Dr. - Hillsboro OR 97124 - UNITED STATES - - 00-20-5C (hex) InterNet Systems of Florida, Inc. - 00205C (base 16) InterNet Systems of Florida, Inc. - P.O. BOX 578 - CRESTVIEW FL 32536 - UNITED STATES - - 00-20-5D (hex) NANOMATIC OY - 00205D (base 16) NANOMATIC OY - PUISTOLAN RAITTI 4 - 00760 HELSINKI - FINLAND - - 00-20-5E (hex) CASTLE ROCK, INC. - 00205E (base 16) CASTLE ROCK, INC. - 20 SOUTH SANTA CRUZ AVE. - SUITE #310 - LOS GATOS CA 95030 - UNITED STATES - - 00-20-5F (hex) GAMMADATA COMPUTER GMBH - 00205F (base 16) GAMMADATA COMPUTER GMBH - GUTENBERGSTR. 13 - 82168 PUCHHEIM - GERMANY - - 00-20-60 (hex) ALCATEL ITALIA S.p.A. - 002060 (base 16) ALCATEL ITALIA S.p.A. - VIA TRENTO, 30 - 20059 VIMERCATE (MI) - ITALY - - 00-20-61 (hex) GarrettCom, Inc. - 002061 (base 16) GarrettCom, Inc. - 47823 Westinghouse Dr. - Fremont CA 94539 - UNITED STATES - - 00-20-62 (hex) SCORPION LOGIC, LTD. - 002062 (base 16) SCORPION LOGIC, LTD. - 19 BROOKSIDE ROAD - OXHEY, WATFORD - HERTS WD1 4BW - UNITED KINGDOM - - 00-20-63 (hex) WIPRO INFOTECH LTD. - 002063 (base 16) WIPRO INFOTECH LTD. - UNITS 47-48, SDF BLOCK VII - MEPZ, KADAPPERI MADRAS-600045 - INDIA - - 00-20-64 (hex) PROTEC MICROSYSTEMS, INC. - 002064 (base 16) PROTEC MICROSYSTEMS, INC. - 297 LABROSSE - POINTE-CLAIRE, QUEBEC H9R 1A3 - CANADA - - 00-20-65 (hex) SUPERNET NETWORKING INC. - 002065 (base 16) SUPERNET NETWORKING INC. - 16 TOZERET HA'ARETZ ST. - TEL-AVIV 67891 - ISRAEL - - 00-20-66 (hex) GENERAL MAGIC, INC. - 002066 (base 16) GENERAL MAGIC, INC. - 2465 LATHAM STREET - MOUNTAIN VIEW CA 94040 - UNITED STATES - - 00-20-67 (hex) PRIVATE - 002067 (base 16) - - 00-20-68 (hex) ISDYNE - 002068 (base 16) ISDYNE - 11 ROXBURY AVENUE - NATICK MA 01760 - UNITED STATES - - 00-20-69 (hex) ISDN SYSTEMS CORPORATION - 002069 (base 16) ISDN SYSTEMS CORPORATION - 8320 OLD COURTHOUSE RD. - SUITE #203 - VIENNA VA 22182 - UNITED STATES - - 00-20-6A (hex) OSAKA COMPUTER CORP. - 00206A (base 16) OSAKA COMPUTER CORP. - 2-8 KOYACHOU NEYAGAW-SHI - OSAKA 572 - JAPAN - - 00-20-6B (hex) KONICA MINOLTA HOLDINGS, INC. - 00206B (base 16) KONICA MINOLTA HOLDINGS, INC. - 1-6-1, Marunouchi, - Chiyoda-ku - Tokyo 100-0005 - JAPAN - - 00-20-6C (hex) EVERGREEN TECHNOLOGY CORP. - 00206C (base 16) EVERGREEN TECHNOLOGY CORP. - 231 EMERSON STREET - PALO ALTO CA 94301 - UNITED STATES - - 00-20-6D (hex) DATA RACE, INC. - 00206D (base 16) DATA RACE, INC. - 11550 IH-10WEST STE#395 - SAN ANTONIO TX 78230 - UNITED STATES - - 00-20-6E (hex) XACT, INC. - 00206E (base 16) XACT, INC. - P.O. BOX 55 - ARGYLE TX 76226 - UNITED STATES - - 00-20-6F (hex) FLOWPOINT CORPORATION - 00206F (base 16) FLOWPOINT CORPORATION - 7291 CORONADO DRIVE, STE# 4 - SAN JOSE CA 95129 - UNITED STATES - - 00-20-70 (hex) HYNET, LTD. - 002070 (base 16) HYNET, LTD. - 102 JABOTINSKY ST. - PO BOX 3638 - PETACH TIKVA 49130 - ISRAEL - - 00-20-71 (hex) IBR GMBH - 002071 (base 16) IBR GMBH - KOHLERSTR. 45 - D-46286 DORSTEN - GERMANY - - 00-20-72 (hex) WORKLINK INNOVATIONS - 002072 (base 16) WORKLINK INNOVATIONS - 2452 ARMSTRONG STREET - LIVERMORE CA 9455O - UNITED STATES - - 00-20-73 (hex) FUSION SYSTEMS CORPORATION - 002073 (base 16) FUSION SYSTEMS CORPORATION - 7600 STANDISH PLACE - ROCKVILLE MD 20855 - UNITED STATES - - 00-20-74 (hex) SUNGWOON SYSTEMS - 002074 (base 16) SUNGWOON SYSTEMS - YUSUN BLDG.44-4 - SAMSUNG-DONG KANGNAM-KU, SEOUL 135-090 - KOREA - KOREA, REPUBLIC OF - - 00-20-75 (hex) MOTOROLA COMMUNICATION ISRAEL - 002075 (base 16) MOTOROLA COMMUNICATION ISRAEL - 3 KREMENETSKI STREET - POB 25016 - TEL-AVIV 61250 - ISRAEL - - 00-20-76 (hex) REUDO CORPORATION - 002076 (base 16) REUDO CORPORATION - 4-1-10 SHINSAN - NAGAOKA CITY, NIIGATA 940-21 - JAPAN - - 00-20-77 (hex) KARDIOS SYSTEMS CORP. - 002077 (base 16) KARDIOS SYSTEMS CORP. - 26 N SUMMIT AVE. - GAITHERSBURG MD 20877 - UNITED STATES - - 00-20-78 (hex) RUNTOP, INC. - 002078 (base 16) RUNTOP, INC. - 5/F, NO. 10, ALLEY 8, LANE 45 - PAO SHIN ROAD, HSINTIEN TAIPEI HSIEN - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-79 (hex) MIKRON GMBH - 002079 (base 16) MIKRON GMBH - BRESLAUERSTR. 1-3 - 85386 ECHING - GERMANY - - 00-20-7A (hex) WiSE Communications, Inc. - 00207A (base 16) WiSE Communications, Inc. - 130 KNOWLES DRIVE - LOS GATOS CA 95030 - UNITED STATES - - 00-20-7B (hex) Intel Corporation - 00207B (base 16) Intel Corporation - 2111 NE 25th Avenue - JF3-420 - Hillsboro OR 97124 - UNITED STATES - - 00-20-7C (hex) AUTEC GmbH - 00207C (base 16) AUTEC GmbH - BAHNHOFSTR. 57 - 55234 FRAMERSHEIM - GERMANY - - 00-20-7D (hex) ADVANCED COMPUTER APPLICATIONS - 00207D (base 16) ADVANCED COMPUTER APPLICATIONS - 107 PENNS TRAIL - NEWTOWN PA 18940 - UNITED STATES - - 00-20-7E (hex) FINECOM Co., Ltd. - 00207E (base 16) FINECOM Co., Ltd. - 1108 HWAKOK-DONG, KANGSEO-KU - SEOUL - KOREA, REPUBLIC OF - - 00-20-7F (hex) KYOEI SANGYO CO., LTD. - 00207F (base 16) KYOEI SANGYO CO., LTD. - DIR. & GEN'L MGR.IND. SYSTEMS - 20-4, SHOTO 2-CHOME SHIBUYA-KU - TOKYO - JAPAN - - 00-20-80 (hex) SYNERGY (UK) LTD. - 002080 (base 16) SYNERGY (UK) LTD. - HARTCRAN HOUSE - CARPENDERS PARK, - WATFORD HERTS. WD1 5EZ - UNITED KINGDOM - - 00-20-81 (hex) TITAN ELECTRONICS - 002081 (base 16) TITAN ELECTRONICS - 3033 SCIENCE PARK ROAD - SAN DIEGO CA 92121 - UNITED STATES - - 00-20-82 (hex) ONEAC CORPORATION - 002082 (base 16) ONEAC CORPORATION - 27944 N. BRADLEY RD. - LIBERTYVILLE IL 60048 - UNITED STATES - - 00-20-83 (hex) PRESTICOM INCORPORATED - 002083 (base 16) PRESTICOM INCORPORATED - 3275, 1ST STREET, STE. #1 - ST-HUBERT (QUEBEC) - CANADA J3Y 8Y6 - CANADA - - 00-20-84 (hex) OCE PRINTING SYSTEMS, GMBH - 002084 (base 16) OCE PRINTING SYSTEMS, GMBH - SIEMENSALLEE 2 - D-85586 POING - GERMANY - - 00-20-85 (hex) Eaton Corporation - 002085 (base 16) Eaton Corporation - 8380 Capital Blvd. - RALEIGH NC 27616 - UNITED STATES - - 00-20-86 (hex) MICROTECH ELECTRONICS LIMITED - 002086 (base 16) MICROTECH ELECTRONICS LIMITED - LANCASTER ROAD - CRESSEX INDUSTRIAL ESTATE HIGH WYCOMBE, - KINGDOM - UNITED KINGDOM - - 00-20-87 (hex) MEMOTEC, INC. - 002087 (base 16) MEMOTEC, INC. - 7755 Henri-Bourassa - MONTREAL, QUEBEC H4S 1P7 - CANADA - - 00-20-88 (hex) GLOBAL VILLAGE COMMUNICATION - 002088 (base 16) GLOBAL VILLAGE COMMUNICATION - 1144 EAST ARQUES AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-20-89 (hex) T3PLUS NETWORKING, INC. - 002089 (base 16) T3PLUS NETWORKING, INC. - 2840 SAN TOMAS EXPRESSWAY - SANTA CLARA CA 95051 - UNITED STATES - - 00-20-8A (hex) SONIX COMMUNICATIONS, LTD. - 00208A (base 16) SONIX COMMUNICATIONS, LTD. - WILKINSON ROAD - CIRENCESTER, GLOS. GL7 1YT - ENGLAND - UNITED KINGDOM - - 00-20-8B (hex) LAPIS TECHNOLOGIES, INC. - 00208B (base 16) LAPIS TECHNOLOGIES, INC. - 1100 MARINA VILLAGE PKWY - SUITE #100 - ALAMEDA CA 94501 - UNITED STATES - - 00-20-8C (hex) GALAXY NETWORKS, INC. - 00208C (base 16) GALAXY NETWORKS, INC. - 9348 DE SOTO AVENUE - CHATSWORTH CA 91311 - UNITED STATES - - 00-20-8D (hex) CMD TECHNOLOGY - 00208D (base 16) CMD TECHNOLOGY - 1 VANDERBILT - IRVINE CA 92718 - UNITED STATES - - 00-20-8E (hex) CHEVIN SOFTWARE ENG. LTD. - 00208E (base 16) CHEVIN SOFTWARE ENG. LTD. - 2 BOROUGHGATE, OTLEY, - LEEDS, WEST, YORKSHIRE - LS21 3AL UNITED KINGDOM - UNITED KINGDOM - - 00-20-8F (hex) ECI TELECOM LTD. - 00208F (base 16) ECI TELECOM LTD. - HASIVIM ST. 30, - PETACH-TIKVA 49133 - ISRAEL - - 00-20-90 (hex) ADVANCED COMPRESSION TECHNOLOGY, INC. - 002090 (base 16) ADVANCED COMPRESSION TECHNOLOGY, INC. - 820 FLYNN ROAD - CAMARILLO CA 93012 - UNITED STATES - - 00-20-91 (hex) J125, NATIONAL SECURITY AGENCY - 002091 (base 16) J125, NATIONAL SECURITY AGENCY - 9800 SAVAGE ROAD - FT. MEADE MD 20755-6000 - UNITED STATES - - 00-20-92 (hex) CHESS ENGINEERING B.V. - 002092 (base 16) CHESS ENGINEERING B.V. - NIEUWE GRACHT 74 - 2011 NJ HAARLEM - NETHERLANDS - - 00-20-93 (hex) LANDINGS TECHNOLOGY CORP. - 002093 (base 16) LANDINGS TECHNOLOGY CORP. - 163 WATER STREET - MERRILL BLOCK UNIT A2 - EXETER NH 03833 - UNITED STATES - - 00-20-94 (hex) CUBIX CORPORATION - 002094 (base 16) CUBIX CORPORATION - 2800 LOCKHEED WAY - CARSON CITY NV 89706 - UNITED STATES - - 00-20-95 (hex) RIVA ELECTRONICS - 002095 (base 16) RIVA ELECTRONICS - UNIT 17, BARRSFOLD RD. - WINGATES INDUSTRIAL PARK WESTHOUGHTON, B - LANCASHIRE ENGLAND BL5 3XW - UNITED KINGDOM - - 00-20-96 (hex) Invensys - 002096 (base 16) Invensys - Robershaw Industrial Products - 1602 Mustang Drive - Marysville TN 37801 - UNITED STATES - - 00-20-97 (hex) APPLIED SIGNAL TECHNOLOGY - 002097 (base 16) APPLIED SIGNAL TECHNOLOGY - 160 SOBRANTE WAY - SUNNYVALE CA 94086 - UNITED STATES - - 00-20-98 (hex) HECTRONIC AB - 002098 (base 16) HECTRONIC AB - BOX 3002 - S-75003 UPPSALA - SWEDEN - - 00-20-99 (hex) BON ELECTRIC CO., LTD. - 002099 (base 16) BON ELECTRIC CO., LTD. - 4-4 28, MIZUDO-CHO - AMAGASAKI, 661 - HYOGO HYOGO - JAPAN - - 00-20-9A (hex) THE 3DO COMPANY - 00209A (base 16) THE 3DO COMPANY - 600 GALVESTON DRIVE - REDWOOD CITY CA 94063 - UNITED STATES - - 00-20-9B (hex) ERSAT ELECTRONIC GMBH - 00209B (base 16) ERSAT ELECTRONIC GMBH - HAARBERGSTR. 61 - D-99097 ERFURT - GERMANY - - 00-20-9C (hex) PRIMARY ACCESS CORP. - 00209C (base 16) PRIMARY ACCESS CORP. - 10080 CARROLL CANYON RD - SAN DIEGO CA 92131 - UNITED STATES - - 00-20-9D (hex) LIPPERT AUTOMATIONSTECHNIK - 00209D (base 16) LIPPERT AUTOMATIONSTECHNIK - D-68165 MANNHEIM - KRAPPMUEHLSTR. 34 - GERMANY - - 00-20-9E (hex) BROWN'S OPERATING SYSTEM SERVICES, LTD. - 00209E (base 16) BROWN'S OPERATING SYSTEM SERVICES, LTD. - ST. AGNES HOUSE, CRESSWELL PK, - BLACKHEATH, London SE3 9RD - UNITED KINGDOM - - 00-20-9F (hex) MERCURY COMPUTER SYSTEMS, INC. - 00209F (base 16) MERCURY COMPUTER SYSTEMS, INC. - 199 RIVERNECK ROAD - CHELMSFORD MA 01824 - UNITED STATES - - 00-20-A0 (hex) OA LABORATORY CO., LTD. - 0020A0 (base 16) OA LABORATORY CO., LTD. - 228 KAMIMACHIYA KAMAKURA - KANAGAWA 247 - JAPAN - - 00-20-A1 (hex) DOVATRON - 0020A1 (base 16) DOVATRON - PRODUCTS DIVISION - 1198 BOSTON AVENUE - LONGMONT CO 80501 - UNITED STATES - - 00-20-A2 (hex) GALCOM NETWORKING LTD. - 0020A2 (base 16) GALCOM NETWORKING LTD. - P.O. BOX 1568 - RAMAT HASHARON 47113 - ISRAEL - - 00-20-A3 (hex) Harmonic, Inc - 0020A3 (base 16) Harmonic, Inc - 4300 North First Street - San Jose CA 95134 - UNITED STATES - - 00-20-A4 (hex) MULTIPOINT NETWORKS - 0020A4 (base 16) MULTIPOINT NETWORKS - 19 DAVIS DRIVE - BELMONT CA 94002-3001 - UNITED STATES - - 00-20-A5 (hex) API ENGINEERING - 0020A5 (base 16) API ENGINEERING - 2689 POPLARWOOD WAY - SAN JOSE CA 95132 - UNITED STATES - - 00-20-A6 (hex) Proxim Wireless - 0020A6 (base 16) Proxim Wireless - 1561 Buckeye Drive - Milpitas CA 95035 - UNITED STATES - - 00-20-A7 (hex) PAIRGAIN TECHNOLOGIES, INC. - 0020A7 (base 16) PAIRGAIN TECHNOLOGIES, INC. - 14402 FRANKLIN AVENUE - TUSTIN CA 92680-7013 - UNITED STATES - - 00-20-A8 (hex) SAST TECHNOLOGY CORP. - 0020A8 (base 16) SAST TECHNOLOGY CORP. - 225 OLD NEW BRUNSWICK RD. - SUITE #101 - PISCATAWAY NJ 08854 - UNITED STATES - - 00-20-A9 (hex) WHITE HORSE INDUSTRIAL - 0020A9 (base 16) WHITE HORSE INDUSTRIAL - 4F. NO.16, ALLEY 56, LANE 181 - SEC.4, CHUNG HSIAO EAST ROAD TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-20-AA (hex) Ericsson Television Limited - 0020AA (base 16) Ericsson Television Limited - Solution Area Media - Unit 2 Stratefic Park - Comines Way, Hedge End Southhampton SO 30 4DA - UNITED KINGDOM - - 00-20-AB (hex) MICRO INDUSTRIES CORP. - 0020AB (base 16) MICRO INDUSTRIES CORP. - 8399 GREEN MEADOWS DR. N. - WESTERVILLE OH 43081 - UNITED STATES - - 00-20-AC (hex) INTERFLEX DATENSYSTEME GMBH - 0020AC (base 16) INTERFLEX DATENSYSTEME GMBH - GROBWIESENSTRASE 24 - W-7201 DURCHHAUSEN - WESTGERMANY - GERMANY - - 00-20-AD (hex) LINQ SYSTEMS - 0020AD (base 16) LINQ SYSTEMS - P.O. BOX 11040 - TUCSON AZ 85734 - UNITED STATES - - 00-20-AE (hex) ORNET DATA COMMUNICATION TECH. - 0020AE (base 16) ORNET DATA COMMUNICATION TECH. - P.O. BOX 323 - CARMIEL 20100 - ISRAEL - - 00-20-AF (hex) 3COM CORPORATION - 0020AF (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - SANTA CLARA CA 95052 - UNITED STATES - - 00-20-B0 (hex) GATEWAY DEVICES, INC. - 0020B0 (base 16) GATEWAY DEVICES, INC. - 2440 STANWELL DRIVE - CONCORD CA 94520 - UNITED STATES - - 00-20-B1 (hex) COMTECH RESEARCH INC. - 0020B1 (base 16) COMTECH RESEARCH INC. - 24271 TAHOE - LAGUNA NIGUEL CA 92656 - UNITED STATES - - 00-20-B2 (hex) GKD Gesellschaft Fur Kommunikation Und Datentechnik - 0020B2 (base 16) GKD Gesellschaft Fur Kommunikation Und Datentechnik - - SAARBURGER RING 10-12 - 68229 MANNHEIM - GERMANY - - 00-20-B3 (hex) Tattile SRL - 0020B3 (base 16) Tattile SRL - 3 APOLLO PLACE - LANE COVE N.S.W. 2066 - AUSTRALIA - - 00-20-B4 (hex) TERMA ELEKTRONIK AS - 0020B4 (base 16) TERMA ELEKTRONIK AS - HOVMARKEN 4, - DK-8520 LYSTRUP - DENMARK - - 00-20-B5 (hex) YASKAWA ELECTRIC CORPORATION - 0020B5 (base 16) YASKAWA ELECTRIC CORPORATION - 2-1 KUROSAKI-SHIROISHI - YAHATANISHI-KU KITAKYUSHU-CITY - JAPAN - - 00-20-B6 (hex) AGILE NETWORKS, INC. - 0020B6 (base 16) AGILE NETWORKS, INC. - 200 BAKER AVENUE - CONCORD MA 01742 - UNITED STATES - - 00-20-B7 (hex) NAMAQUA COMPUTERWARE - 0020B7 (base 16) NAMAQUA COMPUTERWARE - P.O. BOX 7155 - STELLEN BOSCH 7599 - SOUTH AFRICA - - 00-20-B8 (hex) PRIME OPTION, INC. - 0020B8 (base 16) PRIME OPTION, INC. - 2341 W. 205TH STREET #116 - TORRANCE CA 90501 - UNITED STATES - - 00-20-B9 (hex) METRICOM, INC. - 0020B9 (base 16) METRICOM, INC. - 980 UNIVERSITY AVENUE - LOS GATOS CA 95030 - UNITED STATES - - 00-20-BA (hex) CENTER FOR HIGH PERFORMANCE - 0020BA (base 16) CENTER FOR HIGH PERFORMANCE - COMPUTING OF WPI - SUITE #170 293 BOSTON POST ROAD W. - MARLBORO MA 01752 - UNITED STATES - - 00-20-BB (hex) ZAX CORPORATION - 0020BB (base 16) ZAX CORPORATION - 20-12 OGIKUBO 5-CHOME - SUGINAMI-KU TOKYO - 167 - JAPAN - - 00-20-BC (hex) Long Reach Networks Pty Ltd - 0020BC (base 16) Long Reach Networks Pty Ltd - Unit 3, 118-122 Bowden St - MEADOWBANK NSW 2114 - AUSTRALIA - - 00-20-BD (hex) NIOBRARA R & D CORPORATION - 0020BD (base 16) NIOBRARA R & D CORPORATION - PO BOX 3418 - JOPLIN MO 64803-3418 - UNITED STATES - - 00-20-BE (hex) LAN ACCESS CORP. - 0020BE (base 16) LAN ACCESS CORP. - 2730 MONTEREY STREET, STE.#102 - TORRANCE CA 90503 - UNITED STATES - - 00-20-BF (hex) AEHR TEST SYSTEMS - 0020BF (base 16) AEHR TEST SYSTEMS - 1667 PLYMOUTH STREET - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-20-C0 (hex) PULSE ELECTRONICS, INC. - 0020C0 (base 16) PULSE ELECTRONICS, INC. - 5706 FREDERICK AVENUE - ROCKVILLE MD 20852 - UNITED STATES - - 00-20-C1 (hex) SAXA, Inc. - 0020C1 (base 16) SAXA, Inc. - NBF Platinum Tower 1-17-3 Shirokane - Minato-ku - Tokyo 108-8050 - JAPAN - - 00-20-C2 (hex) TEXAS MEMORY SYSTEMS, INC. - 0020C2 (base 16) TEXAS MEMORY SYSTEMS, INC. - 11200 WESTHEIMER RD-STE#1000 - HOUSTON TX 77042 - UNITED STATES - - 00-20-C3 (hex) COUNTER SOLUTIONS LTD. - 0020C3 (base 16) COUNTER SOLUTIONS LTD. - 263 HEAGE ROAD - RIPLEY, DERBYS DE5 3GH - UNITED KINGDOM - - 00-20-C4 (hex) INET,INC. - 0020C4 (base 16) INET,INC. - 801 E. CAMPBELL-STE.#330 - RICHARDSON TX 75081 - UNITED STATES - - 00-20-C5 (hex) EAGLE TECHNOLOGY - 0020C5 (base 16) EAGLE TECHNOLOGY - 2865 ZANKER ROAD - SAN JOSE CA 95134 - UNITED STATES - - 00-20-C6 (hex) NECTEC - 0020C6 (base 16) NECTEC - RAMA VI ROAD - RAJTHEVI BANGKOK 10400 - THAILAND - - 00-20-C7 (hex) AKAI Professional M.I. Corp. - 0020C7 (base 16) AKAI Professional M.I. Corp. - 1-3, Hiranuma 1-Chome, - Nishi-ku, Yokohama, - 220-0023 - JAPAN - - 00-20-C8 (hex) LARSCOM INCORPORATED - 0020C8 (base 16) LARSCOM INCORPORATED - 4600 PATRICK HENRY DRIVE - SANTA CLARA CA 95054 - UNITED STATES - - 00-20-C9 (hex) VICTRON BV - 0020C9 (base 16) VICTRON BV - POB 31 - NL 9700 AA GRONINGEN - THE - NETHERLANDS - - 00-20-CA (hex) DIGITAL OCEAN - 0020CA (base 16) DIGITAL OCEAN - 11206 THOMPSON AVENUE - LENEXA KS 66219-2303 - UNITED STATES - - 00-20-CB (hex) PRETEC ELECTRONICS CORP. - 0020CB (base 16) PRETEC ELECTRONICS CORP. - 39899 BALENTINE DR. - SUITE #305 - NEWARK CA 94560 - UNITED STATES - - 00-20-CC (hex) DIGITAL SERVICES, LTD. - 0020CC (base 16) DIGITAL SERVICES, LTD. - 9 WAYTE STREET - COSHAM HAMPSHIRE - ENGLAND PO6 3BS - UNITED KINGDOM - - 00-20-CD (hex) HYBRID NETWORKS, INC. - 0020CD (base 16) HYBRID NETWORKS, INC. - 10201 BUBB ROAD - CUPERTINO CA 95014-4167 - UNITED STATES - - 00-20-CE (hex) LOGICAL DESIGN GROUP, INC. - 0020CE (base 16) LOGICAL DESIGN GROUP, INC. - 6301 CHAPEL HILL ROAD - RALEIGH NC 27607 - UNITED STATES - - 00-20-CF (hex) TEST & MEASUREMENT SYSTEMS INC - 0020CF (base 16) TEST & MEASUREMENT SYSTEMS INC - 2045 SITKA COURT - LOVELAND CO 80538 - UNITED STATES - - 00-20-D0 (hex) VERSALYNX CORPORATION - 0020D0 (base 16) VERSALYNX CORPORATION - 8950 CARLEY CIRCLE - SAN DIEGO CA 92126 - UNITED STATES - - 00-20-D1 (hex) MICROCOMPUTER SYSTEMS (M) SDN. - 0020D1 (base 16) MICROCOMPUTER SYSTEMS (M) SDN. - 23-25, JALAN JEJAKA TUJUH - TAMAN MALURI, CHERAS 55100 KUALA LUMPUR - MALAYSIA - - 00-20-D2 (hex) RAD DATA COMMUNICATIONS, LTD. - 0020D2 (base 16) RAD DATA COMMUNICATIONS, LTD. - 8 HANECHOSHET STREET - TEL-AVIV 69710 - ISRAEL - - 00-20-D3 (hex) OST (OUEST STANDARD TELEMATIQU - 0020D3 (base 16) OST (OUEST STANDARD TELEMATIQU - RUE DU BAS VILLAGE - BP 158, Z.I. SUD-EST 35515 CESSON-SEVIGN - FRANCE - - 00-20-D4 (hex) CABLETRON - ZEITTNET INC. - 0020D4 (base 16) CABLETRON - ZEITTNET INC. - 35 INDUSTRIAL WAY - P.O. BOX 5005 - ROHESTER NH 03866-5005 - UNITED STATES - - 00-20-D5 (hex) VIPA GMBH - 0020D5 (base 16) VIPA GMBH - WETTERKREUZ 27 - D-91058 ERLANGEN - GERMANY - - 00-20-D6 (hex) BREEZECOM - 0020D6 (base 16) BREEZECOM - ATIDIM TECHNOLOGICAL PK-BLDG.3 - TEL-AVIV 61131 - ISRAEL - - 00-20-D7 (hex) JAPAN MINICOMPUTER SYSTEMS CO., Ltd. - 0020D7 (base 16) JAPAN MINICOMPUTER SYSTEMS CO., Ltd. - 3-33-18 TAKAIDOHIGASHI - SUGINAMI-KU - TOKYO 168 - JAPAN - - 00-20-D8 (hex) Nortel Networks - 0020D8 (base 16) Nortel Networks - 4401 Great America Pkwy. - Santa Clara CA 94588 - UNITED STATES - - 00-20-D9 (hex) PANASONIC TECHNOLOGIES, INC./MIECO-US - 0020D9 (base 16) PANASONIC TECHNOLOGIES, INC./MIECO-US - 1703 N. RANDALL RD. - ELGIN IL 60123 - UNITED STATES - - 00-20-DA (hex) Alcatel North America ESD - 0020DA (base 16) Alcatel North America ESD - 26801 West Agoura Road - CALABASAS CA 91301 - UNITED STATES - - 00-20-DB (hex) XNET TECHNOLOGY, INC. - 0020DB (base 16) XNET TECHNOLOGY, INC. - 426 S. HILLVIEW DRIVE - MILPITAS CA 95035 - UNITED STATES - - 00-20-DC (hex) DENSITRON TAIWAN LTD. - 0020DC (base 16) DENSITRON TAIWAN LTD. - KYOWA NANABANKAN 5F - 1-11-5 OMORI-KITA OTA-KU, TOKYO 143 - JAPAN - - 00-20-DD (hex) Cybertec Pty Ltd - 0020DD (base 16) Cybertec Pty Ltd - Unit 11, 41 Higginbotham Road - Gladesville NSW 2111 - AUSTRALIA - - 00-20-DE (hex) JAPAN DIGITAL LABORAT'Y CO.LTD - 0020DE (base 16) JAPAN DIGITAL LABORAT'Y CO.LTD - JDL KAWASAKI R & D CENTER - 10-1 MINAMI-KUROKAWA ASAO-KU, KAWASKAKI- - KANAGAWA-KEN 215 - JAPAN - - 00-20-DF (hex) KYOSAN ELECTRIC MFG. CO., LTD. - 0020DF (base 16) KYOSAN ELECTRIC MFG. CO., LTD. - 2-29, HEIAN-CHO, TSURUMI-KU - YOKOHAMA, 230 - JAPAN - - 00-20-E0 (hex) Actiontec Electronics, Inc. - 0020E0 (base 16) Actiontec Electronics, Inc. - 760 North Mary Ave. - Sunnyvale. CA 94085 - UNITED STATES - - 00-20-E1 (hex) ALAMAR ELECTRONICS - 0020E1 (base 16) ALAMAR ELECTRONICS - 489 DIVISION STREET - CAMPBELL CA 95008 - UNITED STATES - - 00-20-E2 (hex) INFORMATION RESOURCE ENGINEERING - 0020E2 (base 16) INFORMATION RESOURCE ENGINEERING - 8029 CORPORATE DRIVE - BALTIMORE MD 21236 - UNITED STATES - - 00-20-E3 (hex) MCD KENCOM CORPORATION - 0020E3 (base 16) MCD KENCOM CORPORATION - 20950 CASTLE ROCK ROAD - LAGUNA BEACH CA 92651-1115 - UNITED STATES - - 00-20-E4 (hex) HSING TECH ENTERPRISE CO., LTD - 0020E4 (base 16) HSING TECH ENTERPRISE CO., LTD - NO. 2, LANE 128, SEC. 2 - CHUNG SHAN N. RD. - TEIPEI, - TAIWAN, PROVINCE OF CHINA - - 00-20-E5 (hex) APEX DATA, INC. - 0020E5 (base 16) APEX DATA, INC. - 6624 OWENS DRIVE - PLEASANTON CA 94588 - UNITED STATES - - 00-20-E6 (hex) LIDKOPING MACHINE TOOLS AB - 0020E6 (base 16) LIDKOPING MACHINE TOOLS AB - BOX 910 - 531 19 LIDKOPING - SWEDEN - - 00-20-E7 (hex) B&W NUCLEAR SERVICE COMPANY - 0020E7 (base 16) B&W NUCLEAR SERVICE COMPANY - SPECIAL PRODUCTS & INTEG.SVCS. - 155 MILL RIDGE ROAD - LYNCHBURG VA 24502 - UNITED STATES - - 00-20-E8 (hex) DATATREK CORPORATION - 0020E8 (base 16) DATATREK CORPORATION - 4505 WYLAND DRIVE - ELKHART IN 46516 - UNITED STATES - - 00-20-E9 (hex) DANTEL - 0020E9 (base 16) DANTEL - P.O. BOX 55013 - 2991 NORTH ARGYLE AVE. - FRESNO CA 93727-1388 - UNITED STATES - - 00-20-EA (hex) EFFICIENT NETWORKS, INC. - 0020EA (base 16) EFFICIENT NETWORKS, INC. - 4201 SPRING VALLEY ROAD - SUITE #1200 - DALLAS TX 75244-3666 - UNITED STATES - - 00-20-EB (hex) CINCINNATI MICROWAVE, INC. - 0020EB (base 16) CINCINNATI MICROWAVE, INC. - ONE MICROWAVE PLAZA - CINCINNATI OH 45249 - UNITED STATES - - 00-20-EC (hex) TECHWARE SYSTEMS CORP. - 0020EC (base 16) TECHWARE SYSTEMS CORP. - #100 - 12051 HORSESHOE WAY - RICHMOND, B.C. CANADA - V7A 4V4 - CANADA - - 00-20-ED (hex) GIGA-BYTE TECHNOLOGY CO., LTD. - 0020ED (base 16) GIGA-BYTE TECHNOLOGY CO., LTD. - 365 CLOVERLEAF - BALDWIN PARK CA 91706 - UNITED STATES - - 00-20-EE (hex) GTECH CORPORATION - 0020EE (base 16) GTECH CORPORATION - 55 TECHNOLOGY WAY - WEST GREENWICH RI 02817 - UNITED STATES - - 00-20-EF (hex) USC CORPORATION - 0020EF (base 16) USC CORPORATION - 6-4, OSAKI 1-CHOME - SHINAGAWA-KU TOKYO, - 141 - JAPAN - - 00-20-F0 (hex) UNIVERSAL MICROELECTRONICS CO. - 0020F0 (base 16) UNIVERSAL MICROELECTRONICS CO. - 3, 27TH RD., TAICHUNG IND.PARK - TAICHUN - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-F1 (hex) ALTOS INDIA LIMITED - 0020F1 (base 16) ALTOS INDIA LIMITED - D-60, OKLHLA INDUSTRIAL - AREA, PHASE 1 NEW DELHI -110020 - INDIA - - 00-20-F2 (hex) Oracle Corporation - 0020F2 (base 16) Oracle Corporation - 500 Oracle Parkway - Redwood Shores CA 95065 - UNITED STATES - - 00-20-F3 (hex) RAYNET CORPORATION - 0020F3 (base 16) RAYNET CORPORATION - 155 CONSTITUTION DRIVE - MENLO PARK CA 94025 - UNITED STATES - - 00-20-F4 (hex) SPECTRIX CORPORATION - 0020F4 (base 16) SPECTRIX CORPORATION - 106 WILMOT ROAD, SUITE 250 - DEERFIELD IL 60015-5150 - UNITED STATES - - 00-20-F5 (hex) PANDATEL AG - 0020F5 (base 16) PANDATEL AG - FASANENWEG 25 - D-22145 HAMBURG - GERMANY - - 00-20-F6 (hex) NET TEK AND KARLNET, INC. - 0020F6 (base 16) NET TEK AND KARLNET, INC. - LITTLE STREAMS - THE ABBOTSBROOK, BOURNE END BUCKS, SL8 5 - UNITED KINGDOM - UNITED KINGDOM - - 00-20-F7 (hex) CYBERDATA CORPORATION - 0020F7 (base 16) CYBERDATA CORPORATION - 3 Justin Court - MONTEREY CA 93940 - UNITED STATES - - 00-20-F8 (hex) CARRERA COMPUTERS, INC. - 0020F8 (base 16) CARRERA COMPUTERS, INC. - 23181 VERDUGO DRIVE-STE.#105A - LAGUNA HILLS CA 92653 - UNITED STATES - - 00-20-F9 (hex) PARALINK NETWORKS, INC. - 0020F9 (base 16) PARALINK NETWORKS, INC. - 4F, NO. 27, SEC.3, PATEH RD. - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-20-FA (hex) GDE SYSTEMS, INC. - 0020FA (base 16) GDE SYSTEMS, INC. - P.O. BOX 85468 - BLDG.#61 - SAN DIEGO CA 92186-5468 - UNITED STATES - - 00-20-FB (hex) OCTEL COMMUNICATIONS CORP. - 0020FB (base 16) OCTEL COMMUNICATIONS CORP. - 1001 MURPHY RANCH RD - MILPITAS CA 95035 - UNITED STATES - - 00-20-FC (hex) MATROX - 0020FC (base 16) MATROX - 1055 ST. REGIS, - DORVAL, QUEBEC H9P-2T4 - CANADA - - 00-20-FD (hex) ITV TECHNOLOGIES, INC. - 0020FD (base 16) ITV TECHNOLOGIES, INC. - 6800 OWENSMOUTH AVE. #230 - CANOGA PARK CA 91303 - UNITED STATES - - 00-20-FE (hex) TOPWARE INC. / GRAND COMPUTER - 0020FE (base 16) TOPWARE INC. / GRAND COMPUTER - CORPORATION - B1, NO. 9, LANE 50 SECTION 3, NAN KANG R - TAIPEI R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-20-FF (hex) SYMMETRICAL TECHNOLOGIES - 0020FF (base 16) SYMMETRICAL TECHNOLOGIES - 500 HUNTMAR PARK DRIVE - HERNDON VA 22070 - UNITED STATES - - 00-21-00 (hex) GemTek Technology Co., Ltd. - 002100 (base 16) GemTek Technology Co., Ltd. - No.1 Jen Ai Road, Hsinchu Industrial Park, - Hukou, Hsinchu 303 - TAIWAN, PROVINCE OF CHINA - - 00-21-01 (hex) Aplicaciones Electronicas Quasar (AEQ) - 002101 (base 16) Aplicaciones Electronicas Quasar (AEQ) - C/Rey Pastor 40 - Poligono Industrial Butarque - Leganes Madrid 28914 - SPAIN - - 00-21-02 (hex) UpdateLogic Inc. - 002102 (base 16) UpdateLogic Inc. - 2 Willow Street, Suite 101 - Southborough MA 01745 - UNITED STATES - - 00-21-03 (hex) GHI Electronics, LLC - 002103 (base 16) GHI Electronics, LLC - 35555 Garfield Rd. - Suite 4B - Clinton Township MI 48035 - UNITED STATES - - 00-21-04 (hex) Gigaset Communications GmbH - 002104 (base 16) Gigaset Communications GmbH - Frankenstrasse 2 - 46395 Bocholt - GERMANY - - 00-21-05 (hex) Alcatel-Lucent - 002105 (base 16) Alcatel-Lucent - 701 E. Middlefield Rd. - Mountain View CA 94043 - UNITED STATES - - 00-21-06 (hex) RIM Testing Services - 002106 (base 16) RIM Testing Services - 440 Phillip Street - Waterloo ON N2L 5R9 - CANADA - - 00-21-07 (hex) Seowonintech Co Ltd. - 002107 (base 16) Seowonintech Co Ltd. - 689-47 Geumjeongdong - Gunposi Kyoungkido 436-862 - KOREA, REPUBLIC OF - - 00-21-08 (hex) Nokia Danmark A/S - 002108 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-21-09 (hex) Nokia Danmark A/S - 002109 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-21-0A (hex) byd:sign Corporation - 00210A (base 16) byd:sign Corporation - 2-10-6 Tsukiji - BPS SQUARE 2F - Chuo-ku Tokyo 104-0045 - JAPAN - - 00-21-0B (hex) GEMINI TRAZE RFID PVT. LTD. - 00210B (base 16) GEMINI TRAZE RFID PVT. LTD. - 1, DR. RANGA ROAD - ALWARPET - CHENNAI TAMILNADU 600018 - INDIA - - 00-21-0C (hex) Cymtec Systems, Inc. - 00210C (base 16) Cymtec Systems, Inc. - 10845 Olive Bouleveard - Suite 306 - St Louis MO 63141 - UNITED STATES - - 00-21-0D (hex) SAMSIN INNOTEC - 00210D (base 16) SAMSIN INNOTEC - SARIYUNDONG ILSANDONG-GU - 252-23 - GOYANG KYUNGGI 411530 - KOREA, REPUBLIC OF - - 00-21-0E (hex) Orpak Systems L.T.D. - 00210E (base 16) Orpak Systems L.T.D. - 31 Lechi St - Bnei - Brak 51114 - ISRAEL - - 00-21-0F (hex) Cernium Corp - 00210F (base 16) Cernium Corp - 1943 Isaac Newton Sq - Suite 200 - Reston VA 20190 - UNITED STATES - - 00-21-10 (hex) Clearbox Systems - 002110 (base 16) Clearbox Systems - Suite 2, Level 2 - 67 Epping Rd - Macquarie Park NSW 2113 - AUSTRALIA - - 00-21-11 (hex) Uniphone Inc. - 002111 (base 16) Uniphone Inc. - 795 Main Street - Half Moon Bay CA 94019 - UNITED STATES - - 00-21-12 (hex) WISCOM SYSTEM CO.,LTD - 002112 (base 16) WISCOM SYSTEM CO.,LTD - 100 Jiangjun Road,Jiangning, - Nanjing 211100 - CHINA - - 00-21-13 (hex) Padtec S/A - 002113 (base 16) Padtec S/A - Road Campinas Mogi-Mirim km 118,5 - Campinas São Paulo 13086-902 - BRAZIL - - 00-21-14 (hex) Hylab Technology Inc. - 002114 (base 16) Hylab Technology Inc. - 15F-2.,No.872,Jhongjheng Rd. - Jhonghe City, Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-21-15 (hex) PHYWE Systeme GmbH & Co. KG - 002115 (base 16) PHYWE Systeme GmbH & Co. KG - Robert-Bosch-Breite 10 - Goettingen Niedersachsen 37079 - GERMANY - - 00-21-16 (hex) Transcon Electronic Systems, spol. s r. o. - 002116 (base 16) Transcon Electronic Systems, spol. s r. o. - Kvapilova 2133 - Frydek-Mistek 73802 - CZECH REPUBLIC - - 00-21-17 (hex) Tellord - 002117 (base 16) Tellord - Gurogu Gurodong 170-5 Woolim e-Biz Center 709 - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-21-18 (hex) Athena Tech, Inc. - 002118 (base 16) Athena Tech, Inc. - 3721 Macintosh Dr - Vint Hill Tech Park - Warrenton VA 20187 - UNITED STATES - - 00-21-19 (hex) Samsung Electro-Mechanics - 002119 (base 16) Samsung Electro-Mechanics - 314, Metan 3 dong - Suwon Kyung-gi do 443-743 - KOREA, REPUBLIC OF - - 00-21-1A (hex) LInTech Corporation - 00211A (base 16) LInTech Corporation - Krasnokazarmennaya st., 12 - Moscow 111250 - RUSSIAN FEDERATION - - 00-21-1B (hex) CISCO SYSTEMS, INC. - 00211B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-1C (hex) CISCO SYSTEMS, INC. - 00211C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-1D (hex) Dataline AB - 00211D (base 16) Dataline AB - Katrinedalsgatan 53 - BorÃ¥s S-50451 - SWEDEN - - 00-21-1E (hex) ARRIS Group, Inc. - 00211E (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-21-1F (hex) SHINSUNG DELTATECH CO.,LTD. - 00211F (base 16) SHINSUNG DELTATECH CO.,LTD. - 44-10 - UNGNAM-DONG - CHANGWON-CITY KYUNGNAM-DO 641-290 - KOREA, REPUBLIC OF - - 00-21-20 (hex) Sequel Technologies - 002120 (base 16) Sequel Technologies - 2951 Cleveland Ave N - Roseville MN 55113 - UNITED STATES - - 00-21-21 (hex) VRmagic GmbH - 002121 (base 16) VRmagic GmbH - Augustaanlage 32 - Mannheim BW 68165 - GERMANY - - 00-21-22 (hex) Chip-pro Ltd. - 002122 (base 16) Chip-pro Ltd. - 5F.-4, No.63, Siwei Rd., North District, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-21-23 (hex) Aerosat Avionics - 002123 (base 16) Aerosat Avionics - 62 State Rd. - 101A Suite 2B - Amherst NH 03031 - UNITED STATES - - 00-21-24 (hex) Optos Plc - 002124 (base 16) Optos Plc - Queensferry House - Carnegie Business Campus - Dunfermline Fife KY11 8GR - UNITED KINGDOM - - 00-21-25 (hex) KUK JE TONG SHIN Co.,LTD - 002125 (base 16) KUK JE TONG SHIN Co.,LTD - 476-3 - JakJeon-Dong, - Incheon Kwangyouk-Si 407-060 - KOREA, REPUBLIC OF - - 00-21-26 (hex) Shenzhen Torch Equipment Co., Ltd. - 002126 (base 16) Shenzhen Torch Equipment Co., Ltd. - Floor 5, Block 3, Liming Industrial District, Zhongshanyuan Road, Nanshan, - Shenzhen Guangdong 518052 - CHINA - - 00-21-27 (hex) TP-LINK Technology Co., Ltd. - 002127 (base 16) TP-LINK Technology Co., Ltd. - South Building, No.5 Keyuan Road, Central Zone, - Science & Technology Park,Nanshan - Shenzhen Guangdong 518000 - CHINA - - 00-21-28 (hex) Oracle Corporation - 002128 (base 16) Oracle Corporation - 17 Network Circle - Building 17, UMPK17-131 - Menlo Park CA 95025 - UNITED STATES - - 00-21-29 (hex) Cisco-Linksys, LLC - 002129 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92617 - UNITED STATES - - 00-21-2A (hex) Audiovox Corporation - 00212A (base 16) Audiovox Corporation - 150 Marcus Blvd - Hauppauge NY 11788 - UNITED STATES - - 00-21-2B (hex) MSA Auer - 00212B (base 16) MSA Auer - Thiemannstraße 1 - Berlin 12059 - GERMANY - - 00-21-2C (hex) SemIndia System Private Limited - 00212C (base 16) SemIndia System Private Limited - No. 1106/9, A.M Industrial Estate, Garvebhavipalya - 7th mile, Hosur Road - Bangalore Karnataka 560 068 - INDIA - - 00-21-2D (hex) SCIMOLEX CORPORATION - 00212D (base 16) SCIMOLEX CORPORATION - 2430, Saijou, Showa-cho - Nakakoma-gun, Yamanashi 409-3866 - JAPAN - - 00-21-2E (hex) dresden-elektronik - 00212E (base 16) dresden-elektronik - Enno-Heidebroek-Str. 12 - Dresden Saxony D-01237 - GERMANY - - 00-21-2F (hex) Phoebe Micro Inc. - 00212F (base 16) Phoebe Micro Inc. - 47606 Kato Rd - Fremont CA 94538 - UNITED STATES - - 00-21-30 (hex) Keico Hightech Inc. - 002130 (base 16) Keico Hightech Inc. - Ace twin tower I, 12th Fl. - 212-1, Guro-dong, guro-gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-21-31 (hex) Blynke Inc. - 002131 (base 16) Blynke Inc. - 133 Richmond St. West - Suite 600 - Toronto Ontario M5H 2L3 - CANADA - - 00-21-32 (hex) Masterclock, Inc. - 002132 (base 16) Masterclock, Inc. - 2484 West Clay St. - St. Charles MO 63301 - UNITED STATES - - 00-21-33 (hex) Building B, Inc - 002133 (base 16) Building B, Inc - 1000 NW 65th Street, Suite 300 - Ft. Lauderdale FL 33309 - UNITED STATES - - 00-21-34 (hex) Brandywine Communications - 002134 (base 16) Brandywine Communications - 1153 Warner Ave - Tustin CA 92780 - UNITED STATES - - 00-21-35 (hex) ALCATEL-LUCENT - 002135 (base 16) ALCATEL-LUCENT - Ramirez de Prado 5 - Madrid 28045 - SPAIN - - 00-21-36 (hex) ARRIS Group, Inc. - 002136 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-21-37 (hex) Bay Controls, LLC - 002137 (base 16) Bay Controls, LLC - 6528 Weatherfield Ct - Maumee OH 43537 - UNITED STATES - - 00-21-38 (hex) Cepheid - 002138 (base 16) Cepheid - 904 Caribbean Drive - Sunnyvale CA 94089 - UNITED STATES - - 00-21-39 (hex) Escherlogic Inc. - 002139 (base 16) Escherlogic Inc. - 1481 Rosebank Rd. - Pickering Ontario L1V 1P3 - CANADA - - 00-21-3A (hex) Winchester Systems Inc. - 00213A (base 16) Winchester Systems Inc. - 101 Billerica Avenue - Bldg 5 suite 101 - Billerica, MA 01862 - UNITED STATES - - 00-21-3B (hex) Berkshire Products, Inc - 00213B (base 16) Berkshire Products, Inc - PO Box 2819 - Cumming GA 30028 - UNITED STATES - - 00-21-3C (hex) AliphCom - 00213C (base 16) AliphCom - 150 Executive Park Blvd - Suite 4550 - San Francisco CA 94134 - UNITED STATES - - 00-21-3D (hex) Cermetek Microelectronics, Inc. - 00213D (base 16) Cermetek Microelectronics, Inc. - 374 Turquoise Street - Milpitas CA 95035 - UNITED STATES - - 00-21-3E (hex) TomTom - 00213E (base 16) TomTom - Oosterdoksstraat 114 - Amsterdam North Holland 1011 DK - NETHERLANDS - - 00-21-3F (hex) A-Team Technology Ltd. - 00213F (base 16) A-Team Technology Ltd. - Rm. 1608, 16/F., Metropole Square, - 2 On Yiu St., Shatin, - New Territories, - HONG KONG - - 00-21-40 (hex) EN Technologies Inc. - 002140 (base 16) EN Technologies Inc. - Geumbok Bldg. 9F, Band-yi-dong 45-2, Songpa-gu - Seoul 138-828 - KOREA, REPUBLIC OF - - 00-21-41 (hex) RADLIVE - 002141 (base 16) RADLIVE - 4 Hanechoshet St. - Tel Aviv 69710 - ISRAEL - - 00-21-42 (hex) Advanced Control Systems doo - 002142 (base 16) Advanced Control Systems doo - Bulevar Zorana Djindjica 8a - Belgrade Serbia 11070 - - 00-21-43 (hex) ARRIS Group, Inc. - 002143 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-21-44 (hex) SS Telecoms - 002144 (base 16) SS Telecoms - 23 Botha Avenue - Lyttelton Manor - Centurion Gauteng 0140 - SOUTH AFRICA - - 00-21-45 (hex) Semptian Technologies Ltd. - 002145 (base 16) Semptian Technologies Ltd. - No. 809, Tower B, Shi Ji Ke Mao - No. 66 Rd. Zhongguan Cun Dong - Beijing 100190 - CHINA - - 00-21-46 (hex) Sanmina-SCI - 002146 (base 16) Sanmina-SCI - 13000 South Memorial Parkway - Huntsville AL 35803 - UNITED STATES - - 00-21-47 (hex) Nintendo Co., Ltd. - 002147 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-21-48 (hex) Kaco Solar Korea - 002148 (base 16) Kaco Solar Korea - Chung-won-ku Sang-dea-won-dong 333-1 - Songnam Kyung-kido 462-806 - KOREA, REPUBLIC OF - - 00-21-49 (hex) China Daheng Group ,Inc. - 002149 (base 16) China Daheng Group ,Inc. - 12F Daheng Science & Technology Tower ,NO.3 Suzhou Str. - Beijing 100080 - CHINA - - 00-21-4A (hex) Pixel Velocity, Inc - 00214A (base 16) Pixel Velocity, Inc - 3917 Research Park Dr. - Suite B7 - Ann Arbor MI 48108 - UNITED STATES - - 00-21-4B (hex) Shenzhen HAMP Science & Technology Co.,Ltd - 00214B (base 16) Shenzhen HAMP Science & Technology Co.,Ltd - No.302-303,3 Floor,District A,TCL Tower,Gaoxin Nan Yi Road,NanShan District - Shenzhen Guangdong 518057 - CHINA - - 00-21-4C (hex) SAMSUNG ELECTRONICS CO., LTD. - 00214C (base 16) SAMSUNG ELECTRONICS CO., LTD. - 416, METAN-3DONG, - YOUNGTONG-GU - SUWON KYUNGKI-DO 442-742 - KOREA, REPUBLIC OF - - 00-21-4D (hex) Guangzhou Skytone Transmission Technology Com. Ltd. - 00214D (base 16) Guangzhou Skytone Transmission Technology Com. Ltd. - 3/F West, Block 4, Huangzhou - Industrial Park, Chebei Road. - Guangzhou Guangdong 510660 - CHINA - - 00-21-4E (hex) GS Yuasa Power Supply Ltd. - 00214E (base 16) GS Yuasa Power Supply Ltd. - 1, Inobanba-cho, Nishinosho, Kisshoin, Minami-ku, - Kyoto 601-8520 - JAPAN - - 00-21-4F (hex) ALPS Electric Co., Ltd - 00214F (base 16) ALPS Electric Co., Ltd - 1-2-1, Okinouchi - Soma city Fukushima 976-8501 - JAPAN - - 00-21-50 (hex) EYEVIEW ELECTRONICS - 002150 (base 16) EYEVIEW ELECTRONICS - 3 Floor, No. 86, Kung Yeh 32 Road - TAICHUNG 407 - TAIWAN, PROVINCE OF CHINA - - 00-21-51 (hex) Millinet Co., Ltd. - 002151 (base 16) Millinet Co., Ltd. - 2F, West Building, IT Venture Tower, 78, Garakbon-Dong - Songpa-gu Seoul 138-803 - KOREA, REPUBLIC OF - - 00-21-52 (hex) General Satellite Research & Development Limited - 002152 (base 16) General Satellite Research & Development Limited - Lit. "E", building 2, 4 Novoladozhskaya str - Saint Petersburg 197110 - RUSSIAN FEDERATION - - 00-21-53 (hex) SeaMicro Inc. - 002153 (base 16) SeaMicro Inc. - 3250 Jay Street - Santa Clara CA 95054 - UNITED STATES - - 00-21-54 (hex) D-TACQ Solutions Ltd - 002154 (base 16) D-TACQ Solutions Ltd - James Watt Building - SETP - East Kilbride Lanarkshire G75 0QD - UNITED KINGDOM - - 00-21-55 (hex) CISCO SYSTEMS, INC. - 002155 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-56 (hex) CISCO SYSTEMS, INC. - 002156 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-57 (hex) National Datacast, Inc. - 002157 (base 16) National Datacast, Inc. - 2100 Crystal Drive, Suite 750 - Arlington VA 22202 - UNITED STATES - - 00-21-58 (hex) Style Flying Technology Co. - 002158 (base 16) Style Flying Technology Co. - 22/F,Cyber Tower B,No.2 Zhong Guan Cun South Street,Haidian District, - Beijing 100086 - CHINA - - 00-21-59 (hex) Juniper Networks - 002159 (base 16) Juniper Networks - 1194 N. Mathilda Ave - Sunnyvale CA 94089 - UNITED STATES - - 00-21-5A (hex) Hewlett-Packard Company - 00215A (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040802 - Houston TX 77070 - UNITED STATES - - 00-21-5B (hex) Inotive - 00215B (base 16) Inotive - De Pinckart 54 - Nuenen Noord Brabant 5674 CC - NETHERLANDS - - 00-21-5C (hex) Intel Corporate - 00215C (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-21-5D (hex) Intel Corporate - 00215D (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-21-5E (hex) IBM Corp - 00215E (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-21-5F (hex) IHSE GmbH - 00215F (base 16) IHSE GmbH - Maybachstraße 11 - Oberteuringen Baden-Württemberg 88094 - GERMANY - - 00-21-60 (hex) Hidea Solutions Co. Ltd. - 002160 (base 16) Hidea Solutions Co. Ltd. - 4F, Do&Can house Dldg., #656-1683, Seongsu 1-ga 2-dong, Seongdong-gu - Seoul 656-1683 - KOREA, REPUBLIC OF - - 00-21-61 (hex) Yournet Inc. - 002161 (base 16) Yournet Inc. - KT R&D Center - 17 Umyeon-dong, Seocho-gu - Seoul 137-792 - KOREA, REPUBLIC OF - - 00-21-62 (hex) Nortel - 002162 (base 16) Nortel - 1830 Matheson Boulevard - Suite 1 - Mississauga Ontario L4W 0B3 - CANADA - - 00-21-63 (hex) ASKEY COMPUTER CORP - 002163 (base 16) ASKEY COMPUTER CORP - 10F,NO.119.CHIENKANG RD,CHUNG-HO, - TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - 00-21-64 (hex) Special Design Bureau for Seismic Instrumentation - 002164 (base 16) Special Design Bureau for Seismic Instrumentation - 129, Krainyaya Str. - Saratov Saratov region 410019 - RUSSIAN FEDERATION - - 00-21-65 (hex) Presstek Inc. - 002165 (base 16) Presstek Inc. - 55 Executive Drive - Hudson New Hampshire 03051 - UNITED STATES - - 00-21-66 (hex) NovAtel Inc. - 002166 (base 16) NovAtel Inc. - 1120 - 68 Ave NE - Calgary Alberta T2E 8S5 - CANADA - - 00-21-67 (hex) HWA JIN T&I Corp. - 002167 (base 16) HWA JIN T&I Corp. - 5F., SEHWA Bldg 164-24, Poi-dong, Gangnam-gu, Seoul, Korea - Gangnam-gu Seoul 135-960 - KOREA, REPUBLIC OF - - 00-21-68 (hex) iVeia, LLC - 002168 (base 16) iVeia, LLC - 51 Franklin Street - Suite 301 - Annapolis MD 21401 - UNITED STATES - - 00-21-69 (hex) Prologix, LLC. - 002169 (base 16) Prologix, LLC. - 17217 NE 133rd Place - Redmond Washington 98052-2153 - UNITED STATES - - 00-21-6A (hex) Intel Corporate - 00216A (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-21-6B (hex) Intel Corporate - 00216B (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-21-6C (hex) ODVA - 00216C (base 16) ODVA - 4220 Varsity Drive - Suite A - Ann Arbor MI 48108-5006 - UNITED STATES - - 00-21-6D (hex) Soltech Co., Ltd. - 00216D (base 16) Soltech Co., Ltd. - #30-3,3F - Wonhyoro2-Ka - Yongsan Ku Seoul 140837 - KOREA, REPUBLIC OF - - 00-21-6E (hex) Function ATI (Huizhou) Telecommunications Co., Ltd. - 00216E (base 16) Function ATI (Huizhou) Telecommunications Co., Ltd. - No. 8, Huitai Road, Huitai Industrial Zone - Huizhou City Guangdong Province 516006 - CHINA - - 00-21-6F (hex) SymCom, Inc. - 00216F (base 16) SymCom, Inc. - 2880 North Plaza Drive - Rapid City SD 57702 - UNITED STATES - - 00-21-70 (hex) Dell Inc - 002170 (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-21-71 (hex) Wesung TNC Co., Ltd. - 002171 (base 16) Wesung TNC Co., Ltd. - 102-1409, Bucheon Chunui Technopark 1st, - 200-1, Chunui-dong, Wonmi-Gu - Bucheon-City, Gyeongggi-Do 420-857 - KOREA, REPUBLIC OF - - 00-21-72 (hex) Seoultek Valley - 002172 (base 16) Seoultek Valley - Bang-i Dong 51-5, Songpa - Seoul 138-050 - KOREA, REPUBLIC OF - - 00-21-73 (hex) Ion Torrent Systems, Inc. - 002173 (base 16) Ion Torrent Systems, Inc. - 37 Soundview Rd - Suite 2 - Guilford CT 06437 - UNITED STATES - - 00-21-74 (hex) AvaLAN Wireless - 002174 (base 16) AvaLAN Wireless - 958 San Leandro Ave, Suite 900 - Mountain View CA 94043 - UNITED STATES - - 00-21-75 (hex) Pacific Satellite International Ltd. - 002175 (base 16) Pacific Satellite International Ltd. - 20/F Tai Tung Building, - 8 Fleming Road, - Wanchai 100000 - HONG KONG - - 00-21-76 (hex) YMax Telecom Ltd. - 002176 (base 16) YMax Telecom Ltd. - 11 Moshe Levi str. - UMI Building - Rishon Le Zion 75658 - ISRAEL - - 00-21-77 (hex) W. L. Gore & Associates - 002177 (base 16) W. L. Gore & Associates - 402 Vieves Way - Elkton MD 21921 - UNITED STATES - - 00-21-78 (hex) Matuschek Messtechnik GmbH - 002178 (base 16) Matuschek Messtechnik GmbH - Werner Heisenberg Straße 14 - Alsdorf NRW 52477 - GERMANY - - 00-21-79 (hex) IOGEAR, Inc. - 002179 (base 16) IOGEAR, Inc. - 23 Hubble - Irvine CA 92618 - UNITED STATES - - 00-21-7A (hex) Sejin Electron, Inc. - 00217A (base 16) Sejin Electron, Inc. - SJ Technoville - 4th Floor Room 412, 60-19 KaSan-Dong, KeumChon-Ku - Seoul 153-801 - KOREA, REPUBLIC OF - - 00-21-7B (hex) Bastec AB - 00217B (base 16) Bastec AB - Hästvägen 4A - Malmö SE 212 35 - SWEDEN - - 00-21-7C (hex) 2Wire - 00217C (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-21-7D (hex) PYXIS S.R.L. - 00217D (base 16) PYXIS S.R.L. - C/O DIP. INFORMATICA E SISTEMISTICA - UNIVERSITY OF PAVIA - VIA FERRATA 1 - PAVIA 27100 - ITALY - - 00-21-7E (hex) Telit Communication s.p.a - 00217E (base 16) Telit Communication s.p.a - Via stazione di prosecco 5B - SGONICO Trieste 34010 - ITALY - - 00-21-7F (hex) Intraco Technology Pte Ltd - 00217F (base 16) Intraco Technology Pte Ltd - 750e Chai Chee Road #05-01 - Singapore 4690005 - SINGAPORE - - 00-21-80 (hex) ARRIS Group, Inc. - 002180 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-21-81 (hex) Si2 Microsystems Limited - 002181 (base 16) Si2 Microsystems Limited - No 84, Sy No 150, EPIP, Whitefield Industrial Area - Bangalore Karnataka 560066 - INDIA - - 00-21-82 (hex) SandLinks Systems, Ltd. - 002182 (base 16) SandLinks Systems, Ltd. - P.O.Box 4629 - Petah-Tiqwa Israel 49277 - ISRAEL - - 00-21-83 (hex) VATECH HYDRO - 002183 (base 16) VATECH HYDRO - Wienerbergstrasse 41 - Object D - Vienna A-1120 - AUSTRIA - - 00-21-84 (hex) POWERSOFT SRL - 002184 (base 16) POWERSOFT SRL - VIA ENRICO CONTI, 5 - SCANDICCI FI 50018 - ITALY - - 00-21-85 (hex) MICRO-STAR INT'L CO.,LTD. - 002185 (base 16) MICRO-STAR INT'L CO.,LTD. - No.69,Li-De St,Jung-Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-21-86 (hex) Universal Global Scientific Industrial Co., Ltd - 002186 (base 16) Universal Global Scientific Industrial Co., Ltd - 141, Lane 351, Sec.1, Taiping Road, - TSAOTUEN - NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 00-21-87 (hex) Imacs GmbH - 002187 (base 16) Imacs GmbH - Mittelfeldstrasse 25 - Kornwestheim Germany D-70806 - GERMANY - - 00-21-88 (hex) EMC Corporation - 002188 (base 16) EMC Corporation - 2421 Mission College Blvd - Santa Clara CA 95050 - UNITED STATES - - 00-21-89 (hex) AppTech, Inc. - 002189 (base 16) AppTech, Inc. - 363 E Greyhound Pass - Carmel Indiana 46032 - UNITED STATES - - 00-21-8A (hex) Electronic Design and Manufacturing Company - 00218A (base 16) Electronic Design and Manufacturing Company - 31 Millrace Dr - Lynchburg VA 24502 - UNITED STATES - - 00-21-8B (hex) Wescon Technology, Inc. - 00218B (base 16) Wescon Technology, Inc. - 4655-170 Old Ironsides Drive - Santa Clara California 95054 - UNITED STATES - - 00-21-8C (hex) TopControl GMBH - 00218C (base 16) TopControl GMBH - Enzenbergweg 24/A - Terlan (BZ) 39018 - ITALY - - 00-21-8D (hex) AP Router Ind. Eletronica LTDA - 00218D (base 16) AP Router Ind. Eletronica LTDA - Av. Lomanto Junior, 1000 - Bairro Pontal - Ilheus Bahia 45654-000 - BRAZIL - - 00-21-8E (hex) MEKICS CO., LTD. - 00218E (base 16) MEKICS CO., LTD. - Industrial Zone 861-10, Taegye-Dong - Chunchon Kangwon 200-944 - KOREA, REPUBLIC OF - - 00-21-8F (hex) Avantgarde Acoustic Lautsprechersysteme GmbH - 00218F (base 16) Avantgarde Acoustic Lautsprechersysteme GmbH - Nibelungenstraße 349 - Lautertal - Reichenbach Hessen D-64686 - GERMANY - - 00-21-90 (hex) Goliath Solutions - 002190 (base 16) Goliath Solutions - 3082 Sterling Circle - Boulder Colorado 80301 - UNITED STATES - - 00-21-91 (hex) D-Link Corporation - 002191 (base 16) D-Link Corporation - NO.289, Sinhu 3rd RD. - Neihu District Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-21-92 (hex) Baoding Galaxy Electronic Technology Co.,Ltd - 002192 (base 16) Baoding Galaxy Electronic Technology Co.,Ltd - NO.91 Fengfan Rd.,GaoKai District,Baoding City,Hebei Prov.China 071051 - Baoding City Hebei Prov. 071051 - CHINA - - 00-21-93 (hex) Videofon MV - 002193 (base 16) Videofon MV - 6 Blackoak Mews - Newtown PA 18940 - UNITED STATES - - 00-21-94 (hex) Ping Communication - 002194 (base 16) Ping Communication - Sandakerveien 24C - Oslo 0473 - NORWAY - - 00-21-95 (hex) GWD Media Limited - 002195 (base 16) GWD Media Limited - 10 Leeds Road - Sheffield South Yorkshire S9 3TY - UNITED KINGDOM - - 00-21-96 (hex) Telsey S.p.A. - 002196 (base 16) Telsey S.p.A. - Viale dell'Industria, 1 - Quinto DiTreviso 31055 - ITALY - - 00-21-97 (hex) ELITEGROUP COMPUTER SYSTEM - 002197 (base 16) ELITEGROUP COMPUTER SYSTEM - NO.239, Sec. 2, Ti Ding Blvd., - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 00-21-98 (hex) Thai Radio Co, LTD - 002198 (base 16) Thai Radio Co, LTD - Hi-Tech Industrial Estate - 787 M00 1 Baanlane Sub District Bang Pa-In District - Ayutthaya 13160 - THAILAND - - 00-21-99 (hex) Vacon Plc - 002199 (base 16) Vacon Plc - P.O.Box 25 - Vaasa 65380 - FINLAND - - 00-21-9A (hex) Cambridge Visual Networks Ltd - 00219A (base 16) Cambridge Visual Networks Ltd - 61 Selwyn Road - Cambridge Cambridgeshire CB3 9EA - UNITED KINGDOM - - 00-21-9B (hex) Dell Inc - 00219B (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-21-9C (hex) Honeywld Technology Corp. - 00219C (base 16) Honeywld Technology Corp. - No.40,Hsueh-Fu Rd. - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-21-9D (hex) Adesys BV - 00219D (base 16) Adesys BV - Molenweer 4 - Wateringen Zuid Holland 2291 NR - NETHERLANDS - - 00-21-9E (hex) Sony Ericsson Mobile Communications - 00219E (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-21-9F (hex) SATEL OY - 00219F (base 16) SATEL OY - Meriniitynkatu 17 - SALO Lansi-Suomen Laani 24100 - FINLAND - - 00-21-A0 (hex) CISCO SYSTEMS, INC. - 0021A0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-A1 (hex) CISCO SYSTEMS, INC. - 0021A1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-A2 (hex) EKE-Electronics Ltd. - 0021A2 (base 16) EKE-Electronics Ltd. - Piispanportti 7 - ESPOO 02240 - FINLAND - - 00-21-A3 (hex) Micromint - 0021A3 (base 16) Micromint - 111 Commerce St - Lake Mary FL 32746 - UNITED STATES - - 00-21-A4 (hex) Dbii Networks - 0021A4 (base 16) Dbii Networks - 2217 Via Blanca - Oceanside CA 92054 - UNITED STATES - - 00-21-A5 (hex) ERLPhase Power Technologies Ltd. - 0021A5 (base 16) ERLPhase Power Technologies Ltd. - 74 Scurfield Blvd. - Winnipeg Manitoba R3Y 1G4 - CANADA - - 00-21-A6 (hex) Videotec Spa - 0021A6 (base 16) Videotec Spa - Via Friuli,6 - Schio Vicenza 36015 - ITALY - - 00-21-A7 (hex) Hantle System Co., Ltd. - 0021A7 (base 16) Hantle System Co., Ltd. - 481-10 Byucksan Digital Vally II, RM 1511 - Gasan-Dong, Gumchon-Gu - Seoul City Seoul 153-783 - KOREA, REPUBLIC OF - - 00-21-A8 (hex) Telephonics Corporation - 0021A8 (base 16) Telephonics Corporation - 815 Broad Hollow Road - Farmingdale New York 11790 - UNITED STATES - - 00-21-A9 (hex) Mobilink Telecom Co.,Ltd - 0021A9 (base 16) Mobilink Telecom Co.,Ltd - 292-3 Sindang-ri, Sandong-myun - Gumi Gyeongbuk 730-853 - KOREA, REPUBLIC OF - - 00-21-AA (hex) Nokia Danmark A/S - 0021AA (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-21-AB (hex) Nokia Danmark A/S - 0021AB (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 V - DENMARK - - 00-21-AC (hex) Infrared Integrated Systems Ltd - 0021AC (base 16) Infrared Integrated Systems Ltd - Park Circle, Tithe Barn Way - Swan Valley - Northampton Northants NN4 9BG - UNITED KINGDOM - - 00-21-AD (hex) Nordic ID Oy - 0021AD (base 16) Nordic ID Oy - Myllyojankatu 2A - SALO FIN-24100 - FINLAND - - 00-21-AE (hex) ALCATEL-LUCENT FRANCE - WTD - 0021AE (base 16) ALCATEL-LUCENT FRANCE - WTD - 7-9, Avenue Morane Saulnier - BP 57 - VELIZY 78141 - FRANCE - - 00-21-AF (hex) Radio Frequency Systems - 0021AF (base 16) Radio Frequency Systems - Kabelkamp 20 - Hannover 30179 - GERMANY - - 00-21-B0 (hex) Tyco Telecommunications - 0021B0 (base 16) Tyco Telecommunications - 1011 Pawtucket Blvd - Lowell Massachusetts 01853 - UNITED STATES - - 00-21-B1 (hex) DIGITAL SOLUTIONS LTD - 0021B1 (base 16) DIGITAL SOLUTIONS LTD - Tsarigradsko Shose 7km BLVD - Hi Tech Park Izot, - Sofia Sofia 1784 - BULGARIA - - 00-21-B2 (hex) Fiberblaze A/S - 0021B2 (base 16) Fiberblaze A/S - Kildevangsvej 9 - Goederup - Roskilde 4000 - DENMARK - - 00-21-B3 (hex) Ross Controls - 0021B3 (base 16) Ross Controls - One Ross Way - Lavonia GA 30553 - UNITED STATES - - 00-21-B4 (hex) APRO MEDIA CO., LTD - 0021B4 (base 16) APRO MEDIA CO., LTD - #13-5,Dodang-Dong,Wonmi-Gu, - Bucheon-City Kyunggi-Do 420-801 - KOREA, REPUBLIC OF - - 00-21-B5 (hex) Galvanic Ltd - 0021B5 (base 16) Galvanic Ltd - 38 Nothumberland Road - Dublin 2 - IRELAND - - 00-21-B6 (hex) Triacta Power Technologies Inc. - 0021B6 (base 16) Triacta Power Technologies Inc. - Box 582, 7 Mill Street - Almonte Ontario K0A 1A0 - CANADA - - 00-21-B7 (hex) Lexmark International Inc. - 0021B7 (base 16) Lexmark International Inc. - 740 West New Circle Road - Lexington KY 40550 - UNITED STATES - - 00-21-B8 (hex) Inphi Corporation - 0021B8 (base 16) Inphi Corporation - 112 S. Lakeview Canyon Rd., Suite 100 - Westlake Village CA 91362 - UNITED STATES - - 00-21-B9 (hex) Universal Devices Inc. - 0021B9 (base 16) Universal Devices Inc. - 5353 Yarmouth Ave. #209 - Encino CA 91316 - UNITED STATES - - 00-21-BA (hex) Texas Instruments - 0021BA (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-21-BB (hex) Riken Keiki Co., Ltd. - 0021BB (base 16) Riken Keiki Co., Ltd. - 2-7-6 Azusawa - Itabashi-Ku Tokyo 174-8744 - JAPAN - - 00-21-BC (hex) ZALA COMPUTER - 0021BC (base 16) ZALA COMPUTER - EL BOUNI - ANNABA 23000 - ALGERIA - - 00-21-BD (hex) Nintendo Co., Ltd. - 0021BD (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-21-BE (hex) Cisco, Service Provider Video Technology Group - 0021BE (base 16) Cisco, Service Provider Video Technology Group - 5030 Sugarloaf Parkway - Mail Stop 2.T.603 - Lawrenceville GA 30044 - UNITED STATES - - 00-21-BF (hex) Hitachi High-Tech Control Systems Corporation - 0021BF (base 16) Hitachi High-Tech Control Systems Corporation - 500,Miyu-cho - Mito-shi Ibaraki-ken 319-0316 - JAPAN - - 00-21-C0 (hex) Mobile Appliance, Inc. - 0021C0 (base 16) Mobile Appliance, Inc. - #819 Kranz Techno, - Sangdaewon-1 Dong, Jungwon-Gu - Seong nam Gyeonggi-Do 462-729 - KOREA, REPUBLIC OF - - 00-21-C1 (hex) ABB Oy / Medium Voltage Products - 0021C1 (base 16) ABB Oy / Medium Voltage Products - PO Box 699 - Vaasa FI-65101 - FINLAND - - 00-21-C2 (hex) GL Communications Inc - 0021C2 (base 16) GL Communications Inc - 818 West Diamond Ave - Third Floor - Gaithersburg MD 20878 - UNITED STATES - - 00-21-C3 (hex) CORNELL Communications, Inc. - 0021C3 (base 16) CORNELL Communications, Inc. - 7915 N. 81st Street - Milwaukee Wisconsin 53223 - UNITED STATES - - 00-21-C4 (hex) Consilium AB - 0021C4 (base 16) Consilium AB - Västra Finnbodavägen 2-4 - Nacka Stockholm 13131 - SWEDEN - - 00-21-C5 (hex) 3DSP Corp - 0021C5 (base 16) 3DSP Corp - 16271 Laguna Canyon Road - Suite 200 - Irvine, CA 92618 - UNITED STATES - - 00-21-C6 (hex) CSJ Global, Inc. - 0021C6 (base 16) CSJ Global, Inc. - 9th Fl. Samwhan Bldg. Annex, 17-26 Yeouido-dong, - Youngdeungpo-Gu - Seoul 150-874 - KOREA, REPUBLIC OF - - 00-21-C7 (hex) Russound - 0021C7 (base 16) Russound - 5 Forbes Road - Newmarket NH 03857 - UNITED STATES - - 00-21-C8 (hex) LOHUIS Networks - 0021C8 (base 16) LOHUIS Networks - 2681 TV Monster - Votlaan 408 Votlaan 31 - NETHERLANDS - - 00-21-C9 (hex) Wavecom Asia Pacific Limited - 0021C9 (base 16) Wavecom Asia Pacific Limited - 201 Bio-Informatics Centre, No.2 Science Park West Ave - Hong Kong Science Park, Shatin, NT - HONG KONG - - 00-21-CA (hex) ART System Co., Ltd. - 0021CA (base 16) ART System Co., Ltd. - Mobile Techno Bldg Room 910 - 573-13, Bokhyeon-dong, Buk-gu - Dae-Gu 702-020 - KOREA, REPUBLIC OF - - 00-21-CB (hex) SMS TECNOLOGIA ELETRONICA LTDA - 0021CB (base 16) SMS TECNOLOGIA ELETRONICA LTDA - Av. Pirâmide, 661 - DIADEMA São Paulo 09970330 - BRAZIL - - 00-21-CC (hex) Flextronics International - 0021CC (base 16) Flextronics International - Stretton Green Distribution Centre Langford Way - Warrington Cheshire WA4 4TQ - UNITED KINGDOM - - 00-21-CD (hex) LiveTV - 0021CD (base 16) LiveTV - 1333 Gateway Drive, Suite 1007 - Melbourne Florida 32901 - UNITED STATES - - 00-21-CE (hex) NTC-Metrotek - 0021CE (base 16) NTC-Metrotek - 9, Nevzorovoy street - Saint-Petersburg 192148 - RUSSIAN FEDERATION - - 00-21-CF (hex) The Crypto Group - 0021CF (base 16) The Crypto Group - Zugerstrasse 42 - Steinhausen Zug 6312 - SWITZERLAND - - 00-21-D0 (hex) Global Display Solutions Spa - 0021D0 (base 16) Global Display Solutions Spa - Via Tezze, 20/A - VAT IT02940180249 - Cornedo Vicentino Vicenza 36073 - ITALY - - 00-21-D1 (hex) Samsung Electronics Co.,Ltd - 0021D1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-21-D2 (hex) Samsung Electronics Co.,Ltd - 0021D2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-21-D3 (hex) BOCOM SECURITY(ASIA PACIFIC) LIMITED - 0021D3 (base 16) BOCOM SECURITY(ASIA PACIFIC) LIMITED - Flr.3,NO.29,#69 Guiqing RD - China - Shanghai 200233 - CHINA - - 00-21-D4 (hex) Vollmer Werke GmbH - 0021D4 (base 16) Vollmer Werke GmbH - Maschinenfabrik - Biberach Baden-Württemberg 88400 - GERMANY - - 00-21-D5 (hex) X2E GmbH - 0021D5 (base 16) X2E GmbH - Raiffeisenstrasse 9 - Winden Rheinland-Pfalz 76872 - GERMANY - - 00-21-D6 (hex) LXI Consortium - 0021D6 (base 16) LXI Consortium - P.O. Box 1016 - Niwot CO 80544-1016 - UNITED STATES - - 00-21-D7 (hex) CISCO SYSTEMS, INC. - 0021D7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-D8 (hex) CISCO SYSTEMS, INC. - 0021D8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-21-D9 (hex) SEKONIC CORPORATION - 0021D9 (base 16) SEKONIC CORPORATION - 7-24-14 - OIZUMI-GAKUEN-CHO - NERIMA-KU TOKYO 178-8686 - JAPAN - - 00-21-DA (hex) Automation Products Group Inc. - 0021DA (base 16) Automation Products Group Inc. - 1025 West 1700 North - Logan Utah 84321 - UNITED STATES - - 00-21-DB (hex) Santachi Video Technology (Shenzhen) Co., Ltd. - 0021DB (base 16) Santachi Video Technology (Shenzhen) Co., Ltd. - Santachi Building,#14 Kaifeng Road,Meilin, - Shenzhen Guangdong 518049 - CHINA - - 00-21-DC (hex) TECNOALARM S.r.l. - 0021DC (base 16) TECNOALARM S.r.l. - Via Cirie' - San Mauro Torinese Torino 10099 - ITALY - - 00-21-DD (hex) Northstar Systems Corp - 0021DD (base 16) Northstar Systems Corp - 5F, No.200 Gang Qian Rd - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-21-DE (hex) Firepro Wireless - 0021DE (base 16) Firepro Wireless - 27, Zamrudpur Community Center, - Kailash Colony - New Delhi Haryana 110020 - INDIA - - 00-21-DF (hex) Martin Christ GmbH - 0021DF (base 16) Martin Christ GmbH - An der Unteren Soese 50 - Osterode Niedersachsen 37520 - GERMANY - - 00-21-E0 (hex) CommAgility Ltd - 0021E0 (base 16) CommAgility Ltd - Holywell Park - Loughborough Leics LE11 3AQ - UNITED KINGDOM - - 00-21-E1 (hex) Nortel Networks - 0021E1 (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson TX 75082-4399 - UNITED STATES - - 00-21-E2 (hex) Creative Electronic GmbH - 0021E2 (base 16) Creative Electronic GmbH - Lorcher Straße 52 - Birenbach Baden-Württemberg 73102 - GERMANY - - 00-21-E3 (hex) SerialTek LLC - 0021E3 (base 16) SerialTek LLC - 1570 Oakland Road - San Jose CA 95131 - UNITED STATES - - 00-21-E4 (hex) I-WIN - 0021E4 (base 16) I-WIN - 27 Rue des Econdeaux - EPINAY SUR SEINE Seine Saint Denis 93800 - FRANCE - - 00-21-E5 (hex) Display Solution AG - 0021E5 (base 16) Display Solution AG - Talhofstraße 32a - Gilching D 82205 - GERMANY - - 00-21-E6 (hex) Starlight Video Limited - 0021E6 (base 16) Starlight Video Limited - 5/F., Shing Dao Industrial Building, - 232 Aberdeen Main Road, - HONG KONG - - 00-21-E7 (hex) Informatics Services Corporation - 0021E7 (base 16) Informatics Services Corporation - 140, Negin Bldg., - Mirdamad Blvd - Tehran 1549534511 - IRAN, ISLAMIC REPUBLIC OF - - 00-21-E8 (hex) Murata Manufacturing Co., Ltd. - 0021E8 (base 16) Murata Manufacturing Co., Ltd. - 2288, Oaza-Ohshinohara, Yasu-cho, - Yasu-gun Shiga 520-2393 - JAPAN - - 00-21-E9 (hex) Apple - 0021E9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-21-EA (hex) Bystronic Laser AG - 0021EA (base 16) Bystronic Laser AG - Industriestrasse 21 - 3362 Niederönz - SWITZERLAND - - 00-21-EB (hex) ESP SYSTEMS, LLC - 0021EB (base 16) ESP SYSTEMS, LLC - 1422 East Fourth Street - Charlotte NC 28204 - UNITED STATES - - 00-21-EC (hex) Solutronic GmbH - 0021EC (base 16) Solutronic GmbH - Kueferstrasse 18 - Koengen 73257 - GERMANY - - 00-21-ED (hex) Telegesis - 0021ED (base 16) Telegesis - 84 Station Road - Marlow Bucks SL7 1NX - UNITED KINGDOM - - 00-21-EE (hex) Full Spectrum Inc. - 0021EE (base 16) Full Spectrum Inc. - 1149 Chestnut Street, Suite 100 - Menlo Park California 94025 - UNITED STATES - - 00-21-EF (hex) Kapsys - 0021EF (base 16) Kapsys - 790 Av du Docteur Maurice Donat - Le Marco Polo A1 - 06250 Mougins Sophia Antipolis - FRANCE - - 00-21-F0 (hex) EW3 Technologies LLC - 0021F0 (base 16) EW3 Technologies LLC - 114 E 11th St - Connersville IN 47331 - UNITED STATES - - 00-21-F1 (hex) Tutus Data AB - 0021F1 (base 16) Tutus Data AB - Svardvagen 11 - Danderyd Stockholm 18233 - SWEDEN - - 00-21-F2 (hex) EASY3CALL Technology Limited - 0021F2 (base 16) EASY3CALL Technology Limited - Room 1903-6, 19/F., HING YIP Commercial Centre - 272-284 DES VOEUX Road Central - Hong Kong 999077 - CHINA - - 00-21-F3 (hex) Si14 SpA - 0021F3 (base 16) Si14 SpA - Via Tommaseo 77 - Padova PD 35131 - ITALY - - 00-21-F4 (hex) INRange Systems, Inc - 0021F4 (base 16) INRange Systems, Inc - 3316 5th Avenue, Suite 100 - Altoona PA 16602 - UNITED STATES - - 00-21-F5 (hex) Western Engravers Supply, Inc. - 0021F5 (base 16) Western Engravers Supply, Inc. - 17621 N Black Canyon Highway - Phoenix AZ 85023 - UNITED STATES - - 00-21-F6 (hex) Oracle Corporation - 0021F6 (base 16) Oracle Corporation - 900 Chelmsford Street - Lowell MA 01851 - UNITED STATES - - 00-21-F7 (hex) HPN Supply Chain - 0021F7 (base 16) HPN Supply Chain - 8000 Foothills Blvd - Roseville CA 95747 - UNITED STATES - - 00-21-F8 (hex) Enseo, Inc. - 0021F8 (base 16) Enseo, Inc. - 401 International Parkway - Suite 100 - Richardson TX 75081 - UNITED STATES - - 00-21-F9 (hex) WIRECOM Technologies - 0021F9 (base 16) WIRECOM Technologies - 135, rue Jacques Charles - OLIVET Loiret 45166 - FRANCE - - 00-21-FA (hex) A4SP Technologies Ltd. - 0021FA (base 16) A4SP Technologies Ltd. - Keilaranta 19 D - Espoo Uusimaa 02150 - FINLAND - - 00-21-FB (hex) LG Electronics - 0021FB (base 16) LG Electronics - 60-39,Kasan-dong,Kumchon-ku, - Seoul 153-801 - KOREA, REPUBLIC OF - - 00-21-FC (hex) Nokia Danmark A/S - 0021FC (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-21-FD (hex) DSTA S.L. - 0021FD (base 16) DSTA S.L. - Majada 4 - Tres Cantos Madrid 28760 - SPAIN - - 00-21-FE (hex) Nokia Danmark A/S - 0021FE (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-21-FF (hex) Cyfrowy Polsat SA - 0021FF (base 16) Cyfrowy Polsat SA - Åubinowa - Warsaw Mazowieckie 03-878 - POLAND - - 00-22-00 (hex) IBM Corp - 002200 (base 16) IBM Corp - 2051 Mission College Blvd - Santa Clara CA 95054 - UNITED STATES - - 00-22-01 (hex) Aksys Networks Inc - 002201 (base 16) Aksys Networks Inc - 428, 3553 - 31 Street NW - Calgary T2L 2K7 - CANADA - - 00-22-02 (hex) Excito Elektronik i SkÃ¥ne AB - 002202 (base 16) Excito Elektronik i SkÃ¥ne AB - Box 126 - Löddeköpinge 246 22 - SWEDEN - - 00-22-03 (hex) Glensound Electronics Ltd - 002203 (base 16) Glensound Electronics Ltd - 1 - 6 Brooks Place - Maidstone Kent ME17 1UN - UNITED KINGDOM - - 00-22-04 (hex) KORATEK - 002204 (base 16) KORATEK - Geumjeong-dong - Gunpo-si Gyeonggi-do 435-825 - KOREA, REPUBLIC OF - - 00-22-05 (hex) WeLink Solutions, Inc. - 002205 (base 16) WeLink Solutions, Inc. - 3F, No. 88, Sec. 1, Nei-Hu Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-22-06 (hex) Cyberdyne Inc. - 002206 (base 16) Cyberdyne Inc. - 504 @C49-2 - Tsukuba-shi Ibaraki-ken 305-0817 - JAPAN - - 00-22-07 (hex) Inteno Broadband Technology AB - 002207 (base 16) Inteno Broadband Technology AB - Drivhjulsvägen 22 - Stockholm SE 12630 - SWEDEN - - 00-22-08 (hex) Certicom Corp - 002208 (base 16) Certicom Corp - 5520 Explorer Drive, 4th Floor - Mississauga ON L4W 5L1 - CANADA - - 00-22-09 (hex) Omron Healthcare Co., Ltd - 002209 (base 16) Omron Healthcare Co., Ltd - 24 Yamanoshita-cho Yamanouchi - Ukyoku - Kyoto 6150084 - JAPAN - - 00-22-0A (hex) OnLive, Inc - 00220A (base 16) OnLive, Inc - 1091 N Shoreline Blvd - Mountainview California 94043 - UNITED STATES - - 00-22-0B (hex) National Source Coding Center - 00220B (base 16) National Source Coding Center - Suite 701,Power Creative A,No.1 - Shangdi East Road,Haidian District - Beijing 100085 - CHINA - - 00-22-0C (hex) CISCO SYSTEMS, INC. - 00220C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-0D (hex) CISCO SYSTEMS, INC. - 00220D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-0E (hex) Indigo Security Co., Ltd. - 00220E (base 16) Indigo Security Co., Ltd. - 2nd Floor, 277-169 Sungsoo2-Ga, Sungdong-Gu - Seoul 133-832 - KOREA, REPUBLIC OF - - 00-22-0F (hex) MoCA (Multimedia over Coax Alliance) - 00220F (base 16) MoCA (Multimedia over Coax Alliance) - 90 Inverness Circle East - Englewood CA 94583 - UNITED STATES - - 00-22-10 (hex) ARRIS Group, Inc. - 002210 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-22-11 (hex) Rohati Systems - 002211 (base 16) Rohati Systems - 1192 Borregas Ave - Sunnyvale CA 94089 - UNITED STATES - - 00-22-12 (hex) CAI Networks, Inc. - 002212 (base 16) CAI Networks, Inc. - 4790 Irvine Blvd - Suite 105-203 - Irvine California 92620 - UNITED STATES - - 00-22-13 (hex) PCI CORPORATION - 002213 (base 16) PCI CORPORATION - No.25, Lane 66, Hebei 1st St., Beitun District - Taichung 406 - TAIWAN, PROVINCE OF CHINA - - 00-22-14 (hex) RINNAI KOREA - 002214 (base 16) RINNAI KOREA - 560-2, Shibjong-1dong, Pupyoung-gu - 5th Research Team - Pupyoung-gu Incheon 403-847 - KOREA, REPUBLIC OF - - 00-22-15 (hex) ASUSTek COMPUTER INC. - 002215 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-22-16 (hex) SHIBAURA VENDING MACHINE CORPORATION - 002216 (base 16) SHIBAURA VENDING MACHINE CORPORATION - Ekimae-cho13-10 - Obama-shi Fukui-ken 917-0077 - JAPAN - - 00-22-17 (hex) Neat Electronics - 002217 (base 16) Neat Electronics - Varuvägen 2 - Löddeköpinge SkÃ¥ne SE-24642 - SWEDEN - - 00-22-18 (hex) Verivue Inc. - 002218 (base 16) Verivue Inc. - 3 Carlisle Road - Westford MA 01886 - UNITED STATES - - 00-22-19 (hex) Dell Inc - 002219 (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-22-1A (hex) Audio Precision - 00221A (base 16) Audio Precision - 5750 SW Arctic Drive - Beaverton OR 97005 - UNITED STATES - - 00-22-1B (hex) Morega Systems - 00221B (base 16) Morega Systems - 5770 Hurontario Street - Suite 501 - Mississauga Ontario L5R 3G5 - CANADA - - 00-22-1C (hex) PRIVATE - 00221C (base 16) - - 00-22-1D (hex) Freegene Technology LTD - 00221D (base 16) Freegene Technology LTD - 3/F ,C BLDG,Weipengda Industrial Park - longkou industrial area,bao-an district - Shenzhen Gongdong 518109 - CHINA - - 00-22-1E (hex) Media Devices Co., Ltd. - 00221E (base 16) Media Devices Co., Ltd. - Rm1002 Ace TechnoTower(9th) 345-30 - Kasan-dong, Kumchon-ku - Seoul 153-802 - KOREA, REPUBLIC OF - - 00-22-1F (hex) eSang Technologies Co., Ltd. - 00221F (base 16) eSang Technologies Co., Ltd. - #1-817, IT Castle 550-1, Gasan-Dong, - Geumcheon-Gu, - Seoul 153-768 - KOREA, REPUBLIC OF - - 00-22-20 (hex) Mitac Technology Corp - 002220 (base 16) Mitac Technology Corp - 9th Fl., #75, Min-sheng E. Road, Sec. 3, - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-22-21 (hex) ITOH DENKI CO,LTD. - 002221 (base 16) ITOH DENKI CO,LTD. - 1146-2, Asazuma-cho - Kasai Hyogo 679-0180 - JAPAN - - 00-22-22 (hex) Schaffner Deutschland GmbH - 002222 (base 16) Schaffner Deutschland GmbH - Nürtingen Branch - Raidwanger Straße 12 - Nürtingen BW D-72622 - GERMANY - - 00-22-23 (hex) TimeKeeping Systems, Inc. - 002223 (base 16) TimeKeeping Systems, Inc. - 30700 Bainbridge Road - Suite H - Solon OH 44139 - UNITED STATES - - 00-22-24 (hex) Good Will Instrument Co., Ltd. - 002224 (base 16) Good Will Instrument Co., Ltd. - No. 7-1 Jhongsing Road, - Tucheng City - Taipei 236 - TAIWAN, PROVINCE OF CHINA - - 00-22-25 (hex) Thales Avionics Ltd - 002225 (base 16) Thales Avionics Ltd - 86 Bushey Road - Raynes Park - London SW20 0JW - UNITED KINGDOM - - 00-22-26 (hex) Avaak, Inc. - 002226 (base 16) Avaak, Inc. - 9645 Scranton Rd., Suite 110 - San Diego CA 92121 - UNITED STATES - - 00-22-27 (hex) uv-electronic GmbH - 002227 (base 16) uv-electronic GmbH - Grosswiesenstraße 20 - Durchhausen Baden-Württemberg 78591 - GERMANY - - 00-22-28 (hex) Breeze Innovations Ltd. - 002228 (base 16) Breeze Innovations Ltd. - Har Hotzvim, P.O. Box 45397 - Jerusalem Israel 91451 - ISRAEL - - 00-22-29 (hex) Compumedics Ltd - 002229 (base 16) Compumedics Ltd - 30 - 40 Flockhart Street - Abbotsford Victoria 3067 - AUSTRALIA - - 00-22-2A (hex) SoundEar A/S - 00222A (base 16) SoundEar A/S - Rentemestervej 80 - Copenhagen NV Denmark DK-2400 - DENMARK - - 00-22-2B (hex) Nucomm, Inc. - 00222B (base 16) Nucomm, Inc. - 101 Bilby Road - Hackettstown NJ 07840 - UNITED STATES - - 00-22-2C (hex) Ceton Corp - 00222C (base 16) Ceton Corp - 8259 122nd Ave NE, Suite 275 - Kirkland Washington 98033 - UNITED STATES - - 00-22-2D (hex) SMC Networks Inc. - 00222D (base 16) SMC Networks Inc. - 20 Mason - Irvine CA 92618 - UNITED STATES - - 00-22-2E (hex) maintech GmbH - 00222E (base 16) maintech GmbH - Seeweg 60 - Höchberg Bavaria 97204 - GERMANY - - 00-22-2F (hex) Open Grid Computing, Inc. - 00222F (base 16) Open Grid Computing, Inc. - 4030-1 West Braker Lane STE130 - Austin TX 78759 - UNITED STATES - - 00-22-30 (hex) FutureLogic Inc. - 002230 (base 16) FutureLogic Inc. - 425 E. Colorado St., Ste. 100 - Glendale CA 91205 - UNITED STATES - - 00-22-31 (hex) SMT&C Co., Ltd. - 002231 (base 16) SMT&C Co., Ltd. - 2Fr. Haksan Bldg. 110, Gwangjang-dong, Gwangjin-gu - Seoul 143-802 - KOREA, REPUBLIC OF - - 00-22-32 (hex) Design Design Technology Ltd - 002232 (base 16) Design Design Technology Ltd - Unit 9, Ash Road South - Wrexham Industrial Estate - Wrexham North Wales LL13 9UG - UNITED KINGDOM - - 00-22-33 (hex) ADB Broadband Italia - 002233 (base 16) ADB Broadband Italia - VIALE SARCA 222 - MILANO 20126 - ITALY - - 00-22-34 (hex) Corventis Inc. - 002234 (base 16) Corventis Inc. - 1410 Energy Park Dr. Suite #1 - St. Paul Minnesota 55108 - UNITED STATES - - 00-22-35 (hex) Strukton Systems bv - 002235 (base 16) Strukton Systems bv - Westkanaaldijk 2 - Utrecht 3542 DA - NETHERLANDS - - 00-22-36 (hex) VECTOR SP. Z O.O. - 002236 (base 16) VECTOR SP. Z O.O. - KRZEMOWA 6 - GDYNIA 81-577 - POLAND - - 00-22-37 (hex) Shinhint Group - 002237 (base 16) Shinhint Group - Unit 1506, 15/F, Nanyang Plaza,, 57 Hung To Road, - Kwun Tong, Kln - HONG KONG - - 00-22-38 (hex) LOGIPLUS - 002238 (base 16) LOGIPLUS - 1, RUE CLEMENT ADER - B-6041 GOSSELEIES - GOSSELIES HAINAUT B-6041 - BELGIUM - - 00-22-39 (hex) Indiana Life Sciences Incorporated - 002239 (base 16) Indiana Life Sciences Incorporated - 8875 Bash Street - Indianapolis Indiana 46256 - UNITED STATES - - 00-22-3A (hex) Scientific Atlanta, Cisco SPVT Group - 00223A (base 16) Scientific Atlanta, Cisco SPVT Group - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 00-22-3B (hex) Communication Networks, LLC - 00223B (base 16) Communication Networks, LLC - 3 Corporate Drive - Danbury CT 06810 - UNITED STATES - - 00-22-3C (hex) RATIO Entwicklungen GmbH - 00223C (base 16) RATIO Entwicklungen GmbH - Ludwig-Erhard-Strasse 22 - Hamburg 20459 - GERMANY - - 00-22-3D (hex) JumpGen Systems, LLC - 00223D (base 16) JumpGen Systems, LLC - 2111 Palomar Airport Rd - Suitte 350 - Carlsbad CA 92011 - UNITED STATES - - 00-22-3E (hex) IRTrans GmbH - 00223E (base 16) IRTrans GmbH - Einsteinstrasse 14 - Unterschleissheim BAYERN 85716 - GERMANY - - 00-22-3F (hex) Netgear Inc. - 00223F (base 16) Netgear Inc. - 4500 Great America Pky - Santa Clara CA 95054 - UNITED STATES - - 00-22-40 (hex) Universal Telecom S/A - 002240 (base 16) Universal Telecom S/A - Avenida Paulista, 2444 - 17 andar - São Paulo 01310-300 - BRAZIL - - 00-22-41 (hex) Apple - 002241 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-22-42 (hex) Alacron Inc. - 002242 (base 16) Alacron Inc. - 71 Spit Brook Rd. - Suite 204 - Nashua NH 03060 - UNITED STATES - - 00-22-43 (hex) AzureWave Technologies, Inc. - 002243 (base 16) AzureWave Technologies, Inc. - 8F., No. 94, Baozhong Rd., Xindian - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 00-22-44 (hex) Chengdu Linkon Communications Device Co., Ltd - 002244 (base 16) Chengdu Linkon Communications Device Co., Ltd - 5f-02, Juntong Building, No. 53,Shuangfeng Road, Wuhou District, - Chengdu Sichuan 610041 - CHINA - - 00-22-45 (hex) Leine & Linde AB - 002245 (base 16) Leine & Linde AB - Box 8 - Strängnäs Södermanland SE-645 21 - SWEDEN - - 00-22-46 (hex) Evoc Intelligent Technology Co.,Ltd. - 002246 (base 16) Evoc Intelligent Technology Co.,Ltd. - No.31 Gaoxin Centeral Avenue 4th Road,Nanshan District Shenzhen City - Shenzhen Guangdong 518057 - CHINA - - 00-22-47 (hex) DAC ENGINEERING CO., LTD. - 002247 (base 16) DAC ENGINEERING CO., LTD. - 1-5 Oyanagi-cho - Kamitoba, Minami-ku - Kyoto 601-8128 - JAPAN - - 00-22-48 (hex) Microsoft Corporation - 002248 (base 16) Microsoft Corporation - One Microsoft Way - Redmond Washington 98052-6399 - UNITED STATES - - 00-22-49 (hex) HOME MULTIENERGY SL - 002249 (base 16) HOME MULTIENERGY SL - Capitán HAYA 1 - EDIFICIO EUCOCENTRO BAJO - MADRID 28020 - SPAIN - - 00-22-4A (hex) RAYLASE AG - 00224A (base 16) RAYLASE AG - Argelsrieder Feld 2-4 - Wessling Bavaria 82234 - GERMANY - - 00-22-4B (hex) AIRTECH TECHNOLOGIES, INC. - 00224B (base 16) AIRTECH TECHNOLOGIES, INC. - 19fl-4, no.77, Hsin Tai Wu Rd., sec.1, Hsin-Chih - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 00-22-4C (hex) Nintendo Co., Ltd. - 00224C (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-22-4D (hex) MITAC INTERNATIONAL CORP. - 00224D (base 16) MITAC INTERNATIONAL CORP. - 6TH FL., NO187, TIDING BLVD., SEC. 2 - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-22-4E (hex) SEEnergy Corp. - 00224E (base 16) SEEnergy Corp. - 4F, No.61, Dongsing RD. - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 00-22-4F (hex) Byzoro Networks Ltd. - 00224F (base 16) Byzoro Networks Ltd. - Room 5A1,Block A, Keshi Plaza,No. 28A Info. Road, - HaiDian District, - Beijing 100085 - CHINA - - 00-22-50 (hex) Point Six Wireless, LLC - 002250 (base 16) Point Six Wireless, LLC - 2333 Alumni Park Plaza - Suite 305 - Lexington KY 40517 - UNITED STATES - - 00-22-51 (hex) Lumasense Technologies - 002251 (base 16) Lumasense Technologies - 3033 Scott Blvd. - Santa Clara CA 95054 - UNITED STATES - - 00-22-52 (hex) ZOLL Lifecor Corporation - 002252 (base 16) ZOLL Lifecor Corporation - 121 Freeport Road - Pittsburgh PA 15238 - UNITED STATES - - 00-22-53 (hex) Entorian Technologies - 002253 (base 16) Entorian Technologies - 8900 Shoal Creek Blvd - Austin TX 78757 - UNITED STATES - - 00-22-54 (hex) Bigelow Aerospace - 002254 (base 16) Bigelow Aerospace - 1899 W. Brooks Ave - North Las Vegas NV 89032 - UNITED STATES - - 00-22-55 (hex) CISCO SYSTEMS, INC. - 002255 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-56 (hex) CISCO SYSTEMS, INC. - 002256 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-57 (hex) 3Com Europe Ltd - 002257 (base 16) 3Com Europe Ltd - Peoplebuilding 2 - Maylands Avenue - Hemel Hempstead Herts. HP2 4NW - UNITED KINGDOM - - 00-22-58 (hex) Taiyo Yuden Co., Ltd. - 002258 (base 16) Taiyo Yuden Co., Ltd. - 8-1, Sakae-cho - Takasaki-shi Gunma-ken 370-8522 - JAPAN - - 00-22-59 (hex) Guangzhou New Postcom Equipment Co.,Ltd. - 002259 (base 16) Guangzhou New Postcom Equipment Co.,Ltd. - No.3¡¡Guangpuxi Road,Guangzhou Science City, - Guangzhou Guangdong 510663 - CHINA - - 00-22-5A (hex) Garde Security AB - 00225A (base 16) Garde Security AB - Box 78 - Soderhamn S-826 22 - SWEDEN - - 00-22-5B (hex) Teradici Corporation - 00225B (base 16) Teradici Corporation - 101 4621 Canada Way, - Burnaby BC V6G 4X8 - CANADA - - 00-22-5C (hex) Multimedia & Communication Technology - 00225C (base 16) Multimedia & Communication Technology - Digital Empire D-801 #980-3 - YeongTong-Dong - Suwon-City KyeongGi-Do 443-813 - KOREA, REPUBLIC OF - - 00-22-5D (hex) Digicable Network India Pvt. Ltd. - 00225D (base 16) Digicable Network India Pvt. Ltd. - 7B, Shah Industrial Estate - Off. Veera Desai Road, - Andheri - West, Mumbai. Maharashtra 400 053 - INDIA - - 00-22-5E (hex) Uwin Technologies Co.,LTD - 00225E (base 16) Uwin Technologies Co.,LTD - 2F,No.22.R&D RD II,SBIP - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-22-5F (hex) Liteon Technology Corporation - 00225F (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo, - Taipei Hsien, 23585 - TAIWAN, PROVINCE OF CHINA - - 00-22-60 (hex) AFREEY Inc. - 002260 (base 16) AFREEY Inc. - 6F, No.249, Chien I Road - Chung Ho City Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-22-61 (hex) Frontier Silicon Ltd - 002261 (base 16) Frontier Silicon Ltd - Gleneagles, The Belfry - Colonial Way - Watford Hertfordshire WD24 4WH - UNITED KINGDOM - - 00-22-62 (hex) BEP Marine - 002262 (base 16) BEP Marine - 13 Tarndale Grove Albany - North Shore - Auckland 0632 - NEW ZEALAND - - 00-22-63 (hex) Koos Technical Services, Inc. - 002263 (base 16) Koos Technical Services, Inc. - 1025 Greenwood Blvd. - Suite 391 - Lake Mary FL 32746 - UNITED STATES - - 00-22-64 (hex) Hewlett-Packard Company - 002264 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040802 - Houston TX 77070 - UNITED STATES - - 00-22-65 (hex) Nokia Danmark A/S - 002265 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-22-66 (hex) Nokia Danmark A/S - 002266 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-22-67 (hex) Nortel Networks - 002267 (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson Texas 75082-4399 - UNITED STATES - - 00-22-68 (hex) Hon Hai Precision Ind. Co., Ltd. - 002268 (base 16) Hon Hai Precision Ind. Co., Ltd. - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-22-69 (hex) Hon Hai Precision Ind. Co., Ltd. - 002269 (base 16) Hon Hai Precision Ind. Co., Ltd. - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-22-6A (hex) Honeywell - 00226A (base 16) Honeywell - 8840 Evergreen Blvd. - Minneapolis MN 55433-6040 - UNITED STATES - - 00-22-6B (hex) Cisco-Linksys, LLC - 00226B (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 00-22-6C (hex) LinkSprite Technologies, Inc. - 00226C (base 16) LinkSprite Technologies, Inc. - 1410 Cannon Mountain Dr - Longmont CO 80503 - UNITED STATES - - 00-22-6D (hex) Shenzhen GIEC Electronics Co., Ltd. - 00226D (base 16) Shenzhen GIEC Electronics Co., Ltd. - 24/F, XiNian Center, ShenNan Road 6021#, Futian District - Shenzhen Guangdong Province 518040 - CHINA - - 00-22-6E (hex) Gowell Electronic Limited - 00226E (base 16) Gowell Electronic Limited - Room 3601 ,36 Floor,Golden Central Tower,Jintian Road,Futian Central District, - Shenzhen GuangDong 518048 - CHINA - - 00-22-6F (hex) 3onedata Technology Co. Ltd. - 00226F (base 16) 3onedata Technology Co. Ltd. - 3/F, B/2, Jiuxiangling Industrial District, Xili Town, Nanshan District, - Shenzhen Guangdong 518055 - CHINA - - 00-22-70 (hex) ABK North America, LLC - 002270 (base 16) ABK North America, LLC - 440 North Wolfe Rd. - Sunnyvale CA 94085 - UNITED STATES - - 00-22-71 (hex) Jäger Computergesteuerte Meßtechnik GmbH. - 002271 (base 16) Jäger Computergesteuerte Meßtechnik GmbH. - Rheinstraße 2-4 - Lorsch Hessen 64653 - GERMANY - - 00-22-72 (hex) American Micro-Fuel Device Corp. - 002272 (base 16) American Micro-Fuel Device Corp. - 2181 Buchanan Loop - Ferndale WA 98248 - UNITED STATES - - 00-22-73 (hex) Techway - 002273 (base 16) Techway - Rm 1002, Daehyun Techno World Bd, - 174, Ojun-Dong, - Uiwang-Si, Kyungki-Do 437-820 - KOREA, REPUBLIC OF - - 00-22-74 (hex) FamilyPhone AB - 002274 (base 16) FamilyPhone AB - Anckargripsgatan 3 - Malmö 21119 - SWEDEN - - 00-22-75 (hex) Belkin International Inc. - 002275 (base 16) Belkin International Inc. - 12045 E. Waterfront Drive - Playa Vista Ca 90094 - UNITED STATES - - 00-22-76 (hex) Triple EYE B.V. - 002276 (base 16) Triple EYE B.V. - Vaassenseweg 71 - Emst 8166 AT - NETHERLANDS - - 00-22-77 (hex) NEC Australia Pty Ltd - 002277 (base 16) NEC Australia Pty Ltd - 649-655 Springvale Rd - Mulgrave Victoria 3170 - AUSTRALIA - - 00-22-78 (hex) Shenzhen Tongfang Multimedia Technology Co.,Ltd. - 002278 (base 16) Shenzhen Tongfang Multimedia Technology Co.,Ltd. - 2f Sector D of TongFang Information Harbor - Langshan Road, Hi-Tech Industrial Park - Nanshan District, Shenzhen GuangDong 518058 - CHINA - - 00-22-79 (hex) Nippon Conlux Co., Ltd. - 002279 (base 16) Nippon Conlux Co., Ltd. - 5-3-8, Chiyoda - Sakado-shi Saitama 350-0214 - JAPAN - - 00-22-7A (hex) Telecom Design - 00227A (base 16) Telecom Design - Za Remora - Voie Romaine - 33170 Gradignan - FRANCE - - 00-22-7B (hex) Apogee Labs, Inc. - 00227B (base 16) Apogee Labs, Inc. - 210 S. 3rd St. - North Wales PA 19454 - UNITED STATES - - 00-22-7C (hex) Woori SMT Co.,ltd - 00227C (base 16) Woori SMT Co.,ltd - 649-2,Suwolam-ri,Seotan-Myun - Pyongtaek Kyonggi-Do 451-852 - KOREA, REPUBLIC OF - - 00-22-7D (hex) YE DATA INC. - 00227D (base 16) YE DATA INC. - 182 Shinko - Iruma Saitama 358-0055 - JAPAN - - 00-22-7E (hex) Chengdu 30Kaitian Communication Industry Co.Ltd - 00227E (base 16) Chengdu 30Kaitian Communication Industry Co.Ltd - No.6 Chuangye Road - Chengdu Sichuan 610041 - CHINA - - 00-22-7F (hex) Ruckus Wireless - 00227F (base 16) Ruckus Wireless - 880 West Maude Ave. - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 00-22-80 (hex) A2B Electronics AB - 002280 (base 16) A2B Electronics AB - Box 14 - Motala S-591 21 - SWEDEN - - 00-22-81 (hex) Daintree Networks Pty - 002281 (base 16) Daintree Networks Pty - 1 Dalmore Drive - Scoresby Victoria 3179 - AUSTRALIA - - 00-22-82 (hex) 8086 Consultancy - 002282 (base 16) 8086 Consultancy - 17 Lowfield Lane - Balderton - Newark Notts NG24 3HJ - UNITED KINGDOM - - 00-22-83 (hex) Juniper Networks - 002283 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-22-84 (hex) DESAY A&V SCIENCE AND TECHNOLOGY CO.,LTD - 002284 (base 16) DESAY A&V SCIENCE AND TECHNOLOGY CO.,LTD - DESAY 3rd Zone,Chenjiang, - Huizhou Guangdong 516229 - CHINA - - 00-22-85 (hex) NOMUS COMM SYSTEMS - 002285 (base 16) NOMUS COMM SYSTEMS - 601, Gunjan Tower, - Off. Alembic Gorwa Road - Baroda Gujarat 390023 - INDIA - - 00-22-86 (hex) ASTRON - 002286 (base 16) ASTRON - Oudehoogeveensedijk 4 - Dwingeloo Drenthe 7991PD - NETHERLANDS - - 00-22-87 (hex) Titan Wireless LLC - 002287 (base 16) Titan Wireless LLC - 3914 Gattis School Rd - Suite 102 - Round Rock Texas 78664 - UNITED STATES - - 00-22-88 (hex) Sagrad, Inc. - 002288 (base 16) Sagrad, Inc. - 751 North Drive - Melbourne FL 32934 - UNITED STATES - - 00-22-89 (hex) Optosecurity Inc. - 002289 (base 16) Optosecurity Inc. - 505, Boul. du Parc Technologique - Quebec G1P 4S9 - CANADA - - 00-22-8A (hex) Teratronik elektronische systeme gmbh - 00228A (base 16) Teratronik elektronische systeme gmbh - Karl-Ulrich-Strasse 1 - Gross-Umstadt D-64823 - GERMANY - - 00-22-8B (hex) Kensington Computer Products Group - 00228B (base 16) Kensington Computer Products Group - 333 Twin Dolphin Dr. - Sixth Floor - Redwood Shores CA 94065 - UNITED STATES - - 00-22-8C (hex) Photon Europe GmbH - 00228C (base 16) Photon Europe GmbH - Jülicher Straße 376 - Aachen Nordrhein-Westfalen 52070 - GERMANY - - 00-22-8D (hex) GBS Laboratories LLC - 00228D (base 16) GBS Laboratories LLC - 2325 Dulles Corner Blvd - Herndon VA 20171 - UNITED STATES - - 00-22-8E (hex) TV-NUMERIC - 00228E (base 16) TV-NUMERIC - 24-26 rue Louis Armand - Paris 75015 - FRANCE - - 00-22-8F (hex) CNRS - 00228F (base 16) CNRS - MRCT - 1 place Aristide Briand - Meudon Ile de France 92195 - FRANCE - - 00-22-90 (hex) CISCO SYSTEMS, INC. - 002290 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-91 (hex) CISCO SYSTEMS, INC. - 002291 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-92 (hex) Cinetal - 002292 (base 16) Cinetal - 8651 Castle Park - Indianapolis IN 46256 - UNITED STATES - - 00-22-93 (hex) ZTE Corporation - 002293 (base 16) ZTE Corporation - 12/F zte plaza,keji Road South,Hi-Tech Industrial Park,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-22-94 (hex) Kyocera Corporation - 002294 (base 16) Kyocera Corporation - 2-1-1,Kagahara - Tsuzuki-ku - Yokohama-shi Kanagawa 224-8502 - JAPAN - - 00-22-95 (hex) SGM Technology for lighting spa - 002295 (base 16) SGM Technology for lighting spa - Via Pio La Torre 1 - Tavullia PU 61010 - ITALY - - 00-22-96 (hex) LinoWave Corporation - 002296 (base 16) LinoWave Corporation - 1001-101 Champlain Avenue - Burlington Onatario L7L 5Z4 - CANADA - - 00-22-97 (hex) XMOS Semiconductor - 002297 (base 16) XMOS Semiconductor - Venturers House - King Street - Bristol BS1 4PB - UNITED KINGDOM - - 00-22-98 (hex) Sony Ericsson Mobile Communications - 002298 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-22-99 (hex) SeaMicro Inc. - 002299 (base 16) SeaMicro Inc. - 4677 Old Ironsides Dr., - Suite 310 - Santa Clara CA 95054 - UNITED STATES - - 00-22-9A (hex) Lastar, Inc. - 00229A (base 16) Lastar, Inc. - 3555 Kettering BLVD. - Moraine Ohio 45439 - UNITED STATES - - 00-22-9B (hex) AverLogic Technologies, Inc. - 00229B (base 16) AverLogic Technologies, Inc. - 7F-2, No.2, Lane 258, Rui Guang Rd., Nei-Hu Dist., - Taipei Taiwan 114 - TAIWAN, PROVINCE OF CHINA - - 00-22-9C (hex) Verismo Networks Inc - 00229C (base 16) Verismo Networks Inc - 295 Bernando Avenue - Ste # 300 - Mountain View CA 94043 - UNITED STATES - - 00-22-9D (hex) PYUNG-HWA IND.CO.,LTD - 00229D (base 16) PYUNG-HWA IND.CO.,LTD - 230-1 - Duckwoo-RI, Paltan-MYUN - HWASUNG-SI KYUNGGI-DO 445-912 - KOREA, REPUBLIC OF - - 00-22-9E (hex) Social Aid Research Co., Ltd. - 00229E (base 16) Social Aid Research Co., Ltd. - South 3, West 10, Chuo-ku - 4F, Fukuyama-Minami-3jyou Build. - Sapporo Hokkaido 060-0063 - JAPAN - - 00-22-9F (hex) Sensys Traffic AB - 00229F (base 16) Sensys Traffic AB - Slottsgatan 14 - Box 2174 - Jonkoping Smaland 55322 - SWEDEN - - 00-22-A0 (hex) Delphi Corporation - 0022A0 (base 16) Delphi Corporation - M/C-480-405-255 - 5820 Delphi Drive - Troy MI 48446 - UNITED STATES - - 00-22-A1 (hex) Huawei Symantec Technologies Co.,Ltd. - 0022A1 (base 16) Huawei Symantec Technologies Co.,Ltd. - Building 1,The West Zone Science Park of UESTC,No.88,Tianchen Road - Chengdu Sichuan 611731 - CHINA - - 00-22-A2 (hex) Xtramus Technologies - 0022A2 (base 16) Xtramus Technologies - 5th Fl., No. 102, Lide St., - Zhonghe City Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 00-22-A3 (hex) California Eastern Laboratories - 0022A3 (base 16) California Eastern Laboratories - 4590 Patrick Henry Dr. - Santa Clara CA 95054 - UNITED STATES - - 00-22-A4 (hex) 2Wire - 0022A4 (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-22-A5 (hex) Texas Instruments - 0022A5 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-22-A6 (hex) Sony Computer Entertainment America - 0022A6 (base 16) Sony Computer Entertainment America - 919 East Hillsdale Blvd - Foster City California 94404-2175 - UNITED STATES - - 00-22-A7 (hex) Tyco Electronics AMP GmbH - 0022A7 (base 16) Tyco Electronics AMP GmbH - Amperestraße 12-14 - Bensheim Hessen 64625 - GERMANY - - 00-22-A8 (hex) Ouman Oy - 0022A8 (base 16) Ouman Oy - Voimatie 6 - Kempele FIN-90440 - FINLAND - - 00-22-A9 (hex) LG Electronics Inc - 0022A9 (base 16) LG Electronics Inc - 60-39,Gasan-dong - Gumchon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-22-AA (hex) Nintendo Co., Ltd. - 0022AA (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-22-AB (hex) Shenzhen Turbosight Technology Ltd - 0022AB (base 16) Shenzhen Turbosight Technology Ltd - Unit C-8A,Shennan Garden Bldg,Hightech Park,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-22-AC (hex) Hangzhou Siyuan Tech. Co., Ltd - 0022AC (base 16) Hangzhou Siyuan Tech. Co., Ltd - 5 F, Tower B, No. 37, Xiang Yuan Road - Hangzhou Zhejiang 310012 - CHINA - - 00-22-AD (hex) TELESIS TECHNOLOGIES, INC. - 0022AD (base 16) TELESIS TECHNOLOGIES, INC. - 28181 River Drive - Circleville Ohio 43113 - UNITED STATES - - 00-22-AE (hex) Mattel Inc. - 0022AE (base 16) Mattel Inc. - 333 Continental Blvd. - El Segundo CA 90245 - UNITED STATES - - 00-22-AF (hex) Safety Vision - 0022AF (base 16) Safety Vision - 6100 W. Sam Houston Pkwy. North - Houston Texas 77041 - UNITED STATES - - 00-22-B0 (hex) D-Link Corporation - 0022B0 (base 16) D-Link Corporation - No.289, Sinhu 3rd RD., - Neihu District, Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-22-B1 (hex) Elbit Systems - 0022B1 (base 16) Elbit Systems - POB 539 - Haifa 31053 - ISRAEL - - 00-22-B2 (hex) 4RF Communications Ltd - 0022B2 (base 16) 4RF Communications Ltd - 26 Glover Street - Ngauranga Wellington 6035 - NEW ZEALAND - - 00-22-B3 (hex) Sei S.p.A. - 0022B3 (base 16) Sei S.p.A. - Via Ruffilli, 1 - Curno Bergamo 24035 - ITALY - - 00-22-B4 (hex) ARRIS Group, Inc. - 0022B4 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-22-B5 (hex) NOVITA - 0022B5 (base 16) NOVITA - 3F301,Namsung B/D 340-30 - Gasan-Dong - Geumcheon-Gu Seoul 153-782 - KOREA, REPUBLIC OF - - 00-22-B6 (hex) Superflow Technologies Group - 0022B6 (base 16) Superflow Technologies Group - 4060 Dixon Street - Des Moines IA 50266 - UNITED STATES - - 00-22-B7 (hex) GSS Grundig SAT-Systems GmbH - 0022B7 (base 16) GSS Grundig SAT-Systems GmbH - Beutherner Strasse 43 - Nuernberg Bayern 90471 - GERMANY - - 00-22-B8 (hex) Norcott - 0022B8 (base 16) Norcott - Brookfield House - Grimsditch Lane off Tarporley Road - Norcott Brook Cheshire WA4 4EA - UNITED KINGDOM - - 00-22-B9 (hex) Analogix Seminconductor, Inc - 0022B9 (base 16) Analogix Seminconductor, Inc - 3211 Scott Blvd., Suite 100 - Santa Clara CA 95054 - UNITED STATES - - 00-22-BA (hex) HUTH Elektronik Systeme GmbH - 0022BA (base 16) HUTH Elektronik Systeme GmbH - Echternacher Str. 10 - Troisdorf-Spich NRW 53842 - GERMANY - - 00-22-BB (hex) beyerdynamic GmbH & Co. KG - 0022BB (base 16) beyerdynamic GmbH & Co. KG - Theresienstraße 8 - Heilbronn 74072 - GERMANY - - 00-22-BC (hex) JDSU France SAS - 0022BC (base 16) JDSU France SAS - 34 rue Necker - SAINT ETIENNE LOIRE 42000 - FRANCE - - 00-22-BD (hex) CISCO SYSTEMS, INC. - 0022BD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-BE (hex) CISCO SYSTEMS, INC. - 0022BE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-22-BF (hex) SieAmp Group of Companies - 0022BF (base 16) SieAmp Group of Companies - 2 Ang Mo Kio Street 64 - Ang Mo Kio Industrial Park 3, Unit 02-01D Econ Building - Singapore 569084 - SINGAPORE - - 00-22-C0 (hex) Shenzhen Forcelink Electronic Co, Ltd - 0022C0 (base 16) Shenzhen Forcelink Electronic Co, Ltd - 2nd and 3rd floor, Hasse manufacture building, Hasee industrial park - Banxuegang industrial area, Longgang district - Shenzhen Guangdong 518112 - CHINA - - 00-22-C1 (hex) Active Storage Inc. - 0022C1 (base 16) Active Storage Inc. - 2295 Jefferson Street - Torrance CA 90501 - UNITED STATES - - 00-22-C2 (hex) Proview Eletrônica do Brasil LTDA - 0022C2 (base 16) Proview Eletrônica do Brasil LTDA - R. Acará 203 - Distrito Industrial - Manaus Amazonas 69075-030 - BRAZIL - - 00-22-C3 (hex) Zeeport Technology Inc. - 0022C3 (base 16) Zeeport Technology Inc. - 1F,No231,Xianzheng 2nd Rd. - HsinChu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-22-C4 (hex) epro GmbH - 0022C4 (base 16) epro GmbH - Joebkesweg 3 - Gronau NRW 48599 - GERMANY - - 00-22-C5 (hex) INFORSON Co,Ltd. - 0022C5 (base 16) INFORSON Co,Ltd. - Room 704,Tower B1, ChangYuanTianDi Plaza - SuZhou Street, HaiDian District - BeiJing City 100080 - CHINA - - 00-22-C6 (hex) Sutus Inc - 0022C6 (base 16) Sutus Inc - 301-3999 Henning Drive - Burnaby British Columbia V5C 6P9 - CANADA - - 00-22-C7 (hex) SEGGER Microcontroller GmbH & Co. KG - 0022C7 (base 16) SEGGER Microcontroller GmbH & Co. KG - In den Weiden 11 - Hilden NRW 40721 - GERMANY - - 00-22-C8 (hex) Applied Instruments B.V. - 0022C8 (base 16) Applied Instruments B.V. - Dynamoweg 3 - Vlissingen Zeeland NL-4382WZ - NETHERLANDS - - 00-22-C9 (hex) Lenord, Bauer & Co GmbH - 0022C9 (base 16) Lenord, Bauer & Co GmbH - Dohlenstr 32 - Oberhausen NRW 46145 - GERMANY - - 00-22-CA (hex) Anviz Biometric Tech. Co., Ltd. - 0022CA (base 16) Anviz Biometric Tech. Co., Ltd. - 5th Floor, 4299 Jindu Road, - Shanghai 201108 - CHINA - - 00-22-CB (hex) IONODES Inc. - 0022CB (base 16) IONODES Inc. - 4001 boulevard Industriel - Laval Quebec H7L 4S3 - CANADA - - 00-22-CC (hex) SciLog, Inc. - 0022CC (base 16) SciLog, Inc. - 8845 South Greenview Drive - Suite 4 - Middleton Wisconsin 53562 - UNITED STATES - - 00-22-CD (hex) Ared Technology Co., Ltd. - 0022CD (base 16) Ared Technology Co., Ltd. - 6F-8 No.83 Sec.1, Nankan Rd. Luzhu Shiang - Taoyuan County Taiwan 33859 - TAIWAN, PROVINCE OF CHINA - - 00-22-CE (hex) Cisco, Service Provider Video Technology Group - 0022CE (base 16) Cisco, Service Provider Video Technology Group - 5030 Sugarloaf Parkway - Lawrenceville GA 30042 - UNITED STATES - - 00-22-CF (hex) PLANEX Communications INC - 0022CF (base 16) PLANEX Communications INC - 2F F ・ NISSAY Ebisu Bldg3-16-3 - Shibuya-ku Tokyo 150-0011 - JAPAN - - 00-22-D0 (hex) Polar Electro Oy - 0022D0 (base 16) Polar Electro Oy - Professorintie 5 - Kempele Oulu 90440 - FINLAND - - 00-22-D1 (hex) Albrecht Jung GmbH & Co. KG - 0022D1 (base 16) Albrecht Jung GmbH & Co. KG - Volmestraße 1 - Schalksmühle NRW 58579 - GERMANY - - 00-22-D2 (hex) All Earth Comércio de Eletrônicos LTDA. - 0022D2 (base 16) All Earth Comércio de Eletrônicos LTDA. - Rua Leonida Reimman Trotti, 343 - Parque Via Norte - Campinas São Paulo 13065-704 - BRAZIL - - 00-22-D3 (hex) Hub-Tech - 0022D3 (base 16) Hub-Tech - 77, Imae-dong - Bundang-gu - Seongnam-si Gyeonggi-do 463-829 - KOREA, REPUBLIC OF - - 00-22-D4 (hex) ComWorth Co., Ltd. - 0022D4 (base 16) ComWorth Co., Ltd. - 2-35-7 Nishimagome - Ohta-ku Tokyo 143-0026 - JAPAN - - 00-22-D5 (hex) Eaton Corp. Electrical Group Data Center Solutions - Pulizzi - 0022D5 (base 16) Eaton Corp. Electrical Group Data Center Solutions - Pulizzi - 3200 S. Susan St. - Santa Ana CA 92704 - UNITED STATES - - 00-22-D6 (hex) Cypak AB - 0022D6 (base 16) Cypak AB - P.O. BOX 2332 - Funckens Gränd 1 - Stockholm 103 18 - SWEDEN - - 00-22-D7 (hex) Nintendo Co., Ltd. - 0022D7 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-22-D8 (hex) Shenzhen GST Security and Safety Technology Limited - 0022D8 (base 16) Shenzhen GST Security and Safety Technology Limited - Room 502,Building 6 of Kupai Infomation Harbour, - No.2 Mengxi Road, HNTIA(North area),Nanshan District - Shenzhen Guangdong 518040 - CHINA - - 00-22-D9 (hex) Fortex Industrial Ltd. - 0022D9 (base 16) Fortex Industrial Ltd. - Flat 16, 12 /F.,Pacific Trade Centre - 2 Kai Hing Road,Kowloon Bay, - Kowloon Hong Kong 852 - CHINA - - 00-22-DA (hex) ANATEK, LLC - 0022DA (base 16) ANATEK, LLC - 3219 East Camelback Road - Suite 502 - Phoenix AZ 85018 - UNITED STATES - - 00-22-DB (hex) Translogic Corporation - 0022DB (base 16) Translogic Corporation - 10825 E. 47th Avenue - Denver Colorado 80239 - UNITED STATES - - 00-22-DC (hex) Vigil Health Solutions Inc. - 0022DC (base 16) Vigil Health Solutions Inc. - 2102-4464 Markham St - Victoria BC V8Z 7X8 - CANADA - - 00-22-DD (hex) Protecta Electronics Ltd - 0022DD (base 16) Protecta Electronics Ltd - Kesmark str 7/A - Budapest Hungary 1158 - HUNGARY - - 00-22-DE (hex) OPPO Digital, Inc. - 0022DE (base 16) OPPO Digital, Inc. - 2629B Terminal Blvd - Mountain View CA 94043 - UNITED STATES - - 00-22-DF (hex) TAMUZ Monitors - 0022DF (base 16) TAMUZ Monitors - Tiedenkamp 16 - Henstedt-Ulzburg SH 24558 - GERMANY - - 00-22-E0 (hex) Atlantic Software Technologies S.r.L. - 0022E0 (base 16) Atlantic Software Technologies S.r.L. - Via Martino Bassi, 9 - Milano 20148 - ITALY - - 00-22-E1 (hex) ZORT Labs, LLC. - 0022E1 (base 16) ZORT Labs, LLC. - 44H Dover Point Road - Dover NH 03820 - UNITED STATES - - 00-22-E2 (hex) WABTEC Transit Division - 0022E2 (base 16) WABTEC Transit Division - 130 Ridgeview Circle - Duncan SC 29334 - UNITED STATES - - 00-22-E3 (hex) Amerigon - 0022E3 (base 16) Amerigon - 21680 Haggerty Road - Suite 101 - Northville Michigan 48167 - UNITED STATES - - 00-22-E4 (hex) APASS TECHNOLOGY CO., LTD. - 0022E4 (base 16) APASS TECHNOLOGY CO., LTD. - 2F, No. 267, Sec. 3, Chengde Rd., - Datong District - TEIPEI 113 - TAIWAN, PROVINCE OF CHINA - - 00-22-E5 (hex) Fisher-Rosemount Systems Inc. - 0022E5 (base 16) Fisher-Rosemount Systems Inc. - 12301 Research Blvd - Building 3 - Austin Texas 78759 - UNITED STATES - - 00-22-E6 (hex) Intelligent Data - 0022E6 (base 16) Intelligent Data - Edf. Inverinnova – Avda. Punto Mobi, 4. Parque Científico Tecnológico - TECNOALCALÃ. Crta. Nacional II Madrid-Barcelona Km. 31,600 - Alcalá de Henares Madrid 28805 - SPAIN - - 00-22-E7 (hex) WPS Parking Systems - 0022E7 (base 16) WPS Parking Systems - Hoevenweg 11 - Eindhoven Noord-Brabant 5652 AW - NETHERLANDS - - 00-22-E8 (hex) Applition Co., Ltd. - 0022E8 (base 16) Applition Co., Ltd. - 509-1, Bundang Techno Park D-dong, - 151 Yatap-dong, Bundang-gu - SeongNam Kyunggi-do 463-760 - KOREA, REPUBLIC OF - - 00-22-E9 (hex) ProVision Communications - 0022E9 (base 16) ProVision Communications - 1 Portland Square - Bristol BS2 8RR - UNITED KINGDOM - - 00-22-EA (hex) Rustelcom Inc. - 0022EA (base 16) Rustelcom Inc. - Garagniy proezd, 1 - St.-Petersburg 192288 - RUSSIAN FEDERATION - - 00-22-EB (hex) Data Respons A/S - 0022EB (base 16) Data Respons A/S - Ellekær 6 - Herlev 2730 - DENMARK - - 00-22-EC (hex) IDEALBT TECHNOLOGY CORPORATION - 0022EC (base 16) IDEALBT TECHNOLOGY CORPORATION - 6F., NO.8, LANE 345, YANGGUANG ST., NEIHU DISTRICT - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-22-ED (hex) TSI Power Corporation - 0022ED (base 16) TSI Power Corporation - 1103 West Pierce Avenue - Antigo WI 54409 - UNITED STATES - - 00-22-EE (hex) Algo Communication Products Ltd - 0022EE (base 16) Algo Communication Products Ltd - 4500 Beedie Street - Burnaby BC V5J 5L2 - CANADA - - 00-22-EF (hex) iWDL Technologies - 0022EF (base 16) iWDL Technologies - 10522 Meinert Rd - Wexford PA 15090 - UNITED STATES - - 00-22-F0 (hex) 3 Greens Aviation Limited - 0022F0 (base 16) 3 Greens Aviation Limited - 10 Hedingham Close - Macclesfield SK10 3LZ - UNITED KINGDOM - - 00-22-F1 (hex) PRIVATE - 0022F1 (base 16) - - 00-22-F2 (hex) SunPower Corp - 0022F2 (base 16) SunPower Corp - 1414 Harbour Way South - Richmond CA 94804 - UNITED STATES - - 00-22-F3 (hex) SHARP Corporation - 0022F3 (base 16) SHARP Corporation - 22-22,Nagaike-cho - Abeno-ku - Osaka city Osaka prefecture 545-8522 - JAPAN - - 00-22-F4 (hex) AMPAK Technology, Inc. - 0022F4 (base 16) AMPAK Technology, Inc. - No. 8-1, Nanyuan 2nd Rd. - Jhongli Taoyuan 320 - TAIWAN, PROVINCE OF CHINA - - 00-22-F5 (hex) Advanced Realtime Tracking GmbH - 0022F5 (base 16) Advanced Realtime Tracking GmbH - Am Oeferl 6 - Weilheim Bayern D-82362 - GERMANY - - 00-22-F6 (hex) Syracuse Research Corporation - 0022F6 (base 16) Syracuse Research Corporation - 6225 Running Ridge Road - North Syracuse NY 13212 - UNITED STATES - - 00-22-F7 (hex) Conceptronic - 0022F7 (base 16) Conceptronic - Databankweg 7 - AMERSFOORT utrecht 3821 AL - NETHERLANDS - - 00-22-F8 (hex) PIMA Electronic Systems Ltd. - 0022F8 (base 16) PIMA Electronic Systems Ltd. - 5 Hatzoref St. - Holon 58856 - ISRAEL - - 00-22-F9 (hex) Pollin Electronic GmbH - 0022F9 (base 16) Pollin Electronic GmbH - Max-Pollin-Str. 1 - Pfoerring 85104 - GERMANY - - 00-22-FA (hex) Intel Corporate - 0022FA (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-22-FB (hex) Intel Corporate - 0022FB (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-22-FC (hex) Nokia Danmark A/S - 0022FC (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-22-FD (hex) Nokia Danmark A/S - 0022FD (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-22-FE (hex) Advanced Illumination - 0022FE (base 16) Advanced Illumination - 440 State Garage Road - Rochester Vermont 05767 - UNITED STATES - - 00-22-FF (hex) iWDL Technologies - 0022FF (base 16) iWDL Technologies - 10522 Meinert Rd - Wexford PA 15090 - UNITED STATES - - 00-23-00 (hex) Cayee Computer Ltd. - 002300 (base 16) Cayee Computer Ltd. - Units 1002-1003, 10/F, Join-In Hang Sing Centre - 71-75 Container Port Road - Kwai Chung N.T - HONG KONG - - 00-23-01 (hex) Witron Technology Limited - 002301 (base 16) Witron Technology Limited - 6/F, Xin Rui Building, 32 Tao Hua Road, Futian Free Trade Zone, - Shenzhen 86 - CHINA - - 00-23-02 (hex) Cobalt Digital, Inc. - 002302 (base 16) Cobalt Digital, Inc. - 2406 East University Avenue - Urbana IL 61802 - UNITED STATES - - 00-23-03 (hex) LITE-ON IT Corporation - 002303 (base 16) LITE-ON IT Corporation - 14F, No. 392, Ruey Kuang Road, Neihu - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-23-04 (hex) CISCO SYSTEMS, INC. - 002304 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-05 (hex) CISCO SYSTEMS, INC. - 002305 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-06 (hex) ALPS Electric Co., Ltd - 002306 (base 16) ALPS Electric Co., Ltd - 1-2-1, Okinouchi - Soma city Fukushima 976-8501 - JAPAN - - 00-23-07 (hex) FUTURE INNOVATION TECH CO.,LTD - 002307 (base 16) FUTURE INNOVATION TECH CO.,LTD - 312 3-DONG, GWANGMYUNG INDUSTRIAL COMPLEX 201 - HAAN-DONG - GWANGMYUNG GYUNGGI 423060 - KOREA, REPUBLIC OF - - 00-23-08 (hex) Arcadyan Technology Corporation - 002308 (base 16) Arcadyan Technology Corporation - 4F., No. 9 , Park Avenue II, - Science-based Industrial Park, - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-23-09 (hex) Janam Technologies LLC - 002309 (base 16) Janam Technologies LLC - 100 Crossways Park West - Suite 105 - Woodbury NY 11797 - UNITED STATES - - 00-23-0A (hex) ARBURG GmbH & Co KG - 00230A (base 16) ARBURG GmbH & Co KG - Arthur Hehl Straße - Lossburg D-72290 - GERMANY - - 00-23-0B (hex) ARRIS Group, Inc. - 00230B (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-0C (hex) CLOVER ELECTRONICS CO.,LTD. - 00230C (base 16) CLOVER ELECTRONICS CO.,LTD. - AKENO 306-1 - OBATA Chyou - ISE City MIE Prefecture 519-0501 - JAPAN - - 00-23-0D (hex) Nortel Networks - 00230D (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson Texas 75082-4399 - UNITED STATES - - 00-23-0E (hex) Gorba AG - 00230E (base 16) Gorba AG - Sandackerstrasse - Oberbüren SG CH - 9245 - SWITZERLAND - - 00-23-0F (hex) Hirsch Electronics Corporation - 00230F (base 16) Hirsch Electronics Corporation - 1900 Carnegie, Bldg B - Santa Ana CA 92705 - UNITED STATES - - 00-23-10 (hex) LNC Technology Co., Ltd. - 002310 (base 16) LNC Technology Co., Ltd. - 19F, No. 78-2, Sec. 3, Taichung Kang Rd. - Taichung 40764 - TAIWAN, PROVINCE OF CHINA - - 00-23-11 (hex) Gloscom Co., Ltd. - 002311 (base 16) Gloscom Co., Ltd. - #507 Changhyun Bldg. - 960-1 Hogye-dong - Anyang City Kyunggo-do 431-080 - KOREA, REPUBLIC OF - - 00-23-12 (hex) Apple - 002312 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-23-13 (hex) Qool Technologies Ltd. - 002313 (base 16) Qool Technologies Ltd. - Gotanda Chuo Bldg 8f, 2-3-5 - Higashi-gotanda - Shinagawa-ku Tokyo 141-0022 - JAPAN - - 00-23-14 (hex) Intel Corporate - 002314 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-23-15 (hex) Intel Corporate - 002315 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-23-16 (hex) KISAN ELECTRONICS CO - 002316 (base 16) KISAN ELECTRONICS CO - 317-15 - SUNG SU 2GA 3DONG - SEOUNG-DONG GU SEOUL 133-123 - KOREA, REPUBLIC OF - - 00-23-17 (hex) Lasercraft Inc - 002317 (base 16) Lasercraft Inc - 1450 Oakbrook Drive - Suite 900 - Norcross GA 30093 - UNITED STATES - - 00-23-18 (hex) Toshiba - 002318 (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - 00-23-19 (hex) Sielox LLC - 002319 (base 16) Sielox LLC - 170 East Ninth Ave. - Runnemede NJ 08078 - UNITED STATES - - 00-23-1A (hex) ITF Co., Ltd. - 00231A (base 16) ITF Co., Ltd. - 2-2-11 Nishiki-cho - Tachikawa-shi Tokyo 190-0022 - JAPAN - - 00-23-1B (hex) Danaher Motion - Kollmorgen - 00231B (base 16) Danaher Motion - Kollmorgen - 201 W. Rock Road - Radford VA 24141 - UNITED STATES - - 00-23-1C (hex) Fourier Systems Ltd. - 00231C (base 16) Fourier Systems Ltd. - 16 Hamelacha St - Rosh Haayin 48091 - ISRAEL - - 00-23-1D (hex) Deltacom Electronics Ltd - 00231D (base 16) Deltacom Electronics Ltd - 2F,ZIT,7km Tzarigradsko Shose - Sofia Sofia-grad 1784 - BULGARIA - - 00-23-1E (hex) Cezzer Multimedia Technologies - 00231E (base 16) Cezzer Multimedia Technologies - Pépinière d'entreprises CREATIC - 115 rue Claude Chappe - Plouzané 29280 - FRANCE - - 00-23-1F (hex) Guangda Electronic & Telecommunication Technology Development Co., Ltd. - 00231F (base 16) Guangda Electronic & Telecommunication Technology Development Co., Ltd. - #8 Gaopengdong Road, Gaoxin District - Chengdu Sichuan 610041 - CHINA - - 00-23-20 (hex) Nicira Networks - 002320 (base 16) Nicira Networks - 3460 W. Bayshore Rd. - Palo Alto CA 94303 - UNITED STATES - - 00-23-21 (hex) Avitech International Corp - 002321 (base 16) Avitech International Corp - 15333 NE 90th Street - Redmond WA 98052 - UNITED STATES - - 00-23-22 (hex) KISS Teknical Solutions, Inc. - 002322 (base 16) KISS Teknical Solutions, Inc. - 1583 S. Navajo Way - Chandler Arizona 85286 - UNITED STATES - - 00-23-23 (hex) Zylin AS - 002323 (base 16) Zylin AS - Auglendsdalen 78 - Stavanger 4017 - NORWAY - - 00-23-24 (hex) G-PRO COMPUTER - 002324 (base 16) G-PRO COMPUTER - first arrange C, YingHu industrial estate - QingXi Country - DongGuan City GuangDong Province 523648 - CHINA - - 00-23-25 (hex) IOLAN Holding - 002325 (base 16) IOLAN Holding - Mon Plaisir 26 - Etten Leur 4879AN - NETHERLANDS - - 00-23-26 (hex) Fujitsu Limited - 002326 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome,Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - 00-23-27 (hex) Shouyo Electronics CO., LTD - 002327 (base 16) Shouyo Electronics CO., LTD - 4F., No.8, Lane 345, Yang Kung St. - Taipei 11491 - TAIWAN, PROVINCE OF CHINA - - 00-23-28 (hex) ALCON TELECOMMUNICATIONS CO., LTD. - 002328 (base 16) ALCON TELECOMMUNICATIONS CO., LTD. - 2nd FL, NO 480-5, SEC. 6, YEN-PING N. RD., - SHIH-LIN - TAIPEI TAIWAN 111 - TAIWAN, PROVINCE OF CHINA - - 00-23-29 (hex) DDRdrive LLC - 002329 (base 16) DDRdrive LLC - 384 Madeline CT - Palo Alto CA 94306 - UNITED STATES - - 00-23-2A (hex) eonas IT-Beratung und -Entwicklung GmbH - 00232A (base 16) eonas IT-Beratung und -Entwicklung GmbH - Greifenhagener Str. 54 - Berlin 10437 - GERMANY - - 00-23-2B (hex) IRD A/S - 00232B (base 16) IRD A/S - Kullinggade 31 - Svendborg Fyn 5700 - DENMARK - - 00-23-2C (hex) Senticare - 00232C (base 16) Senticare - 161 Worcester Rd - Suite 305 - Framingham MA 01701 - UNITED STATES - - 00-23-2D (hex) SandForce - 00232D (base 16) SandForce - 12950 Saratoga Ave. - Saratoga California 95070-4658 - UNITED STATES - - 00-23-2E (hex) Kedah Electronics Engineering, LLC - 00232E (base 16) Kedah Electronics Engineering, LLC - Zelenograd, 445 - Moscow 124498 - RUSSIAN FEDERATION - - 00-23-2F (hex) Advanced Card Systems Ltd. - 00232F (base 16) Advanced Card Systems Ltd. - Unit 2010-13, Chevalier Commercial Centre, - 8 Wang Hoi Road, - Kowloon Bay, SAR - HONG KONG - - 00-23-30 (hex) DIZIPIA, INC. - 002330 (base 16) DIZIPIA, INC. - 15th Floor, East Wing, IT Venture Tower - 78 Garak-dong, Songpa-Gu, - Seoul 138160 - KOREA, REPUBLIC OF - - 00-23-31 (hex) Nintendo Co., Ltd. - 002331 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-23-32 (hex) Apple - 002332 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-23-33 (hex) CISCO SYSTEMS, INC. - 002333 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-34 (hex) CISCO SYSTEMS, INC. - 002334 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-35 (hex) Linkflex Co.,Ltd - 002335 (base 16) Linkflex Co.,Ltd - 5F. Min Young Bldg. 175-2 - Nonhyeon-Dong, Gangnam-Gu - Seoul 135-010 - KOREA, REPUBLIC OF - - 00-23-36 (hex) METEL s.r.o. - 002336 (base 16) METEL s.r.o. - Zizkuv Kopec 617 - Ceska Skalice Nachod 55203 - CZECH REPUBLIC - - 00-23-37 (hex) Global Star Solutions ULC - 002337 (base 16) Global Star Solutions ULC - 4600 Jacombs Road - Richmond BC V6V 3B1 - CANADA - - 00-23-38 (hex) OJ-Electronics A/S - 002338 (base 16) OJ-Electronics A/S - Stenager 13B - Sønderborg 6400 - DENMARK - - 00-23-39 (hex) Samsung Electronics - 002339 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-23-3A (hex) Samsung Electronics Co.,Ltd - 00233A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-23-3B (hex) C-Matic Systems Ltd - 00233B (base 16) C-Matic Systems Ltd - Warren Court - Park Road - Crowborough East Sussex TN6 2QX - UNITED KINGDOM - - 00-23-3C (hex) Alflex - 00233C (base 16) Alflex - Blauw-roodlaan 300 - ZOETERMEER 2718 SK - NETHERLANDS - - 00-23-3D (hex) Novero holding B.V. - 00233D (base 16) Novero holding B.V. - Parsevalstrasse 7A - Düsseldorf 40468 - GERMANY - - 00-23-3E (hex) Alcatel-Lucent-IPD - 00233E (base 16) Alcatel-Lucent-IPD - 701 E. Middlefield Rd. - Mountain View CA 94043 - UNITED STATES - - 00-23-3F (hex) Purechoice Inc - 00233F (base 16) Purechoice Inc - 11481 Rupp Drive - Burnsville MN 55337 - UNITED STATES - - 00-23-40 (hex) MiX Telematics - 002340 (base 16) MiX Telematics - Blaauwklip Office Park 2 - Cnr Strand & Webersvallei Rd - Stellenbosch Western Cape 7600 - SOUTH AFRICA - - 00-23-41 (hex) Siemens AB, Infrastructure & Cities, Building Technologies Division, IC BT SSP SP BA PR - 002341 (base 16) Siemens AB, Infrastructure & Cities, Building Technologies Division, IC BT SSP SP BA PR - Englundavaegen 7 - Solna SE-171 41 - SWEDEN - - 00-23-42 (hex) Coffee Equipment Company - 002342 (base 16) Coffee Equipment Company - 4216 6th Ave NW - Seattle WA 98107 - UNITED STATES - - 00-23-43 (hex) TEM AG - 002343 (base 16) TEM AG - Triststrasse 8 - Chur 7007 - SWITZERLAND - - 00-23-44 (hex) Objective Interface Systems, Inc. - 002344 (base 16) Objective Interface Systems, Inc. - 220 Spring Street, Suite 530 - Herndon VA 20170-6201 - UNITED STATES - - 00-23-45 (hex) Sony Ericsson Mobile Communications - 002345 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-23-46 (hex) Vestac - 002346 (base 16) Vestac - P.O. Box 7358 - Shrewsbury NJ 07702 - UNITED STATES - - 00-23-47 (hex) ProCurve Networking by HP - 002347 (base 16) ProCurve Networking by HP - 8000 Foothills Blvd - Roseville California 95747 - UNITED STATES - - 00-23-48 (hex) SAGEM COMMUNICATION - 002348 (base 16) SAGEM COMMUNICATION - 14 Rue Paul Dautier - Velizy 78457 - FRANCE - - 00-23-49 (hex) Helmholtz Centre Berlin for Material and Energy - 002349 (base 16) Helmholtz Centre Berlin for Material and Energy - Department FMD - Glienicker Strasse 100 - Berlin 14109 - GERMANY - - 00-23-4A (hex) PRIVATE - 00234A (base 16) - - 00-23-4B (hex) Inyuan Technology Inc. - 00234B (base 16) Inyuan Technology Inc. - No. 3, Singye St., - Gueishan Township - Taoyuan County 33341 - TAIWAN, PROVINCE OF CHINA - - 00-23-4C (hex) KTC AB - 00234C (base 16) KTC AB - F O Petersons gata 6 - Vastra Frolunda Gothenburg SE-42131 - SWEDEN - - 00-23-4D (hex) Hon Hai Precision Ind. Co., Ltd. - 00234D (base 16) Hon Hai Precision Ind. Co., Ltd. - 66, Chung Shan Rd.Tu-Cheng - Taipei Hsien Taiwan 236 - TAIWAN, PROVINCE OF CHINA - - 00-23-4E (hex) Hon Hai Precision Ind. Co., Ltd. - 00234E (base 16) Hon Hai Precision Ind. Co., Ltd. - 66,Chung Shan Rd.Tu-cheng - Taipei Hsien Taiwan 236 - TAIWAN, PROVINCE OF CHINA - - 00-23-4F (hex) Luminous Power Technologies Pvt. Ltd. - 00234F (base 16) Luminous Power Technologies Pvt. Ltd. - C8-C9, Community Center, - Behind Janak Cinema, Janakpuri, - New Delhi 110058 - INDIA - - 00-23-50 (hex) LynTec - 002350 (base 16) LynTec - 8401 Melrose Drive - Lenexa KS 66214 - UNITED STATES - - 00-23-51 (hex) 2Wire - 002351 (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-23-52 (hex) DATASENSOR S.p.A. - 002352 (base 16) DATASENSOR S.p.A. - Via Lavino, 265 - Monte San Pietro (BO) 40050 - ITALY - - 00-23-53 (hex) F E T Elettronica snc - 002353 (base 16) F E T Elettronica snc - Via Alessandro Manzoni 14/a - C/O Studio Commle Giorli - Poggibonsi Siena 53036 - ITALY - - 00-23-54 (hex) ASUSTek COMPUTER INC. - 002354 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 00-23-55 (hex) Kinco Automation(Shanghai) Ltd. - 002355 (base 16) Kinco Automation(Shanghai) Ltd. - Bldg1, No.1387, Zhangdong Road, - Zhangjiang Hi-tech Park, Pudong. - Shanghai 201203 - CHINA - - 00-23-56 (hex) Packet Forensics LLC - 002356 (base 16) Packet Forensics LLC - 420 S Smith Rd - Tempe AZ 85281 - UNITED STATES - - 00-23-57 (hex) Pitronot Technologies and Engineering P.T.E. Ltd. - 002357 (base 16) Pitronot Technologies and Engineering P.T.E. Ltd. - 8 Hatut st - Pardesiya 42815 - ISRAEL - - 00-23-58 (hex) SYSTEL SA - 002358 (base 16) SYSTEL SA - ZI DE BELLE AIRE - BP 31 - AYTRE 17440 - FRANCE - - 00-23-59 (hex) Benchmark Electronics ( Thailand ) Public Company Limited - 002359 (base 16) Benchmark Electronics ( Thailand ) Public Company Limited - 94 Moo 1, Hi-Tech Industrial Estate - Banlane - Bang Pa-in Ayudhaya 13160 - THAILAND - - 00-23-5A (hex) COMPAL INFORMATION (KUNSHAN) CO., Ltd. - 00235A (base 16) COMPAL INFORMATION (KUNSHAN) CO., Ltd. - NO 25, The 3rd street, - KuanShan Export Processing Zone - KuanShan SUZHOU 215300 - CHINA - - 00-23-5B (hex) Gulfstream - 00235B (base 16) Gulfstream - 32 Lummus Drive - RDC Lab R-08 - Savannah GA 31407 - UNITED STATES - - 00-23-5C (hex) Aprius, Inc. - 00235C (base 16) Aprius, Inc. - 440 N. Wolfe Rd - Sunnyvale CA 94085 - UNITED STATES - - 00-23-5D (hex) CISCO SYSTEMS, INC. - 00235D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-5E (hex) CISCO SYSTEMS, INC. - 00235E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-5F (hex) Silicon Micro Sensors GmbH - 00235F (base 16) Silicon Micro Sensors GmbH - Grenzstrasse 28 / Gebäude 32 - Dresden Saxony 01109 - GERMANY - - 00-23-60 (hex) Lookit Technology Co., Ltd - 002360 (base 16) Lookit Technology Co., Ltd - FL 8 Seashore Mansion - Bao'an CBD District - Shenzhen Guangdong 518100 - CHINA - - 00-23-61 (hex) Unigen Corporation - 002361 (base 16) Unigen Corporation - 45388 Warm Springs Blvd - Fremont CA 94539 - UNITED STATES - - 00-23-62 (hex) Goldline Controls - 002362 (base 16) Goldline Controls - 61 Whitecap Dr - North Kingstown RI 02852 - UNITED STATES - - 00-23-63 (hex) Zhuhai RaySharp Technology Co., Ltd. - 002363 (base 16) Zhuhai RaySharp Technology Co., Ltd. - No.119 of Huawei Road, Qianshan Science & Technology Park, - Zhuhai Guangdong 519070 - CHINA - - 00-23-64 (hex) Power Instruments Pte Ltd - 002364 (base 16) Power Instruments Pte Ltd - BLK 40 TOH GUAN RD EAST, #01-62 ENTERPRISE HUB - 608582 - SINGAPORE - - 00-23-65 (hex) ELKA-Elektronik GmbH - 002365 (base 16) ELKA-Elektronik GmbH - Lüdenscheid 104 - Lüdenscheid NRW 58515 - GERMANY - - 00-23-66 (hex) Beijing Siasun Electronic System Co.,Ltd. - 002366 (base 16) Beijing Siasun Electronic System Co.,Ltd. - Rm.1018 Huatian Bldg, No.6 Bei Xiaomachang - Haidian District - Beijing 100038 - CHINA - - 00-23-67 (hex) UniControls a.s. - 002367 (base 16) UniControls a.s. - Krenicka 2257 - Prague 10 100 00 - CZECH REPUBLIC - - 00-23-68 (hex) Zebra Technologies Inc - 002368 (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - 00-23-69 (hex) Cisco-Linksys, LLC - 002369 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 00-23-6A (hex) SmartRG Inc - 00236A (base 16) SmartRG Inc - 501 SE Columbia Shores Blvd - Suite 500 - Vancouver WA 98661 - UNITED STATES - - 00-23-6B (hex) Xembedded, Inc. - 00236B (base 16) Xembedded, Inc. - 1050 Highland Dr - Suite E - Ann Arbor MI 48108 - UNITED STATES - - 00-23-6C (hex) Apple - 00236C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-23-6D (hex) ResMed Ltd - 00236D (base 16) ResMed Ltd - 1, Elizabeth Macarthur Drive - Bella Vista NSW 2153 - AUSTRALIA - - 00-23-6E (hex) Burster GmbH & Co KG - 00236E (base 16) Burster GmbH & Co KG - Talstraße 1-5 - Gernsbach Baden-Württemberg 76593 - GERMANY - - 00-23-6F (hex) DAQ System - 00236F (base 16) DAQ System - Rm 913, SungNam Woolim Lions VAlley I, 311-3 - Sangdaeweon-Dong, Jungweon-Gu - Sungnam-Si Kyunggi-Do, 462-806 - KOREA, REPUBLIC OF - - 00-23-70 (hex) Snell - 002370 (base 16) Snell - Hartman House - Danehill - Reading Berks RG6 4PB - UNITED KINGDOM - - 00-23-71 (hex) SOAM Systel - 002371 (base 16) SOAM Systel - 182-13, Daerung Post Tower II, 1504 - Seoul Guro-dong, Guro-gu 152-847 - KOREA, REPUBLIC OF - - 00-23-72 (hex) MORE STAR INDUSTRIAL GROUP LIMITED - 002372 (base 16) MORE STAR INDUSTRIAL GROUP LIMITED - Rm1221-1225, F12 Sangda Science and Technology Building , - Keji Road , Hi-Tech Industrial Park, - Shenzhen Guangdong 518057 - CHINA - - 00-23-73 (hex) GridIron Systems, Inc. - 002373 (base 16) GridIron Systems, Inc. - 726 Palomar Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-23-74 (hex) ARRIS Group, Inc. - 002374 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-75 (hex) ARRIS Group, Inc. - 002375 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-76 (hex) HTC Corporation - 002376 (base 16) HTC Corporation - No.23 Xinghua Road - Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 00-23-77 (hex) Isotek Electronics Ltd - 002377 (base 16) Isotek Electronics Ltd - 9 Clayton Wood Bank - West Park Ring Road - Leeds LS16 6QZ - UNITED KINGDOM - - 00-23-78 (hex) GN Netcom A/S - 002378 (base 16) GN Netcom A/S - Lautrupbjerg 7 - P.O.Box 99 - Ballerup DK - 2750 - DENMARK - - 00-23-79 (hex) Union Business Machines Co. Ltd. - 002379 (base 16) Union Business Machines Co. Ltd. - Unit 2, 2/F, Block A, Hong Kong Industrial Centre, - 489-491 Castle Peak Road, - Lai Chi Kok Kowloon - HONG KONG - - 00-23-7A (hex) RIM - 00237A (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 00-23-7B (hex) WHDI LLC - 00237B (base 16) WHDI LLC - 2350 Mission College Blvd. - Suite 500 - Santa Clara CA 95054 - UNITED STATES - - 00-23-7C (hex) NEOTION - 00237C (base 16) NEOTION - ZI les Paluds - 165, avenue du Marin Blanc - AUBAGNE F-13400 - FRANCE - - 00-23-7D (hex) Hewlett-Packard Company - 00237D (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040802 - Houston TX 77070 - UNITED STATES - - 00-23-7E (hex) ELSTER GMBH - 00237E (base 16) ELSTER GMBH - KUHLMANNSTRASSE 10 - HAMELN 31785 - GERMANY - - 00-23-7F (hex) PLANTRONICS, INC. - 00237F (base 16) PLANTRONICS, INC. - 345 ENCINAL STREET - SANTA CRUZ CALIFORNIA 95060 - UNITED STATES - - 00-23-80 (hex) Nanoteq - 002380 (base 16) Nanoteq - PO Box 7991 - 1 Pieter Street, Highveld Park - Centurion Gauteng 0046 - SOUTH AFRICA - - 00-23-81 (hex) Lengda Technology(Xiamen) Co.,Ltd. - 002381 (base 16) Lengda Technology(Xiamen) Co.,Ltd. - 5/F, 47 Haijing South 2nd Road,Xiamen Export Processing Zone, Haicang District, - Xiamen Fujian 361026 - CHINA - - 00-23-82 (hex) Lih Rong Electronic Enterprise Co., Ltd. - 002382 (base 16) Lih Rong Electronic Enterprise Co., Ltd. - No. 2, Lane 387, Hsin Shu Rd. - Hsin Chuang City, Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 00-23-83 (hex) InMage Systems Inc - 002383 (base 16) InMage Systems Inc - 3255-1 Scott Blvd, #104 - Santa Clara CA 95054 - UNITED STATES - - 00-23-84 (hex) GGH Engineering s.r.l. - 002384 (base 16) GGH Engineering s.r.l. - Via Agucchi 84/2 - Bologna 40133 - ITALY - - 00-23-85 (hex) ANTIPODE - 002385 (base 16) ANTIPODE - 5 RUE DE DOUAI - PARIS ILE DE FRANCE 75009 - FRANCE - - 00-23-86 (hex) Tour & Andersson AB - 002386 (base 16) Tour & Andersson AB - Annelund - Ljung 524 80 - SWEDEN - - 00-23-87 (hex) ThinkFlood, Inc. - 002387 (base 16) ThinkFlood, Inc. - 138 Claflin St - Belmont MA 02478 - UNITED STATES - - 00-23-88 (hex) V.T. Telematica S.p.a. - 002388 (base 16) V.T. Telematica S.p.a. - Via Gorky, 21 - San Giuliano Milanese Milano 20098 - ITALY - - 00-23-89 (hex) HANGZHOU H3C Technologies Co., Ltd. - 002389 (base 16) HANGZHOU H3C Technologies Co., Ltd. - Oriental Electronics Bldg., #2, Chuangye Road£¬Shangdi Information Industry Base, - Haidian District, Beijing, P.R.China - Beijing 100085 - CHINA - - 00-23-8A (hex) Ciena Corporation - 00238A (base 16) Ciena Corporation - 920 Elkridge Landing - Linthicum MD 21090 - UNITED STATES - - 00-23-8B (hex) Quanta Computer Inc. - 00238B (base 16) Quanta Computer Inc. - NO. 211, WEN HWA 2RD.,KUEI SHAN HSIANG, TAO YUAN SHIEN, - TAIPEI TAIWAN 333 - TAIWAN, PROVINCE OF CHINA - - 00-23-8C (hex) PRIVATE - 00238C (base 16) - - 00-23-8D (hex) Techno Design Co., Ltd. - 00238D (base 16) Techno Design Co., Ltd. - 312-2 - Toriko, Nishihara-mura - Aso-gun Kumamoto-ken 861-2401 - JAPAN - - 00-23-8E (hex) Pirelli Tyre S.p.A. - 00238E (base 16) Pirelli Tyre S.p.A. - VIALE SARCA 222 - MILANO 20126 - ITALY - - 00-23-8F (hex) NIDEC COPAL CORPORATION - 00238F (base 16) NIDEC COPAL CORPORATION - 2-18-10,SHIMURA - ITABASHI-KU TOKYO 174-8550 - JAPAN - - 00-23-90 (hex) Algolware Corporation - 002390 (base 16) Algolware Corporation - 13F-5, No. 77, Sec. 1, Sintai 5th Rd., - Sijhih City, - Taipei County Taiwan 221 - TAIWAN, PROVINCE OF CHINA - - 00-23-91 (hex) Maxian - 002391 (base 16) Maxian - 21th Fl. KINS tower, 25-1 - Jeonja-dong, Bundang-gu - Seongnam-city Gyeonggi-do 463-847 - KOREA, REPUBLIC OF - - 00-23-92 (hex) Proteus Industries Inc. - 002392 (base 16) Proteus Industries Inc. - 340 Pioneer Way - Mountain View CA 94041 - UNITED STATES - - 00-23-93 (hex) AJINEXTEK - 002393 (base 16) AJINEXTEK - 9-3, Holimdong, Dalseogu - Daegu 704-240 - KOREA, REPUBLIC OF - - 00-23-94 (hex) Samjeon - 002394 (base 16) Samjeon - #1313-1 Joil-Ri, Samdong-Myeun,Ulju-Gun - Ulsan City South Korea 689-934 - KOREA, REPUBLIC OF - - 00-23-95 (hex) ARRIS Group, Inc. - 002395 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-96 (hex) ANDES TECHNOLOGY CORPORATION - 002396 (base 16) ANDES TECHNOLOGY CORPORATION - 2F,No. 1, Li-Hsin First Road, - Science-Based Industrial Park - Hsin-Chu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-23-97 (hex) Westell Technologies Inc. - 002397 (base 16) Westell Technologies Inc. - 11852 Presley Cr - Plainfield IL 60585 - UNITED STATES - - 00-23-98 (hex) Sky Control - 002398 (base 16) Sky Control - ul. Svornosti 41 - Bratislava BA 82 107 - SLOVAKIA - - 00-23-99 (hex) VD Division, Samsung Electronics Co. - 002399 (base 16) VD Division, Samsung Electronics Co. - 416, Maetan-3dong, yeongtong-gu, Suwon-city - Korea - Suwon 443-742 - KOREA, REPUBLIC OF - - 00-23-9A (hex) EasyData Hardware GmbH - 00239A (base 16) EasyData Hardware GmbH - Breslauer Str. 24 - Wehrheim Hessen D-61273 - GERMANY - - 00-23-9B (hex) Elster Solutions, LLC - 00239B (base 16) Elster Solutions, LLC - 208 South Rogers Lane - Raleigh North Carolina 27610 - UNITED STATES - - 00-23-9C (hex) Juniper Networks - 00239C (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-23-9D (hex) Mapower Electronics Co., Ltd - 00239D (base 16) Mapower Electronics Co., Ltd - No. 50 Minquan Road - Luzhu Shiang - Taoyuan County 33846 - TAIWAN, PROVINCE OF CHINA - - 00-23-9E (hex) Jiangsu Lemote Technology Corporation Limited - 00239E (base 16) Jiangsu Lemote Technology Corporation Limited - Menglan Industrial Park,Yushan - Changshu Jiangsu 215500 - CHINA - - 00-23-9F (hex) Institut für Prüftechnik - 00239F (base 16) Institut für Prüftechnik - Schulstraße 3 - Todtenweis Bayern 86447 - GERMANY - - 00-23-A0 (hex) Hana CNS Co., LTD. - 0023A0 (base 16) Hana CNS Co., LTD. - Taejang-dong 1720-52 Taejang-NongGong-Danji - Wonju Gangwon-do 220-962 - KOREA, REPUBLIC OF - - 00-23-A1 (hex) Trend Electronics Ltd - 0023A1 (base 16) Trend Electronics Ltd - Gut No. 350 - Village - Bhalgaon - Auranagabad Maharashtra 431210 - INDIA - - 00-23-A2 (hex) ARRIS Group, Inc. - 0023A2 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-A3 (hex) ARRIS Group, Inc. - 0023A3 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-A4 (hex) New Concepts Development Corp. - 0023A4 (base 16) New Concepts Development Corp. - 2650 Bridge Lane - Woodstock IL 60098 - UNITED STATES - - 00-23-A5 (hex) SageTV, LLC - 0023A5 (base 16) SageTV, LLC - 9800 S. La Cienega Blvd - Suite 905 - Inglewood CA 90301 - UNITED STATES - - 00-23-A6 (hex) E-Mon - 0023A6 (base 16) E-Mon - One Oxford Valley, Suite 418 - Langhorne PA 19047 - UNITED STATES - - 00-23-A7 (hex) Redpine Signals, Inc. - 0023A7 (base 16) Redpine Signals, Inc. - Plot 87, Sagar Society - Banjara Hills Road No. 2 - Hyderabad AP 500034 - INDIA - - 00-23-A8 (hex) Marshall Electronics - 0023A8 (base 16) Marshall Electronics - 1910 E Maple Ave - El Segundo Ca 90245 - UNITED STATES - - 00-23-A9 (hex) Beijing Detianquan Electromechanical Equipment Co., Ltd - 0023A9 (base 16) Beijing Detianquan Electromechanical Equipment Co., Ltd - No. 2 Chapeng Road, Haidian District, - Beijing 100091 - CHINA - - 00-23-AA (hex) HFR, Inc. - 0023AA (base 16) HFR, Inc. - 5F, Hana EZ Tower - 158, Gumi-dong, Bundang-gu - Sungnam-si Kyunggi-do 463-870 - KOREA, REPUBLIC OF - - 00-23-AB (hex) CISCO SYSTEMS, INC. - 0023AB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-AC (hex) CISCO SYSTEMS, INC. - 0023AC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-AD (hex) Xmark Corporation - 0023AD (base 16) Xmark Corporation - 309 Legget Drive - Ottawa Ontario K2K 3A3 - CANADA - - 00-23-AE (hex) Dell Inc. - 0023AE (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-23-AF (hex) ARRIS Group, Inc. - 0023AF (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-B0 (hex) COMXION Technology Inc. - 0023B0 (base 16) COMXION Technology Inc. - 11F, No. 111, Sec 2, Keelung Rd., Sinyi Distric - Taipei Taiwan 110 - TAIWAN, PROVINCE OF CHINA - - 00-23-B1 (hex) Longcheer Technology (Singapore) Pte Ltd - 0023B1 (base 16) Longcheer Technology (Singapore) Pte Ltd - 43 Kaki Bukit View, #04-01 , - Kaki Bukit Tech Park II, - 415970 - SINGAPORE - - 00-23-B2 (hex) Intelligent Mechatronic Systems Inc - 0023B2 (base 16) Intelligent Mechatronic Systems Inc - 161 Roger Street - Waterloo Ontario N2J 1B1 - CANADA - - 00-23-B3 (hex) Lyyn AB - 0023B3 (base 16) Lyyn AB - IDEON Science Park - Scheelevägen 17 - Lund 223 70 - SWEDEN - - 00-23-B4 (hex) Nokia Danmark A/S - 0023B4 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen v DK-1790 - DENMARK - - 00-23-B5 (hex) ORTANA LTD - 0023B5 (base 16) ORTANA LTD - OSTIM KOCASINAN SANAYI SITESI - 13. SOKAK NO:37-39 Y. MAHALLE - ANKARA 06370 - TURKEY - - 00-23-B6 (hex) SECURITE COMMUNICATIONS / HONEYWELL - 0023B6 (base 16) SECURITE COMMUNICATIONS / HONEYWELL - FONT DE L'ORME - 1198 AV DU DOCTEUR DONAT - MOUGINS FRANCE 06250 - FRANCE - - 00-23-B7 (hex) Q-Light Co., Ltd. - 0023B7 (base 16) Q-Light Co., Ltd. - 178-1 Woogye-Ri, Sangdong-Myun, - Gimhae-Si GyungsangNam-Do 621-812 - KOREA, REPUBLIC OF - - 00-23-B8 (hex) Sichuan Jiuzhou Electronic Technology Co.,Ltd - 0023B8 (base 16) Sichuan Jiuzhou Electronic Technology Co.,Ltd - No.259 Jiuzhou Road, - Mianyang Sichuan 621000 - CHINA - - 00-23-B9 (hex) EADS Deutschland GmbH - 0023B9 (base 16) EADS Deutschland GmbH - Willy Messerschmitt Str. - Ottobrunn Bavaria 85521 - GERMANY - - 00-23-BA (hex) Chroma - 0023BA (base 16) Chroma - 68, Hwa-Ya 1st Rd., Hwa-Ya Technical Park, - Kuei-Shan Hsiang, - Taoyuan Hsien Taiwan 333 - TAIWAN, PROVINCE OF CHINA - - 00-23-BB (hex) Schmitt Industries - 0023BB (base 16) Schmitt Industries - 2765 NW Nicolai St - Portland Oregon 97210 - UNITED STATES - - 00-23-BC (hex) EQ-SYS GmbH - 0023BC (base 16) EQ-SYS GmbH - Hinter den Gärten 15b - Treuenbrietzen OT Feldheim Brandenburg 14929 - GERMANY - - 00-23-BD (hex) Digital Ally, Inc. - 0023BD (base 16) Digital Ally, Inc. - 1218 Valley Ridge Drive - Grain Valley MO 64029 - UNITED STATES - - 00-23-BE (hex) Cisco SPVTG - 0023BE (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville GA 30044 - UNITED STATES - - 00-23-BF (hex) Mainpine, Inc. - 0023BF (base 16) Mainpine, Inc. - PO Box 241 - Wilsonville Oregon 97070-0241 - UNITED STATES - - 00-23-C0 (hex) Broadway Networks - 0023C0 (base 16) Broadway Networks - 1754 Technology Drive, Suite 208 - San Jose California 95110 - UNITED STATES - - 00-23-C1 (hex) Securitas Direct AB - 0023C1 (base 16) Securitas Direct AB - Angbatsbron 1 - Malmö 21120 - SWEDEN - - 00-23-C2 (hex) SAMSUNG Electronics. Co. LTD - 0023C2 (base 16) SAMSUNG Electronics. Co. LTD - 19th Fl., Korea Life Bldg. 1338-12 - Seocho 2 Dong Seocho-gu Domastic Sales& Marketing Division - Seoul 137-860 - KOREA, REPUBLIC OF - - 00-23-C3 (hex) LogMeIn, Inc. - 0023C3 (base 16) LogMeIn, Inc. - 500 Unicorn Park Drive - Woburn Massachusetts 01801 - UNITED STATES - - 00-23-C4 (hex) Lux Lumen - 0023C4 (base 16) Lux Lumen - Kernenergiestraat 53A - Wilrijk Antwerp 2610 - BELGIUM - - 00-23-C5 (hex) Radiation Safety and Control Services Inc - 0023C5 (base 16) Radiation Safety and Control Services Inc - 91 Portsmouth Ave - Stratham New Hampshire 03885 - UNITED STATES - - 00-23-C6 (hex) SMC Corporation - 0023C6 (base 16) SMC Corporation - 4-2-2, Kinunodai - Tsukuba Mirai-shi Ibaraki-ken 300-2493 - JAPAN - - 00-23-C7 (hex) AVSystem - 0023C7 (base 16) AVSystem - ul. Friedleina 4 - Kraków maÅ‚opolskie 30-009 - POLAND - - 00-23-C8 (hex) TEAM-R - 0023C8 (base 16) TEAM-R - Gragdanski str.111, A, 9-N - St. Petersburg 195265 - RUSSIAN FEDERATION - - 00-23-C9 (hex) Sichuan Tianyi Information Science & Technology Stock CO.,LTD - 0023C9 (base 16) Sichuan Tianyi Information Science & Technology Stock CO.,LTD - No.1,Hot Spring Highway,Dayi County - Chengdu Sichuan 611330 - CHINA - - 00-23-CA (hex) Behind The Set, LLC - 0023CA (base 16) Behind The Set, LLC - 2185 Knollwood Dr. - Boulder CO 80302 - UNITED STATES - - 00-23-CB (hex) Shenzhen Full-join Technology Co.,Ltd - 0023CB (base 16) Shenzhen Full-join Technology Co.,Ltd - 9/F,No.1,Xinrui Road,Hourui ,Xixiang Town, Bao'an District - ShenZhen GuangDong 518000 - CHINA - - 00-23-CC (hex) Nintendo Co., Ltd. - 0023CC (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-23-CD (hex) TP-LINK TECHNOLOGIES CO., LTD. - 0023CD (base 16) TP-LINK TECHNOLOGIES CO., LTD. - South Building, No.5 Keyuan Road, Central Zone, - Science & Technology Park Nanshan - Shenzhen Guangdong 518000 - CHINA - - 00-23-CE (hex) KITA DENSHI CORPORATION - 0023CE (base 16) KITA DENSHI CORPORATION - 12F TOKYO-NISHIIKEBUKURO Bilg., - 1-7-7, Nishi-ikebukuro - Toshima-ku, Tokyo 171-0021 - JAPAN - - 00-23-CF (hex) CUMMINS-ALLISON CORP. - 0023CF (base 16) CUMMINS-ALLISON CORP. - 891 FEEHANVILLE DRIVE - MT. PROSPECT IL 60056 - UNITED STATES - - 00-23-D0 (hex) Uniloc USA Inc. - 0023D0 (base 16) Uniloc USA Inc. - 3333 Michelson Drive - Suite 600 - Irvine CA 92612 - UNITED STATES - - 00-23-D1 (hex) TRG - 0023D1 (base 16) TRG - Wisma Kosgoro 13th Floor - Jl. MH. Thamrin 53 - Jakarta Pusat 10350 - INDONESIA - - 00-23-D2 (hex) Inhand Electronics, Inc. - 0023D2 (base 16) Inhand Electronics, Inc. - 30 West Gude Drive - Suite 550 - Rockville Maryland 20850 - UNITED STATES - - 00-23-D3 (hex) AirLink WiFi Networking Corp. - 0023D3 (base 16) AirLink WiFi Networking Corp. - 19F-1 Room A , No.97, Sec 4, Chung Hsin Rd., - San Chung City, Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 00-23-D4 (hex) Texas Instruments - 0023D4 (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-23-D5 (hex) WAREMA electronic GmbH - 0023D5 (base 16) WAREMA electronic GmbH - Dillberg 33 - Marktheidenfeld Bavaria 97828 - GERMANY - - 00-23-D6 (hex) Samsung Electronics Co.,LTD - 0023D6 (base 16) Samsung Electronics Co.,LTD - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-23-D7 (hex) Samsung Electronics - 0023D7 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-23-D8 (hex) Ball-It Oy - 0023D8 (base 16) Ball-It Oy - Uusikatu 24 G 76 - Oulu 90100 - FINLAND - - 00-23-D9 (hex) Banner Engineering - 0023D9 (base 16) Banner Engineering - 9714 10th Ave. N. - Plymouth MN 55441 - UNITED STATES - - 00-23-DA (hex) Industrial Computer Source (Deutschland)GmbH - 0023DA (base 16) Industrial Computer Source (Deutschland)GmbH - Marie-Curie-Straße 9 - Pulheim NRW 50259 - GERMANY - - 00-23-DB (hex) saxnet gmbh - 0023DB (base 16) saxnet gmbh - Willy-Brandt-Ring 1 - Oelsnitz Sachsen 08606 - GERMANY - - 00-23-DC (hex) Benein, Inc - 0023DC (base 16) Benein, Inc - Hyojachonjesangga228 B9, 297, - seohyun-dong, bundang-gu - Sengnam-si Kyunggi-do 463-818 - KOREA, REPUBLIC OF - - 00-23-DD (hex) ELGIN S.A. - 0023DD (base 16) ELGIN S.A. - RUA BARAO DE CAMPINAS, 305 - CAMPOS ELISEOS - São Paulo 01201-901 - BRAZIL - - 00-23-DE (hex) Ansync Inc. - 0023DE (base 16) Ansync Inc. - 4970 Robert J Matthews Pky - Suite 160 - El Dorado Hills CA 95762 - UNITED STATES - - 00-23-DF (hex) Apple - 0023DF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-23-E0 (hex) INO Therapeutics LLC - 0023E0 (base 16) INO Therapeutics LLC - 2902 Dairy Drive - Madison WI 53718 - UNITED STATES - - 00-23-E1 (hex) Cavena Image Products AB - 0023E1 (base 16) Cavena Image Products AB - Nytorpsvägen 26 - Täby Stockholm se-183 53 - SWEDEN - - 00-23-E2 (hex) SEA Signalisation - 0023E2 (base 16) SEA Signalisation - 20-22 Rue Pierre Mendès France - BP 231 - Vaulx en Velin CEDEX 69515 - FRANCE - - 00-23-E3 (hex) Microtronic AG - 0023E3 (base 16) Microtronic AG - Duennernstrasse 32 - Oensingen Solothurn 4702 - SWITZERLAND - - 00-23-E4 (hex) IPnect co. ltd. - 0023E4 (base 16) IPnect co. ltd. - 808 albatross B/D 237-18 - Gasan-dong, Geumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 00-23-E5 (hex) IPaXiom Networks - 0023E5 (base 16) IPaXiom Networks - Aston Court - Kingsmead Business Park, Frederick Place - High Wycombe Buckinghamshire HP11 1LA - UNITED KINGDOM - - 00-23-E6 (hex) Pirkus, Inc. - 0023E6 (base 16) Pirkus, Inc. - 2F,1-1-2 - Shimura - Itabashi-ku Tokyo 174-0056 - JAPAN - - 00-23-E7 (hex) Hinke A/S - 0023E7 (base 16) Hinke A/S - Tingbjergvej 2 - Bjaeverskov DK-4632 - DENMARK - - 00-23-E8 (hex) Demco Corp. - 0023E8 (base 16) Demco Corp. - #919, Doosan Venturedigm, 126-1 - Pyungchon-Dong, Dongan-Ku - Anyang-Si Kyungki-Do 431-070 - KOREA, REPUBLIC OF - - 00-23-E9 (hex) F5 Networks, Inc. - 0023E9 (base 16) F5 Networks, Inc. - 401 Elliott Ave. W. - Seattle WA 98119 - UNITED STATES - - 00-23-EA (hex) CISCO SYSTEMS, INC. - 0023EA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-EB (hex) CISCO SYSTEMS, INC. - 0023EB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-23-EC (hex) Algorithmix GmbH - 0023EC (base 16) Algorithmix GmbH - Klettgaustrasse 21 - Waldshut-Tiengen BW 79761 - GERMANY - - 00-23-ED (hex) ARRIS Group, Inc. - 0023ED (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-EE (hex) ARRIS Group, Inc. - 0023EE (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-23-EF (hex) Zuend Systemtechnik AG - 0023EF (base 16) Zuend Systemtechnik AG - Industriestrasse 8 - Altstaetten SG 9450 - SWITZERLAND - - 00-23-F0 (hex) Shanghai Jinghan Weighing Apparatus Co. Ltd. - 0023F0 (base 16) Shanghai Jinghan Weighing Apparatus Co. Ltd. - Building 58, No.99 Chunguang Road, Xinzhuang Industrial Zone,Minhang, - Shanghai 201108 - CHINA - - 00-23-F1 (hex) Sony Ericsson Mobile Communications - 0023F1 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund SkÃ¥ne 22188 - SWEDEN - - 00-23-F2 (hex) TVLogic - 0023F2 (base 16) TVLogic - suite 914 ACE Techno Tower-9th - Gasan-dong - Geumcheon-gu SEOUL 153-782 - KOREA, REPUBLIC OF - - 00-23-F3 (hex) Glocom, Inc. - 0023F3 (base 16) Glocom, Inc. - 22 Firstfield Road - Suite 125 - Gaithersburg Maryland 20878 - UNITED STATES - - 00-23-F4 (hex) Masternaut - 0023F4 (base 16) Masternaut - 4, rue Charles Cros - Louviers 27407 - FRANCE - - 00-23-F5 (hex) WILO SE - 0023F5 (base 16) WILO SE - Nortkirchenstraße 100 - D - 44263 Dortmund NRW 44263 - GERMANY - - 00-23-F6 (hex) Softwell Technology Co., Ltd. - 0023F6 (base 16) Softwell Technology Co., Ltd. - 4F, No. 419, Jhonghe Rd., Yonghe City, - Taipei County 234 - TAIWAN, PROVINCE OF CHINA - - 00-23-F7 (hex) PRIVATE - 0023F7 (base 16) - - 00-23-F8 (hex) ZyXEL Communications Corporation - 0023F8 (base 16) ZyXEL Communications Corporation - NO.6 Innovation Road II, - Science Park, - Hsin-Chu, Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-23-F9 (hex) Double-Take Software, INC. - 0023F9 (base 16) Double-Take Software, INC. - 8470 Allison Pointe Blvd - Suite 300 - Indianapolis IN 46250 - UNITED STATES - - 00-23-FA (hex) RG Nets, Inc. - 0023FA (base 16) RG Nets, Inc. - 316 California Ave. - Reno NV 89501 - UNITED STATES - - 00-23-FB (hex) IP Datatel, LLC. - 0023FB (base 16) IP Datatel, LLC. - 13110 Southwest Freeway - Sugar Land Texas 77478 - UNITED STATES - - 00-23-FC (hex) Ultra Stereo Labs, Inc - 0023FC (base 16) Ultra Stereo Labs, Inc - 181 Bonetti Drive - San Luis Obispo CA 93401 - UNITED STATES - - 00-23-FD (hex) AFT Atlas Fahrzeugtechnik GmbH - 0023FD (base 16) AFT Atlas Fahrzeugtechnik GmbH - Gewerbestraße 14 - Werdohl 58791 - GERMANY - - 00-23-FE (hex) Biodevices, SA - 0023FE (base 16) Biodevices, SA - Rua 5 de Outubro 309 - Porto 4100-175 - PORTUGAL - - 00-23-FF (hex) Beijing HTTC Technology Ltd. - 0023FF (base 16) Beijing HTTC Technology Ltd. - B-13D-3 Keshi Building,Jia No.28 Xinxi Road,SHANGDI IT Industry Base - Beijing 100085 - CHINA - - 00-24-00 (hex) Nortel Networks - 002400 (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson TX 75082 - UNITED STATES - - 00-24-01 (hex) D-Link Corporation - 002401 (base 16) D-Link Corporation - No.289, Xinhu 3rd. - Neihu District Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-24-02 (hex) Op-Tection GmbH - 002402 (base 16) Op-Tection GmbH - Borsigstraße 80 - Heinsberg Germany 52525 - GERMANY - - 00-24-03 (hex) Nokia Danmark A/S - 002403 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-24-04 (hex) Nokia Danmark A/S - 002404 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-24-05 (hex) Dilog Nordic AB - 002405 (base 16) Dilog Nordic AB - Faktorvägen 9 - Kungsbacka Halland 439 34 - SWEDEN - - 00-24-06 (hex) Pointmobile - 002406 (base 16) Pointmobile - 301,World Meridian Verture Center-1 60-24 - Gasan-dong - Seoul Geumcheon-gu 153781 - KOREA, REPUBLIC OF - - 00-24-07 (hex) TELEM SAS - 002407 (base 16) TELEM SAS - 16, RUE DE L'ETANG - GIERES RHONE ALPES 38610 - FRANCE - - 00-24-08 (hex) Pacific Biosciences - 002408 (base 16) Pacific Biosciences - 1505 Adams Drive - Menlo Park CA 94025 - UNITED STATES - - 00-24-09 (hex) The Toro Company - 002409 (base 16) The Toro Company - 5825 Jasmine Street - Riverside CA 92504 - UNITED STATES - - 00-24-0A (hex) US Beverage Net - 00240A (base 16) US Beverage Net - 1001 W. Fayette Street - 3A - Syracuse NY 13204 - UNITED STATES - - 00-24-0B (hex) Virtual Computer Inc. - 00240B (base 16) Virtual Computer Inc. - 3 LAN Drive - Westford MA 01886 - UNITED STATES - - 00-24-0C (hex) DELEC GmbH - 00240C (base 16) DELEC GmbH - Ruheweg 17-21 - Göllheim Rheinland-Pfalz 67307 - GERMANY - - 00-24-0D (hex) OnePath Networks LTD. - 00240D (base 16) OnePath Networks LTD. - 8 Hartom St - Jerusalem 91450 - ISRAEL - - 00-24-0E (hex) Inventec Besta Co., Ltd. - 00240E (base 16) Inventec Besta Co., Ltd. - 10FL, No.36, Lane 513, Rui Guang Road, Nei Hu Dist. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-24-0F (hex) Ishii Tool & Engineering Corporation - 00240F (base 16) Ishii Tool & Engineering Corporation - 2-5-60 Higashi-Omichi - Oita 870-0823 - JAPAN - - 00-24-10 (hex) NUETEQ Technology,Inc. - 002410 (base 16) NUETEQ Technology,Inc. - 11F, No. 112, Sec. 1, Zhong-Xiao E Rd. - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 00-24-11 (hex) PharmaSmart LLC - 002411 (base 16) PharmaSmart LLC - 3495 Winton Place - Bldg A, Suite 1 - Rochester NY 14623 - UNITED STATES - - 00-24-12 (hex) Benign Technologies Co, Ltd. - 002412 (base 16) Benign Technologies Co, Ltd. - 504 room, 5F, South building, Forsafe Tower, - South One Street, Hi-Tech Zone, - Shenzhen Guangdong 518057 - CHINA - - 00-24-13 (hex) CISCO SYSTEMS, INC. - 002413 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-14 (hex) CISCO SYSTEMS, INC. - 002414 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-15 (hex) Magnetic Autocontrol GmbH - 002415 (base 16) Magnetic Autocontrol GmbH - Grienmatt 20 - Schopfheim D-79650 - GERMANY - - 00-24-16 (hex) Any Use - 002416 (base 16) Any Use - LG APT 211-1805, - Shinbong-Dong, Suji-Gu, - Yongin City Gyeong-Gi Province 448-150 - KOREA, REPUBLIC OF - - 00-24-17 (hex) Thomson Telecom Belgium - 002417 (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - Edegem - Antwerp B-2650 - BELGIUM - - 00-24-18 (hex) Nextwave Semiconductor - 002418 (base 16) Nextwave Semiconductor - 3611 Valley Centre Dr - San Diego CA 92130 - UNITED STATES - - 00-24-19 (hex) PRIVATE - 002419 (base 16) - - 00-24-1A (hex) Red Beetle Inc. - 00241A (base 16) Red Beetle Inc. - 898 Silas Deane Highway - Wethersfield CT 06109 - UNITED STATES - - 00-24-1B (hex) iWOW Communications Pte Ltd - 00241B (base 16) iWOW Communications Pte Ltd - 1 Lorong 2 Toa Payoh #04-01 - Yellow Pages Building - 319637 - SINGAPORE - - 00-24-1C (hex) FuGang Electronic (DG) Co.,Ltd - 00241C (base 16) FuGang Electronic (DG) Co.,Ltd - Industry Street, Dong-Keng - Guang Dong Province - Dong Guan City 523448 - CHINA - - 00-24-1D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 00241D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - No.215,Nan-Ping Road, - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 00-24-1E (hex) Nintendo Co., Ltd. - 00241E (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-24-1F (hex) DCT-Delta GmbH - 00241F (base 16) DCT-Delta GmbH - Bodanrückstraße 1 - Bodman - Ludwigshafen Baden-Württemberg 78351 - GERMANY - - 00-24-20 (hex) NetUP Inc. - 002420 (base 16) NetUP Inc. - Olof Palme st., 1, sect. 7 - Moscow 119311 - RUSSIAN FEDERATION - - 00-24-21 (hex) MICRO-STAR INT'L CO., LTD. - 002421 (base 16) MICRO-STAR INT'L CO., LTD. - No.69, Li-De St - Jung-Ho City - Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-24-22 (hex) Knapp Logistik Automation GmbH - 002422 (base 16) Knapp Logistik Automation GmbH - Günter Knapp-Straße 5-7 - Hart bei Graz Styria 8075 - AUSTRIA - - 00-24-23 (hex) AzureWave Technologies (Shanghai) Inc. - 002423 (base 16) AzureWave Technologies (Shanghai) Inc. - NO. 8, LANE 66, CHENGBAO RD. - MALU COUNTY, JIADING DISTRICT, - SHANGHAI 201801 - CHINA - - 00-24-24 (hex) Axis Network Technology - 002424 (base 16) Axis Network Technology - Unit 10, Midshires Bus Park - Smeaton Close - Aylesbury Bucks HP19 8HL - UNITED KINGDOM - - 00-24-25 (hex) Shenzhenshi chuangzhicheng Technology Co.,Ltd - 002425 (base 16) Shenzhenshi chuangzhicheng Technology Co.,Ltd - 5th Floor,Block2,25th Building,Industrial Zone West Keyuan Sci-tech Garden Nanshan Districh,Shenzhen - Shenzhen Guangdong 518057 - CHINA - - 00-24-26 (hex) NOHMI BOSAI LTD. - 002426 (base 16) NOHMI BOSAI LTD. - 7-3,Kudan-Minami 4-Chome, - Chiyoda-ku - Tokyo 102-8277 - JAPAN - - 00-24-27 (hex) SSI COMPUTER CORP - 002427 (base 16) SSI COMPUTER CORP - 4F, NO4, LANE 235, BAO CHIAO ROAD - HSIN TIEN TAIPEI 231 - TAIWAN, PROVINCE OF CHINA - - 00-24-28 (hex) EnergyICT - 002428 (base 16) EnergyICT - Theodoor Sevenslaan 104a - Kortrijk 8500 - BELGIUM - - 00-24-29 (hex) MK MASTER INC. - 002429 (base 16) MK MASTER INC. - 6F, -1, NO. 110,SEC. 3, JHONGSHAN RD., - JHONG-HE CITY, TAIPEI COUNTY 235 - TAIWAN, PROVINCE OF CHINA - - 00-24-2A (hex) Hittite Microwave Corporation - 00242A (base 16) Hittite Microwave Corporation - 20 Alpha Rd - Chelmsford MA 01824 - UNITED STATES - - 00-24-2B (hex) Hon Hai Precision Ind.Co.,Ltd. - 00242B (base 16) Hon Hai Precision Ind.Co.,Ltd. - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien Taiwan 236 - TAIWAN, PROVINCE OF CHINA - - 00-24-2C (hex) Hon Hai Precision Ind. Co., Ltd. - 00242C (base 16) Hon Hai Precision Ind. Co., Ltd. - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 00-24-2E (hex) Datastrip Inc. - 00242E (base 16) Datastrip Inc. - 1 Waterview Drive - Suite 103 - Shelton CT 06484 - UNITED STATES - - 00-24-2F (hex) Micron - 00242F (base 16) Micron - 8000 S Federal Way - Boise ID 83716 - UNITED STATES - - 00-24-30 (hex) Ruby Tech Corp. - 002430 (base 16) Ruby Tech Corp. - 3F, NO. 1, Lane 50, Nan Kang Road, Sec. 3, - Taipei 11510 - TAIWAN, PROVINCE OF CHINA - - 00-24-31 (hex) Uni-v co.,ltd - 002431 (base 16) Uni-v co.,ltd - 5/F,COFCO Property Tower, - the 3rd Area, Bao'an - Shenzhen Guangdong 518126 - CHINA - - 00-24-32 (hex) Neostar Technology Co.,LTD - 002432 (base 16) Neostar Technology Co.,LTD - 8F., No.102, Sec. 1, Sintai 5th Rd. - Sijhih City Taipei 22161 - TAIWAN, PROVINCE OF CHINA - - 00-24-33 (hex) Alps Electric Co., Ltd - 002433 (base 16) Alps Electric Co., Ltd - 1-2-1, Okinouchi - Soma city Fukushima-ken 976-8501 - JAPAN - - 00-24-34 (hex) Lectrosonics, Inc. - 002434 (base 16) Lectrosonics, Inc. - 581 Laser Rd. - Rio Rancho NM 87124 - UNITED STATES - - 00-24-35 (hex) WIDE CORPORATION - 002435 (base 16) WIDE CORPORATION - LEADERS TOWER 7TH FL., GOMAE-DONG, GIHEUNG-GU - YONGIN GYEONGGI 446-901 - KOREA, REPUBLIC OF - - 00-24-36 (hex) Apple - 002436 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-24-37 (hex) Motorola - BSG - 002437 (base 16) Motorola - BSG - 1101 Marina Village Pkwy - Ste 200 - Alameda CA 94501 - UNITED STATES - - 00-24-38 (hex) Brocade Communications Systems, Inc - 002438 (base 16) Brocade Communications Systems, Inc - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-24-39 (hex) Digital Barriers Advanced Technologies - 002439 (base 16) Digital Barriers Advanced Technologies - 4th Floor - 39 St Vincent Place - Glasgow Lanarkshire G1 2QQ - UNITED KINGDOM - - 00-24-3A (hex) Ludl Electronic Products - 00243A (base 16) Ludl Electronic Products - 171 Brady Ave - Hawthorne NY 10532 - UNITED STATES - - 00-24-3B (hex) CSSI (S) Pte Ltd - 00243B (base 16) CSSI (S) Pte Ltd - 70 Bendemeer Road Unit 04-04 - 339940 - SINGAPORE - - 00-24-3C (hex) S.A.A.A. - 00243C (base 16) S.A.A.A. - Z.A. Croix Saint Mathieu - GALLARDON Eure et Loir 28320 - FRANCE - - 00-24-3D (hex) Emerson Appliance Motors and Controls - 00243D (base 16) Emerson Appliance Motors and Controls - 1901 South St. - Elgin IL 60123 - UNITED STATES - - 00-24-3F (hex) Storwize, Inc. - 00243F (base 16) Storwize, Inc. - 11 Alatlef St. - Yehud 56216 - ISRAEL - - 00-24-40 (hex) Halo Monitoring, Inc. - 002440 (base 16) Halo Monitoring, Inc. - 515 Sparkman Dr. - Huntsville AL 35816 - UNITED STATES - - 00-24-41 (hex) Wanzl Metallwarenfabrik GmbH - 002441 (base 16) Wanzl Metallwarenfabrik GmbH - Bubesheimer Straße 4 - Leipheim Bavaria 89340 - GERMANY - - 00-24-42 (hex) Axona Limited - 002442 (base 16) Axona Limited - Unit 4U St. Albans Enterprise Centre - Long Spring, Porters Wood - St. Albans Herts AL3 6EN - UNITED KINGDOM - - 00-24-43 (hex) Nortel Networks - 002443 (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson TX 75082 - UNITED STATES - - 00-24-44 (hex) Nintendo Co., Ltd. - 002444 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-24-45 (hex) CommScope Canada Inc. - 002445 (base 16) CommScope Canada Inc. - 8400 Boul. Du Golf - Montreal Quebec H1J 3A1 - CANADA - - 00-24-46 (hex) MMB Research Inc. - 002446 (base 16) MMB Research Inc. - 35 Prince Arthur Ave. - Toronto Ontario M5R 1B2 - CANADA - - 00-24-47 (hex) Kaztek Systems - 002447 (base 16) Kaztek Systems - 17 Bromfield Road - Acton MA 01720 - UNITED STATES - - 00-24-48 (hex) SpiderCloud Wireless, Inc - 002448 (base 16) SpiderCloud Wireless, Inc - 3900 Freedom Circle, Suite 104 - Santa Clara CA 95054 - UNITED STATES - - 00-24-49 (hex) Shen Zhen Lite Star Electronics Technology Co., Ltd - 002449 (base 16) Shen Zhen Lite Star Electronics Technology Co., Ltd - Xinghong Science Park,1st Ind.Area, - Fenghuangguang, Xixiang,Baoan Area - ShenZhen GuangDong 518102 - CHINA - - 00-24-4A (hex) Voyant International - 00244A (base 16) Voyant International - 444 Castro St - Mountain View CA 94041 - UNITED STATES - - 00-24-4B (hex) PERCEPTRON INC - 00244B (base 16) PERCEPTRON INC - 47827 HALYARD DR - PO #CC67348 - PLYMOUTH MI 48170 - UNITED STATES - - 00-24-4C (hex) Solartron Metrology Ltd - 00244C (base 16) Solartron Metrology Ltd - Steyning Way - Bognor Regis West Sussex PO20 9ST - UNITED KINGDOM - - 00-24-4D (hex) Hokkaido Electronics Corporation - 00244D (base 16) Hokkaido Electronics Corporation - 1-1 East 10 North 10 - Higashi-ku - Sapporo Hokkaido 065-0010 - JAPAN - - 00-24-4E (hex) RadChips, Inc. - 00244E (base 16) RadChips, Inc. - 422 East Vermijo Ave. - Suite 401 - Colorado Springs CO 80903 - UNITED STATES - - 00-24-4F (hex) Asantron Technologies Ltd. - 00244F (base 16) Asantron Technologies Ltd. - 3F-1, No.30 Jihe Rd., 111 - Shihlin District - Taipei 11166 - TAIWAN, PROVINCE OF CHINA - - 00-24-50 (hex) CISCO SYSTEMS, INC. - 002450 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-51 (hex) CISCO SYSTEMS, INC. - 002451 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-52 (hex) Silicon Software GmbH - 002452 (base 16) Silicon Software GmbH - Steubenstrasse 46 - Mannheim Baden-Wuerttemberg 68163 - GERMANY - - 00-24-53 (hex) Initra d.o.o. - 002453 (base 16) Initra d.o.o. - Slomskova 33 - Ljubljana 1000 - SLOVENIA - - 00-24-54 (hex) Samsung Electronics CO., LTD - 002454 (base 16) Samsung Electronics CO., LTD - 416, Maetan 3Dong, Yeongtong-Gu - Suwon City, Geyonggi Do, Korea - Suwon Geyonggi 443742 - KOREA, REPUBLIC OF - - 00-24-55 (hex) MuLogic BV - 002455 (base 16) MuLogic BV - Olivier van Noortstraat 4 - Schiedam ZH 3124LA - NETHERLANDS - - 00-24-56 (hex) 2Wire - 002456 (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-24-58 (hex) PA Bastion CC - 002458 (base 16) PA Bastion CC - 97, liter K, Buddyonnovsky ave. - Rostov-on-Don 344011 - RUSSIAN FEDERATION - - 00-24-59 (hex) ABB STOTZ-KONTAKT GmbH - 002459 (base 16) ABB STOTZ-KONTAKT GmbH - Eppelheimer Straße 82 - STO/KE1 - Heidelberg 69123 - GERMANY - - 00-24-5A (hex) Nanjing Panda Electronics Company Limited - 00245A (base 16) Nanjing Panda Electronics Company Limited - Zhongshan EastRoad 301, - NANJING JIANGSU 210016 - CHINA - - 00-24-5B (hex) RAIDON TECHNOLOGY, INC. - 00245B (base 16) RAIDON TECHNOLOGY, INC. - 4F-8, NO.16, Lane 609, Sec.5, Chung-Hsin Rd., - San-Chung City Taipei county, 24159 - TAIWAN, PROVINCE OF CHINA - - 00-24-5C (hex) Design-Com Technologies Pty. Ltd. - 00245C (base 16) Design-Com Technologies Pty. Ltd. - 14 Redland Drive - Mitcham Victoria 3132 - AUSTRALIA - - 00-24-5D (hex) Terberg besturingstechniek B.V. - 00245D (base 16) Terberg besturingstechniek B.V. - Lage Dijk-Noord 3 - IJsselstein Utrecht 3401 VA - NETHERLANDS - - 00-24-5E (hex) Hivision Co.,ltd - 00245E (base 16) Hivision Co.,ltd - 2201-2202, COFCO Property Tower, - 3rd Bao'an District - Shenzhen Guangdong 518101 - CHINA - - 00-24-5F (hex) Vine Telecom CO.,Ltd. - 00245F (base 16) Vine Telecom CO.,Ltd. - 191-4, 4F, Anyang-dong, Manan-gu - Anyang-si Gyeonggi-do 430-010 - KOREA, REPUBLIC OF - - 00-24-60 (hex) Giaval Science Development Co. Ltd. - 002460 (base 16) Giaval Science Development Co. Ltd. - 58 Bei Si Huan Xi Rd - Ideal Plaza, Suite 413 - Beijing 100080 - CHINA - - 00-24-61 (hex) Shin Wang Tech. - 002461 (base 16) Shin Wang Tech. - 632-62, Guro-Dong, Guro-Gu - 105-Ho, C-Dong, Guroculation Dept. - Seoul 152-866 - KOREA, REPUBLIC OF - - 00-24-62 (hex) Rayzone Corporation - 002462 (base 16) Rayzone Corporation - #2008, B-Dong, Samho BLDG - Yangjae2-Dong, Seocho-Gu - Seoul 137-941 - KOREA, REPUBLIC OF - - 00-24-63 (hex) Phybridge Inc - 002463 (base 16) Phybridge Inc - 3495 Laird Rd - Unit 12 - Mississauga Ontario L5L5S5 - CANADA - - 00-24-64 (hex) Bridge Technologies Co AS - 002464 (base 16) Bridge Technologies Co AS - Mølleparken 4 - Oslo 0459 - NORWAY - - 00-24-65 (hex) Elentec - 002465 (base 16) Elentec - 401-13 Chunggye-Ri,Dongtan-Myun - Hwasung Kyunggi 445-811 - KOREA, REPUBLIC OF - - 00-24-66 (hex) Unitron nv - 002466 (base 16) Unitron nv - Franrkijklaan 27 - Poperinge W-vl 8970 - BELGIUM - - 00-24-67 (hex) AOC International (Europe) GmbH - 002467 (base 16) AOC International (Europe) GmbH - Lahnstrasse 86A - Berlin 12055 - GERMANY - - 00-24-68 (hex) Sumavision Technologies Co.,Ltd - 002468 (base 16) Sumavision Technologies Co.,Ltd - 6F, Block A2, Power Creative Building,No.1 Shangdi East Road, Haidian District - Beijing 100085 - CHINA - - 00-24-69 (hex) Smart Doorphones - 002469 (base 16) Smart Doorphones - Klipsenstraat 18A - Lokeren 9160 - BELGIUM - - 00-24-6A (hex) Solid Year Co., Ltd. - 00246A (base 16) Solid Year Co., Ltd. - 2F-1, No. 94, Bao-chung Road, - Hsin-tien City Taipei Hsien 23147 - TAIWAN, PROVINCE OF CHINA - - 00-24-6B (hex) Covia, Inc. - 00246B (base 16) Covia, Inc. - Benex S-3 Bldg., 3-20-8, Shinyokohama,Kohoku-ku, - Yokohama-city Kanagawa-pref. 222-0033 - JAPAN - - 00-24-6C (hex) ARUBA NETWORKS, INC. - 00246C (base 16) ARUBA NETWORKS, INC. - 1344 Crossman Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-24-6D (hex) Weinzierl Engineering GmbH - 00246D (base 16) Weinzierl Engineering GmbH - Bahnhofstraße 6 - Tyrlaching Bavaria 84558 - GERMANY - - 00-24-6E (hex) Phihong USA Corp. - 00246E (base 16) Phihong USA Corp. - 47800 Fremont Blvd. - Fremont CA 94538 - UNITED STATES - - 00-24-6F (hex) Onda Communication spa - 00246F (base 16) Onda Communication spa - via del lavoro 9 - pordenone 33170 - ITALY - - 00-24-70 (hex) AUROTECH ultrasound AS. - 002470 (base 16) AUROTECH ultrasound AS. - Svingen 1 - Tydal Sr-Tr N-7590 - NORWAY - - 00-24-71 (hex) Fusion MultiSystems dba Fusion-io - 002471 (base 16) Fusion MultiSystems dba Fusion-io - 6350 S. 3000 E., 6th floor - Salt lake City UT 84121 - UNITED STATES - - 00-24-72 (hex) ReDriven Power Inc. - 002472 (base 16) ReDriven Power Inc. - 24A Bath Rd. - Iroquois Ontario K0E 1K0 - CANADA - - 00-24-73 (hex) 3Com Europe Ltd - 002473 (base 16) 3Com Europe Ltd - People Building 2 - Maylands Avenue - Hemel Hempstead Herts. HP2 4NW - UNITED KINGDOM - - 00-24-74 (hex) Autronica Fire And Securirty - 002474 (base 16) Autronica Fire And Securirty - Haakon VII's g.4 - Trondheim N-7483 - NORWAY - - 00-24-75 (hex) Compass System(Embedded Dept.) - 002475 (base 16) Compass System(Embedded Dept.) - 1403 ACE TechnoTower 8th - 191-7, Guro-dong, Guro-Gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 00-24-76 (hex) TAP.tv - 002476 (base 16) TAP.tv - 16w361 South Frontage Road - Suite 128 - Burr Ridge IL 60527 - UNITED STATES - - 00-24-77 (hex) Tibbo Technology - 002477 (base 16) Tibbo Technology - 9F-3, No 31, Lane 169, Kang-Ning St., - Hsi-Chih Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 00-24-78 (hex) Mag Tech Electronics Co Limited - 002478 (base 16) Mag Tech Electronics Co Limited - Flat / Room T78 GOF Bangkok Building - 18 Bonham Strand West - Sheung Wan HK - HONG KONG - - 00-24-79 (hex) Optec Displays, Inc. - 002479 (base 16) Optec Displays, Inc. - 528 S. 6th Avenue - City of Industry California 91746 - UNITED STATES - - 00-24-7A (hex) FU YI CHENG Technology Co., Ltd. - 00247A (base 16) FU YI CHENG Technology Co., Ltd. - 13F, No. 105-1, Jilin Rd., Luju Shiang, - Taoyuan 338 - TAIWAN, PROVINCE OF CHINA - - 00-24-7B (hex) Actiontec Electronics, Inc - 00247B (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-24-7C (hex) Nokia Danmark A/S - 00247C (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790V - DENMARK - - 00-24-7D (hex) Nokia Danmark A/S - 00247D (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-24-7E (hex) Universal Global Scientific Industrial Co., Ltd - 00247E (base 16) Universal Global Scientific Industrial Co., Ltd - 141, LANE 351,SEC.1, TAIPING RD. - TSAOTUEN - NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 00-24-7F (hex) Nortel Networks - 00247F (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson TX 75082-4399 - UNITED STATES - - 00-24-80 (hex) Meteocontrol GmbH - 002480 (base 16) Meteocontrol GmbH - Spichererstrasse 48 - Augsburg Bavaria 86152 - GERMANY - - 00-24-81 (hex) Hewlett-Packard Company - 002481 (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040802 - Houston TX 77070 - UNITED STATES - - 00-24-82 (hex) Ruckus Wireless - 002482 (base 16) Ruckus Wireless - 880 West Maude Ave. - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 00-24-83 (hex) LG Electronics - 002483 (base 16) LG Electronics - 60-39,Kasan-dong,Kumchon-ku, - Seoul 153-801 - KOREA, REPUBLIC OF - - 00-24-84 (hex) Bang and Olufsen Medicom a/s - 002484 (base 16) Bang and Olufsen Medicom a/s - Gimsinglundvej 20 - Struer DK DK7600 - DENMARK - - 00-24-85 (hex) ConteXtream Ltd - 002485 (base 16) ConteXtream Ltd - 94 Em-HaMoshavot - POB 3246 - Petach-Tikva 49527 - ISRAEL - - 00-24-86 (hex) DesignArt Networks - 002486 (base 16) DesignArt Networks - 4 Ha'haroshet St - P.O. Box 2278 - Ra'anana 43101 - ISRAEL - - 00-24-87 (hex) Blackboard Inc. - 002487 (base 16) Blackboard Inc. - 22601 North 19th Avenue - Suite 200 - Phoenix AZ 85027 - UNITED STATES - - 00-24-88 (hex) Centre For Development Of Telematics - 002488 (base 16) Centre For Development Of Telematics - B01, Electronic City, Phase 1 - Hosur Road - Bangalore Karnataka 560100 - INDIA - - 00-24-89 (hex) Vodafone Omnitel N.V. - 002489 (base 16) Vodafone Omnitel N.V. - Via Jervis 13 - 10015 Ivrea Torino - ITALY - - 00-24-8A (hex) Kaga Electronics Co., Ltd. - 00248A (base 16) Kaga Electronics Co., Ltd. - Hongo 2-2-9 - Bunkyo-ku - Tokyo 113-8503 - JAPAN - - 00-24-8B (hex) HYBUS CO., LTD. - 00248B (base 16) HYBUS CO., LTD. - Rm# 701, Daerung Post Tower 1st - 212-8, Guro-3dong, Guro-gu - SEOUL 152-790 - KOREA, REPUBLIC OF - - 00-24-8C (hex) ASUSTek COMPUTER INC. - 00248C (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-24-8D (hex) Sony Computer Entertainment Inc. - 00248D (base 16) Sony Computer Entertainment Inc. - 2-6-21 Minami-Aoyama, - Minato-ku Tokyo 107-0062 - JAPAN - - 00-24-8E (hex) Infoware ZRt. - 00248E (base 16) Infoware ZRt. - Huseg u. 10/a - Budapest 1223 - HUNGARY - - 00-24-8F (hex) DO-MONIX - 00248F (base 16) DO-MONIX - #501, Koreana B/D - 7-5, Sunae-dong, Bundang-gu - Seongnam-si Gyeonggi-do 82 - KOREA, DEMOCRATIC PEOPLE'S REPUBLI - - 00-24-90 (hex) Samsung Electronics Co.,LTD - 002490 (base 16) Samsung Electronics Co.,LTD - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-24-91 (hex) Samsung Electronics - 002491 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-24-92 (hex) Motorola, Broadband Solutions Group - 002492 (base 16) Motorola, Broadband Solutions Group - 1101 Marina Village Parkway - Suite 200 - Alameda CA 94501 - UNITED STATES - - 00-24-93 (hex) ARRIS Group, Inc. - 002493 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-24-94 (hex) Shenzhen Baoxin Tech CO., Ltd. - 002494 (base 16) Shenzhen Baoxin Tech CO., Ltd. - 6F Huale BLDG., Zhonghangbei Rd., - Futian District - Shenzhen GuangDong 518028 - CHINA - - 00-24-95 (hex) ARRIS Group, Inc. - 002495 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-24-96 (hex) Ginzinger electronic systems - 002496 (base 16) Ginzinger electronic systems - Gewerbegebiet Pirath 16 - Weng Upper Austria 4952 - AUSTRIA - - 00-24-97 (hex) CISCO SYSTEMS, INC. - 002497 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-98 (hex) CISCO SYSTEMS, INC. - 002498 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-99 (hex) Aquila Technologies - 002499 (base 16) Aquila Technologies - 8429A Washington Place NE - Albuquerque NM 87113 - UNITED STATES - - 00-24-9A (hex) Beijing Zhongchuang Telecommunication Test Co., Ltd. - 00249A (base 16) Beijing Zhongchuang Telecommunication Test Co., Ltd. - 12-14,Block C,Beijing International Building,#18,Zhong Guan Cun Nan Road, - Hai Dian District - Beijing 100081 - CHINA - - 00-24-9B (hex) Action Star Enterprise Co., Ltd. - 00249B (base 16) Action Star Enterprise Co., Ltd. - 10F, No.159, Sec.2, Datong Rd. - Xizhi Dist. New Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - 00-24-9C (hex) Bimeng Comunication System Co. Ltd - 00249C (base 16) Bimeng Comunication System Co. Ltd - Level 16/f, Tower B,Sinotrans Plaza,No.43, Xi Zhi Men Northern Road,Hai dian District - Beijing 100044 - CHINA - - 00-24-9D (hex) NES Technology Inc. - 00249D (base 16) NES Technology Inc. - #205 ACE Technotower 10, 470-5 Gasan-dong - Geumcheon-gu - Seoul 153-789 - KOREA, REPUBLIC OF - - 00-24-9E (hex) ADC-Elektronik GmbH - 00249E (base 16) ADC-Elektronik GmbH - Östingstraße 13b - Hamm NRW D-59063 - GERMANY - - 00-24-9F (hex) RIM Testing Services - 00249F (base 16) RIM Testing Services - 440 Phillip Street - Waterloo Ontario N2L 5R9 - CANADA - - 00-24-A0 (hex) ARRIS Group, Inc. - 0024A0 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-24-A1 (hex) ARRIS Group, Inc. - 0024A1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-24-A2 (hex) Hong Kong Middleware Technology Limited - 0024A2 (base 16) Hong Kong Middleware Technology Limited - Room 1315 ,Leighton Centre,77 Leighton Road - Causeway Bay 852 - HONG KONG - - 00-24-A3 (hex) Sonim Technologies Inc - 0024A3 (base 16) Sonim Technologies Inc - 1875 S.Grant Street - Ste#620 - Sanmateo CA 94402 - UNITED STATES - - 00-24-A4 (hex) Siklu Communication - 0024A4 (base 16) Siklu Communication - 7 Shoham St., , 3rd Floor - Petah Tikva 49517 - ISRAEL - - 00-24-A5 (hex) Buffalo Inc. - 0024A5 (base 16) Buffalo Inc. - AKAMONDORI Bldg., 30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref. 460-8315 - JAPAN - - 00-24-A6 (hex) TELESTAR DIGITAL GmbH - 0024A6 (base 16) TELESTAR DIGITAL GmbH - Vulkanhöhe / B410 - Dreis-Brück 54552 - GERMANY - - 00-24-A7 (hex) Advanced Video Communications Inc. - 0024A7 (base 16) Advanced Video Communications Inc. - 633 W 5th Street - 6800 - Los Angeles CA 90017 - UNITED STATES - - 00-24-A8 (hex) ProCurve Networking by HP - 0024A8 (base 16) ProCurve Networking by HP - 8000 Foothills Blvd - Roseville California 95747 - UNITED STATES - - 00-24-A9 (hex) Ag Leader Technology - 0024A9 (base 16) Ag Leader Technology - 2202 S Riverside Dr. - PO Box 2348 - Ames IA 50010 - UNITED STATES - - 00-24-AA (hex) Dycor Technologies Ltd. - 0024AA (base 16) Dycor Technologies Ltd. - 1851 94 Street - Edmonton Alberta T6N 1E6 - CANADA - - 00-24-AB (hex) A7 Engineering, Inc. - 0024AB (base 16) A7 Engineering, Inc. - 12127 Kirkham Road Suite 101 - Poway CA 92064 - UNITED STATES - - 00-24-AC (hex) Hangzhou DPtech Technologies Co., Ltd. - 0024AC (base 16) Hangzhou DPtech Technologies Co., Ltd. - Huarong Shidai Bld., NO.3880,Jiang-Nan Avenue, Binjiang District - Hangzhou Zhejiang 310051 - CHINA - - 00-24-AD (hex) Adolf Thies Gmbh & Co. KG - 0024AD (base 16) Adolf Thies Gmbh & Co. KG - Hauptstraße 76 - Göttingen 37083 - GERMANY - - 00-24-AE (hex) Morpho - 0024AE (base 16) Morpho - 18 chaussee Jules Cesar - OSNY 95520 - FRANCE - - 00-24-AF (hex) EchoStar Technologies - 0024AF (base 16) EchoStar Technologies - 94 Inverness Circle - Englewood CO 80112 - UNITED STATES - - 00-24-B0 (hex) ESAB AB - 0024B0 (base 16) ESAB AB - Box 8004 - Lindholmsallén 9 - Göteborg SE-402 77 - SWEDEN - - 00-24-B1 (hex) Coulomb Technologies - 0024B1 (base 16) Coulomb Technologies - 1692 Dell Ave - Campbell CA 95008 - UNITED STATES - - 00-24-B2 (hex) Netgear - 0024B2 (base 16) Netgear - 350 East Plumeria Drive - San Jose CA 95134 - UNITED STATES - - 00-24-B3 (hex) Graf-Syteco GmbH & Co. KG - 0024B3 (base 16) Graf-Syteco GmbH & Co. KG - Kaiserstraße 18 - Tuningen Baden-Württemberg 78609 - GERMANY - - 00-24-B4 (hex) ESCATRONIC GmbH - 0024B4 (base 16) ESCATRONIC GmbH - Wuerzburger Str. 8 - Laatzen Lower Saxony 30880 - GERMANY - - 00-24-B5 (hex) Nortel Networks - 0024B5 (base 16) Nortel Networks - 2221 Lakeside Blvd - Richardson TX 75082-4399 - UNITED STATES - - 00-24-B6 (hex) Seagate Technology - 0024B6 (base 16) Seagate Technology - 1280 Disc Drive - Shakopee MN 55379 - UNITED STATES - - 00-24-B7 (hex) GridPoint, Inc. - 0024B7 (base 16) GridPoint, Inc. - 2801 Clarendon Blvd. - Suite 100 - Arlington VA 22201 - UNITED STATES - - 00-24-B8 (hex) free alliance sdn bhd - 0024B8 (base 16) free alliance sdn bhd - B-3-2 Plaza Damas - Sri Hartamas - Kuala Lumpur WP 50480 - MALAYSIA - - 00-24-B9 (hex) Wuhan Higheasy Electronic Technology Development Co.Ltd - 0024B9 (base 16) Wuhan Higheasy Electronic Technology Development Co.Ltd - Bldg A2 Optics Valley Software Park,Guanshan 1st Rd, - Wuhan Hubei 430033 - CHINA - - 00-24-BA (hex) Texas Instruments - 0024BA (base 16) Texas Instruments - 12500 TI Boulevard, MS 8723 - Dallas TX 75243 - UNITED STATES - - 00-24-BB (hex) CENTRAL Corporation - 0024BB (base 16) CENTRAL Corporation - NISSO 17 Bldg.7F 2-14-30 - Shinyokohama Kouhoku-ku - Yokohama Kanagawa 222-0033 - JAPAN - - 00-24-BC (hex) HuRob Co.,Ltd - 0024BC (base 16) HuRob Co.,Ltd - 2121, Jeongwang-Dong - Siheung-Si Gyeonggi-Do 429-793 - KOREA, REPUBLIC OF - - 00-24-BD (hex) Hainzl Industriesysteme GmbH - 0024BD (base 16) Hainzl Industriesysteme GmbH - Industriezeile 56 - Postfach 100 - Linz Upper Austria 4021 - AUSTRIA - - 00-24-BE (hex) Sony Corporation - 0024BE (base 16) Sony Corporation - Gotenyama Tec. 5-1-12 - Kitashinagawa - Shinagawa-ku Tokyo 141-0001 - JAPAN - - 00-24-BF (hex) CIAT - 0024BF (base 16) CIAT - 30, Avenue Jean Falconnier - Culoz 01350 - FRANCE - - 00-24-C0 (hex) NTI COMODO INC - 0024C0 (base 16) NTI COMODO INC - Rm#502, Kangyong Bldg, Sungnam-dong - Cheungwon-gu - Sungnam-si Kyunggi-do 462-827 - KOREA, REPUBLIC OF - - 00-24-C1 (hex) ARRIS Group, Inc. - 0024C1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-24-C2 (hex) Asumo Co.,Ltd. - 0024C2 (base 16) Asumo Co.,Ltd. - Oya-Kita 1-3-1 - EBINA-CITY KANAGAWA-PREF. 243-0419 - JAPAN - - 00-24-C3 (hex) CISCO SYSTEMS, INC. - 0024C3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-C4 (hex) CISCO SYSTEMS, INC. - 0024C4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-C5 (hex) Meridian Audio Limited - 0024C5 (base 16) Meridian Audio Limited - 11 Latham Road - Huntingdon Cambs PE29 6YE - UNITED KINGDOM - - 00-24-C6 (hex) Hager Electro SAS - 0024C6 (base 16) Hager Electro SAS - 132, boulevard d'Europe - Obernai Bas-Rhin 67215 - FRANCE - - 00-24-C7 (hex) Mobilarm Ltd - 0024C7 (base 16) Mobilarm Ltd - 768 Canning Highway - Applecross - Western Australia 6153 - AUSTRALIA - - 00-24-C8 (hex) Broadband Solutions Group - 0024C8 (base 16) Broadband Solutions Group - 1101 Marina Village Parkway - Alameda CA 94501 - UNITED STATES - - 00-24-C9 (hex) Broadband Solutions Group - 0024C9 (base 16) Broadband Solutions Group - 1101 Marina Village Parkway - Alameda CA 94501 - UNITED STATES - - 00-24-CA (hex) Tobii Technology AB - 0024CA (base 16) Tobii Technology AB - Karlsrovägen 2D - Danderyd 18253 - SWEDEN - - 00-24-CB (hex) Autonet Mobile - 0024CB (base 16) Autonet Mobile - 2235 Mercury Way Ste. 145 - Santa Rosa CA 95407 - UNITED STATES - - 00-24-CC (hex) Fascinations Toys and Gifts, Inc. - 0024CC (base 16) Fascinations Toys and Gifts, Inc. - 19224 Des Moines Way S - Ste 100 - Seattle Washington 98148 - UNITED STATES - - 00-24-CD (hex) Willow Garage, Inc. - 0024CD (base 16) Willow Garage, Inc. - 68 Willow Rd. - Menlo Park CA 94025 - UNITED STATES - - 00-24-CE (hex) Exeltech Inc - 0024CE (base 16) Exeltech Inc - 7317 Jack Newell Blvd North - Fort Worth TX 76118 - UNITED STATES - - 00-24-CF (hex) Inscape Data Corporation - 0024CF (base 16) Inscape Data Corporation - 1611 South Main Street - Milpitas CA 95035 - UNITED STATES - - 00-24-D0 (hex) Shenzhen SOGOOD Industry CO.,LTD. - 0024D0 (base 16) Shenzhen SOGOOD Industry CO.,LTD. - SOGOOD Science Park,Aviation Road,XiXiang Town,Bao'an District, - Shenzhen Guangzhou 518102 - CHINA - - 00-24-D1 (hex) Thomson Inc. - 0024D1 (base 16) Thomson Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 00-24-D2 (hex) Askey Computer - 0024D2 (base 16) Askey Computer - 10F,NO.119,CHIENKANG RD,CHUNG-HO,TAIPEI, - TAIWAN TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - 00-24-D3 (hex) QUALICA Inc. - 0024D3 (base 16) QUALICA Inc. - 5-29-15,Toyo, - Koto-ku, - Tokyo 135-0016 - JAPAN - - 00-24-D4 (hex) FREEBOX SA - 0024D4 (base 16) FREEBOX SA - 8 rue de la Ville l'Eveque - PARIS IdF 75008 - FRANCE - - 00-24-D5 (hex) Winward Industrial Limited - 0024D5 (base 16) Winward Industrial Limited - Rm.7, P Floor, Tower A, - Hung Hom Commercial Centre, - HongKong 852 - CHINA - - 00-24-D6 (hex) Intel Corporate - 0024D6 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-24-D7 (hex) Intel Corporate - 0024D7 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-24-D8 (hex) IlSung Precision - 0024D8 (base 16) IlSung Precision - 182-2, Jegi-ri, Jeongnam-myeon - Hwanseong-si Gyeonggi-do 445-964 - KOREA, REPUBLIC OF - - 00-24-D9 (hex) BICOM, Inc. - 0024D9 (base 16) BICOM, Inc. - 755 Main Street - Building 3 - Monroe CT 06468 - UNITED STATES - - 00-24-DA (hex) Innovar Systems Limited - 0024DA (base 16) Innovar Systems Limited - 12155 Commissioner Drive - PO Box 486 - North Jackson Ohio 44451 - UNITED STATES - - 00-24-DB (hex) Alcohol Monitoring Systems - 0024DB (base 16) Alcohol Monitoring Systems - 1241 W. Mineral Avenue - Suite 200 - Littleton CO 80120 - UNITED STATES - - 00-24-DC (hex) Juniper Networks - 0024DC (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-24-DD (hex) Centrak, Inc. - 0024DD (base 16) Centrak, Inc. - 207 Penns Trail - Newtown PA 18940 - UNITED STATES - - 00-24-DE (hex) GLOBAL Technology Inc. - 0024DE (base 16) GLOBAL Technology Inc. - No.168,Shanshan Rd., Wangchun Industrial Park, - Ningbo 315176 - CHINA - - 00-24-DF (hex) Digitalbox Europe GmbH - 0024DF (base 16) Digitalbox Europe GmbH - Sandstraße 65 - Ratingen 40878 - GERMANY - - 00-24-E0 (hex) DS Tech, LLC - 0024E0 (base 16) DS Tech, LLC - 2210 Hutton Drive - Suite 100 - Carrollton TX 75006 - UNITED STATES - - 00-24-E1 (hex) Convey Computer Corp. - 0024E1 (base 16) Convey Computer Corp. - 1302 E. Collins Blvd. - Richardson TX 75081 - UNITED STATES - - 00-24-E2 (hex) HASEGAWA ELECTRIC CO.,LTD. - 0024E2 (base 16) HASEGAWA ELECTRIC CO.,LTD. - 5-6-20 SHIOE - LIGHTNING TECHNOLOGY CENTER - AMAGASAKI HYOGO 661-0976 - JAPAN - - 00-24-E3 (hex) CAO Group - 0024E3 (base 16) CAO Group - 4628 West Skyhawk Drive - West Jordan UT 84084 - UNITED STATES - - 00-24-E4 (hex) Withings - 0024E4 (base 16) Withings - 37bis rue du General Leclerc - Issy les Moulineaux 92442 - FRANCE - - 00-24-E5 (hex) Seer Technology, Inc - 0024E5 (base 16) Seer Technology, Inc - 2681 Parleys Way - Suite 201 - Salt Lake City Utah 84109 - UNITED STATES - - 00-24-E6 (hex) In Motion Technology Inc. - 0024E6 (base 16) In Motion Technology Inc. - #350, 625 Agnes Street - New Westminster BC V3M 5Y4 - CANADA - - 00-24-E7 (hex) Plaster Networks - 0024E7 (base 16) Plaster Networks - 935 Hamilton Avenue - Menlo Park CA 94025-1431 - UNITED STATES - - 00-24-E8 (hex) Dell Inc. - 0024E8 (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-24-E9 (hex) Samsung Electronics Co., Ltd., Storage System Division - 0024E9 (base 16) Samsung Electronics Co., Ltd., Storage System Division - 416, Maetan 3Dong, Yeongtong-Gu - Suwon City Geyonggi Do 443-742 - KOREA, REPUBLIC OF - - 00-24-EA (hex) iris-GmbH infrared & intelligent sensors - 0024EA (base 16) iris-GmbH infrared & intelligent sensors - Ostendstrasse 1-14 - Berlin 12459 - GERMANY - - 00-24-EB (hex) ClearPath Networks, Inc. - 0024EB (base 16) ClearPath Networks, Inc. - 1940 E. Mariposa Ave. - Suite 150 - El Segundo CA 90245 - UNITED STATES - - 00-24-EC (hex) United Information Technology Co.,Ltd. - 0024EC (base 16) United Information Technology Co.,Ltd. - 5/F,9th Building,Software Park,2nd Keji-zhong Road,High-Tech Industrial Park - Shenzhen Guangdong 518057 - CHINA - - 00-24-ED (hex) YT Elec. Co,.Ltd. - 0024ED (base 16) YT Elec. Co,.Ltd. - Block B,2 Floor ,Bao Ying Industrial District, - Long Gang LongXi, - Wu Lian Lu Shenzhen 518116 - CHINA - - 00-24-EE (hex) Wynmax Inc. - 0024EE (base 16) Wynmax Inc. - 18F., No. 75, Sec. 1, XinTai 5th Rd., - Xizhi City, Taipei County 221 - TAIWAN, PROVINCE OF CHINA - - 00-24-EF (hex) Sony Ericsson Mobile Communications - 0024EF (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund 22188 - SWEDEN - - 00-24-F0 (hex) Seanodes - 0024F0 (base 16) Seanodes - Batiment Platon - 25 Bvd Victor Hugo - Colomiers 31770 - FRANCE - - 00-24-F1 (hex) Shenzhen Fanhai Sanjiang Electronics Co., Ltd. - 0024F1 (base 16) Shenzhen Fanhai Sanjiang Electronics Co., Ltd. - 3Floor-Guangcai Xintiandi Building,Nanshan Rd,Nanshan, - Shenzhen Guangdong 518054 - CHINA - - 00-24-F2 (hex) Uniphone Telecommunication Co., Ltd. - 0024F2 (base 16) Uniphone Telecommunication Co., Ltd. - No. 25, Chu-Kung 3rd Lane, Chu-Hou Tsung, Jen-Wu Hsiang, - Kaohsiung Hsien 81448 - TAIWAN, PROVINCE OF CHINA - - 00-24-F3 (hex) Nintendo Co., Ltd. - 0024F3 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-24-F4 (hex) Kaminario Technologies Ltd. - 0024F4 (base 16) Kaminario Technologies Ltd. - Yatam Industrial Park - CPC Building - Yokneam ISRAEL 20692 - ISRAEL - - 00-24-F5 (hex) NDS Surgical Imaging - 0024F5 (base 16) NDS Surgical Imaging - 5750 Hellyer Ave. - San Jose CA. 95138 - UNITED STATES - - 00-24-F6 (hex) MIYOSHI ELECTRONICS CORPORATION - 0024F6 (base 16) MIYOSHI ELECTRONICS CORPORATION - 3-13-21 KUSHIRO - KAWANISHI-CITY HYOGO-PREF. 666-0024 - JAPAN - - 00-24-F7 (hex) CISCO SYSTEMS, INC. - 0024F7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-F8 (hex) Technical Solutions Company Ltd. - 0024F8 (base 16) Technical Solutions Company Ltd. - Box 31750 - Whitehorse Yukon Y1A 6L3 - CANADA - - 00-24-F9 (hex) CISCO SYSTEMS, INC. - 0024F9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-24-FA (hex) Hilger u. Kern GMBH - 0024FA (base 16) Hilger u. Kern GMBH - Kaefertaler Strasse 253-255 - Mannheim Baden-Württemberg 68167 - GERMANY - - 00-24-FB (hex) PRIVATE - 0024FB (base 16) - - 00-24-FC (hex) QuoPin Co., Ltd. - 0024FC (base 16) QuoPin Co., Ltd. - #109, R&D Center for Advanced Technology 68 Yatap-dong Bundang-gu - Seongnam Kyungki-do 463-816 - KOREA, REPUBLIC OF - - 00-24-FD (hex) Accedian Networks Inc - 0024FD (base 16) Accedian Networks Inc - 2351 Alfred Nobel Blvd - Suite N-40 - Saint Laurent QC h4s 2A9 - CANADA - - 00-24-FE (hex) AVM GmbH - 0024FE (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 00-24-FF (hex) QLogic Corporation - 0024FF (base 16) QLogic Corporation - 26650 Aliso Viejo Parkway - Aliso Viejo CA 92656 - UNITED STATES - - 00-25-00 (hex) Apple - 002500 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-25-01 (hex) JSC "Supertel" - 002501 (base 16) JSC "Supertel" - 38A Petrogradskaya emb. - St.Petersburg 197101 - RUSSIAN FEDERATION - - 00-25-02 (hex) NaturalPoint - 002502 (base 16) NaturalPoint - PO Box 2317 - Corvallis OR 97339 - UNITED STATES - - 00-25-03 (hex) IBM Corp - 002503 (base 16) IBM Corp - 2051 Mission College Blvd - Santa Clara CA 95054 - UNITED STATES - - 00-25-04 (hex) Valiant Communications Limited - 002504 (base 16) Valiant Communications Limited - 71-1 Shivaji Marg - New Delhi Delhi 110015 - INDIA - - 00-25-05 (hex) eks Engel GmbH & Co. KG - 002505 (base 16) eks Engel GmbH & Co. KG - Schuetzenstrasse 2 - Wenden-Hillmicke NRW 57482 - GERMANY - - 00-25-06 (hex) A.I. ANTITACCHEGGIO ITALIA SRL - 002506 (base 16) A.I. ANTITACCHEGGIO ITALIA SRL - VICOLO DELLE DAME 4 - BOLOGNA 40124 - ITALY - - 00-25-07 (hex) ASTAK Inc. - 002507 (base 16) ASTAK Inc. - 1911 Hartog Drive - San Jose CA 95131 - UNITED STATES - - 00-25-08 (hex) Maquet Cardiopulmonary AG - 002508 (base 16) Maquet Cardiopulmonary AG - Hechinger Strasse 38 - Hirrlingen 72145 - GERMANY - - 00-25-09 (hex) SHARETRONIC Group LTD - 002509 (base 16) SHARETRONIC Group LTD - ShaJing,Bao'an Zone, - ShenZhen Guangdong 518104 - CHINA - - 00-25-0A (hex) Security Expert Co. Ltd - 00250A (base 16) Security Expert Co. Ltd - 8F-3, No.2, Jian 8th Rd., - Jhonghe Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 00-25-0B (hex) CENTROFACTOR INC - 00250B (base 16) CENTROFACTOR INC - Road Town, Tortola, P.O.Box 3161, - Tortola 194295 - VIRGIN ISLANDS, BRITISH - - 00-25-0C (hex) Enertrac - 00250C (base 16) Enertrac - 94 River Rd - Suite 100 - Hudson NH 03051 - UNITED STATES - - 00-25-0D (hex) GZT Telkom-Telmor sp. z o.o. - 00250D (base 16) GZT Telkom-Telmor sp. z o.o. - Mickiewicza 5/7 - Gdansk pomorskie 80-425 - POLAND - - 00-25-0E (hex) gt german telematics gmbh - 00250E (base 16) gt german telematics gmbh - Rankestrasse 26 - Berlin D-10789 - GERMANY - - 00-25-0F (hex) On-Ramp Wireless, Inc. - 00250F (base 16) On-Ramp Wireless, Inc. - 16885 West Bernardo Drive - Suite 255 - San Diego CA 92127 - UNITED STATES - - 00-25-10 (hex) Pico-Tesla Magnetic Therapies - 002510 (base 16) Pico-Tesla Magnetic Therapies - 7852 South Elati - #202 - Littleton CO 80120 - UNITED STATES - - 00-25-11 (hex) ELITEGROUP COMPUTER SYSTEM CO., LTD. - 002511 (base 16) ELITEGROUP COMPUTER SYSTEM CO., LTD. - NO. 239, Sec. 2, Ti Ding Blvd. - Taipei Taiwan 11493 - TAIWAN, PROVINCE OF CHINA - - 00-25-12 (hex) ZTE Corporation - 002512 (base 16) ZTE Corporation - 12F, R&D Building, Zte, Hi-Tech Industrial Park - Shenzhen Guangdong 518057 - CHINA - - 00-25-13 (hex) CXP DIGITAL BV - 002513 (base 16) CXP DIGITAL BV - De Reulver 97A - Enschede 7544RT - NETHERLANDS - - 00-25-14 (hex) PC Worth Int'l Co., Ltd. - 002514 (base 16) PC Worth Int'l Co., Ltd. - 18F, No.100, Sec. 1, Xintai 5th Rd., Xizhi Dist., - New Taipei City Taipei 22102 - TAIWAN, PROVINCE OF CHINA - - 00-25-15 (hex) SFR - 002515 (base 16) SFR - 42 Quai du point du jour - Boulogne billancourt . 92659 - FRANCE - - 00-25-16 (hex) Integrated Design Tools, Inc. - 002516 (base 16) Integrated Design Tools, Inc. - 1202 E Park Avenue - Tallahassee FL 32301 - UNITED STATES - - 00-25-17 (hex) Venntis, LLC - 002517 (base 16) Venntis, LLC - 11301 James Street - Holland MI 49424 - UNITED STATES - - 00-25-18 (hex) Power PLUS Communications AG - 002518 (base 16) Power PLUS Communications AG - Am Exerzierplatz 2 - Mannheim Baden Wuerttemberg 68167 - GERMANY - - 00-25-19 (hex) Viaas Inc - 002519 (base 16) Viaas Inc - 3175 South Winchester Blvd - Campbell CA 95008 - UNITED STATES - - 00-25-1A (hex) Psiber Data Systems Inc. - 00251A (base 16) Psiber Data Systems Inc. - 7075-K Mission Gorge Rd - San Diego CA 92120 - UNITED STATES - - 00-25-1B (hex) Philips CareServant - 00251B (base 16) Philips CareServant - High Tech Campus 27 - Eindhoven Noord-Brabant 5656 AE - NETHERLANDS - - 00-25-1C (hex) EDT - 00251C (base 16) EDT - 1400 SW Compton - Suite 315 - Beaverton OR 97008 - UNITED STATES - - 00-25-1D (hex) DSA Encore, LLC - 00251D (base 16) DSA Encore, LLC - 50 Pocono Rd - Brookfield CT 06804 - UNITED STATES - - 00-25-1E (hex) ROTEL TECHNOLOGIES - 00251E (base 16) ROTEL TECHNOLOGIES - CEVIZLIDERE 14.CD NO:2/19 BALGAT - ANKARA 06520 - TURKEY - - 00-25-1F (hex) ZYNUS VISION INC. - 00251F (base 16) ZYNUS VISION INC. - 1-1-7-1A - SAGAMIHARA KANAGAWA 229-0039 - JAPAN - - 00-25-20 (hex) SMA Railway Technology GmbH - 002520 (base 16) SMA Railway Technology GmbH - Miramstraße 87 - Kassel Hesse 34123 - GERMANY - - 00-25-21 (hex) Logitek Electronic Systems, Inc. - 002521 (base 16) Logitek Electronic Systems, Inc. - 5622 Edgemoor Drive - Houston Texas 77081 - UNITED STATES - - 00-25-22 (hex) ASRock Incorporation - 002522 (base 16) ASRock Incorporation - 2F., No. 37, Sec. 2, Jhongyang S. Rd., Beitou District, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-25-23 (hex) OCP Inc. - 002523 (base 16) OCP Inc. - 18495 S Dixie Hwy PMB 107 - Miami Florida 33157 - UNITED STATES - - 00-25-24 (hex) Lightcomm Technology Co., Ltd - 002524 (base 16) Lightcomm Technology Co., Ltd - 9/F.,Hi-Tech Venture Park Tower A, - Tian an Cyber Park,Futian - ShenZhen GuangDong 518040 - CHINA - - 00-25-25 (hex) CTERA Networks Ltd. - 002525 (base 16) CTERA Networks Ltd. - 24 Imber St. - Petach-Tikva 495111 - ISRAEL - - 00-25-26 (hex) Genuine Technologies Co., Ltd. - 002526 (base 16) Genuine Technologies Co., Ltd. - Klingelnberg Bldg. - 1-13-12 Shin-Yokohama Kouhoku-ku - Yokohama Kanagawa 222-0033 - JAPAN - - 00-25-27 (hex) Bitrode Corp. - 002527 (base 16) Bitrode Corp. - 9787 Green Park Industrial Drive - St. Louis MO 63123 - UNITED STATES - - 00-25-28 (hex) Daido Signal Co., Ltd. - 002528 (base 16) Daido Signal Co., Ltd. - 6-17-19 - Shinbashi - Minato-ku TOKYO 105-8650 - JAPAN - - 00-25-29 (hex) COMELIT GROUP S.P.A - 002529 (base 16) COMELIT GROUP S.P.A - DON ARRIGONI N. 5 - SAN LORENZO, ROVETTA BERGAMO 24020 - ITALY - - 00-25-2A (hex) Chengdu GeeYa Technology Co.,LTD - 00252A (base 16) Chengdu GeeYa Technology Co.,LTD - 50 Shuxi Road, - Chengdu SiChuan 610091 - CHINA - - 00-25-2B (hex) Stirling Energy Systems - 00252B (base 16) Stirling Energy Systems - Sandia National Labs - NSTTF - PO Box 5800 MS 1127 - Albuquerque NM 87185-1127 - UNITED STATES - - 00-25-2C (hex) Entourage Systems, Inc. - 00252C (base 16) Entourage Systems, Inc. - 7901 Jones Branch Drive - Suite 700 - McLean Virginia 22102 - UNITED STATES - - 00-25-2D (hex) Kiryung Electronics - 00252D (base 16) Kiryung Electronics - Kiryung Bldg. 686-70, Sindaebang-dong - Dongjak-gu, - Seoul 156-010 - KOREA, REPUBLIC OF - - 00-25-2E (hex) Cisco SPVTG - 00252E (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville GA 30044 - UNITED STATES - - 00-25-2F (hex) Energy, Inc. - 00252F (base 16) Energy, Inc. - 3297 Pacific Street - Charleston SC 29418 - UNITED STATES - - 00-25-30 (hex) Aetas Systems Inc. - 002530 (base 16) Aetas Systems Inc. - 3A3, No. 1, LiHsin Road I - HsinChu Taiwan 30078 - TAIWAN, PROVINCE OF CHINA - - 00-25-31 (hex) Cloud Engines, Inc. - 002531 (base 16) Cloud Engines, Inc. - 857 Montgomery Street - San Francisco CA 94133 - UNITED STATES - - 00-25-32 (hex) Digital Recorders - 002532 (base 16) Digital Recorders - 4018 Patriot Drive - Suite 100 - Durham NC 27709 - UNITED STATES - - 00-25-33 (hex) WITTENSTEIN AG - 002533 (base 16) WITTENSTEIN AG - Walter-Wittenstein-Straße 1 - Igersheim 97999 - GERMANY - - 00-25-35 (hex) Minimax GmbH & Co KG - 002535 (base 16) Minimax GmbH & Co KG - Industriestrasse 10/12 - Bad Oldesloe SH 23840 - GERMANY - - 00-25-36 (hex) Oki Electric Industry Co., Ltd. - 002536 (base 16) Oki Electric Industry Co., Ltd. - 1-16-8 Chuou - Warabi-shi Saitama 335-8510 - JAPAN - - 00-25-37 (hex) Runcom Technologies Ltd. - 002537 (base 16) Runcom Technologies Ltd. - 11 Moshe Levi Str. 11th Flr. - UMI Building - Rishon Le Zion 75658 - ISRAEL - - 00-25-38 (hex) Samsung Electronics Co., Ltd., Memory Division - 002538 (base 16) Samsung Electronics Co., Ltd., Memory Division - San #16 Banwol-Dong, Taean-Gu - Hwasung City Gyeonggi Do 445-701 - KOREA, REPUBLIC OF - - 00-25-39 (hex) IfTA GmbH - 002539 (base 16) IfTA GmbH - Industriestraße 33 - Groebenzell Bavaria 82194 - GERMANY - - 00-25-3A (hex) CEVA, Ltd. - 00253A (base 16) CEVA, Ltd. - 2 Maskit Street. - P.O. Box 2068 - Herzelia 46120 - ISRAEL - - 00-25-3B (hex) din Dietmar Nocker Facilitymanagement GmbH - 00253B (base 16) din Dietmar Nocker Facilitymanagement GmbH - Kotzinastrasse 5 - Linz Upper Austria 4030 - AUSTRIA - - 00-25-3C (hex) 2Wire - 00253C (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-25-3D (hex) DRS Consolidated Controls - 00253D (base 16) DRS Consolidated Controls - 21 South Street - Danbury CT 06810-8147 - UNITED STATES - - 00-25-3E (hex) Sensus Metering Systems - 00253E (base 16) Sensus Metering Systems - 10147 W. Emerald Street - Suite 100 - Boise Idaho 83704 - UNITED STATES - - 00-25-40 (hex) Quasar Technologies, Inc. - 002540 (base 16) Quasar Technologies, Inc. - 1701 Barrett Lakes Boulevard - Suite 160 - Kennesaw GA 30144 - UNITED STATES - - 00-25-41 (hex) Maquet Critical Care AB - 002541 (base 16) Maquet Critical Care AB - Röntgenvägen 2 - Solna SE-171 95 - SWEDEN - - 00-25-42 (hex) Pittasoft - 002542 (base 16) Pittasoft - #913 Daeryung Techno Town 8th 481-11ga - Gasan-dong - Geumcheon-gu Seoul 153-775 - KOREA, REPUBLIC OF - - 00-25-43 (hex) MONEYTECH - 002543 (base 16) MONEYTECH - Rua Guiratinga 931 un. 103 - Chacara Inglesa - São Paulo SP 04141-001 - BRAZIL - - 00-25-44 (hex) LoJack Corporation - 002544 (base 16) LoJack Corporation - 780 Dedham Street - MA 02021 - UNITED STATES - - 00-25-45 (hex) CISCO SYSTEMS, INC. - 002545 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-25-46 (hex) CISCO SYSTEMS, INC. - 002546 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-25-47 (hex) Nokia Danmark A/S - 002547 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-25-48 (hex) Nokia Danmark A/S - 002548 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-25-49 (hex) Jeorich Tech. Co.,Ltd. - 002549 (base 16) Jeorich Tech. Co.,Ltd. - 4F., No.6, Ln. 70, Sec. 2, Academia Rd., Nangang District, Taipei City 115, Taiwan (R.O.C.) - Taipei Taiwan 110 - TAIWAN, PROVINCE OF CHINA - - 00-25-4A (hex) RingCube Technologies, Inc. - 00254A (base 16) RingCube Technologies, Inc. - 100 West Evelyn Ave, Suite 210 - Mountain View CA 94041 - UNITED STATES - - 00-25-4B (hex) Apple - 00254B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-25-4C (hex) Videon Central, Inc. - 00254C (base 16) Videon Central, Inc. - 2171 Sandy Drive - State College PA 16803 - UNITED STATES - - 00-25-4D (hex) Singapore Technologies Electronics Limited - 00254D (base 16) Singapore Technologies Electronics Limited - 24 Ang Mo Kio - Street 65 - 569061 - SINGAPORE - - 00-25-4E (hex) Vertex Wireless Co., Ltd. - 00254E (base 16) Vertex Wireless Co., Ltd. - 5F, Seohyeon Plaza, 254-5, Seohyeon-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-824 - KOREA, REPUBLIC OF - - 00-25-4F (hex) ELETTROLAB Srl - 00254F (base 16) ELETTROLAB Srl - Via Dell'Industria 25 - San Vendemiano Treviso 31020 - ITALY - - 00-25-50 (hex) Riverbed Technology - 002550 (base 16) Riverbed Technology - 125 Cambridge Park Drive - Cambridge MA 02140 - UNITED STATES - - 00-25-51 (hex) SE-Elektronic GmbH - 002551 (base 16) SE-Elektronic GmbH - Eythstraße 16 - Göppingen 73037 - GERMANY - - 00-25-52 (hex) VXI CORPORATION - 002552 (base 16) VXI CORPORATION - One Front Sreet - Rollinsford NH 03869 - UNITED STATES - - 00-25-53 (hex) Pirelli Tyre S.p.A. - 002553 (base 16) Pirelli Tyre S.p.A. - VIALE SARCA 222 - MILANO 20126 - ITALY - - 00-25-54 (hex) Pixel8 Networks - 002554 (base 16) Pixel8 Networks - 22 Great Oaks Blvd, Suite 150 - San Jose CA 95119 - UNITED STATES - - 00-25-55 (hex) Visonic Technologies 1993 Ltd - 002555 (base 16) Visonic Technologies 1993 Ltd - 23 Habarzel st' - Tel - Aviv 69710 - ISRAEL - - 00-25-56 (hex) Hon Hai Precision Ind. Co., Ltd. - 002556 (base 16) Hon Hai Precision Ind. Co., Ltd. - No.1925, Nanle Road - Songjiang Export Processing Zone - ShangHai 201613 - CHINA - - 00-25-57 (hex) Research In Motion - 002557 (base 16) Research In Motion - 440 Phillip Street - Waterloo Ontario N2L 5W9 - CANADA - - 00-25-58 (hex) MPEDIA - 002558 (base 16) MPEDIA - Shinyoung Tower 12F 246-2 - Seohyeon-ding Bundang-gu - Seongnam Gyeonggi-do 463-824 - KOREA, REPUBLIC OF - - 00-25-59 (hex) Syphan Technologies Ltd - 002559 (base 16) Syphan Technologies Ltd - The Watermill - Broughton Hall - Skipton North Yorkshire BD23 3AG - UNITED KINGDOM - - 00-25-5A (hex) Tantalus Systems Corp. - 00255A (base 16) Tantalus Systems Corp. - 301-3480 Gilmore Way - Burnaby BC V5G 4Y1 - CANADA - - 00-25-5B (hex) CoachComm, LLC - 00255B (base 16) CoachComm, LLC - 205 Technology Parkway - Auburn AL 36830 - UNITED STATES - - 00-25-5C (hex) NEC Corporation - 00255C (base 16) NEC Corporation - 1753, Shimonumabe, Nakahara-Ku, Kawasaki - Kanagawa 211-8666 - JAPAN - - 00-25-5D (hex) Morningstar Corporation - 00255D (base 16) Morningstar Corporation - 10611 Iron Bridge Road - Suites L-N - Jessup MD 20794 - UNITED STATES - - 00-25-5E (hex) Shanghai Dare Technologies Co.,Ltd. - 00255E (base 16) Shanghai Dare Technologies Co.,Ltd. - 22F,Info Tech Building, No.1555,Kongjiang Road, - Shanghai 200092 - CHINA - - 00-25-5F (hex) SenTec AG - 00255F (base 16) SenTec AG - Ringstrasse 39 - Therwil 4106 - SWITZERLAND - - 00-25-60 (hex) Ibridge Networks & Communications Ltd. - 002560 (base 16) Ibridge Networks & Communications Ltd. - 28,Bedford Road East Ham - London E6 2NN - UNITED KINGDOM - - 00-25-61 (hex) ProCurve Networking by HP - 002561 (base 16) ProCurve Networking by HP - 8000 Foothills Blvd. - Roseville California 95747 - UNITED STATES - - 00-25-62 (hex) interbro Co. Ltd. - 002562 (base 16) interbro Co. Ltd. - 6F Joyang B/D, 113 Samseong-Dong, Gangnam-Gu - Seoul 135-090 - KOREA, REPUBLIC OF - - 00-25-63 (hex) Luxtera Inc - 002563 (base 16) Luxtera Inc - 2320. Camino Vida Roble - Suite 100 - Carlsbad CA 92011 - UNITED STATES - - 00-25-64 (hex) Dell Inc. - 002564 (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-25-65 (hex) Vizimax Inc. - 002565 (base 16) Vizimax Inc. - 2284, rue de la Province - Longueuil Québec J4G 1G1 - CANADA - - 00-25-66 (hex) Samsung Electronics Co.,Ltd - 002566 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-25-67 (hex) Samsung Electronics - 002567 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-25-68 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 002568 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 00-25-69 (hex) SAGEM COMMUNICATION - 002569 (base 16) SAGEM COMMUNICATION - 14 Rue Paul Dautier - Velizy 78457 - FRANCE - - 00-25-6A (hex) inIT - Institut Industrial IT - 00256A (base 16) inIT - Institut Industrial IT - Liebigstrasse 87 - Lemgo Northrhine-Westfalia 32657 - GERMANY - - 00-25-6B (hex) ATENIX E.E. s.r.l. - 00256B (base 16) ATENIX E.E. s.r.l. - Via Torricelli, 15/b - VERONA VR 37135 - ITALY - - 00-25-6C (hex) "Azimut" Production Association JSC - 00256C (base 16) "Azimut" Production Association JSC - 2-B Ataeva Street - Makhachkala Dagestan 367005 - RUSSIAN FEDERATION - - 00-25-6D (hex) Broadband Forum - 00256D (base 16) Broadband Forum - 48377 Fremont Boulevard - Suite 117 - Fremont CA 94538 - UNITED STATES - - 00-25-6E (hex) Van Breda B.V. - 00256E (base 16) Van Breda B.V. - Mercuriusweg 21 - Brummen Gelderland 6971 GV - NETHERLANDS - - 00-25-6F (hex) Dantherm Power - 00256F (base 16) Dantherm Power - Marienlystvej 65 - Skive 7800 - DENMARK - - 00-25-70 (hex) Eastern Communications Company Limited - 002570 (base 16) Eastern Communications Company Limited - No.398 Wensan Road, - No.66 Dongxin Road,R&D building,B311 - Hangzhou Zhejiang 310013 - CHINA - - 00-25-71 (hex) Zhejiang Tianle Digital Electric Co.,Ltd - 002571 (base 16) Zhejiang Tianle Digital Electric Co.,Ltd - No.8 Tianle Rd,Economic Development Zone - Shengzhou Zhejiang 312400 - CHINA - - 00-25-72 (hex) Nemo-Q International AB - 002572 (base 16) Nemo-Q International AB - Box 210 - Sollentuna 19123 - SWEDEN - - 00-25-73 (hex) ST Electronics (Info-Security) Pte Ltd - 002573 (base 16) ST Electronics (Info-Security) Pte Ltd - 100, Jurong East Street 21, ST Electronics Jurong East Bldg - 609602 - SINGAPORE - - 00-25-74 (hex) KUNIMI MEDIA DEVICE Co., Ltd. - 002574 (base 16) KUNIMI MEDIA DEVICE Co., Ltd. - 3 KITAMACHIDA YAMAZAKI - KUNIMI, DATE FUKUSHIMA 969-1771 - JAPAN - - 00-25-75 (hex) FiberPlex Technologies, LLC - 002575 (base 16) FiberPlex Technologies, LLC - 10840-412 Guilford Rd - Annapolis Junction MD 20701 - UNITED STATES - - 00-25-76 (hex) NELI TECHNOLOGIES - 002576 (base 16) NELI TECHNOLOGIES - Route Nationale - Immeuble Orchis - LE RHEU 35650 - FRANCE - - 00-25-77 (hex) D-BOX Technologies - 002577 (base 16) D-BOX Technologies - 2172 de la Province - Longueuil Quebec J4G 1R7 - CANADA - - 00-25-78 (hex) JSC "Concern "Sozvezdie" - 002578 (base 16) JSC "Concern "Sozvezdie" - Plekhanovskaya st., 14 - Voronezh 394018 - RUSSIAN FEDERATION - - 00-25-79 (hex) J & F Labs - 002579 (base 16) J & F Labs - 1214 W. Boston Post Road - Mamaroneck NY 10543 - UNITED STATES - - 00-25-7A (hex) CAMCO Produktions- und Vertriebs-GmbH für Beschallungs- und Beleuchtungsanlagen - 00257A (base 16) CAMCO Produktions- und Vertriebs-GmbH für Beschallungs- und Beleuchtungsanlagen - Fischpicke 5 - Wenden NRW 57482 - GERMANY - - 00-25-7B (hex) STJ ELECTRONICS PVT LTD - 00257B (base 16) STJ ELECTRONICS PVT LTD - X-24 OKHLA INDUSTRIAL AREA - PHASE - 2 - NEW DELHI DELHI 110 020 - INDIA - - 00-25-7C (hex) Huachentel Technology Development Co., Ltd - 00257C (base 16) Huachentel Technology Development Co., Ltd - 747 XinYu Rd. High-Tech Zone - Jinan Shandong Province 250101 - CHINA - - 00-25-7D (hex) PointRed Telecom Private Ltd. - 00257D (base 16) PointRed Telecom Private Ltd. - 15F - 5., No. 1071, Zhongzheng Road, - Taoyuan City 330 330 - TAIWAN, PROVINCE OF CHINA - - 00-25-7E (hex) NEW POS Technology Limited - 00257E (base 16) NEW POS Technology Limited - 6FRM, 6F, China Economic Trade Building - 7Rd Zizhu, Zhuzilin, Futian District - Shenzhen Guangdong 518000 - CHINA - - 00-25-7F (hex) CallTechSolution Co.,Ltd - 00257F (base 16) CallTechSolution Co.,Ltd - #123,Daewooprugio B/D,344-1, Seogyo-Dong,Mapo-gu - Seoul 121-837 - KOREA, REPUBLIC OF - - 00-25-80 (hex) Equipson S.A. - 002580 (base 16) Equipson S.A. - Poligono Ind. L´Alteró - Avda. Saler, 14 - Silla Valencia 46460 - SPAIN - - 00-25-81 (hex) x-star networks Inc. - 002581 (base 16) x-star networks Inc. - 1F,NO1-2,Chungching S.Rd.Sec 3 - Taipei 10076 - TAIWAN, PROVINCE OF CHINA - - 00-25-82 (hex) Maksat Technologies (P) Ltd - 002582 (base 16) Maksat Technologies (P) Ltd - D-10/6, Okhla, Phase-I - New Delhi 110020 - INDIA - - 00-25-83 (hex) CISCO SYSTEMS, INC. - 002583 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-25-84 (hex) CISCO SYSTEMS, INC. - 002584 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-25-85 (hex) KOKUYO S&T Co., Ltd. - 002585 (base 16) KOKUYO S&T Co., Ltd. - 1-8-35 - Konan - Minato-ku Tokyo 108-8710 - JAPAN - - 00-25-86 (hex) TP-LINK Technologies Co., Ltd. - 002586 (base 16) TP-LINK Technologies Co., Ltd. - Building 7, Second Part, Honghualing Industrial Zone - Xili town, Nanshan - Shenzhen Guangdong 518057 - CHINA - - 00-25-87 (hex) Vitality, Inc. - 002587 (base 16) Vitality, Inc. - One Broadway - 14th Floor - Cambridge MA 02142 - UNITED STATES - - 00-25-88 (hex) Genie Industries, Inc. - 002588 (base 16) Genie Industries, Inc. - 18620 NE 67th Ct - Redmond WA 98052 - UNITED STATES - - 00-25-89 (hex) Hills Industries Limited - 002589 (base 16) Hills Industries Limited - 5 Cambria Road - Keysborough - Melbourne VIC 3173 - AUSTRALIA - - 00-25-8A (hex) Pole/Zero Corporation - 00258A (base 16) Pole/Zero Corporation - 5530 Union Centre Drive - West Chester OH 45069 - UNITED STATES - - 00-25-8B (hex) Mellanox Technologies Ltd - 00258B (base 16) Mellanox Technologies Ltd - 350 Oakmead Parkway - Sunnyvale, CA 94085 - UNITED STATES - - 00-25-8C (hex) ESUS ELEKTRONIK SAN. VE DIS. TIC. LTD. STI. - 00258C (base 16) ESUS ELEKTRONIK SAN. VE DIS. TIC. LTD. STI. - ESENSEHIR MAHALLESI KURKCULER CADDESI - SAFIR SOKAK NO:11/1 DUDULLU UMRANIYE - ISTANBUL 34776 - TURKEY - - 00-25-8D (hex) Haier - 00258D (base 16) Haier - No.1,Haier Road - Qingdao Shandong 266101 - CHINA - - 00-25-8E (hex) The Weather Channel - 00258E (base 16) The Weather Channel - Mail Stop 500 - 300 Interstate North Pkwy - Atlanta GA 30339 - UNITED STATES - - 00-25-8F (hex) Trident Microsystems, Inc. - 00258F (base 16) Trident Microsystems, Inc. - 3408 Garrett Drive - Santa Clara CA 95054 - UNITED STATES - - 00-25-90 (hex) Super Micro Computer, Inc. - 002590 (base 16) Super Micro Computer, Inc. - 980 Rock Avenue - San Jose California 95131 - UNITED STATES - - 00-25-91 (hex) NEXTEK, Inc. - 002591 (base 16) NEXTEK, Inc. - 410 Douglass Street - Reading PA 19601 - UNITED STATES - - 00-25-92 (hex) Guangzhou Shirui Electronic Co., Ltd - 002592 (base 16) Guangzhou Shirui Electronic Co., Ltd - 301D, No.9, Caipin Road, - Guangzhou Science Park - Guangzhou Guangdong 510663 - CHINA - - 00-25-93 (hex) DatNet Informatikai Kft. - 002593 (base 16) DatNet Informatikai Kft. - Hétvezér u. 5. - Szigetszentmiklós Pest megye 2310 - HUNGARY - - 00-25-94 (hex) Eurodesign BG LTD - 002594 (base 16) Eurodesign BG LTD - Business Park Sofia, Building 4, Floor 2 - Sofia 1766 - BULGARIA - - 00-25-95 (hex) Northwest Signal Supply, Inc - 002595 (base 16) Northwest Signal Supply, Inc - 12965 SW Herman Rd - Tualatin OR 97062 - UNITED STATES - - 00-25-96 (hex) GIGAVISION srl - 002596 (base 16) GIGAVISION srl - Via Figini, 16 - Muggiò Milano 20053 - ITALY - - 00-25-97 (hex) Kalki Communication Technologies - 002597 (base 16) Kalki Communication Technologies - #147,2nd Floor, AnantaPushpa Building, - 5th Main Road,7th Sector,HSR Layout - Bangalore Karnataka 560034 - INDIA - - 00-25-98 (hex) Zhong Shan City Litai Electronic Industrial Co. Ltd - 002598 (base 16) Zhong Shan City Litai Electronic Industrial Co. Ltd - No.3 Industrial District, Wuguishan, Cheng gui Road - Zhong shan City Guang dong Province 528458 - CHINA - - 00-25-99 (hex) Hedon e.d. B.V. - 002599 (base 16) Hedon e.d. B.V. - Elektronicaweg 15 - Delft Zuid Holland 2628 XG - NETHERLANDS - - 00-25-9A (hex) CEStronics GmbH - 00259A (base 16) CEStronics GmbH - Friedrichstraße 243 - Velbert 42551 - GERMANY - - 00-25-9B (hex) Beijing PKUNITY Microsystems Technology Co., Ltd - 00259B (base 16) Beijing PKUNITY Microsystems Technology Co., Ltd - 11th Floor, Resource Plaza, No.151 North Zhongguancun Street - Haidian District - Beijing 100080 - CHINA - - 00-25-9C (hex) Cisco-Linksys, LLC - 00259C (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 00-25-9D (hex) PRIVATE - 00259D (base 16) - - 00-25-9E (hex) Huawei Technologies Co., Ltd. - 00259E (base 16) Huawei Technologies Co., Ltd. - B1-7,Huawei Base,Bantian, Longgang District,ShenZhen,GuangDong,CHINA - ShenZhen GuangDong 518129 - CHINA - - 00-25-9F (hex) TechnoDigital Technologies GmbH - 00259F (base 16) TechnoDigital Technologies GmbH - Haesslerstraße 8 - Erfurt Thuringia 99096 - GERMANY - - 00-25-A0 (hex) Nintendo Co., Ltd. - 0025A0 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-25-A1 (hex) Enalasys - 0025A1 (base 16) Enalasys - 250 Avenida Campillo - Calexico California 92231 - UNITED STATES - - 00-25-A2 (hex) Alta Definicion LINCEO S.L. - 0025A2 (base 16) Alta Definicion LINCEO S.L. - Maria de Luna 11, nave 4 - Zaragoza Es-50018 - SPAIN - - 00-25-A3 (hex) Trimax Wireless, Inc. - 0025A3 (base 16) Trimax Wireless, Inc. - 2675 S Horseshoe Dr - Suite 401 - Naples FL 34104 - UNITED STATES - - 00-25-A4 (hex) EuroDesign embedded technologies GmbH - 0025A4 (base 16) EuroDesign embedded technologies GmbH - Waldstratraße 4A - Kirchdorf a.d. Amper Bayern 85414 - GERMANY - - 00-25-A5 (hex) Walnut Media Network - 0025A5 (base 16) Walnut Media Network - 440 N Wolfe Rd - Sunnyvale CA 94085 - UNITED STATES - - 00-25-A6 (hex) Central Network Solution Co., Ltd. - 0025A6 (base 16) Central Network Solution Co., Ltd. - 584-1, Pajang-Dong, JangAn-Gu - Suwon-Si, Kyunggi-Do 440-854 - KOREA, REPUBLIC OF - - 00-25-A7 (hex) Comverge, Inc. - 0025A7 (base 16) Comverge, Inc. - 5390 Triangle Parkway - Suite 300 - Norcross GA 30092 - UNITED STATES - - 00-25-A8 (hex) Kontron (BeiJing) Technology Co.,Ltd - 0025A8 (base 16) Kontron (BeiJing) Technology Co.,Ltd - 17 Building, Block #1,ABP. 188 Western South 4th Ring Road - BeiJing 100070 - CHINA - - 00-25-A9 (hex) Shanghai Embedway Information Technologies Co.,Ltd - 0025A9 (base 16) Shanghai Embedway Information Technologies Co.,Ltd - 2F,Building 9,Lujiazui Software Park, No.20,Lane 91,E'Shan Road - Shanghai 200127 - CHINA - - 00-25-AA (hex) Beijing Soul Technology Co.,Ltd. - 0025AA (base 16) Beijing Soul Technology Co.,Ltd. - Room 606,Xinzheng Office Building - No.1 Changwa Middle Street,Haidian District. - BEIJING 100089 - CHINA - - 00-25-AB (hex) AIO LCD PC BU / TPV - 0025AB (base 16) AIO LCD PC BU / TPV - 10F., No., 230, Liancheng Rd. - Zhonghe City Taipei Taiwan 23553 - TAIWAN, PROVINCE OF CHINA - - 00-25-AC (hex) I-Tech corporation - 0025AC (base 16) I-Tech corporation - 1-15 Shin-ogawa machi - Shinjyuku-ku Tokyo 162-0814 - JAPAN - - 00-25-AD (hex) Manufacturing Resources International - 0025AD (base 16) Manufacturing Resources International - 6415 Shiloh Road East - Alpharetta GA 30005 - UNITED STATES - - 00-25-AE (hex) Microsoft Corporation - 0025AE (base 16) Microsoft Corporation - One Microsoft Way - Redmond Washington 98052-6399 - UNITED STATES - - 00-25-AF (hex) COMFILE Technology - 0025AF (base 16) COMFILE Technology - Guro 5 dong, Guro-gu - 104-5 - Seoul 152-842 - KOREA, REPUBLIC OF - - 00-25-B0 (hex) Schmartz Inc - 0025B0 (base 16) Schmartz Inc - 2307 Valerian Trl - Round Rock TX 78665 - UNITED STATES - - 00-25-B1 (hex) Maya-Creation Corporation - 0025B1 (base 16) Maya-Creation Corporation - 3F, Building M-10, Centre od Hi-Tech Ind. Dist. - Shenzhen 518057 - CHINA - - 00-25-B2 (hex) MBDA Deutschland GmbH - 0025B2 (base 16) MBDA Deutschland GmbH - Hagenauer Forst 27 - Schrobenhausen Bavaria 86529 - GERMANY - - 00-25-B3 (hex) Hewlett-Packard Company - 0025B3 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - MS 6.3.049 - Houston Texas 77070 - UNITED STATES - - 00-25-B4 (hex) CISCO SYSTEMS, INC. - 0025B4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-25-B5 (hex) CISCO SYSTEMS, INC. - 0025B5 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-25-B6 (hex) Telecom FM - 0025B6 (base 16) Telecom FM - 895 Plymouth Road - Slough Berks SL1 4LP - UNITED KINGDOM - - 00-25-B7 (hex) Costar electronics, inc., - 0025B7 (base 16) Costar electronics, inc., - 3fl,-1 no 13,lane 120,nei-hu road sec.1, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-25-B8 (hex) Agile Communications, Inc. - 0025B8 (base 16) Agile Communications, Inc. - 810 Lawrence Dr - Thousand Oaks California 91320 - UNITED STATES - - 00-25-B9 (hex) Cypress Solutions Inc - 0025B9 (base 16) Cypress Solutions Inc - 3066 Beta Ave - Burnaby - BC V5G 4K4 - CANADA - - 00-25-BA (hex) Alcatel-Lucent IPD - 0025BA (base 16) Alcatel-Lucent IPD - 701 E. Middlefield Rd. - Mountain View CA 94043 - UNITED STATES - - 00-25-BB (hex) INNERINT Co., Ltd. - 0025BB (base 16) INNERINT Co., Ltd. - Dongyoung CentralTower #202, Geumjung-dong, - Gunpo-si,Kyunggi-do,435-050 South KOREA. - Gunpo-si Kyunggi-do 430050 - KOREA, REPUBLIC OF - - 00-25-BC (hex) Apple - 0025BC (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-25-BD (hex) Italdata Ingegneria dell'Idea S.p.A. - 0025BD (base 16) Italdata Ingegneria dell'Idea S.p.A. - viale Eroi di Cefalonia 123 - Roma 00128 - ITALY - - 00-25-BE (hex) Tektrap Systems Inc. - 0025BE (base 16) Tektrap Systems Inc. - 15 Buteau St. - Suite 230-9 - Gatineau Quebec J8Z 1V4 - CANADA - - 00-25-BF (hex) Wireless Cables Inc. - 0025BF (base 16) Wireless Cables Inc. - 2880 Zanker Rd, Ste 203 - San Jose CA 95134 - UNITED STATES - - 00-25-C0 (hex) ZillionTV Corporation - 0025C0 (base 16) ZillionTV Corporation - 1170 Kifer Road - Sunnyvale CA 94086 - UNITED STATES - - 00-25-C1 (hex) Nawoo Korea Corp. - 0025C1 (base 16) Nawoo Korea Corp. - 4Fl., Hanwon Bldg., 6-1, Sunae-dong, Bundang-gu, - Seongnam-si Gyeonggi-do 463-825 - KOREA, REPUBLIC OF - - 00-25-C2 (hex) RingBell Co.,Ltd. - 0025C2 (base 16) RingBell Co.,Ltd. - 10586 KingGeorge Hwy - Surrey B.C V3T 2X3 - CANADA - - 00-25-C3 (hex) Nortel Networks - 0025C3 (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - 00-25-C4 (hex) Ruckus Wireless - 0025C4 (base 16) Ruckus Wireless - 880 West Maude Ave. - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 00-25-C5 (hex) Star Link Communication Pvt. Ltd. - 0025C5 (base 16) Star Link Communication Pvt. Ltd. - HR114/6 & Hr132/6, Pulprehladpur, - Suraj kund Road, Near Badarpur, - New Delhi 110044 - INDIA - - 00-25-C6 (hex) kasercorp, ltd - 0025C6 (base 16) kasercorp, ltd - South 20,Gaobu Road,Gaobu Town - Dongwan Guangdong 523000 - CHINA - - 00-25-C7 (hex) altek Corporation - 0025C7 (base 16) altek Corporation - 3F, No. 10, Li-Hsin Road, Science-Based Industrial Park, - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-25-C8 (hex) S-Access GmbH - 0025C8 (base 16) S-Access GmbH - Oberhausenstrasse 47 - Wettswil a/A Zuerich 8907 - SWITZERLAND - - 00-25-C9 (hex) SHENZHEN HUAPU DIGITAL CO., LTD - 0025C9 (base 16) SHENZHEN HUAPU DIGITAL CO., LTD - Futian District,Chegongmiao,TianAn Cyberpark - 17/F East,High-Tech Plaza, Phase ¢ò - ShenZhen Guangdong Province 518040 - CHINA - - 00-25-CA (hex) LS Research, LLC - 0025CA (base 16) LS Research, LLC - W66 N220 Commerce Court - Cedarburg WI 53012 - UNITED STATES - - 00-25-CB (hex) Reiner SCT - 0025CB (base 16) Reiner SCT - Reiner Kartengeräte GmbH & Co. KG. - Goethestraße 14 - Furtwangen 78120 - GERMANY - - 00-25-CC (hex) Mobile Communications Korea Incorporated - 0025CC (base 16) Mobile Communications Korea Incorporated - 1011-1012, Suwon High Venture Valley, - 958 Gosaek-dong, Gwonseon-gu, - Suwon-si, Gyeonggi-do, 441-360 - KOREA, REPUBLIC OF - - 00-25-CD (hex) Skylane Optics - 0025CD (base 16) Skylane Optics - Rue d'Arlon, 6 - Windhof 8399 - LUXEMBOURG - - 00-25-CE (hex) InnerSpace - 0025CE (base 16) InnerSpace - PO Box 2186 - Grand Rapids MI 49501 - UNITED STATES - - 00-25-CF (hex) Nokia Danmark A/S - 0025CF (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-25-D0 (hex) Nokia Danmark A/S - 0025D0 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-25-D1 (hex) Eastern Asia Technology Limited - 0025D1 (base 16) Eastern Asia Technology Limited - 8F-1, No. 188, Baoqiao Rd., Xindian Dist. - New Taipei City 23145 - TAIWAN, PROVINCE OF CHINA - - 00-25-D2 (hex) InpegVision Co., Ltd - 0025D2 (base 16) InpegVision Co., Ltd - 226-3, Bugok-dong, Geumjeong-gu, - Busan 609-320 - KOREA, REPUBLIC OF - - 00-25-D3 (hex) AzureWave Technologies, Inc - 0025D3 (base 16) AzureWave Technologies, Inc - 8F ., No.94, Baozhong Rd. - Xindian City 231 - TAIWAN, PROVINCE OF CHINA - - 00-25-D4 (hex) Fortress Technologies - 0025D4 (base 16) Fortress Technologies - 2 Technology Park Dr - Westford MA 01886 - UNITED STATES - - 00-25-D5 (hex) Robonica (Pty) Ltd - 0025D5 (base 16) Robonica (Pty) Ltd - 41 Park Avenue North - Highway Business Park - Centurion Gauteng 0046 - SOUTH AFRICA - - 00-25-D6 (hex) The Kroger Co. - 0025D6 (base 16) The Kroger Co. - 11450 Grooms Road - Blue Ash OH 45242 - UNITED STATES - - 00-25-D7 (hex) CEDO - 0025D7 (base 16) CEDO - Videnska 127 - BRNO 61900 - CZECH REPUBLIC - - 00-25-D8 (hex) KOREA MAINTENANCE - 0025D8 (base 16) KOREA MAINTENANCE - 3F HAELIM BUIDING 103-7, GURO-5DONG - GURO-GU, - SEOUL 152-842 - KOREA, REPUBLIC OF - - 00-25-D9 (hex) DataFab Systems Inc. - 0025D9 (base 16) DataFab Systems Inc. - 385-3 Hongzun Road - Pingzhen City Taoyuan County 32466 - TAIWAN, PROVINCE OF CHINA - - 00-25-DA (hex) Secura Key - 0025DA (base 16) Secura Key - 20301 Nordhoff St. - Chatsworth CA 91311 - UNITED STATES - - 00-25-DB (hex) ATI Electronics(Shenzhen) Co., LTD - 0025DB (base 16) ATI Electronics(Shenzhen) Co., LTD - 2F,1st Buliding,Tangyanshan Industrial Park, - Tangkeng Village,Shiyan Town, - Shenzhen Guangdong 518108 - CHINA - - 00-25-DC (hex) Sumitomo Electric Networks, Inc - 0025DC (base 16) Sumitomo Electric Networks, Inc - 1-1-3, Shimaya, Konohana-ku - Osaka Osaka Prefecture 554-0024 - JAPAN - - 00-25-DD (hex) SUNNYTEK INFORMATION CO., LTD. - 0025DD (base 16) SUNNYTEK INFORMATION CO., LTD. - 12F, NO. 88, HSIN-TE ROAD - SAN CHUNG CITY - TAIPEI HSIEN 241 - TAIWAN, PROVINCE OF CHINA - - 00-25-DE (hex) Probits Co., LTD. - 0025DE (base 16) Probits Co., LTD. - #1502, Kolon Science Valley II, 811 - Guro-Dong, Guro-Gu, - Seoul 152-878 - KOREA, REPUBLIC OF - - 00-25-DF (hex) PRIVATE - 0025DF (base 16) - - 00-25-E0 (hex) CeedTec Sdn Bhd - 0025E0 (base 16) CeedTec Sdn Bhd - 303-4-5, Krystal Point Business Center - Bayan Lepas Penang 11900 - MALAYSIA - - 00-25-E1 (hex) SHANGHAI SEEYOO ELECTRONIC & TECHNOLOGY CO., LTD - 0025E1 (base 16) SHANGHAI SEEYOO ELECTRONIC & TECHNOLOGY CO., LTD - RM701,XIN'AN BUILDING,99 TIANZHOU RD,XUHUI DISTRICT,SHANGHAI - SHANGHAI 200233 - CHINA - - 00-25-E2 (hex) Everspring Industry Co., Ltd. - 0025E2 (base 16) Everspring Industry Co., Ltd. - 7F., No. 609, Sec 1, Wanshou Rd. - Gueishan Township Taoyuan County 333 - TAIWAN, PROVINCE OF CHINA - - 00-25-E3 (hex) Hanshinit Inc. - 0025E3 (base 16) Hanshinit Inc. - Dong-Won Bld 3F, 395-13, Gal-Ma 2, Seo-Gu - Daejeon 302-809 - KOREA, REPUBLIC OF - - 00-25-E4 (hex) OMNI-WiFi, LLC - 0025E4 (base 16) OMNI-WiFi, LLC - 70 Sullivan Street - Berwick Maine 03901 - UNITED STATES - - 00-25-E5 (hex) LG Electronics Inc - 0025E5 (base 16) LG Electronics Inc - 60-39 ,Gasan-Dong - Gumchon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-25-E6 (hex) Belgian Monitoring Systems bvba - 0025E6 (base 16) Belgian Monitoring Systems bvba - Th. Sevenslaan 106 - Kortrijk WVL 8500 - BELGIUM - - 00-25-E7 (hex) Sony Ericsson Mobile Communications - 0025E7 (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund 22188 - SWEDEN - - 00-25-E8 (hex) Idaho Technology - 0025E8 (base 16) Idaho Technology - 390 Wakara way - Salt lake City UT 84108 - UNITED STATES - - 00-25-E9 (hex) i-mate Development, Inc. - 0025E9 (base 16) i-mate Development, Inc. - 8383 158th Ave. N.E., Suite 300, Redmond, - WA 98052-3871 - Washington WA 98052-3871 - UNITED STATES - - 00-25-EA (hex) Iphion BV - 0025EA (base 16) Iphion BV - Willemstraat 106 - Eindhoven 5616GE - NETHERLANDS - - 00-25-EB (hex) Reutech Radar Systems (PTY) Ltd - 0025EB (base 16) Reutech Radar Systems (PTY) Ltd - 35 Elektron Avenue - Technopark - Stellenbosch Western Cape 7600 - SOUTH AFRICA - - 00-25-EC (hex) Humanware - 0025EC (base 16) Humanware - 445 rue du Parc Industriel - Longueuil Québec J4H 3V7 - CANADA - - 00-25-ED (hex) NuVo Technologies LLC - 0025ED (base 16) NuVo Technologies LLC - 3015 Kustom Drive - Hebron KY 41048 - UNITED STATES - - 00-25-EE (hex) Avtex Ltd - 0025EE (base 16) Avtex Ltd - Unit G5 Capital Business Park - Parkway - Cardiff CF3 2PX - UNITED KINGDOM - - 00-25-EF (hex) I-TEC Co., Ltd. - 0025EF (base 16) I-TEC Co., Ltd. - 7/F,KAWARAMACHI KOYO BLDG.3-4-3,KAWARAMCHI,CHUO-KU, - OSAKA 541-0048 - JAPAN - - 00-25-F0 (hex) Suga Electronics Limited - 0025F0 (base 16) Suga Electronics Limited - Units 1904-1907, Chevalier Commercial Centre, - 8 Wang Hoi Road, , - Kowloon Bay Hong Kong - CHINA - - 00-25-F1 (hex) ARRIS Group, Inc. - 0025F1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-25-F2 (hex) ARRIS Group, Inc. - 0025F2 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-25-F3 (hex) Nordwestdeutsche Zählerrevision - 0025F3 (base 16) Nordwestdeutsche Zählerrevision - Ing. Aug. Knemeyer GmbH & Co. KG - Heideweg 33 - Bad Laer Niedersachsen 49196 - GERMANY - - 00-25-F4 (hex) KoCo Connector AG - 0025F4 (base 16) KoCo Connector AG - Marienstraße 12 - Berlin 10117 - GERMANY - - 00-25-F5 (hex) DVS Korea, Co., Ltd - 0025F5 (base 16) DVS Korea, Co., Ltd - 497-3, SangHa-Dong, Giheung-gu - R&D Hardware 2Team - Yong-In city Gyeonggi-do 446-914 - KOREA, REPUBLIC OF - - 00-25-F6 (hex) netTALK.com, Inc. - 0025F6 (base 16) netTALK.com, Inc. - 1100 NW 163RD DRIVE - SUITE B-4 - NORTH MIAMI BEACH FL 33169 - UNITED STATES - - 00-25-F7 (hex) Ansaldo STS USA - 0025F7 (base 16) Ansaldo STS USA - 1000 Technology Drive - Union Switch & Signal Building - Pittsburgh PA 15219 - UNITED STATES - - 00-25-F9 (hex) GMK electronic design GmbH - 0025F9 (base 16) GMK electronic design GmbH - Daimlerstraße 8 - Wernberg-Koeblitz Bavaria D-92533 - GERMANY - - 00-25-FA (hex) J&M Analytik AG - 0025FA (base 16) J&M Analytik AG - Willy-Messerschmitt-Strasse 8 - Essingen BW 73457 - GERMANY - - 00-25-FB (hex) Tunstall Healthcare A/S - 0025FB (base 16) Tunstall Healthcare A/S - Stroemmen 6 - Noerresundby 9400 - DENMARK - - 00-25-FC (hex) ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. - 0025FC (base 16) ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. - Y. Dudullu Barbaros C. Kutup S. No. 20 - Umraniye - Istanbul 34775 - TURKEY - - 00-25-FD (hex) OBR Centrum Techniki Morskiej S.A. - 0025FD (base 16) OBR Centrum Techniki Morskiej S.A. - Dickmana 62 - Gdynia 81-109 - POLAND - - 00-25-FE (hex) Pilot Electronics Corporation - 0025FE (base 16) Pilot Electronics Corporation - No. 2, Tzu-Chiang 3rd Road, Chung-Li Industrial Zone, - Taoyuan Hsien 32063 - TAIWAN, PROVINCE OF CHINA - - 00-25-FF (hex) CreNova Multimedia Co., Ltd - 0025FF (base 16) CreNova Multimedia Co., Ltd - 7/F, Hana EZ Tower, Gumi-Dong 10, Sungnam Rd 43, - Bundang-Gu - Sungnam-Si Kyunggi-Do 463-870 - KOREA, REPUBLIC OF - - 00-26-00 (hex) TEAC Australia Pty Ltd. - 002600 (base 16) TEAC Australia Pty Ltd. - 75 Northgate Drive - Thomastown Victoria 3074 - AUSTRALIA - - 00-26-01 (hex) Cutera Inc - 002601 (base 16) Cutera Inc - 3240 Bayshore Blvd - Brisbane CA 94405 - UNITED STATES - - 00-26-02 (hex) SMART Temps LLC - 002602 (base 16) SMART Temps LLC - 435 PARK PL CIRCLE SUITE 100 - Mishawaka IN 46545 - UNITED STATES - - 00-26-03 (hex) Shenzhen Wistar Technology Co., Ltd - 002603 (base 16) Shenzhen Wistar Technology Co., Ltd - Rm919, Science &Technology Service Center - No.1 Qilin Rd - Shenzhen Guang Dong 518000 - CHINA - - 00-26-04 (hex) Audio Processing Technology Ltd - 002604 (base 16) Audio Processing Technology Ltd - Whiterock Business Park - 729 Springfield Road - Belfast County Antrim BT12 7FP - UNITED KINGDOM - - 00-26-05 (hex) CC Systems AB - 002605 (base 16) CC Systems AB - Box 83 - Alfta Sweden 82222 - SWEDEN - - 00-26-06 (hex) RAUMFELD GmbH - 002606 (base 16) RAUMFELD GmbH - Reichenberger Str. 124 - Berlin 10999 - GERMANY - - 00-26-07 (hex) Enabling Technology Pty Ltd - 002607 (base 16) Enabling Technology Pty Ltd - 23/44 Kings Park Road - West Perth Western Australia 6005 - AUSTRALIA - - 00-26-08 (hex) Apple - 002608 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-26-09 (hex) Phyllis Co., Ltd. - 002609 (base 16) Phyllis Co., Ltd. - 9th Fl., Room 3/4, No. 52, Sec. 2, Chung Shan North Road, - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 00-26-0A (hex) CISCO SYSTEMS, INC. - 00260A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-0B (hex) CISCO SYSTEMS, INC. - 00260B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-0C (hex) Dataram - 00260C (base 16) Dataram - 186 Princeton Rd. - Bldg. 3A - West Windsor NJ 08550 - UNITED STATES - - 00-26-0D (hex) Mercury Systems, Inc. - 00260D (base 16) Mercury Systems, Inc. - 26 Hampshire Dr - Hudson NH 03051 - UNITED STATES - - 00-26-0E (hex) Ablaze Systems, LLC - 00260E (base 16) Ablaze Systems, LLC - 523 West Valley Road - Wayne Pennsylvania 19087 - UNITED STATES - - 00-26-0F (hex) Linn Products Ltd - 00260F (base 16) Linn Products Ltd - Glasgow Road - Waterfoot - Glasgow G76 0EQ - UNITED KINGDOM - - 00-26-10 (hex) Apacewave Technologies - 002610 (base 16) Apacewave Technologies - 48389 Fremont Blvd, STE#100 - Fremont CA 94538 - UNITED STATES - - 00-26-11 (hex) Licera AB - 002611 (base 16) Licera AB - Teknikringen 1C - Linköping 58330 - SWEDEN - - 00-26-12 (hex) Space Exploration Technologies - 002612 (base 16) Space Exploration Technologies - 1 Rocket Road - Hawthorne CA 90250 - UNITED STATES - - 00-26-13 (hex) Engel Axil S.L. - 002613 (base 16) Engel Axil S.L. - Puig dels Tudons, 6 - Pol. Industrial Santiga - Barbera del Valles Barcelona 08210 - SPAIN - - 00-26-14 (hex) KTNF - 002614 (base 16) KTNF - 204,Daeryungtechnotown1,327,Gasan-Dong, - Geumcheon-Gu, - Seoul 153-771 - KOREA, REPUBLIC OF - - 00-26-15 (hex) Teracom Limited - 002615 (base 16) Teracom Limited - B-84 - Sector - 60 - Noida Uttar Pradesh 201301 - INDIA - - 00-26-16 (hex) Rosemount Inc. - 002616 (base 16) Rosemount Inc. - 8200 Market Boulevard - Chanhassen MN 55317 - UNITED STATES - - 00-26-17 (hex) OEM Worldwide - 002617 (base 16) OEM Worldwide - 2920 Kelly Ave - Watertown SD 57201 - UNITED STATES - - 00-26-18 (hex) ASUSTek COMPUTER INC. - 002618 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 00-26-19 (hex) FRC - 002619 (base 16) FRC - 1511 South Benjamin Avenue - Mason City IA 50401 - UNITED STATES - - 00-26-1A (hex) Femtocomm System Technology Corp. - 00261A (base 16) Femtocomm System Technology Corp. - 2F.-2,No.28, Taiyuan St., - Jhubei City, Hsinchu Country, 30288 - TAIWAN, PROVINCE OF CHINA - - 00-26-1B (hex) LAUREL BANK MACHINES CO., LTD. - 00261B (base 16) LAUREL BANK MACHINES CO., LTD. - 12-6 - higashitabata 1-Chome - Kita-Ku Tokyo 114-0013 - JAPAN - - 00-26-1C (hex) NEOVIA INC. - 00261C (base 16) NEOVIA INC. - 503 LOTTE IT CASTLE 1DONG,550-1 - GASAN-DONG, GEUMCHEON-GU - SEOUL 153-768 - KOREA, REPUBLIC OF - - 00-26-1D (hex) COP SECURITY SYSTEM CORP. - 00261D (base 16) COP SECURITY SYSTEM CORP. - 4~7F, No.5, Lane 130, Min-Chung Rd., - Hsin Tien City - Taipei 23141 - TAIWAN, PROVINCE OF CHINA - - 00-26-1E (hex) QINGBANG ELEC(SZ) CO., LTD - 00261E (base 16) QINGBANG ELEC(SZ) CO., LTD - No. 2, qimin Rd. North District, High-tech Industrial Park, Nanshan, - Shenzhen Guangdong 518000 - CHINA - - 00-26-1F (hex) SAE Magnetics (H.K.) Ltd. - 00261F (base 16) SAE Magnetics (H.K.) Ltd. - SAE Technology Centre - 6 Science Park East Avenue - Hong Kong Science Park Shatin, New Territories - HONG KONG - - 00-26-20 (hex) ISGUS GmbH - 002620 (base 16) ISGUS GmbH - Oberdorfstraße 18 - 22 - VS - Schwenningen BW 78054 - GERMANY - - 00-26-21 (hex) InteliCloud Technology Inc. - 002621 (base 16) InteliCloud Technology Inc. - 895 Dove St. - Ste. 300 - Newport Beach CA 92660 - UNITED STATES - - 00-26-22 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - 002622 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN SUZHOU 215300 - CHINA - - 00-26-23 (hex) JRD Communication Inc - 002623 (base 16) JRD Communication Inc - 16/F, TCL Tower, Gaoxin Nanyi Road, Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-26-24 (hex) Thomson Inc. - 002624 (base 16) Thomson Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 00-26-25 (hex) MediaSputnik - 002625 (base 16) MediaSputnik - Yaroslavskoe shosse, 19, - Moscow 129337 - RUSSIAN FEDERATION - - 00-26-26 (hex) Geophysical Survey Systems, Inc. - 002626 (base 16) Geophysical Survey Systems, Inc. - 12 Industrial Way - Salem NH 03079 - UNITED STATES - - 00-26-27 (hex) Truesell - 002627 (base 16) Truesell - 301 Sungyun Bldg, 89-2 - Yangjae-dong, - Seocho-gu, Seoul 137-130 - KOREA, REPUBLIC OF - - 00-26-28 (hex) companytec automação e controle ltda. - 002628 (base 16) companytec automação e controle ltda. - Rua Marcilio Dias 3005 - Pelotas Rio Grande do Sul 96020-480 - BRAZIL - - 00-26-29 (hex) Juphoon System Software Inc. - 002629 (base 16) Juphoon System Software Inc. - Room 910,Building 2 - Shangdong Internation Building,Jiangdong District - Ningbo Zhejiang 315041 - CHINA - - 00-26-2A (hex) Proxense, LLC - 00262A (base 16) Proxense, LLC - 689 NW Stonepine Dr - Bend Oregon 97701 - UNITED STATES - - 00-26-2B (hex) Wongs Electronics Co. Ltd. - 00262B (base 16) Wongs Electronics Co. Ltd. - Wanfeng Ind. Esata, Shajing, Baoan, - Shenzhen Guang Dong 518104 - CHINA - - 00-26-2C (hex) IKT Advanced Technologies s.r.o. - 00262C (base 16) IKT Advanced Technologies s.r.o. - Piseckeho 334/19 - Praha 5 15000 - CZECH REPUBLIC - - 00-26-2D (hex) Wistron Corporation - 00262D (base 16) Wistron Corporation - 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, - Taipei Hsien Taiwan 221 - TAIWAN, PROVINCE OF CHINA - - 00-26-2E (hex) Chengdu Jiuzhou Electronic Technology Inc - 00262E (base 16) Chengdu Jiuzhou Electronic Technology Inc - A2 Building,Tianfu Software Park - No.765,Mid Tianfu Avenue,High-tech industrial Development Zone - Chengdu Sichuan 610041 - CHINA - - 00-26-2F (hex) HAMAMATSU TOA ELECTRONICS - 00262F (base 16) HAMAMATSU TOA ELECTRONICS - 9162-1 - MIYAKODA-CHO - HAMAMATSU SIZUOKA 431-2102 - JAPAN - - 00-26-30 (hex) ACOREL S.A.S - 002630 (base 16) ACOREL S.A.S - 3, Rue Paul LANGEVIN - SAINT-PERAY F-07130 - FRANCE - - 00-26-31 (hex) COMMTACT LTD - 002631 (base 16) COMMTACT LTD - Nahal Snir 10 - PO Box 169 - Yazne 81101 - ISRAEL - - 00-26-32 (hex) Instrumentation Technologies d.d. - 002632 (base 16) Instrumentation Technologies d.d. - Velika pot 22 - Solkan Nova Gorica 5250 - SLOVENIA - - 00-26-33 (hex) MIR - Medical International Research - 002633 (base 16) MIR - Medical International Research - Via del Maggiolino 125 - Rome RM 00155 - ITALY - - 00-26-34 (hex) Infineta Systems, Inc - 002634 (base 16) Infineta Systems, Inc - 2870 Zanker Rd - Suite 100 - San Jose CA 95134 - UNITED STATES - - 00-26-35 (hex) Bluetechnix GmbH - 002635 (base 16) Bluetechnix GmbH - Waidhausenstr. 3/19 - Vienna 1140 - AUSTRIA - - 00-26-36 (hex) ARRIS Group, Inc. - 002636 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-26-37 (hex) Samsung Electro-Mechanics - 002637 (base 16) Samsung Electro-Mechanics - 314, Metan dong - Suwon Kyung-ki do 443-743 - KOREA, REPUBLIC OF - - 00-26-38 (hex) Xia Men Joyatech Co., Ltd. - 002638 (base 16) Xia Men Joyatech Co., Ltd. - Room 304, 28th Building, Guanri Road, Xiamen Software Park - Xiamen Fujian Province 361008 - CHINA - - 00-26-39 (hex) T.M. Electronics, Inc. - 002639 (base 16) T.M. Electronics, Inc. - 45 Main St - Boylston MA 01505 - UNITED STATES - - 00-26-3A (hex) Digitec Systems - 00263A (base 16) Digitec Systems - 7,1st Street, Kasturibai Nagar - Avadi - Chennai Tamil Nadu 600054 - INDIA - - 00-26-3B (hex) Onbnetech - 00263B (base 16) Onbnetech - 506, Samsung IT Valley, 197-5 - Guro-Dong - Guro-Gu Seoul 152-848 - KOREA, REPUBLIC OF - - 00-26-3C (hex) Bachmann Technology GmbH & Co. KG - 00263C (base 16) Bachmann Technology GmbH & Co. KG - Ernsthaldenstrasse 33 - Stuttgart BW 70565 - GERMANY - - 00-26-3D (hex) MIA Corporation - 00263D (base 16) MIA Corporation - 1-3-15 Yoshino-cho, Minami-ku - Yokohama Kanagawa 232-0014 - JAPAN - - 00-26-3E (hex) Trapeze Networks - 00263E (base 16) Trapeze Networks - 5753 West Las Positas Blvd. - Pleasanton California 94588 - UNITED STATES - - 00-26-3F (hex) LIOS Technology GmbH - 00263F (base 16) LIOS Technology GmbH - Schanzenstraße 39 - Building D9-D13 - Köln Germany D-51063 - GERMANY - - 00-26-40 (hex) Baustem Broadband Technologies, Ltd. - 002640 (base 16) Baustem Broadband Technologies, Ltd. - 910 Quantum Plaza - No.23 Zhichun Road - Beijing 100191 - CHINA - - 00-26-41 (hex) ARRIS Group, Inc. - 002641 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-26-42 (hex) ARRIS Group, Inc. - 002642 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-26-43 (hex) Alps Electric Co., Ltd - 002643 (base 16) Alps Electric Co., Ltd - 1-2-1,Okinouchi - Soma-city Fukushima-ken 976-8501 - JAPAN - - 00-26-44 (hex) Thomson Telecom Belgium - 002644 (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - Edegem Antwerp B-2650 - BELGIUM - - 00-26-45 (hex) Circontrol S.A. - 002645 (base 16) Circontrol S.A. - Lepant 43 - Terrassa Barcelona 08223 - SPAIN - - 00-26-46 (hex) SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED - 002646 (base 16) SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED - No.10 Ping Nan East Road - Hunnan New District. - Shenyang Liao Ning 110014 - CHINA - - 00-26-47 (hex) WFE TECHNOLOGY CORP. - 002647 (base 16) WFE TECHNOLOGY CORP. - 17F NO.238,Chin-Hua N Rd, - Taichung 404 - TAIWAN, PROVINCE OF CHINA - - 00-26-48 (hex) Emitech Corp. - 002648 (base 16) Emitech Corp. - No. 156-5A, ChengGong 1st St., - Jhubei City Hsinchu County 302 - TAIWAN, PROVINCE OF CHINA - - 00-26-4A (hex) Apple - 00264A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-26-4C (hex) Shanghai DigiVision Technology Co., Ltd. - 00264C (base 16) Shanghai DigiVision Technology Co., Ltd. - No. 333 Guangji Rd. - Shanghai 200083 - CHINA - - 00-26-4D (hex) Arcadyan Technology Corporation - 00264D (base 16) Arcadyan Technology Corporation - 4F., No. 9 , Park Avenue II , - Hsinchu Science Park , - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-26-4E (hex) Rail & Road Protec GmbH - 00264E (base 16) Rail & Road Protec GmbH - Norderhofenden 12-13 - Flensburg 24937 - GERMANY - - 00-26-4F (hex) Krüger &Gothe GmbH - 00264F (base 16) Krüger &Gothe GmbH - Atzendorfer Straße 19 - Staßfurt Sachsen Anhalt 39418 - GERMANY - - 00-26-50 (hex) 2Wire - 002650 (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 00-26-51 (hex) CISCO SYSTEMS, INC. - 002651 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-52 (hex) CISCO SYSTEMS, INC. - 002652 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-53 (hex) DaySequerra Corporation - 002653 (base 16) DaySequerra Corporation - 154 Cooper Road - Suite #902 - West Berlin NJ 08091 - UNITED STATES - - 00-26-54 (hex) 3Com Corporation - 002654 (base 16) 3Com Corporation - 5353 Betsy Ross Drive - Bldg 14, M/S 1425 - Santa Clara California 95054-1162 - UNITED STATES - - 00-26-55 (hex) Hewlett-Packard Company - 002655 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Ms 060302 - Houston Texas 77095 - UNITED STATES - - 00-26-56 (hex) Sansonic Electronics USA - 002656 (base 16) Sansonic Electronics USA - 9950 Baldwin Place - El Monte Cailfornia 91731 - UNITED STATES - - 00-26-57 (hex) OOO NPP EKRA - 002657 (base 16) OOO NPP EKRA - I.Yakovleva St., 3 - Cheboksary Chuvash Republic 428003 - RUSSIAN FEDERATION - - 00-26-58 (hex) T-Platforms (Cyprus) Limited - 002658 (base 16) T-Platforms (Cyprus) Limited - Themistokli Dervi 3, Julia House - Nicosia P.C.-1066 - CYPRUS - - 00-26-59 (hex) Nintendo Co., Ltd. - 002659 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-26-5A (hex) D-Link Corporation - 00265A (base 16) D-Link Corporation - No.289, Sinhu 3rd Rd., - Neihu District 114 - TAIWAN, PROVINCE OF CHINA - - 00-26-5B (hex) Hitron Technologies. Inc - 00265B (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd. Hsinchu Science Park, - Hsin-chu 300 - TAIWAN, PROVINCE OF CHINA - - 00-26-5C (hex) Hon Hai Precision Ind. Co.,Ltd. - 00265C (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 00-26-5D (hex) Samsung Electronics - 00265D (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-26-5E (hex) Hon Hai Precision Ind. Co.,Ltd. - 00265E (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 00-26-5F (hex) Samsung Electronics Co.,Ltd - 00265F (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-26-60 (hex) Logiways - 002660 (base 16) Logiways - 24/26 rue Louis ARMAND - PARIS 75015 - FRANCE - - 00-26-61 (hex) Irumtek Co., Ltd. - 002661 (base 16) Irumtek Co., Ltd. - Apt 708 513-22 Joongil Eines Platz - Sangdaewon-dong, Jungwon-Gu - Seongnam-City Gyunggi-do 462-120 - KOREA, REPUBLIC OF - - 00-26-62 (hex) Actiontec Electronics, Inc - 002662 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-26-63 (hex) Shenzhen Huitaiwei Tech. Ltd, co. - 002663 (base 16) Shenzhen Huitaiwei Tech. Ltd, co. - JianDa Building,501-502 - Kewei No. 1 - Shenzhen Guangdong 518000 - CHINA - - 00-26-64 (hex) Core System Japan - 002664 (base 16) Core System Japan - Bunshu Bldg,2-27-6,Myojin - Hachioji Tokyo 1920046 - JAPAN - - 00-26-65 (hex) ProtectedLogic Corporation - 002665 (base 16) ProtectedLogic Corporation - PO Box 67707 - Albuquerque NM 87193 - UNITED STATES - - 00-26-66 (hex) EFM Networks - 002666 (base 16) EFM Networks - 6F Benposra II B/D 1802-1 - Bojeong-dong Giheung-gu, - Yong In Kyunggi-do 446-913 - KOREA, REPUBLIC OF - - 00-26-67 (hex) CARECOM CO.,LTD. - 002667 (base 16) CARECOM CO.,LTD. - 3-35-4 - Tamagawa - Chofu Tokyo 182-0025 - JAPAN - - 00-26-68 (hex) Nokia Danmark A/S - 002668 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-26-69 (hex) Nokia Danmark A/S - 002669 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 00-26-6A (hex) ESSENSIUM NV - 00266A (base 16) ESSENSIUM NV - Gaston Geenslaan 9 - LEUVEN VL BRABANT 3001 - BELGIUM - - 00-26-6B (hex) SHINE UNION ENTERPRISE LIMITED - 00266B (base 16) SHINE UNION ENTERPRISE LIMITED - UNIT 1211, 12FL., CHEVALIER COMMERCIAL CENTER, - NO.8 WANG HOI ROAD, KOWLOONBAY - KOWLOON NIL - HONG KONG - - 00-26-6C (hex) Inventec - 00266C (base 16) Inventec - Inventec Building, 66 Hou-Kang Street Shih-Lin District, - Taipei 111 - TAIWAN, PROVINCE OF CHINA - - 00-26-6D (hex) MobileAccess Networks - 00266D (base 16) MobileAccess Networks - 8391 Old Courthouse Rd. - Suite 300 - Vienna VA 22182 - UNITED STATES - - 00-26-6E (hex) Nissho-denki Co.,LTD. - 00266E (base 16) Nissho-denki Co.,LTD. - 3-7-6,chidori - ohta Tokyo 146-0083 - JAPAN - - 00-26-6F (hex) Coordiwise Technology Corp. - 00266F (base 16) Coordiwise Technology Corp. - 2F., No.123, Sec. 1, Lioujia 5th Rd. - Jhubei City, Hsinchu County 30272 - TAIWAN, PROVINCE OF CHINA - - 00-26-70 (hex) Cinch Connectors - 002670 (base 16) Cinch Connectors - 1700 Finley Road - Lombard IL 60148 - UNITED STATES - - 00-26-71 (hex) AUTOVISION Co., Ltd - 002671 (base 16) AUTOVISION Co., Ltd - Shinsegae YBS Bldg. 102 - 227-1, Yongdap-Dong - Seongdong-gu Seoul 133-847 - KOREA, REPUBLIC OF - - 00-26-72 (hex) AAMP of America - 002672 (base 16) AAMP of America - 13190 56th Court - Suite 401 - Clearwater Florida 33760 - UNITED STATES - - 00-26-73 (hex) RICOH COMPANY,LTD. - 002673 (base 16) RICOH COMPANY,LTD. - 810 Shimoimaizumi - Ebina-City Kanagawa-Pref 243-0460 - JAPAN - - 00-26-74 (hex) Electronic Solutions, Inc. - 002674 (base 16) Electronic Solutions, Inc. - 1355 Horizon Avenue - Lafayette CO 80026 - UNITED STATES - - 00-26-75 (hex) Aztech Electronics Pte Ltd - 002675 (base 16) Aztech Electronics Pte Ltd - 31 Ubi Road 1 - Aztech Building - Singapore 408694 - SINGAPORE - - 00-26-76 (hex) COMMidt AS - 002676 (base 16) COMMidt AS - Kikregata 57-59 - Levanger Nord-Troendelag 7600 - NORWAY - - 00-26-77 (hex) DEIF A/S - 002677 (base 16) DEIF A/S - Frisenborgvej 33 - Skive 7800 - DENMARK - - 00-26-78 (hex) Logic Instrument SA - 002678 (base 16) Logic Instrument SA - 43, Avenue de l'Europe - BP 60012 - Domont 95330 - FRANCE - - 00-26-79 (hex) Euphonic Technologies, Inc. - 002679 (base 16) Euphonic Technologies, Inc. - 2-5-10 Shin-yokohama, Kouhoku-ku - Yokohama 222-0033 - JAPAN - - 00-26-7A (hex) wuhan hongxin telecommunication technologies co.,ltd - 00267A (base 16) wuhan hongxin telecommunication technologies co.,ltd - No.5 Donxin Road,Wuhan East Lake High-Tech Development Zone - Wuhan Hubei 430073 - CHINA - - 00-26-7B (hex) GSI Helmholtzzentrum für Schwerionenforschung GmbH - 00267B (base 16) GSI Helmholtzzentrum für Schwerionenforschung GmbH - Planckstraße 1 - Darmstadt Hessen 64291 - GERMANY - - 00-26-7C (hex) Metz-Werke GmbH & Co KG - 00267C (base 16) Metz-Werke GmbH & Co KG - Ohmstrasse 55 - Zirndorf 90513 - GERMANY - - 00-26-7D (hex) A-Max Technology Macao Commercial Offshore Company Limited - 00267D (base 16) A-Max Technology Macao Commercial Offshore Company Limited - Avenida Da Praia Grande No. 409 - Edificio Dos Servicos Juridicos Da China 5A - Macau - CHINA - - 00-26-7E (hex) Parrot SA - 00267E (base 16) Parrot SA - 174 quai de Jemmapes - Paris 78100 - FRANCE - - 00-26-7F (hex) Zenterio AB - 00267F (base 16) Zenterio AB - Diskettgatan 11B - Linköping 58335 - SWEDEN - - 00-26-80 (hex) Lockie Innovation Pty Ltd - 002680 (base 16) Lockie Innovation Pty Ltd - Factory 10 - 9-13 Dingley Avenue - DANDENONG VICTORIA 3175 - AUSTRALIA - - 00-26-81 (hex) Interspiro AB - 002681 (base 16) Interspiro AB - Box 2853 - Täby 18728 - SWEDEN - - 00-26-82 (hex) Gemtek Technology Co., Ltd. - 002682 (base 16) Gemtek Technology Co., Ltd. - No.1 Jen Ai Road, Hsinchu Industrial Park, - Hsinchu Taiwan 303 - TAIWAN, PROVINCE OF CHINA - - 00-26-83 (hex) Ajoho Enterprise Co., Ltd. - 002683 (base 16) Ajoho Enterprise Co., Ltd. - 7F., No.101, Ruihu St. - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-26-84 (hex) KISAN SYSTEM - 002684 (base 16) KISAN SYSTEM - GWANGMYEONG TECHNOPARK B-403 - SOHA-DONG, GWANGMYEONG-SI - GWANGMYEONG GYEONGGI 423-050 - KOREA, REPUBLIC OF - - 00-26-85 (hex) Digital Innovation - 002685 (base 16) Digital Innovation - Travbaneveien 6 - Trondheim 7044 - NORWAY - - 00-26-86 (hex) Quantenna Communcations, Inc. - 002686 (base 16) Quantenna Communcations, Inc. - 3450 W. Warren Ave. - Fremont CA 94538 - UNITED STATES - - 00-26-87 (hex) Corega K.K - 002687 (base 16) Corega K.K - 1-19-20, Shinyokohama - Kouhoku-ku - Yokohama-city Kanagawa-ken 222-0033 - JAPAN - - 00-26-88 (hex) Juniper Networks - 002688 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-26-89 (hex) General Dynamics Robotic Systems - 002689 (base 16) General Dynamics Robotic Systems - 1231 Tech Court - Westminster MD 21157 - UNITED STATES - - 00-26-8A (hex) Terrier SC Ltd - 00268A (base 16) Terrier SC Ltd - Strettit Farm - Snoll Hatch Road - East Peckham Kent TN12 5EE - UNITED KINGDOM - - 00-26-8B (hex) Guangzhou Escene Computer Technology Limited - 00268B (base 16) Guangzhou Escene Computer Technology Limited - Room 209, No.54-56 Yuehe Building, Huacui Street, Tianhe Industrial Park - Guangzhou Guangdong Province 510065 - CHINA - - 00-26-8C (hex) StarLeaf Ltd. - 00268C (base 16) StarLeaf Ltd. - Chaston House, Mill Court - Great Shelford - Cambridge CB22 5LD - UNITED KINGDOM - - 00-26-8D (hex) CellTel S.p.A. - 00268D (base 16) CellTel S.p.A. - Via Romano 72 - Scarmagno Torino 10010 - ITALY - - 00-26-8E (hex) Alta Solutions, Inc. - 00268E (base 16) Alta Solutions, Inc. - 11305 Rancho Bernardo Road - Suite 104 - San Diego CA 92127 - UNITED STATES - - 00-26-8F (hex) MTA SpA - 00268F (base 16) MTA SpA - Viale dell Industria 12 - Codogno LODI 26845 - ITALY - - 00-26-90 (hex) I DO IT - 002690 (base 16) I DO IT - 1308, WoolimLions2nd Doksan Station - Seoul 153-787 - KOREA, REPUBLIC OF - - 00-26-91 (hex) SAGEM COMMUNICATION - 002691 (base 16) SAGEM COMMUNICATION - 14 Rue Paul Dautier - Velizy 78457 - FRANCE - - 00-26-92 (hex) Mitsubishi Electric Co. - 002692 (base 16) Mitsubishi Electric Co. - 2-7-3 Marunouchi - Chiyoda-ku Tokyo 100-8310 - JAPAN - - 00-26-93 (hex) QVidium Technologies, Inc. - 002693 (base 16) QVidium Technologies, Inc. - 12989 Chaparral Ridge Rd - San Diego CA 92130 - UNITED STATES - - 00-26-94 (hex) Senscient Ltd - 002694 (base 16) Senscient Ltd - Unit 2, Block A, Arena Business Centre - Holy Rood Close - Poole Dorset BH17 7FJ - UNITED KINGDOM - - 00-26-95 (hex) ZT Group Int'l Inc - 002695 (base 16) ZT Group Int'l Inc - 350 Meadowlands Parkway - Secaucus NJ 07094 - UNITED STATES - - 00-26-96 (hex) NOOLIX Co., Ltd - 002696 (base 16) NOOLIX Co., Ltd - DAECHANG B/D 3F, 8-2 SUNAE-DONG - BUDANG-GU - SUNGNAM-SI KYUNGGI-DO 463-825 - KOREA, REPUBLIC OF - - 00-26-97 (hex) Cheetah Technologies, L.P. - 002697 (base 16) Cheetah Technologies, L.P. - 381 Mansfield Avenue - Suite 200 - Pittsburgh PA 15220 - UNITED STATES - - 00-26-98 (hex) CISCO SYSTEMS, INC. - 002698 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-99 (hex) CISCO SYSTEMS, INC. - 002699 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-9A (hex) Carina System Co., Ltd. - 00269A (base 16) Carina System Co., Ltd. - 2-2-11 Kotonoo-cho - Chuo-ku - Kobe Hyogo 651-0094 - JAPAN - - 00-26-9B (hex) SOKRAT Ltd. - 00269B (base 16) SOKRAT Ltd. - Volkonskogo 2 - Irkutsk 664007 - RUSSIAN FEDERATION - - 00-26-9C (hex) ITUS JAPAN CO. LTD - 00269C (base 16) ITUS JAPAN CO. LTD - 7F Shinkawa B/D - 1-1-7 Shinkawa - Chuoku Tokyo 1040033 - JAPAN - - 00-26-9D (hex) M2Mnet Co., Ltd. - 00269D (base 16) M2Mnet Co., Ltd. - 607 Downtown Bld. 1043-1 Hogye-Dong Dongan-Gu - Anyang-City Kyunggi-Do 431-080 - KOREA, REPUBLIC OF - - 00-26-9E (hex) Quanta Computer Inc - 00269E (base 16) Quanta Computer Inc - NO. 211, WEN HWA 2RD., KUEI SHAN HSIANG, TAIPEI, SHIEN - TAO YUAN 333 - TAIWAN, PROVINCE OF CHINA - - 00-26-9F (hex) PRIVATE - 00269F (base 16) - - 00-26-A0 (hex) moblic - 0026A0 (base 16) moblic - 7F, 271-1, Seohyeon-dong, Bundang-gu - Seongnam-si Kyeonggi-do 463-824 - KOREA, REPUBLIC OF - - 00-26-A1 (hex) Megger - 0026A1 (base 16) Megger - 4271 Bronze Way - Dallas Texas 75237 - UNITED STATES - - 00-26-A2 (hex) Instrumentation Technology Systems - 0026A2 (base 16) Instrumentation Technology Systems - 19360 Business Center Drive - Northridge CA 91324 - UNITED STATES - - 00-26-A3 (hex) FQ Ingenieria Electronica S.A. - 0026A3 (base 16) FQ Ingenieria Electronica S.A. - Avda. Roquetes 9 - Poligon Industrial Vilanoveta - Sant Pere de Ribes Barcelona 08812 - SPAIN - - 00-26-A4 (hex) Novus Produtos Eletronicos Ltda - 0026A4 (base 16) Novus Produtos Eletronicos Ltda - Rua Alvaro Chaves, 155 - Bairro Floresta - Porto Alegre RS 90220-040 - BRAZIL - - 00-26-A5 (hex) MICROROBOT.CO.,LTD - 0026A5 (base 16) MICROROBOT.CO.,LTD - 167-3 Gungpyeong-ri - Docheok-myeon - Gwangju-si Gyeonggi-Do 464-881 - KOREA, REPUBLIC OF - - 00-26-A6 (hex) TRIXELL - 0026A6 (base 16) TRIXELL - 460, Rue du pommarin - MOIRANS 38210 - FRANCE - - 00-26-A7 (hex) CONNECT SRL - 0026A7 (base 16) CONNECT SRL - Via Cernaia, 11 - Milan 20121 - ITALY - - 00-26-A8 (hex) DAEHAP HYPER-TECH - 0026A8 (base 16) DAEHAP HYPER-TECH - Mega center #1108, SK Techno-Park, #190-1, Sangdaewon-Dong, Jungwon-Gu - Seongnam Gyeonggi-Do 462-807 - KOREA, REPUBLIC OF - - 00-26-A9 (hex) Strong Technologies Pty Ltd - 0026A9 (base 16) Strong Technologies Pty Ltd - 60 Wedgewood Road - Hallam Victoria 3803 - AUSTRALIA - - 00-26-AA (hex) Kenmec Mechanical Engineering Co., Ltd. - 0026AA (base 16) Kenmec Mechanical Engineering Co., Ltd. - 3F, No. 97, Sec.2 Nan-Kang Rd., - Taipei 11578 - TAIWAN, PROVINCE OF CHINA - - 00-26-AB (hex) SEIKO EPSON CORPORATION - 0026AB (base 16) SEIKO EPSON CORPORATION - 3-3-5 OWA - SUWA-SHI NAGANO-KEN 392-8502 - JAPAN - - 00-26-AC (hex) Shanghai LUSTER Teraband photonic Co., Ltd. - 0026AC (base 16) Shanghai LUSTER Teraband photonic Co., Ltd. - F4, No.39 ChengZhong Rd. - JiaDing District - Shanghai 201800 - CHINA - - 00-26-AD (hex) Arada Systems, Inc. - 0026AD (base 16) Arada Systems, Inc. - 1024 Morse Avenue - Sunnyvale CA 94089 - UNITED STATES - - 00-26-AE (hex) Wireless Measurement Ltd - 0026AE (base 16) Wireless Measurement Ltd - The Crescent - EMSWORTH PO10 8JS - UNITED KINGDOM - - 00-26-AF (hex) Duelco A/S - 0026AF (base 16) Duelco A/S - Mommarkvej 5 - Vollerup - Soenderborg Soenderjylland DK6400 - DENMARK - - 00-26-B0 (hex) Apple - 0026B0 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-26-B1 (hex) Navis Auto Motive Systems, Inc. - 0026B1 (base 16) Navis Auto Motive Systems, Inc. - Busan, Centumjungang-ro 78, Centum Greentower 8th floor - BUSAN 612-822 - KOREA, REPUBLIC OF - - 00-26-B2 (hex) Setrix GmbH - 0026B2 (base 16) Setrix GmbH - Josephspitalstrasse 15 - Muenchen Bayern 80331 - GERMANY - - 00-26-B3 (hex) Thales Communications Inc - 0026B3 (base 16) Thales Communications Inc - 22605 Gateway Center Drive - Clarksburg MD 20871 - UNITED STATES - - 00-26-B4 (hex) Ford Motor Company - 0026B4 (base 16) Ford Motor Company - 20300 Rotunda Drive - Building #5, 2G053 - Dearborn MI 48124 - UNITED STATES - - 00-26-B5 (hex) ICOMM Tele Ltd - 0026B5 (base 16) ICOMM Tele Ltd - 304, Trendset Towers, - Raod # 2, Banjara Hills - Hyderabad AP 500034 - INDIA - - 00-26-B6 (hex) Askey Computer - 0026B6 (base 16) Askey Computer - 10F,NO.119,CHIENKANG RD,CHUNG-HO - TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - 00-26-B7 (hex) Kingston Technology Company, Inc. - 0026B7 (base 16) Kingston Technology Company, Inc. - 17600 Newhope St. - Fountain Valley CA 92708 - UNITED STATES - - 00-26-B8 (hex) Actiontec Electronics, Inc - 0026B8 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-26-B9 (hex) Dell Inc - 0026B9 (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 00-26-BA (hex) ARRIS Group, Inc. - 0026BA (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-26-BB (hex) Apple - 0026BB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-26-BC (hex) General Jack Technology Ltd. - 0026BC (base 16) General Jack Technology Ltd. - The Area of Administration of Lian Bei, - Chang Ping - Dong Guan Guang Dong 523580 - CHINA - - 00-26-BD (hex) JTEC Card & Communication Co., Ltd. - 0026BD (base 16) JTEC Card & Communication Co., Ltd. - Dabo Bldg, 4F, 61-1, Gyesu-dong, Sosa-gu - Bucheon Gyunggi-do 422-070 - KOREA, REPUBLIC OF - - 00-26-BE (hex) Schoonderbeek Elektronica Systemen B.V. - 0026BE (base 16) Schoonderbeek Elektronica Systemen B.V. - Roggestraat 3-5 - Nieuw Vennep Noord Holland 2153GC - NETHERLANDS - - 00-26-BF (hex) ShenZhen Temobi Science&Tech Development Co.,Ltd - 0026BF (base 16) ShenZhen Temobi Science&Tech Development Co.,Ltd - 4FloorG, Jinrun Tower, 6019 Shennan Road - FuTian District - ShenZhen 518000 - CHINA - - 00-26-C0 (hex) EnergyHub - 0026C0 (base 16) EnergyHub - 232 3rd St C201 - Brooklyn NY 11215 - UNITED STATES - - 00-26-C1 (hex) ARTRAY CO., LTD. - 0026C1 (base 16) ARTRAY CO., LTD. - 5F Ueno Bldg, 1-17-5 Kouenjikita, - Suginami-ku, - Tokyo 166-0002 - JAPAN - - 00-26-C2 (hex) SCDI Co. LTD - 0026C2 (base 16) SCDI Co. LTD - #451, Hagal-Dong, Giheung-Gu, - Yongin-Si Gyeonggi-Do 446-930 - KOREA, REPUBLIC OF - - 00-26-C3 (hex) Insightek Corp. - 0026C3 (base 16) Insightek Corp. - 5F,NO.755,Chung Cheng Rd., - Chung Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 00-26-C4 (hex) Cadmos microsystems S.r.l. - 0026C4 (base 16) Cadmos microsystems S.r.l. - Via Pietro Frattini, 255 - Roma 00149 - ITALY - - 00-26-C5 (hex) Guangdong Gosun Telecommunications Co.,Ltd - 0026C5 (base 16) Guangdong Gosun Telecommunications Co.,Ltd - Guangdong software park D, No.11, CaiPing road , Guangzhou science city - Guangzhou Guangdong 510663 - CHINA - - 00-26-C6 (hex) Intel Corporate - 0026C6 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-26-C7 (hex) Intel Corporate - 0026C7 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-26-C8 (hex) System Sensor - 0026C8 (base 16) System Sensor - 3825 Ohio Avenue - Saint Charles IL 60174 - UNITED STATES - - 00-26-C9 (hex) Proventix Systems, Inc. - 0026C9 (base 16) Proventix Systems, Inc. - 4518 Valleydale Road - Suite 202 - Birmingham AL 35242 - UNITED STATES - - 00-26-CA (hex) CISCO SYSTEMS, INC. - 0026CA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-CB (hex) CISCO SYSTEMS, INC. - 0026CB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-26-CC (hex) Nokia Danmark A/S - 0026CC (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 V - DENMARK - - 00-26-CD (hex) PurpleComm, Inc. - 0026CD (base 16) PurpleComm, Inc. - 2620 Augustine Dr., Ste. 100 - Santa Clara CA 95054 - UNITED STATES - - 00-26-CE (hex) Kozumi USA Corp. - 0026CE (base 16) Kozumi USA Corp. - 3005 Hartridge Terrace - Wellington FL 33414 - UNITED STATES - - 00-26-CF (hex) DEKA R&D - 0026CF (base 16) DEKA R&D - 340 Commercial Street - Manchester NH 03101 - UNITED STATES - - 00-26-D0 (hex) Semihalf - 0026D0 (base 16) Semihalf - ul. Wadowicka 8A - Krakow ... 30-415 - POLAND - - 00-26-D1 (hex) S Squared Innovations Inc. - 0026D1 (base 16) S Squared Innovations Inc. - 6807-104 Street - Edmonton AB T6H 2L5 - CANADA - - 00-26-D2 (hex) Pcube Systems, Inc. - 0026D2 (base 16) Pcube Systems, Inc. - 1857 O'Toole Lane - San Jose CA 95131 - UNITED STATES - - 00-26-D3 (hex) Zeno Information System - 0026D3 (base 16) Zeno Information System - #1404 A-Dong Digital Empire Bldg, 980-3, Youngtong-dong, Youngtong-gu - Suwon City Gyeonggi-Do 443-702 - KOREA, REPUBLIC OF - - 00-26-D4 (hex) IRCA SpA - 0026D4 (base 16) IRCA SpA - Viale Venezia 31 - C.P. 248 - San Vendemiano (Treviso) Italy 31020 - ITALY - - 00-26-D5 (hex) Ory Solucoes em Comercio de Informatica Ltda. - 0026D5 (base 16) Ory Solucoes em Comercio de Informatica Ltda. - Av. Unisinos, 615 - Sao Leopoldo RS 93022000 - BRAZIL - - 00-26-D6 (hex) Ningbo Andy Optoelectronic Co., Ltd. - 0026D6 (base 16) Ningbo Andy Optoelectronic Co., Ltd. - Lanjiang Street Industrial Zone - Yuyao Zhejiang 315400 - CHINA - - 00-26-D7 (hex) KM Electornic Technology Co., Ltd. - 0026D7 (base 16) KM Electornic Technology Co., Ltd. - 5F, NO.3 Building, NO.118 Rd. Baoan District, Shenzhen China - Shenzhen Guangdong 518101 - CHINA - - 00-26-D8 (hex) Magic Point Inc. - 0026D8 (base 16) Magic Point Inc. - Suite 203, Building 17, No. 295 Lin Nan Road, Pudong Software Park Sanlin World Expo Block - Shanghai 2000126 - CHINA - - 00-26-D9 (hex) Pace plc - 0026D9 (base 16) Pace plc - Salts Mill - Victoria Road - Bradford West Yorkshire BD18 3LF - UNITED KINGDOM - - 00-26-DA (hex) Universal Media Corporation /Slovakia/ s.r.o. - 0026DA (base 16) Universal Media Corporation /Slovakia/ s.r.o. - Mickiewiczova 7104/14 - Bratislava 811 07 - SLOVAKIA - - 00-26-DB (hex) Ionics EMS Inc. - 0026DB (base 16) Ionics EMS Inc. - Carmelray Industrial Park 2, Brgy. Tulo - Calamba Laguna 4027 - PHILIPPINES - - 00-26-DC (hex) Optical Systems Design - 0026DC (base 16) Optical Systems Design - 7/1 Vuko Place - Warriewood NSW 2102 - AUSTRALIA - - 00-26-DD (hex) Fival Science & Technology Co.,Ltd. - 0026DD (base 16) Fival Science & Technology Co.,Ltd. - 1/F, Building 57, No.461 - HongCao Road, XuHui District - Shanghai Shanghai 200233 - CHINA - - 00-26-DE (hex) FDI MATELEC - 0026DE (base 16) FDI MATELEC - Route de saint symphorien - BP 69 - Les landes Génusson 85130 - FRANCE - - 00-26-DF (hex) TaiDoc Technology Corp. - 0026DF (base 16) TaiDoc Technology Corp. - 7F, No. 127, Wugong 2nd Rd., 24888 Wugu Township - Taipei County Taiwan 24888 - TAIWAN, PROVINCE OF CHINA - - 00-26-E0 (hex) ASITEQ - 0026E0 (base 16) ASITEQ - 5F, DONGYOUNG Bldg,382-6,Yatap dong - Bundang Gu, - Sung Nam si Kyounggi-do 463-827 - KOREA, REPUBLIC OF - - 00-26-E1 (hex) Stanford University, OpenFlow Group - 0026E1 (base 16) Stanford University, OpenFlow Group - 353 Serra Mall - EE - Computer Systems Laboratory - Stanford CA 94305-9030 - UNITED STATES - - 00-26-E2 (hex) LG Electronics - 0026E2 (base 16) LG Electronics - 60-39,Gasan-dong,Gumcheon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 00-26-E3 (hex) DTI - 0026E3 (base 16) DTI - Rue de la gare, 35 - NANINNE NAMUR 5100 - BELGIUM - - 00-26-E4 (hex) CANAL OVERSEAS - 0026E4 (base 16) CANAL OVERSEAS - 48 quai du point du jour - Boulogne-Billancourt 92659 - FRANCE - - 00-26-E5 (hex) AEG Power Solutions - 0026E5 (base 16) AEG Power Solutions - Emil Siepmannstraße 32 - Warstein NRW 59581 - GERMANY - - 00-26-E6 (hex) Visionhitech Co., Ltd. - 0026E6 (base 16) Visionhitech Co., Ltd. - Vision bldg. 150-3 - Simgok-Dong, Wonmi-Ku - Buchon Kyunggi-Do 420-822 - KOREA, REPUBLIC OF - - 00-26-E7 (hex) Shanghai ONLAN Communication Tech. Co., Ltd. - 0026E7 (base 16) Shanghai ONLAN Communication Tech. Co., Ltd. - 3F, 6C, No. 1658, Gumei Road, Xuhui District - Shanghai 200233 - CHINA - - 00-26-E8 (hex) Murata Manufacturing Co., Ltd. - 0026E8 (base 16) Murata Manufacturing Co., Ltd. - 2288, Oaza-Ohshinohara, Yasu-cho, - Yasu-gun Shiga 520-2393 - JAPAN - - 00-26-E9 (hex) SP Corp - 0026E9 (base 16) SP Corp - Guro 3-dong ,Guro-gu - Ace Techno 8 Cha 1305 - Seoul 152-780 - KOREA, REPUBLIC OF - - 00-26-EA (hex) Cheerchip Electronic Technology (ShangHai) Co., Ltd. - 0026EA (base 16) Cheerchip Electronic Technology (ShangHai) Co., Ltd. - ROOM 1202, NO. 51, 7 Area, NO. 1467 CAOBAO ROAD; - MINHANG AREA - SHANGHAI 201101 - CHINA - - 00-26-EB (hex) Advanced Spectrum Technology Co., Ltd. - 0026EB (base 16) Advanced Spectrum Technology Co., Ltd. - 1F., No.67 Jhongjheng Rd. - Sinjhuang Taiwan 242 - TAIWAN, PROVINCE OF CHINA - - 00-26-EC (hex) Legrand Home Systems, Inc - 0026EC (base 16) Legrand Home Systems, Inc - 301 Fulling Mill Rd - Suite G - Middletown PA 17057 - UNITED STATES - - 00-26-ED (hex) zte corporation - 0026ED (base 16) zte corporation - 12/F zte plaza,keji Road South,HI-Tech Industrial Park,Nanshan District - shenzhen guangdong 518057 - CHINA - - 00-26-EE (hex) TKM GmbH - 0026EE (base 16) TKM GmbH - Schlossstraße 123 - Mönchengladbach NRW 41238 - GERMANY - - 00-26-EF (hex) Technology Advancement Group, Inc. - 0026EF (base 16) Technology Advancement Group, Inc. - 22355 Tag Way - Dulles VA 20166-9310 - UNITED STATES - - 00-26-F0 (hex) cTrixs International GmbH. - 0026F0 (base 16) cTrixs International GmbH. - Lieferinger Hauptstr. 140 - Salzburg Salzburg 5020 - AUSTRIA - - 00-26-F1 (hex) ProCurve Networking by HP - 0026F1 (base 16) ProCurve Networking by HP - 8000 Foothills Blvd. - Roseville California 95747 - UNITED STATES - - 00-26-F2 (hex) Netgear - 0026F2 (base 16) Netgear - 350 East Plumeria Drive - San Jose California 95134 - UNITED STATES - - 00-26-F3 (hex) SMC Networks - 0026F3 (base 16) SMC Networks - 20 Mason - Irvine CA 92618 - UNITED STATES - - 00-26-F4 (hex) Nesslab - 0026F4 (base 16) Nesslab - 489-2 Maetan 3-dong, Yeong Tong-gu - Suwon-si Gyeonggi-do 443-803 - KOREA, REPUBLIC OF - - 00-26-F5 (hex) XRPLUS Inc. - 0026F5 (base 16) XRPLUS Inc. - #805 Ace Techno Tower 2nd 197-17 - Guro3Dong, Guro-Gu - Seoul 152-766 - KOREA, REPUBLIC OF - - 00-26-F6 (hex) Military Communication Institute - 0026F6 (base 16) Military Communication Institute - ul. Warszawska 22A - Zegrze 05-130 - POLAND - - 00-26-F7 (hex) Infosys Technologies Ltd. - 0026F7 (base 16) Infosys Technologies Ltd. - 44, Electronics City - Hosur Road - Bangalore Karnakata 560100 - INDIA - - 00-26-F8 (hex) Golden Highway Industry Development Co., Ltd. - 0026F8 (base 16) Golden Highway Industry Development Co., Ltd. - Floor 7, Block 8, Vision Shenzhen Business Park, No.9 Gaoxin 9th South Road - Shenzhen Hi-tech Industrial Park, Nanshan District - Shenzhen City Guangdong Province 518057 - CHINA - - 00-26-F9 (hex) S.E.M. srl - 0026F9 (base 16) S.E.M. srl - via Lecco, 61 - Vimercate Monza Brianza 20059 - ITALY - - 00-26-FA (hex) BandRich Inc. - 0026FA (base 16) BandRich Inc. - 7F., No.188, Baociao Road - Sindian City Taipei 23145 - TAIWAN, PROVINCE OF CHINA - - 00-26-FB (hex) AirDio Wireless, Inc. - 0026FB (base 16) AirDio Wireless, Inc. - 13-5, No. 79, Sec. 1, Hsin Tai Wu Road - Hsichih City, Taipei County Taiwan 22101 - TAIWAN, PROVINCE OF CHINA - - 00-26-FC (hex) AcSiP Technology Corp. - 0026FC (base 16) AcSiP Technology Corp. - 3F., No.22, Dalin Rd., - Taoyuan City, Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 00-26-FD (hex) Interactive Intelligence - 0026FD (base 16) Interactive Intelligence - 7601 Interactive Way - Indianapolis IN 46278 - UNITED STATES - - 00-26-FE (hex) MKD Technology Inc. - 0026FE (base 16) MKD Technology Inc. - R.B8, No.1 Lising 1st Rd., - Hsinchu 30078 - TAIWAN, PROVINCE OF CHINA - - 00-26-FF (hex) Research In Motion - 0026FF (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 00-27-00 (hex) Shenzhen Siglent Technology Co., Ltd. - 002700 (base 16) Shenzhen Siglent Technology Co., Ltd. - BUILDING A8,TANGLANG INDUSTRIAL ZONE,XILI,NANSHAN - Shenzhen Guangdong 518000 - CHINA - - 00-27-01 (hex) INCOstartec GmbH - 002701 (base 16) INCOstartec GmbH - Rheinstraße 17 - Teltow Germany 14513 - GERMANY - - 00-27-02 (hex) SolarEdge Technologies - 002702 (base 16) SolarEdge Technologies - 1 Abba Eban St. - POB 12766 - Herzelia 46725 - ISRAEL - - 00-27-03 (hex) Testech Electronics Pte Ltd - 002703 (base 16) Testech Electronics Pte Ltd - Block 118, #05-110, - Aljunied Ave 2 - Singapore 380118 - SINGAPORE - - 00-27-04 (hex) Accelerated Concepts, Inc - 002704 (base 16) Accelerated Concepts, Inc - 1208 E Kennedy Blvd - Suite 226 - Tampa FL 33602 - UNITED STATES - - 00-27-05 (hex) Sectronic - 002705 (base 16) Sectronic - Z.I. Les Saulniers - Sainte-Maure de Touraine 37800 - FRANCE - - 00-27-06 (hex) YOISYS - 002706 (base 16) YOISYS - 309-52 SUNGSU-2GA, 1DONG, SUNGDONG-GU - SEOUL 133-827 - KOREA, REPUBLIC OF - - 00-27-07 (hex) Lift Complex DS, JSC - 002707 (base 16) Lift Complex DS, JSC - mikrorayon Gorsky, 6 - Novosibirsk 630073 - RUSSIAN FEDERATION - - 00-27-08 (hex) Nordiag ASA - 002708 (base 16) Nordiag ASA - Frysjaveien 40 - Oslo 0884 - NORWAY - - 00-27-09 (hex) Nintendo Co., Ltd. - 002709 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 00-27-0A (hex) IEE S.A. - 00270A (base 16) IEE S.A. - ZAE Weiergewan - 11, rue Edmond Reuter - Contern L-5326 - LUXEMBOURG - - 00-27-0B (hex) Adura Technologies - 00270B (base 16) Adura Technologies - 28 Second Street - 4th Floor - San Francisco CA 94105 - UNITED STATES - - 00-27-0C (hex) CISCO SYSTEMS, INC. - 00270C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-27-0D (hex) CISCO SYSTEMS, INC. - 00270D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-27-0E (hex) Intel Corporate - 00270E (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-27-0F (hex) Envisionnovation Inc - 00270F (base 16) Envisionnovation Inc - 4 Wareham Drive - Mississauga Ontario L5M 1B6 - CANADA - - 00-27-10 (hex) Intel Corporate - 002710 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-27-11 (hex) LanPro Inc - 002711 (base 16) LanPro Inc - 1880 NW 93Av - Miami Florida 33172 - UNITED STATES - - 00-27-12 (hex) MaxVision LLC - 002712 (base 16) MaxVision LLC - 495 Production Ave - Madison AL 35758 - UNITED STATES - - 00-27-13 (hex) Universal Global Scientific Industrial Co., Ltd. - 002713 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351, SEC.1, TAIPING RD. - TSAOTUEN - NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 00-27-14 (hex) Grainmustards, Co,ltd. - 002714 (base 16) Grainmustards, Co,ltd. - HEIWA MK Bldg,2-48-4,Nihonbashi-Hama-cho - Chuo-ku, - Tokyo 103-0007 - JAPAN - - 00-27-15 (hex) Rebound Telecom. Co., Ltd - 002715 (base 16) Rebound Telecom. Co., Ltd - 12F,Building No.82,No.1198,North Qinzhou Rd, - Shanghai 200233 - CHINA - - 00-27-16 (hex) Adachi-Syokai Co., Ltd. - 002716 (base 16) Adachi-Syokai Co., Ltd. - 228-2 Hazama Maki - Fukuchiyama-shi Kyoto 620-0913 - JAPAN - - 00-27-17 (hex) CE Digital(Zhenjiang)Co.,Ltd - 002717 (base 16) CE Digital(Zhenjiang)Co.,Ltd - Wei 3 Road, Dingmao, Eco.Dev.Zone, - Jiangsu - Zhenjiang 212009 - CHINA - - 00-27-18 (hex) Suzhou NEW SEAUNION Video Technology Co.,Ltd - 002718 (base 16) Suzhou NEW SEAUNION Video Technology Co.,Ltd - 383 Jingmao Road, Industry Park - Suzhou Jiangsu 215021 - CHINA - - 00-27-19 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 002719 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 7, Second Part, Honghualing Industrial Zone, Xili town - Nanshan - ShenZhen GuangDong 518057 - CHINA - - 00-27-1A (hex) Geenovo Technology Ltd. - 00271A (base 16) Geenovo Technology Ltd. - Unit 402, 4/F., Tower I,SHUI QING MU HUA YUAN, - Haidian District - Beijing 100080 - CHINA - - 00-27-1B (hex) Alec Sicherheitssysteme GmbH - 00271B (base 16) Alec Sicherheitssysteme GmbH - Friedrich-Hoelscher-Strasse 367 - Dortmund 44328 - GERMANY - - 00-27-1C (hex) MERCURY CORPORATION - 00271C (base 16) MERCURY CORPORATION - 531-6, Gajwadong, - Seogu - Incheon 404-250 - KOREA, REPUBLIC OF - - 00-27-1D (hex) Comba Telecom Systems (China) Ltd. - 00271D (base 16) Comba Telecom Systems (China) Ltd. - 10 Shenzhou Road - Guangzhou Guangdong 510663 - CHINA - - 00-27-1E (hex) Xagyl Communications - 00271E (base 16) Xagyl Communications - 1667 Marronier Crt - Cumberland Ontario K4C 1C2 - CANADA - - 00-27-1F (hex) MIPRO Electronics Co., Ltd - 00271F (base 16) MIPRO Electronics Co., Ltd - 814,Peikang Road - Chiayi 60096 - TAIWAN, PROVINCE OF CHINA - - 00-27-20 (hex) NEW-SOL COM - 002720 (base 16) NEW-SOL COM - Bucheon Tecnopark 403-602 - Yakdae-dong Wonmi-gu - Bucheon city Kyoungki-do 420-734 - KOREA, REPUBLIC OF - - 00-27-21 (hex) Shenzhen Baoan Fenda Industrial Co., Ltd - 002721 (base 16) Shenzhen Baoan Fenda Industrial Co., Ltd - Fenda Hi-Tech Park - Zhoushi Road, Shiyan - Baoan Shenzhen 518108 - CHINA - - 00-27-22 (hex) Ubiquiti Networks - 002722 (base 16) Ubiquiti Networks - 91 E. Tasman Dr. - San Jose CA 95134 - UNITED STATES - - 00-27-F8 (hex) Brocade Communications Systems, Inc. - 0027F8 (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-2A-6A (hex) CISCO SYSTEMS, INC. - 002A6A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-2A-AF (hex) LARsys-Automation GmbH - 002AAF (base 16) LARsys-Automation GmbH - Sinzinger Str. 3 - Hochburg-Ach 5122 - AUSTRIA - - 00-2D-76 (hex) TITECH GmbH - 002D76 (base 16) TITECH GmbH - Otto-Hahn-Str. 6 - Muelheim-Kaerlich 56218 - GERMANY - - 00-30-00 (hex) ALLWELL TECHNOLOGY CORP. - 003000 (base 16) ALLWELL TECHNOLOGY CORP. - 4F, #15, LANE3, SEC.2 - CHIEN KWO N. ROAD TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-01 (hex) SMP - 003001 (base 16) SMP - 22, RUE DES COSMONAUTES - 31400 TOULOUSE - FRANCE - - 00-30-02 (hex) Expand Networks - 003002 (base 16) Expand Networks - Atidim Tech Park, Bldg. 4 - P.O. Box 58142 - Tel-Aviv 61580 - ISRAEL - - 00-30-03 (hex) Phasys Ltd. - 003003 (base 16) Phasys Ltd. - #100-9404 41st Avenue - Edmonton Alberta T6X 1R2 - CANADA - - 00-30-04 (hex) LEADTEK RESEARCH INC. - 003004 (base 16) LEADTEK RESEARCH INC. - 18F, No.166, Chien-Yi Road - Chung-Ho Taipei, - Hsien - TAIWAN, PROVINCE OF CHINA - - 00-30-05 (hex) Fujitsu Siemens Computers - 003005 (base 16) Fujitsu Siemens Computers - Buergermeister ulrich 100 - 86199 Augsburg - GERMANY - - 00-30-06 (hex) SUPERPOWER COMPUTER - 003006 (base 16) SUPERPOWER COMPUTER - ELECTRONICS CO., LTD. - NO. 20 WU-GONG 6TH ROAD WU-KU INDUSTR'L - Taipei 248 - TAIWAN, PROVINCE OF CHINA - - 00-30-07 (hex) OPTI, INC. - 003007 (base 16) OPTI, INC. - 1440 MCCARTHY BLVD. - MILPITAS CA 95035 - UNITED STATES - - 00-30-08 (hex) AVIO DIGITAL, INC. - 003008 (base 16) AVIO DIGITAL, INC. - 957 INDUSTRIAL ROAD - SAN CARLOS CA 94070 - UNITED STATES - - 00-30-09 (hex) Tachion Networks, Inc. - 003009 (base 16) Tachion Networks, Inc. - 2 Meridian Road - Eatontown NJ 07724 - UNITED STATES - - 00-30-0A (hex) AZTECH Electronics Pte Ltd - 00300A (base 16) AZTECH Electronics Pte Ltd - 31 UBI ROAD 1 - AZTECH BUILDING - 408694 - SINGAPORE - - 00-30-0B (hex) mPHASE Technologies, Inc. - 00300B (base 16) mPHASE Technologies, Inc. - 250 14th Street - GCATT Bldg. - Room #248A - Atlanta GA 30318 - UNITED STATES - - 00-30-0C (hex) CONGRUENCY, LTD. - 00300C (base 16) CONGRUENCY, LTD. - 23 HASIVIM STREET - POB 7813 - PETAH-TIKVA 49170 - ISRAEL - - 00-30-0D (hex) MMC Technology, Inc. - 00300D (base 16) MMC Technology, Inc. - #1502, Seoul Venture Town, Aju Bldg - 679-5, Yeoksam-Dong, Kangnam-Gu - Seoul 135-080 - KOREA, REPUBLIC OF - - 00-30-0E (hex) Klotz Digital AG - 00300E (base 16) Klotz Digital AG - Hans-Stiessbergerstraße 2A - D-85540 Haar - GERMANY - - 00-30-0F (hex) IMT - Information Management T - 00300F (base 16) IMT - Information Management T - Gewerbestrasse 8 - CH-9470 Buchs - SWITZERLAND - - 00-30-10 (hex) VISIONETICS INTERNATIONAL - 003010 (base 16) VISIONETICS INTERNATIONAL - 3F, NO. 3, PROSPERITY ROAD 1 - SCIENCE-BASED INDUSTRIAL PARK HSINCHU - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-11 (hex) HMS Industrial Networks - 003011 (base 16) HMS Industrial Networks - P O Box 4126 - HALMSTAD - SE-300 04 - SWEDEN - - 00-30-12 (hex) DIGITAL ENGINEERING LTD. - 003012 (base 16) DIGITAL ENGINEERING LTD. - 2 TRENCH ROAD, MALLUSK - BELFAST BT36 4TY - NORTHERN - IRELAND - - 00-30-13 (hex) NEC Corporation - 003013 (base 16) NEC Corporation - 1-10 Nisshincho, Fuchu - Tokyo 183-8501 - JAPAN - - 00-30-14 (hex) DIVIO, INC. - 003014 (base 16) DIVIO, INC. - 997 E. ARQUES AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-30-15 (hex) CP CLARE CORP. - 003015 (base 16) CP CLARE CORP. - 78 CHERRY HILL DRIVE - BEVERLY MA 01915 - UNITED STATES - - 00-30-16 (hex) ISHIDA CO., LTD. - 003016 (base 16) ISHIDA CO., LTD. - 959-1 SHIMOMAGARI - RITTO SHIGA 520-3026 - JAPAN - - 00-30-17 (hex) BlueArc UK Ltd - 003017 (base 16) BlueArc UK Ltd - Queensgate House - Cookham Road - Bracknell RG12 1RB - UNITED KINGDOM - - 00-30-18 (hex) Jetway Information Co., Ltd. - 003018 (base 16) Jetway Information Co., Ltd. - 4F, No. 168, LI THE ST. - Chung Ho City 235 Taipei - TAIWAN, PROVINCE OF CHINA - - 00-30-19 (hex) CISCO SYSTEMS, INC. - 003019 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-1A (hex) SMARTBRIDGES PTE. LTD. - 00301A (base 16) SMARTBRIDGES PTE. LTD. - 745 Toa Payoh Lorong 5 - #04-01 - 319455 - SINGAPORE - - 00-30-1B (hex) SHUTTLE, INC. - 00301B (base 16) SHUTTLE, INC. - 5F, No. 34, Lane 60 - Wen-Hu St., Nei-Hu Dist., - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-30-1C (hex) ALTVATER AIRDATA SYSTEMS - 00301C (base 16) ALTVATER AIRDATA SYSTEMS - GMBH & CO. KG - RIEMENSTRASSE 30 74906 BAD RAPPENAU - GERMANY - - 00-30-1D (hex) SKYSTREAM, INC. - 00301D (base 16) SKYSTREAM, INC. - 455 DeGuigne Drive - Sunnyvale CA 94086-3835 - UNITED STATES - - 00-30-1E (hex) 3COM Europe Ltd. - 00301E (base 16) 3COM Europe Ltd. - 3COM Centre - Boundary Way, Hemel Hempstead - Herts. HP2 7YU - UNITED KINGDOM - - 00-30-1F (hex) OPTICAL NETWORKS, INC. - 00301F (base 16) OPTICAL NETWORKS, INC. - 166 BAYPOINTE PARKWAY - SAN JOSE CA 95134 - UNITED STATES - - 00-30-20 (hex) TSI, Inc.. - 003020 (base 16) TSI, Inc.. - 500 Cardigan Road - Shoreview MN 55126 - UNITED STATES - - 00-30-21 (hex) HSING TECH. ENTERPRISE CO.,LTD - 003021 (base 16) HSING TECH. ENTERPRISE CO.,LTD - 2F, NO. 22, ALLLEY 38, LANE 91 - SEC. 1, NEI HU ROAD - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-30-22 (hex) Fong Kai Industrial Co., Ltd. - 003022 (base 16) Fong Kai Industrial Co., Ltd. - 4F-3, No. 13, Wu Chuan 1st Road - Hsin Chuang City, Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-30-23 (hex) COGENT COMPUTER SYSTEMS, INC. - 003023 (base 16) COGENT COMPUTER SYSTEMS, INC. - 10 RIVER ROAD - STE. #205 - UXBRIDGE MA 01569 - UNITED STATES - - 00-30-24 (hex) CISCO SYSTEMS, INC. - 003024 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-25 (hex) CHECKOUT COMPUTER SYSTEMS, LTD - 003025 (base 16) CHECKOUT COMPUTER SYSTEMS, LTD - TOWNSEND FARM ROAD - HOUGHTON REGIS, DUNSTABLE BEDFORDSHIRE - UNITED KINGDOM - UNITED KINGDOM - - 00-30-26 (hex) HeiTel Digital Video GmbH - 003026 (base 16) HeiTel Digital Video GmbH - Stuthagen 25 - 24113 Molfsee - GERMANY - - 00-30-27 (hex) KERBANGO, INC. - 003027 (base 16) KERBANGO, INC. - 21771 STEVENS CREEK BLVD. #100 - CUPERTINO CA 95014 - UNITED STATES - - 00-30-28 (hex) FASE Saldatura srl - 003028 (base 16) FASE Saldatura srl - V.R. Bernardi 5 - 10042 Stupiniqi-Nichelino - TORINO - ITALY - - 00-30-29 (hex) OPICOM - 003029 (base 16) OPICOM - ROOM #302, STYLE FACTORY 151 - YATAB-DONG, BUNDANG-GU SUNGNAM-SI, KYUNG - KOREA - KOREA, REPUBLIC OF - - 00-30-2A (hex) SOUTHERN INFORMATION - 00302A (base 16) SOUTHERN INFORMATION - SYSTEM, INC. - NO.8, R&D RD. IV SCIENCE-BASED INDUSTRIA - HSINCHU TAIWAN, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-2B (hex) INALP NETWORKS, INC. - 00302B (base 16) INALP NETWORKS, INC. - MERIEDWEG 7 - CH-3172 NIEDERWANGEN - SWITZERLAND - - 00-30-2C (hex) SYLANTRO SYSTEMS CORPORATION - 00302C (base 16) SYLANTRO SYSTEMS CORPORATION - 1686 DELL AVENUE - CAMPBELL CA 95008 - UNITED STATES - - 00-30-2D (hex) QUANTUM BRIDGE COMMUNICATIONS - 00302D (base 16) QUANTUM BRIDGE COMMUNICATIONS - ONE HIGH STREET - NORTH ANDOVER MA 01845 - UNITED STATES - - 00-30-2E (hex) Hoft & Wessel AG - 00302E (base 16) Hoft & Wessel AG - Rotenburger Strasse 20 - 30659 Hannover - GERMANY - - 00-30-2F (hex) GE Aviation System - 00302F (base 16) GE Aviation System - 3290 Patterson Ave., S.E. - Grand Rapids MI 49512 - UNITED STATES - - 00-30-30 (hex) HARMONIX CORPORATION - 003030 (base 16) HARMONIX CORPORATION - 1755 OSGOOD STREET - NORTH ANDOVER MA 01845 - UNITED STATES - - 00-30-31 (hex) LIGHTWAVE COMMUNICATIONS, INC. - 003031 (base 16) LIGHTWAVE COMMUNICATIONS, INC. - 261 PEPE'S FARM ROAD - MILFORD CT 06460 - UNITED STATES - - 00-30-32 (hex) MagicRam, Inc. - 003032 (base 16) MagicRam, Inc. - 1850 Beverly Blvd. - Los Angeles CA 90057 - UNITED STATES - - 00-30-33 (hex) ORIENT TELECOM CO., LTD. - 003033 (base 16) ORIENT TELECOM CO., LTD. - MISUNG BULDING 115-7 - NONHYUN-DONG, KANGMAN-KU SEOUL - KOREA - KOREA, REPUBLIC OF - - 00-30-34 (hex) SET ENGINEERING - 003034 (base 16) SET ENGINEERING - 15750 VINEYARD BLVD. STE. #100 - MORGAN HILL CA 95037 - UNITED STATES - - 00-30-35 (hex) Corning Incorporated - 003035 (base 16) Corning Incorporated - Data Center - M/S - SP-ZV-01 - Corning NY 14831 - UNITED STATES - - 00-30-36 (hex) RMP ELEKTRONIKSYSTEME GMBH - 003036 (base 16) RMP ELEKTRONIKSYSTEME GMBH - HANNS-MARTIN-SCHLE'R-STR.12-14 - D-47877 WILLICH-MUNCHHEIDE - GERMANY - - 00-30-37 (hex) Packard Bell Nec Services - 003037 (base 16) Packard Bell Nec Services - 299 avenue Patton, BP 645 - 49006 Angers Cedex 01 - FRANCE - - 00-30-38 (hex) XCP, INC. - 003038 (base 16) XCP, INC. - 40 ELM STREET - DRYDEN NY 13053 - UNITED STATES - - 00-30-39 (hex) SOFTBOOK PRESS - 003039 (base 16) SOFTBOOK PRESS - 7745 HERSCHEL AVENUE - LA JOLLA CA 92037 - UNITED STATES - - 00-30-3A (hex) MAATEL - 00303A (base 16) MAATEL - 495 RUE DE POMMARIN - 38360 VOREPPE - FRANCE - - 00-30-3B (hex) PowerCom Technology - 00303B (base 16) PowerCom Technology - 2F, No. 34, Industry E. Road IV - Hsinchu Science-based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 00-30-3C (hex) ONNTO CORP. - 00303C (base 16) ONNTO CORP. - 12F-2, NO. 161 - SUNG TEH RD., TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-3D (hex) IVA CORPORATION - 00303D (base 16) IVA CORPORATION - 142 NORTH RD STE R - SUDBURY MA 01776 - UNITED STATES - - 00-30-3E (hex) Radcom Ltd. - 00303E (base 16) Radcom Ltd. - 12 Hanechoshet Street - Tel-Aviv 69710 - ISRAEL - - 00-30-3F (hex) TurboComm Tech Inc. - 00303F (base 16) TurboComm Tech Inc. - 4F-2, No 171, Sung-Tch Road - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-30-40 (hex) CISCO SYSTEMS, INC. - 003040 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-41 (hex) SAEJIN T & M CO., LTD. - 003041 (base 16) SAEJIN T & M CO., LTD. - 2ND FL., SAEJIN BLDG. 689 - ILWON-DONG, KANGNAM-GU, SEOUL - 135-230 KOREA - KOREA, REPUBLIC OF - - 00-30-42 (hex) DeTeWe-Deutsche Telephonwerke - 003042 (base 16) DeTeWe-Deutsche Telephonwerke - Zeughofstrasse 1 - D-10997 Berlin - GERMANY - - 00-30-43 (hex) IDREAM TECHNOLOGIES, PTE. LTD. - 003043 (base 16) IDREAM TECHNOLOGIES, PTE. LTD. - 54 KALLANG BAHRU, #02-14 - SINGAPORE 339336 - SINGAPORE - - 00-30-44 (hex) CradlePoint, Inc - 003044 (base 16) CradlePoint, Inc - 805 W. Franklin St. - Boise ID 83702 - UNITED STATES - - 00-30-45 (hex) Village Networks, Inc. (VNI) - 003045 (base 16) Village Networks, Inc. (VNI) - 100 Village Court - Ste. #301 - Hazlet NJ 07730 - UNITED STATES - - 00-30-46 (hex) Controlled Electronic Manageme - 003046 (base 16) Controlled Electronic Manageme - Unit 4 Ravenhill Business Park - Ravenhill Road - Belfast - IRELAND - - 00-30-47 (hex) NISSEI ELECTRIC CO., LTD. - 003047 (base 16) NISSEI ELECTRIC CO., LTD. - 32 MIYAWAKE, SHIMONOISHIKI-CHO - NAKAGAWA-KU, NAGOYA 454-0945 - JAPAN - - 00-30-48 (hex) Supermicro Computer, Inc. - 003048 (base 16) Supermicro Computer, Inc. - 2051 Junction Avenue - San Jose CA 95131 - UNITED STATES - - 00-30-49 (hex) BRYANT TECHNOLOGY, LTD. - 003049 (base 16) BRYANT TECHNOLOGY, LTD. - P.O. BOX 69557 - BRYANSTON, 2021 - SOUTH AFRICA - SOUTH AFRICA - - 00-30-4A (hex) Fraunhofer IPMS - 00304A (base 16) Fraunhofer IPMS - Maria-Reiche-Strasse 2 - Dresden 01109 - GERMANY - - 00-30-4B (hex) ORBACOM SYSTEMS, INC. - 00304B (base 16) ORBACOM SYSTEMS, INC. - 1704 TAYLORS LANE - CINNAMINSON NJ 08077 - UNITED STATES - - 00-30-4C (hex) APPIAN COMMUNICATIONS, INC. - 00304C (base 16) APPIAN COMMUNICATIONS, INC. - 80 CENTRAL STREET - BOXBOROUGH MA 01719 - UNITED STATES - - 00-30-4D (hex) ESI - 00304D (base 16) ESI - 3701 E. Plano Parkway - Plano TX 75074 - UNITED STATES - - 00-30-4E (hex) BUSTEC PRODUCTION LTD. - 00304E (base 16) BUSTEC PRODUCTION LTD. - WORLD AVIATION PARK - Shannon County Clare - IRELAND - - 00-30-4F (hex) PLANET Technology Corporation - 00304F (base 16) PLANET Technology Corporation - 11F, No. 96, Min-Chuan Road - Hsin-Tien Dist, New Taipei City - TAIWAN, PROVINCE OF CHINA - - 00-30-50 (hex) Versa Technology - 003050 (base 16) Versa Technology - 4430 E. Miraloma Ave., - Ste. - Anaheim CA 92807 - UNITED STATES - - 00-30-51 (hex) ORBIT AVIONIC & COMMUNICATION - 003051 (base 16) ORBIT AVIONIC & COMMUNICATION - SYSTEMS, LTD. - P.O. BOX 3171 INDUSTRIAL ZONE, NETANYA 4 - ISRAEL - - 00-30-52 (hex) ELASTIC NETWORKS - 003052 (base 16) ELASTIC NETWORKS - 6120 WINDWARD PARKWAY -STE#100 - ALPHARETTA GA 30005 - UNITED STATES - - 00-30-53 (hex) Basler AG - 003053 (base 16) Basler AG - An Der Strusbek 60-62 - 22926 Ahrensburg - GERMANY - - 00-30-54 (hex) CASTLENET TECHNOLOGY, INC. - 003054 (base 16) CASTLENET TECHNOLOGY, INC. - NO. 130 WU-KUNG RD., - WU-KU HSIANG TAIPEI HSIEN - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-55 (hex) Renesas Technology America, Inc. - 003055 (base 16) Renesas Technology America, Inc. - 450 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-30-56 (hex) Beck IPC GmbH - 003056 (base 16) Beck IPC GmbH - Grüninger Weg 24 - D-35415 Pohlheim - GERMANY - - 00-30-57 (hex) QTelNet, Inc. - 003057 (base 16) QTelNet, Inc. - 400 - 3115 12th Street NE - Calgary Alberta T2E 7J2 - CANADA - - 00-30-58 (hex) API MOTION - 003058 (base 16) API MOTION - 45 HAZELWOOD DRIVE - AMHERST NY 14228 - UNITED STATES - - 00-30-59 (hex) KONTRON COMPACT COMPUTERS AG - 003059 (base 16) KONTRON COMPACT COMPUTERS AG - Nordstrasse 11/F - LUTERBACH 4542 - SWITZERLAND - - 00-30-5A (hex) TELGEN CORPORATION - 00305A (base 16) TELGEN CORPORATION - 3101 SOVEREIGN DR. - STE. - LANSING MI 48911 - UNITED STATES - - 00-30-5B (hex) Toko Inc. - 00305B (base 16) Toko Inc. - 18 COMIGAYA, TSURUGASHIMA-SHI - SAITAMA-KEN - JAPAN 350-2281 - JAPAN - - 00-30-5C (hex) SMAR Laboratories Corp. - 00305C (base 16) SMAR Laboratories Corp. - 10960 Millridge North - Ste. #107 - Houston TX 77070 - UNITED STATES - - 00-30-5D (hex) DIGITRA SYSTEMS, INC. - 00305D (base 16) DIGITRA SYSTEMS, INC. - 8-61, GAWOL-DONG - YONGSAN-KU SEOUL - KOREA 140-150 - KOREA, REPUBLIC OF - - 00-30-5E (hex) Abelko Innovation - 00305E (base 16) Abelko Innovation - Box 808 - Lulea 97125 - SWEDEN - - 00-30-5F (hex) Hasselblad - 00305F (base 16) Hasselblad - Hejrevej 30 - Copenhagen NV DK-2400 - DENMARK - - 00-30-60 (hex) Powerfile, Inc. - 003060 (base 16) Powerfile, Inc. - 3350 Thomas Road - Santa Clara CA 95054-2062 - UNITED STATES - - 00-30-61 (hex) MobyTEL - 003061 (base 16) MobyTEL - 4301 Connecticut Ave. NW - Ste. #454 - Washington DC 20008 - UNITED STATES - - 00-30-62 (hex) IP Video Networks Inc - 003062 (base 16) IP Video Networks Inc - 6650 Lusk Blvd - Suite B100 - SAN DIEGO CA 92121 - UNITED STATES - - 00-30-63 (hex) SANTERA SYSTEMS, INC. - 003063 (base 16) SANTERA SYSTEMS, INC. - 2901 SUMMIT AVENUE - STE. #100 - PLANO TX 75074 - UNITED STATES - - 00-30-64 (hex) ADLINK TECHNOLOGY, INC. - 003064 (base 16) ADLINK TECHNOLOGY, INC. - 9F, NO. 166, JIEN-YI R.D. - CHUNG-HO CITY TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-30-65 (hex) Apple - 003065 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-30-66 (hex) RFM - 003066 (base 16) RFM - 3079 Premiere Pkwy - Suite 140 - Duluth GA 30097 - UNITED STATES - - 00-30-67 (hex) BIOSTAR MICROTECH INT'L CORP. - 003067 (base 16) BIOSTAR MICROTECH INT'L CORP. - 2FL. NO. 108-2 MIN CHUAN ROAD - HSIN TIEN CITY, TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-30-68 (hex) CYBERNETICS TECH. CO., LTD. - 003068 (base 16) CYBERNETICS TECH. CO., LTD. - DAITOH BLDG. 4F 3-32-1 - TAKADA, TOSHIMA-KU, TOKYO - JAPAN 171-0033 - JAPAN - - 00-30-69 (hex) IMPACCT TECHNOLOGY CORP. - 003069 (base 16) IMPACCT TECHNOLOGY CORP. - 2F, NO. 12, R&D RD. II - SCIENCE-BASED INDUSTRIAL PARK HSIN-CHU - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-6A (hex) PENTA MEDIA CO., LTD. - 00306A (base 16) PENTA MEDIA CO., LTD. - E-504 Bundang Technopark,151 - Yatop-dong Bundang-gu - Seongnam Gyeonggi-do - KOREA, REPUBLIC OF - - 00-30-6B (hex) CMOS SYSTEMS, INC. - 00306B (base 16) CMOS SYSTEMS, INC. - 23440 HAWTHORNE BLVD-STE #290 - TORRANCE CA 90505 - UNITED STATES - - 00-30-6C (hex) Hitex Holding GmbH - 00306C (base 16) Hitex Holding GmbH - Greschbachstraße 12 - 76229 Karlsruhe - GERMANY - - 00-30-6D (hex) LUCENT TECHNOLOGIES - 00306D (base 16) LUCENT TECHNOLOGIES - 300 BAKER AVENUE - STE. #100 - CONCORD MA 01742-2168 - UNITED STATES - - 00-30-6E (hex) HEWLETT PACKARD - 00306E (base 16) HEWLETT PACKARD - 11000 WOLFE ROAD - CUPERTINO CA 95014 - UNITED STATES - - 00-30-6F (hex) SEYEON TECH. CO., LTD. - 00306F (base 16) SEYEON TECH. CO., LTD. - NAMCHEON BLDG. 6F, - DAECHI-DONG, 957-013 KANGNAM-GU, SEOUL - KOREA 135-280 - KOREA, REPUBLIC OF - - 00-30-70 (hex) 1Net Corporation - 003070 (base 16) 1Net Corporation - 347 Elizabeth Avenue - Ste. #100 - Somerset NJ 08873 - UNITED STATES - - 00-30-71 (hex) CISCO SYSTEMS, INC. - 003071 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-72 (hex) Intellibyte Inc. - 003072 (base 16) Intellibyte Inc. - Canada Trust Tower - BCE Place - 161 Bay St. 27th Floor, - Toronto Ontario M5J 2S1 - CANADA - - 00-30-73 (hex) International Microsystems, In - 003073 (base 16) International Microsystems, In - 521 Valley Way - Milpitas CA 95035 - UNITED STATES - - 00-30-74 (hex) EQUIINET LTD. - 003074 (base 16) EQUIINET LTD. - EDISON HOUSE - EDISON ROAD - SWINDON, SN3 5JA - UNITED KINGDOM - - 00-30-75 (hex) ADTECH - 003075 (base 16) ADTECH - RUE DU VAL ST LAMBERT 191 / i - SERAING 4100 - BELGIUM - - 00-30-76 (hex) Akamba Corporation - 003076 (base 16) Akamba Corporation - 15595 Los Gatos Blvd. - Los Gatos CA 95032 - UNITED STATES - - 00-30-77 (hex) ONPREM NETWORKS - 003077 (base 16) ONPREM NETWORKS - 42501 ALBRAE STREET - FREMONT CA 94538 - UNITED STATES - - 00-30-78 (hex) CISCO SYSTEMS, INC. - 003078 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-79 (hex) CQOS, INC. - 003079 (base 16) CQOS, INC. - 25 MAUCHLY - STE. #329 - IRVINE CA 92618 - UNITED STATES - - 00-30-7A (hex) Advanced Technology & Systems - 00307A (base 16) Advanced Technology & Systems - Yokohama Business Park East Tower 9F, - 134 Goudo-cho, Hodogaya-ku, Yokohama, Ka - 240-0005 - JAPAN - - 00-30-7B (hex) CISCO SYSTEMS, INC. - 00307B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-7C (hex) ADID SA - 00307C (base 16) ADID SA - 70 RU ANATOLE FRANCE - 92 300 LEVALLOIS-PERRET CEDEX - FRANCE - - 00-30-7D (hex) GRE AMERICA, INC. - 00307D (base 16) GRE AMERICA, INC. - 425 HARBOR BLVD. - BELMONT CA 94002 - UNITED STATES - - 00-30-7E (hex) Redflex Communication Systems - 00307E (base 16) Redflex Communication Systems - 11-29 Eastern Road - South Melbourne Victoria 3205 - AUSTRALIA - - 00-30-7F (hex) IRLAN LTD. - 00307F (base 16) IRLAN LTD. - 1 HATAMAR STREET - P.O. BOX 288 YOKNEAM 20692 - ISRAEL - - 00-30-80 (hex) CISCO SYSTEMS, INC. - 003080 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-81 (hex) ALTOS C&C - 003081 (base 16) ALTOS C&C - 150-010 RM. 1012, 44-1 - DAE YOUNG B/D, YOVIDO-DONG YOUNGCHUNGPO- - KOREA - KOREA, REPUBLIC OF - - 00-30-82 (hex) TAIHAN ELECTRIC WIRE CO., LTD. - 003082 (base 16) TAIHAN ELECTRIC WIRE CO., LTD. - Communication Engineering Team - 996 Siheung-Dong Keym Cheon-ku - Seoul - KOREA, REPUBLIC OF - - 00-30-83 (hex) Ivron Systems - 003083 (base 16) Ivron Systems - 19-20 YORK ROAD - DUN LAOGHAIRE COUNTY DUBLIN - IRELAND - - 00-30-84 (hex) ALLIED TELESYN INTERNAIONAL - 003084 (base 16) ALLIED TELESYN INTERNAIONAL - CORPORATION - 960 STEWART DRIVE, STE. - SUNNYVALE CA 94086 - UNITED STATES - - 00-30-85 (hex) CISCO SYSTEMS, INC. - 003085 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-86 (hex) Transistor Devices, Inc. - 003086 (base 16) Transistor Devices, Inc. - 36A Newburgh Road - Hackettstown NJ 07840 - UNITED STATES - - 00-30-87 (hex) VEGA GRIESHABER KG - 003087 (base 16) VEGA GRIESHABER KG - AM HOHENSTEIN 113 - 77761 SCHULTACH - GERMANY - - 00-30-88 (hex) Ericsson - 003088 (base 16) Ericsson - 250 Holger Way - SAN JOSE CA 95134 - UNITED STATES - - 00-30-89 (hex) Spectrapoint Wireless, LLC - 003089 (base 16) Spectrapoint Wireless, LLC - 1125 E. Collins Blvd. - Richardson TX 75081 - UNITED STATES - - 00-30-8A (hex) NICOTRA SISTEMI S.P.A - 00308A (base 16) NICOTRA SISTEMI S.P.A - 41 Via Primo Maggio - Baranzate (MI) 20021 - ITALY - - 00-30-8B (hex) Brix Networks - 00308B (base 16) Brix Networks - 300 Concord Road - Billerica MA 01821 - UNITED STATES - - 00-30-8C (hex) Quantum Corporation - 00308C (base 16) Quantum Corporation - 10125 Federal Drive - Colorado Springs CO 80908 - UNITED STATES - - 00-30-8D (hex) Pinnacle Systems, Inc. - 00308D (base 16) Pinnacle Systems, Inc. - Frankfurter Str. 3c - D-38122 Braunschweig - GERMANY - - 00-30-8E (hex) CROSS MATCH TECHNOLOGIES, INC. - 00308E (base 16) CROSS MATCH TECHNOLOGIES, INC. - 3960 RCA Blvd., Suite 6001 - Palm Beach FL 33410 - UNITED STATES - - 00-30-8F (hex) MICRILOR, Inc. - 00308F (base 16) MICRILOR, Inc. - 17 Lakeside Office Park - 607 North Avenue - Wakefield MA 01880 - UNITED STATES - - 00-30-90 (hex) CYRA TECHNOLOGIES, INC. - 003090 (base 16) CYRA TECHNOLOGIES, INC. - 8000 CAPWELL DRIVE - OAKLAND CA 94621 - UNITED STATES - - 00-30-91 (hex) TAIWAN FIRST LINE ELEC. CORP. - 003091 (base 16) TAIWAN FIRST LINE ELEC. CORP. - 40 Chung-Shan Road - Tu-Cheng Industrial Park - Taipei County - TAIWAN, PROVINCE OF CHINA - - 00-30-92 (hex) ModuNORM GmbH - 003092 (base 16) ModuNORM GmbH - Langrutistrasse 33 - CH-8840 Einsledeln - SWITZERLAND - - 00-30-93 (hex) Sonnet Technologies, Inc - 003093 (base 16) Sonnet Technologies, Inc - 8 Autry - Irvine, CA 92618 - UNITED STATES - - 00-30-94 (hex) CISCO SYSTEMS, INC. - 003094 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-95 (hex) Procomp Informatics, Ltd. - 003095 (base 16) Procomp Informatics, Ltd. - 5F, 69-10, Sec. 2, - Chung Cheng E. Road - Tamshui, Taipei, Hsien R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-96 (hex) CISCO SYSTEMS, INC. - 003096 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-97 (hex) AB Regin - 003097 (base 16) AB Regin - Box 366 - SE-26123 Landskrona - SWEDEN - - 00-30-98 (hex) Global Converging Technologies - 003098 (base 16) Global Converging Technologies - 1800 Preston Park Blvd. - Suite #250 - Plano TX 75093 - UNITED STATES - - 00-30-99 (hex) BOENIG UND KALLENBACH OHG - 003099 (base 16) BOENIG UND KALLENBACH OHG - AM SPOERKEL 100 - 44227 DORTMUND - GERMANY - - 00-30-9A (hex) ASTRO TERRA CORP. - 00309A (base 16) ASTRO TERRA CORP. - 11526 SORRENTO VALLEY ROAD - SAN DIEGO CA 92121 - UNITED STATES - - 00-30-9B (hex) Smartware - 00309B (base 16) Smartware - 49 AV Aristide - Briand - 92160 Antony - FRANCE - - 00-30-9C (hex) Timing Applications, Inc. - 00309C (base 16) Timing Applications, Inc. - 4775 Walnut St. - Suite 1B - Boulder CO 80301 - UNITED STATES - - 00-30-9D (hex) Nimble Microsystems, Inc. - 00309D (base 16) Nimble Microsystems, Inc. - 50 Church Street - 5th Floor - Cambridge MA 02138 - UNITED STATES - - 00-30-9E (hex) WORKBIT CORPORATION. - 00309E (base 16) WORKBIT CORPORATION. - 1-2-2 Chuou, Yamato - Kanagawa 242-0021 - JAPAN - - 00-30-9F (hex) AMBER NETWORKS - 00309F (base 16) AMBER NETWORKS - 2475 AUGUSTINE DR. - SANTA CLARA CA 95054 - UNITED STATES - - 00-30-A0 (hex) TYCO SUBMARINE SYSTEMS, LTD. - 0030A0 (base 16) TYCO SUBMARINE SYSTEMS, LTD. - 250 INDUSTRIAL WAY WEST - EATONTOWN NJ 07724 - UNITED STATES - - 00-30-A1 (hex) WEBGATE Inc. - 0030A1 (base 16) WEBGATE Inc. - 4F, Pika Bldg., 894-20, Hoyke 2-dong - Dongan-Ku, - Anyang-Si Kyunggi-Do - KOREA, REPUBLIC OF - - 00-30-A2 (hex) Lightner Engineering - 0030A2 (base 16) Lightner Engineering - 8551 La Jolla Shores Dr - La Jolla CA 92037 - UNITED STATES - - 00-30-A3 (hex) CISCO SYSTEMS, INC. - 0030A3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-A4 (hex) Woodwind Communications System - 0030A4 (base 16) Woodwind Communications System - 20300 Century Blvd., Suite 200B - Germantown MD 20874 - UNITED STATES - - 00-30-A5 (hex) ACTIVE POWER - 0030A5 (base 16) ACTIVE POWER - 11525 STONEHOLLOW - STE.#255 - AUSTIN TX 78758 - UNITED STATES - - 00-30-A6 (hex) VIANET TECHNOLOGIES, LTD. - 0030A6 (base 16) VIANET TECHNOLOGIES, LTD. - 8 HACHARASH STREET - RAMAT HASHARON 47262 - ISRAEL - - 00-30-A7 (hex) SCHWEITZER ENGINEERING - 0030A7 (base 16) SCHWEITZER ENGINEERING - LABORATORIES, INC. - 2350 NE HOPKINS COURT - PULLMAN WA 99163 - UNITED STATES - - 00-30-A8 (hex) OL'E COMMUNICATIONS, INC. - 0030A8 (base 16) OL'E COMMUNICATIONS, INC. - 1962 ZANKER ROAD - SAN JOSE CA 95112 - UNITED STATES - - 00-30-A9 (hex) Netiverse, Inc. - 0030A9 (base 16) Netiverse, Inc. - 100 Century Center Court - Suite #600 - San Jose CA 95112 - UNITED STATES - - 00-30-AA (hex) AXUS MICROSYSTEMS, INC. - 0030AA (base 16) AXUS MICROSYSTEMS, INC. - 2F-4, NO.18/N. 609, SEC. 5 - CHUN-HSIN ROAD, SAN CHUNG TAIPEI COUNTY - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-AB (hex) DELTA NETWORKS, INC. - 0030AB (base 16) DELTA NETWORKS, INC. - 8, KON JAN WEST ROAD - LIUTU INDUSTRIAL ZONE KEELUNG - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-AC (hex) Systeme Lauer GmbH & Co., Ltd. - 0030AC (base 16) Systeme Lauer GmbH & Co., Ltd. - Kelterstrasse 59 - 72669 Unterensingen - GERMANY - - 00-30-AD (hex) SHANGHAI COMMUNICATION - 0030AD (base 16) SHANGHAI COMMUNICATION - TECHNOLOGIES CENTER - 15 GUI-QING ROAD SHANGHAI 200233 - P.R. - CHINA - - 00-30-AE (hex) Times N System, Inc. - 0030AE (base 16) Times N System, Inc. - 1826 Kramer Lane - Ste. - Austin TX 78758 - UNITED STATES - - 00-30-AF (hex) Honeywell GmbH - 0030AF (base 16) Honeywell GmbH - Boeblinger Str. 17 - P.O. Box 1164 - D-71098 Schoenaich - GERMANY - - 00-30-B0 (hex) Convergenet Technologies - 0030B0 (base 16) Convergenet Technologies - 2222 Trade Zone Boulevard - San Jose CA 95131 - UNITED STATES - - 00-30-B1 (hex) TrunkNet - 0030B1 (base 16) TrunkNet - Aubergenviller Allee 51 - Dieburg D-64807 - GERMANY - - 00-30-B2 (hex) L-3 Sonoma EO - 0030B2 (base 16) L-3 Sonoma EO - 428 Aviation Blvd - Santa Rosa CA 95403 - UNITED STATES - - 00-30-B3 (hex) San Valley Systems, Inc. - 0030B3 (base 16) San Valley Systems, Inc. - 2105 S. Bascom Ave. - Ste. #390 - Campbell CA 95008 - UNITED STATES - - 00-30-B4 (hex) INTERSIL CORP. - 0030B4 (base 16) INTERSIL CORP. - P.O. BOX 883 - 2401 PALM BAY ROAD - MELBOURNE FL 32902 - UNITED STATES - - 00-30-B5 (hex) Tadiran Microwave Networks - 0030B5 (base 16) Tadiran Microwave Networks - 4000 Greenbriar Drive - Stafford TX 77477 - UNITED STATES - - 00-30-B6 (hex) CISCO SYSTEMS, INC. - 0030B6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-B7 (hex) Teletrol Systems, Inc. - 0030B7 (base 16) Teletrol Systems, Inc. - Technology Center - 286 Commercial Street - Manchester NH 03101 - UNITED STATES - - 00-30-B8 (hex) RiverDelta Networks - 0030B8 (base 16) RiverDelta Networks - Three Highwood Drive East - Tewksbury MA 01876 - UNITED STATES - - 00-30-B9 (hex) ECTEL - 0030B9 (base 16) ECTEL - 22240 COMSAT DRIVE - CLARKSBURG MD 20871 - UNITED STATES - - 00-30-BA (hex) AC&T SYSTEM CO., LTD. - 0030BA (base 16) AC&T SYSTEM CO., LTD. - ROOM 702, KEUM-WHA PLAZA - 1142-5, SANBON-DONG KOONPO-SHI, KYONGKI- - 435-040 SOUTH KOREA - KOREA, REPUBLIC OF - - 00-30-BB (hex) CacheFlow, Inc. - 0030BB (base 16) CacheFlow, Inc. - 650 Almanor Drive - Sunnyvale CA 94086 - UNITED STATES - - 00-30-BC (hex) Optronic AG - 0030BC (base 16) Optronic AG - untereggerstrasse 53 - 9403 Goldach - SWITZERLAND - - 00-30-BD (hex) BELKIN COMPONENTS - 0030BD (base 16) BELKIN COMPONENTS - 501 WEST WALNUT STREET - COMPTON CA 90220 - UNITED STATES - - 00-30-BE (hex) City-Net Technology, Inc. - 0030BE (base 16) City-Net Technology, Inc. - 135 E. Chesnut Ave., Ste. - Monrovia CA 91016 - UNITED STATES - - 00-30-BF (hex) MULTIDATA GMBH - 0030BF (base 16) MULTIDATA GMBH - Dieburger Str. 96a - D-64289 DARMSTADT - GERMANY - - 00-30-C0 (hex) Lara Technology, Inc. - 0030C0 (base 16) Lara Technology, Inc. - 2345 North First Street - San Jose CA 95131 - UNITED STATES - - 00-30-C1 (hex) HEWLETT-PACKARD - 0030C1 (base 16) HEWLETT-PACKARD - 11000 WOLFE ROAD - CUPERTINO CA 95014 - UNITED STATES - - 00-30-C2 (hex) COMONE - 0030C2 (base 16) COMONE - Parc De Marticot - 33610 Cestas - FRANCE - - 00-30-C3 (hex) FLUECKIGER ELEKTRONIK AG - 0030C3 (base 16) FLUECKIGER ELEKTRONIK AG - KIRCHBARGSTRASSE 201 - CH-3400 BURGDORF - SWITZERLAND - - 00-30-C4 (hex) Canon Imaging Systems Inc. - 0030C4 (base 16) Canon Imaging Systems Inc. - 1-24 Yoneyama, Chuo-ku - Niigata-shi Niigata 950-0916 - JAPAN - - 00-30-C5 (hex) CADENCE DESIGN SYSTEMS - 0030C5 (base 16) CADENCE DESIGN SYSTEMS - CANADA, LTD. - 240-1130 MORRISON DRIVE OTTAWA, ONTARIO - CANADA - - 00-30-C6 (hex) CONTROL SOLUTIONS, INC. - 0030C6 (base 16) CONTROL SOLUTIONS, INC. - 201 85TH AVENUE NW - MINNEAPOLIS MN 55433 - UNITED STATES - - 00-30-C7 (hex) Macromate Corp. - 0030C7 (base 16) Macromate Corp. - 8F,Universal Center,Number 179 - Sec.1,Ta-Tung Road, Hsi-Chih - Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-30-C8 (hex) GAD LINE, LTD. - 0030C8 (base 16) GAD LINE, LTD. - BEIT ROKAR HAR HOTZVIM - JERUSALEM - ISRAEL - - 00-30-C9 (hex) LuxN, N - 0030C9 (base 16) LuxN, N - 570 Maude Court - Sunnyvale CA 94086 - UNITED STATES - - 00-30-CA (hex) Discovery Com - 0030CA (base 16) Discovery Com - 4935 Century Street - Huntsville AL 35816 - UNITED STATES - - 00-30-CB (hex) OMNI FLOW COMPUTERS, INC. - 0030CB (base 16) OMNI FLOW COMPUTERS, INC. - 10701 CORPORATE DRIVE-STE.#300 - STAFFORD TX 77477 - UNITED STATES - - 00-30-CC (hex) Tenor Networks, Inc. - 0030CC (base 16) Tenor Networks, Inc. - 50 Nagog Park - Acton MA 01720 - UNITED STATES - - 00-30-CD (hex) CONEXANT SYSTEMS, INC. - 0030CD (base 16) CONEXANT SYSTEMS, INC. - 4311 JAMBOREE ROAD - NEWPORT BEACH CA 92660 - UNITED STATES - - 00-30-CE (hex) Zaffire - 0030CE (base 16) Zaffire - 2630 Orchard Parkway - San Jose CA 95134-2020 - UNITED STATES - - 00-30-CF (hex) TWO TECHNOLOGIES, INC. - 0030CF (base 16) TWO TECHNOLOGIES, INC. - 419 SARGON WAY - HORSHAM PA 19044 - UNITED STATES - - 00-30-D0 (hex) Tellabs - 0030D0 (base 16) Tellabs - 1750 Founder's Parkway - Suite 100 - Alpharetta GA 30004 - UNITED STATES - - 00-30-D1 (hex) INOVA CORPORATION - 0030D1 (base 16) INOVA CORPORATION - 110 AVON STREET - CHARLOTTESVILE VA 22902 - UNITED STATES - - 00-30-D2 (hex) WIN TECHNOLOGIES, CO., LTD. - 0030D2 (base 16) WIN TECHNOLOGIES, CO., LTD. - 4F-6, No. 81, Sec. 1 - Hsin Tai Wu Road, Hsi-Chi - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-30-D3 (hex) Agilent Technologies - 0030D3 (base 16) Agilent Technologies - 1501 Page Mill Road - Palo Alto CA 94304-1126 - UNITED STATES - - 00-30-D4 (hex) AAE Systems, Inc. - 0030D4 (base 16) AAE Systems, Inc. - 642 North Pastoria Avenue - Sunnyvale CA 94085 - UNITED STATES - - 00-30-D5 (hex) DResearch GmbH - 0030D5 (base 16) DResearch GmbH - Otto-Schmirgal-Str.3 - 10319 Berlin - GERMANY - - 00-30-D6 (hex) MSC VERTRIEBS GMBH - 0030D6 (base 16) MSC VERTRIEBS GMBH - INDUSTRIESTR. 16 - D-76297 STUTENSEE - GERMANY - - 00-30-D7 (hex) Innovative Systems, L.L.C. - 0030D7 (base 16) Innovative Systems, L.L.C. - 1000 Innovative Drive - Mitchell SD 57301 - UNITED STATES - - 00-30-D8 (hex) SITEK - 0030D8 (base 16) SITEK - VIA MONTE FIORINO 9 - 37057 - S. GIOVANNI LUP. VERONA - ITALY - - 00-30-D9 (hex) DATACORE SOFTWARE CORP. - 0030D9 (base 16) DATACORE SOFTWARE CORP. - CORPORATE PARK - 6261 NW 6TH WAY #110 - FORT LAUDERDALE FL 33309 - UNITED STATES - - 00-30-DA (hex) COMTREND CO. - 0030DA (base 16) COMTREND CO. - 3F-1 10 LANE 609 CHUNG - HSIN ROAD, SEC 5, SAN CHUNG CITY, TAIPEI - TAIWAN 241 - TAIWAN, PROVINCE OF CHINA - - 00-30-DB (hex) Mindready Solutions, Inc. - 0030DB (base 16) Mindready Solutions, Inc. - 2800 Marie-Curie Avenue - Saint-Laurent - Quebec H4S 2C2 - CANADA - - 00-30-DC (hex) RIGHTECH CORPORATION - 0030DC (base 16) RIGHTECH CORPORATION - 4F, NO. 351, CHUNG-SHUN RD. - SEC. 2, CHUNG-HO CITY TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-30-DD (hex) INDIGITA CORPORATION - 0030DD (base 16) INDIGITA CORPORATION - 30 Corporate Park Drive - Suite 310 - Irvine CA 92606 - UNITED STATES - - 00-30-DE (hex) WAGO Kontakttechnik GmbH - 0030DE (base 16) WAGO Kontakttechnik GmbH - Hansastrasse 27 - 32423 Minden - GERMANY - - 00-30-DF (hex) KB/TEL TELECOMUNICACIONES - 0030DF (base 16) KB/TEL TELECOMUNICACIONES - S.A. DE C.V. - TORRE TELMEX 4 PISO, PLAZA CUICUILCO - Mexico City 14060 - MEXICO - - 00-30-E0 (hex) OXFORD SEMICONDUCTOR LTD. - 0030E0 (base 16) OXFORD SEMICONDUCTOR LTD. - 25 MILTON PARK - Abingdon Oxon OX14 4SH - UNITED KINGDOM - - 00-30-E1 (hex) Network Equipment Technologies, Inc. - 0030E1 (base 16) Network Equipment Technologies, Inc. - 6900 Paseo Padre Parkway - Fremont CA 94555 - UNITED STATES - - 00-30-E2 (hex) GARNET SYSTEMS CO., LTD. - 0030E2 (base 16) GARNET SYSTEMS CO., LTD. - Sungwon Bldg. 545-7 - Dogok-Dong, Kangnam-Gu - Seoul - KOREA, REPUBLIC OF - - 00-30-E3 (hex) SEDONA NETWORKS CORP. - 0030E3 (base 16) SEDONA NETWORKS CORP. - 10A HEARST WAY - KANATA, ONTARIO - CANADA K2L 2P4 - CANADA - - 00-30-E4 (hex) CHIYODA SYSTEM RIKEN - 0030E4 (base 16) CHIYODA SYSTEM RIKEN - 2-7, KANDA-NISHIKI-CHO - CHIYODA-KU TOKYO - JAPAN - - 00-30-E5 (hex) Amper Datos S.A. - 0030E5 (base 16) Amper Datos S.A. - C/Marconi n*3 (PTM) - Tres Cantos - 28760 Madrid - SPAIN - - 00-30-E6 (hex) Draeger Medical Systems, Inc. - 0030E6 (base 16) Draeger Medical Systems, Inc. - 6 Tech Drive - Andover MA 01810 - UNITED STATES - - 00-30-E7 (hex) CNF MOBILE SOLUTIONS, INC. - 0030E7 (base 16) CNF MOBILE SOLUTIONS, INC. - 7722 E. GRAY ROAD - SCOTTSDALE AZ 85260 - UNITED STATES - - 00-30-E8 (hex) ENSIM CORP. - 0030E8 (base 16) ENSIM CORP. - 1215 Terra Bella Ave. - Mountainview CA 94043 - UNITED STATES - - 00-30-E9 (hex) GMA COMMUNICATION MANUFACT'G - 0030E9 (base 16) GMA COMMUNICATION MANUFACT'G - MARKETING, (1991) LTD. - 102 JABUTINSKI STREET KIRYAT ARIE, PETAC - ISRAEL ISRAEL 49130 - ISRAEL - - 00-30-EA (hex) TeraForce Technology Corporation - 0030EA (base 16) TeraForce Technology Corporation - 1100 EXECUTIVE DRIVE - RICHARDSON TX 75081 - UNITED STATES - - 00-30-EB (hex) TURBONET COMMUNICATIONS, INC. - 0030EB (base 16) TURBONET COMMUNICATIONS, INC. - 19F-1, NO. 171, SUNG-TEH ROAD - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-30-EC (hex) BORGARDT - 0030EC (base 16) BORGARDT - DIESELSTR. 15 - D71665 VAIHINGEN/ENZ - GERMANY - - 00-30-ED (hex) Expert Magnetics Corp. - 0030ED (base 16) Expert Magnetics Corp. - 12/F., Unit D, MTG Bldg., 1-3, Nakase - Mihama-ku, Chiba-city, 261-8501 - JAPAN - - 00-30-EE (hex) DSG Technology, Inc. - 0030EE (base 16) DSG Technology, Inc. - 6F-4 No. 270, Chwig Hsiao - East Road, Sec. 4 - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-30-EF (hex) NEON TECHNOLOGY, INC. - 0030EF (base 16) NEON TECHNOLOGY, INC. - 85 WEST MONTAGUE EXPRESSWAY - MILPITAS CA 95035 - UNITED STATES - - 00-30-F0 (hex) Uniform Industrial Corp. - 0030F0 (base 16) Uniform Industrial Corp. - 18F, 171, Shung Teh Road - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-30-F1 (hex) Accton Technology Corp. - 0030F1 (base 16) Accton Technology Corp. - No. 1, Creation Rd. IV - S.G.Z.P - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-30-F2 (hex) CISCO SYSTEMS, INC. - 0030F2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-30-F3 (hex) At Work Computers - 0030F3 (base 16) At Work Computers - P.O. Box 947 - Corvallis OR 97339 - UNITED STATES - - 00-30-F4 (hex) STARDOT TECHNOLOGIES - 0030F4 (base 16) STARDOT TECHNOLOGIES - 6820-H ORANGE THORPE AVE. - BUENA PARK CA 90620 - UNITED STATES - - 00-30-F5 (hex) Wild Lab. Ltd. - 0030F5 (base 16) Wild Lab. Ltd. - 1-33-17-604 Harayama - Urawa City Saitama prif. 336-0931 - JAPAN - - 00-30-F6 (hex) SECURELOGIX CORPORATION - 0030F6 (base 16) SECURELOGIX CORPORATION - 13750 SAN PEDRO - SAN ANTONIO TX 78232 - UNITED STATES - - 00-30-F7 (hex) RAMIX INC. - 0030F7 (base 16) RAMIX INC. - 1672 DONLON STREET - VENTURA CA 93003 - UNITED STATES - - 00-30-F8 (hex) Dynapro Systems, Inc. - 0030F8 (base 16) Dynapro Systems, Inc. - 800 Carleton Court - Annacis Island - New Westminster British Columbia V3M 6L3 - CANADA - - 00-30-F9 (hex) Sollae Systems Co., Ltd. - 0030F9 (base 16) Sollae Systems Co., Ltd. - 607 Incheo IT Tower - 592-5, Dohwa-1-dong - Nam-gu Incheon - KOREA, REPUBLIC OF - - 00-30-FA (hex) TELICA, INC. - 0030FA (base 16) TELICA, INC. - 734 FOREST STREET, BLDG. - SUITE #100 - MARLBORO MA 01752 - UNITED STATES - - 00-30-FB (hex) AZS Technology AG - 0030FB (base 16) AZS Technology AG - Steinbeisstrasse 2-4 - 72510 Stetten A.K.M. - GERMANY - - 00-30-FC (hex) Terawave Communications, Inc. - 0030FC (base 16) Terawave Communications, Inc. - 30695 Huntwood Avenue - Hayward CA 94544 - UNITED STATES - - 00-30-FD (hex) INTEGRATED SYSTEMS DESIGN - 0030FD (base 16) INTEGRATED SYSTEMS DESIGN - 3650-G CENTRE CIRCLE DRIVE - FORT MILL SC 29715 - UNITED STATES - - 00-30-FE (hex) DSA GmbH - 0030FE (base 16) DSA GmbH - Pascalstraße 28 - 52076 Aachen - GERMANY - - 00-30-FF (hex) DATAFAB SYSTEMS, INC. - 0030FF (base 16) DATAFAB SYSTEMS, INC. - ROOM #1910, 19F, NO. 333 - KEELUNG ROAD SEC. 1, TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-32-3A (hex) so-logic - 00323A (base 16) so-logic - Lustkandlgasse 52 - Vienna Vienna 1090 - AUSTRIA - - 00-33-6C (hex) SynapSense Corporation - 00336C (base 16) SynapSense Corporation - 2365 Iron Point Road, Suite 100 - Folsom CA 95630 - UNITED STATES - - 00-34-F1 (hex) Radicom Research, Inc. - 0034F1 (base 16) Radicom Research, Inc. - 2148 Bering Drive - San Jose Ca 95131 - UNITED STATES - - 00-35-32 (hex) Electro-Metrics Corporation - 003532 (base 16) Electro-Metrics Corporation - 231 Enterprise Road - Johnstown New York 12095 - UNITED STATES - - 00-35-60 (hex) Rosen Aviation - 003560 (base 16) Rosen Aviation - 1020 Owen Loop South - Eugene Oregon 97402 - UNITED STATES - - 00-36-F8 (hex) Conti Temic microelectronic GmbH - 0036F8 (base 16) Conti Temic microelectronic GmbH - Dornierstraße 1 - Markdorf 88677 - GERMANY - - 00-36-FE (hex) SuperVision - 0036FE (base 16) SuperVision - po box 3472 - palos verdes CA 90274 - UNITED STATES - - 00-37-6D (hex) Murata Manufacturing Co., Ltd. - 00376D (base 16) Murata Manufacturing Co., Ltd. - 1-10-1,Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 00-37-B7 (hex) SAGEMCOM - 0037B7 (base 16) SAGEMCOM - 250 route de l'Empereur - Rueil Malmaison Hauts de Seine 92848 - FRANCE - - 00-3A-98 (hex) CISCO SYSTEMS, INC. - 003A98 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-3A-99 (hex) CISCO SYSTEMS, INC. - 003A99 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-3A-9A (hex) CISCO SYSTEMS, INC. - 003A9A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-3A-9B (hex) CISCO SYSTEMS, INC. - 003A9B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-3A-9C (hex) CISCO SYSTEMS, INC. - 003A9C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-3A-9D (hex) NEC Platforms, Ltd. - 003A9D (base 16) NEC Platforms, Ltd. - 800 Shimomata - Kakegawa Shizuoka 436-8501 - JAPAN - - 00-3A-AF (hex) BlueBit Ltd. - 003AAF (base 16) BlueBit Ltd. - Unit B, 21/F., 78 Hung To Road, - Kwun Tong, - Kowloon, - HONG KONG - - 00-3C-C5 (hex) WONWOO Engineering Co., Ltd - 003CC5 (base 16) WONWOO Engineering Co., Ltd - 7F 201, Techno-Park SsangYong III, - 36-1 Samjeong-dong Ojeong-gu, - Bucheon City Gyeonggi-Do 421-808 - KOREA, REPUBLIC OF - - 00-3D-41 (hex) Hatteland Computer AS - 003D41 (base 16) Hatteland Computer AS - Aamsosen - Nedre Vats Rogaland 5578 - NORWAY - - 00-3E-E1 (hex) Apple - 003EE1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-40-00 (hex) PCI COMPONENTES DA AMZONIA LTD - 004000 (base 16) PCI COMPONENTES DA AMZONIA LTD - RUA JOSEF KRYSS - 129 - SAO PAULO - SP - 01140 BRASIL - BRAZIL - - 00-40-01 (hex) Zero One Technology Co. Ltd. - 004001 (base 16) Zero One Technology Co. Ltd. - 10 Fl., No. 8, Lane 360, Sec 1, - Neihu Road - Neihu Dist., Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-40-02 (hex) PERLE SYSTEMS LIMITED - 004002 (base 16) PERLE SYSTEMS LIMITED - 60 RENFREW DRIVE - MARKHAM ONTARIO - CANADA L3R 0E1 - CANADA - - 00-40-03 (hex) Emerson Process Management Power & Water Solutions, Inc. - 004003 (base 16) Emerson Process Management Power & Water Solutions, Inc. - 200 Beta Drive - PITTSBURGH PA 15238 - UNITED STATES - - 00-40-04 (hex) ICM CO. LTD. - 004004 (base 16) ICM CO. LTD. - 4-2-9 NIHONBASHI NANIWA-KU - OSAKA, (556) - JAPAN - - 00-40-05 (hex) ANI COMMUNICATIONS INC. - 004005 (base 16) ANI COMMUNICATIONS INC. - 8 ANZIO - IRVINE CA 92714 - UNITED STATES - - 00-40-06 (hex) SAMPO TECHNOLOGY CORPORATION - 004006 (base 16) SAMPO TECHNOLOGY CORPORATION - 26-2 TING-HU, - TA-KANG TSUN KUEI-SHAN HSIANG, TAOYUAN H - 33334 TAIWAN 33334 TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-40-07 (hex) TELMAT INFORMATIQUE - 004007 (base 16) TELMAT INFORMATIQUE - 6 RUE DE L'INDUSTRIE - BP 12 68360 SOULTZ - FRANCE - - 00-40-08 (hex) A PLUS INFO CORPORATION - 004008 (base 16) A PLUS INFO CORPORATION - 5F, NO.2, LANE 235 - BAO CHIAO ROAD HSIN TIEN, TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-40-09 (hex) TACHIBANA TECTRON CO., LTD. - 004009 (base 16) TACHIBANA TECTRON CO., LTD. - SYSTEMATIC EQUIPMENT DIVISION - 2-2-5 HIGASHIYAMA, MEGUROKU TOKYO, 153 - JAPAN - - 00-40-0A (hex) PIVOTAL TECHNOLOGIES, INC. - 00400A (base 16) PIVOTAL TECHNOLOGIES, INC. - 100 W. RINCON AVENUE-STE #211 - CAMPBELL CA 95008 - UNITED STATES - - 00-40-0B (hex) CISCO SYSTEMS, INC. - 00400B (base 16) CISCO SYSTEMS, INC. - 170 WEST TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-40-0C (hex) GENERAL MICRO SYSTEMS, INC. - 00400C (base 16) GENERAL MICRO SYSTEMS, INC. - P.O. BOX 3689 - RANCHO CUCAMONGA CA 91729 - UNITED STATES - - 00-40-0D (hex) LANNET DATA COMMUNICATIONS,LTD - 00400D (base 16) LANNET DATA COMMUNICATIONS,LTD - ATIDIM TECHNOLOG'L PARK, BG.#3 - TEL AVIV 61131 - ISRAEL - - 00-40-0E (hex) MEMOTEC, INC. - 00400E (base 16) MEMOTEC, INC. - 7755 Henri-Bourassa - MONTREAL, QUEBEC H4S 1P7 - CANADA - - 00-40-0F (hex) DATACOM TECHNOLOGIES - 00400F (base 16) DATACOM TECHNOLOGIES - 11001 31ST PLACE WEST - EVERETT WA 98204 - UNITED STATES - - 00-40-10 (hex) SONIC SYSTEMS, INC. - 004010 (base 16) SONIC SYSTEMS, INC. - 575 PASTORIA NORTH AVENUE - SUNNYVALE CA 940867 - UNITED STATES - - 00-40-11 (hex) ANDOVER CONTROLS CORPORATION - 004011 (base 16) ANDOVER CONTROLS CORPORATION - 300 BRICKSTONE SQUARE - ANDOVER MA 01810 - UNITED STATES - - 00-40-12 (hex) WINDATA, INC. - 004012 (base 16) WINDATA, INC. - 10 BEARFOOT ROAD - NORTHBORO MA 01532 - UNITED STATES - - 00-40-13 (hex) NTT DATA COMM. SYSTEMS CORP. - 004013 (base 16) NTT DATA COMM. SYSTEMS CORP. - DEVELOPMENT HEADQUARTERS - TOYOSU CENTER BLDG., 3-3-3 TOYOSU, KOTO- - TOKYO 135 TOKYO 135 - JAPAN - - 00-40-14 (hex) COMSOFT GMBH - 004014 (base 16) COMSOFT GMBH - WACHHAUSSTR. 5A - 7500 KARLSRUHE 41 - GERMANY - - 00-40-15 (hex) ASCOM INFRASYS AG - 004015 (base 16) ASCOM INFRASYS AG - DPT. EASO 3726 - GLUTZ-BLOTZHEIMSTR. 1 CH-4503 SOLOTHURN - SWITZERLAND - - 00-40-16 (hex) ADC - Global Connectivity Solutions Division - 004016 (base 16) ADC - Global Connectivity Solutions Division - P.O. Box 1101 - Minneapolis MN 55440-1101 - UNITED STATES - - 00-40-17 (hex) Silex Technology America - 004017 (base 16) Silex Technology America - 157 West 7065 South - Salt Lake City UT 84047 - UNITED STATES - - 00-40-18 (hex) ADOBE SYSTEMS, INC. - 004018 (base 16) ADOBE SYSTEMS, INC. - 1585 CHARLESTON ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-40-19 (hex) AEON SYSTEMS, INC. - 004019 (base 16) AEON SYSTEMS, INC. - 8401 WASHINGTON PLACE NE - ALBUQUERQUE NM 87113 - UNITED STATES - - 00-40-1A (hex) FUJI ELECTRIC CO., LTD. - 00401A (base 16) FUJI ELECTRIC CO., LTD. - NEW YURAKUCHO BLDG - 12-1 YURAKUCHO 1-CHOME CHIYODA-KU, TOKYO - JAPAN - - 00-40-1B (hex) PRINTER SYSTEMS CORP. - 00401B (base 16) PRINTER SYSTEMS CORP. - 207 PERRY PARKWAY - GAITHERSBURG MD 20877-2142 - UNITED STATES - - 00-40-1C (hex) AST RESEARCH, INC. - 00401C (base 16) AST RESEARCH, INC. - MS 2-78 - 1615 ALTON PARKWAY - IRVINE CA 92618 - UNITED STATES - - 00-40-1D (hex) INVISIBLE SOFTWARE, INC. - 00401D (base 16) INVISIBLE SOFTWARE, INC. - 1142 CHESS DRIVE - FOSTER CITY CA 94404 - UNITED STATES - - 00-40-1E (hex) ICC - 00401E (base 16) ICC - 8230 MONTGOMERY ROAD - CINCINNATI OH 45236 - UNITED STATES - - 00-40-1F (hex) COLORGRAPH LTD - 00401F (base 16) COLORGRAPH LTD - UNIT 2, MARS HOUSE - CALLEVA PARK, ALDERMASTON NR. READING, B - RG7 4QW - UNITED KINGDOM - UNITED KINGDOM - - 00-40-20 (hex) TE Connectivity Ltd. - 004020 (base 16) TE Connectivity Ltd. - Kinmel Park - Bodelwyddan RHYL LL18 5TZ - UNITED KINGDOM - - 00-40-21 (hex) RASTER GRAPHICS - 004021 (base 16) RASTER GRAPHICS - 285 N. WOLFE ROAD - SUNNYVALE CA 94086 - UNITED STATES - - 00-40-22 (hex) KLEVER COMPUTERS, INC. - 004022 (base 16) KLEVER COMPUTERS, INC. - 1028 W. MAUDE AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-40-23 (hex) LOGIC CORPORATION - 004023 (base 16) LOGIC CORPORATION - 3-14-10 MEIJI-SEIMEI BUILDING - MITA MINATO-KU TOKYO - JAPAN - - 00-40-24 (hex) COMPAC INC. - 004024 (base 16) COMPAC INC. - 16-7 NIHONBASI HAMACHO 3-CHO - CHUO-KU, TOKYO - JAPAN - - 00-40-25 (hex) MOLECULAR DYNAMICS - 004025 (base 16) MOLECULAR DYNAMICS - 880 EAST ARQUES AVENUE - SUNNYVALE CA 94086-4536 - UNITED STATES - - 00-40-26 (hex) Buffalo Inc. - 004026 (base 16) Buffalo Inc. - AKAMONDORI Bldg., 30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref. 460-8315 - JAPAN - - 00-40-27 (hex) SMC MASSACHUSETTS, INC. - 004027 (base 16) SMC MASSACHUSETTS, INC. - 25 WALKERS BROOK DRIVE - READING MA 01867 - UNITED STATES - - 00-40-28 (hex) NETCOMM LIMITED - 004028 (base 16) NETCOMM LIMITED - 3 OLYMPIC BUSINESS CENTRE - PAYCOCKE ROAD BASILDON, ESSEX SS14 3EX - UNITED KINGDOM - UNITED KINGDOM - - 00-40-29 (hex) COMPEX - 004029 (base 16) COMPEX - B.P. 35 - 74371 PRINGY-FRANCE - FRANCE - - 00-40-2A (hex) CANOGA-PERKINS - 00402A (base 16) CANOGA-PERKINS - 21012 LASSEN STREET - CHATSWORTH CA 91311-4241 - UNITED STATES - - 00-40-2B (hex) TRIGEM COMPUTER, INC. - 00402B (base 16) TRIGEM COMPUTER, INC. - KISUNG B/D 4F, 784-6 - YEOKSAM-DONG, KANGNAM-GU - SEOUL KOREA 135-080 - KOREA, REPUBLIC OF - - 00-40-2C (hex) ISIS DISTRIBUTED SYSTEMS, INC. - 00402C (base 16) ISIS DISTRIBUTED SYSTEMS, INC. - 111 SOUTH CAYUGA STREET - SUITE #200 - ITHACA NY 14850 - UNITED STATES - - 00-40-2D (hex) HARRIS ADACOM CORPORATION - 00402D (base 16) HARRIS ADACOM CORPORATION - 1100 VENTURE COURT - CARROLLTON TX 75006-5412 - UNITED STATES - - 00-40-2E (hex) PRECISION SOFTWARE, INC. - 00402E (base 16) PRECISION SOFTWARE, INC. - 600 S FEDERAL HWY STE - DEERFIELD BEACH FL 33441-4193 - UNITED STATES - - 00-40-2F (hex) XLNT DESIGNS INC. - 00402F (base 16) XLNT DESIGNS INC. - 15050 AVENUE OF SCIENCE - SUITE 200 - SAN DIEGO CA 92128 - UNITED STATES - - 00-40-30 (hex) GK COMPUTER - 004030 (base 16) GK COMPUTER - BASLER STRASSE 103 - D-7800 FREIBURG - GERMANY - - 00-40-31 (hex) KOKUSAI ELECTRIC CO., LTD - 004031 (base 16) KOKUSAI ELECTRIC CO., LTD - 2-1 YASUUCHI - YATSUO-MACHI NEIGUN - TOYAMA 939-23 - JAPAN - - 00-40-32 (hex) DIGITAL COMMUNICATIONS - 004032 (base 16) DIGITAL COMMUNICATIONS - ASSOCIATES, INC. - 2010 FORTUNE DRIVE, #101 - SAN JOSE CA 95131 - UNITED STATES - - 00-40-33 (hex) ADDTRON TECHNOLOGY CO., LTD. - 004033 (base 16) ADDTRON TECHNOLOGY CO., LTD. - 46560 FREMONT BLVD. #303 - FREMONT CA 94538 - UNITED STATES - - 00-40-34 (hex) BUSTEK CORPORATION - 004034 (base 16) BUSTEK CORPORATION - 4151 BURTON DRIVE - SANTA CLARA CA 95054 - UNITED STATES - - 00-40-35 (hex) OPCOM - 004035 (base 16) OPCOM - 1215 W. CROSBY RD. - CARROLLTON TX 75006 - UNITED STATES - - 00-40-36 (hex) Zoom Telephonics, Inc - 004036 (base 16) Zoom Telephonics, Inc - 207 South St - Boston MA 02111 - UNITED STATES - - 00-40-37 (hex) SEA-ILAN, INC. - 004037 (base 16) SEA-ILAN, INC. - 14602 NORTH US HIGHWAY #31 - CARMEL IN 46032 - UNITED STATES - - 00-40-38 (hex) TALENT ELECTRIC INCORPORATED - 004038 (base 16) TALENT ELECTRIC INCORPORATED - 3RD FL., NO. 260, PA TEH ROAD - SEC. 2 TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-40-39 (hex) OPTEC DAIICHI DENKO CO., LTD. - 004039 (base 16) OPTEC DAIICHI DENKO CO., LTD. - FIBER OPTICS & TELECOM. DIV. - 3-1-1 MARUNOUCHI CHIYODAKU TOKYO 100 - JAPAN - - 00-40-3A (hex) IMPACT TECHNOLOGIES - 00403A (base 16) IMPACT TECHNOLOGIES - 6 RUE DE L'ACADIE - Z.A. COURTABOEUF 91953 LES ULIS CEDEX - FRANCE - - 00-40-3B (hex) SYNERJET INTERNATIONAL CORP. - 00403B (base 16) SYNERJET INTERNATIONAL CORP. - 5F, NO 35, KUANG FU S. ROAD - TAIPEI, - TAIWAN R. O. C. - TAIWAN, PROVINCE OF CHINA - - 00-40-3C (hex) FORKS, INC. - 00403C (base 16) FORKS, INC. - 1-27-4 IRIYA, - IRIYA 1-27-4 TAITO, - 110 - JAPAN - - 00-40-3D (hex) Teradata Corporation - 00403D (base 16) Teradata Corporation - 17095 Via Del Campo - San Diego CA 92127 - UNITED STATES - - 00-40-3E (hex) RASTER OPS CORPORATION - 00403E (base 16) RASTER OPS CORPORATION - 2500 WALSH AVENUE - SANTA CLARA CA 95051 - UNITED STATES - - 00-40-3F (hex) SSANGYONG COMPUTER SYSTEMS - 00403F (base 16) SSANGYONG COMPUTER SYSTEMS - CORPORATION - 60-1, 3GA, CHUNGMU-RO, JUNG-GU SEOUL - KOREA 100-705 - KOREA, REPUBLIC OF - - 00-40-40 (hex) RING ACCESS, INC. - 004040 (base 16) RING ACCESS, INC. - 957-R INDUSTRIAL ROAD - SAN CARLOS CA 94070 - UNITED STATES - - 00-40-41 (hex) FUJIKURA LTD. - 004041 (base 16) FUJIKURA LTD. - 1-5-1, KIBA, KOTO-KU - TOKYO 135 - JAPAN - - 00-40-42 (hex) N.A.T. GMBH - 004042 (base 16) N.A.T. GMBH - GOETHESTR. 2 - 5210 TROISDORF-SIEGLAR - GERMANY - - 00-40-43 (hex) Nokia Siemens Networks GmbH & Co. KG. - 004043 (base 16) Nokia Siemens Networks GmbH & Co. KG. - Werner-von-Siemens Straße 2-6 - Bruchsal Baden-Württemberg 76646 - GERMANY - - 00-40-44 (hex) QNIX COMPUTER CO., LTD. - 004044 (base 16) QNIX COMPUTER CO., LTD. - 8,9F KOREAN TEACHER'S MUT.BLDG - 35-3, YEOUIDO_DONG, YEONGDEUNGPO_GU - SEOUL KOREA 150-010 - KOREA, REPUBLIC OF - - 00-40-45 (hex) TWINHEAD CORPORATION - 004045 (base 16) TWINHEAD CORPORATION - 1537 CENTRE POINTE DRIVE - MILPITAS CA 95035 - UNITED STATES - - 00-40-46 (hex) UDC RESEARCH LIMITED - 004046 (base 16) UDC RESEARCH LIMITED - 8A KING WAN INDUSTRIAL BLDG. - 54 HUNG TO ROAD, KWUN TONG - HONG KONG - HONG KONG - - 00-40-47 (hex) WIND RIVER SYSTEMS - 004047 (base 16) WIND RIVER SYSTEMS - 1010 ATLANTIC AVENUE - ALAMEDA CA 94501 - UNITED STATES - - 00-40-48 (hex) SMD INFORMATICA S.A. - 004048 (base 16) SMD INFORMATICA S.A. - LARGO MOVIMENTO DAS FORCAS - ARMADAS, 4 ALFRAGIDE, 2700 AMADORA - PORTUGAL - - 00-40-49 (hex) Roche Diagnostics International Ltd. - 004049 (base 16) Roche Diagnostics International Ltd. - FORRENSTRASSE - ROTKREUZ ZG 6343 - SWITZERLAND - - 00-40-4A (hex) WEST AUSTRALIAN DEPARTMENT - 00404A (base 16) WEST AUSTRALIAN DEPARTMENT - OF EMPLOYMENT (DEVET) - LEVER 2, 151 ROYAL ST. EAST PERTH 6001 - WESTERN - AUSTRALIA - - 00-40-4B (hex) MAPLE COMPUTER SYSTEMS - 00404B (base 16) MAPLE COMPUTER SYSTEMS - P.O. BOX 10050 - ST. JOHN'S, NF - CANADA ALA 4L5 - CANADA - - 00-40-4C (hex) HYPERTEC PTY LTD. - 00404C (base 16) HYPERTEC PTY LTD. - P.O. BOX 1782 - MACQUARIE CENTRE NSW, 2113 - AUSTRALIA - - 00-40-4D (hex) TELECOMMUNICATIONS TECHNIQUES - 00404D (base 16) TELECOMMUNICATIONS TECHNIQUES - M/S - 20400 OBSERVATION DRIVE - GERMANTOWN MD 20876 - UNITED STATES - - 00-40-4E (hex) FLUENT, INC. - 00404E (base 16) FLUENT, INC. - 594 WORCESTER ROAD-STE.#308 - NATICK MA 01760 - UNITED STATES - - 00-40-4F (hex) SPACE & NAVAL WARFARE SYSTEMS - 00404F (base 16) SPACE & NAVAL WARFARE SYSTEMS - NUWC - CODE 2222, BLDG 1171-3 - NEWPORT RI 02841-5047 - UNITED STATES - - 00-40-50 (hex) IRONICS, INCORPORATED - 004050 (base 16) IRONICS, INCORPORATED - 767 WARREN RD - ITHACA N.Y. 14850 - UNITED STATES - - 00-40-51 (hex) GRACILIS, INC. - 004051 (base 16) GRACILIS, INC. - 623 PALACE STREET - AURORA IL 60506 - UNITED STATES - - 00-40-52 (hex) STAR TECHNOLOGIES, INC. - 004052 (base 16) STAR TECHNOLOGIES, INC. - 515 SHAW ROAD - STERLING VA 22075 - UNITED STATES - - 00-40-53 (hex) AMPRO COMPUTERS - 004053 (base 16) AMPRO COMPUTERS - 990 ALMONDOR AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-40-54 (hex) CONNECTION MACHINES SERVICES - 004054 (base 16) CONNECTION MACHINES SERVICES - 12 HENSHAW STREET - WOBURN MA 01801-466664 - UNITED STATES - - 00-40-55 (hex) METRONIX GMBH - 004055 (base 16) METRONIX GMBH - NEUE KNOCHENHAUERSTRAßE 5 - D-3300 BRAUNSCHWEIG - WEST - GERMANY - - 00-40-56 (hex) MCM JAPAN LTD. - 004056 (base 16) MCM JAPAN LTD. - SYUUKAEN BLD. 2-11-1 - KOMAZAWA SETAGAYA-KU TOKYO 154 - JAPAN - - 00-40-57 (hex) LOCKHEED - SANDERS - 004057 (base 16) LOCKHEED - SANDERS - DANIEL WEBSTER HIGHWAY SOUTH - P.O. BOX 868 - NASHUA NH 03061-0868 - UNITED STATES - - 00-40-58 (hex) KRONOS, INC. - 004058 (base 16) KRONOS, INC. - 400 FIFTH AVENUE - WALTHAM MA 02154 - UNITED STATES - - 00-40-59 (hex) YOSHIDA KOGYO K. K. - 004059 (base 16) YOSHIDA KOGYO K. K. - TECHNICAL RESEARCH DEPT. - 200 YOSHIDA KUROBE CITY TOYAMA PREF. - 939 - JAPAN - - 00-40-5A (hex) GOLDSTAR INFORMATION & COMM. - 00405A (base 16) GOLDSTAR INFORMATION & COMM. - 533, HOGAE-DONG, ANYANG-SHI - KYONGKI-DO 430-080 - KOREA - KOREA, REPUBLIC OF - - 00-40-5B (hex) FUNASSET LIMITED - 00405B (base 16) FUNASSET LIMITED - ORCHARDS, 14 TOWNSEND - SOMERSET TA19 OAU ILMINSTER - UNITED KINGDOM - UNITED KINGDOM - - 00-40-5C (hex) FUTURE SYSTEMS, INC. - 00405C (base 16) FUTURE SYSTEMS, INC. - ROOM 102 DONG BANG B/D, - YEOG SAM-DONG 740-5, KANG NAM-KU - SEOUL 130-080 SEOUL 130-080 KOREA - KOREA, REPUBLIC OF - - 00-40-5D (hex) STAR-TEK, INC. - 00405D (base 16) STAR-TEK, INC. - 71 LYMAN STREET - NORTHBORO MA 01532 - UNITED STATES - - 00-40-5E (hex) NORTH HILLS ISRAEL - 00405E (base 16) NORTH HILLS ISRAEL - P.O. BOX 1280 - YOKNEAM 20692 - ISRAEL - - 00-40-5F (hex) AFE COMPUTERS LTD. - 00405F (base 16) AFE COMPUTERS LTD. - 62 ANCHORAGE ROAD - SUTTON COLDFIELD WEST MIDLANDS B74 2PG - UNITED KINGDOM - UNITED KINGDOM - - 00-40-60 (hex) COMENDEC LTD - 004060 (base 16) COMENDEC LTD - ENTERPRISE WAY, - ASTON SCIENCE PARK, ASTON TRIANGLE - BIRMINGHAM BIRMINGHAM ENGLAND - UNITED KINGDOM - - 00-40-61 (hex) DATATECH ENTERPRISES CO., LTD. - 004061 (base 16) DATATECH ENTERPRISES CO., LTD. - (LIN KOU INDUSTRIAL ZONE SEC,4 - 27, HSI-SHIH LAKE ROAD KUEI-SHAN HSIANG - TAOYUAN COUNTY TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-40-62 (hex) E-SYSTEMS, INC./GARLAND DIV. - 004062 (base 16) E-SYSTEMS, INC./GARLAND DIV. - P.O. BOX 660023 - MAIL STOP 63000 - DALLAS TX 75266-0023 - UNITED STATES - - 00-40-63 (hex) VIA TECHNOLOGIES, INC. - 004063 (base 16) VIA TECHNOLOGIES, INC. - 5020 BRANDIN COURT - FREMONT CA 94538 - UNITED STATES - - 00-40-64 (hex) KLA INSTRUMENTS CORPORATION - 004064 (base 16) KLA INSTRUMENTS CORPORATION - 160 RIO ROBLES - SAN JOSE CA 95161-9055 - UNITED STATES - - 00-40-65 (hex) GTE SPACENET - 004065 (base 16) GTE SPACENET - 1700 OLD MEADOW ROAD - MCLEAN VA 22102 - UNITED STATES - - 00-40-66 (hex) Hitachi Metals, Ltd. - 004066 (base 16) Hitachi Metals, Ltd. - 880 ISAGOZAWA-CHO - HITACHI-SHI IBARAKI-KEN - 319-1418 - JAPAN - - 00-40-67 (hex) OMNIBYTE CORPORATION - 004067 (base 16) OMNIBYTE CORPORATION - 245 WEST ROOSEVELT ROAD - WEST CHICAGO IL 60185 - UNITED STATES - - 00-40-68 (hex) EXTENDED SYSTEMS - 004068 (base 16) EXTENDED SYSTEMS - 6123 NORTH MEEKER AVENUE - BOISE ID 83704 - UNITED STATES - - 00-40-69 (hex) LEMCOM SYSTEMS, INC. - 004069 (base 16) LEMCOM SYSTEMS, INC. - 2104 WEST PEORIA AVENUE - PHOENIX AZ 85029 - UNITED STATES - - 00-40-6A (hex) KENTEK INFORMATION SYSTEMS,INC - 00406A (base 16) KENTEK INFORMATION SYSTEMS,INC - 2945 WILDERNESS PLACE - BOULDER CO 80301 - UNITED STATES - - 00-40-6B (hex) SYSGEN - 00406B (base 16) SYSGEN - 556 GIBRALTAR DRIVE - MILPITAS CA 95035 - UNITED STATES - - 00-40-6C (hex) COPERNIQUE - 00406C (base 16) COPERNIQUE - 6, MAIL DE L'EUROPE BP 25 - 78170 LA CELLE-SAINT-CLOUD - FRANCE - - 00-40-6D (hex) LANCO, INC. - 00406D (base 16) LANCO, INC. - 800 WEST AIRPORT FREEWAY - SUITE #1100 - IRVING TX 75062 - UNITED STATES - - 00-40-6E (hex) COROLLARY, INC. - 00406E (base 16) COROLLARY, INC. - 2802 KELVIN - IRVINE CA 92714 - UNITED STATES - - 00-40-6F (hex) SYNC RESEARCH INC. - 00406F (base 16) SYNC RESEARCH INC. - 7 STUDEBAKER - IRVINE CA 92718 - UNITED STATES - - 00-40-70 (hex) INTERWARE CO., LTD. - 004070 (base 16) INTERWARE CO., LTD. - 7F KUDAN NEW CENTRAL BLDG., - 1-4-5 KUDAN-KITA, CHIYODA-KU - TOKYO 102 TOKYO 102 - JAPAN - - 00-40-71 (hex) ATM COMPUTER GMBH - 004071 (base 16) ATM COMPUTER GMBH - BUCKLESTR. 1-5,POSTFACH 101043 - D7750 KONSTANZ - GERMANY - - 00-40-72 (hex) Applied Innovation Inc. - 004072 (base 16) Applied Innovation Inc. - 5800 Innovation Drive - Dublin OH 43016-3271 - UNITED STATES - - 00-40-73 (hex) BASS ASSOCIATES - 004073 (base 16) BASS ASSOCIATES - 435 TASSO STREET, STE. #325 - PALO ALTO CA 94301 - UNITED STATES - - 00-40-74 (hex) CABLE AND WIRELESS - 004074 (base 16) CABLE AND WIRELESS - COMMUNICATIONS, INC. - 1919 GALLOWS ROAD - VIENNA VA 22182-3964 - UNITED STATES - - 00-40-75 (hex) Tattile SRL - 004075 (base 16) Tattile SRL - 11-12 NORTHFIELD PROSPECT - PUTNEY BRIDGE ROAD LONDON SW18 1HR - UNITED KINGDOM - UNITED KINGDOM - - 00-40-76 (hex) Sun Conversion Technologies - 004076 (base 16) Sun Conversion Technologies - 100 Commerce Boulevard - Quakertown PA 78951-2237 - UNITED STATES - - 00-40-77 (hex) MAXTON TECHNOLOGY CORPORATION - 004077 (base 16) MAXTON TECHNOLOGY CORPORATION - 4FK, 249, SEC. 3, - CHUNG HSIAO E. RD., TAIPEI - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-40-78 (hex) WEARNES AUTOMATION PTE LTD - 004078 (base 16) WEARNES AUTOMATION PTE LTD - 801 LORONG 7, TOA PAYOH - SINGAPORE 1231 - SINGAPORE - - 00-40-79 (hex) JUKO MANUFACTURE COMPANY, LTD. - 004079 (base 16) JUKO MANUFACTURE COMPANY, LTD. - FLAT C, 3RD FLOOR, CDW BLDG. - 388 CASTLE PEAK ROAD, TSUEN WAN, N.T. - HONG KONG - HONG KONG - - 00-40-7A (hex) SOCIETE D'EXPLOITATION DU CNIT - 00407A (base 16) SOCIETE D'EXPLOITATION DU CNIT - 2 GLACE DE LA DEFENSE 92053 - PARIS-LA-DEFENSE - FRANCE - - 00-40-7B (hex) SCIENTIFIC ATLANTA - 00407B (base 16) SCIENTIFIC ATLANTA - Information Technology - 4311 Communications Drive Mail Code: 30 - Norcross GA 30091-6850 - UNITED STATES - - 00-40-7C (hex) QUME CORPORATION - 00407C (base 16) QUME CORPORATION - 500 YOSEMITE DRIVE, M/S-29 - MILPITAS CA 95035-5426 - UNITED STATES - - 00-40-7D (hex) EXTENSION TECHNOLOGY CORP. - 00407D (base 16) EXTENSION TECHNOLOGY CORP. - 30 HOLLIS STREET - FRAMINGHAM MA 01701 - UNITED STATES - - 00-40-7E (hex) EVERGREEN SYSTEMS, INC. - 00407E (base 16) EVERGREEN SYSTEMS, INC. - 120 LANDING COURT-SUITE - NOVATO CA 94945 - UNITED STATES - - 00-40-7F (hex) FLIR Systems - 00407F (base 16) FLIR Systems - BOX 3 - 182-11 DANDERYD - SWEDEN - - 00-40-80 (hex) ATHENIX CORPORATION - 004080 (base 16) ATHENIX CORPORATION - 675 ALMANOR AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-40-81 (hex) MANNESMANN SCANGRAPHIC GMBH - 004081 (base 16) MANNESMANN SCANGRAPHIC GMBH - RISSENER STRASSE 112-114 - W-2000 WEDEL - GERMANY - - 00-40-82 (hex) LABORATORY EQUIPMENT CORP. - 004082 (base 16) LABORATORY EQUIPMENT CORP. - 1-7-3 MINATOMACHI - TUCHIURA-CITY IBARAGI-KEN, - 300 - JAPAN - - 00-40-83 (hex) TDA INDUSTRIA DE PRODUTOS - 004083 (base 16) TDA INDUSTRIA DE PRODUTOS - ELETRONICOS S.A. - RUE AGOSTINO TOGNERI, 92 04690 - SAO PAU - BRAZIL - - 00-40-84 (hex) HONEYWELL ACS - 004084 (base 16) HONEYWELL ACS - - 512 Virginia Drive - Fort Washington PA 19034 - UNITED STATES - - 00-40-85 (hex) SAAB INSTRUMENTS AB - 004085 (base 16) SAAB INSTRUMENTS AB - P.O. BOX 1017 - S-551 11 JONKOPING - SWEDEN - - 00-40-86 (hex) MICHELS & KLEBERHOFF COMPUTER - 004086 (base 16) MICHELS & KLEBERHOFF COMPUTER - GATHE 117 - 5600 WUPPERTAL 1 - GERMANY - - 00-40-87 (hex) UBITREX CORPORATION - 004087 (base 16) UBITREX CORPORATION - 19TH FLOOR, 155 CARLTON STREET - WINNIPEG, MANITOBA - CANADA R3C 3H8 - CANADA - - 00-40-88 (hex) MOBIUS TECHNOLOGIES, INC. - 004088 (base 16) MOBIUS TECHNOLOGIES, INC. - 5835 DOYLE STREET - EMERYVILLE CA 94608 - UNITED STATES - - 00-40-89 (hex) MEIDENSHA CORPORATION - 004089 (base 16) MEIDENSHA CORPORATION - FACTORY NO.4, 515 KAMINAKAMIZO - HIGASHI MAKADO NUMAZU-CITY SHIZUOKA-PREF - JAPAN - - 00-40-8A (hex) TPS TELEPROCESSING SYS. GMBH - 00408A (base 16) TPS TELEPROCESSING SYS. GMBH - SCHWADERMUCHLSTRASSE 4-8 - W-8501 CADOLZBURG - GERMANY - - 00-40-8B (hex) RAYLAN CORPORATION - 00408B (base 16) RAYLAN CORPORATION - 120 INDEPENDENCE DRIVE - MENLO PARK CA 94025 - UNITED STATES - - 00-40-8C (hex) AXIS COMMUNICATIONS AB - 00408C (base 16) AXIS COMMUNICATIONS AB - SCHEELEVAGEN 16 - S-223 70 LUND - SWEDEN - - 00-40-8D (hex) THE GOODYEAR TIRE & RUBBER CO. - 00408D (base 16) THE GOODYEAR TIRE & RUBBER CO. - 1144 EAST MARKET STREET - AKRON OH 44316 - UNITED STATES - - 00-40-8E (hex) Tattile SRL - 00408E (base 16) Tattile SRL - 2360 MARYLAND ROAD - WILLOW GROVE PA 19090 - UNITED STATES - - 00-40-8F (hex) WM-DATA MINFO AB - 00408F (base 16) WM-DATA MINFO AB - OLOF ASKLUNDS GATA 14 - BOX 2065 421 02 GOTEBORG - SWEDEN - - 00-40-90 (hex) ANSEL COMMUNICATIONS - 004090 (base 16) ANSEL COMMUNICATIONS - 1701 JUNCTION COURT - SAN JOSE CA 95112 - UNITED STATES - - 00-40-91 (hex) PROCOMP INDUSTRIA ELETRONICA - 004091 (base 16) PROCOMP INDUSTRIA ELETRONICA - AV. KENKITI SIMOMOTO, 767 - 05347 - SAO PAULO / SP - BRAZIL - - 00-40-92 (hex) ASP COMPUTER PRODUCTS, INC. - 004092 (base 16) ASP COMPUTER PRODUCTS, INC. - 160 SAN GABRIEL DRIVE - SUNNYVALE CA 94086 - UNITED STATES - - 00-40-93 (hex) PAXDATA NETWORKS LTD. - 004093 (base 16) PAXDATA NETWORKS LTD. - COMMUNICATIONS HOUSE, - FROGMORE ROAD HEMEL HEMPSTEAD, HERTS HP3 - ENGLAND - UNITED KINGDOM - - 00-40-94 (hex) SHOGRAPHICS, INC. - 004094 (base 16) SHOGRAPHICS, INC. - 1890 N. SHORELINE BLVD. - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-40-95 (hex) R.P.T. INTERGROUPS INT'L LTD. - 004095 (base 16) R.P.T. INTERGROUPS INT'L LTD. - 9F, 50 MIN CHUAN RD - HSIN TIEN, TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-40-96 (hex) Cisco Systems - 004096 (base 16) Cisco Systems - 170 W. Tasman Drive - San Jose CA 95134 - UNITED STATES - - 00-40-97 (hex) DATEX DIVISION OF - 004097 (base 16) DATEX DIVISION OF - INSTRUMENTARIUM CORP. - P.O. BOX 446, SF-00101 HELSINKI - FINLAND - - 00-40-98 (hex) DRESSLER GMBH & CO. - 004098 (base 16) DRESSLER GMBH & CO. - KACKERTSTRASSE 10 - D-52072 AACHEN - GERMANY - - 00-40-99 (hex) NEWGEN SYSTEMS CORP. - 004099 (base 16) NEWGEN SYSTEMS CORP. - 17580 NEWHOPE STREET - FOUNTAIN VALLEY CA 92708 - UNITED STATES - - 00-40-9A (hex) NETWORK EXPRESS, INC. - 00409A (base 16) NETWORK EXPRESS, INC. - 2200 GREEN ROAD - STE - ANN ARBOR MI 48170 - UNITED STATES - - 00-40-9B (hex) HAL COMPUTER SYSTEMS INC. - 00409B (base 16) HAL COMPUTER SYSTEMS INC. - 1315 DELL AVENUE - CAMPBELL CA 95008 - UNITED STATES - - 00-40-9C (hex) TRANSWARE - 00409C (base 16) TRANSWARE - 21, RUE DU 8 MAI 1945 - 941107 ARCUEIL - FRANCE - - 00-40-9D (hex) DIGIBOARD, INC. - 00409D (base 16) DIGIBOARD, INC. - 6400 FLYING CLOUD DRIVE - EDEN PRAIRIE MN 55344 - UNITED STATES - - 00-40-9E (hex) CONCURRENT TECHNOLOGIES LTD. - 00409E (base 16) CONCURRENT TECHNOLOGIES LTD. - 654 THE CRESCENT - COLCHESTER BUSINESS PARK COLCHESTER, ESS - UNITED KINGDOM - UNITED KINGDOM - - 00-40-9F (hex) Telco Systems, Inc. - 00409F (base 16) Telco Systems, Inc. - 15 Berkshire Road - Mansfield, MA 02048 - UNITED STATES - - 00-40-A0 (hex) GOLDSTAR CO., LTD. - 0040A0 (base 16) GOLDSTAR CO., LTD. - 6 GA 3B MUNLAE YEONGDEUNGPO - SEOUL - KOREA - KOREA, REPUBLIC OF - - 00-40-A1 (hex) ERGO COMPUTING - 0040A1 (base 16) ERGO COMPUTING - ONE INTERCONTINENTAL WAY - PEABODY MA 01960 - UNITED STATES - - 00-40-A2 (hex) KINGSTAR TECHNOLOGY INC. - 0040A2 (base 16) KINGSTAR TECHNOLOGY INC. - 1-3F, NO. 185, SEC. 3, - CHENG TEH ROAD - TAIPEI TAIWAN, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-40-A3 (hex) MICROUNITY SYSTEMS ENGINEERING - 0040A3 (base 16) MICROUNITY SYSTEMS ENGINEERING - 255 CASPIAN DRIVE - SUNNYVALE CA 94089-1015 - UNITED STATES - - 00-40-A4 (hex) ROSE ELECTRONICS - 0040A4 (base 16) ROSE ELECTRONICS - P.O. BOX 742571 - HOUSTON TX 77274-2571 - UNITED STATES - - 00-40-A5 (hex) CLINICOMP INTL. - 0040A5 (base 16) CLINICOMP INTL. - 4510 EXECCUTIVE DRIVE-STE.#200 - SAN DIEGO CA 92121 - UNITED STATES - - 00-40-A6 (hex) Cray, Inc. - 0040A6 (base 16) Cray, Inc. - 655F LONE OAK DRIVE - EAGAN MN 55121 - UNITED STATES - - 00-40-A7 (hex) ITAUTEC PHILCO S.A. - 0040A7 (base 16) ITAUTEC PHILCO S.A. - GRUPO ITAUTEC PHILCO - RUA SANTA CATARINA, 1 03086-020 SAO PAUL - BRAZIL - - 00-40-A8 (hex) IMF INTERNATIONAL LTD. - 0040A8 (base 16) IMF INTERNATIONAL LTD. - NO.5 2/F KINGSFORD IND. CENTRE - 13 WANG HOI ROAD KOWLOON BAY, KOWLOON - HONG KONG - HONG KONG - - 00-40-A9 (hex) DATACOM INC. - 0040A9 (base 16) DATACOM INC. - 146 HIGHWAY ROUTE 34 - STE 250 - HOLMDEL NJ 07733 - UNITED STATES - - 00-40-AA (hex) Metso Automation - 0040AA (base 16) Metso Automation - P.O. BOX 237 - SF-33101 TAMPERE - FINLAND - - 00-40-AB (hex) ROLAND DG CORPORATION - 0040AB (base 16) ROLAND DG CORPORATION - 1227 OKUBO-CHO, HAMAMATSU-SHI - SHIZUOKA-KEN - 432 - JAPAN - - 00-40-AC (hex) SUPER WORKSTATION, INC. - 0040AC (base 16) SUPER WORKSTATION, INC. - 2190 PARAGON DRIVE - SAN JOSE CA 95131 - UNITED STATES - - 00-40-AD (hex) SMA REGELSYSTEME GMBH - 0040AD (base 16) SMA REGELSYSTEME GMBH - HANNOVERSCHE STR. 1-5 - D 3501 NIESTETAL - GERMANY - - 00-40-AE (hex) DELTA CONTROLS, INC. - 0040AE (base 16) DELTA CONTROLS, INC. - 13520 78TH AVENUE - SURREY, B.C. - CANADA V3W 8J6 - CANADA - - 00-40-AF (hex) DIGITAL PRODUCTS, INC. - 0040AF (base 16) DIGITAL PRODUCTS, INC. - 411 WAVERLY OAKS ROAD - WALTHAM MA 02154 - UNITED STATES - - 00-40-B0 (hex) BYTEX CORPORATION, ENGINEERING - 0040B0 (base 16) BYTEX CORPORATION, ENGINEERING - 13873 PARK CENTER ROAD - HERNDON VA 22071 - UNITED STATES - - 00-40-B1 (hex) CODONICS INC. - 0040B1 (base 16) CODONICS INC. - 17991 ENGLEWOOD DRIVE - MIDDLEBURG HTS OH 44130 - UNITED STATES - - 00-40-B2 (hex) SYSTEMFORSCHUNG - 0040B2 (base 16) SYSTEMFORSCHUNG - KONIGSTRASSE 33A - 5300 BONN 1 - GERMANY - - 00-40-B3 (hex) ParTech Inc. - 0040B3 (base 16) ParTech Inc. - 8383 Seneca Turnpike - NEW HARTFORD NY 13413 - UNITED STATES - - 00-40-B4 (hex) NEXTCOM K.K. - 0040B4 (base 16) NEXTCOM K.K. - 1-12-1 SHIBUYA - SHIBUYA-KU, TOKYO, 150 - JAPAN - - 00-40-B5 (hex) VIDEO TECHNOLOGY COMPUTERS LTD - 0040B5 (base 16) VIDEO TECHNOLOGY COMPUTERS LTD - 33/F., BLOCK #1, - TAI PING INDUSTRIAL CENTER 57 TING KOK R - N.T. HONG KONG - HONG KONG - - 00-40-B6 (hex) COMPUTERM CORPORATION - 0040B6 (base 16) COMPUTERM CORPORATION - 111 WOOD STREET - PITTSBURGH PA 15222 - UNITED STATES - - 00-40-B7 (hex) STEALTH COMPUTER SYSTEMS - 0040B7 (base 16) STEALTH COMPUTER SYSTEMS - 2341 REGINA CT. - SANTA CLARA CA 95054 - UNITED STATES - - 00-40-B8 (hex) IDEA ASSOCIATES - 0040B8 (base 16) IDEA ASSOCIATES - 29 DUNHAM ROAD - BILLERICA MA 01821 - UNITED STATES - - 00-40-B9 (hex) MACQ ELECTRONIQUE SA - 0040B9 (base 16) MACQ ELECTRONIQUE SA - RUE DE L'AERONEF 2 - B - 1140 BRUSSELS - BELGIUM - - 00-40-BA (hex) ALLIANT COMPUTER SYSTEMS CORP. - 0040BA (base 16) ALLIANT COMPUTER SYSTEMS CORP. - ONE MONARCH DRIVE - LITTLETON MA 01460 - UNITED STATES - - 00-40-BB (hex) GOLDSTAR CABLE CO., LTD. - 0040BB (base 16) GOLDSTAR CABLE CO., LTD. - 555, HOGYE-DONG, ANYANG-SHI - KYUNGKI-DO, 430-080 - KOREA - KOREA, REPUBLIC OF - - 00-40-BC (hex) ALGORITHMICS LTD. - 0040BC (base 16) ALGORITHMICS LTD. - 3 DRAYTON PARK - LONDON N5 1NU - ENGLAND - UNITED KINGDOM - - 00-40-BD (hex) STARLIGHT NETWORKS, INC. - 0040BD (base 16) STARLIGHT NETWORKS, INC. - 444 CASTRO STREET STE - MOUNTAIN VIEW CA 94041 - UNITED STATES - - 00-40-BE (hex) BOEING DEFENSE & SPACE - 0040BE (base 16) BOEING DEFENSE & SPACE - P.O. BOX 3999 - MAIL STOP 88-12 - SEATTLE WA 98124-2499 - UNITED STATES - - 00-40-BF (hex) CHANNEL SYSTEMS INTERN'L INC. - 0040BF (base 16) CHANNEL SYSTEMS INTERN'L INC. - 93 SO. LA PATERA LANE - SANTA BARBARA CA 93117 - UNITED STATES - - 00-40-C0 (hex) VISTA CONTROLS CORPORATION - 0040C0 (base 16) VISTA CONTROLS CORPORATION - 27825 FREMONT COURT - VALENCIA CA 91355 - UNITED STATES - - 00-40-C1 (hex) BIZERBA-WERKE WILHEIM KRAUT - 0040C1 (base 16) BIZERBA-WERKE WILHEIM KRAUT - GMBH & CO. KG, - WILHELM-KRAUT-STR. 65 P.O. BOX 100164 - D-7460 BALINGEN D-7460 BALINGEN - GERMANY - - 00-40-C2 (hex) APPLIED COMPUTING DEVICES - 0040C2 (base 16) APPLIED COMPUTING DEVICES - ALEPH PARK - 100 SOUTH CAMPUS DRIVE - TERRE HAUTE IN 47802 - UNITED STATES - - 00-40-C3 (hex) FISCHER AND PORTER CO. - 0040C3 (base 16) FISCHER AND PORTER CO. - 125 E. COUNTY LINE ROAD - WARMINSTER PA 18974 - UNITED STATES - - 00-40-C4 (hex) KINKEI SYSTEM CORPORATION - 0040C4 (base 16) KINKEI SYSTEM CORPORATION - 1-22-17, KAMIKITA, HIRANOKU - OSAKA, 547 - JAPAN - - 00-40-C5 (hex) MICOM COMMUNICATIONS INC. - 0040C5 (base 16) MICOM COMMUNICATIONS INC. - 4100 LOS ANGELES AVENUE - SIMI VALLEY CA 93063 - UNITED STATES - - 00-40-C6 (hex) FIBERNET RESEARCH, INC. - 0040C6 (base 16) FIBERNET RESEARCH, INC. - 1 TARA BOULEVARD-#405 - NASHUA NH 03062 - UNITED STATES - - 00-40-C7 (hex) RUBY TECH CORPORATION - 0040C7 (base 16) RUBY TECH CORPORATION - 6F-1, NO.3, LANE 250, - SEC. 5 NANKING E.ROAD - TAIPEI TAIWAN, R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-40-C8 (hex) MILAN TECHNOLOGY CORPORATION - 0040C8 (base 16) MILAN TECHNOLOGY CORPORATION - 894 ROSS DRIVE--STE #105 - SUNNYVALE CA 94089 - UNITED STATES - - 00-40-C9 (hex) NCUBE - 0040C9 (base 16) NCUBE - 919 EAST HILLSDALE BLVD. - SUITE 200 - FOSTER CITY CA 94404 - UNITED STATES - - 00-40-CA (hex) FIRST INTERNAT'L COMPUTER, INC - 0040CA (base 16) FIRST INTERNAT'L COMPUTER, INC - FIC Building - No 300 Yang Guang Street - Neihu Taipei 114 Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-40-CB (hex) LANWAN TECHNOLOGIES - 0040CB (base 16) LANWAN TECHNOLOGIES - 1566 LA PRADERA DRIVE - CAMPBELL CA 95008 - UNITED STATES - - 00-40-CC (hex) SILCOM MANUF'G TECHNOLOGY INC. - 0040CC (base 16) SILCOM MANUF'G TECHNOLOGY INC. - 5620 TIMBERLEA BOULEVARD - MISSISSAUGA, ONTARIO - CANADA L4W 4M6 - CANADA - - 00-40-CD (hex) TERA MICROSYSTEMS, INC. - 0040CD (base 16) TERA MICROSYSTEMS, INC. - 2500 GREAT AMERICA PARKWAY - STE. #250 - SANTA CLARA CA 95054 - UNITED STATES - - 00-40-CE (hex) NET-SOURCE, INC. - 0040CE (base 16) NET-SOURCE, INC. - 1265 EL CAMINO REAL - SUITE 101 - SANTA CLARA CA 95050 - UNITED STATES - - 00-40-CF (hex) STRAWBERRY TREE, INC. - 0040CF (base 16) STRAWBERRY TREE, INC. - 160 SOUTH WOLFE ROAD - SUNNYVALE CA 94086 - UNITED STATES - - 00-40-D0 (hex) MITAC INTERNATIONAL CORP. - 0040D0 (base 16) MITAC INTERNATIONAL CORP. - 8TH FL. 585 MING SHENG E. RD. - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-40-D1 (hex) FUKUDA DENSHI CO., LTD. - 0040D1 (base 16) FUKUDA DENSHI CO., LTD. - R & D DEPARTMENT NO. 1 - 35-8, HONGO 2-CHOME, BUNKYO-KU TOKYO 113 - JAPAN - - 00-40-D2 (hex) PAGINE CORPORATION - 0040D2 (base 16) PAGINE CORPORATION - 1961-A CONCOURSE DRIVE - SAN JOSE CA 95131 - UNITED STATES - - 00-40-D3 (hex) KIMPSION INTERNATIONAL CORP. - 0040D3 (base 16) KIMPSION INTERNATIONAL CORP. - 4701 PATRICK HENRY DRIVE - SUITE 401 - SANTA CLARA CA 95054 - UNITED STATES - - 00-40-D4 (hex) GAGE TALKER CORP. - 0040D4 (base 16) GAGE TALKER CORP. - 13680 NE 16TH STREET - BELLEVUE WA 98005 - UNITED STATES - - 00-40-D5 (hex) Sartorius Mechatronics T&H GmbH - 0040D5 (base 16) Sartorius Mechatronics T&H GmbH - WEENDER LANDSTR: 94 - 108 - 3400 GOTTINGEN - GERMANY - - 00-40-D6 (hex) LOCAMATION B.V. - 0040D6 (base 16) LOCAMATION B.V. - POSTBOX 360 - 7500 AJ ENSCHEDE - HOLLAND - NETHERLANDS - - 00-40-D7 (hex) STUDIO GEN INC. - 0040D7 (base 16) STUDIO GEN INC. - 3-12-8 TAKANAWA #202 - MINATOKU, TOKYO 108 - JAPAN - - 00-40-D8 (hex) OCEAN OFFICE AUTOMATION LTD. - 0040D8 (base 16) OCEAN OFFICE AUTOMATION LTD. - 4TH & 5TH FLOOR, KADER BLDG. - 22 KAI CHEUNG ROAD KOWLOON BAY, KOWLOON - HONG KONG - HONG KONG - - 00-40-D9 (hex) AMERICAN MEGATRENDS INC. - 0040D9 (base 16) AMERICAN MEGATRENDS INC. - 6145F N BELT PARKWAY - NORCROSS GA 30071 - UNITED STATES - - 00-40-DA (hex) TELSPEC LTD - 0040DA (base 16) TELSPEC LTD - LANCASTER PARKER ROAD - ROCHESTER AIRPORT, ROCHESTER KENT ME1 3Q - ENGLAND - UNITED KINGDOM - - 00-40-DB (hex) ADVANCED TECHNICAL SOLUTIONS - 0040DB (base 16) ADVANCED TECHNICAL SOLUTIONS - 8050 SEMINOLE OFFICE CENTER - SUITE 210 - SEMINOLE FL 34642 - UNITED STATES - - 00-40-DC (hex) TRITEC ELECTRONIC GMBH - 0040DC (base 16) TRITEC ELECTRONIC GMBH - ROBERT KOCH STR. 35 - D6500 MAINZ 42 - GERMANY - - 00-40-DD (hex) HONG TECHNOLOGIES - 0040DD (base 16) HONG TECHNOLOGIES - 532 WEDDELL DRIVE - SUNNYVALE CA 94089 - UNITED STATES - - 00-40-DE (hex) Elsag Datamat spa - 0040DE (base 16) Elsag Datamat spa - ELSAG S.P.A. - VIA G. PUCCINI, 2 - GENOVA 16154 - ITALY - - 00-40-DF (hex) DIGALOG SYSTEMS, INC. - 0040DF (base 16) DIGALOG SYSTEMS, INC. - 3180 SOUTH 166TH STREET - NEW BERLIN WI 53151 - UNITED STATES - - 00-40-E0 (hex) ATOMWIDE LTD. - 0040E0 (base 16) ATOMWIDE LTD. - 23 THE GREENWAY - ORPINGTON BR5 2AY - UNITED KINGDOM - UNITED KINGDOM - - 00-40-E1 (hex) MARNER INTERNATIONAL, INC. - 0040E1 (base 16) MARNER INTERNATIONAL, INC. - 1617 93RD LANE NE - BLAINE MN 55449 - UNITED STATES - - 00-40-E2 (hex) MESA RIDGE TECHNOLOGIES, INC. - 0040E2 (base 16) MESA RIDGE TECHNOLOGIES, INC. - 6725 MESA RIDGE ROAD-STE#100 - SAN DIEGO CA 92121 - UNITED STATES - - 00-40-E3 (hex) QUIN SYSTEMS LTD - 0040E3 (base 16) QUIN SYSTEMS LTD - OAKLANDS BUSINESS CENTRE - OAKLANDS PARK, WOKINGHAM BERKS RG11 2FD - UNITED KINGDOM - UNITED KINGDOM - - 00-40-E4 (hex) E-M TECHNOLOGY, INC. - 0040E4 (base 16) E-M TECHNOLOGY, INC. - 9245 SOUTHWEST NIMBUS AVE. - BEAVERTON OR 97005 - UNITED STATES - - 00-40-E5 (hex) SYBUS CORPORATION - 0040E5 (base 16) SYBUS CORPORATION - 2300 TALL PINE DRIVE-STE. #100 - LARGO FL 34641 - UNITED STATES - - 00-40-E6 (hex) C.A.E.N. - 0040E6 (base 16) C.A.E.N. - 2, CHEMIN LATERAL - F94290 VILLENEUVE LE ROI - FRANCE - - 00-40-E7 (hex) ARNOS INSTRUMENTS & COMPUTER - 0040E7 (base 16) ARNOS INSTRUMENTS & COMPUTER - SYSTEMS (GROUP) CO., LTD. - 4/F., EUREKA IND. BLDG., 1-17 SAI LAU KO - TSUEN WAN N.T. - HONG KONG - - 00-40-E8 (hex) CHARLES RIVER DATA SYSTEMS,INC - 0040E8 (base 16) CHARLES RIVER DATA SYSTEMS,INC - 983 CONCORD STREET - FRAMINGHAM MA 01701 - UNITED STATES - - 00-40-E9 (hex) ACCORD SYSTEMS, INC. - 0040E9 (base 16) ACCORD SYSTEMS, INC. - 572 VALLEY WAY - MILPITAS CA 95035 - UNITED STATES - - 00-40-EA (hex) PLAIN TREE SYSTEMS INC - 0040EA (base 16) PLAIN TREE SYSTEMS INC - CHIEF EXECTUVIE OFFICER - 59 IBER ROAD, STITTSVILLE ONTARIO K2S 1E - CANADA - - 00-40-EB (hex) MARTIN MARIETTA CORPORATION - 0040EB (base 16) MARTIN MARIETTA CORPORATION - 12506 LAKE UNDERHILL - ORLANDO FL 32825 - UNITED STATES - - 00-40-EC (hex) MIKASA SYSTEM ENGINEERING - 0040EC (base 16) MIKASA SYSTEM ENGINEERING - CO., LTD. - 1-3-10, MINAMI-SHINMACHI, CHUO-KU, OSAKA - JAPAN - - 00-40-ED (hex) NETWORK CONTROLS INT'NATL INC. - 0040ED (base 16) NETWORK CONTROLS INT'NATL INC. - 9 WOODLAWN GREEN - CHARLOTTE NC 28217 - UNITED STATES - - 00-40-EE (hex) OPTIMEM - 0040EE (base 16) OPTIMEM - 297 N. BERNARDO AVENUE - MOUNTAIN VIEW CA 94043-5205 - UNITED STATES - - 00-40-EF (hex) HYPERCOM, INC. - 0040EF (base 16) HYPERCOM, INC. - 2851 WEST KATHLEEN ROAD - PHOENIX AZ 85023 - UNITED STATES - - 00-40-F0 (hex) MicroBrain,Inc. - 0040F0 (base 16) MicroBrain,Inc. - Yuzan Bldg. 4F, - 205,Kibutake,Nagakuteâ€Cho, - Aichi-gun AICHI 480-1117 - JAPAN - - 00-40-F1 (hex) CHUO ELECTRONICS CO., LTD. - 0040F1 (base 16) CHUO ELECTRONICS CO., LTD. - 1-9-9, MOTOHONGO-CHO - HACHIOJI-SHI TOKYO 192 - JAPAN - - 00-40-F2 (hex) JANICH & KLASS COMPUTERTECHNIK - 0040F2 (base 16) JANICH & KLASS COMPUTERTECHNIK - ZUM ALTEN ZOLLHAUS 20 - W-5600 WUPPERTAL 2 - GERMANY - - 00-40-F3 (hex) NETCOR - 0040F3 (base 16) NETCOR - 850 AUBURN COURT - FREMONT CA 94538 - UNITED STATES - - 00-40-F4 (hex) CAMEO COMMUNICATIONS, INC. - 0040F4 (base 16) CAMEO COMMUNICATIONS, INC. - 71 SPITBROOK ROAD, STE #410 - NASHUA NH 030603 - UNITED STATES - - 00-40-F5 (hex) OEM ENGINES - 0040F5 (base 16) OEM ENGINES - 1190 DELL AVENUE, STE. - CAMPBELL CA 95008 - UNITED STATES - - 00-40-F6 (hex) KATRON COMPUTERS INC. - 0040F6 (base 16) KATRON COMPUTERS INC. - 4 FL. NO. 2, ALLEY 23 - LANE 91 SEC. 1 NEI HU ROAD - TAIPEI TAIPEI TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-40-F7 (hex) Polaroid Corporation - 0040F7 (base 16) Polaroid Corporation - 300 Baker Avenue - Concord MA 01742 - UNITED STATES - - 00-40-F8 (hex) SYSTEMHAUS DISCOM - 0040F8 (base 16) SYSTEMHAUS DISCOM - DISTRIBUTED COMPUTING GMBH - ROERMONDERSTR. 615 D-5100 AACHEN - GERMANY - - 00-40-F9 (hex) COMBINET - 0040F9 (base 16) COMBINET - 333 W. EL CAMINO REAL-STE#310 - SUNNYVALE CA 94087 - UNITED STATES - - 00-40-FA (hex) MICROBOARDS, INC. - 0040FA (base 16) MICROBOARDS, INC. - 31-8, TAKASECHO,FUNABASHI-CITY - CHIBA 273 CHIBA 273 - JAPAN - - 00-40-FB (hex) CASCADE COMMUNICATIONS CORP. - 0040FB (base 16) CASCADE COMMUNICATIONS CORP. - PRODUCTION QUALITY ENGINEER - 239 LITTLETON ROAD-UNIT 4A - WESTFORD MA 01886 - UNITED STATES - - 00-40-FC (hex) IBR COMPUTER TECHNIK GMBH - 0040FC (base 16) IBR COMPUTER TECHNIK GMBH - FRANKFURTER STR. 114 - D 6056 HEUSENSTAMM - WEST - GERMANY - - 00-40-FD (hex) LXE - 0040FD (base 16) LXE - 303 RESEARCH DRIVE - NORCROSS GA 30092 - UNITED STATES - - 00-40-FE (hex) SYMPLEX COMMUNICATIONS - 0040FE (base 16) SYMPLEX COMMUNICATIONS - 5 RESEARCH DRIVE - ANN ARBOR MI 48103 - UNITED STATES - - 00-40-FF (hex) TELEBIT CORPORATION - 0040FF (base 16) TELEBIT CORPORATION - 1315 CHESAPEAKE TERRACE - SUNNYVALE CA 94089-1100 - UNITED STATES - - 00-41-B4 (hex) Wuxi Zhongxing Optoelectronics Technology Co.,Ltd. - 0041B4 (base 16) Wuxi Zhongxing Optoelectronics Technology Co.,Ltd. - Block 93-C, Sci. & Tech. Industry park, - New district. - Wuxi Jiangsu 214028 - CHINA - - 00-42-52 (hex) RLX Technologies - 004252 (base 16) RLX Technologies - 25231 Grograns Mill Rd - Suite 600 - The Woodlands Tx 77380 - UNITED STATES - - 00-43-FF (hex) KETRON S.R.L. - 0043FF (base 16) KETRON S.R.L. - Via Giuseppe Taliercio n. 7 - Ancona 60131 - ITALY - - 00-45-01 (hex) Versus Technology, Inc. - 004501 (base 16) Versus Technology, Inc. - 2600 Miller Creek Road - Traverse City MI 49684 - UNITED STATES - - 00-46-4B (hex) HUAWEI TECHNOLOGIES CO.,LTD - 00464B (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 00-4D-32 (hex) Andon Health Co.,Ltd. - 004D32 (base 16) Andon Health Co.,Ltd. - NO.3Jin PIng Road Ya An Street - Nankai District - Tianjin 300190 - CHINA - - 00-50-00 (hex) NEXO COMMUNICATIONS, INC. - 005000 (base 16) NEXO COMMUNICATIONS, INC. - 2ND FL., 160, MINGCHU ROAD - HSINCHU CITY - TAIWAN, PROVINCE OF CHINA - - 00-50-01 (hex) YAMASHITA SYSTEMS CORP. - 005001 (base 16) YAMASHITA SYSTEMS CORP. - 5-7-12 IKEGAMI - OTA-KU TOKYO - JAPAN - - 00-50-02 (hex) OMNISEC AG - 005002 (base 16) OMNISEC AG - RIETSTRASSE 14 - CH-8108 DAELLIKON - SWITZERLAND - - 00-50-03 (hex) Xrite Inc - 005003 (base 16) Xrite Inc - 4300 44TH Street, S.E. - Grand Rapids MI 49512 - UNITED STATES - - 00-50-04 (hex) 3COM CORPORATION - 005004 (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - SANTA CLARA CA 95052 - UNITED STATES - - 00-50-06 (hex) TAC AB - 005006 (base 16) TAC AB - JAGERSHILLGATON 18 - 21375 MALMO - SWEDEN - - 00-50-07 (hex) SIEMENS TELECOMMUNICATION SYSTEMS LIMITED - 005007 (base 16) SIEMENS TELECOMMUNICATION SYSTEMS LIMITED - NO. 90, SEC. 1, CHIEN KUO NORTH ROAD - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-50-08 (hex) TIVA MICROCOMPUTER CORP. (TMC) - 005008 (base 16) TIVA MICROCOMPUTER CORP. (TMC) - 48550 FREMONT BLVD. - FREMONT CA 94538 - UNITED STATES - - 00-50-09 (hex) PHILIPS BROADBAND NETWORKS - 005009 (base 16) PHILIPS BROADBAND NETWORKS - 64 PERIMETER CENTRE EAST - ATLANTA GA 30346 - UNITED STATES - - 00-50-0A (hex) IRIS TECHNOLOGIES, INC. - 00500A (base 16) IRIS TECHNOLOGIES, INC. - WESTMORELAND INDUSRIAL PARK - R.R. 12 BOX 36 - GREENSBURG PA 15601 - UNITED STATES - - 00-50-0B (hex) CISCO SYSTEMS, INC. - 00500B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-0C (hex) e-Tek Labs, Inc. - 00500C (base 16) e-Tek Labs, Inc. - 1057 EAST HENRIETTA RD. - ROCHESTER NY 14623 - UNITED STATES - - 00-50-0D (hex) SATORI ELECTORIC CO., LTD. - 00500D (base 16) SATORI ELECTORIC CO., LTD. - TIGUSADAI 38-8 MIDORI-KU - YOKOHAMA, KANAGAWA - JAPAN - - 00-50-0E (hex) CHROMATIS NETWORKS, INC. - 00500E (base 16) CHROMATIS NETWORKS, INC. - 3 BETHESDA METRO CENTER - BETHESDA MD 20814 - UNITED STATES - - 00-50-0F (hex) CISCO SYSTEMS, INC. - 00500F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-10 (hex) NovaNET Learning, Inc. - 005010 (base 16) NovaNET Learning, Inc. - 125 W. CHURCH STREET-STE. #300 - CHAMPAIGN IL 61820 - UNITED STATES - - 00-50-12 (hex) CBL - GMBH - 005012 (base 16) CBL - GMBH - DARMSTAEDTER STR. 81 - D-64839 MUENSTER - GERMANY - - 00-50-13 (hex) Chaparral Network Storage - 005013 (base 16) Chaparral Network Storage - 7420 E. Dry Creek Parkway - Longmont CO 80503 - UNITED STATES - - 00-50-14 (hex) CISCO SYSTEMS, INC. - 005014 (base 16) CISCO SYSTEMS, INC. - M/S/ SJA-2 - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-15 (hex) BRIGHT STAR ENGINEERING - 005015 (base 16) BRIGHT STAR ENGINEERING - 19 ENFIELD DRIVE - ANDOVER MA 01810 - UNITED STATES - - 00-50-16 (hex) SST/WOODHEAD INDUSTRIES - 005016 (base 16) SST/WOODHEAD INDUSTRIES - 50 NORTHLAND ROAD - WATERLOO - ONTARIO N2V 1N3 - CANADA - - 00-50-17 (hex) RSR S.R.L. - 005017 (base 16) RSR S.R.L. - VIA SINIGAGLIA, 38 - LURATE CACCIVIO (CO) - 22075 - ITALY - - 00-50-18 (hex) AMIT, Inc. - 005018 (base 16) AMIT, Inc. - No.32, Huangong Rd., - Yongkang City, Tainan County 71041 - TAIWAN, PROVINCE OF CHINA - - 00-50-19 (hex) SPRING TIDE NETWORKS, INC. - 005019 (base 16) SPRING TIDE NETWORKS, INC. - 85 SWANSON ROAD - BOXBOROUGH MA 01719 - UNITED STATES - - 00-50-1A (hex) IQinVision - 00501A (base 16) IQinVision - 33122 Valle Road - San Juan Capistrano CA 92675-4853 - UNITED STATES - - 00-50-1B (hex) ABL CANADA, INC. - 00501B (base 16) ABL CANADA, INC. - 8550 COTE DE LIESSE - ST-LAURENT (QUEBEC) H4T 1H2 - CANADA - - 00-50-1C (hex) JATOM SYSTEMS, INC. - 00501C (base 16) JATOM SYSTEMS, INC. - 99 MICHAEL COWPLAND DRIVE - KANATA - ONTARIO, K2M 1X3 - CANADA - - 00-50-1E (hex) Miranda Technologies, Inc. - 00501E (base 16) Miranda Technologies, Inc. - 3499, Douglas B. Floreani - Saint-Laurent Quebec H4S 2C6 - CANADA - - 00-50-1F (hex) MRG SYSTEMS, LTD. - 00501F (base 16) MRG SYSTEMS, LTD. - WILLOW HOUSE, SLAD ROAD - STROUD - GLOS. GL5 1QG England - UNITED KINGDOM - - 00-50-20 (hex) MEDIASTAR CO., LTD. - 005020 (base 16) MEDIASTAR CO., LTD. - 3FL, SOHUN BLDG. - 951-33 DOGOK-DONG, KANGNAM-KU SEOUL - KOREA - KOREA, REPUBLIC OF - - 00-50-21 (hex) EIS INTERNATIONAL, INC. - 005021 (base 16) EIS INTERNATIONAL, INC. - 1351 WASHINGTON BLVD. - STAMFORD CT 06902 - UNITED STATES - - 00-50-22 (hex) ZONET TECHNOLOGY, INC. - 005022 (base 16) ZONET TECHNOLOGY, INC. - 830 ROOM, BLDG. 53, 195, SEC.4 - CHUNG HSIUNG RD, CHUTUNG - HSINCHA - TAIWAN, PROVINCE OF CHINA - - 00-50-23 (hex) PG DESIGN ELECTRONICS, INC. - 005023 (base 16) PG DESIGN ELECTRONICS, INC. - 48700 STRUCTURAL DRIVE - CHESTERFIELD MI 48051 - UNITED STATES - - 00-50-24 (hex) NAVIC SYSTEMS, INC. - 005024 (base 16) NAVIC SYSTEMS, INC. - 74 CRESCENT STREET - NEEDHAM MA - UNITED STATES - - 00-50-26 (hex) COSYSTEMS, INC. - 005026 (base 16) COSYSTEMS, INC. - 1263 OAKMEAD PARKWAY - SUNNYVALE CA 94086 - UNITED STATES - - 00-50-27 (hex) GENICOM CORPORATION - 005027 (base 16) GENICOM CORPORATION - 900 CLOPPER ROAD - STE. #110 - GAITHERSBURG MD 20878 - UNITED STATES - - 00-50-28 (hex) AVAL COMMUNICATIONS - 005028 (base 16) AVAL COMMUNICATIONS - 1777 NORTH CALIFORNIA BLVD. - WALNUT CREEK CA 94596 - UNITED STATES - - 00-50-29 (hex) 1394 PRINTER WORKING GROUP - 005029 (base 16) 1394 PRINTER WORKING GROUP - P.O. BOX 23158 - SAN JOSE CA 95153 - UNITED STATES - - 00-50-2A (hex) CISCO SYSTEMS, INC. - 00502A (base 16) CISCO SYSTEMS, INC. - M/S SJA-2 - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-2B (hex) GENRAD LTD. - 00502B (base 16) GENRAD LTD. - ORION BUSINESS PARK - BIRDHALL LANE STOCKPORT, CHESHIRE - UNITED KINGDOM SK3 OXG - UNITED KINGDOM - - 00-50-2C (hex) SOYO COMPUTER, INC. - 00502C (base 16) SOYO COMPUTER, INC. - NO. 21 WU-KUNG 5 RD. - HSING CHUANG CITY TAIPEI HSIEN - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-50-2D (hex) ACCEL, INC. - 00502D (base 16) ACCEL, INC. - 1F, NO. 7, R&D 1ST ROAD - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-50-2E (hex) CAMBEX CORPORATION - 00502E (base 16) CAMBEX CORPORATION - 115 Flanders Road - Westborough MA 01581 - UNITED STATES - - 00-50-2F (hex) TollBridge Technologies, Inc. - 00502F (base 16) TollBridge Technologies, Inc. - 872 HERMOSA DRIVE - SUNNYVALE CA 94086 - UNITED STATES - - 00-50-30 (hex) FUTURE PLUS SYSTEMS - 005030 (base 16) FUTURE PLUS SYSTEMS - 36 OLDE ENGLISH RD. - BEDFORD NH 03110 - UNITED STATES - - 00-50-31 (hex) AEROFLEX LABORATORIES, INC. - 005031 (base 16) AEROFLEX LABORATORIES, INC. - 35 SOUTH SERVICE ROAD - PLAINVIEW NY 11803 - UNITED STATES - - 00-50-32 (hex) PICAZO COMMUNICATIONS, INC. - 005032 (base 16) PICAZO COMMUNICATIONS, INC. - 61 DAGGETT DRIVE - SAN JOSE CA 95134 - UNITED STATES - - 00-50-33 (hex) MAYAN NETWORKS - 005033 (base 16) MAYAN NETWORKS - 3350 SCOTT BLVD. - BLDG. #9 - SANTA CLARA CA 95054 - UNITED STATES - - 00-50-36 (hex) NETCAM, LTD. - 005036 (base 16) NETCAM, LTD. - 6071 N. PASEO ZALDIVAR - TUCSON AZ 85750 - UNITED STATES - - 00-50-37 (hex) KOGA ELECTRONICS CO. - 005037 (base 16) KOGA ELECTRONICS CO. - 5-8-10, TEHARA, RITTO-CHO - KURITA GUN - SHIGA, 420-3047 - JAPAN - - 00-50-38 (hex) DAIN TELECOM CO., LTD. - 005038 (base 16) DAIN TELECOM CO., LTD. - 2ND Flr., OH-SUNG BLDG. #2-28 - YANGJAE-DONG, SEOCHO-GU SEOUL - KOREA, REPUBLIC OF - - 00-50-39 (hex) MARINER NETWORKS - 005039 (base 16) MARINER NETWORKS - 1585 S. MANCHESTER AVE. - ANAHEIM CA 92802-2907 - UNITED STATES - - 00-50-3A (hex) DATONG ELECTRONICS LTD. - 00503A (base 16) DATONG ELECTRONICS LTD. - CLAYTON WOOD CLOSE - WEST PARK - Leeds LS16 6QE - UNITED KINGDOM - - 00-50-3B (hex) MEDIAFIRE CORPORATION - 00503B (base 16) MEDIAFIRE CORPORATION - 11317 FREDERICK AVENUE - BELTSVILLE MD 20705 - UNITED STATES - - 00-50-3C (hex) TSINGHUA NOVEL ELECTRONICS - 00503C (base 16) TSINGHUA NOVEL ELECTRONICS - CO., LTD. - ROOM 1205, HUAYE BUILDING TSINGHUA UNIVE - 100084 100084 - CHINA - - 00-50-3E (hex) CISCO SYSTEMS, INC. - 00503E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-3F (hex) ANCHOR GAMES - 00503F (base 16) ANCHOR GAMES - 815 PILOT ROAD, Suite G - LAS VEGAS NV 89119 - UNITED STATES - - 00-50-40 (hex) Panasonic Electric Works Co., Ltd. - 005040 (base 16) Panasonic Electric Works Co., Ltd. - Tsu-Factory, 1668, Fujikata - Tsu-shi Mie-ken 514-8555 - JAPAN - - 00-50-41 (hex) Coretronic Corporation - 005041 (base 16) Coretronic Corporation - NO.11, LI HSIN RD. - SCIENCE-BASED INDUSTRIAL PARK HISNCHU - TAIWAN, PROVINCE OF CHINA - - 00-50-42 (hex) SCI MANUFACTURING SINGAPORE PTE, LTD. - 005042 (base 16) SCI MANUFACTURING SINGAPORE PTE, LTD. - 3 DEPOT CLOSE - SINGAPORE 109840 - SINGAPORE - - 00-50-43 (hex) MARVELL SEMICONDUCTOR, INC. - 005043 (base 16) MARVELL SEMICONDUCTOR, INC. - 645 ALMANOR AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-50-44 (hex) ASACA CORPORATION - 005044 (base 16) ASACA CORPORATION - 420 CORPORATE CIRCLE, Unit H - GOLDEN CO 80401 - UNITED STATES - - 00-50-45 (hex) RIOWORKS SOLUTIONS, INC. - 005045 (base 16) RIOWORKS SOLUTIONS, INC. - 4F, NO.28, LANE 583 - JUI-KWANG ROAD TAIPEI, 11457 - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-50-46 (hex) MENICX INTERNATIONAL CO., LTD. - 005046 (base 16) MENICX INTERNATIONAL CO., LTD. - NO.9, MING TSUN ROAD - CHUTUNG, HSINCHU - TAIWAN 310 TAIWAN 310 R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-50-47 (hex) PRIVATE - 005047 (base 16) - - 00-50-48 (hex) INFOLIBRIA - 005048 (base 16) INFOLIBRIA - 411 WAVERLY OAKS RD-STE #323 - WALTHAM MA 02154-8414 - UNITED STATES - - 00-50-49 (hex) Arbor Networks Inc - 005049 (base 16) Arbor Networks Inc - 6 Omni Way - Chelmsford MA 01824 - UNITED STATES - - 00-50-4A (hex) ELTECO A.S. - 00504A (base 16) ELTECO A.S. - ROSINSKA CESTA P.O. BOX C-9 - 01001 ZILINA - SLOVAKIA - - 00-50-4B (hex) BARCONET N.V. - 00504B (base 16) BARCONET N.V. - LUIPAARDSTRAAT 12 - 8500 KORTRIJK - BELGIUM - - 00-50-4C (hex) Galil Motion Control - 00504C (base 16) Galil Motion Control - 270 Technology Way - Rocklin CA 95765 - UNITED STATES - - 00-50-4D (hex) Tokyo Electron Device Limited - 00504D (base 16) Tokyo Electron Device Limited - 1, Higashikata-machi, Tsuzuki-ku, - Yokohama-shi Kanagawa-ken - JAPAN - - 00-50-4E (hex) SIERRA MONITOR CORP. - 00504E (base 16) SIERRA MONITOR CORP. - 1991 TAROB COURT - MILPITAS CA 95035 - UNITED STATES - - 00-50-4F (hex) OLENCOM ELECTRONICS - 00504F (base 16) OLENCOM ELECTRONICS - SOLTAM INDUSTRIAL PARK - P.O. BOX 196 - YOKNEAM 20692 - ISRAEL - - 00-50-50 (hex) CISCO SYSTEMS, INC. - 005050 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE- SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-51 (hex) IWATSU ELECTRIC CO., LTD. - 005051 (base 16) IWATSU ELECTRIC CO., LTD. - 7-41, KUGAYAMA 1-CHOME - SUGINAMI-KU, TOKYO 168-8501 - JAPAN - - 00-50-52 (hex) TIARA NETWORKS, INC. - 005052 (base 16) TIARA NETWORKS, INC. - 113 FOORIER AVENUE - FREMONT CA 94539 - UNITED STATES - - 00-50-53 (hex) CISCO SYSTEMS, INC. - 005053 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE-SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-54 (hex) CISCO SYSTEMS, INC. - 005054 (base 16) CISCO SYSTEMS, INC. - M/S SJA-2 - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-55 (hex) DOMS A/S - 005055 (base 16) DOMS A/S - FORMERVANGEN 28 - DK-2600 GLOSTRUP - DENMARK - - 00-50-56 (hex) VMware, Inc. - 005056 (base 16) VMware, Inc. - 3401 Hillview Avenue - PALO ALTO CA 94304 - UNITED STATES - - 00-50-57 (hex) BROADBAND ACCESS SYSTEMS - 005057 (base 16) BROADBAND ACCESS SYSTEMS - 48 South Park St #208 - Montclair NJ 07042 - UNITED STATES - - 00-50-58 (hex) VegaStream Group Limted - 005058 (base 16) VegaStream Group Limted - Asmec Centre, Eagle House - The Ring - Bracknell Berkshire RG12 1HB - UNITED KINGDOM - - 00-50-59 (hex) iBAHN - 005059 (base 16) iBAHN - 10757 S. River Front Parkway - Suite 300 - South Jordan UT 84095 - UNITED STATES - - 00-50-5A (hex) NETWORK ALCHEMY, INC. - 00505A (base 16) NETWORK ALCHEMY, INC. - 1521.5 PACIFIC AVENUE - SANTA CRUZ CA 95060 - UNITED STATES - - 00-50-5B (hex) KAWASAKI LSI U.S.A., INC. - 00505B (base 16) KAWASAKI LSI U.S.A., INC. - 2570 NORTHFIRST STREET - SUITE #301 - SAN JOSE CA 95131 - UNITED STATES - - 00-50-5C (hex) TUNDO CORPORATION - 00505C (base 16) TUNDO CORPORATION - 7 GIBOREI ISRAEL STREET - NATANYA 42504 - ISRAEL - - 00-50-5E (hex) DIGITEK MICROLOGIC S.A. - 00505E (base 16) DIGITEK MICROLOGIC S.A. - SANT JOAN DE LA SALLE 6 - E08022 BARCELONA - SPAIN - - 00-50-5F (hex) BRAND INNOVATORS - 00505F (base 16) BRAND INNOVATORS - Steenovenweg 5 - Helmond 5708 HN - NETHERLANDS - - 00-50-60 (hex) TANDBERG TELECOM AS - 005060 (base 16) TANDBERG TELECOM AS - Philip Pedersens vei 20 - 1361 Lysaker - NORWAY - - 00-50-62 (hex) KOUWELL ELECTRONICS CORP. ** - 005062 (base 16) KOUWELL ELECTRONICS CORP. ** - 7F, NO.99, NAN-KANG ROAD - SEC. 3, TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-50-63 (hex) OY COMSEL SYSTEM AB - 005063 (base 16) OY COMSEL SYSTEM AB - TEGELBRUKSGATAN 5-7 - FIN-65100 VASA - FINLAND - - 00-50-64 (hex) CAE ELECTRONICS - 005064 (base 16) CAE ELECTRONICS - P.O. BOX 1800 - ST. LAURENT, QUEBEC H4L 4X4 - CANADA - - 00-50-65 (hex) TDK-Lambda Corporation - 005065 (base 16) TDK-Lambda Corporation - 36-1 Kasuminosato - Ami-Machi Inashiki-Gun Ibaraki, 300-0396 - JAPAN - - 00-50-66 (hex) AtecoM GmbH advanced telecomunication modules - 005066 (base 16) AtecoM GmbH advanced telecomunication modules - KAISERSTR. 100 - D-52134 HERZOGENRATH - GERMANY - - 00-50-67 (hex) AEROCOMM, INC. - 005067 (base 16) AEROCOMM, INC. - 13256 W. 98TH STREET - LENEXA KS 66215 - UNITED STATES - - 00-50-68 (hex) ELECTRONIC INDUSTRIES ASSOCIATION - 005068 (base 16) ELECTRONIC INDUSTRIES ASSOCIATION - 2500 WILSON BLVD. - ARLINGTON VA 22201 - UNITED STATES - - 00-50-69 (hex) PixStream Incorporated - 005069 (base 16) PixStream Incorporated - 180 COLUMBIA ST. W. - WATERLOO - Ontario N2L 3L3 - CANADA - - 00-50-6A (hex) EDEVA, INC. - 00506A (base 16) EDEVA, INC. - 298 S. SUNNYVALE AVE. - #208 - SUNNYVALE CA 94086 - UNITED STATES - - 00-50-6B (hex) SPX-ATEG - 00506B (base 16) SPX-ATEG - 802 S. MAIN STREET - WAYLAND MI 49348 - UNITED STATES - - 00-50-6C (hex) Beijer Electronics Products AB - 00506C (base 16) Beijer Electronics Products AB - Box 426 - SE-201 24 Malmoe - SWEDEN - - 00-50-6D (hex) VIDEOJET SYSTEMS - 00506D (base 16) VIDEOJET SYSTEMS - INTERNATIONAL INC. - 1500 MITTEL BLVD. - WOODDALE IL 60091-1073 - UNITED STATES - - 00-50-6E (hex) CORDER ENGINEERING CORPORATION - 00506E (base 16) CORDER ENGINEERING CORPORATION - 151 KALMUS DRIVE - STE #A103 - COSTA MESA CA 92626 - UNITED STATES - - 00-50-6F (hex) G-CONNECT - 00506F (base 16) G-CONNECT - P.O. BOX 2200 - HERZLIYA 46120 - ISRAEL - - 00-50-70 (hex) CHAINTECH COMPUTER CO., LTD. - 005070 (base 16) CHAINTECH COMPUTER CO., LTD. - 5TH F, ALLEY 2, LANE 222 - LIEN-CHENG RD., CHUNG-HO TAIPEI-HSIEN - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-50-71 (hex) AIWA CO., LTD. - 005071 (base 16) AIWA CO., LTD. - 1-11, KAMITOMATSURI 4-CHOME - UTSUNOMIYA-SHI, TOCHIGI-KEN 320-85 - JAPAN - - 00-50-72 (hex) CORVIS CORPORATION - 005072 (base 16) CORVIS CORPORATION - 8320 GUILFORD ROAD - COLUMBIA MD 21046 - UNITED STATES - - 00-50-73 (hex) CISCO SYSTEMS, INC. - 005073 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-74 (hex) ADVANCED HI-TECH CORP. - 005074 (base 16) ADVANCED HI-TECH CORP. - 1990 EAST GRAND AVE. - EL SEGUNDO CA 90505 - UNITED STATES - - 00-50-75 (hex) KESTREL SOLUTIONS - 005075 (base 16) KESTREL SOLUTIONS - 2370 CHARLESTON ROAD - MT. VIEW CA 94043 - UNITED STATES - - 00-50-76 (hex) IBM Corp - 005076 (base 16) IBM Corp - 3039 E Cornwallis Road - P O Box 12195 - Reearch Triangle Park NC 27709-2195 - UNITED STATES - - 00-50-77 (hex) PROLIFIC TECHNOLOGY, INC. - 005077 (base 16) PROLIFIC TECHNOLOGY, INC. - 6F 1, LANE 51, SEC 1 - NAN-CHAN ROAD TAIPEI - 100 - TAIWAN, PROVINCE OF CHINA - - 00-50-78 (hex) MEGATON HOUSE, LTD. - 005078 (base 16) MEGATON HOUSE, LTD. - ZIP: 224 NO.1-3-5 NAKAMACHIBAI - TSUDUKI WARD - YOKOHAMA - JAPAN - - 00-50-79 (hex) PRIVATE - 005079 (base 16) - - 00-50-7A (hex) XPEED, INC. - 00507A (base 16) XPEED, INC. - 4699 OLD IRONSIDES DRIVE - SUITE #300 - SANTA CLARA CA 95054 - UNITED STATES - - 00-50-7B (hex) MERLOT COMMUNICATIONS - 00507B (base 16) MERLOT COMMUNICATIONS - BERKSHIRE CORPORATE PARK - 4 BERKSHIRE BLVD. - BETHEL CT 06801 - UNITED STATES - - 00-50-7C (hex) VIDEOCON AG - 00507C (base 16) VIDEOCON AG - ALBERT-SCHWEITZER-STR. 64 - D-81735 MUNICH - GERMANY - - 00-50-7D (hex) IFP - 00507D (base 16) IFP - LESSINGSTR. 4 - D-78315 RADOLFZELL - GERMANY - - 00-50-7E (hex) NEWER TECHNOLOGY - 00507E (base 16) NEWER TECHNOLOGY - 4848 WEST IRVING ST. - WICHITA KS 67209-2621 - UNITED STATES - - 00-50-7F (hex) DrayTek Corp. - 00507F (base 16) DrayTek Corp. - 26, Fushing Rd. - Hsinchu Industrial Park - Hsinchu Hukou 303 - TAIWAN, PROVINCE OF CHINA - - 00-50-80 (hex) CISCO SYSTEMS, INC. - 005080 (base 16) CISCO SYSTEMS, INC. - M/S SJA-2 - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-81 (hex) MURATA MACHINERY, LTD. - 005081 (base 16) MURATA MACHINERY, LTD. - 136, TAKEDA-MUKAISHIRO-CHO - FUSHIMI-KU, KYOTO 612-8686 - JAPAN - - 00-50-82 (hex) FORESSON CORPORATION - 005082 (base 16) FORESSON CORPORATION - 3F, NO.9 SEC.1 - CHANG AN EAST ROAD - TAIPEI 10404 - TAIWAN, PROVINCE OF CHINA - - 00-50-83 (hex) GILBARCO, INC. - 005083 (base 16) GILBARCO, INC. - POB 22087 - GREENSBORO NC 27420 - UNITED STATES - - 00-50-84 (hex) ATL PRODUCTS - 005084 (base 16) ATL PRODUCTS - 2801 KELVIN AVENUE - IRVINE CA 92614-5872 - UNITED STATES - - 00-50-86 (hex) TELKOM SA, LTD. - 005086 (base 16) TELKOM SA, LTD. - TELKOM LABORATORY - P. BAG X74 - PRETORIA - SOUTH AFRICA - - 00-50-87 (hex) TERASAKI ELECTRIC CO., LTD. - 005087 (base 16) TERASAKI ELECTRIC CO., LTD. - 7-2-10 HANNAN-CHO ABENO-KU - OSAKA, 545-0021 - JAPAN - - 00-50-88 (hex) AMANO CORPORATION - 005088 (base 16) AMANO CORPORATION - 275, MAMEDO-CHO - KOUHOKU-KU, YOKOHAMA - 222-8558 - JAPAN - - 00-50-89 (hex) SAFETY MANAGEMENT SYSTEMS - 005089 (base 16) SAFETY MANAGEMENT SYSTEMS - BRANDERIJSTRAAT 6 - 5223 AS 'S-HERTOGENBOSCH' - NETHERLANDS - - 00-50-8B (hex) Hewlett-Packard Company - 00508B (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-50-8C (hex) RSI SYSTEMS - 00508C (base 16) RSI SYSTEMS - 5555 W. 78TH STREET, Suite F - EDINA MN 55439 - UNITED STATES - - 00-50-8D (hex) ABIT COMPUTER CORPORATION - 00508D (base 16) ABIT COMPUTER CORPORATION - 3F-7, NO. 79, SEC.1 - HSIN TAI WU ROAD, HSI CHI - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-50-8E (hex) OPTIMATION, INC. - 00508E (base 16) OPTIMATION, INC. - P.O. BOX 14357 - HUNTSVILLE AL 35815 - UNITED STATES - - 00-50-8F (hex) ASITA TECHNOLOGIES INT'L LTD. - 00508F (base 16) ASITA TECHNOLOGIES INT'L LTD. - UNIT 2 BALLYBRIT BUSINESS PARK - GALWAY - IRELAND - - 00-50-90 (hex) DCTRI - 005090 (base 16) DCTRI - NO.40 XUE YUAN RD - HAIDIAN DISTRICT BEIJING, 100083, P.R. - CHINA - - 00-50-91 (hex) NETACCESS, INC. - 005091 (base 16) NETACCESS, INC. - 18 KEEWAYDIN DRIVE - SALEM NH 03079 - UNITED STATES - - 00-50-92 (hex) Rigaku Corporation Osaka Plant - 005092 (base 16) Rigaku Corporation Osaka Plant - 14-8 AKAOJI-CHO - TAKATSUKI-SHI, OSAKA 569-1146 - JAPAN - - 00-50-93 (hex) BOEING - 005093 (base 16) BOEING - 3370 Miraloma Avenue - Anaheim CA 92803-3105 - UNITED STATES - - 00-50-94 (hex) PACE plc - 005094 (base 16) PACE plc - VICTORIA RD, SALTAIRE - SHIPLEY, W. YORKSHIRE BRADFORD BD18 3LF - ENGLAND - UNITED KINGDOM - - 00-50-95 (hex) PERACOM NETWORKS - 005095 (base 16) PERACOM NETWORKS - 13000 WESTON PARKWAY - SUITE #105 - CARY NC 27513 - UNITED STATES - - 00-50-96 (hex) SALIX TECHNOLOGIES, INC. - 005096 (base 16) SALIX TECHNOLOGIES, INC. - 904 WIND RIVER LANE- STE. #101 - GAITHERSBURG MD 20878 - UNITED STATES - - 00-50-97 (hex) MMC-EMBEDDED COMPUTERTECHNIK GmbH - 005097 (base 16) MMC-EMBEDDED COMPUTERTECHNIK GmbH - ULRICHSBERGERSTR. 17 - D-94469 DEGGENDORF - GERMANY - - 00-50-98 (hex) GLOBALOOP, LTD. - 005098 (base 16) GLOBALOOP, LTD. - 12 HASHARON ROAD - KFAR SABA 44269 - ISRAEL - - 00-50-99 (hex) 3COM EUROPE, LTD. - 005099 (base 16) 3COM EUROPE, LTD. - BOUNDARY WAY - HEMEL HEMPSTEAD - HERTS. HP2 7YU - UNITED KINGDOM - - 00-50-9A (hex) TAG ELECTRONIC SYSTEMS - 00509A (base 16) TAG ELECTRONIC SYSTEMS - GENESIS BUSINESS PARK - Albert Drive - WOKING, SURREY GU21 5RW - UNITED KINGDOM - - 00-50-9B (hex) SWITCHCORE AB - 00509B (base 16) SWITCHCORE AB - POSITIONEN 153 - 115 74 STOCKHOLM - SWEDEN - - 00-50-9C (hex) BETA RESEARCH - 00509C (base 16) BETA RESEARCH - BETASTR. 1 - 85774 UNTERFOEHRING - GERMANY - - 00-50-9D (hex) THE INDUSTREE B.V. - 00509D (base 16) THE INDUSTREE B.V. - P.O. BOX 462 - 5600 AL EINDHOVEN - THE - NETHERLANDS - - 00-50-9E (hex) Les Technologies SoftAcoustik Inc. - 00509E (base 16) Les Technologies SoftAcoustik Inc. - - 390, RUE SAINT-VALLIER EST, 4th floor - Quebec G1K 3P6 - CANADA - - 00-50-9F (hex) HORIZON COMPUTER - 00509F (base 16) HORIZON COMPUTER - TRINITY BLDG. 4-22-7 - NISHI-AZABU, MINATO-KU - TOKYO 106 - JAPAN - - 00-50-A0 (hex) DELTA COMPUTER SYSTEMS, INC. - 0050A0 (base 16) DELTA COMPUTER SYSTEMS, INC. - 11719 NE 95TH STREET - STE. - VANCOUVER WA 98682-2444 - UNITED STATES - - 00-50-A1 (hex) CARLO GAVAZZI, INC. - 0050A1 (base 16) CARLO GAVAZZI, INC. - 222 PENNBRIGHT DR. - STE.#210 - HOUSTON TX 77090 - UNITED STATES - - 00-50-A2 (hex) CISCO SYSTEMS, INC. - 0050A2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-A3 (hex) TransMedia Communications, Inc. - 0050A3 (base 16) TransMedia Communications, Inc. - 20 GREAT OAKS BLVD., #210 - SAN JOSE CA 95119 - UNITED STATES - - 00-50-A4 (hex) IO TECH, INC. - 0050A4 (base 16) IO TECH, INC. - 25971 CANNON ROAD - CLEVELAND OH 44146 - UNITED STATES - - 00-50-A5 (hex) CAPITOL BUSINESS SYSTEMS, LTD. - 0050A5 (base 16) CAPITOL BUSINESS SYSTEMS, LTD. - 43/44 RIVERSIDE - SIR THOMAS LONGLEY ROAD - ROCHESTER, KENT England ME2 4DP - UNITED KINGDOM - - 00-50-A6 (hex) OPTRONICS - 0050A6 (base 16) OPTRONICS - 175 CREMONA DRIVE - GOLETA CA 93117 - UNITED STATES - - 00-50-A7 (hex) CISCO SYSTEMS, INC. - 0050A7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-A8 (hex) OpenCon Systems, Inc. - 0050A8 (base 16) OpenCon Systems, Inc. - 377 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 00-50-A9 (hex) MOLDAT WIRELESS TECHNOLGIES - 0050A9 (base 16) MOLDAT WIRELESS TECHNOLGIES - 3 SHIMON ISRAELI STREET - RISHON LE ZION 75654 - ISRAEL - - 00-50-AA (hex) KONICA MINOLTA HOLDINGS, INC. - 0050AA (base 16) KONICA MINOLTA HOLDINGS, INC. - 1-6-1, Marunouchi, - Chiyoda-ku - Tokyo 100-0005 - JAPAN - - 00-50-AB (hex) NALTEC, Inc. - 0050AB (base 16) NALTEC, Inc. - 1-1-15, Nakanogo, Shimizu-ku - Shizuoka-shi Shizuoka 424-0888 - JAPAN - - 00-50-AC (hex) MAPLE COMPUTER CORPORATION - 0050AC (base 16) MAPLE COMPUTER CORPORATION - 2F, NO. 184, SEC. 2 - CHANG-AN E. RD. - Taipei - TAJIKISTAN - - 00-50-AD (hex) CommUnique Wireless Corp. - 0050AD (base 16) CommUnique Wireless Corp. - 1070 MARINA VILLAGE PARKWAY - SUITE #206 - ALAMEDA CA 94501 - UNITED STATES - - 00-50-AE (hex) FDK Co., Ltd - 0050AE (base 16) FDK Co., Ltd - 2281 Washizu - Kosai-shi - Shizuoka-ken 431-0495 - JAPAN - - 00-50-AF (hex) INTERGON, INC. - 0050AF (base 16) INTERGON, INC. - 5800 RANCHESTER DRIVE - HOUSTON TX 77036 - UNITED STATES - - 00-50-B0 (hex) TECHNOLOGY ATLANTA CORPORATION - 0050B0 (base 16) TECHNOLOGY ATLANTA CORPORATION - 500 Sugar Mill Road - Suite 202A - Atlanta GA 30350 - UNITED STATES - - 00-50-B1 (hex) GIDDINGS & LEWIS - 0050B1 (base 16) GIDDINGS & LEWIS - 660 S. MILITARY RD. - FOND DU LAC WI 54935 - UNITED STATES - - 00-50-B2 (hex) BRODEL GmbH - 0050B2 (base 16) BRODEL GmbH - Distelbusch 24 - Velbert NRW 42549 - GERMANY - - 00-50-B3 (hex) VOICEBOARD CORPORATION - 0050B3 (base 16) VOICEBOARD CORPORATION - 3151 WEST FIFTH STREET - OXNARD CA 93030 - UNITED STATES - - 00-50-B4 (hex) SATCHWELL CONTROL SYSTEMS, LTD - 0050B4 (base 16) SATCHWELL CONTROL SYSTEMS, LTD - P.O. BOX 57, 94 FARNHAM ROAD - SLOUGH, - BERKSHIRE SL1 4UH - UNITED KINGDOM - - 00-50-B5 (hex) FICHET-BAUCHE - 0050B5 (base 16) FICHET-BAUCHE - 15-17 AVE. MORANE-SAULNIER - 78140 VELIZY - FRANCE - - 00-50-B6 (hex) GOOD WAY IND. CO., LTD. - 0050B6 (base 16) GOOD WAY IND. CO., LTD. - 5F, NO.8, ALLEY 6, - LANE 45 PAO-HSIN RD.-HSIN TIEN TAIPEI HS - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-50-B7 (hex) BOSER TECHNOLOGY CO., LTD. - 0050B7 (base 16) BOSER TECHNOLOGY CO., LTD. - 15F-6, 77 HSIN TAI WU ROAD - SEC. 1, HSI-CHI - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-50-B8 (hex) INOVA COMPUTERS GMBH & CO. KG - 0050B8 (base 16) INOVA COMPUTERS GMBH & CO. KG - SUDETENSTRASSE 5 - 87600 KAUFBEUREN - GERMANY - - 00-50-B9 (hex) XITRON TECHNOLOGIES, INC. - 0050B9 (base 16) XITRON TECHNOLOGIES, INC. - 6295-D FERRIS SQUARE - SAN DIEGO CA 92121 - UNITED STATES - - 00-50-BA (hex) D-LINK - 0050BA (base 16) D-LINK - 2F, NO. 233L-2, PAO-CHIAO RD. - Hsin-Tien 231 - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-50-BB (hex) CMS TECHNOLOGIES - 0050BB (base 16) CMS TECHNOLOGIES - 13955 FARMINGTON RAOD - LIVONIA MI 48154 - UNITED STATES - - 00-50-BC (hex) HAMMER STORAGE SOLUTIONS - 0050BC (base 16) HAMMER STORAGE SOLUTIONS - 8450 CENTRAL AVENUE - NEWARK CA 94560 - UNITED STATES - - 00-50-BD (hex) CISCO SYSTEMS, INC. - 0050BD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-BE (hex) FAST MULTIMEDIA AG - 0050BE (base 16) FAST MULTIMEDIA AG - RUEDESHEIMERSTR. 11-13 - 80686 MUNICH - GERMANY - - 00-50-BF (hex) Metalligence Technology Corp. - 0050BF (base 16) Metalligence Technology Corp. - NO.9, PARK AVENUE II - SCIENCE-BASE INDUSTRIAL PARK - HSIN-CHU - TAIWAN, PROVINCE OF CHINA - - 00-50-C0 (hex) GATAN, INC. - 0050C0 (base 16) GATAN, INC. - 5933 CORONADO LANE - PLEASANTON CA 94588 - UNITED STATES - - 00-50-C1 (hex) GEMFLEX NETWORKS, LTD. - 0050C1 (base 16) GEMFLEX NETWORKS, LTD. - 230-6651 FRASERWOOD PL. - RICHMOND, B.C. - CANADA V6W 1J3 - CANADA - - 00-50-C2 (hex) IEEE REGISTRATION AUTHORITY - Please see IAB public listing for more information. - 0050C2 (base 16) IEEE REGISTRATION AUTHORITY - Please see IAB public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 00-50-C4 (hex) IMD - 0050C4 (base 16) IMD - HERBSTRASSE 8 - D-82178 PUCHHEIM - GERMANY - - 00-50-C5 (hex) ADS Technologies, Inc - 0050C5 (base 16) ADS Technologies, Inc - 12627 Hiddencreek Way - Cerritos CA 90703 - UNITED STATES - - 00-50-C6 (hex) LOOP TELECOMMUNICATION INTERNATIONAL, INC. - 0050C6 (base 16) LOOP TELECOMMUNICATION INTERNATIONAL, INC. - 2F, NO. 22, PROSPERITY RD. 2 - Science-Based Industrial Park - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-50-C8 (hex) Addonics Technologies, Inc. - 0050C8 (base 16) Addonics Technologies, Inc. - 1918 Junction Ave., - San Jose CA 95131 - UNITED STATES - - 00-50-C9 (hex) MASPRO DENKOH CORP. - 0050C9 (base 16) MASPRO DENKOH CORP. - ASADA NISSHIN AICHI - 470-0194 - JAPAN - - 00-50-CA (hex) NET TO NET TECHNOLOGIES - 0050CA (base 16) NET TO NET TECHNOLOGIES - 680 CENTRAL AVENUE - STE. #301 - DOVER NH 03820 - UNITED STATES - - 00-50-CB (hex) JETTER - 0050CB (base 16) JETTER - GRAETERSTRASSE 2 - D71642 LUDWIGSBURG - GERMANY - - 00-50-CC (hex) XYRATEX - 0050CC (base 16) XYRATEX - MAIL POINT: 26/13; DEPT: STORAGE SYSTEM - Langstone Road - Havant PO9 1SA - UNITED KINGDOM - - 00-50-CD (hex) DIGIANSWER A/S - 0050CD (base 16) DIGIANSWER A/S - SKALHUSE 5 - 9240 NIBE - DENMARK - - 00-50-CE (hex) LG INTERNATIONAL CORP. - 0050CE (base 16) LG INTERNATIONAL CORP. - LG TWIN TOWERS - 20 YOIDO-DONG, YOUNGDUNGPO-GU - SEOUL, 150-606 - KOREA, REPUBLIC OF - - 00-50-CF (hex) VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE - 0050CF (base 16) VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE - 210 YADI OFFICE BUILDING - NO. 48 BEI SAN Huan Zhong Lu - BEIJING 100088 - CHINA - - 00-50-D0 (hex) MINERVA SYSTEMS - 0050D0 (base 16) MINERVA SYSTEMS - 1585 CHARLESTON ROAD - MOUNTAIN VIEW CA 84943 - UNITED STATES - - 00-50-D1 (hex) CISCO SYSTEMS, INC. - 0050D1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-D2 (hex) CMC Electronics Inc - 0050D2 (base 16) CMC Electronics Inc - 600 Dr.Frederik-Philips Blvd - Montreal QC H4M 2S9 - CANADA - - 00-50-D3 (hex) DIGITAL AUDIO PROCESSING PTY. LTD. - 0050D3 (base 16) DIGITAL AUDIO PROCESSING PTY. LTD. - PO BOX 40 - CONCORD WEST - NSW 2138 - AUSTRALIA - - 00-50-D4 (hex) JOOHONG INFORMATION & - 0050D4 (base 16) JOOHONG INFORMATION & - COMMUNICATIONS, LTD. - JUNGNAM B/D, 721-39 YEOKSAM-DONG, KANGNA - SEOUL SEOUL KOREA - KOREA, REPUBLIC OF - - 00-50-D5 (hex) AD SYSTEMS CORP. - 0050D5 (base 16) AD SYSTEMS CORP. - 1-4-1, NAKACHO, MUSASHINO CITY - TOKYO 180-0006 - JAPAN - - 00-50-D6 (hex) ATLAS COPCO TOOLS AB - 0050D6 (base 16) ATLAS COPCO TOOLS AB - - S-105 23 STOCKHOLM - SWEDEN - - 00-50-D7 (hex) TELSTRAT - 0050D7 (base 16) TELSTRAT - 3600 AVENUE - PLANO TX 75074 - UNITED STATES - - 00-50-D8 (hex) UNICORN COMPUTER CORP. - 0050D8 (base 16) UNICORN COMPUTER CORP. - 7 FL., NO. 96 KWANG FU NORTH ROAD - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-50-D9 (hex) ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA - 0050D9 (base 16) ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA - VIA SOCRATES M. BITTENCOURT, 1099 - 32010-010 Contagem MG - BRAZIL - - 00-50-DA (hex) 3COM CORPORATION - 0050DA (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - MS: 4220 - SANTA CLARA CA 95052 - UNITED STATES - - 00-50-DB (hex) CONTEMPORARY CONTROL - 0050DB (base 16) CONTEMPORARY CONTROL - SYSTEMS, INC. - 2431 CURTISS STREET - DOWNERS GROVE IL 60515 - UNITED STATES - - 00-50-DC (hex) TAS TELEFONBAU A. SCHWABE GMBH & CO. KG - 0050DC (base 16) TAS TELEFONBAU A. SCHWABE GMBH & CO. KG - - LANGMAAR 25 - D-41238 MONCHENGLADBACH - GERMANY - - 00-50-DD (hex) SERRA SOLDADURA, S.A. - 0050DD (base 16) SERRA SOLDADURA, S.A. - POL. IND. ZONA FRANCA, - SECTOR C, CALLE D, N. 29 08040 BARCELONA - SPAIN - - 00-50-DE (hex) SIGNUM SYSTEMS CORP. - 0050DE (base 16) SIGNUM SYSTEMS CORP. - 1211 Flynn Rd, - #104 - Camarillo CA 93021 - UNITED STATES - - 00-50-DF (hex) AirFiber, Inc. - 0050DF (base 16) AirFiber, Inc. - P.O. BOX 502148 - SAN DIEGO CA 92150-2148 - UNITED STATES - - 00-50-E1 (hex) NS TECH ELECTRONICS SDN BHD - 0050E1 (base 16) NS TECH ELECTRONICS SDN BHD - NO. 21 & 23 JALAN CANGGIH 10 - TAMAN PERINDUSTRIAN CEMERLANG - 81800 Ulu Tiram-Johor Bahru - MALAYSIA - - 00-50-E2 (hex) CISCO SYSTEMS, INC. - 0050E2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-E3 (hex) ARRIS Group, Inc. - 0050E3 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-50-E4 (hex) Apple - 0050E4 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-50-E6 (hex) HAKUSAN CORPORATION - 0050E6 (base 16) HAKUSAN CORPORATION - J TOWER, 1-1, NIKKOU-CHO - FUCHU-SHI TOKYO 183-0044 - JAPAN - - 00-50-E7 (hex) PARADISE INNOVATIONS (ASIA) - 0050E7 (base 16) PARADISE INNOVATIONS (ASIA) - PTE. LTD. - 25 SERANGOON NORTH AVE. 5 6TH FLOOR URAC - SINGAPORE 554914 - SINGAPORE - - 00-50-E8 (hex) NOMADIX INC. - 0050E8 (base 16) NOMADIX INC. - 2701 OCEAN PARK BLVD.-STE.#231 - SANTA MONICA CA 90405 - UNITED STATES - - 00-50-EA (hex) XEL COMMUNICATIONS, INC. - 0050EA (base 16) XEL COMMUNICATIONS, INC. - 17101 E. OHIO DRIVE - AURORA CO 80017 - UNITED STATES - - 00-50-EB (hex) ALPHA-TOP CORPORATION - 0050EB (base 16) ALPHA-TOP CORPORATION - 19F., NO. 2, LANE 150 - SEC. 5, HSIN-YI ROAD - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-50-EC (hex) OLICOM A/S - 0050EC (base 16) OLICOM A/S - NYBROVEJ 114 - DK-2800 LYNGBY - DENMARK - - 00-50-ED (hex) ANDA NETWORKS - 0050ED (base 16) ANDA NETWORKS - 2921 COPPER ROAD - SANTA CLARA CA 95051 - UNITED STATES - - 00-50-EE (hex) TEK DIGITEL CORPORATION - 0050EE (base 16) TEK DIGITEL CORPORATION - 20010 CENTURY BLVD. #300 - GERMANTOWN MD 20874 - UNITED STATES - - 00-50-EF (hex) SPE Systemhaus GmbH - 0050EF (base 16) SPE Systemhaus GmbH - WALDSTRASSE 7 - 63150 HEUSENSTAMM - GERMANY - - 00-50-F0 (hex) CISCO SYSTEMS, INC. - 0050F0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-50-F1 (hex) Intel Corporation - 0050F1 (base 16) Intel Corporation - 94 Em-Hamoshavot Way. - Park Azorim,P.O. Box 10097 - Petach-Tikva - ISRAEL - - 00-50-F2 (hex) MICROSOFT CORP. - 0050F2 (base 16) MICROSOFT CORP. - ONE MICROSOFT WAY - REDMOND WA 98052-6399 - UNITED STATES - - 00-50-F3 (hex) GLOBAL NET INFORMATION CO., Ltd. - 0050F3 (base 16) GLOBAL NET INFORMATION CO., Ltd. - NORTH TOWER- RM 1305 - WORLD TRADE CENTRE COMPLEX NO.371-375, H - GUANG ZHOU 510095 - CHINA - - 00-50-F4 (hex) SIGMATEK GMBH & CO. KG - 0050F4 (base 16) SIGMATEK GMBH & CO. KG - A-5112 LAMPRECHTSHAUSEN, - BURMOOSER STRASSE 10 - AUSTRIA - - 00-50-F6 (hex) PAN-INTERNATIONAL INDUSTRIAL CORP. - 0050F6 (base 16) PAN-INTERNATIONAL INDUSTRIAL CORP. - GF, NO. 176, CHANG CHUN RD. - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-50-F7 (hex) VENTURE MANUFACTURING (SINGAPORE) LTD. - 0050F7 (base 16) VENTURE MANUFACTURING (SINGAPORE) LTD. - - 5006 ANG MO KIO AVENUE - #05-01 Techplace II 569873 - SINGAPORE - - 00-50-F8 (hex) ENTREGA TECHNOLOGIES, INC. - 0050F8 (base 16) ENTREGA TECHNOLOGIES, INC. - 25691 ATLANTIC OCEAN DRIVE - SUITE #18 - LAKE FOREST CA 92630 - UNITED STATES - - 00-50-F9 (hex) Sensormatic Electronics LLC - 0050F9 (base 16) Sensormatic Electronics LLC - 1501 Yamato Rd - Boca Raton FL 33431 - UNITED STATES - - 00-50-FA (hex) OXTEL, LTD. - 0050FA (base 16) OXTEL, LTD. - THE MARKET PLACE - DIDCOT - 0X11 7LE England - UNITED KINGDOM - - 00-50-FB (hex) VSK ELECTRONICS - 0050FB (base 16) VSK ELECTRONICS - VENETIELAAN 39 - 8530 HARELBEKE - BELGIUM - - 00-50-FC (hex) EDIMAX TECHNOLOGY CO., LTD. - 0050FC (base 16) EDIMAX TECHNOLOGY CO., LTD. - 3 WU-CHUN 3rd ROAD - Wu-Ku Industrial Park - TAIPEI Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 00-50-FD (hex) VISIONCOMM CO., LTD. - 0050FD (base 16) VISIONCOMM CO., LTD. - 4, 5F, DAEWON B/D - 198-8, SEOBINGGO-DONG - YONGSAN-GU, SEOUL - KOREA, REPUBLIC OF - - 00-50-FE (hex) PCTVnet ASA - 0050FE (base 16) PCTVnet ASA - STRANDVEILEN 50 - N-1324 LYSAKER - NORWAY - - 00-50-FF (hex) HAKKO ELECTRONICS CO., LTD. - 0050FF (base 16) HAKKO ELECTRONICS CO., LTD. - 238, KAMIKASHIWANO-MACHI - MATTO-SHI, ISHIKAWA 924-0035 - JAPAN - - 00-52-18 (hex) Wuxi Keboda Electron Co.Ltd - 005218 (base 16) Wuxi Keboda Electron Co.Ltd - No.155 Chunhui Road, Xishan District, - Wuxi Jiangsu 214101 - CHINA - - 00-54-AF (hex) Continental Automotive Systems Inc. - 0054AF (base 16) Continental Automotive Systems Inc. - 21440 W. Lake Cook Rd. - Deer Park IL 60010 - UNITED STATES - - 00-59-07 (hex) LenovoEMC Products USA, LLC - 005907 (base 16) LenovoEMC Products USA, LLC - 22 South St - Suite # 201 - Hopinkton MA 01748 - UNITED STATES - - 00-5A-39 (hex) SHENZHEN FAST TECHNOLOGIES CO., LTD. - 005A39 (base 16) SHENZHEN FAST TECHNOLOGIES CO., LTD. - Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-5C-B1 (hex) Gospell DIGITAL TECHNOLOGY CO., LTD - 005CB1 (base 16) Gospell DIGITAL TECHNOLOGY CO., LTD - Block F10-F13¡¢F518 Idea land ¡¢Bao Yuan Road - Shenzhen Guangdong 518102 - CHINA - - 00-5D-03 (hex) Xilinx, Inc - 005D03 (base 16) Xilinx, Inc - 2100 Logic drive - San Jose CA 95124 - UNITED STATES - - 00-60-00 (hex) XYCOM INC. - 006000 (base 16) XYCOM INC. - 750 N. MAPLE - SALINE MI 48176 - UNITED STATES - - 00-60-01 (hex) InnoSys, Inc. - 006001 (base 16) InnoSys, Inc. - 3095 RICHMOND PKWY #207 - RICHMOND CA 94806 - UNITED STATES - - 00-60-02 (hex) SCREEN SUBTITLING SYSTEMS, LTD - 006002 (base 16) SCREEN SUBTITLING SYSTEMS, LTD - THE OLD RECTORY - CHURCH LANE - CLAYDON IPSWICH IP6 OEQ - UNITED KINGDOM - - 00-60-03 (hex) TERAOKA WEIGH SYSTEM PTE, LTD. - 006003 (base 16) TERAOKA WEIGH SYSTEM PTE, LTD. - 3A TUAS AVENUE 8 - SINGAPORE 639128 - SINGAPORE - - 00-60-04 (hex) COMPUTADORES MODULARES SA - 006004 (base 16) COMPUTADORES MODULARES SA - AVDA MONTESIERRA S/N - EDIFICIO CONGRESOS 314 - 41020-SEVILLA - SPAIN - - 00-60-05 (hex) FEEDBACK DATA LTD. - 006005 (base 16) FEEDBACK DATA LTD. - PARK ROAD - CROWBOROUGH - EAST SUSSEX, TN6 2QR - UNITED KINGDOM - - 00-60-06 (hex) SOTEC CO., LTD - 006006 (base 16) SOTEC CO., LTD - YOKOHAMA BASHAMICHI BLDG., - 4-55 OHTA-CHO NAKA-KU - YOKOHAMA 231 - JAPAN - - 00-60-07 (hex) ACRES GAMING, INC. - 006007 (base 16) ACRES GAMING, INC. - 815 NW 9TH STREET - CORVALLIS OR 97330 - UNITED STATES - - 00-60-08 (hex) 3COM CORPORATION - 006008 (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - SANTA CLARA CA 95052 - UNITED STATES - - 00-60-09 (hex) CISCO SYSTEMS, INC. - 006009 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-60-0A (hex) SORD COMPUTER CORPORATION - 00600A (base 16) SORD COMPUTER CORPORATION - 20-7, MASAGO 5-CHOME - MIHAMA-KU, CHIBA-SHI - CHIBA 261 - JAPAN - - 00-60-0B (hex) LOGWARE GmbH - 00600B (base 16) LOGWARE GmbH - SCHWEDENSTR. 9 - D-13359 BERLIN - GERMANY - - 00-60-0C (hex) Eurotech Inc. - 00600C (base 16) Eurotech Inc. - 10260 Old Columbia Road - COLUMBIA MD 21046 - UNITED STATES - - 00-60-0D (hex) Digital Logic GmbH - 00600D (base 16) Digital Logic GmbH - Stahlwerkstraße 25 - Mudersbach 57555 - GERMANY - - 00-60-0E (hex) WAVENET INTERNATIONAL, INC. - 00600E (base 16) WAVENET INTERNATIONAL, INC. - 5825 KENNEDY ROAD - MISSISSAUGA, ONTARIO L4Z 2G3 - CANADA - - 00-60-0F (hex) WESTELL, INC. - 00600F (base 16) WESTELL, INC. - 75 EXECUTIVE DRIVE - AURORA IL 60504-4101 - UNITED STATES - - 00-60-10 (hex) NETWORK MACHINES, INC. - 006010 (base 16) NETWORK MACHINES, INC. - 255 OLD NEW BRUNSWICK RD., # N320 - PISCATAWAY NJ 08854 - UNITED STATES - - 00-60-11 (hex) CRYSTAL SEMICONDUCTOR CORP. - 006011 (base 16) CRYSTAL SEMICONDUCTOR CORP. - P.O. BOX 17847 - AUSTIN TX 78760 - UNITED STATES - - 00-60-12 (hex) POWER COMPUTING CORPORATION - 006012 (base 16) POWER COMPUTING CORPORATION - 10261 BUBB ROAD - CUPERTINO CA 95014 - UNITED STATES - - 00-60-13 (hex) NETSTAL MASCHINEN AG - 006013 (base 16) NETSTAL MASCHINEN AG - INDUSTRIESTRASSE - CH-8752 NAEFELS - SWITZERLAND - - 00-60-14 (hex) EDEC CO., LTD. - 006014 (base 16) EDEC CO., LTD. - 9F OF T.O.C. BUILDING - 7-22-17 NISHIGOTANDA - SHINAGAWAKU, TOKYO - JAPAN - - 00-60-15 (hex) NET2NET CORPORATION - 006015 (base 16) NET2NET CORPORATION - 131 COOLIDGE STREET - HUDSON MA 01749 - UNITED STATES - - 00-60-16 (hex) CLARIION - 006016 (base 16) CLARIION - COSLIN DRIVE - Mail Stop C25 - SOUTHBORO MA 01772 - UNITED STATES - - 00-60-17 (hex) TOKIMEC INC. - 006017 (base 16) TOKIMEC INC. - 2-16, MINAMI-KAMATA, OHTA-KU - TOKYO 144 - JAPAN - - 00-60-18 (hex) STELLAR ONE CORPORATION - 006018 (base 16) STELLAR ONE CORPORATION - 500 108TH AVE. NE--STE. #2200 - BELLEVUE WA 98004 - UNITED STATES - - 00-60-19 (hex) Roche Diagnostics - 006019 (base 16) Roche Diagnostics - 9115 Hague Road - Building D - Indianapolis IN 46250-0457 - UNITED STATES - - 00-60-1A (hex) KEITHLEY INSTRUMENTS - 00601A (base 16) KEITHLEY INSTRUMENTS - 30500 BAINBRIDGE RD. - SOLON OH 44139 - UNITED STATES - - 00-60-1B (hex) MESA ELECTRONICS - 00601B (base 16) MESA ELECTRONICS - 1323 61ST STREET - EMERYVILLE CA 94608-2117 - UNITED STATES - - 00-60-1C (hex) TELXON CORPORATION - 00601C (base 16) TELXON CORPORATION - 3330 W. MARKET STREET - PO BOX 5582 - AKRON OH 44334-0582 - UNITED STATES - - 00-60-1D (hex) LUCENT TECHNOLOGIES - 00601D (base 16) LUCENT TECHNOLOGIES - 101 CRAWFORDS CORNER RD. - ROOM 4K-321 - HOLMDEL NJ 07733 - UNITED STATES - - 00-60-1E (hex) SOFTLAB, INC. - 00601E (base 16) SOFTLAB, INC. - P.O. BOX 8 - CHIMNEY ROCK CO 81127 - UNITED STATES - - 00-60-1F (hex) STALLION TECHNOLOGIES - 00601F (base 16) STALLION TECHNOLOGIES - 33 WOODSTOCK ROAD - TOOWONG Q-L-D- 4066 - AUSTRALIA - - 00-60-20 (hex) PIVOTAL NETWORKING, INC. - 006020 (base 16) PIVOTAL NETWORKING, INC. - 7246 SHARON DR., STE - SAN JOSE CA 95129 - UNITED STATES - - 00-60-21 (hex) DSC CORPORATION - 006021 (base 16) DSC CORPORATION - RECRUIT-SHINOHTSUKA BLDG., - 2-25-15 MINAMIOHTSUKA, TOSHIMA-KU, - TOKYO 170 - JAPAN - - 00-60-22 (hex) VICOM SYSTEMS, INC. - 006022 (base 16) VICOM SYSTEMS, INC. - 1961 LANDINGS DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-60-23 (hex) PERICOM SEMICONDUCTOR CORP. - 006023 (base 16) PERICOM SEMICONDUCTOR CORP. - 2380 BERING DRIVE - SAN JOSE CA 95131 - UNITED STATES - - 00-60-24 (hex) GRADIENT TECHNOLOGIES, INC. - 006024 (base 16) GRADIENT TECHNOLOGIES, INC. - 2 MOUNT ROYAL AVENUE - MARLBORO MA 01752 - UNITED STATES - - 00-60-25 (hex) ACTIVE IMAGING PLC - 006025 (base 16) ACTIVE IMAGING PLC - HATTORI HOUSE - VANWALL BUSINESS PARK - MAIDENHEAD Berkshire SL6 4UB - UNITED KINGDOM - - 00-60-26 (hex) VIKING Modular Solutions - 006026 (base 16) VIKING Modular Solutions - 11 COLUMBIA - LAGUNA HILLS CA 92656 - UNITED STATES - - 00-60-27 (hex) Superior Modular Products - 006027 (base 16) Superior Modular Products - General Technology Division - 415 PINEDA COURT - MELBOURNE FL 32940 - UNITED STATES - - 00-60-28 (hex) MACROVISION CORPORATION - 006028 (base 16) MACROVISION CORPORATION - 2830 De La Cruz Boulevard - Santa Clara CA 95050 - UNITED STATES - - 00-60-29 (hex) CARY PERIPHERALS INC. - 006029 (base 16) CARY PERIPHERALS INC. - 190 COLONNADE ROAD S, UNIT 9 - NEPEAN, ONTARIO K2E 7J5 - CANADA - - 00-60-2A (hex) SYMICRON COMPUTER COMMUNICATIONS, LTD. - 00602A (base 16) SYMICRON COMPUTER COMMUNICATIONS, LTD. - UNIT 4 GREEN LANE BUSINESS PARK - 238 Green lane - London SE9 3TL - UNITED STATES - - 00-60-2B (hex) PEAK AUDIO - 00602B (base 16) PEAK AUDIO - 1790 30TH STREET STE #414 - BOULDER CO 80301 - UNITED STATES - - 00-60-2C (hex) LINX Data Terminals, Inc. - 00602C (base 16) LINX Data Terminals, Inc. - 625 DIGITAL DRIVE-STE #100 - PLANO TX 75075 - UNITED STATES - - 00-60-2D (hex) ALERTON TECHNOLOGIES, INC. - 00602D (base 16) ALERTON TECHNOLOGIES, INC. - 6670 185TH AVE. N.E. - REDMOND WA 98052 - UNITED STATES - - 00-60-2E (hex) CYCLADES CORPORATION - 00602E (base 16) CYCLADES CORPORATION - 41934 CHRISTY STREET - FREMONT CA 94538 - UNITED STATES - - 00-60-2F (hex) CISCO SYSTEMS, INC. - 00602F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-60-30 (hex) VILLAGE TRONIC ENTWICKLUNG - 006030 (base 16) VILLAGE TRONIC ENTWICKLUNG - WELLWEG 95 - 31157 SARSTEDT - GERMANY - - 00-60-31 (hex) HRK SYSTEMS - 006031 (base 16) HRK SYSTEMS - P.O. BOX 514 - WESTVILLE 3630 - SOUTH AFRICA - - 00-60-32 (hex) I-CUBE, INC. - 006032 (base 16) I-CUBE, INC. - 2328-C WALSH AVENUE - SANTA CLARA CA 95014 - UNITED STATES - - 00-60-33 (hex) ACUITY IMAGING, INC. - 006033 (base 16) ACUITY IMAGING, INC. - 9 TOWNSEND WEST - NASHUA NH 03063 - UNITED STATES - - 00-60-34 (hex) ROBERT BOSCH GmbH - 006034 (base 16) ROBERT BOSCH GmbH - POSTBOX 11 62 - D-64701 ERBACH - GERMANY - - 00-60-35 (hex) DALLAS SEMICONDUCTOR, INC. - 006035 (base 16) DALLAS SEMICONDUCTOR, INC. - 4401 SOUTH BELTWOOD PARKWAY - DALLAS TX 75244-3292 - UNITED STATES - - 00-60-36 (hex) AIT Austrian Institute of Technology GmbH - 006036 (base 16) AIT Austrian Institute of Technology GmbH - Donau-City-Straße 1 - Vienna 1220 - AUSTRIA - - 00-60-37 (hex) NXP Semiconductors - 006037 (base 16) NXP Semiconductors - High Tech Campus 32, Office 1.21 - 5656 AE Eindhoven - NETHERLANDS - - 00-60-38 (hex) Nortel Networks - 006038 (base 16) Nortel Networks - Global Operations Engineering - Dep 6800 Program Manager 8200 Dixie Road - Brampton Ontario 16T 5P6 - CANADA - - 00-60-39 (hex) SanCom Technology, Inc. - 006039 (base 16) SanCom Technology, Inc. - 7719 WOOD HOLLOW DRIVE - SUITE #156 - AUSTIN TX 78731 - UNITED STATES - - 00-60-3A (hex) QUICK CONTROLS LTD. - 00603A (base 16) QUICK CONTROLS LTD. - DURHAM HOUSE, WARWICK COURT - PARK ROAD, MIDDLETON - MANCHESTER M24 1AE - UNITED KINGDOM - - 00-60-3B (hex) AMTEC spa - 00603B (base 16) AMTEC spa - LOC. S. MARTINO - 53025 PIANCASTAGNAIO (SIENA) - ITALY - - 00-60-3C (hex) HAGIWARA SYS-COM CO., LTD. - 00603C (base 16) HAGIWARA SYS-COM CO., LTD. - 2-4-3 NISHIKI NAKA-KU - NAGOYA - AICHI 460 - JAPAN - - 00-60-3D (hex) 3CX - 00603D (base 16) 3CX - 2085 HAMILTON AVE., -STE.#220 - SAN JOSE CA 95125 - UNITED STATES - - 00-60-3E (hex) CISCO SYSTEMS, INC. - 00603E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-60-3F (hex) PATAPSCO DESIGNS - 00603F (base 16) PATAPSCO DESIGNS - 5350 PARTNERS COURT - FREDERICK MD 21703 - UNITED STATES - - 00-60-40 (hex) NETRO CORP. - 006040 (base 16) NETRO CORP. - 3120 SCOTT BLVD. - SANTA CLARA CA 95054 - UNITED STATES - - 00-60-41 (hex) Yokogawa Electric Corporation - 006041 (base 16) Yokogawa Electric Corporation - 2-9-31 Nakacho, Musashino-shi - Tokyo 180-8750 - JAPAN - - 00-60-42 (hex) TKS (USA), INC. - 006042 (base 16) TKS (USA), INC. - 1201 COMMERCE - RICHARDSON TX 75081 - UNITED STATES - - 00-60-43 (hex) iDirect, INC. - 006043 (base 16) iDirect, INC. - 13865 Sunrise Vally Drive - Suite 100 - Herndon VA 20171 - UNITED STATES - - 00-60-44 (hex) LITTON/POLY-SCIENTIFIC - 006044 (base 16) LITTON/POLY-SCIENTIFIC - 2200 SOUTH MAIN STREET - BLACKSBURG VA 24060 - UNITED STATES - - 00-60-45 (hex) PATHLIGHT TECHNOLOGIES - 006045 (base 16) PATHLIGHT TECHNOLOGIES - 767 WARREN ROAD - ITHACA NY 14850 - UNITED STATES - - 00-60-46 (hex) VMETRO, INC. - 006046 (base 16) VMETRO, INC. - 1880 DAIRY ASHFORD- STE #535 - HOUSTON TX 77077 - UNITED STATES - - 00-60-47 (hex) CISCO SYSTEMS, INC. - 006047 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-60-48 (hex) EMC CORPORATION - 006048 (base 16) EMC CORPORATION - 171 SOUTH ST., - HOPKINTON MA 01748 - UNITED STATES - - 00-60-49 (hex) VINA TECHNOLOGIES - 006049 (base 16) VINA TECHNOLOGIES - 6 UNION SQUARE - STE F - UNION CITY CA 94587 - UNITED STATES - - 00-60-4A (hex) SAIC IDEAS GROUP - 00604A (base 16) SAIC IDEAS GROUP - 7120 COLUMBIA GATEWAY DRIVE - COLUMBIA MD 21046 - UNITED STATES - - 00-60-4B (hex) Safe-com GmbH & Co. KG - 00604B (base 16) Safe-com GmbH & Co. KG - Burg Lichtenfels - 35104 Lichtenfels - GERMANY - - 00-60-4C (hex) SAGEM COMMUNICATION - 00604C (base 16) SAGEM COMMUNICATION - 27 RUE LEBLANC - CEDEX 15 PARIS 75512 - FRANCE - - 00-60-4D (hex) MMC NETWORKS, INC. - 00604D (base 16) MMC NETWORKS, INC. - 1134 EAST ARQUES AVENUE - SUNNYVALE CA 94086-4602 - UNITED STATES - - 00-60-4E (hex) CYCLE COMPUTER CORPORATION, INC. - 00604E (base 16) CYCLE COMPUTER CORPORATION, INC. - 20245 STEVENS CREEK BLVD. - CUPERTINO CA 95014 - UNITED STATES - - 00-60-4F (hex) Tattile SRL - 00604F (base 16) Tattile SRL - 552-51 AJIGAURA - HITACHINAKA - IBARAKI, 311-12 - JAPAN - - 00-60-50 (hex) INTERNIX INC. - 006050 (base 16) INTERNIX INC. - 59-10 TAKAKURA-CHO - HACHIOJI - TOKYO 192 - JAPAN - - 00-60-51 (hex) QUALITY SEMICONDUCTOR - 006051 (base 16) QUALITY SEMICONDUCTOR - 851 MARTIN AVENUE - SANTA CLARA CA 95050 - UNITED STATES - - 00-60-52 (hex) PERIPHERALS ENTERPRISE CO., Ltd. - 006052 (base 16) PERIPHERALS ENTERPRISE CO., Ltd. - 3F, NO.10, ALLEY 6, LANE 45 - PAO SHIN ROAD, HSIN TIEN CITY - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-60-53 (hex) TOYODA MACHINE WORKS, LTD. - 006053 (base 16) TOYODA MACHINE WORKS, LTD. - 1-7 KITAJIZOYAMA NODACHOU - KARIYA CITY, AICHI - JAPAN - - 00-60-54 (hex) CONTROLWARE GMBH - 006054 (base 16) CONTROLWARE GMBH - WALDSTRASSE 92 - 63128 DIETZENBACH - GERMANY - - 00-60-55 (hex) CORNELL UNIVERSITY - 006055 (base 16) CORNELL UNIVERSITY - 729 Rhodes Hall - ITHACA NY 14850-4902 - UNITED STATES - - 00-60-56 (hex) NETWORK TOOLS, INC. - 006056 (base 16) NETWORK TOOLS, INC. - 2975 BOWERS AVENUE, #202 - SANTA CLARA CA 95051-0955 - UNITED STATES - - 00-60-57 (hex) MURATA MANUFACTURING CO., LTD. - 006057 (base 16) MURATA MANUFACTURING CO., LTD. - 1-18-1 HAKUSAN MIDORI-KU - YOKOHAMA 226 - JAPAN - - 00-60-58 (hex) COPPER MOUNTAIN COMMUNICATIONS, INC. - 006058 (base 16) COPPER MOUNTAIN COMMUNICATIONS, INC. - 6650 LUSK BLVD.-STE #B103 - SAN DIEGO CA 92121 - UNITED STATES - - 00-60-59 (hex) TECHNICAL COMMUNICATIONS CORP. - 006059 (base 16) TECHNICAL COMMUNICATIONS CORP. - 100 DOMINO DRIVE - CONCORD MA 01742 - UNITED STATES - - 00-60-5A (hex) CELCORE, INC. - 00605A (base 16) CELCORE, INC. - 8001 CENTERVIEW PARKWAY - SUITE #201 - MEMPHIS TN 38018 - UNITED STATES - - 00-60-5B (hex) IntraServer Technology, Inc. - 00605B (base 16) IntraServer Technology, Inc. - 125 HOPPING BROOK PARK - HOLLISTON MA 01746 - UNITED STATES - - 00-60-5C (hex) CISCO SYSTEMS, INC. - 00605C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-60-5D (hex) SCANIVALVE CORP. - 00605D (base 16) SCANIVALVE CORP. - 1722 N. MADSON STREET - LIBERTY LAKE WA 99019 - UNITED STATES - - 00-60-5E (hex) LIBERTY TECHNOLOGY NETWORKING - 00605E (base 16) LIBERTY TECHNOLOGY NETWORKING - P.O. BOX 11566 - HATFIELD, PRETORIA 0028 - SOUTH AFRICA - - 00-60-5F (hex) NIPPON UNISOFT CORPORATION - 00605F (base 16) NIPPON UNISOFT CORPORATION - BR NINGYOCHO 1,2-13-9 - NIHONBASHI-NINGYOCHO, CHUO-KU - TOKYO 103 - JAPAN - - 00-60-60 (hex) Data Innovations North America - 006060 (base 16) Data Innovations North America - 120 Kimball Avenue Suite 100 - South Burlington VT 05403 - UNITED STATES - - 00-60-61 (hex) WHISTLE COMMUNICATIONS CORP. - 006061 (base 16) WHISTLE COMMUNICATIONS CORP. - 110 MARSH DRIVE-STE #100 - FOSTER CITY CA 94404 - UNITED STATES - - 00-60-62 (hex) TELESYNC, INC. - 006062 (base 16) TELESYNC, INC. - 5555 OAKBROOK PKWY-STE #110 - NORCROSS GA 30093 - UNITED STATES - - 00-60-63 (hex) PSION DACOM PLC. - 006063 (base 16) PSION DACOM PLC. - PSION DACOM HOUSE - PRESLEY WAY, - CROWNHILL MILTON KEYNES MK8 0EF - UNITED KINGDOM - - 00-60-64 (hex) NETCOMM LIMITED - 006064 (base 16) NETCOMM LIMITED - PO BOX 379 - NORTH RYDE, NSW, 2113 - AUSTRALIA - - 00-60-65 (hex) BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH - 006065 (base 16) BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH - EGGELSBERG 120 - 5142 EGGELSBERG - AUSTRIA - - 00-60-66 (hex) LACROIX Trafic - 006066 (base 16) LACROIX Trafic - 1 ere Avenue, 11 eme rue - 06516 CARROS - FRANCE - - 00-60-67 (hex) ACER NETXUS INC. - 006067 (base 16) ACER NETXUS INC. - 5F-3, 5 HSIN ANN ROAD SBIP - HSINCHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-60-68 (hex) Dialogic Corporation - 006068 (base 16) Dialogic Corporation - 9800 Cavendish Blvd, 5th Floor - Montreal Quebec H4M 2V9 - CANADA - - 00-60-69 (hex) Brocade Communications Systems, Inc. - 006069 (base 16) Brocade Communications Systems, Inc. - 1745 Technology Drive - San Jose CA 95110 - UNITED STATES - - 00-60-6A (hex) MITSUBISHI WIRELESS COMMUNICATIONS. INC. - 00606A (base 16) MITSUBISHI WIRELESS COMMUNICATIONS. INC. - 2001 CHERRY DRIVE - BRASELTON GA 30517 - UNITED STATES - - 00-60-6B (hex) Synclayer Inc. - 00606B (base 16) Synclayer Inc. - 1-20 Himegaoka - Kani-City - GIFU 509-0249 - JAPAN - - 00-60-6C (hex) ARESCOM - 00606C (base 16) ARESCOM - 2833 JUNCTION AVE. - STE #206 - SAN JOSE CA 95134 - UNITED STATES - - 00-60-6D (hex) DIGITAL EQUIPMENT CORP. - 00606D (base 16) DIGITAL EQUIPMENT CORP. - 550 KING STREET - M/S LKG1-3/A10 - LITTLETON MA 01460 - UNITED STATES - - 00-60-6E (hex) DAVICOM SEMICONDUCTOR, INC. - 00606E (base 16) DAVICOM SEMICONDUCTOR, INC. - 2457 AUGUSTINE DRIVE - SANTA CLARA CA 95054 - UNITED STATES - - 00-60-6F (hex) CLARION CORPORATION OF AMERICA - 00606F (base 16) CLARION CORPORATION OF AMERICA - 17 LAKESIDE OFFICE PARK - 607 NORTH AVENUE - WAKEFIELD MA 01880 - UNITED STATES - - 00-60-70 (hex) CISCO SYSTEMS, INC. - 006070 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-60-71 (hex) MIDAS LAB, INC. - 006071 (base 16) MIDAS LAB, INC. - 4 KATAMACHI, - SHINJUKU-KU - TOKYO 160 - JAPAN - - 00-60-72 (hex) VXL INSTRUMENTS, LIMITED - 006072 (base 16) VXL INSTRUMENTS, LIMITED - PLOT NO. 17, KONAPPANA AGRAHARA - ELECTRONIC CITY - BANGALORE - 561 229 - INDIA - - 00-60-73 (hex) REDCREEK COMMUNICATIONS, INC. - 006073 (base 16) REDCREEK COMMUNICATIONS, INC. - 3900 NEWPARK MALL ROAD - NEWARK CA 94560 - UNITED STATES - - 00-60-74 (hex) QSC AUDIO PRODUCTS - 006074 (base 16) QSC AUDIO PRODUCTS - 1675 MACARTHUR BLVD. - COSTA MESA CA 92626 - UNITED STATES - - 00-60-75 (hex) PENTEK, INC. - 006075 (base 16) PENTEK, INC. - 1 PARK WAY - UPPER SADDLE RIVER NJ 07458 - UNITED STATES - - 00-60-76 (hex) SCHLUMBERGER TECHNOLOGIES RETAIL PETROLEUM SYSTEMS - 006076 (base 16) SCHLUMBERGER TECHNOLOGIES RETAIL PETROLEUM SYSTEMS - 825-M GREENBRIER CIRCLE - CHESAPEAKE VA 23320 - UNITED STATES - - 00-60-77 (hex) PRISA NETWORKS - 006077 (base 16) PRISA NETWORKS - 6620 Mesa Ridge Road, - Suite 200 - San Diego CA 92121 - UNITED STATES - - 00-60-78 (hex) POWER MEASUREMENT LTD. - 006078 (base 16) POWER MEASUREMENT LTD. - 2195 KEATING CROSS ROAD - SAANICHTON, B.C. V8M 2A5 - CANADA - - 00-60-79 (hex) Mainstream Data, Inc. - 006079 (base 16) Mainstream Data, Inc. - 375 Chipeta Way, Suite B - Salt Lake City UT 84108 - UNITED STATES - - 00-60-7A (hex) DVS GmbH - 00607A (base 16) DVS GmbH - KREPENSTRASSE 8 - D-30165 HANNOVER - GERMANY - - 00-60-7B (hex) FORE SYSTEMS, INC. - 00607B (base 16) FORE SYSTEMS, INC. - 1000 FORE DRIVE - WARRENDALE PA 15086 - UNITED STATES - - 00-60-7C (hex) WaveAccess, Ltd. - 00607C (base 16) WaveAccess, Ltd. - P.O. BOX 2473 - 10 HAYEZIRA STREET - RA'ANANA 43663 - ISRAEL - - 00-60-7D (hex) SENTIENT NETWORKS INC. - 00607D (base 16) SENTIENT NETWORKS INC. - 2201 CANTU COURT-STE #205 - SARASOTA FL 34232 - UNITED STATES - - 00-60-7E (hex) GIGALABS, INC. - 00607E (base 16) GIGALABS, INC. - 290 SANTA ANA COURT - SUNNYVALE CA 94086 - UNITED STATES - - 00-60-7F (hex) AURORA TECHNOLOGIES, INC. - 00607F (base 16) AURORA TECHNOLOGIES, INC. - 176 SECOND AVENUE - WALTHAM MA 02154 - UNITED STATES - - 00-60-80 (hex) MICROTRONIX DATACOM LTD. - 006080 (base 16) MICROTRONIX DATACOM LTD. - 200 ABERDEEN DRIVE - LONDON, ONTARIO N5V 4N2 - CANADA - - 00-60-81 (hex) TV/COM INTERNATIONAL - 006081 (base 16) TV/COM INTERNATIONAL - 16516 VIA ESPRILLO - SAN DIEGO CA 92127 - UNITED STATES - - 00-60-82 (hex) NOVALINK TECHNOLOGIES, INC. - 006082 (base 16) NOVALINK TECHNOLOGIES, INC. - 48511 WARM SPRINGS BLVD. #208 - FREMONT CA 94539 - UNITED STATES - - 00-60-83 (hex) CISCO SYSTEMS, INC. - 006083 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-60-84 (hex) DIGITAL VIDEO - 006084 (base 16) DIGITAL VIDEO - 4920 AVALON RIDGE PKWY - SUITE #600 - NORCROSS GA 30092 - UNITED STATES - - 00-60-85 (hex) Storage Concepts - 006085 (base 16) Storage Concepts - 14352 Chamber Road - Tustin CA 92780 - UNITED STATES - - 00-60-86 (hex) LOGIC REPLACEMENT TECH. LTD. - 006086 (base 16) LOGIC REPLACEMENT TECH. LTD. - 14 ARKWRIGHT ROAD - READING BERKS RG20LS - UNITED KINGDOM - UNITED KINGDOM - - 00-60-87 (hex) KANSAI ELECTRIC CO., LTD. - 006087 (base 16) KANSAI ELECTRIC CO., LTD. - 6-14-9 MIDORII, ASAMINAMI-KU - HIROSHIMA 731-01 - JAPAN - - 00-60-88 (hex) WHITE MOUNTAIN DSP, INC. - 006088 (base 16) WHITE MOUNTAIN DSP, INC. - 410 AMHERST STREET-STE #325 - NASHUA NH 03063 - UNITED STATES - - 00-60-89 (hex) XATA - 006089 (base 16) XATA - 151 EAST CLIFF ROAD-STE.#10 - BURNSVILLE MN 55337 - UNITED STATES - - 00-60-8A (hex) CITADEL COMPUTER - 00608A (base 16) CITADEL COMPUTER - 29 ARMORY RD - MILFORD MA 03055 - UNITED STATES - - 00-60-8B (hex) ConferTech International - 00608B (base 16) ConferTech International - 12110 N. PECOS STREET - WESTMINSTER CO 80234-2074 - UNITED STATES - - 00-60-8C (hex) 3COM CORPORATION - 00608C (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - SANTA CLARA CA 95052-8145 - UNITED STATES - - 00-60-8D (hex) UNIPULSE CORP. - 00608D (base 16) UNIPULSE CORP. - 2-7, SENGENDAI-NISHI - KOSHIGAYA-CITY - SAITAMA 343 - JORDAN - - 00-60-8E (hex) HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH - 00608E (base 16) HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH - AM GNEISENAUFLOT 8 - D-66538 NEUNHIRCHEN - GERMANY - - 00-60-8F (hex) TEKRAM TECHNOLOGY CO., LTD. - 00608F (base 16) TEKRAM TECHNOLOGY CO., LTD. - B1, NO. 17, LANE 159, SEC. 6 - ROOSEVELT RD, - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-60-90 (hex) Artiza Networks Inc - 006090 (base 16) Artiza Networks Inc - Faret Tachikawa Center Square, 2-36-2 Akebono-cho, - Tachikawa-shi, Tokyo 190-0012 - JAPAN - - 00-60-91 (hex) FIRST PACIFIC NETWORKS, INC. - 006091 (base 16) FIRST PACIFIC NETWORKS, INC. - 871 FOX LANE - SAN JOSE CA 95131 - UNITED STATES - - 00-60-92 (hex) MICRO/SYS, INC. - 006092 (base 16) MICRO/SYS, INC. - 3447 OCEAN VIEW BLVD. - GLENDALE CA 91208 - UNITED STATES - - 00-60-93 (hex) VARIAN - 006093 (base 16) VARIAN - 2700 MITCHELL DR. - WALNUT GREEK CA 94598 - UNITED STATES - - 00-60-94 (hex) IBM Corp - 006094 (base 16) IBM Corp - 3039 E Cornwallis Road - PO BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 00-60-95 (hex) ACCU-TIME SYSTEMS, INC. - 006095 (base 16) ACCU-TIME SYSTEMS, INC. - 420 SOMERS ROAD - ELLINGTON CT 06029 - UNITED STATES - - 00-60-96 (hex) T.S. MICROTECH INC. - 006096 (base 16) T.S. MICROTECH INC. - 20818 HIGGINS COURT - TORRANCE CA 90501 - UNITED STATES - - 00-60-97 (hex) 3COM CORPORATION - 006097 (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - SANTA CLARA CA 95052 - UNITED STATES - - 00-60-98 (hex) HT COMMUNICATIONS - 006098 (base 16) HT COMMUNICATIONS - 4480 SHOPPING LANE - SIMI VALLEY CA 93063 - UNITED STATES - - 00-60-99 (hex) SBE, Inc. - 006099 (base 16) SBE, Inc. - 2305 Camino Ramon - Suite 200 - San Ramon CA 94583 - UNITED STATES - - 00-60-9A (hex) NJK TECHNO CO. - 00609A (base 16) NJK TECHNO CO. - N1-25 KAMIYASATO - KOMATSU #923 - JAPAN - - 00-60-9B (hex) ASTRO-MED, INC. - 00609B (base 16) ASTRO-MED, INC. - 600 EAST GREENWICH AVE. - WEST WARWICK RI 02893 - UNITED STATES - - 00-60-9C (hex) Perkin-Elmer Incorporated - 00609C (base 16) Perkin-Elmer Incorporated - 710 Bridgeport Ave. - Shelton CT 06484 - UNITED STATES - - 00-60-9D (hex) PMI FOOD EQUIPMENT GROUP - 00609D (base 16) PMI FOOD EQUIPMENT GROUP - 701 RIDGE AVENUE - TROY OH 45374 - UNITED STATES - - 00-60-9E (hex) ASC X3 - INFORMATION TECHNOLOGY STANDARDS SECRETARIATS - 00609E (base 16) ASC X3 - INFORMATION TECHNOLOGY STANDARDS SECRETARIATS - 1250 EYE STREET NW - STE #200 - WASHINGTON DC 20005 - UNITED STATES - - 00-60-9F (hex) PHAST CORPORATION - 00609F (base 16) PHAST CORPORATION - 79 WEST 4500 SOUTH - BLDG.#14 - SALT LAKE CITY UT 84107 - UNITED STATES - - 00-60-A0 (hex) SWITCHED NETWORK TECHNOLOGIES, INC. - 0060A0 (base 16) SWITCHED NETWORK TECHNOLOGIES, INC. - 13805 1ST AVENUE NORTH - PLYMOUTH MN 55441-5455 - UNITED STATES - - 00-60-A1 (hex) VPNet, Inc. - 0060A1 (base 16) VPNet, Inc. - 555 N. MATHILDA AVE.,-STE #110 - SUNNYVALE CA 94086 - UNITED STATES - - 00-60-A2 (hex) NIHON UNISYS LIMITED CO. - 0060A2 (base 16) NIHON UNISYS LIMITED CO. - P.O. BOX 135 - TOKYO-TO, KOUTOU-KU - SHINONOME 1-10-9 - JAPAN - - 00-60-A3 (hex) CONTINUUM TECHNOLOGY CORP. - 0060A3 (base 16) CONTINUUM TECHNOLOGY CORP. - 220 CONTINUUM DRIVE - FLETCHER NC 28732 - UNITED STATES - - 00-60-A4 (hex) GEW Technologies (PTY)Ltd - 0060A4 (base 16) GEW Technologies (PTY)Ltd - BOX 912-561 - SILVERTON 0127 - SOUTH AFRICA - - 00-60-A5 (hex) PERFORMANCE TELECOM CORP. - 0060A5 (base 16) PERFORMANCE TELECOM CORP. - 10 CARLSON ROAD - ROCHESTER NY 14610-1021 - UNITED STATES - - 00-60-A6 (hex) PARTICLE MEASURING SYSTEMS - 0060A6 (base 16) PARTICLE MEASURING SYSTEMS - 5475 AIRPORT BLVD. - BOULDER CO 80301 - UNITED STATES - - 00-60-A7 (hex) MICROSENS GmbH & CO. KG - 0060A7 (base 16) MICROSENS GmbH & CO. KG - Kueferstrasse 16 - D-59067 Hamm - GERMANY - - 00-60-A8 (hex) TIDOMAT AB - 0060A8 (base 16) TIDOMAT AB - - S-12089 STOCKHOLM - SWEDEN - - 00-60-A9 (hex) GESYTEC MbH - 0060A9 (base 16) GESYTEC MbH - PASCALSTRASSE 6 - D 52076 AACHEN - GERMANY - - 00-60-AA (hex) INTELLIGENT DEVICES INC. (IDI) - 0060AA (base 16) INTELLIGENT DEVICES INC. (IDI) - 1718-L BELMONT AVENUE - BALTIMORE MD 21244 - UNITED STATES - - 00-60-AB (hex) LARSCOM INCORPORATED - 0060AB (base 16) LARSCOM INCORPORATED - 1845 MCCANDLESS DRIVE - MILPITAS CA 95035 - UNITED STATES - - 00-60-AC (hex) RESILIENCE CORPORATION - 0060AC (base 16) RESILIENCE CORPORATION - 1755 EMBARCADERO ROAD-STE #120 - PALO ALTO CA 94303 - UNITED STATES - - 00-60-AD (hex) MegaChips Corporation - 0060AD (base 16) MegaChips Corporation - 4-1-6,Miyahara - Yodogawa-ku - Osaka 532-0003 - JAPAN - - 00-60-AE (hex) TRIO INFORMATION SYSTEMS AB - 0060AE (base 16) TRIO INFORMATION SYSTEMS AB - FOGDEVAGEN 4B - S-183 64 TABY - SWEDEN - - 00-60-AF (hex) PACIFIC MICRO DATA, INC. - 0060AF (base 16) PACIFIC MICRO DATA, INC. - 16751 MILLIKAN AVENUE - IRVINE CA 92714 - UNITED STATES - - 00-60-B0 (hex) HEWLETT-PACKARD CO. - 0060B0 (base 16) HEWLETT-PACKARD CO. - MS 42LE - 10000 WOLFE ROAD - CUPERTINO CA 95014 - UNITED STATES - - 00-60-B1 (hex) INPUT/OUTPUT, INC. - 0060B1 (base 16) INPUT/OUTPUT, INC. - 12300 PARC CREST DRIVE - STAFFORD TX 77477-2416 - UNITED STATES - - 00-60-B2 (hex) PROCESS CONTROL CORP. - 0060B2 (base 16) PROCESS CONTROL CORP. - 6875 MIMMS DRIVE - ATLANTA GA 30340 - UNITED STATES - - 00-60-B3 (hex) Z-COM, INC. - 0060B3 (base 16) Z-COM, INC. - 7F-2, NO.9, PROSPERITY 1ST RD. - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-60-B4 (hex) GLENAYRE R&D INC. - 0060B4 (base 16) GLENAYRE R&D INC. - 1570 KOOTENAY STREET - VANCOUVER, BC V5K 5B8 - CANADA - - 00-60-B5 (hex) KEBA GmbH - 0060B5 (base 16) KEBA GmbH - GEWERBEPARK URFAHR - A-4041 LINZ - AUSTRIA - - 00-60-B6 (hex) LAND COMPUTER CO., LTD. - 0060B6 (base 16) LAND COMPUTER CO., LTD. - 7-4-17 NISHINAKAJIMA - YODOGAWAKU 532 - JAPAN - - 00-60-B7 (hex) CHANNELMATIC, INC. - 0060B7 (base 16) CHANNELMATIC, INC. - 1700 GILLESPIE WAY - EL CAJON CA 92020-0901 - UNITED STATES - - 00-60-B8 (hex) CORELIS Inc. - 0060B8 (base 16) CORELIS Inc. - 12607 Hiddencreek Way - Cerritos CA 90703 - UNITED STATES - - 00-60-B9 (hex) NEC Platforms, Ltd - 0060B9 (base 16) NEC Platforms, Ltd - 2-6-1,Kitamikata,Takatsu-ku - Kawasaki 213-8511 - JAPAN - - 00-60-BA (hex) SAHARA NETWORKS, INC. - 0060BA (base 16) SAHARA NETWORKS, INC. - 335 HIGHLAND AVE. - CHESHIRE CT 06410 - UNITED STATES - - 00-60-BB (hex) CABLETRON - NETLINK, INC. - 0060BB (base 16) CABLETRON - NETLINK, INC. - 35 INDUSTRIAL WAY - P.O. BOX 5005 - ROCHESTER NH 03866-5005 - UNITED STATES - - 00-60-BC (hex) KeunYoung Electronics & Communication Co., Ltd. - 0060BC (base 16) KeunYoung Electronics & Communication Co., Ltd. - 325-76, DAEHEUNG-DONG, MAPO-GU, - SEOUL - KOREA, REPUBLIC OF - - 00-60-BD (hex) HUBBELL-PULSECOM - 0060BD (base 16) HUBBELL-PULSECOM - 2900 TOWERVIEW ROAD - HERNDON VA 21071 - UNITED STATES - - 00-60-BE (hex) WEBTRONICS - 0060BE (base 16) WEBTRONICS - 3B-1 8-2-12 - NISHI-GOTANDA - SHINAGAWA-KU TOKYO 141 - JAPAN - - 00-60-BF (hex) MACRAIGOR SYSTEMS, INC. - 0060BF (base 16) MACRAIGOR SYSTEMS, INC. - PO BOX 1008 - BROOKLINE VILLAGE MA 02147 - UNITED STATES - - 00-60-C0 (hex) Nera Networks AS - 0060C0 (base 16) Nera Networks AS - Kokstadveien 23 - Bergen 5020 - NORWAY - - 00-60-C1 (hex) WaveSpan Corporation - 0060C1 (base 16) WaveSpan Corporation - 500 N. BERNARDO AVE. - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-60-C2 (hex) MPL AG - 0060C2 (base 16) MPL AG - Taefernstrasse 20 - CH-5405 Daettwil - SWITZERLAND - - 00-60-C3 (hex) NETVISION CORPORATION - 0060C3 (base 16) NETVISION CORPORATION - MS# 1A - ONE COMAC LOOP - RONKONKOMA NY 11779 - UNITED STATES - - 00-60-C4 (hex) SOLITON SYSTEMS K.K. - 0060C4 (base 16) SOLITON SYSTEMS K.K. - 2-4-3 SHINJUKU, SHINJUKU-KU - TOKYO 160 - JAPAN - - 00-60-C5 (hex) ANCOT CORP. - 0060C5 (base 16) ANCOT CORP. - 115 CONSTITUTION DR. - MENLO PARK CA 94025 - UNITED STATES - - 00-60-C6 (hex) DCS AG - 0060C6 (base 16) DCS AG - SALZACHSTRASS 31 - D-14129 BERLIN - GERMANY - - 00-60-C7 (hex) AMATI COMMUNICATIONS CORP. - 0060C7 (base 16) AMATI COMMUNICATIONS CORP. - 2043 SAMARITAN DRIVE - SAN JOSE CA 95124 - UNITED STATES - - 00-60-C8 (hex) KUKA WELDING SYSTEMS & ROBOTS - 0060C8 (base 16) KUKA WELDING SYSTEMS & ROBOTS - BLUECHERSTRASSE 144 - DEPT. RE-SH - D-86165 AUGSBURG - GERMANY - - 00-60-C9 (hex) ControlNet, Inc. - 0060C9 (base 16) ControlNet, Inc. - 747 CAMDEN, STE. A - CAMPBELL CA 95008 - UNITED STATES - - 00-60-CA (hex) HARMONIC SYSTEMS INCORPORATED - 0060CA (base 16) HARMONIC SYSTEMS INCORPORATED - 199 1ST STREET - STE #302 - LOS ALTOS CA 94022 - UNITED STATES - - 00-60-CB (hex) HITACHI ZOSEN CORPORATION - 0060CB (base 16) HITACHI ZOSEN CORPORATION - 3-4, SAKURAJIMA 1-CHOME - KONOHANA-KU, OSAKA 554 - JAPAN - - 00-60-CC (hex) EMTRAK, INCORPORATED - 0060CC (base 16) EMTRAK, INCORPORATED - 7150 CAMPUS DRIVE, STE #180 - COLORADO SPRINGS CO 80920 - UNITED STATES - - 00-60-CD (hex) VideoServer, Inc. - 0060CD (base 16) VideoServer, Inc. - 5 FORBES ROAD - LEXINGTON MA 02173 - UNITED STATES - - 00-60-CE (hex) ACCLAIM COMMUNICATIONS - 0060CE (base 16) ACCLAIM COMMUNICATIONS - 5000 OLD IRONSIDES DRIVE - SANTA CLARA CA 95054 - UNITED STATES - - 00-60-CF (hex) ALTEON NETWORKS, INC. - 0060CF (base 16) ALTEON NETWORKS, INC. - 50 GREAT OAKS BLVD. - SAN JOSE CA 95119 - UNITED STATES - - 00-60-D0 (hex) SNMP RESEARCH INCORPORATED - 0060D0 (base 16) SNMP RESEARCH INCORPORATED - 3001 KIMBERLIN HEIGHTS ROAD - KNOXVILLE TN 37920-9716 - UNITED STATES - - 00-60-D1 (hex) CASCADE COMMUNICATIONS - 0060D1 (base 16) CASCADE COMMUNICATIONS - 6 TECHNOLOGY PARK DRIVE - WESTFORD MA 01886 - UNITED STATES - - 00-60-D2 (hex) LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD. - 0060D2 (base 16) LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD. - #2, INNOVATION ROAD II - SCIENCE-BASED INDUSTRIAL PARK - HSIN CHU - TAIWAN, PROVINCE OF CHINA - - 00-60-D3 (hex) AT&T - 0060D3 (base 16) AT&T - 101 CRAWFORDS CORNER ROAD, Rd. 1J321 - P.O. BOX 3030 - HOLMDEL NJ 07733-3030 - UNITED STATES - - 00-60-D4 (hex) ELDAT COMMUNICATION LTD. - 0060D4 (base 16) ELDAT COMMUNICATION LTD. - 10 HAKISHON STREET - BNEI-BRAK 51203 - ISRAEL - - 00-60-D5 (hex) MIYACHI TECHNOS CORP. - 0060D5 (base 16) MIYACHI TECHNOS CORP. - 95-3, FUTASUZUKA - NODA CITY, CHIBA, 278 - JAPAN - - 00-60-D6 (hex) NovAtel Wireless Technologies Ltd. - 0060D6 (base 16) NovAtel Wireless Technologies Ltd. - SUITE 200, 6715-8TH STREET NE - CALGARY, ALBERTA T2E 8M4 - CANADA - - 00-60-D7 (hex) ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (EPFL) - 0060D7 (base 16) ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (EPFL) - ECUBLENS - CH-1015 LAUSANNE - SWITZERLAND - - 00-60-D8 (hex) ELMIC SYSTEMS, INC. - 0060D8 (base 16) ELMIC SYSTEMS, INC. - DAI-ICHI SEIMEI BLDG. - 4-59 BENTEN-DORI, NAKA-KU - YOKOHAMA 231 - JAPAN - - 00-60-D9 (hex) TRANSYS NETWORKS INC. - 0060D9 (base 16) TRANSYS NETWORKS INC. - 3403 GRIFFITH - ST. LAURENT, QUEBEC H4T 1W5 - CANADA - - 00-60-DA (hex) Red Lion Controls, LP - 0060DA (base 16) Red Lion Controls, LP - 20 Willow Springs Circle - York PA 17402 - UNITED STATES - - 00-60-DB (hex) NTP ELEKTRONIK A/S - 0060DB (base 16) NTP ELEKTRONIK A/S - KNAPHOLM 7 - DK-2730 HERLEV - DENMARK - - 00-60-DC (hex) Toyo Network Systems & System Integration Co. LTD - 0060DC (base 16) Toyo Network Systems & System Integration Co. LTD - 18 Nihon-odori,Naka-ku - Yokohama, Kanagawa 231-0021 - JAPAN - - 00-60-DD (hex) MYRICOM, INC. - 0060DD (base 16) MYRICOM, INC. - 325B N. SANTA ANITA AVE. - ARCADIA CA 91006 - UNITED STATES - - 00-60-DE (hex) Kayser-Threde GmbH - 0060DE (base 16) Kayser-Threde GmbH - Wolfratshauser Str. 48 - D-81379 Munich - GERMANY - - 00-60-DF (hex) Brocade Communications Systems, Inc. - 0060DF (base 16) Brocade Communications Systems, Inc. - 1745 Technology Dr. - San Jose CA 95110 - UNITED STATES - - 00-60-E0 (hex) AXIOM TECHNOLOGY CO., LTD. - 0060E0 (base 16) AXIOM TECHNOLOGY CO., LTD. - 3F, 14, LANE 235 - PAO CHIAO ROAD, HSIN TIEN - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-60-E1 (hex) ORCKIT COMMUNICATIONS LTD. - 0060E1 (base 16) ORCKIT COMMUNICATIONS LTD. - 38 NAHALAT YIZHAK STREET - TEL-AVIV 67448 - ISRAEL - - 00-60-E2 (hex) QUEST ENGINEERING & DEVELOPMENT - 0060E2 (base 16) QUEST ENGINEERING & DEVELOPMENT - 1345 EAST ROCK WREN ROAD - PHOENIX AZ 85048 - UNITED STATES - - 00-60-E3 (hex) ARBIN INSTRUMENTS - 0060E3 (base 16) ARBIN INSTRUMENTS - 3206 LONGMIRE DRIVE - COLLEGE STATION TX 77845 - UNITED STATES - - 00-60-E4 (hex) COMPUSERVE, INC. - 0060E4 (base 16) COMPUSERVE, INC. - 5000 ARLINGTON CENTRE BLVD. - P.O. BOX 20212 - COLUMBUS OH 43220 - UNITED STATES - - 00-60-E5 (hex) FUJI AUTOMATION CO., LTD. - 0060E5 (base 16) FUJI AUTOMATION CO., LTD. - 3-23-10, NEGISHI - URAWA-SHI, 336 SAITAMA - JAPAN - - 00-60-E6 (hex) SHOMITI SYSTEMS INCORPORATED - 0060E6 (base 16) SHOMITI SYSTEMS INCORPORATED - 2099 GATEWAY PLACE - STE.#220 - SAN JOSE CA 95110 - UNITED STATES - - 00-60-E7 (hex) RANDATA - 0060E7 (base 16) RANDATA - PO BOX 209 - HAWTHORN VIC 3122 - AUSTRALIA - - 00-60-E8 (hex) HITACHI COMPUTER PRODUCTS (AMERICA), INC. - 0060E8 (base 16) HITACHI COMPUTER PRODUCTS (AMERICA), INC. - 3101 TASMAN DRIVE - SANTA CLARA CA 95054 - UNITED STATES - - 00-60-E9 (hex) ATOP TECHNOLOGIES, INC. - 0060E9 (base 16) ATOP TECHNOLOGIES, INC. - SUITE 305, NO. 47, PARK AVENUE II, - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU 30047 - TAIWAN, PROVINCE OF CHINA - - 00-60-EA (hex) StreamLogic - 0060EA (base 16) StreamLogic - 21329 NORDHOFF STREET - CHATSWORTH CA 91311 - UNITED STATES - - 00-60-EB (hex) FOURTHTRACK SYSTEMS - 0060EB (base 16) FOURTHTRACK SYSTEMS - UNIT 3 THE SYCAMORES - 27 MILL ROAD - MARLOW - SL7 1QB - UNITED KINGDOM - - 00-60-EC (hex) HERMARY OPTO ELECTRONICS INC. - 0060EC (base 16) HERMARY OPTO ELECTRONICS INC. - 201-4050 GRAVELEY ST - BURNABY, BC V5C-3T6 - CANADA - - 00-60-ED (hex) RICARDO TEST AUTOMATION LTD. - 0060ED (base 16) RICARDO TEST AUTOMATION LTD. - LOWESMOOR WHARF - WORCESTER, WR12RS - UNITED KINGDOM - - 00-60-EE (hex) APOLLO - 0060EE (base 16) APOLLO - 3610 BIRCH STREET--STE #100 - NEWPORT BEACH CA 92660 - UNITED STATES - - 00-60-EF (hex) FLYTECH TECHNOLOGY CO., LTD. - 0060EF (base 16) FLYTECH TECHNOLOGY CO., LTD. - No.168 Sing-ai Rd., Neihu District - TAIPEI CITY 114 - TAIWAN, PROVINCE OF CHINA - - 00-60-F0 (hex) JOHNSON & JOHNSON MEDICAL, INC - 0060F0 (base 16) JOHNSON & JOHNSON MEDICAL, INC - 4110 GEORGE RD. - TAMPA FL 33634 - UNITED STATES - - 00-60-F1 (hex) EXP COMPUTER, INC. - 0060F1 (base 16) EXP COMPUTER, INC. - 141 EILEEN WAY - SYOSSET NY 11791 - UNITED STATES - - 00-60-F2 (hex) LASERGRAPHICS, INC. - 0060F2 (base 16) LASERGRAPHICS, INC. - 20 ADA - IRVINE CA 92718 - UNITED STATES - - 00-60-F3 (hex) Performance Analysis Broadband, Spirent plc - 0060F3 (base 16) Performance Analysis Broadband, Spirent plc - 27349 Agoura Road - Calabasas Hills CA 91301 - UNITED STATES - - 00-60-F4 (hex) ADVANCED COMPUTER SOLUTIONS, Inc. - 0060F4 (base 16) ADVANCED COMPUTER SOLUTIONS, Inc. - 12675 DANIELSON COURT - SUITE #407 - POWAY CA 92064 - UNITED STATES - - 00-60-F5 (hex) ICON WEST, INC. - 0060F5 (base 16) ICON WEST, INC. - 3342 SOUTH 300 EAST - SALT LAKE CITY UT 84115 - UNITED STATES - - 00-60-F6 (hex) NEXTEST COMMUNICATIONS PRODUCTS, INC. - 0060F6 (base 16) NEXTEST COMMUNICATIONS PRODUCTS, INC. - TWO MID AMERICA PLAZA, STE.500 - OAKBROOK TERRACE IL 60181 - UNITED STATES - - 00-60-F7 (hex) DATAFUSION SYSTEMS - 0060F7 (base 16) DATAFUSION SYSTEMS - P.O. BOX 582 - STELLENBOSCH, 7599 - SOUTH AFRICA - - 00-60-F8 (hex) Loran International Technologies Inc. - 0060F8 (base 16) Loran International Technologies Inc. - 955 GREEN VALLEY CRESCENT - SUITE #165 - OTTAWA, ONTARIO K2C 3V4 - CANADA - - 00-60-F9 (hex) DIAMOND LANE COMMUNICATIONS - 0060F9 (base 16) DIAMOND LANE COMMUNICATIONS - 1310 REDWOOD WAY - STE. - PETALUMA CA 94954 - UNITED STATES - - 00-60-FA (hex) EDUCATIONAL TECHNOLOGY RESOURCES, INC. - 0060FA (base 16) EDUCATIONAL TECHNOLOGY RESOURCES, INC. - 1742 CHURCH STREET - HOLBROOK NY 11741 - UNITED STATES - - 00-60-FB (hex) PACKETEER, INC. - 0060FB (base 16) PACKETEER, INC. - 10201 N. DE ANZA BOULEVARD - CUPERTINO CA 95014 - UNITED STATES - - 00-60-FC (hex) CONSERVATION THROUGH INNOVATION LTD. - 0060FC (base 16) CONSERVATION THROUGH INNOVATION LTD. - 1040 WHIPPLE ST.- STE. #225 - PRESCOTT AZ 86301 - UNITED STATES - - 00-60-FD (hex) NetICs, Inc. - 0060FD (base 16) NetICs, Inc. - 42 NAGOG PARK - ACTON MA 01720 - UNITED STATES - - 00-60-FE (hex) LYNX SYSTEM DEVELOPERS, INC. - 0060FE (base 16) LYNX SYSTEM DEVELOPERS, INC. - 175N NEW BOSTON STREET - WOBURN MA 01801 - UNITED STATES - - 00-60-FF (hex) QuVis, Inc. - 0060FF (base 16) QuVis, Inc. - 2921 SW WANAMAKER DRIVE - SUITE #107 - TOPEKA KS 66614 - UNITED STATES - - 00-61-71 (hex) Apple - 006171 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-64-40 (hex) CISCO SYSTEMS, INC. - 006440 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-64-A6 (hex) Maquet CardioVascular - 0064A6 (base 16) Maquet CardioVascular - 1300 MacArthur Blvd - Mahwah NJ 07430 - UNITED STATES - - 00-66-4B (hex) Huawei Technologies Co., Ltd - 00664B (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - 00-6B-8E (hex) Shanghai Feixun Communication Co.,Ltd. - 006B8E (base 16) Shanghai Feixun Communication Co.,Ltd. - Building 90,No,4855,Guangfulin Road - ,Songjiang District - Shanghai 201616 - CHINA - - 00-6B-9E (hex) VIZIO Inc - 006B9E (base 16) VIZIO Inc - 39 Tesla - Irvine CA 92618 - UNITED STATES - - 00-6B-A0 (hex) SHENZHEN UNIVERSAL INTELLISYS PTE LTD - 006BA0 (base 16) SHENZHEN UNIVERSAL INTELLISYS PTE LTD - ROOM 1607-1608,XINGJI MANSION - XINXINSHA ROAD, SHAJING TOWN - SHENZHEN GUANGDONG 518104 - CHINA - - 00-6D-FB (hex) Vutrix (UK) Ltd - 006DFB (base 16) Vutrix (UK) Ltd - Unit 1 Red Lodge Business Park - Warleys Lane - Weston-super-mare North Somerset BS24 7TN - UNITED KINGDOM - - 00-70-B0 (hex) M/A-COM INC. COMPANIES - 0070B0 (base 16) M/A-COM INC. COMPANIES - 11717 EXPLORATION LANE - GERMANTOWN MD 20767 - UNITED STATES - - 00-70-B3 (hex) DATA RECALL LTD. - 0070B3 (base 16) DATA RECALL LTD. - SONDES PLACE - DORKING SURREY RH4 3EF - UNITED KINGDOM - UNITED KINGDOM - - 00-71-C2 (hex) PEGATRON CORPORATION - 0071C2 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 00-71-CC (hex) Hon Hai Precision Ind. Co.,Ltd. - 0071CC (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District,Chongqing,China - Chongqing Chongqing 401332 - CHINA - - 00-73-8D (hex) Tinno Mobile Technology Corp - 00738D (base 16) Tinno Mobile Technology Corp - 4/F.,H-3 Building,OCT Eastern lndustrial Park. NO.1 XiangShan East Road. - Nanshan District - GuangDong Shenzhen 518053 - CHINA - - 00-73-E0 (hex) Samsung Electronics Co.,Ltd - 0073E0 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-75-32 (hex) INID BV - 007532 (base 16) INID BV - Mariettahof 27 - Haarlem NH 2033WS - NETHERLANDS - - 00-75-E1 (hex) Ampt, LLC - 0075E1 (base 16) Ampt, LLC - 4850 Innovation Drive - Fort Collins Colorado 80525 - UNITED STATES - - 00-78-9E (hex) SAGEMCOM - 00789E (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON 92848 - FRANCE - - 00-7D-FA (hex) Volkswagen Group of America - 007DFA (base 16) Volkswagen Group of America - 3800 Hamlin Rd - Auburn Hills MI 48326 - UNITED STATES - - 00-7E-56 (hex) China Dragon Technology Limited - 007E56 (base 16) China Dragon Technology Limited - B4 Bldg.Haoshan 1st Industry Park, - Nanpu Rd, Shajing Town, Bao'an Dist. - Shenzhen Guangdong 518104 - CHINA - - 00-7F-28 (hex) Actiontec Electronics, Inc - 007F28 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 00-80-00 (hex) MULTITECH SYSTEMS, INC. - 008000 (base 16) MULTITECH SYSTEMS, INC. - 2205 WOODALE DRIVE - MOUNDS VIEW MN 55112 - UNITED STATES - - 00-80-01 (hex) PERIPHONICS CORPORATION - 008001 (base 16) PERIPHONICS CORPORATION - 4000 VETERANS MEMORIAL HIGHWAY - BOHEMIA NEW YORK 11716 - UNITED STATES - - 00-80-02 (hex) SATELCOM (UK) LTD - 008002 (base 16) SATELCOM (UK) LTD - TECHNOLOGY TRANSFER CENTRE - SILWOOD PARK, BUCKHURST ROAD ASCOT, BERK - ENGLAND - UNITED KINGDOM - - 00-80-03 (hex) HYTEC ELECTRONICS LTD. - 008003 (base 16) HYTEC ELECTRONICS LTD. - 5 CRADOCK ROAD - READING BERKS RG5 4DX - ENGLAND - UNITED KINGDOM - - 00-80-04 (hex) ANTLOW COMMUNICATIONS, LTD. - 008004 (base 16) ANTLOW COMMUNICATIONS, LTD. - 4 COLTHROP WAY - THATCHAM RG19 4LW - ENGLAND - UNITED KINGDOM - - 00-80-05 (hex) CACTUS COMPUTER INC. - 008005 (base 16) CACTUS COMPUTER INC. - 1120 METROCREST DRIVE - SUITE 103 - CARROLLTON TX 75006 - UNITED STATES - - 00-80-06 (hex) COMPUADD CORPORATION - 008006 (base 16) COMPUADD CORPORATION - ENGINEERING - 12303 TECHNOLOGY BLVD. - AUSTIN TX 78727 - UNITED STATES - - 00-80-07 (hex) DLOG NC-SYSTEME - 008007 (base 16) DLOG NC-SYSTEME - WERNER-VON-SIEMENS STRASSE 13 - D-8037, OLCHING - GERMANY - - 00-80-08 (hex) DYNATECH COMPUTER SYSTEMS - 008008 (base 16) DYNATECH COMPUTER SYSTEMS - 280 BERNARDO AVENUE - P.O. BOX 7400 - MOUNTAIN VIEW CA 94039-7400 - UNITED STATES - - 00-80-09 (hex) JUPITER SYSTEMS, INC. - 008009 (base 16) JUPITER SYSTEMS, INC. - 3073 TEAGARDEN STREET - SAN LEANDRO CA 94577-5720 - UNITED STATES - - 00-80-0A (hex) JAPAN COMPUTER CORP. - 00800A (base 16) JAPAN COMPUTER CORP. - L. K. BLDG. HIGASHI KANDA - 2-6-9 CHIYODA-KU TOKYO 101 - JAPAN - - 00-80-0B (hex) CSK CORPORATION - 00800B (base 16) CSK CORPORATION - 18F MATSUSHITA IMP BLDG, - 1-3-7 SHIROMI CHUO-KU OSAKA - JAPAN 540 - JAPAN - - 00-80-0C (hex) VIDECOM LIMITED - 00800C (base 16) VIDECOM LIMITED - NEWTOWN ESTATE - HENLEY-ON-THAMES OXON RG9 1HG - ENGLAND - UNITED KINGDOM - - 00-80-0D (hex) VOSSWINKEL F.U. - 00800D (base 16) VOSSWINKEL F.U. - AM JOSTENHOF 15 - D-4130 MOERS - GERMANY - - 00-80-0E (hex) ATLANTIX CORPORATION - 00800E (base 16) ATLANTIX CORPORATION - 5401 NW BROKENSOUND BLVD. - BOCA RATON FL 33431 - UNITED STATES - - 00-80-0F (hex) STANDARD MICROSYSTEMS - 00800F (base 16) STANDARD MICROSYSTEMS - 300 KENNEDY DRIVE - HAUPPAUGE NY 11788 - UNITED STATES - - 00-80-10 (hex) COMMODORE INTERNATIONAL - 008010 (base 16) COMMODORE INTERNATIONAL - 1200 WILSON DRIVE - WEST CHESTER PA 19380 - UNITED STATES - - 00-80-11 (hex) DIGITAL SYSTEMS INT'L. INC. - 008011 (base 16) DIGITAL SYSTEMS INT'L. INC. - 7659 178TH PL. NE - P.O. BOX 908 - REDMOND WA 98073-0908 - UNITED STATES - - 00-80-12 (hex) INTEGRATED MEASUREMENT SYSTEMS - 008012 (base 16) INTEGRATED MEASUREMENT SYSTEMS - 9525 SW GEMINI DRIVE - BEAVERTON OR 97005 - UNITED STATES - - 00-80-13 (hex) THOMAS-CONRAD CORPORATION - 008013 (base 16) THOMAS-CONRAD CORPORATION - 1908-R KRAMER LANE - AUSTIN TX 78758 - UNITED STATES - - 00-80-14 (hex) ESPRIT SYSTEMS - 008014 (base 16) ESPRIT SYSTEMS - 14F, NO. 1, SEC. 4 - NAN KING EAST ROAD 10569 TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-80-15 (hex) SEIKO SYSTEMS, INC. - 008015 (base 16) SEIKO SYSTEMS, INC. - 8,Nakase 1-chome,Mihama-ku - 8,Nakase 1-chome,Mihama-ku - JAPAN - - 00-80-16 (hex) WANDEL AND GOLTERMANN - 008016 (base 16) WANDEL AND GOLTERMANN - 1030 SWABIA COURT - RESEARCH TRIANGLE PARK - NC 27709 - UNITED STATES - - 00-80-17 (hex) PFU LIMITED - 008017 (base 16) PFU LIMITED - NETWORK SEC. - 658-1, TSURUMA MACHIDA-SHI, TOKYO 194-00 - JAPAN - - 00-80-18 (hex) KOBE STEEL, LTD. - 008018 (base 16) KOBE STEEL, LTD. - KOBE ISUZU RECRUIT BLDG. - 7TH FLOOR 2-2, 4-CHOME, KUMOI-DORI, CHUO - JAPAN - - 00-80-19 (hex) DAYNA COMMUNICATIONS, INC. - 008019 (base 16) DAYNA COMMUNICATIONS, INC. - 50 SOUTH MAIN STREET-#530 - SALT LAKE CITY UTAH 84144 - UNITED STATES - - 00-80-1A (hex) BELL ATLANTIC - 00801A (base 16) BELL ATLANTIC - N92 W14612 ANTHONY AVENUE - MENOMONEE FALLS WI 53051 - UNITED STATES - - 00-80-1B (hex) KODIAK TECHNOLOGY - 00801B (base 16) KODIAK TECHNOLOGY - 2340 HARRIS WAY - SAN JOSE CA 95131 - UNITED STATES - - 00-80-1C (hex) NEWPORT SYSTEMS SOLUTIONS - 00801C (base 16) NEWPORT SYSTEMS SOLUTIONS - 4019 WESTERLY AVENUE - SUITE 103 - NEWPORT BEACH CA 92660 - UNITED STATES - - 00-80-1D (hex) INTEGRATED INFERENCE MACHINES - 00801D (base 16) INTEGRATED INFERENCE MACHINES - 1468 EAST KATELLA - ANAHEIM CA 92805 - UNITED STATES - - 00-80-1E (hex) XINETRON, INC. - 00801E (base 16) XINETRON, INC. - 2330 B. WALSH AVE. - SANTA CLARA CA 95051 - UNITED STATES - - 00-80-1F (hex) KRUPP ATLAS ELECTRONIK GMBH - 00801F (base 16) KRUPP ATLAS ELECTRONIK GMBH - P.O. BOX 448545 - D-2800 BREMEN 44 - GERMANY - - 00-80-20 (hex) NETWORK PRODUCTS - 008020 (base 16) NETWORK PRODUCTS - DIVISION OF ANDREW CORPORATION - 2771 PLAZA DEL AMO3 - TORRANCE CA 90503 - UNITED STATES - - 00-80-21 (hex) Alcatel Canada Inc. - 008021 (base 16) Alcatel Canada Inc. - 349 Terry Fox Drive - Kanata Ontario K2K 2V6 - CANADA - - 00-80-22 (hex) SCAN-OPTICS - 008022 (base 16) SCAN-OPTICS - 201 TECHNOLOGY DRIVE - IRVINE CA 92718 - UNITED STATES - - 00-80-23 (hex) INTEGRATED BUSINESS NETWORKS - 008023 (base 16) INTEGRATED BUSINESS NETWORKS - 1BN THE SYSTEMS CENTRE - 14, BRIDGEGATE BUSINESS PARK, GATEHOUSE - BUCKS HP19 3XN - ENGLAND - UNITED KINGDOM - - 00-80-24 (hex) KALPANA, INC. - 008024 (base 16) KALPANA, INC. - 1154 EAST ARQUES AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-80-25 (hex) STOLLMANN GMBH - 008025 (base 16) STOLLMANN GMBH - MAX-BRAUER-ALLEE 81 - D-2000 HAMBURG 50 - GERMANY - - 00-80-26 (hex) NETWORK PRODUCTS CORPORATION - 008026 (base 16) NETWORK PRODUCTS CORPORATION - 1440 WEST COLORADO BLVD. - PASADENA CA 91105 - UNITED STATES - - 00-80-27 (hex) ADAPTIVE SYSTEMS, INC. - 008027 (base 16) ADAPTIVE SYSTEMS, INC. - 1400 N.W. COMPTON DRIVE - SUITE 340 - BEAVERTON OR 97006 - UNITED STATES - - 00-80-28 (hex) TRADPOST (HK) LTD - 008028 (base 16) TRADPOST (HK) LTD - 5/F, STAR CENTRE - 443-451 CASTLE PEAK ROAD KWAI CHUNG, N.T - HONG KONG - HONG KONG - - 00-80-29 (hex) EAGLE TECHNOLOGY, INC. - 008029 (base 16) EAGLE TECHNOLOGY, INC. - 6800 ORANGETHORPE AVE.UNIT - BUENA PARK CA 90620 - UNITED STATES - - 00-80-2A (hex) TEST SYSTEMS & SIMULATIONS INC - 00802A (base 16) TEST SYSTEMS & SIMULATIONS INC - 32429 INDUSTRIAL DRIVE - MADISON HEIGHTS MI 48071-1528 - UNITED STATES - - 00-80-2B (hex) INTEGRATED MARKETING CO - 00802B (base 16) INTEGRATED MARKETING CO - 1360 BORDEAUX DRIVE - BLDG. #4 - SUNNYVALE CA 94089 - UNITED STATES - - 00-80-2C (hex) THE SAGE GROUP PLC - 00802C (base 16) THE SAGE GROUP PLC - SAGE HOUSE, BENTON PARK ROAD - NEWCASTLE UPON TYNE NE7 7LZ - UNITED KINGDOM - UNITED KINGDOM - - 00-80-2D (hex) XYLOGICS INC - 00802D (base 16) XYLOGICS INC - 53 THIRD AVENUE - BURLINGTON MA 01803 - UNITED STATES - - 00-80-2E (hex) CASTLE ROCK COMPUTING - 00802E (base 16) CASTLE ROCK COMPUTING - 20837 BOYCE LANE - SARATOGA CA 95070-4806 - UNITED STATES - - 00-80-2F (hex) NATIONAL INSTRUMENTS CORP. - 00802F (base 16) NATIONAL INSTRUMENTS CORP. - 11500 North Mopac Expressway - AUSTIN TX 78759-3504 - UNITED STATES - - 00-80-30 (hex) NEXUS ELECTRONICS - 008030 (base 16) NEXUS ELECTRONICS - 39 SPRINGFIELD ROAD - CAMBRIDGE CB4 1AD - UNITED KINGDOM - UNITED KINGDOM - - 00-80-31 (hex) BASYS, CORP. - 008031 (base 16) BASYS, CORP. - 501 MACARA AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-80-32 (hex) ACCESS CO., LTD. - 008032 (base 16) ACCESS CO., LTD. - HIEI-KUDAN BLDG. B1 - 3-8-11 KUDAN-MINAMI, CHIYODA-KU, TOKYO 1 - JAPAN - - 00-80-33 (hex) EMS Aviation, Inc. - 008033 (base 16) EMS Aviation, Inc. - 121 WHITTENDALE DRIVE - Suite A - MOORESTOWN NJ 08057 - UNITED STATES - - 00-80-34 (hex) SMT GOUPIL - 008034 (base 16) SMT GOUPIL - 3 RUE DES ARCHIVES - 94000 CRETEIL - FRANCE - - 00-80-35 (hex) TECHNOLOGY WORKS, INC. - 008035 (base 16) TECHNOLOGY WORKS, INC. - 4030 BRAKER LANE #350 - AUSTIN TX 78759 - UNITED STATES - - 00-80-36 (hex) REFLEX MANUFACTURING SYSTEMS - 008036 (base 16) REFLEX MANUFACTURING SYSTEMS - UNIT D, THE FLEMING CENTRE, - FLEMING WAY, CRAWLEY WEST SUSSEX RH10 2N - ENGLAND - UNITED KINGDOM - - 00-80-37 (hex) Ericsson Group - 008037 (base 16) Ericsson Group - Telefonaktiebolaget - LM Ericsson Corp. 126 25 STOCKHOLM - SWEDEN - - 00-80-38 (hex) DATA RESEARCH & APPLICATIONS - 008038 (base 16) DATA RESEARCH & APPLICATIONS - 9041 EXECUTIVE PARK DR. - SUITE 200 - KNOXVILLE TN 37923-4609 - UNITED STATES - - 00-80-39 (hex) ALCATEL STC AUSTRALIA - 008039 (base 16) ALCATEL STC AUSTRALIA - 252-280 BOTANY ROAD - ALEXANDRIA, NSW 2015 - AUSTRALIA - - 00-80-3A (hex) VARITYPER, INC. - 00803A (base 16) VARITYPER, INC. - 900 MIDDLESEX TURNPIKE - BILLERICA MA 01821 - UNITED STATES - - 00-80-3B (hex) APT COMMUNICATIONS, INC. - 00803B (base 16) APT COMMUNICATIONS, INC. - 9607 DR. PERRY ROAD - IJAMSVILLE MD 21754 - UNITED STATES - - 00-80-3C (hex) TVS ELECTRONICS LTD - 00803C (base 16) TVS ELECTRONICS LTD - 44, MILLER ROAD - BANGALORE 560 052 - INDIA - - 00-80-3D (hex) SURIGIKEN CO., LTD. - 00803D (base 16) SURIGIKEN CO., LTD. - YOUTH BLDG, 4-1-9 SHINJUKU - SHINJUKU-KU, TOKYO - JAPAN - - 00-80-3E (hex) SYNERNETICS - 00803E (base 16) SYNERNETICS - 85 RANGEWAY ROAD - NORTH BILLERICA MA 01862 - UNITED STATES - - 00-80-3F (hex) TATUNG COMPANY - 00803F (base 16) TATUNG COMPANY - 22 CHUNGSHANG N. RD. 3RD SEC. - TAIPEI TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-80-40 (hex) JOHN FLUKE MANUFACTURING CO. - 008040 (base 16) JOHN FLUKE MANUFACTURING CO. - P.O. BOX C9090-M/S 244F - EVERETT WA 98206 - UNITED STATES - - 00-80-41 (hex) VEB KOMBINAT ROBOTRON - 008041 (base 16) VEB KOMBINAT ROBOTRON - GRUNAER STRAßE 2, DRESDEN 8010 - GDR EAST - GERMANY - - 00-80-42 (hex) Artesyn Embedded Technologies - 008042 (base 16) Artesyn Embedded Technologies - 2900 S. Diablo Way - Tempe AZ 85282 - UNITED STATES - - 00-80-43 (hex) NETWORLD, INC. - 008043 (base 16) NETWORLD, INC. - KANDA 3 AMEREX BLDG. - 3-10 KANDAJINBOCHO CHIYODA-KU TOKYO 1 - JAPAN - - 00-80-44 (hex) SYSTECH COMPUTER CORP. - 008044 (base 16) SYSTECH COMPUTER CORP. - 6465 NANCY RIDGE DRIVE - SAN DIEGO CA 92121 - UNITED STATES - - 00-80-45 (hex) MATSUSHITA ELECTRIC IND. CO - 008045 (base 16) MATSUSHITA ELECTRIC IND. CO - COMPUTER DIVISION - 1006, KADOMA, - OSAKA 571 - JAPAN - - 00-80-46 (hex) Tattile SRL - 008046 (base 16) Tattile SRL - DEPT. OF ELECTRICAL ENGIN'ING - 10 KINGS COLLEGE RD. TORONTO, ONTARIO M5 - CANADA - - 00-80-47 (hex) IN-NET CORP. - 008047 (base 16) IN-NET CORP. - 16720 WEST BERNARDO DRIVE - SAN DIEGO CA 92127-1904 - UNITED STATES - - 00-80-48 (hex) COMPEX INCORPORATED - 008048 (base 16) COMPEX INCORPORATED - 4055 EAST LA PALMA - UNIT - ANAHEIM CA 92807 - UNITED STATES - - 00-80-49 (hex) NISSIN ELECTRIC CO., LTD. - 008049 (base 16) NISSIN ELECTRIC CO., LTD. - 47, UMEZU - TAKASE - CHO - UKYO-KU, KYOTO, 615 - JAPAN - - 00-80-4A (hex) PRO-LOG - 00804A (base 16) PRO-LOG - 12 UPPER RAGSDALE DRIVE - MONTEREY CA 93940 - UNITED STATES - - 00-80-4B (hex) EAGLE TECHNOLOGIES PTY.LTD. - 00804B (base 16) EAGLE TECHNOLOGIES PTY.LTD. - 70 KEYS ROAD - MOORABBIN VIC. 3189 - AUSTRALIA - - 00-80-4C (hex) CONTEC CO., LTD. - 00804C (base 16) CONTEC CO., LTD. - 3-9-31, HIMESATO - NISHIYODOGAWA-KU OSAKA, 555 - JAPAN - - 00-80-4D (hex) CYCLONE MICROSYSTEMS, INC. - 00804D (base 16) CYCLONE MICROSYSTEMS, INC. - 25 SCIENCE PARK - NEW HAVEN CT 06511 - UNITED STATES - - 00-80-4E (hex) APEX COMPUTER COMPANY - 00804E (base 16) APEX COMPUTER COMPANY - 4500 150TH AVENUE, NE - REDMOND WA 98052 - UNITED STATES - - 00-80-4F (hex) DAIKIN INDUSTRIES, LTD. - 00804F (base 16) DAIKIN INDUSTRIES, LTD. - ELECTRONICS DIVISION - SHIGA PLANT 1000-2 OHTANI OKAMOTO-CHO, K - JAPAN 525 - JAPAN - - 00-80-50 (hex) ZIATECH CORPORATION - 008050 (base 16) ZIATECH CORPORATION - 3433 ROBERTO COURT - SAN LUIS OBISPO CA 93401 - UNITED STATES - - 00-80-51 (hex) FIBERMUX - 008051 (base 16) FIBERMUX - 9310 TOPANGA CANYON BLVD. - CHATSWORTH CA 91311 - UNITED STATES - - 00-80-52 (hex) TECHNICALLY ELITE CONCEPTS - 008052 (base 16) TECHNICALLY ELITE CONCEPTS - 2615 PACIFIC COAST HIGHWAY - HERMOSA BEACH CA 90250 - UNITED STATES - - 00-80-53 (hex) INTELLICOM, INC. - 008053 (base 16) INTELLICOM, INC. - 20415 NORDHOFF STREET - CHATSWORTH CA 91311 - UNITED STATES - - 00-80-54 (hex) FRONTIER TECHNOLOGIES CORP. - 008054 (base 16) FRONTIER TECHNOLOGIES CORP. - 10201 NO. PT. WASHINGTON ROAD - MEQUON WI 53092 - UNITED STATES - - 00-80-55 (hex) FERMILAB - 008055 (base 16) FERMILAB - P.O. BOX 500, MS-234 - BATAVIA IL 60510 - UNITED STATES - - 00-80-56 (hex) SPHINX ELEKTRONIK GMBH - 008056 (base 16) SPHINX ELEKTRONIK GMBH - WALDMATTENSTR, 13 - 7808 WALDKIRCH 3 RAPPENECKSTRAßE 1 - WEST - GERMANY - - 00-80-57 (hex) ADSOFT, LTD. - 008057 (base 16) ADSOFT, LTD. - Im Baumgarten 6 - MOHLIN CH-4313 - SWITZERLAND - - 00-80-58 (hex) PRINTER SYSTEMS CORPORATION - 008058 (base 16) PRINTER SYSTEMS CORPORATION - 207 PARRY PARKWAY - GAITHERSBURG MD 20877 - UNITED STATES - - 00-80-59 (hex) STANLEY ELECTRIC CO., LTD - 008059 (base 16) STANLEY ELECTRIC CO., LTD - R&D LABORATORY - 1-3-1 EDA-NISHI, MIDORI-KU, YOKOHAMA-SHI - JAPAN - - 00-80-5A (hex) TULIP COMPUTERS INTERNAT'L B.V - 00805A (base 16) TULIP COMPUTERS INTERNAT'L B.V - P.O. BOX 3333 - 5203 DH 'S-HERTOGENBOSCH - THE - NETHERLANDS - - 00-80-5B (hex) CONDOR SYSTEMS, INC. - 00805B (base 16) CONDOR SYSTEMS, INC. - 2133 SAMARILTAN DRIVE - SAN JOSE CA 95124 - UNITED STATES - - 00-80-5C (hex) AGILIS CORPORATION - 00805C (base 16) AGILIS CORPORATION - 1101 SAN ANTONIO ROAD - SUITE 101 - Mountain View CA 94043-1008 - UNITED STATES - - 00-80-5D (hex) CANSTAR - 00805D (base 16) CANSTAR - 3900 VICTORIA PARK AVENUE - NORTH YORK ONTARIO, CANADA - M2H 3H7 - CANADA - - 00-80-5E (hex) LSI LOGIC CORPORATION - 00805E (base 16) LSI LOGIC CORPORATION - 1551 MCCARTHY BOULEVARD - MS G813 - MILPITAS CA 95035 - UNITED STATES - - 00-80-5F (hex) Hewlett-Packard Company - 00805F (base 16) Hewlett-Packard Company - 20555 State Highway 249 - MS040801 - Houston TX 77070 - UNITED STATES - - 00-80-60 (hex) NETWORK INTERFACE CORPORATION - 008060 (base 16) NETWORK INTERFACE CORPORATION - 15019 WEST 95 STREET - LENEXA KS 66215 - UNITED STATES - - 00-80-61 (hex) LITTON SYSTEMS, INC. - 008061 (base 16) LITTON SYSTEMS, INC. - M/S 44-20 - 29851 AGOURA ROAD - AGOURA HILLS CA 91301-0500 - UNITED STATES - - 00-80-62 (hex) INTERFACE CO. - 008062 (base 16) INTERFACE CO. - 8-26 OZU 5-CHOME MINAMI-KU - HIROSHIMA 732 - JAPAN - - 00-80-63 (hex) Hirschmann Automation and Control GmbH - 008063 (base 16) Hirschmann Automation and Control GmbH - Stuttgarter Straße 45-51 - Neckartenzlingen D-72654 - GERMANY - - 00-80-64 (hex) WYSE TECHNOLOGY LLC - 008064 (base 16) WYSE TECHNOLOGY LLC - 3471 NORTH FIRST STREET M/S - SAN JOSE CA 95134 - UNITED STATES - - 00-80-65 (hex) CYBERGRAPHIC SYSTEMS PTY LTD. - 008065 (base 16) CYBERGRAPHIC SYSTEMS PTY LTD. - 290 BURWOOD ROAD - HAWTHORN, VICTORIA 3122 - AUSTRALIA - - 00-80-66 (hex) ARCOM CONTROL SYSTEMS, LTD. - 008066 (base 16) ARCOM CONTROL SYSTEMS, LTD. - UNIT 8, CLIFTON ROAD - CAMBRIDGE CBI 4WH - UNITED KINGDOM - UNITED KINGDOM - - 00-80-67 (hex) SQUARE D COMPANY - 008067 (base 16) SQUARE D COMPANY - 4041 NORTH RICHARD STREET - P.O. BOX 472 - MILWAUKEE WI 53201 - UNITED STATES - - 00-80-68 (hex) YAMATECH SCIENTIFIC LTD. - 008068 (base 16) YAMATECH SCIENTIFIC LTD. - 1255 LAIRD, SUITE 260 - MONTREAL, QUEBEC H3P 2T1 - CANADA - - 00-80-69 (hex) COMPUTONE SYSTEMS - 008069 (base 16) COMPUTONE SYSTEMS - 1100 NORTHMEADOW PARKWAY - SUITE 150 - ROSWELL GA 30076 - UNITED STATES - - 00-80-6A (hex) ERI (EMPAC RESEARCH INC.) - 00806A (base 16) ERI (EMPAC RESEARCH INC.) - 47560 SEABRIDGE DRIVE - FREMONT CA 94538 - UNITED STATES - - 00-80-6B (hex) SCHMID TELECOMMUNICATION - 00806B (base 16) SCHMID TELECOMMUNICATION - BINZSTRASSE 35, - CH-8045 ZURICH - SWITZERLAND - - 00-80-6C (hex) CEGELEC PROJECTS LTD - 00806C (base 16) CEGELEC PROJECTS LTD - DEPT. MDD, - BOUGHTON RD, RUGBY WARKS, CO21 1BU - ENGLAND - UNITED KINGDOM - - 00-80-6D (hex) CENTURY SYSTEMS CORP. - 00806D (base 16) CENTURY SYSTEMS CORP. - 2-8-12 MINAMI-CHO - KOKUBUNJI-SHI, TOKYO - 185 - JAPAN - - 00-80-6E (hex) NIPPON STEEL CORPORATION - 00806E (base 16) NIPPON STEEL CORPORATION - 31-1 SHINKAWA 2-CHOUME - CHUO-KU TOKYO 104 - JAPAN - - 00-80-6F (hex) ONELAN LTD. - 00806F (base 16) ONELAN LTD. - P.O. BOX 107 - HENLEY ON THAMES OXFORDSHIRE RG9 3NOQ - UNITED KINGDOM - UNITED KINGDOM - - 00-80-70 (hex) COMPUTADORAS MICRON - 008070 (base 16) COMPUTADORAS MICRON - GUERRERO 2001 - 19 - IRAPUATO GTO 36660 - MEXICO - - 00-80-71 (hex) SAI TECHNOLOGY - 008071 (base 16) SAI TECHNOLOGY - 4224 CAMPUS POINT COURT - SAN DIEGO CA 92121-1513 - UNITED STATES - - 00-80-72 (hex) MICROPLEX SYSTEMS LTD. - 008072 (base 16) MICROPLEX SYSTEMS LTD. - 301-2071 Kingsway - Port Coquitlam BC BC V3C 6N2 - CANADA - - 00-80-73 (hex) DWB ASSOCIATES - 008073 (base 16) DWB ASSOCIATES - 9360 SW GEMINI DRIVE - BEAVERTON OR 97005-7151 - UNITED STATES - - 00-80-74 (hex) FISHER CONTROLS - 008074 (base 16) FISHER CONTROLS - 1712 CENTRE CREEK DRIVE - AUSTIN TX 78754 - UNITED STATES - - 00-80-75 (hex) PARSYTEC GMBH - 008075 (base 16) PARSYTEC GMBH - JUELICHER STR. 338 - D5100 AACHEN - F.R. - GERMANY - - 00-80-76 (hex) MCNC - 008076 (base 16) MCNC - P.O. BOX 12889 - RTP NC 27709 - UNITED STATES - - 00-80-77 (hex) BROTHER INDUSTRIES, LTD. - 008077 (base 16) BROTHER INDUSTRIES, LTD. - RESEARCH LABORATORY - 9-35 HORITA-DORI, MIZUHO-KU NAGOYA, 467 - JAPAN - - 00-80-78 (hex) PRACTICAL PERIPHERALS, INC. - 008078 (base 16) PRACTICAL PERIPHERALS, INC. - 375 CONEJO RIDGE AVENUE - THOUSAND OAKS CA 91361 - UNITED STATES - - 00-80-79 (hex) MICROBUS DESIGNS LTD. - 008079 (base 16) MICROBUS DESIGNS LTD. - TREADAWAY HILL - LOUDWATER HIGH WYCOMBE BUCKS HP10 9QL - UNITED KINGDOM - UNITED KINGDOM - - 00-80-7A (hex) AITECH SYSTEMS LTD. - 00807A (base 16) AITECH SYSTEMS LTD. - 3080 OLCOTT STREET - SUITE 105A - SANTA CLARA CA 95054 - UNITED STATES - - 00-80-7B (hex) ARTEL COMMUNICATIONS CORP. - 00807B (base 16) ARTEL COMMUNICATIONS CORP. - 22 KANE INDUSTRIAL DRIVE - HUDSON MA 01749 - UNITED STATES - - 00-80-7C (hex) FIBERCOM, INC. - 00807C (base 16) FIBERCOM, INC. - 3353 ORANGE AVENUE NE - ROANOKE VA 24012 - UNITED STATES - - 00-80-7D (hex) EQUINOX SYSTEMS INC. - 00807D (base 16) EQUINOX SYSTEMS INC. - 14260 SW 119TH AVENUE - MIAMI FL 33186 - UNITED STATES - - 00-80-7E (hex) SOUTHERN PACIFIC LTD. - 00807E (base 16) SOUTHERN PACIFIC LTD. - SANWA BLDG., 2-16-20 - MINAMISAIWAI NISHI YOKOHAMA - JAPAN JAPAN 220 - JAPAN - - 00-80-7F (hex) DY-4 INCORPORATED - 00807F (base 16) DY-4 INCORPORATED - 333 PALLADIUM DRIVE, MS 312 - KANATA, ONTARIO, K2V 1A6 - CANADA - - 00-80-80 (hex) DATAMEDIA CORPORATION - 008080 (base 16) DATAMEDIA CORPORATION - 7401 CENTRAL HIGHWAY - PENNSAUKEN NJ 08109 - UNITED STATES - - 00-80-81 (hex) KENDALL SQUARE RESEARCH CORP. - 008081 (base 16) KENDALL SQUARE RESEARCH CORP. - 170 TRACER LANE - WALTHAM MA 02154-1379 - UNITED STATES - - 00-80-82 (hex) PEP MODULAR COMPUTERS GMBH - 008082 (base 16) PEP MODULAR COMPUTERS GMBH - APFELSTRANGER STR. 16 - D - 8950 KAUFBEUREN - WEST - GERMANY - - 00-80-83 (hex) AMDAHL - 008083 (base 16) AMDAHL - 1250 EAST ARQUES AVENUE - M/S 286 P.O. BOX 3470 - SUNNYVALE CA 94088-3470 - UNITED STATES - - 00-80-84 (hex) THE CLOUD INC. - 008084 (base 16) THE CLOUD INC. - CLOUD BLDG. - 71-1, CHEONG-DAM DONG KANG-NAM KU, SEOUL - KOREA - KOREA, REPUBLIC OF - - 00-80-85 (hex) H-THREE SYSTEMS CORPORATION - 008085 (base 16) H-THREE SYSTEMS CORPORATION - 100 PARK DRIVE, SUITE 204 - RESEARCH TRIANGLE PARK - NC 27709 - UNITED STATES - - 00-80-86 (hex) COMPUTER GENERATION INC. - 008086 (base 16) COMPUTER GENERATION INC. - 3855 PRESIDENTIAL PARKWAY - ATLANTA GA 30340 - UNITED STATES - - 00-80-87 (hex) OKI ELECTRIC INDUSTRY CO., LTD - 008087 (base 16) OKI ELECTRIC INDUSTRY CO., LTD - 10-3 SHIBAURA 4-CHOME - MINATO-KU, TOKYO 108 - JAPAN - - 00-80-88 (hex) VICTOR COMPANY OF JAPAN, LTD. - 008088 (base 16) VICTOR COMPANY OF JAPAN, LTD. - 58-7 SHINMEI-CHO, YOKOSUKA - KANAGAWA 239 - JAPAN - - 00-80-89 (hex) TECNETICS (PTY) LTD. - 008089 (base 16) TECNETICS (PTY) LTD. - P.O. BOX/POSBUS 56412 - PINEGOWRIE, 2123 - SOUTH AFRICA - SOUTH AFRICA - - 00-80-8A (hex) SUMMIT MICROSYSTEMS CORP. - 00808A (base 16) SUMMIT MICROSYSTEMS CORP. - 710 LAKEWAY-STE.#150 - SUNNYVALE CA 940867 - UNITED STATES - - 00-80-8B (hex) DACOLL LIMITED - 00808B (base 16) DACOLL LIMITED - DACOLL HOUSE, GARDNERS LANE - BATHGATE WEST LOTHIAN - SCOTLAND EH48 1TP - UNITED KINGDOM - - 00-80-8C (hex) NetScout Systems, Inc. - 00808C (base 16) NetScout Systems, Inc. - 1501 MAIN STREET - SUITE #40 - TEWKSBURY MA 01876 - UNITED STATES - - 00-80-8D (hex) WESTCOAST TECHNOLOGY B.V. - 00808D (base 16) WESTCOAST TECHNOLOGY B.V. - P.O. BOX 3317 - 2601 DH DELFT - NETHERLANDS - - 00-80-8E (hex) RADSTONE TECHNOLOGY - 00808E (base 16) RADSTONE TECHNOLOGY - WATER LANE, TOWCESTER - NORTHANTS NN12 7JN - ENGLAND - UNITED KINGDOM - - 00-80-8F (hex) C. ITOH ELECTRONICS, INC. - 00808F (base 16) C. ITOH ELECTRONICS, INC. - 2505 MCCABE WAY - IRVINE CA 92714 - UNITED STATES - - 00-80-90 (hex) MICROTEK INTERNATIONAL, INC. - 008090 (base 16) MICROTEK INTERNATIONAL, INC. - 3300 NW 211TH TERRACE - HILLSBOR OR 97124-7136 - UNITED STATES - - 00-80-91 (hex) TOKYO ELECTRIC CO.,LTD - 008091 (base 16) TOKYO ELECTRIC CO.,LTD - 10-14 UCHIKANDA - 1-CHOME CHIYODA-KU - TOKYO JAPAN 101 - JAPAN - - 00-80-92 (hex) Silex Technology, Inc. - 008092 (base 16) Silex Technology, Inc. - 2-3-1 Hikaridai, - Seika-cho - Kyoto 619-0237 - JAPAN - - 00-80-93 (hex) XYRON CORPORATION - 008093 (base 16) XYRON CORPORATION - 7864 LILY COURT - CUPERTINO CA 95014 - UNITED STATES - - 00-80-94 (hex) ALFA LAVAL AUTOMATION AB - 008094 (base 16) ALFA LAVAL AUTOMATION AB - ADN - S-205 22 MALMO - SWEDEN - - 00-80-95 (hex) BASIC MERTON HANDELSGES.M.B.H. - 008095 (base 16) BASIC MERTON HANDELSGES.M.B.H. - DURCHLASS-STRASSE 42 - A - 9020 KLAGENFURT - AUSTRIA - - 00-80-96 (hex) HUMAN DESIGNED SYSTEMS, INC. - 008096 (base 16) HUMAN DESIGNED SYSTEMS, INC. - 421 FEHELEY DRIVE - KING OF PRUSSIA PA 19406 - UNITED STATES - - 00-80-97 (hex) CENTRALP AUTOMATISMES - 008097 (base 16) CENTRALP AUTOMATISMES - 21, RUE MARCEL PAGNOL 69694 - VENISSIEUX CEDEX - FRANCE - - 00-80-98 (hex) TDK CORPORATION - 008098 (base 16) TDK CORPORATION - CORP. R&D DEPT. TECH. HDQTERS. - 2-15-7, HIGASHI-OWADA, ICHIKAWA-SHI - CHIBA-KEN 272, - JAPAN - - 00-80-99 (hex) Eaton Industries GmbH - 008099 (base 16) Eaton Industries GmbH - Hein-Moeller - Straße 7-11 - 53115 Bonn - GERMANY - - 00-80-9A (hex) NOVUS NETWORKS LTD - 00809A (base 16) NOVUS NETWORKS LTD - JOHN SCOTT HOUSE - MARKET STREET BRACKNELL, BERKW RG12 1JB - ENGLAND - UNITED KINGDOM - - 00-80-9B (hex) JUSTSYSTEM CORPORATION - 00809B (base 16) JUSTSYSTEM CORPORATION - 3-46 OKINOHAMAHIGASHI - TOKUSIMASHI 770 - JAPAN - - 00-80-9C (hex) LUXCOM, INC. - 00809C (base 16) LUXCOM, INC. - 3249 LAURELVIEW COURT - FREMONT CA 94538 - UNITED STATES - - 00-80-9D (hex) Commscraft Ltd. - 00809D (base 16) Commscraft Ltd. - PO BOX 160 - BENTLEY, W.A. 6102 - AUSTRALIA - - 00-80-9E (hex) DATUS GMBH - 00809E (base 16) DATUS GMBH - INDUSTRIESTR. 2 - D-5102 WURSELEN/AACHEN - WEST - GERMANY - - 00-80-9F (hex) Alcatel-Lucent Enterprise - 00809F (base 16) Alcatel-Lucent Enterprise - 32 avenue Kléber - 92707 COLOMBES CEDEX - FRANCE - - 00-80-A0 (hex) EDISA HEWLETT PACKARD S/A - 0080A0 (base 16) EDISA HEWLETT PACKARD S/A - ALAMEDA RIO NEGRO, - 750-ALPHAVILLE 06454-000 BARUERI SP - BRAZIL - - 00-80-A1 (hex) MICROTEST, INC. - 0080A1 (base 16) MICROTEST, INC. - 4747 N. 22ND STREET - PHOENIX AZ 85016-4708 - UNITED STATES - - 00-80-A2 (hex) CREATIVE ELECTRONIC SYSTEMS - 0080A2 (base 16) CREATIVE ELECTRONIC SYSTEMS - Avenue Eugène-Lance 38bis - CH-1212 Grand-Lancy, Geneva - SWITZERLAND - - 00-80-A3 (hex) Lantronix - 0080A3 (base 16) Lantronix - 15353 Barranca Parkway - Irvine CA 92618 - UNITED STATES - - 00-80-A4 (hex) LIBERTY ELECTRONICS - 0080A4 (base 16) LIBERTY ELECTRONICS - 332 HARBOR WAY - SOUTH SAN FRANCISCO CA 94080 - UNITED STATES - - 00-80-A5 (hex) SPEED INTERNATIONAL - 0080A5 (base 16) SPEED INTERNATIONAL - 1320 ARBOLITA DR. - LA HABRA CA 90631 - UNITED STATES - - 00-80-A6 (hex) REPUBLIC TECHNOLOGY, INC. - 0080A6 (base 16) REPUBLIC TECHNOLOGY, INC. - P.O. BOX 141006 - AUSTIN TX 78714 - UNITED STATES - - 00-80-A7 (hex) Honeywell International Inc - 0080A7 (base 16) Honeywell International Inc - Vancouver Center of Excellence - 500 Brooksbank Avenue - North Vancouver V7J 3S4 - CANADA - - 00-80-A8 (hex) VITACOM CORPORATION - 0080A8 (base 16) VITACOM CORPORATION - 1330 CHARLESTON ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-80-A9 (hex) CLEARPOINT RESEARCH - 0080A9 (base 16) CLEARPOINT RESEARCH - 190 NORTH MAIN STREET - NATICK MA - UNITED STATES - - 00-80-AA (hex) MAXPEED - 0080AA (base 16) MAXPEED - 1120 CHESS DRIVE - FOSTER CITY CA 94404 - UNITED STATES - - 00-80-AB (hex) DUKANE NETWORK INTEGRATION - 0080AB (base 16) DUKANE NETWORK INTEGRATION - 2900 DUKANE DRIVE - ST. CHARLES IL 60174 - UNITED STATES - - 00-80-AC (hex) IMLOGIX, DIVISION OF GENESYS - 0080AC (base 16) IMLOGIX, DIVISION OF GENESYS - 1900 SUMMIT TOWER BLVD.STE#770 - ORLANDO FL 32810 - UNITED STATES - - 00-80-AD (hex) CNET TECHNOLOGY, INC. - 0080AD (base 16) CNET TECHNOLOGY, INC. - 2199 ZANKER ROAD - SAN JOSE CA 95131 - UNITED STATES - - 00-80-AE (hex) HUGHES NETWORK SYSTEMS - 0080AE (base 16) HUGHES NETWORK SYSTEMS - 11717 EXPLORATION LANE - GERMANTOWN MD 20876 - UNITED STATES - - 00-80-AF (hex) ALLUMER CO., LTD. - 0080AF (base 16) ALLUMER CO., LTD. - 2-8-8 CHUO-CHO, MEGURO-KU - TOKYO 152 - JAPAN - - 00-80-B0 (hex) ADVANCED INFORMATION - 0080B0 (base 16) ADVANCED INFORMATION - TECHNOLOGY, INC. - 5F 1-2-6 NIHONBASHI-HONCHO CHUO-KU, TOK - JAPAN - - 00-80-B1 (hex) SOFTCOM A/S - 0080B1 (base 16) SOFTCOM A/S - STUDIESTRAEDE 21 - DK 1455 COPENNHAGEN K. - DENMARK - - 00-80-B2 (hex) NETWORK EQUIPMENT TECHNOLOGIES - 0080B2 (base 16) NETWORK EQUIPMENT TECHNOLOGIES - 6900 PASEO PADRE PARKWAY - FREMONT CA 94555 - UNITED STATES - - 00-80-B3 (hex) AVAL DATA CORPORATION - 0080B3 (base 16) AVAL DATA CORPORATION - MACHIDA ENGINEERING CENTER - 1757-1 KANAI-CHO MACHIDA CITY TOKYO JAPA - JAPAN - - 00-80-B4 (hex) SOPHIA SYSTEMS - 0080B4 (base 16) SOPHIA SYSTEMS - 3337 KIFER ROAD - SANTA CLARA CA 95051 - UNITED STATES - - 00-80-B5 (hex) UNITED NETWORKS INC. - 0080B5 (base 16) UNITED NETWORKS INC. - 2178 PARAGON DRIVE - SAN JOSE CA 95131 - UNITED STATES - - 00-80-B6 (hex) THEMIS COMPUTER - 0080B6 (base 16) THEMIS COMPUTER - 6681 OWENS DRIVE - PLEASONTON CA 94588 - UNITED STATES - - 00-80-B7 (hex) STELLAR COMPUTER - 0080B7 (base 16) STELLAR COMPUTER - 95 WELLS AVENUE - NEWTON MA 02159 - UNITED STATES - - 00-80-B8 (hex) B.U.G. MORISEIKI, INCORPORATED - 0080B8 (base 16) B.U.G. MORISEIKI, INCORPORATED - 1-14 TECHNO-PARK 1-CHOME - SHIMONOPPORO, ATSUBETSU-KU SAPPORO 004, - JAPAN - - 00-80-B9 (hex) ARCHE TECHNOLIGIES INC. - 0080B9 (base 16) ARCHE TECHNOLIGIES INC. - 48502 KATO ROAD - FREMONT CA 94538 - UNITED STATES MINOR OUTLYING ISLAN - - 00-80-BA (hex) SPECIALIX (ASIA) PTE, LTD - 0080BA (base 16) SPECIALIX (ASIA) PTE, LTD - 3 WINTERSELLS ROAD - BYFLEET SURREY KT147LF - UNITED KINGDOM - UNITED KINGDOM - - 00-80-BB (hex) HUGHES LAN SYSTEMS - 0080BB (base 16) HUGHES LAN SYSTEMS - 1225 CHARLESTON ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-80-BC (hex) HITACHI ENGINEERING CO., LTD - 0080BC (base 16) HITACHI ENGINEERING CO., LTD - 4-8-26, OMIKACHO - HITACHI CITY IBARAKI PREFECTURE 319-12 - JAPAN - - 00-80-BD (hex) THE FURUKAWA ELECTRIC CO., LTD - 0080BD (base 16) THE FURUKAWA ELECTRIC CO., LTD - 6-1, MARUNOUCHI 2-CHOME - CHIYODA-KU, TOKYO - 100 - JAPAN - - 00-80-BE (hex) ARIES RESEARCH - 0080BE (base 16) ARIES RESEARCH - 46791 FREMOND BLVD. - FREMONT CA 94538 - UNITED STATES - - 00-80-BF (hex) TAKAOKA ELECTRIC MFG. CO. LTD. - 0080BF (base 16) TAKAOKA ELECTRIC MFG. CO. LTD. - KANDA BRANCH OFFICE TONEN - 2-1-11, SARUGAKU-CHO CHIYODA-KU, TOKYO, - JAPAN - - 00-80-C0 (hex) PENRIL DATACOMM - 0080C0 (base 16) PENRIL DATACOMM - 1300 QUINCE ORCHARD BLVD. - GAITHERSBURG MD 20878 - UNITED STATES - - 00-80-C1 (hex) LANEX CORPORATION - 0080C1 (base 16) LANEX CORPORATION - 10727 TUCKER STREET - BELTSVILLE MD 20705 - UNITED STATES - - 00-80-C2 (hex) IEEE 802.1 COMMITTEE - 0080C2 (base 16) IEEE 802.1 COMMITTEE - 802.1 Chair, c/o IEEE Standards Association - 445 Hoes Lane - Piscataway NJ 08854 - UNITED STATES - - 00-80-C3 (hex) BICC INFORMATION SYSTEMS & SVC - 0080C3 (base 16) BICC INFORMATION SYSTEMS & SVC - 500 CAPABILITY GREEN, LUTON - BEDFORDSHIRE - ENGLAND LU1 3LT - UNITED KINGDOM - - 00-80-C4 (hex) DOCUMENT TECHNOLOGIES, INC. - 0080C4 (base 16) DOCUMENT TECHNOLOGIES, INC. - 1300 CHARLESTON ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-80-C5 (hex) NOVELLCO DE MEXICO - 0080C5 (base 16) NOVELLCO DE MEXICO - CONSTITUYENTES NO. 907 - COL. LOMAS ALTAS - 11950 MEXICO 11950 MEXICO D.F. - MEXICO - - 00-80-C6 (hex) NATIONAL DATACOMM CORPORATION - 0080C6 (base 16) NATIONAL DATACOMM CORPORATION - 2F, 28, INDUSTRY EAST 9TH RD. - SCIENCE PARK, HSIN-CHU - TAIWAN 30077 TAIWAN 30077 R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-80-C7 (hex) XIRCOM - 0080C7 (base 16) XIRCOM - 26025 MUREAU ROAD - CALABASAS CA 91302 - UNITED STATES - - 00-80-C8 (hex) D-LINK SYSTEMS, INC. - 0080C8 (base 16) D-LINK SYSTEMS, INC. - 53 Discover Dr. - Irvine CA 92618 - UNITED STATES - - 00-80-C9 (hex) ALBERTA MICROELECTRONIC CENTRE - 0080C9 (base 16) ALBERTA MICROELECTRONIC CENTRE - 318, 11315 - 87 AVENUE - EDMONTON, AB T6G 2C2 - CANADA - - 00-80-CA (hex) NETCOM RESEARCH INCORPORATED - 0080CA (base 16) NETCOM RESEARCH INCORPORATED - 201 TECHNOLOGY DRIVE - IRVINE CA 92718 - UNITED STATES - - 00-80-CB (hex) FALCO DATA PRODUCTS - 0080CB (base 16) FALCO DATA PRODUCTS - 440 POTRERO AVENUE - SUNNYVALE CA 94086-4196 - UNITED STATES - - 00-80-CC (hex) MICROWAVE BYPASS SYSTEMS - 0080CC (base 16) MICROWAVE BYPASS SYSTEMS - 25 BRAINTREE HILL OFFICE PARK - BRAINTREE MA 02184 - UNITED STATES - - 00-80-CD (hex) MICRONICS COMPUTER, INC. - 0080CD (base 16) MICRONICS COMPUTER, INC. - 45365 NORTHPORT LOOP WEST - FREMONT CA 94538 - UNITED STATES - - 00-80-CE (hex) BROADCAST TELEVISION SYSTEMS - 0080CE (base 16) BROADCAST TELEVISION SYSTEMS - P.O. BOX 30816 - SALT LAKE CITY, UTAH - Utah 84130-0816 - UNITED STATES - - 00-80-CF (hex) EMBEDDED PERFORMANCE INC. - 0080CF (base 16) EMBEDDED PERFORMANCE INC. - 3385 SCOTT BLVD. - SANTA CLARA CA 95054-3115 - UNITED STATES - - 00-80-D0 (hex) COMPUTER PERIPHERALS, INC. - 0080D0 (base 16) COMPUTER PERIPHERALS, INC. - 667 RANCHO CONEJO BLVD. - NEWBURY PARK CA 91320 - UNITED STATES - - 00-80-D1 (hex) KIMTRON CORPORATION - 0080D1 (base 16) KIMTRON CORPORATION - 1709 JUNCTION COURT - BUILDING 380 - SAN JOSE CA 95112 - UNITED STATES - - 00-80-D2 (hex) SHINNIHONDENKO CO., LTD. - 0080D2 (base 16) SHINNIHONDENKO CO., LTD. - 6-8 NISHITENMA 2 CHOME - KITA-KU, OSAKA 530 - JAPAN - - 00-80-D3 (hex) SHIVA CORP. - 0080D3 (base 16) SHIVA CORP. - 205 BURLINGTON ROAD - BEDFORD MA 01730 - UNITED STATES - - 00-80-D4 (hex) CHASE RESEARCH LTD. - 0080D4 (base 16) CHASE RESEARCH LTD. - 7 CHINEHAM BUSINESS PARK - BASINGSTOKE, RG 24 OWD - ENGLAND - UNITED KINGDOM - - 00-80-D5 (hex) CADRE TECHNOLOGIES - 0080D5 (base 16) CADRE TECHNOLOGIES - 19545 NW VON NEUMANN DRIVE - BEAVERTON OR 97006 - UNITED STATES - - 00-80-D6 (hex) NUVOTECH, INC. - 0080D6 (base 16) NUVOTECH, INC. - 2015 BRIDGEWAY, SUITE 204 - SAUSALITO CA 94965 - UNITED STATES - - 00-80-D7 (hex) Fantum Engineering - 0080D7 (base 16) Fantum Engineering - - P.O. Box 1509 - Rockwall TX 75087 - UNITED STATES - - 00-80-D8 (hex) NETWORK PERIPHERALS INC. - 0080D8 (base 16) NETWORK PERIPHERALS INC. - 2890 ZONKER ROAD SUITE 209 - SAN JOSE CA 95134 - UNITED STATES - - 00-80-D9 (hex) EMK Elektronik GmbH & Co. KG - 0080D9 (base 16) EMK Elektronik GmbH & Co. KG - Obere Bergstrasse 28 - 75335 Dobel - GERMANY - - 00-80-DA (hex) Bruel & Kjaer Sound & Vibration Measurement A/S - 0080DA (base 16) Bruel & Kjaer Sound & Vibration Measurement A/S - Skodsborgvej 307 - DK-2850 NAERUM - DENMARK - - 00-80-DB (hex) GRAPHON CORPORATION - 0080DB (base 16) GRAPHON CORPORATION - 1506 DELL AVE - # - CAMPBELL CA 95008-6911 - UNITED STATES - - 00-80-DC (hex) PICKER INTERNATIONAL - 0080DC (base 16) PICKER INTERNATIONAL - 595 MINER ROAD - CLEVELAND OH 44143 - UNITED STATES - - 00-80-DD (hex) GMX INC/GIMIX - 0080DD (base 16) GMX INC/GIMIX - 3223 ARNOLD LANE - NORTHBROOK IL 60062-2406 - UNITED STATES - - 00-80-DE (hex) GIPSI S.A. - 0080DE (base 16) GIPSI S.A. - 2,BD VAUBAN - B.P. 268 - 78053 ST. QUENTIN EN YVELINES CEDEX - FRANCE - - 00-80-DF (hex) ADC CODENOLL TECHNOLOGY CORP. - 0080DF (base 16) ADC CODENOLL TECHNOLOGY CORP. - 200 CORPORATE BLVD. SO. - YONKERS NY 10701 - UNITED STATES - - 00-80-E0 (hex) XTP SYSTEMS, INC. - 0080E0 (base 16) XTP SYSTEMS, INC. - 1900 STATE STREET , STE - SANTA BARBARA CA 93101 - UNITED STATES - - 00-80-E1 (hex) STMICROELECTRONICS - 0080E1 (base 16) STMICROELECTRONICS - 1000 AZTEC WEST - ALMONDSBURY BRISTOL BS32 4SQ - UNITED KINGDOM - - 00-80-E2 (hex) T.D.I. CO., LTD. - 0080E2 (base 16) T.D.I. CO., LTD. - DEVELOPMENT DIV. #3 FUJI BLDG - 1-3-13 ITACHIBORI NISHI-KU OSAKA 550 - JAPAN - - 00-80-E3 (hex) CORAL NETWORK CORPORATION - 0080E3 (base 16) CORAL NETWORK CORPORATION - (NOW BAY NETWORKS) - 4401 GREAT AMERICAN PKWY M/S: SC01-05 - SANTA CLARA CA 95052-8185 - UNITED STATES - - 00-80-E4 (hex) NORTHWEST DIGITAL SYSTEMS, INC - 0080E4 (base 16) NORTHWEST DIGITAL SYSTEMS, INC - P.O. BOX 15288 - SEATTLE WA 98115 - UNITED STATES - - 00-80-E5 (hex) NetApp, Inc - 0080E5 (base 16) NetApp, Inc - 3718 N. Rock Road - Wichita KS 67226-1397 - UNITED STATES - - 00-80-E6 (hex) PEER NETWORKS, INC. - 0080E6 (base 16) PEER NETWORKS, INC. - 3350 SCOTT BLVD. BLDG. 14 - SANTA CLARA CA 95054 - UNITED STATES - - 00-80-E7 (hex) LYNWOOD SCIENTIFIC DEV. LTD. - 0080E7 (base 16) LYNWOOD SCIENTIFIC DEV. LTD. - FARNHAM TRADING ESTATE - FARNHAM, SURREY, GU9 9NN - UNITED KINGDOM - UNITED KINGDOM - - 00-80-E8 (hex) CUMULUS CORPORATIION - 0080E8 (base 16) CUMULUS CORPORATIION - 23500 MERCANTILE ROAD - CLEVELAND OH 44122 - UNITED STATES - - 00-80-E9 (hex) Madge Ltd. - 0080E9 (base 16) Madge Ltd. - Madge House - Priors Way - Maindenhead Berkshire SL6 2HP - UNITED KINGDOM - - 00-80-EA (hex) ADVA Optical Networking Ltd. - 0080EA (base 16) ADVA Optical Networking Ltd. - ADVAntage House - Tribune Way - York YO30 4RY - UNITED KINGDOM - - 00-80-EB (hex) COMPCONTROL B.V. - 0080EB (base 16) COMPCONTROL B.V. - STRATUMSED K31 - 5611 NB EINDHOVEN - THE - NETHERLANDS - - 00-80-EC (hex) SUPERCOMPUTING SOLUTIONS, INC. - 0080EC (base 16) SUPERCOMPUTING SOLUTIONS, INC. - 6175 NANCY RIDGE BLVD. - SAN DIEGO CA 92121 - UNITED STATES - - 00-80-ED (hex) IQ TECHNOLOGIES, INC. - 0080ED (base 16) IQ TECHNOLOGIES, INC. - 11811 NE FIRST STREET - SUITE 201 - BELLEVUE WA 98005 - UNITED STATES - - 00-80-EE (hex) THOMSON CSF - 0080EE (base 16) THOMSON CSF - 51 ESPLANADE DU GENERAL - DE GAULLE 92045 - PARIS LA DEFENSE - CE - FRANCE - - 00-80-EF (hex) RATIONAL - 0080EF (base 16) RATIONAL - 3320 SCOTT BOULEVARD - SANTA CLARA CA 95054 - UNITED STATES - - 00-80-F0 (hex) Panasonic Communications Co., Ltd. - 0080F0 (base 16) Panasonic Communications Co., Ltd. - 4-1-62 Minoshima Hakata Fukuoka - 812-8531 - JAPAN - - 00-80-F1 (hex) OPUS SYSTEMS - 0080F1 (base 16) OPUS SYSTEMS - 3000 CORONADO DRIVE - SANTA CLARA CA 95054 - UNITED STATES - - 00-80-F2 (hex) RAYCOM SYSTEMS INC - 0080F2 (base 16) RAYCOM SYSTEMS INC - 16525 SHERMAN WAY #C-8 - VAN NUYS CA 91406 - UNITED STATES - - 00-80-F3 (hex) SUN ELECTRONICS CORP. - 0080F3 (base 16) SUN ELECTRONICS CORP. - 250 ASAHI KOCHINO-CHO - KONAN-CITY AICHI - 483 - JAPAN - - 00-80-F4 (hex) TELEMECANIQUE ELECTRIQUE - 0080F4 (base 16) TELEMECANIQUE ELECTRIQUE - 33 BIS AVENUE, - DU MARECHAL JOFFRE 92002 NANTERRE CEDEX - FRANCE - - 00-80-F5 (hex) Quantel Ltd - 0080F5 (base 16) Quantel Ltd - Turnpike Road - Newbury Berkshire RG14 2NX - UNITED KINGDOM - - 00-80-F6 (hex) SYNERGY MICROSYSTEMS - 0080F6 (base 16) SYNERGY MICROSYSTEMS - 9605 SCRANTON ROAD-STE #700 - SAN DIEGO CA 92121-1773 - UNITED STATES - - 00-80-F7 (hex) ZENITH ELECTRONICS - 0080F7 (base 16) ZENITH ELECTRONICS - 1000 MILWAUKEE AVENUE - GLENVIEW IL 60025 - UNITED STATES - - 00-80-F8 (hex) MIZAR, INC. - 0080F8 (base 16) MIZAR, INC. - 1419 DUNN DRIVE - CARROLLTON TX 75006 - UNITED STATES - - 00-80-F9 (hex) HEURIKON CORPORATION - 0080F9 (base 16) HEURIKON CORPORATION - 8310 EXCELSIOR DRIVE - MADISON WI 53717 - UNITED STATES - - 00-80-FA (hex) RWT GMBH - 0080FA (base 16) RWT GMBH - TALANGERSTR. 5-7 - D - 8033 KRAILLING - WEST - GERMANY - - 00-80-FB (hex) BVM LIMITED - 0080FB (base 16) BVM LIMITED - HOBB LANE - HEDGE END SOUTHAMPTON - ENGLAND - UNITED KINGDOM - - 00-80-FC (hex) AVATAR CORPORATION - 0080FC (base 16) AVATAR CORPORATION - 65 SOUTH STREET - HOPKINTON MA 01748 - UNITED STATES - - 00-80-FD (hex) EXSCEED CORPRATION - 0080FD (base 16) EXSCEED CORPRATION - 1-15-12, KITAKASE, SAIWAI-KU - KAWASAKI-CITY, 211 KANAGAWA - JAPAN - - 00-80-FE (hex) AZURE TECHNOLOGIES, INC. - 0080FE (base 16) AZURE TECHNOLOGIES, INC. - 63 SOUTH STREET - HOPKINTON MA 01748-2212 - UNITED STATES - - 00-80-FF (hex) SOC. DE TELEINFORMATIQUE RTC - 0080FF (base 16) SOC. DE TELEINFORMATIQUE RTC - P.O. BOX 955 PLACE DU PARC - 300 LEO-PARISTAU SUITE 725 MONTREAL ( - CANADA H2W 2N1 - CANADA - - 00-86-A0 (hex) PRIVATE - 0086A0 (base 16) - - 00-88-65 (hex) Apple - 008865 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-8B-43 (hex) RFTECH - 008B43 (base 16) RFTECH - Cheoin-gu - Jwahang-ri, Wonsam-myeon 339 -17 - Yongin Gyeonggi 449-871 - KOREA, REPUBLIC OF - - 00-8C-10 (hex) Black Box Corp. - 008C10 (base 16) Black Box Corp. - 1000 Park Drive - Lawrence PA 15055 - UNITED STATES - - 00-8C-54 (hex) ADB Broadband Italia - 008C54 (base 16) ADB Broadband Italia - VIALE SARCA 336 - MILANO ITALY 20126 - ITALY - - 00-8C-FA (hex) Inventec Corporation - 008CFA (base 16) Inventec Corporation - No. 255, Jen-Ho Road Sec. 2, 33547, - Tachi Taoyuan 33547 - TAIWAN, PROVINCE OF CHINA - - 00-8D-4E (hex) CJSC NII STT - 008D4E (base 16) CJSC NII STT - N.Leningradskaya str, 10 - Smolensk 214012 - RUSSIAN FEDERATION - - 00-8D-DA (hex) Link One Co., Ltd. - 008DDA (base 16) Link One Co., Ltd. - 601F Chungjuk tower 546-9 - Buchion Gyeonggi-do 420-864 - KOREA, REPUBLIC OF - - 00-8E-F2 (hex) NETGEAR INC., - 008EF2 (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 00-90-00 (hex) DIAMOND MULTIMEDIA - 009000 (base 16) DIAMOND MULTIMEDIA - 312 SE STONEMILL DRIVE - SUITE #150 - VANCOUVER WA 98684 - UNITED STATES - - 00-90-01 (hex) NISHIMU ELECTRONICS INDUSTRIES CO., LTD. - 009001 (base 16) NISHIMU ELECTRONICS INDUSTRIES CO., LTD. - 700 TATENO MITAGAWA-CHO - KANZAKI-GUN SAGA PREF. - JAPAN - - 00-90-02 (hex) ALLGON AB - 009002 (base 16) ALLGON AB - GARDATORGET 1 - 412 50 GOTEBORG - SWEDEN - - 00-90-03 (hex) APLIO - 009003 (base 16) APLIO - 18 Avenue Du 8 Mai 1945 - 95200 SARCELLES - FRANCE - - 00-90-04 (hex) 3COM EUROPE LTD. - 009004 (base 16) 3COM EUROPE LTD. - 3COM CENTRE, BOUNDARY WAY - HEMEL HEMPSTEAD - HERTS. HP2 7YU - UNITED KINGDOM - - 00-90-05 (hex) PROTECH SYSTEMS CO., LTD. - 009005 (base 16) PROTECH SYSTEMS CO., LTD. - 5F, NO. 34, LANE 80, SEC. 3 - NANKANG ROAD - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-90-06 (hex) HAMAMATSU PHOTONICS K.K. - 009006 (base 16) HAMAMATSU PHOTONICS K.K. - 812 JOKO-CHO - HAMAMATSU 431-3196 - JAPAN - - 00-90-07 (hex) DOMEX TECHNOLOGY CORP. - 009007 (base 16) DOMEX TECHNOLOGY CORP. - NO. 2, TECHNOLOGY RD. 1 - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-90-08 (hex) HanA Systems Inc. - 009008 (base 16) HanA Systems Inc. - EAHO B/D 740-1 - YEOK SAM-DONG, KANGNAM-KU - SEOUL - KOREA, REPUBLIC OF - - 00-90-09 (hex) I Controls, Inc. - 009009 (base 16) I Controls, Inc. - 3rd Fl, I'Park 302, 11 Jeongja-Dong, - Bundang-GU - Seongnam Gyeonggi-Do 463-859 - KOREA, REPUBLIC OF - - 00-90-0A (hex) PROTON ELECTRONIC INDUSTRIAL CO., LTD. - 00900A (base 16) PROTON ELECTRONIC INDUSTRIAL CO., LTD. - - 4F, 45, SECTION 1, SAN-MIN RD - Panchiao, Taipei County - TAIWAN, PROVINCE OF CHINA - - 00-90-0B (hex) LANNER ELECTRONICS, INC. - 00900B (base 16) LANNER ELECTRONICS, INC. - 8F-4, NO. 77, SEC. 1 - HSIN TAI WU RD., HSICHIH - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-90-0C (hex) CISCO SYSTEMS, INC. - 00900C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-0D (hex) Overland Storage Inc. - 00900D (base 16) Overland Storage Inc. - 9112 Spectrum Center Blvd - SAN DIEGO CA 92123 - UNITED STATES - - 00-90-0E (hex) HANDLINK TECHNOLOGIES, INC. - 00900E (base 16) HANDLINK TECHNOLOGIES, INC. - 5F, 24-2, Industry E. Road IV, - Science-Based Industrial Park, - Hsinchu 30077 - TAIWAN, PROVINCE OF CHINA - - 00-90-0F (hex) KAWASAKI HEAVY INDUSTRIES, LTD - 00900F (base 16) KAWASAKI HEAVY INDUSTRIES, LTD - ELEC. & CONTROL TECH CENTER - 1-1 KAWASAKI-CHO AKASHI 673-8666 - JAPAN - - 00-90-10 (hex) SIMULATION LABORATORIES, INC. - 009010 (base 16) SIMULATION LABORATORIES, INC. - 10078 TYLER PLACE #A - IJAMSVILLE MD 21754 - UNITED STATES - - 00-90-11 (hex) WAVTrace, Inc. - 009011 (base 16) WAVTrace, Inc. - 1555 132ND AVE. NE - BELLEVUE WA 98005 - UNITED STATES - - 00-90-12 (hex) GLOBESPAN SEMICONDUCTOR, INC. - 009012 (base 16) GLOBESPAN SEMICONDUCTOR, INC. - 100 SCHULZ DRIVE - RED BANK NJ 07701 - UNITED STATES - - 00-90-13 (hex) SAMSAN CORP. - 009013 (base 16) SAMSAN CORP. - ELECTRONICS & COMM DIVISION - SAMSAN BLDG., 506-7, AMSA-DONG - Kangdong-Gu Seoul 134-050 - KOREA, REPUBLIC OF - - 00-90-14 (hex) ROTORK INSTRUMENTS, LTD. - 009014 (base 16) ROTORK INSTRUMENTS, LTD. - CHAUL END LANE - LUTON BEDFORDSHIRE - LU4 8EZ England - UNITED KINGDOM - - 00-90-15 (hex) CENTIGRAM COMMUNICATIONS CORP. - 009015 (base 16) CENTIGRAM COMMUNICATIONS CORP. - 91 EAST TASMAN DRIVE - SAN JOSE CA 95134 - UNITED STATES - - 00-90-16 (hex) ZAC - 009016 (base 16) ZAC - Stüvestraße 9 - D-31141 Hildesheim - GERMANY - - 00-90-17 (hex) Zypcom, Inc - 009017 (base 16) Zypcom, Inc - 28400 Kohoutek Way - Suite 170 - Union City CA 94587-1212 - UNITED STATES - - 00-90-18 (hex) ITO ELECTRIC INDUSTRY CO, LTD. - 009018 (base 16) ITO ELECTRIC INDUSTRY CO, LTD. - 4-26-12 MEIEKI NAKAMURA-KU - NAGOYA-CITY AICHI 450-0002 - JAPAN - - 00-90-19 (hex) HERMES ELECTRONICS CO., LTD. - 009019 (base 16) HERMES ELECTRONICS CO., LTD. - 3-2-12 YUSHIMA, BUNKYO-KU - TOKYO, 113-0034 - JAPAN - - 00-90-1A (hex) UNISPHERE SOLUTIONS - 00901A (base 16) UNISPHERE SOLUTIONS - 5 CARLISLE ROAD - WESTFORD MA 01886 - UNITED STATES - - 00-90-1B (hex) DIGITAL CONTROLS - 00901B (base 16) DIGITAL CONTROLS - 305 PIONEER BLVD. - SPRINGBORO OH 45066-1100 - UNITED STATES - - 00-90-1C (hex) mps Software Gmbh - 00901C (base 16) mps Software Gmbh - LUDWIGSTR 36 - 85551 KIRCHHEIM - GERMANY - - 00-90-1D (hex) PEC (NZ) LTD. - 00901D (base 16) PEC (NZ) LTD. - 2 STATION ROAD - P.O. BOX 308 - MARTON - NEW ZEALAND - - 00-90-1E (hex) Selesta Ingegneria S.p.A. - 00901E (base 16) Selesta Ingegneria S.p.A. - via di Francia, 28 - Genova 16149 - ITALY - - 00-90-1F (hex) ADTEC PRODUCTIONS, INC. - 00901F (base 16) ADTEC PRODUCTIONS, INC. - 408 RUSSELL STREET - NASHVILLE TN 37206 - UNITED STATES - - 00-90-20 (hex) PHILIPS ANALYTICAL X-RAY B.V. - 009020 (base 16) PHILIPS ANALYTICAL X-RAY B.V. - LELYWEG 1 - 7602 EA ALMELO - NETHERLANDS - - 00-90-21 (hex) CISCO SYSTEMS, INC. - 009021 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-22 (hex) IVEX - 009022 (base 16) IVEX - 4295 INTERNATIONAL BLVD. - SUITE - NORCROSS GA 30093 - UNITED STATES - - 00-90-23 (hex) ZILOG INC. - 009023 (base 16) ZILOG INC. - 910 East Hamilton Ave. - Campbell CA 95008 - UNITED STATES - - 00-90-24 (hex) PIPELINKS, INC. - 009024 (base 16) PIPELINKS, INC. - 2710 WALSH AVE., STE #300 - SANTA CLARA CA 95051 - UNITED STATES - - 00-90-25 (hex) BAE Systems Australia (Electronic Systems) Pty Ltd - 009025 (base 16) BAE Systems Australia (Electronic Systems) Pty Ltd - 2 Second Ave - Mawson Lakes South Australia 5095 - AUSTRALIA - - 00-90-26 (hex) ADVANCED SWITCHING COMMUNICATIONS, INC. - 009026 (base 16) ADVANCED SWITCHING COMMUNICATIONS, INC. - 8330 BOONE BOULEVARD--5TH FL. - VIENNA VA 22182 - UNITED STATES - - 00-90-27 (hex) INTEL CORPORATION - 009027 (base 16) INTEL CORPORATION - HF1-06 - 5200 N.E. ELAM YOUNG PARKWAY - HILLSBORO OR 97124 - UNITED STATES - - 00-90-28 (hex) NIPPON SIGNAL CO., LTD. - 009028 (base 16) NIPPON SIGNAL CO., LTD. - 11 HIRAIDE-KOGIO-DANCHI - UISUNOMIYA TOCHIGI 321-8651 - JAPAN - - 00-90-29 (hex) CRYPTO AG - 009029 (base 16) CRYPTO AG - P.O. BOX - CH-6301 Zug - SWITZERLAND - - 00-90-2A (hex) COMMUNICATION DEVICES, INC. - 00902A (base 16) COMMUNICATION DEVICES, INC. - 85 Fulton Street - Boonton NJ 07005-1912 - UNITED STATES - - 00-90-2B (hex) CISCO SYSTEMS, INC. - 00902B (base 16) CISCO SYSTEMS, INC. - SJA-2 - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-2C (hex) DATA & CONTROL EQUIPMENT LTD. - 00902C (base 16) DATA & CONTROL EQUIPMENT LTD. - COUNTY FARM, WENDOVER RD. - STOKE MANDEVILLE - BUCKS. HP22 STA - UNITED KINGDOM - - 00-90-2D (hex) DATA ELECTRONICS (AUST.) PTY, LTD. - 00902D (base 16) DATA ELECTRONICS (AUST.) PTY, LTD. - 7 SEISMIC COURT - ROWVILLE - VICTORIA 3178 - AUSTRALIA - - 00-90-2E (hex) NAMCO LIMITED - 00902E (base 16) NAMCO LIMITED - 1-1-32 SHIN-URASHIMA-CHO - KANAGAWA-KU, YOKOHAMA - KANAGAWA 221-0031 - JAPAN - - 00-90-2F (hex) NETCORE SYSTEMS, INC. - 00902F (base 16) NETCORE SYSTEMS, INC. - 187 BALLARDVALE STREET - WILMINGTON MA 01887 - UNITED STATES - - 00-90-30 (hex) HONEYWELL-DATING - 009030 (base 16) HONEYWELL-DATING - VIA TINTORETTO, 15 - 21012 CASSANO MAGNAGO (VA) - ITALY - - 00-90-31 (hex) MYSTICOM, LTD. - 009031 (base 16) MYSTICOM, LTD. - P.O. 8364 - NATANIA 42504 - ISRAEL - - 00-90-32 (hex) PELCOMBE GROUP LTD. - 009032 (base 16) PELCOMBE GROUP LTD. - MAIN ROAD - DOVERCOURT, HARWICH - ESSEX C012 4LP - UNITED KINGDOM - - 00-90-33 (hex) INNOVAPHONE AG - 009033 (base 16) INNOVAPHONE AG - Boeblinger Str. 76 - SINDELFINGEN D71065 - GERMANY - - 00-90-34 (hex) IMAGIC, INC. - 009034 (base 16) IMAGIC, INC. - 235 West Road #7 - Portsmouth NH 03801 - UNITED STATES - - 00-90-35 (hex) ALPHA TELECOM, INC. - 009035 (base 16) ALPHA TELECOM, INC. - 2F, NO.2, LI HSIN ROAD - SCIENCE-BASED INDUSTRIAL PARK - HSIN-CHU - TAIWAN, PROVINCE OF CHINA - - 00-90-36 (hex) ens, inc. - 009036 (base 16) ens, inc. - P.O. BOX 19207 - RALEIGH NC 27619 - UNITED STATES - - 00-90-37 (hex) ACUCOMM, INC. - 009037 (base 16) ACUCOMM, INC. - 4633 OLD IRONSIDES - STE #310 - SANTA CLARA CA 95054 - UNITED STATES - - 00-90-38 (hex) FOUNTAIN TECHNOLOGIES, INC. - 009038 (base 16) FOUNTAIN TECHNOLOGIES, INC. - 50 RANDOLPH ROAD - SOMERSET NJ 08873 - UNITED STATES - - 00-90-39 (hex) SHASTA NETWORKS - 009039 (base 16) SHASTA NETWORKS - 249 HUMBOLDT COURT - SUNNYVALE CA 94089-1300 - UNITED STATES - - 00-90-3A (hex) NIHON MEDIA TOOL INC. - 00903A (base 16) NIHON MEDIA TOOL INC. - 1875 OYAMA-CHO - YOKKAICHI-CITY - MIE 512-1102 - JAPAN - - 00-90-3B (hex) TriEMS Research Lab, Inc. - 00903B (base 16) TriEMS Research Lab, Inc. - 1275 N. TUSTIN AVENUE - ANAHEIM CA 92807 - UNITED STATES - - 00-90-3C (hex) ATLANTIC NETWORK SYSTEMS - 00903C (base 16) ATLANTIC NETWORK SYSTEMS - IMMEUBLE "Kennedy" - ZITER AVENUE JF KENNEDY - 33700 MERIGNAC - FRANCE - - 00-90-3D (hex) BIOPAC SYSTEMS, INC. - 00903D (base 16) BIOPAC SYSTEMS, INC. - 42 AERO CAMINO - SANTA BARBARA CA 93117 - UNITED STATES - - 00-90-3E (hex) N.V. PHILIPS INDUSTRIAL ACTIVITIES - 00903E (base 16) N.V. PHILIPS INDUSTRIAL ACTIVITIES - - INTERLEUVENLAAN 74-76 - B-3001 LEUVEN - BELGIUM - - 00-90-3F (hex) AZTEC RADIOMEDIA - 00903F (base 16) AZTEC RADIOMEDIA - 31, RUE DU CHEMINDEFER - 67200 STRASBOURG - FRANCE - - 00-90-40 (hex) Siemens Network Convergence LLC - 009040 (base 16) Siemens Network Convergence LLC - Ten Technology Park Drive - Westford MA 01886-3146 - UNITED STATES - - 00-90-41 (hex) APPLIED DIGITAL ACCESS - 009041 (base 16) APPLIED DIGITAL ACCESS - 9855 SCRANTON ROAD - SAN DIEGO CA 92121 - UNITED STATES - - 00-90-42 (hex) ECCS, Inc. - 009042 (base 16) ECCS, Inc. - ONE SHEILA DRIVE - TINTON FALLS NJ 07724 - UNITED STATES - - 00-90-43 (hex) Tattile SRL - 009043 (base 16) Tattile SRL - 1-13-10 SHIROGANE CHUO-KU - FUKUOKA-CITY - JAPAN - - 00-90-44 (hex) ASSURED DIGITAL, INC. - 009044 (base 16) ASSURED DIGITAL, INC. - 9-11 GOLDSMITH ST. - LITTLETON MA 01460 - UNITED STATES - - 00-90-45 (hex) Marconi Communications - 009045 (base 16) Marconi Communications - 1000 Fore Drive - Warrendale PA 15086-7502 - UNITED STATES - - 00-90-46 (hex) DEXDYNE, LTD. - 009046 (base 16) DEXDYNE, LTD. - 15 MARKET PL. - CIRENCESTER - GLOCESTERSHIRE GL7 2PB - UNITED KINGDOM - - 00-90-47 (hex) GIGA FAST E. LTD. - 009047 (base 16) GIGA FAST E. LTD. - 14F, NO.112, SEC. 1 - HSIN-TAI WU RD. - Hsi-Chih Taipei Hsien - TAIWAN, PROVINCE OF CHINA - - 00-90-48 (hex) ZEAL CORPORATION - 009048 (base 16) ZEAL CORPORATION - 301, HIRAIKE - NAGAKUTE-CHO, AICHI-PREF. 480-1155 - JAPAN - - 00-90-49 (hex) ENTRIDIA CORPORATION - 009049 (base 16) ENTRIDIA CORPORATION - 101 PARK CENTER PLAZA - SUITE #500 - SAN JOSE CA 95113-2218 - UNITED STATES - - 00-90-4A (hex) CONCUR SYSTEM TECHNOLOGIES - 00904A (base 16) CONCUR SYSTEM TECHNOLOGIES - 2525 WALLINGWOOD DR.-STE. #804 - AUSTIN TX 78746 - UNITED STATES - - 00-90-4B (hex) GemTek Technology Co., Ltd. - 00904B (base 16) GemTek Technology Co., Ltd. - No. 1 Jen Ai Road, - Hsinchu Industrial Park, - Hukou, Hsinchu, Taiwan 30352 - TAIWAN, PROVINCE OF CHINA - - 00-90-4C (hex) EPIGRAM, INC. - 00904C (base 16) EPIGRAM, INC. - 870 WEST MAUDE AVE. - SUNNYVALE CA 94086 - UNITED STATES - - 00-90-4D (hex) SPEC S.A. - 00904D (base 16) SPEC S.A. - CASP 172 3-B - 08013 BARCELONA - SPAIN - - 00-90-4E (hex) DELEM BV - 00904E (base 16) DELEM BV - LUCHTHAVEN WEG 42 - 5657 EB EINDHOVEN - NETHERLANDS - - 00-90-4F (hex) ABB POWER T&D COMPANY, INC. - 00904F (base 16) ABB POWER T&D COMPANY, INC. - 7036 SNOWDRIFT ROAD - ALLENTOWN PA 18106 - UNITED STATES - - 00-90-50 (hex) TELESTE OY - 009050 (base 16) TELESTE OY - SEPONKATU 1 - LITTOINEN FIN-20660 - FINLAND - - 00-90-51 (hex) ULTIMATE TECHNOLOGY CORP. - 009051 (base 16) ULTIMATE TECHNOLOGY CORP. - 100 RAWSON ROAD - VICTOR NY 14564 - UNITED STATES - - 00-90-52 (hex) SELCOM ELETTRONICA S.R.L. - 009052 (base 16) SELCOM ELETTRONICA S.R.L. - VIA GRANDI, 5 - 40013 CASTELMAGGIORE BO - ITALY - - 00-90-53 (hex) DAEWOO ELECTRONICS CO., LTD. - 009053 (base 16) DAEWOO ELECTRONICS CO., LTD. - DIT RESEARCH CENTER - DAEWOO CENTER 541 NAMDAEMUNNO 5-GA - CHUNG-GU SEOUL 100-714 - KOREA, REPUBLIC OF - - 00-90-54 (hex) INNOVATIVE SEMICONDUCTORS, INC - 009054 (base 16) INNOVATIVE SEMICONDUCTORS, INC - 2570 W. EL CAMINO REAL - SUITE #205 - MOUNTAIN VIEW CA 94040 - UNITED STATES - - 00-90-55 (hex) PARKER HANNIFIN CORPORATION COMPUMOTOR DIVISION - 009055 (base 16) PARKER HANNIFIN CORPORATION COMPUMOTOR DIVISION - 5500 BUSINESS PARK DRIVE - ROHNERT PARK CA 94928 - UNITED STATES - - 00-90-56 (hex) TELESTREAM, INC. - 009056 (base 16) TELESTREAM, INC. - 848 GOLD FLAT RD., SUITE 1 - NEVADA CITY CA 95959 - UNITED STATES - - 00-90-57 (hex) AANetcom, Inc. - 009057 (base 16) AANetcom, Inc. - 4949 LIBERTY LANE - STE. #200 - ALLENTOWN PA 18106-9015 - UNITED STATES - - 00-90-58 (hex) Ultra Electronics Ltd., Command and Control Systems - 009058 (base 16) Ultra Electronics Ltd., Command and Control Systems - KNAVES BEECH BUSINESS CENTRE - LOUDWATER, HIGH WYCOMBE - BUCKINGHAMSHIRE HP10 9UT England - UNITED KINGDOM - - 00-90-59 (hex) TELECOM DEVICE K.K. - 009059 (base 16) TELECOM DEVICE K.K. - SANMIYANAGA BLDG. 3F, 1-5-12 - MOTOAKASAKA, MINATO-KU - TOKYO 107 - JAPAN - - 00-90-5A (hex) DEARBORN GROUP, INC. - 00905A (base 16) DEARBORN GROUP, INC. - 33604 West 8 Mile Rd - Farmington Hills MI 48335 - UNITED STATES - - 00-90-5B (hex) RAYMOND AND LAE ENGINEERING - 00905B (base 16) RAYMOND AND LAE ENGINEERING - 208 COMMERCE DR., UNIT #3C - FORT COLLINS CO 80524 - UNITED STATES - - 00-90-5C (hex) EDMI - 00905C (base 16) EDMI - 626 OLD GYMPIE ROAD - NARANGBA QLD 4504 - AUSTRALIA - - 00-90-5D (hex) NETCOM SICHERHEITSTECHNIK GmbH - 00905D (base 16) NETCOM SICHERHEITSTECHNIK GmbH - BOPPSTRASSE 38 - 55118 MAINZ - GERMANY - - 00-90-5E (hex) RAULAND-BORG CORPORATION - 00905E (base 16) RAULAND-BORG CORPORATION - 3450 W. OAKTON ST. - SKOKIE IL 60076 - UNITED STATES - - 00-90-5F (hex) CISCO SYSTEMS, INC. - 00905F (base 16) CISCO SYSTEMS, INC. - SJA-2 - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-60 (hex) SYSTEM CREATE CORP. - 009060 (base 16) SYSTEM CREATE CORP. - 3-13-6 YOSHIKAWA BLD. - KImshi SUMIDA-KU - TOKYO - JAPAN - - 00-90-61 (hex) PACIFIC RESEARCH & ENGINEERING CORPORATION - 009061 (base 16) PACIFIC RESEARCH & ENGINEERING CORPORATION - 2070 LAS PALMAS DRIVE - CARLSBAD CA 92009 - UNITED STATES - - 00-90-62 (hex) ICP VORTEX COMPUTERSYSTEME GmbH - 009062 (base 16) ICP VORTEX COMPUTERSYSTEME GmbH - FALTERSTRASSE 51-53 - D 74223 FLEIN - GERMANY - - 00-90-63 (hex) COHERENT COMMUNICATIONS SYSTEMS CORPORATION - 009063 (base 16) COHERENT COMMUNICATIONS SYSTEMS CORPORATION - 45085 UNIVERSITY DRIVE - ASHBURN VA 20147 - UNITED STATES - - 00-90-64 (hex) Thomson Inc. - 009064 (base 16) Thomson Inc. - 101 West 103rd Street - Indianapolis IN 46290-1102 - UNITED STATES - - 00-90-65 (hex) FINISAR CORPORATION - 009065 (base 16) FINISAR CORPORATION - 1389 Moffett Park Dr - Sunnyvale CA 94089 - UNITED STATES - - 00-90-66 (hex) Troika Networks, Inc. - 009066 (base 16) Troika Networks, Inc. - 2829 Townsgate Road, - Suite 200 - Westlake Village CA 91361 - UNITED STATES - - 00-90-67 (hex) WalkAbout Computers, Inc. - 009067 (base 16) WalkAbout Computers, Inc. - 2655 N. OCEAN DRIVE--STE. #510 - SINGER ISLAND FL 33404 - UNITED STATES - - 00-90-68 (hex) DVT CORP. - 009068 (base 16) DVT CORP. - 1670 OAKBROOK DR. - STE. #330 - NORCROSS GA 30093 - UNITED STATES - - 00-90-69 (hex) JUNIPER NETWORKS, INC. - 009069 (base 16) JUNIPER NETWORKS, INC. - 1194 N. Mathilda Avenue - Sunnyvale CA 94089-1206 - UNITED STATES - - 00-90-6A (hex) TURNSTONE SYSTEMS, INC. - 00906A (base 16) TURNSTONE SYSTEMS, INC. - 274 Ferguson Drive - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-90-6B (hex) APPLIED RESOURCES, INC. - 00906B (base 16) APPLIED RESOURCES, INC. - 9821 WIDMER ROAD - LENEXA KS 66215-1239 - UNITED STATES - - 00-90-6C (hex) Sartorius Hamburg GmbH - 00906C (base 16) Sartorius Hamburg GmbH - Meiendorferstraße 205 - Hamburg D-22145 - GERMANY - - 00-90-6D (hex) CISCO SYSTEMS, INC. - 00906D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-6E (hex) PRAXON, INC. - 00906E (base 16) PRAXON, INC. - 1700 DELL AVENUE - CAMPBELL CA 95008 - UNITED STATES - - 00-90-6F (hex) CISCO SYSTEMS, INC. - 00906F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-70 (hex) NEO NETWORKS, INC. - 009070 (base 16) NEO NETWORKS, INC. - 10300 BREN ROAD EAST - MINNETONKA MN 55343 - UNITED STATES - - 00-90-71 (hex) Applied Innovation Inc. - 009071 (base 16) Applied Innovation Inc. - 5800 Innovation Drive - Dublin OH 43016-3271 - UNITED STATES - - 00-90-72 (hex) SIMRAD AS - 009072 (base 16) SIMRAD AS - P.O. BOX 111 - 3191 HORTEN - NORWAY - - 00-90-73 (hex) GAIO TECHNOLOGY - 009073 (base 16) GAIO TECHNOLOGY - OAK-YOKOHAMA BLDG. - 2-15-10 KITA-SAIWAI, - NISHI-KU YOKOHAMA-CITY Kanagawa - JAPAN - - 00-90-74 (hex) ARGON NETWORKS, INC. - 009074 (base 16) ARGON NETWORKS, INC. - 25 PORTER ROAD - LITTLETON MA 01460 - UNITED STATES - - 00-90-75 (hex) NEC DO BRASIL S.A. - 009075 (base 16) NEC DO BRASIL S.A. - RODOVIA PRESIDENTE DUTRA, KM 218 - CUMBICA-GUARULHOS - São Paulo-SP CEP - 07210-902 - BRAZIL - - 00-90-76 (hex) FMT AIRCRAFT GATE SUPPORT SYSTEMS AB - 009076 (base 16) FMT AIRCRAFT GATE SUPPORT SYSTEMS AB - - DALASLINGAN 8 - SE-231 32 TRELLEBORG - SWEDEN - - 00-90-77 (hex) ADVANCED FIBRE COMMUNICATIONS - 009077 (base 16) ADVANCED FIBRE COMMUNICATIONS - PO BOX #751239 - 1 WILLOWBROOK CT - PETALUMA CA 94975 - UNITED STATES - - 00-90-78 (hex) MER TELEMANAGEMENT SOLUTIONS, LTD. - 009078 (base 16) MER TELEMANAGEMENT SOLUTIONS, LTD. - 5 HATSOREF STR. - IND. AREA - HOLON - ISRAEL - - 00-90-79 (hex) ClearOne, Inc. - 009079 (base 16) ClearOne, Inc. - 299 WASHINGTON STREET - WOBURN MA 01801 - UNITED STATES - - 00-90-7A (hex) Spectralink, Inc - 00907A (base 16) Spectralink, Inc - 2560 55th Street - BOULDER CO 80301 - UNITED STATES - - 00-90-7B (hex) E-TECH, INC. - 00907B (base 16) E-TECH, INC. - 30, R&D ROAD 2 - SCIENCE PARK - HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-90-7C (hex) DIGITALCAST, INC. - 00907C (base 16) DIGITALCAST, INC. - 503, ILKWANG BLDG., 1656-2 - SEOCHO-DONG - SEOCHO-KU SEOUL - KOREA, REPUBLIC OF - - 00-90-7D (hex) Lake Communications - 00907D (base 16) Lake Communications - Beech House, Greenhills Road - Dublin 24 - IRELAND - - 00-90-7E (hex) VETRONIX CORP. - 00907E (base 16) VETRONIX CORP. - 2030 ALAMEDE PADRE SERRA - SANTA BARBARA CA 93103 - UNITED STATES - - 00-90-7F (hex) WatchGuard Technologies, Inc. - 00907F (base 16) WatchGuard Technologies, Inc. - 505 Fifth Ave South - Suite 500 - Seattle WA 98104 - UNITED STATES - - 00-90-80 (hex) NOT LIMITED, INC. - 009080 (base 16) NOT LIMITED, INC. - 500 ALLERTON STREET, STE #102 - REDWOOD CITY CA 94063 - UNITED STATES - - 00-90-81 (hex) ALOHA NETWORKS, INC. - 009081 (base 16) ALOHA NETWORKS, INC. - 1001A O'REILLY AVENUE - P.O. BOX 29472 - SAN FRANCISCO CA 94129-0472 - UNITED STATES - - 00-90-82 (hex) FORCE INSTITUTE - 009082 (base 16) FORCE INSTITUTE - PARK ALLE 345 - DK-2605 BROENDBY - DENMARK - - 00-90-83 (hex) TURBO COMMUNICATION, INC. - 009083 (base 16) TURBO COMMUNICATION, INC. - 4F-2, NO. 171, SUNG-TEH ROAD - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-90-84 (hex) ATECH SYSTEM - 009084 (base 16) ATECH SYSTEM - 4F DAEBOONG BLDG. 1451-78 - SEOCHO-DONG SEOCHO-KU - SEOUL 137-070 - KOREA, REPUBLIC OF - - 00-90-85 (hex) GOLDEN ENTERPRISES, INC. - 009085 (base 16) GOLDEN ENTERPRISES, INC. - 4450 WEST EAU GALLIE BLVD. - 250 PERIMETER CENTER - MELBOURNE FL 32934 - UNITED STATES - - 00-90-86 (hex) CISCO SYSTEMS, INC. - 009086 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-87 (hex) ITIS - 009087 (base 16) ITIS - CENTRE ESPACE PERFORMANCE - ALPHASIS-BATIMENT C1 - 35769 SAINT-GREGOIRE CEDEX - FRANCE - - 00-90-88 (hex) BAXALL SECURITY LTD. - 009088 (base 16) BAXALL SECURITY LTD. - UNIT 1 CASTLEHILL - HORSEFIELD WAY, BREDBURY PARK IND. Estat - STOCKPORT Great Britain SK6 2SV - UNITED KINGDOM - - 00-90-89 (hex) SOFTCOM MICROSYSTEMS, INC. - 009089 (base 16) SOFTCOM MICROSYSTEMS, INC. - 47509 SEABRIDGE DRIVE - FREMONT CA 94538 - UNITED STATES - - 00-90-8A (hex) BAYLY COMMUNICATIONS, INC. - 00908A (base 16) BAYLY COMMUNICATIONS, INC. - 105 GREEN COURT - AJAX Ontario L1S 6W9 - CANADA - - 00-90-8B (hex) Tattile SRL - 00908B (base 16) Tattile SRL - 2600 Fernbrook Lane - Suite 130 - Plymouth MN 55447 - UNITED STATES - - 00-90-8C (hex) ETREND ELECTRONICS, INC. - 00908C (base 16) ETREND ELECTRONICS, INC. - 2F, 22 INDUSTRY E. 9TH ROAD - HSINCHU SCIENCE PARK - TAIWAN, PROVINCE OF CHINA - - 00-90-8D (hex) VICKERS ELECTRONICS SYSTEMS - 00908D (base 16) VICKERS ELECTRONICS SYSTEMS - 1151 W. MASON-MORROW RD. - LEBANON OH 45036 - UNITED STATES - - 00-90-8E (hex) Nortel Networks Broadband Access - 00908E (base 16) Nortel Networks Broadband Access - 39660 Eureka Drive - Newark CA 94560 - UNITED STATES - - 00-90-8F (hex) AUDIO CODES LTD. - 00908F (base 16) AUDIO CODES LTD. - 3A NETANYAHU STREET - OR YEHUDA 60256 - ISRAEL - - 00-90-90 (hex) I-BUS - 009090 (base 16) I-BUS - 9174 SKY PARK COURT - SAN DIEGO CA 92123 - UNITED STATES - - 00-90-91 (hex) DigitalScape, Inc. - 009091 (base 16) DigitalScape, Inc. - 6 MORGAN - STE.#100 - IRVINE CA 92618 - UNITED STATES - - 00-90-92 (hex) CISCO SYSTEMS, INC. - 009092 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-93 (hex) NANAO CORPORATION - 009093 (base 16) NANAO CORPORATION - 153 SHIMOKASHIWANO, MATTO - ISHIKAWA 924-8566 - JAPAN - - 00-90-94 (hex) OSPREY TECHNOLOGIES, INC. - 009094 (base 16) OSPREY TECHNOLOGIES, INC. - 600 AIRPORT BLVD. - STE. #900 - MORRISVILLE NC 27560 - UNITED STATES - - 00-90-95 (hex) UNIVERSAL AVIONICS - 009095 (base 16) UNIVERSAL AVIONICS - 11351 WILLOWS ROAD NE - REDMOND WA 98052-2552 - UNITED STATES - - 00-90-96 (hex) ASKEY COMPUTER CORP. - 009096 (base 16) ASKEY COMPUTER CORP. - 2F, NO. 2, LANE 497 - CHUNG-CHENG RD., HSIN-TIEN - TAIPEI 23136 - TAIWAN, PROVINCE OF CHINA - - 00-90-97 (hex) Sycamore Networks - 009097 (base 16) Sycamore Networks - 220 Mill Rd - Chelmsford MA 01824 - UNITED STATES - - 00-90-98 (hex) SBC DESIGNS, INC. - 009098 (base 16) SBC DESIGNS, INC. - 3077-H LEEMAN FERRY ROAD - HUNTSVILLE AL 35801 - UNITED STATES - - 00-90-99 (hex) ALLIED TELESIS, K.K. - 009099 (base 16) ALLIED TELESIS, K.K. - NO. 2 TOC BUILDING, 7-21-11Nishi-Gotand - Shinagawa-Ku Tokyo 141 - JAPAN - - 00-90-9A (hex) ONE WORLD SYSTEMS, INC. - 00909A (base 16) ONE WORLD SYSTEMS, INC. - 1144 EAST ARQUES AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-90-9B (hex) MARKEM-IMAJE - 00909B (base 16) MARKEM-IMAJE - Frihamnen 16A - Gothenburg 417 55 - SWEDEN - - 00-90-9C (hex) ARRIS Group, Inc. - 00909C (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-90-9D (hex) NovaTech Process Solutions, LLC - 00909D (base 16) NovaTech Process Solutions, LLC - 11500 Cronridge Drive - Suite 110 - Owings Mills MD 21117 - UNITED STATES - - 00-90-9E (hex) Critical IO, LLC - 00909E (base 16) Critical IO, LLC - 485 E. 17th Street - Suite 2010 - Costa Mesa CA 92627 - UNITED STATES - - 00-90-9F (hex) DIGI-DATA CORPORATION - 00909F (base 16) DIGI-DATA CORPORATION - 7165 Columbia Gateway Drive - Columbia MD 21045 - UNITED STATES - - 00-90-A0 (hex) 8X8 INC. - 0090A0 (base 16) 8X8 INC. - 2445 MISSION COLLEGE BLVD. - SANTA CLARA CA 95054 - UNITED STATES - - 00-90-A1 (hex) Flying Pig Systems/High End Systems Inc. - 0090A1 (base 16) Flying Pig Systems/High End Systems Inc. - 2105 Gracy Farms Lane - Austin TX 78758 - UNITED STATES - - 00-90-A2 (hex) CYBERTAN TECHNOLOGY, INC. - 0090A2 (base 16) CYBERTAN TECHNOLOGY, INC. - 99, Park Avenue III - Science-Based Industrial Park - Hsinchu - TAIWAN, PROVINCE OF CHINA - - 00-90-A3 (hex) Corecess Inc. - 0090A3 (base 16) Corecess Inc. - 135-726, Keopyung B-Town 1F, 203, Nonhyu - Kangnam-gu, - Seoul - KOREA, REPUBLIC OF - - 00-90-A4 (hex) ALTIGA NETWORKS - 0090A4 (base 16) ALTIGA NETWORKS - 124 GROVE STREET - FRANKLIN MA 02038-3206 - UNITED STATES - - 00-90-A5 (hex) SPECTRA LOGIC - 0090A5 (base 16) SPECTRA LOGIC - 1700 N. 55TH STREET - BOULDER CO 80301 - UNITED STATES - - 00-90-A6 (hex) CISCO SYSTEMS, INC. - 0090A6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-A7 (hex) CLIENTEC CORPORATION - 0090A7 (base 16) CLIENTEC CORPORATION - 8175 S. VIRGINIA ST. - SUITE #850-249 - RENO NV 89511 - UNITED STATES - - 00-90-A8 (hex) NineTiles Networks, Ltd. - 0090A8 (base 16) NineTiles Networks, Ltd. - 9 Station Road - Waterbeach Cambridge CB5 9HT - UNITED KINGDOM - - 00-90-A9 (hex) WESTERN DIGITAL - 0090A9 (base 16) WESTERN DIGITAL - 1599 NORTH BROADWAY - ROCHESTER MN 55906 - UNITED STATES - - 00-90-AA (hex) INDIGO ACTIVE VISION SYSTEMS LIMITED - 0090AA (base 16) INDIGO ACTIVE VISION SYSTEMS LIMITED - THE EDINBURGH TECHNOPOLE - BASH LOAN - Edinburgh EH26 OPJ - UNITED KINGDOM - - 00-90-AB (hex) CISCO SYSTEMS, INC. - 0090AB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-AC (hex) OPTIVISION, INC. - 0090AC (base 16) OPTIVISION, INC. - 3450 HILLVIEW AVENUE - PALO ALTO CA 94304 - UNITED STATES - - 00-90-AD (hex) ASPECT ELECTRONICS, INC. - 0090AD (base 16) ASPECT ELECTRONICS, INC. - 12740 EARHART AVE. - AUBURN CA 95602 - UNITED STATES - - 00-90-AE (hex) ITALTEL S.p.A. - 0090AE (base 16) ITALTEL S.p.A. - LOCALITA' BOSCHETTO - 67100 L'AQUILA - ITALY - - 00-90-AF (hex) J. MORITA MFG. CORP. - 0090AF (base 16) J. MORITA MFG. CORP. - 680 HIGASHIHAMA MINAMI-CHO - FUSHIMI-KU, KYOTO 612-8213 - JAPAN - - 00-90-B0 (hex) VADEM - 0090B0 (base 16) VADEM - 1960 ZANKER RD - SAN JOSE CA 95112 - UNITED STATES - - 00-90-B1 (hex) CISCO SYSTEMS, INC. - 0090B1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DR. - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-B2 (hex) AVICI SYSTEMS INC. - 0090B2 (base 16) AVICI SYSTEMS INC. - 12 ELIZABETH DRIVE - CHELMSFORD MA 01824 - UNITED STATES - - 00-90-B3 (hex) AGRANAT SYSTEMS - 0090B3 (base 16) AGRANAT SYSTEMS - 1345 MAIN STREET - WALTHAM MA 02154 - UNITED STATES - - 00-90-B4 (hex) WILLOWBROOK TECHNOLOGIES - 0090B4 (base 16) WILLOWBROOK TECHNOLOGIES - 7120 HAYVENHURST AVE.-STE.#401 - VAN NUYS CA 91406 - UNITED STATES - - 00-90-B5 (hex) NIKON CORPORATION - 0090B5 (base 16) NIKON CORPORATION - Electronic Imaging Division, Designing D - 1-6-3, NISHI-OHI, SHINAGAWA-KU - TOKYO 140-8601 - JAPAN - - 00-90-B6 (hex) FIBEX SYSTEMS - 0090B6 (base 16) FIBEX SYSTEMS - 5350 OLD REDWOOD HIGHWAY - PETALUMA CA 94954 - UNITED STATES - - 00-90-B7 (hex) DIGITAL LIGHTWAVE, INC. - 0090B7 (base 16) DIGITAL LIGHTWAVE, INC. - 601 CLEVELAND STREET- 5TH FL. - CLEARWATER FL 33755 - UNITED STATES - - 00-90-B8 (hex) ROHDE & SCHWARZ GMBH & CO. KG - 0090B8 (base 16) ROHDE & SCHWARZ GMBH & CO. KG - POSTFACH: 80 14 69/ABT.: 3CK - D-81614 MUNCHEN - GERMANY - - 00-90-B9 (hex) BERAN INSTRUMENTS LTD. - 0090B9 (base 16) BERAN INSTRUMENTS LTD. - HATCHMOOR INDUSTRIAL ESTATE - TORRINGTON - N DEVON EX38 7HP - UNITED KINGDOM - - 00-90-BA (hex) VALID NETWORKS, INC. - 0090BA (base 16) VALID NETWORKS, INC. - 6 CROMWELL #102 - IRVINE CA 92618 - UNITED STATES - - 00-90-BB (hex) TAINET COMMUNICATION SYSTEM Corp. - 0090BB (base 16) TAINET COMMUNICATION SYSTEM Corp. - 3 FL, NO. 6, ALLEY 23, LANE 91 SEC. 1 - Nei-Hu Road - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-90-BC (hex) TELEMANN CO., LTD. - 0090BC (base 16) TELEMANN CO., LTD. - 6F DONGSIN BLDG. - 543, DOGOK-DONG, KANGNAM-KU - SEOUL, 135-270 - KOREA, REPUBLIC OF - - 00-90-BD (hex) OMNIA COMMUNICATIONS, INC. - 0090BD (base 16) OMNIA COMMUNICATIONS, INC. - 100 NICKERSON ROAD - MARLBOROUGH MA 01752 - UNITED STATES - - 00-90-BE (hex) IBC/INTEGRATED BUSINESS COMPUTERS - 0090BE (base 16) IBC/INTEGRATED BUSINESS COMPUTERS - 2685 C PARK CENTER DRIVE - SIMI VALLEY CA 93065 - UNITED STATES - - 00-90-BF (hex) CISCO SYSTEMS, INC. - 0090BF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-C0 (hex) K.J. LAW ENGINEERS, INC. - 0090C0 (base 16) K.J. LAW ENGINEERS, INC. - 42300 W. NINE MILE ROAD - NOVI MI 48375 - UNITED STATES - - 00-90-C1 (hex) Peco II, Inc. - 0090C1 (base 16) Peco II, Inc. - 7060 Huntley Road - Columbus OH 43229 - UNITED STATES - - 00-90-C2 (hex) JK microsystems, Inc. - 0090C2 (base 16) JK microsystems, Inc. - 1275 YUBA AVENUE - SAN PABLO CA 94806 - UNITED STATES - - 00-90-C3 (hex) TOPIC SEMICONDUCTOR CORP. - 0090C3 (base 16) TOPIC SEMICONDUCTOR CORP. - 11F-1, NO. 2, WU-LIN RD. - HSIN-CHU - TAIWAN, PROVINCE OF CHINA - - 00-90-C4 (hex) JAVELIN SYSTEMS, INC. - 0090C4 (base 16) JAVELIN SYSTEMS, INC. - 1881 LANGLEY AVE. - IRVINE CA 92614 - UNITED STATES - - 00-90-C5 (hex) INTERNET MAGIC, INC. - 0090C5 (base 16) INTERNET MAGIC, INC. - 6450 LUSK BLVD.-STE. #E-201 - SAN DIEGO CA 92121 - UNITED STATES - - 00-90-C6 (hex) OPTIM SYSTEMS, INC. - 0090C6 (base 16) OPTIM SYSTEMS, INC. - 8201 GREENSBORO DR.-STE. #1000 - MCLEAN VA 22102 - UNITED STATES - - 00-90-C7 (hex) ICOM INC. - 0090C7 (base 16) ICOM INC. - 6-9-16 KAMIHIGASHI - HIRANO-KU, OSAKA - JAPAN - - 00-90-C8 (hex) WAVERIDER COMMUNICATIONS (CANADA) INC. - 0090C8 (base 16) WAVERIDER COMMUNICATIONS (CANADA) INC. - - British Columbia V1E 4R9 - CANADA - - 00-90-C9 (hex) DPAC Technologies - 0090C9 (base 16) DPAC Technologies - 7321 Lincoln Way - Garden Grove CA 92841 - UNITED STATES - - 00-90-CA (hex) ACCORD VIDEO TELECOMMUNICATIONS, LTD. - 0090CA (base 16) ACCORD VIDEO TELECOMMUNICATIONS, LTD. - 10, MARTIN GEHL STR, PO BOX 3564 - Petach-Tikva 49130 - ISRAEL - - 00-90-CB (hex) Wireless OnLine, Inc. - 0090CB (base 16) Wireless OnLine, Inc. - 4410 EL CAMINO REAL, STE #101 - LOS ALTOS CA 94022 - UNITED STATES - - 00-90-CC (hex) Planex Communications - 0090CC (base 16) Planex Communications - 2F FENISSAY Ebisu Bldg - 3-16-3 Higashi, - Shibuya-ku, Tokyo 150-0011 - JAPAN - - 00-90-CD (hex) ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. - 0090CD (base 16) ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. - R. ENG FREDERICO ULRICH - APARTADO 3081 - Guardeiras - 4470 Moreira Maia - PORTUGAL - - 00-90-CE (hex) TETRA GmbH - 0090CE (base 16) TETRA GmbH - GEWERBEPARK "AmWald" 4 - D-98693 ILMENAU - GERMANY - - 00-90-CF (hex) NORTEL - 0090CF (base 16) NORTEL - 250 SIDNEY STREET - Belleville Ontario K8N 5B7 - CANADA - - 00-90-D0 (hex) Thomson Telecom Belgium - 0090D0 (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - B-2650 EDEGEM - BELGIUM - - 00-90-D1 (hex) LEICHU ENTERPRISE CO., LTD. - 0090D1 (base 16) LEICHU ENTERPRISE CO., LTD. - 8F, NO. 203, PA-TEH ROAD, SEC.2 - TAIPEI CITY - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-90-D2 (hex) ARTEL VIDEO SYSTEMS - 0090D2 (base 16) ARTEL VIDEO SYSTEMS - 237 CEDAR HILL ST. - MARLBORO MA 01752 - UNITED STATES - - 00-90-D3 (hex) GIESECKE & DEVRIENT GmbH - 0090D3 (base 16) GIESECKE & DEVRIENT GmbH - PRINZREGENTENSTRASSE 159 - D-81677 MUNCHEN - GERMANY - - 00-90-D4 (hex) BindView Development Corp. - 0090D4 (base 16) BindView Development Corp. - 3355 WEST ALABAMA #1200 - HOUSTON TX 77098 - UNITED STATES - - 00-90-D5 (hex) EUPHONIX, INC. - 0090D5 (base 16) EUPHONIX, INC. - 220 PORTAGE AVE. - PALO ALTO CA 94306 - UNITED STATES - - 00-90-D6 (hex) CRYSTAL GROUP - 0090D6 (base 16) CRYSTAL GROUP - 850 KACENA RD. - HIAWATHA IA 52233 - UNITED STATES - - 00-90-D7 (hex) NetBoost Corp. - 0090D7 (base 16) NetBoost Corp. - 390 CAMBRIDGE AVENUE - PALO ALTO CA 94306-1506 - UNITED STATES - - 00-90-D8 (hex) WHITECROSS SYSTEMS - 0090D8 (base 16) WHITECROSS SYSTEMS - 3A WATERSIDE PARK, COOKHAM RD - BRACKNELL - BERKSHIRE RG12 1RB - UNITED KINGDOM - - 00-90-D9 (hex) CISCO SYSTEMS, INC. - 0090D9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S/ SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-DA (hex) DYNARC, INC. - 0090DA (base 16) DYNARC, INC. - 1887 LANDINGS DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-90-DB (hex) NEXT LEVEL COMMUNICATIONS - 0090DB (base 16) NEXT LEVEL COMMUNICATIONS - 6085 STATE FARM DRIVE - ROHNERT PARK CA 94928 - UNITED STATES - - 00-90-DC (hex) TECO INFORMATION SYSTEMS - 0090DC (base 16) TECO INFORMATION SYSTEMS - CO., LTD. - 2841 JUNCTION AVE., STE. #116 - SAN JOSE CA 95134 - UNITED STATES - - 00-90-DD (hex) MIHARU COMMUNICATIONS Inc - 0090DD (base 16) MIHARU COMMUNICATIONS Inc - - 1285, IWASE, KAMAKURA-CITY - KANAGAWA - JAPAN - - 00-90-DE (hex) CARDKEY SYSTEMS, INC. - 0090DE (base 16) CARDKEY SYSTEMS, INC. - 1757 TAPO CANYON ROAD - SIMI VALLEY CA 93063 - UNITED STATES - - 00-90-DF (hex) MITSUBISHI CHEMICAL AMERICA, INC. - 0090DF (base 16) MITSUBISHI CHEMICAL AMERICA, INC. - 445 INDIO WAY - SUNNYVALE CA 94086 - UNITED STATES - - 00-90-E0 (hex) SYSTRAN CORP. - 0090E0 (base 16) SYSTRAN CORP. - 4126 LINDEN AVENUE - DAYTON OH 45432 - UNITED STATES - - 00-90-E1 (hex) TELENA S.P.A. - 0090E1 (base 16) TELENA S.P.A. - VIA SAVONA, 146 - 20144 MILANO - ITALY - - 00-90-E2 (hex) DISTRIBUTED PROCESSING TECHNOLOGY - 0090E2 (base 16) DISTRIBUTED PROCESSING TECHNOLOGY - 140 CANDACE DRIVE - ORLANDO FL 32751 - UNITED STATES - - 00-90-E3 (hex) AVEX ELECTRONICS INC. - 0090E3 (base 16) AVEX ELECTRONICS INC. - 4807 BRADFORD DRIVE - HUNTSVILLE AL 35805 - UNITED STATES - - 00-90-E4 (hex) NEC AMERICA, INC. - 0090E4 (base 16) NEC AMERICA, INC. - 3100 N.E. SHUTE ROAD - HILLSBORO OR 97124 - UNITED STATES - - 00-90-E5 (hex) TEKNEMA, INC. - 0090E5 (base 16) TEKNEMA, INC. - 2656 E. BAYSHORE ROAD - PALO ALTO CA 94303 - UNITED STATES - - 00-90-E6 (hex) ALi Corporation - 0090E6 (base 16) ALi Corporation - 6F, 246 NeiHu Road, Sec. 1 - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 00-90-E7 (hex) HORSCH ELEKTRONIK AG - 0090E7 (base 16) HORSCH ELEKTRONIK AG - HAAGERSTRASSE - POSTFACH - CH-9473 GAMS - SWITZERLAND - - 00-90-E8 (hex) MOXA TECHNOLOGIES CORP., LTD. - 0090E8 (base 16) MOXA TECHNOLOGIES CORP., LTD. - 7F, NO. 2, ALY6, LN 235 - PAO-CHIAO RD, - SHIENG-TIEN CITY TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-90-E9 (hex) JANZ COMPUTER AG - 0090E9 (base 16) JANZ COMPUTER AG - Im Dörener Feld 8 - D-33100 Paderborn - GERMANY - - 00-90-EA (hex) ALPHA TECHNOLOGIES, INC. - 0090EA (base 16) ALPHA TECHNOLOGIES, INC. - 3767 ALPHA WAY - BELLINGHAM WA 98226 - UNITED STATES - - 00-90-EB (hex) SENTRY TELECOM SYSTEMS - 0090EB (base 16) SENTRY TELECOM SYSTEMS - 8664 COMMERCE COURT - BURNABY BC V5A 4N7 - CANADA - - 00-90-EC (hex) PYRESCOM - 0090EC (base 16) PYRESCOM - 3 ALLEE DU MOULIN - 66680 CANOHES - FRANCE - - 00-90-ED (hex) CENTRAL SYSTEM RESEARCH CO., LTD. - 0090ED (base 16) CENTRAL SYSTEM RESEARCH CO., LTD. - 4-13-2 HIYOSHICHO - KOKUBUNJI-CITY TOKYO 18500032 - JAPAN - - 00-90-EE (hex) PERSONAL COMMUNICATIONS TECHNOLOGIES - 0090EE (base 16) PERSONAL COMMUNICATIONS TECHNOLOGIES - 50 STILES ROAD - SALEM NH 03079 - UNITED STATES - - 00-90-EF (hex) INTEGRIX, INC. - 0090EF (base 16) INTEGRIX, INC. - 2001 CORPORATE CENTER DRIVE - NEWBURY PARK CA 91320 - UNITED STATES - - 00-90-F0 (hex) Harmonic Video Systems Ltd. - 0090F0 (base 16) Harmonic Video Systems Ltd. - 19 ALON HATAVOR STREET - Zone 3, PO Box 3600 - CAESAREA Industrial Park 38900 - ISRAEL - - 00-90-F1 (hex) DOT HILL SYSTEMS CORPORATION - 0090F1 (base 16) DOT HILL SYSTEMS CORPORATION - 6305 El Camino Real - Carlsbad CA 92009 - UNITED STATES - - 00-90-F2 (hex) CISCO SYSTEMS, INC. - 0090F2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-90-F3 (hex) ASPECT COMMUNICATIONS - 0090F3 (base 16) ASPECT COMMUNICATIONS - 1310 Ridder Park Drive - San Jose CA 95131-2313 - UNITED STATES - - 00-90-F4 (hex) LIGHTNING INSTRUMENTATION - 0090F4 (base 16) LIGHTNING INSTRUMENTATION - BOVERESSES 50 - 1010 LAUSANNE - SWITZERLAND - - 00-90-F5 (hex) CLEVO CO. - 0090F5 (base 16) CLEVO CO. - 35, WU-GON 6TH ROAD - WU-KU INDUSTRIAL PARK - TAIPEI HSIEN - TAIWAN, PROVINCE OF CHINA - - 00-90-F6 (hex) ESCALATE NETWORKS, INC. - 0090F6 (base 16) ESCALATE NETWORKS, INC. - 6 HUGHES - IRVINE CA 92617 - UNITED STATES - - 00-90-F7 (hex) NBASE COMMUNICATIONS LTD. - 0090F7 (base 16) NBASE COMMUNICATIONS LTD. - INDUSTRIAL PARK - YOQNEAM ILIT P.O. BOX 114 - ISRAEL - - 00-90-F8 (hex) MEDIATRIX TELECOM - 0090F8 (base 16) MEDIATRIX TELECOM - 4229 GARLOCK - SHERBROOKE - QUEBEC J1L 2C8 - CANADA - - 00-90-F9 (hex) LEITCH - 0090F9 (base 16) LEITCH - 10 DYAS ROAD - DON MILLS - ONTARIO M3B 1V5 - CANADA - - 00-90-FA (hex) Emulex Corporation - 0090FA (base 16) Emulex Corporation - 3333 Susan Street - Costa Mesa CA 92626 - UNITED STATES - - 00-90-FB (hex) PORTWELL, INC. - 0090FB (base 16) PORTWELL, INC. - 7F-4, NO. 160, SEC. 6 - MING-CHUANG E. RD. - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-90-FC (hex) NETWORK COMPUTING DEVICES - 0090FC (base 16) NETWORK COMPUTING DEVICES - 301 RAVENDALE DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-90-FD (hex) CopperCom, Inc. - 0090FD (base 16) CopperCom, Inc. - 3255-1 SCOTT BLVD.,--STE.#103 - SANTA CLARA CA 95054 - UNITED STATES - - 00-90-FE (hex) ELECOM CO., LTD. (LANEED DIV.) - 0090FE (base 16) ELECOM CO., LTD. (LANEED DIV.) - TOKYU BANCHO BLDG. - 4-6 - Chiyoda-ku TOKYO 102-0081 - JAPAN - - 00-90-FF (hex) TELLUS TECHNOLOGY INC. - 0090FF (base 16) TELLUS TECHNOLOGY INC. - 40990 ENCYCLOPEDIA CIR. - FREMONT CA 94538-2470 - UNITED STATES - - 00-91-D6 (hex) Crystal Group, Inc. - 0091D6 (base 16) Crystal Group, Inc. - 850 Kacena Rd. - Hiawatha IA 52233 - UNITED STATES - - 00-91-FA (hex) Synapse Product Development - 0091FA (base 16) Synapse Product Development - 1511 6th Ave - Suite 400 - Seattle WA 98101 - UNITED STATES - - 00-92-FA (hex) SHENZHEN WISKY TECHNOLOGY CO.,LTD - 0092FA (base 16) SHENZHEN WISKY TECHNOLOGY CO.,LTD - 5/F W2-A,Hight-tech Park South 1 Road,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 00-93-63 (hex) Uni-Link Technology Co., Ltd. - 009363 (base 16) Uni-Link Technology Co., Ltd. - 7-5, No.66, Sec.2, Nan-Kan Rd., Lu-Chu Hsiang, - Taoyuan 338 - TAIWAN, PROVINCE OF CHINA - - 00-95-69 (hex) LSD Science and Technology Co.,Ltd. - 009569 (base 16) LSD Science and Technology Co.,Ltd. - Lierda Building,No.425 Dengyun Rd. - Hangzhou Zhijiang 310011 - CHINA - - 00-97-FF (hex) Heimann Sensor GmbH - 0097FF (base 16) Heimann Sensor GmbH - Maria-Reiche-Str. 1 - Dresden Sachsen 01109 - GERMANY - - 00-9C-02 (hex) Hewlett-Packard Company - 009C02 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 00-9D-8E (hex) CARDIAC RECORDERS, INC. - 009D8E (base 16) CARDIAC RECORDERS, INC. - 34 SCARBORO ROAD - LONDON N4 4L U - UNITED KINGDOM - UNITED KINGDOM - - 00-9E-C8 (hex) Beijing Xiaomi Electronic Products Co., Ltd. - 009EC8 (base 16) Beijing Xiaomi Electronic Products Co., Ltd. - Floor 2, Building 7, TianChangYuan, MeiTiCun, - HongJunYing South Road, ChaoYang District - Beijing 100107 - CHINA - - 00-A0-00 (hex) CENTILLION NETWORKS, INC. - 00A000 (base 16) CENTILLION NETWORKS, INC. - 359 RAVENDALE DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-A0-01 (hex) DRS Signal Solutions - 00A001 (base 16) DRS Signal Solutions - 700 Quince Orchard Road - Gaithersburg MD 20878-1794 - UNITED STATES - - 00-A0-02 (hex) LEEDS & NORTHRUP AUSTRALIA PTY LTD - 00A002 (base 16) LEEDS & NORTHRUP AUSTRALIA PTY LTD - PO BOX 4009 - EIGHT MILE PLAINS QLD 4113 - AUSTRALIA - - 00-A0-03 (hex) Siemens Switzerland Ltd., I B T HVP - 00A003 (base 16) Siemens Switzerland Ltd., I B T HVP - Building Technologies Division, International Headquarters - I BT HVP SYS RD EU Gubelstrasse 22 - Zug 6301 - SWITZERLAND - - 00-A0-04 (hex) NETPOWER, INC. - 00A004 (base 16) NETPOWER, INC. - 545 OAKMEAD PARKWAY - SUNNYVALE CA 94086 - UNITED STATES - - 00-A0-05 (hex) DANIEL INSTRUMENTS, LTD. - 00A005 (base 16) DANIEL INSTRUMENTS, LTD. - TROLLSTRASSE 33 - CH-8400 WINTERTHUR - SWITZERLAND - - 00-A0-06 (hex) IMAGE DATA PROCESSING SYSTEM GROUP - 00A006 (base 16) IMAGE DATA PROCESSING SYSTEM GROUP - SHINTOYOFUTA 2-1 - KASHIWA-CITY, CHIBA 277 - JAPAN - - 00-A0-07 (hex) APEXX TECHNOLOGY, INC. - 00A007 (base 16) APEXX TECHNOLOGY, INC. - 506 S. 11TH - PO BOX 9291 - BOISE ID 83707 - UNITED STATES - - 00-A0-08 (hex) NETCORP - 00A008 (base 16) NETCORP - 8 PLACE OF COMMERCE--STE #200 - BROSSARD, QUEBEC - CANADA J4W 3H2 - CANADA - - 00-A0-09 (hex) WHITETREE NETWORK - 00A009 (base 16) WHITETREE NETWORK - TECHNOLOGIES, INC. - 3200 ASH STREET - PALO ALTO CA 94306 - UNITED STATES - - 00-A0-0A (hex) Airspan - 00A00A (base 16) Airspan - Unitronics Building, Arava Street, Airport City - POB 199 - 70100 - ISRAEL - - 00-A0-0B (hex) COMPUTEX CO., LTD. - 00A00B (base 16) COMPUTEX CO., LTD. - 432-13 GOJYOBASHI-HIGASHI 4-CHYOME - HIGASHIYAMAKU, KYOTO-CITY 605 - JAPAN - - 00-A0-0C (hex) KINGMAX TECHNOLOGY, INC. - 00A00C (base 16) KINGMAX TECHNOLOGY, INC. - 2FL., NO. 4, LANE 902, SEC.2 - KUANG FU RD., HSIN-CHU CITY - TAIWAN, PROVINCE OF CHINA - - 00-A0-0D (hex) THE PANDA PROJECT - 00A00D (base 16) THE PANDA PROJECT - 5201 CONGRESS AVE. - C-100 - BOCA RATON FL 33487 - UNITED STATES - - 00-A0-0E (hex) VISUAL NETWORKS, INC. - 00A00E (base 16) VISUAL NETWORKS, INC. - 2092 GAITHER ROAD- STE #220 - ROCKVILLE MD 20850 - UNITED STATES - - 00-A0-0F (hex) Broadband Technologies - 00A00F (base 16) Broadband Technologies - P.O. Box 13737 - Research Triangle Park, NC 27709-3737 - UNITED STATES - - 00-A0-10 (hex) SYSLOGIC DATENTECHNIK AG - 00A010 (base 16) SYSLOGIC DATENTECHNIK AG - Bruggerstrasse 69 - CH-5400 Baden - SWITZERLAND - - 00-A0-11 (hex) MUTOH INDUSTRIES LTD. - 00A011 (base 16) MUTOH INDUSTRIES LTD. - 253 KANAGAWA-KEN, - CHIGASAKI-SHI SHIMOMACHIYA 1-3-1 - JAPAN - - 00-A0-12 (hex) Telco Systems, Inc. - 00A012 (base 16) Telco Systems, Inc. - 15 Berkshire Road - Mansfield, MA 02048 - UNITED STATES - - 00-A0-13 (hex) TELTREND LTD. - 00A013 (base 16) TELTREND LTD. - RINGWAY HOUSE, BELL ROAD - DANESHILL, - BASINGSTOKE HAMPSHIRE RG24 8F - UNITED KINGDOM - - 00-A0-14 (hex) CSIR - 00A014 (base 16) CSIR - P.O. BOX 395 - PRETORIA 0001 - SOUTH AFRICA - SOUTH AFRICA - - 00-A0-15 (hex) WYLE - 00A015 (base 16) WYLE - 3000 BOWERS AVENUE - SANTA CLARA CA 95051 - UNITED STATES - - 00-A0-16 (hex) MICROPOLIS CORP. - 00A016 (base 16) MICROPOLIS CORP. - 21211 NORDHOFF STREET - CHATSWORTH CA 91311 - UNITED STATES - - 00-A0-17 (hex) J B M CORPORATION - 00A017 (base 16) J B M CORPORATION - 10-1, ARAMOTOSHIN MACHI - HIGASHI OSAKA - 577 - JAPAN - - 00-A0-18 (hex) CREATIVE CONTROLLERS, INC. - 00A018 (base 16) CREATIVE CONTROLLERS, INC. - 128 KENDRICK LANE - PICAYUNE MS 39466 - UNITED STATES - - 00-A0-19 (hex) NEBULA CONSULTANTS, INC. - 00A019 (base 16) NEBULA CONSULTANTS, INC. - 1449 DUNCAN DRIVE - DELTA, BC V4L 1R5 - CANADA - - 00-A0-1A (hex) BINAR ELEKTRONIK AB - 00A01A (base 16) BINAR ELEKTRONIK AB - MAGNETUAGEN 18 - S-46138 TROLLHATTAN - SWEDEN - - 00-A0-1B (hex) PREMISYS COMMUNICATIONS, INC. - 00A01B (base 16) PREMISYS COMMUNICATIONS, INC. - 48664 MILMONT DRIVE - FREMONT CA 94538 - UNITED STATES - - 00-A0-1C (hex) NASCENT NETWORKS CORPORATION - 00A01C (base 16) NASCENT NETWORKS CORPORATION - 277 MAIN STREET, 3RD FLR. - MARLBORO MA 01752 - UNITED STATES - - 00-A0-1D (hex) Red Lion Controls, LP - 00A01D (base 16) Red Lion Controls, LP - 20 Willow Springs Circle - York NY 17402 - UNITED STATES - - 00-A0-1E (hex) EST CORPORATION - 00A01E (base 16) EST CORPORATION - 120 ROYALL STREET - CANTON MA 02021 - UNITED STATES - - 00-A0-1F (hex) TRICORD SYSTEMS, INC. - 00A01F (base 16) TRICORD SYSTEMS, INC. - 2800 NORTHWEST BOULEVARD - PLYMOUTH MN 55441-2625 - UNITED STATES - - 00-A0-20 (hex) CITICORP/TTI - 00A020 (base 16) CITICORP/TTI - 3100 OCEAN PARK BLVD. - SANTA MONICA CA 90405 - UNITED STATES - - 00-A0-21 (hex) General Dynamics - 00A021 (base 16) General Dynamics - C4 Systems - 77A Street - Needham Heights MA 02494-2892 - UNITED STATES - - 00-A0-22 (hex) CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING - 00A022 (base 16) CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING - UNIVERSITY OF POONA CAMPUS - GANESH KHIND, Pune - 411 008 - INDIA - - 00-A0-23 (hex) APPLIED CREATIVE TECHNOLOGY, INC. - 00A023 (base 16) APPLIED CREATIVE TECHNOLOGY, INC. - 2626 LOMBARDY LANE--STE.#107 - DALLAS TX 75220 - UNITED STATES - - 00-A0-24 (hex) 3COM CORPORATION - 00A024 (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - SANTA CLARA CA 95052 - UNITED STATES - - 00-A0-25 (hex) REDCOM LABS INC. - 00A025 (base 16) REDCOM LABS INC. - ONE REDCOM CENTER - VICTOR NY 14564-0995 - UNITED STATES - - 00-A0-26 (hex) TELDAT, S.A. - 00A026 (base 16) TELDAT, S.A. - PARQUE TECNOLOGICO MADRID - 28760 TACS CAN TOS (MADRID) - SPAIN - - 00-A0-27 (hex) FIREPOWER SYSTEMS, INC. - 00A027 (base 16) FIREPOWER SYSTEMS, INC. - 190 INDEPENDENCE DRIVE - MENLO PARK CA 94025 - UNITED STATES - - 00-A0-28 (hex) CONNER PERIPHERALS - 00A028 (base 16) CONNER PERIPHERALS - 3061 ZANKER ROAD - SAN JOSE CA 95134-2128 - UNITED STATES - - 00-A0-29 (hex) COULTER CORPORATION - 00A029 (base 16) COULTER CORPORATION - 11800 S.W. 147TH AVE. - MIAMI FL 33196 - UNITED STATES - - 00-A0-2A (hex) TRANCELL SYSTEMS - 00A02A (base 16) TRANCELL SYSTEMS - 3180 DE LA CRUZ BLVD.-STE#200 - SANTA CLARA CA 95054-2402 - UNITED STATES - - 00-A0-2B (hex) TRANSITIONS RESEARCH CORP. - 00A02B (base 16) TRANSITIONS RESEARCH CORP. - SHELTER ROCK LANE - DANBURY CT 06810 - UNITED STATES - - 00-A0-2C (hex) interWAVE Communications - 00A02C (base 16) interWAVE Communications - 656 BAIR ISLAND BLVD.-STE.#108 - REDWOOD CITY CA 94063-2704 - UNITED STATES - - 00-A0-2D (hex) 1394 Trade Association - 00A02D (base 16) 1394 Trade Association - 3925 WEST BRAKER LANE - AUSTIN TX 78759 - UNITED STATES - - 00-A0-2E (hex) BRAND COMMUNICATIONS, LTD. - 00A02E (base 16) BRAND COMMUNICATIONS, LTD. - ENTERPRISE HOUSE, CHIVERS WAY, - HISTON, CAMBRIDGE CB4 4ZR - UNITED KINGDOM - - 00-A0-2F (hex) PIRELLI CAVI - 00A02F (base 16) PIRELLI CAVI - VIALE SARCA 222 - 20126 MILAN - ITALY - - 00-A0-30 (hex) CAPTOR NV/SA - 00A030 (base 16) CAPTOR NV/SA - DE HENE 13 - B-1780 WEMMEL - BELGIUM - - 00-A0-31 (hex) HAZELTINE CORPORATION, MS 1-17 - 00A031 (base 16) HAZELTINE CORPORATION, MS 1-17 - 450 E. PULASKI ROAD - GREENLAWN NY 11740 - UNITED STATES - - 00-A0-32 (hex) GES SINGAPORE PTE. LTD. - 00A032 (base 16) GES SINGAPORE PTE. LTD. - 14 SUNGEI KADUT AVENUE - SINGAPORE 2572 - SINGAPORE - - 00-A0-33 (hex) imc MeBsysteme GmbH - 00A033 (base 16) imc MeBsysteme GmbH - VOLTASTRASSE 5 - D-13355 BERLIN - GERMANY - - 00-A0-34 (hex) AXEL - 00A034 (base 16) AXEL - 16, AVENUE DU QUEBEC - Z.A. COURTABOEUF 91962 LES ULIS - FRANCE - - 00-A0-35 (hex) CYLINK CORPORATION - 00A035 (base 16) CYLINK CORPORATION - 3131 JAY STREET - SANTA CLARA CA 95054 - UNITED STATES - - 00-A0-36 (hex) APPLIED NETWORK TECHNOLOGY - 00A036 (base 16) APPLIED NETWORK TECHNOLOGY - 319 LITTLETON ROAD--STE #101 - WESTFORD MA 01886-4133 - UNITED STATES - - 00-A0-37 (hex) Mindray DS USA, Inc. - 00A037 (base 16) Mindray DS USA, Inc. - 800 Macarthur Blvd. - Mahwah NJ 07430 - UNITED STATES - - 00-A0-38 (hex) EMAIL ELECTRONICS - 00A038 (base 16) EMAIL ELECTRONICS - P.O. BOX 154 - MOOROOLBARK, 3138 - AUSTRALIA - - 00-A0-39 (hex) ROSS TECHNOLOGY, INC. - 00A039 (base 16) ROSS TECHNOLOGY, INC. - 5316 HWY 290 WEST - STE. #500 - AUSTIN TX 78735 - UNITED STATES - - 00-A0-3A (hex) KUBOTEK CORPORATION - 00A03A (base 16) KUBOTEK CORPORATION - 56 NISHIAKETA-CHO, HIGASHIKUJO - MINAMI-KU, KYOTO 601 - JAPAN - - 00-A0-3B (hex) TOSHIN ELECTRIC CO., LTD. - 00A03B (base 16) TOSHIN ELECTRIC CO., LTD. - 3FL. RIVER-STONE 3RD. BLG.234 - MIZONOKUCHI, TAKATSU-KV, KAWASAKI-SHI, - 213 - JAPAN - - 00-A0-3C (hex) EG&G NUCLEAR INSTRUMENTS - 00A03C (base 16) EG&G NUCLEAR INSTRUMENTS - 100 MIDLAND ROAD - OAK RIDGE TN 37830 - UNITED STATES - - 00-A0-3D (hex) OPTO-22 - 00A03D (base 16) OPTO-22 - 43044 BUSINESS PARK DR. - TEMECULA CA 92590 - UNITED STATES - - 00-A0-3E (hex) ATM FORUM - 00A03E (base 16) ATM FORUM - WORLDWIDE HEADQUARTERS - 303 VINTAGE PARK DRIVE - FOSTER CITY CA 94404-1138 - UNITED STATES - - 00-A0-3F (hex) COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C - 00A03F (base 16) COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C - % APPLE COMPUTER, INC. - 1 INFINITE LOOP, - CUPERTINO CA 95014 - UNITED STATES - - 00-A0-40 (hex) Apple - 00A040 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-A0-41 (hex) INFICON - 00A041 (base 16) INFICON - 2 Technology Place - E. Syracuse NY 13057 - UNITED STATES - - 00-A0-42 (hex) SPUR PRODUCTS CORP. - 00A042 (base 16) SPUR PRODUCTS CORP. - 9288 W. EMERALD STREET - BOISE ID 83704 - UNITED STATES - - 00-A0-43 (hex) AMERICAN TECHNOLOGY LABS, INC. - 00A043 (base 16) AMERICAN TECHNOLOGY LABS, INC. - 115 WEST 3RD STREET - LOWER LEVEL - STEVENSVILLE MT 59870 - UNITED STATES - - 00-A0-44 (hex) NTT IT CO., LTD. - 00A044 (base 16) NTT IT CO., LTD. - - KANNAI-WISE BLDG., 2-9-1 FUROU-CHO, NAKA - 231 - JAPAN - - 00-A0-45 (hex) PHOENIX CONTACT GMBH & CO. - 00A045 (base 16) PHOENIX CONTACT GMBH & CO. - POSTFACH 1341 - D-32819 BLOMBERG - GERMANY - - 00-A0-46 (hex) SCITEX CORP. LTD. - 00A046 (base 16) SCITEX CORP. LTD. - P.O.BOX 330 - HERZLIA B 46103 - ISRAEL - - 00-A0-47 (hex) INTEGRATED FITNESS CORP. - 00A047 (base 16) INTEGRATED FITNESS CORP. - 26 6TH STREET - STAMFORD CT 06905 - UNITED STATES - - 00-A0-48 (hex) QUESTECH, LTD. - 00A048 (base 16) QUESTECH, LTD. - EASTHEATH AVENUE - WOKINGHAM - BERKS, RG11 2PP - UNITED KINGDOM - - 00-A0-49 (hex) DIGITECH INDUSTRIES, INC. - 00A049 (base 16) DIGITECH INDUSTRIES, INC. - PO BOX 2267 - 55 KENOSIA AVENUE - DANBURY CT 06810 - UNITED STATES - - 00-A0-4A (hex) NISSHIN ELECTRIC CO., LTD. - 00A04A (base 16) NISSHIN ELECTRIC CO., LTD. - 5, MEOTOGOSHI, MUTSUSHI, - SHIKATSU-CYO, NISHIKASUGAI, - AICHI 481 - JAPAN - - 00-A0-4B (hex) TFL LAN INC. - 00A04B (base 16) TFL LAN INC. - 9F, NO. 499 CHUNG CHENG ROAD - SHIH-LIN DISTRICT, TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-A0-4C (hex) INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. - 00A04C (base 16) INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. - 48511 WARM SPRINGS BLVD. - SUITE # 211C - FREMONT CA 94539 - UNITED STATES - - 00-A0-4D (hex) EDA INSTRUMENTS, INC. - 00A04D (base 16) EDA INSTRUMENTS, INC. - 4 THORNCLIFFE PARK DRIVE - TORONTO, ONTARIO - M4H 1H1 - CANADA - - 00-A0-4E (hex) VOELKER TECHNOLOGIES, INC. - 00A04E (base 16) VOELKER TECHNOLOGIES, INC. - 22 NEW BOSTON COURT - DANVILLE CA 94526 - UNITED STATES - - 00-A0-4F (hex) AMERITEC CORP. - 00A04F (base 16) AMERITEC CORP. - 760 ARROW GRAND CIRCLE - COVINA CA 91722 - UNITED STATES - - 00-A0-50 (hex) CYPRESS SEMICONDUCTOR - 00A050 (base 16) CYPRESS SEMICONDUCTOR - 3901 NORTH FIRST STREET - SAN JOSE CA 95134 - UNITED STATES - - 00-A0-51 (hex) ANGIA COMMUNICATIONS. INC. - 00A051 (base 16) ANGIA COMMUNICATIONS. INC. - 441 EAST BAY BLVD. - PROVO UTAH 84606 - UNITED STATES - - 00-A0-52 (hex) STANILITE ELECTRONICS PTY. LTD - 00A052 (base 16) STANILITE ELECTRONICS PTY. LTD - 424, LANE COVE ROAD - NORTH RYDE NSW 2113 - AUSTRALIA - - 00-A0-53 (hex) COMPACT DEVICES, INC. - 00A053 (base 16) COMPACT DEVICES, INC. - 16795 LARK AVENUE - LOS GATOS CA 95030 - UNITED STATES - - 00-A0-54 (hex) PRIVATE - 00A054 (base 16) - - 00-A0-55 (hex) Data Device Corporation - 00A055 (base 16) Data Device Corporation - 105 Wilbur Place - Bohemia NY 11716 - UNITED STATES - - 00-A0-56 (hex) MICROPROSS - 00A056 (base 16) MICROPROSS - 33, RUE GANTOIS - 59000 LILLE - FRANCE - - 00-A0-57 (hex) LANCOM Systems GmbH - 00A057 (base 16) LANCOM Systems GmbH - Adenauer Straße 20 /B2 - D-52070 AACHEN - Würselen 52146 - GERMANY - - 00-A0-58 (hex) GLORY, LTD. - 00A058 (base 16) GLORY, LTD. - 1-3-1 SHIMOTENO, HIMEJI - HYOGO PREF. 670 - JAPAN - - 00-A0-59 (hex) HAMILTON HALLMARK - 00A059 (base 16) HAMILTON HALLMARK - 2105 LUNDY AVENUE - SAN JOSE CA 95131 - UNITED STATES - - 00-A0-5A (hex) KOFAX IMAGE PRODUCTS - 00A05A (base 16) KOFAX IMAGE PRODUCTS - 3 JENNER STREET - IRVINE CA 92718-3807 - UNITED STATES - - 00-A0-5B (hex) MARQUIP, INC. - 00A05B (base 16) MARQUIP, INC. - 1245 E. WASHINGTON AVE. - MADISON WI 53703 - UNITED STATES - - 00-A0-5C (hex) INVENTORY CONVERSION, INC./ - 00A05C (base 16) INVENTORY CONVERSION, INC./ - NEKOTECH DIVISION - 102 TIDE MILL ROAD -SUITE # 6 - HAMPTON NH 03842 - UNITED STATES - - 00-A0-5D (hex) CS COMPUTER SYSTEME GmbH - 00A05D (base 16) CS COMPUTER SYSTEME GmbH - ISARSTRASSE 3, - 82065 BAIERBRUNN - GERMANY - - 00-A0-5E (hex) MYRIAD LOGIC INC. - 00A05E (base 16) MYRIAD LOGIC INC. - 1109 SPRING STREET - SILVER SPRING MD 20910 - UNITED STATES - - 00-A0-5F (hex) BTG Electronics Design BV - 00A05F (base 16) BTG Electronics Design BV - P.O. Box 1543 - 3260 - BA Oud Beijerland - NETHERLANDS - - 00-A0-60 (hex) ACER PERIPHERALS, INC. - 00A060 (base 16) ACER PERIPHERALS, INC. - 9F, 135 CHIAN KUO N. RD. SEC 2 - TAIPEI, 10479 - TAIWAN, PROVINCE OF CHINA - - 00-A0-61 (hex) PURITAN BENNETT - 00A061 (base 16) PURITAN BENNETT - 2200 FARADAY AVENUE - CARLSBAD CA 92008 - UNITED STATES - - 00-A0-62 (hex) AES PRODATA - 00A062 (base 16) AES PRODATA - 249 BALCATTA ROAD - BALCATTA - WESTERN AUSTRALIA 6021 - AUSTRALIA - - 00-A0-63 (hex) JRL SYSTEMS, INC. - 00A063 (base 16) JRL SYSTEMS, INC. - 8305 HWY 71 WEST - AUSTIN TX 78735 - UNITED STATES - - 00-A0-64 (hex) KVB/ANALECT - 00A064 (base 16) KVB/ANALECT - 9420 JERONIMO ROAD - IRVINE CA 92718 - UNITED STATES - - 00-A0-65 (hex) Symantec Corporation - 00A065 (base 16) Symantec Corporation - 20330 Stevens Creek Blvd. - Cupertino CA 95014 - UNITED STATES - - 00-A0-66 (hex) ISA CO., LTD. - 00A066 (base 16) ISA CO., LTD. - SHINJUKU LAMBDAX BLDG. 5F., - 2-4-12 OKUBO, SHINJUKU-KU TOKYO - JAPAN - - 00-A0-67 (hex) NETWORK SERVICES GROUP - 00A067 (base 16) NETWORK SERVICES GROUP - 3421 COMMISSION COURT-STE #202 - WOODBRIDGE VA 22192 - UNITED STATES - - 00-A0-68 (hex) BHP LIMITED - 00A068 (base 16) BHP LIMITED - GPO BOX 86A - MELBOURNE 3001 VICTORIA - AUSTRALIA - - 00-A0-69 (hex) Symmetricom, Inc. - 00A069 (base 16) Symmetricom, Inc. - 3750 Westwind Blvd. - Santa Rosa CA 95403 - UNITED STATES - - 00-A0-6A (hex) Verilink Corporation - 00A06A (base 16) Verilink Corporation - 127 Jetplex Circle - Madison AL 35758 - UNITED STATES - - 00-A0-6B (hex) DMS DORSCH MIKROSYSTEM GMBH - 00A06B (base 16) DMS DORSCH MIKROSYSTEM GMBH - HOLMLUECK 13-15 - D-24972 STEINBERQKIRCHE - GERMANY - - 00-A0-6C (hex) SHINDENGEN ELECTRIC MFG. CO., LTD. - 00A06C (base 16) SHINDENGEN ELECTRIC MFG. CO., LTD. - 10-13, MINAMI-CHO, HANNOU-CITY - SAITAMA 357 - JORDAN - - 00-A0-6D (hex) MANNESMANN TALLY CORPORATION - 00A06D (base 16) MANNESMANN TALLY CORPORATION - P.O. BOX 97018 - KENT WA 98064-9718 - UNITED STATES - - 00-A0-6E (hex) AUSTRON, INC. - 00A06E (base 16) AUSTRON, INC. - P.O. BOX 14766 - AUSTIN TX 78761-4766 - UNITED STATES - - 00-A0-6F (hex) THE APPCON GROUP, INC. - 00A06F (base 16) THE APPCON GROUP, INC. - 23 RICHMOND STREET - ROCHESTER NY 14607 - UNITED STATES - - 00-A0-70 (hex) COASTCOM - 00A070 (base 16) COASTCOM - 1151 HARBOR BAY PARKWAY - ALAMEDA CA 94502-6511 - UNITED STATES - - 00-A0-71 (hex) VIDEO LOTTERY TECHNOLOGIES,INC - 00A071 (base 16) VIDEO LOTTERY TECHNOLOGIES,INC - 2311 SOUTH 7TH AVENUE - BOZEMAN MT 59715 - UNITED STATES - - 00-A0-72 (hex) OVATION SYSTEMS LTD. - 00A072 (base 16) OVATION SYSTEMS LTD. - GREAT HASELEY TRAD. EST. - GREAT HASELEY, OXFORDSHIRE OX9 7PF - ENGLAND - UNITED KINGDOM - - 00-A0-73 (hex) COM21, INC. - 00A073 (base 16) COM21, INC. - 2113 LANDINGS DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-A0-74 (hex) PERCEPTION TECHNOLOGY - 00A074 (base 16) PERCEPTION TECHNOLOGY - 40 SHAWMUT ROAD - CANTON MA 02021-1409 - UNITED STATES - - 00-A0-75 (hex) MICRON TECHNOLOGY, INC. - 00A075 (base 16) MICRON TECHNOLOGY, INC. - 8000 S. Federal Way - P.O. Box 6 - Boise ID 83707-0006 - UNITED STATES - - 00-A0-76 (hex) CARDWARE LAB, INC. - 00A076 (base 16) CARDWARE LAB, INC. - 285 SOBRANTE WAY, STE. - SUNNYVALE CA 94086 - UNITED STATES - - 00-A0-77 (hex) FUJITSU NEXION, INC. - 00A077 (base 16) FUJITSU NEXION, INC. - 289 GREAT ROAD - ACTON MA 01720-4739 - UNITED STATES - - 00-A0-78 (hex) Marconi Communications - 00A078 (base 16) Marconi Communications - 1000 Fore Drive - Warrendale PA 15086-7502 - UNITED STATES - - 00-A0-79 (hex) ALPS ELECTRIC (USA), INC. - 00A079 (base 16) ALPS ELECTRIC (USA), INC. - 3553 NORTH 1ST STREET - SAN JOSE CA 95134 - UNITED STATES - - 00-A0-7A (hex) ADVANCED PERIPHERALS TECHNOLOGIES, INC. - 00A07A (base 16) ADVANCED PERIPHERALS TECHNOLOGIES, INC. - - KOJIMA BUILDING, 1031 FUJISAWA - FUJISAWA-SHI, KANAGAWA-KEN 251 - JAPAN - - 00-A0-7B (hex) DAWN COMPUTER INCORPORATION - 00A07B (base 16) DAWN COMPUTER INCORPORATION - 6 KEXUEYUAN SOUTH ROAD - ZHONG GUAN CUN BEIJING 100080 - CHINA - - 00-A0-7C (hex) TONYANG NYLON CO., LTD. - 00A07C (base 16) TONYANG NYLON CO., LTD. - ELECTRONIC RESEARCH LAB - 183, HOGE-DONG, DONGAN-GU - ANYANG-CITY, KYUNGKI-DO 430-080 - KOREA, REPUBLIC OF - - 00-A0-7D (hex) SEEQ TECHNOLOGY, INC. - 00A07D (base 16) SEEQ TECHNOLOGY, INC. - 47131 BAYSIDE PARKWAY - FREMONT CA 94538 - UNITED STATES - - 00-A0-7E (hex) AVID TECHNOLOGY, INC. - 00A07E (base 16) AVID TECHNOLOGY, INC. - METROPOLITAN TECHNOLOGY PARK - ONE PARK WEST - TEWKSBURY MA 01876 - UNITED STATES - - 00-A0-7F (hex) GSM-SYNTEL, LTD. - 00A07F (base 16) GSM-SYNTEL, LTD. - VICTORIA WORKS, QUEENS MILL RD - HUDDERSFIELD WEST YORKSHIRE - HD1 3PG ENGLAND - UNITED KINGDOM - - 00-A0-80 (hex) Tattile SRL - 00A080 (base 16) Tattile SRL - 4000 Executive Parkway - Suite 200 - San Ramon CA 94583 - UNITED STATES - - 00-A0-81 (hex) ALCATEL DATA NETWORKS - 00A081 (base 16) ALCATEL DATA NETWORKS - 12502 SUNRISE VALLEY DRIVE - RESTON VA 22096 - UNITED STATES - - 00-A0-82 (hex) NKT ELEKTRONIK A/S - 00A082 (base 16) NKT ELEKTRONIK A/S - NKT ALLE 85 - DK-2605 BRONDBY - DENMARK - - 00-A0-83 (hex) ASIMMPHONY TURKEY - 00A083 (base 16) ASIMMPHONY TURKEY - ELECTRONICS, LTD. - #160.260 - 6651 ELMBRIDGE WAY RICHMOND B - V7C 4N1 - CANADA - - 00-A0-84 (hex) Dataplex Pty Ltd - 00A084 (base 16) Dataplex Pty Ltd - Ground floor, - 101 Waterloo Rd - MACQUARIE PARK NSW 2113 - AUSTRALIA - - 00-A0-85 (hex) PRIVATE - 00A085 (base 16) - - 00-A0-86 (hex) AMBER WAVE SYSTEMS, INC. - 00A086 (base 16) AMBER WAVE SYSTEMS, INC. - 403 MASSACHUSETTS AVENUE - SUITE #202 - ACTON MA 01720 - UNITED STATES - - 00-A0-87 (hex) Microsemi Corporation - 00A087 (base 16) Microsemi Corporation - 400 March Road - Ottawa - Ontario K2K 3H4 - CANADA - - 00-A0-88 (hex) ESSENTIAL COMMUNICATIONS - 00A088 (base 16) ESSENTIAL COMMUNICATIONS - 4374 ALEXANDER BLVD. NE-STE - ALBUQUERQUE NM 87107 - UNITED STATES - - 00-A0-89 (hex) XPOINT TECHNOLOGIES, INC. - 00A089 (base 16) XPOINT TECHNOLOGIES, INC. - 902 CLINT MOORE RD.-STE#132 - BOCA RATON FL 33487 - UNITED STATES - - 00-A0-8A (hex) BROOKTROUT TECHNOLOGY, INC. - 00A08A (base 16) BROOKTROUT TECHNOLOGY, INC. - 144 GOULD STREET- SUITE #200 - NEEDHAM MA 02194 - UNITED STATES - - 00-A0-8B (hex) ASTON ELECTRONIC DESIGNS LTD. - 00A08B (base 16) ASTON ELECTRONIC DESIGNS LTD. - 123/127 DEEPCUT BRIDGE ROAD - DEEPCUT, CAMBERLEY SURREY, GU16 6SD - ENGLAND - UNITED KINGDOM - - 00-A0-8C (hex) MultiMedia LANs, Inc. - 00A08C (base 16) MultiMedia LANs, Inc. - 5600 EXECUTIVE CENTER DRIVE - SUITE #312 - CHARLOTTE NC 28212 - UNITED STATES - - 00-A0-8D (hex) JACOMO CORPORATION - 00A08D (base 16) JACOMO CORPORATION - 26900 E. PINK HILL ROAD - INDEPENDENCE MO 64057 - UNITED STATES - - 00-A0-8E (hex) Check Point Software Technologies - 00A08E (base 16) Check Point Software Technologies - 8333 Ridgepoint Dr. - Suite 150 - Irving TX 75063 - UNITED STATES - - 00-A0-8F (hex) DESKNET SYSTEMS, INC. - 00A08F (base 16) DESKNET SYSTEMS, INC. - 80 BUSINESS PARK DRIVE - ARMONK NY 10504 - UNITED STATES - - 00-A0-90 (hex) TimeStep Corporation - 00A090 (base 16) TimeStep Corporation - 359 TERRY FOX DRIVE - KANATA, ONTARIO K2K 2E7 - CANADA - - 00-A0-91 (hex) APPLICOM INTERNATIONAL - 00A091 (base 16) APPLICOM INTERNATIONAL - 43, RUE MAZAGRAN - 76320 CAUDEBEC-LES-ELBEUF - FRANCE - - 00-A0-92 (hex) H. BOLLMANN MANUFACTURERS, LTD - 00A092 (base 16) H. BOLLMANN MANUFACTURERS, LTD - 26 VICTORIA WAY - BURGESS HILL W. SUSSEX RH 15 9NF - ENGLAND - UNITED KINGDOM - - 00-A0-93 (hex) B/E AEROSPACE, Inc. - 00A093 (base 16) B/E AEROSPACE, Inc. - 17481 RED HILL - IRVINE CA 92714-5630 - UNITED STATES - - 00-A0-94 (hex) COMSAT CORPORATION - 00A094 (base 16) COMSAT CORPORATION - 22300 COMSAT DRIVE - CLARKSBURG MD 20871-9475 - UNITED STATES - - 00-A0-95 (hex) ACACIA NETWORKS, INC. - 00A095 (base 16) ACACIA NETWORKS, INC. - 831 WOBURN STREET - WILMINGTON MA 01887 - UNITED STATES - - 00-A0-96 (hex) MITSUMI ELECTRIC CO., LTD. - 00A096 (base 16) MITSUMI ELECTRIC CO., LTD. - 2-11-2, Tsurumaki - Tama-shi Tokyo 206-8567 - JAPAN - - 00-A0-97 (hex) JC INFORMATION SYSTEMS - 00A097 (base 16) JC INFORMATION SYSTEMS - 4487 TECHNOLOGY DRIVE - FREMONT CA 94538-6343 - UNITED STATES - - 00-A0-98 (hex) NetApp - 00A098 (base 16) NetApp - 495 East Java Drive - Sunnyvale, CA 94089 - UNITED STATES - - 00-A0-99 (hex) K-NET LTD. - 00A099 (base 16) K-NET LTD. - SADDLERS HOUSE - 100 READING RD. - YATELEY, SURREY GU17 7RX - UNITED KINGDOM - - 00-A0-9A (hex) NIHON KOHDEN AMERICA - 00A09A (base 16) NIHON KOHDEN AMERICA - 2446 DUPONT DRIVE - IRVINE CA 92715 - UNITED STATES - - 00-A0-9B (hex) QPSX COMMUNICATIONS, LTD. - 00A09B (base 16) QPSX COMMUNICATIONS, LTD. - 33 RICHARDSON STREET - WEST PERTH 6005 - AUSTRALIA - - 00-A0-9C (hex) Xyplex, Inc. - 00A09C (base 16) Xyplex, Inc. - 25 FOSTER STREET - LITTLETON MA 01460 - UNITED STATES - - 00-A0-9D (hex) JOHNATHON FREEMAN TECHNOLOGIES - 00A09D (base 16) JOHNATHON FREEMAN TECHNOLOGIES - P.O. BOX 880114 - SAN FRANCISCO CA 94188 - UNITED STATES - - 00-A0-9E (hex) ICTV - 00A09E (base 16) ICTV - 14600 WINCHESTER BLVD. - LOS GATOS CA 95030 - UNITED STATES - - 00-A0-9F (hex) COMMVISION CORP. - 00A09F (base 16) COMMVISION CORP. - 510 LOGUE AVE. - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-A0-A0 (hex) COMPACT DATA, LTD. - 00A0A0 (base 16) COMPACT DATA, LTD. - 58 DITTON WALK - CAMBRIDGE CB5 8QE - UNITED KINGDOM - - 00-A0-A1 (hex) EPIC DATA INC. - 00A0A1 (base 16) EPIC DATA INC. - 7280 RIVER ROAD - RICHMOND, B.C. - CANADA V6X 1X5 - CANADA - - 00-A0-A2 (hex) DIGICOM S.P.A. - 00A0A2 (base 16) DIGICOM S.P.A. - VIA VOLTA 39 - 21010 CARDANO AL CAMPO (VA) - ITALY - - 00-A0-A3 (hex) RELIABLE POWER METERS - 00A0A3 (base 16) RELIABLE POWER METERS - 400 BLOSSOM HILL ROAD - LOS GATOS CA 95032-4511 - UNITED STATES - - 00-A0-A4 (hex) MICROS SYSTEMS, INC. - 00A0A4 (base 16) MICROS SYSTEMS, INC. - 12000 BALTIMORE AVENUE - BELTSVILLE MD 20705 - UNITED STATES - - 00-A0-A5 (hex) TEKNOR MICROSYSTEME, INC. - 00A0A5 (base 16) TEKNOR MICROSYSTEME, INC. - 616 CURE BOIVIN - BOISBRIAND QUEBEC - J7G 2A7 - CANADA - - 00-A0-A6 (hex) M.I. SYSTEMS, K.K. - 00A0A6 (base 16) M.I. SYSTEMS, K.K. - 2-7-12-308 Satsukigaoka - Ikeda-Shi Osaka 563-0029 - JAPAN - - 00-A0-A7 (hex) VORAX CORPORATION - 00A0A7 (base 16) VORAX CORPORATION - 1031 EAST DUANE AVENUE, STE H - SUNNYVALE CA 94086 - UNITED STATES - - 00-A0-A8 (hex) RENEX CORPORATION - 00A0A8 (base 16) RENEX CORPORATION - 2750 KILLARNEY DRIVE - WOODBRIDGE VA 22192 - UNITED STATES - - 00-A0-A9 (hex) NAVTEL COMMUNICATIONS INC. - 00A0A9 (base 16) NAVTEL COMMUNICATIONS INC. - 55 RENFREW DRIVE - MARKHAM, ONTARIO L3R 8H3 - CANADA - - 00-A0-AA (hex) SPACELABS MEDICAL - 00A0AA (base 16) SPACELABS MEDICAL - 5150 220 Ave SE - Issaquah WA 98027 - UNITED STATES - - 00-A0-AB (hex) NETCS INFORMATIONSTECHNIK GMBH - 00A0AB (base 16) NETCS INFORMATIONSTECHNIK GMBH - KATHARINENSTRASSE 17-18 - D-10711 BERLIN, - GERMANY - - 00-A0-AC (hex) GILAT SATELLITE NETWORKS, LTD. - 00A0AC (base 16) GILAT SATELLITE NETWORKS, LTD. - 24A HABARZEL STREET - TEL AVIV 69710 - ISRAEL - - 00-A0-AD (hex) MARCONI SPA - 00A0AD (base 16) MARCONI SPA - VIA NEGRONE, 1A - 16153 GENOVA CORNIGLIANO - ITALY - - 00-A0-AE (hex) NUCOM SYSTEMS, INC. - 00A0AE (base 16) NUCOM SYSTEMS, INC. - 9F-6, NO 4, LANE - 609 CHUNG HSIN ROAD, SEC. 5, SAN CHUNG C - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-A0-AF (hex) WMS INDUSTRIES - 00A0AF (base 16) WMS INDUSTRIES - 3401 N. CALIFORNIA - CHICAGO IL 60618 - UNITED STATES - - 00-A0-B0 (hex) I-O DATA DEVICE, INC. - 00A0B0 (base 16) I-O DATA DEVICE, INC. - 24-1, SAKURADA-MACHI - KANAZAWA, ISHIKAWA 920 - JAPAN - - 00-A0-B1 (hex) FIRST VIRTUAL CORPORATION - 00A0B1 (base 16) FIRST VIRTUAL CORPORATION - 3393 OCTAVIUS DR.-STE.# 102 - SANTA CLARA CA 95054 - UNITED STATES - - 00-A0-B2 (hex) SHIMA SEIKI - 00A0B2 (base 16) SHIMA SEIKI - 85, SAKATA WAKAYAMA-CITY - WAKAYAMA 641 - JAPAN - - 00-A0-B3 (hex) ZYKRONIX - 00A0B3 (base 16) ZYKRONIX - 7248 SOUTH TUCSON WAY - ENGLEWOOD CO 80112 - UNITED STATES - - 00-A0-B4 (hex) TEXAS MICROSYSTEMS, INC. - 00A0B4 (base 16) TEXAS MICROSYSTEMS, INC. - 5959 CORPORATE DRIVE - HOUSTON TX 77036 - UNITED STATES - - 00-A0-B5 (hex) 3H TECHNOLOGY - 00A0B5 (base 16) 3H TECHNOLOGY - 3375 SCOTT BLVD. #336 - SANTA CLARA CA 95054 - UNITED STATES - - 00-A0-B6 (hex) SANRITZ AUTOMATION CO., LTD. - 00A0B6 (base 16) SANRITZ AUTOMATION CO., LTD. - 4-21 MINAMI NARUSE - MACHIDA CITY TOKYO 194 - JAPAN - - 00-A0-B7 (hex) CORDANT, INC. - 00A0B7 (base 16) CORDANT, INC. - 11400 COMMERCE PARK DR. - RESTON VA 22091-1506 - UNITED STATES - - 00-A0-B8 (hex) SYMBIOS LOGIC INC. - 00A0B8 (base 16) SYMBIOS LOGIC INC. - 2001 Danfield Ct. - Fort Collins CO 80525 - UNITED STATES - - 00-A0-B9 (hex) EAGLE TECHNOLOGY, INC. - 00A0B9 (base 16) EAGLE TECHNOLOGY, INC. - 6800 ORANGETHORPE AVE., UNIT A - BUENA PARK CA 90620 - UNITED STATES - - 00-A0-BA (hex) PATTON ELECTRONICS CO. - 00A0BA (base 16) PATTON ELECTRONICS CO. - 7622 RICKENBACKER DRIVE - GAITHERSBURG MD 20879 - UNITED STATES - - 00-A0-BB (hex) HILAN GMBH - 00A0BB (base 16) HILAN GMBH - HAID-UND-NEU-STRASSE 7 - D-76131 KARLSRUHE - GERMANY - - 00-A0-BC (hex) VIASAT, INCORPORATED - 00A0BC (base 16) VIASAT, INCORPORATED - 6155 El Camino Real - Carlsbad Ca 92009 - UNITED STATES - - 00-A0-BD (hex) I-TECH CORP. - 00A0BD (base 16) I-TECH CORP. - 10200 VALLEY VIEW ROAD - EDEN PRAIRIE MN 55344 - UNITED STATES - - 00-A0-BE (hex) INTEGRATED CIRCUIT SYSTEMS, INC. COMMUNICATIONS GROUP - 00A0BE (base 16) INTEGRATED CIRCUIT SYSTEMS, INC. COMMUNICATIONS GROUP - 1271 PARKMOOR AVENUE - SAN JOSE CA 95126-3448 - UNITED STATES - - 00-A0-BF (hex) WIRELESS DATA GROUP MOTOROLA - 00A0BF (base 16) WIRELESS DATA GROUP MOTOROLA - 1201 E. WILEY ROAD - SCHAUMBURG IL 60173 - UNITED STATES - - 00-A0-C0 (hex) DIGITAL LINK CORP. - 00A0C0 (base 16) DIGITAL LINK CORP. - 217 HUMBOLDT COURT - SUNNYVALE CA 94089 - UNITED STATES - - 00-A0-C1 (hex) ORTIVUS MEDICAL AB - 00A0C1 (base 16) ORTIVUS MEDICAL AB - BOX 513 - S-18325 TABY - SWEDEN - - 00-A0-C2 (hex) R.A. SYSTEMS CO., LTD. - 00A0C2 (base 16) R.A. SYSTEMS CO., LTD. - 1850-3 HIROOKANOMURA - SHIOJIRI-SHI, NAGAMO 399-07 - JAPAN - - 00-A0-C3 (hex) UNICOMPUTER GMBH - 00A0C3 (base 16) UNICOMPUTER GMBH - LIMBURGER STRASSE 48 - D-61476 KRONBERG I.T.S. - GERMANY - - 00-A0-C4 (hex) CRISTIE ELECTRONICS LTD. - 00A0C4 (base 16) CRISTIE ELECTRONICS LTD. - BOND'S MILL - STONEHOUSE - GLOUCESTERSHIRE GL10 3RG - UNITED KINGDOM - - 00-A0-C5 (hex) ZYXEL COMMUNICATION - 00A0C5 (base 16) ZYXEL COMMUNICATION - 2ND FLR., 58 PARK AVENUE II - SCIENCE BASED INDUSTRIAL PARK - HSINCHU 30077 - TAIWAN, PROVINCE OF CHINA - - 00-A0-C6 (hex) QUALCOMM INCORPORATED - 00A0C6 (base 16) QUALCOMM INCORPORATED - 5775 Morehouse Dr - San Diego CA 92121 - UNITED STATES - - 00-A0-C7 (hex) TADIRAN TELECOMMUNICATIONS - 00A0C7 (base 16) TADIRAN TELECOMMUNICATIONS - P.O. BOX 500 - PETAH-TIKVA 49104 - ISRAEL - - 00-A0-C8 (hex) ADTRAN INC. - 00A0C8 (base 16) ADTRAN INC. - 901 EXPLORER BLVD. - HUNTSVILLE AL 35806-2807 - UNITED STATES - - 00-A0-C9 (hex) INTEL CORPORATION - HF1-06 - 00A0C9 (base 16) INTEL CORPORATION - HF1-06 - 5200 NE ELAM YOUNG PARKWAY - HILLSBORO OR 97124 - UNITED STATES - - 00-A0-CA (hex) FUJITSU DENSO LTD. - 00A0CA (base 16) FUJITSU DENSO LTD. - 3055 ORCHARD DRIVE - SAN JOSE CA 95134 - UNITED STATES - - 00-A0-CB (hex) ARK TELECOMMUNICATIONS, INC. - 00A0CB (base 16) ARK TELECOMMUNICATIONS, INC. - 124 CARMEN LANE--SUITE - SANTA MARIA CA 93454 - UNITED STATES - - 00-A0-CC (hex) LITE-ON COMMUNICATIONS, INC. - 00A0CC (base 16) LITE-ON COMMUNICATIONS, INC. - 720 S. HILLVIEW DRIVE - MILPITAS CA 95035 - UNITED STATES - - 00-A0-CD (hex) DR. JOHANNES HEIDENHAIN GmbH - 00A0CD (base 16) DR. JOHANNES HEIDENHAIN GmbH - DR.-JOHANNES-HEIDENHAIN STR. - 83301 TRAUNREUT - GERMANY - - 00-A0-CE (hex) Ecessa - 00A0CE (base 16) Ecessa - 2800 Campus Drive - Suite 140 - Plymouth MN 55441 - UNITED STATES - - 00-A0-CF (hex) SOTAS, INC. - 00A0CF (base 16) SOTAS, INC. - 2 RESEARCH PLACE, STE. - ROCKVILLE MD 20850 - UNITED STATES - - 00-A0-D0 (hex) TEN X TECHNOLOGY, INC. - 00A0D0 (base 16) TEN X TECHNOLOGY, INC. - 13091 POND SPRINGS ROAD, Suite B-200 - AUSTIN TX 78729 - UNITED STATES - - 00-A0-D1 (hex) INVENTEC CORPORATION - 00A0D1 (base 16) INVENTEC CORPORATION - INVENTEC BUILDING - 66 HOU-KANG STREET SHI-LIN DISTRICT, TAI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-A0-D2 (hex) ALLIED TELESIS INTERNATIONAL CORPORATION - 00A0D2 (base 16) ALLIED TELESIS INTERNATIONAL CORPORATION - 950 KIFER ROAD - SUNNYVALE CA 94086 - UNITED STATES - - 00-A0-D3 (hex) INSTEM COMPUTER SYSTEMS, LTD. - 00A0D3 (base 16) INSTEM COMPUTER SYSTEMS, LTD. - WALTON INDUSTRIAL ESTATE - STONE, STAFFORDSHIRE ST15 OLT - UNITED KINGDOM - - 00-A0-D4 (hex) RADIOLAN, INC. - 00A0D4 (base 16) RADIOLAN, INC. - 454 DEGUIGNE DRIVE - STE - SUNNYVALE CA 94086 - UNITED STATES - - 00-A0-D5 (hex) SIERRA WIRELESS INC. - 00A0D5 (base 16) SIERRA WIRELESS INC. - 13811 Wireless Way - RICHMOND B.C. V6V 3A4 - CANADA - - 00-A0-D6 (hex) SBE, INC. - 00A0D6 (base 16) SBE, INC. - 2305 Camino Ramon - SAN RAMON CA 94583 - UNITED STATES - - 00-A0-D7 (hex) KASTEN CHASE APPLIED RESEARCH - 00A0D7 (base 16) KASTEN CHASE APPLIED RESEARCH - 5100 ORBITOR DRIVE - MISSISSAUGA, ONTARIO - L4W 4Z4 - CANADA - - 00-A0-D8 (hex) SPECTRA - TEK - 00A0D8 (base 16) SPECTRA - TEK - OUTGANG LANE - PICKERING NORTH YORKSHIRE - ENGLAND Y018 FJA - UNITED KINGDOM - - 00-A0-D9 (hex) CONVEX COMPUTER CORPORATION - 00A0D9 (base 16) CONVEX COMPUTER CORPORATION - 3000 WATERVIEW PARKWAY - P.O. BOX 833851 - RICHARDSON TX 75083-3851 - UNITED STATES - - 00-A0-DA (hex) INTEGRATED SYSTEMS Technology, Inc. - 00A0DA (base 16) INTEGRATED SYSTEMS Technology, Inc. - 4601 PRESIDENTS DRIVE - SUITE #210 - LANHAM MD 20706 - UNITED STATES - - 00-A0-DB (hex) FISHER & PAYKEL PRODUCTION - 00A0DB (base 16) FISHER & PAYKEL PRODUCTION - MACHINERY LIMITED - P.O. BOX 58-223, GREENMOUNT AUCKLAND - NEW ZEALAND - - 00-A0-DC (hex) O.N. ELECTRONIC CO., LTD. - 00A0DC (base 16) O.N. ELECTRONIC CO., LTD. - 3-20-27, TARUMI - SUITA, OSAKA 564 - JAPAN - - 00-A0-DD (hex) AZONIX CORPORATION - 00A0DD (base 16) AZONIX CORPORATION - 900 MIDDLESEX TURNPIKE - BLDG. - BILLERICA MA 01821 - UNITED STATES - - 00-A0-DE (hex) YAMAHA CORPORATION - 00A0DE (base 16) YAMAHA CORPORATION - ELECTRONIC DEVICES DIVISION - 203 MATSUNOKIJIMA TOYOOKA-MURA IWATA-GUN - 438-01 - JAPAN - - 00-A0-DF (hex) STS TECHNOLOGIES, INC. - 00A0DF (base 16) STS TECHNOLOGIES, INC. - 13765 ST. CHARLES ROCK RD. - SUITE #108 - BRIDGETON MO 63044 - UNITED STATES - - 00-A0-E0 (hex) TENNYSON TECHNOLOGIES PTY LTD - 00A0E0 (base 16) TENNYSON TECHNOLOGIES PTY LTD - 14 BUSINESS PARK DRIVE - NOTTING HILL - VICTORIA - 3168 - AUSTRALIA - - 00-A0-E1 (hex) WESTPORT RESEARCH ASSOCIATES, INC. - 00A0E1 (base 16) WESTPORT RESEARCH ASSOCIATES, INC. - 6102 ARLINGTON - RAYTOWN MO 64133 - UNITED STATES - - 00-A0-E2 (hex) Keisokugiken Corporation - 00A0E2 (base 16) Keisokugiken Corporation - 2021-5 Houshakuji - Takanezawa-machi - Shioya-gun Tochigi 329-1233 - JAPAN - - 00-A0-E3 (hex) XKL SYSTEMS CORP. - 00A0E3 (base 16) XKL SYSTEMS CORP. - 8420 154TH AVE. NE - REDMOND WA 98052 - UNITED STATES - - 00-A0-E4 (hex) OPTIQUEST - 00A0E4 (base 16) OPTIQUEST - 20490 BUSINESS PARKWAY - WALNUT CA 91789 - UNITED STATES - - 00-A0-E5 (hex) NHC COMMUNICATIONS - 00A0E5 (base 16) NHC COMMUNICATIONS - 5450 COTE DE LIESSE - MONTREAL, QUEBEC H4P 1A5 - CANADA - - 00-A0-E6 (hex) DIALOGIC CORPORATION - 00A0E6 (base 16) DIALOGIC CORPORATION - 1515 ROUTE 10 - PARSIPPANY NJ 07054 - UNITED STATES - - 00-A0-E7 (hex) CENTRAL DATA CORPORATION - 00A0E7 (base 16) CENTRAL DATA CORPORATION - 1602 NEWTON DRIVE - CHAMPAIGN IL 61821 - UNITED STATES - - 00-A0-E8 (hex) REUTERS HOLDINGS PLC - 00A0E8 (base 16) REUTERS HOLDINGS PLC - 85, FLEET STREET - LONDON EC4P 4AJ - ENGLAND - UNITED KINGDOM - - 00-A0-E9 (hex) ELECTRONIC RETAILING SYSTEMS INTERNATIONAL - 00A0E9 (base 16) ELECTRONIC RETAILING SYSTEMS INTERNATIONAL - 372 DANBURY ROAD - WILTON CT 06897-2523 - UNITED STATES - - 00-A0-EA (hex) ETHERCOM CORP. - 00A0EA (base 16) ETHERCOM CORP. - 45990 HOTCHKISS ST. - FREEMONT CA 94539 - UNITED STATES - - 00-A0-EB (hex) Encore Networks, Inc. - 00A0EB (base 16) Encore Networks, Inc. - 3800 Concorde Parkway, - Suite 1500 - Chantilly, VA 20151 - UNITED STATES - - 00-A0-EC (hex) TRANSMITTON LTD. - 00A0EC (base 16) TRANSMITTON LTD. - SMISBY ROAD - ASHBY DE LA ZOUCH - LEICESTERSHIRE LE65 2UG - UNITED KINGDOM - - 00-A0-ED (hex) Brooks Automation, Inc. - 00A0ED (base 16) Brooks Automation, Inc. - 15 Elizabeth Drive - Chelmsford MA 01824 - UNITED STATES - - 00-A0-EE (hex) NASHOBA NETWORKS - 00A0EE (base 16) NASHOBA NETWORKS - 9-11 GOLDSMITH ST. - LITTLETON MA 01460 - UNITED STATES - - 00-A0-EF (hex) LUCIDATA LTD. - 00A0EF (base 16) LUCIDATA LTD. - LUCIDATA HOUSE - SELWYN CLOSE, - GREAT SHELFORD CAMBRIDGE CB2 5HA - UNITED KINGDOM - - 00-A0-F0 (hex) TORONTO MICROELECTRONICS INC. - 00A0F0 (base 16) TORONTO MICROELECTRONICS INC. - 5149 BRADCO BOULEVARD - MISSISSAUGA, ONTARIO - L4W 2A6 - CANADA - - 00-A0-F1 (hex) MTI - 00A0F1 (base 16) MTI - 4905 E. LA PALMA AVENUE - ANAHEIM CA 92807 - UNITED STATES - - 00-A0-F2 (hex) INFOTEK COMMUNICATIONS, INC. - 00A0F2 (base 16) INFOTEK COMMUNICATIONS, INC. - 111 ANZA BLVD., #203 - BURLINGAME CA 94010 - UNITED STATES - - 00-A0-F3 (hex) STAUBLI - 00A0F3 (base 16) STAUBLI - 183 RUE DES USINES - BP 70 F74210 FAVERGES - FRANCE - - 00-A0-F4 (hex) GE - 00A0F4 (base 16) GE - W-657 - 3000 N. GRANDVIEW BLVD. - WAUKESHA WI 53188 - UNITED STATES - - 00-A0-F5 (hex) RADGUARD LTD. - 00A0F5 (base 16) RADGUARD LTD. - 8 HANECHOSHET STREET - TEL-AVIV 69710 - ISRAEL - - 00-A0-F6 (hex) AutoGas Systems Inc. - 00A0F6 (base 16) AutoGas Systems Inc. - P.O. BOX 6957 - ABIOLENE TX 79608 - UNITED STATES - - 00-A0-F7 (hex) V.I COMPUTER CORP. - 00A0F7 (base 16) V.I COMPUTER CORP. - 531 ENCINITAS BLVD--#114 - ENCINITAS CA 92024 - UNITED STATES - - 00-A0-F8 (hex) Zebra Technologies Inc - 00A0F8 (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - 00-A0-F9 (hex) BINTEC COMMUNICATIONS GMBH - 00A0F9 (base 16) BINTEC COMMUNICATIONS GMBH - SUEDWESTPARK 94 - 90449 NUERNBERG - GERMANY - - 00-A0-FA (hex) Marconi Communication GmbH - 00A0FA (base 16) Marconi Communication GmbH - Gerberstrasse 33 - D-71522 Bacnknang - GERMANY - - 00-A0-FB (hex) TORAY ENGINEERING CO., LTD. - 00A0FB (base 16) TORAY ENGINEERING CO., LTD. - 1-45, OE 1-CHOME, OTSU CITY - SHIGA, - 520-21 - JAPAN - - 00-A0-FC (hex) IMAGE SCIENCES, INC. - 00A0FC (base 16) IMAGE SCIENCES, INC. - 7500 INNOVATION WAY - MASON OH 45040 - UNITED STATES - - 00-A0-FD (hex) SCITEX DIGITAL PRINTING, INC. - 00A0FD (base 16) SCITEX DIGITAL PRINTING, INC. - 3100 RESEARCH BLVD. - DAYTON OH 45420 - UNITED STATES - - 00-A0-FE (hex) BOSTON TECHNOLOGY, INC. - 00A0FE (base 16) BOSTON TECHNOLOGY, INC. - 100 QUANNAPOWITT PARKWAY - WAKEFIELD MA 01880 - UNITED STATES - - 00-A0-FF (hex) TELLABS OPERATIONS, INC. - 00A0FF (base 16) TELLABS OPERATIONS, INC. - 1000 REMINGTON BLVD. - BOLINGBROOK IL 60440 - 60440 - UNITED STATES - - 00-A1-DE (hex) ShenZhen ShiHua Technology CO.,LTD - 00A1DE (base 16) ShenZhen ShiHua Technology CO.,LTD - Room505,5/F TsingYi Building,LangShan 2ed Road,High-Tech Industrial Park, - ShenZhen GuangDong 518052 - CHINA - - 00-A2-DA (hex) INAT GmbH - 00A2DA (base 16) INAT GmbH - Ostendstraße 50A - Nuremberg Bavaria 90482 - GERMANY - - 00-A2-F5 (hex) Guangzhou Yuanyun Network Technology Co.,Ltd - 00A2F5 (base 16) Guangzhou Yuanyun Network Technology Co.,Ltd - 31/F,183 TianHe Bei Rd, Metro Plz - TianHe District, GuangZhou City - GuangZhou GuangDong 510630 - CHINA - - 00-A2-FF (hex) abatec group AG - 00A2FF (base 16) abatec group AG - Oberregauerstraße 48 - Regau 4844 - AUSTRIA - - 00-A5-09 (hex) WigWag Inc. - 00A509 (base 16) WigWag Inc. - 4009 banister lane - suite 200 - austin texas 78704 - UNITED STATES - - 00-A7-84 (hex) ITX security - 00A784 (base 16) ITX security - 9F Kolon Digital Tower Aston Bldg - Gasandigital 1-ro Geumcheon-gu - SEOUL (Outside US/Canada/China) 441-813 - KOREA, REPUBLIC OF - - 00-AA-00 (hex) INTEL CORPORATION - 00AA00 (base 16) INTEL CORPORATION - 5200 NE ELAM YOUNG PARKWAY - HILLSBORO OR 97124 - UNITED STATES - - 00-AA-01 (hex) INTEL CORPORATION - 00AA01 (base 16) INTEL CORPORATION - - UNITED STATES - - 00-AA-02 (hex) INTEL CORPORATION - 00AA02 (base 16) INTEL CORPORATION - - UNITED STATES - - 00-AA-3C (hex) OLIVETTI TELECOM SPA (OLTECO) - 00AA3C (base 16) OLIVETTI TELECOM SPA (OLTECO) - 10062 MILLER AVE.-STE.#204 - CUPERTINO CA 95014 - UNITED STATES - - 00-AA-70 (hex) LG Electronics - 00AA70 (base 16) LG Electronics - 60-39, Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 00-AC-E0 (hex) ARRIS Group, Inc. - 00ACE0 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 00-AE-FA (hex) Murata Manufacturing Co., Ltd. - 00AEFA (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 00-B0-09 (hex) Grass Valley Group - 00B009 (base 16) Grass Valley Group - P.O. Box 599000 - Nevada City CA 95959-7900 - UNITED STATES - - 00-B0-17 (hex) InfoGear Technology Corp. - 00B017 (base 16) InfoGear Technology Corp. - 2055 Woodside Road - Redwood City CA 94061 - UNITED STATES - - 00-B0-19 (hex) UTC CCS - 00B019 (base 16) UTC CCS - 791 Commerce Blvd - Suite 100 - Boca Raton FL 33497 - UNITED STATES - - 00-B0-1C (hex) Westport Technologies - 00B01C (base 16) Westport Technologies - 15 Capella Court, Unit 116 - Nepean Ontario - CANADA - - 00-B0-1E (hex) Rantic Labs, Inc. - 00B01E (base 16) Rantic Labs, Inc. - 702 Brazos, Suite #500 - Austin TX 78701 - UNITED STATES - - 00-B0-2A (hex) ORSYS GmbH - 00B02A (base 16) ORSYS GmbH - Am Stadtgraben 25 - D-88677 Markdorf - GERMANY - - 00-B0-2D (hex) ViaGate Technologies, Inc. - 00B02D (base 16) ViaGate Technologies, Inc. - 745 Route 202/206 - Suite 5 - Bridgewater NJ 08807 - UNITED STATES - - 00-B0-33 (hex) OAO "Izhevskiy radiozavod" - 00B033 (base 16) OAO "Izhevskiy radiozavod" - 19 Bazisnaya street - Izhevsk Udmurt Republic 426034 - RUSSIAN FEDERATION - - 00-B0-3B (hex) HiQ Networks - 00B03B (base 16) HiQ Networks - 2475 Augustine Drive - Santa Clara CA 95054 - UNITED STATES - - 00-B0-48 (hex) Marconi Communications Inc. - 00B048 (base 16) Marconi Communications Inc. - 8616 Freeport Parkway - MS A2 - Irving TX 75063 - UNITED STATES - - 00-B0-4A (hex) CISCO SYSTEMS, INC. - 00B04A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-B0-52 (hex) Atheros Communications - 00B052 (base 16) Atheros Communications - 5955 T.G. Lee Blvd, Ste. 600 - Ocala FL 32822 - UNITED STATES - - 00-B0-64 (hex) CISCO SYSTEMS, INC. - 00B064 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-B0-69 (hex) Honewell Oy - 00B069 (base 16) Honewell Oy - P.O. Box 168, FIN-78201 - Varkaus - FINLAND - - 00-B0-6D (hex) Jones Futurex Inc. - 00B06D (base 16) Jones Futurex Inc. - 3715 Atherton Road - Rocklin CA 95765 - UNITED STATES - - 00-B0-80 (hex) Mannesmann Ipulsys B.V. - 00B080 (base 16) Mannesmann Ipulsys B.V. - Bordewijklaan 18 - 2591 XR The Hague - NETHERLANDS - - 00-B0-86 (hex) LocSoft Limited - 00B086 (base 16) LocSoft Limited - 7 Bright Street - Clitheroe Lancashire BB7 1NW - UNITED KINGDOM - - 00-B0-8E (hex) CISCO SYSTEMS, INC. - 00B08E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-B0-91 (hex) Transmeta Corp. - 00B091 (base 16) Transmeta Corp. - 3940 Freedom Circle - Santa Clara CA 95054 - UNITED STATES - - 00-B0-94 (hex) Alaris, Inc. - 00B094 (base 16) Alaris, Inc. - 47338 Fremont Boulevard - Fremont CA 94538 - UNITED STATES - - 00-B0-9A (hex) Morrow Technologies Corp. - 00B09A (base 16) Morrow Technologies Corp. - 2300 Tall Pines Drive - Largo FL 33771-5342 - UNITED STATES - - 00-B0-9D (hex) Point Grey Research Inc. - 00B09D (base 16) Point Grey Research Inc. - 305-1847 West Broadway - Vancouver British Columbia V6J 1Y6 - CANADA - - 00-B0-AC (hex) SIAE-Microelettronica S.p.A. - 00B0AC (base 16) SIAE-Microelettronica S.p.A. - Via Michelangelo Buonarroti, 21 - 20093 Cologno M. (Ml) - ITALY - - 00-B0-AE (hex) Symmetricom - 00B0AE (base 16) Symmetricom - 2300 Orchard Parkway - San Jose CA 95131 - UNITED STATES - - 00-B0-B3 (hex) Xstreamis PLC - 00B0B3 (base 16) Xstreamis PLC - Magdalen Centre - Oxford Science Park - Oxford 0X4 4GA - UNITED KINGDOM - - 00-B0-C2 (hex) CISCO SYSTEMS, INC. - 00B0C2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-B0-C7 (hex) Tellabs Operations, Inc. - 00B0C7 (base 16) Tellabs Operations, Inc. - One Tellabs Center - 1415 West Diehl Road - Naperville IL 60563 - UNITED STATES - - 00-B0-CE (hex) TECHNOLOGY RESCUE - 00B0CE (base 16) TECHNOLOGY RESCUE - 46 Avenue des Speres Lumiere - 7819 Troppes - FRANCE - - 00-B0-D0 (hex) Dell Computer Corp. - 00B0D0 (base 16) Dell Computer Corp. - One Dell Way - Round Rock TX 78682 - UNITED STATES - - 00-B0-DB (hex) Nextcell, Inc. - 00B0DB (base 16) Nextcell, Inc. - 651 East 18th Street - Plano TX 75074 - UNITED STATES - - 00-B0-DF (hex) Starboard Storage Systems - 00B0DF (base 16) Starboard Storage Systems - 12303 Airport Way - Ste 230 - Broomfield Co 80021 - UNITED STATES - - 00-B0-E7 (hex) British Federal Ltd. - 00B0E7 (base 16) British Federal Ltd. - Castle Mill Works - Dudley DY1 4DA England - UNITED KINGDOM - - 00-B0-EC (hex) EACEM - 00B0EC (base 16) EACEM - Avenue Louise 140, Bte 6 - B-1050 BRUSSELS - BELGIUM - - 00-B0-EE (hex) Ajile Systems, Inc. - 00B0EE (base 16) Ajile Systems, Inc. - 920 Saratoga Ave. - Suite 104 - San Jose CA 95129 - UNITED STATES - - 00-B0-F0 (hex) CALY NETWORKS - 00B0F0 (base 16) CALY NETWORKS - 295 Santa Anna Court - Sunnyvale CA 94086 - UNITED STATES - - 00-B0-F5 (hex) NetWorth Technologies, Inc. - 00B0F5 (base 16) NetWorth Technologies, Inc. - 1000 Germantown Pike - ldg. J-1 - Plymouth Metting PA 19462 - UNITED STATES - - 00-B3-38 (hex) Kontron Design Manufacturing Services (M) Sdn. Bhd - 00B338 (base 16) Kontron Design Manufacturing Services (M) Sdn. Bhd - Plot 554, Lorong Perusahaan 4 - Prai Free Trade Zone - Prai Penang 13600 - MALAYSIA - - 00-B3-42 (hex) MacroSAN Technologies Co., Ltd. - 00B342 (base 16) MacroSAN Technologies Co., Ltd. - Room 102, No.2 Building - 301 Bin Xing Road,Binjiang District - Hangzhou Zhejiang 310052 - CHINA - - 00-B5-6D (hex) David Electronics Co., LTD. - 00B56D (base 16) David Electronics Co., LTD. - 9F, -2, No. 188, Sec. 3, Ta-Tung Rd., - Xizhi Dist., - New Taipei City, 22103 - TAIWAN, PROVINCE OF CHINA - - 00-B5-D6 (hex) Omnibit Inc. - 00B5D6 (base 16) Omnibit Inc. - 2-7-9, Soto-Kanda - Chiyoda-ku Tokyo 101-0021 - JAPAN - - 00-B7-8D (hex) Nanjing Shining Electric Automation Co., Ltd - 00B78D (base 16) Nanjing Shining Electric Automation Co., Ltd - NO.699,Laiyinda Road - Jiangning District - Nanjing Jiangsu 211100 - CHINA - - 00-B9-F6 (hex) Shenzhen Super Rich Electronics Co.,Ltd - 00B9F6 (base 16) Shenzhen Super Rich Electronics Co.,Ltd - RM.102,Shibida Building,No.55,Zhenhua Road,Shenzhen Futian District, - Shenzhen Guangdong 518031 - CHINA - - 00-BA-C0 (hex) Biometric Access Company - 00BAC0 (base 16) Biometric Access Company - 2555 North IH 35 - Round Rock Texas 78664 - UNITED STATES - - 00-BB-01 (hex) OCTOTHORPE CORP. - 00BB01 (base 16) OCTOTHORPE CORP. - 285 WEST GREEN STREET - PASADENA CA 91105 - UNITED STATES - - 00-BB-3A (hex) PRIVATE - 00BB3A (base 16) - - 00-BB-8E (hex) HME Co., Ltd. - 00BB8E (base 16) HME Co., Ltd. - No.200 , Liao Bei Str.,San Min Dist., - Kaohsiung 807 - TAIWAN, PROVINCE OF CHINA - - 00-BB-F0 (hex) UNGERMANN-BASS INC. - 00BBF0 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-BD-27 (hex) Exar Corp. - 00BD27 (base 16) Exar Corp. - 48720 Kato Rd. - Fremont CA 94538 - UNITED STATES - - 00-BD-3A (hex) Nokia Corporation - 00BD3A (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90570 - FINLAND - - 00-BF-15 (hex) Genetec Inc. - 00BF15 (base 16) Genetec Inc. - 2280 boul. Alfred-Nobel - Suite 400 - St,. Laurent Quebec H4S 2A4 - CANADA - - 00-C0-00 (hex) LANOPTICS, LTD. - 00C000 (base 16) LANOPTICS, LTD. - P.O. BOX 184 - MIGDAL HA-EMEK - ISRAEL ISRAEL 10551 - ISRAEL - - 00-C0-01 (hex) DIATEK PATIENT MANAGMENT - 00C001 (base 16) DIATEK PATIENT MANAGMENT - SYSTEMS, INC. - 5720 OBERLIN DRIVE - SAN DIEGO CA 92121-1723 - UNITED STATES - - 00-C0-02 (hex) SERCOMM CORPORATION - 00C002 (base 16) SERCOMM CORPORATION - 3F,NO.81,YU-YIH ROAD,CHU-NAN CHEN - MIAO-LIH HSUAN 350 - TAIWAN, PROVINCE OF CHINA - - 00-C0-03 (hex) GLOBALNET COMMUNICATIONS - 00C003 (base 16) GLOBALNET COMMUNICATIONS - 912, PLACE TRANS CANADA - LONGUEUIL, QC - CANADA J4G 2M1 - CANADA - - 00-C0-04 (hex) JAPAN BUSINESS COMPUTER CO.LTD - 00C004 (base 16) JAPAN BUSINESS COMPUTER CO.LTD - 1368 FUTOO-CHO, KOHOKU-KU - YOKOHAMA-CITY - 222 - JAPAN - - 00-C0-05 (hex) LIVINGSTON ENTERPRISES, INC. - 00C005 (base 16) LIVINGSTON ENTERPRISES, INC. - 6920 KOLL CENTER PARKWAY #220 - PLEASANTON CA 94566 - UNITED STATES - - 00-C0-06 (hex) NIPPON AVIONICS CO., LTD. - 00C006 (base 16) NIPPON AVIONICS CO., LTD. - INDUSTRIAL SYSTEM DIVISION - 28-2, HONGOH 2-CHOME, SEYA-KU YOKOHAMA - JAPAN - - 00-C0-07 (hex) PINNACLE DATA SYSTEMS, INC. - 00C007 (base 16) PINNACLE DATA SYSTEMS, INC. - 1350 WEST FIFTH AVENUE - COLUMBUS OH 43212 - UNITED STATES - - 00-C0-08 (hex) SECO SRL - 00C008 (base 16) SECO SRL - VIA CALAMANDREI 91 - 52100 AREZZO - ITALY - - 00-C0-09 (hex) KT TECHNOLOGY (S) PTE LTD - 00C009 (base 16) KT TECHNOLOGY (S) PTE LTD - KT BUILDING - 100E PASIR PANJANG ROAD - SINGAPORE 0511 - SINGAPORE - - 00-C0-0A (hex) MICRO CRAFT - 00C00A (base 16) MICRO CRAFT - 2-4-3 NISHIFURUMATSU - OKAYAMA CITY OKAYAMA PREF. 700 - JAPAN - - 00-C0-0B (hex) NORCONTROL A.S. - 00C00B (base 16) NORCONTROL A.S. - P.O. BOX 1024 - N-3194 HORTEN - NORWAY - - 00-C0-0C (hex) RELIA TECHNOLGIES - 00C00C (base 16) RELIA TECHNOLGIES - 1F., NO. 24, INDUSTRY E. 9TH - RD., SCIENCE-BASED INDUSTRIAL PARK HSIN- - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-C0-0D (hex) ADVANCED LOGIC RESEARCH, INC. - 00C00D (base 16) ADVANCED LOGIC RESEARCH, INC. - 9401 JERONIMO - IRVINE CA 92618 - UNITED STATES - - 00-C0-0E (hex) PSITECH, INC. - 00C00E (base 16) PSITECH, INC. - 18368 BANDILIER CIRCLE - FOUNTAIN VALLEY CA 92708 - UNITED STATES - - 00-C0-0F (hex) QUANTUM SOFTWARE SYSTEMS LTD. - 00C00F (base 16) QUANTUM SOFTWARE SYSTEMS LTD. - 175 TERRENCE MATTHEWS CRESCENT - KANATA, ONTARIO CANADA - K2L 3T5 - CANADA - - 00-C0-10 (hex) HIRAKAWA HEWTECH CORP. - 00C010 (base 16) HIRAKAWA HEWTECH CORP. - 7F, BLDG.B, OMORI BELLPORT - 6-26-2, MINAMI-OI,SHINAGAWA-KU TOKYO 140 - JAPAN - - 00-C0-11 (hex) INTERACTIVE COMPUTING DEVICES - 00C011 (base 16) INTERACTIVE COMPUTING DEVICES - 1735 TECHNOLOGY DRIVE-STE #720 - SAN JOSE CA 95110 - UNITED STATES - - 00-C0-12 (hex) NETSPAN CORPORATION - 00C012 (base 16) NETSPAN CORPORATION - 1411 E. CAMPBELL RD - SUITE #1000 - RICHARDSON TX 75081 - UNITED STATES - - 00-C0-13 (hex) NETRIX - 00C013 (base 16) NETRIX - 13595 DULLES TECHNOLOGY DRIVE - HERNDON VA 22071 - UNITED STATES - - 00-C0-14 (hex) TELEMATICS CALABASAS INT'L,INC - 00C014 (base 16) TELEMATICS CALABASAS INT'L,INC - 26630 AGOURA ROAD - CALABASAS CA 91302-1988 - UNITED STATES - - 00-C0-15 (hex) NEW MEDIA CORPORATION - 00C015 (base 16) NEW MEDIA CORPORATION - 15375 BARRANCA PARKWAY - BUILDING - IRVINE CA 92718 - UNITED STATES - - 00-C0-16 (hex) ELECTRONIC THEATRE CONTROLS - 00C016 (base 16) ELECTRONIC THEATRE CONTROLS - 3030 LAURA LANE - MIDDLETON WI 53562 - UNITED STATES - - 00-C0-17 (hex) Fluke Corporation - 00C017 (base 16) Fluke Corporation - 6920 Seaway Blvd. - Everett WA 98203 - UNITED STATES - - 00-C0-18 (hex) LANART CORPORATION - 00C018 (base 16) LANART CORPORATION - 145 ROSEMARY STREET - NEEDHAM MA 02194 - UNITED STATES - - 00-C0-19 (hex) LEAP TECHNOLOGY, INC. - 00C019 (base 16) LEAP TECHNOLOGY, INC. - 20 - BURLINGTON MA 01803 - UNITED STATES - - 00-C0-1A (hex) COROMETRICS MEDICAL SYSTEMS - 00C01A (base 16) COROMETRICS MEDICAL SYSTEMS - 61 BARNES PARK ROAD NORTH - WALLINGFORD CT 06492-0333 - UNITED STATES - - 00-C0-1B (hex) SOCKET COMMUNICATIONS, INC. - 00C01B (base 16) SOCKET COMMUNICATIONS, INC. - 2823 WHIPPLE RD. - UNION CITY CA 94587 - UNITED STATES - - 00-C0-1C (hex) INTERLINK COMMUNICATIONS LTD. - 00C01C (base 16) INTERLINK COMMUNICATIONS LTD. - BRUNEL ROAD, - GORSE LANE INDUSTRIAL ESTATE CLACTON-ON- - ENGLAND - UNITED KINGDOM - - 00-C0-1D (hex) GRAND JUNCTION NETWORKS, INC. - 00C01D (base 16) GRAND JUNCTION NETWORKS, INC. - 3101 WHIPPLE RD., #27 - UNION CITY CA 94587 - UNITED STATES - - 00-C0-1E (hex) LA FRANCAISE DES JEUX - 00C01E (base 16) LA FRANCAISE DES JEUX - CENTRE DE ROUSSY/DTI - 77230 ROUSSY-LE-VIEUX - FRANCE - - 00-C0-1F (hex) S.E.R.C.E.L. - 00C01F (base 16) S.E.R.C.E.L. - B.P. 439 - 44474 CARQUEFOU CEDEX - FRANCE - - 00-C0-20 (hex) ARCO ELECTRONIC, CONTROL LTD. - 00C020 (base 16) ARCO ELECTRONIC, CONTROL LTD. - 2750 NORTH 29TH AVE.-STE.#316 - HOLLYWOOD FL 33020 - UNITED STATES - - 00-C0-21 (hex) NETEXPRESS - 00C021 (base 16) NETEXPRESS - 989 EAST HILLSDALE BLVD. - SUITE #290 - FOSTER CITY CA 94404-2113 - UNITED STATES - - 00-C0-22 (hex) LASERMASTER TECHNOLOGIES, INC. - 00C022 (base 16) LASERMASTER TECHNOLOGIES, INC. - 7156 SHADY OAK ROAD - EDEN PRAIRIE MN 55344 - UNITED STATES - - 00-C0-23 (hex) TUTANKHAMON ELECTRONICS - 00C023 (base 16) TUTANKHAMON ELECTRONICS - 2446 ESTAND WAY - PLEASANT HILL CA 94523 - UNITED STATES - - 00-C0-24 (hex) EDEN SISTEMAS DE COMPUTACAO SA - 00C024 (base 16) EDEN SISTEMAS DE COMPUTACAO SA - RUA DO OUVIDOR 121 5 ANDAR - RIO DE JANEIRO - BRAZIL - - 00-C0-25 (hex) DATAPRODUCTS CORPORATION - 00C025 (base 16) DATAPRODUCTS CORPORATION - 6219 DESOTO AVENUE - WOODLAND HILLS CA 91365-0746 - UNITED STATES - - 00-C0-26 (hex) LANS TECHNOLOGY CO., LTD. - 00C026 (base 16) LANS TECHNOLOGY CO., LTD. - 153 MINTSU RD. 2F, TAOYUAN, - TAIWAN R. O. C. - TAIWAN, PROVINCE OF CHINA - - 00-C0-27 (hex) CIPHER SYSTEMS, INC. - 00C027 (base 16) CIPHER SYSTEMS, INC. - 22115 NW Imbrie Dr #285 - Hillsboro OR 97124 - UNITED STATES - - 00-C0-28 (hex) JASCO CORPORATION - 00C028 (base 16) JASCO CORPORATION - 2967-5 ISHIKAWA-CHO, - HACHIOJI-SHI TOKYO 192 - JAPAN - - 00-C0-29 (hex) Nexans Deutschland GmbH - ANS - 00C029 (base 16) Nexans Deutschland GmbH - ANS - Bonnenbroicher Str. 100 - 41238 Moenchengladbach - GERMANY - - 00-C0-2A (hex) OHKURA ELECTRIC CO., LTD. - 00C02A (base 16) OHKURA ELECTRIC CO., LTD. - 2-90-20 SHIRAKO WAKO CITY - SAITAMA PREF. - 351-01 - JAPAN - - 00-C0-2B (hex) GERLOFF GESELLSCHAFT FUR - 00C02B (base 16) GERLOFF GESELLSCHAFT FUR - ELEKRONISCHE SYSTEMENTWICKLUNG - FASANENWEG 25 W-2000 HAMBURG 73 - GERMANY - - 00-C0-2C (hex) CENTRUM COMMUNICATIONS, INC. - 00C02C (base 16) CENTRUM COMMUNICATIONS, INC. - 2880 ZANKER ROAD-STE #108 - SAN JOSE CA 95134 - UNITED STATES - - 00-C0-2D (hex) FUJI PHOTO FILM CO., LTD. - 00C02D (base 16) FUJI PHOTO FILM CO., LTD. - 798 MIYANODAI KAISEI-MACHI - ASHIGARA-KAMI-GUN KANAGAWA - JAPAN - - 00-C0-2E (hex) NETWIZ - 00C02E (base 16) NETWIZ - 26 GOLOMB STREET - HAIFA 33391 - ISRAEL - - 00-C0-2F (hex) OKUMA CORPORATION - 00C02F (base 16) OKUMA CORPORATION - OGUCHI-CHO, NIWA-GUN - AICHI 480-01 - JAPAN - - 00-C0-30 (hex) INTEGRATED ENGINEERING B. V. - 00C030 (base 16) INTEGRATED ENGINEERING B. V. - ELLERMANSTRAAT 15 - 1099 BW AMSTERDAM - THE - NETHERLANDS - - 00-C0-31 (hex) DESIGN RESEARCH SYSTEMS, INC. - 00C031 (base 16) DESIGN RESEARCH SYSTEMS, INC. - 925 E. EXECUTIVE PARK DR. - SUITE - SALT LAKE CITY UT 84117 - UNITED STATES - - 00-C0-32 (hex) I-CUBED LIMITED - 00C032 (base 16) I-CUBED LIMITED - UNIT J1, THE POADDOCKS - 347 CHERRY HINTON ROAD CAMBRIDGE - CB1 4DH CB1 4DH ENGLAND - UNITED KINGDOM - - 00-C0-33 (hex) TELEBIT COMMUNICATIONS APS - 00C033 (base 16) TELEBIT COMMUNICATIONS APS - SKANDERBORGVEJ 234 - DK-8260 VIBY - DENMARK - - 00-C0-34 (hex) TRANSACTION NETWORK - 00C034 (base 16) TRANSACTION NETWORK - SERVICES, INC. - OMNILINK COMMUNICATIONS DIV. 3101 TECHNO - LANSING MI 48910-8356 - UNITED STATES - - 00-C0-35 (hex) QUINTAR COMPANY - 00C035 (base 16) QUINTAR COMPANY - 370 AMAPOLA AVE., STE.#106 - TORRANCE CA 90501 - UNITED STATES - - 00-C0-36 (hex) RAYTECH ELECTRONIC CORP. - 00C036 (base 16) RAYTECH ELECTRONIC CORP. - 2F, NO.6, LANE 497 - CHUNG CHENG RD, HSIN TIEN CITY TAIPEI HS - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-C0-37 (hex) DYNATEM - 00C037 (base 16) DYNATEM - 15795 ROCKFIELD BLVD. - SUITE - IRVINE CA 92718 - UNITED STATES - - 00-C0-38 (hex) RASTER IMAGE PROCESSING SYSTEM - 00C038 (base 16) RASTER IMAGE PROCESSING SYSTEM - 4665 NAUTILUS COURT SOUTH - BOULDER CO 80301 - UNITED STATES - - 00-C0-39 (hex) Teridian Semiconductor Corporation - 00C039 (base 16) Teridian Semiconductor Corporation - 6440 Oak Canyon - Irvine CA 92618 - UNITED STATES - - 00-C0-3A (hex) MEN-MIKRO ELEKTRONIK GMBH - 00C03A (base 16) MEN-MIKRO ELEKTRONIK GMBH - WIESENTALSTRASSE 40 - W-8500 NUERNBERG 90 - GERMANY - - 00-C0-3B (hex) MULTIACCESS COMPUTING CORP. - 00C03B (base 16) MULTIACCESS COMPUTING CORP. - 5350 HOLLISTER AVE., STE. - SANTA BARBARA CA 93111 - UNITED STATES - - 00-C0-3C (hex) TOWER TECH S.R.L. - 00C03C (base 16) TOWER TECH S.R.L. - VIA RIDOLFI 6,8 - 56124 PISA - ITALY - - 00-C0-3D (hex) WIESEMANN & THEIS GMBH - 00C03D (base 16) WIESEMANN & THEIS GMBH - WITTENER STR. 312 - 5600 WUPPERTAL 2 - GERMANY - - 00-C0-3E (hex) FA. GEBR. HELLER GMBH - 00C03E (base 16) FA. GEBR. HELLER GMBH - P.O. BOX 1428, DEP. EE7 - 7440 NURTINGEN - GERMANY - - 00-C0-3F (hex) STORES AUTOMATED SYSTEMS, INC. - 00C03F (base 16) STORES AUTOMATED SYSTEMS, INC. - 1360 ADAMS ROAD - BENSALEM PA 19020 - UNITED STATES - - 00-C0-40 (hex) ECCI - 00C040 (base 16) ECCI - 15070-B AVENUE OF SCIENCE - SAN DIEGO CA 92128 - UNITED STATES - - 00-C0-41 (hex) DIGITAL TRANSMISSION SYSTEMS - 00C041 (base 16) DIGITAL TRANSMISSION SYSTEMS - 4830 RIVER GREEN PARKWAY - DULUTH GA 30136 - UNITED STATES - - 00-C0-42 (hex) DATALUX CORP. - 00C042 (base 16) DATALUX CORP. - 2836 CESSNA DRIVE - WINCHESTER VA 22601 - UNITED STATES - - 00-C0-43 (hex) STRATACOM - 00C043 (base 16) STRATACOM - 1400 PARKMOOR AVENUE - SAN JOSE CA 95126 - UNITED STATES - - 00-C0-44 (hex) EMCOM CORPORATION - 00C044 (base 16) EMCOM CORPORATION - 840 AVENUE - PLANO TX 75074 - UNITED STATES - - 00-C0-45 (hex) ISOLATION SYSTEMS, LTD. - 00C045 (base 16) ISOLATION SYSTEMS, LTD. - 26 SIX POINT ROAD - TORONTO, ONTARIO - CANADA M8Z 2W9 - CANADA - - 00-C0-46 (hex) Blue Chip Technology Ltd - 00C046 (base 16) Blue Chip Technology Ltd - Chowley Oak Lane - Tattenhall - Chester Cheshire CH3 9EX - UNITED KINGDOM - - 00-C0-47 (hex) UNIMICRO SYSTEMS, INC. - 00C047 (base 16) UNIMICRO SYSTEMS, INC. - 44382 S. GRIMMER BLVD. - FREMONT CA 94538 - UNITED STATES - - 00-C0-48 (hex) BAY TECHNICAL ASSOCIATES - 00C048 (base 16) BAY TECHNICAL ASSOCIATES - 200 N. SECOND STREET - P.O. BOX 387 - BAY ST. LOUIS MS 39520 - UNITED STATES - - 00-C0-49 (hex) U.S. ROBOTICS, INC. - 00C049 (base 16) U.S. ROBOTICS, INC. - 8100 NORTH MCCORMICK BLVD. - SKOKIE IL 60076-2999 - UNITED STATES - - 00-C0-4A (hex) GROUP 2000 AG - 00C04A (base 16) GROUP 2000 AG - P.O. BOX 331 - TANNAGERTENSTR. 9 CH-8635 DURNTEN - SWITZERLAND - - 00-C0-4B (hex) CREATIVE MICROSYSTEMS - 00C04B (base 16) CREATIVE MICROSYSTEMS - 9, AVENUE DU CANADA - PARC HIGHTEC 6 Z.A. DE COURTABOEUF - 91966 LES ULIS---FRANC - FRANCE - - 00-C0-4C (hex) DEPARTMENT OF FOREIGN AFFAIRS - 00C04C (base 16) DEPARTMENT OF FOREIGN AFFAIRS - & TRADE - ADMINISTRATIVE BUILDING PARKES PLACE, P - AUSTRALIA - - 00-C0-4D (hex) MITEC, INC. - 00C04D (base 16) MITEC, INC. - BR-KAMEIDO 1 BUILDING - Z-33-1, KAMEIDO, KOUTOU-KU TOKYO, 136 - JAPAN - - 00-C0-4E (hex) COMTROL CORPORATION - 00C04E (base 16) COMTROL CORPORATION - 2675 PATTON ROAD - ST. PAUL MN 55113 - UNITED STATES - - 00-C0-4F (hex) DELL COMPUTER CORPORATION - 00C04F (base 16) DELL COMPUTER CORPORATION - 1807 WEST BRAKER LANE-BLDG. - AUSTIN TX 78758-3610 - UNITED STATES - - 00-C0-50 (hex) TOYO DENKI SEIZO K.K. - 00C050 (base 16) TOYO DENKI SEIZO K.K. - 4-6-32 HIGASHIKASHIWAGAYA - EBINASHI - KANAGAWA JAPAN 243-04 - JAPAN - - 00-C0-51 (hex) ADVANCED INTEGRATION RESEARCH - 00C051 (base 16) ADVANCED INTEGRATION RESEARCH - 2188 DEL FRANCO STREET - SAN JOSE CA 95131 - UNITED STATES - - 00-C0-52 (hex) BURR-BROWN - 00C052 (base 16) BURR-BROWN - P.O. BOX 11400 - TUCSON AZ 85734-1400 - UNITED STATES - - 00-C0-53 (hex) Aspect Software Inc. - 00C053 (base 16) Aspect Software Inc. - 6 Technology Park Drive - Westford MA 01886 - UNITED STATES - - 00-C0-54 (hex) NETWORK PERIPHERALS, LTD. - 00C054 (base 16) NETWORK PERIPHERALS, LTD. - 4TH FLOOR, 17 BOWATER RD. - WESTMINSTER INDUSTRIAL ESTATE LONDON SE - ENGLAND - UNITED KINGDOM - - 00-C0-55 (hex) MODULAR COMPUTING TECHNOLOGIES - 00C055 (base 16) MODULAR COMPUTING TECHNOLOGIES - 2352 MAIN STREET - CONCORD MA 01742 - UNITED STATES - - 00-C0-56 (hex) SOMELEC - 00C056 (base 16) SOMELEC - BP 7010 - 95050 - CERGY PONTOISE CEDEX - FRANCE - - 00-C0-57 (hex) MYCO ELECTRONICS - 00C057 (base 16) MYCO ELECTRONICS - MUSSERONGRAND 1G - S-756 UPPSALA - SWEDEN - - 00-C0-58 (hex) DATAEXPERT CORP. - 00C058 (base 16) DATAEXPERT CORP. - 1156 SONOPRA COURTN-KANG RD. - SUNNYVALE CA 94086 - UNITED STATES - - 00-C0-59 (hex) DENSO CORPORATION - 00C059 (base 16) DENSO CORPORATION - 1-1, Showa-cho, - Kariya-shi, Aichi 448-8661 - JAPAN - - 00-C0-5A (hex) SEMAPHORE COMMUNICATIONS CORP. - 00C05A (base 16) SEMAPHORE COMMUNICATIONS CORP. - 217 HUMBOLDT COURT - SUNNYVALE CA 94089-1300 - UNITED STATES - - 00-C0-5B (hex) NETWORKS NORTHWEST, INC. - 00C05B (base 16) NETWORKS NORTHWEST, INC. - P.O. BOX 1188 - ISSAQUAH WA 98027 - UNITED STATES - - 00-C0-5C (hex) ELONEX PLC - 00C05C (base 16) ELONEX PLC - 2 APSLEY WAY - LONDON, NW2 7HF - UNITED KINGDOM - UNITED KINGDOM - - 00-C0-5D (hex) L&N TECHNOLOGIES - 00C05D (base 16) L&N TECHNOLOGIES - 2899 AGOURA ROAD #196 - WESTLAKE VILLAGE CA 91361-3200 - UNITED STATES - - 00-C0-5E (hex) VARI-LITE, INC. - 00C05E (base 16) VARI-LITE, INC. - 201 REGAL ROW - DALLAS TX 75247 - UNITED STATES - - 00-C0-5F (hex) FINE-PAL COMPANY LIMITED - 00C05F (base 16) FINE-PAL COMPANY LIMITED - RM. 9, 11F, KINGSFORD IND. CTR - 13, WANG HOI ROAD KOWLOON BAY, KLN - HONG KONG - HONG KONG - - 00-C0-60 (hex) ID SCANDINAVIA AS - 00C060 (base 16) ID SCANDINAVIA AS - P.O. BOX 4227 - N-5028 BERGEN - NORWAY - - 00-C0-61 (hex) SOLECTEK CORPORATION - 00C061 (base 16) SOLECTEK CORPORATION - 6370 NANCY RIDGE DR.-STE.#109 - SAN DIEGO CA 92121 - UNITED STATES - - 00-C0-62 (hex) IMPULSE TECHNOLOGY - 00C062 (base 16) IMPULSE TECHNOLOGY - 210 DAHLONEGA ST.#204 - CUMMING GA 30130 - UNITED STATES - - 00-C0-63 (hex) MORNING STAR TECHNOLOGIES, INC - 00C063 (base 16) MORNING STAR TECHNOLOGIES, INC - 1760 ZOLLINGER ROAD - COLUMBUS OH 43221 - UNITED STATES - - 00-C0-64 (hex) GENERAL DATACOMM IND. INC. - 00C064 (base 16) GENERAL DATACOMM IND. INC. - PARK ROAD EXTENSION - P.O. BOX 1299 - MIDDLEBURY CT 06762 - UNITED STATES - - 00-C0-65 (hex) SCOPE COMMUNICATIONS, INC. - 00C065 (base 16) SCOPE COMMUNICATIONS, INC. - 100 OTIS STREET - NORTHBORO MA 01532 - UNITED STATES - - 00-C0-66 (hex) DOCUPOINT, INC. - 00C066 (base 16) DOCUPOINT, INC. - 2701 BAYVIEW DRIVE - FREMONT CA 94538 - UNITED STATES - - 00-C0-67 (hex) UNITED BARCODE INDUSTRIES - 00C067 (base 16) UNITED BARCODE INDUSTRIES - 12240 INDIAN CREEK COURT - BELTSVILLE MD 20705 - UNITED STATES - - 00-C0-68 (hex) HME Clear-Com LTD. - 00C068 (base 16) HME Clear-Com LTD. - 7400 Beach Drive - Waterbeach - Cambridgeshire CB25 9TP - UNITED KINGDOM - - 00-C0-69 (hex) Axxcelera Broadband Wireless - 00C069 (base 16) Axxcelera Broadband Wireless - 111 Castilian Drive - Santa Barbara CA 93117 - UNITED STATES - - 00-C0-6A (hex) ZAHNER-ELEKTRIK GMBH & CO. KG - 00C06A (base 16) ZAHNER-ELEKTRIK GMBH & CO. KG - P.O. BOX 1846 - THUERINGER STRASSE 12 DW-8640 KRONACH-GU - GERMANY - - 00-C0-6B (hex) OSI PLUS CORPORATION - 00C06B (base 16) OSI PLUS CORPORATION - 2-1-23 NAKAMEGURO - MEGURO-KU, TOKYO 153 - JAPAN - - 00-C0-6C (hex) SVEC COMPUTER CORP. - 00C06C (base 16) SVEC COMPUTER CORP. - 3F, 531-1 CHUNG CHENG RD. - HSIN-TIEN CITY, TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-C0-6D (hex) BOCA RESEARCH, INC. - 00C06D (base 16) BOCA RESEARCH, INC. - 6401 CONGRESS AVENUE - BOCA RATON FL 33487 - UNITED STATES - - 00-C0-6E (hex) HAFT TECHNOLOGY, INC. - 00C06E (base 16) HAFT TECHNOLOGY, INC. - DAINI-DOHO BLDG. - 3-CHOME 24-7 NINOMIYA TSUKUBA IBARAGI - 305 - JAPAN - - 00-C0-6F (hex) KOMATSU LTD. - 00C06F (base 16) KOMATSU LTD. - 2597 SHINOMIYA HIRATSUKA-SHI - KANAGAWA 254 - JAPAN - - 00-C0-70 (hex) SECTRA SECURE-TRANSMISSION AB - 00C070 (base 16) SECTRA SECURE-TRANSMISSION AB - TEKNIKRINGEN 2 - S-583 30 LINKOPING - SWEDEN - - 00-C0-71 (hex) AREANEX COMMUNICATIONS, INC. - 00C071 (base 16) AREANEX COMMUNICATIONS, INC. - 3333 OCTAVIUS DRIVE UNIT C - SANTA CLARA CA 95051 - UNITED STATES - - 00-C0-72 (hex) KNX LTD. - 00C072 (base 16) KNX LTD. - HOLLINGWOOD HOUSE - WEST CHEVIN ROAD OTLEY, W. YORKSHIRE - LS21 3HA UNITED KINGDOM - UNITED KINGDOM - - 00-C0-73 (hex) XEDIA CORPORATION - 00C073 (base 16) XEDIA CORPORATION - 301 BALLARDVALE STREET - WILMINGTON MA 01887 - UNITED STATES - - 00-C0-74 (hex) TOYODA AUTOMATIC LOOM - 00C074 (base 16) TOYODA AUTOMATIC LOOM - WORKS, LTD. - 2-1, TOYODA-CHO, KARIYA-SHI AICHI-KEN - 448 - JAPAN - - 00-C0-75 (hex) XANTE CORPORATION - 00C075 (base 16) XANTE CORPORATION - 2559 EMOGENE STREET - MOBILE AL 36606 - UNITED STATES - - 00-C0-76 (hex) I-DATA INTERNATIONAL A-S - 00C076 (base 16) I-DATA INTERNATIONAL A-S - 35-43 VADSTRUPVEJ - DK-2880 BAGSVAERD - DENMARK - - 00-C0-77 (hex) DAEWOO TELECOM LTD. - 00C077 (base 16) DAEWOO TELECOM LTD. - PRODUCTS DESIGN DEPT. 1 - PRODUCTS DESIGN CENTER SOCHO. P.O. BOX 1 - SEOUL SEOUL KOREA - KOREA, REPUBLIC OF - - 00-C0-78 (hex) COMPUTER SYSTEMS ENGINEERING - 00C078 (base 16) COMPUTER SYSTEMS ENGINEERING - 46791 FREMONT BLVD. - FREMONT CA 94538 - UNITED STATES - - 00-C0-79 (hex) FONSYS CO.,LTD. - 00C079 (base 16) FONSYS CO.,LTD. - 209-5, YANGJAE, SEOCHO - SEOUL A37130 - KOREA - KOREA, REPUBLIC OF - - 00-C0-7A (hex) PRIVA B.V. - 00C07A (base 16) PRIVA B.V. - P.O. BOX 18 - 2678 ZG DE LIER (Z-H) - NETHERLANDS - - 00-C0-7B (hex) ASCEND COMMUNICATIONS, INC. - 00C07B (base 16) ASCEND COMMUNICATIONS, INC. - 1701 HARBOR BAY PARKWAY - ALAMEDA CA 94502 - UNITED STATES - - 00-C0-7C (hex) HIGHTECH INFORMATION - 00C07C (base 16) HIGHTECH INFORMATION - SYSTEM LTD. - UNIT 7, 2/F, PO LUNG CENTRE 11 WANG CHIU - HONG KONG - HONG KONG - - 00-C0-7D (hex) RISC DEVELOPMENTS LTD. - 00C07D (base 16) RISC DEVELOPMENTS LTD. - 117 HATFIELD ROAD - ST. ALBANS, HERTS AL14J5 - ENGLAND - UNITED KINGDOM - - 00-C0-7E (hex) KUBOTA CORPORATION ELECTRONIC - 00C07E (base 16) KUBOTA CORPORATION ELECTRONIC - DEVICE DEPT. - 2-35, JINMU-CHO, YAO-CITY OSAKA PREF. - JAPAN #581 - JAPAN - - 00-C0-7F (hex) NUPON COMPUTING CORP. - 00C07F (base 16) NUPON COMPUTING CORP. - 1391 WARNER AVE., -SUITE - TUSTIN CA 92680 - UNITED STATES - - 00-C0-80 (hex) NETSTAR, INC. - 00C080 (base 16) NETSTAR, INC. - CEDAR BUSINESS CENTER - 1801 E. 79TH STREET - MINNEAPOLIS MN 55425-1235 - UNITED STATES - - 00-C0-81 (hex) METRODATA LTD. - 00C081 (base 16) METRODATA LTD. - BLENHEIM HOUSE - CRABTREE OFFICE VILLAGE EVERSLEY WAY, EG - TW20 8RY TW20 8RY ENGLAND - UNITED KINGDOM - - 00-C0-82 (hex) MOORE PRODUCTS CO. - 00C082 (base 16) MOORE PRODUCTS CO. - SUMNEYTOWN PIKE - SPRING HOUSE PA 19477 - UNITED STATES - - 00-C0-83 (hex) TRACE MOUNTAIN PRODUCTS, INC. - 00C083 (base 16) TRACE MOUNTAIN PRODUCTS, INC. - 1040 EAST BROKAW ROAD - SAN JOSE CA 95131 - UNITED STATES - - 00-C0-84 (hex) DATA LINK CORP. LTD. - 00C084 (base 16) DATA LINK CORP. LTD. - 3-15-3 MIDORICHO - TOKOROZAWA-CITY SAITAMA 359 - JAPAN - - 00-C0-85 (hex) ELECTRONICS FOR IMAGING, INC. - 00C085 (base 16) ELECTRONICS FOR IMAGING, INC. - 2855 CAMPUS DRIVE - SAN MATEO CA 94403 - UNITED STATES - - 00-C0-86 (hex) THE LYNK CORPORATION - 00C086 (base 16) THE LYNK CORPORATION - 101 QUEENS DRIVE - KING OF PRUSSIA PA 19406 - UNITED STATES - - 00-C0-87 (hex) UUNET TECHNOLOGIES, INC. - 00C087 (base 16) UUNET TECHNOLOGIES, INC. - 3110 FAIRVIEW PARK DR. #570 - FALLS CHURCH VA 22042 - UNITED STATES - - 00-C0-88 (hex) EKF ELEKTRONIK GMBH - 00C088 (base 16) EKF ELEKTRONIK GMBH - PHILIPP-REIS-STR. 4 - 4700 HAMM - GERMANY - - 00-C0-89 (hex) TELINDUS DISTRIBUTION - 00C089 (base 16) TELINDUS DISTRIBUTION - GELDENAAKSEBAAN 335 - 3001 HEVERLEE - BELGIUM - - 00-C0-8A (hex) Lauterbach GmbH - 00C08A (base 16) Lauterbach GmbH - Altlaufstraße 40 - Höhenkirchen-Siegertsbrunn 85635 - GERMANY - - 00-C0-8B (hex) RISQ MODULAR SYSTEMS, INC. - 00C08B (base 16) RISQ MODULAR SYSTEMS, INC. - 39899 BALENTINE DRIVE-STE #375 - NEWARK CA 94560 - UNITED STATES - - 00-C0-8C (hex) PERFORMANCE TECHNOLOGIES, INC. - 00C08C (base 16) PERFORMANCE TECHNOLOGIES, INC. - 315 SCIENCE PARKWAY - ROCHESTER NY 14620 - UNITED STATES - - 00-C0-8D (hex) TRONIX PRODUCT DEVELOPMENT - 00C08D (base 16) TRONIX PRODUCT DEVELOPMENT - 4908 E. MCDOWELL RD. STE.#100 - PHOENIX AZ 85008 - UNITED STATES - - 00-C0-8E (hex) NETWORK INFORMATION TECHNOLOGY - 00C08E (base 16) NETWORK INFORMATION TECHNOLOGY - 10430 S. DE ANZA BLVD. - CUPERTINO CA 95014 - UNITED STATES - - 00-C0-8F (hex) Panasonic Electric Works Co., Ltd. - 00C08F (base 16) Panasonic Electric Works Co., Ltd. - Tsu-Factory - 1668 Fujikata Tsu-shi - Mie-ken 514-8555 - JAPAN - - 00-C0-90 (hex) PRAIM S.R.L. - 00C090 (base 16) PRAIM S.R.L. - VIA MACCANI, 169 - 38100 TRENTO (TN) - ITALY - - 00-C0-91 (hex) JABIL CIRCUIT, INC. - 00C091 (base 16) JABIL CIRCUIT, INC. - 32275 MALLY ROAD - MADISON HEIGHTS MI 48071 - UNITED STATES - - 00-C0-92 (hex) MENNEN MEDICAL INC. - 00C092 (base 16) MENNEN MEDICAL INC. - 10123 MAIN STREET - CLARENCE NY 14031-2095 - UNITED STATES - - 00-C0-93 (hex) ALTA RESEARCH CORP. - 00C093 (base 16) ALTA RESEARCH CORP. - 614 SOUTH FEDERAL HIGHWAY - DEERFIELD BEACH FL 33441 - UNITED STATES - - 00-C0-94 (hex) VMX INC. - 00C094 (base 16) VMX INC. - 2115 O'NEL DRIVE - SAN JOSE CA 95131 - UNITED STATES - - 00-C0-95 (hex) ZNYX - 00C095 (base 16) ZNYX - 48421 Milmont Drive - Fremont CA 94538 - UNITED STATES - - 00-C0-96 (hex) TAMURA CORPORATION - 00C096 (base 16) TAMURA CORPORATION - COMMUNICATION SYSTEMS DIV. - 19-43 HIGASHI OIZUMI 1 CHOME NERIMA-KU, - JAPAN - - 00-C0-97 (hex) ARCHIPEL SA - 00C097 (base 16) ARCHIPEL SA - 1 RUE DU BULLOZ - F 74940 ANNECY-LE-VIEUX - FRANCE - - 00-C0-98 (hex) CHUNTEX ELECTRONIC CO., LTD. - 00C098 (base 16) CHUNTEX ELECTRONIC CO., LTD. - 6F., NO.2, ALLEY 6, LANE 235 - PAO CHIAO RD., HSIN TIEN, TAIPEI HSIEN - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-C0-99 (hex) YOSHIKI INDUSTRIAL CO.,LTD. - 00C099 (base 16) YOSHIKI INDUSTRIAL CO.,LTD. - 1-38 MATSUGASAKI 2-CHOME - YONEZAWA YAMAGATA - 992 - JAPAN - - 00-C0-9A (hex) PHOTONICS CORPORATION - 00C09A (base 16) PHOTONICS CORPORATION - 2940 NORTH FIRST STREET - SAN JOSE CA 95123-2021 - UNITED STATES - - 00-C0-9B (hex) RELIANCE COMM/TEC, R-TEC - 00C09B (base 16) RELIANCE COMM/TEC, R-TEC - SYSTEMS INC. - 2100 RELIANCE PARKWAY, MS 22 - BEDFORD TX 76021 - UNITED STATES - - 00-C0-9C (hex) HIOKI E.E. CORPORATION - 00C09C (base 16) HIOKI E.E. CORPORATION - 81 Koizumi, Ueda, Nagano - Chiyoda-ku - Tokyo 386-1192 - JAPAN - - 00-C0-9D (hex) DISTRIBUTED SYSTEMS INT'L, INC - 00C09D (base 16) DISTRIBUTED SYSTEMS INT'L, INC - 531 WEST ROOSEVLET RD, STE #2 - WHEATON IL 60187 - UNITED STATES - - 00-C0-9E (hex) CACHE COMPUTERS, INC. - 00C09E (base 16) CACHE COMPUTERS, INC. - 46600 LANDING PARKWAY - FREMONT CA 94538 - UNITED STATES - - 00-C0-9F (hex) QUANTA COMPUTER, INC. - 00C09F (base 16) QUANTA COMPUTER, INC. - 7F., 116, HOU-KANG ST., - SHIH-LIN DIST. TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-C0-A0 (hex) ADVANCE MICRO RESEARCH, INC. - 00C0A0 (base 16) ADVANCE MICRO RESEARCH, INC. - 2045 CORPORATE COURT - SAN JOSE CA 95131 - UNITED STATES - - 00-C0-A1 (hex) TOKYO DENSHI SEKEI CO. - 00C0A1 (base 16) TOKYO DENSHI SEKEI CO. - 255-1 RENKOJI, TAMA-SHI - TOKYO - JAPAN 206 - JAPAN - - 00-C0-A2 (hex) INTERMEDIUM A/S - 00C0A2 (base 16) INTERMEDIUM A/S - ODINSVEJ 19 - DK-2600 GLOSTRUP - DENMARK - - 00-C0-A3 (hex) DUAL ENTERPRISES CORPORATION - 00C0A3 (base 16) DUAL ENTERPRISES CORPORATION - 9TH FLOOR 48 NAN-KANG ROAD - SEC.3, TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-C0-A4 (hex) UNIGRAF OY - 00C0A4 (base 16) UNIGRAF OY - RUUKINTIE 18 - 02320 ESP00 - FINLAND - - 00-C0-A5 (hex) DICKENS DATA SYSTEMS - 00C0A5 (base 16) DICKENS DATA SYSTEMS - 1175 NORTHMEADOW PKWY-STE #150 - ROSWELL GA 30076 - UNITED STATES - - 00-C0-A6 (hex) EXICOM AUSTRALIA PTY. LTD - 00C0A6 (base 16) EXICOM AUSTRALIA PTY. LTD - 44-46 MANDARIN STREET - VILLAWOOD NSW 2163 - AUSTRALIA - - 00-C0-A7 (hex) SEEL LTD. - 00C0A7 (base 16) SEEL LTD. - 3 YOUNG SQUARE - LIVINGSTON EH54 9BJ - SCOTLAND - UNITED KINGDOM - - 00-C0-A8 (hex) GVC CORPORATION - 00C0A8 (base 16) GVC CORPORATION - 1961 CONCOURSE DRIVE-STE - SAN JOSE CA 95131 - UNITED STATES - - 00-C0-A9 (hex) BARRON MCCANN LTD. - 00C0A9 (base 16) BARRON MCCANN LTD. - BEMAC HOUSE - FIFTH AVENUE, LETCHWORTH HERTS., SG6 2HF - UNITED KINGDOM - UNITED KINGDOM - - 00-C0-AA (hex) SILICON VALLEY COMPUTER - 00C0AA (base 16) SILICON VALLEY COMPUTER - 441 N. WHISMAN RD., BLDG.#13 - MT. VIEW CA 94043 - UNITED STATES - - 00-C0-AB (hex) Telco Systems, Inc. - 00C0AB (base 16) Telco Systems, Inc. - 15 Berkshire Road - Mansfield, MA 02048 - UNITED STATES - - 00-C0-AC (hex) GAMBIT COMPUTER COMMUNICATIONS - 00C0AC (base 16) GAMBIT COMPUTER COMMUNICATIONS - SOLTAM INDUSTRIAL PARK - P.O. BOX 107 YOKNEAM 20692 - ISRAEL - - 00-C0-AD (hex) MARBEN COMMUNICATION SYSTEMS - 00C0AD (base 16) MARBEN COMMUNICATION SYSTEMS - 1 RUE DU BOIS CHALAND - LISSES 91029 EVRY CEDEX - FRANCE - - 00-C0-AE (hex) TOWERCOM CO. INC. DBA PC HOUSE - 00C0AE (base 16) TOWERCOM CO. INC. DBA PC HOUSE - 841 E. ARTESIA BLVD. - CARSON CA 90746 - UNITED STATES - - 00-C0-AF (hex) TEKLOGIX INC. - 00C0AF (base 16) TEKLOGIX INC. - 2100 MEADOWVALE BOULEVARD - MISSISSAUGA, ONTARIO, - CANADA L5N 7J9 - CANADA - - 00-C0-B0 (hex) GCC TECHNOLOGIES,INC. - 00C0B0 (base 16) GCC TECHNOLOGIES,INC. - 580 WINTER STREET - WALTHAM MA 02154 - UNITED STATES - - 00-C0-B1 (hex) GENIUS NET CO. - 00C0B1 (base 16) GENIUS NET CO. - 4F, HANSOO B/D 210-5 - YANGJAE-DONG, SEOCHO-GU SEOUL - SOUTH KOREA - KOREA, REPUBLIC OF - - 00-C0-B2 (hex) NORAND CORPORATION - 00C0B2 (base 16) NORAND CORPORATION - 550 2ND STREET SE - CEDAR RAPIDS IA 52401 - UNITED STATES - - 00-C0-B3 (hex) COMSTAT DATACOMM CORPORATION - 00C0B3 (base 16) COMSTAT DATACOMM CORPORATION - 1720 SPECTRUM DRIVE - LAWRENCEVILLE GA 30243 - UNITED STATES - - 00-C0-B4 (hex) MYSON TECHNOLOGY, INC. - 00C0B4 (base 16) MYSON TECHNOLOGY, INC. - 2F, NO. 3, INDUSTRY E. RD.IV - SCIENCE-BASED INDUSTRIAL PARK HSINCHU, ( - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-C0-B5 (hex) CORPORATE NETWORK SYSTEMS,INC. - 00C0B5 (base 16) CORPORATE NETWORK SYSTEMS,INC. - 5711 SIX FORKS ROAD--STE #306 - RALEIGH NC 27609 - UNITED STATES - - 00-C0-B6 (hex) Overland Storage, Inc. - 00C0B6 (base 16) Overland Storage, Inc. - 9112 Spectrum Center Boulevard - San Diego CA 92123 - UNITED STATES - - 00-C0-B7 (hex) AMERICAN POWER CONVERSION CORP - 00C0B7 (base 16) AMERICAN POWER CONVERSION CORP - 267 BOSTON ROAD #2 - NORTH BILLERICA MA 01862 - UNITED STATES - - 00-C0-B8 (hex) FRASER'S HILL LTD. - 00C0B8 (base 16) FRASER'S HILL LTD. - 27502 W. GILL ROAD - P.O. BOX 189 - MORRISTOWN AZ 85342 - UNITED STATES - - 00-C0-B9 (hex) FUNK SOFTWARE, INC. - 00C0B9 (base 16) FUNK SOFTWARE, INC. - 222 THIRD STREET - CAMBRIDGE MA 02142 - UNITED STATES - - 00-C0-BA (hex) NETVANTAGE - 00C0BA (base 16) NETVANTAGE - 201 CONTINENTAL BLVD.-STE.#201 - EL SECUNDO CA 90245 - UNITED STATES - - 00-C0-BB (hex) FORVAL CREATIVE, INC. - 00C0BB (base 16) FORVAL CREATIVE, INC. - 3-27-12 HONGO - BUNKYO-KU TOKYO 113 - JAPAN - - 00-C0-BC (hex) TELECOM AUSTRALIA/CSSC - 00C0BC (base 16) TELECOM AUSTRALIA/CSSC - LOCKED BAG 8812 - SOUTHCOAST MAIL CENTRE 2521 N.S.W. - AUSTRALIA - - 00-C0-BD (hex) INEX TECHNOLOGIES, INC. - 00C0BD (base 16) INEX TECHNOLOGIES, INC. - 3350 SCOTT BLVD. - BLDG.#29 - SANTA CLARA CA 95054 - UNITED STATES - - 00-C0-BE (hex) ALCATEL - SEL - 00C0BE (base 16) ALCATEL - SEL - LORENZ STR - 7000 SUTTGART 40 - GERMANY - - 00-C0-BF (hex) TECHNOLOGY CONCEPTS, LTD. - 00C0BF (base 16) TECHNOLOGY CONCEPTS, LTD. - GRANGE ESTATE - CWMBRAN, GWENT, NP44 3XR - UNITED KINGDOM - UNITED KINGDOM - - 00-C0-C0 (hex) SHORE MICROSYSTEMS, INC. - 00C0C0 (base 16) SHORE MICROSYSTEMS, INC. - 23 POCAHONTAS AVENUE - OCEANPORT NJ 07757 - UNITED STATES - - 00-C0-C1 (hex) QUAD/GRAPHICS, INC. - 00C0C1 (base 16) QUAD/GRAPHICS, INC. - N63 W23075 HWY 74 - SUSSEX WI 53089 - UNITED STATES - - 00-C0-C2 (hex) INFINITE NETWORKS LTD. - 00C0C2 (base 16) INFINITE NETWORKS LTD. - 19 BROOKSIDE ROAD, OXHEY - WATFORD, HERTS WD1 4BW ENGLAND - UNITED KINGDOM - UNITED KINGDOM - - 00-C0-C3 (hex) ACUSON COMPUTED SONOGRAPHY - 00C0C3 (base 16) ACUSON COMPUTED SONOGRAPHY - 1220 CHARLESTON ROAD - P.O. BOX 7393 - MOUNTAIN VIEW CA 94039-7393 - UNITED STATES - - 00-C0-C4 (hex) COMPUTER OPERATIONAL - 00C0C4 (base 16) COMPUTER OPERATIONAL - REQUIREMENT ANALYSTS LTD - CORAL HOUSE, 274A HIGH STREET ALDERSHOT, - GU12 4LZ GU12 4LZ ENGLAND - UNITED KINGDOM - - 00-C0-C5 (hex) SID INFORMATICA - 00C0C5 (base 16) SID INFORMATICA - RUA DR. GERALDO CAMPOS MOREIRA - 240 - 5 ANDAR CEP 04571-020 SAO PAULO - - BRAZIL - - 00-C0-C6 (hex) PERSONAL MEDIA CORP. - 00C0C6 (base 16) PERSONAL MEDIA CORP. - 1-7-7 MY BLDG. HIRATSUKA - SHINAGAWA, TOKYO 142 - JAPAN - - 00-C0-C7 (hex) SPARKTRUM MICROSYSTEMS, INC. - 00C0C7 (base 16) SPARKTRUM MICROSYSTEMS, INC. - 2860 ZANKER ROAD, STE.#210 - SAN JOSE CA 95134 - UNITED STATES - - 00-C0-C8 (hex) MICRO BYTE PTY. LTD. - 00C0C8 (base 16) MICRO BYTE PTY. LTD. - 197 SHERBOURNE RD. - MONTMORENCY MELBOURNE VIC - AUSTRALIA 3094 - AUSTRALIA - - 00-C0-C9 (hex) ELSAG BAILEY PROCESS - 00C0C9 (base 16) ELSAG BAILEY PROCESS - AUTOMATION - 29801 EUCLID AVENUE MS-3S1 - WICKLIFFE OH 44092 - UNITED STATES - - 00-C0-CA (hex) ALFA, INC. - 00C0CA (base 16) ALFA, INC. - 11-1, INDUSTRY EAST ROAD IV - SCIENCE BASED INDUSTRIAL PARK HSINCHU - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-C0-CB (hex) CONTROL TECHNOLOGY CORPORATION - 00C0CB (base 16) CONTROL TECHNOLOGY CORPORATION - 25 SOUTH STREET - HOPKINTON MA 01748 - UNITED STATES - - 00-C0-CC (hex) TELESCIENCES CO SYSTEMS, INC. - 00C0CC (base 16) TELESCIENCES CO SYSTEMS, INC. - 351 NEW ALBANY RD. - MOORESTOWN NJ 08057-1177 - UNITED STATES - - 00-C0-CD (hex) COMELTA, S.A. - 00C0CD (base 16) COMELTA, S.A. - AVDA. PARC TECNOLOGIC, 4 - 08290 CERDANYOLA DEL VALLES BARCELONA - SPAIN - - 00-C0-CE (hex) CEI SYSTEMS & ENGINEERING PTE - 00C0CE (base 16) CEI SYSTEMS & ENGINEERING PTE - BLK 73 #02-18 AYER RAJAH CRESC - AYER RAJAH INDUSTRIAL ESTATE - SINGAPORE 0513 - SINGAPORE - - 00-C0-CF (hex) IMATRAN VOIMA OY - 00C0CF (base 16) IMATRAN VOIMA OY - IVO - P.O. BOX 340 02151 ESPOO - FINLAND - - 00-C0-D0 (hex) RATOC SYSTEM INC. - 00C0D0 (base 16) RATOC SYSTEM INC. - ASAHI NAMBA BLDG. - 1-6-14 SHIKITSU HIGASHI NANIWAKU OSAKA C - 556 - JAPAN - - 00-C0-D1 (hex) COMTREE TECHNOLOGY CORPORATION - 00C0D1 (base 16) COMTREE TECHNOLOGY CORPORATION - 5F-7, NO. 1, FU-HSING NORTH RD - TAIPEI - TAIWAN R.O.C. - CHINA - - 00-C0-D2 (hex) SYNTELLECT, INC. - 00C0D2 (base 16) SYNTELLECT, INC. - 15810 N. 28TH AVENUE - PHOENIX AZ 85023 - UNITED STATES - - 00-C0-D3 (hex) OLYMPUS IMAGE SYSTEMS, INC. - 00C0D3 (base 16) OLYMPUS IMAGE SYSTEMS, INC. - 15271 BARRANCA PARKWAY - IRVINE CA 92718-2201 - UNITED STATES - - 00-C0-D4 (hex) AXON NETWORKS, INC. - 00C0D4 (base 16) AXON NETWORKS, INC. - 104 SPRUCE STREET - WATERTOWN MA 02172 - UNITED STATES - - 00-C0-D5 (hex) Werbeagentur Jürgen Siebert - 00C0D5 (base 16) Werbeagentur Jürgen Siebert - Im Klostergarten 8 - D-50321 Brühl - GERMANY - - 00-C0-D6 (hex) J1 SYSTEMS, INC. - 00C0D6 (base 16) J1 SYSTEMS, INC. - 3 DUNWOODY PARK-STE.#103 - ATLANTA GA 30338 - UNITED STATES - - 00-C0-D7 (hex) TAIWAN TRADING CENTER DBA - 00C0D7 (base 16) TAIWAN TRADING CENTER DBA - TTC COMPUTER PRODUCTS - 3244 N. SKYWAY CIRCLE #102 - IRVING TX 75038 - UNITED STATES - - 00-C0-D8 (hex) UNIVERSAL DATA SYSTEMS - 00C0D8 (base 16) UNIVERSAL DATA SYSTEMS - 5000 BRADFORD DRIVE - HUNTSVILLE AL 35805-1993 - UNITED STATES - - 00-C0-D9 (hex) QUINTE NETWORK CONFIDENTIALITY - 00C0D9 (base 16) QUINTE NETWORK CONFIDENTIALITY - EQUIPMENT INC. - 207 - 121 DIMDAS STREET EAST BELLEVILLE, - CANADA K8N 1C3 - CANADA - - 00-C0-DA (hex) NICE SYSTEMS LTD. - 00C0DA (base 16) NICE SYSTEMS LTD. - 3 TEVUOT HA'ARETZ ST - TEL AVIV 69546 - ISRAEL - - 00-C0-DB (hex) IPC CORPORATION (PTE) LTD. - 00C0DB (base 16) IPC CORPORATION (PTE) LTD. - 122 EUNOS AVE., 7 #05-10 - SINGAPORE 1440 - SINGAPORE - - 00-C0-DC (hex) EOS TECHNOLOGIES, INC. - 00C0DC (base 16) EOS TECHNOLOGIES, INC. - 3945 FREEDOM CIRCLE, STE.#770 - SANTA CLARA CA 95054 - UNITED STATES - - 00-C0-DD (hex) QLogic Corporation - 00C0DD (base 16) QLogic Corporation - 6321 Bury Dr. - Eden Prarie MN 55346 - UNITED STATES - - 00-C0-DE (hex) ZCOMM, INC. - 00C0DE (base 16) ZCOMM, INC. - 1050 C EAST DUANE AVENUE - SUNNYVALE CA 94086 - UNITED STATES - - 00-C0-DF (hex) KYE Systems Corp. - 00C0DF (base 16) KYE Systems Corp. - No. 492 Sec 5, Chung Hsin Road - Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 00-C0-E0 (hex) DSC COMMUNICATION CORP. - 00C0E0 (base 16) DSC COMMUNICATION CORP. - 1000 COIT ROAD, MS#ADVP 3 - PLANO TX 75075 - UNITED STATES - - 00-C0-E1 (hex) SONIC SOLUTIONS - 00C0E1 (base 16) SONIC SOLUTIONS - 1891 E. FRANCISCO BLVD. - SAN RAFAEL CA 94901 - UNITED STATES - - 00-C0-E2 (hex) CALCOMP, INC. - 00C0E2 (base 16) CALCOMP, INC. - 2411 W. LAPALMA AVENUE - P.O. BOX 3250, MS22 - ANAHEIM CA 92803-3250 - UNITED STATES - - 00-C0-E3 (hex) OSITECH COMMUNICATIONS, INC. - 00C0E3 (base 16) OSITECH COMMUNICATIONS, INC. - 679 SOUTHGATE DRIVE - GUELPH, ONTARIO - CANADA N1G 4S2 - CANADA - - 00-C0-E4 (hex) SIEMENS BUILDING - 00C0E4 (base 16) SIEMENS BUILDING - TECHNOLOGIES, INC. - 1000 DEERFIELD PARKWAY - BUFFALO GROVE IL 60089 - UNITED STATES - - 00-C0-E5 (hex) GESPAC, S.A. - 00C0E5 (base 16) GESPAC, S.A. - CHEMIN DES AULX 18 - CH-1228 GENEVA - SWITZERLAND - - 00-C0-E6 (hex) Verilink Corporation - 00C0E6 (base 16) Verilink Corporation - 127 Jetplex Circle - Madison AL 35758 - UNITED STATES - - 00-C0-E7 (hex) FIBERDATA AB - 00C0E7 (base 16) FIBERDATA AB - P.O. BOX 20095 - S-16102 BROMMA - SWEDEN - - 00-C0-E8 (hex) PLEXCOM, INC. - 00C0E8 (base 16) PLEXCOM, INC. - 65 MORELAND ROADENUYE - SIMI VALLEY CA 93065 - UNITED STATES - - 00-C0-E9 (hex) OAK SOLUTIONS, LTD. - 00C0E9 (base 16) OAK SOLUTIONS, LTD. - BROADWAY HOUSE - 149-151 ST NEOTS RD, HARDWICK CAMBRIDGE - ENGLAND - UNITED KINGDOM - - 00-C0-EA (hex) ARRAY TECHNOLOGY LTD. - 00C0EA (base 16) ARRAY TECHNOLOGY LTD. - 145 FRIMLEY ROAD - CAMBERLEY, SURREY - ENGLAND GU15 2PS - UNITED KINGDOM - - 00-C0-EB (hex) SEH COMPUTERTECHNIK GMBH - 00C0EB (base 16) SEH COMPUTERTECHNIK GMBH - Suedring 11 - P.O. BOX 140829 D-33628 Bielefeld - GERMANY - - 00-C0-EC (hex) DAUPHIN TECHNOLOGY - 00C0EC (base 16) DAUPHIN TECHNOLOGY - 450 EISENHOWER LANE NORTH - LOMBARD IL 60148 - UNITED STATES - - 00-C0-ED (hex) US ARMY ELECTRONIC - 00C0ED (base 16) US ARMY ELECTRONIC - PROVING GROUND - 1838 PASEO SAN LUIS - SIERRA VISTA AZ 85635 - UNITED STATES - - 00-C0-EE (hex) KYOCERA CORPORATION - 00C0EE (base 16) KYOCERA CORPORATION - 2-14-9 TAMAGAWADAI - SETAGAYA-KU, TOKYO - 158 - JAPAN - - 00-C0-EF (hex) ABIT CORPORATION - 00C0EF (base 16) ABIT CORPORATION - 29-11 HIRAOKA-CHO - HACHIOUJI-SHI TOKYO - 192 - JAPAN - - 00-C0-F0 (hex) KINGSTON TECHNOLOGY CORP. - 00C0F0 (base 16) KINGSTON TECHNOLOGY CORP. - 17600 NEWHOPE STREET - FOUNTAIN VALLEY CA 92708 - UNITED STATES - - 00-C0-F1 (hex) SHINKO ELECTRIC CO., LTD. - 00C0F1 (base 16) SHINKO ELECTRIC CO., LTD. - COMPUTER SYSTEM DIVISION - 150 MOTOYASHIKI, SANYA-CHO TOYOHASHI-SHI - JAPAN 441-31 - JAPAN - - 00-C0-F2 (hex) TRANSITION NETWORKS - 00C0F2 (base 16) TRANSITION NETWORKS - 6475 CITY WEST PARKWAY - MINNEAPOLIS MN 55344 - UNITED STATES - - 00-C0-F3 (hex) NETWORK COMMUNICATIONS CORP. - 00C0F3 (base 16) NETWORK COMMUNICATIONS CORP. - 5501 GREEN VALLEY DRIVE - BLOOMINGTON MN 55437-1085 - UNITED STATES - - 00-C0-F4 (hex) INTERLINK SYSTEM CO., LTD. - 00C0F4 (base 16) INTERLINK SYSTEM CO., LTD. - INTERLINK B/D, 476-20 - SEOGYO-DONG, MAPO-KU SEOUL - KOREA - KOREA, REPUBLIC OF - - 00-C0-F5 (hex) METACOMP, INC. - 00C0F5 (base 16) METACOMP, INC. - 10989 VIA FRONTERA - SAN DIEGO CA 92127 - UNITED STATES - - 00-C0-F6 (hex) CELAN TECHNOLOGY INC. - 00C0F6 (base 16) CELAN TECHNOLOGY INC. - NO. 101, MIN-HSIANG ST. - HSIN-CHU CITY - TAIWAN TAIWAN R.O.C. - CHINA - - 00-C0-F7 (hex) ENGAGE COMMUNICATION, INC. - 00C0F7 (base 16) ENGAGE COMMUNICATION, INC. - 9053 SOQUEL DRIVE - APTOS CA 95003-4034 - UNITED STATES - - 00-C0-F8 (hex) ABOUT COMPUTING INC. - 00C0F8 (base 16) ABOUT COMPUTING INC. - P.O. BOX 172 - BELMONT MA 02178 - UNITED STATES - - 00-C0-F9 (hex) Artesyn Embedded Technologies - 00C0F9 (base 16) Artesyn Embedded Technologies - 2900 S. Diablo Way Suite 190 - Tempe AZ 85282 - UNITED STATES - - 00-C0-FA (hex) CANARY COMMUNICATIONS, INC. - 00C0FA (base 16) CANARY COMMUNICATIONS, INC. - 1851 ZANKER ROAD - SAN JOSE CA 95112-4213 - UNITED STATES - - 00-C0-FB (hex) ADVANCED TECHNOLOGY LABS - 00C0FB (base 16) ADVANCED TECHNOLOGY LABS - 22100 BOTHELL HIGHWAY S.E. - P.O. BOX 3003 - BOTHELL WA 98041-3003 - UNITED STATES - - 00-C0-FC (hex) ELASTIC REALITY, INC. - 00C0FC (base 16) ELASTIC REALITY, INC. - 925 STEWART STREET - MADISON WI 53713 - UNITED STATES - - 00-C0-FD (hex) PROSUM - 00C0FD (base 16) PROSUM - 12 RUE SADI-CARNOT - 94370 NOISEAU - FRANCE - - 00-C0-FE (hex) APTEC COMPUTER SYSTEMS, INC. - 00C0FE (base 16) APTEC COMPUTER SYSTEMS, INC. - P.O. BOX 6750 - PORTLAND OR 97228-6750 - UNITED STATES - - 00-C0-FF (hex) DOT HILL SYSTEMS CORPORATION - 00C0FF (base 16) DOT HILL SYSTEMS CORPORATION - 6305 El Camino Real - Carlsbad CA 92009 - UNITED STATES - - 00-C1-4F (hex) DDL Co,.ltd. - 00C14F (base 16) DDL Co,.ltd. - 6F AFT BLDG. - 1, KITA 5-JYO HIGASHI 2-CHOUME - SAPPORO HOKKAIDO 060-0035 - JAPAN - - 00-C2-C6 (hex) Intel Corporate - 00C2C6 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-C5-DB (hex) Datatech Sistemas Digitales Avanzados SL - 00C5DB (base 16) Datatech Sistemas Digitales Avanzados SL - Cardenal Herrera Oria 165 - Madrid 28034 - SPAIN - - 00-C6-10 (hex) Apple - 00C610 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-CB-BD (hex) Cambridge Broadband Networks Ltd. - 00CBBD (base 16) Cambridge Broadband Networks Ltd. - Selwyn House Cambridge Business Park - Cambridge Business Park - Cambridge CB4 0WZ - UNITED KINGDOM - - 00-CD-90 (hex) MAS Elektronik AG - 00CD90 (base 16) MAS Elektronik AG - Pollhornbogen 19 - Hamburg 21107 - GERMANY - - 00-CF-1C (hex) COMMUNICATION MACHINERY CORP. - 00CF1C (base 16) COMMUNICATION MACHINERY CORP. - 1226 ANACAPA - SANTA BARBARA CA 93101 - UNITED STATES - - 00-D0-00 (hex) FERRAN SCIENTIFIC, INC. - 00D000 (base 16) FERRAN SCIENTIFIC, INC. - 11558 SORRENTO VALLEY ROAD - SUITE #1 - SAN DIEGO CA 92121 - UNITED STATES - - 00-D0-01 (hex) VST TECHNOLOGIES, INC. - 00D001 (base 16) VST TECHNOLOGIES, INC. - 125 NAGOG PARK - ACTON MA 01720 - UNITED STATES - - 00-D0-02 (hex) DITECH CORPORATION - 00D002 (base 16) DITECH CORPORATION - 825 EAST MIDDLEFIELD RD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-D0-03 (hex) COMDA ENTERPRISES CORP. - 00D003 (base 16) COMDA ENTERPRISES CORP. - 2F, NO. 501-18, CHUNGCHEN ROAD - HSINTIEN, TAIPEI - TAIWAN TAIWAN ROC - TAIWAN, PROVINCE OF CHINA - - 00-D0-04 (hex) PENTACOM LTD. - 00D004 (base 16) PENTACOM LTD. - 8 HASADNAOT STREET - P.O. BOX 12109 HERZLIA 46733 - ISRAEL - - 00-D0-05 (hex) ZHS ZEITMANAGEMENTSYSTEME - 00D005 (base 16) ZHS ZEITMANAGEMENTSYSTEME - HARD-UND SOFTWARE GMBH - KREUZBERGER RING 56 65205 WIESBADEN - GERMANY - - 00-D0-06 (hex) CISCO SYSTEMS, INC. - 00D006 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-07 (hex) MIC ASSOCIATES, INC. - 00D007 (base 16) MIC ASSOCIATES, INC. - 1510-1, KAIDOKI - TAMA, TOKYO - JAPAN JAPAN 206-0012 - JAPAN - - 00-D0-08 (hex) MACTELL CORPORATION - 00D008 (base 16) MACTELL CORPORATION - 7000 CAMERON ROAD - AUSTIN TX 78752 - UNITED STATES - - 00-D0-09 (hex) HSING TECH. ENTERPRISE CO. LTD - 00D009 (base 16) HSING TECH. ENTERPRISE CO. LTD - NO.2, LANE 128, SEC. 2 - CHUNG SHAN N. RD. TAIPEI - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-D0-0A (hex) LANACCESS TELECOM S.A. - 00D00A (base 16) LANACCESS TELECOM S.A. - GRAN VIA 8-10 4 1 - 08902- L'HOSPITALET DE LLOBREGAT - SPAIN - - 00-D0-0B (hex) RHK TECHNOLOGY, INC. - 00D00B (base 16) RHK TECHNOLOGY, INC. - 1050 EAST MAPLE ROAD - TROY MI 48083 - UNITED STATES - - 00-D0-0C (hex) SNIJDER MICRO SYSTEMS - 00D00C (base 16) SNIJDER MICRO SYSTEMS - P.O. BOX 300 - NL-5750 AH DEURNE - THE - NETHERLANDS - - 00-D0-0D (hex) MICROMERITICS INSTRUMENT - 00D00D (base 16) MICROMERITICS INSTRUMENT - CORPORATION - ONE MICROMEERITICS DRIVE - NORCROSS GA 30093-1877 - UNITED STATES - - 00-D0-0E (hex) PLURIS, INC. - 00D00E (base 16) PLURIS, INC. - 10455 BANDLEY DRIVE - CUPERTINO CA 95014 - UNITED STATES - - 00-D0-0F (hex) SPEECH DESIGN GMBH - 00D00F (base 16) SPEECH DESIGN GMBH - INDUSTRIESTR. 1 - D-82110 GERMERING - GERMANY - - 00-D0-10 (hex) CONVERGENT NETWORKS, INC. - 00D010 (base 16) CONVERGENT NETWORKS, INC. - 2 HIGHWOOD DRIVE - TEWKSBURY MA 01876 - UNITED STATES - - 00-D0-11 (hex) PRISM VIDEO, INC. - 00D011 (base 16) PRISM VIDEO, INC. - 15851 DALLAS PARKWAY-STE.#1060 - ADDISON TX 75001 - UNITED STATES - - 00-D0-12 (hex) GATEWORKS CORP. - 00D012 (base 16) GATEWORKS CORP. - 7631 MORRO ROAD - ATASCADERO CA 93422 - UNITED STATES - - 00-D0-13 (hex) PRIMEX AEROSPACE COMPANY - 00D013 (base 16) PRIMEX AEROSPACE COMPANY - P.O. BOX 97009 - 11441 WILLOWS ROAD NE - REDMOND WA 98073-9709 - UNITED STATES - - 00-D0-14 (hex) ROOT, INC. - 00D014 (base 16) ROOT, INC. - 8F TOC2 Bldg, 7-21-11 Nishi-Gotanda - Shinagawa-ku - Tokyo 141-0031 - JAPAN - - 00-D0-15 (hex) UNIVEX MICROTECHNOLOGY CORP. - 00D015 (base 16) UNIVEX MICROTECHNOLOGY CORP. - 2, TZE-CHIANG 3RD ROAD - CHUNG-LI INDUSTRIAL PARK, CHUNG-LI - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-D0-16 (hex) SCM MICROSYSTEMS, INC. - 00D016 (base 16) SCM MICROSYSTEMS, INC. - 160 KNOWLES DRIVE - LOS GATOS CA 95032 - UNITED STATES - - 00-D0-17 (hex) SYNTECH INFORMATION CO., LTD. - 00D017 (base 16) SYNTECH INFORMATION CO., LTD. - 8F, 210, TA-TUNG RD., SEC. 3 - HSI-CHIH, TAIPEI HSIEN - TAIWAN TAIWAN ROC - TAIWAN, PROVINCE OF CHINA - - 00-D0-18 (hex) QWES. COM, INC. - 00D018 (base 16) QWES. COM, INC. - 14742 NEWPORT AVE. - STE. #203 - TUSTIN CA 92780 - UNITED STATES - - 00-D0-19 (hex) DAINIPPON SCREEN CORPORATE - 00D019 (base 16) DAINIPPON SCREEN CORPORATE - REPRESENTATIVES OF AMERICA,INC - 17942 COWAN AVENUE - IRVINE CA 92614 - UNITED STATES - - 00-D0-1A (hex) URMET TLC S.P.A. - 00D01A (base 16) URMET TLC S.P.A. - VIA DI CASTEL ROMANO 167 - 00128 - ROMA - ITALY - - 00-D0-1B (hex) MIMAKI ENGINEERING CO., LTD. - 00D01B (base 16) MIMAKI ENGINEERING CO., LTD. - 5-9-41 KITA SHINAGAWA - SHINAGAWA-KU TOKYO 141-0001 - JAPAN - - 00-D0-1C (hex) SBS TECHNOLOGIES, - 00D01C (base 16) SBS TECHNOLOGIES, - CONNECTIVITY PRODUCTS - 1284 CORPORATE CENTER DRIVE - ST. PAUL MN 55121-1245 - UNITED STATES - - 00-D0-1D (hex) FURUNO ELECTRIC CO., LTD. - 00D01D (base 16) FURUNO ELECTRIC CO., LTD. - NO. 9-52, ASHIHARA-CHO - NISHINOMIYA-CITY - 662-8580 - JAPAN - - 00-D0-1E (hex) PINGTEL CORP. - 00D01E (base 16) PINGTEL CORP. - 773 WINTER STREET - N. ANDOVER MA 01845 - UNITED STATES - - 00-D0-1F (hex) Senetas Security - 00D01F (base 16) Senetas Security - 1/11 Queens Road - Melbourne 3004 Victoria - AUSTRALIA - - 00-D0-20 (hex) AIM SYSTEM, INC. - 00D020 (base 16) AIM SYSTEM, INC. - 4TH FLOOR CHUNGWOO B/D 219-1 - POYEE-DONG, GANGNAM-KU SEOL, 135-200 - KOREA - KOREA, REPUBLIC OF - - 00-D0-21 (hex) REGENT ELECTRONICS CORP. - 00D021 (base 16) REGENT ELECTRONICS CORP. - 200 CENTENNIAL AVE.-STE. #201 - PISCATAWAY NJ 08854 - UNITED STATES - - 00-D0-22 (hex) INCREDIBLE TECHNOLOGIES, INC. - 00D022 (base 16) INCREDIBLE TECHNOLOGIES, INC. - 1600 HICKS ROAD - ROLLING MEADOWS IL 60008 - UNITED STATES - - 00-D0-23 (hex) INFORTREND TECHNOLOGY, INC. - 00D023 (base 16) INFORTREND TECHNOLOGY, INC. - 10F, NO. 33 SAN-MIN RD. - SEC. 2 PANCHIAO CITY TAIPEI HSIEN - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-D0-24 (hex) Cognex Corporation - 00D024 (base 16) Cognex Corporation - Modular Vision Systems Division - In-Sight Products Group 15865 SW 74th Av - Portland OR 97224 - UNITED STATES - - 00-D0-25 (hex) XROSSTECH, INC. - 00D025 (base 16) XROSSTECH, INC. - HABDONG B/D 5F 210-2 - YANGJAE-DONG, SEOCHO-KU SEOUL - KOREA - KOREA, REPUBLIC OF - - 00-D0-26 (hex) HIRSCHMANN AUSTRIA GMBH - 00D026 (base 16) HIRSCHMANN AUSTRIA GMBH - OBERER PASPELSWEG 6 - 8 - 6830 RANKWEIL-BREDERIS - AUSTRIA - - 00-D0-27 (hex) APPLIED AUTOMATION, INC. - 00D027 (base 16) APPLIED AUTOMATION, INC. - P.O. BOX 9999 - BARTLESVILLE OK 74005-9999 - UNITED STATES - - 00-D0-28 (hex) Harmonic, Inc - 00D028 (base 16) Harmonic, Inc - 965 Stewart Drive - Sunnyvale CA 94086-3913 - UNITED STATES - - 00-D0-29 (hex) WAKEFERN FOOD CORPORATION - 00D029 (base 16) WAKEFERN FOOD CORPORATION - 230 RARITAN CENTER PARKWAY - EDISON NJ 08837 - UNITED STATES - - 00-D0-2A (hex) Voxent Systems Ltd. - 00D02A (base 16) Voxent Systems Ltd. - Unit 2, Rowan House - Sheldon Business Park - Chippenham Wiltshire SN14 0SQ - UNITED KINGDOM - - 00-D0-2B (hex) JETCELL, INC. - 00D02B (base 16) JETCELL, INC. - 173 CONSTITUTION DRIVE - MENLO PARK CA 94025-1106 - UNITED STATES - - 00-D0-2C (hex) CAMPBELL SCIENTIFIC, INC. - 00D02C (base 16) CAMPBELL SCIENTIFIC, INC. - 815 W. 1800 N. - LOGAN UT 84321-1784 - UNITED STATES - - 00-D0-2D (hex) ADEMCO - 00D02D (base 16) ADEMCO - 165 EILEEN WAY - SYOSSET NY 11791 - UNITED STATES - - 00-D0-2E (hex) COMMUNICATION AUTOMATION CORP. - 00D02E (base 16) COMMUNICATION AUTOMATION CORP. - 1180 MCDERMOTT DRIVE - WEST CHESTER PA 19380 - UNITED STATES - - 00-D0-2F (hex) VLSI TECHNOLOGY INC. - 00D02F (base 16) VLSI TECHNOLOGY INC. - 8375 S. RIVER PARKWAY - TEMPE AZ 85284 - UNITED STATES - - 00-D0-30 (hex) Safetran Systems Corp - 00D030 (base 16) Safetran Systems Corp - 10655 7th Street - Rancho Cucamonga CA 91730 - UNITED STATES - - 00-D0-31 (hex) INDUSTRIAL LOGIC CORPORATION - 00D031 (base 16) INDUSTRIAL LOGIC CORPORATION - 15 PIEDMONT CENTER-STE #700 - ATLANTA GA 30305 - UNITED STATES - - 00-D0-32 (hex) YANO ELECTRIC CO., LTD. - 00D032 (base 16) YANO ELECTRIC CO., LTD. - 7-3-1 IBUKIDAIHIGASHIMACHI - NISHI-KU, KOBE, 651-2242 - JAPAN - - 00-D0-33 (hex) DALIAN DAXIAN NETWORK - 00D033 (base 16) DALIAN DAXIAN NETWORK - SYSTEM CO., LTD. - 98 SHENGLI RD XIGANG DISTRICT DALIAN, P. - CHINA - - 00-D0-34 (hex) ORMEC SYSTEMS CORP. - 00D034 (base 16) ORMEC SYSTEMS CORP. - 19 LINDEN PARK - ROCHESTER NY 14625 - UNITED STATES - - 00-D0-35 (hex) BEHAVIOR TECH. COMPUTER CORP. - 00D035 (base 16) BEHAVIOR TECH. COMPUTER CORP. - 20F-B, No.98, Sec. 1, - Sintai 5th Rd. - Sijhih City Taipei County 22102 - TAIWAN, PROVINCE OF CHINA - - 00-D0-36 (hex) TECHNOLOGY ATLANTA CORP. - 00D036 (base 16) TECHNOLOGY ATLANTA CORP. - 141 W. WIEUCA RD. N.E. - SUITE #300 - ATLANTA GA 30342 - UNITED STATES - - 00-D0-37 (hex) Pace France - 00D037 (base 16) Pace France - 2 rue Albert 1er - 92210 Saint-Cloud - FRANCE - - 00-D0-38 (hex) FIVEMERE, LTD. - 00D038 (base 16) FIVEMERE, LTD. - UNIT 1-HERON INDUSTRIAL ESTATE - BASINGSTOKE ROAD SPENCERS WOOD, READING - RG7 1PJ ENGLAND - UNITED KINGDOM - - 00-D0-39 (hex) UTILICOM, INC. - 00D039 (base 16) UTILICOM, INC. - 323 LOVE PLACE - SANTA BARBARA CA 93112-3289 - UNITED STATES - - 00-D0-3A (hex) ZONEWORX, INC. - 00D03A (base 16) ZONEWORX, INC. - 40925 COUNTY CENTER DRIVE - SUITE #200 - TEMECULA CA 92592 - UNITED STATES - - 00-D0-3B (hex) VISION PRODUCTS PTY. LTD. - 00D03B (base 16) VISION PRODUCTS PTY. LTD. - SECOND AVENUE, TECHNOLOGY PARK - MAWSON LAKES - AUSTRALIA 5095 - AUSTRALIA - - 00-D0-3C (hex) Vieo, Inc. - 00D03C (base 16) Vieo, Inc. - 12416 Hymeadow Drive, - Suite 200 - Austin TX 78750 - UNITED STATES - - 00-D0-3D (hex) GALILEO TECHNOLOGY, LTD. - 00D03D (base 16) GALILEO TECHNOLOGY, LTD. - MOSHAV MANOF - D.N. MISGAV 20184 - ISRAEL - - 00-D0-3E (hex) ROCKETCHIPS, INC. - 00D03E (base 16) ROCKETCHIPS, INC. - 7901 XERXES AVE. S. - MINNEAPOLIS MN 55431 - UNITED STATES - - 00-D0-3F (hex) AMERICAN COMMUNICATION - 00D03F (base 16) AMERICAN COMMUNICATION - TECHNOLIGIES INTERNATIONAL INC - 320 PROFESSIONAL CENTER DR. SUITE #100 - ROHNERT PARK CA 94928 - UNITED STATES - - 00-D0-40 (hex) SYSMATE CO., LTD. - 00D040 (base 16) SYSMATE CO., LTD. - 1091 WOLPYONG-DONG - SEO-GU, DEAJCON 302-280 - SOUTH KOREA - KOREA, REPUBLIC OF - - 00-D0-41 (hex) AMIGO TECHNOLOGY CO., LTD. - 00D041 (base 16) AMIGO TECHNOLOGY CO., LTD. - 4F-1B, NO.12, LANE 609, SEC.5, - CHUNG HSIN ROAD, SAN CHUNG TAIPEI HSIEN - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-D0-42 (hex) MAHLO GMBH & CO. UG - 00D042 (base 16) MAHLO GMBH & CO. UG - DONAUSTRASSE 12 - D-93342 SAAL/DONAU - GERMANY - - 00-D0-43 (hex) ZONAL RETAIL DATA SYSTEMS - 00D043 (base 16) ZONAL RETAIL DATA SYSTEMS - 24 FORTH STREET - EDINBURGH - SCOTLAND - UNITED KINGDOM - - 00-D0-44 (hex) ALIDIAN NETWORKS, INC. - 00D044 (base 16) ALIDIAN NETWORKS, INC. - 1330 W. MIDDLEFIELD ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-D0-45 (hex) KVASER AB - 00D045 (base 16) KVASER AB - BOX 4076 - 511 04 KINNAHULT - SWEDEN - - 00-D0-46 (hex) DOLBY LABORATORIES, INC. - 00D046 (base 16) DOLBY LABORATORIES, INC. - 100 Potrero Avenue - San Francisco CA 94103-4938 - UNITED STATES - - 00-D0-47 (hex) XN TECHNOLOGIES - 00D047 (base 16) XN TECHNOLOGIES - P.O. BOX 350 - CHENEY WA 99004 - UNITED STATES - - 00-D0-48 (hex) ECTON, INC. - 00D048 (base 16) ECTON, INC. - 5168 CAMPUS DRIVE - PLYMOUTH MEETING PA 19462 - UNITED STATES - - 00-D0-49 (hex) IMPRESSTEK CO., LTD. - 00D049 (base 16) IMPRESSTEK CO., LTD. - 6F, SPECIALTY CONSTRUCTION CTR - 1290, SUNSAN-DONG,SO-GU - 302-120 KOREA (REP.) - KOREA, REPUBLIC OF - - 00-D0-4A (hex) PRESENCE TECHNOLOGY GMBH - 00D04A (base 16) PRESENCE TECHNOLOGY GMBH - + CO. KG - SENDENHORSTER STR. 32 D-48317 DRENSTEINF - GERMANY - - 00-D0-4B (hex) LA CIE GROUP S.A. - 00D04B (base 16) LA CIE GROUP S.A. - 17 RUE AMPERE - 91349 MASSY CEDEX - FRANCE - - 00-D0-4C (hex) EUROTEL TELECOM LTD. - 00D04C (base 16) EUROTEL TELECOM LTD. - CANISTER HOUSE - JEWRY STREET WINCHESTER B023 8SA - UNITED KINGDOM - UNITED KINGDOM - - 00-D0-4D (hex) DIV OF RESEARCH & STATISTICS - 00D04D (base 16) DIV OF RESEARCH & STATISTICS - BOG OF THE FEDERAL RESERVE SYS - MAIL STOP 96 20TH & - WASHINGTON DC 20551 - UNITED STATES - - 00-D0-4E (hex) LOGIBAG - 00D04E (base 16) LOGIBAG - 2, Rue de la Mandinière - 72300 SABLE/SARTHE - FRANCE - - 00-D0-4F (hex) BITRONICS, INC. - 00D04F (base 16) BITRONICS, INC. - P.O. BOX 22290 - LEHIGH VALLEY PA 18002-2290 - UNITED STATES - - 00-D0-50 (hex) ISKRATEL - 00D050 (base 16) ISKRATEL - LJUBLJANSKA C. 24A - 4000 KRANJ - SLOVENIA - - 00-D0-51 (hex) O2 MICRO, INC. - 00D051 (base 16) O2 MICRO, INC. - 2901 TASMAN DRIVE, STE.#205 - SANTA CLARA CA 95054 - UNITED STATES - - 00-D0-52 (hex) ASCEND COMMUNICATIONS, INC. - 00D052 (base 16) ASCEND COMMUNICATIONS, INC. - ONE ASCEND PLAZA - 1701 HARBOR BAY PARKWAY - ALAMEDA CA 94502-3002 - UNITED STATES - - 00-D0-53 (hex) CONNECTED SYSTEMS - 00D053 (base 16) CONNECTED SYSTEMS - 126 W. FIGUEROA STREET - SANTA BARBARA CA 93101 - UNITED STATES - - 00-D0-54 (hex) SAS INSTITUTE INC. - 00D054 (base 16) SAS INSTITUTE INC. - SAS CAMPUS DRIVE, R4 - CARY NC 27511 - UNITED STATES - - 00-D0-55 (hex) KATHREIN-WERKE KG - 00D055 (base 16) KATHREIN-WERKE KG - ANTON-KATHREIN-STRASS 1-3 - D-83004 ROSENHEIM - GERMANY - - 00-D0-56 (hex) SOMAT CORPORATION - 00D056 (base 16) SOMAT CORPORATION - 702 KILLARNEY STREET - URBANA IL 61801 - UNITED STATES - - 00-D0-57 (hex) ULTRAK, INC. - 00D057 (base 16) ULTRAK, INC. - 1301 WATERS RIDGE DRIVE - LEWISVILLE TX 75057 - UNITED STATES - - 00-D0-58 (hex) CISCO SYSTEMS, INC. - 00D058 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-59 (hex) AMBIT MICROSYSTEMS CORP. - 00D059 (base 16) AMBIT MICROSYSTEMS CORP. - 5F-1, 5 HSIN-AN ROAD - SCIENCE-BASED INDUSTRIAL PARK HSINCHU - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-D0-5A (hex) SYMBIONICS, LTD. - 00D05A (base 16) SYMBIONICS, LTD. - ST. JOHN'S INNOVATION PARK - CAMBRIDGE CB4 0WS - ENGLAND - UNITED KINGDOM - - 00-D0-5B (hex) ACROLOOP MOTION CONTROL - 00D05B (base 16) ACROLOOP MOTION CONTROL - SYSTEMS - 3650 CHESTNUT ST. N. - CHASKA MN 55318 - UNITED STATES - - 00-D0-5C (hex) KATHREIN TechnoTrend GmbH - 00D05C (base 16) KATHREIN TechnoTrend GmbH - Ing.- Anton-Kathrein Str. 2 - 83101 Rohrdorf-Thansau - GERMANY - - 00-D0-5D (hex) INTELLIWORXX, INC. - 00D05D (base 16) INTELLIWORXX, INC. - 1819 MAIN STREET, STE #1101 - SARASOTA FL 34236 - UNITED STATES - - 00-D0-5E (hex) STRATABEAM TECHNOLOGY, INC. - 00D05E (base 16) STRATABEAM TECHNOLOGY, INC. - 1943 LANDINGS DRIVE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-D0-5F (hex) VALCOM, INC. - 00D05F (base 16) VALCOM, INC. - 1111 INDUSTRY AVENUE - ROANOKE VA 24013 - UNITED STATES - - 00-D0-60 (hex) Panasonic Europe Ltd. - 00D060 (base 16) Panasonic Europe Ltd. - LABORATORIES GMBH - MONZASTR. 4C D-63225 LANGEN - GERMANY - - 00-D0-61 (hex) TREMON ENTERPRISES CO., LTD. - 00D061 (base 16) TREMON ENTERPRISES CO., LTD. - 15F, NO. 116, SEC. 1 - HSIN-TAI 5TH ROAD HSICHIH, TAIPEI COUNTY - TAIWAN TAIWAN ROC - TAIWAN, PROVINCE OF CHINA - - 00-D0-62 (hex) DIGIGRAM - 00D062 (base 16) DIGIGRAM - PARC DE PRE MILLIET - 38330 MONTBONNOT - FRANCE - - 00-D0-63 (hex) CISCO SYSTEMS, INC. - 00D063 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-64 (hex) MULTITEL - 00D064 (base 16) MULTITEL - 2905 RUE DE CELLES - QUEBEC CITY, QUEBEC PROVINCE - CANADA CANADA G2C-1W7 - CANADA - - 00-D0-65 (hex) TOKO ELECTRIC - 00D065 (base 16) TOKO ELECTRIC - 4008 KUROHAMA, HASUDA-SHI - SAITAMA 349-0192 - JAPAN - - 00-D0-66 (hex) WINTRISS ENGINEERING CORP. - 00D066 (base 16) WINTRISS ENGINEERING CORP. - 6344 FERRIS SQUARE - SAN DIEGO CA 92121 - UNITED STATES - - 00-D0-67 (hex) CAMPIO COMMUNICATIONS - 00D067 (base 16) CAMPIO COMMUNICATIONS - 2033 GATEWAY PL, SUITE #600 - SAN JOSE CA 95110 - UNITED STATES - - 00-D0-68 (hex) IWILL CORPORATION - 00D068 (base 16) IWILL CORPORATION - NO.10, WU-CHUAN 3 RD, - HSIN-CHUAN CITY TAIPEI - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-D0-69 (hex) TECHNOLOGIC SYSTEMS - 00D069 (base 16) TECHNOLOGIC SYSTEMS - 16610 E. LASER DRIVE-STE. #10 - FOUNTAIN HILLS AZ 85268 - UNITED STATES - - 00-D0-6A (hex) LINKUP SYSTEMS CORPORATION - 00D06A (base 16) LINKUP SYSTEMS CORPORATION - 1190 COLEMAN AVE.- STE #2C - SAN JOSE CA 95110 - UNITED STATES - - 00-D0-6B (hex) SR TELECOM INC. - 00D06B (base 16) SR TELECOM INC. - 8150 Trans Canada Highway - Montreal - Quebec H4S 1M5 - CANADA - - 00-D0-6C (hex) SHAREWAVE, INC. - 00D06C (base 16) SHAREWAVE, INC. - 5175 HILLSDALE CIRCLE - EL DORADO HILLS CA 95762 - UNITED STATES - - 00-D0-6D (hex) ACRISON, INC. - 00D06D (base 16) ACRISON, INC. - 20 EMPIRE BLVD. - MOONACHIE NJ 07074 - UNITED STATES - - 00-D0-6E (hex) TRENDVIEW RECORDERS LTD. - 00D06E (base 16) TRENDVIEW RECORDERS LTD. - 4 AIRFIELD WAY - CHRISTCHURCH DORSET BH23 3TS - UNITED KINGDOM - UNITED KINGDOM - - 00-D0-6F (hex) KMC CONTROLS - 00D06F (base 16) KMC CONTROLS - P.O. BOX 497 - 19476 NEW PARIS INDUSTRIAL DR. - NEW PARIS IN 46553 - UNITED STATES - - 00-D0-70 (hex) LONG WELL ELECTRONICS CORP. - 00D070 (base 16) LONG WELL ELECTRONICS CORP. - 4F, NO. 59-1, TSAO DI WEI - SHENGKENG HSIANG, TAIPEI HSIEN - TAIWAN 222 TAIWAN 222 R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-D0-71 (hex) ECHELON CORP. - 00D071 (base 16) ECHELON CORP. - 550 Meridian Avenue - San Jose CA 95126 - UNITED STATES - - 00-D0-72 (hex) BROADLOGIC - 00D072 (base 16) BROADLOGIC - 463 S. MILPITAS BLVD. - MILPITAS CA 95035 - UNITED STATES - - 00-D0-73 (hex) ACN ADVANCED COMMUNICATIONS - 00D073 (base 16) ACN ADVANCED COMMUNICATIONS - NETWORKS SA - RUE DU PUITS-GODET BA CH-2000 NEUCHATEL - SWITZERLAND - - 00-D0-74 (hex) TAQUA SYSTEMS, INC. - 00D074 (base 16) TAQUA SYSTEMS, INC. - 1600 FALMOUTH RD. - STE - CENTERVILLE MA 02632 - UNITED STATES - - 00-D0-75 (hex) ALARIS MEDICAL SYSTEMS, INC. - 00D075 (base 16) ALARIS MEDICAL SYSTEMS, INC. - P.O. BOX 85335 - 10221 WATERIDGE CIRCLE - SAN DIEGO CA 92121-2733 - UNITED STATES - - 00-D0-76 (hex) Bank of America - 00D076 (base 16) Bank of America - 1100 Merrill Drive - Pennington NJ 08534 - UNITED STATES - - 00-D0-77 (hex) LUCENT TECHNOLOGIES - 00D077 (base 16) LUCENT TECHNOLOGIES - CLIENT ACCESS BUSINESS UNIT - 101 CRAWFORDS CORNER ROAD ROOM #1E-437AL - HOLMDEL NJ 07733 - UNITED STATES - - 00-D0-78 (hex) Eltex of Sweden AB - 00D078 (base 16) Eltex of Sweden AB - Box 24 - 283 21 OSBY - SWEDEN - - 00-D0-79 (hex) CISCO SYSTEMS, INC. - 00D079 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-7A (hex) AMAQUEST COMPUTER CORP. - 00D07A (base 16) AMAQUEST COMPUTER CORP. - 8/F, 79 HSIN-TAI - 5TH ROAD, SEC. 1 HS1-CHIH, TAIPEI - TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-D0-7B (hex) COMCAM INTERNATIONAL INC - 00D07B (base 16) COMCAM INTERNATIONAL INC - 1140 McDermott Drive Suite 200 - WEST CHESTER PA 19380 - UNITED STATES - - 00-D0-7C (hex) KOYO ELECTRONICS INC. CO.,LTD. - 00D07C (base 16) KOYO ELECTRONICS INC. CO.,LTD. - 1-171 TENJIN-CHO KODAIRA - TOKYO 187-0004 - JAPAN - - 00-D0-7D (hex) COSINE COMMUNICATIONS - 00D07D (base 16) COSINE COMMUNICATIONS - 1200 BRIDGE PARKWAY - REDWOOD CITY CA 94065 - UNITED STATES - - 00-D0-7E (hex) KEYCORP LTD. - 00D07E (base 16) KEYCORP LTD. - P.O. BOX 199 - CHATSWOOD NSW 2057 - AUSTRALIA - - 00-D0-7F (hex) STRATEGY & TECHNOLOGY, LIMITED - 00D07F (base 16) STRATEGY & TECHNOLOGY, LIMITED - Suite 4.2, Clifton Heights - Triangle West - Bristol BS8 1EJ - UNITED KINGDOM - - 00-D0-80 (hex) EXABYTE CORPORATION - 00D080 (base 16) EXABYTE CORPORATION - 1685 38TH STREET - BOULDER CO 80301 - UNITED STATES - - 00-D0-81 (hex) RTD Embedded Technologies, Inc. - 00D081 (base 16) RTD Embedded Technologies, Inc. - 103 Innovation Blvd. - State College PA 16803 - UNITED STATES - - 00-D0-82 (hex) IOWAVE INC. - 00D082 (base 16) IOWAVE INC. - 1010 WISCONSIN AVENUE - WASHINGTON DC 20007 - UNITED STATES - - 00-D0-83 (hex) INVERTEX, INC. - 00D083 (base 16) INVERTEX, INC. - 1012 MORSE AVENUE- STE.#9 - SUNNYVALE CA 94089 - UNITED STATES - - 00-D0-84 (hex) NEXCOMM SYSTEMS, INC. - 00D084 (base 16) NEXCOMM SYSTEMS, INC. - SUIT #NAL-903, - SUNGNAM TECHNO-PARK 148 YATAP-DONG, BUND - SUNGNAM-CITY SUNGNAM-CITY KYUNGGI-DO,K - KOREA, REPUBLIC OF - - 00-D0-85 (hex) OTIS ELEVATOR COMPANY - 00D085 (base 16) OTIS ELEVATOR COMPANY - 5 FARM SPRINGS RD. - FARMINGTON CT 06032 - UNITED STATES - - 00-D0-86 (hex) FOVEON, INC. - 00D086 (base 16) FOVEON, INC. - 2820 San Tomas Expressway - Santa Clara CA 95051 - UNITED STATES - - 00-D0-87 (hex) MICROFIRST INC. - 00D087 (base 16) MICROFIRST INC. - 11 EAST OAK STREET - OAKLAND NJ 07436 - UNITED STATES - - 00-D0-88 (hex) ARRIS Group, Inc. - 00D088 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-D0-89 (hex) DYNACOLOR, INC. - 00D089 (base 16) DYNACOLOR, INC. - No.116, Zhouzi St., Neihu Dist. - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 00-D0-8A (hex) PHOTRON USA - 00D08A (base 16) PHOTRON USA - 1101 S. WINCHESTER BLVD. - SUITE #D-144 - SAN JOSE CA 95128 - UNITED STATES - - 00-D0-8B (hex) ADVA Optical Networking Ltd. - 00D08B (base 16) ADVA Optical Networking Ltd. - ADVAntage House - Tribune Way - York YO30 4RY - UNITED KINGDOM - - 00-D0-8C (hex) GENOA TECHNOLOGY, INC. - 00D08C (base 16) GENOA TECHNOLOGY, INC. - 5401 TECH CIRCLE - MOORPARK CA 93021 - UNITED STATES - - 00-D0-8D (hex) PHOENIX GROUP, INC. - 00D08D (base 16) PHOENIX GROUP, INC. - 123 MARCUS BLVD. - HAUPPAUGE NY 11788 - UNITED STATES - - 00-D0-8E (hex) NVISION INC. - 00D08E (base 16) NVISION INC. - 125 CROWN POINT COURT - GRASS VALLEY CA 95945 - UNITED STATES - - 00-D0-8F (hex) ARDENT TECHNOLOGIES, INC. - 00D08F (base 16) ARDENT TECHNOLOGIES, INC. - 250 N. WOLFE ROAD - SUNNYVALE CA 94086 - UNITED STATES - - 00-D0-90 (hex) CISCO SYSTEMS, INC. - 00D090 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-91 (hex) SMARTSAN SYSTEMS, INC. - 00D091 (base 16) SMARTSAN SYSTEMS, INC. - 4655 OLD IRONSIDES DR. #480 - SANTA CLARA CA 95054 - UNITED STATES - - 00-D0-92 (hex) GLENAYRE WESTERN MULTIPLEX - 00D092 (base 16) GLENAYRE WESTERN MULTIPLEX - 1196 BORREGAS AVENUE - SUNNYVALE CA 94089 - UNITED STATES - - 00-D0-93 (hex) TQ - COMPONENTS GMBH - 00D093 (base 16) TQ - COMPONENTS GMBH - GUT DELLING - MUHLSTR 2 - D-82229 SEEFELD - GERMANY - - 00-D0-94 (hex) Seeion Control LLC - 00D094 (base 16) Seeion Control LLC - 117 Stephanie Lane - vista CA 92084-5316 - UNITED STATES - - 00-D0-95 (hex) Alcatel-Lucent, Enterprise Business Group - 00D095 (base 16) Alcatel-Lucent, Enterprise Business Group - 26801 West Agoura Road - CALABASAS CA 91301 - UNITED STATES - - 00-D0-96 (hex) 3COM EUROPE LTD. - 00D096 (base 16) 3COM EUROPE LTD. - BOUNDARY WAY - HEMEL HEMPSTEAD HERTS. HP2 7YU - UNITED KINGDOM - UNITED KINGDOM - - 00-D0-97 (hex) CISCO SYSTEMS, INC. - 00D097 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-98 (hex) Photon Dynamics Canada Inc. - 00D098 (base 16) Photon Dynamics Canada Inc. - 221 Whitehall Drive - Markham, Ontario - L3R 9T1 - CANADA - - 00-D0-99 (hex) Elcard Wireless Systems Oy - 00D099 (base 16) Elcard Wireless Systems Oy - P.O. BOX 120/BECKERINTIC 38 - 51201 KANGASNIEMI - FINLAND - - 00-D0-9A (hex) FILANET CORPORATION - 00D09A (base 16) FILANET CORPORATION - 931 Benecia Avenue - Sunnyvale CA 94085 - UNITED STATES - - 00-D0-9B (hex) SPECTEL LTD. - 00D09B (base 16) SPECTEL LTD. - 21 STILLORGAN INDUSTRIAL PARK - STILLORGAN, CO. DUBLIN - IRELAND - - 00-D0-9C (hex) KAPADIA COMMUNICATIONS - 00D09C (base 16) KAPADIA COMMUNICATIONS - 3925 WEST BROKER LANE - AUSTIN TX 78759 - UNITED STATES - - 00-D0-9D (hex) VERIS INDUSTRIES - 00D09D (base 16) VERIS INDUSTRIES - 10831 SW CASCADE - PORTLAND OR 97223 - UNITED STATES - - 00-D0-9E (hex) 2WIRE, INC. - 00D09E (base 16) 2WIRE, INC. - 694 TASMAN DRIVE - MILPITAS CA 95035 - UNITED STATES - - 00-D0-9F (hex) NOVTEK TEST SYSTEMS - 00D09F (base 16) NOVTEK TEST SYSTEMS - 2170 PARAGON DRIVE - SAN JOSE CA 95131 - UNITED STATES - - 00-D0-A0 (hex) MIPS DENMARK - 00D0A0 (base 16) MIPS DENMARK - LAUTRUPVANG 2B - 2750 BALLERUP - DK - - DENMARK - - 00-D0-A1 (hex) OSKAR VIERLING GMBH + CO. KG - 00D0A1 (base 16) OSKAR VIERLING GMBH + CO. KG - PRETZFELDER STR. 21 - 91320 EBERMANNSTADT - GERMANY - - 00-D0-A2 (hex) INTEGRATED DEVICE - 00D0A2 (base 16) INTEGRATED DEVICE - TECHNOLOGY, INC. - 2975 STENDER WAY M/S 0-318 - SANTA CLARA CA 95054 - UNITED STATES - - 00-D0-A3 (hex) VOCAL DATA, INC. - 00D0A3 (base 16) VOCAL DATA, INC. - 1701 N GREENVILLE #304 - RICHARDSON TX 75081 - UNITED STATES - - 00-D0-A4 (hex) ALANTRO COMMUNICATIONS - 00D0A4 (base 16) ALANTRO COMMUNICATIONS - 141 STONY CIRCLE, STE. #210 - SANTAROSA CA 95401 - UNITED STATES - - 00-D0-A5 (hex) AMERICAN ARIUM - 00D0A5 (base 16) AMERICAN ARIUM - 14281 CHAMBERS ROAD - TUSTIN CA 92780 - UNITED STATES - - 00-D0-A6 (hex) LANBIRD TECHNOLOGY CO., LTD. - 00D0A6 (base 16) LANBIRD TECHNOLOGY CO., LTD. - ROOM A-211, S.B.I. - 647-26, DEUNGCHON-DONG, KANGSEO-GU, SEO - KOREA 157-030 - KOREA, REPUBLIC OF - - 00-D0-A7 (hex) TOKYO SOKKI KENKYUJO CO., LTD. - 00D0A7 (base 16) TOKYO SOKKI KENKYUJO CO., LTD. - 8-2, MINAMI-OHI 6-CHOME - SHINAGAWA-KU TOKYO - JAPAN 140-8560 - JAPAN - - 00-D0-A8 (hex) NETWORK ENGINES, INC. - 00D0A8 (base 16) NETWORK ENGINES, INC. - 61 PLEASANT STREET - RANDOLPH MA 02368 - UNITED STATES - - 00-D0-A9 (hex) SHINANO KENSHI CO., LTD. - 00D0A9 (base 16) SHINANO KENSHI CO., LTD. - ELECTRONIC EQUIPMENT DIVISION - 6-15-26, CHUO, UEDA-SHI NAGANO-KEN, 386- - JAPAN - - 00-D0-AA (hex) CHASE COMMUNICATIONS - 00D0AA (base 16) CHASE COMMUNICATIONS - ST. LEONARDS ROAD - EAST SHEEN LONDON SW16 7LY - UNITED KINGDOM - UNITED KINGDOM - - 00-D0-AB (hex) DELTAKABEL TELECOM CV - 00D0AB (base 16) DELTAKABEL TELECOM CV - HANZEWEG 14 - 2803 MC GOUDA - THE - NETHERLANDS - - 00-D0-AC (hex) GRAYSON WIRELESS - 00D0AC (base 16) GRAYSON WIRELESS - 140 VISTA CENTRE DRIVE - FOREST VA 24551 - UNITED STATES - - 00-D0-AD (hex) TL INDUSTRIES - 00D0AD (base 16) TL INDUSTRIES - 2541 TRACY ROAD - NORTHWOOD OH 43619 - UNITED STATES - - 00-D0-AE (hex) ORESIS COMMUNICATIONS, INC. - 00D0AE (base 16) ORESIS COMMUNICATIONS, INC. - 14670 NW GREENBRIER PKWY - BEAVERTON OR 97006 - UNITED STATES - - 00-D0-AF (hex) CUTLER-HAMMER, INC. - 00D0AF (base 16) CUTLER-HAMMER, INC. - PMP CENTER - 240 VISTA PARK DRIVE - PITTSBURGH PA 15205 - UNITED STATES - - 00-D0-B0 (hex) BITSWITCH LTD. - 00D0B0 (base 16) BITSWITCH LTD. - 3 MEADOW COURT, AMOS ROAD - MEADOWHALL, SHEFFIELD S9 1BX - UNITED KINGDOM - UNITED KINGDOM - - 00-D0-B1 (hex) OMEGA ELECTRONICS SA - 00D0B1 (base 16) OMEGA ELECTRONICS SA - ROUTE DE SOLEURE 68 - CH-2500 BIENNE 4 - SWITZERLAND - - 00-D0-B2 (hex) XIOTECH CORPORATION - 00D0B2 (base 16) XIOTECH CORPORATION - 6455 FLYING CLOUD DRIVE - EDEN PRAIRIE MN 55344 - UNITED STATES - - 00-D0-B3 (hex) DRS Technologies Canada Ltd - 00D0B3 (base 16) DRS Technologies Canada Ltd - 700 Palladium Drive - Suite100 - Ottawa Ontario K2V 1C6 - CANADA - - 00-D0-B4 (hex) KATSUJIMA CO., LTD. - 00D0B4 (base 16) KATSUJIMA CO., LTD. - 1-6-1, SHIRATORI - KATSUSHIKA-KU TOKYO 125-0063 - JAPAN - - 00-D0-B5 (hex) IPricot formerly DotCom - 00D0B5 (base 16) IPricot formerly DotCom - 10-12, avenue de Verdun - La-Garenne-Colombes F-92250 - FRANCE - - 00-D0-B6 (hex) CRESCENT NETWORKS, INC. - 00D0B6 (base 16) CRESCENT NETWORKS, INC. - 201 RIVERNECK ROAD - CHELMSFORD MA 01842 - UNITED STATES - - 00-D0-B7 (hex) INTEL CORPORATION - 00D0B7 (base 16) INTEL CORPORATION - 5200 NE ELAM YOUNG PARKWAY - HF1-08 - HILLSBORO OR 97124 - UNITED STATES - - 00-D0-B8 (hex) Iomega Corporation - 00D0B8 (base 16) Iomega Corporation - - CANADA - - 00-D0-B9 (hex) MICROTEK INTERNATIONAL, INC. - 00D0B9 (base 16) MICROTEK INTERNATIONAL, INC. - NO. 6 INDUSTRY EAST ROAD 3 - SCIENCE-BASED INDUSTRIAL PARK HSINCHU - TAIWAN 30077 TAIWAN 30077 R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-D0-BA (hex) CISCO SYSTEMS, INC. - 00D0BA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-BB (hex) CISCO SYSTEMS, INC. - 00D0BB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-BC (hex) CISCO SYSTEMS, INC. - 00D0BC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-BD (hex) Silicon Image GmbH - 00D0BD (base 16) Silicon Image GmbH - Garbsener Landstraße 10 - D-30419 Hannover - GERMANY - - 00-D0-BE (hex) EMUTEC INC. - 00D0BE (base 16) EMUTEC INC. - P.O. BOX 3035 - EVERETT WA 98203 - UNITED STATES - - 00-D0-BF (hex) PIVOTAL TECHNOLOGIES - 00D0BF (base 16) PIVOTAL TECHNOLOGIES - 70 S. LAKE AVENUE - STE. #900 - PASADENA CA 91101 - UNITED STATES - - 00-D0-C0 (hex) CISCO SYSTEMS, INC. - 00D0C0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-C1 (hex) HARMONIC DATA SYSTEMS, LTD. - 00D0C1 (base 16) HARMONIC DATA SYSTEMS, LTD. - 10 BEIT SHAMAI STREET - TEL-AVIV - ISRAEL 67018 - ISRAEL - - 00-D0-C2 (hex) BALTHAZAR TECHNOLOGY AB - 00D0C2 (base 16) BALTHAZAR TECHNOLOGY AB - ANKDAMMSGATAN 24 - S-17143 SOLNA - SWEDEN - - 00-D0-C3 (hex) VIVID TECHNOLOGY PTE, LTD. - 00D0C3 (base 16) VIVID TECHNOLOGY PTE, LTD. - 1003 BUKIT MERAH CENTRAL - #03-09, S159836 - SINGAPORE - - 00-D0-C4 (hex) TERATECH CORPORATION - 00D0C4 (base 16) TERATECH CORPORATION - 223 MIDDLESEX TRPK. - BURLINGTON MA 01803-3308 - UNITED STATES - - 00-D0-C5 (hex) COMPUTATIONAL SYSTEMS, INC. - 00D0C5 (base 16) COMPUTATIONAL SYSTEMS, INC. - 835 INNOVATION DRIVE - KNOXVILLE TN 37932 - UNITED STATES - - 00-D0-C6 (hex) THOMAS & BETTS CORP. - 00D0C6 (base 16) THOMAS & BETTS CORP. - Thomas & Betts Aust. Pty. Ltd. - 23a Nyrang Street - Lidcombe New South Wales 92618 - AUSTRALIA - - 00-D0-C7 (hex) PATHWAY, INC. - 00D0C7 (base 16) PATHWAY, INC. - 777 BETA DRIVE - MAYFIELD VILLAGE OH 44143 - UNITED STATES - - 00-D0-C8 (hex) Prevas A/S - 00D0C8 (base 16) Prevas A/S - Lyskær 3EF - DK-2730 Herlev - DENMARK - - 00-D0-C9 (hex) ADVANTECH CO., LTD. - 00D0C9 (base 16) ADVANTECH CO., LTD. - FL. 4, NO. 108-3 - MING-CHUAN ROAD SHING-TIEN CITY - TAIPEI TAIPEI TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-D0-CA (hex) Intrinsyc Software International Inc. - 00D0CA (base 16) Intrinsyc Software International Inc. - 885 Dunsmuir Street, Suite 380 - Vancouver B.C. V6C 1N5 - CANADA - - 00-D0-CB (hex) DASAN CO., LTD. - 00D0CB (base 16) DASAN CO., LTD. - DASAN Tower 7F, 49 Daewangpangyo-ro644beon-gil - Bundang-gu - Seonggnam-Si Gyeoenggi-do 463-4000 - KOREA, REPUBLIC OF - - 00-D0-CC (hex) TECHNOLOGIES LYRE INC. - 00D0CC (base 16) TECHNOLOGIES LYRE INC. - 1200 ST-JEAN-BAPTISTE, - SUITE #120 QUEBEC, QUEBEC - CANADA G2E 5E8 - CANADA - - 00-D0-CD (hex) ATAN TECHNOLOGY INC. - 00D0CD (base 16) ATAN TECHNOLOGY INC. - #5, ALLEY 18, LANE 81, - CHIEN KANG, 2ND ROAD HINCHU - TAIWAN TAIWAN R.O.C. - TAIWAN, PROVINCE OF CHINA - - 00-D0-CE (hex) ASYST ELECTRONIC - 00D0CE (base 16) ASYST ELECTRONIC - BRODISCE 7, 10C TRZIN - 1236 TRZIN - SLOVENIA - - 00-D0-CF (hex) MORETON BAY - 00D0CF (base 16) MORETON BAY - 12/97 JIJAWS STREET - SUMNER PARK. 4074 QLD. - AUSTRALIA - - 00-D0-D0 (hex) ZHONGXING TELECOM LTD. - 00D0D0 (base 16) ZHONGXING TELECOM LTD. - 8-9F BUILDING 54,301# - ZHONG SHAN DONGLU, NANJING PRC, PC=21000 - CHINA - - 00-D0-D1 (hex) Sycamore Networks - 00D0D1 (base 16) Sycamore Networks - 220 Mill Rd - Chelmsford MA 01824 - UNITED STATES - - 00-D0-D2 (hex) EPILOG CORPORATION - 00D0D2 (base 16) EPILOG CORPORATION - 500 CORPORATE CIRCLE - STE. - GOLDEN CO 80401 - UNITED STATES - - 00-D0-D3 (hex) CISCO SYSTEMS, INC. - 00D0D3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D0-D4 (hex) V-BITS, INC. - 00D0D4 (base 16) V-BITS, INC. - 2150 TRADE ZONE BLVD. - SUITE #105 - SAN JOSE CA 95131 - UNITED STATES - - 00-D0-D5 (hex) GRUNDIG AG - 00D0D5 (base 16) GRUNDIG AG - KURGARTENSGTREET 37 - D-90762 FUERTH/BAYERN - GERMANY - - 00-D0-D6 (hex) AETHRA TELECOMUNICAZIONI - 00D0D6 (base 16) AETHRA TELECOMUNICAZIONI - VIA MATTEO RICCI, 10 - 60020 ANCONA - ITALY - - 00-D0-D7 (hex) B2C2, INC. - 00D0D7 (base 16) B2C2, INC. - 2020 CHALLENGER DRIVE- - SUITE #101 - ALAMEDA CA 94501 - UNITED STATES - - 00-D0-D8 (hex) 3Com Corporation - 00D0D8 (base 16) 3Com Corporation - 2133 LEGHORN STREET - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-D0-D9 (hex) DEDICATED MICROCOMPUTERS - 00D0D9 (base 16) DEDICATED MICROCOMPUTERS - GROUP, LTD. - 11 OAK STREET, PENDLEBURY SWINTON, MANCH - M274FL UNITED KINGDOM - UNITED KINGDOM - - 00-D0-DA (hex) TAICOM DATA SYSTEMS CO., LTD. - 00D0DA (base 16) TAICOM DATA SYSTEMS CO., LTD. - 45, WU-KUNG 5 ROAD - WU-KU IND. PAVK TAIPEI-HSIEN - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-D0-DB (hex) MCQUAY INTERNATIONAL - 00D0DB (base 16) MCQUAY INTERNATIONAL - 13600 INDUSTRIAL PARK BLVD. - MINNEAPOLIS MN 55441 - UNITED STATES - - 00-D0-DC (hex) MODULAR MINING SYSTEMS, INC. - 00D0DC (base 16) MODULAR MINING SYSTEMS, INC. - 3289 E. HEMISPHERE LOOP - TUCSON AZ 85706 - UNITED STATES - - 00-D0-DD (hex) SUNRISE TELECOM, INC. - 00D0DD (base 16) SUNRISE TELECOM, INC. - 22 GREAT OAKS BLVD. - SAN JOSE CA 95119 - UNITED STATES - - 00-D0-DE (hex) PHILIPS MULTIMEDIA NETWORK - 00D0DE (base 16) PHILIPS MULTIMEDIA NETWORK - SYSTEMS GMBH - FICHTESTRASSE 1A D-02601 BAUTZEN - GERMANY - - 00-D0-DF (hex) KUZUMI ELECTRONICS, INC. - 00D0DF (base 16) KUZUMI ELECTRONICS, INC. - 28-6 IIJIMA-CHYO, SAKAE-KU - YOKOHAMA-SHI KANAGAWA, 244-0842 - JAPAN - - 00-D0-E0 (hex) DOOIN ELECTRONICS CO. - 00D0E0 (base 16) DOOIN ELECTRONICS CO. - DOOIN BLDG. 16-6, SOONAE-DONG - BUNDANG-GU, SUNGNAM-SI KYUNGGI-DO - KOREA 463-020 - KOREA, REPUBLIC OF - - 00-D0-E1 (hex) AVIONITEK ISRAEL INC. - 00D0E1 (base 16) AVIONITEK ISRAEL INC. - 1 ETGAR STREET - TIRAT CARMEL 39120 - ISRAEL - - 00-D0-E2 (hex) MRT MICRO, INC. - 00D0E2 (base 16) MRT MICRO, INC. - 14000 S. MILITARY TRAIL - DELRAY BEACH FL 33484 - UNITED STATES - - 00-D0-E3 (hex) ELE-CHEM ENGINEERING CO., LTD. - 00D0E3 (base 16) ELE-CHEM ENGINEERING CO., LTD. - WINDSTONE OFFICE - 1-803, 275-2 YANGJUE-DONG, SEOCHO-KU - SEOUL 137-130 SEOUL 137-130 KOREA - KOREA, REPUBLIC OF - - 00-D0-E4 (hex) CISCO SYSTEMS, INC. - 00D0E4 (base 16) CISCO SYSTEMS, INC. - 170 WEST TASMAN DRIVE - SAN JOSE CA 95134 - UNITED STATES - - 00-D0-E5 (hex) SOLIDUM SYSTEMS CORP. - 00D0E5 (base 16) SOLIDUM SYSTEMS CORP. - 940 BELFAST ROAD 1S.217 - OTTAWA, ONTARIO K1G 4A2 - CANADA - - 00-D0-E6 (hex) IBOND INC. - 00D0E6 (base 16) IBOND INC. - 3160, DE LA CRUZ BLVD. - SUITE #101 - SANTA CLARA CA 95054 - UNITED STATES - - 00-D0-E7 (hex) VCON TELECOMMUNICATION LTD. - 00D0E7 (base 16) VCON TELECOMMUNICATION LTD. - 22 MASKIT STREET - HERZLIYA 46733 - ISRAEL - - 00-D0-E8 (hex) MAC SYSTEM CO., LTD. - 00D0E8 (base 16) MAC SYSTEM CO., LTD. - R&D INSTITUTE - MAC SYSTEM CO., LTD. 219-2 ANANG7-DONG, - KYUNGKI-DO KOREA, 430-017 - KOREA, REPUBLIC OF - - 00-D0-E9 (hex) Advantage Century Telecommunication Corp. - 00D0E9 (base 16) Advantage Century Telecommunication Corp. - 4F, 41, Tunghsin Rd. - Taipei - TAIWAN, PROVINCE OF CHINA - - 00-D0-EA (hex) NEXTONE COMMUNICATIONS, INC. - 00D0EA (base 16) NEXTONE COMMUNICATIONS, INC. - 9700 GREAT SENECA HGHWY - ROCKVILLE MD 20850 - UNITED STATES - - 00-D0-EB (hex) LIGHTERA NETWORKS, INC. - 00D0EB (base 16) LIGHTERA NETWORKS, INC. - 10201 BUBB ROAD - CUPERTINO CA 95014 - UNITED STATES - - 00-D0-EC (hex) NAKAYO TELECOMMUNICATIONS, INC - 00D0EC (base 16) NAKAYO TELECOMMUNICATIONS, INC - 1-3-2 SOUJYA-MACHI - MAEBASHI-SHI GUNMA, 371-0853 - JAPAN - - 00-D0-ED (hex) XIOX - 00D0ED (base 16) XIOX - 150 DOW STREET - MANCHESTER NH 03101 - UNITED STATES - - 00-D0-EE (hex) DICTAPHONE CORPORATION - 00D0EE (base 16) DICTAPHONE CORPORATION - 3191 BROADBRIDGE AVE. - STRATFORD CT 06614-2559 - UNITED STATES - - 00-D0-EF (hex) IGT - 00D0EF (base 16) IGT - 9295 PROTOTYPE DRIVE - RENO NV 89511 - UNITED STATES - - 00-D0-F0 (hex) CONVISION TECHNOLOGY GMBH - 00D0F0 (base 16) CONVISION TECHNOLOGY GMBH - REBENRING 33 - D-38106 BRAUNSCHWEIG - GERMANY - - 00-D0-F1 (hex) SEGA ENTERPRISES, LTD. - 00D0F1 (base 16) SEGA ENTERPRISES, LTD. - 12-14 HIGASHIKOUJIYA 2-CHOME - OHTA-KU TOKYO 144-8532 - JAPAN - - 00-D0-F2 (hex) MONTEREY NETWORKS - 00D0F2 (base 16) MONTEREY NETWORKS - 1909 N. GLENVILLE DRIVE - RICHARDSON TX 75081 - UNITED STATES - - 00-D0-F3 (hex) SOLARI DI UDINE SPA - 00D0F3 (base 16) SOLARI DI UDINE SPA - VIA GINO PIERI 29 - 33100 UDINE - ITALY - - 00-D0-F4 (hex) CARINTHIAN TECH INSTITUTE - 00D0F4 (base 16) CARINTHIAN TECH INSTITUTE - RICHARD-WAGNER STR. 19 - 9500 VILLACH - AUSTRIA - - 00-D0-F5 (hex) ORANGE MICRO, INC. - 00D0F5 (base 16) ORANGE MICRO, INC. - 1400 N. LAKEVIEW AVE. - ANAHEIM CA 92807 - UNITED STATES - - 00-D0-F6 (hex) Alcatel Canada - 00D0F6 (base 16) Alcatel Canada - 600 March Road - Kanata, Ontario - K2K 2E6 - CANADA - - 00-D0-F7 (hex) NEXT NETS CORPORATION - 00D0F7 (base 16) NEXT NETS CORPORATION - MITA KOKUSAI BLDG. 17F - 1-4-28 MITA MINATO-KU TOKYO 108-0073 - JAPAN - - 00-D0-F8 (hex) FUJIAN STAR TERMINAL - 00D0F8 (base 16) FUJIAN STAR TERMINAL - DEVICE CO., LTD. - FUER INDUSTRIAL ZONE STAR SCIENCE & TECH - FUZHOU FUJIAN, CHINA 350002 - CHINA - - 00-D0-F9 (hex) ACUTE COMMUNICATIONS CORP. - 00D0F9 (base 16) ACUTE COMMUNICATIONS CORP. - NO. 1, CREATION ROAD III - SCIENCE BASED INDUSTRIAL PARK HSINCHU 30 - TAIWAN - TAIWAN, PROVINCE OF CHINA - - 00-D0-FA (hex) Thales e-Security Ltd. - 00D0FA (base 16) Thales e-Security Ltd. - Meadow View House, Crendon Industrial Estate - Long Crendon - Aylesbury Buckinghamshire HP18 9EQ - UNITED KINGDOM - - 00-D0-FB (hex) TEK MICROSYSTEMS, INCORPORATED - 00D0FB (base 16) TEK MICROSYSTEMS, INCORPORATED - ONE NORTH AVENUE - BURLINGTON MA 01803 - UNITED STATES - - 00-D0-FC (hex) GRANITE MICROSYSTEMS - 00D0FC (base 16) GRANITE MICROSYSTEMS - 10202 N. ENTERPRISE DRIVE - MEQUON WI 53092 - UNITED STATES - - 00-D0-FD (hex) OPTIMA TELE.COM, INC. - 00D0FD (base 16) OPTIMA TELE.COM, INC. - 4-20 Cachet Woods Court - Markham ON L6C 3G1 - CANADA - - 00-D0-FE (hex) ASTRAL POINT - 00D0FE (base 16) ASTRAL POINT - COMMUNICATIONS, INC. - 27 INDUSTRIAL AVE.,-STE. #3 - CHELMSFORD MA 01824 - UNITED STATES - - 00-D0-FF (hex) CISCO SYSTEMS, INC. - 00D0FF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-D1-1C (hex) ACETEL - 00D11C (base 16) ACETEL - #1006, World Merdian 2-cha, 426-5, - Gasan-dong, Geumcheon-gu, - Seoul 153-759 - KOREA, REPUBLIC OF - - 00-D3-8D (hex) Hotel Technology Next Generation - 00D38D (base 16) Hotel Technology Next Generation - 650 E. Algonquin Road - Ste 207 - Schaumburg IL 60173 - UNITED STATES - - 00-D6-32 (hex) GE Energy - 00D632 (base 16) GE Energy - Lissue Industrial Estate East - Lissue Road - Lisburn Co Antrim BT28 2RE - UNITED KINGDOM - - 00-D9-D1 (hex) Sony Computer Entertainment Inc. - 00D9D1 (base 16) Sony Computer Entertainment Inc. - 1-7-1 Konan - Minato-ku Tokyo 108-0075 - JAPAN - - 00-DB-1E (hex) Albedo Telecom SL - 00DB1E (base 16) Albedo Telecom SL - Joan d'Austria 112 - Barcelona 08018 - SPAIN - - 00-DB-45 (hex) THAMWAY CO.,LTD. - 00DB45 (base 16) THAMWAY CO.,LTD. - 3-9-2 - Imaizumi - Fuji Shizuoka 417-0001 - JAPAN - - 00-DB-DF (hex) Intel Corporate - 00DBDF (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 00-DD-00 (hex) UNGERMANN-BASS INC. - 00DD00 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-01 (hex) UNGERMANN-BASS INC. - 00DD01 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-02 (hex) UNGERMANN-BASS INC. - 00DD02 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-03 (hex) UNGERMANN-BASS INC. - 00DD03 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-04 (hex) UNGERMANN-BASS INC. - 00DD04 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-05 (hex) UNGERMANN-BASS INC. - 00DD05 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-06 (hex) UNGERMANN-BASS INC. - 00DD06 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-07 (hex) UNGERMANN-BASS INC. - 00DD07 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-08 (hex) UNGERMANN-BASS INC. - 00DD08 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-09 (hex) UNGERMANN-BASS INC. - 00DD09 (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-0A (hex) UNGERMANN-BASS INC. - 00DD0A (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-0B (hex) UNGERMANN-BASS INC. - 00DD0B (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-0C (hex) UNGERMANN-BASS INC. - 00DD0C (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-0D (hex) UNGERMANN-BASS INC. - 00DD0D (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-0E (hex) UNGERMANN-BASS INC. - 00DD0E (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DD-0F (hex) UNGERMANN-BASS INC. - 00DD0F (base 16) UNGERMANN-BASS INC. - 3900 FREEDOM CIRCLE - SANTA CLARA CA 95054 - UNITED STATES - - 00-DE-FB (hex) CISCO SYSTEMS, INC. - 00DEFB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-00 (hex) Fujitsu Limited - 00E000 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - Kosugi-cho 1-chome,Nakahara-ku - KAWASAKI 211-88 Kanagawa - JAPAN - - 00-E0-01 (hex) STRAND LIGHTING LIMITED - 00E001 (base 16) STRAND LIGHTING LIMITED - GRANT WAY - ISLEWORTH - MIDDLESEX England TW7 5QD - UNITED KINGDOM - - 00-E0-02 (hex) CROSSROADS SYSTEMS, INC. - 00E002 (base 16) CROSSROADS SYSTEMS, INC. - 9390 RESEARCH BLVD. - SUITE 2-300 - AUSTIN TX 78759 - UNITED STATES - - 00-E0-03 (hex) NOKIA WIRELESS BUSINESS COMMUN - 00E003 (base 16) NOKIA WIRELESS BUSINESS COMMUN - ACCESS POINT PRODUCTS GROUP - UNIT 6, CAMBRIDGE BUS PARK MILTON RD, CA - CB4 0WS - UNITED KINGDOM - - 00-E0-04 (hex) PMC-SIERRA, INC. - 00E004 (base 16) PMC-SIERRA, INC. - 105-8555 BAXTER PLACE - BURNABY, BC V5A 4V7 - CANADA - - 00-E0-05 (hex) TECHNICAL CORP. - 00E005 (base 16) TECHNICAL CORP. - 22-6 MINAMI SENGENCHO - NISHIKU YOKOHAMA CITY - KANAGAWA - JAPAN - - 00-E0-06 (hex) SILICON INTEGRATED SYS. CORP. - 00E006 (base 16) SILICON INTEGRATED SYS. CORP. - 16, CREATION RD. I - SCIENCE-BASED INDUSTRIAL PARK - HSIN CHU - TAIWAN, PROVINCE OF CHINA - - 00-E0-07 (hex) Avaya ECS Ltd - 00E007 (base 16) Avaya ECS Ltd - Unit 1 Sterling Court, Mundells - Welwyn Garden City Hert AL7 1LZ - UNITED KINGDOM - - 00-E0-08 (hex) AMAZING CONTROLS! INC. - 00E008 (base 16) AMAZING CONTROLS! INC. - 1615 WYATT DRIVE - SANTA CLARA CA 95054 - UNITED STATES - - 00-E0-09 (hex) MARATHON TECHNOLOGIES CORP. - 00E009 (base 16) MARATHON TECHNOLOGIES CORP. - 1300 MASSACHUSETTS AVENUE - BOXBOROUGH MA 01719 - UNITED STATES - - 00-E0-0A (hex) DIBA, INC. - 00E00A (base 16) DIBA, INC. - 3355 EDISON WAY - MENLO PARK CA 94025 - UNITED STATES - - 00-E0-0B (hex) ROOFTOP COMMUNICATIONS CORP. - 00E00B (base 16) ROOFTOP COMMUNICATIONS CORP. - 468 PACO DRIVE - LOS ALTOS CA 94024 - UNITED STATES - - 00-E0-0C (hex) MOTOROLA - 00E00C (base 16) MOTOROLA - 5401 N. BEACH ST. S243 - FT. WORTH TX 76137 - UNITED STATES - - 00-E0-0D (hex) RADIANT SYSTEMS - 00E00D (base 16) RADIANT SYSTEMS - 1000 ALDERMAN DR. - ALPHARETTA GA 30202 - UNITED STATES - - 00-E0-0E (hex) AVALON IMAGING SYSTEMS, INC. - 00E00E (base 16) AVALON IMAGING SYSTEMS, INC. - 3133 INDIAN ROAD - BOULDER CO 80301 - UNITED STATES - - 00-E0-0F (hex) SHANGHAI BAUD DATA - 00E00F (base 16) SHANGHAI BAUD DATA - COMMUNICATION DEVELOPMENT CORP - 3F, GOLD LUCK BUILDING 2507 PUDONG ROAD - SHANGHAI - CHINA - - 00-E0-10 (hex) HESS SB-AUTOMATENBAU GmbH - 00E010 (base 16) HESS SB-AUTOMATENBAU GmbH - HINDENBURGSTRASSE 27-29 - D-71106 MAGSTADT - GERMANY - - 00-E0-11 (hex) Uniden Corporation - 00E011 (base 16) Uniden Corporation - 2-12-7 Hatchobori, - Chuo-ku Tokyo 104-8512 - JAPAN - - 00-E0-12 (hex) PLUTO TECHNOLOGIES INTERNATIONAL INC. - 00E012 (base 16) PLUTO TECHNOLOGIES INTERNATIONAL INC. - 2511 55TH STREET - BOULDER CO 80301 - UNITED STATES - - 00-E0-13 (hex) EASTERN ELECTRONIC CO., LTD. - 00E013 (base 16) EASTERN ELECTRONIC CO., LTD. - NO. 4, SHIN-LONG ROAD, - KWEI-SHAN INDUSTRIAL AREA - TAO-YUAN - TAIWAN, PROVINCE OF CHINA - - 00-E0-14 (hex) CISCO SYSTEMS, INC. - 00E014 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-15 (hex) HEIWA CORPORATION - 00E015 (base 16) HEIWA CORPORATION - 2-3014-8, HIROSAWA-CHO - KIRYU-SHI - GUNMA PREF. 376 - JAPAN - - 00-E0-16 (hex) RAPID CITY COMMUNICATIONS - 00E016 (base 16) RAPID CITY COMMUNICATIONS - 555 CLYDE AVE. - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 00-E0-17 (hex) EXXACT GmbH - 00E017 (base 16) EXXACT GmbH - RHEINSTRAßE 7 - D-41836 HUCKELHOVEN - GERMANY - - 00-E0-18 (hex) ASUSTEK COMPUTER INC. - 00E018 (base 16) ASUSTEK COMPUTER INC. - 150 LI-TE RD. - PEITOU, TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-E0-19 (hex) ING. GIORDANO ELETTRONICA - 00E019 (base 16) ING. GIORDANO ELETTRONICA - VIA PIETRO COSSA 115/12 - 10146-TORINO - ITALY - - 00-E0-1A (hex) COMTEC SYSTEMS. CO., LTD. - 00E01A (base 16) COMTEC SYSTEMS. CO., LTD. - 404-9 CHOUNGCHEN-DONG - BUPYOUNG-KU, INCHON - KOREA, REPUBLIC OF - - 00-E0-1B (hex) SPHERE COMMUNICATIONS, INC. - 00E01B (base 16) SPHERE COMMUNICATIONS, INC. - 2 ENERGY DRIVE - LAKE BLUFF IL 60044 - UNITED STATES - - 00-E0-1C (hex) Cradlepoint, Inc - 00E01C (base 16) Cradlepoint, Inc - 1199 Shoreline Lane - Suite 301 - Boise ID 83702 - UNITED STATES - - 00-E0-1D (hex) WebTV NETWORKS, INC. - 00E01D (base 16) WebTV NETWORKS, INC. - 305 LYTTON AVE. - PALO ALTO CA 94301 - UNITED STATES - - 00-E0-1E (hex) CISCO SYSTEMS, INC. - 00E01E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-1F (hex) AVIDIA Systems, Inc. - 00E01F (base 16) AVIDIA Systems, Inc. - 135 NORTH PLAINS INDUSTRIAL RD - WALLINGFORD CT 06492 - UNITED STATES - - 00-E0-20 (hex) TECNOMEN OY - 00E020 (base 16) TECNOMEN OY - P.O. BOX 93 - FIN-02271 ESPOO - FINLAND - - 00-E0-21 (hex) FREEGATE CORP. - 00E021 (base 16) FREEGATE CORP. - 710 LAKEWAY STE.#230 - SUNNYVALE CA 94086 - UNITED STATES - - 00-E0-22 (hex) Analog Devices Inc. - 00E022 (base 16) Analog Devices Inc. - 777 Bay Street - Suite 2303 - Toronto Ontario M5G 2C8 - CANADA - - 00-E0-23 (hex) TELRAD - 00E023 (base 16) TELRAD - P.O. BOX 50 - LOD 71100 - ISRAEL - - 00-E0-24 (hex) GADZOOX NETWORKS - 00E024 (base 16) GADZOOX NETWORKS - 5850 HELLYER AVENUE - SAN JOSE CA 95138 - UNITED STATES - - 00-E0-25 (hex) dit Co., Ltd. - 00E025 (base 16) dit Co., Ltd. - Premier Toyocho Building - 23-21 Toyo 3-chome, - Koto-ku Tokyo 135-0056 - JAPAN - - 00-E0-26 (hex) Redlake MASD LLC - 00E026 (base 16) Redlake MASD LLC - 3440 E. Pritannia Dr. - Suite 124 - Tuscon AZ 85706 - UNITED STATES - - 00-E0-27 (hex) DUX, INC. - 00E027 (base 16) DUX, INC. - 5-18-19, NISHIKAMATA, OTA-KU - TOKYO-TO, 144 - JAPAN - - 00-E0-28 (hex) APTIX CORPORATION - 00E028 (base 16) APTIX CORPORATION - 2880 N. FIRST STREET - SAN JOSE CA 95134 - UNITED STATES - - 00-E0-29 (hex) STANDARD MICROSYSTEMS CORP. - 00E029 (base 16) STANDARD MICROSYSTEMS CORP. - 6 HUGHES - IRVINE CA 92718 - UNITED STATES - - 00-E0-2A (hex) TANDBERG TELEVISION AS - 00E02A (base 16) TANDBERG TELEVISION AS - PHILIP PEDERSENS V 20 - N-1324 LYSAKER - NORWAY - - 00-E0-2B (hex) EXTREME NETWORKS - 00E02B (base 16) EXTREME NETWORKS - 10460 BANDLEY DRIVE - CUPERINT0 CA 95014 - UNITED STATES - - 00-E0-2C (hex) AST COMPUTER - 00E02C (base 16) AST COMPUTER - 16215 ALTON PARKWAY - IRVINE CA 92718 - UNITED STATES - - 00-E0-2D (hex) InnoMediaLogic, Inc. - 00E02D (base 16) InnoMediaLogic, Inc. - 3653 CHEMIN CHAMBLY - LONGUEUIL, QUEBEC J4L J4L IN9 - CANADA - - 00-E0-2E (hex) SPC ELECTRONICS CORPORATION - 00E02E (base 16) SPC ELECTRONICS CORPORATION - 2-1-3 SHIBASAKI, CHOFU-SHI - TOKYO, 182 - JAPAN - - 00-E0-2F (hex) MCNS HOLDINGS, L.P. - 00E02F (base 16) MCNS HOLDINGS, L.P. - TCI, INC.-TECHNOLOGY VENTURES - P.O. BOX 5630 - DENVER CO 80217-5630 - UNITED STATES - - 00-E0-30 (hex) MELITA INTERNATIONAL CORP. - 00E030 (base 16) MELITA INTERNATIONAL CORP. - 5051 PEACHTREE CORNERS CIRCLE - NORCROSS GA 30092 - UNITED STATES - - 00-E0-31 (hex) HAGIWARA ELECTRIC CO., LTD. - 00E031 (base 16) HAGIWARA ELECTRIC CO., LTD. - 7, SHIMOKOFUKADA, ASADA-CHO - NISSHIN-SHI, AICHI 470-01 - JAPAN - - 00-E0-32 (hex) MISYS FINANCIAL SYSTEMS, LTD. - 00E032 (base 16) MISYS FINANCIAL SYSTEMS, LTD. - BUCKHOLT DRIVE, - WARNDON, WORCESTER WR49SR - UNITED KINGDOM - - 00-E0-33 (hex) E.E.P.D. GmbH - 00E033 (base 16) E.E.P.D. GmbH - ROEMER-STRASSE 4 - 85229 MARKT INDERSDORF - GERMANY - - 00-E0-34 (hex) CISCO SYSTEMS, INC. - 00E034 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-35 (hex) Artesyn Embedded Technologies - 00E035 (base 16) Artesyn Embedded Technologies - 2900 S. Diablo Way - Tempe AZ 85282 - UNITED STATES - - 00-E0-36 (hex) PIONEER CORPORATION - 00E036 (base 16) PIONEER CORPORATION - 2610 Hanazono 4-Chome - Tokorozawa-Shi - Saitama Prefecture, 359-8 - JAPAN - - 00-E0-37 (hex) CENTURY CORPORATION - 00E037 (base 16) CENTURY CORPORATION - 2-28-5, Taito - TAITO-KU, TOKYO 101 - JAPAN - - 00-E0-38 (hex) PROXIMA CORPORATION - 00E038 (base 16) PROXIMA CORPORATION - 9440 CARROLL PARK DRIVE - SAN DIEGO CA 92121-2298 - UNITED STATES - - 00-E0-39 (hex) PARADYNE CORP. - 00E039 (base 16) PARADYNE CORP. - 8545 126TH AVENUE NORTH - LARGO FL 33773 - UNITED STATES - - 00-E0-3A (hex) CABLETRON SYSTEMS, INC. - 00E03A (base 16) CABLETRON SYSTEMS, INC. - 35 INDUSTRIAL WAY - BLDG. #36 - ROCHESTER NH 03867 - UNITED STATES - - 00-E0-3B (hex) PROMINET CORPORATION - 00E03B (base 16) PROMINET CORPORATION - 110 TURNPIKE RD. - STE. #208 - WESTBOROUGH MA 01581 - UNITED STATES - - 00-E0-3C (hex) AdvanSys - 00E03C (base 16) AdvanSys - 1150 RINGWOOD COURT - SAN JOSE CA 95131 - UNITED STATES - - 00-E0-3D (hex) FOCON ELECTRONIC SYSTEMS A/S - 00E03D (base 16) FOCON ELECTRONIC SYSTEMS A/S - DAMVANG, PO BOX 269 - DK-6400 SONDERBORG - DENMARK - - 00-E0-3E (hex) ALFATECH, INC. - 00E03E (base 16) ALFATECH, INC. - SHIN-OSAKA EITO BLDG. - 4-15-18 NISHINAKAJIMA, YODOGAWA-KU, - OSAKA - JAPAN - - 00-E0-3F (hex) JATON CORPORATION - 00E03F (base 16) JATON CORPORATION - 556 SOUTH MILPITAS BLVD. - MILPITAS CA 95035 - UNITED STATES - - 00-E0-40 (hex) DeskStation Technology, Inc. - 00E040 (base 16) DeskStation Technology, Inc. - 15729 COLLEGE BLVD. - LENEXA KS 66219 - UNITED STATES - - 00-E0-41 (hex) CSPI - 00E041 (base 16) CSPI - 43 Manning Rd. - Billerica MA 01821 - UNITED STATES - - 00-E0-42 (hex) Pacom Systems Ltd. - 00E042 (base 16) Pacom Systems Ltd. - UNIT 22 38/46 SOUTH ST. - RYDALMERE 2116 NSW - AUSTRALIA - - 00-E0-43 (hex) VitalCom - 00E043 (base 16) VitalCom - 15222 DEL AMO AVE. - TUSTIN CA 92780 - UNITED STATES - - 00-E0-44 (hex) LSICS CORPORATION - 00E044 (base 16) LSICS CORPORATION - 3-8-3 NINOMIYA, TSKUKUBA-SHI - IBARAGI-KEN, 305 - JAPAN - - 00-E0-45 (hex) TOUCHWAVE, INC. - 00E045 (base 16) TOUCHWAVE, INC. - 994 SAN ANTONIO RD. - PALO ALTO CA 94303 - UNITED STATES - - 00-E0-46 (hex) BENTLY NEVADA CORP. - 00E046 (base 16) BENTLY NEVADA CORP. - PO BOX 157 - MINDEN NV 89423 - UNITED STATES - - 00-E0-47 (hex) InFocus Corporation - 00E047 (base 16) InFocus Corporation - 27500 SW Parkway Avenue - Wilsonville OR 97070-8238 - UNITED STATES - - 00-E0-48 (hex) SDL COMMUNICATIONS, INC. - 00E048 (base 16) SDL COMMUNICATIONS, INC. - P.O. BOX 1303 - EASTON MA 02334 - UNITED STATES - - 00-E0-49 (hex) MICROWI ELECTRONIC GmbH - 00E049 (base 16) MICROWI ELECTRONIC GmbH - ZUSAMSTRASSE 8 - D 86165 AUGSBURG - GERMANY - - 00-E0-4A (hex) ZX Technologies, Inc - 00E04A (base 16) ZX Technologies, Inc - 760 Spanish Oak Trail - Dripping Springs TX 78620 - UNITED STATES - - 00-E0-4B (hex) JUMP INDUSTRIELLE COMPUTERTECHNIK GmbH - 00E04B (base 16) JUMP INDUSTRIELLE COMPUTERTECHNIK GmbH - - VEILCHENGASSE 7 - D94469 DEGGENDORF - GERMANY - - 00-E0-4C (hex) REALTEK SEMICONDUCTOR CORP. - 00E04C (base 16) REALTEK SEMICONDUCTOR CORP. - 1F, NO. 11, INDUSTRY E. RD. IX - SCIENCE-BASED INDUSTRIAL PARK - HSINCHU 300 - TAIWAN, PROVINCE OF CHINA - - 00-E0-4D (hex) INTERNET INITIATIVE JAPAN, INC - 00E04D (base 16) INTERNET INITIATIVE JAPAN, INC - 1-4, SANBAN-CHO, CHIYODA-KU - TOKYO 102 - JAPAN - - 00-E0-4E (hex) SANYO DENKI CO., LTD. - 00E04E (base 16) SANYO DENKI CO., LTD. - 812-3, Shimonogou, Ueda-Shi - Nagano 386-1211 - JAPAN - - 00-E0-4F (hex) CISCO SYSTEMS, INC. - 00E04F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-50 (hex) EXECUTONE INFORMATION SYSTEMS, INC. - 00E050 (base 16) EXECUTONE INFORMATION SYSTEMS, INC. - 478 WHEELERS FARMS ROAD - MILFORD CT 06460 - UNITED STATES - - 00-E0-51 (hex) TALX CORPORATION - 00E051 (base 16) TALX CORPORATION - 1850 BORMAN COURT - ST. LOUIS MO 63146 - UNITED STATES - - 00-E0-52 (hex) Brocade Communications Systems, Inc - 00E052 (base 16) Brocade Communications Systems, Inc - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 00-E0-53 (hex) CELLPORT LABS, INC. - 00E053 (base 16) CELLPORT LABS, INC. - 885 ARAPAHOE AVE., - BOULDER CO 80302 - UNITED STATES - - 00-E0-54 (hex) KODAI HITEC CO., LTD. - 00E054 (base 16) KODAI HITEC CO., LTD. - 2-45 ONUMA HANYU CITY - SAITAMA.348 - JAPAN - - 00-E0-55 (hex) INGENIERIA ELECTRONICA COMERCIAL INELCOM S.A. - 00E055 (base 16) INGENIERIA ELECTRONICA COMERCIAL INELCOM S.A. - CL. PIQUER NO.3 - 28033 MADRID - SPAIN - - 00-E0-56 (hex) HOLONTECH CORPORATION - 00E056 (base 16) HOLONTECH CORPORATION - 2039 SAMARITAN DRIVE - SAN JOSE CA 95124 - UNITED STATES - - 00-E0-57 (hex) HAN MICROTELECOM. CO., LTD. - 00E057 (base 16) HAN MICROTELECOM. CO., LTD. - FASHION BD., 3RD FR, - 1194, DOONSAN 2 - DONG SEO-GU, TAEJON KOREA 302-173 - KOREA, REPUBLIC OF - - 00-E0-58 (hex) PHASE ONE DENMARK A/S - 00E058 (base 16) PHASE ONE DENMARK A/S - ROSKILDEVEJ 39 - DK-2000 FREDERIKSBERG - DENMARK - - 00-E0-59 (hex) CONTROLLED ENVIRONMENTS, LTD. - 00E059 (base 16) CONTROLLED ENVIRONMENTS, LTD. - 590 BERRY STREET - WINNEPEG R3H OR9 - CANADA - - 00-E0-5A (hex) GALEA NETWORK SECURITY - 00E05A (base 16) GALEA NETWORK SECURITY - 2 PLACE du COMMERCE - STE #320 - BROSSARD, QUEBEC J4W 2T8 - CANADA - - 00-E0-5B (hex) WEST END SYSTEMS CORP. - 00E05B (base 16) WEST END SYSTEMS CORP. - 39 WINNER'S CIRCLE DR., - ARNPRIOR, ONTARIO K7S 3G9 - CANADA - - 00-E0-5C (hex) MATSUSHITA KOTOBUKI ELECTRONICS INDUSTRIES, LTD. - 00E05C (base 16) MATSUSHITA KOTOBUKI ELECTRONICS INDUSTRIES, LTD. - 247, FUKUTAKE SAIJO - EHIME, 793 - JAPAN - - 00-E0-5D (hex) UNITEC CO., LTD. - 00E05D (base 16) UNITEC CO., LTD. - KISOGAWA-CHO ICHINOTORI 24 - HAGURI-GUN AICHI 493 - JAPAN - - 00-E0-5E (hex) JAPAN AVIATION ELECTRONICS INDUSTRY, LTD. - 00E05E (base 16) JAPAN AVIATION ELECTRONICS INDUSTRY, LTD. - - 3-1-1 MUSASHINO AKISHIMA-SHI - TOKYO 196 JAPAN - JAPAN - - 00-E0-5F (hex) e-Net, Inc. - 00E05F (base 16) e-Net, Inc. - 12325 HYMEADOW DRIVE - SUITE #2-200 - AUSTIN TX 78750 - UNITED STATES - - 00-E0-60 (hex) SHERWOOD - 00E060 (base 16) SHERWOOD - 21056 FORBES STREET - HAYWARD CA 94545 - UNITED STATES - - 00-E0-61 (hex) EdgePoint Networks, Inc. - 00E061 (base 16) EdgePoint Networks, Inc. - 2238 MARTIN AVENUE - SANTA CLARA CA 95050 - UNITED STATES - - 00-E0-62 (hex) HOST ENGINEERING - 00E062 (base 16) HOST ENGINEERING - 200 EAST MAIN STREET -STE.#700 - JOHNSON CITY TN 37604 - UNITED STATES - - 00-E0-63 (hex) CABLETRON - YAGO SYSTEMS, INC. - 00E063 (base 16) CABLETRON - YAGO SYSTEMS, INC. - 35 INDUSTRIAL WAY - P.O. BOX 5005 - ROCHESTER NH 03866-5005 - UNITED STATES - - 00-E0-64 (hex) SAMSUNG ELECTRONICS - 00E064 (base 16) SAMSUNG ELECTRONICS - 99 W. TASMAN DRIVE - SAN JOSE CA 95134 - UNITED STATES - - 00-E0-65 (hex) OPTICAL ACCESS INTERNATIONAL - 00E065 (base 16) OPTICAL ACCESS INTERNATIONAL - 500 WEST CUMMINGS PL. #3400 - WOBURN MA 01801 - UNITED STATES - - 00-E0-66 (hex) ProMax Systems, Inc. - 00E066 (base 16) ProMax Systems, Inc. - 16 TECHNOLOGY DRIVE--BLDG.#106 - IRVINE CA 92656 - UNITED STATES - - 00-E0-67 (hex) eac AUTOMATION-CONSULTING GmbH - 00E067 (base 16) eac AUTOMATION-CONSULTING GmbH - HERMSDORFER DAMM 222 - 73467 BERLIN - GERMANY - - 00-E0-68 (hex) MERRIMAC SYSTEMS INC. - 00E068 (base 16) MERRIMAC SYSTEMS INC. - 2144 MC COY ROAD - CARROLLTON TX 75006 - UNITED STATES - - 00-E0-69 (hex) JAYCOR - 00E069 (base 16) JAYCOR - 9775 TOWNE CENTRE DRIVE - SAN DIEGO CA 92121 - UNITED STATES - - 00-E0-6A (hex) KAPSCH AG - 00E06A (base 16) KAPSCH AG - WAGENSEILGASSE 1 - 1120-VIENNA - AUSTRIA - - 00-E0-6B (hex) W&G SPECIAL PRODUCTS - 00E06B (base 16) W&G SPECIAL PRODUCTS - SCEINCE PARK EINDHOVIN 5049 - 5692 EB SON - NETHERLANDS - - 00-E0-6C (hex) Ultra Electronics Limited (AEP Networks) - 00E06C (base 16) Ultra Electronics Limited (AEP Networks) - Knaves Beech Business Centre - Loudwater - Hemel Hemstead Herts England HP2 7BW - UNITED KINGDOM - - 00-E0-6D (hex) COMPUWARE CORPORATION - 00E06D (base 16) COMPUWARE CORPORATION - One Campus Martius - Detroit MI 48226 - UNITED STATES - - 00-E0-6E (hex) FAR SYSTEMS S.p.A. - 00E06E (base 16) FAR SYSTEMS S.p.A. - VIA F. ZENI 8 - 3868 ROVERETO (TN) - ITALY - - 00-E0-6F (hex) ARRIS Group, Inc. - 00E06F (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 00-E0-70 (hex) DH TECHNOLOGY - 00E070 (base 16) DH TECHNOLOGY - 3003 ROLLIE GATES DRIVE - PASO ROBLES CA 93446 - UNITED STATES - - 00-E0-71 (hex) EPIS MICROCOMPUTER - 00E071 (base 16) EPIS MICROCOMPUTER - 72458 ALBSTADT - LAUTLINGER STRASSE 147 - 72458 ALBSTADT - GERMANY - - 00-E0-72 (hex) LYNK - 00E072 (base 16) LYNK - RABIN BUILDING - TERADION INDUSTRIAL PARK - D.N. MISGAV 201 - ISRAEL - - 00-E0-73 (hex) NATIONAL AMUSEMENT NETWORK, INC. - 00E073 (base 16) NATIONAL AMUSEMENT NETWORK, INC. - 401 N. MICHIGAN AVENUE - CHICAGO IL 60611 - UNITED STATES - - 00-E0-74 (hex) TIERNAN COMMUNICATIONS, INC. - 00E074 (base 16) TIERNAN COMMUNICATIONS, INC. - 11025 ROSELLE ST. - SAN DIEGO CA 92121 - UNITED STATES - - 00-E0-75 (hex) Verilink Corporation - 00E075 (base 16) Verilink Corporation - 127 Jetplex Circle - Madison AL 35758 - UNITED STATES - - 00-E0-76 (hex) DEVELOPMENT CONCEPTS, INC. - 00E076 (base 16) DEVELOPMENT CONCEPTS, INC. - 1000 N. BROAD STREET - LANSDALE PA 19446 - UNITED STATES - - 00-E0-77 (hex) WEBGEAR, INC. - 00E077 (base 16) WEBGEAR, INC. - 1263 OAKMEAD PKWY - SUNNYVALE CA 94080 - UNITED STATES - - 00-E0-78 (hex) BERKELEY NETWORKS - 00E078 (base 16) BERKELEY NETWORKS - 683 RIVER OAKS PARKWAY - SAN JOSE CA 95134 - UNITED STATES - - 00-E0-79 (hex) A.T.N.R. - 00E079 (base 16) A.T.N.R. - BP 966 - 91976 COURTABOEUF - FRANCE - - 00-E0-7A (hex) MIKRODIDAKT AB - 00E07A (base 16) MIKRODIDAKT AB - Skiffervägen 48 - LUND SE22478 - SWEDEN - - 00-E0-7B (hex) BAY NETWORKS - 00E07B (base 16) BAY NETWORKS - 125 NAGOG PARK - ACTON MA 01720 - UNITED STATES - - 00-E0-7C (hex) METTLER-TOLEDO, INC. - 00E07C (base 16) METTLER-TOLEDO, INC. - 1150 DEARBORN DRIVE - WORTHINGTON OH 43085 - UNITED STATES - - 00-E0-7D (hex) NETRONIX, INC. - 00E07D (base 16) NETRONIX, INC. - 340 THOR PLACE - BREA CA 92821 - UNITED STATES - - 00-E0-7E (hex) WALT DISNEY IMAGINEERING - 00E07E (base 16) WALT DISNEY IMAGINEERING - 1401 FLOWER ST. - GLENDALE CA 91221 - UNITED STATES - - 00-E0-7F (hex) LOGISTISTEM s.r.l. - 00E07F (base 16) LOGISTISTEM s.r.l. - VIA PANCIATICHI 94/18 - 50127 FIRENZE - ITALY - - 00-E0-80 (hex) CONTROL RESOURCES CORPORATION - 00E080 (base 16) CONTROL RESOURCES CORPORATION - 16-00 POLLITT DRIVE - FAIR LAWN NJ 07410 - UNITED STATES - - 00-E0-81 (hex) TYAN COMPUTER CORP. - 00E081 (base 16) TYAN COMPUTER CORP. - 3288 LAUREVIEW CT - FREMONT CA 95035 - UNITED STATES - - 00-E0-82 (hex) ANERMA - 00E082 (base 16) ANERMA - SCHAAPSDRIES 25 - 2260 WESTERLO - BELGIUM - - 00-E0-83 (hex) JATO TECHNOLOGIES, INC. - 00E083 (base 16) JATO TECHNOLOGIES, INC. - 505 EAST HUNTLAND DR. STE #550 - AUSTIN TX 78752 - UNITED STATES - - 00-E0-84 (hex) COMPULITE R&D - 00E084 (base 16) COMPULITE R&D - 3 HAROSHET STR. NEW IND. ZONE - RAMAT-HASHARON 47279 - ISRAEL - - 00-E0-85 (hex) GLOBAL MAINTECH, INC. - 00E085 (base 16) GLOBAL MAINTECH, INC. - 6468 CITY WEST PARKWAY - EDEN PRAIRIE MN 55344 - UNITED STATES - - 00-E0-86 (hex) Emerson Network Power, Avocent Division - 00E086 (base 16) Emerson Network Power, Avocent Division - 4991 Corporate Drive - HUNTSVILLE AL 35805 - UNITED STATES - - 00-E0-87 (hex) LeCroy - Networking Productions Division - 00E087 (base 16) LeCroy - Networking Productions Division - 25 BURLINGTON MALL ROAD - BURLINGTON MA 01803 - UNITED STATES - - 00-E0-88 (hex) LTX-Credence CORPORATION - 00E088 (base 16) LTX-Credence CORPORATION - 825 UNIVERSITY AVENUE - NORWOOD MA 02062-2643 - UNITED STATES - - 00-E0-89 (hex) ION Networks, Inc. - 00E089 (base 16) ION Networks, Inc. - 1551 South Washington Ave. - Piscataway NJ 08854 - UNITED STATES - - 00-E0-8A (hex) GEC AVERY, LTD. - 00E08A (base 16) GEC AVERY, LTD. - FOUNDRY LANE - SMETHWICK, WARLEY - WEST MIDLANDS, B66 2LP England - UNITED KINGDOM - - 00-E0-8B (hex) QLogic Corp. - 00E08B (base 16) QLogic Corp. - 26600 Laguna Hills Dr. - Aliso Viejo CA 92656 - UNITED STATES - - 00-E0-8C (hex) NEOPARADIGM LABS, INC. - 00E08C (base 16) NEOPARADIGM LABS, INC. - 1735 N. FIRST ST., STE #108 - SAN JOSE CA 95112 - UNITED STATES - - 00-E0-8D (hex) PRESSURE SYSTEMS, INC. - 00E08D (base 16) PRESSURE SYSTEMS, INC. - 34 RESEARCH DRIVE - HAMPTON VA 23666 - UNITED STATES - - 00-E0-8E (hex) UTSTARCOM - 00E08E (base 16) UTSTARCOM - 33 WOOD AVE. SOUTH - ISELIN NJ 08830 - UNITED STATES - - 00-E0-8F (hex) CISCO SYSTEMS, INC. - 00E08F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-90 (hex) BECKMAN LAB. AUTOMATION DIV. - 00E090 (base 16) BECKMAN LAB. AUTOMATION DIV. - 90 BOROLINE ROAD - ALLENDALE NJ 07401 - UNITED STATES - - 00-E0-91 (hex) LG ELECTRONICS, INC. - 00E091 (base 16) LG ELECTRONICS, INC. - 16, WOOMYEON-DONG, - SEOCHO-GU, SEOUL, 137-140, - KOREA, REPUBLIC OF - - 00-E0-92 (hex) ADMTEK INCORPORATED - 00E092 (base 16) ADMTEK INCORPORATED - 1962 ZANKER ROAD - SAN JOSE CA 95112 - UNITED STATES - - 00-E0-93 (hex) ACKFIN NETWORKS - 00E093 (base 16) ACKFIN NETWORKS - 575 N. PASTORIA AVE. - SUNNYVALE CA 94086 - UNITED STATES - - 00-E0-94 (hex) OSAI SRL - 00E094 (base 16) OSAI SRL - VIA TORINO - 603-IVREA (TO) - ITALY - - 00-E0-95 (hex) ADVANCED-VISION TECHNOLGIES CORP. - 00E095 (base 16) ADVANCED-VISION TECHNOLGIES CORP. - 8F-1, 87 SECTION 3, CHUNG YANG RD, - Tu Cheng Taipei - TAIWAN, PROVINCE OF CHINA - - 00-E0-96 (hex) SHIMADZU CORPORATION - 00E096 (base 16) SHIMADZU CORPORATION - 1, NISHINOKYO-KUWABARACHO - NAKAGYO-KU, KYOTO 604 - JAPAN - - 00-E0-97 (hex) CARRIER ACCESS CORPORATION - 00E097 (base 16) CARRIER ACCESS CORPORATION - 5395 PEARL PARKWAY - BOULDER CO 80301 - UNITED STATES - - 00-E0-98 (hex) AboCom Systems, Inc. - 00E098 (base 16) AboCom Systems, Inc. - 12F-3, NO. 333, SEC. 1 - GUAN-FU ROAD - HSIN-CHU - TAIWAN, PROVINCE OF CHINA - - 00-E0-99 (hex) SAMSON AG - 00E099 (base 16) SAMSON AG - WEISMULLERSTR. 3 - D-60314 FRANKFURT - GERMANY - - 00-E0-9A (hex) Positron Inc. - 00E09A (base 16) Positron Inc. - 5101 Buchan Street - Suite 220 - Montreal, Québec H4P 2R9 - CANADA - - 00-E0-9B (hex) ENGAGE NETWORKS, INC. - 00E09B (base 16) ENGAGE NETWORKS, INC. - 316 N. MILWAUKEE ST., STE.#214 - MILWAUKEE WI 53202 - UNITED STATES - - 00-E0-9C (hex) MII - 00E09C (base 16) MII - LE parc du MOULIN - 2, grande rue Prolongee - F95650 PUISEUX-POTOISE - FRANCE - - 00-E0-9D (hex) SARNOFF CORPORATION - 00E09D (base 16) SARNOFF CORPORATION - CN 5300 - PRINCETON NJ 08543-5300 - UNITED STATES - - 00-E0-9E (hex) QUANTUM CORPORATION - 00E09E (base 16) QUANTUM CORPORATION - 500 McCarthy Boulevard - Milpitas CA 95035 - UNITED STATES - - 00-E0-9F (hex) PIXEL VISION - 00E09F (base 16) PIXEL VISION - 43 NAGOG PARK - ACTON MA 01720 - UNITED STATES - - 00-E0-A0 (hex) WILTRON CO. - 00E0A0 (base 16) WILTRON CO. - 490 JARVIS DRIVE - MORGAN HILL CA 95037 - UNITED STATES - - 00-E0-A1 (hex) HIMA PAUL HILDEBRANDT GmbH Co. KG - 00E0A1 (base 16) HIMA PAUL HILDEBRANDT GmbH Co. KG - - POSTBOX 1261 - D-68777 BRUEHL NEAR MANNHEIM - GERMANY - - 00-E0-A2 (hex) MICROSLATE INC. - 00E0A2 (base 16) MICROSLATE INC. - 9625 IGNACE - STE. D - BROSSARD QC J4Y 2P3 - CANADA - - 00-E0-A3 (hex) CISCO SYSTEMS, INC. - 00E0A3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-A4 (hex) ESAOTE S.p.A. - 00E0A4 (base 16) ESAOTE S.p.A. - via di CACIOLLE, 15 - 50127 FLORENCE - ITALY - - 00-E0-A5 (hex) ComCore Semiconductor, Inc. - 00E0A5 (base 16) ComCore Semiconductor, Inc. - 4505 LAS VIRGENES, Suite 202 - CALABASAS CA 91302 - UNITED STATES - - 00-E0-A6 (hex) TELOGY NETWORKS, INC. - 00E0A6 (base 16) TELOGY NETWORKS, INC. - 20250 CENTURY BLVD. - GERMANTOWN MD 20874 - UNITED STATES - - 00-E0-A7 (hex) IPC INFORMATION SYSTEMS, INC. - 00E0A7 (base 16) IPC INFORMATION SYSTEMS, INC. - METRO CENTER - ONE STATION PLACE - STAMFORD CT 06907 - UNITED STATES - - 00-E0-A8 (hex) SAT GmbH & Co. - 00E0A8 (base 16) SAT GmbH & Co. - RUTHNERGASSE 1 - VIENNA A-1210 - AUSTRIA - - 00-E0-A9 (hex) FUNAI ELECTRIC CO., LTD. - 00E0A9 (base 16) FUNAI ELECTRIC CO., LTD. - 7-1, NAKAGAITO 7-CHOME, DAITO - OSAKA 574 - JAPAN - - 00-E0-AA (hex) ELECTROSONIC LTD. - 00E0AA (base 16) ELECTROSONIC LTD. - HAWLEY MILL, HAWLEY RD. - DARTFORD, KENT DA2 7SY - UNITED KINGDOM - - 00-E0-AB (hex) DIMAT S.A. - 00E0AB (base 16) DIMAT S.A. - C/BISCAIA 383 3 - 08023 BARCELONA - SPAIN - - 00-E0-AC (hex) MIDSCO, INC. - 00E0AC (base 16) MIDSCO, INC. - 710 ROUTE 46 EAST - FAIRFIELD NJ 07004 - UNITED STATES - - 00-E0-AD (hex) EES TECHNOLOGY, LTD. - 00E0AD (base 16) EES TECHNOLOGY, LTD. - 25 EASTWAYS - WITHAM, ESSEX, CM8 3AL - UNITED KINGDOM - - 00-E0-AE (hex) XAQTI CORPORATION - 00E0AE (base 16) XAQTI CORPORATION - 1630 OAKLAND RD. #A-214 - SAN JOSE CA 95131 - UNITED STATES - - 00-E0-AF (hex) GENERAL DYNAMICS INFORMATION SYSTEMS - 00E0AF (base 16) GENERAL DYNAMICS INFORMATION SYSTEMS - COMPUTING DEVICES, LTD. - 3190 FAIRVIEW PA - FALLS CHURCH VA 22042-4523 - UNITED STATES - - 00-E0-B0 (hex) CISCO SYSTEMS, INC. - 00E0B0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-B1 (hex) Alcatel-Lucent, Enterprise Business Group - 00E0B1 (base 16) Alcatel-Lucent, Enterprise Business Group - 26801 West Agoura Road - Calabasas CA 91301 - UNITED STATES - - 00-E0-B2 (hex) TELMAX COMMUNICATIONS CORP. - 00E0B2 (base 16) TELMAX COMMUNICATIONS CORP. - 46515 LANDING PARKWAY - FREMONT CA 94538 - UNITED STATES - - 00-E0-B3 (hex) EtherWAN Systems, Inc. - 00E0B3 (base 16) EtherWAN Systems, Inc. - 14 HUGHES, STE.B-105 - IRVINE CA 92618 - UNITED STATES - - 00-E0-B4 (hex) TECHNO SCOPE CO., LTD. - 00E0B4 (base 16) TECHNO SCOPE CO., LTD. - 13-6-7 KISHIMATI URAWASI - SAITAMA 336 - JAPAN - - 00-E0-B5 (hex) ARDENT COMMUNICATIONS CORP. - 00E0B5 (base 16) ARDENT COMMUNICATIONS CORP. - 3801 ZANKER ROAD, Suite A - SAN JOSE CA 95134 - UNITED STATES - - 00-E0-B6 (hex) Entrada Networks - 00E0B6 (base 16) Entrada Networks - 9020 JUNCTION DRIVE - ANNAPOLIS JUNCTION MD 20701 - UNITED STATES - - 00-E0-B7 (hex) PI GROUP, LTD. - 00E0B7 (base 16) PI GROUP, LTD. - MILTON HALL, CHURCH LANE - MILTON, CAMBRIDGE CBA 6AB - UNITED KINGDOM - - 00-E0-B8 (hex) GATEWAY 2000 - 00E0B8 (base 16) GATEWAY 2000 - 610 GATEWAY DRIVE - N. SIOUX CITY SD 57049 - UNITED STATES - - 00-E0-B9 (hex) BYAS SYSTEMS - 00E0B9 (base 16) BYAS SYSTEMS - 2250 MONROE STREET, #371 - SANTA CLARA CA 95050 - UNITED STATES - - 00-E0-BA (hex) BERGHOF AUTOMATIONSTECHNIK GmbH - 00E0BA (base 16) BERGHOF AUTOMATIONSTECHNIK GmbH - HARRET STRASSE 1 - D 72800 ENINGEN - GERMANY - - 00-E0-BB (hex) NBX CORPORATION - 00E0BB (base 16) NBX CORPORATION - 100 BRICKSTONE SQUARE - ANDOVER MA 01810 - UNITED STATES - - 00-E0-BC (hex) SYMON COMMUNICATIONS, INC. - 00E0BC (base 16) SYMON COMMUNICATIONS, INC. - 10701 CORPORATE DR.-STE. #290 - STAFFORD TX 77477 - UNITED STATES - - 00-E0-BD (hex) INTERFACE SYSTEMS, INC. - 00E0BD (base 16) INTERFACE SYSTEMS, INC. - 5855 INTERFACE DRIVE - ANN ARBOR MI 48103-9515 - UNITED STATES - - 00-E0-BE (hex) GENROCO INTERNATIONAL, INC. - 00E0BE (base 16) GENROCO INTERNATIONAL, INC. - 255 ENDERS COURT - SLINGER WI 53086 - UNITED STATES - - 00-E0-BF (hex) TORRENT NETWORKING TECHNOLOGIES CORP. - 00E0BF (base 16) TORRENT NETWORKING TECHNOLOGIES CORP. - 8181 PROFESSIONAL PLACE - SUITE #160 - LANDOVER MD 20785 - UNITED STATES - - 00-E0-C0 (hex) SEIWA ELECTRIC MFG. CO., LTD. - 00E0C0 (base 16) SEIWA ELECTRIC MFG. CO., LTD. - 86 TARADA SHIN-IKE, - JOYO, - KYOTO PREFECTURE - JAPAN - - 00-E0-C1 (hex) MEMOREX TELEX JAPAN, LTD. - 00E0C1 (base 16) MEMOREX TELEX JAPAN, LTD. - YAESUGUCHI KAIKAN, 1-7-20 - YAESU, CHUO-KU - TOKYO 103 - JAPAN - - 00-E0-C2 (hex) NECSY S.p.A. - 00E0C2 (base 16) NECSY S.p.A. - VIA LISBONA 28 - 35020 PADOVA - ITALY - - 00-E0-C3 (hex) SAKAI SYSTEM DEVELOPMENT CORP. - 00E0C3 (base 16) SAKAI SYSTEM DEVELOPMENT CORP. - PORTUS CENTER BLD., 4-45-1 - EBISUJIMA-CHO, SAKAI-CITY - OSAKA-FU, 590 - JAPAN - - 00-E0-C4 (hex) HORNER ELECTRIC, INC. - 00E0C4 (base 16) HORNER ELECTRIC, INC. - 1521 E. WASHINGTON ST. - INDIANAPOLIS IN 46201 - UNITED STATES - - 00-E0-C5 (hex) BCOM ELECTRONICS INC. - 00E0C5 (base 16) BCOM ELECTRONICS INC. - 8 FL, NO. 64, AN HO ROAD, SEC. 2 - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-E0-C6 (hex) LINK2IT, L.L.C. - 00E0C6 (base 16) LINK2IT, L.L.C. - 4256 BECK AVENUE - STUDIO CITY CA 91604 - UNITED STATES - - 00-E0-C7 (hex) EUROTECH SRL - 00E0C7 (base 16) EUROTECH SRL - VIA JACOPO LINUSSIO 1 - 33030 AMAROO (UD) - ITALY - - 00-E0-C8 (hex) VIRTUAL ACCESS, LTD. - 00E0C8 (base 16) VIRTUAL ACCESS, LTD. - WOODSIDE HOUSE, WINKFIELD, - WINDSOR, BERKSHIRE SL4 2DX ENGLAND - UNITED KINGDOM - - 00-E0-C9 (hex) AutomatedLogic Corporation - 00E0C9 (base 16) AutomatedLogic Corporation - 1150 ROBERTS BOULEVARD - KENNESAW GA 30144-3618 - UNITED STATES - - 00-E0-CA (hex) BEST DATA PRODUCTS - 00E0CA (base 16) BEST DATA PRODUCTS - 21800 NORDHOFF STREET - CHATSWORTH CA 91311 - UNITED STATES - - 00-E0-CB (hex) RESON, INC. - 00E0CB (base 16) RESON, INC. - 300 LOPEZ ROAD - GOLETA CA 93117 - UNITED STATES - - 00-E0-CC (hex) HERO SYSTEMS, LTD. - 00E0CC (base 16) HERO SYSTEMS, LTD. - THE BARNES, COOMBELANDS LANE, - ADDLESTONE, WEYBRIDGE - SURREY KT15 1HY England - UNITED KINGDOM - - 00-E0-CD (hex) SAAB SENSIS CORPORATION - 00E0CD (base 16) SAAB SENSIS CORPORATION - 85 Collamer Crossings - East Syracuse NY 13057 - UNITED STATES - - 00-E0-CE (hex) ARN - 00E0CE (base 16) ARN - 51, RUE GASTON LAURIAU - F-93512 MONTREUIL CEDEX - FRANCE - - 00-E0-CF (hex) INTEGRATED DEVICE TECHNOLOGY, INC. - 00E0CF (base 16) INTEGRATED DEVICE TECHNOLOGY, INC. - 6024 Silver Creek Valley Road - San Jose CA 95138 - UNITED STATES - - 00-E0-D0 (hex) NETSPEED, INC. - 00E0D0 (base 16) NETSPEED, INC. - 12303 TECHNOLOGY BLVD. - AUSTIN TX 78727 - UNITED STATES - - 00-E0-D1 (hex) TELSIS LIMITED - 00E0D1 (base 16) TELSIS LIMITED - 16 BARNES WALLACE ROAD - FAREHAM, HAMPSHIRE PO15 5TT ENGLAND - UNITED KINGDOM - - 00-E0-D2 (hex) VERSANET COMMUNICATIONS, INC. - 00E0D2 (base 16) VERSANET COMMUNICATIONS, INC. - 628 N. DIAMOND BAR BLVD. - DIAMOND BAR CA 91765 - UNITED STATES - - 00-E0-D3 (hex) DATENTECHNIK GmbH - 00E0D3 (base 16) DATENTECHNIK GmbH - THERESIANUMGASSE 11 - A-1040 WIEN - AUSTRIA - - 00-E0-D4 (hex) EXCELLENT COMPUTER - 00E0D4 (base 16) EXCELLENT COMPUTER - 551, M.K.N. ROAD - ALANDUR, CHENNAI 600016 - INDIA - - 00-E0-D5 (hex) Emulex Corporation - 00E0D5 (base 16) Emulex Corporation - 3333 Susan Street - Costa Mesa CA 92626 - UNITED STATES - - 00-E0-D6 (hex) COMPUTER & COMMUNICATION RESEARCH LAB. - 00E0D6 (base 16) COMPUTER & COMMUNICATION RESEARCH LAB. - - 195 SEC.4, CHUNG HSING RD - CHUTUNG, HSINCHU - TAIWAN, PROVINCE OF CHINA - - 00-E0-D7 (hex) SUNSHINE ELECTRONICS, INC. - 00E0D7 (base 16) SUNSHINE ELECTRONICS, INC. - 46560 FREMONT BLVD. -STE. #113 - FREMONT CA 94538 - UNITED STATES - - 00-E0-D8 (hex) LANBit Computer, Inc. - 00E0D8 (base 16) LANBit Computer, Inc. - 12F, 552 CHUNG HSIAO E., RD. - SEC. 5, TAIPEI 110 - TAIWAN, PROVINCE OF CHINA - - 00-E0-D9 (hex) TAZMO CO., LTD. - 00E0D9 (base 16) TAZMO CO., LTD. - 6186 KINOKO, IBARA-SHI - OKAYAMA 715 - JAPAN - - 00-E0-DA (hex) Alcatel North America ESD - 00E0DA (base 16) Alcatel North America ESD - 26801 West Agoura Road - Calabasas CA 91301 - UNITED STATES - - 00-E0-DB (hex) ViaVideo Communications, Inc. - 00E0DB (base 16) ViaVideo Communications, Inc. - 8900 SHOAL CREEK BLVD. - BLDG. #300 - AUSTIN TX 78757 - UNITED STATES - - 00-E0-DC (hex) NEXWARE CORP. - 00E0DC (base 16) NEXWARE CORP. - 825 STEWART DR., STE #4 - SUNNYVALE CA 94086 - UNITED STATES - - 00-E0-DD (hex) ZENITH ELECTRONICS CORPORATION - 00E0DD (base 16) ZENITH ELECTRONICS CORPORATION - 1000 MILWAUKEE AVENUE - GLENVIEW IL 60025 - UNITED STATES - - 00-E0-DE (hex) DATAX NV - 00E0DE (base 16) DATAX NV - RINGLAAN 51 - B-2600 BERCHEM - BELGIUM - - 00-E0-DF (hex) KEYMILE GmbH - 00E0DF (base 16) KEYMILE GmbH - Wohlenbergstraße 3 - 30179 Hannover - GERMANY - - 00-E0-E0 (hex) SI ELECTRONICS, LTD. - 00E0E0 (base 16) SI ELECTRONICS, LTD. - 28-16, SHIMOMARUKO 2-CHOME, - TOKYO 146 - JAPAN - - 00-E0-E1 (hex) G2 NETWORKS, INC. - 00E0E1 (base 16) G2 NETWORKS, INC. - 142 SO. SANTA CRUZ AVE. - LOS GATOS CA 95030-6702 - UNITED STATES - - 00-E0-E2 (hex) INNOVA CORP. - 00E0E2 (base 16) INNOVA CORP. - 3325 SOUTH 116TH STREET - SEATTLE WA 98168 - UNITED STATES - - 00-E0-E3 (hex) SK-ELEKTRONIK GmbH - 00E0E3 (base 16) SK-ELEKTRONIK GmbH - HEMMELRATHERWEG 201 - 51377 LEVERKUSEN - GERMANY - - 00-E0-E4 (hex) FANUC ROBOTICS NORTH AMERICA, Inc. - 00E0E4 (base 16) FANUC ROBOTICS NORTH AMERICA, Inc. - 3900 W. HAMLIN RD. - ROCHESTER HILLS MI 48309-3253 - UNITED STATES - - 00-E0-E5 (hex) CINCO NETWORKS, INC. - 00E0E5 (base 16) CINCO NETWORKS, INC. - 6601 KOLL CENTER PARK WAY - SUITE #140 - PLEASANTON CA 94566 - UNITED STATES - - 00-E0-E6 (hex) INCAA DATACOM B.V. - 00E0E6 (base 16) INCAA DATACOM B.V. - P.O. BOX 211 - 7300 AE APELDOORN - NETHERLANDS - - 00-E0-E7 (hex) RAYTHEON E-SYSTEMS, INC. - 00E0E7 (base 16) RAYTHEON E-SYSTEMS, INC. - 1301 E. COLLINS - RICHARDSON TX 75081 - UNITED STATES - - 00-E0-E8 (hex) GRETACODER Data Systems AG - 00E0E8 (base 16) GRETACODER Data Systems AG - ALTHARDSTRASSE 150 - CH-8105 REGENSDORF - SWITZERLAND - - 00-E0-E9 (hex) DATA LABS, INC. - 00E0E9 (base 16) DATA LABS, INC. - 444 NORTH FREDERICK AVE. - SUITE #240 - GAITHERSBURG MD 20877 - UNITED STATES - - 00-E0-EA (hex) INNOVAT COMMUNICATIONS, INC. - 00E0EA (base 16) INNOVAT COMMUNICATIONS, INC. - 1257 N. PLANO ROAD - RICHARDSON TX 75081 - UNITED STATES - - 00-E0-EB (hex) DIGICOM SYSTEMS, INCORPORATED - 00E0EB (base 16) DIGICOM SYSTEMS, INCORPORATED - 188 TOPAZ STREET - MILPITAS CA 95035 - UNITED STATES - - 00-E0-EC (hex) CELESTICA INC. - 00E0EC (base 16) CELESTICA INC. - 844 DON MILLS ROAD - NORTH YORK ONTARIO M3C 1V7 - CANADA - - 00-E0-ED (hex) SILICOM, LTD. - 00E0ED (base 16) SILICOM, LTD. - 8 HANAGER ST. - P.O. BOX 2164 - KFAR-SAVA 44000 - ISRAEL - - 00-E0-EE (hex) MAREL HF - 00E0EE (base 16) MAREL HF - Austurhraun 9 - Gardabaer 210 - ICELAND - - 00-E0-EF (hex) DIONEX - 00E0EF (base 16) DIONEX - PO BOX 3603 - SUNNYVALE CA 94088-3603 - UNITED STATES - - 00-E0-F0 (hex) ABLER TECHNOLOGY, INC. - 00E0F0 (base 16) ABLER TECHNOLOGY, INC. - 4F, NO. 54 SEC. 4 - MIN-SHENG E. RD. - TAIPEI - TAIWAN, PROVINCE OF CHINA - - 00-E0-F1 (hex) THAT CORPORATION - 00E0F1 (base 16) THAT CORPORATION - 734 FOREST STREET - MARLBOROUGH MA 01752 - UNITED STATES - - 00-E0-F2 (hex) ARLOTTO COMNET, INC. - 00E0F2 (base 16) ARLOTTO COMNET, INC. - 7F-4,55,TUNG-KUANG ROAD - HSIN-CHU, 300 - TAIWAN, PROVINCE OF CHINA - - 00-E0-F3 (hex) WebSprint Communications, Inc. - 00E0F3 (base 16) WebSprint Communications, Inc. - 3026 SCOTT BLVD. - SANTA CLARA CA 95054 - UNITED STATES - - 00-E0-F4 (hex) INSIDE Technology A/S - 00E0F4 (base 16) INSIDE Technology A/S - VENLIGHEDSVEJ 6 - DK-2970 HOERSHOLM - DENMARK - - 00-E0-F5 (hex) TELES AG - 00E0F5 (base 16) TELES AG - DOVESTR. 2-4 - 10587 BERLIN - GERMANY - - 00-E0-F6 (hex) DECISION EUROPE - 00E0F6 (base 16) DECISION EUROPE - 3, rue de Lattre de Tassigny - 85170 SAINT DENIS LA CHEVASSE - FRANCE - - 00-E0-F7 (hex) CISCO SYSTEMS, INC. - 00E0F7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-F8 (hex) DICNA CONTROL AB - 00E0F8 (base 16) DICNA CONTROL AB - STENYXEGATAN 21 C - 213 76 MALMOE - SWEDEN - - 00-E0-F9 (hex) CISCO SYSTEMS, INC. - 00E0F9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-FA (hex) TRL TECHNOLOGY, LTD. - 00E0FA (base 16) TRL TECHNOLOGY, LTD. - SHANNON WAY, ASHCHURCH, - TEWKESBURY, GLOS. GL20 8ND - UNITED KINGDOM - - 00-E0-FB (hex) LEIGHTRONIX, INC. - 00E0FB (base 16) LEIGHTRONIX, INC. - 2330 JARCO DR. - HOLT MI 48842 - UNITED STATES - - 00-E0-FC (hex) HUAWEI TECHNOLOGIES CO., LTD. - 00E0FC (base 16) HUAWEI TECHNOLOGIES CO., LTD. - KEFA ROAD, SCIENCE-BASED INDUSTRIAL PARK - NANSHAN DISTRICT, - SHENZHEN 518057 - CHINA - - 00-E0-FD (hex) A-TREND TECHNOLOGY CO., LTD. - 00E0FD (base 16) A-TREND TECHNOLOGY CO., LTD. - 10F, NO. 75, HSIN TAI WU RD., - SEC. 1, HSI CHIH, - TAIPEI HSIEN 221 - TAIWAN, PROVINCE OF CHINA - - 00-E0-FE (hex) CISCO SYSTEMS, INC. - 00E0FE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - SAN JOSE CA 95134-1706 - UNITED STATES - - 00-E0-FF (hex) SECURITY DYNAMICS TECHNOLOGIES, Inc. - 00E0FF (base 16) SECURITY DYNAMICS TECHNOLOGIES, Inc. - 20 CROSBY DRIVE - BEDFORD MA 01730 - UNITED STATES - - 00-E1-6D (hex) Cisco - 00E16D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 00-E1-75 (hex) AK-Systems Ltd - 00E175 (base 16) AK-Systems Ltd - off 62, 27/29 Pavlovskaya str. - Moscow 115093 - RUSSIAN FEDERATION - - 00-E3-B2 (hex) Samsung Electronics Co.,Ltd - 00E3B2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-E6-66 (hex) ARIMA Communications Corp. - 00E666 (base 16) ARIMA Communications Corp. - 6F.,No.866,Zhongzheng Rd.,Zhonghe Dist., - New Taipei City Taiwan 23586 - TAIWAN, PROVINCE OF CHINA - - 00-E6-D3 (hex) NIXDORF COMPUTER CORP. - 00E6D3 (base 16) NIXDORF COMPUTER CORP. - 2520 MISSION COLLEGE ROAD - SANTA CLARA CA 95054 - UNITED STATES - - 00-E6-E8 (hex) Netzin Technology Corporation,.Ltd. - 00E6E8 (base 16) Netzin Technology Corporation,.Ltd. - 4F-17, No. 26, Lane 321, Yang-Kuang St.,Neihu District, Taipei, Taiwan, - Taiwan Taipei Taiwan Taipei 11491 - TAIWAN, PROVINCE OF CHINA - - 00-E8-AB (hex) Meggitt Training Systems, Inc. - 00E8AB (base 16) Meggitt Training Systems, Inc. - 296 Brogdon Rd - Suwanee GA 30024 - UNITED STATES - - 00-EB-2D (hex) Sony Mobile Communications AB - 00EB2D (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 00-EE-BD (hex) HTC Corporation - 00EEBD (base 16) HTC Corporation - No. 23, Xinghua Rd, Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - 00-F0-51 (hex) KWB Gmbh - 00F051 (base 16) KWB Gmbh - Industriestraße 235 - St. Margarethen Styria 8321 - AUSTRIA - - 00-F3-DB (hex) WOO Sports - 00F3DB (base 16) WOO Sports - 11 Elkins St. - Suite 230 - BOSTON Massachusetts 02127 - UNITED STATES - - 00-F4-03 (hex) Orbis Systems Oy - 00F403 (base 16) Orbis Systems Oy - Taivaltie 5 - Vantaa 01610 - FINLAND - - 00-F4-6F (hex) Samsung Elec Co.,Ltd - 00F46F (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 00-F4-B9 (hex) Apple - 00F4B9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-F7-6F (hex) Apple - 00F76F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 00-F8-60 (hex) PT. Panggung Electric Citrabuana - 00F860 (base 16) PT. Panggung Electric Citrabuana - Jl. Raya Waru no. 1 - Sidoarjo Jawa Timur 61256 - INDONESIA - - 00-FA-3B (hex) CLOOS ELECTRONIC GMBH - 00FA3B (base 16) CLOOS ELECTRONIC GMBH - Jambe ducommun 8 - LE LOCLE 2400 - SWITZERLAND - - 00-FC-58 (hex) WebSilicon Ltd. - 00FC58 (base 16) WebSilicon Ltd. - 25, Habarzel St., - Tel-Aviv 69710 - ISRAEL - - 00-FC-70 (hex) Intrepid Control Systems, Inc. - 00FC70 (base 16) Intrepid Control Systems, Inc. - 31601 Research Park Dr. - Madison Heights MI 48071 - UNITED STATES - - 00-FC-8D (hex) Hitron Technologies. Inc - 00FC8D (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd - Hsinchu Science Park - Hsin-chu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 00-FD-4C (hex) NEVATEC - 00FD4C (base 16) NEVATEC - Lindaraja 2 - Granada 18009 - SPAIN - - 02-07-01 (hex) RACAL-DATACOM - 020701 (base 16) RACAL-DATACOM - LAN INTERNETWORKING DIVISION - 155 SWANSON ROAD - BOXBOROUGH MA 01719 - UNITED STATES - - 02-1C-7C (hex) PERQ SYSTEMS CORPORATION - 021C7C (base 16) PERQ SYSTEMS CORPORATION - 2600 LIBERTY AVENUE - P.O. BOX 2600 - PITTSBURGH PA 15230 - UNITED STATES - - 02-60-86 (hex) LOGIC REPLACEMENT TECH. LTD. - 026086 (base 16) LOGIC REPLACEMENT TECH. LTD. - 14 ARKWRIGHT ROAD - READING BERKS RG2OLS - UNITED KINGDOM - UNITED KINGDOM - - 02-60-8C (hex) 3COM CORPORATION - 02608C (base 16) 3COM CORPORATION - 2081 N. SHORLINE BLVD. - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 02-70-01 (hex) RACAL-DATACOM - 027001 (base 16) RACAL-DATACOM - LAN INTERNETWORKING DIVISION - 155 SWANSON ROAD - BOXBOROUGH MA 01719 - UNITED STATES - - 02-70-B0 (hex) M/A-COM INC. COMPANIES - 0270B0 (base 16) M/A-COM INC. COMPANIES - 11717 EXPLORATION LANE - GERMANTOWN MD 20767 - UNITED STATES - - 02-70-B3 (hex) DATA RECALL LTD - 0270B3 (base 16) DATA RECALL LTD - SONDES PLACE - DORKING SURREY RH4 3EF - UNITED KINGDOM - UNITED KINGDOM - - 02-9D-8E (hex) CARDIAC RECORDERS INC. - 029D8E (base 16) CARDIAC RECORDERS INC. - 34 SCARBORO RD - LONDON N4 4L U - UNITED KINGDOM - UNITED KINGDOM - - 02-AA-3C (hex) OLIVETTI TELECOMM SPA (OLTECO) - 02AA3C (base 16) OLIVETTI TELECOMM SPA (OLTECO) - 20300 STEVENS CREEK BLVD. - CUPERTINO CA 95014 - UNITED STATES - - 02-BB-01 (hex) OCTOTHORPE CORP. - 02BB01 (base 16) OCTOTHORPE CORP. - 285 WEST GREEN STREET - PASADENA CA 91105 - UNITED STATES - - 02-C0-8C (hex) 3COM CORPORATION - 02C08C (base 16) 3COM CORPORATION - 5400 BAYFRONT PLAZA - P.O. BOX 58145 - SANTA CLARA CA 95052 - UNITED STATES - - 02-CF-1C (hex) COMMUNICATION MACHINERY CORP. - 02CF1C (base 16) COMMUNICATION MACHINERY CORP. - 1226 ANACAPA - SANTA BARBARA CA 93101 - UNITED STATES - - 02-E6-D3 (hex) NIXDORF COMPUTER CORPORATION - 02E6D3 (base 16) NIXDORF COMPUTER CORPORATION - NIXDORF TECHNOLOGY CENTER - 2520 MISSION COLLEGE BLVD - SANTA CLARA CA 95054 - UNITED STATES - - 04-0A-83 (hex) Alcatel-Lucent - 040A83 (base 16) Alcatel-Lucent - Via Trento, 30 - Vimenrcate MB 2059 - ITALY - - 04-0A-E0 (hex) XMIT AG COMPUTER NETWORKS - 040AE0 (base 16) XMIT AG COMPUTER NETWORKS - 11 AVENUE DE BAUMETTES - 1020 RENANS - SWITZERLAND - - 04-0C-CE (hex) Apple - 040CCE (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-0E-C2 (hex) ViewSonic Mobile China Limited - 040EC2 (base 16) ViewSonic Mobile China Limited - Room 601, The Gate Tower B, No.19, Zhongguancun Street, Haidian District - Beijing 100080 - CHINA - - 04-15-52 (hex) Apple - 041552 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-18-0F (hex) Samsung Electronics Co.,Ltd - 04180F (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 04-18-B6 (hex) PRIVATE - 0418B6 (base 16) - - 04-18-D6 (hex) Ubiquiti Networks - 0418D6 (base 16) Ubiquiti Networks - 91 E. Tasman Dr. - San Jose California 95134 - UNITED STATES - - 04-1A-04 (hex) WaveIP - 041A04 (base 16) WaveIP - 1 Sky street - Teradion Industrial Park - Misgav 20179 - ISRAEL - - 04-1B-94 (hex) Host Mobility AB - 041B94 (base 16) Host Mobility AB - Anders Personsgatan 12 - Gothenburg Vastra Gotaland 41664 - SWEDEN - - 04-1B-BA (hex) Samsung Electronics Co.,Ltd - 041BBA (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 04-1D-10 (hex) Dream Ware Inc. - 041D10 (base 16) Dream Ware Inc. - 5-23-7 Masugata, Tama-ku, - Kawasaki Kanagawa 214-0032 - JAPAN - - 04-1E-64 (hex) Apple - 041E64 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-20-9A (hex) Panasonic AVC Networks Company - 04209A (base 16) Panasonic AVC Networks Company - 1-15 Matsuo-cho - Kadoma City Osaka 571-8504 - JAPAN - - 04-22-34 (hex) Wireless Standard Extensions - 042234 (base 16) Wireless Standard Extensions - 1322 Crossman avenue - Sunnyvale California 94089 - UNITED STATES - - 04-26-05 (hex) GFR Gesellschaft für Regelungstechnik und Energieeinsparung mbH - 042605 (base 16) GFR Gesellschaft für Regelungstechnik und Energieeinsparung mbH - Kapellenweg 42 - Verl 33415 - GERMANY - - 04-26-65 (hex) Apple - 042665 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-2B-BB (hex) PicoCELA, Inc. - 042BBB (base 16) PicoCELA, Inc. - 3-8-33, Momochihama - Sawara-ku - Fukuoka-city Fukuoka 814-0001 - JAPAN - - 04-2F-56 (hex) ATOCS (Shenzhen) LTD - 042F56 (base 16) ATOCS (Shenzhen) LTD - 4/F., Building 10, Tongfuyu Industry Zone, - Shenzhen - CHINA - - 04-32-F4 (hex) Partron - 0432F4 (base 16) Partron - 22-6, Seokwoo-dong - Hwaseong-si Gyeonggi-do 445-170 - KOREA, REPUBLIC OF - - 04-36-04 (hex) Gyeyoung I&T - 043604 (base 16) Gyeyoung I&T - 6F, Woosung Bldg. 1000-1, Daechi-dong - Gangnam-gu, - Seoul 135-502 - KOREA, REPUBLIC OF - - 04-3D-98 (hex) ChongQing QingJia Electronics CO.,LTD - 043D98 (base 16) ChongQing QingJia Electronics CO.,LTD - No.1,DianCe Village JiangBei District - Chongqing city 400020 - CHINA - - 04-44-A1 (hex) TELECON GALICIA,S.A. - 0444A1 (base 16) TELECON GALICIA,S.A. - AVENIDA DE NOSTIAN - POLIGONO DE LA ARTISTICA NAVE 7 - A CORUNA 15008 - SPAIN - - 04-46-65 (hex) Murata Manufacturing Co., Ltd. - 044665 (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 04-48-9A (hex) Apple - 04489A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-4A-50 (hex) Ramaxel Technology (Shenzhen) limited company - 044A50 (base 16) Ramaxel Technology (Shenzhen) limited company - 2-5/F,North Block Southeast Industrial and Commercial Building Houhai Road,Shekou Shenzhen - shenzhen guangdong 518067 - CHINA - - 04-4B-FF (hex) GuangZhou Hedy Digital Technology Co., Ltd - 044BFF (base 16) GuangZhou Hedy Digital Technology Co., Ltd - B 701, Gaoke Building, TianHe Bei Road, - GuangZhou GuangDong 510630 - CHINA - - 04-4C-EF (hex) Fujian Sanao Technology Co.,Ltd - 044CEF (base 16) Fujian Sanao Technology Co.,Ltd - Fuzhou shibei bicyclic road no. 117 - blue building three layer - Fuzhou Fujian 350000 - CHINA - - 04-4E-06 (hex) Ericsson AB - 044E06 (base 16) Ericsson AB - Torshamnsgatan 36 - Stockholm SE-164 80 - SWEDEN - - 04-4F-8B (hex) Adapteva, Inc. - 044F8B (base 16) Adapteva, Inc. - 1666 Massachusetts Ave - Suite 14 - Lexington MA 02420 - UNITED STATES - - 04-4F-AA (hex) Ruckus Wireless - 044FAA (base 16) Ruckus Wireless - 880 West Maude Ave. - Sunnyvale CA 94085 - UNITED STATES - - 04-54-53 (hex) Apple - 045453 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-55-CA (hex) BriView (Xiamen) Corp. - 0455CA (base 16) BriView (Xiamen) Corp. - NO.1998 West of Fangshan Road,Xiang An Branch,Torch Hi-tech lndustrial Development Zone, - Xiamen city Fujian Province 361102 - CHINA - - 04-57-2F (hex) Sertel Electronics UK Ltd - 04572F (base 16) Sertel Electronics UK Ltd - Rutland House, 148 Edmund Street, - Birmingham B3 2FD - UNITED KINGDOM - - 04-58-6F (hex) Sichuan Whayer information industry Co.,LTD - 04586F (base 16) Sichuan Whayer information industry Co.,LTD - Layer 16,Building 10, C Area - Tianfu Software Park,Hi-Tech district - Chengdu City 610041 - CHINA - - 04-5A-95 (hex) Nokia Corporation - 045A95 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 04-5C-06 (hex) Zmodo Technology Corporation - 045C06 (base 16) Zmodo Technology Corporation - 1401 Interstate Dr - Champaign IL 61822 - UNITED STATES - - 04-5C-8E (hex) gosund GROUP CO.,LTD - 045C8E (base 16) gosund GROUP CO.,LTD - 11/F., FRONT BLOCK, HANG LOK BUILDING - , 130 WING LOK ST., - SHEUNG WAN, HK 999077 - HONG KONG - - 04-5D-56 (hex) camtron industrial inc. - 045D56 (base 16) camtron industrial inc. - 5F, Kuem-Ah B/D, 31-3, Karak-dong, Songpa-gu - Seoul 138-801 - KOREA, REPUBLIC OF - - 04-5F-A7 (hex) Shenzhen Yichen Technology Development Co.,LTD - 045FA7 (base 16) Shenzhen Yichen Technology Development Co.,LTD - 5/F Honghualing 2nd Industry Zone,Xili Town - Nanshan District - Shenzhen Guangdong 518055 - CHINA - - 04-61-69 (hex) MEDIA GLOBAL LINKS CO., LTD. - 046169 (base 16) MEDIA GLOBAL LINKS CO., LTD. - 580-16, Horikawa-cho - Saiwai-ku - Kawasaki Kanagawa 212-0013 - JAPAN - - 04-62-D7 (hex) ALSTOM HYDRO FRANCE - 0462D7 (base 16) ALSTOM HYDRO FRANCE - 82 Avenue Leon Blum - GRENOBLE 38041 - FRANCE - - 04-63-E0 (hex) Nome Oy - 0463E0 (base 16) Nome Oy - Lunkintie 9 - Oulunsalo Oulun lللni 90460 - FINLAND - - 04-67-85 (hex) scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH - 046785 (base 16) scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH - Gewerbeparkstr. 20 - Reichshof-Wehnrath NRW 51580 - GERMANY - - 04-6D-42 (hex) Bryston Ltd. - 046D42 (base 16) Bryston Ltd. - P.O. Box 2170 - 677 Neal Drive - Peterborough Ontario K9J 7Y4 - CANADA - - 04-6E-49 (hex) TaiYear Electronic Technology (Suzhou) Co., Ltd - 046E49 (base 16) TaiYear Electronic Technology (Suzhou) Co., Ltd - 12-B101 Creative Industrial Park ,No. 328,Xinghu Street - Suzhou Industrial Park - SuZhou JiangSu 215000 - CHINA - - 04-70-BC (hex) Globalstar Inc. - 0470BC (base 16) Globalstar Inc. - 461 S Milpitas Blvd - Milpitas CA 95035 - UNITED STATES - - 04-74-A1 (hex) Aligera Equipamentos Digitais Ltda - 0474A1 (base 16) Aligera Equipamentos Digitais Ltda - Av. Para 330 / 302 - Porto Alegre RS 90240-590 - BRAZIL - - 04-75-F5 (hex) CSST - 0475F5 (base 16) CSST - Building 6, CSST industrial park, Tong fuyu Industrial zone - Guangmin District - Shenzhen Guangdong 518107 - CHINA - - 04-76-6E (hex) ALPS Co,. Ltd. - 04766E (base 16) ALPS Co,. Ltd. - 6-3-36 Furukawanakazato, - Osaki Miyagi-pref 989-6181 - JAPAN - - 04-7D-7B (hex) Quanta Computer Inc. - 047D7B (base 16) Quanta Computer Inc. - 211, Wen Hwa 2nd Rd., Kuei Shan, Tao Yuan, - Taipei 33377 - TAIWAN, PROVINCE OF CHINA - - 04-81-AE (hex) Clack Corporation - 0481AE (base 16) Clack Corporation - 4462 Duraform Lane - Windsor WI 53598 - UNITED STATES - - 04-84-8A (hex) 7INOVA TECHNOLOGY LIMITED - 04848A (base 16) 7INOVA TECHNOLOGY LIMITED - 1811unit,B Block,ZhanTao Technology Building, - MinZhi Road,LongHua District - ShenZhen GuangDong 518000 - CHINA - - 04-88-8C (hex) Eifelwerk Butler Systeme GmbH - 04888C (base 16) Eifelwerk Butler Systeme GmbH - Eifelwerkstrasse 1 - Malbergweich 54655 - GERMANY - - 04-88-E2 (hex) Beats Electronics LLC - 0488E2 (base 16) Beats Electronics LLC - 1601 Cloverfield Blvd. - Suite 5000N - Santa Monica California 90404 - UNITED STATES - - 04-8A-15 (hex) Avaya, Inc - 048A15 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 04-8B-42 (hex) Skspruce Technology Limited - 048B42 (base 16) Skspruce Technology Limited - Haidian, Anningzhuang west road #9 - building 29, Jingtaifudi plaza - Beijing 100085 - CHINA - - 04-8C-03 (hex) ThinPAD Technology (Shenzhen)CO.,LTD - 048C03 (base 16) ThinPAD Technology (Shenzhen)CO.,LTD - Room 2305, Xingji Building, Xinsha Road - Shajing Town,Baoan - Shenzhen Guangdong 518104 - CHINA - - 04-8D-38 (hex) Netcore Technology Inc. - 048D38 (base 16) Netcore Technology Inc. - 9F,B block,Tsinghua Information Guard - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 04-92-EE (hex) iway AG - 0492EE (base 16) iway AG - Badenerstrasse 569 - Zurich ZH 8048 - SWITZERLAND - - 04-94-A1 (hex) CATCH THE WIND INC - 0494A1 (base 16) CATCH THE WIND INC - 10781 JAMES PAYNE COURT - MANASSAS VA 20110 - UNITED STATES - - 04-98-F3 (hex) ALPS Electric Co,. Ltd. - 0498F3 (base 16) ALPS Electric Co,. Ltd. - 6-1 NISHIDA - KAKUDA MIYAGI PREF 9876-8501 - JAPAN - - 04-99-E6 (hex) Shenzhen Yoostar Technology Co., Ltd - 0499E6 (base 16) Shenzhen Yoostar Technology Co., Ltd - #503,Tower D, HUA HAN Innovation Park, - LANGSHAN Rd., NORTH DISTRICT OF HIGH-TECH PARK, NANSHAN DISTRICT, SHENZHEN - Shenzhen Guangdong 518000 - CHINA - - 04-9B-9C (hex) Eadingcore Intelligent Technology Co., Ltd. - 049B9C (base 16) Eadingcore Intelligent Technology Co., Ltd. - No. 169 Lijia city C District comprehensive 3 layer C3-10 mall,Five-One road - Taijiang District - Fuzhou Fujian 350000 - CHINA - - 04-9C-62 (hex) BMT Medical Technology s.r.o. - 049C62 (base 16) BMT Medical Technology s.r.o. - Cejl 50 - Brno 65660 - CZECH REPUBLIC - - 04-9F-06 (hex) Smobile Co., Ltd. - 049F06 (base 16) Smobile Co., Ltd. - T-1009, Poongrim i-won Plus, 255-1 - Seohyeon-dong, Bundang-gu Seongnam-si, Gyeonggi-do 463-862 - KOREA, REPUBLIC OF - - 04-9F-81 (hex) Netscout Systems, Inc. - 049F81 (base 16) Netscout Systems, Inc. - 45999 Center Oak Plaza - suite 100 - Sterling Virginia 20166 - UNITED STATES - - 04-A1-51 (hex) NETGEAR INC., - 04A151 (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 04-A3-F3 (hex) Emicon - 04A3F3 (base 16) Emicon - shelkovskoe shosse, 77 - Moscow 107241 - RUSSIAN FEDERATION - - 04-A8-2A (hex) Nokia Corporation - 04A82A (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 04-B3-B6 (hex) Seamap (UK) Ltd - 04B3B6 (base 16) Seamap (UK) Ltd - Unit 34, The Maltings - Charlton Estate - Shepton Mallet Somerset BA4 5QE - UNITED KINGDOM - - 04-B4-66 (hex) BSP Co., Ltd. - 04B466 (base 16) BSP Co., Ltd. - 162-10 - Gongdan Dong - Gumi Gyeungsangbuk Do 730-902 - KOREA, REPUBLIC OF - - 04-BD-70 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 04BD70 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base, - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 04-BD-88 (hex) Aruba Networks - 04BD88 (base 16) Aruba Networks - 1344 Crossman Ave - Sunnyvale CA 94089 - UNITED STATES - - 04-BF-A8 (hex) ISB Corporation - 04BFA8 (base 16) ISB Corporation - 1-2-1 Shinyokohama, Kohoku-ku - Yokohama Kanagawa 222-0033 - JAPAN - - 04-C0-5B (hex) Tigo Energy - 04C05B (base 16) Tigo Energy - 170 Knowles Dr - Los Gatos CA 95032 - UNITED STATES - - 04-C0-6F (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 04C06F (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 04-C0-9C (hex) Tellabs Inc. - 04C09C (base 16) Tellabs Inc. - 1415 W. Diehl Road - Naperville Illinois 60563 - UNITED STATES - - 04-C1-B9 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 04C1B9 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 04-C5-A4 (hex) CISCO SYSTEMS, INC. - 04C5A4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 04-C8-80 (hex) Samtec Inc - 04C880 (base 16) Samtec Inc - 520 Park East Blvd - New Albany IN 47150 - UNITED STATES - - 04-C9-91 (hex) Phistek INC. - 04C991 (base 16) Phistek INC. - 5 Floor, No.188, Section 3, Datong Road - Xizhi District - New Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - 04-C9-D9 (hex) EchoStar Technologies Corp - 04C9D9 (base 16) EchoStar Technologies Corp - 94 Inverness Terrace E - Englewood CO 80134 - UNITED STATES - - 04-CB-1D (hex) Traka plc - 04CB1D (base 16) Traka plc - 30 Stilebrook Road - Olney - Bucks Buckinghamshire MK46 5EA - UNITED KINGDOM - - 04-CE-14 (hex) Wilocity LTD. - 04CE14 (base 16) Wilocity LTD. - 21 Bareket St. - North Industrial Park - Caesarea Israel 38900 - UNITED STATES - - 04-CF-25 (hex) MANYCOLORS, INC. - 04CF25 (base 16) MANYCOLORS, INC. - 3F, 4-1-18 Jinnoharu - Yahatanishi - Kitakyushu Fukuoka 8070821 - JAPAN - - 04-D4-37 (hex) ZNV - 04D437 (base 16) ZNV - 4/F, W1-A, Bldg, Gaoxin S, 1st Ave., Hi-tech Park, Nanshan District, Shenzhen, P.R.C - Shenzhen Guangdong 518057 - CHINA - - 04-D7-83 (hex) Y&H E&C Co.,LTD. - 04D783 (base 16) Y&H E&C Co.,LTD. - 1501 Daerung Technotown 224-5 - Gwanyang-dong, Dongan-ku - Anyang-city Gyeonggi-do 431-062 - KOREA, REPUBLIC OF - - 04-DA-D2 (hex) Cisco - 04DAD2 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 04-DB-56 (hex) Apple, Inc. - 04DB56 (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-DB-8A (hex) Suntech International Ltd. - 04DB8A (base 16) Suntech International Ltd. - Room 605, IT Mirae Tower - 33, 9 Gil, Digital-ro, Geumcheon-gu - Seoul 153-760 - KOREA, REPUBLIC OF - - 04-DD-4C (hex) Velocytech - 04DD4C (base 16) Velocytech - PoppelgÃ¥rdvej 11 - Søborg DK 2860 - DENMARK - - 04-DE-DB (hex) Rockport Networks Inc - 04DEDB (base 16) Rockport Networks Inc - 515 Legget Dr., Suite 600 - Kanata ON K2K 3G4 - CANADA - - 04-DF-69 (hex) Car Connectivity Consortium - 04DF69 (base 16) Car Connectivity Consortium - 3855 SW 153rd Drive - Beaverton Oregon 97006 - UNITED STATES - - 04-E0-C4 (hex) TRIUMPH-ADLER AG - 04E0C4 (base 16) TRIUMPH-ADLER AG - HUNDINGSTRAßE 11B - 8500 NURNBURG 80 - GERMANY - - 04-E1-C8 (hex) IMS Soluções em Energia Ltda. - 04E1C8 (base 16) IMS Soluções em Energia Ltda. - Av. Bernardino Silveira Pastoriza, 720 - Porto Alegre RS 91160-310 - BRAZIL - - 04-E2-F8 (hex) AEP Ticketing solutions srl - 04E2F8 (base 16) AEP Ticketing solutions srl - Via dei Colli, 240 - Signa Firenze 50058 - ITALY - - 04-E4-51 (hex) Texas Instruments - 04E451 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 04-E5-36 (hex) Apple - 04E536 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-E5-48 (hex) Cohda Wireless Pty Ltd - 04E548 (base 16) Cohda Wireless Pty Ltd - Suite 5 / 83 Fullarton Road - Kent Town South Australia 5067 - AUSTRALIA - - 04-E6-62 (hex) Acroname Inc. - 04E662 (base 16) Acroname Inc. - 4822 Sterling Drive - Boulder CO 80301-2350 - UNITED STATES - - 04-E6-76 (hex) AMPAK Technology Inc. - 04E676 (base 16) AMPAK Technology Inc. - No.1,Jen Ai Road - Hsinchu Industrail Park,Hukou - Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - 04-E9-E5 (hex) PJRC.COM, LLC - 04E9E5 (base 16) PJRC.COM, LLC - 14723 SW Brooke Ct - Sherwood Oregon 97140 - UNITED STATES - - 04-EE-91 (hex) x-fabric GmbH - 04EE91 (base 16) x-fabric GmbH - Nachodstraße 7 - Berlin 10779 - GERMANY - - 04-F0-21 (hex) Compex Systems Pte Ltd - 04F021 (base 16) Compex Systems Pte Ltd - 135 Joo Seng Road, - #08-01 PM Industrial Building - 368363 - SINGAPORE - - 04-F1-3E (hex) Apple - 04F13E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-F1-7D (hex) Tarana Wireless - 04F17D (base 16) Tarana Wireless - 2105 Martin Luther King Jr Way - Suite 200 - Berkeley CA 94704 - UNITED STATES - - 04-F4-BC (hex) Xena Networks - 04F4BC (base 16) Xena Networks - Graabroedretorv 6, 3. sal - København Danmark 1154 - DENMARK - - 04-F7-E4 (hex) Apple - 04F7E4 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 04-F8-C2 (hex) Flaircomm Microelectronics, Inc. - 04F8C2 (base 16) Flaircomm Microelectronics, Inc. - 7F,Guomai Building,116 East JiangBin Ave - Fuzhou Fujian 350015 - CHINA - - 04-F9-38 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 04F938 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - Shenzheng Guangdong 518129 - CHINA - - 04-FE-31 (hex) Samsung Electronics Co.,Ltd - 04FE31 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 04-FE-7F (hex) CISCO SYSTEMS, INC. - 04FE7F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 04-FF-51 (hex) NOVAMEDIA INNOVISION SP. Z O.O. - 04FF51 (base 16) NOVAMEDIA INNOVISION SP. Z O.O. - WODNA 7 - KALISZ WIELKOPOLSKA 62-800 - POLAND - - 08-00-01 (hex) COMPUTERVISION CORPORATION - 080001 (base 16) COMPUTERVISION CORPORATION - 14 CROSBY DRIVE MS 5-1 - BEDFORD MA 01730 - UNITED STATES - - 08-00-02 (hex) BRIDGE COMMUNICATIONS INC. - 080002 (base 16) BRIDGE COMMUNICATIONS INC. - 2081 STIERLING ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 08-00-03 (hex) ADVANCED COMPUTER COMM. - 080003 (base 16) ADVANCED COMPUTER COMM. - 720 SANTA BARBARA ST. - SANTA BARBARA CA 93101 - UNITED STATES - - 08-00-04 (hex) CROMEMCO INCORPORATED - 080004 (base 16) CROMEMCO INCORPORATED - 280 BERNARDO AVENUE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 08-00-05 (hex) SYMBOLICS INC. - 080005 (base 16) SYMBOLICS INC. - 257 VASSAR STREET - CAMBRIDGE MA 02139 - UNITED STATES - - 08-00-06 (hex) SIEMENS AG - 080006 (base 16) SIEMENS AG - Siemens IT Solutions and Services, SIS GO QM O - Siemensstrasse 2-4 - POB 2353 Fuerth 90713 - GERMANY - - 08-00-07 (hex) Apple - 080007 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 08-00-08 (hex) BOLT BERANEK AND NEWMAN INC. - 080008 (base 16) BOLT BERANEK AND NEWMAN INC. - 70 FAWCETT STREET - CAMBRIDGE MA 02138 - UNITED STATES - - 08-00-09 (hex) HEWLETT PACKARD - 080009 (base 16) HEWLETT PACKARD - ENTERPRISE SYSTEMS TECH.CENTER - 11000 WOLFE ROAD - CUPERTINO CA 95014 - UNITED STATES - - 08-00-0A (hex) NESTAR SYSTEMS INCORPORATED - 08000A (base 16) NESTAR SYSTEMS INCORPORATED - 2585 EAST BAYSHORE ROAD - PALO ALTO CA 94303 - UNITED STATES - - 08-00-0B (hex) UNISYS CORPORATION - 08000B (base 16) UNISYS CORPORATION - TOWNSHIP LINE ROAD - BLUE BELL PA 19424 - UNITED STATES - - 08-00-0C (hex) MIKLYN DEVELOPMENT CO. - 08000C (base 16) MIKLYN DEVELOPMENT CO. - 3613 ANDOVER DIVE - BEDFORD TX 76021 - UNITED STATES - - 08-00-0D (hex) INTERNATIONAL COMPUTERS LTD. - 08000D (base 16) INTERNATIONAL COMPUTERS LTD. - WENLOCK WAY - WEST GORTON MANCHESTER, M12 5DR - UNITED KINGDOM - UNITED KINGDOM - - 08-00-0E (hex) NCR CORPORATION - 08000E (base 16) NCR CORPORATION - WORLD HEADQUARTERS - DAYTON OH 45479 - UNITED STATES - - 08-00-0F (hex) MITEL CORPORATION - 08000F (base 16) MITEL CORPORATION - 350 LEGGET DRIVE - P.O. BOX 13089 KANATA ONTARIO - CANADA K2K 1X3 - CANADA - - 08-00-11 (hex) TEKTRONIX INC. - 080011 (base 16) TEKTRONIX INC. - TECHNICAL STANDARDS - 13975 SW KARL BRAUN DRIVE PO BOX 500, M - BEAVERTON OR 97077 - UNITED STATES - - 08-00-12 (hex) BELL ATLANTIC INTEGRATED SYST. - 080012 (base 16) BELL ATLANTIC INTEGRATED SYST. - 40 TALL PINE DRIVE - SUDBURY MA 01776 - UNITED STATES - - 08-00-13 (hex) EXXON - 080013 (base 16) EXXON - - - 08-00-14 (hex) EXCELAN - 080014 (base 16) EXCELAN - 1599 FLICKINGER AVENUE - SAN JOSE CA 95131 - UNITED STATES - - 08-00-15 (hex) STC BUSINESS SYSTEMS - 080015 (base 16) STC BUSINESS SYSTEMS - HOLBROOK HOUSE - COCKFOSTERS ROAD COCKFOSTERS HERTS EN4 O - UNITED KINGDOM - UNITED KINGDOM - - 08-00-16 (hex) BARRISTER INFO SYS CORP - 080016 (base 16) BARRISTER INFO SYS CORP - ONE TECHNOLOGY CENTER - 45 OAK STREET - BUFFALO NY 14203 - UNITED STATES - - 08-00-17 (hex) NATIONAL SEMICONDUCTOR - 080017 (base 16) NATIONAL SEMICONDUCTOR - 2900 SEMICONDUCTOR DRIVE - SANTA CLARA CA 95051 - UNITED STATES - - 08-00-18 (hex) PIRELLI FOCOM NETWORKS - 080018 (base 16) PIRELLI FOCOM NETWORKS - DENTON DRIVE - NORTHWICH CHESHIRE CW9 7LU - ENGLAND - UNITED KINGDOM - - 08-00-19 (hex) GENERAL ELECTRIC CORPORATION - 080019 (base 16) GENERAL ELECTRIC CORPORATION - 1285 BOSTON AVENUE - BRIDGEPORT CT 06602 - UNITED STATES - - 08-00-1A (hex) TIARA/ 10NET - 08001A (base 16) TIARA/ 10NET - 7777 WASHINGTON VILLAGE DRIVE - SUITE 200 - DAYTON OHIO 45459-3957 - UNITED STATES - - 08-00-1B (hex) EMC Corporation - 08001B (base 16) EMC Corporation - 176 South Street - Hopkinton MA 01748 - UNITED STATES - - 08-00-1C (hex) KDD-KOKUSAI DEBNSIN DENWA CO. - 08001C (base 16) KDD-KOKUSAI DEBNSIN DENWA CO. - FUJI XEROX CO., LTD. TELEGRAPH - NO. 3-5, AKASAKA 3-CHOME MINATO-KU, TOKY - 107 - JAPAN - - 08-00-1D (hex) ABLE COMMUNICATIONS INC. - 08001D (base 16) ABLE COMMUNICATIONS INC. - 17891 CARTWRIGHT ROAD - IRVINE CA 92714-6216 - UNITED STATES - - 08-00-1E (hex) APOLLO COMPUTER INC. - 08001E (base 16) APOLLO COMPUTER INC. - 15 ELIZABETH DRIVE - CHELMSFORD MA 01824 - UNITED STATES - - 08-00-1F (hex) SHARP CORPORATION - 08001F (base 16) SHARP CORPORATION - ENGINEERING DEPARTMENT 6 - 492 MINOSHO-CHO YAMATOKOORIYMA-SHI, - NARA 639-11 - JAPAN - - 08-00-20 (hex) Oracle Corporation - 080020 (base 16) Oracle Corporation - 17 Network Circle - Building 17, UMPK17-131 - Menlo Park CA 95025 - UNITED STATES - - 08-00-21 (hex) 3M COMPANY - 080021 (base 16) 3M COMPANY - Telecom Division - 6801 River Place Boulevard - Austin TX 78726-9000 - UNITED STATES - - 08-00-22 (hex) NBI INC. - 080022 (base 16) NBI INC. - 3450 MITCHELL LANE - P.O. BOX 9001 - BOULDER CO 80301 - UNITED STATES - - 08-00-23 (hex) Panasonic Communications Co., Ltd. - 080023 (base 16) Panasonic Communications Co., Ltd. - 4-1-62 Minoshima Hakata Fukuoka - 812-8531 - JAPAN - - 08-00-24 (hex) 10NET COMMUNICATIONS/DCA - 080024 (base 16) 10NET COMMUNICATIONS/DCA - 7777 WASHINGTON VILLAGE DR. - SUITE 200 - DAYTON OH 45459-3957 - UNITED STATES - - 08-00-25 (hex) CONTROL DATA - 080025 (base 16) CONTROL DATA - 4201 LEXINGTON AVE NORTH - ARDEN HILLS MN 55112 - UNITED STATES - - 08-00-26 (hex) NORSK DATA A.S. - 080026 (base 16) NORSK DATA A.S. - P.O. BOX 25 BOGERUD - OSLO 6 - NORWAY - - 08-00-27 (hex) CADMUS COMPUTER SYSTEMS - 080027 (base 16) CADMUS COMPUTER SYSTEMS - 600 SUFFOLK ST - LOWELL MA 08154 - UNITED STATES - - 08-00-28 (hex) Texas Instruments - 080028 (base 16) Texas Instruments - 12500 TI Boulevard - M/S 8723 - Dallas TX 75243 - UNITED STATES - - 08-00-29 (hex) MEGATEK CORPORATION - 080029 (base 16) MEGATEK CORPORATION - 9645 SCRANTON ROAD - SAN DIEGO CA 92121 - UNITED STATES - - 08-00-2A (hex) MOSAIC TECHNOLOGIES INC. - 08002A (base 16) MOSAIC TECHNOLOGIES INC. - 47 MANNING ROAD - BILLERICA MA 01821-3970 - UNITED STATES - - 08-00-2B (hex) DIGITAL EQUIPMENT CORPORATION - 08002B (base 16) DIGITAL EQUIPMENT CORPORATION - LKG 1-2/A19 - 550 KING STREET - LITTLETON MA 01460-1289 - UNITED STATES - - 08-00-2C (hex) BRITTON LEE INC. - 08002C (base 16) BRITTON LEE INC. - 14600 WINCHESTER BLVD - LOS GATOS CA 95030 - UNITED STATES - - 08-00-2D (hex) LAN-TEC INC. - 08002D (base 16) LAN-TEC INC. - 2131 UNIVERSITY AVENUE - BERKELEY CA 94704 - UNITED STATES - - 08-00-2E (hex) METAPHOR COMPUTER SYSTEMS - 08002E (base 16) METAPHOR COMPUTER SYSTEMS - 2500 GARCIA AVENUE - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 08-00-2F (hex) PRIME COMPUTER INC. - 08002F (base 16) PRIME COMPUTER INC. - 100 CROSBY DRIVE - BEDFORD MA 01730-1402 - UNITED STATES - - 08-00-30 (hex) NETWORK RESEARCH CORPORATION - 080030 (base 16) NETWORK RESEARCH CORPORATION - 2380 N. ROSE AVENUE - OXNARD CA 93010 - UNITED STATES - - 08-00-30 (hex) CERN - 080030 (base 16) CERN - CH-1211 GENEVE 23 - SUISSE/SWITZ - SWITZERLAND - - 08-00-30 (hex) ROYAL MELBOURNE INST OF TECH - 080030 (base 16) ROYAL MELBOURNE INST OF TECH - GPO BOX 2476V - MELBOURNE VIC 3001 - AUSTRALIA - - 08-00-31 (hex) LITTLE MACHINES INC. - 080031 (base 16) LITTLE MACHINES INC. - 4141 JUTLAND DRIVE - SAN DIEGO CA 92117 - UNITED STATES - - 08-00-32 (hex) TIGAN INCORPORATED - 080032 (base 16) TIGAN INCORPORATED - 4020 FABIAN WAY - SUITE D - PALO ALTO CA 94303 - UNITED STATES - - 08-00-33 (hex) BAUSCH & LOMB - 080033 (base 16) BAUSCH & LOMB - INTERACTIVE GRAPHICS DIVISION - P.O. BOX 14547 - AUSITN TX 78671 - UNITED STATES - - 08-00-34 (hex) FILENET CORPORATION - 080034 (base 16) FILENET CORPORATION - 1575 CORPORATE DRIVE - COSTA MESA CA 92626 - UNITED STATES - - 08-00-35 (hex) MICROFIVE CORPORATION - 080035 (base 16) MICROFIVE CORPORATION - 3560 HYLAND AVENUE - P.O. BOX 5011 - COSTA MESA CA 92626 - UNITED STATES - - 08-00-36 (hex) INTERGRAPH CORPORATION - 080036 (base 16) INTERGRAPH CORPORATION - ONE MADISON INDUSTRIAL PARK - HUNTSVILLE AL 35807 - UNITED STATES - - 08-00-37 (hex) FUJI-XEROX CO. LTD. - 080037 (base 16) FUJI-XEROX CO. LTD. - ADVANCED TECH & ENG'G CENTER - 9-50 CHUO 2-CHOME, EBINA-SHI KANAGAWA 24 - JAPAN - - 08-00-38 (hex) BULL S.A.S. - 080038 (base 16) BULL S.A.S. - rue Jean Jaures B.P.68 - Les Clayes sous Bois 78430 - FRANCE - - 08-00-39 (hex) SPIDER SYSTEMS LIMITED - 080039 (base 16) SPIDER SYSTEMS LIMITED - SPIDER PARK - STANWELL STREET EDINBURGH EH6 5NG - SCOTLAND - UNITED KINGDOM - - 08-00-3A (hex) ORCATECH INC. - 08003A (base 16) ORCATECH INC. - 2680 QUEENSVIEW DRIVE - OTTAWA ONTARIO - CANADA K2B 8H6 - CANADA - - 08-00-3B (hex) TORUS SYSTEMS LIMITED - 08003B (base 16) TORUS SYSTEMS LIMITED - SCIENCE PARK - MILTON ROAD CAMBRIDGE CB4 4BH - UNITED KINGDOM - UNITED KINGDOM - - 08-00-3C (hex) SCHLUMBERGER WELL SERVICES - 08003C (base 16) SCHLUMBERGER WELL SERVICES - AUSTIN ENGINEERING SERVICES - P.O. BOX 200015 - AUSTIN TX 78720-0015 - UNITED STATES - - 08-00-3D (hex) CADNETIX CORPORATIONS - 08003D (base 16) CADNETIX CORPORATIONS - 5797 CENTRAL AVENUE - BOULDER CO 80301 - UNITED STATES - - 08-00-3E (hex) CODEX CORPORATION - 08003E (base 16) CODEX CORPORATION - 50 EAST COMMERCE DRIVE - SUITE M1 - SCHAUMBURG IL 60173 - UNITED STATES - - 08-00-3F (hex) FRED KOSCHARA ENTERPRISES - 08003F (base 16) FRED KOSCHARA ENTERPRISES - - - 08-00-40 (hex) FERRANTI COMPUTER SYS. LIMITED - 080040 (base 16) FERRANTI COMPUTER SYS. LIMITED - WYTHENSHAWE DIVISION - WESTERN ROAD BRACKNELL RG12 1RA - UNITED KINGDOM - UNITED KINGDOM - - 08-00-41 (hex) RACAL-MILGO INFORMATION SYS.. - 080041 (base 16) RACAL-MILGO INFORMATION SYS.. - 400 EMBASSY ROW - SUITE 300 - ATLANTA GA 30328 - UNITED STATES - - 08-00-42 (hex) JAPAN MACNICS CORP. - 080042 (base 16) JAPAN MACNICS CORP. - - JAPAN - - 08-00-43 (hex) PIXEL COMPUTER INC. - 080043 (base 16) PIXEL COMPUTER INC. - 260 FORDHAM ROAD - WILMINGTON MA 01887 - UNITED STATES - - 08-00-44 (hex) DAVID SYSTEMS INC. - 080044 (base 16) DAVID SYSTEMS INC. - 615 TASMAN DRIVE - SUNNYVALE CA 94088 - UNITED STATES - - 08-00-45 (hex) CONCURRENT COMPUTER CORP. - 080045 (base 16) CONCURRENT COMPUTER CORP. - 2 CRESCENT PLACE - OCEANPORT NJ 07757 - UNITED STATES - - 08-00-46 (hex) Sony Corporation - 080046 (base 16) Sony Corporation - Gotenyama Tec, 5-1-2 Kitashinagawa - Shinagawa-ku - Tokyo 141-0001 - JAPAN - - 08-00-47 (hex) SEQUENT COMPUTER SYSTEMS INC. - 080047 (base 16) SEQUENT COMPUTER SYSTEMS INC. - 15450 S.W. KOLL PARKWAY . - MAILSTOP COL2-831 - BEAVERTON OR 97006 - UNITED STATES - - 08-00-48 (hex) EUROTHERM GAUGING SYSTEMS - 080048 (base 16) EUROTHERM GAUGING SYSTEMS - 900 MIDDLESEX TURNPIKE, BDG. 6 - BILLERICA MA 01821 - UNITED STATES - - 08-00-49 (hex) UNIVATION - 080049 (base 16) UNIVATION - 1037 NORTH FAIR OAKS AVE. - SUNNYVALE CA 94089 - UNITED STATES - - 08-00-4A (hex) BANYAN SYSTEMS INC. - 08004A (base 16) BANYAN SYSTEMS INC. - 135 FLANDERS ROAD - WESTBORO MA 01581 - UNITED STATES - - 08-00-4B (hex) PLANNING RESEARCH CORP. - 08004B (base 16) PLANNING RESEARCH CORP. - 1DHS SYSTEMS - 1508 KENNEDY DRIVE-STE#215 - BELLEVUE NE 68--5 - UNITED STATES - - 08-00-4C (hex) HYDRA COMPUTER SYSTEMS INC. - 08004C (base 16) HYDRA COMPUTER SYSTEMS INC. - 12 MERCER ROAD - NATICK MA 01760 - UNITED STATES - - 08-00-4D (hex) CORVUS SYSTEMS INC. - 08004D (base 16) CORVUS SYSTEMS INC. - 2100 CORVUS DRIVE - SAN JOSE CA 95124 - UNITED STATES - - 08-00-4E (hex) 3COM EUROPE LTD. - 08004E (base 16) 3COM EUROPE LTD. - 3COM CENTRE - BOUNDARY WAY, HEMEL HEMPSTEAD HERTFORSHI - UNITED KINGDOM - UNITED KINGDOM - - 08-00-4F (hex) CYGNET SYSTEMS - 08004F (base 16) CYGNET SYSTEMS - 2560 JUNCTION AVENUE - SAN JOSE CA 95134 - UNITED STATES - - 08-00-50 (hex) DAISY SYSTEMS CORP. - 080050 (base 16) DAISY SYSTEMS CORP. - 139 KIFER COURT - SUNNYVALE CA 94086 - UNITED STATES - - 08-00-51 (hex) EXPERDATA - 080051 (base 16) EXPERDATA - 88, RUE BRILLAT SAVARIN - 75013 PARIS - FRANCE - - 08-00-52 (hex) INSYSTEC - 080052 (base 16) INSYSTEC - 450 LAKEMONT AVENUE - WINTER PARK FL 32792 - UNITED STATES - - 08-00-53 (hex) MIDDLE EAST TECH. UNIVERSITY - 080053 (base 16) MIDDLE EAST TECH. UNIVERSITY - DEPARTMENT OF - COMPUTER ENGINEERING - ANKARA - TURKEY - - 08-00-55 (hex) STANFORD TELECOMM. INC. - 080055 (base 16) STANFORD TELECOMM. INC. - 1221 CROSSMAN - SUNNYVALE CA 94089 - UNITED STATES - - 08-00-56 (hex) STANFORD LINEAR ACCEL. CENTER - 080056 (base 16) STANFORD LINEAR ACCEL. CENTER - 2575 SANDHILL ROAD - MENLO PARK CA 94025 - UNITED STATES - - 08-00-57 (hex) EVANS & SUTHERLAND - 080057 (base 16) EVANS & SUTHERLAND - P.O. BOX 8700 - 580 ARAPEEN DRIVE - SALT LAKE CITY UT 84108 - UNITED STATES - - 08-00-58 (hex) SYSTEMS CONCEPTS - 080058 (base 16) SYSTEMS CONCEPTS - 520 THIRD STREET - SAN FRANCISCO CA 94107 - UNITED STATES - - 08-00-59 (hex) A/S MYCRON - 080059 (base 16) A/S MYCRON - PO BOX 6199 - N-0602 OSLO 6 - NORWAY - - 08-00-5A (hex) IBM Corp - 08005A (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 08-00-5B (hex) VTA TECHNOLOGIES INC. - 08005B (base 16) VTA TECHNOLOGIES INC. - 2040 SHERMAN STREET - HOLLYWOOD FL 33020 - UNITED STATES - - 08-00-5C (hex) FOUR PHASE SYSTEMS - 08005C (base 16) FOUR PHASE SYSTEMS - 2001 LOGIC DRIVE - SAN JOSE CA 95124-3452 - UNITED STATES - - 08-00-5D (hex) GOULD INC. - 08005D (base 16) GOULD INC. - 6901 WEST SUNRISE BLVD. - P.O. BOX 9148 - FT. LAUDERDALE FL 33310-9148 - UNITED STATES - - 08-00-5E (hex) COUNTERPOINT COMPUTER INC. - 08005E (base 16) COUNTERPOINT COMPUTER INC. - 2127 RINGWOOD AVENUE - SAN JOSE CA 95131 - UNITED STATES - - 08-00-5F (hex) SABER TECHNOLOGY CORP. - 08005F (base 16) SABER TECHNOLOGY CORP. - 2381 BERING DRIVE - SAN JOSE CA 95131-1125 - UNITED STATES - - 08-00-60 (hex) INDUSTRIAL NETWORKING INC. - 080060 (base 16) INDUSTRIAL NETWORKING INC. - 3990 FREEDOM CIRCLE - SANTA CLARA CA 95050 - UNITED STATES - - 08-00-61 (hex) JAROGATE LTD. - 080061 (base 16) JAROGATE LTD. - 197-213 LYHAM ROAD - BRISTON LONDON SW2 5PY - UNITED KINGDOM - UNITED KINGDOM - - 08-00-62 (hex) GENERAL DYNAMICS - 080062 (base 16) GENERAL DYNAMICS - FORT WORTH DIVISION - P.O. BOX 748 - FT. WORTH TX 76101 - UNITED STATES - - 08-00-63 (hex) PLESSEY - 080063 (base 16) PLESSEY - PLESSEY - UK LIMITED - 167-55 148TH AVENUE - JAMAICA NY 11434 - UNITED STATES - - 08-00-64 (hex) Sitasys AG - 080064 (base 16) Sitasys AG - Industriestrasse 6 - 4513 Langendorf - SWITZERLAND - - 08-00-65 (hex) GENRAD INC. - 080065 (base 16) GENRAD INC. - 300 BAKER AVENUE - MAIL STOP 26 - CONCORD MA 01742 - UNITED STATES - - 08-00-66 (hex) AGFA CORPORATION - 080066 (base 16) AGFA CORPORATION - 200 BALLARDVALE STREET - WILMINGTON MA 01887 - UNITED STATES - - 08-00-67 (hex) COMDESIGN - 080067 (base 16) COMDESIGN - 751 SOUTH KELLOG AVENUE - GOLETA CA 93117-3880 - UNITED STATES - - 08-00-68 (hex) RIDGE COMPUTERS - 080068 (base 16) RIDGE COMPUTERS - 2451 MISSION COLLEGE BLVD. - SANTA CLARA CA 95054 - UNITED STATES - - 08-00-69 (hex) SILICON GRAPHICS INC. - 080069 (base 16) SILICON GRAPHICS INC. - 2011 N. SHORELINE BLVD. - P.O. BOX 7311 CA 94043 - MOUNTAIN VIEW CA 94039-7311 - UNITED STATES - - 08-00-6A (hex) ATT BELL LABORATORIES - 08006A (base 16) ATT BELL LABORATORIES - 1100 EAST WARRENVILLE ROAD - NAPERVILLE IL 60566 - UNITED STATES - - 08-00-6B (hex) ACCEL TECHNOLOGIES INC. - 08006B (base 16) ACCEL TECHNOLOGIES INC. - 7358 TRADE STREET - SAN DIEGO CA 92121 - UNITED STATES - - 08-00-6C (hex) SUNTEK TECHNOLOGY INT'L - 08006C (base 16) SUNTEK TECHNOLOGY INT'L - 586 NO. FIRST STREET - SAN JOSE CA 95112 - UNITED STATES - - 08-00-6D (hex) WHITECHAPEL COMPUTER WORKS - 08006D (base 16) WHITECHAPEL COMPUTER WORKS - 75 WHITECHAPEL ROAD - LONDON E1 1DU - UNITED KINGDOM - - 08-00-6E (hex) MASSCOMP - 08006E (base 16) MASSCOMP - ONE TECHNOLOGY PARK - WESTFORD MA 01886 - UNITED STATES - - 08-00-6F (hex) PHILIPS APELDOORN B.V. - 08006F (base 16) PHILIPS APELDOORN B.V. - P.O. BOX 105 - 7300 AC APELDOORN - THE - NETHERLANDS - - 08-00-70 (hex) MITSUBISHI ELECTRIC CORP. - 080070 (base 16) MITSUBISHI ELECTRIC CORP. - 325 KAMIMACHIYA - KAMAKURA CITY KANAGWA PREFECTURE 247 - JAPAN - - 08-00-71 (hex) MATRA (DSIE) - 080071 (base 16) MATRA (DSIE) - PARC D'AFFAIRES - B.P. 262 - 27100 VAL DE REUIL - FRANCE - - 08-00-72 (hex) XEROX CORP UNIV GRANT PROGRAM - 080072 (base 16) XEROX CORP UNIV GRANT PROGRAM - ZEROX SYSTEMS INSTITUTE - M/S 105 50C 800 PHILLIPS ROAD - WEBSTER NY 14580 - UNITED STATES - - 08-00-73 (hex) TECMAR INC. - 080073 (base 16) TECMAR INC. - 6225 COCHRAN ROAD - SOLON OH 44139 - UNITED STATES - - 08-00-74 (hex) CASIO COMPUTER CO. LTD. - 080074 (base 16) CASIO COMPUTER CO. LTD. - 3-2-1 SAKAE-CHO - HAMURAMACHI, NISHITMAGUN TOKYO - 190-11 - JAPAN - - 08-00-75 (hex) DANSK DATA ELECTRONIK - 080075 (base 16) DANSK DATA ELECTRONIK - HERLEV HOVEDGADE 199 - DK 2730 HERLEV - DENMARK - - 08-00-76 (hex) PC LAN TECHNOLOGIES - 080076 (base 16) PC LAN TECHNOLOGIES - 5780 LINCOLN DRIVE SUITE 106 - MINNEAPOLIS MN 55436 - UNITED STATES - - 08-00-77 (hex) TSL COMMUNICATIONS LTD. - 080077 (base 16) TSL COMMUNICATIONS LTD. - THE LANDSBURY ESTATE - LOWER GUILDFORD ROAD KNAPHIL WOKING SURR - ENGLAND - UNITED KINGDOM - - 08-00-78 (hex) ACCELL CORPORATION - 080078 (base 16) ACCELL CORPORATION - 50 SAGINAW DRIVE - ROCHESTER NY 14623 - UNITED STATES - - 08-00-79 (hex) THE DROID WORKS - 080079 (base 16) THE DROID WORKS - P.O. BOX CS 8180 - SAN RAFAEL CA 94912 - UNITED STATES - - 08-00-7A (hex) INDATA - 08007A (base 16) INDATA - GJERDRUMS VEI 12 C - N-0486 OSLO 4 - NORWAY - - 08-00-7B (hex) SANYO ELECTRIC CO. LTD. - 08007B (base 16) SANYO ELECTRIC CO. LTD. - 1-18-13 HASHIRIDANI - HIRAKATA-SHI - OSAKA 573 - JAPAN - - 08-00-7C (hex) VITALINK COMMUNICATIONS CORP. - 08007C (base 16) VITALINK COMMUNICATIONS CORP. - 48761 KATO ROAD - FREMONT CA 94538 - UNITED STATES - - 08-00-7E (hex) AMALGAMATED WIRELESS(AUS) LTD - 08007E (base 16) AMALGAMATED WIRELESS(AUS) LTD - NORTH RYDE DIVISION - P.O. BOX 96 NORTH RYDE NSW - AUSTRALIA 2113 - AUSTRALIA - - 08-00-7F (hex) CARNEGIE-MELLON UNIVERSITY - 08007F (base 16) CARNEGIE-MELLON UNIVERSITY - INFORMATION TECHNOLOGY - SCHENLEY PARK - PITTSBURGE PA 15213 - UNITED STATES - - 08-00-80 (hex) AES DATA INC. - 080080 (base 16) AES DATA INC. - 1900 MINNESOTA COURT - MISSISAUGA ONTARIO - CANADA L5N L5N 3C9 - CANADA - - 08-00-81 (hex) ASTECH INC. - 080081 (base 16) ASTECH INC. - 670 NORTH COMMERCIAL STREET - MANCHESTER NH 03101 - UNITED STATES - - 08-00-82 (hex) VERITAS SOFTWARE - 080082 (base 16) VERITAS SOFTWARE - 4800 GREAT AMERICA PARKWAY - SANTA CLARA CA 95054 - UNITED STATES - - 08-00-83 (hex) Seiko Instruments Inc. - 080083 (base 16) Seiko Instruments Inc. - 8, Nakase 1-chome Mihama-ku - Chiba-shi Chiba 261-8507 - JAPAN - - 08-00-84 (hex) TOMEN ELECTRONICS CORP. - 080084 (base 16) TOMEN ELECTRONICS CORP. - 1-1 UCHISAIWAI-CHO 2CHOME - CHIYODA-KU TOKYO 100 - JAPAN - - 08-00-85 (hex) ELXSI - 080085 (base 16) ELXSI - 2334 LUNDY PLACE - SAN JOSE CA 95131 - UNITED STATES - - 08-00-86 (hex) KONICA MINOLTA HOLDINGS, INC. - 080086 (base 16) KONICA MINOLTA HOLDINGS, INC. - 1-6-1, Marunouchi, - Chiyoda-ku - Tokyo 100-0005 - JAPAN - - 08-00-87 (hex) XYPLEX - 080087 (base 16) XYPLEX - 295 FOSTER STREET - LITTLETON MA 01460 - UNITED STATES - - 08-00-88 (hex) Brocade Communications Systems, Inc. - 080088 (base 16) Brocade Communications Systems, Inc. - 1745 Technology Dr. - San Jose CA 95110 - UNITED STATES - - 08-00-89 (hex) KINETICS - 080089 (base 16) KINETICS - 3182 OLD TUNNEL ROAD - SUITE H - LAFAYETTE CA 94549 - UNITED STATES - - 08-00-8A (hex) PerfTech, Inc. - 08008A (base 16) PerfTech, Inc. - 613 NW Loop 410 - Suite 520 - SAN ANTONIO TX 78216 - UNITED STATES - - 08-00-8B (hex) PYRAMID TECHNOLOGY CORP. - 08008B (base 16) PYRAMID TECHNOLOGY CORP. - 1295 CHARLESTON ROAD - MOUNTAIN VIEW CA 94043 - UNITED STATES - - 08-00-8C (hex) NETWORK RESEARCH CORPORATION - 08008C (base 16) NETWORK RESEARCH CORPORATION - 2380 N. ROSE AVENUE - OXNARD CA 93010 - UNITED STATES - - 08-00-8D (hex) XYVISION INC. - 08008D (base 16) XYVISION INC. - 101 EDGEWATER DRIVE - WAKEFIELD MA 01880 - UNITED STATES - - 08-00-8E (hex) TANDEM COMPUTERS - 08008E (base 16) TANDEM COMPUTERS - 14321 TANDEM BLVD. - AUSTIN TX 78728-6610 - UNITED STATES - - 08-00-8F (hex) CHIPCOM CORPORATION - 08008F (base 16) CHIPCOM CORPORATION - SOUTHBOROUGH OFFICE - 118 TURNPIKE ROAD - SOUTHBOROUGH MA 01772-1886 - UNITED STATES - - 08-00-90 (hex) SONOMA SYSTEMS - 080090 (base 16) SONOMA SYSTEMS - 4640 ADMIRALTY WAY, STE. #600 - MARINA DEL REY CA 90292-6695 - UNITED STATES - - 08-03-71 (hex) KRG CORPORATE - 080371 (base 16) KRG CORPORATE - 41 rue Perier - Montrouge 92120 - FRANCE - - 08-05-CD (hex) DongGuang EnMai Electronic Product Co.Ltd. - 0805CD (base 16) DongGuang EnMai Electronic Product Co.Ltd. - 701 7th Floor,YiFeng Building, - XiaoBian - DongGuang GuangDong Province 523843 - CHINA - - 08-08-C2 (hex) Samsung Electronics - 0808C2 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 08-08-EA (hex) AMSC - 0808EA (base 16) AMSC - 15775 W Schaefer Court - New Berlin WI 53151 - UNITED STATES - - 08-09-B6 (hex) Masimo Corp - 0809B6 (base 16) Masimo Corp - 40 Parker - Irvine CA 92618 - UNITED STATES - - 08-0C-0B (hex) SysMik GmbH Dresden - 080C0B (base 16) SysMik GmbH Dresden - Bertolt-Brecht-Allee 24 - Dresden 01309 - GERMANY - - 08-0C-C9 (hex) Mission Technology Group, dba Magma - 080CC9 (base 16) Mission Technology Group, dba Magma - 9918 Via Pasar - San Diego CA 92126 - UNITED STATES - - 08-0D-84 (hex) GECO, Inc. - 080D84 (base 16) GECO, Inc. - 1754 N. 48th St. - Mesa AZ 85205 - UNITED STATES - - 08-0E-A8 (hex) Velex s.r.l. - 080EA8 (base 16) Velex s.r.l. - Via Dell'Artigianato 56 - Vigodarzere Padova 35010 - ITALY - - 08-0F-FA (hex) KSP INC. - 080FFA (base 16) KSP INC. - RM 501, 138 Kwangdeokdae-ro - Danwon-gu, Ansan-si Gyeonggi-do 425906 - KOREA, REPUBLIC OF - - 08-11-5E (hex) Bitel Co., Ltd. - 08115E (base 16) Bitel Co., Ltd. - 9F Yohyun B/D, 242-29, Nonhyun-dong - Gangnam-Gu - Seoul Gangnam-gu 135830 - KOREA, REPUBLIC OF - - 08-11-96 (hex) Intel Corporate - 081196 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 08-14-43 (hex) UNIBRAIN S.A. - 081443 (base 16) UNIBRAIN S.A. - 84, ETHNIKIS ANTISTASEOS - 15231 ATHENS - GREECE - - 08-16-51 (hex) Shenzhen Sea Star Technology Co.,Ltd - 081651 (base 16) Shenzhen Sea Star Technology Co.,Ltd - Seastar industrial Park, BaoLong 6th Ave - BaoLong industrial City, LongGang District, Shenzhen GuangDong P.R.C - ShenZhen GuangDong 518116 - CHINA - - 08-17-35 (hex) CISCO SYSTEMS, INC. - 081735 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 08-17-F4 (hex) IBM Corp - 0817F4 (base 16) IBM Corp - 2051 Mission College Blvd - Santa Clara CA 95054 - UNITED STATES - - 08-18-1A (hex) zte corporation - 08181A (base 16) zte corporation - 12/F.,ZTE R&D Building,keji nan Road - Shenzhen guangdong 518057 - CHINA - - 08-18-4C (hex) A. S. Thomas, Inc. - 08184C (base 16) A. S. Thomas, Inc. - 355 Providence Hwy - Westwood MA 02090 - UNITED STATES - - 08-19-A6 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 0819A6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 08-1D-FB (hex) Shanghai Mexon Communication Technology Co.,Ltd - 081DFB (base 16) Shanghai Mexon Communication Technology Co.,Ltd - Floor4-5, Unit B, Building 5 ,Lane 128, Jiujing Road - Songjiang hi-tech industrial zone - Shanghai 201615 - CHINA - - 08-1F-3F (hex) WondaLink Inc. - 081F3F (base 16) WondaLink Inc. - 2F, No. 23, R&D Road 2 - Science-Based Industrial Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 08-1F-EB (hex) BinCube - 081FEB (base 16) BinCube - Si Ming Shan Road 116, Beilun - Ningbo Zhejiang 315800 - CHINA - - 08-1F-F3 (hex) CISCO SYSTEMS, INC. - 081FF3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 08-25-22 (hex) ADVANSEE - 082522 (base 16) ADVANSEE - 9 Rue Alfred Kastler - CS30750 - NANTES 44307 - FRANCE - - 08-27-19 (hex) APS systems/electronic AG - 082719 (base 16) APS systems/electronic AG - Neumatt 4 - Niederbuchsiten SO 4626 - SWITZERLAND - - 08-2A-D0 (hex) SRD Innovations Inc. - 082AD0 (base 16) SRD Innovations Inc. - 11525 Valley Ridge Dr. NW - Calgary AB T3B 5T4 - CANADA - - 08-2C-B0 (hex) Network Instruments - 082CB0 (base 16) Network Instruments - 10701 Red Circle Dr - Minnetonka Minnesota 55343 - UNITED STATES - - 08-2E-5F (hex) Hewlett Packard - 082E5F (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 08-35-71 (hex) CASwell INC. - 083571 (base 16) CASwell INC. - 8F,No.242,Bo-Ai St., Shu-Lin Dist - New Taipei City 23845 - TAIWAN, PROVINCE OF CHINA - - 08-37-3D (hex) Samsung Electronics Co.,Ltd - 08373D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 08-37-9C (hex) Topaz Co. LTD. - 08379C (base 16) Topaz Co. LTD. - B305-22, Acrotower, 1591 Gwanyang-dong - Dongan-gu - Anyang-si Gyeonggi-Do 431-060 - KOREA, REPUBLIC OF - - 08-38-A5 (hex) Funkwerk plettac electronic GmbH - 0838A5 (base 16) Funkwerk plettac electronic GmbH - Wuerzburger Str. 150 - Fuerth Bavaria 90766 - GERMANY - - 08-3A-5C (hex) Junilab, Inc. - 083A5C (base 16) Junilab, Inc. - #205 107 Gyounggyo-Ro, Yeongtong-Gu, Suwon - Gyeonggi-Do, Republic of Korea (Lui-Dong, GSBC Business Incubation Center) - Suwon Gyeonggi-Do 443-766 - KOREA, REPUBLIC OF - - 08-3A-B8 (hex) Shinoda Plasma Co., Ltd. - 083AB8 (base 16) Shinoda Plasma Co., Ltd. - 4-6-7, Minatojima Minamimachi, Chuo-ku - Kobe Hyogo 6500047 - JAPAN - - 08-3D-88 (hex) Samsung Electronics Co.,Ltd - 083D88 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 08-3E-0C (hex) ARRIS Group, Inc. - 083E0C (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 08-3E-8E (hex) Hon Hai Precision Ind.Co.Ltd - 083E8E (base 16) Hon Hai Precision Ind.Co.Ltd - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 08-3F-3E (hex) WSH GmbH - 083F3E (base 16) WSH GmbH - Koelner Str. 58a - Gummersbach NRW 51645 - GERMANY - - 08-3F-76 (hex) Intellian Technologies, Inc. - 083F76 (base 16) Intellian Technologies, Inc. - 348-5 Chungho-Ri Jinwi-Myeon - Pyeongtaek-Si - Gyeonggi-Do 451-862 - KOREA, REPUBLIC OF - - 08-40-27 (hex) Gridstore Inc. - 084027 (base 16) Gridstore Inc. - 1975 Landings Dr. - Mountain View CA 94043 - UNITED STATES - - 08-46-56 (hex) VODALYS Ingénierie - 084656 (base 16) VODALYS Ingénierie - 14 rue du Patis Tatelin - Batiment D - RENNES Bretagne 35700 - FRANCE - - 08-48-2C (hex) Raycore Taiwan Co., LTD. - 08482C (base 16) Raycore Taiwan Co., LTD. - 3F-5, No.351, Sec.2, Zongshan Rd - Zonghe Dist, - New Taipei city 23504 - TAIWAN, PROVINCE OF CHINA - - 08-4E-1C (hex) H2A Systems, LLC - 084E1C (base 16) H2A Systems, LLC - 7545 Irvine Center Drive - Suite 200 - Irvine CA 92618 - UNITED STATES - - 08-4E-BF (hex) Broad Net Mux Corporation - 084EBF (base 16) Broad Net Mux Corporation - 4-1-8 Kounan Minato-ku - Tokyo 108-0075 - JAPAN - - 08-51-2E (hex) Orion Diagnostica Oy - 08512E (base 16) Orion Diagnostica Oy - Koivu-Mankkaan tie 6 - Espoo 02100 - FINLAND - - 08-52-40 (hex) EbV Elektronikbau- und Vertriebs GmbH - 085240 (base 16) EbV Elektronikbau- und Vertriebs GmbH - Heisterner Weg 8 - 12 - Burbach Nordrhein-Westfalen 57299 - GERMANY - - 08-57-00 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 085700 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4) - Central Science and Technology Park, - Shennan Road,Nanshan, Shenzhen Guangdong 518057 - CHINA - - 08-5A-E0 (hex) Recovision Technology Co., Ltd. - 085AE0 (base 16) Recovision Technology Co., Ltd. - 1709,No.5 Wanghai Road, - 2nd Software Park - Xiamen Fujian 361006 - CHINA - - 08-5B-0E (hex) Fortinet, Inc. - 085B0E (base 16) Fortinet, Inc. - 1090 Kifer Road - Sunnyvale California 94086 - UNITED STATES - - 08-5D-DD (hex) Mercury Corporation - 085DDD (base 16) Mercury Corporation - 531-6, Gajwadong, Seogu - Incheon 404-250 - KOREA, REPUBLIC OF - - 08-60-6E (hex) ASUSTek COMPUTER INC. - 08606E (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, Taipei 112 - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 08-62-66 (hex) ASUSTek COMPUTER INC. - 086266 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 08-63-61 (hex) Huawei Technologies Co., Ltd - 086361 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 08-68-D0 (hex) Japan System Design - 0868D0 (base 16) Japan System Design - Skyhills Deshio 3F - 3-4-1 Deshio Minami-ku - Hiroshima 734-0001 - JAPAN - - 08-68-EA (hex) EITO ELECTRONICS CO., LTD. - 0868EA (base 16) EITO ELECTRONICS CO., LTD. - 1-34-1 Shinmeidai - Hamura-shi Tokyo 205-0023 - JAPAN - - 08-6D-F2 (hex) Shenzhen MIMOWAVE Technology Co.,Ltd - 086DF2 (base 16) Shenzhen MIMOWAVE Technology Co.,Ltd - No.709,Wan XiangTian Cheng 1st Block, - Long-Gang District - Shenzhen Guangdong 518172 - CHINA - - 08-70-45 (hex) Apple - 087045 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 08-74-F6 (hex) Winterhalter Gastronom GmbH - 0874F6 (base 16) Winterhalter Gastronom GmbH - Tettnanger Straße 72 - Meckenbeuren Baden-Württemberg 88074 - GERMANY - - 08-75-72 (hex) Obelux Oy - 087572 (base 16) Obelux Oy - Kutomotie 6 B - Helsinki 00380 - FINLAND - - 08-76-18 (hex) ViE Technologies Sdn. Bhd. - 087618 (base 16) ViE Technologies Sdn. Bhd. - no. 85-A, Lintang Bayan Lepas 11, - Phase 4 - Bayan Lepas Penang 11900 - MALAYSIA - - 08-76-95 (hex) Auto Industrial Co., Ltd. - 087695 (base 16) Auto Industrial Co., Ltd. - 14Floor, #235 Hanshin IT Tower, - Guro-dong, Guro-gu - Seoul 152-768 - KOREA, REPUBLIC OF - - 08-76-FF (hex) Thomson Telecom Belgium - 0876FF (base 16) Thomson Telecom Belgium - Prins Boudewijnlaan 47 - Edegem 2650 - BELGIUM - - 08-79-99 (hex) AIM GmbH - 087999 (base 16) AIM GmbH - Sasbacherstraße 2 - Freiburg BW 79111 - GERMANY - - 08-7A-4C (hex) Huawei Technologies Co., Ltd - 087A4C (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 08-7B-AA (hex) SVYAZKOMPLEKTSERVICE, LLC - 087BAA (base 16) SVYAZKOMPLEKTSERVICE, LLC - Lenskaya 2-21 - Moscow 129327 - RUSSIAN FEDERATION - - 08-7C-BE (hex) Quintic Corp. - 087CBE (base 16) Quintic Corp. - 1600 Wyatt Dr., #8 - Santa Clara CA 95054 - UNITED STATES - - 08-7D-21 (hex) Altasec technology corporation - 087D21 (base 16) Altasec technology corporation - 9F-1, No.75, Sec.1, Xintai 5th Rd., - Xizhi Dist., - New Taipei City Taiwan 221 - TAIWAN, PROVINCE OF CHINA - - 08-80-39 (hex) Cisco SPVTG - 088039 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 08-81-BC (hex) HongKong Ipro Technology Co., Limited - 0881BC (base 16) HongKong Ipro Technology Co., Limited - Flat/Rm A3 9/F Silvercorp Int Tower - 707-713 Nathan Rd Mongk Ok - HONGKONG 999077 - HONG KONG - - 08-81-F4 (hex) Juniper Networks - 0881F4 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 08-86-3B (hex) Belkin International, Inc. - 08863B (base 16) Belkin International, Inc. - 12045 East Waterfront Drive - Playa Vista CA 90094 - UNITED STATES - - 08-8D-C8 (hex) Ryowa Electronics Co.,Ltd - 088DC8 (base 16) Ryowa Electronics Co.,Ltd - 1483-1 Takahara-machi - Yamagata-shi Yamagata-pref. 9900002 - JAPAN - - 08-8E-4F (hex) SF Software Solutions - 088E4F (base 16) SF Software Solutions - Buchenweg 32 - Großbettlingen Baden-Württemberg 72663 - GERMANY - - 08-8F-2C (hex) Hills Sound Vision & Lighting - 088F2C (base 16) Hills Sound Vision & Lighting - 1 Clyde Street - Silverwater New South Wales 2128 - AUSTRALIA - - 08-95-2A (hex) Technicolor CH USA Inc - 08952A (base 16) Technicolor CH USA Inc - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 08-96-D7 (hex) AVM GmbH - 0896D7 (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 08-97-58 (hex) Shenzhen Strong Rising Electronics Co.,Ltd DongGuan Subsidiary - 089758 (base 16) Shenzhen Strong Rising Electronics Co.,Ltd DongGuan Subsidiary - QingPing Road 2,Qinghutou village - TangXia Town - DongGuan GuangDong 523711 - CHINA - - 08-9E-01 (hex) QUANTA COMPUTER INC. - 089E01 (base 16) QUANTA COMPUTER INC. - No.211, Wen Hwa 2nd Rd., Kuei Shan Hsiang,Tao Yuan Shien, Taiwan, R. O. C. - Taoyuan Taiwan 33377 - TAIWAN, PROVINCE OF CHINA - - 08-9F-97 (hex) LEROY AUTOMATION - 089F97 (base 16) LEROY AUTOMATION - 35, Boulevard du Libre Echange - Saint Orens de Gameville 31650 - FRANCE - - 08-A1-2B (hex) ShenZhen EZL Technology Co., Ltd - 08A12B (base 16) ShenZhen EZL Technology Co., Ltd - RM21B, Building 2, China Phoenix Building, - No. 2008 Of Shennan Avenue, Futian District - ShenZhen GuangDong 518026 - CHINA - - 08-A5-C8 (hex) Sunnovo International Limited - 08A5C8 (base 16) Sunnovo International Limited - 1717 Haitai Building - Beisihuan Zhong Road - Beijing Beijing 100083 - CHINA - - 08-A9-5A (hex) Azurewave - 08A95A (base 16) Azurewave - 8F., No. 94, Baozhong Rd., Xindian - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 08-AC-A5 (hex) Benu Video, Inc. - 08ACA5 (base 16) Benu Video, Inc. - 300 Concord Rd., Suite #110 - Billerica MA 01821 - UNITED STATES - - 08-AF-78 (hex) Totus Solutions, Inc. - 08AF78 (base 16) Totus Solutions, Inc. - 1505 Wallace Drive, Suite 102 - Carrollton TX 75006 - UNITED STATES - - 08-B2-A3 (hex) Cynny Italia S.r.L. - 08B2A3 (base 16) Cynny Italia S.r.L. - Via delle Mantellate, 8 - Firenze FI 59021 - ITALY - - 08-B4-CF (hex) Abicom International - 08B4CF (base 16) Abicom International - The Old Grammar School - Phoenix Bank - Market Drayton Shropshire TF9 1JR - UNITED KINGDOM - - 08-B7-38 (hex) Lite-On Technogy Corp. - 08B738 (base 16) Lite-On Technogy Corp. - 18F, 392, RueyKuang Road, Neihu, - Taipei 11492 - TAIWAN, PROVINCE OF CHINA - - 08-B7-EC (hex) Wireless Seismic - 08B7EC (base 16) Wireless Seismic - 13100 SW Freeway - Suite 150 - Sugar Land TX 77478 - UNITED STATES - - 08-BB-CC (hex) AK-NORD EDV VERTRIEBSGES. mbH - 08BBCC (base 16) AK-NORD EDV VERTRIEBSGES. mbH - FRIEDRICHSTRASSE 10 - 25436 TORNESCH - GERMANY - - 08-BD-43 (hex) NETGEAR INC., - 08BD43 (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 08-BE-09 (hex) Astrol Electronic AG - 08BE09 (base 16) Astrol Electronic AG - Vorderi Böde 3 - Gewerbehaus Casora - Oberrohrdorf AG 5452 - SWITZERLAND - - 08-CA-45 (hex) Toyou Feiji Electronics Co., Ltd. - 08CA45 (base 16) Toyou Feiji Electronics Co., Ltd. - No.2 Building No.9 Yard, Dijin Road, - Haidian District - Beijing 100095 - CHINA - - 08-CC-68 (hex) Cisco - 08CC68 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 08-CD-9B (hex) samtec automotive electronics & software GmbH - 08CD9B (base 16) samtec automotive electronics & software GmbH - Saarstrasse 27 - Filderstadt Baden-Wuerttemberg 70794 - GERMANY - - 08-D0-9F (hex) CISCO SYSTEMS, INC. - 08D09F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 08-D0-B7 (hex) HISENSE ELECTRIC CO.,LTD. - 08D0B7 (base 16) HISENSE ELECTRIC CO.,LTD. - Qingdao Hisense Electric Co.,Ltd. - 11,Jiangxi Road - Qingdao Shandong 266071 - CHINA - - 08-D2-9A (hex) Proformatique - 08D29A (base 16) Proformatique - 10 bis rue Lucien Voilin - Puteaux 92800 - FRANCE - - 08-D3-4B (hex) Techman Electronics (Changshu) Co., Ltd. - 08D34B (base 16) Techman Electronics (Changshu) Co., Ltd. - No.66, Dalian Road, High-Tech Industrial Park - Changshu Economic Development Zone - Changshu Jiangsu Province 215500 - CHINA - - 08-D4-0C (hex) Intel Corporate - 08D40C (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 08-D4-2B (hex) Samsung Electronics - 08D42B (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 08-D5-C0 (hex) Seers Technology Co., Ltd - 08D5C0 (base 16) Seers Technology Co., Ltd - 1210 Techcenter, SKnTechnopark, 190-1 - Sangdaewond-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-721 - KOREA, REPUBLIC OF - - 08-D8-33 (hex) Shenzhen RF Technology Co,.Ltd - 08D833 (base 16) Shenzhen RF Technology Co,.Ltd - 5/F,Building 4 ,Baokun science and Technology Industrial Park - Dalang Street - Baoan District Shenzhen Guangdong 518109 - CHINA - - 08-DF-1F (hex) Bose Corporation - 08DF1F (base 16) Bose Corporation - The Mountain - Framingham MA 01701-9168 - UNITED STATES - - 08-E5-DA (hex) NANJING FUJITSU COMPUTER PRODUCTS CO.,LTD. - 08E5DA (base 16) NANJING FUJITSU COMPUTER PRODUCTS CO.,LTD. - NO.1,XIANXIN MID-ROAD - NANJING ECONOMIC AND TECHNOLOGICAL DEVELOPMENT ZONE - NANJING JIANGSU 210046 - CHINA - - 08-E6-72 (hex) JEBSEE ELECTRONICS CO.,LTD. - 08E672 (base 16) JEBSEE ELECTRONICS CO.,LTD. - 24-3, SIN LE ROAD, - TAINAN 70268 - TAIWAN, PROVINCE OF CHINA - - 08-E8-4F (hex) HUAWEI TECHNOLOGIES CO.,LTD - 08E84F (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base, - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 08-EA-44 (hex) Aerohive Networks, Inc. - 08EA44 (base 16) Aerohive Networks, Inc. - 330 Gibraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - 08-EB-29 (hex) Jiangsu Huitong Group Co.,Ltd. - 08EB29 (base 16) Jiangsu Huitong Group Co.,Ltd. - No. 24, Block 2, Taohuawu New District - Zhenjiang Jiangsu 212003 - CHINA - - 08-EB-74 (hex) Humax - 08EB74 (base 16) Humax - HUMAX Village, 11-4, Sunae-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-825 - KOREA, REPUBLIC OF - - 08-EB-ED (hex) World Elite Technology Co.,LTD - 08EBED (base 16) World Elite Technology Co.,LTD - 6/F Liyuan floor ,Dragon City North Road on the 3rd - Longgang Town Center Longgang - ShenZhen GuangDong 518100 - CHINA - - 08-EC-A9 (hex) Samsung Electronics Co.,Ltd - 08ECA9 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 08-ED-B9 (hex) Hon Hai Precision Ind. Co.,Ltd. - 08EDB9 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 08-EE-8B (hex) Samsung Elec Co.,Ltd - 08EE8B (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 08-EF-3B (hex) MCS Logic Inc. - 08EF3B (base 16) MCS Logic Inc. - 6F. Samho Center B Bldg., 275-6,Yangjae-Dong, Secho-Ku,Seoul - Seoul 137-941 - KOREA, REPUBLIC OF - - 08-EF-AB (hex) SAYME WIRELESS SENSOR NETWORK - 08EFAB (base 16) SAYME WIRELESS SENSOR NETWORK - Calle Albert Einstein 18, 4a - Ed. Salia - PCTCAN - Santander Cantabria 39011 - SPAIN - - 08-F1-B7 (hex) Towerstream Corpration - 08F1B7 (base 16) Towerstream Corpration - 55 Hammerlund Way - Middletown RI 02842 - UNITED STATES - - 08-F2-F4 (hex) Net One Partners Co.,Ltd. - 08F2F4 (base 16) Net One Partners Co.,Ltd. - 2-8 Higashi Shinagawa 2-chome, - Shinagawa-ku, - Tokyo 1400002 - JAPAN - - 08-F6-F8 (hex) GET Engineering - 08F6F8 (base 16) GET Engineering - 9350 Bond Ave - El Cajon CA 92021 - UNITED STATES - - 08-F7-28 (hex) GLOBO Multimedia Sp. z o.o. Sp.k. - 08F728 (base 16) GLOBO Multimedia Sp. z o.o. Sp.k. - Gryfinska 104 - Szczecin Zachodniopomorskie 70-772 - POLAND - - 08-FA-E0 (hex) Fohhn Audio AG - 08FAE0 (base 16) Fohhn Audio AG - Hohes Gestade 3-7 - Nuertingen BW 72622 - GERMANY - - 08-FC-52 (hex) OpenXS BV - 08FC52 (base 16) OpenXS BV - Koaibosk 3 - Terwispel Friesland 8407ED - NETHERLANDS - - 08-FC-88 (hex) Samsung Electronics Co.,Ltd - 08FC88 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 08-FD-0E (hex) Samsung Electronics Co.,Ltd - 08FD0E (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 0C-04-00 (hex) Jantar d.o.o. - 0C0400 (base 16) Jantar d.o.o. - Kranjska cesta 24 - Naklo Slovenia 4202 - SLOVENIA - - 0C-05-35 (hex) Juniper Systems - 0C0535 (base 16) Juniper Systems - 1132 W. 1700 N. - Logan UT 84321 - UNITED STATES - - 0C-11-05 (hex) Ringslink (Xiamen) Network Communication Technologies Co., Ltd - 0C1105 (base 16) Ringslink (Xiamen) Network Communication Technologies Co., Ltd - Suite 201-15, 31 WangHai Rd - Software Park II - Xiamen Fujian 361008 - CHINA - - 0C-12-62 (hex) zte corporation - 0C1262 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 0C-13-0B (hex) Uniqoteq Ltd. - 0C130B (base 16) Uniqoteq Ltd. - Lemminkaisenkatu 14-18 A - Turku 20520 - FINLAND - - 0C-14-20 (hex) Samsung Electronics Co.,Ltd - 0C1420 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 0C-15-39 (hex) Apple - 0C1539 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 0C-15-C5 (hex) SDTEC Co., Ltd. - 0C15C5 (base 16) SDTEC Co., Ltd. - 167, Churye-2Dong, Sasang-Gu, - Busan 617-716 - KOREA, REPUBLIC OF - - 0C-17-F1 (hex) TELECSYS - 0C17F1 (base 16) TELECSYS - 31 chemin du fief aux pretres - L'ORBRIE 85200 - FRANCE - - 0C-19-1F (hex) Inform Electronik - 0C191F (base 16) Inform Electronik - Emek mah.Ordu cad.No-49-51-53 - Sarigazi-Sancaktepe Istanbul 34785 - TURKEY - - 0C-1D-AF (hex) Beijing Xiaomi communications co.,ltd - 0C1DAF (base 16) Beijing Xiaomi communications co.,ltd - Office Building,The Rainbow City of China Resources, - NO.68,Qinghe Middle Street - Haidian District Beijing 100085 - CHINA - - 0C-1D-C2 (hex) SeAH Networks - 0C1DC2 (base 16) SeAH Networks - 9F, IT Venture Tower East Wing 78 Garak-Dong, - Seoul Songpa-gu 138-950 - KOREA, REPUBLIC OF - - 0C-20-26 (hex) noax Technologies AG - 0C2026 (base 16) noax Technologies AG - Am Forst 6 - Ebersberg 85560 - GERMANY - - 0C-27-24 (hex) Cisco - 0C2724 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 0C-27-55 (hex) Valuable Techologies Limited - 0C2755 (base 16) Valuable Techologies Limited - 602, Centre Point, J.B.Nagar, - Andheri-Kurla Road, Andheri (E) - Mumbai Maharashtra 400059 - INDIA - - 0C-2A-69 (hex) electric imp, incorporated - 0C2A69 (base 16) electric imp, incorporated - 5050 El Camino Real, Ste 221 - Los Altos California 94022 - UNITED STATES - - 0C-2A-E7 (hex) Beijing General Research Institute of Mining and Metallurgy - 0C2AE7 (base 16) Beijing General Research Institute of Mining and Metallurgy - Building 23, Zone 18 of ABP, No. 188 - South 4th Ring Road West - Beijing 100160 - CHINA - - 0C-2D-89 (hex) QiiQ Communications Inc. - 0C2D89 (base 16) QiiQ Communications Inc. - 30 East Beaver Creek Road - Unit 209 - Richmond Hill Ontario L4B 1J2 - CANADA - - 0C-30-21 (hex) Apple - 0C3021 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 0C-37-DC (hex) Huawei Technologies Co., Ltd - 0C37DC (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - 0C-38-3E (hex) Fanvil Technology Co., Ltd. - 0C383E (base 16) Fanvil Technology Co., Ltd. - Unit 3-B702, Creative Base (Chuangyi Park), - No. 328, Xinghu St., Suzhou Industrial Park - Suzhou, Jiangsu 215123 - CHINA - - 0C-39-56 (hex) Observator instruments - 0C3956 (base 16) Observator instruments - Rietdekkerstraat 6 - Ridderkerk Zuid Holland 2984 BM - NETHERLANDS - - 0C-3C-65 (hex) Dome Imaging Inc - 0C3C65 (base 16) Dome Imaging Inc - 400 Fifth Av - Suite 500 - Waltham MA 02451 - UNITED STATES - - 0C-3E-9F (hex) Apple, Inc - 0C3E9F (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 0C-41-3E (hex) Microsoft Corporation - 0C413E (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 0C-46-9D (hex) MS Sedco - 0C469D (base 16) MS Sedco - 8701 Castle Park Drive - Indianapolis 46256 - UNITED STATES - - 0C-47-3D (hex) Hitron Technologies. Inc - 0C473D (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C - Hsin-chu 300 - TAIWAN, PROVINCE OF CHINA - - 0C-48-85 (hex) LG Electronics - 0C4885 (base 16) LG Electronics - 60-39, Kasan-dong, Kumchon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 0C-4C-39 (hex) Mitrastar Technology - 0C4C39 (base 16) Mitrastar Technology - 4F No.6 Innovation Road II - Science Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 0C-4D-E9 (hex) Apple - 0C4DE9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 0C-4F-5A (hex) ASA-RT s.r.l. - 0C4F5A (base 16) ASA-RT s.r.l. - Strada del Lionetto 16/a - Torino To 10146 - ITALY - - 0C-51-F7 (hex) CHAUVIN ARNOUX - 0C51F7 (base 16) CHAUVIN ARNOUX - LA QUEUE DEVEE - REUX 14130 - FRANCE - - 0C-54-A5 (hex) PEGATRON CORPORATION - 0C54A5 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 0C-55-21 (hex) Axiros GmbH - 0C5521 (base 16) Axiros GmbH - Altlaufstrasse 34 - Munich Hoehenkirchen Bavaria 85635 - GERMANY - - 0C-56-5C (hex) HyBroad Vision (Hong Kong) Technology Co Ltd - 0C565C (base 16) HyBroad Vision (Hong Kong) Technology Co Ltd - Unit 1808 18/F Tower 3 Enterprise Square - 9 Sheung Yuet Road - Kowloon Bay - HONG KONG - - 0C-57-EB (hex) Mueller Systems - 0C57EB (base 16) Mueller Systems - 48 Leona Drive, Suite C - Middleboro MA 02346 - UNITED STATES - - 0C-5A-19 (hex) Axtion Sdn Bhd - 0C5A19 (base 16) Axtion Sdn Bhd - A13-07, Subang Avenue Serviced Suites - Persiaran Kemajuan SS16 - Subang Jaya Selangor 47500 - MALAYSIA - - 0C-5C-D8 (hex) DOLI Elektronik GmbH - 0C5CD8 (base 16) DOLI Elektronik GmbH - Adi-Maislinger-Str. 7 - Munich 81373 - GERMANY - - 0C-60-76 (hex) Hon Hai Precision Ind. Co.,Ltd. - 0C6076 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 0C-63-FC (hex) Nanjing Signway Technology Co., Ltd - 0C63FC (base 16) Nanjing Signway Technology Co., Ltd - Rm 1001,10/F,28 Ningshuang Rd, - Yuhuatai Dist. - Nanjing Jiangsu 210012 - CHINA - - 0C-68-03 (hex) Cisco - 0C6803 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 0C-6E-4F (hex) PrimeVOLT Co., Ltd. - 0C6E4F (base 16) PrimeVOLT Co., Ltd. - 2F-3, No. 9, Lane 3, Jihu Rd, Neihu - Taipei 11492 - TAIWAN, PROVINCE OF CHINA - - 0C-71-5D (hex) Samsung Electronics Co.,Ltd - 0C715D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 0C-72-2C (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 0C722C (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd, Nanshan - Shenzhen Guangdong Province 518057 - CHINA - - 0C-74-C2 (hex) Apple - 0C74C2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 0C-75-23 (hex) BEIJING GEHUA CATV NETWORK CO.,LTD - 0C7523 (base 16) BEIJING GEHUA CATV NETWORK CO.,LTD - No.35,N.Huayuan RD.,Haidian District - BEIJING 100083 - CHINA - - 0C-77-1A (hex) Apple - 0C771A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 0C-7D-7C (hex) Kexiang Information Technology Co, Ltd. - 0C7D7C (base 16) Kexiang Information Technology Co, Ltd. - Room 1502, Longxi Hotel No.3788 Jiangnan Avenue. - Hangzhou Zhejiang 310053 - CHINA - - 0C-81-12 (hex) PRIVATE - 0C8112 (base 16) - - 0C-82-30 (hex) SHENZHEN MAGNUS TECHNOLOGIES CO.,LTD - 0C8230 (base 16) SHENZHEN MAGNUS TECHNOLOGIES CO.,LTD - c-504,Skyworth Building,No.8 Road,High-tech south,Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - 0C-82-68 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 0C8268 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) Central Science and Technology Park,Shennan Rd - Shenzhen Guandong 518057 - CHINA - - 0C-82-6A (hex) Wuhan Huagong Genuine Optics Technology Co., Ltd - 0C826A (base 16) Wuhan Huagong Genuine Optics Technology Co., Ltd - Science & Technology Region of HUST, Donghu High-Tech Zone - Wuhan Hubei 430223 - CHINA - - 0C-84-11 (hex) A.O. Smith Water Products - 0C8411 (base 16) A.O. Smith Water Products - 25589 Hwy 1 - McBee SC 29101 - UNITED STATES - - 0C-84-84 (hex) Zenovia Electronics Inc. - 0C8484 (base 16) Zenovia Electronics Inc. - #206, 506B St. Albert Rd. - St. Albert AB T8N 5Z1 - CANADA - - 0C-84-DC (hex) Hon Hai Precision Ind. Co.,Ltd. - 0C84DC (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 0C-85-25 (hex) CISCO SYSTEMS, INC. - 0C8525 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 0C-89-10 (hex) Samsung Electronics Co.,LTD - 0C8910 (base 16) Samsung Electronics Co.,LTD - 416,Maetan 3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 0C-8B-FD (hex) Intel Corporate - 0C8BFD (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 0C-8C-8F (hex) Kamo Technology Limited - 0C8C8F (base 16) Kamo Technology Limited - Room 1502, 15/F., Yue Xiu Building, - 160-174 Lockhart Road, - Wanchai Hong Kong 160-174 - CHINA - - 0C-8C-DC (hex) Suunto Oy - 0C8CDC (base 16) Suunto Oy - Valimotie 7 - Vantaa Uusimaa 02710 - FINLAND - - 0C-8D-98 (hex) TOP EIGHT IND CORP - 0C8D98 (base 16) TOP EIGHT IND CORP - 8F.,No79-1 Zhouzi St., Neihu District, Taipei City (Neihu Technology Park) - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 0C-92-4E (hex) Rice Lake Weighing Systems - 0C924E (base 16) Rice Lake Weighing Systems - 230 West Coleman St - Rice Lake WI 54868 - UNITED STATES - - 0C-93-01 (hex) PT. Prasimax Inovasi Teknologi - 0C9301 (base 16) PT. Prasimax Inovasi Teknologi - Jl. Margonda Raya 494D - Depok Jawa Barat 16424 - INDONESIA - - 0C-93-FB (hex) BNS Solutions - 0C93FB (base 16) BNS Solutions - PO Box 508 - Walpole MA 02081 - UNITED STATES - - 0C-96-BF (hex) Huawei Technologies Co., Ltd - 0C96BF (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - 0C-9B-13 (hex) Shanghai Magic Mobile Telecommunication Co.Ltd. - 0C9B13 (base 16) Shanghai Magic Mobile Telecommunication Co.Ltd. - B7 parts, second floor - No. 30, East Fute Road - Waigaoqiao Free Trade Zone Shanghai 200131 - CHINA - - 0C-9D-56 (hex) Consort Controls Ltd - 0C9D56 (base 16) Consort Controls Ltd - 13 Campion Terrace - Leamington Spa CV32 4SU - UNITED KINGDOM - - 0C-9E-91 (hex) Sankosha Corporation - 0C9E91 (base 16) Sankosha Corporation - 1-12, Miyashimo - 1-Chome, Chuo-ku - Sagamihara-shi Kanagawa-ken 252-0212 - JAPAN - - 0C-A1-38 (hex) Blinq Wireless Inc. - 0CA138 (base 16) Blinq Wireless Inc. - 400 MARCH RD UNIT 240 - KANATA ON K2K3H4 - CANADA - - 0C-A2-F4 (hex) Chameleon Technology (UK) Limited - 0CA2F4 (base 16) Chameleon Technology (UK) Limited - Winters Barn, Haggs Farm Business Park - Haggs Road, Follifoot - Harrogate North Yorkshire HG3 1EQ - UNITED KINGDOM - - 0C-A4-02 (hex) Alcatel Lucent IPD - 0CA402 (base 16) Alcatel Lucent IPD - 600 March Drive - Kanata Ontario k2k2e6 - CANADA - - 0C-A4-2A (hex) OB Telecom Electronic Technology Co., Ltd - 0CA42A (base 16) OB Telecom Electronic Technology Co., Ltd - 17/F, Jiangong Building - No.20 Wensan Road - Hangzhou ZheJiang 310012 - CHINA - - 0C-A6-94 (hex) Sunitec Enterprise Co.,Ltd - 0CA694 (base 16) Sunitec Enterprise Co.,Ltd - 3F.,No.98-1,Mincyuan Rd.Sindian City - Taipei County 231 231141 - CHINA - - 0C-AC-05 (hex) Unitend Technologies Inc. - 0CAC05 (base 16) Unitend Technologies Inc. - No.6 Nanda'an Hutong, Xizhimeng st - 3 floor - Zicheng District Beijing 100035 - CHINA - - 0C-AF-5A (hex) GENUS POWER INFRASTRUCTURES LIMITED - 0CAF5A (base 16) GENUS POWER INFRASTRUCTURES LIMITED - SPL-3 RIICO INDUSTRIAL AREA - SITAPURA - JAIPUR RAJASTHAN 302022 - INDIA - - 0C-B3-19 (hex) Samsung Elec Co.,Ltd - 0CB319 (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 0C-B4-EF (hex) Digience Co.,Ltd. - 0CB4EF (base 16) Digience Co.,Ltd. - 204 Building for Growth, Gumi Electronics&Information Technology Research Institute, 17 Cheomdangieop-1ro, - Sandong-myeon, Gumi-si, - Gumi Gyeongbuk - KOREA, REPUBLIC OF - - 0C-B5-DE (hex) Alcatel Lucent - 0CB5DE (base 16) Alcatel Lucent - Via Energy Park, 14 - Vimercate MB 20871 - ITALY - - 0C-BC-9F (hex) Apple - 0CBC9F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 0C-BD-51 (hex) TCT Mobile Limited - 0CBD51 (base 16) TCT Mobile Limited - 70 Huifeng 4rd - ZhongKai Hi-tech Development District - Huizhou Guangdong 516006 - CHINA - - 0C-BF-15 (hex) Genetec - 0CBF15 (base 16) Genetec - 2280 boul Alfred-Nobel - Suite 400 - St. Laurent Quebec H4S 2A4 - CANADA - - 0C-C0-C0 (hex) MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO - 0CC0C0 (base 16) MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO - AV. INDUSTRIA 20/21 - EL TREBOL - TEPOTZOTLAN MEXICO 54600 - MEXICO - - 0C-C3-A7 (hex) Meritec - 0CC3A7 (base 16) Meritec - P.O. Box 8003 - Painesville Ohio 44077 - UNITED STATES - - 0C-C4-7A (hex) Super Micro Computer, Inc. - 0CC47A (base 16) Super Micro Computer, Inc. - 980 Rock Ave - San Jose CA 95131 - UNITED STATES - - 0C-C4-7E (hex) EUCAST Co., Ltd. - 0CC47E (base 16) EUCAST Co., Ltd. - Room 303, 1018-2 Unjung-dong, Bundang-Gu - Seongnam-si Kyunggi-do 463-440 - KOREA, REPUBLIC OF - - 0C-C6-55 (hex) Wuxi YSTen Technology Co.,Ltd. - 0CC655 (base 16) Wuxi YSTen Technology Co.,Ltd. - Room 1801,18F, North Star Times Tower, - No.8,Beichen East Road - Chaoyang District Beijing 100101 - CHINA - - 0C-C6-6A (hex) Nokia Corporation - 0CC66A (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 0C-C6-AC (hex) DAGS - 0CC6AC (base 16) DAGS - Ace High end Tower 7th 1802 - Seoul Geumcheon-gu 153-802 - KOREA, REPUBLIC OF - - 0C-C8-1F (hex) Summer Infant, Inc. - 0CC81F (base 16) Summer Infant, Inc. - 1275 Park East Drive - Woonsocket Rhode Island 02895 - UNITED STATES - - 0C-C9-C6 (hex) Samwin Hong Kong Limited - 0CC9C6 (base 16) Samwin Hong Kong Limited - Rm 901-902, 9/F, Futura Plaza, - 111-113 How Ming Street, Kwun Tong - Hong Kong - CHINA - - 0C-CB-8D (hex) ASCO Numatics GmbH - 0CCB8D (base 16) ASCO Numatics GmbH - Otto-Hahn-Str. 7-11 - Oelbronn-Duerrn 75248 - GERMANY - - 0C-CD-D3 (hex) EASTRIVER TECHNOLOGY CO., LTD. - 0CCDD3 (base 16) EASTRIVER TECHNOLOGY CO., LTD. - 30 JINNIU XINCUN - GUANCHENG DISTRICT - DONGGUAN GUANGDONG 523010 - CHINA - - 0C-CD-FB (hex) EDIC Systems Inc. - 0CCDFB (base 16) EDIC Systems Inc. - 1-3-7 Nakamachidai - Tuzuki word - Yokohama Kanagawa 224-0041 - JAPAN - - 0C-CF-D1 (hex) SPRINGWAVE Co., Ltd - 0CCFD1 (base 16) SPRINGWAVE Co., Ltd - #B-703,U-space 1-danji,670 Sampyeong-dong Bundang-gu - Seongnam-si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - 0C-D2-92 (hex) Intel Corporate - 0CD292 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 0C-D2-B5 (hex) Binatone Telecommunication Pvt. Ltd - 0CD2B5 (base 16) Binatone Telecommunication Pvt. Ltd - A36, G/F, Sector 4 - Noida - Uttar Pradesh 201301 - INDIA - - 0C-D5-02 (hex) Westell - 0CD502 (base 16) Westell - 750 N. Commons dr. - Aurora IL 60504 - UNITED STATES - - 0C-D6-96 (hex) Amimon Ltd - 0CD696 (base 16) Amimon Ltd - 2 Maskit st - PO Box 12618 - Herzlia 46733 - ISRAEL - - 0C-D7-C2 (hex) Axium Technologies, Inc. - 0CD7C2 (base 16) Axium Technologies, Inc. - 6625 N. Calle Eva Miranda - Ste B - Irwindale CA 91702 - UNITED STATES - - 0C-D9-96 (hex) CISCO SYSTEMS, INC. - 0CD996 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 0C-D9-C1 (hex) Visteon Corporation - 0CD9C1 (base 16) Visteon Corporation - One Village Center Drive - Van Buren Twp MI 48111 - UNITED STATES - - 0C-DA-41 (hex) Hangzhou H3C Technologies Co., Limited - 0CDA41 (base 16) Hangzhou H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang, P.R.China 310053 - CHINA - - 0C-DC-CC (hex) Inala Technologies - 0CDCCC (base 16) Inala Technologies - Inala House, 557 15th Road - Randjiespark - Midrand Gauteng 1685 - SOUTH AFRICA - - 0C-DD-EF (hex) Nokia Corporation - 0CDDEF (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - 0C-DF-A4 (hex) Samsung Electronics Co.,Ltd - 0CDFA4 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 0C-E0-E4 (hex) Plantronics, Inc - 0CE0E4 (base 16) Plantronics, Inc - 345 Encinal Street - Santa Cruz California 95060 - UNITED STATES - - 0C-E5-D3 (hex) DH electronics GmbH - 0CE5D3 (base 16) DH electronics GmbH - Am Anger 8 - Bergen 83346 - GERMANY - - 0C-E7-09 (hex) Fox Crypto B.V. - 0CE709 (base 16) Fox Crypto B.V. - P.O. box 638 - Delft ZH 2600 AP - NETHERLANDS - - 0C-E8-2F (hex) Bonfiglioli Vectron GmbH - 0CE82F (base 16) Bonfiglioli Vectron GmbH - Europark Fichtenhain B6 - Krefeld NRW 47807 - GERMANY - - 0C-E9-36 (hex) ELIMOS srl - 0CE936 (base 16) ELIMOS srl - Area Science Park - Padriciano 99 - TRIESTE 34149 - ITALY - - 0C-EE-E6 (hex) Hon Hai Precision Ind. Co.,Ltd. - 0CEEE6 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 0C-EF-7C (hex) AnaCom Inc - 0CEF7C (base 16) AnaCom Inc - 1996 Lundy Ave - San Jose CA 95131 - UNITED STATES - - 0C-EF-AF (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 0CEFAF (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 0C-F0-19 (hex) Malgn Technology Co., Ltd. - 0CF019 (base 16) Malgn Technology Co., Ltd. - Star Tower #305, 223-25 - Sangdaewon1-Dong, Jungwon-Gu - Seongnam-Si Kyounggi-Do 462-738 - KOREA, REPUBLIC OF - - 0C-F0-B4 (hex) Globalsat International Technology Ltd - 0CF0B4 (base 16) Globalsat International Technology Ltd - 17th floor,China Youse Building,No.6013 Shennan Avenue,Futian District, - Shenzhen Guangdong 518040 - CHINA - - 0C-F3-61 (hex) Java Information - 0CF361 (base 16) Java Information - Woolim Lions Valley 2nd B-1305 - Sangdaewon-Dong, Joonwon-Gu - Seongnam-Si Gyounggi-Do 462-120 - KOREA, REPUBLIC OF - - 0C-F3-EE (hex) EM Microelectronic - 0CF3EE (base 16) EM Microelectronic - Rue des Sors 3 - Marin-Epagnier Neuchatel 2074 - SWITZERLAND - - 0C-F4-05 (hex) Beijing Signalway Technologies Co.,Ltd - 0CF405 (base 16) Beijing Signalway Technologies Co.,Ltd - Room B 1905,Tri-tower - No.66 Zhongguancun eastRoad - Haidian District Beijing 100190 - CHINA - - 0C-F5-A4 (hex) Cisco - 0CF5A4 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 0C-F8-93 (hex) ARRIS Group, Inc. - 0CF893 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 0C-FC-83 (hex) Airoha Technology Corp., - 0CFC83 (base 16) Airoha Technology Corp., - 5F, No.6-5, Dushing Road , Hsinchu Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 0C-FE-45 (hex) Sony Computer Entertainment Inc. - 0CFE45 (base 16) Sony Computer Entertainment Inc. - 1-7-1, Konan - Minato-ku Tokyo 108-0075 - JAPAN - - 10-00-00 (hex) PRIVATE - 100000 (base 16) - - 10-00-5A (hex) IBM Corp - 10005A (base 16) IBM Corp - 3039 E Cornwallis Road - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 10-00-E8 (hex) NATIONAL SEMICONDUCTOR - 1000E8 (base 16) NATIONAL SEMICONDUCTOR - 2900 SEMICONDUCTOR DRIVE - SANTA CLARA CA 95051 - UNITED STATES - - 10-00-FD (hex) LaonPeople - 1000FD (base 16) LaonPeople - 402-3, Bundang Techno Park B, 148 - Yatap-dong, Bundang-gu - Sungnam-si Gyeonggi-do 463-760 - KOREA, REPUBLIC OF - - 10-01-CA (hex) Ashley Butterworth - 1001CA (base 16) Ashley Butterworth - P.O. Box 3410 - Santa Clara CA 95055 - UNITED STATES - - 10-05-CA (hex) Cisco - 1005CA (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 10-07-23 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 100723 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 10-08-B1 (hex) Hon Hai Precision Ind. Co.,Ltd. - 1008B1 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - Xiyong Town,Shapingba District - Chongqing 401332 - CHINA - - 10-09-0C (hex) Janome Sewing Machine Co., Ltd. - 10090C (base 16) Janome Sewing Machine Co., Ltd. - 1463 Hazama-Machi - Hachioji-Shi Tokyo 193-0941 - JAPAN - - 10-0B-A9 (hex) Intel Corporate - 100BA9 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 10-0C-24 (hex) pomdevices, LLC - 100C24 (base 16) pomdevices, LLC - 178 Colvard Park Dr - Durham NC 27713 - UNITED STATES - - 10-0D-2F (hex) Online Security Pty. Ltd. - 100D2F (base 16) Online Security Pty. Ltd. - 5/21-25 Redland Drive - Mitcham VIC 3132 - AUSTRALIA - - 10-0D-32 (hex) Embedian, Inc. - 100D32 (base 16) Embedian, Inc. - 10F., 95, Nanjing E. Rd. Sec. 4, - Taipei 10580 - TAIWAN, PROVINCE OF CHINA - - 10-0D-7F (hex) NETGEAR INC., - 100D7F (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 10-0E-2B (hex) NEC CASIO Mobile Communications - 100E2B (base 16) NEC CASIO Mobile Communications - 1753,Shimonumabe - Nakahara-ku - Kawasaki-shi Kanagawa 211-8666 - JAPAN - - 10-0E-7E (hex) Juniper networks - 100E7E (base 16) Juniper networks - 1194 N. Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 10-0F-18 (hex) Fu Gang Electronic(KunShan)CO.,LTD - 100F18 (base 16) Fu Gang Electronic(KunShan)CO.,LTD - No.6 Zheng Wei West Road, Jin Xi Town, Kun Shan City, Jiang Su Province, China - Jiang Su 215324 - CHINA - - 10-10-B6 (hex) McCain Inc - 1010B6 (base 16) McCain Inc - 2365 Oak Ridge Way - Vista CA 92081 - UNITED STATES - - 10-12-12 (hex) Vivo International Corporation Pty Ltd - 101212 (base 16) Vivo International Corporation Pty Ltd - 9-13 Bibby Street, - NSW Chiswick 2046 - AUSTRALIA - - 10-12-18 (hex) Korins Inc. - 101218 (base 16) Korins Inc. - Rm. 608, Suntechcity Bldg. - Dunchon-Daero #474 - Seongnam Gyeonggi 462-725 - KOREA, REPUBLIC OF - - 10-12-48 (hex) ITG, Inc. - 101248 (base 16) ITG, Inc. - YASUHARA BLDG 302, 1-42-6, ITABASHI, - ITABASHI-KU TOKYO 173-0004 - JAPAN - - 10-13-EE (hex) Justec International Technology INC. - 1013EE (base 16) Justec International Technology INC. - 7F-2 No 113 Zihyou Road - Hsinchu City 30041 - TAIWAN, PROVINCE OF CHINA - - 10-18-9E (hex) Elmo Motion Control - 10189E (base 16) Elmo Motion Control - 64 Gisin St. - Petach Tikva 49103 - ISRAEL - - 10-1B-54 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 101B54 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 10-1C-0C (hex) Apple - 101C0C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95051 - UNITED STATES - - 10-1D-51 (hex) ON-Q LLC dba ON-Q Mesh Networks - 101D51 (base 16) ON-Q LLC dba ON-Q Mesh Networks - 2859 Mandela Parkway - Oakland CA 94611 - UNITED STATES - - 10-1D-C0 (hex) Samsung Electronics Co.,Ltd - 101DC0 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 10-1F-74 (hex) Hewlett-Packard Company - 101F74 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 10-22-79 (hex) ZeroDesktop, Inc. - 102279 (base 16) ZeroDesktop, Inc. - 125 University Ave, Suite 150 - Palo Alto California 94301 - UNITED STATES - - 10-27-BE (hex) TVIP - 1027BE (base 16) TVIP - 190000 ul. Decabristov, h.6 Ð, of.10-Ð - Saint-Petersburg 197227 - RUSSIAN FEDERATION - - 10-28-31 (hex) Morion Inc. - 102831 (base 16) Morion Inc. - Shosse Kosmonavtov, 111 - Perm Permsky Krai 614990 - RUSSIAN FEDERATION - - 10-2C-83 (hex) XIMEA - 102C83 (base 16) XIMEA - Lesna 52 - Marianka SK 90033 - SLOVAKIA - - 10-2D-96 (hex) Looxcie Inc. - 102D96 (base 16) Looxcie Inc. - 1196 Borregas Ave. - Suite 200 - Sunnyvale CA 94089 - UNITED STATES - - 10-2E-AF (hex) Texas Instruments - 102EAF (base 16) Texas Instruments - 12500 TI Boulevard MS 8723 - Dallas TX 75243 - UNITED STATES - - 10-2F-6B (hex) Microsoft Corporation - 102F6B (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 10-30-47 (hex) Samsung Electronics Co.,Ltd - 103047 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 10-33-78 (hex) FLECTRON Co., LTD - 103378 (base 16) FLECTRON Co., LTD - A-625, Sigma2, Tancheonsang-ro 164 - Bundang-gu - Seongnam-si Gyeonggi-do 463-741 - KOREA, REPUBLIC OF - - 10-37-11 (hex) Simlink AS - 103711 (base 16) Simlink AS - Otto Nielsens Veg 12 - Trondheim N-7004 - NORWAY - - 10-3B-59 (hex) Samsung Electronics Co.,Ltd - 103B59 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 10-3D-EA (hex) HFC Technology (Beijing) Ltd. Co. - 103DEA (base 16) HFC Technology (Beijing) Ltd. Co. - Building #3, Room 1214 - Zhongguancun Software Park (ZPARK) - Beijing AP (Area Pacific) 100193 - CHINA - - 10-40-F3 (hex) Apple - 1040F3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 10-41-7F (hex) Apple Inc - 10417F (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 10-43-69 (hex) Soundmax Electronic Limited - 104369 (base 16) Soundmax Electronic Limited - Room#1505, Oriental plaza, #1072 JianShe Road - SHENZHEN Guangdong 518001 - CHINA - - 10-44-5A (hex) Shaanxi Hitech Electronic Co., LTD - 10445A (base 16) Shaanxi Hitech Electronic Co., LTD - 35 Tuanjienan Rode, - Xian Shaanxi 710075 - CHINA - - 10-45-BE (hex) Norphonic AS - 1045BE (base 16) Norphonic AS - Fabrikkgaten 10 - Bergen 5059 - NORWAY - - 10-45-F8 (hex) LNT-Automation GmbH - 1045F8 (base 16) LNT-Automation GmbH - Hans-Paul-Kaysser-Straße 1 - Leutenbach-Nellmersbach BW D-71397 - GERMANY - - 10-47-80 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 104780 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 10-48-B1 (hex) Beijing Duokan Technology Limited - 1048B1 (base 16) Beijing Duokan Technology Limited - Room 1105, Changxin Building, No.39 Anding Road - Chaoyang District Beijing 100029 - CHINA - - 10-4A-7D (hex) Intel Corporate - 104A7D (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 10-4B-46 (hex) Mitsubishi Electric Corporation - 104B46 (base 16) Mitsubishi Electric Corporation - 2-7-3 - Marunouchi - Chiyoda-ku Tokyo 100-8310 - JAPAN - - 10-4D-77 (hex) Innovative Computer Engineering - 104D77 (base 16) Innovative Computer Engineering - 10302 Eaton Place STE 100 - Fairfax VA 22030 - UNITED STATES - - 10-4E-07 (hex) Shanghai Genvision Industries Co.,Ltd - 104E07 (base 16) Shanghai Genvision Industries Co.,Ltd - 2/F Building E,NO.55,Luo Jin Road,MinHang District,Shanghai - Shanghai Shanghai 200237 - CHINA - - 10-51-72 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 105172 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 10-56-CA (hex) Peplink International Ltd. - 1056CA (base 16) Peplink International Ltd. - 17/F, Park Building, - 476 Castle Peak Road, - Cheung Sha Wan - HONG KONG - - 10-5C-3B (hex) Perma-Pipe, Inc. - 105C3B (base 16) Perma-Pipe, Inc. - 7720 Lehigh Ave - Niles IL 60714 - UNITED STATES - - 10-5C-BF (hex) DuroByte Inc - 105CBF (base 16) DuroByte Inc - 6008 6th Concession N - RR 4 - Amherstburg Ontario N9V2Y9 - CANADA - - 10-5F-06 (hex) Actiontec Electronics, Inc - 105F06 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 10-5F-49 (hex) Cisco SPVTG - 105F49 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 10-60-4B (hex) Hewlett Packard - 10604B (base 16) Hewlett Packard - 11445 Compaq Center Drive W - Houston Texas 77070 - UNITED STATES - - 10-62-C9 (hex) Adatis GmbH & Co. KG - 1062C9 (base 16) Adatis GmbH & Co. KG - Forchheimer Straße 6 - Nürnberg Bavaria 90425 - GERMANY - - 10-64-E2 (hex) ADFweb.com s.r.l. - 1064E2 (base 16) ADFweb.com s.r.l. - Strada Nuova, 17 - . - Mareno di Piave Treviso 31010 - ITALY - - 10-65-A3 (hex) Core Brands LLC - 1065A3 (base 16) Core Brands LLC - 1880 South McDowell Blvd - 2nd Floor - Petaluma CA 94954 - UNITED STATES - - 10-65-CF (hex) IQSIM - 1065CF (base 16) IQSIM - 2000 Route des Lucioles - Les Algorithmes Aristote A - BIOT 06410 - FRANCE - - 10-66-82 (hex) NEC Platforms, Ltd. - 106682 (base 16) NEC Platforms, Ltd. - 800 Shimomata - Kakegawa Shizuoka 436-8501 - JAPAN - - 10-68-3F (hex) LG Electronics - 10683F (base 16) LG Electronics - 60-39, Gasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 10-6F-3F (hex) Buffalo Inc. - 106F3F (base 16) Buffalo Inc. - AKAMONDORI Bldg., 30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref. 460-8315 - JAPAN - - 10-6F-EF (hex) Ad-Sol Nissin Corp - 106FEF (base 16) Ad-Sol Nissin Corp - Rivage Shinagawa, 4-1-8 Kounan - Minato-ku Tokyo 108-0075 - JAPAN - - 10-71-F9 (hex) Cloud Telecomputers, LLC - 1071F9 (base 16) Cloud Telecomputers, LLC - 1032 Elwell Court - Suite 222 - Palo Alto CA 94303 - UNITED STATES - - 10-76-8A (hex) EoCell - 10768A (base 16) EoCell - 149 Beaconsfield Street - Silverwater NSW 2128 - AUSTRALIA - - 10-77-B1 (hex) Samsung Electronics Co.,LTD - 1077B1 (base 16) Samsung Electronics Co.,LTD - 416,Maetan 3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 10-78-73 (hex) Shenzhen Jinkeyi Communication Co., Ltd. - 107873 (base 16) Shenzhen Jinkeyi Communication Co., Ltd. - No. 10 Shun King Road, Zhen Ping Xi Cun, - Pingdi Street, Longgang District - Shenzhen Guangdong 518117 - CHINA - - 10-78-CE (hex) Hanvit SI, Inc. - 1078CE (base 16) Hanvit SI, Inc. - #201 Daeheung Building, 265-18 Yangjae-dong - Seocho-gu - Seoul 137130 - KOREA, REPUBLIC OF - - 10-78-D2 (hex) ELITEGROUP COMPUTER SYSTEM CO., LTD. - 1078D2 (base 16) ELITEGROUP COMPUTER SYSTEM CO., LTD. - NO. 239, Sec. 2, Ti Ding Blvd. - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 10-7A-86 (hex) U&U ENGINEERING INC. - 107A86 (base 16) U&U ENGINEERING INC. - No.15, Gaoyang S. Rd - Long-tan Township - Taoyuan County 325-44 - TAIWAN, PROVINCE OF CHINA - - 10-7B-EF (hex) ZyXEL Communications Corp - 107BEF (base 16) ZyXEL Communications Corp - No. 6 Innovation Road II - Science Park - Hsichu 300 - TAIWAN, PROVINCE OF CHINA - - 10-83-D2 (hex) Microseven Systems, LLC - 1083D2 (base 16) Microseven Systems, LLC - 404 South Lemon Ave., #9 - Walnut California 91789 - UNITED STATES - - 10-88-0F (hex) Daruma Telecomunicações e Informática S.A. - 10880F (base 16) Daruma Telecomunicações e Informática S.A. - AVENIDA INDEPENDENCIA, 3500, LOTEAMENTO INDUSTRIAL - Taubaté São Paulo 12032-000 - BRAZIL - - 10-88-CE (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 1088CE (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 10-8A-1B (hex) RAONIX Inc. - 108A1B (base 16) RAONIX Inc. - Changeop-Center 710, Shin-Gu Univ. Gwangmyeong-ro 377, Jungwon-gu - Seongnam-si Gyeonggi-do 462-743 - KOREA, REPUBLIC OF - - 10-8C-CF (hex) CISCO SYSTEMS, INC. - 108CCF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 10-92-66 (hex) Samsung Electronics Co.,Ltd - 109266 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 10-93-E9 (hex) Apple - 1093E9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 10-98-36 (hex) Dell Inc. - 109836 (base 16) Dell Inc. - One Dell Way - MS: RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 10-9A-B9 (hex) Tosibox Oy - 109AB9 (base 16) Tosibox Oy - Elektroniikkatie 8 - Oulu 90590 - FINLAND - - 10-9A-DD (hex) Apple - 109ADD (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 10-9F-A9 (hex) Actiontec Electronics, Inc - 109FA9 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 10-A1-3B (hex) FUJIKURA RUBBER LTD. - 10A13B (base 16) FUJIKURA RUBBER LTD. - 1-840,Mihashi,Omiya - Saitama 330-0856 - JAPAN - - 10-A5-D0 (hex) Murata Manufacturing Co.,Ltd. - 10A5D0 (base 16) Murata Manufacturing Co.,Ltd. - 1-10-1,Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 10-A6-59 (hex) Mobile Create Co.,Ltd. - 10A659 (base 16) Mobile Create Co.,Ltd. - Kakukita 2-20-8 - Oita 870-0848 - JAPAN - - 10-A7-43 (hex) SK Mtek Limited - 10A743 (base 16) SK Mtek Limited - Flat/Rm 1808, 18F Tower II, Admirality - 18 Harcourt Road - Hong Kong - HONG KONG - - 10-A9-32 (hex) Beijing Cyber Cloud Technology Co. ,Ltd. - 10A932 (base 16) Beijing Cyber Cloud Technology Co. ,Ltd. - 2/F, Tower B, Jingmeng High-tech Building. No. 5 Shangdi East Road, Haidian District. - Beijing 100085 - CHINA - - 10-AE-60 (hex) PRIVATE - 10AE60 (base 16) - - 10-AF-78 (hex) Shenzhen ATUE Technology Co., Ltd - 10AF78 (base 16) Shenzhen ATUE Technology Co., Ltd - 3/F,Building 2nd, Xintang Industry Zone, - Fuyong Town,Bao'an District - Shenzhen Guangdong 518103 - CHINA - - 10-B2-6B (hex) base Co.,Ltd. - 10B26B (base 16) base Co.,Ltd. - F1 92 building taoyuancun longzhu road - Nanshan District - Shenzhen Guangdong 518000 - CHINA - - 10-B7-13 (hex) PRIVATE - 10B713 (base 16) - - 10-B7-F6 (hex) Plastoform Industries Ltd. - 10B7F6 (base 16) Plastoform Industries Ltd. - Units 1506A - 1512, Mita Centre, - 552-566 Castle Peak Road - Kwai Chung - HONG KONG - - 10-B9-FE (hex) Lika srl - 10B9FE (base 16) Lika srl - Via San Lorenzo 25 - Carrè Vicenza 36010 - ITALY - - 10-BA-A5 (hex) GANA I&C CO., LTD - 10BAA5 (base 16) GANA I&C CO., LTD - 154-17 kyoungdong B/D 3F karak-dong songpa-gu - Seoul Korea 138-160 - KOREA, REPUBLIC OF - - 10-BD-18 (hex) CISCO SYSTEMS, INC. - 10BD18 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 10-BF-48 (hex) ASUSTEK COMPUTER INC. - 10BF48 (base 16) ASUSTEK COMPUTER INC. - 15,LI-TE RD.,PEITOU - TAIPEI TAIWAN 112 - TAIWAN, PROVINCE OF CHINA - - 10-C0-7C (hex) Blu-ray Disc Association - 10C07C (base 16) Blu-ray Disc Association - 4444 Riverside Drive #103 - Burbank California 91505 - UNITED STATES - - 10-C2-BA (hex) UTT Co., Ltd. - 10C2BA (base 16) UTT Co., Ltd. - #41, 18-gil, Seocho Jungang-ro, Seocho-gu - Seoul - 135-913 - KOREA, REPUBLIC OF - - 10-C3-7B (hex) ASUSTek COMPUTER INC. - 10C37B (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 10-C5-86 (hex) BIO SOUND LAB CO., LTD. - 10C586 (base 16) BIO SOUND LAB CO., LTD. - Suite 311, 312 SKn Techno Park - Biz Center 190-1 Sangdaewon-dong, Jungwon-gu - Seongnam-si Gyeonggi-do, 462-721 - KOREA, REPUBLIC OF - - 10-C6-1F (hex) Huawei Technologies Co., Ltd - 10C61F (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - 10-C6-7E (hex) SHENZHEN JUCHIN TECHNOLOGY CO., LTD - 10C67E (base 16) SHENZHEN JUCHIN TECHNOLOGY CO., LTD - Unit 423 4/B NO.1, Central Business District - HuaMeiJiu ,XinHu Road ,Bao'An District - Shenzhen Guangdong 518000 - CHINA - - 10-C6-FC (hex) Garmin International - 10C6FC (base 16) Garmin International - 1200 East 151st Street - Olathe KS 66062 - UNITED STATES - - 10-C7-3F (hex) Midas Klark Teknik Ltd - 10C73F (base 16) Midas Klark Teknik Ltd - Klark Teknik Building - Walter Nash Road - Kidderminster Worcestershire DY11 7HJ - UNITED KINGDOM - - 10-CA-81 (hex) PRECIA - 10CA81 (base 16) PRECIA - Le ruissol VEYRAS - BP 106 - PRIVAS 07001 - FRANCE - - 10-CC-DB (hex) AXIMUM PRODUITS ELECTRONIQUES - 10CCDB (base 16) AXIMUM PRODUITS ELECTRONIQUES - ZI DELTA INDUSTRIE - BP 71 LA VALENTINE - MARSEILLE CEDEX 11 13368 - FRANCE - - 10-CD-AE (hex) Avaya, Inc - 10CDAE (base 16) Avaya, Inc - 211 Mt. Airy Road - Basking Ridge NJ 079202311 - UNITED STATES - - 10-D1-DC (hex) INSTAR Deutschland GmbH - 10D1DC (base 16) INSTAR Deutschland GmbH - Auf der Hostert 17 - Huenstetten Bechtheim Hessen 65510 - GERMANY - - 10-D3-8A (hex) Samsung Electronics Co.,Ltd - 10D38A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 10-D5-42 (hex) Samsung Electronics Co.,Ltd - 10D542 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 10-DD-B1 (hex) Apple - 10DDB1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 10-DD-F4 (hex) Maxway Electronics CO.,LTD - 10DDF4 (base 16) Maxway Electronics CO.,LTD - 2F Building 4,A Section,3rd Industrial zone,Tangtou - Shiyan town,Bao’an district - Shenzhen Guangdong 518018 - CHINA - - 10-DE-E4 (hex) automationNEXT GmbH - 10DEE4 (base 16) automationNEXT GmbH - Millennium Park 4 - Lustenau Vorarlberg 6890 - AUSTRIA - - 10-DF-8B (hex) Shenzhen CareDear Communication Technology Co.,Ltd - 10DF8B (base 16) Shenzhen CareDear Communication Technology Co.,Ltd - No.605,6th floor, 1st Section, 25th Building, Science and Technology Park Industrial Zone, median space, High-tech Zone - Nanshan District, ShenZhen City, China - ShenZhen Guangdong 518000 - CHINA - - 10-E2-D5 (hex) Qi Hardware Inc. - 10E2D5 (base 16) Qi Hardware Inc. - 555 4TH STREET #403 - San Francisco CA 94107 - UNITED STATES - - 10-E3-C7 (hex) Seohwa Telecom - 10E3C7 (base 16) Seohwa Telecom - 678 Seohwa Bldg - Gasan-Dong, Gumcheon-Gu Seoul 153-803 - KOREA, REPUBLIC OF - - 10-E4-AF (hex) APR, LLC - 10E4AF (base 16) APR, LLC - 4800 US HWY 280 West - Opelika AL 36801 - UNITED STATES - - 10-E6-AE (hex) Source Technologies, LLC - 10E6AE (base 16) Source Technologies, LLC - 2910 Whitehall Park Drive - Charlotte NC 28273 - UNITED STATES - - 10-E8-78 (hex) Alcatel-Lucent - 10E878 (base 16) Alcatel-Lucent - 600 March Rd - Kanata Ontario K2K 2E6 - CANADA - - 10-E8-EE (hex) PhaseSpace - 10E8EE (base 16) PhaseSpace - 1933 Davis St Suite 312 - San Leandro CA 94577 - UNITED STATES - - 10-EA-59 (hex) Cisco SPVTG - 10EA59 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 10-EE-D9 (hex) Canoga Perkins Corporation - 10EED9 (base 16) Canoga Perkins Corporation - 20600 Prairie Street - Chatsworth CA 91311 - UNITED STATES - - 10-F3-11 (hex) Cisco - 10F311 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 10-F3-DB (hex) Gridco Systems, Inc. - 10F3DB (base 16) Gridco Systems, Inc. - 10-L Commerice Way - Woburn MA 01801 - UNITED STATES - - 10-F4-9A (hex) T3 Innovation - 10F49A (base 16) T3 Innovation - 808 Calle Plano - Camarillo CA 93012 - UNITED STATES - - 10-F6-81 (hex) vivo Mobile Communication Co., Ltd. - 10F681 (base 16) vivo Mobile Communication Co., Ltd. - #283,BBK Road - Wusha,Chang'An DongGuan City,Guangdong, 523860 - CHINA - - 10-F9-6F (hex) LG Electronics - 10F96F (base 16) LG Electronics - 60-39 , Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 10-F9-EE (hex) Nokia Corporation - 10F9EE (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 10-FA-CE (hex) Reacheng Communication Technology Co.,Ltd - 10FACE (base 16) Reacheng Communication Technology Co.,Ltd - Building No.5-401, - No.3000 Long Dong Avenue, - Pu Dong New District, Shanghai 201203 - CHINA - - 10-FB-F0 (hex) KangSheng LTD. - 10FBF0 (base 16) KangSheng LTD. - 2F., No.11, - Wuquan 6th Rd., Wugu Dist. - New Taipei City 24889 - TAIWAN, PROVINCE OF CHINA - - 10-FC-54 (hex) Shany Electronic Co., Ltd. - 10FC54 (base 16) Shany Electronic Co., Ltd. - 4F, No. 92, Section 1, Nei-Hu Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 10-FE-ED (hex) TP-LINK TECHNOLOGIES CO., LTD. - 10FEED (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park - Shennan Rd, Nanshan - shenzhen guangdong Province 518057 - CHINA - - 11-00-AA (hex) PRIVATE - 1100AA (base 16) - - 14-07-08 (hex) PRIVATE - 140708 (base 16) - - 14-07-E0 (hex) Abrantix AG - 1407E0 (base 16) Abrantix AG - Foerrlibuckstrasse 66 - Zuerich ZH 8005 - SWITZERLAND - - 14-0C-76 (hex) FREEBOX SAS - 140C76 (base 16) FREEBOX SAS - 16 rue de la Ville l'Eveque - PARIS 75008 - FRANCE - - 14-0D-4F (hex) Flextronics International - 140D4F (base 16) Flextronics International - 2241 Lundy Ave. - San Jose CA 95131 - UNITED STATES - - 14-10-9F (hex) Apple - 14109F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 14-13-30 (hex) Anakreon UK LLP - 141330 (base 16) Anakreon UK LLP - 5-th Floor - 52-54 Gracechurch Street - London EC3V 0EH - UNITED KINGDOM - - 14-14-4B (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD - 14144B (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD - 19-22# Building,Star-net Science Plaza,Juyuanzhou, - 618 Jinshan Road - FUZHOU FUJIAN 350002 - CHINA - - 14-15-7C (hex) TOKYO COSMOS ELECTRIC CO.,LTD. - 14157C (base 16) TOKYO COSMOS ELECTRIC CO.,LTD. - 2-268 Sobudai - Zama Kanagawa 252-8550 - JAPAN - - 14-1A-51 (hex) Treetech Sistemas Digitais - 141A51 (base 16) Treetech Sistemas Digitais - Praca Claudino Alves, 141 - Atibaia São Paulo 12940-800 - BRAZIL - - 14-1A-A3 (hex) Motorola Mobility LLC - 141AA3 (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - 14-1B-BD (hex) Volex Inc. - 141BBD (base 16) Volex Inc. - 915 Tate Blvd. SE - Suite 130 - Hickory NC 28602 - UNITED STATES - - 14-1B-F0 (hex) Intellimedia Systems Ltd - 141BF0 (base 16) Intellimedia Systems Ltd - Sandhill Barn - Sandhill Lane - Washington West Sussex RH204TD - UNITED KINGDOM - - 14-1F-BA (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 141FBA (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 14-22-DB (hex) eero inc. - 1422DB (base 16) eero inc. - 230 9th St. - San Francisco CA 94103 - UNITED STATES - - 14-23-D7 (hex) EUTRONIX CO., LTD. - 1423D7 (base 16) EUTRONIX CO., LTD. - EUTRONIX BLDG. 4TH FLOOR - 861-1 GWANYANG-DONG DONGAN-GU - ANYANG KYEONGGI 431-804 - KOREA, REPUBLIC OF - - 14-29-71 (hex) NEMOA ELECTRONICS (HK) CO. LTD - 142971 (base 16) NEMOA ELECTRONICS (HK) CO. LTD - ROOM 610, B1 Area, MINGYOU PURCHASING & DISPLAYING CENTER, - BAOYUAN ROAD, BAOAN DISTRICT, - SHENZHEN GUANGDONG 518000 - CHINA - - 14-2B-D2 (hex) Armtel Ltd. - 142BD2 (base 16) Armtel Ltd. - 33A Smolenskaya str. - St. Petersburg 196084 - RUSSIAN FEDERATION - - 14-2B-D6 (hex) Guangdong Appscomm Co.,Ltd - 142BD6 (base 16) Guangdong Appscomm Co.,Ltd - Rm 903, Block C3, Chuangxin Building, No.182, - Science Road, Science City, LuoGang Zone - Guangzhou Guangdong 510663 - CHINA - - 14-2D-27 (hex) Hon Hai Precision Ind. Co.,Ltd. - 142D27 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District,Chongqing,China - Chongqing Chongqing 401332 - CHINA - - 14-2D-8B (hex) Incipio Technologies, Inc - 142D8B (base 16) Incipio Technologies, Inc - 6001 Oak Canyon - Irvine CA 92618 - UNITED STATES - - 14-2D-F5 (hex) Amphitech - 142DF5 (base 16) Amphitech - 1, rue Robert & Sonia DELAUNAY - Paris 75011 - FRANCE - - 14-30-7A (hex) Avermetrics - 14307A (base 16) Avermetrics - 2973 Glendale Blvd. - Los Angeles CA 90039 - UNITED STATES - - 14-30-C6 (hex) Motorola Mobility LLC - 1430C6 (base 16) Motorola Mobility LLC - 600 North US Highway 45 - Libertyville IL 60048 - UNITED STATES - - 14-32-D1 (hex) Samsung Electronics Co.,Ltd - 1432D1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 14-35-8B (hex) Mediabridge Products, LLC. - 14358B (base 16) Mediabridge Products, LLC. - 1951 Old Cuthbert Rd - Suite 301 - Cherry Hill New Jersey 08034 - UNITED STATES - - 14-35-B3 (hex) Future Designs, Inc. - 1435B3 (base 16) Future Designs, Inc. - 2702 Triana Blvd - Huntsville AL 35805 - UNITED STATES - - 14-36-05 (hex) Nokia Corporation - 143605 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 14-36-C6 (hex) Lenovo Mobile Communication Technology Ltd. - 1436C6 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999, Qishan North 2nd Road, Information & Optoelectronics Park, Torch Hi-tech Industry Development Zone, Xiamen, P.R.China - Xiamen Fujian 361006 - CHINA - - 14-37-3B (hex) PROCOM Systems - 14373B (base 16) PROCOM Systems - #1001, Kranz Techno, 5442-1 - Sangdaewon-dong, Jungwon-gu - Seongnam-si Gyunggi-do 462-729 - KOREA, REPUBLIC OF - - 14-3A-EA (hex) Dynapower Company LLC - 143AEA (base 16) Dynapower Company LLC - 85 Meadowland Drive - South Burlington VT 05403 - UNITED STATES - - 14-3D-F2 (hex) Beijing Shidai Hongyuan Network Communication Co.,Ltd - 143DF2 (base 16) Beijing Shidai Hongyuan Network Communication Co.,Ltd - #505, 5F, Tower 3 - No.11 , Hepingli East Street, Dongcheng, Beijing - Beijing 100000 - CHINA - - 14-3E-60 (hex) Alcatel-Lucent - 143E60 (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 14-41-46 (hex) Honeywell (China) Co., LTD - 144146 (base 16) Honeywell (China) Co., LTD - No. 100, Zunyi Road, Changning District - Shanghai Shanghai 200051 - CHINA - - 14-41-E2 (hex) Monaco Enterprises, Inc. - 1441E2 (base 16) Monaco Enterprises, Inc. - 14820 E. Sprague Ave. - Spokane WA 99216 - UNITED STATES - - 14-43-19 (hex) Creative&Link Technology Limited - 144319 (base 16) Creative&Link Technology Limited - ROOM 704 HONG JIN GE BLD. NO.3018,YANHE SOUTH ROAD - HUANGBEI ST.,LUOHU - Shenzhen Guangdong 518002 - CHINA - - 14-46-E4 (hex) AVISTEL - 1446E4 (base 16) AVISTEL - 15 rue Auguste Bartholdi - Carrieres sur Seine 78420 - FRANCE - - 14-48-8B (hex) Shenzhen Doov Technology Co.,Ltd - 14488B (base 16) Shenzhen Doov Technology Co.,Ltd - 11st Floor,East,2nd Phase - Innovation and Technology Square,Tianan Cyber Park - Futian District, Shenzhen Guangdong 518040 - CHINA - - 14-49-78 (hex) Digital Control Incorporated - 144978 (base 16) Digital Control Incorporated - 19625 62nd Ave S - Suite B103 - Kent WA 98032 - UNITED STATES - - 14-49-E0 (hex) Samsung Electro Mechanics co.,LTD. - 1449E0 (base 16) Samsung Electro Mechanics co.,LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - 14-4C-1A (hex) Max Communication GmbH - 144C1A (base 16) Max Communication GmbH - Siemensstrasse 47 - Rellingen 25462 - GERMANY - - 14-54-12 (hex) Entis Co., Ltd. - 145412 (base 16) Entis Co., Ltd. - 2-20-6, Hanaoka Bldg, 6F - Nihonbashi Hamacho, Chuo-ku - Tokyo 1030007 - JAPAN - - 14-56-45 (hex) Savitech Corp. - 145645 (base 16) Savitech Corp. - 3F, No.309, Guangming 1st Rd., - Zhubei Hsinchu 30259 - TAIWAN, PROVINCE OF CHINA - - 14-58-D0 (hex) Hewlett Packard - 1458D0 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 14-5A-05 (hex) Apple - 145A05 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 14-5A-83 (hex) Logi-D inc - 145A83 (base 16) Logi-D inc - 5550 Des Rossignol Blvd - Laval Quebec H7L 5W6 - CANADA - - 14-5B-D1 (hex) ARRIS Group, Inc. - 145BD1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 14-60-80 (hex) zte corporation - 146080 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 14-63-08 (hex) JABIL CIRCUIT (SHANGHAI) LTD. - 146308 (base 16) JABIL CIRCUIT (SHANGHAI) LTD. - FL5-UNIT A2 NO. 1528 GUMEI ROAD - SHANGHAI 200233 - CHINA - - 14-6A-0B (hex) Cypress Electronics Limited - 146A0B (base 16) Cypress Electronics Limited - 11/F., Block G, East Sun Industrial Centre, 16 Shing Yip Street, - Kwun Tong, Kowloon - Hong Kong nil nil - HONG KONG - - 14-6B-72 (hex) Shenzhen Fortune Ship Technology Co., Ltd. - 146B72 (base 16) Shenzhen Fortune Ship Technology Co., Ltd. - Room 701-716, 7th Floor, - Kanghesheng Building, No.1 Chuangsheng Road - Nanshan District, Shenzhen Guangdong 518000 - CHINA - - 14-6E-0A (hex) PRIVATE - 146E0A (base 16) - - 14-73-73 (hex) TUBITAK UEKAE - 147373 (base 16) TUBITAK UEKAE - ANIBAL ST. - GEBZE - KOCAELI 41470 - TURKEY - - 14-74-11 (hex) RIM - 147411 (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 14-75-90 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 147590 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park - Shennan Road, Nanshan - Shenzhen Guangdong 518057 - CHINA - - 14-7D-B3 (hex) JOA TELECOM.CO.,LTD - 147DB3 (base 16) JOA TELECOM.CO.,LTD - 1007,Sicox tower,513-14,Sangdaewon-dong,Jungwon-gu - Seongnam-si Gyeonggi-do 462-806 - KOREA, REPUBLIC OF - - 14-7D-C5 (hex) Murata Manufacturing Co., Ltd. - 147DC5 (base 16) Murata Manufacturing Co., Ltd. - 1-10-1,Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 14-82-5B (hex) Hefei Radio Communication Technology Co., Ltd - 14825B (base 16) Hefei Radio Communication Technology Co., Ltd - No.108, YinXing Road, High-tech Development Zone, Hefei, Anhui Province, China - Hefei Anhui Province 230088 - CHINA - - 14-86-92 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 148692 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd - Nanshan District, Shenzhen Guandong 518057 - CHINA - - 14-89-3E (hex) VIXTEL TECHNOLOGIES LIMTED - 14893E (base 16) VIXTEL TECHNOLOGIES LIMTED - ROOM 1409, 14/F, BLOCK B, KAILEY CENTER - 12 FUNG YIP STREET - CHAI WAN - HONG KONG - - 14-89-FD (hex) Samsung Electronics - 1489FD (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 14-8A-70 (hex) ADS GmbH - 148A70 (base 16) ADS GmbH - Im Rohnweiher 39 - Lohmar Germany D-53797 - GERMANY - - 14-8F-21 (hex) Garmin International - 148F21 (base 16) Garmin International - 1200 E. 151st St - Olathe KS 66062 - UNITED STATES - - 14-8F-C6 (hex) Apple - 148FC6 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 14-90-90 (hex) KongTop industrial(shen zhen)CO.,LTD - 149090 (base 16) KongTop industrial(shen zhen)CO.,LTD - xinwuyuan,gushu,Xixiang,Baoan, - Shenzhen Guangdong 518000 - CHINA - - 14-94-48 (hex) BLU CASTLE S.A. - 149448 (base 16) BLU CASTLE S.A. - 5 RUE BONNEVOIE - LUXEMBOURG L-1260 - UNITED STATES - - 14-99-E2 (hex) Apple, Inc - 1499E2 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 14-9A-10 (hex) Microsoft Corporation - 149A10 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 14-9F-E8 (hex) Lenovo Mobile Communication Technology Ltd. - 149FE8 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone - Xiamen Fujian 361006 - CHINA - - 14-A3-64 (hex) Samsung Electronics Co.,Ltd - 14A364 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 14-A6-2C (hex) S.M. Dezac S.A. - 14A62C (base 16) S.M. Dezac S.A. - Vial Sant jordi S/N - Pol. Ind. Can Mitjans - Viladecavalls Barcelona 08232 - SPAIN - - 14-A8-6B (hex) ShenZhen Telacom Science&Technology Co., Ltd - 14A86B (base 16) ShenZhen Telacom Science&Technology Co., Ltd - B1701/1705 Pavilion, Hua Qiang Bei RD4002, Futian District - ShenZhen GuangDong 518028 - CHINA - - 14-A9-E3 (hex) MST CORPORATION - 14A9E3 (base 16) MST CORPORATION - 4th Floor Lawford House - Albert Place - London England N3 1 RL - UNITED KINGDOM - - 14-AB-F0 (hex) ARRIS Group, Inc. - 14ABF0 (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 14-AE-DB (hex) VTech Telecommunications Ltd. - 14AEDB (base 16) VTech Telecommunications Ltd. - 23/F, Tai Ping Industrial Centre, Block 1, - 57 Ting Kok Road, Tai Po, NT - HONG KONG NA 000000 - HONG KONG - - 14-B1-26 (hex) Industrial Software Co - 14B126 (base 16) Industrial Software Co - 91, Aleksandyr Malinov blvd. - room 604 - Sofia 1715 - BULGARIA - - 14-B1-C8 (hex) InfiniWing, Inc. - 14B1C8 (base 16) InfiniWing, Inc. - 19925 Stevens Creek Blvd - Cupertino CA 95014 - UNITED STATES - - 14-B4-84 (hex) Samsung Electronics Co.,Ltd - 14B484 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 14-B7-3D (hex) ARCHEAN Technologies - 14B73D (base 16) ARCHEAN Technologies - 1899 avenue d'Italie - Zone Albasud II - MONTAUBAN 82000 - FRANCE - - 14-B9-68 (hex) Huawei Technologies Co., Ltd - 14B968 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 14-C0-89 (hex) DUNE HD LTD - 14C089 (base 16) DUNE HD LTD - 2F., No.297, Sec. 2, Tiding Blvd., - Neihu Dist., - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 14-C1-26 (hex) Nokia Corporation - 14C126 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo Varsinais-Suomi 24101 - FINLAND - - 14-C2-1D (hex) Sabtech Industries - 14C21D (base 16) Sabtech Industries - 23231 La Palma Ave - Yorba Linda Ca 92887-4788 - UNITED STATES - - 14-CC-20 (hex) TP-LINK TECHNOLOGIES CO.,LTD - 14CC20 (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24(floors 1,3,4,5)and 28(floors1-4) Central Science and Technology Park, - Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - 14-CF-8D (hex) OHSUNG ELECTRONICS CO., LTD. - 14CF8D (base 16) OHSUNG ELECTRONICS CO., LTD. - 181 - GONGDAN-DONG - GUMI KYUNGBUK 730-030 - KOREA, REPUBLIC OF - - 14-CF-92 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 14CF92 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) - Central Science and Technology Park,Shennan Rd, Nanshan District - shenzhen guangdong Province 518057 - CHINA - - 14-CF-E2 (hex) ARRIS Group, Inc. - 14CFE2 (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 14-D4-FE (hex) Pace plc - 14D4FE (base 16) Pace plc - Victoria Road - Saltaire West Yorkshire BD18 3LF, England - UNITED KINGDOM - - 14-D6-4D (hex) D-Link International - 14D64D (base 16) D-Link International - 1 INTERNATIONAL BUSINESS PARK - #03-12, THE SYNERGY - 609917 - SINGAPORE - - 14-D7-6E (hex) CONCH ELECTRONIC Co.,Ltd - 14D76E (base 16) CONCH ELECTRONIC Co.,Ltd - No.3 Keji 1st Load. - Tainan 70955 - TAIWAN, PROVINCE OF CHINA - - 14-DA-E9 (hex) ASUSTek COMPUTER INC. - 14DAE9 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 14-DB-85 (hex) S NET MEDIA - 14DB85 (base 16) S NET MEDIA - 4F, SEHYUN BLDG, 1581-7 - SEOCHO DONG, SEOCHO GU - SEOUL 137-875 - KOREA, REPUBLIC OF - - 14-DD-A9 (hex) ASUSTek COMPUTER INC. - 14DDA9 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, Taipei 112, Taiwan - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 14-E4-EC (hex) mLogic LLC - 14E4EC (base 16) mLogic LLC - 8440 Warner Drive - Suite B2 - Culver City CA 90232 - UNITED STATES - - 14-E6-E4 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 14E6E4 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, - Shenzhen, Guangdong Province, 518057 - CHINA - - 14-EB-33 (hex) BSMediasoft Co., Ltd. - 14EB33 (base 16) BSMediasoft Co., Ltd. - #603, Garden Bldg., 14-13, Yoido-Dong, Youngdeungpo-Gu - Seoul 150-871 - KOREA, REPUBLIC OF - - 14-ED-A5 (hex) Wächter GmbH Sicherheitssysteme - 14EDA5 (base 16) Wächter GmbH Sicherheitssysteme - Alte Ricklinger Str. 3 - Hannover Garbsen 30823 - GERMANY - - 14-ED-E4 (hex) Kaiam Corporation - 14EDE4 (base 16) Kaiam Corporation - 39677 Eureka Drive - Newark California 94560 - UNITED STATES - - 14-EE-9D (hex) AirNav Systems LLC - 14EE9D (base 16) AirNav Systems LLC - 4660 La Jolla Village Dr. - Suite 500 - San Diego California CA 92122 - UNITED STATES - - 14-F0-C5 (hex) Xtremio Ltd. - 14F0C5 (base 16) Xtremio Ltd. - POB 5246 - Herzelyia 46152 - ISRAEL - - 14-F2-8E (hex) ShenYang ZhongKe-Allwin Technology Co.LTD - 14F28E (base 16) ShenYang ZhongKe-Allwin Technology Co.LTD - No.6, Gaoge Road, - Hunnan New District, - ShenYang Liaoning 110179 - CHINA - - 14-F4-2A (hex) Samsung Electronics - 14F42A (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 14-F6-5A (hex) Xiaomi inc. - 14F65A (base 16) Xiaomi inc. - Office Building,The Rainbow City of China Resources, NO.68,Qinghe Middle Street,Haidian District, - Beijing 100085 - CHINA - - 14-F8-93 (hex) Wuhan FiberHome Digital Technology Co.,Ltd. - 14F893 (base 16) Wuhan FiberHome Digital Technology Co.,Ltd. - No.88 YouKeyuan Road - Hongshan District - Wuhan Hubei 430074 - CHINA - - 14-FE-AF (hex) SAGITTAR LIMITED - 14FEAF (base 16) SAGITTAR LIMITED - 2-102, BLD34, BAIWANGMOLIYUAN - XIBEIWANG, HAIDIAN - BEIJING 100094 - CHINA - - 14-FE-B5 (hex) Dell Inc - 14FEB5 (base 16) Dell Inc - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 18-00-2D (hex) Sony Mobile Communications AB - 18002D (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 18-00-DB (hex) Fitbit Inc. - 1800DB (base 16) Fitbit Inc. - 150 Spear St Ste 200 - San Francisco CA 94105 - UNITED STATES - - 18-01-E3 (hex) Elektrobit Wireless Communications Ltd - 1801E3 (base 16) Elektrobit Wireless Communications Ltd - Tutkijantie 8 - Oulu 90570 - FINLAND - - 18-03-73 (hex) Dell Inc - 180373 (base 16) Dell Inc - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 18-03-FA (hex) IBT Interfaces - 1803FA (base 16) IBT Interfaces - Im Taubhaus 19 - Roedermark Hessen 63322 - GERMANY - - 18-06-75 (hex) DILAX Intelcom GmbH - 180675 (base 16) DILAX Intelcom GmbH - Alt-Moabit 96b - Berlin 10559 - GERMANY - - 18-0B-52 (hex) Nanotron Technologies GmbH - 180B52 (base 16) Nanotron Technologies GmbH - Alt-Moabit 60 - Berlin 10555 - GERMANY - - 18-0C-14 (hex) iSonea Limited - 180C14 (base 16) iSonea Limited - 125 South Tremont Street - Oceanside CA 92054 - UNITED STATES - - 18-0C-77 (hex) Westinghouse Electric Company, LLC - 180C77 (base 16) Westinghouse Electric Company, LLC - 1000 Westinghouse Drive - Suite 152 - Cranberry Township PA 16066 - UNITED STATES - - 18-0C-AC (hex) CANON INC. - 180CAC (base 16) CANON INC. - 3-30-2 - Shimomaruko - Ohta-Ku Tokyo 146-8501 - JAPAN - - 18-10-4E (hex) CEDINT-UPM - 18104E (base 16) CEDINT-UPM - Campus de Montegancedo - 28223 Pozuelo de Alarcón - Madrid - SPAIN - - 18-14-20 (hex) TEB SAS - 181420 (base 16) TEB SAS - RD294 - Corpeau - Meursault Burgundy 21190 - FRANCE - - 18-14-56 (hex) Nokia Corporation - 181456 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - 18-16-C9 (hex) Samsung Electronics Co.,Ltd - 1816C9 (base 16) Samsung Electronics Co.,Ltd - 129, Samsung-ro, Youngtongl-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 18-17-14 (hex) DAEWOOIS - 181714 (base 16) DAEWOOIS - 7F Namkwang Centlex Bldg. 440-4 Cheongcheon2-dong - Incheon Pupyeong-gu 82 - KOREA, REPUBLIC OF - - 18-17-25 (hex) Cameo Communications, Inc. - 181725 (base 16) Cameo Communications, Inc. - No. 276, Sinhu 1st Rd., Neihu District, - Taipei City 114, Taiwan - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 18-19-3F (hex) Tamtron Oy - 18193F (base 16) Tamtron Oy - P.O.Box 15 (Vestonkatu 11) - Tampere 33561 - FINLAND - - 18-1B-EB (hex) Actiontec Electronics, Inc - 181BEB (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 95124 - UNITED STATES - - 18-1E-78 (hex) SAGEMCOM - 181E78 (base 16) SAGEMCOM - 250 route de l'Empereur - Rueil Malmaison Cedex idf 92848 - FRANCE - - 18-1E-B0 (hex) Samsung Electronics Co.,Ltd - 181EB0 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-20-12 (hex) Aztech Associates Inc. - 182012 (base 16) Aztech Associates Inc. - 805 Bayridge Dr. - Kingston Ontario K7P1T5 - CANADA - - 18-20-32 (hex) Apple - 182032 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-20-A6 (hex) Sage Co., Ltd. - 1820A6 (base 16) Sage Co., Ltd. - 2-24 Sumiyoshicho, Naka-ku - KY Bldg. - Yokohama-shi Kanagawa 231-0013 - JAPAN - - 18-22-7E (hex) Samsung Electronics Co.,Ltd - 18227E (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-26-66 (hex) Samsung Electronics Co.,Ltd - 182666 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-28-61 (hex) AirTies Wireless Networks - 182861 (base 16) AirTies Wireless Networks - Gulbahar Mah. Avni Dilligil Sokak No 5 - Celik Is Merkezi , Mecidiyekoy - Sisli/ ISTANBUL 34394 - TURKEY - - 18-2A-7B (hex) Nintendo Co., Ltd. - 182A7B (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 18-2B-05 (hex) 8D Technologies - 182B05 (base 16) 8D Technologies - 416, de Maisonneuve West - Suite 406 - Montreal, Quebec H3A 1L2 - CANADA - - 18-2C-91 (hex) Concept Development, Inc. - 182C91 (base 16) Concept Development, Inc. - 1881 Langley Avenue - Irvine CA 92614-5623 - UNITED STATES - - 18-30-09 (hex) Woojin Industrial Systems Co., Ltd. - 183009 (base 16) Woojin Industrial Systems Co., Ltd. - 95, Sari-ro, Sari-myeon - Goesan-gun Chungcheongbuk-do 367-822 - KOREA, REPUBLIC OF - - 18-32-A2 (hex) LAON TECHNOLOGY CO., LTD. - 1832A2 (base 16) LAON TECHNOLOGY CO., LTD. - #1212 HO, BIZ CENTER, SKn TECHNOPARK - SANGDAEWON-DONG , JUNGWON-GU - SEONGNAM KYOUNGGI DO 462-721 - KOREA, REPUBLIC OF - - 18-33-9D (hex) CISCO SYSTEMS, INC. - 18339D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 18-34-51 (hex) Apple - 183451 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-36-FC (hex) Elecsys International Corporation - 1836FC (base 16) Elecsys International Corporation - 846 N Mart-Way Court - Olathe KS 66061 - UNITED STATES - - 18-38-25 (hex) Wuhan Lingjiu High-tech Co.,Ltd. - 183825 (base 16) Wuhan Lingjiu High-tech Co.,Ltd. - No.718 - Luyu Road - Wuhan Hubei 430074 - CHINA - - 18-38-64 (hex) CAP-TECH INTERNATIONAL CO., LTD. - 183864 (base 16) CAP-TECH INTERNATIONAL CO., LTD. - Rm. 6, 4F., No.120, Qiaohe Rd., Zhonghe Dist - New Taipei City Taiwan 235 - TAIWAN, PROVINCE OF CHINA - - 18-39-19 (hex) Unicoi Systems - 183919 (base 16) Unicoi Systems - 410 Peachtree Pkwy - Bldg 400, Ste 4226 - Cumming GA 30041 - UNITED STATES - - 18-3A-2D (hex) Samsung Electronics Co.,Ltd - 183A2D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-3B-D2 (hex) BYD Precision Manufacture Company Ltd. - 183BD2 (base 16) BYD Precision Manufacture Company Ltd. - No3000 LongDong Avenue, Pudong District - Shanghai 201203 - CHINA - - 18-3D-A2 (hex) Intel Corporate - 183DA2 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 18-3F-47 (hex) Samsung Electronics Co.,Ltd - 183F47 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-42-1D (hex) PRIVATE - 18421D (base 16) - - 18-42-2F (hex) Alcatel Lucent - 18422F (base 16) Alcatel Lucent - Via Trento, 30 - Vimercate MB 20059 - ITALY - - 18-44-62 (hex) Riava Networks, Inc. - 184462 (base 16) Riava Networks, Inc. - Kato Bldg. 1F, 6-12-4 Soto-Kanda - Chiyoda-ku Tokyo 1010021 - JAPAN - - 18-44-E6 (hex) zte corporation - 1844E6 (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - 18-46-17 (hex) Samsung Electronics - 184617 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-48-D8 (hex) Fastback Networks - 1848D8 (base 16) Fastback Networks - 2480 N 1st Street - Suite 250 - San Jose California 95131 - UNITED STATES - - 18-4A-6F (hex) Alcatel-Lucent Shanghai Bell Co., Ltd - 184A6F (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd - No. 389, Ningqiao Road - Pudong Jinqiao - Shanghai 201206 - CHINA - - 18-4E-94 (hex) MESSOA TECHNOLOGIES INC. - 184E94 (base 16) MESSOA TECHNOLOGIES INC. - 13611 12th St., Unit B - Chino CA 91710 - UNITED STATES - - 18-4F-32 (hex) Hon Hai Precision Ind. Co.,Ltd. - 184F32 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District,Chongqing,China - Chongqing Chongqing 401332 - CHINA - - 18-52-53 (hex) Pixord Corporation - 185253 (base 16) Pixord Corporation - 6F, No 12, Innovation 1st Road - Hsinchu Science Park - Hsinchu 30076 - TAIWAN, PROVINCE OF CHINA - - 18-53-E0 (hex) Hanyang Digitech Co.Ltd - 1853E0 (base 16) Hanyang Digitech Co.Ltd - 103, BANWOL-DONG, HWASEONG-SI, KYUNGGI-DO, KOREA - HWASEONG KYUNGGI 445-330 - KOREA, REPUBLIC OF - - 18-55-0F (hex) Cisco SPVTG - 18550F (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 18-59-33 (hex) Cisco SPVTG - 185933 (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville GA 30044 - UNITED STATES - - 18-59-36 (hex) XIAOMI INC - 185936 (base 16) XIAOMI INC - The Rainbow city of China Resource,NO.68,Qinghe Middle street,Haidian District,Beijing,Chian. - Beijing Beijing 100085 - CHINA - - 18-5A-E8 (hex) Zenotech.Co.,Ltd - 185AE8 (base 16) Zenotech.Co.,Ltd - E-503, BundangTechno Park, Yatap-dong - Bundang-Gu - Seongnam 463-760 - KOREA, REPUBLIC OF - - 18-5D-9A (hex) BobjGear LLC - 185D9A (base 16) BobjGear LLC - 4327 S Highway 27 # 504 - Clermont Florida 34711 - UNITED STATES - - 18-62-2C (hex) SAGEMCOM SAS - 18622C (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON 92848 - FRANCE - - 18-64-72 (hex) Aruba Networks - 186472 (base 16) Aruba Networks - 1344 Orleans Avenue - Sunnyvale California 94089 - UNITED STATES - - 18-65-71 (hex) Top Victory Electronics (Taiwan) Co., Ltd. - 186571 (base 16) Top Victory Electronics (Taiwan) Co., Ltd. - 14F,No.166,Jian 1st Rd - Zhonghe Dist. - New Taipei City Taiwan 23511 - TAIWAN, PROVINCE OF CHINA - - 18-66-E3 (hex) Veros Systems, Inc. - 1866E3 (base 16) Veros Systems, Inc. - PO Box 10534 - College Station Texas 77842 - UNITED STATES - - 18-67-3F (hex) Hanover Displays Limited - 18673F (base 16) Hanover Displays Limited - Unit 24 - Cliffe Industrial Estate - Lewes East Sussex BN8 6JL - UNITED KINGDOM - - 18-67-51 (hex) KOMEG Industrielle Messtechnik GmbH - 186751 (base 16) KOMEG Industrielle Messtechnik GmbH - Zum Wasserwerk 3 - Völklingen 66333 - GERMANY - - 18-67-B0 (hex) Samsung Electronics Co.,LTD - 1867B0 (base 16) Samsung Electronics Co.,LTD - 129, Samsung-ro, Yeongtong-gu - Suwon Gyeonggi-Do 443-742 - KOREA, REPUBLIC OF - - 18-68-82 (hex) Beward R&D Co., Ltd. - 186882 (base 16) Beward R&D Co., Ltd. - Molokova street 16, apt.355 - Krasnoyarsk Krasnoyarsk region 660118 - RUSSIAN FEDERATION - - 18-6D-99 (hex) Adanis Inc. - 186D99 (base 16) Adanis Inc. - #2015-2016 Geumkang Penterium - IT Tower B Tower 282 - Hakuro, Dongan-Gu, Anyang-Si Kyunggi-Do 431-060 - KOREA, REPUBLIC OF - - 18-71-17 (hex) eta plus electronic gmbh - 187117 (base 16) eta plus electronic gmbh - Lauterstr. 29 - Nuertingen BW 72622 - GERMANY - - 18-79-A2 (hex) GMJ ELECTRIC LIMITED - 1879A2 (base 16) GMJ ELECTRIC LIMITED - RM 1405, 14/F, C C WU BUILDING - 302-308 HENNESSY ROAD, WAN CHAI - 999077 - HONG KONG - - 18-7A-93 (hex) AMICCOM Electronics Corporation - 187A93 (base 16) AMICCOM Electronics Corporation - Room A3, 1F., No.1, Lixing 1st Rd - Science-Based Industrial Park - Hsinchu 30078 - TAIWAN, PROVINCE OF CHINA - - 18-7C-81 (hex) Valeo Vision Systems - 187C81 (base 16) Valeo Vision Systems - Dunmore Road - Tuam - County Galway - IRELAND - - 18-7E-D5 (hex) shenzhen kaism technology Co. Ltd - 187ED5 (base 16) shenzhen kaism technology Co. Ltd - 37# chuanglong west road pinghu - shenzhen 518111 - CHINA - - 18-80-CE (hex) Barberry Solutions Ltd - 1880CE (base 16) Barberry Solutions Ltd - 2/13 Naviti Place - Browns Bay - Auckland 0630 - NEW ZEALAND - - 18-80-F5 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd - 1880F5 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd - No. 389, Ningqiao Road, Pudong Jinqiao, - Shanghai 201206 - CHINA - - 18-82-19 (hex) Alibaba Cloud Computing Ltd. - 188219 (base 16) Alibaba Cloud Computing Ltd. - Yuhang District of Hangzhou Wenyi Road, Building 1, No. 969 Xixi Park, Zhejiang Province - Hangzhou Zhejiang 310000 - CHINA - - 18-83-31 (hex) Samsung Electronics Co.,Ltd - 188331 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-83-BF (hex) Arcadyan Technology Corporation - 1883BF (base 16) Arcadyan Technology Corporation - 4F, No. 9, Park Avenue II , - Science based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 18-84-10 (hex) CoreTrust Inc. - 188410 (base 16) CoreTrust Inc. - 14F Saman Bldg. 945 Daechi-dong - Gangnam-gu - Seoul Republic of Korea 135-280 - KOREA, REPUBLIC OF - - 18-86-3A (hex) DIGITAL ART SYSTEM - 18863A (base 16) DIGITAL ART SYSTEM - 838 rue de l'Aiguelongue - Montpellier Etat 34090 - FRANCE - - 18-86-AC (hex) Nokia Danmark A/S - 1886AC (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 18-87-96 (hex) HTC Corporation - 188796 (base 16) HTC Corporation - No. 23, Xinghua Rd., - Taoyuan City 330 - TAIWAN, PROVINCE OF CHINA - - 18-88-57 (hex) Beijing Jinhong Xi-Dian Information Technology Corp. - 188857 (base 16) Beijing Jinhong Xi-Dian Information Technology Corp. - 4th -5th Floor, 1# Building NO.1 Zhonghe Road - Fengtai District - Beijing 100070 - CHINA - - 18-89-DF (hex) CerebrEX Inc. - 1889DF (base 16) CerebrEX Inc. - Central Shin-Osaka Building 10F - 4-5-36, Miyahara, Yodogawa-ku - Osaka 532-0003 - JAPAN - - 18-8E-D5 (hex) TP Vision Belgium N.V. - innovation site Brugge - 188ED5 (base 16) TP Vision Belgium N.V. - innovation site Brugge - Pathoekeweg 11 - Bruges West Flanders 8000 - BELGIUM - - 18-8E-F9 (hex) G2C Co. Ltd. - 188EF9 (base 16) G2C Co. Ltd. - 1004,1591-9, K-Center Kwanyang Dong - Dongan Gu, - Anyang Si Kyeonggido 431-815 - KOREA, REPUBLIC OF - - 18-92-2C (hex) Virtual Instruments - 18922C (base 16) Virtual Instruments - 100 Enterprise Way - Suite C-3 - Scotts Valley CA 95066 - UNITED STATES - - 18-97-FF (hex) TechFaith Wireless Technology Limited - 1897FF (base 16) TechFaith Wireless Technology Limited - Building C, Jia No.5, Rongchang East Street, BDA District, - Beijing 100176 - CHINA - - 18-9A-67 (hex) CSE-Servelec Limited - 189A67 (base 16) CSE-Servelec Limited - Rotherside Road - Sheffield S21 4HL - UNITED KINGDOM - - 18-9C-5D (hex) Cisco - 189C5D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 18-9E-FC (hex) Apple - 189EFC (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-A3-E8 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 18A3E8 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 18-A9-05 (hex) Hewlett-Packard Company - 18A905 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 18-A9-58 (hex) PROVISION THAI CO., LTD. - 18A958 (base 16) PROVISION THAI CO., LTD. - 155/7-10 Rachadapisek Rd., - Bukkalo - Thonburi Bangkok 10600 - THAILAND - - 18-A9-9B (hex) Dell Inc - 18A99B (base 16) Dell Inc - one dell way - Round rock Texas 78682 - UNITED STATES - - 18-AA-45 (hex) Fon Technology - 18AA45 (base 16) Fon Technology - C/Quintanavides, 15 Edificio 2 Planta 1 - 28050 Madrid - SPAIN - - 18-AB-F5 (hex) Ultra Electronics - Electrics - 18ABF5 (base 16) Ultra Electronics - Electrics - Kingsditch Lane - Cheltenham Gloucestershire GL51 9PG - UNITED KINGDOM - - 18-AD-4D (hex) Polostar Technology Corporation - 18AD4D (base 16) Polostar Technology Corporation - 2F, No.351, Yangguang St. - Taipei 11491 - TAIWAN, PROVINCE OF CHINA - - 18-AE-BB (hex) Siemens Convergence Creators GmbH&Co.KG - 18AEBB (base 16) Siemens Convergence Creators GmbH&Co.KG - Communications, Media and Technology - Harburger Schlossstrasse 18 - Hamburg D-21079 - GERMANY - - 18-AF-61 (hex) Apple, Inc - 18AF61 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-AF-8F (hex) Apple - 18AF8F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-AF-9F (hex) DIGITRONIC Automationsanlagen GmbH - 18AF9F (base 16) DIGITRONIC Automationsanlagen GmbH - Auf der Langwies 1 - Wallbach Hessen 65510 - GERMANY - - 18-B1-69 (hex) Sonicwall - 18B169 (base 16) Sonicwall - 2001 Logic Drive - San Jose CA 95124-3452 - UNITED STATES - - 18-B2-09 (hex) Torrey Pines Logic, Inc - 18B209 (base 16) Torrey Pines Logic, Inc - 12651 High Bluff Drive, #100 - San Diego CA 92130 - UNITED STATES - - 18-B3-BA (hex) Netlogic AB - 18B3BA (base 16) Netlogic AB - Datavägen 14A - ASKIM Västra Götaland 43632 - SWEDEN - - 18-B4-30 (hex) Nest Labs Inc. - 18B430 (base 16) Nest Labs Inc. - 235 Alma - Palo Alto CA 94301 - UNITED STATES - - 18-B5-91 (hex) I-Storm - 18B591 (base 16) I-Storm - Hogye-dong, Dongan-gu - #301, Daerim Pleza, 1027-20,21 - Anyang-si Gyeonggi-do 431-080 - KOREA, REPUBLIC OF - - 18-B7-9E (hex) Invoxia - 18B79E (base 16) Invoxia - 87 rue du Gouverneur Général Eboué - Issy-Les-Moulineaux 92130 - FRANCE - - 18-BD-AD (hex) L-TECH CORPORATION - 18BDAD (base 16) L-TECH CORPORATION - 201, Moonbon-dong - Ilsandong-gu Gyeonggi-do 410-560 - KOREA, REPUBLIC OF - - 18-C0-86 (hex) Broadcom Corporation - 18C086 (base 16) Broadcom Corporation - 5300 California Avenue - Irvine CA 92617 - UNITED STATES - - 18-C4-51 (hex) Tucson Embedded Systems - 18C451 (base 16) Tucson Embedded Systems - 5620 North Kolb Road - Suite 160 - Tucson AZ 85750 - UNITED STATES - - 18-C5-8A (hex) HUAWEI TECHNOLOGIES CO.,LTD - 18C58A (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 18-C8-E7 (hex) Shenzhen Hualistone Technology Co.,Ltd - 18C8E7 (base 16) Shenzhen Hualistone Technology Co.,Ltd - 1708RM,Huafeng HQ Economic Building, - Xixiang Street, Baoan District - Shenzhen Guangdong 518102 - CHINA - - 18-CC-23 (hex) Philio Technology Corporation - 18CC23 (base 16) Philio Technology Corporation - 8F., No.653-2, Zhongzheng Rd - Xinzhuang Dist. - New Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 18-CF-5E (hex) Liteon Technology Corporation - 18CF5E (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo, Taipei Hsien - TaiPei TaiWan 23585 - TAIWAN, PROVINCE OF CHINA - - 18-D0-71 (hex) DASAN CO., LTD. - 18D071 (base 16) DASAN CO., LTD. - DASAN Tower 7F, 49 Daewangpangyo-ro644beon-gil - Bundang-gu - Seongnam-si Gyeonggi-do 463-760 - KOREA, REPUBLIC OF - - 18-D5-B6 (hex) SMG Holdings LLC - 18D5B6 (base 16) SMG Holdings LLC - 205 N Michigan Ave - Suite 4230 - Chicago IL 60601 - UNITED STATES - - 18-D6-6A (hex) Inmarsat - 18D66A (base 16) Inmarsat - 99 City Road - London EC1Y 1AX - UNITED KINGDOM - - 18-D6-CF (hex) Kurth Electronic GmbH - 18D6CF (base 16) Kurth Electronic GmbH - Im Scherbental 5 - Eningen BW 72800 - GERMANY - - 18-D9-49 (hex) Qvis Labs, LLC - 18D949 (base 16) Qvis Labs, LLC - 3204 Rustic River Cove - Austin TX 78746-2001 - UNITED STATES - - 18-DC-56 (hex) Yulong Computer Telecommunication Scientific(shenzhen)Co.,Lt - 18DC56 (base 16) Yulong Computer Telecommunication Scientific(shenzhen)Co.,Lt - Coolpad Information Harbor, 2nd Mengxi road, Hi-Tech Industrial Park(North), Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 18-E2-88 (hex) STT Condigi - 18E288 (base 16) STT Condigi - Agnesfridsvagen 113 A - Malmö SkÃ¥ne 21237 - SWEDEN - - 18-E2-C2 (hex) Samsung Electronics - 18E2C2 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 18-E7-28 (hex) Cisco - 18E728 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 18-E7-F4 (hex) Apple - 18E7F4 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-E8-0F (hex) Viking Electronics Inc. - 18E80F (base 16) Viking Electronics Inc. - 1531 Industrial St - Hudson WI 54016 - UNITED STATES - - 18-E8-DD (hex) MODULETEK - 18E8DD (base 16) MODULETEK - Unit 4A.4F.B Building. Shenfubao Science and Technology Industrial Park - No.3 Huang Huai Road, Futian Free Trade Zone - Shenzhen Guangdong 518038 - CHINA - - 18-EE-69 (hex) Apple - 18EE69 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-EF-63 (hex) CISCO SYSTEMS, INC. - 18EF63 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 18-F1-45 (hex) NetComm Wireless Limited - 18F145 (base 16) NetComm Wireless Limited - Level 2, 18-20 Orion Road - Lane Cove Sydney 2066 - AUSTRALIA - - 18-F4-6A (hex) Hon Hai Precision Ind. Co.,Ltd. - 18F46A (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 18-F6-43 (hex) Apple - 18F643 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 18-F6-50 (hex) Multimedia Pacific Limited - 18F650 (base 16) Multimedia Pacific Limited - 1 Matheson Street, Shell Tower 29F/12 - Time Square, Causeway Bay - 000000 - HONG KONG - - 18-F8-7A (hex) i3 International Inc. - 18F87A (base 16) i3 International Inc. - 780 Birchmount Road - Unit 16 - Scarborough Ontario M1K5H4 - CANADA - - 18-FA-6F (hex) ISC applied systems corp - 18FA6F (base 16) ISC applied systems corp - 295 Labrosse - Pointe-claire QC H9R-1A3 - CANADA - - 18-FB-7B (hex) Dell Inc - 18FB7B (base 16) Dell Inc - one dell way - MS:RR5-45 - Round rock Texas 78682 - UNITED STATES - - 18-FC-9F (hex) Changhe Electronics Co., Ltd. - 18FC9F (base 16) Changhe Electronics Co., Ltd. - 6th Floor, Building B, Dajiahao Square, Yu¡¯an 1st Road, Bao¡¯an, - Shenzhen Guangdong 518101 - CHINA - - 18-FE-34 (hex) Espressif Inc. - 18FE34 (base 16) Espressif Inc. - 2966 Jin Ke Road - North Tower Unit 204 - Shanghai 201203 - CHINA - - 18-FF-0F (hex) Intel Corporate - 18FF0F (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 18-FF-2E (hex) Shenzhen Rui Ying Da Technology Co., Ltd - 18FF2E (base 16) Shenzhen Rui Ying Da Technology Co., Ltd - KaiXinda Electronic Science and Technology Park, Zhoushi Road 49,Shiyan Street,Baoan District,ShenZhen,China - shenzhen guangdong 518108 - CHINA - - 1C-06-56 (hex) IDY Corporation - 1C0656 (base 16) IDY Corporation - IDEMITSU Korakuen Bld 9F - 1-2-1 Koishikawa - Bunkyo-ku Tokyo 112-0002 - JAPAN - - 1C-08-C1 (hex) Lg Innotek - 1C08C1 (base 16) Lg Innotek - 978-1 Jangduk dong, Gwangsangu - Gwangju Gwangju 506-731 - KOREA, REPUBLIC OF - - 1C-0B-52 (hex) EPICOM S.A - 1C0B52 (base 16) EPICOM S.A - Autovia Andalucia Km 12.700 - P.I Los Angeles - Getafe Madrid 28905 - SPAIN - - 1C-0F-CF (hex) Sypro Optics GmbH - 1C0FCF (base 16) Sypro Optics GmbH - Carl-Zeiss-Promenade 10 - Jena Thuringia 07745 - GERMANY - - 1C-11-E1 (hex) Wartsila Finland Oy - 1C11E1 (base 16) Wartsila Finland Oy - Jarvikatu 2-4 - Vaasa Western Finland 65101 - FINLAND - - 1C-12-9D (hex) IEEE PES PSRC/SUB - 1C129D (base 16) IEEE PES PSRC/SUB - Working Group H7/Sub C7 (IEEE PC37.238) - 445 Hoes Lane - Piscataway NJ 08854 - UNITED STATES - - 1C-14-48 (hex) ARRIS Group, Inc. - 1C1448 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 1C-14-B3 (hex) Pinyon Technologies - 1C14B3 (base 16) Pinyon Technologies - 529 M Street - Sparks NV 89431 - UNITED STATES - - 1C-17-D3 (hex) CISCO SYSTEMS, INC. - 1C17D3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 1C-18-4A (hex) ShenZhen RicherLink Technologies Co.,LTD - 1C184A (base 16) ShenZhen RicherLink Technologies Co.,LTD - 703,Building W1-A,High-Tech Industrial Park,KeJiNan 1st Road,NanShan, - ShenZhen GuangDong 518057 - CHINA - - 1C-19-DE (hex) eyevis GmbH - 1C19DE (base 16) eyevis GmbH - Hundsschleestrasse 23 - Reutlingen BW 72766 - GERMANY - - 1C-1A-C0 (hex) Apple - 1C1AC0 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 1C-1B-68 (hex) ARRIS Group, Inc. - 1C1B68 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 1C-1C-FD (hex) Dalian Hi-Think Computer Technology, Corp - 1C1CFD (base 16) Dalian Hi-Think Computer Technology, Corp - Hi-Think Software Building,No.6 Hi-Tech Street, Qixianling Industrial Base, Hi-Tech Zone, Dalian, China - Dalian LiaoNing 116023 - CHINA - - 1C-1D-67 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 1C1D67 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 1C-1D-86 (hex) Cisco - 1C1D86 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 1C-33-4D (hex) ITS Telecom - 1C334D (base 16) ITS Telecom - 29 Hametzuda st. - Azur Israel 580001 - ISRAEL - - 1C-34-77 (hex) Innovation Wireless - 1C3477 (base 16) Innovation Wireless - 11869 Teale Street - Culver City CA 90230 - UNITED STATES - - 1C-35-F1 (hex) NEW Lift Neue Elektronische Wege Steuerungsbau GmbH - 1C35F1 (base 16) NEW Lift Neue Elektronische Wege Steuerungsbau GmbH - Lochhamer Schlag 8 - Graefelfing Bavaria 82166 - GERMANY - - 1C-37-BF (hex) Cloudium Systems Ltd. - 1C37BF (base 16) Cloudium Systems Ltd. - Hartnett Centre - Moylish Park - Limerick 00 - IRELAND - - 1C-39-47 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - 1C3947 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN SUZHOU 215300 - CHINA - - 1C-3A-4F (hex) AccuSpec Electronics, LLC - 1C3A4F (base 16) AccuSpec Electronics, LLC - 8140 Hawthorne Drive - Erie Pennsylvania 16509 - UNITED STATES - - 1C-3D-E7 (hex) Sigma Koki Co.,Ltd. - 1C3DE7 (base 16) Sigma Koki Co.,Ltd. - 1-19-9 Midori - Sumida-ku Tokyo 130-0021 - JAPAN - - 1C-3E-84 (hex) Hon Hai Precision Ind. Co.,Ltd. - 1C3E84 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 1C-41-58 (hex) Gemalto M2M GmbH - 1C4158 (base 16) Gemalto M2M GmbH - St.-Martin-Strasse 60 - Munich Bavaria 81541 - GERMANY - - 1C-43-EC (hex) JAPAN CIRCUIT CO.,LTD - 1C43EC (base 16) JAPAN CIRCUIT CO.,LTD - NKF-Kawasaki-Building 7F - 1-2 Higashidacho,Kawasaki-ku - Kawasaki Kanagawa 2100005 - JAPAN - - 1C-45-93 (hex) Texas Instruments - 1C4593 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 1C-48-40 (hex) IMS Messsysteme GmbH - 1C4840 (base 16) IMS Messsysteme GmbH - Dieselstr. 55 - Heiligenhaus NRW D-42579 - GERMANY - - 1C-48-F9 (hex) GN Netcom A/S - 1C48F9 (base 16) GN Netcom A/S - Lautrupbjerg 7 - P.O. Box 99 - Ballerup DK-2750 - DENMARK - - 1C-4A-F7 (hex) AMON INC - 1C4AF7 (base 16) AMON INC - HANJUN BLDG 4/F, SHINGILDONG 110-4 - YEONGDEUNGPOGU - SEOUL 150839 - KOREA, REPUBLIC OF - - 1C-4B-B9 (hex) SMG ENTERPRISE, LLC - 1C4BB9 (base 16) SMG ENTERPRISE, LLC - 865 LOVE ST - ELK GROVE VILLAGE IL 60007 - UNITED STATES - - 1C-4B-D6 (hex) AzureWave - 1C4BD6 (base 16) AzureWave - 8F., No. 94, Baoshong Rd. - Xindian City, Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 1C-51-B5 (hex) Techaya LTD - 1C51B5 (base 16) Techaya LTD - P.O.B 1500 - Pardes Hanna 3700 - ISRAEL - - 1C-52-16 (hex) DONGGUAN HELE ELECTRONICS CO., LTD - 1C5216 (base 16) DONGGUAN HELE ELECTRONICS CO., LTD - Lijiangwei Group, - Xiaohe Village, Daojiao Town, - Dongguan City Guangdong 86 - CHINA - - 1C-52-D6 (hex) FLAT DISPLAY TECHNOLOGY CORPORATION - 1C52D6 (base 16) FLAT DISPLAY TECHNOLOGY CORPORATION - No.85, Sec. 1, Fuxing Rd., South Dist - Taichung 402 - TAIWAN, PROVINCE OF CHINA - - 1C-5A-3E (hex) Samsung Eletronics Co., Ltd (Visual Display Divison) - 1C5A3E (base 16) Samsung Eletronics Co., Ltd (Visual Display Divison) - 416, Maetan 3dong, Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 1C-5A-6B (hex) Philips Electronics Nederland BV - 1C5A6B (base 16) Philips Electronics Nederland BV - PO BOX 80045 - Eindhoven 5600 JZ - NETHERLANDS - - 1C-5C-55 (hex) PRIMA Cinema, Inc - 1C5C55 (base 16) PRIMA Cinema, Inc - 1903 Wright Place, Suite 320 - Carlsbad CA 92008 - UNITED STATES - - 1C-5C-60 (hex) Shenzhen Belzon Technology Co.,LTD. - 1C5C60 (base 16) Shenzhen Belzon Technology Co.,LTD. - 5F Block 1,Zhongxin Building,Chuangye Rd - Shenzhen Guangdong 518054 - CHINA - - 1C-5F-FF (hex) Beijing Ereneben Information Technology Co.,Ltd Shenzhen Branch - 1C5FFF (base 16) Beijing Ereneben Information Technology Co.,Ltd Shenzhen Branch - Room 14A, Building A, Honglong Central Plaza, No.3001,Heping Road, Luohu District, Shenzhen City - Shenzhen Guangdong 518001 - CHINA - - 1C-62-B8 (hex) Samsung Electronics Co.,Ltd - 1C62B8 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 1C-63-B7 (hex) OpenProducts 237 AB - 1C63B7 (base 16) OpenProducts 237 AB - Barsebaecksvaegen 27 - Loddekopinge 24630 - SWEDEN - - 1C-65-9D (hex) Liteon Technology Corporation - 1C659D (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo,Taipei Hsien, - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 1C-66-6D (hex) Hon Hai Precision Ind.Co.Ltd - 1C666D (base 16) Hon Hai Precision Ind.Co.Ltd - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 1C-66-AA (hex) Samsung Electronics - 1C66AA (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 1C-69-A5 (hex) Research In Motion - 1C69A5 (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 1C-6A-7A (hex) Cisco - 1C6A7A (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 1C-6B-CA (hex) Mitsunami Co., Ltd. - 1C6BCA (base 16) Mitsunami Co., Ltd. - 2-30-11, Nishi-gotanda, Shinagawa-ku - Tokyo 141-0031 - JAPAN - - 1C-6F-65 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 1C6F65 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - Pin-Jen City, - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 1C-75-08 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - 1C7508 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN SUZHOU 215300 - CHINA - - 1C-76-CA (hex) Terasic Technologies Inc. - 1C76CA (base 16) Terasic Technologies Inc. - 9F., No.176, Sec.2, Gongdao 5th Rd - East District - Hsinchu City 30070 - TAIWAN, PROVINCE OF CHINA - - 1C-78-39 (hex) Shenzhen Tencent Computer System Co., Ltd. - 1C7839 (base 16) Shenzhen Tencent Computer System Co., Ltd. - 36/F, Tencent Building, Kejizhongyi Avenue, Hi-Tech Park - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 1C-7B-21 (hex) Sony Mobile Communications AB - 1C7B21 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 1C-7C-11 (hex) EID - 1C7C11 (base 16) EID - Rua Quinta dos Medronheiros - Charneca da Caparica 2820-486 - PORTUGAL - - 1C-7C-45 (hex) Vitek Industrial Video Products, Inc. - 1C7C45 (base 16) Vitek Industrial Video Products, Inc. - 28492 Constellation Rd - Valencia CA 91355 - UNITED STATES - - 1C-7C-C7 (hex) Coriant GmbH - 1C7CC7 (base 16) Coriant GmbH - St.-Martin-Str. 76 - Munich Germany 81541 - GERMANY - - 1C-7D-22 (hex) Fuji Xerox Co., Ltd. - 1C7D22 (base 16) Fuji Xerox Co., Ltd. - 6-1 Minatomirai, Nishi-ku - Yokohama Kanagawa 220-8668 - JAPAN - - 1C-7E-51 (hex) 3bumen.com - 1C7E51 (base 16) 3bumen.com - 11/F FRONT BLK HANG LOK BLDG - 130 WING LOK ST SHEUNG WAN - HONG KONG KONG KONG N/A - HONG KONG - - 1C-7E-E5 (hex) D-Link International - 1C7EE5 (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy - 609917 - SINGAPORE - - 1C-83-41 (hex) Hefei Bitland Information Technology Co.Ltd - 1C8341 (base 16) Hefei Bitland Information Technology Co.Ltd - C1# Building, Bitland Industrial Park, No#4088, Jinxiu RD,Economic Development Zone, Hefei, Anhui, China - Hefei Anhui 230061 - CHINA - - 1C-83-B0 (hex) Linked IP GmbH - 1C83B0 (base 16) Linked IP GmbH - Kirchenstrasse 9 - Anif / Niederalm SBG 5081 - AUSTRIA - - 1C-84-64 (hex) FORMOSA WIRELESS COMMUNICATION CORP. - 1C8464 (base 16) FORMOSA WIRELESS COMMUNICATION CORP. - 11F., No.3-2, Yuanqu St., Nangang Dist., - Taipei City 115 - TAIWAN, PROVINCE OF CHINA - - 1C-86-AD (hex) MCT CO., LTD. - 1C86AD (base 16) MCT CO., LTD. - C-815/816, Garden5 Works, 52 Chungmin-ro - Songpa-gu Seoul 138-961 - KOREA, REPUBLIC OF - - 1C-8E-5C (hex) Huawei Technologies Co., Ltd - 1C8E5C (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 1C-8E-8E (hex) DB Communication & Systems Co., ltd. - 1C8E8E (base 16) DB Communication & Systems Co., ltd. - 3-3 Yeongdeok-dong, Giheung-gu - Yongin-si Gyeonggi-do 449-908 - KOREA, REPUBLIC OF - - 1C-8F-8A (hex) Phase Motion Control SpA - 1C8F8A (base 16) Phase Motion Control SpA - via Adamoli, 461 - Genova IT16141 - ITALY - - 1C-91-79 (hex) Integrated System Technologies Ltd - 1C9179 (base 16) Integrated System Technologies Ltd - Suite 5 Birch House - Birch Lane - Aldridge West Midlands WS9 0NF - UNITED KINGDOM - - 1C-94-92 (hex) RUAG Schweiz AG - 1C9492 (base 16) RUAG Schweiz AG - RUAG Defence - Stauffacherstrasse 65 - Bern 22 BE 3000 - SWITZERLAND - - 1C-95-5D (hex) I-LAX ELECTRONICS INC. - 1C955D (base 16) I-LAX ELECTRONICS INC. - 2283 ARGENTIA RD.- UNIT # 10 - MISSISSAUGA ON. L5N 5Z2 - CANADA - - 1C-95-9F (hex) Veethree Electronics And Marine LLC - 1C959F (base 16) Veethree Electronics And Marine LLC - 2050 47th Terrace East - Bradenton Florida 34203 - UNITED STATES - - 1C-96-5A (hex) Weifang goertek Electronics CO.,LTD - 1C965A (base 16) Weifang goertek Electronics CO.,LTD - Gaoxin 2 Road,Free Trade Zone - Wei Fang Shan Dong 261205 - CHINA - - 1C-97-3D (hex) PRICOM Design - 1C973D (base 16) PRICOM Design - 2755 Slocum Rd - Peyton CO 80831 - UNITED STATES - - 1C-99-4C (hex) Murata Manufactuaring Co.,Ltd. - 1C994C (base 16) Murata Manufactuaring Co.,Ltd. - 1-10-1 Higashikotari  - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 1C-9C-26 (hex) Zoovel Technologies - 1C9C26 (base 16) Zoovel Technologies - Paseo de la Castellana 259C - Torre de Cristal. Planta 18 - Madrid 28046 - SPAIN - - 1C-9E-CB (hex) Beijing Nari Smartchip Microelectronics Company Limited - 1C9ECB (base 16) Beijing Nari Smartchip Microelectronics Company Limited - Northern Territory Xixiaokou Rd,Haidian district,Beijing 100192,China - beijing beijing 100192 - CHINA - - 1C-A2-B1 (hex) ruwido austria gmbh - 1CA2B1 (base 16) ruwido austria gmbh - Koestendorferstrasse 8 - Neumarkt a.W. Salzburg 5202 - AUSTRIA - - 1C-A5-32 (hex) Shenzhen Gongjin Electronics Co.,Ltd - 1CA532 (base 16) Shenzhen Gongjin Electronics Co.,Ltd - 1#SongGang RD, Bao'an Dist - Shenzhen Guangdong 518105 - CHINA - - 1C-A7-70 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LT - 1CA770 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LT - Unit A 13-16/F,Skyworth Bldg., Gaoxin Ave.1.S.,Nanshan District - ShenZhen GuangDong 518057 - CHINA - - 1C-AA-07 (hex) CISCO SYSTEMS, INC. - 1CAA07 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 1C-AB-01 (hex) Innovolt - 1CAB01 (base 16) Innovolt - 14 Piedmont Center - 3535 Piedmont Rd Suite 1205 - Atlanta GA 30305 - UNITED STATES - - 1C-AB-A7 (hex) Apple - 1CABA7 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 1C-AD-D1 (hex) Bosung Electronics Co., Ltd. - 1CADD1 (base 16) Bosung Electronics Co., Ltd. - 74-12, Saemaeul-ro. - Gumi-si Gyeongsangbuk-do 730-930 - KOREA, REPUBLIC OF - - 1C-AF-05 (hex) Samsung Electronics Co.,Ltd - 1CAF05 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 1C-AF-F7 (hex) D-LINK INTERNATIONAL PTE LIMITED - 1CAFF7 (base 16) D-LINK INTERNATIONAL PTE LIMITED - 1 INTERNATIONAL BUSINESS PARK, - #03-12, THE SYNERGY - 609917 - SINGAPORE - - 1C-B0-94 (hex) HTC Corporation - 1CB094 (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 1C-B1-7F (hex) NEC Platforms, Ltd. - 1CB17F (base 16) NEC Platforms, Ltd. - 800 Shimomata - Kakegawa Shizuoka 436-8501 - JAPAN - - 1C-B2-43 (hex) TDC A/S - 1CB243 (base 16) TDC A/S - Telehøjen 1 - Odense SØ 5220 - DENMARK - - 1C-B7-2C (hex) ASUSTek COMPUTER INC. - 1CB72C (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 1C-BA-8C (hex) Texas Instruments - 1CBA8C (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 1C-BB-A8 (hex) OJSC "Ufimskiy Zavod "Promsvyaz" - 1CBBA8 (base 16) OJSC "Ufimskiy Zavod "Promsvyaz" - 39, 50 let SSSR - Ufa Bashkortostan 450071 - RUSSIAN FEDERATION - - 1C-BD-0E (hex) Amplified Engineering Pty Ltd - 1CBD0E (base 16) Amplified Engineering Pty Ltd - 5 Turner Avenue - Bentley WA 6102 - AUSTRALIA - - 1C-BD-B9 (hex) D-LINK INTERNATIONAL PTE LIMITED - 1CBDB9 (base 16) D-LINK INTERNATIONAL PTE LIMITED - 1 INTERNATIONAL BUSINESS PARK, #03-12 - THE SYNERGY, 609917 - SINGAPORE - - 1C-C1-1A (hex) Wavetronix - 1CC11A (base 16) Wavetronix - 78 East 1700 South - Provo UT 84606 - UNITED STATES - - 1C-C1-DE (hex) Hewlett-Packard Company - 1CC1DE (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 1C-C3-16 (hex) MileSight Technology Co., Ltd. - 1CC316 (base 16) MileSight Technology Co., Ltd. - 202-2,No.21 Wanghai Road, 2nd Software Park - Xiamen Fujian 361006 - CHINA - - 1C-C5-86 (hex) Absolute Acoustics - 1CC586 (base 16) Absolute Acoustics - Av. Corifeu de Azevedo Marques, 1703 - Sao Paulo 05581-001 - BRAZIL - - 1C-C6-3C (hex) Arcadyan Technology Corporation - 1CC63C (base 16) Arcadyan Technology Corporation - 4F., No.9 , Park Avenue II - Hsinchu Science Park , - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 1C-C7-2D (hex) Shenzhen Huapu Digital CO.,Ltd - 1CC72D (base 16) Shenzhen Huapu Digital CO.,Ltd - R2305 Malata Technology Building,NO.9998 Shennan Boulevard, Shenzhen,P.R.China 518057 - Shenzhen Guangzhou 518057 - CHINA - - 1C-CA-E3 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 1CCAE3 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 1C-D4-0C (hex) Kriwan Industrie-Elektronik GmbH - 1CD40C (base 16) Kriwan Industrie-Elektronik GmbH - Allmand 11 - Forchtenberg Baden-Würtemberg D-74670 - GERMANY - - 1C-DE-A7 (hex) Cisco - 1CDEA7 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 1C-DF-0F (hex) CISCO SYSTEMS, INC. - 1CDF0F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 1C-E1-65 (hex) Marshal Corporation - 1CE165 (base 16) Marshal Corporation - Field Three Sotokanda Bldg. - 5-3-6, Sotokanda, Chiyoda-ku Tokyo 101-0021 - JAPAN - - 1C-E1-92 (hex) Qisda Corporation - 1CE192 (base 16) Qisda Corporation - 157 Shan-Ying Road - Gueishan Taoyuan 333 - TAIWAN, PROVINCE OF CHINA - - 1C-E2-CC (hex) Texas Instruments - 1CE2CC (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 1C-E6-2B (hex) Apple - 1CE62B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 1C-E6-C7 (hex) Cisco - 1CE6C7 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 1C-E8-5D (hex) Cisco - 1CE85D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 1C-EE-E8 (hex) Ilshin Elecom - 1CEEE8 (base 16) Ilshin Elecom - 2973, Hagun-ri, Yangchon-eup - Gimpo-si Gyeonggi-do 415-843 - KOREA, REPUBLIC OF - - 1C-F0-3E (hex) Wearhaus Inc. - 1CF03E (base 16) Wearhaus Inc. - 2041 Bancroft Way - Suite 303 - Berkeley CA 94704 - UNITED STATES - - 1C-F0-61 (hex) SCAPS GmbH - 1CF061 (base 16) SCAPS GmbH - Bahnhofstraße 17 - Deisenhofen Bavaria 82041 - GERMANY - - 1C-F4-CA (hex) PRIVATE - 1CF4CA (base 16) - - 1C-F5-E7 (hex) Turtle Industry Co., Ltd. - 1CF5E7 (base 16) Turtle Industry Co., Ltd. - 1-12-4 Nishineminami - Tsutiura Ibaraki 300-0842 - JAPAN - - 1C-FA-68 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 1CFA68 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) Central Science and Technology Park,Shennan Rd - shenzhen Guandong 518057 - CHINA - - 1C-FC-BB (hex) Realfiction ApS - 1CFCBB (base 16) Realfiction ApS - Oester Alle 42, 5 - Copenhagen OE 2100 - DENMARK - - 1C-FE-A7 (hex) IDentytech Solutins Ltd. - 1CFEA7 (base 16) IDentytech Solutins Ltd. - 14 Hadaya Street - Ramat- Hasharon 47226 - ISRAEL - - 20-01-4F (hex) Linea Research Ltd - 20014F (base 16) Linea Research Ltd - 1 Marquis Business Centre - Royston Road - Baldock Hertfordshire SG7 6XL - UNITED KINGDOM - - 20-02-AF (hex) Murata Manufactuaring Co.,Ltd. - 2002AF (base 16) Murata Manufactuaring Co.,Ltd. - 1-10-1 Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 20-05-05 (hex) RADMAX COMMUNICATION PRIVATE LIMITED - 200505 (base 16) RADMAX COMMUNICATION PRIVATE LIMITED - F-24/34, IIND FLOOR, SECTOR-7 - ROHINI, - DELHI DELHI 110085 - INDIA - - 20-05-E8 (hex) OOO InProMedia - 2005E8 (base 16) OOO InProMedia - pr.4806, d.6 - Zelenograd Moscow 124466 - RUSSIAN FEDERATION - - 20-08-ED (hex) Huawei Technologies Co., Ltd - 2008ED (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 20-0A-5E (hex) Xiangshan Giant Eagle Technology Developing co.,LTD - 200A5E (base 16) Xiangshan Giant Eagle Technology Developing co.,LTD - Juexi Road no.9 Juexi street - Xiangshan County Zhejiang Province - Ningbo Zhejiang 315708 - CHINA - - 20-0B-C7 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 200BC7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - Shenzhen Guangdong 518129 - CHINA - - 20-0C-C8 (hex) NETGEAR INC., - 200CC8 (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 20-0E-95 (hex) IEC – TC9 WG43 - 200E95 (base 16) IEC – TC9 WG43 - 3, rue de VarembeÌ - P.O. Box 131 - Geneva GE 1211 - SWITZERLAND - - 20-10-7A (hex) Gemtek Technology Co., Ltd. - 20107A (base 16) Gemtek Technology Co., Ltd. - No. 1 Jen Ai Road Hsinchu Industrial Park Hukou, - No. 15-1 Zhonghua Road, - Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - 20-12-57 (hex) Most Lucky Trading Ltd - 201257 (base 16) Most Lucky Trading Ltd - Room403 No.506 Zhongshan South 2nd Road,Xuhui District - Shanghai 200032 - CHINA - - 20-12-D5 (hex) Scientech Materials Corporation - 2012D5 (base 16) Scientech Materials Corporation - No.7, Hejiang 2nd Rd - Taoyuan Hsien Chungli 320 - TAIWAN, PROVINCE OF CHINA - - 20-13-E0 (hex) Samsung Electronics Co.,Ltd - 2013E0 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 20-16-D8 (hex) Liteon Technology Corporation - 2016D8 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo,New Taipei City - Taipei TaiWan 23585 - TAIWAN, PROVINCE OF CHINA - - 20-18-0E (hex) Shenzhen Sunchip Technology Co., Ltd - 20180E (base 16) Shenzhen Sunchip Technology Co., Ltd - Room 818-831, Building B1, - Mingyou Purchasing Center, Bao'an District - Shenzhen Guangdong 518101 - CHINA - - 20-1A-06 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - 201A06 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - No.25, Third Avenue, A Zone - Kunshan Comprehensive Free Trade Zone - KUNSHANJiangsu SUZHOU 215300 - CHINA - - 20-1D-03 (hex) Elatec GmbH - 201D03 (base 16) Elatec GmbH - Lilienthalstr. 3 - Puchheim Bayern 82178 - GERMANY - - 20-21-A5 (hex) LG Electronics Inc - 2021A5 (base 16) LG Electronics Inc - 60-39,Gasan-dong,Gumcheon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 20-25-64 (hex) PEGATRON CORPORATION - 202564 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 20-25-98 (hex) Teleview - 202598 (base 16) Teleview - #401 Sehwa, 355-1 - Yatap, Bundang - Sungnam Gyeonggi 463-828 - KOREA, REPUBLIC OF - - 20-28-BC (hex) Visionscape Co,. Ltd. - 2028BC (base 16) Visionscape Co,. Ltd. - 503, 145, Gasan Digital 1-ro, Geumcheon-gu, - Seoul Korea 153-787 - KOREA, REPUBLIC OF - - 20-2B-C1 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 202BC1 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 20-2C-B7 (hex) Kong Yue Electronics & Information Industry (Xinhui) Ltd. - 202CB7 (base 16) Kong Yue Electronics & Information Industry (Xinhui) Ltd. - Kong Yue Industrial Park, 18 Kongyue Road, Jinguzhou - Xinhui District, - Jiangmen Guangdong 529141 - CHINA - - 20-31-EB (hex) HDSN - 2031EB (base 16) HDSN - 4 allée des roseaux - Saint mitre les remparts BDR 13920 - FRANCE - - 20-37-06 (hex) CISCO SYSTEMS, INC. - 203706 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 20-37-BC (hex) Kuipers Electronic Engineering BV - 2037BC (base 16) Kuipers Electronic Engineering BV - Houtkopersstraat 6 - Zwijndrecht Zuid-Holland 3334 KD - NETHERLANDS - - 20-3A-07 (hex) Cisco - 203A07 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 20-40-05 (hex) feno GmbH - 204005 (base 16) feno GmbH - Kolpingring 22 - Oberhaching Bavaria 82041 - GERMANY - - 20-41-5A (hex) Smarteh d.o.o. - 20415A (base 16) Smarteh d.o.o. - Trg tigrovcev 1 - Tolmin 5220 - SLOVENIA - - 20-44-3A (hex) Schneider Electric Asia Pacific Ltd - 20443A (base 16) Schneider Electric Asia Pacific Ltd - 13F East Wing, Warwick House, Taikoo Place - 979 King's Road - Quarry Bay - HONG KONG - - 20-46-A1 (hex) VECOW Co., Ltd - 2046A1 (base 16) VECOW Co., Ltd - 7F., No.105, Zhongcheng Rd., Tucheng Dist., - New Taipei City 23674 - TAIWAN, PROVINCE OF CHINA - - 20-46-F9 (hex) Advanced Network Devices (dba:AND) - 2046F9 (base 16) Advanced Network Devices (dba:AND) - 3820 Ventura Drive - Arlington Heights IL 60004 - UNITED STATES - - 20-47-47 (hex) Dell Inc. - 204747 (base 16) Dell Inc. - One Dell Way - Round Rock Texas 78682 - UNITED STATES - - 20-4A-AA (hex) Hanscan Spain S.A. - 204AAA (base 16) Hanscan Spain S.A. - Avda. de la Vega, 1 - Alcobendas Madrid 28108 - SPAIN - - 20-4C-6D (hex) Hugo Brennenstuhl Gmbh & Co. KG. - 204C6D (base 16) Hugo Brennenstuhl Gmbh & Co. KG. - Seestr. 1-3 - Tuebingen Baden-Wuerttemberg 72074 - GERMANY - - 20-4C-9E (hex) Cisco - 204C9E (base 16) Cisco - 170 West Tasman Drive - San Jose CA 95134 - UNITED STATES - - 20-4E-6B (hex) Axxana(israel) ltd - 204E6B (base 16) Axxana(israel) ltd - Habarzel 38 - Tel aviv 69710 - ISRAEL - - 20-4E-7F (hex) NETGEAR - 204E7F (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 20-53-CA (hex) Risk Technology Ltd - 2053CA (base 16) Risk Technology Ltd - Matrix House, Merlin Court - Atlantic Street - Altrincham Cheshire WA14 5NL - UNITED KINGDOM - - 20-54-76 (hex) Sony Mobile Communications AB - 205476 (base 16) Sony Mobile Communications AB - Mobilvägen 10 - Lund 22188 - SWEDEN - - 20-57-21 (hex) Salix Technology CO., Ltd. - 205721 (base 16) Salix Technology CO., Ltd. - 5F., No. 16, Lane 77, Hsing Ai Road - Nei-Hu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 20-59-A0 (hex) Paragon Technologies Inc. - 2059A0 (base 16) Paragon Technologies Inc. - 68 North 4th Ring Rd West, - Suite 15B-H - Beijing 100080 - CHINA - - 20-5A-00 (hex) Coval - 205A00 (base 16) Coval - ZA Les Petits Champs - MONTELIER Drome 26120 - FRANCE - - 20-5B-2A (hex) PRIVATE - 205B2A (base 16) - - 20-5B-5E (hex) Shenzhen Wonhe Technology Co., Ltd - 205B5E (base 16) Shenzhen Wonhe Technology Co., Ltd - South Block 10th floor, Yuanxing Building, No. 1 - Songpingshan Rd, Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - 20-5C-FA (hex) Yangzhou ChangLian Network Technology Co,ltd. - 205CFA (base 16) Yangzhou ChangLian Network Technology Co,ltd. - No.60, Shangfang Temple Road - Hanjiang Area - Yangzhou City Jiangsu 225000 - CHINA - - 20-62-74 (hex) Microsoft Corporation - 206274 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 20-63-5F (hex) Abeeway - 20635F (base 16) Abeeway - 29 chemin du vieux chêne - meylan Isere 38240 - FRANCE - - 20-64-32 (hex) SAMSUNG ELECTRO MECHANICS CO.,LTD. - 206432 (base 16) SAMSUNG ELECTRO MECHANICS CO.,LTD. - 314, Maetan3-Dong, Yeongtong-Gu - Suwon Gyunggi-Do 443-743 - KOREA, REPUBLIC OF - - 20-67-B1 (hex) Pluto inc. - 2067B1 (base 16) Pluto inc. - Hongo5-21-1-303 - Bunkyo-ku Tokyo 113-0033 - JAPAN - - 20-68-9D (hex) Liteon Technology Corporation - 20689D (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road - ChungHo,New Taipei City - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 20-6A-8A (hex) Wistron InfoComm Manufacturing(Kunshan)Co.,Ltd. - 206A8A (base 16) Wistron InfoComm Manufacturing(Kunshan)Co.,Ltd. - 168# First Avenue,Kunshan Export Processing Zone - Kunshan Jiangsu 215300 - CHINA - - 20-6A-FF (hex) Atlas Elektronik UK Limited - 206AFF (base 16) Atlas Elektronik UK Limited - A22 Buliding, Dorset Green Tech. Park - Winfrith Newburgh - Dorchester Dorset DT2 8ZB - UNITED KINGDOM - - 20-6E-9C (hex) Samsung Electronics Co.,Ltd - 206E9C (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 20-6F-EC (hex) Braemac CA LLC - 206FEC (base 16) Braemac CA LLC - 43134 Osgood Road - Fremont CA 94539 - UNITED STATES - - 20-73-55 (hex) ARRIS Group, Inc. - 207355 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 20-74-CF (hex) Shenzhen Voxtech Co.,Ltd - 2074CF (base 16) Shenzhen Voxtech Co.,Ltd - 4/F East, Building 4, Minqi Science&Technology Park, Pingshan, - Xili, Nanshan, Shenzhen, PR China. - Shenzhen Guangdong 518055 - CHINA - - 20-76-00 (hex) Actiontec Electronics, Inc - 207600 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 20-76-93 (hex) Lenovo (Beijing) Limited. - 207693 (base 16) Lenovo (Beijing) Limited. - No.6 Chuang Ye Road Shangdi Information Industry Base, - Haidian District - Beijing 100085 - CHINA - - 20-7C-8F (hex) Quanta Microsystems,Inc. - 207C8F (base 16) Quanta Microsystems,Inc. - No.5 Lane 91,Dongmei Rd. - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 20-7D-74 (hex) Apple - 207D74 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 20-85-8C (hex) Assa - 20858C (base 16) Assa - Gurogu Guro3dong Ace Twintower 2cha 209 - Seoul 152-779 - KOREA, REPUBLIC OF - - 20-87-AC (hex) AES motomation - 2087AC (base 16) AES motomation - 48501 Warm Springs Blvd. - Suite 113 - Fremont CA 94539 - UNITED STATES - - 20-89-84 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD - 208984 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD - No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone - KUNSHAN SUZHOU 215300 - CHINA - - 20-89-86 (hex) zte corporation - 208986 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 20-91-48 (hex) Texas Instruments - 209148 (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 20-91-8A (hex) PROFALUX - 20918A (base 16) PROFALUX - 377 rue des Cypr - THYEZ Haute Savoie 74300 - FRANCE - - 20-91-D9 (hex) I'M SPA - 2091D9 (base 16) I'M SPA - VIA BIRON 102/3 - MONTEVIALE VICENZA 36050 - ITALY - - 20-93-4D (hex) Fujian Star-net Communication Co., Ltd - 20934D (base 16) Fujian Star-net Communication Co., Ltd - 19-22# Building,,Star-net Science Plaza - Juyuanzhou, 618 Jinshan Road - Fuzhou Fujian 350002 - CHINA - - 20-9A-E9 (hex) Volacomm Co., Ltd - 209AE9 (base 16) Volacomm Co., Ltd - 15F-6., No.7, Sec.3, New Taipei Blvd., Xinzhuang Dist., New Taipei City 242., Taiwan (R.O.C) - Xinzhuang Dist. New Taipei City 242 - TAIWAN, PROVINCE OF CHINA - - 20-9B-A5 (hex) JIAXING GLEAD Electronics Co.,Ltd - 209BA5 (base 16) JIAXING GLEAD Electronics Co.,Ltd - No.66 Zhengyuan Road in Tanghu Industrial Garden - Jiaxing Economic Development Zone - Jiaxing Zhejiang 314003 - CHINA - - 20-A2-E4 (hex) Apple - 20A2E4 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 20-A2-E7 (hex) Lee-Dickens Ltd - 20A2E7 (base 16) Lee-Dickens Ltd - Rushton Rd - Desborough - Kettering Northamptonshire NN14 2QW - UNITED KINGDOM - - 20-A7-87 (hex) Bointec Taiwan Corporation Limited - 20A787 (base 16) Bointec Taiwan Corporation Limited - 1F, A20, L790, SEC.5, - CHUNGHSIAO E. RD. - TAIPEI TAIWAN 11082 - TAIWAN, PROVINCE OF CHINA - - 20-A9-9B (hex) Microsoft Corporation - 20A99B (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - FINLAND - - 20-AA-25 (hex) IP-NET LLC - 20AA25 (base 16) IP-NET LLC - 10256 N.W. 47th St. - Sunrise FL 33351 - UNITED STATES - - 20-AA-4B (hex) Cisco-Linksys, LLC - 20AA4B (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 20-B0-F7 (hex) Enclustra GmbH - 20B0F7 (base 16) Enclustra GmbH - Technoparkstrasse 1 - Zurich ZH CH-8005 - SWITZERLAND - - 20-B3-99 (hex) Enterasys - 20B399 (base 16) Enterasys - 50 Minuteman Rd - Andover MA 01810 - UNITED STATES - - 20-B5-C6 (hex) Mimosa Networks - 20B5C6 (base 16) Mimosa Networks - 656 N. Santa Cruz. Ave., Suite B - Los Gatos CA 95030 - UNITED STATES - - 20-B7-C0 (hex) Omicron electronics GmbH - 20B7C0 (base 16) Omicron electronics GmbH - Oberes Ried 1 - Klaus 6833 - AUSTRIA - - 20-BB-C0 (hex) Cisco - 20BBC0 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 20-BB-C6 (hex) Jabil Circuit Hungary Ltd. - 20BBC6 (base 16) Jabil Circuit Hungary Ltd. - Huszár Andor 1. - Tiszaújváros H-3580 - HUNGARY - - 20-BF-DB (hex) DVL - 20BFDB (base 16) DVL - 21 Gradinilor Str - Chisinau MD2001 - MOLDOVA, REPUBLIC OF - - 20-C0-6D (hex) SHENZHEN SPACETEK TECHNOLOGY CO.,LTD - 20C06D (base 16) SHENZHEN SPACETEK TECHNOLOGY CO.,LTD - 3F, NO.2, ChaXiSanWei Industrial Park, Gushu Community, XiXiang Street, BaoAn District - ShenZhen GuangDong 518100 - CHINA - - 20-C1-AF (hex) i Wit Digital Co., Limited - 20C1AF (base 16) i Wit Digital Co., Limited - 303,Buiding1,Nanhai Ecool Innovation Park, - No.6 Xinghua Road,Shekou - Shenzhen GuangDong 518000 - CHINA - - 20-C3-8F (hex) Texas Instruments Inc - 20C38F (base 16) Texas Instruments Inc - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 20-C6-0D (hex) Shanghai annijie Information technology Co.,LTD - 20C60D (base 16) Shanghai annijie Information technology Co.,LTD - Room605,NO.9,Lane 777 - West Guangzhong Road, - Shanghai 200070 - CHINA - - 20-C6-EB (hex) Panasonic Corporation AVC Networks Company - 20C6EB (base 16) Panasonic Corporation AVC Networks Company - 1-15 Matsuo-cho - Kadoma City Osaka 571-8504 - JAPAN - - 20-C8-B3 (hex) SHENZHEN BUL-TECH CO.,LTD. - 20C8B3 (base 16) SHENZHEN BUL-TECH CO.,LTD. - Area C,4/F,NO.59,Longjing 2nd Road, - 3rd District,Baoan District - SHENZHEN GuangDong 518101 - CHINA - - 20-C9-D0 (hex) Apple - 20C9D0 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 20-CD-39 (hex) Texas Instruments, Inc - 20CD39 (base 16) Texas Instruments, Inc - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 20-CE-C4 (hex) Peraso Technologies - 20CEC4 (base 16) Peraso Technologies - 144 Front St. West, Suite 685 - Toronto ON M5J 2L7 - CANADA - - 20-CF-30 (hex) ASUSTek COMPUTER INC. - 20CF30 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 20-D2-1F (hex) Wincal Technology Corp. - 20D21F (base 16) Wincal Technology Corp. - 1028 South Greenwood Ave. - Suite 7 - Montebello California 90640 - UNITED STATES - - 20-D3-90 (hex) Samsung Electronics Co.,Ltd - 20D390 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 20-D5-AB (hex) Korea Infocom Co.,Ltd. - 20D5AB (base 16) Korea Infocom Co.,Ltd. - 5F Wintek B/D 511 - Poil-dong - Uiwang Kyunggi-Do 437-830 - KOREA, REPUBLIC OF - - 20-D5-BF (hex) Samsung Eletronics Co., Ltd - 20D5BF (base 16) Samsung Eletronics Co., Ltd - 416, Maetan 3dong, Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 20-D6-07 (hex) Nokia Corporation - 20D607 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - 20-D7-5A (hex) Posh Mobile Limited - 20D75A (base 16) Posh Mobile Limited - 1011A 10/F Harbour Centre Tower 1, 1 Hok Cheung Street - HungHom Kowloon 00000 - HONG KONG - - 20-D9-06 (hex) Iota, Inc. - 20D906 (base 16) Iota, Inc. - 2212 Queen Anne Ave. N., #348 - Seattle WA 98109 - UNITED STATES - - 20-DC-93 (hex) Cheetah Hi-Tech, Inc. - 20DC93 (base 16) Cheetah Hi-Tech, Inc. - Rm 804, No. 5, Sec. 2, Anhe Rd. - Taipei Taiwan 10680 - TAIWAN, PROVINCE OF CHINA - - 20-DC-E6 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 20DCE6 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) - Central Science and Technology Park,Shennan Rd, Nanshan District - shenzhen guangdong Province 518057 - CHINA - - 20-DF-3F (hex) Nanjing SAC Power Grid Automation Co., Ltd. - 20DF3F (base 16) Nanjing SAC Power Grid Automation Co., Ltd. - No.11 Phoenix Road - Jiangning Development Zone - Nanjing Jiangsu 211106 - CHINA - - 20-E4-07 (hex) Spark srl - 20E407 (base 16) Spark srl - Via A. Gramsci 86/A - Reggio Emilia 42124 - ITALY - - 20-E5-2A (hex) NETGEAR INC., - 20E52A (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 20-E5-64 (hex) ARRIS Group, Inc. - 20E564 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 20-E7-91 (hex) Siemens Healthcare Diagnostics, Inc - 20E791 (base 16) Siemens Healthcare Diagnostics, Inc - 2 Edgewater Drive - Norwood MA 02062 - UNITED STATES - - 20-EA-C7 (hex) SHENZHEN RIOPINE ELECTRONICS CO., LTD - 20EAC7 (base 16) SHENZHEN RIOPINE ELECTRONICS CO., LTD - ROOM1002~1004, - BaoYuan HuaFeng Headquarters' Business Building, Xixiang Avenue (west) , - Bao'an District Shenzhen Guangdong 518000 - CHINA - - 20-ED-74 (hex) Ability enterprise co.,Ltd. - 20ED74 (base 16) Ability enterprise co.,Ltd. - 4F., No.8, Ln.7, Wuquan Rd - Wugu Dist, - Taipei 24886 - TAIWAN, PROVINCE OF CHINA - - 20-EE-C6 (hex) Elefirst Science & Tech Co ., ltd - 20EEC6 (base 16) Elefirst Science & Tech Co ., ltd - Floor 9, No 77 Zijinmingmen Building - Muxuyuan Avenue - Nanjing Jiangsu 210007 - CHINA - - 20-F0-02 (hex) MTData Developments Pty. Ltd. - 20F002 (base 16) MTData Developments Pty. Ltd. - 20 Miles Street - Mulgrave Victoria 3170 - AUSTRALIA - - 20-F3-A3 (hex) Huawei Technologies Co., Ltd - 20F3A3 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 20-F4-1B (hex) Shenzhen Bilian electronic CO.,LTD - 20F41B (base 16) Shenzhen Bilian electronic CO.,LTD - NO 268, Fuqian Rd,Jutang Community,Guanlan town, - LongHua new district,Shenzhen,518110,China. - ShenZhen Guangdong 518110 - CHINA - - 20-F8-5E (hex) Delta Electronics - 20F85E (base 16) Delta Electronics - 252 Shangying Road - Guishan Industrial Zone - Taoyuan County Taiwan 33341 - TAIWAN, PROVINCE OF CHINA - - 20-FA-BB (hex) Cambridge Executive Limited - 20FABB (base 16) Cambridge Executive Limited - St John's Innovation Centre - Cowley Road - Cambridge Cambridgeshire CB40WS - UNITED KINGDOM - - 20-FD-F1 (hex) 3COM EUROPE LTD - 20FDF1 (base 16) 3COM EUROPE LTD - Peoplebuilding 2 - Maylands Avenue - Hemel Hempstead Hertfordshire HP2 4NW - UNITED KINGDOM - - 20-FE-CD (hex) System In Frontier Inc. - 20FECD (base 16) System In Frontier Inc. - 4F Shinsuzuharu Bldg. 2-8-3 Akebonocyo - Tachikawa-shi Tokyo 190-0012 - JAPAN - - 20-FE-DB (hex) M2M Solution S.A.S. - 20FEDB (base 16) M2M Solution S.A.S. - Centre d'Affaires Regus Bat.D - 45 Allee des Ormes - Mougins 06254 - FRANCE - - 24-01-C7 (hex) Cisco - 2401C7 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 24-05-0F (hex) MTN Electronic Co. Ltd - 24050F (base 16) MTN Electronic Co. Ltd - MTN Industrial Park,No 3, Fuhua Road, - Pingxi Community,Longgang District - Shenzhen Guangdong Province 518117 - CHINA - - 24-09-17 (hex) Devlin Electronics Limited - 240917 (base 16) Devlin Electronics Limited - Unit D1 - Grafton Way - Basingstoke Hampshire RG226HZ - UNITED KINGDOM - - 24-09-95 (hex) Huawei Technologies Co., Ltd - 240995 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 24-0A-11 (hex) TCT Mobile Limited - 240A11 (base 16) TCT Mobile Limited - No.86, Hechang 7th West Road ,Zhong Kai Hi-tech Development District, Hui Zhou, Guang Dong - Huizhou Guangdong 516006 - CHINA - - 24-0A-64 (hex) AzureWaveTechnologies,Inc - 240A64 (base 16) AzureWaveTechnologies,Inc - 9F.,No.92,Baozhong Rd - Xindian Dist - Xindian NewTaipeiCity 231 - TAIWAN, PROVINCE OF CHINA - - 24-0B-2A (hex) Viettel Group - 240B2A (base 16) Viettel Group - Center for Research and Development - 01 Giang Van Minh, Ba Dinh - Hanoi 1111 - VIETNAM - - 24-0B-B1 (hex) KOSTAL Industrie Elektrik GmbH - 240BB1 (base 16) KOSTAL Industrie Elektrik GmbH - Gewerbering 20 - Schalksmuehle North Rhine-Westphalia 58579 - GERMANY - - 24-10-64 (hex) Shenzhen Ecsino Tecnical Co. Ltd - 241064 (base 16) Shenzhen Ecsino Tecnical Co. Ltd - 7F Guoxin build ChangXin Road. Nan'shan District - Shenzhen Guangdong 518000 - CHINA - - 24-11-25 (hex) Hutek Co., Ltd. - 241125 (base 16) Hutek Co., Ltd. - E-402 Bundang Technopark - 151 Yatap-dong, Bundang-gu - Seongnam-city Gyeonggi-do 463-760 - KOREA, REPUBLIC OF - - 24-11-48 (hex) Entropix, LLC - 241148 (base 16) Entropix, LLC - 100 Rawson Road - Suite 212 - Victor New York 14564 - UNITED STATES - - 24-11-D0 (hex) Chongqing Ehs Science and Technology Development Co.,Ltd. - 2411D0 (base 16) Chongqing Ehs Science and Technology Development Co.,Ltd. - Saturn Business Center C3-15-7,Starlight No.5 Street - Beibu New District, - Chongqing 400060 - CHINA - - 24-1A-8C (hex) Squarehead Technology AS - 241A8C (base 16) Squarehead Technology AS - PO Box 13 Nydalen - Oslo NO-0410 - NORWAY - - 24-1B-13 (hex) Shanghai Nutshell Electronic Co., Ltd. - 241B13 (base 16) Shanghai Nutshell Electronic Co., Ltd. - 365 Guoshoujing RD.,Zhangjiang Hi-Tech Park, Pudong District - Shanghai Shanghai 201203 - CHINA - - 24-1B-44 (hex) Hangzhou Tuners Electronics Co., Ltd - 241B44 (base 16) Hangzhou Tuners Electronics Co., Ltd - 5/F,Building No.1,No.619 - BinKang Road - BinJiang District, Hangzhou ZheJiang 310053 - CHINA - - 24-1C-04 (hex) SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. - 241C04 (base 16) SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. - 2/F, Block A, Tsinghua Information Harbor, North Section - Shenzhen Hi-Tech Park, Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 24-1F-2C (hex) Calsys, Inc. - 241F2C (base 16) Calsys, Inc. - 2700 Augustine drive, Ste145 - Santa Clara California 95054 - UNITED STATES - - 24-21-AB (hex) Sony Ericsson Mobile Communications - 2421AB (base 16) Sony Ericsson Mobile Communications - Nya Vattentornet - Lund 22188 - SWEDEN - - 24-24-0E (hex) Apple - 24240E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 24-26-42 (hex) SHARP Corporation. - 242642 (base 16) SHARP Corporation. - 22-22,Abeno-ku - Nagaike-Cho - Osaka-City Osaka-Prefecture 545-8522 - JAPAN - - 24-2F-FA (hex) Toshiba Global Commerce Solutions - 242FFA (base 16) Toshiba Global Commerce Solutions - B307/D121F - 3039 E Cornwallis Rd - RTP NC 27709 - UNITED STATES - - 24-33-6C (hex) PRIVATE - 24336C (base 16) - - 24-37-4C (hex) Cisco SPVTG - 24374C (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 24-37-EF (hex) EMC Electronic Media Communication SA - 2437EF (base 16) EMC Electronic Media Communication SA - Via Cantonale 4 - S. Antonino Ticino 6592 - SWITZERLAND - - 24-3C-20 (hex) Dynamode Group - 243C20 (base 16) Dynamode Group - Head Office, 132a St Albans Road - Watford Herts WD24 4AE - UNITED KINGDOM - - 24-42-BC (hex) Alinco,incorporated - 2442BC (base 16) Alinco,incorporated - Yodoyabashi Dai-Bldg 13F, - 4 Chome 4-9, Koraibashi, Chuo-ku - Osaka Osaka pref. 541-0043 - JAPAN - - 24-45-97 (hex) GEMUE Gebr. Mueller Apparatebau - 244597 (base 16) GEMUE Gebr. Mueller Apparatebau - Fritz-Mueller-Strasse 6-8 - Ingelfingen Criesbach 74653 - GERMANY - - 24-47-0E (hex) PentronicAB - 24470E (base 16) PentronicAB - Bergsliden 1 - GUNNEBO 59093 - SWEDEN - - 24-49-7B (hex) Innovative Converged Devices Inc - 24497B (base 16) Innovative Converged Devices Inc - 424 8th Avenue North - Seattle WA 98109 - UNITED STATES - - 24-4B-03 (hex) Samsung Electronics Co.,Ltd - 244B03 (base 16) Samsung Electronics Co.,Ltd - 129, Samsung-ro, Youngtongl-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 24-4B-81 (hex) Samsung Electronics Co.,Ltd - 244B81 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 24-4F-1D (hex) iRule LLC - 244F1D (base 16) iRule LLC - 1555 Broadway St - Detroit MI 48226 - UNITED STATES - - 24-5F-DF (hex) KYOCERA Corporation - 245FDF (base 16) KYOCERA Corporation - 2-1-1,Kagahara, - Tsuzuki-ku - Yokohama-shi Kanagawa 224-8502 - JAPAN - - 24-62-78 (hex) sysmocom - systems for mobile communications GmbH - 246278 (base 16) sysmocom - systems for mobile communications GmbH - Schievelbeiner Str. 5 - Berlin 10439 - GERMANY - - 24-64-EF (hex) CYG SUNRI CO.,LTD. - 2464EF (base 16) CYG SUNRI CO.,LTD. - No. 3, Langshan 1st Road, North Area of Hi-Tech Industrial Park - Nanshan District, Shenzhen City - Shenzhen Guangdong 518057 - CHINA - - 24-65-11 (hex) AVM GmbH - 246511 (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 24-69-3E (hex) innodisk Corporation - 24693E (base 16) innodisk Corporation - 5F., No. 237, Sec. 1, Datong Rd., Xizhi Dist. - New Taipei City Taiwan 221 - TAIWAN, PROVINCE OF CHINA - - 24-69-4A (hex) Jasmine Systems Inc. - 24694A (base 16) Jasmine Systems Inc. - 50 Charles Lindbergh Blvd. Suite 411 - Uniondale NY 11553 - UNITED STATES - - 24-69-A5 (hex) Huawei Technologies Co., Ltd - 2469A5 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - 24-6A-AB (hex) IT-IS International - 246AAB (base 16) IT-IS International - 1 Wainstones Court - Stokesley - Middlesbrough Cleveland TS9 5JY - UNITED KINGDOM - - 24-71-89 (hex) Texas Instruments - 247189 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - 24-76-56 (hex) Shanghai Net Miles Fiber Optics Technology Co., LTD. - 247656 (base 16) Shanghai Net Miles Fiber Optics Technology Co., LTD. - Flat F, 17th Floor, Southern International Mansion - 8519 Nanfeng Road - Shanghai 201401 - CHINA - - 24-76-7D (hex) Cisco SPVTG - 24767D (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 24-77-03 (hex) Intel Corporate - 247703 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 24-7F-3C (hex) Huawei Technologies Co., Ltd - 247F3C (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 24-80-00 (hex) Westcontrol AS - 248000 (base 16) Westcontrol AS - Breivikvg 7 - Joerpeland - 4100 - NORWAY - - 24-81-AA (hex) KSH International Co., Ltd. - 2481AA (base 16) KSH International Co., Ltd. - 2F, No.17 Minsheng Rd, Xindian Dist., - New Taipei City 23150 - TAIWAN, PROVINCE OF CHINA - - 24-82-8A (hex) Prowave Technologies Ltd. - 24828A (base 16) Prowave Technologies Ltd. - 2F,No.879-16,Zhongjiang Road - Shanghai 200333 - CHINA - - 24-86-F4 (hex) Ctek, Inc. - 2486F4 (base 16) Ctek, Inc. - 34 Miraleste Plaza - Rancho Palos Verdes California 90275 - UNITED STATES - - 24-87-07 (hex) SEnergy Corporation - 248707 (base 16) SEnergy Corporation - Koizumi Bldg. 3F, 1-38-18 - Nakagawa-cyuo Tsuzuki-ku - Yokohama city Kanagawa Pref. 224-0003 - JAPAN - - 24-93-CA (hex) Voxtronic Technology Computer-Systeme GmbH - 2493CA (base 16) Voxtronic Technology Computer-Systeme GmbH - Jochen-Rindt-Straße 15 - Vienna 1230 - AUSTRIA - - 24-94-42 (hex) OPEN ROAD SOLUTIONS , INC. - 249442 (base 16) OPEN ROAD SOLUTIONS , INC. - 88-13 SHUILI ROAD - HSINCHU 30059 - TAIWAN, PROVINCE OF CHINA - - 24-95-04 (hex) SFR - 249504 (base 16) SFR - 40-42 QUAI DU POINT DU JOUR - BOULOGNE BILLANCOURT HAUT DE SEINE 92100 - FRANCE - - 24-97-ED (hex) Techvision Intelligent Technology Limited - 2497ED (base 16) Techvision Intelligent Technology Limited - Room 7006B, Tianxia IC Industry Building, - Yiyuan Road, Nanshan District - Shenzhen Guangdong 518052 - CHINA - - 24-9E-AB (hex) HUAWEI TECHNOLOGIES CO.,LTD - 249EAB (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - 24-A0-74 (hex) Apple - 24A074 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 24-A2-E1 (hex) Apple, Inc - 24A2E1 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 24-A4-2C (hex) KOUKAAM a.s. - 24A42C (base 16) KOUKAAM a.s. - U vinnych sklepu 7 - Prague 190 00 - CZECH REPUBLIC - - 24-A4-3C (hex) Ubiquiti Networks, INC - 24A43C (base 16) Ubiquiti Networks, INC - 91 E. Tasman Dr. - San Jose California 95134 - UNITED STATES - - 24-A4-95 (hex) Thales Canada Inc. - 24A495 (base 16) Thales Canada Inc. - 105 Moatfield Road - Suite 100 - Toronto Ontario M3B 0A4 - CANADA - - 24-A8-7D (hex) Panasonic Automotive Systems Asia Pacific(Thailand)Co.,Ltd. - 24A87D (base 16) Panasonic Automotive Systems Asia Pacific(Thailand)Co.,Ltd. - 101 Moo 2 Teparak Road , - T.Bangsaothong - Bangsaothong Samutprakarn 10540 - THAILAND - - 24-A9-37 (hex) PURE Storage - 24A937 (base 16) PURE Storage - 650 Castro Street - 440 - Mt. View CA 94041 - UNITED STATES - - 24-AB-81 (hex) Apple - 24AB81 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 24-AF-4A (hex) Alcatel-Lucent-IPD - 24AF4A (base 16) Alcatel-Lucent-IPD - 777 Middlefield Rd. - Mountain View CA 94043 - UNITED STATES - - 24-AF-54 (hex) NEXGEN Mediatech Inc. - 24AF54 (base 16) NEXGEN Mediatech Inc. - 8F No. 150, Jianyi Rd., - Chung Ho Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 24-B0-A9 (hex) Shanghai Mobiletek Communication Ltd. - 24B0A9 (base 16) Shanghai Mobiletek Communication Ltd. - RM201, Building 9, No 99 Tianzhou RD, Shanghai China - Shanghai Shanghai 200233 - CHINA - - 24-B6-57 (hex) CISCO SYSTEMS, INC. - 24B657 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 24-B6-B8 (hex) FRIEM SPA - 24B6B8 (base 16) FRIEM SPA - Via Edison 1 - Segrate Milano 20090 - ITALY - - 24-B6-FD (hex) Dell Inc - 24B6FD (base 16) Dell Inc - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 24-B8-8C (hex) Crenus Co.,Ltd. - 24B88C (base 16) Crenus Co.,Ltd. - Mario Tower 814, 222-12 - Guro-dong, Guro-gu - Seoul 152-050 - KOREA, REPUBLIC OF - - 24-B8-D2 (hex) Opzoon Technology Co.,Ltd. - 24B8D2 (base 16) Opzoon Technology Co.,Ltd. - 11th floor, Tower B£¬Yintai Center 2 Jianguomenwai St,. - Beijing Asia 100022 - CHINA - - 24-BA-30 (hex) Technical Consumer Products, Inc. - 24BA30 (base 16) Technical Consumer Products, Inc. - 325 Campus Drive - Aurora OH 44202 - UNITED STATES - - 24-BB-C1 (hex) Absolute Analysis - 24BBC1 (base 16) Absolute Analysis - 2393 Teller Road Ste #109 - Newbury Park California 91320 - UNITED STATES - - 24-BC-82 (hex) Dali Wireless, Inc. - 24BC82 (base 16) Dali Wireless, Inc. - 125 University Avenue, Suite 88 - Palo Alto CA 94301 - UNITED STATES - - 24-BE-05 (hex) Hewlett Packard - 24BE05 (base 16) Hewlett Packard - 11445 Compaq Center Drive W - Houston Texas 77070 - UNITED STATES - - 24-BF-74 (hex) PRIVATE - 24BF74 (base 16) - - 24-C0-B3 (hex) RSF - 24C0B3 (base 16) RSF - 45 Av Marcel Dassault - Toulouse Garonne, Haute (31) 31500 - FRANCE - - 24-C6-96 (hex) Samsung Electronics Co.,Ltd - 24C696 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 24-C8-48 (hex) mywerk system GmbH - 24C848 (base 16) mywerk system GmbH - Dennis-Gabor-Str. 2 - Potsdam Brandenburg 14469 - GERMANY - - 24-C8-6E (hex) Chaney Instrument Co. - 24C86E (base 16) Chaney Instrument Co. - 965 Wells Street - Lake Geneva WI 53147 - UNITED STATES - - 24-C9-A1 (hex) Ruckus Wireless - 24C9A1 (base 16) Ruckus Wireless - 350 West Java Drive - Sunnyvale CA 94089 - UNITED STATES - - 24-C9-DE (hex) Genoray - 24C9DE (base 16) Genoray - #812 Byucksan Technopia 434-6 Sangdaewon 1-Dong - Jungwon-Gu - Seongnam-City Gyeonggi-Do 462-716 - KOREA, REPUBLIC OF - - 24-CB-E7 (hex) MYK, Inc. - 24CBE7 (base 16) MYK, Inc. - 4-60-30-108, Kamoi, - Midori-ku - Yokohama Kanagawa 226-0003 - JAPAN - - 24-CF-21 (hex) Shenzhen State Micro Technology Co., Ltd - 24CF21 (base 16) Shenzhen State Micro Technology Co., Ltd - SSMEC Building2/F, Gao Xin Nan First Avenue, Hi-Tech Park South, Nanshan - Shenzhen City Guangdong Province 518057 - CHINA - - 24-D1-3F (hex) MEXUS CO.,LTD - 24D13F (base 16) MEXUS CO.,LTD - 1512, Seoulsup IT Valley, - 77, Seongsuil-ro, Seongdong-gu, - Seoul 133-822 - KOREA, REPUBLIC OF - - 24-D2-CC (hex) SmartDrive Systems Inc. - 24D2CC (base 16) SmartDrive Systems Inc. - 9276 Scranton Road - Suite 500 - San Diego CA 92121 - UNITED STATES - - 24-D9-21 (hex) Avaya, Inc - 24D921 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 24-DA-B6 (hex) Sistemas de Gestión Energética S.A. de C.V - 24DAB6 (base 16) Sistemas de Gestión Energética S.A. de C.V - Calzada de los Fresnos 70-A - Ciudad Granja - Zapopan Jalisoc 45010 - MEXICO - - 24-DB-AC (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 24DBAC (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 24-DB-AD (hex) ShopperTrak RCT Corporation - 24DBAD (base 16) ShopperTrak RCT Corporation - 200 W. Monroe Street - Suite 1100 - Chicago IL 60606 - UNITED STATES - - 24-DB-ED (hex) Samsung Electronics Co.,Ltd - 24DBED (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 24-DE-C6 (hex) Aruba Networks - 24DEC6 (base 16) Aruba Networks - 1344 Crossman Ave. - Sunnyvale CA 94089 - UNITED STATES - - 24-E2-71 (hex) Qingdao Hisense Communications Co.,Ltd - 24E271 (base 16) Qingdao Hisense Communications Co.,Ltd - 218,Qianwangang Road, Qingdao Economic&Technological Development Zone - Qingdao Shandong 266510 - CHINA - - 24-E3-14 (hex) Apple - 24E314 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 24-E5-AA (hex) Philips Oral Healthcare, Inc. - 24E5AA (base 16) Philips Oral Healthcare, Inc. - 22100 Bothell Everett Hwy - Bothell WA 98021 - UNITED STATES - - 24-E6-BA (hex) JSC Zavod im. Kozitsky - 24E6BA (base 16) JSC Zavod im. Kozitsky - Bld. 70, 5th line, V.O, - St.-Petersburg 199048 - RUSSIAN FEDERATION - - 24-E9-B3 (hex) Cisco - 24E9B3 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 24-EA-40 (hex) Systeme Helmholz GmbH - 24EA40 (base 16) Systeme Helmholz GmbH - Hannberger Weg 2 - Grossenseebach BAY 91091 - GERMANY - - 24-EB-65 (hex) SAET I.S. S.r.l. - 24EB65 (base 16) SAET I.S. S.r.l. - Via Leinì 1/B - San Maurizio C.se TO 10077 - ITALY - - 24-EC-99 (hex) Askey Computer Corp - 24EC99 (base 16) Askey Computer Corp - 10F,NO.119,CHIENKANG RD,CHUNG-HO, - TAIPEI 23585 - TAIWAN, PROVINCE OF CHINA - - 24-EC-D6 (hex) CSG Science & Technology Co.,Ltd.Hefei - 24ECD6 (base 16) CSG Science & Technology Co.,Ltd.Hefei - No.612-1,Huangshan Road,Gaoxin District - Hefei Anhui Province 230088 - CHINA - - 24-EE-3A (hex) Chengdu Yingji Electronic Hi-tech Co Ltd - 24EE3A (base 16) Chengdu Yingji Electronic Hi-tech Co Ltd - No.3 South Herui Road Hi-tech Zone - Chengdu City Sichuan 611731 - CHINA - - 24-F0-FF (hex) GHT Co., Ltd. - 24F0FF (base 16) GHT Co., Ltd. - #16 Nanyunyi Lu, Guangzhou Science City - Guangzhou Guangdong 510663 - CHINA - - 24-F2-DD (hex) Radiant Zemax LLC - 24F2DD (base 16) Radiant Zemax LLC - 22908 NE Alder Crest Dr NE Ste 100 - Redmond WA 98053 - UNITED STATES - - 24-F5-AA (hex) Samsung Electronics Co.,LTD - 24F5AA (base 16) Samsung Electronics Co.,LTD - 129, Samsung-ro, Yeongtong-gu - Suwon Gyeonggi-Do 443-742 - KOREA, REPUBLIC OF - - 24-FD-52 (hex) Liteon Technology Corporation - 24FD52 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo - New Taipei City 23585 - TAIWAN, PROVINCE OF CHINA - - 28-04-E0 (hex) FERMAX ELECTRONICA S.A.U. - 2804E0 (base 16) FERMAX ELECTRONICA S.A.U. - Tres Cruces 133 - Valencia 46017 - SPAIN - - 28-06-1E (hex) NINGBO GLOBAL USEFUL ELECTRIC CO.,LTD - 28061E (base 16) NINGBO GLOBAL USEFUL ELECTRIC CO.,LTD - No.88,Kechuang South Road, - Wangchun Industry Zone - Ningbo Zhejiang 315000 - CHINA - - 28-06-8D (hex) ITL, LLC - 28068D (base 16) ITL, LLC - P.O. Box 41875 - Nashville TN 37204 - UNITED STATES - - 28-0B-5C (hex) Apple - 280B5C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-0C-B8 (hex) Mikrosay Yazilim ve Elektronik A.S. - 280CB8 (base 16) Mikrosay Yazilim ve Elektronik A.S. - Cevizli Mah. Tansel Cad. - no:18 Maltepe - Istanbul 34846 - TURKEY - - 28-0D-FC (hex) Sony Computer Entertainment Inc. - 280DFC (base 16) Sony Computer Entertainment Inc. - 1-7-1 Konan - Minato-ku Tokyo 108-0075 - JAPAN - - 28-10-7B (hex) D-Link International - 28107B (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy - 609917 - SINGAPORE - - 28-14-71 (hex) Lantis co., LTD. - 281471 (base 16) Lantis co., LTD. - busan innobiz center 401 - buk-ku, mandeok 3-dong - busan 616-829 - KOREA, REPUBLIC OF - - 28-16-2E (hex) 2Wire - 28162E (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 28-17-CE (hex) Omnisense Ltd - 2817CE (base 16) Omnisense Ltd - 3rd Floor St Andrew's House - 59 St Andrews Street - Cambridge Cambridgeshire CB2 3BZ - UNITED KINGDOM - - 28-18-78 (hex) Microsoft Corporation - 281878 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 28-18-FD (hex) Aditya Infotech Ltd. - 2818FD (base 16) Aditya Infotech Ltd. - Khemka Square, A-12, Sector-4, - Noida Uttar Pradesh 201301 - INDIA - - 28-22-46 (hex) Beijing Sinoix Communication Co., LTD - 282246 (base 16) Beijing Sinoix Communication Co., LTD - Gehua Tower Room 603 - Beijing 100000 - CHINA - - 28-26-A6 (hex) PBR electronics GmbH - 2826A6 (base 16) PBR electronics GmbH - Berliner Strasse 5 - Sandhausen Baden Wuertemmberg 69207 - GERMANY - - 28-28-5D (hex) ZyXEL Communications Corporation - 28285D (base 16) ZyXEL Communications Corporation - No. 6 Innovation Road II, Science Park, Hsinchu, Taiwan - Hsichu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 28-29-CC (hex) Corsa Technology Incorporated - 2829CC (base 16) Corsa Technology Incorporated - 505 March Road - Ottawa Ontario K2K 3A4 - CANADA - - 28-29-D9 (hex) GlobalBeiMing technology (Beijing)Co. Ltd - 2829D9 (base 16) GlobalBeiMing technology (Beijing)Co. Ltd - Beijing Chaoyang District 8 Guanghua Road A seat 320 rooms - Beijing 100026 - CHINA - - 28-2C-B2 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 282CB2 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - 28-31-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 283152 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 28-32-C5 (hex) Humax.co.,ltd - 2832C5 (base 16) Humax.co.,ltd - HUMAX Village,216,Hwangsaeul-ro,Bundang-gu - Seongnam-si Gyeonggi-do 463-875 - KOREA, REPUBLIC OF - - 28-34-10 (hex) Enigma Diagnostics Limited - 283410 (base 16) Enigma Diagnostics Limited - Building 224 - Titricus Science Park - DSTL Porton Down Salisbury SP4 0JQ - UNITED KINGDOM - - 28-34-A2 (hex) Cisco - 2834A2 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 28-37-37 (hex) Apple - 283737 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-38-CF (hex) Gen2wave - 2838CF (base 16) Gen2wave - Gumi-dong, Bundang-gu - #707, Point town B/D, 187-4 - Seongnam-si Gyeonggi-do 463-741 - KOREA, REPUBLIC OF - - 28-39-E7 (hex) Preceno Technology Pte.Ltd. - 2839E7 (base 16) Preceno Technology Pte.Ltd. - 11F, No.207-2, Sec. 3, Beixin Rd., Xindian Dist. - New Taipei City 23143 - TAIWAN, PROVINCE OF CHINA - - 28-3B-96 (hex) Cool Control LTD - 283B96 (base 16) Cool Control LTD - Mivtahim 2 - Petah Tikva Israel 4951774 - ISRAEL - - 28-3C-E4 (hex) Huawei Technologies Co., Ltd - 283CE4 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - 28-40-1A (hex) C8 MediSensors, Inc. - 28401A (base 16) C8 MediSensors, Inc. - 727 University Ave - Los Gatos CA 95032 - UNITED STATES - - 28-41-21 (hex) OptiSense Network, LLC - 284121 (base 16) OptiSense Network, LLC - 1308 10th Street - Bridgeport TX 76426 - UNITED STATES - - 28-44-30 (hex) GenesisTechnical Systems (UK) Ltd - 284430 (base 16) GenesisTechnical Systems (UK) Ltd - Venture Centre - Sir William Lyons Rd - Coventry CV4 7EZ - UNITED KINGDOM - - 28-47-AA (hex) Nokia Corporation - 2847AA (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - 28-48-46 (hex) GridCentric Inc. - 284846 (base 16) GridCentric Inc. - 350 Bloor St. E - Toronto Ontario M4W 0A1 - CANADA - - 28-4C-53 (hex) Intune Networks - 284C53 (base 16) Intune Networks - 9B Beckett Way - Parkwest Business Park - Dublin 12 - IRELAND - - 28-4D-92 (hex) Luminator - 284D92 (base 16) Luminator - 900 Klein Road - Plano Texas 75074 - UNITED STATES - - 28-4E-D7 (hex) OutSmart Power Systems, Inc. - 284ED7 (base 16) OutSmart Power Systems, Inc. - 11 Mercer Rd - Natick 23 01760 - UNITED STATES - - 28-4F-CE (hex) Liaoning Wontel Science and Technology Development Co.,Ltd. - 284FCE (base 16) Liaoning Wontel Science and Technology Development Co.,Ltd. - A704 Floor TaiHe building - No.99,Shenzhou road - Shenyang Liaoning 110000 - CHINA - - 28-51-32 (hex) Shenzhen Prayfly Technology Co.,Ltd - 285132 (base 16) Shenzhen Prayfly Technology Co.,Ltd - 16F B International Chamber of Commerce Building - NO.138 Fuhua 1RD Futian Area - Shenzhen Guangdong Province 518048 - CHINA - - 28-52-E0 (hex) Layon international Electronic & Telecom Co.,Ltd - 2852E0 (base 16) Layon international Electronic & Telecom Co.,Ltd - 4rd Floor, Building 15, Juda Industrial Zone, ShiBei Industrial Road, - HuiJiang , Da Shi Street - PanYu District, Guangzhou guangdong 511430 - CHINA - - 28-57-67 (hex) Echostar Technologies Corp - 285767 (base 16) Echostar Technologies Corp - 94 Inverness Terrace E - Englewood CO 80112 - UNITED STATES - - 28-5A-EB (hex) Apple - 285AEB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-5F-DB (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 285FDB (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 28-60-46 (hex) Lantech Communications Global, Inc. - 286046 (base 16) Lantech Communications Global, Inc. - 7F, No. 45, Lane 188, Ruiguang Rd., Neihu District - Taipei City 11491 - TAIWAN, PROVINCE OF CHINA - - 28-60-94 (hex) CAPELEC - 286094 (base 16) CAPELEC - 1130 rue des Marels - Montpellier Hérault 34000 - FRANCE - - 28-63-36 (hex) Siemens AG - Industrial Automation - EWA - 286336 (base 16) Siemens AG - Industrial Automation - EWA - Werner-von-Siemens Strasse 50 - Amberg 92224 - GERMANY - - 28-65-6B (hex) Keystone Microtech Corporation - 28656B (base 16) Keystone Microtech Corporation - 9F., No.255, Dong Sec. 1, - Guangming 6th Rd., - Jhubei City, Hsinchu County 302 - TAIWAN, PROVINCE OF CHINA - - 28-6A-B8 (hex) Apple - 286AB8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-6A-BA (hex) Apple - 286ABA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-6D-97 (hex) SAMJIN Co., Ltd. - 286D97 (base 16) SAMJIN Co., Ltd. - 199-6, Anyang 7-dong, Manan-gu - Anyang-si Gyeonggi-do 430-817 - KOREA, REPUBLIC OF - - 28-6E-D4 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 286ED4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - B1-7,Huawei Industrial Base,Bantian,Longgang - ShenZhen guangdong 518129 - CHINA - - 28-71-84 (hex) Spire Payments - 287184 (base 16) Spire Payments - Units 3 & 6 Milford Trading Estate - Blakey Road - Salisbury Wiltshire SP1 2UD - UNITED KINGDOM - - 28-72-C5 (hex) Smartmatic Corp - 2872C5 (base 16) Smartmatic Corp - 1001 Broken Sound Pkwy NW Suite D - Boca Raton Florida 33487 - UNITED STATES - - 28-72-F0 (hex) ATHENA - 2872F0 (base 16) ATHENA - 42 RUE MONGE - PARIS 75005 - FRANCE - - 28-76-10 (hex) IgniteNet - 287610 (base 16) IgniteNet - 1, Creation 3rd Rd. - Science-based Industrial Park - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 28-79-94 (hex) Realplay Digital Technology(Shenzhen) Co.,Ltd - 287994 (base 16) Realplay Digital Technology(Shenzhen) Co.,Ltd - 7/F,Building E,SDG Information Port ,Kefeng Rd.,Hi-tech - Shenzhen Guangdong 518057 - CHINA - - 28-80-23 (hex) Hewlett Packard - 288023 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 28-84-FA (hex) SHARP Corporation - 2884FA (base 16) SHARP Corporation - 22-22,Nagaike-Cho - Abeno-Ku - Osaka-City Osaka-Prefecture 545-8522 - JAPAN - - 28-85-2D (hex) Touch Networks - 28852D (base 16) Touch Networks - 2515 152nd Ave NE - Redmond Washington 98052 - UNITED STATES - - 28-89-15 (hex) CashGuard Sverige AB - 288915 (base 16) CashGuard Sverige AB - Finlandsgatan 16 - Kista 16474 - SWEDEN - - 28-8A-1C (hex) Juniper networks - 288A1C (base 16) Juniper networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 28-91-D0 (hex) Stage Tec Entwicklungsgesellschaft für professionelle Audiotechnik mbH - 2891D0 (base 16) Stage Tec Entwicklungsgesellschaft für professionelle Audiotechnik mbH - Tabbertstraße 10 - Berlin 12459 - GERMANY - - 28-92-4A (hex) Hewlett Packard - 28924A (base 16) Hewlett Packard - 11445 Compaq Center Drive W - Houston Texas 77070 - UNITED STATES - - 28-93-FE (hex) CISCO SYSTEMS, INC. - 2893FE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 28-94-0F (hex) CISCO SYSTEMS, INC. - 28940F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 28-94-AF (hex) Samhwa Telecom - 2894AF (base 16) Samhwa Telecom - 293-7, Doksan-dong - Kumchun-gu - Seoul 153-813 - KOREA, REPUBLIC OF - - 28-98-7B (hex) Samsung Electronics Co.,Ltd - 28987B (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 28-9A-4B (hex) SteelSeries ApS - 289A4B (base 16) SteelSeries ApS - 656 West Randolph, Suite 2E - Chicago IL 60661 - UNITED STATES - - 28-9A-FA (hex) TCT Mobile Limited - 289AFA (base 16) TCT Mobile Limited - No.86, Hechang 7th West Road , ZhongKai Hi-tech Develop distriect - Huizhou Guangdong 516006 - CHINA - - 28-9E-DF (hex) Danfoss Turbocor Compressors, Inc - 289EDF (base 16) Danfoss Turbocor Compressors, Inc - 1769 E. Paul Dirac Ave. - Tallahassee Florida 32310 - UNITED STATES - - 28-A1-86 (hex) enblink - 28A186 (base 16) enblink - Room 212 Building 105-1 SNU - Gwanak-ro 1, Gwanak-gu - SEOUL 151-742 - KOREA, REPUBLIC OF - - 28-A1-92 (hex) GERP Solution - 28A192 (base 16) GERP Solution - Rua Costa Aguiar, 1710 - São Paulo SP 04204002 - BRAZIL - - 28-A1-EB (hex) ETEK TECHNOLOGY (SHENZHEN) CO.,LTD - 28A1EB (base 16) ETEK TECHNOLOGY (SHENZHEN) CO.,LTD - A505-506ã€A509 Room,A5 Floor, Academy Of International Technology Innovation, Keji Nan 10th Road, Hi-Tech Industrial Park, Shenzhen, P.R.C. - 4/F, Building A5, Xinjianxing Technology Industrial Park, Fengxin Road, Guangming New District, Shenzhen, P.R.C. - SHENZHEN GUANGDONG 518057 - CHINA - - 28-A2-41 (hex) exlar corp - 28A241 (base 16) exlar corp - 18400 west 77th street - chanhassen mn 55317 - UNITED STATES - - 28-A5-74 (hex) Miller Electric Mfg. Co. - 28A574 (base 16) Miller Electric Mfg. Co. - N676 Communication Drive - Appleton WI 54914 - UNITED STATES - - 28-A5-EE (hex) Shenzhen SDGI CATV Co., Ltd - 28A5EE (base 16) Shenzhen SDGI CATV Co., Ltd - 2/F, NO, 3, QIONGYU ROAD, - Nanshan - shenzhen Guangdong province 518057 - CHINA - - 28-AF-0A (hex) Sirius XM Radio Inc - 28AF0A (base 16) Sirius XM Radio Inc - 1221 Avenue of the Americas - 36th Floor - New York NY 10020 - UNITED STATES - - 28-B0-CC (hex) Xenya d.o.o. - 28B0CC (base 16) Xenya d.o.o. - Celovska cesta 172 - Ljubljana 1000 - SLOVENIA - - 28-B2-BD (hex) Intel Corporate - 28B2BD (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 28-B3-AB (hex) Genmark Automation - 28B3AB (base 16) Genmark Automation - 1201 Cadillac Ct - Milpitas CA 95035 - UNITED STATES - - 28-BA-18 (hex) NextNav, LLC - 28BA18 (base 16) NextNav, LLC - 484 Oakmead Parkway - Sunnyvale CA 94085 - UNITED STATES - - 28-BA-B5 (hex) Samsung Electronics Co.,Ltd - 28BAB5 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 28-BB-59 (hex) RNET Technologies, Inc. - 28BB59 (base 16) RNET Technologies, Inc. - 240. W. Elmwood Dr. - Suite 2010 - Dayton OHIO 45459-4248 - UNITED STATES - - 28-BE-9B (hex) Technicolor USA Inc. - 28BE9B (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 28-C0-DA (hex) Juniper Networks - 28C0DA (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 28-C2-DD (hex) AzureWave Technologies, Inc. - 28C2DD (base 16) AzureWave Technologies, Inc. - 8F, No. 94, Baozhong Rd. - Xindian Dist. - New Taipei City Taiwan 231 - TAIWAN, PROVINCE OF CHINA - - 28-C6-71 (hex) Yota Devices OY - 28C671 (base 16) Yota Devices OY - Elektronikkatie 13 - Oulu 90590 - FINLAND - - 28-C6-8E (hex) NETGEAR INC., - 28C68E (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 28-C7-18 (hex) Altierre - 28C718 (base 16) Altierre - 1980 Concourse Drive - San Jose United States 95131 - UNITED STATES - - 28-C7-CE (hex) Cisco - 28C7CE (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 28-C8-25 (hex) DellKing Industrial Co., Ltd - 28C825 (base 16) DellKing Industrial Co., Ltd - 2F,Building D,Zhongxing Science Park, No 3,Ganli 2nd Road,Gankeng Community - Buji,Longgang District - Shenzhen GuangDong 518112 - CHINA - - 28-C9-14 (hex) Taimag Corporation - 28C914 (base 16) Taimag Corporation - NO. 1, West 2nd St. N.E.P.Z - Kaohsiung 811 - TAIWAN, PROVINCE OF CHINA - - 28-CB-EB (hex) One - 28CBEB (base 16) One - Mechelsesteenweg 326 - Edegem Antwerpen 2650 - BELGIUM - - 28-CC-01 (hex) Samsung Electronics Co.,Ltd - 28CC01 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 28-CC-FF (hex) Corporacion Empresarial Altra SL - 28CCFF (base 16) Corporacion Empresarial Altra SL - Marie Curie 21 - Malaga 29590 - SPAIN - - 28-CD-1C (hex) Espotel Oy - 28CD1C (base 16) Espotel Oy - Kappelitie 6 - Espoo Espoo FI-02200 - FINLAND - - 28-CD-4C (hex) Individual Computers GmbH - 28CD4C (base 16) Individual Computers GmbH - Im Zemmer 6 - Woffelsbach NRW 52152 - GERMANY - - 28-CD-9C (hex) Shenzhen Dynamax Software Development Co.,Ltd. - 28CD9C (base 16) Shenzhen Dynamax Software Development Co.,Ltd. - Room 425-426,Block A,No.30,Hangkong Road - Xixiang Town,BaoAn District - Shenzhen Guangdong 518000 - CHINA - - 28-CF-DA (hex) Apple - 28CFDA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-CF-E9 (hex) Apple - 28CFE9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-D1-AF (hex) Nokia Corporation - 28D1AF (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 28-D2-44 (hex) LCFC(HeFei) Electronics Technology Co., Ltd. - 28D244 (base 16) LCFC(HeFei) Electronics Technology Co., Ltd. - 6 Cui Wei Road - Heifei Economic and Technological Development Zone - Hefei Anhui 230000 - CHINA - - 28-D5-76 (hex) Premier Wireless, Inc. - 28D576 (base 16) Premier Wireless, Inc. - 4222 E. La Palma Ave. - Anaheim CA 92807 - UNITED STATES - - 28-D9-3E (hex) Telecor Inc. - 28D93E (base 16) Telecor Inc. - 1114 Westport Crescent - Mississauga Ontario L5T1G1 - CANADA - - 28-D9-8A (hex) Hangzhou Konke Technology Co.,Ltd. - 28D98A (base 16) Hangzhou Konke Technology Co.,Ltd. - Hangzhou cuibai road 7, ROOM 422 - Hangzhou Zhejiang 310012 - CHINA - - 28-D9-97 (hex) Yuduan Mobile Co., Ltd. - 28D997 (base 16) Yuduan Mobile Co., Ltd. - Room 401 No 84 Lane 887 Zuchongzhi Rd. - Shanghai 201203 - CHINA - - 28-DB-81 (hex) Shanghai Guao Electronic Technology Co., Ltd - 28DB81 (base 16) Shanghai Guao Electronic Technology Co., Ltd - No.6, Alley 1225 TongPu Road, - PuTuo District - Shanghai 200333 - CHINA - - 28-DE-F6 (hex) bioMerieux Inc. - 28DEF6 (base 16) bioMerieux Inc. - 595 Anglum Road - Hazelwood MO 63042 - UNITED STATES - - 28-E0-2C (hex) Apple - 28E02C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-E1-4C (hex) Apple, Inc. - 28E14C (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-E2-97 (hex) Shanghai InfoTM Microelectronics Co.,Ltd. - 28E297 (base 16) Shanghai InfoTM Microelectronics Co.,Ltd. - building 11,NO.115,lane 572,BiBo Road, - PuDong New District - ShangHai 201203 - CHINA - - 28-E3-1F (hex) Xiaomi inc. - 28E31F (base 16) Xiaomi inc. - Office Building,The Rainbow City of China Resources, NO.68,Qinghe Middle Street,Haidian District,Beijing,China,100085 - Beijing Beijing 100085 - CHINA - - 28-E3-47 (hex) Liteon Technology Corporation - 28E347 (base 16) Liteon Technology Corporation - 4F,90, Chien1 Road, ChungHo, - New Taipei City. - Taipei Taiwan 23585 - TAIWAN, PROVINCE OF CHINA - - 28-E4-76 (hex) Pi-Coral - 28E476 (base 16) Pi-Coral - 2130 Gold Street, Ste. 200 - suite 200 - San Jose CA - California 95002 - UNITED STATES - - 28-E6-08 (hex) Tokheim - 28E608 (base 16) Tokheim - Industrieweg 5 - Bladel NBr 5531 AD - NETHERLANDS - - 28-E6-E9 (hex) SIS Sat Internet Services GmbH - 28E6E9 (base 16) SIS Sat Internet Services GmbH - Justus-von-Liebig Str. 26 - Neustadt Niedersachsen 31535 - GERMANY - - 28-E7-94 (hex) Microtime Computer Inc. - 28E794 (base 16) Microtime Computer Inc. - 4F, No. 222, Sec. 4, Cheng-Teh Rd., - Taipei 11167 - TAIWAN, PROVINCE OF CHINA - - 28-E7-CF (hex) Apple - 28E7CF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 28-ED-58 (hex) JAG Jakob AG - 28ED58 (base 16) JAG Jakob AG - Industriestrasse 20 - BRUEGG BE 2555 - SWITZERLAND - - 28-EE-2C (hex) Frontline Test Equipment - 28EE2C (base 16) Frontline Test Equipment - PO Box 7507 - Charlottesville Virginia 22906-7507 - UNITED STATES - - 28-EF-01 (hex) PRIVATE - 28EF01 (base 16) - - 28-F3-58 (hex) 2C - Trifonov & Co - 28F358 (base 16) 2C - Trifonov & Co - 133, Tsarigradsko Shose Blvd, BIZ IZOT, - Build. 3, Floor 3 - Sofia 1784 - BULGARIA - - 28-F5-32 (hex) ADD-Engineering BV - 28F532 (base 16) ADD-Engineering BV - P.O. BOX 5893 - ROTTERDAM ZH 3008 AW - NETHERLANDS - - 28-F6-06 (hex) Syes srl - 28F606 (base 16) Syes srl - Via Zanella 21 - Lissone (MB) Monza Brianza 20851 - ITALY - - 28-FB-D3 (hex) Ragentek Technology Group - 28FBD3 (base 16) Ragentek Technology Group - D10/D11,No.3188, Xiupu Road, PuDong District, Shanghai - No.3938.Hu Qing Ping Road,Qingpu District,Shanghai,PRC - Shanghai 201703 - CHINA - - 28-FC-51 (hex) The Electric Controller and Manufacturing Co., LLC - 28FC51 (base 16) The Electric Controller and Manufacturing Co., LLC - PO Box 468 - 2759 Old Belleville Rd - Saint Matthews SC 29135 - UNITED STATES - - 28-FC-F6 (hex) Shenzhen Xin KingBrand enterprises Co.,Ltd - 28FCF6 (base 16) Shenzhen Xin KingBrand enterprises Co.,Ltd - Kingbrand Industrial Zone,Nanpu Road,Shang liao ling pi keng,Shajing Town - Baoan District, - Shenzhen Guangdong 518000 - CHINA - - 28-FD-80 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 28FD80 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 2C-00-2C (hex) UNOWHY - 2C002C (base 16) UNOWHY - 11, rue Tronchet - Paris 75008 - FRANCE - - 2C-00-33 (hex) EControls, LLC - 2C0033 (base 16) EControls, LLC - 5757 Farinon Dr - San Antonio TX 78249 - UNITED STATES - - 2C-00-F7 (hex) XOS - 2C00F7 (base 16) XOS - 15 Tech Valley Drive - Suite 1 - East Greenbush NY 12061 - UNITED STATES - - 2C-01-0B (hex) NASCENT Technology, LLC - RemKon - 2C010B (base 16) NASCENT Technology, LLC - RemKon - 2744 Yorkmont Road - Charlotte NC 28208 - UNITED STATES - - 2C-06-23 (hex) Win Leader Inc. - 2C0623 (base 16) Win Leader Inc. - Level 3 ,Alexander House, - 35 Cybercity - Ebene - MAURITIUS - - 2C-07-3C (hex) DEVLINE LIMITED - 2C073C (base 16) DEVLINE LIMITED - FLAT/RM A9,9/F SILVERCORP INT TOWER - 707-713 NATHAN RD MONGKOK - HONGKONG 999077 - CHINA - - 2C-10-C1 (hex) Nintendo Co., Ltd. - 2C10C1 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 2C-18-AE (hex) Trend Electronics Co., Ltd. - 2C18AE (base 16) Trend Electronics Co., Ltd. - 4F-3, No 17, Lane 77, Sec. 2 - Zhongshan N. Road, - Taipei 10446 - TAIWAN, PROVINCE OF CHINA - - 2C-19-84 (hex) IDN Telecom, Inc. - 2C1984 (base 16) IDN Telecom, Inc. - 2669 Great Arbor Way - Union City CA 94587 - UNITED STATES - - 2C-1A-31 (hex) Electronics Company Limited - 2C1A31 (base 16) Electronics Company Limited - Units 12,15&16,8/F,Metro Centre 2 - No.21 Lam Hing Street, - Kowloon Bay HongKong 852 - CHINA - - 2C-1E-EA (hex) AERODEV - 2C1EEA (base 16) AERODEV - No.59,1985 Lane,Chunshen Road, - Shanghai 200237 - CHINA - - 2C-1F-23 (hex) Apple - 2C1F23 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 2C-21-72 (hex) Juniper Networks - 2C2172 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 2C-24-5F (hex) Babolat VS - 2C245F (base 16) Babolat VS - 93 rue Andre Bollier - Lyon 69007 - FRANCE - - 2C-26-5F (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 2C265F (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 2C-26-C5 (hex) zte corporation - 2C26C5 (base 16) zte corporation - 12/F.,zte R&D building Road,kejinan Road - shenzhen guangdong 518057 - CHINA - - 2C-27-D7 (hex) Hewlett-Packard Company - 2C27D7 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - 2C-28-2D (hex) BBK COMMUNICATIAO TECHNOLOGY CO.,LTD. - 2C282D (base 16) BBK COMMUNICATIAO TECHNOLOGY CO.,LTD. - 255#,BBKRoad,Wusha,Chang'an - Dongguan Guangdong 523860 - CHINA - - 2C-29-97 (hex) Microsoft Corporation - 2C2997 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 2C-2D-48 (hex) bct electronic GesmbH - 2C2D48 (base 16) bct electronic GesmbH - Saalachstrasse 88 - Salzburg 5020 - AUSTRIA - - 2C-30-68 (hex) Pantech Co.,Ltd - 2C3068 (base 16) Pantech Co.,Ltd - 110-1 Ongjeong-Ri, Tongjin-Eup - Gimpo-Si Gyounggi-Do 415-865 - KOREA, REPUBLIC OF - - 2C-33-7A (hex) Hon Hai Precision Ind. Co.,Ltd. - 2C337A (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - Xiyong Town,Shapingba District - Chongqing 401332 - CHINA - - 2C-34-27 (hex) ERCO & GENER - 2C3427 (base 16) ERCO & GENER - ZI de SAINT LAMBERT DES LEVEES - BP 30163 - SAUMUR 49412 - FRANCE - - 2C-35-57 (hex) ELLIY Power CO..Ltd - 2C3557 (base 16) ELLIY Power CO..Ltd - 1-6-4, Osaki - OSAKI NEW CITY 4th Building 19F - Shinagawa-ku TOKYO 141-0032 - JAPAN - - 2C-36-A0 (hex) Capisco Limited - 2C36A0 (base 16) Capisco Limited - PO Box 938 - Whangaparaoa - Auckland 0943 - NEW ZEALAND - - 2C-36-F8 (hex) CISCO SYSTEMS, INC. - 2C36F8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 2C-37-31 (hex) ShenZhen Yifang Digital Technology Co.,LTD - 2C3731 (base 16) ShenZhen Yifang Digital Technology Co.,LTD - Building # 22 and #23, Zone 5, Bai Wang Xin Industrial Park, Song Bai Road - Nanshan District - ShenZhen GUANGDONG 518108 - CHINA - - 2C-37-96 (hex) CYBO CO.,LTD. - 2C3796 (base 16) CYBO CO.,LTD. - 218 MOO 3 LAEM CHA BANG - INDUSTRIAL ESTATE, T.TUNGSUKLA - SRIRACHA CHONBURI 20230 - THAILAND - - 2C-39-96 (hex) SAGEMCOM - 2C3996 (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON - 92848 - FRANCE - - 2C-39-C1 (hex) Ciena Corporation - 2C39C1 (base 16) Ciena Corporation - 7035 Ridge Road - Hanover MD 21076 - UNITED STATES - - 2C-3A-28 (hex) Fagor Electrónica - 2C3A28 (base 16) Fagor Electrónica - B. San Andres, s/n - Mondragón Guipuzcoa 20500 - SPAIN - - 2C-3B-FD (hex) Netstor Technology Co., Ltd. - 2C3BFD (base 16) Netstor Technology Co., Ltd. - 6F, No. 1, Alley 16, Lane 235, Baoqiao Rd., Xindian District - New Taipei City 23145 - TAIWAN, PROVINCE OF CHINA - - 2C-3E-CF (hex) Cisco - 2C3ECF (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 2C-3F-38 (hex) CISCO SYSTEMS, INC. - 2C3F38 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 2C-3F-3E (hex) Alge-Timing GmbH - 2C3F3E (base 16) Alge-Timing GmbH - Rotkreuzstrasse 39 - Lustenau 6890 - AUSTRIA - - 2C-41-38 (hex) Hewlett-Packard Company - 2C4138 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - 2C-44-01 (hex) Samsung Electronics Co.,Ltd - 2C4401 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 2C-44-1B (hex) Spectrum Medical Limited - 2C441B (base 16) Spectrum Medical Limited - Harrier 4, Meteor Business Park - Cheltenham Road East - Gloucester GL2 9QL - UNITED KINGDOM - - 2C-44-FD (hex) Hewlett Packard - 2C44FD (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 2C-50-89 (hex) Shenzhen Kaixuan Visual Technology Co.,Limited - 2C5089 (base 16) Shenzhen Kaixuan Visual Technology Co.,Limited - No.19th Xifu Road, Hongxing Community - Songgang, Baoan - Shenzhen Guangdong 518000 - CHINA - - 2C-53-4A (hex) Shenzhen Winyao Electronic Limited - 2C534A (base 16) Shenzhen Winyao Electronic Limited - 7B Block A Fuqiao Building Fuhua Road - Futian District - Shen Zhen Guangdong 518000 - CHINA - - 2C-54-2D (hex) CISCO SYSTEMS, INC. - 2C542D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 2C-54-CF (hex) LG Electronics - 2C54CF (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul Korea, Republic of 153-801 - KOREA, REPUBLIC OF - - 2C-55-3C (hex) Gainspeed, Inc. - 2C553C (base 16) Gainspeed, Inc. - 295 Santa Ana Court - Sunnyvale CA 94085 - UNITED STATES - - 2C-59-E5 (hex) Hewlett Packard - 2C59E5 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 2C-5A-05 (hex) Nokia Corporation - 2C5A05 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - 2C-5A-A3 (hex) PROMATE ELECTRONIC CO.LTD - 2C5AA3 (base 16) PROMATE ELECTRONIC CO.LTD - 4F 32,SEC.1 HUAN SHAN RD.,NEI HU, - TAIPEI 114 - TAIWAN, PROVINCE OF CHINA - - 2C-5B-E1 (hex) Centripetal Networks, Inc - 2C5BE1 (base 16) Centripetal Networks, Inc - 11720 Sunrise Valley Drive, Suite 100 - Reston Virginia 20191 - UNITED STATES - - 2C-5D-93 (hex) Ruckus Wireless - 2C5D93 (base 16) Ruckus Wireless - 350 W. Java Drive - Sunnyvale California 94089 - UNITED STATES - - 2C-5F-F3 (hex) Pertronic Industries - 2C5FF3 (base 16) Pertronic Industries - 17 Eastern Hutt Road - Wingate 5019 - NEW ZEALAND - - 2C-60-0C (hex) QUANTA COMPUTER INC. - 2C600C (base 16) QUANTA COMPUTER INC. - No.211, Wen Hwa 2nd Rd - Kuei Shan Hsiang,Tao Yuan Shien - Taoyuan Taiwan 33377 - TAIWAN, PROVINCE OF CHINA - - 2C-62-5A (hex) Finest Security Systems Co., Ltd - 2C625A (base 16) Finest Security Systems Co., Ltd - 12F, No.103, Sec3, Nan King E. RD - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - 2C-62-89 (hex) Regenersis (Glenrothes) Ltd - 2C6289 (base 16) Regenersis (Glenrothes) Ltd - 1 James Watt Avenue - Westwood Park - Glenrothes Fife KY7 4UA - UNITED KINGDOM - - 2C-67-FB (hex) ShenZhen Zhengjili Electronics Co., LTD - 2C67FB (base 16) ShenZhen Zhengjili Electronics Co., LTD - The Longhua Town Shenzhen City Streets huaning three house Science Park Road Chiayi Source fifth floor - Shenzhen Guangdong 518000 - CHINA - - 2C-69-BA (hex) RF Controls, LLC - 2C69BA (base 16) RF Controls, LLC - 2518 Lemay Ferry Rd, Suite 350 - Saint Louis Missouri 63125 - UNITED STATES - - 2C-6A-6F (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 2C6A6F (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 2C-6B-F5 (hex) Juniper networks - 2C6BF5 (base 16) Juniper networks - 1194 N. Mathilda ave - Sunnyvale CA 94089 - UNITED STATES - - 2C-71-55 (hex) HiveMotion - 2C7155 (base 16) HiveMotion - 1806, STX-V Tower - 371-37 Gasan-dong, Geumcheon-gu - Seoul 153-803 - KOREA, REPUBLIC OF - - 2C-72-C3 (hex) Soundmatters - 2C72C3 (base 16) Soundmatters - 8060 Double R Blvd Suite 100 - Reno NV 89511 - UNITED STATES - - 2C-75-0F (hex) Shanghai Dongzhou-Lawton Communication Technology Co. Ltd. - 2C750F (base 16) Shanghai Dongzhou-Lawton Communication Technology Co. Ltd. - NO.188,FengyeRoad,BaoshanDistrict - shanghai 200949 - CHINA - - 2C-76-8A (hex) Hewlett-Packard Company - 2C768A (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 2C-7B-5A (hex) Milper Ltd - 2C7B5A (base 16) Milper Ltd - 32 Shaham St. - Petach Tikva 49250 - ISRAEL - - 2C-7B-84 (hex) OOO Petr Telegin - 2C7B84 (base 16) OOO Petr Telegin - Gagarin avenue, 37, build P1 - Nizhny Novgorod 603009 - RUSSIAN FEDERATION - - 2C-7E-CF (hex) Onzo Ltd - 2C7ECF (base 16) Onzo Ltd - 6 Great Newport Street - London WC2H 7JB - UNITED KINGDOM - - 2C-80-65 (hex) HARTING Inc. of North America - 2C8065 (base 16) HARTING Inc. of North America - 1370 Bowes Road - Elgin Illinois 60123 - UNITED STATES - - 2C-81-58 (hex) Hon Hai Precision Ind. Co.,Ltd - 2C8158 (base 16) Hon Hai Precision Ind. Co.,Ltd - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 2C-8A-72 (hex) HTC Corporation - 2C8A72 (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - 2C-8B-F2 (hex) Hitachi Metals America Ltd - 2C8BF2 (base 16) Hitachi Metals America Ltd - 1920 Zanker Road - San Jose CA 95112 - UNITED STATES - - 2C-91-27 (hex) Eintechno Corporation - 2C9127 (base 16) Eintechno Corporation - 3359-1, kako, Inami-cho - kako-gun hyogo 675-1105 - JAPAN - - 2C-92-2C (hex) Kishu Giken Kogyou Company Ltd,. - 2C922C (base 16) Kishu Giken Kogyou Company Ltd,. - 466 Nunohiki - Wakayama city Wakayama prefecture 6410015 - JAPAN - - 2C-94-64 (hex) Cincoze Co., Ltd. - 2C9464 (base 16) Cincoze Co., Ltd. - 7F., No. 4 Aly. 1 Ln. 235, Baociao Rd., - Sindian Dist. - New Taipei City 23145 - TAIWAN, PROVINCE OF CHINA - - 2C-95-7F (hex) zte corporation - 2C957F (base 16) zte corporation - 12/F.,zte R&D building Road - shenzhen guangdong 518057 - CHINA - - 2C-97-17 (hex) I.C.Y. B.V. - 2C9717 (base 16) I.C.Y. B.V. - Houtsaachmole 35 - Lemmer Friesland 8531 WC - NETHERLANDS - - 2C-9A-A4 (hex) NGI SpA - 2C9AA4 (base 16) NGI SpA - via Gran San Bernardo 12 - Busto Arsizio VA 21052 - ITALY - - 2C-9E-5F (hex) ARRIS Group, Inc. - 2C9E5F (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 2C-9E-FC (hex) CANON INC. - 2C9EFC (base 16) CANON INC. - 3-30-2 - Shimomaruko - Ohta-Ku Tokyo 146-8501 - JAPAN - - 2C-A1-57 (hex) acromate, Inc. - 2CA157 (base 16) acromate, Inc. - #1101, JnK Digital Tower, 111 - Digitalro-26-gil, Guro-gu - Seoul 152-848 - KOREA, REPUBLIC OF - - 2C-A2-B4 (hex) Fortify Technologies, LLC - 2CA2B4 (base 16) Fortify Technologies, LLC - 6200 Shingle Creek Pkwy, Suite 400 - Minneapolis Minnesota 55430 - UNITED STATES - - 2C-A3-0E (hex) POWER DRAGON DEVELOPMENT LIMITED - 2CA30E (base 16) POWER DRAGON DEVELOPMENT LIMITED - Room D, 10/F Tower A, Billion Centre, 1 Wang Kwong Road, Kowloon Bay - HONG KONG HONG KONG 999077 - CHINA - - 2C-A7-80 (hex) True Technologies Inc. - 2CA780 (base 16) True Technologies Inc. - R476, AngelCity 1st, - 161, Guemgok, Bundang - Seongnam, Kyungki 463-862 - KOREA, REPUBLIC OF - - 2C-A8-35 (hex) RIM - 2CA835 (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 2C-AB-25 (hex) Shenzhen Gongjin Electronics Co.,Ltd - 2CAB25 (base 16) Shenzhen Gongjin Electronics Co.,Ltd - B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 Nanshan Medical Instrument Industry Park - ,1019# Nanhai Road,Nanshan District, - Shenzhen Guangdong 518067 - CHINA - - 2C-AB-A4 (hex) Cisco SPVTG - 2CABA4 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 2C-AD-13 (hex) SHENZHEN ZHILU TECHNOLOGY CO.,LTD - 2CAD13 (base 16) SHENZHEN ZHILU TECHNOLOGY CO.,LTD - B2-402 Kexin Science Park, Keyuan Road, Hi-tech Park, Nanshan District, Shenzhen - shenzhen Guangdong 518052 - CHINA - - 2C-B0-5D (hex) NETGEAR - 2CB05D (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 2C-B0-DF (hex) Soliton Technologies Pvt Ltd - 2CB0DF (base 16) Soliton Technologies Pvt Ltd - # 683, 15th Cross - J P Nagar 2nd Phase - Bangalore Karnataka 560 078 - INDIA - - 2C-B4-3A (hex) Apple - 2CB43A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 2C-B6-93 (hex) Radware - 2CB693 (base 16) Radware - 22 Raoul Wallenberg St. - Tel-Aviv 69710 - ISRAEL - - 2C-B6-9D (hex) RED Digital Cinema - 2CB69D (base 16) RED Digital Cinema - 20291 Valencia Circle - Lake Forest California 92630 - UNITED STATES - - 2C-BE-08 (hex) Apple - 2CBE08 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 2C-BE-97 (hex) Ingenieurbuero Bickele und Buehler GmbH - 2CBE97 (base 16) Ingenieurbuero Bickele und Buehler GmbH - St.Poeltener Str. 70 - Stuttgart BW 70469 - GERMANY - - 2C-C2-60 (hex) Ravello Systems - 2CC260 (base 16) Ravello Systems - Zarhin 13 - Building C - Raanana 4366241 - ISRAEL - - 2C-C5-48 (hex) IAdea Corporation - 2CC548 (base 16) IAdea Corporation - 3F, No.33, Lane 77, Xing-ai Road - Taipei Taiwan 114 - TAIWAN, PROVINCE OF CHINA - - 2C-C5-D3 (hex) Ruckus Wireless - 2CC5D3 (base 16) Ruckus Wireless - 350 West Java Drive - Sunnyvale CA 94089 - UNITED STATES - - 2C-CC-15 (hex) Nokia Corporation - 2CCC15 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - 2C-CD-27 (hex) Precor Inc - 2CCD27 (base 16) Precor Inc - 20031 142nd Avenue NE - Woodinville WA 98072 - UNITED STATES - - 2C-CD-43 (hex) Summit Technology Group - 2CCD43 (base 16) Summit Technology Group - 145 Belmont Drive - Somerset NJ 08873 - UNITED STATES - - 2C-CD-69 (hex) Aqavi.com - 2CCD69 (base 16) Aqavi.com - 3 Riverway - Suite 700 - Houston TX 77056 - UNITED STATES - - 2C-D0-5A (hex) Liteon Technology Corporation - 2CD05A (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo, - New Taipei City - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 2C-D1-41 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 2CD141 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 2C-D1-DA (hex) Sanjole, Inc. - 2CD1DA (base 16) Sanjole, Inc. - 2800 Woodlawn Drive, #271 - Honolulu Hawaii 96822 - UNITED STATES - - 2C-D2-E7 (hex) Nokia Corporation - 2CD2E7 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - 2C-D4-44 (hex) Fujitsu Limited - 2CD444 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - 2C-DD-0C (hex) Discovergy GmbH - 2CDD0C (base 16) Discovergy GmbH - Pascalstraße 15 - Aachen NRW 52076 - GERMANY - - 2C-E2-A8 (hex) DeviceDesign - 2CE2A8 (base 16) DeviceDesign - Yeongtong-dong, Yeongtong-gu - #D-303, DigitalEmpire Bldg. - Suwon-si Gyeonggi-do 443-813 - KOREA, REPUBLIC OF - - 2C-E4-12 (hex) SAGEMCOM SAS - 2CE412 (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON CEDEX IDF 92848 - FRANCE - - 2C-E6-CC (hex) Ruckus Wireless - 2CE6CC (base 16) Ruckus Wireless - 350 W. Java Drive - Sunnyvale CA 94089 - UNITED STATES - - 2C-E8-71 (hex) Alert Metalguard ApS - 2CE871 (base 16) Alert Metalguard ApS - Vester Voldgade 104, st, th - Copenhagen V 1552 - DENMARK - - 2C-ED-EB (hex) Alpheus Digital Company Limited - 2CEDEB (base 16) Alpheus Digital Company Limited - Room 2, 23/F Tak King Industrial building - 27 Lee Chung Street, Chai Wan - Hong Kong 852 - HONG KONG - - 2C-EE-26 (hex) Petroleum Geo-Services - 2CEE26 (base 16) Petroleum Geo-Services - 12555 Harris Branch Pkwy - Suite 108 - Austin TX 78653 - UNITED STATES - - 2C-F0-EE (hex) Apple - 2CF0EE (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 2C-F2-03 (hex) EMKO ELEKTRONIK SAN VE TIC AS - 2CF203 (base 16) EMKO ELEKTRONIK SAN VE TIC AS - DOSAB, KARANFIL SOK, NO:6 - BURSA 16369 - TURKEY - - 2C-F4-C5 (hex) Avaya, Inc - 2CF4C5 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 2C-F7-F1 (hex) Seeed Technology Inc. - 2CF7F1 (base 16) Seeed Technology Inc. - 5th Floor, 8th Building, Shiling industrial Park - XiLi Town,Nangang District - ShenZhen GuangDong 518055 - CHINA - - 2C-FA-A2 (hex) Alcatel-Lucent - 2CFAA2 (base 16) Alcatel-Lucent - 26801 West Agoura Rd - Calabasas CA 91301 - UNITED STATES - - 30-05-5C (hex) Brother industries, LTD. - 30055C (base 16) Brother industries, LTD. - 1-1-1, Kawagishi, Mizuho-ku, - Nagoya Aichi 467-8562 - JAPAN - - 30-0B-9C (hex) Delta Mobile Systems, Inc. - 300B9C (base 16) Delta Mobile Systems, Inc. - 700 Remington Road - 2nd Floor - Schaumburg Illinois 60173 - UNITED STATES - - 30-0D-2A (hex) Zhejiang Wellcom Technology Co.,Ltd. - 300D2A (base 16) Zhejiang Wellcom Technology Co.,Ltd. - Liuhe Road,Binjiang District , Hangzhou - No. 368 , 4th Floor, North Haichuang base B3 District - Zhejiang 310012 - CHINA - - 30-0E-D5 (hex) Hon Hai Precision Ind.Co.Ltd - 300ED5 (base 16) Hon Hai Precision Ind.Co.Ltd - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 30-0E-E3 (hex) Aquantia Corporation - 300EE3 (base 16) Aquantia Corporation - 700 Tasman Drive - Milpitas CA 95035 - UNITED STATES - - 30-10-B3 (hex) Liteon Technology Corporation - 3010B3 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road, ChungHo - TaiPei Hsien - TaiPei TaiWan 23585 - TAIWAN, PROVINCE OF CHINA - - 30-10-E4 (hex) Apple, Inc. - 3010E4 (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 30-14-2D (hex) Piciorgros GmbH - 30142D (base 16) Piciorgros GmbH - Claudiastrasse 5 - Cologne NRW 51149 - GERMANY - - 30-14-4A (hex) Wistron Neweb Corp. - 30144A (base 16) Wistron Neweb Corp. - 20 Park Avenue II,Hsinchu Science Park - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 30-15-18 (hex) Ubiquitous Communication Co. ltd. - 301518 (base 16) Ubiquitous Communication Co. ltd. - JEI Platz RM No.410-1 - 459-11, Gasan-Dong, Geumcheon-Gu - Seoul 153-792 - KOREA, REPUBLIC OF - - 30-16-8D (hex) ProLon - 30168D (base 16) ProLon - 1989 Michelin - Laval Quebec H7L5B7 - CANADA - - 30-17-C8 (hex) Sony Ericsson Mobile Communications AB - 3017C8 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 30-18-CF (hex) DEOS control systems GmbH - 3018CF (base 16) DEOS control systems GmbH - Birkenallee 113 - Rheine NRW 48432 - GERMANY - - 30-19-66 (hex) Samsung Electronics Co.,Ltd - 301966 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 30-1A-28 (hex) Mako Networks Ltd - 301A28 (base 16) Mako Networks Ltd - 1/62 Paul Matthews Rd - Albany - Auckland 0632 - NEW ZEALAND - - 30-21-5B (hex) Shenzhen Ostar Display Electronic Co.,Ltd - 30215B (base 16) Shenzhen Ostar Display Electronic Co.,Ltd - Room218, CASTD Incubator Building, High-tech South Street No.1, - South District of High-tech industrial Area - Shenzhen Guangdong 518057 - CHINA - - 30-2D-E8 (hex) JDA, LLC (JDA Systems) - 302DE8 (base 16) JDA, LLC (JDA Systems) - 4080 Pike Lane - Concord CA 94520 - UNITED STATES - - 30-32-94 (hex) W-IE-NE-R Plein & Baus GmbH - 303294 (base 16) W-IE-NE-R Plein & Baus GmbH - Muellersbaum 20 - Burscheid NRW 51399 - GERMANY - - 30-32-D4 (hex) Hanilstm Co., Ltd. - 3032D4 (base 16) Hanilstm Co., Ltd. - 138-6, Sangdaewon-dong Jungwon-gu - 709, Joongang Induspia 5th - Seongnam Kyonggi-do 462-120 - KOREA, REPUBLIC OF - - 30-33-35 (hex) Boosty - 303335 (base 16) Boosty - 40 Princes Street - Ipswich Suffolk IP11RJ - UNITED KINGDOM - - 30-37-A6 (hex) CISCO SYSTEMS, INC. - 3037A6 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 30-38-55 (hex) Nokia Corporation - 303855 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - 30-39-26 (hex) Sony Ericsson Mobile Communications AB - 303926 (base 16) Sony Ericsson Mobile Communications AB - Sölvegatan 51 - - - Lund - 22188 - SWEDEN - - 30-39-55 (hex) Shenzhen Jinhengjia Electronic Co., Ltd. - 303955 (base 16) Shenzhen Jinhengjia Electronic Co., Ltd. - 4-6 Floors, Factory Building, Jijia Industrial Park, - Xialilang Area, Nanwan Street, Longgang Area. - Shenzhen Guangdong 518112 - CHINA - - 30-39-F2 (hex) ADB Broadband Italia - 3039F2 (base 16) ADB Broadband Italia - VIALE SARCA 222 - MILANO 20126 - ITALY - - 30-3A-64 (hex) Intel Corporate - 303A64 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 30-3D-08 (hex) GLINTT TES S.A. - 303D08 (base 16) GLINTT TES S.A. - Beloura Office Park, Ed.10 - Quinta da Beloura - Sintra 2710-693 - PORTUGAL - - 30-3E-AD (hex) Sonavox Canada Inc - 303EAD (base 16) Sonavox Canada Inc - 81 Zenway Blvd #25 - Woodbridge Ontario L4S0S5 - CANADA - - 30-41-74 (hex) ALTEC LANSING LLC - 304174 (base 16) ALTEC LANSING LLC - 535 ROUTES 6 & 209 - MILFORD PA 18337 - UNITED STATES - - 30-42-25 (hex) BURG-WÄCHTER KG - 304225 (base 16) BURG-WÄCHTER KG - Altenhofer Weg 15 - Wetter NRW 58300 - GERMANY - - 30-44-49 (hex) PLATH GmbH - 304449 (base 16) PLATH GmbH - Gotenstrasse 18 - Hamburg 20097 - GERMANY - - 30-46-9A (hex) NETGEAR - 30469A (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 30-49-3B (hex) Nanjing Z-Com Wireless Co.,Ltd - 30493B (base 16) Nanjing Z-Com Wireless Co.,Ltd - Z-Com Building,NO.30 Jiangsu Software Park,NO.699-22 Xuanwu Avenue, - Nanjing Jiangsu 210042 - CHINA - - 30-4C-7E (hex) Panasonic Electric Works Automation Controls Techno Co.,Ltd. - 304C7E (base 16) Panasonic Electric Works Automation Controls Techno Co.,Ltd. - 2-9-18 Chidori - Oota-ku Tokyo 146-8540 - JAPAN - - 30-4E-C3 (hex) Tianjin Techua Technology Co., Ltd. - 304EC3 (base 16) Tianjin Techua Technology Co., Ltd. - 12-1-1401 Tianlinyuan Fulicheng Gulouxi Road,Nankai District - Tianjin 300101 - CHINA - - 30-51-F8 (hex) BYK-Gardner GmbH - 3051F8 (base 16) BYK-Gardner GmbH - Lausitzer Strasse 8 - Geretsried Bavarian 82538 - GERMANY - - 30-52-5A (hex) NST Co., LTD - 30525A (base 16) NST Co., LTD - RM301,Daeryung Techno Town 2, 569-21 - Gasan-dong, Geumcheon-gu - Seoul 153-771 - KOREA, REPUBLIC OF - - 30-55-ED (hex) Trex Network LLC - 3055ED (base 16) Trex Network LLC - Room 505, Tower B Nongke Building, - No.11 Shuguang Huayuan Middle Street,Haidian District - Beijing 100097 - CHINA - - 30-57-AC (hex) IRLAB LTD. - 3057AC (base 16) IRLAB LTD. - 3rd Floor, 2A Biulding, Huihao Industrial Park - Heshuikou,Gongming - Shenzhen Guang Dong 518106 - CHINA - - 30-59-5B (hex) streamnow AG - 30595B (base 16) streamnow AG - Brandstrasse 33 - Schlieren Zürich 8952 - SWITZERLAND - - 30-59-B7 (hex) Microsoft - 3059B7 (base 16) Microsoft - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 30-5D-38 (hex) Beissbarth - 305D38 (base 16) Beissbarth - Hanauer Str. 101 - Muenchen 80993 - GERMANY - - 30-60-23 (hex) ARRIS Group, Inc. - 306023 (base 16) ARRIS Group, Inc. - 3871 Lakrfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 30-61-12 (hex) PAV GmbH - 306112 (base 16) PAV GmbH - Georg-Kaindl-Straße 11 - Otterfing 83624 - GERMANY - - 30-61-18 (hex) Paradom Inc. - 306118 (base 16) Paradom Inc. - 8F, N0. 178, Sec-2, Gongdaowu Rd. - Hsinchu City 300 - TAIWAN, PROVINCE OF CHINA - - 30-65-EC (hex) Wistron (ChongQing) - 3065EC (base 16) Wistron (ChongQing) - No.F08/F09,D zone,Konggang Functional Zone - Cuntan Bonded Port,Yubei District, - ChongQing 401120 - CHINA - - 30-68-8C (hex) Reach Technology Inc. - 30688C (base 16) Reach Technology Inc. - 4575 Cushing Parkway - Fremont California 94538 - UNITED STATES - - 30-69-4B (hex) RIM - 30694B (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 30-6C-BE (hex) Skymotion Technology (HK) Limited - 306CBE (base 16) Skymotion Technology (HK) Limited - Unit 2603, 26/F, Metropole Square, - #2 On Yiu Street, Shatin, N.T., - 852 - HONG KONG - - 30-6E-5C (hex) Validus Technologies - 306E5C (base 16) Validus Technologies - 420 North Main Street - East Peoria Illinois 61611 - UNITED STATES - - 30-71-B2 (hex) Hangzhou Prevail Optoelectronic Equipment Co.,LTD. - 3071B2 (base 16) Hangzhou Prevail Optoelectronic Equipment Co.,LTD. - Industrial Development Area, Guali Town, - Xiaoshan - Hangzhou City Zhe Jiang 311241 - CHINA - - 30-73-50 (hex) Inpeco SA - 307350 (base 16) Inpeco SA - Via San Gottardo 10 - Lugano Ticino 6900 - SWITZERLAND - - 30-75-12 (hex) Sony Mobile Communications AB - 307512 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 30-76-6F (hex) LG Electronics - 30766F (base 16) LG Electronics - 60-39, Kasan-dong, Kumchon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 30-77-CB (hex) Maike Industry(Shenzhen)CO.,LTD - 3077CB (base 16) Maike Industry(Shenzhen)CO.,LTD - Maike Industrial Garden, Sanwei village, - Xixiang Town, Baoan District. - Shenzhen Guangdong 518100 - CHINA - - 30-78-6B (hex) TIANJIN Golden Pentagon Electronics Co., Ltd. - 30786B (base 16) TIANJIN Golden Pentagon Electronics Co., Ltd. - No. 196 Rixin Road, Binhai Science Park, - Binhai High-tech Zone, - Tianjin 300457 - CHINA - - 30-78-C2 (hex) Innowireless, Co. Ltd. - 3078C2 (base 16) Innowireless, Co. Ltd. - 1-301, Pangyo Seven Venture Valley 2-danji - 633, Sampyeong-dong,Bundang-gu - Seongnam-Si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - 30-7C-30 (hex) RIM - 307C30 (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 30-7E-CB (hex) SFR - 307ECB (base 16) SFR - 40/42 Quai du point du jour - Boulongne Billancourt Hauts de Seine 92659 - FRANCE - - 30-85-A9 (hex) Asustek Computer Inc - 3085A9 (base 16) Asustek Computer Inc - 15,Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 30-87-30 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 308730 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 30-89-99 (hex) Guangdong East Power Co., - 308999 (base 16) Guangdong East Power Co., - No.6 Northern Industry Road,Songshan lake SCI&TECH Industry Park - DongGuan GuangDong 523808 - CHINA - - 30-89-D3 (hex) HONGKONG UCLOUDLINK NETWORK TECHNOLOGY LIMITED - 3089D3 (base 16) HONGKONG UCLOUDLINK NETWORK TECHNOLOGY LIMITED - FLAT A-8 9/F DELYA INDUSTRIAL CENTRE 7 SHEK PAI TAU ROAD - TUEN MUN NT - Hong Kong - CHINA - - 30-8C-FB (hex) Dropcam - 308CFB (base 16) Dropcam - 160 Spear Street - Suite 1700 - San Francisco CA 94105 - UNITED STATES - - 30-90-AB (hex) Apple - 3090AB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 30-91-8F (hex) Technicolor - 30918F (base 16) Technicolor - Prins Boudewijnlaan 47 - Edegem - Belgium Antwerp B-2650 - BELGIUM - - 30-92-F6 (hex) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD - 3092F6 (base 16) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD - Suite 604-605,Xing Yuan Technology Plaza - 418 Gui Ping Road - ShangHai 200233 - CHINA - - 30-9B-AD (hex) BBK Electronics Corp., Ltd., - 309BAD (base 16) BBK Electronics Corp., Ltd., - #255,BBK Road, - Wusha,Chang'An, DongGuan City,Guangdong, 523860 - CHINA - - 30-A8-DB (hex) Sony Mobile Communications AB - 30A8DB (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 30-AA-BD (hex) Shanghai Reallytek Information Technology Co.,Ltd - 30AABD (base 16) Shanghai Reallytek Information Technology Co.,Ltd - Building No.1-906, No.3000 Long Dong Avenue - Pu Dong New District - Shanghai 201203 - CHINA - - 30-AE-7B (hex) Deqing Dusun Electron CO., LTD - 30AE7B (base 16) Deqing Dusun Electron CO., LTD - No. 640 FengQing Street, Deqing - Huzhou Zhejiang 313200 - CHINA - - 30-AE-F6 (hex) Radio Mobile Access - 30AEF6 (base 16) Radio Mobile Access - 1 Elm Sq - Andover MA 01870 - UNITED STATES - - 30-B2-16 (hex) Hytec Geraetebau GmbH - 30B216 (base 16) Hytec Geraetebau GmbH - Cochemer Straße 12 - 14 - Mannheim 68309 - GERMANY - - 30-B3-A2 (hex) Shenzhen Heguang Measurement & Control Technology Co.,Ltd - 30B3A2 (base 16) Shenzhen Heguang Measurement & Control Technology Co.,Ltd - 3/F, Tower A, Xiangnian Plaza, 6060 Qiaoxiang Road, - Shenzhen Guangdong 518053 - CHINA - - 30-B5-C2 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 30B5C2 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4) - Central Science and Technology Park, - Shennan Road,Nanshan, Shenzhen Guangdong 518057 - CHINA - - 30-B5-F1 (hex) Aitexin Technology Co., Ltd - 30B5F1 (base 16) Aitexin Technology Co., Ltd - 1210 PDAY research center streer 2 - north of Zhongguan vallege Haidian district - Peiking 100190 - CHINA - - 30-C7-50 (hex) MIC Technology Group - 30C750 (base 16) MIC Technology Group - No. 6 Gaoxin 3 road - Xi'an Shaanxi 710075 - CHINA - - 30-C7-AE (hex) Samsung Electronics Co.,Ltd - 30C7AE (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 30-C8-2A (hex) Wi-Next s.r.l. - 30C82A (base 16) Wi-Next s.r.l. - Via Carlo Ferrero 10 - Cascine Vica Rivoli Torino 10098 - ITALY - - 30-CD-A7 (hex) Samsung Electronics ITS, Printer division - 30CDA7 (base 16) Samsung Electronics ITS, Printer division - 416 MAETAN 3-DONG - YEONGTONG-GU - SUWON- SI GYEONGGI 443-742 - KOREA, REPUBLIC OF - - 30-D1-7E (hex) HUAWEI TECHNOLOGIES CO.,LTD - 30D17E (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - ShenZhen GuangDong 518129 - CHINA - - 30-D3-57 (hex) Logosol, Inc. - 30D357 (base 16) Logosol, Inc. - 5041 ROBERT J. MATHEWS PARKWAY - SUITE 100 - EL DORADO HILLS California 95762 - UNITED STATES - - 30-D4-6A (hex) Autosales Incorporated - 30D46A (base 16) Autosales Incorporated - 1200 Souteat Avenue - Tallmadge Ohio 44278 - UNITED STATES - - 30-D5-87 (hex) Samsung Electronics Co.,Ltd - 30D587 (base 16) Samsung Electronics Co.,Ltd - #416, Maetan 3-dong - Yeongtong-gu - Suwon-si Gyeonggi-do 443-742 - KOREA, REPUBLIC OF - - 30-D6-C9 (hex) Samsung Electronics Co.,Ltd - 30D6C9 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 30-DE-86 (hex) Cedac Software S.r.l. - 30DE86 (base 16) Cedac Software S.r.l. - Via Toscana, 3 - Castiglione dei Pepoli Bologna 40035 - ITALY - - 30-E4-8E (hex) Vodafone UK - 30E48E (base 16) Vodafone UK - Vodafone House - The Connection - Newbury Berkshire RG142FN - UNITED KINGDOM - - 30-E4-DB (hex) CISCO SYSTEMS, INC. - 30E4DB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 30-EB-25 (hex) INTEK DIGITAL - 30EB25 (base 16) INTEK DIGITAL - 801, 8th Fl., Anyang K-center building, 1591-9 - Gwanyang-dong, Dongan-gu - Anyang 431-060 - KOREA, REPUBLIC OF - - 30-EF-D1 (hex) Alstom Strongwish (Shenzhen) Co., Ltd. - 30EFD1 (base 16) Alstom Strongwish (Shenzhen) Co., Ltd. - 5F,Building No.6, Keji Middle 2 Road High-Tech Industrial Park, - Shen Zhen Guangdong 518057 - CHINA - - 30-F3-1D (hex) zte corporation - 30F31D (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 30-F3-35 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 30F335 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - 30-F3-3A (hex) +plugg srl - 30F33A (base 16) +plugg srl - via giovanni ventura, 5 - Milano MI 20134 - ITALY - - 30-F4-2F (hex) ESP - 30F42F (base 16) ESP - 126-1 Pyeongchon-dong, Dongan-gu - Anyang-si Gyeonggi-do 431-755 - KOREA, REPUBLIC OF - - 30-F7-0D (hex) Cisco Systems - 30F70D (base 16) Cisco Systems - 80 West Tasman Dr. - San Jose CA 95134 - UNITED STATES - - 30-F7-C5 (hex) Apple - 30F7C5 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 30-F7-D7 (hex) Thread Technology Co., Ltd - 30F7D7 (base 16) Thread Technology Co., Ltd - 4F, A Block, CYG, No.2,Mid GaoXin - Rd,NanShan District - Shenzhen GuangDong 518055 - CHINA - - 30-F9-ED (hex) Sony Corporation - 30F9ED (base 16) Sony Corporation - Gotenyama Tec. - 5-1-12 Kitashinagawa Shinagawa-ku - Tokyo 141-0001 - JAPAN - - 30-FA-B7 (hex) Tunai Creative - 30FAB7 (base 16) Tunai Creative - 12F, No.221, Sec.4, Zongxiao E. Rd, Taipei 106, Taiwan - TAIPEI TAIPEI 10690 - TAIWAN, PROVINCE OF CHINA - - 30-FD-11 (hex) MACROTECH (USA) INC. - 30FD11 (base 16) MACROTECH (USA) INC. - 1799 BAYSHORE HIGHWAY - SUITE 286 - BURLINGAME CA 94010 - UNITED STATES - - 34-00-A3 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 3400A3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 34-02-86 (hex) Intel Corporate - 340286 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 34-02-9B (hex) CloudBerry Technologies Private Limited - 34029B (base 16) CloudBerry Technologies Private Limited - 209, S.C.O. - 11, SECTOR 7 - MADHYA MARG - CHANDIGARH Punjab 160019 - INDIA - - 34-07-FB (hex) Ericsson AB - 3407FB (base 16) Ericsson AB - Torshamnsgatan 36 - Stockholm SE-164 80 - SWEDEN - - 34-08-04 (hex) D-Link Corporation - 340804 (base 16) D-Link Corporation - No.289, Sinhu 3rd Rd., Neihu District, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 34-0A-22 (hex) TOP-ACCESS ELECTRONICS CO LTD - 340A22 (base 16) TOP-ACCESS ELECTRONICS CO LTD - No. 2 Building - MinXing Industrial Park - MingZhi Street BaoAn District,ShenzheN 518131 - CHINA - - 34-0A-FF (hex) Qingdao Hisense Communications Co.,Ltd - 340AFF (base 16) Qingdao Hisense Communications Co.,Ltd - 218 Qian wan gang Road Economic & Technological cevelopment Zone - Qingdao Shandong 266510 - CHINA - - 34-0B-40 (hex) MIOS ELETTRONICA SRL - 340B40 (base 16) MIOS ELETTRONICA SRL - VIA ARCHIMEDE, 10 - SAN MARTINO B.A. (VR) VERONA 37036 - ITALY - - 34-12-98 (hex) Apple - 341298 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 34-13-A8 (hex) Mediplan Limited - 3413A8 (base 16) Mediplan Limited - 245 Sheffield Road - Woodhouse Mill - Sheffield South Yorkshire S13 9ZD - UNITED KINGDOM - - 34-13-E8 (hex) Intel Corporate - 3413E8 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 34-15-9E (hex) Apple - 34159E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 34-17-EB (hex) Dell Inc - 3417EB (base 16) Dell Inc - one dell way - MS:RR5-45 - Round rock Texas 78682 - UNITED STATES - - 34-1A-4C (hex) SHENZHEN WEIBU ELECTRONICS CO.,LTD. - 341A4C (base 16) SHENZHEN WEIBU ELECTRONICS CO.,LTD. - 3/F, Block 132,Jindi Industrial Zone - Futian Dist - Shenzhen Guangdong 518048 - CHINA - - 34-1B-22 (hex) Grandbeing Technology Co., Ltd - 341B22 (base 16) Grandbeing Technology Co., Ltd - B-301,Science and Technology Building Phase II - 1057 Nanhai Rd, Nanshan District - Shenzhen Guangdong 518000 - CHINA - - 34-21-09 (hex) Jensen Scandinavia AS - 342109 (base 16) Jensen Scandinavia AS - Balder Allé 3 - Jessheim 2050 - NORWAY - - 34-23-87 (hex) Hon Hai Precision Ind. Co.,Ltd. - 342387 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 34-23-BA (hex) Samsung Electro Mechanics co.,LTD. - 3423BA (base 16) Samsung Electro Mechanics co.,LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - 34-25-5D (hex) Shenzhen Loadcom Technology Co.,Ltd - 34255D (base 16) Shenzhen Loadcom Technology Co.,Ltd - Yuehai Building A-13CD,Nanhai Road,Nanshan Area - Shenzhen Guangdong 518054 - CHINA - - 34-28-F0 (hex) ATN International Limited - 3428F0 (base 16) ATN International Limited - 4210, Office Tower, Convention Plaza - 1 Harbour Road, Wanchai, - Hong Kong 00000 - HONG KONG - - 34-29-EA (hex) MCD ELECTRONICS SP. Z O.O. - 3429EA (base 16) MCD ELECTRONICS SP. Z O.O. - Lelewela 26 - Zywiec Slaskie 34-300 - POLAND - - 34-2F-6E (hex) Anywire corporation - 342F6E (base 16) Anywire corporation - 1 Zusyo, Baba - Nagaokakyo Kyoto pref. 617-8550 - JAPAN - - 34-31-11 (hex) Samsung Electronics Co.,Ltd - 343111 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 34-31-C4 (hex) AVM GmbH - 3431C4 (base 16) AVM GmbH - Alt-Moabit 95 - Berlin Berlin 10559 - GERMANY - - 34-36-3B (hex) Apple - 34363B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 34-38-AF (hex) Inlab Software GmbH - 3438AF (base 16) Inlab Software GmbH - Josef-Wuerth-Str. 3 - Gruenwald Bavaria 82031 - GERMANY - - 34-3D-98 (hex) Fujian JinQianMao Electronic Technology Co.,Ltd. - 343D98 (base 16) Fujian JinQianMao Electronic Technology Co.,Ltd. - 58#,Jiangbin Road,Taijiang District - Fuzhou Fujian 350009 - CHINA - - 34-40-B5 (hex) IBM - 3440B5 (base 16) IBM - 3039 E Cornwallis Rd - Research Triangle Park NC 27709 - UNITED STATES - - 34-46-6F (hex) HiTEM Engineering - 34466F (base 16) HiTEM Engineering - 7420 Carroll Road - San Diego CA 92121 - UNITED STATES - - 34-4B-3D (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 344B3D (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 34-4B-50 (hex) ZTE Corporation - 344B50 (base 16) ZTE Corporation - 12/F,ZTE R&D Buliding,Kejinan Road,Shenzhen,P.R.China - Shenzhen Guangdong 518057 - CHINA - - 34-4C-A4 (hex) amazipoint technology Ltd. - 344CA4 (base 16) amazipoint technology Ltd. - 1F,No. 14, Aly. 32, Ln. 133, Zhongyang Rd., - Xindian Dist., - New Taipei City, 231 - TAIWAN, PROVINCE OF CHINA - - 34-4D-EA (hex) zte corporation - 344DEA (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 34-4D-F7 (hex) LG Electronics - 344DF7 (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul Seoul 153-801 - KOREA, REPUBLIC OF - - 34-4F-3F (hex) IO-Power Technology Co., Ltd. - 344F3F (base 16) IO-Power Technology Co., Ltd. - 1F., No.100, - Jinzhu Rd., North Dist., - Hsinchu City 30055 - TAIWAN, PROVINCE OF CHINA - - 34-4F-5C (hex) R&M AG - 344F5C (base 16) R&M AG - Binzstrasse 32 - Wetzikon Zurich 8620 - SWITZERLAND - - 34-4F-69 (hex) EKINOPS SAS - 344F69 (base 16) EKINOPS SAS - 3, Rue Blaise Pascal - LANNION FRANCE 22300 - FRANCE - - 34-51-AA (hex) JID GLOBAL - 3451AA (base 16) JID GLOBAL - 211, Biz Plus Suwon 2F Chungho Bldg, 17 363Road, Susung-ro - , Jangan-gu, Suwon-si, Gyeonggi-do, Korea - SUWON Gyeonggi-do 440-846 - KOREA, REPUBLIC OF - - 34-51-C9 (hex) Apple - 3451C9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 34-5B-11 (hex) EVI HEAT AB - 345B11 (base 16) EVI HEAT AB - Box 55 - Kungsaengen 196 22 - SWEDEN - - 34-5C-40 (hex) Cargt Holdings LLC - 345C40 (base 16) Cargt Holdings LLC - 8820 Hillside Dr - Lenexa KANSAS (KS) 66227 - UNITED STATES - - 34-5D-10 (hex) Wytek - 345D10 (base 16) Wytek - 10 rue jean jaures - Poitiers 86000 - FRANCE - - 34-61-78 (hex) The Boeing Company - 346178 (base 16) The Boeing Company - 325 James S. McDonnell Blvd - MC S306-2115 - Hazelwood MO 63042-2513 - UNITED STATES - - 34-62-88 (hex) Cisco - 346288 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 34-64-A9 (hex) Hewlett Packard - 3464A9 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 34-68-4A (hex) Teraworks Co., Ltd. - 34684A (base 16) Teraworks Co., Ltd. - Room No. 201 , 515-30 , Mok-Dong - Yangcheon-Gu - Seoul 158-808 - KOREA, REPUBLIC OF - - 34-68-95 (hex) Hon Hai Precision Ind. Co.,Ltd. - 346895 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District, - Chongqing 401332 - CHINA - - 34-6B-D3 (hex) Huawei Technologies Co., Ltd - 346BD3 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - 34-6C-0F (hex) Pramod Telecom Pvt. Ltd - 346C0F (base 16) Pramod Telecom Pvt. Ltd - Plot No. 6-B, Malviya Nagar, - Aishbagh - Lucknow Uttar Pradesh 226004 - INDIA - - 34-6E-8A (hex) Ecosense - 346E8A (base 16) Ecosense - 1414 Kolon science vallet-II., #811 - Guro3-dong - Seoul Guro-gu 152-878 - KOREA, REPUBLIC OF - - 34-6F-90 (hex) Cisco - 346F90 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 34-6F-92 (hex) White Rodgers Division - 346F92 (base 16) White Rodgers Division - 8100 West Florissant - P.O. Box 36921 - St. Louis MO 63136 - UNITED STATES - - 34-75-C7 (hex) Avaya, Inc - 3475C7 (base 16) Avaya, Inc - 211 Mt. Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 34-76-C5 (hex) I-O DATA DEVICE, INC. - 3476C5 (base 16) I-O DATA DEVICE, INC. - 3-10, SAKURADA-MACHI - KANAZAWA ISHIKAWA 920-8512 - JAPAN - - 34-78-77 (hex) O-NET Communications(Shenzhen) Limited - 347877 (base 16) O-NET Communications(Shenzhen) Limited - #10-1 South,Maqueling Industrial Park,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 34-7A-60 (hex) Pace plc - 347A60 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - 34-7E-39 (hex) Nokia Danmark A/S - 347E39 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 34-80-B3 (hex) XIAOMI INC - 3480B3 (base 16) XIAOMI INC - The Rainbow city of China Resource,NO.68,Qinghe Middle street,Haidian District,Beijing,Chian. - Beijing Beijing 100085 - CHINA - - 34-81-37 (hex) UNICARD SA - 348137 (base 16) UNICARD SA - UL.WADOWICKA 12 - KRAKOW woj. malopolskie 30-415 - POLAND - - 34-81-C4 (hex) AVM GmbH - 3481C4 (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 34-82-DE (hex) Kayo Technology, Inc. - 3482DE (base 16) Kayo Technology, Inc. - 404 Holtzman Rd - Madison WI 53713 - UNITED STATES - - 34-83-02 (hex) iFORCOM Co., Ltd - 348302 (base 16) iFORCOM Co., Ltd - 1326 - Midoriku Nakano - Sagamihara Kanagawa 252-0157 - JAPAN - - 34-84-46 (hex) Ericsson AB - 348446 (base 16) Ericsson AB - Torshamnsgatan 36 - Stockholm Stockholm SE-164 80 - SWEDEN - - 34-86-2A (hex) Heinz Lackmann GmbH & Co KG - 34862A (base 16) Heinz Lackmann GmbH & Co KG - Harkortstraße 15 - Münster NRW 48163 - GERMANY - - 34-87-3D (hex) Quectel Wireless Solution Co.,Ltd. - 34873D (base 16) Quectel Wireless Solution Co.,Ltd. - RM501,Building 13,No.99 TianZhou Road - Xuhui District - Shanghai 200233 - CHINA - - 34-88-5D (hex) Logitech Far East - 34885D (base 16) Logitech Far East - #2 Creation Rd. 4, - Science-Based Ind. Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 34-8A-AE (hex) SAGEMCOM SAS - 348AAE (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON CEDEX 92848 - FRANCE - - 34-95-DB (hex) Logitec Corporation - 3495DB (base 16) Logitec Corporation - 8268 Rokudohara, Misuzu - Ina Nagano 3960111 - JAPAN - - 34-97-FB (hex) ADVANCED RF TECHNOLOGIES INC - 3497FB (base 16) ADVANCED RF TECHNOLOGIES INC - 3116 W Vanowen St - Burbank California 91505 - UNITED STATES - - 34-99-6F (hex) VPI Engineering - 34996F (base 16) VPI Engineering - 11814 S. Election Rd., Suite 200 - Draper UT 84020 - UNITED STATES - - 34-99-D7 (hex) Universal Flow Monitors, Inc. - 3499D7 (base 16) Universal Flow Monitors, Inc. - 1755 E. Nine Mile Rd. - Hazel Park MI 48030 - UNITED STATES - - 34-9A-0D (hex) ZBD Displays Ltd - 349A0D (base 16) ZBD Displays Ltd - Orchard Lea - Winkfield Lane - Windsor Berkshire SL4 4RU - UNITED KINGDOM - - 34-9B-5B (hex) Maquet GmbH - 349B5B (base 16) Maquet GmbH - Kehler Strasse 31 - Rastatt Baden-Württemberg 76437 - GERMANY - - 34-9D-90 (hex) Heinzmann GmbH & CO. KG - 349D90 (base 16) Heinzmann GmbH & CO. KG - Am Haselbach 1 - Schoenau Baden Wuertemberg 79677 - GERMANY - - 34-9E-34 (hex) Evervictory Electronic Co.Ltd - 349E34 (base 16) Evervictory Electronic Co.Ltd - Chu-Chi management district Humen Town, DongGuan GuangDong Province, China - DongGuan GuangDong 523000 - CHINA - - 34-A1-83 (hex) AWare, Inc - 34A183 (base 16) AWare, Inc - 614 Massachusetts Ave. - Cambridge MA 02139 - UNITED STATES - - 34-A3-95 (hex) Apple - 34A395 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 34-A3-BF (hex) Terewave. Inc. - 34A3BF (base 16) Terewave. Inc. - Room 217, Ssangyong Research Center - 100-beongji, Shinseong-dong - Yuseong-gu Daejeon-city 305804 - KOREA, REPUBLIC OF - - 34-A5-5D (hex) TECHNOSOFT INTERNATIONAL SRL - 34A55D (base 16) TECHNOSOFT INTERNATIONAL SRL - RO6640904 - Str. Paduretu 50 - Bucuresti - Sector 6 061992 - ROMANIA - - 34-A5-E1 (hex) Sensorist ApS - 34A5E1 (base 16) Sensorist ApS - Nyhavn 16 - Copenhagen K Sjaelland 1051 - DENMARK - - 34-A6-8C (hex) Shine Profit Development Limited - 34A68C (base 16) Shine Profit Development Limited - Unit 1401B Telecom Tower - Wharf T&T Square - Kwun Tong Kowloon 000001 - HONG KONG - - 34-A7-09 (hex) Trevil srl - 34A709 (base 16) Trevil srl - Via Copernico 1 - Pozzo d'Adda MI 20060 - ITALY - - 34-A7-BA (hex) Fischer International Systems Corporation - 34A7BA (base 16) Fischer International Systems Corporation - 5801 Pelican Bay Boulevard #300 - Naples Florida 34108 - UNITED STATES - - 34-A8-43 (hex) KYOCERA Display Corporation - 34A843 (base 16) KYOCERA Display Corporation - 5-7-18 Higashinippori - Arakawa-ku Tokyo 116-0014 - JAPAN - - 34-A8-4E (hex) Cisco - 34A84E (base 16) Cisco - 170 West Tasman Drive - San Jose CA 95134 - UNITED STATES - - 34-AA-8B (hex) Samsung Electronics Co.,Ltd - 34AA8B (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 34-AA-99 (hex) Alcatel-Lucent - 34AA99 (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 34-AA-EE (hex) Mikrovisatos Servisas UAB - 34AAEE (base 16) Mikrovisatos Servisas UAB - Savanoriu pr. 125 - Kaunas LT44146 - LITHUANIA - - 34-AD-E4 (hex) Shanghai Chint Power Systems Co., Ltd. - 34ADE4 (base 16) Shanghai Chint Power Systems Co., Ltd. - 855 Wenhe Road, Block 4 - Songjiang District - 201614 - CHINA - - 34-AF-2C (hex) Nintendo Co., Ltd. - 34AF2C (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO KYOTO 601-8501 - JAPAN - - 34-B1-F7 (hex) Texas Instruments - 34B1F7 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 34-B5-71 (hex) PLDS - 34B571 (base 16) PLDS - Schanzenfeldstrasse 2 - Wetzlar Hessen 35578 - GERMANY - - 34-B7-FD (hex) Guangzhou Younghead Electronic Technology Co.,Ltd - 34B7FD (base 16) Guangzhou Younghead Electronic Technology Co.,Ltd - Room 206,Wenzhenxin Building,Block 3, No.2 Kefa RD,Hi-Tech Park - Nangang Dist. - Shenzhen Guangdong 518052 - CHINA - - 34-BA-51 (hex) Se-Kure Controls, Inc. - 34BA51 (base 16) Se-Kure Controls, Inc. - 3714 Runge Street - Franklin Park IL 60131 - UNITED STATES - - 34-BA-9A (hex) Asiatelco Technologies Co. - 34BA9A (base 16) Asiatelco Technologies Co. - 301,#8 Building,#289 Bisheng Road - Zhangjiang Hi-Tech Park,Pudong - Shanghai 201204 - CHINA - - 34-BB-1F (hex) Research In Motion - 34BB1F (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 34-BB-26 (hex) Motorola Mobility LLC - 34BB26 (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - 34-BC-A6 (hex) Beijing Ding Qing Technology, Ltd. - 34BCA6 (base 16) Beijing Ding Qing Technology, Ltd. - 218 Han Tai Hua Office Building, 13 Huan Yuan Lu, - Haidian District Beijing 100083 - CHINA - - 34-BD-C8 (hex) Cisco Systems - 34BDC8 (base 16) Cisco Systems - 80 West Tasman Dr. - San Jose CA 95134 - UNITED STATES - - 34-BD-F9 (hex) Shanghai WDK Industrial Co.,Ltd. - 34BDF9 (base 16) Shanghai WDK Industrial Co.,Ltd. - No.2100,Songzhen Road,Songjiang District - Shanghai 201606 - CHINA - - 34-BD-FA (hex) Cisco SPVTG - 34BDFA (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 34-BE-00 (hex) Samsung Electronics Co.,Ltd - 34BE00 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 34-BF-90 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 34BF90 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 34-C0-59 (hex) Apple - 34C059 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 34-C3-AC (hex) Samsung Electronics - 34C3AC (base 16) Samsung Electronics - 94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 34-C5-D0 (hex) Hagleitner Hygiene International GmbH - 34C5D0 (base 16) Hagleitner Hygiene International GmbH - Lunastrasse 5 - Zell am See Salzburg 5700 - AUSTRIA - - 34-C6-9A (hex) Enecsys Ltd - 34C69A (base 16) Enecsys Ltd - Harston Mill - Royston Road - Cambridge Cambridgeshire CB22 7GG - UNITED KINGDOM - - 34-C7-31 (hex) ALPS Co,. Ltd. - 34C731 (base 16) ALPS Co,. Ltd. - 6-3-36 Furukawanakazato, - Osaki Miyagi-pref 989-6181 - JAPAN - - 34-C8-03 (hex) Nokia Corporation - 34C803 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 34-C9-9D (hex) EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD. - 34C99D (base 16) EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD. - Room 603, 6/F., Wanchai Central Building, 89 Lockhart Road, Wanchai, - HONG KONG - - 34-CC-28 (hex) Nexpring Co. LTD., - 34CC28 (base 16) Nexpring Co. LTD., - 3rd Floor, Building C, PDC Tower - Sampyung-Dong, Bundang-Gu - Sungnam City Kyungki-do 463400 - KOREA, REPUBLIC OF - - 34-CD-6D (hex) CommSky Technologies - 34CD6D (base 16) CommSky Technologies - 4655 Old Ironsides Dr - #350 - Santa Clara CA 95054 - UNITED STATES - - 34-CD-BE (hex) Huawei Technologies Co., Ltd - 34CDBE (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - ,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - 34-CE-94 (hex) Parsec (Pty) Ltd - 34CE94 (base 16) Parsec (Pty) Ltd - Building 8-10 Manhattan Office Park - 16 Pieter Street, Highveld Technopark - Centurion Gauteng 0157 - SOUTH AFRICA - - 34-D0-9B (hex) MobilMAX Technology Inc. - 34D09B (base 16) MobilMAX Technology Inc. - 2F-5, No.28, Tai-Yuan St. - Chupei City, Hsinchu Country 302 - TAIWAN, PROVINCE OF CHINA - - 34-D2-C4 (hex) RENA GmbH Print Systeme - 34D2C4 (base 16) RENA GmbH Print Systeme - Hienlohestrasse 24 - Otterfing Bavaria 83624 - GERMANY - - 34-D7-B4 (hex) Tributary Systems, Inc. - 34D7B4 (base 16) Tributary Systems, Inc. - 3717 Commerce Place - Suite C - Bedford Texas 76021 - UNITED STATES - - 34-DB-FD (hex) Cisco - 34DBFD (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 34-DE-1A (hex) Intel Corporate - 34DE1A (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 34-DE-34 (hex) zte corporation - 34DE34 (base 16) zte corporation - 12/F.,zte R&D building Road - shenzhen guangdong 518057 - CHINA - - 34-DF-2A (hex) Fujikon Industrial Co.,Limited - 34DF2A (base 16) Fujikon Industrial Co.,Limited - 16/F., Tower 1, Grand Central Plaza,138 Shatin Rural - Committee Road,Shatin, N.T., - 523930 - HONG KONG - - 34-E0-CF (hex) zte corporation - 34E0CF (base 16) zte corporation - 12/F.,R&D building,kejinan Road, - shenzhen guangdong 518057 - CHINA - - 34-E0-D7 (hex) DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD - 34E0D7 (base 16) DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD - XINJI INDUSTRIAL ZONE, MACHONG TOWN - DONGGUAN GUANGDONG 523123 - CHINA - - 34-E2-FD (hex) Apple - 34E2FD (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 34-E4-2A (hex) Automatic Bar Controls Inc. - 34E42A (base 16) Automatic Bar Controls Inc. - 790 Eubanks Dr - Vacaville CA 95688 - UNITED STATES - - 34-E6-AD (hex) Intel Corporate - 34E6AD (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 34-E6-D7 (hex) Dell Inc. - 34E6D7 (base 16) Dell Inc. - One Dell way - Round Rock Texas 78682 - UNITED STATES - - 34-EF-44 (hex) 2Wire - 34EF44 (base 16) 2Wire - 1764 Automation Pkwy - San Jose CA 95131 - UNITED STATES - - 34-EF-8B (hex) NTT Communications Corporation - 34EF8B (base 16) NTT Communications Corporation - NTT Hibiya Bldg. 7F - 1-6,Uchisaiwai-cho 1-chome - Chiyoda-ku Tokyo 100-8019 - JAPAN - - 34-F0-CA (hex) Shenzhen Linghangyuan Digital Technology Co.,Ltd. - 34F0CA (base 16) Shenzhen Linghangyuan Digital Technology Co.,Ltd. - Building R, Linghangyuan Industrial Park, No. 163 Banxuegang Road, Longgang Distrial, Shenzhen, China - Shenzhen Guangdong 518129 - CHINA - - 34-F3-9B (hex) WizLAN Ltd. - 34F39B (base 16) WizLAN Ltd. - P.O.Box 7948 - Haifa 31078 - ISRAEL - - 34-F6-2D (hex) SHARP Corporation - 34F62D (base 16) SHARP Corporation - 22-22,Nagaike-Cho - Abeno-Ku - Osaka-City Osaka-Prefecture 545-8522 - JAPAN - - 34-F6-D2 (hex) Panasonic Taiwan Co.,Ltd. - 34F6D2 (base 16) Panasonic Taiwan Co.,Ltd. - 579,Yuan Shan Road - Chung-Ho District - New Taipei Taiwan 235 - TAIWAN, PROVINCE OF CHINA - - 34-F9-68 (hex) ATEK Products, LLC - 34F968 (base 16) ATEK Products, LLC - 210 NE 10th Avenue - Brainerd MN 56401 - UNITED STATES - - 34-FA-40 (hex) Guangzhou Robustel Technologies Co., Limited - 34FA40 (base 16) Guangzhou Robustel Technologies Co., Limited - B301, Tianchang Shangmaoyuan - No.393 Zhongshan Avenue, Tianhe Distri - Guangzhou Guangdong 510660 - CHINA - - 34-FC-6F (hex) ALCEA - 34FC6F (base 16) ALCEA - 3, rue Joly de Bammeville - ZAC de la Fontaine de Jouvence - Marcoussis 91460 - FRANCE - - 34-FC-EF (hex) LG Electronics - 34FCEF (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 38-01-97 (hex) Toshiba Samsung Storage Technolgoy Korea Corporation - 380197 (base 16) Toshiba Samsung Storage Technolgoy Korea Corporation - 14 Floor, Bldg. No. 102, Digital Empire2, 486, Sin-dong, Yeongtong-gu, Suwon-si, - Su-won Gyeonggi 443-734 - KOREA, REPUBLIC OF - - 38-06-B4 (hex) A.D.C. GmbH - 3806B4 (base 16) A.D.C. GmbH - Peter-Dornier-Str. 10 - Lindau 88131 - GERMANY - - 38-08-FD (hex) Silca Spa - 3808FD (base 16) Silca Spa - Via Podgora, 20 (Z.I.) - Vittorio Veneto TV 31029 - ITALY - - 38-09-A4 (hex) Firefly Integrations - 3809A4 (base 16) Firefly Integrations - 1013 Elroy Dr - Middlebury IN 46540 - UNITED STATES - - 38-0A-0A (hex) Sky-City Communication and Electronics Limited Company - 380A0A (base 16) Sky-City Communication and Electronics Limited Company - 1109, Building A, Kefa Industrial park, Huanguan south road, Guanlan, - Baoan, - Shenzhen Guangdong 518110 - CHINA - - 38-0A-94 (hex) Samsung Electronics Co.,Ltd - 380A94 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 38-0B-40 (hex) Samsung Electronics Co.,Ltd - 380B40 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 38-0D-D4 (hex) Primax Electronics LTD. - 380DD4 (base 16) Primax Electronics LTD. - 8F,No. 669, Ruey Kuang Road, Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 38-0E-7B (hex) V.P.S. Thai Co., Ltd - 380E7B (base 16) V.P.S. Thai Co., Ltd - 279-281 Mangkorn Rd., Pomprab District - Bangkok Bangkok 10100 - THAILAND - - 38-0F-4A (hex) Apple - 380F4A (base 16) Apple - 1 infinite loop - Cupertino CA 95014 - UNITED STATES - - 38-0F-E4 (hex) Dedicated Network Partners Oy - 380FE4 (base 16) Dedicated Network Partners Oy - Linnoitustie 6 - Espoo - 02600 - FINLAND - - 38-16-D1 (hex) Samsung Electronics Co.,Ltd - 3816D1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 38-17-66 (hex) PROMZAKAZ LTD. - 381766 (base 16) PROMZAKAZ LTD. - Noviy Arbat street, 21 - Moscow 119019 - RUSSIAN FEDERATION - - 38-19-2F (hex) Nokia Corporation - 38192F (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90450 - FINLAND - - 38-1C-1A (hex) Cisco - 381C1A (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 38-1C-4A (hex) SIMCom Wireless Solutions Co.,Ltd. - 381C4A (base 16) SIMCom Wireless Solutions Co.,Ltd. - Building A,SIM Technology Building,No.633,Jinzhong Road, - Changning District - Shanghai 200335 - CHINA - - 38-22-9D (hex) Pirelli Tyre S.p.A. - 38229D (base 16) Pirelli Tyre S.p.A. - VIALE SARCA 222 - MILANO 20126 - ITALY - - 38-22-D6 (hex) H3C Technologies Co., Limited - 3822D6 (base 16) H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang, 310053 - CHINA - - 38-26-2B (hex) UTran Technology - 38262B (base 16) UTran Technology - No.130, Guoji Rd., Tucheng Dist., - New Taipei City 23650 - TAIWAN, PROVINCE OF CHINA - - 38-26-CD (hex) ANDTEK - 3826CD (base 16) ANDTEK - Am Soeldnermoos 17 - Hallbergmoos Bavaria 85399 - GERMANY - - 38-28-EA (hex) Fujian Netcom Technology Co., LTD - 3828EA (base 16) Fujian Netcom Technology Co., LTD - Netcom Technology Building, B Zone:Tongpan Software Park, - Fuzhou Fujian 350003 - CHINA - - 38-2B-78 (hex) ECO PLUGS ENTERPRISE CO., LTD - 382B78 (base 16) ECO PLUGS ENTERPRISE CO., LTD - 10F,-6, No.117, Sec.2, Zhongbei Rd., Zhongli Dist., - Taoyuan Taiwan 32097 - TAIWAN, PROVINCE OF CHINA - - 38-2C-4A (hex) ASUSTek COMPUTER INC. - 382C4A (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 38-2D-D1 (hex) Samsung Electronics Co.,Ltd - 382DD1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 38-31-AC (hex) WEG - 3831AC (base 16) WEG - Av. Pref. Waldemar Grubba, 3000 - Jaraguá do Sul Santa Catarina 89256-900 - BRAZIL - - 38-3B-C8 (hex) 2wire - 383BC8 (base 16) 2wire - 1764 Automation Parkway - San Jose Ca 95131 - UNITED STATES - - 38-3F-10 (hex) DBL Technology Ltd. - 383F10 (base 16) DBL Technology Ltd. - Unit 42, 18/F., Block D, Wah Lok Industrial Center - 31 - 35 Shan Mei Street, Fotan, Shatin - HONG KONG - - 38-42-33 (hex) Wildeboer Bauteile GmbH - 384233 (base 16) Wildeboer Bauteile GmbH - Marker Weg 11 - Weener Niedersachsen 26826 - GERMANY - - 38-42-A6 (hex) Ingenieurbuero Stahlkopf - 3842A6 (base 16) Ingenieurbuero Stahlkopf - Senner Hellweg 115 - Bielefeld NRW 33659 - GERMANY - - 38-43-69 (hex) Patrol Products Consortium LLC - 384369 (base 16) Patrol Products Consortium LLC - 1128 Narragansett Blvd. - Cranston RI 02905 - UNITED STATES - - 38-45-8C (hex) MyCloud Technology corporation - 38458C (base 16) MyCloud Technology corporation - Room 705£¬Building F, Jiahua Building£¬ - #9, Shangdi 3rd Street£¬Haidian District - Beijing 100085 - CHINA - - 38-46-08 (hex) ZTE Corporation - 384608 (base 16) ZTE Corporation - 12/F,ZTE R&D Buliding,Kejinan Road, - Shenzhen Guangdong 518057 - CHINA - - 38-48-4C (hex) Apple - 38484C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 38-4B-76 (hex) AIRTAME ApS - 384B76 (base 16) AIRTAME ApS - Vestergade 20C - Copenhagen C Copenhagen 1456 - DENMARK - - 38-4F-F0 (hex) Azurewave Technologies, Inc. - 384FF0 (base 16) Azurewave Technologies, Inc. - 8F., No.120, Sec. 2, Kongdao 5 Rd - Hsinchu Science - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 38-52-1A (hex) Alcatel-Lucent 7705 - 38521A (base 16) Alcatel-Lucent 7705 - 600 March Rd. - Ottawa Onatrio K0A 1T0 - CANADA - - 38-58-0C (hex) Panaccess Systems GmbH - 38580C (base 16) Panaccess Systems GmbH - Gutenbergstr. 8 - Ismaning BY 85737 - GERMANY - - 38-59-F8 (hex) MindMade sp. z o.o. - 3859F8 (base 16) MindMade sp. z o.o. - Sniadeckich 10 - Warszawa Mazowieckie 00-656 - POLAND - - 38-59-F9 (hex) Hon Hai Precision Ind. Co.,Ltd. - 3859F9 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 38-5A-A8 (hex) Beijing Zhongdun Security Technology Development Co. - 385AA8 (base 16) Beijing Zhongdun Security Technology Development Co. - No.1 Capital Gymnasium South Road - Beijing 100048 - CHINA - - 38-5F-C3 (hex) Yu Jeong System, Co.Ltd - 385FC3 (base 16) Yu Jeong System, Co.Ltd - #503, Dong il B/D, 826, Guro-3dong, - Guro-Gu, - Seoul 152-879 - KOREA, REPUBLIC OF - - 38-60-77 (hex) PEGATRON CORPORATION - 386077 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 38-63-BB (hex) Hewlett Packard - 3863BB (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 38-63-F6 (hex) 3NOD MULTIMEDIA(SHENZHEN)CO.,LTD - 3863F6 (base 16) 3NOD MULTIMEDIA(SHENZHEN)CO.,LTD - F6,Building11,Shenzhen Software Park - No.2 Kejizhong Road,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 38-66-45 (hex) OOSIC Technology CO.,Ltd - 386645 (base 16) OOSIC Technology CO.,Ltd - 8F,No 1559, Zuchongzhi Road - Pudong District - Shanghai 201203 - CHINA - - 38-67-93 (hex) Asia Optical Co., Inc. - 386793 (base 16) Asia Optical Co., Inc. - No. 22-3 South 2nd Road, T.E.P.Z. - Tantz District - Taichung Taiwan 42754 - TAIWAN, PROVINCE OF CHINA - - 38-6B-BB (hex) ARRIS Group, Inc. - 386BBB (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 38-6C-9B (hex) Ivy Biomedical - 386C9B (base 16) Ivy Biomedical - 11 Business Park Drive - Branford Connecticut 06405 - UNITED STATES - - 38-6E-21 (hex) Wasion Group Ltd. - 386E21 (base 16) Wasion Group Ltd. - No.468 West Tongzipo Road High-Tech Industrial Development Zone - Changsha City Hunan Province, 410205 - CHINA - - 38-72-C0 (hex) COMTREND - 3872C0 (base 16) COMTREND - 3F-1,10 Lane 609, Chung Hsin Road, Section 5 - San Chung City, - Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 38-7B-47 (hex) AKELA, Inc. - 387B47 (base 16) AKELA, Inc. - 5551 Ekwill Street, Suite A - Santa Barbara California 93111 - UNITED STATES - - 38-83-45 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 388345 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, - Shenzhen, Guangdong Province 518057 - CHINA - - 38-89-DC (hex) Opticon Sensors Europe B.V. - 3889DC (base 16) Opticon Sensors Europe B.V. - Opaallaan 35 - Hoofddorp Noord Holland 2132 XV - NETHERLANDS - - 38-8A-B7 (hex) ITC Networks - 388AB7 (base 16) ITC Networks - 3F Daiwa Shibaura Bldg - 1-12-3 Shibaura Minato-ku - Tokyo 105-0023 - JAPAN - - 38-8E-E7 (hex) Fanhattan LLC - 388EE7 (base 16) Fanhattan LLC - 489 S El Camino Real - San Mateo CA 94402 - UNITED STATES - - 38-91-FB (hex) Xenox Holding BV - 3891FB (base 16) Xenox Holding BV - Lingedijk 80 - Tricht Gelderland 4196 HC - NETHERLANDS - - 38-94-96 (hex) Samsung Elec Co.,Ltd - 389496 (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 38-95-92 (hex) Beijing Tendyron Corporation - 389592 (base 16) Beijing Tendyron Corporation - 1810,Tower B,Jin-ma,Building,17 East Qing Hua Road - Haidian District - Beijing 100083 - CHINA - - 38-9F-83 (hex) OTN Systems N.V. - 389F83 (base 16) OTN Systems N.V. - Industrielaan 17b - Olen 2250 - BELGIUM - - 38-A5-3C (hex) Veenstra Instruments - 38A53C (base 16) Veenstra Instruments - Madame Curieweg 1 - Joure Friesland 8500 AC - NETHERLANDS - - 38-A5-B6 (hex) SHENZHEN MEGMEET ELECTRICAL CO.,LTD - 38A5B6 (base 16) SHENZHEN MEGMEET ELECTRICAL CO.,LTD - 5th Floor,Building B, Ziguang Information Harbor - ,Langshan Rd, North Area of Science & Techonolgy Park - Shenzhen Guangdong 518057 - CHINA - - 38-A8-51 (hex) Moog, Ing - 38A851 (base 16) Moog, Ing - 3650 Woodhead Drive - Northbrook IL 60062 - UNITED STATES - - 38-A8-6B (hex) Orga BV - 38A86B (base 16) Orga BV - Strickledeweg 13 - Schiedam 3125 AT - NETHERLANDS - - 38-A9-5F (hex) Actifio Inc - 38A95F (base 16) Actifio Inc - 225 Wyman Street - Suite 30 - Waltham MA 02451 - INDIA - - 38-AA-3C (hex) SAMSUNG ELECTRO-MECHANICS - 38AA3C (base 16) SAMSUNG ELECTRO-MECHANICS - 314, Maetan3-Dong, Yeongtong-Gu - Suwon Gyunggi-Do 443-743 - KOREA, REPUBLIC OF - - 38-B1-2D (hex) Sonotronic Nagel GmbH - 38B12D (base 16) Sonotronic Nagel GmbH - Becker-Goering-Str. 17-25 - Karlsbad 76307 - GERMANY - - 38-B1-DB (hex) Hon Hai Precision Ind. Co.,Ltd. - 38B1DB (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - ,Xiyong Town,Shapingba District - Chongqing Chongqing 401332 - CHINA - - 38-B5-BD (hex) E.G.O. Elektro-Ger - 38B5BD (base 16) E.G.O. Elektro-Ger - Einkauf - Rote-Tor-Strasse 14 - Oberderdingen 75038 - GERMANY - - 38-B7-4D (hex) Fijowave Limited - 38B74D (base 16) Fijowave Limited - Synergy Centre - ITT Dublin, Tallaght - Dublin 24 - IRELAND - - 38-BB-23 (hex) OzVision America LLC - 38BB23 (base 16) OzVision America LLC - 400 West Cummings Park - Woburn MA 01801 - UNITED STATES - - 38-BB-3C (hex) Avaya, Inc - 38BB3C (base 16) Avaya, Inc - 211 Mount Airy Rolad - Basking Ridge NJ 07920-2311 - UNITED STATES - - 38-BC-1A (hex) Meizu technology co.,ltd - 38BC1A (base 16) Meizu technology co.,ltd - Meizu Tech Bldg., - Technology&Innovation coast - Zhuhai Guangdong 519085 - CHINA - - 38-BF-2F (hex) Espec Corp. - 38BF2F (base 16) Espec Corp. - 5-2-5 Kanokodai Minamimachi - Kita-ku, - Kobe City Hyogo 561-1514 - JAPAN - - 38-BF-33 (hex) NEC CASIO Mobile Communications - 38BF33 (base 16) NEC CASIO Mobile Communications - 1753,Shimonumabe - Nakahara-ku - Kawasaki-shi Kanagawa 211-8666 - JAPAN - - 38-C0-96 (hex) ALPS ELECTRIC CO.,LTD. - 38C096 (base 16) ALPS ELECTRIC CO.,LTD. - 6-1 - NISHIDA - KAKUDA-CITY MIYAGI-PREF 981-1595 - JAPAN - - 38-C7-0A (hex) WiFiSong - 38C70A (base 16) WiFiSong - Rm. 605, Building 3, No. 75 Wenyi West Road - Hangzhou Zhengjiang 310012 - CHINA - - 38-C7-BA (hex) CS Services Co.,Ltd. - 38C7BA (base 16) CS Services Co.,Ltd. - Imon BLDG 95 Edomachi - Chuoh-ku - Kobe Hyogo 6500033 - JAPAN - - 38-C8-5C (hex) Cisco SPVTG - 38C85C (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - MS 4.T.607 - Lawrenceville GA 30017 - UNITED STATES - - 38-C9-A9 (hex) SMART High Reliability Solutions, Inc. - 38C9A9 (base 16) SMART High Reliability Solutions, Inc. - 2600 W. Geronimo Place - Chandler AZ 85224 - UNITED STATES - - 38-CA-97 (hex) Contour Design LLC - 38CA97 (base 16) Contour Design LLC - 10 Industrial Drive - Windham NH 03087 - UNITED STATES - - 38-D1-35 (hex) EasyIO Corporation Sdn. Bhd. - 38D135 (base 16) EasyIO Corporation Sdn. Bhd. - No. 32-2 & 32-3, Jalan Puteri 2/4 - Bandar Puteri - Puchong Selangor 47100 - MALAYSIA - - 38-D8-2F (hex) zte corporation - 38D82F (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road - shenzhen guangdong 518057 - CHINA - - 38-DB-BB (hex) Sunbow Telecom Co., Ltd. - 38DBBB (base 16) Sunbow Telecom Co., Ltd. - 3F, 501-21, Chung Cheng Rd., Hsin Tien Dist. - New Taipei City 23148 - TAIWAN, PROVINCE OF CHINA - - 38-DE-60 (hex) Mohlenhoff GmbH - 38DE60 (base 16) Mohlenhoff GmbH - Museumstraße 54a - Salzgitter Niedersachsen 38229 - GERMANY - - 38-E0-8E (hex) Mitsubishi Electric Corporation - 38E08E (base 16) Mitsubishi Electric Corporation - 2-7-3 Marunouchi Chiyoda-ku - Tokyo 100-8310 - JAPAN - - 38-E5-95 (hex) Shenzhen Gongjin Electronics Co.,Ltd - 38E595 (base 16) Shenzhen Gongjin Electronics Co.,Ltd - B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 - Shenzhen Guangdong 518067 - CHINA - - 38-E7-D8 (hex) HTC Corporation - 38E7D8 (base 16) HTC Corporation - No.23 Xinghua Road - Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 38-E8-DF (hex) b gmbh medien + datenbanken - 38E8DF (base 16) b gmbh medien + datenbanken - Kurfuerstenstrasse 22 - Ludwigsburg BW 71636 - GERMANY - - 38-E9-8C (hex) Reco S.p.A. - 38E98C (base 16) Reco S.p.A. - via dellIndustria, 8 - Montano Lucino CO 22070 - ITALY - - 38-EA-A7 (hex) Hewlett Packard - 38EAA7 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 38-EC-11 (hex) Novatek Microelectronics Corp. - 38EC11 (base 16) Novatek Microelectronics Corp. - No.1-2 Innovation Rd I., - Hsinchu Science Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 38-EC-E4 (hex) Samsung Electronics - 38ECE4 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 38-EE-9D (hex) Anedo Ltd. - 38EE9D (base 16) Anedo Ltd. - Huelsmeyerstraße 35 - Eydelstedt 49406 - GERMANY - - 38-F0-98 (hex) Vapor Stone Rail Systems - 38F098 (base 16) Vapor Stone Rail Systems - 10000 Cavendish - Saint-Laurent Quebec H4M2V1 - CANADA - - 38-F3-3F (hex) TATSUNO CORPORATION - 38F33F (base 16) TATSUNO CORPORATION - 2-6,Mita 3-Chome,Minato-ku - Tokyo 108-8520 - JAPAN - - 38-F5-97 (hex) home2net GmbH - 38F597 (base 16) home2net GmbH - Im Haslet 42 - Woerth/Donau Bayern 93086 - GERMANY - - 38-F7-08 (hex) National Resource Management, Inc. - 38F708 (base 16) National Resource Management, Inc. - 480 Neponset St. Bldg. #2 - Canton MA 02021 - UNITED STATES - - 38-F8-89 (hex) Huawei Technologies Co., Ltd - 38F889 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 38-F8-B7 (hex) V2COM PARTICIPACOES S.A. - 38F8B7 (base 16) V2COM PARTICIPACOES S.A. - Rua Cunha Gago, 700 - Conjunto 131 - São Paulo 05421001 - BRAZIL - - 38-FA-CA (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd - 38FACA (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd - 7F,Block A,Skyworth Building, - Gaoxin AVE.1.S,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 38-FE-C5 (hex) Ellips B.V. - 38FEC5 (base 16) Ellips B.V. - Esp 300 - Eindhoven Noord-Brabant 5633 AE - NETHERLANDS - - 3C-02-B1 (hex) Creation Technologies LP - 3C02B1 (base 16) Creation Technologies LP - 3939 North Fraser Way - Burnaby BC V5J 5J2 - CANADA - - 3C-04-BF (hex) PRAVIS SYSTEMS Co.Ltd., - 3C04BF (base 16) PRAVIS SYSTEMS Co.Ltd., - 4F, 5F Jaeyoon Bld, 75-3 Yangjae-Dong, - Seoul Seocho-Gu 137-889 - KOREA, REPUBLIC OF - - 3C-05-AB (hex) Product Creation Studio - 3C05AB (base 16) Product Creation Studio - 425 Westlake Ave N - Seattle WA 98109 - UNITED STATES - - 3C-07-54 (hex) Apple - 3C0754 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 3C-07-71 (hex) Sony Corporation - 3C0771 (base 16) Sony Corporation - 1-7-1 Konan - Minato-ku - Tokyo 108-0075 - JAPAN - - 3C-08-1E (hex) Beijing Yupont Electric Power Technology Co.,Ltd - 3C081E (base 16) Beijing Yupont Electric Power Technology Co.,Ltd - No.1,Dizang-an Nanxiang - Fuxingmenwai - Beijing 100045 - CHINA - - 3C-08-F6 (hex) Cisco - 3C08F6 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 3C-09-6D (hex) Powerhouse Dynamics - 3C096D (base 16) Powerhouse Dynamics - 1 Bridge Street - Newton MA 02458 - UNITED STATES - - 3C-0C-48 (hex) Servergy, Inc. - 3C0C48 (base 16) Servergy, Inc. - 1700 N. Redbud - McKinney TEXAS 75069 - UNITED STATES - - 3C-0E-23 (hex) Cisco - 3C0E23 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 3C-0F-C1 (hex) KBC Networks - 3C0FC1 (base 16) KBC Networks - 25691 Atlantic Ocean Dr - Suite B3 - Lake Forest CA 92630 - UNITED STATES - - 3C-10-40 (hex) daesung network - 3C1040 (base 16) daesung network - #209 e-space Bldg,Guro-dong,Guro-gu - Seoul 152-789 - KOREA, REPUBLIC OF - - 3C-10-6F (hex) ALBAHITH TECHNOLOGIES - 3C106F (base 16) ALBAHITH TECHNOLOGIES - 165, King Abdullah Second Street - Amman 11953 - JORDAN - - 3C-15-C2 (hex) Apple - 3C15C2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 3C-15-EA (hex) TESCOM CO., LTD. - 3C15EA (base 16) TESCOM CO., LTD. - #928 UTV, 1141-2 Baeksuk Ilsandong - Goyang Gyeonggi 410-722 - KOREA, REPUBLIC OF - - 3C-18-9F (hex) Nokia Corporation - 3C189F (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - 3C-18-A0 (hex) Luxshare Precision Industry Co.,Ltd. - 3C18A0 (base 16) Luxshare Precision Industry Co.,Ltd. - Fanshen Industrial Zone - Jiuwei, Xixiang Town - Bao'an District, Shenzhen City Guangdong Province 523000 - CHINA - - 3C-19-15 (hex) GFI Chrono Time - 3C1915 (base 16) GFI Chrono Time - 121 rue des Guillees - CHAURAY 79180 - FRANCE - - 3C-19-7D (hex) Ericsson AB - 3C197D (base 16) Ericsson AB - Torshamnsgatan 36 - Stockholm Stockholm SE-164 80 - SWEDEN - - 3C-1A-0F (hex) ClearSky Data - 3C1A0F (base 16) ClearSky Data - 99 Summer Street - Suite 1130 - Boston MA 02110 - UNITED STATES - - 3C-1A-57 (hex) Cardiopulmonary Corp - 3C1A57 (base 16) Cardiopulmonary Corp - 200 Cascade Blvd - Milford CT 06460 - UNITED STATES - - 3C-1A-79 (hex) Huayuan Technology CO.,LTD - 3C1A79 (base 16) Huayuan Technology CO.,LTD - R308 Block Jingmeng High-Tech Building,NO.5-1 Shangdi East Road, - Haidian District, - Beijing 100085 - CHINA - - 3C-1C-BE (hex) JADAK LLC - 3C1CBE (base 16) JADAK LLC - 7279 William Barry Blvd - North Syracuse NY 13212 - UNITED STATES - - 3C-1E-04 (hex) D-Link International - 3C1E04 (base 16) D-Link International - 1 Internal Business Park, #03-12, - The Synergy - 609917 - SINGAPORE - - 3C-1E-13 (hex) HANGZHOU SUNRISE TECHNOLOGY CO., LTD - 3C1E13 (base 16) HANGZHOU SUNRISE TECHNOLOGY CO., LTD - No.9, LongTan Road, CangQian Town, YuHang District, Hangzhou, China - HangZhou ZheJiang 311121 - CHINA - - 3C-25-D7 (hex) Nokia Corporation - 3C25D7 (base 16) Nokia Corporation - Joensuunkatu 7 - P.O.Box 86 - Salo N.A. 24101 - FINLAND - - 3C-26-D5 (hex) Sotera Wireless - 3C26D5 (base 16) Sotera Wireless - 9444 Waples Street - San Diego CA 92121 - UNITED STATES - - 3C-27-63 (hex) SLE quality engineering GmbH & Co. KG - 3C2763 (base 16) SLE quality engineering GmbH & Co. KG - Josef-Buchinger-Str. 9 - Grafenau Bavaria 94481 - GERMANY - - 3C-2C-94 (hex) æ­å·žå¾·æ¾œç§‘技有é™å…¬å¸ï¼ˆHangZhou Delan Technology Co.,Ltd) - 3C2C94 (base 16) æ­å·žå¾·æ¾œç§‘技有é™å…¬å¸ï¼ˆHangZhou Delan Technology Co.,Ltd) - tianmushan road no.398,Xihu District, hangzhou city, zhejiang province, China - Hangzhou ZheJiang 310013 - CHINA - - 3C-2D-B7 (hex) Texas Instruments - 3C2DB7 (base 16) Texas Instruments - 12500 TI Boulevard, MS8723 - Dallas Texas 75243 - UNITED STATES - - 3C-2F-3A (hex) SFORZATO Corp. - 3C2F3A (base 16) SFORZATO Corp. - 863 - ARAI - HINO-SHI TOKYO 191-0022 - JAPAN - - 3C-30-0C (hex) Dewar Electronics Pty Ltd - 3C300C (base 16) Dewar Electronics Pty Ltd - 32 Taylors Road - Croydon Victoria 3136 - AUSTRALIA - - 3C-31-78 (hex) Qolsys Inc. - 3C3178 (base 16) Qolsys Inc. - 1900 The Alameda - San Jose CA 95126 - UNITED STATES - - 3C-36-3D (hex) Nokia Corporation - 3C363D (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 3C-36-E4 (hex) Arris Group, Inc. - 3C36E4 (base 16) Arris Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 3C-38-88 (hex) ConnectQuest, llc - 3C3888 (base 16) ConnectQuest, llc - P.O. Box 425 - West Simsbury Connecticut 06092 - UNITED STATES - - 3C-39-C3 (hex) JW Electronics Co., Ltd. - 3C39C3 (base 16) JW Electronics Co., Ltd. - 3A17, No. 5 Hsin-yi Rd., Sec. 5 - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 3C-39-E7 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 3C39E7 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 3C-3A-73 (hex) Avaya, Inc - 3C3A73 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 3C-40-4F (hex) Guangdong Pisen Electronics Co. Ltd. - 3C404F (base 16) Guangdong Pisen Electronics Co. Ltd. - Building C,Liuyue Jintang Industry Zone - LongGang District - Shenzhen Guangdong 518173 - CHINA - - 3C-43-8E (hex) ARRIS Group, Inc. - 3C438E (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 3C-46-D8 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 3C46D8 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park - Shennan Road, Nanshan - Shenzhen Guangdong 518057 - CHINA - - 3C-47-11 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 3C4711 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 3C-49-37 (hex) ASSMANN Electronic GmbH - 3C4937 (base 16) ASSMANN Electronic GmbH - Auf dem Schueffel 3 - Luedenscheid Germany 58513 - GERMANY - - 3C-4A-92 (hex) Hewlett-Packard Company - 3C4A92 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 3C-4C-69 (hex) Infinity System S.L. - 3C4C69 (base 16) Infinity System S.L. - Crtra. N-II, Km 48,5 Pol. Ind. Cabanillas del Campo, Parc. 12B - Guadalajara 19171 - SPAIN - - 3C-4E-47 (hex) Etronic A/S - 3C4E47 (base 16) Etronic A/S - Rødeledsvej 95 - Svendborg South Denmark 5700 - DENMARK - - 3C-57-BD (hex) Kessler Crane Inc. - 3C57BD (base 16) Kessler Crane Inc. - 602 East Jefferson St - Plymouth Indidana 46563 - UNITED STATES - - 3C-57-D5 (hex) FiveCo - 3C57D5 (base 16) FiveCo - Ch. de la Rueyre 116 - Renens VD 1020 - SWITZERLAND - - 3C-5A-37 (hex) Samsung Electronics - 3C5A37 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 3C-5A-B4 (hex) Google - 3C5AB4 (base 16) Google - 1600 Amphitheatre Parkway - MS: SB-83 - Mountain View California 94043 - UNITED STATES - - 3C-5E-C3 (hex) Cisco - 3C5EC3 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 3C-5F-01 (hex) Synerchip Co., Ltd. - 3C5F01 (base 16) Synerchip Co., Ltd. - c/o Synerchip USA Corp. - 880 E. Arques Ave. - Sunnyvale CA 94085 - UNITED STATES - - 3C-61-04 (hex) Juniper Networks - 3C6104 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 3C-62-00 (hex) Samsung electronics CO., LTD - 3C6200 (base 16) Samsung electronics CO., LTD - 416, Maetan-3dong, Yeongtong-gu, - Suwon-City Gyeonggi-do 443-742 - KOREA, REPUBLIC OF - - 3C-62-78 (hex) SHENZHEN JETNET TECHNOLOGY CO.,LTD. - 3C6278 (base 16) SHENZHEN JETNET TECHNOLOGY CO.,LTD. - Room 403,4th floor,Qinghua Information Building,Keyuan Road,North District of Tech-Park,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 3C-67-2C (hex) Sciovid Inc. - 3C672C (base 16) Sciovid Inc. - 387 S Silverbrook Dr - Anaheim CA 92807 - UNITED STATES - - 3C-6A-7D (hex) Niigata Power Systems Co., Ltd. - 3C6A7D (base 16) Niigata Power Systems Co., Ltd. - 7-26,Tatsumi 3-Chome - Koto-ku TOKYO 135-0053 - JAPAN - - 3C-6A-9D (hex) Dexatek Technology LTD. - 3C6A9D (base 16) Dexatek Technology LTD. - 15F, NO.81, Sec.1, Xizhi Dist., - New Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - 3C-6E-63 (hex) Mitron OY - 3C6E63 (base 16) Mitron OY - Yrittäjankaari 19 - FORSSA Kanta-Hame 30420 - FINLAND - - 3C-6F-45 (hex) Fiberpro Inc. - 3C6F45 (base 16) Fiberpro Inc. - 59-4 Jang-dong, Yusong-gu - Deajeon 305-343 - KOREA, REPUBLIC OF - - 3C-6F-F7 (hex) EnTek Systems, Inc. - 3C6FF7 (base 16) EnTek Systems, Inc. - 562 Starlight Dr. - Sautee Nacoochee GA 30571 - UNITED STATES - - 3C-70-59 (hex) MakerBot Industries - 3C7059 (base 16) MakerBot Industries - 87 3rd Avenue - Brooklyn NY 11217 - UNITED STATES - - 3C-74-37 (hex) RIM - 3C7437 (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 3C-75-4A (hex) ARRIS Group, Inc. - 3C754A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 3C-77-E6 (hex) Hon Hai Precision Ind. Co.,Ltd. - 3C77E6 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 3C-7D-B1 (hex) Texas Instruments - 3C7DB1 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 3C-81-D8 (hex) SAGEMCOM SAS - 3C81D8 (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON CEDEX IDF 92848 - FRANCE - - 3C-83-75 (hex) Microsoft Corporation - 3C8375 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 3C-83-B5 (hex) Advance Vision Electronics Co. Ltd. - 3C83B5 (base 16) Advance Vision Electronics Co. Ltd. - 6F, No. 199, Lide St. - New Taipei City, Jhonghe Dist 23556 - TAIWAN, PROVINCE OF CHINA - - 3C-86-A8 (hex) Sangshin elecom .co,, LTD - 3C86A8 (base 16) Sangshin elecom .co,, LTD - 614-1 Wolhari Suhmyon - Yunkikun Choongnam 339-814 - KOREA, REPUBLIC OF - - 3C-89-A6 (hex) KAPELSE - 3C89A6 (base 16) KAPELSE - 5 Allee De Saint-Cloud - Technopole de Nancy Brabois - 54600 Villers Les Nancy - FRANCE - - 3C-8A-B0 (hex) Juniper Networks - 3C8AB0 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 3C-8A-E5 (hex) Tensun Information Technology(Hangzhou) Co.,LTD - 3C8AE5 (base 16) Tensun Information Technology(Hangzhou) Co.,LTD - Room 207,Building 5,Wensan Road - Hangzhou Zhejiang 310013 - CHINA - - 3C-8B-FE (hex) Samsung Electronics - 3C8BFE (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 3C-8C-40 (hex) Hangzhou H3C Technologies Co., Limited - 3C8C40 (base 16) Hangzhou H3C Technologies Co., Limited - 466 Changhe Road, Binjiang District - Hangzhou Zhejiang 310052 - CHINA - - 3C-91-2B (hex) Vexata Inc - 3C912B (base 16) Vexata Inc - 1735 Technology Dr Suite 520 - San Jose CA 95110 - UNITED STATES - - 3C-91-57 (hex) Hangzhou Yulong Conmunication Co.,Ltd - 3C9157 (base 16) Hangzhou Yulong Conmunication Co.,Ltd - 5F Building 2,No.56,Liuhe Road,Xihu District - Hangzhou Zhejiang 310023 - CHINA - - 3C-91-74 (hex) ALONG COMMUNICATION TECHNOLOGY - 3C9174 (base 16) ALONG COMMUNICATION TECHNOLOGY - 1301, Zhenye International Business Center, - No.3101-90 Qianhai Road, Nanshan District - Shenzhen Guandong 518000 - CHINA - - 3C-94-D5 (hex) Juniper Networks - 3C94D5 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 3C-97-0E (hex) Wistron InfoComm(Kunshan)Co.,Ltd. - 3C970E (base 16) Wistron InfoComm(Kunshan)Co.,Ltd. - 168# First Avence, - Kunshan Export Processing Zone - Kunshan JiangSu 215300 - CHINA - - 3C-97-7E (hex) IPS Technology Limited - 3C977E (base 16) IPS Technology Limited - 7 Floor,E block,Dong Hai Wang Building - ,BuLong Road,LongGang District - Shenzhen Guangodng 518000 - CHINA - - 3C-98-BF (hex) Quest Controls, Inc. - 3C98BF (base 16) Quest Controls, Inc. - 208 9th Street Dr. West - Palmetto FL 34221 - UNITED STATES - - 3C-99-F7 (hex) Lansentechnology AB - 3C99F7 (base 16) Lansentechnology AB - Rörkullsvägen 4 - Halmstad 30241 - SWEDEN - - 3C-9F-81 (hex) Shenzhen CATIC Bit Communications Technology Co.,Ltd - 3C9F81 (base 16) Shenzhen CATIC Bit Communications Technology Co.,Ltd - in Nanshan District,Shenzhen Software park Road 10 in Room 202 - Shenzhen Guangdong 518057 - CHINA - - 3C-A1-0D (hex) Samsung Electronics Co.,Ltd - 3CA10D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 3C-A3-15 (hex) Bless Information & Communications Co., Ltd - 3CA315 (base 16) Bless Information & Communications Co., Ltd - #64-1, Wonhyoro 3-ga, Yongsan-gu, - Seoul 140-848 - KOREA, REPUBLIC OF - - 3C-A3-1A (hex) Oilfind International LLC - 3CA31A (base 16) Oilfind International LLC - 12651 Briar Forest Dr, Suite 151 - Houston Texas 77077 - UNITED STATES - - 3C-A7-2B (hex) MRV Communications (Networks) LTD - 3CA72B (base 16) MRV Communications (Networks) LTD - P.O Box 614 - Yokneam 20692 - ISRAEL - - 3C-A8-2A (hex) Hewlett Packard - 3CA82A (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Tx 77070 - UNITED STATES - - 3C-A9-F4 (hex) Intel Corporate - 3CA9F4 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 3C-AA-3F (hex) iKey, Ltd. - 3CAA3F (base 16) iKey, Ltd. - 2621 Ridgepoint Drive - Suite 230 - Austin Texas 78754 - UNITED STATES - - 3C-AB-8E (hex) Apple - 3CAB8E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 3C-AE-69 (hex) ESA Elektroschaltanlagen Grimma GmbH - 3CAE69 (base 16) ESA Elektroschaltanlagen Grimma GmbH - Broner Ring 30 - Grimma Saxony 04668 - GERMANY - - 3C-B1-5B (hex) Avaya, Inc - 3CB15B (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 3C-B1-7F (hex) Wattwatchers Pty Ld - 3CB17F (base 16) Wattwatchers Pty Ld - 22 Woodbury Rd St. Ives - Sydney NSW 2075 - AUSTRALIA - - 3C-B7-92 (hex) Hitachi Maxell, Ltd., Optronics Division - 3CB792 (base 16) Hitachi Maxell, Ltd., Optronics Division - 5030 Totsuka-cho, Totsuka-ku - Yokohama Kanagawa 244-0003 - JAPAN - - 3C-B8-7A (hex) PRIVATE - 3CB87A (base 16) - - 3C-B9-A6 (hex) Belden Deutschland GmbH - 3CB9A6 (base 16) Belden Deutschland GmbH - Stuttgarter Straße 45-51 - Neckartenzlingen 72654 - GERMANY - - 3C-BD-D8 (hex) LG ELECTRONICS INC - 3CBDD8 (base 16) LG ELECTRONICS INC - 19-1, CHEONGHO-RI, JINWI-MYEON - PYEONGTAEK GYEONGGI-DO 451-713 - KOREA, REPUBLIC OF - - 3C-C0-C6 (hex) d&b audiotechnik GmbH - 3CC0C6 (base 16) d&b audiotechnik GmbH - Eugen Adolff Str 134 - Backnang Baden Wuerttemberg 71522 - GERMANY - - 3C-C1-2C (hex) AES Corporation - 3CC12C (base 16) AES Corporation - 285 Newbury St - Peabody MA 01960 - UNITED STATES - - 3C-C1-F6 (hex) Melange Systems Pvt. Ltd. - 3CC1F6 (base 16) Melange Systems Pvt. Ltd. - 4/1, 7th Cross, Kumarapark West - Bangalore Karnataka 560020 - INDIA - - 3C-C2-43 (hex) Nokia Corporation - 3CC243 (base 16) Nokia Corporation - Joensuunkatu 7E - P.O. Box 86 - Salo 24101 - FINLAND - - 3C-C2-E1 (hex) XINHUA CONTROL ENGINEERING CO.,LTD - 3CC2E1 (base 16) XINHUA CONTROL ENGINEERING CO.,LTD - 160 Wenjing Road, Minhang - Shanghai Shanghai 200245 - CHINA - - 3C-C9-9E (hex) Huiyang Technology Co., Ltd - 3CC99E (base 16) Huiyang Technology Co., Ltd - 22D 7 Block ZhonghuiNewcity - Xiaobian Avenue Changan Town - Dongguan Guangdong 523849 - CHINA - - 3C-CA-87 (hex) Iders Incorporated - 3CCA87 (base 16) Iders Incorporated - 27047 Oakwood Rd - Oakbank Manitoba R0E 1J2 - CANADA - - 3C-CB-7C (hex) TCT mobile ltd - 3CCB7C (base 16) TCT mobile ltd - NO.86 hechang 7th road, zhongkai hi-tech distrct - Hui Zhou Guang Dong 516006 - CHINA - - 3C-CD-5A (hex) Technische Alternative GmbH - 3CCD5A (base 16) Technische Alternative GmbH - Langestr. 124 - Amaliendorf Lower Austria A-3872 - AUSTRIA - - 3C-CD-93 (hex) LG ELECTRONICS INC - 3CCD93 (base 16) LG ELECTRONICS INC - 19-1, CHEONGHO-RI, JINWI-MYEON - PYEONGTAEK GYEONGGI-DO 451-713 - KOREA, REPUBLIC OF - - 3C-CE-15 (hex) Mercedes-Benz USA, LLC - 3CCE15 (base 16) Mercedes-Benz USA, LLC - One Mercedes Drive - Montvale NJ 07645 - UNITED STATES - - 3C-CE-73 (hex) CISCO SYSTEMS, INC. - 3CCE73 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 3C-D0-F8 (hex) Apple - 3CD0F8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 3C-D1-6E (hex) Telepower Communication Co., Ltd - 3CD16E (base 16) Telepower Communication Co., Ltd - 5/F,Zonghe Building, Hantian Technology Town,Guiping RD,Nanhai District,F - Foshan City Guangdong 528251 - CHINA - - 3C-D4-D6 (hex) WirelessWERX, Inc - 3CD4D6 (base 16) WirelessWERX, Inc - 22687 Old Canal Rd. - Yorba Linda California 92887 - UNITED STATES - - 3C-D7-DA (hex) SK Mtek microelectronics(shenzhen)limited - 3CD7DA (base 16) SK Mtek microelectronics(shenzhen)limited - 12F, Micro-profit Building,South 6 road - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 3C-D9-2B (hex) Hewlett-Packard Company - 3CD92B (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - 3C-D9-CE (hex) Eclipse WiFi - 3CD9CE (base 16) Eclipse WiFi - 68 S Service Rd - Suite 100 - Melville NY 11747 - UNITED STATES - - 3C-DA-2A (hex) zte corporation - 3CDA2A (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road - shenzhen guangdong 518057 - CHINA - - 3C-DF-1E (hex) CISCO SYSTEMS, INC. - 3CDF1E (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 3C-DF-A9 (hex) ARRIS Group, Inc. - 3CDFA9 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 3C-DF-BD (hex) Huawei Technologies Co., Ltd - 3CDFBD (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 3C-E0-72 (hex) Apple - 3CE072 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 3C-E5-A6 (hex) Hangzhou H3C Technologies Co., Ltd. - 3CE5A6 (base 16) Hangzhou H3C Technologies Co., Ltd. - Oriental Electronic Bld., NO.2,Chuangye Road - Shang Di Information Industry Base, Haidian District - Beijing 100085 - CHINA - - 3C-E5-B4 (hex) KIDASEN INDUSTRIA E COMERCIO DE ANTENAS LTDA - 3CE5B4 (base 16) KIDASEN INDUSTRIA E COMERCIO DE ANTENAS LTDA - AV SINCLER SAMBATTI, 1945 - JARDIM BERTIOGA - MARINGA PARANA 87055-020 - BRAZIL - - 3C-E6-24 (hex) LG Display - 3CE624 (base 16) LG Display - 9th, Fl., LG U+ building, 65-228, Hangangro, 3-ga, Yongsan-gu - Seoul 140-716 - KOREA, REPUBLIC OF - - 3C-EA-4F (hex) 2Wire - 3CEA4F (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 3C-EA-FB (hex) NSE AG - 3CEAFB (base 16) NSE AG - Bremgarterstrasse 54 - Wohlen AG 5610 - SWITZERLAND - - 3C-F3-92 (hex) Virtualtek. Co. Ltd - 3CF392 (base 16) Virtualtek. Co. Ltd - 12F, ShinhanDm Bldg., - 25, Mapo-daero, Mapo-gu - Seoul 121-708 - KOREA, REPUBLIC OF - - 3C-F5-2C (hex) DSPECIALISTS GmbH - 3CF52C (base 16) DSPECIALISTS GmbH - Helmholtzstr. 2-9 L - Berlin 10587 - GERMANY - - 3C-F7-2A (hex) Nokia Corporation - 3CF72A (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90570 - FINLAND - - 3C-F7-48 (hex) Shenzhen Linsn Technology Development Co.,Ltd - 3CF748 (base 16) Shenzhen Linsn Technology Development Co.,Ltd - Floor 4,Block 7,Zone 2,Baiwangxin Industrial Park - Xili,Nanshan District - Shenzhen Guangdong 518055 - CHINA - - 3C-F8-08 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 3CF808 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - ShenZhen GuangDong 518129 - CHINA - - 3C-FB-96 (hex) Emcraft Systems LLC - 3CFB96 (base 16) Emcraft Systems LLC - 2191 S. El Camino Real - Suite 208C - Oceanside CA 92054 - UNITED STATES - - 3C-FD-FE (hex) Intel Corporate - 3CFDFE (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 40-01-07 (hex) Arista Corp - 400107 (base 16) Arista Corp - 40675 Encyclopedia Circle - Fremont CA 94538 - UNITED STATES - - 40-01-C6 (hex) 3COM EUROPE LTD - 4001C6 (base 16) 3COM EUROPE LTD - Peoplebuilding 2 - Maylands Avenue - Hemel Hempstead Herts HP2 4NW - UNITED KINGDOM - - 40-04-0C (hex) A&T - 40040C (base 16) A&T - #411, Will Town, 402-3 - Sang-Dong, Wonmi-Gu, - Bucheon-Si Gyeonggi-Do 420-814 - KOREA, REPUBLIC OF - - 40-07-C0 (hex) Railtec Systems GmbH - 4007C0 (base 16) Railtec Systems GmbH - Sonnenbergstr. 19 - Hergiswil Nidwalden 6052 - SWITZERLAND - - 40-0E-67 (hex) Tremol Ltd. - 400E67 (base 16) Tremol Ltd. - 6 Toledo str. - Veliko Turnovo 5000 - BULGARIA - - 40-0E-85 (hex) Samsung Electro Mechanics co.,LTD. - 400E85 (base 16) Samsung Electro Mechanics co.,LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - 40-11-DC (hex) Sonance - 4011DC (base 16) Sonance - 212 Avenida Fabricante - San Clemente California 92672 - UNITED STATES - - 40-12-E4 (hex) Compass-EOS - 4012E4 (base 16) Compass-EOS - 7 Giborei Israel - Natanya 42504 - ISRAEL - - 40-13-D9 (hex) Global ES - 4013D9 (base 16) Global ES - Sinimäentie 8 b - Espoo 02631 - FINLAND - - 40-15-97 (hex) Protect America, Inc. - 401597 (base 16) Protect America, Inc. - 5100 N IH-35 - Suite B - Round Rock TX 78681 - UNITED STATES - - 40-16-7E (hex) ASUSTek COMPUTER INC. - 40167E (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, Taipei 112, Taiwan - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 40-16-9F (hex) TP-LINK TECHNOLOGIES CO., LTD. - 40169F (base 16) TP-LINK TECHNOLOGIES CO., LTD. - 1-6F, Building 2, Pingshandayuan Industrial, South Zone, - Taoyuan Street, Nanshan District, - Shenzhen Guangdong 518000 - CHINA - - 40-16-FA (hex) EKM Metering - 4016FA (base 16) EKM Metering - 363 Berkeley Way - Santa Cruz CA 95062 - UNITED STATES - - 40-18-B1 (hex) Aerohive Networks Inc. - 4018B1 (base 16) Aerohive Networks Inc. - 330 Gibraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - 40-18-D7 (hex) Smartronix, Inc. - 4018D7 (base 16) Smartronix, Inc. - 44150 Smartronix Way - Hollywood MD 20636 - UNITED STATES - - 40-1D-59 (hex) Biometric Associates, LP - 401D59 (base 16) Biometric Associates, LP - 9475 Deereco Rd. - Suite 304 - Timonium MD 21093 - UNITED STATES - - 40-22-ED (hex) Digital Projection Ltd - 4022ED (base 16) Digital Projection Ltd - Greenside Way - Middleton - Manchester Lancs M24 1XX - UNITED KINGDOM - - 40-25-C2 (hex) Intel Corporate - 4025C2 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 40-27-0B (hex) Mobileeco Co., Ltd - 40270B (base 16) Mobileeco Co., Ltd - #2126, IT Tower B, Keumkang Penterium Bldg, 810 - Kwanyang-Dong, Dongan-Ku - Anyang City Kyunggi-Do 431810 - KOREA, REPUBLIC OF - - 40-28-14 (hex) RFI Engineering - 402814 (base 16) RFI Engineering - Markerkant 13-76 - Almere Flevoland 1314AN - NETHERLANDS - - 40-2B-A1 (hex) Sony Ericsson Mobile Communications AB - 402BA1 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 40-2C-F4 (hex) Universal Global Scientific Industrial Co., Ltd. - 402CF4 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, Lane 351, Taiping Rd. Sec. 1, Tsao Tuen, - Nan-Tou Hsien, 542 - TAIWAN, PROVINCE OF CHINA - - 40-30-04 (hex) Apple - 403004 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 40-30-67 (hex) Conlog (Pty) Ltd - 403067 (base 16) Conlog (Pty) Ltd - 270 Felix Dlamini Road - Overport - Durban Kwa-zulu Natal 4000 - SOUTH AFRICA - - 40-33-6C (hex) Godrej & Boyce Mfg. co. ltd - 40336C (base 16) Godrej & Boyce Mfg. co. ltd - PSS TECH CELL, 2ND FLOOR, PLANT 17, SECURITY SOLUTIONS DIVISION - GODREJ & BOYCE MFG. CO. LTD, VIKHROLI (EAST) - MUMBAI MAHARASHTRA 400079 - INDIA - - 40-37-AD (hex) Macro Image Technology, Inc. - 4037AD (base 16) Macro Image Technology, Inc. - East Bldg., 6th Floor, IT Venture Tower, - 78 Garakbon-Dong, Songpa-Gu, - Seoul 138-950 - KOREA, REPUBLIC OF - - 40-3C-FC (hex) Apple - 403CFC (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 40-40-22 (hex) ZIV - 404022 (base 16) ZIV - Polígono Parque Tecnológico, 210 - ZAMUDIO VIZCAYA 48170 - SPAIN - - 40-40-6B (hex) Icomera - 40406B (base 16) Icomera - Vikingsgatan 3 - Göteborg 41104 - SWEDEN - - 40-45-DA (hex) Spreadtrum Communications (Shanghai) Co., Ltd. - 4045DA (base 16) Spreadtrum Communications (Shanghai) Co., Ltd. - Building 1, Spreadtrum Center, No.2288, Zuchongzhi Rd - Zhangjiang High-Tech Park, Pudong District, - Shanghai 201203 - CHINA - - 40-4A-03 (hex) ZyXEL Communications Corporation - 404A03 (base 16) ZyXEL Communications Corporation - No.6 Innovation Road II - Science Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - 40-4A-18 (hex) Addrek Smart Solutions - 404A18 (base 16) Addrek Smart Solutions - Al Gharrafa Thani Bin Jassim St - Doha - QATAR - - 40-4D-8E (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 404D8E (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 40-4E-EB (hex) Higher Way Electronic Co., Ltd. - 404EEB (base 16) Higher Way Electronic Co., Ltd. - No.15 Jingke E. Rd., Nantun District - Taichung 408 - TAIWAN, PROVINCE OF CHINA - - 40-50-E0 (hex) Milton Security Group LLC - 4050E0 (base 16) Milton Security Group LLC - 111 North Harbor Blvd - Suite D - Fullerton CA 92832 - UNITED STATES - - 40-51-6C (hex) Grandex International Corporation - 40516C (base 16) Grandex International Corporation - 4F, 525 Chung Cheng Road - Hsin Tien Dist. New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 40-52-0D (hex) Pico Technology - 40520D (base 16) Pico Technology - James House, Marlborough Road - Colmworth Business Park - St Neots Cambridgeshire PE19 8YP - UNITED KINGDOM - - 40-55-39 (hex) CISCO SYSTEMS, INC. - 405539 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 40-56-0C (hex) In Home Displays Ltd - 40560C (base 16) In Home Displays Ltd - Innovation Centre - 1 Harrison Road - Dundee Angus DD2 3SN - UNITED KINGDOM - - 40-5A-9B (hex) ANOVO - 405A9B (base 16) ANOVO - ZI de Bracheux - 16, Rue Joseph Cugnot - BEAUVAIS 60000 - FRANCE - - 40-5F-BE (hex) RIM - 405FBE (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 40-5F-C2 (hex) Texas Instruments - 405FC2 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 40-60-5A (hex) Hawkeye Tech Co. Ltd - 40605A (base 16) Hawkeye Tech Co. Ltd - 2F, No. 758 Chung Cheng Road, Chung He - New Taipei 23552 - TAIWAN, PROVINCE OF CHINA - - 40-61-86 (hex) MICRO-STAR INT'L CO.,LTD - 406186 (base 16) MICRO-STAR INT'L CO.,LTD - No.69,Li-De St - Jung-Ho City Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 40-61-8E (hex) Stella-Green Co - 40618E (base 16) Stella-Green Co - 1-5-16 Edobori, Nishi-ku - Osaka 550-0002 - JAPAN - - 40-62-B6 (hex) Tele system communication - 4062B6 (base 16) Tele system communication - 5F, No.437, Tao Ying Rd - Taoyuan 33068 - TAIWAN, PROVINCE OF CHINA - - 40-66-7A (hex) mediola - connected living AG - 40667A (base 16) mediola - connected living AG - Nobelring 26 - Frankfurt am Main Hessen 60598 - GERMANY - - 40-68-26 (hex) Thales UK Limited - 406826 (base 16) Thales UK Limited - 1 Linthouse Road - Glasgow Scotland G51 4BZ - UNITED KINGDOM - - 40-6A-AB (hex) RIM - 406AAB (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 5R9 - CANADA - - 40-6C-8F (hex) Apple - 406C8F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 40-6F-2A (hex) Research In Motion - 406F2A (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 40-70-09 (hex) ARRIS Group, Inc. - 407009 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 40-70-4A (hex) Power Idea Technology Limited - 40704A (base 16) Power Idea Technology Limited - 1401A, Mintai Building, WenXin 5 Road, ShenZhen, PRC - Guang Dong Shen Zhen 518054 - CHINA - - 40-70-74 (hex) Life Technology (China) Co., Ltd - 407074 (base 16) Life Technology (China) Co., Ltd - No.1, 2F, Nanshan Digital Culture Industrial base (East Tower Podium) 10128 Shennan Blvd, Nanshan Dist. - Shenzhen Guangdong 518000 - CHINA - - 40-74-96 (hex) aFUN TECHNOLOGY INC. - 407496 (base 16) aFUN TECHNOLOGY INC. - 2F.,No.3,Lane29,HuLu ST.,Shihlin District, - Taipei 11165 - TAIWAN, PROVINCE OF CHINA - - 40-78-6A (hex) Motorola Mobility LLC - 40786A (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - 40-78-75 (hex) IMBEL - Industria de Material Belico do Brasil - 407875 (base 16) IMBEL - Industria de Material Belico do Brasil - Rua Monsenhor Manoel Gomes, 520 - Caju - Rio de Janeiro RJ 20931-670 - BRAZIL - - 40-7A-80 (hex) Nokia Corporation - 407A80 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - 40-7B-1B (hex) Mettle Networks Inc. - 407B1B (base 16) Mettle Networks Inc. - 111 N. Market St STE 300 - San Jose CA 95113 - UNITED STATES - - 40-7F-E0 (hex) Glory Star Technics (ShenZhen) Limited - 407FE0 (base 16) Glory Star Technics (ShenZhen) Limited - 4/f, West Block, Xi Li Village, Xin Wu Industry Bldg - Nanshan District - Shenzhen China 518035 - CHINA - - 40-82-56 (hex) Continental Automotive GmbH - 408256 (base 16) Continental Automotive GmbH - VD=-Strasse 1 - Babenhausen Germany 64832 - GERMANY - - 40-83-DE (hex) Zebra Technologies Inc - 4083DE (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - 40-84-93 (hex) Clavister AB - 408493 (base 16) Clavister AB - Sjogatan 6J - Ornskoldsvik 89160 - SWEDEN - - 40-88-E0 (hex) Beijing Ereneben Information Technology Limited Shenzhen Branch - 4088E0 (base 16) Beijing Ereneben Information Technology Limited Shenzhen Branch - Room 14A, Building A, Honglong Central Plaza, No.3001,Heping Road, Luohu District, Shenzhen City - Shenzhen Guangdong 518001 - CHINA - - 40-8A-9A (hex) TITENG CO., Ltd. - 408A9A (base 16) TITENG CO., Ltd. - 7Fl. Shindo B/D 10 Garak-dong - Songpa-gu - Seoul 138-160 - KOREA, REPUBLIC OF - - 40-8B-07 (hex) Actiontec Electronics, Inc - 408B07 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 40-8B-F6 (hex) Shenzhen TCL New Technology Co; Ltd. - 408BF6 (base 16) Shenzhen TCL New Technology Co; Ltd. - TCL Building, #5 Central Nanhai Road, Nanshan District, - Shenzhen, Guangdong, 518067 - CHINA - - 40-8D-5C (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 408D5C (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - Pin-Jen City, Taoyuan, Taiwan, R.O.C. - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 40-95-58 (hex) Aisino Corporation - 409558 (base 16) Aisino Corporation - No.18A, Xingshikou Road, - Haidian District - Beijing 100195 - CHINA - - 40-97-D1 (hex) BK Electronics cc - 4097D1 (base 16) BK Electronics cc - 150 Swaardlelie Ave - The Willows - Pretoria Gauteng 0184 - SOUTH AFRICA - - 40-98-4C (hex) Casacom Solutions AG - 40984C (base 16) Casacom Solutions AG - Badenerstarsse 551 - Zuerich 8046 - SWITZERLAND - - 40-98-4E (hex) Texas Instruments - 40984E (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 40-98-7B (hex) Aisino Corporation - 40987B (base 16) Aisino Corporation - No.18 A,Xingshikou Road,Haidian District, - Beijing 100195 - CHINA - - 40-9B-0D (hex) Shenzhen Yourf Kwan Industrial Co., Ltd - 409B0D (base 16) Shenzhen Yourf Kwan Industrial Co., Ltd - MCN Edifice 5D, R1 Building, No.21 4th Hi-tech Road South, High-tech Industrial Park(south) - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 40-9F-C7 (hex) BAEKCHUN I&C Co., Ltd. - 409FC7 (base 16) BAEKCHUN I&C Co., Ltd. - 67-5, Gyesu-dong - Sosa-gu - Bucheon-si Gyeonggi-do 422-070 - KOREA, REPUBLIC OF - - 40-A5-EF (hex) Shenzhen Four Seas Global Link Network Technology Co., Ltd. - 40A5EF (base 16) Shenzhen Four Seas Global Link Network Technology Co., Ltd. - Room 607-610, Block B, TAOJINDI Electronic Business Incubation Base, Tenglong Road, Longhua District, Shenzhen, China. - shenzhen guangdong 518000 - CHINA - - 40-A6-77 (hex) Juniper Networks - 40A677 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 40-A6-A4 (hex) PassivSystems Ltd - 40A6A4 (base 16) PassivSystems Ltd - Medway House - Newbury Business Park - Newbury Berks RG14 2PZ - UNITED KINGDOM - - 40-A6-D9 (hex) Apple - 40A6D9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 40-A6-E8 (hex) Cisco - 40A6E8 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 40-A8-F0 (hex) Hewlett Packard - 40A8F0 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 40-AC-8D (hex) Data Management, Inc. - 40AC8D (base 16) Data Management, Inc. - 3322 Loop 306 - San Angelo Texas 76904 - UNITED STATES - - 40-B0-FA (hex) LG Electronics - 40B0FA (base 16) LG Electronics - 60-39, Kasan-dong, Gumcheon-gu - Seoul Seoul 153-801 - KOREA, REPUBLIC OF - - 40-B2-C8 (hex) Nortel Networks - 40B2C8 (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - 40-B3-95 (hex) Apple - 40B395 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 40-B3-CD (hex) Chiyoda Electronics Co.,Ltd. - 40B3CD (base 16) Chiyoda Electronics Co.,Ltd. - 1-3-11 Nishiki-cho - Warabi Saitama 335-0005 - JAPAN - - 40-B3-FC (hex) Logital Co. Limited - 40B3FC (base 16) Logital Co. Limited - Rm 901-902, 9/F, Nathan Centre, - 580G-K Nathan Road, Mongkok, - Kowloon - HONG KONG - - 40-B4-F0 (hex) Juniper Networks - 40B4F0 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 40-B6-B1 (hex) SUNGSAM CO,.Ltd - 40B6B1 (base 16) SUNGSAM CO,.Ltd - SUNGSAM Bldg, 7-1, BAnga-ro 23beon-gil, Bundang-gu - Seongnam-si Gyeonggi-do 463-829 - KOREA, REPUBLIC OF - - 40-B7-F3 (hex) ARRIS Group, Inc. - 40B7F3 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 40-B8-37 (hex) Sony Mobile Communications AB - 40B837 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 40-B8-9A (hex) Hon Hai Precision Ind. Co.,Ltd. - 40B89A (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - Xiyong Town - Shapingba District Chongqing 401332 - CHINA - - 40-BA-61 (hex) Arima Communications Corp. - 40BA61 (base 16) Arima Communications Corp. - 6F., No.866, Jhongjheng Rd., Jhonghe Dist. - New Taipei City 23586 - TAIWAN, PROVINCE OF CHINA - - 40-BC-73 (hex) Cronoplast S.L. - 40BC73 (base 16) Cronoplast S.L. - Pol.Ind.S.Ermengol II - - c/Francesc Layret,12-14, - ABRERA BARCELONA 08630 - SPAIN - - 40-BC-8B (hex) itelio GmbH - 40BC8B (base 16) itelio GmbH - Franz-Larcher-Straße 4 - Kiefersfelden Bavaria 83088 - GERMANY - - 40-BD-9E (hex) Physio-Control, Inc - 40BD9E (base 16) Physio-Control, Inc - 11811 Willows Rd NE - Redmond WA 98052 - UNITED STATES - - 40-BF-17 (hex) Digistar Telecom. SA - 40BF17 (base 16) Digistar Telecom. SA - Av. Theodomiro Porto da Fonseca, 3101 - Building 2 - Sao Leopoldo RS 9302080 - BRAZIL - - 40-C2-45 (hex) Shenzhen Hexicom Technology Co., Ltd. - 40C245 (base 16) Shenzhen Hexicom Technology Co., Ltd. - 1510 West Building,Nanshan Software Park, Nanshan Dist. - Shenzhen Guangdong 518053 - CHINA - - 40-C4-D6 (hex) ChongQing Camyu Technology Development Co.,Ltd. - 40C4D6 (base 16) ChongQing Camyu Technology Development Co.,Ltd. - 4th Floor,Tower of Venus Technology Building ,NO 60 Xing Guang Road - New North Zone - Chong Qing 401121 - CHINA - - 40-C6-2A (hex) Shanghai Jing Ren Electronic Technology Co., Ltd. - 40C62A (base 16) Shanghai Jing Ren Electronic Technology Co., Ltd. - GUI Qing Road 7 No. 3 building G7 software base A District 208 room - Xuhui District Shanghai City 200233 - CHINA - - 40-C7-C9 (hex) Naviit Inc. - 40C7C9 (base 16) Naviit Inc. - 3058A Scott Blvd. - Santa Clara CA 95054 - UNITED STATES - - 40-CB-A8 (hex) Huawei Technologies Co., Ltd - 40CBA8 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - Shiyan Baoan District, - Shenzhen, Guangdong 518057 - CHINA - - 40-CD-3A (hex) Z3 Technology - 40CD3A (base 16) Z3 Technology - 2720 Harrison St - Evanston IL 60201 - UNITED STATES - - 40-D2-8A (hex) Nintendo Co., Ltd. - 40D28A (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO KYOTO 601-8501 - JAPAN - - 40-D3-2D (hex) Apple - 40D32D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 40-D4-0E (hex) Biodata Ltd - 40D40E (base 16) Biodata Ltd - 10 Stocks Street - Manchester M8 8QG - UNITED KINGDOM - - 40-D5-59 (hex) MICRO S.E.R.I. - 40D559 (base 16) MICRO S.E.R.I. - 24, rue Henri FARMAN - ZA Tremblay Charles de Gaulle - TREMBLAY EN FRANCE Ile de France 93290 - FRANCE - - 40-D8-55 (hex) IEEE REGISTRATION AUTHORITY - Please see IAB public listing for more information. - 40D855 (base 16) IEEE REGISTRATION AUTHORITY - Please see IAB public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 40-E2-30 (hex) AzureWave Technologies, Inc. - 40E230 (base 16) AzureWave Technologies, Inc. - 8F., No. 94, Baozhong Rd., - Xindian Dist., - New Taipei City Taiwan 231 - TAIWAN, PROVINCE OF CHINA - - 40-E7-30 (hex) DEY Storage Systems, Inc. - 40E730 (base 16) DEY Storage Systems, Inc. - 215 South B Street - San Mateo CA 94401 - UNITED STATES - - 40-E7-93 (hex) Shenzhen Siviton Technology Co.,Ltd - 40E793 (base 16) Shenzhen Siviton Technology Co.,Ltd - 4F,Block6,Coolpad Business Centre,North of Keyuan Road,Hi-technology Zone,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 40-EA-CE (hex) FOUNDER BROADBAND NETWORK SERVICE CO.,LTD - 40EACE (base 16) FOUNDER BROADBAND NETWORK SERVICE CO.,LTD - 5F,Tower B,Beifa Plaza,No.16 Building - No.15 Xue Yuan South Rd - Haisdian District Beijing 100088 - CHINA - - 40-EC-F8 (hex) Siemens AG - 40ECF8 (base 16) Siemens AG - I IS MS EDM - Munich Germany 85630 - GERMANY - - 40-EF-4C (hex) Fihonest communication co.,Ltd - 40EF4C (base 16) Fihonest communication co.,Ltd - Room902,Park road,Zhixing business-building - Changping town - Dongguan Guangdong 523560 - CHINA - - 40-F0-2F (hex) Liteon Technology Corporation - 40F02F (base 16) Liteon Technology Corporation - 4F,90, Chien 1 Road, Chung Ho - , Taipei Hsien - TaiPei 23585 - TAIWAN, PROVINCE OF CHINA - - 40-F1-4C (hex) ISE Europe SPRL - 40F14C (base 16) ISE Europe SPRL - Fauvette 1 - Uccle 1180 - BELGIUM - - 40-F2-01 (hex) SAGEMCOM - 40F201 (base 16) SAGEMCOM - 250 route de l'Empereur - Rueil Malmaison HAUTS DE SEINE 92848 - FRANCE - - 40-F2-E9 (hex) IBM - 40F2E9 (base 16) IBM - 3039 E Cornwallis Rd - PO Box 12195 - Research Triangle Park NC 27560 - UNITED STATES - - 40-F3-08 (hex) Murata Manufactuaring Co.,Ltd. - 40F308 (base 16) Murata Manufactuaring Co.,Ltd. - 1-10-1 Higashikotari  - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 40-F4-07 (hex) Nintendo Co., Ltd. - 40F407 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 40-F4-EC (hex) CISCO SYSTEMS, INC. - 40F4EC (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 40-F5-2E (hex) Leica Microsystems (Schweiz) AG - 40F52E (base 16) Leica Microsystems (Schweiz) AG - Max Schmidheiny-Strasse 201 - Heerbrugg SG 9435 - SWITZERLAND - - 40-FC-89 (hex) ARRIS Group, Inc. - 40FC89 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 44-03-A7 (hex) Cisco - 4403A7 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 44-0C-FD (hex) NetMan Co., Ltd. - 440CFD (base 16) NetMan Co., Ltd. - Rm 406, DIP, 2139, Daemyeong-dong, - Nam-gu, - Daegu 705-701 - KOREA, REPUBLIC OF - - 44-11-C2 (hex) Telegartner Karl Gartner GmbH - 4411C2 (base 16) Telegartner Karl Gartner GmbH - Lerchenstr. 35 - Steinenbronn Baden-Wurttemberg 71144 - GERMANY - - 44-13-19 (hex) WKK TECHNOLOGY LTD. - 441319 (base 16) WKK TECHNOLOGY LTD. - 23/F., One Kowloon, No.1, Wang Yuen Street, - Kowloon Bay, - 852 - HONG KONG - - 44-18-4F (hex) Fitview - 44184F (base 16) Fitview - 5615 Scotts Valley Drive, Suite 110 - Scotts Valley CA 95066 - UNITED STATES - - 44-19-B6 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. - 4419B6 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. - No.469,Jianghui Road - Binjiang District - Hangzhou Zhejiang 310052 - CHINA - - 44-1E-91 (hex) ARVIDA Intelligent Electronics Technology Co.,Ltd. - 441E91 (base 16) ARVIDA Intelligent Electronics Technology Co.,Ltd. - No.3 Qiliang Road., - Danyang Jiangsu 212300 - CHINA - - 44-1E-A1 (hex) Hewlett-Packard Company - 441EA1 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 44-23-AA (hex) Farmage Co., Ltd. - 4423AA (base 16) Farmage Co., Ltd. - 166-8 Kanazawa Toubetsu - Ishikari-gun Hokkaido - Hokkaido 061-0212 - JAPAN - - 44-25-BB (hex) Bamboo Entertainment Corporation - 4425BB (base 16) Bamboo Entertainment Corporation - 179 South Street - 6th Floor - Boston MA 02111 - UNITED STATES - - 44-29-38 (hex) NietZsche enterprise Co.Ltd. - 442938 (base 16) NietZsche enterprise Co.Ltd. - 4F. No.560 Sec2 Chung Shan Rd. - Chunh Ho Dist - New Taipei City Taipei ( 臺 北 縣 / 市 ) 220 - TAIWAN, PROVINCE OF CHINA - - 44-2A-60 (hex) Apple - 442A60 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 44-2A-FF (hex) E3 Technology, Inc. - 442AFF (base 16) E3 Technology, Inc. - Martell-house 2F, 2-28-3 Sekimachi-Kita, - Nerima-ku Tokyo 177-0051 - JAPAN - - 44-2B-03 (hex) CISCO SYSTEMS, INC. - 442B03 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 44-31-92 (hex) Hewlett Packard - 443192 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 44-32-2A (hex) Avaya, Inc - 44322A (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 44-32-C8 (hex) Technicolor USA Inc. - 4432C8 (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 44-33-4C (hex) Shenzhen Bilian electronic CO.,LTD - 44334C (base 16) Shenzhen Bilian electronic CO.,LTD - NO 268 - Shenzhen Guangdong 518110 - CHINA - - 44-34-8F (hex) MXT INDUSTRIAL LTDA - 44348F (base 16) MXT INDUSTRIAL LTDA - RODOVIA BR 381, KM 490, JARDIM DAS ALTEROSAS - BETIM MINAS GERAIS 32670790 - BRAZIL - - 44-35-6F (hex) Neterix - 44356F (base 16) Neterix - The Printworks - Sealand Road - Chester Cheshire CH1 4RN - UNITED KINGDOM - - 44-37-19 (hex) 2 Save Energy Ltd - 443719 (base 16) 2 Save Energy Ltd - The Annexe, Field House Barn - Chineham Lane - Sherborne St John Hampshire RG24 9LR - UNITED KINGDOM - - 44-37-6F (hex) Young Electric Sign Co - 44376F (base 16) Young Electric Sign Co - 1651 N 1000 W - Logan UT 84321 - UNITED STATES - - 44-37-E6 (hex) Hon Hai Precision Ind.Co.Ltd - 4437E6 (base 16) Hon Hai Precision Ind.Co.Ltd - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 44-38-39 (hex) Cumulus Networks, inc - 443839 (base 16) Cumulus Networks, inc - 650 Castro Street, suite 120-245 - Mountain View CA 94041 - UNITED STATES - - 44-39-C4 (hex) Universal Global Scientific Industrial Co.,Ltd - 4439C4 (base 16) Universal Global Scientific Industrial Co.,Ltd - 141,Lane351,Taiping Rd.Sec.1 - Tsao Tuen,Nan-Tou Hsien - 542 - TAIWAN, PROVINCE OF CHINA - - 44-3C-9C (hex) Pintsch Tiefenbach GmbH - 443C9C (base 16) Pintsch Tiefenbach GmbH - Beisenbruchstrasse 10 - Sprockhoevel 45549 - GERMANY - - 44-3D-21 (hex) Nuvolt - 443D21 (base 16) Nuvolt - 8087 Boul. de la Rive Sud - Levis Quebec G6V 9G9 - CANADA - - 44-3E-B2 (hex) DEOTRON Co., LTD. - 443EB2 (base 16) DEOTRON Co., LTD. - 506, Dain Bldg - 742-3 Choji-dong - Ansan Kyonggi-do 425-856 - KOREA, REPUBLIC OF - - 44-48-91 (hex) HDMI Licensing, LLC - 444891 (base 16) HDMI Licensing, LLC - 1140 East Arques, Suite 100 - Sunnyvale CA 94085 - UNITED STATES - - 44-4A-65 (hex) Silverflare Ltd. - 444A65 (base 16) Silverflare Ltd. - 2 Bakers Yard - 163 High Street - Uxbridge Greater London UB8 1JZ - UNITED KINGDOM - - 44-4C-0C (hex) Apple - 444C0C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 44-4E-1A (hex) Samsung Electronics Co.,Ltd - 444E1A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 44-4F-5E (hex) Pan Studios Co.,Ltd. - 444F5E (base 16) Pan Studios Co.,Ltd. - 1F., NO.402, SEC. 2, JHONGYANG N. RD., BEITOU DISTRICT, - TAIPEI CITY 11258 - TAIWAN, PROVINCE OF CHINA - - 44-51-DB (hex) Raytheon BBN Technologies - 4451DB (base 16) Raytheon BBN Technologies - 10 Moulton Street - Cambridge MA 02138 - UNITED STATES - - 44-54-C0 (hex) Thompson Aerospace - 4454C0 (base 16) Thompson Aerospace - 18 Technology - Suite 121 - Irvine CA 92618 - UNITED STATES - - 44-55-B1 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 4455B1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - 44-56-8D (hex) PNC Technologies Co., Ltd. - 44568D (base 16) PNC Technologies Co., Ltd. - Development Center - 898-43, Hogye-dong, Dongan-Gu, - Anyang Gyeonggi-Do 431-836 - KOREA, REPUBLIC OF - - 44-56-B7 (hex) Spawn Labs, Inc - 4456B7 (base 16) Spawn Labs, Inc - 2209 Granger Lane - Austin TX 78613 - UNITED STATES - - 44-58-29 (hex) Cisco SPVTG - 445829 (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - MS 4.T.421 - Lawrenceville Georgia 30044 - UNITED STATES - - 44-59-9F (hex) Criticare Systems, Inc - 44599F (base 16) Criticare Systems, Inc - 20925 Crossroads Circle - Waukasha WI 53186 - UNITED STATES - - 44-5E-CD (hex) Razer Inc - 445ECD (base 16) Razer Inc - 2035 Corte Del Nogal - Suite 101 - Carlsbad CA 92011 - UNITED STATES - - 44-5E-F3 (hex) Tonalite Holding B.V. - 445EF3 (base 16) Tonalite Holding B.V. - Nieuw Amsterdamsestraat 40 - Emmen Drenthe 7814 VA - NETHERLANDS - - 44-5F-7A (hex) Shihlin Electric & Engineering Corp. - 445F7A (base 16) Shihlin Electric & Engineering Corp. - 16F NO.88, SEC, 6, CHUNG SHAN N. RD., TAIPEI - No. 234, ChungLun, - HsinChu HsinFun Shiang 304 - TAIWAN, PROVINCE OF CHINA - - 44-61-32 (hex) ecobee inc - 446132 (base 16) ecobee inc - 333 Adelaide St W 6th Floor - Toronto Ontario M5V1R5 - CANADA - - 44-61-9C (hex) FONsystem co. ltd. - 44619C (base 16) FONsystem co. ltd. - 3F annex of Venture support center - GJTP, DaeChon Dong, Buk Gu - GwangJu 500-706 - KOREA, REPUBLIC OF - - 44-66-6E (hex) IP-LINE - 44666E (base 16) IP-LINE - #204, Gangseo B/D - 46, Jungangro-3gil - Guro-gu Seoul 152-826 - KOREA, REPUBLIC OF - - 44-67-55 (hex) Orbit Irrigation - 446755 (base 16) Orbit Irrigation - P.O. Box 328 - Bountiful Utah 84011 - UNITED STATES - - 44-68-AB (hex) JUIN COMPANY, LIMITED - 4468AB (base 16) JUIN COMPANY, LIMITED - 2FL, 1075-1, Wonpyeong-Dong - Gumi City Gyeongsangbuk-Do 730-010 - KOREA, REPUBLIC OF - - 44-6C-24 (hex) Reallin Electronic Co.,Ltd - 446C24 (base 16) Reallin Electronic Co.,Ltd - 2/F, Building 3, No.202 Zhengzhong Rd, XiHu industry Park - Hang Zhou Zhe Jiang 310030 - CHINA - - 44-6D-57 (hex) Liteon Technology Corporation - 446D57 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo - Taipei TaiWan 23585 - TAIWAN, PROVINCE OF CHINA - - 44-6D-6C (hex) Samsung Elec Co.,Ltd - 446D6C (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 44-70-0B (hex) IFFU - 44700B (base 16) IFFU - 33, Annyeom-gil 112 beon-gil,jeongnam-myeon - Hwaseong-si Gyeonggi-do 445-968 - KOREA, REPUBLIC OF - - 44-70-98 (hex) MING HONG TECHNOLOGY (SHEN ZHEN) LIMITED - 447098 (base 16) MING HONG TECHNOLOGY (SHEN ZHEN) LIMITED - Unit 906,South Block,Resources Tech Building, - NO.1 Song Ping Shan Road,High-Tech Park - Shenzhen Guangdong province 518000 - CHINA - - 44-74-6C (hex) Sony Mobile Communications AB - 44746C (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 44-7B-C4 (hex) DualShine Technology(SZ)Co.,Ltd - 447BC4 (base 16) DualShine Technology(SZ)Co.,Ltd - No.334-1,LuoTian 3rd Industrial Park, - XiangShan Ave.SongGang Town,BaoAn Dist., - Shen Zhen Guang Dong 518000 - CHINA - - 44-7C-7F (hex) Innolight Technology Corporation - 447C7F (base 16) Innolight Technology Corporation - 3 Results Way - Cupertino CA 95014 - UNITED STATES - - 44-7D-A5 (hex) VTION INFORMATION TECHNOLOGY (FUJIAN) CO.,LTD - 447DA5 (base 16) VTION INFORMATION TECHNOLOGY (FUJIAN) CO.,LTD - Room 502, Wing A, World Trade Center - No.36 East North Third Ring Road,Dongcheng District, - Beijing, - CHINA - - 44-7E-76 (hex) Trek Technology (S) Pte Ltd - 447E76 (base 16) Trek Technology (S) Pte Ltd - 30 Loyang Way #07-15 - Loyang Industrial Estate - Singapore 508769 - SINGAPORE - - 44-7E-95 (hex) Alpha and Omega, Inc - 447E95 (base 16) Alpha and Omega, Inc - 4735 Montview Blvd - Denver CO 80207 - UNITED STATES - - 44-80-EB (hex) Motorola Mobility LLC, a Lenovo Company - 4480EB (base 16) Motorola Mobility LLC, a Lenovo Company - 222 West Merchandise Mart Plaza - Suite 1800 - Chicago IL 60654 - UNITED STATES - - 44-83-12 (hex) Star-Net - 448312 (base 16) Star-Net - Egoz 64 - Kiryat Byalik Israel 27000 - ISRAEL - - 44-85-00 (hex) Intel Corporate - 448500 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 44-86-C1 (hex) Siemens Low Voltage & Products - 4486C1 (base 16) Siemens Low Voltage & Products - 5400 Triangle Parkway - Norcross GA 30092 - UNITED STATES - - 44-87-FC (hex) ELITEGROUP COMPUTER SYSTEM CO., LTD. - 4487FC (base 16) ELITEGROUP COMPUTER SYSTEM CO., LTD. - NO. 239, Sec. 2, Ti Ding Blvd. - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - 44-88-CB (hex) Camco Technologies NV - 4488CB (base 16) Camco Technologies NV - Technologielaan 13 - Heverlee VB 3001 - BELGIUM - - 44-8A-5B (hex) Micro-Star INT'L CO., LTD. - 448A5B (base 16) Micro-Star INT'L CO., LTD. - No69, LIde St. - Jhonghe City - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 44-8C-52 (hex) KTIS CO., Ltd - 448C52 (base 16) KTIS CO., Ltd - 1208ho-103dong - 36-1, Bucheon Technopark3. Samjung-Dong - Ojung-Gu, Bucheon-si Gyeonggi-do 421-808 - KOREA, REPUBLIC OF - - 44-8E-12 (hex) DT Research, Inc. - 448E12 (base 16) DT Research, Inc. - 2000 Concourse Drive - San Jose CA 95131 - UNITED STATES - - 44-8E-81 (hex) VIG - 448E81 (base 16) VIG - 705 Hanshin IT Tower, 60-18, Kasan-dong, Geumcheon-gu - Seoul KSXX0022 - KOREA, REPUBLIC OF - - 44-91-DB (hex) Shanghai Huaqin Telecom Technology Co.,Ltd - 4491DB (base 16) Shanghai Huaqin Telecom Technology Co.,Ltd - No.1 Building,399 Keyuan Road, Zhangjian Hi-Tech Park, Pudong New Area, - Shanghai 201203 - CHINA - - 44-94-FC (hex) NETGEAR INC., - 4494FC (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 44-95-FA (hex) Qingdao Santong Digital Technology Co.Ltd - 4495FA (base 16) Qingdao Santong Digital Technology Co.Ltd - Room701, No.1£¬Fu Ying Building,No.443East Changjiang Road,Qingdao Economic and Technological Development District - No.866 LinggangRoad, South Haier Avenue, Qingdao Economic and Technological Development District - Qingdao Shandong 266555 - CHINA - - 44-96-2B (hex) Aidon Oy - 44962B (base 16) Aidon Oy - Piippukatu 11 - Jyvaskyla Jyvaskyla 40100 - FINLAND - - 44-9B-78 (hex) The Now Factory - 449B78 (base 16) The Now Factory - Arkle Road - Sandyford Business Park - Dublin 18 - IRELAND - - 44-9C-B5 (hex) Alcomp, Inc - 449CB5 (base 16) Alcomp, Inc - 11537 Walnut Lane - Fort Atkinson WI 53538 - UNITED STATES - - 44-A4-2D (hex) TCT Mobile Limited - 44A42D (base 16) TCT Mobile Limited - 4/F, South Building,No.2966, Jinke Road, Zhangjiang High-Tech Park, Pudong - Shanghai 201203 - CHINA - - 44-A6-89 (hex) PROMAX ELECTRONICA SA - 44A689 (base 16) PROMAX ELECTRONICA SA - FRANCESC MORAGAS 71-75 - HOSPITALET DE LLOBREGAT BARCELONA 08907 - SPAIN - - 44-A6-E5 (hex) THINKING TECHNOLOGY CO.,LTD - 44A6E5 (base 16) THINKING TECHNOLOGY CO.,LTD - The 6th Floor,Gate No. 3 of Huaqiang Logistics Building - Longzhu 3rd Road - Nanshan, Shenzhen Guangdong 518055 - CHINA - - 44-A7-CF (hex) Murata Manufacturing Co., Ltd. - 44A7CF (base 16) Murata Manufacturing Co., Ltd. - 2288, Oaza-Ohshinohara, Yasu-cho, - Yasu-gun Shiga 520-2393 - JAPAN - - 44-A8-42 (hex) Dell Inc. - 44A842 (base 16) Dell Inc. - One dell Way - Round rock TX 78682 - UNITED STATES - - 44-A8-C2 (hex) SEWOO TECH CO., LTD - 44A8C2 (base 16) SEWOO TECH CO., LTD - 689-20 GEUMJUNG-DONG - GUNPO-SI KYUNGGI-DO 435-862 - KOREA, REPUBLIC OF - - 44-AA-27 (hex) udworks Co., Ltd. - 44AA27 (base 16) udworks Co., Ltd. - #810, Byuksan3cha Digital Valley, 212-13, Guro-dong, Guro-gu - Seoul 152-775 - KOREA, REPUBLIC OF - - 44-AA-E8 (hex) Nanotec Electronic GmbH & Co. KG - 44AAE8 (base 16) Nanotec Electronic GmbH & Co. KG - Gewerbestrasse 11 - Landsham Bavaria 85652 - GERMANY - - 44-AD-D9 (hex) Cisco - 44ADD9 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 44-B3-82 (hex) Kuang-chi Institute of Advanced Technology - 44B382 (base 16) Kuang-chi Institute of Advanced Technology - Software building, Gaoxingzhong 1st Road, - High-Tech park, Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 44-C1-5C (hex) Texas Instruments - 44C15C (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 44-C2-33 (hex) Guangzhou Comet Technology Development Co.Ltd - 44C233 (base 16) Guangzhou Comet Technology Development Co.Ltd - Rm 304,FL 3,Block G,Science and Technology Innovation Base, - No.80,Lanyue Road,Science Park, - Guangzhou Guangdong 510663 - CHINA - - 44-C3-06 (hex) SIFROM Inc. - 44C306 (base 16) SIFROM Inc. - 1201 N. Orange St., Ste 700 #7112 - Wilmington DE 19801-1186 - UNITED STATES - - 44-C3-9B (hex) OOO RUBEZH NPO - 44C39B (base 16) OOO RUBEZH NPO - Pionerskaya 11a - Bratsk Irkutsk 665717 - RUSSIAN FEDERATION - - 44-C4-A9 (hex) Opticom Communication, LLC - 44C4A9 (base 16) Opticom Communication, LLC - 1050 Connecticut Avenue, NW - Suite 10000 - Washington DC 20036 - UNITED STATES - - 44-C5-6F (hex) NGN Easy Satfinder (Tianjin) Electronic Co., Ltd - 44C56F (base 16) NGN Easy Satfinder (Tianjin) Electronic Co., Ltd - A4, Sifang Hi-tech Building, - Nankai Hi-tech Industry Area, Ya'an Road, Nankai District - No.496, Jie Fangnan Road, Hexi District, Tianjin 300113 - CHINA - - 44-C6-9B (hex) Wuhan Feng Tian Information Network CO.,LTD - 44C69B (base 16) Wuhan Feng Tian Information Network CO.,LTD - Room 1002,10th Floor,Oversea talent Building A, - NO999 Gaoxin Street,Wuhan,China - Wuhan City Hubei Province 430074 - CHINA - - 44-C9-A2 (hex) Greenwald Industries - 44C9A2 (base 16) Greenwald Industries - 212 Middlesex Avenue - Chester CT 06412 - UNITED STATES - - 44-CE-7D (hex) SFR - 44CE7D (base 16) SFR - 5 RUE NOEL PONS - NANTERRE IDF 92000 - FRANCE - - 44-D1-5E (hex) Shanghai Kingto Information Technology Ltd - 44D15E (base 16) Shanghai Kingto Information Technology Ltd - No.738 Guangji RD.3F shanghai.china - shanghai 200434 - CHINA - - 44-D2-44 (hex) Seiko Epson Corporation - 44D244 (base 16) Seiko Epson Corporation - 80 Harashinden - Hirooka - Shiojiri-shi Nagano-ken 399-0785 - JAPAN - - 44-D2-CA (hex) Anvia TV Oy - 44D2CA (base 16) Anvia TV Oy - PO Box 29 - SEINAJOKI FIN60101 - FINLAND - - 44-D3-CA (hex) CISCO SYSTEMS, INC. - 44D3CA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 44-D4-E0 (hex) Sony Mobile Communications AB - 44D4E0 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22128 - SWEDEN - - 44-D6-3D (hex) Talari Networks - 44D63D (base 16) Talari Networks - 3200 Glen Royal Rd. - Suite 100 - Raleigh NC 27617 - UNITED STATES - - 44-D8-32 (hex) Azurewave Technologies, Inc. - 44D832 (base 16) Azurewave Technologies, Inc. - 8F., Baozhong Rd. - Xindian City Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 44-D8-84 (hex) Apple - 44D884 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 44-D9-E7 (hex) Ubiquiti Networks, Inc. - 44D9E7 (base 16) Ubiquiti Networks, Inc. - 2580 Orchard Parkway - San Jose CA 95131 - UNITED STATES - - 44-DC-91 (hex) PLANEX COMMUNICATIONS INC. - 44DC91 (base 16) PLANEX COMMUNICATIONS INC. - 2F F-NISSAY Ebisu Bldg 3-16-3 Higashi, - Shibuya-ku Tokyo 150-0011 - JAPAN - - 44-DC-CB (hex) SEMINDIA SYSTEMS PVT LTD - 44DCCB (base 16) SEMINDIA SYSTEMS PVT LTD - 1006/13, Sy No.49/1&3, 7th Mile, A.M Indl Estate, - Garvebhavipalya,Hosur Road, - Bangalore Karnataka 560068 - INDIA - - 44-E0-8E (hex) Cisco SPVTG - 44E08E (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 44-E1-37 (hex) ARRIS Group, Inc. - 44E137 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 44-E4-9A (hex) OMNITRONICS PTY LTD - 44E49A (base 16) OMNITRONICS PTY LTD - 27 SARICH CRT - OSBORNE PARK WA 6017 - AUSTRALIA - - 44-E4-D9 (hex) CISCO SYSTEMS, INC. - 44E4D9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 44-E8-A5 (hex) Myreka Technologies Sdn. Bhd. - 44E8A5 (base 16) Myreka Technologies Sdn. Bhd. - 2-13, JALAN MAYANG PASIR 1, - KOMPLEKS MAYANG MALL - Bayan Baru Penang 11950 - MALAYSIA - - 44-E9-DD (hex) SAGEMCOM SAS - 44E9DD (base 16) SAGEMCOM SAS - 250 route de l'Empereur - RUEIL MALMAISON CEDEX Hauts de Seine 92848 - FRANCE - - 44-ED-57 (hex) Longicorn, inc. - 44ED57 (base 16) Longicorn, inc. - Rm1001-2, 10F, Byuksan Digital Valley1 - 212-16, Guro-3Dong, Guro-Gu - Seoul 152-775 - KOREA, REPUBLIC OF - - 44-EE-30 (hex) Budelmann Elektronik GmbH - 44EE30 (base 16) Budelmann Elektronik GmbH - Von-Renesse-Weg 60 - Muenster North Rhine-Westphalia 48163 - GERMANY - - 44-F4-36 (hex) zte corporation - 44F436 (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road - shenzhen guangdong 518057 - CHINA - - 44-F4-59 (hex) Samsung Electronics - 44F459 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 44-F4-77 (hex) Juniper Networks - 44F477 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 44-F8-49 (hex) Union Pacific Railroad - 44F849 (base 16) Union Pacific Railroad - 1400 Douglas St. STOP 0610 - Omaha NE 68179 - UNITED STATES - - 44-FB-42 (hex) Apple - 44FB42 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 48-02-2A (hex) B-Link Electronic Limited - 48022A (base 16) B-Link Electronic Limited - NO 268,FuQian Rd, JuTang Community,GuanLan town BaoAn district,ShenZhen, 518110,China - Shen Zhen Guang Dong 518110 - CHINA - - 48-03-62 (hex) DESAY ELECTRONICS(HUIZHOU)CO.,LTD - 480362 (base 16) DESAY ELECTRONICS(HUIZHOU)CO.,LTD - BuildingA,No.3 Desay Industrial Zone - Huizhou Guangdong 516029 - CHINA - - 48-06-6A (hex) Tempered Networks, Inc. - 48066A (base 16) Tempered Networks, Inc. - 100 West Harrison St - South Tower, Suite 370 - Seattle WA 98119 - UNITED STATES - - 48-0C-49 (hex) NAKAYO TELECOMMUNICATIONS,INC - 480C49 (base 16) NAKAYO TELECOMMUNICATIONS,INC - 165 - Higashiomuro-machi - Maebashi-shi Gunma 379-2105 - JAPAN - - 48-0F-CF (hex) Hewlett Packard - 480FCF (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Tx 77070 - UNITED STATES - - 48-12-49 (hex) Luxcom Technologies Inc. - 481249 (base 16) Luxcom Technologies Inc. - 102 Walgreen Road - Ottawa Ontario K0A 1L0 - CANADA - - 48-13-F3 (hex) BBK Electronics Corp., Ltd. - 4813F3 (base 16) BBK Electronics Corp., Ltd. - BBK Road,Wusha,Chang¡¯an - Dongguan Guangdong 523860 - CHINA - - 48-17-4C (hex) MicroPower technologies - 48174C (base 16) MicroPower technologies - 4225 Executive Sq. - Suite 430 - La Jolla California 92037 - UNITED STATES - - 48-18-42 (hex) Shanghai Winaas Co. Equipment Co. Ltd. - 481842 (base 16) Shanghai Winaas Co. Equipment Co. Ltd. - 8F Building A, WanDa Square - 18 Guobin Rd. Yangpu District - Shanghai 200433 - CHINA - - 48-1A-84 (hex) Pointer Telocation Ltd - 481A84 (base 16) Pointer Telocation Ltd - 14 Hamelacha Street, - Rosh Ha’ayin Israel 48091 - ISRAEL - - 48-1B-D2 (hex) Intron Scientific co., ltd. - 481BD2 (base 16) Intron Scientific co., ltd. - 6F., NO. 136,Sec 2,Keelung Rd., Da-an district - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - 48-1D-70 (hex) Cisco SPVTG - 481D70 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 48-26-E8 (hex) Tek-Air Systems, Inc. - 4826E8 (base 16) Tek-Air Systems, Inc. - 41 Eagle Road - Danbury CT 06810 - UNITED STATES - - 48-28-2F (hex) ZTE Corporation - 48282F (base 16) ZTE Corporation - 12/F.,R&D building,kejinan Road - Shenzhen Guangdong 518057 - CHINA - - 48-2C-EA (hex) Motorola Inc Business Light Radios - 482CEA (base 16) Motorola Inc Business Light Radios - 8000 W Sunrise Boulevard - Plantation Florida 33324 - UNITED STATES - - 48-33-DD (hex) ZENNIO AVANCE Y TECNOLOGIA, S.L. - 4833DD (base 16) ZENNIO AVANCE Y TECNOLOGIA, S.L. - RIO JARAMA 132 NAVE P8.11 - TOLEDO 45007 - SPAIN - - 48-34-3D (hex) IEP GmbH - 48343D (base 16) IEP GmbH - Am Pferdemarkt 9c - Langenhagen Niedersachsen 30853 - GERMANY - - 48-3D-32 (hex) Syscor Controls & Automation - 483D32 (base 16) Syscor Controls & Automation - 201-60 Bastion Sq - Victoria BC V8W 1J2 - CANADA - - 48-43-7C (hex) Apple - 48437C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 48-44-87 (hex) Cisco SPVTG - 484487 (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - MS 4.T.607 - Lawrenceville GA 30044 - UNITED STATES - - 48-44-F7 (hex) Samsung Electronics Co., LTD - 4844F7 (base 16) Samsung Electronics Co., LTD - 416, Maetan 3-dong, Yeongtong-gu - Suwon Gyeonggi-do 443742 - KOREA, REPUBLIC OF - - 48-46-F1 (hex) Uros Oy - 4846F1 (base 16) Uros Oy - Tutkijantie 4 - OULU 90590 - FINLAND - - 48-46-FB (hex) HUAWEI TECHNOLOGIES CO.,LTD - 4846FB (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - Shenzhen Guangdong 518129 - CHINA - - 48-50-73 (hex) Microsoft Corporation - 485073 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 48-51-B7 (hex) Intel Corporate - 4851B7 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 48-52-61 (hex) SOREEL - 485261 (base 16) SOREEL - 18 Rue de la Gâtine - CHOLET FRANCE 49304 - FRANCE - - 48-54-15 (hex) NET RULES TECNOLOGIA EIRELI - 485415 (base 16) NET RULES TECNOLOGIA EIRELI - Rua Madre Cabrini, 240 - 7°andar - São Paulo São Paulo 04020000 - BRAZIL - - 48-55-5F (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 48555F (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 48-57-DD (hex) Facebook - 4857DD (base 16) Facebook - 1 Hacker Way - Menlo Park California 94025 - UNITED STATES - - 48-59-29 (hex) LG Electronics - 485929 (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul Seoul 153-801 - KOREA, REPUBLIC OF - - 48-5A-3F (hex) WISOL - 485A3F (base 16) WISOL - 373-7, Gajang-dong - Osan-si Gyeonggi-do 447-210 - KOREA, REPUBLIC OF - - 48-5A-B6 (hex) Hon Hai Precision Ind. Co.,Ltd. - 485AB6 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 48-5B-39 (hex) ASUSTek COMPUTER INC. - 485B39 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 48-5D-36 (hex) Verizon - 485D36 (base 16) Verizon - One Verizon Way - Basking Ridge NJ 07030 - UNITED STATES - - 48-5D-60 (hex) Azurewave Technologies, Inc. - 485D60 (base 16) Azurewave Technologies, Inc. - 8F ., No.94, Baozhong Rd. - Xindian City Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 48-60-BC (hex) Apple - 4860BC (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 48-61-A3 (hex) Concern "Axion" JSC - 4861A3 (base 16) Concern "Axion" JSC - 90, M. Gorkogo St. - Izhevsk Udmurt Republic 426000 - RUSSIAN FEDERATION - - 48-62-76 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 486276 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 48-6B-2C (hex) BBK Electronics Corp., Ltd., - 486B2C (base 16) BBK Electronics Corp., Ltd., - #255,BBK Road, - Wusha,Chang'An, DongGuan City,Guangdong, 523860 - CHINA - - 48-6B-91 (hex) Fleetwood Group Inc. - 486B91 (base 16) Fleetwood Group Inc. - 11832 James St - PO Box 1259 - Holland Michigan 49424 - UNITED STATES - - 48-6E-73 (hex) Pica8, Inc. - 486E73 (base 16) Pica8, Inc. - 1032 Elwell Court, Suite 105 - Palo Alto CA 94303 - UNITED STATES - - 48-6E-FB (hex) Davit System Technology Co., Ltd. - 486EFB (base 16) Davit System Technology Co., Ltd. - #304 Hanlim Human Tower, LS-Ro 172 - Gunpo-si Gyeonggi-Do 435-824 - KOREA, REPUBLIC OF - - 48-6F-D2 (hex) StorSimple Inc - 486FD2 (base 16) StorSimple Inc - 2350 Mission College Blvd - Suite #470 - Santa Clara CA 95054 - UNITED STATES - - 48-71-19 (hex) SGB GROUP LTD. - 487119 (base 16) SGB GROUP LTD. - 13F,No.192,Sec.2,Chung Hsin Rd.,Hsin Tien City - Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 48-74-6E (hex) Apple - 48746E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 48-76-04 (hex) PRIVATE - 487604 (base 16) - - 48-82-44 (hex) Life Fitness / Div. of Brunswick - 488244 (base 16) Life Fitness / Div. of Brunswick - 10601 W. Belmont Ave - Franklin Park IL 60131 - UNITED STATES - - 48-86-E8 (hex) Microsoft Corporation - 4886E8 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 48-8E-42 (hex) DIGALOG GmbH - 488E42 (base 16) DIGALOG GmbH - Wattstraße 11-13 - Berlin D-13355 - GERMANY - - 48-91-53 (hex) Weinmann Geräte für Medizin GmbH + Co. KG - 489153 (base 16) Weinmann Geräte für Medizin GmbH + Co. KG - Kronsaalsweg 40 - Hamburg D-22525 - GERMANY - - 48-91-F6 (hex) Shenzhen Reach software technology CO.,LTD - 4891F6 (base 16) Shenzhen Reach software technology CO.,LTD - 6/F,Block B, Kingdee Software park,#2,Keji 12th South Road,Hi-tech Industrial Park,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 48-9B-E2 (hex) SCI Innovations Ltd - 489BE2 (base 16) SCI Innovations Ltd - 16C Hurst End - Folly Lane - Newport Pagnell Buckinghamshire MK16 9HS - UNITED KINGDOM - - 48-9D-18 (hex) Flashbay Limited - 489D18 (base 16) Flashbay Limited - 6 The Fountain Centre - Imperial Wharf - London London SW6 2TW - UNITED KINGDOM - - 48-9D-24 (hex) Research In Motion - 489D24 (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 48-A2-2D (hex) Shenzhen Huaxuchang Telecom Technology Co.,Ltd - 48A22D (base 16) Shenzhen Huaxuchang Telecom Technology Co.,Ltd - Room 501 Block B, Cyber Time Plaza - Tian'an, Futian District - Shenzhen Guangdong 518040 - CHINA - - 48-A2-B7 (hex) Kodofon JSC - 48A2B7 (base 16) Kodofon JSC - 97 Moskovsky pr. - Voronezh 394077 - RUSSIAN FEDERATION - - 48-A6-D2 (hex) GJsun Optical Science and Tech Co.,Ltd. - 48A6D2 (base 16) GJsun Optical Science and Tech Co.,Ltd. - First floor National Information Industry Park D-08 - Chaoyang Road,Qixing District - Guilin Guangxi 541004 - CHINA - - 48-A9-D2 (hex) Wistron Neweb Corp. - 48A9D2 (base 16) Wistron Neweb Corp. - 20 Park Avenue II, Hsin Science Park - HsinChu Taiwan 308 - TAIWAN, PROVINCE OF CHINA - - 48-AA-5D (hex) Store Electronic Systems - 48AA5D (base 16) Store Electronic Systems - 39 rue de montigny - Argenteuil 95100 - FRANCE - - 48-B2-53 (hex) Marketaxess Corporation - 48B253 (base 16) Marketaxess Corporation - 299 Park Avenue - 10th Floor - New York NY 10171 - UNITED STATES - - 48-B5-A7 (hex) Glory Horse Industries Ltd. - 48B5A7 (base 16) Glory Horse Industries Ltd. - Woekshop 8, 4/F., World Wide Industrial Centre, - No. 43-47, Shan Mei Street, Fotan, - Shatin, N.T. HKG - HONG KONG - - 48-B8-DE (hex) HOMEWINS TECHNOLOGY CO.,LTD. - 48B8DE (base 16) HOMEWINS TECHNOLOGY CO.,LTD. - 10F-1, NO. 122, QIAOHE RD., - ZHONGHE DIST., - NEW TAIPEI CITY, 235 - TAIWAN, PROVINCE OF CHINA - - 48-B9-77 (hex) PulseOn Oy - 48B977 (base 16) PulseOn Oy - Tekniikantie 12 - ESPOO Uusimaa 02150 - FINLAND - - 48-B9-C2 (hex) Teletics Inc. - 48B9C2 (base 16) Teletics Inc. - 103 Edgevalley Close NW - Calgary AB T3A 5E9 - CANADA - - 48-BE-2D (hex) Symanitron - 48BE2D (base 16) Symanitron - Ap.103, 17 Rudnevka str.,111674 - Barklay Street 6-3, 121087 - Moscow - RUSSIAN FEDERATION - - 48-C0-93 (hex) Xirrus, Inc. - 48C093 (base 16) Xirrus, Inc. - 2101 Corporate Center Dr. - Thousand Oaks CA 91320 - UNITED STATES - - 48-C1-AC (hex) PLANTRONICS, INC. - 48C1AC (base 16) PLANTRONICS, INC. - 345 ENCINAL STREET - SANTA CRUZ CALIFORNIA 95060 - UNITED STATES - - 48-C8-62 (hex) Simo Wireless,Inc. - 48C862 (base 16) Simo Wireless,Inc. - 326#,Building 4,Zhongxing Industrial Park,Chuangye - Shenzhen Guangdong 518054 - CHINA - - 48-C8-B6 (hex) SysTec GmbH - 48C8B6 (base 16) SysTec GmbH - Ludwig-Erhard-Strasse 6 - Bergheim-Glessen NRW 50129 - GERMANY - - 48-CB-6E (hex) Cello Electronics (UK) Ltd - 48CB6E (base 16) Cello Electronics (UK) Ltd - Cliff Lodge - Harmby Road - Leyburn North Yorkshire DL8 5NS - UNITED KINGDOM - - 48-D0-CF (hex) Universal Electronics, Inc. - 48D0CF (base 16) Universal Electronics, Inc. - 201 E. Sandpointe Ave - 8th Floor - Santa Ana CA 92707 - UNITED STATES - - 48-D1-8E (hex) Metis Communication Co.,Ltd - 48D18E (base 16) Metis Communication Co.,Ltd - #102-805 Digital Empire2 - YeongTong-Gu Sinwon-Ro 88 - Suwon-Si GyeongGi-Do 443-734 - KOREA, REPUBLIC OF - - 48-D2-24 (hex) Liteon Technology Corporation - 48D224 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo - New Taipei City - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 48-D5-4C (hex) Jeda Networks - 48D54C (base 16) Jeda Networks - 2618 San Miguel Drive - Suite # 408 - Newport Beach Ca. 92660 - UNITED STATES - - 48-D7-05 (hex) Apple - 48D705 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 48-D7-FF (hex) BLANKOM Antennentechnik GmbH - 48D7FF (base 16) BLANKOM Antennentechnik GmbH - Hermann-Petersilge Str. 1 - Bad Blankenburg TH 07422 - GERMANY - - 48-D8-55 (hex) Telvent - 48D855 (base 16) Telvent - P.I. Alcobendas c/ Valgrande. 6 - Alcobendas Madrid 28108 - SPAIN - - 48-D8-FE (hex) ClarIDy Solutions, Inc. - 48D8FE (base 16) ClarIDy Solutions, Inc. - 7F, No.9, ParkAvenue II Rd., Hsinchu Science Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 48-DC-FB (hex) Nokia Corporation - 48DCFB (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 48-DF-1C (hex) Wuhan NEC Fibre Optic Communications industry Co. Ltd - 48DF1C (base 16) Wuhan NEC Fibre Optic Communications industry Co. Ltd - 3rd Road Guanshan, - Wuhan Hubei 430074 - CHINA - - 48-E1-AF (hex) Vity - 48E1AF (base 16) Vity - 180 rue Pierre Landais - Caudan 56 56850 - FRANCE - - 48-E9-F1 (hex) Apple - 48E9F1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 48-EA-63 (hex) Zhejiang Uniview Technologies Co., Ltd. - 48EA63 (base 16) Zhejiang Uniview Technologies Co., Ltd. - Eastcom Building C,Eastcom Avenue - Hangzhou Zhejiang 310053 - CHINA - - 48-EB-30 (hex) ETERNA TECHNOLOGY, INC. - 48EB30 (base 16) ETERNA TECHNOLOGY, INC. - 3939 veselich ave - 317 - los angeles california 90039 - UNITED STATES - - 48-ED-80 (hex) daesung eltec - 48ED80 (base 16) daesung eltec - #509 SJ Technoville, 60-19, Gasan-dong - Geumcheon-gu - Seoul 153-769 - KOREA, REPUBLIC OF - - 48-EE-07 (hex) Silver Palm Technologies LLC - 48EE07 (base 16) Silver Palm Technologies LLC - 9639 DOCTOR PERRY RD STE 123N - IJAMSVILLE Maryland 21754 - UNITED STATES - - 48-EE-0C (hex) D-Link International - 48EE0C (base 16) D-Link International - 1 Internal Business Park, #03-12 - The Synergy - Singapore 609917 - SINGAPORE - - 48-EE-86 (hex) UTStarcom (China) Co.,Ltd - 48EE86 (base 16) UTStarcom (China) Co.,Ltd - 25 Floor,A Block,1#Building,TianZuo International Center, - No.12 Zhong Guancun Sorth Street, - Haidian District BeiJing 100081 - CHINA - - 48-F2-30 (hex) Ubizcore Co.,LTD - 48F230 (base 16) Ubizcore Co.,LTD - Kranz Techno #1420, Sangdaewon 1-dong - Jungwon-gu, Seongnam-si - Seongnam-Si 462-729 - KOREA, REPUBLIC OF - - 48-F3-17 (hex) PRIVATE - 48F317 (base 16) - - 48-F4-7D (hex) TechVision Holding Internation Limited - 48F47D (base 16) TechVision Holding Internation Limited - Offshore Incorporations Centre - P.O. Box 957 - Road Town Tortola VG1110 - VIRGIN ISLANDS, BRITISH - - 48-F7-F1 (hex) Alcatel-Lucent - 48F7F1 (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 48-F8-B3 (hex) Cisco-Linksys, LLC - 48F8B3 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 48-F8-E1 (hex) Alcatel Lucent WT - 48F8E1 (base 16) Alcatel Lucent WT - 600 March Drive - Ottawa Ontario k2k 2e6 - CANADA - - 48-F9-25 (hex) Maestronic - 48F925 (base 16) Maestronic - Futura plaza 2103 - How Ming street 111 - Kwun Tong 88 - HONG KONG - - 48-FC-B8 (hex) Woodstream Corporation - 48FCB8 (base 16) Woodstream Corporation - 69 N. Locust Street - Lititz PA 17543 - UNITED STATES - - 48-FE-EA (hex) HOMA B.V. - 48FEEA (base 16) HOMA B.V. - P.O. Box 545 - Enschede 7500 AM - NETHERLANDS - - 4C-00-82 (hex) Cisco - 4C0082 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 4C-02-2E (hex) CMR KOREA CO., LTD - 4C022E (base 16) CMR KOREA CO., LTD - 6F, J-Tower, 24-5 Bangi-dong, Songpa-Gu - Seoul 138-050 - KOREA, REPUBLIC OF - - 4C-02-89 (hex) LEX COMPUTECH CO., LTD - 4C0289 (base 16) LEX COMPUTECH CO., LTD - 3F, No.77, LI DE St. Chung Ho Dist., - New Taipei City 23556 - TAIWAN, PROVINCE OF CHINA - - 4C-06-8A (hex) Basler Electric Company - 4C068A (base 16) Basler Electric Company - 12570 State Route 143 - Highland IL 62249 - UNITED STATES - - 4C-07-C9 (hex) COMPUTER OFFICE Co.,Ltd. - 4C07C9 (base 16) COMPUTER OFFICE Co.,Ltd. - 1368-10 Muramatsu-cho - Ise-shi Mie-ken 515-0507 - JAPAN - - 4C-09-B4 (hex) zte corporation - 4C09B4 (base 16) zte corporation - 12/F.,R&D building,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - 4C-09-D4 (hex) Arcadyan Technology Corporation - 4C09D4 (base 16) Arcadyan Technology Corporation - 4F, No. 9, Park Avenue II , - Science based Industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 4C-0B-3A (hex) TCT Mobile Limited - 4C0B3A (base 16) TCT Mobile Limited - 5F, C-Tower, No.232, Liangjing Road, - Zhangjiang High-tech Park, Pudong, - Shanghai 201203 - CHINA - - 4C-0B-BE (hex) Microsoft - 4C0BBE (base 16) Microsoft - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 4C-0D-EE (hex) JABIL CIRCUIT (SHANGHAI) LTD. - 4C0DEE (base 16) JABIL CIRCUIT (SHANGHAI) LTD. - FL5-UNIT A2 NO 1528 GUMEI ROAD - SHANGHAI 200233 - CHINA - - 4C-0F-6E (hex) Hon Hai Precision Ind. Co.,Ltd. - 4C0F6E (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 4C-0F-C7 (hex) Earda Electronics Co.,Ltd - 4C0FC7 (base 16) Earda Electronics Co.,Ltd - 5/F,Block 2 East area,Haosheng Industrial Park, - 8 Dengyun Av., Nancun Town, Panyu District, - Guangzhou Guangdong 511400 - CHINA - - 4C-11-BF (hex) ZHEJIANG DAHUA TECHNOLOGY CO.,LTD. - 4C11BF (base 16) ZHEJIANG DAHUA TECHNOLOGY CO.,LTD. - NO.1199 Bin An Road,Binjiang District,HangZhou,P.R.China - HangZhou ZheJiang 310053 - CHINA - - 4C-14-80 (hex) NOREGON SYSTEMS, INC - 4C1480 (base 16) NOREGON SYSTEMS, INC - 100 N. MAIN ST. SUITE 2200 - WINSTON - SALEM NC 27101 - UNITED STATES - - 4C-14-A3 (hex) TCL Technoly Electronics (Huizhou) Co., Ltd. - 4C14A3 (base 16) TCL Technoly Electronics (Huizhou) Co., Ltd. - 19th Zhongkai Hi-tech Development Zone - Huizhou Guangdong 516006 - CHINA - - 4C-16-F1 (hex) zte corporation - 4C16F1 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 4C-17-EB (hex) SAGEMCOM - 4C17EB (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON 92848 - FRANCE - - 4C-1A-3A (hex) PRIMA Research And Production Enterprise Ltd. - 4C1A3A (base 16) PRIMA Research And Production Enterprise Ltd. - 63, Svobody st. - Nizhny Novgorod 603003 - RUSSIAN FEDERATION - - 4C-1A-95 (hex) Novakon Co., Ltd. - 4C1A95 (base 16) Novakon Co., Ltd. - 6F., No. 120, Lane 235, Pao Chiao Road - Xindian Dist - New Taipei City 23145 - TAIWAN, PROVINCE OF CHINA - - 4C-1F-CC (hex) HUAWEI TECHNOLOGIES CO.,LTD - 4C1FCC (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 4C-21-D0 (hex) Sony Mobile Communications AB - 4C21D0 (base 16) Sony Mobile Communications AB - Nya Vattentornet - . - Lund SE 22188 - SWEDEN - - 4C-22-58 (hex) cozybit, Inc. - 4C2258 (base 16) cozybit, Inc. - 605 Market Street - Suite 1350 - San Francisco CA 94105 - UNITED STATES - - 4C-25-78 (hex) Nokia Corporation - 4C2578 (base 16) Nokia Corporation - P.O.Box 86 - SALO 24280 - FINLAND - - 4C-26-E7 (hex) Welgate Co., Ltd. - 4C26E7 (base 16) Welgate Co., Ltd. - 19F, Geopyeong Bldg. 129 - Bongeunsa-ro, Gangnam-gu - Seoul 135726 - KOREA, REPUBLIC OF - - 4C-2C-80 (hex) Beijing Skyway Technologies Co.,Ltd - 4C2C80 (base 16) Beijing Skyway Technologies Co.,Ltd - No.5 Jiangtai Road, - Chaoyang District - Beijing 100015 - CHINA - - 4C-2C-83 (hex) Zhejiang KaNong Network Technology Co.,Ltd. - 4C2C83 (base 16) Zhejiang KaNong Network Technology Co.,Ltd. - Room 633, Building B, ShunFan Technology Park,JingChang Road No.768, YuHang District - Hangzhou Zhejiang 310000 - CHINA - - 4C-2F-9D (hex) ICM Controls - 4C2F9D (base 16) ICM Controls - 7313 William Barry Blvd - North Syracuse NY 13212 - UNITED STATES - - 4C-30-89 (hex) Thales Transportation Systems GmbH - 4C3089 (base 16) Thales Transportation Systems GmbH - Bierweg 2 - Arnstadt Thuringia 99310 - GERMANY - - 4C-32-2D (hex) TELEDATA NETWORKS - 4C322D (base 16) TELEDATA NETWORKS - 10 Hasadnaot Street - HERZLIYA 46120 - ISRAEL - - 4C-32-D9 (hex) M Rutty Holdings Pty. Ltd. - 4C32D9 (base 16) M Rutty Holdings Pty. Ltd. - Unit 1, 4 Beaumont Road - Mount Kuring-Gai New South Wales 2080 - AUSTRALIA - - 4C-34-88 (hex) Intel Corporate - 4C3488 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 4C-39-09 (hex) HPL Electric & Power Private Limited - 4C3909 (base 16) HPL Electric & Power Private Limited - 133, Pace City-1, Sec-37 - Gurgaon Haryana 122001 - INDIA - - 4C-39-10 (hex) Newtek Electronics co., Ltd. - 4C3910 (base 16) Newtek Electronics co., Ltd. - Byucksan-Sunyoung Technopia 1004, - Ojeon-Dong, - Uiwang-City Kyunggi-Do 437-821 - KOREA, REPUBLIC OF - - 4C-3B-74 (hex) VOGTEC(H.K.) Co., Ltd - 4C3B74 (base 16) VOGTEC(H.K.) Co., Ltd - Flat 01, 2/F, On Ning Building, - 425-431 King's Road,North Point - Hong Kong 999077 - CHINA - - 4C-3C-16 (hex) Samsung Electronics Co.,Ltd - 4C3C16 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 4C-48-DA (hex) Beijing Autelan Technology Co.,Ltd - 4C48DA (base 16) Beijing Autelan Technology Co.,Ltd - 1-4F, 3rd Area, 9#Building Zhongguancun Software Park - 8# Dongbeiwang West Road, Haidian District - Beijing 100193 - CHINA - - 4C-4B-68 (hex) Mobile Device, Inc. - 4C4B68 (base 16) Mobile Device, Inc. - 8F-1, No. 145, Sianjheng 9th Rd., - Jhubei City, Hsinchu County 30251 - TAIWAN, PROVINCE OF CHINA - - 4C-4E-35 (hex) Cisco - 4C4E35 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 4C-54-27 (hex) Linepro Sp. z o.o. - 4C5427 (base 16) Linepro Sp. z o.o. - ul. Miedziana 11 - Warszawa mazowieckie 00-835 - POLAND - - 4C-54-99 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 4C5499 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 4C-55-85 (hex) Hamilton Systems - 4C5585 (base 16) Hamilton Systems - 3143 Production Drive - Fairfield OH 45014 - UNITED STATES - - 4C-55-B8 (hex) Turkcell Teknoloji - 4C55B8 (base 16) Turkcell Teknoloji - TUBITAK MAM Teknoloji Serbest Bolgesi Gebze - Kocaeli 41470 - TURKEY - - 4C-55-CC (hex) ACKme Networks Pty Ltd - 4C55CC (base 16) ACKme Networks Pty Ltd - 3/9 Park Rd - Five Dock NSW 2046 - AUSTRALIA - - 4C-5D-CD (hex) Oy Finnish Electric Vehicle Technologies Ltd - 4C5DCD (base 16) Oy Finnish Electric Vehicle Technologies Ltd - Majavantie 10 - TUUSULA FI-04320 - FINLAND - - 4C-5E-0C (hex) Routerboard.com - 4C5E0C (base 16) Routerboard.com - Mikrotikls SIA - Pernavas 46 - Riga LV1009 - LATVIA - - 4C-5F-D2 (hex) Alcatel-Lucent - 4C5FD2 (base 16) Alcatel-Lucent - 777 East Middlefield Road - Mountain View CA 94043 - UNITED STATES - - 4C-60-D5 (hex) airPointe of New Hampshire - 4C60D5 (base 16) airPointe of New Hampshire - 35E Industrial Way - Rochester NH 03867 - UNITED STATES - - 4C-60-DE (hex) NETGEAR - 4C60DE (base 16) NETGEAR - 350 East Plumeria Drive - San Jose California 95134 - UNITED STATES - - 4C-62-55 (hex) SANMINA-SCI SYSTEM DE MEXICO S.A. DE C.V. - 4C6255 (base 16) SANMINA-SCI SYSTEM DE MEXICO S.A. DE C.V. - Carretera Guadalajara-chapala km 15.5 #45 - TLAJOMULCO JALISCO 45640 - MEXICO - - 4C-63-EB (hex) Application Solutions (Electronics and Vision) Ltd - 4C63EB (base 16) Application Solutions (Electronics and Vision) Ltd - The Riverside Centre - Railway Lane - Lewes East Sussex BN7 2AQ - UNITED KINGDOM - - 4C-64-D9 (hex) Guangdong Leawin Group Co., Ltd - 4C64D9 (base 16) Guangdong Leawin Group Co., Ltd - 10/F, Domain Bldg,No.8 Keji Road(E),HiTech Development District, - Shantou Guangdong 515041 - CHINA - - 4C-6E-6E (hex) Comnect Technology CO.,LTD - 4C6E6E (base 16) Comnect Technology CO.,LTD - 7-402, Xinyuan Industrial Park, No.61 - Xinguang Rd.,Xili,Nanshan - Shenzhen Guangdong 518055 - CHINA - - 4C-72-B9 (hex) Pegatron Corporation - 4C72B9 (base 16) Pegatron Corporation - No. 76, Ligong St., Beitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 4C-73-67 (hex) Genius Bytes Software Solutions GmbH - 4C7367 (base 16) Genius Bytes Software Solutions GmbH - Merianstraße 30 - Bochum NRW 44801 - GERMANY - - 4C-73-A5 (hex) KOVE - 4C73A5 (base 16) KOVE - 14 N. Peoria Street - Suite 2H - Chicago IL 60607 - UNITED STATES - - 4C-74-03 (hex) Mundo Reader (bq) - 4C7403 (base 16) Mundo Reader (bq) - c Sofía 10. Polígono Európolis - Las Rozas de Madrid Madrid 28230 - SPAIN - - 4C-76-25 (hex) Dell Inc. - 4C7625 (base 16) Dell Inc. - One Dell way - Round Rock Texas 78682 - UNITED STATES - - 4C-77-4F (hex) Embedded Wireless Labs - 4C774F (base 16) Embedded Wireless Labs - 702 Level 7 Uptown 2 No.2 - Jalan SS21/37 Damansara Uptown - Petaling Jaya Selangor 47400 - MALAYSIA - - 4C-78-97 (hex) Arrowhead Alarm Products Ltd - 4C7897 (base 16) Arrowhead Alarm Products Ltd - 344B Rosedale Road - Albany - Auckland Auckland 0751 - NEW ZEALAND - - 4C-79-BA (hex) Intel Corporate - 4C79BA (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 4C-7C-5F (hex) Apple - 4C7C5F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 4C-7F-62 (hex) Nokia Corporation - 4C7F62 (base 16) Nokia Corporation - Joensuunkatu 7 - P.O.Box 86 - Salo N.A. 24101 - FINLAND - - 4C-80-4F (hex) Armstrong Monitoring Corp - 4C804F (base 16) Armstrong Monitoring Corp - 215 Colonnade Rd - Nepean Ontario K2E 7K3 - CANADA - - 4C-80-93 (hex) Intel Corporate - 4C8093 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 4C-82-CF (hex) Echostar Technologies - 4C82CF (base 16) Echostar Technologies - 94 Inverness Terrace E - Englewood CO 80112 - UNITED STATES - - 4C-83-DE (hex) Cisco SPVTG - 4C83DE (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 4C-8B-30 (hex) Actiontec Electronics, Inc - 4C8B30 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 4C-8B-55 (hex) Grupo Digicon - 4C8B55 (base 16) Grupo Digicon - Rua Nissin Castiel, 640 - Gravataí Rio Grande do Sul 94045420 - BRAZIL - - 4C-8B-EF (hex) Huawei Technologies Co., Ltd - 4C8BEF (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - 4C-8D-79 (hex) Apple - 4C8D79 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 4C-8F-A5 (hex) Jastec - 4C8FA5 (base 16) Jastec - yuna.sa@jastec.co.kr - Yonghee.Kim@jastec.co.kr - Jastec B/D 2F, 92-7 Kumgok-dong, Boondang-gu, Seongnam-city, Kyeongi-Do 463-804 - KOREA, REPUBLIC OF - - 4C-96-14 (hex) Juniper Networks - 4C9614 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 4C-98-EF (hex) Zeo - 4C98EF (base 16) Zeo - 320 Nevada St - 4th Floor - Newton MA 02460 - UNITED STATES - - 4C-9E-80 (hex) KYOKKO ELECTRIC Co., Ltd. - 4C9E80 (base 16) KYOKKO ELECTRIC Co., Ltd. - 5-7-20, Motomachi-dori, Chuo-Ku - Kobe Hyogo 6500022 - JAPAN - - 4C-9E-E4 (hex) Hanyang Navicom Co.,Ltd. - 4C9EE4 (base 16) Hanyang Navicom Co.,Ltd. - 713, Gwanpyeong-dong, Yusung-gu - Daejeon 305-509 - KOREA, REPUBLIC OF - - 4C-9E-FF (hex) ZyXEL Communications Corp - 4C9EFF (base 16) ZyXEL Communications Corp - No. 6 Innovation Road II, Science Park, Hsinchu, Taiwan - Hsichu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 4C-A5-15 (hex) Baikal Electronics JSC - 4CA515 (base 16) Baikal Electronics JSC - Highway Baltic 26 km, BC 'RigaLand", Block B, 3-rd entrance, 2-nd floor. - Krasnogorsk district Moscow region 143421 - RUSSIAN FEDERATION - - 4C-A5-6D (hex) Samsung Electronics Co.,Ltd - 4CA56D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 4C-A7-4B (hex) Alcatel Lucent - 4CA74B (base 16) Alcatel Lucent - Via trento, 30 - Vimercate MB 20059 - ITALY - - 4C-A9-28 (hex) Insensi - 4CA928 (base 16) Insensi - 2025 Broadway, 2CD - New York City New York 10023 - UNITED STATES - - 4C-AA-16 (hex) AzureWave Technologies (Shanghai) Inc. - 4CAA16 (base 16) AzureWave Technologies (Shanghai) Inc. - No.8 Lane 66, Chenbao Road, Malu Town Jiading District - Shanghai 201801 - CHINA - - 4C-AB-33 (hex) KST technology - 4CAB33 (base 16) KST technology - Bangi-dong,Songpa-gu - KST B/D 164-1 - SEOUL Seoul 138-050 - KOREA, REPUBLIC OF - - 4C-AC-0A (hex) ZTE Corporation - 4CAC0A (base 16) ZTE Corporation - 12/F,ZTE R&D Building,Kejinan Road, - Shenzhen Guangdong 518057 - CHINA - - 4C-AE-31 (hex) ShengHai Electronics (Shenzhen) Ltd - 4CAE31 (base 16) ShengHai Electronics (Shenzhen) Ltd - Block 17&18,Hui Ming Ying Industry,YanChuan,SongGang - Baoan County,Shenzhen,china 518105 - Shenzhen Guangdong 518105 - CHINA - - 4C-B1-6C (hex) HUAWEI TECHNOLOGIES CO.,LTD - 4CB16C (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 4C-B1-99 (hex) Apple - 4CB199 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 4C-B4-EA (hex) HRD (S) PTE., LTD. - 4CB4EA (base 16) HRD (S) PTE., LTD. - Lot 7, Block 9, Phase 1, Cavite Eco-Zone, - Rosario Cavite 4106 - PHILIPPINES - - 4C-B7-6D (hex) Novi Security - 4CB76D (base 16) Novi Security - 1434 E 820 N - Orem UT 84097 - UNITED STATES - - 4C-B8-1C (hex) SAM Electronics GmbH - 4CB81C (base 16) SAM Electronics GmbH - Behringstr. 120 - Hamburg 22763 - GERMANY - - 4C-B9-C8 (hex) CONET CO., LTD. - 4CB9C8 (base 16) CONET CO., LTD. - 2-8,HIGASHIJIMA-CHO - ICHINOMIYA AICHI 491-0074 - JAPAN - - 4C-BA-A3 (hex) Bison Electronics Inc. - 4CBAA3 (base 16) Bison Electronics Inc. - 3F., No.28, Lane 583, Rueiguang Rd., Neihu District - Taipei City 11492 - TAIWAN, PROVINCE OF CHINA - - 4C-BB-58 (hex) Chicony Electronics Co., Ltd. - 4CBB58 (base 16) Chicony Electronics Co., Ltd. - No.25, Wugong 6th Rd., Wugu Dist., - New Taipei City 248, 248 - TAIWAN, PROVINCE OF CHINA - - 4C-BC-42 (hex) Shenzhen Hangsheng Electronics Co.,Ltd. - 4CBC42 (base 16) Shenzhen Hangsheng Electronics Co.,Ltd. - Hangsheng Industrial Area, Fuyuan 1st Road,Heping Village - Fuyong Town,Baoan District - Shenzhen City Guangdong 518103 - CHINA - - 4C-BC-A5 (hex) Samsung Electronics Co.,Ltd - 4CBCA5 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 4C-C4-52 (hex) Shang Hai Tyd. Electon Technology Ltd. - 4CC452 (base 16) Shang Hai Tyd. Electon Technology Ltd. - Room No.5,N0.396,GuiLin Road, - Xu Hui District - Shang Hai 200233 - CHINA - - 4C-C6-02 (hex) Radios, Inc. - 4CC602 (base 16) Radios, Inc. - 31355 State Road 46 - Sorrento Florida 32776 - UNITED STATES - - 4C-C9-4F (hex) Alcatel-Lucent - 4CC94F (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 4C-CA-53 (hex) Skyera, Inc. - 4CCA53 (base 16) Skyera, Inc. - 1704 Automation Pkwy - San Jose CA 95131 - UNITED STATES - - 4C-CB-F5 (hex) zte corporation - 4CCBF5 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 4C-CC-34 (hex) Motorola Solutions Inc. - 4CCC34 (base 16) Motorola Solutions Inc. - One Motorola Plaza - Holtsville NY 11742 - UNITED STATES - - 4C-D0-8A (hex) HUMAX.CO.,LTD - 4CD08A (base 16) HUMAX.CO.,LTD - HUMAX Village,216,Hwangsaeul-ro, - Bundang-gu - Seongnam-si Gyeonggi-do 463875 - KOREA, REPUBLIC OF - - 4C-D6-37 (hex) Qsono Electronics Co., Ltd - 4CD637 (base 16) Qsono Electronics Co., Ltd - 2nd Floor,Dingxin Industry park,jiayuan Road,East Lake Development Zone - Wuhan Hubei 430074 - CHINA - - 4C-D7-B6 (hex) Helmer Scientific - 4CD7B6 (base 16) Helmer Scientific - 14400 Bergen Boulevard - Noblesville Indiana 46060 - UNITED STATES - - 4C-D9-C4 (hex) Magneti Marelli Automotive Electronics (Guangzhou) Co. Ltd - 4CD9C4 (base 16) Magneti Marelli Automotive Electronics (Guangzhou) Co. Ltd - Building B10, No.8 Jinghu Road - Xin Hua Town, Huadu Region - Guangzhou Guangdong 510800 - CHINA - - 4C-DF-3D (hex) TEAM ENGINEERS ADVANCE TECHNOLOGIES INDIA PVT LTD - 4CDF3D (base 16) TEAM ENGINEERS ADVANCE TECHNOLOGIES INDIA PVT LTD - A-1/2/A,IDA UPPAL, - UPPAL - HYDERABAD AP 500039 - INDIA - - 4C-E1-BB (hex) Zhuhai HiFocus Technology Co., Ltd. - 4CE1BB (base 16) Zhuhai HiFocus Technology Co., Ltd. - The second floor of the friend industrial park, - jinzhou road, jingding town - zhuhai guangdong 519080 - CHINA - - 4C-E2-F1 (hex) sclak srl - 4CE2F1 (base 16) sclak srl - via borgonuovo 7 - milano mi 20121 - ITALY - - 4C-E6-76 (hex) Buffalo Inc. - 4CE676 (base 16) Buffalo Inc. - AKAMONDORI Bldg., 30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref. 460-8315 - JAPAN - - 4C-E9-33 (hex) RailComm, LLC - 4CE933 (base 16) RailComm, LLC - 1387 Fairport Road - Building 900 - Fairport New York 14450 - UNITED STATES - - 4C-EB-42 (hex) Intel Corporate - 4CEB42 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 4C-ED-DE (hex) Askey Computer Corp - 4CEDDE (base 16) Askey Computer Corp - 10f,no.119,chienkang rd,chung-ho, - TAIPEI 23585 - TAIWAN, PROVINCE OF CHINA - - 4C-EE-B0 (hex) SHC Netzwerktechnik GmbH - 4CEEB0 (base 16) SHC Netzwerktechnik GmbH - Ludwigstrasse 33-37 - Frankfurt am Main Hessen 60327 - GERMANY - - 4C-F0-2E (hex) Vifa Denmark A/S - 4CF02E (base 16) Vifa Denmark A/S - Mariendalsvej 2A - Viborg DK-8800 - DENMARK - - 4C-F2-BF (hex) Cambridge Industries(Group) Co.,Ltd. - 4CF2BF (base 16) Cambridge Industries(Group) Co.,Ltd. - 22 Floor,Qilai Tower;889 Yishan Road - Shanghai 200233 - CHINA - - 4C-F4-5B (hex) Blue Clover Devices - 4CF45B (base 16) Blue Clover Devices - 1001 Bayhill Dr - Ste 200 - San Bruno CA 94066 - UNITED STATES - - 4C-F5-A0 (hex) Scalable Network Technologies Inc - 4CF5A0 (base 16) Scalable Network Technologies Inc - 600 Corporate Pointe - Suite 1200 - Culver City CA 90230 - UNITED STATES - - 4C-F7-37 (hex) SamJi Electronics Co., Ltd - 4CF737 (base 16) SamJi Electronics Co., Ltd - 459-21, Gasan-dong, Gumchun-ku - Seoul 153-803 - KOREA, REPUBLIC OF - - 50-00-8C (hex) Hong Kong Telecommunications (HKT) Limited - 50008C (base 16) Hong Kong Telecommunications (HKT) Limited - 41/F, PCCW Tower, Taikoo Place, - Quarry Bay, - HONG KONG - - 50-01-BB (hex) Samsung Electronics - 5001BB (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 50-05-3D (hex) CyWee Group Ltd - 50053D (base 16) CyWee Group Ltd - 3F, No.28, Lane128 - Jing Ye 1st Road - Taipei 10462 - TAIWAN, PROVINCE OF CHINA - - 50-06-04 (hex) Cisco - 500604 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 50-0B-32 (hex) Foxda Technology Industrial(ShenZhen)Co.,LTD - 500B32 (base 16) Foxda Technology Industrial(ShenZhen)Co.,LTD - 1F of 1st Building&1F-3F of 2nd Building, Foxda Industrial Zone,North of Lanzhu Road,Pingshan New District,Shenzhen City,Guangdong Province,P.R.China - Shenzhen Guangdong 518122 - CHINA - - 50-0E-6D (hex) TrafficCast International - 500E6D (base 16) TrafficCast International - 2801 Coho Street - Suite 100 - Madison WI 53713 - UNITED STATES - - 50-11-EB (hex) SilverNet Ltd - 5011EB (base 16) SilverNet Ltd - 16 Cocran Close - Crownhill - Milton Keynes Bucks MK8 0AJ - UNITED KINGDOM - - 50-14-B5 (hex) Richfit Information Technology Co., Ltd - 5014B5 (base 16) Richfit Information Technology Co., Ltd - Room 1501, Gehua Tower, Suite N0.1, Qinglong lane, - Dongcheng District - Beijing 100007 - CHINA - - 50-17-FF (hex) Cisco - 5017FF (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 50-1A-C5 (hex) Microsoft - 501AC5 (base 16) Microsoft - One Microsoft Way - REDMOND WA 98052 - UNITED STATES - - 50-1C-BF (hex) Cisco - 501CBF (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 50-20-6B (hex) Emerson Climate Technologies Transportation Solutions - 50206B (base 16) Emerson Climate Technologies Transportation Solutions - Axel Kiers Vej 5A - Hoejbjerg 8270 - DENMARK - - 50-22-67 (hex) PixeLINK - 502267 (base 16) PixeLINK - 3030 Conroy Road - Ottawa Ontario K1G 6C2 - CANADA - - 50-25-2B (hex) Nethra Imaging Incorporated - 50252B (base 16) Nethra Imaging Incorporated - 2855 Bowers Ave - Santa Clara CA 95051 - UNITED STATES - - 50-26-90 (hex) Fujitsu Limited - 502690 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - 50-27-C7 (hex) TECHNART Co.,Ltd - 5027C7 (base 16) TECHNART Co.,Ltd - 2-21 Nishiohjicho - Kusatsu Shiga 525-0037 - JAPAN - - 50-29-4D (hex) NANJING IOT SENSOR TECHNOLOGY CO,LTD - 50294D (base 16) NANJING IOT SENSOR TECHNOLOGY CO,LTD - ROOM 422 NO.420 ZHONGHUA ROAD QINHUAI DISTRICT NANJING CITY - Nangjing jiangsu 210000 - CHINA - - 50-2A-7E (hex) Smart electronic GmbH - 502A7E (base 16) Smart electronic GmbH - Industrie Str. 29 - St. Georgen 78112 - GERMANY - - 50-2A-8B (hex) Telekom Research and Development Sdn Bhd - 502A8B (base 16) Telekom Research and Development Sdn Bhd - TMRND Innovation Centre - Lingkaran Teknokrat Timur - Cyberjaya Selangor 63000 - MALAYSIA - - 50-2D-1D (hex) Nokia Corporation - 502D1D (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 50-2D-A2 (hex) Intel Corporate - 502DA2 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 50-2D-F4 (hex) Phytec Messtechnik GmbH - 502DF4 (base 16) Phytec Messtechnik GmbH - Robert-Koch-Straße 39 - Mainz Rheinland-Pfalz 55129 - GERMANY - - 50-2E-5C (hex) HTC Corporation - 502E5C (base 16) HTC Corporation - No. 23, Xinghua Rd, Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - 50-2E-CE (hex) Asahi Electronics Co.,Ltd - 502ECE (base 16) Asahi Electronics Co.,Ltd - 29-25 Kariyado - Kawasaki-shi, Nakahara-ku - Kanagawa-ken 211-0022 - JAPAN - - 50-32-75 (hex) Samsung Electronics Co.,Ltd - 503275 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 50-39-55 (hex) Cisco SPVTG - 503955 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 50-3C-C4 (hex) Lenovo Mobile Communication Technology Ltd. - 503CC4 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road,Information&Optoelectronics Park, - .Torch Hi-tech Industry Development Zone - Xiamen Fujian 361006 - CHINA - - 50-3D-E5 (hex) CISCO SYSTEMS, INC. - 503DE5 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 50-3F-56 (hex) Syncmold Enterprise Corp - 503F56 (base 16) Syncmold Enterprise Corp - 9F., No.168, Jiankang Rd., Zhonghe Dist. - No.168, Jiankang Rd., Zhonghe Dist. - Xinbei City 235 - TAIWAN, PROVINCE OF CHINA - - 50-46-5D (hex) ASUSTek COMPUTER INC. - 50465D (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 50-48-EB (hex) BEIJING HAIHEJINSHENG NETWORK TECHNOLOGY CO. LTD. - 5048EB (base 16) BEIJING HAIHEJINSHENG NETWORK TECHNOLOGY CO. LTD. - RM 701 Unit 2 Huirong Bldg. No.106 Lianhuachi East RD. Xuanwu Dist. Beijing - BEIJING CHINA 100055 - CHINA - - 50-4A-5E (hex) Masimo Corporation - 504A5E (base 16) Masimo Corporation - 40 Parker - Irvine California 92618 - UNITED STATES - - 50-4A-6E (hex) NETGEAR INC., - 504A6E (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 50-4F-94 (hex) Loxone Electronics GmbH - 504F94 (base 16) Loxone Electronics GmbH - Falkensteinstraße 6 - Kollerschlag Upper Austria 4154 - AUSTRIA - - 50-50-2A (hex) Egardia - 50502A (base 16) Egardia - Kleine Landtong 19 - Gorinchem Zuid Holland 4201 HL - NETHERLANDS - - 50-50-65 (hex) TAKT Corporation - 505065 (base 16) TAKT Corporation - 2762-8 - Chino-City Nagano-Pref. 391-0001 - JAPAN - - 50-55-27 (hex) LG Electronics - 505527 (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 50-56-63 (hex) Texas Instruments - 505663 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 50-56-A8 (hex) Jolla Ltd - 5056A8 (base 16) Jolla Ltd - Itaemerenkatu 11-13 - Helsinki 00180 - FINLAND - - 50-56-BF (hex) Samsung Electronics Co.,LTD - 5056BF (base 16) Samsung Electronics Co.,LTD - 129,SamsungRo,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 50-57-A8 (hex) CISCO SYSTEMS, INC. - 5057A8 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 50-58-00 (hex) WyTec International, Inc. - 505800 (base 16) WyTec International, Inc. - 19206 Huebner Rd Suite 202 - San Antonio Texas 78258 - UNITED STATES - - 50-5A-C6 (hex) GUANGDONG SUPER TELECOM CO.,LTD. - 505AC6 (base 16) GUANGDONG SUPER TELECOM CO.,LTD. - 4/F,NO.1025-1027 Gaopu Rd - Guangzhou Guangdong 510663 - CHINA - - 50-60-28 (hex) Xirrus Inc. - 506028 (base 16) Xirrus Inc. - 2101 CORPORATE CENTER DR - Thousand Oaks CALIFORNIA 91320 - UNITED STATES - - 50-61-84 (hex) Avaya, Inc - 506184 (base 16) Avaya, Inc - 211 Mt. Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 50-61-D6 (hex) Indu-Sol GmbH - 5061D6 (base 16) Indu-Sol GmbH - Blumenstr. 3 - Schmölln Thüringen 04626 - GERMANY - - 50-63-13 (hex) Hon Hai Precision Ind. Co.,Ltd. - 506313 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 50-64-41 (hex) Greenlee - 506441 (base 16) Greenlee - 219 S Main St - Dallas TX 76104 - UNITED STATES - - 50-65-F3 (hex) Hewlett Packard - 5065F3 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 50-67-87 (hex) iTellus - 506787 (base 16) iTellus - PO Box 668 - North Hampton New Hampshire 03862 - UNITED STATES - - 50-67-AE (hex) Cisco - 5067AE (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 50-67-F0 (hex) ZyXEL Communications Corporation - 5067F0 (base 16) ZyXEL Communications Corporation - No.6 Innovation Road II, - Science Park, - Hsin-Chu, 22099505 - TAIWAN, PROVINCE OF CHINA - - 50-6A-03 (hex) Netgear - 506A03 (base 16) Netgear - 350 East Plumeria Drive - San Jose CA 95134 - UNITED STATES - - 50-6F-9A (hex) Wi-Fi Alliance - 506F9A (base 16) Wi-Fi Alliance - 10900-B Stonelake Boulevard - Suite126 - Austin TX 78759 - UNITED STATES - - 50-70-E5 (hex) He Shan World Fair Electronics Technology Limited - 5070E5 (base 16) He Shan World Fair Electronics Technology Limited - New Material Base, Gonghe Town - Heshan City - Jiangmen Guangdong 529728 - CHINA - - 50-72-24 (hex) Texas Instruments - 507224 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - 50-72-4D (hex) BEG Brueck Electronic GmbH - 50724D (base 16) BEG Brueck Electronic GmbH - Schlosserstraße 30 - Lindlar Nordrhein-Westfalen 51789 - GERMANY - - 50-76-91 (hex) Tekpea, Inc. - 507691 (base 16) Tekpea, Inc. - 2225 East Bayshore Road - Suite 200 - Palo Alto California 94303 - UNITED STATES - - 50-76-A6 (hex) Ecil Informatica Ind. Com. Ltda - 5076A6 (base 16) Ecil Informatica Ind. Com. Ltda - Av. Araguacema, 388 - Barueri São Paulo 06460-070 - BRAZIL - - 50-79-5B (hex) Interexport Telecomunicaciones S.A. - 50795B (base 16) Interexport Telecomunicaciones S.A. - Cerro Colorado 5240 piso 14 - Santiago Region Metropolitana 8320000 - CHILE - - 50-7D-02 (hex) BIODIT - 507D02 (base 16) BIODIT - Calle Gustave Eiffel 3 - Parque Tecnologico - Paterna Valencia 46980 - SPAIN - - 50-7E-5D (hex) Arcadyan Technology Corporation - 507E5D (base 16) Arcadyan Technology Corporation - 4F, No. 9, Park Avenue II, - Science-based industrial Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 50-85-69 (hex) Samsung Electronics Co.,LTD - 508569 (base 16) Samsung Electronics Co.,LTD - 416,Maetan 3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 50-87-89 (hex) Cisco - 508789 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 50-87-B8 (hex) Nuvyyo Inc - 5087B8 (base 16) Nuvyyo Inc - 1 Smythe Rd - Suite 1 - Carleton Place Ontario K7C4J4 - CANADA - - 50-8A-42 (hex) Uptmate Technology Co., LTD - 508A42 (base 16) Uptmate Technology Co., LTD - 6F., No.5, Jian 1st Rd.,Zhonghe Dist., - New Taipei City 23558 - TAIWAN, PROVINCE OF CHINA - - 50-8A-CB (hex) SHENZHEN MAXMADE TECHNOLOGY CO., LTD. - 508ACB (base 16) SHENZHEN MAXMADE TECHNOLOGY CO., LTD. - Building 3,No.5 Fuqiao Industrial Estate, - Qiaotou,Fuyong,Baoan District - Shenzhen Guangdong 518103 - CHINA - - 50-8C-77 (hex) DIRMEIER Schanktechnik GmbH &Co KG - 508C77 (base 16) DIRMEIER Schanktechnik GmbH &Co KG - Alfons-Goppel-Straße 5 - 92526 Oberviechtach - GERMANY - - 50-8D-6F (hex) CHAHOO Limited - 508D6F (base 16) CHAHOO Limited - B-4thFloor, 631 - Sampyeong-dong - Sungnam Gyeonggi 463-400 - KOREA, REPUBLIC OF - - 50-93-4F (hex) Gradual Tecnologia Ltda. - 50934F (base 16) Gradual Tecnologia Ltda. - Rua Attilio Giaretta, 110 - Itatiba SP 13257-584 - BRAZIL - - 50-97-72 (hex) Westinghouse Digital - 509772 (base 16) Westinghouse Digital - 500 N. State College Blvd. - Suite 1300 - Orange CA 92868 - UNITED STATES - - 50-98-71 (hex) Inventum Technologies Private Limited - 509871 (base 16) Inventum Technologies Private Limited - C-70, Phase 2 Extension - (Hosiery Complex) - NOIDA Uttar Pradesh 201305 - INDIA - - 50-9F-27 (hex) Huawei Technologies Co., Ltd - 509F27 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 50-A0-54 (hex) Actineon - 50A054 (base 16) Actineon - 47751 Fremont Blvd - Fremont California 94538 - UNITED STATES - - 50-A0-BF (hex) Alba Fiber Systems Inc. - 50A0BF (base 16) Alba Fiber Systems Inc. - 265 E. Merrick Rd - Valley Stream NY 11580 - UNITED STATES - - 50-A4-C8 (hex) Samsung Electronics Co.,Ltd - 50A4C8 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 50-A6-E3 (hex) David Clark Company - 50A6E3 (base 16) David Clark Company - 360 Franklin St. - Worcester MA 01615 - UNITED STATES - - 50-A7-15 (hex) Aboundi, Inc. - 50A715 (base 16) Aboundi, Inc. - 4 Bud Way, Unit 10 - Nashua NH 03063 - UNITED STATES - - 50-A7-33 (hex) Ruckus Wireless - 50A733 (base 16) Ruckus Wireless - 880 West Maude Ave - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 50-AB-BF (hex) Hoseo Telecom - 50ABBF (base 16) Hoseo Telecom - 701 ACE Techno Tower 684-1 - Deungchon 3-dong, Gangseo-gu - Seoul 157-721 - KOREA, REPUBLIC OF - - 50-AD-D5 (hex) Dynalec Corporation - 50ADD5 (base 16) Dynalec Corporation - 87 West Main Street - Sodus NY 14551 - UNITED STATES - - 50-AF-73 (hex) Shenzhen Bitland Information Technology Co., Ltd. - 50AF73 (base 16) Shenzhen Bitland Information Technology Co., Ltd. - 1-4F,44 Building,Tanglang Industrial Park and 1-6F,#7 Building,XiLi Tongfuyu Industrial Town,Nanshan District - Shenzhen Guangdong 518055 - CHINA - - 50-B6-95 (hex) Micropoint Biotechnologies,Inc. - 50B695 (base 16) Micropoint Biotechnologies,Inc. - 6F, No.3, Industry 5 Road, Shekou - Shenzhen Guangdong 518067 - CHINA - - 50-B7-C3 (hex) Samsung Electronics CO., LTD - 50B7C3 (base 16) Samsung Electronics CO., LTD - 416, Maetan 3Dong, Yeongtong-Gu - Suwon City, Geyonggi Do, Korea - Suwon Geyonggi 443742 - KOREA, REPUBLIC OF - - 50-B8-88 (hex) wi2be Tecnologia S/A - 50B888 (base 16) wi2be Tecnologia S/A - Rua Manoel Valdomiro de Macedo, 2285 - Barracao B - Curitiba Parana 81170-150 - BRAZIL - - 50-B8-A2 (hex) ImTech Technologies LLC, - 50B8A2 (base 16) ImTech Technologies LLC, - 2101 NE Jack London St - Corvallis Oregon 97330 - UNITED STATES - - 50-BD-5F (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 50BD5F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park - Shennan Road, Nanshan - Shenzhen Guangdong 518057 - CHINA - - 50-C0-06 (hex) Carmanah Signs - 50C006 (base 16) Carmanah Signs - #5 6025 12 Street SE - Calgary Alberta T2H2K1 - CANADA - - 50-C2-71 (hex) SECURETECH INC - 50C271 (base 16) SECURETECH INC - #304, 799 Kwanyang-dong, Dongan-gu, - Anyang-ci Gyunggi-do 431-767 - KOREA, REPUBLIC OF - - 50-C5-8D (hex) Juniper Networks - 50C58D (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 50-C7-BF (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 50C7BF (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - 50-C9-71 (hex) GN Netcom A/S - 50C971 (base 16) GN Netcom A/S - Lautrupbjerg 7 - P.O. Box 99 - Ballerup DK-2750 - DENMARK - - 50-C9-A0 (hex) SKIPPER Electronics AS - 50C9A0 (base 16) SKIPPER Electronics AS - Enebakkvn 150 - Oslo 0612 - NORWAY - - 50-CC-F8 (hex) Samsung Electro Mechanics - 50CCF8 (base 16) Samsung Electro Mechanics - Metan Dong 314, Youngtong Gu - Suwon Kyung-gi Do. 443-743 - KOREA, REPUBLIC OF - - 50-CD-32 (hex) NanJing Chaoran Science & Technology Co.,Ltd. - 50CD32 (base 16) NanJing Chaoran Science & Technology Co.,Ltd. - Block C,Floor 5,Tianzexingwang Building - No. 80. Yunlongshan Road,Jianye District - NanJing City JiangSu Province 210019 - CHINA - - 50-CE-75 (hex) Measy Electronics Ltd - 50CE75 (base 16) Measy Electronics Ltd - #1506, Block B, Hai Song Bldg, Tairan 9th Road - Che Gong Miao, Futian District - Shenzhen Guang Dong 518040 - CHINA - - 50-D2-74 (hex) Steffes Corporation - 50D274 (base 16) Steffes Corporation - 3050 Highway 22 North - Dickinson ND 58601 - UNITED STATES - - 50-D6-D7 (hex) Takahata Precision - 50D6D7 (base 16) Takahata Precision - 4-17-1 Suniyoshi - Kofu Shi Yamanashi 400-0851 - JAPAN - - 50-E0-C7 (hex) TurControlSystme AG - 50E0C7 (base 16) TurControlSystme AG - Geschwister-Scholl-Strasse 7 - Genthin Sachsen-Anhalt 39307 - GERMANY - - 50-E1-4A (hex) PRIVATE - 50E14A (base 16) - - 50-E5-49 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 50E549 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - No.215,Nan-Ping Road, - Pin-Jen City, Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 50-EA-D6 (hex) Apple - 50EAD6 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 50-EB-1A (hex) Brocade Communications Systems, Inc. - 50EB1A (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 50-ED-78 (hex) Changzhou Yongse Infotech Co.,Ltd - 50ED78 (base 16) Changzhou Yongse Infotech Co.,Ltd - No.128 Zhengzhong Rd, Xixiashua Town - Changzhou Jiangsu 213135 - CHINA - - 50-ED-94 (hex) Egatel SL - 50ED94 (base 16) Egatel SL - Parque Tecnologico de Galicia - Edificio Egatel, adv. Ourense, nº 1 - Ourense 32901 - SPAIN - - 50-F0-03 (hex) Open Stack, Inc. - 50F003 (base 16) Open Stack, Inc. - Advanced Research Center #411 - Ya-Tap 68 - Bun-Dang, Seong-Nam Gyung-Gi 463-816 - KOREA, REPUBLIC OF - - 50-F0-D3 (hex) Samsung Electronics Co.,Ltd - 50F0D3 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 50-F4-3C (hex) Leeo Inc - 50F43C (base 16) Leeo Inc - 989 Comercial St - Palo Alto CA 94303 - UNITED STATES - - 50-F5-20 (hex) Samsung Electronics Co.,Ltd - 50F520 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 50-F6-1A (hex) Kunshan JADE Technologies co., Ltd. - 50F61A (base 16) Kunshan JADE Technologies co., Ltd. - 12th Floor, Southern Building, Pudong Software Park,828 Xueyuan Road, Bacheng Town - Kunshan Jiangsu 215311 - CHINA - - 50-FA-AB (hex) L-tek d.o.o. - 50FAAB (base 16) L-tek d.o.o. - Obrtna cesta 18 - Sentjernej 8310 - SLOVENIA - - 50-FC-30 (hex) Treehouse Labs - 50FC30 (base 16) Treehouse Labs - 601 Great Oaks Dr. - Ste. B-103 - Round Rock TX 78681 - UNITED STATES - - 50-FC-9F (hex) Samsung Electronics Co.,Ltd - 50FC9F (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 50-FE-F2 (hex) Sify Technologies Ltd - 50FEF2 (base 16) Sify Technologies Ltd - II floor, TIDEL Park, - 4, Rajiv Gandhi Salai, Taramani p.o - Chennai Tamilnadu 600113 - INDIA - - 54-03-F5 (hex) EBN Technology Corp. - 5403F5 (base 16) EBN Technology Corp. - 10F, No.90, Sec. 1, Sintai 5th Rd. - Sijhih City Taipei County 22102 - TAIWAN, PROVINCE OF CHINA - - 54-04-96 (hex) Gigawave LTD - 540496 (base 16) Gigawave LTD - GIGAWAVE TECHNICAL CENTRE - Earls Colne Business Park - Colchester ESSEX CO62NS - UNITED KINGDOM - - 54-04-A6 (hex) ASUSTek COMPUTER INC. - 5404A6 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 54-05-36 (hex) Vivago Oy - 540536 (base 16) Vivago Oy - Itsehallintokuja 6 - Espoo FI-02600 - FINLAND - - 54-05-5F (hex) Alcatel Lucent - 54055F (base 16) Alcatel Lucent - Via Trento, 30 - Vimercate MB 20059 - ITALY - - 54-09-8D (hex) deister electronic GmbH - 54098D (base 16) deister electronic GmbH - Hermann-Bahlsen-Str. 11 - Barsinghausen Niedersachsen 30890 - GERMANY - - 54-11-2F (hex) Sulzer Pump Solutions Finland Oy - 54112F (base 16) Sulzer Pump Solutions Finland Oy - Lentokentaentie 44 - Lappeenranta FI-53600 - FINLAND - - 54-11-5F (hex) Atamo Pty Ltd - 54115F (base 16) Atamo Pty Ltd - 21 River Road - Bayswater WA 6156 - AUSTRALIA - - 54-14-73 (hex) Wingtech Group (HongKong) Limited - 541473 (base 16) Wingtech Group (HongKong) Limited - FLAT/RM 1903 19/F PODIUM PLAZA 5HANOI ROAD TSIM SHA TSUI - HongKong 999077 - HONG KONG - - 54-1B-5D (hex) Techno-Innov - 541B5D (base 16) Techno-Innov - 35 rue du champ Blanc - Meyzieu Rhône 69330 - FRANCE - - 54-1D-FB (hex) Freestyle Energy Ltd - 541DFB (base 16) Freestyle Energy Ltd - 18-24 Ricketts Road - Mount Waverley Victoria 3149 - AUSTRALIA - - 54-1F-D5 (hex) Advantage Electronics - 541FD5 (base 16) Advantage Electronics - PO Box 407 - Greenwood IN 46143 - UNITED STATES - - 54-20-18 (hex) Tely Labs - 542018 (base 16) Tely Labs - 545 Middlefield Road - Suite 165 - Menlo Park CA 94025 - UNITED STATES - - 54-21-60 (hex) Resolution Products - 542160 (base 16) Resolution Products - 1402 Heggen Street - Hudson WI 54016 - UNITED STATES - - 54-22-F8 (hex) zte corporation - 5422F8 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 54-26-96 (hex) Apple - 542696 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 54-27-1E (hex) AzureWave Technonloies, Inc. - 54271E (base 16) AzureWave Technonloies, Inc. - 8F., No. 94, Baozhong Rd. - Sindian Dist. - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 54-2A-9C (hex) LSY Defense, LLC. - 542A9C (base 16) LSY Defense, LLC. - 4175 Westport Rd. - STE 204 - Louisville Kentucky 40207 - UNITED STATES - - 54-2A-A2 (hex) Alpha Networks Inc. - 542AA2 (base 16) Alpha Networks Inc. - No.8 Li-shing 7th Rd., Science-based Industrial Park - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 54-2C-EA (hex) PROTECTRON - 542CEA (base 16) PROTECTRON - 140 zone industriel - CASABLANCA 18600 - MOROCCO - - 54-2F-89 (hex) Euclid Laboratories, Inc. - 542F89 (base 16) Euclid Laboratories, Inc. - 9151 Arvida Ln - Coral Gables Florida 33156 - UNITED STATES - - 54-31-31 (hex) Raster Vision Ltd - 543131 (base 16) Raster Vision Ltd - Unit 1, Crundalls - Gedges Hill, Matfield - Tonbridge Kent TN12 7EA - UNITED KINGDOM - - 54-35-30 (hex) Hon Hai Precision Ind. Co.,Ltd. - 543530 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 54-35-DF (hex) Symeo GmbH - 5435DF (base 16) Symeo GmbH - Prof.-Messerschmitt-Str. 3 - Neubiberg Bavaria 85579 - GERMANY - - 54-36-9B (hex) 1Verge Internet Technology (Beijing) Co., Ltd. - 54369B (base 16) 1Verge Internet Technology (Beijing) Co., Ltd. - 5th Floor, Sinosteel International Plaza - 8 Haidian Street - Haidian District Beijing - CHINA - - 54-39-68 (hex) Edgewater Networks Inc - 543968 (base 16) Edgewater Networks Inc - 2895 Northwestern Parkway - Santa Clara CA 95051 - UNITED STATES - - 54-39-DF (hex) HUAWEI TECHNOLOGIES CO.,LTD - 5439DF (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - Shenzheng Guodong 518129 - CHINA - - 54-3D-37 (hex) Ruckus Wireless - 543D37 (base 16) Ruckus Wireless - 350 West Java Drive - Sunnyvale CA 94089 - UNITED STATES - - 54-40-AD (hex) Samsung Electronics Co.,Ltd - 5440AD (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 54-42-49 (hex) Sony Corporation - 544249 (base 16) Sony Corporation - Gotenyama Tec. - 5-1-12 Kitashinagawa Shinagawa-ku - Tokyo 141-0001 - JAPAN - - 54-44-08 (hex) Nokia Corporation - 544408 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - 54-46-6B (hex) Shenzhen CZTIC Electronic Technology Co., Ltd - 54466B (base 16) Shenzhen CZTIC Electronic Technology Co., Ltd - Xinghe Building, Zhongxin Road, Shajing Town, Baoan - SHENZHEN GUANGDONG 518104 - CHINA - - 54-4A-00 (hex) Cisco - 544A00 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 54-4A-05 (hex) wenglor sensoric gmbh - 544A05 (base 16) wenglor sensoric gmbh - wenglor Str. 3 - Tettnang 88069 - GERMANY - - 54-4A-16 (hex) Texas Instruments - 544A16 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75093 - UNITED STATES - - 54-51-46 (hex) AMG Systems Ltd. - 545146 (base 16) AMG Systems Ltd. - 3 The Omega Centre - Stratton Business Park - Biggleswade Bedfordshire SG18 8QB - UNITED KINGDOM - - 54-53-ED (hex) Sony Corporation - 5453ED (base 16) Sony Corporation - Gotenyama Tec. - 5-1-12 Kitashinagawa Shinagawa-ku - Tokyo 141-0001 - JAPAN - - 54-54-14 (hex) Digital RF Corea, Inc - 545414 (base 16) Digital RF Corea, Inc - 2 Floor, SeMin B/D, 201, Jangdari-ro - Paldal-gu - Suwon-si Gyeonggi-do 442-833 - KOREA, REPUBLIC OF - - 54-5E-BD (hex) NL Technologies - 545EBD (base 16) NL Technologies - 33 Laird Drive - Toronto ON M4G3S8 - CANADA - - 54-5F-A9 (hex) Teracom Limited - 545FA9 (base 16) Teracom Limited - B-84, Sector - 60, - Noida Uttar Pradesh 201 301 - INDIA - - 54-60-09 (hex) Google Inc - 546009 (base 16) Google Inc - 1600 Amphitheatre Parkway - Mountain View CA 94043 - UNITED STATES - - 54-61-72 (hex) ZODIAC AEROSPACE SAS - 546172 (base 16) ZODIAC AEROSPACE SAS - 61 rue Pierre Curie - PLAISIR Yvelines 78370 - FRANCE - - 54-61-EA (hex) Zaplox AB - 5461EA (base 16) Zaplox AB - Scheelev - Lund Sk 22370 - SWEDEN - - 54-64-D9 (hex) Sagemcom SAS - 5464D9 (base 16) Sagemcom SAS - 250 route de l'Empereur - Rueil Malmaison Cedex Hauts de Seine 92848 - FRANCE - - 54-65-DE (hex) ARRIS Group, Inc. - 5465DE (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 54-72-4F (hex) Apple - 54724F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 54-73-98 (hex) Toyo Electronics Corporation - 547398 (base 16) Toyo Electronics Corporation - 1860-38, Simoakasaka - Kawagoe Saitama 3501155 - JAPAN - - 54-74-E6 (hex) Webtech Wireless - 5474E6 (base 16) Webtech Wireless - 215-4299 Canada Way - Burnaby BC V5G 1H3 - CANADA - - 54-75-D0 (hex) CISCO SYSTEMS, INC. - 5475D0 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 54-78-1A (hex) Cisco - 54781A (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 54-79-75 (hex) Nokia Corporation - 547975 (base 16) Nokia Corporation - Joensuunkatu 7E - P.O. Box 86 - Salo 24101 - FINLAND - - 54-7C-69 (hex) Cisco - 547C69 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 54-7F-54 (hex) INGENICO - 547F54 (base 16) INGENICO - 9, avenue de la gare - BP 25156 - Rovaltain TGV - Valence cedex 9 26958 - FRANCE - - 54-7F-A8 (hex) TELCO systems, s.r.o. - 547FA8 (base 16) TELCO systems, s.r.o. - Zvolenska cesta 20 - Banska Bystrica Slovak republic 974 05 - SLOVAKIA - - 54-7F-EE (hex) CISCO SYSTEMS, INC. - 547FEE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 54-81-AD (hex) Eagle Research Corporation - 5481AD (base 16) Eagle Research Corporation - 4237 State Route 34 - Hurricane West Virginia 25526 - UNITED STATES - - 54-84-7B (hex) Digital Devices GmbH - 54847B (base 16) Digital Devices GmbH - Moewestr 45 A - Muenchen 81827 - GERMANY - - 54-88-0E (hex) Samsung Electro Mechanics co., LTD. - 54880E (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - 54-89-22 (hex) Zelfy Inc - 548922 (base 16) Zelfy Inc - 4655 Old Ironsides Dr, Suite#200 - Santa Clara Ca 95054 - UNITED STATES - - 54-89-98 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 548998 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 54-92-BE (hex) Samsung Electronics Co.,Ltd - 5492BE (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 54-93-59 (hex) SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. - 549359 (base 16) SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. - F 4th ,5th , 6th, No.6 Building, - Jianghao Industrial Park, Bantian, Longgang, - Shenzhen Guangdong 518129 - CHINA - - 54-94-78 (hex) Silvershore Technology Partners - 549478 (base 16) Silvershore Technology Partners - 800 High Street - Suite 101 - Palo Alto CA 94301 - UNITED STATES - - 54-9A-11 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 549A11 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 54-9A-16 (hex) Uzushio Electric Co.,Ltd. - 549A16 (base 16) Uzushio Electric Co.,Ltd. - 105 - Noma - Imabari-city Ehime pref. 7948582 - JAPAN - - 54-9B-12 (hex) Samsung Electronics - 549B12 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 54-9D-85 (hex) EnerAccess inc - 549D85 (base 16) EnerAccess inc - 3154 Le Corbusier Blvd - Laval Quebec H7L 4S8 - CANADA - - 54-9F-13 (hex) Apple - 549F13 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 54-9F-35 (hex) Dell Inc. - 549F35 (base 16) Dell Inc. - One Dell way - Round Rock Texas 78682 - UNITED STATES - - 54-A0-4F (hex) t-mac Technologies Ltd - 54A04F (base 16) t-mac Technologies Ltd - Stand Park - Sheffield Road - Chesterfield Derbyshire S41 8JT - UNITED KINGDOM - - 54-A0-50 (hex) ASUSTek COMPUTER INC. - 54A050 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 54-A2-74 (hex) Cisco Systems - 54A274 (base 16) Cisco Systems - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 54-A3-1B (hex) Shenzhen Linkworld Technology Co,.LTD - 54A31B (base 16) Shenzhen Linkworld Technology Co,.LTD - Room 667-675 , sixth floor , - E-business industrial Park ,No. 1063 ,Rd. Chaguang,Xili,Nanshan district - Shenzhen Guangdong 518055 - CHINA - - 54-A5-1B (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 54A51B (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 54-A5-4B (hex) NSC Communications Siberia Ltd - 54A54B (base 16) NSC Communications Siberia Ltd - Ordjonikidze 38 - Novosibirsk 630099 - RUSSIAN FEDERATION - - 54-A6-19 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd - 54A619 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd - No. 389, Ningqiao Road,Pudong - Jinqiao, - Shanghai 201206 - CHINA - - 54-A9-D4 (hex) Minibar Systems - 54A9D4 (base 16) Minibar Systems - 7340 Westmore Road - Rockville MD 20850 - UNITED STATES - - 54-AE-27 (hex) Apple - 54AE27 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 54-B6-20 (hex) SUHDOL E&C Co.Ltd. - 54B620 (base 16) SUHDOL E&C Co.Ltd. - 920, Ilsan TechnoTown 1141-1, Baekseok-dong, Ilsandong-gu - Goyang-si Gyunggi-do 410-722 - KOREA, REPUBLIC OF - - 54-B7-53 (hex) Hunan Fenghui Yinjia Science And Technology Co.,Ltd - 54B753 (base 16) Hunan Fenghui Yinjia Science And Technology Co.,Ltd - No.15 Lutian Road - Galaxy science and technology park - Changsha Hunan 410205 - CHINA - - 54-B8-0A (hex) D-Link International - 54B80A (base 16) D-Link International - 1 Internal Business Park, #03-12, - The Synergy - 609917 - SINGAPORE - - 54-BE-F7 (hex) PEGATRON CORPORATION - 54BEF7 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 54-C8-0F (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 54C80F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - 54-CD-10 (hex) Panasonic Mobile Communications Co.,Ltd. - 54CD10 (base 16) Panasonic Mobile Communications Co.,Ltd. - 600 Saedo-cho Tsuzuki-ku - Yokohama City Kanagawa 224-8539 - JAPAN - - 54-CD-A7 (hex) Fujian Shenzhou Electronic Co.,Ltd - 54CDA7 (base 16) Fujian Shenzhou Electronic Co.,Ltd - Quanzhou Economical&Technological Development Zone, - QUANZHOU FUJIAN 362005 - CHINA - - 54-CD-EE (hex) ShenZhen Apexis Electronic Co.,Ltd - 54CDEE (base 16) ShenZhen Apexis Electronic Co.,Ltd - 12th floor,Keji BuildiHigng - ShenZhen h-Tech Ind-Park,Nanshan District, - ShenZhen GuangDong 518057 - CHINA - - 54-D0-ED (hex) AXIM Communications - 54D0ED (base 16) AXIM Communications - 1F., No. 5, Aly. 12, Ln. 15, Sec. 6, Sinyi Rd., Sinyi Dist., - Taipei 110 - TAIWAN, PROVINCE OF CHINA - - 54-D1-63 (hex) MAX-TECH,INC - 54D163 (base 16) MAX-TECH,INC - 2F, 26, 2gil, Dujeonggongdan - Seobukgu - Cheonan Chungnam 331957 - KOREA, REPUBLIC OF - - 54-D1-B0 (hex) Universal Laser Systems, Inc - 54D1B0 (base 16) Universal Laser Systems, Inc - 16008 N 81st street - scottsdale az 85260 - UNITED STATES - - 54-D4-6F (hex) Cisco SPVTG - 54D46F (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville GA 30044 - UNITED STATES - - 54-DF-00 (hex) Ulterius Technologies, LLC - 54DF00 (base 16) Ulterius Technologies, LLC - 1625 N. Waterfront Parkway - Suite 250 - Wichita KS 67206 - UNITED STATES - - 54-DF-63 (hex) Intrakey technologies GmbH - 54DF63 (base 16) Intrakey technologies GmbH - Wiener Strasse 114-116 - Dresden Saxony 01219 - GERMANY - - 54-E0-32 (hex) Juniper Networks - 54E032 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 54-E1-40 (hex) INGENICO - 54E140 (base 16) INGENICO - 9 AVENUE DE LA GARE - BP 25156 ROVALTAIN TGV - VALENCE DROME 26958 - FRANCE - - 54-E2-C8 (hex) Dongguan Aoyuan Electronics Technology Co., Ltd - 54E2C8 (base 16) Dongguan Aoyuan Electronics Technology Co., Ltd - Factory A7 Zhen'an Sci-Tech Industrial Park, Chang'an Town, Dongguan City, Guangdong Province, China - Dongguan Guangdong 523863 - CHINA - - 54-E2-E0 (hex) Pace plc - 54E2E0 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - 54-E3-B0 (hex) JVL Industri Elektronik - 54E3B0 (base 16) JVL Industri Elektronik - Blokken 42 - Birkeroed DK-3460 - DENMARK - - 54-E4-3A (hex) Apple, Inc. - 54E43A (base 16) Apple, Inc. - 1 Infinite Loop - cupertino CA 95014 - UNITED STATES - - 54-E4-BD (hex) FN-LINK TECHNOLOGY LIMITED - 54E4BD (base 16) FN-LINK TECHNOLOGY LIMITED - 5th Floor, A Building, Haoye Logistics Park, - Shugang Channel, Bao'an District, - SHENZHEN GUANGDONG 518000 - CHINA - - 54-E6-3F (hex) ShenZhen LingKeWeiEr Technology Co., Ltd. - 54E63F (base 16) ShenZhen LingKeWeiEr Technology Co., Ltd. - Room 625, YiJing Building, MeiLin Rd., FuTian District - ShenZhen GuandDong 518000 - CHINA - - 54-E6-FC (hex) TP-LINK TECHNOLOGIES CO., LTD. - 54E6FC (base 16) TP-LINK TECHNOLOGIES CO., LTD. - 1-6F, Building 2, Pingshandayuan Industrial, South Zone, - Taoyuan Street, Nanshan District, - Shenzhen Guangdong 518000 - CHINA - - 54-EA-A8 (hex) Apple, Inc. - 54EAA8 (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 54-EE-75 (hex) Wistron InfoComm(Kunshan)Co.,Ltd. - 54EE75 (base 16) Wistron InfoComm(Kunshan)Co.,Ltd. - 168# First Avenue,Kunshan Integrated Free Trade Zone,Kunshan,Jiangsu,China - Kunshan Jiangsu 215300 - CHINA - - 54-EF-92 (hex) Shenzhen Elink Technology Co., LTD - 54EF92 (base 16) Shenzhen Elink Technology Co., LTD - A531, Famous, No 168 Bao Yuan Road, - Xixiang, Bao'an District - Shenzhen Guangdong 518000 - CHINA - - 54-F5-B6 (hex) ORIENTAL PACIFIC INTERNATIONAL LIMITED - 54F5B6 (base 16) ORIENTAL PACIFIC INTERNATIONAL LIMITED - 5 ARGUS PLACE - HILLCREST - NORTH SHORE CITY AUCKLAND 0627 - NEW ZEALAND - - 54-F6-66 (hex) Berthold Technologies GmbH and Co.KG - 54F666 (base 16) Berthold Technologies GmbH and Co.KG - Calmbacher Strasse 22 - Bad Wildbad 75323 - GERMANY - - 54-F8-76 (hex) ABB AG - 54F876 (base 16) ABB AG - Trafoweg 4 - Halle / Saale Saxony-Anhalt 06112 - GERMANY - - 54-FA-3E (hex) Samsung Electronics Co.,LTD - 54FA3E (base 16) Samsung Electronics Co.,LTD - 416,Maetan 3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 54-FB-58 (hex) WISEWARE, Lda - 54FB58 (base 16) WISEWARE, Lda - Centro Social e Administrativo da ZIV - Lote 141, R/C - Zona Industrial de Vagos Portugal 3840-385 - PORTUGAL - - 54-FD-BF (hex) Scheidt & Bachmann GmbH - 54FDBF (base 16) Scheidt & Bachmann GmbH - Breite Strasse 132 - Moenchengladbach NRW 41238 - GERMANY - - 54-FF-CF (hex) Mopria Alliance - 54FFCF (base 16) Mopria Alliance - 2400 Camino Ramon, Ste #375 - San Ramon CA 94583 - UNITED STATES - - 58-04-CB (hex) Tianjin Huisun Technology Co.,Ltd. - 5804CB (base 16) Tianjin Huisun Technology Co.,Ltd. - 4/f, Building 3, No 1 Haitai Huake Street (outside Ring Road) - Huayuan New Technology Industrial Park, - Tianjin 300384 - CHINA - - 58-05-28 (hex) LABRIS NETWORKS - 580528 (base 16) LABRIS NETWORKS - Silikon Blok 1 NK 24 Teknokent - ODTU - ANKARA AN 06540 - TURKEY - - 58-05-56 (hex) Elettronica GF S.r.L. - 580556 (base 16) Elettronica GF S.r.L. - Via Vittori, 63 - FAENZA RA 48018 - ITALY - - 58-08-FA (hex) Fiber Optic & telecommunication INC. - 5808FA (base 16) Fiber Optic & telecommunication INC. - 161-4 Kumjeong-Dong, - Kunpo-city Gyeonggi-Do 435-824 - KOREA, REPUBLIC OF - - 58-09-43 (hex) PRIVATE - 580943 (base 16) - - 58-09-E5 (hex) Kivic Inc. - 5809E5 (base 16) Kivic Inc. - 670 Sampyeong-dong, Bundang-gu - #320 B Uspace1 - Seongnam City 463-400 - KOREA, REPUBLIC OF - - 58-0A-20 (hex) Cisco - 580A20 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 58-10-8C (hex) Intelbras - 58108C (base 16) Intelbras - BR 101, km 210, S/N° - São José Santa Catarina 88104800 - BRAZIL - - 58-12-43 (hex) AcSiP Technology Corp. - 581243 (base 16) AcSiP Technology Corp. - 3F., No.22, Dalin Rd., - Taoyuan Taoyuan County 33067 - TAIWAN, PROVINCE OF CHINA - - 58-16-26 (hex) Avaya, Inc - 581626 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 58-17-0C (hex) Sony Ericsson Mobile Communications AB - 58170C (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 58-1C-BD (hex) Affinegy - 581CBD (base 16) Affinegy - 1705 S. Capital of Texas Hwy. Ste 310 - Austin Texas 78746 - UNITED STATES - - 58-1D-91 (hex) Advanced Mobile Telecom co.,ltd. - 581D91 (base 16) Advanced Mobile Telecom co.,ltd. - #608, Yatap Leaders Bldg. 342-1 - Yatap-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-828 - KOREA, REPUBLIC OF - - 58-1F-28 (hex) Huawei Technologies Co., Ltd - 581F28 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 58-1F-67 (hex) Open-m technology limited - 581F67 (base 16) Open-m technology limited - logan century buildding ,No.23 of Hai xiu road - Shenzhen Guangdong 518000 - CHINA - - 58-1F-AA (hex) Apple - 581FAA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 58-1F-EF (hex) Tuttnaer LTD - 581FEF (base 16) Tuttnaer LTD - Har-Tuv B - Beith Shemesh 99000 - ISRAEL - - 58-21-36 (hex) KMB systems, s.r.o. - 582136 (base 16) KMB systems, s.r.o. - Dr. M. Horakove 559 - Liberec Czech Republic 46006 - CZECH REPUBLIC - - 58-23-8C (hex) Technicolor CH USA - 58238C (base 16) Technicolor CH USA - 101 West 103rd Street - INH720 - Indianapolis IN 46290 - UNITED STATES - - 58-2A-F7 (hex) Huawei Technologies Co., Ltd - 582AF7 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - 58-2E-FE (hex) Lighting Science Group - 582EFE (base 16) Lighting Science Group - 1227 South Patrick Drive - Satellite Beach FL 32937 - UNITED STATES - - 58-2F-42 (hex) Universal Electric Corporation - 582F42 (base 16) Universal Electric Corporation - 168 Georgetown Road - Canonsburg PA 15317 - UNITED STATES - - 58-34-3B (hex) Glovast Technology Ltd. - 58343B (base 16) Glovast Technology Ltd. - 6F., No.23, JianKang Rd., SongShan Dist., - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - 58-35-D9 (hex) CISCO SYSTEMS, INC. - 5835D9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 58-3C-C6 (hex) Omneality Ltd. - 583CC6 (base 16) Omneality Ltd. - 10B Glossop Road - Sanderstead - South Croydon Surrey CR2 0PU - UNITED KINGDOM - - 58-3F-54 (hex) LG Electronics (Mobile Communications) - 583F54 (base 16) LG Electronics (Mobile Communications) - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 58-42-E4 (hex) Sigma International General Medical Apparatus, LLC. - 5842E4 (base 16) Sigma International General Medical Apparatus, LLC. - 711 Park Avenue - Medina NY 14103 - UNITED STATES - - 58-46-8F (hex) Koncar Electronics and Informatics - 58468F (base 16) Koncar Electronics and Informatics - Fallerovo setaliste 22 - Zagreb Drvinje 10000 - CROATIA - - 58-46-E1 (hex) Baxter Healthcare - 5846E1 (base 16) Baxter Healthcare - 25212 W. Illinois Route 120 - Round Lake IL 60073 - UNITED STATES - - 58-47-04 (hex) Shenzhen Webridge Technology Co.,Ltd - 584704 (base 16) Shenzhen Webridge Technology Co.,Ltd - B2-22/F Chinese Technology Development Institute, High South Road, Nanshan District, Shenzhen, China - Shenzhen Guangdong 518000 - CHINA - - 58-48-C0 (hex) COFLEC - 5848C0 (base 16) COFLEC - Parc d'activités du moulin de Massy - 7 rue du Saule Trapu - MASSY 91300 - FRANCE - - 58-49-3B (hex) Palo Alto Networks - 58493B (base 16) Palo Alto Networks - 4401 Great America Parkway - Santa Clara CA 95054 - UNITED STATES - - 58-49-BA (hex) Chitai Electronic Corp. - 5849BA (base 16) Chitai Electronic Corp. - 5F., No. 1 Lane 123, Pao-Chung Rd., Hsin-Tien City - Taiepi 23144 - TAIWAN, PROVINCE OF CHINA - - 58-4C-19 (hex) Chongqing Guohong Technology Development Company Limited - 584C19 (base 16) Chongqing Guohong Technology Development Company Limited - Rongzhi Building, Science & Technology Venture Center, - No.8 Yuma Road, Nan'an District, - Chongqing 401336 - CHINA - - 58-4C-EE (hex) Digital One Technologies, Limited - 584CEE (base 16) Digital One Technologies, Limited - No.1 Shangdi Xinxi Road - Haidian District - Beijing 100085 - CHINA - - 58-50-76 (hex) Linear Equipamentos Eletronicos SA - 585076 (base 16) Linear Equipamentos Eletronicos SA - Praca Linear 100 - Santa Rita do Sapucai MG 37540000 - BRAZIL - - 58-50-AB (hex) TLS Corporation - 5850AB (base 16) TLS Corporation - 1241 Superior Ave. - Cleveland OH 44114 - UNITED STATES - - 58-50-E6 (hex) Best Buy Corporation - 5850E6 (base 16) Best Buy Corporation - 7601 Penn Ave South - C7 - Richfield MN 55423 - UNITED STATES - - 58-55-CA (hex) Apple - 5855CA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 58-56-E8 (hex) ARRIS Group, Inc. - 5856E8 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 58-57-0D (hex) Danfoss Solar Inverters - 58570D (base 16) Danfoss Solar Inverters - Jyllandsgade 28 - Sønderborg DK-6400 - DENMARK - - 58-63-9A (hex) TPL SYSTEMES - 58639A (base 16) TPL SYSTEMES - ZAE DU PERIGORD NOIR - SARLAT 24200 - FRANCE - - 58-65-E6 (hex) INFOMARK CO., LTD. - 5865E6 (base 16) INFOMARK CO., LTD. - #801, KINS TOWER, JEONGJA-DONG - BUNDANG-GU - SEONGNAM GYOUNGGI 463-847 - KOREA, REPUBLIC OF - - 58-66-BA (hex) Hangzhou H3C Technologies Co., Limited - 5866BA (base 16) Hangzhou H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang, 310053 - CHINA - - 58-67-1A (hex) BARNES&NOBLE.COM - 58671A (base 16) BARNES&NOBLE.COM - 400 HAMILTON AVENUE - SUITE 130 - PALO ALTO CA 94301 - UNITED STATES - - 58-67-7F (hex) Clare Controls Inc. - 58677F (base 16) Clare Controls Inc. - 7519 Pennsylvania Ave - Suite 104 - Sarasota FL 34243 - UNITED STATES - - 58-69-6C (hex) Fujian Ruijie Networks co, ltd - 58696C (base 16) Fujian Ruijie Networks co, ltd - 19# Building,Star-net Science Plaza - Juyuanzhou, 618 Jinshan Road - Fuzhou Fujian 350002 - CHINA - - 58-69-F9 (hex) Fusion Transactive Ltd. - 5869F9 (base 16) Fusion Transactive Ltd. - PO Box 68281 - Newton - Auckland 1145 - NEW ZEALAND - - 58-6A-B1 (hex) Hangzhou H3C Technologies Co., Limited - 586AB1 (base 16) Hangzhou H3C Technologies Co., Limited - 466 Changhe Road, Binjiang District, - Hangzhou, Zhejiang, P.R.China 310052 - CHINA - - 58-6D-8F (hex) Cisco-Linksys, LLC - 586D8F (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 58-6E-D6 (hex) PRIVATE - 586ED6 (base 16) - - 58-70-C6 (hex) Shanghai Xiaoyi Technology Co., Ltd. - 5870C6 (base 16) Shanghai Xiaoyi Technology Co., Ltd. - Shanghai Zhangjiang hi-tech park of Pudong New Area - Chenhui Road No. 88,Building No. 1,Room 303 - Shanghai Shanghai 200120 - CHINA - - 58-75-21 (hex) CJSC RTSoft - 587521 (base 16) CJSC RTSoft - Nikitinskaya str., 3 - Moscow 105037 - RUSSIAN FEDERATION - - 58-76-75 (hex) Beijing ECHO Technologies Co.,Ltd - 587675 (base 16) Beijing ECHO Technologies Co.,Ltd - NO1 Street 4 Shangdi - Haidian District, - BeiJing 100085 - CHINA - - 58-76-C5 (hex) DIGI I'S LTD - 5876C5 (base 16) DIGI I'S LTD - 31, Takahata, Maesawa - Oshu Iwate 029-4204 - JAPAN - - 58-7A-4D (hex) Stonesoft Corporation - 587A4D (base 16) Stonesoft Corporation - Italahdenkatu 22A - Helsinki 00210 - FINLAND - - 58-7B-E9 (hex) AirPro Technology India Pvt. Ltd - 587BE9 (base 16) AirPro Technology India Pvt. Ltd - D30, Gautam Marg, - Nirman Nagar, - Jaipur Rajasthan 302018 - INDIA - - 58-7E-61 (hex) Hisense Electric Co., Ltd - 587E61 (base 16) Hisense Electric Co., Ltd - No. 11 Jiangxi Road - Qingdao Shandong 266071 - CHINA - - 58-7F-66 (hex) Huawei Technologies Co., Ltd - 587F66 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - 58-7F-B7 (hex) SONAR INDUSTRIAL CO., LTD. - 587FB7 (base 16) SONAR INDUSTRIAL CO., LTD. - 29, 29/1, 29/2, MOO.3, THATALAD, - SAMPRAN NAKORN PATHOM 73110 - THAILAND - - 58-7F-C8 (hex) S2M - 587FC8 (base 16) S2M - 2 rue des champs - Saint Marcel 27950 - FRANCE - - 58-84-E4 (hex) IP500 Alliance e.V. - 5884E4 (base 16) IP500 Alliance e.V. - Scharnhorststraße 16 - Berlin 10115 - GERMANY - - 58-85-6E (hex) QSC AG - 58856E (base 16) QSC AG - Mathias-Brueggen-Str. 55 - Köln 50829 - GERMANY - - 58-87-4C (hex) LITE-ON CLEAN ENERGY TECHNOLOGY CORP. - 58874C (base 16) LITE-ON CLEAN ENERGY TECHNOLOGY CORP. - 3F, 392, Ruey Kuang Road, Neihu, - Taipei 11492 - TAIWAN, PROVINCE OF CHINA - - 58-87-E2 (hex) Shenzhen Coship Electronics Co., Ltd. - 5887E2 (base 16) Shenzhen Coship Electronics Co., Ltd. - Rainbow Bldg., North, Hi-Tech Industrial Park - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 58-8D-09 (hex) CISCO SYSTEMS, INC. - 588D09 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 58-91-CF (hex) Intel Corporate - 5891CF (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 58-92-0D (hex) Kinetic Avionics Limited - 58920D (base 16) Kinetic Avionics Limited - Elstree Aerodrome - Hertfordshire WD6 3AW - UNITED KINGDOM - - 58-93-96 (hex) Ruckus Wireless - 589396 (base 16) Ruckus Wireless - 880 West Maude Ave - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 58-94-6B (hex) Intel Corporate - 58946B (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 58-94-CF (hex) Vertex Standard LMR, Inc. - 5894CF (base 16) Vertex Standard LMR, Inc. - 4-8-8 Nakameguro - Meguro-ku Tokyo 153-8644 - JAPAN - - 58-97-1E (hex) Cisco - 58971E (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 58-98-35 (hex) Technicolor - 589835 (base 16) Technicolor - Prins Boudewijnlaan 47 - Edegem B-2650 - BELGIUM - - 58-98-6F (hex) Revolution Display - 58986F (base 16) Revolution Display - 912 Ruberta Ave - Glendale CA 91201 - UNITED STATES - - 58-9B-0B (hex) Shineway Technologies, Inc. - 589B0B (base 16) Shineway Technologies, Inc. - Floor 5, Huanxing Building - No.14 Hua Yuan North Road - Haidian District Beijing 100191 - CHINA - - 58-9C-FC (hex) FreeBSD Foundation - 589CFC (base 16) FreeBSD Foundation - P.O. Box 20247 - Boulder CO 80308-3247 - UNITED STATES - - 58-A2-B5 (hex) LG Electronics - 58A2B5 (base 16) LG Electronics - 60-39, Kasan-dong, Kumchon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 58-A7-6F (hex) iD corporation - 58A76F (base 16) iD corporation - goryokaku bld. 2F - 6-10 - hakodate hokkaido 040-0011 - JAPAN - - 58-A8-39 (hex) Intel Corporate - 58A839 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 58-B0-35 (hex) Apple - 58B035 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 58-B0-D4 (hex) ZuniData Systems Inc. - 58B0D4 (base 16) ZuniData Systems Inc. - 4F-7, No.65, Gaotia 7th Rd, Zhubei City - Hsinchu 302 - TAIWAN, PROVINCE OF CHINA - - 58-B9-61 (hex) SOLEM Electronique - 58B961 (base 16) SOLEM Electronique - ZAE La Plaine - 5, Rue Georges Besse - CLAPIERS 34830 - FRANCE - - 58-B9-E1 (hex) Crystalfontz America, Inc. - 58B9E1 (base 16) Crystalfontz America, Inc. - 12412 E. Saltese Ave. - Spokane Valley WA 99216 - UNITED STATES - - 58-BC-27 (hex) CISCO SYSTEMS, INC. - 58BC27 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 58-BD-A3 (hex) Nintendo Co., Ltd. - 58BDA3 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 58-BD-F9 (hex) Sigrand - 58BDF9 (base 16) Sigrand - UNIT 602 6/F, Causeway Bay Comm Bldg, - 1 Sugar st., Causeway Bay, - Hong Kong 999077 - HONG KONG - - 58-BF-EA (hex) CISCO SYSTEMS, INC. - 58BFEA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 58-C2-32 (hex) NEC Corporation - 58C232 (base 16) NEC Corporation - 1753, Shimonumabe, Nakahara-Ku - Kawasaki Kanagawa 211-8666 - JAPAN - - 58-C3-8B (hex) Samsung Electronics - 58C38B (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 58-CF-4B (hex) Lufkin Industries - 58CF4B (base 16) Lufkin Industries - 811 Willow Oak Drive - Missouri City Texas 77489 - UNITED STATES - - 58-D0-71 (hex) BW Broadcast - 58D071 (base 16) BW Broadcast - Unit 27 IO Centre - 57 Croydon Road - Croydon Surrey CR0 4WQ - UNITED KINGDOM - - 58-D0-8F (hex) IEEE 1904.1 Working Group - 58D08F (base 16) IEEE 1904.1 Working Group - 1351 Redwood Way, - Petaluma CA 94954 - UNITED STATES - - 58-D6-D3 (hex) Dairy Cheq Inc - 58D6D3 (base 16) Dairy Cheq Inc - 60 Baffin Place, Unit 5 - Waterloo Ontario N2V 1Z7 - CANADA - - 58-DB-8D (hex) Fast Co., Ltd. - 58DB8D (base 16) Fast Co., Ltd. - 2-11-1 Iwamotocho - 7th Fl., Herb Kanda Bldg., - Chiyoda-ku Tokyo 101-0032 - JAPAN - - 58-E0-2C (hex) Micro Technic A/S - 58E02C (base 16) Micro Technic A/S - Smedevaenget 5 - Aarup 5560 - DENMARK - - 58-E3-26 (hex) Compass Technologies Inc. - 58E326 (base 16) Compass Technologies Inc. - Unit 1012 C-dong, Woolim Lion's Valley - 168, Gasan Digital 1-ro, Geumcheon-gu - Seoul 153-786 - KOREA, REPUBLIC OF - - 58-E4-76 (hex) CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD - 58E476 (base 16) CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD - 4th Floor,Jiaodajiepu Building,72# Kejierlu Road, - Xi'an Shaanxi Province 710100 - CHINA - - 58-E6-36 (hex) EVRsafe Technologies - 58E636 (base 16) EVRsafe Technologies - 59 North Terrace - Hackney - Adelaide South Australia 5069 - AUSTRALIA - - 58-E7-47 (hex) Deltanet AG - 58E747 (base 16) Deltanet AG - Riedstrasse 8 - Dietikon Zurich 8953 - SWITZERLAND - - 58-E8-08 (hex) AUTONICS CORPORATION - 58E808 (base 16) AUTONICS CORPORATION - 41-5 YONGDANG-DONG - YANGSAN-SI KYEONGNAM 626-847 - KOREA, REPUBLIC OF - - 58-EB-14 (hex) Proteus Digital Health - 58EB14 (base 16) Proteus Digital Health - 2600 Bridge Parkway, Ste 101 - Redwood City California 94065 - UNITED STATES - - 58-EC-E1 (hex) Newport Corporation - 58ECE1 (base 16) Newport Corporation - 1791 Deere Ave. - Irvine California 92606 - UNITED STATES - - 58-EE-CE (hex) Icon Time Systems - 58EECE (base 16) Icon Time Systems - 15201 NW Greenbrier Parkway - Suite A1 - Beaverton OR 97006 - UNITED STATES - - 58-F3-87 (hex) HCCP - 58F387 (base 16) HCCP - Gabriel Metsulaan 4a - EINDHOVEN 5611SP - NETHERLANDS - - 58-F3-9C (hex) Cisco - 58F39C (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 58-F6-7B (hex) Xia Men UnionCore Technology LTD. - 58F67B (base 16) Xia Men UnionCore Technology LTD. - (224)2F Chuangye Building,Xiamen Pioneering Park for Overseas Chinese Scholars - Xia Men Fu Jian 361009 - CHINA - - 58-F6-BF (hex) Kyoto University - 58F6BF (base 16) Kyoto University - Yoshida-Hommachi - Sakyo-ku - Kyoto 6068501 - JAPAN - - 58-F9-8E (hex) SECUDOS GmbH - 58F98E (base 16) SECUDOS GmbH - Rhenus-Platz 2 - Holzwickede NRW 59439 - GERMANY - - 58-FC-DB (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 58FCDB (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 58-FD-20 (hex) Bravida Sakerhet AB - 58FD20 (base 16) Bravida Sakerhet AB - Mikrofonvagen 28 - STOCKHOLM 126 81 - SWEDEN - - 5C-02-6A (hex) Applied Vision Corporation - 5C026A (base 16) Applied Vision Corporation - 2020 Vision Lane - Cuyahoga Falls OH 44223 - UNITED STATES - - 5C-07-6F (hex) Thought Creator - 5C076F (base 16) Thought Creator - Largo da Pirâmide, Nº 3, Sala D - Oeiras Lisboa 2795-156 Linda-a-Velha - PORTUGAL - - 5C-0A-5B (hex) SAMSUNG ELECTRO-MECHANICS CO., LTD. - 5C0A5B (base 16) SAMSUNG ELECTRO-MECHANICS CO., LTD. - 314, Maetan3-Dong, Yeongtong-Gu - Suwon Gyunggi-Do 443-743 - KOREA, REPUBLIC OF - - 5C-0C-BB (hex) CELIZION Inc. - 5C0CBB (base 16) CELIZION Inc. - #206 Lordland EZ Tower, GuMi-Dong 153 BunDang-Gu - SeongNam-Si GyeongGi-Do 463-870 - KOREA, REPUBLIC OF - - 5C-0E-8B (hex) Zebra Technologies Inc - 5C0E8B (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - 5C-11-93 (hex) Seal One AG - 5C1193 (base 16) Seal One AG - Berliner Str. 44 - Frankfurt am Main Hessen 60311 - GERMANY - - 5C-14-37 (hex) Thyssenkrupp Aufzugswerke GmbH - 5C1437 (base 16) Thyssenkrupp Aufzugswerke GmbH - Bernhaeuser Str.45 - Neuhausen a.d.F 73765 - GERMANY - - 5C-15-15 (hex) ADVAN - 5C1515 (base 16) ADVAN - Wisma SMR.JL.Yos Sudarso Kav 89,Lt8. - Suite 104 - Jakarta Jakarta Utara ï¼‘ï¼”ï¼“ï¼•ï¼ - INDONESIA - - 5C-15-E1 (hex) AIDC TECHNOLOGY (S) PTE LTD - 5C15E1 (base 16) AIDC TECHNOLOGY (S) PTE LTD - NO.1 GOLDHILL PLAZA #03-21 - SINGAPORE 308899 - SINGAPORE - - 5C-16-C7 (hex) Big Switch Networks - 5C16C7 (base 16) Big Switch Networks - 100 W Evelyn - STE 110 - Mountain View CA 94041 - UNITED STATES - - 5C-17-37 (hex) I-View Now, LLC. - 5C1737 (base 16) I-View Now, LLC. - 1421 E. Sunset - #2 - Las Vegas NV 89119 - UNITED STATES - - 5C-17-D3 (hex) LGE - 5C17D3 (base 16) LGE - 60-39 , Kasan -dong , Gumcheon-gu. - Seoul 153-801 - KOREA, REPUBLIC OF - - 5C-18-B5 (hex) Talon Communications - 5C18B5 (base 16) Talon Communications - 10636 Scripps Summit Ct. - Suite 209 - San Diego CA 92131 - UNITED STATES - - 5C-20-D0 (hex) Asoni Communication Co., Ltd. - 5C20D0 (base 16) Asoni Communication Co., Ltd. - 21F-1, No.97, Sec. 4, Chongsin Rd. - Sanchong District - New Taipei City 24161 - TAIWAN, PROVINCE OF CHINA - - 5C-22-C4 (hex) DAE EUN ELETRONICS CO., LTD - 5C22C4 (base 16) DAE EUN ELETRONICS CO., LTD - 1029 Hokye-Dong, Dongan-Goo - Anyang-Shi Kyongki-Do 431-080 - KOREA, REPUBLIC OF - - 5C-24-79 (hex) Baltech AG - 5C2479 (base 16) Baltech AG - Lilienthalstrasse 27 - Hallbergmoos 85399 - GERMANY - - 5C-25-4C (hex) Avire Global Pte Ltd - 5C254C (base 16) Avire Global Pte Ltd - 8 Admiralty Street - #05-02 Admirax - Singapore 757438 - SINGAPORE - - 5C-26-0A (hex) Dell Inc. - 5C260A (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 5C-2A-EF (hex) Open Access Pty Ltd - 5C2AEF (base 16) Open Access Pty Ltd - 65 Epping Road - North Ryde 2113 - Sydney NSW 2113 - AUSTRALIA - - 5C-2B-F5 (hex) Vivint - 5C2BF5 (base 16) Vivint - 4931 N 300 W - Provo UT 84604 - UNITED STATES - - 5C-2E-59 (hex) Samsung Electronics Co.,Ltd - 5C2E59 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 5C-2E-D2 (hex) ABC(XiSheng) Electronics Co.,Ltd - 5C2ED2 (base 16) ABC(XiSheng) Electronics Co.,Ltd - No.2 Industrial building, FuRong 7 Road - , XinQiao Area,ShaJing Village, Bao’An - ShenZhen GongDong 518100 - CHINA - - 5C-31-3E (hex) Texas Instruments - 5C313E (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75093 - UNITED STATES - - 5C-33-27 (hex) Spazio Italia srl - 5C3327 (base 16) Spazio Italia srl - Via G.Galilei, 50 - Padenghe sul Garda BS 25080 - ITALY - - 5C-33-5C (hex) Swissphone Telecom AG - 5C335C (base 16) Swissphone Telecom AG - Faelmisstrasse 21 - Samstagern Zurich CH-8833 - SWITZERLAND - - 5C-33-8E (hex) Alpha Networkc Inc. - 5C338E (base 16) Alpha Networkc Inc. - No.8 Li-shing Seventh Road,Science-based - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 5C-35-3B (hex) Compal Broadband Networks Inc. - 5C353B (base 16) Compal Broadband Networks Inc. - 13F., No.1, Taiyuan 1st St. - Zhubei City Hsinchu County 30265 - TAIWAN, PROVINCE OF CHINA - - 5C-35-DA (hex) There Corporation Oy - 5C35DA (base 16) There Corporation Oy - Elimäenkatu 5 - Helsinki 00510 - FINLAND - - 5C-36-B8 (hex) TCL King Electrical Appliances (Huizhou) Ltd. - 5C36B8 (base 16) TCL King Electrical Appliances (Huizhou) Ltd. - 7/F,TCL Multimedia Building, TCL International E City, - No.1001 Zhongshanyuan Road, Nanshan - Shenzhen Guangdong 518052 - CHINA - - 5C-38-E0 (hex) Shanghai Super Electronics Technology Co.,LTD - 5C38E0 (base 16) Shanghai Super Electronics Technology Co.,LTD - 1/F Building A 39 Hongcao Road - Xuhui District - Shanghai 200233 - CHINA - - 5C-3B-35 (hex) Gehirn Inc. - 5C3B35 (base 16) Gehirn Inc. - 1-3-6 Kudan-kita - Seki BLDG. 7F - Chiyoda Tokyo 102-0073 - JAPAN - - 5C-3C-27 (hex) Samsung Electronics Co.,Ltd - 5C3C27 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 5C-40-58 (hex) Jefferson Audio Video Systems, Inc. - 5C4058 (base 16) Jefferson Audio Video Systems, Inc. - 13020 Middletown Industrial Blvd. - Louisville Kentucky 40223 - UNITED STATES - - 5C-41-E7 (hex) Wiatec International Ltd. - 5C41E7 (base 16) Wiatec International Ltd. - Unit 601-605,TaoJinDi Electronic Commercial - Plaza B, TengLong Rd, LongHua - Shenzhen GuangDong 518131 - CHINA - - 5C-43-D2 (hex) HAZEMEYER - 5C43D2 (base 16) HAZEMEYER - ZI Route de Grugies - GAUCHY FRANCE 02430 - FRANCE - - 5C-45-27 (hex) Juniper Networks - 5C4527 (base 16) Juniper Networks - 1133 Innovation Way - Sunnyvale CA 94089 - UNITED STATES - - 5C-4A-26 (hex) Enguity Technology Corp - 5C4A26 (base 16) Enguity Technology Corp - 2020 Pennsylvania Ave., NW - Suite #868 - Washington DC 20006 - UNITED STATES - - 5C-4C-A9 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 5C4CA9 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 5C-50-15 (hex) CISCO SYSTEMS, INC. - 5C5015 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 5C-51-4F (hex) Intel Corporate - 5C514F (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 5C-56-ED (hex) 3pleplay Electronics Private Limited - 5C56ED (base 16) 3pleplay Electronics Private Limited - Plot No 54, Eshwarapuri Colony - Nagaram, Keesara Mandal - Hyderabad Andhra Pradesh 500083 - INDIA - - 5C-57-1A (hex) ARRIS Group, Inc. - 5C571A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 5C-57-C8 (hex) Nokia Corporation - 5C57C8 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90570 - FINLAND - - 5C-59-48 (hex) Apple - 5C5948 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 5C-5B-35 (hex) Mist Systems, Inc. - 5C5B35 (base 16) Mist Systems, Inc. - 4410 El Camino Real - Los Altos CA 94022 - UNITED STATES - - 5C-5B-C2 (hex) YIK Corporation - 5C5BC2 (base 16) YIK Corporation - B-4F,Pangyo Silicon Park 613 - Sampyeong-dong,Bundang-gu - Seongnam-si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - 5C-5E-AB (hex) Juniper Networks - 5C5EAB (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 5C-63-BF (hex) TP-LINK TECHNOLOGIES CO., LTD. - 5C63BF (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) - Central Science and Technology Park,Shennan Rd, - Shenzhen Guangdong 518057 - CHINA - - 5C-69-84 (hex) NUVICO - 5C6984 (base 16) NUVICO - 72-3 Sindae, Silchon - Gwanju Gyeonggi 464-873 - KOREA, REPUBLIC OF - - 5C-6A-7D (hex) KENTKART EGE ELEKTRONIK SAN. VE TIC. LTD. STI. - 5C6A7D (base 16) KENTKART EGE ELEKTRONIK SAN. VE TIC. LTD. STI. - 1370 SK, NO:42/304, - MONTRO IZMIR 35230 - TURKEY - - 5C-6B-32 (hex) Texas Instruments - 5C6B32 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 5C-6B-4F (hex) PRIVATE - 5C6B4F (base 16) - - 5C-6D-20 (hex) Hon Hai Precision Ind. Co.,Ltd. - 5C6D20 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 5C-6F-4F (hex) S.A. SISTEL - 5C6F4F (base 16) S.A. SISTEL - C/SOLSONES, 87 - POL. IND. PLA DE LA BRUGUERA - CASTELLAR DEL VALLES BARCELONA 08211 - SPAIN - - 5C-77-57 (hex) Haivision Network Video - 5C7757 (base 16) Haivision Network Video - 4445 Garand - Montreal QC H4R 2H9 - CANADA - - 5C-7D-5E (hex) Huawei Technologies Co., Ltd - 5C7D5E (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - 5C-84-86 (hex) Brightsource Industries Israel LTD - 5C8486 (base 16) Brightsource Industries Israel LTD - 11 Kiryat Mada st - Amot bldg # 6 - Jerusalem 91450 - ISRAEL - - 5C-86-4A (hex) Secret Labs LLC - 5C864A (base 16) Secret Labs LLC - 315 Bleecker St #308 - New York NY 10014 - UNITED STATES - - 5C-87-78 (hex) Cybertelbridge co.,ltd - 5C8778 (base 16) Cybertelbridge co.,ltd - #901 Acehighend tower 2 - 222-14 Guro-gu Guro-dong - Seoul 152-050 - KOREA, REPUBLIC OF - - 5C-89-9A (hex) TP-LINK TECHNOLOGIES CO.,LTD - 5C899A (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24 (floors 1,3,4,5) and 28 (floors1-4)  - Central Science and Technology Park - Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 - CHINA - - 5C-89-D4 (hex) Beijing Banner Electric Co.,Ltd - 5C89D4 (base 16) Beijing Banner Electric Co.,Ltd - Mail Box 1033,Long cheng Garden - Huilongguan - Chang Ping District beijing 102208 - CHINA - - 5C-8A-38 (hex) Hewlett Packard - 5C8A38 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 5C-8D-4E (hex) Apple - 5C8D4E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 5C-8F-E0 (hex) ARRIS Group, Inc. - 5C8FE0 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - 5C-93-A2 (hex) Liteon Technology Corporation - 5C93A2 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road, ChungHo, TaiPei Hsien - TaiPei TaiWan 23585 - TAIWAN, PROVINCE OF CHINA - - 5C-95-AE (hex) Apple - 5C95AE (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 5C-96-6A (hex) RTNET - 5C966A (base 16) RTNET - 827-64, Yeoksam-dong, Kangnam-Gu - Seoul - 135-080 - KOREA, REPUBLIC OF - - 5C-96-9D (hex) Apple - 5C969D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 5C-97-F3 (hex) Apple - 5C97F3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 5C-9A-D8 (hex) Fujitsu Limited - 5C9AD8 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome,Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - 5C-A1-78 (hex) TableTop Media (dba Ziosk) - 5CA178 (base 16) TableTop Media (dba Ziosk) - 12404 Park Central Drive - Suite 350 - Dallas TX 75251 - UNITED STATES - - 5C-A3-9D (hex) SAMSUNG ELECTRO-MECHANICS CO., LTD. - 5CA39D (base 16) SAMSUNG ELECTRO-MECHANICS CO., LTD. - 314, Maetan3-Dong,Yeongtong-Gu - Suwon Gyunggi-Do 443-743 - KOREA, REPUBLIC OF - - 5C-A3-EB (hex) Lokel s.r.o. - 5CA3EB (base 16) Lokel s.r.o. - Moravska 797/85 - Ostrava Moravskoslezský kraj 700 30 - CZECH REPUBLIC - - 5C-A4-8A (hex) Cisco - 5CA48A (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 5C-AA-FD (hex) Sonos, Inc. - 5CAAFD (base 16) Sonos, Inc. - 223 E. De La Guerra Street - Santa Barbara CA 93101 - UNITED STATES - - 5C-AC-4C (hex) Hon Hai Precision Ind. Co.,Ltd. - 5CAC4C (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 5C-B3-95 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 5CB395 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 5C-B4-3E (hex) HUAWEI TECHNOLOGIES CO.,LTD - 5CB43E (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - 5C-B5-24 (hex) Sony Ericsson Mobile Communications AB - 5CB524 (base 16) Sony Ericsson Mobile Communications AB - Mobilvägen 10 - Lund 22181 - SWEDEN - - 5C-B6-CC (hex) NovaComm Technologies Inc. - 5CB6CC (base 16) NovaComm Technologies Inc. - 902A, #560 Shengxia Rd., ZJ Inno Park - Shanghai 201203 - CHINA - - 5C-B8-CB (hex) Allis Communications - 5CB8CB (base 16) Allis Communications - 10F.-3,No.31-1, Lane 169 Kangning St., - Xizhi Dist., - New Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - 5C-B9-01 (hex) Hewlett Packard - 5CB901 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Tx 77070 - UNITED STATES - - 5C-BD-9E (hex) HONGKONG MIRACLE EAGLE TECHNOLOGY(GROUP) LIMITED - 5CBD9E (base 16) HONGKONG MIRACLE EAGLE TECHNOLOGY(GROUP) LIMITED - FLAT RM 2103, EASEY COMMERCIAL BLDG,253-261 HENNESSY RD, - WANCHAI 999077 - HONG KONG - - 5C-C2-13 (hex) Fr. Sauter AG - 5CC213 (base 16) Fr. Sauter AG - Im Surinam 55 - Basel BS CH4016 - SWITZERLAND - - 5C-C5-D4 (hex) Intel Corporate - 5CC5D4 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 5C-C6-D0 (hex) Skyworth Digital technology(shenzhen)co.ltd. - 5CC6D0 (base 16) Skyworth Digital technology(shenzhen)co.ltd. - 13F,Block A,Skyworth Building,Gaoxin AVE.1.S, - Nanshan District, - ShenZhen GuangDong 518057 - CHINA - - 5C-C9-D3 (hex) PALLADIUM ENERGY ELETRONICA DA AMAZONIA LTDA - 5CC9D3 (base 16) PALLADIUM ENERGY ELETRONICA DA AMAZONIA LTDA - AVENIDA BURITI, 4285 - DISTRITO INDUSTRIAL - MANAUS AMAZONAS 69075-000 - BRAZIL - - 5C-CA-32 (hex) Theben AG - 5CCA32 (base 16) Theben AG - Hohenbergstraße 32 - Haigerloch Baden-Württemberg 72401 - GERMANY - - 5C-CC-FF (hex) Techroutes Network Pvt Ltd - 5CCCFF (base 16) Techroutes Network Pvt Ltd - WW1-SF, Malibu Towne - Sohna Road - Gurgaon Haryana 122002 - INDIA - - 5C-CE-AD (hex) CDYNE Corporation - 5CCEAD (base 16) CDYNE Corporation - 505 Independence Pkwy Ste 300 - Chesapeake VA 23320 - UNITED STATES - - 5C-D1-35 (hex) Xtreme Power Systems - 5CD135 (base 16) Xtreme Power Systems - 2440 Kiowa Blvd. N. #102 - Lake Havasu City AZ 86403 - UNITED STATES - - 5C-D2-E4 (hex) Intel Corporate - 5CD2E4 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 5C-D4-1B (hex) UCZOON Technology Co., LTD - 5CD41B (base 16) UCZOON Technology Co., LTD - 9 th Floor,Pan Gu Plaza,No.27 North 4 th Ring, - Chao Yang District - Beijing Beijing 100029 - CHINA - - 5C-D4-AB (hex) Zektor - 5CD4AB (base 16) Zektor - 12675 Danielson Ct. Ste 401 - Poway CA 92064 - UNITED STATES - - 5C-D6-1F (hex) Qardio, Inc - 5CD61F (base 16) Qardio, Inc - 340 S Lemon Ave #1104F - Walnut California 91789 - UNITED STATES - - 5C-D9-98 (hex) D-Link Corporation - 5CD998 (base 16) D-Link Corporation - No.289, Sinhu 3rd Rd., Neihu District, - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 5C-DA-D4 (hex) Murata Manufacturing Co., Ltd. - 5CDAD4 (base 16) Murata Manufacturing Co., Ltd. - 2288, Oaza-Ohshinohara, Yasu-cho, - Yasu-gun Shiga 520-2393 - JAPAN - - 5C-DC-96 (hex) Arcadyan Technology Corporation - 5CDC96 (base 16) Arcadyan Technology Corporation - No.8, Sec.2, Guangfu Rd., - Hsinchu City 30071, Hsinchu 30071 - TAIWAN, PROVINCE OF CHINA - - 5C-DD-70 (hex) Hangzhou H3C Technologies Co., Limited - 5CDD70 (base 16) Hangzhou H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang 310053 - CHINA - - 5C-E0-C5 (hex) Intel Corporate - 5CE0C5 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 5C-E0-CA (hex) FeiTian United (Beijing) System Technology Co., Ltd. - 5CE0CA (base 16) FeiTian United (Beijing) System Technology Co., Ltd. - 3 Floor, Tower B, Huizhi Tower - No.9 Xueqing Rd - Haidian District Beijing 100085 - CHINA - - 5C-E0-F6 (hex) NIC.br- Nucleo de Informacao e Coordenacao do Ponto BR - 5CE0F6 (base 16) NIC.br- Nucleo de Informacao e Coordenacao do Ponto BR - Av. das Nacoes Unidas, 11541, 7o andar - São Paulo SP 04578-000 - BRAZIL - - 5C-E2-23 (hex) Delphin Technology AG - 5CE223 (base 16) Delphin Technology AG - Lustheide 81 - Bergisch-Gladbach 51427 - GERMANY - - 5C-E2-86 (hex) Nortel Networks - 5CE286 (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - 5C-E2-F4 (hex) AcSiP Technology Corp. - 5CE2F4 (base 16) AcSiP Technology Corp. - 3F., No.22, Dalin Rd. - Taoyuan Taoyuan County 33067 - TAIWAN, PROVINCE OF CHINA - - 5C-E7-BF (hex) New Singularity International Technical Development Co.,Ltd - 5CE7BF (base 16) New Singularity International Technical Development Co.,Ltd - 8F,NorthStar-Ultrapower Tower, - No.13 Beiyuan Road, Chaoyang District, - Beijing 100107 - CHINA - - 5C-E8-EB (hex) Samsung Electronics - 5CE8EB (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 5C-EB-4E (hex) R. STAHL HMI Systems GmbH - 5CEB4E (base 16) R. STAHL HMI Systems GmbH - Im Gewerbegebiet Pesch 14 - Cologne 50767 - GERMANY - - 5C-EB-68 (hex) Cheerstar Technology Co., Ltd - 5CEB68 (base 16) Cheerstar Technology Co., Ltd - 5th Floor,Hongye Industrial Park, - Le Chuk Kok village,West Township, BaoAn - ShenZhen GuangDong 518006 - CHINA - - 5C-EE-79 (hex) Global Digitech Co LTD - 5CEE79 (base 16) Global Digitech Co LTD - 1F., No.25, Aly.56, Ln. 245, Sec. 4, Bade Rd., - Taipei Taiwan 105 - TAIWAN, PROVINCE OF CHINA - - 5C-F2-07 (hex) Speco Technologies - 5CF207 (base 16) Speco Technologies - 200 New Highway - Amityville New York 11701 - UNITED STATES - - 5C-F3-70 (hex) CC&C Technologies, Inc - 5CF370 (base 16) CC&C Technologies, Inc - 8F, 150, Chien I Rd. - Chung Ho 235 - TAIWAN, PROVINCE OF CHINA - - 5C-F3-FC (hex) IBM Corp - 5CF3FC (base 16) IBM Corp - 3039 E Cornwallis Rd - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - 5C-F4-AB (hex) ZyXEL Communications Corp - 5CF4AB (base 16) ZyXEL Communications Corp - No. 6 Innovation Road II, Science Park - Hsichu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 5C-F5-0D (hex) Institute of microelectronic applications - 5CF50D (base 16) Institute of microelectronic applications - Na Valentince 1003/1 - Praha 15000 - CZECH REPUBLIC - - 5C-F5-DA (hex) Apple - 5CF5DA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 5C-F6-DC (hex) Samsung Electronics Co.,LTD - 5CF6DC (base 16) Samsung Electronics Co.,LTD - 416,Maetan 3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 5C-F7-C3 (hex) SYNTECH (HK) TECHNOLOGY LIMITED - 5CF7C3 (base 16) SYNTECH (HK) TECHNOLOGY LIMITED - Unit No. 1, 12/F., Perfect Industrial Building , - 31 Tai Yau Street, San Po Kong - Kowloon, Hong Kong 999077 - HONG KONG - - 5C-F8-A1 (hex) Murata Manufactuaring Co.,Ltd. - 5CF8A1 (base 16) Murata Manufactuaring Co.,Ltd. - 1-10-1 Higashikotari  - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 5C-F9-38 (hex) Apple, Inc - 5CF938 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 5C-F9-6A (hex) Huawei Technologies Co., Ltd - 5CF96A (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 5C-F9-DD (hex) Dell Inc - 5CF9DD (base 16) Dell Inc - One dell Way - Round Rock TX 78782 - UNITED STATES - - 5C-F9-F0 (hex) Atomos Engineering P/L - 5CF9F0 (base 16) Atomos Engineering P/L - 36 Park St - South Melbourne Victoria 3205 - AUSTRALIA - - 5C-FC-66 (hex) Cisco - 5CFC66 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 5C-FF-35 (hex) Wistron Corporation - 5CFF35 (base 16) Wistron Corporation - 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - 5C-FF-FF (hex) Shenzhen Kezhonglong Optoelectronic Technology Co., Ltd - 5CFFFF (base 16) Shenzhen Kezhonglong Optoelectronic Technology Co., Ltd - 3/F, B5 Building, Xinfu Industrial Park, Heping Village - Fuyong Town, Bao'an District - Shenzhen, Guangdong 518101 - CHINA - - 60-02-92 (hex) PEGATRON CORPORATION - 600292 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Beitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 60-02-B4 (hex) Wistron NeWeb Corp. - 6002B4 (base 16) Wistron NeWeb Corp. - No.20 Park Avenue II - Hsinchu Science Park - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 60-03-08 (hex) Apple - 600308 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-03-47 (hex) Billion Electric Co. Ltd. - 600347 (base 16) Billion Electric Co. Ltd. - 8F., No.192, Sec. 2, Zhongxing Rd., - Xindian Dist., - New Taipei City, 231 - TAIWAN, PROVINCE OF CHINA - - 60-04-17 (hex) POSBANK CO.,LTD - 600417 (base 16) POSBANK CO.,LTD - Room 805-808, New T Castle B/D, 429-1 - Gasan-Dong, Geumchen-Gu - Seoul 153-803 - KOREA, REPUBLIC OF - - 60-0F-77 (hex) SilverPlus, Inc - 600F77 (base 16) SilverPlus, Inc - 18 Technology Dr, #143 - Irvine CA 92618 - UNITED STATES - - 60-11-99 (hex) Siama Systems Inc - 601199 (base 16) Siama Systems Inc - 410 Saint-Nicolas Street - Suite 110 - Montreal Quebec H2Y 2P5 - CANADA - - 60-12-83 (hex) Soluciones Tecnologicas para la Salud y el Bienestar SA - 601283 (base 16) Soluciones Tecnologicas para la Salud y el Bienestar SA - Rd. Auguste y Louis Lumiere, 23 nave 13 - Parque Tecnologico de Valencia - Paterna Valencia- CIF ES A 98005978 46980 - SPAIN - - 60-12-8B (hex) CANON INC. - 60128B (base 16) CANON INC. - 30-2 Shimomaruko 3-chome, - Ohta-ku Tokyo 146-8501 - JAPAN - - 60-15-C7 (hex) IdaTech - 6015C7 (base 16) IdaTech - 63065 NE 18th St. - Bend OR 97701 - UNITED STATES - - 60-19-0C (hex) RRAMAC - 60190C (base 16) RRAMAC - 15400 Medina Rd - Plymouth MN 55447 - UNITED STATES - - 60-19-29 (hex) VOLTRONIC POWER TECHNOLOGY(SHENZHEN) CORP. - 601929 (base 16) VOLTRONIC POWER TECHNOLOGY(SHENZHEN) CORP. - 1-4F,Building 5,YuSheng Industrial Park,No.467,Section Xixiang - National Highway 107,Xixiang,Bao An District - Shenzhen 518000 - CHINA - - 60-19-70 (hex) HUIZHOU QIAOXING ELECTRONICS TECHNOLOGY CO., LTD. - 601970 (base 16) HUIZHOU QIAOXING ELECTRONICS TECHNOLOGY CO., LTD. - Room -611, TianAn High-Tech Plaza II , Futian District, Shenzhen, China - Shenzhen Guangdong 518040 - CHINA - - 60-1D-0F (hex) Midnite Solar - 601D0F (base 16) Midnite Solar - 17722 67th Ave NE #C - Arlington WA 98223 - UNITED STATES - - 60-1E-02 (hex) EltexAlatau - 601E02 (base 16) EltexAlatau - Ibragimova 9 - Almaty Province 050032 - KAZAKHSTAN - - 60-21-03 (hex) STCUBE.INC - 602103 (base 16) STCUBE.INC - TLI Building 6th floor, 195 - Yeosu-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-100 - KOREA, REPUBLIC OF - - 60-21-C0 (hex) Murata Manufactuaring Co.,Ltd. - 6021C0 (base 16) Murata Manufactuaring Co.,Ltd. - 1-10-1 Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 60-24-C1 (hex) Jiangsu Zhongxun Electronic Technology Co., Ltd - 6024C1 (base 16) Jiangsu Zhongxun Electronic Technology Co., Ltd - tangshu road #8 - dingshu town - yixing jiangsu 214221 - CHINA - - 60-2A-54 (hex) CardioTek B.V. - 602A54 (base 16) CardioTek B.V. - Amerikalaan 70 - Maastricht Airport Limburg 6199AE - NETHERLANDS - - 60-2A-D0 (hex) Cisco SPVTG - 602AD0 (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville GA 30017 - UNITED STATES - - 60-32-F0 (hex) Mplus technology - 6032F0 (base 16) Mplus technology - #201 Gayang Dong, Gangsea Gu - Seoul 157-793 - KOREA, REPUBLIC OF - - 60-33-4B (hex) Apple - 60334B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-35-53 (hex) Buwon Technology - 603553 (base 16) Buwon Technology - (Cunuitechnopark 102-1507) 200-1,Chunui-dong - Wonmi-gu - Buchon-si Gyeinggi-do 420-857 - KOREA, REPUBLIC OF - - 60-36-96 (hex) The Sapling Company - 603696 (base 16) The Sapling Company - 1633 Republic Rd - Huntingdon Valley PA 19006 - UNITED STATES - - 60-36-DD (hex) Intel Corporate - 6036DD (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 60-38-0E (hex) Alps Electric Co., - 60380E (base 16) Alps Electric Co., - 1-2-1, Okinouchi - Soma-city Fukushima 976-8501 - JAPAN - - 60-39-1F (hex) ABB Ltd - 60391F (base 16) ABB Ltd - Distribution Automation - Maneja - Vadodara Gujarat 390013 - INDIA - - 60-3F-C5 (hex) COX CO., LTD - 603FC5 (base 16) COX CO., LTD - 904HO, ACE TWIN TOWER 1-CHA - 212-1 GURO-DONG, GURO-GU - SEOUL 152-779 - KOREA, REPUBLIC OF - - 60-44-F5 (hex) Easy Digital Ltd. - 6044F5 (base 16) Easy Digital Ltd. - Victoria Buildings, 1 Haddington Road - Dublin 4 - IRELAND - - 60-45-5E (hex) Liptel s.r.o. - 60455E (base 16) Liptel s.r.o. - Hradna 338 - Liptovsky Hradok 03301 - SLOVAKIA - - 60-45-BD (hex) Microsoft - 6045BD (base 16) Microsoft - 1 Microsoft Way - Studio -B/3936 - Redmond Washington 98023 - UNITED STATES - - 60-46-16 (hex) XIAMEN VANN INTELLIGENT CO., LTD - 604616 (base 16) XIAMEN VANN INTELLIGENT CO., LTD - UNIT 101£¬NO.28 GUANRI RD., SOFTWARE PARK ¢ò - XIAMEN FUJIAN 361009 - CHINA - - 60-47-D4 (hex) FORICS Electronic Technology Co., Ltd. - 6047D4 (base 16) FORICS Electronic Technology Co., Ltd. - BLD 2A, No 1588, Lianhang Rd - Minhang District, - Shanghai 201112 - CHINA - - 60-48-26 (hex) Newbridge Technologies Int. Ltd. - 604826 (base 16) Newbridge Technologies Int. Ltd. - 35/F Central Plaza - 18 Harbour Road Wanchai, - Hong Kong - CHINA - - 60-4A-1C (hex) SUYIN Corporation - 604A1C (base 16) SUYIN Corporation - No.377,Fude 1st Rd - Xizhi City - Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 60-50-C1 (hex) Kinetek Sports - 6050C1 (base 16) Kinetek Sports - 16885 Via Del Campo Ct. - Suite 207 - San Diego Ca 92127 - UNITED STATES - - 60-51-2C (hex) TCT mobile limited - 60512C (base 16) TCT mobile limited - No.86,Hechang 7th West Road, Zhongkai Hi-tech Development District, - Hui Zhou, Guang Dong - Hui Zhou Guang Dong 516006 - CHINA - - 60-52-D0 (hex) FACTS Engineering - 6052D0 (base 16) FACTS Engineering - 8049 Photonics Drive - New Port Richey FL 34655 - UNITED STATES - - 60-54-64 (hex) Eyedro Green Solutions Inc. - 605464 (base 16) Eyedro Green Solutions Inc. - 151 Charles St W - Suite 100 - Kitchener Ontario N2G1H6 - CANADA - - 60-57-18 (hex) Intel Corporate - 605718 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 60-5B-B4 (hex) AzureWave Technologies, Inc. - 605BB4 (base 16) AzureWave Technologies, Inc. - 8F., No. 94, Baozhong Rd. - Xindian Dist. - New Taipei City Taiwan 231 - TAIWAN, PROVINCE OF CHINA - - 60-60-1F (hex) SZ DJI TECHNOLOGY CO.,LTD - 60601F (base 16) SZ DJI TECHNOLOGY CO.,LTD - 6/F,HKUST SZ IER Bldg,9 Yuexing 1st Rd - Hi-Tech Park(South),Nanshan District - shenzhen guangdong 518057 - CHINA - - 60-63-FD (hex) Transcend Communication Beijing Co.,Ltd. - 6063FD (base 16) Transcend Communication Beijing Co.,Ltd. - A-6,Keshi plaza,28#,Information Road - Haidian Dist, - Beijing 100085 - CHINA - - 60-64-A1 (hex) RADiflow Ltd. - 6064A1 (base 16) RADiflow Ltd. - 31 Habarzel St. - Tel Aviv 6971045 - ISRAEL - - 60-67-20 (hex) Intel Corporate - 606720 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 60-69-44 (hex) Apple, Inc - 606944 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-69-9B (hex) isepos GmbH - 60699B (base 16) isepos GmbH - Wannweiler Str. 12 - Kirchentellinsfurt 72138 - GERMANY - - 60-6B-BD (hex) Samsung Electronics Co., LTD - 606BBD (base 16) Samsung Electronics Co., LTD - 416, Maetan-3dong, Yeongtong-gu - Suwon-si Gyeonggi-do 443742 - KOREA, REPUBLIC OF - - 60-6C-66 (hex) Intel Corporate - 606C66 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 60-6D-C7 (hex) Hon Hai Precision Ind. Co.,Ltd. - 606DC7 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District,Chongqing,China - Chongqing Chongqing 401332 - CHINA - - 60-73-5C (hex) Cisco - 60735C (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 60-74-8D (hex) Atmaca Elektronik - 60748D (base 16) Atmaca Elektronik - Namik Kemal Mahallesi 177, Sokak No:2 - Istanbul Esenyurt 34510 - TURKEY - - 60-76-88 (hex) Velodyne - 607688 (base 16) Velodyne - 345 Digital Drive - Morgan Hill CA 95037 - UNITED STATES - - 60-77-E2 (hex) Samsung Electronics Co.,Ltd - 6077E2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 60-81-2B (hex) Custom Control Concepts - 60812B (base 16) Custom Control Concepts - 6020 S 190th ST - Kent Washington 98032 - UNITED STATES - - 60-81-F9 (hex) Helium Systems, Inc - 6081F9 (base 16) Helium Systems, Inc - 717 Market Street - Ste 100 - San Francisco CA 94102 - UNITED STATES - - 60-83-B2 (hex) GkWare e.K. - 6083B2 (base 16) GkWare e.K. - Hatzper Str. 172B - Essen NRW 45149 - GERMANY - - 60-84-3B (hex) Soladigm, Inc. - 60843B (base 16) Soladigm, Inc. - 195. S Milpitas Blvd - Milpitas CA 95035 - UNITED STATES - - 60-86-45 (hex) Avery Weigh-Tronix, LLC - 608645 (base 16) Avery Weigh-Tronix, LLC - 1000 Armstrong Drive - Fairmont MN 56031 - UNITED STATES - - 60-89-3C (hex) Thermo Fisher Scientific P.O.A. - 60893C (base 16) Thermo Fisher Scientific P.O.A. - 46 Jonspin Rd. - Wilmington MA 01887 - UNITED STATES - - 60-89-B1 (hex) Key Digital Systems - 6089B1 (base 16) Key Digital Systems - 521 E 3rd Street - Mount Vernon NY 10553 - UNITED STATES - - 60-89-B7 (hex) KAEL MÜHENDİSLİK ELEKTRONİK TİCARET SANAYİ LİMİTED ŞİRKETİ - 6089B7 (base 16) KAEL MÜHENDİSLİK ELEKTRONİK TİCARET SANAYİ LİMİTED ŞİRKETİ - Atatürk Mah. 78 sokak ,No:10, Büyükalan Mevkii - Ulucak / Kemalpasa - Izmir Aegean 35175 - TURKEY - - 60-8C-2B (hex) Hanson Technology - 608C2B (base 16) Hanson Technology - Room 1503, Zhao Jia Bang Road - Shanghai 200030 - CHINA - - 60-8D-17 (hex) Sentrus Government Systems Division, Inc - 608D17 (base 16) Sentrus Government Systems Division, Inc - 141 Chesterfield Industrial Blvd - Chesterfield MO 63005-1219 - UNITED STATES - - 60-8F-5C (hex) Samsung Electronics Co.,Ltd - 608F5C (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 60-90-84 (hex) DSSD Inc - 609084 (base 16) DSSD Inc - 4025 Bohannon Dr - Menlo Park CA 94025 - UNITED STATES - - 60-92-17 (hex) Apple - 609217 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-96-20 (hex) PRIVATE - 609620 (base 16) - - 60-99-D1 (hex) Vuzix / Lenovo - 6099D1 (base 16) Vuzix / Lenovo - 2166 Brighton Henrietta Town Line Road - Rochester NY 14623 - UNITED STATES - - 60-9A-A4 (hex) GVI SECURITY INC. - 609AA4 (base 16) GVI SECURITY INC. - 2801 TRADE CENTER DR STE.120 - CARROLLTON TX 75007 - UNITED STATES - - 60-9C-9F (hex) Brocade Communications Systems, Inc. - 609C9F (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose California 95134 - UNITED STATES - - 60-9E-64 (hex) Vivonic GmbH - 609E64 (base 16) Vivonic GmbH - Kurfuerst-Eppstein-Ring 4 - Sailauf Bayern 63877 - GERMANY - - 60-9F-9D (hex) CloudSwitch - 609F9D (base 16) CloudSwitch - 200 Wheeler Rd - Burlington MA 01803 - UNITED STATES - - 60-A1-0A (hex) Samsung Electronics Co.,Ltd - 60A10A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 60-A4-4C (hex) ASUSTek COMPUTER INC. - 60A44C (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, Taipei 112 - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 60-A8-FE (hex) Nokia Solutions and Networks - 60A8FE (base 16) Nokia Solutions and Networks - Karaportti 3 - Espoo Finland 02610 - FINLAND - - 60-A9-B0 (hex) Merchandising Technologies, Inc - 60A9B0 (base 16) Merchandising Technologies, Inc - 1050 NW 229th Avenue - HIllsboro OR 97124 - UNITED STATES - - 60-AF-6D (hex) Samsung Electronics Co.,Ltd - 60AF6D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 60-B1-85 (hex) ATH system - 60B185 (base 16) ATH system - Osady lezaku 498 - Chrast CZ 53851 - CZECH REPUBLIC - - 60-B3-C4 (hex) Elber Srl - 60B3C4 (base 16) Elber Srl - via Pontevecchio 42 W - Carasco Ge 16042 - ITALY - - 60-B6-06 (hex) Phorus - 60B606 (base 16) Phorus - 16255 Ventura Boulevard, Suite 310 - Encino CA 91436 - UNITED STATES - - 60-B6-17 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 60B617 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 60-B9-33 (hex) Deutron Electronics Corp. - 60B933 (base 16) Deutron Electronics Corp. - 8F, 68, Sec. 3, Nanking E. Rd. - Taipei Taiwan 104 - TAIWAN, PROVINCE OF CHINA - - 60-B9-82 (hex) RO.VE.R. Laboratories S.p.A. - 60B982 (base 16) RO.VE.R. Laboratories S.p.A. - Via Parini, 2 - Sirmione Brescia 25019 - ITALY - - 60-BB-0C (hex) Beijing HuaqinWorld Technology Co,Ltd - 60BB0C (base 16) Beijing HuaqinWorld Technology Co,Ltd - 30F,Beijing Silver Tower,No.2 North Road - Dong San Huan. - Chao Yang District Beijing 100027 - CHINA - - 60-BC-4C (hex) EWM Hightec Welding GmbH - 60BC4C (base 16) EWM Hightec Welding GmbH - Dr.Günter-Henle-Str. 8 - Mündersbach Rheinland Pfalz 56271 - GERMANY - - 60-BD-91 (hex) Move Innovation - 60BD91 (base 16) Move Innovation - Generatorvej 8B,st - Herlev DK 2730 - DENMARK - - 60-BE-B5 (hex) Motorola Mobility LLC - 60BEB5 (base 16) Motorola Mobility LLC - 600 North US Highway 45 - Libertyville IL 60048 - UNITED STATES - - 60-C1-CB (hex) Fujian Great Power PLC Equipment Co.,Ltd - 60C1CB (base 16) Fujian Great Power PLC Equipment Co.,Ltd - 6/F.Bld.34.Zone C.Software Park - Tongpan Road,Gulou - Fuzhou Fujian,China 350003 - CHINA - - 60-C3-97 (hex) 2Wire Inc - 60C397 (base 16) 2Wire Inc - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 60-C5-47 (hex) Apple - 60C547 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-C5-A8 (hex) Beijing LT Honway Technology Co.,Ltd - 60C5A8 (base 16) Beijing LT Honway Technology Co.,Ltd - Room 1703,A1 Tower, Changyuan Tiandi, No.18,Suzhou Street - Haidian District - beijing beijing 100086 - CHINA - - 60-C7-98 (hex) Verifone, Inc. - 60C798 (base 16) Verifone, Inc. - 2455 Augustine Drive - Santa Clara California 95054 - UNITED STATES - - 60-C9-80 (hex) Trymus - 60C980 (base 16) Trymus - Bucheon Techno Park 303-902 - Ojeong-gu Samjung-dong - Bucheon-si 421-741 Gyunggi-do - KOREA, REPUBLIC OF - - 60-CB-FB (hex) AirScape Inc. - 60CBFB (base 16) AirScape Inc. - 625 Charles Way - Medford OR 97501 - UNITED STATES - - 60-CD-A9 (hex) Abloomy - 60CDA9 (base 16) Abloomy - Room 501 ,CTS Building,No 1 Beishatan Chaoyang District - BeiJing 100083 - CHINA - - 60-CD-C5 (hex) Taiwan Carol Electronics., Ltd - 60CDC5 (base 16) Taiwan Carol Electronics., Ltd - No.202, Tung Kuang Road - Taichung Taiwan 40151 - TAIWAN, PROVINCE OF CHINA - - 60-D0-A9 (hex) Samsung Electronics Co.,Ltd - 60D0A9 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 60-D1-AA (hex) Vishal Telecommunications Pvt Ltd - 60D1AA (base 16) Vishal Telecommunications Pvt Ltd - 25 Sitaram Building Dr D N Road - Fort Mumbai - Mumbai Maharastra 400001 - INDIA - - 60-D2-B9 (hex) REALAND BIO CO., LTD. - 60D2B9 (base 16) REALAND BIO CO., LTD. - Room 201A, N.set, Jinshan Bd., No.248 Wushan Rd., Tianhe District - Guangzhou Guangdong 510630 - CHINA - - 60-D3-0A (hex) Quatius Limited - 60D30A (base 16) Quatius Limited - Units 05-07, 16/F, Greenfield Tower, Concordia Plaza, - 1 Science Museum Rd., TST East - Kowloon - HONG KONG - - 60-D8-19 (hex) Hon Hai Precision Ind. Co.,Ltd. - 60D819 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 60-D9-A0 (hex) Lenovo Mobile Communication Technology Ltd. - 60D9A0 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999, Qishan North 2nd Road - Information & Optoelectronics Park - Torch Hi-tech Industry Development Zone Xiamen, Fujian 361006 - CHINA - - 60-D9-C7 (hex) Apple - 60D9C7 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-DA-23 (hex) Estech Co.,Ltd - 60DA23 (base 16) Estech Co.,Ltd - #717,133-1,Sangdaewon-Dong - Jungwon-Gu - Seongnam-Si Gyeonggi-Do 462-120 - KOREA, REPUBLIC OF - - 60-DB-2A (hex) HNS - 60DB2A (base 16) HNS - 345-50, Gasan-dong, Geumcheon-gu, Seoul, Korea[153-707] - #1204, IT PREMIERE TOWER - Seoul The Seoul Metropolis 82 - KOREA, REPUBLIC OF - - 60-DE-44 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 60DE44 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 60-E0-0E (hex) SHINSEI ELECTRONICS CO LTD - 60E00E (base 16) SHINSEI ELECTRONICS CO LTD - 2-6-25 - Nishinagasu-cho - Amagasaki Hyogo 660-0805 - JAPAN - - 60-E3-27 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 60E327 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - 60-E6-BC (hex) Sino-Telecom Technology Co.,Ltd. - 60E6BC (base 16) Sino-Telecom Technology Co.,Ltd. - 6F, Building 2, No.115, Lane 1276 Nanle Rd - Songjiang District, Shanghai - 201613 - CHINA - - 60-E7-01 (hex) Huawei Technologies Co., Ltd - 60E701 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 60-E9-56 (hex) Ayla Networks, Inc - 60E956 (base 16) Ayla Networks, Inc - 218 Morgan Lane - Menlo Park CA 94025 - UNITED STATES - - 60-EB-69 (hex) Quanta computer Inc. - 60EB69 (base 16) Quanta computer Inc. - 211, Wen Hwa 2nd Rd.,Kuei Shan, - Tao Yuan 33377 - TAIWAN, PROVINCE OF CHINA - - 60-F1-3D (hex) JABLOCOM s.r.o. - 60F13D (base 16) JABLOCOM s.r.o. - V Nivach 12 - Jablonec nad Nisou 466 01 - CZECH REPUBLIC - - 60-F1-89 (hex) Murata Manufacturing Co., Ltd. - 60F189 (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 60-F2-81 (hex) TRANWO TECHNOLOGY CO., LTD. - 60F281 (base 16) TRANWO TECHNOLOGY CO., LTD. - No.236, Sec.3, Huanbei Rd. - Jubei City Hsinchu County 30265 - TAIWAN, PROVINCE OF CHINA - - 60-F2-EF (hex) VisionVera International Co., Ltd. - 60F2EF (base 16) VisionVera International Co., Ltd. - A1103 Gehua Building - Dongchen District - Beijing 100007 - CHINA - - 60-F3-DA (hex) Logic Way GmbH - 60F3DA (base 16) Logic Way GmbH - Hagenower Str. 73 - Schwerin Mecklenburg-West Pomerania 19061 - GERMANY - - 60-F4-94 (hex) Hon Hai Precision Ind. Co.,Ltd. - 60F494 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 60-F5-9C (hex) CRU-Dataport - 60F59C (base 16) CRU-Dataport - 1000 SE Tech Center Drive - Suite 160 - Vancouver WA 98683 - UNITED STATES - - 60-F6-73 (hex) TERUMO CORPORATION - 60F673 (base 16) TERUMO CORPORATION - 1500,Inokuchi,Nakai-machi - Ashigarakami-gun Kanagawa 259-0151 - JAPAN - - 60-F8-1D (hex) Apple - 60F81D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-FA-CD (hex) Apple - 60FACD (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-FB-42 (hex) Apple - 60FB42 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-FE-1E (hex) China Palms Telecom.Ltd - 60FE1E (base 16) China Palms Telecom.Ltd - 2nd Floor of Building 1 - No.80, Lane 1505 , ZuChongZhi Road, - PuDong District Shanghai 201203 - CHINA - - 60-FE-20 (hex) 2 Wire - 60FE20 (base 16) 2 Wire - 1764 Automation ParkWay - San Jose CA 95131 - UNITED STATES - - 60-FE-C5 (hex) Apple - 60FEC5 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 60-FE-F9 (hex) Thomas & Betts - 60FEF9 (base 16) Thomas & Betts - 5900 Eastport Blvd - Bldg V - Richmond VA 23231 - UNITED STATES - - 60-FF-DD (hex) C.E. ELECTRONICS, INC - 60FFDD (base 16) C.E. ELECTRONICS, INC - 2107 INDUSTRIAL DR - BRYAN OHIO 43506 - UNITED STATES - - 64-00-2D (hex) Powerlinq Co., LTD - 64002D (base 16) Powerlinq Co., LTD - 13 PingDong Road 4 , - Nanping Sci & Tech, Indt'l Park - Zhuhai GD 519060 - CHINA - - 64-00-6A (hex) Dell Inc. - 64006A (base 16) Dell Inc. - One Dell way - MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 64-00-F1 (hex) CISCO SYSTEMS, INC. - 6400F1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 64-05-BE (hex) NEW LIGHT LED - 6405BE (base 16) NEW LIGHT LED - No.50, Siyuan Rd - Xinzhuang Dist - New Taipei 24251 - TAIWAN, PROVINCE OF CHINA - - 64-09-4C (hex) Beijing Superbee Wireless Technology Co.,Ltd - 64094C (base 16) Beijing Superbee Wireless Technology Co.,Ltd - B7,Science-Tech Fortune Center, - No.8,XueqingRoad,Haidian District - Beijing 100192 - CHINA - - 64-09-80 (hex) XIAOMI Electronics,CO.,LTD - 640980 (base 16) XIAOMI Electronics,CO.,LTD - Xiaomi Building, No.68 Qinghe Middle Street - Haidian District - Beijing 100085 - CHINA - - 64-0B-4A (hex) Digital Telecom Technology Limited - 640B4A (base 16) Digital Telecom Technology Limited - 1708 Nan Fung Tower, - 173 Des Voeux Road Central - 00852 - HONG KONG - - 64-0E-36 (hex) TAZTAG - 640E36 (base 16) TAZTAG - Cicea 1 - Rue du Courtil - Bruz 35170 - FRANCE - - 64-0E-94 (hex) Pluribus Networks, Inc. - 640E94 (base 16) Pluribus Networks, Inc. - 1808 Embarcadero Rd Suite B - Palo Alto CA 94303 - UNITED STATES - - 64-0F-28 (hex) 2wire - 640F28 (base 16) 2wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 64-10-84 (hex) HEXIUM Technical Development Co., Ltd. - 641084 (base 16) HEXIUM Technical Development Co., Ltd. - Vaci ut 51b - BUDAPEST H-1134 - HUNGARY - - 64-12-25 (hex) Cisco - 641225 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 64-16-7F (hex) Polycom - 64167F (base 16) Polycom - 6001 America Center Drive - San Jose CA 95002 - UNITED STATES - - 64-16-8D (hex) CISCO SYSTEMS, INC. - 64168D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 64-16-F0 (hex) Shehzhen Huawei Communication Technologies Co., Ltd. - 6416F0 (base 16) Shehzhen Huawei Communication Technologies Co., Ltd. - Building 2, Zone B,Huawei Industrial Park,Bantian, Longgang District - Shenzhen Guangdong 518129 - CHINA - - 64-1A-22 (hex) Heliospectra/Woodhill Investments - 641A22 (base 16) Heliospectra/Woodhill Investments - ArmbÃ¥gavägen 3 - BorÃ¥s None 50630 - SWEDEN - - 64-1C-67 (hex) DIGIBRAS INDUSTRIA DO BRASILS/A - 641C67 (base 16) DIGIBRAS INDUSTRIA DO BRASILS/A - Rua Tambaqui, 180-B - MANAUS - AM ¨C BRAZIL - MANAUS 69075-210 - BRAZIL - - 64-1E-81 (hex) Dowslake Microsystems - 641E81 (base 16) Dowslake Microsystems - 21 High Street, Suite 306 - North Andover MA 01845 - UNITED STATES - - 64-20-0C (hex) Apple - 64200C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 64-21-84 (hex) Nippon Denki Kagaku Co.,LTD - 642184 (base 16) Nippon Denki Kagaku Co.,LTD - Nishino Gotochou 18 - Yamashina Ward - Kyoto City Kyoto Pref 607-8356 - JAPAN - - 64-22-16 (hex) Shandong Taixin Electronic co.,Ltd - 642216 (base 16) Shandong Taixin Electronic co.,Ltd - FL.6,Haichen Building - Wenhua(West) Road,Lixia District - Jinan Shandong 250010 - CHINA - - 64-24-00 (hex) Xorcom Ltd. - 642400 (base 16) Xorcom Ltd. - Teradyon Industrial Park - D.N Misgav 20179 - ISRAEL - - 64-27-37 (hex) Hon Hai Precision Ind. Co.,Ltd. - 642737 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 64-2D-B7 (hex) SEUNGIL ELECTRONICS - 642DB7 (base 16) SEUNGIL ELECTRONICS - #16-8, Dodang-dong - Wonmi-gu - Buchon Gyuonggi-do 420-801 - KOREA, REPUBLIC OF - - 64-31-50 (hex) Hewlett-Packard Company - 643150 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 64-31-7E (hex) Dexin Corporation - 64317E (base 16) Dexin Corporation - 14F-8, No. 258, Lian Cheng Rd. - Chung Ho City, Taipei Hsien 235 - TAIWAN, PROVINCE OF CHINA - - 64-34-09 (hex) BITwave Pte Ltd - 643409 (base 16) BITwave Pte Ltd - 2 Serangoon North Ave 5 - #03-01 - 554911 - SINGAPORE - - 64-3A-B1 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD - 643AB1 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD - FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, Chengdu, Sichuan - Chengdu Sichuan 610000 - CHINA - - 64-3E-8C (hex) HUAWEI TECHNOLOGIES CO.,LTD - 643E8C (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 64-3F-5F (hex) Exablaze - 643F5F (base 16) Exablaze - Level 6 - 80 Clarence St - Sydney NSW 2000 - AUSTRALIA - - 64-42-14 (hex) Swisscom Energy Solutions AG - 644214 (base 16) Swisscom Energy Solutions AG - Solothurnerstrasse 19 - Olten 4600 - SWITZERLAND - - 64-43-46 (hex) GuangDong Quick Network Computer CO.,LTD - 644346 (base 16) GuangDong Quick Network Computer CO.,LTD - 12F,No.80 of Middle XianLie Road,YueXiu District - GuangZhou GuangDong 510070 - CHINA - - 64-4B-C3 (hex) Shanghai WOASiS Telecommunications Ltd., Co. - 644BC3 (base 16) Shanghai WOASiS Telecommunications Ltd., Co. - 15F, Software Building, - 461 Hongcao Road, Xuhui District - Shanghai 200233 - CHINA - - 64-4B-F0 (hex) CalDigit, Inc - 644BF0 (base 16) CalDigit, Inc - 1941 Miraloma Ave #B - Placentia CA 92870 - UNITED STATES - - 64-4D-70 (hex) dSPACE GmbH - 644D70 (base 16) dSPACE GmbH - Rathenaustraße 26 - Paderborn 33102 - GERMANY - - 64-4F-74 (hex) LENUS Co., Ltd. - 644F74 (base 16) LENUS Co., Ltd. - 18-5 Gwacheon-Dong - Gwacheon Gyeonggi-Do 427-060 - KOREA, REPUBLIC OF - - 64-4F-B0 (hex) Hyunjin.com - 644FB0 (base 16) Hyunjin.com - Hyochang-dong 5-86, Yongsan-gu - Daejung bldg 5F - Seoul 140-896 - KOREA, REPUBLIC OF - - 64-51-06 (hex) Hewlett Packard - 645106 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 64-51-7E (hex) LONG BEN (DONGGUAN) ELECTRONIC TECHNOLOGY CO.,LTD. - 64517E (base 16) LONG BEN (DONGGUAN) ELECTRONIC TECHNOLOGY CO.,LTD. - NO.19.Jian she Road,Shi ma Village,Tang xia Town,Dong guan,Guang dong,China - Dong guan Guang dong 523731 - CHINA - - 64-52-99 (hex) The Chamberlain Group, Inc - 645299 (base 16) The Chamberlain Group, Inc - 845 N Larch Ave - Elmhurst Illinois 60126 - UNITED STATES - - 64-53-5D (hex) Frauscher Sensortechnik - 64535D (base 16) Frauscher Sensortechnik - Gewerbestraße 1 - St. Marienkirchen Upper Austria 4774 - AUSTRIA - - 64-54-22 (hex) Equinox Payments - 645422 (base 16) Equinox Payments - 8888 E. Raintree Dr., Suite 300 - Scottsdale Arizona 85260 - UNITED STATES - - 64-55-63 (hex) Intelight Inc. - 645563 (base 16) Intelight Inc. - 3450 S Broadmont Drive, Suite 126 - Tucson AZ 85713 - UNITED STATES - - 64-55-7F (hex) NSFOCUS Information Technology Co., Ltd. - 64557F (base 16) NSFOCUS Information Technology Co., Ltd. - 3/F,Ether Building, No.4 Beiwa Rd.,Haidian District - Beijing 100089 - CHINA - - 64-55-B1 (hex) ARRIS Group, Inc. - 6455B1 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 64-56-01 (hex) TP-LINK TECHNOLOGIES CO.,LTD - 645601 (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24(floors 1,3,4,5)and 28(floors1-4)Central Science and Technology Park - Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - 64-59-F8 (hex) Vodafone Omnitel B.V. - 6459F8 (base 16) Vodafone Omnitel B.V. - VIA JERVIS, 13 10015 IVREA (TO) - ITALY - - 64-5A-04 (hex) Chicony Electronics Co., Ltd. - 645A04 (base 16) Chicony Electronics Co., Ltd. - No.25, Wugong 6th Rd., Wugu Dist., - New Taipei City 248 - TAIWAN, PROVINCE OF CHINA - - 64-5D-D7 (hex) Shenzhen Lifesense Medical Electronics Co., Ltd. - 645DD7 (base 16) Shenzhen Lifesense Medical Electronics Co., Ltd. - China Academy of Science and Technology Development, Room 19A - High-tech. South Street No. 1, South District of High-tech Industrial Area - Shenzhen Guangdong 518057 - CHINA - - 64-5E-BE (hex) Yahoo! JAPAN - 645EBE (base 16) Yahoo! JAPAN - Midtown Tower - 9-7-1 Akasaka - Minato-ku Tokyo 107-6211 - JAPAN - - 64-5F-FF (hex) Nicolet Neuro - 645FFF (base 16) Nicolet Neuro - 1850 Deming Way - Middleton WI 53562 - UNITED STATES - - 64-62-23 (hex) Cellient Co., Ltd. - 646223 (base 16) Cellient Co., Ltd. - 6F Glass Tower, 366-4 Yatap-dong Bundang-gu - Seongnam-si Gyeonggi-do 463-827 - KOREA, REPUBLIC OF - - 64-64-9B (hex) juniper networks - 64649B (base 16) juniper networks - 1194 N Mathilda Avenue - sunnyvale CA 94089 - UNITED STATES - - 64-65-C0 (hex) Nuvon, Inc - 6465C0 (base 16) Nuvon, Inc - 3130 Alpine Road - Suite 288-465 - Portola Valley California 94028 - UNITED STATES - - 64-66-B3 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 6466B3 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park - Shennan Rd, Nanshan - Shenzhen Guangdong 518057 - CHINA - - 64-67-07 (hex) Beijing Omnific Technology, Ltd. - 646707 (base 16) Beijing Omnific Technology, Ltd. - Rm. 402, Building 1, Shui Mu Qing Hua Community - Zhong Guan Cun Bei Er Jie, Haidian District - Beijing 100190 - CHINA - - 64-68-0C (hex) COMTREND - 64680C (base 16) COMTREND - 3F-1,10 Lane 609, Chung Hsin Road, Section 5 - San Chung City - Taipei Hsien 241 - TAIWAN, PROVINCE OF CHINA - - 64-69-BC (hex) Hytera Communications Co .,ltd - 6469BC (base 16) Hytera Communications Co .,ltd - HYT Tower ,Hi-Tech Industrial Park North,Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - 64-6A-52 (hex) Avaya, Inc - 646A52 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 64-6C-B2 (hex) Samsung Electronics Co.,Ltd - 646CB2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 64-6E-6C (hex) Radio Datacom LLC - 646E6C (base 16) Radio Datacom LLC - 9601 N 35th St - Phoenix AZ 85028 - UNITED STATES - - 64-6E-EA (hex) Iskratel d.o.o. - 646EEA (base 16) Iskratel d.o.o. - Ljubljanska cesta 24a - Kranj 4000 - SLOVENIA - - 64-70-02 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 647002 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, - Shenzhen, Guangdong Province, 518057 - CHINA - - 64-72-D8 (hex) GooWi Technology Co.,Limited - 6472D8 (base 16) GooWi Technology Co.,Limited - Unit C8.,9/F,Hongming Fatoty Building - 99 How Ming Street Kwun Tong 999077 - HONG KONG - - 64-73-E2 (hex) Arbiter Systems, Inc. - 6473E2 (base 16) Arbiter Systems, Inc. - 1324 Vendels Circle - Suite 121 - Paso Robles California 93446 - UNITED STATES - - 64-76-57 (hex) Innovative Security Designs - 647657 (base 16) Innovative Security Designs - 18 Technology Drive - Suite #134 - Irvine CA 92618 - UNITED STATES - - 64-76-BA (hex) Apple - 6476BA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 64-77-91 (hex) Samsung Electronics Co.,Ltd - 647791 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 64-7B-D4 (hex) Texas Instruments - 647BD4 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 64-7C-34 (hex) Ubee Interactive Corp. - 647C34 (base 16) Ubee Interactive Corp. - 10F-1, No. 5, Taiyuan 1st St - Jhubei City Hsinchu County 302 - TAIWAN, PROVINCE OF CHINA - - 64-7D-81 (hex) YOKOTA INDUSTRIAL CO,.LTD - 647D81 (base 16) YOKOTA INDUSTRIAL CO,.LTD - 5-55 NISHIIWATA - 3-CHOME - HIGASHI OSAKA-CITY OSAKA 578-0947 - JAPAN - - 64-7F-DA (hex) TEKTELIC Communications Inc. - 647FDA (base 16) TEKTELIC Communications Inc. - 7657 10th Street NE - Calgary Alberta T2E 8X2 - CANADA - - 64-80-8B (hex) VG Controls, Inc. - 64808B (base 16) VG Controls, Inc. - 11 Butternut Drive - Vernon NJ 07462 - UNITED STATES - - 64-80-99 (hex) Intel Corporate - 648099 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 64-81-25 (hex) Alphatron Marine BV - 648125 (base 16) Alphatron Marine BV - Schaardijk 23 - Rotterdam Zuid-Holland 3063NH - NETHERLANDS - - 64-87-88 (hex) Juniper Networks - 648788 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 64-87-D7 (hex) Pirelli Tyre S.p.A. - 6487D7 (base 16) Pirelli Tyre S.p.A. - VIALE SARCA 222 - MILANO 20126 - ITALY - - 64-88-FF (hex) Sichuan Changhong Electric Ltd. - 6488FF (base 16) Sichuan Changhong Electric Ltd. - 35 East Mianxing Road - High-Tech Park - MianYang SiChuan 621000 - CHINA - - 64-89-9A (hex) LG Electronics - 64899A (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul Seoul 153-801 - KOREA, REPUBLIC OF - - 64-8D-9E (hex) IVT Electronic Co.,Ltd - 648D9E (base 16) IVT Electronic Co.,Ltd - F building Dongxing Insdustrial Area - Dongkeng Town - Dongguan City Guangdong provice 523457 - CHINA - - 64-99-5D (hex) LGE - 64995D (base 16) LGE - 60-39 , Kasan -dong , Gumcheon-gu. - Seoul 153-801 - KOREA, REPUBLIC OF - - 64-99-68 (hex) Elentec - 649968 (base 16) Elentec - 401-13 Chunggye-Ri - Dongtan-Myun Kyunggi 445-811 - KOREA, REPUBLIC OF - - 64-99-A0 (hex) AG Elektronik AB - 6499A0 (base 16) AG Elektronik AB - Smidesv 12 - Staffanstorp 24534 - SWEDEN - - 64-9A-BE (hex) Apple - 649ABE (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 64-9B-24 (hex) V Technology Co., Ltd. - 649B24 (base 16) V Technology Co., Ltd. - YBP East Tower 5F, - 134 Godo-cho, Hogogaya-ku, - Yokohama city Kanagawa 240-0005 - JAPAN - - 64-9C-81 (hex) Qualcomm iSkoot, Inc. - 649C81 (base 16) Qualcomm iSkoot, Inc. - 5665 Morehouse Drive - San Diego CA 92071 - UNITED STATES - - 64-9C-8E (hex) Texas Instruments - 649C8E (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 64-9E-F3 (hex) CISCO SYSTEMS, INC. - 649EF3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 64-9F-F7 (hex) Kone OYj - 649FF7 (base 16) Kone OYj - Myllykatu 3 - Hyvinkaa Hyvinkaa 05830 - FINLAND - - 64-A0-E7 (hex) CISCO SYSTEMS, INC. - 64A0E7 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 64-A2-32 (hex) OOO Samlight - 64A232 (base 16) OOO Samlight - 44A, Dubninskaya str., - Moscow 127591 - RUSSIAN FEDERATION - - 64-A3-41 (hex) Wonderlan (Beijing) Technology Co., Ltd. - 64A341 (base 16) Wonderlan (Beijing) Technology Co., Ltd. - Room 04D, Building D, KeShi Plaza - No. A28, Shangdi Xinxi Road - Haidian District Beijing 100085 - CHINA - - 64-A3-CB (hex) Apple - 64A3CB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 64-A7-69 (hex) HTC Corporation - 64A769 (base 16) HTC Corporation - No. 23, Xinghua Rd, - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 64-A7-DD (hex) Avaya, Inc - 64A7DD (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 64-A8-37 (hex) Juni Korea Co., Ltd - 64A837 (base 16) Juni Korea Co., Ltd - E603 Bundang Techno-Park 151 - Yatap, Bundang - Seongnam Gyeonggi 463-760 - KOREA, REPUBLIC OF - - 64-AE-0C (hex) CISCO SYSTEMS, INC. - 64AE0C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 64-AE-88 (hex) Polytec GmbH - 64AE88 (base 16) Polytec GmbH - Polytec Platz 1-7 - Waldbronn BW 76337 - GERMANY - - 64-B2-1D (hex) Chengdu Phycom Tech Co., Ltd. - 64B21D (base 16) Chengdu Phycom Tech Co., Ltd. - No.216 beisen road - Chengdu Sichuan 610000 - CHINA - - 64-B3-10 (hex) Samsung Electronics Co.,Ltd - 64B310 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 64-B3-70 (hex) PowerComm Solutions LLC - 64B370 (base 16) PowerComm Solutions LLC - 15 Minneakoning Rd. Suite 311 - Flemington NJ 08822 - UNITED STATES - - 64-B4-73 (hex) Xiaomi inc. - 64B473 (base 16) Xiaomi inc. - Office Building,The Rainbow City of China Resources, NO.68,Qinghe Middle Street,Haidian District,Beijing,China,100085 - Beijing Beijing 100085 - CHINA - - 64-B6-4A (hex) ViVOtech, Inc. - 64B64A (base 16) ViVOtech, Inc. - 451 El Camino Real - Santa Clara CA 95050 - UNITED STATES - - 64-B8-53 (hex) Samsung Elec Co.,Ltd - 64B853 (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 64-B9-E8 (hex) Apple - 64B9E8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 64-BA-BD (hex) SDJ Technologies, Inc. - 64BABD (base 16) SDJ Technologies, Inc. - 2125-B Madera Road - Simi Valley CA 93065 - UNITED STATES - - 64-BC-11 (hex) CombiQ AB - 64BC11 (base 16) CombiQ AB - Science Park - Gjuterigatan 9 - Jonkoping 553 18 - SWEDEN - - 64-C5-AA (hex) South African Broadcasting Corporation - 64C5AA (base 16) South African Broadcasting Corporation - 77 Twickenham Avenue - Corner Henley Road - Auckland Park Gauteng 2006 - SOUTH AFRICA - - 64-C6-67 (hex) Barnes&Noble - 64C667 (base 16) Barnes&Noble - 400 Hamilton Avenue - Suite 130 - Palo Alto CA 94301 - UNITED STATES - - 64-C6-AF (hex) AXERRA Networks Ltd - 64C6AF (base 16) AXERRA Networks Ltd - 24 Raoul Wallenberg St. , - Tel-Aviv ISRAEL 69719 - ISRAEL - - 64-C9-44 (hex) LARK Technologies, Inc - 64C944 (base 16) LARK Technologies, Inc - 2570 W El Camino Real - Ste 100 - Mountain View CA 94040 - UNITED STATES - - 64-D0-2D (hex) Next Generation Integration (NGI) - 64D02D (base 16) Next Generation Integration (NGI) - 137 rue de Versailles - Le Chesnay 78150 - FRANCE - - 64-D1-A3 (hex) Sitecom Europe BV - 64D1A3 (base 16) Sitecom Europe BV - Linatebaan 101 - Rotterdam Zuid-Holland 3045 AH - NETHERLANDS - - 64-D2-41 (hex) Keith & Koep GmbH - 64D241 (base 16) Keith & Koep GmbH - Uellendahler Str. 199 - Wuppertal NRW 42109 - GERMANY - - 64-D4-BD (hex) ALPS ELECTRIC CO.,LTD. - 64D4BD (base 16) ALPS ELECTRIC CO.,LTD. - 6-1 - nishida - kakuda city Miyagi_PREF 981-1595 - JAPAN - - 64-D4-DA (hex) Intel Corporate - 64D4DA (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 64-D8-14 (hex) CISCO SYSTEMS, INC. - 64D814 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 64-D9-12 (hex) Solidica, Inc. - 64D912 (base 16) Solidica, Inc. - 5840 Interface Drive - Suite 200 - Ann Arbor Michigan 48103 - UNITED STATES - - 64-D9-54 (hex) TAICANG AND W ELECTRONICS CO LTD - 64D954 (base 16) TAICANG AND W ELECTRONICS CO LTD - 89# Jiang Nan RD, Lu Du, - Taicang Jiangsu 215412 - CHINA - - 64-D9-89 (hex) CISCO SYSTEMS, INC. - 64D989 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 64-DB-18 (hex) OpenPattern - 64DB18 (base 16) OpenPattern - 109/111 rue des Côtes - Maisons Laffitte Yvelines 78600 - FRANCE - - 64-DB-81 (hex) Syszone Co., Ltd. - 64DB81 (base 16) Syszone Co., Ltd. - 9F Garak, 310 Ogeum-ro - Songpa-gu - Seoul Seoul, Korea 138-716 - KOREA, REPUBLIC OF - - 64-DC-01 (hex) Static Systems Group PLC - 64DC01 (base 16) Static Systems Group PLC - Heathmill Road - Wombourne - Wolverhampton West Midlands WV5 8AN - UNITED KINGDOM - - 64-DE-1C (hex) Kingnetic Pte Ltd - 64DE1C (base 16) Kingnetic Pte Ltd - 47 Kaki Bukit Place - #02-00 Eunos Techpark - 416225 - SINGAPORE - - 64-E1-61 (hex) DEP Corp. - 64E161 (base 16) DEP Corp. - Nishi-shinjuku 6-12-7 - Stork Shinjuku 1F A-11 - Shinjuku Tokyo 160-0023 - JAPAN - - 64-E5-99 (hex) EFM Networks - 64E599 (base 16) EFM Networks - 6F Benposra II B/D - 1197-1 Bojeong-dong - Yong In Kyunggi-do 446-913 - KOREA, REPUBLIC OF - - 64-E6-25 (hex) Woxu Wireless Co., Ltd - 64E625 (base 16) Woxu Wireless Co., Ltd - B103 Building1 No.6 Changjianghoujie - Nanjing 210000 - CHINA - - 64-E6-82 (hex) Apple - 64E682 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 64-E8-4F (hex) Serialway Communication Technology Co. Ltd - 64E84F (base 16) Serialway Communication Technology Co. Ltd - Room 315, 706 Painting Room, - 85# Jiancaicheng West Road, Haidian District - Beijing 100096 - CHINA - - 64-E8-92 (hex) Morio Denki Co., Ltd. - 64E892 (base 16) Morio Denki Co., Ltd. - 2, Nadooka - Ryugasaki Ibaraki 301-0845 - JAPAN - - 64-E8-E6 (hex) global moisture management system - 64E8E6 (base 16) global moisture management system - 11132 broad river road - suite a - irmo sc 29063 - UNITED STATES - - 64-E9-50 (hex) Cisco - 64E950 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 64-EA-C5 (hex) SiboTech Automation Co., Ltd. - 64EAC5 (base 16) SiboTech Automation Co., Ltd. - 5th Floor, Bld 3 - No.518 Xinzhuan Rd - Shanghai Shanghai 201612 - CHINA - - 64-EB-8C (hex) Seiko Epson Corporation - 64EB8C (base 16) Seiko Epson Corporation - 80 Harashinden - Hirooka - Shiojiri-shi Nagano-ken 399-0785 - JAPAN - - 64-ED-57 (hex) ARRIS Group, Inc. - 64ED57 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 64-ED-62 (hex) WOORI SYSTEMS Co., Ltd - 64ED62 (base 16) WOORI SYSTEMS Co., Ltd - 101Ho #42-9, Jeongja-dong, Pundang-gu - Sungnam-si Kyunggi-do 463-848 - KOREA, REPUBLIC OF - - 64-F2-42 (hex) Gerdes Aktiengesellschaft - 64F242 (base 16) Gerdes Aktiengesellschaft - Bergerwiesenstraße 9 - Meckenheim NRW 53340 - GERMANY - - 64-F5-0E (hex) Kinion Technology Company Limited - 64F50E (base 16) Kinion Technology Company Limited - ng Kon107A, 1/F, Enterprise Place, - Hog Science Park, Shatin,NT - HONG KONG - - 64-F6-9D (hex) Cisco - 64F69D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 64-F9-70 (hex) Kenade Electronics Technology Co.,LTD. - 64F970 (base 16) Kenade Electronics Technology Co.,LTD. - F/G room,11/F,Hangdu building,Huafu Rd, Futian district, - ShenZhen GuangDong 518028 - CHINA - - 64-F9-87 (hex) Avvasi Inc. - 64F987 (base 16) Avvasi Inc. - 103 Randall Dr. - Waterloo ON N2V 1C5 - CANADA - - 64-FB-81 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 64FB81 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 64-FC-8C (hex) Zonar Systems - 64FC8C (base 16) Zonar Systems - 18200 Cascade Ave South - Seattle WA 98118 - UNITED STATES - - 68-05-71 (hex) Samsung Electronics Co.,Ltd - 680571 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 68-05-CA (hex) Intel Corporate - 6805CA (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 68-09-27 (hex) Apple - 680927 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 68-0A-D7 (hex) Yancheng Kecheng Optoelectronic Technology Co., Ltd - 680AD7 (base 16) Yancheng Kecheng Optoelectronic Technology Co., Ltd - No.1 East Road, Kaifa Avenue, - Economic Development Zone, - Yancheng Jiangsu 224007 - CHINA - - 68-12-2D (hex) Special Instrument Development Co., Ltd. - 68122D (base 16) Special Instrument Development Co., Ltd. - 6F-1, No. 123, Lane 235 - Bao Chiao Road - Hsin Tien Taipei Hsien 231 - TAIWAN, PROVINCE OF CHINA - - 68-15-90 (hex) SAGEMCOM SAS - 681590 (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON CEDEX Choisissez l'état / la province 92848 - FRANCE - - 68-15-D3 (hex) Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A. - 6815D3 (base 16) Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A. - ul. Traugutta 7 - Mielec 39-300 - POLAND - - 68-16-05 (hex) Systems And Electronic Development FZCO - 681605 (base 16) Systems And Electronic Development FZCO - Roundabout no. 8 - Factory unit no. FB-06 - Jebel Ali free Zone Dubai P.O.Box 61129 - UNITED ARAB EMIRATES - - 68-17-29 (hex) Intel Corporate - 681729 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 68-19-3F (hex) Digital Airways - 68193F (base 16) Digital Airways - 5, Place Jean SIARD - ARGENTAN NORMANDY 61200 - FRANCE - - 68-1A-B2 (hex) zte corporation - 681AB2 (base 16) zte corporation - 12/F.,zte R&D Building,Kejinan Road - Shenzhen Guangdong 518057 - CHINA - - 68-1C-A2 (hex) Rosewill Inc. - 681CA2 (base 16) Rosewill Inc. - 17708 Rowland St., - City of Industry CA 91748 - UNITED STATES - - 68-1D-64 (hex) Sunwave Communications Co., Ltd - 681D64 (base 16) Sunwave Communications Co., Ltd - 581,huoju Avenue,BinJiang District - Hangzhou Zhejiang Province 310053 - CHINA - - 68-1E-8B (hex) InfoSight Corporation - 681E8B (base 16) InfoSight Corporation - 20700 US Hwy 23 - Chillicothe Ohio 45601 - UNITED STATES - - 68-1F-D8 (hex) Advanced Telemetry - 681FD8 (base 16) Advanced Telemetry - 10670 Treena Street - Suite 106 - San Diego CA 92131 - UNITED STATES - - 68-23-4B (hex) Nihon Dengyo Kousaku - 68234B (base 16) Nihon Dengyo Kousaku - shinmachi 21-1 - matoba - kawagoe-shi saitama 350-1107 - JAPAN - - 68-28-BA (hex) Dejai - 6828BA (base 16) Dejai - PO Box 101 - Toorak Vic 3142 - AUSTRALIA - - 68-28-F6 (hex) Vubiq Networks, Inc. - 6828F6 (base 16) Vubiq Networks, Inc. - 9231 Irvine Blvd. - Irvine California 92618 - UNITED STATES - - 68-2D-DC (hex) Wuhan Changjiang Electro-Communication Equipment CO.,LTD - 682DDC (base 16) Wuhan Changjiang Electro-Communication Equipment CO.,LTD - No.8,Yinghu Sience&Technology industrial park - Jiutong Road,East-West Lake District - Wuhan Hubei 430040 - CHINA - - 68-36-B5 (hex) DriveScale, Inc. - 6836B5 (base 16) DriveScale, Inc. - 530 Lakeside Dr. #190 - Sunnyvale CALIFORNIA 94085 - UNITED STATES - - 68-3B-1E (hex) Countwise LTD - 683B1E (base 16) Countwise LTD - 1149 Sawgrass Corporate Parkway - Sunrise Florida 33323 - UNITED STATES - - 68-3C-7D (hex) Magic Intelligence Technology Limited - 683C7D (base 16) Magic Intelligence Technology Limited - B13/Flat 4,East block,Jinhui Blding.Nanhai Road - Nanshan District, Shenzhen guangdong 518000 - CHINA - - 68-3E-EC (hex) ERECA - 683EEC (base 16) ERECA - 75, Rue d'Orgemont - Saint GRATIEN 95210 - FRANCE - - 68-43-52 (hex) Bhuu Limited - 684352 (base 16) Bhuu Limited - Office 1, 465 Mt Eden Road - Mt Eden - Auckland 1023 - NEW ZEALAND - - 68-48-98 (hex) Samsung Electronics Co.,Ltd - 684898 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 68-4B-88 (hex) Galtronics Telemetry Inc. - 684B88 (base 16) Galtronics Telemetry Inc. - 31 Lupi Ct - Suite 150 - Palm Coast Florida 32137 - UNITED STATES - - 68-4C-A8 (hex) Shenzhen Herotel Tech. Co., Ltd. - 684CA8 (base 16) Shenzhen Herotel Tech. Co., Ltd. - Room W1402, West Tower, No.10128, Shennan Road, Nanshan District - Shenzhen Guangdong 518000 - - 68-51-B7 (hex) PowerCloud Systems, Inc. - 6851B7 (base 16) PowerCloud Systems, Inc. - 3333 Coyote Hill Rd - Palo Alto CA 94304 - UNITED STATES - - 68-54-ED (hex) Alcatel-Lucent - Nuage - 6854ED (base 16) Alcatel-Lucent - Nuage - 777 E. Middlefield Rd - Mountain View CA 94043 - UNITED STATES - - 68-54-F5 (hex) enLighted Inc - 6854F5 (base 16) enLighted Inc - 1451 Grant Rd - Suite 200 - Mountain View CA 94040 - UNITED STATES - - 68-59-7F (hex) Alcatel Lucent - 68597F (base 16) Alcatel Lucent - Via Trento, 30 - Vimercate MB 20059 - ITALY - - 68-5B-35 (hex) Apple - 685B35 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 68-5B-36 (hex) POWERTECH INDUSTRIAL CO., LTD. - 685B36 (base 16) POWERTECH INDUSTRIAL CO., LTD. - 10F, No. 407, Chung Shan Rd., Sec 2, - Chung Ho Taipei County 23558 - TAIWAN, PROVINCE OF CHINA - - 68-5D-43 (hex) Intel Corporate - 685D43 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 68-5E-6B (hex) PowerRay Co., Ltd. - 685E6B (base 16) PowerRay Co., Ltd. - 7F-1, No 190, Sec 2, Chung Hsing Road, Sindian District - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 68-63-59 (hex) Advanced Digital Broadcast SA - 686359 (base 16) Advanced Digital Broadcast SA - Avenue de Tournay 7 - Pregny-Chambesy 1292 - SWITZERLAND - - 68-64-4B (hex) Apple - 68644B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 68-69-2E (hex) Zycoo Co.,Ltd - 68692E (base 16) Zycoo Co.,Ltd - F7,B7,Tianfu Software park - Chengdu Sichuan 610000 - CHINA - - 68-69-F2 (hex) ComAp s.r.o. - 6869F2 (base 16) ComAp s.r.o. - Kundratka 17 - Prague 18000 - CZECH REPUBLIC - - 68-6E-23 (hex) Wi3 Inc. - 686E23 (base 16) Wi3 Inc. - 7620 Omnitech Place - Suite #4 - Victor NY 14564 - UNITED STATES - - 68-6E-48 (hex) Prophet Electronic Technology Corp.,Ltd - 686E48 (base 16) Prophet Electronic Technology Corp.,Ltd - 9F ,3 Building,No 1535,Hongmei Road ,Xuhui District - Shanghai 200233 - CHINA - - 68-72-51 (hex) Ubiquiti Networks - 687251 (base 16) Ubiquiti Networks - 91 E. Tasman Dr. - San Jose California 95134 - UNITED STATES - - 68-72-DC (hex) CETORY.TV Company Limited - 6872DC (base 16) CETORY.TV Company Limited - Building C-1601, Tiley Central Plaza - No. 3 Haide Road, Nanshan District - Shenzhen Guangdong 518054 - CHINA - - 68-76-4F (hex) Sony Mobile Communications AB - 68764F (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 68-78-48 (hex) Westunitis Co., Ltd. - 687848 (base 16) Westunitis Co., Ltd. - North Building 7F, 3-1 Ofuka-cho, Kita-ku - Osaka-city Osaka-pref 5300011 - JAPAN - - 68-78-4C (hex) Nortel Networks - 68784C (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - 68-79-24 (hex) ELS-GmbH & Co. KG - 687924 (base 16) ELS-GmbH & Co. KG - Dammstrasse 21 - Werther NRW 33824 - GERMANY - - 68-79-ED (hex) SHARP Corporation - 6879ED (base 16) SHARP Corporation - 22-22,Nagaike-cho - Abeno-ku - Osaka city Osaka prefecture 545-8522 - JAPAN - - 68-7C-C8 (hex) Measurement Systems S. de R.L. - 687CC8 (base 16) Measurement Systems S. de R.L. - 45999 Regal Plaza - Ste 160-216 - Sterling VA 20165 - UNITED STATES - - 68-7C-D5 (hex) Y Soft Corporation, a.s. - 687CD5 (base 16) Y Soft Corporation, a.s. - Technicka 2948/13 - Brno Czech Republic 616 00 - CZECH REPUBLIC - - 68-7F-74 (hex) Cisco-Linksys, LLC - 687F74 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - 68-83-1A (hex) Pandora Mobility Corporation - 68831A (base 16) Pandora Mobility Corporation - 1F., No.33, Fude St., - Guishan Township - Taoyuan Guishan 333 - TAIWAN, PROVINCE OF CHINA - - 68-84-70 (hex) eSSys Co.,Ltd - 688470 (base 16) eSSys Co.,Ltd - Daerung Post Tower 5 15F, 60-3 - Gasan-dong - Seoul Geumcheon-gu 153-702 - KOREA, REPUBLIC OF - - 68-85-40 (hex) IGI Mobile, Inc. - 688540 (base 16) IGI Mobile, Inc. - 4F Kyongnam Bldg., - 830-48 Yoksam-dong, Kangnam-gu - Seoul 135-080 - KOREA, REPUBLIC OF - - 68-85-6A (hex) OuterLink Corporation - 68856A (base 16) OuterLink Corporation - 187 Ballardvale St., Ste. A260 - Wilmington MA 01887 - UNITED STATES - - 68-86-A7 (hex) Cisco - 6886A7 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 68-86-E7 (hex) Orbotix, Inc. - 6886E7 (base 16) Orbotix, Inc. - 1155 Canyon Blvd. - Suite 210 - Boulder CO 80302 - UNITED STATES - - 68-87-6B (hex) INQ Mobile Limited - 68876B (base 16) INQ Mobile Limited - 6 Hester Road - Battersea London SW11 4AN - UNITED KINGDOM - - 68-8A-B5 (hex) EDP Servicos - 688AB5 (base 16) EDP Servicos - Rua Castilho, número 165, 5º andar - Lisboa 1070-050 - PORTUGAL - - 68-8F-84 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 688F84 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - 68-92-34 (hex) Ruckus Wireless - 689234 (base 16) Ruckus Wireless - 880 West Maude Ave. - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 68-94-23 (hex) Hon Hai Precision Ind. Co.,Ltd. - 689423 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 68-96-7B (hex) Apple - 68967B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 68-97-4B (hex) Shenzhen Costar Electronics Co. Ltd. - 68974B (base 16) Shenzhen Costar Electronics Co. Ltd. - No.94 Fuyuan 1st Road,Yuyuan Industrial Park, - Heping Village,Fuyong Town, BaoAn District - Shenzhen Guangdong 518103 - CHINA - - 68-97-E8 (hex) Society of Motion Picture & Television Engineers - 6897E8 (base 16) Society of Motion Picture & Television Engineers - 3 Barker Ave. FL5 - White Plains NY 10601 - UNITED STATES - - 68-99-CD (hex) Cisco - 6899CD (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 68-9C-5E (hex) AcSiP Technology Corp. - 689C5E (base 16) AcSiP Technology Corp. - 3F., No.22, Dalin Rd. - Taoyuan Taoyuan County 33067 - TAIWAN, PROVINCE OF CHINA - - 68-9C-70 (hex) Apple - 689C70 (base 16) Apple - 1 infinite loop - Cupertino CA 95014 - UNITED STATES - - 68-9C-E2 (hex) Cisco - 689CE2 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 68-9E-19 (hex) Texas Instruments - 689E19 (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 68-A0-F6 (hex) Huawei Technologies Co., Ltd - 68A0F6 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 68-A1-B7 (hex) Honghao Mingchuan Technology (Beijing) CO.,Ltd. - 68A1B7 (base 16) Honghao Mingchuan Technology (Beijing) CO.,Ltd. - Floor 8,Tower A, Wanliu Yicheng Building - No.11, Changchun Qiao Road, Haidian District - Beijing 100089 - CHINA - - 68-A3-78 (hex) FREEBOX SAS - 68A378 (base 16) FREEBOX SAS - 16 rue de la Ville l'Eveque - PARIS IdF 75008 - FRANCE - - 68-A3-C4 (hex) Liteon Technology Corporation - 68A3C4 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo, - TaiPei 23585 - TAIWAN, PROVINCE OF CHINA - - 68-A4-0E (hex) BSH Bosch and Siemens Home Appliances GmbH - 68A40E (base 16) BSH Bosch and Siemens Home Appliances GmbH - Im Gewerbepark B35 - Regensburg Bayern 93059 - GERMANY - - 68-A8-6D (hex) Apple - 68A86D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 68-AA-D2 (hex) DATECS LTD., - 68AAD2 (base 16) DATECS LTD., - BUL. TSARIGRADSKO SHOSSE 115A - SOFIA 1784 - BULGARIA - - 68-AB-8A (hex) RF IDeas - 68AB8A (base 16) RF IDeas - 4020 Winnetka Ave - Rolling Meadows IL 60008 - UNITED STATES - - 68-AE-20 (hex) Apple - 68AE20 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 68-AF-13 (hex) Futura Mobility - 68AF13 (base 16) Futura Mobility - 515 PENNSYLVANIA AVE - FORT WASHINTON PA 19034 - UNITED STATES - - 68-B0-94 (hex) INESA ELECTRON CO.,LTD - 68B094 (base 16) INESA ELECTRON CO.,LTD - 5F, NO.168, Tianlin Road - Shanghai 200233 - CHINA - - 68-B4-3A (hex) WaterFurnace International, Inc. - 68B43A (base 16) WaterFurnace International, Inc. - 9000 Conservation Way - Fort Wayne IN 46809 - UNITED STATES - - 68-B5-99 (hex) Hewlett-Packard Company - 68B599 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 68-B6-FC (hex) Hitron Technologies. Inc - 68B6FC (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C - Hsin-chu 300 - TAIWAN, PROVINCE OF CHINA - - 68-B8-D9 (hex) Act KDE, Inc. - 68B8D9 (base 16) Act KDE, Inc. - 196-14, Bangi-dong, Songpa-gu - Seoul 138-834 - KOREA, REPUBLIC OF - - 68-B9-83 (hex) b-plus GmbH - 68B983 (base 16) b-plus GmbH - Ulrichsberger Str. 17 - Deggendorf Bavaria 94469 - GERMANY - - 68-BC-0C (hex) CISCO SYSTEMS, INC. - 68BC0C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 68-BD-AB (hex) CISCO SYSTEMS, INC. - 68BDAB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 68-C9-0B (hex) Texas Instruments - 68C90B (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - 68-CA-00 (hex) Octopus Systems Limited - 68CA00 (base 16) Octopus Systems Limited - 36/F, 148 Electric Road - North Point - HONG KONG - - 68-CC-9C (hex) Mine Site Technologies - 68CC9C (base 16) Mine Site Technologies - 113 Wicks Road - North Ryde NSW 2113 - AUSTRALIA - - 68-CD-0F (hex) U Tek Company Limited - 68CD0F (base 16) U Tek Company Limited - FL5, BLDG12, 3RD DISTRICT, TANGTOU INDUSTRIAL PARK - SHIYAN, BAOAN - SHENZHEN GUANGDONG 518018 - CHINA - - 68-CE-4E (hex) L-3 Communications Infrared Products - 68CE4E (base 16) L-3 Communications Infrared Products - 3414 Herrmann Drive - Garland TX 75043 - UNITED STATES - - 68-D1-FD (hex) Shenzhen Trimax Technology Co.,Ltd - 68D1FD (base 16) Shenzhen Trimax Technology Co.,Ltd - Room 1016, 10F, Max Smart Commercial Center, - No.21 Bao Xing Road, Bao'an District, Shenzhen, PRC - Shenzhen Guangdong 518133 - CHINA - - 68-D2-47 (hex) Portalis LC - 68D247 (base 16) Portalis LC - 204 Fort Union Blvd. Ste. 202 - Midvale UT 84047 - UNITED STATES - - 68-D9-25 (hex) ProSys Development Services - 68D925 (base 16) ProSys Development Services - Mill House - 44-46 Mill Green Road - Mitcham Surrey CR4 4HY - UNITED KINGDOM - - 68-D9-3C (hex) Apple - 68D93C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 68-DB-67 (hex) Nantong Coship Electronics Co., Ltd - 68DB67 (base 16) Nantong Coship Electronics Co., Ltd - No.188 Xinsheng Road - Chongchuan Area - Nantong Jiangsu 226000 - CHINA - - 68-DB-96 (hex) OPWILL Technologies CO .,LTD - 68DB96 (base 16) OPWILL Technologies CO .,LTD - Room 415,Digital Media Building,NO.7 Shangdi Information Road,HaiDian District, - Beijing 100085 - CHINA - - 68-DC-E8 (hex) PacketStorm Communications - 68DCE8 (base 16) PacketStorm Communications - 20 Meridian Rd - Eatontown NJ 07724 - UNITED STATES - - 68-DF-DD (hex) Xiaomi inc. - 68DFDD (base 16) Xiaomi inc. - Office Building, The Rainbow City of China Resources, - NO.68,Qinghe Middle Street - Haidian District Beijing 100085 - CHINA - - 68-E1-66 (hex) PRIVATE - 68E166 (base 16) - - 68-E4-1F (hex) Unglaube Identech GmbH - 68E41F (base 16) Unglaube Identech GmbH - An der Moosach 3a - Massenhausen Bayern 85376 - GERMANY - - 68-EB-AE (hex) Samsung Electronics Co.,Ltd - 68EBAE (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 68-EB-C5 (hex) Angstrem Telecom - 68EBC5 (base 16) Angstrem Telecom - Yuzhnaya promzona, passage 4806, 4, build 3 - Zelenograd Moscow 124460 - RUSSIAN FEDERATION - - 68-EC-62 (hex) YODO Technology Corp. Ltd. - 68EC62 (base 16) YODO Technology Corp. Ltd. - 8F., No.168-1, Liancheng Rd - Zhonghe Dist - Taipei City 235 - TAIWAN, PROVINCE OF CHINA - - 68-ED-43 (hex) Research In Motion - 68ED43 (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 68-ED-A4 (hex) Shenzhen Seavo Technology Co.,Ltd - 68EDA4 (base 16) Shenzhen Seavo Technology Co.,Ltd - 5H,West Building,NO.210,Terra Hi-Tech Industrial Park, - Chegongmiao - Shenzhen Guangdong 518040 - CHINA - - 68-EE-96 (hex) Cisco SPVTG - 68EE96 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 68-EF-BD (hex) CISCO SYSTEMS, INC. - 68EFBD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 68-F0-6D (hex) ALONG INDUSTRIAL CO., LIMITED - 68F06D (base 16) ALONG INDUSTRIAL CO., LIMITED - FLAT/RM,3 11/F, HUNG TO INDUSTRIAL BUILDING - 80 HUNG TO ROAD, KWUN TONG ,KL - HONG KONG - HONG KONG - - 68-F0-BC (hex) Shenzhen LiWiFi Technology Co., Ltd - 68F0BC (base 16) Shenzhen LiWiFi Technology Co., Ltd - No.7, Xinxi Road, Hi-Tech Park (North Zone) - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 68-F1-25 (hex) Data Controls Inc. - 68F125 (base 16) Data Controls Inc. - 3-17-4 Ueno - Taito-ku Tokyo 1100005 - JAPAN - - 68-F7-28 (hex) LCFC(HeFei) Electronics Technology co., ltd - 68F728 (base 16) LCFC(HeFei) Electronics Technology co., ltd - YunGu Road 3188-1 - Hefei Economic And Technological Development Zone, HeFei, Anhui, China - Hefei Anhui 230000 - CHINA - - 68-F8-95 (hex) Redflow Limited - 68F895 (base 16) Redflow Limited - 1/27 Counihan Rd - Seventeen Mile Rocks - Brisbane Queensland 4073 - AUSTRALIA - - 68-FB-95 (hex) Generalplus Technology Inc. - 68FB95 (base 16) Generalplus Technology Inc. - 3F, No.8, Dusing Rd - Hsinchu Science Park - Hsinchu City 30077 - TAIWAN, PROVINCE OF CHINA - - 68-FC-B3 (hex) Next Level Security Systems, Inc. - 68FCB3 (base 16) Next Level Security Systems, Inc. - 6353 Corte Del Abeto - Suite 102 - Carlsbad CA 92011 - UNITED STATES - - 6C-02-73 (hex) Shenzhen Jin Yun Video Equipment Co., Ltd. - 6C0273 (base 16) Shenzhen Jin Yun Video Equipment Co., Ltd. - 4th floor, 78th, Matou Road - Xixiang, Bao'an District - Shenzhen Guangdong 518000 - CHINA - - 6C-04-60 (hex) RBH Access Technologies Inc. - 6C0460 (base 16) RBH Access Technologies Inc. - 2 Automatic Road - Unit 108 - Brampton Ontario L6S 6K8 - CANADA - - 6C-09-D6 (hex) Digiquest Electronics LTD - 6C09D6 (base 16) Digiquest Electronics LTD - 26 Park House - North End Road - London NW11 7PT - UNITED KINGDOM - - 6C-0B-84 (hex) Universal Global Scientific Industrial Co.,Ltd. - 6C0B84 (base 16) Universal Global Scientific Industrial Co.,Ltd. - 141, Lane 351, TaiPing Road, Sec.1 - Tsao-Tuen Nan-Tou 54261 - TAIWAN, PROVINCE OF CHINA - - 6C-0E-0D (hex) Sony Ericsson Mobile Communications AB - 6C0E0D (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 6C-0F-6A (hex) JDC Tech Co., Ltd. - 6C0F6A (base 16) JDC Tech Co., Ltd. - 370-12 Daemyung-ri Daegot-myun - Kimpo-si Kyunggi-do 410-853 - KOREA, REPUBLIC OF - - 6C-14-F7 (hex) Erhardt+Leimer GmbH - 6C14F7 (base 16) Erhardt+Leimer GmbH - Albert-Leimer-Platz 1 - Stadtbergen 86391 - GERMANY - - 6C-15-F9 (hex) Nautronix Limited - 6C15F9 (base 16) Nautronix Limited - Blackwood House - Union Grove Lane - Aberdeen AB10 6XU - UNITED KINGDOM - - 6C-18-11 (hex) Decatur Electronics - 6C1811 (base 16) Decatur Electronics - 715 Bright Street - Decatur IL 62522 - UNITED STATES - - 6C-19-8F (hex) D-Link International - 6C198F (base 16) D-Link International - 1 Internal Business Park, #03-12 - The Synergy - Singapore 609917 - SINGAPORE - - 6C-1E-70 (hex) Guangzhou YBDS IT Co.,Ltd - 6C1E70 (base 16) Guangzhou YBDS IT Co.,Ltd - Room 318,3/F,970 Kang Wang Bei Lu,Liwan District,Guangzhou,PRC - Guangzhou City Guangdong Province 510170 - CHINA - - 6C-20-56 (hex) Cisco - 6C2056 (base 16) Cisco - 170 West Tasman Drive - San Jose CA 95134 - UNITED STATES - - 6C-22-AB (hex) Ainsworth Game Technology - 6C22AB (base 16) Ainsworth Game Technology - 10 Holker Street - Newington New South Wales 2127 - AUSTRALIA - - 6C-23-B9 (hex) Sony Ericsson Mobile Communications AB - 6C23B9 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 6C-25-B9 (hex) BBK Electronics Corp., Ltd., - 6C25B9 (base 16) BBK Electronics Corp., Ltd., - #255,BBK Road, - Wusha,Chang'An, DongGuan City,Guangdong, 523860 - CHINA - - 6C-29-95 (hex) Intel Corporate - 6C2995 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 6C-2C-06 (hex) OOO NPP Systemotechnika-NN - 6C2C06 (base 16) OOO NPP Systemotechnika-NN - Nartova lane, 2v - Nizhny Novgorod Nizhegorodskaya oblast 603057 - RUSSIAN FEDERATION - - 6C-2E-33 (hex) Accelink Technologies Co.,Ltd. - 6C2E33 (base 16) Accelink Technologies Co.,Ltd. - 88 Youkeyuan Road, - Wuhan Hubei 430074 - CHINA - - 6C-2E-72 (hex) B&B EXPORTING LIMITED - 6C2E72 (base 16) B&B EXPORTING LIMITED - Bldg.#D,Xinhe Industrial Park - ,Huashan Sandong Avenue, Huadu - Guangzhou Guangdong 510880 - CHINA - - 6C-2E-85 (hex) SAGEMCOM - 6C2E85 (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON 92848 - FRANCE - - 6C-2F-2C (hex) Samsung Electronics Co.,Ltd - 6C2F2C (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 6C-32-DE (hex) Indieon Technologies Pvt. Ltd. - 6C32DE (base 16) Indieon Technologies Pvt. Ltd. - 601, Alpha 2, Gigaspace IT Park - Viman Nagar - Pune Maharastra 411014 - INDIA - - 6C-33-A9 (hex) Magicjack LP - 6C33A9 (base 16) Magicjack LP - 5700 Georgia Avenue - West Palm Beach FL 33405 - UNITED STATES - - 6C-39-1D (hex) Beijing ZhongHuaHun Network Information center - 6C391D (base 16) Beijing ZhongHuaHun Network Information center - 6F BeiAo Mansion,HuiXin East Street A2, - Chaoyang District, - Beijing 100029 - CHINA - - 6C-3A-84 (hex) Shenzhen Aero-Startech. Co.Ltd - 6C3A84 (base 16) Shenzhen Aero-Startech. Co.Ltd - F3-4, Building3,Zhongyuntai Industrial Park.Shiyan Town., - Bao'an District - Shenzhen Guangdong 518108 - CHINA - - 6C-3B-E5 (hex) Hewlett Packard - 6C3BE5 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 6C-3C-53 (hex) SoundHawk Corp - 6C3C53 (base 16) SoundHawk Corp - 20380 Town Center Lane - Suite 215 - Cupertino CA 95014 - UNITED STATES - - 6C-3E-6D (hex) Apple - 6C3E6D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 6C-3E-9C (hex) KE Knestel Elektronik GmbH - 6C3E9C (base 16) KE Knestel Elektronik GmbH - Osterwalder Str. 12 - Hopferbach Bavaria 87496 - GERMANY - - 6C-40-08 (hex) Apple - 6C4008 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 6C-40-C6 (hex) Nimbus Data Systems, Inc. - 6C40C6 (base 16) Nimbus Data Systems, Inc. - 701 Gateway Blvd - Ste 100 - South San Francisco CA 94080 - UNITED STATES - - 6C-41-6A (hex) Cisco - 6C416A (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 6C-44-18 (hex) Zappware - 6C4418 (base 16) Zappware - Ilgatlaan 19 - Hasselt Limburg 3500 - BELGIUM - - 6C-45-98 (hex) Antex Electronic Corp. - 6C4598 (base 16) Antex Electronic Corp. - 170 He Ping St., - Liujia Dist. - Tainan City Taiwan 73443 - TAIWAN, PROVINCE OF CHINA - - 6C-4B-7F (hex) Vossloh-Schwabe Deutschland GmbH - 6C4B7F (base 16) Vossloh-Schwabe Deutschland GmbH - Wasenstrasse 25 - Urbach 73660 - GERMANY - - 6C-50-4D (hex) CISCO SYSTEMS, INC. - 6C504D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 6C-57-79 (hex) Aclima, Inc. - 6C5779 (base 16) Aclima, Inc. - 10 Lombard Street - Suite 200 - San Francisco California 94111 - UNITED STATES - - 6C-59-40 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - 6C5940 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road - Ke Yuan West - Nanshan, Shenzhen Guangdong 518057 - CHINA - - 6C-5A-34 (hex) Shenzhen Haitianxiong Electronic Co., Ltd. - 6C5A34 (base 16) Shenzhen Haitianxiong Electronic Co., Ltd. - Rm.407, Block A, University-town Business Park, Taoyuan street, Lishan Road - Nanshan District - Shenzhen Guangdong 518055 - CHINA - - 6C-5A-B5 (hex) TCL Technoly Electronics (Huizhou) Co., Ltd. - 6C5AB5 (base 16) TCL Technoly Electronics (Huizhou) Co., Ltd. - 19th Zhongkai Hi-tech Development Zone - Huizhou Guangdong 516006 - CHINA - - 6C-5C-DE (hex) SunReports, Inc. - 6C5CDE (base 16) SunReports, Inc. - 1406 Cedarwood Dr. - San Mateo CA 94403 - UNITED STATES - - 6C-5D-63 (hex) ShenZhen Rapoo Technology Co., Ltd. - 6C5D63 (base 16) ShenZhen Rapoo Technology Co., Ltd. - Block A1,B1,B2,1st second stage, 1st Industrial Park, 3rd Industrial Zone ,Fenghuang Fuyong, BaoAn - ShenZhen 518103 - CHINA - - 6C-5E-7A (hex) Ubiquitous Internet Telecom Co., Ltd - 6C5E7A (base 16) Ubiquitous Internet Telecom Co., Ltd - #512, 5th Floor, Kolon Digital Valley,Guro 3(sam)-dong, Guro-gu - Seoul 152-777 - KOREA, REPUBLIC OF - - 6C-5F-1C (hex) Lenovo Mobile Communication Technology Ltd. - 6C5F1C (base 16) Lenovo Mobile Communication Technology Ltd. - No.999, Qishan North 2nd Road, - Information & Optoelectronics Park, Torch Hi-tech Industry Development Zone - Xiamen 361000 Fujian - CHINA - - 6C-61-26 (hex) Rinicom Holdings - 6C6126 (base 16) Rinicom Holdings - Riverway House - Morecambe Road - Lancaster Lancashire LA1 2RX - UNITED KINGDOM - - 6C-62-6D (hex) Micro-Star INT'L CO., LTD - 6C626D (base 16) Micro-Star INT'L CO., LTD - No.69, Lide St., Jhonghe City - Taipei Conuty 235 - TAIWAN, PROVINCE OF CHINA - - 6C-64-1A (hex) Penguin Computing - 6C641A (base 16) Penguin Computing - 45800 Northport Loop West - Fremont CA 94538 - UNITED STATES - - 6C-6E-FE (hex) Core Logic Inc. - 6C6EFE (base 16) Core Logic Inc. - 11th Fl., 1-B U-SPACE Bldg. - Daewangpangyo-ro, Bundang-gu - Seongnam Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - 6C-6F-18 (hex) Stereotaxis, Inc. - 6C6F18 (base 16) Stereotaxis, Inc. - 4320 Forest Park Ave - Suite 100 - St. Louis MO 63108 - UNITED STATES - - 6C-70-39 (hex) Novar GmbH - 6C7039 (base 16) Novar GmbH - Johannes-Mauthe-Str. 14 - Albstadt Baden-Württemberg 72458 - GERMANY - - 6C-70-9F (hex) Apple - 6C709F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 6C-71-D9 (hex) AzureWave Technologies, Inc - 6C71D9 (base 16) AzureWave Technologies, Inc - 9F.,No.92,Baozhong Rd - Xindian District New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 6C-76-60 (hex) KYOCERA Corporation - 6C7660 (base 16) KYOCERA Corporation - 2-1-1 Kagahara - Tsuzuki-ku - Yokohama-shi Kanagawa 224-8502 - JAPAN - - 6C-81-FE (hex) Mitsuba Corporation - 6C81FE (base 16) Mitsuba Corporation - 1-2681 - Hirosawa-cho - Kiryu Gunma 376-8555 - JAPAN - - 6C-83-36 (hex) Samsung Electronics Co.,Ltd - 6C8336 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 6C-83-66 (hex) Nanjing SAC Power Grid Automation Co., Ltd. - 6C8366 (base 16) Nanjing SAC Power Grid Automation Co., Ltd. - No11 Phoenix Road - Jiangning Development Zone, - Nanjing Jiangsu 211100 - CHINA - - 6C-86-86 (hex) Technonia - 6C8686 (base 16) Technonia - #1101, Hanshin IT Tower 235 - Guro-dong, Guro-gu - Seoul 152-768 - KOREA, REPUBLIC OF - - 6C-88-14 (hex) Intel Corporate - 6C8814 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 6C-8B-2F (hex) zte corporation - 6C8B2F (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 6C-8C-DB (hex) Otus Technologies Ltd - 6C8CDB (base 16) Otus Technologies Ltd - 26 Braid Road - Edinburgh Morningside EH10 6AD - UNITED KINGDOM - - 6C-8D-65 (hex) Wireless Glue Networks, Inc. - 6C8D65 (base 16) Wireless Glue Networks, Inc. - 1601 N. Main Street, Suite 202 - Walnut Creek CA 94596 - UNITED STATES - - 6C-90-B1 (hex) SanLogic Inc - 6C90B1 (base 16) SanLogic Inc - 2350 Mission College Blvd - Santa Clara CA 95054 - UNITED STATES - - 6C-92-BF (hex) Inspur Electronic Information Industry Co.,Ltd. - 6C92BF (base 16) Inspur Electronic Information Industry Co.,Ltd. - No 224 Shanda Road - Jinan Shandong 250013 - CHINA - - 6C-94-F8 (hex) Apple - 6C94F8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 6C-98-EB (hex) Ocedo GmbH - 6C98EB (base 16) Ocedo GmbH - Erbprinzenstrasse 27 - Karlsruhe BW 76133 - GERMANY - - 6C-99-89 (hex) Cisco - 6C9989 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 6C-9A-C9 (hex) Valentine Research, Inc. - 6C9AC9 (base 16) Valentine Research, Inc. - 10280 Alliance Rd - Cincinnati OH 45242 - UNITED STATES - - 6C-9B-02 (hex) Nokia Corporation - 6C9B02 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - 6C-9C-E9 (hex) Nimble Storage - 6C9CE9 (base 16) Nimble Storage - 2645 Zanker Road - San Jose CA 95134 - UNITED STATES - - 6C-9C-ED (hex) CISCO SYSTEMS, INC. - 6C9CED (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 6C-A1-00 (hex) Intel Corporate - 6CA100 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 6C-A6-82 (hex) EDAM information & communications - 6CA682 (base 16) EDAM information & communications - 601, Hanlim Veture town, 689-6 - Geumjeong-dong - Gunpo Gyenggi-Do 435-862 - KOREA, REPUBLIC OF - - 6C-A7-5F (hex) zte corporation - 6CA75F (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road - shenzhen guangdong 518057 - CHINA - - 6C-A7-80 (hex) Nokia Corporation - 6CA780 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 6C-A7-FA (hex) YOUNGBO ENGINEERING INC. - 6CA7FA (base 16) YOUNGBO ENGINEERING INC. - 132, Haewian-gil, Dunpo-myeon - Asan-si Chungcheongnam-do 336-873 - KOREA, REPUBLIC OF - - 6C-A8-49 (hex) Avaya, Inc - 6CA849 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 6C-A9-06 (hex) Telefield Ltd - 6CA906 (base 16) Telefield Ltd - Flat D,2/F., Valiant Industrial Centre,2-12 Au Pui Wan Street, - Fo Tan, N.T. - Hongkong 852 - CHINA - - 6C-A9-6F (hex) TransPacket AS - 6CA96F (base 16) TransPacket AS - Drammensveien 134 - Building 4 - Oslo 0277 - NORWAY - - 6C-AA-B3 (hex) Ruckus Wireless - 6CAAB3 (base 16) Ruckus Wireless - 350 W. Java Drive - Sunnyvale California 94089 - UNITED STATES - - 6C-AB-4D (hex) Digital Payment Technologies - 6CAB4D (base 16) Digital Payment Technologies - 4105 Grandview Hwy - Burnaby BC V5C 6B4 - CANADA - - 6C-AC-60 (hex) Venetex Corp - 6CAC60 (base 16) Venetex Corp - 8-3-9,Shin-machi - Ome-shi, Tokyo 198-0024 - JAPAN - - 6C-AD-3F (hex) Hubbell Building Automation, Inc. - 6CAD3F (base 16) Hubbell Building Automation, Inc. - 9601 Dessau Rd - Bldg 1 Suite 100 - Austin Texas 78754 - UNITED STATES - - 6C-AD-EF (hex) KZ Broadband Technologies, Ltd. - 6CADEF (base 16) KZ Broadband Technologies, Ltd. - 1601 Tower C - Skyworth Building, High-Tech - Shenzhen Guangdong 518057 - CHINA - - 6C-AD-F8 (hex) Azurewave Technologies, Inc. - 6CADF8 (base 16) Azurewave Technologies, Inc. - 8F., No.120, Sec. 2, Kongdao 5 Rd., Hsinchu, Taiwan 30056 - Taipei Taiwan 231 - TAIWAN, PROVINCE OF CHINA - - 6C-AE-8B (hex) IBM Corporation - 6CAE8B (base 16) IBM Corporation - 4400 North First Street - San Jose CA 95134 - UNITED STATES - - 6C-B0-CE (hex) NETGEAR - 6CB0CE (base 16) NETGEAR - 350 East Plumeria Drive - San Jose CA 95134 - UNITED STATES - - 6C-B3-11 (hex) Shenzhen Lianrui Electronics Co.,Ltd - 6CB311 (base 16) Shenzhen Lianrui Electronics Co.,Ltd - Block C4 XinTang Industrial Park - Baishixia FuYong Town BaoAn District - Shenzhen Guangdong 518000 - CHINA - - 6C-B3-50 (hex) Anhui comhigher tech co.,ltd - 6CB350 (base 16) Anhui comhigher tech co.,ltd - B6,717 Zhongshan South Road - Wuhu Anhui 241000 - CHINA - - 6C-B5-6B (hex) HUMAX.CO.,LTD - 6CB56B (base 16) HUMAX.CO.,LTD - HUMAX Village,216,Hwangsaeul-ro,Bundang-gu - Seongnam-city Geyonggi-do 463875 - KOREA, REPUBLIC OF - - 6C-B7-F4 (hex) Samsung Electronics Co.,Ltd - 6CB7F4 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 6C-BE-E9 (hex) Alcatel-Lucent-IPD - 6CBEE9 (base 16) Alcatel-Lucent-IPD - 777 Middlefield Rd. - Mountain View CA 94043 - UNITED STATES - - 6C-BF-B5 (hex) Noon Technology Co., Ltd - 6CBFB5 (base 16) Noon Technology Co., Ltd - Building C, Zhangkeng Industrial Park, Minzhi - Longhua, - Shenzhen GuangDong 518131 - CHINA - - 6C-C1-D2 (hex) ARRIS Group, Inc. - 6CC1D2 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 6C-C2-17 (hex) Hewlett Packard - 6CC217 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 6C-C2-6B (hex) Apple - 6CC26B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 6C-CA-08 (hex) ARRIS Group, Inc. - 6CCA08 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 6C-D0-32 (hex) LG Electronics - 6CD032 (base 16) LG Electronics - 16, Woomyeon-dong, Seocho-gu - Seoul 137-724 - KOREA, REPUBLIC OF - - 6C-D1-46 (hex) Smartek d.o.o. - 6CD146 (base 16) Smartek d.o.o. - B.J.Jelacica 22c - Cakovec Croatia 40000 - CROATIA - - 6C-D1-B0 (hex) WING SING ELECTRONICS HONG KONG LIMITED - 6CD1B0 (base 16) WING SING ELECTRONICS HONG KONG LIMITED - No. 1, Guoyuan Industrial Zone - Huancui South Road, Dongsha Dadao - Guangzhou Guang Dong 510385 - CHINA - - 6C-D6-8A (hex) LG Electronics Inc - 6CD68A (base 16) LG Electronics Inc - 60-39,Gasan-dong,Gumcheon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - 6C-DC-6A (hex) Promethean Limited - 6CDC6A (base 16) Promethean Limited - Activlab - Philips Road - Blackburn Lancashire BB1 5SN - UNITED KINGDOM - - 6C-E0-1E (hex) Modcam AB - 6CE01E (base 16) Modcam AB - Bredgatan 4 - Malmö SkÃ¥ne 21130 - SWEDEN - - 6C-E0-B0 (hex) SOUND4 - 6CE0B0 (base 16) SOUND4 - 11 quai Joseph Gillet - LYON 69004 - FRANCE - - 6C-E4-CE (hex) Villiger Security Solutions AG - 6CE4CE (base 16) Villiger Security Solutions AG - Giessenmatt 2 - Sins 5643 - SWITZERLAND - - 6C-E8-73 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 6CE873 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park - Shennan Rd, Nanshan - shenzhen guangdong Province 518057 - CHINA - - 6C-E9-07 (hex) Nokia Corporation - 6CE907 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 6C-E9-83 (hex) Gastron Co., LTD. - 6CE983 (base 16) Gastron Co., LTD. - #75-10, Palgok2-dong, Sangnok-gu, - Ansan-city Kyunggi-do 426-190 - KOREA, REPUBLIC OF - - 6C-EC-A1 (hex) SHENZHEN CLOU ELECTRONICS CO. LTD. - 6CECA1 (base 16) SHENZHEN CLOU ELECTRONICS CO. LTD. - 5/F, building. T2, Hi-tech Industrial Park - Nanshan District - SHENZ GUANGONG 518057 - CHINA - - 6C-EC-EB (hex) Texas Instruments - 6CECEB (base 16) Texas Instruments - 12500 TI BLVD - Dallas Texas 75243 - UNITED STATES - - 6C-F0-49 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 6CF049 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - No.215,Nan-Ping Road, - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 6C-F3-73 (hex) Samsung Electronics Co.,Ltd - 6CF373 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 6C-F3-7F (hex) Aruba Networks - 6CF37F (base 16) Aruba Networks - 1344 Crossman Ave. - Sunnyvale CA 94089 - UNITED STATES - - 6C-F5-E8 (hex) Mooredoll Inc. - 6CF5E8 (base 16) Mooredoll Inc. - 5F,No.50,Ln.316,Ruiguan Rd.,Neihu Dist.,Taipei 114, Taiwan - Taipei Neihu 114 - TAIWAN, PROVINCE OF CHINA - - 6C-F9-7C (hex) Nanoptix Inc. - 6CF97C (base 16) Nanoptix Inc. - 699 Champlain St - Dieppe NB E1A 1P6 - CANADA - - 6C-FA-58 (hex) Avaya, Inc - 6CFA58 (base 16) Avaya, Inc - 211 Mout Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 6C-FA-89 (hex) Cisco - 6CFA89 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 6C-FA-A7 (hex) AMPAK Technology Inc. - 6CFAA7 (base 16) AMPAK Technology Inc. - No.1,Jen Ai Road - Hsinchu Industrail Park,Hukou - Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - 6C-FD-B9 (hex) Proware Technologies Co Ltd. - 6CFDB9 (base 16) Proware Technologies Co Ltd. - 2nd F1 East Wing,South Section,Factory Building 24,Science&Technology Park - Shennan Rd,Nanshan District - Shenzhen Guangdong 518000 - CHINA - - 6C-FF-BE (hex) MPB Communications Inc. - 6CFFBE (base 16) MPB Communications Inc. - 147 Hymus Blvd - Pointe-Claire Quebec H9R 1E9 - CANADA - - 70-01-36 (hex) FATEK Automation Corporation - 700136 (base 16) FATEK Automation Corporation - 26FL., No. 29, Sec. 2, Jung Jeng E. Rd - Dan Shuei Dist - New Taipei City 25170 - TAIWAN, PROVINCE OF CHINA - - 70-02-58 (hex) 01DB-METRAVIB - 700258 (base 16) 01DB-METRAVIB - 200 CHEMIN DES ORMEAUX - LIMONEST CEDEX RHONE 69578 - FRANCE - - 70-05-14 (hex) LG Electronics - 700514 (base 16) LG Electronics - 60-39 , Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 70-0B-C0 (hex) Dewav Technology Company - 700BC0 (base 16) Dewav Technology Company - Room 1408, Real Estate Mansion - 201 Nanquan Road North - Shanghai 200120 - CHINA - - 70-0F-C7 (hex) SHENZHEN IKINLOOP TECHNOLOGY CO.,LTD. - 700FC7 (base 16) SHENZHEN IKINLOOP TECHNOLOGY CO.,LTD. - Room 8B,Building C, Tongfang Information Port, Langshan Road, Science - Shenzhen Guangdong 518057 - CHINA - - 70-0F-EC (hex) Poindus Systems Corp. - 700FEC (base 16) Poindus Systems Corp. - 5F., No. 59, Lane. 77, Xing-Ai Rd., Neihu Dist., - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 70-10-5C (hex) Cisco - 70105C (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 70-11-24 (hex) Apple - 701124 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-14-04 (hex) Limited Liability Company - 701404 (base 16) Limited Liability Company - I.Yakovleva St., 1 - Cheboksary Chuvash Republic 428003 - RUSSIAN FEDERATION - - 70-14-A6 (hex) Apple, Inc. - 7014A6 (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-18-8B (hex) Hon Hai Precision Ind. Co.,Ltd. - 70188B (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 70-1A-04 (hex) Liteon Tech Corp. - 701A04 (base 16) Liteon Tech Corp. - 4F 90 Chien 1 Rd.ChungHo - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 70-1A-ED (hex) ADVAS CO., LTD. - 701AED (base 16) ADVAS CO., LTD. - 3-8-8 Shin-yokohama, Kohoku-ku - Nissou 16Bldg. 6F - Yokohama-shi Kanagawa-ken 222-0033 - JAPAN - - 70-1D-7F (hex) Comtech Technology Co., Ltd. - 701D7F (base 16) Comtech Technology Co., Ltd. - 2F, No. 42, Sec. 3 Chung Yang Rd. - Tu Cheng Dist. - New Taipei City 23673 - TAIWAN, PROVINCE OF CHINA - - 70-23-93 (hex) fos4X GmbH - 702393 (base 16) fos4X GmbH - Thalkirchner Str. 210, Geb. 6 - 81371 München - GERMANY - - 70-25-26 (hex) Alcatel-Lucent - 702526 (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 70-25-59 (hex) CyberTAN Technology, Inc. - 702559 (base 16) CyberTAN Technology, Inc. - 99, Park Avenue III, Science-Based Industrial Park - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 70-2A-7D (hex) EpSpot AB - 702A7D (base 16) EpSpot AB - Aluddsparken 7D - Stockholm 11265 - SWEDEN - - 70-2B-1D (hex) E-Domus International Limited - 702B1D (base 16) E-Domus International Limited - 1st Floor - 5 Bourlet Close - London W1W 7BL - UNITED KINGDOM - - 70-2C-1F (hex) Wisol - 702C1F (base 16) Wisol - 377-3, Gajang-dong, Osan-si - 447-210 - KOREA, REPUBLIC OF - - 70-2D-D1 (hex) Newings Communication CO., LTD. - 702DD1 (base 16) Newings Communication CO., LTD. - 12F, Block 1, NO 7866, Humin Rd, Minhang District, Shanghai, China - Shanghai Shanghai 200000 - CHINA - - 70-2F-4B (hex) PolyVision Inc. - 702F4B (base 16) PolyVision Inc. - 3970 Johns Creek Ct. - Suite 325 - Suwanee Georgia 30024 - UNITED STATES - - 70-2F-97 (hex) Aava Mobile Oy - 702F97 (base 16) Aava Mobile Oy - Nahkatehtaankatu 2 - Oulu 90100 - FINLAND - - 70-30-18 (hex) Avaya, Inc - 703018 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 70-30-5D (hex) Ubiquoss Inc - 70305D (base 16) Ubiquoss Inc - 8F Ubiquoss B/D, 68, Pangyo-ro 255beon-gil, Bundang-gu - Seongnam-si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - 70-30-5E (hex) Nanjing Zhongke Menglian Information Technology Co.,LTD - 70305E (base 16) Nanjing Zhongke Menglian Information Technology Co.,LTD - 3rd Floor,Building A,Area 3 - Xuzhuang software Park - Nanjing Jiangsu 210042 - CHINA - - 70-31-87 (hex) ACX GmbH - 703187 (base 16) ACX GmbH - Äußere Zwickauer Straße 8 - Zwickau 08064 - GERMANY - - 70-32-D5 (hex) Athena Wireless Communications Inc - 7032D5 (base 16) Athena Wireless Communications Inc - 12425 W Bell Rd - Suite 110 - Surprise AZ 85378 - UNITED STATES - - 70-38-11 (hex) Invensys Rail - 703811 (base 16) Invensys Rail - PO Box 79 - Pew Hill - Chippenham Wiltshire SN15 1JD - UNITED KINGDOM - - 70-38-B4 (hex) Low Tech Solutions - 7038B4 (base 16) Low Tech Solutions - 350 N. Orleans - 3rd floor south - Chicago IL 60654 - UNITED STATES - - 70-38-EE (hex) Avaya, Inc - 7038EE (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 70-3A-D8 (hex) Shenzhen Afoundry Electronic Co., Ltd - 703AD8 (base 16) Shenzhen Afoundry Electronic Co., Ltd - 201, A Building, Bole Industrial Zone, Bantian, Longgang District - No# 906, 2 Building, Xincheng Plaza, Fuhuan RD-3, Futian District - Shenzhen Guangdong 518129 - CHINA - - 70-3C-39 (hex) SEAWING Kft - 703C39 (base 16) SEAWING Kft - Palánkai utca 5. - Székesfehérvár Fejér 8000 - HUNGARY - - 70-3E-AC (hex) Apple - 703EAC (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-41-B7 (hex) Edwards Lifesciences LLC - 7041B7 (base 16) Edwards Lifesciences LLC - One Edwards Way - Irvine CA 92614 - UNITED STATES - - 70-46-42 (hex) CHYNG HONG ELECTRONIC CO., LTD. - 704642 (base 16) CHYNG HONG ELECTRONIC CO., LTD. - No.80, Lane 258, Sec. 3, Hansi W. Rd., - Beitun District, - Taichung 40647 - TAIWAN, PROVINCE OF CHINA - - 70-4A-AE (hex) Xstream Flow (Pty) Ltd - 704AAE (base 16) Xstream Flow (Pty) Ltd - Room 123, Building 16, CSIR campus - Meiring Naude road - Pretoria Gauteng 0184 - SOUTH AFRICA - - 70-4A-E4 (hex) Rinstrum Pty Ltd - 704AE4 (base 16) Rinstrum Pty Ltd - 41 Success St - Acacia Ridge QLD 4110 - AUSTRALIA - - 70-4C-ED (hex) TMRG, Inc. - 704CED (base 16) TMRG, Inc. - 11950 Democracy Drive - Suite 600 - Reston VA 20190 - UNITED STATES - - 70-4E-01 (hex) KWANGWON TECH CO., LTD. - 704E01 (base 16) KWANGWON TECH CO., LTD. - D-401, Digital-Empire Bldg., 980-3 - Yeongtong-Dong, Yeongtong-Gu - Suwon Gyeonggi-Do 443-702 - KOREA, REPUBLIC OF - - 70-4E-66 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD - 704E66 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD - Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 70-52-C5 (hex) Avaya, Inc. - 7052C5 (base 16) Avaya, Inc. - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 70-53-3F (hex) Alfa Instrumentos Eletronicos Ltda. - 70533F (base 16) Alfa Instrumentos Eletronicos Ltda. - Rua Coronel Mario de Azevedo, 138 - Sao Paulo SP 02710-020 - BRAZIL - - 70-54-D2 (hex) PEGATRON CORPORATION - 7054D2 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 70-54-F5 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 7054F5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian - Longgang - ShenZhen GuangDong 518129 - CHINA - - 70-56-81 (hex) Apple - 705681 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-58-12 (hex) Panasonic AVC Networks Company - 705812 (base 16) Panasonic AVC Networks Company - 1-15 Matsuo-cho - Kadoma Osaka 571-8504 - JAPAN - - 70-59-57 (hex) Medallion Instrumentation Systems - 705957 (base 16) Medallion Instrumentation Systems - 17150 Hickory St - Spring Lake MI 49456 - UNITED STATES - - 70-59-86 (hex) OOO TTV - 705986 (base 16) OOO TTV - No. 75, Okulov Street, Building 8 - Perm 614068 - RUSSIAN FEDERATION - - 70-5A-B6 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - 705AB6 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN SUZHOU 215300 - CHINA - - 70-5B-2E (hex) M2Communication Inc. - 705B2E (base 16) M2Communication Inc. - Room 12, 18F., No.65, Gaotie 7th Road - Zhubei City Hsinchu County 302 - TAIWAN, PROVINCE OF CHINA - - 70-5C-AD (hex) Konami Gaming Inc - 705CAD (base 16) Konami Gaming Inc - 585 Trade Center Drive - Las Vegas Nevada 89119 - UNITED STATES - - 70-5E-AA (hex) Action Target, Inc. - 705EAA (base 16) Action Target, Inc. - PO Box 636 - Provo UT 84603 - UNITED STATES - - 70-60-DE (hex) LaVision GmbH - 7060DE (base 16) LaVision GmbH - Anna-Vandenhoeck-Ring 19 - Goettingen Niedersachsen 37081 - GERMANY - - 70-61-73 (hex) Calantec GmbH - 706173 (base 16) Calantec GmbH - Doebelner Str. 4 - Aufgang C - Berlin 12627 - GERMANY - - 70-62-B8 (hex) D-Link International - 7062B8 (base 16) D-Link International - 1 Internal Business Park, #03-12,The Synergy, Singapore - Singapore Singapore 609917 - SINGAPORE - - 70-64-17 (hex) ORBIS TECNOLOGIA ELECTRICA S.A. - 706417 (base 16) ORBIS TECNOLOGIA ELECTRICA S.A. - Lerida, 61 - Madrid Madrid E28020 - SPAIN - - 70-65-82 (hex) Suzhou Hanming Technologies Co., Ltd. - 706582 (base 16) Suzhou Hanming Technologies Co., Ltd. - Suite 407, No. 166, Ren Ai Road - Suzhou Industrial Park - Suzhou Jiangsu 215123 - CHINA - - 70-68-79 (hex) Saijo Denki International Co., Ltd. - 706879 (base 16) Saijo Denki International Co., Ltd. - 39/9 Moo 9 Soi Duangmanee - Ngamwongwan Rd., Bangkhen - Muang Nonthaburi 11000 - THAILAND - - 70-6F-81 (hex) PRIVATE - 706F81 (base 16) - - 70-70-4C (hex) Purple Communications, Inc - 70704C (base 16) Purple Communications, Inc - 595 Menlo - Rocklin CA 95765 - UNITED STATES - - 70-71-B3 (hex) Brain Corporation - 7071B3 (base 16) Brain Corporation - 5665 Morehouse Dr. - QRC-130 - San Diego CA 92121 - UNITED STATES - - 70-71-BC (hex) PEGATRON CORPORATION - 7071BC (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 70-72-0D (hex) Lenovo Mobile Communication Technology Ltd. - 70720D (base 16) Lenovo Mobile Communication Technology Ltd. - No.999, Qishan North 2nd Road, Information & Optoelectronics Park, Torch Hi-tech Industry Development Zone, Xiamen, P.R.China - Xiamen Fujian 361000 - CHINA - - 70-72-3C (hex) Huawei Technologies Co., Ltd - 70723C (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - 70-72-CF (hex) EdgeCore Networks - 7072CF (base 16) EdgeCore Networks - 20 Mason - Irvine CA 92618 - UNITED STATES - - 70-73-CB (hex) Apple - 7073CB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-76-30 (hex) Pace plc. - 707630 (base 16) Pace plc. - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - 70-76-DD (hex) Oxyguard International A/S - 7076DD (base 16) Oxyguard International A/S - Blokken 59 - Birkeroed DK-3460 - DENMARK - - 70-76-F0 (hex) LevelOne Communications (India) Private Limited - 7076F0 (base 16) LevelOne Communications (India) Private Limited - 2F, Lane 1, 45 Bharat Nagar - New Friends Colony - New Delhi DELHI 110025 - INDIA - - 70-76-FF (hex) KERLINK - 7076FF (base 16) KERLINK - 1 rue Jacqueline AURIOL - THORIGNE FOUILLARD Britany 35235 - FRANCE - - 70-77-81 (hex) Hon Hai Precision Ind. Co.,Ltd. - 707781 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - Xiyong Town - Shapingba District Chongqing 401332 - CHINA - - 70-7B-E8 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 707BE8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 70-7C-18 (hex) ADATA Technology Co., Ltd - 707C18 (base 16) ADATA Technology Co., Ltd - 2F, No.258, Lian Cheng Rd. - Chung Ho Dist. - New Taipei City 23553 - TAIWAN, PROVINCE OF CHINA - - 70-7E-43 (hex) ARRIS Group, Inc. - 707E43 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 70-7E-DE (hex) NASTEC LTD. - 707EDE (base 16) NASTEC LTD. - 111-D, Krasnorechenskaya str. - Khabarovsk 680006 - RUSSIAN FEDERATION - - 70-81-05 (hex) CISCO SYSTEMS, INC. - 708105 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 70-82-0E (hex) as electronics GmbH - 70820E (base 16) as electronics GmbH - Kantstraße 10 - Großbettlingen Baden -Württemberg 72663 - GERMANY - - 70-82-8E (hex) OleumTech Corporation - 70828E (base 16) OleumTech Corporation - 23 Hubble - Irvine CA 92618 - UNITED STATES - - 70-85-C6 (hex) Pace plc. - 7085C6 (base 16) Pace plc. - 2 rue Albert 1er - Saint-Cloud 92210 - FRANCE - - 70-8B-78 (hex) citygrow technology co., ltd - 708B78 (base 16) citygrow technology co., ltd - rm1404, blk A, ,5 - 21 Pak Tin Par Street - Hi-Tech Industrial Centre, - Tsuen Wan - HONG KONG - - 70-8D-09 (hex) Nokia Corporation - 708D09 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - 70-93-83 (hex) Intelligent Optical Network High Tech CO.,LTD. - 709383 (base 16) Intelligent Optical Network High Tech CO.,LTD. - Room 205,Building 11,Jia - NO.1,Chaoqian Road,Science and Technology Park - Changping District Beijing 102200 - CHINA - - 70-93-F8 (hex) Space Monkey, Inc. - 7093F8 (base 16) Space Monkey, Inc. - 7707 south main street - Suite 103 - Midvale Utah 84047 - UNITED STATES - - 70-97-56 (hex) Happyelectronics Co.,Ltd - 709756 (base 16) Happyelectronics Co.,Ltd - #A-805, Bundang Technopark, - 150 Yatap-Dong, Bundang-Gu - Seongnam-Si 463-816 - KOREA, REPUBLIC OF - - 70-9A-0B (hex) Italian Institute of Technology - 709A0B (base 16) Italian Institute of Technology - Via Morego 30 - Genova GE 16163 - ITALY - - 70-9B-A5 (hex) Shenzhen Y&D Electronics Co.,LTD. - 709BA5 (base 16) Shenzhen Y&D Electronics Co.,LTD. - D zone3F,Shenzhen Academy of Aerospace Technology,Hi-Tech Park,south 10th Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - 70-9B-FC (hex) Bryton Inc. - 709BFC (base 16) Bryton Inc. - 6F., No. 100, Zhouzi St., Neihu Dist. - Taipei City 11493 - TAIWAN, PROVINCE OF CHINA - - 70-9C-8F (hex) Nero AG - 709C8F (base 16) Nero AG - Rueppurrer Str. 1A - Karlsruhe BW 76137 - GERMANY - - 70-9E-29 (hex) Sony Computer Entertainment Inc. - 709E29 (base 16) Sony Computer Entertainment Inc. - 1-7-1 Konan - Minatoku Tokyo 108-0075 - JAPAN - - 70-9E-86 (hex) X6D Limited - 709E86 (base 16) X6D Limited - 199, Arch. Makariou III - Neocleous House - Limassol 3030 - CYPRUS - - 70-9F-2D (hex) zte corporation - 709F2D (base 16) zte corporation - 12/F.,zte R&D building - kejinan Road - shenzhen guangdong 518057 - CHINA - - 70-A1-91 (hex) Trendsetter Medical, LLC - 70A191 (base 16) Trendsetter Medical, LLC - 2030 Ardmore BLVD - STE 380 - Pittsburgh PA 15221 - UNITED STATES - - 70-A4-1C (hex) Advanced Wireless Dynamics S.L. - 70A41C (base 16) Advanced Wireless Dynamics S.L. - Centro de Empresas UPM oficina 3 - Campus UPM Montegancedo - Pozuelo de Alarcon Madrid 28223 - SPAIN - - 70-A6-6A (hex) Prox Dynamics AS - 70A66A (base 16) Prox Dynamics AS - Smedsvingen 4 - Hvalstad Akershus 1395 - NORWAY - - 70-A8-E3 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 70A8E3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - Shenzhen Guangdong 518129 - CHINA - - 70-AA-B2 (hex) Research In Motion - 70AAB2 (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 70-AD-54 (hex) Malvern Instruments Ltd - 70AD54 (base 16) Malvern Instruments Ltd - Grovewood Rd - Malvern Worcestershire WR14 1XZ - UNITED KINGDOM - - 70-AF-25 (hex) Nishiyama Industry Co.,LTD. - 70AF25 (base 16) Nishiyama Industry Co.,LTD. - 177-2 - Tenma - Fuji Shizuoka 419-0205 - JAPAN - - 70-B0-35 (hex) Shenzhen Zowee Technology Co., Ltd - 70B035 (base 16) Shenzhen Zowee Technology Co., Ltd - Block 5, Science and Technology Industrial - Park of Privately Owned Enterprises, Pingshan, Xili, Nanshan - Shenzhen Guangdong 518055 - CHINA - - 70-B0-8C (hex) Shenou Communication Equipment Co.,Ltd - 70B08C (base 16) Shenou Communication Equipment Co.,Ltd - No.118 Middle Juguang Road, High & New Industrial Zone - Wenzhou Zhejiang 325029 - CHINA - - 70-B1-4E (hex) Pace plc - 70B14E (base 16) Pace plc - Victoria Road - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - 70-B2-65 (hex) Hiltron s.r.l. - 70B265 (base 16) Hiltron s.r.l. - Strada Provinciale di Caserta, 218 - Naples 80144 - ITALY - - 70-B3-D5 (hex) IEEE REGISTRATION AUTHORITY - Please see OUI36 public listing for more information. - 70B3D5 (base 16) IEEE REGISTRATION AUTHORITY - Please see OUI36 public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 70-B5-99 (hex) Embedded Technologies s.r.o. - 70B599 (base 16) Embedded Technologies s.r.o. - Doubravice 134 - Turnov 51101 - CZECH REPUBLIC - - 70-B9-21 (hex) FiberHome Telecommunication Technologies CO.,LTD - 70B921 (base 16) FiberHome Telecommunication Technologies CO.,LTD - No.5 Dongxin Road,Hongshan District - Wuhan Hubei 430074 - CHINA - - 70-BA-EF (hex) Hangzhou H3C Technologies Co., Limited - 70BAEF (base 16) Hangzhou H3C Technologies Co., Limited - 466 Changhe Road, Binjiang District, - Hangzhou Zhejiang, P.R.China 310052 - CHINA - - 70-C6-AC (hex) Bosch Automotive Aftermarket - 70C6AC (base 16) Bosch Automotive Aftermarket - Franz Oechsle Str. 4 - Plochingen D-73201 - GERMANY - - 70-C7-6F (hex) INNO S - 70C76F (base 16) INNO S - 215beon-gil, 119 - Guri-si Gyeonggi-do 471-060 - KOREA, REPUBLIC OF - - 70-CA-9B (hex) CISCO SYSTEMS, INC. - 70CA9B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 70-CD-60 (hex) Apple - 70CD60 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-D4-F2 (hex) RIM - 70D4F2 (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - 70-D5-7E (hex) Scalar Corporation - 70D57E (base 16) Scalar Corporation - 1F San-Ei Bldg - 1-22-2 - Shinjuku-ku Tokyo 160-0023 - JAPAN - - 70-D5-E7 (hex) Wellcore Corporation - 70D5E7 (base 16) Wellcore Corporation - 2870 Zanker Road - Suite 130 - San Jose CA 95134 - UNITED STATES - - 70-D6-B6 (hex) Metrum Technologies - 70D6B6 (base 16) Metrum Technologies - 315 South University Parks Drive - Waco Texas 76701 - UNITED STATES - - 70-D8-80 (hex) Upos System sp. z o.o. - 70D880 (base 16) Upos System sp. z o.o. - Sienkiewicza 13 - Knurow Slaskie 44-190 - POLAND - - 70-D9-31 (hex) Cambridge Industries Group Co Ltd. - 70D931 (base 16) Cambridge Industries Group Co Ltd. - 22Floor,Qilai Tower;889Yishan Road - shanghai 200233 - CHINA - - 70-DA-9C (hex) TECSEN - 70DA9C (base 16) TECSEN - #401, Jeongsu Bd, 94-70, - Youngdeungpo-Dong 7 Ga, youngdeungpo-Gu, - SEOUL 150-037 - KOREA, REPUBLIC OF - - 70-DD-A1 (hex) Tellabs - 70DDA1 (base 16) Tellabs - One Tellabs Center - 1415 West Diehl Road - Naperville Illinois 60563 - UNITED STATES - - 70-DE-E2 (hex) Apple - 70DEE2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-E0-27 (hex) HONGYU COMMUNICATION TECHNOLOGY LIMITED - 70E027 (base 16) HONGYU COMMUNICATION TECHNOLOGY LIMITED - Room4B, East Building 210, - Tairan Technology Park, Futian District, - Shen Zhen Guang Dong Province 518040 - CHINA - - 70-E1-39 (hex) 3view Ltd - 70E139 (base 16) 3view Ltd - 168-172 Old Street - London EC1V 9BP - UNITED KINGDOM - - 70-E2-4C (hex) SAE IT-systems GmbH & Co. KG - 70E24C (base 16) SAE IT-systems GmbH & Co. KG - Im Gewerbegebiet Pesch 14 - Koln NRW 50767 - GERMANY - - 70-E2-84 (hex) Wistron InfoComm(Zhongshan) Corporation - 70E284 (base 16) Wistron InfoComm(Zhongshan) Corporation - No.38,East Keji Road,Zhongshan Torch Development Zone,Zhongshan City,Guangdong,China - Zhongshan Guangdong 528437 - CHINA - - 70-E7-2C (hex) Apple - 70E72C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 70-E8-43 (hex) Beijing C&W Optical Communication Technology Co.,Ltd. - 70E843 (base 16) Beijing C&W Optical Communication Technology Co.,Ltd. - 2/F Yufa Plaza, No.19 Xiaoying Beilu, Chaoyang District, - Beijing 100101 - CHINA - - 70-EE-50 (hex) Netatmo - 70EE50 (base 16) Netatmo - 17 route de la reine - Boulogne-Billancourt 92100 - FRANCE - - 70-F1-76 (hex) Data Modul AG - 70F176 (base 16) Data Modul AG - Landsberger Str. 322 - Munich Bavaria 80687 - GERMANY - - 70-F1-96 (hex) Actiontec Electronics, Inc - 70F196 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - 70-F1-A1 (hex) Liteon Technology Corporation - 70F1A1 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo,Taipei Hsien - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 70-F1-E5 (hex) Xetawave LLC - 70F1E5 (base 16) Xetawave LLC - 1668 Valtec Lane - Suite G - Boulder CO 80301 - UNITED STATES - - 70-F3-95 (hex) Universal Global Scientific Industrial Co., Ltd. - 70F395 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351, SEC.1,TAIPING RD. - TSAOTUEN - NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - 70-F9-27 (hex) Samsung Electronics - 70F927 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 70-F9-6D (hex) Hangzhou H3C Technologies Co., Limited - 70F96D (base 16) Hangzhou H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang, P.R.China 310053 - CHINA - - 70-FC-8C (hex) OneAccess SA - 70FC8C (base 16) OneAccess SA - 381 avenue du général de Gaulle - CLAMART France 92140 - FRANCE - - 70-FF-5C (hex) Cheerzing Communication(Xiamen)Technology Co.,Ltd - 70FF5C (base 16) Cheerzing Communication(Xiamen)Technology Co.,Ltd - Room N514,North Torch Building,5 Torch Road - Torch Garden,Torch High-tech Zone - Xiamen Fujian 361005 - CHINA - - 70-FF-76 (hex) Texas Instruments - 70FF76 (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 74-03-BD (hex) Buffalo Inc. - 7403BD (base 16) Buffalo Inc. - AKAMONDORI Bldg, 30-20, Ohsu 3-chome, - Minami-ku, Nagoya Aichi Pref. 457-8520 - JAPAN - - 74-04-2B (hex) Lenovo Mobile Communication (Wuhan) Company Limited - 74042B (base 16) Lenovo Mobile Communication (Wuhan) Company Limited - No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan, China 430205 - Wuhan Hubei 430205 - CHINA - - 74-0A-BC (hex) JSJS Designs (Europe) Limited - 740ABC (base 16) JSJS Designs (Europe) Limited - Ezekiel House - Ezekiel Lane - Willenhall West Midlands WV12 5QU - UNITED KINGDOM - - 74-0E-DB (hex) Optowiz Co., Ltd - 740EDB (base 16) Optowiz Co., Ltd - D-901 Bundang Techno Park - 151 Yatap-dong, Bundang-gu - Seongnam-si Kyeonggi-do 463-760 - KOREA, REPUBLIC OF - - 74-14-89 (hex) SRT Wireless - 741489 (base 16) SRT Wireless - 4101 SW 47th Avenue #102 - Davie Florida 33314 - UNITED STATES - - 74-15-E2 (hex) Tri-Sen Systems Corporation - 7415E2 (base 16) Tri-Sen Systems Corporation - 17625 El Camino Real Suite 200 - Houston TX 77058 - UNITED STATES - - 74-19-F8 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 7419F8 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 74-1E-93 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - 741E93 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - 74-1F-4A (hex) Hangzhou H3C Technologies Co., Limited - 741F4A (base 16) Hangzhou H3C Technologies Co., Limited - 466 Changhe Road, Binjiang District - Hangzhou Zhejiang 310052 - CHINA - - 74-25-8A (hex) Hangzhou H3C Technologies Co., Limited - 74258A (base 16) Hangzhou H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang, P.R.China 310053 - CHINA - - 74-26-AC (hex) Cisco - 7426AC (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 74-27-3C (hex) ChangYang Technology (Nanjing) Co., LTD - 74273C (base 16) ChangYang Technology (Nanjing) Co., LTD - NO.9 KaiCheng Road,QiLinTown - JiangNing District,NanJing - NanJing JiangSu 211100 - CHINA - - 74-27-EA (hex) Elitegroup Computer Systems Co., Ltd. - 7427EA (base 16) Elitegroup Computer Systems Co., Ltd. - No. 239, Sec. 2, Ti Ding Blvd., - Taipei Taiwan 11493 - TAIWAN, PROVINCE OF CHINA - - 74-29-AF (hex) Hon Hai Precision Ind. Co.,Ltd. - 7429AF (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - Xiyong Town,Shapingba District - Chongqing 401332 - CHINA - - 74-2B-0F (hex) Infinidat Ltd. - 742B0F (base 16) Infinidat Ltd. - 11 Galgalei Haplada St. - P.O.B 12696 - Herzliya Pituach Center 46722 - ISRAEL - - 74-2B-62 (hex) Fujitsu Limited - 742B62 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - 74-2D-0A (hex) Norfolk Elektronik AG - 742D0A (base 16) Norfolk Elektronik AG - Luzernstrasse 12 - Eschenbach LU 6274 - SWITZERLAND - - 74-2E-FC (hex) DirectPacket Research, Inc, - 742EFC (base 16) DirectPacket Research, Inc, - 909 Lake Carolyn Parkway - Suite 1800 - Irving Texas 75039 - UNITED STATES - - 74-2F-68 (hex) Azurewave Technologies, Inc. - 742F68 (base 16) Azurewave Technologies, Inc. - 8F., Baozhong Rd. - Xindian City Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - 74-31-70 (hex) Arcadyan Technology Corporation - 743170 (base 16) Arcadyan Technology Corporation - 4F. , No. 9 , Park Avenue II, - Hsinchu Science Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 74-32-56 (hex) NT-ware Systemprg GmbH - 743256 (base 16) NT-ware Systemprg GmbH - Niedersachsenstrasse 6 - Bad Iburg NDS 49186 - GERMANY - - 74-37-2F (hex) Tongfang Shenzhen Cloudcomputing Technology Co.,Ltd - 74372F (base 16) Tongfang Shenzhen Cloudcomputing Technology Co.,Ltd - 4,1 Building,FinanceBase,NO.8KeFaRoad,Science park - Nanshan District - ShenZhen City GuangDong 518057 - CHINA - - 74-38-89 (hex) ANNAX Anzeigesysteme GmbH - 743889 (base 16) ANNAX Anzeigesysteme GmbH - Wettersteinstrasse 18 - Taufkirchen Bavaria 82024 - GERMANY - - 74-3E-CB (hex) Gentrice tech - 743ECB (base 16) Gentrice tech - 15F No.738-5 JhengJhong Rd - JhengHo dist - New Taipei city 235 - TAIWAN, PROVINCE OF CHINA - - 74-44-01 (hex) NETGEAR - 744401 (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 74-45-8A (hex) Samsung Electronics Co.,Ltd - 74458A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 74-46-A0 (hex) Hewlett Packard - 7446A0 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston TX 77070 - UNITED STATES - - 74-4B-E9 (hex) EXPLORER HYPERTECH CO.,LTD - 744BE9 (base 16) EXPLORER HYPERTECH CO.,LTD - 7F.-9,NO.112,Xinmin St - Zhonghe Dist - New Taipei City 235 - TAIWAN, PROVINCE OF CHINA - - 74-4D-79 (hex) Arrive Systems Inc. - 744D79 (base 16) Arrive Systems Inc. - 1404 Franklin Street, # 350 - Oakland CA 94612 - UNITED STATES - - 74-51-BA (hex) XIAOMI INC - 7451BA (base 16) XIAOMI INC - The Rainbow city of China Resource,NO.68,Qinghe Middle street,Haidian District,Beijing,Chian. - Beijing Beijing 100085 - CHINA - - 74-53-27 (hex) COMMSEN CO., LIMITED - 745327 (base 16) COMMSEN CO., LIMITED - 12/F., San Toi Building,139 Connaught Road Central - 999077 - HONG KONG - - 74-54-7D (hex) Cisco SPVTG - 74547D (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 74-56-12 (hex) ARRIS Group, Inc. - 745612 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 74-57-98 (hex) TRUMPF Laser GmbH + Co. KG - 745798 (base 16) TRUMPF Laser GmbH + Co. KG - Aichhalder Str. 39 - Schramberg BW 78713 - GERMANY - - 74-5C-9F (hex) TCT mobile ltd. - 745C9F (base 16) TCT mobile ltd. - NO86,hechang 7th road - Zhongkai hi-tech District - Hui Zhou Guang Gong 516006 - CHINA - - 74-5E-1C (hex) PIONEER CORPORATION - 745E1C (base 16) PIONEER CORPORATION - 1-1 Shin-ogura - Saiwai-ku - Kawasaki-shi Kanagawa Prefecture 2120031 - JAPAN - - 74-5F-00 (hex) Samsung Semiconductor Inc. - 745F00 (base 16) Samsung Semiconductor Inc. - 3566 N. 1St Street - San Jose CA 95134 - UNITED STATES - - 74-5F-AE (hex) TSL PPL - 745FAE (base 16) TSL PPL - Units 1-2, First Avenue - Globe Park - Marlow Buckinghamshire SL7 1YA - UNITED KINGDOM - - 74-63-DF (hex) VTS GmbH - 7463DF (base 16) VTS GmbH - Am Königholz Ost 4 - Eglhausen Bavaria 85411 - GERMANY - - 74-65-D1 (hex) Atlinks - 7465D1 (base 16) Atlinks - 30 Avenue Geroge V - Paris 75008 - FRANCE - - 74-66-30 (hex) T:mi Ytti - 746630 (base 16) T:mi Ytti - Messitytonkatu 8 C 39 - Helsinki 00180 - FINLAND - - 74-6A-3A (hex) Aperi Corporation - 746A3A (base 16) Aperi Corporation - 360 Mobil Avenue - Suite 200 - Camarillo CA 93010 - UNITED STATES - - 74-6A-89 (hex) Rezolt Corporation - 746A89 (base 16) Rezolt Corporation - 2855 Bowers Avenue - Santa Clara CA 95051 - UNITED STATES - - 74-6A-8F (hex) VS Vision Systems GmbH - 746A8F (base 16) VS Vision Systems GmbH - Aspelohe 27A - Norderstedt Schleswig-Holstein 22848 - GERMANY - - 74-6B-82 (hex) MOVEK - 746B82 (base 16) MOVEK - 6517 Navaho Trail - Edina Minnesota 55439 - UNITED STATES - - 74-6F-3D (hex) Contec GmbH - 746F3D (base 16) Contec GmbH - Oberahrer Straße 9 - Sainerholz RP 56244 - GERMANY - - 74-72-F2 (hex) Chipsip Technology Co., Ltd. - 7472F2 (base 16) Chipsip Technology Co., Ltd. - 8F-1, No.186, Jian-Yi Road, ChungHo City, - Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 74-75-48 (hex) Amazon Technologies Inc. - 747548 (base 16) Amazon Technologies Inc. - P.O Box 8102 - Reno NV 89507 - UNITED STATES - - 74-78-18 (hex) ServiceAssure - 747818 (base 16) ServiceAssure - Ground Floor, Block P, Crystal Park One - 249 Basden Avenue, Lyttelton - Centurion Tshwane 0157 - SOUTH AFRICA - - 74-7B-7A (hex) ETH Inc. - 747B7A (base 16) ETH Inc. - #202 Mazium BLG, 545-6, Dangjung-dong, - Gunpo-si Gyeonggi-do 435-833 - KOREA, REPUBLIC OF - - 74-7D-B6 (hex) Aliwei Communications, Inc - 747DB6 (base 16) Aliwei Communications, Inc - Keji 6 Road , Hi-tech Industrial Park - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 74-7E-1A (hex) Red Embedded Design Limited - 747E1A (base 16) Red Embedded Design Limited - The Wave - View Croft Road - Shipley West Yorkshire BD17 7Du - UNITED KINGDOM - - 74-7E-2D (hex) Beijing Thomson CITIC Digital Technology Co. LTD. - 747E2D (base 16) Beijing Thomson CITIC Digital Technology Co. LTD. - 8301, No.8 Workshop, 3 Yongchangbei Road - Beijing Economic&Tecnnological Development Area - Beijing 100176 - CHINA - - 74-81-14 (hex) Apple - 748114 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 74-85-2A (hex) PEGATRON CORPORATION - 74852A (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - 74-86-7A (hex) Dell Inc - 74867A (base 16) Dell Inc - one dell way - Round rock Texas 78682 - UNITED STATES - - 74-88-2A (hex) HUAWEI TECHNOLOGIES CO.,LTD - 74882A (base 16) HUAWEI TECHNOLOGIES CO.,LTD - Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 74-88-8B (hex) ADB Broadband Italia - 74888B (base 16) ADB Broadband Italia - via Sarca 222 - Milano 20126 - ITALY - - 74-8E-08 (hex) Bestek Corp. - 748E08 (base 16) Bestek Corp. - No. 6, Lane 229, Sec. 3, Chang-Xing Rd. - Luzhu Township - Taoyuan 33852 - TAIWAN, PROVINCE OF CHINA - - 74-8E-F8 (hex) Brocade Communications Systems, Inc. - 748EF8 (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 74-8F-1B (hex) MasterImage 3D - 748F1B (base 16) MasterImage 3D - 131, Gasan Digital 1-ro, Geumcheon-gu - (BYC, HIGHCITY) Building A 22F - Seoul 153-803 - KOREA, REPUBLIC OF - - 74-8F-4D (hex) MEN Mikro Elektronik GmbH - 748F4D (base 16) MEN Mikro Elektronik GmbH - Neuwieder Str. 3 - 7 - Nuernberg Bavaria 90411 - GERMANY - - 74-90-50 (hex) Renesas Electronics Corporation - 749050 (base 16) Renesas Electronics Corporation - 1753, Shimonumabe, Nakahara-Ku - Kawasaki Kanagawa 211-8668 - JAPAN - - 74-91-1A (hex) Ruckus Wireless - 74911A (base 16) Ruckus Wireless - 880 West Maude Ave. - Sunnyvale CA 94085 - UNITED STATES - - 74-91-BD (hex) Four systems Co.,Ltd. - 7491BD (base 16) Four systems Co.,Ltd. - 608-608/7 Ramintra Road Kannayao - Bangkok 10230 - THAILAND - - 74-93-A4 (hex) Zebra Technologies Corp. - 7493A4 (base 16) Zebra Technologies Corp. - 20314 Seneca Meadows Parkway - Germantown Maryland 21771 - UNITED STATES - - 74-94-3D (hex) AgJunction - 74943D (base 16) AgJunction - 8444 N. 90th St - Suite 130 - Scottsdale AZ 85258 - UNITED STATES - - 74-96-37 (hex) Todaair Electronic Co., Ltd - 749637 (base 16) Todaair Electronic Co., Ltd - F.6 Electronic Building, No.1 Shuinan Guangdeli Road,Peng’Jiang District, Jiangmen, Guangdong, China - JiangMen Guangdong 529000 - CHINA - - 74-99-75 (hex) IBM Corporation - 749975 (base 16) IBM Corporation - 4400 North First Street - San Jose CA 95134 - UNITED STATES - - 74-9C-52 (hex) Huizhou Desay SV Automotive Co., Ltd. - 749C52 (base 16) Huizhou Desay SV Automotive Co., Ltd. - 103, Hechang 5th Road West, - Zhongkai National Hi-tech Industrial Development Zone - Huizhou Guangdong 516006 - CHINA - - 74-9C-E3 (hex) Art2Wave Canada Inc. - 749CE3 (base 16) Art2Wave Canada Inc. - Suite 310 - 515 Legget Dr - Ottawa Ontario K2K3G4 - CANADA - - 74-9D-DC (hex) 2Wire - 749DDC (base 16) 2Wire - 1764 Automation Parkway - San Jose Ca 95131 - UNITED STATES - - 74-A0-2F (hex) Cisco - 74A02F (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 74-A0-63 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 74A063 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - 74-A2-E6 (hex) Cisco - 74A2E6 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 74-A3-4A (hex) ZIMI CORPORATION - 74A34A (base 16) ZIMI CORPORATION - Room A913, 159 Chengjiang Road, Jiangyin City, Jiangsu Province, P, R.China - 214400 - CHINA - - 74-A4-A7 (hex) QRS Music Technologies, Inc. - 74A4A7 (base 16) QRS Music Technologies, Inc. - 269 Quaker Drive - Seneca PA 16346 - UNITED STATES - - 74-A4-B5 (hex) Powerleader Science and Technology Co. Ltd. - 74A4B5 (base 16) Powerleader Science and Technology Co. Ltd. - Powerleader Technology Park, #3 Guanyi Rd. - Guanlan Hi-Tech Park, Longhua New Area - Shenzhen Guangdong 518110 - CHINA - - 74-A7-22 (hex) LG Electronics - 74A722 (base 16) LG Electronics - 603-39 , Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 74-AD-B7 (hex) China Mobile Group Device Co.,Ltd. - 74ADB7 (base 16) China Mobile Group Device Co.,Ltd. - 32 Xuanwumen West Street - Xicheng District - Beijing 100053 - CHINA - - 74-AE-76 (hex) iNovo Broadband, Inc. - 74AE76 (base 16) iNovo Broadband, Inc. - 3475 Corporate Way, Suite C - Duluth Georgia 30096 - UNITED STATES - - 74-B0-0C (hex) Network Video Technologies, Inc - 74B00C (base 16) Network Video Technologies, Inc - 4005 Bohannon Drive - Menlo Park CA 94025 - UNITED STATES - - 74-B9-EB (hex) Fujian JinQianMao Electronic Technology Co.,Ltd - 74B9EB (base 16) Fujian JinQianMao Electronic Technology Co.,Ltd - Room 506 YongHeng Building NO.58 JiangBing Raod - FuZhou FuJian 350005 - CHINA - - 74-BA-DB (hex) Longconn Electornics(shenzhen)Co.,Ltd - 74BADB (base 16) Longconn Electornics(shenzhen)Co.,Ltd - Building D12,n 30,Xingye One Road - Fenghuang First Industrial Zone - Fuyong Street,Bao an District Shenzhen,Guangdong Province 518000 - CHINA - - 74-BE-08 (hex) ATEK Products, LLC - 74BE08 (base 16) ATEK Products, LLC - 210 NE 10th Avenue - Brainerd MN 56401 - UNITED STATES - - 74-BF-A1 (hex) HYUNTECK - 74BFA1 (base 16) HYUNTECK - #603 107-Dong, Jugong Apt., Changhyeon-ri, Hwado-eup - Namyangju-si Gyeonggi-do 472-779 - KOREA, REPUBLIC OF - - 74-C2-46 (hex) Amazon Technologies Inc. - 74C246 (base 16) Amazon Technologies Inc. - P.O Box 8102 - Reno NV 89507 - UNITED STATES - - 74-C6-21 (hex) Zhejiang Hite Renewable Energy Co.,LTD - 74C621 (base 16) Zhejiang Hite Renewable Energy Co.,LTD - NO1320,2th Ring Road(South) - Tongxiang City Zhejiang Province 314500 - CHINA - - 74-C9-9A (hex) Ericsson AB - 74C99A (base 16) Ericsson AB - Torshamnsgatan 36 - Stockholm SE-164 80 - SWEDEN - - 74-CA-25 (hex) Calxeda, Inc. - 74CA25 (base 16) Calxeda, Inc. - 7000 North Mopac Expressway - Suite 250 - Austin TX 78731 - UNITED STATES - - 74-CD-0C (hex) Smith Myers Communications Ltd. - 74CD0C (base 16) Smith Myers Communications Ltd. - The Omega Centre - Stratton Business Park - Biggleswade BEDS SG18 8QB - UNITED KINGDOM - - 74-CE-56 (hex) Packet Force Technology Limited Company - 74CE56 (base 16) Packet Force Technology Limited Company - 2F., No.25, Sec. 1, Shuangshi Rd., Central Dist., - Taichung 40046 - TAIWAN, PROVINCE OF CHINA - - 74-D0-2B (hex) ASUSTek COMPUTER INC. - 74D02B (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd - Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 74-D0-DC (hex) ERICSSON AB - 74D0DC (base 16) ERICSSON AB - Torshamnsgatan 48 - STOCKHOLM 164 83 - SWEDEN - - 74-D4-35 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 74D435 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - Pin-Jen City, Taoyuan, Taiwan, R.O.C. - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 74-D6-75 (hex) WYMA Tecnologia - 74D675 (base 16) WYMA Tecnologia - Rua Clímaco Barbosa, 171-179 - Cambuci - São Paulo 01523-000 - BRAZIL - - 74-D6-EA (hex) Texas Instruments - 74D6EA (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - 74-D8-50 (hex) Evrisko Systems - 74D850 (base 16) Evrisko Systems - 2322 Alpine Rd, Ste 10 - Eau Claire WI 54703 - UNITED STATES - - 74-DA-38 (hex) Edimax Technology Co. Ltd. - 74DA38 (base 16) Edimax Technology Co. Ltd. - No. 3, Wu-Chuan 3rd Road, - Wu-Gu Dist., - New Taipei City, 248 - TAIWAN, PROVINCE OF CHINA - - 74-DB-D1 (hex) Ebay Inc - 74DBD1 (base 16) Ebay Inc - 2211 N. First St - San Jose Ca 95131 - UNITED STATES - - 74-DE-2B (hex) Liteon Technology Corporation - 74DE2B (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road, ChungHo. Taipei Hsien 235,Taiwan - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 74-E0-6E (hex) Ergophone GmbH - 74E06E (base 16) Ergophone GmbH - Temmlerstrasse 5 - Marburg Hessen 35039 - GERMANY - - 74-E1-4A (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 74E14A (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 74-E1-B6 (hex) Apple - 74E1B6 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 74-E2-77 (hex) Vizmonet Pte Ltd - 74E277 (base 16) Vizmonet Pte Ltd - 32,Canberra drive,#05-28 - 76431 - SINGAPORE - - 74-E2-8C (hex) Microsoft Corporation - 74E28C (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond WA 98052 - UNITED STATES - - 74-E2-F5 (hex) Apple - 74E2F5 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 74-E4-24 (hex) APISTE CORPORATION - 74E424 (base 16) APISTE CORPORATION - 1-4-16 Dojimahama, Kita-ku - Osaka Japan 530-0004 - JAPAN - - 74-E5-0B (hex) Intel Corporate - 74E50B (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 74-E5-37 (hex) RADSPIN - 74E537 (base 16) RADSPIN - Songpa-gu Garak-dong 78 - IT Venture Tower West Wing 12th Fl. - Seoul 138-950 - KOREA, REPUBLIC OF - - 74-E5-43 (hex) Liteon Technology Corporation - 74E543 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo - New Taipei City Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - 74-E6-E2 (hex) Dell Inc. - 74E6E2 (base 16) Dell Inc. - One dell way - Round Rock Texas 78682 - UNITED STATES - - 74-E7-C6 (hex) ARRIS Group, Inc. - 74E7C6 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 74-EA-3A (hex) TP-LINK Technologies Co.,Ltd. - 74EA3A (base 16) TP-LINK Technologies Co.,Ltd. - Building 7, Second Part, Honghualing Industrial Zone - Xili,Nanshan District - Shenzhen Guangdong 518000 - CHINA - - 74-EC-F1 (hex) Acumen - 74ECF1 (base 16) Acumen - 6F, No.207-3, Sec 3, Beisin Rd - Sindian Dist New Taipei City 23143 - TAIWAN, PROVINCE OF CHINA - - 74-F0-6D (hex) AzureWave Technologies, Inc. - 74F06D (base 16) AzureWave Technologies, Inc. - 8F., Baozhong Rd., - Xindian City, Taipei County. 231 - TAIWAN, PROVINCE OF CHINA - - 74-F0-7D (hex) BnCOM Co.,Ltd - 74F07D (base 16) BnCOM Co.,Ltd - Room1007, Daehyun Techno World, 174 - Ojeon-dong, - Uiwang-si Gyeonggi-do 437-753 - KOREA, REPUBLIC OF - - 74-F1-02 (hex) Beijing HCHCOM Technology Co., Ltd - 74F102 (base 16) Beijing HCHCOM Technology Co., Ltd - Patton Building 8 floor,11# Wan liu zhong lu - Haidian District - Beijing China 100089 - CHINA - - 74-F4-13 (hex) Maxwell Forest - 74F413 (base 16) Maxwell Forest - Level 2, 51 Murray Street - Pyrmont NSW 2009 - AUSTRALIA - - 74-F6-12 (hex) ARRIS Group, Inc. - 74F612 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 74-F7-26 (hex) Neuron Robotics - 74F726 (base 16) Neuron Robotics - 91 Pearson Ave - Unit 2 - Somerville MA 02144 - UNITED STATES - - 74-F8-5D (hex) Berkeley Nucleonics Corp - 74F85D (base 16) Berkeley Nucleonics Corp - 2955 Kerner Blvd #D - San Rafael California 94901 - UNITED STATES - - 74-FD-A0 (hex) Compupal (Group) Corporation - 74FDA0 (base 16) Compupal (Group) Corporation - No.1555 Jiashan Avenue - Jiashan Zhejiang 314113 - CHINA - - 74-FE-48 (hex) ADVANTECH CO., LTD. - 74FE48 (base 16) ADVANTECH CO., LTD. - NO.1, Alley 20, Lane 26 - Rueiguang Rd, Neihu District, - TAIPEI 231 - TAIWAN, PROVINCE OF CHINA - - 74-FF-7D (hex) Wren Sound Systems, LLC - 74FF7D (base 16) Wren Sound Systems, LLC - 169 Gateshead Way - Phoenixville PA 19460 - UNITED STATES - - 78-02-8F (hex) Adaptive Spectrum and Signal Alignment (ASSIA), Inc. - 78028F (base 16) Adaptive Spectrum and Signal Alignment (ASSIA), Inc. - 333 Twin Dolphin Drive - Redwood City CA 94065 - UNITED STATES - - 78-07-38 (hex) Z.U.K. Elzab S.A. - 780738 (base 16) Z.U.K. Elzab S.A. - ul. Kruczkowskiego 39 - Zabrze 41-813 - POLAND - - 78-11-85 (hex) NBS Payment Solutions Inc. - 781185 (base 16) NBS Payment Solutions Inc. - 703 Evans Ave - Suite 400 - Toronto Ontario M9C 5E9 - CANADA - - 78-12-B8 (hex) ORANTEK LIMITED - 7812B8 (base 16) ORANTEK LIMITED - 5/F, Building E, Dakan Tech Park, Dakan village, Xili Town, Nanshan District, Shenzhen, China - Shenzhen Guangdong 518000 - CHINA - - 78-18-81 (hex) AzureWave Technologies, Inc. - 781881 (base 16) AzureWave Technologies, Inc. - 8F., No.94 Baozhong Rd., - Xindian, Taipei 23144 - TAIWAN, PROVINCE OF CHINA - - 78-19-2E (hex) NASCENT Technology - 78192E (base 16) NASCENT Technology - 2744 Yorkmont RD - Charlotte NC 28208 - UNITED STATES - - 78-19-F7 (hex) Juniper Networks - 7819F7 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 78-1C-5A (hex) SHARP Corporation - 781C5A (base 16) SHARP Corporation - 22-22,Nagaike-cho - Abeno-ku - Osaka city Osaka prefecture 545-8522 - JAPAN - - 78-1D-BA (hex) HUAWEI TECHNOLOGIES CO.,LTD - 781DBA (base 16) HUAWEI TECHNOLOGIES CO.,LTD - HUAWEI Industrial Base Bantian,Longgang - Shenzhen guangdong 518129 - CHINA - - 78-1D-FD (hex) Jabil Inc - 781DFD (base 16) Jabil Inc - 10500 Dr. Martin Luther King Jr. St. N. - Dock C - St. Petersburg Florida 33716 - UNITED STATES - - 78-1F-DB (hex) Samsung Electronics Co.,Ltd - 781FDB (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-22-3D (hex) Affirmed Networks - 78223D (base 16) Affirmed Networks - 35 Nagog Park - Acton MA 01720 - UNITED STATES - - 78-24-AF (hex) ASUSTek COMPUTER INC. - 7824AF (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 78-25-44 (hex) Omnima Limited - 782544 (base 16) Omnima Limited - Oxford Science Park - John Eccles House, Robert Robinson Ave - Oxford Oxfordshire OX4 4GP - UNITED KINGDOM - - 78-25-AD (hex) SAMSUNG ELECTRONICS CO., LTD. - 7825AD (base 16) SAMSUNG ELECTRONICS CO., LTD. - 416, MAETAN-3DONG, PALDAL-GU - SUWON CITY KYUNGKI-DO 442-742 - KOREA, REPUBLIC OF - - 78-2B-CB (hex) Dell Inc - 782BCB (base 16) Dell Inc - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 78-2E-EF (hex) Nokia Corporation - 782EEF (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 78-30-3B (hex) Stephen Technologies Co.,Limited - 78303B (base 16) Stephen Technologies Co.,Limited - 5/F, Building NO.1, TongXin Industry Zone - HengGang, LongGang - Shenzhen Guangdong 518115 - CHINA - - 78-30-E1 (hex) UltraClenz, LLC - 7830E1 (base 16) UltraClenz, LLC - 1440 W Indiantown Road - Suite 350 - Jupiter FL 33458 - UNITED STATES - - 78-31-2B (hex) zte corporation - 78312B (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - 78-31-C1 (hex) Apple - 7831C1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-32-4F (hex) Millennium Group, Inc. - 78324F (base 16) Millennium Group, Inc. - 16 Tech Circle - Suite 225 - Natick MA 01760 - UNITED STATES - - 78-3A-84 (hex) Apple - 783A84 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-3C-E3 (hex) Kai-EE - 783CE3 (base 16) Kai-EE - 3F.-12, No.79, Sec. 1, Xintai 5th Rd., - Xizhi Dist. - New Taipei City 22101 - TAIWAN, PROVINCE OF CHINA - - 78-3D-5B (hex) TELNET Redes Inteligentes S.A. - 783D5B (base 16) TELNET Redes Inteligentes S.A. - Polígono Industrial Centrovía - C/ Buenos Aires 18 - La Muela Zaragoza 50198 - SPAIN - - 78-3E-53 (hex) BSkyB Ltd - 783E53 (base 16) BSkyB Ltd - 130 Kings Road - Brentwood - Essex CM14 4EF - UNITED KINGDOM - - 78-3F-15 (hex) EasySYNC Ltd. - 783F15 (base 16) EasySYNC Ltd. - Unit 1, 2 Seaward Place - Centurion Business Park - Glasgow Scotland G41 1HH - UNITED KINGDOM - - 78-40-E4 (hex) Samsung Electronics Co.,Ltd - 7840E4 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-44-05 (hex) FUJITU(HONG KONG) ELECTRONIC Co.,LTD. - 784405 (base 16) FUJITU(HONG KONG) ELECTRONIC Co.,LTD. - 8/F,QingHai Building,Xiang Mei Road,Futian District - Shenzhen City - SHENZHEN GUANGDONG 518000 - CHINA - - 78-44-76 (hex) Zioncom technology co.,ltd - 784476 (base 16) Zioncom technology co.,ltd - A1&A2 building,lantian technology park, xinyu road, xingqiao henggang block, shajing street, Baoan District - shenzhen guangdong 518000 - CHINA - - 78-45-61 (hex) CyberTAN Technology Inc. - 784561 (base 16) CyberTAN Technology Inc. - 99 Park Ave III, Hsinchu Science Park - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 78-45-C4 (hex) Dell Inc - 7845C4 (base 16) Dell Inc - One Dell Way - MS:RR5-45 - Round Rock TX 78682 - UNITED STATES - - 78-46-C4 (hex) DAEHAP HYPER-TECH - 7846C4 (base 16) DAEHAP HYPER-TECH - #A-805, Woolim Lions Vally 5-cha, #144-3 Sangdaewon-dong, Jungwon-Gu - Seongnam Gyeonggi-Do 462-726 - KOREA, REPUBLIC OF - - 78-47-1D (hex) Samsung Electronics Co.,Ltd - 78471D (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-48-59 (hex) Hewlett Packard - 784859 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 78-49-1D (hex) The Will-Burt Company - 78491D (base 16) The Will-Burt Company - 169 S. Main St. - Orrivlle Ohio 44667 - UNITED STATES - - 78-4B-08 (hex) f.robotics acquisitions ltd - 784B08 (base 16) f.robotics acquisitions ltd - Yevulim, Industrial Zone - Pardesia Hasharon 42815 - ISRAEL - - 78-4B-87 (hex) Murata Manufacturing Co.,Ltd. - 784B87 (base 16) Murata Manufacturing Co.,Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 78-51-0C (hex) LiveU Ltd. - 78510C (base 16) LiveU Ltd. - 5 Hagavish St. - Kfar-Saba 44641 - ISRAEL - - 78-52-1A (hex) Samsung Electronics Co.,Ltd - 78521A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-52-62 (hex) Shenzhen Hojy Software Co., Ltd. - 785262 (base 16) Shenzhen Hojy Software Co., Ltd. - 3F,East of Building25,Keyuanxi,Number 5,Kezhixi Road, Science & Industry Park ,Nan Shan District ,Shenzhen - ShenZhen GuangDong 508057 - CHINA - - 78-54-2E (hex) D-Link International - 78542E (base 16) D-Link International - 1 Internal Business Park, #03-12. - The Synergy Singapore - Singapore 609917 - TAIWAN, PROVINCE OF CHINA - - 78-55-17 (hex) SankyuElectronics - 785517 (base 16) SankyuElectronics - 2-30-12 - Unoki - Ohta-ku Tokyo 146-0091 - JAPAN - - 78-57-12 (hex) Mobile Integration Workgroup - 785712 (base 16) Mobile Integration Workgroup - 4580 Klahanie DR SE STE 106 - Issaquah WA 98029 - UNITED STATES - - 78-58-F3 (hex) Vachen Co.,Ltd - 7858F3 (base 16) Vachen Co.,Ltd - Rm1206, Hanyang Bldg, 18, - Gukhoe-daero 70-gil, Yeongdeungpo-gu - Seoul 150-748 - KOREA, REPUBLIC OF - - 78-59-3E (hex) RAFI GmbH & Co.KG - 78593E (base 16) RAFI GmbH & Co.KG - Ravensburger Str. 128-134 - Berg Baden Wurttemberg 88276 - GERMANY - - 78-59-5E (hex) Samsung Electronics Co.,Ltd - 78595E (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-59-68 (hex) Hon Hai Precision Ind.Co.,Ltd. - 785968 (base 16) Hon Hai Precision Ind.Co.,Ltd. - B Section, Export Processing Zone, No. 50, Beijing Zhong Road - Yantai Economic And Technological Development Area, Shandong, P.R. China - Yantai Shandong 264006 - CHINA - - 78-5C-72 (hex) Hioso Technology Co., Ltd. - 785C72 (base 16) Hioso Technology Co., Ltd. - 6th Floor, 12th Building, Wangtang Industrial Zone, - Xingao Road, Xili, Nanshan District - Shenzhen Guangdong 518055 - CHINA - - 78-5F-4C (hex) Argox Information Co., Ltd. - 785F4C (base 16) Argox Information Co., Ltd. - 7F, No.126, Lane 235, Baoqiao Rd., Xindian Dist. - New Taipei City Taipei 231 - TAIWAN, PROVINCE OF CHINA - - 78-61-7C (hex) MITSUMI ELECTRIC CO.,LTD - 78617C (base 16) MITSUMI ELECTRIC CO.,LTD - Tsurumaki - 2-11-2 - Tama-shi Tokyo 206-8567 - JAPAN - - 78-66-AE (hex) ZTEC Instruments, Inc. - 7866AE (base 16) ZTEC Instruments, Inc. - 7715 Tiburon St. NE - Albuquerque NM 87109 - UNITED STATES - - 78-6A-89 (hex) Huawei Technologies Co., Ltd - 786A89 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 78-6C-1C (hex) Apple - 786C1C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-71-9C (hex) ARRIS Group, Inc. - 78719C (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 78-7E-61 (hex) Apple - 787E61 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-7F-62 (hex) GiK mbH - 787F62 (base 16) GiK mbH - Goethestraße 5 - Aachen 52064 - GERMANY - - 78-81-8F (hex) Server Racks Australia Pty Ltd - 78818F (base 16) Server Racks Australia Pty Ltd - 4 - 6 Endurance Ave - Queanbeyan NSW 2620 - AUSTRALIA - - 78-84-3C (hex) Sony Corporation - 78843C (base 16) Sony Corporation - 5-1-12 Kitashinagawa Shinagawa-ku - Tokyo 141-0001 - JAPAN - - 78-84-EE (hex) INDRA ESPACIO S.A. - 7884EE (base 16) INDRA ESPACIO S.A. - C/ ROC BORONAT, 133 - BARCELONA 08018 - SPAIN - - 78-89-73 (hex) CMC - 788973 (base 16) CMC - Industriepark De Bruwaan 37B - Oudenaarde Oost-Vlaanderen 9700 - BELGIUM - - 78-8C-54 (hex) Eltek Technologies LTD - 788C54 (base 16) Eltek Technologies LTD - Glatt Tower - PO Box 1133 - 8301 Glattzentrum ZH - SWITZERLAND - - 78-8D-F7 (hex) Hitron Technologies. Inc - 788DF7 (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd.Hsinchu - Hsinchu Science Park, - Hsin-chu 300 - TAIWAN, PROVINCE OF CHINA - - 78-92-3E (hex) Nokia Corporation - 78923E (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - 78-92-9C (hex) Intel Corporate - 78929C (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 78-96-84 (hex) ARRIS Group, Inc. - 789684 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - 78-98-FD (hex) Q9 Networks Inc. - 7898FD (base 16) Q9 Networks Inc. - Suite 4400, PO Box 235 - 77 King Street West - Toronto ON M5K 1J3 - CANADA - - 78-99-5C (hex) Nationz Technologies Inc - 78995C (base 16) Nationz Technologies Inc - 12F,Tower Building #3,China Academy of Science and Technology Development,Gaoxin South Ave.1 - Nashan District - Shen Zhen GuangDong 518057 - CHINA - - 78-99-66 (hex) Musilab Electronics (DongGuan)Co.,Ltd. - 789966 (base 16) Musilab Electronics (DongGuan)Co.,Ltd. - A2, LinDong 3 Road, LinCun - TangXia Town, DongGuan City, - DongGuan Guangdong 523710 - CHINA - - 78-99-8F (hex) MEDILINE ITALIA SRL - 78998F (base 16) MEDILINE ITALIA SRL - VIA 8 MARZO, 4 - CORTE TEGGE REGGIO NELL'EMILIA 42025 - ITALY - - 78-9C-E7 (hex) Shenzhen Aikede Technology Co., Ltd - 789CE7 (base 16) Shenzhen Aikede Technology Co., Ltd - Room 9B,Block B,Neptunus Mansion, - Nan Hai Road,Nan Shan district - Shenzhen Guangdong 518000 - CHINA - - 78-9E-D0 (hex) Samsung Electronics - 789ED0 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-9F-4C (hex) HOERBIGER Elektronik GmbH - 789F4C (base 16) HOERBIGER Elektronik GmbH - Justinus-Kernerstr. 7 - Ammerbuch Baden-Wuerttemberg D-72119 - GERMANY - - 78-9F-70 (hex) Apple Inc - 789F70 (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-9F-87 (hex) Siemens AG I IA PP PRM - 789F87 (base 16) Siemens AG I IA PP PRM - Gleiwitzer Strasse 555 - Nuremberg Bavaria 90475 - GERMANY - - 78-A0-51 (hex) iiNet Labs Pty Ltd - 78A051 (base 16) iiNet Labs Pty Ltd - Level 1 - 502 Hay Street - Subiaco WA 6008 - AUSTRALIA - - 78-A1-06 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 78A106 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - 78-A1-83 (hex) Advidia - 78A183 (base 16) Advidia - 3 Riverway - Suite 700 - Houston TX 77056 - UNITED STATES - - 78-A2-A0 (hex) Nintendo Co., Ltd. - 78A2A0 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 78-A3-51 (hex) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD - 78A351 (base 16) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD - 2F,Bldg. A,Kangmai Industrial Park,Renmin Rd - Guanlan,Longhua District, - Shenzhen Guangdong 518110 - CHINA - - 78-A3-E4 (hex) Apple - 78A3E4 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-A5-04 (hex) Texas Instruments - 78A504 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 78-A5-DD (hex) Shenzhen Smarteye Digital Electronics Co., Ltd - 78A5DD (base 16) Shenzhen Smarteye Digital Electronics Co., Ltd - #6 Northen Area - Shangxue S&T Industrial Park - Shenzhen Guangdong 518129 - CHINA - - 78-A6-83 (hex) Precidata - 78A683 (base 16) Precidata - CP 672 - Maladiere 71 - 2002 NE 2002 - SWITZERLAND - - 78-A6-BD (hex) DAEYEON Control&Instrument Co,.Ltd - 78A6BD (base 16) DAEYEON Control&Instrument Co,.Ltd - ACETECHNOTOWER 2-108, 197-7, Guro3-Dong, Guro-Gu, - Seoul 152-766 - KOREA, REPUBLIC OF - - 78-A7-14 (hex) Amphenol - 78A714 (base 16) Amphenol - 20 Valley St. - Endicott New York 13760 - UNITED STATES - - 78-A8-73 (hex) Samsung Electronics Co.,Ltd - 78A873 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-AB-60 (hex) ABB Australia - 78AB60 (base 16) ABB Australia - PMB 88 - Berrimah NT 0828 - AUSTRALIA - - 78-AB-BB (hex) Samsung Electronics Co.,LTD - 78ABBB (base 16) Samsung Electronics Co.,LTD - 416,Maetan 3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 78-AC-BF (hex) Igneous Systems - 78ACBF (base 16) Igneous Systems - 2401 4th Ave - Suite 200 - Seattle WA 98121 - UNITED STATES - - 78-AC-C0 (hex) Hewlett-Packard Company - 78ACC0 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - 78-AE-0C (hex) Far South Networks - 78AE0C (base 16) Far South Networks - 49 Bell Crescent - Westlake Business Park - Westlake Western Cape 7945 - SOUTH AFRICA - - 78-B3-B9 (hex) ShangHai sunup lighting CO.,LTD - 78B3B9 (base 16) ShangHai sunup lighting CO.,LTD - RM2508,Building 2,1077# Zu Chong Zhi Rd,Zhang Jiang Hi-Tech Park,Pudong New Area,ShangHai,China - shanghai shanghai 201203 - CHINA - - 78-B3-CE (hex) Elo touch solutions - 78B3CE (base 16) Elo touch solutions - 1033 McCarthy Boulevard - Milpitas CA 95035 - UNITED STATES - - 78-B5-D2 (hex) Ever Treasure Industrial Limited - 78B5D2 (base 16) Ever Treasure Industrial Limited - 15A Tung Lee Commercial Building - 91-97 Jervois Street - Sheung Wan 852 - HONG KONG - - 78-B6-C1 (hex) AOBO Telecom Co.,Ltd - 78B6C1 (base 16) AOBO Telecom Co.,Ltd - Room1508,Jiangong Building - No.20 Wensan Road - Hangzhou ZheJiang 310012 - CHINA - - 78-B8-1A (hex) INTER SALES A/S - 78B81A (base 16) INTER SALES A/S - Stavneagervej 22 - Egaa Jutland 8250 - DENMARK - - 78-BA-D0 (hex) Shinybow Technology Co. Ltd. - 78BAD0 (base 16) Shinybow Technology Co. Ltd. - 9Fl.,No.63,Ju Guang Rd.,Chung Ho Dist. - New Taipei 235 - TAIWAN, PROVINCE OF CHINA - - 78-BA-F9 (hex) Cisco - 78BAF9 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 78-BD-BC (hex) Samsung Electronics Co.,Ltd - 78BDBC (base 16) Samsung Electronics Co.,Ltd - 129, Samsung-ro, Youngtongl-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 78-BE-B6 (hex) Enhanced Vision - 78BEB6 (base 16) Enhanced Vision - 5882 MACHINE DR. - Huntington Beach California 92649 - UNITED STATES - - 78-BE-BD (hex) STULZ GmbH - 78BEBD (base 16) STULZ GmbH - Holsteiner Chausse 283 - Hamburg 22457 - GERMANY - - 78-C4-0E (hex) H&D Wireless - 78C40E (base 16) H&D Wireless - Sjövägen 17 - Solna 169 55 - SWEDEN - - 78-C4-AB (hex) Shenzhen Runsil Technology Co.,Ltd - 78C4AB (base 16) Shenzhen Runsil Technology Co.,Ltd - 4/F., Yuhua Building A, Yangmen Industrial Park, - Dakan 2nd Village, Xili Town, Nanshan District, - Shenzhen GuangDong 518055 - CHINA - - 78-C5-E5 (hex) Texas Instruments - 78C5E5 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 78-C6-BB (hex) Innovasic, Inc. - 78C6BB (base 16) Innovasic, Inc. - - Albuquerque NM 87109 - UNITED STATES - - 78-CA-04 (hex) Nokia Corporation - 78CA04 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 78-CA-39 (hex) Apple - 78CA39 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-CA-5E (hex) ELNO - 78CA5E (base 16) ELNO - 43 rue Michel Carré - Argenteuil - F95102 - FRANCE - - 78-CB-33 (hex) DHC Software Co.,Ltd - 78CB33 (base 16) DHC Software Co.,Ltd - 16/F,DHC Mansion No.3 Zijin - Digital Park.Zhichun - Beijing 100190 - CHINA - - 78-CD-8E (hex) SMC Networks Inc - 78CD8E (base 16) SMC Networks Inc - 20 Mason - Irvine CA 92618 - UNITED STATES - - 78-D0-04 (hex) Neousys Technology Inc. - 78D004 (base 16) Neousys Technology Inc. - 13F.-1, NO.1, BAOSHENG RD., - YONGHE CITY TAIPEI COUNTY 23444 - TAIWAN, PROVINCE OF CHINA - - 78-D1-29 (hex) Vicos - 78D129 (base 16) Vicos - Eugenmuellerstrasse 14 - Salzburg 5020 - AUSTRIA - - 78-D3-4F (hex) Pace-O-Matic, Inc. - 78D34F (base 16) Pace-O-Matic, Inc. - 4150 Blue Ridge Industrial Parkway - Norcross GA 30071 - UNITED STATES - - 78-D3-8D (hex) HONGKONG YUNLINK TECHNOLOGY LIMITED - 78D38D (base 16) HONGKONG YUNLINK TECHNOLOGY LIMITED - 15B 15/F CHEUK NANG PLAZA 250 HENNESSY RD HK - ShenzhenCity Guangdong Province 518103 - CHINA - - 78-D5-B5 (hex) NAVIELEKTRO KY - 78D5B5 (base 16) NAVIELEKTRO KY - HALLIMESTARINKATU 11 - KAARINA FIN-20780 - FINLAND - - 78-D6-6F (hex) Aristocrat Technologies Australia Pty. Ltd. - 78D66F (base 16) Aristocrat Technologies Australia Pty. Ltd. - Building A, Pinnacle Office Park - 85 Epping Road - North Ryde N.S.W. 2113 - AUSTRALIA - - 78-D6-F0 (hex) Samsung Electro Mechanics - 78D6F0 (base 16) Samsung Electro Mechanics - Metan Dong 314, Youngtong Gu - Suwon Kyung-gi Do. 443-743 - KOREA, REPUBLIC OF - - 78-D7-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 78D752 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 78-D9-9F (hex) NuCom HK Ltd. - 78D99F (base 16) NuCom HK Ltd. - Unit B 11/F, Eton Bldg, 288 Des Voeux Rd. Central - Hong Kong Hong Kong 00852 - CHINA - - 78-DA-6E (hex) Cisco - 78DA6E (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 78-DA-B3 (hex) GBO Technology - 78DAB3 (base 16) GBO Technology - 1150 Bayhill Dr. Ste. 111 - San Bruno CA 94066 - UNITED STATES - - 78-DD-08 (hex) Hon Hai Precision Ind. Co.,Ltd. - 78DD08 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 78-DD-D6 (hex) c-scape - 78DDD6 (base 16) c-scape - westerkade 22 - Gouda 2802 SL - NETHERLANDS - - 78-DE-E4 (hex) Texas Instruments - 78DEE4 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 78-E3-B5 (hex) Hewlett-Packard Company - 78E3B5 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - 78-E4-00 (hex) Hon Hai Precision Ind. Co.,Ltd. - 78E400 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 78-E7-D1 (hex) Hewlett-Packard Company - 78E7D1 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 78-E8-B6 (hex) zte corporation - 78E8B6 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 78-E9-80 (hex) RainUs Co.,Ltd - 78E980 (base 16) RainUs Co.,Ltd - E-703, Digital Empire, 16, Deogyeong-daero - 1556 beon-gill, Yeongtong-gu - Suwon-si Gyeonggi-do 443-702 - KOREA, REPUBLIC OF - - 78-EB-14 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD - 78EB14 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD - Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 78-EC-22 (hex) Shanghai Qihui Telecom Technology Co., LTD - 78EC22 (base 16) Shanghai Qihui Telecom Technology Co., LTD - Room 501, No 2 BoYun Rd, PuDong New Area, - Shanghai 201203 - CHINA - - 78-EC-74 (hex) Kyland-USA - 78EC74 (base 16) Kyland-USA - 1107 SE Willow Pl - Blue Springs MO 64014 - UNITED STATES - - 78-EF-4C (hex) Unetconvergence Co., Ltd. - 78EF4C (base 16) Unetconvergence Co., Ltd. - 101-511, Digital Empire2, 486, Shin-dong, Youngtong-gu - Suwon Kyonggi-do 443-390 - KOREA, REPUBLIC OF - - 78-F5-E5 (hex) BEGA Gantenbrink-Leuchten KG - 78F5E5 (base 16) BEGA Gantenbrink-Leuchten KG - Hennenbusch - Menden NRW 58708 - GERMANY - - 78-F5-FD (hex) Huawei Technologies Co., Ltd - 78F5FD (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - 78-F7-BE (hex) Samsung Electronics Co.,Ltd - 78F7BE (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 78-F7-D0 (hex) Silverbrook Research - 78F7D0 (base 16) Silverbrook Research - 3 Montague Street - Balmain New South Wales 2041 - AUSTRALIA - - 78-F9-44 (hex) PRIVATE - 78F944 (base 16) - - 78-FC-14 (hex) B Communications Pty Ltd - 78FC14 (base 16) B Communications Pty Ltd - 175 Heytesbury Rd - Subiaco WA 6008 - AUSTRALIA - - 78-FD-94 (hex) Apple - 78FD94 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 78-FE-3D (hex) Juniper Networks - 78FE3D (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 78-FE-41 (hex) Socus networks - 78FE41 (base 16) Socus networks - 2F.-2, No.215, Sec. 2, Chengde Rd., Datong Dist., - Taipei City 103 - TAIWAN, PROVINCE OF CHINA - - 78-FE-E2 (hex) Shanghai Diveo Technology Co., Ltd - 78FEE2 (base 16) Shanghai Diveo Technology Co., Ltd - No.8,Lane 777,LongWu Rd - 3F - Shanghai 200232 - CHINA - - 78-FF-57 (hex) Intel Corporate - 78FF57 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 7C-01-87 (hex) Curtis Instruments, Inc. - 7C0187 (base 16) Curtis Instruments, Inc. - 200 Kisco Avenue - Mt Kisco NY 10549 - UNITED STATES - - 7C-02-BC (hex) Hansung Electronics Co. LTD - 7C02BC (base 16) Hansung Electronics Co. LTD - 319, Bong san-ri, San dong-myun - Gumi city, Kyung Buk - Gumi 730-853 - KOREA, REPUBLIC OF - - 7C-03-4C (hex) SAGEMCOM - 7C034C (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON Ile de France 92848 - FRANCE - - 7C-03-D8 (hex) SAGEMCOM SAS - 7C03D8 (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON CEDEX IDF 92848 - FRANCE - - 7C-05-07 (hex) PEGATRON CORPORATION - 7C0507 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 7C-05-1E (hex) RAFAEL LTD. - 7C051E (base 16) RAFAEL LTD. - GUSH SEGEV POB 2250 - HAIFA 31008 - ISRAEL - - 7C-06-23 (hex) Ultra Electronics, CIS - 7C0623 (base 16) Ultra Electronics, CIS - 419 Bridport Road - Greenford Middlesex UB6 8UA - UNITED KINGDOM - - 7C-08-D9 (hex) Shanghai B-Star Technology Co - 7C08D9 (base 16) Shanghai B-Star Technology Co - 1158 Xiehe Road - Changning District - Shanghai 200335 - CHINA - - 7C-09-2B (hex) Bekey A/S - 7C092B (base 16) Bekey A/S - Bredebjergvej 6 - Taastrup 2630 - DENMARK - - 7C-0A-50 (hex) J-MEX Inc. - 7C0A50 (base 16) J-MEX Inc. - B2, 3F, No.1, Li-Hsin 1st Road, - Science Park - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 7C-0E-CE (hex) Cisco - 7C0ECE (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 7C-11-BE (hex) Apple - 7C11BE (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-11-CD (hex) QianTang Technology - 7C11CD (base 16) QianTang Technology - 36 Landmark Palace - Beijing 100125 - CHINA - - 7C-14-76 (hex) Damall Technologies SAS - 7C1476 (base 16) Damall Technologies SAS - Corso della Repubblica 65 - Fabriano Ancona 60044 - ITALY - - 7C-16-0D (hex) Saia-Burgess Controls AG - 7C160D (base 16) Saia-Burgess Controls AG - Bahnhofstrasse 18 - Murten FR 3280 - SWITZERLAND - - 7C-1A-03 (hex) 8Locations Co., Ltd. - 7C1A03 (base 16) 8Locations Co., Ltd. - 1F, No. 123, Chenggong 2rd Street - Zhube City Hsinchu 302 - TAIWAN, PROVINCE OF CHINA - - 7C-1A-FC (hex) Dalian Co-Edifice Video Technology Co., Ltd - 7C1AFC (base 16) Dalian Co-Edifice Video Technology Co., Ltd - 23F , Block A , #32 Huoju Road , Hi-Tech Zone - Dalian Liaoning 116023 - CHINA - - 7C-1D-D9 (hex) XIAOMI IMC - 7C1DD9 (base 16) XIAOMI IMC - The Rainbow city of Chian Resource,NO.68,Qinghe Middle Street.Haidian District, - Beijing 100085 - CHINA - - 7C-1E-52 (hex) Microsoft - 7C1E52 (base 16) Microsoft - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 7C-1E-B3 (hex) 2N TELEKOMUNIKACE a.s. - 7C1EB3 (base 16) 2N TELEKOMUNIKACE a.s. - Modranska 621 - Prague Czech Republic 14301 - CZECH REPUBLIC - - 7C-20-48 (hex) KoamTac - 7C2048 (base 16) KoamTac - 116 Village Boulevard - Suite 200 - Princeton New Jersey 08540 - UNITED STATES - - 7C-20-64 (hex) Alcatel Lucent IPD - 7C2064 (base 16) Alcatel Lucent IPD - 600 March Drive - Kanata Ontario K2K2E6 - CANADA - - 7C-25-87 (hex) chaowifi.com - 7C2587 (base 16) chaowifi.com - No. 502 1th Building TaiHe Square - ShangCheng District - HangZhou QianJiangRoad 310002 - CHINA - - 7C-2C-F3 (hex) Secure Electrans Ltd - 7C2CF3 (base 16) Secure Electrans Ltd - Pioneer House, Pioneer Business Park - North Road - Ellesmere Port CH65 1AD - UNITED KINGDOM - - 7C-2E-0D (hex) Blackmagic Design - 7C2E0D (base 16) Blackmagic Design - 11 Gateway Court - Port Melbourne - Melbourne Victoria 3207 - AUSTRALIA - - 7C-2F-80 (hex) Gigaset Communications GmbH - 7C2F80 (base 16) Gigaset Communications GmbH - SCM PE 2 - Frankenstrasse 2 - Bocholt 46395 - GERMANY - - 7C-33-6E (hex) MEG Electronics Inc. - 7C336E (base 16) MEG Electronics Inc. - Bogazici Universitesi Kuzey Kampus - BUN Teknopark Kat:2 No:306 Bebek-Besiktas - ISTANBUL 34342 - TURKEY - - 7C-38-6C (hex) Real Time Logic - 7C386C (base 16) Real Time Logic - 12515 Academy Ridge View - Colorado Springs CO 80921 - UNITED STATES - - 7C-39-20 (hex) SSOMA SECURITY - 7C3920 (base 16) SSOMA SECURITY - Unit 703, Daeryung Technotown 13th, - 664, Gasandong, - Geumcheongu Seoul 153754 - KOREA, REPUBLIC OF - - 7C-3B-D5 (hex) Imago Group - 7C3BD5 (base 16) Imago Group - Ramon Marti Alsina 2-4-6 - Badalona Barcelona 08911 - SPAIN - - 7C-3C-B6 (hex) Shenzhen Homecare Technology Co.,Ltd. - 7C3CB6 (base 16) Shenzhen Homecare Technology Co.,Ltd. - Homecare Industrial Zone,NO.30,Langdong road,Yangchuan, - Songgang Town,Bao'an District - Shenzhen Guangdong 5108105 - CHINA - - 7C-3E-9D (hex) PATECH - 7C3E9D (base 16) PATECH - #23-17. WonhyoRo-2Ga - YongSan-Gu Seoul 140112 - KOREA, REPUBLIC OF - - 7C-43-8F (hex) E-Band Communications Corp. - 7C438F (base 16) E-Band Communications Corp. - 10095 Scripps Ranch Ct. Ste A - San Diego CA 92131 - UNITED STATES - - 7C-44-4C (hex) Entertainment Solutions, S.L. - 7C444C (base 16) Entertainment Solutions, S.L. - Parque Empresarial Miraflores, nave 3 - Ctra. CastelloÌn Km 5,25 - Zaragoza 50720 - SPAIN - - 7C-49-B9 (hex) Plexus Manufacturing Sdn Bhd - 7C49B9 (base 16) Plexus Manufacturing Sdn Bhd - Plot 87 - Lebuhraya Kampung Jawa - Bayan Lepas Penang 11900 - MALAYSIA - - 7C-4A-82 (hex) Portsmith LLC - 7C4A82 (base 16) Portsmith LLC - 850 E. Franklin Road - Suite 401 - Meridian ID 83642 - UNITED STATES - - 7C-4A-A8 (hex) MindTree Wireless PVT Ltd - 7C4AA8 (base 16) MindTree Wireless PVT Ltd - LGF, Phase III, Mindtree West Campus, - Global Village Campus, RVCE Post, Mylasandra Village, off Mysore Road - Bangalore Karnataka 560 059 - INDIA - - 7C-4B-78 (hex) Red Sun Synthesis Pte Ltd - 7C4B78 (base 16) Red Sun Synthesis Pte Ltd - 639, #11-544 - Pasir Ris Drive 1 - 510539 - SINGAPORE - - 7C-4C-58 (hex) Scale Computing, Inc. - 7C4C58 (base 16) Scale Computing, Inc. - 2121 El Camino Real - Suite 100 - San Mateo UNITED STATES 94403 - UNITED STATES - - 7C-4C-A5 (hex) BSkyB Ltd - 7C4CA5 (base 16) BSkyB Ltd - 130 Kings Road - Brentwood Essex CM14 4EQ - UNITED KINGDOM - - 7C-4F-B5 (hex) Arcadyan Technology Corporation - 7C4FB5 (base 16) Arcadyan Technology Corporation - 4F., NO.9, Park Avenue II, - Hsinchu Science Park, - Hsinchu , 300 - TAIWAN, PROVINCE OF CHINA - - 7C-53-4A (hex) Metamako - 7C534A (base 16) Metamako - Suite 207 - 83 York Street - Sydney Other 2000 - AUSTRALIA - - 7C-55-E7 (hex) YSI, Inc. - 7C55E7 (base 16) YSI, Inc. - 1725 Brannum Lane - Yellow Springs Ohio 45387 - UNITED STATES - - 7C-5C-F8 (hex) Intel Corporate - 7C5CF8 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 7C-60-97 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 7C6097 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4-A52R,Huawei Industrial Base - Bantian Longgang - Shenzhen GuangDong 518129 - CHINA - - 7C-61-93 (hex) HTC Corporation - 7C6193 (base 16) HTC Corporation - No. 23, Xinghua Rd., - Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 7C-66-9D (hex) Texas Instruments - 7C669D (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 7C-69-F6 (hex) Cisco - 7C69F6 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 7C-6A-B3 (hex) IBC TECHNOLOGIES INC. - 7C6AB3 (base 16) IBC TECHNOLOGIES INC. - 1445 CHARLES STREET - Vancouver British Columbia V5L2S7 - CANADA - - 7C-6A-C3 (hex) GatesAir, Inc - 7C6AC3 (base 16) GatesAir, Inc - 5300 Kings Island Drive - Suite 101 - Mason Ohio 45040 - UNITED STATES - - 7C-6A-DB (hex) SafeTone Technology Co.,Ltd - 7C6ADB (base 16) SafeTone Technology Co.,Ltd - Room 323,ZhuouJi Plaza,No.16 AnDe Road,East District, - Beijing 100011 - CHINA - - 7C-6B-33 (hex) Tenyu Tech Co. Ltd. - 7C6B33 (base 16) Tenyu Tech Co. Ltd. - 1F., No.10, Ln. 36, Ganzhen 2nd St. - Danshui Dist - New Taipei City 251 - TAIWAN, PROVINCE OF CHINA - - 7C-6B-52 (hex) Tigaro Wireless - 7C6B52 (base 16) Tigaro Wireless - Shen A'ari 7 - PO 5193 - Even Yehuda 40500 - ISRAEL - - 7C-6C-39 (hex) PIXSYS SRL - 7C6C39 (base 16) PIXSYS SRL - VIA DELLA CROCE ROSSA, 42 - PADOVA PD 35129 - ITALY - - 7C-6C-8F (hex) AMS NEVE LTD - 7C6C8F (base 16) AMS NEVE LTD - BILLINGTON ROAD - BURNLEY LANCASHIRE BB11 5UB - UNITED KINGDOM - - 7C-6D-62 (hex) Apple - 7C6D62 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-6D-F8 (hex) Apple - 7C6DF8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-6F-06 (hex) Caterpillar Trimble Control Technologies - 7C6F06 (base 16) Caterpillar Trimble Control Technologies - 5475 Kellenburger Rd. - Dayton OH 45424 - UNITED STATES - - 7C-6F-F8 (hex) ShenZhen ACTO Digital Video Technology Co.,Ltd. - 7C6FF8 (base 16) ShenZhen ACTO Digital Video Technology Co.,Ltd. - 3/F,Building 7,Software Park - ,High-Tech Industrial Park,keji C. Rd.2nd - ShenZhen GuangDong 518055 - CHINA - - 7C-70-BC (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 7C70BC (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 7C-72-E4 (hex) Unikey Technologies - 7C72E4 (base 16) Unikey Technologies - 2250 Lee Rd - Suite 100 - Winter Park FL 32789 - UNITED STATES - - 7C-76-73 (hex) ENMAS GmbH - 7C7673 (base 16) ENMAS GmbH - Holzkoppelweg 23 - Kiel Schleswig-Holstein 24251 - GERMANY - - 7C-7A-53 (hex) Phytrex Technology Corp. - 7C7A53 (base 16) Phytrex Technology Corp. - 8F-16, No.81, Shuili Rd., - Hsinchu Taiwan 30059 - TAIWAN, PROVINCE OF CHINA - - 7C-7A-91 (hex) Intel Corporate - 7C7A91 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 7C-7B-E4 (hex) Z'SEDAI KENKYUSHO CORPORATION - 7C7BE4 (base 16) Z'SEDAI KENKYUSHO CORPORATION - Meikai sannomiya 2nd Bldg. 11th/fl. - 76-2 Kyomachi Chuo-ku - Kobe Hyogo 650-0034 - JAPAN - - 7C-7D-41 (hex) Jinmuyu Electronics Co., Ltd. - 7C7D41 (base 16) Jinmuyu Electronics Co., Ltd. - Room 132, Building 16, Tianqiaowan - Xinhua North Road, Tongzhou District - Beijing 101101 - CHINA - - 7C-82-2D (hex) Nortec - 7C822D (base 16) Nortec - 2740 Fenton Rd - Ottawa ON K1T3T7 - CANADA - - 7C-82-74 (hex) Shenzhen Hikeen Technology CO.,LTD - 7C8274 (base 16) Shenzhen Hikeen Technology CO.,LTD - 15rd floor,unit1,Building A of Kexing Science Park - Nanshan District - Shenzhen GuangDong 518057 - CHINA - - 7C-83-06 (hex) Glen Dimplex Nordic as - 7C8306 (base 16) Glen Dimplex Nordic as - Postboks 16 - Stjoerdal N-T 7501 - NORWAY - - 7C-8D-91 (hex) Shanghai Hongzhuo Information Technology co.,LTD - 7C8D91 (base 16) Shanghai Hongzhuo Information Technology co.,LTD - Room.161,Building 5,No.311 Jingao RD - Pudong Shanghai 200136 - CHINA - - 7C-8E-E4 (hex) Texas Instruments - 7C8EE4 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 7C-94-B2 (hex) Philips Healthcare PCCI - 7C94B2 (base 16) Philips Healthcare PCCI - 2271 Cosmos Ct - Carlsbad CA 92011 - UNITED STATES - - 7C-95-F3 (hex) Cisco - 7C95F3 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 7C-97-63 (hex) Openmatics s.r.o. - 7C9763 (base 16) Openmatics s.r.o. - Podebradova 2842/1 - 2842/1 - Pilsen Tschechien 30100 - CZECH REPUBLIC - - 7C-9A-9B (hex) VSE valencia smart energy - 7C9A9B (base 16) VSE valencia smart energy - Sir Alexander Fleming n - Paterna Valencia 46980 - SPAIN - - 7C-A1-5D (hex) GN ReSound A/S - 7CA15D (base 16) GN ReSound A/S - Lautrupbjerg 7 - Ballerup DK-CPH 2750 - DENMARK - - 7C-A2-9B (hex) D.SignT GmbH & Co. KG - 7CA29B (base 16) D.SignT GmbH & Co. KG - Marktstraße 10 - Kerken 47647 - GERMANY - - 7C-A6-1D (hex) MHL, LLC - 7CA61D (base 16) MHL, LLC - 1140 East Arques Avenue - Sunnyvale CA 94085 - UNITED STATES - - 7C-AC-B2 (hex) Bosch Software Innovations GmbH - 7CACB2 (base 16) Bosch Software Innovations GmbH - Ziegelei 7 - Immenstaad BadenWuertemberg 88090 - GERMANY - - 7C-AD-74 (hex) Cisco - 7CAD74 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 7C-B0-3E (hex) OSRAM GmbH - 7CB03E (base 16) OSRAM GmbH - Berliner Allee 65 - Augsburg Bayern 86136 - GERMANY - - 7C-B1-77 (hex) Satelco AG - 7CB177 (base 16) Satelco AG - Seestrasse 241 - Au / Waedenswil ZH 8804 - SWITZERLAND - - 7C-B2-1B (hex) Cisco SPVTG - 7CB21B (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville Georgia 30044 - UNITED STATES - - 7C-B2-32 (hex) Hui Zhou Gaoshengda Technology Co.,LTD - 7CB232 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD - No.75,Zhongkai High-Tech Development District,Huizhou - Huizhou Guangdong 516006 - CHINA - - 7C-B5-42 (hex) ACES Technology - 7CB542 (base 16) ACES Technology - #928, Hyundai Venture Ville - 713 Suseo-dong, Kangnam-gu - Seoul 135-539 - KOREA, REPUBLIC OF - - 7C-B7-33 (hex) ASKEY COMPUTER CORP - 7CB733 (base 16) ASKEY COMPUTER CORP - 10F,No.119,JIANKANG RD, - ZHONGHE DIST - NEW TAIPEI CITY 23585 TAIPEI - TAIWAN, PROVINCE OF CHINA - - 7C-B7-7B (hex) Paradigm Electronics Inc - 7CB77B (base 16) Paradigm Electronics Inc - 205 Annagem Blvd - Mississauga ON L5T 2VI - CANADA - - 7C-BB-6F (hex) Cosco Electronics Co., Ltd. - 7CBB6F (base 16) Cosco Electronics Co., Ltd. - #1101, ENC Dream tower, 327-27 - Gasan-dong, Geumcheon-gu - Seoul 153-793 - KOREA, REPUBLIC OF - - 7C-BD-06 (hex) AE REFUsol - 7CBD06 (base 16) AE REFUsol - Uracher Str. 91 - Metzingen Baden-Württemberg 72555 - GERMANY - - 7C-BF-88 (hex) Mobilicom LTD - 7CBF88 (base 16) Mobilicom LTD - Hametzoda 31 - Azor 5800174 - ISRAEL - - 7C-BF-B1 (hex) ARRIS Group, Inc. - 7CBFB1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 7C-C3-A1 (hex) Apple - 7CC3A1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-C4-EF (hex) Devialet - 7CC4EF (base 16) Devialet - 126, rue Réaumur - Paris Paris 75002 - FRANCE - - 7C-C5-37 (hex) Apple - 7CC537 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-C7-09 (hex) Shenzhen RF-LINK Elec&Technology.,Ltd - 7CC709 (base 16) Shenzhen RF-LINK Elec&Technology.,Ltd - Bldg56A, 6/F, Baotian Rd3 - Baoan - Shenzhen Guangdong 518100 - CHINA - - 7C-C8-AB (hex) Acro Associates, Inc. - 7CC8AB (base 16) Acro Associates, Inc. - 1990 Olivera Rd. - Suite A - Concord CA 94520 - UNITED STATES - - 7C-C8-D0 (hex) TIANJIN YAAN TECHNOLOGY CO., LTD. - 7CC8D0 (base 16) TIANJIN YAAN TECHNOLOGY CO., LTD. - No.8 Ziyuan Road,Huayuan Industrial Zone - Tianjin 300384 - CHINA - - 7C-C8-D7 (hex) Damalisk - 7CC8D7 (base 16) Damalisk - Coriolis 2 - Avenue de l'Europe - ECUISSES 71210 - FRANCE - - 7C-CB-0D (hex) Antaira Technologies, LLC - 7CCB0D (base 16) Antaira Technologies, LLC - 445 Capricorn St. - Brea California 92821 - UNITED STATES - - 7C-CC-B8 (hex) Intel Corporate - 7CCCB8 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech Park - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 7C-CD-11 (hex) MS-Magnet - 7CCD11 (base 16) MS-Magnet - Parchevich 42 - Sofia 1000 - BULGARIA - - 7C-CD-3C (hex) Guangzhou Juzing Technology Co., Ltd - 7CCD3C (base 16) Guangzhou Juzing Technology Co., Ltd - Building C Rm 1906-1909 - BaiNaoHui Squre Rd Tianhe 596 - Guangzhou Guangdong 510630 - CHINA - - 7C-CF-CF (hex) Shanghai SEARI Intelligent System Co., Ltd - 7CCFCF (base 16) Shanghai SEARI Intelligent System Co., Ltd - No.505 Wuning Road, Putuo District - Shanghai 200063 - CHINA - - 7C-D1-C3 (hex) Apple - 7CD1C3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-D3-0A (hex) INVENTEC Corporation - 7CD30A (base 16) INVENTEC Corporation - Inventec Building, 66 Hou-Kang Street - Shih-Lin District, - Taipei 111 - TAIWAN, PROVINCE OF CHINA - - 7C-D7-62 (hex) Freestyle Technology Pty Ltd - 7CD762 (base 16) Freestyle Technology Pty Ltd - 1A 24 Ricketts Road - Mount Waverley Victoria 3149 - AUSTRALIA - - 7C-D8-44 (hex) Enmotus Inc - 7CD844 (base 16) Enmotus Inc - 65 Enterprise - Aliso Viejo CA 92656 - UNITED STATES - - 7C-D9-FE (hex) New Cosmos Electric Co., Ltd. - 7CD9FE (base 16) New Cosmos Electric Co., Ltd. - 2-5-4 Mitsuyanaka - Yodogawa-ku - Osaka Osaka-fu 532-0036 - JAPAN - - 7C-DA-84 (hex) Dongnian Networks Inc. - 7CDA84 (base 16) Dongnian Networks Inc. - 90 Wensan Road, Building 8-A303 - Hangzhou Zhejiang 310012 - CHINA - - 7C-DD-11 (hex) Chongqing MAS SCI&TECH.Co.,Ltd - 7CDD11 (base 16) Chongqing MAS SCI&TECH.Co.,Ltd - 6th Floor, Zone C2,Hi-tech Venture Park, No.105 Erlang Venture Road - Jiulongpo District, - Chongqing City 400039 - CHINA - - 7C-DD-20 (hex) IOXOS Technologies S.A. - 7CDD20 (base 16) IOXOS Technologies S.A. - 4 Chemin de Fontenailles - GLAND VAUD CH-1196 - SWITZERLAND - - 7C-DD-90 (hex) Shenzhen Ogemray Technology Co., Ltd. - 7CDD90 (base 16) Shenzhen Ogemray Technology Co., Ltd. - 3 Floor, 9 Building, Minxing Industrial Zone, - Minkang Road, Minzhi Street, Baoan District, - Shenzhen Guangdong 518131 - CHINA - - 7C-E0-44 (hex) NEON Inc - 7CE044 (base 16) NEON Inc - 5340 Airport Boulevard - Boulder CO 80301 - UNITED STATES - - 7C-E1-FF (hex) Computer Performance, Inc. DBA Digital Loggers, Inc. - 7CE1FF (base 16) Computer Performance, Inc. DBA Digital Loggers, Inc. - 2695 Walsh Avenue - Santa Clara CA 95051 - UNITED STATES - - 7C-E4-AA (hex) PRIVATE - 7CE4AA (base 16) - - 7C-E5-24 (hex) Quirky, Inc. - 7CE524 (base 16) Quirky, Inc. - 606 W 28th Street - 7th Floor - New York NY 10001 - UNITED STATES - - 7C-E5-6B (hex) ESEN Optoelectronics Technology Co.,Ltd. - 7CE56B (base 16) ESEN Optoelectronics Technology Co.,Ltd. - Houcheng Yuanjiaqiao ,Jingang Town - Zhangjiagang Jiangsu 215631 - CHINA - - 7C-E9-D3 (hex) Hon Hai Precision Ind. Co.,Ltd. - 7CE9D3 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 7C-EB-EA (hex) ASCT - 7CEBEA (base 16) ASCT - 4F., No.49, Wu-Gong 6th Rd. Wu-Gu Industrial Park, - New Taipei City 248 - TAIWAN, PROVINCE OF CHINA - - 7C-EC-79 (hex) Texas Instruments - 7CEC79 (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 7C-ED-8D (hex) MICROSOFT - 7CED8D (base 16) MICROSOFT - One Microsoft Way - Redmond WA 98052-6399 - UNITED STATES - - 7C-EF-18 (hex) Creative Product Design Pty. Ltd. - 7CEF18 (base 16) Creative Product Design Pty. Ltd. - 82 Victoria Street - Sandringham Victoria 3191 - AUSTRALIA - - 7C-EF-8A (hex) Inhon International Ltd. - 7CEF8A (base 16) Inhon International Ltd. - 2F, No.552, Ruiguang Rd, Neihu Dist - Taipei Taiwan 114 - TAIWAN, PROVINCE OF CHINA - - 7C-F0-5F (hex) Apple - 7CF05F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-F0-98 (hex) Bee Beans Technologies, Inc. - 7CF098 (base 16) Bee Beans Technologies, Inc. - TCI B5 - 2-6-1 Sengen - Tsukuba City Ibaraki 305-0047 - JAPAN - - 7C-F0-BA (hex) Linkwell Telesystems Pvt Ltd - 7CF0BA (base 16) Linkwell Telesystems Pvt Ltd - 1-11-252/1/A, Gowra Klassic - Begumpet - Hyderabad Andhra Pradesh 500016 - INDIA - - 7C-F4-29 (hex) NUUO Inc. - 7CF429 (base 16) NUUO Inc. - C block, 18 Sihyuan St. Jhongjheng District, - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 7C-F8-54 (hex) Samsung Electronics - 7CF854 (base 16) Samsung Electronics - 415, Maetan-3dong, Yeongtong-gu, Suwon-City Gyeonggi-do 443-742 - Suwon 443-742 - KOREA, REPUBLIC OF - - 7C-F9-0E (hex) Samsung Electronics Co.,Ltd - 7CF90E (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 7C-FA-DF (hex) Apple - 7CFADF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 7C-FE-28 (hex) Salutron Inc. - 7CFE28 (base 16) Salutron Inc. - 40979 Encyclopedia Circle - Fremont CA 94538 - UNITED STATES - - 7C-FE-4E (hex) Shenzhen Safe vision Technology Co.,LTD - 7CFE4E (base 16) Shenzhen Safe vision Technology Co.,LTD - Shenzhen ring view south road and 27 digital dragon industrial park industrial zone - shenzhen Guangdong province 518110 - CHINA - - 7C-FF-62 (hex) Huizhou Super Electron Technology Co.,Ltd. - 7CFF62 (base 16) Huizhou Super Electron Technology Co.,Ltd. - 10F,Financial Tower,No.23,Xiapu Road - Huizhou City Guangdong Province 516001 - CHINA - - 80-00-0B (hex) Intel Corporate - 80000B (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 80-00-10 (hex) ATT BELL LABORATORIES - 800010 (base 16) ATT BELL LABORATORIES - 1100 EAST WARRENVILLE ROAD - NAPERVILLE IL 60566 - UNITED STATES - - 80-00-6E (hex) Apple - 80006E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 80-01-84 (hex) HTC Corporation - 800184 (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City, - Taoyuan 330 - TAIWAN, PROVINCE OF CHINA - - 80-05-DF (hex) Montage Technology Group Limited - 8005DF (base 16) Montage Technology Group Limited - Rm#A16F, Technolgy Blgd.,Yishan Rd. - Shanghai 200233 - CHINA - - 80-07-A2 (hex) Esson Technology Inc. - 8007A2 (base 16) Esson Technology Inc. - Room A2, 5F Longsheng Commericial Building, - Heping Road No.368, Longsheng community - Baoan District ShenZhen 518000 - CHINA - - 80-09-02 (hex) Keysight Technologies, Inc. - 800902 (base 16) Keysight Technologies, Inc. - 1400 Fountaingrove Pkwy. - M.S. 4US-L - Santa Rosa CA 95403 - UNITED STATES - - 80-0A-06 (hex) COMTEC co.,ltd - 800A06 (base 16) COMTEC co.,ltd - 60 shimoishida,azabu-cho, - Miyoshi-shi Aichi-ken 470-0206 - JAPAN - - 80-0B-51 (hex) Chengdu XGimi Technology Co.,Ltd - 800B51 (base 16) Chengdu XGimi Technology Co.,Ltd - 5F Building A7,Tianfu Software Park,Tianfu - Avenue,Hi-tech Zone - Chengdu Sichuan 610041 - CHINA - - 80-0E-24 (hex) ForgetBox - 800E24 (base 16) ForgetBox - 61 rue de Sèvres - Ville d'Avray IDF 92140 - FRANCE - - 80-14-40 (hex) Sunlit System Technology Corp - 801440 (base 16) Sunlit System Technology Corp - 8F, No.19,Lane 120, Sec1, Neihu Rd. - Tapiei 114 - TAIWAN, PROVINCE OF CHINA - - 80-14-A8 (hex) Guangzhou V-SOLUTION Electronic Technology Co., Ltd. - 8014A8 (base 16) Guangzhou V-SOLUTION Electronic Technology Co., Ltd. - Room 406,Originality Building B3, - NO.162 Science Avenue,Science Town - Guangzhou Guangdong 510663 - CHINA - - 80-16-B7 (hex) Brunel University - 8016B7 (base 16) Brunel University - School of IS, Computing & Maths - Kingston Lane - Uxbridge Middlesex UB8 3PH - UNITED KINGDOM - - 80-17-7D (hex) Nortel Networks - 80177D (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - 80-18-A7 (hex) Samsung Eletronics Co., Ltd - 8018A7 (base 16) Samsung Eletronics Co., Ltd - 416, Maetan 3dong, Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 80-19-34 (hex) Intel Corporate - 801934 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 80-19-67 (hex) Shanghai Reallytek Information Technology Co.,Ltd - 801967 (base 16) Shanghai Reallytek Information Technology Co.,Ltd - 906 Room,No.1 Building,No.3000 Longdong Avenue - Pudong - Shanghai 201203 - CHINA - - 80-1D-AA (hex) Avaya Inc - 801DAA (base 16) Avaya Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 80-1F-02 (hex) Edimax Technology Co. Ltd. - 801F02 (base 16) Edimax Technology Co. Ltd. - No. 3, Wu-Chuan 3rd Road, Wu-Ku Industrial Park, - Taipei Hsien 248 - TAIWAN, PROVINCE OF CHINA - - 80-20-AF (hex) Trade FIDES, a.s. - 8020AF (base 16) Trade FIDES, a.s. - Dornych 57 - Brno 61700 - CZECH REPUBLIC - - 80-22-75 (hex) Beijing Beny Wave Technology Co Ltd - 802275 (base 16) Beijing Beny Wave Technology Co Ltd - No.55, Jiachuang Road - Taihu Town - Tongzhou District Beijing 101111 - CHINA - - 80-2A-A8 (hex) Ubiquiti Networks, Inc. - 802AA8 (base 16) Ubiquiti Networks, Inc. - 2580 Orchard Parkway - San Jose CA 95131 - UNITED STATES - - 80-2A-FA (hex) Germaneers GmbH - 802AFA (base 16) Germaneers GmbH - Dr.-Kurt-Schumacher-Ring 3 - Wettstetten Bayern 85139 - GERMANY - - 80-2D-E1 (hex) Solarbridge Technologies - 802DE1 (base 16) Solarbridge Technologies - 9229 Waterford Centre Blvd - Building C, Suite 110 - Austin TX 78758 - UNITED STATES - - 80-2E-14 (hex) azeti Networks AG - 802E14 (base 16) azeti Networks AG - Am Brambusch 1a - Luenen NRW 44536 - GERMANY - - 80-2F-DE (hex) Zurich Instruments AG - 802FDE (base 16) Zurich Instruments AG - Technoparkstrasse 1 - Zurich 8005 - SWITZERLAND - - 80-34-57 (hex) OT Systems Limited - 803457 (base 16) OT Systems Limited - Unit 1023, 10/F., Landmark North, - Sheung Shui, N. T. - HONG KONG - - 80-37-73 (hex) Netgear Inc - 803773 (base 16) Netgear Inc - 350 East Plumeria Drive - San Jose CA 95134 - UNITED STATES - - 80-38-BC (hex) Huawei Technologies Co., Ltd - 8038BC (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 80-38-FD (hex) LeapFrog Enterprises, Inc. - 8038FD (base 16) LeapFrog Enterprises, Inc. - 6401 Holis Street - Emeryville CA 94608 - UNITED STATES - - 80-39-E5 (hex) PATLITE CORPORATION - 8039E5 (base 16) PATLITE CORPORATION - 19-2 - TECHNOPARK - SANDA HYOUGOKEN 669-1339 - JAPAN - - 80-3B-2A (hex) ABB Xiamen Low Voltage Equipment Co.,Ltd. - 803B2A (base 16) ABB Xiamen Low Voltage Equipment Co.,Ltd. - No.12-20,3rd Chuang Xin Road - Xiamen SEZ Fujian 361006 - CHINA - - 80-3B-9A (hex) ghe-ces electronic ag - 803B9A (base 16) ghe-ces electronic ag - Hoemelstraße 17 - Wald ZH 8636 - SWITZERLAND - - 80-3F-5D (hex) Winstars Technology Ltd - 803F5D (base 16) Winstars Technology Ltd - Block4,Taisong Industrial Park, DaLang Street, LongHua Town , Bao'an District - Shenzhen Guangdong 518109 - CHINA - - 80-3F-D6 (hex) bytes at work AG - 803FD6 (base 16) bytes at work AG - Konradstrasse 15 - Winterthur ZH 8400 - SWITZERLAND - - 80-41-4E (hex) BBK Electronics Corp., Ltd., - 80414E (base 16) BBK Electronics Corp., Ltd., - #255,BBK Road, - Wusha,Chang'An, DongGuan City,Guangdong, 523860 - CHINA - - 80-42-7C (hex) Adolf Tedsen GmbH & Co. KG - 80427C (base 16) Adolf Tedsen GmbH & Co. KG - Otto-Hahn-Str. 13-15 - Trittau Schleswig-Holstein D-22946 - GERMANY - - 80-47-31 (hex) Packet Design, Inc. - 804731 (base 16) Packet Design, Inc. - 2455 Augustine Drive - Suite 100 - Santa Clara CA 95054 - UNITED STATES - - 80-48-A5 (hex) SICHUAN TIANYI COMHEART TELECOM CO.,LTD - 8048A5 (base 16) SICHUAN TIANYI COMHEART TELECOM CO.,LTD - FL12,TowerB,TianYi International Hotel - ,No.2 West Section One,Second Ring Road - Chengdu Sichuan 61000 - CHINA - - 80-49-71 (hex) Apple - 804971 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 80-4B-20 (hex) Ventilation Control - 804B20 (base 16) Ventilation Control - Kronenstrasse 34 - Villingen-Schwenningen Baden-Wuerttemberg 78054 - GERMANY - - 80-4E-81 (hex) Samsung Electronics Co.,Ltd - 804E81 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 80-4F-58 (hex) ThinkEco, Inc. - 804F58 (base 16) ThinkEco, Inc. - 303 Fifth Avenue - 1801 - New York NY 10016 - UNITED STATES - - 80-50-1B (hex) Nokia Corporation - 80501B (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - 80-50-67 (hex) W & D TECHNOLOGY CORPORATION - 805067 (base 16) W & D TECHNOLOGY CORPORATION - 1F., NO.22, GONGYEQU 31TH RD - XITUN DIST - TAICHUNG CITY TAIWAN 40768 - TAIWAN, PROVINCE OF CHINA - - 80-56-F2 (hex) Hon Hai Precision Ind. Co.,Ltd. - 8056F2 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 80-57-19 (hex) Samsung Electronics Co.,Ltd - 805719 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 80-58-C5 (hex) NovaTec Kommunikationstechnik GmbH - 8058C5 (base 16) NovaTec Kommunikationstechnik GmbH - Technologiepark 9 - 4th Floor - Paderborn NRW 33100 - GERMANY - - 80-59-FD (hex) Noviga - 8059FD (base 16) Noviga - Lefortovskaya nab., 1 - Moscow - 105005 - RUSSIAN FEDERATION - - 80-60-07 (hex) RIM - 806007 (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 5R9 - CANADA - - 80-61-8F (hex) Shenzhen sangfei consumer communications co.,ltd - 80618F (base 16) Shenzhen sangfei consumer communications co.,ltd - 11 science and technology road,shenzhen hi-tech industrial park nanshan district,shenzhen 518057,PRC - ShenZhen China/GuangDong 518057 - CHINA - - 80-64-59 (hex) Nimbus Inc. - 806459 (base 16) Nimbus Inc. - 1359 Gwanpyeong-dong, Yuseong-gu - Suite 619 Hanshin S meca - Daejeon 305-509 - KOREA, REPUBLIC OF - - 80-65-E9 (hex) BenQ Corporation - 8065E9 (base 16) BenQ Corporation - 16 Jihu Road, Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 80-66-29 (hex) Prescope Technologies CO.,LTD. - 806629 (base 16) Prescope Technologies CO.,LTD. - 12F-1,No.192,Sec 2,Chung Hsin Road - Hsin Tien City Taipei County 23146 - TAIWAN, PROVINCE OF CHINA - - 80-6A-B0 (hex) Tinno Mobile Technology Corp - 806AB0 (base 16) Tinno Mobile Technology Corp - 4/F.,H-3 Building,OCT Eastern lndustrial Park - NO.1 XiangShan East Road - Nanshan District, Shenzhen GUANGDONG 518053 - CHINA - - 80-6C-1B (hex) Motorola Mobility LLC - 806C1B (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - 80-6C-8B (hex) KAESER KOMPRESSOREN AG - 806C8B (base 16) KAESER KOMPRESSOREN AG - Carl-Kaeser-Strasse 26 - Coburg Bavaria 96450 - GERMANY - - 80-6C-BC (hex) NET New Electronic Technology GmbH - 806CBC (base 16) NET New Electronic Technology GmbH - Lerchenberg 7 - Finning Bavarian 86923 - GERMANY - - 80-71-1F (hex) Juniper Networks - 80711F (base 16) Juniper Networks - 1194 N Mathilda Ave - Sunnyvale CA 94089 - UNITED STATES - - 80-71-7A (hex) Huawei Technologies Co., Ltd - 80717A (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 80-74-59 (hex) K's Co.,Ltd. - 807459 (base 16) K's Co.,Ltd. - 2864-16 Ryomitsuyanagi - Yonago Tottori 683-0853 - JAPAN - - 80-76-93 (hex) Newag SA - 807693 (base 16) Newag SA - Wyspianskiego 3 - Nowy Sacz woj. Malopolskie 33-300 - POLAND - - 80-79-AE (hex) ShanDong Tecsunrise Co.,Ltd - 8079AE (base 16) ShanDong Tecsunrise Co.,Ltd - B316,F-2,QiLu Soft Park, - No.1 ShunHua Road,Hi-tech Development Zone - JiNan ShanDong 250101 - CHINA - - 80-7A-7F (hex) ABB Genway Xiamen Electrical Equipment CO., LTD - 807A7F (base 16) ABB Genway Xiamen Electrical Equipment CO., LTD - 7F,No.23 Wanghai Road,Software Park 2, Lvling Road, - Xiamen Fujian Province 361008 - CHINA - - 80-7B-1E (hex) Corsair Components - 807B1E (base 16) Corsair Components - 46221 Landing Parkway - Fremont CA 94538 - UNITED STATES - - 80-7B-85 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 807B85 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 80-7D-1B (hex) Neosystem Co. Ltd. - 807D1B (base 16) Neosystem Co. Ltd. - 4-19-12 Takao - Dazaifu-shi Fukuoka 818-0122 - JAPAN - - 80-7D-E3 (hex) Chongqing Sichuan Instrument Microcircuit Co.LTD. - 807DE3 (base 16) Chongqing Sichuan Instrument Microcircuit Co.LTD. - Jinhua Road No.309, Beibei, - Chongqing 400700 - CHINA - - 80-81-A5 (hex) TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd - 8081A5 (base 16) TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd - Tongqing Industry Park,jiuwei,xixiang Town,Baoan District, - Shenzhen Guangdong 518126 - CHINA - - 80-82-87 (hex) ATCOM Technology Co.Ltd. - 808287 (base 16) ATCOM Technology Co.Ltd. - A-2F, #3 , Crown industry buildings - Chegongmiao Industry area,Futian district - Shenzhen Guang Dong 518040 - CHINA - - 80-86-98 (hex) Netronics Technologies Inc. - 808698 (base 16) Netronics Technologies Inc. - 600-15 Allstate Parkway - Markham Ontario L3R 5B4 - CANADA - - 80-86-F2 (hex) Intel Corporate - 8086F2 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 80-89-17 (hex) TP-LINK TECHNOLOGIES CO.,LTD - 808917 (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24 (floors 1,3,4,5) and 28 (floors1-4)  - Central Science and Technology Park - Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 - CHINA - - 80-8B-5C (hex) Shenzhen Runhuicheng Technology Co., Ltd - 808B5C (base 16) Shenzhen Runhuicheng Technology Co., Ltd - 315.3rd Floor Taoyuan Commercial Building A2 ridgepole Guang Qian Industrial Estate XiLi - Shenzhen Guangdong 518052 - CHINA - - 80-91-2A (hex) Lih Rong electronic Enterprise Co., Ltd. - 80912A (base 16) Lih Rong electronic Enterprise Co., Ltd. - 2F, No. 2, Lane 387, Hsin Shu Road - Hsin Chuang Taipei 242 - TAIWAN, PROVINCE OF CHINA - - 80-91-C0 (hex) AgileMesh, Inc. - 8091C0 (base 16) AgileMesh, Inc. - 1671 International Pkwy - Suite 113 - Richardson TX 75081 - UNITED STATES - - 80-92-9F (hex) Apple - 80929F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 80-93-93 (hex) Xapt GmbH - 809393 (base 16) Xapt GmbH - Neidenburger Str. 10 - Gelsenkirchen NRW 45897 - GERMANY - - 80-94-6C (hex) TOKYO RADAR CORPORATION - 80946C (base 16) TOKYO RADAR CORPORATION - 15-7 Nishikubo-cho - Hodogaya-ku, Yokohama-shi Kanagawa 240-0022 - JAPAN - - 80-96-B1 (hex) ARRIS Group, Inc. - 8096B1 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 80-96-CA (hex) Hon Hai Precision Ind Co.,Ltd - 8096CA (base 16) Hon Hai Precision Ind Co.,Ltd - G11 building, No. 2, 2nd Dong Huan Road, - 10th You Song Industrial District, - Long Hua TownShenZhen GuangDong 518109 - CHINA - - 80-97-1B (hex) Altenergy Power System,Inc. - 80971B (base 16) Altenergy Power System,Inc. - No.1 Yatai Road, - Jiaxing City, Zhejiang Province, 314050 - CHINA - - 80-9B-20 (hex) Intel Corporate - 809B20 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 80-9F-AB (hex) Fiberhome Telecommunication Technologies Co.,LTD - 809FAB (base 16) Fiberhome Telecommunication Technologies Co.,LTD - No.5 DongXin Road - Hongsan District - Wuhan Hubei 430074 - CHINA - - 80-A1-D7 (hex) Shanghai DareGlobal Technologies Co.,Ltd - 80A1D7 (base 16) Shanghai DareGlobal Technologies Co.,Ltd - 22F,Info Tech Building,No.1555,Kongjiang Rd. - Shanghai 200092 - CHINA - - 80-A8-5D (hex) Osterhout Design Group - 80A85D (base 16) Osterhout Design Group - 153 Townsend Suite 570 - San Francisco CA 94107 - UNITED STATES - - 80-AA-A4 (hex) USAG - 80AAA4 (base 16) USAG - 301 Goolsby Blvd - Deerfield Beach FL 33442 - UNITED STATES - - 80-AD-67 (hex) Kasda Networks Inc - 80AD67 (base 16) Kasda Networks Inc - B-31 Building, Tanglang Industry Zone, Xili, Nanshan District - Shenzhen Guangdong 518055 - CHINA - - 80-B2-19 (hex) ELEKTRON TECHNOLOGY UK LIMITED - 80B219 (base 16) ELEKTRON TECHNOLOGY UK LIMITED - BROERS BUILDING, - 21 JJ THOMSON AVENUE - CAMBRIDGE CAMBS CB3 0FA - UNITED KINGDOM - - 80-B2-89 (hex) Forworld Electronics Ltd. - 80B289 (base 16) Forworld Electronics Ltd. - No.16 Keyuan 2nd Rd., Situn District - Taichung City 886 - TAIWAN, PROVINCE OF CHINA - - 80-B3-2A (hex) Alstom Grid - 80B32A (base 16) Alstom Grid - St Leonard's Ave - Stafford Staffordshire ST17 4LX - UNITED KINGDOM - - 80-B6-86 (hex) Huawei Technologies Co., Ltd - 80B686 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - 80-B9-5C (hex) ELFTECH Co., Ltd. - 80B95C (base 16) ELFTECH Co., Ltd. - 174, Daehyeon Techno World 6F 609, - Ojeon-Dong - Uiwang-Si Gyeonggi-Do 437-753 - KOREA, REPUBLIC OF - - 80-BA-AC (hex) TeleAdapt Ltd - 80BAAC (base 16) TeleAdapt Ltd - Axis 5 - Rhodes Way - Watford Hertfordshire WD244YW - UNITED KINGDOM - - 80-BA-E6 (hex) Neets - 80BAE6 (base 16) Neets - Langballe 4 - Horsens Jylland 8700 - DENMARK - - 80-BB-EB (hex) Satmap Systems Ltd - 80BBEB (base 16) Satmap Systems Ltd - 4 Fountain House - Cleeve Road - Leatherhead Surrey KT22 7LX - UNITED KINGDOM - - 80-BE-05 (hex) Apple - 80BE05 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 80-C1-6E (hex) Hewlett Packard - 80C16E (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 80-C5-E6 (hex) Microsoft Corporation - 80C5E6 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 80-C6-3F (hex) Remec Broadband Wireless , LLC - 80C63F (base 16) Remec Broadband Wireless , LLC - 17034 Camino San Bernardo - San Diego CA 92127 - UNITED STATES - - 80-C6-AB (hex) Technicolor USA Inc. - 80C6AB (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 80-C6-CA (hex) Endian s.r.l. - 80C6CA (base 16) Endian s.r.l. - Pillhof 47 - Frangarto Bolzano 39010 - ITALY - - 80-C8-62 (hex) Openpeak, Inc - 80C862 (base 16) Openpeak, Inc - 1750 Clint Moore Rd - Boca Raton Florida 33487 - UNITED STATES - - 80-CE-B1 (hex) Theissen Training Systems GmbH - 80CEB1 (base 16) Theissen Training Systems GmbH - Schuchardstrasse 3 - Duesseldorf NRW 40595 - GERMANY - - 80-CF-41 (hex) Lenovo Mobile Communication Technology Ltd. - 80CF41 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone, - Xiamen Fujian 361006 - CHINA - - 80-D0-19 (hex) Embed, Inc - 80D019 (base 16) Embed, Inc - 410 Great Road - Littleton MA 01460 - UNITED STATES - - 80-D0-9B (hex) Huawei Technologies Co., Ltd - 80D09B (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 80-D1-8B (hex) Hangzhou I'converge Technology Co.,Ltd - 80D18B (base 16) Hangzhou I'converge Technology Co.,Ltd - No.618 Xixi Road, - Hangzhou Zhejiang 310012 - CHINA - - 80-D2-1D (hex) AzureWave Technologies, Inc - 80D21D (base 16) AzureWave Technologies, Inc - 8F., No. 94, Baozhong Rd. - Sindian Dist. - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 80-D4-33 (hex) LzLabs GmbH - 80D433 (base 16) LzLabs GmbH - Alte Winterthurerstrasse 14B - Wallisellen Zurich 8304 - SWITZERLAND - - 80-D7-33 (hex) QSR Automations, Inc. - 80D733 (base 16) QSR Automations, Inc. - 2301 Stanley Gault Pkwy - Louisville KY 40223 - UNITED STATES - - 80-DB-31 (hex) Power Quotient International Co., Ltd. - 80DB31 (base 16) Power Quotient International Co., Ltd. - 8F., No. 49, Sec. 4, Jhongyang Rd., Tu Cheng Dist., - New Taipei City 23675 - TAIWAN, PROVINCE OF CHINA - - 80-E4-DA (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 80E4DA (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 80-E6-50 (hex) Apple - 80E650 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 80-EA-96 (hex) Apple - 80EA96 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 80-EA-CA (hex) Dialog Semiconductor Hellas SA - 80EACA (base 16) Dialog Semiconductor Hellas SA - Leoforos Syggrou 143 - Nea Smyrni - Athens Attiki 17121 - GREECE - - 80-EE-73 (hex) Shuttle Inc. - 80EE73 (base 16) Shuttle Inc. - No. 30 Lane 76, Rei Kuang Rd - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 80-F2-5E (hex) Kyynel - 80F25E (base 16) Kyynel - Pirttikuja 3 - Oulu 90450 - FINLAND - - 80-F5-03 (hex) Pace plc - 80F503 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - 80-F5-93 (hex) IRCO Sistemas de Telecomunicación S.A. - 80F593 (base 16) IRCO Sistemas de Telecomunicación S.A. - Via Sergia 98 - Mataró Barcelona 08302 - SPAIN - - 80-F6-2E (hex) Hangzhou H3C Technologies Co., Limited - 80F62E (base 16) Hangzhou H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang, P.R.China 310053 - CHINA - - 80-F8-EB (hex) RayTight - 80F8EB (base 16) RayTight - Room 1-216, Building 25, No 9, Anningzhuang West Road - Haidian District Beijing 100085 - CHINA - - 80-FA-5B (hex) CLEVO CO. - 80FA5B (base 16) CLEVO CO. - NO. 129, XINGDE ROAD - SANCHONG DIST., - New TAIPEI CITY 241 - TAIWAN, PROVINCE OF CHINA - - 80-FB-06 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 80FB06 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 80-FF-A8 (hex) UNIDIS - 80FFA8 (base 16) UNIDIS - 4 floors(401), 144-4, Gumi-dong - Bundang-gu - Sungnam-si Gyeonggi-do 463-810 - KOREA, REPUBLIC OF - - 84-00-D2 (hex) Sony Ericsson Mobile Communications AB - 8400D2 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 84-01-A7 (hex) Greyware Automation Products, Inc - 8401A7 (base 16) Greyware Automation Products, Inc - 308 Oriole Ct - Murphy TX 75094 - UNITED STATES - - 84-0B-2D (hex) SAMSUNG ELECTRO-MECHANICS CO., LTD - 840B2D (base 16) SAMSUNG ELECTRO-MECHANICS CO., LTD - 314, Maetan3-Dong, Yeongtong-Gu - SUWON KYUNGGI-DO 443-743 - KOREA, REPUBLIC OF - - 84-0F-45 (hex) Shanghai GMT Digital Technologies Co., Ltd - 840F45 (base 16) Shanghai GMT Digital Technologies Co., Ltd - Room 501-505 - Building 1,NO.500 Zhangheng Rd - Zhangjiang Hi-tech Park Shanghai 201204 - CHINA - - 84-11-9E (hex) Samsung Electronics Co.,Ltd - 84119E (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 84-17-15 (hex) GP Electronics (HK) Ltd. - 841715 (base 16) GP Electronics (HK) Ltd. - Gold Peak Industrial Building, 6F - 30 Kwai Wing Road, - Kwai Chung NT - HONG KONG - - 84-17-66 (hex) Weifang GoerTek Electronics Co., Ltd - 841766 (base 16) Weifang GoerTek Electronics Co., Ltd - Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China - Wei Fang Shan Dong 261205 - CHINA - - 84-18-26 (hex) Osram GmbH - 841826 (base 16) Osram GmbH - Marcel Breuer Str. 6 - Munich Bavaria 80807 - GERMANY - - 84-18-3A (hex) Ruckus Wireless - 84183A (base 16) Ruckus Wireless - 350 W Java Drive - Sunnyvale CA 94089 - UNITED STATES - - 84-18-88 (hex) Juniper Networks - 841888 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 84-1B-38 (hex) Shenzhen Excelsecu Data Technology Co.,Ltd - 841B38 (base 16) Shenzhen Excelsecu Data Technology Co.,Ltd - Unit 701-709,7/F,South Block,SDGI Building A, No.2, - Shenzhen Guangdong 518057 - CHINA - - 84-1B-5E (hex) NETGEAR - 841B5E (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 84-1E-26 (hex) KERNEL-I Co.,LTD - 841E26 (base 16) KERNEL-I Co.,LTD - #606,ACE Techno Tower 10,470-5 - Gasan-Dong, Geumcheon-gu, Seoul 153-789 - KOREA, REPUBLIC OF - - 84-21-41 (hex) Shenzhen Ginwave Technologies Ltd. - 842141 (base 16) Shenzhen Ginwave Technologies Ltd. - 4/F,R2-A,High-Tech Industrial Park - Shenzhen Guangdong 518057 - CHINA - - 84-24-8D (hex) Zebra Technologies Inc - 84248D (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - 84-25-3F (hex) Silex Technology, Inc - 84253F (base 16) Silex Technology, Inc - 2-3-1 Hikaridai - Seika-cho Kyoto 619-0237 - JAPAN - - 84-25-A4 (hex) Tariox Limited - 8425A4 (base 16) Tariox Limited - 429 Mount Pleasant Road - Brantford Ontario N3T5L5 - CANADA - - 84-25-DB (hex) Samsung Electronics Co.,Ltd - 8425DB (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 84-26-15 (hex) ADB Broadband Italia - 842615 (base 16) ADB Broadband Italia - VIALE SARCA 336 - MILANO ITALY 20126 - ITALY - - 84-26-2B (hex) Alcatel-Lucent - 84262B (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 84-26-90 (hex) BEIJING THOUGHT SCIENCE CO.,LTD. - 842690 (base 16) BEIJING THOUGHT SCIENCE CO.,LTD. - 1-1102,Intermational Business Park,No.1 ShangDi Xinxi Rd,Haidian District,Beijing - beijing beijing 100085 - CHINA - - 84-27-CE (hex) Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints - 8427CE (base 16) Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints - Audiovisual Engineering - 2LL - 50 East North Temple - Salt Lake City UT 84150 - UNITED STATES - - 84-29-14 (hex) EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG - 842914 (base 16) EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG - Industriezeile 36, - Linz 4020 - AUSTRIA - - 84-29-99 (hex) Apple - 842999 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 84-2B-2B (hex) Dell Inc. - 842B2B (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 84-2B-50 (hex) Huria Co.,Ltd. - 842B50 (base 16) Huria Co.,Ltd. - #190-28 Chungchun-2Dong - Bupyoung-Gu - Incheon 403-032 - KOREA, REPUBLIC OF - - 84-2B-BC (hex) Modelleisenbahn GmbH - 842BBC (base 16) Modelleisenbahn GmbH - Plainbachstrasse 4 - Bergheim 5101 - AUSTRIA - - 84-2E-27 (hex) Samsung Electronics Co.,Ltd - 842E27 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 84-2F-75 (hex) Innokas Group - 842F75 (base 16) Innokas Group - Tarjusojantie 12 - Kempele Oulu 90440 - FINLAND - - 84-30-E5 (hex) SkyHawke Technologies, LLC - 8430E5 (base 16) SkyHawke Technologies, LLC - 274 Commerce Park Dr, Ste M - Ridgeland MS 39157 - UNITED STATES - - 84-32-EA (hex) ANHUI WANZTEN P&T CO., LTD - 8432EA (base 16) ANHUI WANZTEN P&T CO., LTD - 9F Building B1 HUAYI science Park - 71 TIANDA Road - Hefei Anhui Province 230088 - CHINA - - 84-34-97 (hex) Hewlett Packard - 843497 (base 16) Hewlett Packard - 11445 Compaq Center Drive W - Houston Texas 77070 - UNITED STATES - - 84-36-11 (hex) hyungseul publishing networks - 843611 (base 16) hyungseul publishing networks - 526-4, paju bookcity, munbal-li, gyoha-eup - paju-si Gyeonggi-do 413-832 - KOREA, REPUBLIC OF - - 84-38-35 (hex) Apple - 843835 (base 16) Apple - 1 Infinite Loop - Cupertion CA 95014 - UNITED STATES - - 84-38-38 (hex) Samsung Electro Mechanics co., LTD. - 843838 (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - 84-3A-4B (hex) Intel Corporate - 843A4B (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 84-3F-4E (hex) Tri-Tech Manufacturing, Inc. - 843F4E (base 16) Tri-Tech Manufacturing, Inc. - 333 Turbine Drive - Rapid City SD 57703 - UNITED STATES - - 84-44-64 (hex) ServerU Inc - 844464 (base 16) ServerU Inc - 8100 NW 64th Street - Miami FL 33166 - UNITED STATES - - 84-48-23 (hex) WOXTER TECHNOLOGY Co. Ltd - 844823 (base 16) WOXTER TECHNOLOGY Co. Ltd - 23F Doushiyangguang, Chegongmiao - Futian District - Shenzhen 518040 - CHINA - - 84-49-15 (hex) vArmour Networks, Inc. - 844915 (base 16) vArmour Networks, Inc. - 4633 OLD IRONSIDES DR - Suite 308 - SANTA CLARA CA 95054-1807 - UNITED STATES - - 84-4B-B7 (hex) Beijing Sankuai Online Technology Co.,Ltd - 844BB7 (base 16) Beijing Sankuai Online Technology Co.,Ltd - Block F&G, Wangjing International R & D Park, - No.6 Wang Jing East Rd, - Chaoyang District BEIJING 100102 - CHINA - - 84-4B-F5 (hex) Hon Hai Precision Ind. Co.,Ltd. - 844BF5 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 84-4F-03 (hex) Ablelink Electronics Ltd - 844F03 (base 16) Ablelink Electronics Ltd - Flat 1602,16/F Kodak House 2 39 Healthy Street East, - North Point, Hong Kong - CHINA - - 84-51-81 (hex) Samsung Electronics Co.,Ltd - 845181 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 84-55-A5 (hex) Samsung Elec Co.,Ltd - 8455A5 (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 84-56-9C (hex) Coho Data, Inc., - 84569C (base 16) Coho Data, Inc., - 1230 Midas Way, Suite 110 - Sunnyvale CA 94085 - UNITED STATES - - 84-57-87 (hex) DVR C&C Co., Ltd. - 845787 (base 16) DVR C&C Co., Ltd. - 7F 720 Namkwang Centlex Bldg, Cheongcheon-dong, Bupyeong-gu - Incheon 403-030 - KOREA, REPUBLIC OF - - 84-5C-93 (hex) Chabrier Services - 845C93 (base 16) Chabrier Services - 354 Chemin de la Pinatte - BP146 - Saint-Peray 07130 - FRANCE - - 84-5D-D7 (hex) Shenzhen Netcom Electronics Co.,Ltd - 845DD7 (base 16) Shenzhen Netcom Electronics Co.,Ltd - 8/F,1 Building,Finance Base,No.8,Kefa Road,High-Tech Park - Shenzhen Guangdong 518057 - CHINA - - 84-61-A0 (hex) ARRIS Group, Inc. - 8461A0 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 84-62-23 (hex) Shenzhen Coship Electronics Co., Ltd. - 846223 (base 16) Shenzhen Coship Electronics Co., Ltd. - Rainbow Bldg., North, Hi-Tech Industrial Park - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 84-62-A6 (hex) EuroCB (Phils), Inc. - 8462A6 (base 16) EuroCB (Phils), Inc. - SFB No.2 - Mactan Economic Zone - I - Lapulapu CIty Cebu 6015 - PHILIPPINES - - 84-63-D6 (hex) Microsoft Corporation - 8463D6 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - FINLAND - - 84-6A-ED (hex) Wireless Tsukamoto.,co.LTD - 846AED (base 16) Wireless Tsukamoto.,co.LTD - 16-21 1chome,Isoyama - Suzuka Mie-pref 5100256 - JAPAN - - 84-6E-B1 (hex) Park Assist LLC - 846EB1 (base 16) Park Assist LLC - 111 W28th Street - Suite 2B - New York NY 10001 - UNITED STATES - - 84-72-07 (hex) I&C Technology - 847207 (base 16) I&C Technology - 24,Pangyo-ro 255beon-gil, Bundang-gu, Seongnam-si, Gyeonggi-do, 463-400,Korea - I&C Building - Seongnam-si Gyeonggi-do 463-400,Korea - KOREA, REPUBLIC OF - - 84-73-03 (hex) Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd. - 847303 (base 16) Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd. - 5th floor,Hongchengxintai building,No.105,Yaojiayuan Road,Chaoyang District,Beijing - WENHUAYING NORTH (No.1, LINKONG 2nd St), GAOLIYING, SHUNYI DISTRICT, BEIJING - Beijing Chaoyang 100025 - CHINA - - 84-74-2A (hex) zte corporation - 84742A (base 16) zte corporation - 12/F.,R&D building,kejinan Road - shenzhen guangdong 518057 - UNITED STATES - - 84-76-16 (hex) Addat S.r.o. - 847616 (base 16) Addat S.r.o. - U krematoria 24 - Liberec 4 - 46001 - CZECH REPUBLIC - - 84-78-8B (hex) Apple - 84788B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 84-78-AC (hex) Cisco - 8478AC (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 84-7A-88 (hex) HTC Corporation - 847A88 (base 16) HTC Corporation - No. 23, Xinghua Rd, Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 84-7E-40 (hex) Texas Instruments - 847E40 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 84-80-2D (hex) Cisco - 84802D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 84-82-F4 (hex) Beijing Huasun Unicreate Technology Co., Ltd - 8482F4 (base 16) Beijing Huasun Unicreate Technology Co., Ltd - North Region 6th Floor, Tower A, Huizhi Mansion, - No.9, Xueqing Road,Haidian District - Beijing 100085 - CHINA - - 84-83-36 (hex) Newrun - 848336 (base 16) Newrun - #803 IT Convergence Industry Bldg., Kyungpook National Univ. - Sangyeok-dong, Buk-gu, Daegu, Korea, Republic of - Daegu N/A 702-010 - KOREA, REPUBLIC OF - - 84-83-71 (hex) Avaya, Inc - 848371 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - 84-84-33 (hex) Paradox Engineering SA - 848433 (base 16) Paradox Engineering SA - Via Passeggiata, 7 - Novazzano Ticino 6883 - SWITZERLAND - - 84-85-06 (hex) Apple - 848506 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 84-85-0A (hex) Hella Sonnen- und Wetterschutztechnik GmbH - 84850A (base 16) Hella Sonnen- und Wetterschutztechnik GmbH - Abfaltersbach 125 - Abfaltersbach Tirol 9913 - AUSTRIA - - 84-86-F3 (hex) Greenvity Communications - 8486F3 (base 16) Greenvity Communications - 673 S. Milpitas Blvd. Suite 204 - Milpitas California 95035 - UNITED STATES - - 84-8D-84 (hex) Rajant Corporation - 848D84 (base 16) Rajant Corporation - 400 East King Street - Malvern PA 19355 - UNITED STATES - - 84-8D-C7 (hex) Cisco SPVTG - 848DC7 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - 84-8E-0C (hex) Apple - 848E0C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 84-8E-96 (hex) Embertec Pty Ltd - 848E96 (base 16) Embertec Pty Ltd - 182 Fullarton Road - Dulwich, Adelaide South Australia 5065 - AUSTRALIA - - 84-8E-DF (hex) Sony Mobile Communications AB - 848EDF (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - 84-8F-69 (hex) Dell Inc. - 848F69 (base 16) Dell Inc. - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 84-90-00 (hex) Arnold & Richter Cine Technik - 849000 (base 16) Arnold & Richter Cine Technik - Tuerkenstrasse 89 - Munich Bavaria 80799 - GERMANY - - 84-93-0C (hex) InCoax Networks Europe AB - 84930C (base 16) InCoax Networks Europe AB - Strommavagen 2 - Gavle Sweden 80309 - SWEDEN - - 84-94-8C (hex) Hitron Technologies. Inc - 84948C (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C - Hsin-chu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - 84-96-81 (hex) Cathay Communication Co.,Ltd - 849681 (base 16) Cathay Communication Co.,Ltd - Tsinghua Institude A319 of Hi-tech Park,Nanshan district,Shenzhen China - Shenzhen Canton 0755 - CHINA - - 84-96-D8 (hex) Pace plc - 8496D8 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - 84-97-B8 (hex) Memjet Inc. - 8497B8 (base 16) Memjet Inc. - 15920 Bernardo Center Drive - San Diego CA 92127 - UNITED STATES - - 84-9C-A6 (hex) Arcadyan Technology Corporation - 849CA6 (base 16) Arcadyan Technology Corporation - 4F. , No. 9, Park Avenue II , - Hsinchu Science Park, - 300 - TAIWAN, PROVINCE OF CHINA - - 84-9D-C5 (hex) Centera Photonics Inc. - 849DC5 (base 16) Centera Photonics Inc. - 3F, No 6-3 Dusing Rd. - Hsinchu Taiwan 30078 - TAIWAN, PROVINCE OF CHINA - - 84-A4-66 (hex) Samsung Electronics Co.,Ltd - 84A466 (base 16) Samsung Electronics Co.,Ltd - 129, Samsung-ro, Youngtongl-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 84-A6-C8 (hex) Intel Corporate - 84A6C8 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 84-A7-83 (hex) Alcatel Lucent - 84A783 (base 16) Alcatel Lucent - Via Trento, 30 - Vimercate MB 20871 - ITALY - - 84-A8-E4 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - 84A8E4 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - 84-A9-91 (hex) Cyber Trans Japan Co.,Ltd. - 84A991 (base 16) Cyber Trans Japan Co.,Ltd. - - 4-8-8, Kitazawa - Setagaya-ku Tokyo 155-0031 - JAPAN - - 84-AC-A4 (hex) Beijing Novel Super Digital TV Technology Co., Ltd - 84ACA4 (base 16) Beijing Novel Super Digital TV Technology Co., Ltd - 4F Tower B Jingmeng Hightech building - No5 Shangdi east road, Haidian District - Beijing 100085 - CHINA - - 84-AF-1F (hex) Beat System Service Co,. Ltd. - 84AF1F (base 16) Beat System Service Co,. Ltd. - 1-11-1-2F, Nodaya-cho - Kita-ku - Okayama-city Okayama 700-0815 - JAPAN - - 84-B1-53 (hex) Apple - 84B153 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 84-B5-9C (hex) Juniper networks - 84B59C (base 16) Juniper networks - 1194 N. Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 84-B8-02 (hex) Cisco - 84B802 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 84-C2-E4 (hex) Jiangsu Qinheng Co., Ltd. - 84C2E4 (base 16) Jiangsu Qinheng Co., Ltd. - No. 18, Ningshuang Road - Yuhuatai Area - Nanjing Jiangsu 210012 - CHINA - - 84-C3-E8 (hex) Vaillant GmbH - 84C3E8 (base 16) Vaillant GmbH - Berghauser Straße 40 - Remscheid NRW D-42859 - GERMANY - - 84-C7-27 (hex) Gnodal Ltd - 84C727 (base 16) Gnodal Ltd - 178 - 180 Hotwell Road - Bristol BS8 4RP - UNITED KINGDOM - - 84-C7-A9 (hex) C3PO S.A. - 84C7A9 (base 16) C3PO S.A. - Alejandro Goicoechea 6 Local 9 - Sant Just Desvern Barcelona ES08960 - SPAIN - - 84-C8-B1 (hex) Incognito Software Inc. - 84C8B1 (base 16) Incognito Software Inc. - #500 - 375 Water St - Vancouver BC - British Columbia V6B 5C6 - CANADA - - 84-C9-B2 (hex) D-Link International - 84C9B2 (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy - 609917 - SINGAPORE - - 84-CF-BF (hex) Fairphone - 84CFBF (base 16) Fairphone - Piet Heinkade 181A - Amsterdam North Holland 1019HC - NETHERLANDS - - 84-D3-2A (hex) IEEE 1905.1 - 84D32A (base 16) IEEE 1905.1 - 445 Hoes Lane - PO Box 1331 - Piscataway NJ 08855-1331 - UNITED STATES - - 84-D9-C8 (hex) Unipattern Co., - 84D9C8 (base 16) Unipattern Co., - 16F., No.30., Beiping E. Rd., Zhongzheng Dist., - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 84-DB-2F (hex) Sierra Wireless Inc - 84DB2F (base 16) Sierra Wireless Inc - 1381 Wireless Way - Richmond BC V6V 3A4 - CANADA - - 84-DB-AC (hex) Huawei Technologies Co., Ltd - 84DBAC (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 84-DB-FC (hex) Alcatel-Lucent - 84DBFC (base 16) Alcatel-Lucent - 600 March Road - Ottawa Ontario K2K 2E6 - CANADA - - 84-DD-20 (hex) Texas Instruments - 84DD20 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 84-DD-B7 (hex) Cilag GmbH International - 84DDB7 (base 16) Cilag GmbH International - Gubelstrasse 34 - Zug _ CH-6300 - SWITZERLAND - - 84-DE-3D (hex) Crystal Vision Ltd - 84DE3D (base 16) Crystal Vision Ltd - Lion Technology park - Station Road east - Whittlesford/ Cambridge Cambs CB22 4WL - UNITED KINGDOM - - 84-DF-0C (hex) NET2GRID BV - 84DF0C (base 16) NET2GRID BV - Krullelaan 28 - Zeist Utrecht 3701 TD - NETHERLANDS - - 84-DF-19 (hex) Chuango Security Technology Corporation - 84DF19 (base 16) Chuango Security Technology Corporation - 6-17, Overseas Students Pioneer Park, - No. 108 Jiangbin East Road - Fuzhou Fujian 350015 - CHINA - - 84-E0-58 (hex) Pace plc - 84E058 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - 84-E4-D9 (hex) Shenzhen NEED technology Ltd. - 84E4D9 (base 16) Shenzhen NEED technology Ltd. - Room 581 ,Jinda technology center,No.8, Kefeng road, - Hi-Tech industrial park Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 84-E6-29 (hex) Bluwan SA - 84E629 (base 16) Bluwan SA - Parc Les Grillons, Bat 1 - 60 route de Sartrouville - Le Pecq 78230 - FRANCE - - 84-E7-14 (hex) Liang Herng Enterprise,Co.Ltd. - 84E714 (base 16) Liang Herng Enterprise,Co.Ltd. - 1FL,No.27,KweiYang Street,Sanchung District,New Taipei City,Taiwan,R.O.C. - New Taipei City 241 - TAIWAN, PROVINCE OF CHINA - - 84-EA-99 (hex) Vieworks - 84EA99 (base 16) Vieworks - 6F Suntechcity 2,307-2 Sangdaewon-dong, Jungwon-gu - Seongnam Gyeonggi 462-806 - KOREA, REPUBLIC OF - - 84-EB-18 (hex) Texas Instruments - 84EB18 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - 84-ED-33 (hex) BBMC Co.,Ltd - 84ED33 (base 16) BBMC Co.,Ltd - #301, DaerungPostTower 3, 182-4, - Guro-3dong, Guro-gu, Seoul, Korea South - Seoul None 152-746 - KOREA, REPUBLIC OF - - 84-F1-29 (hex) Metrascale Inc. - 84F129 (base 16) Metrascale Inc. - 400 Liberty Ave. - Brooklyn NY 11207 - UNITED STATES - - 84-F4-93 (hex) OMS spol. s.r.o. - 84F493 (base 16) OMS spol. s.r.o. - Dojc 419 - Dojc Slovakia 90602 - SLOVAKIA - - 84-F6-4C (hex) Cross Point BV - 84F64C (base 16) Cross Point BV - Waanderweg 12 - Emmen Drenthe 7812 HZ - NETHERLANDS - - 84-FC-FE (hex) Apple - 84FCFE (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 84-FE-9E (hex) RTC Industries, Inc. - 84FE9E (base 16) RTC Industries, Inc. - 2800 Golf Road - Rolling Meadows IL 60008 - UNITED STATES - - 88-03-55 (hex) Arcadyan Technology Corp. - 880355 (base 16) Arcadyan Technology Corp. - 4F., No.9 , Park Avenue II - Hsinchu Science Park, - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 88-09-05 (hex) MTMCommunications - 880905 (base 16) MTMCommunications - 2-3-10 Honmachi - 3F-Hirayama building - Ichinomiya-shi Aichi-ken 491-0853 - JAPAN - - 88-0F-10 (hex) Huami Information Technology Co.,Ltd. - 880F10 (base 16) Huami Information Technology Co.,Ltd. - Room 1201 Building A4, National Animation Industry Base - No.800 Wangjing West Road. - Hefei Anhui 230088 - CHINA - - 88-0F-B6 (hex) Jabil Circuits India Pvt Ltd,-EHTP unit - 880FB6 (base 16) Jabil Circuits India Pvt Ltd,-EHTP unit - B-26, MIDC, Ranjangaon, Tal.Shirur - Dist.Pune - Pune Maharashtra 412220 - INDIA - - 88-10-36 (hex) Panodic(ShenZhen) Electronics Limted - 881036 (base 16) Panodic(ShenZhen) Electronics Limted - Floor 12, Grentech Building, Keji.C. Road - 3rd Hi-Tech Industrial Park, Nanshan District - ShenZhen GuangDong 518052 - CHINA - - 88-12-4E (hex) Qualcomm Atheros - 88124E (base 16) Qualcomm Atheros - 1700 Technology Drive - San Jose CA 95110 - UNITED STATES - - 88-14-2B (hex) Protonic Holland - 88142B (base 16) Protonic Holland - Factorij 36 - Zwaag Netherlands 1689 AL - NETHERLANDS - - 88-15-44 (hex) Meraki, Inc. - 881544 (base 16) Meraki, Inc. - 660 Alabama St - San Francisco CA 94110 - UNITED STATES - - 88-18-AE (hex) Tamron Co., Ltd - 8818AE (base 16) Tamron Co., Ltd - 1385,Hasunuma, Minuma-ku - Saitama-shi Saitama 337-8556 - JAPAN - - 88-1D-FC (hex) Cisco - 881DFC (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 88-1F-A1 (hex) Apple - 881FA1 (base 16) Apple - 1 infinite loop - Cupertino CA 95014 - UNITED STATES - - 88-20-12 (hex) LMI Technologies - 882012 (base 16) LMI Technologies - 1673 Cliveden Avenue - Delta British Columbia V3M 6V5 - CANADA - - 88-21-E3 (hex) Nebusens, S.L. - 8821E3 (base 16) Nebusens, S.L. - C/ Adaja S/N, Edificio M2 - Parque cientifico de la USAL - Villamayor de la Armuña Salamanca 37185 - SPAIN - - 88-23-64 (hex) Watchnet DVR Inc - 882364 (base 16) Watchnet DVR Inc - Unit 5 - 351 Ferrier St. - Markham Ontario L3R 5Z2 - CANADA - - 88-23-FE (hex) TTTech Computertechnik AG - 8823FE (base 16) TTTech Computertechnik AG - Schoenbrunnerstrasse 7 - Vienna 1040 - AUSTRIA - - 88-25-2C (hex) Arcadyan Technology Corporation - 88252C (base 16) Arcadyan Technology Corporation - 4F., NO.9, Park Avenue II , - Hsinchu Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 88-25-93 (hex) TP-LINK TECHNOLOGIES CO.,LTD - 882593 (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24 (floors 1,3,4,5) and 28 (floors1-4) - Central Science and Technology Park,Shennan Rd - Shenzhen Guangdong 518057 - CHINA - - 88-29-50 (hex) Dalian Netmoon Tech Develop Co.,Ltd - 882950 (base 16) Dalian Netmoon Tech Develop Co.,Ltd - Shahekou District NO.19-2 Wansui Street - Dalian Liaoning 116000 - CHINA - - 88-2E-5A (hex) storONE - 882E5A (base 16) storONE - POB 2660 - 4 Hayezira st. - Ra'anana - ISRAEL - - 88-30-8A (hex) Murata Manufactuaring Co.,Ltd. - 88308A (base 16) Murata Manufactuaring Co.,Ltd. - 1-10-1 Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 88-32-9B (hex) Samsung Electro Mechanics co.,LTD. - 88329B (base 16) Samsung Electro Mechanics co.,LTD. - 93Moo5T. Bangsamak - THAI, WEELGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - 88-33-14 (hex) Texas Instruments - 883314 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 88-33-BE (hex) Ivenix, Inc. - 8833BE (base 16) Ivenix, Inc. - 21 Water Street - Amesbury MA 01913 - UNITED STATES - - 88-35-4C (hex) Transics - 88354C (base 16) Transics - p/a Ter Waarde 91 - Ieper 8900 - BELGIUM - - 88-36-12 (hex) SRC Computers, LLC - 883612 (base 16) SRC Computers, LLC - 4240 N Nevada Ave - Colorado Springs CO 80907 - UNITED STATES - - 88-3B-8B (hex) Cheering Connection Co. Ltd. - 883B8B (base 16) Cheering Connection Co. Ltd. - Room 602, Shenzhen Software Park T2-B - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 88-41-57 (hex) Shenzhen Atsmart Technology Co.,Ltd. - 884157 (base 16) Shenzhen Atsmart Technology Co.,Ltd. - East 3F ,2 Building, Meijing Industry Park, Qiaoxiang Road, Nanshan District - Shenzhen Guangdong 518000 - CHINA - - 88-41-C1 (hex) ORBISAT DA AMAZONIA IND E AEROL SA - 8841C1 (base 16) ORBISAT DA AMAZONIA IND E AEROL SA - AV SHISHIMA HIFUMI, 2911 - URBANOVA - SAO JOSE DOS CAMPOS São Paulo 12244-000 - BRAZIL - - 88-41-FC (hex) AirTies Wireless Netowrks - 8841FC (base 16) AirTies Wireless Netowrks - Gulbahar Mahallesi, Avni Diligil Sokak - Celik Is Merkezi No:5 Mecidiyekoy/Sisli - ISTANBUL 34394 - TURKEY - - 88-43-E1 (hex) CISCO SYSTEMS, INC. - 8843E1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 88-44-F6 (hex) Nokia Corporation - 8844F6 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - 88-46-2A (hex) Telechips Inc. - 88462A (base 16) Telechips Inc. - Luther Building,7-20, - Sincheon-dong,Songpa-gu, - Seoul 138-240 - KOREA, REPUBLIC OF - - 88-4B-39 (hex) Siemens AG, Healthcare Sector - 884B39 (base 16) Siemens AG, Healthcare Sector - Henkestrasse 127 - Erlangen Bavaria 91052 - GERMANY - - 88-51-FB (hex) Hewlett Packard - 8851FB (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 88-53-2E (hex) Intel Corporate - 88532E (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 88-53-95 (hex) Apple - 885395 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 88-53-D4 (hex) Huawei Technologies Co., Ltd - 8853D4 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - 88-57-6D (hex) XTA Electronics Ltd - 88576D (base 16) XTA Electronics Ltd - The Design House - Worcester Road - Stourport-on-Severn Worcestershire DY13 9BZ - UNITED KINGDOM - - 88-5A-92 (hex) Cisco - 885A92 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 88-5B-DD (hex) Aerohive Networks Inc. - 885BDD (base 16) Aerohive Networks Inc. - 330 Gibraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - 88-5C-47 (hex) Alcatel Lucent - 885C47 (base 16) Alcatel Lucent - Via trento, 30 - Vimercate MB 20059 - ITALY - - 88-61-5A (hex) Siano Mobile Silicon Ltd. - 88615A (base 16) Siano Mobile Silicon Ltd. - P.O. Box 8684 - Netanya 42504 - ISRAEL - - 88-63-DF (hex) Apple - 8863DF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 88-68-5C (hex) Shenzhen ChuangDao & Perpetual Eternal Technology Co.,Ltd - 88685C (base 16) Shenzhen ChuangDao & Perpetual Eternal Technology Co.,Ltd - Area c,2/F,Building 1, BaoAn foreign trade industrial zone - No.51,Lane 1,3 Road xinan - BaoAn District, Shenzhen Guangdong province 518100 - CHINA - - 88-6B-76 (hex) CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD - 886B76 (base 16) CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD - Shunde District of Foshan City, Guangdong Province, Guangxi Rong Ronggui Town Road, No. 148 - Changhong and Technology Technology Building 22 Floor Fuhua Building,Hi-Tech Park,Nanshan Distrist,shenzhen City , - Foshan GuangDong 528305 - CHINA - - 88-70-33 (hex) Hangzhou Silan Microelectronic Inc - 887033 (base 16) Hangzhou Silan Microelectronic Inc - No.4 HuangGuShan Road - Hangzhou Zhejiang 310012 - CHINA - - 88-70-8C (hex) Lenovo Mobile Communication Technology Ltd. - 88708C (base 16) Lenovo Mobile Communication Technology Ltd. - No.999, Qishan North 2nd Road - Information & Optoelectronics Park, Torch Hi-tech Industry Development Zone - Xiamen Fujian 361006 - CHINA - - 88-70-EF (hex) SC Professional Trading Co., Ltd. - 8870EF (base 16) SC Professional Trading Co., Ltd. - 2 Soi Krungthepkreetar 21 - Sapansoong Bangkok 10250 - THAILAND - - 88-73-84 (hex) Toshiba - 887384 (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - 88-73-98 (hex) K2E Tekpoint - 887398 (base 16) K2E Tekpoint - 201,Winstower,278-51,Sungsoo2ga 3dong,Sungdong-gu,Seoul,S.Korea,133-123 - Seoul Sungdong-gu 133-123 - KOREA, REPUBLIC OF - - 88-75-56 (hex) Cisco - 887556 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 88-78-9C (hex) Game Technologies SA - 88789C (base 16) Game Technologies SA - Plac W. Andersa 3 - Poznan 61894 - POLAND - - 88-86-03 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 888603 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - Shenzhen Guangdong 518129 - CHINA - - 88-86-A0 (hex) Simton Technologies, Ltd. - 8886A0 (base 16) Simton Technologies, Ltd. - 2 Taishan Road, Building C, 3rd Floor - Wuxi, Province of Jiangsu, 214028 - CHINA - - 88-87-17 (hex) CANON INC. - 888717 (base 16) CANON INC. - 3-30-2 - Shimomaruko - Ohta-Ku Tokyo 146-8501 - JAPAN - - 88-87-DD (hex) DarbeeVision Inc. - 8887DD (base 16) DarbeeVision Inc. - 153 E City Place Drive - Santa Ana California 92705 - UNITED STATES - - 88-89-14 (hex) All Components Incorporated - 888914 (base 16) All Components Incorporated - 828 New Meister Lane - Suite 300 - Pflugerville TX 78660 - UNITED STATES - - 88-89-64 (hex) GSI Electronics Inc. - 888964 (base 16) GSI Electronics Inc. - 5200 Armand-Frappier - St-Hubert Quebec J3Z 1G5 - CANADA - - 88-8B-5D (hex) Storage Appliance Corporation - 888B5D (base 16) Storage Appliance Corporation - 29 Su Zhou Jie, Haidian Dist. - Suite 601-603 - Beijing 100080 - CHINA - - 88-8C-19 (hex) Brady Corp Asia Pacific Ltd - 888C19 (base 16) Brady Corp Asia Pacific Ltd - 1, Kaki Bukit Crescent - 416236 - SINGAPORE - - 88-90-8D (hex) Cisco - 88908D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 88-91-66 (hex) Viewcooper Corp. - 889166 (base 16) Viewcooper Corp. - Room 1061, A,Seven Block, No.128 Huayuan Rd - Hong Kou District - SHANGHAI 200083 - CHINA - - 88-91-DD (hex) Racktivity - 8891DD (base 16) Racktivity - Hertstokweg 5 - Ternat Flanders 1741 - BELGIUM - - 88-94-71 (hex) Brocade Communications Systems, Inc. - 889471 (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 88-94-F9 (hex) Gemicom Technology, Inc. - 8894F9 (base 16) Gemicom Technology, Inc. - 16F, Building B, No. 98, Sec 1, Hsin-Tai-Wu Rd. - Hsi-Chih city Taipei 22102 - TAIWAN, PROVINCE OF CHINA - - 88-95-B9 (hex) Unified Packet Systems Crop - 8895B9 (base 16) Unified Packet Systems Crop - 1F., No32,Lane 15,SEC 6, MinQuan E Rd., - Taipei Neihu 114 - TAIWAN, PROVINCE OF CHINA - - 88-96-76 (hex) TTC MARCONI s.r.o. - 889676 (base 16) TTC MARCONI s.r.o. - Trebohosticka s.r.o. - Praha 10000 - CZECH REPUBLIC - - 88-97-DF (hex) Entrypass Corporation Sdn. Bhd. - 8897DF (base 16) Entrypass Corporation Sdn. Bhd. - No.40, Jalan TPP 1/10, - Taman Industri Puchong, Batu 12, Jalan - Puchong Selangor Darul Ehsan 47100 - MALAYSIA - - 88-98-21 (hex) TERAON - 889821 (base 16) TERAON - 2F Seohan Bldg., 1552-10, Seocho-Dong, Seocho-Gu, - Seoul 137-070 - KOREA, REPUBLIC OF - - 88-9B-39 (hex) Samsung Electronics Co.,Ltd - 889B39 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 88-9C-A6 (hex) BTB Korea INC - 889CA6 (base 16) BTB Korea INC - #1001, Suntech City 1st - 474 Doonchondaero - Sungnam Kyunggido 462-725 - KOREA, REPUBLIC OF - - 88-9F-FA (hex) Hon Hai Precision Ind. Co.,Ltd. - 889FFA (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 88-A2-5E (hex) juniper networks - 88A25E (base 16) juniper networks - 1194 N Mathilda Avenue - sunnyvale ca 94089 - UNITED STATES - - 88-A2-D7 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 88A2D7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 88-A3-CC (hex) Amatis Controls - 88A3CC (base 16) Amatis Controls - 400 W. Main St. - Aspen CO 81611 - UNITED STATES - - 88-A5-BD (hex) QPCOM INC. - 88A5BD (base 16) QPCOM INC. - 6030 NW 99 AVE - SUITE 404 - DORAL FLORIDA 33178 - UNITED STATES - - 88-A7-3C (hex) Ragentek Technology Group - 88A73C (base 16) Ragentek Technology Group - D10/D11, No.3188, Xiupu Road - PuDong District - Shanghai 201315 - CHINA - - 88-AC-C1 (hex) Generiton Co., Ltd. - 88ACC1 (base 16) Generiton Co., Ltd. - 8F-1, No. 81, Shuili Rd., - Hsinchu City, 30059 - TAIWAN, PROVINCE OF CHINA - - 88-AE-1D (hex) COMPAL INFORMATION(KUNSHAN)CO.,LTD - 88AE1D (base 16) COMPAL INFORMATION(KUNSHAN)CO.,LTD - NO. 25, THE 3RD STREET KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN SUZHOU 215300 - CHINA - - 88-B1-68 (hex) Delta Control GmbH - 88B168 (base 16) Delta Control GmbH - Rondorfer Hauptstraße 33 - Cologne NRW 50997 - GERMANY - - 88-B1-E1 (hex) AirTight Networks, Inc. - 88B1E1 (base 16) AirTight Networks, Inc. - 339 N.Bernardo Ave, - Ste #200, - Mountain View CA 94043 - UNITED STATES - - 88-B6-27 (hex) Gembird Europe BV - 88B627 (base 16) Gembird Europe BV - Wittevrouwen 56 - Almere Flevoland 1358CD - NETHERLANDS - - 88-BA-7F (hex) Qfiednet Co., Ltd. - 88BA7F (base 16) Qfiednet Co., Ltd. - #204 KJ Bldg. DaeChi-Dong - GangNam-Gu - Seoul 135-847 - KOREA, REPUBLIC OF - - 88-BF-D5 (hex) Simple Audio Ltd - 88BFD5 (base 16) Simple Audio Ltd - Unit 59 Elderpark Workspace - 100 Elderpark Street - Glasgow G51 3TR - UNITED KINGDOM - - 88-C3-6E (hex) Beijing Ereneben lnformation Technology Limited - 88C36E (base 16) Beijing Ereneben lnformation Technology Limited - Room 14F,Building F,Honglong Central Plaza,NO,3001,Heping Road,LuoHu - ShenZhen GuangDong 518110 - CHINA - - 88-C6-26 (hex) Logitech - Ultimate Ears - 88C626 (base 16) Logitech - Ultimate Ears - 4700 NW Camas Meadows Dr - Camas WA 98607 - UNITED STATES - - 88-C6-63 (hex) Apple - 88C663 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 88-C9-D0 (hex) LG Electronics - 88C9D0 (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 88-CB-87 (hex) Apple - 88CB87 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 88-CB-A5 (hex) Suzhou Torchstar Intelligent Technology Co.,Ltd - 88CBA5 (base 16) Suzhou Torchstar Intelligent Technology Co.,Ltd - Rm1704B,Business Building, No.181, Cuiyuan Rd.,SIP - Suzhou Jiangsu Province 215000 - CHINA - - 88-CE-FA (hex) Huawei Technologies Co., Ltd - 88CEFA (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 88-D3-7B (hex) FirmTek, LLC - 88D37B (base 16) FirmTek, LLC - 29300 Kohoutek Way - Suite 120 - Union City CA 94587 - UNITED STATES - - 88-D7-BC (hex) DEP Company - 88D7BC (base 16) DEP Company - Poryadkovy pereulok,21 - Moscow 127055 - RUSSIAN FEDERATION - - 88-D9-62 (hex) Canopus Systems US LLC - 88D962 (base 16) Canopus Systems US LLC - Nasa Ames Research Park - 340 Cody Rd., Building 503 - Moffett Field CALIFORNIA 94035 - UNITED STATES - - 88-DC-96 (hex) SENAO Networks, Inc. - 88DC96 (base 16) SENAO Networks, Inc. - No. 500, Fusing 3rd Rd., Hwa-Ya Technology Park - Kuei-Shan Hsiang TaoYuan County 333 - TAIWAN, PROVINCE OF CHINA - - 88-DD-79 (hex) Voltaire - 88DD79 (base 16) Voltaire - 13, Zarchin St - Raanana 43662 - ISRAEL - - 88-E0-A0 (hex) Shenzhen VisionSTOR Technologies Co., Ltd - 88E0A0 (base 16) Shenzhen VisionSTOR Technologies Co., Ltd - 12/F, East Tower,Nanshan Software Park - 10128 Shennan Blvd - Shenzhen Guangdong 518000 - CHINA - - 88-E0-F3 (hex) Juniper Networks - 88E0F3 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - 88-E1-61 (hex) Art Beijing Science and Technology Development Co., Ltd. - 88E161 (base 16) Art Beijing Science and Technology Development Co., Ltd. - Room 210,Building 1#, No. 27 Qinghe Longgang Rd., Haidian District, Beijing,100192,China - Beijing Beijing 100192 - CHINA - - 88-E3-AB (hex) Huawei Technologies Co., Ltd - 88E3AB (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 88-E6-03 (hex) Avotek corporation - 88E603 (base 16) Avotek corporation - 9-17, Dongil-ro 174-gil, Nowon-gu, Seoul - Seoul Seoul 139-808 - KOREA, REPUBLIC OF - - 88-E7-12 (hex) Whirlpool Corporation - 88E712 (base 16) Whirlpool Corporation - 750 Monte Dr. - Mail Stop 5210 - Benton Harbor Michigan 49022 - UNITED STATES - - 88-E7-A6 (hex) iKnowledge Integration Corp. - 88E7A6 (base 16) iKnowledge Integration Corp. - 10F No.2, Sec. 3, Xinsheng S. Rd., - Daan Dist. - Taipei 10660 - TAIWAN, PROVINCE OF CHINA - - 88-E8-F8 (hex) YONG TAI ELECTRONIC (DONGGUAN) LTD. - 88E8F8 (base 16) YONG TAI ELECTRONIC (DONGGUAN) LTD. - Yuan Shan Bei Managed Region - Chang Ping Town - Dong Guan Guang Dong 523583 - CHINA - - 88-E9-17 (hex) Tamaggo - 88E917 (base 16) Tamaggo - 2001 McGill College - Suite 700 - Montreal Quebec H3A 3L3 - CANADA - - 88-ED-1C (hex) Cudo Communication Co., Ltd. - 88ED1C (base 16) Cudo Communication Co., Ltd. - 10F ArirangTV 1467-80, Seocho-3dong, Seocho-gu - Seoul 137-868 - KOREA, REPUBLIC OF - - 88-F0-31 (hex) Cisco - 88F031 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - 88-F0-77 (hex) CISCO SYSTEMS, INC. - 88F077 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 88-F4-88 (hex) cellon communications technology(shenzhen)Co.,Ltd. - 88F488 (base 16) cellon communications technology(shenzhen)Co.,Ltd. - 13/F C Building,Gaoxin S.Ave.,Hi-Tech Industrial Park,Nanshan,shenzhen518057,PRC - shenzhen Guangdong 518057 - CHINA - - 88-F4-90 (hex) Jetmobile Pte Ltd - 88F490 (base 16) Jetmobile Pte Ltd - 541 Orchard Road - Liat Towers #09-01 - Singapore 238881 - SINGAPORE - - 88-F7-C7 (hex) Technicolor USA Inc. - 88F7C7 (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 88-FD-15 (hex) LINEEYE CO., LTD - 88FD15 (base 16) LINEEYE CO., LTD - 5F Marufuku Bldg. 39-1 Karahashi - Nishihiragaki-cho, Minami-ku - Kyoto 601-8468 - JAPAN - - 88-FE-D6 (hex) ShangHai WangYong Software Co., Ltd. - 88FED6 (base 16) ShangHai WangYong Software Co., Ltd. - Shanghai Pudong Zhangjiang Hi-Tech Park, - No. 498 Guo Shou Jing Road - Pudong Software Park 22301-283 ShangHai 201203 - CHINA - - 8C-00-6D (hex) Apple - 8C006D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 8C-04-FF (hex) Technicolor USA Inc. - 8C04FF (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - 8C-05-51 (hex) Koubachi AG - 8C0551 (base 16) Koubachi AG - Technoparkstrasse 1 - Zurich Zurich 8005 - SWITZERLAND - - 8C-07-8C (hex) FLOW DATA INC - 8C078C (base 16) FLOW DATA INC - 2309 GRAND PARK DRIVE - GRAND JUNCTION CO 81505 - UNITED STATES - - 8C-08-8B (hex) Remote Solution - 8C088B (base 16) Remote Solution - 92, Chogokri, Nammyun - Kimcheon city Kyungbuk 740-871 - KOREA, REPUBLIC OF - - 8C-09-F4 (hex) ARRIS Group, Inc. - 8C09F4 (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 8C-0C-90 (hex) Ruckus Wireless - 8C0C90 (base 16) Ruckus Wireless - 880 West Maude Ave - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - 8C-0C-A3 (hex) Amper - 8C0CA3 (base 16) Amper - Marconi 3, PTM - Tres Cantos Madrid 28760 - SPAIN - - 8C-0E-E3 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - 8C0EE3 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - NO.18 HAIBIN ROAD,WUSHA,CHANG'AN - DONGGUAN GUANGDONG 523860 - CHINA - - 8C-11-CB (hex) ABUS Security-Center GmbH & Co. KG - 8C11CB (base 16) ABUS Security-Center GmbH & Co. KG - Linker Kreuthweg 5 - Affing / Muehlhausen Bavaria 86444 - GERMANY - - 8C-18-D9 (hex) Shenzhen RF Technology Co., Ltd - 8C18D9 (base 16) Shenzhen RF Technology Co., Ltd - 5/F,Building 4,Baokun Science and Technology Industial Park - Dalang Street - Baoan Guangdong 518100 - CHINA - - 8C-1F-94 (hex) RF Surgical System Inc. - 8C1F94 (base 16) RF Surgical System Inc. - 9740 Appaloosa Road - Suite 150 - San Diego CA 92131 - UNITED STATES - - 8C-21-0A (hex) TP-LINK TECHNOLOGIES CO., LTD. - 8C210A (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan - shenzhen guangdong Province 518057 - CHINA - - 8C-27-1D (hex) QuantHouse - 8C271D (base 16) QuantHouse - 52 Rue de la Victoire - Paris 75009 - FRANCE - - 8C-27-8A (hex) Vocollect Inc - 8C278A (base 16) Vocollect Inc - 703 Rodi Road - Pittsburgh Pa 15235 - UNITED STATES - - 8C-29-37 (hex) Apple - 8C2937 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 8C-2D-AA (hex) Apple - 8C2DAA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 8C-2F-39 (hex) IBA Dosimetry GmbH - 8C2F39 (base 16) IBA Dosimetry GmbH - Bahnhofstrasse 5 - Schwarzenbruck 90592 - GERMANY - - 8C-33-30 (hex) EmFirst Co., Ltd. - 8C3330 (base 16) EmFirst Co., Ltd. - 701 Suwon Venture Center - 1017 ingye-dong - Suwon Gyeonggi-do 442-833 - KOREA, REPUBLIC OF - - 8C-33-57 (hex) HiteVision Digital Media Technology Co.,Ltd. - 8C3357 (base 16) HiteVision Digital Media Technology Co.,Ltd. - 1st building,Honghui Industrial Park,LiuXian - 2nd RD,XinAn Street, BaoAn District - Shenzhen Guangdong 510008 - CHINA - - 8C-34-FD (hex) Huawei Technologies Co., Ltd - 8C34FD (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - 8C-3A-E3 (hex) LG Electronics - 8C3AE3 (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 8C-3C-07 (hex) Skiva Technologies, Inc. - 8C3C07 (base 16) Skiva Technologies, Inc. - 8330 Sterling St - Irving TX 75063 - UNITED STATES - - 8C-3C-4A (hex) NAKAYO TELECOMMUNICATIONS,INC. - 8C3C4A (base 16) NAKAYO TELECOMMUNICATIONS,INC. - 165 - Higashiomuro-machi - Maebashi-shi Gunma 379-2105 - JAPAN - - 8C-41-F2 (hex) RDA Technologies Ltd. - 8C41F2 (base 16) RDA Technologies Ltd. - Suite 2203, CC Wu Building, - 302-308 Hennessy Road, - WanChai Hong Kong 00000 - HONG KONG - - 8C-44-35 (hex) Shanghai BroadMobi Communication Technology Co., Ltd. - 8C4435 (base 16) Shanghai BroadMobi Communication Technology Co., Ltd. - Rm. 901, Bld. 9, No.1515 Gumei Rd, Xuhui District - Shanghai 200233 - CHINA - - 8C-4A-EE (hex) GIGA TMS INC - 8C4AEE (base 16) GIGA TMS INC - 9F-2 NO.31 Lane 169 Kang-ning Street, Hsi-Chih - Taipei County 221 221 - TAIWAN, PROVINCE OF CHINA - - 8C-4B-59 (hex) 3D Imaging & Simulations Corp - 8C4B59 (base 16) 3D Imaging & Simulations Corp - 815, Timnip-Dong, Yuseong-Gu - Daejeon 305510 - KOREA, REPUBLIC OF - - 8C-4C-DC (hex) PLANEX COMMUNICATIONS INC. - 8C4CDC (base 16) PLANEX COMMUNICATIONS INC. - Planex Volta Bldg., - 2-11-9 Ebisu-Nishi,Shibuya-ku - Tokyo 150-0021 - JAPAN - - 8C-4D-B9 (hex) Unmonday Ltd - 8C4DB9 (base 16) Unmonday Ltd - Laivakatu 3 - Helsinki Uusimaa 00150 - FINLAND - - 8C-4D-EA (hex) Cerio Corporation - 8C4DEA (base 16) Cerio Corporation - 5F., No.88, Mincyuan Rd., Sindian City - Taipei County 23141 - TAIWAN, PROVINCE OF CHINA - - 8C-51-05 (hex) Shenzhen ireadygo Information Technology CO.,LTD. - 8C5105 (base 16) Shenzhen ireadygo Information Technology CO.,LTD. - Room 02,11F,DESAY Building,No.1 Hi-Tech South Road - Shenzhen 518057 - CHINA - - 8C-53-F7 (hex) A&D ENGINEERING CO., LTD. - 8C53F7 (base 16) A&D ENGINEERING CO., LTD. - 336-6 Dangsandong 6-ga, Yeongdeungpo-gu - Seoul 150-810 - KOREA, REPUBLIC OF - - 8C-54-1D (hex) LGE - 8C541D (base 16) LGE - 60-39 , Kasan -dong , Gumcheon-gu. - Seoul 153-801 - KOREA, REPUBLIC OF - - 8C-56-9D (hex) Imaging Solutions Group - 8C569D (base 16) Imaging Solutions Group - 1387 Fairport Rd - Suite 890 - Fairport NY 14450 - UNITED STATES - - 8C-56-C5 (hex) Nintendo Co., Ltd. - 8C56C5 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 8C-57-FD (hex) LVX Western - 8C57FD (base 16) LVX Western - 700 54th ave North - St. Cloud MN 56303 - UNITED STATES - - 8C-58-77 (hex) Apple - 8C5877 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 8C-59-8B (hex) C Technologies AB - 8C598B (base 16) C Technologies AB - Traktorvägen 11 - Lund SkÃ¥ne 226 60 - SWEDEN - - 8C-5A-F0 (hex) Exeltech Solar Products - 8C5AF0 (base 16) Exeltech Solar Products - 3001 Northern Cross Blvd #361 - Fort Worth TX 76137 - UNITED STATES - - 8C-5C-A1 (hex) d-broad,INC - 8C5CA1 (base 16) d-broad,INC - 3-17-5 ShinYokohama Kouhoku-Ku - Yokohama Kanagawa 222-0033 - JAPAN - - 8C-5D-60 (hex) UCI Corporation Co.,Ltd. - 8C5D60 (base 16) UCI Corporation Co.,Ltd. - 299/195-7, Chaengwattana Road, - Thungsonghong, Laksi - Bangkok 10210 - THAILAND - - 8C-5F-DF (hex) Beijing Railway Signal Factory - 8C5FDF (base 16) Beijing Railway Signal Factory - No.2 Sicun Xilu Langfa,Huangcun, - Daxing Area, - Beiijng 102613 - CHINA - - 8C-60-4F (hex) CISCO SYSTEMS, INC. - 8C604F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 8C-64-0B (hex) Beyond Devices d.o.o. - 8C640B (base 16) Beyond Devices d.o.o. - Trzaska cesta 515 - Brezovica pri Ljubljani SI-1351 - SLOVENIA - - 8C-64-22 (hex) Sony Ericsson Mobile Communications AB - 8C6422 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - 8C-68-78 (hex) Nortek-AS - 8C6878 (base 16) Nortek-AS - Vangkroken 2 - Akreshus 1351 RUD - NORWAY - - 8C-6A-E4 (hex) Viogem Limited - 8C6AE4 (base 16) Viogem Limited - Paddock House - Rectory Lane - Orlingbury Northamptonshire NN141JH - UNITED KINGDOM - - 8C-70-5A (hex) Intel Corporate - 8C705A (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 8C-71-F8 (hex) Samsung Electronics Co.,Ltd - 8C71F8 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 8C-73-6E (hex) Fujitsu Limited - 8C736E (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome,Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - 8C-76-C1 (hex) Goden Tech Limited - 8C76C1 (base 16) Goden Tech Limited - ROOM 510-511C2 NAN FUNG TOWER., - 173 DES VOEUS ROAD C - 999077 - HONG KONG - - 8C-77-12 (hex) Samsung Electronics Co.,Ltd - 8C7712 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 8C-77-16 (hex) LONGCHEER TELECOMMUNICATION LIMITED - 8C7716 (base 16) LONGCHEER TELECOMMUNICATION LIMITED - Building 1,No.401,Caobao Rd - Xuhui District - Shanghai 200233 - CHINA - - 8C-79-67 (hex) zte corporation - 8C7967 (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road - shenzhen guangdong 518057 - CHINA - - 8C-7B-9D (hex) Apple - 8C7B9D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 8C-7C-92 (hex) Apple - 8C7C92 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 8C-7C-B5 (hex) Hon Hai Precision Ind. Co.,Ltd. - 8C7CB5 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 8C-7C-FF (hex) Brocade Communications Systems, Inc. - 8C7CFF (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - 8C-7E-B3 (hex) Lytro, Inc. - 8C7EB3 (base 16) Lytro, Inc. - 1300 Terra Bella Avenue - Mountain View California 94043 - UNITED STATES - - 8C-7F-3B (hex) ARRIS Group, Inc. - 8C7F3B (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - 8C-82-A8 (hex) Insigma Technology Co.,Ltd - 8C82A8 (base 16) Insigma Technology Co.,Ltd - No.226 Tianmushan Road, - Hangzhou Zhejiang 310000 - CHINA - - 8C-84-01 (hex) PRIVATE - 8C8401 (base 16) - - 8C-87-3B (hex) Leica Camera AG - 8C873B (base 16) Leica Camera AG - Am Leitz-Park 5 - Wetzlar Hessen 35578 - GERMANY - - 8C-89-A5 (hex) Micro-Star INT'L CO., LTD - 8C89A5 (base 16) Micro-Star INT'L CO., LTD - No.69, Lide st. - Jhonghe City - Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - 8C-8A-6E (hex) ESTUN AUTOMATION TECHNOLOY CO., LTD - 8C8A6E (base 16) ESTUN AUTOMATION TECHNOLOY CO., LTD - 16,Shuige Road - Jiangning Development Zone - Nanjing Jiangsu 211106 - CHINA - - 8C-8B-83 (hex) Texas Instruments - 8C8B83 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - 8C-8E-76 (hex) taskit GmbH - 8C8E76 (base 16) taskit GmbH - Groß-Berliner Damm 37 - Berlin 12487 - GERMANY - - 8C-90-D3 (hex) Alcatel Lucent - 8C90D3 (base 16) Alcatel Lucent - 600 March Drive - Ottawa ON K2K 2E6 - CANADA - - 8C-91-09 (hex) Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. - 8C9109 (base 16) Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. - No.399,Baisheng Road,Jinxi Town - Kunshan Jiangsu 215324 - CHINA - - 8C-92-36 (hex) Aus.Linx Technology Co., Ltd. - 8C9236 (base 16) Aus.Linx Technology Co., Ltd. - 6F-2, No. 190, Sec. 2, Zhongxing Rd., Xindian Dist., - New Taipei City 23146 - TAIWAN, PROVINCE OF CHINA - - 8C-94-CF (hex) Encell Technology, Inc. - 8C94CF (base 16) Encell Technology, Inc. - 1412 Sachem Place, Suite 204 - Charlottesville VA 22901 - UNITED STATES - - 8C-A0-48 (hex) Beijing NeTopChip Technology Co.,LTD - 8CA048 (base 16) Beijing NeTopChip Technology Co.,LTD - 309,Intergration Building Olympic Center, No.1 An Ding Road,Chao Yang District,, - Beijing 100029 - CHINA - - 8C-A9-82 (hex) Intel Corporate - 8CA982 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 8C-AE-4C (hex) Plugable Technologies - 8CAE4C (base 16) Plugable Technologies - 40 Lake Bellevue Dr. - Suite 100 - Bellevue WA 98005 - UNITED STATES - - 8C-AE-89 (hex) Y-cam Solutions Ltd - 8CAE89 (base 16) Y-cam Solutions Ltd - 3 dee road - Richmond Surrey TW9 2JN - UNITED KINGDOM - - 8C-B0-94 (hex) Airtech I&C Co., Ltd - 8CB094 (base 16) Airtech I&C Co., Ltd - 33B-9L #613-9, Namchon-dong - Namdong-gu Incheon 405-846 - KOREA, REPUBLIC OF - - 8C-B6-4F (hex) CISCO SYSTEMS, INC. - 8CB64F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 8C-B7-F7 (hex) Shenzhen UniStrong Science & Technology Co., Ltd - 8CB7F7 (base 16) Shenzhen UniStrong Science & Technology Co., Ltd - 17/F, Global Digital Bldg, Hi-tech Park - Nanshan District - Shen zhen Guang dong 518000 - CHINA - - 8C-B8-2C (hex) IPitomy Communications - 8CB82C (base 16) IPitomy Communications - 1940 Northgate Boulevard - Suite B-1 - Sarasota Florida 34234 - UNITED STATES - - 8C-B8-64 (hex) AcSiP Technology Corp. - 8CB864 (base 16) AcSiP Technology Corp. - 3F., No.22, Dalin Rd., - Taoyuan City 330 - TAIWAN, PROVINCE OF CHINA - - 8C-BE-BE (hex) Xiaomi Technology Co.,Ltd - 8CBEBE (base 16) Xiaomi Technology Co.,Ltd - The Rainbow City of China Resources, - NO 68,Qinghe Middle Street - Haidian District Beijing 100085 - CHINA - - 8C-BF-9D (hex) Shanghai Xinyou Information Technology Ltd. Co. - 8CBF9D (base 16) Shanghai Xinyou Information Technology Ltd. Co. - 905,418 Guiqing Road, Xuhui District, - Shanghai Shanghai 200233 - CHINA - - 8C-BF-A6 (hex) Samsung Electronics Co.,Ltd - 8CBFA6 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 8C-C1-21 (hex) Panasonic Corporation AVC Networks Company - 8CC121 (base 16) Panasonic Corporation AVC Networks Company - 1-15 Matsuo-cho - Kadoma Osaka 571-8504 - JAPAN - - 8C-C5-E1 (hex) ShenZhen Konka Telecommunication Technology Co.,Ltd - 8CC5E1 (base 16) ShenZhen Konka Telecommunication Technology Co.,Ltd - No.9008 Shennan Road - ,Overseas Chinese Town - ShenZhen GuangDong 518053 - CHINA - - 8C-C7-AA (hex) Radinet Communications Inc. - 8CC7AA (base 16) Radinet Communications Inc. - 7F-2, No.229, Fuxing 2nd Rd, Zhubei, 30271 - Hsinchu Taiwan 30271 - TAIWAN, PROVINCE OF CHINA - - 8C-C7-D0 (hex) zhejiang ebang communication co.,ltd - 8CC7D0 (base 16) zhejiang ebang communication co.,ltd - 1418-36#,Moganshan Road - hangzhou zhejiang 310013 - CHINA - - 8C-C8-CD (hex) Samsung Electronics Co., LTD - 8CC8CD (base 16) Samsung Electronics Co., LTD - 416, Maetan 3-dong, Yeongtong-gu - Suwon Gyeonggi-do 443742 - KOREA, REPUBLIC OF - - 8C-CD-A2 (hex) ACTP, Inc. - 8CCDA2 (base 16) ACTP, Inc. - 2400 Sand Lake Rd - #600 - Orlando FL 32809 - UNITED STATES - - 8C-CD-E8 (hex) Nintendo Co., Ltd. - 8CCDE8 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - 8C-CF-5C (hex) BEFEGA GmbH - 8CCF5C (base 16) BEFEGA GmbH - Reichenbacher Str. 22 - Schwabach Bavaria 91126 - GERMANY - - 8C-D1-7B (hex) CG Mobile - 8CD17B (base 16) CG Mobile - 3F Caohejing Software Building, No.461 Hongcao Rd.,XuHui District - Shanghai 200233 - CHINA - - 8C-D3-A2 (hex) VisSim AS - 8CD3A2 (base 16) VisSim AS - Vollveien 5 - Horten Vestfold 3183 - NORWAY - - 8C-D6-28 (hex) Ikor Metering - 8CD628 (base 16) Ikor Metering - Francisco Grandmontagne 4 - San Sebastian Guipuzcoa 20008 - SPAIN - - 8C-DB-25 (hex) ESG Solutions - 8CDB25 (base 16) ESG Solutions - 20 Hyperion Court - Kingston Ontario K7K 7K2 - CANADA - - 8C-DC-D4 (hex) Hewlett Packard - 8CDCD4 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 8C-DD-8D (hex) Wifly-City System Inc. - 8CDD8D (base 16) Wifly-City System Inc. - 4F.,-1,NO 106,RUEIGUANG Rd.Neihu District, - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - 8C-DE-52 (hex) ISSC Technologies Corp. - 8CDE52 (base 16) ISSC Technologies Corp. - 4F, No.8, Dusing Rd., - Hsinchu Science Park, - Hsinchu City 30078 - TAIWAN, PROVINCE OF CHINA - - 8C-DE-99 (hex) Comlab Inc. - 8CDE99 (base 16) Comlab Inc. - 2300 Leon-Harmel, suite 220 - Quebec G1N 4L2 - CANADA - - 8C-DF-9D (hex) NEC Corporation - 8CDF9D (base 16) NEC Corporation - 7-1, Shiba 5-chome, - Minato-ku - Tokyo 108-8001 - JAPAN - - 8C-E0-81 (hex) zte corporation - 8CE081 (base 16) zte corporation - 12/F.,R&D building,kejinan Road - Shenzhen Guangdong 518057 - CHINA - - 8C-E7-48 (hex) PRIVATE - 8CE748 (base 16) - - 8C-E7-8C (hex) DK Networks - 8CE78C (base 16) DK Networks - 20F-3, No.689, Zhong-Zheng Road, Zhong-He Dist. - New Taipei City Taiwan 235 - TAIWAN, PROVINCE OF CHINA - - 8C-E7-B3 (hex) Sonardyne International Ltd - 8CE7B3 (base 16) Sonardyne International Ltd - Blackbushe Business Park - Yateley Hampshire GU46 6GD - UNITED KINGDOM - - 8C-EE-C6 (hex) Precepscion Pty. Ltd. - 8CEEC6 (base 16) Precepscion Pty. Ltd. - Level 10 - 99 Queen St. - Melbourne Victoria 3000 - AUSTRALIA - - 8C-F2-28 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - 8CF228 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan - Shenzhen Guangdong 518057 - CHINA - - 8C-F8-13 (hex) ORANGE POLSKA - 8CF813 (base 16) ORANGE POLSKA - AL.JEROZOLIMSKIE 160 - WARSAW MASOVIA 02-326 - POLAND - - 8C-F9-45 (hex) Power Automation pte Ltd - 8CF945 (base 16) Power Automation pte Ltd - 28 Ayer Rajah Crescent - #05-02/03 - 139959 - SINGAPORE - - 8C-F9-C9 (hex) MESADA Technology Co.,Ltd. - 8CF9C9 (base 16) MESADA Technology Co.,Ltd. - TongFng Information Harbor,No.11 LangShan Road,HI-tech Park,Nanshan District, - Shenzhen GuangDong 518057 - CHINA - - 8C-FA-BA (hex) Apple - 8CFABA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 8C-FD-F0 (hex) QUALCOMM Incorporated - 8CFDF0 (base 16) QUALCOMM Incorporated - 5775 Morehouse Drive - San Diego CA 92121 - UNITED STATES - - 90-00-4E (hex) Hon Hai Precision Ind. Co.,Ltd. - 90004E (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 90-00-DB (hex) Samsung Electronics Co.,Ltd - 9000DB (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 90-01-3B (hex) SAGEMCOM - 90013B (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON 92848 - FRANCE - - 90-02-8A (hex) Shenzhen Shidean Legrand Electronic Products Co.,Ltd - 90028A (base 16) Shenzhen Shidean Legrand Electronic Products Co.,Ltd - Block39,Shahe Industrial Zone Baishizhou - Nanshan District,Shenzhen - Guangdong 518053 - CHINA - - 90-02-A9 (hex) ZHEJIANG DAHUA TECHNOLOGY CO.,LTD - 9002A9 (base 16) ZHEJIANG DAHUA TECHNOLOGY CO.,LTD - NO.1199 BinAn Road - Binjiang District - Hangzhou Zhejiang 310053 - CHINA - - 90-03-B7 (hex) PARROT - 9003B7 (base 16) PARROT - 174 quai de jemmapes - PARIS 7510 - FRANCE - - 90-09-17 (hex) Far-sighted mobile - 900917 (base 16) Far-sighted mobile - Technology Park Desay Building 6th-Floor - Nanshan District - Shenzhen Guangdong Province 518000 - CHINA - - 90-0A-39 (hex) Wiio, Inc. - 900A39 (base 16) Wiio, Inc. - 99 S. Almaden Boulevard - San Jose California 95113 - UNITED STATES - - 90-0A-3A (hex) PSG Plastic Service GmbH - 900A3A (base 16) PSG Plastic Service GmbH - Pinaer Str. 12-16 - Mannheim BW 68309 - GERMANY - - 90-0C-B4 (hex) Alinket Electronic Technology Co., Ltd - 900CB4 (base 16) Alinket Electronic Technology Co., Ltd - 412 Guilin Rd. 3F, Xuhui District - Shanghai Shanghai 201235 - CHINA - - 90-0D-66 (hex) Digimore Electronics Co., Ltd - 900D66 (base 16) Digimore Electronics Co., Ltd - 10 FL., No. 61, Yan-Ping South Road - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - 90-0D-CB (hex) ARRIS Group, Inc. - 900DCB (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 90-17-9B (hex) Nanomegas - 90179B (base 16) Nanomegas - BD Ed.Machtens 79/22 - BXL Molenbeek 1080 - BELGIUM - - 90-17-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD - 9017AC (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 90-18-5E (hex) Apex Tool Group GmbH & Co OHG - 90185E (base 16) Apex Tool Group GmbH & Co OHG - Industriestraße 1 - Westhausen 73463 - GERMANY - - 90-18-7C (hex) Samsung Electro Mechanics co., LTD. - 90187C (base 16) Samsung Electro Mechanics co., LTD. - 314, Maetan3-Dong, Yeongtong-Gu - Suwon KYUNGGI-DO 443-743 - KOREA, REPUBLIC OF - - 90-18-AE (hex) Shanghai Meridian Technologies, Co. Ltd. - 9018AE (base 16) Shanghai Meridian Technologies, Co. Ltd. - Suite 6A Tongsheng Tower - #458 Fushan Road - Pudong shanghai 200122 - CHINA - - 90-19-00 (hex) SCS SA - 901900 (base 16) SCS SA - Via Pini, 32 - Biasca 6710 - SWITZERLAND - - 90-1A-CA (hex) ARRIS Group, Inc. - 901ACA (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 90-1B-0E (hex) Fujitsu Technology Solutions GmbH - 901B0E (base 16) Fujitsu Technology Solutions GmbH - Buergermeister-Ulrich-Strasse 100 - Augsburg Bayern 86199 - GERMANY - - 90-1D-27 (hex) zte corporation - 901D27 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 90-1E-DD (hex) GREAT COMPUTER CORPORATION - 901EDD (base 16) GREAT COMPUTER CORPORATION - 4F., No.236, Fude 2nd Rd., Xizhi Dist., - New Taipei City 22151 - TAIWAN, PROVINCE OF CHINA - - 90-20-3A (hex) BYD Precision Manufacture Co.,Ltd - 90203A (base 16) BYD Precision Manufacture Co.,Ltd - Building 23#,NO.3009 BYD Road,Pingshan - Shenzhen Guangdong 518118 - CHINA - - 90-20-83 (hex) General Engine Management Systems Ltd. - 902083 (base 16) General Engine Management Systems Ltd. - GEMS - Crabtree Road - Egham Surrey TW208RN - UNITED KINGDOM - - 90-21-06 (hex) BSkyB Ltd - 902106 (base 16) BSkyB Ltd - 130 KINGS ROAD - BRENTWOOD ESSEX CM14 4EQ - UNITED KINGDOM - - 90-21-55 (hex) HTC Corporation - 902155 (base 16) HTC Corporation - No.23 Xinghua Road - Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 90-21-81 (hex) Shanghai Huaqin Telecom Technology Co.,Ltd - 902181 (base 16) Shanghai Huaqin Telecom Technology Co.,Ltd - No.1 Building,399 Keyuan Road, Zhangjian Hi-Tech Park, - Pudong New Area, Shanghai, China - shanghai shanghai 201203 - CHINA - - 90-27-E4 (hex) Apple - 9027E4 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-2B-34 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 902B34 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - Pin-Jen City, - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 90-2C-C7 (hex) C-MAX Asia Limited - 902CC7 (base 16) C-MAX Asia Limited - Unit 117, 1/F, Liven House - 61-63 King Yip Street - Kwun Tong Kowloon 852 - HONG KONG - - 90-2E-1C (hex) Intel Corporate - 902E1C (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 90-2E-87 (hex) LabJack - 902E87 (base 16) LabJack - 3232 S Vance St STE 100 - Lakewood CO 80227 - UNITED STATES - - 90-31-CD (hex) Onyx Healthcare Inc. - 9031CD (base 16) Onyx Healthcare Inc. - 2F ,No135, Lane235, - PaoChiao Rd,Hsin-Tien Dist - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 90-34-2B (hex) Gatekeeper Systems, Inc. - 90342B (base 16) Gatekeeper Systems, Inc. - 8 Studebaker - Irvine CA 92618 - UNITED STATES - - 90-34-FC (hex) Hon Hai Precision Ind. Co.,Ltd. - 9034FC (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 90-35-6E (hex) Vodafone Omnitel N.V. - 90356E (base 16) Vodafone Omnitel N.V. - Via Guglielmo Jervis, 13 - Ivrea Italy / Tourin 10015 - ITALY - - 90-38-DF (hex) Changzhou Tiannengbo System Co. Ltd. - 9038DF (base 16) Changzhou Tiannengbo System Co. Ltd. - #9 East Hehai Road, RM 306 - Changzhou Jiangsu Province 213000 - CHINA - - 90-3A-A0 (hex) Alcatel-Lucent - 903AA0 (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 90-3C-92 (hex) Apple - 903C92 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-3C-AE (hex) Yunnan KSEC Digital Technology Co.,Ltd. - 903CAE (base 16) Yunnan KSEC Digital Technology Co.,Ltd. - 3F,NO.176 Keyi ROAD,High and New Technological Industrial Development Zone - Kunming Yunnan 650106 - CHINA - - 90-3D-5A (hex) Shenzhen Wision Technology Holding Limited - 903D5A (base 16) Shenzhen Wision Technology Holding Limited - Room 26A, Jinrun Building, N0.6019, Shennan Rd., Futian District - Shenzhen Guangdong 518040 - CHINA - - 90-3D-6B (hex) Zicon Technology Corp. - 903D6B (base 16) Zicon Technology Corp. - 15F., No.688-2, Zhongzheng Rd., Zhonghe City, Taipei County 235 - Taipei 23586 - TAIWAN, PROVINCE OF CHINA - - 90-3E-AB (hex) ARRIS Group, Inc. - 903EAB (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 90-45-06 (hex) Tokyo Boeki Medisys Inc. - 904506 (base 16) Tokyo Boeki Medisys Inc. - 1-14-21, Higashitoyoda - Hino Tokyo 191-0052 - JAPAN - - 90-46-B7 (hex) Vadaro Pte Ltd - 9046B7 (base 16) Vadaro Pte Ltd - 71 Ayer Rajah Crescent - #04-18 Ayer Rajah Industrial Estate - 139951 - SINGAPORE - - 90-47-16 (hex) RORZE CORPORATION - 904716 (base 16) RORZE CORPORATION - 1588-2 Michinoue, Kannabe-cho - Fukuyama Hiroshima 720-2104 - JAPAN - - 90-48-9A (hex) Hon Hai Precision Ind. Co.,Ltd. - 90489A (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District,Chongqing,China - Chongqing Chongqing 401332 - CHINA - - 90-49-FA (hex) Intel Corporation - 9049FA (base 16) Intel Corporation - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 90-4C-E5 (hex) Hon Hai Precision Ind. Co.,Ltd. - 904CE5 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 90-4E-2B (hex) Huawei Technologies Co., Ltd - 904E2B (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 90-50-7B (hex) Advanced PANMOBIL Systems GmbH & Co. KG - 90507B (base 16) Advanced PANMOBIL Systems GmbH & Co. KG - Hansestraße 91 - Cologne NRW 51149 - GERMANY - - 90-51-3F (hex) Elettronica Santerno SpA - 90513F (base 16) Elettronica Santerno SpA - Via della Concia 7 - Castel Guelfo (BO) 40026 - ITALY - - 90-54-46 (hex) TES ELECTRONIC SOLUTIONS - 905446 (base 16) TES ELECTRONIC SOLUTIONS - Immeuble Odyssee - ZAC de Blossac - BRUZ 35170 - FRANCE - - 90-55-AE (hex) Ericsson, EAB/RWI/K - 9055AE (base 16) Ericsson, EAB/RWI/K - SkolgÃ¥ngen 17 - Gävle SE-800 06 - SWEDEN - - 90-56-82 (hex) Lenbrook Industries Limited - 905682 (base 16) Lenbrook Industries Limited - 633 Granite Court - Pickering Ontario L1W 3K1 - CANADA - - 90-56-92 (hex) Autotalks Ltd. - 905692 (base 16) Autotalks Ltd. - Kfar Netter - Israel 40593 - ISRAEL - - 90-59-AF (hex) Texas Instruments - 9059AF (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 90-5F-2E (hex) TCT Mobile Limited - 905F2E (base 16) TCT Mobile Limited - 5F, C-Tower, No.232, Liangjing Road - Zhangjiang High-tech Park - Pudong Shanghai 201203 - CHINA - - 90-5F-8D (hex) modas GmbH - 905F8D (base 16) modas GmbH - Belziger Str. 69-71 - Berlin 10823 - GERMANY - - 90-61-0C (hex) Fida International (S) Pte Ltd - 90610C (base 16) Fida International (S) Pte Ltd - Blk 16, Kallang Place - #06-02, - 339156 - SINGAPORE - - 90-67-17 (hex) Alphion India Private Limited - 906717 (base 16) Alphion India Private Limited - 405 Windfall, Sahar Plaza - J B Nagar, Andheri Kurla Road, Andheri - Mumbai Maharashtra 400059 - INDIA - - 90-67-1C (hex) Huawei Technologies Co., Ltd - 90671C (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - 90-67-B5 (hex) Alcatel-Lucent - 9067B5 (base 16) Alcatel-Lucent - 600-700 Mountain Ave. - 3B-217 - Murray Hiill NJ 07974-0636 - UNITED STATES - - 90-67-F3 (hex) Alcatel Lucent - 9067F3 (base 16) Alcatel Lucent - Via trento, 30 - Vimercate MB 20059 - ITALY - - 90-68-C3 (hex) Motorola Mobility LLC - 9068C3 (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - 90-6C-AC (hex) Fortinet, Inc. - 906CAC (base 16) Fortinet, Inc. - 899 Kifer Road - Sunnyvale California 94086 - UNITED STATES - - 90-6D-C8 (hex) DLG Automação Industrial Ltda - 906DC8 (base 16) DLG Automação Industrial Ltda - Rua José Batista Soares, 53 - Distrito Industrial - Sertãozinho São Paulo 14176-119 - BRAZIL - - 90-6E-BB (hex) Hon Hai Precision Ind. Co.,Ltd. - 906EBB (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 90-70-25 (hex) Garea Microsys Co.,Ltd. - 907025 (base 16) Garea Microsys Co.,Ltd. - 4th Floor, Building 2, Software Park - 2 Keling Road, New district, - Suzhou Jiangsu 215163 - CHINA - - 90-72-40 (hex) Apple - 907240 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-79-90 (hex) Benchmark Electronics Romania SRL - 907990 (base 16) Benchmark Electronics Romania SRL - Aeroportului no 6 Ghimbav - Brasov 507075 - ROMANIA - - 90-7A-0A (hex) Gebr. Bode GmbH & Co KG - 907A0A (base 16) Gebr. Bode GmbH & Co KG - Ochshaeuser Str. 14 - Kassel 34266 - GERMANY - - 90-7A-28 (hex) Beijing Morncloud Information And Technology Co. Ltd. - 907A28 (base 16) Beijing Morncloud Information And Technology Co. Ltd. - A#1107, XiaoYun center - XiaoYun Road - Chaoyang District Beijing 100125 - CHINA - - 90-7A-F1 (hex) SNUPI Technologies - 907AF1 (base 16) SNUPI Technologies - Fluke Hall, Box 352141 - 4000 Mason Road - Seattle WA 98195 - UNITED STATES - - 90-7E-BA (hex) UTEK TECHNOLOGY (SHENZHEN) CO.,LTD - 907EBA (base 16) UTEK TECHNOLOGY (SHENZHEN) CO.,LTD - 6F, C Building JiaAn Industrial Zone, 72# district of Baoan, ShenZhen, China - SHENZHEN Guangdong Province 518101 - CHINA - - 90-7F-61 (hex) Chicony Electronics Co., Ltd. - 907F61 (base 16) Chicony Electronics Co., Ltd. - No.25, Wu-Gong 6th Rd., Wu Ku Industrial Park, - New Taipei City, 248 - TAIWAN, PROVINCE OF CHINA - - 90-82-60 (hex) IEEE 1904.1 Working Group - 908260 (base 16) IEEE 1904.1 Working Group - 1351 Redwood Way - Petaluma CA 94954 - UNITED STATES - - 90-83-7A (hex) General Electric Water & Process Technologies - 90837A (base 16) General Electric Water & Process Technologies - 6060 Spine Road - Boulder Colorado 80301-3687 - UNITED STATES - - 90-84-0D (hex) Apple - 90840D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-88-A2 (hex) IONICS TECHNOLOGY ME LTDA - 9088A2 (base 16) IONICS TECHNOLOGY ME LTDA - RUA DEP. ANTONIO EDU VIEIRA - FLORIAN POLIS SANTA CATARINA 88040000 - BRAZIL - - 90-8C-09 (hex) Total Phase - 908C09 (base 16) Total Phase - 735 Palomar Ave - Sunnyvale CA 94085 - UNITED STATES - - 90-8C-44 (hex) H.K ZONGMU TECHNOLOGY CO., LTD. - 908C44 (base 16) H.K ZONGMU TECHNOLOGY CO., LTD. - ROOM 604, BUILDING B, 977 SHANGFENG RD - TANG TOWN, PUDONG DISTRICT - SHANGHAI 201201 - CHINA - - 90-8C-63 (hex) GZ Weedong Networks Technology Co. , Ltd - 908C63 (base 16) GZ Weedong Networks Technology Co. , Ltd - 38th Floor,Ren Feng Building - NO.490 Tianhe road - Guangzhou Guangdong 510620 - CHINA - - 90-8D-1D (hex) GH Technologies - 908D1D (base 16) GH Technologies - 5022 Binhe Road, Block B, United Plaza - Shenzhen 518026 - CHINA - - 90-8D-6C (hex) Apple - 908D6C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-8F-CF (hex) UNO System Co., Ltd - 908FCF (base 16) UNO System Co., Ltd - #402 Kolon Science Valley °., 187-10, Guro-dong, Guro-gu - Seoul 152-848 - KOREA, REPUBLIC OF - - 90-90-3C (hex) TRISON TECHNOLOGY CORPORATION - 90903C (base 16) TRISON TECHNOLOGY CORPORATION - No.3, Kung-Yeh 12th Rd., Ping-Jen Industrial Park, - Ping-Jen City, TaoYuan County 32459 - TAIWAN, PROVINCE OF CHINA - - 90-90-60 (hex) RSI VIDEO TECHNOLOGIES - 909060 (base 16) RSI VIDEO TECHNOLOGIES - 56, Rue Jean-Giraudoux - BAT 60 - Parc d'activité des Forges - STRASBOURG Bas-Rhin 67200 - FRANCE - - 90-92-B4 (hex) Diehl BGT Defence GmbH & Co. KG - 9092B4 (base 16) Diehl BGT Defence GmbH & Co. KG - Alte Nussdorfer Strasse 13 - E-EE - Ueberlingen 88662 - GERMANY - - 90-94-E4 (hex) D-Link International - 9094E4 (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy Singapore 609917 - Singapore Singapore 609917 - SINGAPORE - - 90-98-64 (hex) Impex-Sat GmbH&Co KG - 909864 (base 16) Impex-Sat GmbH&Co KG - Beim Giesshaus 7 - Glueckstadt 25348 - GERMANY - - 90-99-16 (hex) ELVEES NeoTek OJSC - 909916 (base 16) ELVEES NeoTek OJSC - Proezd 4922, dom 4, stroenie 2 - Moscow Zelenograd 124498 - RUSSIAN FEDERATION - - 90-9D-E0 (hex) Newland Design + Assoc. Inc. - 909DE0 (base 16) Newland Design + Assoc. Inc. - 3186-G Airway Ave. - Costa Mesa CA 92626 - UNITED STATES - - 90-9F-33 (hex) EFM Networks - 909F33 (base 16) EFM Networks - 6F, Benposra II 1197-1 Bojeong Giheung Gu - Yong In Kyunggi do 446913 - KOREA, REPUBLIC OF - - 90-9F-43 (hex) Accutron Instruments Inc. - 909F43 (base 16) Accutron Instruments Inc. - 11 Mary Street - Unit B - Sudbury Ontario P3C1B4 - CANADA - - 90-A2-10 (hex) United Telecoms Ltd - 90A210 (base 16) United Telecoms Ltd - 18A/19,Doddanekundi Industrial Area, - Mahadevapura Post, - Bangalore Karanataka 560048 - INDIA - - 90-A2-DA (hex) GHEO SA - 90A2DA (base 16) GHEO SA - Via Soldini, 22 - Chiasso CH-6830 - SWITZERLAND - - 90-A4-DE (hex) Wistron Neweb Corp. - 90A4DE (base 16) Wistron Neweb Corp. - 20 Park Avenue II, Hsinchu Science Park, - Hsinchu 308 - TAIWAN, PROVINCE OF CHINA - - 90-A7-83 (hex) JSW PACIFIC CORPORATION - 90A783 (base 16) JSW PACIFIC CORPORATION - 3F-3, No.700, Chung-Zheng Rd, Zhonghe District - New Taipei City 235 - TAIWAN, PROVINCE OF CHINA - - 90-A7-C1 (hex) Pakedge Device and Software Inc. - 90A7C1 (base 16) Pakedge Device and Software Inc. - 1011 Edwards Road - Burlingame CA 94010 - UNITED STATES - - 90-AC-3F (hex) BrightSign LLC - 90AC3F (base 16) BrightSign LLC - 16795 Lark Ave. - Suite 200 - Los Gatos CA 95032 - UNITED STATES - - 90-AE-1B (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 90AE1B (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - 90-B1-1C (hex) Dell Inc. - 90B11C (base 16) Dell Inc. - One dell Way - MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - 90-B1-34 (hex) ARRIS Group, Inc. - 90B134 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 90-B2-1F (hex) Apple - 90B21F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-B6-86 (hex) Murata Manufacturing Co., Ltd. - 90B686 (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 90-B8-D0 (hex) Joyent, Inc. - 90B8D0 (base 16) Joyent, Inc. - 345 California Street, - Suite 2000 - San Francisco CA 94104 - UNITED STATES - - 90-B9-31 (hex) Apple, Inc - 90B931 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-B9-7D (hex) Johnson Outdoors Marine Electronics d/b/a Minnkota - 90B97D (base 16) Johnson Outdoors Marine Electronics d/b/a Minnkota - 1531 E Madison Ave - Mankato MN 56001 - UNITED STATES - - 90-C1-15 (hex) Sony Ericsson Mobile Communications AB - 90C115 (base 16) Sony Ericsson Mobile Communications AB - Mobilvägen 10 - Lund 22181 - SWEDEN - - 90-C3-5F (hex) Nanjing Jiahao Technology Co., Ltd. - 90C35F (base 16) Nanjing Jiahao Technology Co., Ltd. - Moling Industrial Park, Development Zone, Jiangning, Nanjing - Nanjing Jiangsu 211111 - CHINA - - 90-C6-82 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 90C682 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 90-C7-92 (hex) ARRIS Group, Inc. - 90C792 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - 90-CC-24 (hex) Synaptics, Inc - 90CC24 (base 16) Synaptics, Inc - 3120 Scott Blvd. - Santa Clara CA 95054 - UNITED STATES - - 90-CF-15 (hex) Nokia Corporation - 90CF15 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 90-CF-6F (hex) Dlogixs Co Ltd - 90CF6F (base 16) Dlogixs Co Ltd - DLogixs Bldg, #351-1, Anyang-Dong - Manan-Gu - Anyang-si Gyeonggi-do 430-010 - KOREA, REPUBLIC OF - - 90-CF-7D (hex) Qingdao Hisense Electric Co.,Ltd. - 90CF7D (base 16) Qingdao Hisense Electric Co.,Ltd. - 11,Jiangxi Road,Qingdao,China - Qingdao Shandong 266071 - CHINA - - 90-D1-1B (hex) Palomar Medical Technologies - 90D11B (base 16) Palomar Medical Technologies - 15 Network Drive - Burlington MA 01803 - UNITED STATES - - 90-D7-4F (hex) Bookeen - 90D74F (base 16) Bookeen - 27, rue de la Vistule - Paris 75013 - FRANCE - - 90-D7-EB (hex) Texas Instruments - 90D7EB (base 16) Texas Instruments - 12500 TI Boulevard - MS 8723 - Dallas TX 75243 - UNITED STATES - - 90-D8-52 (hex) Comtec Co., Ltd. - 90D852 (base 16) Comtec Co., Ltd. - 3F., No.81, Jiankang Rd., - Zhonghe City Taipei County 23586 - TAIWAN, PROVINCE OF CHINA - - 90-D9-2C (hex) HUG-WITSCHI AG - 90D92C (base 16) HUG-WITSCHI AG - Auriedstrasse 10 - Boesingen Fribourg 3178 - SWITZERLAND - - 90-DA-4E (hex) AVANU - 90DA4E (base 16) AVANU - 5205 Prospect Rd - Suite 135-143 - San Jose CA 95129-5034 - UNITED STATES - - 90-DA-6A (hex) FOCUS H&S Co., Ltd. - 90DA6A (base 16) FOCUS H&S Co., Ltd. - #113, Doosan Venture Digm, 126-1 - Pyeongchon-Dong, Dongan-Gu, - Anyang Gyeonggi-Do 431-755 - KOREA, REPUBLIC OF - - 90-DB-46 (hex) E-LEAD ELECTRONIC CO., LTD - 90DB46 (base 16) E-LEAD ELECTRONIC CO., LTD - NO.37, GUNGDUNG 1ST RD. - SHENGANG SHIANG CHANGHUA 50971 - TAIWAN, PROVINCE OF CHINA - - 90-DF-B7 (hex) s.m.s smart microwave sensors GmbH - 90DFB7 (base 16) s.m.s smart microwave sensors GmbH - In den Waashainen 1 - Braunschweig NI 38108 - GERMANY - - 90-E0-F0 (hex) IEEE 1722a Working Group - 90E0F0 (base 16) IEEE 1722a Working Group - 8760 Sandy Parkway - Sandy Utah 84070 - UNITED STATES - - 90-E2-BA (hex) Intel Corporate - 90E2BA (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 90-E6-BA (hex) ASUSTek COMPUTER INC. - 90E6BA (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - 90-E7-C4 (hex) HTC Corporation - 90E7C4 (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - 90-EA-60 (hex) SPI Lasers Ltd - 90EA60 (base 16) SPI Lasers Ltd - 6 wellington Park - Hedge End - Southampton Hampshire S0302QU - UNITED KINGDOM - - 90-EF-68 (hex) ZyXEL Communications Corporation - 90EF68 (base 16) ZyXEL Communications Corporation - No. 6 Innovation Road II, Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 90-F1-AA (hex) Samsung Electronics Co.,LTD - 90F1AA (base 16) Samsung Electronics Co.,LTD - 416,Maetan 3Dong,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 90-F1-B0 (hex) Hangzhou Anheng Info&Tech CO.,LTD - 90F1B0 (base 16) Hangzhou Anheng Info&Tech CO.,LTD - 15F Zhongcai Bldg,#68 Tonghe Rd - Binjiang District - Hangzhou Zhejiang 310051 - CHINA - - 90-F2-78 (hex) Radius Gateway - 90F278 (base 16) Radius Gateway - 520 E. Montford Ave - Ada OH 45810 - UNITED STATES - - 90-F3-B7 (hex) Kirisun Communications Co., Ltd. - 90F3B7 (base 16) Kirisun Communications Co., Ltd. - 3-6Flrs, ROBETA Building, 1 QiMin Road, Songping Shan Area, - Science & Industry Park - Nanshan District, Shenzhen GuangDong 518057 - CHINA - - 90-F4-C1 (hex) Rand McNally - 90F4C1 (base 16) Rand McNally - 9855 Woods Drive - Skokie IL 60077 - UNITED STATES - - 90-F6-52 (hex) TP-LINK TECHNOLOGIES CO., LTD. - 90F652 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, - Shenzhen Guangdong Province, 518057 - CHINA - - 90-F7-2F (hex) Phillips Machine & Welding Co., Inc. - 90F72F (base 16) Phillips Machine & Welding Co., Inc. - 16125 E. Gale Ave. - Industry CA 91745 - UNITED STATES - - 90-FB-5B (hex) Avaya, Inc - 90FB5B (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - 90-FB-A6 (hex) Hon Hai Precision Ind.Co.Ltd - 90FBA6 (base 16) Hon Hai Precision Ind.Co.Ltd - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - 90-FD-61 (hex) Apple - 90FD61 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 90-FF-79 (hex) Metro Ethernet Forum - 90FF79 (base 16) Metro Ethernet Forum - 6033 W. Century Boulevard - Suite 1107 - Los Angeles California 90045 - UNITED STATES - - 94-00-70 (hex) Nokia Corporation - 940070 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - 94-01-49 (hex) AutoHotBox - 940149 (base 16) AutoHotBox - 14090 SW Frwy, Ste. 300 - Sugar Land TX 77478 - UNITED STATES - - 94-01-C2 (hex) Samsung Electronics Co.,Ltd - 9401C2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 94-04-9C (hex) HUAWEI TECHNOLOGIES CO.,LTD - 94049C (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518129 - CHINA - - 94-05-B6 (hex) Liling FullRiver Electronics & Technology Ltd - 9405B6 (base 16) Liling FullRiver Electronics & Technology Ltd - FullRiver Industrial Area Economic Development Zone - LiLing City - HuNan Province 412200 - CHINA - - 94-09-37 (hex) HUMAX Co., Ltd. - 940937 (base 16) HUMAX Co., Ltd. - HUMAX Village, 216, Hwangsaeul-ro, Bundang-gu, - Seongnam-si Gyeonggi-do 463-875 - KOREA, REPUBLIC OF - - 94-0B-2D (hex) NetView Technologies(Shenzhen) Co., Ltd - 940B2D (base 16) NetView Technologies(Shenzhen) Co., Ltd - RM2902,East Tower, Nanshan Software Park - Shenzhen Guangdong 518052 - CHINA - - 94-0B-D5 (hex) Himax Technologies, Inc - 940BD5 (base 16) Himax Technologies, Inc - No.26, Zilian Rd., Xinshi Dist. - Tainan City 741 - TAIWAN, PROVINCE OF CHINA - - 94-0C-6D (hex) TP-LINK Technologies Co.,Ltd. - 940C6D (base 16) TP-LINK Technologies Co.,Ltd. - Building 7, Second Part, Honghualing Industrial Zone - Xili town, Nanshan, - Shenzhen Guangdong 518000 - CHINA - - 94-10-3E (hex) Belkin International Inc. - 94103E (base 16) Belkin International Inc. - 12045 East Waterfront Drive - Playa Vista CA 90094 - UNITED STATES - - 94-11-DA (hex) ITF Fröschl GmbH - 9411DA (base 16) ITF Fröschl GmbH - Hauserbachstraße 7 - 10 - Walderbach Bavaria 93194 - GERMANY - - 94-16-73 (hex) Point Core SARL - 941673 (base 16) Point Core SARL - 29/31 Rue du Bois Galon - FONTENAY SOUS BOIS Ile de France 94120 - FRANCE - - 94-1D-1C (hex) TLab West Systems AB - 941D1C (base 16) TLab West Systems AB - Ebbe Lieberathsgatan 23B - Gothenburg 41265 - SWEDEN - - 94-20-53 (hex) Nokia Corporation - 942053 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - 94-21-97 (hex) Stalmart Technology Limited - 942197 (base 16) Stalmart Technology Limited - Rm1106-1107E, Building F, Xihaimingzhu, No.1, Taoyuan Road - Nanshan - Shenzhen Gunagdong 518052 - CHINA - - 94-23-6E (hex) Shenzhen Junlan Electronic Ltd - 94236E (base 16) Shenzhen Junlan Electronic Ltd - Block C,No.2 Industrial District, Fuyuan, Tangwei,Fuyong, Bao'an - Shenzhen Guangdong 518103 - CHINA - - 94-2E-17 (hex) Schneider Electric Canada Inc - 942E17 (base 16) Schneider Electric Canada Inc - 1400 industrielle street - La Prairie Quebec J5R 2E5 - CANADA - - 94-2E-63 (hex) Finsécur - 942E63 (base 16) Finsécur - 52 rue Paul Lescop - Nanterre 92000 - FRANCE - - 94-31-9B (hex) Alphatronics BV - 94319B (base 16) Alphatronics BV - Watergoorweg 71 - NIJKERK Gld 3861 MA - NETHERLANDS - - 94-33-DD (hex) Taco Electronic Solutions, Inc. - 9433DD (base 16) Taco Electronic Solutions, Inc. - 1160 Cranston Street - Cranston RI 02920 - UNITED STATES - - 94-35-0A (hex) Samsung Electronics Co.,Ltd - 94350A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 94-36-E0 (hex) Sichuan Bihong Broadcast & Television New Technologies Co.,Ltd - 9436E0 (base 16) Sichuan Bihong Broadcast & Television New Technologies Co.,Ltd - Guanghan City, Sichuan province Zhongshan road south three period of 36 - Deyang Guanghan Sichuan Province 618300 - CHINA - - 94-39-E5 (hex) Hon Hai Precision Ind. Co.,Ltd. - 9439E5 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 94-3A-F0 (hex) Nokia Corporation - 943AF0 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 94-3B-B1 (hex) KAONMEDIA - 943BB1 (base 16) KAONMEDIA - KAONMEDIA Building 513-4 - Yatop-Dong, Bundang-Gu - Sungnam-City Kyonggi-Do 463-839, KOREA - KOREA, REPUBLIC OF - - 94-40-A2 (hex) Anywave Communication Technologies, Inc. - 9440A2 (base 16) Anywave Communication Technologies, Inc. - 300 Knightsbridge Parkway, Suite 150 - Lincolnshire IL 60069 - UNITED STATES - - 94-44-44 (hex) LG Innotek - 944444 (base 16) LG Innotek - Jangduk-dong, Gwangsan-gu - Gwang-ju 506-731 - KOREA, REPUBLIC OF - - 94-44-52 (hex) Belkin International Inc. - 944452 (base 16) Belkin International Inc. - 12045 E. Waterfront Drive - Playa Vista Ca 90094 - UNITED STATES - - 94-46-96 (hex) BaudTec Corporation - 944696 (base 16) BaudTec Corporation - 12F, No.181, Sec.1.Tatung Rd. - Hsi-chih Taipei 221 - TAIWAN, PROVINCE OF CHINA - - 94-4A-09 (hex) BitWise Controls - 944A09 (base 16) BitWise Controls - 98 Inverness Dr East - Englewood CO 80112 - UNITED STATES - - 94-4A-0C (hex) Sercomm Corporation - 944A0C (base 16) Sercomm Corporation - 8F, 3-1, YuanQu St., NanKang, - Taipei Taiwan 115 - TAIWAN, PROVINCE OF CHINA - - 94-50-47 (hex) Rechnerbetriebsgruppe - 945047 (base 16) Rechnerbetriebsgruppe - Werner von Siemens Str. 64 - Würzburg Bayern 97076 - GERMANY - - 94-51-03 (hex) Samsung Electronics - 945103 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 94-51-BF (hex) Hyundai ESG - 9451BF (base 16) Hyundai ESG - Gangnam-gu - 942-19, Daechi 2-dong, - Seoul KOREA, REPUBLIC OF 135-845 - KOREA, REPUBLIC OF - - 94-54-93 (hex) Rigado, LLC - 945493 (base 16) Rigado, LLC - 2601 25th ST SE, STE 200 - Salem OR 97302 - UNITED STATES - - 94-59-2D (hex) EKE Building Technology Systems Ltd - 94592D (base 16) EKE Building Technology Systems Ltd - Piispanportti 7 - Espoo - 02240 - FINLAND - - 94-5B-7E (hex) TRILOBIT LTDA. - 945B7E (base 16) TRILOBIT LTDA. - R. ALVARENGA 1377 - BUTANTA - São Paulo 05509002 - BRAZIL - - 94-61-24 (hex) Pason Systems - 946124 (base 16) Pason Systems - 6130 - 3rd Street S.E. - Calgary Alberta T2H1K4 - CANADA - - 94-62-69 (hex) Arris Group, Inc. - 946269 (base 16) Arris Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - 94-63-D1 (hex) Samsung Electronics Co.,Ltd - 9463D1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 94-65-9C (hex) Intel Corporate - 94659C (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 94-70-D2 (hex) WINFIRM TECHNOLOGY - 9470D2 (base 16) WINFIRM TECHNOLOGY - 2-1015 Lotte IT Castle - 550-1 Gasan-dong, Geumcheon-gu - Seoul 153-768 - KOREA, REPUBLIC OF - - 94-71-AC (hex) TCT Mobile Limited - 9471AC (base 16) TCT Mobile Limited - 5F, E building, No. 232, Liang Jing Road ZhangJiang High-Tech Park, Pudong Area - Shanghai 201203 - CHINA - - 94-75-6E (hex) QinetiQ North America - 94756E (base 16) QinetiQ North America - 137 Delta Drive - Pittsburgh PA 15238 - UNITED STATES - - 94-77-2B (hex) Huawei Technologies Co., Ltd - 94772B (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - 94-7C-3E (hex) Polewall Norge AS - 947C3E (base 16) Polewall Norge AS - Vige Havnevei 78 - Kristiansand Vest-Agder 4633 - NORWAY - - 94-81-A4 (hex) Azuray Technologies - 9481A4 (base 16) Azuray Technologies - 7470 SW Bridgeport Rd - Durham OR 97224 - UNITED STATES - - 94-85-7A (hex) Evantage Industries Corp - 94857A (base 16) Evantage Industries Corp - 815 Bridge St. W. - Waterloo Ontario N2V 2M7 - CANADA - - 94-86-D4 (hex) Surveillance Pro Corporation - 9486D4 (base 16) Surveillance Pro Corporation - 12F., No.4, Ln. 609, Sec. 5, Chongxin Rd., Sanchong Dist. - New Taipei City 241 - TAIWAN, PROVINCE OF CHINA - - 94-87-7C (hex) ARRIS Group, Inc. - 94877C (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - 94-88-54 (hex) Texas Instruments - 948854 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 94-8B-03 (hex) EAGET Innovation and Technology Co., Ltd. - 948B03 (base 16) EAGET Innovation and Technology Co., Ltd. - 3/F, Building 4, Lianchuang Technology Park,Buji Town, - Shenzhen Guangdong 518112 - CHINA - - 94-8D-50 (hex) Beamex Oy Ab - 948D50 (base 16) Beamex Oy Ab - Ristisuonraitti 10 - Pietarsaari FI-68600 - FINLAND - - 94-8E-89 (hex) INDUSTRIAS UNIDAS SA DE CV - 948E89 (base 16) INDUSTRIAS UNIDAS SA DE CV - CARRETERA PANAMERICANA - MEXICO QUERETARO KILOMETRO 109 - PASTEJE JOCOTITLAN ESTADO DE MEXICO 50700 - MEXICO - - 94-8F-EE (hex) Hughes Telematics, Inc. - 948FEE (base 16) Hughes Telematics, Inc. - 2002 Summit Blvd - Suite 1800 - Atlanta GA 30319 - UNITED STATES - - 94-94-26 (hex) Apple - 949426 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 94-98-A2 (hex) Shanghai LISTEN TECH.LTD - 9498A2 (base 16) Shanghai LISTEN TECH.LTD - 7F,A#,NO.3699,Gonghexin Road - SHANGHAI SHANGHAI 200435 - CHINA - - 94-9B-FD (hex) Trans New Technology, Inc. - 949BFD (base 16) Trans New Technology, Inc. - KY Bldg. 8F, 5-14-4 Nishinippori - Arakawa Tokyo 116-0013 - JAPAN - - 94-9C-55 (hex) Alta Data Technologies - 949C55 (base 16) Alta Data Technologies - 4901 Rockaway Blvd, Building A - Rio Rancho NM 87124 - UNITED STATES - - 94-9F-3F (hex) Optek Digital Technology company limited - 949F3F (base 16) Optek Digital Technology company limited - Room508 Build A, Shennan Garden, Shenzhen Science and Industry Park, Nanshan - Shenzhen GuangDong 518057 - CHINA - - 94-9F-B4 (hex) ChengDu JiaFaAnTai Technology Co.,Ltd - 949FB4 (base 16) ChengDu JiaFaAnTai Technology Co.,Ltd - 8th Floor, Building No.2, Zone A of Wisdom Valley - No.443 of Wuxing 5th Road Wuhou District - Chengdu Sichuan 610000 - CHINA - - 94-A1-A2 (hex) AMPAK Technology Inc. - 94A1A2 (base 16) AMPAK Technology Inc. - No.1,Jen Ai Road - Hsinchu Industrail Park - Hukou Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - 94-A7-B7 (hex) zte corporation - 94A7B7 (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - 94-A7-BC (hex) BodyMedia, Inc. - 94A7BC (base 16) BodyMedia, Inc. - 420 Fort Duquesne Blvd - Gateway 1, Suite 1900 - Pittsburgh PA 15222 - UNITED STATES - - 94-AA-B8 (hex) Joview(Beijing) Technology Co. Ltd. - 94AAB8 (base 16) Joview(Beijing) Technology Co. Ltd. - Room 302, South Building - No.80 Xueyuannanlu - Beijing 100081 - CHINA - - 94-AC-CA (hex) trivum technologies GmbH - 94ACCA (base 16) trivum technologies GmbH - Heusteigstraße 37 - Stuttgart 70108 - GERMANY - - 94-AE-61 (hex) Alcatel Lucent - 94AE61 (base 16) Alcatel Lucent - Via trento, 30 - Vimercate MB 20059 - ITALY - - 94-AE-E3 (hex) Belden Hirschmann Industries (Suzhou) Ltd. - 94AEE3 (base 16) Belden Hirschmann Industries (Suzhou) Ltd. - 333 Yanhu Road, Huaqiao Town - Kunshan Jiangsu 215332 - CHINA - - 94-B4-0F (hex) Aruba Networks - 94B40F (base 16) Aruba Networks - 1344 Crossman Ave - Sunnyvale CA 94089 - UNITED STATES - - 94-B8-C5 (hex) RuggedCom Inc. - 94B8C5 (base 16) RuggedCom Inc. - 300 Applewood Crescent - Concord Ontario L4K 5C7 - CANADA - - 94-B9-B4 (hex) Aptos Technology - 94B9B4 (base 16) Aptos Technology - 5F., No.65, Guangfu N. Rd., Zhongxing Vil., - Hukou Township - Hsinchu 303 - TAIWAN, PROVINCE OF CHINA - - 94-BA-31 (hex) Visiontec da Amazônia Ltda. - 94BA31 (base 16) Visiontec da Amazônia Ltda. - Rod. Geraldo Scavone, 2300 - Galpao 27 - California Center - Pq. California - Jacareí SP 12305-490 - BRAZIL - - 94-BA-56 (hex) Shenzhen Coship Electronics Co., Ltd. - 94BA56 (base 16) Shenzhen Coship Electronics Co., Ltd. - Rainbow Bldg., North, Hi-Tech Industrial Park - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 94-BF-1E (hex) eflow Inc. / Smart Device Planning and Development Division - 94BF1E (base 16) eflow Inc. / Smart Device Planning and Development Division - Ryoka-Yoyogi building 3F - 4-2-12 Sendagaya - Shibuya-Ku TOKYO 151-0051 - JAPAN - - 94-BF-95 (hex) Shenzhen Coship Electronics Co., Ltd - 94BF95 (base 16) Shenzhen Coship Electronics Co., Ltd - Rainbow Bldg., North, Hi-Tech Industrial Park - Nanshan - Shenzhen Guangdong 518057 - CHINA - - 94-C0-14 (hex) Sorter Sp. j. Konrad Grzeszczyk MichaA, Ziomek - 94C014 (base 16) Sorter Sp. j. Konrad Grzeszczyk MichaA, Ziomek - ul. Gdynska 32 - 26-600 Radom - PL9482565081 Mazowieckie 26-600 - POLAND - - 94-C0-38 (hex) Tallac Networks - 94C038 (base 16) Tallac Networks - 6528 Lonetree Blvd. - Rocklin CA 95765 - UNITED STATES - - 94-C1-50 (hex) 2Wire Inc - 94C150 (base 16) 2Wire Inc - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - 94-C3-E4 (hex) SCA Schucker Gmbh & Co KG - 94C3E4 (base 16) SCA Schucker Gmbh & Co KG - Gewerbestrasse 52 - Bretten 75015 - GERMANY - - 94-C4-E9 (hex) PowerLayer Microsystems HongKong Limited - 94C4E9 (base 16) PowerLayer Microsystems HongKong Limited - 23 Zhichun Rd,Liangziyinzuo Rm1009 - Haidian District - Beijing 100083 - CHINA - - 94-C6-EB (hex) NOVA electronics, Inc. - 94C6EB (base 16) NOVA electronics, Inc. - Grand Axe Bldg. 3F. - 1-7-20, Uehara, - Shibuya-ku Tokyo 151-0064 - JAPAN - - 94-C7-AF (hex) Raylios Technology - 94C7AF (base 16) Raylios Technology - 12F., No.16, Jian 8th Rd - Zhonghe City Taipei County 23511 - TAIWAN, PROVINCE OF CHINA - - 94-C9-62 (hex) Teseq AG - 94C962 (base 16) Teseq AG - Nordstrasse 11F - Luterbach Solothurn 4542 - SWITZERLAND - - 94-CA-0F (hex) Honeywell Analytics - 94CA0F (base 16) Honeywell Analytics - 2840 2nd Ave SE - Calgary Alberta T2A7X9 - CANADA - - 94-CC-B9 (hex) ARRIS Group, Inc. - 94CCB9 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 94-CD-AC (hex) Creowave Oy - 94CDAC (base 16) Creowave Oy - Lentokatu 2 - Oulunsalo FIN-90460 - FINLAND - - 94-CE-2C (hex) Sony Mobile Communications AB - 94CE2C (base 16) Sony Mobile Communications AB - Nya Vattentornet - - - Lund SE 22188 - SWEDEN - - 94-CE-31 (hex) CTS Limited - 94CE31 (base 16) CTS Limited - 1st district, 23D, 21 - Moscowsky City - Moscow - 142784 - RUSSIAN FEDERATION - - 94-D0-19 (hex) Cydle Corp. - 94D019 (base 16) Cydle Corp. - 1203, KofomoTower, 16-3 , Sunae-Dong, Bundang-Gu - Seongnam-City Gyeonggi-Do 463825 - KOREA, REPUBLIC OF - - 94-D4-17 (hex) GPI KOREA INC. - 94D417 (base 16) GPI KOREA INC. - Daebang Triplaon B-Dong 201 - Jangsan-Dong, Ilsan-Gu - Goyang-Si Kyeonggi-Do 410-704 - KOREA, REPUBLIC OF - - 94-D6-0E (hex) shenzhen yunmao information technologies co., ltd - 94D60E (base 16) shenzhen yunmao information technologies co., ltd - H4-3A, Twelve Oaks Manor, bulong road - shenzhen guanggong 518127 - CHINA - - 94-D7-23 (hex) Shanghai DareGlobal Technologies Co., Ltd - 94D723 (base 16) Shanghai DareGlobal Technologies Co., Ltd - 22F Info-Tech Building - No.1555 Kongjiang Road - Shanghai 200092 - CHINA - - 94-D7-71 (hex) Samsung Electronics Co.,Ltd - 94D771 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 94-D9-3C (hex) ENELPS - 94D93C (base 16) ENELPS - Bul Arsenija Carnojevica 117 - Belgrade 11070 - SERBIA - - 94-DB-49 (hex) SITCORP - 94DB49 (base 16) SITCORP - 7 RUE CADET - PARIS 75015 - FRANCE - - 94-DB-C9 (hex) Azurewave - 94DBC9 (base 16) Azurewave - 8F No94 Baozhong Rd - XindianDistrict, New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - 94-DD-3F (hex) A+V Link Technologies, Corp. - 94DD3F (base 16) A+V Link Technologies, Corp. - 5F., No.550, Xianzheng 2nd Rd. - Zhubei City Hsinchu Country 30268 - TAIWAN, PROVINCE OF CHINA - - 94-DE-0E (hex) SmartOptics AS - 94DE0E (base 16) SmartOptics AS - Stalfjaera 9 - Oslo N-0975 - NORWAY - - 94-DE-80 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - 94DE80 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - 94-DF-4E (hex) Wistron InfoComm(Kunshan)Co.,Ltd. - 94DF4E (base 16) Wistron InfoComm(Kunshan)Co.,Ltd. - 168# First Avence,Kunshan Export Processing Zone ,China - Kunsha JiangSu 215300 - CHINA - - 94-DF-58 (hex) IJ Electron CO.,Ltd. - 94DF58 (base 16) IJ Electron CO.,Ltd. - 401 ACE HIGHEND8, 345-4 GASAN-DONG - KEUMCHEON-GU - SEOUL 153-802 - KOREA, REPUBLIC OF - - 94-E0-D0 (hex) HealthStream Taiwan Inc. - 94E0D0 (base 16) HealthStream Taiwan Inc. - 16-3, Zichiang 1st Road - Jhongli, Taoyuan county 32063 - TAIWAN, PROVINCE OF CHINA - - 94-E2-26 (hex) D. ORtiz Consulting, LLC - 94E226 (base 16) D. ORtiz Consulting, LLC - 22601 N. 17th Avenue Suite 270 - Phoenix AZ 85027 - UNITED STATES - - 94-E2-FD (hex) Boge Kompressoren Otto Boge GmbH & Co. KG - 94E2FD (base 16) Boge Kompressoren Otto Boge GmbH & Co. KG - Otto Boge Str. 1-7 - Bielefeld Westfalia 33739 - GERMANY - - 94-E7-11 (hex) Xirka Dama Persada PT - 94E711 (base 16) Xirka Dama Persada PT - Gdg CM - Jln Matraman I No 9 - Jakarta 13150 - INDONESIA - - 94-E8-48 (hex) FYLDE MICRO LTD - 94E848 (base 16) FYLDE MICRO LTD - 8 AVROE CRESCENT - BLACKPOOL LANCASHIRE FY4 2DP - UNITED KINGDOM - - 94-E9-6A (hex) Apple Inc - 94E96A (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 94-E9-8C (hex) Alcatel-Lucent - 94E98C (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 94-EB-2C (hex) Google Inc. - 94EB2C (base 16) Google Inc. - 1600 Amphitheatre Parkway - Mountain View California 94043 - UNITED STATES - - 94-EB-CD (hex) Research In Motion Limited - 94EBCD (base 16) Research In Motion Limited - 295 Phillip Street - Waterloo Ontario N2L3W8 - CANADA - - 94-F1-9E (hex) HUIZHOU MAORONG INTELLIGENT TECHNOLOGY CO.,LTD - 94F19E (base 16) HUIZHOU MAORONG INTELLIGENT TECHNOLOGY CO.,LTD - China Guangdong Huizhou - Huizhou Guangdong 516000 - CHINA - - 94-F6-65 (hex) Ruckus Wireless - 94F665 (base 16) Ruckus Wireless - 350 West Maude Ave - sunnyvale CA 94089 - UNITED STATES - - 94-F6-92 (hex) Geminico co.,Ltd. - 94F692 (base 16) Geminico co.,Ltd. - #102-1112, Chunui-Technopark, 200-1, - Chunui-dong, Wonmi-gu - Bucheon-city Kyunggi-do 420-857 - KOREA, REPUBLIC OF - - 94-F7-20 (hex) Tianjin Deviser Electronics Instrument Co., Ltd - 94F720 (base 16) Tianjin Deviser Electronics Instrument Co., Ltd - No.40 Yibin Road,Nankai district, - Tianjin 300113 - CHINA - - 94-FA-E8 (hex) Shenzhen Eycom Technology Co., Ltd - 94FAE8 (base 16) Shenzhen Eycom Technology Co., Ltd - EYANG Building, No. 3 of Qimin Rd, Langshan 2nd Street, North Area of Hi-Tech Industrial Zone, Nanshan District - Shenzhen Guang Dong 518057 - CHINA - - 94-FB-B2 (hex) Shenzhen Gongjin Electronics Co.,Ltd - 94FBB2 (base 16) Shenzhen Gongjin Electronics Co.,Ltd - No.1, Songgang Avenue, Songgang Street, Bao’an District - Shenzhen Guangdong 518105 - CHINA - - 94-FD-1D (hex) WhereWhen Corp - 94FD1D (base 16) WhereWhen Corp - 96A Flynn Avenue - Mountain View California 94043 - UNITED STATES - - 94-FD-2E (hex) Shanghai Uniscope Technologies Co.,Ltd - 94FD2E (base 16) Shanghai Uniscope Technologies Co.,Ltd - 5th Floor, Building 10, - No 99 Tianzhou Rd - Shanghai 200233 - CHINA - - 94-FE-F4 (hex) SAGEMCOM - 94FEF4 (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON 92848 - FRANCE - - 98-02-84 (hex) Theobroma Systems GmbH - 980284 (base 16) Theobroma Systems GmbH - Gutheil-Schoder Gasse 17 - Wien 1230 - AUSTRIA - - 98-02-D8 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - 9802D8 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - 98-03-A0 (hex) ABB n.v. Power Quality Products - 9803A0 (base 16) ABB n.v. Power Quality Products - 10 allée centrale - Jumet 6040 - BELGIUM - - 98-03-D8 (hex) Apple - 9803D8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 98-0C-82 (hex) Samsung Electro Mechanics - 980C82 (base 16) Samsung Electro Mechanics - Metan Dong 314, Youngtong Gu - Suwon Kyung-gi Do. 443-743 - KOREA, REPUBLIC OF - - 98-0D-2E (hex) HTC Corporation - 980D2E (base 16) HTC Corporation - No. 23, Xinghua Rd., - Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - 98-0E-E4 (hex) PRIVATE - 980EE4 (base 16) - - 98-10-94 (hex) Shenzhen Vsun communication technology Co.,ltd - 981094 (base 16) Shenzhen Vsun communication technology Co.,ltd - Room 1903, Block A, - Xiangnian plaza,NO.4060 - Shenzhen Guangdong 518000 - CHINA - - 98-16-EC (hex) IC Intracom - 9816EC (base 16) IC Intracom - 550 Commerce Blvd - Oldsmar Florida 34677 - UNITED STATES - - 98-1D-FA (hex) Samsung Electronics Co.,Ltd - 981DFA (base 16) Samsung Electronics Co.,Ltd - 129, Samsung-ro, Youngtongl-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - 98-20-8E (hex) Definium Technologies - 98208E (base 16) Definium Technologies - 34 Fairthorne Road - Trevallyn - Launceston Tasmania 7250 - AUSTRALIA - - 98-26-2A (hex) Applied Research Associates, Inc - 98262A (base 16) Applied Research Associates, Inc - 4300 San Mateo Boulevard NE - Suite a-220 - Albuquerque NM 87110 - UNITED STATES - - 98-29-1D (hex) Jaguar de Mexico, SA de CV - 98291D (base 16) Jaguar de Mexico, SA de CV - Calle Tabla Grande No.2 - Espiritu Santo - Jilotzongo Estado de Mexico 54570 - MEXICO - - 98-29-3F (hex) Fujian Start Computer Equipment Co.,Ltd - 98293F (base 16) Fujian Start Computer Equipment Co.,Ltd - No.68 Hongshangyuan Road, - Fuzhou City, Fujian Province, 350002 - CHINA - - 98-2C-BE (hex) 2Wire - 982CBE (base 16) 2Wire - 1764 Automation Pkwy - San Jose CA 95131 - UNITED STATES - - 98-2D-56 (hex) Resolution Audio - 982D56 (base 16) Resolution Audio - 88 Hoff Street #106 - San Francisco CA 94110 - UNITED STATES - - 98-2F-3C (hex) Sichuan Changhong Electric Ltd. - 982F3C (base 16) Sichuan Changhong Electric Ltd. - 35 East Mianxing Road,High-Tech Park, - MianYang SiChuan 621000 - CHINA - - 98-30-00 (hex) Beijing KEMACOM Technologies Co., Ltd. - 983000 (base 16) Beijing KEMACOM Technologies Co., Ltd. - Room 208, Building 6, No.50, Xi San Huan Bei Road - Haidian District, - Beijing 100044 - CHINA - - 98-30-71 (hex) DAIKYUNG VASCOM - 983071 (base 16) DAIKYUNG VASCOM - DAIKYUNG Bldg.#1164-15,Gaepo-dong - Gangnam-gu Seoul 135-960 - KOREA, REPUBLIC OF - - 98-34-9D (hex) Krauss Maffei Technologies GmbH - 98349D (base 16) Krauss Maffei Technologies GmbH - Krauss-Mafffei-Str. 2 - Munich 80997 - GERMANY - - 98-35-71 (hex) Sub10 Systems Ltd - 983571 (base 16) Sub10 Systems Ltd - Ash House - Canal Way - Kingsteignton Devon TQ12 3RZ - UNITED KINGDOM - - 98-35-B8 (hex) Assembled Products Corporation - 9835B8 (base 16) Assembled Products Corporation - 115 E. Linden - Rogers Arkansas 72756 - UNITED STATES - - 98-37-13 (hex) PT.Navicom Indonesia - 983713 (base 16) PT.Navicom Indonesia - Perkantoran Citragrand Blok CW7 no 10 - Jl.Raya Alternatif Cibubur Km.4 - Bekasi Jawa Barat 17435 - INDONESIA - - 98-3B-16 (hex) AMPAK Technology Inc - 983B16 (base 16) AMPAK Technology Inc - No.1,Jen Ai Road - Hsinchu Industrial Park,Hukou - Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - 98-3F-9F (hex) China SSJ (Suzhou) Network Technology Inc. - 983F9F (base 16) China SSJ (Suzhou) Network Technology Inc. - 399 Linquan St., Dongnan Building 411 - Suzhou Industrial Park - Suzhou Jiangsu 215123 - CHINA - - 98-42-46 (hex) SOL INDUSTRY PTE., LTD - 984246 (base 16) SOL INDUSTRY PTE., LTD - 1 NORTH BRIDGE RD., - #24-05, HIGH STREET CENTRE, - 179094 - SINGAPORE - - 98-43-DA (hex) INTERTECH - 9843DA (base 16) INTERTECH - 3F. 14-9 Sarihyun-Ro. Ilsandong-Gu - Goyang-Si Gyeonggi-Do 410-821 - KOREA, REPUBLIC OF - - 98-47-3C (hex) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD - 98473C (base 16) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD - Suite 604-605,Xing Yuan Technology Plaza - 418 Gui Ping Road - Shanghai 200233 - CHINA - - 98-4A-47 (hex) CHG Hospital Beds - 984A47 (base 16) CHG Hospital Beds - 1020 Adelaide St S - London ON N6E 1R6 - CANADA - - 98-4B-4A (hex) ARRIS Group, Inc. - 984B4A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - 98-4B-E1 (hex) Hewlett-Packard Company - 984BE1 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 98-4C-04 (hex) Zhangzhou Keneng Electrical Equipment Co Ltd - 984C04 (base 16) Zhangzhou Keneng Electrical Equipment Co Ltd - Keneng Technology Park,No.12 Wuqiao Zhong Rd - Lantian Economic Development Zone - Zhangzhou Fujian 363005 - CHINA - - 98-4C-D3 (hex) Mantis Deposition - 984CD3 (base 16) Mantis Deposition - 2 Goodson Industrial Mews - Wellington Street - Thame Oxfordshire OX9 3BX - UNITED KINGDOM - - 98-4E-97 (hex) Starlight Marketing (H. K.) Ltd. - 984E97 (base 16) Starlight Marketing (H. K.) Ltd. - 5/F., Shing Dao Industrial Building, - 232 Aberdeen Main Road - HONG KONG - - 98-4F-EE (hex) Intel Corporate - 984FEE (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 98-52-B1 (hex) Samsung Electronics - 9852B1 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 98-57-D3 (hex) HON HAI-CCPBG PRECISION IND.CO.,LTD. - 9857D3 (base 16) HON HAI-CCPBG PRECISION IND.CO.,LTD. - 5F, No.9,Li-Hsin Road V,Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 98-58-8A (hex) SYSGRATION Ltd. - 98588A (base 16) SYSGRATION Ltd. - 10Fl.NO.868-3.Chung Cheng Rd. - Chung Ho District, - NewTaipei City 235 - TAIWAN, PROVINCE OF CHINA - - 98-59-45 (hex) Texas Instruments - 985945 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - 98-5A-EB (hex) Apple, Inc. - 985AEB (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 98-5C-93 (hex) SBG Systems SAS - 985C93 (base 16) SBG Systems SAS - 3bis, chemin de la Jonchere - Rueil Malmaison Ile de France 92500 - FRANCE - - 98-5D-46 (hex) PeopleNet Communication - 985D46 (base 16) PeopleNet Communication - 4400 Baker Road - Minnetonka Minnesota 55343 - UNITED STATES - - 98-5E-1B (hex) ConversDigital Co., Ltd. - 985E1B (base 16) ConversDigital Co., Ltd. - 5308 5th Bldg., Dong Seoul Univ. - Bokjeong-dong, Sujeong-gu - Seongnam Gyeonggi 461714 - KOREA, REPUBLIC OF - - 98-60-22 (hex) EMW Co., Ltd. - 986022 (base 16) EMW Co., Ltd. - 80B-4L, 680-3 Gojan-Dong - Namdong-Gu - Incheon 405-819 - KOREA, REPUBLIC OF - - 98-66-EA (hex) Industrial Control Communications, Inc. - 9866EA (base 16) Industrial Control Communications, Inc. - 1600 Aspen Commons - Suite 210 - Middleton WI 53562 - UNITED STATES - - 98-6B-3D (hex) ARRIS Group, Inc. - 986B3D (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - 98-6C-F5 (hex) zte corporation - 986CF5 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - 98-6D-C8 (hex) TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION - 986DC8 (base 16) TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION - MITA 43MT BLDG. - 13-16MITA 3-CHOME,MINATO-KU - TOKYO JAPAN 108-0073 - JAPAN - - 98-73-C4 (hex) Sage Electronic Engineering LLC - 9873C4 (base 16) Sage Electronic Engineering LLC - 201 Terry St. - Suite 1A - Longmont CO 80501 - UNITED STATES - - 98-76-B6 (hex) Adafruit - 9876B6 (base 16) Adafruit - 150 Varick st - 3rd floor - New York NY 10013 - UNITED STATES - - 98-77-70 (hex) Pep Digital Technology (Guangzhou) Co., Ltd - 987770 (base 16) Pep Digital Technology (Guangzhou) Co., Ltd - 23F, Yinhui Building, No.117 Longyi Road, - Tianhe District, - Guangdong Province 510635 - CHINA - - 98-7B-F3 (hex) Texas Instruments - 987BF3 (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - 98-7E-46 (hex) Emizon Networks Limited - 987E46 (base 16) Emizon Networks Limited - 1 Allerton Road - Park Place - Rugby Warwickshire CV23 0PA - UNITED KINGDOM - - 98-82-17 (hex) Disruptive Ltd - 988217 (base 16) Disruptive Ltd - Windsor House - Turnpike Road - High Wycombe Buckinghamshire HP12 3NR - UNITED KINGDOM - - 98-83-89 (hex) Samsung Electronics Co.,LTD - 988389 (base 16) Samsung Electronics Co.,LTD - 129,Samsung-ro, Yeongtong-gu - Suwon Gyeonggi-Do 443-742 - KOREA, REPUBLIC OF - - 98-86-B1 (hex) Flyaudio corporation (China) - 9886B1 (base 16) Flyaudio corporation (China) - No.16 Mingzhu RD Economic&Technology - Development zone Guangzhou,China - Guangzhou Guangdong Province 510730 - CHINA - - 98-89-ED (hex) Anadem Information Inc. - 9889ED (base 16) Anadem Information Inc. - 2nd F, 79 Zhouzi Street, Neihu District, - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - 98-8B-5D (hex) SAGEM COMMUNICATION - 988B5D (base 16) SAGEM COMMUNICATION - 250 route de l'Empereur - Rueil Malmaison 92848 - FRANCE - - 98-8B-AD (hex) Corintech Ltd. - 988BAD (base 16) Corintech Ltd. - Ashford Mill - Station Road - Fordingbridge Hampshire SP6 1DZ - UNITED KINGDOM - - 98-8E-34 (hex) ZHEJIANG BOXSAM ELECTRONIC CO.,LTD - 988E34 (base 16) ZHEJIANG BOXSAM ELECTRONIC CO.,LTD - No.288,LONGTAN ROAD, - JINHUA CITY ZHEJIANG PROVINCE, 321017 - CHINA - - 98-8E-4A (hex) NOXUS(BEIJING) TECHNOLOGY CO.,LTD - 988E4A (base 16) NOXUS(BEIJING) TECHNOLOGY CO.,LTD - 02-1205,11/F, No.2 Building,No.8,Worker’s Stadium North Road Chaoyang District - Beijing 100027 - CHINA - - 98-8E-DD (hex) TE Connectivity Limerick - 988EDD (base 16) TE Connectivity Limerick - International Science Centre, Block 1 - Univeristy of Limerick (NTP) - Castletroy Co. Limerick - IRELAND - - 98-90-80 (hex) Linkpower Network System Inc Ltd. - 989080 (base 16) Linkpower Network System Inc Ltd. - Room 202, Build 18, Shahe Industrial Zone - Baishizhou, Nanshan District - Shenzhen Guangdong 518053 - CHINA - - 98-90-96 (hex) Dell Inc - 989096 (base 16) Dell Inc - One Dell Way - Round Rock TX 78682 - UNITED STATES - - 98-93-CC (hex) LG Electronics Inc. - 9893CC (base 16) LG Electronics Inc. - 19-1, Cheongho-ri, Jinwi-myeon - Pyeongtaek-si, Gyeonggi-do, Korea - Pyeongtaek-si Gyeonggi-do 451-713 - KOREA, REPUBLIC OF - - 98-94-49 (hex) Skyworth Wireless Technology Ltd. - 989449 (base 16) Skyworth Wireless Technology Ltd. - Unit A Rm.3A01, Skyworth Bldg., Gaoxin Ave. 1.S., - Nanshan District Shenzhen 518057 - CHINA - - 98-A7-B0 (hex) MCST ZAO - 98A7B0 (base 16) MCST ZAO - 35/50, Nizhnyaya Krasnoselskaya St., - Moscow 105666 - RUSSIAN FEDERATION - - 98-AA-D7 (hex) BLUE WAVE NETWORKING CO LTD - 98AAD7 (base 16) BLUE WAVE NETWORKING CO LTD - No. 20, Lane 68, Da-feng RD, - NEW TAIPEI TAIPEI 23121 - TAIWAN, PROVINCE OF CHINA - - 98-B0-39 (hex) Alcatel-Lucent - 98B039 (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - 98-B8-E3 (hex) Apple - 98B8E3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 98-BC-57 (hex) SVA TECHNOLOGIES CO.LTD - 98BC57 (base 16) SVA TECHNOLOGIES CO.LTD - 5F No.192 Tinglin Road, - SHANGHAI 200233 - CHINA - - 98-BC-99 (hex) Edeltech Co.,Ltd. - 98BC99 (base 16) Edeltech Co.,Ltd. - #302 Jamae Bldg, 1010-28, Sadang-dong, Dongjak=gu - Seoul 156-824 - KOREA, REPUBLIC OF - - 98-BE-94 (hex) IBM - 98BE94 (base 16) IBM - 3039 E Cornwallis Rd - Research Triangle Park NC 27709 - UNITED STATES - - 98-C0-EB (hex) Global Regency Ltd - 98C0EB (base 16) Global Regency Ltd - 20F, Phase A, Wenjin Plaza, - Tianbei Rd. 1, Luohu Dist. - Shen Zhen Guangdong 518000 - CHINA - - 98-C8-45 (hex) PacketAccess - 98C845 (base 16) PacketAccess - 611 North Main Street - Goldfield IA 50543 - UNITED STATES - - 98-CD-B4 (hex) Virident Systems, Inc. - 98CDB4 (base 16) Virident Systems, Inc. - 500 Yosemite Dr. - Suite 108 - Milpitas CA 95035 - UNITED STATES - - 98-D3-31 (hex) Shenzhen Bolutek Technology Co.,Ltd. - 98D331 (base 16) Shenzhen Bolutek Technology Co.,Ltd. - Building B, District A, Internet industry base, Baoan - Shenzhen Guangdong 518000 - CHINA - - 98-D6-86 (hex) Chyi Lee industry Co., ltd. - 98D686 (base 16) Chyi Lee industry Co., ltd. - No.25, Wufu Rd., Xinying Dist. - Tainan city 73054 - TAIWAN, PROVINCE OF CHINA - - 98-D6-BB (hex) Apple - 98D6BB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 98-D6-F7 (hex) LG Electronics - 98D6F7 (base 16) LG Electronics - 60-39, Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - 98-D8-8C (hex) Nortel Networks - 98D88C (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - 98-DA-92 (hex) Vuzix Corporation - 98DA92 (base 16) Vuzix Corporation - 2166 Brighton Henrietta Town Line Road - Rochester NY 14623 - UNITED STATES - - 98-DC-D9 (hex) UNITEC Co., Ltd. - 98DCD9 (base 16) UNITEC Co., Ltd. - 1-2-1-Shinyokohama - Kohoku-ku - Yokohama-shi Kanagawa 222-0033 - JAPAN - - 98-E0-D9 (hex) Apple - 98E0D9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 98-E1-65 (hex) Accutome - 98E165 (base 16) Accutome - 3222 Phoenixville Pike - Malvern PA 19355 - UNITED STATES - - 98-E7-9A (hex) Foxconn(NanJing) Communication Co.,Ltd. - 98E79A (base 16) Foxconn(NanJing) Communication Co.,Ltd. - A-2FMinfang Building No.189 Guangzhou Rd - Nanjing Jiang su 210029 - CHINA - - 98-EC-65 (hex) Cosesy ApS - 98EC65 (base 16) Cosesy ApS - Tyttebaervej 2 - Ans Jylland DK-8643 - DENMARK - - 98-EE-CB (hex) Wistron InfoComm(ZhongShan)Corporation - 98EECB (base 16) Wistron InfoComm(ZhongShan)Corporation - No.38,East Keji Road,Zhongshan Torch Development Zone,Zhongshan City,Guangdong,China - Zhongshan Guangdong 528437 - CHINA - - 98-F0-AB (hex) Apple - 98F0AB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 98-F1-70 (hex) Murata Manufacturing Co., Ltd. - 98F170 (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - 98-F5-37 (hex) zte corporation - 98F537 (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road, - shenzhen guangdong 518057 - CHINA - - 98-F5-A9 (hex) OHSUNG ELECTRONICS CO.,LTD. - 98F5A9 (base 16) OHSUNG ELECTRONICS CO.,LTD. - 181 - GONGDAN-DONG - GUMI KYUNGBUK 730-030 - KOREA, REPUBLIC OF - - 98-F8-C1 (hex) IDT Technology Limited - 98F8C1 (base 16) IDT Technology Limited - Block C, 9/F.,Kaiser Estate, Phase 1, - 41 Man Yue Street, Hunghom - Kowloon Hong Kong - HONG KONG - - 98-F8-DB (hex) Marini Impianti Industriali s.r.l. - 98F8DB (base 16) Marini Impianti Industriali s.r.l. - Via delle Province, 6A - (Zona Artigianale) - Cisterna di Latina 04012 - ITALY - - 98-FA-E3 (hex) Xiaomi inc. - 98FAE3 (base 16) Xiaomi inc. - Office Building,The Rainbow City of China Resources, NO.68,Qinghe Middle Street,Haidian District,Beijing,China,100085 - Beijing Beijing 100085 - CHINA - - 98-FB-12 (hex) Grand Electronics (HK) Ltd - 98FB12 (base 16) Grand Electronics (HK) Ltd - Flat/Room 1120, 11/F Beverley Commercial Centre - 87-105 Chatham Road, South TST, KL - 999077 - HONG KONG - - 98-FC-11 (hex) Cisco-Linksys, LLC - 98FC11 (base 16) Cisco-Linksys, LLC - 131 Theroy Drive - Irvine California 92612 - UNITED STATES - - 98-FE-03 (hex) Ericsson - North America - 98FE03 (base 16) Ericsson - North America - 6300 Legacy Drive - Plano TX 75024 - UNITED STATES - - 98-FE-94 (hex) Apple - 98FE94 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 98-FF-6A (hex) OTEC(Shanghai)Technology Co.,Ltd. - 98FF6A (base 16) OTEC(Shanghai)Technology Co.,Ltd. - 13th Floor,Building 2 - No.100 Qinzhou Rd, - Shanghai 200235 - CHINA - - 98-FF-D0 (hex) Lenovo Mobile Communication Technology Ltd. - 98FFD0 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road - Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone, - Xiamen Fujian 361006 - CHINA - - 9C-01-11 (hex) Shenzhen Newabel Electronic Co., Ltd. - 9C0111 (base 16) Shenzhen Newabel Electronic Co., Ltd. - 5Flr, South Tower of Sichuan Bld., - No.2001 Hongli Rd., Futian District - Shenzhen Guangdong 518028 - CHINA - - 9C-02-98 (hex) Samsung Electronics Co.,Ltd - 9C0298 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 9C-03-9E (hex) Beijing Winchannel Software Technology Co., Ltd - 9C039E (base 16) Beijing Winchannel Software Technology Co., Ltd - 8F, Block E, Dazhongsi Zhongkun Plaza No. A - 18 West Beisanhuan Road - Haidian District BEIJING 100089 - CHINA - - 9C-04-73 (hex) Tecmobile (International) Ltd. - 9C0473 (base 16) Tecmobile (International) Ltd. - Unit L, Braintree Industrial Estate, - Braintree Road - South Ruislip HA4 0EJ - UNITED KINGDOM - - 9C-04-EB (hex) Apple - 9C04EB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 9C-06-6E (hex) Hytera Communications Corporation Limited - 9C066E (base 16) Hytera Communications Corporation Limited - Hytera Tower, Hi-Tech Industrial Park North, Nanshan District - Shenzhen Guangdong 518057 - CHINA - - 9C-0D-AC (hex) Tymphany HK Limited - 9C0DAC (base 16) Tymphany HK Limited - RM 1307-8 - Dominion Centre - 43-59, Queen's Road East Wanchai - HONG KONG - - 9C-14-65 (hex) Edata Elektronik San. ve Tic. A.Åž. - 9C1465 (base 16) Edata Elektronik San. ve Tic. A.Åž. - Tantavi Mahallesi MenteÅŸoÄŸlu Cad. - Terra Plaza No:25 Ümraniye - İstanbul - 34764 - TURKEY - - 9C-18-74 (hex) Nokia Danmark A/S - 9C1874 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - 9C-1C-12 (hex) Aruba Networks - 9C1C12 (base 16) Aruba Networks - 1344 Crossman Ave - Sunnyvale CA 94089 - UNITED STATES - - 9C-1F-DD (hex) Accupix Inc. - 9C1FDD (base 16) Accupix Inc. - 3F Gaeyang BLDG, 548-1, - Anyang 8-Dong, Manan-Gu, - Anyang Kyeonggi-Do 430-730 - KOREA, REPUBLIC OF - - 9C-20-7B (hex) Apple - 9C207B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 9C-21-6A (hex) TP-LINK TECHNOLOGIES CO.,LTD. - 9C216A (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4)Central Science and Technology Park - Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - 9C-22-0E (hex) TASCAN Service GmbH - 9C220E (base 16) TASCAN Service GmbH - Max-Planck-Str. 38 - Cologne NRW 50858 - GERMANY - - 9C-28-40 (hex) Discovery Technology,LTD.. - 9C2840 (base 16) Discovery Technology,LTD.. - 5th floor Building 2,Block A,Internet industrial park, - Baoyuan road,Xixiang,Baoan district,Shenzhen,PRC - Shenzhen Guangzhou 518100 - CHINA - - 9C-28-BF (hex) Continental Automotive Czech Republic s.r.o. - 9C28BF (base 16) Continental Automotive Czech Republic s.r.o. - Průmyslová 1851 - Brandýs nad Labem 250 01 - CZECH REPUBLIC - - 9C-28-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD - 9C28EF (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - 9C-2A-70 (hex) Hon Hai Precision Ind. Co.,Ltd. - 9C2A70 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - 9C-30-66 (hex) RWE Effizienz GmbH - 9C3066 (base 16) RWE Effizienz GmbH - Flamingoweg 1 - Dortmund NRW 44139 - GERMANY - - 9C-31-78 (hex) Foshan Huadian Intelligent Communications Teachnologies Co.,Ltd - 9C3178 (base 16) Foshan Huadian Intelligent Communications Teachnologies Co.,Ltd - Building B,No.8 of Shishan Industrial Avenue - Nanhai National New and hi-tech Industrial Park - Foshan Guangdong 528225 - CHINA - - 9C-31-B6 (hex) Kulite Semiconductor Products Inc - 9C31B6 (base 16) Kulite Semiconductor Products Inc - 1 Willow Tree Rd - Leonia NJ 07605 - UNITED STATES - - 9C-35-83 (hex) Nipro Diagnostics, Inc - 9C3583 (base 16) Nipro Diagnostics, Inc - 2400 N.W. 55th Court. - Ft. Lauderdale FL 33309 - UNITED STATES - - 9C-35-EB (hex) Apple, Inc. - 9C35EB (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 9C-37-F4 (hex) HUAWEI TECHNOLOGIES CO.,LTD - 9C37F4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - 9C-3A-AF (hex) Samsung Electronics Co.,Ltd - 9C3AAF (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 9C-3E-AA (hex) EnvyLogic Co.,Ltd. - 9C3EAA (base 16) EnvyLogic Co.,Ltd. - #605,Gwanyang Doosan Ven Digm B/D - 250,Hagui-ro,Dongan-gu - Anyang-si Gyeonggi-do 431-810 - KOREA, REPUBLIC OF - - 9C-41-7C (hex) Hame Technology Co., Limited - 9C417C (base 16) Hame Technology Co., Limited - 5F, No. 18 High Tech Middle Avenue One, High Tech Industrial Park, Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - 9C-44-3D (hex) CHENGDU XUGUANG TECHNOLOGY CO, LTD - 9C443D (base 16) CHENGDU XUGUANG TECHNOLOGY CO, LTD - 2ND SECTION,PARK ROAD - LONGQUANYI - CHENGDU SICHUAN 610100 - CHINA - - 9C-44-A6 (hex) SwiftTest, Inc. - 9C44A6 (base 16) SwiftTest, Inc. - 3255 Scott Blvd - Bldg. 2, Suite 120 - Santa Clara California 95054 - UNITED STATES - - 9C-45-63 (hex) DIMEP Sistemas - 9C4563 (base 16) DIMEP Sistemas - Av. MOfarrej, 840 - São Paulo SP 05311000 - BRAZIL - - 9C-4A-7B (hex) Nokia Corporation - 9C4A7B (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - 9C-4C-AE (hex) Mesa Labs - 9C4CAE (base 16) Mesa Labs - 10 Evergreen Dr - Bozeman MT 59715 - UNITED STATES - - 9C-4E-20 (hex) CISCO SYSTEMS, INC. - 9C4E20 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 9C-4E-36 (hex) Intel Corporate - 9C4E36 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - 9C-4E-8E (hex) ALT Systems Ltd - 9C4E8E (base 16) ALT Systems Ltd - PoBox 17 - Helsinki 00761 - FINLAND - - 9C-4E-BF (hex) BoxCast - 9C4EBF (base 16) BoxCast - 14538 Grapeland Ave - Cleveland Ohio 44111 - UNITED STATES - - 9C-53-CD (hex) ENGICAM s.r.l. - 9C53CD (base 16) ENGICAM s.r.l. - Via Dei Pratoni n.16 - Scandicci FIRENZE 50018 - ITALY - - 9C-54-1C (hex) Shenzhen My-power Technology Co.,Ltd - 9C541C (base 16) Shenzhen My-power Technology Co.,Ltd - 202¬Building 3¬Shenzhen Software Park - Technology Middle 2 Rd¬Technology Park North - Shenzhen Nanshan 518000 - CHINA - - 9C-54-CA (hex) Zhengzhou VCOM Science and Technology Co.,Ltd - 9C54CA (base 16) Zhengzhou VCOM Science and Technology Co.,Ltd - National 863 Software Park£¬No.6 Cuizhu Street, Hi-tech Indusry Developing Park - ZhengZhou City Henan Province 450001 - CHINA - - 9C-55-B4 (hex) I.S.E. S.r.l. - 9C55B4 (base 16) I.S.E. S.r.l. - Via della Canapiglia 5 - Migliarino Pisano PISA 56010 - ITALY - - 9C-57-11 (hex) Feitian Xunda(Beijing) Aeronautical Information Technology Co., Ltd. - 9C5711 (base 16) Feitian Xunda(Beijing) Aeronautical Information Technology Co., Ltd. - Building B,Horizon International Tower,No.6 Zhichun Rd,Haidian District, - Beijing 100088 - CHINA - - 9C-5B-96 (hex) NMR Corporation - 9C5B96 (base 16) NMR Corporation - 3F Esprit Build.,1-3-6 Nishi-Nippori - Arakawa-Ku Tokyo 116-0013 - JAPAN - - 9C-5C-8D (hex) FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA - 9C5C8D (base 16) FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA - R: Vicente de Felice, 589 - Jd.Ouro Verde - Limeira São Paulo 13482-075 - BRAZIL - - 9C-5D-12 (hex) Aerohive Networks Inc - 9C5D12 (base 16) Aerohive Networks Inc - 330 Gibraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - 9C-5D-95 (hex) VTC Electronics Corp. - 9C5D95 (base 16) VTC Electronics Corp. - 5F,No.21,Sec.6,Zhongxiao E.Rd.,Nangang District - Taipei 11575 - TAIWAN, PROVINCE OF CHINA - - 9C-5E-73 (hex) Calibre UK Ltd - 9C5E73 (base 16) Calibre UK Ltd - Cornwall House - Cornwall Terrace - Bradford West Yorkshire BD8 7JS - UNITED KINGDOM - - 9C-61-1D (hex) Omni-ID USA, Inc. - 9C611D (base 16) Omni-ID USA, Inc. - 1200 Ridgeway Ave - Rochester NY 14615 - UNITED STATES - - 9C-64-5E (hex) Harman Consumer Group - 9C645E (base 16) Harman Consumer Group - 8500 Balboa Blvd - Northridge CA 91329 - UNITED STATES - - 9C-65-B0 (hex) Samsung Electronics Co.,Ltd - 9C65B0 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 9C-65-F9 (hex) AcSiP Technology Corp. - 9C65F9 (base 16) AcSiP Technology Corp. - 3F-1, No. 207, Fusing Rd. - Taoyuan 33066 - TAIWAN, PROVINCE OF CHINA - - 9C-66-50 (hex) Glodio Technolies Co.,Ltd Tianjin Branch - 9C6650 (base 16) Glodio Technolies Co.,Ltd Tianjin Branch - Room 904, No.1-2 LanYuan Road, HuaYuan Industrial Area - TianJin TianJin 300384 - CHINA - - 9C-68-5B (hex) Octonion SA - 9C685B (base 16) Octonion SA - EPFL Innovation Park, Bâtiment C - Lausanne Vaud 1015 - SWITZERLAND - - 9C-6A-BE (hex) QEES ApS. - 9C6ABE (base 16) QEES ApS. - Naverland 31, 2.tv - Glostrup Hovedstaden 2600 - DENMARK - - 9C-6C-15 (hex) Microsoft Corporation - 9C6C15 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - 9C-75-14 (hex) Wildix srl - 9C7514 (base 16) Wildix srl - loc. Le Basse, 3 - Trento TN 38100 - ITALY - - 9C-77-AA (hex) NADASNV - 9C77AA (base 16) NADASNV - 2203, T-dong, Poonglim I-won Plus - Seohyeon-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-862 - KOREA, REPUBLIC OF - - 9C-79-AC (hex) Suntec Software(Shanghai) Co., Ltd. - 9C79AC (base 16) Suntec Software(Shanghai) Co., Ltd. - 17F New Hualian Mansion - 775 Middle Huaihai Road - Shanghai 200020 - CHINA - - 9C-7B-D2 (hex) NEOLAB Convergence - 9C7BD2 (base 16) NEOLAB Convergence - 4F Yujung bldg., - Seocho-dong, Seocho-gu - Seoul 137-070 - KOREA, REPUBLIC OF - - 9C-80-7D (hex) SYSCABLE Korea Inc. - 9C807D (base 16) SYSCABLE Korea Inc. - 2F KAMA Bldg 1461-15 Secho-3dong Seocho-Gu - Seoul 137-720 - KOREA, REPUBLIC OF - - 9C-80-DF (hex) Arcadyan Technology Corporation - 9C80DF (base 16) Arcadyan Technology Corporation - 4F, No, 9 , Park Avenue II , - Science-based Industrial Park , - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - 9C-86-DA (hex) Phoenix Geophysics Ltd. - 9C86DA (base 16) Phoenix Geophysics Ltd. - 3781 Victoria Park Ave. - Unit 3 - Toronto ON M1W 3K5 - CANADA - - 9C-88-88 (hex) Simac Techniek NV - 9C8888 (base 16) Simac Techniek NV - De Run 1101 - Veldhoven NB 5503LB - NETHERLANDS - - 9C-8B-F1 (hex) The Warehouse Limited - 9C8BF1 (base 16) The Warehouse Limited - Suite 601, City Point, 1600 Zhonghua Road, Huangpu District - Shanghai 200010 - CHINA - - 9C-8D-1A (hex) INTEG process group inc - 9C8D1A (base 16) INTEG process group inc - 2919 E Hardies Rd, First Floor - Gibsonia PA 15044 - UNITED STATES - - 9C-8E-99 (hex) Hewlett-Packard Company - 9C8E99 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 9C-8E-DC (hex) Teracom Limited - 9C8EDC (base 16) Teracom Limited - - Noida Uttar Pradesh 201301 - INDIA - - 9C-93-4E (hex) Xerox Corporation - 9C934E (base 16) Xerox Corporation - Mail Stop 0214 - 7E - 800 Phillips Road - Webster NY 14580 - UNITED STATES - - 9C-93-E4 (hex) PRIVATE - 9C93E4 (base 16) - - 9C-95-F8 (hex) SmartDoor Systems, LLC - 9C95F8 (base 16) SmartDoor Systems, LLC - 5711-A Center Lane - Falls Church Virginia 22041 - UNITED STATES - - 9C-97-26 (hex) Technicolor - 9C9726 (base 16) Technicolor - Prins Boudewijnlaan 47 - Edegem Belgium B-2650 - BELGIUM - - 9C-98-11 (hex) Guangzhou Sunrise Electronics Development Co., Ltd - 9C9811 (base 16) Guangzhou Sunrise Electronics Development Co., Ltd - 12th Floor,368 GuangZhou Avenue South - Guangzhou Guangdong 510300 - CHINA - - 9C-9C-1D (hex) Starkey Labs Inc. - 9C9C1D (base 16) Starkey Labs Inc. - 6600 Washington Ave. S. - Eden Prairie MN 55344 - UNITED STATES - - 9C-A1-0A (hex) SCLE SFE - 9CA10A (base 16) SCLE SFE - Parc des Aygalades – BaÌ‚t 10 - MARSEILLE PACA 13014 - FRANCE - - 9C-A1-34 (hex) Nike, Inc. - 9CA134 (base 16) Nike, Inc. - 1 Bowerman Drive - Beaverton OR 97005 - UNITED STATES - - 9C-A3-BA (hex) SAKURA Internet Inc. - 9CA3BA (base 16) SAKURA Internet Inc. - 7-20-1 Nishi-shinjuku - Shinjuku-ku Tokyo 1600023 - JAPAN - - 9C-A5-77 (hex) Osorno Enterprises Inc. - 9CA577 (base 16) Osorno Enterprises Inc. - 976 Elgin Ave - Winnipeg MB R3E 1B4 - CANADA - - 9C-A9-E4 (hex) zte corporation - 9CA9E4 (base 16) zte corporation - 12/F.,zte R&D building Road - shenzhen guangdong 518057 - CHINA - - 9C-AD-97 (hex) Hon Hai Precision Ind. Co.,Ltd. - 9CAD97 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - ,Xiyong Town,Shapingba District - Chongqing 401332 - CHINA - - 9C-AD-EF (hex) Obihai Technology, Inc. - 9CADEF (base 16) Obihai Technology, Inc. - 2105 S. Bascom Ave #285 - Campbell CA 95008 - UNITED STATES - - 9C-AF-CA (hex) CISCO SYSTEMS, INC. - 9CAFCA (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - 9C-B0-08 (hex) Ubiquitous Computing Technology Corporation - 9CB008 (base 16) Ubiquitous Computing Technology Corporation - 2-20-1 Nishi-Gotanda - Shinagawa-ku Tokyo 1410031 - JAPAN - - 9C-B2-06 (hex) PROCENTEC - 9CB206 (base 16) PROCENTEC - Turfschipper 41 - Wateringen Zuid Holland 2292JC - NETHERLANDS - - 9C-B6-54 (hex) Hewlett Packard - 9CB654 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - 9C-B6-D0 (hex) Rivet Networks - 9CB6D0 (base 16) Rivet Networks - 11940 Jollyville Rd - Suite 105s - Austin TX 78759 - UNITED STATES - - 9C-B7-0D (hex) Liteon Technology Corporation - 9CB70D (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road, ChungHo. - Taipei Hsien 23585 - TAIWAN, PROVINCE OF CHINA - - 9C-B7-93 (hex) Creatcomm Technology Inc. - 9CB793 (base 16) Creatcomm Technology Inc. - Rm 619, Buld A, Modern Plaza - , No. 18 Weiye Road - Kunshan Jiangsu 201203 - CHINA - - 9C-BB-98 (hex) Shen Zhen RND Electronic Co.,LTD - 9CBB98 (base 16) Shen Zhen RND Electronic Co.,LTD - G315,Hua Chuang Da business Certer - ,BaoAn 42 District, - Shen Zhen Guang Dong 518000 - CHINA - - 9C-BD-9D (hex) SkyDisk, Inc. - 9CBD9D (base 16) SkyDisk, Inc. - 2F Tenjin central place, - 1-10-24, Tenjin, Chuo-ku - Fukuoka-shi Fukuoka 810-0001 - JAPAN - - 9C-BE-E0 (hex) Biosoundlab Co., Ltd. - 9CBEE0 (base 16) Biosoundlab Co., Ltd. - (Sangdaewon-dong, Sunil Technopia 907-908ho) - Dunchon-daero 555 - Jungwon-gu Seongnam-si Gyeonggi-do, 462726 - KOREA, REPUBLIC OF - - 9C-C0-77 (hex) PrintCounts, LLC - 9CC077 (base 16) PrintCounts, LLC - 5109 W Lemon St - Tampa FL 33609 - UNITED STATES - - 9C-C0-D2 (hex) Conductix-Wampfler GmbH - 9CC0D2 (base 16) Conductix-Wampfler GmbH - Rheinstrasse 27+33 - D-79576 Weil am Rhein - Baden-Württemberg - GERMANY - - 9C-C1-72 (hex) Huawei Technologies Co., Ltd - 9CC172 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - 9C-C7-A6 (hex) AVM GmbH - 9CC7A6 (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - 9C-C7-D1 (hex) SHARP Corporation - 9CC7D1 (base 16) SHARP Corporation - 22-22,Nagaike-cho - Abeno-ku - Osaka city Osaka prefecture 545-8522 - JAPAN - - 9C-CA-D9 (hex) Nokia Corporation - 9CCAD9 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - 9C-CD-82 (hex) CHENG UEI PRECISION INDUSTRY CO.,LTD - 9CCD82 (base 16) CHENG UEI PRECISION INDUSTRY CO.,LTD - No.18, Chung Shan Rd., Tu-Cheng Industry Park - Tu Cheng City Taipei Hsien 23680 - TAIWAN, PROVINCE OF CHINA - - 9C-D2-1E (hex) Hon Hai Precision Ind. Co.,Ltd. - 9CD21E (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District,Chongqing,China - Chongqing Chongqing 401332 - CHINA - - 9C-D2-4B (hex) zte corporation - 9CD24B (base 16) zte corporation - 12/F.,Zte R&D Building,Kejinan Road, - Shenzhen Guangdong 518057 - CHINA - - 9C-D3-5B (hex) Samsung Electronics Co.,Ltd - 9CD35B (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 9C-D3-6D (hex) NETGEAR INC., - 9CD36D (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - 9C-D6-43 (hex) D-Link International - 9CD643 (base 16) D-Link International - 1 Internal Business Park, #03-12, - The Synergy - 609917 - SINGAPORE - - 9C-D9-17 (hex) Motorola Mobility LLC - 9CD917 (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - 9C-DF-03 (hex) Harman/Becker Automotive Systems GmbH - 9CDF03 (base 16) Harman/Becker Automotive Systems GmbH - Becker-Göring-Straße 16 - Karlsbad Baden-Württemberg 76307 - GERMANY - - 9C-E1-0E (hex) NCTech Ltd - 9CE10E (base 16) NCTech Ltd - 20-22 Braid Road - Morningside - Edinburgh EH10 6AD - UNITED KINGDOM - - 9C-E1-D6 (hex) Junger Audio-Studiotechnik GmbH - 9CE1D6 (base 16) Junger Audio-Studiotechnik GmbH - Justus-von-Liebig-Strasse 7 - 12489 Berlin - GERMANY - - 9C-E2-30 (hex) JULONG CO,.LTD. - 9CE230 (base 16) JULONG CO,.LTD. - 308,QianShanZhong Road, - TieDong District,AnShan - AnShan City LiaoNing Province 114051 - CHINA - - 9C-E6-35 (hex) Nintendo Co., Ltd. - 9CE635 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO KYOTO 601-8501 - JAPAN - - 9C-E6-E7 (hex) Samsung Electronics Co.,Ltd - 9CE6E7 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - 9C-E7-BD (hex) Winduskorea co., Ltd - 9CE7BD (base 16) Winduskorea co., Ltd - RM313, Seoul-Garden Bldg, - 141-1 Gocheok-dong, Guro-ku - Seoul 152-828 - KOREA, REPUBLIC OF - - 9C-EB-E8 (hex) BizLink (Kunshan) Co.,Ltd - 9CEBE8 (base 16) BizLink (Kunshan) Co.,Ltd - No.168,Nanhe Road,Economic & Technological Development Zone, - Kunshan City Jiangsu Province 215300 - CHINA - - 9C-F3-87 (hex) Apple - 9CF387 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 9C-F6-1A (hex) UTC Fire and Security - 9CF61A (base 16) UTC Fire and Security - 2955 Red Hill Ave. - Costa Mesa CA 92626 - UNITED STATES - - 9C-F6-7D (hex) Ricardo Prague, s.r.o. - 9CF67D (base 16) Ricardo Prague, s.r.o. - Thamova 13 - Praha 8 186 00 - CZECH REPUBLIC - - 9C-F8-DB (hex) shenzhen eyunmei technology co,.ltd - 9CF8DB (base 16) shenzhen eyunmei technology co,.ltd - 8/F Yiben Building,No.1063 ChaGuang Road,XiLi Town, - Nanshan District - Shenzhen Guangdong 518055 - CHINA - - 9C-F9-38 (hex) AREVA NP GmbH - 9CF938 (base 16) AREVA NP GmbH - Seligenstaedter Str. 100 - Dept. PTLDV-G - Karlstein Germany 63791 - GERMANY - - 9C-FB-F1 (hex) MESOMATIC GmbH & Co.KG - 9CFBF1 (base 16) MESOMATIC GmbH & Co.KG - Siemensstr. 36 - Kernen i.R. 71394 - GERMANY - - 9C-FC-01 (hex) Apple Inc - 9CFC01 (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - 9C-FF-BE (hex) OTSL Inc. - 9CFFBE (base 16) OTSL Inc. - HANROKU Bldg. 2F, 2-1-2 - Kabuki-Cho - Shinjuku-ku Tokyo 160-0021 - JAPAN - - A0-02-DC (hex) Amazon Technologies Inc. - A002DC (base 16) Amazon Technologies Inc. - P.O Box 8102 - Reno NV 89507 - UNITED STATES - - A0-03-63 (hex) Robert Bosch Healthcare GmbH - A00363 (base 16) Robert Bosch Healthcare GmbH - Stuttgarter Stra - Waiblingen Baden-Württemberg 71332 - GERMANY - - A0-06-27 (hex) NEXPA System - A00627 (base 16) NEXPA System - #105, YBS bldg,227-1 Yongdap-Dong - Seongdong-Gu - Seoul ASI/KR/KS013/SEOUL - KOREA, REPUBLIC OF - - A0-07-98 (hex) Samsung Electronics - A00798 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - UNITED STATES - - A0-07-B6 (hex) Advanced Technical Support, Inc. - A007B6 (base 16) Advanced Technical Support, Inc. - 10 Grassmere Ave - West Hartford CT 06110 - UNITED STATES - - A0-0A-BF (hex) Wieson Technologies Co., Ltd. - A00ABF (base 16) Wieson Technologies Co., Ltd. - 7F, No. 276, Sec. 1, Datong Rd - Xizhi Dist - New Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - A0-0B-BA (hex) SAMSUNG ELECTRO-MECHANICS - A00BBA (base 16) SAMSUNG ELECTRO-MECHANICS - Suwon-Si, Gyeonggi_Do, - Suwon 443-743 - KOREA, REPUBLIC OF - - A0-0C-A1 (hex) SKTB SKiT - A00CA1 (base 16) SKTB SKiT - 239 B. Sadovaya Str. - Saratov Saratov region 410005 - RUSSIAN FEDERATION - - A0-12-90 (hex) Avaya, Inc - A01290 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - A0-12-DB (hex) TABUCHI ELECTRIC CO.,LTD - A012DB (base 16) TABUCHI ELECTRIC CO.,LTD - 4-2-21 - MIYAHARA YODOGAWAKU - OSAKA 532-0003 - JAPAN - - A0-13-3B (hex) HiTi Digital, Inc. - A0133B (base 16) HiTi Digital, Inc. - 9F., No.225, Sec. 3, Beixin Rd., Xindian Dist., - Xindian Dist. New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - A0-13-CB (hex) Fiberhome Telecommunication Technologies Co.,LTD - A013CB (base 16) Fiberhome Telecommunication Technologies Co.,LTD - No.5 DongXin Road - Hongsan District - Wuhan Hubei 430074 - CHINA - - A0-14-3D (hex) PARROT SA - A0143D (base 16) PARROT SA - 174, quai de Jemmapes - PARIS 75010 - FRANCE - - A0-16-5C (hex) Triteka LTD - A0165C (base 16) Triteka LTD - Malha Technology Park - Jerusalem 96951 - ISRAEL - - A0-18-28 (hex) Apple Inc - A01828 (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A0-18-59 (hex) Shenzhen Yidashi Electronics Co Ltd - A01859 (base 16) Shenzhen Yidashi Electronics Co Ltd - Building A10, Fukang Industrial Zone - Fuming Village,Guanlan Town, Bao'An - Shenzhen Guangdong 518110 - CHINA - - A0-19-17 (hex) Bertel S.p.a. - A01917 (base 16) Bertel S.p.a. - Frazione Rimale, Via Emilia Ovest 61 - Fidenza Parma 43036 - ITALY - - A0-1C-05 (hex) NIMAX TELECOM CO.,LTD. - A01C05 (base 16) NIMAX TELECOM CO.,LTD. - 1F. NO.308-7,SEC.1,DATONG RD - XIZHI DIST - NEW TAIPEI CITY 221 - TAIWAN, PROVINCE OF CHINA - - A0-1D-48 (hex) Hewlett Packard - A01D48 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - A0-21-95 (hex) Samsung Electronics Digital Imaging - A02195 (base 16) Samsung Electronics Digital Imaging - #416, Maetan 3-dong - Yeongtong-gu - Suwon-si Gyeonggi-do 443-742 - KOREA, REPUBLIC OF - - A0-21-B7 (hex) NETGEAR - A021B7 (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CA 95134 - UNITED STATES - - A0-23-1B (hex) TeleComp R&D Corp. - A0231B (base 16) TeleComp R&D Corp. - 102 SW Orange Blossom - Lake City Florida 32025 - UNITED STATES - - A0-2B-B8 (hex) Hewlett Packard - A02BB8 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - A0-2E-F3 (hex) United Integrated Services Co., Led. - A02EF3 (base 16) United Integrated Services Co., Led. - 5F No 3 Lane 7 Packao Road Hsintien - Taipei Hsien 23144 - TAIWAN, PROVINCE OF CHINA - - A0-36-9F (hex) Intel Corporate - A0369F (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - A0-36-F0 (hex) Comprehensive Power - A036F0 (base 16) Comprehensive Power - 420 Northboro Road Central - Marlborough MA 01752 - UNITED STATES - - A0-36-FA (hex) Ettus Research LLC - A036FA (base 16) Ettus Research LLC - 1043 N Shoreline Blvd - Suite 100 - Mountain View CA 94043 - UNITED STATES - - A0-3A-75 (hex) PSS Belgium N.V. - A03A75 (base 16) PSS Belgium N.V. - Hoogveld 50 - Dendermonde 9200 - BELGIUM - - A0-3B-1B (hex) Inspire Tech - A03B1B (base 16) Inspire Tech - No.588-10,Zhongzheng Rd.,Xinzhuang Dist - 4F.-5,No.1.Sec. 1,Chongyang Rd., Sanchong Dist - New Taipei 24255 - TAIWAN, PROVINCE OF CHINA - - A0-40-25 (hex) Actioncable, Inc. - A04025 (base 16) Actioncable, Inc. - 998 Westlynn Way - Suite 4 - Cupertino CA 95014 - UNITED STATES - - A0-40-41 (hex) SAMWONFA Co.,Ltd. - A04041 (base 16) SAMWONFA Co.,Ltd. - 470-5, Moonhyun2-Dong - Nam-Gu, - Busan 608-042 - KOREA, REPUBLIC OF - - A0-41-A7 (hex) NL Ministry of Defense - A041A7 (base 16) NL Ministry of Defense - PO Box 10000 - Noord Holland 1780 CA Den Helder - NETHERLANDS - - A0-42-3F (hex) Tyan Computer Corp - A0423F (base 16) Tyan Computer Corp - 3288 Larurelview Court - Fremont CA 94538 - UNITED STATES - - A0-48-1C (hex) Hewlett Packard - A0481C (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - A0-4C-C1 (hex) Helixtech Corp. - A04CC1 (base 16) Helixtech Corp. - 6F Lions bldg., 160-2 Gangnam-daero, - Seocho-gu - Seoul 137-888 - KOREA, REPUBLIC OF - - A0-4E-04 (hex) Nokia Corporation - A04E04 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - A0-4F-D4 (hex) ADB Broadband Italia - A04FD4 (base 16) ADB Broadband Italia - VIALE SARCA 222 - MILANO 20126 - ITALY - - A0-51-C6 (hex) Avaya, Inc - A051C6 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - A0-55-4F (hex) Cisco - A0554F (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - A0-55-DE (hex) Pace plc - A055DE (base 16) Pace plc - Salts Mill - Victoria Road - Bradford West Yorkshire BD18 3LF - UNITED KINGDOM - - A0-56-B2 (hex) Harman/Becker Automotive Systems GmbH - A056B2 (base 16) Harman/Becker Automotive Systems GmbH - Becker-Göring-Straße 16 - Karlsbad Baden-Württemberg 76307 - GERMANY - - A0-59-3A (hex) V.D.S. Video Display Systems srl - A0593A (base 16) V.D.S. Video Display Systems srl - Via Del Pantano 71 - SCANDICCI FI 50018 - ITALY - - A0-5A-A4 (hex) Grand Products Nevada, Inc. - A05AA4 (base 16) Grand Products Nevada, Inc. - 751 Pilot Rd. - Las Vegas Nevada 89119 - UNITED STATES - - A0-5B-21 (hex) ENVINET GmbH - A05B21 (base 16) ENVINET GmbH - Hans-Pinsel-Str. 4 - Haar 85540 - GERMANY - - A0-5D-C1 (hex) TMCT Co., LTD. - A05DC1 (base 16) TMCT Co., LTD. - 5F-561, #19-11 SanChong Rd. - NanGang District. - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - A0-5D-E7 (hex) DIRECTV, Inc. - A05DE7 (base 16) DIRECTV, Inc. - 2230 E. Imperial Hwy - El Segundo CA 90245 - UNITED STATES - - A0-5E-6B (hex) MELPER Co., Ltd. - A05E6B (base 16) MELPER Co., Ltd. - 207, 2nd FL.,Wonhyo Bldg.,1365-22 - Seocho-dong, Seocho-gu - SEOUL 137-863 - KOREA, REPUBLIC OF - - A0-63-91 (hex) Netgear Inc. - A06391 (base 16) Netgear Inc. - 350 East Plumeria Drive - San Jose CA 95134 - UNITED STATES - - A0-65-18 (hex) VNPT TECHNOLOGY - A06518 (base 16) VNPT TECHNOLOGY - HoaLac Hi-Tech Park - HANOI 10000 - VIET NAM - - A0-67-BE (hex) Sicon s.r.l. - A067BE (base 16) Sicon s.r.l. - Via Sila, 1/3 - Isola Vicentina Vicenza 36033 - ITALY - - A0-69-86 (hex) Wellav Technologies Ltd - A06986 (base 16) Wellav Technologies Ltd - 15F Desay Building - No.12 Yunshan West Ave. - Huizhou Guangdong 516003 - CHINA - - A0-6A-00 (hex) Verilink Corporation - A06A00 (base 16) Verilink Corporation - 127 Jetplex Circle - Madison AL 35758 - UNITED STATES - - A0-6C-EC (hex) RIM - A06CEC (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 5R9 - CANADA - - A0-6D-09 (hex) Intelcan Technosystems Inc. - A06D09 (base 16) Intelcan Technosystems Inc. - 5490 Boul Thimens - Suite 250 - Saint-Laurent Quebec H4R2K9 - CANADA - - A0-6E-50 (hex) Nanotek Elektronik Sistemler Ltd. Sti. - A06E50 (base 16) Nanotek Elektronik Sistemler Ltd. Sti. - Ivedik Organize Sanayi - 559. Sokak, No:56, Yenimahalle - Ankara 06370 - TURKEY - - A0-71-A9 (hex) Nokia Corporation - A071A9 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - A0-73-32 (hex) Cashmaster International Limited - A07332 (base 16) Cashmaster International Limited - Fairykirk Road - Rosyth Fife KY11 2QQ - UNITED KINGDOM - - A0-73-FC (hex) Rancore Technologies Private Limited - A073FC (base 16) Rancore Technologies Private Limited - 5th Floor, Court House - Lokmanya Tilak Marg - Dhobi Talao Maharashtra 400 002 - INDIA - - A0-75-91 (hex) Samsung Electronics Co.,Ltd - A07591 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A0-77-71 (hex) Vialis BV - A07771 (base 16) Vialis BV - Loodsboot 15 - 3991 CJ - HOUTEN Utrecht 3991 CJ - NETHERLANDS - - A0-78-BA (hex) Pantech Co., Ltd. - A078BA (base 16) Pantech Co., Ltd. - 110-1 Ongjeong-Ri, Tongjin-Eup - Gimpo-Si Gyounggi-Do 415-865 - KOREA, REPUBLIC OF - - A0-82-1F (hex) Samsung Electronics Co.,Ltd - A0821F (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A0-82-C7 (hex) P.T.I Co.,LTD - A082C7 (base 16) P.T.I Co.,LTD - 1-5-1,Tsurumidan - Koriyama-shi Fukushima 963-8861 - JAPAN - - A0-86-1D (hex) Chengdu Fuhuaxin Technology co.,Ltd - A0861D (base 16) Chengdu Fuhuaxin Technology co.,Ltd - Room 1608,Building G1,No.1800 of Yizhou Ave - Hightech Zone - Chengdu Sichuan 610041 - CHINA - - A0-86-C6 (hex) XIAOMI INC - A086C6 (base 16) XIAOMI INC - The Rainbow city of China Resource,NO.68,Qinghe Middle street,Haidian District,Beijing,Chian. - Beijing Beijing 100085 - CHINA - - A0-86-EC (hex) SAEHAN HITEC Co., Ltd - A086EC (base 16) SAEHAN HITEC Co., Ltd - 16-3, Yongsu-ri, Chowol-eup - Gwangju-si, Gyeonggi-do 464-865 - KOREA, REPUBLIC OF - - A0-88-69 (hex) Intel Corporate - A08869 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - A0-88-B4 (hex) Intel Corporate - A088B4 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - A0-89-E4 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd - A089E4 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd - 7F,Block A,Skyworth Building, - Gaoxin AVE.1.S,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - A0-8A-87 (hex) HuiZhou KaiYue Electronic Co.,Ltd - A08A87 (base 16) HuiZhou KaiYue Electronic Co.,Ltd - 3#,Ruttang 2nd area,Tongcheng Avenue - Shuikuo - Huizhou Guangdong 516005 - CHINA - - A0-8C-15 (hex) Gerhard D. Wempe KG - A08C15 (base 16) Gerhard D. Wempe KG - Steinstrasse 23 - Hamburg 20095 - GERMANY - - A0-8C-9B (hex) Xtreme Technologies Corp - A08C9B (base 16) Xtreme Technologies Corp - 200 4616 Valiant Dr NW - Calgary AB T3A0X9 - CANADA - - A0-90-DE (hex) VEEDIMS,LLC - A090DE (base 16) VEEDIMS,LLC - 49 N. Federal Highway #397 - Pompano Beach Florida 33062 - UNITED STATES - - A0-93-47 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - A09347 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - NO.18 HAIBIN ROAD,WUSHA,CHANG'AN - DONGGUAN GUANGDONG 523860 - CHINA - - A0-98-05 (hex) OpenVox Communication Co Ltd - A09805 (base 16) OpenVox Communication Co Ltd - F2,Building No.14,Shangsha Science & - Technology Park,No.9283,Binhe Road - ShenZhen GuangDong 518031 - CHINA - - A0-98-ED (hex) Shandong Intelligent Optical Communication Development Co., Ltd. - A098ED (base 16) Shandong Intelligent Optical Communication Development Co., Ltd. - No.149 Yingcui Road,Torch Town,Advanced Technique Development Area - Jining Shandong 272023 - CHINA - - A0-99-9B (hex) Apple - A0999B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A0-9A-5A (hex) Time Domain - A09A5A (base 16) Time Domain - 330 Wynn Drive - Suite 300 - Huntsville AL 35805 - UNITED STATES - - A0-9B-BD (hex) Total Aviation Solutions Pty Ltd - A09BBD (base 16) Total Aviation Solutions Pty Ltd - Suite 816A / 3 PARKLAND BVDE - Brisbane QLD 4000 - AUSTRALIA - - A0-A1-30 (hex) DLI Taiwan Branch office - A0A130 (base 16) DLI Taiwan Branch office - No.18-5, No.738. Zhong Zheng Rd - Zhong He Dist. - Taipei New City 23511 - TAIWAN, PROVINCE OF CHINA - - A0-A2-3C (hex) GPMS - A0A23C (base 16) GPMS - 40 Ridge Rd - Cornwall VT 05753 - UNITED STATES - - A0-A3-E2 (hex) Actiontec Electronics, Inc - A0A3E2 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - A0-A6-5C (hex) Supercomputing Systems AG - A0A65C (base 16) Supercomputing Systems AG - Technoparkstrasse 1 - Zurich ZH 8005 - SWITZERLAND - - A0-A7-63 (hex) Polytron Vertrieb GmbH - A0A763 (base 16) Polytron Vertrieb GmbH - Langwiesenweg 64-71 - Bad Wildbad Baden-Württemberg 75323 - GERMANY - - A0-A8-CD (hex) Intel Corporate - A0A8CD (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - A0-AA-FD (hex) EraThink Technologies Corp. - A0AAFD (base 16) EraThink Technologies Corp. - 289 Bisheng Road Building 4,Floor 4 - Shanghai 201204 - CHINA - - A0-AD-A1 (hex) JMR Electronics, Inc - A0ADA1 (base 16) JMR Electronics, Inc - 8968 Fullbright Avenue - Chatsworth California 91311 - UNITED STATES - - A0-B1-00 (hex) ShenZhen Cando Electronics Co.,Ltd - A0B100 (base 16) ShenZhen Cando Electronics Co.,Ltd - Building A, Dagang Industrial Zone, Changzhen Community - Gongming Street, Guangming New District - Shenzhen City Guangdong 518132 - CHINA - - A0-B3-CC (hex) Hewlett Packard - A0B3CC (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - A0-B4-37 (hex) GENERAL DYNAMICS C4 SYSEMS - A0B437 (base 16) GENERAL DYNAMICS C4 SYSEMS - 8220 EAST ROOSEVELT ST R2121 - SCOTTSDALE AZ 85257 - UNITED STATES - - A0-B4-A5 (hex) Samsung Elec Co.,Ltd - A0B4A5 (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A0-B5-DA (hex) HongKong THTF Co., Ltd - A0B5DA (base 16) HongKong THTF Co., Ltd - 2F,Sector C of Tsinghua University Academy, - Hi-Tech Park(South),Nanshan District - Shenzhen Guangdong 518057 - CHINA - - A0-B6-62 (hex) Acutvista Innovation Co., Ltd. - A0B662 (base 16) Acutvista Innovation Co., Ltd. - 2F-1, No. 20 Alley 1, Lane 768, Sec. 4 - Pa-Teh Rd., - Taipei City 11577 - TAIWAN, PROVINCE OF CHINA - - A0-B9-ED (hex) Skytap - A0B9ED (base 16) Skytap - 710 2nd Ave Suite 1130 - Seattle WA 98104 - UNITED STATES - - A0-BA-B8 (hex) Pixon Imaging - A0BAB8 (base 16) Pixon Imaging - 9530 Towne Center Dr. - Suite 120 - San Diego CA 92121 - UNITED STATES - - A0-BB-3E (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - A0BB3E (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - A0-BF-50 (hex) S.C. ADD-PRODUCTION S.R.L. - A0BF50 (base 16) S.C. ADD-PRODUCTION S.R.L. - 36, Dragomirna str. - Chisinau MD-2008 - MOLDOVA, REPUBLIC OF - - A0-BF-A5 (hex) CORESYS - A0BFA5 (base 16) CORESYS - 267-1 Nonhyundong Gangnamgu - JK Bld., #301 - Seoul 135-833 - KOREA, REPUBLIC OF - - A0-C2-DE (hex) Costar Video Systems - A0C2DE (base 16) Costar Video Systems - 101 Wrangler, Suite 201 - Coppell Texas 75019 - UNITED STATES - - A0-C3-DE (hex) Triton Electronic Systems Ltd. - A0C3DE (base 16) Triton Electronic Systems Ltd. - 620063, Ekaterinburg, P/O box 522 - Ekaterinburg Sverdlovskaya obl. 620063 - RUSSIAN FEDERATION - - A0-C5-62 (hex) Pace plc - A0C562 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - A0-C6-EC (hex) ShenZhen ANYK Technology Co.,LTD - A0C6EC (base 16) ShenZhen ANYK Technology Co.,LTD - 5F,12B,ZhongXing Industrial Zone, Venture Road - Nanshan District, Shenzhen City - ShenZhen GuangDong 518054 - CHINA - - A0-CE-C8 (hex) CE LINK LIMITED - A0CEC8 (base 16) CE LINK LIMITED - 2/F, Building G, Licheng Tech. Ind. Zone - Shajing Town, - Shenzhen Guangdong 518104 - CHINA - - A0-CF-5B (hex) CISCO SYSTEMS, INC. - A0CF5B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - A0-D1-2A (hex) AXPRO Technology Inc. - A0D12A (base 16) AXPRO Technology Inc. - 8F, No.128, sec. 4 Chung Hsiao E. RD., - Taipei 106 - Taipei city 10866 - TAIWAN, PROVINCE OF CHINA - - A0-D3-C1 (hex) Hewlett Packard - A0D3C1 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - A0-DA-92 (hex) Nanjing Glarun Atten Technology Co. Ltd. - A0DA92 (base 16) Nanjing Glarun Atten Technology Co. Ltd. - Dinghuai men No. 1, Gulou District - Nanjing - CHINA - - A0-DC-04 (hex) Becker-Antriebe GmbH - A0DC04 (base 16) Becker-Antriebe GmbH - Friedrich-Ebert-Straße 2 - 4 - 35764 Sinn Hessen DE811177977 - GERMANY - - A0-DD-97 (hex) PolarLink Technologies, Ltd - A0DD97 (base 16) PolarLink Technologies, Ltd - 6FL 352, Zhonghua 1st Rd. - Kaohsiung 804 - TAIWAN, PROVINCE OF CHINA - - A0-DD-E5 (hex) SHARP Corporation - A0DDE5 (base 16) SHARP Corporation - 22-22,Nagaike-cho - Abeno-ku - Osaka city Osaka prefecture 545-8522 - JAPAN - - A0-DE-05 (hex) JSC "Irbis-T" - A0DE05 (base 16) JSC "Irbis-T" - 5, Liteynaya street - Tula 300002 - RUSSIAN FEDERATION - - A0-E2-01 (hex) AVTrace Ltd.(China) - A0E201 (base 16) AVTrace Ltd.(China) - RM704, District B1, Originality Building, No.162 KeXue Avenue Science Town,GUANGZHOU,CHINA - GUANGZHOU GUANGDONG 510611 - CHINA - - A0-E2-5A (hex) Amicus SK, s.r.o. - A0E25A (base 16) Amicus SK, s.r.o. - Koreszkova 9 - Skalica Trnavsky kraj 90901 - SLOVAKIA - - A0-E2-95 (hex) DAT System Co.,Ltd - A0E295 (base 16) DAT System Co.,Ltd - Gun San Free Trade Area 511-1 , - Osik do dong Gunsan si Jeon Buk - 573-540 - KOREA, REPUBLIC OF - - A0-E4-53 (hex) Sony Mobile Communications AB - A0E453 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - A0-E4-CB (hex) ZyXEL Communications Corporation - A0E4CB (base 16) ZyXEL Communications Corporation - No. 6 Innovation Road II, Science Park - Hsichu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - A0-E5-34 (hex) Stratec Biomedical AG - A0E534 (base 16) Stratec Biomedical AG - Gewerbestrasse 37 - Birkenfeld Baden Wuertemberg 75217 - GERMANY - - A0-E5-E9 (hex) enimai Inc - A0E5E9 (base 16) enimai Inc - 701 Villa St - Mountain View California 94041 - UNITED STATES - - A0-E6-F8 (hex) Texas Instruments Inc - A0E6F8 (base 16) Texas Instruments Inc - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - A0-E9-DB (hex) Ningbo FreeWings Technologies Co.,Ltd - A0E9DB (base 16) Ningbo FreeWings Technologies Co.,Ltd - Room 1107-1108, No 298 XueShi Road Yinzhou District Ningbo, - Ningbo Zhejiang 315000 - CHINA - - A0-EB-76 (hex) AirCUVE Inc. - A0EB76 (base 16) AirCUVE Inc. - Guro-gu Digital-ro - Seoul 152-719 - KOREA, REPUBLIC OF - - A0-EC-80 (hex) zte corporation - A0EC80 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - A0-EC-F9 (hex) Cisco - A0ECF9 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - A0-ED-CD (hex) Apple - A0EDCD (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A0-EF-84 (hex) Seine Image Int'l Co., Ltd - A0EF84 (base 16) Seine Image Int'l Co., Ltd - 6F,4Building, NO.63,Mingz North Road - ZhuHai 519075 - CHINA - - A0-F2-17 (hex) GE Medical System(China) Co., Ltd. - A0F217 (base 16) GE Medical System(China) Co., Ltd. - No.19, ChangJiang Road - Wuxi Jiangsu 214028 - CHINA - - A0-F3-C1 (hex) TP-LINK TECHNOLOGIES CO., LTD. - A0F3C1 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Shennan Rd, - Central Science and Technology Park - shenzhen guangdong Province 518057 - CHINA - - A0-F3-E4 (hex) Alcatel Lucent IPD - A0F3E4 (base 16) Alcatel Lucent IPD - 600 March Dr - Kanata On K2K 2E1 - CANADA - - A0-F4-19 (hex) Nokia Corporation - A0F419 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - A0-F4-50 (hex) HTC Corporation - A0F450 (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - A0-F4-59 (hex) FN-LINK TECHNOLOGY LIMITED - A0F459 (base 16) FN-LINK TECHNOLOGY LIMITED - 5th Floor, A Building, Haoye Logistics Park, - Shugang Channel, Bao'an District, - SHENZHEN GUANGDONG 518126 - CHINA - - A0-F6-FD (hex) Texas Instruments - A0F6FD (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - A0-F8-49 (hex) Cisco - A0F849 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - A0-FC-6E (hex) Telegrafia a.s. - A0FC6E (base 16) Telegrafia a.s. - Lomena 7 - Kosice Slovakia 040 01 - SLOVAKIA - - A0-FE-91 (hex) AVAT Automation GmbH - A0FE91 (base 16) AVAT Automation GmbH - Derendinger Strasse 40 - Tuebingen 72072 - GERMANY - - A4-01-30 (hex) ABIsystems Co., LTD - A40130 (base 16) ABIsystems Co., LTD - 308 ACE Techno Tower8 191-7 Guro-dong - Guro-gu - Seoul - KOREA, REPUBLIC OF - - A4-05-9E (hex) STA Infinity LLP - A4059E (base 16) STA Infinity LLP - WINNINGTON HOUSE - 2 WOODBERRY GROVE NORTH FINCHLEY - London N12 0DR - UNITED KINGDOM - - A4-08-EA (hex) Murata Manufacturing Co., Ltd. - A408EA (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - A4-09-CB (hex) Alfred Kaercher GmbH & Co KG - A409CB (base 16) Alfred Kaercher GmbH & Co KG - Alfred Kaercher Gmbh & Co KG - Winnenden Baden-Wuerttemberg 71364 - GERMANY - - A4-0B-ED (hex) Carry Technology Co.,Ltd - A40BED (base 16) Carry Technology Co.,Ltd - 4F, No.119, JianKang Road - Jhonghe Dist. New Taipei City 23585 - TAIWAN, PROVINCE OF CHINA - - A4-0C-C3 (hex) CISCO SYSTEMS, INC. - A40CC3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - A4-12-42 (hex) NEC Platforms, Ltd. - A41242 (base 16) NEC Platforms, Ltd. - 800 Shimomata - Kakegawa Shizuoka 436-8501 - JAPAN - - A4-13-4E (hex) Luxul - A4134E (base 16) Luxul - 14203 Minuteman Drive - Suite 201 - Draper UT 84020 - UNITED STATES - - A4-15-66 (hex) Wei Fang Goertek Electronics Co.,Ltd - A41566 (base 16) Wei Fang Goertek Electronics Co.,Ltd - Wei fang Export processing Zone - Wei Fang Shan Dong 261205 - CHINA - - A4-17-31 (hex) Hon Hai Precision Ind. Co.,Ltd. - A41731 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - A4-18-75 (hex) CISCO SYSTEMS, INC. - A41875 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - A4-1B-C0 (hex) Fastec Imaging Corporation - A41BC0 (base 16) Fastec Imaging Corporation - 17150 Via Del Campo - Suite 301 - San Diego California 92127 - UNITED STATES - - A4-1F-72 (hex) Dell Inc. - A41F72 (base 16) Dell Inc. - One Dell way - MS:RR5-45 - Round Rock Tx 78682 - UNITED STATES - - A4-21-8A (hex) Nortel Networks - A4218A (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - A4-23-05 (hex) Open Networking Laboratory - A42305 (base 16) Open Networking Laboratory - 1000 El Camino Real - Suite 100 - Menlo Park CA 94025 - UNITED STATES - - A4-24-B3 (hex) FlatFrog Laboratories AB - A424B3 (base 16) FlatFrog Laboratories AB - Magistratsvägen 10 - Lund SkÃ¥ne 22643 - SWEDEN - - A4-24-DD (hex) Cambrionix Ltd - A424DD (base 16) Cambrionix Ltd - St Johns Innovation Centre - Cowley Road - Cambridge Cambridgeshire CB4 0WS - UNITED KINGDOM - - A4-25-1B (hex) Avaya, Inc - A4251B (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - A4-29-40 (hex) Shenzhen YOUHUA Technology Co., Ltd - A42940 (base 16) Shenzhen YOUHUA Technology Co., Ltd - Shenzhen University-town Business Park,Lishan Road,Taoyuan Street - Nanshan District - Shenzhen Guangdong 518055 - CHINA - - A4-29-B7 (hex) bluesky - A429B7 (base 16) bluesky - Rm1410 Tower A,Chengjian plaza,NO.18 beitaipingzhuang Road,Haidian District, - Beijing 100088 - CHINA - - A4-2B-8C (hex) Netgear Inc - A42B8C (base 16) Netgear Inc - 350 East Plumeria Drive - San Jose CA 95134 - UNITED STATES - - A4-2C-08 (hex) Masterwork Automodules - A42C08 (base 16) Masterwork Automodules - 11F-3, 3,PARK ST., NAN GANG - TAIPEI 11503 - TAIWAN, PROVINCE OF CHINA - - A4-31-35 (hex) Apple Inc - A43135 (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A4-33-D1 (hex) Fibrlink Communications Co.,Ltd. - A433D1 (base 16) Fibrlink Communications Co.,Ltd. - 28F Ages Wealth World, No.1 Hangfeng Road - Fengtai District - Beijing 100070 - CHINA - - A4-34-D9 (hex) Intel Corporate - A434D9 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - A4-38-FC (hex) Plastic Logic - A438FC (base 16) Plastic Logic - 650 Castro St., Suite 500 - Mountain View CA 94041 - UNITED STATES - - A4-3A-69 (hex) Vers Inc - A43A69 (base 16) Vers Inc - PO Box 5265 - Wayland MA 01778 - UNITED STATES - - A4-3B-FA (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - A43BFA (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - A4-3D-78 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD - A43D78 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD - NO.18 HAIBIN ROAD, - WUSHA,CHANG'AN - DONG GUAN GUANG DONG 523860 - CHINA - - A4-46-6B (hex) EOC Technology - A4466B (base 16) EOC Technology - #1601 Acro Palace, 1594 Gwanyang-dong, Dongan-gu - Anyang-si Gyeonggi-do 431-060 - KOREA, REPUBLIC OF - - A4-46-FA (hex) AmTRAN Video Corporation - A446FA (base 16) AmTRAN Video Corporation - 9 Goddard - Irvine CA 92618 - UNITED STATES - - A4-4A-D3 (hex) ST Electronics(Shanghai) Co.,Ltd - A44AD3 (base 16) ST Electronics(Shanghai) Co.,Ltd - Floors 1&3, No.6 Building, No.1151 Lianxi Road - Pudong New Area - Shanghai 201204 - CHINA - - A4-4B-15 (hex) Sun Cupid Technology (HK) LTD - A44B15 (base 16) Sun Cupid Technology (HK) LTD - Room 1201-3, 12/F., Tower 6 - China Hong Kong City - Tsim Sha Tsui - HONG KONG - - A4-4C-11 (hex) CISCO SYSTEMS, INC. - A44C11 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - A4-4E-2D (hex) Adaptive Wireless Solutions, LLC - A44E2D (base 16) Adaptive Wireless Solutions, LLC - 577 Main Street - Hudson MA 01749 - UNITED STATES - - A4-4E-31 (hex) Intel Corporate - A44E31 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - A4-4F-29 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - A44F29 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - A4-50-55 (hex) busware.de - A45055 (base 16) busware.de - Loessnitzgrundstrasse 115a - Moritzburg Saxony 01468 - GERMANY - - A4-52-6F (hex) ADB Broadband Italia - A4526F (base 16) ADB Broadband Italia - via Sarca 222 - Milano 20126 - ITALY - - A4-56-02 (hex) fenglian Technology Co.,Ltd. - A45602 (base 16) fenglian Technology Co.,Ltd. - 302 R D Building Oriental Cyberport HighTech Industrial Park Nanshan Shenzhen China - Shenzhen,Guangdong Province 518057 - CHINA - - A4-56-1B (hex) MCOT Corporation - A4561B (base 16) MCOT Corporation - Yogohigashi 1-5-12 - Matsuyama city Ehime prefecture 790-0044 - JAPAN - - A4-56-30 (hex) CISCO SYSTEMS, INC. - A45630 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - A4-5A-1C (hex) smart-electronic GmbH - A45A1C (base 16) smart-electronic GmbH - Industriestrasse 29 - St. Georgen Baden-Württemberg 78122 - GERMANY - - A4-5C-27 (hex) Nintendo Co., Ltd. - A45C27 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - A4-5D-36 (hex) Hewlett Packard - A45D36 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - A4-5D-A1 (hex) ADB Broadband Italia - A45DA1 (base 16) ADB Broadband Italia - VIALE SARCA 336 - MILANO ITALY 20126 - ITALY - - A4-5E-60 (hex) Apple - A45E60 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A4-60-32 (hex) MRV Communications (Networks) LTD - A46032 (base 16) MRV Communications (Networks) LTD - Hayetzira 6 - P.O Box 614 - Yokneam Yokneam 20692 - ISRAEL - - A4-67-06 (hex) Apple - A46706 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A4-6C-2A (hex) Cisco - A46C2A (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - A4-6C-C1 (hex) LTi REEnergy GmbH - A46CC1 (base 16) LTi REEnergy GmbH - Heinrich-Hertz-Straße 18 - Unna North Rhine-Westfalia 59423 - GERMANY - - A4-6E-79 (hex) DFT System Co.Ltd - A46E79 (base 16) DFT System Co.Ltd - Room 6B XINHAOFANG Building - NO.188 Shennan road - SHENZHEN GUANGDONG 518052 - CHINA - - A4-70-D6 (hex) Motorola Mobility LLC - A470D6 (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - A4-77-33 (hex) Google - A47733 (base 16) Google - 1600 Ampitheatre Parkway - Mountain View California 94043 - UNITED STATES - - A4-77-60 (hex) Nokia Corporation - A47760 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - A4-79-E4 (hex) KLINFO Corp - A479E4 (base 16) KLINFO Corp - 301 923 wolpyung-dong - seo gu - Daejeon 302-852 - KOREA, REPUBLIC OF - - A4-7A-A4 (hex) ARRIS Group, Inc. - A47AA4 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - A4-7A-CF (hex) VIBICOM COMMUNICATIONS INC. - A47ACF (base 16) VIBICOM COMMUNICATIONS INC. - 900 CORPORATE DRIVE - MAHWAH NEW JERSEY 074030 - UNITED STATES - - A4-7B-2C (hex) Alcatel-Lucent - A47B2C (base 16) Alcatel-Lucent - 600 March Road - Ottawa ON K2K 2E6 - CANADA - - A4-7B-85 (hex) ULTIMEDIA Co Ltd, - A47B85 (base 16) ULTIMEDIA Co Ltd, - Saeaml-ro 102 - 2520 - Guro-Gu Seoul 152770 - KOREA, REPUBLIC OF - - A4-7C-14 (hex) ChargeStorm AB - A47C14 (base 16) ChargeStorm AB - Laxholmstorget 3 - Norrköping 60221 - SWEDEN - - A4-7C-1F (hex) Cobham plc - A47C1F (base 16) Cobham plc - 3985 Gateway Centre Blvd - Pinellas Park FL 33782 - UNITED STATES - - A4-7E-39 (hex) zte corporation - A47E39 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - A4-81-EE (hex) Nokia Corporation - A481EE (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - A4-85-6B (hex) Q Electronics Ltd - A4856B (base 16) Q Electronics Ltd - Beck House, Hawksworth Road - Horsforth - Leeds West Yorkshire LS18 4JP - UNITED KINGDOM - - A4-89-5B (hex) ARK INFOSOLUTIONS PVT LTD - A4895B (base 16) ARK INFOSOLUTIONS PVT LTD - 4428, GANESH BAZAR CLOTH MARKET - CHANDNI CHOWK - DELHI 110006 - INDIA - - A4-8C-DB (hex) Lenovo - A48CDB (base 16) Lenovo - 1009 Think Place - Morrisvilee NC 27560 - ALAND ISLANDS - - A4-90-05 (hex) CHINA GREATWALL COMPUTER SHENZHEN CO.,LTD - A49005 (base 16) CHINA GREATWALL COMPUTER SHENZHEN CO.,LTD - 409,2#,Greatwall Bldg,No.3 Kefa Road,Science & Industry Park,Nanshan District, - Shenzhen Guangdong 51807 - CHINA - - A4-93-4C (hex) CISCO SYSTEMS, INC. - A4934C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - A4-97-BB (hex) Hitachi Industrial Equipment Systems Co.,Ltd - A497BB (base 16) Hitachi Industrial Equipment Systems Co.,Ltd - 3, Kanda Neribei-cho - AKS Building - Chiyoda-ku Tokyo 101-0022 - JAPAN - - A4-99-47 (hex) Huawei Technologies Co., Ltd - A49947 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - A4-99-81 (hex) FuJian Elite Power Tech CO.,LTD. - A49981 (base 16) FuJian Elite Power Tech CO.,LTD. - 8th Floor£¬56 GuanRi Road - Software Square (Phase Two), Siming District - Xiamen Fujian 361009 - CHINA - - A4-9A-58 (hex) Samsung Electronics Co.,Ltd - A49A58 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A4-9B-13 (hex) Burroughs Payment Systems, Inc. - A49B13 (base 16) Burroughs Payment Systems, Inc. - 41100 Plymouth Road - Plymouth Michigan 48170 - UNITED STATES - - A4-9D-49 (hex) Ketra, Inc. - A49D49 (base 16) Ketra, Inc. - 3815 S. Capital of Texas Hwy - Suite 100 - Austin TX 78704 - UNITED STATES - - A4-9E-DB (hex) AutoCrib, Inc. - A49EDB (base 16) AutoCrib, Inc. - 3011 S. Croddy Way - Santa Ana CA 92704 - UNITED STATES - - A4-9F-85 (hex) Lyve Minds, Inc - A49F85 (base 16) Lyve Minds, Inc - 10001 N. De Anza Blvd, Ste 300 - Cupertino CA 95014 - UNITED STATES - - A4-9F-89 (hex) Shanghai Rui Rui Communication Technology Co.Ltd. - A49F89 (base 16) Shanghai Rui Rui Communication Technology Co.Ltd. - Room 1130,Building No.1 - No.388 ShenFu Road,MinXing District - ShangHai 201199 - CHINA - - A4-A1-C2 (hex) Ericsson AB (EAB) - A4A1C2 (base 16) Ericsson AB (EAB) - Torshamnsgatan 36 - Stockholm Stockholm SE-164 80 - SWEDEN - - A4-A1-E4 (hex) Innotube, Inc. - A4A1E4 (base 16) Innotube, Inc. - #1212 MegaCenter SknTechnoPark 124 Sagimakgol-ro Jungwon-gu - Seongnam-si Gyeonggi-do 462-120 - KOREA, REPUBLIC OF - - A4-A2-4A (hex) Cisco SPVTG - A4A24A (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - A4-A4-D3 (hex) Bluebank Communication Technology Co.Ltd - A4A4D3 (base 16) Bluebank Communication Technology Co.Ltd - No.13-2.Jiang Ying Road, - Nan An District - Chongqing 401336 - CHINA - - A4-A8-0F (hex) Shenzhen Coship Electronics Co., Ltd. - A4A80F (base 16) Shenzhen Coship Electronics Co., Ltd. - Rainbow Bldg., North, Hi-Tech Industrial Park, Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - A4-AD-00 (hex) Ragsdale Technology - A4AD00 (base 16) Ragsdale Technology - 505 Echo Lane - PO Box 120507 - Big Bear Lake CA 92315 - UNITED STATES - - A4-AD-B8 (hex) Vitec Group, Camera Dynamics Ltd - A4ADB8 (base 16) Vitec Group, Camera Dynamics Ltd - William Vinten Building - Western Way - Bury St Edmunds Suffolk IP33 3TB - UNITED KINGDOM - - A4-AE-9A (hex) Maestro Wireless Solutions ltd. - A4AE9A (base 16) Maestro Wireless Solutions ltd. - 3603-9, 36/F - 118 Connaught Road West - Sai Ying Pun - HONG KONG - - A4-B1-21 (hex) Arantia 2010 S.L. - A4B121 (base 16) Arantia 2010 S.L. - Volta do Castro s/n - Santiago de Compostela A Coruña 15706 - SPAIN - - A4-B1-97 (hex) Apple - A4B197 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A4-B1-E9 (hex) Technicolor - A4B1E9 (base 16) Technicolor - Prins Boudewijnlaan 47 - Edegem Belgium B-2650 - BELGIUM - - A4-B1-EE (hex) H. ZANDER GmbH & Co. KG - A4B1EE (base 16) H. ZANDER GmbH & Co. KG - Am Gut Wolf 15 - Aachen 52070 - GERMANY - - A4-B2-A7 (hex) Adaxys Solutions AG - A4B2A7 (base 16) Adaxys Solutions AG - Eichtalstrasse 55 - Hombrechtikon CH 8634 - SWITZERLAND - - A4-B3-6A (hex) JSC SDO Chromatec - A4B36A (base 16) JSC SDO Chromatec - 94, Stroiteley street - Yoshkar-Ola Mari El republic 424000 - RUSSIAN FEDERATION - - A4-B8-18 (hex) PENTA Gesellschaft für elektronische Industriedatenverarbeitung mbH - A4B818 (base 16) PENTA Gesellschaft für elektronische Industriedatenverarbeitung mbH - Ulrichsberger Str. 17 - Deggendorf 94469 - GERMANY - - A4-B9-80 (hex) Parking BOXX Inc. - A4B980 (base 16) Parking BOXX Inc. - 382 NE 191st St. #93984 - Miami FL 33179-3899 - UNITED STATES - - A4-BA-DB (hex) Dell Inc. - A4BADB (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - A4-BB-AF (hex) Lime Instruments - A4BBAF (base 16) Lime Instruments - 1187 Brittmoore Road - Houston TX 77043 - UNITED STATES - - A4-BE-61 (hex) EutroVision System, Inc. - A4BE61 (base 16) EutroVision System, Inc. - Rm 403,Building33,No.680 GuipingRd,Xuhui, - Shanghai 200233 - CHINA - - A4-C0-C7 (hex) ShenZhen Hitom Communication Technology Co..LTD - A4C0C7 (base 16) ShenZhen Hitom Communication Technology Co..LTD - Room 110,Unit A,No.1 Chuangye Building,43# YanShan Road,Shekou Area - Nanshan District - ShenZhen GuangDong 518052 - CHINA - - A4-C0-E1 (hex) Nintendo Co., Ltd. - A4C0E1 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - A4-C2-AB (hex) Hangzhou LEAD-IT Information & Technology Co.,Ltd - A4C2AB (base 16) Hangzhou LEAD-IT Information & Technology Co.,Ltd - F2 Builder B,Xidomen Road NO.22 - Hangzhou Zhejiang 310012 - CHINA - - A4-C3-61 (hex) Apple - A4C361 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A4-C4-94 (hex) Intel Corporate - A4C494 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - A4-C7-DE (hex) Cambridge Industries(Group) Co.,Ltd. - A4C7DE (base 16) Cambridge Industries(Group) Co.,Ltd. - 22 Floor,Qilai Tower;889 Yishan Road - Shanghai 200233 - CHINA - - A4-D0-94 (hex) Erwin Peters Systemtechnik GmbH - A4D094 (base 16) Erwin Peters Systemtechnik GmbH - Josef Baumann Strasse 37 - Bochum D44805 - GERMANY - - A4-D1-8F (hex) Shenzhen Skyee Optical Fiber Communication Technology Ltd. - A4D18F (base 16) Shenzhen Skyee Optical Fiber Communication Technology Ltd. - No.5 Bldg. Yimin Industrial Park, No.31, Makan South Road, Nanshan District - Shenzhen Guangdong 518000 - CHINA - - A4-D1-D1 (hex) ECOtality North America - A4D1D1 (base 16) ECOtality North America - 430 S 2nd Avenue - Phoenix AZ 85003 - UNITED STATES - - A4-D1-D2 (hex) Apple - A4D1D2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A4-D3-B5 (hex) GLITEL Stropkov, s.r.o. - A4D3B5 (base 16) GLITEL Stropkov, s.r.o. - Cintorinska 557/73 - Stropkov 09101 - SLOVAKIA - - A4-D8-56 (hex) Gimbal, Inc - A4D856 (base 16) Gimbal, Inc - 12526 High Bluff Drive - Suite 250 - San Diego Ca 92130 - UNITED STATES - - A4-DA-3F (hex) Bionics Corp. - A4DA3F (base 16) Bionics Corp. - 1406 Masters Tower - 553 Dowha-dong Mapo-gu - Seoul 121-748 - KOREA, REPUBLIC OF - - A4-DB-2E (hex) Kingspan Environmental Ltd - A4DB2E (base 16) Kingspan Environmental Ltd - 180 Gilford Road - Portadown Armagh BT63 5LF - UNITED KINGDOM - - A4-DB-30 (hex) Liteon Technology Corporation - A4DB30 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo - Taipei Hsien, - TaiPei 23585 - TAIWAN, PROVINCE OF CHINA - - A4-DE-50 (hex) Total Walther GmbH - A4DE50 (base 16) Total Walther GmbH - Frankfurter Ring 17 - Munich 80807 - GERMANY - - A4-E0-E6 (hex) FILIZOLA S.A. PESAGEM E AUTOMACAO - A4E0E6 (base 16) FILIZOLA S.A. PESAGEM E AUTOMACAO - RUA JOAO VENTURA BATISTA, 450 - VILA GUILHERME - SAO PAULO 02054-100 - BRAZIL - - A4-E3-2E (hex) Silicon & Software Systems Ltd. - A4E32E (base 16) Silicon & Software Systems Ltd. - South County Business Park - Leopardstown Dublin 18 - IRELAND - - A4-E3-91 (hex) DENY FONTAINE - A4E391 (base 16) DENY FONTAINE - ROUTE DE SAINT VALERY - SAINT BLIMONT 80960 - FRANCE - - A4-E4-B8 (hex) BlackBerry Limited - A4E4B8 (base 16) BlackBerry Limited - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - A4-E7-31 (hex) Nokia Corporation - A4E731 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - A4-E7-E4 (hex) Connex GmbH - A4E7E4 (base 16) Connex GmbH - Elbestrasse 12 - Oldenburg 26135 - GERMANY - - A4-E9-91 (hex) SISTEMAS AUDIOVISUALES ITELSIS S.L. - A4E991 (base 16) SISTEMAS AUDIOVISUALES ITELSIS S.L. - POL.IND. DEL TAMBRE - VIA EDISON 16 - SANTIAGO COMPOSTELA A CORUÑA 15890 - SPAIN - - A4-E9-A3 (hex) Honest Technology Co., Ltd - A4E9A3 (base 16) Honest Technology Co., Ltd - 5F, KyungDong Bldg. 906-5, - Jijok-Dong, Yuseong-Gu, - Daejeon 305-330 - KOREA, REPUBLIC OF - - A4-EB-D3 (hex) Samsung Electronics Co.,Ltd - A4EBD3 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A4-ED-4E (hex) ARRIS Group, Inc. - A4ED4E (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - A4-EE-57 (hex) SEIKO EPSON CORPORATION - A4EE57 (base 16) SEIKO EPSON CORPORATION - 3-3-5 OWA - SUWA-SHI NAGANO-KEN 392-8502 - JAPAN - - A4-EF-52 (hex) Telewave Co., Ltd. - A4EF52 (base 16) Telewave Co., Ltd. - A-203, SK Twintech Tower - Gasan-dong, Geumcheon-gu - Seoul 153-773 - KOREA, REPUBLIC OF - - A4-F3-C1 (hex) Open Source Robotics Foundation, Inc. - A4F3C1 (base 16) Open Source Robotics Foundation, Inc. - 419 N Shoreline Blvd - Mountain View CA 94043 - UNITED STATES - - A4-F5-22 (hex) CHOFU SEISAKUSHO CO.,LTD - A4F522 (base 16) CHOFU SEISAKUSHO CO.,LTD - 2-1 - Chofu Ogi-machi - Shimonoseki-shi Yamaguchi 752-8555 - JAPAN - - A4-F7-D0 (hex) LAN Accessories Co., Ltd. - A4F7D0 (base 16) LAN Accessories Co., Ltd. - 8F-1, No. 159, Sec. 1 Hsin Tai Wu Road, - Shih Chih Dist., - New Taipei City, 221 - TAIWAN, PROVINCE OF CHINA - - A4-FB-8D (hex) Hangzhou Dunchong Technology Co.Ltd - A4FB8D (base 16) Hangzhou Dunchong Technology Co.Ltd - Yitian Square 1#401A - Binjiang - hangzhou zhejiang 310051 - CHINA - - A4-FC-CE (hex) Security Expert Ltd. - A4FCCE (base 16) Security Expert Ltd. - 75, Ekaterininskaya Street, of. 105 - Perm Perm region 614000 - RUSSIAN FEDERATION - - A8-01-80 (hex) IMAGO Technologies GmbH - A80180 (base 16) IMAGO Technologies GmbH - Strassheimer Str. 45 - Friedberg Hessen 61169 - GERMANY - - A8-06-00 (hex) Samsung Electronics Co.,Ltd - A80600 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A8-0C-0D (hex) Cisco - A80C0D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - A8-13-74 (hex) Panasonic Corporation AVC Networks Company - A81374 (base 16) Panasonic Corporation AVC Networks Company - 1-15 Matsuo cho - Kadoma city Osaka 571-8504 - JAPAN - - A8-15-4D (hex) TP-LINK TECHNOLOGIES CO.,LTD. - A8154D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - A8-16-B2 (hex) LG Electronics - A816B2 (base 16) LG Electronics - 60-39 , Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - A8-17-58 (hex) Elektronik System i UmeÃ¥ AB - A81758 (base 16) Elektronik System i UmeÃ¥ AB - Box 7978 - Tvistevägen 47 - UmeÃ¥ Västerbotten 907 19 - SWEDEN - - A8-1B-18 (hex) XTS CORP - A81B18 (base 16) XTS CORP - 10125 NW 116TH WAY, SUITE 5 - MEDLEY FLORIDA 33178 - UNITED STATES - - A8-1B-5A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - A81B5A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - NO.18 HAIBIN ROAD,WUSHA,CHANG'AN - DONGGUAN GUANGDONG 523860 - CHINA - - A8-1B-5D (hex) Foxtel Management Pty Ltd - A81B5D (base 16) Foxtel Management Pty Ltd - Building 3, Level 3 - 5 Thomas Holt Drive - NORTH RYDE NSW 2113 - AUSTRALIA - - A8-1D-16 (hex) AzureWave Technologies, Inc - A81D16 (base 16) AzureWave Technologies, Inc - 8F., No. 94, Baozhong Rd. - Xindian Dist. - New Taipei City Taiwan 231 - TAIWAN, PROVINCE OF CHINA - - A8-1F-AF (hex) KRYPTON POLSKA - A81FAF (base 16) KRYPTON POLSKA - AL. JEROZOLIMSKIE 131 - WARSZAWA MAZOWIECKIE 02-304 - POLAND - - A8-20-66 (hex) Apple - A82066 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-24-EB (hex) ZAO NPO Introtest - A824EB (base 16) ZAO NPO Introtest - Studencheskaya st. 55 - Ekaterinburg Sverdlovsk region 620078 - RUSSIAN FEDERATION - - A8-26-D9 (hex) HTC Corporation - A826D9 (base 16) HTC Corporation - No. 23, Xinghua Rd, Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - A8-29-4C (hex) Precision Optical Transceivers, Inc. - A8294C (base 16) Precision Optical Transceivers, Inc. - 2328 Innovation Way - Rochester NY 14624 - UNITED STATES - - A8-2B-D6 (hex) Shina System Co., Ltd - A82BD6 (base 16) Shina System Co., Ltd - 6FL-601, The-O Valley, Anyang International Distribute Complex - Hogye 1-Dong 555-9, Dongan-Gu - Anyang-Si Gyeounggi-Do 431-763 - KOREA, REPUBLIC OF - - A8-30-AD (hex) Wei Fang Goertek Electronics Co.,Ltd - A830AD (base 16) Wei Fang Goertek Electronics Co.,Ltd - Wei fang Export processing Zone - Wei Fang Shan Dong 261205 - CHINA - - A8-32-9A (hex) Digicom Futuristic Technologies Ltd. - A8329A (base 16) Digicom Futuristic Technologies Ltd. - 406 Mirror Tower, Modi Road, TST - Kowlon - 000086 - HONG KONG - - A8-39-44 (hex) Actiontec Electronics, Inc - A83944 (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - A8-40-41 (hex) Dragino Technology Co., Limited - A84041 (base 16) Dragino Technology Co., Limited - 303, Block B, No 8; 349, Jian'An 1 Road,Bao'An - Shenzhen GuangDong 518101 - CHINA - - A8-44-81 (hex) Nokia Corporation - A84481 (base 16) Nokia Corporation - Joensuunkatu 7 - P.O.Box 86 - Salo NA 24101 - FINLAND - - A8-45-E9 (hex) Firich Enterprises CO., LTD. - A845E9 (base 16) Firich Enterprises CO., LTD. - 10F., No. 75, Sec. 1, Xintai 5th Rd., Xizhi Dist. - New Taipei City Taiwan (R.O.C.) 886 - TAIWAN, PROVINCE OF CHINA - - A8-49-A5 (hex) Lisantech Co., Ltd. - A849A5 (base 16) Lisantech Co., Ltd. - 1108, STX V-Tower Gasan-dong - Geumcheon-gu - Seoul 153-803 - KOREA, REPUBLIC OF - - A8-54-B2 (hex) Wistron Neweb Corp. - A854B2 (base 16) Wistron Neweb Corp. - 20 Park Avenue II, Hsinchu Science Park,Hsinchu 308, Taiwan, R.O.C. - Hsinchu Taiwan 308 - TAIWAN, PROVINCE OF CHINA - - A8-55-6A (hex) Pocketnet Technology Inc. - A8556A (base 16) Pocketnet Technology Inc. - Suite B, 7F., No. 550, Ruie Kwang Rd., Neihu District, - Taipei 11429 - TAIWAN, PROVINCE OF CHINA - - A8-57-4E (hex) TP-LINK TECHNOLOGIES CO.,LTD. - A8574E (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4) - Central Science and Technology Park, - Shennan Road,Nanshan, Shenzhen Guangdong 518057 - CHINA - - A8-5B-78 (hex) Apple - A85B78 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-5B-B0 (hex) Shenzhen Dehoo Technology Co.,Ltd - A85BB0 (base 16) Shenzhen Dehoo Technology Co.,Ltd - 5C,Tianzhan Building Tianan Cyberpark, - Futian district - ShenZhen Guang Dong 518040 - CHINA - - A8-5B-F3 (hex) Audivo GmbH - A85BF3 (base 16) Audivo GmbH - Irrenloher Damm 17 - Schwarzenfeld 92521 - GERMANY - - A8-61-AA (hex) Cloudview Limited - A861AA (base 16) Cloudview Limited - Kingsway House - Havilland Street - St Peter Port Guernsey GY1 2QE - UNITED KINGDOM - - A8-62-A2 (hex) JIWUMEDIA CO., LTD. - A862A2 (base 16) JIWUMEDIA CO., LTD. - #902, Daerug Techno Town 13'th, 664 - Gasan-dong - Geumcheon-gu Seoul 153-803 - KOREA, REPUBLIC OF - - A8-63-DF (hex) DISPLAIRE CORPORATION - A863DF (base 16) DISPLAIRE CORPORATION - 1300 Valley House Dr, Ste 100 - Rohnert Park CA 94928 - UNITED STATES - - A8-63-F2 (hex) Texas Instruments - A863F2 (base 16) Texas Instruments - 12203 S.W.Freeway, MS728 - Stafford Texas 77477 - UNITED STATES - - A8-64-05 (hex) nimbus 9, Inc - A86405 (base 16) nimbus 9, Inc - 29 W. Cimarron St. - STE3 - Colorado Springs CO 80903 - UNITED STATES - - A8-65-B2 (hex) DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED - A865B2 (base 16) DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED - 3rd floor, B# Building ,Houdefu Logistics Park,Qingshuiao, - Jianshazhou,Wanjiang District - Dongguan Guangdong 523062 - CHINA - - A8-66-7F (hex) Apple, Inc. - A8667F (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-6A-6F (hex) RIM - A86A6F (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 5R9 - CANADA - - A8-70-A5 (hex) UniComm Inc. - A870A5 (base 16) UniComm Inc. - 7F-7, No. 716, Chung-Cheng Road, - Chung-Ho City Taipei Hsien 23500 - TAIWAN, PROVINCE OF CHINA - - A8-75-D6 (hex) FreeTek International Co., Ltd. - A875D6 (base 16) FreeTek International Co., Ltd. - Unit D, 15/F, Tai Ping Ind.Ctr., Blk 2 - 55 Ting Kok Rd. - HonTai Po 1111 - HONG KONG - - A8-75-E2 (hex) Aventura Technologies, Inc. - A875E2 (base 16) Aventura Technologies, Inc. - 180 Adams Avenue - Hauppauge NY 11788 - UNITED STATES - - A8-77-6F (hex) Zonoff - A8776F (base 16) Zonoff - 70E Swedesford Rd - Malvern PA 19355 - UNITED STATES - - A8-7B-39 (hex) Nokia Corporation - A87B39 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90570 - FINLAND - - A8-7C-01 (hex) Samsung Elec Co.,Ltd - A87C01 (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A8-7E-33 (hex) Nokia Danmark A/S - A87E33 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - A8-80-38 (hex) ShenZhen MovingComm Technology Co., Limited - A88038 (base 16) ShenZhen MovingComm Technology Co., Limited - 5F, FuXinFa Industrial Park, LiuXianDong Industrial Zone, - XiLi Town, NanShan District, - ShenZhen GuangDong 518055 - CHINA - - A8-81-F1 (hex) BMEYE B.V. - A881F1 (base 16) BMEYE B.V. - Hoogoorddreef 60 - Amsterdam 1101BE - NETHERLANDS - - A8-82-7F (hex) CIBN Oriental Network(Beijing) CO.,Ltd - A8827F (base 16) CIBN Oriental Network(Beijing) CO.,Ltd - Floor 18B,Block B(International Resources Building),No.18B(Wanda Plaza),Shijingshan Road,Shijingshan,Beijing(100043) - Beijing Beijing 100043 - CHINA - - A8-86-DD (hex) Apple, Inc. - A886DD (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-87-92 (hex) Broadband Antenna Tracking Systems - A88792 (base 16) Broadband Antenna Tracking Systems - 8902 Vincennes Circle, Suite D-2 - Indianapolis IN 46268 - UNITED STATES - - A8-87-ED (hex) ARC Wireless LLC - A887ED (base 16) ARC Wireless LLC - 6330 N. Washington St. - STE 13 - Denver CO 80216 - UNITED STATES - - A8-88-08 (hex) Apple - A88808 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-8C-EE (hex) MicroMade Galka i Drozdz sp.j. - A88CEE (base 16) MicroMade Galka i Drozdz sp.j. - ul. Wieniawskiego 16 - Pila Wielkopolskie 64-920 - POLAND - - A8-8D-7B (hex) SunDroid Global limited. - A88D7B (base 16) SunDroid Global limited. - Room 1305B, Fiyta Science Building, - Gao Xin South Ave 1, Nanshan District, - Shenzhen Guang Dong 518057 - CHINA - - A8-8E-24 (hex) Apple - A88E24 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-90-08 (hex) Beijing Yuecheng Technology Co. Ltd. - A89008 (base 16) Beijing Yuecheng Technology Co. Ltd. - Room 1601, Floor 16 - Tian Zuo International Tower - ZhongGuanCun South Street Beijing 100000 - CHINA - - A8-92-2C (hex) LG Electronics - A8922C (base 16) LG Electronics - 60-39 , Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - A8-93-E6 (hex) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD - A893E6 (base 16) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD - 5F,301building,Tairan High-tech park, Chegongmiao,Futian zone, - SHENZHEN GUANGDONG 518000 - CHINA - - A8-95-B0 (hex) Aker Subsea Ltd - A895B0 (base 16) Aker Subsea Ltd - Kiekhill Industrial Estate - Dyce - Aberdeen AB51 3XA - UNITED KINGDOM - - A8-96-8A (hex) Apple - A8968A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-97-DC (hex) IBM - A897DC (base 16) IBM - 4400 North First Street - San Jose CA 95134 - UNITED STATES - - A8-98-C6 (hex) Shinbo Co., Ltd. - A898C6 (base 16) Shinbo Co., Ltd. - 203-14, Anyang 7-Dong, Manan-Gu - Anyang-Si Kyungki-Do 430-817 - KOREA, REPUBLIC OF - - A8-99-5C (hex) aizo ag - A8995C (base 16) aizo ag - Brandstrasse 33 - Schlieren 8952 - SWITZERLAND - - A8-9B-10 (hex) inMotion Ltd. - A89B10 (base 16) inMotion Ltd. - Unit 2709 Exchange Tower - 33 Wang Chui Road · Kowloon Bay · KLN - KLN - HONG KONG - - A8-9D-21 (hex) Cisco - A89D21 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - A8-9D-D2 (hex) Shanghai DareGlobal Technologies Co., Ltd - A89DD2 (base 16) Shanghai DareGlobal Technologies Co., Ltd - 22F Info-Tech Building - No.1555 Kongjiang Road - Shanghai Shanghai 200092 - CHINA - - A8-9F-BA (hex) Samsung Electronics Co.,Ltd - A89FBA (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A8-A6-68 (hex) zte corporation - A8A668 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - A8-AD-3D (hex) Alcatel-Lucent Shanghai Bell Co., Ltd - A8AD3D (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd - No.389 Ningqiao Road,Pudong,Jingqiao,Shanghai, P.R. - Shanghai Shanghai 201206 - CHINA - - A8-B0-AE (hex) LEONI - A8B0AE (base 16) LEONI - 3945 Freedom Circle - Suite 550 - Santa Clara California 95054 - UNITED STATES - - A8-B1-D4 (hex) CISCO SYSTEMS, INC. - A8B1D4 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - A8-B9-B3 (hex) ESSYS - A8B9B3 (base 16) ESSYS - Daerung Post Tower 5 15F - 60-3 - Seoul Gasan-Dong, Geumchen-gu 153-702 - KOREA, REPUBLIC OF - - A8-BB-CF (hex) Apple - A8BBCF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-BD-1A (hex) Honey Bee (Hong Kong) Limited - A8BD1A (base 16) Honey Bee (Hong Kong) Limited - Flat L, 12/F., Phase 4, Kwun Tong Industrial Ctr., - 436-446 Kwun Tong Road, Kwun Tong - HONG KONG - - A8-BD-3A (hex) UNIONMAN TECHNOLOGY CO.,LTD - A8BD3A (base 16) UNIONMAN TECHNOLOGY CO.,LTD - 18F, HUAYANG TOWER,YANDAYI ROAD - Huizhou Guangdong 516007 - CHINA - - A8-C2-22 (hex) TM-Research Inc. - A8C222 (base 16) TM-Research Inc. - Hiyoshi Honcho 1-15-4 - Kohoku-ku - Yokohama Kanagawa 223-0062 - JAPAN - - A8-CB-95 (hex) EAST BEST CO., LTD. - A8CB95 (base 16) EAST BEST CO., LTD. - 4F,NO.98,SHING TEH ROAD - SAN CHUNG CITY TAIPEI 241 - TAIWAN, PROVINCE OF CHINA - - A8-CC-C5 (hex) Saab AB (publ) - A8CCC5 (base 16) Saab AB (publ) - Nobymalmsvagen - Linkoping SE-581 82 - SWEDEN - - A8-CE-90 (hex) CVC - A8CE90 (base 16) CVC - No.361,Renhua Rd., - Dali City Taichung 412 - TAIWAN, PROVINCE OF CHINA - - A8-D0-E3 (hex) Systech Electronics Ltd. - A8D0E3 (base 16) Systech Electronics Ltd. - Lever Tech Centre, 69-71 King Yip Street, - Kwun Tong, Kowloon, Hong Kong - 852 - HONG KONG - - A8-D0-E5 (hex) Juniper Networks - A8D0E5 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - A8-D2-36 (hex) Lightware Visual Engineering - A8D236 (base 16) Lightware Visual Engineering - Peterdy utca 15. - Budapest H-1071 - HUNGARY - - A8-D3-C8 (hex) Wachendorff Elektronik GmbH & Co. KG - A8D3C8 (base 16) Wachendorff Elektronik GmbH & Co. KG - Industriestraße 7 - Geisenheim 65366 - GERMANY - - A8-D4-09 (hex) USA 111 Inc - A8D409 (base 16) USA 111 Inc - 5885 Green Pointe Drive - Suite B - Groveport Ohio 43125 - UNITED STATES - - A8-D8-8A (hex) Wyconn - A8D88A (base 16) Wyconn - Rennweg 97-99 - Vienna - 1030 - AUSTRIA - - A8-E0-18 (hex) Nokia Corporation - A8E018 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - A8-E3-EE (hex) Sony Computer Entertainment Inc. - A8E3EE (base 16) Sony Computer Entertainment Inc. - 2-6-21 Minami-Aoyama - Minato-ku Tokyo 107-0062 - JAPAN - - A8-E5-39 (hex) Moimstone Co.,Ltd - A8E539 (base 16) Moimstone Co.,Ltd - 4F, 954-9 Gwanyang-dong - Dongan-Gu - Anyang-Si Gyeonggi-do 431-060 - KOREA, REPUBLIC OF - - A8-EF-26 (hex) Tritonwave - A8EF26 (base 16) Tritonwave - 795 Lakeshore Dr, Suite 307 - Dorval, QC H9S 0A8 - Quebec H9S 0A8 - CANADA - - A8-F0-38 (hex) SHEN ZHEN SHI JIN HUA TAI ELECTRONICS CO.,LTD - A8F038 (base 16) SHEN ZHEN SHI JIN HUA TAI ELECTRONICS CO.,LTD - Room A,Forth Floor,Building B,Hengmingzhu Industrial Park,Xixiang Forist and Fruit Bureau,Qianjin Road, Baoan District,Shenzhen city,Guangdong provice - 518126 - CHINA - - A8-F2-74 (hex) Samsung Electronics - A8F274 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - A8-F4-70 (hex) Fujian Newland Communication Science Technologies Co.,Ltd. - A8F470 (base 16) Fujian Newland Communication Science Technologies Co.,Ltd. - Newland Science & Technology Park No.1 Rujiang West Rd., Mawei, - Fuzhou Fujian 350015 - CHINA - - A8-F7-E0 (hex) PLANET Technology Corporation - A8F7E0 (base 16) PLANET Technology Corporation - 11F, No. 96, Min Quan Road, - Xin Dian Dist., - New Taipei City 22341 - TAIWAN, PROVINCE OF CHINA - - A8-F9-4B (hex) Eltex Enterprise Ltd. - A8F94B (base 16) Eltex Enterprise Ltd. - Obyedineniya st., 9 - Novosibirsk 630020 - RUSSIAN FEDERATION - - A8-FA-D8 (hex) Apple - A8FAD8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - A8-FB-70 (hex) WiseSec L.t.d - A8FB70 (base 16) WiseSec L.t.d - 145 yaffo ST. - Haifa Israel 37503 - ISRAEL - - A8-FC-B7 (hex) Consolidated Resource Imaging - A8FCB7 (base 16) Consolidated Resource Imaging - 2943 S Wilson CT NW - Grand Rapids MI 49534 - UNITED STATES - - AA-00-00 (hex) DIGITAL EQUIPMENT CORPORATION - AA0000 (base 16) DIGITAL EQUIPMENT CORPORATION - LKG 1-2/A19 - 550 KING STREET - LITTLETON MA 01460-1289 - UNITED STATES - - AA-00-01 (hex) DIGITAL EQUIPMENT CORPORATION - AA0001 (base 16) DIGITAL EQUIPMENT CORPORATION - LKG 1-2/A19 - 550 KING STREET - LITTLETON MA 01460-1289 - UNITED STATES - - AA-00-02 (hex) DIGITAL EQUIPMENT CORPORATION - AA0002 (base 16) DIGITAL EQUIPMENT CORPORATION - LKG 1-2/A19 - 550 KING STREET - LITTLETON MA 01460-1289 - UNITED STATES - - AA-00-03 (hex) DIGITAL EQUIPMENT CORPORATION - AA0003 (base 16) DIGITAL EQUIPMENT CORPORATION - LKG 1-2/A19 - 550 KING STREET - LITTLETON MA 01460-1289 - UNITED STATES - - AA-00-04 (hex) DIGITAL EQUIPMENT CORPORATION - AA0004 (base 16) DIGITAL EQUIPMENT CORPORATION - LKG 1-2/A19 - 550 KING STREET - LITTLETON MA 01460-1289 - UNITED STATES - - AC-01-42 (hex) Uriel Technologies SIA - AC0142 (base 16) Uriel Technologies SIA - Dzerbenes iela 14 - Riga LV-1006 - LATVIA - - AC-02-CA (hex) HI Solutions, Inc. - AC02CA (base 16) HI Solutions, Inc. - 4105 Royal Drive - Suite 100 - Kennesaw GA 30144 - UNITED STATES - - AC-02-CF (hex) RW Tecnologia Industria e Comercio Ltda - AC02CF (base 16) RW Tecnologia Industria e Comercio Ltda - Centro Empresarial Paulo Frederico de Toledo, 80 A - Bairro Arco Irirs - Santa Rita do Sapucai Minas Gerais 37540000 - BRAZIL - - AC-02-EF (hex) Comsis - AC02EF (base 16) Comsis - 3 rue Broussais - Paris 75014 - FRANCE - - AC-06-13 (hex) Senselogix Ltd - AC0613 (base 16) Senselogix Ltd - 56 Carlton Court, Ford William Morgan - St. Asaph Business Park - St. Asaph Debighshire LL17 0JG - UNITED KINGDOM - - AC-0A-61 (hex) Labor S.r.L. - AC0A61 (base 16) Labor S.r.L. - Via della Scrofa 117 - Rome 00186 - ITALY - - AC-0D-FE (hex) Ekon GmbH - myGEKKO - AC0DFE (base 16) Ekon GmbH - myGEKKO - Rienzfeldstraße 30 - Bruneck Südtirol (BZ) 39031 - ITALY - - AC-11-D3 (hex) Suzhou HOTEK Video Technology Co. Ltd - AC11D3 (base 16) Suzhou HOTEK Video Technology Co. Ltd - No.78,Keling Road,Suzhou National new and hi-tech industrial Development zone - Suzhou Jiangsu 215200 - CHINA - - AC-14-61 (hex) ATAW Co., Ltd. - AC1461 (base 16) ATAW Co., Ltd. - Dongan-gu Pyeongchon-dong 126-1 - Doosan Venture Digm#531 - Anyang-si Gyeonggi-do 431-755 - KOREA, REPUBLIC OF - - AC-14-D2 (hex) wi-daq, inc. - AC14D2 (base 16) wi-daq, inc. - 850 NW Federal Hwy - Suite 129 - Stuart Florida 34994 - UNITED STATES - - AC-16-2D (hex) Hewlett Packard - AC162D (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - AC-17-02 (hex) Fibar Group sp. z o.o. - AC1702 (base 16) Fibar Group sp. z o.o. - ul. Lotnicza 1 - Poznan 60-421 - POLAND - - AC-18-26 (hex) SEIKO EPSON CORPORATION - AC1826 (base 16) SEIKO EPSON CORPORATION - 3-3-5 OWA - SUWA-SHI NAGANO-KEN 392-8502 - JAPAN - - AC-19-9F (hex) SUNGROW POWER SUPPLY CO.,LTD. - AC199F (base 16) SUNGROW POWER SUPPLY CO.,LTD. - NO.2 Tianhu Road, New and High Technology Industrial Development Zone - Hefei Anhui 230088 - CHINA - - AC-20-AA (hex) DMATEK Co., Ltd. - AC20AA (base 16) DMATEK Co., Ltd. - 11F.-2, No.386, Shizheng Rd., Xitun Dist., - Taichung 40757 - TAIWAN, PROVINCE OF CHINA - - AC-22-0B (hex) ASUSTek COMPUTER INC. - AC220B (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - AC-29-3A (hex) Apple Inc - AC293A (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - AC-2D-A3 (hex) TXTR GmbH - AC2DA3 (base 16) TXTR GmbH - Rosenthaler Str. 13 - Berlin 10119 - GERMANY - - AC-2F-A8 (hex) Humannix Co.,Ltd. - AC2FA8 (base 16) Humannix Co.,Ltd. - #402, 98-4, Songpa-Dong, Songpa-Gu - Seoul 138-170 - KOREA, REPUBLIC OF - - AC-31-9D (hex) Shenzhen TG-NET Botone Technology Co.,Ltd. - AC319D (base 16) Shenzhen TG-NET Botone Technology Co.,Ltd. - 2nd floor,Building No.6,Pengtengda industrial zone,Huarong road,Dalang Street Office, - Longhua Town - Shenzhen Guangdong 518109 - CHINA - - AC-34-CB (hex) Shanhai GBCOM Communication Technology Co. Ltd - AC34CB (base 16) Shanhai GBCOM Communication Technology Co. Ltd - Room 602, Building 6, No.555 Dongchuan Road - Shanghai 200241 - CHINA - - AC-36-13 (hex) Samsung Electronics Co.,Ltd - AC3613 (base 16) Samsung Electronics Co.,Ltd - Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - AC-38-70 (hex) Lenovo Mobile Communication Technology Ltd. - AC3870 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999, Qishan North 2nd Road, Information & Optoelectronics Park, - Torch Hi-tech Industry Development Zone - Xiamen Fujian 361006 - CHINA - - AC-3A-7A (hex) Roku - AC3A7A (base 16) Roku - 12980 Saratoga Ave - Suite D - Saratoga California 95070 - UNITED STATES - - AC-3C-0B (hex) Apple - AC3C0B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - AC-3C-B4 (hex) Nilan A/S - AC3CB4 (base 16) Nilan A/S - Nilanvej 2 - Hedensted 8722 - DENMARK - - AC-3D-05 (hex) Instorescreen Aisa - AC3D05 (base 16) Instorescreen Aisa - Room 207, North Bldg,No 28 - Lane 411, Shilong Road - Shanghai 200237 - CHINA - - AC-3D-75 (hex) HANGZHOU ZHIWAY TECHNOLOGIES CO.,LTD. - AC3D75 (base 16) HANGZHOU ZHIWAY TECHNOLOGIES CO.,LTD. - FLOOR12B,BUILDING E,PARADISE SOFTWARE PARK,NO.3 XIDOUMEN ROAD, - WESTLAKE DISTRICT, - HANGZHOU ZHEJIANG 310012 - CHINA - - AC-3F-A4 (hex) TAIYO YUDEN CO.,LTD - AC3FA4 (base 16) TAIYO YUDEN CO.,LTD - 8-1, Sakae-cho - Takasaki-shi Gunma 370-8522 - JAPAN - - AC-40-EA (hex) C&T Solution Inc. - AC40EA (base 16) C&T Solution Inc. - 12F-1, No.700, Zhongzheng Rd., Zhonghe Dist. - New Taipei City Taiwan 235 - TAIWAN, PROVINCE OF CHINA - - AC-41-22 (hex) Eclipse Electronic Systems Inc. - AC4122 (base 16) Eclipse Electronic Systems Inc. - 17111 Waterview Parkway - Dallas TX 75252 - UNITED STATES - - AC-44-F2 (hex) Revolabs Inc - AC44F2 (base 16) Revolabs Inc - 63 Great Rd - Maynard MA 01754 - UNITED STATES - - AC-47-23 (hex) Genelec - AC4723 (base 16) Genelec - Olvitie 5 - Iisalmi 74100 - FINLAND - - AC-4A-FE (hex) Hisense Broadband Multimedia Technology Co.,Ltd. - AC4AFE (base 16) Hisense Broadband Multimedia Technology Co.,Ltd. - No.11 Jiangxi Road,Shinan District - Qingdao City Shandong Province 266071 - CHINA - - AC-4B-C8 (hex) Juniper Networks - AC4BC8 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - AC-4E-91 (hex) HUAWEI TECHNOLOGIES CO.,LTD - AC4E91 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4-A52R,Huawei Industrial Base - Bantian Longgang - Shenzhen GuangDong 518129 - CHINA - - AC-4F-FC (hex) SVS-VISTEK GmbH - AC4FFC (base 16) SVS-VISTEK GmbH - Muehlbachstraße 20 - Seefeld BY 82229 - GERMANY - - AC-50-36 (hex) Pi-Coral Inc - AC5036 (base 16) Pi-Coral Inc - 2130 Gold St - Suite 200 - San Jose CA 95002-1177 - UNITED STATES - - AC-51-35 (hex) MPI TECH - AC5135 (base 16) MPI TECH - Vadstrupvej 35 - Bagsværd DK-2880 - DENMARK - - AC-51-EE (hex) Cambridge Communication Systems Ltd - AC51EE (base 16) Cambridge Communication Systems Ltd - Sheraton House - Castle Park - Cambridge Cambridgeshire CB3 0AX - UNITED KINGDOM - - AC-54-EC (hex) IEEE P1823 Standards Working Group - AC54EC (base 16) IEEE P1823 Standards Working Group - 445 Hoes Lane - Piscataway NJ 08854 - UNITED STATES - - AC-56-2C (hex) LAVA INTERNATIONAL(H.K) LIMITED - AC562C (base 16) LAVA INTERNATIONAL(H.K) LIMITED - UNIT L 1/F MAU LAM COMM BLDG 16-18 - MAU LAM ST, JORDAN KL, HK - Hong Kong - CHINA - - AC-58-3B (hex) Human Assembler, Inc. - AC583B (base 16) Human Assembler, Inc. - 2-1-11-6F - Shibuya - Shibuya-ku Tokyo 150-0002 - JAPAN - - AC-5A-14 (hex) Samsung Electronics Co.,Ltd - AC5A14 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - AC-5D-10 (hex) Pace Americas - AC5D10 (base 16) Pace Americas - 1764 Automation Parkway - San Jose Ca 95131 - UNITED STATES - - AC-5E-8C (hex) Utillink - AC5E8C (base 16) Utillink - 817 Woolim Lions Valley 1, 311-3 Sangdaewon-dong Jungwon-gu - Seongnam-si Gyeonggi-do 462160 - KOREA, REPUBLIC OF - - AC-61-23 (hex) Drivven, Inc. - AC6123 (base 16) Drivven, Inc. - 12001 Network Boulevard - Building E, Suite 110 - San Antonio TX 78249 - UNITED STATES - - AC-62-0D (hex) Jabil Circuit (Wuxi) Co. LTD - AC620D (base 16) Jabil Circuit (Wuxi) Co. LTD - Lot J9, J10 Export Processing Zone - Wuxi City Jiangsu 214028 - CHINA - - AC-67-06 (hex) Ruckus Wireless - AC6706 (base 16) Ruckus Wireless - 880 West Maude Ave. - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - AC-6B-AC (hex) Jenny Science AG - AC6BAC (base 16) Jenny Science AG - Sandblatte 7a - Rain Luzern 6026 - SWITZERLAND - - AC-6E-1A (hex) Shenzhen Gongjin Electronics Co.,Ltd - AC6E1A (base 16) Shenzhen Gongjin Electronics Co.,Ltd - B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 Nanshan Medical Instrument Industry Park, - 1019# Nanhai Road,Nanshan District - Shenzhen Guangdong 518067 - CHINA - - AC-6F-4F (hex) Enspert Inc - AC6F4F (base 16) Enspert Inc - 2F., Daehwa B/D, - 169 Samsung-dong, Gangnam-gu - Seoul 135090 - KOREA, REPUBLIC OF - - AC-6F-BB (hex) TATUNG Technology Inc. - AC6FBB (base 16) TATUNG Technology Inc. - 22, Chungshan N. Rd., 3rd Sec., - Taipei 104 - TAIWAN, PROVINCE OF CHINA - - AC-6F-D9 (hex) Valueplus Inc. - AC6FD9 (base 16) Valueplus Inc. - #803, Sicox Tower, 513-14 - Sangdaewon-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-806 - KOREA, REPUBLIC OF - - AC-72-36 (hex) Lexking Technology Co., Ltd. - AC7236 (base 16) Lexking Technology Co., Ltd. - 2F, No. 3, Baoqiang Road, - Xindian Dist. - New Taipei City 231111 - TAIWAN, PROVINCE OF CHINA - - AC-72-89 (hex) Intel Corporate - AC7289 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - AC-7A-42 (hex) iConnectivity - AC7A42 (base 16) iConnectivity - #21, 1725 30th Ave NE - Calgary Alberta T2E 7P6 - CANADA - - AC-7A-4D (hex) ALPS ELECTRIC CO.,LTD. - AC7A4D (base 16) ALPS ELECTRIC CO.,LTD. - 6-1 - NISHIDA - KAKUDA-CITY MIYAGI-PREF 981-1595 - JAPAN - - AC-7B-A1 (hex) Intel Corporate - AC7BA1 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - AC-7F-3E (hex) Apple - AC7F3E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - AC-80-D6 (hex) Hexatronic AB - AC80D6 (base 16) Hexatronic AB - Exportgatan 47B - Gothenburg 42246 - SWEDEN - - AC-81-12 (hex) Gemtek Technology Co., Ltd. - AC8112 (base 16) Gemtek Technology Co., Ltd. - No. 1 Jen Ai Road Hsinchu Industrial Park Hukou, - No. 15-1 Zhonghua Road, - Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - AC-81-F3 (hex) Nokia Corporation - AC81F3 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - AC-83-17 (hex) Shenzhen Furtunetel Communication Co., Ltd - AC8317 (base 16) Shenzhen Furtunetel Communication Co., Ltd - F19 building A zhongke plaza Nan yi street high-tech zone, Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - AC-83-F0 (hex) ImmediaTV Corporation - AC83F0 (base 16) ImmediaTV Corporation - 2005 De La Cruz Blvd - Suite 150 - Santa Clara California 95050 - UNITED STATES - - AC-85-3D (hex) HUAWEI TECHNOLOGIES CO.,LTD - AC853D (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - Shenzhen Guangdong 518129 - CHINA - - AC-86-74 (hex) Open Mesh, Inc. - AC8674 (base 16) Open Mesh, Inc. - 5837 NW Skyline Blvd - Portland OR 97229 - UNITED STATES - - AC-86-7E (hex) Create New Technology (HK) Limited Company - AC867E (base 16) Create New Technology (HK) Limited Company - Rm B 10/F JinFeng Building,1001 ShangBu South Road,FuTian District - Shen Zhen Guang Dong 518031 - CHINA - - AC-87-A3 (hex) Apple - AC87A3 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - AC-8A-CD (hex) ROGER D.Wensker, G.Wensker sp.j. - AC8ACD (base 16) ROGER D.Wensker, G.Wensker sp.j. - Gosciszewo 59 - Sztum Pomorskie 82-400 - POLAND - - AC-8D-14 (hex) Smartrove Inc - AC8D14 (base 16) Smartrove Inc - 19630 Allendale Ave. - PO Box 2536 - Saratoga CA 95070 - UNITED STATES - - AC-93-2F (hex) Nokia Corporation - AC932F (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - AC-94-03 (hex) Envision Peripherals Inc - AC9403 (base 16) Envision Peripherals Inc - 47490 Seabridge Dr - Fremont California 94538 - UNITED STATES - - AC-9A-96 (hex) Lantiq Deutschland GmbH - AC9A96 (base 16) Lantiq Deutschland GmbH - Am Campeon 3 - Neubiberg Bavaria 85579 - GERMANY - - AC-9B-0A (hex) Sony Corporation - AC9B0A (base 16) Sony Corporation - 1-7-1 Konan - Minato-ku Tokyo 108-0075 - JAPAN - - AC-9B-84 (hex) Smak Tecnologia e Automacao - AC9B84 (base 16) Smak Tecnologia e Automacao - Av. Sto. Antonio, 201 - Bela Vista - Osasco São Paulo CEP 06086-075 - BRAZIL - - AC-9C-E4 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd - AC9CE4 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd - No. 389, Ningqiao Road, Pudong Jinqiao, - Shanghai 201206 - CHINA - - AC-9E-17 (hex) ASUSTek COMPUTER INC. - AC9E17 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - AC-A0-16 (hex) CISCO SYSTEMS, INC. - ACA016 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - AC-A2-13 (hex) Shenzhen Bilian electronic CO.,LTD - ACA213 (base 16) Shenzhen Bilian electronic CO.,LTD - NO 268,Fuqian Rd,Jutang Community - Guanlan Town, BaoAn District - shenzhen guangdong 518110 - CHINA - - AC-A2-2C (hex) Baycity Technologies Ltd - ACA22C (base 16) Baycity Technologies Ltd - 10 Nazareth Ave - P O Box 1497 - Christchurch Canterbury 8024 - NEW ZEALAND - - AC-A3-1E (hex) Aruba Networks - ACA31E (base 16) Aruba Networks - 1344 Crossman Drive - Sunnyvale CA 94089 - UNITED STATES - - AC-A4-30 (hex) Peerless AV - ACA430 (base 16) Peerless AV - 2300 White Oak Circle - Aurora illinios 60502 - UNITED STATES - - AC-A9-19 (hex) TrekStor GmbH - ACA919 (base 16) TrekStor GmbH - Kastanienallee 8-10 - Lorsch Hessen 64653 - GERMANY - - AC-A9-A0 (hex) Audioengine, Ltd. - ACA9A0 (base 16) Audioengine, Ltd. - 1535 Dido Mt Salem Rd - Ackerman Ms 39735 - UNITED STATES - - AC-AB-8D (hex) Lyngso Marine A/S - ACAB8D (base 16) Lyngso Marine A/S - Lyngso Alle 2 - Horsholm DK-2970 - DENMARK - - AC-AB-BF (hex) AthenTek Inc. - ACABBF (base 16) AthenTek Inc. - 8F., No.356, Sec. 1, Neihu Rd - Neihu Dist., - Taipei City Taiwan 114 - TAIWAN, PROVINCE OF CHINA - - AC-B3-13 (hex) ARRIS Group, Inc. - ACB313 (base 16) ARRIS Group, Inc. - 3871 Lakfield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - AC-B5-7D (hex) Liteon Technology Corporation - ACB57D (base 16) Liteon Technology Corporation - 4F, 90, Chien 1 Road - Chung Ho - New Taipei City Taiwan 23585 - TAIWAN, PROVINCE OF CHINA - - AC-B7-4F (hex) METEL s.r.o. - ACB74F (base 16) METEL s.r.o. - Zizkuv Kopec 617 - Ceska Skalice NA 55203 - CZECH REPUBLIC - - AC-B8-59 (hex) Uniband Electronic Corp, - ACB859 (base 16) Uniband Electronic Corp, - 6F-1 No. Dongguang Rd., - Hsinchu 300 300 - TAIWAN, PROVINCE OF CHINA - - AC-BD-0B (hex) IMAC CO.,LTD - ACBD0B (base 16) IMAC CO.,LTD - Sazukawa-cho 1551 - Moriyama-shi Shiga-ken 524-0215 - JAPAN - - AC-BE-75 (hex) Ufine Technologies Co.,Ltd. - ACBE75 (base 16) Ufine Technologies Co.,Ltd. - 46, Geumgok-dong, Bundang-gu - Seong-nam-si Gyeonggi-do 463-804 - KOREA, REPUBLIC OF - - AC-BE-B6 (hex) Visualedge Technology Co., Ltd. - ACBEB6 (base 16) Visualedge Technology Co., Ltd. - 13FL.-1 No. 716, Zhongzheng Road, Zhonghe City, - Taipei County, 23511 - TAIWAN, PROVINCE OF CHINA - - AC-C2-EC (hex) CLT INT'L IND. CORP. - ACC2EC (base 16) CLT INT'L IND. CORP. - 11F-2, NO.1, ZHANQIAN - MIAOLI 36043 - TAIWAN, PROVINCE OF CHINA - - AC-C5-95 (hex) Graphite Systems - ACC595 (base 16) Graphite Systems - 2037 Landings Drive - Mountain View California 94043 - UNITED STATES - - AC-C6-98 (hex) Kohzu Precision Co., Ltd. - ACC698 (base 16) Kohzu Precision Co., Ltd. - 2-6-15, Kurigi, Asao-ku - Kawasaki-shi Kanagawa 215-8521 - JAPAN - - AC-C7-3F (hex) VITSMO CO., LTD. - ACC73F (base 16) VITSMO CO., LTD. - RM1418-1419, HansinIntervalley 24 Bldg. - 322 Teheranro Gangnamgu - SEOUL 135-918 - KOREA, REPUBLIC OF - - AC-C9-35 (hex) Ness Corporation - ACC935 (base 16) Ness Corporation - 4/167 Prospect Highway - Seven Hills - Sydney NSW 2147 - AUSTRALIA - - AC-CA-54 (hex) Telldus Technologies AB - ACCA54 (base 16) Telldus Technologies AB - Skiffervägen 102 - Lund 224 78 - SWEDEN - - AC-CA-8E (hex) ODA Technologies - ACCA8E (base 16) ODA Technologies - 607-A Woorim Lions Valley, #425 - Chungchun Dong, Bupyung Gu - Incheon KSXX0009 - KOREA, REPUBLIC OF - - AC-CA-AB (hex) Virtual Electric Inc - ACCAAB (base 16) Virtual Electric Inc - 1314 Vanna Ct - San Jose CA 95131 - UNITED STATES - - AC-CA-BA (hex) Midokura Co., Ltd. - ACCABA (base 16) Midokura Co., Ltd. - 7th Floor Azabudai Hinoki building - 3-1-5 Azabudai Minato-ku - Tokyo 106-0041 - JAPAN - - AC-CB-09 (hex) Hefcom Metering (Pty) Ltd - ACCB09 (base 16) Hefcom Metering (Pty) Ltd - PO Box 10770 - Centurion Gauteng 0046 - SOUTH AFRICA - - AC-CC-8E (hex) Axis Communications AB - ACCC8E (base 16) Axis Communications AB - Emdalavägen 14 - LUND 22369 - SWEDEN - - AC-CE-8F (hex) HWA YAO TECHNOLOGIES CO., LTD - ACCE8F (base 16) HWA YAO TECHNOLOGIES CO., LTD - NO. 6, LN. 48, NANSING RD., - YONGKANG CITY, TAINAN COUNTY 710 - TAIWAN, PROVINCE OF CHINA - - AC-CF-23 (hex) Hi-flying electronics technology Co.,Ltd - ACCF23 (base 16) Hi-flying electronics technology Co.,Ltd - Room B101,456 BiBo Raod,PuDong - Shanghai 201200 - CHINA - - AC-CF-5C (hex) Apple - ACCF5C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - AC-D0-74 (hex) Espressif Inc. - ACD074 (base 16) Espressif Inc. - A207-1, 456 Bibo Road, Zhangjiang High-tech Park,Shanghai 201203, China - Shanghai Shanghai 201203 - CHINA - - AC-D1-80 (hex) Crexendo Business Solutions, Inc. - ACD180 (base 16) Crexendo Business Solutions, Inc. - 10201 S. 5st St. - Suite A-265 - Phoenix AZ 85044 - UNITED STATES - - AC-D1-B8 (hex) Hon Hai Precision Ind. Co.,Ltd. - ACD1B8 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District,Chongqing,China - Chongqing Chongqing 401332 - CHINA - - AC-D3-64 (hex) ABB SPA, ABB SACE DIV. - ACD364 (base 16) ABB SPA, ABB SACE DIV. - V.LE DELL'INDUSTRIA, 18 - VITTUONE MI 20010 - ITALY - - AC-D6-57 (hex) Shaanxi Guolian Digital TV Technology Co., Ltd. - ACD657 (base 16) Shaanxi Guolian Digital TV Technology Co., Ltd. - Chief Building, Fifth Yannan Road, Qujiang New District - xi'an shaanxi 71000 - CHINA - - AC-D9-D6 (hex) tci GmbH - ACD9D6 (base 16) tci GmbH - Ludwig-Rinn-Straße 10-14 - Heuchelheim Hessen 35452 - GERMANY - - AC-DB-DA (hex) Shenzhen Geniatech Inc, Ltd - ACDBDA (base 16) Shenzhen Geniatech Inc, Ltd - 18th F, GDC Building,No.9 ,Gaoxin Central Avenue 3rd - Nanshan District - Shenzhen GuangDong 518057 - CHINA - - AC-DE-48 (hex) PRIVATE - ACDE48 (base 16) - - AC-E0-10 (hex) Liteon Technology Corporation - ACE010 (base 16) Liteon Technology Corporation - 4F, 90, Chien 1 Road, ChungHo - New Taipei City Taiwan 23585 - TAIWAN, PROVINCE OF CHINA - - AC-E0-69 (hex) ISAAC Instruments - ACE069 (base 16) ISAAC Instruments - 240 Frechette - Chambly Quebec J3L2Z5 - CANADA - - AC-E2-15 (hex) Huawei Technologies Co., Ltd - ACE215 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - AC-E3-48 (hex) MadgeTech, Inc - ACE348 (base 16) MadgeTech, Inc - 879 Maple St - Contoocook NH 03229 - UNITED STATES - - AC-E4-2E (hex) SK hynix - ACE42E (base 16) SK hynix - SK u-Tower, 25-1, Jeongja-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-844 - KOREA, REPUBLIC OF - - AC-E6-4B (hex) Shenzhen Baojia Battery Technology Co., Ltd. - ACE64B (base 16) Shenzhen Baojia Battery Technology Co., Ltd. - Block A, Tongfuyu Industrial Zone - Heping Village, Fuyong Town,Baoan District - Shenzhen Guangdong 518013 - CHINA - - AC-E8-7B (hex) Huawei Technologies Co., Ltd - ACE87B (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - AC-E8-7E (hex) Bytemark Computer Consulting Ltd - ACE87E (base 16) Bytemark Computer Consulting Ltd - Unit 2 - Novus Business Park - Opus Avenue York YO26 6BL - UNITED KINGDOM - - AC-E9-7F (hex) IoT Tech Limited - ACE97F (base 16) IoT Tech Limited - 20b Lough Road - Lisburn Antrim BT28 2HA - UNITED KINGDOM - - AC-E9-AA (hex) Hay Systems Ltd - ACE9AA (base 16) Hay Systems Ltd - Watermark - Alba Campus - Livingston West Lothian EH54 7EG - UNITED KINGDOM - - AC-EA-6A (hex) GENIX INFOCOMM CO., LTD. - ACEA6A (base 16) GENIX INFOCOMM CO., LTD. - 2F, Daebo Bldg. #1009-34 - Doksan-Dong, Keumcheon-Gu - Seoul 153-829 - KOREA, REPUBLIC OF - - AC-EE-3B (hex) 6harmonics Inc - ACEE3B (base 16) 6harmonics Inc - 21 Concourse Gate - Suite 10 - Ottawa Ontario K2E 7S4 - CANADA - - AC-F0-B2 (hex) Becker Electronics Taiwan Ltd. - ACF0B2 (base 16) Becker Electronics Taiwan Ltd. - No.32, Lane 30, Long Yuan Rd. - Long-Tan Taoyuan 32544 - TAIWAN, PROVINCE OF CHINA - - AC-F1-DF (hex) D-Link International - ACF1DF (base 16) D-Link International - 1 International Business Park - #03-12, The Synergy - Singapore 609917 - TAIWAN, PROVINCE OF CHINA - - AC-F2-C5 (hex) Cisco - ACF2C5 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - AC-F7-F3 (hex) XIAOMI CORPORATION - ACF7F3 (base 16) XIAOMI CORPORATION - Quanshitiandi Tower A,12th Floor, Jia 50 Wangjing Xilu - Chaoyang Dist - Beijing 100102 - CHINA - - AC-F9-7E (hex) ELESYS INC. - ACF97E (base 16) ELESYS INC. - Suit 623, 812-1, Hyomun-dong - Ulsan Buk-gu 683-360 - KOREA, REPUBLIC OF - - AC-FD-93 (hex) Weifang GoerTek Electronics Co., Ltd. - ACFD93 (base 16) Weifang GoerTek Electronics Co., Ltd. - Gaoxin 2 Road,Free Trade Zone - Weifang Shandong 261205 - CHINA - - AC-FD-CE (hex) Intel Corporate - ACFDCE (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - AC-FD-EC (hex) Apple, Inc - ACFDEC (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B0-00-B4 (hex) Cisco - B000B4 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - B0-05-94 (hex) Liteon Technology Corporation - B00594 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo - New Taipei City - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - B0-08-BF (hex) Vital Connect, Inc. - B008BF (base 16) Vital Connect, Inc. - 900 E HAMILTON AVE STE 500 - CAMPBELL CA 95008-0667 - UNITED STATES - - B0-09-D3 (hex) Avizia - B009D3 (base 16) Avizia - 12018 Sunrise Valley Drive - 150 - Reston VA 20191 - UNITED STATES - - B0-10-41 (hex) Hon Hai Precision Ind. Co.,Ltd. - B01041 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - ,Xiyong Town,Shapingba District, - Chongqing 401332 - CHINA - - B0-12-03 (hex) Dynamics Hong Kong Limited - B01203 (base 16) Dynamics Hong Kong Limited - Room A4, 3/F, Friend's House , No.6A Carnarvon Road, - Tsim Sha Tsui, Kowloon, - 999077 - HONG KONG - - B0-12-66 (hex) Futaba-Kikaku - B01266 (base 16) Futaba-Kikaku - 2-17-20-302 Yanaka - Taito-ku Tokyo 110-0001 - JAPAN - - B0-14-08 (hex) LIGHTSPEED INTERNATIONAL CO. - B01408 (base 16) LIGHTSPEED INTERNATIONAL CO. - No.20, LANE 526 NIUPU East RD. - Hsinchu Not US/Canada 30091 - TAIWAN, PROVINCE OF CHINA - - B0-17-43 (hex) EDISON GLOBAL CIRCUITS LLC - B01743 (base 16) EDISON GLOBAL CIRCUITS LLC - 1475 Sawdust Rd - Ste 3108 - Spring TX 77380-2974 - UNITED STATES - - B0-1B-7C (hex) Ontrol A.S. - B01B7C (base 16) Ontrol A.S. - Turcan Cad No:19 Y.Dudullu - Umraniye Istanbul 34775 - TURKEY - - B0-1C-91 (hex) Elim Co - B01C91 (base 16) Elim Co - 4F Gagu Plaza B/D 81-9, jeongja-dong, Jangan-gu, - Suwon city Gyeonggi-Do 440-300 - KOREA, REPUBLIC OF - - B0-1F-81 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - B01F81 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - B0-24-F3 (hex) Progeny Systems - B024F3 (base 16) Progeny Systems - 9500 Innovation Drive - Manassas VA 20110 - UNITED STATES - - B0-25-AA (hex) PRIVATE - B025AA (base 16) - - B0-34-95 (hex) Apple - B03495 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B0-35-8D (hex) Nokia Corporation - B0358D (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - B0-38-29 (hex) Siliconware Precision Industries Co., Ltd. - B03829 (base 16) Siliconware Precision Industries Co., Ltd. - No. 123, Sec.3, Da Fong Rd, Tantzu, - Taichung 427 - TAIWAN, PROVINCE OF CHINA - - B0-38-50 (hex) Nanjing CAS-ZDC IOT SYSTEM CO.,LTD - B03850 (base 16) Nanjing CAS-ZDC IOT SYSTEM CO.,LTD - 699-27 Xuanwu Avenue - 2nd Floor of Building A,R&D3 - Nanjing Jiangsu 210000 - CHINA - - B0-43-5D (hex) NuLEDs, Inc. - B0435D (base 16) NuLEDs, Inc. - 1497 Poinsettia Ave. - Suite 153 - Vista CA 92081 - UNITED STATES - - B0-45-15 (hex) mira fitness,LLC. - B04515 (base 16) mira fitness,LLC. - 1925 West Field Court Suite100 - Lake Forest IL 60045 - UNITED STATES - - B0-45-19 (hex) TCT mobile ltd - B04519 (base 16) TCT mobile ltd - NO.86 hechang 7th road, zhongkai hi-tech distrct - Hui Zhou Guang Dong 516006 - CHINA - - B0-45-45 (hex) YACOUB Automation GmbH - B04545 (base 16) YACOUB Automation GmbH - Gustav Meyer Allee 25 - Berlin 13355 - GERMANY - - B0-46-FC (hex) MitraStar Technology Corp. - B046FC (base 16) MitraStar Technology Corp. - No. 6, Innovation Road II, - Hsinchu Science Park - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - B0-48-7A (hex) TP-LINK TECHNOLOGIES CO., LTD. - B0487A (base 16) TP-LINK TECHNOLOGIES CO., LTD. - 1-6F, Building 2, Pingshandayuan Industrial, South Zone, - Taoyuan Street, Nanshan District, - Shenzhen Guangdong 518000 - CHINA - - B0-49-5F (hex) OMRON HEALTHCARE Co., Ltd. - B0495F (base 16) OMRON HEALTHCARE Co., Ltd. - 53, Kunotsubo, Terado-cho - Muko Kyoto 6170002 - JAPAN - - B0-4C-05 (hex) Fresenius Medical Care Deutschland GmbH - B04C05 (base 16) Fresenius Medical Care Deutschland GmbH - Hafenstr. 9 - Schweinfurt 97424 - GERMANY - - B0-50-BC (hex) SHENZHEN BASICOM ELECTRONIC CO.,LTD. - B050BC (base 16) SHENZHEN BASICOM ELECTRONIC CO.,LTD. - Basicom industry park, Baolong Avenue 3rd Road, Baolong industry town - LongGang District - Shenzhen Guangdong 518116 - CHINA - - B0-51-8E (hex) Holl technology CO.Ltd. - B0518E (base 16) Holl technology CO.Ltd. - F2,Bld 27,Anle Industrial Park,Nantou Guankou No.2 Road - Nanshan District, - Shenzhen Guangdong 518052 - CHINA - - B0-57-06 (hex) Vallox Oy - B05706 (base 16) Vallox Oy - Myllykylantie 9-11 - Loimaa 32200 - FINLAND - - B0-58-C4 (hex) Broadcast Microwave Services, Inc - B058C4 (base 16) Broadcast Microwave Services, Inc - 12367 Crosthwaite Circle - Poway CA 92064 - UNITED STATES - - B0-5B-1F (hex) THERMO FISHER SCIENTIFIC S.P.A. - B05B1F (base 16) THERMO FISHER SCIENTIFIC S.P.A. - STRADA RIVOLTANA KM 6/7 - RODANO MILAN 20090 - ITALY - - B0-5B-67 (hex) Huawei Technologies Co., Ltd - B05B67 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - B0-5C-E5 (hex) Nokia Corporation - B05CE5 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - B0-61-C7 (hex) Ericsson-LG Enterprise - B061C7 (base 16) Ericsson-LG Enterprise - 77, Heungan-daro 81beon-gil, - Dongan-gu, Anyang-si, Gyeonggi-do, Korea - Anyang Gyeonggi 431-749 - KOREA, REPUBLIC OF - - B0-65-63 (hex) Shanghai Railway Communication Factory - B06563 (base 16) Shanghai Railway Communication Factory - No.179 West Jiangchang road - Shanghai 200436 - CHINA - - B0-65-BD (hex) Apple - B065BD (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B0-68-B6 (hex) Hangzhou OYE Technology Co. Ltd - B068B6 (base 16) Hangzhou OYE Technology Co. Ltd - Room 202 Building 12 Wenxinrenjia, - Binjiang District - Hangzhou Zhejiang 310051 - CHINA - - B0-69-71 (hex) DEI Sales, Inc. - B06971 (base 16) DEI Sales, Inc. - 1 Viper Way - Vista CA 92081 - UNITED STATES - - B0-6C-BF (hex) 3ality Digital Systems GmbH - B06CBF (base 16) 3ality Digital Systems GmbH - Gut Mergenthau 1 - Kissing Bayern 86438 - GERMANY - - B0-75-0C (hex) QA Cafe - B0750C (base 16) QA Cafe - 33 Jewell Court - Unit 1 - Portsmouth NH 03801 - UNITED STATES - - B0-75-4D (hex) Alcatel-Lucent - B0754D (base 16) Alcatel-Lucent - 600 March Rd - Ottawa ON K2K 2E6 - CANADA - - B0-75-D5 (hex) ZTE Corporation - B075D5 (base 16) ZTE Corporation - 12/F,ZTE R&D Building,Kejinan Road, - Shenzhen Guangdong 518057 - CHINA - - B0-77-AC (hex) ARRIS Group, Inc. - B077AC (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - B0-79-08 (hex) Cummings Engineering - B07908 (base 16) Cummings Engineering - 145 S. 79th St., Ste. 26 - Chandler AZ 85226 - UNITED STATES - - B0-79-3C (hex) Revolv Inc - B0793C (base 16) Revolv Inc - 2060 Broadway #380 - Boulder CO 80302 - UNITED STATES - - B0-79-94 (hex) Motorola Mobility LLC - B07994 (base 16) Motorola Mobility LLC - 600 North US Hwy 45 - Libertyville IL 60048 - UNITED STATES - - B0-7D-62 (hex) Dipl.-Ing. H. Horstmann GmbH - B07D62 (base 16) Dipl.-Ing. H. Horstmann GmbH - Humboldtstraße 2 - Heiligenhaus 42579 - GERMANY - - B0-80-8C (hex) Laser Light Engines - B0808C (base 16) Laser Light Engines - 8C Industrial Way - Salem New Hamshire 03079 - UNITED STATES - - B0-81-D8 (hex) I-sys Corp - B081D8 (base 16) I-sys Corp - 2457 Aviation Ave - Suite 900 - N. Charleston South Carolina 29406 - UNITED STATES - - B0-83-FE (hex) Dell Inc - B083FE (base 16) Dell Inc - One Dell way - Round Rock Tx 78682 - UNITED STATES - - B0-86-9E (hex) Chloride S.r.L - B0869E (base 16) Chloride S.r.L - Via Fornace ,30 - CastelGuelfo (Bologna) Italy 40023 - ITALY - - B0-88-07 (hex) Strata Worldwide - B08807 (base 16) Strata Worldwide - 8995 Roswell Road - Sandy Springs GA 30350 - UNITED STATES - - B0-89-91 (hex) LGE - B08991 (base 16) LGE - 60-39 , Kasan -dong , Gumcheon-gu. - Seoul 153-801 - KOREA, REPUBLIC OF - - B0-8E-1A (hex) URadio Systems Co., Ltd - B08E1A (base 16) URadio Systems Co., Ltd - Phase II D202-2, 1355 JinJiHu Blvd - Suzhou Industrial Park - Suzhou Jiangsu 215021 - CHINA - - B0-90-74 (hex) Fulan Electronics Limited - B09074 (base 16) Fulan Electronics Limited - Flat B&C,3/F,A1 Block, Gaoxin Cyber-Tech Zone,Nanshan - Shenzhen Guangdong 518057 - CHINA - - B0-91-34 (hex) Taleo - B09134 (base 16) Taleo - 4140 Dublin Blvd - Suite 400 - Dublin California 94568 - UNITED STATES - - B0-91-37 (hex) ISis ImageStream Internet Solutions, Inc - B09137 (base 16) ISis ImageStream Internet Solutions, Inc - 4374 FM 1518 - Selma TX 78154 - UNITED STATES - - B0-96-6C (hex) Lanbowan Technology Ltd. - B0966C (base 16) Lanbowan Technology Ltd. - No. 60 Langbao Xi Road - Zhangcha, Chancheng - Foshan Guangdong 528051 - CHINA - - B0-97-3A (hex) E-Fuel Corporation - B0973A (base 16) E-Fuel Corporation - 15466 Los Gatos Blvd. #37 - Los Gatos CA 95032 - UNITED STATES - - B0-98-9F (hex) LG CNS - B0989F (base 16) LG CNS - 53-94 Jinwisandan-ro, Jinwuy-Myun - Pyungtaek-City Kyunggi-Do 451-862 - KOREA, REPUBLIC OF - - B0-99-28 (hex) Fujitsu Limited - B09928 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - B0-9A-E2 (hex) STEMMER IMAGING GmbH - B09AE2 (base 16) STEMMER IMAGING GmbH - Gutenbergstraße 11 - Puchheim By 82178 - GERMANY - - B0-9B-D4 (hex) GNH Software India Private Limited - B09BD4 (base 16) GNH Software India Private Limited - 9/14 Sengani Amman Koil Street - Maduvankarai, Guindy - Chennai Tamilnadu 600032 - INDIA - - B0-9F-BA (hex) Apple - B09FBA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B0-A1-0A (hex) Pivotal Systems Corporation - B0A10A (base 16) Pivotal Systems Corporation - 4683 Chabot Drive - Pleasanton CA 94588 - UNITED STATES - - B0-A3-7E (hex) Qingdao Haier Electronics Co.,Ltd - B0A37E (base 16) Qingdao Haier Electronics Co.,Ltd - No.1,Haier Road,Qingdao 266101 P.R.China - Qingdao Shandong 266101 - CHINA - - B0-A7-2A (hex) Ensemble Designs, Inc. - B0A72A (base 16) Ensemble Designs, Inc. - 870 Gold Flat Road - Nevada City CA 95959 - UNITED STATES - - B0-A7-37 (hex) Roku, Inc. - B0A737 (base 16) Roku, Inc. - 12980 Saratoga Ave - Suite D - Saratoga CA 95070 - UNITED STATES - - B0-A8-6E (hex) Juniper Networks - B0A86E (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - B0-AA-36 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - B0AA36 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - NO.18 HAIBIN ROAD - WUSHA,CHANG'AN - DONGGUAN GUANGDONG 523860 - CHINA - - B0-AA-77 (hex) Cisco - B0AA77 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - B0-AC-FA (hex) Fujitsu Limited - B0ACFA (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa - JAPAN - - B0-AD-AA (hex) Avaya, Inc - B0ADAA (base 16) Avaya, Inc - 211 Mt. Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - B0-B2-DC (hex) Zyxel Communications Corporation - B0B2DC (base 16) Zyxel Communications Corporation - No. 6, Innovation Road, II, - Hsinchu Science Park, - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - B0-B3-2B (hex) Slican Sp. z o.o. - B0B32B (base 16) Slican Sp. z o.o. - M. Konopnickiej 18 - Bydgoszcz Kujawsko-Pomorskie 85-124 - POLAND - - B0-B4-48 (hex) Texas Instruments - B0B448 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - B0-B8-D5 (hex) Nanjing Nengrui Auto Equipment CO.,Ltd - B0B8D5 (base 16) Nanjing Nengrui Auto Equipment CO.,Ltd - No.108 Ganjiabian East Yaohua Town - Nanjing Jiangsu 210046 - CHINA - - B0-BD-6D (hex) Echostreams Innovative Solutions - B0BD6D (base 16) Echostreams Innovative Solutions - 1130 Coiner Ct. - City of Industry CA 91748 - UNITED STATES - - B0-BD-A1 (hex) ZAKLAD ELEKTRONICZNY SIMS - B0BDA1 (base 16) ZAKLAD ELEKTRONICZNY SIMS - POD SKARPA 51A - BYDGOSZCZ KUJAWSKO-POMORSKIE 85-796 - POLAND - - B0-BF-99 (hex) WIZITDONGDO - B0BF99 (base 16) WIZITDONGDO - 2F, 299-1, 3-DONG, SUNGSU 2-GA - SUNGDONG-KU - SEOUL 133-833 - KOREA, REPUBLIC OF - - B0-C2-87 (hex) Technicolor CH USA Inc - B0C287 (base 16) Technicolor CH USA Inc - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - B0-C4-E7 (hex) Samsung Electronics - B0C4E7 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B0-C5-54 (hex) D-Link International - B0C554 (base 16) D-Link International - 1 Internal Business Park, #03-12 - The Synergy - Singapore 609917 - SINGAPORE - - B0-C5-59 (hex) Samsung Electronics Co.,Ltd - B0C559 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B0-C6-9A (hex) Juniper Networks - B0C69A (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - B0-C7-45 (hex) Buffalo Inc. - B0C745 (base 16) Buffalo Inc. - AKAMONDORI Bldg., 30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref. 460-8315 - JAPAN - - B0-C8-3F (hex) Jiangsu Cynray IOT Co., Ltd. - B0C83F (base 16) Jiangsu Cynray IOT Co., Ltd. - Building D1, 1 Zidong road, Qixia district - Nanjing Jiangsu 210000 - CHINA - - B0-C8-AD (hex) People Power Company - B0C8AD (base 16) People Power Company - 620 Lowell Ave - Palo Alto CA 94301 - UNITED STATES - - B0-C9-5B (hex) Beijing Symtech CO.,LTD - B0C95B (base 16) Beijing Symtech CO.,LTD - Technology Park Building 2-1,The Hung Fu Pioneer Park - Changping District Beiqijia - Beijing 102209 - CHINA - - B0-CE-18 (hex) Zhejiang shenghui lighting co.,Ltd - B0CE18 (base 16) Zhejiang shenghui lighting co.,Ltd - Rm801,1th Xinye Building - Tianlin Rd388 - cao he jing Develop Zone Shanghai 200233 - CHINA - - B0-CF-4D (hex) MI-Zone Technology Ireland - B0CF4D (base 16) MI-Zone Technology Ireland - 2nd floor,block 10 unit 3 - Blanchardstown corporate park - dublin Blanchardstown 15 - IRELAND - - B0-D0-9C (hex) Samsung Electronics Co.,Ltd - B0D09C (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B0-D2-F5 (hex) Vello Systems, Inc. - B0D2F5 (base 16) Vello Systems, Inc. - 1530 O'Brien Drive - Menlo Park California 94025 - UNITED STATES - - B0-D5-9D (hex) Shenzhen Zowee Technology Co., Ltd - B0D59D (base 16) Shenzhen Zowee Technology Co., Ltd - Block 5 (ZOWEE Technology Building), - Science&Technology Industrial Park of Privately Owned Enterprises - Pingshan, Xili Town, Nanshan District Shenzhen, Guangdong 518055 - CHINA - - B0-D7-C5 (hex) Logipix Ltd - B0D7C5 (base 16) Logipix Ltd - Kesmark utca 11-13 - Budapest - 1158 - HUNGARY - - B0-DA-00 (hex) CERA ELECTRONIQUE - B0DA00 (base 16) CERA ELECTRONIQUE - PARC D'ACTIVITES - ROUTE DES FALAISES - VAL DE REUIL HAUTE NORMANDIE 27100 - FRANCE - - B0-DF-3A (hex) Samsung Electronics Co.,Ltd - B0DF3A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B0-E0-3C (hex) TCT mobile ltd - B0E03C (base 16) TCT mobile ltd - NO.86 hechang 7th road, zhongkai hi-tech distrct - Hui Zhou Guang Dong 516006 - CHINA - - B0-E2-E5 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - B0E2E5 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - B0-E3-9D (hex) CAT SYSTEM CO.,LTD. - B0E39D (base 16) CAT SYSTEM CO.,LTD. - 3-147-27 Higasi-sinmachi Hirohata-ku - Himeji Hyogo 671-1121 - JAPAN - - B0-E5-0E (hex) NRG SYSTEMS INC - B0E50E (base 16) NRG SYSTEMS INC - PO BOX 0509 - Hinesburg VT 054610509 - UNITED STATES - - B0-E7-54 (hex) 2Wire - B0E754 (base 16) 2Wire - 1764 Automation Parkway - San Jose California 95131 - UNITED STATES - - B0-E8-92 (hex) SEIKO EPSON CORPORATION - B0E892 (base 16) SEIKO EPSON CORPORATION - 3-3-5 OWA - SUWA-SHI NAGANO-KEN 392-8502 - JAPAN - - B0-E9-7E (hex) Advanced Micro Peripherals - B0E97E (base 16) Advanced Micro Peripherals - Unit 1 Harrier House - Sedgeway Buisness Park - Witchford Cambridgeshire CB6 2HY - UNITED KINGDOM - - B0-EC-71 (hex) Samsung Electronics Co.,Ltd - B0EC71 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B0-EC-8F (hex) GMX SAS - B0EC8F (base 16) GMX SAS - 32 Rue Brancion - PARIS 75015 - FRANCE - - B0-EC-E1 (hex) PRIVATE - B0ECE1 (base 16) - - B0-EE-45 (hex) AzureWave Technologies, Inc. - B0EE45 (base 16) AzureWave Technologies, Inc. - 8F ., No.94, Baozhong Rd. , Xindian Dist., - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - B0-F1-BC (hex) Dhemax Ingenieros Ltda - B0F1BC (base 16) Dhemax Ingenieros Ltda - Siete Oriente 1234 - Vina del Mar Region de Valparaiso 2530954 - CHILE - - B0-FA-EB (hex) Cisco - B0FAEB (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - B0-FE-BD (hex) PRIVATE - B0FEBD (base 16) - - B4-00-9C (hex) CableWorld Ltd. - B4009C (base 16) CableWorld Ltd. - Kondorfa u. 6/B - Budapest 1112 - HUNGARY - - B4-01-42 (hex) GCI Science & Technology Co.,LTD - B40142 (base 16) GCI Science & Technology Co.,LTD - No.381,xingangzhong road , - GuangZhou GuangDong 510310 - CHINA - - B4-04-18 (hex) Smartchip Integrated Inc. - B40418 (base 16) Smartchip Integrated Inc. - 9B,Science Plaza,1355 JinJiHu Avenue,Suzhou Industrial Park - Suzhou Jiangsu 215021 - CHINA - - B4-05-66 (hex) SP Best Corporation Co., LTD. - B40566 (base 16) SP Best Corporation Co., LTD. - 555/25 B-Avenue, Sukhaphibal 5 Road - Or-Ngern - Saimai Bangkok 10220 - THAILAND - - B4-07-F9 (hex) SAMSUNG ELECTRO-MECHANICS - B407F9 (base 16) SAMSUNG ELECTRO-MECHANICS - Suwon-Si, Gyeonggi_Do, Korea - Suwon Gyeonggi_Do 443-743 - KOREA, REPUBLIC OF - - B4-08-32 (hex) TC Communications - B40832 (base 16) TC Communications - 17881 Cartwright Road - Irvine CA 92614 - UNITED STATES - - B4-0A-C6 (hex) DEXON Systems Ltd. - B40AC6 (base 16) DEXON Systems Ltd. - Baross u. 165 - Budaors Pest H-2040 - HUNGARY - - B4-0B-44 (hex) Smartisan Technology Co., Ltd. - B40B44 (base 16) Smartisan Technology Co., Ltd. - 7/F, Motorola Bldg., 1st Wangjing East Rd, - Chaoyang District - Beijing 100102 - CHINA - - B4-0B-7A (hex) Brusa Elektronik AG - B40B7A (base 16) Brusa Elektronik AG - Neudorf 14 - Sennwald St. Gallen 9466 - SWITZERLAND - - B4-0C-25 (hex) Palo Alto Networks - B40C25 (base 16) Palo Alto Networks - 3300 Olcott Street - Santa Clara CA 95054 - UNITED STATES - - B4-0E-96 (hex) HERAN - B40E96 (base 16) HERAN - No.88, Keji 3rd Rd., Guishan Township - Taoyuan R.O.C 333 - TAIWAN, PROVINCE OF CHINA - - B4-0E-DC (hex) LG-Ericsson Co.,Ltd. - B40EDC (base 16) LG-Ericsson Co.,Ltd. - 533,Hogye-1dong,Dongan-gu - LG R&D Complex.LG-Ericsson, - Anyang-shi Kyungki-do 431-749 - KOREA, REPUBLIC OF - - B4-14-89 (hex) CISCO SYSTEMS, INC. - B41489 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - B4-15-13 (hex) HUAWEI TECHNOLOGIES CO.,LTD - B41513 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4A52R,Huawei Industrial Base - Bantian Longgang - ShenZhen GuangDong 518129 - CHINA - - B4-17-80 (hex) DTI Group Ltd - B41780 (base 16) DTI Group Ltd - 50 Affleck Rd - Perth Airport Western Australia 6105 - AUSTRALIA - - B4-18-D1 (hex) Apple - B418D1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B4-1D-EF (hex) Internet Laboratories, Inc. - B41DEF (base 16) Internet Laboratories, Inc. - P.O. Box 7697 - Atlanta GA 30357 - UNITED STATES - - B4-21-1D (hex) Beijing GuangXin Technology Co., Ltd - B4211D (base 16) Beijing GuangXin Technology Co., Ltd - Room 313,B Bld,Horizon International Tower,Zhichun Road,6,Haidian District,Beijing City,P.R.China - Beijing 100086 - CHINA - - B4-21-8A (hex) Dog Hunter LLC - B4218A (base 16) Dog Hunter LLC - 8 Faneuil Hall SQ - Boston MA 02109 - UNITED STATES - - B4-24-E7 (hex) Codetek Technology Co.,Ltd - B424E7 (base 16) Codetek Technology Co.,Ltd - 4F.-1, No.55, Dongguang Rd., East Dist., - Hsinchu City 300 - TAIWAN, PROVINCE OF CHINA - - B4-28-F1 (hex) E-Prime Co., Ltd. - B428F1 (base 16) E-Prime Co., Ltd. - Rm1207, Kolon Science Valley, 811, - Kuro-Dong, Kuro-Ku - Seoul 152050 - KOREA, REPUBLIC OF - - B4-2A-39 (hex) ORBIT MERRET, spol. s r. o. - B42A39 (base 16) ORBIT MERRET, spol. s r. o. - Vodnanska 675/30 - Praha 198 00 - CZECH REPUBLIC - - B4-2C-92 (hex) Zhejiang Weirong Electronic Co., Ltd - B42C92 (base 16) Zhejiang Weirong Electronic Co., Ltd - North of South Tanghe Road, Lingxi Town, - Cangnan Industrial Park - Wenzhou City Zhejiang Province 325800 - CHINA - - B4-2C-BE (hex) Direct Payment Solutions Limited - B42CBE (base 16) Direct Payment Solutions Limited - 98 Anzac Avenue - Auckland 1035 - NEW ZEALAND - - B4-30-52 (hex) Huawei Technologies Co., Ltd - B43052 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - B4-31-B8 (hex) Aviwest - B431B8 (base 16) Aviwest - 6 rue du Patis Tatelin - Rennes 35700 - FRANCE - - B4-34-6C (hex) MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED - B4346C (base 16) MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED - 22/F. TWO INTERNATIONAL FINANCE CTR - 8 FINANCE STREET CENTRAL - 999077 - HONG KONG - - B4-35-64 (hex) Fujian Tian Cheng Electron Science & Technical Development Co.,Ltd. - B43564 (base 16) Fujian Tian Cheng Electron Science & Technical Development Co.,Ltd. - 1801 unit,Tian an Cyber Times Tower A,Futian District - Shenzhen Guangdong 518000 - CHINA - - B4-35-F7 (hex) Zhejiang Pearmain Electronics Co.ltd. - B435F7 (base 16) Zhejiang Pearmain Electronics Co.ltd. - 4F Yitai Mansion, 76 Gucui Road, - Hangzhou Zhejiang 310012 - CHINA - - B4-37-41 (hex) Consert, Inc. - B43741 (base 16) Consert, Inc. - 4700 Falls of Neuse Rd. - Suite 340 - Raleigh NC 27609 - UNITED STATES - - B4-39-34 (hex) Pen Generations, Inc. - B43934 (base 16) Pen Generations, Inc. - 8th FL., SOLiD Space, - 673 Sampyeong-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - B4-39-D6 (hex) ProCurve Networking by HP - B439D6 (base 16) ProCurve Networking by HP - 800 Foothills Blvd. - Roseville California 95747 - UNITED STATES - - B4-3A-28 (hex) Samsung Electronics Co.,Ltd - B43A28 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B4-3D-B2 (hex) Degreane Horizon - B43DB2 (base 16) Degreane Horizon - 730 Rue de l'Initiative - Cuers Var 83390 - FRANCE - - B4-3E-3B (hex) Viableware, Inc - B43E3B (base 16) Viableware, Inc - 12220 113th Ave NE - Suite 210 - Kirkland WA 98034 - UNITED STATES - - B4-41-7A (hex) ShenZhen Gongjin Electronics Co.,Ltd - B4417A (base 16) ShenZhen Gongjin Electronics Co.,Ltd - 4F,Baiying Building, No.1019,Nanhai RD,Shekou - ShenZhen GuangDong 518067 - CHINA - - B4-43-0D (hex) Broadlink Pty Ltd - B4430D (base 16) Broadlink Pty Ltd - room 1201, No. 588 jiangnan Rd, - Binjiang High Tech Zone - Hangzhou Zhejiang province 310052 - CHINA - - B4-47-5E (hex) Avaya, Inc - B4475E (base 16) Avaya, Inc - 211 Mt. Airy Road - Basking Ridge NJ 079202311 - UNITED STATES - - B4-4C-C2 (hex) NR ELECTRIC CO., LTD - B44CC2 (base 16) NR ELECTRIC CO., LTD - 69,Suyuan Avenue - Jiangning - Nanjing Jiangsu 211102 - CHINA - - B4-51-F9 (hex) NB Software - B451F9 (base 16) NB Software - Eichhalde 3 - Weissach i. T. Baden-Württemberg 71554 - GERMANY - - B4-52-53 (hex) Seagate Technology - B45253 (base 16) Seagate Technology - 1280 Disc Drive - Shakopee MN 55379 - UNITED STATES - - B4-52-7D (hex) Sony Mobile Communications AB - B4527D (base 16) Sony Mobile Communications AB - Nya Vattentornet - - - Lund SE 22188 - UNITED STATES - - B4-52-7E (hex) Sony Mobile Communications AB - B4527E (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - B4-55-70 (hex) Borea - B45570 (base 16) Borea - Mlaka 1b - Begunje SI-4275 - SLOVENIA - - B4-58-61 (hex) CRemote, LLC - B45861 (base 16) CRemote, LLC - 1195 Noel Drive - MENLO PARK CA 94025 - UNITED STATES - - B4-5C-A4 (hex) Thing-talk Wireless Communication Technologies Corporation Limited - B45CA4 (base 16) Thing-talk Wireless Communication Technologies Corporation Limited - 498 Guo Shou Jing Road, Suite 10402 - Shanghai 201203 - CHINA - - B4-61-FF (hex) Lumigon A/S - B461FF (base 16) Lumigon A/S - Baadehavnsgade 2A - Copenhagen SV Denmark 2450 - DENMARK - - B4-62-38 (hex) Exablox - B46238 (base 16) Exablox - 365 San Antonio Road - Mountain View CA 94040 - UNITED STATES - - B4-62-93 (hex) Samsung Electronics Co.,Ltd - B46293 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B4-62-AD (hex) raytest GmbH - B462AD (base 16) raytest GmbH - Benzstr. 4 - Straubenhardt Baden-Wuerttemberg 75334 - GERMANY - - B4-66-98 (hex) Zealabs srl - B46698 (base 16) Zealabs srl - via Longhin, 131 - Padova Italy 35129 - ITALY - - B4-67-E9 (hex) Qingdao GoerTek Technology Co., Ltd. - B467E9 (base 16) Qingdao GoerTek Technology Co., Ltd. - 5F, No.3 Building, Fortune Center - No.18, Qinling Road, Laoshan District - Qingdao Shandong 266061 - CHINA - - B4-6D-35 (hex) Dalian Seasky Automation Co;Ltd - B46D35 (base 16) Dalian Seasky Automation Co;Ltd - Room 408, DUT Science & Technology Park Building B, No.80 Software Park Road, High-Tech Industrial Zone, Dalian, Liaoning, China - Dalian Liao Ning 116023 - CHINA - - B4-6D-83 (hex) Intel Corporate - B46D83 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - B4-73-56 (hex) Hangzhou Treebear Networking Co., Ltd. - B47356 (base 16) Hangzhou Treebear Networking Co., Ltd. - 2F,Block A, Lianhe Building, 2#, Zijinghua RD, Xihu District - Hangzhou Zhejiang 310012 - CHINA - - B4-74-9F (hex) askey computer corp - B4749F (base 16) askey computer corp - 110F,NO.119,CHIENKANG RD,CHUNG-HO, - TAIPEI 23585 - TAIWAN, PROVINCE OF CHINA - - B4-75-0E (hex) Belkin International Inc. - B4750E (base 16) Belkin International Inc. - 12045 East Waterfront Drive - Playa Vista CA. 90094 - UNITED STATES - - B4-79-A7 (hex) Samsung Electro Mechanics co., LTD. - B479A7 (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - B4-7C-29 (hex) Shenzhen Guzidi Technology Co.,Ltd - B47C29 (base 16) Shenzhen Guzidi Technology Co.,Ltd - South 6/F,Yingtang Building,No.5 Kejiyuan Road,Nanshan District,Shenzhen City,Guangdong Province,P.R. China - Room403,4/f,3Building,Meilin Industrial Zone,Meilin Street,Futian District,Shenzhen City,Guangdong Province,P.R. China - Shenzhen Guangdong 518000 - CHINA - - B4-7F-5E (hex) Foresight Manufacture (S) Pte Ltd - B47F5E (base 16) Foresight Manufacture (S) Pte Ltd - 1 Sims Lane #04-09 - One Sims Lane - Singapore 387355 - SINGAPORE - - B4-82-55 (hex) Research Products Corporation - B48255 (base 16) Research Products Corporation - 1015 E. Washington Ave - Madison WI 53703 - UNITED STATES - - B4-82-7B (hex) AKG Acoustics GmbH - B4827B (base 16) AKG Acoustics GmbH - Lemboeckgasse 21-25 - Vienna 1230 - AUSTRIA - - B4-82-C5 (hex) Relay2, Inc. - B482C5 (base 16) Relay2, Inc. - 1525 McCarthy Blvd., - Suite #209 - Milpitas CA 95035 - UNITED STATES - - B4-82-FE (hex) Askey Computer Corp - B482FE (base 16) Askey Computer Corp - 10F,NO.119,CHIENKANG RD,CHUNG-HO, - TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - B4-85-47 (hex) Amptown System Company GmbH - B48547 (base 16) Amptown System Company GmbH - Wandsbeker Strasse 26 - Hamburg 22179 - GERMANY - - B4-89-10 (hex) Coster T.E. S.P.A. - B48910 (base 16) Coster T.E. S.P.A. - Via San Giovanni Battista De La Salle 4/a - Milano MI 20132 - ITALY - - B4-94-4E (hex) WeTelecom Co., Ltd. - B4944E (base 16) WeTelecom Co., Ltd. - The'O Plus #915 - Sanbon-dong - Gunpo-si Kyunggi-do 435-805 - KOREA, REPUBLIC OF - - B4-98-42 (hex) zte corporation - B49842 (base 16) zte corporation - 12/F.,R&D building,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - UNITED STATES - - B4-99-4C (hex) Texas Instruments - B4994C (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - B4-99-BA (hex) Hewlett-Packard Company - B499BA (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - B4-9D-B4 (hex) Axion Technologies Inc. - B49DB4 (base 16) Axion Technologies Inc. - 105-1203, 70, Jingeononam-ro - 759beon-gil, Onam-eup, - Namyangju Gyeonggi-do 472-859 - KOREA, REPUBLIC OF - - B4-9E-AC (hex) Imagik Int'l Corp - B49EAC (base 16) Imagik Int'l Corp - 2299 SW 37 th Ave - Miami Florida 33145 - UNITED STATES - - B4-9E-E6 (hex) SHENZHEN TECHNOLOGY CO LTD - B49EE6 (base 16) SHENZHEN TECHNOLOGY CO LTD - NO34 SHILONG RD - SHIYANG TOWN - SHENZHEN GUANGDONG 91732 - CHINA - - B4-A4-B5 (hex) Zen Eye Co.,Ltd - B4A4B5 (base 16) Zen Eye Co.,Ltd - #401, 157-5 Chunui-dong - Wonmi-gu - Bucheon-si Gyeonggi-do 420-859 - KOREA, REPUBLIC OF - - B4-A4-E3 (hex) CISCO SYSTEMS, INC. - B4A4E3 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - B4-A5-A9 (hex) MODI GmbH - B4A5A9 (base 16) MODI GmbH - Kapellenweg 21 - REICHSHOF-Sinspert 51580 - GERMANY - - B4-A8-28 (hex) Shenzhen Concox Information Technology Co., Ltd - B4A828 (base 16) Shenzhen Concox Information Technology Co., Ltd - Floor 4th, Building B, Gaoxinqi Industrial Park, Liuxian 1st Road, district 67, Bao’an, Shenzhen, Guangdong,China - Shenzhen Guangdong 518102 - CHINA - - B4-A8-2B (hex) Histar Digital Electronics Co., Ltd. - B4A82B (base 16) Histar Digital Electronics Co., Ltd. - Room 616,Block A, - Huameiju Business Building, - Shenzhen Baoan 518133 - CHINA - - B4-A9-5A (hex) Avaya, Inc - B4A95A (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - B4-A9-FE (hex) GHIA Technology (Shenzhen) LTD - B4A9FE (base 16) GHIA Technology (Shenzhen) LTD - RM 1606, BLDG 3rd, COFCO Clouds Mansion - Xixiang Street, Bao An District - Shenzhen 518101 - CHINA - - B4-AA-4D (hex) Ensequence, Inc. - B4AA4D (base 16) Ensequence, Inc. - 111 SW 5th Ave Suite 1400 - Portland OR 97204 - UNITED STATES - - B4-AB-2C (hex) MtM Technology Corporation - B4AB2C (base 16) MtM Technology Corporation - 12F, No. 186, Fuxing Road - Taoyuan City Taoyuan County 33066 - TAIWAN, PROVINCE OF CHINA - - B4-AE-6F (hex) Circle Reliance, Inc DBA Cranberry Networks - B4AE6F (base 16) Circle Reliance, Inc DBA Cranberry Networks - 921 Rose Avenue - Menlo Park CA 94025 - UNITED STATES - - B4-B0-17 (hex) Avaya, Inc - B4B017 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - B4-B2-65 (hex) DAEHO I&T - B4B265 (base 16) DAEHO I&T - 211, Jayumuyeok 3-gil, MasanHoewon-gu - 3 Hodong 5th floor - Changwon-si Gyeongsangnam-do 630-812 - KOREA, REPUBLIC OF - - B4-B3-62 (hex) ZTE Corporation - B4B362 (base 16) ZTE Corporation - 12/F,ZTE R&D Building,kejinan Road, - Shenzhen Guangdong 518057 - CHINA - - B4-B5-2F (hex) Hewlett Packard - B4B52F (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - B4-B5-42 (hex) Hubbell Power Systems, Inc. - B4B542 (base 16) Hubbell Power Systems, Inc. - 8100 Churchill Ave - Leeds AL 35094 - UNITED STATES - - B4-B5-AF (hex) Minsung Electronics - B4B5AF (base 16) Minsung Electronics - Mega-valley #620 - Dongan-gu Gwanyang-dong, 799 - Anyang-si Kyeonggi-do 431-767 - KOREA, REPUBLIC OF - - B4-B6-76 (hex) Intel Corporate - B4B676 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - B4-B8-59 (hex) Texa Spa - B4B859 (base 16) Texa Spa - Via I Maggio, 9 - Monastier di Treviso Treviso 31050 - ITALY - - B4-B8-8D (hex) Thuh Company - B4B88D (base 16) Thuh Company - 605 Territorial Dr - Suite C - Bolingbrook IL 60440 - UNITED STATES - - B4-C4-4E (hex) VXL eTech Pvt Ltd - B4C44E (base 16) VXL eTech Pvt Ltd - #91, 11th Main, Begur Main Road - Hongasandra - Bangalore Karnataka 560068 - INDIA - - B4-C7-99 (hex) Zebra Technologies Inc - B4C799 (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - B4-C8-10 (hex) UMPI Elettronica - B4C810 (base 16) UMPI Elettronica - Via Respighi, 15 - Cattolica 47841 - ITALY - - B4-CC-E9 (hex) PROSYST - B4CCE9 (base 16) PROSYST - 2C Rue de l' EPINOY - ZAC de TEMPLEMARS - TEMPLEMARS 59175 - FRANCE - - B4-CE-F6 (hex) HTC Corporation - B4CEF6 (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - B4-CF-DB (hex) Shenzhen Jiuzhou Electric Co.,LTD - B4CFDB (base 16) Shenzhen Jiuzhou Electric Co.,LTD - 6F,Jiuzhou Electric Building,Southern No.12RD.,Hi-Tech Industrial Park,Nanshan District, - Shenzhen Guangdong 518057 - CHINA - - B4-D8-A9 (hex) BetterBots - B4D8A9 (base 16) BetterBots - 1600 Wilson Way SE, Ste. 9 - Smyrna GA 30082 - UNITED STATES - - B4-D8-DE (hex) iota Computing, Inc. - B4D8DE (base 16) iota Computing, Inc. - 2275 East Bayshore Road - Suite 108 - Palo Alto CA 94303-3222 - UNITED STATES - - B4-DD-15 (hex) ControlThings Oy Ab - B4DD15 (base 16) ControlThings Oy Ab - Werner Söderströmin katu 24 - Porvoo Finland 06100 - FINLAND - - B4-DF-3B (hex) Chromlech - B4DF3B (base 16) Chromlech - 19 av. Gabriel Faure - THORIGNE FOUILLARD 35235 - FRANCE - - B4-DF-FA (hex) Litemax Electronics Inc. - B4DFFA (base 16) Litemax Electronics Inc. - 8F, No.137,Lane 235 - Shin-dian-Dist New Taipei 23145 - TAIWAN, PROVINCE OF CHINA - - B4-E0-CD (hex) Fusion-io, Inc - B4E0CD (base 16) Fusion-io, Inc - 2880 Junction Avenue - San Jose CA 95134-1922 - UNITED STATES - - B4-E1-EB (hex) PRIVATE - B4E1EB (base 16) - - B4-E9-B0 (hex) Cisco - B4E9B0 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - B4-ED-19 (hex) Pie Digital, Inc. - B4ED19 (base 16) Pie Digital, Inc. - 575 Market st., 8th floor - San Francisco CA 94105-2823 - UNITED STATES - - B4-ED-54 (hex) Wohler Technologies - B4ED54 (base 16) Wohler Technologies - 31055 Huntwood Avenue - Hayward CA 94544 - UNITED STATES - - B4-EE-B4 (hex) ASKEY COMPUTER CORP - B4EEB4 (base 16) ASKEY COMPUTER CORP - 10F,NO.119,CHIENKANG RD,ZHONGHE DIST NEW TAIPEI CITY - TAIWAN TAIPEI 23585 - TAIWAN, PROVINCE OF CHINA - - B4-EE-D4 (hex) Texas Instruments - B4EED4 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - B4-EF-39 (hex) Samsung Electronics Co.,Ltd - B4EF39 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B4-F0-AB (hex) Apple - B4F0AB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B4-F2-E8 (hex) Pace plc - B4F2E8 (base 16) Pace plc - Victoria Road - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - B4-F3-23 (hex) PETATEL INC. - B4F323 (base 16) PETATEL INC. - #322 THE O VILLE 720-25, YEOKSAM-DONG - GANGNAM-GU SEOUL 135080 - KOREA, REPUBLIC OF - - B4-FC-75 (hex) SEMA Electronics(HK) CO.,LTD - B4FC75 (base 16) SEMA Electronics(HK) CO.,LTD - Xialingbei Industrial Zone Liaobu, - Dongguan Guangdong 523411 - CHINA - - B4-FE-8C (hex) Centro Sicurezza Italia SpA - B4FE8C (base 16) Centro Sicurezza Italia SpA - Via Venaria 28-30 - Alpignano Torino 10091 - ITALY - - B8-03-05 (hex) Intel Corporate - B80305 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - B8-04-15 (hex) Bayan Audio - B80415 (base 16) Bayan Audio - 5 The Pavilions - Brighton Road - Pease Pottage West Sussex RH11 9BJ - UNITED KINGDOM - - B8-08-CF (hex) Intel Corporate - B808CF (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - B8-09-8A (hex) Apple - B8098A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B8-0B-9D (hex) ROPEX Industrie-Elektronik GmbH - B80B9D (base 16) ROPEX Industrie-Elektronik GmbH - Gansaecker 21 - Bietigheim-Bissingen Baden Wuerttemberg 74321 - GERMANY - - B8-14-13 (hex) Keen High Holding(HK) Ltd. - B81413 (base 16) Keen High Holding(HK) Ltd. - 25th Floor, In-long Development Centre, No.6025 Shennan Ave - Futian District, - Shenzhen Guangdong 518040 - CHINA - - B8-16-19 (hex) ARRIS Group, Inc. - B81619 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - B8-17-C2 (hex) Apple - B817C2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B8-18-6F (hex) ORIENTAL MOTOR CO., LTD. - B8186F (base 16) ORIENTAL MOTOR CO., LTD. - 5-8-3 Tokodai - Tsukuba Ibaraki 300-2635 - JAPAN - - B8-19-99 (hex) Nesys - B81999 (base 16) Nesys - Energeticheskaya, 1 - Moscow 111116 - RUSSIAN FEDERATION - - B8-20-E7 (hex) Guangzhou Horizontal Information & Network Integration Co. Ltd - B820E7 (base 16) Guangzhou Horizontal Information & Network Integration Co. Ltd - Floor 10¬Golden Star Building¬Wushan Hanjing Road¬Tianhe District¬Guangzhou City - Guangzhou Guangdong Province 510630 - CHINA - - B8-24-10 (hex) Magneti Marelli Slovakia s.r.o. - B82410 (base 16) Magneti Marelli Slovakia s.r.o. - Industrial Park Kechnec - Kechnec 04458 - SLOVAKIA - - B8-24-1A (hex) SWEDA INFORMATICA LTDA - B8241A (base 16) SWEDA INFORMATICA LTDA - RUA DONA BRIGIDA, 713 - VILA MARIANA - SAO PAULO SP 04111-081 - BRAZIL - - B8-26-6C (hex) ANOV France - B8266C (base 16) ANOV France - Chemin de Baillot - Montauban Tarn & Garonne 82000 - FRANCE - - B8-26-D4 (hex) Furukawa Industrial S.A. Produtos Elétricos - B826D4 (base 16) Furukawa Industrial S.A. Produtos Elétricos - Rua Hasdrubal Bellegard, 820 - Bairro: Cidade Industrial de Curitiba - Parana 81460-120 - BRAZIL - - B8-27-EB (hex) Raspberry Pi Foundation - B827EB (base 16) Raspberry Pi Foundation - Mitchell Wood House - Caldecote Cambridgeshire CB23 7NU - UNITED KINGDOM - - B8-28-8B (hex) Parker Hannifin - B8288B (base 16) Parker Hannifin - Condition Monitoring Centre - Brunel Way - Thetford Norfolk IP24 1HP - UNITED KINGDOM - - B8-29-F7 (hex) Blaster Tech - B829F7 (base 16) Blaster Tech - 13337 South Street - Suite 349 - Cerritos CA 90703 - UNITED STATES - - B8-2A-72 (hex) Dell Inc - B82A72 (base 16) Dell Inc - one dell way - MS:RR5-45 - Round rock Texas 78682 - UNITED STATES - - B8-2A-DC (hex) EFR Europäische Funk-Rundsteuerung GmbH - B82ADC (base 16) EFR Europäische Funk-Rundsteuerung GmbH - Nymphenburger Straße 20b - Munich 80335 - GERMANY - - B8-2C-A0 (hex) Honeywell HomMed - B82CA0 (base 16) Honeywell HomMed - 3400 Intertech Drive - Suite 200 - Brookfield WI 53025 - UNITED STATES - - B8-30-A8 (hex) Road-Track Telematics Development - B830A8 (base 16) Road-Track Telematics Development - 15th Keren Hayesod St. - Tirat Hacarmel Israel 15223 - ISRAEL - - B8-36-D8 (hex) Videoswitch - B836D8 (base 16) Videoswitch - Uspallata 3579 - Distrito Tecnologico - Buenos Aires Capital Federal C1437JCS - ARGENTINA - - B8-38-61 (hex) Cisco - B83861 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - B8-38-CA (hex) Kyokko Tsushin System CO.,LTD - B838CA (base 16) Kyokko Tsushin System CO.,LTD - 2-25-7 sakado,Takatsu-ku - Kawasaki Kanagawa 213-0012 - JAPAN - - B8-3A-7B (hex) Worldplay (Canada) Inc. - B83A7B (base 16) Worldplay (Canada) Inc. - 803-24th Ave SE, Unit 200 - Calgary Alberta T2G 1P5 - CANADA - - B8-3D-4E (hex) Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch - B83D4E (base 16) Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch - 2/F,Building#5,1690Cailun Road,Zhangjiang Hi-tech Park, - Shanghai 201203 - CHINA - - B8-3E-59 (hex) Roku, Inc - B83E59 (base 16) Roku, Inc - 12980 Saratoga Ave. - Suite D - Saratoga CA 95070 - UNITED STATES - - B8-41-5F (hex) ASP AG - B8415F (base 16) ASP AG - Max- Planck-Str. 15 a-c - Erkrath NRW 40699 - GERMANY - - B8-43-E4 (hex) Vlatacom - B843E4 (base 16) Vlatacom - Milutina Milankovica 5 - Belgrade Serbia 11080 - SERBIA - - B8-47-C6 (hex) SanJet Technology Corp. - B847C6 (base 16) SanJet Technology Corp. - 4F,No2,Li-Hsin Rd., 6, - Hsinchu Science Park - Hsinchu 30078 - TAIWAN, PROVINCE OF CHINA - - B8-4F-D5 (hex) Microsoft Corporation - B84FD5 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - B8-55-10 (hex) Zioncom Electronics (Shenzhen) Ltd. - B85510 (base 16) Zioncom Electronics (Shenzhen) Ltd. - A1&A2 Building,Lantian Technology Park, Xinyu Road, Xingqiao Henggang Block, Shajing Street, - Baoan District - Shenzhen Guangdong 518000 - CHINA - - B8-56-BD (hex) ITT LLC - B856BD (base 16) ITT LLC - 1-ya Brestkaya St, building 35 - Moscow 125047 - RUSSIAN FEDERATION - - B8-58-10 (hex) NUMERA, INC. - B85810 (base 16) NUMERA, INC. - 1511 3RD AVE - SUITE 808 - SEATTLE WA 98101 - UNITED STATES - - B8-5A-73 (hex) Samsung Electronics Co.,Ltd - B85A73 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B8-5A-F7 (hex) Ouya, Inc - B85AF7 (base 16) Ouya, Inc - 11693 San Vicente Blvd - Suite 551 - Los Angeles CA 90049 - UNITED STATES - - B8-5A-FE (hex) Handaer Communication Technology (Beijing) Co., Ltd - B85AFE (base 16) Handaer Communication Technology (Beijing) Co., Ltd - Jiancaicheng West Rd.65,Xisanqi, - Haidian Dist - Beijing 100096 - CHINA - - B8-5E-7B (hex) Samsung Electronics Co.,Ltd - B85E7B (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B8-60-91 (hex) Onnet Technologies and Innovations LLC - B86091 (base 16) Onnet Technologies and Innovations LLC - 1, 82/83 Street, New Industrial Area -II - Saniya Industrial Area - Ajman 52141 - UNITED ARAB EMIRATES - - B8-61-6F (hex) Accton Wireless Broadband(AWB), Corp. - B8616F (base 16) Accton Wireless Broadband(AWB), Corp. - No.1 Creation Rd III, Science-based Industrial Park - Hsinchu 30077 - TAIWAN, PROVINCE OF CHINA - - B8-62-1F (hex) CISCO SYSTEMS, INC. - B8621F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - B8-63-BC (hex) ROBOTIS, Co, Ltd - B863BC (base 16) ROBOTIS, Co, Ltd - #1506 Ace high End Tower 3, 371-50 - Gasan-dong, Geumcheon-gu - Seoul 153-787 - KOREA, REPUBLIC OF - - B8-64-91 (hex) CK Telecom Ltd - B86491 (base 16) CK Telecom Ltd - Keji Avenue,Heyuan Hi-tech Development Zone - Heyuan Guangdong Province 517000 - CHINA - - B8-65-3B (hex) Bolymin, Inc. - B8653B (base 16) Bolymin, Inc. - 13F-1, No.20, Ta-Long Rd., - Taichung 40310 - TAIWAN, PROVINCE OF CHINA - - B8-6B-23 (hex) Toshiba - B86B23 (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - B8-6C-E8 (hex) Samsung Electronics Co.,Ltd - B86CE8 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B8-70-F4 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - B870F4 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN SUZHOU 215300 - CHINA - - B8-74-24 (hex) Viessmann Elektronik GmbH - B87424 (base 16) Viessmann Elektronik GmbH - Beetwiese 2 - Allendorf (Eder) 35108 - GERMANY - - B8-74-47 (hex) Convergence Technologies - B87447 (base 16) Convergence Technologies - 16W215 83rd Street Suite D - Burr Ridge IL 60527 - UNITED STATES - - B8-75-C0 (hex) PayPal, Inc. - B875C0 (base 16) PayPal, Inc. - 2211 North 1st Street - San Jose California 95131 - UNITED STATES - - B8-76-3F (hex) Hon Hai Precision Ind. Co.,Ltd. - B8763F (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - B8-77-C3 (hex) Decagon Devices, Inc. - B877C3 (base 16) Decagon Devices, Inc. - 2365 NE Hopkins Court - Pullman WA 99163 - UNITED STATES - - B8-78-2E (hex) Apple - B8782E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95051 - UNITED STATES - - B8-78-79 (hex) Roche Diagnostics GmbH - B87879 (base 16) Roche Diagnostics GmbH - Sandhofer Strasse 116 - Mannheim Baden-Wuerttemberg 68305 - GERMANY - - B8-79-7E (hex) Secure Meters (UK) Limited - B8797E (base 16) Secure Meters (UK) Limited - Secure House - Moorside Road - Winchester Hampshire SO23 7RX - UNITED KINGDOM - - B8-7A-C9 (hex) Siemens Ltd. - B87AC9 (base 16) Siemens Ltd. - 885 Mountain Hwy - Bayswater Victoria 3153 - AUSTRALIA - - B8-7C-F2 (hex) Aerohive Networks Inc. - B87CF2 (base 16) Aerohive Networks Inc. - 330 Gibraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - B8-87-1E (hex) Good Mind Industries Co., Ltd. - B8871E (base 16) Good Mind Industries Co., Ltd. - 22, Ta Yeou 2nd St, - Ta Liao Dist. - Kaohsiung 831 - TAIWAN, PROVINCE OF CHINA - - B8-87-A8 (hex) Step Ahead Innovations Inc. - B887A8 (base 16) Step Ahead Innovations Inc. - 20 Wintersport Ln. - Suite 140 - Williston VT 05495 - UNITED STATES - - B8-88-E3 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD - B888E3 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD - No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone, Jiangsu, - KUNSHAN SUZHOU 215300 - CHINA - - B8-89-CA (hex) ILJIN ELECTRIC Co., Ltd. - B889CA (base 16) ILJIN ELECTRIC Co., Ltd. - 112-83, Annyeong-dong - Hwaseong Gyeonggi-do 445-380 - KOREA, REPUBLIC OF - - B8-8A-60 (hex) Intel Corporate - B88A60 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - B8-8D-12 (hex) Apple - B88D12 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B8-8E-3A (hex) Infinite Technologies JLT - B88E3A (base 16) Infinite Technologies JLT - Office 3203, Level 32 - Liwa Heights Tower - Jumeirah Lake Towers Dubai - UNITED ARAB EMIRATES - - B8-8E-C6 (hex) Stateless Networks - B88EC6 (base 16) Stateless Networks - 388 Market Street - Suite 1300 - San Francisco CA 94111 - UNITED STATES - - B8-8F-14 (hex) Analytica GmbH - B88F14 (base 16) Analytica GmbH - Vorholzstraße 36 - Karlsruhe Baden-Württemberg 76137 - GERMANY - - B8-92-1D (hex) BG T&A - B8921D (base 16) BG T&A - 4F, L&C Tower - 1026-52 Sanbon-dong - Gunpo-si Gyeonggi-do 435-845 - KOREA, REPUBLIC OF - - B8-94-D2 (hex) Retail Innovation HTT AB - B894D2 (base 16) Retail Innovation HTT AB - Sjöängsvägen 2 - Sollentuna S-192 72 - SWEDEN - - B8-96-74 (hex) AllDSP GmbH & Co. KG - B89674 (base 16) AllDSP GmbH & Co. KG - Spenglerstrasse 6 - Hamm NRW 59067 - GERMANY - - B8-97-5A (hex) BIOSTAR Microtech Int'l Corp. - B8975A (base 16) BIOSTAR Microtech Int'l Corp. - 2Fl. No. 108-2, Min Chuan Road, Hsin Tien Dist., - New Taipei 231 - TAIWAN, PROVINCE OF CHINA - - B8-98-B0 (hex) Atlona Inc. - B898B0 (base 16) Atlona Inc. - 70 Daggett Dr. - San Jose CA 95134 - UNITED STATES - - B8-98-F7 (hex) Gionee Communication Equipment Co,Ltd.ShenZhen - B898F7 (base 16) Gionee Communication Equipment Co,Ltd.ShenZhen - 21/F Times Technology Building, 7028 Shennan Road, - Futian District - Shenzhen Guangdong 518040 - CHINA - - B8-99-19 (hex) 7signal Solutions, Inc - B89919 (base 16) 7signal Solutions, Inc - 526 S. Main Street - Suite 601G - Akron OH 44311 - UNITED STATES - - B8-99-B0 (hex) Cohere Technologies - B899B0 (base 16) Cohere Technologies - 404 Saratoga Avenue - Suite 200 - Santa Clara CA 95050 - UNITED STATES - - B8-9A-CD (hex) ELITE OPTOELECTRONIC(ASIA)CO.,LTD - B89ACD (base 16) ELITE OPTOELECTRONIC(ASIA)CO.,LTD - A9 jin Fu 1 Road,Tangchun lndustrial zone,Liaobu Town,Dongguan City,Guangdong Province - Liaobu dongguan /guangdong 523400 - CHINA - - B8-9A-ED (hex) OceanServer Technology, Inc - B89AED (base 16) OceanServer Technology, Inc - 151 Martine St - Fall River MA 02723 - UNITED STATES - - B8-9B-C9 (hex) SMC Networks Inc - B89BC9 (base 16) SMC Networks Inc - 20 Mason - Irvine CA 92618 - UNITED STATES - - B8-9B-E4 (hex) ABB Power Systems Power Generation - B89BE4 (base 16) ABB Power Systems Power Generation - 29801 Euclid Ave - Wickliffe Ohio 44092 - UNITED STATES - - B8-A3-86 (hex) D-Link International - B8A386 (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy Singapore 609917 - 609917 - SINGAPORE - - B8-A3-E0 (hex) BenRui Technology Co.,Ltd - B8A3E0 (base 16) BenRui Technology Co.,Ltd - No.3A room A Unit Hongsong Building - TaiRan TechnoPark.FuTian District - ShenZhen GuangDong 518000 - CHINA - - B8-A8-AF (hex) Logic S.p.A. - B8A8AF (base 16) Logic S.p.A. - Via Galilei 5 - Cassina de' Pecchi MI 20060 - ITALY - - B8-AC-6F (hex) Dell Inc - B8AC6F (base 16) Dell Inc - One Dell Way, MS RR5-45 - Round Rock TX 78748 - UNITED STATES - - B8-AD-3E (hex) BLUECOM - B8AD3E (base 16) BLUECOM - 116, Venture-ro, Yeonsu-gu, - Incheon 406-840 - KOREA, REPUBLIC OF - - B8-AE-6E (hex) Nintendo Co., Ltd. - B8AE6E (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO KYOTO 601-8501 - JAPAN - - B8-AE-ED (hex) Elitegroup Computer Systems Co., Ltd. - B8AEED (base 16) Elitegroup Computer Systems Co., Ltd. - No. 239, Sec. 2, Ti Ding Blvd., - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - B8-AF-67 (hex) Hewlett-Packard Company - B8AF67 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - B8-B1-C7 (hex) BT&COM CO.,LTD - B8B1C7 (base 16) BT&COM CO.,LTD - #1103, E&C Venture Dream Tower II - 197-10, Guro-3dong, Guro-Gu, - Seoul 152-719 - KOREA, REPUBLIC OF - - B8-B3-DC (hex) DEREK (SHAOGUAN) LIMITED - B8B3DC (base 16) DEREK (SHAOGUAN) LIMITED - Gaojiling, Taiping Town, - Shixing County - Shao Guan Guang Dong 512500 - CHINA - - B8-B4-2E (hex) Gionee Communication Equipment Co,Ltd.ShenZhen - B8B42E (base 16) Gionee Communication Equipment Co,Ltd.ShenZhen - 21/F Times Technology Building, 7028 Shennan Road, Futian District, - Shenzhen Guangdong 518040 - CHINA - - B8-B7-D7 (hex) 2GIG Technologies - B8B7D7 (base 16) 2GIG Technologies - 2961 West Maple Loop Drive - Lehi Utah 84043 - UNITED STATES - - B8-B8-1E (hex) Intel Corporate - B8B81E (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - B8-B9-4E (hex) Shenzhen iBaby Labs, Inc. - B8B94E (base 16) Shenzhen iBaby Labs, Inc. - Room 218, Building 17,Shangsha Innovation Science and Technology Park,Futian District - Shenzhen Guangdong 518047 - CHINA - - B8-BA-68 (hex) Xi'an Jizhong Digital Communication Co.,Ltd - B8BA68 (base 16) Xi'an Jizhong Digital Communication Co.,Ltd - 10 Block NO.1 Enterprise Newly-typed Industrial Zone High-Tech Zone Xi¡¯an,China - Xi'an ShaanXi 710119 - CHINA - - B8-BA-72 (hex) Cynove - B8BA72 (base 16) Cynove - 10 cite rougemont - Paris 75009 - FRANCE - - B8-BB-6D (hex) ENERES Co.,Ltd. - B8BB6D (base 16) ENERES Co.,Ltd. - 1907 Tokyo Art Center - 1-4-1 Senjyu - Adahci-ku Tokyo 120-0034 - JAPAN - - B8-BC-1B (hex) Huawei Technologies Co., Ltd - B8BC1B (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - B8-BD-79 (hex) TrendPoint Systems - B8BD79 (base 16) TrendPoint Systems - 1595 East 6th Street - Suite 101 - Corona CA 92879 - UNITED STATES - - B8-BE-BF (hex) CISCO SYSTEMS, INC. - B8BEBF (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - B8-BF-83 (hex) Intel Corporate - B8BF83 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - B8-C1-A2 (hex) Dragon Path Technologies Co., Limited - B8C1A2 (base 16) Dragon Path Technologies Co., Limited - 12/F., San Toi Building, - 137-139 Connaught Road - Central Hong Kong - HONG KONG - - B8-C3-BF (hex) Henan Chengshi NetWork Technology Co.,Ltd - B8C3BF (base 16) Henan Chengshi NetWork Technology Co.,Ltd - Ruhe Road South,Kunlun Road West,Zhongyuan District,Zhengzhou,Henan,P.R.China,450007 - Zhengzhou Henan 450007 - CHINA - - B8-C4-6F (hex) PRIMMCON INDUSTRIES INC - B8C46F (base 16) PRIMMCON INDUSTRIES INC - 137 MinQuan Rd, 5th Floor, - XinDian dist. - New Taipei 23141 - TAIWAN, PROVINCE OF CHINA - - B8-C6-8E (hex) Samsung Electronics Co.,Ltd - B8C68E (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B8-C7-16 (hex) Fiberhome Telecommunication Technologies Co.,LTD - B8C716 (base 16) Fiberhome Telecommunication Technologies Co.,LTD - No.5 Dongxin Road - Hongshan District - Wuhan Hubei 430074 - CHINA - - B8-C7-5D (hex) Apple - B8C75D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B8-C8-55 (hex) Shanghai GBCOM Communication Technology Co.,Ltd. - B8C855 (base 16) Shanghai GBCOM Communication Technology Co.,Ltd. - Room 602, Building 6, No. - 555 Dongchuan Road - Shanghai 200241 - CHINA - - B8-CA-3A (hex) Dell Inc - B8CA3A (base 16) Dell Inc - One Dell Way - MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - B8-CD-93 (hex) Penetek, Inc - B8CD93 (base 16) Penetek, Inc - 6F, No.18, Wuqun 7th Rd, Wugu Dist - New Taipei City 248 - TAIWAN, PROVINCE OF CHINA - - B8-CD-A7 (hex) Maxeler Technologies Ltd. - B8CDA7 (base 16) Maxeler Technologies Ltd. - 1 Down Place - London UK W6 9JH - UNITED KINGDOM - - B8-D0-6F (hex) GUANGZHOU HKUST FOK YING TUNG RESEARCH INSTITUTE - B8D06F (base 16) GUANGZHOU HKUST FOK YING TUNG RESEARCH INSTITUTE - Rm 403, North of Software Building,Nansha IT Park, - Nansha District - Guangzhou Guangdong Privince 511458 - CHINA - - B8-D4-9D (hex) M Seven System Ltd. - B8D49D (base 16) M Seven System Ltd. - 24F, Trust Tower Bldg, 275-7, Yangjae2-Dong, Seocho-Gu - Seoul 137-739 - KOREA, REPUBLIC OF - - B8-D8-12 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - B8D812 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - B8-D9-CE (hex) Samsung Electronics - B8D9CE (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - B8-DA-F1 (hex) Strahlenschutz- Entwicklungs- und Ausruestungsgesellschaft mbH - B8DAF1 (base 16) Strahlenschutz- Entwicklungs- und Ausruestungsgesellschaft mbH - Ostdamm 139 - Duelmen NRW 48249 - GERMANY - - B8-DA-F7 (hex) Advanced Photonics, Inc. - B8DAF7 (base 16) Advanced Photonics, Inc. - the University of Tokyo, CCR507 - Komaba 4-6-1 - Meguro-ku Tokyo 153-8904 - JAPAN - - B8-DC-87 (hex) IAI Corporation - B8DC87 (base 16) IAI Corporation - 577-1 Obane - Shimizu-Ku - Shizuoka-City Shizuoka 424-0103 - JAPAN - - B8-DF-6B (hex) SpotCam Co., Ltd. - B8DF6B (base 16) SpotCam Co., Ltd. - 12F.-1, No.125, Jianguo Rd. - Yingge Dist - New Taipei City 239 - TAIWAN, PROVINCE OF CHINA - - B8-E5-89 (hex) Payter BV - B8E589 (base 16) Payter BV - Rozenlaan 115 - Rotterdam Zuid-Holland 3051 LP - NETHERLANDS - - B8-E6-25 (hex) 2Wire - B8E625 (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - B8-E7-79 (hex) 9Solutions Oy - B8E779 (base 16) 9Solutions Oy - Teknologiantie 2 - 90590 - Oulu - FINLAND - - B8-E8-56 (hex) Apple - B8E856 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B8-E9-37 (hex) Sonos, Inc. - B8E937 (base 16) Sonos, Inc. - 223 East De La Guerra Street - Santa Barbara CA 93101 - UNITED STATES - - B8-EE-65 (hex) Liteon Technology Corporation - B8EE65 (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, - TaiPei TaiWan 23585 - TAIWAN, PROVINCE OF CHINA - - B8-EE-79 (hex) YWire Technologies, Inc. - B8EE79 (base 16) YWire Technologies, Inc. - 1372 Overdale - Montreal QC H3G 1V3 - CANADA - - B8-F0-80 (hex) SPS, INC. - B8F080 (base 16) SPS, INC. - 70, Techno8-ro - Yuseong-gu Daejeon 305-500 - KOREA, REPUBLIC OF - - B8-F3-17 (hex) iSun Smasher Communications Private Limited - B8F317 (base 16) iSun Smasher Communications Private Limited - No. 826, Ferns Paradise, 2nd Street, - Doddanekkundi, Marathahalli - Bangalore Karnataka 560037 - INDIA - - B8-F4-D0 (hex) Herrmann Ultraschalltechnik GmbH & Co. Kg - B8F4D0 (base 16) Herrmann Ultraschalltechnik GmbH & Co. Kg - Descostraße 3-9 - Karlsbad Baden-Württemberg 76307 - GERMANY - - B8-F5-E7 (hex) WayTools, LLC - B8F5E7 (base 16) WayTools, LLC - 401 Wilshire Blvd. - Ninth Floor - Santa Monica CA 90401 - UNITED STATES - - B8-F6-B1 (hex) Apple - B8F6B1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B8-F7-32 (hex) Aryaka Networks Inc - B8F732 (base 16) Aryaka Networks Inc - 691 S. Milpitas Blvd., - Suite 206 - Milpitas CA 95035 - UNITED STATES - - B8-F8-28 (hex) Changshu Gaoshida Optoelectronic Technology Co. Ltd. - B8F828 (base 16) Changshu Gaoshida Optoelectronic Technology Co. Ltd. - Baimao Industrail Park Changshu Jiangsu - Changshu Jiangsu 215500 - CHINA - - B8-F9-34 (hex) Sony Ericsson Mobile Communications AB - B8F934 (base 16) Sony Ericsson Mobile Communications AB - Nya Vattentornet - Lund SE 221 88 - SWEDEN - - B8-FD-32 (hex) Zhejiang ROICX Microelectronics - B8FD32 (base 16) Zhejiang ROICX Microelectronics - 22 Floor, 1888 Jianghui Road, Binjiang District - Hangzhou Zhejiang 310051 - CHINA - - B8-FF-61 (hex) Apple - B8FF61 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - B8-FF-6F (hex) Shanghai Typrotech Technology Co.Ltd - B8FF6F (base 16) Shanghai Typrotech Technology Co.Ltd - Design Building 903, NO.63, - ChiFeng Road,YangPu District, - Shanghai 200092 - CHINA - - B8-FF-FE (hex) Texas Instruments - B8FFFE (base 16) Texas Instruments - 12500 TI Boulevard - MS 8723 - Dallas TX 75243 - UNITED STATES - - BC-02-00 (hex) Stewart Audio - BC0200 (base 16) Stewart Audio - 100 West El Camino Real - Suite 72 - Mountain View CA 94041 - UNITED STATES - - BC-05-43 (hex) AVM GmbH - BC0543 (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - BC-0D-A5 (hex) Texas Instruments - BC0DA5 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - BC-0F-2B (hex) FORTUNE TECHGROUP CO.,LTD - BC0F2B (base 16) FORTUNE TECHGROUP CO.,LTD - 7-8F,No.1198 North Qinzhou Road, - Shanghai 200233 - CHINA - - BC-0F-64 (hex) Intel Corporate - BC0F64 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - BC-12-5E (hex) Beijing WisVideo INC. - BC125E (base 16) Beijing WisVideo INC. - RM 3A08 Technology&Fortune Center A block No.8 Xue Qing Road,Haidian District , - Beijing 100192 - CHINA - - BC-14-01 (hex) Hitron Technologies. Inc - BC1401 (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300 - Hsin-chu 300 - TAIWAN, PROVINCE OF CHINA - - BC-14-85 (hex) Samsung Electronics Co.,Ltd - BC1485 (base 16) Samsung Electronics Co.,Ltd - 129, Samsung-ro, Youngtongl-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - BC-14-EF (hex) ITON Technology Limited - BC14EF (base 16) ITON Technology Limited - Room 1302,A ablock, Building 4 - TianAn Cyber park, Long Gang district - ShenZhen GuangDong Pronvice 518000 - CHINA - - BC-15-A6 (hex) Taiwan Jantek Electronics,Ltd. - BC15A6 (base 16) Taiwan Jantek Electronics,Ltd. - 6F-1,No.1 Wu-Chuan 1St. Rd,Wu-Ku Industrial Park, - Sinchwang City Taipei Hsien 24892 - TAIWAN, PROVINCE OF CHINA - - BC-16-65 (hex) Cisco - BC1665 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - BC-16-F5 (hex) Cisco - BC16F5 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - BC-1A-67 (hex) YF Technology Co., Ltd - BC1A67 (base 16) YF Technology Co., Ltd - No.62,South Fumin Road, - Fumin Industrial Park, Dalang Town, - Dongguang Guangdong 523773 - CHINA - - BC-20-A4 (hex) Samsung Electronics - BC20A4 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - BC-20-BA (hex) Inspur (Shandong) Electronic Information Co., Ltd - BC20BA (base 16) Inspur (Shandong) Electronic Information Co., Ltd - No.1036 Shunya Rd. - Jinan Shandong 250101 - CHINA - - BC-25-E0 (hex) Huawei Technologies Co., Ltd - BC25E0 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - BC-25-F0 (hex) 3D Display Technologies Co., Ltd. - BC25F0 (base 16) 3D Display Technologies Co., Ltd. - 4F., No.542-17, Zhongzheng Rd - Xinzhuang Dist - New Taipei City 242 - TAIWAN, PROVINCE OF CHINA - - BC-26-1D (hex) HONG KONG TECON TECHNOLOGY - BC261D (base 16) HONG KONG TECON TECHNOLOGY - ROOM 2802,BLOCK A,SHEN FANG OLAZA - REN MIN ROAD SOUTH - Shenzhen Guangdong 518000 - CHINA - - BC-28-46 (hex) NextBIT Computing Pvt. Ltd. - BC2846 (base 16) NextBIT Computing Pvt. Ltd. - 30/2, 2nd Floor, R.K. Plaza, - CMH Road, Indiranagar - Bangalore Karnataka 560038 - INDIA - - BC-28-D6 (hex) Rowley Associates Limited - BC28D6 (base 16) Rowley Associates Limited - Suite 4B/4C Drake House - Drake Lane - Dursley Gloucestershire GL11 4HH - UNITED KINGDOM - - BC-2B-6B (hex) Beijing Haier IC Design Co.,Ltd - BC2B6B (base 16) Beijing Haier IC Design Co.,Ltd - Room 205, Tongheng Building, No.4 Huayuan Road, Haidian District - Beijing, China - Beijing Beijing 100088 - CHINA - - BC-2B-D7 (hex) Revogi Innovation Co., Ltd. - BC2BD7 (base 16) Revogi Innovation Co., Ltd. - 2018, Anhui Building, No. 6007, - Shennan Boulevard, - Shenzhen Guangdong 518113 - CHINA - - BC-2C-55 (hex) Bear Flag Design, Inc. - BC2C55 (base 16) Bear Flag Design, Inc. - 1 Thayer Road - Santa Cruz CA 95060 - UNITED STATES - - BC-2D-98 (hex) ThinGlobal LLC - BC2D98 (base 16) ThinGlobal LLC - 703 wildflower RD - Davenport FL 33837 - UNITED STATES - - BC-30-5B (hex) Dell Inc. - BC305B (base 16) Dell Inc. - One Dell Way, MS RR5-45 - Round Rock Texas 78682 - UNITED STATES - - BC-30-7D (hex) Wistron Neweb Corp. - BC307D (base 16) Wistron Neweb Corp. - 20 Park Avenue II. Hsinchu Science Park - HsinChu Taiwan 308 - TAIWAN, PROVINCE OF CHINA - - BC-34-00 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - BC3400 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - BC-35-E5 (hex) Hydro Systems Company - BC35E5 (base 16) Hydro Systems Company - 3798 Round Bottom Road - Cincinnati Ohio 45244 - UNITED STATES - - BC-38-D2 (hex) Pandachip Limited - BC38D2 (base 16) Pandachip Limited - Unit 210, 2/F (Lakeside 1), Building 15, No. 8 Science Park West Avenue - Hong Kong Science Park Phase II, - Shatin, N.T. - HONG KONG - - BC-39-A6 (hex) CSUN System Technology Co.,LTD - BC39A6 (base 16) CSUN System Technology Co.,LTD - 4-16-22,Chiyogaoka - Asao Ku - Kawasaki-shi Kanagawa Ken 2150005 - JAPAN - - BC-3A-EA (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - BC3AEA (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - NO.18 HAIBIN ROAD,WUSHA,CHANG'AN - DONGGUAN GUANGDONG 523860 - CHINA - - BC-3B-AF (hex) Apple - BC3BAF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - BC-3E-13 (hex) Accordance Systems Inc. - BC3E13 (base 16) Accordance Systems Inc. - 2F, No. 31, Sec. 6, Hsin Yi Road - Taipei 11085 - TAIWAN, PROVINCE OF CHINA - - BC-41-00 (hex) Codaco Electronic s.r.o. - BC4100 (base 16) Codaco Electronic s.r.o. - Hemy 825 - Valasske Mezirici Vsetin 75701 - CZECH REPUBLIC - - BC-43-77 (hex) Hang Zhou Huite Technology Co.,ltd. - BC4377 (base 16) Hang Zhou Huite Technology Co.,ltd. - Rm1338,Block A¬FuLi Technology Building ,No.328,WenEr Rd - Hang Zhou Zhe Jiang 310012 - CHINA - - BC-44-86 (hex) Samsung Electronics Co.,Ltd - BC4486 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - BC-47-60 (hex) Samsung Electronics Co.,Ltd - BC4760 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - BC-4B-79 (hex) SensingTek - BC4B79 (base 16) SensingTek - 2F, No.6-2,Dusing Rd.,Hsinchu Science Park, - Hsinchu 30078 - TAIWAN, PROVINCE OF CHINA - - BC-4C-C4 (hex) Apple - BC4CC4 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - BC-4D-FB (hex) Hitron Technologies. Inc - BC4DFB (base 16) Hitron Technologies. Inc - No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C - Hsin-chu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - BC-4E-3C (hex) CORE STAFF CO., LTD. - BC4E3C (base 16) CORE STAFF CO., LTD. - Shin-osaka Oriental Bldg. 14F, 7-1-26 Nishinakajima - Yodogawa-ku Osaka 532-0011 - JAPAN - - BC-4E-5D (hex) ZhongMiao Technology Co., Ltd. - BC4E5D (base 16) ZhongMiao Technology Co., Ltd. - NO.2009 Lihu Avenue, WuxiStudioA-A3 - Wuxi Jiangsu 214000 - CHINA - - BC-51-FE (hex) Swann Communications Pty Ltd - BC51FE (base 16) Swann Communications Pty Ltd - Unit 13 - 331 Ingles Street - Port Melbourne Victoria 3207 - AUSTRALIA - - BC-52-B4 (hex) Alcatel-Lucent - BC52B4 (base 16) Alcatel-Lucent - 600 March Road - Ottawa ON K2K 2E6 - CANADA - - BC-52-B7 (hex) Apple - BC52B7 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - BC-54-F9 (hex) Drogoo Technology Co., Ltd. - BC54F9 (base 16) Drogoo Technology Co., Ltd. - Shenzhen Dayun software town 17 2 floor - Longgang Road No. 8288. Longgang District - Shenzhen Guangdong 518172 - CHINA - - BC-5C-4C (hex) ELECOM CO.,LTD. - BC5C4C (base 16) ELECOM CO.,LTD. - 11F Tokyubancho Bldg. 6-2, - Yonbancho, - Chiyoda-ku Tokyo 102-0081 - JAPAN - - BC-5F-F4 (hex) ASRock Incorporation - BC5FF4 (base 16) ASRock Incorporation - 2F.,No.37, Sec.2, Jhongyang S.Rd., Beitou Distric, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - BC-60-10 (hex) Qingdao Hisense Communications Co.,Ltd - BC6010 (base 16) Qingdao Hisense Communications Co.,Ltd - 218 Qian wan gang Road Economic & - Technological Development Zone - Qingdao Shandong 266510 - CHINA - - BC-62-9F (hex) Telenet Systems P. Ltd. - BC629F (base 16) Telenet Systems P. Ltd. - 2 Mani Bhuvan, Cama Road - Ghatkopar - Mumbai Maharashtra 400086 - INDIA - - BC-66-41 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - BC6641 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - BC-67-1C (hex) Cisco - BC671C (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - BC-67-78 (hex) Apple - BC6778 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - BC-67-84 (hex) Environics Oy - BC6784 (base 16) Environics Oy - Graanintie 5 - Mikkeli 50190 - FINLAND - - BC-6A-16 (hex) tdvine - BC6A16 (base 16) tdvine - 301 Maison Maru Building - 86-9 Nonheon-dong Gangnam-gu - Seoul 135-010 - KOREA, REPUBLIC OF - - BC-6A-29 (hex) Texas Instruments - BC6A29 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - BC-6A-2F (hex) Henge Docks LLC - BC6A2F (base 16) Henge Docks LLC - 455 10th St. - San Francisco California 94103 - UNITED STATES - - BC-6B-4D (hex) Alcatel-Lucent - BC6B4D (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - BC-6E-64 (hex) Sony Mobile Communications AB - BC6E64 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - BC-6E-76 (hex) Green Energy Options Ltd - BC6E76 (base 16) Green Energy Options Ltd - 3 St. Mary's Court, Main Street - Hardwick - Cambridge Cambridgeshire CB23 7QS - UNITED KINGDOM - - BC-71-C1 (hex) XTrillion, Inc. - BC71C1 (base 16) XTrillion, Inc. - 1-12-3-4F - Kanda Suda-cho - Chiyoda-ku Tokyo 101-0041 - JAPAN - - BC-72-B1 (hex) Samsung Electronics Co.,Ltd - BC72B1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - BC-74-D7 (hex) HangZhou JuRu Technology CO.,LTD - BC74D7 (base 16) HangZhou JuRu Technology CO.,LTD - No.803 Room,Shuyu Building,No.98 Wenyi West Road,Hangzhou,Zhejiang,China - hangzhou zhejiang 310053 - CHINA - - BC-76-4E (hex) Rackspace US, Inc. - BC764E (base 16) Rackspace US, Inc. - 5000 Walzem Rd. - San Antonio TX 78218 - UNITED STATES - - BC-76-70 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - BC7670 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - BC-77-37 (hex) Intel Corporate - BC7737 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - BC-77-9F (hex) SBM Co., Ltd. - BC779F (base 16) SBM Co., Ltd. - Hyunwoo Bldg 206, Anyang7-Dong - Manan-Gu - Anyang Gyeonggi-Do 430-817 - KOREA, REPUBLIC OF - - BC-79-AD (hex) Samsung Electronics Co.,Ltd - BC79AD (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - BC-7D-D1 (hex) Radio Data Comms - BC7DD1 (base 16) Radio Data Comms - 5/20-30 Stubbs Street - Silverwater New South Wales (NSW) 2128 - AUSTRALIA - - BC-81-1F (hex) Ingate Systems - BC811F (base 16) Ingate Systems - Rissneleden 45 - Sundbyberg 17444 - SWEDEN - - BC-81-99 (hex) BASIC Co.,Ltd. - BC8199 (base 16) BASIC Co.,Ltd. - Keiefu-Building 9F - 4-13-8 Shiba - Minato-ku Tokyo 108-0014 - JAPAN - - BC-83-A7 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LT - BC83A7 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LT - Unit A 13-16/F,Skyworth Bldg., Gaoxin Ave.1.S.,Nanshan District - Shenzhen GuangDong 518057 - CHINA - - BC-85-1F (hex) Samsung Electronics - BC851F (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - BC-85-56 (hex) Hon Hai Precision Ind. Co.,Ltd. - BC8556 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - BC-88-93 (hex) VILLBAU Ltd. - BC8893 (base 16) VILLBAU Ltd. - Üllöi ut 611. - Budapest - H-1182 - HUNGARY - - BC-8B-55 (hex) NPP ELIKS America Inc. DBA T&M Atlantic - BC8B55 (base 16) NPP ELIKS America Inc. DBA T&M Atlantic - 175 SW 7th St Suite 1812 - Miami FL 33130 - UNITED STATES - - BC-8C-CD (hex) Samsung Electro Mechanics co.,LTD. - BC8CCD (base 16) Samsung Electro Mechanics co.,LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - BC-8D-0E (hex) Alcatel-Lucent - BC8D0E (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - BC-92-6B (hex) Apple - BC926B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - BC-96-80 (hex) Shenzhen Gongjin Electronics Co.,Ltd - BC9680 (base 16) Shenzhen Gongjin Electronics Co.,Ltd - B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 - Nanshan Medical Instrument Industry Park,1019# Nanhai Road, - Nanshan District, Shenzhen Guangdong 518067 - CHINA - - BC-98-89 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - BC9889 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - BC-99-BC (hex) FonSee Technology Inc. - BC99BC (base 16) FonSee Technology Inc. - 14F-2, No.32, Gaotie 2nd Rd., - Zhubei City Hsinchu County 302 - TAIWAN, PROVINCE OF CHINA - - BC-9C-C5 (hex) Beijing Huafei Technology Co., Ltd. - BC9CC5 (base 16) Beijing Huafei Technology Co., Ltd. - 2 floor, Research building, Guanghua Pioneer Park, No.18, Anningzhuang East Rd, Haidian District, Beijing, China. - Beijing Beijing 100085 - CHINA - - BC-9D-A5 (hex) DASCOM Europe GmbH - BC9DA5 (base 16) DASCOM Europe GmbH - Heuweg 3 - Ulm Baden-Württemberg 89079 - GERMANY - - BC-A4-E1 (hex) Nabto - BCA4E1 (base 16) Nabto - Aabogade 15 - Aarhus Jutland 8200 - DENMARK - - BC-A9-D6 (hex) Cyber-Rain, Inc. - BCA9D6 (base 16) Cyber-Rain, Inc. - 5272 Evanwood Avenue - Oak Park California 91377-4809 - UNITED STATES - - BC-AE-C5 (hex) ASUSTek COMPUTER INC. - BCAEC5 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - BC-B1-81 (hex) SHARP CORPORATION - BCB181 (base 16) SHARP CORPORATION - 22-22,Nagaike-cho, - Abeno-KU, - Osaka, 545-8522 - JAPAN - - BC-B1-F3 (hex) Samsung Electronics - BCB1F3 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - BC-B3-08 (hex) HONGKONG RAGENTEK COMMUNICATION TECHNOLOGY CO.,LIMITED - BCB308 (base 16) HONGKONG RAGENTEK COMMUNICATION TECHNOLOGY CO.,LIMITED - Building D10-D11 - No. 58-60, Lane 3188, Xiipu Road - PuDong District Shanghai 201315 - CHINA - - BC-B8-52 (hex) Cybera, Inc. - BCB852 (base 16) Cybera, Inc. - 9009 Carothers Parkway - Suite C-5 - Franklin TN 37067 - UNITED STATES - - BC-BA-E1 (hex) AREC Inc. - BCBAE1 (base 16) AREC Inc. - 3F, No.367, Sec.2, Wenhua Rd - Banqiao Dist New Taipei City 220 - TAIWAN, PROVINCE OF CHINA - - BC-BB-C9 (hex) Kellendonk Elektronik GmbH - BCBBC9 (base 16) Kellendonk Elektronik GmbH - Butzweilerhof Allee 4 - Cologne NRW 50829 - GERMANY - - BC-BC-46 (hex) SKS Welding Systems GmbH - BCBC46 (base 16) SKS Welding Systems GmbH - Marie-Curie-Str. 14 - Kaiserslautern Rheinlandpfalz 67661 - GERMANY - - BC-C1-68 (hex) DinBox Sverige AB - BCC168 (base 16) DinBox Sverige AB - Surbrunnsgatan 14 - Stockholm 11427 - SWEDEN - - BC-C2-3A (hex) Thomson Video Networks - BCC23A (base 16) Thomson Video Networks - 6, rue du Clos Courtel - Cesson Sevigne 35510 - FRANCE - - BC-C3-42 (hex) Panasonic System Networks Co., Ltd. - BCC342 (base 16) Panasonic System Networks Co., Ltd. - 4-1-62 Minoshima Hakata-ku - Fukuoka city Fukuoka 812-8531 - JAPAN - - BC-C4-93 (hex) Cisco - BCC493 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - BC-C6-1A (hex) SPECTRA EMBEDDED SYSTEMS - BCC61A (base 16) SPECTRA EMBEDDED SYSTEMS - Khasra No. 24, Village Ghumman,1st Floor, Chawla Mansion, - B/h. Sant Vihar, Uncha Parwanoo,Sector-1 - PARWANOO HIMACHAL PRADESH 173220 - INDIA - - BC-C6-DB (hex) Nokia Corporation - BCC6DB (base 16) Nokia Corporation - Joensuunkatu 7E - Salo 24101 - FINLAND - - BC-C8-10 (hex) Cisco SPVTG - BCC810 (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville GA 30044 - UNITED STATES - - BC-CA-B5 (hex) ARRIS Group, Inc. - BCCAB5 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - BC-CD-45 (hex) VOISMART - BCCD45 (base 16) VOISMART - VIA BENIGNO CRESPI 12 - MILANO 20159 - ITALY - - BC-CF-CC (hex) HTC Corporation - BCCFCC (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - BC-D1-65 (hex) Cisco SPVTG - BCD165 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - BC-D1-77 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - BCD177 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) Central Science and Technology Park,Shennan Rd - Shenzhen Guandong 518057 - CHINA - - BC-D1-D3 (hex) Tinno Mobile Technology Corp - BCD1D3 (base 16) Tinno Mobile Technology Corp - 4/F.,H-3 Building,OCT Eastern lndustrial Park. - NO.1 XiangShan East Road - Nanshan, Shenzhen GUANGDONG 518053 - CHINA - - BC-D5-B6 (hex) d2d technologies - BCD5B6 (base 16) d2d technologies - 10611 roundwood glen ct - Jacksonville Fl 32256 - UNITED STATES - - BC-D9-40 (hex) ASR Co,.Ltd. - BCD940 (base 16) ASR Co,.Ltd. - 1-3-1 Sotokanda Chiyoda-ku - Tokyo 101-0021 - JAPAN - - BC-E0-9D (hex) Eoslink - BCE09D (base 16) Eoslink - #602, 900-1 - Gwanyang-Dong, Dongan-Gu - Anyang-City Kyonggi-Do 431-060 - KOREA, REPUBLIC OF - - BC-E5-9F (hex) WATERWORLD Technology Co.,LTD - BCE59F (base 16) WATERWORLD Technology Co.,LTD - 6 Floor,Block B,Digital Building,Garden City,No.1079,Nanhai Road,Nanshan District, - Shenzhen Guangdong 518067 - CHINA - - BC-E7-67 (hex) Quanzhou TDX Electronics Co., Ltd - BCE767 (base 16) Quanzhou TDX Electronics Co., Ltd - Hi-tech Park economic and tech development zone - Quanzhou Fujian province 362005 - CHINA - - BC-EA-2B (hex) CityCom GmbH - BCEA2B (base 16) CityCom GmbH - Am Kroit 25 - Amerang Bavaria 83123 - GERMANY - - BC-EA-FA (hex) Hewlett Packard - BCEAFA (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - BC-EB-5F (hex) Fujian Beifeng Telecom Technology Co., Ltd. - BCEB5F (base 16) Fujian Beifeng Telecom Technology Co., Ltd. - A-15, Huaqiao Economic Development Zone, Shuangyang, Luojiang, - quanzhou fujian 362000 - CHINA - - BC-EC-23 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD - BCEC23 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD - Unit A13-16/F,Skyworth Bldg - Gaoxin Ave.1.S.,Nanshan District, - ShenZhen GuangDong 518057 - CHINA - - BC-EE-7B (hex) ASUSTek COMPUTER INC. - BCEE7B (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - BC-F1-F2 (hex) Cisco - BCF1F2 (base 16) Cisco - 170 West Tasman Drive - San Jose CA 95134 - UNITED STATES - - BC-F2-AF (hex) devolo AG - BCF2AF (base 16) devolo AG - Charlottenburger Allee 60 - Aachen 52068 - GERMANY - - BC-F5-AC (hex) LG Electronics - BCF5AC (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - BC-F6-1C (hex) Geomodeling Wuxi Technology Co. Ltd. - BCF61C (base 16) Geomodeling Wuxi Technology Co. Ltd. - Room1708, 17/F, North Star Times Tower, No.8 BeiChen East Road - Chaoyang District - Beijing 100101 - CHINA - - BC-F6-85 (hex) D-Link International - BCF685 (base 16) D-Link International - 1 International Business Park, #03-12 - , The Synergy - Singapore 609917 - SINGAPORE - - BC-F8-11 (hex) Xiamen DNAKE Technology Co.,Ltd - BCF811 (base 16) Xiamen DNAKE Technology Co.,Ltd - 5F,Xingtel Building,Chuangxin Rd. - Torch Hi-Tech Industrial District, - Xiamen Fujian 361006 - CHINA - - BC-FE-8C (hex) Altronic, LLC - BCFE8C (base 16) Altronic, LLC - 712 Trumbull Ave - Girard Ohio 44420 - UNITED STATES - - BC-FF-AC (hex) TOPCON CORPORATION - BCFFAC (base 16) TOPCON CORPORATION - 75-1, Hasunuma-cho - Itabashi-ku TOKYO 174-8580 - JAPAN - - C0-05-C2 (hex) ARRIS Group, Inc. - C005C2 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - C0-0D-7E (hex) Additech, Inc. - C00D7E (base 16) Additech, Inc. - 10925 Kinghurst - Suite 500 - Houston TX 77099 - UNITED STATES - - C0-11-A6 (hex) Fort-Telecom ltd. - C011A6 (base 16) Fort-Telecom ltd. - Hrustalnaya 8a - Perm 614107 - RUSSIAN FEDERATION - - C0-12-42 (hex) Alpha Security Products - C01242 (base 16) Alpha Security Products - 10715 Sikes Place, Ste. 200 - Charlotte NC 28277 - UNITED STATES - - C0-14-3D (hex) Hon Hai Precision Ind. Co.,Ltd. - C0143D (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - C0-18-85 (hex) Hon Hai Precision Ind. Co.,Ltd. - C01885 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - C0-1A-DA (hex) Apple - C01ADA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C0-1E-9B (hex) Pixavi AS - C01E9B (base 16) Pixavi AS - Dusavikveien 39 - Stavanger 4003 - NORWAY - - C0-22-50 (hex) PRIVATE - C02250 (base 16) - - C0-25-06 (hex) AVM GmbH - C02506 (base 16) AVM GmbH - Alt-Moabit 95 - Berlin 10559 - GERMANY - - C0-25-5C (hex) Cisco - C0255C (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - C0-25-67 (hex) Nexxt Solutions - C02567 (base 16) Nexxt Solutions - 3505 NW 107TH AVENUE - MIAMI FLORIDA 33178 - UNITED STATES - - C0-27-B9 (hex) Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd. - C027B9 (base 16) Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd. - Building No.18, Huayuan YiLi,Fengtai District, - Beijing 100073 - CHINA - - C0-29-73 (hex) Audyssey Laboratories Inc. - C02973 (base 16) Audyssey Laboratories Inc. - 110 E. 9th Street, Suite C700 - Los Angeles CA 90079 - UNITED STATES - - C0-29-F3 (hex) XySystem - C029F3 (base 16) XySystem - #1304 Daerung Post Tower 5 - GasanDong 60-3, GumChum-Gu - Seoul 153-801 - KOREA, REPUBLIC OF - - C0-2B-FC (hex) iNES. applied informatics GmbH - C02BFC (base 16) iNES. applied informatics GmbH - Ohmstrasse 9 - Ludwigsburg 71642 - GERMANY - - C0-2C-7A (hex) Shen Zhen Horn audio Co., Ltd. - C02C7A (base 16) Shen Zhen Horn audio Co., Ltd. - Block17,Tongfuyu lnd.Zone,Dalang,Baoan - Shenzhen Guang Dong 518109 - CHINA - - C0-33-5E (hex) Microsoft - C0335E (base 16) Microsoft - 1 Microsoft Way - Redmond Washingtonm 98023 - UNITED STATES - - C0-34-B4 (hex) Gigastone Corporation - C034B4 (base 16) Gigastone Corporation - 12F.NO 480. Rueiguang Rd. - Taipei 11492 - TAIWAN, PROVINCE OF CHINA - - C0-35-80 (hex) A&R TECH - C03580 (base 16) A&R TECH - Marksteinergasse 13 - Vienna 1210 - AUSTRIA - - C0-35-BD (hex) Velocytech Aps - C035BD (base 16) Velocytech Aps - Automatikvej 1, 3rd floor - SOEBORG 2860 - DENMARK - - C0-35-C5 (hex) Prosoft Systems LTD - C035C5 (base 16) Prosoft Systems LTD - Volgogradskaya 194-a - Ekaterinburg Sverdlovskay 620102 - RUSSIAN FEDERATION - - C0-38-96 (hex) Hon Hai Precision Ind. Co.,Ltd. - C03896 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road, - Xiyong Town,Shapingba District - Chongqing 401332 - CHINA - - C0-38-F9 (hex) Nokia Danmark A/S - C038F9 (base 16) Nokia Danmark A/S - Frederikskaj - Copenhagen V DK-1790 - DENMARK - - C0-3B-8F (hex) Minicom Digital Signage - C03B8F (base 16) Minicom Digital Signage - 24 Hebron Road - Jerusalem 93542 - ISRAEL - - C0-3D-46 (hex) Shanghai Mochui Network Technology Co., Ltd - C03D46 (base 16) Shanghai Mochui Network Technology Co., Ltd - No 666 Zhangheng Road - Zhangjiang High-tech Park - Pudong Shanghai 210203 - CHINA - - C0-3E-0F (hex) BSkyB Ltd - C03E0F (base 16) BSkyB Ltd - 130 Kings Road - Brentwood Essex CM14 4EF - UNITED KINGDOM - - C0-3F-0E (hex) NETGEAR - C03F0E (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - C0-3F-2A (hex) Biscotti, Inc. - C03F2A (base 16) Biscotti, Inc. - 5900 South Lake Forest Drive - Suite 290 - McKinney TX 75070 - UNITED STATES - - C0-3F-D5 (hex) Elitegroup Computer Systems Co., LTD - C03FD5 (base 16) Elitegroup Computer Systems Co., LTD - No. 239, Sec. 2, Ti-Ding Blvd - Neihu Dist. - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - C0-41-F6 (hex) LG Electronics Inc - C041F6 (base 16) LG Electronics Inc - 19-1,Cheongho-Ri,Jinwi-Myeon - Pyeongtaek Gyeonggi-Do 451-713 - KOREA, REPUBLIC OF - - C0-43-01 (hex) Epec Oy - C04301 (base 16) Epec Oy - Tiedekatu 6 - P.O. Box 194 - Seinäjoki 60101 - FINLAND - - C0-44-E3 (hex) Shenzhen Sinkna Electronics Co., LTD - C044E3 (base 16) Shenzhen Sinkna Electronics Co., LTD - 9 Building, XinXin Tian Industry Area, - XinSha Road, Shajing, Bao'an District, - Shenzhen Guangdong 5180000 - CHINA - - C0-49-3D (hex) MAITRISE TECHNOLOGIQUE - C0493D (base 16) MAITRISE TECHNOLOGIQUE - 224 RUE DE LA SAINTE BAUME - SAINT MAXIMIN LA SAINTE BAUME VAR 83470 - FRANCE - - C0-4A-00 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - C04A00 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd,Nanshan - shenzhen guangdong Province 518057 - CHINA - - C0-4D-F7 (hex) SERELEC - C04DF7 (base 16) SERELEC - 2, Chemin du Génie - BP85 - VENISSIEUX CEDEX 69633 - FRANCE - - C0-56-27 (hex) Belkin International, Inc. - C05627 (base 16) Belkin International, Inc. - 12045 E. Waterfront Drive - Playa Vista CA 90094 - UNITED STATES - - C0-56-E3 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. - C056E3 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. - No.469,Jianghui Road - Binjiang District - Hangzhou Zhejiang 310052 - CHINA - - C0-57-BC (hex) Avaya, Inc - C057BC (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge, NJ 07920-2311 - UNITED STATES - - C0-58-A7 (hex) Pico Systems Co., Ltd. - C058A7 (base 16) Pico Systems Co., Ltd. - 332-7 Kouya - Matsudo Chiba pref. 270-0017 - JAPAN - - C0-5E-6F (hex) V. Stonkaus firma "Kodinis Raktas" - C05E6F (base 16) V. Stonkaus firma "Kodinis Raktas" - Ateities 10 - Vilnius 08303 - LITHUANIA - - C0-5E-79 (hex) SHENZHEN HUAXUN ARK TECHNOLOGIES CO.,LTD - C05E79 (base 16) SHENZHEN HUAXUN ARK TECHNOLOGIES CO.,LTD - 3F,C4 Building,Yintian Industrial Zone,Xixiang,Baoan District - shenzhen guangdong 518102 - CHINA - - C0-61-18 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - C06118 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - C0-62-6B (hex) CISCO SYSTEMS, INC. - C0626B (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C0-63-94 (hex) Apple - C06394 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C0-64-C6 (hex) Nokia Corporation - C064C6 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - C0-65-99 (hex) Samsung Electronics Co.,Ltd - C06599 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C0-67-AF (hex) Cisco - C067AF (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - C0-6C-0F (hex) Dobbs Stanford - C06C0F (base 16) Dobbs Stanford - 2715 Electronic Lane - Dallas Texas 75220 - UNITED STATES - - C0-6C-6D (hex) MagneMotion, Inc. - C06C6D (base 16) MagneMotion, Inc. - 139 Barnum Road - Devens Massachusetts 01434 - UNITED STATES - - C0-70-09 (hex) Huawei Technologies Co., Ltd - C07009 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - C0-7B-BC (hex) Cisco - C07BBC (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - C0-7E-40 (hex) SHENZHEN XDK COMMUNICATION EQUIPMENT CO.,LTD - C07E40 (base 16) SHENZHEN XDK COMMUNICATION EQUIPMENT CO.,LTD - XDK BUILDING,NO.1 INDUSTRIAL AREA,BANTIAN,LONGGANG DISTRICT - SHENZHEN GUANGDONG 518129 - CHINA - - C0-81-70 (hex) Effigis GeoSolutions - C08170 (base 16) Effigis GeoSolutions - 4101, rue Molson - Suite 400 - Montreal Quebec H1Y3L1 - CANADA - - C0-83-0A (hex) 2Wire - C0830A (base 16) 2Wire - 1764 Automation Pkwy - San Jose CA 95131 - UNITED STATES - - C0-84-7A (hex) Apple - C0847A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C0-88-5B (hex) SnD Tech Co., Ltd. - C0885B (base 16) SnD Tech Co., Ltd. - 1140-4 Triple Tower C-406 - Wonmi-gu, Jung 1-Dong - Bucheon Si Gyeonggi-Do 420-852 - KOREA, REPUBLIC OF - - C0-8A-DE (hex) Ruckus Wireless - C08ADE (base 16) Ruckus Wireless - 880 West Maude Ave - Sunnyvale CA 94085 - UNITED STATES - - C0-8B-6F (hex) S I Sistemas Inteligentes Eletrônicos Ltda - C08B6F (base 16) S I Sistemas Inteligentes Eletrônicos Ltda - Rua Amadeu Piotto 161 - Curitiba Paraná 81280020 - BRAZIL - - C0-8C-60 (hex) Cisco - C08C60 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - C0-91-32 (hex) Patriot Memory - C09132 (base 16) Patriot Memory - 47027 Benicia - Fremont CA 94555 - UNITED STATES - - C0-91-34 (hex) ProCurve Networking by HP - C09134 (base 16) ProCurve Networking by HP - 8000 Foothills Blvd. - Roseville California 95747 - UNITED STATES - - C0-98-79 (hex) Acer Inc. - C09879 (base 16) Acer Inc. - 8F, 88, Sec.1, Xintai 5th Rd. - Xizhi - New Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - C0-98-E5 (hex) University of Michigan - C098E5 (base 16) University of Michigan - 4808 Beyster Bldg, - 2260 Hayward St. - Ann Arbor Michigan 48109 - UNITED STATES - - C0-9A-71 (hex) XIAMEN MEITU MOBILE TECHNOLOGY CO.LTD - C09A71 (base 16) XIAMEN MEITU MOBILE TECHNOLOGY CO.LTD - 1-3F, Block2, No.6 Wanghai Rd - Siming District, - Xiamen Fujian 361008 - CHINA - - C0-9C-92 (hex) COBY - C09C92 (base 16) COBY - COBY Electronics ShenZhen R&D Center - Block 3,TaoXia 2nd Industrial Zone,LongHua Town,BaoAn District, - SHENZHEN GUANGDONG 518109 - CHINA - - C0-9D-26 (hex) Topicon HK Lmd. - C09D26 (base 16) Topicon HK Lmd. - 302, 3F, Lee Loong Building - 4 Queen Victoria street - Central Hong Kong 0000 - HONG KONG - - C0-9F-42 (hex) Apple - C09F42 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C0-A0-BB (hex) D-Link International - C0A0BB (base 16) D-Link International - 1 Internal Business Park, #03-12,The Synergy - Singapore 609917 - SINGAPORE - - C0-A0-C7 (hex) FAIRFIELD INDUSTRIES - C0A0C7 (base 16) FAIRFIELD INDUSTRIES - 1111 GILLINGHAM LANE - SUGAR LAND TEXAS 77478 - UNITED STATES - - C0-A0-DE (hex) Multi Touch Oy - C0A0DE (base 16) Multi Touch Oy - Henry Fordin katu 6 - Helsinki 00150 - FINLAND - - C0-A0-E2 (hex) Eden Innovations - C0A0E2 (base 16) Eden Innovations - ZAC - 670 Route de berre - Eguilles PACA 13510 - FRANCE - - C0-A2-6D (hex) Abbott Point of Care - C0A26D (base 16) Abbott Point of Care - 400 College Road East - Princeton NJ 08540 - UNITED STATES - - C0-A3-64 (hex) 3D Systems Massachusetts - C0A364 (base 16) 3D Systems Massachusetts - 19 Connector Road - Andover MA 01810 - UNITED STATES - - C0-A3-9E (hex) EarthCam, Inc. - C0A39E (base 16) EarthCam, Inc. - 84 Kennedy Street - Hackensack New Jersey 07601 - UNITED STATES - - C0-AA-68 (hex) OSASI Technos Inc. - C0AA68 (base 16) OSASI Technos Inc. - 65-3, Hongu-cho, - Kochi-shi, Kochi-ken 780-0945 - JAPAN - - C0-AC-54 (hex) SAGEMCOM - C0AC54 (base 16) SAGEMCOM - 250 RTE DE L'EMPEREUR - RUEIL MALMAISON 92848 - FRANCE - - C0-B3-39 (hex) Comigo Ltd. - C0B339 (base 16) Comigo Ltd. - 15 HaPardes St. - Yarkona 45915 - ISRAEL - - C0-B3-57 (hex) Yoshiki Electronics Industry Ltd. - C0B357 (base 16) Yoshiki Electronics Industry Ltd. - Ooicyoyo Building 7f - 5-12-10 Higashiooi - Shinagawa-ku Tokyo 140-0011 - JAPAN - - C0-B8-B1 (hex) BitBox Ltd - C0B8B1 (base 16) BitBox Ltd - Whitney Road - Daneshill Industrial Estate - Basingstoke Hampshire RG24 8NS - UNITED KINGDOM - - C0-BA-E6 (hex) Application Solutions (Electronics and Vision) Ltd - C0BAE6 (base 16) Application Solutions (Electronics and Vision) Ltd - The Riverside Centre - Railway Lane - Lewes East Sussex BN7 2AQ - UNITED KINGDOM - - C0-BD-42 (hex) ZPA Smart Energy a.s. - C0BD42 (base 16) ZPA Smart Energy a.s. - Komenskeho 821 - Trutnov 54101 - CZECH REPUBLIC - - C0-BD-D1 (hex) Samsung Electro Mechanics co., LTD. - C0BDD1 (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - C0-C1-C0 (hex) Cisco-Linksys, LLC - C0C1C0 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - C0-C3-B6 (hex) Automatic Systems - C0C3B6 (base 16) Automatic Systems - avenue mercator,5 - Wavre Belgium 1300 - BELGIUM - - C0-C5-20 (hex) Ruckus Wireless - C0C520 (base 16) Ruckus Wireless - 880 West Maude Ave. - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - C0-C5-69 (hex) SHANGHAI LYNUC CNC TECHNOLOGY CO.,LTD - C0C569 (base 16) SHANGHAI LYNUC CNC TECHNOLOGY CO.,LTD - Building 3,No.25 Cangwu Rd - ,Xuhui District, - Shanghai 200233 - CHINA - - C0-C6-87 (hex) Cisco SPVTG - C0C687 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - C0-C9-46 (hex) MITSUYA LABORATORIES INC. - C0C946 (base 16) MITSUYA LABORATORIES INC. - 6-31-18,KAMIASAO - ASAO-KU - KAWASAKI-CITY KANAGAWA 215-0021 - JAPAN - - C0-CB-38 (hex) Hon Hai Precision Ind. Co.,Ltd. - C0CB38 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - C0-CE-CD (hex) Apple - C0CECD (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C0-CF-A3 (hex) Creative Electronics & Software, Inc. - C0CFA3 (base 16) Creative Electronics & Software, Inc. - 650 Sundown Road - South Elgin IL 60177 - UNITED STATES - - C0-D0-44 (hex) SAGEMCOM - C0D044 (base 16) SAGEMCOM - 250, Route de l'Empereur - RUEIL-MALMAISON 92500 - FRANCE - - C0-D9-62 (hex) Askey Computer Corp. - C0D962 (base 16) Askey Computer Corp. - 10F,NO.119,JIANKANG RD.,ZHONGHE DIST XINBEI CITY - TAIPEI 23585 - TAIWAN, PROVINCE OF CHINA - - C0-DA-74 (hex) Hangzhou Sunyard Technology Co., Ltd. - C0DA74 (base 16) Hangzhou Sunyard Technology Co., Ltd. - No.3888 Jiangnan Ave, Binjiang District, - Hangzhou Zhejiang 310053 - CHINA - - C0-DC-6A (hex) Qingdao Eastsoft Communication Technology Co.,LTD - C0DC6A (base 16) Qingdao Eastsoft Communication Technology Co.,LTD - Shandong QINGDAO, No. 16A, Shangqing Road, Shibei District - QINGDAO Shandong 266023 - CHINA - - C0-DF-77 (hex) Conrad Electronic SE - C0DF77 (base 16) Conrad Electronic SE - Klaus Conrad Str. 1 - Hirschau Bavaria 92240 - GERMANY - - C0-E4-22 (hex) Texas Instruments - C0E422 (base 16) Texas Instruments - 12500 TI Boulevard, MS8723 - Dallas TX 75243 - UNITED STATES - - C0-E5-4E (hex) DENX Computer Systems GmbH - C0E54E (base 16) DENX Computer Systems GmbH - Innsbrucker Str. 84 - Groebenzell 82194 - GERMANY - - C0-EA-E4 (hex) Sonicwall - C0EAE4 (base 16) Sonicwall - 2001 Logic Drive - San Jose CA 95124-3452 - UNITED STATES - - C0-EE-FB (hex) OnePlus Tech (Shenzhen) Ltd - C0EEFB (base 16) OnePlus Tech (Shenzhen) Ltd - 18F Tairan Building C, Tairan 8th Road Chegongmiao, Futian - Shenzhen Guangdong 518040 - CHINA - - C0-F1-C4 (hex) Pacidal Corporation Ltd. - C0F1C4 (base 16) Pacidal Corporation Ltd. - 3F., No. 11, Aly 3, Ln. 123, Sec. 3 Ren'ai Rd. - Da'an District - Taipei City 106 - TAIWAN, PROVINCE OF CHINA - - C0-F2-FB (hex) Apple - C0F2FB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C0-F7-9D (hex) Powercode - C0F79D (base 16) Powercode - 300 Industrial Dr - Random Lake Wisconsin 53075 - UNITED STATES - - C0-F8-DA (hex) Hon Hai Precision Ind. Co.,Ltd. - C0F8DA (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - C0-F9-91 (hex) GME Standard Communications P/L - C0F991 (base 16) GME Standard Communications P/L - 17 Gibbon Rd. - Winston Hills New South Wales 2153 - AUSTRALIA - - C0-FF-D4 (hex) Netgear Inc - C0FFD4 (base 16) Netgear Inc - 350 East Plumeria Drive - San Jose CA 95134 - UNITED STATES - - C4-00-06 (hex) Lipi Data Systems Ltd. - C40006 (base 16) Lipi Data Systems Ltd. - Mewar Industrial Area (M.I.A) - Madri - UDAIPUR RAJASTHAN 313003 - INDIA - - C4-01-42 (hex) MaxMedia Technology Limited - C40142 (base 16) MaxMedia Technology Limited - 5F, No. 113, Jian 2nd Rd. Jhonghe District. - New Taipei City 23585 - TAIWAN, PROVINCE OF CHINA - - C4-01-7C (hex) Ruckus Wireless - C4017C (base 16) Ruckus Wireless - 880 West Maude Ave - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - C4-01-B1 (hex) SeekTech INC - C401B1 (base 16) SeekTech INC - 3855 Ruffin Road - San Diego California 92123 - UNITED STATES - - C4-01-CE (hex) PRESITION (2000) CO., LTD. - C401CE (base 16) PRESITION (2000) CO., LTD. - 42/6 Moo6 - Bangnumjeud - Muang Samutsakorn 74000 - THAILAND - - C4-04-15 (hex) NETGEAR INC., - C40415 (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - C4-05-28 (hex) Huawei Technologies Co., Ltd - C40528 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - C4-07-2F (hex) Huawei Technologies Co., Ltd - C4072F (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - C4-08-4A (hex) Alcatel-Lucent - C4084A (base 16) Alcatel-Lucent - 600 MARCH RD - Ottawa ON K2K 2E6 - CANADA - - C4-08-80 (hex) Shenzhen UTEPO Tech Co., Ltd. - C40880 (base 16) Shenzhen UTEPO Tech Co., Ltd. - 5/F Western Block, M-8 Building, - Mid-section of Hi-tech industrial park, nanshan district - Shenzhen Guangdong 518057 - CHINA - - C4-09-38 (hex) Fujian Star-net Communication Co., Ltd - C40938 (base 16) Fujian Star-net Communication Co., Ltd - 19-22# Building,Star-net Science Plaza,Juyuanzhou, 618 Jinshan Road - Fuzhou Fujian 350002 - CHINA - - C4-0A-CB (hex) CISCO SYSTEMS, INC. - C40ACB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C4-0E-45 (hex) ACK Networks,Inc. - C40E45 (base 16) ACK Networks,Inc. - Floor3,Building B.,No.1 ShangDi XinXi Rd. - HaiDian District - Beijing 100085 - CHINA - - C4-0F-09 (hex) Hermes electronic GmbH - C40F09 (base 16) Hermes electronic GmbH - Am Handwerkerpark 1 - Essen NRW 45309 - GERMANY - - C4-10-8A (hex) Ruckus Wireless - C4108A (base 16) Ruckus Wireless - 880 West Maude Ave - Suite 101 - Sunnyvale CA 94085 - UNITED STATES - - C4-12-F5 (hex) D-Link International - C412F5 (base 16) D-Link International - 1 Internal Business Park, #03-12 - The Synergy - Singapore 609917 - SINGAPORE - - C4-13-E2 (hex) Aerohive Networks Inc. - C413E2 (base 16) Aerohive Networks Inc. - 330 Gibraltar Dr. - Sunnyvale CA 94089 - UNITED STATES - - C4-14-3C (hex) Cisco - C4143C (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - C4-16-FA (hex) Prysm Inc - C416FA (base 16) Prysm Inc - 180 Baytech Drive - Suite 200 - San Jose California 95134 - UNITED STATES - - C4-17-FE (hex) Hon Hai Precision Ind. Co.,Ltd. - C417FE (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - C4-19-8B (hex) Dominion Voting Systems Corporation - C4198B (base 16) Dominion Voting Systems Corporation - 215 Spadina Avenue - Suite 200 - Toronto Ontario M5T 2C7 - CANADA - - C4-19-EC (hex) Qualisys AB - C419EC (base 16) Qualisys AB - Packhusgatan 6 - Gothenburg 41113 - SWEDEN - - C4-1E-CE (hex) HMI Sources Ltd. - C41ECE (base 16) HMI Sources Ltd. - 5 Floor, Suite 2, 233 Hsin Yi Road, Section 4 - Taipei 10681 - TAIWAN, PROVINCE OF CHINA - - C4-21-C8 (hex) KYOCERA Corporation - C421C8 (base 16) KYOCERA Corporation - 2-1-1 Kagahara, - Tsuzuki-ku - Yokohama-shi Kanagawa 224-8502 - JAPAN - - C4-23-7A (hex) WhizNets Inc. - C4237A (base 16) WhizNets Inc. - 830 Stewart Drive - Sunnyvale California 94085 - UNITED STATES - - C4-24-2E (hex) Galvanic Applied Sciences Inc - C4242E (base 16) Galvanic Applied Sciences Inc - 7000 Fisher Road SE - Calgary Alberta T2H 0W3 - CANADA - - C4-26-28 (hex) Airo Wireless - C42628 (base 16) Airo Wireless - 12 Piedmont Center - Suite 205 - Atlanta GA 30305 - UNITED STATES - - C4-27-95 (hex) Technicolor USA Inc. - C42795 (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - C4-29-1D (hex) KLEMSAN ELEKTRIK ELEKTRONIK SAN.VE TIC.AS. - C4291D (base 16) KLEMSAN ELEKTRIK ELEKTRONIK SAN.VE TIC.AS. - kemalpasa yolu - 3.km KEMALPASA 35170 - izmir 35170 - TURKEY - - C4-2C-03 (hex) Apple - C42C03 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C4-2F-90 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. - C42F90 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. - No.469,Jianghui Road - Binjiang District - Hangzhou Zhejiang 310052 - CHINA - - C4-34-6B (hex) Hewlett Packard - C4346B (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - C4-36-6C (hex) LG Innotek - C4366C (base 16) LG Innotek - 978-1, Jangduk-dong - Gwangsan-gu Gwang-ju 506-731 - KOREA, REPUBLIC OF - - C4-36-DA (hex) Rusteletech Ltd. - C436DA (base 16) Rusteletech Ltd. - Ordzhonikidze Str. 11, Bldg. 40, Off. 15 - Moscow 115419 - RUSSIAN FEDERATION - - C4-38-D3 (hex) TAGATEC CO.,LTD - C438D3 (base 16) TAGATEC CO.,LTD - #604, Dongmoon Goodmorning Tower 2, - 1324, Baekseok-dong, Ilsandong-gu - Goyang-si Kyunggi-do 410-704 - KOREA, REPUBLIC OF - - C4-39-3A (hex) SMC Networks Inc - C4393A (base 16) SMC Networks Inc - 20 Mason - Irvine CA 92618 - UNITED STATES - - C4-3A-9F (hex) Siconix Inc. - C43A9F (base 16) Siconix Inc. - #28, 2333 18th Ave NE - Calgary Alberta T2E 8T6 - CANADA - - C4-3A-BE (hex) Sony Mobile Communications AB - C43ABE (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - C4-3C-3C (hex) CYBELEC SA - C43C3C (base 16) CYBELEC SA - Rue des Uttins 27 - Yverdon-les-Bains 1401 - SWITZERLAND - - C4-3D-C7 (hex) NETGEAR - C43DC7 (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - C4-42-02 (hex) Samsung Electronics Co.,Ltd - C44202 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C4-43-8F (hex) LG Electronics - C4438F (base 16) LG Electronics - 60-39, Kasan-dong, Gucheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - C4-45-67 (hex) SAMBON PRECISON and ELECTRONICS - C44567 (base 16) SAMBON PRECISON and ELECTRONICS - 204, Samjeong-dong, Ojeong-gu - Bucheon-city Kyeonggi-do 421-810 - KOREA, REPUBLIC OF - - C4-45-EC (hex) Shanghai Yali Electron Co.,LTD - C445EC (base 16) Shanghai Yali Electron Co.,LTD - Room 1-607 - Xinfu Road 388, Xinzhuang Town - Shanghai 201100 - CHINA - - C4-46-19 (hex) Hon Hai Precision Ind. Co.,Ltd. - C44619 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - C4-48-38 (hex) Satcom Direct, Inc. - C44838 (base 16) Satcom Direct, Inc. - 1901 Hwy A1A - Satellite Beach FL 32937 - UNITED STATES - - C4-4A-D0 (hex) FIREFLIES SYSTEMS - C44AD0 (base 16) FIREFLIES SYSTEMS - 3 CHEMIN DU PRE CARRE - MEYLAN 38240 - FRANCE - - C4-4B-44 (hex) Omniprint Inc. - C44B44 (base 16) Omniprint Inc. - 1923 East Deere Ave. - Santa Ana CA 92705 - UNITED STATES - - C4-4B-D1 (hex) Wallys Communications Teachnologies Co.,Ltd. - C44BD1 (base 16) Wallys Communications Teachnologies Co.,Ltd. - 5-207, DongHong Pioneer Park, #99 YangYu Lane, - GuSu District - SuZhou JiangSu 215000 - CHINA - - C4-4E-1F (hex) BlueN - C44E1F (base 16) BlueN - 121-122 3F - Daebong dong, Jung-gu - Daegu Korea 700-809 - KOREA, REPUBLIC OF - - C4-4E-AC (hex) Shenzhen Shiningworth Technology Co., Ltd. - C44EAC (base 16) Shenzhen Shiningworth Technology Co., Ltd. - Room 610, Block B, Huameiju Business Center, - Xinhu Road, Bao'an Area - Shenzhen Guangdong 518000 - CHINA - - C4-50-06 (hex) Samsung Electronics Co.,Ltd - C45006 (base 16) Samsung Electronics Co.,Ltd - Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C4-54-44 (hex) QUANTA COMPUTER INC. - C45444 (base 16) QUANTA COMPUTER INC. - No.211, Wen Hwa 2nd Rd - Kuei Shan Hsiang - Tao Yuan Shien Taoyuan 33377 - TAIWAN, PROVINCE OF CHINA - - C4-55-A6 (hex) Cadac Holdings Ltd - C455A6 (base 16) Cadac Holdings Ltd - 1 New Street - Luton Bedfordshire LU1 5DX - UNITED KINGDOM - - C4-55-C2 (hex) Bach-Simpson - C455C2 (base 16) Bach-Simpson - 109 Meg Drive - London Ontario N6E3Z7 - CANADA - - C4-56-00 (hex) Galleon Embedded Computing - C45600 (base 16) Galleon Embedded Computing - Grenseveien 97c - Pb. 6200 Etterstad - Oslo Oslo N-0602 - NORWAY - - C4-56-FE (hex) Lava International Ltd. - C456FE (base 16) Lava International Ltd. - Room 705, Block A, HengYue Building - , No.19 Deng,Liang Road, NanShan District, ShenZhen City, - Shanghai 518054 - CHINA - - C4-57-6E (hex) Samsung Electronics Co.,LTD - C4576E (base 16) Samsung Electronics Co.,LTD - 129,SamsungRo,Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - C4-58-C2 (hex) Shenzhen TATFOOK Technology Co., Ltd. - C458C2 (base 16) Shenzhen TATFOOK Technology Co., Ltd. - 3rd Industrial Area of Shajing Industrial Company, Haoxiang Road - Shajing District, Bao'an Town - Shenzhen Guangdong 518104 - CHINA - - C4-59-76 (hex) Fugoo Coorporation - C45976 (base 16) Fugoo Coorporation - 8001 Irvine Center Drive - Suite 250 - Irvine CA 62618 - UNITED STATES - - C4-5D-D8 (hex) HDMI Forum - C45DD8 (base 16) HDMI Forum - 1140 East Arques Avenue, Suite 900 - Sunnyvale CA 94085 - UNITED STATES - - C4-60-44 (hex) Everex Electronics Limited - C46044 (base 16) Everex Electronics Limited - Unit 3, Block A, 16/F - Kailey Industrial Center - HONG KONG - - C4-62-6B (hex) ZPT Vigantice - C4626B (base 16) ZPT Vigantice - Vigantice 266 - Roznov pod Radhostem 75661 - CZECH REPUBLIC - - C4-62-EA (hex) Samsung Electronics Co.,Ltd - C462EA (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C4-63-54 (hex) U-Raku, Inc. - C46354 (base 16) U-Raku, Inc. - 401-1 Deba - Ritto-shi Shiga 520-3041 - JAPAN - - C4-64-13 (hex) CISCO SYSTEMS, INC. - C46413 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C4-67-B5 (hex) Libratone A/S - C467B5 (base 16) Libratone A/S - Marielundvej 43 A - 2730 HERLEV - DENMARK - - C4-69-3E (hex) Turbulence Design Inc. - C4693E (base 16) Turbulence Design Inc. - 1-3-14 - Koshigaya - Koshigaya-City Saitama 343-0813 - JAPAN - - C4-6A-B7 (hex) Xiaomi Technology,Inc. - C46AB7 (base 16) Xiaomi Technology,Inc. - Quanshitiandi Tower A,8th Floor,jia50-1 Wangjing Xilu,Chaoyang District, Beijing, China 100102 - Beijing Beijing 100102 - CHINA - - C4-6B-B4 (hex) myIDkey - C46BB4 (base 16) myIDkey - 65 Enterprise - 370 - Aliso Viejo CA 92656 - UNITED STATES - - C4-6D-F1 (hex) DataGravity - C46DF1 (base 16) DataGravity - 10 Tara Blvd - Nashua NH 03062 - UNITED STATES - - C4-6E-1F (hex) TP-LINK TECHNOLOGIES CO.,LTD - C46E1F (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24(floors1,3,4,5)and 28(floors 1-4)Central Science and Technology Park, - Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - C4-71-30 (hex) Fon Technology S.L. - C47130 (base 16) Fon Technology S.L. - Quintanavides 13 - Edificio 2, planta 1 - Madrid 28050 - SPAIN - - C4-71-FE (hex) CISCO SYSTEMS, INC. - C471FE (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C4-72-95 (hex) Cisco - C47295 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - C4-73-1E (hex) Samsung Eletronics Co., Ltd - C4731E (base 16) Samsung Eletronics Co., Ltd - 416, Maetan 3dong, Yeongtong-Gu - Suwon 443742 - KOREA, REPUBLIC OF - - C4-7B-2F (hex) Beijing JoinHope Image Technology Ltd. - C47B2F (base 16) Beijing JoinHope Image Technology Ltd. - 624 Room .Automation Building.95# Zhong Guancun East Road.Haidian District - Beijing 100190 - CHINA - - C4-7B-A3 (hex) NAVIS Inc. - C47BA3 (base 16) NAVIS Inc. - Dmitrovskoe shosse 157 - Moscow 127411 - RUSSIAN FEDERATION - - C4-7D-46 (hex) Fujitsu Limited - C47D46 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - C4-7D-4F (hex) CISCO SYSTEMS, INC. - C47D4F (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C4-7D-CC (hex) Zebra Technologies Inc - C47DCC (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - C4-7D-FE (hex) A.N. Solutions GmbH - C47DFE (base 16) A.N. Solutions GmbH - Am Brauhaus 12 - Dresden Saxony 01099 - GERMANY - - C4-7F-51 (hex) Inventek Systems - C47F51 (base 16) Inventek Systems - 2 Republic Road - Billerica Ma 01862 - UNITED STATES - - C4-82-3F (hex) Fujian Newland Auto-ID Tech. Co,.Ltd. - C4823F (base 16) Fujian Newland Auto-ID Tech. Co,.Ltd. - Newland Science & Technology Park, No.1 Rujiang West Rd., Mawei - Fuzhou Fujian 350015 - CHINA - - C4-82-4E (hex) Changzhou Uchip Electronics Co., LTD. - C4824E (base 16) Changzhou Uchip Electronics Co., LTD. - Room1801~1802, - No.345 Jinxiang Rd.,Pudong - Shanghai 201206 - CHINA - - C4-85-08 (hex) Intel Corporate - C48508 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - C4-88-E5 (hex) Samsung Electronics Co.,Ltd - C488E5 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C4-8E-8F (hex) Hon Hai Precision Ind. Co.,Ltd. - C48E8F (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - Xiyong Town,Shapingba District - Chongqing 401332 - CHINA - - C4-91-3A (hex) Shenzhen Sanland Electronic Co., ltd. - C4913A (base 16) Shenzhen Sanland Electronic Co., ltd. - 3 floor,Block D, Glory Technology Industrial Park, - Baolong 5th road, Longgang District - ShenZhen Guangdong 518116 - CHINA - - C4-92-4C (hex) KEISOKUKI CENTER CO.,LTD. - C4924C (base 16) KEISOKUKI CENTER CO.,LTD. - 2-6-7 SAKANE - KAWANISHI-CITY HYOGO 666-0021 - JAPAN - - C4-93-00 (hex) 8Devices - C49300 (base 16) 8Devices - Gedimino st. 47 - Kaunas LT 44242 - LITHUANIA - - C4-93-13 (hex) 100fio networks technology llc - C49313 (base 16) 100fio networks technology llc - 2534 crescent st. apt 3F - Astoria New york 11102 - UNITED STATES - - C4-93-80 (hex) Speedytel technology - C49380 (base 16) Speedytel technology - ROOM 1103,HANG SENG MONGKOK BUILDING,677 NATHAN ROAD,MONGKOK,KOWLOON - HONG KONG HONG KONG 999077 - HONG KONG - - C4-95-A2 (hex) SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD - C495A2 (base 16) SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD - ROOM 1713,BAOHUA BUILDING, HUAQIANG NORTH ROAD, FUTIAN DISTRICT, - SHENZHEN GUANGDONG 518031 - CHINA - - C4-98-05 (hex) Minieum Networks, Inc - C49805 (base 16) Minieum Networks, Inc - 6404 International Parkway - ste 2020 - Plano Texas 75093 - UNITED STATES - - C4-9A-02 (hex) LG Electronics (Mobile Communicaitons) - C49A02 (base 16) LG Electronics (Mobile Communicaitons) - 60-39, Kasan-dong, Kumchon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - C4-A8-1D (hex) D-Link International - C4A81D (base 16) D-Link International - 1 Internal Business Park, #03-12 - The Synergy - Singapore 609917 - SINGAPORE - - C4-AA-A1 (hex) SUMMIT DEVELOPMENT, spol.s r.o. - C4AAA1 (base 16) SUMMIT DEVELOPMENT, spol.s r.o. - K Vodoteci 197 - Orech Praha-zapad 252 25 - CZECH REPUBLIC - - C4-AD-21 (hex) MEDIAEDGE Corporation - C4AD21 (base 16) MEDIAEDGE Corporation - 23F Kobe Commerce, Industry and Trade Center Bldg. - 5-1-14, Hamabe-dori, Chuo-ku - Kobe Hyogo 651-0083 - JAPAN - - C4-B5-12 (hex) General Electric Digital Energy - C4B512 (base 16) General Electric Digital Energy - 4200 Wildwood Pkwy - Atlanta GA 30339 - UNITED STATES - - C4-BA-99 (hex) I+ME Actia Informatik und Mikro-Elektronik GmbH - C4BA99 (base 16) I+ME Actia Informatik und Mikro-Elektronik GmbH - Dresdenstrasse 17/18 - Braunschweig Niedersachsen 38690 - GERMANY - - C4-BA-A3 (hex) Beijing Winicssec Technologies Co., Ltd. - C4BAA3 (base 16) Beijing Winicssec Technologies Co., Ltd. - F block 9th floor 907 of Jiahua Building, No.9 Shangdi 3rd Street - Haidian District Beijing 100085 - CHINA - - C4-BD-6A (hex) SKF GmbH - C4BD6A (base 16) SKF GmbH - Gunnar-Wester-Strasse 12 - Schweinfurt DE DE-97421 - GERMANY - - C4-BE-84 (hex) Texas Instruments. - C4BE84 (base 16) Texas Instruments. - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - C4-C0-AE (hex) MIDORI ELECTRONIC CO., LTD. - C4C0AE (base 16) MIDORI ELECTRONIC CO., LTD. - 397 - Togura - Chikuma Nagano 389-0804 - JAPAN - - C4-C1-9F (hex) National Oilwell Varco Instrumentation, Monitoring, and Optimization (NOV IMO) - C4C19F (base 16) National Oilwell Varco Instrumentation, Monitoring, and Optimization (NOV IMO) - 1200 Cypress Creek Rd. - Cedar Park TX 78613 - UNITED STATES - - C4-C7-55 (hex) Beijing HuaqinWorld Technology Co.,Ltd - C4C755 (base 16) Beijing HuaqinWorld Technology Co.,Ltd - 30F,Beijing Silver Tower,No.2 North Road, - Dong San Huan.Chao Yang Dist - Beijing 100027 - CHINA - - C4-C9-19 (hex) Energy Imports Ltd - C4C919 (base 16) Energy Imports Ltd - 306a Broadway Ave - Palmerston North Manawatu 4414 - NEW ZEALAND - - C4-C9-EC (hex) Gugaoo HK Limited - C4C9EC (base 16) Gugaoo HK Limited - Unit 04, 7/F BRIGHT WAY TOWER - no. 33 MONG KOK road - Kowloon, Hongkong - HONG KONG - - C4-CA-D9 (hex) Hangzhou H3C Technologies Co., Limited - C4CAD9 (base 16) Hangzhou H3C Technologies Co., Limited - 310 Liuhe Road, Zhijiang Science Park - Hangzhou Zhejiang, 310053 - CHINA - - C4-CD-45 (hex) Beijing Boomsense Technology CO.,LTD. - C4CD45 (base 16) Beijing Boomsense Technology CO.,LTD. - 803 Building 4 INTERWEST Business Center,No.9 South Shouti Road ,HaidianDistrict, - Beijing 100048 - CHINA - - C4-D4-89 (hex) JiangSu Joyque Information Industry Co.,Ltd - C4D489 (base 16) JiangSu Joyque Information Industry Co.,Ltd - 10 Floor YaHua Building, Xi'anBei Road, - Xuzhou JiangSu 221006 - CHINA - - C4-D6-55 (hex) Tercel technology co.,ltd - C4D655 (base 16) Tercel technology co.,ltd - Huafa South Road, Futian District, - Building B-807 FlyingTimes - SHENZHEN GUANGDONG 518000 - CHINA - - C4-D9-87 (hex) Intel Corporate - C4D987 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - C4-DA-26 (hex) NOBLEX SA - C4DA26 (base 16) NOBLEX SA - Vicente Padín Moreira 97 - Ushuaia Tierra del fuego 9410 - ARGENTINA - - C4-E0-32 (hex) IEEE 1904.1 Working Group - C4E032 (base 16) IEEE 1904.1 Working Group - 1351 Redwood Way - Petaluma CA 94954 - UNITED STATES - - C4-E1-7C (hex) U2S co. - C4E17C (base 16) U2S co. - 104-706, SK Ventium Building, 522, Dangjeong-Dong - Gunpo-si Geonggi-do 435-776 - KOREA, REPUBLIC OF - - C4-E7-BE (hex) SCSpro Co.,Ltd - C4E7BE (base 16) SCSpro Co.,Ltd - #1203, KCC welltz valley 470-8 - Gasan-dong Keumcheon-gu - Seoul Korea 153-710 - KOREA, REPUBLIC OF - - C4-E9-2F (hex) AB Sciex - C4E92F (base 16) AB Sciex - 71 Four Valley Drive - Concord Ontario L4K 4V8 - CANADA - - C4-E9-84 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - C4E984 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4) - Central Science and Technology Park, - Shennan Road,Nanshan, Shenzhen Guangdong 518057 - CHINA - - C4-EA-1D (hex) Technicolor - C4EA1D (base 16) Technicolor - Prins Boudewijnlaan 47 - Edegem - Belgium Antwerp B-2650 - BELGIUM - - C4-EB-E3 (hex) RRCN SAS - C4EBE3 (base 16) RRCN SAS - 23 chemin du vieux chene - Meylan Isere 38246 - FRANCE - - C4-ED-BA (hex) Texas Instruments - C4EDBA (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - C4-EE-AE (hex) VSS Monitoring - C4EEAE (base 16) VSS Monitoring - 1850 Gateway Dr, Suite 500 - San Mateo CA 94404 - UNITED STATES - - C4-EE-F5 (hex) Oclaro, Inc. - C4EEF5 (base 16) Oclaro, Inc. - 343 Daniel Zenker Dr., Suite 102 - Horseheads NY 14845 - UNITED STATES - - C4-F4-64 (hex) Spica international - C4F464 (base 16) Spica international - Pot k sejmiscu 33 - Ljubljana 1000 - SLOVENIA - - C4-F5-7C (hex) Brocade Communications Systems, Inc. - C4F57C (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - C4-FC-E4 (hex) DishTV NZ Ltd - C4FCE4 (base 16) DishTV NZ Ltd - 10 Penney Ave - Mt Roskill - Auckland 1041 - NEW ZEALAND - - C8-00-84 (hex) Cisco - C80084 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - C8-02-10 (hex) LG Innotek - C80210 (base 16) LG Innotek - Jangduk-dong 978-1 - Gwang-ju Gwangsan-gu 506-731 - KOREA, REPUBLIC OF - - C8-02-58 (hex) ITW GSE ApS - C80258 (base 16) ITW GSE ApS - Smedebakken 31-33 - Odense N 5270 - DENMARK - - C8-02-A6 (hex) Beijing Newmine Technology - C802A6 (base 16) Beijing Newmine Technology - 10 floor,Keshi Plaza - HaiDian District - Beijing 100085 - CHINA - - C8-07-18 (hex) TDSi - C80718 (base 16) TDSi - Unit 10 Concept Park - Innovation Close - Poole Dorset BH12 4QT - UNITED KINGDOM - - C8-08-E9 (hex) LG Electronics - C808E9 (base 16) LG Electronics - 222 LG-ro, JINWI-MYEON - Pyeongtaek-si Gyeonggi-do 451-713 - KOREA, REPUBLIC OF - - C8-0A-A9 (hex) Quanta Computer Inc. - C80AA9 (base 16) Quanta Computer Inc. - 211, Wen Hwa 2nd Rd., - Tao Yuan Kuei Shan 33377 - TAIWAN, PROVINCE OF CHINA - - C8-0E-14 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH - C80E14 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH - Alt-Moabit 95 - Berlin Berlin 10559 - GERMANY - - C8-0E-77 (hex) Le Shi Zhi Xin Electronic Technology (Tianjin) Co.,Ltd - C80E77 (base 16) Le Shi Zhi Xin Electronic Technology (Tianjin) Co.,Ltd - No.201-427,2F,Tthe Animation Building B1 District£¬No. 126£¬Tianjin eco-city animation Road - Tianjin 300467 - CHINA - - C8-0E-95 (hex) OmniLync Inc. - C80E95 (base 16) OmniLync Inc. - 51a Bennington St. - Newton MA 02458 - UNITED STATES - - C8-14-79 (hex) Samsung Electronics Co.,Ltd - C81479 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C8-16-BD (hex) HISENSE ELECTRIC CO.,LTD. - C816BD (base 16) HISENSE ELECTRIC CO.,LTD. - Qingdao Hisense Electric Co.,Ltd. - 11,Jiangxi Road - Qingdao Shandong 266071 - CHINA - - C8-19-F7 (hex) Samsung Electronics Co.,Ltd - C819F7 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C8-1A-FE (hex) DLOGIC GmbH - C81AFE (base 16) DLOGIC GmbH - Rathausstrasse 14 - Postfach 321 - Baar ZG 6341 - SWITZERLAND - - C8-1B-6B (hex) Innova Security - C81B6B (base 16) Innova Security - Av. General Ataliba Leonel, 1205 - Sao Paulo Sao Paulo 02033000 - BRAZIL - - C8-1E-8E (hex) ADV Security (S) Pte Ltd - C81E8E (base 16) ADV Security (S) Pte Ltd - 56 Dunlop Street - 209386 - SINGAPORE - - C8-1E-E7 (hex) Apple Inc - C81EE7 (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-1F-66 (hex) Dell Inc - C81F66 (base 16) Dell Inc - one dell way - Round rock Texas 78682 - UNITED STATES - - C8-20-8E (hex) Storagedata - C8208E (base 16) Storagedata - Randstad 22117 - Almere Flevoland 1316BW - NETHERLANDS - - C8-29-2A (hex) Barun Electronics - C8292A (base 16) Barun Electronics - 869, Jangji-ri, Dongtan-myeon - Hwaseong-si Gyeonggi-do 445812 - KOREA, REPUBLIC OF - - C8-2A-14 (hex) Apple - C82A14 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-2E-94 (hex) Halfa Enterprise Co., Ltd. - C82E94 (base 16) Halfa Enterprise Co., Ltd. - 5F, No.102, Ming Chuan Road - Hsin Tien Taipei County 23141 - TAIWAN, PROVINCE OF CHINA - - C8-31-68 (hex) eZEX corporation - C83168 (base 16) eZEX corporation - Rm 508, Ssangyong IT Twin-Tower II, 442-5 - Sangdaewon-dong, Jungwon-gu - Seongnam-si Gyeonggi-do 462-120 - KOREA, REPUBLIC OF - - C8-32-32 (hex) Hunting Innova - C83232 (base 16) Hunting Innova - 8383 N Sam Houston Pkwy West - Houston Texas 77064 - UNITED STATES - - C8-33-4B (hex) Apple - C8334B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-34-8E (hex) Intel Corporate - C8348E (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - C8-35-B8 (hex) Ericsson, EAB/RWI/K - C835B8 (base 16) Ericsson, EAB/RWI/K - SkolgÃ¥ngen 17 - Gävle - SE-800 06 - SWEDEN - - C8-3A-35 (hex) Tenda Technology Co., Ltd. - C83A35 (base 16) Tenda Technology Co., Ltd. - Room 601-602,R/D Building Complex,Tsinghua High-Tech Park,nanshan district - Shenzhen Guandong 518057 - CHINA - - C8-3B-45 (hex) JRI-Maxant - C83B45 (base 16) JRI-Maxant - 116 Quai de bezons - Argenteuil 95100 - FRANCE - - C8-3D-97 (hex) Nokia Corporation - C83D97 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90450 - FINLAND - - C8-3E-99 (hex) Texas Instruments - C83E99 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - C8-3E-A7 (hex) KUNBUS GmbH - C83EA7 (base 16) KUNBUS GmbH - Heerweg 15C - Denkendorf BW D-73770 - GERMANY - - C8-3F-B4 (hex) ARRIS Group, Inc. - C83FB4 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - C8-45-29 (hex) IMK Networks Co.,Ltd - C84529 (base 16) IMK Networks Co.,Ltd - 201-Ho jungribjunja, 16-3bunji, - Guui-dong, Gwangjin-gu - Seoul 143-816 - KOREA, REPUBLIC OF - - C8-45-44 (hex) Shanghai Enlogic Electric Technology Co., Ltd. - C84544 (base 16) Shanghai Enlogic Electric Technology Co., Ltd. - Room 1104-1106, Building A, No. 391 Guiping Road - Xuhui Distric Shanghai 200233 - CHINA - - C8-45-8F (hex) Wyler AG - C8458F (base 16) Wyler AG - Im Hoelderli 13 - Winterthur ZH 8405 - SWITZERLAND - - C8-48-F5 (hex) MEDISON Xray Co., Ltd - C848F5 (base 16) MEDISON Xray Co., Ltd - 3F Burim B/D 999 Daechi-dong - Gangnam-gu - Seoul 135-280 - KOREA, REPUBLIC OF - - C8-4C-75 (hex) CISCO SYSTEMS, INC. - C84C75 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C8-56-45 (hex) Intermas France - C85645 (base 16) Intermas France - Rue de l'industrie - Beauvais Oise 60000 - FRANCE - - C8-56-63 (hex) Sunflex Europe GmbH - C85663 (base 16) Sunflex Europe GmbH - Konrad-Zuse-Str. 13 - Schwerte NRW 58239 - GERMANY - - C8-60-00 (hex) ASUSTek COMPUTER INC. - C86000 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - C8-64-C7 (hex) zte corporation - C864C7 (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road, - shenzhen guangdong 518057 - CHINA - - C8-6C-1E (hex) Display Systems Ltd - C86C1E (base 16) Display Systems Ltd - 16-Parkovaja Street 26 - Moscow 105484 - RUSSIAN FEDERATION - - C8-6C-87 (hex) Zyxel Communications Corp - C86C87 (base 16) Zyxel Communications Corp - No.6 Innovation Road II - Science Park - Hsin-Chu 300 - TAIWAN, PROVINCE OF CHINA - - C8-6C-B6 (hex) Optcom Co., Ltd. - C86CB6 (base 16) Optcom Co., Ltd. - 792-3 Tomigaoka - Iwata Shizuoka 438-0803 - JAPAN - - C8-6F-1D (hex) Apple - C86F1D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-72-48 (hex) Aplicom Oy - C87248 (base 16) Aplicom Oy - Rautatienkatu 56 - Äänekoski Länsi-Suomi 44101 - FINLAND - - C8-7B-5B (hex) zte corporation - C87B5B (base 16) zte corporation - 12/F.,zte R&D Building,Kejinan Road, - Shenzhen, Guangdong 518057 - CHINA - - C8-7C-BC (hex) Valink Co., Ltd. - C87CBC (base 16) Valink Co., Ltd. - 1F Dongwon Bldg. 90, Dangsan-Dong 3-Ga Youngdungpo-Gu - Seoul 150-803 - KOREA, REPUBLIC OF - - C8-7D-77 (hex) Shenzhen Kingtech Communication Equipment Co.,Ltd - C87D77 (base 16) Shenzhen Kingtech Communication Equipment Co.,Ltd - Floor3.Building A,NO.3,Road 1 of shangxue Dengxinkeng Industry Park,Bantian Street, - Longgang District, - Shenzhen City Guangdong 518112 - CHINA - - C8-7E-75 (hex) Samsung Electronics Co.,Ltd - C87E75 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C8-84-39 (hex) Sunrise Technologies - C88439 (base 16) Sunrise Technologies - 54 Commercial Street - Raynham MA 02767 - UNITED STATES - - C8-84-47 (hex) Beautiful Enterprise Co., Ltd - C88447 (base 16) Beautiful Enterprise Co., Ltd - 26th Floor, Beautiful Group Tower - 77 Connaught Road Central - HONG KONG - - C8-85-50 (hex) Apple - C88550 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-87-3B (hex) Net Optics - C8873B (base 16) Net Optics - 5303 Betsy Ross Drive - Santa Clara CA 95054 - UNITED STATES - - C8-8A-83 (hex) Dongguan HuaHong Electronics Co.,Ltd - C88A83 (base 16) Dongguan HuaHong Electronics Co.,Ltd - NO.25,Xing Er Road,Chen Wu Industrial Zone,Wusha Village,Chang£§an Town - Dongguan City China/Guangdong 523858 - CHINA - - C8-8B-47 (hex) Nolangroup S.P.A con Socio Unico - C88B47 (base 16) Nolangroup S.P.A con Socio Unico - via Terzi di S.Agata 2 - Brembate di Sopra Bergamo 24030 - ITALY - - C8-90-3E (hex) Pakton Technologies - C8903E (base 16) Pakton Technologies - 1 Helium St - Narangba QLD 4504 - AUSTRALIA - - C8-91-F9 (hex) SAGEMCOM - C891F9 (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON CEDEX HAUTS DE SEINE 92848 - FRANCE - - C8-93-46 (hex) MXCHIP Company Limited - C89346 (base 16) MXCHIP Company Limited - Room 811,Tongpu Building, - No.1220 Tongpu Road - Shanghai Shanghai 200333 - CHINA - - C8-93-83 (hex) Embedded Automation, Inc. - C89383 (base 16) Embedded Automation, Inc. - 17345 Abbey Drive - Surrey BC V4N 4M3 - CANADA - - C8-94-D2 (hex) Jiangsu Datang Electronic Products Co., Ltd - C894D2 (base 16) Jiangsu Datang Electronic Products Co., Ltd - NO.20 - Puzhu South Road - Nanjing Jiangsu 211800 - CHINA - - C8-97-9F (hex) Nokia Corporation - C8979F (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90570 - FINLAND - - C8-9C-1D (hex) CISCO SYSTEMS, INC. - C89C1D (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C8-9C-DC (hex) ELITEGROUP COMPUTER SYSTEM CO., LTD. - C89CDC (base 16) ELITEGROUP COMPUTER SYSTEM CO., LTD. - NO. 239, Sec. 2, Ti Ding Blvd. - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - C8-9F-1D (hex) SHENZHEN COMMUNICATION TECHNOLOGIES CO.,LTD - C89F1D (base 16) SHENZHEN COMMUNICATION TECHNOLOGIES CO.,LTD - NO.6 QINGNING ROAD,CAIHUANG INDUSTRY PARK, - QINGHU,LONGHUA,NEW DISTRICT,SHENZHEN,P.R.CHINA - SHENZHEN GUANGDONG 518109 - CHINA - - C8-9F-42 (hex) VDII Innovation AB - C89F42 (base 16) VDII Innovation AB - Nedre Holländaregatan 5 - Helsingborg 25225 - SWEDEN - - C8-A0-30 (hex) Texas Instruments - C8A030 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - C8-A1-B6 (hex) Shenzhen Longway Technologies Co., Ltd - C8A1B6 (base 16) Shenzhen Longway Technologies Co., Ltd - Suite 707,Incubation Building, China Academy of Science&Tech Development, South area - Hi-Tech Industrial Park - Shenzhen Guangdong 518057 - CHINA - - C8-A1-BA (hex) Neul Ltd - C8A1BA (base 16) Neul Ltd - Suite 42 Innovation Centre - Unit 23 Science Park - Cambridge Cambs CB4 0EY - UNITED KINGDOM - - C8-A6-20 (hex) Nebula, Inc - C8A620 (base 16) Nebula, Inc - 548 Market Street #85510 - San Francisco CA 98158 - UNITED STATES - - C8-A7-0A (hex) Verizon Business - C8A70A (base 16) Verizon Business - One Digex Plaza - Beltsville MD 20705 - UNITED STATES - - C8-A7-29 (hex) SYStronics Co., Ltd. - C8A729 (base 16) SYStronics Co., Ltd. - #301-1404, Buchun Techno-Park II - 365, Samjeong-dong, Ojeong-gu - Buchun City Kyung gi-do 421-741 - KOREA, REPUBLIC OF - - C8-A8-23 (hex) Samsung Electronics Co.,Ltd - C8A823 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - C8-AA-21 (hex) ARRIS Group, Inc. - C8AA21 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - C8-AA-CC (hex) PRIVATE - C8AACC (base 16) - - C8-AE-9C (hex) Shanghai TYD Elecronic Technology Co. Ltd - C8AE9C (base 16) Shanghai TYD Elecronic Technology Co. Ltd - 21F, BLKB, NO.391 GuiPing Rd, - Shanghai 200233 - CHINA - - C8-AF-40 (hex) marco Systemanalyse und Entwicklung GmbH - C8AF40 (base 16) marco Systemanalyse und Entwicklung GmbH - Hans-Böckler-Straße 2 - Dachau Bavaria 85221 - GERMANY - - C8-B3-73 (hex) Cisco-Linksys, LLC - C8B373 (base 16) Cisco-Linksys, LLC - 121 Theory Drive - Irvine California 92612 - UNITED STATES - - C8-B5-B7 (hex) Apple - C8B5B7 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-BA-94 (hex) Samsung Electro Mechanics co., LTD. - C8BA94 (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - C8-BB-D3 (hex) Embrane - C8BBD3 (base 16) Embrane - 2350 Mission College Blvd., Ste 703 - Santa Clara CA 95054 - UNITED STATES - - C8-BC-C8 (hex) Apple - C8BCC8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-BE-19 (hex) D-Link International - C8BE19 (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy Singapore 609917 - Singapore Singapore 609917 - TAIWAN, PROVINCE OF CHINA - - C8-C1-26 (hex) ZPM Industria e Comercio Ltda - C8C126 (base 16) ZPM Industria e Comercio Ltda - Rua Araguaia, 175 - Canoas RS 92410-000 - BRAZIL - - C8-C1-3C (hex) RuggedTek Hangzhou Co., Ltd - C8C13C (base 16) RuggedTek Hangzhou Co., Ltd - Zhejiang University National Science Park - 525 Xixi Roard, Building C Room 401 - Hangzhou Zhejiang 310013 - CHINA - - C8-C5-0E (hex) Shenzhen Primestone Network Technologies.Co., Ltd. - C8C50E (base 16) Shenzhen Primestone Network Technologies.Co., Ltd. - Room 705,Complex Building, Tsinghua Hi-Tech Park - Keyuan Road, Nanshan Dist. - Shenzhen Guangdong 518057 - CHINA - - C8-C7-91 (hex) Zero1.tv GmbH - C8C791 (base 16) Zero1.tv GmbH - Heinrich-Roller-Str. 16 B - Berlin 10405 - GERMANY - - C8-CB-B8 (hex) Hewlett Packard - C8CBB8 (base 16) Hewlett Packard - 11445 Compaq Center Drive W - Houston Texas 77070 - UNITED STATES - - C8-CD-72 (hex) SAGEMCOM - C8CD72 (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON 92848 - FRANCE - - C8-D0-19 (hex) Shanghai Tigercel Communication Technology Co.,Ltd - C8D019 (base 16) Shanghai Tigercel Communication Technology Co.,Ltd - Room 805, building 1 - No. 100 Qinzhou Road - Shanghai 200235 - CHINA - - C8-D1-0B (hex) Nokia Corporation - C8D10B (base 16) Nokia Corporation - Joensuunkatu 7 - P.O. Box 86 - Salo 24101 - FINLAND - - C8-D1-5E (hex) Huawei Technologies Co., Ltd - C8D15E (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - C8-D1-D1 (hex) AGAiT Technology Corporation - C8D1D1 (base 16) AGAiT Technology Corporation - 5F,No.27-8, Sec. 2, Zhongzheng E. Rd., Danshui Township - Taipei County 25170 - TAIWAN, PROVINCE OF CHINA - - C8-D2-C1 (hex) Jetlun (Shenzhen) Corporation - C8D2C1 (base 16) Jetlun (Shenzhen) Corporation - 1008A Skyworth Building, Gao-xin Rd South - High-Tech Park, NanShan District - Shenzhen 518057 - CHINA - - C8-D3-A3 (hex) D-Link International - C8D3A3 (base 16) D-Link International - 1 Internal Business Park, #03-12. The Synergy Singapore - Singapore Singapore 609917 - TAIWAN, PROVINCE OF CHINA - - C8-D4-29 (hex) Muehlbauer AG - C8D429 (base 16) Muehlbauer AG - Josef-Muehlbauer-Platz 1 - Roding Bavaria 93426 - GERMANY - - C8-D5-90 (hex) FLIGHT DATA SYSTEMS - C8D590 (base 16) FLIGHT DATA SYSTEMS - 31 MCGREGORS DRIVE - KEILOR PARK VICTORIA 3042 - AUSTRALIA - - C8-D5-FE (hex) Shenzhen Zowee Technology Co., Ltd - C8D5FE (base 16) Shenzhen Zowee Technology Co., Ltd - Block 5, Science and Technology Industrial Park of - Privately Owned Enterprises, Pingshan, Xili, Nanshan District , - Shenzhen GuangDong 518055 - CHINA - - C8-D7-19 (hex) Cisco Consumer Products, LLC - C8D719 (base 16) Cisco Consumer Products, LLC - 121 Theory Drive - Irvine Calfornia 92612 - UNITED STATES - - C8-D7-79 (hex) Qingdao Haier Telecom Co.,Ltd - C8D779 (base 16) Qingdao Haier Telecom Co.,Ltd - No 1 Haier road,Hi-tech Zone,Qingdao,PR.China - Qingdao Shandong 266101 - CHINA - - C8-DD-C9 (hex) Lenovo Mobile Communication Technology Ltd. - C8DDC9 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road, - ,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone - Xiamen Fujian 361006 - CHINA - - C8-DE-51 (hex) Integra Networks, Inc. - C8DE51 (base 16) Integra Networks, Inc. - 745 Albany Shaker Rd - Latham NY 12110 - UNITED STATES - - C8-DF-7C (hex) Nokia Corporation - C8DF7C (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - C8-E0-EB (hex) Apple - C8E0EB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-E1-30 (hex) Milkyway Group Ltd - C8E130 (base 16) Milkyway Group Ltd - RM 405 Tung Ming Building - 40-42 Des Voeux Road Central - Hong Kong Hong Kong 999077 - HONG KONG - - C8-E1-A7 (hex) Vertu Corporation Limited - C8E1A7 (base 16) Vertu Corporation Limited - Beacon Hill Road - Church Crookham Hampshire GU52 8DY - UNITED KINGDOM - - C8-E4-2F (hex) Technical Research Design and Development - C8E42F (base 16) Technical Research Design and Development - 186 Lincoln street - Suite 500 - Boston MA 02111 - UNITED STATES - - C8-E7-D8 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - C8E7D8 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - Mid-Fourth Flr., Building 28, Cui Xi Fourth Road,Ke Yuan West,Nanshan - Shenzhen Guangdong 518057 - CHINA - - C8-EE-08 (hex) TANGTOP TECHNOLOGY CO.,LTD - C8EE08 (base 16) TANGTOP TECHNOLOGY CO.,LTD - 1F,NO.153,Ligon St.,Beitou District - Taipei City 112 - TAIWAN, PROVINCE OF CHINA - - C8-EE-75 (hex) Pishion International Co. Ltd - C8EE75 (base 16) Pishion International Co. Ltd - 3F,NO,15-2,Beihuan Rd - Tanzi Dist - Taichung City 42760 - TAIWAN, PROVINCE OF CHINA - - C8-EE-A6 (hex) Shenzhen SHX Technology Co., Ltd - C8EEA6 (base 16) Shenzhen SHX Technology Co., Ltd - 6F,No.10 buliding,JiuXiangling Industial Zone,Xili, - Nanshan District - Shenzhen Guangdong 518055 - CHINA - - C8-EF-2E (hex) Beijing Gefei Tech. Co., Ltd - C8EF2E (base 16) Beijing Gefei Tech. Co., Ltd - A-603 Power Creative Plaza, NO.1 Shangdi E. Rd.,Haidian District, - Beijing 100085 - CHINA - - C8-F3-6B (hex) Yamato Scale Co.,Ltd. - C8F36B (base 16) Yamato Scale Co.,Ltd. - 5-22 - Saenba-cho - Akashi Hyogo 673-8688 - JAPAN - - C8-F3-86 (hex) Shenzhen Xiaoniao Technology Co.,Ltd - C8F386 (base 16) Shenzhen Xiaoniao Technology Co.,Ltd - Floor 13 C-D Yunsong Buliding - Border of Binhe Avenue and Tairan nine Road - Futian District, Shenzhen Guangdong 518040 - CHINA - - C8-F4-06 (hex) Avaya, Inc - C8F406 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - C8-F6-50 (hex) Apple - C8F650 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - C8-F6-8D (hex) S.E.TECHNOLOGIES LIMITED - C8F68D (base 16) S.E.TECHNOLOGIES LIMITED - #303 Shiodome building Level3 - 1-2-20 Kaigan - Minato-ku Tokyo 105-0022 - JAPAN - - C8-F7-04 (hex) Building Block Video - C8F704 (base 16) Building Block Video - 17 APex Park - Hailsham East Sussex BN27 2JU - UNITED KINGDOM - - C8-F7-33 (hex) Intel Corporate - C8F733 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - C8-F9-81 (hex) Seneca s.r.l. - C8F981 (base 16) Seneca s.r.l. - Via Germania, 34 - PADOVA 35127 - ITALY - - C8-F9-F9 (hex) CISCO SYSTEMS, INC. - C8F9F9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - C8-FB-26 (hex) Cisco SPVTG - C8FB26 (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - C8-FE-30 (hex) Bejing DAYO Mobile Communication Technology Ltd. - C8FE30 (base 16) Bejing DAYO Mobile Communication Technology Ltd. - Room 712, ULO Park Building No. 601E - Block B-11-1 WangJing Area, ChaoYang District - Beijing 100102 - CHINA - - C8-FF-77 (hex) Dyson Limited - C8FF77 (base 16) Dyson Limited - Tetbury Hill - Malmesbury Wiltshire SN16 0RP - UNITED KINGDOM - - CC-00-80 (hex) BETTINI SRL - CC0080 (base 16) BETTINI SRL - VIA CESARE BATTISTI 22 - CESANO MADERNO MILAN 20031 - ITALY - - CC-03-FA (hex) Technicolor CH USA - CC03FA (base 16) Technicolor CH USA - 101 West 103rd Street - INH 720 - Indianapolis IN 46290 - UNITED STATES - - CC-04-7C (hex) G-WAY Microwave - CC047C (base 16) G-WAY Microwave - 38 Leuning Street - South Hackensack New Jersey 07078 - UNITED STATES - - CC-04-B4 (hex) Select Comfort - CC04B4 (base 16) Select Comfort - 9800 59th Ave N - Minneapolis MN 55442 - UNITED STATES - - CC-05-1B (hex) Samsung Electronics Co.,Ltd - CC051B (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - CC-07-AB (hex) Samsung Electronics Co.,Ltd - CC07AB (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - CC-07-E4 (hex) Lenovo Mobile Communication Technology Ltd. - CC07E4 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999, Qishan North 2nd Road - Information & Optoelectronics Park, Torch Hi-tech Industry Development Zone, - Xiamen Fujian 361006 - CHINA - - CC-08-E0 (hex) Apple - CC08E0 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - CC-09-C8 (hex) IMAQLIQ LTD - CC09C8 (base 16) IMAQLIQ LTD - Obvodny Canal 93A - St.Petersburg 191119 - RUSSIAN FEDERATION - - CC-0C-DA (hex) Miljovakt AS - CC0CDA (base 16) Miljovakt AS - Gannestadveien 2 - Borre Vestfold 3184 - NORWAY - - CC-0D-EC (hex) Cisco SPVTG - CC0DEC (base 16) Cisco SPVTG - 5030 Sugarloaf Parkway - Lawrenceville GA 30044 - UNITED STATES - - CC-10-A3 (hex) Beijing Nan Bao Technology Co., Ltd. - CC10A3 (base 16) Beijing Nan Bao Technology Co., Ltd. - Room 8476, Floor 8, Building 3 - Yard 30,Shixing Street - Shijingshan District Beijing 100041 - CHINA - - CC-14-A6 (hex) Yichun MyEnergy Domain, Inc - CC14A6 (base 16) Yichun MyEnergy Domain, Inc - 349W. Yuanshan Rd, Yichun - Yichun Jiangxi 336000 - CHINA - - CC-18-7B (hex) Manzanita Systems, Inc. - CC187B (base 16) Manzanita Systems, Inc. - 14269 Danielson Street - Poway CA 92064 - UNITED STATES - - CC-19-A8 (hex) PT Inovação e Sistemas SA - CC19A8 (base 16) PT Inovação e Sistemas SA - Rua Eng. José Ferreira Pinto Basto - Aveiro Aveiro 3810-106 - PORTUGAL - - CC-1A-FA (hex) zte corporation - CC1AFA (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - CC-1E-FF (hex) Metrological Group BV - CC1EFF (base 16) Metrological Group BV - Mariniersweg 151 - Rotterdam Zuid-Holland 3011NK - NETHERLANDS - - CC-22-18 (hex) InnoDigital Co., Ltd. - CC2218 (base 16) InnoDigital Co., Ltd. - No.310 3F Kofomo Tower - 16-3 Sune-dong, Bundang-gu - Sungnam-city Kyunggi-do 463-825 - KOREA, REPUBLIC OF - - CC-26-2D (hex) Verifi, LLC - CC262D (base 16) Verifi, LLC - 9466 Meridian Way - West Chester OH 45069 - UNITED STATES - - CC-29-F5 (hex) Apple - CC29F5 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - CC-2A-80 (hex) Micro-Biz intelligence solutions Co.,Ltd - CC2A80 (base 16) Micro-Biz intelligence solutions Co.,Ltd - Room 611,Sunshine Building - West Renmin Road - Zhuhai City Guangdong 519000 - CHINA - - CC-2D-8C (hex) LG ELECTRONICS INC - CC2D8C (base 16) LG ELECTRONICS INC - 19-1, CHEONGHO-RI,JINWI-MYEON - PYEONGTAEK GYEONGGI-DO 451-713 - KOREA, REPUBLIC OF - - CC-30-80 (hex) VAIO Corporation - CC3080 (base 16) VAIO Corporation - 5432 Toyoshina - Azumino Nagano 399-8282 - JAPAN - - CC-33-BB (hex) SAGEMCOM SAS - CC33BB (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON CEDEX Choisissez l'état / la province 92848 - FRANCE - - CC-34-29 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - CC3429 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4)Central Science and Technology Park - Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - CC-34-D7 (hex) GEWISS S.P.A. - CC34D7 (base 16) GEWISS S.P.A. - VIA ALESSANDRO VOLTA 1 - CENATE SOTTO 24069 - ITALY - - CC-35-40 (hex) Technicolor USA Inc. - CC3540 (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - CC-39-8C (hex) Shiningtek - CC398C (base 16) Shiningtek - No. 53, Nankeng 3 St - Baoshan Township - Hsinchu 30841 - TAIWAN, PROVINCE OF CHINA - - CC-3A-61 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. - CC3A61 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. - 314, Maetan3-Dong, Yeongtong-Gu - Suwon Gyunggi-Do 443-743 - KOREA, REPUBLIC OF - - CC-3C-3F (hex) SA.S.S. Datentechnik AG - CC3C3F (base 16) SA.S.S. Datentechnik AG - Talhofstr. 32 - Gilching Bayern 82205 - GERMANY - - CC-3D-82 (hex) Intel Corporate - CC3D82 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - CC-3E-5F (hex) Hewlett Packard - CC3E5F (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - CC-3F-1D (hex) Intesis Software SL - CC3F1D (base 16) Intesis Software SL - Mila i Fontanals 1bis 1 - Igualada Barcelona 08700 - SPAIN - - CC-43-E3 (hex) Trump s.a. - CC43E3 (base 16) Trump s.a. - rue de la Maitrise 9 - Nivelles 1400 - BELGIUM - - CC-47-03 (hex) Intercon Systems Co., Ltd. - CC4703 (base 16) Intercon Systems Co., Ltd. - #915 Hanlim Human Tower - 1-40 Geumjeong-dong - Gunpo-si Gyeonggi-do 435-824 - KOREA, REPUBLIC OF - - CC-4A-E1 (hex) Fourtec -Fourier Technologies - CC4AE1 (base 16) Fourtec -Fourier Technologies - 16 Hamelacha St. POB 11681 - Rosh Ha’ayin 48091 - ISRAEL - - CC-4B-FB (hex) Hellberg Safety AB - CC4BFB (base 16) Hellberg Safety AB - Stakebergsvagen 2 - Stenkullen 44361 - SWEDEN - - CC-4E-24 (hex) Brocade Communications Systems, Inc. - CC4E24 (base 16) Brocade Communications Systems, Inc. - 130 Holger Way - San Jose CA 95134 - UNITED STATES - - CC-4E-EC (hex) HUMAX Co., Ltd. - CC4EEC (base 16) HUMAX Co., Ltd. - HUMAX Village, 216, Hwangsaeul-ro, Bundang-gu, - Seongnam-si Gyeonggi-do 463-875 - KOREA, REPUBLIC OF - - CC-50-1C (hex) KVH Industries, Inc. - CC501C (base 16) KVH Industries, Inc. - 50 Enterprise Center - Middletown RI 02842-5279 - UNITED STATES - - CC-50-76 (hex) Ocom Communications, Inc. - CC5076 (base 16) Ocom Communications, Inc. - 13F-6, No. 1, Bao Sheng Rd., - Yong Ho City 234 - TAIWAN, PROVINCE OF CHINA - - CC-52-AF (hex) Universal Global Scientific Industrial Co., Ltd. - CC52AF (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351, TAIPING RD. - SEC.1, TSAO TUEN - NAN-TOU 542 - TAIWAN, PROVINCE OF CHINA - - CC-53-B5 (hex) HUAWEI TECHNOLOGIES CO.,LTD - CC53B5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian - Longgang - ShenZhen GuangDong 518129 - CHINA - - CC-54-59 (hex) OnTime Networks AS - CC5459 (base 16) OnTime Networks AS - Gladsvei 20 - Oslo 0489 - NORWAY - - CC-55-AD (hex) RIM - CC55AD (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W9 - CANADA - - CC-59-3E (hex) TOUMAZ LTD - CC593E (base 16) TOUMAZ LTD - 115 MILTON PARK - BUILDING 3 - ABINGDON OXFORDSHIRE OX14 4RZ - UNITED KINGDOM - - CC-5C-75 (hex) Weightech Com. Imp. Exp. Equip. Pesagem Ltda - CC5C75 (base 16) Weightech Com. Imp. Exp. Equip. Pesagem Ltda - Rodovia Virgílio Várzea, 3110 - Sala 01 - Costa Norte Center - Bairro Saco Grande - Florianópolis SC 88032-001 - BRAZIL - - CC-5D-4E (hex) ZyXEL Communications Corporation - CC5D4E (base 16) ZyXEL Communications Corporation - No.6 Innovation Road II, Science Park, - Hsin Chu 300 - TAIWAN, PROVINCE OF CHINA - - CC-5D-57 (hex) Information System Research Institute,Inc. - CC5D57 (base 16) Information System Research Institute,Inc. - Metro city minamiikebukuro-bldg.5F - Minami-ikebukuro - Toshima-ku Tokyo 171-0022 - JAPAN - - CC-60-BB (hex) Empower RF Systems - CC60BB (base 16) Empower RF Systems - 316 W. Florence Ave - Inglewood CA 90301 - UNITED STATES - - CC-65-AD (hex) ARRIS Group, Inc. - CC65AD (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - CC-69-B0 (hex) Global Traffic Technologies, LLC - CC69B0 (base 16) Global Traffic Technologies, LLC - 7800 Third Street North - Suite 100 - St. Paul Minnesota 55128 - UNITED STATES - - CC-6B-98 (hex) Minetec Wireless Technologies - CC6B98 (base 16) Minetec Wireless Technologies - 10 Kembla Way - Willetton WA 6155 - AUSTRALIA - - CC-6B-F1 (hex) Sound Masking Inc. - CC6BF1 (base 16) Sound Masking Inc. - 47 - 23 - Glamis Drive Sw - Calgary Alberta T3E 6S3 - CANADA - - CC-6D-A0 (hex) Roku, Inc. - CC6DA0 (base 16) Roku, Inc. - 12980 Saratoga Ave. - Suite D - Saratoga CA 95070 - UNITED STATES - - CC-6D-EF (hex) TJK Tietolaite Oy - CC6DEF (base 16) TJK Tietolaite Oy - PL 443 - Vaasa 65101 - FINLAND - - CC-72-0F (hex) Viscount Systems Inc. - CC720F (base 16) Viscount Systems Inc. - 4585 Tillicum Street - Burnaby British Columbia V5J 5K9 - CANADA - - CC-74-98 (hex) Filmetrics Inc. - CC7498 (base 16) Filmetrics Inc. - 3560 Dunhill Street, #100 - San Diego CA 92121 - UNITED STATES - - CC-76-69 (hex) SEETECH - CC7669 (base 16) SEETECH - 19-15, Seoku-dong - Hwasung-si Gyeonggi-do 445-170 - KOREA, REPUBLIC OF - - CC-78-5F (hex) Apple - CC785F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - CC-7A-30 (hex) CMAX Wireless Co., Ltd. - CC7A30 (base 16) CMAX Wireless Co., Ltd. - KT Bongduk B/D 9F, 627-15, Bongduk-dong - Namgu Daegu 705710 - KOREA, REPUBLIC OF - - CC-7B-35 (hex) zte corporation - CC7B35 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - CC-7D-37 (hex) ARRIS Group, Inc. - CC7D37 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - CC-7E-E7 (hex) Panasonic AVC Networks Company - CC7EE7 (base 16) Panasonic AVC Networks Company - 1-15 Matsuo-cho - Kadoma City Osaka 571-8504 - JAPAN - - CC-85-6C (hex) SHENZHEN MDK DIGITAL TECHNOLOGY CO.,LTD - CC856C (base 16) SHENZHEN MDK DIGITAL TECHNOLOGY CO.,LTD - Xin fengze industrial park,shangnan east road - Shajing town ,Baoan District - SHENZHEN GUANGDONG 518101 - CHINA - - CC-89-FD (hex) Nokia Corporation - CC89FD (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - CC-8C-E3 (hex) Texas Instruments - CC8CE3 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - CC-90-93 (hex) Hansong Tehnologies - CC9093 (base 16) Hansong Tehnologies - 8 Kangping road, New development zone - Jiangning - Nanjing Jiangsu 210006 - CHINA - - CC-91-2B (hex) TE Connectivity Touch Solutions - CC912B (base 16) TE Connectivity Touch Solutions - 2245 Brighton Henrietta Town Line Road - Rochester New York 14623 - UNITED STATES - - CC-94-4A (hex) Pfeiffer Vacuum GmbH - CC944A (base 16) Pfeiffer Vacuum GmbH - Berliner Str. 43 - Asslar Hessen 35614 - GERMANY - - CC-95-D7 (hex) VIZIO, Inc - CC95D7 (base 16) VIZIO, Inc - 39 Tesla - Irvine California 92618 - UNITED STATES - - CC-96-35 (hex) LVS Co.,Ltd. - CC9635 (base 16) LVS Co.,Ltd. - SmartValley B # 801 - 30, Songdomirae-ro - Yeonsu-gu Incheon 406-840 - KOREA, REPUBLIC OF - - CC-96-A0 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - CC96A0 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - CC-9E-00 (hex) Nintendo Co., Ltd. - CC9E00 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - CC-9F-35 (hex) Transbit Sp. z o.o. - CC9F35 (base 16) Transbit Sp. z o.o. - Lukasza Drewny 80 - Warsaw 02-968 - POLAND - - CC-A0-E5 (hex) DZG Metering GmbH - CCA0E5 (base 16) DZG Metering GmbH - Heidelberger Str. 32 - Oranienburg Brandenburg 16515 - GERMANY - - CC-A2-23 (hex) Huawei Technologies Co., Ltd - CCA223 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - CC-A3-74 (hex) Guangdong Guanglian Electronic Technology Co.Ltd - CCA374 (base 16) Guangdong Guanglian Electronic Technology Co.Ltd - B338,Block13,No.232 Waihuandonglu Road,High Education Mega Center - Guangzhou Guangdong 510006 - CHINA - - CC-A4-62 (hex) ARRIS Group, Inc. - CCA462 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - CC-A4-AF (hex) Shenzhen Sowell Technology Co., LTD - CCA4AF (base 16) Shenzhen Sowell Technology Co., LTD - 7F, Yizhe Building. Yuquan Road. - Nanshan District. - Shen Zhen Guang Dong 518052 - CHINA - - CC-A6-14 (hex) AIFA TECHNOLOGY CORP. - CCA614 (base 16) AIFA TECHNOLOGY CORP. - 1F., No.230, Sec. 2, Bade Rd., Fongshan Dist. - Kaohsiung City Taiwan 83053 - TAIWAN, PROVINCE OF CHINA - - CC-AF-78 (hex) Hon Hai Precision Ind. Co.,Ltd. - CCAF78 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - CC-B2-55 (hex) D-Link International - CCB255 (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy - 609917 - SINGAPORE - - CC-B3-F8 (hex) FUJITSU ISOTEC LIMITED - CCB3F8 (base 16) FUJITSU ISOTEC LIMITED - 135,Higashinozaki,Hobara-machi, - Date-shi Fukushima 960-0695 - JAPAN - - CC-B5-5A (hex) Fraunhofer ITWM - CCB55A (base 16) Fraunhofer ITWM - Fraunhoferplatz 1 - Kaiserslautern Rhineland-Palatinae 67663 - GERMANY - - CC-B6-91 (hex) NECMagnusCommunications - CCB691 (base 16) NECMagnusCommunications - 4-28 MITA 1Chome - MitaKokusai Buld - Minato-ku Tokyo 108-0073 - JAPAN - - CC-B8-88 (hex) AnB Securite s.a. - CCB888 (base 16) AnB Securite s.a. - Rue de Joie,38-40 - Liege 4000 - BELGIUM - - CC-B8-F1 (hex) EAGLE KINGDOM TECHNOLOGIES LIMITED - CCB8F1 (base 16) EAGLE KINGDOM TECHNOLOGIES LIMITED - FLAT/ RM B 26/F TWO CHINACHEM PLAZA 68 CONNAUGHT ROAD CENTRAL HK - HONG KONG - - CC-BD-35 (hex) Steinel GmbH - CCBD35 (base 16) Steinel GmbH - Dieselstrasse 80-84 - Herzebrock-Clarholz 33442 - GERMANY - - CC-BD-D3 (hex) Ultimaker B.V. - CCBDD3 (base 16) Ultimaker B.V. - Burgemeester Rozeveld van de Venlaan 11 - Geldermalsen Gelderland 4191 PL - NETHERLANDS - - CC-BE-71 (hex) OptiLogix BV - CCBE71 (base 16) OptiLogix BV - Joop Geesinkweg 999 - Amsterdam NH 1096AZ - NETHERLANDS - - CC-C1-04 (hex) Applied Technical Systems - CCC104 (base 16) Applied Technical Systems - P.O. Box 5705 - Shreveport LA 71135 - UNITED STATES - - CC-C3-EA (hex) Motorola Mobility LLC - CCC3EA (base 16) Motorola Mobility LLC - 600 North US Highway 45 - Libertyville IL 60048 - UNITED STATES - - CC-C5-0A (hex) SHENZHEN DAJIAHAO TECHNOLOGY CO.,LTD - CCC50A (base 16) SHENZHEN DAJIAHAO TECHNOLOGY CO.,LTD - 3F Buliding 1, 2th Park TaoHuaYuan Tech- Innovation, - Xixiang Baoan - Shenzhen Guangdong 518102 - CHINA - - CC-C6-2B (hex) Tri-Systems Corporation - CCC62B (base 16) Tri-Systems Corporation - 3-27-8 TRS Building 3F - Koyasumachi - Hachioji Tokyo 192-0904 - JAPAN - - CC-C8-D7 (hex) CIAS Elettronica srl - CCC8D7 (base 16) CIAS Elettronica srl - Via Giovanni Durando 38 - Milan 20158 - ITALY - - CC-CC-4E (hex) Sun Fountainhead USA. Corp - CCCC4E (base 16) Sun Fountainhead USA. Corp - 801 S. Garfiled AVE # 236 - Los Angeles California 91801 - UNITED STATES - - CC-CC-81 (hex) HUAWEI TECHNOLOGIES CO.,LTD - CCCC81 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - CC-CD-64 (hex) SM-Electronic GmbH - CCCD64 (base 16) SM-Electronic GmbH - Waldweg 2 - Stapelfeld / Braak 22145 - GERMANY - - CC-CE-40 (hex) Janteq Corp - CCCE40 (base 16) Janteq Corp - 9272 Jeronimo Road - Suite 124 - Irvine CA 92618 - UNITED STATES - - CC-D2-9B (hex) Shenzhen Bopengfa Elec&Technology CO.,Ltd - CCD29B (base 16) Shenzhen Bopengfa Elec&Technology CO.,Ltd - Bldg56A,3/F,Baotian Rd3,Xixiang Town - Baoan District - shenzhen guangdong 518000 - CHINA - - CC-D5-39 (hex) Cisco - CCD539 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - CC-D8-11 (hex) Aiconn Technology Corporation - CCD811 (base 16) Aiconn Technology Corporation - 5F, NO. 9, Alley 2, Lane 35, Ji-Hu Rd., Nei-Hu, - Taipei City 11494 - TAIWAN, PROVINCE OF CHINA - - CC-D8-C1 (hex) Cisco - CCD8C1 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - CC-D9-E9 (hex) SCR Engineers Ltd. - CCD9E9 (base 16) SCR Engineers Ltd. - 6 Haomanut St. - Netanya 42504 - ISRAEL - - CC-E1-7F (hex) juniper networks - CCE17F (base 16) juniper networks - 1194 N Mathilda Avenue - sunnyvale CA 94089 - UNITED STATES - - CC-E1-D5 (hex) Buffalo Inc. - CCE1D5 (base 16) Buffalo Inc. - AKAMONDORI Bldg.,30-20,Ohsu 3-chome - Naka-ku,Nagoya Aichi Pref 460-8315 - JAPAN - - CC-E7-98 (hex) My Social Stuff - CCE798 (base 16) My Social Stuff - Sint-Hubertussyraat 65 - Berchem 2600 - BELGIUM - - CC-E7-DF (hex) American Magnetics, Inc. - CCE7DF (base 16) American Magnetics, Inc. - PO Box 2509 - Oak Ridge TN 37831-2509 - UNITED STATES - - CC-E8-AC (hex) SOYEA Technology Co.,Ltd. - CCE8AC (base 16) SOYEA Technology Co.,Ltd. - STB department,Floor 4,Building 11 south - Jiaogong Rd.No.1 - hangzhou zhejiang 310007 - CHINA - - CC-EA-1C (hex) DCONWORKS Co., Ltd - CCEA1C (base 16) DCONWORKS Co., Ltd - 182-13 Daerung Post Tower 2nd 5F - Guro-dong, Guro-gu - Seoul 152-847 - KOREA, REPUBLIC OF - - CC-EE-D9 (hex) VAHLE DETO GmbH - CCEED9 (base 16) VAHLE DETO GmbH - Gewerbepark Süd 11 - Kufstein Tirol 6330 - AUSTRIA - - CC-EF-48 (hex) CISCO SYSTEMS, INC. - CCEF48 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - CC-F3-A5 (hex) Chi Mei Communication Systems, Inc - CCF3A5 (base 16) Chi Mei Communication Systems, Inc - No.4 - Mingsheng Street - Tucheng City Taipei County 23678 - TAIWAN, PROVINCE OF CHINA - - CC-F4-07 (hex) EUKREA ELECTROMATIQUE SARL - CCF407 (base 16) EUKREA ELECTROMATIQUE SARL - 74 AVENUE JEAN JAURES - PESSAC GIRONDE 33600 - FRANCE - - CC-F5-38 (hex) 3isysnetworks - CCF538 (base 16) 3isysnetworks - 11F-2 No1247 , Jung Jeng RD , - TAOYUAN - Taipei Taiwan 0000 - TAIWAN, PROVINCE OF CHINA - - CC-F6-7A (hex) Ayecka Communication Systems LTD - CCF67A (base 16) Ayecka Communication Systems LTD - POB 3059 - Hod Hasharon 45130 - ISRAEL - - CC-F8-41 (hex) Lumewave - CCF841 (base 16) Lumewave - 4803 B Street - Sacramento CA 95819 - UNITED STATES - - CC-F8-F0 (hex) Xi'an HISU Multimedia Technology Co.,Ltd. - CCF8F0 (base 16) Xi'an HISU Multimedia Technology Co.,Ltd. - 3 Floor , NO.1 Building , Modern Business Enterprise Centre (East) , NO.69, Jinye road , Xi¡¯an - High-tech industry Development Zone - Xi'an City Shanxi Province 710075 - CHINA - - CC-F9-54 (hex) Avaya, Inc - CCF954 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - CC-F9-E8 (hex) Samsung Electronics Co.,Ltd - CCF9E8 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - CC-FA-00 (hex) LG Electronics - CCFA00 (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - CC-FB-65 (hex) Nintendo Co., Ltd. - CCFB65 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - CC-FC-6D (hex) RIZ TRANSMITTERS - CCFC6D (base 16) RIZ TRANSMITTERS - BOZIDAREVICEVA 13 - P.O.BOX 654 - ZAGREB 10000 - CROATIA - - CC-FC-B1 (hex) Wireless Technology, Inc. - CCFCB1 (base 16) Wireless Technology, Inc. - 2064 Eastman Ave. #113 - Ventura CA 93003-7787 - UNITED STATES - - CC-FE-3C (hex) Samsung Electronics - CCFE3C (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D0-03-4B (hex) Apple Inc - D0034B (base 16) Apple Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D0-04-92 (hex) Fiberhome Telecommunication Technologies Co.,LTD - D00492 (base 16) Fiberhome Telecommunication Technologies Co.,LTD - No.5 DongXin Road - Hongsan District - Wuhan Hubei 430074 - CHINA - - D0-07-90 (hex) Texas Instruments - D00790 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - D0-0A-AB (hex) Yokogawa Digital Computer Corporation - D00AAB (base 16) Yokogawa Digital Computer Corporation - 2-9-32 Nakacho - Musashino-shi Tokyo 180-8750 - JAPAN - - D0-0E-A4 (hex) Porsche Cars North America - D00EA4 (base 16) Porsche Cars North America - 980 Hammond Drive - Suite 1000 - Atlanta GA 30328 - UNITED STATES - - D0-0E-D9 (hex) TAICANG T AND W ELECTRONICS CO LTD - D00ED9 (base 16) TAICANG T AND W ELECTRONICS CO LTD - 89# Jiang Nan RD, Lu Du - Taicang Jiangsu 215412 - CHINA - - D0-12-42 (hex) BIOS Corporation - D01242 (base 16) BIOS Corporation - 2-43-15 Tomigaya - Shibuya-ku TOKYO 151-0063 - JAPAN - - D0-13-1E (hex) Sunrex Technology Corp - D0131E (base 16) Sunrex Technology Corp - No. 188-1,Chung Cheng Road.,Ta Ya Shiang - Taichung 428 - TAIWAN, PROVINCE OF CHINA - - D0-15-4A (hex) zte corporation - D0154A (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road, - shenzhen guangdong 518057 - CHINA - - D0-17-6A (hex) Samsung Electronics Co.,Ltd - D0176A (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D0-1A-A7 (hex) UniPrint - D01AA7 (base 16) UniPrint - Unit 309, 1 Eva Road - Toronto Ontario M9C 4Z5 - CANADA - - D0-1C-BB (hex) Beijing Ctimes Digital Technology Co., Ltd. - D01CBB (base 16) Beijing Ctimes Digital Technology Co., Ltd. - 7th Floor, Jinzhou Building, Suzhou Street, No.79, Haidian District, - Beijing 100089 - CHINA - - D0-22-12 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - D02212 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - D0-22-BE (hex) Samsung Electro Mechanics co.,LTD. - D022BE (base 16) Samsung Electro Mechanics co.,LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - D0-23-DB (hex) Apple - D023DB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D0-25-16 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - D02516 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan - Shenzhen Guangdong 518057 - CHINA - - D0-25-98 (hex) Apple, Inc. - D02598 (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D0-27-88 (hex) Hon Hai Precision Ind.Co.Ltd - D02788 (base 16) Hon Hai Precision Ind.Co.Ltd - 66,Chung Shan Rd.Tu-Cheng - Taipei Hsien 236 - TAIWAN, PROVINCE OF CHINA - - D0-2C-45 (hex) littleBits Electronics, Inc. - D02C45 (base 16) littleBits Electronics, Inc. - 60 E. 11th Street - New York NY 10003 - UNITED STATES - - D0-2D-B3 (hex) Huawei Technologies Co., Ltd - D02DB3 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - D0-31-10 (hex) Ingenic Semiconductor Co.,Ltd - D03110 (base 16) Ingenic Semiconductor Co.,Ltd - Room 108,Building A,Information Center Zhongguancun Software Park 8 Dongbeiwang West Road,Haidain District - Beijing 100193 - CHINA - - D0-37-61 (hex) Texas Instruments - D03761 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - D0-39-72 (hex) Texas Instruments - D03972 (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - D0-39-B3 (hex) ARRIS Group, Inc. - D039B3 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - D0-43-1E (hex) Dell Inc. - D0431E (base 16) Dell Inc. - One dell way - MS:RR5-45 - Round rock Texas 78682 - UNITED STATES - - D0-46-DC (hex) Southwest Research Institute - D046DC (base 16) Southwest Research Institute - 6220 Culebra Road - San Antonio Texas 78238 - UNITED STATES - - D0-48-F3 (hex) DATTUS Inc - D048F3 (base 16) DATTUS Inc - 3000 Kent Ave - W Lafayette IN 47906 - UNITED STATES - - D0-4C-C1 (hex) SINTRONES Technology Corp. - D04CC1 (base 16) SINTRONES Technology Corp. - 14F.-3, No.736, Zhongzheng Rd., Zhonghe Dist., New Taipei City 235, Taiwan (R.O.C.) - Taipei N/A 235 - TAIWAN, PROVINCE OF CHINA - - D0-4D-2C (hex) Roku, Inc - D04D2C (base 16) Roku, Inc - 12980 Saratoga Ave - Suite D - Saratoga CA 95070 - UNITED STATES - - D0-4F-7E (hex) Apple - D04F7E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D0-50-99 (hex) ASRock Incorporation - D05099 (base 16) ASRock Incorporation - 2F., No.37, Sec. 2, Jhongyang S. Rd. - Beitou District, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - D0-51-62 (hex) Sony Mobile Communications AB - D05162 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - D0-52-A8 (hex) Physical Graph Corporation - D052A8 (base 16) Physical Graph Corporation - 11654 Plaza America Drive - Suite 601 - Reston VA 20190 - UNITED STATES - - D0-53-49 (hex) Liteon Technology Co., Ltd. - D05349 (base 16) Liteon Technology Co., Ltd. - 4F, 90, Chien 1 Road ChungHo - New Taipei City Taiwan 23585 - TAIWAN, PROVINCE OF CHINA - - D0-54-2D (hex) Cambridge Industries(Group) Co.,Ltd. - D0542D (base 16) Cambridge Industries(Group) Co.,Ltd. - 22 Floor,Qilai Tower;889 Yishan Road - Shanghai 200233 - CHINA - - D0-57-4C (hex) CISCO SYSTEMS, INC. - D0574C (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D0-57-85 (hex) Pantech Co., Ltd. - D05785 (base 16) Pantech Co., Ltd. - 110-1 Ongjeong-Ri, Tongjin-Eup - Gimpo-Si Gyounggi-Do 415-865 - KOREA, REPUBLIC OF - - D0-57-A1 (hex) Werma Signaltechnik GmbH & Co. KG - D057A1 (base 16) Werma Signaltechnik GmbH & Co. KG - Duerbheimer Strasse - Rietheim-Weilheim 78604 - GERMANY - - D0-58-75 (hex) Active Control Technology Inc. - D05875 (base 16) Active Control Technology Inc. - 1800 Appleby Line - Unit 4 - Burlington Ontario L7L 6A1 - CANADA - - D0-59-C3 (hex) CeraMicro Technology Corporation - D059C3 (base 16) CeraMicro Technology Corporation - 4F, No. 16-1, Sec. 6, Mingcyuan East Road - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - D0-59-E4 (hex) Samsung Electronics Co.,Ltd - D059E4 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D0-5A-0F (hex) I-BT DIGITAL CO.,LTD - D05A0F (base 16) I-BT DIGITAL CO.,LTD - 17F.-8, No.866, Zhongzheng Rd., Zhonghe Dist - New Taipei 235 - TAIWAN, PROVINCE OF CHINA - - D0-5A-F1 (hex) Shenzhen Pulier Tech CO.,Ltd - D05AF1 (base 16) Shenzhen Pulier Tech CO.,Ltd - 3rd Floor, NO. B Buliding, District A, Shajing minzhu jiujiu industrial park , Shenzhen, China - Shenzhen Guangdong 518104 - CHINA - - D0-5B-A8 (hex) zte corporation - D05BA8 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - D0-5C-7A (hex) Sartura d.o.o. - D05C7A (base 16) Sartura d.o.o. - Kuniscak 28 - Zagreb 10000 - CROATIA - - D0-5F-B8 (hex) Texas Instruments - D05FB8 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75093 - UNITED STATES - - D0-5F-CE (hex) Hitachi Data Systems - D05FCE (base 16) Hitachi Data Systems - 750 Central Expressway - Santa Clara CA 95050 - UNITED STATES - - D0-62-A0 (hex) China Essence Technology (Zhumadian) Co., Ltd. - D062A0 (base 16) China Essence Technology (Zhumadian) Co., Ltd. - 4th Floor, Administrative Service Center Office of Yicheng District - West Jiefang Road - Zhumadian Henan Province 463000 - CHINA - - D0-63-4D (hex) Meiko Maschinenbau GmbH & Co. KG - D0634D (base 16) Meiko Maschinenbau GmbH & Co. KG - Englerstraße 3 - Offenburg 77652 - GERMANY - - D0-63-B4 (hex) SolidRun Ltd. - D063B4 (base 16) SolidRun Ltd. - P.O Box 50782 - Nazareth ISRAEL 16165 - ISRAEL - - D0-66-7B (hex) Samsung Electronics Co., LTD - D0667B (base 16) Samsung Electronics Co., LTD - 416, Maetan-3dong, Yeongtong-gu - Suwon-si Gyeonggi-do 443742 - KOREA, REPUBLIC OF - - D0-67-E5 (hex) Dell Inc - D067E5 (base 16) Dell Inc - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - D0-69-9E (hex) LUMINEX Lighting Control Equipment - D0699E (base 16) LUMINEX Lighting Control Equipment - Berkenlaan 8A - Hechtel-Eksel Limburg 3940 - BELGIUM - - D0-69-D0 (hex) Verto Medical Solutions, LLC - D069D0 (base 16) Verto Medical Solutions, LLC - 900 Spruce St., Suite 550 - St. Louis Missouri 63012 - UNITED STATES - - D0-6A-1F (hex) BSE CO.,LTD. - D06A1F (base 16) BSE CO.,LTD. - 626-3, Gozan-dong, Namdong-ku - Incheon, 405-817 - KOREA, REPUBLIC OF - - D0-6F-4A (hex) TOPWELL INTERNATIONAL HOLDINGS LIMITED - D06F4A (base 16) TOPWELL INTERNATIONAL HOLDINGS LIMITED - Unit 2506, 25/F, Prosperity Place, - 6 Shing Yip Street, Kwun Tong, Kowloon, - Hong Kong - CHINA - - D0-72-DC (hex) Cisco - D072DC (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - D0-73-7F (hex) Mini-Circuits - D0737F (base 16) Mini-Circuits - 50 Yosef Levi Street - Kiryat Bialik Industrial Zone 27000 - ISRAEL - - D0-73-8E (hex) DONG OH PRECISION CO., LTD. - D0738E (base 16) DONG OH PRECISION CO., LTD. - #282 SHINGAL-RI, JICSAN-EUP - CHEONAN-SI CHUNGCHEONGNAM-DO 331-814 - KOREA, REPUBLIC OF - - D0-73-D5 (hex) LIFI LABS MANAGEMENT PTY LTD - D073D5 (base 16) LIFI LABS MANAGEMENT PTY LTD - 7 Cubitt St - Richmond Victoria 3121 - AUSTRALIA - - D0-75-BE (hex) Reno A&E - D075BE (base 16) Reno A&E - 4655 Aircenter Circle - Reno Nevada 89502 - UNITED STATES - - D0-76-50 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - D07650 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - D0-7A-B5 (hex) Huawei Technologies Co., Ltd - D07AB5 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - D0-7D-E5 (hex) Forward Pay Systems, Inc. - D07DE5 (base 16) Forward Pay Systems, Inc. - 9531 West 78th St., #245 - Eden Prairie MN 55344 - UNITED STATES - - D0-7E-28 (hex) Hewlett Packard - D07E28 (base 16) Hewlett Packard - 11445 Compaq Center Drive W - Houston Texas 77070 - UNITED STATES - - D0-7E-35 (hex) Intel Corporate - D07E35 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - D0-83-D4 (hex) XTel ApS - D083D4 (base 16) XTel ApS - Alfred Nobels vej 21E - Aalborg Oest Nordjylland 9220 - DENMARK - - D0-84-B0 (hex) Sagemcom - D084B0 (base 16) Sagemcom - 250 route de l'Empereur - Rueil Malmaison Cedex Hauts de Seine 92848 - FRANCE - - D0-89-99 (hex) APCON, Inc. - D08999 (base 16) APCON, Inc. - 9255 SW Pioneer Court - Wilsonville OR 97070 - UNITED STATES - - D0-8A-55 (hex) Skullcandy - D08A55 (base 16) Skullcandy - 1441 Ute blvd. - Suite 250 - Park City Utah 84098 - UNITED STATES - - D0-8B-7E (hex) Passif Semiconductor - D08B7E (base 16) Passif Semiconductor - 400 S. El Camino Real Suite 250 - San Mateo California 94402 - UNITED STATES - - D0-8C-B5 (hex) Texas Instruments - D08CB5 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - D0-8C-FF (hex) UPWIS AB - D08CFF (base 16) UPWIS AB - Box 3000 - Uppsala Uppsala 75003 - SWEDEN - - D0-92-9E (hex) Microsoft Corporation - D0929E (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - D0-93-F8 (hex) Stonestreet One LLC - D093F8 (base 16) Stonestreet One LLC - 9960 Corporate Campus Drive - Suite 3300 - Louisville KY 40223 - UNITED STATES - - D0-95-C7 (hex) Pantech Co., Ltd. - D095C7 (base 16) Pantech Co., Ltd. - 110-1 Ongjeong-Ri, Tongjin-Eup - Gimpo-Si Gyounggi-Do 415-865 - KOREA, REPUBLIC OF - - D0-9B-05 (hex) Emtronix - D09B05 (base 16) Emtronix - 5# Gaopeng Dadao - Room 404#, Building B - Chengdu 610041 - CHINA - - D0-9C-30 (hex) Foster Electric Company, Limited - D09C30 (base 16) Foster Electric Company, Limited - 1-1-109, Tsutsujigaoka - Akishima Tokyo 196-8550 - JAPAN - - D0-9D-0A (hex) LINKCOM - D09D0A (base 16) LINKCOM - 11 Rue du Soleil Levant - Clamart 92140 - FRANCE - - D0-9D-AB (hex) TCT mobile ltd - D09DAB (base 16) TCT mobile ltd - NO.86 hechang 7th road, zhongkai hi-tech distrct - Hui Zhou Guang Dong 516006 - CHINA - - D0-A0-D6 (hex) Chengdu TD Tech Ltd. - D0A0D6 (base 16) Chengdu TD Tech Ltd. - 3-5F,Building 3, No.219 Tian Hua Road 2, Software Park C,High-Tech Zone - Chengdu Sichuan 610041 - CHINA - - D0-A3-11 (hex) Neuberger Gebäudeautomation GmbH - D0A311 (base 16) Neuberger Gebäudeautomation GmbH - Oberer Kaiserweg 6 - Rothenburg o.d.T. Bayern 91541 - GERMANY - - D0-A5-A6 (hex) Cisco - D0A5A6 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - D0-A6-37 (hex) Apple - D0A637 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D0-AE-EC (hex) Alpha Networks Inc. - D0AEEC (base 16) Alpha Networks Inc. - No.8 Li-shing Seventh Road,Science-based Industrial Park - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - D0-AF-B6 (hex) Linktop Technology Co., LTD - D0AFB6 (base 16) Linktop Technology Co., LTD - 2F Guangye Buliding, Torch Hi-Tech, - Xiamen Fujian 361006 - CHINA - - D0-B3-3F (hex) SHENZHEN TINNO MOBILE TECHNOLOGY CO.,LTD. - D0B33F (base 16) SHENZHEN TINNO MOBILE TECHNOLOGY CO.,LTD. - 4/F.,H-3 Building,OCT Eastern lndustrial Park. NO.1 XiangShan East Road., - Nan Shan District, - GUANGDONG SHENZHEN 518053 - CHINA - - D0-B4-98 (hex) Robert Bosch LLC Automotive Electronics - D0B498 (base 16) Robert Bosch LLC Automotive Electronics - 15000 N Haggerty - Plymouth Michigan 48170 - UNITED STATES - - D0-B5-23 (hex) Bestcare Cloucal Corp. - D0B523 (base 16) Bestcare Cloucal Corp. - 4F.,No.106,Sec.1,Xintai 5th Rd., - Xizhi Dist., - New Taipei City 22102 - TAIWAN, PROVINCE OF CHINA - - D0-B5-3D (hex) SEPRO ROBOTIQUE - D0B53D (base 16) SEPRO ROBOTIQUE - ZI Acti-Est Les Ajoncs - CS10084 - LA ROCHE SUR YON F85003 - FRANCE - - D0-B5-C2 (hex) Texas Instruments - D0B5C2 (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - D0-BB-80 (hex) SHL Telemedicine International Ltd. - D0BB80 (base 16) SHL Telemedicine International Ltd. - 90 Yigal Alon - Tel Aviv 67891 - ISRAEL - - D0-BD-01 (hex) DS International - D0BD01 (base 16) DS International - 806ho, ACE HITECH21 B/D - 1470 U-Dong, Haeundae-gu - Busan Busan 612-020 - KOREA, REPUBLIC OF - - D0-BE-2C (hex) CNSLink Co., Ltd. - D0BE2C (base 16) CNSLink Co., Ltd. - room 807, Jungang Induspia 5 - 138-6, Sangdaewon 1-dong, Jungwong-gu - Seongnam Gyeonggi 462-807 - KOREA, REPUBLIC OF - - D0-BF-9C (hex) Hewlett Packard - D0BF9C (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Tx 77070 - UNITED STATES - - D0-C0-BF (hex) Actions Microelectronics Co., Ltd - D0C0BF (base 16) Actions Microelectronics Co., Ltd - 201, No 9 Building, Software Park,Kejizhonger Rd., - Gaoxinqu, Nanshan, - Shenzhen Gangdong 518057 - CHINA - - D0-C1-B1 (hex) Samsung Electronics Co.,Ltd - D0C1B1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D0-C2-82 (hex) CISCO SYSTEMS, INC. - D0C282 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D0-C4-2F (hex) Tamagawa Seiki Co.,Ltd. - D0C42F (base 16) Tamagawa Seiki Co.,Ltd. - 1-3-47 Kitainter Kogyodanchi - Hachinohe city Aomori-Pref. 039-2245 - JAPAN - - D0-C7-89 (hex) Cisco - D0C789 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - D0-C7-C0 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - D0C7C0 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - D0-CD-E1 (hex) Scientech Electronics - D0CDE1 (base 16) Scientech Electronics - 4F, No.501-17, Zhong Zheng Rd, - Xin Dian District - New Taipei City 23148 - TAIWAN, PROVINCE OF CHINA - - D0-CF-5E (hex) Energy Micro AS - D0CF5E (base 16) Energy Micro AS - Sandakerveien 118 - Oslo N-0484 - NORWAY - - D0-D0-FD (hex) CISCO SYSTEMS, INC. - D0D0FD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D0-D2-12 (hex) K2NET Co.,Ltd. - D0D212 (base 16) K2NET Co.,Ltd. - K2Net Building - 503-25 Shinwol-dong Yangcheon-gu - Seoul 158-092 - KOREA, REPUBLIC OF - - D0-D2-86 (hex) Beckman Coulter K.K. - D0D286 (base 16) Beckman Coulter K.K. - 454-32 Higashino, - Nagaizumi-cho, Sunto-gun, Shizuoka-ken 411-0943 - JAPAN - - D0-D3-FC (hex) Mios, Ltd. - D0D3FC (base 16) Mios, Ltd. - 1301 Bank of America Tower - 12 Harcout Road - Central . - HONG KONG - - D0-D4-12 (hex) ADB Broadband Italia - D0D412 (base 16) ADB Broadband Italia - VIALE SARCA 336 - MILANO ITALY 20126 - ITALY - - D0-D4-71 (hex) MVTECH co., Ltd - D0D471 (base 16) MVTECH co., Ltd - #1004, Hanshin IT Tower, 235, Guro 3-dong, Guro-Gu - SEOUL 152-768 - KOREA, REPUBLIC OF - - D0-D6-CC (hex) Wintop - D0D6CC (base 16) Wintop - No. 1301,Xinfei Road - Songjiang District Shanghai 201612 - CHINA - - D0-DB-32 (hex) Nokia Corporation - D0DB32 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - D0-DF-9A (hex) Liteon Technology Corporation - D0DF9A (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road, ChungHo. - Taipei 23585 - TAIWAN, PROVINCE OF CHINA - - D0-DF-B2 (hex) Genie Networks Limited - D0DFB2 (base 16) Genie Networks Limited - 5F, No.15, Lane 360 - Sec., 1, Neihu Road - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - D0-DF-C7 (hex) Samsung Electronics Co.,Ltd - D0DFC7 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D0-E1-40 (hex) Apple, Inc - D0E140 (base 16) Apple, Inc - 1 infinite Loop - Cupertino CA 95014 - UNITED STATES - - D0-E3-47 (hex) Yoga - D0E347 (base 16) Yoga - Tammsaare tee 47 - Tallinn Harjumaa 11316 - ESTONIA - - D0-E4-0B (hex) Wearable Inc. - D0E40B (base 16) Wearable Inc. - 3825 Charles Dr. - Northbrook IL 60062 - UNITED STATES - - D0-E5-4D (hex) Pace plc - D0E54D (base 16) Pace plc - Victoria Road - Saltaire, - West Yorkshire England BD18 3LF - UNITED KINGDOM - - D0-E7-82 (hex) Azurewave Technologies, Inc. - D0E782 (base 16) Azurewave Technologies, Inc. - 8F., No. 94, Baozhong Rd - Xindian Dist - . New Taipei City Taiwan 231 - TAIWAN, PROVINCE OF CHINA - - D0-EB-03 (hex) Zhehua technology limited - D0EB03 (base 16) Zhehua technology limited - Room 2206,No 1079,A,ZhanTao Technology Building, MinZhi Street, Longhua District - Palm Grove House P.O.Box 468 Road Town, - Tortoal British Virgin Island,Hong Kong Shenzhen,Guang Dong 518131 - CHINA - - D0-EB-9E (hex) Seowoo Inc. - D0EB9E (base 16) Seowoo Inc. - #B101 Seojung B/D, 590-9 Guui-dong, Gwangjin-gu, - Seoul 143-831 - KOREA, REPUBLIC OF - - D0-F0-DB (hex) Ericsson - D0F0DB (base 16) Ericsson - 250 Holger Way - SAN JOSE CA 95134 - UNITED STATES - - D0-F2-7F (hex) SteadyServ Technoligies, LLC - D0F27F (base 16) SteadyServ Technoligies, LLC - 12895 Brighton Avenue - Suite A - Carmel IN 46032 - UNITED STATES - - D0-F7-3B (hex) Helmut Mauell GmbH - D0F73B (base 16) Helmut Mauell GmbH - Am Rosenhügel 1-7 - Velbert 42553 - GERMANY - - D0-FA-1D (hex) Qihoo 360 Technology Co.,Ltd - D0FA1D (base 16) Qihoo 360 Technology Co.,Ltd - Building 2,6 Haoyuan - Jiuxianqiao Road - Chaoyang District Beijing 100015 - CHINA - - D0-FF-50 (hex) Texas Instruments, Inc - D0FF50 (base 16) Texas Instruments, Inc - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - D4-00-0D (hex) Phoenix Broadband Technologies, LLC. - D4000D (base 16) Phoenix Broadband Technologies, LLC. - 589 Bethlehem Pike - Suite 1000 - Montgomeryville PA 18936 - UNITED STATES - - D4-00-57 (hex) MC Technologies GmbH - D40057 (base 16) MC Technologies GmbH - Kabelkamp 2 - Hannover 30179 - GERMANY - - D4-01-29 (hex) Broadcom Corporation - D40129 (base 16) Broadcom Corporation - 5300 California Ave. - Irvine CA 92617 - UNITED STATES - - D4-01-6D (hex) TP-LINK TECHNOLOGIES CO.,LTD. - D4016D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd - Nanshan District, Shenzhen Guandong 518057 - CHINA - - D4-02-4A (hex) Delphian Systems LLC - D4024A (base 16) Delphian Systems LLC - 720 Dartmouth Lane - Buffalo Grove IL 60089 - UNITED STATES - - D4-05-98 (hex) ARRIS Group, Inc. - D40598 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - D4-0B-1A (hex) HTC Corporation - D40B1A (base 16) HTC Corporation - No. 23, Xinghua Rd. - Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - D4-0B-B9 (hex) Solid Semecs bv. - D40BB9 (base 16) Solid Semecs bv. - Oostwijk 18 - Uden Noord Brabant 5406 XT - NETHERLANDS - - D4-0F-B2 (hex) Applied Micro Electronics AME bv - D40FB2 (base 16) Applied Micro Electronics AME bv - Esp 100 - Eindhoven NB 5633 AA - NETHERLANDS - - D4-10-90 (hex) iNFORM Systems AG - D41090 (base 16) iNFORM Systems AG - Europastrasse 15 - Glattbrugg 8152 - SWITZERLAND - - D4-10-CF (hex) Huanshun Network Science and Technology Co., Ltd. - D410CF (base 16) Huanshun Network Science and Technology Co., Ltd. - No. 218-1, North Binjiang Road - yuyao zhejiang 315400 - CHINA - - D4-11-D6 (hex) ShotSpotter, Inc. - D411D6 (base 16) ShotSpotter, Inc. - 1060 Terra Bella Ave. - Mountain View CA 94043 - UNITED STATES - - D4-12-96 (hex) Anobit Technologies Ltd. - D41296 (base 16) Anobit Technologies Ltd. - 8 Hasadnaot St. - POB 12147 - Herzeliya Pituach 46728 - ISRAEL - - D4-12-BB (hex) Quadrant Components Inc. Ltd - D412BB (base 16) Quadrant Components Inc. Ltd - Unit 5, 17/F, Metro Loft, - 38 Kwai Hei Street, - Kwai Chung, New Territory - HONG KONG - - D4-13-6F (hex) Asia Pacific Brands - D4136F (base 16) Asia Pacific Brands - PO Box 113001 - Broadway - Auckland Newmarket 1149 - NEW ZEALAND - - D4-1C-1C (hex) RCF S.P.A. - D41C1C (base 16) RCF S.P.A. - Via Raffaello Sanzio 13 - Reggio Emilia Italy 42124 - ITALY - - D4-1E-35 (hex) TOHO Electronics INC. - D41E35 (base 16) TOHO Electronics INC. - 1-13-21 Tanashioda, Chuo-Ku - Sagamihara-City Kanagawa 252-0245 - JAPAN - - D4-1F-0C (hex) JAI Oy - D41F0C (base 16) JAI Oy - Asentajankatu 3 - Helsinki 00880 - FINLAND - - D4-20-6D (hex) HTC Corporation - D4206D (base 16) HTC Corporation - No. 23, Xinghua Rd, - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - D4-21-22 (hex) Sercomm Corporation - D42122 (base 16) Sercomm Corporation - 8F, 3-1, YuanQu St., NanKang, - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - D4-22-3F (hex) Lenovo Mobile Communication Technology Ltd. - D4223F (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road,Information&Optoelectronics Park - Torch Hi-tech Industry Development Zone - Xiamen Fujian 361006 - CHINA - - D4-22-4E (hex) Alcatel Lucent - D4224E (base 16) Alcatel Lucent - Via trento, 30 - Vimercate MB 20871 - ITALY - - D4-27-51 (hex) Infopia Co., Ltd - D42751 (base 16) Infopia Co., Ltd - 891, Hogye-dong, Dongan-gu - Anyang Gyeonggi 431-080 - KOREA, REPUBLIC OF - - D4-28-B2 (hex) ioBridge, Inc. - D428B2 (base 16) ioBridge, Inc. - 225 Cedar Hill Street - Suite 200 - Marlborough MA 01752 - UNITED STATES - - D4-29-EA (hex) Zimory GmbH - D429EA (base 16) Zimory GmbH - Revalerstrasse 100 - Berlin Brandenburg 10245 - GERMANY - - D4-2C-3D (hex) Sky Light Digital Limited - D42C3D (base 16) Sky Light Digital Limited - Rm. 1009 Kwong Sang Hong Centre, 151-153 Hoi Bun Road, Kwun Tong, Kowloon, - Hong Kong 999077 - CHINA - - D4-2F-23 (hex) Akenori PTE Ltd - D42F23 (base 16) Akenori PTE Ltd - 176 Joo Chiat Road, #02-02 - Singapore 427447 - SINGAPORE - - D4-31-9D (hex) Sinwatec - D4319D (base 16) Sinwatec - 76 Rikhard Zorge st. - Ufa Bashkortostan 450075 - RUSSIAN FEDERATION - - D4-32-66 (hex) Fike Corporation - D43266 (base 16) Fike Corporation - 704 SW 10th Street - Blue Springs MO 64015 - UNITED STATES - - D4-37-D7 (hex) zte corporation - D437D7 (base 16) zte corporation - 12/F.,zte R&D building ,Kejinan Road - shenzhen guangdong 518057 - CHINA - - D4-3A-65 (hex) IGRS Engineering Lab Ltd. - D43A65 (base 16) IGRS Engineering Lab Ltd. - 8F,Taipeng Mansion - No.10 Haidian North 2nd Street - Haidian District Beijing 10000 - CHINA - - D4-3A-E9 (hex) DONGGUAN ipt INDUSTRIAL CO., LTD - D43AE9 (base 16) DONGGUAN ipt INDUSTRIAL CO., LTD - No.66-1.Ist New Area, Nanshe Dist., Chigang,Humen, - Dongguan Guangdong 52390 - CHINA - - D4-3D-67 (hex) Carma Industries Inc. - D43D67 (base 16) Carma Industries Inc. - 132 Walsh Road - Lindsay Ontario K9V 4R3 - CANADA - - D4-3D-7E (hex) Micro-Star Int'l Co, Ltd - D43D7E (base 16) Micro-Star Int'l Co, Ltd - No.69, Lide St., Jhonghe City - Taipei County 235 - TAIWAN, PROVINCE OF CHINA - - D4-43-A8 (hex) Changzhou Haojie Electric Co., Ltd. - D443A8 (base 16) Changzhou Haojie Electric Co., Ltd. - No. 158, - West Hehai Road, New District, - Changzhou Jiangsu 213022 - CHINA - - D4-4B-5E (hex) TAIYO YUDEN CO., LTD. - D44B5E (base 16) TAIYO YUDEN CO., LTD. - 8-1, Sakae-cho - Takasaki-shi Gunma 370-8522 - JAPAN - - D4-4C-24 (hex) Vuppalamritha Magnetic Components LTD - D44C24 (base 16) Vuppalamritha Magnetic Components LTD - 3rd Floor, 307 ,My Home Ashoka Chambers,S.P Road, - Secunderabad AndhraPradesh 500003 - INDIA - - D4-4C-9C (hex) Shenzhen YOOBAO Technology Co.Ltd - D44C9C (base 16) Shenzhen YOOBAO Technology Co.Ltd - F3,A5,Hua Tong Yuan Logistics Center,Minzhi Street,Longhua Town,Bao’an District,Shenzhen City,China - Shenzhen Guangdong 518000 - CHINA - - D4-4C-A7 (hex) Informtekhnika & Communication, LLC - D44CA7 (base 16) Informtekhnika & Communication, LLC - 1, build. 2/1, Verhnaya - Krasnoselskaya St. - Moscow 107140 - RUSSIAN FEDERATION - - D4-4F-80 (hex) Kemper Digital GmbH - D44F80 (base 16) Kemper Digital GmbH - Koenigswall 16-18 - Recklinghausen North-Rhine-Westphalia 45657 - GERMANY - - D4-50-7A (hex) CEIVA Logic, Inc - D4507A (base 16) CEIVA Logic, Inc - 214 E Magnolia Blvd - Burbank CA 91502 - UNITED STATES - - D4-52-2A (hex) TangoWiFi.com - D4522A (base 16) TangoWiFi.com - TangoWiFi Team - Beijing Beijing 100022 - CHINA - - D4-52-51 (hex) IBT Ingenieurbureau Broennimann Thun - D45251 (base 16) IBT Ingenieurbureau Broennimann Thun - Kasernenstrasse 5 - Thun Bern 3600 - SWITZERLAND - - D4-52-97 (hex) nSTREAMS Technologies, Inc. - D45297 (base 16) nSTREAMS Technologies, Inc. - 10F-2, No. 302, Ruiguang Rd., Neihu District, - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - D4-53-AF (hex) VIGO System S.A. - D453AF (base 16) VIGO System S.A. - 129/133 Poznanska str - Ozarow Mazowiecki Mazowieckie 05-850 - POLAND - - D4-55-56 (hex) Fiber Mountain Inc. - D45556 (base 16) Fiber Mountain Inc. - 700 W Johnson Ave - Cheshire CT 06410 - UNITED STATES - - D4-5A-B2 (hex) Galleon Systems - D45AB2 (base 16) Galleon Systems - Unit 9, Fortnum Close - Kitts Green - Birmingham West Midlands B33 0LG - UNITED KINGDOM - - D4-5C-70 (hex) Wi-Fi Alliance - D45C70 (base 16) Wi-Fi Alliance - 10900-B Stonelake Boulevard - Suite 126 - Austin TX 78759 - UNITED STATES - - D4-5D-42 (hex) Nokia Corporation - D45D42 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - D4-61-32 (hex) Pro Concept Manufacturer Co.,Ltd. - D46132 (base 16) Pro Concept Manufacturer Co.,Ltd. - 88/1 Moo12 Soi Phetkasem120 - Phetkasem Road, Omnoi, - Kratumbaen Samutsakorn 74130 - THAILAND - - D4-64-F7 (hex) CHENGDU USEE DIGITAL TECHNOLOGY CO., LTD - D464F7 (base 16) CHENGDU USEE DIGITAL TECHNOLOGY CO., LTD - NO.6 CHUANGYE ROAD - NO.333 YUNHUA ROAD - CHENGDU SICHUAN 610041 - CHINA - - D4-66-A8 (hex) Riedo Networks GmbH - D466A8 (base 16) Riedo Networks GmbH - Warpelstrasse 10 - Duedingen FR 3186 - SWITZERLAND - - D4-67-61 (hex) SAHAB TECHNOLOGY - D46761 (base 16) SAHAB TECHNOLOGY - OFFICE 31 , BUILDING 134 , ROAD 39 , BLOCK 335 - UMM AL-HASSAM - MANAMA 26584 - BAHRAIN - - D4-67-E7 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - D467E7 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - D4-68-4D (hex) Ruckus Wireless - D4684D (base 16) Ruckus Wireless - 350 West Maude Ave - Sunnyvale CA 94089 - UNITED STATES - - D4-68-67 (hex) Neoventus Design Group - D46867 (base 16) Neoventus Design Group - 2350 Commonwealth Dr, Suite E - Charlottesville VA 22901 - UNITED STATES - - D4-68-BA (hex) Shenzhen Sundray Technologies Company Limited - D468BA (base 16) Shenzhen Sundray Technologies Company Limited - 6th Floor,Block A1, Nanshan iPark, - No.1001 XueYuan Road - Nanshan District, Shenzhen 518055 Guangdong - CHINA - - D4-6A-91 (hex) Snap AV - D46A91 (base 16) Snap AV - 1800 Continental Blvd - Suite 200 - Charlotte North Carolina 28273 - UNITED STATES - - D4-6A-A8 (hex) HUAWEI TECHNOLOGIES CO.,LTD - D46AA8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - Shenzhen Guangdong 518129 - CHINA - - D4-6C-BF (hex) Goodrich ISR - D46CBF (base 16) Goodrich ISR - 6600 Gulton Crt - Albuquerque NM 87109 - UNITED STATES - - D4-6C-DA (hex) CSM GmbH - D46CDA (base 16) CSM GmbH - Raiffeisenstraße 34 - Filderstadt Baden-Württemberg 70794 - GERMANY - - D4-6D-50 (hex) Cisco - D46D50 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - D4-6E-5C (hex) Huawei Technologies Co., Ltd - D46E5C (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate - Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - D4-6F-42 (hex) WAXESS USA Inc - D46F42 (base 16) WAXESS USA Inc - 1401 Dove Street - Suite 220 - Newport Beach CA 92660 - UNITED STATES - - D4-79-C3 (hex) Cameronet GmbH & Co. KG - D479C3 (base 16) Cameronet GmbH & Co. KG - Elberfelder Strasse 96 - Remscheid NRW 42853 - GERMANY - - D4-7B-35 (hex) NEO Monitors AS - D47B35 (base 16) NEO Monitors AS - PoBox 384 - Loerenskog Loerenskog 1471 - NORWAY - - D4-7B-75 (hex) HARTING Electronics GmbH - D47B75 (base 16) HARTING Electronics GmbH - Marienwerderstraße. 3 - Espelkamp North Rhine Westphalia 32339 - GERMANY - - D4-81-CA (hex) iDevices, LLC - D481CA (base 16) iDevices, LLC - 136 Simsbury, Rd - Building 12 - Avon CT 06001 - UNITED STATES - - D4-82-3E (hex) Argosy Technologies, Ltd. - D4823E (base 16) Argosy Technologies, Ltd. - 73-221 Haystack Road - Palm Desert CA 92260 - UNITED STATES - - D4-85-64 (hex) Hewlett-Packard Company - D48564 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - D4-87-D8 (hex) Samsung Electronics - D487D8 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D4-88-90 (hex) Samsung Electronics Co.,Ltd - D48890 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D4-8C-B5 (hex) CISCO SYSTEMS, INC. - D48CB5 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D4-8D-D9 (hex) Meld Technology, Inc - D48DD9 (base 16) Meld Technology, Inc - 725 San Aleso Ave - Sunnyvale CA 94085 - UNITED STATES - - D4-8F-33 (hex) Microsoft Corporation - D48F33 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - D4-8F-AA (hex) Sogecam Industrial, S.A. - D48FAA (base 16) Sogecam Industrial, S.A. - Rosalind Franklin, 22-24 - PTA Campanillas - Malaga 29590 - SPAIN - - D4-91-AF (hex) Electroacustica General Iberica, S.A. - D491AF (base 16) Electroacustica General Iberica, S.A. - Avda Almozara, 79 - Zaragoza 50003 - SPAIN - - D4-93-98 (hex) Nokia Corporation - D49398 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - D4-93-A0 (hex) Fidelix Oy - D493A0 (base 16) Fidelix Oy - Martinkyläntie 41 - VANTAA International 01720 - FINLAND - - D4-94-5A (hex) COSMO CO., LTD - D4945A (base 16) COSMO CO., LTD - 1-12, Higashi-Gotanda 2-chome - Shinagawa-ku Tokyo 141-0022 - JAPAN - - D4-94-A1 (hex) Texas Instruments - D494A1 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - D4-95-24 (hex) Clover Network, Inc. - D49524 (base 16) Clover Network, Inc. - 650 Castro Street - #120-278 - Los Altos California 94041 - UNITED STATES - - D4-96-DF (hex) SUNGJIN C&T CO.,LTD - D496DF (base 16) SUNGJIN C&T CO.,LTD - Daeya - 362-5 - Sheung Gyeonggi 429-809 - KOREA, REPUBLIC OF - - D4-97-0B (hex) XIAOMI CORPORATION - D4970B (base 16) XIAOMI CORPORATION - The Rainbow City of China Resources - NO 68,Qinghe Middle Street, - Haidian District Beijing 100085 - CHINA - - D4-9A-20 (hex) Apple - D49A20 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D4-9C-28 (hex) JayBird Gear LLC - D49C28 (base 16) JayBird Gear LLC - 2825 East Cottonwood Parkway #500 - Salt Lake City UT 84121 - UNITED STATES - - D4-9C-8E (hex) University of FUKUI - D49C8E (base 16) University of FUKUI - 3-9-1 Bunkyo - Fukui City 910-8507 - JAPAN - - D4-9E-6D (hex) Wuhan Zhongyuan Huadian Science & Technology Co., - D49E6D (base 16) Wuhan Zhongyuan Huadian Science & Technology Co., - NO.6, 6 Road, Sci. & Tech. region of HUST, East Lake Development Zone, - Wuhan Hubei 430223 - CHINA - - D4-A0-2A (hex) CISCO SYSTEMS, INC. - D4A02A (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D4-A4-25 (hex) SMAX Technology Co., Ltd. - D4A425 (base 16) SMAX Technology Co., Ltd. - 2F., No. 3, Wuquan 3rd, Wugu Dist. - New Taipei City 248 - TAIWAN, PROVINCE OF CHINA - - D4-A4-99 (hex) InView Technology Corporation - D4A499 (base 16) InView Technology Corporation - 8900 Shoal Creek Blvd - Suite 125 - Austin TX 78757 - UNITED STATES - - D4-A9-28 (hex) GreenWave Reality Inc - D4A928 (base 16) GreenWave Reality Inc - 39 Parker - Irvine California 92618 - UNITED STATES - - D4-AA-FF (hex) MICRO WORLD - D4AAFF (base 16) MICRO WORLD - 19370 VAN NESS AVE - TORRANCE CA 90501 - UNITED STATES - - D4-AC-4E (hex) BODi rS, LLC - D4AC4E (base 16) BODi rS, LLC - 7622 Rickenbacker Drive - Gaithersburg MD 20879 - UNITED STATES - - D4-AD-2D (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - D4AD2D (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - D4-AE-52 (hex) Dell Inc - D4AE52 (base 16) Dell Inc - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - D4-B1-10 (hex) HUAWEI TECHNOLOGIES CO.,LTD - D4B110 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4A52R,Huawei Industrial Base - Bantian Longgang - ShenZhen GuangDong 518129 - CHINA - - D4-B4-3E (hex) Messcomp Datentechnik GmbH - D4B43E (base 16) Messcomp Datentechnik GmbH - Neudecker Str. 11 - Wasserburg Bayern 83512 - GERMANY - - D4-BE-D9 (hex) Dell Inc - D4BED9 (base 16) Dell Inc - One Dell Way, MS:RR5-45 - Round Rock Texas 78682 - UNITED STATES - - D4-BF-2D (hex) SE Controls Asia Pacific Ltd - D4BF2D (base 16) SE Controls Asia Pacific Ltd - Unit 301, 3/F, Hung To Centre, - 94, How Ming Street - Kwun Tong Kowloon - HONG KONG - - D4-BF-7F (hex) UPVEL - D4BF7F (base 16) UPVEL - 13139 Ramona Blvd. #F - Irwindale CA 91706 - UNITED STATES - - D4-C1-FC (hex) Nokia Corporation - D4C1FC (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - D4-C7-66 (hex) Acentic GmbH - D4C766 (base 16) Acentic GmbH - Venloer Strasse 151-153 - Cologne 50672 - GERMANY - - D4-C9-EF (hex) Hewlett Packard - D4C9EF (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - D4-CA-6D (hex) Routerboard.com - D4CA6D (base 16) Routerboard.com - Mikrotikls SIA - Pernavas 46 - Riga LV-1009 - LATVIA - - D4-CA-6E (hex) u-blox AG - D4CA6E (base 16) u-blox AG - Zuercherstrasse 68 - Thalwil 8800 - SWITZERLAND - - D4-CB-AF (hex) Nokia Corporation - D4CBAF (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - D4-CE-B8 (hex) Enatel LTD - D4CEB8 (base 16) Enatel LTD - 66 Treffers Road - Christchurch Canterbury 8042 - NEW ZEALAND - - D4-CF-F9 (hex) Shenzhen Sen5 Technology Co., Ltd. - D4CFF9 (base 16) Shenzhen Sen5 Technology Co., Ltd. - 3F (East), Block D, SDG Infoport, No.2 Kefeng Road,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - D4-D1-84 (hex) ADB Broadband Italia - D4D184 (base 16) ADB Broadband Italia - via Sarca 222 - Milano 20126 - ITALY - - D4-D2-49 (hex) Power Ethernet - D4D249 (base 16) Power Ethernet - 4th Floor, Holborn Gate - 26 Southampton Buildings - London WC2A 1AH - UNITED KINGDOM - - D4-D5-0D (hex) Southwest Microwave, Inc - D4D50D (base 16) Southwest Microwave, Inc - 9055 S McKemy St - Tempe AZ 85284 - UNITED STATES - - D4-D7-48 (hex) CISCO SYSTEMS, INC. - D4D748 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D4-D7-A9 (hex) Shanghai Kaixiang Info Tech LTD - D4D7A9 (base 16) Shanghai Kaixiang Info Tech LTD - A401, NO.509 Caobao Road, Shanghai, PRC - Shanghai Shanghai 200233 - CHINA - - D4-D8-98 (hex) Korea CNO Tech Co., Ltd - D4D898 (base 16) Korea CNO Tech Co., Ltd - #240-1,Uigok-Ri - Yeongsun-Myeon - Mungyeong-Si Gyeongsangbuk-do 745-853 - KOREA, REPUBLIC OF - - D4-D9-19 (hex) GoPro - D4D919 (base 16) GoPro - 3000 Clearview Way - San Mateo CA 94402 - UNITED STATES - - D4-DF-57 (hex) Alpinion Medical Systems - D4DF57 (base 16) Alpinion Medical Systems - 1F Verdi Tower 222-22 - Guro3-Dong Guro-Gu - Seoul 181-848 - KOREA, REPUBLIC OF - - D4-E0-8E (hex) ValueHD Corporation - D4E08E (base 16) ValueHD Corporation - Xinwei Xili, Nanshan District, Shenzhen City Industrial Zone, Shiling 8, 3rd Floor, North - Shenzhen Guangdong 518055 - CHINA - - D4-E3-2C (hex) S. Siedle & Sohne - D4E32C (base 16) S. Siedle & Sohne - Bregstrasse 1 - Furtwangen D-78120 - GERMANY - - D4-E3-3F (hex) Alcatel-Lucent - D4E33F (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - D4-E8-B2 (hex) Samsung Electronics - D4E8B2 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D4-EA-0E (hex) Avaya, Inc - D4EA0E (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - D4-EC-0C (hex) Harley-Davidson Motor Company - D4EC0C (base 16) Harley-Davidson Motor Company - 3700 W. Juneau Avenue - Milwaukee Wisconsin 53208 - UNITED STATES - - D4-EC-86 (hex) LinkedHope Intelligent Technologies Co., Ltd - D4EC86 (base 16) LinkedHope Intelligent Technologies Co., Ltd - 2nd Floor,Building 1, Science Park, - Zhonghe Road, Fengtai District - Beijing 100070 - CHINA - - D4-EE-07 (hex) HIWIFI Co., Ltd. - D4EE07 (base 16) HIWIFI Co., Ltd. - Room 1002, Zhongguancun e-Plaza A, - No.11 Zhongguancun Street - Haidian District Beijing 100080 - CHINA - - D4-F0-27 (hex) Navetas Energy Management - D4F027 (base 16) Navetas Energy Management - 17A Deben Mill Business Centre - Old Maltings Approach - Woodbridge Suffolk IP12 1BL - UNITED KINGDOM - - D4-F0-B4 (hex) Napco Security Technologies - D4F0B4 (base 16) Napco Security Technologies - 333 Bayview Ave - Amityville NY 11701 - UNITED STATES - - D4-F1-43 (hex) IPROAD.,Inc - D4F143 (base 16) IPROAD.,Inc - #505 Byuksan digital valley 7, 170-13, - Guro-3-Dong, Guro-gu - Seoul 152-847 - KOREA, REPUBLIC OF - - D4-F4-6F (hex) Apple - D4F46F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D4-F5-13 (hex) Texas Instruments - D4F513 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - D4-F6-3F (hex) IEA S.R.L. - D4F63F (base 16) IEA S.R.L. - Eva Peron 4468 - Rosario Santa Fe S2002LBQ - ARGENTINA - - D4-F9-A1 (hex) HUAWEI TECHNOLOGIES CO.,LTD - D4F9A1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - Shenzhen Guangdong 518128 - CHINA - - D8-00-4D (hex) Apple - D8004D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-05-2E (hex) Skyviia Corporation - D8052E (base 16) Skyviia Corporation - No. 10-1, Lixing 1st Rd., Science Park, - Hsinchu City 300 - TAIWAN, PROVINCE OF CHINA - - D8-06-D1 (hex) Honeywell Fire System (Shanghai) Co,. Ltd. - D806D1 (base 16) Honeywell Fire System (Shanghai) Co,. Ltd. - No. 430, Li Bing Road, Pudong - Shanghai Shanghai 201203 - CHINA - - D8-08-F5 (hex) Arcadia Networks Co. Ltd. - D808F5 (base 16) Arcadia Networks Co. Ltd. - Cheung Sha Wan 5-B FL - Kowloon 0633 - HONG KONG - - D8-09-C3 (hex) Cercacor Labs - D809C3 (base 16) Cercacor Labs - 189 Technology Dr - Irvine CA 92618 - UNITED STATES - - D8-0C-CF (hex) C.G.V. S.A.S. - D80CCF (base 16) C.G.V. S.A.S. - 18, RUE THEODORE MONOD - ZA LA VIGIE BP 90004 - OSTWALD CEDEX BAS-RHIN 67541 - FRANCE - - D8-0D-E3 (hex) FXI TECHNOLOGIES AS - D80DE3 (base 16) FXI TECHNOLOGIES AS - Postboks 609 - TRONDHEIM Norge 7406 - NORWAY - - D8-15-0D (hex) TP-LINK TECHNOLOGIES CO.,LTD. - D8150D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4) - Central Science and Technology Park, - Shennan Road,Nanshan, Shenzhen Guangdong 518057 - CHINA - - D8-16-0A (hex) Nippon Electro-Sensory Devices - D8160A (base 16) Nippon Electro-Sensory Devices - Itachibori 2-5-12 - Nishi-ku Osaka 550-0012 - JAPAN - - D8-18-2B (hex) Conti Temic Microelectronic GmbH - D8182B (base 16) Conti Temic Microelectronic GmbH - Sieboldstraße 19 - Nuremberg Bavaria 90411 - GERMANY - - D8-19-CE (hex) Telesquare - D819CE (base 16) Telesquare - 670, Sampyeong-dong, Bundang-gu - U-Space-1 1010 - Seongnam-si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - D8-1B-FE (hex) TWINLINX CORPORATION - D81BFE (base 16) TWINLINX CORPORATION - ESPACE DESCARTES BAT B - 425 RUE RENE DESCARTES - AIX EN PROVENCE PROVENCE 13857 - FRANCE - - D8-1C-14 (hex) Compacta International, Ltd. - D81C14 (base 16) Compacta International, Ltd. - 31342 Via Las Palmas - San Juan Capistrano CA 92675 - UNITED STATES - - D8-1D-72 (hex) Apple - D81D72 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-1E-DE (hex) B&W Group Ltd - D81EDE (base 16) B&W Group Ltd - 5070 Francois Cusson - Lachine Quebec H8T1B3 - CANADA - - D8-24-BD (hex) CISCO SYSTEMS, INC. - D824BD (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D8-25-22 (hex) Pace plc - D82522 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - D8-26-B9 (hex) Guangdong Coagent Electronics S &T Co., Ltd. - D826B9 (base 16) Guangdong Coagent Electronics S &T Co., Ltd. - Section C,Xi Nan Industrial Zone Sanshui - Foshan Guangdong 528133 - CHINA - - D8-27-0C (hex) MaxTronic International Co., Ltd. - D8270C (base 16) MaxTronic International Co., Ltd. - 4F., No.529, Zhongzheng Rd., Xindian Dist. - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - D8-28-C9 (hex) General Electric Consumer and Industrial - D828C9 (base 16) General Electric Consumer and Industrial - AP35-1405 - Appliance Park - Louisville KY 40225 - UNITED STATES - - D8-29-16 (hex) Ascent Communication Technology - D82916 (base 16) Ascent Communication Technology - 13/F., Shum Tower - 268 Des Voeux Road Central - Hong Kong 9999 - HONG KONG - - D8-29-86 (hex) Best Wish Technology LTD - D82986 (base 16) Best Wish Technology LTD - 7E,Hai Yi Business Building,No.310,Tianshan RD., - Shanghai 200336 - CHINA - - D8-2A-15 (hex) Leitner SpA - D82A15 (base 16) Leitner SpA - Via Brennero 34 - Vipiteno Bolzano 39049 - ITALY - - D8-2A-7E (hex) Nokia Corporation - D82A7E (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - D8-2D-9B (hex) Shenzhen G.Credit Communication Technology Co., Ltd - D82D9B (base 16) Shenzhen G.Credit Communication Technology Co., Ltd - 4/F, Suite A, XinNengYuan Building, 2239 Nanhai Rd., Nanshan Dist., Shenzhen, Guangdong,China - Shenzhen Guangdong 518054 - CHINA - - D8-2D-E1 (hex) Tricascade Inc. - D82DE1 (base 16) Tricascade Inc. - 5020 Campus Drv. - Newport Beach CA 92660 - UNITED STATES - - D8-30-62 (hex) Apple - D83062 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-31-CF (hex) Samsung Electronics Co.,Ltd - D831CF (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D8-33-7F (hex) Office FA.com Co.,Ltd. - D8337F (base 16) Office FA.com Co.,Ltd. - 293-21 - Naranoki - Oyama-shi Tochigi 329-0216 - JAPAN - - D8-3C-69 (hex) Tinno Mobile Technology Corp - D83C69 (base 16) Tinno Mobile Technology Corp - 4/F.,H-3 Building,OCT Eastern lndustrial Park. NO.1 XiangShan East Road - Nanshan District - SHENZHEN GUANGDONG 518053 - CHINA - - D8-42-AC (hex) Shanghai Feixun Communication Co.,Ltd. - D842AC (base 16) Shanghai Feixun Communication Co.,Ltd. - Building 90, No. 4855, Guangfulin Road, Songjiang District - Shanghai 201616 - CHINA - - D8-46-06 (hex) Silicon Valley Global Marketing - D84606 (base 16) Silicon Valley Global Marketing - 830 Stewart Dr. #201 - Sunnyvale Ca 94085 - UNITED STATES - - D8-49-0B (hex) HUAWEI TECHNOLOGIES CO.,LTD - D8490B (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - Shenzhen Guangdong 518129 - CHINA - - D8-49-2F (hex) CANON INC. - D8492F (base 16) CANON INC. - 30-2 Shimomaruko 3-chome, - Ohta-ku Tokyo 146-8501 - JAPAN - - D8-4A-87 (hex) OI ELECTRIC CO.,LTD - D84A87 (base 16) OI ELECTRIC CO.,LTD - 7-3-16 KIKUNA - KOHOKU-KU - YOKOHAMA KANAGAWA-KEN 222-0011 - JAPAN - - D8-4B-2A (hex) Cognitas Technologies, Inc. - D84B2A (base 16) Cognitas Technologies, Inc. - 6406 Laurel Bush Ln. - Sugar Land Texas 77479 - UNITED STATES - - D8-50-E6 (hex) ASUSTek COMPUTER INC. - D850E6 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, Taipei 112, Taiwan - Taipei Taiwan 112 - TAIWAN, PROVINCE OF CHINA - - D8-54-3A (hex) Texas Instruments - D8543A (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - D8-54-A2 (hex) Aerohive Networks Inc. - D854A2 (base 16) Aerohive Networks Inc. - 330 Gibraltar Dr. - Sunnyvale CA 94089 - UNITED STATES - - D8-55-A3 (hex) zte corporation - D855A3 (base 16) zte corporation - 12/F.,zte R&D building,kejinan Road - shenzhen guangdong 518057 - CHINA - - D8-57-EF (hex) Samsung Electronics - D857EF (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D8-58-D7 (hex) CZ.NIC, z.s.p.o. - D858D7 (base 16) CZ.NIC, z.s.p.o. - Americka 23 - Prague 12000 - CZECH REPUBLIC - - D8-5D-4C (hex) TP-LINK Technologies Co.,Ltd. - D85D4C (base 16) TP-LINK Technologies Co.,Ltd. - Building 7, Second Part, Honghualing Industrial Zone - Xili town, Nanshan, - Shenzhen Guangdong 518000 - CHINA - - D8-5D-84 (hex) CAx soft GmbH - D85D84 (base 16) CAx soft GmbH - Noettinger Strasse 3 - Karlsbad BW 76307 - GERMANY - - D8-5D-E2 (hex) Hon Hai Precision Ind. Co.,Ltd. - D85DE2 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - Xiyong Town,Shapingba District - Chongqing 401332 - CHINA - - D8-5D-EF (hex) Busch-Jaeger Elektro GmbH - D85DEF (base 16) Busch-Jaeger Elektro GmbH - Freisenbergstrasse 2 - Luedenscheid NRW 58513 - GERMANY - - D8-5D-FB (hex) PRIVATE - D85DFB (base 16) - - D8-61-94 (hex) Objetivos y Sevicios de Valor Añadido - D86194 (base 16) Objetivos y Sevicios de Valor Añadido - Calle Monte Esquinza 28, 1ºD - Madrid 28010 - SPAIN - - D8-62-DB (hex) Eno Inc. - D862DB (base 16) Eno Inc. - 2-3-18, Komagome, Toshima-ku - Tokyo 1700013 - JAPAN - - D8-65-95 (hex) Toy's Myth Inc. - D86595 (base 16) Toy's Myth Inc. - 304, Yongsan-gu Changup-Jiwon center - Seobinggo-dong, Yongsan-gu - Seoul 140-240 - KOREA, REPUBLIC OF - - D8-66-C6 (hex) Shenzhen Daystar Technology Co.,ltd - D866C6 (base 16) Shenzhen Daystar Technology Co.,ltd - The 5th Floor,#4 Building, Minxing Industria Zone - Minzhi Minkang Road, Banan District - Shenzhen Guangdong 518131 - CHINA - - D8-66-EE (hex) BOXIN COMMUNICATION CO.,LTD. - D866EE (base 16) BOXIN COMMUNICATION CO.,LTD. - Room 309,Block A,New materials business building - Feng Hui Road No. 7, - Haidian District Beijing 100094 - CHINA - - D8-67-D9 (hex) CISCO SYSTEMS, INC. - D867D9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - D8-69-60 (hex) Steinsvik - D86960 (base 16) Steinsvik - Rundhaug 25 - FOERRESFJORDEN Rogaland 5563 - NORWAY - - D8-6B-F7 (hex) Nintendo Co., Ltd. - D86BF7 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - D8-6C-E9 (hex) SAGEMCOM SAS - D86CE9 (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL-MALMAISON CEDEX IDF 92848 - FRANCE - - D8-71-57 (hex) Lenovo Mobile Communication Technology Ltd. - D87157 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone, - Xiamen Fujian 361006 - CHINA - - D8-74-95 (hex) zte corporation - D87495 (base 16) zte corporation - 12/F.,zte R&D building - kejinan Road - shenzhen guangdong 518057 - CHINA - - D8-75-33 (hex) Nokia Corporation - D87533 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - D8-76-0A (hex) Escort, Inc. - D8760A (base 16) Escort, Inc. - 5440 West Chester Rd. - West Chester Ohio 45069 - UNITED STATES - - D8-78-E5 (hex) KUHN SA - D878E5 (base 16) KUHN SA - 4, impasse des fabriques - SAVERNE 67700 - FRANCE - - D8-79-88 (hex) Hon Hai Precision Ind. Co., Ltd. - D87988 (base 16) Hon Hai Precision Ind. Co., Ltd. - NO.168 FOXCONN ROAD - HUAIAN ECONOMIC DEVELOPMENT ZONE - HUAIAN JIANGSU 223005 - CHINA - - D8-7C-DD (hex) SANIX INCORPORATED - D87CDD (base 16) SANIX INCORPORATED - Creation Core Fukuoka 212, 3-2-16 Kamikoga, - Chikushino-shi Fukuoka 818-0041 - JAPAN - - D8-7E-B1 (hex) x.o.ware, inc. - D87EB1 (base 16) x.o.ware, inc. - 114 E. Haley St., Ste N - Santa Barbara California 93101 - UNITED STATES - - D8-80-39 (hex) Microchip Technology Inc. - D88039 (base 16) Microchip Technology Inc. - 2355 W. Chandler Blvd. - M/S 4-2-A - Chandler AZ 85224 - UNITED STATES - - D8-81-CE (hex) AHN INC. - D881CE (base 16) AHN INC. - 1006,Halla sigma valley, 53, Gasandigital 2-Ro - Geumcheon-Gu - Seoul 153 706 - KOREA, REPUBLIC OF - - D8-84-66 (hex) Extreme Networks - D88466 (base 16) Extreme Networks - 145 Rio Robles - San Jose CA 95134 - UNITED STATES - - D8-8A-3B (hex) UNIT-EM - D88A3B (base 16) UNIT-EM - 167 Merchants Street - Valletta VLT 1174 - MALTA - - D8-8D-5C (hex) Elentec - D88D5C (base 16) Elentec - Dongtangiheung-ro 64-3 - Gyeonggi-do Hwaseong-si/Dongtan-myeon 445-812 - KOREA, REPUBLIC OF - - D8-90-E8 (hex) Samsung Electronics Co.,Ltd - D890E8 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - D8-93-41 (hex) General Electric Global Research - D89341 (base 16) General Electric Global Research - 2623 Camino Ramon - San Ramon CA 94583 - UNITED STATES - - D8-95-2F (hex) Texas Instruments - D8952F (base 16) Texas Instruments - 12500 TI Boulevard - MS 8723 - Dallas Texas 75243 - UNITED STATES - - D8-96-85 (hex) GoPro - D89685 (base 16) GoPro - 3000 Clearview Way - San Mateo CA 94402 - UNITED STATES - - D8-96-95 (hex) Apple - D89695 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-96-E0 (hex) Alibaba Cloud Computing Ltd. - D896E0 (base 16) Alibaba Cloud Computing Ltd. - Yuhang District of Hangzhou Wenyi Road, Building 1, No. 969 Xixi Park, Zhejiang Province - Hangzhou Zhejiang 310000 - CHINA - - D8-97-3B (hex) Artesyn Embedded Technologies - D8973B (base 16) Artesyn Embedded Technologies - 16/F Lu Plaza Building - 2 Wing Yip Street - Kwun Tong Kowloon 00000 - HONG KONG - - D8-97-60 (hex) C2 Development, Inc. - D89760 (base 16) C2 Development, Inc. - 127 S Bell Ave - Ames IA 50010 - UNITED STATES - - D8-97-7C (hex) Grey Innovation - D8977C (base 16) Grey Innovation - 255 Mary St - Richmond Victoria 3121 - AUSTRALIA - - D8-97-BA (hex) PEGATRON CORPORATION - D897BA (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - D8-9A-34 (hex) Beijing SHENQI Technology Co., Ltd. - D89A34 (base 16) Beijing SHENQI Technology Co., Ltd. - No.6 Shang Di West Road - Haidian District Beijing 100085 - CHINA - - D8-9D-67 (hex) Hewlett Packard - D89D67 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - D8-9D-B9 (hex) eMegatech International Corp. - D89DB9 (base 16) eMegatech International Corp. - Room 403, No.24 Wucyuan 2nd Rd., - Sinjhuang City, Taipei County, 238 - TAIWAN, PROVINCE OF CHINA - - D8-9E-3F (hex) Apple - D89E3F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-A2-5E (hex) Apple - D8A25E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-AD-DD (hex) Sonavation, Inc. - D8ADDD (base 16) Sonavation, Inc. - 3970 RCA Blvd. - Suite 7003 - Palm Beach Gardens Florida 33410 - UNITED STATES - - D8-AE-90 (hex) Itibia Technologies - D8AE90 (base 16) Itibia Technologies - 5 Clausen Ct - West Windsor NJ 08550 - UNITED STATES - - D8-AF-3B (hex) Hangzhou Bigbright Integrated communications system Co.,Ltd - D8AF3B (base 16) Hangzhou Bigbright Integrated communications system Co.,Ltd - The 6floor ,Building1,No.1418-41,Moganshan Road - Hangzhou Zhejiang 310015 - CHINA - - D8-AF-F1 (hex) Panasonic Appliances Company - D8AFF1 (base 16) Panasonic Appliances Company - 2-3-1-2 Noji-higashi - Kusatsu City Shiga 525-8555 - JAPAN - - D8-B0-2E (hex) Guangzhou Zonerich Business Machine Co., Ltd - D8B02E (base 16) Guangzhou Zonerich Business Machine Co., Ltd - F4, Office Building, No.17 Xiangshan Road - Science City, Luogang - Guangzhou Guangdong 510663 - CHINA - - D8-B0-4C (hex) Jinan USR IOT Technology Co., Ltd. - D8B04C (base 16) Jinan USR IOT Technology Co., Ltd. - #1-523, Huizhan Guoji Cheng, Gaoxin Qu - JINAN SHANDONG 250101 - CHINA - - D8-B1-2A (hex) Panasonic Mobile Communications Co., Ltd. - D8B12A (base 16) Panasonic Mobile Communications Co., Ltd. - 600 Saedo-cho Tsuzuki-ku - Yokohama City Kanagawa 224-8539 - JAPAN - - D8-B3-77 (hex) HTC Corporation - D8B377 (base 16) HTC Corporation - No. 23, Xinghua Rd., - Taoyuan City 330 - TAIWAN, PROVINCE OF CHINA - - D8-B6-B7 (hex) Comtrend Corporation - D8B6B7 (base 16) Comtrend Corporation - 3F-1, 10 Lane 609, - Chongxin Rd., Section 5, Sanchong Dist, - New Taipei City , Taiwan 24159 - TAIWAN, PROVINCE OF CHINA - - D8-B6-C1 (hex) NetworkAccountant, Inc. - D8B6C1 (base 16) NetworkAccountant, Inc. - 12101 Tukwila International Blvd. - Seattle Washington 98168 - UNITED STATES - - D8-B6-D6 (hex) Blu Tether Limited - D8B6D6 (base 16) Blu Tether Limited - 7600 Leesburg Pike - Suite 140 West - Falls Church VA 22043 - UNITED STATES - - D8-B8-F6 (hex) Nantworks - D8B8F6 (base 16) Nantworks - 12230 El Camino Real, Suite 400 - San Diego CA 92130 - UNITED STATES - - D8-B9-0E (hex) Triple Domain Vision Co.,Ltd. - D8B90E (base 16) Triple Domain Vision Co.,Ltd. - No.9, Aly. 1, Ln. 585, Sec.3, Fulin Rd., - Cyonglin Township - Hsinchu Conuty 307 - TAIWAN, PROVINCE OF CHINA - - D8-BB-2C (hex) Apple - D8BB2C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-BF-4C (hex) Victory Concept Electronics Limited - D8BF4C (base 16) Victory Concept Electronics Limited - 4/F., CAC Tower, - 165 Hoi Bun Road, - Kwun Tong Kowloon KLN - HONG KONG - - D8-C0-68 (hex) Netgenetech.co.,ltd. - D8C068 (base 16) Netgenetech.co.,ltd. - 704, Hanlim Venture Town., #689-6, - Geumjeong- dong, - Gunpo-si 435-862 - KOREA, REPUBLIC OF - - D8-C3-FB (hex) DETRACOM - D8C3FB (base 16) DETRACOM - 41 AVENUE DE L'EUROPE - ZONE EUROCENTRE OUEST - CASTELNAU D'ESTRETEFONDS 31620 - FRANCE - - D8-C6-91 (hex) Hichan Technology Corp. - D8C691 (base 16) Hichan Technology Corp. - 12F., No.2, Jian 8th Rd., Zhonghe Dist - New Taipei City 23511 - TAIWAN, PROVINCE OF CHINA - - D8-C7-C8 (hex) Aruba Networks - D8C7C8 (base 16) Aruba Networks - 1344 Crossman Ave. - Sunnyvale CA 94089 - UNITED STATES - - D8-C9-9D (hex) EA DISPLAY LIMITED - D8C99D (base 16) EA DISPLAY LIMITED - 22/F DELTA HOUSE 3 ON YIU ST - SHATIN NT - HONG KONG - - D8-CB-8A (hex) Micro-Star INTL CO., LTD. - D8CB8A (base 16) Micro-Star INTL CO., LTD. - No.69, Lide St., - Zhonghe Dist., - New Taipei City Taiwan 235 - TAIWAN, PROVINCE OF CHINA - - D8-CF-9C (hex) Apple - D8CF9C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-D1-CB (hex) Apple - D8D1CB (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - D8-D2-7C (hex) JEMA ENERGY, SA - D8D27C (base 16) JEMA ENERGY, SA - Pº Circuito nº10 - Lasarte-Oria Guipuzcoa 20160 - SPAIN - - D8-D3-85 (hex) Hewlett-Packard Company - D8D385 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - D8-D4-3C (hex) Sony Corporation - D8D43C (base 16) Sony Corporation - 1-7-1 Konan - Minato-ku - Tokyo 108-0075 - JAPAN - - D8-D5-B9 (hex) Rainforest Automation, Inc. - D8D5B9 (base 16) Rainforest Automation, Inc. - 34 West 7th Ave - Vancouver British Columbia V5Y 1L6 - CANADA - - D8-D6-7E (hex) GSK CNC EQUIPMENT CO.,LTD - D8D67E (base 16) GSK CNC EQUIPMENT CO.,LTD - NO.7,1st Street,Luochong North Road,Luochongwei - Guangzhou Guangdong 510165 - CHINA - - D8-DA-52 (hex) APATOR S.A. - D8DA52 (base 16) APATOR S.A. - ul Gdanska 4A lok. C4 - Torun Kujawsko-Pomorskie 87-100 - POLAND - - D8-DC-E9 (hex) Kunshan Erlab ductless filtration system Co.,Ltd - D8DCE9 (base 16) Kunshan Erlab ductless filtration system Co.,Ltd - NO.100 Liu Shi Jin Road - Kunshan development Zone Penglang-Jiangsu Province - Kunshan Jiangsu 215300 - CHINA - - D8-DD-5F (hex) BALMUDA Inc. - D8DD5F (base 16) BALMUDA Inc. - 5-1-21 Kyonancho - Musashino Tokyo 180-0023 - JAPAN - - D8-DD-FD (hex) Texas Instruments - D8DDFD (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - D8-DE-CE (hex) ISUNG CO.,LTD - D8DECE (base 16) ISUNG CO.,LTD - 92, Huimanggongwon-ro - 1704-3, Jeongwang-dong, Siheung-si, Kyunggido - Siheung-si Kyunggido 429-859 - KOREA, REPUBLIC OF - - D8-DF-0D (hex) beroNet GmbH - D8DF0D (base 16) beroNet GmbH - Friedrichstraße 231 - Berlin 10969 - GERMANY - - D8-E3-AE (hex) CIRTEC MEDICAL SYSTEMS - D8E3AE (base 16) CIRTEC MEDICAL SYSTEMS - 101B Cooper Court - Los Gatos CA 95032 - UNITED STATES - - D8-E5-6D (hex) TCT Mobile Limited - D8E56D (base 16) TCT Mobile Limited - No.86, Hechang 7th West Road, - Zhong Kai Hi-tech Development District - Hui Zhou Gang Dong 516006 - CHINA - - D8-E7-2B (hex) NetScout Systems, Inc. - D8E72B (base 16) NetScout Systems, Inc. - 2000 Lincoln Drive East - Marlton New Jersey 08053 - UNITED STATES - - D8-E7-43 (hex) Wush, Inc - D8E743 (base 16) Wush, Inc - 17F.No 268, Liancheng Rd., Zhonghe District - New Taipei City 235 - TAIWAN, PROVINCE OF CHINA - - D8-E9-52 (hex) KEOPSYS - D8E952 (base 16) KEOPSYS - 21 RUE LOUIS DE BROGLIE - LANNION BRITANY 22300 - FRANCE - - D8-EB-97 (hex) TRENDnet, Inc. - D8EB97 (base 16) TRENDnet, Inc. - 20675 Manhattan Place - Torrance CA 90501 - UNITED STATES - - D8-EE-78 (hex) Moog Protokraft - D8EE78 (base 16) Moog Protokraft - 4545 W Stone Dr Bldg 135 - Kingsport TN 37660 - UNITED STATES - - D8-F0-F2 (hex) Zeebo Inc - D8F0F2 (base 16) Zeebo Inc - 5405 Morehouse Drive - Suite #300 - San Diego California 92121 - UNITED STATES - - D8-F7-10 (hex) Libre Wireless Technologies Inc. - D8F710 (base 16) Libre Wireless Technologies Inc. - 5405 Alton Parkway - Suite A-563 - Irvine, CA CA 92604 - UNITED STATES - - D8-FB-11 (hex) AXACORE - D8FB11 (base 16) AXACORE - 2468 HISTORIC DECATUR RD - SAN DIEGO CA 92106 - UNITED STATES - - D8-FC-93 (hex) Intel Corporate - D8FC93 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - D8-FE-8F (hex) IDFone Co., Ltd. - D8FE8F (base 16) IDFone Co., Ltd. - 7F Ace techno tower 5th B/D, 197-22 - Guro-dong, Guro-gu Seoul 152-766 - KOREA, REPUBLIC OF - - D8-FE-E3 (hex) D-Link International - D8FEE3 (base 16) D-Link International - 1 International Business Park - #03-12,The Synergy - 609917 - SINGAPORE - - DC-02-65 (hex) Meditech Kft - DC0265 (base 16) Meditech Kft - Üllõi út 200. - Budapest 1191 - HUNGARY - - DC-02-8E (hex) zte corporation - DC028E (base 16) zte corporation - 12/F.,R&D building,kejinan Road - Shenzhen Guangdong 518057 - CHINA - - DC-05-2F (hex) National Products Inc. - DC052F (base 16) National Products Inc. - 8410 Dallas Ave S. - Seattle WA 98108 - UNITED STATES - - DC-05-75 (hex) SIEMENS ENERGY AUTOMATION - DC0575 (base 16) SIEMENS ENERGY AUTOMATION - GOA WORKS ,L-6 , - VERNA INDUSTRIAL ESTATE - VERNA GOA 403722 - INDIA - - DC-05-ED (hex) Nabtesco Corporation - DC05ED (base 16) Nabtesco Corporation - 9-18, Kaigan 1-chome - Minato-ku Tokyo 105-0022 - JAPAN - - DC-07-C1 (hex) HangZhou QiYang Technology Co.,Ltd. - DC07C1 (base 16) HangZhou QiYang Technology Co.,Ltd. - Floor 5, Building 2, Road XiYuanYi, WestLake Technology Park, - SanDun, XiHu Distribute - HangZhou ZheJiang 310028 - CHINA - - DC-09-14 (hex) Talk-A-Phone Co. - DC0914 (base 16) Talk-A-Phone Co. - 7530 N. Natchez Ave. - Niles IL 60714 - UNITED STATES - - DC-0B-1A (hex) ADB Broadband Italia - DC0B1A (base 16) ADB Broadband Italia - via Sarca 222 - Milano 20126 - ITALY - - DC-0E-A1 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD - DC0EA1 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD - No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone,, Jiangsu, - KUNSHAN SUZHOU 215300 - CHINA - - DC-15-DB (hex) Ge Ruili Intelligent Technology ( Beijing ) Co., Ltd. - DC15DB (base 16) Ge Ruili Intelligent Technology ( Beijing ) Co., Ltd. - Room 821, block E, No.6 Taiping Street, Xicheng District - Beijing 100005 - CHINA - - DC-16-A2 (hex) Medtronic Diabetes - DC16A2 (base 16) Medtronic Diabetes - 18000 Devonshire St - Northridge CA 91325 - UNITED STATES - - DC-17-5A (hex) Hitachi High-Technologies Corporation - DC175A (base 16) Hitachi High-Technologies Corporation - 794, Higashitoyoi, - Kudamatsu City, Yamaguchi Pref., 744-0002, - JAPAN - - DC-17-92 (hex) Captivate Network - DC1792 (base 16) Captivate Network - 2 Executive Drive Suite 301 - Chelmsford Massachusetts 01824 - UNITED STATES - - DC-1D-9F (hex) U & B tech - DC1D9F (base 16) U & B tech - 2F, Daeyoung buliding, 1423-6, Kwanyang-1Dong, - DongAn-Gu, - Anyang-Si Gyeonggi-Do 431-061 - KOREA, REPUBLIC OF - - DC-1D-D4 (hex) Microstep-MIS spol. s r.o. - DC1DD4 (base 16) Microstep-MIS spol. s r.o. - Cavojskeho 1 - Bratislava 84104 - SLOVAKIA - - DC-1E-A3 (hex) Accensus LLC - DC1EA3 (base 16) Accensus LLC - 200 South Wacker Drive - Suite 3100 - Chicago IL 60606 - UNITED STATES - - DC-20-08 (hex) ASD Electronics Ltd - DC2008 (base 16) ASD Electronics Ltd - DEDE INDUSTRIAL PARK,JIAN'AN ROAD,HIGH-TECH - INDUSTRIAL PARK,FUYONG TOWN,BAO'AN DISTRICT, - Shenzhen Guang Dong 518103 - CHINA - - DC-2A-14 (hex) Shanghai Longjing Technology Co. - DC2A14 (base 16) Shanghai Longjing Technology Co. - 689 Chundong Road, Minhang District - Shanghai 201108 - CHINA - - DC-2B-61 (hex) Apple - DC2B61 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - DC-2B-66 (hex) InfoBLOCK S.A. de C.V. - DC2B66 (base 16) InfoBLOCK S.A. de C.V. - Hegel 229 - 10 - Chapultepec Morales - Mexico City Distrito Federal 11570 - MEXICO - - DC-2B-CA (hex) Zera GmbH - DC2BCA (base 16) Zera GmbH - Hauptstrasse 392 - Koenigswinter NRW 53639 - GERMANY - - DC-2C-26 (hex) Iton Technology Limited - DC2C26 (base 16) Iton Technology Limited - Room 10E, JingFeng Building, - Binhe Road, Futian District - ShenZhen GuangDong 518034 - CHINA - - DC-2E-6A (hex) HCT. Co., Ltd. - DC2E6A (base 16) HCT. Co., Ltd. - 105-1, Jangam-ri, Majang-myen - Icheon-si Gyeonggi-do 467-811 - KOREA, REPUBLIC OF - - DC-2F-03 (hex) Step forward Group Co., Ltd. - DC2F03 (base 16) Step forward Group Co., Ltd. - 1/3 Park Village Rama2 Floor 2 C2-2 - Soi Rama 2, Soi 56, Samaedum, Bangkhunthain, - Bangkok Bangkok 10150 - THAILAND - - DC-30-9C (hex) Heyrex Limited - DC309C (base 16) Heyrex Limited - Level 1, 236-256 Karori Road - Karori - Wellington 6147 - NEW ZEALAND - - DC-33-50 (hex) TechSAT GmbH - DC3350 (base 16) TechSAT GmbH - Gruber Str. 46c - Poing BY 85586 - GERMANY - - DC-37-14 (hex) Apple, Inc. - DC3714 (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - DC-37-D2 (hex) Hunan HKT Electronic Technology Co., Ltd - DC37D2 (base 16) Hunan HKT Electronic Technology Co., Ltd - Room 428,4F,Hunan Environmental Science and Technology Committee Building,No 18 South of Wanjiali Road,Yuhua District,Changsha - Changsha Hunan 410007 - CHINA - - DC-38-E1 (hex) Juniper networks - DC38E1 (base 16) Juniper networks - 1194 N. Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - DC-39-79 (hex) Skyport Systems - DC3979 (base 16) Skyport Systems - 280 Hope Street - Mountain View CA 94041 - UNITED STATES - - DC-3A-5E (hex) Roku, Inc - DC3A5E (base 16) Roku, Inc - 12980 Saratoga Ave. - Suite D - Saratoga CA 95070 - UNITED STATES - - DC-3C-2E (hex) Manufacturing System Insights, Inc. - DC3C2E (base 16) Manufacturing System Insights, Inc. - 2550 Ninth St. - Suite 204B - Berkely CA 94710 - UNITED STATES - - DC-3C-84 (hex) Ticom Geomatics, Inc. - DC3C84 (base 16) Ticom Geomatics, Inc. - 9130 Jollyville Rd. Ste. 300 - Austin Texas 78759 - UNITED STATES - - DC-3E-51 (hex) Solberg & Andersen AS - DC3E51 (base 16) Solberg & Andersen AS - Litleaasvegen 61 - N-5132 Nyborg - Bergen 5132 - NORWAY - - DC-3E-F8 (hex) Nokia Corporation - DC3EF8 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - DC-45-17 (hex) ARRIS Group, Inc. - DC4517 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - DC-49-C9 (hex) CASCO SIGNAL LTD - DC49C9 (base 16) CASCO SIGNAL LTD - No.489 Xizang Bei Road - Shanghai 200071 - CHINA - - DC-4E-DE (hex) SHINYEI TECHNOLOGY CO., LTD. - DC4EDE (base 16) SHINYEI TECHNOLOGY CO., LTD. - 6-5-2, MINATOJIMA-MINAMIMACHI, CHUO-KU - KOBE HYOGO 650-0047 - JAPAN - - DC-53-7C (hex) Compal Broadband Networks, Inc. - DC537C (base 16) Compal Broadband Networks, Inc. - 13F., No.1, Taiyuan 1st St. - Zhubei City Hsinchu County 30265 - TAIWAN, PROVINCE OF CHINA - - DC-56-E6 (hex) Shenzhen Bococom Technology Co.,LTD - DC56E6 (base 16) Shenzhen Bococom Technology Co.,LTD - 303, Dongjiang Environmental Build, LangShan Road. - Shenzhen Guangdong 518000 - CHINA - - DC-57-26 (hex) Power-One - DC5726 (base 16) Power-One - Via San Girgio 642 - Terranuova Arezzo 52028 - ITALY - - DC-5E-36 (hex) Paterson Technology - DC5E36 (base 16) Paterson Technology - 23490 SE 51st Pl - Issaquah WA 98029 - UNITED STATES - - DC-60-A1 (hex) Teledyne DALSA Professional Imaging - DC60A1 (base 16) Teledyne DALSA Professional Imaging - High Tech Campus 27 - Eindhoven NB 5656 AE - NETHERLANDS - - DC-64-7C (hex) C.R.S. iiMotion GmbH - DC647C (base 16) C.R.S. iiMotion GmbH - Hermann-Schwer-Str. 3 - Building C - Villingen-Schwenningen 78048 - GERMANY - - DC-66-3A (hex) Apacer Technology Inc. - DC663A (base 16) Apacer Technology Inc. - 1F., No.32, Zhongcheng Rd., Tucheng Dist., - New Taipei City Taiwan R.O.C. 236 - TAIWAN, PROVINCE OF CHINA - - DC-6F-00 (hex) Livescribe, Inc. - DC6F00 (base 16) Livescribe, Inc. - 7677 Oakport Street, 12th floor - Oakland California 94621 - UNITED STATES - - DC-6F-08 (hex) Bay Storage Technology - DC6F08 (base 16) Bay Storage Technology - 6200 Stoneridge Mall Road - Suite 300 - Pleasanton CA 94588 - UNITED STATES - - DC-70-14 (hex) PRIVATE - DC7014 (base 16) - - DC-71-44 (hex) Samsung Electro Mechanics - DC7144 (base 16) Samsung Electro Mechanics - 314, Maetan3-Dong, Yeongtong-Gu - Suwon Gyeunggi-Do 443-743 - KOREA, REPUBLIC OF - - DC-7B-94 (hex) CISCO SYSTEMS, INC. - DC7B94 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - DC-82-5B (hex) JANUS, spol. s r.o. - DC825B (base 16) JANUS, spol. s r.o. - Sarajevska 8 - Prague Czech Republic 12000 - CZECH REPUBLIC - - DC-85-DE (hex) Azurewave Technologies., inc. - DC85DE (base 16) Azurewave Technologies., inc. - 8F ., No.94, Baozhong RD, Sindian, - New Taipei City 231 - TAIWAN, PROVINCE OF CHINA - - DC-86-D8 (hex) Apple, Inc - DC86D8 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - DC-9B-1E (hex) Intercom, Inc. - DC9B1E (base 16) Intercom, Inc. - Sorimachi Bldg., 3-5, Taito 1-chome, - Taito-ku Tokyo 110-8654 - JAPAN - - DC-9B-9C (hex) Apple - DC9B9C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - DC-9C-52 (hex) Sapphire Technology Limited. - DC9C52 (base 16) Sapphire Technology Limited. - Unit 1909-1919, 19/F., Tower 2, Grand Central Plaza, - 138 Shatin Rural Committee Road, Shatin, N.T., - HONG KONG - - DC-9F-A4 (hex) Nokia Corporation - DC9FA4 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - DC-9F-DB (hex) Ubiquiti Networks, Inc. - DC9FDB (base 16) Ubiquiti Networks, Inc. - 91 E Tasman Drive - San Jose California 95134 - UNITED STATES - - DC-A5-F4 (hex) Cisco - DCA5F4 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - DC-A6-BD (hex) Beijing Lanbo Technology Co., Ltd. - DCA6BD (base 16) Beijing Lanbo Technology Co., Ltd. - Room.301.Bidg.4NO.8 Shangdi West Road, Haidian District, - Beijing City 100085 - CHINA - - DC-A7-D9 (hex) Compressor Controls Corp - DCA7D9 (base 16) Compressor Controls Corp - 4725 121st Street - Des Moines Iowa 50323 - UNITED STATES - - DC-A8-CF (hex) New Spin Golf, LLC. - DCA8CF (base 16) New Spin Golf, LLC. - 1637 Burr Oak Drive - Libertyville IL 60048 - UNITED STATES - - DC-A9-71 (hex) Intel Corporate - DCA971 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - DC-A9-89 (hex) MACANDC - DCA989 (base 16) MACANDC - 2-nd Filevskaya str.7/6 - Moscow 121096 - RUSSIAN FEDERATION - - DC-AD-9E (hex) GreenPriz - DCAD9E (base 16) GreenPriz - 549, boulevard Pierre Sauvaigo - GreenTech Bât.1 - La Colle sur Loup 06480 - FRANCE - - DC-AE-04 (hex) CELOXICA Ltd - DCAE04 (base 16) CELOXICA Ltd - 34 Porchester Road - London W2 6ES - UNITED KINGDOM - - DC-B0-58 (hex) Burkert Werke GmbH - DCB058 (base 16) Burkert Werke GmbH - Christian-Burkert-Straße 13-17 - Ingelfingen Baden-Württemberg 74653 - GERMANY - - DC-B4-C4 (hex) Microsoft XCG - DCB4C4 (base 16) Microsoft XCG - 1 Microsoft Way - Redmond WA 98052 - UNITED STATES - - DC-BF-90 (hex) HUIZHOU QIAOXING TELECOMMUNICATION INDUSTRY CO.,LTD. - DCBF90 (base 16) HUIZHOU QIAOXING TELECOMMUNICATION INDUSTRY CO.,LTD. - Qiaoxing Science Technological&Industrial Zone Tangquan - Huizhou Guangdong 516023 - CHINA - - DC-C0-DB (hex) Shenzhen Kaiboer Technology Co., Ltd. - DCC0DB (base 16) Shenzhen Kaiboer Technology Co., Ltd. - 4/F, No. 11 Bldg., Yusheng Industrial Park, No. 467, Xixiang Sec., - 107 National Road, Xixing St., Bao'an District, - Shenzhen Guangdong 518126 - CHINA - - DC-C1-01 (hex) SOLiD Technologies, Inc. - DCC101 (base 16) SOLiD Technologies, Inc. - 9th Floor, SOLiD Space, Pangyoyeok-ro 220 - Bundang-gu - Seongnam-si Gyeonggi-do 463-400 - KOREA, REPUBLIC OF - - DC-C4-22 (hex) Systembase Limited - DCC422 (base 16) Systembase Limited - Jupes Field House, Pettridge Lane - Mere - Warminster Wiltshire BA12 6DG - UNITED KINGDOM - - DC-C6-22 (hex) BUHEUNG SYSTEM - DCC622 (base 16) BUHEUNG SYSTEM - 302, 45, Jeonpa-ro, 24 Beongil - Manan-gu - Anyang-si Gyeonggi-do 430-857 - KOREA, REPUBLIC OF - - DC-C7-93 (hex) Nokia Corporation - DCC793 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - DC-CB-A8 (hex) Explora Technologies Inc - DCCBA8 (base 16) Explora Technologies Inc - 360, Franquet Street - Suite 20 - Quebec G1P 4N3 - CANADA - - DC-CE-41 (hex) FE GLOBAL HONG KONG LIMITED - DCCE41 (base 16) FE GLOBAL HONG KONG LIMITED - FLAT 204-205 2/F LAFORD CENTRE838 LAI CHI KOK RD CHEUNG SHA WAN KL - SHENZHEN 518057 - CHINA - - DC-CE-BC (hex) Shenzhen JSR Technology Co.,Ltd. - DCCEBC (base 16) Shenzhen JSR Technology Co.,Ltd. - 2-3F,E building,Yu Jianfeng science and industry park - ,Huafan road,Tongheng community,Dalang,Baoan district, - Shenzhen City Guangdong 518109 - CHINA - - DC-CF-94 (hex) Beijing Rongcheng Hutong Technology Co., Ltd. - DCCF94 (base 16) Beijing Rongcheng Hutong Technology Co., Ltd. - Room 401A,Building No.4,Yard No.5, - Yongfeng Road, Haidian District - Beijing 100024 - CHINA - - DC-D0-F7 (hex) Bentek Systems Ltd. - DCD0F7 (base 16) Bentek Systems Ltd. - 315 - 3750 46th Ave. SE - Calgary AB T2B 0L1 - CANADA - - DC-D2-FC (hex) HUAWEI TECHNOLOGIES CO.,LTD - DCD2FC (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - DC-D3-21 (hex) HUMAX co.,tld - DCD321 (base 16) HUMAX co.,tld - HUMAX Village, 11-4, Sunae-dong, Bundang-gu - Seongnam-si Gyeonggi-do 463-825 - KOREA, REPUBLIC OF - - DC-D5-2A (hex) Sunny Heart Limited - DCD52A (base 16) Sunny Heart Limited - Rm. 1516, 15/F, Hewlett Center - 54 Hoi Yuen Road, - Kwun Tong Kowloon 852 - HONG KONG - - DC-D8-7F (hex) Shenzhen JoinCyber Telecom Equipment Ltd - DCD87F (base 16) Shenzhen JoinCyber Telecom Equipment Ltd - 19CDE, Block A,JinFengBuilding,shangbu South Road,Futian District, - Shenzhen Guangdong 518031 - CHINA - - DC-DA-4F (hex) GETCK TECHNOLOGY, INC - DCDA4F (base 16) GETCK TECHNOLOGY, INC - Room 508, NO .48 ZhengYi road - YangPu District - SHANGHAI 200082 - CHINA - - DC-DB-70 (hex) Tonfunk Systementwicklung und Service GmbH - DCDB70 (base 16) Tonfunk Systementwicklung und Service GmbH - Anger20 - Falkenstein / Harz OT Ermsleben Sachsen-Anhalt 06463 - GERMANY - - DC-DE-CA (hex) Akyllor - DCDECA (base 16) Akyllor - Britannia House, 22, 2F, Cator Road - Bandar Seri Begawan BS 8811 - BRUNEI DARUSSALAM - - DC-E0-26 (hex) Patrol Tag, Inc - DCE026 (base 16) Patrol Tag, Inc - 2800 Western Ave - Suite 212 - Seattle WA 98121 - UNITED STATES - - DC-E1-AD (hex) Shenzhen Wintop Photoelectric Technology Co., Ltd - DCE1AD (base 16) Shenzhen Wintop Photoelectric Technology Co., Ltd - 6th Floor, 1st Building, Zone 3, South Area, Zhongguan& Honghualing Industrial Zone, No. 1213, Liuxian Avenue, Taoyuan Street, Nanshan District, Shenzhen, China - Shenzhen Guangdong 518054 - CHINA - - DC-E2-AC (hex) Lumens Digital Optics Inc. - DCE2AC (base 16) Lumens Digital Optics Inc. - 5F, No.35, Sintai Rd., Jhubei City - Jhubei HsinChu 302 - TAIWAN, PROVINCE OF CHINA - - DC-E5-78 (hex) Experimental Factory of Scientific Engineering and Special Design Department - DCE578 (base 16) Experimental Factory of Scientific Engineering and Special Design Department - 9, Academician Semenov prospect - Chernogolovka Moscow region 142432 - RUSSIAN FEDERATION - - DC-E7-1C (hex) AUG Elektronik GmbH - DCE71C (base 16) AUG Elektronik GmbH - Kleinwoellmiss 53 - St. Martin a. W. Styria A-8580 - AUSTRIA - - DC-EC-06 (hex) Heimi Network Technology Co., Ltd. - DCEC06 (base 16) Heimi Network Technology Co., Ltd. - Room 12B12, Block A2, Long-Term World Building, - No. 18 Suzhou Street, Haidian district - Beijing Beijing 100080 - CHINA - - DC-F0-5D (hex) Letta Teknoloji - DCF05D (base 16) Letta Teknoloji - TUBITAK Teknoloji Gelistirme Bolgesi - C Blok No:26 GEBZE - KOCAELI 41455 - TURKEY - - DC-F1-10 (hex) Nokia Corporation - DCF110 (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - DC-F7-55 (hex) SITRONIK - DCF755 (base 16) SITRONIK - 22 MARISCHAL GARDENS - BUCKSBURN - ABERDEEN ABERDEENSHIRE AB21 9BY - UNITED KINGDOM - - DC-F8-58 (hex) Lorent Networks, Inc. - DCF858 (base 16) Lorent Networks, Inc. - Third Floor, Technology Complex, HAO Science Park - 17 Shenhai Rd., Nanhai District - Foshan Guangdong Province 528200 - CHINA - - DC-FA-D5 (hex) STRONG Ges.m.b.H. - DCFAD5 (base 16) STRONG Ges.m.b.H. - Franz-Josefs-Kai 1 - Vienna 1010 - AUSTRIA - - DC-FB-02 (hex) Buffalo Inc. - DCFB02 (base 16) Buffalo Inc. - Akamon-dori Bldg, 30-20, Ohsu 3-chome - Naka-ku, Nagoya Aichi Pref. 460-8315 - JAPAN - - E0-03-70 (hex) ShenZhen Continental Wireless Technology Co., Ltd. - E00370 (base 16) ShenZhen Continental Wireless Technology Co., Ltd. - North 23F, Dongfang Technology Building, - Keyuan Middle Road, Nanshan Science Park - Shenzhen Guangdong 518057 - CHINA - - E0-05-C5 (hex) TP-LINK Technologies Co.,Ltd. - E005C5 (base 16) TP-LINK Technologies Co.,Ltd. - Building 7, Second Part, Honghualing Industrial Zone - Xili town, Nanshan, - Shenzhen Guangdong 518000 - CHINA - - E0-06-E6 (hex) Hon Hai Precision Ind. Co.,Ltd. - E006E6 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road , - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - E0-0B-28 (hex) Inovonics - E00B28 (base 16) Inovonics - 315 CTC Blvd - Louisville CO 80027 - UNITED STATES - - E0-0C-7F (hex) Nintendo Co., Ltd. - E00C7F (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - E0-0D-B9 (hex) PRIVATE - E00DB9 (base 16) - - E0-10-7F (hex) Ruckus Wireless - E0107F (base 16) Ruckus Wireless - 350 W Java Drive - Sunnyvale CA 94089 - UNITED STATES - - E0-14-3E (hex) Modoosis Inc. - E0143E (base 16) Modoosis Inc. - #302, Samil Bldg., 656-282 - Seongsoo-dong 1 ga, Seongdong-gu - Seoul 133-110 - KOREA, REPUBLIC OF - - E0-18-77 (hex) Fujitsu Limited - E01877 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa - JAPAN - - E0-19-1D (hex) Huawei Technologies Co., Ltd - E0191D (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - E0-1C-41 (hex) Aerohive Networks Inc. - E01C41 (base 16) Aerohive Networks Inc. - 330 Gibraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - E0-1C-EE (hex) Bravo Tech, Inc. - E01CEE (base 16) Bravo Tech, Inc. - 6185 Phyllis Dr. Unit D. - Cypress CA 90630 - UNITED STATES - - E0-1D-38 (hex) Beijing HuaqinWorld Technology Co.,Ltd - E01D38 (base 16) Beijing HuaqinWorld Technology Co.,Ltd - 30F,Beijing Silver Tower - No.2 North Road,Dong San Huan - Chao Yang Dist Beijing 100027 - CHINA - - E0-1D-3B (hex) Cambridge Industries(Group) Co.,Ltd - E01D3B (base 16) Cambridge Industries(Group) Co.,Ltd - 22 Floor, Qilai Tower, #889 Yishan Road - Shanghai 200233 - CHINA - - E0-1E-07 (hex) Anite Telecoms US. Inc - E01E07 (base 16) Anite Telecoms US. Inc - 106 Vista Centre Dr - Forest VA 24551 - UNITED STATES - - E0-1F-0A (hex) Xslent Energy Technologies. LLC - E01F0A (base 16) Xslent Energy Technologies. LLC - 7428 Redwood Blvd - Suite 102 - Novato CA 94945 - UNITED STATES - - E0-24-7F (hex) HUAWEI TECHNOLOGIES CO.,LTD - E0247F (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - E0-25-38 (hex) Titan Pet Products - E02538 (base 16) Titan Pet Products - 6521 Creedmoor Rd. Suite 101 - Raleigh NC 27613 - UNITED STATES - - E0-26-30 (hex) Intrigue Technologies, Inc. - E02630 (base 16) Intrigue Technologies, Inc. - 800 Old Pond Road - #705 - Bridgeville PA 15017 - UNITED STATES - - E0-26-36 (hex) Nortel Networks - E02636 (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - E0-27-1A (hex) TTC Next-generation Home Network System WG - E0271A (base 16) TTC Next-generation Home Network System WG - 1-1-12 Shiba Kouen - Minato-ku Tokyo 105-0011 - JAPAN - - E0-2A-82 (hex) Universal Global Scientific Industrial Co., Ltd. - E02A82 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, LANE 351, SEC.1, TAIPING RD. - TSAOTUEN - NANTOU 54261 - TAIWAN, PROVINCE OF CHINA - - E0-2C-B2 (hex) Lenovo Mobile Communication (Wuhan) Company Limited - E02CB2 (base 16) Lenovo Mobile Communication (Wuhan) Company Limited - No.19, Gaoxin 4th Road - Wuhan East Lake High-tech Zone - Wuhan Hubei 430205 - CHINA - - E0-2F-6D (hex) Cisco - E02F6D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E0-30-05 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd - E03005 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd - Pudong Jinqiao - Shanghai 201206 - CHINA - - E0-31-D0 (hex) SZ Telstar CO., LTD - E031D0 (base 16) SZ Telstar CO., LTD - Telstar Technology Park No.12&14, Longtong Industrial Zone - Ailian, Longgang District - Shenzhen Guangdong 518172 - CHINA - - E0-35-60 (hex) Challenger Supply Holdings, LLC - E03560 (base 16) Challenger Supply Holdings, LLC - 4500 Mercantile Plaza Dr. - Suite 300 - Fort Worth TX 76137 - UNITED STATES - - E0-36-E3 (hex) Stage One International Co., Ltd. - E036E3 (base 16) Stage One International Co., Ltd. - Fl. 5., No. 10., Lane 321, Yangguang St., - Neihu Dist. - Taipei City 11491 - TAIWAN, PROVINCE OF CHINA - - E0-39-D7 (hex) Plexxi, Inc. - E039D7 (base 16) Plexxi, Inc. - 100 Innovative Way Suite 3322 - Suite 3322 - Nashua NH 03062 - UNITED STATES - - E0-3C-5B (hex) SHENZHEN JIAXINJIE ELECTRON CO.,LTD - E03C5B (base 16) SHENZHEN JIAXINJIE ELECTRON CO.,LTD - Shenzhen Jiaxinjie Security Industrial park,No 6 Xin He Xin xing Industrial Park, Fuyong Town,Bao'an District - SHENZHEN GUANGDONG 518103 - CHINA - - E0-3E-44 (hex) Broadcom Corporation - E03E44 (base 16) Broadcom Corporation - 190 Mathilda Place - Sunnyvale CA 94086 - UNITED STATES - - E0-3E-4A (hex) Cavanagh Group International - E03E4A (base 16) Cavanagh Group International - 9180 Four Mile Creek Rd. - Gainesville GA 30506 - UNITED STATES - - E0-3E-7D (hex) data-complex GmbH - E03E7D (base 16) data-complex GmbH - Düsterngraben 7 - Halberstadt Sachsen-Anhalt 38820 - GERMANY - - E0-3F-49 (hex) ASUSTek COMPUTER INC. - E03F49 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - E0-46-9A (hex) NETGEAR - E0469A (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - E0-4B-45 (hex) Hi-P Electronics Pte Ltd - E04B45 (base 16) Hi-P Electronics Pte Ltd - 12 Ang Mo Kio Street 64 - #03-02, UE BizHub Central (Blk A) - Singapore Singapore 569088 - SINGAPORE - - E0-55-97 (hex) Emergent Vision Technologies Inc. - E05597 (base 16) Emergent Vision Technologies Inc. - SUITE# 239 - 552A CLARKE ROAD - COQUITLAM British Columbia V3J 0A3 - CANADA - - E0-56-F4 (hex) AxesNetwork Solutions inc. - E056F4 (base 16) AxesNetwork Solutions inc. - 410 pepin - Sherbrooke qc j1l2y8 - CANADA - - E0-58-9E (hex) Laerdal Medical - E0589E (base 16) Laerdal Medical - Tanke Svilandsgate 30 - Stavanger 4002 - NORWAY - - E0-5B-70 (hex) Innovid, Co., Ltd. - E05B70 (base 16) Innovid, Co., Ltd. - 5th Floor, Boga Building, 821-3, Bangbaedong, Seochogu - Seoul 137-060 - KOREA, REPUBLIC OF - - E0-5D-A6 (hex) Detlef Fink Elektronik & Softwareentwicklung - E05DA6 (base 16) Detlef Fink Elektronik & Softwareentwicklung - Brühlstraße 13 - Mössingen 72116 - GERMANY - - E0-5F-B9 (hex) CISCO SYSTEMS, INC. - E05FB9 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - E0-61-B2 (hex) HANGZHOU ZENOINTEL TECHNOLOGY CO., LTD - E061B2 (base 16) HANGZHOU ZENOINTEL TECHNOLOGY CO., LTD - Room 806, F#, Cambridge Combridge, Shenhua Road,District Xihu, - Hangzhou Zhejiang 310030 - CHINA - - E0-62-90 (hex) Jinan Jovision Science & Technology Co., Ltd. - E06290 (base 16) Jinan Jovision Science & Technology Co., Ltd. - Room 407, Tower C, Cyber Port Building, - 47 Shanda Rd - Jinan Shandong 250013 - CHINA - - E0-63-E5 (hex) Sony Mobile Communications AB - E063E5 (base 16) Sony Mobile Communications AB - Nya Vattentornet - Lund SE 22188 - SWEDEN - - E0-64-BB (hex) DigiView S.r.l. - E064BB (base 16) DigiView S.r.l. - Via Senigallia 18/2 - Milano 20161 - ITALY - - E0-66-78 (hex) Apple - E06678 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E0-67-B3 (hex) C-Data Technology Co., Ltd - E067B3 (base 16) C-Data Technology Co., Ltd - Floor 6th, Bldg 4th,South 2 of Honghualing Industrial Zone,Xili Rd, - Nanshan Dist - Shenzhen Guangdong 518055 - CHINA - - E0-69-95 (hex) PEGATRON CORPORATION - E06995 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - E0-75-0A (hex) ALPS ERECTORIC CO.,LTD. - E0750A (base 16) ALPS ERECTORIC CO.,LTD. - 6-1 - nishida - kakuda-City MIYAGI-Pref 981-1595 - JAPAN - - E0-75-7D (hex) Motorola Mobility LLC - E0757D (base 16) Motorola Mobility LLC - 600 North US Highway 45 - Libertyville IL 60048 - UNITED STATES - - E0-76-D0 (hex) AMPAK Technology, Inc. - E076D0 (base 16) AMPAK Technology, Inc. - No.1,Jen Ai Road - Hsinchu Industrial Park,Hukou - Hsinchu Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - E0-7C-62 (hex) Whistle Labs, Inc. - E07C62 (base 16) Whistle Labs, Inc. - 251 Rhode Island Street, Suite 211 - San Francisco CA 94013 - UNITED STATES - - E0-7F-53 (hex) TECHBOARD SRL - E07F53 (base 16) TECHBOARD SRL - Via Della Scienza, 50 - Modena 41122 - ITALY - - E0-7F-88 (hex) EVIDENCE Network SIA - E07F88 (base 16) EVIDENCE Network SIA - Zilupes 4A - RiÌ„ga LV-1019 - LATVIA - - E0-81-77 (hex) GreenBytes, Inc. - E08177 (base 16) GreenBytes, Inc. - 15 Gray Lane, Suite 301 - Ashaway RI 02804 - UNITED STATES - - E0-87-B1 (hex) Nata-Info Ltd. - E087B1 (base 16) Nata-Info Ltd. - 28, Prokhorova str. - Yoshkar-Ola Republic Mari-El 424007 - RUSSIAN FEDERATION - - E0-88-5D (hex) Technicolor CH USA Inc - E0885D (base 16) Technicolor CH USA Inc - 101 West 103rd St - INH 720 - Indianapolis IN 46290 - UNITED STATES - - E0-89-9D (hex) Cisco - E0899D (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E0-8A-7E (hex) Exponent - E08A7E (base 16) Exponent - 149 Commonwealth Drive - Menlo Park CA 94025 - UNITED STATES - - E0-8E-3C (hex) Aztech Electronics Pte Ltd - E08E3C (base 16) Aztech Electronics Pte Ltd - 31, Ubi Road 1 - Aztech Building - 408694 - SINGAPORE - - E0-8F-EC (hex) REPOTEC CO., LTD. - E08FEC (base 16) REPOTEC CO., LTD. - 3F, 258. - LIAN CHEN RD. - CHUNG HO CITY, TAIPEI COUNTY 235 - TAIWAN, PROVINCE OF CHINA - - E0-91-53 (hex) XAVi Technologies Corp. - E09153 (base 16) XAVi Technologies Corp. - 9F, No. 129, Hsing Te Rd, Sanchung City - Taipei 241 - TAIWAN, PROVINCE OF CHINA - - E0-91-F5 (hex) NETGEAR - E091F5 (base 16) NETGEAR - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - E0-94-67 (hex) Intel Corporate - E09467 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - E0-95-79 (hex) ORTHOsoft inc, d/b/a Zimmer CAS - E09579 (base 16) ORTHOsoft inc, d/b/a Zimmer CAS - 75 Queen Street, Suite 3300 - Montreal Quebec H3C 2N6 - CANADA - - E0-97-96 (hex) HUAWEI TECHNOLOGIES CO.,LTD - E09796 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - Shenzhen Guangdong 518129 - CHINA - - E0-97-F2 (hex) Atomax Inc. - E097F2 (base 16) Atomax Inc. - 8F-1, No.300, Sec.1, Nei-hu Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - E0-99-71 (hex) Samsung Electronics Co.,Ltd - E09971 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E0-9D-31 (hex) Intel Corporate - E09D31 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - E0-9D-B8 (hex) PLANEX COMMUNICATIONS INC. - E09DB8 (base 16) PLANEX COMMUNICATIONS INC. - Planex Volta Bldg., 2-11-9 Ebisu-Nishi,Shibuya-ku, - Tokyo 1500021 - JAPAN - - E0-A1-98 (hex) NOJA Power Switchgear Pty Ltd - E0A198 (base 16) NOJA Power Switchgear Pty Ltd - 16 Archimedes Place - Murarrie QLD 4172 - AUSTRALIA - - E0-A1-D7 (hex) SFR - E0A1D7 (base 16) SFR - 40/42 Quai du point du jour - Boulogne Billancourt Hauts de Seine 92659 - FRANCE - - E0-A3-0F (hex) Pevco - E0A30F (base 16) Pevco - 1401 Tangier Drive - Baltimore MD 21220 - UNITED STATES - - E0-A6-70 (hex) Nokia Corporation - E0A670 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu 90590 - FINLAND - - E0-AA-B0 (hex) GENERAL VISION ELECTRONICS CO. LTD. - E0AAB0 (base 16) GENERAL VISION ELECTRONICS CO. LTD. - ROOM 528 5 Floor , MINLE BUILDING 117-13 , OLD MINLE Village ,MINZI STREET , LONGHUA NEW ZONE - BAOAN District - Shenzhen Guangdong 518040 - CHINA - - E0-AB-FE (hex) Orb Networks, Inc. - E0ABFE (base 16) Orb Networks, Inc. - 428 13th Street - 3rd Floor - Oakland CA 94612 - UNITED STATES - - E0-AC-F1 (hex) Cisco - E0ACF1 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E0-AE-5E (hex) ALPS Co,. Ltd. - E0AE5E (base 16) ALPS Co,. Ltd. - 6-3-36 Furukawanakazato, - Osaki Miyagi-pref 989-6181 - JAPAN - - E0-AE-B2 (hex) Bender GmbH & Co.KG - E0AEB2 (base 16) Bender GmbH & Co.KG - Londorfer Straße 65 - Grünberg Hessen 35305 - GERMANY - - E0-AE-ED (hex) LOENK - E0AEED (base 16) LOENK - F9, Cheongdam Venture Plaza - 41, Cheongdam-dong, Gangnam-gu - SEOUL 135-951 - KOREA, REPUBLIC OF - - E0-AF-4B (hex) Pluribus Networks, Inc. - E0AF4B (base 16) Pluribus Networks, Inc. - 1808 Embarcadero Rd, Suite B - Palo Alto CA 94303 - UNITED STATES - - E0-B2-F1 (hex) FN-LINK TECHNOLOGY LIMITED - E0B2F1 (base 16) FN-LINK TECHNOLOGY LIMITED - 5th Floor, A Building, Haoye Logistics Park, - Shugang Channel, Bao'an District, - SHENZHEN GUANGDONG 518126 - CHINA - - E0-B5-2D (hex) Apple - E0B52D (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E0-B7-0A (hex) ARRIS Group, Inc. - E0B70A (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - E0-B7-B1 (hex) Pace plc - E0B7B1 (base 16) Pace plc - Victoria Road - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - E0-B9-A5 (hex) Azurewave - E0B9A5 (base 16) Azurewave - 8F., Baozhong Rd. - Xindian City Taipei County 231 - TAIWAN, PROVINCE OF CHINA - - E0-B9-BA (hex) Apple - E0B9BA (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E0-BC-43 (hex) C2 Microsystems, Inc. - E0BC43 (base 16) C2 Microsystems, Inc. - 2833 Junction Avenue - Suite 101 - San Jose California 95134 - UNITED STATES - - E0-C2-86 (hex) Aisai Communication Technology Co., Ltd. - E0C286 (base 16) Aisai Communication Technology Co., Ltd. - Room 2610 Asia Trade Centre, - 79 Li Muk Road, - Kwai Chung N.T. 852 - HONG KONG - - E0-C2-B7 (hex) Masimo Corporation - E0C2B7 (base 16) Masimo Corporation - 40 Parker - Irvine CA 92618 - UNITED STATES - - E0-C3-F3 (hex) ZTE Corporation - E0C3F3 (base 16) ZTE Corporation - 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - E0-C6-B3 (hex) MilDef AB - E0C6B3 (base 16) MilDef AB - Box 22079 - Helsingborg Skane 25022 - SWEDEN - - E0-C7-9D (hex) Texas Instruments - E0C79D (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - E0-C8-6A (hex) SHENZHEN TW-SCIE Co., Ltd - E0C86A (base 16) SHENZHEN TW-SCIE Co., Ltd - 816# DongMing Building MinKang Road - MinZhi LongHua New District - Shenzhen Guangdong 518000 - CHINA - - E0-C9-22 (hex) Jireh Energy Tech., Ltd. - E0C922 (base 16) Jireh Energy Tech., Ltd. - #606 Seoul Forest Hallasigmavalley, 325-2 - Seongsu-dong 2(i)-ga, - Seoul Seongdong-Gu 133-120 - KOREA, REPUBLIC OF - - E0-C9-7A (hex) Apple - E0C97A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E0-CA-4D (hex) Shenzhen Unistar Communication Co.,LTD - E0CA4D (base 16) Shenzhen Unistar Communication Co.,LTD - 9/F,Qinghai Building,7043, Berhuan Road, Futian District, - Shenzhen Guangdong 518034 - CHINA - - E0-CA-94 (hex) Askey Computer - E0CA94 (base 16) Askey Computer - 10F,NO.119,CHIENKANG RD,CHUNG-HO CITY, - TAIPEI COUNTY 23585 - TAIWAN, PROVINCE OF CHINA - - E0-CB-1D (hex) PRIVATE - E0CB1D (base 16) - - E0-CB-4E (hex) ASUSTek COMPUTER INC. - E0CB4E (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - E0-CB-EE (hex) Samsung Electronics Co.,Ltd - E0CBEE (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E0-CE-C3 (hex) ASKEY COMPUTER CORP - E0CEC3 (base 16) ASKEY COMPUTER CORP - 10F,No.119,JIANKANG RD - ZHONGHE DIST - TAIPEI 23585 - TAIWAN, PROVINCE OF CHINA - - E0-CF-2D (hex) Gemintek Corporation - E0CF2D (base 16) Gemintek Corporation - 5F-1, No.8, Alley 30, Lane 358, Rueiguang Rd. - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - E0-D1-0A (hex) Katoudenkikougyousyo co ltd - E0D10A (base 16) Katoudenkikougyousyo co ltd - oujihontyou1-4-13 - kita-ku tokyo-to 114-0022 - JAPAN - - E0-D1-73 (hex) Cisco - E0D173 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E0-D1-E6 (hex) Aliph dba Jawbone - E0D1E6 (base 16) Aliph dba Jawbone - 99 Rhode Island Street - 3rd Floor - San Francisco California 94103 - UNITED STATES - - E0-D3-1A (hex) EQUES Technology Co., Limited - E0D31A (base 16) EQUES Technology Co., Limited - Room 301, Building 1, No.168 Jixin Road, - Minhang District - Shanghai 201199 - CHINA - - E0-D7-BA (hex) Texas Instruments - E0D7BA (base 16) Texas Instruments - 12500 TI Boulevard - MS 8723 - Dallas Texas 75243 - UNITED STATES - - E0-D9-A2 (hex) Hippih aps - E0D9A2 (base 16) Hippih aps - Sceince Park Scion - Diplomvej 381 - Lyngby 2800 - DENMARK - - E0-DA-DC (hex) JVC KENWOOD Corporation - E0DADC (base 16) JVC KENWOOD Corporation - 3-12, Moriyacho, Kanagawa-ku - Yokohama-shi Kanagawa 221-0022 - JAPAN - - E0-DB-10 (hex) Samsung Electronics Co.,Ltd - E0DB10 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E0-DB-55 (hex) Dell Inc - E0DB55 (base 16) Dell Inc - One Dell way - MS: RR5-45 - Round Rock Texas 78682 - UNITED STATES - - E0-DB-88 (hex) Open Standard Digital-IF Interface for SATCOM Systems - E0DB88 (base 16) Open Standard Digital-IF Interface for SATCOM Systems - 3090 Raritan Ave - Aberdeen Proving Ground MD 21001 - UNITED STATES - - E0-DC-A0 (hex) Siemens Electrical Apparatus Ltd., Suzhou Chengdu Branch - E0DCA0 (base 16) Siemens Electrical Apparatus Ltd., Suzhou Chengdu Branch - Tianyuan Road 99 - Cheng Du Si Chuan 611731 - CHINA - - E0-E5-CF (hex) Texas Instruments - E0E5CF (base 16) Texas Instruments - 12500 TI Blvd - Dallas TX 75243 - UNITED STATES - - E0-E6-31 (hex) SNB TECHNOLOGIES LIMITED - E0E631 (base 16) SNB TECHNOLOGIES LIMITED - Rm 303, Building #13, - Kangqiao Gardon, Buji town, - Long Gang district, ShenZhen GuangDong 518000 - CHINA - - E0-E7-51 (hex) Nintendo Co., Ltd. - E0E751 (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - E0-E8-E8 (hex) Olive Telecommunication Pvt. Ltd - E0E8E8 (base 16) Olive Telecommunication Pvt. Ltd - 862, Udyog Vihar - Phase - V - Gurgaon Haryana 122016 - INDIA - - E0-ED-1A (hex) vastriver Technology Co., Ltd - E0ED1A (base 16) vastriver Technology Co., Ltd - A-6A Keshi Building,No.28,Xinxi Road,Haidian, - Beijing 100085 - CHINA - - E0-ED-C7 (hex) Shenzhen Friendcom Technology Development Co., Ltd - E0EDC7 (base 16) Shenzhen Friendcom Technology Development Co., Ltd - 6/F,17 Building, Guangqian Industrial Park, - Xili town - Nanshan District, Shen Zhen CIty Guang Dong 518055 - CHINA - - E0-EE-1B (hex) Panasonic Automotive Systems Company of America - E0EE1B (base 16) Panasonic Automotive Systems Company of America - 776 Highway 74 South - Peachtree City Georgia 30269 - UNITED STATES - - E0-EF-25 (hex) Lintes Technology Co., Ltd. - E0EF25 (base 16) Lintes Technology Co., Ltd. - 9F-1., No.150, Jian 1st Rd., Zhonghe Dist., - New Taipei City 23511 - TAIWAN, PROVINCE OF CHINA - - E0-F2-11 (hex) Digitalwatt - E0F211 (base 16) Digitalwatt - Via Dante, 18 - Renate Brianza MB 20055 - ITALY - - E0-F3-79 (hex) Vaddio - E0F379 (base 16) Vaddio - 9433 Science Center Drive - New Hope MN 55428 - UNITED STATES - - E0-F5-C6 (hex) Apple - E0F5C6 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E0-F5-CA (hex) CHENG UEI PRECISION INDUSTRY CO.,LTD. - E0F5CA (base 16) CHENG UEI PRECISION INDUSTRY CO.,LTD. - No. 18, ZhongShan Rd., Tu Cheng Dist., - New Taipei City 23680, Taiwan - New Taipei City Taiwan 23680 - TAIWAN, PROVINCE OF CHINA - - E0-F8-47 (hex) Apple - E0F847 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E0-F9-BE (hex) Cloudena Corp. - E0F9BE (base 16) Cloudena Corp. - 6F., No. 5, Alley 22, Lane 513 - Ruiguang Road - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - E0-FA-EC (hex) Platan sp. z o.o. sp. k. - E0FAEC (base 16) Platan sp. z o.o. sp. k. - ul.Platanowa 2 - Sopot pomorskie 81-855 - POLAND - - E0-FF-F7 (hex) Softiron Inc. - E0FFF7 (base 16) Softiron Inc. - 6540 Central Avenue - Unit O - Newark California 94560 - UNITED STATES - - E4-04-39 (hex) TomTom Software Ltd - E40439 (base 16) TomTom Software Ltd - 20th Floor Euston Tower - 286 Euston Road - London NW1 3AS - UNITED KINGDOM - - E4-11-5B (hex) Hewlett Packard - E4115B (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - E4-12-18 (hex) ShenZhen Rapoo Technology Co., Ltd. - E41218 (base 16) ShenZhen Rapoo Technology Co., Ltd. - 22,Jinxiu Road East,Pingshan District,Shenzhen,China - Shenzhen Guangdong 518122 - CHINA - - E4-12-1D (hex) Samsung Electronics Co.,Ltd - E4121D (base 16) Samsung Electronics Co.,Ltd - Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E4-12-89 (hex) topsystem Systemhaus GmbH - E41289 (base 16) topsystem Systemhaus GmbH - Monnetstraße 24 - Würselen NRW 52146 - GERMANY - - E4-1C-4B (hex) V2 TECHNOLOGY, INC. - E41C4B (base 16) V2 TECHNOLOGY, INC. - 4450 Enterprise Street - Suite 101 - Fremont California 94538 - UNITED STATES - - E4-1D-2D (hex) Mellanox Technologies, Inc. - E41D2D (base 16) Mellanox Technologies, Inc. - 350 Oakmead Parkway, Suite 100 - Sunnyvale California 94085 - UNITED STATES - - E4-1F-13 (hex) IBM Corp - E41F13 (base 16) IBM Corp - 3039 E Cornwallis Rd - P.O. BOX 12195 - Research Triangle Park NC 27709-2195 - UNITED STATES - - E4-23-54 (hex) SHENZHEN FUZHI SOFTWARE TECHNOLOGY CO.,LTD - E42354 (base 16) SHENZHEN FUZHI SOFTWARE TECHNOLOGY CO.,LTD - 4/F,Fuxing Bldg,Binlang Road, - Futian Free Trade Zone - SHENZHEN Guang Dong 518038 - CHINA - - E4-25-E7 (hex) Apple - E425E7 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E4-25-E9 (hex) Color-Chip - E425E9 (base 16) Color-Chip - Tavor Building 1 - P O Box 158 - New Industrial Park Yokneam 20692 - ISRAEL - - E4-27-71 (hex) Smartlabs - E42771 (base 16) Smartlabs - 72, Oktyabrskaya Street - Moscow 127521 - RUSSIAN FEDERATION - - E4-2A-D3 (hex) Magneti Marelli S.p.A. Powertrain - E42AD3 (base 16) Magneti Marelli S.p.A. Powertrain - Via del Timavo 33 - Bologna 40128 - ITALY - - E4-2C-56 (hex) Lilee Systems, Ltd. - E42C56 (base 16) Lilee Systems, Ltd. - 2905 Stender Way, Suite 78 - Santa Clara CA 95054 - UNITED STATES - - E4-2D-02 (hex) TCT Mobile Limited - E42D02 (base 16) TCT Mobile Limited - 70 Huifeng 4rd,ZhongKai Hi-tech Development District - Huizhou Guangdong 516006 - CHINA - - E4-2F-26 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - E42F26 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - E4-2F-F6 (hex) Unicore communication Inc. - E42FF6 (base 16) Unicore communication Inc. - Rm.312 Building 2 IRICO, No.11St.4,Shangdi, Haidian District, - Beijing 100085 - CHINA - - E4-32-CB (hex) Samsung Electronics Co.,Ltd - E432CB (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E4-35-93 (hex) Hangzhou GoTo technology Co.Ltd - E43593 (base 16) Hangzhou GoTo technology Co.Ltd - Room1303,Boee building,3760 Nanhuan Road, Binjiang, - Hangzhou Zhejiang 310053 - CHINA - - E4-35-FB (hex) Sabre Technology (Hull) Ltd - E435FB (base 16) Sabre Technology (Hull) Ltd - 3a Newlands Science Park - Inglemire Lane - Hull East Yorkshire HU6 7TQ - UNITED KINGDOM - - E4-37-D7 (hex) HENRI DEPAEPE S.A.S. - E437D7 (base 16) HENRI DEPAEPE S.A.S. - 75/77 RUE DU PRE BROCHET - SANNOIS 95112 - FRANCE - - E4-38-F2 (hex) Advantage Controls - E438F2 (base 16) Advantage Controls - 4700 Harold Abitz Dr. - Muskogee OK 74403 - UNITED STATES - - E4-3F-A2 (hex) Wuxi DSP Technologies Inc. - E43FA2 (base 16) Wuxi DSP Technologies Inc. - Rm A801,530Mansion,International High-Tech Park,Qingyuan Road - Wuxi Jiangsu 214000 - CHINA - - E4-40-E2 (hex) Samsung Electronics Co.,Ltd - E440E2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E4-41-E6 (hex) Ottec Technology GmbH - E441E6 (base 16) Ottec Technology GmbH - Bünteweg 33 - Gehrden Lower Saxony 30989 - GERMANY - - E4-46-BD (hex) C&C TECHNIC TAIWAN CO., LTD. - E446BD (base 16) C&C TECHNIC TAIWAN CO., LTD. - ROOM6 13F, NO.2,Jian 8th ROAD - Taipei Chungho City, 23511 - TAIWAN, PROVINCE OF CHINA - - E4-48-C7 (hex) Cisco SPVTG - E448C7 (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville Georgia 30044 - UNITED STATES - - E4-4C-6C (hex) Shenzhen Guo Wei Electronic Co,. Ltd. - E44C6C (base 16) Shenzhen Guo Wei Electronic Co,. Ltd. - No 3038, Lo Sha Road, Liantang - LuoHu District - Shenzhen Guangdong 518004 - CHINA - - E4-4E-18 (hex) Gardasoft VisionLimited - E44E18 (base 16) Gardasoft VisionLimited - Units 1 and 2, Castle Acres - Elsworth - Cambridge CB23 4JQ - UNITED KINGDOM - - E4-4F-29 (hex) MA Lighting Technology GmbH - E44F29 (base 16) MA Lighting Technology GmbH - Dachdeckerstraße16 - Waldbüttelbrunn Bavaria 97297 - GERMANY - - E4-4F-5F (hex) EDS Elektronik Destek San.Tic.Ltd.Sti - E44F5F (base 16) EDS Elektronik Destek San.Tic.Ltd.Sti - Meclis Mah. Hayran Sok. No:4 - Sancaktepe - Istanbul 34785 - TURKEY - - E4-55-EA (hex) Dedicated Computing - E455EA (base 16) Dedicated Computing - N26 W23880 Commerce Circle - Waukesha Wisconsin 53188 - UNITED STATES - - E4-56-14 (hex) Suttle Apparatus - E45614 (base 16) Suttle Apparatus - 1001 East Highway 212 - Hector MN 55342 - UNITED STATES - - E4-57-A8 (hex) Stuart Manufacturing, Inc. - E457A8 (base 16) Stuart Manufacturing, Inc. - 1615 East Wallace Street - Fort Wayne Indiana 46803 - UNITED STATES - - E4-58-E7 (hex) Samsung Electronics Co.,Ltd - E458E7 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E4-5A-A2 (hex) vivo Mobile Communication Co., Ltd. - E45AA2 (base 16) vivo Mobile Communication Co., Ltd. - #283,BBK Road - Wusha,Chang'An DongGuan City,Guangdong, 523860 - CHINA - - E4-5D-52 (hex) Avaya, Inc - E45D52 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - E4-64-49 (hex) ARRIS Group, Inc. - E46449 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - E4-67-BA (hex) Danish Interpretation Systems A/S - E467BA (base 16) Danish Interpretation Systems A/S - Vestre Teglgade 12 - Copenhagen SV 2450 - DENMARK - - E4-68-A3 (hex) HUAWEI TECHNOLOGIES CO.,LTD - E468A3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - E4-69-5A (hex) Dictum Health, Inc. - E4695A (base 16) Dictum Health, Inc. - 170 Commerce Way, Suite 104 - Portsmouth NH 03801 - UNITED STATES - - E4-6C-21 (hex) messMa GmbH - E46C21 (base 16) messMa GmbH - Am Stadtfeld 8 - Ixleben Sachsen-Anhalt 39167 - GERMANY - - E4-71-85 (hex) Securifi Ltd - E47185 (base 16) Securifi Ltd - 16F-3, #482 Zhongxiao E Rd, Sec 5 - Taipei 11083 - TAIWAN, PROVINCE OF CHINA - - E4-75-1E (hex) Getinge Sterilization AB - E4751E (base 16) Getinge Sterilization AB - Box 69 - Getinge 31044 - SWEDEN - - E4-77-23 (hex) zte corporation - E47723 (base 16) zte corporation - 12/F.,zte R&D building Road - shenzhen guangdong 518057 - CHINA - - E4-77-6B (hex) AARTESYS AG - E4776B (base 16) AARTESYS AG - Bahnhofplatz 7 - Biel Bern CH-2501 - SWITZERLAND - - E4-77-D4 (hex) Minrray Industry Co.,Ltd - E477D4 (base 16) Minrray Industry Co.,Ltd - C5, Building 2, ZhongHaiXin ,Science&Technology Park, Ganli Rd, LiLang Blvd., Buji - Shenzhen GuangDong 518112 - CHINA - - E4-7C-F9 (hex) Samsung Electronics Co., LTD - E47CF9 (base 16) Samsung Electronics Co., LTD - 416, Maetan-3dong, Yeongtong-gu - Suwon-City, - Suwon Gyeonggi-do 443742 - KOREA, REPUBLIC OF - - E4-7D-5A (hex) Beijing Hanbang Technology Corp. - E47D5A (base 16) Beijing Hanbang Technology Corp. - 4/F,Skirt Building - No.11,Changchunqiao Road - Haidian District Beijing 100080 - CHINA - - E4-7F-B2 (hex) Fujitsu Limited - E47FB2 (base 16) Fujitsu Limited - Musashi-kosugi Tower Place Bldg., - 403, Kosugi-cho 1-chome, Nakahara-ku - Kawasaki Kanagawa 211-0063 - JAPAN - - E4-81-84 (hex) Alcatel-Lucent - E48184 (base 16) Alcatel-Lucent - 600 March Road - Kanata Ontario K2K 2E6 - CANADA - - E4-81-B3 (hex) Shenzhen ACT Industrial Co.,Ltd. - E481B3 (base 16) Shenzhen ACT Industrial Co.,Ltd. - NO.5 B/D,BEISHAN INDUSTRIAL PARK,BEISHAN R/D, - YANTIAN DISTRICT,SHENZHEN,GUANGDONG CHINA - Shenzhen Guangdong 518083 - CHINA - - E4-83-99 (hex) ARRIS Group, Inc. - E48399 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - E4-85-01 (hex) Geberit International AG - E48501 (base 16) Geberit International AG - Schachenstrasse 77 - Jona SG 8645 - SWITZERLAND - - E4-8A-D5 (hex) RF WINDOW CO., LTD. - E48AD5 (base 16) RF WINDOW CO., LTD. - 14F, Daerung Posttower3 - 182-4, Guro-dong, Guro-gu - Seoul 152-746 - KOREA, REPUBLIC OF - - E4-8B-7F (hex) Apple - E48B7F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E4-8C-0F (hex) Discovery Insure - E48C0F (base 16) Discovery Insure - 3 Alice lane - Sandton Gauteng 2196 - SOUTH AFRICA - - E4-8D-8C (hex) Routerboard.com - E48D8C (base 16) Routerboard.com - Mikrotikls SIA - Pernavas 46 - Riga Riga LV1009 - LATVIA - - E4-90-69 (hex) Rockwell Automation - E49069 (base 16) Rockwell Automation - 1 Allen-Bradley Dr. - Mayfield Heights OH 44124-6118 - UNITED STATES - - E4-90-7E (hex) Motorola Mobility LLC, a Lenovo Company - E4907E (base 16) Motorola Mobility LLC, a Lenovo Company - 222 West Merchandise Mart Plaza - Chicago IL 60654 - UNITED STATES - - E4-92-E7 (hex) Gridlink Tech. Co.,Ltd. - E492E7 (base 16) Gridlink Tech. Co.,Ltd. - Room No. 619, No. 108 Jiang Bin Dong Road - Mawei District - Fuzhou Fujian 350015 - CHINA - - E4-92-FB (hex) Samsung Electronics Co.,Ltd - E492FB (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E4-95-6E (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - E4956E (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - E4-96-AE (hex) ALTOGRAPHICS Inc. - E496AE (base 16) ALTOGRAPHICS Inc. - Daegu Venture Center 13F - Shincheon-dong, Dong-gu, - Daegu 701-020 - KOREA, REPUBLIC OF - - E4-97-F0 (hex) Shanghai VLC Technologies Ltd. Co. - E497F0 (base 16) Shanghai VLC Technologies Ltd. Co. - Room 901, B-Zone, East Beijing Road - Huangpu Dist. - Shanghai 200001 - CHINA - - E4-98-D6 (hex) Apple, Inc - E498D6 (base 16) Apple, Inc - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E4-A5-EF (hex) TRON LINK ELECTRONICS CO., LTD. - E4A5EF (base 16) TRON LINK ELECTRONICS CO., LTD. - FLAT A, 20/F., BLOCK 4,ON NING GARDEN, - 10 SHEUNG NING ROAD,TSEUNG KWAN O, - KOWLOON 999077 - HONG KONG - - E4-A7-FD (hex) Cellco Partnership - E4A7FD (base 16) Cellco Partnership - One Verizon Way - Baskin Ridge New Jersey 07920 - UNITED STATES - - E4-AB-46 (hex) UAB Selteka - E4AB46 (base 16) UAB Selteka - Draugystës g. 19 - Kaunas LT-51230 - LITHUANIA - - E4-AD-7D (hex) SCL Elements - E4AD7D (base 16) SCL Elements - 5800 St-Denis, #222 - Montreal Quebec H2S3l5 - CANADA - - E4-AF-A1 (hex) HES-SO - E4AFA1 (base 16) HES-SO - Case postale 2134 - Route du Rawyl 47 - Sion 1950 - SWITZERLAND - - E4-B0-21 (hex) Samsung Electronics Co.,Ltd - E4B021 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E4-BA-D9 (hex) 360 Fly Inc. - E4BAD9 (base 16) 360 Fly Inc. - 1000 Town Center Blvd - Suite 200 - Canonsburg PA 15317 - UNITED STATES - - E4-C1-46 (hex) Objetivos y Servicios de Valor A - E4C146 (base 16) Objetivos y Servicios de Valor A - C/ Monte Esquinza, 28, 1D - Madrid 28017 - SPAIN - - E4-C6-2B (hex) Airware - E4C62B (base 16) Airware - 1045 Bryant St. - Suite 300 - San Francisco California 94103 - UNITED STATES - - E4-C6-3D (hex) Apple, Inc. - E4C63D (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E4-C6-E6 (hex) Mophie, LLC - E4C6E6 (base 16) Mophie, LLC - 2850 Red Hill Ave. - Suite 128 - Santa Ana CA 92705 - UNITED STATES - - E4-C7-22 (hex) Cisco - E4C722 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E4-C8-06 (hex) Ceiec Electric Technology Inc. - E4C806 (base 16) Ceiec Electric Technology Inc. - 8/F West Side, Building 201, Terra Industrial & Tradepark, Che Gong Miao, - Shenzhen Guangdong 518040 - CHINA - - E4-CE-70 (hex) Health & Life co., Ltd. - E4CE70 (base 16) Health & Life co., Ltd. - 9F, No. 186, Jian Yi Road - New Taipei City Taiwan 23553 - TAIWAN, PROVINCE OF CHINA - - E4-CE-8F (hex) Apple - E4CE8F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E4-D3-32 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - E4D332 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan - Shenzhen Guangdong 518057 - CHINA - - E4-D3-F1 (hex) Cisco - E4D3F1 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E4-D5-3D (hex) Hon Hai Precision Ind. Co.,Ltd. - E4D53D (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - E4-D7-1D (hex) Oraya Therapeutics - E4D71D (base 16) Oraya Therapeutics - 8000 Jarvis Avenue Ste. 200 - Newark CA 94560 - UNITED STATES - - E4-DD-79 (hex) En-Vision America, Inc. - E4DD79 (base 16) En-Vision America, Inc. - 1845 Hovey Ave - Normal IL 61761 - UNITED STATES - - E4-E0-C5 (hex) Samsung Electronics Co., LTD - E4E0C5 (base 16) Samsung Electronics Co., LTD - 416, Maetan-3dong, Yeongtong-gu - Suwon Gyeonggi-do 443742 - KOREA, REPUBLIC OF - - E4-E4-09 (hex) LEIFHEIT AG - E4E409 (base 16) LEIFHEIT AG - Leifhheitstreet - Nassau Rheinland-Pfalz 56377 - GERMANY - - E4-EC-10 (hex) Nokia Corporation - E4EC10 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - E4-EE-FD (hex) MR&D Manufacturing - E4EEFD (base 16) MR&D Manufacturing - Viale dell'Unione Europea, 8 - Gallarate Varese 21013 - ITALY - - E4-F3-65 (hex) Time-O-Matic, Inc. - E4F365 (base 16) Time-O-Matic, Inc. - 1015 Maple St. - Danville IL 61832 - UNITED STATES - - E4-F3-E3 (hex) Shanghai iComhome Co.,Ltd. - E4F3E3 (base 16) Shanghai iComhome Co.,Ltd. - Small second floor of No.773 Siping Road - Hongkou District - Shanghai 200092 - CHINA - - E4-F4-C6 (hex) NETGEAR - E4F4C6 (base 16) NETGEAR - 350 East Plumeria Drive - San Jose California 95134 - UNITED STATES - - E4-F7-A1 (hex) Datafox GmbH - E4F7A1 (base 16) Datafox GmbH - Dermbacher Str. 12 - 14 - Geisa Thüringen 36419 - GERMANY - - E4-F8-9C (hex) Intel Corporate - E4F89C (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - E4-F8-EF (hex) Samsung Elec Co.,Ltd - E4F8EF (base 16) Samsung Elec Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E4-F9-39 (hex) Minxon Hotel Technology INC. - E4F939 (base 16) Minxon Hotel Technology INC. - 3F, No.37, Dongxing Rd., Xinyi Dist. - Taipei 11070 - TAIWAN, PROVINCE OF CHINA - - E4-FA-1D (hex) PAD Peripheral Advanced Design Inc. - E4FA1D (base 16) PAD Peripheral Advanced Design Inc. - 1400 Hocquart - Saint-Bruno QC J3V 6E1 - CANADA - - E4-FA-FD (hex) Intel Corporate - E4FAFD (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - E4-FE-D9 (hex) EDMI Europe Ltd - E4FED9 (base 16) EDMI Europe Ltd - The Grainger Suite - Dobson House, Regent Centre - Newcastle upon Tyne NE3 3PF - UNITED KINGDOM - - E4-FF-DD (hex) ELECTRON INDIA - E4FFDD (base 16) ELECTRON INDIA - TYPE II, NO.9, DR. V.S.I. ESTATE - THIRUVANMIYUR - CHENNAI TAMIL NADU 600 041 - INDIA - - E8-03-9A (hex) Samsung Electronics CO., LTD - E8039A (base 16) Samsung Electronics CO., LTD - 416, Maetan 3Dong, Yeongtong-Gu - Suwon City, Geyonggi Do, Korea - Suwon Geyonggi 443742 - KOREA, REPUBLIC OF - - E8-04-0B (hex) Apple - E8040B (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E8-04-10 (hex) PRIVATE - E80410 (base 16) - - E8-04-62 (hex) CISCO SYSTEMS, INC. - E80462 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - E8-04-F3 (hex) Throughtek Co., Ltd. - E804F3 (base 16) Throughtek Co., Ltd. - 4F, no. 221, Chong-yang Rd. - Nangang Dist - Taipei 11573 - TAIWAN, PROVINCE OF CHINA - - E8-05-6D (hex) Nortel Networks - E8056D (base 16) Nortel Networks - CARRETERA BASE AEREA # 5850 - Zapopan Jalisco 44130 - MEXICO - - E8-06-88 (hex) Apple - E80688 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E8-07-BF (hex) SHENZHEN BOOMTECH INDUSTRY CO.,LTD - E807BF (base 16) SHENZHEN BOOMTECH INDUSTRY CO.,LTD - Floor 6 East, Bldg 6, Yusheng Industrial Area, Xixiang, Bao'an District - Shenzhen Guangdong 518000 - CHINA - - E8-08-8B (hex) Huawei Technologies Co., Ltd - E8088B (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - E8-0B-13 (hex) Akib Systems Taiwan, INC - E80B13 (base 16) Akib Systems Taiwan, INC - No.582-1, RuiGuang Rd - NeiHu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - E8-0C-38 (hex) DAEYOUNG INFORMATION SYSTEM CO., LTD - E80C38 (base 16) DAEYOUNG INFORMATION SYSTEM CO., LTD - #826 TAMNIP-DONG, YUSEONG-GO, - DAEJON 305-510 - KOREA, REPUBLIC OF - - E8-0C-75 (hex) Syncbak, Inc. - E80C75 (base 16) Syncbak, Inc. - 5 Research Center - Marion IA 52302 - UNITED STATES - - E8-10-2E (hex) Really Simple Software, Inc - E8102E (base 16) Really Simple Software, Inc - P.O. Box 1086 - Tiburon California 94920 - UNITED STATES - - E8-11-32 (hex) Samsung Electronics CO., LTD - E81132 (base 16) Samsung Electronics CO., LTD - 416, Maetan 3Dong, Yeongtong-Gu - Suwon City, Geyonggi Do, Korea - Suwon Geyonggi 443742 - KOREA, REPUBLIC OF - - E8-13-24 (hex) GuangZhou Bonsoninfo System CO.,LTD - E81324 (base 16) GuangZhou Bonsoninfo System CO.,LTD - 4/F,NO.1029/31,GaoPu Road,GaoTang New Building District - Guangzhou Guangdong 510663 - CHINA - - E8-15-0E (hex) Nokia Corporation - E8150E (base 16) Nokia Corporation - Joensuunkatu 7 - P.O. Box 86 - SALO No states in Finland 24101 - FINLAND - - E8-16-2B (hex) IDEO Security Co., Ltd. - E8162B (base 16) IDEO Security Co., Ltd. - 1404, Seoul Forest IT Valley, 77, Seongsuil-ro - Seongdong-gu, SEOUL 133-822 - KOREA, REPUBLIC OF - - E8-17-FC (hex) NIFTY Corporation - E817FC (base 16) NIFTY Corporation - Shinjuku Front Tower 21-1 - Kita-shinjuku 2-chome - Shinjuku-ku Tokyo 169-8333 - JAPAN - - E8-18-63 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - E81863 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - E8-28-77 (hex) TMY Co., Ltd. - E82877 (base 16) TMY Co., Ltd. - Attic Bldg. 3F, 1-2-10 Ise-cho, - Ashikaga-shi Tochigi 326-0053 - JAPAN - - E8-28-D5 (hex) Cots Technology - E828D5 (base 16) Cots Technology - C-702, Bundang Techno Park, 145, - Yataop-dong, Bundang-gu, - Sungnam-City Kyounggi-do 463-760 - KOREA, REPUBLIC OF - - E8-2A-EA (hex) Intel Corporate - E82AEA (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - E8-2E-24 (hex) Out of the Fog Research LLC - E82E24 (base 16) Out of the Fog Research LLC - 565 Clyde Avenue, Suite 620 - Mountain View CA 94043 - UNITED STATES - - E8-33-81 (hex) ARRIS Group, Inc. - E83381 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego CA 92121 - UNITED STATES - - E8-37-7A (hex) ZyXEL Communications Corporation - E8377A (base 16) ZyXEL Communications Corporation - No. 6 Innovation Road II, Science Park - Taiwan Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - E8-39-35 (hex) Hewlett Packard - E83935 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - E8-39-DF (hex) Askey Computer - E839DF (base 16) Askey Computer - 10F,NO.119,CHIENKANG RD,CHUNG-HO, - TAIPEI 235 - TAIWAN, PROVINCE OF CHINA - - E8-3A-97 (hex) OCZ Technology Group - E83A97 (base 16) OCZ Technology Group - 6373 San Ignacio Ave - San Jose CA 95119 - UNITED STATES - - E8-3E-B6 (hex) RIM - E83EB6 (base 16) RIM - 295 Phillip Street - Waterloo Ontario N2L 3W8 - CANADA - - E8-3E-FB (hex) GEODESIC LTD. - E83EFB (base 16) GEODESIC LTD. - 18,10TH CROSS, MAYURA STREET - PAPANNA LAYOUT, OUTER RING ROAD - BANGALORE KARNATAKA 560094 - INDIA - - E8-3E-FC (hex) ARRIS Group, Inc. - E83EFC (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - E8-40-40 (hex) CISCO SYSTEMS, INC. - E84040 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - E8-40-F2 (hex) PEGATRON CORPORATION - E840F2 (base 16) PEGATRON CORPORATION - No. 76, Ligong St., Beitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - E8-43-B6 (hex) QNAP Systems, Inc. - E843B6 (base 16) QNAP Systems, Inc. - 2F., No.22, Zhongxing Rd., Xizhi Dist. - New Taipei City 221 - TAIWAN, PROVINCE OF CHINA - - E8-44-7E (hex) Bitdefender SRL - E8447E (base 16) Bitdefender SRL - 24 Delea Veche St. - Offices Building A, floor 7, district 2 - Bucharest Romania 024102 - ROMANIA - - E8-48-1F (hex) Advanced Automotive Antennas - E8481F (base 16) Advanced Automotive Antennas - Pol.Ind Can Mitjans s/n - Viladecavalls Barcelona 08232 - SPAIN - - E8-4E-06 (hex) EDUP INTERNATIONAL (HK) CO., LTD - E84E06 (base 16) EDUP INTERNATIONAL (HK) CO., LTD - 20D Room, Block B, Modern Windows Buidling, FuTian District, - Shenzhen Guangdong 518028 - CHINA - - E8-4E-84 (hex) Samsung Electronics Co.,Ltd - E84E84 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E8-4E-CE (hex) Nintendo Co., Ltd. - E84ECE (base 16) Nintendo Co., Ltd. - 11-1 HOKOTATE-CHO - KAMITOBA, MINAMI-KU - KYOTO 601-8501 - JAPAN - - E8-50-8B (hex) Samsung Electro Mechanics co., LTD. - E8508B (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - E8-51-6E (hex) TSMART Inc. - E8516E (base 16) TSMART Inc. - The-O-valley 306, - 555-9 Hogye-dong, Dongan-gu - Anyang-si Gyeonggi-do 431-080 - KOREA, REPUBLIC OF - - E8-51-9D (hex) Yeonhab Precision Co.,LTD - E8519D (base 16) Yeonhab Precision Co.,LTD - 219-27, Haksusosa-Gil, Mokcheon-Eup - Dongnam-Gu - Cheonan Chungcheongnamdo 330-844 - KOREA, REPUBLIC OF - - E8-54-84 (hex) NEO INFORMATION SYSTEMS CO., LTD. - E85484 (base 16) NEO INFORMATION SYSTEMS CO., LTD. - 609, JUNGANGINDUSPIA, #517-13, SANGDAEWEON-DONG, JUNGWEON-GU - SEONGNAM-CITY GYEONGGI-DO 462-713 - KOREA, REPUBLIC OF - - E8-56-D6 (hex) NCTech Ltd - E856D6 (base 16) NCTech Ltd - 20-22 Braid Road - Morningside - Edinburgh EH10 6AD - UNITED KINGDOM - - E8-5A-A7 (hex) LLC Emzior - E85AA7 (base 16) LLC Emzior - Strelna, Svyazi street, 34, Lit A, of. 234 - Saint-Petersburg 198515 - RUSSIAN FEDERATION - - E8-5B-5B (hex) LG ELECTRONICS INC - E85B5B (base 16) LG ELECTRONICS INC - 19-1, CHEONGHO-RI, JINWI-MYEON - PYEONGTAEK GYEONGGI-DO 451-713 - KOREA, REPUBLIC OF - - E8-5B-F0 (hex) Imaging Diagnostics - E85BF0 (base 16) Imaging Diagnostics - POB 698 - Nes Ziona 74106 - ISRAEL - - E8-5D-6B (hex) Luminate Wireless - E85D6B (base 16) Luminate Wireless - 20823 Stevens Creek Blvd, Suite 300 - Cupertino CA 95014 - UNITED STATES - - E8-5E-53 (hex) Infratec Datentechnik GmbH - E85E53 (base 16) Infratec Datentechnik GmbH - Gevener Weg 38 - Neuenrade NRW 58579 - GERMANY - - E8-61-1F (hex) Dawning Information Industry Co.,Ltd - E8611F (base 16) Dawning Information Industry Co.,Ltd - NO.15 Huake Street,Hi-Tech Zone - Tianjin 300384 - CHINA - - E8-61-7E (hex) Liteon Technology Corporation - E8617E (base 16) Liteon Technology Corporation - 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan. - TaiPei TaiWan 23585 - TAIWAN, PROVINCE OF CHINA - - E8-61-83 (hex) Black Diamond Advanced Technology, LLC - E86183 (base 16) Black Diamond Advanced Technology, LLC - 7450 S. Priest Drive - Tempe AZ 85283 - UNITED STATES - - E8-61-BE (hex) Melec Inc. - E861BE (base 16) Melec Inc. - 516-10 Higashiasakawamachi - Hachioji Tokyo 193-0834 - JAPAN - - E8-65-49 (hex) Cisco Systems - E86549 (base 16) Cisco Systems - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E8-66-C4 (hex) Datawise Systems - E866C4 (base 16) Datawise Systems - 111 N. Market St. - Suite 400 - San Jose California 95113 - UNITED STATES - - E8-6C-DA (hex) Supercomputers and Neurocomputers Research Center - E86CDA (base 16) Supercomputers and Neurocomputers Research Center - 2, Chekhov st - Taganrog Rostov-on-Don region 347922 - RUSSIAN FEDERATION - - E8-6D-52 (hex) ARRIS Group, Inc. - E86D52 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - E8-6D-54 (hex) Digit Mobile Inc - E86D54 (base 16) Digit Mobile Inc - 5F.,No.550,Ruiguang Rd., Neihu Dist.,Taipei City 11492, Taiwan - Taipei 11492 - TAIWAN, PROVINCE OF CHINA - - E8-6D-6E (hex) Control & Display Systems Ltd t/a CDSRail - E86D6E (base 16) Control & Display Systems Ltd t/a CDSRail - Unit 1, Fulcrum 4, - Solent Way - Whiteley Hampshire PO15 7FT - UNITED KINGDOM - - E8-71-8D (hex) Elsys Equipamentos Eletronicos Ltda - E8718D (base 16) Elsys Equipamentos Eletronicos Ltda - Av. Torquato Tapajós, n. 1052 - B. Flores - Manaus Amazonas 69.058-830 - BRAZIL - - E8-74-E6 (hex) ADB BROADBAND ITALIA - E874E6 (base 16) ADB BROADBAND ITALIA - VIALE SARCA 336 - MILANO 20126 - ITALY - - E8-75-7F (hex) FIRS Technologies(Shenzhen) Co., Ltd - E8757F (base 16) FIRS Technologies(Shenzhen) Co., Ltd - Rm 12A, Area A, Hongsong Business Building, Tairan 9th Rd, Chegongmiao, - Futian District - Shenzhen Guangdong 518040 - CHINA - - E8-78-A1 (hex) BEOVIEW INTERCOM DOO - E878A1 (base 16) BEOVIEW INTERCOM DOO - TRESNJINOG CVETA 5/17 - BELGRADE 11070 - SERBIA - - E8-7A-F3 (hex) S5 Tech S.r.l. - E87AF3 (base 16) S5 Tech S.r.l. - Via Tortona 72 - Milano 20144 - ITALY - - E8-80-2E (hex) Apple - E8802E (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E8-80-D8 (hex) GNTEK Electronics Co.,Ltd. - E880D8 (base 16) GNTEK Electronics Co.,Ltd. - Suzhou Industrial Park - Satellite Antenna Mansion 204,Zhongxin Road No.56 - Suzhou Jiangsu 215021 - CHINA - - E8-87-A3 (hex) Loxley Public Company Limited - E887A3 (base 16) Loxley Public Company Limited - 102 Na Ranong Road, Klongtoey, - Bangkok 10110 - THAILAND - - E8-89-2C (hex) ARRIS Group, Inc. - E8892C (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - E8-8D-28 (hex) Apple - E88D28 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - E8-8D-F5 (hex) ZNYX Networks, Inc. - E88DF5 (base 16) ZNYX Networks, Inc. - 48421 Milmont Drive - Fremont CA 94538 - UNITED STATES - - E8-8E-60 (hex) NSD Corporation - E88E60 (base 16) NSD Corporation - Osu 3-31-28 - Naka-ku - Nagoya Aichi 460-8302 - JAPAN - - E8-91-20 (hex) Motorola Mobility LLC, a Lenovo Company - E89120 (base 16) Motorola Mobility LLC, a Lenovo Company - 222 West Merchandise Mart Plaza - Chicago IL 60654 - UNITED STATES - - E8-92-18 (hex) Arcontia International AB - E89218 (base 16) Arcontia International AB - Gruvgatan 35A - Vastra Frolunda 421 30 - SWEDEN - - E8-92-A4 (hex) LG Electronics - E892A4 (base 16) LG Electronics - 60-39, Kasan-dong, Gumcheon-Gu - Seoul 153-801 - KOREA, REPUBLIC OF - - E8-94-4C (hex) Cogent Healthcare Systems Ltd - E8944C (base 16) Cogent Healthcare Systems Ltd - 69 Alma Road - Windsor - Berkshire SL4 3HT - UNITED KINGDOM - - E8-94-F6 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - E894F6 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - E8-96-06 (hex) testo Instruments (Shenzhen) Co., Ltd. - E89606 (base 16) testo Instruments (Shenzhen) Co., Ltd. - China Merchants Guangming Science & Technology Park, - Block A, B4 Building, No. 3009 Guan Guang Road, - Guangming New District, Shenzhen Guangdong 518107 - CHINA - - E8-99-5A (hex) PiiGAB, Processinformation i Goteborg AB - E8995A (base 16) PiiGAB, Processinformation i Goteborg AB - Anders Carlssons gata 1 - Gothenburg 417 55 - SWEDEN - - E8-99-C4 (hex) HTC Corporation - E899C4 (base 16) HTC Corporation - No. 23, Xinghua Rd., Taoyuan City - Taoyuan County Taiwan 330 - TAIWAN, PROVINCE OF CHINA - - E8-9A-8F (hex) Quanta Computer Inc. - E89A8F (base 16) Quanta Computer Inc. - 211, Wen Hwa 2nd Rd.,Kuei Shan, Tao Yuan - TAIPEI 33377 - TAIWAN, PROVINCE OF CHINA - - E8-9A-FF (hex) Fujian Landi Commercial Equipment Co.,Ltd - E89AFF (base 16) Fujian Landi Commercial Equipment Co.,Ltd - No.68, Hong Shan Yuan Road, Gulou District - Fuzhou Municipality Fujian Province 350001 - CHINA - - E8-9D-87 (hex) Toshiba - E89D87 (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - E8-A3-64 (hex) Signal Path International / Peachtree Audio - E8A364 (base 16) Signal Path International / Peachtree Audio - 2045 120th Ave NE - Bellevue Washington 98005 - UNITED STATES - - E8-A4-C1 (hex) Deep Sea Electronics PLC - E8A4C1 (base 16) Deep Sea Electronics PLC - Highfield House - Hunmanby Industrial Estate - Hunmanby North Yorkshire YO14 0PH - UNITED KINGDOM - - E8-AB-FA (hex) Shenzhen Reecam Tech.Ltd. - E8ABFA (base 16) Shenzhen Reecam Tech.Ltd. - Room 03D-1 , North Wing Of 3 rd Floor, Block 1 , Vision Shenzhen Business Park - NO.9 Gaoxin 9th South Road , Shenzhen Hi-tech Industrial Park - Nanshan District, Shenzhen Guangdong 518052 - CHINA - - E8-B1-FC (hex) Intel Corporate - E8B1FC (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - E8-B4-AE (hex) Shenzhen C&D Electronics Co.,Ltd - E8B4AE (base 16) Shenzhen C&D Electronics Co.,Ltd - Building 2, Xia You Song Mountain Top Industrial District, You Song Village - Longhua, Bao An - Shenzhen Guang Dong 518000 - CHINA - - E8-B7-48 (hex) CISCO SYSTEMS, INC. - E8B748 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - E8-BA-70 (hex) CISCO SYSTEMS, INC. - E8BA70 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - E8-BB-3D (hex) Sino Prime-Tech Limited - E8BB3D (base 16) Sino Prime-Tech Limited - Room 418, Building 1, Hua Mei Ju (D), - Xinhu Road, Bao An - Shenzhen Guangdong 518101 - CHINA - - E8-BB-A8 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - E8BBA8 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD. - NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA - DONGGUAN GUANGDONG 523860 - CHINA - - E8-BE-81 (hex) SAGEMCOM - E8BE81 (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON Ile de France 92848 - FRANCE - - E8-C2-29 (hex) H-Displays (MSC) Bhd - E8C229 (base 16) H-Displays (MSC) Bhd - No. 31 & 32, Jalan Gangsa Dua - Pasir Gudang - Johor Bahru 81700 - MALAYSIA - - E8-C3-20 (hex) Austco Communication Systems Pty Ltd - E8C320 (base 16) Austco Communication Systems Pty Ltd - 40 O'Malley Street - Osborne Park Western Australia 6017 - AUSTRALIA - - E8-C7-4F (hex) Liteon Technology Corporation - E8C74F (base 16) Liteon Technology Corporation - 4F, No. 90, Chien 1 Road, - ChungHo, - New Taipei City Taiwan 23585 - TAIWAN, PROVINCE OF CHINA - - E8-CB-A1 (hex) Nokia Corporation - E8CBA1 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - E8-CC-18 (hex) D-Link International - E8CC18 (base 16) D-Link International - 1 Internal Business Park, #03-12 - The Synergy - Singapore 609917 - SINGAPORE - - E8-CC-32 (hex) Micronet LTD - E8CC32 (base 16) Micronet LTD - Hametzuda 27 - Azor 58001 - ISRAEL - - E8-CD-2D (hex) Huawei Technologies Co., Ltd - E8CD2D (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - E8-CE-06 (hex) SkyHawke Technologies, LLC. - E8CE06 (base 16) SkyHawke Technologies, LLC. - 274 Commerce Park Drive - Ridgeland MS 39157 - UNITED STATES - - E8-D0-FA (hex) MKS Instruments Deutschland GmbH - E8D0FA (base 16) MKS Instruments Deutschland GmbH - Schatzbogen 43 - Munich 81829 - GERMANY - - E8-D4-83 (hex) ULTIMATE Europe Transportation Equipment GmbH - E8D483 (base 16) ULTIMATE Europe Transportation Equipment GmbH - Industriestraße 3 - 3300 Niederösterreich 3300 - AUSTRIA - - E8-D4-E0 (hex) Beijing BenyWave Technology Co., Ltd. - E8D4E0 (base 16) Beijing BenyWave Technology Co., Ltd. - No.55, Jiachuang Road, Taihu Town - Tongzhou District - Beijing 101111 - CHINA - - E8-DA-96 (hex) Zhuhai Tianrui Electrical Power Tech. Co., Ltd. - E8DA96 (base 16) Zhuhai Tianrui Electrical Power Tech. Co., Ltd. - Minying Technology Zone, 10# Keji 1 Road, Gangwan Main Road, Tangjia - Zhuhai Guangdong 519085 - CHINA - - E8-DA-AA (hex) VideoHome Technology Corp. - E8DAAA (base 16) VideoHome Technology Corp. - 4F-1, No. 192, Da Tung Rd., Sec. 3, Hsichih, - Taipei Hsien 221 - TAIWAN, PROVINCE OF CHINA - - E8-DE-27 (hex) TP-LINK TECHNOLOGIES CO.,LTD. - E8DE27 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors1-4) - Central Science and Technology Park,Shennan Rd - Nanshan District, Shenzhen Guangdong 518057 - CHINA - - E8-DF-F2 (hex) PRF Co., Ltd. - E8DFF2 (base 16) PRF Co., Ltd. - #510, Leaders B/D, Yatop-dong - Bundang-gu - Seongnam-city Gyeonggi-do 463-828 - KOREA, REPUBLIC OF - - E8-E0-8F (hex) GRAVOTECH MARKING SAS - E8E08F (base 16) GRAVOTECH MARKING SAS - 56 AVENUE JEAN JAURES - LA CHAPELLE SAINT LUC AUBE 10600 - FRANCE - - E8-E0-B7 (hex) Toshiba - E8E0B7 (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - E8-E1-E2 (hex) Energotest - E8E1E2 (base 16) Energotest - Chorzowska 44B - Gliwice Slask 44-100 - POLAND - - E8-E5-D6 (hex) Samsung Electronics Co.,Ltd - E8E5D6 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - E8-E7-32 (hex) Alcatel-Lucent - E8E732 (base 16) Alcatel-Lucent - 26801 West Agoura Road - Calabasas CA 91301 - UNITED STATES - - E8-E7-70 (hex) Warp9 Tech Design, Inc. - E8E770 (base 16) Warp9 Tech Design, Inc. - 3650 Pheasant Run N.E. - Blaine MN 55449 - UNITED STATES - - E8-E7-76 (hex) Shenzhen Kootion Technology Co., Ltd - E8E776 (base 16) Shenzhen Kootion Technology Co., Ltd - 3/F, Building #4, XinJianXing Industrial Park - Songbai Road, Nanshan District, - Shenzhen Guangdong Province 518108 - CHINA - - E8-E8-75 (hex) iS5 Communications Inc. - E8E875 (base 16) iS5 Communications Inc. - 8 Quatro Crescent - Brampton Ontario L6P 2T4 - CANADA - - E8-EA-6A (hex) StarTech.com - E8EA6A (base 16) StarTech.com - 45 Artisans Cres - London Ontario N5V5E9 - CANADA - - E8-EA-DA (hex) Denkovi Assembly Electroncs LTD - E8EADA (base 16) Denkovi Assembly Electroncs LTD - St. Stambolov str. 21 - Byala Rousse 7100 - BULGARIA - - E8-ED-05 (hex) ARRIS Group, Inc. - E8ED05 (base 16) ARRIS Group, Inc. - 6450 Sequence Drive - San Diego California 92121 - UNITED STATES - - E8-ED-F3 (hex) Cisco - E8EDF3 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - E8-EF-89 (hex) OPMEX Tech. - E8EF89 (base 16) OPMEX Tech. - 18F GDC Building, 9 Gaoxin Central Avenue 3rd, Nanshan District - Shenzhen Guangdong 518000 - CHINA - - E8-F1-B0 (hex) SAGEMCOM SAS - E8F1B0 (base 16) SAGEMCOM SAS - 250 ROUTE DE L'EMPEREUR - RUEIL MALMAISON CEDEX ILE DE FRANCE 92848 - FRANCE - - E8-F2-26 (hex) MILLSON CUSTOM SOLUTIONS INC. - E8F226 (base 16) MILLSON CUSTOM SOLUTIONS INC. - 2036 COLUMBIA STREET - VANCOUVER BRITISH COLUMBIA V5Y 3E1 - CANADA - - E8-F2-E3 (hex) Starcor Beijing Co.,Limited - E8F2E3 (base 16) Starcor Beijing Co.,Limited - NO.210 Block B, Building 2 - No. 1 Nongda South Road,Haidian District - Beijing Berijing 100089 - CHINA - - E8-F9-28 (hex) RFTECH SRL - E8F928 (base 16) RFTECH SRL - VIA VENETO, 22 - SCHIO VICENZA 36015 - ITALY - - E8-FC-60 (hex) ELCOM Innovations Private Limited - E8FC60 (base 16) ELCOM Innovations Private Limited - 9TH FLOOR, MERIDIEN COMMERCIAL TOWER - RAISINA ROAD - New Delhi 110001 - INDIA - - E8-FC-AF (hex) NETGEAR INC., - E8FCAF (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - EC-0E-C4 (hex) Hon Hai Precision Ind. Co.,Ltd. - EC0EC4 (base 16) Hon Hai Precision Ind. Co.,Ltd. - Building D21,No.1, East Zone 1st Road - ,Xiyong Town,Shapingba District, - Chongqing 401332 - CHINA - - EC-0E-D6 (hex) ITECH INSTRUMENTS SAS - EC0ED6 (base 16) ITECH INSTRUMENTS SAS - 3 Avenue de la Maranne - ZI La Valampe - Châteauneuf-Les-Martigues 13220 - FRANCE - - EC-11-20 (hex) FloDesign Wind Turbine Corporation - EC1120 (base 16) FloDesign Wind Turbine Corporation - Papirfabrikken 28 - Silkeborg 8600 - DENMARK - - EC-11-27 (hex) Texas Instruments - EC1127 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - EC-13-B2 (hex) Netonix - EC13B2 (base 16) Netonix - 6 East Main St - Leola PA 17540 - UNITED STATES - - EC-14-F6 (hex) BioControl AS - EC14F6 (base 16) BioControl AS - Grimstad Gard - Rakkestad N-1890 - NORWAY - - EC-17-2F (hex) TP-LINK TECHNOLOGIES CO., LTD. - EC172F (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, Shenzhen,China - shenzhen guangdong Province 518057 - CHINA - - EC-17-66 (hex) Research Centre Module - EC1766 (base 16) Research Centre Module - 3 Eight March 4Th Street - Moscow Moscow 125190 - RUSSIAN FEDERATION - - EC-1A-59 (hex) Belkin International Inc. - EC1A59 (base 16) Belkin International Inc. - 12045 East Waterfront Drive - Playa Vista Ca. 90094 - UNITED STATES - - EC-1D-7F (hex) zte corporation - EC1D7F (base 16) zte corporation - 12/F.,zte R&D building ,Kejinan Road - shenzhen guangdong 518057 - CHINA - - EC-21-9F (hex) VidaBox LLC - EC219F (base 16) VidaBox LLC - 240 Madison Ave - Garden City Park NEW YORK 11040 - UNITED STATES - - EC-22-57 (hex) JiangSu NanJing University Electronic Information Technology Co.,Ltd - EC2257 (base 16) JiangSu NanJing University Electronic Information Technology Co.,Ltd - F7,Block 06 - No.18 Jialing jiangdong Street - NanJing JiangSu 210000 - CHINA - - EC-22-80 (hex) D-Link International - EC2280 (base 16) D-Link International - 1 Internal Business Park, #03-12, - The Synergy - Singapore 609917 - SINGAPORE - - EC-23-3D (hex) Huawei Technologies Co., Ltd - EC233D (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518057 - CHINA - - EC-23-68 (hex) IntelliVoice Co.,Ltd. - EC2368 (base 16) IntelliVoice Co.,Ltd. - 3-6 Kioicho - Kioicho Park Bld. 1F - Chiyoda Tokyo 102-0094 - JAPAN - - EC-24-B8 (hex) Texas Instruments - EC24B8 (base 16) Texas Instruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - EC-26-CA (hex) TP-LINK TECHNOLOGIES CO.,LTD - EC26CA (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24 (floors 1,3,4,5) and 28 (floors1-4)  - Central Science and Technology Park,Shennan Rd - Nanshan, Shenzhen Guangdong 518057 - CHINA - - EC-2A-F0 (hex) Ypsomed AG - EC2AF0 (base 16) Ypsomed AG - Brunnmattstrasse 6 - Burgdorf BE 3400 - SWITZERLAND - - EC-2C-49 (hex) University of Tokyo - EC2C49 (base 16) University of Tokyo - Nakao-lab, The University of Tokyo - A103 Daiwa Ubiquitous Computing Research Bldg. - 7-3-1 Hongo, Bunkyo-ku Tokyo 113-0033 - JAPAN - - EC-2E-4E (hex) HITACHI-LG DATA STORAGE INC - EC2E4E (base 16) HITACHI-LG DATA STORAGE INC - 4F, MSC CENTER BLDG., 22-23 KAIGAN 3-CHOME, MINATO-KU, - TOKYO TOKYO 108-0022 - JAPAN - - EC-30-91 (hex) CISCO SYSTEMS, INC. - EC3091 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - EC-35-86 (hex) Apple - EC3586 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - EC-3B-F0 (hex) NovelSat - EC3BF0 (base 16) NovelSat - Hataasia 21 - Raanana 2396 - ISRAEL - - EC-3C-5A (hex) SHEN ZHEN HENG SHENG HUI DIGITAL TECHNOLOGY CO.,LTD - EC3C5A (base 16) SHEN ZHEN HENG SHENG HUI DIGITAL TECHNOLOGY CO.,LTD - 5A 6FLOOR, BLOCK C12, FUYUAN INDUSTRIAL AREA, ZHOU SHI ROAD, - NO111, XIXIANG STREET, BAOAN - SHENZHEN GUANGDONG 518102 - CHINA - - EC-3C-88 (hex) MCNEX Co.,Ltd. - EC3C88 (base 16) MCNEX Co.,Ltd. - Hanshin IT Tower2 11F, Digital lo 9 gil - Geumcheon-Gu Seoul 153-712 - KOREA, REPUBLIC OF - - EC-3E-09 (hex) PERFORMANCE DESIGNED PRODUCTS, LLC - EC3E09 (base 16) PERFORMANCE DESIGNED PRODUCTS, LLC - 14144 Ventura Blvd - Suite 200 - Sherman Oaks California 91423 - UNITED STATES - - EC-3F-05 (hex) Institute 706, The Second Academy China Aerospace Science & Industry Corp - EC3F05 (base 16) Institute 706, The Second Academy China Aerospace Science & Industry Corp - YongDing Road ,HaiDian District.BeiJing ,No.51 - BeiJing 100854 - CHINA - - EC-42-F0 (hex) ADL Embedded Solutions, Inc. - EC42F0 (base 16) ADL Embedded Solutions, Inc. - 4411 Morena Blvd. - Suite 101 - San Diego CA 92117 - UNITED STATES - - EC-43-E6 (hex) AWCER Ltd. - EC43E6 (base 16) AWCER Ltd. - 100-413 Bucheon Technopark - 364 SanJeong-dong, Ojeong-gu - Bucheon-city Gyeonggi-do 421-741 - KOREA, REPUBLIC OF - - EC-43-F6 (hex) ZyXEL Communications Corporation - EC43F6 (base 16) ZyXEL Communications Corporation - No. 6 Innovation Road 2, HsinChu Science Park, HsinChu, Taiwan,300 - HsinChu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - EC-44-76 (hex) CISCO SYSTEMS, INC. - EC4476 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - EC-46-44 (hex) TTK SAS - EC4644 (base 16) TTK SAS - 4, Rue du Chemin Vert - Clichy 92110 - FRANCE - - EC-46-70 (hex) Meinberg Funkuhren GmbH & Co. KG - EC4670 (base 16) Meinberg Funkuhren GmbH & Co. KG - Lange Wand 9 - Bad Pyrmont NDS 31812 - GERMANY - - EC-47-3C (hex) Redwire, LLC - EC473C (base 16) Redwire, LLC - 8 Thorndike St - Everett MA 02149 - UNITED STATES - - EC-49-93 (hex) Qihan Technology Co., Ltd - EC4993 (base 16) Qihan Technology Co., Ltd - 20th Floor,Times Technology BuildingNo.7028 - Shennan Road,Futian, - Shenzhen Guangdong 518040 - CHINA - - EC-4C-4D (hex) ZAO NPK RoTeK - EC4C4D (base 16) ZAO NPK RoTeK - Bild. 119-1, Prospekt Mira - Moscow Moscow 129223 - RUSSIAN FEDERATION - - EC-4F-82 (hex) Calix Inc. - EC4F82 (base 16) Calix Inc. - 1035 North McDowell Boulevard - Petaluma CA 94954 - UNITED STATES - - EC-54-2E (hex) Shanghai XiMei Electronic Technology Co. Ltd - EC542E (base 16) Shanghai XiMei Electronic Technology Co. Ltd - Room 503, No.2623, GongHeXin Road - Shanghai 200072 - CHINA - - EC-55-F9 (hex) Hon Hai Precision Ind. Co.,Ltd. - EC55F9 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - EC-59-E7 (hex) Microsoft Corporation - EC59E7 (base 16) Microsoft Corporation - 1 Microsoft Way - Redmond Washington 98052 - UNITED STATES - - EC-5A-86 (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd - EC5A86 (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd - Road NO2, West of Industrial Park,North of Science & Technology Park - Shongshan Lake - Dongguan Guangdong 518057 - CHINA - - EC-5C-69 (hex) MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. - EC5C69 (base 16) MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. - 1-16,5-CHOME,KOMATSU-DORI, - KOBE HYOGO 652-0865 - JAPAN - - EC-60-E0 (hex) AVI-ON LABS - EC60E0 (base 16) AVI-ON LABS - 2585 LARKSPUR DR - PARK CITY UT 84060 - UNITED STATES - - EC-62-64 (hex) Global411 Internet Services, LLC - EC6264 (base 16) Global411 Internet Services, LLC - 10400 W Overland Rd #371 - Boise Idaho 83709 - UNITED STATES - - EC-63-E5 (hex) ePBoard Design LLC - EC63E5 (base 16) ePBoard Design LLC - 4065 E. La Palma Ave. - Suite# C - Anaheim California 92807 - UNITED STATES - - EC-66-D1 (hex) B&W Group LTD - EC66D1 (base 16) B&W Group LTD - Dale Road - Worthing Sussex BN11 2BH - UNITED KINGDOM - - EC-6C-9F (hex) Chengdu Volans Technology CO.,LTD - EC6C9F (base 16) Chengdu Volans Technology CO.,LTD - 2nd Floor Building 4B Hi-Tech Incubation Park,Nanyan Xian,Tianfu Ave - Chengdu Sichuan 610041 - CHINA - - EC-71-DB (hex) Shenzhen Baichuan Digital Technology Co., Ltd. - EC71DB (base 16) Shenzhen Baichuan Digital Technology Co., Ltd. - Room 602, Complex Building, Tsinghua High-Tech Park - Nanshan District, Shenzhen, P.R.China - Shenzhen Guangdong 518000 - CHINA - - EC-74-BA (hex) Hirschmann Automation and Control GmbH - EC74BA (base 16) Hirschmann Automation and Control GmbH - Stuttgarter Strasse 45-51 - Neckartenzlingen Baden-Württemberg 72654 - GERMANY - - EC-7C-74 (hex) Justone Technologies Co., Ltd. - EC7C74 (base 16) Justone Technologies Co., Ltd. - Tongguang Building F19, 12# South Agriculture Exhibition Center Road, - Chaoyang District - Beijing 100125 - CHINA - - EC-7D-9D (hex) MEI - EC7D9D (base 16) MEI - 3222 Phoenixville Pike - Suite 200 - Malvern PA 19355 - UNITED STATES - - EC-80-09 (hex) NovaSparks - EC8009 (base 16) NovaSparks - 12 rue de Chatillon - Paris Ile de France 75014 - FRANCE - - EC-83-6C (hex) RM Tech Co., Ltd. - EC836C (base 16) RM Tech Co., Ltd. - C-801, Bupyeong Woolim Lions Valley - Cheongcheon 2-dong, Bupyeong-gu - Incheon City 403-911 - KOREA, REPUBLIC OF - - EC-85-2F (hex) Apple - EC852F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - EC-88-8F (hex) TP-LINK TECHNOLOGIES CO., LTD. - EC888F (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park - Shennan Rd, Nanshan - Shenzhen Guangdong 518057 - CHINA - - EC-88-92 (hex) Motorola Mobility LLC - EC8892 (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - EC-89-F5 (hex) Lenovo Mobile Communication Technology Ltd. - EC89F5 (base 16) Lenovo Mobile Communication Technology Ltd. - No.999,Qishan North 2nd Road,Information&Optoelectronicse Park, - Torch Hi-tch Industry Development Zone - Xiamen Fujian 361006 - CHINA - - EC-8A-4C (hex) zte corporation - EC8A4C (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - EC-8E-AD (hex) DLX - EC8EAD (base 16) DLX - #401, Seoil B/D,1359-45 Seocho2-dong - Seocho-ku, - Seoul 137-863 - KOREA, REPUBLIC OF - - EC-92-33 (hex) Eddyfi NDT Inc - EC9233 (base 16) Eddyfi NDT Inc - 2800, Louis-Lumiere street - Suite 100 - Quebec Quebec G1P 0A4 - CANADA - - EC-93-27 (hex) MEMMERT GmbH + Co. KG - EC9327 (base 16) MEMMERT GmbH + Co. KG - Aeussere Rittersbacher Strasse 38 - Schwabach Bavaria 91126 - GERMANY - - EC-96-81 (hex) 2276427 Ontario Inc - EC9681 (base 16) 2276427 Ontario Inc - 31-1275 Morningside Ave - Toronto ON M1B3W1 - CANADA - - EC-98-6C (hex) Lufft Mess- und Regeltechnik GmbH - EC986C (base 16) Lufft Mess- und Regeltechnik GmbH - Gutenbergstraße 20 - Fellbach Baden-Württemberg 70736 - GERMANY - - EC-98-C1 (hex) Beijing Risbo Network Technology Co.,Ltd - EC98C1 (base 16) Beijing Risbo Network Technology Co.,Ltd - 1/F Yinyan Building 2A,No.23 Anningzhuangdonglu Haidian District - Beijing 100085 - CHINA - - EC-9A-74 (hex) Hewlett Packard - EC9A74 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - EC-9B-5B (hex) Nokia Corporation - EC9B5B (base 16) Nokia Corporation - Elektroniikkatie 10 - Kempele 90570 - FINLAND - - EC-9E-CD (hex) Artesyn Embedded Technologies - EC9ECD (base 16) Artesyn Embedded Technologies - 2900 S. Diablo Way Suite 190 - Tempe Arizona 85282 - UNITED STATES - - EC-A2-9B (hex) Kemppi Oy - ECA29B (base 16) Kemppi Oy - Kempinkatu 1 - P.O. Box 13 - Lahti Lahti 15810 - FINLAND - - EC-A8-6B (hex) ELITEGROUP COMPUTER SYSTEMS CO., LTD. - ECA86B (base 16) ELITEGROUP COMPUTER SYSTEMS CO., LTD. - NO. 239, Sec. 2, Ti Ding Blvd. - Taipei 11493 - TAIWAN, PROVINCE OF CHINA - - EC-B1-06 (hex) Acuro Networks, Inc - ECB106 (base 16) Acuro Networks, Inc - 42808 Christy St., Suite 100 - Fremont CA 94538 - UNITED STATES - - EC-B1-D7 (hex) Hewlett Packard - ECB1D7 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Tx 77070 - UNITED STATES - - EC-B5-41 (hex) SHINANO E and E Co.Ltd. - ECB541 (base 16) SHINANO E and E Co.Ltd. - 5511-6 Wada - Matsumoto City Nagano 390-1242 - JAPAN - - EC-B9-07 (hex) CloudGenix Inc - ECB907 (base 16) CloudGenix Inc - 2933 Bunker Hill Lane - Suite 205 - Santa Clara CA 95054 - UNITED STATES - - EC-BA-FE (hex) GIROPTIC - ECBAFE (base 16) GIROPTIC - 165 avenue de Bretagne - Euratechnologies - Lille Nord 59000 - FRANCE - - EC-BB-AE (hex) Digivoice Tecnologia em Eletronica Ltda - ECBBAE (base 16) Digivoice Tecnologia em Eletronica Ltda - Alameda Juru, 159 - Torreo - Barueri São Paulo 06455-010 - BRAZIL - - EC-BD-09 (hex) FUSION Electronics Ltd - ECBD09 (base 16) FUSION Electronics Ltd - PO Box 137 - 142 - Parnell - Auckland 1151 - NEW ZEALAND - - EC-C3-8A (hex) Accuenergy (CANADA) Inc - ECC38A (base 16) Accuenergy (CANADA) Inc - 2 Lansing Square, Suite 503 - Toronto Ontario M2J 4P8 - CANADA - - EC-C8-82 (hex) CISCO SYSTEMS, INC. - ECC882 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - EC-CB-30 (hex) Huawei Technologies Co., Ltd - ECCB30 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - EC-CD-6D (hex) Allied Telesis, Inc. - ECCD6D (base 16) Allied Telesis, Inc. - 3041 Orchard Parkway - San Jose California 95134 - UNITED STATES - - EC-D0-0E (hex) MiraeRecognition Co., Ltd. - ECD00E (base 16) MiraeRecognition Co., Ltd. - PrimeBank Bldg. Annex-3F, #278-3 - Nonhyun-dong, Gangnam-gu - Seoul 135-833 - KOREA, REPUBLIC OF - - EC-D0-40 (hex) GEA Farm Technologies GmbH - ECD040 (base 16) GEA Farm Technologies GmbH - Siemensstrasse 25-27 - Boenen Northrhine-Westfalia 59199 - GERMANY - - EC-D1-9A (hex) Zhuhai Liming Industries Co., Ltd - ECD19A (base 16) Zhuhai Liming Industries Co., Ltd - No.6 Xinqing Rd,Xinqing Hi-Tech Industrial Park - Doumen District - Zhuhai Guangdong 519100 - CHINA - - EC-D9-25 (hex) RAMI - ECD925 (base 16) RAMI - 7 RUE RAOUL FOLLEREAU - BUSSY ST GEORGES 77600 - FRANCE - - EC-D9-50 (hex) IRT SA - ECD950 (base 16) IRT SA - Puits-Godet 16 - NEUCHATEL NE 2000 - SWITZERLAND - - EC-D9-D1 (hex) Shenzhen TG-NET Botone Technology Co.,Ltd. - ECD9D1 (base 16) Shenzhen TG-NET Botone Technology Co.,Ltd. - East F/3,No.38 Huarong Second Industry Zone - Langrong Road, Dalang Street, Longhua - Shenzhen Guangdong 518109 - CHINA - - EC-DE-3D (hex) Lamprey Networks, Inc. - ECDE3D (base 16) Lamprey Networks, Inc. - 58 Dover Road - Durham NH 03824 - UNITED STATES - - EC-E0-9B (hex) Samsung electronics CO., LTD - ECE09B (base 16) Samsung electronics CO., LTD - 416, Maetan-3dong, Yeongtong-gu, - Suwon-City Gyeonggi-do 443-742 - KOREA, REPUBLIC OF - - EC-E1-A9 (hex) Cisco - ECE1A9 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - EC-E2-FD (hex) SKG Electric Group(Thailand) Co., Ltd. - ECE2FD (base 16) SKG Electric Group(Thailand) Co., Ltd. - 3F,The Second Building,Sanhe village , Longhua Rd, Baoan Dist., Shenzhen, China - Shenzhen Guangdong 518301 - CHINA - - EC-E5-12 (hex) tado GmbH - ECE512 (base 16) tado GmbH - Lindwurmstr. 76 - Munich Bavaria 80337 - GERMANY - - EC-E5-55 (hex) Hirschmann Automation - ECE555 (base 16) Hirschmann Automation - Stuttgarter Straße 45-51 - Neckartenzlingen Baden-Württemberg 72654 - GERMANY - - EC-E7-44 (hex) Omntec mfg. inc - ECE744 (base 16) Omntec mfg. inc - 1993 Pond Road. - Ronkonkoma NY 11779 - UNITED STATES - - EC-E9-0B (hex) SISTEMA SOLUCOES ELETRONICAS LTDA - EASYTECH - ECE90B (base 16) SISTEMA SOLUCOES ELETRONICAS LTDA - EASYTECH - RUA GUERRA DE AGUIAR, 220 - São Paulo SP 08275-260 - BRAZIL - - EC-E9-15 (hex) STI Ltd - ECE915 (base 16) STI Ltd - Osborn Way - Hook Hampshire RG27 9HX - UNITED KINGDOM - - EC-E9-F8 (hex) Guang Zhou TRI-SUN Electronics Technology Co., Ltd - ECE9F8 (base 16) Guang Zhou TRI-SUN Electronics Technology Co., Ltd - 9th floor Guangzhou info port building B, Keyun Road, Tianhe District, Guangzhou ,PRC - Guangzhou Guangdong 510665 - CHINA - - EC-EA-03 (hex) DARFON LIGHTING CORP - ECEA03 (base 16) DARFON LIGHTING CORP - 167, Shanying Road - Gueishan Taoyuan 33341 - TAIWAN, PROVINCE OF CHINA - - EC-F0-0E (hex) Abocom - ECF00E (base 16) Abocom - 1F , No. 21, Yanfa 2nd Rd., SBIP - Hsinchu City 300 886 - TAIWAN, PROVINCE OF CHINA - - EC-F2-36 (hex) NEOMONTANA ELECTRONICS - ECF236 (base 16) NEOMONTANA ELECTRONICS - Mladost-4, bl. 483, mag. 13 - Sofia 1715 - BULGARIA - - EC-F3-5B (hex) Nokia Corporation - ECF35B (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - EC-F4-BB (hex) Dell Inc - ECF4BB (base 16) Dell Inc - one dell way - MS:RR5-45 - Round rock Texas 78682 - UNITED STATES - - EC-F7-2B (hex) HD DIGITAL TECH CO., LTD. - ECF72B (base 16) HD DIGITAL TECH CO., LTD. - Room 602, Baoyuan road, Banan District - Shenzhen Guangdong 518102 - CHINA - - EC-FA-AA (hex) The IMS Company - ECFAAA (base 16) The IMS Company - 2929 E. Imperial Highway - Suite 170 - Brea CA 92821 - UNITED STATES - - EC-FC-55 (hex) A. Eberle GmbH & Co. KG - ECFC55 (base 16) A. Eberle GmbH & Co. KG - Frankenstrasse 160 - Nuernberg Bavaria 90461 - GERMANY - - EC-FE-7E (hex) BlueRadios, Inc. - ECFE7E (base 16) BlueRadios, Inc. - 7173 S. Havana Street, Suite 600 - Englewood Colorado 80112 - UNITED STATES - - F0-00-7F (hex) Janz - Contadores de Energia, SA - F0007F (base 16) Janz - Contadores de Energia, SA - Avenida Infante D. Henrique - 328 - Lisbon 1800-223 - PORTUGAL - - F0-02-2B (hex) Chrontel - F0022B (base 16) Chrontel - 2210 OToole Ave., Suite 100 - San Jose CA 95131 - UNITED STATES - - F0-02-48 (hex) SmarteBuilding - F00248 (base 16) SmarteBuilding - 3267 Bee Cave Road - 107-173 - Austin TX 78746 - UNITED STATES - - F0-07-86 (hex) Shandong Bittel Electronics Co., Ltd - F00786 (base 16) Shandong Bittel Electronics Co., Ltd - No.1 Rizhao North Road - Rizhao Shandong 276800 - CHINA - - F0-08-F1 (hex) Samsung Electronics Co.,Ltd - F008F1 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F0-13-C3 (hex) SHENZHEN FENDA TECHNOLOGY CO., LTD - F013C3 (base 16) SHENZHEN FENDA TECHNOLOGY CO., LTD - Fenda Hi-Tech Park, Zhoushi Road, Shiyan, Baoan - ShenZhen GuangDong 518108 - CHINA - - F0-15-A0 (hex) KyungDong One Co., Ltd. - F015A0 (base 16) KyungDong One Co., Ltd. - 205-38, Gasan digital 1-ro, - Geumcheon-gu - Seoul 153-803 - KOREA, REPUBLIC OF - - F0-1C-13 (hex) LG Electronics - F01C13 (base 16) LG Electronics - 60-39 , Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - F0-1C-2D (hex) Juniper Networks - F01C2D (base 16) Juniper Networks - 1194 N Mathilda Avenue - sunnyvale CA 94089 - UNITED STATES - - F0-1E-34 (hex) ORICO Technologies Co., Ltd - F01E34 (base 16) ORICO Technologies Co., Ltd - F-9, Block14A, Zhonghaixin Science &Technology Zone - Bulan Road, Longgang District - ShenZhen Guangdong 518112 - CHINA - - F0-1F-AF (hex) Dell Inc - F01FAF (base 16) Dell Inc - one dell way - Round rock Texas 78682 - UNITED STATES - - F0-21-9D (hex) Cal-Comp Electronics & Communications Company Ltd. - F0219D (base 16) Cal-Comp Electronics & Communications Company Ltd. - No. 147, Sec. 3, Beishen Rd., Shenkeng Dist., - New Taipei City 222 - Taipei 222 - TAIWAN, PROVINCE OF CHINA - - F0-23-29 (hex) SHOWA DENKI CO.,LTD. - F02329 (base 16) SHOWA DENKI CO.,LTD. - 1-25 - Shinden Kitamachi - Daito-city Osaka 574-0052 - JAPAN - - F0-24-05 (hex) OPUS High Technology Corporation - F02405 (base 16) OPUS High Technology Corporation - 1st Floor, No. 367, Gaocui Road - Hsinchu City 30064 - TAIWAN, PROVINCE OF CHINA - - F0-24-08 (hex) Talaris (Sweden) AB - F02408 (base 16) Talaris (Sweden) AB - Taljs Sodra Industriomrade - Flen 64284 - SWEDEN - - F0-24-75 (hex) Apple - F02475 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-25-72 (hex) CISCO SYSTEMS, INC. - F02572 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - F0-25-B7 (hex) Samsung Electro Mechanics co., LTD. - F025B7 (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - F0-26-4C (hex) Dr. Sigrist AG - F0264C (base 16) Dr. Sigrist AG - Hofurlistrasse 1 - Ennetbürgen 6373 - SWITZERLAND - - F0-27-65 (hex) Murata Manufactuaring Co.,Ltd. - F02765 (base 16) Murata Manufactuaring Co.,Ltd. - 1-10-1 Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - F0-29-29 (hex) Cisco - F02929 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F0-2A-23 (hex) Creative Next Design - F02A23 (base 16) Creative Next Design - 6-6-15, Kaminopporo 3-jo, - Atsubetsu-ku - Sapporo-shi Hokkaido 004-0033 - JAPAN - - F0-2A-61 (hex) Waldo Networks, Inc. - F02A61 (base 16) Waldo Networks, Inc. - 4505 Spicewood Springs Rd - Suite 333 - Austin Texas 78759 - UNITED STATES - - F0-2F-D8 (hex) Bi2-Vision - F02FD8 (base 16) Bi2-Vision - 16-504, 21-ban, Shimomaruko 4-chome, Oota-ku - Tokyo 146-0092 - JAPAN - - F0-32-1A (hex) Mita-Teknik A/S - F0321A (base 16) Mita-Teknik A/S - Aktieselskabet af 12.12.2006 - Haandvaerkervej 1 - Roedkaersbro 8840 - DENMARK - - F0-37-A1 (hex) Huike Electronics (SHENZHEN) CO., LTD. - F037A1 (base 16) Huike Electronics (SHENZHEN) CO., LTD. - Huike industrial park,Minying industrial park,Shuitian country - Shiyan,Baoan District - SHENZHEN GUANGDONG 518108 - CHINA - - F0-3A-4B (hex) Bloombase, Inc. - F03A4B (base 16) Bloombase, Inc. - 955 Benecia Ave - Sunnyvale California 94085 - UNITED STATES - - F0-3A-55 (hex) Omega Elektronik AS - F03A55 (base 16) Omega Elektronik AS - Ege Serbest Bolgesi - Izmir 35410 - TURKEY - - F0-3D-29 (hex) Actility - F03D29 (base 16) Actility - 110 rue des Poissonniers - Paris Paris 75018 - FRANCE - - F0-3F-F8 (hex) R L Drake - F03FF8 (base 16) R L Drake - 1 Jake Brown Road - Old Bridge NJ 08857 - UNITED STATES - - F0-43-35 (hex) DVN(Shanghai)Ltd. - F04335 (base 16) DVN(Shanghai)Ltd. - 11F,Hechuan Building,2016 Yishan Rd, - Shanghai 201103 - CHINA - - F0-4A-2B (hex) PYRAMID Computer GmbH - F04A2B (base 16) PYRAMID Computer GmbH - Boetzinger Strasse 60 - Freiburg BW 79111 - GERMANY - - F0-4B-6A (hex) Scientific Production Association Siberian Arsenal, Ltd. - F04B6A (base 16) Scientific Production Association Siberian Arsenal, Ltd. - Bld.8A, Gorskiy Microdistrict - Novosibirsk 630073 - RUSSIAN FEDERATION - - F0-4B-F2 (hex) JTECH Communications, Inc. - F04BF2 (base 16) JTECH Communications, Inc. - 6413 Congress Ave. - Boca Raton FL 33487 - UNITED STATES - - F0-4D-A2 (hex) Dell Inc. - F04DA2 (base 16) Dell Inc. - One Dell way, MS RR5-45 - Round rock Texas 78682 - UNITED STATES - - F0-4F-7C (hex) PRIVATE - F04F7C (base 16) - - F0-58-49 (hex) CareView Communications - F05849 (base 16) CareView Communications - 405 State HWY 121 BYP - Suite B240 - Lewisville Texas 75067 - UNITED STATES - - F0-5A-09 (hex) Samsung Electronics Co.,Ltd - F05A09 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F0-5D-89 (hex) Dycon Limited - F05D89 (base 16) Dycon Limited - Unit D - Cwm Cynon Business Park - Mountain Ash Rhondda Cynon Taff CF45 4ER - UNITED KINGDOM - - F0-5D-C8 (hex) Duracell Powermat - F05DC8 (base 16) Duracell Powermat - 230 Park Ave, suit 910 - New York NY 10169 - UNITED STATES - - F0-5F-5A (hex) Getriebebau NORD GmbH and Co. KG - F05F5A (base 16) Getriebebau NORD GmbH and Co. KG - Rudolf-Diesel-Strasse 1 - Bargteheide Schleswig-Holstein 22941 - GERMANY - - F0-61-30 (hex) Advantage Pharmacy Services, LLC - F06130 (base 16) Advantage Pharmacy Services, LLC - 371A Highland Colony Parkway - Ridgeland MISSISSIPPI 39157 - UNITED STATES - - F0-62-0D (hex) Shenzhen Egreat Tech Corp.,Ltd - F0620D (base 16) Shenzhen Egreat Tech Corp.,Ltd - 4F,1Building,Chuangye Industrial park - Shasan,Shajing, - Shenzhen Guangdong 518104 - CHINA - - F0-62-81 (hex) ProCurve Networking by HP - F06281 (base 16) ProCurve Networking by HP - 8000 Foothills Blvd. - Roseville California 95747 - UNITED STATES - - F0-65-DD (hex) Primax Electronics Ltd. - F065DD (base 16) Primax Electronics Ltd. - 669, Ruey Kuang Road, Neihu - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - F0-68-53 (hex) Integrated Corporation - F06853 (base 16) Integrated Corporation - 3/F, Shun On Commercial Bldg., - 112-114 Des Voeux Road, C., - Cetnral, - HONG KONG - - F0-6B-CA (hex) Samsung Electronics Co.,Ltd - F06BCA (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F0-72-8C (hex) Samsung Electronics Co.,Ltd - F0728C (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F0-73-AE (hex) PEAK-System Technik - F073AE (base 16) PEAK-System Technik - Otto-Roehm-Str 69 - Darmstadt Hessen 64293 - GERMANY - - F0-76-1C (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - F0761C (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE - KUNSHAN SUZHOU 215300 - CHINA - - F0-77-65 (hex) Sourcefire, Inc - F07765 (base 16) Sourcefire, Inc - 9780 Patuxent Woods Drive - Columbia Maryland 21046 - UNITED STATES - - F0-77-D0 (hex) Xcellen - F077D0 (base 16) Xcellen - 15F KINS Tower 25-1,Jeongja-dong,Bungdang-gu, - Seongnam Gyeonggi 463811 - KOREA, REPUBLIC OF - - F0-78-16 (hex) Cisco - F07816 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F0-79-59 (hex) ASUSTek COMPUTER INC. - F07959 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd., Peitou - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - F0-7B-CB (hex) Hon Hai Precision Ind. Co.,Ltd. - F07BCB (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - F0-7D-68 (hex) D-Link Corporation - F07D68 (base 16) D-Link Corporation - No.289, Sinhu 3rd Rd., Neihu District, - Taipei City 114 - TAIWAN, PROVINCE OF CHINA - - F0-7F-06 (hex) Cisco - F07F06 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F0-7F-0C (hex) Leopold Kostal GmbH &Co. KG - F07F0C (base 16) Leopold Kostal GmbH &Co. KG - An der Bellmerei 10 - Luedenscheid NRW D-58513 - GERMANY - - F0-81-AF (hex) IRZ AUTOMATION TECHNOLOGIES LTD - F081AF (base 16) IRZ AUTOMATION TECHNOLOGIES LTD - Unit 9-10 27/F Seapower Tower - Concordia Plaza 1 Science Museum Rd,TsimShaTsui - Kowloon - HONG KONG - - F0-82-61 (hex) SAGEMCOM - F08261 (base 16) SAGEMCOM - 250 route de l'Empereur - RUEIL MALMAISON CEDEX hauts de seine 92848 - FRANCE - - F0-84-2F (hex) ADB Broadband Italia - F0842F (base 16) ADB Broadband Italia - VIALE SARCA 336 - MILANO ITALY 20126 - ITALY - - F0-84-C9 (hex) zte corporation - F084C9 (base 16) zte corporation - 12/F.,zte R&D building ,kejinan Road, - shenzhen guangdong 518057 - CHINA - - F0-8A-28 (hex) JIANGSU HENGSION ELECTRONIC S and T CO.,LTD - F08A28 (base 16) JIANGSU HENGSION ELECTRONIC S and T CO.,LTD - 4F,Building 3 - No.111 West Hanjiang Road,New North Hi-Tech District - ChangZhou Jiangsu 213125 - CHINA - - F0-8B-FE (hex) COSTEL.,CO.LTD - F08BFE (base 16) COSTEL.,CO.LTD - 223-39, Sangdaewon-Dong, Jungwon-Gu - Seongnam-si Kyunggi-Do 462-807 - KOREA, REPUBLIC OF - - F0-8C-FB (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - F08CFB (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - F0-8E-DB (hex) VeloCloud Networks - F08EDB (base 16) VeloCloud Networks - 720 University Ave. - Palo Alto CA 94301 - UNITED STATES - - F0-92-1C (hex) Hewlett Packard - F0921C (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - F0-93-3A (hex) NxtConect - F0933A (base 16) NxtConect - Schillerstrasse 4 - Bad Kissingen 97688 - GERMANY - - F0-93-C5 (hex) Garland Technology - F093C5 (base 16) Garland Technology - 2130 Oak Bend Lane - Garland TX 75040 - UNITED STATES - - F0-99-BF (hex) Apple - F099BF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-9C-BB (hex) RaonThink Inc. - F09CBB (base 16) RaonThink Inc. - 916, Byucksan Digital Valley 2-Cha, 481-10, Kasan-Dong, Kumcheon-Gu, - Seoul 153-783 - KOREA, REPUBLIC OF - - F0-9C-E9 (hex) Aerohive Networks Inc - F09CE9 (base 16) Aerohive Networks Inc - 330 Gibraltar Drive - Sunnyvale CA 94089 - UNITED STATES - - F0-9E-63 (hex) Cisco - F09E63 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F0-9F-C2 (hex) Ubiquiti Networks, Inc. - F09FC2 (base 16) Ubiquiti Networks, Inc. - 2580 Orchard Parkway - San Jose CA 95131 - UNITED STATES - - F0-A2-25 (hex) PRIVATE - F0A225 (base 16) - - F0-A7-64 (hex) GST Co., Ltd. - F0A764 (base 16) GST Co., Ltd. - #988-6, Gosaek-Dong, Gwonseon-Gu, - Suwon-Si Gyeonggi-Do 441-813 - KOREA, REPUBLIC OF - - F0-AB-54 (hex) MITSUMI ELECTRIC CO.,LTD. - F0AB54 (base 16) MITSUMI ELECTRIC CO.,LTD. - 2-11-2, Tsurumaki - Tama-shi Tokyo 206-8567 - JAPAN - - F0-AC-A4 (hex) HBC-radiomatic - F0ACA4 (base 16) HBC-radiomatic - Haller Str. 45-53 - Crailsheim Baden Wurttemberg 74564 - GERMANY - - F0-AD-4E (hex) Globalscale Technologies, Inc. - F0AD4E (base 16) Globalscale Technologies, Inc. - 5F, No. 2 Building, Minxing Industrial Park - Minkang Rd., Minzhi St., Baoan Dist. - Shenzhen Guangdong 518109 - CHINA - - F0-AE-51 (hex) Xi3 Corp - F0AE51 (base 16) Xi3 Corp - 299 S. Main St. - Suite 1300 - Salt Lake City UT 84111 - UNITED STATES - - F0-B0-52 (hex) Ruckus Wireless - F0B052 (base 16) Ruckus Wireless - 350 W Java Drive - Sunnyvale CA 94089 - UNITED STATES - - F0-B4-79 (hex) Apple - F0B479 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-B6-EB (hex) Poslab Technology Co., Ltd. - F0B6EB (base 16) Poslab Technology Co., Ltd. - 5F-1, No.490 Bannan Rd. - Taipei County - Jhonghe City 235 - TAIWAN, PROVINCE OF CHINA - - F0-BC-C8 (hex) MaxID (Pty) Ltd - F0BCC8 (base 16) MaxID (Pty) Ltd - 43 Homestead Road - Rivonia - Johannesburg Gauteng 2128 - SOUTH AFRICA - - F0-BD-F1 (hex) Sipod Inc. - F0BDF1 (base 16) Sipod Inc. - 4633 Old Ironsides Drive, #400 - Santa Clara CA 95054 - UNITED STATES - - F0-BF-97 (hex) Sony Corporation - F0BF97 (base 16) Sony Corporation - Gotenyama Tec. - 5-1-12 Kitashinagawa Shinagawa-ku - Tokyo 141-0001 - JAPAN - - F0-C1-F1 (hex) Apple, Inc. - F0C1F1 (base 16) Apple, Inc. - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-C2-4C (hex) Zhejiang FeiYue Digital Technology Co., Ltd - F0C24C (base 16) Zhejiang FeiYue Digital Technology Co., Ltd - Baoting Industrial Park, 531 Jiaogong Road - Hangzhou City Zhejiang Province 310012 - CHINA - - F0-C2-7C (hex) Mianyang Netop Telecom Equipment Co.,Ltd. - F0C27C (base 16) Mianyang Netop Telecom Equipment Co.,Ltd. - No.111,East section of Puming South Road, - Hi-tech zone, - Mianyang City Sichuan Province, 621000 - CHINA - - F0-C8-8C (hex) LeddarTech Inc. - F0C88C (base 16) LeddarTech Inc. - 2740 Einstein Street - Quebec City G1P 4S4 - CANADA - - F0-CB-A1 (hex) Apple - F0CBA1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-D1-4F (hex) LINEAR LLC - F0D14F (base 16) LINEAR LLC - 1950 CAMINO VIDA ROBLE #150 - CARLSBAD CA 92008-6517 - UNITED STATES - - F0-D1-A9 (hex) Apple - F0D1A9 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-D3-A7 (hex) CobaltRay Co., Ltd - F0D3A7 (base 16) CobaltRay Co., Ltd - Room 409,Humanteco Building,#281-16 - Seongsu-Dong,Seongdong-Gu - Seoul 133120 - KOREA, REPUBLIC OF - - F0-D3-E7 (hex) Sensometrix SA - F0D3E7 (base 16) Sensometrix SA - Rue Albert Richard 2 - Geneva GE 1201 - SWITZERLAND - - F0-D6-57 (hex) ECHOSENS - F0D657 (base 16) ECHOSENS - 30 Place d'Italie - PARIS 13 Ile de France 75013 - FRANCE - - F0-D7-67 (hex) Axema Passagekontroll AB - F0D767 (base 16) Axema Passagekontroll AB - Box 90 215 - Stockholm 120 23 - SWEDEN - - F0-DA-7C (hex) RLH INDUSTRIES,INC. - F0DA7C (base 16) RLH INDUSTRIES,INC. - 936 N. MAIN ST. - ORANGE CA 92867 - UNITED STATES - - F0-DB-30 (hex) Yottabyte - F0DB30 (base 16) Yottabyte - 1750 S. Telegraph Road - Suite 200 - Bloomfield Twp. MI 48302 - UNITED STATES - - F0-DB-E2 (hex) Apple - F0DBE2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-DB-F8 (hex) Apple - F0DBF8 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-DC-E2 (hex) Apple - F0DCE2 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-DE-71 (hex) Shanghai EDO Technologies Co.,Ltd. - F0DE71 (base 16) Shanghai EDO Technologies Co.,Ltd. - Unit 12302, Building 12,498 Guoshoujing Road, Pudong New Area - Shanghai 201203 - CHINA - - F0-DE-B9 (hex) ShangHai Y&Y Electronics Co., Ltd - F0DEB9 (base 16) ShangHai Y&Y Electronics Co., Ltd - No.3, 588 Tianxiong Road, Shanghai International Medical Zone(SIMZ), - PuDong New District - Shanghai 201318 - CHINA - - F0-DE-F1 (hex) Wistron InfoComm (Kunshan)Co - F0DEF1 (base 16) Wistron InfoComm (Kunshan)Co - 168KunShan, - JiangSu 215300 - CHINA - - F0-E5-C3 (hex) Drägerwerk AG & Co. KG aA - F0E5C3 (base 16) Drägerwerk AG & Co. KG aA - Moislinger Allee 53-55 - Luebeck Germany 23452 - GERMANY - - F0-E7-7E (hex) Samsung Electronics Co.,Ltd - F0E77E (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F0-EB-D0 (hex) Shanghai Feixun Communication Co.,Ltd. - F0EBD0 (base 16) Shanghai Feixun Communication Co.,Ltd. - Building 90, No. 4855, Guangfulin Road - Songjiang District - Shanghai 201616 - CHINA - - F0-EC-39 (hex) Essec - F0EC39 (base 16) Essec - Schoebroekstraat 48 - Paal Limburg 3583 - BELGIUM - - F0-ED-1E (hex) Bilkon Bilgisayar Kontrollu Cih. Im.Ltd. - F0ED1E (base 16) Bilkon Bilgisayar Kontrollu Cih. Im.Ltd. - Gersan Sanayi Sitesi 658.Sokak No:16 - YENIMAHALLE- BATIKENT - ANKARA 06370 - TURKEY - - F0-EE-BB (hex) VIPAR GmbH - F0EEBB (base 16) VIPAR GmbH - Lichtenbergstrasse 8 - Garching bei Muenchen Bavaria 85748 - GERMANY - - F0-F0-02 (hex) Hon Hai Precision Ind. Co.,Ltd. - F0F002 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - F0-F2-60 (hex) Mobitec AB - F0F260 (base 16) Mobitec AB - Box 97 - Herrljunga VG 52421 - SWEDEN - - F0-F3-36 (hex) TP-LINK TECHNOLOGIES CO.,LTD - F0F336 (base 16) TP-LINK TECHNOLOGIES CO.,LTD - Building 24 (floors 1,3,4,5) and 28 (floors1-4) - Central Science and Technology Park - Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 - CHINA - - F0-F5-AE (hex) Adaptrum Inc. - F0F5AE (base 16) Adaptrum Inc. - 25 E Trimble Rd. - San Jose California 95131 - UNITED STATES - - F0-F6-1C (hex) Apple - F0F61C (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F0-F6-44 (hex) Whitesky Science & Technology Co.,Ltd. - F0F644 (base 16) Whitesky Science & Technology Co.,Ltd. - Room301,Building7,NO.6,Lane365 - XinHua Road,ChangNing District - Shanghai 200052 - CHINA - - F0-F6-69 (hex) Motion Analysis Corporation - F0F669 (base 16) Motion Analysis Corporation - 3617 Westwind Blvd. - Santa Rosa CA 95403 - UNITED STATES - - F0-F7-55 (hex) CISCO SYSTEMS, INC. - F0F755 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - F0-F7-B3 (hex) Phorm - F0F7B3 (base 16) Phorm - 222 Regent Street - London W1B 5TR - UNITED KINGDOM - - F0-F8-42 (hex) KEEBOX, Inc. - F0F842 (base 16) KEEBOX, Inc. - 10 Poppy Trail - Rolling Hills California 90274 - UNITED STATES - - F0-F9-F7 (hex) IES GmbH & Co. KG - F0F9F7 (base 16) IES GmbH & Co. KG - Darmcher Grund 22 - Meinerzhagen 58540 - GERMANY - - F0-FD-A0 (hex) Acurix Networks LP - F0FDA0 (base 16) Acurix Networks LP - PO Box 3838 - Shortland St - Auckland AKL 1021 - NEW ZEALAND - - F0-FE-6B (hex) Shanghai High-Flying Electronics Technology Co., Ltd - F0FE6B (base 16) Shanghai High-Flying Electronics Technology Co., Ltd - Room 1002 ,#1Building,No.3000 Longdong Avenue,Pudong District,Shanghai,China - shanghai shanghai 201203 - CHINA - - F4-03-04 (hex) Google - F40304 (base 16) Google - 1600 Amphitheatre Pkwy - Mt. View CA 94043 - UNITED STATES - - F4-03-21 (hex) BeNeXt B.V. - F40321 (base 16) BeNeXt B.V. - Ter Gouwstraat 3 - Amsterdam NH 1093JX - NETHERLANDS - - F4-03-2F (hex) Reduxio Systems - F4032F (base 16) Reduxio Systems - 2 Granit St - Petach Tikvah 4951446 - ISRAEL - - F4-04-4C (hex) ValenceTech Limited - F4044C (base 16) ValenceTech Limited - Unit 1, 20/F., APEC Plaza - 49 Hoi Yuen Road, Kwun Tong, Kowloon - HONG KONG NIL - CHINA - - F4-06-69 (hex) Intel Corporate - F40669 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - F4-06-8D (hex) devolo AG - F4068D (base 16) devolo AG - Charlottenburger Allee 60 - Aachen NRW 52068 - GERMANY - - F4-06-A5 (hex) Hangzhou Bianfeng Networking Technology Co., Ltd. - F406A5 (base 16) Hangzhou Bianfeng Networking Technology Co., Ltd. - BlockC,2F,Building B,Paradise Software Park - No3 Xidoumen Road - Hangzhou Zhejiang 310012 - CHINA - - F4-09-D8 (hex) Samsung Electro Mechanics co., LTD. - F409D8 (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - F4-0B-93 (hex) Research In Motion - F40B93 (base 16) Research In Motion - 295 Phillip Street - Waterloo Ontario N2L 5R9 - CANADA - - F4-0E-11 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - F40E11 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - F4-0F-1B (hex) Cisco - F40F1B (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F4-0F-9B (hex) WAVELINK - F40F9B (base 16) WAVELINK - #701, Dongyoung Venture'stel 3rd, 202-4, - Anyang-dong, Manan-ku - Anyang-si Kyungki-do 430-817 - KOREA, REPUBLIC OF - - F4-15-63 (hex) F5 Networks, Inc. - F41563 (base 16) F5 Networks, Inc. - 1322 North Whitman Lane - Liberty Lake WA 99019 - UNITED STATES - - F4-15-FD (hex) Shanghai Pateo Electronic Equipment Manufacturing Co., Ltd. - F415FD (base 16) Shanghai Pateo Electronic Equipment Manufacturing Co., Ltd. - 20th Floor, Metro Tower - No. 30 Tianyaoqiao Road - Xuhui District Shanghai 200030 - CHINA - - F4-1B-A1 (hex) Apple - F41BA1 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F4-1E-26 (hex) Simon-Kaloi Engineering - F41E26 (base 16) Simon-Kaloi Engineering - 31192 La Baya Drive Unit G - Westlake Village CA 91362 - UNITED STATES - - F4-1F-0B (hex) YAMABISHI Corporation - F41F0B (base 16) YAMABISHI Corporation - 3-14-12 Kamigou - Ebina-city KANAGAWA 243-0434 - JAPAN - - F4-1F-C2 (hex) Cisco - F41FC2 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F4-20-12 (hex) Cuciniale GmbH - F42012 (base 16) Cuciniale GmbH - Heuriedweg 65 - Lindau 88131 - GERMANY - - F4-28-33 (hex) MMPC Inc. - F42833 (base 16) MMPC Inc. - #F313, KAIST-ICC, 193 Munjiro Yuseong-gu - Daejeon 305-732 - KOREA, REPUBLIC OF - - F4-28-53 (hex) Zioncom Electronics (Shenzhen) Ltd. - F42853 (base 16) Zioncom Electronics (Shenzhen) Ltd. - A1&A2 Building,Lantian Technology Park, Xinyu Road - Xingqiao Henggang Block, ShajingStreet - Baoan District, Shenzhen Guangdong 518000 - CHINA - - F4-28-96 (hex) SPECTO PAINEIS ELETRONICOS LTDA - F42896 (base 16) SPECTO PAINEIS ELETRONICOS LTDA - RUA WALTER JOSE CORREA, AREA 12 - SERTAO DO MARUIN - SAO JOSE SANTA CATARINA 88122-035 - BRAZIL - - F4-29-81 (hex) vivo Mobile Communication Co., Ltd. - F42981 (base 16) vivo Mobile Communication Co., Ltd. - #283,BBK Road - Wusha,Chang'An DongGuan City,Guangdong, 523860 - CHINA - - F4-2C-56 (hex) SENOR TECH CO LTD - F42C56 (base 16) SENOR TECH CO LTD - No.165, Kangning St - Xizhi Dist - New Taipei City Taiwan 221 - TAIWAN, PROVINCE OF CHINA - - F4-36-E1 (hex) Abilis Systems SARL - F436E1 (base 16) Abilis Systems SARL - 3, chemin Pré Fleuri - Plan-Les-Ouates Geneva 1228 - SWITZERLAND - - F4-37-B7 (hex) Apple - F437B7 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F4-38-14 (hex) Shanghai Howell Electronic Co.,Ltd - F43814 (base 16) Shanghai Howell Electronic Co.,Ltd - 5-5/F, Bldg.1, No.788 Fengzhen Rd., - Shanghai 200434 - CHINA - - F4-3D-80 (hex) FAG Industrial Services GmbH - F43D80 (base 16) FAG Industrial Services GmbH - Kaiserstrasse 100 - Herzogenrath NRW 52134 - GERMANY - - F4-3E-61 (hex) Shenzhen Gongjin Electronics Co., Ltd - F43E61 (base 16) Shenzhen Gongjin Electronics Co., Ltd - 2F Baiying Building - 1019# Naihai RD, Nanshan Section - Shenzhen Guangdong 518067 - CHINA - - F4-3E-9D (hex) Benu Networks, Inc. - F43E9D (base 16) Benu Networks, Inc. - 300 Concord Rd., Suite #110 - Billerica MA 01821 - UNITED STATES - - F4-42-27 (hex) S & S Research Inc. - F44227 (base 16) S & S Research Inc. - 89 Access Rd #10 - Norwood MA 02062 - UNITED STATES - - F4-44-50 (hex) BND Co., Ltd. - F44450 (base 16) BND Co., Ltd. - 573-13 Bokhyeon-dong, Buk-gu - IT-convergence BLDG. 10F - Daegu 702-020 - KOREA, REPUBLIC OF - - F4-45-ED (hex) Portable Innovation Technology Ltd. - F445ED (base 16) Portable Innovation Technology Ltd. - 601-602, 6/F Park Building, - 476 Castle Peak Road, - Kowloon - HONG KONG - - F4-47-13 (hex) Leading Public Performance Co., Ltd. - F44713 (base 16) Leading Public Performance Co., Ltd. - 137/77-78 Moo 1 Nanthanagarden Soi 12 Pathum-Rangsit Road Banklang Muang Pathumthani 12000 Thailand - Pathumthani Pathumthani 12000 - THAILAND - - F4-47-2A (hex) Nanjing Rousing Sci. and Tech. Industrial Co., Ltd - F4472A (base 16) Nanjing Rousing Sci. and Tech. Industrial Co., Ltd - A630,F6,NO.58 Nanhu Road,Jianye District - Nanjing Jiangsu 210017 - CHINA - - F4-48-48 (hex) Amscreen Group Ltd - F44848 (base 16) Amscreen Group Ltd - Paragon Business Park - Chorley New Road, Horwich - Bolton Lancs BL6 6HG - UNITED KINGDOM - - F4-4E-05 (hex) Cisco - F44E05 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F4-4E-FD (hex) Actions Semiconductor Co.,Ltd.(Cayman Islands) - F44EFD (base 16) Actions Semiconductor Co.,Ltd.(Cayman Islands) - Po Box 309GT,Ugland House,South Church Street, - George Town Grand Cayman - CAYMAN ISLANDS - - F4-50-EB (hex) Telechips Inc - F450EB (base 16) Telechips Inc - KORAD Bldg,1000-12, Daechi-Dong, Gangnam-Gu, - Seoul 135-280 - KOREA, REPUBLIC OF - - F4-52-14 (hex) Mellanox Technologies, Inc. - F45214 (base 16) Mellanox Technologies, Inc. - 350 Oakmead Parkway, Suite 100 - Sunnyvale California 94085 - UNITED STATES - - F4-54-33 (hex) Rockwell Automation - F45433 (base 16) Rockwell Automation - 1 Allen-Bradley Dr. - Mayfield Heights OH 44124-6118 - UNITED STATES - - F4-55-95 (hex) HENGBAO Corporation LTD. - F45595 (base 16) HENGBAO Corporation LTD. - 8th Floor,Tower B,Xinsheng Mansion No.5 Financial Street, - Xicheng District - Beijing 100140 - CHINA - - F4-55-9C (hex) Huawei Technologies Co., Ltd - F4559C (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - F4-55-E0 (hex) Niceway CNC Technology Co.,Ltd.Hunan Province - F455E0 (base 16) Niceway CNC Technology Co.,Ltd.Hunan Province - 5/F,Innovation-Undertaking Center,HuanBao Industrial Park,199#,ZhenHua Road, - Changsha Hunan 410116 - CHINA - - F4-57-3E (hex) Fiberhome Telecommunication Technologies Co.,LTD - F4573E (base 16) Fiberhome Telecommunication Technologies Co.,LTD - No.5 DongXin Road - Hongsan District - Wuhan Hubei 430074 - CHINA - - F4-58-42 (hex) Boxx TV Ltd - F45842 (base 16) Boxx TV Ltd - Suite 17, Imperial Studios - 3-9 Imperial Road - London SW6 2AG - UNITED KINGDOM - - F4-5F-69 (hex) Matsufu Electronics distribution Company - F45F69 (base 16) Matsufu Electronics distribution Company - Suites 1601~3, Kinwick Centre, 32 Hollywood Road, Hong Kong - No.11, Guanglida Building, Nobile Plaza, Qianjin Rd, - Shanghai, China - HONG KONG - - F4-5F-D4 (hex) Cisco SPVTG - F45FD4 (base 16) Cisco SPVTG - 5030 Sugarloaf Pkwy - Lawrenceville GA 30044 - UNITED STATES - - F4-5F-F7 (hex) DQ Technology Inc. - F45FF7 (base 16) DQ Technology Inc. - 5111 Johnson Drive - Pleasanton CA 94588 - UNITED STATES - - F4-60-0D (hex) Panoptic Technology, Inc - F4600D (base 16) Panoptic Technology, Inc - 587 W Eau Gallie Blvd - Suite 104 - Melbourne FL 32935 - UNITED STATES - - F4-63-49 (hex) Diffon Corporation - F46349 (base 16) Diffon Corporation - Digital Tower Aston 1505 - 505-15 Gasan, Guemcheon - Seoul 153803 - KOREA, REPUBLIC OF - - F4-64-5D (hex) Toshiba - F4645D (base 16) Toshiba - 2-9,Suehiro-Cho - Ome Tokyo 1988710 - JAPAN - - F4-6A-92 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD - F46A92 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD - Room 202,Building No.5,Section 30, - No.2 of Kefa Road,Nanshan District - Shenzhen Guangdong 518057 - CHINA - - F4-6A-BC (hex) Adonit Corp. Ltd. - F46ABC (base 16) Adonit Corp. Ltd. - 10689 Rm. A, 9F, No.107 Sec.4 Ren-Ai Rd., - Da-An Dist. - Taipei 10689 - TAIWAN, PROVINCE OF CHINA - - F4-6D-04 (hex) ASUSTek COMPUTER INC. - F46D04 (base 16) ASUSTek COMPUTER INC. - 15,Li-Te Rd.,Peitou, - Taipei 112 - TAIWAN, PROVINCE OF CHINA - - F4-6D-E2 (hex) zte corporation - F46DE2 (base 16) zte corporation - 12/F.,R&D building,kejinan Road,Shenzhen,P.R.China - shenzhen guangdong 518057 - CHINA - - F4-73-CA (hex) Conversion Sound Inc. - F473CA (base 16) Conversion Sound Inc. - 960 N. Northwest Hwy - Park Ridge IL 60068 - UNITED STATES - - F4-76-26 (hex) Viltechmeda UAB - F47626 (base 16) Viltechmeda UAB - Kalvariju 125 - Vilnius LT-08221 - LITHUANIA - - F4-7A-4E (hex) Woojeon&Handan - F47A4E (base 16) Woojeon&Handan - 569-12, Gasan-dong, - Geumchon-gu - Seoul 153-803 - KOREA, REPUBLIC OF - - F4-7A-CC (hex) SolidFire, Inc. - F47ACC (base 16) SolidFire, Inc. - 1620 Pearl Street - Suite 200 - Boulder Colorado 80302 - UNITED STATES - - F4-7B-5E (hex) Samsung Eletronics Co., Ltd - F47B5E (base 16) Samsung Eletronics Co., Ltd - 416, Maetan 3dong, Yeongtong-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - F4-7F-35 (hex) CISCO SYSTEMS, INC. - F47F35 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - F4-81-39 (hex) CANON INC. - F48139 (base 16) CANON INC. - 30-2 Shimomaruko 3-chome, - Ohta-ku Tokyo 146-8501 - JAPAN - - F4-87-71 (hex) Infoblox - F48771 (base 16) Infoblox - 4750 Patrick Henry Drive - Santa Clara California 95054 - UNITED STATES - - F4-8E-09 (hex) Nokia Corporation - F48E09 (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu Ou 90230 - FINLAND - - F4-90-CA (hex) Tensorcom - F490CA (base 16) Tensorcom - 5900 Pastuer Ct., Suite 105 - Carlsbad CA 92008 - UNITED STATES - - F4-90-EA (hex) Deciso B.V. - F490EA (base 16) Deciso B.V. - Burgemeester Mijslaan 2 - Middelharnis Zuid Holland 3241 XA - NETHERLANDS - - F4-94-61 (hex) NexGen Storage - F49461 (base 16) NexGen Storage - 400 Centennial Blvd. - Louisville CO 80027 - UNITED STATES - - F4-94-66 (hex) CountMax, ltd - F49466 (base 16) CountMax, ltd - 11 Titova str. - poselok Lesnoy Moscowskaya oblast 141231 - RUSSIAN FEDERATION - - F4-99-AC (hex) WEBER Schraubautomaten GmbH - F499AC (base 16) WEBER Schraubautomaten GmbH - Hans-Urmiller-Ring 56 - Wolfratshausen Bayern 82515 - GERMANY - - F4-9F-54 (hex) Samsung Electronics - F49F54 (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F4-9F-F3 (hex) Huawei Technologies Co., Ltd - F49FF3 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - F4-A2-94 (hex) EAGLE WORLD DEVELOPMENT CO., LIMITED - F4A294 (base 16) EAGLE WORLD DEVELOPMENT CO., LIMITED - 1F, CMA Bldg., 64 Connaught Road Central - Hong Kong 00852 - HONG KONG - - F4-A5-2A (hex) Hawa Technologies Inc - F4A52A (base 16) Hawa Technologies Inc - 336 Hayes St - San Francisco California 94102 - UNITED STATES - - F4-AC-C1 (hex) CISCO SYSTEMS, INC. - F4ACC1 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - F4-B1-64 (hex) Lightning Telecommunications Technology Co. Ltd - F4B164 (base 16) Lightning Telecommunications Technology Co. Ltd - Room 1302, Tian¡¯an Hi-Tech Plaza Tower A, Futian District, - ShenZhen GuangDong 518040 - CHINA - - F4-B3-81 (hex) WindowMaster A/S - F4B381 (base 16) WindowMaster A/S - Skelstedet 13 - Vedbaek 2950 - DENMARK - - F4-B5-2F (hex) Juniper networks - F4B52F (base 16) Juniper networks - 1194 N. Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - F4-B5-49 (hex) Yeastar Technology Co., Ltd. - F4B549 (base 16) Yeastar Technology Co., Ltd. - Room202, No.23 Wanghai Road, 2nd Software Park, - Xiamen Fujian 361006 - CHINA - - F4-B6-E5 (hex) TerraSem Co.,Ltd - F4B6E5 (base 16) TerraSem Co.,Ltd - 9,Gwahaksaneop 5-ro - Ohchang-Eup, Cheongwon-Gun - Cheongwon-Gu ChungBuk 363-885 - KOREA, REPUBLIC OF - - F4-B7-2A (hex) TIME INTERCONNECT LTD - F4B72A (base 16) TIME INTERCONNECT LTD - 6/F, Photonics Centre - 2 Science Park East Avenue, Shatin - HONG KONG - - F4-B7-E2 (hex) Hon Hai Precision Ind. Co.,Ltd. - F4B7E2 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road ,Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - F4-B8-5E (hex) Texas INstruments - F4B85E (base 16) Texas INstruments - 12500 TI Blvd - Dallas Texas 75243 - UNITED STATES - - F4-BD-7C (hex) Chengdu jinshi communication Co., LTD - F4BD7C (base 16) Chengdu jinshi communication Co., LTD - No. 108 #1-2-505, Eastern 5 Section, First Ring Road, JinJiang District, - Chengdu, Chongqing, PROC - Chengdu Chongqing 610000 - CHINA - - F4-C4-47 (hex) Coagent International Enterprise Limited - F4C447 (base 16) Coagent International Enterprise Limited - FLAT/RM 2 6F CROWN TND BLDG 106 HOW MING ST KWUN TONG - Hong Kong 528133 - CHINA - - F4-C6-D7 (hex) blackned GmbH - F4C6D7 (base 16) blackned GmbH - Am Hartholz 21 - Alling Bavaria 82239 - GERMANY - - F4-C7-14 (hex) Shenzhen Huawei Communication Technologies Co., Ltd - F4C714 (base 16) Shenzhen Huawei Communication Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen Guangdong 518108 - CHINA - - F4-C7-95 (hex) WEY Elektronik AG - F4C795 (base 16) WEY Elektronik AG - Dorfstrasse 57 - Unterengstringen Zurich 8103 - SWITZERLAND - - F4-CA-E5 (hex) FREEBOX SA - F4CAE5 (base 16) FREEBOX SA - 8 rue de la Ville l'Eveque - PARIS IdF 75008 - FRANCE - - F4-CD-90 (hex) Vispiron Rotec GmbH - F4CD90 (base 16) Vispiron Rotec GmbH - Frankfurter Ring 224 - München Bayern 80807 - GERMANY - - F4-CE-46 (hex) Hewlett-Packard Company - F4CE46 (base 16) Hewlett-Packard Company - 11445 Compaq Center Drive - Mailcode 6.3.049 - Houston Texas 77070 - UNITED STATES - - F4-CF-E2 (hex) Cisco - F4CFE2 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F4-D0-32 (hex) Yunnan Ideal Information&Technology.,Ltd - F4D032 (base 16) Yunnan Ideal Information&Technology.,Ltd - The 1st Floor, Building Four ,JingdianMingju,Haiyuanzhong road, - High Tech Devolopment Zone - Kunming Yunnan 650106 - CHINA - - F4-D2-61 (hex) SEMOCON Co., Ltd - F4D261 (base 16) SEMOCON Co., Ltd - B-19F, Gunpo IT Valley, Dangjeong-dong, 17, Gosan-ro 148beon-gil, - Gunpo-si Gyeonggi-do 435-833 - KOREA, REPUBLIC OF - - F4-D9-FB (hex) Samsung Electronics CO., LTD - F4D9FB (base 16) Samsung Electronics CO., LTD - 416, Maetan-3dong, Yeongtong-gu, - Suwon-City Gyeonggi-do 443-742 - Suwon Gyeonggi-do 443-742 - KOREA, REPUBLIC OF - - F4-DC-4D (hex) Beijing CCD Digital Technology Co., Ltd - F4DC4D (base 16) Beijing CCD Digital Technology Co., Ltd - 107 Dongsi North Street, Dongcheng District, - Beijing Tian Hai Commercial Building, Room 802, Block A - Beijing 100007 - CHINA - - F4-DC-DA (hex) Zhuhai Jiahe Communication Technology Co., limited - F4DCDA (base 16) Zhuhai Jiahe Communication Technology Co., limited - 4/F,East Of B5,Sourth Software Park,Tangjia, - Zhuhai Guangdong 519085 - CHINA - - F4-DC-F9 (hex) Huawei Technologies Co., Ltd - F4DCF9 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, - Tangtou 3nd Industrial Estate,Shiyan Baoan District, - Shenzhen GuangDong 518057 - CHINA - - F4-DD-9E (hex) GoPro - F4DD9E (base 16) GoPro - 3000 Clearview Way - San Mateo CA 94402 - UNITED STATES - - F4-E1-42 (hex) Delta Elektronika BV - F4E142 (base 16) Delta Elektronika BV - Vissersdijk 4 - Zierikzee 4301 ND - NETHERLANDS - - F4-E3-FB (hex) Huawei Technologies Co., Ltd - F4E3FB (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen GuangDong 518057 - CHINA - - F4-E6-D7 (hex) Solar Power Technologies, Inc. - F4E6D7 (base 16) Solar Power Technologies, Inc. - 3006 Bee Caves Rd. - Suite A-330 - Austin Texas 78746 - UNITED STATES - - F4-E9-D4 (hex) QLogic Corporation - F4E9D4 (base 16) QLogic Corporation - 26650 Aliso Viejo Parkway - Aliso Viejo California 92656 - UNITED STATES - - F4-EA-67 (hex) CISCO SYSTEMS, INC. - F4EA67 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - F4-EC-38 (hex) TP-LINK TECHNOLOGIES CO., LTD. - F4EC38 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - 1-6F, Building 2, Pingshandayuan Industrial, South Zone, - Taoyuan Street, Nanshan District, - Shenzhen Guangdong 518000 - CHINA - - F4-EE-14 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - F4EE14 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. - Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan - Shenzhen Guangdong 518057 - CHINA - - F4-F1-5A (hex) Apple - F4F15A (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F4-F1-E1 (hex) Motorola Mobility LLC - F4F1E1 (base 16) Motorola Mobility LLC - 222 Merchandise Mart Plaza, Suite 1800 - Chicago IL 60654 - UNITED STATES - - F4-F2-6D (hex) TP-LINK TECHNOLOGIES CO.,LTD. - F4F26D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. - Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park - Shennan Road, Nanshan - Shenzhen Guangdong 518057 - CHINA - - F4-F5-A5 (hex) Nokia corporation - F4F5A5 (base 16) Nokia corporation - Joensuunkatu 7 - Salo 24101 - FINLAND - - F4-F5-E8 (hex) Google - F4F5E8 (base 16) Google - 1600 Amphitheatre Parkway - Mountain View California 94043 - UNITED STATES - - F4-F6-46 (hex) Dediprog Technology Co. Ltd. - F4F646 (base 16) Dediprog Technology Co. Ltd. - 4F,No.7,Lane 143, Xinming Rd., - Neihu District - Taipei 114 - TAIWAN, PROVINCE OF CHINA - - F4-F9-51 (hex) Apple - F4F951 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F4-FC-32 (hex) Texas Instruments - F4FC32 (base 16) Texas Instruments - 12500 TI Boulevard - Dallas TX 75243 - UNITED STATES - - F4-FD-2B (hex) ZOYI Company - F4FD2B (base 16) ZOYI Company - 827-66 Yeoksam 1-dong, Second Floor - Gangnam-gu - Seoul Korea 135-935 - KOREA, REPUBLIC OF - - F8-01-13 (hex) Huawei Technologies Co., Ltd - F80113 (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park - Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - F8-02-78 (hex) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - F80278 (base 16) IEEE REGISTRATION AUTHORITY - Please see MAM public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - - F8-03-32 (hex) Khomp - F80332 (base 16) Khomp - Rua Joe Collaço, 253 - Sta Monica - Florianópolis Santa Catarina 88037-010 - BRAZIL - - F8-04-2E (hex) Samsung Electro Mechanics co., LTD. - F8042E (base 16) Samsung Electro Mechanics co., LTD. - 93Moo5T. Bangsamak - SEMTHAI. WELLGROW INDUSTRIAL ESTATE - Bangpakong Chachoengsao 24180 - THAILAND - - F8-05-1C (hex) DRS Imaging and Targeting Solutions - F8051C (base 16) DRS Imaging and Targeting Solutions - 100 N. Babcock St - Melbourne FL 32935 - UNITED STATES - - F8-0B-BE (hex) ARRIS Group, Inc. - F80BBE (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - F8-0B-D0 (hex) Datang Telecom communication terminal (Tianjin) Co., Ltd. - F80BD0 (base 16) Datang Telecom communication terminal (Tianjin) Co., Ltd. - Garden East Roadon the 15th, - Kuang Yee Building, 4th Floor - Haidian District Beijing 100191 - CHINA - - F8-0C-F3 (hex) LG Electronics - F80CF3 (base 16) LG Electronics - 60-39 , Kasan-dong, Gumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - F8-0D-43 (hex) Hon Hai Precision Ind. Co., Ltd. - F80D43 (base 16) Hon Hai Precision Ind. Co., Ltd. - GuangDongShenZhen - ShenZhen GuangDong 518109 - CHINA - - F8-0D-EA (hex) ZyCast Technology Inc. - F80DEA (base 16) ZyCast Technology Inc. - No.33, Lane 181, Chung Hwa Road, - Section 4, - Hsin Chu 30060 - TAIWAN, PROVINCE OF CHINA - - F8-0F-41 (hex) Wistron InfoComm(ZhongShan) Corporation - F80F41 (base 16) Wistron InfoComm(ZhongShan) Corporation - Torch High-tech Industrial Development Zone, - ZhongShan Guangdong 528437 - CHINA - - F8-0F-84 (hex) Natural Security SAS - F80F84 (base 16) Natural Security SAS - 165 Avenue de Bretagne - Lille 59000 - FRANCE - - F8-10-37 (hex) Atopia Systems, LP - F81037 (base 16) Atopia Systems, LP - 681 N. Plano Road - Suite 119 - Richardson TX 75082 - UNITED STATES - - F8-15-47 (hex) Avaya, Inc - F81547 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920-2311 - UNITED STATES - - F8-16-54 (hex) Intel Corporate - F81654 (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - F8-18-97 (hex) 2Wire - F81897 (base 16) 2Wire - 1764 Automation Parkway - San Jose CA 95131 - UNITED STATES - - F8-1A-67 (hex) TP-LINK TECHNOLOGIES CO., LTD. - F81A67 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, Shenzhen,China - shenzhen guangdong Province 518057 - CHINA - - F8-1C-E5 (hex) Telefonbau Behnke GmbH - F81CE5 (base 16) Telefonbau Behnke GmbH - Robert-Jungk-Str. 3 - Kirkel Saarland 66459 - GERMANY - - F8-1D-93 (hex) Longdhua(Beijing) Controls Technology Co.,Ltd - F81D93 (base 16) Longdhua(Beijing) Controls Technology Co.,Ltd - Room 1203,Lixiang Building, No.111 Zhichun Road,Haidian District, - Beijing 10086 - CHINA - - F8-1E-DF (hex) Apple - F81EDF (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - F8-22-85 (hex) Cypress Technology CO., LTD. - F82285 (base 16) Cypress Technology CO., LTD. - 6F-5, NO., 130 Jiankang Rd., - Zhonghe Dist. New Taipei City 23585 - TAIWAN, PROVINCE OF CHINA - - F8-24-41 (hex) Yeelink - F82441 (base 16) Yeelink - F10-B4, Bldg. B, International Innovation Park - 169 Songling Rd., Laoshan - Qingdao Shandong 266101 - CHINA - - F8-27-93 (hex) Apple, Inc - F82793 (base 16) Apple, Inc - 1 Infinite Loop - cupertino CA 95014 - UNITED STATES - - F8-2B-C8 (hex) Jiangsu Switter Co., Ltd - F82BC8 (base 16) Jiangsu Switter Co., Ltd - Room 512, Buliding 8, 118 Nanyuanbei Road - Canglang District - Suzhou City Jiangsu Province 215006 - CHINA - - F8-2E-DB (hex) RTW GmbH & Co. KG - F82EDB (base 16) RTW GmbH & Co. KG - Am Wassermann 25 - Cologne NRW 50829 - GERMANY - - F8-2F-5B (hex) eGauge Systems LLC - F82F5B (base 16) eGauge Systems LLC - 1510 28th St, Suite 205 - Boulder CO 80303 - UNITED STATES - - F8-2F-A8 (hex) Hon Hai Precision Ind. Co.,Ltd. - F82FA8 (base 16) Hon Hai Precision Ind. Co.,Ltd. - NO.1925,Nanle Road - Songjiang Export Processing Zone - Shanghai 201613 - CHINA - - F8-30-94 (hex) Alcatel-Lucent Telecom Limited - F83094 (base 16) Alcatel-Lucent Telecom Limited - The Quadrant, Stonehill Green - Westlea - SWINDON SN5 7DJ - UNITED KINGDOM - - F8-31-3E (hex) endeavour GmbH - F8313E (base 16) endeavour GmbH - Max-Planck-Str. 04 - Vreden NRW 48691 - GERMANY - - F8-33-76 (hex) Good Mind Innovation Co., Ltd. - F83376 (base 16) Good Mind Innovation Co., Ltd. - 20, Lane 200, Cheng Hu Rd. - Niao Song District. - Kaohsiung 833 - TAIWAN, PROVINCE OF CHINA - - F8-35-53 (hex) Magenta Research Ltd. - F83553 (base 16) Magenta Research Ltd. - 128 Litchfield Road - New Milford CT 06776 - UNITED STATES - - F8-35-DD (hex) Gemtek Technology Co., Ltd. - F835DD (base 16) Gemtek Technology Co., Ltd. - No. 1 Jen Ai Road Hsinchu Industrial Park - No. 15-1 Zhonghua Road, Hsinstrial Park - Hukou, Hsinchu 30352 - TAIWAN, PROVINCE OF CHINA - - F8-3D-4E (hex) Softlink Automation System Co., Ltd - F83D4E (base 16) Softlink Automation System Co., Ltd - No.12, Hi-tech South 7th Rd., - Hi-tech Park, Nanshan Dist. - Shenzhen GuangDong 518057 - CHINA - - F8-3D-FF (hex) Huawei Technologies Co., Ltd - F83DFF (base 16) Huawei Technologies Co., Ltd - Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District - Shenzhen Guangdong 518057 - CHINA - - F8-42-FB (hex) Yasuda Joho Co.,ltd. - F842FB (base 16) Yasuda Joho Co.,ltd. - 1-11-1 - Kaigan - Minato-ku Tokyo 105-0022 - JAPAN - - F8-43-60 (hex) PRIVATE - F84360 (base 16) - - F8-45-AD (hex) Konka Group Co., Ltd. - F845AD (base 16) Konka Group Co., Ltd. - Overseas Chinese Town Nanshan - shenzhen Guangdong 518053 - CHINA - - F8-46-2D (hex) SYNTEC Incorporation - F8462D (base 16) SYNTEC Incorporation - 3F, NO.105, Shing-shyue St., - Hsinchu 300 - TAIWAN, PROVINCE OF CHINA - - F8-47-2D (hex) X2gen Digital Corp. Ltd - F8472D (base 16) X2gen Digital Corp. Ltd - # 89, Singlong Rd - Taoyuan Hsien - Pin-Jhen City, 324 - TAIWAN, PROVINCE OF CHINA - - F8-48-97 (hex) Hitachi, Ltd. - F84897 (base 16) Hitachi, Ltd. - 27-18, Minami Oi 6-chome, Shinagawa-ku - Tokyo 140-8572 - JAPAN - - F8-4A-73 (hex) EUMTECH CO., LTD - F84A73 (base 16) EUMTECH CO., LTD - Room 1201, 115, Dongdeok-ro - Daegu 700-719 - KOREA, REPUBLIC OF - - F8-4A-7F (hex) Innometriks Inc - F84A7F (base 16) Innometriks Inc - 3654 Ocean Ranch Blvd - Oceanside Ca 92056 - UNITED STATES - - F8-4A-BF (hex) HUAWEI TECHNOLOGIES CO.,LTD - F84ABF (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian Longgang - Shenzhen Guangdong 518129 - CHINA - - F8-4F-57 (hex) Cisco - F84F57 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F8-50-63 (hex) Verathon - F85063 (base 16) Verathon - 20001 N Creek Pkwy - Bothell WA 98011 - UNITED STATES - - F8-51-6D (hex) Denwa Technology Corp. - F8516D (base 16) Denwa Technology Corp. - 1931 NW 150 TH AVE - Penbroke Pines Florida 33028 - UNITED STATES - - F8-52-DF (hex) VNL Europe AB - F852DF (base 16) VNL Europe AB - Finlandsgatan 10 - SE - Kista 164 74 - SWEDEN - - F8-54-AF (hex) ECI Telecom Ltd. - F854AF (base 16) ECI Telecom Ltd. - 30 Hasivim St. - Petah Tikva 49133 - ISRAEL - - F8-57-2E (hex) Core Brands, LLC - F8572E (base 16) Core Brands, LLC - 1800 South McDowell Blvd. - Petaluma CA 94954 - UNITED STATES - - F8-5B-C9 (hex) M-Cube Spa - F85BC9 (base 16) M-Cube Spa - Corso Cavour 2/2d - Trieste 34132 - ITALY - - F8-5C-45 (hex) IC Nexus Co. Ltd. - F85C45 (base 16) IC Nexus Co. Ltd. - 6F-1, No.3-2 Park Street - Nankang Software Park(NKSP), - Taipei 115 - TAIWAN, PROVINCE OF CHINA - - F8-5F-2A (hex) Nokia Corporation - F85F2A (base 16) Nokia Corporation - Yrttipellontie 6 - Oulu 90230 - FINLAND - - F8-62-AA (hex) xn systems - F862AA (base 16) xn systems - #917, Worldmerdian 2nd - Gasan-dong, Guemchun-gu - Seoul 153759 - KOREA, REPUBLIC OF - - F8-66-01 (hex) Suzhou Chi-tek information technology Co., Ltd - F86601 (base 16) Suzhou Chi-tek information technology Co., Ltd - Rm204Cã€204D, Building A7, - Biobay, No.218, Xinghu St, SIP - SuZhou Jiangsu 215123 - CHINA - - F8-66-D1 (hex) Hon Hai Precision Ind. Co., Ltd. - F866D1 (base 16) Hon Hai Precision Ind. Co., Ltd. - GuangDongShenZhen - ShenZhen GuangDong 518109 - CHINA - - F8-66-F2 (hex) CISCO SYSTEMS, INC. - F866F2 (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - F8-69-71 (hex) Seibu Electric Co., - F86971 (base 16) Seibu Electric Co., - 1458-7 - Hazama - Hachioji Tokyo 193-0941 - JAPAN - - F8-6E-CF (hex) Arcx Inc - F86ECF (base 16) Arcx Inc - 151 Amber St, Unit 1 - Markham ON L3R 3B3 - CANADA - - F8-71-FE (hex) The Goldman Sachs Group, Inc. - F871FE (base 16) The Goldman Sachs Group, Inc. - Christchurch Court | 10-15 Newgate Street - London London EC1A 7HD - UNITED KINGDOM - - F8-72-EA (hex) Cisco - F872EA (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F8-73-94 (hex) NETGEAR INC., - F87394 (base 16) NETGEAR INC., - 350 EAST PLUMERIA DRIVE - SAN JOSE CALIFORNIA 95134 - UNITED STATES - - F8-76-9B (hex) Neopis Co., Ltd. - F8769B (base 16) Neopis Co., Ltd. - #401 Neo bd., 196-44 Anyang7-Dong - Manan-Gu - Anyang Kyonggi-Do 430-857 - KOREA, REPUBLIC OF - - F8-7A-EF (hex) Rosonix Technology, Inc. - F87AEF (base 16) Rosonix Technology, Inc. - 10F, No.235, Sec. 4, Chengde Rd., - Shihlin District - Taipei Taiwan 11167 - TAIWAN, PROVINCE OF CHINA - - F8-7B-62 (hex) FASTWEL INTERNATIONAL CO., LTD. Taiwan Branch - F87B62 (base 16) FASTWEL INTERNATIONAL CO., LTD. Taiwan Branch - 6F., No.118, Ln. 235, Baociao Rd - Sindian City - Taipei County 231 Taipei - TAIWAN, PROVINCE OF CHINA - - F8-7B-7A (hex) ARRIS Group, Inc. - F87B7A (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suwanee GA 30024 - UNITED STATES - - F8-7B-8C (hex) Amped Wireless - F87B8C (base 16) Amped Wireless - 13089 Peyton Dr. #C307 - Chino Hills CA 91709 - UNITED STATES - - F8-81-1A (hex) OVERKIZ - F8811A (base 16) OVERKIZ - EUROPA 3 - Site d'Archamps - Archamps 74160 - FRANCE - - F8-84-79 (hex) Yaojin Technology(Shenzhen)Co.,Ltd - F88479 (base 16) Yaojin Technology(Shenzhen)Co.,Ltd - Yaojin Park, Shui Tian No.4 Industrial Area ShiYan Tow, - BaoAn - SHENZHEN GUANGDONG 518108 - CHINA - - F8-84-F2 (hex) Samsung Electronics Co.,Ltd - F884F2 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F8-8C-1C (hex) KAISHUN ELECTRONIC TECHNOLOGY CO., LTD. BEIJING - F88C1C (base 16) KAISHUN ELECTRONIC TECHNOLOGY CO., LTD. BEIJING - NO.1 FARM, HENGQIAO VILLAGE WEST, MACHIKOU TOWN, - CHANGPING DISTRICT - BEIJING 102200 - CHINA - - F8-8D-EF (hex) Tenebraex - F88DEF (base 16) Tenebraex - 27 Drydock Avenue - Boston MA 02210 - UNITED STATES - - F8-8E-85 (hex) COMTREND CORPORATION - F88E85 (base 16) COMTREND CORPORATION - 3F-1, NO. 10, LANE 609, - CHUNG HSIN ROAD, SEC 5, SAN CHUNG DIST. - NEW TAIPEI CITY 24159 - TAIWAN, PROVINCE OF CHINA - - F8-8F-CA (hex) Google Fiber, Inc - F88FCA (base 16) Google Fiber, Inc - 1600 Amphitheatre Parkway - Mountain View California 94043 - UNITED STATES - - F8-91-2A (hex) GLP German Light Products GmbH - F8912A (base 16) GLP German Light Products GmbH - Im Stöckmädle 13 - Karlsbad BW 76307 - GERMANY - - F8-93-F3 (hex) VOLANS - F893F3 (base 16) VOLANS - 3F IJU BD 770-13 YEOKSAM-DONG - GANGNAM-GU - SEOUL 135-928 - KOREA, REPUBLIC OF - - F8-95-50 (hex) Proton Products Chengdu Ltd - F89550 (base 16) Proton Products Chengdu Ltd - 1st Ring - Chengdu Sichuan 610051 - CHINA - - F8-95-C7 (hex) LG Electronics (Mobile Communications) - F895C7 (base 16) LG Electronics (Mobile Communications) - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-023 - KOREA, REPUBLIC OF - - F8-97-CF (hex) DAESHIN-INFORMATION TECHNOLOGY CO., LTD. - F897CF (base 16) DAESHIN-INFORMATION TECHNOLOGY CO., LTD. - 6F, Chungwon Bldg., 828-5 Yuksam-Dong,Kangnam-Gu, - Seoul 135935 - KOREA, REPUBLIC OF - - F8-99-55 (hex) Fortress Technology Inc - F89955 (base 16) Fortress Technology Inc - 51 Grand Marshall Drive - Scarborough Ontario M1B 5N6 - CANADA - - F8-9D-0D (hex) Control Technology Inc. - F89D0D (base 16) Control Technology Inc. - 7608 North Hudson Ave - Oklahoma City OK 73116 - UNITED STATES - - F8-9F-B8 (hex) YAZAKI Energy System Corporation - F89FB8 (base 16) YAZAKI Energy System Corporation - 1-7-1 YOKOI - Shimada -shi,Shizuoka 427-8555 - JAPAN - - F8-A0-3D (hex) Dinstar Technologies Co., Ltd. - F8A03D (base 16) Dinstar Technologies Co., Ltd. - Floor 6, Guoxing Building - Changxing Road, Nanshan District - shenzhen Guangdong 518052 - CHINA - - F8-A2-B4 (hex) RHEWA-WAAGENFABRIK August Freudewald GmbH &Co. KG - F8A2B4 (base 16) RHEWA-WAAGENFABRIK August Freudewald GmbH &Co. KG - Feldstr. 17 - Mettmann 40822 - GERMANY - - F8-A4-5F (hex) Beijing Xiaomi communications co.,ltd - F8A45F (base 16) Beijing Xiaomi communications co.,ltd - The Rainbow City of China Resources,NO 68,Qinghe Middle Street,Haidian District,Beijing,China 100085 - Beijing Beijing 100085 - CHINA - - F8-A9-63 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. - F8A963 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. - No.25, Third Avenue, A Zone, - Kunshan Comprehensive Free Trade Zone - KUNSHAN, Jiangsu SUZHOU 215300 - CHINA - - F8-A9-D0 (hex) LG Electronics - F8A9D0 (base 16) LG Electronics - 60-39, Gasan-dong, Geumcheon-gu - Seoul 153-801 - KOREA, REPUBLIC OF - - F8-A9-DE (hex) PUISSANCE PLUS - F8A9DE (base 16) PUISSANCE PLUS - 222 Impasse Louis Lépine - Z.I. Albasud - Secteur 3 - Montauban 82000 - FRANCE - - F8-AA-8A (hex) Axview Technology (Shenzhen) Co.,Ltd - F8AA8A (base 16) Axview Technology (Shenzhen) Co.,Ltd - NO 1, Mei Zhong Road, Futian District - SHENZHEN GUANGDONG 518049 - CHINA - - F8-AC-6D (hex) Deltenna Ltd - F8AC6D (base 16) Deltenna Ltd - First Floor Unit 2 - Bellinger Close - Chippenham Wiltshire SN15 1BN - UNITED KINGDOM - - F8-B1-56 (hex) Dell Inc - F8B156 (base 16) Dell Inc - one dell way - Round rock Texas 78682 - UNITED STATES - - F8-B2-F3 (hex) GUANGZHOU BOSMA TECHNOLOGY CO.,LTD - F8B2F3 (base 16) GUANGZHOU BOSMA TECHNOLOGY CO.,LTD - FL.3,A5,No.11 Kaiyuan Ave., Science City,Guangzhou,CHINA - Guangzhou GuangDong 510530 - CHINA - - F8-B5-99 (hex) Guangzhou CHNAVS Digital Technology Co.,Ltd - F8B599 (base 16) Guangzhou CHNAVS Digital Technology Co.,Ltd - Buliding C, industy base of digital home application and demonstration ,zhongyi road Guangzhou higher education mega center - Guangzhou Guangdong 510006 - CHINA - - F8-BC-12 (hex) Dell Inc - F8BC12 (base 16) Dell Inc - one dell way - Round rock Texas 78682 - UNITED STATES - - F8-BC-41 (hex) Rosslare Enterprises Limited - F8BC41 (base 16) Rosslare Enterprises Limited - Flat 912 Wing Fat Industrial Building - 12 Wang Tai Road - Kowloon Bay Kowloon 00000 - HONG KONG - - F8-C0-01 (hex) Juniper Networks - F8C001 (base 16) Juniper Networks - 1194 N Mathilda Avenue - Sunnyvale CA 94089 - UNITED STATES - - F8-C0-91 (hex) Highgates Technology - F8C091 (base 16) Highgates Technology - 1415 Highgate Ave - Los Angeles CA 90042 - UNITED STATES - - F8-C2-88 (hex) Cisco - F8C288 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - F8-C3-97 (hex) NZXT Corp. Ltd. - F8C397 (base 16) NZXT Corp. Ltd. - 13164 E. Temple Ave. - City of Industry California 91746 - UNITED STATES - - F8-C6-78 (hex) Carefusion - F8C678 (base 16) Carefusion - 10020 Pacific Mesa Blvd - San Diego CA 92121 - UNITED STATES - - F8-C9-6C (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - F8C96C (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - F8-CF-C5 (hex) Motorola Mobility LLC, a Lenovo Company - F8CFC5 (base 16) Motorola Mobility LLC, a Lenovo Company - 222 West Merchandise Mart Plaza - Suite 1800 - Chicago IL 60654 - UNITED STATES - - F8-D0-AC (hex) Sony Computer Entertainment Inc. - F8D0AC (base 16) Sony Computer Entertainment Inc. - 1-7-1 Konan - Minato-ku Tokyo 108-0075 - JAPAN - - F8-D0-BD (hex) Samsung Electronics Co.,Ltd - F8D0BD (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - F8-D1-11 (hex) TP-LINK TECHNOLOGIES CO., LTD. - F8D111 (base 16) TP-LINK TECHNOLOGIES CO., LTD. - Building 24 (floors 1,3,4,5) and 28 (floors1-4) - Central Science and Technology Park,Shennan Rd, - Shenzhen Guangdong 518057 - CHINA - - F8-D3-A9 (hex) AXAN Networks - F8D3A9 (base 16) AXAN Networks - 2F Myungjin-Bldg Daechi-Dong Gangnam-Gu - Seoul 135-845 - KOREA, REPUBLIC OF - - F8-D4-62 (hex) Pumatronix Equipamentos Eletronicos Ltda. - F8D462 (base 16) Pumatronix Equipamentos Eletronicos Ltda. - Rua Bartolomeu Lourenco de Gusmao 2021 - Curitiba PR 81650050 - BRAZIL - - F8-D7-56 (hex) Simm Tronic Limited - F8D756 (base 16) Simm Tronic Limited - Unit 3, Waterside - Charlton Mead Lane - Hoddesdon Hertfordshire EN11 0QR - UNITED KINGDOM - - F8-D7-BF (hex) REV Ritter GmbH - F8D7BF (base 16) REV Ritter GmbH - Frankenstra - M Bavaria 63776 - GERMANY - - F8-DA-DF (hex) EcoTech, Inc. - F8DADF (base 16) EcoTech, Inc. - 999 Postal Road - Suite 100 - Allentown PA 18109 - UNITED STATES - - F8-DA-E2 (hex) Beta LaserMike - F8DAE2 (base 16) Beta LaserMike - 8001 Technology Blvd - Dayton OH 45424 - UNITED STATES - - F8-DA-F4 (hex) Taishan Online Technology Co., Ltd. - F8DAF4 (base 16) Taishan Online Technology Co., Ltd. - 4/F Fangda Building, South Area, Hi-tech Industial Park, - Shenzhen Guangdong 518057 - CHINA - - F8-DB-4C (hex) PNY Technologies, INC. - F8DB4C (base 16) PNY Technologies, INC. - 100 Jefferson Road - Parsippany New Jersey 07054 - UNITED STATES - - F8-DB-7F (hex) HTC Corporation - F8DB7F (base 16) HTC Corporation - No.23 Xinghua Road - Taoyuan City - Taoyuan County 330 - TAIWAN, PROVINCE OF CHINA - - F8-DB-88 (hex) Dell Inc - F8DB88 (base 16) Dell Inc - one dell way - Round rock Texas 78682 - UNITED STATES - - F8-DC-7A (hex) Variscite LTD - F8DC7A (base 16) Variscite LTD - 60 Medinat Hayehudim st. - Hertzelia 46722 - ISRAEL - - F8-DF-A8 (hex) ZTE Corporation - F8DFA8 (base 16) ZTE Corporation - 12/F.,zte R&D building ,kejinan Road - shenzhen guangdong 518057 - CHINA - - F8-E0-79 (hex) Motorola Mobility LLC - F8E079 (base 16) Motorola Mobility LLC - 600 North US Highway 45 - Libertyville IL 60048 - UNITED STATES - - F8-E4-FB (hex) Actiontec Electronics, Inc - F8E4FB (base 16) Actiontec Electronics, Inc - 760 North Mary Ave - Sunnyvale CA 94085 - UNITED STATES - - F8-E7-B5 (hex) µTech Tecnologia LTDA - F8E7B5 (base 16) µTech Tecnologia LTDA - Rua Lauro Linhares, 598 - Sala 10, Terceiro andar - Florianopolis Santa Catarina 88036-200 - BRAZIL - - F8-E8-11 (hex) HUAWEI TECHNOLOGIES CO.,LTD - F8E811 (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen - Shenzhen Guangdong 518129 - CHINA - - F8-E9-03 (hex) D-Link International - F8E903 (base 16) D-Link International - 1 Internal Business Park, #03-12 - The Synergy - Singapore 609917 - SINGAPORE - - F8-E9-68 (hex) Egker Kft. - F8E968 (base 16) Egker Kft. - Szuglo u. 49. - Budapest 1145 - HUNGARY - - F8-EA-0A (hex) Dipl.-Math. Michael Rauch - F8EA0A (base 16) Dipl.-Math. Michael Rauch - Kapellenstraße 31 - Bretten BaWü 75015 - GERMANY - - F8-ED-A5 (hex) ARRIS Group, Inc. - F8EDA5 (base 16) ARRIS Group, Inc. - 3871 Lakefield Drive - Suite 300 - Suwanee Georgia 30024 - UNITED STATES - - F8-F0-05 (hex) Newport Media Inc. - F8F005 (base 16) Newport Media Inc. - 1 Spectrum Pointe Drive Suite 225 - Newport Media Inc. - Lake Forest CA 92630 - UNITED STATES - - F8-F0-14 (hex) RackWare Inc. - F8F014 (base 16) RackWare Inc. - 44053 Fremont Blvd. - Fremont CA 94538 - UNITED STATES - - F8-F0-82 (hex) Orion Networks International, Inc - F8F082 (base 16) Orion Networks International, Inc - 715 Discovery Blvd, - Ste 502 - Cedar Park TX 78613 - UNITED STATES - - F8-F1-B6 (hex) Motorola Mobility LLC - F8F1B6 (base 16) Motorola Mobility LLC - 600 North US Highway 45 - Libertyville IL 60048 - UNITED STATES - - F8-F2-5A (hex) G-Lab GmbH - F8F25A (base 16) G-Lab GmbH - Schiffbaustrasse 10 - Zurich CH 8005 - SWITZERLAND - - F8-F7-D3 (hex) International Communications Corporation - F8F7D3 (base 16) International Communications Corporation - 11801 Pierce St. 2nd FL - Riverside CA 92505 - UNITED STATES - - F8-F7-FF (hex) SYN-TECH SYSTEMS INC - F8F7FF (base 16) SYN-TECH SYSTEMS INC - 100 FOUR POINTS WAY - TALLAHASSEE FL 32305 - UNITED STATES - - F8-FB-2F (hex) Santur Corporation - F8FB2F (base 16) Santur Corporation - 40931 Encyclopedia Circle - Fremont California 94538 - UNITED STATES - - F8-FE-5C (hex) Reciprocal Labs Corp - F8FE5C (base 16) Reciprocal Labs Corp - 3 S. Pinckney St. - Suite 815 - Madison WI 53703 - UNITED STATES - - F8-FE-A8 (hex) Technico Japan Corporation - F8FEA8 (base 16) Technico Japan Corporation - AM Building 9F, 2-5-3, - Shinjuku-ku - Tokyo 160-0022 - JAPAN - - F8-FF-5F (hex) Shenzhen Communication Technology Co.,Ltd - F8FF5F (base 16) Shenzhen Communication Technology Co.,Ltd - 2F,6 Block, Kupai inforport,No.2 Mengxi Street,(North)High-tech Industrial Park, - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - FC-00-12 (hex) Toshiba Samsung Storage Technolgoy Korea Corporation - FC0012 (base 16) Toshiba Samsung Storage Technolgoy Korea Corporation - 14 Floor, Bldg. No. 102, Digital Empire2, 486, Sin-dong, Yeongtong-gu, Suwon-si, - Su-won Gyeonggi 443-734 - KOREA, REPUBLIC OF - - FC-01-9E (hex) VIEVU - FC019E (base 16) VIEVU - 105 W. John St - Seattle WA 98119 - UNITED STATES - - FC-01-CD (hex) FUNDACION TEKNIKER - FC01CD (base 16) FUNDACION TEKNIKER - Avenida Otaola, 20 - Eibar Gipuzkoa 20600 - SPAIN - - FC-06-47 (hex) Cortland Research, LLC - FC0647 (base 16) Cortland Research, LLC - 12 S Main St., Ste 207 - PO Box 307 - Homer NY 13077 - UNITED STATES - - FC-07-A0 (hex) LRE Medical GmbH - FC07A0 (base 16) LRE Medical GmbH - Hofer Strasse 5 - Noerdlingen Bavaria 86720 - GERMANY - - FC-08-77 (hex) Prentke Romich Company - FC0877 (base 16) Prentke Romich Company - 1022 Heyl Rd - Wooster OH 44691 - UNITED STATES - - FC-09-D8 (hex) ACTEON Group - FC09D8 (base 16) ACTEON Group - ZAC Athelia IV - Avenue des Genevriers - La Ciotat France 13705 - FRANCE - - FC-09-F6 (hex) GUANGDONG TONZE ELECTRIC CO.,LTD - FC09F6 (base 16) GUANGDONG TONZE ELECTRIC CO.,LTD - No.12-12 Block,Jinyuan Industrical City,Chaoshan Road, - Shantou Guangdong 515021 - CHINA - - FC-0A-81 (hex) Zebra Technologies Inc - FC0A81 (base 16) Zebra Technologies Inc - 475 Half Day Road - Suite 500 - Lincolnshire IL 60069 - UNITED STATES - - FC-0F-E6 (hex) Sony Computer Entertainment Inc. - FC0FE6 (base 16) Sony Computer Entertainment Inc. - 1-7-1 Konan - Minato-ku Tokyo 108-0075 - JAPAN - - FC-10-BD (hex) Control Sistematizado S.A. - FC10BD (base 16) Control Sistematizado S.A. - Cra 43 N 31 52 - Medellin Antioquia 10101 - COLOMBIA - - FC-11-86 (hex) Logic3 plc - FC1186 (base 16) Logic3 plc - Rhodes Way - Watford Hertfordshire WD24 4YW - UNITED KINGDOM - - FC-13-49 (hex) Global Apps Corp. - FC1349 (base 16) Global Apps Corp. - 12F., No 225, Sec. 5 Nanjing E. Rd - Songshan Dist, - Taipei 105 - TAIWAN, PROVINCE OF CHINA - - FC-15-B4 (hex) Hewlett Packard - FC15B4 (base 16) Hewlett Packard - 11445 Compaq Center Drive - Houston Texas 77070 - UNITED STATES - - FC-16-07 (hex) Taian Technology(Wuxi) Co.,Ltd. - FC1607 (base 16) Taian Technology(Wuxi) Co.,Ltd. - Gaolang East Road No.29 - Wuxi Jiangsu 214000 - CHINA - - FC-17-94 (hex) InterCreative Co., Ltd - FC1794 (base 16) InterCreative Co., Ltd - 897-6, HoGye-Dong, DongAn-Gu, - AnYang-Si, GyeongGi-Do, 431-836 - KOREA, REPUBLIC OF - - FC-19-10 (hex) Samsung Electronics Co.,Ltd - FC1910 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - FC-19-D0 (hex) Cloud Vision Networks Technology Co.,Ltd. - FC19D0 (base 16) Cloud Vision Networks Technology Co.,Ltd. - F/9,Hechuan Building 2016 - Yishan Road - Shanghai 201103 - CHINA - - FC-1B-FF (hex) V-ZUG AG - FC1BFF (base 16) V-ZUG AG - Industriestrasse 66 - Zug 6301 - SWITZERLAND - - FC-1D-59 (hex) I Smart Cities HK Ltd - FC1D59 (base 16) I Smart Cities HK Ltd - Unit G,10/F,Phase 2,Yip Fat IND - BLDG,73-75HOI YUEN Road - 73-75 - HONG KONG - - FC-1D-84 (hex) Autobase - FC1D84 (base 16) Autobase - 1201, Biz Center, SKnTechno Park, 124, Sagimakgol-ro, Jungwon-gu, Seongnam-si, Gyeonggi-do - Seongnam Gyeonggi 462-721 - KOREA, REPUBLIC OF - - FC-1E-16 (hex) IPEVO corp - FC1E16 (base 16) IPEVO corp - 3F,No.53,Bo-ai Road - Taipei 100 - TAIWAN, PROVINCE OF CHINA - - FC-1F-19 (hex) SAMSUNG ELECTRO-MECHANICS CO., LTD. - FC1F19 (base 16) SAMSUNG ELECTRO-MECHANICS CO., LTD. - 314, Maetan3-Dong, Yeongtong-Gu - SUWON GYUNGGI-DO 443-743 - KOREA, REPUBLIC OF - - FC-1F-C0 (hex) EURECAM - FC1FC0 (base 16) EURECAM - BAT 9 - Miniparc - 6 Avenue des Andes - LES ULIS 91940 - FRANCE - - FC-22-9C (hex) Han Kyung I Net Co.,Ltd. - FC229C (base 16) Han Kyung I Net Co.,Ltd. - 3F,Seung Eun Bldg - 487-1 Geung-Dong - Yu Seong-Gu Dae Jeon 305-335 - KOREA, REPUBLIC OF - - FC-23-25 (hex) EosTek (Shenzhen) Co., Ltd. - FC2325 (base 16) EosTek (Shenzhen) Co., Ltd. - Room 306, Complex Building Tsinghua High-Tech Park - Nanshan District - Shenzhen Guangdong 518057 - CHINA - - FC-25-3F (hex) Apple - FC253F (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - FC-27-A2 (hex) TRANS ELECTRIC CO., LTD. - FC27A2 (base 16) TRANS ELECTRIC CO., LTD. - 771,Sec.2 Chungsan Rd,Huatang - Changhua 503 - TAIWAN, PROVINCE OF CHINA - - FC-2A-54 (hex) Connected Data, Inc. - FC2A54 (base 16) Connected Data, Inc. - 2905 Stender Way - STE 36 - Santa Clara CA 95054 - UNITED STATES - - FC-2E-2D (hex) Lorom Industrial Co.LTD. - FC2E2D (base 16) Lorom Industrial Co.LTD. - F1.13,Rm.2,No.78,Sec.2,An-HoRd. - Taipei 106 - TAIWAN, PROVINCE OF CHINA - - FC-2F-40 (hex) Calxeda, Inc. - FC2F40 (base 16) Calxeda, Inc. - 7000 North Mopac Expressway - Suite 250 - Austin TX 78731 - UNITED STATES - - FC-32-88 (hex) CELOT Wireless Co., Ltd - FC3288 (base 16) CELOT Wireless Co., Ltd - 4Fl.,NongHyup Bldg.,#1588-10 Gwanyang-Dong - Dongan-Gu - Anyang City, Gyeonggi-Do 431-727 - KOREA, REPUBLIC OF - - FC-35-98 (hex) Favite Inc. - FC3598 (base 16) Favite Inc. - No.19, Lane 78, Yanhe St., - Jhubei City Hsinchu County 302 - TAIWAN, PROVINCE OF CHINA - - FC-35-E6 (hex) Visteon corp - FC35E6 (base 16) Visteon corp - One Village Center Dr - Blg 25.3.073 - Belleville MI 48111 - UNITED STATES - - FC-3D-93 (hex) LONGCHEER TELECOMMUNICATION LIMITED - FC3D93 (base 16) LONGCHEER TELECOMMUNICATION LIMITED - Building 1,No.401 - Caobao Rd,Xuhui District - Shanghai 200233 - CHINA - - FC-3F-AB (hex) Henan Lanxin Technology Co., Ltd - FC3FAB (base 16) Henan Lanxin Technology Co., Ltd - 4/F-B, Building No.1, 863 Central China Software Park, No.6 Cuizhu Street, High & New Technology Industries Development Zone - Zhengzhou Henan 450001 - CHINA - - FC-44-63 (hex) Universal Audio, Inc - FC4463 (base 16) Universal Audio, Inc - 4585 Scotts Valley Dr. - Scotts Valley CA 95066 - UNITED STATES - - FC-44-99 (hex) Swarco LEA d.o.o. - FC4499 (base 16) Swarco LEA d.o.o. - Finzgarjeva 1A - Lesce 4248 - SLOVENIA - - FC-45-5F (hex) JIANGXI SHANSHUI OPTOELECTRONIC TECHNOLOGY CO.,LTD - FC455F (base 16) JIANGXI SHANSHUI OPTOELECTRONIC TECHNOLOGY CO.,LTD - No.1010,Anping Road,Eco-Industrial Park,Lushan District - Jiujiang Jiangxi 332000 - CHINA - - FC-48-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD - FC48EF (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1-4,Huawei Industrial Base,Bantian,Longgang - ShenZhen GuangDong 518129 - CHINA - - FC-4A-E9 (hex) Castlenet Technology Inc. - FC4AE9 (base 16) Castlenet Technology Inc. - No.64, Chung-Shan Rd. - Tu-Cheng Dist. - New Taipei City 23680 - TAIWAN, PROVINCE OF CHINA - - FC-4B-1C (hex) INTERSENSOR S.R.L. - FC4B1C (base 16) INTERSENSOR S.R.L. - 101 Bd. Iuliu Maniu str., Bl. A2, Sc. 2, #47 - Bucharest 061094 - ROMANIA - - FC-4B-BC (hex) Sunplus Technology Co., Ltd. - FC4BBC (base 16) Sunplus Technology Co., Ltd. - No.19, Innovation First Road - Hsinchu Science Park - Hsinchu City 300 - TAIWAN, PROVINCE OF CHINA - - FC-4D-D4 (hex) Universal Global Scientific Industrial Co., Ltd. - FC4DD4 (base 16) Universal Global Scientific Industrial Co., Ltd. - 141, Lane 351, Taiping Rd. Sec. 1, Tsao Tuen, - Nan-Tou Hsien, 542 - TAIWAN, PROVINCE OF CHINA - - FC-50-90 (hex) SIMEX Sp. z o.o. - FC5090 (base 16) SIMEX Sp. z o.o. - ul. Wielopole 7 - Gdañsk pomorskie 80-556 - POLAND - - FC-52-CE (hex) Control iD - FC52CE (base 16) Control iD - Rua Hungria, 574 - 9th floor - São Paulo SP 01455-000 - BRAZIL - - FC-58-FA (hex) Shen Zhen Shi Xin Zhong Xin Technology Co.,Ltd. - FC58FA (base 16) Shen Zhen Shi Xin Zhong Xin Technology Co.,Ltd. - Block 3, Dong Huan Industrial Zone, Sha Jing Town - Bao'an District, Shen Zhen, Guang Dong Province, China - Shen Zhen Guang Dong 518000 - CHINA - - FC-5B-24 (hex) Weibel Scientific A/S - FC5B24 (base 16) Weibel Scientific A/S - Solvang 30 - Alleroed 3450 - DENMARK - - FC-5B-26 (hex) MikroBits - FC5B26 (base 16) MikroBits - Jalan Petung 31 Papringan - Yogyakarta DIY 55281 - INDONESIA - - FC-5B-39 (hex) Cisco - FC5B39 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - FC-60-18 (hex) Zhejiang Kangtai Electric Co., Ltd. - FC6018 (base 16) Zhejiang Kangtai Electric Co., Ltd. - No.5, Kangtai Rd - Huanghua Industrial District - Yueqing Zhejiang 325605 - CHINA - - FC-61-98 (hex) NEC Personal Products, Ltd - FC6198 (base 16) NEC Personal Products, Ltd - 6-80, Shimohanazawa 2-chome, - Yonezawa-shi Yamagata 992-8520 - JAPAN - - FC-62-6E (hex) Beijing MDC Telecom - FC626E (base 16) Beijing MDC Telecom - 26 Xiaoyun Road #B2808, Chaoyang - Beijing 100016 - CHINA - - FC-62-B9 (hex) ALPS ERECTRIC CO.,LTD - FC62B9 (base 16) ALPS ERECTRIC CO.,LTD - 6-1 - nishida - kakuda-city Miyagi-Pref 981-1595 - JAPAN - - FC-68-3E (hex) Directed Perception, Inc - FC683E (base 16) Directed Perception, Inc - 890C Cowan Road - Burlingame California 94010 - UNITED STATES - - FC-6C-31 (hex) LXinstruments GmbH - FC6C31 (base 16) LXinstruments GmbH - Herrenberger Str. 130 - Boeblingen 71034 - GERMANY - - FC-6D-C0 (hex) BME CORPORATION - FC6DC0 (base 16) BME CORPORATION - 147-2 - Kawagoe-shi Saitama 350-0845 - JAPAN - - FC-6F-B7 (hex) Pace plc - FC6FB7 (base 16) Pace plc - Victoria Lane - Saltaire West Yorkshire BD18 3LF - UNITED KINGDOM - - FC-75-16 (hex) D-Link International - FC7516 (base 16) D-Link International - 1 International Business Park, #03-12, The Synergy - 609917 - SINGAPORE - - FC-75-E6 (hex) Handreamnet - FC75E6 (base 16) Handreamnet - #1209 MarioTower, 222-12, Guro-Dong, Guro-Gu - Seoul Guro-Gu 152-848 - KOREA, REPUBLIC OF - - FC-79-0B (hex) Hitachi High Technologies America, Inc. - FC790B (base 16) Hitachi High Technologies America, Inc. - 208 Fairforest Way - Greenville SC 29607 - UNITED STATES - - FC-7C-E7 (hex) FCI USA LLC - FC7CE7 (base 16) FCI USA LLC - 825 Old Trail Road - Etters PA 17319 - UNITED STATES - - FC-83-29 (hex) Trei technics - FC8329 (base 16) Trei technics - 801 Northpoint Pkwy - Ste 54 - West Palm Beach Florida 33407 - UNITED STATES - - FC-83-99 (hex) Avaya, Inc - FC8399 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - FC-8B-97 (hex) Shenzhen Gongjin Electronics Co.,Ltd - FC8B97 (base 16) Shenzhen Gongjin Electronics Co.,Ltd - B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 - Nanshan Medical Instrument Industry Park,1019# Nanhai Road,Nanshan District - Shenzhen Guangdong 518067 - CHINA - - FC-8E-7E (hex) Pace plc - FC8E7E (base 16) Pace plc - Victoria Road, - Saltaire - West Yorkshire, England BD18 3LF - UNITED KINGDOM - - FC-8F-90 (hex) Samsung Electronics Co.,Ltd - FC8F90 (base 16) Samsung Electronics Co.,Ltd - 129, Samsung-ro, Youngtongl-Gu - Suwon Gyeonggi-Do 443742 - KOREA, REPUBLIC OF - - FC-8F-C4 (hex) Intelligent Technology Inc. - FC8FC4 (base 16) Intelligent Technology Inc. - Yuanhe 3 Street,Tongsha Industrial Zone, - Dongcheng Area - Dongguan Guangdong 523127 - CHINA - - FC-92-3B (hex) Nokia Corporation - FC923B (base 16) Nokia Corporation - Joensuunkatu 7 - Salo N.A. 24101 - FINLAND - - FC-94-6C (hex) UBIVELOX - FC946C (base 16) UBIVELOX - #1301 KOLONG Digital Villent 222-7 Guro-dong Guro-gu - SEOUL 152-777 - KOREA, REPUBLIC OF - - FC-94-E3 (hex) Technicolor USA Inc. - FC94E3 (base 16) Technicolor USA Inc. - 101 West 103rd Street - Indianapolis IN 46290 - UNITED STATES - - FC-99-47 (hex) Cisco - FC9947 (base 16) Cisco - 170 West Tasman Drive - SJCM/2 - San Jose CA 95134 - UNITED STATES - - FC-9A-FA (hex) Motus Global Inc. - FC9AFA (base 16) Motus Global Inc. - 5394 Merrick Road - 2nd Floor - Massapequa NY 11758 - UNITED STATES - - FC-9F-AE (hex) Fidus Systems Inc - FC9FAE (base 16) Fidus Systems Inc - 35 Fitzgerald Road - Suite 400 - Ottawa Ontario K2H 1E6 - CANADA - - FC-9F-E1 (hex) CONWIN.Tech. Ltd - FC9FE1 (base 16) CONWIN.Tech. Ltd - 4D,Tianxia IC Bldg,115 Yiyuan road, Nanshan District,Shenzhen,Guangdong,P.P.China - Shenzhen Guangdong 518000 - CHINA - - FC-A1-3E (hex) Samsung Electronics - FCA13E (base 16) Samsung Electronics - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - FC-A2-2A (hex) PT. Callysta Multi Engineering - FCA22A (base 16) PT. Callysta Multi Engineering - Jl. Taman Cibeunying No. 2 - Cihapit - Bandung Jawa Barat 40114 - INDONESIA - - FC-A8-41 (hex) Avaya, Inc - FCA841 (base 16) Avaya, Inc - 211 Mount Airy Road - Basking Ridge NJ 07920 - UNITED STATES - - FC-A9-B0 (hex) MIARTECH (SHANGHAI),INC. - FCA9B0 (base 16) MIARTECH (SHANGHAI),INC. - 3F,Building 4,No 290 Zhangheng Road Zhangjiang Hi-Tech Park,Pudong New District Shanghai,P.R.China - SHANGHAI SHANGHAI 201204 - CHINA - - FC-AA-14 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. - FCAA14 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. - Pin-Jen City, Taoyuan, Taiwan, R.O.C. - Pin-Jen Taoyuan 324 - TAIWAN, PROVINCE OF CHINA - - FC-AD-0F (hex) QTS NETWORKS - FCAD0F (base 16) QTS NETWORKS - Jinyanlong Plaza, Huilongguan, - Changping District - Beijing 100092 - CHINA - - FC-AF-6A (hex) Qulsar Inc - FCAF6A (base 16) Qulsar Inc - Torshamnsgatan 35 - Kista SE-16440 - SWEDEN - - FC-AF-AC (hex) Panasonic System LSI - FCAFAC (base 16) Panasonic System LSI - 1 Kotari-yakemachi - Nagaokakyo Kyoto 617-8520 - JAPAN - - FC-B0-C4 (hex) Shanghai DareGlobal Technologies Co., Ltd - FCB0C4 (base 16) Shanghai DareGlobal Technologies Co., Ltd - 22F Info-Tech Building - No.1555 Kongjiang Road - Shanghai 200092 - CHINA - - FC-B4-E6 (hex) ASKEY COMPUTER CORP. - FCB4E6 (base 16) ASKEY COMPUTER CORP. - 10F,No.119,JIANKANG RD,ZHONGHE DIST - TAIWAN NEW TAIPEI 23585 - TAIWAN, PROVINCE OF CHINA - - FC-B6-98 (hex) Cambridge Industries(Group) Co.,Ltd. - FCB698 (base 16) Cambridge Industries(Group) Co.,Ltd. - 22 Floor,Qilai Tower;889 Yishan Road - Shanghai CHINA 200233 - CHINA - - FC-BB-A1 (hex) Shenzhen Minicreate Technology Co.,Ltd - FCBBA1 (base 16) Shenzhen Minicreate Technology Co.,Ltd - 5/F.,5th,Building,Animation Park,Yuehai Road - NanShan District - Shenzhen Guangdong 518066 - CHINA - - FC-C2-3D (hex) Atmel Corporation - FCC23D (base 16) Atmel Corporation - 1150 E Cheyenne Mtn Blvd - Colorado Springs CO 80906 - UNITED STATES - - FC-C2-DE (hex) Murata Manufacturing Co., Ltd. - FCC2DE (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - FC-C7-34 (hex) Samsung Electronics Co.,Ltd - FCC734 (base 16) Samsung Electronics Co.,Ltd - #94-1, Imsoo-Dong - Gumi Gyeongbuk 730-350 - KOREA, REPUBLIC OF - - FC-C8-97 (hex) ZTE Corporation - FCC897 (base 16) ZTE Corporation - 12/F.,R&D Building,Kejinan Road, - Shenzhen, Guangdong 518057 - CHINA - - FC-CC-E4 (hex) Ascon Ltd. - FCCCE4 (base 16) Ascon Ltd. - 1-15-27 Minato-machi - Fukuyama –shi Hiroshima-ken 721-0964 - JAPAN - - FC-CF-62 (hex) IBM Corp - FCCF62 (base 16) IBM Corp - 2051 Mission College Blvd - Santa Clara CA 95054 - UNITED STATES - - FC-D4-F2 (hex) The Coca Cola Company - FCD4F2 (base 16) The Coca Cola Company - One Coca Cola Plaza - Atlanta GA 30313 - UNITED STATES - - FC-D4-F6 (hex) Messana Air.Ray Conditioning s.r.l. - FCD4F6 (base 16) Messana Air.Ray Conditioning s.r.l. - Via Venezia 18 - Oderzo TV 31046 - ITALY - - FC-D5-D9 (hex) Shenzhen SDMC Technology Co., Ltd. - FCD5D9 (base 16) Shenzhen SDMC Technology Co., Ltd. - 7F,W2-A,Hi-Tech. Industrial Park - Nanshan - Shenzhen GuangDong 518000 - CHINA - - FC-D6-BD (hex) Robert Bosch GmbH - FCD6BD (base 16) Robert Bosch GmbH - AE-BE/EKE - P.O. Box 16 61 - Leonberg BW 71206 - GERMANY - - FC-D8-17 (hex) Beijing Hesun Technologies Co.Ltd. - FCD817 (base 16) Beijing Hesun Technologies Co.Ltd. - Room 1811, 18th floor, Building No. 4, Courtyard 1, Shangdi tenth Street - Haidian District - Beijing 100085 - CHINA - - FC-DB-96 (hex) ENERVALLEY CO., LTD - FCDB96 (base 16) ENERVALLEY CO., LTD - 907-101 DIGITAL EMPIRE II - SHINWON RO 88 YEONGTONG GU - SUWON SI GYEONGGI DO 443 734 - KOREA, REPUBLIC OF - - FC-DB-B3 (hex) Murata Manufacturing Co., Ltd. - FCDBB3 (base 16) Murata Manufacturing Co., Ltd. - 1-10-1, Higashikotari - Nagaokakyo-shi Kyoto 617-8555 - JAPAN - - FC-DC-4A (hex) G-Wearables Corp. - FCDC4A (base 16) G-Wearables Corp. - 901, S&CTBuilding, No.9 Zhongguancun South Avenue - Haidian District - Beijing Beijing 100081 - CHINA - - FC-DD-55 (hex) Shenzhen WeWins wireless Co.,Ltd - FCDD55 (base 16) Shenzhen WeWins wireless Co.,Ltd - 6/F.,B Wing,Yuehai Piaza,Nanhai Road - Nanshan District - Shenzhen Guangdong 518000 - CHINA - - FC-E1-86 (hex) A3M Co., LTD - FCE186 (base 16) A3M Co., LTD - KeumJeong Highview 2F #205, - 153-8, LS-ro, - Gunpo Gyeonggi 435-845 - KOREA, REPUBLIC OF - - FC-E1-92 (hex) Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd - FCE192 (base 16) Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd - No.28,Xinchuang Rd.,West Gaoxin District - Chengdu Sichuan 611731 - CHINA - - FC-E1-D9 (hex) Stable Imaging Solutions LLC - FCE1D9 (base 16) Stable Imaging Solutions LLC - 3709 Old Conejo Rd - Newbury Park CA 91320 - UNITED STATES - - FC-E1-FB (hex) Array Networks - FCE1FB (base 16) Array Networks - 1371 McCarthy Blvd - Milpitas California 95035 - UNITED STATES - - FC-E2-3F (hex) CLAY PAKY SPA - FCE23F (base 16) CLAY PAKY SPA - Via Pastrengo 3/b - Seriate Bergamo 24068 - ITALY - - FC-E3-3C (hex) HUAWEI TECHNOLOGIES CO.,LTD - FCE33C (base 16) HUAWEI TECHNOLOGIES CO.,LTD - D1,Huawei Industrial Base - Bantian, Longang - SHENZHEN GUANGDONG 518129 - CHINA - - FC-E5-57 (hex) Nokia Corporation - FCE557 (base 16) Nokia Corporation - Elektroniikkatie 10 - Oulu Ou 90590 - FINLAND - - FC-E8-92 (hex) Hangzhou Lancable Technology Co.,Ltd - FCE892 (base 16) Hangzhou Lancable Technology Co.,Ltd - Zone A,Floor 16,Zhongcai Building,68#,Tonghe Road,Binjiang District, - Hangzhou Zhejiang 310051 - CHINA - - FC-E9-98 (hex) Apple - FCE998 (base 16) Apple - 1 Infinite Loop - Cupertino CA 95014 - UNITED STATES - - FC-ED-B9 (hex) Arrayent - FCEDB9 (base 16) Arrayent - 570 El Camino Real #150-419 - Redwood City CA 94063 - UNITED STATES - - FC-F1-52 (hex) Sony Corporation - FCF152 (base 16) Sony Corporation - 1-7-1 Konan - Minato-ku Tokyo 108-0075 - JAPAN - - FC-F1-CD (hex) OPTEX-FA CO.,LTD. - FCF1CD (base 16) OPTEX-FA CO.,LTD. - 91 Awata-cho - Chudoji Shimogyo-ku - Kyoto 600-8815 - JAPAN - - FC-F5-28 (hex) ZyXEL Communications Corporation - FCF528 (base 16) ZyXEL Communications Corporation - No. 6, Innovation Road 2, Hsinchu Science Park - Hsinchu Taiwan 300 - TAIWAN, PROVINCE OF CHINA - - FC-F6-47 (hex) Fiberhome Telecommunication Tech.Co.,Ltd. - FCF647 (base 16) Fiberhome Telecommunication Tech.Co.,Ltd. - No.5 DongXin Road - Hongsan District - Wuhan City Hubei Province 430074 - CHINA - - FC-F8-AE (hex) Intel Corporate - FCF8AE (base 16) Intel Corporate - Lot 8, Jalan Hi-Tech 2/3 - Kulim Hi-Tech Park - Kulim Kedah 09000 - MALAYSIA - - FC-F8-B7 (hex) TRONTEQ Electronic - FCF8B7 (base 16) TRONTEQ Electronic - Birnenweg 15 - Reutlingen Baden Wuerttemberg 72766 - GERMANY - - FC-FA-F7 (hex) Shanghai Baud Data Communication Co.,Ltd. - FCFAF7 (base 16) Shanghai Baud Data Communication Co.,Ltd. - NO.123 JULI RD - PUDONG ZHANGJIANG HIGH-TECH PARK - SHANGHAI 201203 - CHINA - - FC-FB-FB (hex) CISCO SYSTEMS, INC. - FCFBFB (base 16) CISCO SYSTEMS, INC. - 170 W. TASMAN DRIVE - M/S SJA-2 - SAN JOSE CA 95134-1706 - UNITED STATES - - FC-FE-77 (hex) Hitachi Reftechno, Inc. - FCFE77 (base 16) Hitachi Reftechno, Inc. - 709-2 Tomita - Ohita-machi - Tochigi-shi Tochigi-ken 329-4404 - JAPAN - - FC-FF-AA (hex) IEEE REGISTRATION AUTHORITY - Please see MAL public listing for more information. - FCFFAA (base 16) IEEE REGISTRATION AUTHORITY - Please see MAL public listing for more information. - - 445 HOES LANE - PISCATAWAY NJ 08854 - UNITED STATES - diff --git a/awx/lib/site-packages/netaddr/fbsocket.py b/awx/lib/site-packages/netaddr/fbsocket.py deleted file mode 100644 index 79200a01ac..0000000000 --- a/awx/lib/site-packages/netaddr/fbsocket.py +++ /dev/null @@ -1,246 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""Fallback routines for Python's standard library socket module""" - -from struct import unpack as _unpack, pack as _pack - -from netaddr.compat import _bytes_join, _is_str - -AF_INET = 2 -AF_INET6 = 10 - - -def inet_ntoa(packed_ip): - """ - Convert an IP address from 32-bit packed binary format to string format. - """ - if not _is_str(packed_ip): - raise TypeError('string type expected, not %s' % str(type(packed_ip))) - - if len(packed_ip) != 4: - raise ValueError('invalid length of packed IP address string') - - return '%d.%d.%d.%d' % _unpack('4B', packed_ip) - - -def _compact_ipv6_tokens(tokens): - new_tokens = [] - - positions = [] - start_index = None - num_tokens = 0 - - # Discover all runs of zeros. - for idx, token in enumerate(tokens): - if token == '0': - if start_index is None: - start_index = idx - num_tokens += 1 - else: - if num_tokens > 1: - positions.append((num_tokens, start_index)) - start_index = None - num_tokens = 0 - - new_tokens.append(token) - - # Store any position not saved before loop exit. - if num_tokens > 1: - positions.append((num_tokens, start_index)) - - # Replace first longest run with an empty string. - if len(positions) != 0: - # Locate longest, left-most run of zeros. - positions.sort(key=lambda x: x[1]) - best_position = positions[0] - for position in positions: - if position[0] > best_position[0]: - best_position = position - # Replace chosen zero run. - (length, start_idx) = best_position - new_tokens = new_tokens[0:start_idx] + [''] + \ - new_tokens[start_idx+length:] - - # Add start and end blanks so join creates '::'. - if new_tokens[0] == '': - new_tokens.insert(0, '') - - if new_tokens[-1] == '': - new_tokens.append('') - - return new_tokens - - -def inet_ntop(af, packed_ip): - """Convert an packed IP address of the given family to string format.""" - if af == AF_INET: - # IPv4. - return inet_ntoa(packed_ip) - elif af == AF_INET6: - # IPv6. - if len(packed_ip) != 16 or not _is_str(packed_ip): - raise ValueError('invalid length of packed IP address string') - - tokens = ['%x' % i for i in _unpack('>8H', packed_ip)] - - # Convert packed address to an integer value. - words = list(_unpack('>8H', packed_ip)) - int_val = 0 - for i, num in enumerate(reversed(words)): - word = num - word = word << 16 * i - int_val = int_val | word - - if 0xffff < int_val <= 0xffffffff or int_val >> 32 == 0xffff: - # IPv4 compatible / mapped IPv6. - packed_ipv4 = _pack('>2H', *[int(i, 16) for i in tokens[-2:]]) - ipv4_str = inet_ntoa(packed_ipv4) - tokens = tokens[0:-2] + [ipv4_str] - - return ':'.join(_compact_ipv6_tokens(tokens)) - else: - raise ValueError('unknown address family %d' % af) - - -def _inet_pton_af_inet(ip_string): - """ - Convert an IP address in string format (123.45.67.89) to the 32-bit packed - binary format used in low-level network functions. Differs from inet_aton - by only support decimal octets. Using octal or hexadecimal values will - raise a ValueError exception. - """ - #TODO: optimise this ... use inet_aton with mods if available ... - if _is_str(ip_string): - invalid_addr = ValueError('illegal IP address string %r' % ip_string) - # Support for hexadecimal and octal octets. - tokens = ip_string.split('.') - - # Pack octets. - if len(tokens) == 4: - words = [] - for token in tokens: - if token.startswith('0x') or \ - (token.startswith('0') and len(token) > 1): - raise invalid_addr - try: - octet = int(token) - except ValueError: - raise invalid_addr - - if (octet >> 8) != 0: - raise invalid_addr - words.append(_pack('B', octet)) - return _bytes_join(words) - else: - raise invalid_addr - - raise ValueError('argument should be a string, not %s' % type(ip_string)) - - -def inet_pton(af, ip_string): - """ - Convert an IP address from string format to a packed string suitable for - use with low-level network functions. - """ - if af == AF_INET: - # IPv4. - return _inet_pton_af_inet(ip_string) - elif af == AF_INET6: - invalid_addr = ValueError('illegal IP address string %r' % ip_string) - # IPv6. - values = [] - - if not _is_str(ip_string): - raise invalid_addr - - if 'x' in ip_string: - # Don't accept hextets with the 0x prefix. - raise invalid_addr - - if '::' in ip_string: - if ip_string == '::': - # Unspecified address. - return '\x00'.encode() * 16 - # IPv6 compact mode. - try: - prefix, suffix = ip_string.split('::') - except ValueError: - raise invalid_addr - - l_prefix = [] - l_suffix = [] - - if prefix != '': - l_prefix = prefix.split(':') - - if suffix != '': - l_suffix = suffix.split(':') - - # IPv6 compact IPv4 compatibility mode. - if len(l_suffix) and '.' in l_suffix[-1]: - ipv4_str = _inet_pton_af_inet(l_suffix.pop()) - l_suffix.append('%x' % _unpack('>H', ipv4_str[0:2])[0]) - l_suffix.append('%x' % _unpack('>H', ipv4_str[2:4])[0]) - - token_count = len(l_prefix) + len(l_suffix) - - if not 0 <= token_count <= 8 - 1: - raise invalid_addr - - gap_size = 8 - ( len(l_prefix) + len(l_suffix) ) - - values = [_pack('>H', int(i, 16)) for i in l_prefix] \ - + ['\x00\x00'.encode() for i in range(gap_size)] \ - + [_pack('>H', int(i, 16)) for i in l_suffix] - try: - for token in l_prefix + l_suffix: - word = int(token, 16) - if not 0 <= word <= 0xffff: - raise invalid_addr - except ValueError: - raise invalid_addr - else: - # IPv6 verbose mode. - if ':' in ip_string: - tokens = ip_string.split(':') - - if '.' in ip_string: - ipv6_prefix = tokens[:-1] - if ipv6_prefix[:-1] != ['0', '0', '0', '0', '0']: - raise invalid_addr - - if ipv6_prefix[-1].lower() not in ('0', 'ffff'): - raise invalid_addr - - # IPv6 verbose IPv4 compatibility mode. - if len(tokens) != 7: - raise invalid_addr - - ipv4_str = _inet_pton_af_inet(tokens.pop()) - tokens.append('%x' % _unpack('>H', ipv4_str[0:2])[0]) - tokens.append('%x' % _unpack('>H', ipv4_str[2:4])[0]) - - values = [_pack('>H', int(i, 16)) for i in tokens] - else: - # IPv6 verbose mode. - if len(tokens) != 8: - raise invalid_addr - try: - tokens = [int(token, 16) for token in tokens] - for token in tokens: - if not 0 <= token <= 0xffff: - raise invalid_addr - - except ValueError: - raise invalid_addr - - values = [_pack('>H', i) for i in tokens] - else: - raise invalid_addr - - return _bytes_join(values) - else: - raise ValueError('Unknown address family %d' % af) diff --git a/awx/lib/site-packages/netaddr/ip/__init__.py b/awx/lib/site-packages/netaddr/ip/__init__.py deleted file mode 100644 index ebbb286600..0000000000 --- a/awx/lib/site-packages/netaddr/ip/__init__.py +++ /dev/null @@ -1,1894 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""Routines for IPv4 and IPv6 addresses, subnets and ranges.""" - -import sys as _sys - -from netaddr.core import AddrFormatError, AddrConversionError, num_bits, \ - DictDotLookup, NOHOST, N, INET_PTON, P, ZEROFILL, Z - -from netaddr.strategy import ipv4 as _ipv4, ipv6 as _ipv6 - -from netaddr.compat import _sys_maxint, _iter_range, _is_str, _int_type, \ - _str_type - - -class BaseIP(object): - """ - An abstract base class for common operations shared between various IP - related subclasses. - - """ - __slots__ = ('_value', '_module') - - def __init__(self): - """Constructor.""" - self._value = None - self._module = None - - def _set_value(self, value): - if not isinstance(value, _int_type): - raise TypeError('int argument expected, not %s' % type(value)) - if not 0 <= value <= self._module.max_int: - raise AddrFormatError('value out of bounds for an %s address!' \ - % self._module.family_name) - self._value = value - - value = property(lambda self: self._value, _set_value, - doc='a positive integer representing the value of IP address/subnet.') - - def key(self): - """ - :return: a key tuple that uniquely identifies this IP address. - """ - return NotImplemented - - def sort_key(self): - """ - :return: A key tuple used to compare and sort this `IPAddress` - correctly. - """ - return NotImplemented - - def __hash__(self): - """ - :return: A hash value uniquely indentifying this IP object. - """ - return hash(self.key()) - - def __eq__(self, other): - """ - :param other: an `IPAddress` or `IPNetwork` object. - - :return: ``True`` if this `IPAddress` or `IPNetwork` object is - equivalent to ``other``, ``False`` otherwise. - """ - try: - return self.key() == other.key() - except (AttributeError, TypeError): - return NotImplemented - - def __ne__(self, other): - """ - :param other: an `IPAddress` or `IPNetwork` object. - - :return: ``True`` if this `IPAddress` or `IPNetwork` object is - not equivalent to ``other``, ``False`` otherwise. - """ - try: - return self.key() != other.key() - except (AttributeError, TypeError): - return NotImplemented - - def __lt__(self, other): - """ - :param other: an `IPAddress` or `IPNetwork` object. - - :return: ``True`` if this `IPAddress` or `IPNetwork` object is - less than ``other``, ``False`` otherwise. - """ - try: - return self.sort_key() < other.sort_key() - except (AttributeError, TypeError): - return NotImplemented - - def __le__(self, other): - """ - :param other: an `IPAddress` or `IPNetwork` object. - - :return: ``True`` if this `IPAddress` or `IPNetwork` object is - less than or equal to ``other``, ``False`` otherwise. - """ - try: - return self.sort_key() <= other.sort_key() - except (AttributeError, TypeError): - return NotImplemented - - def __gt__(self, other): - """ - :param other: an `IPAddress` or `IPNetwork` object. - - :return: ``True`` if this `IPAddress` or `IPNetwork` object is - greater than ``other``, ``False`` otherwise. - """ - try: - return self.sort_key() > other.sort_key() - except (AttributeError, TypeError): - return NotImplemented - - def __ge__(self, other): - """ - :param other: an `IPAddress` or `IPNetwork` object. - - :return: ``True`` if this `IPAddress` or `IPNetwork` object is - greater than or equal to ``other``, ``False`` otherwise. - """ - try: - return self.sort_key() >= other.sort_key() - except (AttributeError, TypeError): - return NotImplemented - - def is_unicast(self): - """:return: ``True`` if this IP is unicast, ``False`` otherwise""" - return not self.is_multicast() - - def is_multicast(self): - """:return: ``True`` if this IP is multicast, ``False`` otherwise""" - if self._module == _ipv4: - return self in IPV4_MULTICAST - elif self._module == _ipv6: - return self in IPV6_MULTICAST - - def is_loopback(self): - """ - :return: ``True`` if this IP is loopback address (not for network - transmission), ``False`` otherwise. - References: RFC 3330 and 4291. - """ - if self._module.version == 4: - return self in IPV4_LOOPBACK - elif self._module.version == 6: - return self == IPV6_LOOPBACK - - def is_private(self): - """ - :return: ``True`` if this IP is for internal/private use only - (i.e. non-public), ``False`` otherwise. Reference: RFCs 1918, - 3330, 4193, 3879 and 2365. - """ - if self._module.version == 4: - for cidr in IPV4_PRIVATE: - if self in cidr: - return True - elif self._module.version == 6: - for cidr in IPV6_PRIVATE: - if self in cidr: - return True - - if self.is_link_local(): - return True - - return False - - def is_link_local(self): - """ - :return: ``True`` if this IP is link-local address ``False`` otherwise. - Reference: RFCs 3927 and 4291. - """ - if self._module.version == 4: - return self in IPV4_LINK_LOCAL - elif self._module.version == 6: - return self in IPV6_LINK_LOCAL - - def is_reserved(self): - """ - :return: ``True`` if this IP is in IANA reserved range, ``False`` - otherwise. Reference: RFCs 3330 and 3171. - """ - if self._module.version == 4: - for cidr in IPV4_RESERVED: - if self in cidr: - return True - elif self._module.version == 6: - for cidr in IPV6_RESERVED: - if self in cidr: - return True - return False - - def is_ipv4_mapped(self): - """ - :return: ``True`` if this IP is IPv4-compatible IPv6 address, ``False`` - otherwise. - """ - return self._module.version == 6 and (self._value >> 32) == 0xffff - - def is_ipv4_compat(self): - """ - :return: ``True`` if this IP is IPv4-mapped IPv6 address, ``False`` - otherwise. - """ - return self._module.version == 6 and (self._value >> 32) == 0 - - @property - def info(self): - """ - A record dict containing IANA registration details for this IP address - if available, None otherwise. - """ - # Lazy loading of IANA data structures. - from netaddr.ip.iana import query - return DictDotLookup(query(self)) - - @property - def version(self): - """the IP protocol version represented by this IP object.""" - return self._module.version - - - -class IPAddress(BaseIP): - """ - An individual IPv4 or IPv6 address without a net mask or subnet prefix. - - To support these and other network based operations, see `IPNetwork`. - - """ - __slots__ = () - - def __init__(self, addr, version=None, flags=0): - """ - Constructor. - - :param addr: an IPv4 or IPv6 address which may be represented in an - accepted string format, as an unsigned integer or as another - IPAddress object (copy construction). - - :param version: (optional) optimizes version detection if specified - and distinguishes between IPv4 and IPv6 for addresses with an - equivalent integer value. - - :param flags: (optional) decides which rules are applied to the - interpretation of the addr value. Supported constants are - INET_PTON and ZEROFILL. See the netaddr.core docs for further - details. - - """ - super(IPAddress, self).__init__() - - if isinstance(addr, BaseIP): - # Copy constructor. - if version is not None and version != addr._module.version: - raise ValueError('cannot switch IP versions using ' - 'copy constructor!') - self._value = addr._value - self._module = addr._module - else: - # Explicit IP address version. - if version is not None: - if version == 4: - self._module = _ipv4 - elif version == 6: - self._module = _ipv6 - else: - raise ValueError('%r is an invalid IP version!' % version) - - if _is_str(addr) and '/' in addr: - raise ValueError('%s() does not support netmasks or subnet' \ - ' prefixes! See documentation for details.' - % self.__class__.__name__) - - if self._module is None: - # IP version is implicit, detect it from addr. - if isinstance(addr, _int_type): - try: - if 0 <= int(addr) <= _ipv4.max_int: - self._value = int(addr) - self._module = _ipv4 - elif _ipv4.max_int < int(addr) <= _ipv6.max_int: - self._value = int(addr) - self._module = _ipv6 - except ValueError: - pass - else: - for module in _ipv4, _ipv6: - try: - self._value = module.str_to_int(addr, flags) - except: - continue - else: - self._module = module - break - - if self._module is None: - raise AddrFormatError('failed to detect a valid IP ' \ - 'address from %r' % addr) - else: - # IP version is explicit. - if _is_str(addr): - try: - self._value = self._module.str_to_int(addr, flags) - except AddrFormatError: - raise AddrFormatError('base address %r is not IPv%d' - % (addr, self._module.version)) - else: - if 0 <= int(addr) <= self._module.max_int: - self._value = int(addr) - else: - raise AddrFormatError('bad address format: %r' % addr) - - def __getstate__(self): - """:returns: Pickled state of an `IPAddress` object.""" - return self._value, self._module.version - - def __setstate__(self, state): - """ - :param state: data used to unpickle a pickled `IPAddress` object. - - """ - value, version = state - - self._value = value - - if version == 4: - self._module = _ipv4 - elif version == 6: - self._module = _ipv6 - else: - raise ValueError('unpickling failed for object state: %s' \ - % str(state)) - - def netmask_bits(self): - """ - @return: If this IP is a valid netmask, the number of non-zero - bits are returned, otherwise it returns the width in bits for - the IP address version. - """ - if not self.is_netmask(): - return self._module.width - - i_val = self._value - numbits = 0 - - while i_val > 0: - if i_val & 1 == 1: - break - numbits += 1 - i_val >>= 1 - - mask_length = self._module.width - numbits - - if not 0 <= mask_length <= self._module.width: - raise ValueError('Unexpected mask length %d for address type!' \ - % mask_length) - - return mask_length - - def is_hostmask(self): - """ - :return: ``True`` if this IP address host mask, ``False`` otherwise. - """ - int_val = self._value + 1 - return (int_val & (int_val - 1) == 0) - - def is_netmask(self): - """ - :return: ``True`` if this IP address network mask, ``False`` otherwise. - """ - int_val = (self._value ^ self._module.max_int) + 1 - return (int_val & (int_val - 1) == 0) - - def __iadd__(self, num): - """ - Increases the numerical value of this IPAddress by num. - - An IndexError is raised if result exceeds maximum IP address value or - is less than zero. - - :param num: size of IP address increment. - """ - new_value = int(self._value + num) - if 0 <= new_value <= self._module.max_int: - self._value = new_value - return self - raise IndexError('result outside valid IP address boundary!') - - def __isub__(self, num): - """ - Decreases the numerical value of this IPAddress by num. - - An IndexError is raised if result is less than zero or exceeds maximum - IP address value. - - :param num: size of IP address decrement. - """ - new_value = int(self._value - num) - if 0 <= new_value <= self._module.max_int: - self._value = new_value - return self - raise IndexError('result outside valid IP address boundary!') - - def __add__(self, num): - """ - Add the numerical value of this IP address to num and provide the - result as a new IPAddress object. - - :param num: size of IP address increase. - - :return: a new IPAddress object with its numerical value increased by num. - """ - new_value = int(self._value + num) - if 0 <= new_value <= self._module.max_int: - return self.__class__(new_value, self._module.version) - raise IndexError('result outside valid IP address boundary!') - - __radd__ = __add__ - - def __sub__(self, num): - """ - Subtract the numerical value of this IP address from num providing - the result as a new IPAddress object. - - :param num: size of IP address decrease. - - :return: a new IPAddress object with its numerical value decreased by num. - """ - new_value = int(self._value - num) - if 0 <= new_value <= self._module.max_int: - return self.__class__(new_value, self._module.version) - raise IndexError('result outside valid IP address boundary!') - - def __rsub__(self, num): - """ - Subtract num (lvalue) from the numerical value of this IP address - (rvalue) providing the result as a new IPAddress object. - - :param num: size of IP address decrease. - - :return: a new IPAddress object with its numerical value decreased by num. - """ - new_value = int(num - self._value) - if 0 <= new_value <= self._module.max_int: - return self.__class__(new_value, self._module.version) - raise IndexError('result outside valid IP address boundary!') - - def key(self): - """ - :return: a key tuple that uniquely identifies this IP address. - """ - # NB - we return the value here twice because this IP Address may - # be sorted with a list of networks and it should still end up - # in the expected order. - return self._module.version, self._value - - def sort_key(self): - """:return: A key tuple used to compare and sort this `IPAddress` correctly.""" - return self._module.version, self._value, self._module.width - - def __int__(self): - """:return: the value of this IP address as an unsigned integer""" - return self._value - - def __long__(self): - """:return: the value of this IP address as an unsigned integer""" - return self._value - - def __oct__(self): - """:return: an octal string representation of this IP address.""" - # Python 2.x - if self._value == 0: - return '0' - return '0%o' % self._value - - def __hex__(self): - """:return: a hexadecimal string representation of this IP address.""" - # Python 2.x - return '0x%x' % self._value - - def __index__(self): - """ - :return: return the integer value of this IP address when called by \ - hex(), oct() or bin(). - """ - # Python 3.x - return self._value - - def bits(self, word_sep=None): - """ - :param word_sep: (optional) the separator to insert between words. - Default: None - use default separator for address type. - - :return: the value of this IP address as a binary digit string.""" - return self._module.int_to_bits(self._value, word_sep) - - @property - def packed(self): - """The value of this IP address as a packed binary string.""" - return self._module.int_to_packed(self._value) - - @property - def words(self): - """ - A list of unsigned integer words (octets for IPv4, hextets for IPv6) - found in this IP address. - """ - return self._module.int_to_words(self._value) - - @property - def bin(self): - """ - The value of this IP adddress in standard Python binary - representational form (0bxxx). A back port of the format provided by - the builtin bin() function found in Python 2.6.x and higher. - """ - return self._module.int_to_bin(self._value) - - @property - def reverse_dns(self): - """The reverse DNS lookup record for this IP address""" - return self._module.int_to_arpa(self._value) - - def ipv4(self): - """ - Raises an `AddrConversionError` if IPv6 address cannot be converted - to IPv4. - - :return: A numerically equivalent version 4 `IPAddress` object. - """ - ip = None - klass = self.__class__ - - if self._module.version == 4: - ip = klass(self._value, 4) - elif self._module.version == 6: - if 0 <= self._value <= _ipv4.max_int: - ip = klass(self._value, 4) - elif _ipv4.max_int <= self._value <= 0xffffffffffff: - ip = klass(self._value - 0xffff00000000, 4) - else: - raise AddrConversionError('IPv6 address %s unsuitable for ' \ - 'conversion to IPv4!' % self) - return ip - - def ipv6(self, ipv4_compatible=False): - """ - .. note:: The IPv4-mapped IPv6 address format is now considered \ - deprecated. See RFC 4291 or later for details. - - :param ipv4_compatible: If ``True`` returns an IPv4-mapped address - (::ffff:x.x.x.x), an IPv4-compatible (::x.x.x.x) address - otherwise. Default: False (IPv4-mapped). - - :return: A numerically equivalent version 6 `IPAddress` object. - """ - ip = None - klass = self.__class__ - - if self._module.version == 6: - if ipv4_compatible and \ - (0xffff00000000 <= self._value <= 0xffffffffffff): - ip = klass(self._value - 0xffff00000000, 6) - else: - ip = klass(self._value, 6) - elif self._module.version == 4: - # IPv4-Compatible IPv6 address - ip = klass(self._value, 6) - if not ipv4_compatible: - # IPv4-Mapped IPv6 address - ip = klass(0xffff00000000 + self._value, 6) - - return ip - - def format(self, dialect=None): - """ - Only relevant for IPv6 addresses. Has no effect for IPv4. - - :param dialect: An ipv6_* dialect class. - - :return: an alternate string representation for this IP address. - """ - if dialect is not None: - if not hasattr(dialect, 'word_fmt'): - raise TypeError( - 'custom dialects should subclass ipv6_verbose!') - return self._module.int_to_str(self._value, dialect=dialect) - - def __or__(self, other): - """ - :param other: An `IPAddress` object (or other int-like object). - - :return: bitwise OR (x | y) between the integer value of this IP - address and ``other``. - """ - return self.__class__(self._value | int(other), self._module.version) - - def __and__(self, other): - """ - :param other: An `IPAddress` object (or other int-like object). - - :return: bitwise AND (x & y) between the integer value of this IP - address and ``other``. - """ - return self.__class__(self._value & int(other), self._module.version) - - def __xor__(self, other): - """ - :param other: An `IPAddress` object (or other int-like object). - - :return: bitwise exclusive OR (x ^ y) between the integer value of - this IP address and ``other``. - """ - return self.__class__(self._value ^ int(other), self._module.version) - - def __lshift__(self, numbits): - """ - :param numbits: size of bitwise shift. - - :return: an `IPAddress` object based on this one with its integer - value left shifted by ``numbits``. - """ - return self.__class__(self._value << numbits, self._module.version) - - def __rshift__(self, numbits): - """ - :param numbits: size of bitwise shift. - - :return: an `IPAddress` object based on this one with its integer - value right shifted by ``numbits``. - """ - return self.__class__(self._value >> numbits, self._module.version) - - def __nonzero__(self): - """:return: ``True`` if the numerical value of this IP address is not \ - zero, ``False`` otherwise.""" - # Python 2.x. - return bool(self._value) - - __bool__ = __nonzero__ # Python 3.x. - - def __str__(self): - """:return: IP address in presentational format""" - return self._module.int_to_str(self._value) - - def __repr__(self): - """:return: Python statement to create an equivalent object""" - return "%s('%s')" % (self.__class__.__name__, self) - - -class IPListMixin(object): - """ - A mixin class providing shared list-like functionality to classes - representing groups of IP addresses. - - """ - def __iter__(self): - """ - :return: An iterator providing access to all `IPAddress` objects - within range represented by this ranged IP object. - """ - start_ip = IPAddress(self.first, self._module.version) - end_ip = IPAddress(self.last, self._module.version) - return iter_iprange(start_ip, end_ip) - - @property - def size(self): - """ - The total number of IP addresses within this ranged IP object. - """ - return int(self.last - self.first + 1) - - def __len__(self): - """ - :return: the number of IP addresses in this ranged IP object. Raises - an `IndexError` if size > system max int (a Python 2.x - limitation). Use the .size property for subnets of any size. - """ - size = self.size - if size > _sys_maxint: - raise IndexError(("range contains more than %d (sys.maxint) " - "IP addresses! Use the .size property instead." % _sys_maxint)) - return size - - def __getitem__(self, index): - """ - :return: The IP address(es) in this `IPNetwork` object referenced by - index or slice. As slicing can produce large sequences of objects - an iterator is returned instead of the more usual `list`. - """ - item = None - - if hasattr(index, 'indices'): - if self._module.version == 6: - raise TypeError('IPv6 slices are not supported!') - - (start, stop, step) = index.indices(self.size) - - if (start + step < 0) or (step > stop): - # step value exceeds start and stop boundaries. - item = iter([IPAddress(self.first, self._module.version)]) - else: - start_ip = IPAddress(self.first + start, self._module.version) - end_ip = IPAddress(self.first + stop - step, self._module.version) - item = iter_iprange(start_ip, end_ip, step) - else: - try: - index = int(index) - if (- self.size) <= index < 0: - # negative index. - item = IPAddress(self.last + index + 1, self._module.version) - elif 0 <= index <= (self.size - 1): - # Positive index or zero index. - item = IPAddress(self.first + index, self._module.version) - else: - raise IndexError('index out range for address range size!') - except ValueError: - raise TypeError('unsupported index type %r!' % index) - - return item - - def __contains__(self, other): - """ - :param other: an `IPAddress` or ranged IP object. - - :return: ``True`` if other falls within the boundary of this one, - ``False`` otherwise. - """ - if isinstance(other, BaseIP): - if self._module.version != other._module.version: - return False - if isinstance(other, IPAddress): - return other._value >= self.first and other._value <= self.last - # Assume that we (and the other) provide .first and .last. - return other.first >= self.first and other.last <= self.last - - # Whatever it is, try to interpret it as IPAddress. - return IPAddress(other) in self - - def __nonzero__(self): - """ - Ranged IP objects always represent a sequence of at least one IP - address and are therefore always True in the boolean context. - """ - # Python 2.x. - return True - - __bool__ = __nonzero__ # Python 3.x. - - -def parse_ip_network(module, addr, implicit_prefix=False, flags=0): - if isinstance(addr, tuple): - # CIDR integer tuple - if len(addr) != 2: - raise AddrFormatError('invalid %s tuple!' % module.family_name) - value, prefixlen = addr - - if not(0 <= value <= module.max_int): - raise AddrFormatError('invalid address value for %s tuple!' - % module.family_name) - if not(0 <= prefixlen <= module.width): - raise AddrFormatError('invalid prefix for %s tuple!' \ - % module.family_name) - elif isinstance(addr, _str_type): - # CIDR-like string subnet - if implicit_prefix: - #TODO: deprecate this option in netaddr 0.8.x - addr = cidr_abbrev_to_verbose(addr) - - if '/' in addr: - val1, val2 = addr.split('/', 1) - else: - val1 = addr - val2 = None - - try: - ip = IPAddress(val1, module.version, flags=INET_PTON) - except AddrFormatError: - if module.version == 4: - # Try a partial IPv4 network address... - expanded_addr = _ipv4.expand_partial_address(val1) - ip = IPAddress(expanded_addr, module.version, flags=INET_PTON) - else: - raise AddrFormatError('invalid IPNetwork address %s!' % addr) - value = ip._value - - try: - # Integer CIDR prefix. - prefixlen = int(val2) - except TypeError: - if val2 is None: - # No prefix was specified. - prefixlen = module.width - except ValueError: - # Not an integer prefix, try a netmask/hostmask prefix. - mask = IPAddress(val2, module.version, flags=INET_PTON) - if mask.is_netmask(): - prefixlen = module.netmask_to_prefix[mask._value] - elif mask.is_hostmask(): - prefixlen = module.hostmask_to_prefix[mask._value] - else: - raise AddrFormatError('addr %r is not a valid IPNetwork!' \ - % addr) - - if not 0 <= prefixlen <= module.width: - raise AddrFormatError('invalid prefix for %s address!' \ - % module.family_name) - else: - raise TypeError('unexpected type %s for addr arg' % type(addr)) - - if flags & NOHOST: - # Remove host bits. - netmask = module.prefix_to_netmask[prefixlen] - value = value & netmask - - return value, prefixlen - - -class IPNetwork(BaseIP, IPListMixin): - """ - An IPv4 or IPv6 network or subnet. - - A combination of an IP address and a network mask. - - Accepts CIDR and several related variants : - - a) Standard CIDR:: - - x.x.x.x/y -> 192.0.2.0/24 - x::/y -> fe80::/10 - - b) Hybrid CIDR format (netmask address instead of prefix), where 'y' \ - address represent a valid netmask:: - - x.x.x.x/y.y.y.y -> 192.0.2.0/255.255.255.0 - x::/y:: -> fe80::/ffc0:: - - c) ACL hybrid CIDR format (hostmask address instead of prefix like \ - Cisco's ACL bitmasks), where 'y' address represent a valid netmask:: - - x.x.x.x/y.y.y.y -> 192.0.2.0/0.0.0.255 - x::/y:: -> fe80::/3f:ffff:ffff:ffff:ffff:ffff:ffff:ffff - - d) Abbreviated CIDR format (as of netaddr 0.7.x this requires the \ - optional constructor argument ``implicit_prefix=True``):: - - x -> 192 - x/y -> 10/8 - x.x/y -> 192.168/16 - x.x.x/y -> 192.168.0/24 - - which are equivalent to:: - - x.0.0.0/y -> 192.0.0.0/24 - x.0.0.0/y -> 10.0.0.0/8 - x.x.0.0/y -> 192.168.0.0/16 - x.x.x.0/y -> 192.168.0.0/24 - - """ - __slots__ = ('_prefixlen',) - - def __init__(self, addr, implicit_prefix=False, version=None, flags=0): - """ - Constructor. - - :param addr: an IPv4 or IPv6 address with optional CIDR prefix, - netmask or hostmask. May be an IP address in presentation - (string) format, an tuple containing and integer address and a - network prefix, or another IPAddress/IPNetwork object (copy - construction). - - :param implicit_prefix: (optional) if True, the constructor uses - classful IPv4 rules to select a default prefix when one is not - provided. If False it uses the length of the IP address version. - (default: False) - - :param version: (optional) optimizes version detection if specified - and distinguishes between IPv4 and IPv6 for addresses with an - equivalent integer value. - - :param flags: (optional) decides which rules are applied to the - interpretation of the addr value. Currently only supports the - NOHOST option. See the netaddr.core docs for further details. - - """ - super(IPNetwork, self).__init__() - - value, prefixlen, module = None, None, None - - if hasattr(addr, '_prefixlen'): - # IPNetwork object copy constructor - value = addr._value - module = addr._module - prefixlen = addr._prefixlen - elif hasattr(addr, '_value'): - # IPAddress object copy constructor - value = addr._value - module = addr._module - prefixlen = module.width - elif version == 4: - value, prefixlen = parse_ip_network(_ipv4, addr, - implicit_prefix=implicit_prefix, flags=flags) - module = _ipv4 - elif version == 6: - value, prefixlen = parse_ip_network(_ipv6, addr, - implicit_prefix=implicit_prefix, flags=flags) - module = _ipv6 - else: - if version is not None: - raise ValueError('%r is an invalid IP version!' % version) - try: - module = _ipv4 - value, prefixlen = parse_ip_network(module, addr, - implicit_prefix, flags) - except AddrFormatError: - try: - module = _ipv6 - value, prefixlen = parse_ip_network(module, addr, - implicit_prefix, flags) - except AddrFormatError: - pass - - if value is None: - raise AddrFormatError('invalid IPNetwork %s' % addr) - - self._value = value - self._prefixlen = prefixlen - self._module = module - - def __getstate__(self): - """:return: Pickled state of an `IPNetwork` object.""" - return self._value, self._prefixlen, self._module.version - - def __setstate__(self, state): - """ - :param state: data used to unpickle a pickled `IPNetwork` object. - - """ - value, prefixlen, version = state - - self._value = value - - if version == 4: - self._module = _ipv4 - elif version == 6: - self._module = _ipv6 - else: - raise ValueError('unpickling failed for object state %s' \ - % str(state)) - - if 0 <= prefixlen <= self._module.width: - self._prefixlen = prefixlen - else: - raise ValueError('unpickling failed for object state %s' \ - % str(state)) - - def _set_prefixlen(self, value): - if not isinstance(value, _int_type): - raise TypeError('int argument expected, not %s' % type(value)) - if not 0 <= value <= self._module.width: - raise AddrFormatError('invalid prefix for an %s address!' \ - % self._module.family_name) - self._prefixlen = value - - prefixlen = property(lambda self: self._prefixlen, _set_prefixlen, - doc='size of the bitmask used to separate the network from the host bits') - - @property - def ip(self): - """ - The IP address of this `IPNetwork` object. This is may or may not be - the same as the network IP address which varies according to the value - of the CIDR subnet prefix. - """ - return IPAddress(self._value, self._module.version) - - @property - def network(self): - """The network address of this `IPNetwork` object.""" - return IPAddress(self._value & self._netmask_int, self._module.version) - - @property - def broadcast(self): - """The broadcast address of this `IPNetwork` object""" - return IPAddress(self._value | self._hostmask_int, self._module.version) - - @property - def first(self): - """ - The integer value of first IP address found within this `IPNetwork` - object. - """ - return self._value & (self._module.max_int ^ self._hostmask_int) - - @property - def last(self): - """ - The integer value of last IP address found within this `IPNetwork` - object. - """ - hostmask = (1 << (self._module.width - self._prefixlen)) - 1 - return self._value | hostmask - - @property - def netmask(self): - """The subnet mask of this `IPNetwork` object.""" - netmask = self._module.max_int ^ self._hostmask_int - return IPAddress(netmask, self._module.version) - - @property - def _netmask_int(self): - """Same as self.netmask, but in integer format""" - return self._module.max_int ^ self._hostmask_int - - @property - def hostmask(self): - """The host mask of this `IPNetwork` object.""" - hostmask = (1 << (self._module.width - self._prefixlen)) - 1 - return IPAddress(hostmask, self._module.version) - - @property - def _hostmask_int(self): - """Same as self.hostmask, but in integer format""" - return (1 << (self._module.width - self._prefixlen)) - 1 - - @property - def cidr(self): - """ - The true CIDR address for this `IPNetwork` object which omits any - host bits to the right of the CIDR subnet prefix. - """ - return IPNetwork( - (self._value & self._netmask_int, self._prefixlen), - version=self._module.version) - - def __iadd__(self, num): - """ - Increases the value of this `IPNetwork` object by the current size - multiplied by ``num``. - - An `IndexError` is raised if result exceeds maximum IP address value - or is less than zero. - - :param num: (optional) number of `IPNetwork` blocks to increment \ - this IPNetwork's value by. - """ - new_value = int(self.network) + (self.size * num) - - if (new_value + (self.size - 1)) > self._module.max_int: - raise IndexError('increment exceeds address boundary!') - if new_value < 0: - raise IndexError('increment is less than zero!') - - self._value = new_value - return self - - def __isub__(self, num): - """ - Decreases the value of this `IPNetwork` object by the current size - multiplied by ``num``. - - An `IndexError` is raised if result is less than zero or exceeds - maximum IP address value. - - :param num: (optional) number of `IPNetwork` blocks to decrement \ - this IPNetwork's value by. - """ - new_value = int(self.network) - (self.size * num) - - if new_value < 0: - raise IndexError('decrement is less than zero!') - if (new_value + (self.size - 1)) > self._module.max_int: - raise IndexError('decrement exceeds address boundary!') - - self._value = new_value - return self - - def __contains__(self, other): - """ - :param other: an `IPAddress` or ranged IP object. - - :return: ``True`` if other falls within the boundary of this one, - ``False`` otherwise. - """ - if isinstance(other, BaseIP): - if self._module.version != other._module.version: - return False - - # self_net will contain only the network bits. - shiftwidth = self._module.width - self._prefixlen - self_net = self._value >> shiftwidth - if isinstance(other, IPRange): - # IPRange has no _value. - # (self_net+1)<<shiftwidth is not our last address, but the one - # after the last one. - return ((self_net << shiftwidth) <= other._start._value and - (((self_net + 1) << shiftwidth) > other._end._value)) - - other_net = other._value >> shiftwidth - if isinstance(other, IPAddress): - return other_net == self_net - if isinstance(other, IPNetwork): - return self_net == other_net and self._prefixlen <= other._prefixlen - - # Whatever it is, try to interpret it as IPAddress. - return IPAddress(other) in self - - def key(self): - """ - :return: A key tuple used to uniquely identify this `IPNetwork`. - """ - return self._module.version, self.first, self.last - - def sort_key(self): - """ - :return: A key tuple used to compare and sort this `IPNetwork` correctly. - """ - net_size_bits = self._prefixlen - 1 - first = self._value & (self._module.max_int ^ self._hostmask_int) - host_bits = self._value - first - return self._module.version, first, net_size_bits, host_bits - - def ipv4(self): - """ - :return: A numerically equivalent version 4 `IPNetwork` object. \ - Raises an `AddrConversionError` if IPv6 address cannot be \ - converted to IPv4. - """ - ip = None - klass = self.__class__ - - if self._module.version == 4: - ip = klass('%s/%d' % (self.ip, self.prefixlen)) - elif self._module.version == 6: - if 0 <= self._value <= _ipv4.max_int: - addr = _ipv4.int_to_str(self._value) - ip = klass('%s/%d' % (addr, self.prefixlen - 96)) - elif _ipv4.max_int <= self._value <= 0xffffffffffff: - addr = _ipv4.int_to_str(self._value - 0xffff00000000) - ip = klass('%s/%d' % (addr, self.prefixlen - 96)) - else: - raise AddrConversionError('IPv6 address %s unsuitable for ' \ - 'conversion to IPv4!' % self) - return ip - - def ipv6(self, ipv4_compatible=False): - """ - .. note:: the IPv4-mapped IPv6 address format is now considered \ - deprecated. See RFC 4291 or later for details. - - :param ipv4_compatible: If ``True`` returns an IPv4-mapped address - (::ffff:x.x.x.x), an IPv4-compatible (::x.x.x.x) address - otherwise. Default: False (IPv4-mapped). - - :return: A numerically equivalent version 6 `IPNetwork` object. - """ - ip = None - klass = self.__class__ - - if self._module.version == 6: - if ipv4_compatible and \ - (0xffff00000000 <= self._value <= 0xffffffffffff): - ip = klass((self._value - 0xffff00000000, self._prefixlen), - version=6) - else: - ip = klass((self._value, self._prefixlen), version=6) - elif self._module.version == 4: - if ipv4_compatible: - # IPv4-Compatible IPv6 address - ip = klass((self._value, self._prefixlen + 96), version=6) - else: - # IPv4-Mapped IPv6 address - ip = klass((0xffff00000000 + self._value, - self._prefixlen + 96), version=6) - - return ip - - def previous(self, step=1): - """ - :param step: the number of IP subnets between this `IPNetwork` object - and the expected subnet. Default: 1 (the previous IP subnet). - - :return: The adjacent subnet preceding this `IPNetwork` object. - """ - ip_copy = self.__class__('%s/%d' % (self.network, self.prefixlen), - self._module.version) - ip_copy -= step - return ip_copy - - def next(self, step=1): - """ - :param step: the number of IP subnets between this `IPNetwork` object - and the expected subnet. Default: 1 (the next IP subnet). - - :return: The adjacent subnet succeeding this `IPNetwork` object. - """ - ip_copy = self.__class__('%s/%d' % (self.network, self.prefixlen), - self._module.version) - ip_copy += step - return ip_copy - - def supernet(self, prefixlen=0): - """ - Provides a list of supernets for this `IPNetwork` object between the - size of the current prefix and (if specified) an endpoint prefix. - - :param prefixlen: (optional) a CIDR prefix for the maximum supernet. - Default: 0 - returns all possible supernets. - - :return: a tuple of supernet `IPNetwork` objects. - """ - if not 0 <= prefixlen <= self._module.width: - raise ValueError('CIDR prefix /%d invalid for IPv%d!' \ - % (prefixlen, self._module.version)) - - supernets = [] - # Use a copy of self as we'll be editing it. - supernet = self.cidr - supernet._prefixlen = prefixlen - while supernet._prefixlen != self._prefixlen: - supernets.append(supernet.cidr) - supernet._prefixlen += 1 - return supernets - - def subnet(self, prefixlen, count=None, fmt=None): - """ - A generator that divides up this IPNetwork's subnet into smaller - subnets based on a specified CIDR prefix. - - :param prefixlen: a CIDR prefix indicating size of subnets to be - returned. - - :param count: (optional) number of consecutive IP subnets to be - returned. - - :return: an iterator containing IPNetwork subnet objects. - """ - if not 0 <= self.prefixlen <= self._module.width: - raise ValueError('CIDR prefix /%d invalid for IPv%d!' \ - % (prefixlen, self._module.version)) - - if not self.prefixlen <= prefixlen: - # Don't return anything. - raise StopIteration - - # Calculate number of subnets to be returned. - width = self._module.width - max_subnets = 2 ** (width - self.prefixlen) // 2 ** (width - prefixlen) - - if count is None: - count = max_subnets - - if not 1 <= count <= max_subnets: - raise ValueError('count outside of current IP subnet boundary!') - - base_subnet = self._module.int_to_str(self.first) - i = 0 - while(i < count): - subnet = self.__class__('%s/%d' % (base_subnet, prefixlen), - self._module.version) - subnet.value += (subnet.size * i) - subnet.prefixlen = prefixlen - i += 1 - yield subnet - - def iter_hosts(self): - """ - An generator that provides all the IP addresses that can be assigned - to hosts within the range of this IP object's subnet. - - - for IPv4, the network and broadcast addresses are always excluded. \ - Any subnet that contains less than 4 IP addresses yields an empty list. - - - for IPv6, only the unspecified address '::' or Subnet-Router anycast \ - address (first address in the network) is excluded. - - :return: an IPAddress iterator - """ - it_hosts = iter([]) - - if self._module.version == 4: - # IPv4 logic. - if self.size >= 4: - it_hosts = iter_iprange( - IPAddress(self.first + 1, self._module.version), - IPAddress(self.last - 1, self._module.version)) - else: - # IPv6 logic. - # RFC 4291 section 2.6.1 says that the first IP in the network is - # the Subnet-Router anycast address. This address cannot be - # assigned to a host, so use self.first+1. - if self.size >= 2: - it_hosts = iter_iprange( - IPAddress(self.first + 1, self._module.version), - IPAddress(self.last, self._module.version)) - return it_hosts - - def __str__(self): - """:return: this IPNetwork in CIDR format""" - addr = self._module.int_to_str(self._value) - return "%s/%s" % (addr, self.prefixlen) - - def __repr__(self): - """:return: Python statement to create an equivalent object""" - return "%s('%s')" % (self.__class__.__name__, self) - - -class IPRange(BaseIP, IPListMixin): - """ - An arbitrary IPv4 or IPv6 address range. - - Formed from a lower and upper bound IP address. The upper bound IP cannot - be numerically smaller than the lower bound and the IP version of both - must match. - - """ - __slots__ = ('_start', '_end') - - def __init__(self, start, end, flags=0): - """ - Constructor. - - :param start: an IPv4 or IPv6 address that forms the lower - boundary of this IP range. - - :param end: an IPv4 or IPv6 address that forms the upper - boundary of this IP range. - - :param flags: (optional) decides which rules are applied to the - interpretation of the start and end values. Supported constants - are INET_PTON and ZEROFILL. See the netaddr.core docs for further - details. - - """ - self._start = IPAddress(start, flags=flags) - self._module = self._start._module - self._end = IPAddress(end, self._module.version, flags=flags) - if int(self._start) > int(self._end): - raise AddrFormatError('lower bound IP greater than upper bound!') - - def __getstate__(self): - """:return: Pickled state of an `IPRange` object.""" - return self._start.value, self._end.value, self._module.version - - def __setstate__(self, state): - """ - :param state: data used to unpickle a pickled `IPRange` object. - """ - start, end, version = state - - self._start = IPAddress(start, version) - self._module = self._start._module - self._end = IPAddress(end, version) - - def __contains__(self, other): - if isinstance(other, BaseIP): - if self._module.version != other._module.version: - return False - if isinstance(other, IPAddress): - return (self._start._value <= other._value and - self._end._value >= other._value) - if isinstance(other, IPRange): - return (self._start._value <= other._start._value and - self._end._value >= other._end._value) - if isinstance(other, IPNetwork): - shiftwidth = other._module.width - other._prefixlen - other_start = (other._value >> shiftwidth) << shiftwidth - # Start of the next network after other - other_next_start = other_start + (1 << shiftwidth) - - return (self._start._value <= other_start and - self._end._value > other_next_start) - - # Whatever it is, try to interpret it as IPAddress. - return IPAddress(other) in self - - @property - def first(self): - """The integer value of first IP address in this `IPRange` object.""" - return int(self._start) - - @property - def last(self): - """The integer value of last IP address in this `IPRange` object.""" - return int(self._end) - - def key(self): - """ - :return: A key tuple used to uniquely identify this `IPRange`. - """ - return self._module.version, self.first, self.last - - def sort_key(self): - """ - :return: A key tuple used to compare and sort this `IPRange` correctly. - """ - skey = self._module.width - num_bits(self.size) - return self._module.version, self._start._value, skey - - def cidrs(self): - """ - The list of CIDR addresses found within the lower and upper bound - addresses of this `IPRange`. - """ - return iprange_to_cidrs(self._start, self._end) - - def __str__(self): - """:return: this `IPRange` in a common representational format.""" - return "%s-%s" % (self._start, self._end) - - def __repr__(self): - """:return: Python statement to create an equivalent object""" - return "%s('%s', '%s')" % (self.__class__.__name__, - self._start, self._end) - - -def iter_unique_ips(*args): - """ - :param args: A list of IP addresses and subnets passed in as arguments. - - :return: A generator that flattens out IP subnets, yielding unique - individual IP addresses (no duplicates). - """ - for cidr in cidr_merge(args): - for ip in cidr: - yield ip - - -def cidr_abbrev_to_verbose(abbrev_cidr): - """ - A function that converts abbreviated IPv4 CIDRs to their more verbose - equivalent. - - :param abbrev_cidr: an abbreviated CIDR. - - Uses the old-style classful IP address rules to decide on a default - subnet prefix if one is not explicitly provided. - - Only supports IPv4 addresses. - - Examples :: - - 10 - 10.0.0.0/8 - 10/16 - 10.0.0.0/16 - 128 - 128.0.0.0/16 - 128/8 - 128.0.0.0/8 - 192.168 - 192.168.0.0/16 - - :return: A verbose CIDR from an abbreviated CIDR or old-style classful \ - network address. The original value if it was not recognised as a \ - supported abbreviation. - """ - # Internal function that returns a prefix value based on the old IPv4 - # classful network scheme that has been superseded (almost) by CIDR. - def classful_prefix(octet): - octet = int(octet) - if not 0 <= octet <= 255: - raise IndexError('Invalid octet: %r!' % octet) - if 0 <= octet <= 127: # Legacy class 'A' classification. - return 8 - elif 128 <= octet <= 191: # Legacy class 'B' classification. - return 16 - elif 192 <= octet <= 223: # Legacy class 'C' classification. - return 24 - elif 224 <= octet <= 239: # Multicast address range. - return 4 - return 32 # Default. - - if _is_str(abbrev_cidr): - if ':' in abbrev_cidr or abbrev_cidr == '': - return abbrev_cidr - - try: - # Single octet partial integer or string address. - i = int(abbrev_cidr) - return "%s.0.0.0/%s" % (i, classful_prefix(i)) - except ValueError: - # Multi octet partial string address with optional prefix. - if '/' in abbrev_cidr: - part_addr, prefix = abbrev_cidr.split('/', 1) - - # Check prefix for validity. - try: - if not 0 <= int(prefix) <= 32: - raise ValueError('prefixlen in address %r out of range' \ - ' for IPv4!' % abbrev_cidr) - except ValueError: - return abbrev_cidr - else: - part_addr = abbrev_cidr - prefix = None - - tokens = part_addr.split('.') - if len(tokens) > 4: - # Not a recognisable format. - return abbrev_cidr - for i in range(4 - len(tokens)): - tokens.append('0') - - if prefix is None: - try: - prefix = classful_prefix(tokens[0]) - except ValueError: - return abbrev_cidr - - return "%s/%s" % ('.'.join(tokens), prefix) - except (TypeError, IndexError): - # Not a recognisable format. - return abbrev_cidr - - - -def cidr_merge(ip_addrs): - """ - A function that accepts an iterable sequence of IP addresses and subnets - merging them into the smallest possible list of CIDRs. It merges adjacent - subnets where possible, those contained within others and also removes - any duplicates. - - :param ip_addrs: an iterable sequence of IP addresses and subnets. - - :return: a summarized list of `IPNetwork` objects. - """ - # The algorithm is quite simple: For each CIDR we create an IP range. - # Sort them and merge when possible. Afterwars split them again - # optimally. - if not hasattr(ip_addrs, '__iter__'): - raise ValueError('A sequence or iterator is expected!') - - ranges = [] - - for ip in ip_addrs: - cidr = IPNetwork(ip) - # Since non-overlapping ranges are the common case, remember the original - ranges.append( (cidr.version, cidr.first, cidr.last, cidr) ) - - ranges.sort() - i = 1 - while i < len(ranges): - if ranges[i][0] == ranges[i - 1][0] and ranges[i][1] - 1 <= ranges[i - 1][2]: - ranges[i - 1] = (ranges[i][0], ranges[i - 1][1], max(ranges[i - 1][2], ranges[i][2])) - del ranges[i] - else: - i += 1 - - merged = [] - for range_tuple in ranges: - # If this range wasn't merged we can simply use the old cidr. - if len(range_tuple) == 4: - merged.append(range_tuple[3]) - else: - version = range_tuple[0] - range_start = IPAddress(range_tuple[1], version=version) - range_stop = IPAddress(range_tuple[2], version=version) - merged.extend(iprange_to_cidrs(range_start, range_stop)) - return merged - - -def cidr_exclude(target, exclude): - """ - Removes an exclude IP address or subnet from target IP subnet. - - :param target: the target IP address or subnet to be divided up. - - :param exclude: the IP address or subnet to be removed from target. - - :return: list of `IPNetwork` objects remaining after exclusion. - """ - left, _, right = cidr_partition(target, exclude) - - return left + right - -def cidr_partition(target, exclude): - """ - Partitions a target IP subnet on an exclude IP address. - - :param target: the target IP address or subnet to be divided up. - - :param exclude: the IP address or subnet to partition on - - :return: list of `IPNetwork` objects before, the partition and after, sorted. - - Adding the three lists returns the equivalent of the original subnet. - """ - - target = IPNetwork(target) - exclude = IPNetwork(exclude) - - if exclude.last < target.first: - # Exclude subnet's upper bound address less than target - # subnet's lower bound. - return [], [], [target.cidr] - elif target.last < exclude.first: - # Exclude subnet's lower bound address greater than target - # subnet's upper bound. - return [target.cidr], [], [] - - if target.prefixlen >= exclude.prefixlen: - # Exclude contains the target - return [], [target], [] - - left = [] - right = [] - - new_prefixlen = target.prefixlen + 1 - # Some @properties that are expensive to get and don't change below. - target_module_width = target._module.width - - target_first = target.first - version = exclude.version - i_lower = target_first - i_upper = target_first + (2 ** (target_module_width - new_prefixlen)) - - while exclude.prefixlen >= new_prefixlen: - if exclude.first >= i_upper: - left.append(IPNetwork((i_lower, new_prefixlen), version=version)) - matched = i_upper - else: - right.append(IPNetwork((i_upper, new_prefixlen), version=version)) - matched = i_lower - - new_prefixlen += 1 - - if new_prefixlen > target_module_width: - break - - i_lower = matched - i_upper = matched + (2 ** (target_module_width - new_prefixlen)) - - return left, [exclude], right[::-1] - - -def spanning_cidr(ip_addrs): - """ - Function that accepts a sequence of IP addresses and subnets returning - a single `IPNetwork` subnet that is large enough to span the lower and - upper bound IP addresses with a possible overlap on either end. - - :param ip_addrs: sequence of IP addresses and subnets. - - :return: a single spanning `IPNetwork` subnet. - """ - sorted_ips = sorted( - [IPNetwork(ip) for ip in ip_addrs]) - - if not len(sorted_ips) > 1: - raise ValueError('IP sequence must contain at least 2 elements!') - - lowest_ip = sorted_ips[0] - highest_ip = sorted_ips[-1] - - if lowest_ip.version != highest_ip.version: - raise TypeError('IP sequence cannot contain both IPv4 and IPv6!') - - ipnum = highest_ip.last - prefixlen = highest_ip.prefixlen - lowest_ipnum = lowest_ip.first - width = highest_ip._module.width - - while prefixlen > 0 and ipnum > lowest_ipnum: - prefixlen -= 1 - ipnum &= -(1<<(width-prefixlen)) - - return IPNetwork( (ipnum, prefixlen), version=lowest_ip.version ) - - -def iter_iprange(start, end, step=1): - """ - A generator that produces IPAddress objects between an arbitrary start - and stop IP address with intervals of step between them. Sequences - produce are inclusive of boundary IPs. - - :param start: start IP address. - - :param end: end IP address. - - :param step: (optional) size of step between IP addresses. Default: 1 - - :return: an iterator of one or more `IPAddress` objects. - """ - start = IPAddress(start) - end = IPAddress(end) - - if start.version != end.version: - raise TypeError('start and stop IP versions do not match!') - version = start.version - - step = int(step) - if step == 0: - raise ValueError('step argument cannot be zero') - - # We don't need objects from here, just integers. - start = int(start) - stop = int(end) - - negative_step = False - - if step < 0: - negative_step = True - - index = start - step - while True: - index += step - if negative_step: - if not index >= stop: - break - else: - if not index <= stop: - break - yield IPAddress(index, version) - - - -def iprange_to_cidrs(start, end): - """ - A function that accepts an arbitrary start and end IP address or subnet - and returns a list of CIDR subnets that fit exactly between the boundaries - of the two with no overlap. - - :param start: the start IP address or subnet. - - :param end: the end IP address or subnet. - - :return: a list of one or more IP addresses and subnets. - """ - cidr_list = [] - - start = IPNetwork(start) - end = IPNetwork(end) - - iprange = [start.first, end.last] - - # Get spanning CIDR covering both addresses. - cidr_span = spanning_cidr([start, end]) - width = start._module.width - - if cidr_span.first < iprange[0]: - exclude = IPNetwork((iprange[0]-1, width), version=start.version) - cidr_list = cidr_partition(cidr_span, exclude)[2] - cidr_span = cidr_list.pop() - if cidr_span.last > iprange[1]: - exclude = IPNetwork((iprange[1]+1, width), version=start.version) - cidr_list += cidr_partition(cidr_span, exclude)[0] - else: - cidr_list.append(cidr_span) - - return cidr_list - - -def smallest_matching_cidr(ip, cidrs): - """ - Matches an IP address or subnet against a given sequence of IP addresses - and subnets. - - :param ip: a single IP address or subnet. - - :param cidrs: a sequence of IP addresses and/or subnets. - - :return: the smallest (most specific) matching IPAddress or IPNetwork - object from the provided sequence, None if there was no match. - """ - match = None - - if not hasattr(cidrs, '__iter__'): - raise TypeError('IP address/subnet sequence expected, not %r!' - % cidrs) - - ip = IPAddress(ip) - for cidr in sorted([IPNetwork(cidr) for cidr in cidrs]): - if ip in cidr: - match = cidr - else: - if match is not None and cidr.network not in match: - break - - return match - - -def largest_matching_cidr(ip, cidrs): - """ - Matches an IP address or subnet against a given sequence of IP addresses - and subnets. - - :param ip: a single IP address or subnet. - - :param cidrs: a sequence of IP addresses and/or subnets. - - :return: the largest (least specific) matching IPAddress or IPNetwork - object from the provided sequence, None if there was no match. - """ - match = None - - if not hasattr(cidrs, '__iter__'): - raise TypeError('IP address/subnet sequence expected, not %r!' - % cidrs) - - ip = IPAddress(ip) - for cidr in sorted([IPNetwork(cidr) for cidr in cidrs]): - if ip in cidr: - match = cidr - break - - return match - - -def all_matching_cidrs(ip, cidrs): - """ - Matches an IP address or subnet against a given sequence of IP addresses - and subnets. - - :param ip: a single IP address. - - :param cidrs: a sequence of IP addresses and/or subnets. - - :return: all matching IPAddress and/or IPNetwork objects from the provided - sequence, an empty list if there was no match. - """ - matches = [] - - if not hasattr(cidrs, '__iter__'): - raise TypeError('IP address/subnet sequence expected, not %r!' - % cidrs) - - ip = IPAddress(ip) - for cidr in sorted([IPNetwork(cidr) for cidr in cidrs]): - if ip in cidr: - matches.append(cidr) - else: - if matches and cidr.network not in matches[-1]: - break - - return matches - -#----------------------------------------------------------------------------- -# Cached IPv4 address range lookups. -#----------------------------------------------------------------------------- -IPV4_LOOPBACK = IPNetwork('127.0.0.0/8') - -IPV4_PRIVATE = ( - IPNetwork('10.0.0.0/8'), # Private-Use Networks - IPNetwork('172.16.0.0/12'), # Private-Use Networks - IPNetwork('192.0.2.0/24'), # Test-Net - IPNetwork('192.168.0.0/16'), # Private-Use Networks - IPRange('239.0.0.0', '239.255.255.255'), # Administrative Multicast -) - -IPV4_LINK_LOCAL = IPNetwork('169.254.0.0/16') - -IPV4_MULTICAST = IPNetwork('224.0.0.0/4') - -IPV4_6TO4 = IPNetwork('192.88.99.0/24') # 6to4 Relay Anycast - -IPV4_RESERVED = ( - IPNetwork('192.0.0.0/24'), # Reserved but subject to allocation - IPNetwork('240.0.0.0/4'), # Reserved for Future Use - - # Reserved multicast - IPRange('234.0.0.0', '238.255.255.255'), - IPRange('225.0.0.0', '231.255.255.255'), -) - -#----------------------------------------------------------------------------- -# Cached IPv6 address range lookups. -#----------------------------------------------------------------------------- -IPV6_LOOPBACK = IPAddress('::1') - -IPV6_PRIVATE = ( - IPNetwork('fc00::/7'), # Unique Local Addresses (ULA) - IPNetwork('fec0::/10'), # Site Local Addresses (deprecated - RFC 3879) -) - -IPV6_LINK_LOCAL = IPNetwork('fe80::/10') - -IPV6_MULTICAST = IPNetwork('ff00::/8') - -IPV6_RESERVED = ( - IPNetwork('ff00::/12'), IPNetwork('::/8'), - IPNetwork('0100::/8'), IPNetwork('0200::/7'), - IPNetwork('0400::/6'), IPNetwork('0800::/5'), - IPNetwork('1000::/4'), IPNetwork('4000::/3'), - IPNetwork('6000::/3'), IPNetwork('8000::/3'), - IPNetwork('A000::/3'), IPNetwork('C000::/3'), - IPNetwork('E000::/4'), IPNetwork('F000::/5'), - IPNetwork('F800::/6'), IPNetwork('FE00::/9'), -) diff --git a/awx/lib/site-packages/netaddr/ip/glob.py b/awx/lib/site-packages/netaddr/ip/glob.py deleted file mode 100644 index dc0ec9975c..0000000000 --- a/awx/lib/site-packages/netaddr/ip/glob.py +++ /dev/null @@ -1,312 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -Routines and classes for supporting and expressing IP address ranges using a -glob style syntax. - -""" -from netaddr.core import AddrFormatError, AddrConversionError -from netaddr.ip import IPRange, IPAddress, IPNetwork, iprange_to_cidrs -from netaddr.compat import _is_str - - -def valid_glob(ipglob): - """ - :param ipglob: An IP address range in a glob-style format. - - :return: ``True`` if IP range glob is valid, ``False`` otherwise. - """ - #TODO: Add support for abbreviated ipglobs. - #TODO: e.g. 192.0.*.* == 192.0.* - #TODO: *.*.*.* == * - #TODO: Add strict flag to enable verbose ipglob checking. - if not _is_str(ipglob): - return False - - seen_hyphen = False - seen_asterisk = False - - octets = ipglob.split('.') - - if len(octets) != 4: - return False - - for octet in octets: - if '-' in octet: - if seen_hyphen: - return False - seen_hyphen = True - if seen_asterisk: - # Asterisks cannot precede hyphenated octets. - return False - try: - (octet1, octet2) = [int(i) for i in octet.split('-')] - except ValueError: - return False - if octet1 >= octet2: - return False - if not 0 <= octet1 <= 254: - return False - if not 1 <= octet2 <= 255: - return False - elif octet == '*': - seen_asterisk = True - else: - if seen_hyphen is True: - return False - if seen_asterisk is True: - return False - try: - if not 0 <= int(octet) <= 255: - return False - except ValueError: - return False - return True - - -def glob_to_iptuple(ipglob): - """ - A function that accepts a glob-style IP range and returns the component - lower and upper bound IP address. - - :param ipglob: an IP address range in a glob-style format. - - :return: a tuple contain lower and upper bound IP objects. - """ - if not valid_glob(ipglob): - raise AddrFormatError('not a recognised IP glob range: %r!' % ipglob) - - start_tokens = [] - end_tokens = [] - - for octet in ipglob.split('.'): - if '-' in octet: - tokens = octet.split('-') - start_tokens.append(tokens[0]) - end_tokens.append(tokens[1]) - elif octet == '*': - start_tokens.append('0') - end_tokens.append('255') - else: - start_tokens.append(octet) - end_tokens.append(octet) - - return IPAddress('.'.join(start_tokens)), IPAddress('.'.join(end_tokens)) - - -def glob_to_iprange(ipglob): - """ - A function that accepts a glob-style IP range and returns the equivalent - IP range. - - :param ipglob: an IP address range in a glob-style format. - - :return: an IPRange object. - """ - if not valid_glob(ipglob): - raise AddrFormatError('not a recognised IP glob range: %r!' % ipglob) - - start_tokens = [] - end_tokens = [] - - for octet in ipglob.split('.'): - if '-' in octet: - tokens = octet.split('-') - start_tokens.append(tokens[0]) - end_tokens.append(tokens[1]) - elif octet == '*': - start_tokens.append('0') - end_tokens.append('255') - else: - start_tokens.append(octet) - end_tokens.append(octet) - - return IPRange('.'.join(start_tokens), '.'.join(end_tokens)) - - -def iprange_to_globs(start, end): - """ - A function that accepts an arbitrary start and end IP address or subnet - and returns one or more glob-style IP ranges. - - :param start: the start IP address or subnet. - - :param end: the end IP address or subnet. - - :return: a list containing one or more IP globs. - """ - start = IPAddress(start) - end = IPAddress(end) - - if start.version != 4 and end.version != 4: - raise AddrConversionError('IP glob ranges only support IPv4!') - - def _iprange_to_glob(lb, ub): - # Internal function to process individual IP globs. - t1 = [int(_) for _ in str(lb).split('.')] - t2 = [int(_) for _ in str(ub).split('.')] - - tokens = [] - - seen_hyphen = False - seen_asterisk = False - - for i in range(4): - if t1[i] == t2[i]: - # A normal octet. - tokens.append(str(t1[i])) - elif (t1[i] == 0) and (t2[i] == 255): - # An asterisk octet. - tokens.append('*') - seen_asterisk = True - else: - # Create a hyphenated octet - only one allowed per IP glob. - if not seen_asterisk: - if not seen_hyphen: - tokens.append('%s-%s' % (t1[i], t2[i])) - seen_hyphen = True - else: - raise AddrConversionError('only 1 hyphenated octet' \ - ' per IP glob allowed!') - else: - raise AddrConversionError("asterisks are not allowed' \ - ' before hyphenated octets!") - - return '.'.join(tokens) - - globs = [] - - try: - # IP range can be represented by a single glob. - ipglob = _iprange_to_glob(start, end) - if not valid_glob(ipglob): - #TODO: this is a workaround, it is produces non-optimal but valid - #TODO: glob conversions. Fix inner function so that is always - #TODO: produces a valid glob. - raise AddrConversionError('invalid ip glob created') - globs.append(ipglob) - except AddrConversionError: - # Break IP range up into CIDRs before conversion to globs. - # - #TODO: this is still not completely optimised but is good enough - #TODO: for the moment. - # - for cidr in iprange_to_cidrs(start, end): - ipglob = _iprange_to_glob(cidr[0], cidr[-1]) - globs.append(ipglob) - - return globs - - -def glob_to_cidrs(ipglob): - """ - A function that accepts a glob-style IP range and returns a list of one - or more IP CIDRs that exactly matches it. - - :param ipglob: an IP address range in a glob-style format. - - :return: a list of one or more IP objects. - """ - return iprange_to_cidrs(*glob_to_iptuple(ipglob)) - - -def cidr_to_glob(cidr): - """ - A function that accepts an IP subnet in a glob-style format and returns - a list of CIDR subnets that exactly matches the specified glob. - - :param cidr: an IP object CIDR subnet. - - :return: a list of one or more IP addresses and subnets. - """ - ip = IPNetwork(cidr) - globs = iprange_to_globs(ip[0], ip[-1]) - if len(globs) != 1: - # There should only ever be a one to one mapping between a CIDR and - # an IP glob range. - raise AddrConversionError('bad CIDR to IP glob conversion!') - return globs[0] - - -class IPGlob(IPRange): - """ - Represents an IP address range using a glob-style syntax ``x.x.x-y.*`` - - Individual octets can be represented using the following shortcuts : - - 1. ``*`` - the asterisk octet (represents values ``0`` through ``255``) - 2. ``x-y`` - the hyphenated octet (represents values ``x`` through ``y``) - - A few basic rules also apply : - - 1. ``x`` must always be greater than ``y``, therefore : - - - ``x`` can only be ``0`` through ``254`` - - ``y`` can only be ``1`` through ``255`` - - 2. only one hyphenated octet per IP glob is allowed - 3. only asterisks are permitted after a hyphenated octet - - Examples: - - +------------------+------------------------------+ - | IP glob | Description | - +==================+==============================+ - | ``192.0.2.1`` | a single address | - +------------------+------------------------------+ - | ``192.0.2.0-31`` | 32 addresses | - +------------------+------------------------------+ - | ``192.0.2.*`` | 256 addresses | - +------------------+------------------------------+ - | ``192.0.2-3.*`` | 512 addresses | - +------------------+------------------------------+ - | ``192.0-1.*.*`` | 131,072 addresses | - +------------------+------------------------------+ - | ``*.*.*.*`` | the whole IPv4 address space | - +------------------+------------------------------+ - - .. note :: \ - IP glob ranges are not directly equivalent to CIDR blocks. \ - They can represent address ranges that do not fall on strict bit mask \ - boundaries. They are suitable for use in configuration files, being \ - more obvious and readable than their CIDR counterparts, especially for \ - admins and end users with little or no networking knowledge or \ - experience. All CIDR addresses can always be represented as IP globs \ - but the reverse is not always true. - """ - __slots__ = ('_glob',) - - def __init__(self, ipglob): - (start, end) = glob_to_iptuple(ipglob) - super(IPGlob, self).__init__(start, end) - self.glob = iprange_to_globs(self._start, self._end)[0] - - def __getstate__(self): - """:return: Pickled state of an `IPGlob` object.""" - return super(IPGlob, self).__getstate__() - - def __setstate__(self, state): - """:param state: data used to unpickle a pickled `IPGlob` object.""" - super(IPGlob, self).__setstate__(state) - self.glob = iprange_to_globs(self._start, self._end)[0] - - def _get_glob(self): - return self._glob - - def _set_glob(self, ipglob): - (self._start, self._end) = glob_to_iptuple(ipglob) - self._glob = iprange_to_globs(self._start, self._end)[0] - - glob = property(_get_glob, _set_glob, None, - 'an arbitrary IP address range in glob format.') - - def __str__(self): - """:return: IP glob in common representational format.""" - return "%s" % self.glob - - def __repr__(self): - """:return: Python statement to create an equivalent object""" - return "%s('%s')" % (self.__class__.__name__, self.glob) diff --git a/awx/lib/site-packages/netaddr/ip/iana.py b/awx/lib/site-packages/netaddr/ip/iana.py deleted file mode 100755 index 01e51b09c8..0000000000 --- a/awx/lib/site-packages/netaddr/ip/iana.py +++ /dev/null @@ -1,430 +0,0 @@ -#!/usr/bin/env python -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -# -# DISCLAIMER -# -# netaddr is not sponsored nor endorsed by IANA. -# -# Use of data from IANA (Internet Assigned Numbers Authority) is subject to -# copyright and is provided with prior written permission. -# -# IANA data files included with netaddr are not modified in any way but are -# parsed and made available to end users through an API. -# -# See README file and source code for URLs to latest copies of the relevant -# files. -# -#----------------------------------------------------------------------------- -""" -Routines for accessing data published by IANA (Internet Assigned Numbers -Authority). - -More details can be found at the following URLs :- - - - IANA Home Page - http://www.iana.org/ - - IEEE Protocols Information Home Page - http://www.iana.org/protocols/ -""" - -import os as _os -import os.path as _path -import sys as _sys - -from xml.sax import make_parser, handler - -from netaddr.core import Publisher, Subscriber, dos2unix -from netaddr.ip import IPAddress, IPNetwork, IPRange, cidr_abbrev_to_verbose - -from netaddr.compat import _dict_items, _callable - - - -#: Topic based lookup dictionary for IANA information. -IANA_INFO = { - 'IPv4' : {}, - 'IPv6' : {}, - 'multicast' : {}, -} - - - -class SaxRecordParser(handler.ContentHandler): - - def __init__(self, callback=None): - self._level = 0 - self._is_active = False - self._record = None - self._tag_level = None - self._tag_payload = None - self._tag_feeding = None - self._callback = callback - - def startElement(self, name, attrs): - self._level += 1 - - if self._is_active is False: - if name == 'record': - self._is_active = True - self._tag_level = self._level - self._record = {} - if 'date' in attrs: - self._record['date'] = attrs['date'] - elif self._level == self._tag_level + 1: - if name == 'xref': - if 'type' in attrs and 'data' in attrs: - l = self._record.setdefault(attrs['type'], []) - l.append(attrs['data']) - else: - self._tag_payload = [] - self._tag_feeding = True - else: - self._tag_feeding = False - - def endElement(self, name): - if self._is_active is True: - if name == 'record' and self._tag_level == self._level: - self._is_active = False - self._tag_level = None - if _callable(self._callback): - self._callback(self._record) - self._record = None - elif self._level == self._tag_level + 1: - if name != 'xref': - self._record[name] = ''.join(self._tag_payload) - self._tag_payload = None - self._tag_feeding = False - - self._level -= 1 - - def characters(self, content): - if self._tag_feeding is True: - self._tag_payload.append(content) - - -class XMLRecordParser(Publisher): - """ - A configurable Parser that understands how to parse XML based records. - """ - def __init__(self, fh, **kwargs): - """ - Constructor. - - fh - a valid, open file handle to XML based record data. - """ - super(XMLRecordParser, self).__init__() - - self.xmlparser = make_parser() - self.xmlparser.setContentHandler(SaxRecordParser(self.consume_record)) - - self.fh = fh - - self.__dict__.update(kwargs) - - def process_record(self, rec): - """ - This is the callback method invoked for every record. It is usually - over-ridden by base classes to provide specific record-based logic. - - Any record can be vetoed (not passed to registered Subscriber objects) - by simply returning None. - """ - return rec - - def consume_record(self, rec): - record = self.process_record(rec) - if record is not None: - self.notify(record) - - def parse(self): - """ - Parse and normalises records, notifying registered subscribers with - record data as it is encountered. - """ - self.xmlparser.parse(self.fh) - - -class IPv4Parser(XMLRecordParser): - """ - A XMLRecordParser that understands how to parse and retrieve data records - from the IANA IPv4 address space file. - - It can be found online here :- - - - http://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xml - """ - def __init__(self, fh, **kwargs): - """ - Constructor. - - fh - a valid, open file handle to an IANA IPv4 address space file. - - kwargs - additional parser options. - """ - super(IPv4Parser, self).__init__(fh) - - def process_record(self, rec): - """ - Callback method invoked for every record. - - See base class method for more details. - """ - - record = {} - for key in ('prefix', 'designation', 'date', 'whois', 'status'): - record[key] = str(rec.get(key, '')).strip() - - # Strip leading zeros from octet. - if '/' in record['prefix']: - (octet, prefix) = record['prefix'].split('/') - record['prefix'] = '%d/%d' % (int(octet), int(prefix)) - - record['status'] = record['status'].capitalize() - - return record - - -class IPv6Parser(XMLRecordParser): - """ - A XMLRecordParser that understands how to parse and retrieve data records - from the IANA IPv6 address space file. - - It can be found online here :- - - - http://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xml - """ - def __init__(self, fh, **kwargs): - """ - Constructor. - - fh - a valid, open file handle to an IANA IPv6 address space file. - - kwargs - additional parser options. - """ - super(IPv6Parser, self).__init__(fh) - - def process_record(self, rec): - """ - Callback method invoked for every record. - - See base class method for more details. - """ - - record = { - 'prefix': str(rec.get('prefix', '')).strip(), - 'allocation': str(rec.get('description', '')).strip(), - 'reference': str(rec.get('rfc', [''])[0]).strip(), - } - - return record - - -class MulticastParser(XMLRecordParser): - """ - A XMLRecordParser that knows how to process the IANA IPv4 multicast address - allocation file. - - It can be found online here :- - - - http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xml - """ - def __init__(self, fh, **kwargs): - """ - Constructor. - - fh - a valid, open file handle to an IANA IPv4 multicast address - allocation file. - - kwargs - additional parser options. - """ - super(MulticastParser, self).__init__(fh) - - def normalise_addr(self, addr): - """ - Removes variations from address entries found in this particular file. - """ - if '-' in addr: - (a1, a2) = addr.split('-') - o1 = a1.strip().split('.') - o2 = a2.strip().split('.') - return '%s-%s' % ('.'.join([str(int(i)) for i in o1]), - '.'.join([str(int(i)) for i in o2])) - else: - o1 = addr.strip().split('.') - return '.'.join([str(int(i)) for i in o1]) - - def process_record(self, rec): - """ - Callback method invoked for every record. - - See base class method for more details. - """ - - if 'addr' in rec: - record = { - 'address': self.normalise_addr(str(rec['addr'])), - 'descr': str(rec.get('description', '')), - } - return record - - -class DictUpdater(Subscriber): - """ - Concrete Subscriber that inserts records received from a Publisher into a - dictionary. - """ - def __init__(self, dct, topic, unique_key): - """ - Constructor. - - dct - lookup dict or dict like object to insert records into. - - topic - high-level category name of data to be processed. - - unique_key - key name in data dict that uniquely identifies it. - """ - self.dct = dct - self.topic = topic - self.unique_key = unique_key - - def update(self, data): - """ - Callback function used by Publisher to notify this Subscriber about - an update. Stores topic based information into dictionary passed to - constructor. - """ - data_id = data[self.unique_key] - - if self.topic == 'IPv4': - cidr = IPNetwork(cidr_abbrev_to_verbose(data_id)) - self.dct[cidr] = data - elif self.topic == 'IPv6': - cidr = IPNetwork(cidr_abbrev_to_verbose(data_id)) - self.dct[cidr] = data - elif self.topic == 'multicast': - iprange = None - if '-' in data_id: - # See if we can manage a single CIDR. - (first, last) = data_id.split('-') - iprange = IPRange(first, last) - cidrs = iprange.cidrs() - if len(cidrs) == 1: - iprange = cidrs[0] - else: - iprange = IPAddress(data_id) - self.dct[iprange] = data - - -def load_info(): - """ - Parse and load internal IANA data lookups with the latest information from - data files. - """ - PATH = _path.dirname(__file__) - - ipv4 = IPv4Parser(open(_path.join(PATH, 'ipv4-address-space.xml'))) - ipv4.attach(DictUpdater(IANA_INFO['IPv4'], 'IPv4', 'prefix')) - ipv4.parse() - - ipv6 = IPv6Parser(open(_path.join(PATH, 'ipv6-address-space.xml'))) - ipv6.attach(DictUpdater(IANA_INFO['IPv6'], 'IPv6', 'prefix')) - ipv6.parse() - - mcast = MulticastParser(open(_path.join(PATH, 'multicast-addresses.xml'))) - mcast.attach(DictUpdater(IANA_INFO['multicast'], 'multicast', 'address')) - mcast.parse() - - -def pprint_info(fh=None): - """ - Pretty prints IANA information to filehandle. - """ - if fh is None: - fh = _sys.stdout - - for category in sorted(IANA_INFO): - fh.write('-' * len(category) + "\n") - fh.write(category + "\n") - fh.write('-' * len(category) + "\n") - ipranges = IANA_INFO[category] - for iprange in sorted(ipranges): - details = ipranges[iprange] - fh.write('%-45r' % (iprange) + details + "\n") - - -def query(ip_addr): - """ - Returns informational data specific to this IP address. - """ - info = {} - - def within_bounds(ip, ip_range): - # Boundary checking for multiple IP classes. - if hasattr(ip_range, 'first'): - # IP network or IP range. - return ip in ip_range - elif hasattr(ip_range, 'value'): - # IP address. - return ip == ip_range - - raise Exception('Unsupported IP range or address: %r!' % ip_range) - - if ip_addr.version == 4: - for cidr, record in _dict_items(IANA_INFO['IPv4']): - if within_bounds(ip_addr, cidr): - info.setdefault('IPv4', []) - info['IPv4'].append(record) - - if ip_addr.is_multicast(): - for iprange, record in _dict_items(IANA_INFO['multicast']): - if within_bounds(ip_addr, iprange): - info.setdefault('Multicast', []) - info['Multicast'].append(record) - - elif ip_addr.version == 6: - for cidr, record in _dict_items(IANA_INFO['IPv6']): - if within_bounds(ip_addr, cidr): - info.setdefault('IPv6', []) - info['IPv6'].append(record) - - return info - - -def get_latest_files(): - """Download the latest files from IANA""" - if _sys.version_info[0] == 3: - # Python 3.x - from urllib.request import Request, urlopen - else: - # Python 2.x - from urllib2 import Request, urlopen - - urls = [ - 'http://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xml', - 'http://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xml', - 'http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xml', - ] - - for url in urls: - _sys.stdout.write('downloading latest copy of %s\n' % url) - request = Request(url) - response = urlopen(request) - save_path = _path.dirname(__file__) - basename = _os.path.basename(response.geturl().rstrip('/')) - filename = _path.join(save_path, basename) - fh = open(filename, 'wb') - fh.write(response.read()) - fh.close() - - # Make sure the line endings are consistent across platforms. - dos2unix(filename) - - -if __name__ == '__main__': - # Generate indices when module is executed as a script. - get_latest_files() - -# On module import, read IANA data files and populate lookups dict. -load_info() diff --git a/awx/lib/site-packages/netaddr/ip/ipv4-address-space.xml b/awx/lib/site-packages/netaddr/ip/ipv4-address-space.xml deleted file mode 100644 index 91fae8e377..0000000000 --- a/awx/lib/site-packages/netaddr/ip/ipv4-address-space.xml +++ /dev/null @@ -1,1864 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<?xml-stylesheet type="text/xsl" href="ipv4-address-space.xsl"?> -<?oxygen RNGSchema="ipv4-address-space.rng" type="xml"?> -<registry xmlns="http://www.iana.org/assignments" id="ipv4-address-space"> - <title>IANA IPv4 Address Space Registry - Internet Protocol version 4 (IPv4) Address Space - 2014-10-14 - - Allocations to RIRs are made in line with the Global Policy published at . -All other assignments require IETF Review. - The allocation of Internet Protocol version 4 (IPv4) address space to various registries is listed -here. Originally, all the IPv4 address spaces was managed directly by the IANA. Later parts of the -address space were allocated to various other registries to manage for particular purposes or -regional areas of the world. RFC 1466 documents most of these allocations. - - 000/8 - IANA - Local Identification - 1981-09 - RESERVED - - - - 001/8 - APNIC - 2010-01 - whois.apnic.net - ALLOCATED - - - 002/8 - RIPE NCC - 2009-09 - whois.ripe.net - ALLOCATED - - - 003/8 - General Electric Company - 1994-05 - whois.arin.net - LEGACY - - - 004/8 - Level 3 Communications, Inc. - 1992-12 - whois.arin.net - LEGACY - - - 005/8 - RIPE NCC - 2010-11 - whois.ripe.net - ALLOCATED - - - 006/8 - Army Information Systems Center - 1994-02 - whois.arin.net - LEGACY - - - 007/8 - Administered by ARIN - 1995-04 - whois.arin.net - LEGACY - - - 008/8 - Level 3 Communications, Inc. - 1992-12 - whois.arin.net - LEGACY - - - 009/8 - IBM - 1992-08 - whois.arin.net - LEGACY - - - 010/8 - IANA - Private Use - 1995-06 - RESERVED - - - - 011/8 - DoD Intel Information Systems - 1993-05 - whois.arin.net - LEGACY - - - 012/8 - AT&T Bell Laboratories - 1995-06 - whois.arin.net - LEGACY - - - 013/8 - Xerox Corporation - 1991-09 - whois.arin.net - LEGACY - - - 014/8 - APNIC - 2010-04 - whois.apnic.net - ALLOCATED - - - - 015/8 - Hewlett-Packard Company - 1994-07 - whois.arin.net - LEGACY - - - 016/8 - Digital Equipment Corporation - 1994-11 - whois.arin.net - LEGACY - - - 017/8 - Apple Computer Inc. - 1992-07 - whois.arin.net - LEGACY - - - 018/8 - MIT - 1994-01 - whois.arin.net - LEGACY - - - 019/8 - Ford Motor Company - 1995-05 - whois.arin.net - LEGACY - - - 020/8 - Computer Sciences Corporation - 1994-10 - whois.arin.net - LEGACY - - - 021/8 - DDN-RVN - 1991-07 - whois.arin.net - LEGACY - - - 022/8 - Defense Information Systems Agency - 1993-05 - whois.arin.net - LEGACY - - - 023/8 - ARIN - 2010-11 - whois.arin.net - ALLOCATED - - - 024/8 - ARIN - 2001-05 - whois.arin.net - ALLOCATED - - - 025/8 - UK Ministry of Defence - 1995-01 - whois.ripe.net - LEGACY - - - 026/8 - Defense Information Systems Agency - 1995-05 - whois.arin.net - LEGACY - - - 027/8 - APNIC - 2010-01 - whois.apnic.net - ALLOCATED - - - 028/8 - DSI-North - 1992-07 - whois.arin.net - LEGACY - - - 029/8 - Defense Information Systems Agency - 1991-07 - whois.arin.net - LEGACY - - - 030/8 - Defense Information Systems Agency - 1991-07 - whois.arin.net - LEGACY - - - 031/8 - RIPE NCC - 2010-05 - whois.ripe.net - ALLOCATED - - - 032/8 - AT&T Global Network Services - 1994-06 - whois.arin.net - LEGACY - - - 033/8 - DLA Systems Automation Center - 1991-01 - whois.arin.net - LEGACY - - - 034/8 - Halliburton Company - 1993-03 - whois.arin.net - LEGACY - - - 035/8 - Administered by ARIN - 1994-04 - whois.arin.net - LEGACY - - - 036/8 - APNIC - 2010-10 - whois.apnic.net - ALLOCATED - - - 037/8 - RIPE NCC - 2010-11 - whois.ripe.net - ALLOCATED - - - 038/8 - PSINet, Inc. - 1994-09 - whois.arin.net - LEGACY - - - 039/8 - APNIC - 2011-01 - whois.apnic.net - ALLOCATED - - - 040/8 - Administered by ARIN - 1994-06 - whois.arin.net - LEGACY - - - 041/8 - AFRINIC - 2005-04 - whois.afrinic.net - ALLOCATED - - - 042/8 - APNIC - 2010-10 - whois.apnic.net - ALLOCATED - - - 043/8 - Administered by APNIC - 1991-01 - whois.apnic.net - LEGACY - - - 044/8 - Amateur Radio Digital Communications - 1992-07 - whois.arin.net - LEGACY - - - 045/8 - Administered by ARIN - 1995-01 - whois.arin.net - LEGACY - - - 046/8 - RIPE NCC - 2009-09 - whois.ripe.net - ALLOCATED - - - 047/8 - Administered by ARIN - 1991-01 - whois.arin.net - LEGACY - - - 048/8 - Prudential Securities Inc. - 1995-05 - whois.arin.net - LEGACY - - - 049/8 - APNIC - 2010-08 - whois.apnic.net - ALLOCATED - - - 050/8 - ARIN - 2010-02 - whois.arin.net - ALLOCATED - - - 051/8 - UK Government Department for Work and Pensions - 1994-08 - whois.ripe.net - LEGACY - - - 052/8 - E.I. duPont de Nemours and Co., Inc. - 1991-12 - whois.arin.net - LEGACY - - - 053/8 - Daimler AG - 1993-10 - whois.ripe.net - LEGACY - - - 054/8 - Administered by ARIN - 1992-03 - whois.arin.net - LEGACY - - - 055/8 - DoD Network Information Center - 1995-04 - whois.arin.net - LEGACY - - - 056/8 - US Postal Service - 1994-06 - whois.arin.net - LEGACY - - - 057/8 - Societe Internationale de Telecommunications Aeronautiques S.C.R.L. - 1995-05 - whois.ripe.net - LEGACY - - - 058/8 - APNIC - 2004-04 - whois.apnic.net - ALLOCATED - - - 059/8 - APNIC - 2004-04 - whois.apnic.net - ALLOCATED - - - 060/8 - APNIC - 2003-04 - whois.apnic.net - ALLOCATED - - - 061/8 - APNIC - 1997-04 - whois.apnic.net - ALLOCATED - - - 062/8 - RIPE NCC - 1997-04 - whois.ripe.net - ALLOCATED - - - 063/8 - ARIN - 1997-04 - whois.arin.net - ALLOCATED - - - 064/8 - ARIN - 1999-07 - whois.arin.net - ALLOCATED - - - 065/8 - ARIN - 2000-07 - whois.arin.net - ALLOCATED - - - 066/8 - ARIN - 2000-07 - whois.arin.net - ALLOCATED - - - 067/8 - ARIN - 2001-05 - whois.arin.net - ALLOCATED - - - 068/8 - ARIN - 2001-06 - whois.arin.net - ALLOCATED - - - 069/8 - ARIN - 2002-08 - whois.arin.net - ALLOCATED - - - 070/8 - ARIN - 2004-01 - whois.arin.net - ALLOCATED - - - 071/8 - ARIN - 2004-08 - whois.arin.net - ALLOCATED - - - 072/8 - ARIN - 2004-08 - whois.arin.net - ALLOCATED - - - 073/8 - ARIN - 2005-03 - whois.arin.net - ALLOCATED - - - 074/8 - ARIN - 2005-06 - whois.arin.net - ALLOCATED - - - 075/8 - ARIN - 2005-06 - whois.arin.net - ALLOCATED - - - 076/8 - ARIN - 2005-06 - whois.arin.net - ALLOCATED - - - 077/8 - RIPE NCC - 2006-08 - whois.ripe.net - ALLOCATED - - - 078/8 - RIPE NCC - 2006-08 - whois.ripe.net - ALLOCATED - - - 079/8 - RIPE NCC - 2006-08 - whois.ripe.net - ALLOCATED - - - 080/8 - RIPE NCC - 2001-04 - whois.ripe.net - ALLOCATED - - - 081/8 - RIPE NCC - 2001-04 - whois.ripe.net - ALLOCATED - - - 082/8 - RIPE NCC - 2002-11 - whois.ripe.net - ALLOCATED - - - 083/8 - RIPE NCC - 2003-11 - whois.ripe.net - ALLOCATED - - - 084/8 - RIPE NCC - 2003-11 - whois.ripe.net - ALLOCATED - - - 085/8 - RIPE NCC - 2004-04 - whois.ripe.net - ALLOCATED - - - 086/8 - RIPE NCC - 2004-04 - whois.ripe.net - ALLOCATED - - - 087/8 - RIPE NCC - 2004-04 - whois.ripe.net - ALLOCATED - - - 088/8 - RIPE NCC - 2004-04 - whois.ripe.net - ALLOCATED - - - 089/8 - RIPE NCC - 2005-06 - whois.ripe.net - ALLOCATED - - - 090/8 - RIPE NCC - 2005-06 - whois.ripe.net - ALLOCATED - - - 091/8 - RIPE NCC - 2005-06 - whois.ripe.net - ALLOCATED - - - 092/8 - RIPE NCC - 2007-03 - whois.ripe.net - ALLOCATED - - - 093/8 - RIPE NCC - 2007-03 - whois.ripe.net - ALLOCATED - - - 094/8 - RIPE NCC - 2007-07 - whois.ripe.net - ALLOCATED - - - 095/8 - RIPE NCC - 2007-07 - whois.ripe.net - ALLOCATED - - - 096/8 - ARIN - 2006-10 - whois.arin.net - ALLOCATED - - - 097/8 - ARIN - 2006-10 - whois.arin.net - ALLOCATED - - - 098/8 - ARIN - 2006-10 - whois.arin.net - ALLOCATED - - - 099/8 - ARIN - 2006-10 - whois.arin.net - ALLOCATED - - - 100/8 - ARIN - 2010-11 - whois.arin.net - ALLOCATED - - - - 101/8 - APNIC - 2010-08 - whois.apnic.net - ALLOCATED - - - 102/8 - AFRINIC - 2011-02 - whois.afrinic.net - ALLOCATED - - - 103/8 - APNIC - 2011-02 - whois.apnic.net - ALLOCATED - - - 104/8 - ARIN - 2011-02 - whois.arin.net - ALLOCATED - - - 105/8 - AFRINIC - 2010-11 - whois.afrinic.net - ALLOCATED - - - 106/8 - APNIC - 2011-01 - whois.apnic.net - ALLOCATED - - - 107/8 - ARIN - 2010-02 - whois.arin.net - ALLOCATED - - - 108/8 - ARIN - 2008-12 - whois.arin.net - ALLOCATED - - - 109/8 - RIPE NCC - 2009-01 - whois.ripe.net - ALLOCATED - - - 110/8 - APNIC - 2008-11 - whois.apnic.net - ALLOCATED - - - 111/8 - APNIC - 2008-11 - whois.apnic.net - ALLOCATED - - - 112/8 - APNIC - 2008-05 - whois.apnic.net - ALLOCATED - - - 113/8 - APNIC - 2008-05 - whois.apnic.net - ALLOCATED - - - 114/8 - APNIC - 2007-10 - whois.apnic.net - ALLOCATED - - - 115/8 - APNIC - 2007-10 - whois.apnic.net - ALLOCATED - - - 116/8 - APNIC - 2007-01 - whois.apnic.net - ALLOCATED - - - 117/8 - APNIC - 2007-01 - whois.apnic.net - ALLOCATED - - - 118/8 - APNIC - 2007-01 - whois.apnic.net - ALLOCATED - - - 119/8 - APNIC - 2007-01 - whois.apnic.net - ALLOCATED - - - 120/8 - APNIC - 2007-01 - whois.apnic.net - ALLOCATED - - - 121/8 - APNIC - 2006-01 - whois.apnic.net - ALLOCATED - - - 122/8 - APNIC - 2006-01 - whois.apnic.net - ALLOCATED - - - 123/8 - APNIC - 2006-01 - whois.apnic.net - ALLOCATED - - - 124/8 - APNIC - 2005-01 - whois.apnic.net - ALLOCATED - - - 125/8 - APNIC - 2005-01 - whois.apnic.net - ALLOCATED - - - 126/8 - APNIC - 2005-01 - whois.apnic.net - ALLOCATED - - - 127/8 - IANA - Loopback - 1981-09 - RESERVED - - - - 128/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 129/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 130/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 131/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 132/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 133/8 - Administered by APNIC - 1997-03 - whois.apnic.net - LEGACY - - - 134/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 135/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 136/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 137/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 138/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 139/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 140/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 141/8 - Administered by RIPE NCC - 1993-05 - whois.ripe.net - LEGACY - - - 142/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 143/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 144/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 145/8 - Administered by RIPE NCC - 1993-05 - whois.ripe.net - LEGACY - - - 146/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 147/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 148/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 149/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 150/8 - Administered by APNIC - 1993-05 - whois.apnic.net - LEGACY - - - 151/8 - Administered by RIPE NCC - 1993-05 - whois.ripe.net - LEGACY - - - 152/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 153/8 - Administered by APNIC - 1993-05 - whois.apnic.net - LEGACY - - - 154/8 - Administered by AFRINIC - 1993-05 - whois.afrinic.net - LEGACY - - - 155/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 156/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 157/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 158/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 159/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 160/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 161/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 162/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 163/8 - Administered by APNIC - 1993-05 - whois.apnic.net - LEGACY - - - 164/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 165/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 166/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 167/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 168/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 169/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - - 170/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - 171/8 - Administered by APNIC - 1993-05 - whois.apnic.net - LEGACY - - - 172/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - - 173/8 - ARIN - 2008-02 - whois.arin.net - ALLOCATED - - - 174/8 - ARIN - 2008-02 - whois.arin.net - ALLOCATED - - - 175/8 - APNIC - 2009-08 - whois.apnic.net - ALLOCATED - - - 176/8 - RIPE NCC - 2010-05 - whois.ripe.net - ALLOCATED - - - 177/8 - LACNIC - 2010-06 - whois.lacnic.net - ALLOCATED - - - 178/8 - RIPE NCC - 2009-01 - whois.ripe.net - ALLOCATED - - - 179/8 - LACNIC - 2011-02 - whois.lacnic.net - ALLOCATED - - - 180/8 - APNIC - 2009-04 - whois.apnic.net - ALLOCATED - - - 181/8 - LACNIC - 2010-06 - whois.lacnic.net - ALLOCATED - - - 182/8 - APNIC - 2009-08 - whois.apnic.net - ALLOCATED - - - 183/8 - APNIC - 2009-04 - whois.apnic.net - ALLOCATED - - - 184/8 - ARIN - 2008-12 - whois.arin.net - ALLOCATED - - - 185/8 - RIPE NCC - 2011-02 - whois.ripe.net - ALLOCATED - - - 186/8 - LACNIC - 2007-09 - whois.lacnic.net - ALLOCATED - - - 187/8 - LACNIC - 2007-09 - whois.lacnic.net - ALLOCATED - - - 188/8 - Administered by RIPE NCC - 1993-05 - whois.ripe.net - LEGACY - - - 189/8 - LACNIC - 1995-06 - whois.lacnic.net - ALLOCATED - - - 190/8 - LACNIC - 1995-06 - whois.lacnic.net - ALLOCATED - - - 191/8 - Administered by LACNIC - 1993-05 - whois.lacnic.net - LEGACY - - - 192/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - - - 193/8 - RIPE NCC - 1993-05 - whois.ripe.net - ALLOCATED - - - 194/8 - RIPE NCC - 1993-05 - whois.ripe.net - ALLOCATED - - - 195/8 - RIPE NCC - 1993-05 - whois.ripe.net - ALLOCATED - - - 196/8 - Administered by AFRINIC - 1993-05 - whois.afrinic.net - LEGACY - - - 197/8 - AFRINIC - 2008-10 - whois.afrinic.net - ALLOCATED - - - 198/8 - Administered by ARIN - 1993-05 - whois.arin.net - LEGACY - - - - 199/8 - ARIN - 1993-05 - whois.arin.net - ALLOCATED - - - 200/8 - LACNIC - 2002-11 - whois.lacnic.net - ALLOCATED - - - 201/8 - LACNIC - 2003-04 - whois.lacnic.net - ALLOCATED - - - 202/8 - APNIC - 1993-05 - whois.apnic.net - ALLOCATED - - - 203/8 - APNIC - 1993-05 - whois.apnic.net - ALLOCATED - - - - 204/8 - ARIN - 1994-03 - whois.arin.net - ALLOCATED - - - 205/8 - ARIN - 1994-03 - whois.arin.net - ALLOCATED - - - 206/8 - ARIN - 1995-04 - whois.arin.net - ALLOCATED - - - 207/8 - ARIN - 1995-11 - whois.arin.net - ALLOCATED - - - 208/8 - ARIN - 1996-04 - whois.arin.net - ALLOCATED - - - 209/8 - ARIN - 1996-06 - whois.arin.net - ALLOCATED - - - 210/8 - APNIC - 1996-06 - whois.apnic.net - ALLOCATED - - - 211/8 - APNIC - 1996-06 - whois.apnic.net - ALLOCATED - - - 212/8 - RIPE NCC - 1997-10 - whois.ripe.net - ALLOCATED - - - 213/8 - RIPE NCC - 1993-10 - whois.ripe.net - ALLOCATED - - - 214/8 - US-DOD - 1998-03 - whois.arin.net - LEGACY - - - 215/8 - US-DOD - 1998-03 - whois.arin.net - LEGACY - - - 216/8 - ARIN - 1998-04 - whois.arin.net - ALLOCATED - - - 217/8 - RIPE NCC - 2000-06 - whois.ripe.net - ALLOCATED - - - 218/8 - APNIC - 2000-12 - whois.apnic.net - ALLOCATED - - - 219/8 - APNIC - 2001-09 - whois.apnic.net - ALLOCATED - - - 220/8 - APNIC - 2001-12 - whois.apnic.net - ALLOCATED - - - 221/8 - APNIC - 2002-07 - whois.apnic.net - ALLOCATED - - - 222/8 - APNIC - 2003-02 - whois.apnic.net - ALLOCATED - - - 223/8 - APNIC - 2010-04 - whois.apnic.net - ALLOCATED - - - 224/8 - Multicast - 1981-09 - RESERVED - - - - 225/8 - Multicast - 1981-09 - RESERVED - - - - 226/8 - Multicast - 1981-09 - RESERVED - - - - 227/8 - Multicast - 1981-09 - RESERVED - - - - 228/8 - Multicast - 1981-09 - RESERVED - - - - 229/8 - Multicast - 1981-09 - RESERVED - - - - 230/8 - Multicast - 1981-09 - RESERVED - - - - 231/8 - Multicast - 1981-09 - RESERVED - - - - 232/8 - Multicast - 1981-09 - RESERVED - - - - 233/8 - Multicast - 1981-09 - RESERVED - - - - 234/8 - Multicast - 1981-09 - RESERVED - - - - - 235/8 - Multicast - 1981-09 - RESERVED - - - - 236/8 - Multicast - 1981-09 - RESERVED - - - - 237/8 - Multicast - 1981-09 - RESERVED - - - - 238/8 - Multicast - 1981-09 - RESERVED - - - - 239/8 - Multicast - 1981-09 - RESERVED - - - - - 240/8 - Future use - 1981-09 - RESERVED - - - - 241/8 - Future use - 1981-09 - RESERVED - - - - 242/8 - Future use - 1981-09 - RESERVED - - - - 243/8 - Future use - 1981-09 - RESERVED - - - - 244/8 - Future use - 1981-09 - RESERVED - - - - 245/8 - Future use - 1981-09 - RESERVED - - - - 246/8 - Future use - 1981-09 - RESERVED - - - - 247/8 - Future use - 1981-09 - RESERVED - - - - 248/8 - Future use - 1981-09 - RESERVED - - - - 249/8 - Future use - 1981-09 - RESERVED - - - - 250/8 - Future use - 1981-09 - RESERVED - - - - 251/8 - Future use - 1981-09 - RESERVED - - - - 252/8 - Future use - 1981-09 - RESERVED - - - - 253/8 - Future use - 1981-09 - RESERVED - - - - 254/8 - Future use - 1981-09 - RESERVED - - - - 255/8 - Future use - 1981-09 - RESERVED - - - - Indicates the status of address blocks as follows: -RESERVED: designated by the IETF for specific non-global-unicast purposes as noted. -LEGACY: allocated by the central Internet Registry (IR) prior to the Regional Internet Registries -(RIRs). This address space is now administered by individual RIRs as noted, including maintenance -of WHOIS Directory and reverse DNS records. Assignments from these blocks are distributed globally -on a regional basis. -ALLOCATED: delegated entirely to specific RIR as indicated. -UNALLOCATED: not yet allocated or reserved. - 0.0.0.0/8 reserved for self-identification , section 3.2.1.3. -Reserved by protocol. For authoritative registration, see . - Reserved for Private-Use Networks . -Complete registration details for 10.0.0.0/8 are found in . - This was reserved for Public Data Networks . See . -It was recovered in February 2008 and was subsequently allocated to APNIC in April 2010. - 100.64.0.0/10 reserved for Shared Address Space . -Complete registration details for 100.64.0.0/10 are found in . - 127.0.0.0/8 reserved for Loopback , section 3.2.1.3. -Reserved by protocol. For authoritative registration, see . - 169.254.0.0/16 reserved for Link Local . -Reserved by protocol. For authoritative registration, see . - 172.16.0.0/12 reserved for Private-Use Networks . -Complete registration details are found in . - 192.0.2.0/24 reserved for TEST-NET-1 . -Complete registration details for 192.0.2.0/24 are found in . -192.88.99.0/24 reserved for 6to4 Relay Anycast -Complete registration details for 192.88.99.0/24 are found in . -192.88.99.2/32 reserved for 6a44 Relay Anycast (possibly collocated with 6to4 Relay -at 192.88.99.1/32 - see section 2.4) -192.168.0.0/16 reserved for Private-Use Networks . -Complete registration details for 192.168.0.0/16 are found in . - 192.0.0.0/24 reserved for IANA IPv4 Special Purpose Address Registry . -Complete registration details for 192.0.0.0/24 are found in . - 198.18.0.0/15 reserved for Network Interconnect Device Benchmark Testing . -Complete registration details for 198.18.0.0/15 are found in . -198.51.100.0/24 reserved for TEST-NET-2 . -Complete registration details for 198.51.100.0/24 are found in . - 203.0.113.0/24 reserved for TEST-NET-3 . -Complete registration details for 203.0.113.0/24 are found in . - Multicast (formerly "Class D") registered in - Unicast-Prefix-Based IPv4 Multicast Addresses - Administratively Scoped IP Multicast - Reserved for future use (formerly "Class E") . -Reserved by protocol. For authoritative registration, see . - 255.255.255.255 is reserved for "limited broadcast" destination address and . -Complete registration details for 255.255.255.255/32 are found in . - - diff --git a/awx/lib/site-packages/netaddr/ip/ipv6-address-space.xml b/awx/lib/site-packages/netaddr/ip/ipv6-address-space.xml deleted file mode 100644 index fa45ce96b7..0000000000 --- a/awx/lib/site-packages/netaddr/ip/ipv6-address-space.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - - Internet Protocol Version 6 Address Space - 2013-02-15 - The IPv6 address management function was formally delegated to -IANA in December 1995 . The registration procedure -was confirmed with the IETF Chair in March 2010. - - IESG Approval - - 0000::/8 - Reserved by IETF - - - - - - - - - - - 0100::/8 - Reserved by IETF - - 0100::/64 reserved for Discard-Only Address Block . -Complete registration details are found in . - - - 0200::/7 - Reserved by IETF - - Deprecated as of December 2004 . -Formerly an OSI NSAP-mapped prefix set . - - - 0400::/6 - Reserved by IETF - - - - - 0800::/5 - Reserved by IETF - - - - - 1000::/4 - Reserved by IETF - - - - - 2000::/3 - Global Unicast - - The IPv6 Unicast space encompasses the entire IPv6 address range -with the exception of ff00::/8, per . IANA unicast address -assignments are currently limited to the IPv6 unicast address -range of 2000::/3. IANA assignments from this block are registered -in . - - - - - - - - - - 4000::/3 - Reserved by IETF - - - - - 6000::/3 - Reserved by IETF - - - - - 8000::/3 - Reserved by IETF - - - - - a000::/3 - Reserved by IETF - - - - - c000::/3 - Reserved by IETF - - - - - e000::/4 - Reserved by IETF - - - - - f000::/5 - Reserved by IETF - - - - - f800::/6 - Reserved by IETF - - - - - fc00::/7 - Unique Local Unicast - - For complete registration details, see . - - - fe00::/9 - Reserved by IETF - - - - - fe80::/10 - Link-Scoped Unicast - - Reserved by protocol. For authoritative registration, see . - - - fec0::/10 - Reserved by IETF - - Deprecated by in September 2004. Formerly a Site-Local scoped address prefix. - - - ff00::/8 - Multicast - - IANA assignments from this block are registered in . - - ::1/128 reserved for Loopback Address . -Reserved by protocol. For authoritative registration, see . - ::/128 reserved for Unspecified Address . -Reserved by protocol. For authoritative registration, see . - ::ffff:0:0/96 reserved for IPv4-mapped Address . -Reserved by protocol. For authoritative registration, see . - 0000::/96 deprecated by . Formerly defined as the "IPv4-compatible IPv6 address" prefix. - The "Well Known Prefix" 64:ff9b::/96 is used in an algorithmic mapping between IPv4 to IPv6 addresses . - 2001:0000::/23 reserved for IETF Protocol Assignments . -For complete registration details, see . - 2001:0000::/32 reserved for TEREDO . -For complete registration details, see . - 2001:0002::/48 reserved for Benchmarking . -For complete registration details, see . - 2001:db8::/32 reserved for Documentation . -For complete registration details, see . - 2001:10::/28 reserved for ORCHID . -For complete registration details, see . - 2002::/16 reserved for 6to4 . -For complete registration details, see . - - - - - diff --git a/awx/lib/site-packages/netaddr/ip/multicast-addresses.xml b/awx/lib/site-packages/netaddr/ip/multicast-addresses.xml deleted file mode 100644 index 2603e64c6f..0000000000 --- a/awx/lib/site-packages/netaddr/ip/multicast-addresses.xml +++ /dev/null @@ -1,3882 +0,0 @@ - - - - - IPv4 Multicast Address Space Registry - 2015-03-23 - Stig Venaas - Host Extensions for IP Multicasting specifies the extensions -required of a host implementation of the Internet Protocol (IP) to -support multicasting. The multicast addresses are in the range -224.0.0.0 through 239.255.255.255. Address assignments are listed below. - -The range of addresses between 224.0.0.0 and 224.0.0.255, inclusive, -is reserved for the use of routing protocols and other low-level -topology discovery or maintenance protocols, such as gateway discovery -and group membership reporting. Multicast routers should not forward -any multicast datagram with destination addresses in this range, -regardless of its TTL. - - Local Network Control Block (224.0.0.0 - 224.0.0.255 (224.0.0/24)) - - Expert Review, IESG Approval, or Standards Action - (*) It is only appropriate to use these values in explicitly- -configured experiments; they MUST NOT be shipped as defaults in -implementations. See for details. - - 224.0.0.0 - Base Address (Reserved) - - - - - 224.0.0.1 - All Systems on this Subnet - - - - - 224.0.0.2 - All Routers on this Subnet - - - - 224.0.0.3 - Unassigned - - - - 224.0.0.4 - DVMRP Routers - - - - - 224.0.0.5 - OSPFIGP OSPFIGP All Routers - - - - - 224.0.0.6 - OSPFIGP OSPFIGP Designated Routers - - - - - 224.0.0.7 - ST Routers - - - - - 224.0.0.8 - ST Hosts - - - - - 224.0.0.9 - RIP2 Routers - - - - - 224.0.0.10 - IGRP Routers - - - - 224.0.0.11 - Mobile-Agents - [Bill Simpson] - - - 224.0.0.12 - DHCP Server / Relay Agent - [Unknown] - - - 224.0.0.13 - All PIM Routers - - - - 224.0.0.14 - RSVP-ENCAPSULATION - - - - 224.0.0.15 - all-cbt-routers - - - - - 224.0.0.16 - designated-sbm - - - - 224.0.0.17 - all-sbms - - - - 224.0.0.18 - VRRP - - - - - 224.0.0.19 - IPAllL1ISs - - - - 224.0.0.20 - IPAllL2ISs - - - - 224.0.0.21 - IPAllIntermediate Systems - - - - 224.0.0.22 - IGMP - - - - 224.0.0.23 - GLOBECAST-ID - - - - 224.0.0.24 - OSPFIGP-TE - - - - 224.0.0.25 - router-to-switch - - - - 224.0.0.26 - Unassigned - - - - 224.0.0.27 - Al MPP Hello - - - - 224.0.0.28 - ETC Control - - - - 224.0.0.29 - GE-FANUC - - - - 224.0.0.30 - indigo-vhdp - - - - 224.0.0.31 - shinbroadband - - - - 224.0.0.32 - digistar - - - - 224.0.0.33 - ff-system-management - - - - 224.0.0.34 - pt2-discover - - - - 224.0.0.35 - DXCLUSTER - - - - 224.0.0.36 - DTCP Announcement - - - - 224.0.0.37-224.0.0.68 - zeroconfaddr (renew 12/02) - - - - 224.0.0.69-224.0.0.100 - Reserved - - - - 224.0.0.101 - cisco-nhap - - - - 224.0.0.102 - HSRP - - - - 224.0.0.103 - MDAP - - - - 224.0.0.104 - Nokia MC CH - - - - 224.0.0.105 - ff-lr-address - - - - 224.0.0.106 - All-Snoopers - - - - 224.0.0.107 - PTP-pdelay - - - - - 224.0.0.108 - Saratoga - - 2011-03-17 - - - 224.0.0.109 - LL-MANET-Routers - - 2011-02-23 - - - 224.0.0.110 - IGRS - - - - 224.0.0.111 - Babel - - - - - 224.0.0.112 - MMA Device Discovery - - - - 224.0.0.113 - AllJoyn - - - - 224.0.0.114 - Inter RFID Reader Protocol - - - - 224.0.0.115 - JSDP - - - - 224.0.0.116-224.0.0.250 - Unassigned - - - - 224.0.0.251 - mDNS - - - - 224.0.0.252 - Link-local Multicast Name Resolution - - 2011-03-17 - - - 224.0.0.253 - Teredo - - 2010-02-14 - - - 224.0.0.254 - RFC3692-style Experiment (*) - - - - 224.0.0.255 - Unassigned - - - - - Internetwork Control Block (224.0.1.0 - 224.0.1.255 (224.0.1/24)) - - Expert Review, IESG Approval, or Standards Action - - 224.0.1.0 - VMTP Managers Group - - - - - 224.0.1.1 - NTP Network Time Protocol - - - - - - 224.0.1.2 - SGI-Dogfight - - - - 224.0.1.3 - Rwhod - - - - 224.0.1.4 - VNP - - - - 224.0.1.5 - Artificial Horizons - Aviator - - - - 224.0.1.6 - NSS - Name Service Server - - - - 224.0.1.7 - AUDIONEWS - Audio News Multicast - - - - 224.0.1.8 - SUN NIS+ Information Service - - - - 224.0.1.9 - MTP Multicast Transport Protocol - - - - 224.0.1.10 - IETF-1-LOW-AUDIO - - - - 224.0.1.11 - IETF-1-AUDIO - - - - 224.0.1.12 - IETF-1-VIDEO - - - - 224.0.1.13 - IETF-2-LOW-AUDIO - - - - 224.0.1.14 - IETF-2-AUDIO - - - - 224.0.1.15 - IETF-2-VIDEO - - - - 224.0.1.16 - MUSIC-SERVICE - - - 224.0.1.17 - SEANET-TELEMETRY - - - 224.0.1.18 - SEANET-IMAGE - - - 224.0.1.19 - MLOADD - - - - 224.0.1.20 - any private experiment - - - - 224.0.1.21 - DVMRP on MOSPF - [John Moy] - - - 224.0.1.22 - SVRLOC - - - - 224.0.1.23 - XINGTV - - - - 224.0.1.24 - microsoft-ds - <arnoldm&microsoft.com> - - - 224.0.1.25 - nbc-pro - <bloomer&birch.crd.ge.com> - - - 224.0.1.26 - nbc-pfn - <bloomer&birch.crd.ge.com> - - - 224.0.1.27 - lmsc-calren-1 - - - - 224.0.1.28 - lmsc-calren-2 - - - - 224.0.1.29 - lmsc-calren-3 - - - - 224.0.1.30 - lmsc-calren-4 - - - - 224.0.1.31 - ampr-info - - - - 224.0.1.32 - mtrace - - - - 224.0.1.33 - RSVP-encap-1 - - - - 224.0.1.34 - RSVP-encap-2 - - - - 224.0.1.35 - SVRLOC-DA - - - - 224.0.1.36 - rln-server - - - - 224.0.1.37 - proshare-mc - - - - 224.0.1.38 - unassigned - - - 224.0.1.39 - cisco-rp-announce - - - - 224.0.1.40 - cisco-rp-discovery - - - - 224.0.1.41 - gatekeeper - - - - 224.0.1.42 - iberiagames - - - - 224.0.1.43 - nwn-discovery - - - - 224.0.1.44 - nwn-adaptor - - - - 224.0.1.45 - isma-1 - - - - 224.0.1.46 - isma-2 - - - - 224.0.1.47 - telerate - - - - 224.0.1.48 - ciena - - - - 224.0.1.49 - dcap-servers - - - - 224.0.1.50 - dcap-clients - - - - 224.0.1.51 - mcntp-directory - - - - 224.0.1.52 - mbone-vcr-directory - - - - 224.0.1.53 - heartbeat - - - - 224.0.1.54 - sun-mc-grp - - - - 224.0.1.55 - extended-sys - - - - 224.0.1.56 - pdrncs - - - - 224.0.1.57 - tns-adv-multi - - - - 224.0.1.58 - vcals-dmu - - - - 224.0.1.59 - zuba - - - - 224.0.1.60 - hp-device-disc - - - - 224.0.1.61 - tms-production - - - - 224.0.1.62 - sunscalar - - - - 224.0.1.63 - mmtp-poll - - - - 224.0.1.64 - compaq-peer - - - - 224.0.1.65 - iapp - - - - 224.0.1.66 - multihasc-com - - - - 224.0.1.67 - serv-discovery - - - - 224.0.1.68 - mdhcpdisover - - - - 224.0.1.69 - MMP-bundle-discovery1 - - - - 224.0.1.70 - MMP-bundle-discovery2 - - - - 224.0.1.71 - XYPOINT DGPS Data Feed - - - - 224.0.1.72 - GilatSkySurfer - - - - 224.0.1.73 - SharesLive - - - - 224.0.1.74 - NorthernData - [Sheers] - - - 224.0.1.75 - SIP - [Schulzrinne] - - - 224.0.1.76 - IAPP - - - - 224.0.1.77 - AGENTVIEW - - - - 224.0.1.78 - Tibco Multicast1 - - - - 224.0.1.79 - Tibco Multicast2 - - - - 224.0.1.80 - MSP - - - - 224.0.1.81 - OTT (One-way Trip Time) - - - - 224.0.1.82 - TRACKTICKER - - - - 224.0.1.83 - dtn-mc - - - - 224.0.1.84 - jini-announcement - - - - 224.0.1.85 - jini-request - - - - 224.0.1.86 - sde-discovery - - - - 224.0.1.87 - DirecPC-SI - - - - 224.0.1.88 - B1RMonitor - - - - 224.0.1.89 - 3Com-AMP3 dRMON - - - - 224.0.1.90 - imFtmSvc - - - - 224.0.1.91 - NQDS4 - - - - 224.0.1.92 - NQDS5 - - - - 224.0.1.93 - NQDS6 - - - - 224.0.1.94 - NLVL12 - - - - 224.0.1.95 - NTDS1 - - - - 224.0.1.96 - NTDS2 - - - - 224.0.1.97 - NODSA - - - - 224.0.1.98 - NODSB - - - - 224.0.1.99 - NODSC - - - - 224.0.1.100 - NODSD - - - - 224.0.1.101 - NQDS4R - - - - 224.0.1.102 - NQDS5R - - - - 224.0.1.103 - NQDS6R - - - - 224.0.1.104 - NLVL12R - - - - 224.0.1.105 - NTDS1R - - - - 224.0.1.106 - NTDS2R - - - - 224.0.1.107 - NODSAR - - - - 224.0.1.108 - NODSBR - - - - 224.0.1.109 - NODSCR - - - - 224.0.1.110 - NODSDR - - - - 224.0.1.111 - MRM - - - - 224.0.1.112 - TVE-FILE - - - - 224.0.1.113 - TVE-ANNOUNCE - - - - 224.0.1.114 - Mac Srv Loc - - - - 224.0.1.115 - Simple Multicast - - - - 224.0.1.116 - SpectraLinkGW - - - - 224.0.1.117 - dieboldmcast - - - - 224.0.1.118 - Tivoli Systems - - - - 224.0.1.119 - pq-lic-mcast - - - - 224.0.1.120 - SPRYWARE LLC - - - - 224.0.1.121 - Pipesplatform - - - - 224.0.1.122 - LiebDevMgmg-DM - - - - 224.0.1.123 - TRIBALVOICE - - - - 224.0.1.124 - Unassigned (Retracted 1/29/01) - - - 224.0.1.125 - PolyCom Relay1 - [Coutiere] - - - 224.0.1.126 - Infront Multi1 - - - - 224.0.1.127 - XRX DEVICE DISC - - - - 224.0.1.128 - CNN - - - - 224.0.1.129 - PTP-primary - - - - - 224.0.1.130 - PTP-alternate1 - - - - - 224.0.1.131 - PTP-alternate2 - - - - - 224.0.1.132 - PTP-alternate3 - - - - - 224.0.1.133 - ProCast - - - - 224.0.1.134 - 3Com Discp - - - - 224.0.1.135 - CS-Multicasting - - - - 224.0.1.136 - TS-MC-1 - - - - 224.0.1.137 - Make Source - - - - 224.0.1.138 - Teleborsa - - - - 224.0.1.139 - SUMAConfig - - - - 224.0.1.140 - capwap-ac - - - - 224.0.1.141 - DHCP-SERVERS - - - - 224.0.1.142 - CN Router-LL - - - - 224.0.1.143 - EMWIN - - - - 224.0.1.144 - Alchemy Cluster - - - - - 224.0.1.145 - Satcast One - - - - 224.0.1.146 - Satcast Two - - - - 224.0.1.147 - Satcast Three - - - - 224.0.1.148 - Intline - - - - 224.0.1.149 - 8x8 Multicast - - - - 224.0.1.150 - Unassigned - - - - 224.0.1.151 - Intline-1 - - - - 224.0.1.152 - Intline-2 - - - - 224.0.1.153 - Intline-3 - - - - 224.0.1.154 - Intline-4 - - - - 224.0.1.155 - Intline-5 - - - - 224.0.1.156 - Intline-6 - - - - 224.0.1.157 - Intline-7 - - - - 224.0.1.158 - Intline-8 - - - - 224.0.1.159 - Intline-9 - - - - 224.0.1.160 - Intline-10 - - - - 224.0.1.161 - Intline-11 - - - - 224.0.1.162 - Intline-12 - - - - 224.0.1.163 - Intline-13 - - - - 224.0.1.164 - Intline-14 - - - - 224.0.1.165 - Intline-15 - - - - 224.0.1.166 - marratech-cc - - - - 224.0.1.167 - EMS-InterDev - - - - 224.0.1.168 - itb301 - - - - 224.0.1.169 - rtv-audio - - - - 224.0.1.170 - rtv-video - - - - 224.0.1.171 - HAVI-Sim - - - - 224.0.1.172 - Nokia Cluster - - - - - 224.0.1.173 - host-request - - - - 224.0.1.174 - host-announce - - - - 224.0.1.175 - ptk-cluster - - - - 224.0.1.176 - Proxim Protocol - - - - 224.0.1.177 - Gemtek Systems - - - - 224.0.1.178 - IEEE IAPP - - - - 224.0.1.179 - 1451_Dot5_802_Discovery - - - - 224.0.1.180 - 1451_Dot5_802_Group_1 - - - - 224.0.1.181 - 1451_Dot5_802_Group_2 - - - - 224.0.1.182 - 1451_Dot5_802_Group_3 - - - - 224.0.1.183 - 1451_Dot5_802_Group_4 - - - - 224.0.1.184 - VFSDP - - - - 224.0.1.185 - ASAP - - - - 224.0.1.186 - SL-MANET-ROUTERS - - - - 224.0.1.187 - All CoAP Nodes - - - - 224.0.1.188-224.0.1.255 - Unassigned - - - - AD-HOC Block I (224.0.2.0 - 224.0.255.255) - - Expert Review, IESG Approval, or Standards Action - - 224.0.2.0 - Unassigned - - - 224.0.2.1 - "rwho" Group (BSD) (unofficial) - - - - 224.0.2.2 - SUN RPC PMAPPROC_CALLIT - - - - 224.0.2.3 - EPSON-disc-set - - - - 224.0.2.4 - All C1222 Nodes - - - - 224.0.2.5 - Monitoring Discovery Protocol - - - - 224.0.2.6 - BitSend MediaStreams - - - - 224.0.2.7-224.0.2.8 - rxWARN - - - - 224.0.2.9-224.0.2.63 - Unassigned - - - 224.0.2.64-224.0.2.95 - NYSE Euronext - - 2007-07 - - - 224.0.2.96-224.0.2.127 - BallisterNet - - - - 224.0.2.128-224.0.2.191 - WOZ-Garage - - - - 224.0.2.192-224.0.2.255 - NYSE Euronext - - - - 224.0.3.0-224.0.3.255 - RFE Generic Service - - - - 224.0.4.0-224.0.4.255 - RFE Individual Conferences - - - - 224.0.5.0-224.0.5.127 - CDPD Groups - [Bob Brenner] - - - 224.0.5.128-224.0.5.191 - NYSE Euronext - - - - 224.0.5.192-224.0.5.255 - NYSE Euronext - - - - 224.0.6.0-224.0.6.127 - Cornell ISIS Project - [Tim Clark] - - - 224.0.6.128-224.0.6.143 - MoeSingh - - - - 224.0.6.144-224.0.6.150 - Unassigned - - - - 224.0.6.151 - Canon-Device-control - - - - 224.0.6.152-224.0.6.191 - Unassigned - - - - 224.0.6.192-224.0.6.255 - OneChicago multicast - - - - 224.0.7.0-224.0.7.255 - Where-Are-You - - - - 224.0.8.0-224.0.8.255 - UNASSIGNED - - - 224.0.9.0-224.0.9.255 - The Thing System - - - - 224.0.10.0-224.0.10.255 - DLSw Groups - - - - 224.0.11.0-224.0.11.255 - NCC.NET Audio - - - - 224.0.12.0-224.0.12.63 - Microsoft and MSNBC - - - - 224.0.13.0-224.0.13.255 - WorldCom Broadcast Services - - - - 224.0.14.0-224.0.14.255 - NLANR - - - - 224.0.15.0-224.0.15.255 - Agilent Technologies - - - - 224.0.16.0-224.0.16.255 - XingNet - - - - 224.0.17.0-224.0.17.31 - Mercantile & Commodity Exchange - - - - 224.0.17.32-224.0.17.63 - NDQMD1 - - - - 224.0.17.64-224.0.17.127 - ODN-DTV - - - - 224.0.18.0-224.0.18.255 - Dow Jones - - - - 224.0.19.0-224.0.19.63 - Walt Disney Company - - - - 224.0.19.64-224.0.19.95 - Cal Multicast - - - - 224.0.19.96-224.0.19.127 - NYSE Euronext - - 2007-07 - - - 224.0.19.128-224.0.19.191 - IIG Multicast - - - - 224.0.19.192-224.0.19.207 - Metropol - - - - 224.0.19.208-224.0.19.239 - Xenoscience, Inc. - - - - 224.0.19.240-224.0.19.255 - MJDPM - - - - 224.0.20.0-224.0.20.63 - MS-IP/TV - - - - 224.0.20.64-224.0.20.127 - Reliable Network Solutions - - - - 224.0.20.128-224.0.20.143 - TRACKTICKER Group - - - - 224.0.20.144-224.0.20.207 - CNR Rebroadcast MCA - - - - 224.0.21.0-224.0.21.127 - Talarian MCAST - - - - 224.0.22.0-224.0.22.239 - WORLD MCAST - - - - 224.0.22.240-224.0.22.255 - Jones International - - - - 224.0.23.0 - ECHONET - - - - 224.0.23.1 - Ricoh-device-ctrl - - - - 224.0.23.2 - Ricoh-device-ctrl - - - - 224.0.23.3-224.0.23.10 - Telefeed - - - - 224.0.23.11 - SpectraTalk - - - - 224.0.23.12 - EIBnet/IP - - - - 224.0.23.13 - TVE-ANNOUNCE2 - - - - 224.0.23.14 - DvbServDisc - - - - 224.0.23.15-224.0.23.31 - MJDPM - - - - 224.0.23.32 - Norman MCMP - - - - 224.0.23.33 - RRDP - - - - 224.0.23.34 - AF_NA - - - - 224.0.23.35 - AF_OPRA_NBBO - - - - 224.0.23.36 - AF_OPRA_FULL - - - - 224.0.23.37 - AF_NEWS - - - - 224.0.23.38 - AF_NA_CHI - - - - 224.0.23.39 - AF_OPRA_NBBO_CHI - - - - 224.0.23.40 - AF_OPRA_FULL_CHI - - - - 224.0.23.41 - AF_NEWS_CHI - - - - 224.0.23.42 - Control for IP Video - - - - 224.0.23.43 - acp-discovery - - - - 224.0.23.44 - acp-management - - - - 224.0.23.45 - acp-data - - - - 224.0.23.46 - oap-multicast - - - - 224.0.23.47 - AF_DOB_CHI - - - - 224.0.23.48 - AF_OPRA_FULL2_CHI - - - - 224.0.23.49 - AF_DOB - - - - 224.0.23.50 - AF_OPRA_FULL2 - - - - 224.0.23.51 - Fairview - - - - 224.0.23.52 - NYSE Euronext - - - - 224.0.23.53 - MCP - - - - 224.0.23.54 - ServDiscovery - - - - 224.0.23.55 - noaaport1 - - - - 224.0.23.56 - noaaport2 - - - - 224.0.23.57 - noaaport3 - - - - 224.0.23.58 - noaaport4 - - - - 224.0.23.59 - DigacIP7 - - - - 224.0.23.60 - AtscSvcSig - - - - 224.0.23.61 - SafetyNET p (potentially IGMPv1) - - - - 224.0.23.62 - BluemoonGamesMC - - - - 224.0.23.63 - iADT Discovery - - - - 224.0.23.64-224.0.23.80 - Moneyline - - - - 224.0.23.81-224.0.23.127 - Reserved (Moneyline) - - - 224.0.23.128-224.0.23.157 - PHLX - - - - 224.0.23.158 - VSCP - - - - 224.0.23.159 - LXI-EVENT - - - - 224.0.23.160 - solera_lmca - - - - 224.0.23.161 - VBooster - - - - 224.0.23.162 - cajo discovery - - - - 224.0.23.163 - INTELLIDEN - - - - 224.0.23.164 - IceEDCP - - - - 224.0.23.165 - omasg - - - - 224.0.23.166 - MEDIASTREAM - - - - 224.0.23.167 - Systech Mcast - - - - 224.0.23.168 - tricon-system-management - - - - 224.0.23.169 - MNET discovery - - - - 224.0.23.170 - CCNx (not for global routing) - - - - 224.0.23.171 - LLAFP - - - - 224.0.23.172 - UFMP - - - - 224.0.23.173 - PHILIPS-HEALTH - - - - 224.0.23.174 - PHILIPS-HEALTH - - - - 224.0.23.175 - QDP - - - - 224.0.23.176 - CalAmp WCP - - - - 224.0.23.177 - AES discovery - - - - 224.0.23.178 - JDP Java Discovery Protocol - - - - 224.0.23.179 - PixelPusher - - - - 224.0.23.180 - network metronome - - - - 224.0.23.181-224.0.23.191 - Unassigned - - - 224.0.23.192-224.0.23.255 - PINKOTC - - - - 224.0.24.0-224.0.24.127 - AGSC UK VVs - - - - 224.0.24.128-224.0.24.255 - EM-MULTI - - - - 224.0.25.0-224.0.28.255 - CME Market Data - - - - 224.0.29.0-224.0.30.255 - Deutsche Boerse - - - - 224.0.31.0-224.0.34.255 - CME Market Data - - - - 224.0.35.0-224.0.35.255 - M2S - - - - 224.0.36.0-224.0.38.255 - Unassigned - - - 224.0.39.0-224.0.40.255 - CDAS - - - - 224.0.41.0-224.0.41.255 - NYSE Euronext - - 2011-02-15 - - - 224.0.42.0-224.0.45.255 - MEDIAL - - - - 224.0.46.0-224.0.50.255 - Deutsche Boerse - - - - 224.0.51.0-224.0.51.255 - ALCOM-IPTV - - - - 224.0.52.0-224.0.53.255 - Euronext - - 2014-11-24 - - - 224.0.54.0-224.0.57.255 - Get - BCN - - - - 224.0.58.0-224.0.61.255 - NYSE Euronext - - - - 224.0.62.0-224.0.62.255 - BATS - - - - 224.0.63.0-224.0.63.255 - BATS Trading - - - - 224.0.64.0-224.0.67.255 - Euronext - - 2014-11-24 - - - 224.0.68.0-224.0.69.255 - ISE - - - - 224.0.70.0-224.0.71.255 - NYSE Euronext - - 2011-03-01 - - - 224.0.72.0-224.0.72.255 - TMX - - - - - 224.0.73.0-224.0.74.255 - Direct Edge - - - - 224.0.75.0-224.0.75.255 - ISE - - - - 224.0.76.0-224.0.76.255 - NYSE Euronext - - 2011-03-01 - - - 224.0.77.0-224.0.77.255 - NYSE Euronext - - - - 224.0.78.0-224.0.78.255 - ALCOM-IPTV - - - - 224.0.79.0-224.0.81.255 - ISE - - - - 224.0.82.0-224.0.85.255 - BATS Trading - - - - 224.0.86.0-224.0.101.255 - NYSE Euronext - - - - 224.0.102.0-224.0.102.127 - NYSE Euronext - - - - 224.0.102.128-224.0.102.255 - MVS-IPTV-2 - - - - 224.0.103.0-224.0.104.255 - MVS-IPTV - - - - - 224.0.105.0-224.0.105.127 - MIAX Multicast - - - - 224.0.105.128-224.0.105.255 - - Unassigned - - - 224.0.106.0-224.0.106.255 - TMX - - - - - 224.0.107.0-224.0.108.255 - Alpha Group - - - - 224.0.109.0-224.0.110.255 - Zaklina_Petkovic - - - - 224.0.111.0-224.0.111.255 - VoleraDataFeed - - - - 224.0.112.0-224.0.112.255 - JHB-STOCK-EXCH - - - - 224.0.113.0-224.0.114.255 - Deutsche Boerse - - - - 224.0.115.0-224.0.115.255 - TMX - - - - - 224.0.116.0-224.0.116.255 - Ido Rosen - - - - 224.0.117.0-224.0.119.255 - ISE - - - - 224.0.120.0-224.0.120.255 - czechbone iptv - - - - 224.0.121.0-224.0.121.255 - AQUIS-EXCHANGE - - - - 224.0.122.0-224.0.123.255 - DNS:NET TV - - - - 224.0.124.0-224.0.124.255 - Boston Options Exchange - - - - - 224.0.125.0-224.0.125.255 - Hanweck Associates - - - - 224.0.126.0-224.0.129.255 - ICE market data - - - - 224.0.130.0-224.0.131.255 - BATS Trading - - - - 224.0.132.0-224.0.135.255 - Net By Net Holding IPTV - - - - 224.0.136.0-224.0.139.255 - Aequitas Innovations Inc. - - - - 224.0.140.0-224.0.140.255 - Instinet - - - - 224.0.141.0-224.0.143.255 - Unassigned - - - - 224.0.144.0-224.0.151.255 - VZ-Multicast-Public - - - - 224.0.152.0-224.0.249.255 - Unassigned - - - - 224.0.250.0-224.0.251.255 - KPN Broadcast Services - - - - - 224.0.252.0-224.0.252.255 - KPN Broadcast Services - - - - - 224.0.253.0-224.0.253.255 - KPN Broadcast Services - - - - - 224.0.254.0-224.0.254.255 - Intelsat IPTV - - 2011-02-22 - - - 224.0.255.0-224.0.255.255 - Intelsat IPTV - - 2011-02-22 - - - - - RESERVED (224.1.0.0-224.1.255.255 (224.1/16)) - - No new assignments are being made in this range for the time being. - - 224.1.0.0-224.1.0.37 - Reserved - - - - 224.1.0.38 - dantz - - - - 224.1.0.39-224.1.1.255 - Reserved - - - - 224.1.2.0-224.1.2.255 - NYSE Euronext - - - - 224.1.3.0-224.1.4.255 - NOB Cross media facilities - - - - 224.1.5.0-224.1.255.255 - Reserved - - - - - - SDP/SAP Block (224.2.0.0-224.2.255.255 (224.2/16)) - - - 224.2.0.0-224.2.127.253 - Multimedia Conference Calls - - - - 224.2.127.254 - SAPv1 Announcements - - - - 224.2.127.255 - SAPv0 Announcements (deprecated) - - - - 224.2.128.0-224.2.255.255 - SAP Dynamic Assignments - - - - - - AD-HOC Block II (224.3.0.0-224.4.255.255 (224.3/16, 224.4/16)) - - Expert Review, IESG Approval, or Standards Action - - 224.3.0.0-224.3.0.63 - Nasdaqmdfeeds (re-new/March 2003) - - - - 224.3.0.64-224.3.255.255 - Reserved - - - - 224.4.0.0-224.4.0.255 - London Stock Exchange - - - - 224.4.1.0-224.4.1.255 - London Stock Exchange - - - - 224.4.2.0-224.4.2.255 - London Stock Exchange - - - - 224.4.3.0-224.4.4.255 - London Stock Exchange - - - - 224.4.5.0-224.4.6.255 - London Stock Exchange - - - - 224.4.7.0-224.4.7.255 - CBOE Holdings - - - - 224.4.8.0-224.4.9.255 - ISE - - - - 224.4.10.0-224.4.13.255 - London Stock Exchange - - - - 224.4.14.0-224.4.255.255 - Reserved - - - - - - RESERVED (224.5.0.0-224.251.255.255 (251 /16s)) - - - 224.5.0.0-224.251.255.255 - Reserved - - - - - - DIS Transient Groups 224.252.0.0-224.255.255.255 (224.252/14)) - - - 224.252.0.0-224.255.255.255 - DIS Transient Groups - - - - - - RESERVED (225.0.0.0-231.255.255.255 (7 /8s)) - - - 225.0.0.0-231.255.255.255 - Reserved - - - - - - Source-Specific Multicast Block (232.0.0.0-232.255.255.255 (232/8)) - - Addresses within the 232.0.1.0-232.255.255.255 are dynamically -allocated by hosts when needed - - 232.0.0.0 - Reserved - - - - 232.0.0.1-232.0.0.255 - Reserved for IANA allocation - - - - 232.0.1.0-232.255.255.255 - Reserved for local host allocation - - - - - - GLOP Block - - - 233.0.0.0-233.251.255.255 - GLOP Block - - - - - - AD-HOC Block III (233.252.0.0-233.255.255.255 (233.252/14)) - - Expert Review, IESG Approval, or Standards Action - - 233.252.0.0-233.252.0.255 - MCAST-TEST-NET - - - - 2010-01-20 - - - 233.252.1.0-233.252.1.31 - Spryware - - - - 233.252.1.32-233.252.1.255 - Unassigned - - - - 233.252.2.0-233.252.7.255 - Tradition - - - - 233.252.8.0-233.252.11.255 - BVMF_MKT_DATA - - - - 233.252.12.0-233.252.13.255 - blizznet-tv-services - - - - 233.252.124.0-233.255.255.255 - Unassigned - - - - - - Unicast-Prefix-based IPv4 Multicast Addresses - - - 234.0.0.0-234.255.255.255 - Unicast-Prefix-based IPv4 Multicast Addresses - - - - - - Scoped Multicast Ranges - - - 235.0.0.0-238.255.255.255 - Reserved - - - - 239.0.0.0-239.255.255.255 - Organization-Local Scope - - - - - - - Relative Addresses used with Scoped Multicast Addresses - - (*) It is only appropriate to use these values in explicitly- -configured experiments; they MUST NOT be shipped as defaults in -implementations. See for details. - -These addresses are listed in the Domain Name Service under MCAST.NET -and 224.IN-ADDR.ARPA. - -Note that when used on an Ethernet or IEEE 802 network, the 23 -low-order bits of the IP Multicast address are placed in the low-order -23 bits of the Ethernet or IEEE 802 net multicast address -1.0.94.0.0.0. See the section on "IANA ETHERNET ADDRESS BLOCK". - - 0 - SAP Session Announcement Protocol - - - - 1 - MADCAP Protocol - - - - 2 - SLPv2 Discovery - - - - 3 - MZAP - - - - 4 - Multicast Discovery of DNS Services - - - - 5 - SSDP - - - - 6 - DHCP v4 - - - - 7 - AAP - - - - 8 - MBUS - - - - 9 - UPnP - - - - 10 - MCAST-TEST-NET-2 - - - - 11-252 - Reserved - To be assigned by the IANA - - - 253 - Reserved - - - 254 - RFC3692-style Experiment (*) - - - - 255 - Reserved - To be assigned by the IANA - - - - - - Adam DeMinter - mailto:adam.deminter&mwt.net - 2011-04-20 - - - Adam Yellen - mailto:adam&videofurnace.com - 2009-08-12 - - - Akihiro Nishida - mailto:nishida&src.ricoh.co.jp - 2003-02-01 - - - Alan Novick - mailto:anovick&tdc.com - 1998-08-01 - - - Alan Robertson - mailto:alanr&unix.sh - 2012-04-17 - - - Albert Berlovitch - mailto:albertb&voltaire.com - 2010-02-04 - - - Alex Lee - mailto:alex_mrlee&gemtek.com.tw - 2002-10-01 - - - Alexander Pevzner - mailto:pzz&pzz.msk.ru - 2006-03-17 - - - Andrew Brown - mailto:abrown&batstrading.com - 2014-03-05 - - - Andrew Cherenson - mailto:arc&sgi.com - - - Andrew Hoyos - mailto:andrew&hoyosconsulting.com - 2011-04-20 - - - Andrew Rowley - mailto:Andrew.Rowley&manchester.ac.uk - 2006-06-09 - - - Andy Belk - mailto:register1&azulsystems.com - 2005-02-01 - - - Andy Crick - mailto:acrick&haascnc.com - 2008-01-14 - - - Anthony Daga - mailto:anthony&mksrc.com - 1999-06-01 - - - Anthony Kandaya - mailto:Anthony.kandaya&philips.com - 2012-05-23 - - - Antonio Querubin - mailto:tony&lava.net - 2008-02-04 - - - Arne Hvidsten - mailto:arne.hvidsten&get.no - 2008-08-20 - - - Arnoud Zwemmer - mailto:arnoud&nwn.nl - 1996-11-01 - - - Asad Gilani - mailto:agilani&nymex.com - 1997-07-01 - - - Bert van Willigen - mailto:bert.vanwilligen&philips.com - 2004-01-01 - - - Beverly Schwartz - mailto:bschwart&bbn.com - 1998-06-01 - - - Bill Manning - mailto:bmanning&isi.edu - 1999-08-01 - - - Bill Schilit - mailto:schilit&parc.xerox.com - - - Bill Simpson - mailto:bill.simpson&um.cc.umich.edu - 1994-11-01 - - - Bill Woodcock - mailto:woody&zocalo.net - 1998-11-01 - - - Bob Braden - mailto:braden&isi.edu - 1996-04-01 - - - Bob Brzezinski - mailto:bob.brzezinski&activfinancial.com - 2005-10-28 - - - Bob Gaddie - mailto:bobg&dtn.com - 1998-08-01 - - - Bob Meier - mailto:meierb&norand.com - 1997-12-01 - - - Bob Scheifler - mailto:Bob.Scheifler&sun.com - 1998-08-01 - - - Bob Sledge - mailto:bob&pqsystems.com - 1998-12-01 - - - Bodo Rueskamp - mailto:br&itchigo.com - 2000-03-01 - - - Boris Garber - mailto:Boris.Garber&tsx.com - 2012-06-12 - - - Brendan Eic - mailto:brendan&illyria.wpd.sgi.com - - - Brian Kean - mailto:bkean&dca.com - 1995-08-01 - - - Brian Kerkan - mailto:brian&satcomsystems.com - 2000-05-01 - - - Brian Martinicky - mailto:Brian_Martinicky&automationintelligence.com - 2000-03-01 - - - Brian Trudeau - mailto:btrudeau&onechicago.com - 2014-09-19 - - - Bruce Factor - mailto:ahi!bigapple!bruce&uunet.uu.net - - - Bryan Costales - mailto:bcx&infobeat.com - 1997-09-01 - - - Bryant Eastham - mailto:protocols&pewla.us.pewg.panasonic.com - 2006-06-16 - - - Caleb Bell - mailto:cbell&rxnetworks.com - 2012-11-19 - - - Carl-Johan Sjöberg - mailto:cjs&bitsend.se - 2012-04-25 - - - Carl Malamud - mailto:carl&media.org - 2014-01-03 - - - Chad Myers - mailto:chad.myers&theice.com - 2013-10-31 - - - Charles Tewiah - mailto:charles.tewiah&westlb-systems.co.uk - 2005-09-01 - - - Chas Honton - mailto:chas&secant.com - 1997-12-01 - - - Choon Lee - mailto:cwl&nsd.3com.com - 1996-04-01 - - - Chris Adams - mailto:jc.adams&reuters.com - 2000-07-01 - - - Christopher Mettin - mailto:cmettin&gqbc-online.com - 2009-05-12 - - - Chuck McManis - mailto:cmcmanis&sun.com - - - Clem Verwey - mailto:clemv&jse.co.za - 2011-12-07 - - - Colin Caughie - mailto:cfc&indigo-avs.com - 2000-05-01 - - - Craig Dowell - mailto:cdowell&quicinc.com - 2011-11-18 - - - Dan Jackson - mailto:jdan&us.ibm.com - 1997-09-01 - - - Dan Jakubiec - mailto:dan.jakubiec&systech.com - 2006-09-21 - - - Daniel Dissett - mailto:ddissett&peerlogic.com - 1998-12-01 - - - Daniel Steinber - mailto:Daniel.Steinberg&eng.sun.com - - - Darcy Brockbank - mailto:darcy&hasc.com - 1997-12-01 - - - Darrell Sveistrup - mailto:darrells&truesolutions.net - 1999-06-01 - - - Dave Cheriton - mailto:cheriton&dsg.stanford.edu - - - Dave Glanzer - mailto:dave.glanzer&fieldbus.org - 2003-03-01 - - - Dave Thaler - mailto:dthaler&microsoft.com - 2000-06-01 - - - David Brett - mailto:david.brett&alpha-group.ca - 2011-10-25 - - - David Meyer - mailto:meyer&ns.uoregon.edu - 1997-01-01 - - - David Mills - mailto:mills&udel.edu - - - David Poole - mailto:davep&extendsys.com - 1997-04-01 - - - David Rubin - mailto:drubin&ncc.net - 1996-08-01 - - - David Wilson - mailto:dwilson&m-x.ca - 2013-05-30 - - - Dean Blackketter - mailto:dean&corp.webtv.net - 1998-11-01 - - - Dino Farinacci - mailto:dino&procket.com - 1996-03-01 - - - Dirk Koopman - mailto:djk&tobit.co.uk - 2000-07-01 - - - Doug Dillon - mailto:dillon&hns.com - 1998-08-01 - - - Douglas Marquardt - mailto:dmarquar&woz.org - 1997-02-01 - - - Duane Wessels - mailto:wessels&nlanr.net - 1997-02-01 - - - Ed Moran - mailto:admin&cruzjazz.com - 1997-10-01 - - - Ed Purkiss - mailto:epurkiss&wdmacodi.com - 1998-09-01 - - - Eric Hall - mailto:ehall&ntrg.com - 1999-10-01 - - - Erik Guttman - mailto:Erik.Guttman&sun.com - 2001-12-01 - - - Euronext Admin - mailto:iana-admin&euronext.com - 2014-11-24 - - - Evan Caves - mailto:evan&acc.com - 1998-06-01 - - - Fabrice Albert - mailto:falbert&ise.com - 2012-07-12 - - - Florian Weimer - mailto:fweimer&redhat.com - 2013-02-08 - - - Fred Baker - mailto:fred&cisco.com - 1997-06-01 - - - Gajendra Shukla - mailto:gshukla&proxim.com - 2002-02-01 - - - Gary S. Malkin - mailto:GMALKIN&xylogics.com - - - Gary Scott Malkin - mailto:gmalkin&baynetworks.com - 1998-02-01 - - - Gene Marsh - mailto:MarshM&diebold.com - 1998-11-01 - - - Geoff Mendal - mailto:mendal&talarian.com - 1999-01-01 - - - George Neville-Neil - mailto:gnn&neville-neil.com - 2014-12-17 - - - Gerald Hanweck - mailto:jhanweck&hanweckassoc.com - 2014-09-05 - - - Greig Saunders - mailto:gsaunder&londonstockexchange.com - 2009-05-12 - - - Guido Petronio - mailto:guido.petronio&moneyline.com - 2004-01-01 - - - Guy Whitehouse - mailto:gwhitehouse&londonstockexchange.com - 2006-03-31 - - - Heiko Rupp - mailto:hwr&xlink.net - 1997-01-01 - - - Henri Moelard - mailto:HMOELARD&wcnd.nl.lucent.com - 1998-03 - - - Hiroshi Okubo - mailto:okubo.hiroshi&canon.co.jp - 2014-08-01 - - - Howard Gordon - mailto:hgordon&xingtech.com - - - IANA - mailto:iana&iana.org - - - Ian Armitage - mailto:ian&coactive.com - 1999-08-01 - - - Ian Stewart - mailto:iandbige&yahoo.com - 1999-06-01 - - - Ian Wacey - mailto:iain.wacey&gefalbany.ge.com - 2000-05-01 - - - Ian Wilson - mailto:iwilson&cisco.com - 2001-12-01 - - - Ido Rosen - mailto:iana&idorosen.com - 2012-06-19 - - - Ishan Wu - mailto:iwu&cisco.com - 2000-03-01 - - - Itamar Gilad - mailto:itamar&arootz.com - 2007-08-31 - - - J. Ryan Stinnett - mailto:jryans&mozilla.com - 2014-07-01 - - - James Crawford - mailto:jcrawford&metropol.net - 1998-05-01 - - - Jan Drwal - mailto:Jan.Drwal&deutsche-boerse.com - 2011-12-19 - - - Jan-Erik Eriksson - mailto:jee&alcom.ax - 2010-03-12 - - - Jan Vitek - mailto:vitek&selfservis.cz - 2013-01-15 - - - Jasmine Strong - mailto:jasmine&heroicrobotics.com - 2014-06-04 - - - Javier Landin - mailto:jlandin&directedge.com - 2009-08-28 - - - Jeff Schenk - mailto:Jeff.Schenk&intelliden.com - 2006-03-31 - - - Jerome Albin - mailto:albin&taec.enet.dec.com - 1997-06-01 - - - Jerry Whitaker - mailto:jwhitaker&atsc.org - 2008-12-19 - - - Jim Ginsburg - mailto:JGinsburg&jonescorp.com - 2007-10-31 - - - Jim Lyle - mailto:jim.lyle&siliconimage.com - 2006-08-07 - - - Jim Toga - mailto:jtoga&ibeam.jf.intel.com - 1996-05-01 - - - Joel Lynch - mailto:joel.lynch&cnn.com - 1999-04-01 - - - Johan Deleu - mailto:johan.deleu&alcatel.be - 2002-02-01 - - - John Catherino - mailto:cajo&dev.java.net - 2006-03-31 - - - John Gabler - mailto:john.gabler&ips.invensys.com - 2007-07-06 - - - John Rittner - mailto:rittnerj&cboe.com - 2012-04-10 - - - John Veizades - mailto:veizades&tgv.com - 1995-05-01 - - - Jon Crowcroft - mailto:jon&hocus.cs.ucl.ac.uk - 1998-11-01 - - - Jon Gabriel - mailto:grabriel&tivoli.com - 1998-12-01 - - - Jon Postel - mailto:postel&isi.edu - - - Jonathan Niedfeldt - mailto:jon&digitalacoustics.com - 2008-02-22 - - - Jose Luis Marocho - mailto:73374.313&compuserve.com - 1996-07-01 - - - Julian Nevell - mailto:JNEVELL&vbs.bt.co.uk - 1999-08-01 - - - Kang Lee - mailto:kang.lee&nist.gov - 2007-02-02 - - - Karen Seo - mailto:kseo&bbn.com - - - Karl Elad - mailto:karl.elad&intelsat.com - 2006-03-31 - - - Keith Thompson - mailto:thompson&ridgeback.east.sun.com - 2001-06-01 - - - Kevin Gross - mailto:kvng&ieee.org - 2010-03-12 - - - Kevin Gross - mailto:kevin.gross&avanw.com - 2012-08-28 - - - KPN IP Office - mailto:kpn-ip-office&kpn.com - 2011-04-18 - - - Kristian A. Bognaes - mailto:kristian.bognaes&norman.com - 2014-01-08 - - - Lev V. Cherednikov - mailto:lev.cherednikov&nbn-holding.ru - 2014-04-12 - - - Liming Wei - mailto:lwei&cisco.com - 1998-10-01 - - - Lloyd Wood - mailto:L.Wood&surrey.ac.uk - 2011-03-17 - - - Louis Mamakos - mailto:louie&uu.net - 1997-03-01 - - - Kenneth Felix - mailto:ken&spryware.com - 2010-08-12 - - - Madhav Karhade - mailto:Madhav.Karhade&wibhu.com - 2003-05-01 - - - Marc Goossens - mailto:mgoossens&eiba.com - 2003-07-01 - - - Mark Armstrong - mailto:Mark.Armstrong&soleratec.com - 2006-02-09 - - - Mark Bakke - mailto:mbakke&cisco.com - 2001-12-01 - - - Mark Chester - mailto:networks&aquis.eu - 2013-05-13 - - - Mark Hamilton - mailto:mah&spectralink.com - 1998-11-01 - - - Mark Handley - mailto:mjh&isi.edu - 1998-12-01 - - - Mark Lewis - mailto:Mark_Lewis&ccm.jf.intel.com - 1995-10-01 - - - Mark Lipford - mailto:mark.a.lipford&sprint.com - 2006-07-11 - - - Marlon Berlin - mailto:marlon.berlin&dns-net.de - 2013-05-25 - - - Martin Forssen - mailto:maf&dtek.chalmers.se - - - Mary Timm - mailto:mary&xenoscience.com - 1998-07-01 - - - Masato Shindoh - mailto:jl11456&yamato.ibm.co.jp - 1997-08-01 - - - Matthew Straight - mailto:matt_straight&yahoo.com - 2007-03-01 - - - Maurice Robberson - mailto:ceo&mediastreamusa.com - 2006-09-15 - - - Media Alliance JSC - mailto:noc&medi-a.ru - 2008-01-15 - - - Michael Caravetta - mailto:Michael.Caravetta&tsx.com - 2012-06-15 - - - Michael Caravetta - mailto:Network_Reps&tsx.com - 2013-06-03 - - - Michael DeMoney - mailto:demoney&eng.sun.com - 1997-04-01 - - - Michael Dolan - mailto:miked&tbt.com - 2003-10-01 - - - Michael Kreutzjans - mailto:mike&spryware.com - 2007-03-01 - - - Michael Lyle - mailto:protocols&translattice.com - 2009-11-11 - - - Michael Rosenberg - mailto:michael.rosenberg&nasdaqomx.com - 2012-03-15 - - - Michael Wang - mailto:Michael.Wang&usa.xerox.com - 1999-03-01 - - - Mika Uusitalo - mailto:msu&xingtech.com - 1997-04-01 - - - Mike Rodbell - mailto:mrodbell&ciena.com - 1997-01-01 - - - Mike Roper - mailto:mroper&8x8.com - 1999-09-01 - - - Mike Velten - mailto:mike_velten&liebert.com - 1999-01-01 - - - Moe Singh - mailto:moesingh&hotmail.com - 2009-09-24 - - - Morten Lindeman - mailto:Morten.Lindeman&os.telia.no - 1999-03-01 - - - Morteza Kalhour - mailto:morteza.kalhour&nokia.com - 2002-10-01 - - - Nadine Guillaume - mailto:nadine.guillaume&sciatl.com - 2005-02-01 - - - Nedelcho Stanev - mailto:nstanev&csoft.bg - 1999-05-01 - - - NE-TEAM_at_telecomsys.com - mailto:NE-TEAM&telecomsys.com - 2014-11-07 - - - Nick Barendt - mailto:nbarendt&vxitech.com - 2005-11-01 - - - Nigel Thompson - mailto:nigelt&tribal.com - 1999-01-01 - - - Oliver Lewis - mailto:o.lewis&icerobotics.co.uk - 2006-07-11 - - - OSPF WG Chairs - mailto:ospf-chairs&ietf.org - - - Oyvind H. Olsen - mailto:oyvind-hollup.olsen&canaldigital.com - 2007-09-12 - - - Paolo Strazzera - mailto:p.strazzera&telematica.it - 1999-06-01 - - - Patrick Cipiere - mailto:Patrick.Cipiere&udcast.com - 2001-01-01 - - - Paul Langille - mailto:plangille&dnpg.com - 2007-01-17 - - - Paul Suhler - mailto:paul.suhler&quantum.com - 2009-05-12 - - - Paul Wallner - mailto:paul.wallner&wienstrom.at - 2010-09-14 - - - Paul Wissenbach - mailto:paulwi&vnd.tek.com - 1997-06-01 - - - Peter Aronson - mailto:paronson&esri.com - 1998-08-01 - - - Peter Parnes - mailto:peppar&marratech.com - 2000-02-01 - - - Peter White - mailto:peter_white&3com.com - 1999-04-01 - - - Pierre Oliver - mailto:polivier&calamp.com - 2011-06-06 - - - Piers Scannell - mailto:piers&globecastne.com - 2000-03-01 - - - Pilz GmbH and Co. KG - mailto:pilz.gmbh&pilz.de - 2009-03-17 - - - Prakash Banthia - mailto:prakash_banthia&3com.com - 1998-09-01 - - - Ralph Kammerlander - mailto:ralph.kammerlander&khe.siemens.de - 2000-06-01 - - - Ram Iyer - mailto:ram&aaccorp.com - 1998-03-01 - - - Raymond Shum - mailto:rshum&ms.com - 1998-04-01 - - - Richard Hodges - mailto:rh&source.net - 1999-03-01 - - - Richard Zulch - mailto:richard_zulch&dantz.com - 2004-05-01 - - - RIR Admin - mailto:riradmin&nyx.com - 2013-10-29 - - - Rob Janssen - mailto:rob&pe1chl.ampr.org - 1995-01-01 - - - Robert Hodgson - mailto:robert&paratek.co.uk - 2001-12-01 - - - Robert Sautter - mailto:rsautter&acdnj.itt.com - 1999-08-01 - - - Robert Sliwinski - mailto:sliwinre&mail1st.com - 2000-02-01 - - - Roberto Costa Simoes - mailto:rcosta&bvmf.com.br - 2010-08-18 - - - Ron van der Meulen - mailto:ron_vandermeulen&agilent.com - 1997-02-01 - - - Ruben Hernandez - mailto:rhernandez&miami-holdings.com - 2011-06-06 - - - Ryon Coleman - mailto:rcoleman&3eti.com - 2006-04-11 - - - SEIKO EPSON Corp - mailto:ogata.hideaki&exc.epson.co.jp - 2005-01-01 - - - Sakon Kittivatcharapong - mailto:sakonk&cscoms.net - 2000-05-01 - - - Sam Birru - mailto:sam.birru&instinet.co.uk - 2014-09-05 - - - Sarunas Brakauskas - mailto:sbrakaus&cme.com - 2007-07-17 - - - Scott Watson - mailto:scott&disney.com - 1997-08-01 - - - Sergey Shulgin - mailto:sshulgin&pinkotc.com - 2008-08-12 - - - Shai Revzen - mailto:shai.revzen&harmonicinc.com - 1999-04-01 - - - Shane Rowatt - mailto:shane.rowatt&star.com.au - 1997-03-01 - - - Shivaun Albright - mailto:shivaun_albright&hp.com - 1997-07-01 - - - Simon Barber - mailto:simon.barber&parc.com - 2009-09-24 - - - Soren Martin Sorensen - mailto:sms&energimidt.dk - 2006-08-07 - - - Stacey O'Rourke - mailto:stacey&network-alchemy.com - 1999-08-01 - - - Stacey O'Rourke - mailto:stacey&cips.nokia.com - 2001-01-01 - - - Stephan Wasserroth - mailto:wasserroth&fokus.gmd.de - 2000-07-01 - - - Stephen Dunne - mailto:sdun&isma.co.uk - 1997-01-01 - - - Stephen Hanna - mailto:steve.hanna&sun.com - 2000-07-01 - - - Stephen Ray Middleton - mailto:stephen.r.middleton&verizon.com - 2015-03-23 - - - Stephen T. Lyda - mailto:slyda&emsg.com - 2000-02-01 - - - Steve Casner - mailto:casner&precept.com - - - Steve Casner - mailto:casner&isi.edu - 1995-01-01 - - - Steve Deering - mailto:deering&cisco.com - 1999-10-01 - - - Steve Deering - mailto:deering&parc.xerox.com - - - Steve Polishinski - mailto:spolishinski&etcconnect.com - 2000-03-01 - - - Stuart Kerry - mailto:stuart.kerry&philips.com - 2003-01-01 - - - Susie Armstrong - mailto:Armstrong.wbst128&xerox.com - - - Takeshi Saito - mailto:takeshi.saito&toshiba.co.jp - 2003-02-01 - - - Technicolor NL NOC - mailto:noc&technicolor.com - 2009-12-23 - - - Terry Gibson - mailto:terry.gibson&sun.com - 1997-08-01 - - - Tetsuo Hoshi - mailto:tetsuo.hoshi&jp.yokogawa.com - 2004-06-01 - - - Tim DeBaillie - mailto:debaillie&ciholas.com - 2006-11-30 - - - Tim Gorsline - mailto:tgorsline&batstrading.com - 2011-01-31 - - - mailto:tjohnson&londonstockexchange.com - 2012-04-11 - - - Tom Ballister - mailto:tom&ballister.com - 1997-07-01 - - - Tom Blank - mailto:tomblank&microsoft.com - 1996-11-01 - - - Tom White - mailto:info&midi.org - 2011-11-02 - - - Tony Ballardie - mailto:A.Ballardie&cs.ucl.ac.uk - 1997-02-01 - - - Tony Barber - mailto:tony.barber&wcom.com - 1997-01-01 - - - Tony Przygienda - mailto:prz&siara.com - 1999-10-01 - - - Tony Wong - mailto:wongt&ms.com - 1998-07-01 - - - Tradition Network Operations and Command Center - mailto:SH-Networking&tradition.com - 2010-09-22 - - - UPnP Forum - mailto:upnpadmin&forum.upnp.org - 2006-06-27 - - - Victor Volpe - mailto:vvolpe&smtp.microcom.com - 1997-10-01 - - - Wally Beddoe - mailto:WBeddoe&tkusa.com - 2003-04-01 - - - Walter Wallach - mailto:walt&sumatech.com - 1999-07-01 - - - Wayne Carr - mailto:Wayne_Carr&ccm.intel.com - 1997-12-01 - - - Wayne Wenyu Liu - mailto:wayne.wenyu.liu&gmail.com - 2012-06-12 - - - Wenjie Peng - mailto:wpeng&tts.telerate.com - 1997-01-01 - - - Werner Vogels - mailto:vogels&rnets.com - 1998-08-01 - - - Wieland Holdfelder - mailto:whd&pi4.informatik.uni-mannheim.de - 1997-01-01 - - - Xiaoyu Zhou - mailto:zhouxyi&lenovo.com - 2009-01-20 - - - Yea Uang - mailto:uang&force.decnet.lockheed.com - 1994-11-01 - - - Yossi Gal - mailto:yossi&gilat.com - 1998-02-01 - - - Zaklina Petkovic - mailto:zaklina.petkovic&alphatradingsystems.ca - 2011-07-13 - - - Zaklina Petkovic - mailto:zaklina.petkovic&aequin.com - 2014-05-16 - - - Zia Bhatti - mailto:zia&netright.com - 1998-09-01 - - - diff --git a/awx/lib/site-packages/netaddr/ip/nmap.py b/awx/lib/site-packages/netaddr/ip/nmap.py deleted file mode 100644 index f04c8fb9ab..0000000000 --- a/awx/lib/site-packages/netaddr/ip/nmap.py +++ /dev/null @@ -1,98 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -Routines for dealing with nmap-style IPv4 address ranges. - -Based on nmap's Target Specification :- - - http://nmap.org/book/man-target-specification.html -""" - -from netaddr.core import AddrFormatError -from netaddr.ip import IPAddress -from netaddr.compat import _iter_range, _is_str - - -def _nmap_octet_target_values(spec): - # Generates sequence of values for an individual octet as defined in the - # nmap Target Specification. - values = set() - - for element in spec.split(','): - if '-' in element: - left, right = element.split('-', 1) - if not left: - left = 0 - if not right: - right = 255 - low = int(left) - high = int(right) - if not ((0 <= low <= 255) and (0 <= high <= 255)): - raise ValueError('octet value overflow for spec %s!' % spec) - if low > high: - raise ValueError('left side of hyphen must be <= right %r' % element) - for octet in _iter_range(low, high + 1): - values.add(octet) - else: - octet = int(element) - if not (0 <= octet <= 255): - raise ValueError('octet value overflow for spec %s!' % spec) - values.add(octet) - - return sorted(values) - - -def _generate_nmap_octet_ranges(nmap_target_spec): - # Generate 4 lists containing all octets defined by a given nmap Target - # specification. - if not _is_str(nmap_target_spec): - raise TypeError('string expected, not %s' % type(nmap_target_spec)) - - if not nmap_target_spec: - raise ValueError('nmap target specification cannot be blank!') - - tokens = nmap_target_spec.split('.') - - if len(tokens) != 4: - raise AddrFormatError('invalid nmap range: %s' % nmap_target_spec) - - return (_nmap_octet_target_values(tokens[0]), - _nmap_octet_target_values(tokens[1]), - _nmap_octet_target_values(tokens[2]), - _nmap_octet_target_values(tokens[3])) - - -def valid_nmap_range(nmap_target_spec): - """ - :param nmap_target_spec: an nmap-style IP range target specification. - - :return: ``True`` if IP range target spec is valid, ``False`` otherwise. - """ - try: - _generate_nmap_octet_ranges(nmap_target_spec) - return True - except (TypeError, ValueError, AddrFormatError): - pass - return False - - -def iter_nmap_range(nmap_target_spec): - """ - The nmap security tool supports a custom type of IPv4 range using multiple - hyphenated octets. This generator provides iterators yielding IP addresses - according to this rule set. - - :param nmap_target_spec: an nmap-style IP range target specification. - - :return: an iterator producing IPAddress objects for each IP in the range. - """ - octet_ranges = _generate_nmap_octet_ranges(nmap_target_spec) - for w in octet_ranges[0]: - for x in octet_ranges[1]: - for y in octet_ranges[2]: - for z in octet_ranges[3]: - yield IPAddress("%d.%d.%d.%d" % (w, x, y, z), 4) - diff --git a/awx/lib/site-packages/netaddr/ip/rfc1924.py b/awx/lib/site-packages/netaddr/ip/rfc1924.py deleted file mode 100644 index 6ea05661ad..0000000000 --- a/awx/lib/site-packages/netaddr/ip/rfc1924.py +++ /dev/null @@ -1,58 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""A basic implementation of RFC 1924 ;-)""" - -from netaddr.core import AddrFormatError -from netaddr.ip import IPAddress - -from netaddr.compat import _zip - - -def chr_range(low, high): - """Returns all characters between low and high chars.""" - return [chr(i) for i in range(ord(low), ord(high)+1)] - -#: Base 85 integer index to character lookup table. -BASE_85 = chr_range('0', '9') + chr_range('A', 'Z') + chr_range('a', 'z') + \ - ['!', '#', '$', '%', '&', '(',')', '*', '+', '-',';', '<', '=', '>', - '?', '@', '^', '_','`', '{', '|', '}', '~'] - -#: Base 85 digit to integer lookup table. -BASE_85_DICT = dict(_zip(BASE_85, range(0, 86))) - - -def ipv6_to_base85(addr): - """Convert a regular IPv6 address to base 85.""" - ip = IPAddress(addr) - int_val = int(ip) - - remainder = [] - while int_val > 0: - remainder.append(int_val % 85) - int_val //= 85 - - encoded = ''.join([BASE_85[w] for w in reversed(remainder)]) - leading_zeroes = (20 - len(encoded)) * "0" - return leading_zeroes + encoded - - -def base85_to_ipv6(addr): - """ - Convert a base 85 IPv6 address to its hexadecimal format. - """ - tokens = list(addr) - - if len(tokens) != 20: - raise AddrFormatError('Invalid base 85 IPv6 address: %r' % addr) - - result = 0 - for i, num in enumerate(reversed(tokens)): - num = BASE_85_DICT[num] - result += (num * 85 ** i) - - ip = IPAddress(result, 6) - - return str(ip) diff --git a/awx/lib/site-packages/netaddr/ip/sets.py b/awx/lib/site-packages/netaddr/ip/sets.py deleted file mode 100644 index 5df6e9f254..0000000000 --- a/awx/lib/site-packages/netaddr/ip/sets.py +++ /dev/null @@ -1,743 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""Set based operations for IP addresses and subnets.""" - -import itertools as _itertools - -from netaddr.ip import IPNetwork, IPAddress, IPRange, cidr_merge, \ - cidr_exclude, iprange_to_cidrs - -from netaddr.compat import _sys_maxint, _dict_keys, _int_type - - -def _subtract(supernet, subnets, subnet_idx, ranges): - """Calculate IPSet([supernet]) - IPSet(subnets). - - Assumptions: subnets is sorted, subnet_idx points to the first - element in subnets that is a subnet of supernet. - - Results are appended to the ranges parameter as tuples of in format - (version, first, last). Return value is the first subnet_idx that - does not point to a subnet of supernet (or len(subnets) if all - subsequents items are a subnet of supernet). - """ - version = supernet._module.version - subnet = subnets[subnet_idx] - if subnet.first > supernet.first: - ranges.append((version, supernet.first, subnet.first - 1)) - - subnet_idx += 1 - prev_subnet = subnet - while subnet_idx < len(subnets): - cur_subnet = subnets[subnet_idx] - - if cur_subnet not in supernet: - break - if prev_subnet.last + 1 == cur_subnet.first: - # two adjacent, non-mergable IPNetworks - pass - else: - ranges.append((version, prev_subnet.last + 1, cur_subnet.first - 1)) - - subnet_idx += 1 - prev_subnet = cur_subnet - - first = prev_subnet.last + 1 - last = supernet.last - if first <= last: - ranges.append((version, first, last)) - - return subnet_idx - -def _iter_merged_ranges(sorted_ranges): - """Iterate over sorted_ranges, merging where possible - - Sorted ranges must be a sorted iterable of (version, first, last) tuples. - Merging occurs for pairs like [(4, 10, 42), (4, 43, 100)] which is merged - into (4, 10, 100), and leads to return value - ( IPAddress(10, 4), IPAddress(100, 4) ), which is suitable input for the - iprange_to_cidrs function. - """ - if not sorted_ranges: - return - - current_version, current_start, current_stop = sorted_ranges[0] - - for next_version, next_start, next_stop in sorted_ranges[1:]: - if next_start == current_stop + 1 and next_version == current_version: - # Can be merged. - current_stop = next_stop - continue - # Cannot be merged. - yield (IPAddress(current_start, current_version), - IPAddress(current_stop, current_version)) - current_start = next_start - current_stop = next_stop - current_version = next_version - yield (IPAddress(current_start, current_version), - IPAddress(current_stop, current_version)) - - -class IPSet(object): - """ - Represents an unordered collection (set) of unique IP addresses and - subnets. - - """ - __slots__ = ('_cidrs',) - - def __init__(self, iterable=None, flags=0): - """ - Constructor. - - :param iterable: (optional) an iterable containing IP addresses and - subnets. - - :param flags: decides which rules are applied to the interpretation - of the addr value. See the netaddr.core namespace documentation - for supported constant values. - - """ - if isinstance(iterable, IPNetwork): - self._cidrs = {IPNetwork(iterable): True} - elif isinstance(iterable, IPRange): - self._cidrs = dict.fromkeys( - iprange_to_cidrs(iterable[0], iterable[-1]), True) - elif isinstance(iterable, IPSet): - self._cidrs = dict.fromkeys(iterable.iter_cidrs(), True) - else: - self._cidrs = {} - if iterable is not None: - mergeable = [] - for addr in iterable: - if isinstance(addr, _int_type): - addr = IPAddress(addr, flags=flags) - mergeable.append(addr) - - for cidr in cidr_merge(mergeable): - self._cidrs[cidr] = True - - def __getstate__(self): - """:return: Pickled state of an ``IPSet`` object.""" - return tuple([cidr.__getstate__() for cidr in self._cidrs]) - - def __setstate__(self, state): - """ - :param state: data used to unpickle a pickled ``IPSet`` object. - - """ - self._cidrs = dict.fromkeys( - (IPNetwork((value, prefixlen), version=version) - for value, prefixlen, version in state), - True) - - def _compact_single_network(self, added_network): - """ - Same as compact(), but assume that added_network is the only change and - that this IPSet was properly compacted before added_network was added. - This allows to perform compaction much faster. added_network must - already be present in self._cidrs. - """ - added_first = added_network.first - added_last = added_network.last - added_version = added_network.version - - # Check for supernets and subnets of added_network. - if added_network._prefixlen == added_network._module.width: - # This is a single IP address, i.e. /32 for IPv4 or /128 for IPv6. - # It does not have any subnets, so we only need to check for its - # potential supernets. - for potential_supernet in added_network.supernet(): - if potential_supernet in self._cidrs: - del self._cidrs[added_network] - return - else: - # IPNetworks from self._cidrs that are subnets of added_network. - to_remove = [] - for cidr in self._cidrs: - if (cidr._module.version != added_version or cidr == added_network): - # We found added_network or some network of a different version. - continue - first = cidr.first - last = cidr.last - if first >= added_first and last <= added_last: - # cidr is a subnet of added_network. Remember to remove it. - to_remove.append(cidr) - elif first <= added_first and last >= added_last: - # cidr is a supernet of added_network. Remove added_network. - del self._cidrs[added_network] - # This IPSet was properly compacted before. Since added_network - # is removed now, it must again be properly compacted -> done. - assert(not to_remove) - return - for item in to_remove: - del self._cidrs[item] - - # Check if added_network can be merged with another network. - - # Note that merging can only happen between networks of the same - # prefixlen. This just leaves 2 candidates: The IPNetworks just before - # and just after the added_network. - # This can be reduced to 1 candidate: 10.0.0.0/24 and 10.0.1.0/24 can - # be merged into into 10.0.0.0/23. But 10.0.1.0/24 and 10.0.2.0/24 - # cannot be merged. With only 1 candidate, we might as well make a - # dictionary lookup. - shift_width = added_network._module.width - added_network.prefixlen - while added_network.prefixlen != 0: - # figure out if the least significant bit of the network part is 0 or 1. - the_bit = (added_network._value >> shift_width) & 1 - if the_bit: - candidate = added_network.previous() - else: - candidate = added_network.next() - - if candidate not in self._cidrs: - # The only possible merge does not work -> merge done - return - # Remove added_network&candidate, add merged network. - del self._cidrs[candidate] - del self._cidrs[added_network] - added_network.prefixlen -= 1 - # Be sure that we set the host bits to 0 when we move the prefixlen. - # Otherwise, adding 255.255.255.255/32 will result in a merged - # 255.255.255.255/24 network, but we want 255.255.255.0/24. - shift_width += 1 - added_network._value = (added_network._value >> shift_width) << shift_width - self._cidrs[added_network] = True - - def compact(self): - """ - Compact internal list of `IPNetwork` objects using a CIDR merge. - """ - cidrs = cidr_merge(self._cidrs) - self._cidrs = dict.fromkeys(cidrs, True) - - def __hash__(self): - """ - Raises ``TypeError`` if this method is called. - - .. note:: IPSet objects are not hashable and cannot be used as \ - dictionary keys or as members of other sets. \ - """ - raise TypeError('IP sets are unhashable!') - - def __contains__(self, ip): - """ - :param ip: An IP address or subnet. - - :return: ``True`` if IP address or subnet is a member of this IP set. - """ - ip = IPNetwork(ip) - # Iterating over self._cidrs is an O(n) operation: 1000 items in - # self._cidrs would mean 1000 loops. Iterating over all possible - # supernets loops at most 32 times for IPv4 or 128 times for IPv6, - # no matter how many CIDRs this object contains. - if ip in self._cidrs: - return True - for cidr in ip.supernet(): - if cidr in self._cidrs: - return True - return False - - def __nonzero__(self): - """Return True if IPSet contains at least one IP, else False""" - return bool(self._cidrs) - - __bool__ = __nonzero__ # Python 3.x. - - def __iter__(self): - """ - :return: an iterator over the IP addresses within this IP set. - """ - return _itertools.chain(*sorted(self._cidrs)) - - def iter_cidrs(self): - """ - :return: an iterator over individual IP subnets within this IP set. - """ - return sorted(self._cidrs) - - def add(self, addr, flags=0): - """ - Adds an IP address or subnet or IPRange to this IP set. Has no effect if - it is already present. - - Note that where possible the IP address or subnet is merged with other - members of the set to form more concise CIDR blocks. - - :param addr: An IP address or subnet in either string or object form, or - an IPRange object. - - :param flags: decides which rules are applied to the interpretation - of the addr value. See the netaddr.core namespace documentation - for supported constant values. - - """ - if isinstance(addr, IPRange): - new_cidrs = dict.fromkeys( - iprange_to_cidrs(addr[0], addr[-1]), True) - self._cidrs.update(new_cidrs) - self.compact() - return - - if isinstance(addr, _int_type): - addr = IPNetwork(IPAddress(addr, flags=flags)) - else: - addr = IPNetwork(addr) - - self._cidrs[addr] = True - self._compact_single_network(addr) - - def remove(self, addr, flags=0): - """ - Removes an IP address or subnet or IPRange from this IP set. Does - nothing if it is not already a member. - - Note that this method behaves more like discard() found in regular - Python sets because it doesn't raise KeyError exceptions if the - IP address or subnet is question does not exist. It doesn't make sense - to fully emulate that behaviour here as IP sets contain groups of - individual IP addresses as individual set members using IPNetwork - objects. - - :param addr: An IP address or subnet, or an IPRange. - - :param flags: decides which rules are applied to the interpretation - of the addr value. See the netaddr.core namespace documentation - for supported constant values. - - """ - if isinstance(addr, IPRange): - cidrs = iprange_to_cidrs(addr[0], addr[-1]) - for cidr in cidrs: - self.remove(cidr) - return - - if isinstance(addr, _int_type): - addr = IPAddress(addr, flags=flags) - else: - addr = IPNetwork(addr) - - # This add() is required for address blocks provided that are larger - # than blocks found within the set but have overlaps. e.g. :- - # - # >>> IPSet(['192.0.2.0/24']).remove('192.0.2.0/23') - # IPSet([]) - # - self.add(addr) - - remainder = None - matching_cidr = None - - # Search for a matching CIDR and exclude IP from it. - for cidr in self._cidrs: - if addr in cidr: - remainder = cidr_exclude(cidr, addr) - matching_cidr = cidr - break - - # Replace matching CIDR with remaining CIDR elements. - if remainder is not None: - del self._cidrs[matching_cidr] - for cidr in remainder: - self._cidrs[cidr] = True - # No call to self.compact() is needed. Removing an IPNetwork cannot - # create mergable networks. - - def pop(self): - """ - Removes and returns an arbitrary IP address or subnet from this IP - set. - - :return: An IP address or subnet. - """ - return self._cidrs.popitem()[0] - - def isdisjoint(self, other): - """ - :param other: an IP set. - - :return: ``True`` if this IP set has no elements (IP addresses - or subnets) in common with other. Intersection *must* be an - empty set. - """ - result = self.intersection(other) - return not result - - def copy(self): - """:return: a shallow copy of this IP set.""" - obj_copy = self.__class__() - obj_copy._cidrs.update(self._cidrs) - return obj_copy - - def update(self, iterable, flags=0): - """ - Update the contents of this IP set with the union of itself and - other IP set. - - :param iterable: an iterable containing IP addresses and subnets. - - :param flags: decides which rules are applied to the interpretation - of the addr value. See the netaddr.core namespace documentation - for supported constant values. - - """ - if isinstance(iterable, IPSet): - self._cidrs = dict.fromkeys( - (ip for ip in cidr_merge(_dict_keys(self._cidrs) - + _dict_keys(iterable._cidrs))), True) - return - elif isinstance(iterable, (IPNetwork, IPRange)): - self.add(iterable) - return - - if not hasattr(iterable, '__iter__'): - raise TypeError('an iterable was expected!') - # An iterable containing IP addresses or subnets. - mergeable = [] - for addr in iterable: - if isinstance(addr, _int_type): - addr = IPAddress(addr, flags=flags) - mergeable.append(addr) - - for cidr in cidr_merge(_dict_keys(self._cidrs) + mergeable): - self._cidrs[cidr] = True - - self.compact() - - def clear(self): - """Remove all IP addresses and subnets from this IP set.""" - self._cidrs = {} - - def __eq__(self, other): - """ - :param other: an IP set - - :return: ``True`` if this IP set is equivalent to the ``other`` IP set, - ``False`` otherwise. - """ - try: - return self._cidrs == other._cidrs - except AttributeError: - return NotImplemented - - def __ne__(self, other): - """ - :param other: an IP set - - :return: ``False`` if this IP set is equivalent to the ``other`` IP set, - ``True`` otherwise. - """ - try: - return self._cidrs != other._cidrs - except AttributeError: - return NotImplemented - - def __lt__(self, other): - """ - :param other: an IP set - - :return: ``True`` if this IP set is less than the ``other`` IP set, - ``False`` otherwise. - """ - if not hasattr(other, '_cidrs'): - return NotImplemented - - return self.size < other.size and self.issubset(other) - - def issubset(self, other): - """ - :param other: an IP set. - - :return: ``True`` if every IP address and subnet in this IP set - is found within ``other``. - """ - for cidr in self._cidrs: - if cidr not in other: - return False - return True - - __le__ = issubset - - def __gt__(self, other): - """ - :param other: an IP set. - - :return: ``True`` if this IP set is greater than the ``other`` IP set, - ``False`` otherwise. - """ - if not hasattr(other, '_cidrs'): - return NotImplemented - - return self.size > other.size and self.issuperset(other) - - def issuperset(self, other): - """ - :param other: an IP set. - - :return: ``True`` if every IP address and subnet in other IP set - is found within this one. - """ - if not hasattr(other, '_cidrs'): - return NotImplemented - - for cidr in other._cidrs: - if cidr not in self: - return False - return True - - __ge__ = issuperset - - def union(self, other): - """ - :param other: an IP set. - - :return: the union of this IP set and another as a new IP set - (combines IP addresses and subnets from both sets). - """ - ip_set = self.copy() - ip_set.update(other) - return ip_set - - __or__ = union - - def intersection(self, other): - """ - :param other: an IP set. - - :return: the intersection of this IP set and another as a new IP set. - (IP addresses and subnets common to both sets). - """ - result_cidrs = {} - - own_nets = sorted(self._cidrs) - other_nets = sorted(other._cidrs) - own_idx = 0 - other_idx = 0 - own_len = len(own_nets) - other_len = len(other_nets) - while own_idx < own_len and other_idx < other_len: - own_cur = own_nets[own_idx] - other_cur = other_nets[other_idx] - - if own_cur == other_cur: - result_cidrs[own_cur] = True - own_idx += 1 - other_idx += 1 - elif own_cur in other_cur: - result_cidrs[own_cur] = True - own_idx += 1 - elif other_cur in own_cur: - result_cidrs[other_cur] = True - other_idx += 1 - else: - # own_cur and other_cur have nothing in common - if own_cur < other_cur: - own_idx += 1 - else: - other_idx += 1 - - # We ran out of networks in own_nets or other_nets. Either way, there - # can be no further result_cidrs. - result = IPSet() - result._cidrs = result_cidrs - return result - - __and__ = intersection - - def symmetric_difference(self, other): - """ - :param other: an IP set. - - :return: the symmetric difference of this IP set and another as a new - IP set (all IP addresses and subnets that are in exactly one - of the sets). - """ - # In contrast to intersection() and difference(), we cannot construct - # the result_cidrs easily. Some cidrs may have to be merged, e.g. for - # IPSet(["10.0.0.0/32"]).symmetric_difference(IPSet(["10.0.0.1/32"])). - result_ranges = [] - - own_nets = sorted(self._cidrs) - other_nets = sorted(other._cidrs) - own_idx = 0 - other_idx = 0 - own_len = len(own_nets) - other_len = len(other_nets) - while own_idx < own_len and other_idx < other_len: - own_cur = own_nets[own_idx] - other_cur = other_nets[other_idx] - - if own_cur == other_cur: - own_idx += 1 - other_idx += 1 - elif own_cur in other_cur: - own_idx = _subtract(other_cur, own_nets, own_idx, result_ranges) - other_idx += 1 - elif other_cur in own_cur: - other_idx = _subtract(own_cur, other_nets, other_idx, result_ranges) - own_idx += 1 - else: - # own_cur and other_cur have nothing in common - if own_cur < other_cur: - result_ranges.append( (own_cur._module.version, - own_cur.first, own_cur.last) ) - own_idx += 1 - else: - result_ranges.append( (other_cur._module.version, - other_cur.first, other_cur.last) ) - other_idx += 1 - - # If the above loop terminated because it processed all cidrs of - # "other", then any remaining cidrs in self must be part of the result. - while own_idx < own_len: - own_cur = own_nets[own_idx] - result_ranges.append((own_cur._module.version, - own_cur.first, own_cur.last)) - own_idx += 1 - - # If the above loop terminated because it processed all cidrs of - # self, then any remaining cidrs in "other" must be part of the result. - while other_idx < other_len: - other_cur = other_nets[other_idx] - result_ranges.append((other_cur._module.version, - other_cur.first, other_cur.last)) - other_idx += 1 - - result = IPSet() - for start, stop in _iter_merged_ranges(result_ranges): - cidrs = iprange_to_cidrs(start, stop) - for cidr in cidrs: - result._cidrs[cidr] = True - return result - - __xor__ = symmetric_difference - - def difference(self, other): - """ - :param other: an IP set. - - :return: the difference between this IP set and another as a new IP - set (all IP addresses and subnets that are in this IP set but - not found in the other.) - """ - result_ranges = [] - result_cidrs = {} - - own_nets = sorted(self._cidrs) - other_nets = sorted(other._cidrs) - own_idx = 0 - other_idx = 0 - own_len = len(own_nets) - other_len = len(other_nets) - while own_idx < own_len and other_idx < other_len: - own_cur = own_nets[own_idx] - other_cur = other_nets[other_idx] - - if own_cur == other_cur: - own_idx += 1 - other_idx += 1 - elif own_cur in other_cur: - own_idx += 1 - elif other_cur in own_cur: - other_idx = _subtract(own_cur, other_nets, other_idx, - result_ranges) - own_idx += 1 - else: - # own_cur and other_cur have nothing in common - if own_cur < other_cur: - result_cidrs[own_cur] = True - own_idx += 1 - else: - other_idx += 1 - - # If the above loop terminated because it processed all cidrs of - # "other", then any remaining cidrs in self must be part of the result. - while own_idx < own_len: - result_cidrs[own_nets[own_idx]] = True - own_idx += 1 - - for start, stop in _iter_merged_ranges(result_ranges): - for cidr in iprange_to_cidrs(start, stop): - result_cidrs[cidr] = True - - result = IPSet() - result._cidrs = result_cidrs - return result - - __sub__ = difference - - def __len__(self): - """ - :return: the cardinality of this IP set (i.e. sum of individual IP \ - addresses). Raises ``IndexError`` if size > maxint (a Python \ - limitation). Use the .size property for subnets of any size. - """ - size = self.size - if size > _sys_maxint: - raise IndexError("range contains more than %d (sys.maxint) " \ - "IP addresses! Use the .size property instead." % _sys_maxint) - return size - - @property - def size(self): - """ - The cardinality of this IP set (based on the number of individual IP - addresses including those implicitly defined in subnets). - """ - return sum([cidr.size for cidr in self._cidrs]) - - def __repr__(self): - """:return: Python statement to create an equivalent object""" - return 'IPSet(%r)' % [str(c) for c in sorted(self._cidrs)] - - __str__ = __repr__ - - def iscontiguous(self): - """ - Returns True if the members of the set form a contiguous IP - address range (with no gaps), False otherwise. - - :return: ``True`` if the ``IPSet`` object is contiguous. - """ - cidrs = self.iter_cidrs() - if len(cidrs) > 1: - previous = cidrs[0][0] - for cidr in cidrs: - if cidr[0] != previous: - return False - previous = cidr[-1] + 1 - return True - - def iprange(self): - """ - Generates an IPRange for this IPSet, if all its members - form a single contiguous sequence. - - Raises ``ValueError`` if the set is not contiguous. - - :return: An ``IPRange`` for all IPs in the IPSet. - """ - if self.iscontiguous(): - cidrs = self.iter_cidrs() - if not cidrs: - return None - return IPRange(cidrs[0][0], cidrs[-1][-1]) - else: - raise ValueError("IPSet is not contiguous") - - def iter_ipranges(self): - """Generate the merged IPRanges for this IPSet. - - In contrast to self.iprange(), this will work even when the IPSet is - not contiguous. Adjacent IPRanges will be merged together, so you - get the minimal number of IPRanges. - """ - sorted_ranges = [(cidr._module.version, cidr.first, cidr.last) for - cidr in self.iter_cidrs()] - - for start, stop in _iter_merged_ranges(sorted_ranges): - yield IPRange(start, stop) diff --git a/awx/lib/site-packages/netaddr/strategy/__init__.py b/awx/lib/site-packages/netaddr/strategy/__init__.py deleted file mode 100644 index 6ab370fd66..0000000000 --- a/awx/lib/site-packages/netaddr/strategy/__init__.py +++ /dev/null @@ -1,273 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -Shared logic for various address types. -""" -import re as _re - -from netaddr.compat import _range, _is_str - - -def bytes_to_bits(): - """ - :return: A 256 element list containing 8-bit binary digit strings. The - list index value is equivalent to its bit string value. - """ - lookup = [] - bits_per_byte = _range(7, -1, -1) - for num in range(256): - bits = 8 * [None] - for i in bits_per_byte: - bits[i] = '01'[num & 1] - num >>= 1 - lookup.append(''.join(bits)) - return lookup - -#: A lookup table of 8-bit integer values to their binary digit bit strings. -BYTES_TO_BITS = bytes_to_bits() - - -def valid_words(words, word_size, num_words): - """ - :param words: A sequence of unsigned integer word values. - - :param word_size: Width (in bits) of each unsigned integer word value. - - :param num_words: Number of unsigned integer words expected. - - :return: ``True`` if word sequence is valid for this address type, - ``False`` otherwise. - """ - if not hasattr(words, '__iter__'): - return False - - if len(words) != num_words: - return False - - max_word = 2 ** word_size - 1 - - for i in words: - if not 0 <= i <= max_word: - return False - - return True - - -def int_to_words(int_val, word_size, num_words): - """ - :param int_val: Unsigned integer to be divided into words of equal size. - - :param word_size: Width (in bits) of each unsigned integer word value. - - :param num_words: Number of unsigned integer words expected. - - :return: A tuple contain unsigned integer word values split according - to provided arguments. - """ - max_int = 2 ** (num_words * word_size) - 1 - - if not 0 <= int_val <= max_int: - raise IndexError('integer out of bounds: %r!' % hex(int_val)) - - max_word = 2 ** word_size - 1 - - words = [] - for _ in range(num_words): - word = int_val & max_word - words.append(int(word)) - int_val >>= word_size - - return tuple(reversed(words)) - - -def words_to_int(words, word_size, num_words): - """ - :param words: A sequence of unsigned integer word values. - - :param word_size: Width (in bits) of each unsigned integer word value. - - :param num_words: Number of unsigned integer words expected. - - :return: An unsigned integer that is equivalent to value represented - by word sequence. - """ - if not valid_words(words, word_size, num_words): - raise ValueError('invalid integer word sequence: %r!' % words) - - int_val = 0 - for i, num in enumerate(reversed(words)): - word = num - word = word << word_size * i - int_val = int_val | word - - return int_val - - -def valid_bits(bits, width, word_sep=''): - """ - :param bits: A network address in a delimited binary string format. - - :param width: Maximum width (in bits) of a network address (excluding - delimiters). - - :param word_sep: (optional) character or string used to delimit word - groups (default: '', no separator). - - :return: ``True`` if network address is valid, ``False`` otherwise. - """ - if not _is_str(bits): - return False - - if word_sep != '': - bits = bits.replace(word_sep, '') - - if len(bits) != width: - return False - - max_int = 2 ** width - 1 - - try: - if 0 <= int(bits, 2) <= max_int: - return True - except ValueError: - pass - - return False - - -def bits_to_int(bits, width, word_sep=''): - """ - :param bits: A network address in a delimited binary string format. - - :param width: Maximum width (in bits) of a network address (excluding - delimiters). - - :param word_sep: (optional) character or string used to delimit word - groups (default: '', no separator). - - :return: An unsigned integer that is equivalent to value represented - by network address in readable binary form. - """ - if not valid_bits(bits, width, word_sep): - raise ValueError('invalid readable binary string: %r!' % bits) - - if word_sep != '': - bits = bits.replace(word_sep, '') - - return int(bits, 2) - - -def int_to_bits(int_val, word_size, num_words, word_sep=''): - """ - :param int_val: An unsigned integer. - - :param word_size: Width (in bits) of each unsigned integer word value. - - :param num_words: Number of unsigned integer words expected. - - :param word_sep: (optional) character or string used to delimit word - groups (default: '', no separator). - - :return: A network address in a delimited binary string format that is - equivalent in value to unsigned integer. - """ - bit_words = [] - - for word in int_to_words(int_val, word_size, num_words): - bits = [] - while word: - bits.append(BYTES_TO_BITS[word & 255]) - word >>= 8 - bits.reverse() - bit_str = ''.join(bits) or '0' * word_size - bits = ('0' * word_size + bit_str)[-word_size:] - bit_words.append(bits) - - if word_sep is not '': - # Check custom separator. - if not _is_str(word_sep): - raise ValueError('word separator is not a string: %r!' % word_sep) - - return word_sep.join(bit_words) - - -def valid_bin(bin_val, width): - """ - :param bin_val: A network address in Python's binary representation format - ('0bxxx'). - - :param width: Maximum width (in bits) of a network address (excluding - delimiters). - - :return: ``True`` if network address is valid, ``False`` otherwise. - """ - if not _is_str(bin_val): - return False - - if not bin_val.startswith('0b'): - return False - - bin_val = bin_val.replace('0b', '') - - if len(bin_val) > width: - return False - - max_int = 2 ** width - 1 - - try: - if 0 <= int(bin_val, 2) <= max_int: - return True - except ValueError: - pass - - return False - - -def int_to_bin(int_val, width): - """ - :param int_val: An unsigned integer. - - :param width: Maximum allowed width (in bits) of a unsigned integer. - - :return: Equivalent string value in Python's binary representation format - ('0bxxx'). - """ - bin_tokens = [] - - try: - # Python 2.6.x and upwards. - bin_val = bin(int_val) - except NameError: - # Python 2.4.x and 2.5.x - i = int_val - while i > 0: - word = i & 0xff - bin_tokens.append(BYTES_TO_BITS[word]) - i >>= 8 - - bin_tokens.reverse() - bin_val = '0b' + _re.sub(r'^[0]+([01]+)$', r'\1', ''.join(bin_tokens)) - - if len(bin_val[2:]) > width: - raise IndexError('binary string out of bounds: %s!' % bin_val) - - return bin_val - - -def bin_to_int(bin_val, width): - """ - :param bin_val: A string containing an unsigned integer in Python's binary - representation format ('0bxxx'). - - :param width: Maximum allowed width (in bits) of a unsigned integer. - - :return: An unsigned integer that is equivalent to value represented - by Python binary string format. - """ - if not valid_bin(bin_val, width): - raise ValueError('not a valid Python binary string: %r!' % bin_val) - - return int(bin_val.replace('0b', ''), 2) diff --git a/awx/lib/site-packages/netaddr/strategy/eui48.py b/awx/lib/site-packages/netaddr/strategy/eui48.py deleted file mode 100644 index edef94a01e..0000000000 --- a/awx/lib/site-packages/netaddr/strategy/eui48.py +++ /dev/null @@ -1,296 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -IEEE 48-bit EUI (MAC address) logic. - -Supports numerous MAC string formats including Cisco's triple hextet as well -as bare MACs containing no delimiters. -""" -import struct as _struct -import re as _re - -# Check whether we need to use fallback code or not. -try: - from socket import AF_LINK -except ImportError: - AF_LINK = 48 - -from netaddr.core import AddrFormatError -from netaddr.strategy import \ - valid_words as _valid_words, \ - int_to_words as _int_to_words, \ - words_to_int as _words_to_int, \ - valid_bits as _valid_bits, \ - bits_to_int as _bits_to_int, \ - int_to_bits as _int_to_bits, \ - valid_bin as _valid_bin, \ - int_to_bin as _int_to_bin, \ - bin_to_int as _bin_to_int -from netaddr.compat import _is_str - -#: The width (in bits) of this address type. -width = 48 - -#: The AF_* constant value of this address type. -family = AF_LINK - -#: A friendly string name address type. -family_name = 'MAC' - -#: The version of this address type. -version = 48 - -#: The maximum integer value that can be represented by this address type. -max_int = 2 ** width - 1 - -#----------------------------------------------------------------------------- -# Dialect classes. -#----------------------------------------------------------------------------- - -class mac_eui48(object): - """A standard IEEE EUI-48 dialect class.""" - #: The individual word size (in bits) of this address type. - word_size = 8 - - #: The number of words in this address type. - num_words = width // word_size - - #: The maximum integer value for an individual word in this address type. - max_word = 2 ** word_size - 1 - - #: The separator character used between each word. - word_sep = '-' - - #: The format string to be used when converting words to string values. - word_fmt = '%.2X' - - #: The number base to be used when interpreting word values as integers. - word_base = 16 - -class mac_unix(mac_eui48): - """A UNIX-style MAC address dialect class.""" - word_size = 8 - num_words = width // word_size - word_sep = ':' - word_fmt = '%x' - word_base = 16 - -class mac_unix_expanded(mac_unix): - """A UNIX-style MAC address dialect class with leading zeroes.""" - word_fmt = '%.2x' - -class mac_cisco(mac_eui48): - """A Cisco 'triple hextet' MAC address dialect class.""" - word_size = 16 - num_words = width // word_size - word_sep = '.' - word_fmt = '%.4x' - word_base = 16 - -class mac_bare(mac_eui48): - """A bare (no delimiters) MAC address dialect class.""" - word_size = 48 - num_words = width // word_size - word_sep = '' - word_fmt = '%.12X' - word_base = 16 - -class mac_pgsql(mac_eui48): - """A PostgreSQL style (2 x 24-bit words) MAC address dialect class.""" - word_size = 24 - num_words = width // word_size - word_sep = ':' - word_fmt = '%.6x' - word_base = 16 - -#: The default dialect to be used when not specified by the user. -DEFAULT_DIALECT = mac_eui48 - -#----------------------------------------------------------------------------- -#: Regular expressions to match all supported MAC address formats. -RE_MAC_FORMATS = ( - # 2 bytes x 6 (UNIX, Windows, EUI-48) - '^' + ':'.join(['([0-9A-F]{1,2})'] * 6) + '$', - '^' + '-'.join(['([0-9A-F]{1,2})'] * 6) + '$', - - # 4 bytes x 3 (Cisco) - '^' + ':'.join(['([0-9A-F]{1,4})'] * 3) + '$', - '^' + '-'.join(['([0-9A-F]{1,4})'] * 3) + '$', - '^' + '\.'.join(['([0-9A-F]{1,4})'] * 3) + '$', - - # 6 bytes x 2 (PostgreSQL) - '^' + '-'.join(['([0-9A-F]{5,6})'] * 2) + '$', - '^' + ':'.join(['([0-9A-F]{5,6})'] * 2) + '$', - - # 12 bytes (bare, no delimiters) - '^(' + ''.join(['[0-9A-F]'] * 12) + ')$', - '^(' + ''.join(['[0-9A-F]'] * 11) + ')$', -) -# For efficiency, each string regexp converted in place to its compiled -# counterpart. -RE_MAC_FORMATS = [_re.compile(_, _re.IGNORECASE) for _ in RE_MAC_FORMATS] - - -def valid_str(addr): - """ - :param addr: An IEEE EUI-48 (MAC) address in string form. - - :return: ``True`` if MAC address string is valid, ``False`` otherwise. - """ - for regexp in RE_MAC_FORMATS: - try: - match_result = regexp.findall(addr) - if len(match_result) != 0: - return True - except TypeError: - pass - - return False - - -def str_to_int(addr): - """ - :param addr: An IEEE EUI-48 (MAC) address in string form. - - :return: An unsigned integer that is equivalent to value represented - by EUI-48/MAC string address formatted according to the dialect - settings. - """ - words = [] - if _is_str(addr): - found_match = False - for regexp in RE_MAC_FORMATS: - match_result = regexp.findall(addr) - if len(match_result) != 0: - found_match = True - if isinstance(match_result[0], tuple): - words = match_result[0] - else: - words = (match_result[0],) - break - if not found_match: - raise AddrFormatError('%r is not a supported MAC format!' % addr) - else: - raise TypeError('%r is not str() or unicode()!' % addr) - - int_val = None - - if len(words) == 6: - # 2 bytes x 6 (UNIX, Windows, EUI-48) - int_val = int(''.join(['%.2x' % int(w, 16) for w in words]), 16) - elif len(words) == 3: - # 4 bytes x 3 (Cisco) - int_val = int(''.join(['%.4x' % int(w, 16) for w in words]), 16) - elif len(words) == 2: - # 6 bytes x 2 (PostgreSQL) - int_val = int(''.join(['%.6x' % int(w, 16) for w in words]), 16) - elif len(words) == 1: - # 12 bytes (bare, no delimiters) - int_val = int('%012x' % int(words[0], 16), 16) - else: - raise AddrFormatError('unexpected word count in MAC address %r!' \ - % addr) - - return int_val - - -def int_to_str(int_val, dialect=None): - """ - :param int_val: An unsigned integer. - - :param dialect: (optional) a Python class defining formatting options. - - :return: An IEEE EUI-48 (MAC) address string that is equivalent to - unsigned integer formatted according to the dialect settings. - """ - if dialect is None: - dialect = mac_eui48 - - words = int_to_words(int_val, dialect) - tokens = [dialect.word_fmt % i for i in words] - addr = dialect.word_sep.join(tokens) - - return addr - - -def int_to_packed(int_val): - """ - :param int_val: the integer to be packed. - - :return: a packed string that is equivalent to value represented by an - unsigned integer. - """ - return _struct.pack(">HI", int_val >> 32, int_val & 0xffffffff) - - -def packed_to_int(packed_int): - """ - :param packed_int: a packed string containing an unsigned integer. - It is assumed that string is packed in network byte order. - - :return: An unsigned integer equivalent to value of network address - represented by packed binary string. - """ - words = list(_struct.unpack('>6B', packed_int)) - - int_val = 0 - for i, num in enumerate(reversed(words)): - word = num - word = word << 8 * i - int_val = int_val | word - - return int_val - - -def valid_words(words, dialect=None): - if dialect is None: - dialect = DEFAULT_DIALECT - return _valid_words(words, dialect.word_size, dialect.num_words) - - -def int_to_words(int_val, dialect=None): - if dialect is None: - dialect = DEFAULT_DIALECT - return _int_to_words(int_val, dialect.word_size, dialect.num_words) - - -def words_to_int(words, dialect=None): - if dialect is None: - dialect = DEFAULT_DIALECT - return _words_to_int(words, dialect.word_size, dialect.num_words) - - -def valid_bits(bits, dialect=None): - if dialect is None: - dialect = DEFAULT_DIALECT - return _valid_bits(bits, width, dialect.word_sep) - - -def bits_to_int(bits, dialect=None): - if dialect is None: - dialect = DEFAULT_DIALECT - return _bits_to_int(bits, width, dialect.word_sep) - - -def int_to_bits(int_val, dialect=None): - if dialect is None: - dialect = DEFAULT_DIALECT - return _int_to_bits(int_val, dialect.word_size, dialect.num_words, - dialect.word_sep) - - -def valid_bin(bin_val, dialect=None): - if dialect is None: - dialect = DEFAULT_DIALECT - return _valid_bin(bin_val, width) - - -def int_to_bin(int_val): - return _int_to_bin(int_val, width) - - -def bin_to_int(bin_val): - return _bin_to_int(bin_val, width) diff --git a/awx/lib/site-packages/netaddr/strategy/eui64.py b/awx/lib/site-packages/netaddr/strategy/eui64.py deleted file mode 100644 index d3f1e785b1..0000000000 --- a/awx/lib/site-packages/netaddr/strategy/eui64.py +++ /dev/null @@ -1,193 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -IEEE 64-bit EUI (Extended Unique Indentifier) logic. -""" -import struct as _struct -import re as _re - -# This is a fake constant that doesn't really exist. Here for completeness. -AF_EUI64 = 64 - -from netaddr.core import AddrFormatError -from netaddr.compat import _is_str -from netaddr.strategy import \ - valid_words as _valid_words, \ - int_to_words as _int_to_words, \ - words_to_int as _words_to_int, \ - valid_bits as _valid_bits, \ - bits_to_int as _bits_to_int, \ - int_to_bits as _int_to_bits, \ - valid_bin as _valid_bin, \ - int_to_bin as _int_to_bin, \ - bin_to_int as _bin_to_int - -#: The width (in bits) of this address type. -width = 64 - -#: The individual word size (in bits) of this address type. -word_size = 8 - -#: The format string to be used when converting words to string values. -word_fmt = '%.2X' - -#: The separator character used between each word. -word_sep = '-' - -#: The AF_* constant value of this address type. -family = AF_EUI64 - -#: A friendly string name address type. -family_name = 'EUI-64' - -#: The version of this address type. -version = 64 - -#: The number base to be used when interpreting word values as integers. -word_base = 16 - -#: The maximum integer value that can be represented by this address type. -max_int = 2 ** width - 1 - -#: The number of words in this address type. -num_words = width // word_size - -#: The maximum integer value for an individual word in this address type. -max_word = 2 ** word_size - 1 - -#: Compiled regular expression for detecting value EUI-64 identifiers. -RE_EUI64_FORMATS = [ - _re.compile('^' + ':'.join(['([0-9A-F]{1,2})'] * 8) + '$', _re.IGNORECASE), - _re.compile('^' + '-'.join(['([0-9A-F]{1,2})'] * 8) + '$', _re.IGNORECASE), - _re.compile('^(' + '[0-9A-F]' * 16 + ')$', _re.IGNORECASE), -] - - -def _get_match_result(address, formats): - for regexp in formats: - match = regexp.findall(address) - if match: - return match[0] - -def valid_str(addr): - """ - :param addr: An IEEE EUI-64 indentifier in string form. - - :return: ``True`` if EUI-64 indentifier is valid, ``False`` otherwise. - """ - try: - if _get_match_result(addr, RE_EUI64_FORMATS): - return True - except TypeError: - pass - - return False - - -def str_to_int(addr): - """ - :param addr: An IEEE EUI-64 indentifier in string form. - - :return: An unsigned integer that is equivalent to value represented - by EUI-64 string identifier. - """ - words = [] - - try: - words = _get_match_result(addr, RE_EUI64_FORMATS) - if not words: - raise TypeError - except TypeError: - raise AddrFormatError('invalid IEEE EUI-64 identifier: %r!' % addr) - - if _is_str(words): - return int(words, 16) - if len(words) != num_words: - raise AddrFormatError('bad word count for EUI-64 identifier: %r!' \ - % addr) - - return int(''.join(['%.2x' % int(w, 16) for w in words]), 16) - - -def int_to_str(int_val, dialect=None): - """ - :param int_val: An unsigned integer. - - :param dialect: (optional) a Python class defining formatting options - (Please Note - not currently in use). - - :return: An IEEE EUI-64 identifier that is equivalent to unsigned integer. - """ - words = int_to_words(int_val) - tokens = [word_fmt % i for i in words] - addr = word_sep.join(tokens) - return addr - - -def int_to_packed(int_val): - """ - :param int_val: the integer to be packed. - - :return: a packed string that is equivalent to value represented by an - unsigned integer. - """ - words = int_to_words(int_val) - return _struct.pack('>8B', *words) - - -def packed_to_int(packed_int): - """ - :param packed_int: a packed string containing an unsigned integer. - It is assumed that string is packed in network byte order. - - :return: An unsigned integer equivalent to value of network address - represented by packed binary string. - """ - words = list(_struct.unpack('>8B', packed_int)) - - int_val = 0 - for i, num in enumerate(reversed(words)): - word = num - word = word << 8 * i - int_val = int_val | word - - return int_val - - -def valid_words(words, dialect=None): - return _valid_words(words, word_size, num_words) - - -def int_to_words(int_val, dialect=None): - return _int_to_words(int_val, word_size, num_words) - - -def words_to_int(words, dialect=None): - return _words_to_int(words, word_size, num_words) - - -def valid_bits(bits, dialect=None): - return _valid_bits(bits, width, word_sep) - - -def bits_to_int(bits, dialect=None): - return _bits_to_int(bits, width, word_sep) - - -def int_to_bits(int_val, dialect=None): - return _int_to_bits(int_val, word_size, num_words, word_sep) - - -def valid_bin(bin_val): - return _valid_bin(bin_val, width) - - -def int_to_bin(int_val): - return _int_to_bin(int_val, width) - - -def bin_to_int(bin_val): - return _bin_to_int(bin_val, width) diff --git a/awx/lib/site-packages/netaddr/strategy/ipv4.py b/awx/lib/site-packages/netaddr/strategy/ipv4.py deleted file mode 100644 index 504b907cc5..0000000000 --- a/awx/lib/site-packages/netaddr/strategy/ipv4.py +++ /dev/null @@ -1,283 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""IPv4 address logic.""" - -import sys as _sys -import struct as _struct - -from socket import inet_aton as _inet_aton -# Check whether we need to use fallback code or not. -if _sys.platform in ('win32', 'cygwin'): - # inet_pton() not available on Windows. inet_pton() under cygwin - # behaves exactly like inet_aton() and is therefore highly unreliable. - from netaddr.fbsocket import inet_pton as _inet_pton, AF_INET -else: - # All other cases, use all functions from the socket module. - from socket import inet_pton as _inet_pton, AF_INET - -from netaddr.core import AddrFormatError, ZEROFILL, INET_PTON - -from netaddr.strategy import valid_words as _valid_words, \ - valid_bits as _valid_bits, \ - bits_to_int as _bits_to_int, \ - int_to_bits as _int_to_bits, \ - valid_bin as _valid_bin, \ - int_to_bin as _int_to_bin, \ - bin_to_int as _bin_to_int - -from netaddr.compat import _str_type - -#: The width (in bits) of this address type. -width = 32 - -#: The individual word size (in bits) of this address type. -word_size = 8 - -#: The format string to be used when converting words to string values. -word_fmt = '%d' - -#: The separator character used between each word. -word_sep = '.' - -#: The AF_* constant value of this address type. -family = AF_INET - -#: A friendly string name address type. -family_name = 'IPv4' - -#: The version of this address type. -version = 4 - -#: The number base to be used when interpreting word values as integers. -word_base = 10 - -#: The maximum integer value that can be represented by this address type. -max_int = 2 ** width - 1 - -#: The number of words in this address type. -num_words = width // word_size - -#: The maximum integer value for an individual word in this address type. -max_word = 2 ** word_size - 1 - -#: A dictionary mapping IPv4 CIDR prefixes to the equivalent netmasks. -prefix_to_netmask = dict( - [(i, max_int ^ (2 ** (width - i) - 1)) for i in range(0, width+1)]) - -#: A dictionary mapping IPv4 netmasks to their equivalent CIDR prefixes. -netmask_to_prefix = dict( - [(max_int ^ (2 ** (width - i) - 1), i) for i in range(0, width+1)]) - -#: A dictionary mapping IPv4 CIDR prefixes to the equivalent hostmasks. -prefix_to_hostmask = dict( - [(i, (2 ** (width - i) - 1)) for i in range(0, width+1)]) - -#: A dictionary mapping IPv4 hostmasks to their equivalent CIDR prefixes. -hostmask_to_prefix = dict( - [((2 ** (width - i) - 1), i) for i in range(0, width+1)]) - - -def valid_str(addr, flags=0): - """ - :param addr: An IPv4 address in presentation (string) format. - - :param flags: decides which rules are applied to the interpretation of the - addr value. Supported constants are INET_PTON and ZEROFILL. See the - netaddr.core docs for details. - - :return: ``True`` if IPv4 address is valid, ``False`` otherwise. - """ - if addr == '': - raise AddrFormatError('Empty strings are not supported!') - - validity = True - - if flags & ZEROFILL: - addr = '.'.join(['%d' % int(i) for i in addr.split('.')]) - - try: - if flags & INET_PTON: - _inet_pton(AF_INET, addr) - else: - _inet_aton(addr) - except Exception: - validity = False - - return validity - - -def str_to_int(addr, flags=0): - """ - :param addr: An IPv4 dotted decimal address in string form. - - :param flags: decides which rules are applied to the interpretation of the - addr value. Supported constants are INET_PTON and ZEROFILL. See the - netaddr.core docs for details. - - :return: The equivalent unsigned integer for a given IPv4 address. - """ - if flags & ZEROFILL: - addr = '.'.join(['%d' % int(i) for i in addr.split('.')]) - - try: - if flags & INET_PTON: - return _struct.unpack('>I', _inet_pton(AF_INET, addr))[0] - else: - return _struct.unpack('>I', _inet_aton(addr))[0] - except Exception: - raise AddrFormatError('%r is not a valid IPv4 address string!' % addr) - - -def int_to_str(int_val, dialect=None): - """ - :param int_val: An unsigned integer. - - :param dialect: (unused) Any value passed in is ignored. - - :return: The IPv4 presentation (string) format address equivalent to the - unsigned integer provided. - """ - if 0 <= int_val <= max_int: - return '%d.%d.%d.%d' % ( - int_val >> 24, - (int_val >> 16) & 0xff, - (int_val >> 8) & 0xff, - int_val & 0xff) - else: - raise ValueError('%r is not a valid 32-bit unsigned integer!' \ - % int_val) - - -def int_to_arpa(int_val): - """ - :param int_val: An unsigned integer. - - :return: The reverse DNS lookup for an IPv4 address in network byte - order integer form. - """ - words = ["%d" % i for i in int_to_words(int_val)] - words.reverse() - words.extend(['in-addr', 'arpa', '']) - return '.'.join(words) - - -def int_to_packed(int_val): - """ - :param int_val: the integer to be packed. - - :return: a packed string that is equivalent to value represented by an - unsigned integer. - """ - return _struct.pack('>I', int_val) - - -def packed_to_int(packed_int): - """ - :param packed_int: a packed string containing an unsigned integer. - It is assumed that string is packed in network byte order. - - :return: An unsigned integer equivalent to value of network address - represented by packed binary string. - """ - return _struct.unpack('>I', packed_int)[0] - - -def valid_words(words): - return _valid_words(words, word_size, num_words) - - -def int_to_words(int_val): - """ - :param int_val: An unsigned integer. - - :return: An integer word (octet) sequence that is equivalent to value - represented by an unsigned integer. - """ - if not 0 <= int_val <= max_int: - raise ValueError('%r is not a valid integer value supported ' \ - 'by this address type!' % int_val) - return ( int_val >> 24, - (int_val >> 16) & 0xff, - (int_val >> 8) & 0xff, - int_val & 0xff) - - -def words_to_int(words): - """ - :param words: A list or tuple containing integer octets. - - :return: An unsigned integer that is equivalent to value represented - by word (octet) sequence. - """ - if not valid_words(words): - raise ValueError('%r is not a valid octet list for an IPv4 ' \ - 'address!' % words) - return _struct.unpack('>I', _struct.pack('4B', *words))[0] - - -def valid_bits(bits): - return _valid_bits(bits, width, word_sep) - - -def bits_to_int(bits): - return _bits_to_int(bits, width, word_sep) - - -def int_to_bits(int_val, word_sep=None): - if word_sep is None: - word_sep = globals()['word_sep'] - return _int_to_bits(int_val, word_size, num_words, word_sep) - - -def valid_bin(bin_val): - return _valid_bin(bin_val, width) - - -def int_to_bin(int_val): - return _int_to_bin(int_val, width) - - -def bin_to_int(bin_val): - return _bin_to_int(bin_val, width) - - -def expand_partial_address(addr): - """ - Expands a partial IPv4 address into a full 4-octet version. - - :param addr: an partial or abbreviated IPv4 address - - :return: an expanded IP address in presentation format (x.x.x.x) - - """ - tokens = [] - - error = AddrFormatError('invalid partial IPv4 address: %r!' % addr) - - if isinstance(addr, _str_type): - if ':' in addr: - # Ignore IPv6 ... - raise error - - try: - if '.' in addr: - tokens = ['%d' % int(o) for o in addr.split('.')] - else: - tokens = ['%d' % int(addr)] - except ValueError: - raise error - - if 1 <= len(tokens) <= 4: - for i in range(4 - len(tokens)): - tokens.append('0') - else: - raise error - - if not tokens: - raise error - - return '%s.%s.%s.%s' % tuple(tokens) - diff --git a/awx/lib/site-packages/netaddr/strategy/ipv6.py b/awx/lib/site-packages/netaddr/strategy/ipv6.py deleted file mode 100644 index fd3cb14984..0000000000 --- a/awx/lib/site-packages/netaddr/strategy/ipv6.py +++ /dev/null @@ -1,266 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -""" -IPv6 address logic. -""" -import struct as _struct - -OPT_IMPORTS = False - -# Check whether we need to use fallback code or not. -try: - import socket as _socket - # These might all generate exceptions on different platforms. - if not _socket.has_ipv6: - raise Exception('IPv6 disabled') - _socket.inet_pton - _socket.AF_INET6 - from _socket import inet_pton as _inet_pton, \ - inet_ntop as _inet_ntop, \ - AF_INET6 - OPT_IMPORTS = True -except Exception: - from netaddr.fbsocket import inet_pton as _inet_pton, \ - inet_ntop as _inet_ntop, \ - AF_INET6 - -from netaddr.core import AddrFormatError -from netaddr.strategy import \ - valid_words as _valid_words, \ - int_to_words as _int_to_words, \ - words_to_int as _words_to_int, \ - valid_bits as _valid_bits, \ - bits_to_int as _bits_to_int, \ - int_to_bits as _int_to_bits, \ - valid_bin as _valid_bin, \ - int_to_bin as _int_to_bin, \ - bin_to_int as _bin_to_int - -#: The width (in bits) of this address type. -width = 128 - -#: The individual word size (in bits) of this address type. -word_size = 16 - -#: The separator character used between each word. -word_sep = ':' - -#: The AF_* constant value of this address type. -family = AF_INET6 - -#: A friendly string name address type. -family_name = 'IPv6' - -#: The version of this address type. -version = 6 - -#: The number base to be used when interpreting word values as integers. -word_base = 16 - -#: The maximum integer value that can be represented by this address type. -max_int = 2 ** width - 1 - -#: The number of words in this address type. -num_words = width // word_size - -#: The maximum integer value for an individual word in this address type. -max_word = 2 ** word_size - 1 - -#: A dictionary mapping IPv6 CIDR prefixes to the equivalent netmasks. -prefix_to_netmask = dict( - [(i, max_int ^ (2 ** (width - i) - 1)) for i in range(0, width+1)]) - -#: A dictionary mapping IPv6 netmasks to their equivalent CIDR prefixes. -netmask_to_prefix = dict( - [(max_int ^ (2 ** (width - i) - 1), i) for i in range(0, width+1)]) - -#: A dictionary mapping IPv6 CIDR prefixes to the equivalent hostmasks. -prefix_to_hostmask = dict( - [(i, (2 ** (width - i) - 1)) for i in range(0, width+1)]) - -#: A dictionary mapping IPv6 hostmasks to their equivalent CIDR prefixes. -hostmask_to_prefix = dict( - [((2 ** (width - i) - 1), i) for i in range(0, width+1)]) - -#----------------------------------------------------------------------------- -# Dialect classes. -#----------------------------------------------------------------------------- - -class ipv6_compact(object): - """An IPv6 dialect class - compact form.""" - #: The format string used to converting words into string values. - word_fmt = '%x' - - #: Boolean flag indicating if IPv6 compaction algorithm should be used. - compact = True - -class ipv6_full(ipv6_compact): - """An IPv6 dialect class - 'all zeroes' form.""" - - #: Boolean flag indicating if IPv6 compaction algorithm should be used. - compact = False - -class ipv6_verbose(ipv6_compact): - """An IPv6 dialect class - extra wide 'all zeroes' form.""" - - #: The format string used to converting words into string values. - word_fmt = '%.4x' - - #: Boolean flag indicating if IPv6 compaction algorithm should be used. - compact = False - - -def valid_str(addr, flags=0): - """ - :param addr: An IPv6 address in presentation (string) format. - - :param flags: decides which rules are applied to the interpretation of the - addr value. Future use - currently has no effect. - - :return: ``True`` if IPv6 address is valid, ``False`` otherwise. - """ - if addr == '': - raise AddrFormatError('Empty strings are not supported!') - - try: - _inet_pton(AF_INET6, addr) - except: - return False - return True - - -def str_to_int(addr, flags=0): - """ - :param addr: An IPv6 address in string form. - - :param flags: decides which rules are applied to the interpretation of the - addr value. Future use - currently has no effect. - - :return: The equivalent unsigned integer for a given IPv6 address. - """ - try: - packed_int = _inet_pton(AF_INET6, addr) - return packed_to_int(packed_int) - except Exception: - raise AddrFormatError('%r is not a valid IPv6 address string!' % addr) - - -def int_to_str(int_val, dialect=None): - """ - :param int_val: An unsigned integer. - - :param dialect: (optional) a Python class defining formatting options. - - :return: The IPv6 presentation (string) format address equivalent to the - unsigned integer provided. - """ - if dialect is None: - dialect = ipv6_compact - - addr = None - - try: - packed_int = int_to_packed(int_val) - if dialect.compact: - # Default return value. - addr = _inet_ntop(AF_INET6, packed_int) - else: - # Custom return value. - words = list(_struct.unpack('>8H', packed_int)) - tokens = [dialect.word_fmt % word for word in words] - addr = word_sep.join(tokens) - except Exception: - raise ValueError('%r is not a valid 128-bit unsigned integer!' \ - % int_val) - - return addr - - -def int_to_arpa(int_val): - """ - :param int_val: An unsigned integer. - - :return: The reverse DNS lookup for an IPv6 address in network byte - order integer form. - """ - addr = int_to_str(int_val, ipv6_verbose) - tokens = list(addr.replace(':', '')) - tokens.reverse() - # We won't support ip6.int here - see RFC 3152 for details. - tokens = tokens + ['ip6', 'arpa', ''] - return '.'.join(tokens) - - -def int_to_packed(int_val): - """ - :param int_val: the integer to be packed. - - :return: a packed string that is equivalent to value represented by an - unsigned integer. - """ - words = int_to_words(int_val, 4, 32) - return _struct.pack('>4I', *words) - - -def packed_to_int(packed_int): - """ - :param packed_int: a packed string containing an unsigned integer. - It is assumed that string is packed in network byte order. - - :return: An unsigned integer equivalent to value of network address - represented by packed binary string. - """ - words = list(_struct.unpack('>4I', packed_int)) - - int_val = 0 - for i, num in enumerate(reversed(words)): - word = num - word = word << 32 * i - int_val = int_val | word - - return int_val - - -def valid_words(words): - return _valid_words(words, word_size, num_words) - - -def int_to_words(int_val, num_words=None, word_size=None): - if num_words is None: - num_words = globals()['num_words'] - if word_size is None: - word_size = globals()['word_size'] - return _int_to_words(int_val, word_size, num_words) - - -def words_to_int(words): - return _words_to_int(words, word_size, num_words) - - -def valid_bits(bits): - return _valid_bits(bits, width, word_sep) - - -def bits_to_int(bits): - return _bits_to_int(bits, width, word_sep) - - -def int_to_bits(int_val, word_sep=None): - if word_sep is None: - word_sep = globals()['word_sep'] - return _int_to_bits(int_val, word_size, num_words, word_sep) - - -def valid_bin(bin_val): - return _valid_bin(bin_val, width) - - -def int_to_bin(int_val): - return _int_to_bin(int_val, width) - - -def bin_to_int(bin_val): - return _bin_to_int(bin_val, width) diff --git a/awx/lib/site-packages/netaddr/tests/2.x/core/compat.txt b/awx/lib/site-packages/netaddr/tests/2.x/core/compat.txt deleted file mode 100644 index e2c19d1ed5..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/core/compat.txt +++ /dev/null @@ -1,107 +0,0 @@ -=Python 2.x and 3.x compatibility tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.compat import _sys_maxint, _is_str, _is_int, _callable - ->>> from netaddr.compat import _func_doc, _dict_keys, _dict_items - ->>> from netaddr.compat import _iter_dict_keys, _bytes_join, _zip, _range - ->>> from netaddr.compat import _iter_range, _func_name, _func_doc - -# string and integer detection tests. ->>> _is_int(_sys_maxint) -True - ->>> _is_str(_sys_maxint) -False - ->>> _is_str('') -True - ->>> _is_str(''.encode()) -True - ->>> _is_str(unicode('')) -True - -# Python 2.x - 8 bit strings are just regular strings ->>> str_8bit = _bytes_join(['a', 'b', 'c']) - ->>> str_8bit == 'abc'.encode() -True - ->>> "'abc'" == '%r' % str_8bit -True - -# dict operation tests. ->>> d = { 'a' : 0, 'b' : 1, 'c' : 2 } - ->>> sorted(_dict_keys(d)) == ['a', 'b', 'c'] -True - ->>> sorted(_dict_items(d)) == [('a', 0), ('b', 1), ('c', 2)] -True - -# zip() BIF tests. ->>> l2 = _zip([0], [1]) - ->>> hasattr(_zip(l2), 'pop') -True - ->>> l2 == [(0, 1)] -True - -# range/xrange() tests. ->>> l1 = _range(3) - ->>> isinstance(l1, list) -True - ->>> hasattr(l1, 'pop') -True - ->>> l1 == [0, 1, 2] -True - ->>> it = _iter_range(3) - ->>> isinstance(it, list) -False - ->>> hasattr(it, '__iter__') -True - ->>> it == [0, 1, 2] -False - ->>> list(it) == [0, 1, 2] -True - -# callable() and function meta-data tests. ->>> i = 1 ->>> def f1(): -... """docstring""" -... pass - ->>> f2 = lambda x: x - ->>> _callable(i) -False - ->>> _callable(f1) -True - ->>> _callable(f2) -True - ->>> _func_name(f1) == 'f1' -True - ->>> _func_doc(f1) == 'docstring' -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/core/pubsub.txt b/awx/lib/site-packages/netaddr/tests/2.x/core/pubsub.txt deleted file mode 100644 index 5f55c205ea..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/core/pubsub.txt +++ /dev/null @@ -1,48 +0,0 @@ -=Publish / Subscribe DP Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -Basic Publisher and Subscriber object tests. - -{{{ - ->>> from netaddr.core import Publisher, Subscriber, PrettyPrinter ->>> import pprint - ->>> class Subject(Publisher): -... pass - - ->>> class Observer(Subscriber): -... def __init__(self, id): -... self.id = id -... -... def update(self, data): -... return repr(self), pprint.pformat(data) -... -... def __repr__(self): -... return '%s(%r)' % (self.__class__.__name__, self.id) -... - ->>> s = Subject() - ->>> s.attach(Observer('foo')) ->>> s.attach(Observer('bar')) - -#FIXME: >>> pp = PrettyPrinter() -#FIXME: >>> s.attach(pp) - ->>> data = [{'foo': 42}, {'list': [1,'2', list(range(10))]}, {'strings': ['foo', 'bar', 'baz', 'quux']}] ->>> s.notify(data) - -#FIXME: >>> s.detach(pp) ->>> s.notify(['foo', 'bar', 'baz']) - ->>> s.attach('foo') -Traceback (most recent call last): -... -TypeError: 'foo' does not support required interface! - ->>> s.detach('foo') - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/eui/eui.txt b/awx/lib/site-packages/netaddr/tests/2.x/eui/eui.txt deleted file mode 100644 index bbf5d548de..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/eui/eui.txt +++ /dev/null @@ -1,402 +0,0 @@ -=IEEE EUI-64 Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -IEEE EUI-64 tests. - -{{{ - ->>> eui = EUI('00-1B-77-FF-FE-49-54-FD') ->>> eui -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> eui.oui -OUI('00-1B-77') - ->>> eui.ei -'FF-FE-49-54-FD' - ->>> eui.eui64() -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> mac = EUI('00-0F-1F-12-E7-33') ->>> ip = mac.ipv6_link_local() ->>> ip -IPAddress('fe80::20f:1fff:fe12:e733') ->>> ip.is_link_local() -True - ->>> mac.eui64() -EUI('00-0F-1F-FF-FE-12-E7-33') - -}}} - -Individual Address Block tests. - -{{{ - ->>> lower_eui = EUI('00-50-C2-05-C0-00') ->>> upper_eui = EUI('00-50-C2-05-CF-FF') - ->>> lower_eui.is_iab() -True - ->>> str(lower_eui.oui) -'00-50-C2' - ->>> str(lower_eui.iab) -'00-50-C2-05-C0-00' - ->>> lower_eui.ei -'05-C0-00' - ->>> int(lower_eui.oui) == 0x0050c2 -True - ->>> int(lower_eui.iab) == 0x0050c205c -True - ->>> upper_eui.is_iab() -True - ->>> str(upper_eui.oui) -'00-50-C2' - ->>> str(upper_eui.iab) -'00-50-C2-05-C0-00' - ->>> upper_eui.ei -'05-CF-FF' - ->>> int(upper_eui.oui) == 0x0050c2 -True - ->>> int(upper_eui.iab) == 0x0050c205c -True - -}}} - -Constructor tests. - -{{{ - ->>> eui = EUI('00-90-96-AF-CC-39') - ->>> eui == EUI('0-90-96-AF-CC-39') -True - ->>> eui == EUI('00-90-96-af-cc-39') -True - ->>> eui == EUI('00:90:96:AF:CC:39') -True - ->>> eui == EUI('00:90:96:af:cc:39') -True - ->>> eui == EUI('0090-96AF-CC39') -True - ->>> eui == EUI('0090:96af:cc39') -True - ->>> eui == EUI('009096-AFCC39') -True - ->>> eui == EUI('009096:AFCC39') -True - ->>> eui == EUI('009096AFCC39') -True - ->>> eui == EUI('009096afcc39') -True - ->>> EUI('01-00-00-00-00-00') == EUI('010000000000') -True - ->>> EUI('01-00-00-00-00-00') == EUI('10000000000') -True - ->>> EUI('01-00-00-01-00-00') == EUI('010000:010000') -True - ->>> EUI('01-00-00-01-00-00') == EUI('10000:10000') -True - -}}} - -EUI-48 and EUI-64 indentifiers of the same value are *not* equivalent. - -{{{ - ->>> eui48 = EUI('01-00-00-01-00-00') ->>> int(eui48) == 1099511693312 -True - ->>> eui64 = EUI('00-00-01-00-00-01-00-00') ->>> int(eui64) == 1099511693312 -True - ->>> eui48 == eui64 -False - -}}} - -Comparison of EUIs must support subclassing - -{{{ ->>> eui = EUI(42) ->>> class MySubclass(EUI): pass ->>> my_instance = MySubclass(42) ->>> my_instance2 = MySubclass(43) ->>> class YourSubclass(EUI): pass ->>> your_instance = YourSubclass(42) ->>> your_instance2 = YourSubclass(43) - ->>> eui == my_instance -True - ->>> eui != my_instance -False - ->>> eui == my_instance2 -False - ->>> eui != my_instance2 -True - ->>> my_instance != your_instance -False - ->>> my_instance == your_instance -True - ->>> my_instance == your_instance2 -False - ->>> my_instance != your_instance2 -True - ->>> my_instance < your_instance2 -True - ->>> my_instance2 > your_instance -True - ->>> my_instance <= your_instance2 -True - ->>> my_instance2 >= your_instance -True - -}}} - -Equality check for OUI must support subclassing - -{{{ ->>> oui = OUI('00-1B-77') ->>> class MySubclass(OUI): pass ->>> my_instance = MySubclass('00-1B-77') ->>> my_instance2 = MySubclass('00-1B-78') ->>> class YourSubclass(OUI): pass ->>> your_instance = YourSubclass('00-1B-77') ->>> your_instance2 = YourSubclass('00-1B-78') - ->>> oui == my_instance -True - ->>> oui != my_instance -False - ->>> oui == my_instance2 -False - ->>> oui != my_instance2 -True - ->>> my_instance != your_instance -False - ->>> my_instance == your_instance -True - ->>> my_instance == your_instance2 -False - ->>> my_instance != your_instance2 -True - -}}} - -Equality check for IAB must support subclassing - -{{{ ->>> iab = IAB('00-50-C2-00-00-00') ->>> class MySubclass(IAB): pass ->>> my_instance = MySubclass('00-50-C2-00-00-00') ->>> my_instance2 = MySubclass('00-50-C2-99-00-00') ->>> class YourSubclass(IAB): pass ->>> your_instance = YourSubclass('00-50-C2-00-00-00') ->>> your_instance2 = YourSubclass('00-50-C2-99-00-00') - ->>> iab == my_instance -True - ->>> iab != my_instance -False - ->>> iab == my_instance2 -False - ->>> iab != my_instance2 -True - ->>> my_instance != your_instance -False - ->>> my_instance == your_instance -True - ->>> my_instance == your_instance2 -False - ->>> my_instance != your_instance2 -True - -}}} - -Comparison between EUI objects and their textual representations - -{{{ - ->>> eui = EUI('11-22-33-44-55-66') ->>> class MySubclass(EUI): pass ->>> my_instance = MySubclass('11-22-33-44-55-66') - ->>> eui == '11-22-33-44-55-66' -True - ->>> my_instance == '11-22-33-44-55-66' -True - ->>> my_instance == '99-22-33-44-55-66' -False - ->>> '11-22-33-44-55-66' >= my_instance -True - ->>> my_instance > '11-22-33-44-55-00' -True - ->>> my_instance < '11-22-33-44-55-00' -False - ->>> my_instance <= '11-22-33-44-55-00' -False - ->>> my_instance >= '11-22-33-44-55-00' -True - -}}} - -Check equality between OUI objects and their textual representations - -{{{ - ->>> oui = OUI('00-1B-77') ->>> class MySubclass(OUI): pass ->>> my_instance = MySubclass('00-1B-77') - ->>> oui == '00-1B-77' -True - ->>> my_instance == '00-1B-77' -True - ->>> my_instance == '00-1B-99' -False - -}}} - -Check equality between IAB objects and their textual representations - -{{{ - ->>> eui = IAB('00-50-C2-00-00-00') ->>> class MySubclass(IAB): pass ->>> my_instance = MySubclass('00-50-C2-00-00-00') - ->>> eui == '00-50-C2-00-00-00' -True - ->>> my_instance == '00-50-C2-00-00-00' -True - ->>> my_instance == '00-50-C2-99-00-00' -False - -}}} - -Sortability - -{{{ - ->>> import random - ->>> eui_list = [EUI(0, 64), EUI(0), EUI(0xffffffffffff, dialect=mac_unix), EUI(0x1000000000000)] - ->>> random.shuffle(eui_list) - ->>> eui_list.sort() - ->>> for eui in eui_list: -... str(eui), eui.version -('00-00-00-00-00-00', 48) -('ff:ff:ff:ff:ff:ff', 48) -('00-00-00-00-00-00-00-00', 64) -('00-01-00-00-00-00-00-00', 64) - -}}} - -Persistence - -{{{ - ->>> import pickle - ->>> eui1 = EUI('00-00-00-01-02-03') ->>> eui2 = pickle.loads(pickle.dumps(eui1)) ->>> eui1 == eui2 -True - ->>> eui1 = EUI('00-00-00-01-02-03', dialect=mac_cisco) ->>> eui2 = pickle.loads(pickle.dumps(eui1)) ->>> eui1 == eui2 -True - ->>> eui1.dialect == eui2.dialect -True - ->>> oui1 = EUI('00-00-00-01-02-03').oui ->>> oui2 = pickle.loads(pickle.dumps(oui1)) ->>> oui1 == oui2 -True ->>> oui1.records == oui2.records -True - ->>> iab1 = EUI('00-50-C2-00-1F-FF').iab ->>> iab2 = pickle.loads(pickle.dumps(iab1)) ->>> iab1 == iab2 -True ->>> iab1.record == iab2.record -True - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/2.x/eui/eui64.txt b/awx/lib/site-packages/netaddr/tests/2.x/eui/eui64.txt deleted file mode 100644 index ce8d3a9f9d..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/eui/eui64.txt +++ /dev/null @@ -1,75 +0,0 @@ -=IEEE EUI-64 Identifier Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Basic operations. - -{{{ - ->>> mac = EUI('00-1B-77-49-54-FD') ->>> mac -EUI('00-1B-77-49-54-FD') - ->>> eui = mac.eui64() ->>> eui -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> eui.eui64() -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> int(eui) == 7731765737772285 -True - ->>> eui.packed -'\x00\x1bw\xff\xfeIT\xfd' - ->>> eui.bin -'0b11011011101111111111111111110010010010101010011111101' - ->>> eui.bits() -'00000000-00011011-01110111-11111111-11111110-01001001-01010100-11111101' - -}}} - -IPv6 interoperability - -{{{ - ->>> mac = EUI('00-1B-77-49-54-FD') - ->>> eui = mac.eui64() - ->>> mac -EUI('00-1B-77-49-54-FD') - ->>> eui -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> mac.modified_eui64() -EUI('02-1B-77-FF-FE-49-54-FD') - ->>> mac.ipv6_link_local() -IPAddress('fe80::21b:77ff:fe49:54fd') - ->>> eui.ipv6_link_local() -IPAddress('fe80::21b:77ff:fe49:54fd') - ->>> mac.ipv6(0x12340000000000000000000000000000) -IPAddress('1234::21b:77ff:fe49:54fd') - ->>> eui.ipv6(0x12340000000000000000000000000000) -IPAddress('1234::21b:77ff:fe49:54fd') - ->>> addr_colonned = EUI('00:1B:77:49:54:FD:BB:34') ->>> addr_colonned -EUI('00-1B-77-49-54-FD-BB-34') - ->>> addr_no_delimeter = EUI('001B774954FDBB34') ->>> addr_no_delimeter -EUI('00-1B-77-49-54-FD-BB-34') diff --git a/awx/lib/site-packages/netaddr/tests/2.x/eui/pubsub.txt b/awx/lib/site-packages/netaddr/tests/2.x/eui/pubsub.txt deleted file mode 100644 index c02ee1399a..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/eui/pubsub.txt +++ /dev/null @@ -1,52 +0,0 @@ -=IEEE Publish/Subscribe Parser Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -Basic OUIIndexParser and FileIndexer object tests. - -{{{ - ->>> from netaddr.eui.ieee import OUIIndexParser, IABIndexParser, FileIndexer ->>> from cStringIO import StringIO - ->>> infile = StringIO() ->>> outfile = StringIO() ->>> infile.write(""" -... 00-CA-FE (hex) ACME CORPORATION -... 00CAFE (base 16) ACME CORPORATION -... 1 MAIN STREET -... SPRINGFIELD -... UNITED STATES -... """) - ->>> infile.seek(0) ->>> iab_parser = OUIIndexParser(infile) ->>> iab_parser.attach(FileIndexer(outfile)) ->>> iab_parser.parse() ->>> print outfile.getvalue(), -51966,1,210 - -}}} - -Basic IABIndexParser and FileIndexer object tests. - -{{{ - ->>> infile = StringIO() ->>> outfile = StringIO() ->>> infile.write(""" -... 00-50-C2 (hex) ACME CORPORATION -... ABC000-ABCFFF (base 16) ACME CORPORATION -... 1 MAIN STREET -... SPRINGFIELD -... UNITED STATES -... """) - ->>> infile.seek(0) ->>> iab_parser = IABIndexParser(infile) ->>> iab_parser.attach(FileIndexer(outfile)) ->>> iab_parser.parse() ->>> print outfile.getvalue(), -84683452,1,181 - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/eui/tutorial.txt b/awx/lib/site-packages/netaddr/tests/2.x/eui/tutorial.txt deleted file mode 100644 index 2688029d78..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/eui/tutorial.txt +++ /dev/null @@ -1,191 +0,0 @@ -First of all you need to pull the various MAC related classes and functions into your namespace. - -.. note:: Do this for the purpose of this tutorial only. In your own code, you should be explicit about the classes, functions and constants you import to avoid name clashes. - ->>> from netaddr import * - -You can reasonably safely import everything from the netaddr namespace as care has been taken to only export the necessary classes, functions and constants. - -Always hand pick your imports if you are unsure about possible name clashes. - ----------------- -Basic operations ----------------- - -Instances of the EUI class are used to represent MAC addresses. - ->>> mac = EUI('00-1B-77-49-54-FD') - -Standard repr() access returns a Python statement that can reconstruct the MAC address object from scratch if executed in the Python interpreter. - ->>> mac -EUI('00-1B-77-49-54-FD') - -Accessing the EUI object in the string context. - ->>> str(mac) -'00-1B-77-49-54-FD' ->>> '%s' % mac -'00-1B-77-49-54-FD' - -Here are a few other common properties. - ->>> str(mac), str(mac.oui), mac.ei, mac.version -('00-1B-77-49-54-FD', '00-1B-77', '49-54-FD', 48) - -------------------------- -Numerical representations -------------------------- - -You can view an individual IP address in various other formats. - ->>> int(mac) == 117965411581 -True ->>> hex(mac) -'0x1b774954fd' ->>> oct(mac) -'01556722252375' ->>> mac.bits() -'00000000-00011011-01110111-01001001-01010100-11111101' ->>> mac.bin -'0b1101101110111010010010101010011111101' - ----------- -Formatting ----------- - -It is very common to see MAC address in many different formats other than the standard IEEE EUI-48. - -The EUI class constructor handles all these common forms. - ->>> EUI('00-1B-77-49-54-FD') -EUI('00-1B-77-49-54-FD') - -IEEE EUI-48 lowercase format - ->>> EUI('00-1b-77-49-54-fd') -EUI('00-1B-77-49-54-FD') - -Common UNIX format - ->>> EUI('0:1b:77:49:54:fd') -EUI('00-1B-77-49-54-FD') - -Cisco triple hextet format - ->>> EUI('001b:7749:54fd') -EUI('00-1B-77-49-54-FD') ->>> EUI('1b:7749:54fd') -EUI('00-1B-77-49-54-FD') ->>> EUI('1B:7749:54FD') -EUI('00-1B-77-49-54-FD') - -Bare MAC addresses (no delimiters) - ->>> EUI('001b774954fd') -EUI('00-1B-77-49-54-FD') ->>> EUI('01B774954FD') -EUI('00-1B-77-49-54-FD') - -PostreSQL format (found in documentation) - ->>> EUI('001B77:4954FD') -EUI('00-1B-77-49-54-FD') - -It is equally possible to specify a selected format for your MAC string output in the form of a 'dialect' class. Its use is similar to the dialect class used in the Python standard library csv module. - ->>> mac = EUI('00-1B-77-49-54-FD') ->>> mac -EUI('00-1B-77-49-54-FD') ->>> mac.dialect = mac_unix ->>> mac -EUI('0:1b:77:49:54:fd') ->>> mac.dialect = mac_unix_expanded ->>> mac -EUI('00:1b:77:49:54:fd') ->>> mac.dialect = mac_cisco ->>> mac -EUI('001b.7749.54fd') ->>> mac.dialect = mac_bare ->>> mac -EUI('001B774954FD') ->>> mac.dialect = mac_pgsql ->>> mac -EUI('001b77:4954fd') - -You can, of course, create your own dialect classes to customise the MAC formatting if the standard ones do not suit your needs. - -Here's a tweaked UNIX MAC dialect that generates uppercase, zero-filled octets. - ->>> class mac_custom(mac_unix): pass ->>> mac_custom.word_fmt = '%.2X' ->>> mac = EUI('00-1B-77-49-54-FD', dialect=mac_custom) ->>> mac -EUI('00:1B:77:49:54:FD') - ------------------------------------ -Querying organisational information ------------------------------------ - -EUI objects provide an interface to the OUI (Organisationally Unique Identifier) and IAB (Individual Address Block) registration databases available from the IEEE. - -Here is how you query an OUI with the EUI interface. - ->>> mac = EUI('00-1B-77-49-54-FD') ->>> oui = mac.oui ->>> oui -OUI('00-1B-77') ->>> oui.registration().address -['Lot 8, Jalan Hi-Tech 2/3', 'Kulim Hi-Tech Park', 'Kulim Kedah 09000', 'MALAYSIA'] ->>> oui.registration().org -'Intel Corporate' - -You can also use OUI objects directly without going through the EUI interface. - -A few OUI records have multiple registrations against them. I'm not sure if this is recording historical information or just a quirk of the IEEE reigstration process. - -This example shows you how you access them individually by specifying an index number. - ->>> oui = OUI(524336) # OUI constructor accepts integer values, too. ->>> oui -OUI('08-00-30') ->>> oui.registration(0).address -['2380 N. ROSE AVENUE', 'OXNARD CA 93010', 'UNITED STATES'] ->>> oui.registration(0).org -'NETWORK RESEARCH CORPORATION' ->>> oui.registration(0).oui -'08-00-30' ->>> oui.registration(1).address -['CH-1211 GENEVE 23', 'SUISSE/SWITZ', 'SWITZERLAND'] ->>> oui.registration(1).org -'CERN' ->>> oui.registration(1).oui -'08-00-30' ->>> oui.registration(2).address -['GPO BOX 2476V', 'MELBOURNE VIC 3001', 'AUSTRALIA'] ->>> oui.registration(2).org -'ROYAL MELBOURNE INST OF TECH' ->>> oui.registration(2).oui -'08-00-30' ->>> for i in range(oui.reg_count): -... str(oui), oui.registration(i).org -... -('08-00-30', 'NETWORK RESEARCH CORPORATION') -('08-00-30', 'CERN') -('08-00-30', 'ROYAL MELBOURNE INST OF TECH') - -Here is how you query an IAB with the EUI interface. - ->>> mac = EUI('00-50-C2-00-0F-01') ->>> mac.is_iab() -True ->>> iab = mac.iab ->>> iab -IAB('00-50-C2-00-00-00') ->>> iab.registration() -{'address': ['1241 Superieor Ave E', 'Cleveland OH 44114', 'UNITED STATES'], - 'iab': '00-50-C2-00-00-00', - ... - 'offset': 123, - 'org': 'T.L.S. Corp.', - 'size': 139} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/abbreviated.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/abbreviated.txt deleted file mode 100644 index b23a5f9fd6..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/abbreviated.txt +++ /dev/null @@ -1,202 +0,0 @@ -=Abbreviated CIDR Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Abbreviation tests. - -{{{ - ->>> ranges = ( -... (IPAddress('::'), IPAddress('::')), -... (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), -... (IPAddress('::'), IPAddress('::255.255.255.255')), -... (IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), -... ) - ->>> sorted(ranges) -[(IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), (IPAddress('::'), IPAddress('::')), (IPAddress('::'), IPAddress('::255.255.255.255'))] - -# Integer values. ->>> cidr_abbrev_to_verbose(-1) --1 - -# Class A ->>> cidr_abbrev_to_verbose(0) -'0.0.0.0/8' ->>> cidr_abbrev_to_verbose(10) -'10.0.0.0/8' ->>> cidr_abbrev_to_verbose(127) -'127.0.0.0/8' - -# Class B ->>> cidr_abbrev_to_verbose(128) -'128.0.0.0/16' ->>> cidr_abbrev_to_verbose(191) -'191.0.0.0/16' - -# Class C ->>> cidr_abbrev_to_verbose(192) -'192.0.0.0/24' ->>> cidr_abbrev_to_verbose(223) -'223.0.0.0/24' - -# Class D (multicast) ->>> cidr_abbrev_to_verbose(224) -'224.0.0.0/4' ->>> cidr_abbrev_to_verbose(225) -'225.0.0.0/4' ->>> cidr_abbrev_to_verbose(239) -'239.0.0.0/4' - -# Class E (reserved) ->>> cidr_abbrev_to_verbose(240) -'240.0.0.0/32' ->>> cidr_abbrev_to_verbose(254) -'254.0.0.0/32' ->>> cidr_abbrev_to_verbose(255) -'255.0.0.0/32' ->>> cidr_abbrev_to_verbose(256) -256 - -# String values. ->>> cidr_abbrev_to_verbose('-1') -'-1' - -# Class A ->>> cidr_abbrev_to_verbose('0') -'0.0.0.0/8' ->>> cidr_abbrev_to_verbose('10') -'10.0.0.0/8' ->>> cidr_abbrev_to_verbose('127') -'127.0.0.0/8' - -# Class B ->>> cidr_abbrev_to_verbose('128') -'128.0.0.0/16' ->>> cidr_abbrev_to_verbose('191') -'191.0.0.0/16' - -# Class C ->>> cidr_abbrev_to_verbose('192') -'192.0.0.0/24' ->>> cidr_abbrev_to_verbose('223') -'223.0.0.0/24' - -# Class D (multicast) ->>> cidr_abbrev_to_verbose('224') -'224.0.0.0/4' ->>> cidr_abbrev_to_verbose('225') -'225.0.0.0/4' ->>> cidr_abbrev_to_verbose('239') -'239.0.0.0/4' - -# Class E (reserved) ->>> cidr_abbrev_to_verbose('240') -'240.0.0.0/32' ->>> cidr_abbrev_to_verbose('254') -'254.0.0.0/32' ->>> cidr_abbrev_to_verbose('255') -'255.0.0.0/32' ->>> cidr_abbrev_to_verbose('256') -'256' - ->>> cidr_abbrev_to_verbose('128/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('128.0/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('128.0.0.0/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('128.0.0/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('192.168') -'192.168.0.0/24' ->>> cidr_abbrev_to_verbose('192.0.2') -'192.0.2.0/24' ->>> cidr_abbrev_to_verbose('192.0.2.0') -'192.0.2.0/24' ->>> cidr_abbrev_to_verbose('0.0.0.0') -'0.0.0.0/8' - -# No IPv6 support current. ->>> cidr_abbrev_to_verbose('::/128') -'::/128' - -# IPv6 proper, not IPv4 mapped? ->>> cidr_abbrev_to_verbose('::10/128') -'::10/128' ->>> cidr_abbrev_to_verbose('0.0.0.0.0') -'0.0.0.0.0' ->>> cidr_abbrev_to_verbose('') -'' ->>> cidr_abbrev_to_verbose(None) - ->>> cidr_abbrev_to_verbose([]) -[] ->>> cidr_abbrev_to_verbose({}) -{} - -}}} - -Negative testing. - -{{{ - ->>> cidr_abbrev_to_verbose('192.0.2.0') -'192.0.2.0/24' - ->>> cidr_abbrev_to_verbose('192.0.2.0/32') -'192.0.2.0/32' - -#FIXME: >>> cidr_abbrev_to_verbose('192.0.2.0/33') -Traceback (most recent call last): -... -ValueError: prefixlen in address '192.0.2.0/33' out of range for IPv4! - -}}} - -IPv4 octet expansion routine. - -{{{ - ->>> from netaddr.strategy import ipv4 - ->>> ipv4.expand_partial_address('10') -'10.0.0.0' - ->>> ipv4.expand_partial_address('10.1') -'10.1.0.0' - ->>> ipv4.expand_partial_address('192.168.1') -'192.168.1.0' - -}}} - -IPNetwork constructor testing. - -{{{ - ->>> IPNetwork('192.168/16') -IPNetwork('192.168.0.0/16') - ->>> IPNetwork('192.168.0.15') -IPNetwork('192.168.0.15/32') - ->>> IPNetwork('192.168') -IPNetwork('192.168.0.0/32') - ->>> IPNetwork('192.168', implicit_prefix=True) -IPNetwork('192.168.0.0/24') - ->>> IPNetwork('192.168', True) -IPNetwork('192.168.0.0/24') - ->>> IPNetwork('10.0.0.1', True) -IPNetwork('10.0.0.1/8') - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/binops.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/binops.txt deleted file mode 100644 index 661c0effa7..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/binops.txt +++ /dev/null @@ -1,67 +0,0 @@ -=Binary and numerical operations on IP addresses= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -==Addition and Subtraction == - -{{{ - ->>> IPAddress('192.0.2.0') + 1 -IPAddress('192.0.2.1') - ->>> 1 + IPAddress('192.0.2.0') -IPAddress('192.0.2.1') - ->>> IPAddress('192.0.2.1') - 1 -IPAddress('192.0.2.0') - ->>> IPAddress('192.0.0.0') + IPAddress('0.0.0.42') -IPAddress('192.0.0.42') - ->>> IPAddress('192.0.0.42') - IPAddress('0.0.0.42') -IPAddress('192.0.0.0') - ->>> 1 - IPAddress('192.0.2.1') -Traceback (most recent call last): -... -IndexError: result outside valid IP address boundary! - ->>> ip = IPAddress('10.0.0.1') ->>> ip += 1 ->>> ip -IPAddress('10.0.0.2') ->>> ip -= 1 ->>> ip -IPAddress('10.0.0.1') ->>> ip += IPAddress('0.0.0.42') ->>> ip -IPAddress('10.0.0.43') ->>> ip -= IPAddress('0.0.0.43') ->>> ip -IPAddress('10.0.0.0') - -}}} - -==Binary operations== - -{{{ - ->>> IPAddress('192.0.2.15') & IPAddress('255.255.255.0') -IPAddress('192.0.2.0') - ->>> IPAddress('255.255.0.0') | IPAddress('0.0.255.255') -IPAddress('255.255.255.255') - ->>> IPAddress('255.255.0.0') ^ IPAddress('255.0.0.0') -IPAddress('0.255.0.0') - ->>> IPAddress('1.2.3.4').packed -'\x01\x02\x03\x04' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/boundaries.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/boundaries.txt deleted file mode 100644 index 5bbe265680..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/boundaries.txt +++ /dev/null @@ -1,170 +0,0 @@ -=IP Range Boundary Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * ->>> import pprint - -}}} - -`iter_iprange()` iterator boundary tests. - -{{{ - ->>> pprint.pprint(list(iter_iprange('192.0.2.0', '192.0.2.7'))) -[IPAddress('192.0.2.0'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6'), - IPAddress('192.0.2.7')] - ->>> pprint.pprint(list(iter_iprange('::ffff:192.0.2.0', '::ffff:192.0.2.7'))) -[IPAddress('::ffff:192.0.2.0'), - IPAddress('::ffff:192.0.2.1'), - IPAddress('::ffff:192.0.2.2'), - IPAddress('::ffff:192.0.2.3'), - IPAddress('::ffff:192.0.2.4'), - IPAddress('::ffff:192.0.2.5'), - IPAddress('::ffff:192.0.2.6'), - IPAddress('::ffff:192.0.2.7')] - - -}}} - -`IPNetwork()` iterator boundary tests. - -{{{ - ->>> pprint.pprint(list(IPNetwork('192.0.2.0/29')[0:-1])) -[IPAddress('192.0.2.0'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6')] - ->>> pprint.pprint(list(IPNetwork('192.0.2.0/29')[::-1])) -[IPAddress('192.0.2.7'), - IPAddress('192.0.2.6'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.0')] - -For IPv4, network (first) and broadcast (last) address must be skipped. ->>> pprint.pprint(list(IPNetwork('192.0.2.0/29').iter_hosts())) -[IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6')] - -For IPv6, Subnet-Router anycast address (first) must be skipped. ->>> pprint.pprint(list(IPNetwork('::ffff:192.0.2.0/125').iter_hosts())) -[IPAddress('::ffff:192.0.2.1'), - IPAddress('::ffff:192.0.2.2'), - IPAddress('::ffff:192.0.2.3'), - IPAddress('::ffff:192.0.2.4'), - IPAddress('::ffff:192.0.2.5'), - IPAddress('::ffff:192.0.2.6'), - IPAddress('::ffff:192.0.2.7')] - -Very small IPNetworks do contain some IP addresses ->>> list(IPNetwork("192.168.0.0/31")) -[IPAddress('192.168.0.0'), IPAddress('192.168.0.1')] ->>> list(IPNetwork("1234::/128")) -[IPAddress('1234::')] - -But they have no IPs that can be assigned to hosts. ->>> list(IPNetwork("1234::/128").iter_hosts()) -[] ->>> list(IPNetwork("192.168.0.0/31").iter_hosts()) -[] - -}}} - -`IPRange()` iterator boundary tests. - -{{{ - ->>> pprint.pprint(list(IPRange('192.0.2.0', '192.0.2.7'))) -[IPAddress('192.0.2.0'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6'), - IPAddress('192.0.2.7')] - ->>> pprint.pprint(list(IPRange('::ffff:192.0.2.0', '::ffff:192.0.2.7'))) -[IPAddress('::ffff:192.0.2.0'), - IPAddress('::ffff:192.0.2.1'), - IPAddress('::ffff:192.0.2.2'), - IPAddress('::ffff:192.0.2.3'), - IPAddress('::ffff:192.0.2.4'), - IPAddress('::ffff:192.0.2.5'), - IPAddress('::ffff:192.0.2.6'), - IPAddress('::ffff:192.0.2.7')] - -}}} - -Boolean contexts. - -{{{ - ->>> bool(IPAddress('0.0.0.0')) -False - ->>> bool(IPAddress('0.0.0.1')) -True - ->>> bool(IPAddress('255.255.255.255')) -True - ->>> bool(IPNetwork('0.0.0.0/0')) -True - ->>> bool(IPNetwork('::/0')) -True - ->>> bool(IPRange('0.0.0.0', '255.255.255.255')) -True - ->>> bool(IPRange('0.0.0.0', '0.0.0.0')) -True - ->>> bool(IPGlob('*.*.*.*')) -True - ->>> bool(IPGlob('0.0.0.0')) -True - -}}} - -`IPAddress()` negative increment tests. - -{{{ - ->>> ip = IPAddress('0.0.0.0') ->>> ip += -1 -Traceback (most recent call last): -... -IndexError: result outside valid IP address boundary! - ->>> ip = IPAddress('255.255.255.255') ->>> ip -= -1 -Traceback (most recent call last): -... -IndexError: result outside valid IP address boundary! - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/cidr.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/cidr.txt deleted file mode 100644 index c8eb0f3282..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/cidr.txt +++ /dev/null @@ -1,449 +0,0 @@ -=CIDR Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -==Basic IP Range Tuple Sorting== - -{{{ - ->>> ranges = ( -... (IPAddress('::'), IPAddress('::')), -... (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), -... (IPAddress('::'), IPAddress('::255.255.255.255')), -... (IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), -... ) - ->>> sorted(ranges) -[(IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), (IPAddress('::'), IPAddress('::')), (IPAddress('::'), IPAddress('::255.255.255.255'))] - -}}} - -Worst case IPv4 range to CIDR conversion. - -{{{ - ->>> for ip in iprange_to_cidrs('0.0.0.1', '255.255.255.254'): -... ip -... -IPNetwork('0.0.0.1/32') -IPNetwork('0.0.0.2/31') -IPNetwork('0.0.0.4/30') -IPNetwork('0.0.0.8/29') -IPNetwork('0.0.0.16/28') -IPNetwork('0.0.0.32/27') -IPNetwork('0.0.0.64/26') -IPNetwork('0.0.0.128/25') -IPNetwork('0.0.1.0/24') -IPNetwork('0.0.2.0/23') -IPNetwork('0.0.4.0/22') -IPNetwork('0.0.8.0/21') -IPNetwork('0.0.16.0/20') -IPNetwork('0.0.32.0/19') -IPNetwork('0.0.64.0/18') -IPNetwork('0.0.128.0/17') -IPNetwork('0.1.0.0/16') -IPNetwork('0.2.0.0/15') -IPNetwork('0.4.0.0/14') -IPNetwork('0.8.0.0/13') -IPNetwork('0.16.0.0/12') -IPNetwork('0.32.0.0/11') -IPNetwork('0.64.0.0/10') -IPNetwork('0.128.0.0/9') -IPNetwork('1.0.0.0/8') -IPNetwork('2.0.0.0/7') -IPNetwork('4.0.0.0/6') -IPNetwork('8.0.0.0/5') -IPNetwork('16.0.0.0/4') -IPNetwork('32.0.0.0/3') -IPNetwork('64.0.0.0/2') -IPNetwork('128.0.0.0/2') -IPNetwork('192.0.0.0/3') -IPNetwork('224.0.0.0/4') -IPNetwork('240.0.0.0/5') -IPNetwork('248.0.0.0/6') -IPNetwork('252.0.0.0/7') -IPNetwork('254.0.0.0/8') -IPNetwork('255.0.0.0/9') -IPNetwork('255.128.0.0/10') -IPNetwork('255.192.0.0/11') -IPNetwork('255.224.0.0/12') -IPNetwork('255.240.0.0/13') -IPNetwork('255.248.0.0/14') -IPNetwork('255.252.0.0/15') -IPNetwork('255.254.0.0/16') -IPNetwork('255.255.0.0/17') -IPNetwork('255.255.128.0/18') -IPNetwork('255.255.192.0/19') -IPNetwork('255.255.224.0/20') -IPNetwork('255.255.240.0/21') -IPNetwork('255.255.248.0/22') -IPNetwork('255.255.252.0/23') -IPNetwork('255.255.254.0/24') -IPNetwork('255.255.255.0/25') -IPNetwork('255.255.255.128/26') -IPNetwork('255.255.255.192/27') -IPNetwork('255.255.255.224/28') -IPNetwork('255.255.255.240/29') -IPNetwork('255.255.255.248/30') -IPNetwork('255.255.255.252/31') -IPNetwork('255.255.255.254/32') - -}}} - -Worst case IPv4 mapped IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::ffff:1', '::ffff:255.255.255.254'): -... ip -... -IPNetwork('::255.255.0.1/128') -IPNetwork('::255.255.0.2/127') -IPNetwork('::255.255.0.4/126') -IPNetwork('::255.255.0.8/125') -IPNetwork('::255.255.0.16/124') -IPNetwork('::255.255.0.32/123') -IPNetwork('::255.255.0.64/122') -IPNetwork('::255.255.0.128/121') -IPNetwork('::255.255.1.0/120') -IPNetwork('::255.255.2.0/119') -IPNetwork('::255.255.4.0/118') -IPNetwork('::255.255.8.0/117') -IPNetwork('::255.255.16.0/116') -IPNetwork('::255.255.32.0/115') -IPNetwork('::255.255.64.0/114') -IPNetwork('::255.255.128.0/113') -IPNetwork('::1:0:0/96') -IPNetwork('::2:0:0/95') -IPNetwork('::4:0:0/94') -IPNetwork('::8:0:0/93') -IPNetwork('::10:0:0/92') -IPNetwork('::20:0:0/91') -IPNetwork('::40:0:0/90') -IPNetwork('::80:0:0/89') -IPNetwork('::100:0:0/88') -IPNetwork('::200:0:0/87') -IPNetwork('::400:0:0/86') -IPNetwork('::800:0:0/85') -IPNetwork('::1000:0:0/84') -IPNetwork('::2000:0:0/83') -IPNetwork('::4000:0:0/82') -IPNetwork('::8000:0:0/82') -IPNetwork('::c000:0:0/83') -IPNetwork('::e000:0:0/84') -IPNetwork('::f000:0:0/85') -IPNetwork('::f800:0:0/86') -IPNetwork('::fc00:0:0/87') -IPNetwork('::fe00:0:0/88') -IPNetwork('::ff00:0:0/89') -IPNetwork('::ff80:0:0/90') -IPNetwork('::ffc0:0:0/91') -IPNetwork('::ffe0:0:0/92') -IPNetwork('::fff0:0:0/93') -IPNetwork('::fff8:0:0/94') -IPNetwork('::fffc:0:0/95') -IPNetwork('::fffe:0:0/96') -IPNetwork('::ffff:0.0.0.0/97') -IPNetwork('::ffff:128.0.0.0/98') -IPNetwork('::ffff:192.0.0.0/99') -IPNetwork('::ffff:224.0.0.0/100') -IPNetwork('::ffff:240.0.0.0/101') -IPNetwork('::ffff:248.0.0.0/102') -IPNetwork('::ffff:252.0.0.0/103') -IPNetwork('::ffff:254.0.0.0/104') -IPNetwork('::ffff:255.0.0.0/105') -IPNetwork('::ffff:255.128.0.0/106') -IPNetwork('::ffff:255.192.0.0/107') -IPNetwork('::ffff:255.224.0.0/108') -IPNetwork('::ffff:255.240.0.0/109') -IPNetwork('::ffff:255.248.0.0/110') -IPNetwork('::ffff:255.252.0.0/111') -IPNetwork('::ffff:255.254.0.0/112') -IPNetwork('::ffff:255.255.0.0/113') -IPNetwork('::ffff:255.255.128.0/114') -IPNetwork('::ffff:255.255.192.0/115') -IPNetwork('::ffff:255.255.224.0/116') -IPNetwork('::ffff:255.255.240.0/117') -IPNetwork('::ffff:255.255.248.0/118') -IPNetwork('::ffff:255.255.252.0/119') -IPNetwork('::ffff:255.255.254.0/120') -IPNetwork('::ffff:255.255.255.0/121') -IPNetwork('::ffff:255.255.255.128/122') -IPNetwork('::ffff:255.255.255.192/123') -IPNetwork('::ffff:255.255.255.224/124') -IPNetwork('::ffff:255.255.255.240/125') -IPNetwork('::ffff:255.255.255.248/126') -IPNetwork('::ffff:255.255.255.252/127') -IPNetwork('::ffff:255.255.255.254/128') - -}}} - -RFC 4291 CIDR tests. - -{{{ - ->>> str(IPNetwork('2001:0DB8:0000:CD30:0000:0000:0000:0000/60')) -'2001:db8:0:cd30::/60' - ->>> str(IPNetwork('2001:0DB8::CD30:0:0:0:0/60')) -'2001:db8:0:cd30::/60' - ->>> str(IPNetwork('2001:0DB8:0:CD30::/60')) -'2001:db8:0:cd30::/60' - -}}} - -Equality tests. - -{{{ - ->>> IPNetwork('192.0.2.0/255.255.254.0') == IPNetwork('192.0.2.0/23') -True - ->>> IPNetwork('192.0.2.65/255.255.254.0') == IPNetwork('192.0.2.0/23') -True - ->>> IPNetwork('192.0.2.65/255.255.254.0') == IPNetwork('192.0.2.65/23') -True - ->>> IPNetwork('192.0.2.65/255.255.255.0') == IPNetwork('192.0.2.0/23') -False - ->>> IPNetwork('192.0.2.65/255.255.254.0') == IPNetwork('192.0.2.65/24') -False - -}}} - -Slicing tests. - -{{{ - ->>> ip = IPNetwork('192.0.2.0/23') ->>> ip.first == 3221225984 -True - ->>> ip.last == 3221226495 -True - ->>> ip[0] -IPAddress('192.0.2.0') - ->>> ip[-1] -IPAddress('192.0.3.255') - ->>> list(ip[::128]) -[IPAddress('192.0.2.0'), IPAddress('192.0.2.128'), IPAddress('192.0.3.0'), IPAddress('192.0.3.128')] - ->>> ip = IPNetwork('fe80::/10') ->>> ip[0] -IPAddress('fe80::') - ->>> ip[-1] -IPAddress('febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff') - ->>> ip.size == 332306998946228968225951765070086144 -True - ->>> list(ip[0:5:1]) -Traceback (most recent call last): -... -TypeError: IPv6 slices are not supported! - - -}}} - -Membership tests. - -{{{ - ->>> IPAddress('192.0.2.1') in IPNetwork('192.0.2.0/24') -True - ->>> IPAddress('192.0.2.255') in IPNetwork('192.0.2.0/24') -True - ->>> IPNetwork('192.0.2.0/24') in IPNetwork('192.0.2.0/23') -True - ->>> IPNetwork('192.0.2.0/24') in IPNetwork('192.0.2.0/24') -True - ->>> IPAddress('ffff::1') in IPNetwork('ffff::/127') -True - ->>> IPNetwork('192.0.2.0/23') in IPNetwork('192.0.2.0/24') -False - -}}} - -Equality tests. - -{{{ - ->>> IPNetwork('192.0.2.0/24') == IPNetwork('192.0.2.0/24') -True - ->>> IPNetwork('192.0.2.0/24') is not IPNetwork('192.0.2.0/24') -True - ->>> IPNetwork('192.0.2.0/24') != IPNetwork('192.0.2.0/24') -False - ->>> IPNetwork('192.0.2.0/24') is IPNetwork('192.0.2.0/24') -False - ->>> IPNetwork('fe80::/10') == IPNetwork('fe80::/10') -True - ->>> IPNetwork('fe80::/10') is not IPNetwork('fe80::/10') -True - ->>> IPNetwork('fe80::/10') != IPNetwork('fe80::/10') -False - ->>> IPNetwork('fe80::/10') is IPNetwork('fe80::/10') -False - -}}} - -Exclusion tests. - -{{{ - -# Equivalent to :- -# >>> set([1]) - set([1]) -# set([1]) ->>> cidr_exclude('192.0.2.1/32', '192.0.2.1/32') -[] - -# Equivalent to :- -# >>> set([1,2]) - set([2]) -# set([1]) ->>> cidr_exclude('192.0.2.0/31', '192.0.2.1/32') -[IPNetwork('192.0.2.0/32')] - -# Equivalent to :- -# >>> set([1,2,3,4,5,6,7,8]) - set([5,6,7,8]) -# set([1, 2, 3, 4]) ->>> cidr_exclude('192.0.2.0/24', '192.0.2.128/25') -[IPNetwork('192.0.2.0/25')] - -# Equivalent to :- -# >>> set([1,2,3,4,5,6,7,8]) - set([5,6]) -# set([1, 2, 3, 4, 7, 8]) ->>> cidr_exclude('192.0.2.0/24', '192.0.2.128/27') -[IPNetwork('192.0.2.0/25'), IPNetwork('192.0.2.160/27'), IPNetwork('192.0.2.192/26')] - -# Subtracting a larger range from a smaller one results in an empty -# list (rather than a negative CIDR - which would be rather odd)! -# -# Equivalent to :- -# >>> set([1]) - set([1,2,3]) -# set([]) ->>> cidr_exclude('192.0.2.1/32', '192.0.2.0/24') -[] - -}}} - -Please Note: excluding IP subnets that are not within each other and have no overlaps should return the original target IP object. - -{{{ - -# Equivalent to :- -# >>> set([1,2,3]) - set([4]) -# set([1,2,3]) ->>> cidr_exclude('192.0.2.0/28', '192.0.2.16/32') -[IPNetwork('192.0.2.0/28')] - -# Equivalent to :- -# >>> set([1]) - set([2,3,4]) -# set([1]) ->>> cidr_exclude('192.0.1.255/32', '192.0.2.0/28') -[IPNetwork('192.0.1.255/32')] - -}}} - -Merge tests. - -{{{ - ->>> cidr_merge(['192.0.128.0/24', '192.0.129.0/24']) -[IPNetwork('192.0.128.0/23')] - ->>> cidr_merge(['192.0.129.0/24', '192.0.130.0/24']) -[IPNetwork('192.0.129.0/24'), IPNetwork('192.0.130.0/24')] - ->>> cidr_merge(['192.0.2.112/30', '192.0.2.116/31', '192.0.2.118/31']) -[IPNetwork('192.0.2.112/29')] - ->>> cidr_merge(['192.0.2.112/30', '192.0.2.116/32', '192.0.2.118/31']) -[IPNetwork('192.0.2.112/30'), IPNetwork('192.0.2.116/32'), IPNetwork('192.0.2.118/31')] - ->>> cidr_merge(['192.0.2.112/31', '192.0.2.116/31', '192.0.2.118/31']) -[IPNetwork('192.0.2.112/31'), IPNetwork('192.0.2.116/30')] - ->>> cidr_merge(['192.0.1.254/31', -... '192.0.2.0/28', -... '192.0.2.16/28', -... '192.0.2.32/28', -... '192.0.2.48/28', -... '192.0.2.64/28', -... '192.0.2.80/28', -... '192.0.2.96/28', -... '192.0.2.112/28', -... '192.0.2.128/28', -... '192.0.2.144/28', -... '192.0.2.160/28', -... '192.0.2.176/28', -... '192.0.2.192/28', -... '192.0.2.208/28', -... '192.0.2.224/28', -... '192.0.2.240/28', -... '192.0.3.0/28']) -[IPNetwork('192.0.1.254/31'), IPNetwork('192.0.2.0/24'), IPNetwork('192.0.3.0/28')] - -}}} - -Extended merge tests. - -{{{ - ->>> import random - -# Start with a single /23 CIDR. - ->>> orig_cidr_ipv4 = IPNetwork('192.0.2.0/23') ->>> orig_cidr_ipv6 = IPNetwork('::192.0.2.0/120') - -# Split it into /28 subnet CIDRs (mix CIDR objects and CIDR strings). - ->>> cidr_subnets = [] ->>> cidr_subnets.extend([str(c) for c in orig_cidr_ipv4.subnet(28)]) ->>> cidr_subnets.extend(list(orig_cidr_ipv4.subnet(28))) ->>> cidr_subnets.extend([str(c) for c in orig_cidr_ipv6.subnet(124)]) ->>> cidr_subnets.extend(list(orig_cidr_ipv6.subnet(124))) - -# Add a couple of duplicates in to make sure summarization is working OK. - ->>> cidr_subnets.append('192.0.2.1/32') ->>> cidr_subnets.append('192.0.2.128/25') ->>> cidr_subnets.append('::192.0.2.92/128') - -# Randomize the order of subnets. ->>> random.shuffle(cidr_subnets) - -# Perform summarization operation. ->>> merged_cidrs = cidr_merge(cidr_subnets) ->>> merged_cidrs -[IPNetwork('192.0.2.0/23'), IPNetwork('::192.0.2.0/120')] - ->>> merged_cidrs == [orig_cidr_ipv4, orig_cidr_ipv6] -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/constructor.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/constructor.txt deleted file mode 100644 index c8805c1983..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/constructor.txt +++ /dev/null @@ -1,234 +0,0 @@ -=IP Constructor Stress Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -IPAddress constructor - integer values. - -{{{ - ->>> IPAddress(1) -IPAddress('0.0.0.1') - ->>> IPAddress(1, 4) -IPAddress('0.0.0.1') - ->>> IPAddress(1, 6) -IPAddress('::1') - ->>> IPAddress(10) -IPAddress('0.0.0.10') - ->>> IPAddress(0x1ffffffff) -IPAddress('::1:ffff:ffff') - ->>> IPAddress(0xffffffff, 6) -IPAddress('::255.255.255.255') - ->>> IPAddress(0x1ffffffff) -IPAddress('::1:ffff:ffff') - ->>> IPAddress(2 ** 128 - 1) -IPAddress('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff') - -}}} - -IPAddress constructor - IPv4 inet_aton behaviour (default). - -{{{ - -# Hexadecimal octets. ->>> IPAddress('0x7f.0x1') -IPAddress('127.0.0.1') - ->>> IPAddress('0x7f.0x0.0x0.0x1') -IPAddress('127.0.0.1') - -# Octal octets. ->>> IPAddress('0177.01') -IPAddress('127.0.0.1') - -# Mixed octets. ->>> IPAddress('0x7f.0.01') -IPAddress('127.0.0.1') - -# Partial addresses - pretty weird ... ->>> IPAddress('127') -IPAddress('0.0.0.127') - ->>> IPAddress('127') -IPAddress('0.0.0.127') - ->>> IPAddress('127.1') -IPAddress('127.0.0.1') - ->>> IPAddress('127.0.1') -IPAddress('127.0.0.1') - -}}} - -IPAddress constructor - IPv4 inet_pton behaviour (stricter parser). - -{{{ - -# Octal octets. ->>> IPAddress('0177.01', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '0177.01' - -# Mixed octets. ->>> IPAddress('0x7f.0.01', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '0x7f.0.01' - -# Partial octets. ->>> IPAddress('10', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '10' - ->>> IPAddress('10.1', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '10.1' - ->>> IPAddress('10.0.1', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '10.0.1' - ->>> IPAddress('10.0.0.1', flags=INET_PTON) -IPAddress('10.0.0.1') - -}}} - -IPAddress constructor - zero filled octets. - -{{{ - -# This takes a lot of people by surprise ... ->>> IPAddress('010.000.000.001') -IPAddress('8.0.0.1') - -# So, we need this! ->>> IPAddress('010.000.000.001', flags=ZEROFILL) -IPAddress('10.0.0.1') - -# Zero-fill with inet_aton behaviour - partial octets are OK but zero-filled -# octets are interpreted as decimal ... ->>> IPAddress('010.000.001', flags=ZEROFILL) -IPAddress('10.0.0.1') - -# Zero-fill with inet_pton behaviour - 4 octets only! ->>> IPAddress('010.000.001', flags=INET_PTON|ZEROFILL) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '010.000.001' - -# Zero-fill with inet_pton behaviour - 4 octets only! ->>> IPAddress('010.000.000.001', flags=INET_PTON|ZEROFILL) -IPAddress('10.0.0.1') - -# To save some typing there are short versions of these flags. ->>> IPAddress('010.000.000.001', flags=P|Z) -IPAddress('10.0.0.1') - -}}} - -IP network construction. - -{{{ - ->>> IPNetwork('192.0.2.0/24') -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('192.0.2.0/255.255.255.0') -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('192.0.2.0/0.0.0.255') -IPNetwork('192.0.2.0/24') - ->>> IPNetwork(IPNetwork('192.0.2.0/24')) -IPNetwork('192.0.2.0/24') - ->>> IPNetwork(IPNetwork('::192.0.2.0/120')) -IPNetwork('::192.0.2.0/120') - ->>> IPNetwork(IPNetwork('192.0.2.0/24')) -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('::192.0.2.0/120') -IPNetwork('::192.0.2.0/120') - ->>> IPNetwork('::192.0.2.0/120', 6) -IPNetwork('::192.0.2.0/120') - -}}} - -Optional implicit IP network prefix selection rules. - -{{{ - ->>> IPNetwork('192.0.2.0', implicit_prefix=True) -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('231.192.0.15', implicit_prefix=True) -IPNetwork('231.192.0.15/4') - ->>> IPNetwork('10', implicit_prefix=True) -IPNetwork('10.0.0.0/8') - -}}} - -Optional flags for tweaking IPNetwork constructor behaviour. - -{{{ - ->>> IPNetwork('172.24.200') -IPNetwork('172.24.200.0/32') - ->>> IPNetwork('172.24.200', implicit_prefix=True) -IPNetwork('172.24.200.0/16') - -# Truncate the host bits so we get a pure network. ->>> IPNetwork('172.24.200', implicit_prefix=True, flags=NOHOST) -IPNetwork('172.24.0.0/16') - - -}}} - -Negative testing - -{{{ - ->>> IPNetwork('foo') -Traceback (most recent call last): -... -AddrFormatError: invalid IPNetwork foo - -}}} - -Netmasks - -{{{ - ->>> IPAddress('1.1.1.1').netmask_bits() -32 - ->>> IPAddress('255.255.255.254').netmask_bits() -31 - ->>> IPAddress('255.255.255.0').netmask_bits() -24 - ->>> IPAddress('::').netmask_bits() -128 - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/formats.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/formats.txt deleted file mode 100644 index 7ad1986968..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/formats.txt +++ /dev/null @@ -1,27 +0,0 @@ -=IP formatting options= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -==IPAddress representations== - -{{{ - ->>> hex(IPAddress(0)) -'0x0' - ->>> hex(IPAddress(0xffffffff)) -'0xffffffff' - ->>> oct(IPAddress(0)) -'0' - ->>> oct(IPAddress(0xffffffff)) -'037777777777' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/functions.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/functions.txt deleted file mode 100644 index 2f6a8ca48d..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/functions.txt +++ /dev/null @@ -1,48 +0,0 @@ -=IP Function Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -During a cidr merge operation, the address 0.0.0.0/0, representing the whole of the IPv4 address space, should swallow anything it is merged with. - -{{{ - ->>> cidr_merge(['0.0.0.0/0', '0.0.0.0']) -[IPNetwork('0.0.0.0/0')] - ->>> cidr_merge(['0.0.0.0/0', '255.255.255.255']) -[IPNetwork('0.0.0.0/0')] - ->>> cidr_merge(['0.0.0.0/0', '192.0.2.0/24', '10.0.0.0/8']) -[IPNetwork('0.0.0.0/0')] - -}}} - -Same goes for the IPv6 CIDR ::/0, representing the whole of the IPv6 address space. - -{{{ - ->>> cidr_merge(['::/0', 'fe80::1']) -[IPNetwork('::/0')] - ->>> cidr_merge(['::/0', '::']) -[IPNetwork('::/0')] - ->>> cidr_merge(['::/0', '::192.0.2.0/124', 'ff00::101']) -[IPNetwork('::/0')] - -}}} - -This also applies to mixed IPv4 and IPv6 address lists. - -{{{ - ->>> cidr_merge(['0.0.0.0/0', '0.0.0.0', '::/0', '::']) -[IPNetwork('0.0.0.0/0'), IPNetwork('::/0')] - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/ipglob.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/ipglob.txt deleted file mode 100644 index 9a9a256799..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/ipglob.txt +++ /dev/null @@ -1,72 +0,0 @@ -=IP Glob Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -IP Glob tests. - -{{{ - ->>> cidr_to_glob('10.0.0.1/32') -'10.0.0.1' - ->>> cidr_to_glob('192.0.2.0/24') -'192.0.2.*' - ->>> cidr_to_glob('172.16.0.0/12') -'172.16-31.*.*' - ->>> cidr_to_glob('0.0.0.0/0') -'*.*.*.*' - ->>> glob_to_cidrs('10.0.0.1') -[IPNetwork('10.0.0.1/32')] - ->>> glob_to_cidrs('192.0.2.*') -[IPNetwork('192.0.2.0/24')] - ->>> glob_to_cidrs('172.16-31.*.*') -[IPNetwork('172.16.0.0/12')] - ->>> glob_to_cidrs('*.*.*.*') -[IPNetwork('0.0.0.0/0')] - ->>> glob_to_iptuple('*.*.*.*') -(IPAddress('0.0.0.0'), IPAddress('255.255.255.255')) - ->>> iprange_to_globs('192.0.2.0', '192.0.2.255') -['192.0.2.*'] - ->>> iprange_to_globs('192.0.2.1', '192.0.2.15') -['192.0.2.1-15'] - ->>> iprange_to_globs('192.0.2.255', '192.0.4.1') -['192.0.2.255', '192.0.3.*', '192.0.4.0-1'] - ->>> iprange_to_globs('10.0.1.255', '10.0.255.255') -['10.0.1.255', '10.0.2-3.*', '10.0.4-7.*', '10.0.8-15.*', '10.0.16-31.*', '10.0.32-63.*', '10.0.64-127.*', '10.0.128-255.*'] - -}}} - -Validity tests. - -{{{ - ->>> valid_glob('1.1.1.a') -False - ->>> valid_glob('1.1.1.1/32') -False - ->>> valid_glob('1.1.1.a-b') -False - ->>> valid_glob('1.1.a-b.*') -False - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/iprange.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/iprange.txt deleted file mode 100644 index eb359e604a..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/iprange.txt +++ /dev/null @@ -1,171 +0,0 @@ -=IPRange Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Constructor tests. - -{{{ - ->>> iprange = IPRange('192.0.2.1', '192.0.2.254') - ->>> iprange -IPRange('192.0.2.1', '192.0.2.254') - ->>> '%s' % iprange -'192.0.2.1-192.0.2.254' - ->>> IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') -IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') - ->>> IPRange('192.0.2.1', '192.0.2.1') -IPRange('192.0.2.1', '192.0.2.1') - ->>> IPRange('208.049.164.000', '208.050.066.255', flags=ZEROFILL) -IPRange('208.49.164.0', '208.50.66.255') - -}}} - -Bad constructor tests. - -{{{ - ->>> IPRange('192.0.2.2', '192.0.2.1') -Traceback (most recent call last): -... -AddrFormatError: lower bound IP greater than upper bound! - ->>> IPRange('::', '0.0.0.1') -Traceback (most recent call last): -... -AddrFormatError: base address '0.0.0.1' is not IPv6 - ->>> IPRange('0.0.0.0', '::1') -Traceback (most recent call last): -... -AddrFormatError: base address '::1' is not IPv4 - -}}} - -Indexing and slicing tests. - -{{{ - ->>> iprange = IPRange('192.0.2.1', '192.0.2.254') - ->>> len(iprange) -254 - ->>> iprange.first == 3221225985 -True - ->>> iprange.last == 3221226238 -True - ->>> iprange[0] -IPAddress('192.0.2.1') - ->>> iprange[-1] -IPAddress('192.0.2.254') - ->>> iprange[512] -Traceback (most recent call last): -... -IndexError: index out range for address range size! - ->>> list(iprange[0:3]) -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3')] - ->>> list(iprange[0:10:2]) -[IPAddress('192.0.2.1'), IPAddress('192.0.2.3'), IPAddress('192.0.2.5'), IPAddress('192.0.2.7'), IPAddress('192.0.2.9')] - ->>> list(iprange[0:1024:512]) -[IPAddress('192.0.2.1')] - ->>> IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254')[0:10:2] -Traceback (most recent call last): -... -TypeError: IPv6 slices are not supported! - -}}} - -Membership tests. - -{{{ - ->>> IPRange('192.0.2.5', '192.0.2.10') in IPRange('192.0.2.1', '192.0.2.254') -True - ->>> IPRange('fe80::1', 'fe80::fffe') in IPRange('fe80::', 'fe80::ffff:ffff:ffff:ffff') -True - ->>> IPRange('192.0.2.5', '192.0.2.10') in IPRange('::', '::255.255.255.255') -False - -}}} - -Sorting tests. - -{{{ - ->>> ipranges = (IPRange('192.0.2.40', '192.0.2.50'), IPRange('192.0.2.20', '192.0.2.30'), IPRange('192.0.2.1', '192.0.2.254'),) - ->>> sorted(ipranges) -[IPRange('192.0.2.1', '192.0.2.254'), IPRange('192.0.2.20', '192.0.2.30'), IPRange('192.0.2.40', '192.0.2.50')] - ->>> ipranges = list(ipranges) - ->>> ipranges.append(IPRange('192.0.2.45', '192.0.2.49')) - ->>> sorted(ipranges) -[IPRange('192.0.2.1', '192.0.2.254'), IPRange('192.0.2.20', '192.0.2.30'), IPRange('192.0.2.40', '192.0.2.50'), IPRange('192.0.2.45', '192.0.2.49')] - -}}} - -CIDR interoperability tests. - -{{{ - ->>> IPRange('192.0.2.5', '192.0.2.10').cidrs() -[IPNetwork('192.0.2.5/32'), IPNetwork('192.0.2.6/31'), IPNetwork('192.0.2.8/31'), IPNetwork('192.0.2.10/32')] - ->>> IPRange('fe80::', 'fe80::ffff:ffff:ffff:ffff').cidrs() -[IPNetwork('fe80::/64')] - -}}} - -Various additional tests. - -{{{ - ->>> iprange.info -{'IPv4': [{'date': '1993-05', - 'designation': 'Administered by ARIN', - 'prefix': '192/8', - 'status': 'Legacy', - 'whois': 'whois.arin.net'}]} - ->>> iprange.is_private() -True - ->>> iprange.version -4 - -len() fails when the IPRange is longer than sys.maxint, which is quite likely with IPv6. ->>> from netaddr.compat import _sys_maxint ->>> r = IPRange(IPAddress("::0"), IPAddress(_sys_maxint, 6)) ->>> len(r) -Traceback (most recent call last): - ... -IndexError: range contains more than ... - ->>> r = IPRange(IPAddress("::0"), IPAddress(_sys_maxint - 1, 6)) ->>> len(r) == _sys_maxint -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/matches.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/matches.txt deleted file mode 100644 index 1029228bcb..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/matches.txt +++ /dev/null @@ -1,71 +0,0 @@ -=IP Matching Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - ->>> largest_matching_cidr('192.0.2.0', ['192.0.2.0']) -IPNetwork('192.0.2.0/32') - ->>> largest_matching_cidr('192.0.2.0', ['10.0.0.1', '192.0.2.0']) -IPNetwork('192.0.2.0/32') - ->>> largest_matching_cidr('192.0.2.0', ['10.0.0.1', '192.0.2.0', '224.0.0.1']) -IPNetwork('192.0.2.0/32') - ->>> smallest_matching_cidr('192.0.2.0', ['10.0.0.1', '192.0.2.0', '224.0.0.1']) -IPNetwork('192.0.2.0/32') - ->>> smallest_matching_cidr('192.0.2.32', ['0.0.0.0/0', '10.0.0.0/8', '192.0.0.0/8', '192.0.1.0/24', '192.0.2.0/24', '192.0.3.0/24']) -IPNetwork('192.0.2.0/24') - ->>> all_matching_cidrs('192.0.2.32', ['0.0.0.0/0', '10.0.0.0/8', '192.0.0.0/8', '192.0.1.0/24', '192.0.2.0/24', '192.0.3.0/24']) -[IPNetwork('0.0.0.0/0'), IPNetwork('192.0.0.0/8'), IPNetwork('192.0.2.0/24')] - ->>> smallest_matching_cidr('192.0.2.0', ['10.0.0.1', '224.0.0.1']) - ->>> largest_matching_cidr('192.0.2.0', ['10.0.0.1', '224.0.0.1']) - ->>> networks = [str(c) for c in IPNetwork('192.0.2.128/27').supernet(22)] - ->>> networks -['192.0.0.0/22', '192.0.2.0/23', '192.0.2.0/24', '192.0.2.128/25', '192.0.2.128/26'] - ->>> all_matching_cidrs('192.0.2.0', networks) -[IPNetwork('192.0.0.0/22'), IPNetwork('192.0.2.0/23'), IPNetwork('192.0.2.0/24')] - ->>> smallest_matching_cidr('192.0.2.0', networks) -IPNetwork('192.0.2.0/24') - ->>> largest_matching_cidr('192.0.2.0', networks) -IPNetwork('192.0.0.0/22') - -}}} - -Checking matches with varying IP address versions. - -{{{ ->>> all_matching_cidrs('192.0.2.0', ['192.0.2.0/24']) -[IPNetwork('192.0.2.0/24')] - ->>> all_matching_cidrs('192.0.2.0', ['::/96']) -[] - ->>> all_matching_cidrs('::ffff:192.0.2.1', ['::ffff:192.0.2.0/96']) -[IPNetwork('::ffff:192.0.2.0/96')] - ->>> all_matching_cidrs('::192.0.2.1', ['::192.0.2.0/96']) -[IPNetwork('::192.0.2.0/96')] - ->>> all_matching_cidrs('::192.0.2.1', ['192.0.2.0/23']) -[] - ->>> all_matching_cidrs('::192.0.2.1', ['192.0.2.0/24', '::192.0.2.0/120']) -[IPNetwork('::192.0.2.0/120')] - ->>> all_matching_cidrs('::192.0.2.1', [IPNetwork('192.0.2.0/24'), IPNetwork('::192.0.2.0/120')]) -[IPNetwork('::192.0.2.0/120')] - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/multicast.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/multicast.txt deleted file mode 100644 index 6420b783d8..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/multicast.txt +++ /dev/null @@ -1,30 +0,0 @@ -=IP Multicast Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - ->>> ip = IPAddress('239.192.0.1') - ->>> ip.is_multicast() -True - ->>> ip = IPAddress(3221225984) - ->>> ip = IPAddress('224.0.1.173') - ->>> ip.info.IPv4[0].designation -'Multicast' - ->>> ip.info.IPv4[0].prefix -'224/8' - ->>> ip.info.IPv4[0].status -'Reserved' - ->>> ip.info.Multicast[0].address -'224.0.1.173' - -}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/nmap.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/nmap.txt deleted file mode 100644 index 84825ff3f3..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/nmap.txt +++ /dev/null @@ -1,118 +0,0 @@ -=nmap IP Range Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -nmap IP range validation. - -{{{ - ->>> valid_nmap_range('192.0.2.1') -True - ->>> valid_nmap_range('192.0.2.0-31') -True - ->>> valid_nmap_range('192.0.2-3.1-254') -True - ->>> valid_nmap_range('0-255.0-255.0-255.0-255') -True - ->>> valid_nmap_range('192.168.3-5,7.1') -True - ->>> valid_nmap_range('192.168.3-5,7,10-12,13,14.1') -True - ->>> valid_nmap_range(1) -False - ->>> valid_nmap_range('1') -False - ->>> valid_nmap_range([]) -False - ->>> valid_nmap_range({}) -False - ->>> valid_nmap_range('::') -False - ->>> valid_nmap_range('255.255.255.256') -False - ->>> valid_nmap_range('0-255.0-255.0-255.0-256') -False - ->>> valid_nmap_range('0-255.0-255.0-255.-1-0') -False - ->>> valid_nmap_range('0-255.0-255.0-255.256-0') -False - ->>> valid_nmap_range('0-255.0-255.0-255.255-0') -False - ->>> valid_nmap_range('a.b.c.d-e') -False - ->>> valid_nmap_range('255.255.255.a-b') -False - -}}} - -nmap IP range iteration. - -{{{ - ->>> list(iter_nmap_range('192.0.2.1')) -[IPAddress('192.0.2.1')] - ->>> ip_list = list(iter_nmap_range('192.0.2.0-31')) ->>> len(ip_list) -32 ->>> ip_list -[IPAddress('192.0.2.0'), IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3'), IPAddress('192.0.2.4'), IPAddress('192.0.2.5'), IPAddress('192.0.2.6'), IPAddress('192.0.2.7'), IPAddress('192.0.2.8'), IPAddress('192.0.2.9'), IPAddress('192.0.2.10'), IPAddress('192.0.2.11'), IPAddress('192.0.2.12'), IPAddress('192.0.2.13'), IPAddress('192.0.2.14'), IPAddress('192.0.2.15'), IPAddress('192.0.2.16'), IPAddress('192.0.2.17'), IPAddress('192.0.2.18'), IPAddress('192.0.2.19'), IPAddress('192.0.2.20'), IPAddress('192.0.2.21'), IPAddress('192.0.2.22'), IPAddress('192.0.2.23'), IPAddress('192.0.2.24'), IPAddress('192.0.2.25'), IPAddress('192.0.2.26'), IPAddress('192.0.2.27'), IPAddress('192.0.2.28'), IPAddress('192.0.2.29'), IPAddress('192.0.2.30'), IPAddress('192.0.2.31')] - ->>> ip_list = list(iter_nmap_range('192.0.2-3.1-7')) ->>> len(ip_list) -14 - ->>> list(iter_nmap_range('192.0.2.1-3,5,7-9')) -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3'), IPAddress('192.0.2.5'), IPAddress('192.0.2.7'), IPAddress('192.0.2.8'), IPAddress('192.0.2.9')] - ->>> for ip in ip_list: -... print ip -... -192.0.2.1 -192.0.2.2 -192.0.2.3 -192.0.2.4 -192.0.2.5 -192.0.2.6 -192.0.2.7 -192.0.3.1 -192.0.3.2 -192.0.3.3 -192.0.3.4 -192.0.3.5 -192.0.3.6 -192.0.3.7 - ->>> list(iter_nmap_range('::')) -Traceback (most recent call last): -... -AddrFormatError: invalid nmap range: :: - -Remove duplicates, just like nmap does. ->>> list(iter_nmap_range('10.0.0.42,42-42')) -[IPAddress('10.0.0.42')] - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/pickling.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/pickling.txt deleted file mode 100644 index 14d00f1af0..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/pickling.txt +++ /dev/null @@ -1,214 +0,0 @@ -=IP Persistence Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * ->>> import pickle - -}}} - -IPAddress object pickling - IPv4. - -{{{ - ->>> ip = IPAddress(3221225985) ->>> ip -IPAddress('192.0.2.1') - ->>> buf = pickle.dumps(ip) - ->>> ip2 = pickle.loads(buf) - ->>> ip2 == ip -True - ->>> id(ip2) != id(ip) -True - ->>> ip2.value == 3221225985 -True - ->>> ip2.version -4 - ->>> del ip, buf, ip2 - -}}} - -IPAddress object pickling - IPv6. - -{{{ - ->>> ip = IPAddress('::ffff:192.0.2.1') - ->>> ip -IPAddress('::ffff:192.0.2.1') - ->>> ip.value == 281473902969345 -True - ->>> buf = pickle.dumps(ip) - ->>> ip2 = pickle.loads(buf) - ->>> ip2 == ip -True - ->>> ip2.value == 281473902969345 -True - ->>> ip2.version -6 - ->>> del ip, buf, ip2 - -}}} - -IPNetwork pickling - IPv4. - -{{{ - ->>> cidr = IPNetwork('192.0.2.0/24') ->>> cidr -IPNetwork('192.0.2.0/24') - ->>> buf = pickle.dumps(cidr) - ->>> cidr2 = pickle.loads(buf) - ->>> cidr2 == cidr -True - ->>> id(cidr2) != id(cidr) -True - ->>> cidr2.value == 3221225984 -True - ->>> cidr2.prefixlen -24 - ->>> cidr2.version -4 - ->>> del cidr, buf, cidr2 - -}}} - -IPNetwork object pickling - IPv6. - -{{{ - ->>> cidr = IPNetwork('::ffff:192.0.2.0/120') - ->>> cidr -IPNetwork('::ffff:192.0.2.0/120') - ->>> cidr.value == 281473902969344 -True - ->>> cidr.prefixlen -120 - ->>> buf = pickle.dumps(cidr) - ->>> cidr2 = pickle.loads(buf) - ->>> cidr2 == cidr -True - ->>> cidr2.value == 281473902969344 -True - ->>> cidr2.prefixlen -120 - ->>> cidr2.version -6 - ->>> del cidr, buf, cidr2 - -}}} - -}}} - -IPRange object pickling - IPv4. - -{{{ - ->>> iprange = IPRange('192.0.2.1', '192.0.2.254') ->>> iprange -IPRange('192.0.2.1', '192.0.2.254') - ->>> iprange.first == 3221225985 -True - ->>> iprange.last == 3221226238 -True - ->>> iprange.version -4 - ->>> buf = pickle.dumps(iprange) - ->>> iprange2 = pickle.loads(buf) - ->>> iprange2 == iprange -True - ->>> id(iprange2) != id(iprange) -True - ->>> iprange2.first == 3221225985 -True - ->>> iprange2.last == 3221226238 -True - ->>> iprange2.version -4 - ->>> del iprange, buf, iprange2 - -}}} - -IPRange object pickling - IPv6. - -{{{ - ->>> iprange = IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') - ->>> iprange -IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') - ->>> iprange.first == 281473902969345 -True - ->>> iprange.last == 281473902969598 -True - ->>> iprange.version -6 - ->>> buf = pickle.dumps(iprange) - ->>> iprange2 = pickle.loads(buf) - ->>> iprange2 == iprange -True - ->>> iprange2.first == 281473902969345 -True - ->>> iprange2.last == 281473902969598 -True - ->>> iprange2.version -6 - ->>> del iprange, buf, iprange2 - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_darwin.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_darwin.txt deleted file mode 100644 index 0efe91f038..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_darwin.txt +++ /dev/null @@ -1,90 +0,0 @@ -=Mac OSX Specific Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Worst case IPv4 compatible IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::1', '::255.255.255.254'): -... ip -... -IPNetwork('::1/128') -IPNetwork('::0.0.0.2/127') -IPNetwork('::0.0.0.4/126') -IPNetwork('::0.0.0.8/125') -IPNetwork('::0.0.0.16/124') -IPNetwork('::0.0.0.32/123') -IPNetwork('::0.0.0.64/122') -IPNetwork('::0.0.0.128/121') -IPNetwork('::0.0.1.0/120') -IPNetwork('::0.0.2.0/119') -IPNetwork('::0.0.4.0/118') -IPNetwork('::0.0.8.0/117') -IPNetwork('::0.0.16.0/116') -IPNetwork('::0.0.32.0/115') -IPNetwork('::0.0.64.0/114') -IPNetwork('::0.0.128.0/113') -IPNetwork('::0.1.0.0/112') -IPNetwork('::0.2.0.0/111') -IPNetwork('::0.4.0.0/110') -IPNetwork('::0.8.0.0/109') -IPNetwork('::0.16.0.0/108') -IPNetwork('::0.32.0.0/107') -IPNetwork('::0.64.0.0/106') -IPNetwork('::0.128.0.0/105') -IPNetwork('::1.0.0.0/104') -IPNetwork('::2.0.0.0/103') -IPNetwork('::4.0.0.0/102') -IPNetwork('::8.0.0.0/101') -IPNetwork('::16.0.0.0/100') -IPNetwork('::32.0.0.0/99') -IPNetwork('::64.0.0.0/98') -IPNetwork('::128.0.0.0/98') -IPNetwork('::192.0.0.0/99') -IPNetwork('::224.0.0.0/100') -IPNetwork('::240.0.0.0/101') -IPNetwork('::248.0.0.0/102') -IPNetwork('::252.0.0.0/103') -IPNetwork('::254.0.0.0/104') -IPNetwork('::255.0.0.0/105') -IPNetwork('::255.128.0.0/106') -IPNetwork('::255.192.0.0/107') -IPNetwork('::255.224.0.0/108') -IPNetwork('::255.240.0.0/109') -IPNetwork('::255.248.0.0/110') -IPNetwork('::255.252.0.0/111') -IPNetwork('::255.254.0.0/112') -IPNetwork('::255.255.0.0/113') -IPNetwork('::255.255.128.0/114') -IPNetwork('::255.255.192.0/115') -IPNetwork('::255.255.224.0/116') -IPNetwork('::255.255.240.0/117') -IPNetwork('::255.255.248.0/118') -IPNetwork('::255.255.252.0/119') -IPNetwork('::255.255.254.0/120') -IPNetwork('::255.255.255.0/121') -IPNetwork('::255.255.255.128/122') -IPNetwork('::255.255.255.192/123') -IPNetwork('::255.255.255.224/124') -IPNetwork('::255.255.255.240/125') -IPNetwork('::255.255.255.248/126') -IPNetwork('::255.255.255.252/127') -IPNetwork('::255.255.255.254/128') - -# inet_pton has to be different on Mac OSX *sigh* ->>> IPAddress('010.000.000.001', flags=INET_PTON) -IPAddress('10.0.0.1') - ->>> from netaddr.strategy.ipv6 import int_to_str ->>> int_to_str(0xffff) -'::0.0.255.255' - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_linux2.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_linux2.txt deleted file mode 100644 index 08335050a3..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_linux2.txt +++ /dev/null @@ -1,94 +0,0 @@ -=Linux Specific Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Worst case IPv4 compatible IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::1', '::255.255.255.254'): -... ip -... -IPNetwork('::1/128') -IPNetwork('::2/127') -IPNetwork('::4/126') -IPNetwork('::8/125') -IPNetwork('::10/124') -IPNetwork('::20/123') -IPNetwork('::40/122') -IPNetwork('::80/121') -IPNetwork('::100/120') -IPNetwork('::200/119') -IPNetwork('::400/118') -IPNetwork('::800/117') -IPNetwork('::1000/116') -IPNetwork('::2000/115') -IPNetwork('::4000/114') -IPNetwork('::8000/113') -IPNetwork('::0.1.0.0/112') -IPNetwork('::0.2.0.0/111') -IPNetwork('::0.4.0.0/110') -IPNetwork('::0.8.0.0/109') -IPNetwork('::0.16.0.0/108') -IPNetwork('::0.32.0.0/107') -IPNetwork('::0.64.0.0/106') -IPNetwork('::0.128.0.0/105') -IPNetwork('::1.0.0.0/104') -IPNetwork('::2.0.0.0/103') -IPNetwork('::4.0.0.0/102') -IPNetwork('::8.0.0.0/101') -IPNetwork('::16.0.0.0/100') -IPNetwork('::32.0.0.0/99') -IPNetwork('::64.0.0.0/98') -IPNetwork('::128.0.0.0/98') -IPNetwork('::192.0.0.0/99') -IPNetwork('::224.0.0.0/100') -IPNetwork('::240.0.0.0/101') -IPNetwork('::248.0.0.0/102') -IPNetwork('::252.0.0.0/103') -IPNetwork('::254.0.0.0/104') -IPNetwork('::255.0.0.0/105') -IPNetwork('::255.128.0.0/106') -IPNetwork('::255.192.0.0/107') -IPNetwork('::255.224.0.0/108') -IPNetwork('::255.240.0.0/109') -IPNetwork('::255.248.0.0/110') -IPNetwork('::255.252.0.0/111') -IPNetwork('::255.254.0.0/112') -IPNetwork('::255.255.0.0/113') -IPNetwork('::255.255.128.0/114') -IPNetwork('::255.255.192.0/115') -IPNetwork('::255.255.224.0/116') -IPNetwork('::255.255.240.0/117') -IPNetwork('::255.255.248.0/118') -IPNetwork('::255.255.252.0/119') -IPNetwork('::255.255.254.0/120') -IPNetwork('::255.255.255.0/121') -IPNetwork('::255.255.255.128/122') -IPNetwork('::255.255.255.192/123') -IPNetwork('::255.255.255.224/124') -IPNetwork('::255.255.255.240/125') -IPNetwork('::255.255.255.248/126') -IPNetwork('::255.255.255.252/127') -IPNetwork('::255.255.255.254/128') - -# Sadly, inet_pton cannot help us here ... ->>> IPAddress('010.000.000.001', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '010.000.000.001' - ->>> from netaddr.strategy.ipv6 import int_to_str ->>> int_to_str(0xffff) -'::ffff' - -}}} - - - diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_win32.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_win32.txt deleted file mode 100644 index 8bba1101d0..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/platform_win32.txt +++ /dev/null @@ -1,92 +0,0 @@ -=Windows Specific Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Worst case IPv4 compatible IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::1', '::255.255.255.254'): -... ip -... -IPNetwork('::1/128') -IPNetwork('::2/127') -IPNetwork('::4/126') -IPNetwork('::8/125') -IPNetwork('::10/124') -IPNetwork('::20/123') -IPNetwork('::40/122') -IPNetwork('::80/121') -IPNetwork('::100/120') -IPNetwork('::200/119') -IPNetwork('::400/118') -IPNetwork('::800/117') -IPNetwork('::1000/116') -IPNetwork('::2000/115') -IPNetwork('::4000/114') -IPNetwork('::8000/113') -IPNetwork('::0.1.0.0/112') -IPNetwork('::0.2.0.0/111') -IPNetwork('::0.4.0.0/110') -IPNetwork('::0.8.0.0/109') -IPNetwork('::0.16.0.0/108') -IPNetwork('::0.32.0.0/107') -IPNetwork('::0.64.0.0/106') -IPNetwork('::0.128.0.0/105') -IPNetwork('::1.0.0.0/104') -IPNetwork('::2.0.0.0/103') -IPNetwork('::4.0.0.0/102') -IPNetwork('::8.0.0.0/101') -IPNetwork('::16.0.0.0/100') -IPNetwork('::32.0.0.0/99') -IPNetwork('::64.0.0.0/98') -IPNetwork('::128.0.0.0/98') -IPNetwork('::192.0.0.0/99') -IPNetwork('::224.0.0.0/100') -IPNetwork('::240.0.0.0/101') -IPNetwork('::248.0.0.0/102') -IPNetwork('::252.0.0.0/103') -IPNetwork('::254.0.0.0/104') -IPNetwork('::255.0.0.0/105') -IPNetwork('::255.128.0.0/106') -IPNetwork('::255.192.0.0/107') -IPNetwork('::255.224.0.0/108') -IPNetwork('::255.240.0.0/109') -IPNetwork('::255.248.0.0/110') -IPNetwork('::255.252.0.0/111') -IPNetwork('::255.254.0.0/112') -IPNetwork('::255.255.0.0/113') -IPNetwork('::255.255.128.0/114') -IPNetwork('::255.255.192.0/115') -IPNetwork('::255.255.224.0/116') -IPNetwork('::255.255.240.0/117') -IPNetwork('::255.255.248.0/118') -IPNetwork('::255.255.252.0/119') -IPNetwork('::255.255.254.0/120') -IPNetwork('::255.255.255.0/121') -IPNetwork('::255.255.255.128/122') -IPNetwork('::255.255.255.192/123') -IPNetwork('::255.255.255.224/124') -IPNetwork('::255.255.255.240/125') -IPNetwork('::255.255.255.248/126') -IPNetwork('::255.255.255.252/127') -IPNetwork('::255.255.255.254/128') - -# Sadly, inet_pton cannot help us here ... ->>> IPAddress('010.000.000.001', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: failed to detect a valid IP address from '010.000.000.001' - ->>> from netaddr.strategy.ipv6 import int_to_str ->>> int_to_str(0xffff) -'::ffff' - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/rfc1924.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/rfc1924.txt deleted file mode 100644 index 06115d6c3b..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/rfc1924.txt +++ /dev/null @@ -1,33 +0,0 @@ -=RFC 1924 Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -The example from the RFC. - -{{{ - ->>> from netaddr.ip.rfc1924 import ipv6_to_base85, base85_to_ipv6 - ->>> ip_addr = '1080::8:800:200c:417a' - ->>> ip_addr -'1080::8:800:200c:417a' - ->>> base85 = ipv6_to_base85(ip_addr) - ->>> base85 -'4)+k&C#VzJ4br>0wv%Yp' - -RFC specifies that "leading zeroes are never omitted" ->>> ipv6_to_base85("::1") -'00000000000000000001' - ->>> base85_to_ipv6(base85) -'1080::8:800:200c:417a' - -Invalid length for a base85 encoded IPv6 address ->>> base85_to_ipv6('not 20 chars') -Traceback (most recent call last): -AddrFormatError: Invalid base 85 IPv6 address: 'not 20 chars' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/sets.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/sets.txt deleted file mode 100644 index e38df64674..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/sets.txt +++ /dev/null @@ -1,526 +0,0 @@ -First of all you need to pull the various netaddr classes and functions into your namespace. - -.. note:: Do this for the purpose of this tutorial only. In your own code, you should be explicit about the classes, functions and constants you import to avoid name clashes. - ->>> from netaddr import * - ----------------- -Creating IP sets ----------------- - -Here how to create IP sets. - -An empty set. - ->>> IPSet() -IPSet([]) ->>> IPSet([]) -IPSet([]) ->>> len(IPSet([])) -0 - -You can specify either IP addresses and networks as strings. Alternatively, you -can use IPAddress, IPNetwork, IPRange or other IPSet objects. - ->>> IPSet(['192.0.2.0']) -IPSet(['192.0.2.0/32']) ->>> IPSet([IPAddress('192.0.2.0')]) -IPSet(['192.0.2.0/32']) ->>> IPSet([IPNetwork('192.0.2.0')]) -IPSet(['192.0.2.0/32']) ->>> IPSet(IPNetwork('1234::/32')) -IPSet(['1234::/32']) ->>> IPSet([IPNetwork('192.0.2.0/24')]) -IPSet(['192.0.2.0/24']) ->>> IPSet(IPSet(['192.0.2.0/32'])) -IPSet(['192.0.2.0/32']) ->>> IPSet(IPRange("10.0.0.0", "10.0.1.31")) -IPSet(['10.0.0.0/24', '10.0.1.0/27']) ->>> IPSet(IPRange('0.0.0.0', '255.255.255.255')) -IPSet(['0.0.0.0/0']) - -You can interate over all the IP addresses that are members of the IP set. - ->>> for ip in IPSet(['192.0.2.0/28', '::192.0.2.0/124']): -... print ip -192.0.2.0 -192.0.2.1 -192.0.2.2 -192.0.2.3 -192.0.2.4 -192.0.2.5 -192.0.2.6 -192.0.2.7 -192.0.2.8 -192.0.2.9 -192.0.2.10 -192.0.2.11 -192.0.2.12 -192.0.2.13 -192.0.2.14 -192.0.2.15 -::192.0.2.0 -::192.0.2.1 -::192.0.2.2 -::192.0.2.3 -::192.0.2.4 -::192.0.2.5 -::192.0.2.6 -::192.0.2.7 -::192.0.2.8 -::192.0.2.9 -::192.0.2.10 -::192.0.2.11 -::192.0.2.12 -::192.0.2.13 -::192.0.2.14 -::192.0.2.15 - --------------------------------- -Adding and removing set elements --------------------------------- - ->>> s1 = IPSet() ->>> s1.add('192.0.2.0') ->>> s1 -IPSet(['192.0.2.0/32']) ->>> s1.remove('192.0.2.0') ->>> s1 -IPSet([]) ->>> s1.add(IPRange("10.0.0.0", "10.0.0.255")) ->>> s1 -IPSet(['10.0.0.0/24']) ->>> s1.remove(IPRange("10.0.0.128", "10.10.10.10")) ->>> s1 -IPSet(['10.0.0.0/25']) - --------------- -Set membership --------------- - -Here is a simple arbitrary IP address range. - ->>> iprange = IPRange('192.0.1.255', '192.0.2.16') - -We can see the CIDR networks that can existing with this defined range. - ->>> iprange.cidrs() -[IPNetwork('192.0.1.255/32'), IPNetwork('192.0.2.0/28'), IPNetwork('192.0.2.16/32')] - -Here's an IP set. - ->>> ipset = IPSet(['192.0.2.0/28']) - -Now, let's iterate over the IP addresses in the arbitrary IP address range and see if they are found within the IP set. - ->>> for ip in iprange: -... print ip, ip in ipset -192.0.1.255 False -192.0.2.0 True -192.0.2.1 True -192.0.2.2 True -192.0.2.3 True -192.0.2.4 True -192.0.2.5 True -192.0.2.6 True -192.0.2.7 True -192.0.2.8 True -192.0.2.9 True -192.0.2.10 True -192.0.2.11 True -192.0.2.12 True -192.0.2.13 True -192.0.2.14 True -192.0.2.15 True -192.0.2.16 False - -More exotic IPSets - ->>> bigone = IPSet(['0.0.0.0/0']) ->>> IPAddress("10.0.0.1") in bigone -True ->>> IPAddress("0.0.0.0") in bigone -True ->>> IPAddress("255.255.255") in bigone -True ->>> IPNetwork("10.0.0.0/24") in bigone -True ->>> IPAddress("::1") in bigone -False - ->>> smallone = IPSet(["10.0.0.42/32"]) ->>> IPAddress("10.0.0.42") in smallone -True ->>> IPAddress("10.0.0.41") in smallone -False ->>> IPAddress("10.0.0.43") in smallone -False ->>> IPNetwork("10.0.0.42/32") in smallone -True ->>> IPNetwork("10.0.0.42/31") in smallone -False - -------------------------------------- -Unions, intersections and differences -------------------------------------- - -Here are some examples of union operations performed on `IPSet` objects. - ->>> IPSet(['192.0.2.0']) -IPSet(['192.0.2.0/32']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) -IPSet(['192.0.2.0/31']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3']) -IPSet(['192.0.2.0/31', '192.0.2.3/32']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3/30']) -IPSet(['192.0.2.0/30']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3/31']) -IPSet(['192.0.2.0/30']) - ->>> IPSet(['192.0.2.0/24']) | IPSet(['192.0.3.0/24']) | IPSet(['192.0.4.0/24']) -IPSet(['192.0.2.0/23', '192.0.4.0/24']) - -Here is an example of the union, intersection and symmetric difference operations all in play at the same time. - ->>> adj_cidrs = list(IPNetwork('192.0.2.0/24').subnet(28)) ->>> even_cidrs = adj_cidrs[::2] ->>> evens = IPSet(even_cidrs) ->>> evens -IPSet(['192.0.2.0/28', '192.0.2.32/28', '192.0.2.64/28', '192.0.2.96/28', '192.0.2.128/28', '192.0.2.160/28', '192.0.2.192/28', '192.0.2.224/28']) ->>> IPSet(['192.0.2.0/24']) & evens -IPSet(['192.0.2.0/28', '192.0.2.32/28', '192.0.2.64/28', '192.0.2.96/28', '192.0.2.128/28', '192.0.2.160/28', '192.0.2.192/28', '192.0.2.224/28']) ->>> odds = IPSet(['192.0.2.0/24']) ^ evens ->>> odds -IPSet(['192.0.2.16/28', '192.0.2.48/28', '192.0.2.80/28', '192.0.2.112/28', '192.0.2.144/28', '192.0.2.176/28', '192.0.2.208/28', '192.0.2.240/28']) ->>> evens | odds -IPSet(['192.0.2.0/24']) ->>> evens & odds -IPSet([]) ->>> evens ^ odds -IPSet(['192.0.2.0/24']) - ---------------------- -Supersets and subsets ---------------------- - -IP sets provide the ability to test whether a group of addresses ranges fit within the set of another group of address ranges. - ->>> s1 = IPSet(['192.0.2.0/24', '192.0.4.0/24']) ->>> s2 = IPSet(['192.0.2.0', '192.0.4.0']) ->>> s1 -IPSet(['192.0.2.0/24', '192.0.4.0/24']) ->>> s2 -IPSet(['192.0.2.0/32', '192.0.4.0/32']) ->>> s1.issuperset(s2) -True ->>> s2.issubset(s1) -True ->>> s2.issuperset(s1) -False ->>> s1.issubset(s2) -False - -Here's a more complete example using various well known IPv4 address ranges. - ->>> ipv4_addr_space = IPSet(['0.0.0.0/0']) ->>> private = IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '239.192.0.0/14']) ->>> reserved = IPSet(['225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '240.0.0.0/4']) ->>> unavailable = reserved | private ->>> available = ipv4_addr_space ^ unavailable - -Let's see what we've got: - ->>> for cidr in available.iter_cidrs(): -... print cidr, cidr[0], cidr[-1] -0.0.0.0/5 0.0.0.0 7.255.255.255 -8.0.0.0/7 8.0.0.0 9.255.255.255 -11.0.0.0/8 11.0.0.0 11.255.255.255 -12.0.0.0/6 12.0.0.0 15.255.255.255 -16.0.0.0/4 16.0.0.0 31.255.255.255 -32.0.0.0/3 32.0.0.0 63.255.255.255 -64.0.0.0/2 64.0.0.0 127.255.255.255 -128.0.0.0/3 128.0.0.0 159.255.255.255 -160.0.0.0/5 160.0.0.0 167.255.255.255 -168.0.0.0/6 168.0.0.0 171.255.255.255 -172.0.0.0/12 172.0.0.0 172.15.255.255 -172.32.0.0/11 172.32.0.0 172.63.255.255 -172.64.0.0/10 172.64.0.0 172.127.255.255 -172.128.0.0/9 172.128.0.0 172.255.255.255 -173.0.0.0/8 173.0.0.0 173.255.255.255 -174.0.0.0/7 174.0.0.0 175.255.255.255 -176.0.0.0/4 176.0.0.0 191.255.255.255 -192.0.0.0/23 192.0.0.0 192.0.1.255 -192.0.3.0/24 192.0.3.0 192.0.3.255 -192.0.4.0/22 192.0.4.0 192.0.7.255 -192.0.8.0/21 192.0.8.0 192.0.15.255 -192.0.16.0/20 192.0.16.0 192.0.31.255 -192.0.32.0/19 192.0.32.0 192.0.63.255 -192.0.64.0/18 192.0.64.0 192.0.127.255 -192.0.128.0/17 192.0.128.0 192.0.255.255 -192.1.0.0/16 192.1.0.0 192.1.255.255 -192.2.0.0/15 192.2.0.0 192.3.255.255 -192.4.0.0/14 192.4.0.0 192.7.255.255 -192.8.0.0/13 192.8.0.0 192.15.255.255 -192.16.0.0/12 192.16.0.0 192.31.255.255 -192.32.0.0/11 192.32.0.0 192.63.255.255 -192.64.0.0/10 192.64.0.0 192.127.255.255 -192.128.0.0/11 192.128.0.0 192.159.255.255 -192.160.0.0/13 192.160.0.0 192.167.255.255 -192.169.0.0/16 192.169.0.0 192.169.255.255 -192.170.0.0/15 192.170.0.0 192.171.255.255 -192.172.0.0/14 192.172.0.0 192.175.255.255 -192.176.0.0/12 192.176.0.0 192.191.255.255 -192.192.0.0/10 192.192.0.0 192.255.255.255 -193.0.0.0/8 193.0.0.0 193.255.255.255 -194.0.0.0/7 194.0.0.0 195.255.255.255 -196.0.0.0/6 196.0.0.0 199.255.255.255 -200.0.0.0/5 200.0.0.0 207.255.255.255 -208.0.0.0/4 208.0.0.0 223.255.255.255 -224.0.0.0/8 224.0.0.0 224.255.255.255 -232.0.0.0/7 232.0.0.0 233.255.255.255 -239.0.0.0/9 239.0.0.0 239.127.255.255 -239.128.0.0/10 239.128.0.0 239.191.255.255 -239.196.0.0/14 239.196.0.0 239.199.255.255 -239.200.0.0/13 239.200.0.0 239.207.255.255 -239.208.0.0/12 239.208.0.0 239.223.255.255 -239.224.0.0/11 239.224.0.0 239.255.255.255 - ->>> ipv4_addr_space ^ available -IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '239.192.0.0/14', '240.0.0.0/4']) - - ------------------------------- -Combined IPv4 and IPv6 support ------------------------------- - -In keeping with netaddr's pragmatic approach, you are free to mix and match IPv4 and IPv6 within the same data structure. - ->>> s1 = IPSet(['192.0.2.0', '::192.0.2.0', '192.0.2.2', '::192.0.2.2']) ->>> s2 = IPSet(['192.0.2.2', '::192.0.2.2', '192.0.2.4', '::192.0.2.4']) - ->>> s1 -IPSet(['192.0.2.0/32', '192.0.2.2/32', '::192.0.2.0/128', '::192.0.2.2/128']) ->>> s2 -IPSet(['192.0.2.2/32', '192.0.2.4/32', '::192.0.2.2/128', '::192.0.2.4/128']) - -^^^^^^^^^^^^^^^^^^^^^^^ -IPv4 and IPv6 set union -^^^^^^^^^^^^^^^^^^^^^^^ - ->>> s1 | s2 -IPSet(['192.0.2.0/32', '192.0.2.2/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.2/128', '::192.0.2.4/128']) ->>> s2 | s1 -IPSet(['192.0.2.0/32', '192.0.2.2/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.2/128', '::192.0.2.4/128']) - -^^^^^^^^^^^^^^^^ -set intersection -^^^^^^^^^^^^^^^^ - ->>> s1 & s2 -IPSet(['192.0.2.2/32', '::192.0.2.2/128']) - -^^^^^^^^^^^^^^ -set difference -^^^^^^^^^^^^^^ - ->>> s1 - s2 -IPSet(['192.0.2.0/32', '::192.0.2.0/128']) ->>> s2 - s1 -IPSet(['192.0.2.4/32', '::192.0.2.4/128']) - -^^^^^^^^^^^^^^^^^^^^^^^^ -set symmetric difference -^^^^^^^^^^^^^^^^^^^^^^^^ - ->>> s1 ^ s2 -IPSet(['192.0.2.0/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.4/128']) - ------------------- -Disjointed IP sets ------------------- - ->>> s1 = IPSet(['192.0.2.0', '192.0.2.1', '192.0.2.2']) ->>> s2 = IPSet(['192.0.2.2', '192.0.2.3', '192.0.2.4']) ->>> s1 & s2 -IPSet(['192.0.2.2/32']) ->>> s1.isdisjoint(s2) -False ->>> s1 = IPSet(['192.0.2.0', '192.0.2.1']) ->>> s2 = IPSet(['192.0.2.3', '192.0.2.4']) ->>> s1 & s2 -IPSet([]) ->>> s1.isdisjoint(s2) -True - ------------------- -Updating an IP set ------------------- - -As with a normal Python set you can also update one IP set with the contents of another. - ->>> s1 = IPSet(['192.0.2.0/25']) ->>> s1 -IPSet(['192.0.2.0/25']) ->>> s2 = IPSet(['192.0.2.128/25']) ->>> s2 -IPSet(['192.0.2.128/25']) ->>> s1.update(s2) ->>> s1 -IPSet(['192.0.2.0/24']) ->>> s1.update(['192.0.0.0/24', '192.0.1.0/24', '192.0.3.0/24']) ->>> s1 -IPSet(['192.0.0.0/22']) - ->>> s2 = IPSet(['10.0.0.0/16']) ->>> s2.update(IPRange('10.1.0.0', '10.1.255.255')) ->>> s2 -IPSet(['10.0.0.0/15']) - ->>> s2.clear() ->>> s2 -IPSet([]) - --------------------------------- -Removing elements from an IP set --------------------------------- - -Removing an IP address from an IPSet will split the CIDR subnets within it into their constituent parts. - -Here we create a set representing the entire IPv4 address space. - ->>> s1 = IPSet(['0.0.0.0/0']) ->>> s1 -IPSet(['0.0.0.0/0']) - -Then we strip off the last address. - ->>> s1.remove('255.255.255.255') - -Leaving us with: - ->>> s1 -IPSet(['0.0.0.0/1', '128.0.0.0/2', ..., '255.255.255.252/31', '255.255.255.254/32']) ->>> list(s1.iter_cidrs()) -[IPNetwork('0.0.0.0/1'), IPNetwork('128.0.0.0/2'), ..., IPNetwork('255.255.255.252/31'), IPNetwork('255.255.255.254/32')] ->>> len(list(s1.iter_cidrs())) -32 - -Let's check the result using the `cidr_exclude` function. - ->>> list(s1.iter_cidrs()) == cidr_exclude('0.0.0.0/0', '255.255.255.255') -True - -Next, let's remove the first address from the original range. - ->>> s1.remove('0.0.0.0') - -This fractures the CIDR subnets further. - ->>> s1 -IPSet(['0.0.0.1/32', '0.0.0.2/31', ..., '255.255.255.252/31', '255.255.255.254/32']) ->>> len(list(s1.iter_cidrs())) -62 - -You can keep doing this but be aware that large IP sets can take up a lot of memory if they contain many thousands of entries. - ----------------------------- -Adding elements to an IP set ----------------------------- - -Let's fix up the fractured IP set from the previous section by re-adding the IP addresses we removed. - ->>> s1.add('255.255.255.255') ->>> s1 -IPSet(['0.0.0.1/32', '0.0.0.2/31', ..., '64.0.0.0/2', '128.0.0.0/1']) - -Getting better. - ->>> list(s1.iter_cidrs()) -[IPNetwork('0.0.0.1/32'), IPNetwork('0.0.0.2/31'), ..., IPNetwork('64.0.0.0/2'), IPNetwork('128.0.0.0/1')] - ->>> len(list(s1.iter_cidrs())) -32 - -Add back the other IP address. - ->>> s1.add('0.0.0.0') - -And we're back to our original address. - ->>> s1 -IPSet(['0.0.0.0/0']) - --------------------------------- -Convert an IP set to an IP Range --------------------------------- -Sometimes you may want to convert an IPSet back to an IPRange. - ->>> s1 = IPSet(['10.0.0.0/25', '10.0.0.128/25']) ->>> s1.iprange() -IPRange('10.0.0.0', '10.0.0.255') - -This only works if the IPSet is contiguous - ->>> s1.iscontiguous() -True ->>> s1.remove('10.0.0.16') ->>> s1 -IPSet(['10.0.0.0/28', '10.0.0.17/32', '10.0.0.18/31', '10.0.0.20/30', '10.0.0.24/29', '10.0.0.32/27', '10.0.0.64/26', '10.0.0.128/25']) ->>> s1.iscontiguous() -False ->>> s1.iprange() -Traceback (most recent call last): - File "", line 1, in -ValueError: IPSet is not contiguous - -If it is not contiguous, you can still convert the IPSet, but you will get multiple IPRanges. ->>> list(s1.iter_ipranges()) -[IPRange('10.0.0.0', '10.0.0.15'), IPRange('10.0.0.17', '10.0.0.255')] - ->>> s2 = IPSet(['0.0.0.0/0']) ->>> s2.iscontiguous() -True ->>> s2.iprange() -IPRange('0.0.0.0', '255.255.255.255') - ->>> s3 = IPSet() ->>> s3.iscontiguous() -True ->>> s3.iprange() - ->>> s4 = IPSet(IPRange('10.0.0.0', '10.0.0.8')) ->>> s4.iscontiguous() -True - ----------------------- -Pickling IPSet objects ----------------------- - -As with all other netaddr classes, you can use ``pickle`` to persist IP sets for later use. - ->>> import pickle ->>> ip_data = IPSet(['10.0.0.0/16', 'fe80::/64']) ->>> buf = pickle.dumps(ip_data) ->>> ip_data_unpickled = pickle.loads(buf) ->>> ip_data == ip_data_unpickled -True - ----------------------- -Compare IPSet objects ----------------------- - ->>> x = IPSet(['fc00::/2']) ->>> y = IPSet(['fc00::/3']) - ->>> x > y -True - ->>> x < y -False - ->>> x != y -True diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/sets_non_sphinx.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/sets_non_sphinx.txt deleted file mode 100644 index 8209dac60f..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/sets_non_sphinx.txt +++ /dev/null @@ -1,166 +0,0 @@ -Since "sets.txt" is used by Sphinx to build the documentation, those test cases for IPSet that should not become part of the documenation go here. The tests for Python3 are not imported by Sphinx, though. - ->>> from netaddr import * - --------------------------------- -Adding and removing set elements --------------------------------- - ->>> s1 = IPSet(['10.0.0.0/25']) - -This hits a special case in IPSet._compact_single_network() ->>> s1.add('10.0.0.0/24') ->>> s1 -IPSet(['10.0.0.0/24']) - -Various places must also accept integers. ->>> integer1 = int(IPAddress('10.0.0.1')) ->>> integer2 = int(IPAddress('fe80::')) ->>> integer3 = int(IPAddress('10.0.0.2')) ->>> s2 = IPSet([integer1, integer2]) ->>> s2 -IPSet(['10.0.0.1/32', 'fe80::/128']) ->>> s2.add(integer3) ->>> s2 -IPSet(['10.0.0.1/32', '10.0.0.2/32', 'fe80::/128']) ->>> s2.remove(integer2) ->>> s2 -IPSet(['10.0.0.1/32', '10.0.0.2/32']) ->>> s2.update([integer2]) ->>> s2 -IPSet(['10.0.0.1/32', '10.0.0.2/32', 'fe80::/128']) - ------------------------------- -Combined IPv4 and IPv6 support ------------------------------- - -In keeping with netaddr's pragmatic approach, you are free to mix and match IPv4 and IPv6 within the same data structure. - ->>> s1 = IPSet(['192.0.2.0', '::192.0.2.0', '192.0.2.2', '::192.0.2.2']) ->>> s2 = IPSet(['192.0.2.2', '::192.0.2.2', '192.0.2.4', '::192.0.2.4']) - -IPSets with IPNetworks that need to be merged or split (sometimes multiple times) during various set operations. -IPNetwork('10.0.0.64/30') is the same as IPRange('10.0.0.64', '10.0.0.67') ->>> s3 = IPSet(['0.0.0.1', '10.0.0.64/30', '255.255.255.1']) ->>> s4 = IPSet(['10.0.0.64', '10.0.0.66']) ->>> s4b = IPSet(['10.0.0.64', '10.0.0.66', '111.111.111.111']) ->>> s5 = IPSet(['10.0.0.65', '10.0.0.67']) - -The documentation show various "s1 s2" examples. Tests below check that "s2 s1" also works. Additionally, operations on s3, s4... are performed. - -IPSets must be usable in boolean context, even when they are very large. ->>> s6 = IPSet(['2405:8100::/32']) ->>> bool(s6) -True ->>> bool(IPSet()) -False - -^^^^^^^^^^^^^^^^ -set intersection -^^^^^^^^^^^^^^^^ ->>> s2 & s1 -IPSet(['192.0.2.2/32', '::192.0.2.2/128']) - ->>> s3 & s4 -IPSet(['10.0.0.64/32', '10.0.0.66/32']) ->>> s4 & s3 -IPSet(['10.0.0.64/32', '10.0.0.66/32']) - ->>> s3 & s5 -IPSet(['10.0.0.65/32', '10.0.0.67/32']) ->>> s5 & s3 -IPSet(['10.0.0.65/32', '10.0.0.67/32']) - -^^^^^^^^^^^^^^ -set difference -^^^^^^^^^^^^^^ - ->>> s3 - s4 -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) ->>> s4 - s3 -IPSet([]) ->>> s3 - s4b -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) - ->>> s3 - s5 -IPSet(['0.0.0.1/32', '10.0.0.64/32', '10.0.0.66/32', '255.255.255.1/32']) ->>> s5 - s3 -IPSet([]) - - -^^^^^^^^^^^^^^^^^^^^^^^^ -set symmetric difference -^^^^^^^^^^^^^^^^^^^^^^^^ - ->>> s2 ^ s1 -IPSet(['192.0.2.0/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.4/128']) - ->>> IPSet([]) ^ IPSet([]) -IPSet([]) ->>> IPSet(['0.0.0.1/32']) ^ IPSet([]) -IPSet(['0.0.0.1/32']) ->>> IPSet(['0.0.0.1/32']) ^ IPSet(['0.0.0.1/32']) -IPSet([]) - ->>> s3 ^ s4 -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) ->>> s4 ^ s3 -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) ->>> s3 ^ s4b -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '111.111.111.111/32', '255.255.255.1/32']) - ->>> s3 ^ s5 -IPSet(['0.0.0.1/32', '10.0.0.64/32', '10.0.0.66/32', '255.255.255.1/32']) ->>> s5 ^ s3 -IPSet(['0.0.0.1/32', '10.0.0.64/32', '10.0.0.66/32', '255.255.255.1/32']) - --------------------------------- -Convert an IP set to an IP Range --------------------------------- ->>> list(IPSet().iter_ipranges()) -[] - ->>> list(IPSet([IPAddress('10.0.0.1')]).iter_ipranges()) -[IPRange('10.0.0.1', '10.0.0.1')] - -Adjacent, non-mergable CIDRs must be merged by iter_ipranges(). ->>> list(IPSet([IPAddress('10.0.0.1'), IPAddress('10.0.0.2')]).iter_ipranges()) -[IPRange('10.0.0.1', '10.0.0.2')] - -IPv4 and IPv6 addresses must not be merged. ->>> list(IPSet([IPAddress(1, 4), IPAddress(1, 6)]).iter_ipranges()) -[IPRange('0.0.0.1', '0.0.0.1'), IPRange('::1', '::1')] - -len() fails when the IPSet is longer than sys.maxint, which is quite likely with IPv6. ->>> from netaddr.compat import _sys_maxint ->>> s = IPSet(IPRange(IPAddress("::0"), IPAddress(_sys_maxint, 6))) ->>> len(s) -Traceback (most recent call last): - File "", line 1, in - ... -IndexError: range contains more than ... - ->>> s = IPSet(IPRange(IPAddress("::0"), IPAddress(_sys_maxint - 1, 6))) ->>> len(s) == _sys_maxint -True - ------------------- -Various exceptions ------------------- - ->>> s1 = IPSet(['10.0.0.1']) - ->>> hash(s1) -Traceback (most recent call last): -TypeError: IP sets are unhashable! - ->>> s1.update(42) -Traceback (most recent call last): -TypeError: an iterable was expected! - -In the following cases, the exceptions are caught and translated to booleans. ->>> s1 == 42 -False ->>> s1 != 42 -True - diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/socket_fallback.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/socket_fallback.txt deleted file mode 100644 index a5e71174d5..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/socket_fallback.txt +++ /dev/null @@ -1,88 +0,0 @@ -=Socket Fallback Module Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.fbsocket import * - -}}} - -IPv6 '::' compression algorithm tests. - -{{{ - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:0:0:0:0:0')) -'::' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:0:0:0:0:A')) -'::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:0:0:0:0:0')) -'a::' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:A:0:0:0:0:0')) -'a:0:a::' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:0:0:0:0:A')) -'a::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:A:0:0:0:0:0:A')) -'0:a::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:A:0:0:0:0:A')) -'a:0:a::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:A:0:0:0:A')) -'::a:0:0:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:0:A:0:0:A')) -'::a:0:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:0:0:A:0:A')) -'a::a:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:A:0:0:A:0')) -'a::a:0:0:a:0' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:A:0:A:0:A:0')) -'a:0:a:0:a:0:a:0' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:A:0:A:0:A:0:A')) -'0:a:0:a:0:a:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '1080:0:0:0:8:800:200C:417A')) -'1080::8:800:200c:417a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210')) -'fedc:ba98:7654:3210:fedc:ba98:7654:3210' - -}}} - -IPv4 failure tests - -{{{ - ->>> inet_ntoa(1) -Traceback (most recent call last): -... -TypeError: string type expected, not - - ->>> inet_ntoa('\x00') -Traceback (most recent call last): -... -ValueError: invalid length of packed IP address string - -}}} - -IPv6 failure tests. - -{{{ - ->>> inet_pton(AF_INET6, '::0x07f') -Traceback (most recent call last): -... -ValueError: illegal IP address string '::0x07f' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/subnet.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/subnet.txt deleted file mode 100644 index b9a4c7cf06..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/subnet.txt +++ /dev/null @@ -1,108 +0,0 @@ -=IP Subnet Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Incrementing IP objects. - -{{{ - ->>> ip = IPNetwork('192.0.2.0/28') ->>> for i in range(16): -... str(ip) -... ip += 1 -'192.0.2.0/28' -'192.0.2.16/28' -'192.0.2.32/28' -'192.0.2.48/28' -'192.0.2.64/28' -'192.0.2.80/28' -'192.0.2.96/28' -'192.0.2.112/28' -'192.0.2.128/28' -'192.0.2.144/28' -'192.0.2.160/28' -'192.0.2.176/28' -'192.0.2.192/28' -'192.0.2.208/28' -'192.0.2.224/28' -'192.0.2.240/28' - ->>> ip = IPNetwork('2001:470:1f04::/48') ->>> for i in ip.subnet(128): -... print i -... break -2001:470:1f04::/128 - -}}} - -IP address and subnet sortability. - -{{{ - ->>> ip_list = [] - ->>> for subnet in IPNetwork('192.0.2.0/24').subnet(28, 3): -... ip_list.append(subnet) -... ip_list.extend([ip for ip in subnet]) - ->>> for addr in sorted(ip_list): -... print '%r' % addr -IPNetwork('192.0.2.0/28') -IPAddress('192.0.2.0') -IPAddress('192.0.2.1') -IPAddress('192.0.2.2') -IPAddress('192.0.2.3') -IPAddress('192.0.2.4') -IPAddress('192.0.2.5') -IPAddress('192.0.2.6') -IPAddress('192.0.2.7') -IPAddress('192.0.2.8') -IPAddress('192.0.2.9') -IPAddress('192.0.2.10') -IPAddress('192.0.2.11') -IPAddress('192.0.2.12') -IPAddress('192.0.2.13') -IPAddress('192.0.2.14') -IPAddress('192.0.2.15') -IPNetwork('192.0.2.16/28') -IPAddress('192.0.2.16') -IPAddress('192.0.2.17') -IPAddress('192.0.2.18') -IPAddress('192.0.2.19') -IPAddress('192.0.2.20') -IPAddress('192.0.2.21') -IPAddress('192.0.2.22') -IPAddress('192.0.2.23') -IPAddress('192.0.2.24') -IPAddress('192.0.2.25') -IPAddress('192.0.2.26') -IPAddress('192.0.2.27') -IPAddress('192.0.2.28') -IPAddress('192.0.2.29') -IPAddress('192.0.2.30') -IPAddress('192.0.2.31') -IPNetwork('192.0.2.32/28') -IPAddress('192.0.2.32') -IPAddress('192.0.2.33') -IPAddress('192.0.2.34') -IPAddress('192.0.2.35') -IPAddress('192.0.2.36') -IPAddress('192.0.2.37') -IPAddress('192.0.2.38') -IPAddress('192.0.2.39') -IPAddress('192.0.2.40') -IPAddress('192.0.2.41') -IPAddress('192.0.2.42') -IPAddress('192.0.2.43') -IPAddress('192.0.2.44') -IPAddress('192.0.2.45') -IPAddress('192.0.2.46') -IPAddress('192.0.2.47') - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/ip/tutorial.txt b/awx/lib/site-packages/netaddr/tests/2.x/ip/tutorial.txt deleted file mode 100644 index 381e922f0b..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/ip/tutorial.txt +++ /dev/null @@ -1,743 +0,0 @@ -First of all you need to pull the various netaddr classes and functions into your namespace. - -.. note:: Do this for the purpose of this tutorial only. In your own code, you should be explicit about the classes, functions and constants you import to avoid name clashes. - ->>> from netaddr import * - -We also import the standard library module `pprint` to help format our output. - ->>> import pprint - ----------------- -Basic operations ----------------- - -The following `IPAddress` object represents a single IP address. - ->>> ip = IPAddress('192.0.2.1') ->>> ip.version -4 - -The `repr()` call returns a Python statement that can be used to reconstruct an equivalent IP address object state from scratch when run in the Python interpreter. - ->>> repr(ip) -"IPAddress('192.0.2.1')" ->>> ip -IPAddress('192.0.2.1') - -Access in the string context returns the IP object as a string value. - ->>> str(ip) -'192.0.2.1' ->>> '%s' % ip -'192.0.2.1' ->>> ip.format() # only really useful for IPv6 addresses. -'192.0.2.1' - ------------------------- -Numerical representation ------------------------- - -You can view an IP address in various other formats. - ->>> int(ip) == 3221225985 -True ->>> hex(ip) -'0xc0000201' ->>> ip.bin -'0b11000000000000000000001000000001' ->>> ip.bits() -'11000000.00000000.00000010.00000001' ->>> ip.words == (192, 0, 2, 1) -True - ---------------------------------- -Representing networks and subnets ---------------------------------- - -`IPNetwork` objects are used to represent subnets, networks or VLANs that accept CIDR prefixes and netmasks. - ->>> ip = IPNetwork('192.0.2.1') ->>> ip.ip -IPAddress('192.0.2.1') ->>> ip.network, ip.broadcast -(IPAddress('192.0.2.1'), IPAddress('192.0.2.1')) ->>> ip.netmask, ip.hostmask -(IPAddress('255.255.255.255'), IPAddress('0.0.0.0')) ->>> ip.size -1 - -In this case, the network and broadcast address are the same, akin to a host route. - ->>> ip = IPNetwork('192.0.2.0/24') ->>> ip.ip -IPAddress('192.0.2.0') ->>> ip.network, ip.broadcast -(IPAddress('192.0.2.0'), IPAddress('192.0.2.255')) ->>> ip.netmask, ip.hostmask -(IPAddress('255.255.255.0'), IPAddress('0.0.0.255')) ->>> ip.size -256 - -And finally, this IPNetwork object represents an IP address that belongs to a given IP subnet. - ->>> ip = IPNetwork('192.0.3.112/22') ->>> ip.ip -IPAddress('192.0.3.112') ->>> ip.network, ip.broadcast -(IPAddress('192.0.0.0'), IPAddress('192.0.3.255')) ->>> ip.netmask, ip.hostmask -(IPAddress('255.255.252.0'), IPAddress('0.0.3.255')) ->>> ip.size -1024 - -Internally, each IPNetwork object only stores 3 values :- - - * the IP address value as an unsigned integer - * a reference to the IP protocol module for the IP version being represented - * the CIDR prefix bitmask - -All the other values are calculated on-the-fly on access. - -It is possible to adjust the IP address value and the CIDR prefix after object instantiation. - ->>> ip = IPNetwork('0.0.0.0/0') ->>> ip -IPNetwork('0.0.0.0/0') ->>> ip.value = 3221225985 ->>> ip -IPNetwork('192.0.2.1/0') ->>> ip.prefixlen -0 ->>> ip.prefixlen = 23 ->>> ip -IPNetwork('192.0.2.1/23') - -There is also a property that lets you access the *true* CIDR address which removes all host bits from the network address based on the CIDR subnet prefix. - ->>> ip.cidr -IPNetwork('192.0.2.0/23') - -This is handy for specifying some networking configurations correctly. - -If you want to access information about each of the various IP addresses that form the IP subnet, this is available by performing pass through calls to sub methods of each `IPAddress` object. - -For example if you want to see a binary digit representation of each address you can do the following. - ->>> ip.ip.bits() -'11000000.00000000.00000010.00000001' ->>> ip.network.bits() -'11000000.00000000.00000010.00000000' ->>> ip.netmask.bits() -'11111111.11111111.11111110.00000000' ->>> ip.broadcast.bits() -'11000000.00000000.00000011.11111111' - ------------- -IPv6 support ------------- - -Full support for IPv6 is provided. Let's try a few examples: - ->>> ip = IPAddress(0, 6) ->>> ip -IPAddress('::') ->>> ip = IPNetwork('fe80::dead:beef/64') ->>> str(ip), ip.prefixlen, ip.version -('fe80::dead:beef/64', 64, 6) ->>> int(ip.ip) == 338288524927261089654018896845083623151 -True ->>> hex(ip.ip) -'0xfe8000000000000000000000deadbeef' - -Bit-style output isn't as quite as friendly as hexadecimal for such a long numbers, but here the proof that it works! - ->>> ip.ip.bits() -'1111111010000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:1101111010101101:1011111011101111' - -Here are some networking details for an IPv6 subnet. - ->>> ip.network, ip.broadcast, ip.netmask, ip.hostmask -(IPAddress('fe80::'), IPAddress('fe80::ffff:ffff:ffff:ffff'), IPAddress('ffff:ffff:ffff:ffff::'), IPAddress('::ffff:ffff:ffff:ffff')) - --------------------------------------- -Interoperability between IPv4 and IPv6 --------------------------------------- - -It is likely that with IPv6 becoming more prevalent, you'll want to be able to interoperate between IPv4 and IPv6 address seemlessly. - -Here are a couple of methods that help achieve this. - -^^^^^^^^^^^^^^^^^^^^^^^ -IPv4 to IPv6 conversion -^^^^^^^^^^^^^^^^^^^^^^^ - ->>> IPAddress('192.0.2.15').ipv4() -IPAddress('192.0.2.15') ->>> ip = IPAddress('192.0.2.15').ipv6() ->>> ip -IPAddress('::ffff:192.0.2.15') ->>> ip.is_ipv4_mapped() -True ->>> ip.is_ipv4_compat() -False - ->>> IPAddress('192.0.2.15').ipv6(ipv4_compatible=True) -IPAddress('::192.0.2.15') ->>> IPAddress('192.0.2.15').ipv6(ipv4_compatible=True).is_ipv4_compat() -True ->>> IPAddress('192.0.2.15').ipv6(True) -IPAddress('::192.0.2.15') ->>> ip = IPNetwork('192.0.2.1/23') ->>> ip.ipv4() -IPNetwork('192.0.2.1/23') ->>> ip.ipv6() -IPNetwork('::ffff:192.0.2.1/119') ->>> ip.ipv6(ipv4_compatible=True) -IPNetwork('::192.0.2.1/119') - -^^^^^^^^^^^^^^^^^^^^^^^ -IPv6 to IPv4 conversion -^^^^^^^^^^^^^^^^^^^^^^^ - ->>> IPNetwork('::ffff:192.0.2.1/119').ipv6() -IPNetwork('::ffff:192.0.2.1/119') ->>> IPNetwork('::ffff:192.0.2.1/119').ipv6(ipv4_compatible=True) -IPNetwork('::192.0.2.1/119') ->>> IPNetwork('::ffff:192.0.2.1/119').ipv4() -IPNetwork('192.0.2.1/23') ->>> IPNetwork('::192.0.2.1/119').ipv4() -IPNetwork('192.0.2.1/23') - -Note that the IP object returns IPv4 "mapped" addresses by default in preference to IPv4 "compatible" ones. This has been chosen purposefully as the latter form has been deprecated (see RFC 4291 for details). - ---------------- -List operations ---------------- - -If you treat an `IPNetwork` object as if it were a standard Python list object it will give you access to a list of individual IP address objects. This of course is illusory and they are not created until you access them. - ->>> ip = IPNetwork('192.0.2.16/29') - -Accessing an IP object using the `list()` context invokes the default generator which returns a list of all IP objects in the range specified by the IP object's subnet. - ->>> ip_list = list(ip) ->>> len(ip_list) -8 ->>> ip_list -[IPAddress('192.0.2.16'), IPAddress('192.0.2.17'), ..., IPAddress('192.0.2.22'), IPAddress('192.0.2.23')] - -The length of that list is 8 individual IP addresses. - ->>> len(ip) -8 - -^^^^^^^^ -Indexing -^^^^^^^^ - -You can use standard index access to IP addresses in the subnet. - ->>> ip[0] -IPAddress('192.0.2.16') ->>> ip[1] -IPAddress('192.0.2.17') ->>> ip[-1] -IPAddress('192.0.2.23') - -^^^^^^^ -Slicing -^^^^^^^ - -You can also use list slices on IP addresses in the subnet. - ->>> ip[0:4] - - -The slice is a generator function. This was done to save time and system resources as some slices can end up being very large for certain subnets! - -Here is how you'd access all elements in a slice. - ->>> list(ip[0:4]) -[IPAddress('192.0.2.16'), IPAddress('192.0.2.17'), IPAddress('192.0.2.18'), IPAddress('192.0.2.19')] - -Extended slicing is also supported. - ->>> list(ip[0::2]) -[IPAddress('192.0.2.16'), IPAddress('192.0.2.18'), IPAddress('192.0.2.20'), IPAddress('192.0.2.22')] - -List reversal. - ->>> list(ip[-1::-1]) -[IPAddress('192.0.2.23'), IPAddress('192.0.2.22'), ..., IPAddress('192.0.2.17'), IPAddress('192.0.2.16')] - -Use of generators ensures working with large IP subnets is efficient. - ->>> for ip in IPNetwork('192.0.2.0/23'): -... print '%s' % ip -... -192.0.2.0 -192.0.2.1 -192.0.2.2 -192.0.2.3 -... -192.0.3.252 -192.0.3.253 -192.0.3.254 -192.0.3.255 - -In IPv4 networks you only usually assign the addresses between the network and broadcast addresses to actual host interfaces on systems. - -Here is the iterator provided for accessing these IP addresses :- - ->>> for ip in IPNetwork('192.0.2.0/23').iter_hosts(): -... print '%s' % ip -... -192.0.2.1 -192.0.2.2 -192.0.2.3 -192.0.2.4 -... -192.0.3.251 -192.0.3.252 -192.0.3.253 -192.0.3.254 - ---------------------------------- -Sorting IP addresses and networks ---------------------------------- - -It is fairly common and useful to be able to sort IP addresses and networks canonically. - -Here is how sorting works with individual addresses. - ->>> import random ->>> ip_list = list(IPNetwork('192.0.2.128/28')) ->>> random.shuffle(ip_list) ->>> sorted(ip_list) -[IPAddress('192.0.2.128'), IPAddress('192.0.2.129'), ..., IPAddress('192.0.2.142'), IPAddress('192.0.2.143')] - -For convenience, you are able to sort IP subnets at the same time as addresses and they can be combinations of IPv4 and IPv6 addresses at the same time as well (IPv4 addresses and network appear before IPv6 ones). - ->>> ip_list = [ -... IPAddress('192.0.2.130'), -... IPAddress('10.0.0.1'), -... IPNetwork('192.0.2.128/28'), -... IPNetwork('192.0.3.0/24'), -... IPNetwork('192.0.2.0/24'), -... IPNetwork('fe80::/64'), -... IPAddress('::'), -... IPNetwork('172.24/12')] ->>> random.shuffle(ip_list) ->>> ip_list.sort() ->>> pprint.pprint(ip_list) -[IPAddress('10.0.0.1'), - IPNetwork('172.24.0.0/12'), - IPNetwork('192.0.2.0/24'), - IPNetwork('192.0.2.128/28'), - IPAddress('192.0.2.130'), - IPNetwork('192.0.3.0/24'), - IPAddress('::'), - IPNetwork('fe80::/64')] - -Notice how overlapping subnets also sort in order from largest to smallest. - ------------------------------------------ -Summarizing list of addresses and subnets ------------------------------------------ - -Another useful operation is the ability to summarize groups of IP subnets and addresses, merging them together where possible to create the smallest possible list of CIDR subnets. - -You do this in netaddr using the `cidr_merge()` function. - -First we create a list of IP objects that contains a good mix of individual addresses and subnets, along with some string based IP address values for good measure. To make things more interesting some IPv6 addresses are thrown in as well. - ->>> ip_list = [ip for ip in IPNetwork('fe80::/120')] ->>> ip_list.append(IPNetwork('192.0.2.0/24')) ->>> ip_list.extend([str(ip) for ip in IPNetwork('192.0.3.0/24')]) ->>> ip_list.append(IPNetwork('192.0.4.0/25')) ->>> ip_list.append(IPNetwork('192.0.4.128/25')) ->>> len(ip_list) -515 ->>> cidr_merge(ip_list) -[IPNetwork('192.0.2.0/23'), IPNetwork('192.0.4.0/24'), IPNetwork('fe80::/120')] - -Useful isn't it? - ---------------------- -Supernets and subnets ---------------------- - -It is quite common to have a large CIDR subnet that you may want to split up into multiple smaller component blocks to better manage your network allocations, firewall rules etcc and netaddr gives you the tools required to do this. - -Here we take a large /16 private class B network block and split it up into a set of smaller 512 sized blocks. - ->>> ip = IPNetwork('172.24.0.0/16') ->>> ip.subnet(23) - - -Once again, this method produces and iterator because of the possibility for a large number of return values depending on this subnet size specified. - ->>> subnets = list(ip.subnet(23)) ->>> len(subnets) -128 ->>> subnets -[IPNetwork('172.24.0.0/23'), IPNetwork('172.24.2.0/23'), IPNetwork('172.24.4.0/23'), ..., IPNetwork('172.24.250.0/23'), IPNetwork('172.24.252.0/23'), IPNetwork('172.24.254.0/23')] - -It is also possible to retrieve the list of supernets that a given IP address or subnet belongs to. You can also specify an optional limit. - ->>> ip = IPNetwork('192.0.2.114') ->>> supernets = ip.supernet(22) ->>> pprint.pprint(supernets) -[IPNetwork('192.0.0.0/22'), - IPNetwork('192.0.2.0/23'), - IPNetwork('192.0.2.0/24'), - IPNetwork('192.0.2.0/25'), - IPNetwork('192.0.2.64/26'), - IPNetwork('192.0.2.96/27'), - IPNetwork('192.0.2.112/28'), - IPNetwork('192.0.2.112/29'), - IPNetwork('192.0.2.112/30'), - IPNetwork('192.0.2.114/31')] - -Here, we return a list rather than a generator because the potential list of values is of a predictable size (no more than 31 subnets for an IPv4 address and 127 for IPv6). - ---------------------------------------- -Support for non-standard address ranges ---------------------------------------- - -While CIDR is a useful way to describe networks succinctly, it is often necessary (particularly with IPv4 which predates the CIDR specification) to be able to generate lists of IP addresses that have an arbitrary start and end address that do not fall on strict bit mask boundaries. - -The `iter_iprange()` function allow you to do just this. - ->>> ip_list = list(iter_iprange('192.0.2.1', '192.0.2.14')) ->>> len(ip_list) -14 ->>> ip_list -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), ..., IPAddress('192.0.2.13'), IPAddress('192.0.2.14')] - -It is equally nice to know what the actual list of CIDR subnets is that would correctly cover this non-aligned range of addresses. - -Here `cidr_merge()` comes to the rescue once more. - ->>> cidr_merge(ip_list) -[IPNetwork('192.0.2.1/32'), IPNetwork('192.0.2.2/31'), IPNetwork('192.0.2.4/30'), IPNetwork('192.0.2.8/30'), IPNetwork('192.0.2.12/31'), IPNetwork('192.0.2.14/32')] - --------------------------------------------- -Dealing with older IP network specifications --------------------------------------------- - -Until the advent of the CIDR specification it was common to infer the netmask of an IPv4 address based on its first octet using an set of classful rules (first defined in RFC 791). - -You frequently come across reference to them in various RFCs and they are well supported by a number of software libraries. For completeness, rather than leave out this important (but now somewhat historical) set of rules, they are supported via the cryptically named `cidr_abbrev_to_verbose()` function. - -Here is an example of these rules for the whole of the IPv4 address space. - ->>> cidrs = [cidr_abbrev_to_verbose(octet) for octet in range(0, 256)] ->>> pprint.pprint(cidrs) -['0.0.0.0/8', -... - '127.0.0.0/8', - '128.0.0.0/16', -... - '191.0.0.0/16', - '192.0.0.0/24', -... - '223.0.0.0/24', - '224.0.0.0/4', -... - '239.0.0.0/4', - '240.0.0.0/32', -... - '255.0.0.0/32'] ->>> len(cidrs) -256 - -------------------------- -IP address categorisation -------------------------- - -IP addresses fall into several categories, not all of which are suitable for assignment as host addresses. - -^^^^^^^ -Unicast -^^^^^^^ - ->>> IPAddress('192.0.2.1').is_unicast() -True ->>> IPAddress('fe80::1').is_unicast() -True - -^^^^^^^^^ -Multicast -^^^^^^^^^ - -Used to indentify multicast groups (see RFC 2365 and 3171 for more info). - ->>> IPAddress('239.192.0.1').is_multicast() -True ->>> IPAddress('ff00::1').is_multicast() -True - -^^^^^^^ -Private -^^^^^^^ - -Found on intranets and used behind NAT routers. - ->>> IPAddress('172.24.0.1').is_private() -True ->>> IPAddress('10.0.0.1').is_private() -True ->>> IPAddress('192.168.0.1').is_private() -True ->>> IPAddress('fc00::1').is_private() -True - -^^^^^^^^ -Reserved -^^^^^^^^ - -Addresses in reserved ranges are not available for general use. - ->>> IPAddress('253.0.0.1').is_reserved() -True - -^^^^^^ -Public -^^^^^^ - -Addresses accessible via the Internet. - -.. note:: circa the end of 2011 all IPv4 addresses had been allocated to the Regional Internet Registrars. A booming after market in IPv4 addresses has started. There is still plenty of life left in this protocol version yet :) - ->>> ip = IPAddress('62.125.24.5') ->>> ip.is_unicast() and not ip.is_private() -True - -^^^^^^^^ -Netmasks -^^^^^^^^ - -A bitmask used to divide an IP address into its network address and host address. - ->>> IPAddress('255.255.254.0').is_netmask() -True - -^^^^^^^^^ -Hostmasks -^^^^^^^^^ - -Similar to a netmask but with the all the bits flipped the opposite way. - ->>> IPAddress('0.0.1.255').is_hostmask() -True - -^^^^^^^^ -Loopback -^^^^^^^^ - -These addresses are used internally within an IP network stack and packets sent to these addresses are not distributed via a physical network connection. - ->>> IPAddress('127.0.0.1').is_loopback() -True ->>> IPAddress('::1').is_loopback() -True - ----------------------- -Comparing IP addresses ----------------------- - -`IPAddress` objects can be compared with each other. As an `IPAddress` object can represent both an individual IP address and an implicit network, it pays to get both sides of your comparison into the same terms before you compare them to avoid odd results. - -Here are some comparisons of individual IP address to get the ball rolling. - ->>> IPAddress('192.0.2.1') == IPAddress('192.0.2.1') -True ->>> IPAddress('192.0.2.1') < IPAddress('192.0.2.2') -True ->>> IPAddress('192.0.2.2') > IPAddress('192.0.2.1') -True ->>> IPAddress('192.0.2.1') != IPAddress('192.0.2.1') -False ->>> IPAddress('192.0.2.1') >= IPAddress('192.0.2.1') -True ->>> IPAddress('192.0.2.2') >= IPAddress('192.0.2.1') -True ->>> IPAddress('192.0.2.1') <= IPAddress('192.0.2.1') -True ->>> IPAddress('192.0.2.1') <= IPAddress('192.0.2.2') -True - -Now, lets try something a little more interesting. - ->>> IPNetwork('192.0.2.0/24') == IPNetwork('192.0.2.112/24') -True - -Hmmmmmmmm... looks a bit odd doesn't it? That's because by default, IP objects compare their subnets (or lower and upper boundaries) rather than their individual IP address values. - -The solution to this situation is very simple. Knowing this default behaviour, just be explicit about exactly which portion of each IP object you'd like to compare using pass-through properties. - ->>> IPNetwork('192.0.2.0/24').ip == IPNetwork('192.0.2.112/24').ip -False ->>> IPNetwork('192.0.2.0/24').ip < IPNetwork('192.0.2.112/24').ip -True - -That's more like it. You can also be explicit about comparing networks in this way if you so wish (although it is not strictly necessary). - ->>> IPNetwork('192.0.2.0/24').cidr == IPNetwork('192.0.2.112/24').cidr -True - -Armed with this information here are some examples of network comparisons. - ->>> IPNetwork('192.0.2.0/24') == IPNetwork('192.0.3.0/24') -False ->>> IPNetwork('192.0.2.0/24') < IPNetwork('192.0.3.0/24') -True ->>> IPNetwork('192.0.2.0/24') < IPNetwork('192.0.3.0/24') -True - -This will inevitably raise questions about comparing IPAddress (scalar) objects and IPNetwork (vector) objects with each other (or at least it should). - -Here is how netaddr chooses to address this situation. - ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32') -False ->>> IPAddress('192.0.2.0') != IPNetwork('192.0.2.0/32') -True - -An IP network or subnet is different from an individual IP address and therefore cannot be (directly) compared. - -If you want to compare them successfully, you must be explicit about which aspect of the IP network you wish to match against the IP address in question. - -You can use the index of the first or last address if it is a /32 like so :- - ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32')[0] -True ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32')[-1] -True ->>> IPAddress('192.0.2.0') != IPNetwork('192.0.2.0/32')[0] -False - -You can also use the base address if this is what you wish to compare :- - ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32').ip -True ->>> IPAddress('192.0.2.0') != IPNetwork('192.0.2.0/32').ip -False - -While this may seem a bit pointless at first, netaddr strives to keep IP addresses and network separate from one another while still allowing reasonable interoperability. - ------------ -DNS support ------------ - -It is a common administrative task to generate reverse IP lookups for DNS. This is particularly arduous for IPv6 addresses. - -Here is how you do this using an IPAddress object's `reverse_dns()` method. - ->>> IPAddress('172.24.0.13').reverse_dns -'13.0.24.172.in-addr.arpa.' ->>> IPAddress('fe80::feeb:daed').reverse_dns -'d.e.a.d.b.e.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.' - -Note that ``ip6.int`` is not used as this has been deprecated (see RFC 3152 for details). - ---------------------------- -Non standard address ranges ---------------------------- - -As CIDR is a relative newcomer given the long history of IP version 4 you are quite likely to come across systems and documentation which make reference to IP address ranges in formats other than CIDR. Converting from these arbitrary range types to CIDR and back again isn't a particularly fun task. Fortunately, netaddr tries to make this job easy for you with two purpose built classes. - -^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Arbitrary IP address ranges -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can represent an arbitrary IP address range using a lower and upper bound address in the form of an IPRange object. - ->>> r1 = IPRange('192.0.2.1', '192.0.2.15') ->>> r1 -IPRange('192.0.2.1', '192.0.2.15') - -You can iterate across and index these ranges just like and IPNetwork object. - -Importantly, you can also convert it to it's CIDR equivalent. - ->>> r1.cidrs() -[IPNetwork('192.0.2.1/32'), IPNetwork('192.0.2.2/31'), IPNetwork('192.0.2.4/30'), IPNetwork('192.0.2.8/29')] - -Here is how individual IPRange and IPNetwork compare. - ->>> IPRange('192.0.2.0', '192.0.2.255') != IPNetwork('192.0.2.0/24') -False ->>> IPRange('192.0.2.0', '192.0.2.255') == IPNetwork('192.0.2.0/24') -True - -You may wish to compare an IP range against a list of IPAddress and IPNetwork -objects. - ->>> r1 = IPRange('192.0.2.1', '192.0.2.15') ->>> addrs = list(r1) ->>> addrs -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3'), IPAddress('192.0.2.4'), IPAddress('192.0.2.5'), IPAddress('192.0.2.6'), IPAddress('192.0.2.7'), IPAddress('192.0.2.8'), IPAddress('192.0.2.9'), IPAddress('192.0.2.10'), IPAddress('192.0.2.11'), IPAddress('192.0.2.12'), IPAddress('192.0.2.13'), IPAddress('192.0.2.14'), IPAddress('192.0.2.15')] ->>> r1 == addrs -False - -Oops! Not quite what we were looking for or expecting. - -The way to do this is to get either side of the comparison operation into the same terms. - ->>> list(r1) == addrs -True - -That's more like it. - -The same goes for IPNetwork objects. - ->>> subnets = r1.cidrs() ->>> subnets -[IPNetwork('192.0.2.1/32'), IPNetwork('192.0.2.2/31'), IPNetwork('192.0.2.4/30'), IPNetwork('192.0.2.8/29')] ->>> r1 == subnets -False ->>> r1.cidrs() == subnets -True - -The above works if the list you are comparing contains one type or the other, but what if you have a mixed list of `IPAddress`, `IPNetwork` and string addresses? - -Time for some slightly more powerful operations. Let's make use of a new class for dealing with groups of IP addresses and subnets. The IPSet class. - ->>> ips = [IPAddress('192.0.2.1'), '192.0.2.2/31', IPNetwork('192.0.2.4/31'), IPAddress('192.0.2.6'), IPAddress('192.0.2.7'), '192.0.2.8', '192.0.2.9', IPAddress('192.0.2.10'), IPAddress('192.0.2.11'), IPNetwork('192.0.2.12/30')] ->>> s1 = IPSet(r1.cidrs()) ->>> s2 = IPSet(ips) ->>> s2 -IPSet(['192.0.2.1/32', '192.0.2.2/31', '192.0.2.4/30', '192.0.2.8/29']) ->>> s1 == s2 -True - -Let's remove one of the element from one of the IPSet objects and see what happens. - ->>> s2.pop() -IPNetwork('192.0.2.4/30') ->>> s1 == s2 -False - -This is perhaps a somewhat contrived example but it just shows you some of the capabilities on offer. - -See the IPSet tutorial :doc:`tutorial_03` for more details on that class. - -^^^^^^^^^^^^^^ -IP Glob ranges -^^^^^^^^^^^^^^ - -netaddr also supports a user friendly form of specifying IP address ranges using a "glob" style syntax. - -.. note:: At present only IPv4 globs are supported. - ->>> IPGlob('192.0.2.*') == IPNetwork('192.0.2.0/24') -True - -IPGlob('192.0.2.*') != IPNetwork('192.0.2.0/24') -False - -As `IPGlob` is a subclass of `IPRange`, all of the same operations apply. - diff --git a/awx/lib/site-packages/netaddr/tests/2.x/strategy/eui48.txt b/awx/lib/site-packages/netaddr/tests/2.x/strategy/eui48.txt deleted file mode 100644 index 5f8e1d6307..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/strategy/eui48.txt +++ /dev/null @@ -1,96 +0,0 @@ -=IEEE EUI-48 Strategy Module= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.strategy.eui48 import * - -}}} - -==Basic Smoke Tests== - -{{{ - ->>> b = '00000000-00001111-00011111-00010010-11100111-00110011' ->>> i = 64945841971 ->>> t = (0x0, 0x0f, 0x1f, 0x12, 0xe7, 0x33) ->>> s = '00-0F-1F-12-E7-33' ->>> p = '\x00\x0f\x1f\x12\xe73' - ->>> bits_to_int(b) == 64945841971 -True - ->>> int_to_bits(i) == b -True - ->>> int_to_str(i) -'00-0F-1F-12-E7-33' - ->>> int_to_words(i) -(0, 15, 31, 18, 231, 51) - ->>> int_to_packed(i) -'\x00\x0f\x1f\x12\xe73' - ->>> str_to_int(s) == 64945841971 -True - ->>> words_to_int(t) == 64945841971 -True - ->>> words_to_int(list(t)) == 64945841971 -True - ->>> packed_to_int(p) == 64945841971 -True - -}}} - -==Smoke Tests With Alternate Dialects== - -{{{ - ->>> b = '00000000:00001111:00011111:00010010:11100111:00110011' ->>> i = 64945841971 ->>> t = (0x0, 0x0f, 0x1f, 0x12, 0xe7, 0x33) ->>> s = '0:f:1f:12:e7:33' ->>> p = '\x00\x0f\x1f\x12\xe73' - ->>> bits_to_int(b, mac_unix) == 64945841971 -True - ->>> int_to_bits(i, mac_unix) == b -True - ->>> int_to_str(i, mac_unix) -'0:f:1f:12:e7:33' - ->>> int_to_str(i, mac_cisco) -'000f.1f12.e733' - ->>> int_to_str(i, mac_unix) -'0:f:1f:12:e7:33' - ->>> int_to_str(i, mac_unix_expanded) -'00:0f:1f:12:e7:33' - ->>> int_to_words(i, mac_unix) -(0, 15, 31, 18, 231, 51) - ->>> int_to_packed(i) -'\x00\x0f\x1f\x12\xe73' - ->>> str_to_int(s) == 64945841971 -True - ->>> words_to_int(t, mac_unix) == 64945841971 -True - ->>> words_to_int(list(t), mac_unix) == 64945841971 -True - ->>> packed_to_int(p) == 64945841971 -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/strategy/ipv4.txt b/awx/lib/site-packages/netaddr/tests/2.x/strategy/ipv4.txt deleted file mode 100644 index bd46fc3a24..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/strategy/ipv4.txt +++ /dev/null @@ -1,130 +0,0 @@ -=IP version 4 Strategy Module= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -Uses TEST-NET references throughout, as described in RFC 3330. - -{{{ - ->>> from netaddr.strategy.ipv4 import * - -}}} - -==Basic Smoke Tests== - -{{{ - ->>> b = '11000000.00000000.00000010.00000001' ->>> i = 3221225985 ->>> t = (192, 0, 2, 1) ->>> s = '192.0.2.1' ->>> p = '\xc0\x00\x02\x01' ->>> bin_val = '0b11000000000000000000001000000001' - ->>> bits_to_int(b) == 3221225985 -True - ->>> int_to_bits(i) -'11000000.00000000.00000010.00000001' - ->>> int_to_str(i) -'192.0.2.1' - ->>> int_to_words(i) == (192, 0, 2, 1) -True - ->>> int_to_packed(i) -'\xc0\x00\x02\x01' - ->>> int_to_bin(i) -'0b11000000000000000000001000000001' - ->>> int_to_bin(i) -'0b11000000000000000000001000000001' - ->>> bin_to_int(bin_val) == 3221225985 -True - ->>> words_to_int(t) == 3221225985 -True - ->>> words_to_int(list(t)) == 3221225985 -True - ->>> packed_to_int(p) == 3221225985 -True - ->>> valid_bin(bin_val) -True - -}}} - -== inet_aton() Behavioural Tests == - -inet_aton() is a very old system call and is very permissive with regard to what is assume is a valid IPv4 address. Unfortunately, it is also the most widely used by system software used in software today, so netaddr supports this behaviour by default. - -{{{ - ->>> str_to_int('127') == 127 -True - ->>> str_to_int('0x7f') == 127 -True - ->>> str_to_int('0177') == 127 -True - ->>> str_to_int('127.1') == 2130706433 -True - ->>> str_to_int('0x7f.1') == 2130706433 -True - ->>> str_to_int('0177.1') == 2130706433 -True - ->>> str_to_int('127.0.0.1') == 2130706433 -True - -}}} - -== inet_pton() Behavioural Tests == - -inet_pton() is a newer system call that supports both IPv4 and IPv6. It is a lot more strict about what it deems to be a valid IPv4 address and doesn't support many of the features found in inet_aton() such as support for non- decimal octets, partial numbers of octets, etc. - -{{{ - ->>> str_to_int('127', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: '127' is not a valid IPv4 address string! - ->>> str_to_int('0x7f', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: '0x7f' is not a valid IPv4 address string! - ->>> str_to_int('0177', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: '0177' is not a valid IPv4 address string! - ->>> str_to_int('127.1', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: '127.1' is not a valid IPv4 address string! - ->>> str_to_int('0x7f.1', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: '0x7f.1' is not a valid IPv4 address string! - ->>> str_to_int('0177.1', flags=INET_PTON) -Traceback (most recent call last): -... -AddrFormatError: '0177.1' is not a valid IPv4 address string! - ->>> str_to_int('127.0.0.1', flags=INET_PTON) == 2130706433 -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/2.x/strategy/ipv6.txt b/awx/lib/site-packages/netaddr/tests/2.x/strategy/ipv6.txt deleted file mode 100644 index 32080f5798..0000000000 --- a/awx/lib/site-packages/netaddr/tests/2.x/strategy/ipv6.txt +++ /dev/null @@ -1,290 +0,0 @@ -=IP version 6 Strategy Module= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.strategy.ipv6 import * - -}}} - -==Basic Smoke Tests== - -{{{ - ->>> b = '0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:1111111111111111:1111111111111110' ->>> i = 4294967294 ->>> t = (0, 0, 0, 0, 0, 0, 0xffff, 0xfffe) ->>> s = '::255.255.255.254' ->>> p = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe' - ->>> bits_to_int(b) == 4294967294 -True - ->>> int_to_bits(i) == b -True - ->>> int_to_str(i) -'::255.255.255.254' - ->>> int_to_words(i) -(0, 0, 0, 0, 0, 0, 65535, 65534) - ->>> int_to_packed(i) -'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe' - ->>> str_to_int(s) == 4294967294 -True - ->>> words_to_int(t) == 4294967294 -True - ->>> words_to_int(list(t)) == 4294967294 -True - ->>> packed_to_int(p) == 4294967294 -True - -}}} - -==More Specific IPv6 Tests== - -IPv6 string address variants that are all equivalent. - -{{{ - ->>> i = 42540766411282592856903984951992014763 ->>> str_to_int('2001:0db8:0000:0000:0000:0000:1428:57ab') == i -True - ->>> str_to_int('2001:0db8:0000:0000:0000::1428:57ab') == i -True - ->>> str_to_int('2001:0db8:0:0:0:0:1428:57ab') == i -True - ->>> str_to_int('2001:0db8:0:0::1428:57ab') == i -True - ->>> str_to_int('2001:0db8::1428:57ab') == i -True - ->>> str_to_int('2001:0DB8:0000:0000:0000:0000:1428:57AB') == i -True - ->>> str_to_int('2001:DB8::1428:57AB') == i -True - -}}} - -Intensive IPv6 string address validation testing. - -Positive tests. - -{{{ - ->>> valid_addrs = ( -... # RFC 4291 -... # Long forms. -... 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', -... '1080:0:0:0:8:800:200C:417A', # a unicast address -... 'FF01:0:0:0:0:0:0:43', # a multicast address -... '0:0:0:0:0:0:0:1', # the loopback address -... '0:0:0:0:0:0:0:0', # the unspecified addresses -... -... # Short forms. -... '1080::8:800:200C:417A', # a unicast address -... 'FF01::43', # a multicast address -... '::1', # the loopback address -... '::', # the unspecified addresses -... -... # IPv4 compatible forms. -... '::192.0.2.1', -... '::ffff:192.0.2.1', -... '0:0:0:0:0:0:192.0.2.1', -... '0:0:0:0:0:FFFF:192.0.2.1', -... '0:0:0:0:0:0:13.1.68.3', -... '0:0:0:0:0:FFFF:129.144.52.38', -... '::13.1.68.3', -... '::FFFF:129.144.52.38', -... -... # Other tests. -... '1::', -... '::ffff', -... 'ffff::', -... 'ffff::ffff', -... '0:1:2:3:4:5:6:7', -... '8:9:a:b:c:d:e:f', -... '0:0:0:0:0:0:0:0', -... 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', -... ) - ->>> for addr in valid_addrs: -... addr, valid_str(addr) -('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', True) -('1080:0:0:0:8:800:200C:417A', True) -('FF01:0:0:0:0:0:0:43', True) -('0:0:0:0:0:0:0:1', True) -('0:0:0:0:0:0:0:0', True) -('1080::8:800:200C:417A', True) -('FF01::43', True) -('::1', True) -('::', True) -('::192.0.2.1', True) -('::ffff:192.0.2.1', True) -('0:0:0:0:0:0:192.0.2.1', True) -('0:0:0:0:0:FFFF:192.0.2.1', True) -('0:0:0:0:0:0:13.1.68.3', True) -('0:0:0:0:0:FFFF:129.144.52.38', True) -('::13.1.68.3', True) -('::FFFF:129.144.52.38', True) -('1::', True) -('::ffff', True) -('ffff::', True) -('ffff::ffff', True) -('0:1:2:3:4:5:6:7', True) -('8:9:a:b:c:d:e:f', True) -('0:0:0:0:0:0:0:0', True) -('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', True) - -}}} - -Negative tests. - -{{{ - ->>> invalid_addrs = ( -... 'g:h:i:j:k:l:m:n', # bad chars. -... '0:0:0:0:0:0:0:0:0' # too long, -... '', # empty string -... # Unexpected types. -... [], -... (), -... {}, -... True, -... False, -... ) - ->>> for addr in invalid_addrs: -... addr, valid_str(addr) -('g:h:i:j:k:l:m:n', False) -('0:0:0:0:0:0:0:0:0', False) -([], False) -((), False) -({}, False) -(True, False) -(False, False) - -}}} - -String compaction tests. - -{{{ - ->>> valid_addrs = { -... # RFC 4291 -... 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210' : 'fedc:ba98:7654:3210:fedc:ba98:7654:3210', -... '1080:0:0:0:8:800:200C:417A' : '1080::8:800:200c:417a', # a unicast address -... 'FF01:0:0:0:0:0:0:43' : 'ff01::43', # a multicast address -... '0:0:0:0:0:0:0:1' : '::1', # the loopback address -... '0:0:0:0:0:0:0:0' : '::', # the unspecified addresses -... } - ->>> for long_form, short_form in valid_addrs.items(): -... int_val = str_to_int(long_form) -... calc_short_form = int_to_str(int_val) -... calc_short_form == short_form -True -True -True -True -True - -}}} - -IPv6 mapped and compatible IPv4 string formatting. - -{{{ - ->>> int_to_str(0xffffff) -'::0.255.255.255' ->>> int_to_str(0xffffffff) -'::255.255.255.255' - ->>> int_to_str(0x1ffffffff) -'::1:ffff:ffff' - ->>> int_to_str(0xffffffffffff) -'::ffff:255.255.255.255' - ->>> int_to_str(0xfffeffffffff) -'::fffe:ffff:ffff' - ->>> int_to_str(0xffffffffffff) -'::ffff:255.255.255.255' - ->>> int_to_str(0xfffffffffff1) -'::ffff:255.255.255.241' - ->>> int_to_str(0xfffffffffffe) -'::ffff:255.255.255.254' - ->>> int_to_str(0xffffffffff00) -'::ffff:255.255.255.0' - ->>> int_to_str(0xffffffff0000) -'::ffff:255.255.0.0' - ->>> int_to_str(0xffffff000000) -'::ffff:255.0.0.0' - ->>> int_to_str(0xffff000000) -'::ff:ff00:0' - ->>> int_to_str(0xffff00000000) -'::ffff:0.0.0.0' - ->>> int_to_str(0x1ffff00000000) -'::1:ffff:0:0' - ->>> int_to_str(0xffff00000000) -'::ffff:0.0.0.0' - -}}} - -== str_to_int() Behavioural Tests (legacy_mode switch) == - -The legacy_mode switch on str_to_int() is for interface compatibility only and should not effect the behaviour of this method whether set to True or False. - -{{{ - ->>> str_to_int('::127') == 295 -True - ->>> str_to_int('::0x7f') -Traceback (most recent call last): -... -AddrFormatError: '::0x7f' is not a valid IPv6 address string! - ->>> str_to_int('::0177') == 375 -True - ->>> str_to_int('::127.1') -Traceback (most recent call last): -... -AddrFormatError: '::127.1' is not a valid IPv6 address string! - ->>> str_to_int('::0x7f.1') -Traceback (most recent call last): -... -AddrFormatError: '::0x7f.1' is not a valid IPv6 address string! - ->>> str_to_int('::0177.1') -Traceback (most recent call last): -... -AddrFormatError: '::0177.1' is not a valid IPv6 address string! - ->>> str_to_int('::127.0.0.1') == 2130706433 -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/core/compat.txt b/awx/lib/site-packages/netaddr/tests/3.x/core/compat.txt deleted file mode 100644 index ed7401293f..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/core/compat.txt +++ /dev/null @@ -1,104 +0,0 @@ -=Python 2.x and 3.x compatibility tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.compat import _sys_maxint, _is_str, _is_int, _callable - ->>> from netaddr.compat import _func_doc, _dict_keys, _dict_items - ->>> from netaddr.compat import _iter_dict_keys, _bytes_join, _zip, _range - ->>> from netaddr.compat import _iter_range, _func_name, _func_doc - -# string and integer detection tests. ->>> _is_int(_sys_maxint) -True - ->>> _is_str(_sys_maxint) -False - ->>> _is_str('') -True - ->>> _is_str(''.encode()) -True - -# byte string join tests. ->>> str_8bit = _bytes_join(['a'.encode(), 'b'.encode(), 'c'.encode()]) - ->>> str_8bit == 'abc'.encode() -True - ->>> "b'abc'" == '%r' % str_8bit -True - -# dict operation tests. ->>> d = { 'a' : 0, 'b' : 1, 'c' : 2 } - ->>> sorted(_dict_keys(d)) == ['a', 'b', 'c'] -True - ->>> sorted(_dict_items(d)) == [('a', 0), ('b', 1), ('c', 2)] -True - -# zip() BIF tests. ->>> l2 = _zip([0], [1]) - ->>> hasattr(_zip(l2), 'pop') -True - ->>> l2 == [(0, 1)] -True - -# range/xrange() tests. ->>> l1 = _range(3) - ->>> isinstance(l1, list) -True - ->>> hasattr(l1, 'pop') -True - ->>> l1 == [0, 1, 2] -True - ->>> it = _iter_range(3) - ->>> isinstance(it, list) -False - ->>> hasattr(it, '__iter__') -True - ->>> it == [0, 1, 2] -False - ->>> list(it) == [0, 1, 2] -True - -# callable() and function meta-data tests. ->>> i = 1 ->>> def f1(): -... """docstring""" -... pass - ->>> f2 = lambda x: x - ->>> _callable(i) -False - ->>> _callable(f1) -True - ->>> _callable(f2) -True - ->>> _func_name(f1) == 'f1' -True - ->>> _func_doc(f1) == 'docstring' -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/core/pubsub.txt b/awx/lib/site-packages/netaddr/tests/3.x/core/pubsub.txt deleted file mode 100644 index 5f55c205ea..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/core/pubsub.txt +++ /dev/null @@ -1,48 +0,0 @@ -=Publish / Subscribe DP Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -Basic Publisher and Subscriber object tests. - -{{{ - ->>> from netaddr.core import Publisher, Subscriber, PrettyPrinter ->>> import pprint - ->>> class Subject(Publisher): -... pass - - ->>> class Observer(Subscriber): -... def __init__(self, id): -... self.id = id -... -... def update(self, data): -... return repr(self), pprint.pformat(data) -... -... def __repr__(self): -... return '%s(%r)' % (self.__class__.__name__, self.id) -... - ->>> s = Subject() - ->>> s.attach(Observer('foo')) ->>> s.attach(Observer('bar')) - -#FIXME: >>> pp = PrettyPrinter() -#FIXME: >>> s.attach(pp) - ->>> data = [{'foo': 42}, {'list': [1,'2', list(range(10))]}, {'strings': ['foo', 'bar', 'baz', 'quux']}] ->>> s.notify(data) - -#FIXME: >>> s.detach(pp) ->>> s.notify(['foo', 'bar', 'baz']) - ->>> s.attach('foo') -Traceback (most recent call last): -... -TypeError: 'foo' does not support required interface! - ->>> s.detach('foo') - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/eui/eui.txt b/awx/lib/site-packages/netaddr/tests/3.x/eui/eui.txt deleted file mode 100644 index 177fffa2b8..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/eui/eui.txt +++ /dev/null @@ -1,380 +0,0 @@ -=IEEE EUI-64 Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -IEEE EUI-64 tests. - -{{{ - ->>> eui = EUI('00-1B-77-FF-FE-49-54-FD') ->>> eui -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> eui.oui -OUI('00-1B-77') - ->>> eui.ei -'FF-FE-49-54-FD' - ->>> eui.eui64() -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> mac = EUI('00-0F-1F-12-E7-33') ->>> ip = mac.ipv6_link_local() ->>> ip -IPAddress('fe80::20f:1fff:fe12:e733') ->>> ip.is_link_local() -True - ->>> mac.eui64() -EUI('00-0F-1F-FF-FE-12-E7-33') - -}}} - -Individual Address Block tests. - -{{{ - ->>> lower_eui = EUI('00-50-C2-05-C0-00') ->>> upper_eui = EUI('00-50-C2-05-CF-FF') - ->>> lower_eui.is_iab() -True - ->>> str(lower_eui.oui) -'00-50-C2' - ->>> str(lower_eui.iab) -'00-50-C2-05-C0-00' - ->>> lower_eui.ei -'05-C0-00' - ->>> int(lower_eui.oui) == 0x0050c2 -True - ->>> int(lower_eui.iab) == 0x0050c205c -True - ->>> upper_eui.is_iab() -True - ->>> str(upper_eui.oui) -'00-50-C2' - ->>> str(upper_eui.iab) -'00-50-C2-05-C0-00' - ->>> upper_eui.ei -'05-CF-FF' - ->>> int(upper_eui.oui) == 0x0050c2 -True - ->>> int(upper_eui.iab) == 0x0050c205c -True - -}}} - -Constructor tests. - -{{{ - ->>> eui = EUI('00-90-96-AF-CC-39') - ->>> eui == EUI('0-90-96-AF-CC-39') -True - ->>> eui == EUI('00-90-96-af-cc-39') -True - ->>> eui == EUI('00:90:96:AF:CC:39') -True - ->>> eui == EUI('00:90:96:af:cc:39') -True - ->>> eui == EUI('0090-96AF-CC39') -True - ->>> eui == EUI('0090:96af:cc39') -True - ->>> eui == EUI('009096-AFCC39') -True - ->>> eui == EUI('009096:AFCC39') -True - ->>> eui == EUI('009096AFCC39') -True - ->>> eui == EUI('009096afcc39') -True - ->>> EUI('01-00-00-00-00-00') == EUI('010000000000') -True - ->>> EUI('01-00-00-00-00-00') == EUI('10000000000') -True - ->>> EUI('01-00-00-01-00-00') == EUI('010000:010000') -True - ->>> EUI('01-00-00-01-00-00') == EUI('10000:10000') -True - -}}} - -EUI-48 and EUI-64 indentifiers of the same value are *not* equivalent. - -{{{ - ->>> eui48 = EUI('01-00-00-01-00-00') ->>> int(eui48) == 1099511693312 -True - ->>> eui64 = EUI('00-00-01-00-00-01-00-00') ->>> int(eui64) == 1099511693312 -True - ->>> eui48 == eui64 -False - -}}} - -Equality check for EUI must support subclassing - -{{{ ->>> eui = EUI(42) ->>> class MySubclass(EUI): pass ->>> my_instance = MySubclass(42) ->>> my_instance2 = MySubclass(43) ->>> class YourSubclass(EUI): pass ->>> your_instance = YourSubclass(42) ->>> your_instance2 = YourSubclass(43) - ->>> eui == my_instance -True - ->>> eui == my_instance2 -False - ->>> my_instance == your_instance -True - ->>> my_instance == your_instance2 -False - ->>> my_instance != your_instance2 -True - -}}} - -Equality check for OUI must support subclassing - -{{{ ->>> oui = OUI('00-1B-77') ->>> class MySubclass(OUI): pass ->>> my_instance = MySubclass('00-1B-77') ->>> my_instance2 = MySubclass('00-1B-78') ->>> class YourSubclass(OUI): pass ->>> your_instance = YourSubclass('00-1B-77') ->>> your_instance2 = YourSubclass('00-1B-78') - ->>> oui == my_instance -True - ->>> oui != my_instance -False - ->>> oui == my_instance2 -False - ->>> oui != my_instance2 -True - ->>> my_instance != your_instance -False - ->>> my_instance == your_instance -True - ->>> my_instance == your_instance2 -False - ->>> my_instance != your_instance2 -True - -}}} - -Equality check for IAB must support subclassing - -{{{ ->>> iab = IAB('00-50-C2-00-00-00') ->>> class MySubclass(IAB): pass ->>> my_instance = MySubclass('00-50-C2-00-00-00') ->>> my_instance2 = MySubclass('00-50-C2-99-00-00') ->>> class YourSubclass(IAB): pass ->>> your_instance = YourSubclass('00-50-C2-00-00-00') ->>> your_instance2 = YourSubclass('00-50-C2-99-00-00') - ->>> iab == my_instance -True - ->>> iab != my_instance -False - ->>> iab == my_instance2 -False - ->>> iab != my_instance2 -True - ->>> my_instance != your_instance -False - ->>> my_instance == your_instance -True - ->>> my_instance == your_instance2 -False - ->>> my_instance != your_instance2 -True - -}}} - -Comparison between EUI objects and their textual representations - -{{{ - ->>> eui = EUI('11-22-33-44-55-66') ->>> class MySubclass(EUI): pass ->>> my_instance = MySubclass('11-22-33-44-55-66') - ->>> eui == '11-22-33-44-55-66' -True - ->>> my_instance == '11-22-33-44-55-66' -True - ->>> my_instance == '99-22-33-44-55-66' -False - ->>> '11-22-33-44-55-66' >= my_instance -True - ->>> my_instance > '11-22-33-44-55-00' -True - ->>> my_instance < '11-22-33-44-55-00' -False - ->>> my_instance <= '11-22-33-44-55-00' -False - ->>> my_instance >= '11-22-33-44-55-00' -True - -}}} - -Check equality between OUI objects and their textual representations - -{{{ - ->>> oui = OUI('00-1B-77') ->>> class MySubclass(OUI): pass ->>> my_instance = MySubclass('00-1B-77') - ->>> oui == '00-1B-77' -True - ->>> my_instance == '00-1B-77' -True - ->>> my_instance == '00-1B-99' -False - -}}} - -Check equality between IAB objects and their textual representations -{{{ - ->>> eui = IAB('00-50-C2-00-00-00') ->>> class MySubclass(IAB): pass ->>> my_instance = MySubclass('00-50-C2-00-00-00') - ->>> eui == '00-50-C2-00-00-00' -True - ->>> my_instance == '00-50-C2-00-00-00' -True - ->>> my_instance == '00-50-C2-99-00-00' -False - -}}} - -Sortability - -{{{ - ->>> import random - ->>> eui_list = [EUI(0, 64), EUI(0), EUI(0xffffffffffff, dialect=mac_unix), EUI(0x1000000000000)] - ->>> random.shuffle(eui_list) - ->>> eui_list.sort() - ->>> for eui in eui_list: -... str(eui), eui.version -('00-00-00-00-00-00', 48) -('ff:ff:ff:ff:ff:ff', 48) -('00-00-00-00-00-00-00-00', 64) -('00-01-00-00-00-00-00-00', 64) - -}}} - -Persistence - -{{{ - ->>> import pickle - ->>> eui1 = EUI('00-00-00-01-02-03') ->>> eui2 = pickle.loads(pickle.dumps(eui1)) ->>> eui1 == eui2 -True - ->>> eui1 = EUI('00-00-00-01-02-03', dialect=mac_cisco) ->>> eui2 = pickle.loads(pickle.dumps(eui1)) ->>> eui1 == eui2 -True - ->>> eui1.dialect == eui2.dialect -True - ->>> oui1 = EUI('00-00-00-01-02-03').oui ->>> oui2 = pickle.loads(pickle.dumps(oui1)) ->>> oui1 == oui2 -True ->>> oui1.records == oui2.records -True - ->>> iab1 = EUI('00-50-C2-00-1F-FF').iab ->>> iab2 = pickle.loads(pickle.dumps(iab1)) ->>> iab1 == iab2 -True ->>> iab1.record == iab2.record -True - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/3.x/eui/eui64.txt b/awx/lib/site-packages/netaddr/tests/3.x/eui/eui64.txt deleted file mode 100644 index 122b30ba4a..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/eui/eui64.txt +++ /dev/null @@ -1,75 +0,0 @@ -=IEEE EUI-64 Identifier Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Basic operations. - -{{{ - ->>> mac = EUI('00-1B-77-49-54-FD') ->>> mac -EUI('00-1B-77-49-54-FD') - ->>> eui = mac.eui64() ->>> eui -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> eui.eui64() -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> int(eui) == 7731765737772285 -True - ->>> eui.packed -b'\x00\x1bw\xff\xfeIT\xfd' - ->>> eui.bin -'0b11011011101111111111111111110010010010101010011111101' - ->>> eui.bits() -'00000000-00011011-01110111-11111111-11111110-01001001-01010100-11111101' - -}}} - -IPv6 interoperability - -{{{ - ->>> mac = EUI('00-1B-77-49-54-FD') - ->>> eui = mac.eui64() - ->>> mac -EUI('00-1B-77-49-54-FD') - ->>> eui -EUI('00-1B-77-FF-FE-49-54-FD') - ->>> mac.modified_eui64() -EUI('02-1B-77-FF-FE-49-54-FD') - ->>> mac.ipv6_link_local() -IPAddress('fe80::21b:77ff:fe49:54fd') - ->>> eui.ipv6_link_local() -IPAddress('fe80::21b:77ff:fe49:54fd') - ->>> mac.ipv6(0x12340000000000000000000000000000) -IPAddress('1234::21b:77ff:fe49:54fd') - ->>> eui.ipv6(0x12340000000000000000000000000000) -IPAddress('1234::21b:77ff:fe49:54fd') - ->>> addr_colonned = EUI('00:1B:77:49:54:FD:BB:34') ->>> addr_colonned -EUI('00-1B-77-49-54-FD-BB-34') - ->>> addr_no_delimeter = EUI('001B774954FDBB34') ->>> addr_no_delimeter -EUI('00-1B-77-49-54-FD-BB-34') diff --git a/awx/lib/site-packages/netaddr/tests/3.x/eui/pubsub.txt b/awx/lib/site-packages/netaddr/tests/3.x/eui/pubsub.txt deleted file mode 100644 index 83c2f7d145..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/eui/pubsub.txt +++ /dev/null @@ -1,56 +0,0 @@ -=IEEE Publish/Subscribe Parser Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -Basic OUIIndexParser and FileIndexer object tests. - -{{{ - ->>> from netaddr.eui.ieee import OUIIndexParser, IABIndexParser, FileIndexer ->>> from io import StringIO - ->>> infile = StringIO() ->>> outfile = StringIO() ->>> infile.write(""" -... 00-CA-FE (hex) ACME CORPORATION -... 00CAFE (base 16) ACME CORPORATION -... 1 MAIN STREET -... SPRINGFIELD -... UNITED STATES -... """) -211 ->>> infile.seek(0) -0 ->>> iab_parser = OUIIndexParser(infile) ->>> iab_parser.attach(FileIndexer(outfile)) ->>> iab_parser.parse() ->>> print(outfile.getvalue()) -51966,1,210 - - -}}} - -Basic IABIndexParser and FileIndexer object tests. - -{{{ - ->>> infile = StringIO() ->>> outfile = StringIO() ->>> infile.write(""" -... 00-50-C2 (hex) ACME CORPORATION -... ABC000-ABCFFF (base 16) ACME CORPORATION -... 1 MAIN STREET -... SPRINGFIELD -... UNITED STATES -... """) -182 ->>> infile.seek(0) -0 ->>> iab_parser = IABIndexParser(infile) ->>> iab_parser.attach(FileIndexer(outfile)) ->>> iab_parser.parse() ->>> print(outfile.getvalue()) -84683452,1,181 - - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/eui/tutorial.txt b/awx/lib/site-packages/netaddr/tests/3.x/eui/tutorial.txt deleted file mode 100644 index 6c9f980a5b..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/eui/tutorial.txt +++ /dev/null @@ -1,258 +0,0 @@ -=EUI (MAC) Address Tutorial= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -==Basic Operations== - -This EUI object represents a MAC address. - -{{{ - ->>> mac = EUI('00-1B-77-49-54-FD') - -}}} - -Standard repr() access returns a Python statement that can reconstruct the MAC address object from scratch if executed in the Python interpreter. - -{{{ - ->>> mac -EUI('00-1B-77-49-54-FD') - -}}} - -Accessing the EUI object in the string context. - -{{{ - ->>> str(mac) -'00-1B-77-49-54-FD' - ->>> '%s' % mac -'00-1B-77-49-54-FD' - -}}} - -Here are a few other common properties. - -{{{ - ->>> str(mac), str(mac.oui), mac.ei, mac.version -('00-1B-77-49-54-FD', '00-1B-77', '49-54-FD', 48) - -}}} - -==MAC Address Numerical Representations== - -You can view an individual IP address in various other formats. - -{{{ - ->>> int(mac) == 117965411581 -True - ->>> hex(mac) -'0x1b774954fd' - ->>> oct(mac) -'0o1556722252375' - ->>> mac.bits() -'00000000-00011011-01110111-01001001-01010100-11111101' - ->>> mac.bin -'0b1101101110111010010010101010011111101' - -}}} - -==MAC Address Formatting== - -It is very common to see MAC address in many different formats other than the standard IEEE EUI-48. - -The EUI class constructor handles all these common forms. - -{{{ - ->>> EUI('00-1B-77-49-54-FD') -EUI('00-1B-77-49-54-FD') - -IEEE EUI-48 lowercase format. - ->>> EUI('00-1b-77-49-54-fd') -EUI('00-1B-77-49-54-FD') - -Common UNIX format. - ->>> EUI('0:1b:77:49:54:fd') -EUI('00-1B-77-49-54-FD') - -Cisco triple hextet format. - ->>> EUI('001b:7749:54fd') -EUI('00-1B-77-49-54-FD') - ->>> EUI('1b:7749:54fd') -EUI('00-1B-77-49-54-FD') - ->>> EUI('1B:7749:54FD') -EUI('00-1B-77-49-54-FD') - -Bare MAC addresses (no delimiters). - ->>> EUI('001b774954fd') -EUI('00-1B-77-49-54-FD') - ->>> EUI('01B774954FD') -EUI('00-1B-77-49-54-FD') - -PostreSQL format (found in documentation). - ->>> EUI('001B77:4954FD') -EUI('00-1B-77-49-54-FD') - -}}} - -It is equally possible to specify a selected format for your MAC string output in the form of a 'dialect' class. It's use is similar to the dialect class used in the Python standard library csv module. - -{{{ - ->>> mac = EUI('00-1B-77-49-54-FD') - ->>> mac -EUI('00-1B-77-49-54-FD') - ->>> mac.dialect = mac_unix ->>> mac -EUI('0:1b:77:49:54:fd') - ->>> mac.dialect = mac_unix_expanded ->>> mac -EUI('00:1b:77:49:54:fd') - ->>> mac.dialect = mac_cisco ->>> mac -EUI('001b.7749.54fd') - ->>> mac.dialect = mac_bare ->>> mac -EUI('001B774954FD') - ->>> mac.dialect = mac_pgsql ->>> mac -EUI('001b77:4954fd') - -}}} - -You can of course, create your own dialect classes to customise the MAC formatting if the standard ones do not suit your needs. - -Here's a tweaked UNIX MAC dialect that generates uppercase, zero-filled octets. - -{{{ - ->>> class mac_custom(mac_unix): pass ->>> mac_custom.word_fmt = '%.2X' ->>> mac = EUI('00-1B-77-49-54-FD', dialect=mac_custom) ->>> mac -EUI('00:1B:77:49:54:FD') - -}}} - -==Looking Up EUI Organisational Data== - -EUI objects provide an interface to the OUI (Organisationally Unique Identifier) and IAB (Individual Address Block) registration databases available from the IEEE. - -Here is how you query an OUI with the EUI interface. - -{{{ - ->>> mac = EUI('00-1B-77-49-54-FD') ->>> oui = mac.oui ->>> oui -OUI('00-1B-77') - ->>> oui.registration().address -['Lot 8, Jalan Hi-Tech 2/3', 'Kulim Hi-Tech Park', 'Kulim Kedah 09000', 'MALAYSIA'] - ->>> oui.registration().org -'Intel Corporate' - -}}} - -You can also use OUI objects directly without going through the EUI interface. - -A few OUI records have multiple registrations against them. I'm not sure if this is recording historical information or just a quirk of the IEEE reigstration process. - -This example show you how you access them individually by specifying an index number. - -{{{ - ->>> oui = OUI(524336) # OUI constructor accepts integer values too. - ->>> oui -OUI('08-00-30') - ->>> oui.registration(0).address -['2380 N. ROSE AVENUE', 'OXNARD CA 93010', 'UNITED STATES'] - ->>> oui.registration(0).org -'NETWORK RESEARCH CORPORATION' - ->>> oui.registration(0).oui -'08-00-30' - ->>> oui.registration(1).address -['CH-1211 GENEVE 23', 'SUISSE/SWITZ', 'SWITZERLAND'] - ->>> oui.registration(1).org -'CERN' - ->>> oui.registration(1).oui -'08-00-30' - ->>> oui.registration(2).address -['GPO BOX 2476V', 'MELBOURNE VIC 3001', 'AUSTRALIA'] - ->>> oui.registration(2).org -'ROYAL MELBOURNE INST OF TECH' - ->>> oui.registration(2).oui -'08-00-30' - ->>> for i in range(oui.reg_count): -... str(oui), oui.registration(i).org -... -('08-00-30', 'NETWORK RESEARCH CORPORATION') -('08-00-30', 'CERN') -('08-00-30', 'ROYAL MELBOURNE INST OF TECH') - -}}} - -Here is how you query an IAB with the EUI interface. - -{{{ - ->>> mac = EUI('00-50-C2-00-0F-01') - ->>> mac.is_iab() -True - ->>> iab = mac.iab - ->>> iab -IAB('00-50-C2-00-00-00') - ->>> iab.registration() -{'address': ['1241 Superieor Ave E', 'Cleveland OH 44114', 'UNITED STATES'], - 'iab': '00-50-C2-00-00-00', - ... - 'offset': 123, - 'org': 'T.L.S. Corp.', - 'size': 139} - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/abbreviated.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/abbreviated.txt deleted file mode 100644 index b23a5f9fd6..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/abbreviated.txt +++ /dev/null @@ -1,202 +0,0 @@ -=Abbreviated CIDR Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Abbreviation tests. - -{{{ - ->>> ranges = ( -... (IPAddress('::'), IPAddress('::')), -... (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), -... (IPAddress('::'), IPAddress('::255.255.255.255')), -... (IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), -... ) - ->>> sorted(ranges) -[(IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), (IPAddress('::'), IPAddress('::')), (IPAddress('::'), IPAddress('::255.255.255.255'))] - -# Integer values. ->>> cidr_abbrev_to_verbose(-1) --1 - -# Class A ->>> cidr_abbrev_to_verbose(0) -'0.0.0.0/8' ->>> cidr_abbrev_to_verbose(10) -'10.0.0.0/8' ->>> cidr_abbrev_to_verbose(127) -'127.0.0.0/8' - -# Class B ->>> cidr_abbrev_to_verbose(128) -'128.0.0.0/16' ->>> cidr_abbrev_to_verbose(191) -'191.0.0.0/16' - -# Class C ->>> cidr_abbrev_to_verbose(192) -'192.0.0.0/24' ->>> cidr_abbrev_to_verbose(223) -'223.0.0.0/24' - -# Class D (multicast) ->>> cidr_abbrev_to_verbose(224) -'224.0.0.0/4' ->>> cidr_abbrev_to_verbose(225) -'225.0.0.0/4' ->>> cidr_abbrev_to_verbose(239) -'239.0.0.0/4' - -# Class E (reserved) ->>> cidr_abbrev_to_verbose(240) -'240.0.0.0/32' ->>> cidr_abbrev_to_verbose(254) -'254.0.0.0/32' ->>> cidr_abbrev_to_verbose(255) -'255.0.0.0/32' ->>> cidr_abbrev_to_verbose(256) -256 - -# String values. ->>> cidr_abbrev_to_verbose('-1') -'-1' - -# Class A ->>> cidr_abbrev_to_verbose('0') -'0.0.0.0/8' ->>> cidr_abbrev_to_verbose('10') -'10.0.0.0/8' ->>> cidr_abbrev_to_verbose('127') -'127.0.0.0/8' - -# Class B ->>> cidr_abbrev_to_verbose('128') -'128.0.0.0/16' ->>> cidr_abbrev_to_verbose('191') -'191.0.0.0/16' - -# Class C ->>> cidr_abbrev_to_verbose('192') -'192.0.0.0/24' ->>> cidr_abbrev_to_verbose('223') -'223.0.0.0/24' - -# Class D (multicast) ->>> cidr_abbrev_to_verbose('224') -'224.0.0.0/4' ->>> cidr_abbrev_to_verbose('225') -'225.0.0.0/4' ->>> cidr_abbrev_to_verbose('239') -'239.0.0.0/4' - -# Class E (reserved) ->>> cidr_abbrev_to_verbose('240') -'240.0.0.0/32' ->>> cidr_abbrev_to_verbose('254') -'254.0.0.0/32' ->>> cidr_abbrev_to_verbose('255') -'255.0.0.0/32' ->>> cidr_abbrev_to_verbose('256') -'256' - ->>> cidr_abbrev_to_verbose('128/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('128.0/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('128.0.0.0/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('128.0.0/8') -'128.0.0.0/8' ->>> cidr_abbrev_to_verbose('192.168') -'192.168.0.0/24' ->>> cidr_abbrev_to_verbose('192.0.2') -'192.0.2.0/24' ->>> cidr_abbrev_to_verbose('192.0.2.0') -'192.0.2.0/24' ->>> cidr_abbrev_to_verbose('0.0.0.0') -'0.0.0.0/8' - -# No IPv6 support current. ->>> cidr_abbrev_to_verbose('::/128') -'::/128' - -# IPv6 proper, not IPv4 mapped? ->>> cidr_abbrev_to_verbose('::10/128') -'::10/128' ->>> cidr_abbrev_to_verbose('0.0.0.0.0') -'0.0.0.0.0' ->>> cidr_abbrev_to_verbose('') -'' ->>> cidr_abbrev_to_verbose(None) - ->>> cidr_abbrev_to_verbose([]) -[] ->>> cidr_abbrev_to_verbose({}) -{} - -}}} - -Negative testing. - -{{{ - ->>> cidr_abbrev_to_verbose('192.0.2.0') -'192.0.2.0/24' - ->>> cidr_abbrev_to_verbose('192.0.2.0/32') -'192.0.2.0/32' - -#FIXME: >>> cidr_abbrev_to_verbose('192.0.2.0/33') -Traceback (most recent call last): -... -ValueError: prefixlen in address '192.0.2.0/33' out of range for IPv4! - -}}} - -IPv4 octet expansion routine. - -{{{ - ->>> from netaddr.strategy import ipv4 - ->>> ipv4.expand_partial_address('10') -'10.0.0.0' - ->>> ipv4.expand_partial_address('10.1') -'10.1.0.0' - ->>> ipv4.expand_partial_address('192.168.1') -'192.168.1.0' - -}}} - -IPNetwork constructor testing. - -{{{ - ->>> IPNetwork('192.168/16') -IPNetwork('192.168.0.0/16') - ->>> IPNetwork('192.168.0.15') -IPNetwork('192.168.0.15/32') - ->>> IPNetwork('192.168') -IPNetwork('192.168.0.0/32') - ->>> IPNetwork('192.168', implicit_prefix=True) -IPNetwork('192.168.0.0/24') - ->>> IPNetwork('192.168', True) -IPNetwork('192.168.0.0/24') - ->>> IPNetwork('10.0.0.1', True) -IPNetwork('10.0.0.1/8') - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/binops.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/binops.txt deleted file mode 100644 index 97a215380d..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/binops.txt +++ /dev/null @@ -1,68 +0,0 @@ -=Binary and numerical operations on IP addresses= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -==Addition and Subtraction == - -{{{ - ->>> IPAddress('192.0.2.0') + 1 -IPAddress('192.0.2.1') - ->>> 1 + IPAddress('192.0.2.0') -IPAddress('192.0.2.1') - ->>> IPAddress('192.0.2.1') - 1 -IPAddress('192.0.2.0') - ->>> IPAddress('192.0.0.0') + IPAddress('0.0.0.42') -IPAddress('192.0.0.42') - ->>> IPAddress('192.0.0.42') - IPAddress('0.0.0.42') -IPAddress('192.0.0.0') - - ->>> 1 - IPAddress('192.0.2.1') -Traceback (most recent call last): -... -IndexError: result outside valid IP address boundary! - ->>> ip = IPAddress('10.0.0.1') ->>> ip += 1 ->>> ip -IPAddress('10.0.0.2') ->>> ip -= 1 ->>> ip -IPAddress('10.0.0.1') ->>> ip += IPAddress('0.0.0.42') ->>> ip -IPAddress('10.0.0.43') ->>> ip -= IPAddress('0.0.0.43') ->>> ip -IPAddress('10.0.0.0') - -}}} - -==Binary operations== - -{{{ - ->>> IPAddress('192.0.2.15') & IPAddress('255.255.255.0') -IPAddress('192.0.2.0') - ->>> IPAddress('255.255.0.0') | IPAddress('0.0.255.255') -IPAddress('255.255.255.255') - ->>> IPAddress('255.255.0.0') ^ IPAddress('255.0.0.0') -IPAddress('0.255.0.0') - ->>> IPAddress('1.2.3.4').packed -b'\x01\x02\x03\x04' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/boundaries.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/boundaries.txt deleted file mode 100644 index 5bbe265680..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/boundaries.txt +++ /dev/null @@ -1,170 +0,0 @@ -=IP Range Boundary Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * ->>> import pprint - -}}} - -`iter_iprange()` iterator boundary tests. - -{{{ - ->>> pprint.pprint(list(iter_iprange('192.0.2.0', '192.0.2.7'))) -[IPAddress('192.0.2.0'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6'), - IPAddress('192.0.2.7')] - ->>> pprint.pprint(list(iter_iprange('::ffff:192.0.2.0', '::ffff:192.0.2.7'))) -[IPAddress('::ffff:192.0.2.0'), - IPAddress('::ffff:192.0.2.1'), - IPAddress('::ffff:192.0.2.2'), - IPAddress('::ffff:192.0.2.3'), - IPAddress('::ffff:192.0.2.4'), - IPAddress('::ffff:192.0.2.5'), - IPAddress('::ffff:192.0.2.6'), - IPAddress('::ffff:192.0.2.7')] - - -}}} - -`IPNetwork()` iterator boundary tests. - -{{{ - ->>> pprint.pprint(list(IPNetwork('192.0.2.0/29')[0:-1])) -[IPAddress('192.0.2.0'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6')] - ->>> pprint.pprint(list(IPNetwork('192.0.2.0/29')[::-1])) -[IPAddress('192.0.2.7'), - IPAddress('192.0.2.6'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.0')] - -For IPv4, network (first) and broadcast (last) address must be skipped. ->>> pprint.pprint(list(IPNetwork('192.0.2.0/29').iter_hosts())) -[IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6')] - -For IPv6, Subnet-Router anycast address (first) must be skipped. ->>> pprint.pprint(list(IPNetwork('::ffff:192.0.2.0/125').iter_hosts())) -[IPAddress('::ffff:192.0.2.1'), - IPAddress('::ffff:192.0.2.2'), - IPAddress('::ffff:192.0.2.3'), - IPAddress('::ffff:192.0.2.4'), - IPAddress('::ffff:192.0.2.5'), - IPAddress('::ffff:192.0.2.6'), - IPAddress('::ffff:192.0.2.7')] - -Very small IPNetworks do contain some IP addresses ->>> list(IPNetwork("192.168.0.0/31")) -[IPAddress('192.168.0.0'), IPAddress('192.168.0.1')] ->>> list(IPNetwork("1234::/128")) -[IPAddress('1234::')] - -But they have no IPs that can be assigned to hosts. ->>> list(IPNetwork("1234::/128").iter_hosts()) -[] ->>> list(IPNetwork("192.168.0.0/31").iter_hosts()) -[] - -}}} - -`IPRange()` iterator boundary tests. - -{{{ - ->>> pprint.pprint(list(IPRange('192.0.2.0', '192.0.2.7'))) -[IPAddress('192.0.2.0'), - IPAddress('192.0.2.1'), - IPAddress('192.0.2.2'), - IPAddress('192.0.2.3'), - IPAddress('192.0.2.4'), - IPAddress('192.0.2.5'), - IPAddress('192.0.2.6'), - IPAddress('192.0.2.7')] - ->>> pprint.pprint(list(IPRange('::ffff:192.0.2.0', '::ffff:192.0.2.7'))) -[IPAddress('::ffff:192.0.2.0'), - IPAddress('::ffff:192.0.2.1'), - IPAddress('::ffff:192.0.2.2'), - IPAddress('::ffff:192.0.2.3'), - IPAddress('::ffff:192.0.2.4'), - IPAddress('::ffff:192.0.2.5'), - IPAddress('::ffff:192.0.2.6'), - IPAddress('::ffff:192.0.2.7')] - -}}} - -Boolean contexts. - -{{{ - ->>> bool(IPAddress('0.0.0.0')) -False - ->>> bool(IPAddress('0.0.0.1')) -True - ->>> bool(IPAddress('255.255.255.255')) -True - ->>> bool(IPNetwork('0.0.0.0/0')) -True - ->>> bool(IPNetwork('::/0')) -True - ->>> bool(IPRange('0.0.0.0', '255.255.255.255')) -True - ->>> bool(IPRange('0.0.0.0', '0.0.0.0')) -True - ->>> bool(IPGlob('*.*.*.*')) -True - ->>> bool(IPGlob('0.0.0.0')) -True - -}}} - -`IPAddress()` negative increment tests. - -{{{ - ->>> ip = IPAddress('0.0.0.0') ->>> ip += -1 -Traceback (most recent call last): -... -IndexError: result outside valid IP address boundary! - ->>> ip = IPAddress('255.255.255.255') ->>> ip -= -1 -Traceback (most recent call last): -... -IndexError: result outside valid IP address boundary! - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/cidr.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/cidr.txt deleted file mode 100644 index c8eb0f3282..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/cidr.txt +++ /dev/null @@ -1,449 +0,0 @@ -=CIDR Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -==Basic IP Range Tuple Sorting== - -{{{ - ->>> ranges = ( -... (IPAddress('::'), IPAddress('::')), -... (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), -... (IPAddress('::'), IPAddress('::255.255.255.255')), -... (IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), -... ) - ->>> sorted(ranges) -[(IPAddress('0.0.0.0'), IPAddress('0.0.0.0')), (IPAddress('0.0.0.0'), IPAddress('255.255.255.255')), (IPAddress('::'), IPAddress('::')), (IPAddress('::'), IPAddress('::255.255.255.255'))] - -}}} - -Worst case IPv4 range to CIDR conversion. - -{{{ - ->>> for ip in iprange_to_cidrs('0.0.0.1', '255.255.255.254'): -... ip -... -IPNetwork('0.0.0.1/32') -IPNetwork('0.0.0.2/31') -IPNetwork('0.0.0.4/30') -IPNetwork('0.0.0.8/29') -IPNetwork('0.0.0.16/28') -IPNetwork('0.0.0.32/27') -IPNetwork('0.0.0.64/26') -IPNetwork('0.0.0.128/25') -IPNetwork('0.0.1.0/24') -IPNetwork('0.0.2.0/23') -IPNetwork('0.0.4.0/22') -IPNetwork('0.0.8.0/21') -IPNetwork('0.0.16.0/20') -IPNetwork('0.0.32.0/19') -IPNetwork('0.0.64.0/18') -IPNetwork('0.0.128.0/17') -IPNetwork('0.1.0.0/16') -IPNetwork('0.2.0.0/15') -IPNetwork('0.4.0.0/14') -IPNetwork('0.8.0.0/13') -IPNetwork('0.16.0.0/12') -IPNetwork('0.32.0.0/11') -IPNetwork('0.64.0.0/10') -IPNetwork('0.128.0.0/9') -IPNetwork('1.0.0.0/8') -IPNetwork('2.0.0.0/7') -IPNetwork('4.0.0.0/6') -IPNetwork('8.0.0.0/5') -IPNetwork('16.0.0.0/4') -IPNetwork('32.0.0.0/3') -IPNetwork('64.0.0.0/2') -IPNetwork('128.0.0.0/2') -IPNetwork('192.0.0.0/3') -IPNetwork('224.0.0.0/4') -IPNetwork('240.0.0.0/5') -IPNetwork('248.0.0.0/6') -IPNetwork('252.0.0.0/7') -IPNetwork('254.0.0.0/8') -IPNetwork('255.0.0.0/9') -IPNetwork('255.128.0.0/10') -IPNetwork('255.192.0.0/11') -IPNetwork('255.224.0.0/12') -IPNetwork('255.240.0.0/13') -IPNetwork('255.248.0.0/14') -IPNetwork('255.252.0.0/15') -IPNetwork('255.254.0.0/16') -IPNetwork('255.255.0.0/17') -IPNetwork('255.255.128.0/18') -IPNetwork('255.255.192.0/19') -IPNetwork('255.255.224.0/20') -IPNetwork('255.255.240.0/21') -IPNetwork('255.255.248.0/22') -IPNetwork('255.255.252.0/23') -IPNetwork('255.255.254.0/24') -IPNetwork('255.255.255.0/25') -IPNetwork('255.255.255.128/26') -IPNetwork('255.255.255.192/27') -IPNetwork('255.255.255.224/28') -IPNetwork('255.255.255.240/29') -IPNetwork('255.255.255.248/30') -IPNetwork('255.255.255.252/31') -IPNetwork('255.255.255.254/32') - -}}} - -Worst case IPv4 mapped IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::ffff:1', '::ffff:255.255.255.254'): -... ip -... -IPNetwork('::255.255.0.1/128') -IPNetwork('::255.255.0.2/127') -IPNetwork('::255.255.0.4/126') -IPNetwork('::255.255.0.8/125') -IPNetwork('::255.255.0.16/124') -IPNetwork('::255.255.0.32/123') -IPNetwork('::255.255.0.64/122') -IPNetwork('::255.255.0.128/121') -IPNetwork('::255.255.1.0/120') -IPNetwork('::255.255.2.0/119') -IPNetwork('::255.255.4.0/118') -IPNetwork('::255.255.8.0/117') -IPNetwork('::255.255.16.0/116') -IPNetwork('::255.255.32.0/115') -IPNetwork('::255.255.64.0/114') -IPNetwork('::255.255.128.0/113') -IPNetwork('::1:0:0/96') -IPNetwork('::2:0:0/95') -IPNetwork('::4:0:0/94') -IPNetwork('::8:0:0/93') -IPNetwork('::10:0:0/92') -IPNetwork('::20:0:0/91') -IPNetwork('::40:0:0/90') -IPNetwork('::80:0:0/89') -IPNetwork('::100:0:0/88') -IPNetwork('::200:0:0/87') -IPNetwork('::400:0:0/86') -IPNetwork('::800:0:0/85') -IPNetwork('::1000:0:0/84') -IPNetwork('::2000:0:0/83') -IPNetwork('::4000:0:0/82') -IPNetwork('::8000:0:0/82') -IPNetwork('::c000:0:0/83') -IPNetwork('::e000:0:0/84') -IPNetwork('::f000:0:0/85') -IPNetwork('::f800:0:0/86') -IPNetwork('::fc00:0:0/87') -IPNetwork('::fe00:0:0/88') -IPNetwork('::ff00:0:0/89') -IPNetwork('::ff80:0:0/90') -IPNetwork('::ffc0:0:0/91') -IPNetwork('::ffe0:0:0/92') -IPNetwork('::fff0:0:0/93') -IPNetwork('::fff8:0:0/94') -IPNetwork('::fffc:0:0/95') -IPNetwork('::fffe:0:0/96') -IPNetwork('::ffff:0.0.0.0/97') -IPNetwork('::ffff:128.0.0.0/98') -IPNetwork('::ffff:192.0.0.0/99') -IPNetwork('::ffff:224.0.0.0/100') -IPNetwork('::ffff:240.0.0.0/101') -IPNetwork('::ffff:248.0.0.0/102') -IPNetwork('::ffff:252.0.0.0/103') -IPNetwork('::ffff:254.0.0.0/104') -IPNetwork('::ffff:255.0.0.0/105') -IPNetwork('::ffff:255.128.0.0/106') -IPNetwork('::ffff:255.192.0.0/107') -IPNetwork('::ffff:255.224.0.0/108') -IPNetwork('::ffff:255.240.0.0/109') -IPNetwork('::ffff:255.248.0.0/110') -IPNetwork('::ffff:255.252.0.0/111') -IPNetwork('::ffff:255.254.0.0/112') -IPNetwork('::ffff:255.255.0.0/113') -IPNetwork('::ffff:255.255.128.0/114') -IPNetwork('::ffff:255.255.192.0/115') -IPNetwork('::ffff:255.255.224.0/116') -IPNetwork('::ffff:255.255.240.0/117') -IPNetwork('::ffff:255.255.248.0/118') -IPNetwork('::ffff:255.255.252.0/119') -IPNetwork('::ffff:255.255.254.0/120') -IPNetwork('::ffff:255.255.255.0/121') -IPNetwork('::ffff:255.255.255.128/122') -IPNetwork('::ffff:255.255.255.192/123') -IPNetwork('::ffff:255.255.255.224/124') -IPNetwork('::ffff:255.255.255.240/125') -IPNetwork('::ffff:255.255.255.248/126') -IPNetwork('::ffff:255.255.255.252/127') -IPNetwork('::ffff:255.255.255.254/128') - -}}} - -RFC 4291 CIDR tests. - -{{{ - ->>> str(IPNetwork('2001:0DB8:0000:CD30:0000:0000:0000:0000/60')) -'2001:db8:0:cd30::/60' - ->>> str(IPNetwork('2001:0DB8::CD30:0:0:0:0/60')) -'2001:db8:0:cd30::/60' - ->>> str(IPNetwork('2001:0DB8:0:CD30::/60')) -'2001:db8:0:cd30::/60' - -}}} - -Equality tests. - -{{{ - ->>> IPNetwork('192.0.2.0/255.255.254.0') == IPNetwork('192.0.2.0/23') -True - ->>> IPNetwork('192.0.2.65/255.255.254.0') == IPNetwork('192.0.2.0/23') -True - ->>> IPNetwork('192.0.2.65/255.255.254.0') == IPNetwork('192.0.2.65/23') -True - ->>> IPNetwork('192.0.2.65/255.255.255.0') == IPNetwork('192.0.2.0/23') -False - ->>> IPNetwork('192.0.2.65/255.255.254.0') == IPNetwork('192.0.2.65/24') -False - -}}} - -Slicing tests. - -{{{ - ->>> ip = IPNetwork('192.0.2.0/23') ->>> ip.first == 3221225984 -True - ->>> ip.last == 3221226495 -True - ->>> ip[0] -IPAddress('192.0.2.0') - ->>> ip[-1] -IPAddress('192.0.3.255') - ->>> list(ip[::128]) -[IPAddress('192.0.2.0'), IPAddress('192.0.2.128'), IPAddress('192.0.3.0'), IPAddress('192.0.3.128')] - ->>> ip = IPNetwork('fe80::/10') ->>> ip[0] -IPAddress('fe80::') - ->>> ip[-1] -IPAddress('febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff') - ->>> ip.size == 332306998946228968225951765070086144 -True - ->>> list(ip[0:5:1]) -Traceback (most recent call last): -... -TypeError: IPv6 slices are not supported! - - -}}} - -Membership tests. - -{{{ - ->>> IPAddress('192.0.2.1') in IPNetwork('192.0.2.0/24') -True - ->>> IPAddress('192.0.2.255') in IPNetwork('192.0.2.0/24') -True - ->>> IPNetwork('192.0.2.0/24') in IPNetwork('192.0.2.0/23') -True - ->>> IPNetwork('192.0.2.0/24') in IPNetwork('192.0.2.0/24') -True - ->>> IPAddress('ffff::1') in IPNetwork('ffff::/127') -True - ->>> IPNetwork('192.0.2.0/23') in IPNetwork('192.0.2.0/24') -False - -}}} - -Equality tests. - -{{{ - ->>> IPNetwork('192.0.2.0/24') == IPNetwork('192.0.2.0/24') -True - ->>> IPNetwork('192.0.2.0/24') is not IPNetwork('192.0.2.0/24') -True - ->>> IPNetwork('192.0.2.0/24') != IPNetwork('192.0.2.0/24') -False - ->>> IPNetwork('192.0.2.0/24') is IPNetwork('192.0.2.0/24') -False - ->>> IPNetwork('fe80::/10') == IPNetwork('fe80::/10') -True - ->>> IPNetwork('fe80::/10') is not IPNetwork('fe80::/10') -True - ->>> IPNetwork('fe80::/10') != IPNetwork('fe80::/10') -False - ->>> IPNetwork('fe80::/10') is IPNetwork('fe80::/10') -False - -}}} - -Exclusion tests. - -{{{ - -# Equivalent to :- -# >>> set([1]) - set([1]) -# set([1]) ->>> cidr_exclude('192.0.2.1/32', '192.0.2.1/32') -[] - -# Equivalent to :- -# >>> set([1,2]) - set([2]) -# set([1]) ->>> cidr_exclude('192.0.2.0/31', '192.0.2.1/32') -[IPNetwork('192.0.2.0/32')] - -# Equivalent to :- -# >>> set([1,2,3,4,5,6,7,8]) - set([5,6,7,8]) -# set([1, 2, 3, 4]) ->>> cidr_exclude('192.0.2.0/24', '192.0.2.128/25') -[IPNetwork('192.0.2.0/25')] - -# Equivalent to :- -# >>> set([1,2,3,4,5,6,7,8]) - set([5,6]) -# set([1, 2, 3, 4, 7, 8]) ->>> cidr_exclude('192.0.2.0/24', '192.0.2.128/27') -[IPNetwork('192.0.2.0/25'), IPNetwork('192.0.2.160/27'), IPNetwork('192.0.2.192/26')] - -# Subtracting a larger range from a smaller one results in an empty -# list (rather than a negative CIDR - which would be rather odd)! -# -# Equivalent to :- -# >>> set([1]) - set([1,2,3]) -# set([]) ->>> cidr_exclude('192.0.2.1/32', '192.0.2.0/24') -[] - -}}} - -Please Note: excluding IP subnets that are not within each other and have no overlaps should return the original target IP object. - -{{{ - -# Equivalent to :- -# >>> set([1,2,3]) - set([4]) -# set([1,2,3]) ->>> cidr_exclude('192.0.2.0/28', '192.0.2.16/32') -[IPNetwork('192.0.2.0/28')] - -# Equivalent to :- -# >>> set([1]) - set([2,3,4]) -# set([1]) ->>> cidr_exclude('192.0.1.255/32', '192.0.2.0/28') -[IPNetwork('192.0.1.255/32')] - -}}} - -Merge tests. - -{{{ - ->>> cidr_merge(['192.0.128.0/24', '192.0.129.0/24']) -[IPNetwork('192.0.128.0/23')] - ->>> cidr_merge(['192.0.129.0/24', '192.0.130.0/24']) -[IPNetwork('192.0.129.0/24'), IPNetwork('192.0.130.0/24')] - ->>> cidr_merge(['192.0.2.112/30', '192.0.2.116/31', '192.0.2.118/31']) -[IPNetwork('192.0.2.112/29')] - ->>> cidr_merge(['192.0.2.112/30', '192.0.2.116/32', '192.0.2.118/31']) -[IPNetwork('192.0.2.112/30'), IPNetwork('192.0.2.116/32'), IPNetwork('192.0.2.118/31')] - ->>> cidr_merge(['192.0.2.112/31', '192.0.2.116/31', '192.0.2.118/31']) -[IPNetwork('192.0.2.112/31'), IPNetwork('192.0.2.116/30')] - ->>> cidr_merge(['192.0.1.254/31', -... '192.0.2.0/28', -... '192.0.2.16/28', -... '192.0.2.32/28', -... '192.0.2.48/28', -... '192.0.2.64/28', -... '192.0.2.80/28', -... '192.0.2.96/28', -... '192.0.2.112/28', -... '192.0.2.128/28', -... '192.0.2.144/28', -... '192.0.2.160/28', -... '192.0.2.176/28', -... '192.0.2.192/28', -... '192.0.2.208/28', -... '192.0.2.224/28', -... '192.0.2.240/28', -... '192.0.3.0/28']) -[IPNetwork('192.0.1.254/31'), IPNetwork('192.0.2.0/24'), IPNetwork('192.0.3.0/28')] - -}}} - -Extended merge tests. - -{{{ - ->>> import random - -# Start with a single /23 CIDR. - ->>> orig_cidr_ipv4 = IPNetwork('192.0.2.0/23') ->>> orig_cidr_ipv6 = IPNetwork('::192.0.2.0/120') - -# Split it into /28 subnet CIDRs (mix CIDR objects and CIDR strings). - ->>> cidr_subnets = [] ->>> cidr_subnets.extend([str(c) for c in orig_cidr_ipv4.subnet(28)]) ->>> cidr_subnets.extend(list(orig_cidr_ipv4.subnet(28))) ->>> cidr_subnets.extend([str(c) for c in orig_cidr_ipv6.subnet(124)]) ->>> cidr_subnets.extend(list(orig_cidr_ipv6.subnet(124))) - -# Add a couple of duplicates in to make sure summarization is working OK. - ->>> cidr_subnets.append('192.0.2.1/32') ->>> cidr_subnets.append('192.0.2.128/25') ->>> cidr_subnets.append('::192.0.2.92/128') - -# Randomize the order of subnets. ->>> random.shuffle(cidr_subnets) - -# Perform summarization operation. ->>> merged_cidrs = cidr_merge(cidr_subnets) ->>> merged_cidrs -[IPNetwork('192.0.2.0/23'), IPNetwork('::192.0.2.0/120')] - ->>> merged_cidrs == [orig_cidr_ipv4, orig_cidr_ipv6] -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/constructor.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/constructor.txt deleted file mode 100644 index 4ffcdf31f9..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/constructor.txt +++ /dev/null @@ -1,234 +0,0 @@ -=IP Constructor Stress Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -IPAddress constructor - integer values. - -{{{ - ->>> IPAddress(1) -IPAddress('0.0.0.1') - ->>> IPAddress(1, 4) -IPAddress('0.0.0.1') - ->>> IPAddress(1, 6) -IPAddress('::1') - ->>> IPAddress(10) -IPAddress('0.0.0.10') - ->>> IPAddress(0x1ffffffff) -IPAddress('::1:ffff:ffff') - ->>> IPAddress(0xffffffff, 6) -IPAddress('::255.255.255.255') - ->>> IPAddress(0x1ffffffff) -IPAddress('::1:ffff:ffff') - ->>> IPAddress(2 ** 128 - 1) -IPAddress('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff') - -}}} - -IPAddress constructor - IPv4 inet_aton behaviour (default). - -{{{ - -# Hexadecimal octets. ->>> IPAddress('0x7f.0x1') -IPAddress('127.0.0.1') - ->>> IPAddress('0x7f.0x0.0x0.0x1') -IPAddress('127.0.0.1') - -# Octal octets. ->>> IPAddress('0177.01') -IPAddress('127.0.0.1') - -# Mixed octets. ->>> IPAddress('0x7f.0.01') -IPAddress('127.0.0.1') - -# Partial addresses - pretty weird ... ->>> IPAddress('127') -IPAddress('0.0.0.127') - ->>> IPAddress('127') -IPAddress('0.0.0.127') - ->>> IPAddress('127.1') -IPAddress('127.0.0.1') - ->>> IPAddress('127.0.1') -IPAddress('127.0.0.1') - -}}} - -IPAddress constructor - IPv4 inet_pton behaviour (stricter parser). - -{{{ - -# Octal octets. ->>> IPAddress('0177.01', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '0177.01' - -# Mixed octets. ->>> IPAddress('0x7f.0.01', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '0x7f.0.01' - -# Partial octets. ->>> IPAddress('10', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '10' - ->>> IPAddress('10.1', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '10.1' - ->>> IPAddress('10.0.1', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '10.0.1' - ->>> IPAddress('10.0.0.1', flags=INET_PTON) -IPAddress('10.0.0.1') - -}}} - -IPAddress constructor - zero filled octets. - -{{{ - -# This takes a lot of people by surprise ... ->>> IPAddress('010.000.000.001') -IPAddress('8.0.0.1') - -# So, we need this! ->>> IPAddress('010.000.000.001', flags=ZEROFILL) -IPAddress('10.0.0.1') - -# Zero-fill with inet_aton behaviour - partial octets are OK but zero-filled -# octets are interpreted as decimal ... ->>> IPAddress('010.000.001', flags=ZEROFILL) -IPAddress('10.0.0.1') - -# Zero-fill with inet_pton behaviour - 4 octets only! ->>> IPAddress('010.000.001', flags=INET_PTON|ZEROFILL) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '010.000.001' - -# Zero-fill with inet_pton behaviour - 4 octets only! ->>> IPAddress('010.000.000.001', flags=INET_PTON|ZEROFILL) -IPAddress('10.0.0.1') - -# To save some typing there are short versions of these flags. ->>> IPAddress('010.000.000.001', flags=P|Z) -IPAddress('10.0.0.1') - -}}} - -IP network construction. - -{{{ - ->>> IPNetwork('192.0.2.0/24') -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('192.0.2.0/255.255.255.0') -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('192.0.2.0/0.0.0.255') -IPNetwork('192.0.2.0/24') - ->>> IPNetwork(IPNetwork('192.0.2.0/24')) -IPNetwork('192.0.2.0/24') - ->>> IPNetwork(IPNetwork('::192.0.2.0/120')) -IPNetwork('::192.0.2.0/120') - ->>> IPNetwork(IPNetwork('192.0.2.0/24')) -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('::192.0.2.0/120') -IPNetwork('::192.0.2.0/120') - ->>> IPNetwork('::192.0.2.0/120', 6) -IPNetwork('::192.0.2.0/120') - -}}} - -Optional implicit IP network prefix selection rules. - -{{{ - ->>> IPNetwork('192.0.2.0', implicit_prefix=True) -IPNetwork('192.0.2.0/24') - ->>> IPNetwork('231.192.0.15', implicit_prefix=True) -IPNetwork('231.192.0.15/4') - ->>> IPNetwork('10', implicit_prefix=True) -IPNetwork('10.0.0.0/8') - -}}} - -Optional flags for tweaking IPNetwork constructor behaviour. - -{{{ - ->>> IPNetwork('172.24.200') -IPNetwork('172.24.200.0/32') - ->>> IPNetwork('172.24.200', implicit_prefix=True) -IPNetwork('172.24.200.0/16') - -# Truncate the host bits so we get a pure network. ->>> IPNetwork('172.24.200', implicit_prefix=True, flags=NOHOST) -IPNetwork('172.24.0.0/16') - - -}}} - -Negative testing - -{{{ - ->>> IPNetwork('foo') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: invalid IPNetwork foo - -}}} - -Netmasks - -{{{ - ->>> IPAddress('1.1.1.1').netmask_bits() -32 - ->>> IPAddress('255.255.255.254').netmask_bits() -31 - ->>> IPAddress('255.255.255.0').netmask_bits() -24 - ->>> IPAddress('::').netmask_bits() -128 - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/formats.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/formats.txt deleted file mode 100644 index 98d31358f5..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/formats.txt +++ /dev/null @@ -1,27 +0,0 @@ -=IP formatting options= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -==IPAddress representations== - -{{{ - ->>> hex(IPAddress(0)) -'0x0' - ->>> hex(IPAddress(0xffffffff)) -'0xffffffff' - ->>> oct(IPAddress(0)) -'0o0' - ->>> oct(IPAddress(0xffffffff)) -'0o37777777777' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/functions.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/functions.txt deleted file mode 100644 index 2f6a8ca48d..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/functions.txt +++ /dev/null @@ -1,48 +0,0 @@ -=IP Function Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -During a cidr merge operation, the address 0.0.0.0/0, representing the whole of the IPv4 address space, should swallow anything it is merged with. - -{{{ - ->>> cidr_merge(['0.0.0.0/0', '0.0.0.0']) -[IPNetwork('0.0.0.0/0')] - ->>> cidr_merge(['0.0.0.0/0', '255.255.255.255']) -[IPNetwork('0.0.0.0/0')] - ->>> cidr_merge(['0.0.0.0/0', '192.0.2.0/24', '10.0.0.0/8']) -[IPNetwork('0.0.0.0/0')] - -}}} - -Same goes for the IPv6 CIDR ::/0, representing the whole of the IPv6 address space. - -{{{ - ->>> cidr_merge(['::/0', 'fe80::1']) -[IPNetwork('::/0')] - ->>> cidr_merge(['::/0', '::']) -[IPNetwork('::/0')] - ->>> cidr_merge(['::/0', '::192.0.2.0/124', 'ff00::101']) -[IPNetwork('::/0')] - -}}} - -This also applies to mixed IPv4 and IPv6 address lists. - -{{{ - ->>> cidr_merge(['0.0.0.0/0', '0.0.0.0', '::/0', '::']) -[IPNetwork('0.0.0.0/0'), IPNetwork('::/0')] - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/ipglob.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/ipglob.txt deleted file mode 100644 index 9a9a256799..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/ipglob.txt +++ /dev/null @@ -1,72 +0,0 @@ -=IP Glob Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -IP Glob tests. - -{{{ - ->>> cidr_to_glob('10.0.0.1/32') -'10.0.0.1' - ->>> cidr_to_glob('192.0.2.0/24') -'192.0.2.*' - ->>> cidr_to_glob('172.16.0.0/12') -'172.16-31.*.*' - ->>> cidr_to_glob('0.0.0.0/0') -'*.*.*.*' - ->>> glob_to_cidrs('10.0.0.1') -[IPNetwork('10.0.0.1/32')] - ->>> glob_to_cidrs('192.0.2.*') -[IPNetwork('192.0.2.0/24')] - ->>> glob_to_cidrs('172.16-31.*.*') -[IPNetwork('172.16.0.0/12')] - ->>> glob_to_cidrs('*.*.*.*') -[IPNetwork('0.0.0.0/0')] - ->>> glob_to_iptuple('*.*.*.*') -(IPAddress('0.0.0.0'), IPAddress('255.255.255.255')) - ->>> iprange_to_globs('192.0.2.0', '192.0.2.255') -['192.0.2.*'] - ->>> iprange_to_globs('192.0.2.1', '192.0.2.15') -['192.0.2.1-15'] - ->>> iprange_to_globs('192.0.2.255', '192.0.4.1') -['192.0.2.255', '192.0.3.*', '192.0.4.0-1'] - ->>> iprange_to_globs('10.0.1.255', '10.0.255.255') -['10.0.1.255', '10.0.2-3.*', '10.0.4-7.*', '10.0.8-15.*', '10.0.16-31.*', '10.0.32-63.*', '10.0.64-127.*', '10.0.128-255.*'] - -}}} - -Validity tests. - -{{{ - ->>> valid_glob('1.1.1.a') -False - ->>> valid_glob('1.1.1.1/32') -False - ->>> valid_glob('1.1.1.a-b') -False - ->>> valid_glob('1.1.a-b.*') -False - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/iprange.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/iprange.txt deleted file mode 100644 index f3b638ac16..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/iprange.txt +++ /dev/null @@ -1,171 +0,0 @@ -=IPRange Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Constructor tests. - -{{{ - ->>> iprange = IPRange('192.0.2.1', '192.0.2.254') - ->>> iprange -IPRange('192.0.2.1', '192.0.2.254') - ->>> '%s' % iprange -'192.0.2.1-192.0.2.254' - ->>> IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') -IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') - ->>> IPRange('192.0.2.1', '192.0.2.1') -IPRange('192.0.2.1', '192.0.2.1') - ->>> IPRange('208.049.164.000', '208.050.066.255', flags=ZEROFILL) -IPRange('208.49.164.0', '208.50.66.255') - -}}} - -Bad constructor tests. - -{{{ - ->>> IPRange('192.0.2.2', '192.0.2.1') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: lower bound IP greater than upper bound! - ->>> IPRange('::', '0.0.0.1') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: base address '0.0.0.1' is not IPv6 - ->>> IPRange('0.0.0.0', '::1') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: base address '::1' is not IPv4 - -}}} - -Indexing and slicing tests. - -{{{ - ->>> iprange = IPRange('192.0.2.1', '192.0.2.254') - ->>> len(iprange) -254 - ->>> iprange.first == 3221225985 -True - ->>> iprange.last == 3221226238 -True - ->>> iprange[0] -IPAddress('192.0.2.1') - ->>> iprange[-1] -IPAddress('192.0.2.254') - ->>> iprange[512] -Traceback (most recent call last): -... -IndexError: index out range for address range size! - ->>> list(iprange[0:3]) -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3')] - ->>> list(iprange[0:10:2]) -[IPAddress('192.0.2.1'), IPAddress('192.0.2.3'), IPAddress('192.0.2.5'), IPAddress('192.0.2.7'), IPAddress('192.0.2.9')] - ->>> list(iprange[0:1024:512]) -[IPAddress('192.0.2.1')] - ->>> IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254')[0:10:2] -Traceback (most recent call last): -... -TypeError: IPv6 slices are not supported! - -}}} - -Membership tests. - -{{{ - ->>> IPRange('192.0.2.5', '192.0.2.10') in IPRange('192.0.2.1', '192.0.2.254') -True - ->>> IPRange('fe80::1', 'fe80::fffe') in IPRange('fe80::', 'fe80::ffff:ffff:ffff:ffff') -True - ->>> IPRange('192.0.2.5', '192.0.2.10') in IPRange('::', '::255.255.255.255') -False - -}}} - -Sorting tests. - -{{{ - ->>> ipranges = (IPRange('192.0.2.40', '192.0.2.50'), IPRange('192.0.2.20', '192.0.2.30'), IPRange('192.0.2.1', '192.0.2.254'),) - ->>> sorted(ipranges) -[IPRange('192.0.2.1', '192.0.2.254'), IPRange('192.0.2.20', '192.0.2.30'), IPRange('192.0.2.40', '192.0.2.50')] - ->>> ipranges = list(ipranges) - ->>> ipranges.append(IPRange('192.0.2.45', '192.0.2.49')) - ->>> sorted(ipranges) -[IPRange('192.0.2.1', '192.0.2.254'), IPRange('192.0.2.20', '192.0.2.30'), IPRange('192.0.2.40', '192.0.2.50'), IPRange('192.0.2.45', '192.0.2.49')] - -}}} - -CIDR interoperability tests. - -{{{ - ->>> IPRange('192.0.2.5', '192.0.2.10').cidrs() -[IPNetwork('192.0.2.5/32'), IPNetwork('192.0.2.6/31'), IPNetwork('192.0.2.8/31'), IPNetwork('192.0.2.10/32')] - ->>> IPRange('fe80::', 'fe80::ffff:ffff:ffff:ffff').cidrs() -[IPNetwork('fe80::/64')] - -}}} - -Various additional tests. - -{{{ - ->>> iprange.info -{'IPv4': [{'date': '1993-05', - 'designation': 'Administered by ARIN', - 'prefix': '192/8', - 'status': 'Legacy', - 'whois': 'whois.arin.net'}]} - ->>> iprange.is_private() -True - ->>> iprange.version -4 - -len() fails when the IPRange is longer than sys.maxint, which is quite likely with IPv6. ->>> from netaddr.compat import _sys_maxint ->>> r = IPRange(IPAddress("::0"), IPAddress(_sys_maxint, 6)) ->>> len(r) -Traceback (most recent call last): - ... -IndexError: range contains more than ... - ->>> r = IPRange(IPAddress("::0"), IPAddress(_sys_maxint - 1, 6)) ->>> len(r) == _sys_maxint -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/matches.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/matches.txt deleted file mode 100644 index 1029228bcb..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/matches.txt +++ /dev/null @@ -1,71 +0,0 @@ -=IP Matching Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - ->>> largest_matching_cidr('192.0.2.0', ['192.0.2.0']) -IPNetwork('192.0.2.0/32') - ->>> largest_matching_cidr('192.0.2.0', ['10.0.0.1', '192.0.2.0']) -IPNetwork('192.0.2.0/32') - ->>> largest_matching_cidr('192.0.2.0', ['10.0.0.1', '192.0.2.0', '224.0.0.1']) -IPNetwork('192.0.2.0/32') - ->>> smallest_matching_cidr('192.0.2.0', ['10.0.0.1', '192.0.2.0', '224.0.0.1']) -IPNetwork('192.0.2.0/32') - ->>> smallest_matching_cidr('192.0.2.32', ['0.0.0.0/0', '10.0.0.0/8', '192.0.0.0/8', '192.0.1.0/24', '192.0.2.0/24', '192.0.3.0/24']) -IPNetwork('192.0.2.0/24') - ->>> all_matching_cidrs('192.0.2.32', ['0.0.0.0/0', '10.0.0.0/8', '192.0.0.0/8', '192.0.1.0/24', '192.0.2.0/24', '192.0.3.0/24']) -[IPNetwork('0.0.0.0/0'), IPNetwork('192.0.0.0/8'), IPNetwork('192.0.2.0/24')] - ->>> smallest_matching_cidr('192.0.2.0', ['10.0.0.1', '224.0.0.1']) - ->>> largest_matching_cidr('192.0.2.0', ['10.0.0.1', '224.0.0.1']) - ->>> networks = [str(c) for c in IPNetwork('192.0.2.128/27').supernet(22)] - ->>> networks -['192.0.0.0/22', '192.0.2.0/23', '192.0.2.0/24', '192.0.2.128/25', '192.0.2.128/26'] - ->>> all_matching_cidrs('192.0.2.0', networks) -[IPNetwork('192.0.0.0/22'), IPNetwork('192.0.2.0/23'), IPNetwork('192.0.2.0/24')] - ->>> smallest_matching_cidr('192.0.2.0', networks) -IPNetwork('192.0.2.0/24') - ->>> largest_matching_cidr('192.0.2.0', networks) -IPNetwork('192.0.0.0/22') - -}}} - -Checking matches with varying IP address versions. - -{{{ ->>> all_matching_cidrs('192.0.2.0', ['192.0.2.0/24']) -[IPNetwork('192.0.2.0/24')] - ->>> all_matching_cidrs('192.0.2.0', ['::/96']) -[] - ->>> all_matching_cidrs('::ffff:192.0.2.1', ['::ffff:192.0.2.0/96']) -[IPNetwork('::ffff:192.0.2.0/96')] - ->>> all_matching_cidrs('::192.0.2.1', ['::192.0.2.0/96']) -[IPNetwork('::192.0.2.0/96')] - ->>> all_matching_cidrs('::192.0.2.1', ['192.0.2.0/23']) -[] - ->>> all_matching_cidrs('::192.0.2.1', ['192.0.2.0/24', '::192.0.2.0/120']) -[IPNetwork('::192.0.2.0/120')] - ->>> all_matching_cidrs('::192.0.2.1', [IPNetwork('192.0.2.0/24'), IPNetwork('::192.0.2.0/120')]) -[IPNetwork('::192.0.2.0/120')] - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/multicast.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/multicast.txt deleted file mode 100644 index 027676897f..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/multicast.txt +++ /dev/null @@ -1,30 +0,0 @@ -=IP Multicast Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - ->>> ip = IPAddress('239.192.0.1') - ->>> ip.is_multicast() -True - ->>> ip = IPAddress(3221225984) - ->>> ip = IPAddress('224.0.1.173') - ->>> ip.info.IPv4[0].designation -'Multicast' - ->>> ip.info.IPv4[0].prefix -'224/8' - ->>> ip.info.IPv4[0].status -'Reserved' - ->>> ip.info.Multicast[0].address -'224.0.1.173' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/nmap.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/nmap.txt deleted file mode 100644 index 7216ee38f2..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/nmap.txt +++ /dev/null @@ -1,118 +0,0 @@ -=nmap IP Range Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -nmap IP range validation. - -{{{ - ->>> valid_nmap_range('192.0.2.1') -True - ->>> valid_nmap_range('192.0.2.0-31') -True - ->>> valid_nmap_range('192.0.2-3.1-254') -True - ->>> valid_nmap_range('0-255.0-255.0-255.0-255') -True - ->>> valid_nmap_range('192.168.3-5,7.1') -True - ->>> valid_nmap_range('192.168.3-5,7,10-12,13,14.1') -True - ->>> valid_nmap_range(1) -False - ->>> valid_nmap_range('1') -False - ->>> valid_nmap_range([]) -False - ->>> valid_nmap_range({}) -False - ->>> valid_nmap_range('::') -False - ->>> valid_nmap_range('255.255.255.256') -False - ->>> valid_nmap_range('0-255.0-255.0-255.0-256') -False - ->>> valid_nmap_range('0-255.0-255.0-255.-1-0') -False - ->>> valid_nmap_range('0-255.0-255.0-255.256-0') -False - ->>> valid_nmap_range('0-255.0-255.0-255.255-0') -False - ->>> valid_nmap_range('a.b.c.d-e') -False - ->>> valid_nmap_range('255.255.255.a-b') -False - -}}} - -nmap IP range iteration. - -{{{ - ->>> list(iter_nmap_range('192.0.2.1')) -[IPAddress('192.0.2.1')] - ->>> ip_list = list(iter_nmap_range('192.0.2.0-31')) ->>> len(ip_list) -32 ->>> ip_list -[IPAddress('192.0.2.0'), IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3'), IPAddress('192.0.2.4'), IPAddress('192.0.2.5'), IPAddress('192.0.2.6'), IPAddress('192.0.2.7'), IPAddress('192.0.2.8'), IPAddress('192.0.2.9'), IPAddress('192.0.2.10'), IPAddress('192.0.2.11'), IPAddress('192.0.2.12'), IPAddress('192.0.2.13'), IPAddress('192.0.2.14'), IPAddress('192.0.2.15'), IPAddress('192.0.2.16'), IPAddress('192.0.2.17'), IPAddress('192.0.2.18'), IPAddress('192.0.2.19'), IPAddress('192.0.2.20'), IPAddress('192.0.2.21'), IPAddress('192.0.2.22'), IPAddress('192.0.2.23'), IPAddress('192.0.2.24'), IPAddress('192.0.2.25'), IPAddress('192.0.2.26'), IPAddress('192.0.2.27'), IPAddress('192.0.2.28'), IPAddress('192.0.2.29'), IPAddress('192.0.2.30'), IPAddress('192.0.2.31')] - ->>> ip_list = list(iter_nmap_range('192.0.2-3.1-7')) ->>> len(ip_list) -14 - ->>> list(iter_nmap_range('192.0.2.1-3,5,7-9')) -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3'), IPAddress('192.0.2.5'), IPAddress('192.0.2.7'), IPAddress('192.0.2.8'), IPAddress('192.0.2.9')] - ->>> for ip in ip_list: -... print(ip) -... -192.0.2.1 -192.0.2.2 -192.0.2.3 -192.0.2.4 -192.0.2.5 -192.0.2.6 -192.0.2.7 -192.0.3.1 -192.0.3.2 -192.0.3.3 -192.0.3.4 -192.0.3.5 -192.0.3.6 -192.0.3.7 - ->>> list(iter_nmap_range('::')) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: invalid nmap range: :: - -Remove duplicates, just like nmap does. ->>> list(iter_nmap_range('10.0.0.42,42-42')) -[IPAddress('10.0.0.42')] - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/pickling.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/pickling.txt deleted file mode 100644 index 14d00f1af0..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/pickling.txt +++ /dev/null @@ -1,214 +0,0 @@ -=IP Persistence Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * ->>> import pickle - -}}} - -IPAddress object pickling - IPv4. - -{{{ - ->>> ip = IPAddress(3221225985) ->>> ip -IPAddress('192.0.2.1') - ->>> buf = pickle.dumps(ip) - ->>> ip2 = pickle.loads(buf) - ->>> ip2 == ip -True - ->>> id(ip2) != id(ip) -True - ->>> ip2.value == 3221225985 -True - ->>> ip2.version -4 - ->>> del ip, buf, ip2 - -}}} - -IPAddress object pickling - IPv6. - -{{{ - ->>> ip = IPAddress('::ffff:192.0.2.1') - ->>> ip -IPAddress('::ffff:192.0.2.1') - ->>> ip.value == 281473902969345 -True - ->>> buf = pickle.dumps(ip) - ->>> ip2 = pickle.loads(buf) - ->>> ip2 == ip -True - ->>> ip2.value == 281473902969345 -True - ->>> ip2.version -6 - ->>> del ip, buf, ip2 - -}}} - -IPNetwork pickling - IPv4. - -{{{ - ->>> cidr = IPNetwork('192.0.2.0/24') ->>> cidr -IPNetwork('192.0.2.0/24') - ->>> buf = pickle.dumps(cidr) - ->>> cidr2 = pickle.loads(buf) - ->>> cidr2 == cidr -True - ->>> id(cidr2) != id(cidr) -True - ->>> cidr2.value == 3221225984 -True - ->>> cidr2.prefixlen -24 - ->>> cidr2.version -4 - ->>> del cidr, buf, cidr2 - -}}} - -IPNetwork object pickling - IPv6. - -{{{ - ->>> cidr = IPNetwork('::ffff:192.0.2.0/120') - ->>> cidr -IPNetwork('::ffff:192.0.2.0/120') - ->>> cidr.value == 281473902969344 -True - ->>> cidr.prefixlen -120 - ->>> buf = pickle.dumps(cidr) - ->>> cidr2 = pickle.loads(buf) - ->>> cidr2 == cidr -True - ->>> cidr2.value == 281473902969344 -True - ->>> cidr2.prefixlen -120 - ->>> cidr2.version -6 - ->>> del cidr, buf, cidr2 - -}}} - -}}} - -IPRange object pickling - IPv4. - -{{{ - ->>> iprange = IPRange('192.0.2.1', '192.0.2.254') ->>> iprange -IPRange('192.0.2.1', '192.0.2.254') - ->>> iprange.first == 3221225985 -True - ->>> iprange.last == 3221226238 -True - ->>> iprange.version -4 - ->>> buf = pickle.dumps(iprange) - ->>> iprange2 = pickle.loads(buf) - ->>> iprange2 == iprange -True - ->>> id(iprange2) != id(iprange) -True - ->>> iprange2.first == 3221225985 -True - ->>> iprange2.last == 3221226238 -True - ->>> iprange2.version -4 - ->>> del iprange, buf, iprange2 - -}}} - -IPRange object pickling - IPv6. - -{{{ - ->>> iprange = IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') - ->>> iprange -IPRange('::ffff:192.0.2.1', '::ffff:192.0.2.254') - ->>> iprange.first == 281473902969345 -True - ->>> iprange.last == 281473902969598 -True - ->>> iprange.version -6 - ->>> buf = pickle.dumps(iprange) - ->>> iprange2 = pickle.loads(buf) - ->>> iprange2 == iprange -True - ->>> iprange2.first == 281473902969345 -True - ->>> iprange2.last == 281473902969598 -True - ->>> iprange2.version -6 - ->>> del iprange, buf, iprange2 - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_darwin.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_darwin.txt deleted file mode 100644 index 0efe91f038..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_darwin.txt +++ /dev/null @@ -1,90 +0,0 @@ -=Mac OSX Specific Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Worst case IPv4 compatible IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::1', '::255.255.255.254'): -... ip -... -IPNetwork('::1/128') -IPNetwork('::0.0.0.2/127') -IPNetwork('::0.0.0.4/126') -IPNetwork('::0.0.0.8/125') -IPNetwork('::0.0.0.16/124') -IPNetwork('::0.0.0.32/123') -IPNetwork('::0.0.0.64/122') -IPNetwork('::0.0.0.128/121') -IPNetwork('::0.0.1.0/120') -IPNetwork('::0.0.2.0/119') -IPNetwork('::0.0.4.0/118') -IPNetwork('::0.0.8.0/117') -IPNetwork('::0.0.16.0/116') -IPNetwork('::0.0.32.0/115') -IPNetwork('::0.0.64.0/114') -IPNetwork('::0.0.128.0/113') -IPNetwork('::0.1.0.0/112') -IPNetwork('::0.2.0.0/111') -IPNetwork('::0.4.0.0/110') -IPNetwork('::0.8.0.0/109') -IPNetwork('::0.16.0.0/108') -IPNetwork('::0.32.0.0/107') -IPNetwork('::0.64.0.0/106') -IPNetwork('::0.128.0.0/105') -IPNetwork('::1.0.0.0/104') -IPNetwork('::2.0.0.0/103') -IPNetwork('::4.0.0.0/102') -IPNetwork('::8.0.0.0/101') -IPNetwork('::16.0.0.0/100') -IPNetwork('::32.0.0.0/99') -IPNetwork('::64.0.0.0/98') -IPNetwork('::128.0.0.0/98') -IPNetwork('::192.0.0.0/99') -IPNetwork('::224.0.0.0/100') -IPNetwork('::240.0.0.0/101') -IPNetwork('::248.0.0.0/102') -IPNetwork('::252.0.0.0/103') -IPNetwork('::254.0.0.0/104') -IPNetwork('::255.0.0.0/105') -IPNetwork('::255.128.0.0/106') -IPNetwork('::255.192.0.0/107') -IPNetwork('::255.224.0.0/108') -IPNetwork('::255.240.0.0/109') -IPNetwork('::255.248.0.0/110') -IPNetwork('::255.252.0.0/111') -IPNetwork('::255.254.0.0/112') -IPNetwork('::255.255.0.0/113') -IPNetwork('::255.255.128.0/114') -IPNetwork('::255.255.192.0/115') -IPNetwork('::255.255.224.0/116') -IPNetwork('::255.255.240.0/117') -IPNetwork('::255.255.248.0/118') -IPNetwork('::255.255.252.0/119') -IPNetwork('::255.255.254.0/120') -IPNetwork('::255.255.255.0/121') -IPNetwork('::255.255.255.128/122') -IPNetwork('::255.255.255.192/123') -IPNetwork('::255.255.255.224/124') -IPNetwork('::255.255.255.240/125') -IPNetwork('::255.255.255.248/126') -IPNetwork('::255.255.255.252/127') -IPNetwork('::255.255.255.254/128') - -# inet_pton has to be different on Mac OSX *sigh* ->>> IPAddress('010.000.000.001', flags=INET_PTON) -IPAddress('10.0.0.1') - ->>> from netaddr.strategy.ipv6 import int_to_str ->>> int_to_str(0xffff) -'::0.0.255.255' - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_linux2.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_linux2.txt deleted file mode 100644 index 27f57e70ac..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_linux2.txt +++ /dev/null @@ -1,94 +0,0 @@ -=Linux Specific Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Worst case IPv4 compatible IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::1', '::255.255.255.254'): -... ip -... -IPNetwork('::1/128') -IPNetwork('::2/127') -IPNetwork('::4/126') -IPNetwork('::8/125') -IPNetwork('::10/124') -IPNetwork('::20/123') -IPNetwork('::40/122') -IPNetwork('::80/121') -IPNetwork('::100/120') -IPNetwork('::200/119') -IPNetwork('::400/118') -IPNetwork('::800/117') -IPNetwork('::1000/116') -IPNetwork('::2000/115') -IPNetwork('::4000/114') -IPNetwork('::8000/113') -IPNetwork('::0.1.0.0/112') -IPNetwork('::0.2.0.0/111') -IPNetwork('::0.4.0.0/110') -IPNetwork('::0.8.0.0/109') -IPNetwork('::0.16.0.0/108') -IPNetwork('::0.32.0.0/107') -IPNetwork('::0.64.0.0/106') -IPNetwork('::0.128.0.0/105') -IPNetwork('::1.0.0.0/104') -IPNetwork('::2.0.0.0/103') -IPNetwork('::4.0.0.0/102') -IPNetwork('::8.0.0.0/101') -IPNetwork('::16.0.0.0/100') -IPNetwork('::32.0.0.0/99') -IPNetwork('::64.0.0.0/98') -IPNetwork('::128.0.0.0/98') -IPNetwork('::192.0.0.0/99') -IPNetwork('::224.0.0.0/100') -IPNetwork('::240.0.0.0/101') -IPNetwork('::248.0.0.0/102') -IPNetwork('::252.0.0.0/103') -IPNetwork('::254.0.0.0/104') -IPNetwork('::255.0.0.0/105') -IPNetwork('::255.128.0.0/106') -IPNetwork('::255.192.0.0/107') -IPNetwork('::255.224.0.0/108') -IPNetwork('::255.240.0.0/109') -IPNetwork('::255.248.0.0/110') -IPNetwork('::255.252.0.0/111') -IPNetwork('::255.254.0.0/112') -IPNetwork('::255.255.0.0/113') -IPNetwork('::255.255.128.0/114') -IPNetwork('::255.255.192.0/115') -IPNetwork('::255.255.224.0/116') -IPNetwork('::255.255.240.0/117') -IPNetwork('::255.255.248.0/118') -IPNetwork('::255.255.252.0/119') -IPNetwork('::255.255.254.0/120') -IPNetwork('::255.255.255.0/121') -IPNetwork('::255.255.255.128/122') -IPNetwork('::255.255.255.192/123') -IPNetwork('::255.255.255.224/124') -IPNetwork('::255.255.255.240/125') -IPNetwork('::255.255.255.248/126') -IPNetwork('::255.255.255.252/127') -IPNetwork('::255.255.255.254/128') - -# Sadly, inet_pton cannot help us here ... ->>> IPAddress('010.000.000.001', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '010.000.000.001' - ->>> from netaddr.strategy.ipv6 import int_to_str ->>> int_to_str(0xffff) -'::ffff' - -}}} - - - diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_win32.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_win32.txt deleted file mode 100644 index 9129424bc9..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/platform_win32.txt +++ /dev/null @@ -1,92 +0,0 @@ -=Windows Specific Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Worst case IPv4 compatible IPv6 range to CIDR. - -{{{ - ->>> for ip in iprange_to_cidrs('::1', '::255.255.255.254'): -... ip -... -IPNetwork('::1/128') -IPNetwork('::2/127') -IPNetwork('::4/126') -IPNetwork('::8/125') -IPNetwork('::10/124') -IPNetwork('::20/123') -IPNetwork('::40/122') -IPNetwork('::80/121') -IPNetwork('::100/120') -IPNetwork('::200/119') -IPNetwork('::400/118') -IPNetwork('::800/117') -IPNetwork('::1000/116') -IPNetwork('::2000/115') -IPNetwork('::4000/114') -IPNetwork('::8000/113') -IPNetwork('::0.1.0.0/112') -IPNetwork('::0.2.0.0/111') -IPNetwork('::0.4.0.0/110') -IPNetwork('::0.8.0.0/109') -IPNetwork('::0.16.0.0/108') -IPNetwork('::0.32.0.0/107') -IPNetwork('::0.64.0.0/106') -IPNetwork('::0.128.0.0/105') -IPNetwork('::1.0.0.0/104') -IPNetwork('::2.0.0.0/103') -IPNetwork('::4.0.0.0/102') -IPNetwork('::8.0.0.0/101') -IPNetwork('::16.0.0.0/100') -IPNetwork('::32.0.0.0/99') -IPNetwork('::64.0.0.0/98') -IPNetwork('::128.0.0.0/98') -IPNetwork('::192.0.0.0/99') -IPNetwork('::224.0.0.0/100') -IPNetwork('::240.0.0.0/101') -IPNetwork('::248.0.0.0/102') -IPNetwork('::252.0.0.0/103') -IPNetwork('::254.0.0.0/104') -IPNetwork('::255.0.0.0/105') -IPNetwork('::255.128.0.0/106') -IPNetwork('::255.192.0.0/107') -IPNetwork('::255.224.0.0/108') -IPNetwork('::255.240.0.0/109') -IPNetwork('::255.248.0.0/110') -IPNetwork('::255.252.0.0/111') -IPNetwork('::255.254.0.0/112') -IPNetwork('::255.255.0.0/113') -IPNetwork('::255.255.128.0/114') -IPNetwork('::255.255.192.0/115') -IPNetwork('::255.255.224.0/116') -IPNetwork('::255.255.240.0/117') -IPNetwork('::255.255.248.0/118') -IPNetwork('::255.255.252.0/119') -IPNetwork('::255.255.254.0/120') -IPNetwork('::255.255.255.0/121') -IPNetwork('::255.255.255.128/122') -IPNetwork('::255.255.255.192/123') -IPNetwork('::255.255.255.224/124') -IPNetwork('::255.255.255.240/125') -IPNetwork('::255.255.255.248/126') -IPNetwork('::255.255.255.252/127') -IPNetwork('::255.255.255.254/128') - -# Sadly, inet_pton cannot help us here ... ->>> IPAddress('010.000.000.001', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: failed to detect a valid IP address from '010.000.000.001' - ->>> from netaddr.strategy.ipv6 import int_to_str ->>> int_to_str(0xffff) -'::ffff' - -}}} - diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/rfc1924.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/rfc1924.txt deleted file mode 100644 index d61794a6e1..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/rfc1924.txt +++ /dev/null @@ -1,33 +0,0 @@ -=RFC 1924 Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -The example from the RFC. - -{{{ - ->>> from netaddr.ip.rfc1924 import ipv6_to_base85, base85_to_ipv6 - ->>> ip_addr = '1080::8:800:200c:417a' - ->>> ip_addr -'1080::8:800:200c:417a' - ->>> base85 = ipv6_to_base85(ip_addr) - ->>> base85 -'4)+k&C#VzJ4br>0wv%Yp' - -RFC specifies that "leading zeroes are never omitted" ->>> ipv6_to_base85("::1") -'00000000000000000001' - ->>> base85_to_ipv6(base85) -'1080::8:800:200c:417a' - -Invalid length for a base85 encoded IPv6 address ->>> base85_to_ipv6('not 20 chars') -Traceback (most recent call last): -netaddr.core.AddrFormatError: Invalid base 85 IPv6 address: 'not 20 chars' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/sets.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/sets.txt deleted file mode 100644 index b07e70021b..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/sets.txt +++ /dev/null @@ -1,695 +0,0 @@ -=IPSet Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Basic operations. - -{{{ - ->>> IPSet() -IPSet([]) - ->>> IPSet([]) -IPSet([]) - ->>> len(IPSet([])) -0 - -len() fails when the IPSet is longer than sys.maxint, which is most likely with IPv6. ->>> from netaddr.compat import _sys_maxint ->>> s = IPSet(IPRange(IPAddress("::0"), IPAddress(_sys_maxint, 6))) ->>> len(s) -Traceback (most recent call last): - File "", line 1, in - ... -IndexError: range contains more than ... - ->>> s = IPSet(IPRange(IPAddress("::0"), IPAddress(_sys_maxint - 1, 6))) ->>> len(s) == _sys_maxint -True - -IPSets must be usable in boolean context, even when they are very large. ->>> s6 = IPSet(['2405:8100::/32']) ->>> bool(s6) -True ->>> bool(IPSet()) -False - ->>> IPSet(['192.0.2.0']) -IPSet(['192.0.2.0/32']) - ->>> IPSet([IPAddress('192.0.2.0')]) -IPSet(['192.0.2.0/32']) - ->>> IPSet([IPNetwork('192.0.2.0')]) -IPSet(['192.0.2.0/32']) - ->>> IPSet(IPNetwork('1234::/32')) -IPSet(['1234::/32']) - ->>> IPSet([IPNetwork('192.0.2.0/24')]) -IPSet(['192.0.2.0/24']) - ->>> IPSet(IPSet(['192.0.2.0/32'])) -IPSet(['192.0.2.0/32']) - ->>> IPSet(IPRange("10.0.0.0", "10.0.1.31")) -IPSet(['10.0.0.0/24', '10.0.1.0/27']) - ->>> IPSet(IPRange('0.0.0.0', '255.255.255.255')) -IPSet(['0.0.0.0/0']) - ->>> for ip in IPSet(['192.0.2.0/28', '::192.0.2.0/124']): -... print(ip) -192.0.2.0 -192.0.2.1 -192.0.2.2 -192.0.2.3 -192.0.2.4 -192.0.2.5 -192.0.2.6 -192.0.2.7 -192.0.2.8 -192.0.2.9 -192.0.2.10 -192.0.2.11 -192.0.2.12 -192.0.2.13 -192.0.2.14 -192.0.2.15 -::192.0.2.0 -::192.0.2.1 -::192.0.2.2 -::192.0.2.3 -::192.0.2.4 -::192.0.2.5 -::192.0.2.6 -::192.0.2.7 -::192.0.2.8 -::192.0.2.9 -::192.0.2.10 -::192.0.2.11 -::192.0.2.12 -::192.0.2.13 -::192.0.2.14 -::192.0.2.15 - -}}} - -Adding and removing elements. - -{{{ - ->>> s1 = IPSet() - ->>> s1.add('192.0.2.0') - ->>> s1 -IPSet(['192.0.2.0/32']) - ->>> s1.remove('192.0.2.0') - ->>> s1 -IPSet([]) - ->>> s1.remove('192.0.2.0') ->>> s1 -IPSet([]) - ->>> s1.add(IPRange("10.0.0.0", "10.0.0.255")) ->>> s1 -IPSet(['10.0.0.0/24']) - ->>> s1.remove(IPRange("10.0.0.128", "10.10.10.10")) ->>> s1 -IPSet(['10.0.0.0/25']) - -This hits a special case in IPSet._compact_single_network() ->>> s1.add('10.0.0.0/24') ->>> s1 -IPSet(['10.0.0.0/24']) - -Various places must also accept integers. ->>> integer1 = int(IPAddress('10.0.0.1')) ->>> integer2 = int(IPAddress('fe80::')) ->>> integer3 = int(IPAddress('10.0.0.2')) ->>> s2 = IPSet([integer1, integer2]) ->>> s2 -IPSet(['10.0.0.1/32', 'fe80::/128']) ->>> s2.add(integer3) ->>> s2 -IPSet(['10.0.0.1/32', '10.0.0.2/32', 'fe80::/128']) ->>> s2.remove(integer2) ->>> s2 -IPSet(['10.0.0.1/32', '10.0.0.2/32']) ->>> s2.update([integer2]) ->>> s2 -IPSet(['10.0.0.1/32', '10.0.0.2/32', 'fe80::/128']) - -}}} - -Set membership. - -{{{ - ->>> iprange = IPRange('192.0.1.255', '192.0.2.16') - ->>> iprange.cidrs() -[IPNetwork('192.0.1.255/32'), IPNetwork('192.0.2.0/28'), IPNetwork('192.0.2.16/32')] - ->>> ipset = IPSet(['192.0.2.0/28']) - ->>> for ip in iprange: -... print(ip, ip in ipset) -192.0.1.255 False -192.0.2.0 True -192.0.2.1 True -192.0.2.2 True -192.0.2.3 True -192.0.2.4 True -192.0.2.5 True -192.0.2.6 True -192.0.2.7 True -192.0.2.8 True -192.0.2.9 True -192.0.2.10 True -192.0.2.11 True -192.0.2.12 True -192.0.2.13 True -192.0.2.14 True -192.0.2.15 True -192.0.2.16 False - ->>> bigone = IPSet(['0.0.0.0/0']) ->>> IPAddress("10.0.0.1") in bigone -True ->>> IPAddress("0.0.0.0") in bigone -True ->>> IPAddress("255.255.255") in bigone -True ->>> IPNetwork("10.0.0.0/24") in bigone -True ->>> IPAddress("::1") in bigone -False - ->>> smallone = IPSet(["10.0.0.42/32"]) ->>> IPAddress("10.0.0.42") in smallone -True ->>> IPAddress("10.0.0.41") in smallone -False ->>> IPAddress("10.0.0.43") in smallone -False ->>> IPNetwork("10.0.0.42/32") in smallone -True ->>> IPNetwork("10.0.0.42/31") in smallone -False - -}}} - -Set union. - -{{{ - ->>> IPSet(['192.0.2.0']) -IPSet(['192.0.2.0/32']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) -IPSet(['192.0.2.0/31']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3']) -IPSet(['192.0.2.0/31', '192.0.2.3/32']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3/30']) -IPSet(['192.0.2.0/30']) - ->>> IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3/31']) -IPSet(['192.0.2.0/30']) - ->>> IPSet(['192.0.2.0/24']) | IPSet(['192.0.3.0/24']) | IPSet(['192.0.4.0/24']) -IPSet(['192.0.2.0/23', '192.0.4.0/24']) - -}}} - -A joined up example of the union, intersection and symmetric difference operations. - -{{{ - ->>> adj_cidrs = list(IPNetwork('192.0.2.0/24').subnet(28)) ->>> even_cidrs = adj_cidrs[::2] - ->>> evens = IPSet(even_cidrs) ->>> evens -IPSet(['192.0.2.0/28', '192.0.2.32/28', '192.0.2.64/28', '192.0.2.96/28', '192.0.2.128/28', '192.0.2.160/28', '192.0.2.192/28', '192.0.2.224/28']) - ->>> IPSet(['192.0.2.0/24']) & evens -IPSet(['192.0.2.0/28', '192.0.2.32/28', '192.0.2.64/28', '192.0.2.96/28', '192.0.2.128/28', '192.0.2.160/28', '192.0.2.192/28', '192.0.2.224/28']) - ->>> odds = IPSet(['192.0.2.0/24']) ^ evens ->>> odds -IPSet(['192.0.2.16/28', '192.0.2.48/28', '192.0.2.80/28', '192.0.2.112/28', '192.0.2.144/28', '192.0.2.176/28', '192.0.2.208/28', '192.0.2.240/28']) - ->>> evens | odds -IPSet(['192.0.2.0/24']) - ->>> evens & odds -IPSet([]) - ->>> evens ^ odds -IPSet(['192.0.2.0/24']) - -}}} - -Superset and subset tests. - -{{{ - ->>> s1 = IPSet(['192.0.2.0/24', '192.0.4.0/24']) ->>> s2 = IPSet(['192.0.2.0', '192.0.4.0']) - ->>> s1 -IPSet(['192.0.2.0/24', '192.0.4.0/24']) - ->>> s2 -IPSet(['192.0.2.0/32', '192.0.4.0/32']) - ->>> s1.issuperset(s2) -True - ->>> s2.issubset(s1) -True - ->>> s2.issuperset(s1) -False - ->>> s1.issubset(s2) -False - -}}} - - - -{{{ - ->>> ipv4_addr_space = IPSet(['0.0.0.0/0']) - ->>> private = IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '239.192.0.0/14']) - ->>> reserved = IPSet(['225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '240.0.0.0/4']) - ->>> unavailable = reserved | private - ->>> available = ipv4_addr_space ^ unavailable - ->>> for cidr in available.iter_cidrs(): -... print(cidr, cidr[0], cidr[-1]) -0.0.0.0/5 0.0.0.0 7.255.255.255 -8.0.0.0/7 8.0.0.0 9.255.255.255 -11.0.0.0/8 11.0.0.0 11.255.255.255 -12.0.0.0/6 12.0.0.0 15.255.255.255 -16.0.0.0/4 16.0.0.0 31.255.255.255 -32.0.0.0/3 32.0.0.0 63.255.255.255 -64.0.0.0/2 64.0.0.0 127.255.255.255 -128.0.0.0/3 128.0.0.0 159.255.255.255 -160.0.0.0/5 160.0.0.0 167.255.255.255 -168.0.0.0/6 168.0.0.0 171.255.255.255 -172.0.0.0/12 172.0.0.0 172.15.255.255 -172.32.0.0/11 172.32.0.0 172.63.255.255 -172.64.0.0/10 172.64.0.0 172.127.255.255 -172.128.0.0/9 172.128.0.0 172.255.255.255 -173.0.0.0/8 173.0.0.0 173.255.255.255 -174.0.0.0/7 174.0.0.0 175.255.255.255 -176.0.0.0/4 176.0.0.0 191.255.255.255 -192.0.0.0/23 192.0.0.0 192.0.1.255 -192.0.3.0/24 192.0.3.0 192.0.3.255 -192.0.4.0/22 192.0.4.0 192.0.7.255 -192.0.8.0/21 192.0.8.0 192.0.15.255 -192.0.16.0/20 192.0.16.0 192.0.31.255 -192.0.32.0/19 192.0.32.0 192.0.63.255 -192.0.64.0/18 192.0.64.0 192.0.127.255 -192.0.128.0/17 192.0.128.0 192.0.255.255 -192.1.0.0/16 192.1.0.0 192.1.255.255 -192.2.0.0/15 192.2.0.0 192.3.255.255 -192.4.0.0/14 192.4.0.0 192.7.255.255 -192.8.0.0/13 192.8.0.0 192.15.255.255 -192.16.0.0/12 192.16.0.0 192.31.255.255 -192.32.0.0/11 192.32.0.0 192.63.255.255 -192.64.0.0/10 192.64.0.0 192.127.255.255 -192.128.0.0/11 192.128.0.0 192.159.255.255 -192.160.0.0/13 192.160.0.0 192.167.255.255 -192.169.0.0/16 192.169.0.0 192.169.255.255 -192.170.0.0/15 192.170.0.0 192.171.255.255 -192.172.0.0/14 192.172.0.0 192.175.255.255 -192.176.0.0/12 192.176.0.0 192.191.255.255 -192.192.0.0/10 192.192.0.0 192.255.255.255 -193.0.0.0/8 193.0.0.0 193.255.255.255 -194.0.0.0/7 194.0.0.0 195.255.255.255 -196.0.0.0/6 196.0.0.0 199.255.255.255 -200.0.0.0/5 200.0.0.0 207.255.255.255 -208.0.0.0/4 208.0.0.0 223.255.255.255 -224.0.0.0/8 224.0.0.0 224.255.255.255 -232.0.0.0/7 232.0.0.0 233.255.255.255 -239.0.0.0/9 239.0.0.0 239.127.255.255 -239.128.0.0/10 239.128.0.0 239.191.255.255 -239.196.0.0/14 239.196.0.0 239.199.255.255 -239.200.0.0/13 239.200.0.0 239.207.255.255 -239.208.0.0/12 239.208.0.0 239.223.255.255 -239.224.0.0/11 239.224.0.0 239.255.255.255 - ->>> ipv4_addr_space ^ available -IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '239.192.0.0/14', '240.0.0.0/4']) - -}}} - -==Tests on combined IPv4 and IPv6 sets== - -{{{ - ->>> s1 = IPSet(['192.0.2.0', '::192.0.2.0', '192.0.2.2', '::192.0.2.2']) ->>> s2 = IPSet(['192.0.2.2', '::192.0.2.2', '192.0.2.4', '::192.0.2.4']) - -IPSets with IPNetworks that need to be merged or split (sometimes multiple times) during various set operations. -IPNetwork('10.0.0.64/30') is the same as IPRange('10.0.0.64', '10.0.0.67') ->>> s3 = IPSet(['0.0.0.1', '10.0.0.64/30', '255.255.255.1']) ->>> s4 = IPSet(['10.0.0.64', '10.0.0.66']) ->>> s4b = IPSet(['10.0.0.64', '10.0.0.66', '111.111.111.111']) ->>> s5 = IPSet(['10.0.0.65', '10.0.0.67']) - ->>> s1 -IPSet(['192.0.2.0/32', '192.0.2.2/32', '::192.0.2.0/128', '::192.0.2.2/128']) - ->>> s2 -IPSet(['192.0.2.2/32', '192.0.2.4/32', '::192.0.2.2/128', '::192.0.2.4/128']) - -}}} - -Set union. - -{{{ - ->>> s1 | s2 -IPSet(['192.0.2.0/32', '192.0.2.2/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.2/128', '::192.0.2.4/128']) ->>> s2 | s1 -IPSet(['192.0.2.0/32', '192.0.2.2/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.2/128', '::192.0.2.4/128']) - -}}} - -Set intersection. - -{{{ - ->>> s1 & s2 -IPSet(['192.0.2.2/32', '::192.0.2.2/128']) ->>> s2 & s1 -IPSet(['192.0.2.2/32', '::192.0.2.2/128']) - ->>> s3 & s4 -IPSet(['10.0.0.64/32', '10.0.0.66/32']) ->>> s4 & s3 -IPSet(['10.0.0.64/32', '10.0.0.66/32']) - ->>> s3 & s5 -IPSet(['10.0.0.65/32', '10.0.0.67/32']) ->>> s5 & s3 -IPSet(['10.0.0.65/32', '10.0.0.67/32']) - -}}} - -Set difference. - -{{{ - ->>> s1 - s2 -IPSet(['192.0.2.0/32', '::192.0.2.0/128']) - ->>> s2 - s1 -IPSet(['192.0.2.4/32', '::192.0.2.4/128']) - ->>> s3 - s4 -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) ->>> s4 - s3 -IPSet([]) ->>> s3 - s4b -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) - ->>> s3 - s5 -IPSet(['0.0.0.1/32', '10.0.0.64/32', '10.0.0.66/32', '255.255.255.1/32']) ->>> s5 - s3 -IPSet([]) - -}}} - -Symmetric set difference. - -{{{ - ->>> s1 ^ s2 -IPSet(['192.0.2.0/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.4/128']) ->>> s2 ^ s1 -IPSet(['192.0.2.0/32', '192.0.2.4/32', '::192.0.2.0/128', '::192.0.2.4/128']) - ->>> IPSet([]) ^ IPSet([]) -IPSet([]) ->>> IPSet(['0.0.0.1/32']) ^ IPSet([]) -IPSet(['0.0.0.1/32']) ->>> IPSet(['0.0.0.1/32']) ^ IPSet(['0.0.0.1/32']) -IPSet([]) - ->>> s3 ^ s4 -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) ->>> s4 ^ s3 -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '255.255.255.1/32']) ->>> s3 ^ s4b -IPSet(['0.0.0.1/32', '10.0.0.65/32', '10.0.0.67/32', '111.111.111.111/32', '255.255.255.1/32']) - ->>> s3 ^ s5 -IPSet(['0.0.0.1/32', '10.0.0.64/32', '10.0.0.66/32', '255.255.255.1/32']) ->>> s5 ^ s3 -IPSet(['0.0.0.1/32', '10.0.0.64/32', '10.0.0.66/32', '255.255.255.1/32']) - -}}} - -Disjointed sets. - -{{{ - ->>> s1 = IPSet(['192.0.2.0', '192.0.2.1', '192.0.2.2']) - ->>> s2 = IPSet(['192.0.2.2', '192.0.2.3', '192.0.2.4']) - ->>> s1 & s2 -IPSet(['192.0.2.2/32']) - ->>> s1.isdisjoint(s2) -False - ->>> s1 = IPSet(['192.0.2.0', '192.0.2.1']) - ->>> s2 = IPSet(['192.0.2.3', '192.0.2.4']) - ->>> s1 & s2 -IPSet([]) - ->>> s1.isdisjoint(s2) -True - -}}} - -Updating a set. - -{{{ - ->>> s1 = IPSet(['192.0.2.0/25']) ->>> s1 -IPSet(['192.0.2.0/25']) - ->>> s2 = IPSet(['192.0.2.128/25']) ->>> s2 -IPSet(['192.0.2.128/25']) - ->>> s1.update(s2) - ->>> s1 -IPSet(['192.0.2.0/24']) - ->>> s1.update(['192.0.0.0/24', '192.0.1.0/24', '192.0.3.0/24']) ->>> s1 -IPSet(['192.0.0.0/22']) - ->>> s2 = IPSet(['10.0.0.0/16']) ->>> s2.update(IPRange('10.1.0.0', '10.1.255.255')) ->>> s2 -IPSet(['10.0.0.0/15']) - ->>> s2.clear() ->>> s2 -IPSet([]) - -}}} - -Removing IP addresses from an IPSet. - -{{{ - ->>> s1 = IPSet(['0.0.0.0/0']) - ->>> s1 -IPSet(['0.0.0.0/0']) - ->>> s1.remove('255.255.255.255') - ->>> s1 -IPSet(['0.0.0.0/1', '128.0.0.0/2', ..., '255.255.255.252/31', '255.255.255.254/32']) - ->>> list(s1.iter_cidrs()) -[IPNetwork('0.0.0.0/1'), IPNetwork('128.0.0.0/2'), ..., IPNetwork('255.255.255.252/31'), IPNetwork('255.255.255.254/32')] - ->>> len(list(s1.iter_cidrs())) -32 - ->>> list(s1.iter_cidrs()) == cidr_exclude('0.0.0.0/0', '255.255.255.255') -True - ->>> s1.remove('0.0.0.0') - ->>> s1 -IPSet(['0.0.0.1/32', '0.0.0.2/31', ..., '255.255.255.252/31', '255.255.255.254/32']) - ->>> len(list(s1.iter_cidrs())) -62 - -}}} - -Adding IP address to an IPSet. - -{{{ - ->>> s1.add('255.255.255.255') - ->>> s1 -IPSet(['0.0.0.1/32', '0.0.0.2/31', ..., '64.0.0.0/2', '128.0.0.0/1']) - ->>> list(s1.iter_cidrs()) -[IPNetwork('0.0.0.1/32'), IPNetwork('0.0.0.2/31'), ..., IPNetwork('64.0.0.0/2'), IPNetwork('128.0.0.0/1')] - ->>> len(list(s1.iter_cidrs())) -32 - ->>> s1.add('0.0.0.0') - ->>> s1 -IPSet(['0.0.0.0/0']) - -}}} - -Converting an IP set to an IP range - -{{{ - ->>> s1 = IPSet(['10.0.0.0/25', '10.0.0.128/25']) ->>> s1.iprange() -IPRange('10.0.0.0', '10.0.0.255') ->>> s1.iscontiguous() -True ->>> s1.remove('10.0.0.16') ->>> s1 -IPSet(['10.0.0.0/28', '10.0.0.17/32', '10.0.0.18/31', '10.0.0.20/30', '10.0.0.24/29', '10.0.0.32/27', '10.0.0.64/26', '10.0.0.128/25']) ->>> s1.iscontiguous() -False ->>> s1.iprange() -Traceback (most recent call last): - ... -ValueError: IPSet is not contiguous - ->>> list(s1.iter_ipranges()) -[IPRange('10.0.0.0', '10.0.0.15'), IPRange('10.0.0.17', '10.0.0.255')] - ->>> list(IPSet().iter_ipranges()) -[] - ->>> list(IPSet([IPAddress('10.0.0.1')]).iter_ipranges()) -[IPRange('10.0.0.1', '10.0.0.1')] - -Adjacent, non-mergable CIDRs must be merged by iter_ipranges(). ->>> list(IPSet([IPAddress('10.0.0.1'), IPAddress('10.0.0.2')]).iter_ipranges()) -[IPRange('10.0.0.1', '10.0.0.2')] - -IPv4 and IPv6 addresses must not be merged. ->>> list(IPSet([IPAddress(1, 4), IPAddress(1, 6)]).iter_ipranges()) -[IPRange('0.0.0.1', '0.0.0.1'), IPRange('::1', '::1')] - ->>> s2 = IPSet(['0.0.0.0/0']) ->>> s2.iscontiguous() -True ->>> s2.iprange() -IPRange('0.0.0.0', '255.255.255.255') - ->>> s3 = IPSet() ->>> s3.iscontiguous() -True ->>> s3.iprange() - ->>> s4 = IPSet(IPRange('10.0.0.0', '10.0.0.8')) ->>> s4.iscontiguous() -True - -}}} - -Pickling of IPSet objects - -{{{ - ->>> import pickle ->>> ip_data = IPSet(['10.0.0.0/16', 'fe80::/64']) ->>> buf = pickle.dumps(ip_data) ->>> ip_data_unpickled = pickle.loads(buf) ->>> ip_data == ip_data_unpickled -True - -}}} - - -Compare IPSet objects - -{{{ - ->>> x = IPSet(['fc00::/2']) ->>> y = IPSet(['fc00::/3']) - ->>> x > y -True - ->>> x < y -False - ->>> x != y -True - -}}} - -Various exceptions - -{{{ - ->>> s1 = IPSet(['10.0.0.1']) - ->>> hash(s1) -Traceback (most recent call last): -TypeError: IP sets are unhashable! - ->>> s1.update(42) -Traceback (most recent call last): -TypeError: an iterable was expected! - -In the following cases, the exceptions are caught and translated to booleans. ->>> s1 == 42 -False ->>> s1 != 42 -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/socket_fallback.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/socket_fallback.txt deleted file mode 100644 index 19ae821ab4..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/socket_fallback.txt +++ /dev/null @@ -1,88 +0,0 @@ -=Socket Fallback Module Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.fbsocket import * - -}}} - -IPv6 '::' compression algorithm tests. - -{{{ - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:0:0:0:0:0')) -'::' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:0:0:0:0:A')) -'::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:0:0:0:0:0')) -'a::' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:A:0:0:0:0:0')) -'a:0:a::' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:0:0:0:0:A')) -'a::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:A:0:0:0:0:0:A')) -'0:a::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:A:0:0:0:0:A')) -'a:0:a::a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:A:0:0:0:A')) -'::a:0:0:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:0:0:0:A:0:0:A')) -'::a:0:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:0:0:A:0:A')) -'a::a:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:0:A:0:0:A:0')) -'a::a:0:0:a:0' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'A:0:A:0:A:0:A:0')) -'a:0:a:0:a:0:a:0' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '0:A:0:A:0:A:0:A')) -'0:a:0:a:0:a:0:a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, '1080:0:0:0:8:800:200C:417A')) -'1080::8:800:200c:417a' - ->>> inet_ntop(AF_INET6, inet_pton(AF_INET6, 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210')) -'fedc:ba98:7654:3210:fedc:ba98:7654:3210' - -}}} - -IPv4 failure tests - -{{{ - ->>> inet_ntoa(1) -Traceback (most recent call last): -... -TypeError: string type expected, not - - ->>> inet_ntoa('\x00') -Traceback (most recent call last): -... -ValueError: invalid length of packed IP address string - -}}} - -IPv6 failure tests. - -{{{ - ->>> inet_pton(AF_INET6, '::0x07f') -Traceback (most recent call last): -... -ValueError: illegal IP address string '::0x07f' - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/subnet.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/subnet.txt deleted file mode 100644 index 493885ddd8..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/subnet.txt +++ /dev/null @@ -1,108 +0,0 @@ -=IP Subnet Tests= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr import * - -}}} - -Incrementing IP objects. - -{{{ - ->>> ip = IPNetwork('192.0.2.0/28') ->>> for i in range(16): -... str(ip) -... ip += 1 -'192.0.2.0/28' -'192.0.2.16/28' -'192.0.2.32/28' -'192.0.2.48/28' -'192.0.2.64/28' -'192.0.2.80/28' -'192.0.2.96/28' -'192.0.2.112/28' -'192.0.2.128/28' -'192.0.2.144/28' -'192.0.2.160/28' -'192.0.2.176/28' -'192.0.2.192/28' -'192.0.2.208/28' -'192.0.2.224/28' -'192.0.2.240/28' - ->>> ip = IPNetwork('2001:470:1f04::/48') ->>> for i in ip.subnet(128): -... print (i) -... break -2001:470:1f04::/128 - -}}} - -IP address and subnet sortability. - -{{{ - ->>> ip_list = [] - ->>> for subnet in IPNetwork('192.0.2.0/24').subnet(28, 3): -... ip_list.append(subnet) -... ip_list.extend([ip for ip in subnet]) - ->>> for addr in sorted(ip_list): -... print('%r' % addr) -IPNetwork('192.0.2.0/28') -IPAddress('192.0.2.0') -IPAddress('192.0.2.1') -IPAddress('192.0.2.2') -IPAddress('192.0.2.3') -IPAddress('192.0.2.4') -IPAddress('192.0.2.5') -IPAddress('192.0.2.6') -IPAddress('192.0.2.7') -IPAddress('192.0.2.8') -IPAddress('192.0.2.9') -IPAddress('192.0.2.10') -IPAddress('192.0.2.11') -IPAddress('192.0.2.12') -IPAddress('192.0.2.13') -IPAddress('192.0.2.14') -IPAddress('192.0.2.15') -IPNetwork('192.0.2.16/28') -IPAddress('192.0.2.16') -IPAddress('192.0.2.17') -IPAddress('192.0.2.18') -IPAddress('192.0.2.19') -IPAddress('192.0.2.20') -IPAddress('192.0.2.21') -IPAddress('192.0.2.22') -IPAddress('192.0.2.23') -IPAddress('192.0.2.24') -IPAddress('192.0.2.25') -IPAddress('192.0.2.26') -IPAddress('192.0.2.27') -IPAddress('192.0.2.28') -IPAddress('192.0.2.29') -IPAddress('192.0.2.30') -IPAddress('192.0.2.31') -IPNetwork('192.0.2.32/28') -IPAddress('192.0.2.32') -IPAddress('192.0.2.33') -IPAddress('192.0.2.34') -IPAddress('192.0.2.35') -IPAddress('192.0.2.36') -IPAddress('192.0.2.37') -IPAddress('192.0.2.38') -IPAddress('192.0.2.39') -IPAddress('192.0.2.40') -IPAddress('192.0.2.41') -IPAddress('192.0.2.42') -IPAddress('192.0.2.43') -IPAddress('192.0.2.44') -IPAddress('192.0.2.45') -IPAddress('192.0.2.46') -IPAddress('192.0.2.47') - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/ip/tutorial.txt b/awx/lib/site-packages/netaddr/tests/3.x/ip/tutorial.txt deleted file mode 100644 index f9a0e2c2cc..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/ip/tutorial.txt +++ /dev/null @@ -1,1002 +0,0 @@ -=IP Address Tutorial= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -This unit test serves as both testing of the netaddr API and an executable tutorial courtesy of the doctest and unittest modules in the Python standard library. - -Let's start with the standard module import. - -{{{ - ->>> from netaddr import * ->>> import pprint - -}}} - -You can safely import everything from the netaddr namespace as care has been taken to only export the necessary classes, functions and constants. - -You can always hand pick them if you are unsure about possible name clashes. - -We install the standard library module `pprint` to help format some output. - - -==Basic IP Address Operations== - -This IP object represents a single address. - -{{{ - ->>> ip = IPAddress('192.0.2.1') - ->>> ip.version -4 - -}}} - -Standard `repr()` access returns a Python statement that can reconstruct an equivalent IP address object from scratch if executed in the Python interpreter. - -{{{ - ->>> repr(ip) -"IPAddress('192.0.2.1')" - ->>> ip -IPAddress('192.0.2.1') - -}}} - -Access in the string context returns the IP object as a string value. - -{{{ - ->>> str(ip) -'192.0.2.1' - ->>> '%s' % ip -'192.0.2.1' - ->>> ip.format() # only really useful for IPv6 addresses. -'192.0.2.1' - -}}} - -==IP Address Numerical Representations== - -You can view an IP address in various other formats. - -{{{ - ->>> int(ip) == 3221225985 -True - ->>> hex(ip) -'0xc0000201' - ->>> ip.bin -'0b11000000000000000000001000000001' - ->>> ip.bits() -'11000000.00000000.00000010.00000001' - ->>> ip.words == (192, 0, 2, 1) -True - -}}} - -==Representing IP Subnets== - -IPNetwork objects are used to represent subnets that accept netmasks and CIDR prefixes. - -{{{ - ->>> ip = IPNetwork('192.0.2.1') - ->>> ip.ip -IPAddress('192.0.2.1') - ->>> ip.network, ip.broadcast -(IPAddress('192.0.2.1'), IPAddress('192.0.2.1')) - ->>> ip.netmask, ip.hostmask -(IPAddress('255.255.255.255'), IPAddress('0.0.0.0')) - ->>> ip.size -1 - -}}} - -In this case, the network and broadcast address are the same, akin to a host route. - -{{{ - ->>> ip = IPNetwork('192.0.2.0/24') - ->>> ip.ip -IPAddress('192.0.2.0') - ->>> ip.network, ip.broadcast -(IPAddress('192.0.2.0'), IPAddress('192.0.2.255')) - ->>> ip.netmask, ip.hostmask -(IPAddress('255.255.255.0'), IPAddress('0.0.0.255')) - ->>> ip.size -256 - -}}} - -And finally, this IPNetwork object represents an IP address that belongs to a given IP subnet. - -{{{ - ->>> ip = IPNetwork('192.0.3.112/22') - ->>> ip.ip -IPAddress('192.0.3.112') - ->>> ip.network, ip.broadcast -(IPAddress('192.0.0.0'), IPAddress('192.0.3.255')) - ->>> ip.netmask, ip.hostmask -(IPAddress('255.255.252.0'), IPAddress('0.0.3.255')) - ->>> ip.size -1024 - -}}} - -Internally, each IPNetwork object only stores 3 values :- - - * the IP address value as an unsigned integer - * a reference to the IP protocol module for the IP version being represented - * the network CIDR prefix bitmask - -All the other values are calculated on-the-fly as they are accessed. - -It is possible to adjust the IP address value and the CIDR prefix after object instantiation. - -{{{ - ->>> ip = IPNetwork('0.0.0.0/0') - ->>> ip -IPNetwork('0.0.0.0/0') - ->>> ip.value = 3221225985 - ->>> ip -IPNetwork('192.0.2.1/0') - ->>> ip.prefixlen -0 - ->>> ip.prefixlen = 23 - ->>> ip -IPNetwork('192.0.2.1/23') - -}}} - -There is also a property that lets you access the *true* CIDR address which removes all host bits from the network address based on the CIDR subnet prefix. - -{{{ - ->>> ip.cidr -IPNetwork('192.0.2.0/23') - -}}} - -This is handy for specifying some networking configurations correctly. - -If you want to access information about each of the various IP addresses that form the IP subnet, this is available by performing pass through calls to sub methods of each `IPAddress` object. - -For example if you want to see a binary digit representation of each address you can do the following. - -{{{ - ->>> ip.ip.bits() -'11000000.00000000.00000010.00000001' - ->>> ip.network.bits() -'11000000.00000000.00000010.00000000' - ->>> ip.netmask.bits() -'11111111.11111111.11111110.00000000' - ->>> ip.broadcast.bits() -'11000000.00000000.00000011.11111111' - -}}} - -==IPv6 support== - -Full support for IPv6 addressing is provided as well. To prove this, let's try a few examples. - -{{{ - ->>> ip = IPAddress(0, 6) - ->>> ip -IPAddress('::') - ->>> ip = IPNetwork('fe80::dead:beef/64') - ->>> str(ip), ip.prefixlen, ip.version -('fe80::dead:beef/64', 64, 6) - ->>> int(ip.ip) == 338288524927261089654018896845083623151 -True - ->>> hex(ip.ip) -'0xfe8000000000000000000000deadbeef' - -}}} - -Bit-style output isn't as quite as friendly as hexadecimal for such a long numbers, but here the proof that it works! - -{{{ - ->>> ip.ip.bits() -'1111111010000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:1101111010101101:1011111011101111' - -}}} - -Here are some networking details for an IPv6 subnet. - -{{{ - ->>> ip.network, ip.broadcast, ip.netmask, ip.hostmask -(IPAddress('fe80::'), IPAddress('fe80::ffff:ffff:ffff:ffff'), IPAddress('ffff:ffff:ffff:ffff::'), IPAddress('::ffff:ffff:ffff:ffff')) - -}}} - -==IPv4 / IPv6 Interoperability== - -It is likely that with IPv6 becoming more prevalent, you'll want to be able to interoperate between IPv4 and IPv6 address seemlessly. - -Here are a couple of methods that help achieve this. - -===IPv4 to IPv6=== - -{{{ - ->>> IPAddress('192.0.2.15').ipv4() -IPAddress('192.0.2.15') - ->>> ip = IPAddress('192.0.2.15').ipv6() ->>> ip -IPAddress('::ffff:192.0.2.15') ->>> ip.is_ipv4_mapped() -True ->>> ip.is_ipv4_compat() -False - ->>> IPAddress('192.0.2.15').ipv6(ipv4_compatible=True) -IPAddress('::192.0.2.15') ->>> IPAddress('192.0.2.15').ipv6(ipv4_compatible=True).is_ipv4_compat() -True ->>> IPAddress('192.0.2.15').ipv6(True) -IPAddress('::192.0.2.15') - ->>> ip = IPNetwork('192.0.2.1/23') - ->>> ip.ipv4() -IPNetwork('192.0.2.1/23') - ->>> ip.ipv6() -IPNetwork('::ffff:192.0.2.1/119') - ->>> ip.ipv6(ipv4_compatible=True) -IPNetwork('::192.0.2.1/119') - -}}} - -===IPv6 to IPv4=== - -{{{ - ->>> IPNetwork('::ffff:192.0.2.1/119').ipv4() -IPNetwork('192.0.2.1/23') - ->>> IPNetwork('::192.0.2.1/119').ipv4() -IPNetwork('192.0.2.1/23') - -}}} - -Note that the IP object returns IPv4 "mapped" addresses by default in preference to IPv4 "compatible" ones. This has been chosen purposefully as the latter form has been deprecated (see RFC 4291 for details). - -==List Operations On IP Objects== - -If you treat an IP network object as if it were a standard Python list object it will give you access to a list of individual IP address objects. This of course is illusory and they are not created until you access them. - -{{{ - ->>> ip = IPNetwork('192.0.2.16/29') - -}}} - -Accessing an IP object using the list() context invokes the default generator which returns a list of all IP objects in the range specified by the IP object's subnet. - -{{{ - ->>> ip_list = list(ip) - ->>> len(ip_list) -8 - ->>> ip_list -[IPAddress('192.0.2.16'), IPAddress('192.0.2.17'), ..., IPAddress('192.0.2.22'), IPAddress('192.0.2.23')] - -}}} - -The length of that list is 8 individual IP addresses. - -{{{ - ->>> len(ip) -8 - -}}} - -You can use standard index access to IP addresses in the subnet. - -{{{ - ->>> ip[0] -IPAddress('192.0.2.16') - ->>> ip[1] -IPAddress('192.0.2.17') - ->>> ip[-1] -IPAddress('192.0.2.23') - -}}} - -You can even uses extended slices on IP addresses in the subnet. - -{{{ - ->>> ip[0:4] - - -}}} - -The slice is actually a generator function. This is to save time and system resources. Some slices can obviously end up being extremely large for some subnets! - -Here is how you'd access all elements in a slice. - -{{{ - ->>> list(ip[0:4]) -[IPAddress('192.0.2.16'), IPAddress('192.0.2.17'), IPAddress('192.0.2.18'), IPAddress('192.0.2.19')] - -}}} - -Extended slicing is also supported. - -{{{ - ->>> list(ip[0::2]) -[IPAddress('192.0.2.16'), IPAddress('192.0.2.18'), IPAddress('192.0.2.20'), IPAddress('192.0.2.22')] - -}}} - -List reversal. - -{{{ - ->>> list(ip[-1::-1]) -[IPAddress('192.0.2.23'), IPAddress('192.0.2.22'), ..., IPAddress('192.0.2.17'), IPAddress('192.0.2.16')] - -}}} - -Use of generators ensures working with large IP subnets is efficient. - -{{{ - ->>> for ip in IPNetwork('192.0.2.0/23'): -... print('%s' % ip) -... -192.0.2.0 -192.0.2.1 -192.0.2.2 -192.0.2.3 -... -192.0.3.252 -192.0.3.253 -192.0.3.254 -192.0.3.255 - -}}} - -In IPv4 networks you only usually assign the addresses between the network and broadcast addresses to actual host interfaces on systems. - -Here is the iterator provided for accessing these IP addresses :- - -{{{ - ->>> for ip in IPNetwork('192.0.2.0/23').iter_hosts(): -... print('%s' % ip) -... -192.0.2.1 -192.0.2.2 -192.0.2.3 -192.0.2.4 -... -192.0.3.251 -192.0.3.252 -192.0.3.253 -192.0.3.254 - -}}} - -==Sorting Collection Of IP Objects== - -It is fairly common and useful to be able to sort IP addresses correctly (in numerical order). - -Here is how sorting works with individual addresses. - -{{{ - ->>> import random - ->>> ip_list = list(IPNetwork('192.0.2.128/28')) - ->>> random.shuffle(ip_list) - ->>> sorted(ip_list) -[IPAddress('192.0.2.128'), IPAddress('192.0.2.129'), ..., IPAddress('192.0.2.142'), IPAddress('192.0.2.143')] - -}}} - -You can just as easily sort IP subnets at the same time, including combinations of IPv4 and IPv6 addresses as well. - -{{{ - ->>> ip_list = [ -... IPAddress('192.0.2.130'), -... IPAddress('10.0.0.1'), -... IPNetwork('192.0.2.128/28'), -... IPNetwork('192.0.3.0/24'), -... IPNetwork('192.0.2.0/24'), -... IPNetwork('fe80::/64'), -... IPAddress('::'), -... IPNetwork('172.24/12')] - ->>> random.shuffle(ip_list) - ->>> ip_list.sort() - ->>> pprint.pprint(ip_list) -[IPAddress('10.0.0.1'), - IPNetwork('172.24.0.0/12'), - IPNetwork('192.0.2.0/24'), - IPNetwork('192.0.2.128/28'), - IPAddress('192.0.2.130'), - IPNetwork('192.0.3.0/24'), - IPAddress('::'), - IPNetwork('fe80::/64')] - -}}} - -Notice how IPv4 is ordered before IPv6 and overlapping subnets sort in order from largest subnet to smallest. - -==Merging IP Addresses And Subnets== - -Another useful operation is the ability to summarize groups of IP subnets and addresses, merging them together where possible to create the smallest possible list of CIDR subnets. - -Here is how to do this using the `cidr_merge()` function. - -First we create a list of IP objects that is a good mix of individual addresses and subnets, along with some string based IP address values for good measure. To make things more challenging some IPv6 addresses have been included as well. - -{{{ - ->>> ip_list = [ip for ip in IPNetwork('fe80::/120')] - ->>> ip_list.append(IPNetwork('192.0.2.0/24')) - ->>> ip_list.extend([str(ip) for ip in IPNetwork('192.0.3.0/24')]) - ->>> ip_list.append(IPNetwork('192.0.4.0/25')) - ->>> ip_list.append(IPNetwork('192.0.4.128/25')) - ->>> len(ip_list) -515 - ->>> cidr_merge(ip_list) -[IPNetwork('192.0.2.0/23'), IPNetwork('192.0.4.0/24'), IPNetwork('fe80::/120')] - -}}} - -==Dealing With Arbitrary Lists Of IP Objects== - -While CIDR subnets are a useful construct, sometimes it is necessarily (particularly with IPv4 which predates the CIDR specification) to be able to generate lists of IP addresses that have an arbitrary start and end address that do not fall on bit mask boundaries. - -The iter_iprange() function allow you to do just this. - -{{{ - ->>> ip_list = list(iter_iprange('192.0.2.1', '192.0.2.14')) - ->>> len(ip_list) -14 - ->>> ip_list -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), ..., IPAddress('192.0.2.13'), IPAddress('192.0.2.14')] - -}}} - -It is equally nice to know what the actual list of CIDR subnets is that would correctly cover this non-aligned range of addresses. - -Here `cidr_merge()` comes to the rescue. - -{{{ - ->>> cidr_merge(ip_list) -[IPNetwork('192.0.2.1/32'), IPNetwork('192.0.2.2/31'), IPNetwork('192.0.2.4/30'), IPNetwork('192.0.2.8/30'), IPNetwork('192.0.2.12/31'), IPNetwork('192.0.2.14/32')] - -}}} - -==IP Subnetting And Supernetting== - -It is quite common to have a large CIDR subnet that you may want to split up into multiple smaller component blocks to better manage your networks. - -{{{ - ->>> ip = IPNetwork('172.24.0.0/16') - ->>> ip.subnet(23) - - -}}} - -Again this method produces and iterator because of the possibility for a large number of return values. - -{{{ - ->>> subnets = list(ip.subnet(23)) - ->>> len(subnets) -128 - ->>> subnets -[IPNetwork('172.24.0.0/23'), IPNetwork('172.24.2.0/23'), IPNetwork('172.24.4.0/23'), ..., IPNetwork('172.24.250.0/23'), IPNetwork('172.24.252.0/23'), IPNetwork('172.24.254.0/23')] - -}}} - -It is also possible to retrieve the list of supernets that a given IP address or subnet belongs to (with an optional limit). - -{{{ - ->>> ip = IPNetwork('192.0.2.114') - ->>> supernets = ip.supernet(22) - ->>> pprint.pprint(supernets) -[IPNetwork('192.0.0.0/22'), - IPNetwork('192.0.2.0/23'), - IPNetwork('192.0.2.0/24'), - IPNetwork('192.0.2.0/25'), - IPNetwork('192.0.2.64/26'), - IPNetwork('192.0.2.96/27'), - IPNetwork('192.0.2.112/28'), - IPNetwork('192.0.2.112/29'), - IPNetwork('192.0.2.112/30'), - IPNetwork('192.0.2.114/31')] - -}}} - -This method returns a list because the potential list of values is of a predictable size (no more than 31 CIDRs for an IPv4 address and 127 for IPv6). - -==Dealing With Less Common IP Network Specifications== - -Until the advent of the CIDR specification it was common to infer the netmask of an IPv4 address based on its first octet using an set of classful rules. - -It is common to come across these in various RFCs and they are well supported by a number of software libraries. Rather than leave out this important (mainly historical) set of rules they are catered for using the cidr_abbrev_to_verbose() function. - -Here is an example of these rules for the whole of the IPv4 address space. - -{{{ - ->>> cidrs = [cidr_abbrev_to_verbose(octet) for octet in range(0, 256)] - ->>> pprint.pprint(cidrs) -['0.0.0.0/8', -... - '127.0.0.0/8', - '128.0.0.0/16', -... - '191.0.0.0/16', - '192.0.0.0/24', -... - '223.0.0.0/24', - '224.0.0.0/4', -... - '239.0.0.0/4', - '240.0.0.0/32', -... - '255.0.0.0/32'] - ->>> len(cidrs) -256 - -}}} - -==IP Address Categories== - -IP addresses fall several broad categories and not all are suitable for assignment as system interface addresses. - -Unicast - -{{{ - ->>> IPAddress('192.0.2.1').is_unicast() -True - ->>> IPAddress('fe80::1').is_unicast() -True - -}}} - -Multicast - -{{{ - ->>> IPAddress('239.192.0.1').is_multicast() -True - ->>> IPAddress('ff00::1').is_multicast() -True - -}}} - -Private - -{{{ - ->>> IPAddress('172.24.0.1').is_private() -True - ->>> IPAddress('10.0.0.1').is_private() -True - ->>> IPAddress('192.168.0.1').is_private() -True - ->>> IPAddress('fc00::1').is_private() -True - -}}} - -Reserved - -{{{ - ->>> IPAddress('253.0.0.1').is_reserved() -True - -}}} - -Public (Internet) addresses. - -Note that not all of these may be allocated by the various regional Internet registrars. - -{{{ - ->>> ip = IPAddress('62.125.24.5') - ->>> ip.is_unicast() and not ip.is_private() -True - -}}} - -There are also other types of addresses that have specific functions e.g. masking - -Netmasks - -{{{ - ->>> IPAddress('255.255.254.0').is_netmask() -True - -}}} - -Hostmasks - -{{{ - ->>> IPAddress('0.0.1.255').is_hostmask() -True - -}}} - -Loopback addresses - -{{{ - ->>> IPAddress('127.0.0.1').is_loopback() -True - ->>> IPAddress('::1').is_loopback() -True - -}}} - -==IP address comparisons== - -IP objects can be compared with each other. As an IP object can represent both an individual IP address and an implicit network, it pays to get both sides of your comparison into the same terms before you compare them to avoid any odd results. - -Here are some comparisons of individual IP address to get the ball rolling. - -{{{ - ->>> IPAddress('192.0.2.1') == IPAddress('192.0.2.1') -True - ->>> IPAddress('192.0.2.1') < IPAddress('192.0.2.2') -True - ->>> IPAddress('192.0.2.2') > IPAddress('192.0.2.1') -True - ->>> IPAddress('192.0.2.1') != IPAddress('192.0.2.1') -False - ->>> IPAddress('192.0.2.1') >= IPAddress('192.0.2.1') -True - ->>> IPAddress('192.0.2.2') >= IPAddress('192.0.2.1') -True - ->>> IPAddress('192.0.2.1') <= IPAddress('192.0.2.1') -True - ->>> IPAddress('192.0.2.1') <= IPAddress('192.0.2.2') -True - -}}} - -Now lets try something a little more interesting. - -{{{ - ->>> IPNetwork('192.0.2.0/24') == IPNetwork('192.0.2.112/24') -True - -}}} - -Hmmmmmmmm... looks a bit odd doesn't it? That's because by default, IP objects compare their subnets (or lower and upper boundaries) rather than their individual IP address values. - -The solution to this situation is very simple. Knowing this default behaviour, just be explicit about exactly which portion of each IP object you'd like to compare using pass-through properties. - -{{{ - ->>> IPNetwork('192.0.2.0/24').ip == IPNetwork('192.0.2.112/24').ip -False - ->>> IPNetwork('192.0.2.0/24').ip < IPNetwork('192.0.2.112/24').ip -True - -That's more like it. You can also be explicit about comparing networks in this way if you so wish (although it is not strictly necessary). - ->>> IPNetwork('192.0.2.0/24').cidr == IPNetwork('192.0.2.112/24').cidr -True - -Armed with this information here are some examples of network comparisons. - ->>> IPNetwork('192.0.2.0/24') == IPNetwork('192.0.3.0/24') -False - ->>> IPNetwork('192.0.2.0/24') < IPNetwork('192.0.3.0/24') -True - ->>> IPNetwork('192.0.2.0/24') < IPNetwork('192.0.3.0/24') -True - -}}} - -This will inevitably raise questions about comparing IPAddress (scalar) objects and IPNetwork (vector) objects with each other (or at least it should). - -Here is how netaddr chooses to address this situation. - -{{{ - ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32') -False - ->>> IPAddress('192.0.2.0') != IPNetwork('192.0.2.0/32') -True - -}}} - -An IP network or subnet is different from an individual IP address and therefore cannot be (directly) compared. - -If you want to compare them successfully, you must be explicit about which aspect of the IP network you wish to match against the IP address in question. - -You can use the index of the first or last address if it is a /32 like so :- - -{{{ - ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32')[0] -True - ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32')[-1] -True - ->>> IPAddress('192.0.2.0') != IPNetwork('192.0.2.0/32')[0] -False - -}}} - -You can also use the base address if this is what you wish to compare :- - -{{{ - ->>> IPAddress('192.0.2.0') == IPNetwork('192.0.2.0/32').ip -True - ->>> IPAddress('192.0.2.0') != IPNetwork('192.0.2.0/32').ip -False - -}}} - -While this may seem a bit pointless at first, netaddr strives to keep IP addresses and network separate from one another while still allowing reasonable interoperability. - -==Interaction with DNS== - -It is a common administrative task to Generating reverse IP lookups for DNS. This is particularly arduous for IPv6 addresses. - -Here is how you do this using the IP object's `reverse_dns()` method. - -{{{ - ->>> IPAddress('172.24.0.13').reverse_dns -'13.0.24.172.in-addr.arpa.' - ->>> IPAddress('fe80::feeb:daed').reverse_dns -'d.e.a.d.b.e.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.' - -}}} - -Note that ip6.int is not used as this has been deprecated (see RFC 3152 for details). - -==Non standard IP address range types== - -As CIDR is a relative newcomer given the long history of IP version 4 you are quite likely to come across systems and documentation which make reference to IP address ranges in formats other than CIDR. Converting from these arbitrary range types to CIDR and back again isn't a particularly fun task. Fortunately, netaddr tries to make this job easy for both you and your end users with two purpose built classes. - -===Arbitrary IP Address Ranges=== - -You can represent an arbitrary IP address range using a lower and upper bound address in the form of an IPRange object. - -{{{ - ->>> r1 = IPRange('192.0.2.1', '192.0.2.15') - ->>> r1 -IPRange('192.0.2.1', '192.0.2.15') - -}}} - -You can iterate across and index these ranges just like and IPNetwork object. - -Importantly, you can also convert it to it's CIDR equivalent. - -{{{ - ->>> r1.cidrs() -[IPNetwork('192.0.2.1/32'), IPNetwork('192.0.2.2/31'), IPNetwork('192.0.2.4/30'), IPNetwork('192.0.2.8/29')] - -}}} - -Here is how individual IPRange and IPNetwork compare. - -{{{ - ->>> IPRange('192.0.2.0', '192.0.2.255') != IPNetwork('192.0.2.0/24') -False - ->>> IPRange('192.0.2.0', '192.0.2.255') == IPNetwork('192.0.2.0/24') -True - -}}} - -You may wish to compare an IP range against a list of IPAddress and IPNetwork -objects. - -{{{ - ->>> r1 = IPRange('192.0.2.1', '192.0.2.15') - ->>> addrs = list(r1) - ->>> addrs -[IPAddress('192.0.2.1'), IPAddress('192.0.2.2'), IPAddress('192.0.2.3'), IPAddress('192.0.2.4'), IPAddress('192.0.2.5'), IPAddress('192.0.2.6'), IPAddress('192.0.2.7'), IPAddress('192.0.2.8'), IPAddress('192.0.2.9'), IPAddress('192.0.2.10'), IPAddress('192.0.2.11'), IPAddress('192.0.2.12'), IPAddress('192.0.2.13'), IPAddress('192.0.2.14'), IPAddress('192.0.2.15')] - ->>> r1 == addrs -False - -}}} - -Oops! Not quite what we were looking for or expecting. - -The way to do this is to get either side of the comparison operation into the same terms. - -{{{ - ->>> list(r1) == addrs -True - -}}} - -That's more like it. - -The same goes for IPNetwork objects. - -{{{ - ->>> subnets = r1.cidrs() - ->>> subnets -[IPNetwork('192.0.2.1/32'), IPNetwork('192.0.2.2/31'), IPNetwork('192.0.2.4/30'), IPNetwork('192.0.2.8/29')] - ->>> r1 == subnets -False - ->>> r1.cidrs() == subnets -True - -}}} - -The above works if the list you are comparing contains one type or the other, but what if you have a mixed list of IPAddress, IPNetwork and string addresses? - -Time for some slightly more powerful operations. Let's make use of a new class for dealing with groups of IP addresses and subnets. The IPSet class. - -{{{ - ->>> ips = [IPAddress('192.0.2.1'), '192.0.2.2/31', IPNetwork('192.0.2.4/31'), IPAddress('192.0.2.6'), IPAddress('192.0.2.7'), '192.0.2.8', '192.0.2.9', IPAddress('192.0.2.10'), IPAddress('192.0.2.11'), IPNetwork('192.0.2.12/30')] - ->>> s1 = IPSet(r1.cidrs()) - ->>> s2 = IPSet(ips) - ->>> s2 -IPSet(['192.0.2.1/32', '192.0.2.2/31', '192.0.2.4/30', '192.0.2.8/29']) - ->>> s1 == s2 -True - -}}} - -Let's remove one of the element from one of the IPSet objects and see what happens. - -{{{ - ->>> s2.pop() -IPNetwork('192.0.2.4/30') - ->>> s1 == s2 -False - -}}} - -This is perhaps a somewhat contrived example but it just shows you some of the capabilities on offer. - -See the IPSet tutorial in the wiki for more details on that class. - -===IP Globs=== - -netaddr also supports a user friendly form of specifying IP address ranges using a glob style syntax. Please note that at the current time this only supports IPv4. - -{{{ - ->>> IPGlob('192.0.2.*') == IPNetwork('192.0.2.0/24') -True - -IPGlob('192.0.2.*') != IPNetwork('192.0.2.0/24') -False - -}}} - -As IPGlob is a subclass of IPRange, all of the same operations apply. diff --git a/awx/lib/site-packages/netaddr/tests/3.x/strategy/eui48.txt b/awx/lib/site-packages/netaddr/tests/3.x/strategy/eui48.txt deleted file mode 100644 index e5e55c4237..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/strategy/eui48.txt +++ /dev/null @@ -1,96 +0,0 @@ -=IEEE EUI-48 Strategy Module= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.strategy.eui48 import * - -}}} - -==Basic Smoke Tests== - -{{{ - ->>> b = '00000000-00001111-00011111-00010010-11100111-00110011' ->>> i = 64945841971 ->>> t = (0x0, 0x0f, 0x1f, 0x12, 0xe7, 0x33) ->>> s = '00-0F-1F-12-E7-33' ->>> p = b'\x00\x0f\x1f\x12\xe73' - ->>> bits_to_int(b) == 64945841971 -True - ->>> int_to_bits(i) == b -True - ->>> int_to_str(i) -'00-0F-1F-12-E7-33' - ->>> int_to_words(i) -(0, 15, 31, 18, 231, 51) - ->>> int_to_packed(i) -b'\x00\x0f\x1f\x12\xe73' - ->>> str_to_int(s) == 64945841971 -True - ->>> words_to_int(t) == 64945841971 -True - ->>> words_to_int(list(t)) == 64945841971 -True - ->>> packed_to_int(p) == 64945841971 -True - -}}} - -==Smoke Tests With Alternate Dialects== - -{{{ - ->>> b = '00000000:00001111:00011111:00010010:11100111:00110011' ->>> i = 64945841971 ->>> t = (0x0, 0x0f, 0x1f, 0x12, 0xe7, 0x33) ->>> s = '0:f:1f:12:e7:33' ->>> p = b'\x00\x0f\x1f\x12\xe73' - ->>> bits_to_int(b, mac_unix) == 64945841971 -True - ->>> int_to_bits(i, mac_unix) == b -True - ->>> int_to_str(i, mac_unix) -'0:f:1f:12:e7:33' - ->>> int_to_str(i, mac_unix_expanded) -'00:0f:1f:12:e7:33' - ->>> int_to_str(i, mac_cisco) -'000f.1f12.e733' - ->>> int_to_str(i, mac_unix) -'0:f:1f:12:e7:33' - ->>> int_to_words(i, mac_unix) -(0, 15, 31, 18, 231, 51) - ->>> int_to_packed(i) -b'\x00\x0f\x1f\x12\xe73' - ->>> str_to_int(s) == 64945841971 -True - ->>> words_to_int(t, mac_unix) == 64945841971 -True - ->>> words_to_int(list(t), mac_unix) == 64945841971 -True - ->>> packed_to_int(p) == 64945841971 -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/strategy/ipv4.txt b/awx/lib/site-packages/netaddr/tests/3.x/strategy/ipv4.txt deleted file mode 100644 index 6d9c346a48..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/strategy/ipv4.txt +++ /dev/null @@ -1,130 +0,0 @@ -=IP version 4 Strategy Module= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -Uses TEST-NET references throughout, as described in RFC 3330. - -{{{ - ->>> from netaddr.strategy.ipv4 import * - -}}} - -==Basic Smoke Tests== - -{{{ - ->>> b = '11000000.00000000.00000010.00000001' ->>> i = 3221225985 ->>> t = (192, 0, 2, 1) ->>> s = '192.0.2.1' ->>> p = b'\xc0\x00\x02\x01' ->>> bin_val = '0b11000000000000000000001000000001' - ->>> bits_to_int(b) == 3221225985 -True - ->>> int_to_bits(i) -'11000000.00000000.00000010.00000001' - ->>> int_to_str(i) -'192.0.2.1' - ->>> int_to_words(i) == (192, 0, 2, 1) -True - ->>> int_to_packed(i) -b'\xc0\x00\x02\x01' - ->>> int_to_bin(i) -'0b11000000000000000000001000000001' - ->>> int_to_bin(i) -'0b11000000000000000000001000000001' - ->>> bin_to_int(bin_val) == 3221225985 -True - ->>> words_to_int(t) == 3221225985 -True - ->>> words_to_int(list(t)) == 3221225985 -True - ->>> packed_to_int(p) == 3221225985 -True - ->>> valid_bin(bin_val) -True - -}}} - -== inet_aton() Behavioural Tests == - -inet_aton() is a very old system call and is very permissive with regard to what is assume is a valid IPv4 address. Unfortunately, it is also the most widely used by system software used in software today, so netaddr supports this behaviour by default. - -{{{ - ->>> str_to_int('127') == 127 -True - ->>> str_to_int('0x7f') == 127 -True - ->>> str_to_int('0177') == 127 -True - ->>> str_to_int('127.1') == 2130706433 -True - ->>> str_to_int('0x7f.1') == 2130706433 -True - ->>> str_to_int('0177.1') == 2130706433 -True - ->>> str_to_int('127.0.0.1') == 2130706433 -True - -}}} - -== inet_pton() Behavioural Tests == - -inet_pton() is a newer system call that supports both IPv4 and IPv6. It is a lot more strict about what it deems to be a valid IPv4 address and doesn't support many of the features found in inet_aton() such as support for non- decimal octets, partial numbers of octets, etc. - -{{{ - ->>> str_to_int('127', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '127' is not a valid IPv4 address string! - ->>> str_to_int('0x7f', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '0x7f' is not a valid IPv4 address string! - ->>> str_to_int('0177', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '0177' is not a valid IPv4 address string! - ->>> str_to_int('127.1', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '127.1' is not a valid IPv4 address string! - ->>> str_to_int('0x7f.1', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '0x7f.1' is not a valid IPv4 address string! - ->>> str_to_int('0177.1', flags=INET_PTON) -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '0177.1' is not a valid IPv4 address string! - ->>> str_to_int('127.0.0.1', flags=INET_PTON) == 2130706433 -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/3.x/strategy/ipv6.txt b/awx/lib/site-packages/netaddr/tests/3.x/strategy/ipv6.txt deleted file mode 100644 index dc6db1fcb4..0000000000 --- a/awx/lib/site-packages/netaddr/tests/3.x/strategy/ipv6.txt +++ /dev/null @@ -1,290 +0,0 @@ -=IP version 6 Strategy Module= - -Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. - -{{{ - ->>> from netaddr.strategy.ipv6 import * - -}}} - -==Basic Smoke Tests== - -{{{ - ->>> b = '0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:1111111111111111:1111111111111110' ->>> i = 4294967294 ->>> t = (0, 0, 0, 0, 0, 0, 0xffff, 0xfffe) ->>> s = '::255.255.255.254' ->>> p = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe' - ->>> bits_to_int(b) == 4294967294 -True - ->>> int_to_bits(i) == b -True - ->>> int_to_str(i) -'::255.255.255.254' - ->>> int_to_words(i) -(0, 0, 0, 0, 0, 0, 65535, 65534) - ->>> int_to_packed(i) -b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe' - ->>> str_to_int(s) == 4294967294 -True - ->>> words_to_int(t) == 4294967294 -True - ->>> words_to_int(list(t)) == 4294967294 -True - ->>> packed_to_int(p) == 4294967294 -True - -}}} - -==More Specific IPv6 Tests== - -IPv6 string address variants that are all equivalent. - -{{{ - ->>> i = 42540766411282592856903984951992014763 ->>> str_to_int('2001:0db8:0000:0000:0000:0000:1428:57ab') == i -True - ->>> str_to_int('2001:0db8:0000:0000:0000::1428:57ab') == i -True - ->>> str_to_int('2001:0db8:0:0:0:0:1428:57ab') == i -True - ->>> str_to_int('2001:0db8:0:0::1428:57ab') == i -True - ->>> str_to_int('2001:0db8::1428:57ab') == i -True - ->>> str_to_int('2001:0DB8:0000:0000:0000:0000:1428:57AB') == i -True - ->>> str_to_int('2001:DB8::1428:57AB') == i -True - -}}} - -Intensive IPv6 string address validation testing. - -Positive tests. - -{{{ - ->>> valid_addrs = ( -... # RFC 4291 -... # Long forms. -... 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', -... '1080:0:0:0:8:800:200C:417A', # a unicast address -... 'FF01:0:0:0:0:0:0:43', # a multicast address -... '0:0:0:0:0:0:0:1', # the loopback address -... '0:0:0:0:0:0:0:0', # the unspecified addresses -... -... # Short forms. -... '1080::8:800:200C:417A', # a unicast address -... 'FF01::43', # a multicast address -... '::1', # the loopback address -... '::', # the unspecified addresses -... -... # IPv4 compatible forms. -... '::192.0.2.1', -... '::ffff:192.0.2.1', -... '0:0:0:0:0:0:192.0.2.1', -... '0:0:0:0:0:FFFF:192.0.2.1', -... '0:0:0:0:0:0:13.1.68.3', -... '0:0:0:0:0:FFFF:129.144.52.38', -... '::13.1.68.3', -... '::FFFF:129.144.52.38', -... -... # Other tests. -... '1::', -... '::ffff', -... 'ffff::', -... 'ffff::ffff', -... '0:1:2:3:4:5:6:7', -... '8:9:a:b:c:d:e:f', -... '0:0:0:0:0:0:0:0', -... 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', -... ) - ->>> for addr in valid_addrs: -... addr, valid_str(addr) -('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', True) -('1080:0:0:0:8:800:200C:417A', True) -('FF01:0:0:0:0:0:0:43', True) -('0:0:0:0:0:0:0:1', True) -('0:0:0:0:0:0:0:0', True) -('1080::8:800:200C:417A', True) -('FF01::43', True) -('::1', True) -('::', True) -('::192.0.2.1', True) -('::ffff:192.0.2.1', True) -('0:0:0:0:0:0:192.0.2.1', True) -('0:0:0:0:0:FFFF:192.0.2.1', True) -('0:0:0:0:0:0:13.1.68.3', True) -('0:0:0:0:0:FFFF:129.144.52.38', True) -('::13.1.68.3', True) -('::FFFF:129.144.52.38', True) -('1::', True) -('::ffff', True) -('ffff::', True) -('ffff::ffff', True) -('0:1:2:3:4:5:6:7', True) -('8:9:a:b:c:d:e:f', True) -('0:0:0:0:0:0:0:0', True) -('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', True) - -}}} - -Negative tests. - -{{{ - ->>> invalid_addrs = ( -... 'g:h:i:j:k:l:m:n', # bad chars. -... '0:0:0:0:0:0:0:0:0' # too long, -... '', # empty string -... # Unexpected types. -... [], -... (), -... {}, -... True, -... False, -... ) - ->>> for addr in invalid_addrs: -... addr, valid_str(addr) -('g:h:i:j:k:l:m:n', False) -('0:0:0:0:0:0:0:0:0', False) -([], False) -((), False) -({}, False) -(True, False) -(False, False) - -}}} - -String compaction tests. - -{{{ - ->>> valid_addrs = { -... # RFC 4291 -... 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210' : 'fedc:ba98:7654:3210:fedc:ba98:7654:3210', -... '1080:0:0:0:8:800:200C:417A' : '1080::8:800:200c:417a', # a unicast address -... 'FF01:0:0:0:0:0:0:43' : 'ff01::43', # a multicast address -... '0:0:0:0:0:0:0:1' : '::1', # the loopback address -... '0:0:0:0:0:0:0:0' : '::', # the unspecified addresses -... } - ->>> for long_form, short_form in valid_addrs.items(): -... int_val = str_to_int(long_form) -... calc_short_form = int_to_str(int_val) -... calc_short_form == short_form -True -True -True -True -True - -}}} - -IPv6 mapped and compatible IPv4 string formatting. - -{{{ - ->>> int_to_str(0xffffff) -'::0.255.255.255' ->>> int_to_str(0xffffffff) -'::255.255.255.255' - ->>> int_to_str(0x1ffffffff) -'::1:ffff:ffff' - ->>> int_to_str(0xffffffffffff) -'::ffff:255.255.255.255' - ->>> int_to_str(0xfffeffffffff) -'::fffe:ffff:ffff' - ->>> int_to_str(0xffffffffffff) -'::ffff:255.255.255.255' - ->>> int_to_str(0xfffffffffff1) -'::ffff:255.255.255.241' - ->>> int_to_str(0xfffffffffffe) -'::ffff:255.255.255.254' - ->>> int_to_str(0xffffffffff00) -'::ffff:255.255.255.0' - ->>> int_to_str(0xffffffff0000) -'::ffff:255.255.0.0' - ->>> int_to_str(0xffffff000000) -'::ffff:255.0.0.0' - ->>> int_to_str(0xffff000000) -'::ff:ff00:0' - ->>> int_to_str(0xffff00000000) -'::ffff:0.0.0.0' - ->>> int_to_str(0x1ffff00000000) -'::1:ffff:0:0' - ->>> int_to_str(0xffff00000000) -'::ffff:0.0.0.0' - -}}} - -== str_to_int() Behavioural Tests (legacy_mode switch) == - -The legacy_mode switch on str_to_int() is for interface compatibility only and should not effect the behaviour of this method whether set to True or False. - -{{{ - ->>> str_to_int('::127') == 295 -True - ->>> str_to_int('::0x7f') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '::0x7f' is not a valid IPv6 address string! - ->>> str_to_int('::0177') == 375 -True - ->>> str_to_int('::127.1') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '::127.1' is not a valid IPv6 address string! - ->>> str_to_int('::0x7f.1') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '::0x7f.1' is not a valid IPv6 address string! - ->>> str_to_int('::0177.1') -Traceback (most recent call last): -... -netaddr.core.AddrFormatError: '::0177.1' is not a valid IPv6 address string! - ->>> str_to_int('::127.0.0.1') == 2130706433 -True - -}}} diff --git a/awx/lib/site-packages/netaddr/tests/__init__.py b/awx/lib/site-packages/netaddr/tests/__init__.py deleted file mode 100755 index 564253d638..0000000000 --- a/awx/lib/site-packages/netaddr/tests/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""Runs all netaddr unit tests.""" - -from os.path import abspath, basename, dirname, join as pathjoin -import sys -import glob -import doctest -import unittest - -sys.path.insert(0, abspath(pathjoin(dirname(__file__), '..', '..'))) - - -def test_suite_all(): - - test_dirs = [ - 'ip', - 'eui', - 'strategy', - 'core' - ] - - base_path = abspath(pathjoin(dirname(__file__), '..')) - - # Select tests based on the version of the Python interpreter. - py_ver_dir = '2.x' - if sys.version_info[0] == 3: - py_ver_dir = '3.x' - - # Gather list of files containing tests. - test_files = [] - for entry in test_dirs: - test_path = pathjoin(base_path, "tests", py_ver_dir, entry, "*.txt") - files = glob.glob(test_path) - test_files.extend(files) - - sys.stdout.write('testdir: %s\n' % '\n'.join(test_files)) - - # Add anything to the skiplist that we want to leave out. - skiplist = [] - - # Drop platform specific tests for other platforms. - platform_tests = ['platform_darwin.txt', 'platform_linux2.txt', 'platform_win32.txt'] - for platform_test in platform_tests: - if not sys.platform in platform_test: - skiplist.append(platform_test) - - # Exclude any entries from the skip list. - test_files = [t for t in test_files if basename(t) not in skiplist] - - # Build and return a complete unittest test suite. - suite = unittest.TestSuite() - - for test_file in test_files: - doctest_suite = doctest.DocFileSuite(test_file, - optionflags=doctest.ELLIPSIS, module_relative=False) - suite.addTest(doctest_suite) - - return suite - - -def run(): - runner = unittest.TextTestRunner() - return runner.run(test_suite_all()) - - -if __name__ == "__main__": - result = run() - sys.exit(not result.wasSuccessful()) diff --git a/awx/lib/site-packages/netaddr/tools/netaddr b/awx/lib/site-packages/netaddr/tools/netaddr deleted file mode 100755 index b5beeb22dc..0000000000 --- a/awx/lib/site-packages/netaddr/tools/netaddr +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -#----------------------------------------------------------------------------- -# Copyright (c) 2008-2015, David P. D. Moss. All rights reserved. -# -# Released under the BSD license. See the LICENSE file for details. -#----------------------------------------------------------------------------- -"""an interactive shell for the netaddr library""" - -import os -import sys -import netaddr -from netaddr import * - -# aliases to save some typing ... -from netaddr import IPAddress as IP, IPNetwork as CIDR -from netaddr import EUI as MAC - -argv = sys.argv[1:] - -banner = "\nnetaddr shell %s - %s\n" % (netaddr.__version__, __doc__) -exit_msg = "\nShare and enjoy!" -rc_override = None - -try: - try: - # ipython >= 0.11 - from IPython.frontend.terminal.embed import InteractiveShellEmbed - ipshell = InteractiveShellEmbed(banner1=banner, exit_msg=exit_msg) - except ImportError: - # ipython < 0.11 - from IPython.Shell import IPShellEmbed - ipshell = IPShellEmbed(argv, banner, exit_msg, rc_override) -except ImportError: - sys.stderr.write('IPython (http://ipython.scipy.org/) not found!\n') - sys.exit(1) - -ipshell() diff --git a/awx/lib/site-packages/neutronclient/__init__.py b/awx/lib/site-packages/neutronclient/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/client.py b/awx/lib/site-packages/neutronclient/client.py deleted file mode 100644 index 0a68ff0632..0000000000 --- a/awx/lib/site-packages/neutronclient/client.py +++ /dev/null @@ -1,387 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -try: - import json -except ImportError: - import simplejson as json -import logging -import os - -from keystoneclient import access -from keystoneclient import adapter -import requests - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ - -_logger = logging.getLogger(__name__) - -if os.environ.get('NEUTRONCLIENT_DEBUG'): - ch = logging.StreamHandler() - _logger.setLevel(logging.DEBUG) - _logger.addHandler(ch) - _requests_log_level = logging.DEBUG -else: - _requests_log_level = logging.WARNING - -logging.getLogger("requests").setLevel(_requests_log_level) - - -class HTTPClient(object): - """Handles the REST calls and responses, include authn.""" - - USER_AGENT = 'python-neutronclient' - CONTENT_TYPE = 'application/json' - - # 8192 Is the default max URI len for eventlet.wsgi.server - MAX_URI_LEN = 8192 - - def __init__(self, username=None, user_id=None, - tenant_name=None, tenant_id=None, - password=None, auth_url=None, - token=None, region_name=None, timeout=None, - endpoint_url=None, insecure=False, - endpoint_type='publicURL', - auth_strategy='keystone', ca_cert=None, log_credentials=False, - service_type='network', - **kwargs): - - self.username = username - self.user_id = user_id - self.tenant_name = tenant_name - self.tenant_id = tenant_id - self.password = password - self.auth_url = auth_url.rstrip('/') if auth_url else None - self.service_type = service_type - self.endpoint_type = endpoint_type - self.region_name = region_name - self.timeout = timeout - self.auth_token = token - self.auth_tenant_id = None - self.auth_user_id = None - self.endpoint_url = endpoint_url - self.auth_strategy = auth_strategy - self.log_credentials = log_credentials - if insecure: - self.verify_cert = False - else: - self.verify_cert = ca_cert if ca_cert else True - - def _cs_request(self, *args, **kwargs): - kargs = {} - kargs.setdefault('headers', kwargs.get('headers', {})) - kargs['headers']['User-Agent'] = self.USER_AGENT - - if 'body' in kwargs: - kargs['body'] = kwargs['body'] - - if self.log_credentials: - log_kargs = kargs - else: - log_kargs = self._strip_credentials(kargs) - - utils.http_log_req(_logger, args, log_kargs) - try: - resp, body = self.request(*args, **kargs) - except requests.exceptions.SSLError as e: - raise exceptions.SslCertificateValidationError(reason=e) - except Exception as e: - # Wrap the low-level connection error (socket timeout, redirect - # limit, decompression error, etc) into our custom high-level - # connection exception (it is excepted in the upper layers of code) - _logger.debug("throwing ConnectionFailed : %s", e) - raise exceptions.ConnectionFailed(reason=e) - utils.http_log_resp(_logger, resp, body) - if resp.status_code == 401: - raise exceptions.Unauthorized(message=body) - return resp, body - - def _strip_credentials(self, kwargs): - if kwargs.get('body') and self.password: - log_kwargs = kwargs.copy() - log_kwargs['body'] = kwargs['body'].replace(self.password, - 'REDACTED') - return log_kwargs - else: - return kwargs - - def authenticate_and_fetch_endpoint_url(self): - if not self.auth_token: - self.authenticate() - elif not self.endpoint_url: - self.endpoint_url = self._get_endpoint_url() - - def request(self, url, method, body=None, headers=None, **kwargs): - """Request without authentication.""" - - content_type = kwargs.pop('content_type', None) or 'application/json' - headers = headers or {} - headers.setdefault('Accept', content_type) - - if body: - headers.setdefault('Content-Type', content_type) - - headers['User-Agent'] = self.USER_AGENT - - resp = requests.request( - method, - url, - data=body, - headers=headers, - verify=self.verify_cert, - timeout=self.timeout, - **kwargs) - - return resp, resp.text - - def _check_uri_length(self, action): - uri_len = len(self.endpoint_url) + len(action) - if uri_len > self.MAX_URI_LEN: - raise exceptions.RequestURITooLong( - excess=uri_len - self.MAX_URI_LEN) - - def do_request(self, url, method, **kwargs): - # Ensure client always has correct uri - do not guesstimate anything - self.authenticate_and_fetch_endpoint_url() - self._check_uri_length(url) - - # Perform the request once. If we get a 401 back then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - kwargs.setdefault('headers', {}) - if self.auth_token is None: - self.auth_token = "" - kwargs['headers']['X-Auth-Token'] = self.auth_token - resp, body = self._cs_request(self.endpoint_url + url, method, - **kwargs) - return resp, body - except exceptions.Unauthorized: - self.authenticate() - kwargs.setdefault('headers', {}) - kwargs['headers']['X-Auth-Token'] = self.auth_token - resp, body = self._cs_request( - self.endpoint_url + url, method, **kwargs) - return resp, body - - def _extract_service_catalog(self, body): - """Set the client's service catalog from the response data.""" - self.auth_ref = access.AccessInfo.factory(body=body) - self.service_catalog = self.auth_ref.service_catalog - self.auth_token = self.auth_ref.auth_token - self.auth_tenant_id = self.auth_ref.tenant_id - self.auth_user_id = self.auth_ref.user_id - - if not self.endpoint_url: - self.endpoint_url = self.service_catalog.url_for( - attr='region', filter_value=self.region_name, - service_type=self.service_type, - endpoint_type=self.endpoint_type) - - def _authenticate_keystone(self): - if self.user_id: - creds = {'userId': self.user_id, - 'password': self.password} - else: - creds = {'username': self.username, - 'password': self.password} - - if self.tenant_id: - body = {'auth': {'passwordCredentials': creds, - 'tenantId': self.tenant_id, }, } - else: - body = {'auth': {'passwordCredentials': creds, - 'tenantName': self.tenant_name, }, } - - if self.auth_url is None: - raise exceptions.NoAuthURLProvided() - - token_url = self.auth_url + "/tokens" - resp, resp_body = self._cs_request(token_url, "POST", - body=json.dumps(body), - content_type="application/json", - allow_redirects=True) - if resp.status_code != 200: - raise exceptions.Unauthorized(message=resp_body) - if resp_body: - try: - resp_body = json.loads(resp_body) - except ValueError: - pass - else: - resp_body = None - self._extract_service_catalog(resp_body) - - def _authenticate_noauth(self): - if not self.endpoint_url: - message = _('For "noauth" authentication strategy, the endpoint ' - 'must be specified either in the constructor or ' - 'using --os-url') - raise exceptions.Unauthorized(message=message) - - def authenticate(self): - if self.auth_strategy == 'keystone': - self._authenticate_keystone() - elif self.auth_strategy == 'noauth': - self._authenticate_noauth() - else: - err_msg = _('Unknown auth strategy: %s') % self.auth_strategy - raise exceptions.Unauthorized(message=err_msg) - - def _get_endpoint_url(self): - if self.auth_url is None: - raise exceptions.NoAuthURLProvided() - - url = self.auth_url + '/tokens/%s/endpoints' % self.auth_token - try: - resp, body = self._cs_request(url, "GET") - except exceptions.Unauthorized: - # rollback to authenticate() to handle case when neutron client - # is initialized just before the token is expired - self.authenticate() - return self.endpoint_url - - body = json.loads(body) - for endpoint in body.get('endpoints', []): - if (endpoint['type'] == 'network' and - endpoint.get('region') == self.region_name): - if self.endpoint_type not in endpoint: - raise exceptions.EndpointTypeNotFound( - type_=self.endpoint_type) - return endpoint[self.endpoint_type] - - raise exceptions.EndpointNotFound() - - def get_auth_info(self): - return {'auth_token': self.auth_token, - 'auth_tenant_id': self.auth_tenant_id, - 'auth_user_id': self.auth_user_id, - 'endpoint_url': self.endpoint_url} - - -class SessionClient(adapter.Adapter): - - def request(self, *args, **kwargs): - kwargs.setdefault('authenticated', False) - kwargs.setdefault('raise_exc', False) - - content_type = kwargs.pop('content_type', None) or 'application/json' - - headers = kwargs.setdefault('headers', {}) - headers.setdefault('Accept', content_type) - - try: - kwargs.setdefault('data', kwargs.pop('body')) - except KeyError: - pass - - if kwargs.get('data'): - headers.setdefault('Content-Type', content_type) - - resp = super(SessionClient, self).request(*args, **kwargs) - return resp, resp.text - - def do_request(self, url, method, **kwargs): - kwargs.setdefault('authenticated', True) - return self.request(url, method, **kwargs) - - @property - def endpoint_url(self): - # NOTE(jamielennox): This is used purely by the CLI and should be - # removed when the CLI gets smarter. - return self.get_endpoint() - - @property - def auth_token(self): - # NOTE(jamielennox): This is used purely by the CLI and should be - # removed when the CLI gets smarter. - return self.get_token() - - def authenticate(self): - # NOTE(jamielennox): This is used purely by the CLI and should be - # removed when the CLI gets smarter. - self.get_token() - - def get_auth_info(self): - auth_info = {'auth_token': self.auth_token, - 'endpoint_url': self.endpoint_url} - - # NOTE(jamielennox): This is the best we can do here. It will work - # with identity plugins which is the primary case but we should - # deprecate it's usage as much as possible. - try: - get_access = (self.auth or self.session.auth).get_access - except AttributeError: - pass - else: - auth_ref = get_access(self.session) - - auth_info['auth_tenant_id'] = auth_ref.project_id - auth_info['auth_user_id'] = auth_ref.user_id - - return auth_info - - -# FIXME(bklei): Should refactor this to use kwargs and only -# explicitly list arguments that are not None. -def construct_http_client(username=None, - user_id=None, - tenant_name=None, - tenant_id=None, - password=None, - auth_url=None, - token=None, - region_name=None, - timeout=None, - endpoint_url=None, - insecure=False, - endpoint_type='publicURL', - log_credentials=None, - auth_strategy='keystone', - ca_cert=None, - service_type='network', - session=None, - **kwargs): - - if session: - kwargs.setdefault('user_agent', 'python-neutronclient') - kwargs.setdefault('interface', endpoint_type) - return SessionClient(session=session, - service_type=service_type, - region_name=region_name, - **kwargs) - else: - # FIXME(bklei): username and password are now optional. Need - # to test that they were provided in this mode. Should also - # refactor to use kwargs. - return HTTPClient(username=username, - password=password, - tenant_id=tenant_id, - tenant_name=tenant_name, - user_id=user_id, - auth_url=auth_url, - token=token, - endpoint_url=endpoint_url, - insecure=insecure, - timeout=timeout, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - ca_cert=ca_cert, - log_credentials=log_credentials, - auth_strategy=auth_strategy) diff --git a/awx/lib/site-packages/neutronclient/common/__init__.py b/awx/lib/site-packages/neutronclient/common/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/common/clientmanager.py b/awx/lib/site-packages/neutronclient/common/clientmanager.py deleted file mode 100644 index e9cc88574f..0000000000 --- a/awx/lib/site-packages/neutronclient/common/clientmanager.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -"""Manage access to the clients, including authenticating when needed. -""" - -import logging - -from neutronclient import client -from neutronclient.neutron import client as neutron_client - - -LOG = logging.getLogger(__name__) - - -class ClientCache(object): - """Descriptor class for caching created client handles.""" - - def __init__(self, factory): - self.factory = factory - self._handle = None - - def __get__(self, instance, owner): - # Tell the ClientManager to login to keystone - if self._handle is None: - self._handle = self.factory(instance) - return self._handle - - -class ClientManager(object): - """Manages access to API clients, including authentication.""" - neutron = ClientCache(neutron_client.make_client) - # Provide support for old quantum commands (for example - # in stable versions) - quantum = neutron - - def __init__(self, token=None, url=None, - auth_url=None, - endpoint_type=None, - tenant_name=None, - tenant_id=None, - username=None, - user_id=None, - password=None, - region_name=None, - api_version=None, - auth_strategy=None, - insecure=False, - ca_cert=None, - log_credentials=False, - service_type=None, - timeout=None, - retries=0, - raise_errors=True, - session=None, - auth=None, - ): - self._token = token - self._url = url - self._auth_url = auth_url - self._service_type = service_type - self._endpoint_type = endpoint_type - self._tenant_name = tenant_name - self._tenant_id = tenant_id - self._username = username - self._user_id = user_id - self._password = password - self._region_name = region_name - self._api_version = api_version - self._service_catalog = None - self._auth_strategy = auth_strategy - self._insecure = insecure - self._ca_cert = ca_cert - self._log_credentials = log_credentials - self._timeout = timeout - self._retries = retries - self._raise_errors = raise_errors - self._session = session - self._auth = auth - return - - def initialize(self): - if not self._url: - httpclient = client.construct_http_client( - username=self._username, - user_id=self._user_id, - tenant_name=self._tenant_name, - tenant_id=self._tenant_id, - password=self._password, - region_name=self._region_name, - auth_url=self._auth_url, - service_type=self._service_type, - endpoint_type=self._endpoint_type, - insecure=self._insecure, - ca_cert=self._ca_cert, - timeout=self._timeout, - session=self._session, - auth=self._auth, - log_credentials=self._log_credentials) - httpclient.authenticate() - # Populate other password flow attributes - self._token = httpclient.auth_token - self._url = httpclient.endpoint_url diff --git a/awx/lib/site-packages/neutronclient/common/command.py b/awx/lib/site-packages/neutronclient/common/command.py deleted file mode 100644 index 3d0540744f..0000000000 --- a/awx/lib/site-packages/neutronclient/common/command.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from cliff import command - - -class OpenStackCommand(command.Command): - """Base class for OpenStack commands.""" - - api = None - - def run(self, parsed_args): - if not self.api: - return - else: - return super(OpenStackCommand, self).run(parsed_args) - - def get_data(self, parsed_args): - pass - - def take_action(self, parsed_args): - return self.get_data(parsed_args) diff --git a/awx/lib/site-packages/neutronclient/common/constants.py b/awx/lib/site-packages/neutronclient/common/constants.py deleted file mode 100644 index 305b5df055..0000000000 --- a/awx/lib/site-packages/neutronclient/common/constants.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -EXT_NS = '_extension_ns' -XML_NS_V20 = 'http://openstack.org/quantum/api/v2.0' -XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" -XSI_ATTR = "xsi:nil" -XSI_NIL_ATTR = "xmlns:xsi" -TYPE_XMLNS = "xmlns:quantum" -TYPE_ATTR = "quantum:type" -VIRTUAL_ROOT_KEY = "_v_root" -ATOM_NAMESPACE = "http://www.w3.org/2005/Atom" -ATOM_XMLNS = "xmlns:atom" -ATOM_LINK_NOTATION = "{%s}link" % ATOM_NAMESPACE - -TYPE_BOOL = "bool" -TYPE_INT = "int" -TYPE_LONG = "long" -TYPE_FLOAT = "float" -TYPE_LIST = "list" -TYPE_DICT = "dict" - -PLURALS = {'networks': 'network', - 'ports': 'port', - 'subnets': 'subnet', - 'dns_nameservers': 'dns_nameserver', - 'host_routes': 'host_route', - 'allocation_pools': 'allocation_pool', - 'fixed_ips': 'fixed_ip', - 'extensions': 'extension'} diff --git a/awx/lib/site-packages/neutronclient/common/exceptions.py b/awx/lib/site-packages/neutronclient/common/exceptions.py deleted file mode 100644 index 9728fbdd7e..0000000000 --- a/awx/lib/site-packages/neutronclient/common/exceptions.py +++ /dev/null @@ -1,232 +0,0 @@ -# Copyright 2011 VMware, Inc -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from neutronclient.i18n import _ - -""" -Neutron base exception handling. - -Exceptions are classified into three categories: -* Exceptions corresponding to exceptions from neutron server: - This type of exceptions should inherit one of exceptions - in HTTP_EXCEPTION_MAP. -* Exceptions from client library: - This type of exceptions should inherit NeutronClientException. -* Exceptions from CLI code: - This type of exceptions should inherit NeutronCLIError. -""" - - -class NeutronException(Exception): - """Base Neutron Exception. - - To correctly use this class, inherit from it and define - a 'message' property. That message will get printf'd - with the keyword arguments provided to the constructor. - """ - message = _("An unknown exception occurred.") - - def __init__(self, message=None, **kwargs): - if message: - self.message = message - try: - self._error_string = self.message % kwargs - except Exception: - # at least get the core message out if something happened - self._error_string = self.message - - def __str__(self): - return self._error_string - - -class NeutronClientException(NeutronException): - """Base exception which exceptions from Neutron are mapped into. - - NOTE: on the client side, we use different exception types in order - to allow client library users to handle server exceptions in try...except - blocks. The actual error message is the one generated on the server side. - """ - - status_code = 0 - - def __init__(self, message=None, **kwargs): - if 'status_code' in kwargs: - self.status_code = kwargs['status_code'] - super(NeutronClientException, self).__init__(message, **kwargs) - - -# Base exceptions from Neutron - -class BadRequest(NeutronClientException): - status_code = 400 - - -class Unauthorized(NeutronClientException): - status_code = 401 - message = _("Unauthorized: bad credentials.") - - -class Forbidden(NeutronClientException): - status_code = 403 - message = _("Forbidden: your credentials don't give you access to this " - "resource.") - - -class NotFound(NeutronClientException): - status_code = 404 - - -class Conflict(NeutronClientException): - status_code = 409 - - -class InternalServerError(NeutronClientException): - status_code = 500 - - -class ServiceUnavailable(NeutronClientException): - status_code = 503 - - -HTTP_EXCEPTION_MAP = { - 400: BadRequest, - 401: Unauthorized, - 403: Forbidden, - 404: NotFound, - 409: Conflict, - 500: InternalServerError, - 503: ServiceUnavailable, -} - - -# Exceptions mapped to Neutron server exceptions -# These are defined if a user of client library needs specific exception. -# Exception name should be + 'Client' -# e.g., NetworkNotFound -> NetworkNotFoundClient - -class NetworkNotFoundClient(NotFound): - pass - - -class PortNotFoundClient(NotFound): - pass - - -class StateInvalidClient(BadRequest): - pass - - -class NetworkInUseClient(Conflict): - pass - - -class PortInUseClient(Conflict): - pass - - -class IpAddressInUseClient(Conflict): - pass - - -class InvalidIpForNetworkClient(BadRequest): - pass - - -class OverQuotaClient(Conflict): - pass - - -# TODO(amotoki): It is unused in Neutron, but it is referred to -# in Horizon code. After Horizon code is updated, remove it. -class AlreadyAttachedClient(Conflict): - pass - - -class IpAddressGenerationFailureClient(Conflict): - pass - - -class MacAddressInUseClient(Conflict): - pass - - -class ExternalIpAddressExhaustedClient(BadRequest): - pass - - -# Exceptions from client library - -class NoAuthURLProvided(Unauthorized): - message = _("auth_url was not provided to the Neutron client") - - -class EndpointNotFound(NeutronClientException): - message = _("Could not find Service or Region in Service Catalog.") - - -class EndpointTypeNotFound(NeutronClientException): - message = _("Could not find endpoint type %(type_)s in Service Catalog.") - - -class AmbiguousEndpoints(NeutronClientException): - message = _("Found more than one matching endpoint in Service Catalog: " - "%(matching_endpoints)") - - -class RequestURITooLong(NeutronClientException): - """Raised when a request fails with HTTP error 414.""" - - def __init__(self, **kwargs): - self.excess = kwargs.get('excess', 0) - super(RequestURITooLong, self).__init__(**kwargs) - - -class ConnectionFailed(NeutronClientException): - message = _("Connection to neutron failed: %(reason)s") - - -class SslCertificateValidationError(NeutronClientException): - message = _("SSL certificate validation has failed: %(reason)s") - - -class MalformedResponseBody(NeutronClientException): - message = _("Malformed response body: %(reason)s") - - -class InvalidContentType(NeutronClientException): - message = _("Invalid content type %(content_type)s.") - - -# Command line exceptions - -class NeutronCLIError(NeutronException): - """Exception raised when command line parsing fails.""" - pass - - -class CommandError(NeutronCLIError): - pass - - -class UnsupportedVersion(NeutronCLIError): - """Indicates that the user is trying to use an unsupported version of - the API. - """ - pass - - -class NeutronClientNoUniqueMatch(NeutronCLIError): - message = _("Multiple %(resource)s matches found for name '%(name)s'," - " use an ID to be more specific.") diff --git a/awx/lib/site-packages/neutronclient/common/serializer.py b/awx/lib/site-packages/neutronclient/common/serializer.py deleted file mode 100644 index 0a016d17a8..0000000000 --- a/awx/lib/site-packages/neutronclient/common/serializer.py +++ /dev/null @@ -1,409 +0,0 @@ -# Copyright 2013 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -### -### Codes from neutron wsgi -### - -import logging -from xml.etree import ElementTree as etree -from xml.parsers import expat - -from oslo.serialization import jsonutils -import six - -from neutronclient.common import constants -from neutronclient.common import exceptions as exception -from neutronclient.i18n import _ - -LOG = logging.getLogger(__name__) - -if six.PY3: - long = int - - -class ActionDispatcher(object): - """Maps method name to local methods through action name.""" - - def dispatch(self, *args, **kwargs): - """Find and call local method.""" - action = kwargs.pop('action', 'default') - action_method = getattr(self, str(action), self.default) - return action_method(*args, **kwargs) - - def default(self, data): - raise NotImplementedError() - - -class DictSerializer(ActionDispatcher): - """Default request body serialization.""" - - def serialize(self, data, action='default'): - return self.dispatch(data, action=action) - - def default(self, data): - return "" - - -class JSONDictSerializer(DictSerializer): - """Default JSON request body serialization.""" - - def default(self, data): - def sanitizer(obj): - return six.text_type(obj) - return jsonutils.dumps(data, default=sanitizer) - - -class XMLDictSerializer(DictSerializer): - - def __init__(self, metadata=None, xmlns=None): - """XMLDictSerializer constructor. - - :param metadata: information needed to deserialize XML into - a dictionary. - :param xmlns: XML namespace to include with serialized XML - """ - super(XMLDictSerializer, self).__init__() - self.metadata = metadata or {} - if not xmlns: - xmlns = self.metadata.get('xmlns') - if not xmlns: - xmlns = constants.XML_NS_V20 - self.xmlns = xmlns - - def default(self, data): - """Default serializer of XMLDictSerializer. - - :param data: expect data to contain a single key as XML root, or - contain another '*_links' key as atom links. Other - case will use 'VIRTUAL_ROOT_KEY' as XML root. - """ - try: - links = None - has_atom = False - if data is None: - root_key = constants.VIRTUAL_ROOT_KEY - root_value = None - else: - link_keys = [k for k in six.iterkeys(data) or [] - if k.endswith('_links')] - if link_keys: - links = data.pop(link_keys[0], None) - has_atom = True - root_key = (len(data) == 1 and - list(data.keys())[0] or constants.VIRTUAL_ROOT_KEY) - root_value = data.get(root_key, data) - doc = etree.Element("_temp_root") - used_prefixes = [] - self._to_xml_node(doc, self.metadata, root_key, - root_value, used_prefixes) - if links: - self._create_link_nodes(list(doc)[0], links) - return self.to_xml_string(list(doc)[0], used_prefixes, has_atom) - except AttributeError as e: - LOG.exception(str(e)) - return '' - - def __call__(self, data): - # Provides a migration path to a cleaner WSGI layer, this - # "default" stuff and extreme extensibility isn't being used - # like originally intended - return self.default(data) - - def to_xml_string(self, node, used_prefixes, has_atom=False): - self._add_xmlns(node, used_prefixes, has_atom) - return etree.tostring(node, encoding='UTF-8') - - #NOTE (ameade): the has_atom should be removed after all of the - # XML serializers and view builders have been updated to the current - # spec that required all responses include the xmlns:atom, the has_atom - # flag is to prevent current tests from breaking - def _add_xmlns(self, node, used_prefixes, has_atom=False): - node.set('xmlns', self.xmlns) - node.set(constants.TYPE_XMLNS, self.xmlns) - if has_atom: - node.set(constants.ATOM_XMLNS, constants.ATOM_NAMESPACE) - node.set(constants.XSI_NIL_ATTR, constants.XSI_NAMESPACE) - ext_ns = self.metadata.get(constants.EXT_NS, {}) - for prefix in used_prefixes: - if prefix in ext_ns: - node.set('xmlns:' + prefix, ext_ns[prefix]) - - def _to_xml_node(self, parent, metadata, nodename, data, used_prefixes): - """Recursive method to convert data members to XML nodes.""" - result = etree.SubElement(parent, nodename) - if ":" in nodename: - used_prefixes.append(nodename.split(":", 1)[0]) - #TODO(bcwaldon): accomplish this without a type-check - if isinstance(data, list): - if not data: - result.set( - constants.TYPE_ATTR, - constants.TYPE_LIST) - return result - singular = metadata.get('plurals', {}).get(nodename, None) - if singular is None: - if nodename.endswith('s'): - singular = nodename[:-1] - else: - singular = 'item' - for item in data: - self._to_xml_node(result, metadata, singular, item, - used_prefixes) - #TODO(bcwaldon): accomplish this without a type-check - elif isinstance(data, dict): - if not data: - result.set( - constants.TYPE_ATTR, - constants.TYPE_DICT) - return result - attrs = metadata.get('attributes', {}).get(nodename, {}) - for k, v in sorted(data.items()): - if k in attrs: - result.set(k, str(v)) - else: - self._to_xml_node(result, metadata, k, v, - used_prefixes) - elif data is None: - result.set(constants.XSI_ATTR, 'true') - else: - if isinstance(data, bool): - result.set( - constants.TYPE_ATTR, - constants.TYPE_BOOL) - elif isinstance(data, int): - result.set( - constants.TYPE_ATTR, - constants.TYPE_INT) - elif isinstance(data, long): - result.set( - constants.TYPE_ATTR, - constants.TYPE_LONG) - elif isinstance(data, float): - result.set( - constants.TYPE_ATTR, - constants.TYPE_FLOAT) - LOG.debug("Data %(data)s type is %(type)s", - {'data': data, - 'type': type(data)}) - result.text = six.text_type(data) - return result - - def _create_link_nodes(self, xml_doc, links): - for link in links: - link_node = etree.SubElement(xml_doc, 'atom:link') - link_node.set('rel', link['rel']) - link_node.set('href', link['href']) - - -class TextDeserializer(ActionDispatcher): - """Default request body deserialization.""" - - def deserialize(self, datastring, action='default'): - return self.dispatch(datastring, action=action) - - def default(self, datastring): - return {} - - -class JSONDeserializer(TextDeserializer): - - def _from_json(self, datastring): - try: - return jsonutils.loads(datastring) - except ValueError: - msg = _("Cannot understand JSON") - raise exception.MalformedResponseBody(reason=msg) - - def default(self, datastring): - return {'body': self._from_json(datastring)} - - -class XMLDeserializer(TextDeserializer): - - def __init__(self, metadata=None): - """XMLDeserializer constructor. - - :param metadata: information needed to deserialize XML into - a dictionary. - """ - super(XMLDeserializer, self).__init__() - self.metadata = metadata or {} - xmlns = self.metadata.get('xmlns') - if not xmlns: - xmlns = constants.XML_NS_V20 - self.xmlns = xmlns - - def _get_key(self, tag): - tags = tag.split("}", 1) - if len(tags) == 2: - ns = tags[0][1:] - bare_tag = tags[1] - ext_ns = self.metadata.get(constants.EXT_NS, {}) - if ns == self.xmlns: - return bare_tag - for prefix, _ns in ext_ns.items(): - if ns == _ns: - return prefix + ":" + bare_tag - else: - return tag - - def _get_links(self, root_tag, node): - link_nodes = node.findall(constants.ATOM_LINK_NOTATION) - root_tag = self._get_key(node.tag) - link_key = "%s_links" % root_tag - link_list = [] - for link in link_nodes: - link_list.append({'rel': link.get('rel'), - 'href': link.get('href')}) - # Remove link node in order to avoid link node being - # processed as an item in _from_xml_node - node.remove(link) - return link_list and {link_key: link_list} or {} - - def _from_xml(self, datastring): - if datastring is None: - return None - plurals = set(self.metadata.get('plurals', {})) - try: - node = etree.fromstring(datastring) - root_tag = self._get_key(node.tag) - links = self._get_links(root_tag, node) - result = self._from_xml_node(node, plurals) - # There is no case where root_tag = constants.VIRTUAL_ROOT_KEY - # and links is not None because of the way data are serialized - if root_tag == constants.VIRTUAL_ROOT_KEY: - return result - return dict({root_tag: result}, **links) - except Exception as e: - parseError = False - # Python2.7 - if (hasattr(etree, 'ParseError') and - isinstance(e, getattr(etree, 'ParseError'))): - parseError = True - # Python2.6 - elif isinstance(e, expat.ExpatError): - parseError = True - if parseError: - msg = _("Cannot understand XML") - raise exception.MalformedResponseBody(reason=msg) - else: - raise - - def _from_xml_node(self, node, listnames): - """Convert a minidom node to a simple Python type. - - :param node: minidom node name - :param listnames: list of XML node names whose subnodes should - be considered list items. - - """ - attrNil = node.get(str(etree.QName(constants.XSI_NAMESPACE, "nil"))) - attrType = node.get(str(etree.QName( - self.metadata.get('xmlns'), "type"))) - if (attrNil and attrNil.lower() == 'true'): - return None - elif not len(node) and not node.text: - if (attrType and attrType == constants.TYPE_DICT): - return {} - elif (attrType and attrType == constants.TYPE_LIST): - return [] - else: - return '' - elif (len(node) == 0 and node.text): - converters = {constants.TYPE_BOOL: - lambda x: x.lower() == 'true', - constants.TYPE_INT: - lambda x: int(x), - constants.TYPE_LONG: - lambda x: long(x), - constants.TYPE_FLOAT: - lambda x: float(x)} - if attrType and attrType in converters: - return converters[attrType](node.text) - else: - return node.text - elif self._get_key(node.tag) in listnames: - return [self._from_xml_node(n, listnames) for n in node] - else: - result = dict() - for attr in node.keys(): - if (attr == 'xmlns' or - attr.startswith('xmlns:') or - attr == constants.XSI_ATTR or - attr == constants.TYPE_ATTR): - continue - result[self._get_key(attr)] = node.get(attr) - children = list(node) - for child in children: - result[self._get_key(child.tag)] = self._from_xml_node( - child, listnames) - return result - - def default(self, datastring): - return {'body': self._from_xml(datastring)} - - def __call__(self, datastring): - # Adding a migration path to allow us to remove unncessary classes - return self.default(datastring) - - -# NOTE(maru): this class is duplicated from neutron.wsgi -class Serializer(object): - """Serializes and deserializes dictionaries to certain MIME types.""" - - def __init__(self, metadata=None, default_xmlns=None): - """Create a serializer based on the given WSGI environment. - - 'metadata' is an optional dict mapping MIME types to information - needed to serialize a dictionary to that type. - - """ - self.metadata = metadata or {} - self.default_xmlns = default_xmlns - - def _get_serialize_handler(self, content_type): - handlers = { - 'application/json': JSONDictSerializer(), - 'application/xml': XMLDictSerializer(self.metadata), - } - - try: - return handlers[content_type] - except Exception: - raise exception.InvalidContentType(content_type=content_type) - - def serialize(self, data, content_type): - """Serialize a dictionary into the specified content type.""" - return self._get_serialize_handler(content_type).serialize(data) - - def deserialize(self, datastring, content_type): - """Deserialize a string to a dictionary. - - The string must be in the format of a supported MIME type. - """ - return self.get_deserialize_handler(content_type).deserialize( - datastring) - - def get_deserialize_handler(self, content_type): - handlers = { - 'application/json': JSONDeserializer(), - 'application/xml': XMLDeserializer(self.metadata), - } - - try: - return handlers[content_type] - except Exception: - raise exception.InvalidContentType(content_type=content_type) diff --git a/awx/lib/site-packages/neutronclient/common/utils.py b/awx/lib/site-packages/neutronclient/common/utils.py deleted file mode 100644 index a847b0f3b1..0000000000 --- a/awx/lib/site-packages/neutronclient/common/utils.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright 2011, VMware, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# Borrowed from nova code base, more utilities will be added/borrowed as and -# when needed. - -"""Utilities and helper functions.""" - -import argparse -import logging -import os - -from oslo.utils import encodeutils -from oslo.utils import importutils -import six - -from neutronclient.common import exceptions -from neutronclient.i18n import _ - - -def env(*vars, **kwargs): - """Returns the first environment variable set. - - If none are non-empty, defaults to '' or keyword arg default. - """ - for v in vars: - value = os.environ.get(v) - if value: - return value - return kwargs.get('default', '') - - -def get_client_class(api_name, version, version_map): - """Returns the client class for the requested API version. - - :param api_name: the name of the API, e.g. 'compute', 'image', etc - :param version: the requested API version - :param version_map: a dict of client classes keyed by version - :rtype: a client class for the requested API version - """ - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = _("Invalid %(api_name)s client version '%(version)s'. must be " - "one of: %(map_keys)s") - msg = msg % {'api_name': api_name, 'version': version, - 'map_keys': ', '.join(version_map.keys())} - raise exceptions.UnsupportedVersion(msg) - - return importutils.import_class(client_path) - - -def get_item_properties(item, fields, mixed_case_fields=(), formatters=None): - """Return a tuple containing the item properties. - - :param item: a single item resource (e.g. Server, Tenant, etc) - :param fields: tuple of strings with the desired field names - :param mixed_case_fields: tuple of field names to preserve case - :param formatters: dictionary mapping field names to callables - to format the values - """ - if formatters is None: - formatters = {} - - row = [] - - for field in fields: - if field in formatters: - row.append(formatters[field](item)) - else: - if field in mixed_case_fields: - field_name = field.replace(' ', '_') - else: - field_name = field.lower().replace(' ', '_') - if not hasattr(item, field_name) and isinstance(item, dict): - data = item[field_name] - else: - data = getattr(item, field_name, '') - if data is None: - data = '' - row.append(data) - return tuple(row) - - -def str2bool(strbool): - if strbool is None: - return None - return strbool.lower() == 'true' - - -def str2dict(strdict): - """Convert key1=value1,key2=value2,... string into dictionary. - - :param strdict: key1=value1,key2=value2 - """ - if not strdict: - return {} - return dict([kv.split('=', 1) for kv in strdict.split(',')]) - - -def http_log_req(_logger, args, kwargs): - if not _logger.isEnabledFor(logging.DEBUG): - return - - string_parts = ['curl -i'] - for element in args: - if element in ('GET', 'POST', 'DELETE', 'PUT'): - string_parts.append(' -X %s' % element) - else: - string_parts.append(' %s' % element) - - for element in kwargs['headers']: - header = ' -H "%s: %s"' % (element, kwargs['headers'][element]) - string_parts.append(header) - - if 'body' in kwargs and kwargs['body']: - string_parts.append(" -d '%s'" % (kwargs['body'])) - req = encodeutils.safe_encode("".join(string_parts)) - _logger.debug("\nREQ: %s\n", req) - - -def http_log_resp(_logger, resp, body): - if not _logger.isEnabledFor(logging.DEBUG): - return - _logger.debug("RESP:%(code)s %(headers)s %(body)s\n", - {'code': resp.status_code, - 'headers': resp.headers, - 'body': body}) - - -def _safe_encode_without_obj(data): - if isinstance(data, six.string_types): - return encodeutils.safe_encode(data) - return data - - -def safe_encode_list(data): - return list(map(_safe_encode_without_obj, data)) - - -def safe_encode_dict(data): - def _encode_item(item): - k, v = item - if isinstance(v, list): - return (k, safe_encode_list(v)) - elif isinstance(v, dict): - return (k, safe_encode_dict(v)) - return (k, _safe_encode_without_obj(v)) - - return dict(list(map(_encode_item, data.items()))) - - -def add_boolean_argument(parser, name, **kwargs): - for keyword in ('metavar', 'choices'): - kwargs.pop(keyword, None) - default = kwargs.pop('default', argparse.SUPPRESS) - parser.add_argument( - name, - metavar='{True,False}', - choices=['True', 'true', 'False', 'false'], - default=default, - **kwargs) diff --git a/awx/lib/site-packages/neutronclient/common/validators.py b/awx/lib/site-packages/neutronclient/common/validators.py deleted file mode 100644 index 304ba35c57..0000000000 --- a/awx/lib/site-packages/neutronclient/common/validators.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2014 NEC Corporation -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import netaddr - -from neutronclient.common import exceptions -from neutronclient.i18n import _ - - -def validate_int_range(parsed_args, attr_name, min_value=None, max_value=None): - val = getattr(parsed_args, attr_name, None) - if val is None: - return - try: - if not isinstance(val, int): - int_val = int(val, 0) - else: - int_val = val - if ((min_value is None or min_value <= int_val) and - (max_value is None or int_val <= max_value)): - return - except (ValueError, TypeError): - pass - - if min_value is not None and max_value is not None: - msg = (_('%(attr_name)s "%(val)s" should be an integer ' - '[%(min)i:%(max)i].') % - {'attr_name': attr_name.replace('_', '-'), - 'val': val, 'min': min_value, 'max': max_value}) - elif min_value is not None: - msg = (_('%(attr_name)s "%(val)s" should be an integer ' - 'greater than or equal to %(min)i.') % - {'attr_name': attr_name.replace('_', '-'), - 'val': val, 'min': min_value}) - elif max_value is not None: - msg = (_('%(attr_name)s "%(val)s" should be an integer ' - 'smaller than or equal to %(max)i.') % - {'attr_name': attr_name.replace('_', '-'), - 'val': val, 'max': max_value}) - else: - msg = (_('%(attr_name)s "%(val)s" should be an integer.') % - {'attr_name': attr_name.replace('_', '-'), - 'val': val}) - - raise exceptions.CommandError(msg) - - -def validate_ip_subnet(parsed_args, attr_name): - val = getattr(parsed_args, attr_name) - if not val: - return - try: - netaddr.IPNetwork(val) - except (netaddr.AddrFormatError, ValueError): - raise exceptions.CommandError( - (_('%(attr_name)s "%(val)s" is not a valid CIDR.') % - {'attr_name': attr_name.replace('_', '-'), 'val': val})) diff --git a/awx/lib/site-packages/neutronclient/i18n.py b/awx/lib/site-packages/neutronclient/i18n.py deleted file mode 100644 index f8084067fa..0000000000 --- a/awx/lib/site-packages/neutronclient/i18n.py +++ /dev/null @@ -1,28 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo import i18n - -_translators = i18n.TranslatorFactory(domain='neutronclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/neutronclient/neutron/__init__.py b/awx/lib/site-packages/neutronclient/neutron/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/neutron/client.py b/awx/lib/site-packages/neutronclient/neutron/client.py deleted file mode 100644 index 7236a8a0a0..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/client.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ - - -API_NAME = 'network' -API_VERSIONS = { - '2.0': 'neutronclient.v2_0.client.Client', -} - - -def make_client(instance): - """Returns an neutron client.""" - neutron_client = utils.get_client_class( - API_NAME, - instance._api_version[API_NAME], - API_VERSIONS, - ) - instance.initialize() - url = instance._url - url = url.rstrip("/") - if '2.0' == instance._api_version[API_NAME]: - client = neutron_client(username=instance._username, - tenant_name=instance._tenant_name, - password=instance._password, - region_name=instance._region_name, - auth_url=instance._auth_url, - endpoint_url=url, - endpoint_type=instance._endpoint_type, - token=instance._token, - auth_strategy=instance._auth_strategy, - insecure=instance._insecure, - ca_cert=instance._ca_cert, - retries=instance._retries, - raise_errors=instance._raise_errors, - session=instance._session, - auth=instance._auth) - return client - else: - raise exceptions.UnsupportedVersion(_("API version %s is not " - "supported") % - instance._api_version[API_NAME]) - - -def Client(api_version, *args, **kwargs): - """Return an neutron client. - - @param api_version: only 2.0 is supported now - """ - neutron_client = utils.get_client_class( - API_NAME, - api_version, - API_VERSIONS, - ) - return neutron_client(*args, **kwargs) diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/__init__.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/__init__.py deleted file mode 100644 index 1ca26e2216..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/__init__.py +++ /dev/null @@ -1,742 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from __future__ import print_function - -import abc -import argparse -import logging -import re - -from cliff.formatters import table -from cliff import lister -from cliff import show -from oslo.serialization import jsonutils -import six - -from neutronclient.common import command -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ - -HEX_ELEM = '[0-9A-Fa-f]' -UUID_PATTERN = '-'.join([HEX_ELEM + '{8}', HEX_ELEM + '{4}', - HEX_ELEM + '{4}', HEX_ELEM + '{4}', - HEX_ELEM + '{12}']) - - -def _get_resource_plural(resource, client): - plurals = getattr(client, 'EXTED_PLURALS', []) - for k in plurals: - if plurals[k] == resource: - return k - return resource + 's' - - -def find_resourceid_by_id(client, resource, resource_id, cmd_resource=None, - parent_id=None): - if not cmd_resource: - cmd_resource = resource - cmd_resource_plural = _get_resource_plural(cmd_resource, client) - resource_plural = _get_resource_plural(resource, client) - obj_lister = getattr(client, "list_%s" % cmd_resource_plural) - # perform search by id only if we are passing a valid UUID - match = re.match(UUID_PATTERN, resource_id) - collection = resource_plural - if match: - if parent_id: - data = obj_lister(parent_id, id=resource_id, fields='id') - else: - data = obj_lister(id=resource_id, fields='id') - if data and data[collection]: - return data[collection][0]['id'] - not_found_message = (_("Unable to find %(resource)s with id " - "'%(id)s'") % - {'resource': resource, 'id': resource_id}) - # 404 is used to simulate server side behavior - raise exceptions.NeutronClientException( - message=not_found_message, status_code=404) - - -def _find_resourceid_by_name(client, resource, name, project_id=None, - cmd_resource=None, parent_id=None): - if not cmd_resource: - cmd_resource = resource - cmd_resource_plural = _get_resource_plural(cmd_resource, client) - resource_plural = _get_resource_plural(resource, client) - obj_lister = getattr(client, "list_%s" % cmd_resource_plural) - params = {'name': name, 'fields': 'id'} - if project_id: - params['tenant_id'] = project_id - if parent_id: - data = obj_lister(parent_id, **params) - else: - data = obj_lister(**params) - collection = resource_plural - info = data[collection] - if len(info) > 1: - raise exceptions.NeutronClientNoUniqueMatch(resource=resource, - name=name) - elif len(info) == 0: - not_found_message = (_("Unable to find %(resource)s with name " - "'%(name)s'") % - {'resource': resource, 'name': name}) - # 404 is used to simulate server side behavior - raise exceptions.NeutronClientException( - message=not_found_message, status_code=404) - else: - return info[0]['id'] - - -def find_resourceid_by_name_or_id(client, resource, name_or_id, - project_id=None, cmd_resource=None, - parent_id=None): - try: - return find_resourceid_by_id(client, resource, name_or_id, - cmd_resource, parent_id) - except exceptions.NeutronClientException: - return _find_resourceid_by_name(client, resource, name_or_id, - project_id, cmd_resource, parent_id) - - -def add_show_list_common_argument(parser): - parser.add_argument( - '-D', '--show-details', - help=_('Show detailed information.'), - action='store_true', - default=False, ) - parser.add_argument( - '--show_details', - action='store_true', - help=argparse.SUPPRESS) - parser.add_argument( - '--fields', - help=argparse.SUPPRESS, - action='append', - default=[]) - parser.add_argument( - '-F', '--field', - dest='fields', metavar='FIELD', - help=_('Specify the field(s) to be returned by server. You can ' - 'repeat this option.'), - action='append', - default=[]) - - -def add_pagination_argument(parser): - parser.add_argument( - '-P', '--page-size', - dest='page_size', metavar='SIZE', type=int, - help=_("Specify retrieve unit of each request, then split one request " - "to several requests."), - default=None) - - -def add_sorting_argument(parser): - parser.add_argument( - '--sort-key', - dest='sort_key', metavar='FIELD', - action='append', - help=_("Sorts the list by the specified fields in the specified " - "directions. You can repeat this option, but you must " - "specify an equal number of sort_dir and sort_key values. " - "Extra sort_dir options are ignored. Missing sort_dir options " - "use the default asc value."), - default=[]) - parser.add_argument( - '--sort-dir', - dest='sort_dir', metavar='{asc,desc}', - help=_("Sorts the list in the specified direction. You can repeat " - "this option."), - action='append', - default=[], - choices=['asc', 'desc']) - - -def is_number(s): - try: - float(s) # for int, long and float - except ValueError: - try: - complex(s) # for complex - except ValueError: - return False - - return True - - -def _process_previous_argument(current_arg, _value_number, current_type_str, - _list_flag, _values_specs, _clear_flag, - values_specs): - if current_arg is not None: - if _value_number == 0 and (current_type_str or _list_flag): - # This kind of argument should have value - raise exceptions.CommandError( - _("Invalid values_specs %s") % ' '.join(values_specs)) - if _value_number > 1 or _list_flag or current_type_str == 'list': - current_arg.update({'nargs': '+'}) - elif _value_number == 0: - if _clear_flag: - # if we have action=clear, we use argument's default - # value None for argument - _values_specs.pop() - else: - # We assume non value argument as bool one - current_arg.update({'action': 'store_true'}) - - -def parse_args_to_dict(values_specs): - """It is used to analyze the extra command options to command. - - Besides known options and arguments, our commands also support user to - put more options to the end of command line. For example, - list_nets -- --tag x y --key1 value1, where '-- --tag x y --key1 value1' - is extra options to our list_nets. This feature can support V2.0 API's - fields selection and filters. For example, to list networks which has name - 'test4', we can have list_nets -- --name=test4. - - value spec is: --key type=int|bool|... value. Type is one of Python - built-in types. By default, type is string. The key without value is - a bool option. Key with two values will be a list option. - """ - - # values_specs for example: '-- --tag x y --key1 type=int value1' - # -- is a pseudo argument - values_specs_copy = values_specs[:] - if values_specs_copy and values_specs_copy[0] == '--': - del values_specs_copy[0] - # converted ArgumentParser arguments for each of the options - _options = {} - # the argument part for current option in _options - current_arg = None - # the string after remove meta info in values_specs - # for example, '--tag x y --key1 value1' - _values_specs = [] - # record the count of values for an option - # for example: for '--tag x y', it is 2, while for '--key1 value1', it is 1 - _value_number = 0 - # list=true - _list_flag = False - # action=clear - _clear_flag = False - # the current item in values_specs - current_item = None - # the str after 'type=' - current_type_str = None - for _item in values_specs_copy: - if _item.startswith('--'): - # Deal with previous argument if any - _process_previous_argument( - current_arg, _value_number, current_type_str, - _list_flag, _values_specs, _clear_flag, values_specs) - - # Init variables for current argument - current_item = _item - _list_flag = False - _clear_flag = False - current_type_str = None - if "=" in _item: - _value_number = 1 - _item = _item.split('=')[0] - else: - _value_number = 0 - if _item in _options: - raise exceptions.CommandError( - _("Duplicated options %s") % ' '.join(values_specs)) - else: - _options.update({_item: {}}) - current_arg = _options[_item] - _item = current_item - elif _item.startswith('type='): - if current_arg is None: - raise exceptions.CommandError( - _("Invalid values_specs %s") % ' '.join(values_specs)) - if 'type' not in current_arg: - current_type_str = _item.split('=', 2)[1] - current_arg.update({'type': eval(current_type_str)}) - if current_type_str == 'bool': - current_arg.update({'type': utils.str2bool}) - elif current_type_str == 'dict': - current_arg.update({'type': utils.str2dict}) - continue - elif _item == 'list=true': - _list_flag = True - continue - elif _item == 'action=clear': - _clear_flag = True - continue - - if not _item.startswith('--'): - # All others are value items - # Make sure '--' occurs first and allow minus value - if (not current_item or '=' in current_item or - _item.startswith('-') and not is_number(_item)): - raise exceptions.CommandError( - _("Invalid values_specs %s") % ' '.join(values_specs)) - _value_number += 1 - - _values_specs.append(_item) - - # Deal with last one argument - _process_previous_argument( - current_arg, _value_number, current_type_str, - _list_flag, _values_specs, _clear_flag, values_specs) - - # Populate the parser with arguments - _parser = argparse.ArgumentParser(add_help=False) - for opt, optspec in six.iteritems(_options): - _parser.add_argument(opt, **optspec) - _args = _parser.parse_args(_values_specs) - - result_dict = {} - for opt in six.iterkeys(_options): - _opt = opt.split('--', 2)[1] - _opt = _opt.replace('-', '_') - _value = getattr(_args, _opt) - result_dict.update({_opt: _value}) - return result_dict - - -def _merge_args(qCmd, parsed_args, _extra_values, value_specs): - """Merge arguments from _extra_values into parsed_args. - - If an argument value are provided in both and it is a list, - the values in _extra_values will be merged into parsed_args. - - @param parsed_args: the parsed args from known options - @param _extra_values: the other parsed arguments in unknown parts - @param values_specs: the unparsed unknown parts - """ - temp_values = _extra_values.copy() - for key, value in six.iteritems(temp_values): - if hasattr(parsed_args, key): - arg_value = getattr(parsed_args, key) - if arg_value is not None and value is not None: - if isinstance(arg_value, list): - if value and isinstance(value, list): - if (not arg_value or - type(arg_value[0]) == type(value[0])): - arg_value.extend(value) - _extra_values.pop(key) - - -def update_dict(obj, dict, attributes): - """Update dict with fields from obj.attributes. - - :param obj: the object updated into dict - :param dict: the result dictionary - :param attributes: a list of attributes belonging to obj - """ - for attribute in attributes: - if hasattr(obj, attribute) and getattr(obj, attribute) is not None: - dict[attribute] = getattr(obj, attribute) - - -class TableFormater(table.TableFormatter): - """This class is used to keep consistency with prettytable 0.6. - - https://bugs.launchpad.net/python-neutronclient/+bug/1165962 - """ - def emit_list(self, column_names, data, stdout, parsed_args): - if column_names: - super(TableFormater, self).emit_list(column_names, data, stdout, - parsed_args) - else: - stdout.write('\n') - - -# command.OpenStackCommand is abstract class so that metaclass of -# subclass must be subclass of metaclass of all its base. -# otherwise metaclass conflict exception is raised. -class NeutronCommandMeta(abc.ABCMeta): - def __new__(cls, name, bases, cls_dict): - if 'log' not in cls_dict: - cls_dict['log'] = logging.getLogger( - cls_dict['__module__'] + '.' + name) - return super(NeutronCommandMeta, cls).__new__(cls, - name, bases, cls_dict) - - -@six.add_metaclass(NeutronCommandMeta) -class NeutronCommand(command.OpenStackCommand): - - api = 'network' - values_specs = [] - json_indent = None - resource = None - shadow_resource = None - parent_id = None - - def __init__(self, app, app_args): - super(NeutronCommand, self).__init__(app, app_args) - # NOTE(markmcclain): This is no longer supported in cliff version 1.5.2 - # see https://bugs.launchpad.net/python-neutronclient/+bug/1265926 - - # if hasattr(self, 'formatters'): - # self.formatters['table'] = TableFormater() - - @property - def cmd_resource(self): - if self.shadow_resource: - return self.shadow_resource - return self.resource - - def get_client(self): - return self.app.client_manager.neutron - - def get_parser(self, prog_name): - parser = super(NeutronCommand, self).get_parser(prog_name) - parser.add_argument( - '--request-format', - help=_('The XML or JSON request format.'), - default='json', - choices=['json', 'xml', ], ) - parser.add_argument( - '--request_format', - choices=['json', 'xml', ], - help=argparse.SUPPRESS) - - return parser - - def cleanup_output_data(self, data): - pass - - def format_output_data(self, data): - self.cleanup_output_data(data) - # Modify data to make it more readable - if self.resource in data: - for k, v in six.iteritems(data[self.resource]): - if isinstance(v, list): - value = '\n'.join(jsonutils.dumps( - i, indent=self.json_indent) if isinstance(i, dict) - else str(i) for i in v) - data[self.resource][k] = value - elif isinstance(v, dict): - value = jsonutils.dumps(v, indent=self.json_indent) - data[self.resource][k] = value - elif v is None: - data[self.resource][k] = '' - - def add_known_arguments(self, parser): - pass - - def set_extra_attrs(self, parsed_args): - pass - - def args2body(self, parsed_args): - return {} - - -class CreateCommand(NeutronCommand, show.ShowOne): - """Create a resource for a given tenant.""" - - api = 'network' - log = None - - def get_parser(self, prog_name): - parser = super(CreateCommand, self).get_parser(prog_name) - parser.add_argument( - '--tenant-id', metavar='TENANT_ID', - help=_('The owner tenant ID.'), ) - parser.add_argument( - '--tenant_id', - help=argparse.SUPPRESS) - self.add_known_arguments(parser) - return parser - - def get_data(self, parsed_args): - self.log.debug('get_data(%s)' % parsed_args) - self.set_extra_attrs(parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _extra_values = parse_args_to_dict(self.values_specs) - _merge_args(self, parsed_args, _extra_values, - self.values_specs) - body = self.args2body(parsed_args) - body[self.resource].update(_extra_values) - obj_creator = getattr(neutron_client, - "create_%s" % self.cmd_resource) - if self.parent_id: - data = obj_creator(self.parent_id, body) - else: - data = obj_creator(body) - self.format_output_data(data) - info = self.resource in data and data[self.resource] or None - if info: - print(_('Created a new %s:') % self.resource, - file=self.app.stdout) - else: - info = {'': ''} - return zip(*sorted(six.iteritems(info))) - - -class UpdateCommand(NeutronCommand): - """Update resource's information.""" - - api = 'network' - log = None - allow_names = True - - def get_parser(self, prog_name): - parser = super(UpdateCommand, self).get_parser(prog_name) - parser.add_argument( - 'id', metavar=self.resource.upper(), - help=_('ID or name of %s to update.') % self.resource) - self.add_known_arguments(parser) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)', parsed_args) - self.set_extra_attrs(parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _extra_values = parse_args_to_dict(self.values_specs) - _merge_args(self, parsed_args, _extra_values, - self.values_specs) - body = self.args2body(parsed_args) - if self.resource in body: - body[self.resource].update(_extra_values) - else: - body[self.resource] = _extra_values - if not body[self.resource]: - raise exceptions.CommandError( - _("Must specify new values to update %s") % - self.cmd_resource) - if self.allow_names: - _id = find_resourceid_by_name_or_id( - neutron_client, self.resource, parsed_args.id, - cmd_resource=self.cmd_resource, parent_id=self.parent_id) - else: - _id = find_resourceid_by_id( - neutron_client, self.resource, parsed_args.id, - self.cmd_resource, self.parent_id) - obj_updater = getattr(neutron_client, - "update_%s" % self.cmd_resource) - if self.parent_id: - obj_updater(_id, self.parent_id, body) - else: - obj_updater(_id, body) - print((_('Updated %(resource)s: %(id)s') % - {'id': parsed_args.id, 'resource': self.resource}), - file=self.app.stdout) - return - - -class DeleteCommand(NeutronCommand): - """Delete a given resource.""" - - api = 'network' - log = None - allow_names = True - - def get_parser(self, prog_name): - parser = super(DeleteCommand, self).get_parser(prog_name) - if self.allow_names: - help_str = _('ID or name of %s to delete.') - else: - help_str = _('ID of %s to delete.') - parser.add_argument( - 'id', metavar=self.resource.upper(), - help=help_str % self.resource) - self.add_known_arguments(parser) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)', parsed_args) - self.set_extra_attrs(parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - obj_deleter = getattr(neutron_client, - "delete_%s" % self.cmd_resource) - if self.allow_names: - params = {'cmd_resource': self.cmd_resource, - 'parent_id': self.parent_id} - _id = find_resourceid_by_name_or_id(neutron_client, - self.resource, - parsed_args.id, - **params) - else: - _id = parsed_args.id - - if self.parent_id: - obj_deleter(_id, self.parent_id) - else: - obj_deleter(_id) - print((_('Deleted %(resource)s: %(id)s') - % {'id': parsed_args.id, - 'resource': self.resource}), - file=self.app.stdout) - return - - -class ListCommand(NeutronCommand, lister.Lister): - """List resources that belong to a given tenant.""" - - api = 'network' - log = None - _formatters = {} - list_columns = [] - unknown_parts_flag = True - pagination_support = False - sorting_support = False - - def get_parser(self, prog_name): - parser = super(ListCommand, self).get_parser(prog_name) - add_show_list_common_argument(parser) - if self.pagination_support: - add_pagination_argument(parser) - if self.sorting_support: - add_sorting_argument(parser) - self.add_known_arguments(parser) - return parser - - def args2search_opts(self, parsed_args): - search_opts = {} - fields = parsed_args.fields - if parsed_args.fields: - search_opts.update({'fields': fields}) - if parsed_args.show_details: - search_opts.update({'verbose': 'True'}) - return search_opts - - def call_server(self, neutron_client, search_opts, parsed_args): - resource_plural = _get_resource_plural(self.cmd_resource, - neutron_client) - obj_lister = getattr(neutron_client, "list_%s" % resource_plural) - if self.parent_id: - data = obj_lister(self.parent_id, **search_opts) - else: - data = obj_lister(**search_opts) - return data - - def retrieve_list(self, parsed_args): - """Retrieve a list of resources from Neutron server.""" - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _extra_values = parse_args_to_dict(self.values_specs) - _merge_args(self, parsed_args, _extra_values, - self.values_specs) - search_opts = self.args2search_opts(parsed_args) - search_opts.update(_extra_values) - if self.pagination_support: - page_size = parsed_args.page_size - if page_size: - search_opts.update({'limit': page_size}) - if self.sorting_support: - keys = parsed_args.sort_key - if keys: - search_opts.update({'sort_key': keys}) - dirs = parsed_args.sort_dir - len_diff = len(keys) - len(dirs) - if len_diff > 0: - dirs += ['asc'] * len_diff - elif len_diff < 0: - dirs = dirs[:len(keys)] - if dirs: - search_opts.update({'sort_dir': dirs}) - data = self.call_server(neutron_client, search_opts, parsed_args) - collection = _get_resource_plural(self.resource, neutron_client) - return data.get(collection, []) - - def extend_list(self, data, parsed_args): - """Update a retrieved list. - - This method provides a way to modify a original list returned from - the neutron server. For example, you can add subnet cidr information - to a list network. - """ - pass - - def setup_columns(self, info, parsed_args): - _columns = len(info) > 0 and sorted(info[0].keys()) or [] - if not _columns: - # clean the parsed_args.columns so that cliff will not break - parsed_args.columns = [] - elif parsed_args.columns: - _columns = [x for x in parsed_args.columns if x in _columns] - elif self.list_columns: - # if no -c(s) by user and list_columns, we use columns in - # both list_columns and returned resource. - # Also Keep their order the same as in list_columns - _columns = [x for x in self.list_columns if x in _columns] - - formatters = self._formatters - if hasattr(self, '_formatters_csv') and parsed_args.formatter == 'csv': - formatters = self._formatters_csv - - return (_columns, (utils.get_item_properties( - s, _columns, formatters=formatters, ) - for s in info), ) - - def get_data(self, parsed_args): - self.log.debug('get_data(%s)', parsed_args) - self.set_extra_attrs(parsed_args) - data = self.retrieve_list(parsed_args) - self.extend_list(data, parsed_args) - return self.setup_columns(data, parsed_args) - - -class ShowCommand(NeutronCommand, show.ShowOne): - """Show information of a given resource.""" - - api = 'network' - log = None - allow_names = True - - def get_parser(self, prog_name): - parser = super(ShowCommand, self).get_parser(prog_name) - add_show_list_common_argument(parser) - if self.allow_names: - help_str = _('ID or name of %s to look up.') - else: - help_str = _('ID of %s to look up.') - parser.add_argument( - 'id', metavar=self.resource.upper(), - help=help_str % self.resource) - self.add_known_arguments(parser) - return parser - - def get_data(self, parsed_args): - self.log.debug('get_data(%s)', parsed_args) - self.set_extra_attrs(parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - - params = {} - if parsed_args.show_details: - params = {'verbose': 'True'} - if parsed_args.fields: - params = {'fields': parsed_args.fields} - if self.allow_names: - _id = find_resourceid_by_name_or_id(neutron_client, - self.resource, - parsed_args.id, - cmd_resource=self.cmd_resource, - parent_id=self.parent_id) - else: - _id = parsed_args.id - - obj_shower = getattr(neutron_client, "show_%s" % self.cmd_resource) - if self.parent_id: - data = obj_shower(_id, self.parent_id, **params) - else: - data = obj_shower(_id, **params) - self.format_output_data(data) - resource = data[self.resource] - if self.resource in data: - return zip(*sorted(six.iteritems(resource))) - else: - return None diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/agent.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/agent.py deleted file mode 100644 index 8f7de7a7e1..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/agent.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2013 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _format_timestamp(component): - try: - return component['heartbeat_timestamp'].split(".", 2)[0] - except (TypeError, KeyError): - return '' - - -class ListAgent(neutronV20.ListCommand): - """List agents.""" - - resource = 'agent' - list_columns = ['id', 'agent_type', 'host', 'alive', 'admin_state_up', - 'binary'] - _formatters = {'heartbeat_timestamp': _format_timestamp} - sorting_support = True - - def extend_list(self, data, parsed_args): - for agent in data: - if 'alive' in agent: - agent['alive'] = ":-)" if agent['alive'] else 'xxx' - - -class ShowAgent(neutronV20.ShowCommand): - """Show information of a given agent.""" - - resource = 'agent' - allow_names = False - json_indent = 5 - - -class DeleteAgent(neutronV20.DeleteCommand): - """Delete a given agent.""" - - resource = 'agent' - allow_names = False - - -class UpdateAgent(neutronV20.UpdateCommand): - """Updates the admin status and description for a specified agent.""" - - resource = 'agent' - allow_names = False - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', - action='store_false', - help=_('Set admin state up of the agent to false.')) - parser.add_argument( - '--description', - help=_('Description for the agent.')) - - def args2body(self, parsed_args): - body = { - self.resource: { - 'admin_state_up': parsed_args.admin_state, }, } - neutronV20.update_dict(parsed_args, body[self.resource], - ['description']) - return body diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/agentscheduler.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/agentscheduler.py deleted file mode 100644 index e77f186db5..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/agentscheduler.py +++ /dev/null @@ -1,277 +0,0 @@ -# Copyright 2013 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from __future__ import print_function - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 -from neutronclient.neutron.v2_0 import network -from neutronclient.neutron.v2_0 import router - - -PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" - - -class AddNetworkToDhcpAgent(neutronV20.NeutronCommand): - """Add a network to a DHCP agent.""" - - def get_parser(self, prog_name): - parser = super(AddNetworkToDhcpAgent, self).get_parser(prog_name) - parser.add_argument( - 'dhcp_agent', - help=_('ID of the DHCP agent.')) - parser.add_argument( - 'network', - help=_('Network to add.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _net_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'network', parsed_args.network) - neutron_client.add_network_to_dhcp_agent(parsed_args.dhcp_agent, - {'network_id': _net_id}) - print(_('Added network %s to DHCP agent') % parsed_args.network, - file=self.app.stdout) - - -class RemoveNetworkFromDhcpAgent(neutronV20.NeutronCommand): - """Remove a network from a DHCP agent.""" - - def get_parser(self, prog_name): - parser = super(RemoveNetworkFromDhcpAgent, self).get_parser(prog_name) - parser.add_argument( - 'dhcp_agent', - help=_('ID of the DHCP agent.')) - parser.add_argument( - 'network', - help=_('Network to remove.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _net_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'network', parsed_args.network) - neutron_client.remove_network_from_dhcp_agent( - parsed_args.dhcp_agent, _net_id) - print(_('Removed network %s from DHCP agent') % parsed_args.network, - file=self.app.stdout) - - -class ListNetworksOnDhcpAgent(network.ListNetwork): - """List the networks on a DHCP agent.""" - - unknown_parts_flag = False - - def get_parser(self, prog_name): - parser = super(ListNetworksOnDhcpAgent, - self).get_parser(prog_name) - parser.add_argument( - 'dhcp_agent', - help=_('ID of the DHCP agent.')) - return parser - - def call_server(self, neutron_client, search_opts, parsed_args): - data = neutron_client.list_networks_on_dhcp_agent( - parsed_args.dhcp_agent, **search_opts) - return data - - -class ListDhcpAgentsHostingNetwork(neutronV20.ListCommand): - """List DHCP agents hosting a network.""" - - resource = 'agent' - _formatters = {} - list_columns = ['id', 'host', 'admin_state_up', 'alive'] - unknown_parts_flag = False - - def get_parser(self, prog_name): - parser = super(ListDhcpAgentsHostingNetwork, - self).get_parser(prog_name) - parser.add_argument( - 'network', - help=_('Network to query.')) - return parser - - def extend_list(self, data, parsed_args): - for agent in data: - agent['alive'] = ":-)" if agent['alive'] else 'xxx' - - def call_server(self, neutron_client, search_opts, parsed_args): - _id = neutronV20.find_resourceid_by_name_or_id(neutron_client, - 'network', - parsed_args.network) - search_opts['network'] = _id - data = neutron_client.list_dhcp_agent_hosting_networks(**search_opts) - return data - - -class AddRouterToL3Agent(neutronV20.NeutronCommand): - """Add a router to a L3 agent.""" - - def get_parser(self, prog_name): - parser = super(AddRouterToL3Agent, self).get_parser(prog_name) - parser.add_argument( - 'l3_agent', - help=_('ID of the L3 agent.')) - parser.add_argument( - 'router', - help=_('Router to add.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'router', parsed_args.router) - neutron_client.add_router_to_l3_agent(parsed_args.l3_agent, - {'router_id': _id}) - print(_('Added router %s to L3 agent') % parsed_args.router, - file=self.app.stdout) - - -class RemoveRouterFromL3Agent(neutronV20.NeutronCommand): - """Remove a router from a L3 agent.""" - - def get_parser(self, prog_name): - parser = super(RemoveRouterFromL3Agent, self).get_parser(prog_name) - parser.add_argument( - 'l3_agent', - help=_('ID of the L3 agent.')) - parser.add_argument( - 'router', - help=_('Router to remove.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'router', parsed_args.router) - neutron_client.remove_router_from_l3_agent( - parsed_args.l3_agent, _id) - print(_('Removed router %s from L3 agent') % parsed_args.router, - file=self.app.stdout) - - -class ListRoutersOnL3Agent(neutronV20.ListCommand): - """List the routers on a L3 agent.""" - - _formatters = {'external_gateway_info': - router._format_external_gateway_info} - list_columns = ['id', 'name', 'external_gateway_info'] - resource = 'router' - unknown_parts_flag = False - - def get_parser(self, prog_name): - parser = super(ListRoutersOnL3Agent, - self).get_parser(prog_name) - parser.add_argument( - 'l3_agent', - help=_('ID of the L3 agent to query.')) - return parser - - def call_server(self, neutron_client, search_opts, parsed_args): - data = neutron_client.list_routers_on_l3_agent( - parsed_args.l3_agent, **search_opts) - return data - - -class ListL3AgentsHostingRouter(neutronV20.ListCommand): - """List L3 agents hosting a router.""" - - resource = 'agent' - _formatters = {} - list_columns = ['id', 'host', 'admin_state_up', 'alive'] - unknown_parts_flag = False - - def get_parser(self, prog_name): - parser = super(ListL3AgentsHostingRouter, - self).get_parser(prog_name) - parser.add_argument('router', - help=_('Router to query.')) - return parser - - def extend_list(self, data, parsed_args): - for agent in data: - agent['alive'] = ":-)" if agent['alive'] else 'xxx' - - def call_server(self, neutron_client, search_opts, parsed_args): - _id = neutronV20.find_resourceid_by_name_or_id(neutron_client, - 'router', - parsed_args.router) - search_opts['router'] = _id - data = neutron_client.list_l3_agent_hosting_routers(**search_opts) - return data - - -class ListPoolsOnLbaasAgent(neutronV20.ListCommand): - """List the pools on a loadbalancer agent.""" - - list_columns = ['id', 'name', 'lb_method', 'protocol', - 'admin_state_up', 'status'] - resource = 'pool' - unknown_parts_flag = False - - def get_parser(self, prog_name): - parser = super(ListPoolsOnLbaasAgent, self).get_parser(prog_name) - parser.add_argument( - 'lbaas_agent', - help=_('ID of the loadbalancer agent to query.')) - return parser - - def call_server(self, neutron_client, search_opts, parsed_args): - data = neutron_client.list_pools_on_lbaas_agent( - parsed_args.lbaas_agent, **search_opts) - return data - - -class GetLbaasAgentHostingPool(neutronV20.ListCommand): - """Get loadbalancer agent hosting a pool. - - Deriving from ListCommand though server will return only one agent - to keep common output format for all agent schedulers - """ - - resource = 'agent' - list_columns = ['id', 'host', 'admin_state_up', 'alive'] - unknown_parts_flag = False - - def get_parser(self, prog_name): - parser = super(GetLbaasAgentHostingPool, - self).get_parser(prog_name) - parser.add_argument('pool', - help=_('Pool to query.')) - return parser - - def extend_list(self, data, parsed_args): - for agent in data: - agent['alive'] = ":-)" if agent['alive'] else 'xxx' - - def call_server(self, neutron_client, search_opts, parsed_args): - _id = neutronV20.find_resourceid_by_name_or_id(neutron_client, - 'pool', - parsed_args.pool) - search_opts['pool'] = _id - agent = neutron_client.get_lbaas_agent_hosting_pool(**search_opts) - data = {'agents': [agent['agent']]} - return data diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/credential.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/credential.py deleted file mode 100644 index ffec5ee1de..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/credential.py +++ /dev/null @@ -1,73 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListCredential(neutronV20.ListCommand): - """List credentials that belong to a given tenant.""" - - resource = 'credential' - _formatters = {} - list_columns = ['credential_id', 'credential_name', 'user_name', - 'password', 'type'] - - -class ShowCredential(neutronV20.ShowCommand): - """Show information of a given credential.""" - - resource = 'credential' - allow_names = False - - -class CreateCredential(neutronV20.CreateCommand): - """Creates a credential.""" - - resource = 'credential' - - def add_known_arguments(self, parser): - parser.add_argument( - 'credential_name', - help=_('Name/IP address for credential.')) - parser.add_argument( - 'credential_type', - help=_('Type of the credential.')) - parser.add_argument( - '--username', - help=_('Username for the credential.')) - parser.add_argument( - '--password', - help=_('Password for the credential.')) - - def args2body(self, parsed_args): - body = {'credential': { - 'credential_name': parsed_args.credential_name}} - - if parsed_args.credential_type: - body['credential'].update({'type': - parsed_args.credential_type}) - if parsed_args.username: - body['credential'].update({'user_name': - parsed_args.username}) - if parsed_args.password: - body['credential'].update({'password': - parsed_args.password}) - return body - - -class DeleteCredential(neutronV20.DeleteCommand): - """Delete a given credential.""" - - resource = 'credential' - allow_names = False diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/extension.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/extension.py deleted file mode 100644 index 24905d59d4..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/extension.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.neutron import v2_0 as cmd_base - - -class ListExt(cmd_base.ListCommand): - """List all extensions.""" - - resource = 'extension' - list_columns = ['alias', 'name'] - - -class ShowExt(cmd_base.ShowCommand): - """Show information of a given resource.""" - - resource = "extension" - allow_names = False diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/floatingip.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/floatingip.py deleted file mode 100644 index d1fc9f4661..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/floatingip.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from __future__ import print_function - -import argparse - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListFloatingIP(neutronV20.ListCommand): - """List floating IPs that belong to a given tenant.""" - - resource = 'floatingip' - list_columns = ['id', 'fixed_ip_address', 'floating_ip_address', - 'port_id'] - pagination_support = True - sorting_support = True - - -class ShowFloatingIP(neutronV20.ShowCommand): - """Show information of a given floating IP.""" - - resource = 'floatingip' - allow_names = False - - -class CreateFloatingIP(neutronV20.CreateCommand): - """Create a floating IP for a given tenant.""" - - resource = 'floatingip' - - def add_known_arguments(self, parser): - parser.add_argument( - 'floating_network_id', metavar='FLOATING_NETWORK', - help=_('Network name or ID to allocate floating IP from.')) - parser.add_argument( - '--port-id', - help=_('ID of the port to be associated with the floating IP.')) - parser.add_argument( - '--port_id', - help=argparse.SUPPRESS) - parser.add_argument( - '--fixed-ip-address', - help=_('IP address on the port (only required if port has ' - 'multiple IPs).')) - parser.add_argument( - '--fixed_ip_address', - help=argparse.SUPPRESS) - parser.add_argument( - '--floating-ip-address', - help=_('IP address of the floating IP')) - - def args2body(self, parsed_args): - _network_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'network', parsed_args.floating_network_id) - body = {self.resource: {'floating_network_id': _network_id}} - if parsed_args.port_id: - body[self.resource].update({'port_id': parsed_args.port_id}) - if parsed_args.tenant_id: - body[self.resource].update({'tenant_id': parsed_args.tenant_id}) - if parsed_args.fixed_ip_address: - body[self.resource].update({'fixed_ip_address': - parsed_args.fixed_ip_address}) - if parsed_args.floating_ip_address: - body[self.resource].update({'floating_ip_address': - parsed_args.floating_ip_address}) - return body - - -class DeleteFloatingIP(neutronV20.DeleteCommand): - """Delete a given floating IP.""" - - resource = 'floatingip' - allow_names = False - - -class AssociateFloatingIP(neutronV20.NeutronCommand): - """Create a mapping between a floating IP and a fixed IP.""" - - api = 'network' - resource = 'floatingip' - - def get_parser(self, prog_name): - parser = super(AssociateFloatingIP, self).get_parser(prog_name) - parser.add_argument( - 'floatingip_id', metavar='FLOATINGIP_ID', - help=_('ID of the floating IP to associate.')) - parser.add_argument( - 'port_id', metavar='PORT', - help=_('ID or name of the port to be associated with the ' - 'floating IP.')) - parser.add_argument( - '--fixed-ip-address', - help=_('IP address on the port (only required if port has ' - 'multiple IPs).')) - parser.add_argument( - '--fixed_ip_address', - help=argparse.SUPPRESS) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - update_dict = {} - if parsed_args.port_id: - update_dict['port_id'] = parsed_args.port_id - if parsed_args.fixed_ip_address: - update_dict['fixed_ip_address'] = parsed_args.fixed_ip_address - neutron_client.update_floatingip(parsed_args.floatingip_id, - {'floatingip': update_dict}) - print(_('Associated floating IP %s') % parsed_args.floatingip_id, - file=self.app.stdout) - - -class DisassociateFloatingIP(neutronV20.NeutronCommand): - """Remove a mapping from a floating IP to a fixed IP. - """ - - api = 'network' - resource = 'floatingip' - - def get_parser(self, prog_name): - parser = super(DisassociateFloatingIP, self).get_parser(prog_name) - parser.add_argument( - 'floatingip_id', metavar='FLOATINGIP_ID', - help=_('ID of the floating IP to disassociate.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - neutron_client.update_floatingip(parsed_args.floatingip_id, - {'floatingip': {'port_id': None}}) - print(_('Disassociated floating IP %s') % parsed_args.floatingip_id, - file=self.app.stdout) diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/__init__.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewall.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewall.py deleted file mode 100644 index 149036a2a5..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewall.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2013 Big Switch Networks -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: KC Wang, Big Switch Networks -# - -import argparse - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 - - -class ListFirewall(neutronv20.ListCommand): - """List firewalls that belong to a given tenant.""" - - resource = 'firewall' - list_columns = ['id', 'name', 'firewall_policy_id'] - _formatters = {} - pagination_support = True - sorting_support = True - - -class ShowFirewall(neutronv20.ShowCommand): - """Show information of a given firewall.""" - - resource = 'firewall' - - -class CreateFirewall(neutronv20.CreateCommand): - """Create a firewall.""" - - resource = 'firewall' - - def add_known_arguments(self, parser): - parser.add_argument( - 'firewall_policy_id', metavar='POLICY', - help=_('Firewall policy name or ID.')) - parser.add_argument( - '--name', - help=_('Name for the firewall.')) - parser.add_argument( - '--description', - help=_('Description for the firewall rule.')) - parser.add_argument( - '--shared', - action='store_true', - help=_('Set shared to True (default is False).'), - default=argparse.SUPPRESS) - parser.add_argument( - '--admin-state-down', - dest='admin_state', - action='store_false', - help=_('Set admin state up to false.')) - - def args2body(self, parsed_args): - _policy_id = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'firewall_policy', - parsed_args.firewall_policy_id) - body = { - self.resource: { - 'firewall_policy_id': _policy_id, - 'admin_state_up': parsed_args.admin_state, }, } - neutronv20.update_dict(parsed_args, body[self.resource], - ['name', 'description', 'shared', - 'tenant_id']) - return body - - -class UpdateFirewall(neutronv20.UpdateCommand): - """Update a given firewall.""" - - resource = 'firewall' - - def add_known_arguments(self, parser): - parser.add_argument( - '--policy', metavar='POLICY', - help=_('Firewall policy name or ID.')) - - def args2body(self, parsed_args): - data = {} - if parsed_args.policy: - _policy_id = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'firewall_policy', - parsed_args.policy) - data['firewall_policy_id'] = _policy_id - return {self.resource: data} - - -class DeleteFirewall(neutronv20.DeleteCommand): - """Delete a given firewall.""" - - resource = 'firewall' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewallpolicy.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewallpolicy.py deleted file mode 100644 index 32f25eba99..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewallpolicy.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright 2013 Big Switch Networks -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: KC Wang, Big Switch Networks -# - -from __future__ import print_function - -import argparse - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 - - -def _format_firewall_rules(firewall_policy): - try: - output = '[' + ',\n '.join([rule for rule in - firewall_policy['firewall_rules']]) + ']' - return output - except (TypeError, KeyError): - return '' - - -def common_add_known_arguments(parser): - parser.add_argument( - '--firewall-rules', type=lambda x: x.split(), - help=_('Ordered list of whitespace-delimited firewall rule ' - 'names or IDs; e.g., --firewall-rules \"rule1 rule2\"')) - - -def common_args2body(client, parsed_args): - if parsed_args.firewall_rules: - _firewall_rules = [] - for f in parsed_args.firewall_rules: - _firewall_rules.append( - neutronv20.find_resourceid_by_name_or_id( - client, 'firewall_rule', f)) - body = {'firewall_policy': {'firewall_rules': _firewall_rules}} - else: - body = {'firewall_policy': {}} - neutronv20.update_dict(parsed_args, body['firewall_policy'], - ['name', 'description', 'shared', - 'audited', 'tenant_id']) - return body - - -class ListFirewallPolicy(neutronv20.ListCommand): - """List firewall policies that belong to a given tenant.""" - - resource = 'firewall_policy' - list_columns = ['id', 'name', 'firewall_rules'] - _formatters = {'firewall_rules': _format_firewall_rules, - } - pagination_support = True - sorting_support = True - - -class ShowFirewallPolicy(neutronv20.ShowCommand): - """Show information of a given firewall policy.""" - - resource = 'firewall_policy' - - -class CreateFirewallPolicy(neutronv20.CreateCommand): - """Create a firewall policy.""" - - resource = 'firewall_policy' - - def add_known_arguments(self, parser): - parser.add_argument( - 'name', - metavar='NAME', - help=_('Name for the firewall policy.')) - parser.add_argument( - '--description', - help=_('Description for the firewall policy.')) - parser.add_argument( - '--shared', - dest='shared', - action='store_true', - help=_('Create a shared policy.'), - default=argparse.SUPPRESS) - common_add_known_arguments(parser) - parser.add_argument( - '--audited', - action='store_true', - help=_('Sets audited to True.'), - default=argparse.SUPPRESS) - - def args2body(self, parsed_args): - return common_args2body(self.get_client(), parsed_args) - - -class UpdateFirewallPolicy(neutronv20.UpdateCommand): - """Update a given firewall policy.""" - - resource = 'firewall_policy' - - def add_known_arguments(self, parser): - common_add_known_arguments(parser) - - def args2body(self, parsed_args): - return common_args2body(self.get_client(), parsed_args) - - -class DeleteFirewallPolicy(neutronv20.DeleteCommand): - """Delete a given firewall policy.""" - - resource = 'firewall_policy' - - -class FirewallPolicyInsertRule(neutronv20.UpdateCommand): - """Insert a rule into a given firewall policy.""" - - resource = 'firewall_policy' - - def call_api(self, neutron_client, firewall_policy_id, body): - return neutron_client.firewall_policy_insert_rule(firewall_policy_id, - body) - - def args2body(self, parsed_args): - _rule = '' - if parsed_args.firewall_rule_id: - _rule = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'firewall_rule', - parsed_args.firewall_rule_id) - _insert_before = '' - if 'insert_before' in parsed_args: - if parsed_args.insert_before: - _insert_before = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'firewall_rule', - parsed_args.insert_before) - _insert_after = '' - if 'insert_after' in parsed_args: - if parsed_args.insert_after: - _insert_after = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'firewall_rule', - parsed_args.insert_after) - body = {'firewall_rule_id': _rule, - 'insert_before': _insert_before, - 'insert_after': _insert_after} - neutronv20.update_dict(parsed_args, body, []) - return body - - def get_parser(self, prog_name): - parser = super(FirewallPolicyInsertRule, self).get_parser(prog_name) - parser.add_argument( - '--insert-before', - metavar='FIREWALL_RULE', - help=_('Insert before this rule.')) - parser.add_argument( - '--insert-after', - metavar='FIREWALL_RULE', - help=_('Insert after this rule.')) - parser.add_argument( - 'firewall_rule_id', - metavar='FIREWALL_RULE', - help=_('New rule to insert.')) - self.add_known_arguments(parser) - return parser - - def run(self, parsed_args): - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - body = self.args2body(parsed_args) - _id = neutronv20.find_resourceid_by_name_or_id(neutron_client, - self.resource, - parsed_args.id) - self.call_api(neutron_client, _id, body) - print((_('Inserted firewall rule in firewall policy %(id)s') % - {'id': parsed_args.id}), file=self.app.stdout) - - -class FirewallPolicyRemoveRule(neutronv20.UpdateCommand): - """Remove a rule from a given firewall policy.""" - - resource = 'firewall_policy' - - def call_api(self, neutron_client, firewall_policy_id, body): - return neutron_client.firewall_policy_remove_rule(firewall_policy_id, - body) - - def args2body(self, parsed_args): - _rule = '' - if parsed_args.firewall_rule_id: - _rule = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'firewall_rule', - parsed_args.firewall_rule_id) - body = {'firewall_rule_id': _rule} - neutronv20.update_dict(parsed_args, body, []) - return body - - def get_parser(self, prog_name): - parser = super(FirewallPolicyRemoveRule, self).get_parser(prog_name) - parser.add_argument( - 'firewall_rule_id', - metavar='FIREWALL_RULE', - help=_('Firewall rule to remove from policy.')) - self.add_known_arguments(parser) - return parser - - def run(self, parsed_args): - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - body = self.args2body(parsed_args) - _id = neutronv20.find_resourceid_by_name_or_id(neutron_client, - self.resource, - parsed_args.id) - self.call_api(neutron_client, _id, body) - print((_('Removed firewall rule from firewall policy %(id)s') % - {'id': parsed_args.id}), file=self.app.stdout) diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewallrule.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewallrule.py deleted file mode 100644 index ecc369bcfc..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/fw/firewallrule.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2013 Big Switch Networks -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: KC Wang, Big Switch Networks -# - -import argparse - -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 - - -class ListFirewallRule(neutronv20.ListCommand): - """List firewall rules that belong to a given tenant.""" - - resource = 'firewall_rule' - list_columns = ['id', 'name', 'firewall_policy_id', 'summary', 'enabled'] - pagination_support = True - sorting_support = True - - def extend_list(self, data, parsed_args): - for d in data: - val = [] - if d.get('protocol'): - protocol = d['protocol'].upper() - else: - protocol = 'no-protocol' - val.append(protocol) - if 'source_ip_address' in d and 'source_port' in d: - src = 'source: ' + str(d['source_ip_address']).lower() - src = src + '(' + str(d['source_port']).lower() + ')' - else: - src = 'source: none specified' - val.append(src) - if 'destination_ip_address' in d and 'destination_port' in d: - dst = 'dest: ' + str(d['destination_ip_address']).lower() - dst = dst + '(' + str(d['destination_port']).lower() + ')' - else: - dst = 'dest: none specified' - val.append(dst) - if 'action' in d: - action = d['action'] - else: - action = 'no-action' - val.append(action) - d['summary'] = ',\n '.join(val) - - -class ShowFirewallRule(neutronv20.ShowCommand): - """Show information of a given firewall rule.""" - - resource = 'firewall_rule' - - -class CreateFirewallRule(neutronv20.CreateCommand): - """Create a firewall rule.""" - - resource = 'firewall_rule' - - def add_known_arguments(self, parser): - parser.add_argument( - '--name', - help=_('Name for the firewall rule.')) - parser.add_argument( - '--description', - help=_('Description for the firewall rule.')) - parser.add_argument( - '--shared', - dest='shared', - action='store_true', - help=_('Set shared to True (default is False).'), - default=argparse.SUPPRESS) - parser.add_argument( - '--source-ip-address', - help=_('Source IP address or subnet.')) - parser.add_argument( - '--destination-ip-address', - help=_('Destination IP address or subnet.')) - parser.add_argument( - '--source-port', - help=_('Source port (integer in [1, 65535] or range in a:b).')) - parser.add_argument( - '--destination-port', - help=_('Destination port (integer in [1, 65535] or range in ' - 'a:b).')) - utils.add_boolean_argument( - parser, '--enabled', dest='enabled', - help=_('Whether to enable or disable this rule.')) - parser.add_argument( - '--protocol', choices=['tcp', 'udp', 'icmp', 'any'], - required=True, - help=_('Protocol for the firewall rule.')) - parser.add_argument( - '--action', - required=True, - choices=['allow', 'deny'], - help=_('Action for the firewall rule.')) - - def args2body(self, parsed_args): - body = { - self.resource: {}, - } - neutronv20.update_dict(parsed_args, body[self.resource], - ['name', 'description', 'shared', 'protocol', - 'source_ip_address', 'destination_ip_address', - 'source_port', 'destination_port', - 'action', 'enabled', 'tenant_id']) - protocol = parsed_args.protocol - if protocol == 'any': - protocol = None - body[self.resource]['protocol'] = protocol - return body - - -class UpdateFirewallRule(neutronv20.UpdateCommand): - """Update a given firewall rule.""" - - resource = 'firewall_rule' - - def add_known_arguments(self, parser): - parser.add_argument( - '--protocol', choices=['tcp', 'udp', 'icmp', 'any'], - required=False, - help=_('Protocol for the firewall rule.')) - - def args2body(self, parsed_args): - body = { - self.resource: {}, - } - protocol = parsed_args.protocol - if protocol: - if protocol == 'any': - protocol = None - body[self.resource]['protocol'] = protocol - return body - - -class DeleteFirewallRule(neutronv20.DeleteCommand): - """Delete a given firewall rule.""" - - resource = 'firewall_rule' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/__init__.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/healthmonitor.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/healthmonitor.py deleted file mode 100644 index 0956fd4658..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/healthmonitor.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - -from __future__ import print_function - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListHealthMonitor(neutronV20.ListCommand): - """List health monitors that belong to a given tenant.""" - - resource = 'health_monitor' - list_columns = ['id', 'type', 'admin_state_up'] - pagination_support = True - sorting_support = True - - -class ShowHealthMonitor(neutronV20.ShowCommand): - """Show information of a given health monitor.""" - - resource = 'health_monitor' - allow_names = False - - -class CreateHealthMonitor(neutronV20.CreateCommand): - """Create a health monitor.""" - - resource = 'health_monitor' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--expected-codes', - help=_('The list of HTTP status codes expected in ' - 'response from the member to declare it healthy. This ' - 'attribute can contain one value, ' - 'or a list of values separated by comma, ' - 'or a range of values (e.g. "200-299"). If this attribute ' - 'is not specified, it defaults to "200".')) - parser.add_argument( - '--http-method', - help=_('The HTTP method used for requests by the monitor of type ' - 'HTTP.')) - parser.add_argument( - '--url-path', - help=_('The HTTP path used in the HTTP request used by the monitor' - ' to test a member health. This must be a string ' - 'beginning with a / (forward slash).')) - parser.add_argument( - '--delay', - required=True, - help=_('The time in seconds between sending probes to members.')) - parser.add_argument( - '--max-retries', - required=True, - help=_('Number of permissible connection failures before changing ' - 'the member status to INACTIVE. [1..10]')) - parser.add_argument( - '--timeout', - required=True, - help=_('Maximum number of seconds for a monitor to wait for a ' - 'connection to be established before it times out. The ' - 'value must be less than the delay value.')) - parser.add_argument( - '--type', - required=True, choices=['PING', 'TCP', 'HTTP', 'HTTPS'], - help=_('One of the predefined health monitor types.')) - - def args2body(self, parsed_args): - body = { - self.resource: { - 'admin_state_up': parsed_args.admin_state, - 'delay': parsed_args.delay, - 'max_retries': parsed_args.max_retries, - 'timeout': parsed_args.timeout, - 'type': parsed_args.type, - }, - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['expected_codes', 'http_method', 'url_path', - 'tenant_id']) - return body - - -class UpdateHealthMonitor(neutronV20.UpdateCommand): - """Update a given health monitor.""" - - resource = 'health_monitor' - allow_names = False - - -class DeleteHealthMonitor(neutronV20.DeleteCommand): - """Delete a given health monitor.""" - - resource = 'health_monitor' - allow_names = False - - -class AssociateHealthMonitor(neutronV20.NeutronCommand): - """Create a mapping between a health monitor and a pool.""" - - resource = 'health_monitor' - - def get_parser(self, prog_name): - parser = super(AssociateHealthMonitor, self).get_parser(prog_name) - parser.add_argument( - 'health_monitor_id', metavar='HEALTH_MONITOR_ID', - help=_('Health monitor to associate.')) - parser.add_argument( - 'pool_id', metavar='POOL', - help=_('ID of the pool to be associated with the health monitor.')) - return parser - - def run(self, parsed_args): - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - body = {'health_monitor': {'id': parsed_args.health_monitor_id}} - pool_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'pool', parsed_args.pool_id) - neutron_client.associate_health_monitor(pool_id, body) - print((_('Associated health monitor ' - '%s') % parsed_args.health_monitor_id), - file=self.app.stdout) - - -class DisassociateHealthMonitor(neutronV20.NeutronCommand): - """Remove a mapping from a health monitor to a pool.""" - - resource = 'health_monitor' - - def get_parser(self, prog_name): - parser = super(DisassociateHealthMonitor, self).get_parser(prog_name) - parser.add_argument( - 'health_monitor_id', metavar='HEALTH_MONITOR_ID', - help=_('Health monitor to associate.')) - parser.add_argument( - 'pool_id', metavar='POOL', - help=_('ID of the pool to be associated with the health monitor.')) - return parser - - def run(self, parsed_args): - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - pool_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'pool', parsed_args.pool_id) - neutron_client.disassociate_health_monitor(pool_id, - parsed_args - .health_monitor_id) - print((_('Disassociated health monitor ' - '%s') % parsed_args.health_monitor_id), - file=self.app.stdout) diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/member.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/member.py deleted file mode 100644 index 6effb3013e..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/member.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListMember(neutronV20.ListCommand): - """List members that belong to a given tenant.""" - - resource = 'member' - list_columns = [ - 'id', 'address', 'protocol_port', 'weight', 'admin_state_up', 'status' - ] - pagination_support = True - sorting_support = True - - -class ShowMember(neutronV20.ShowCommand): - """Show information of a given member.""" - - resource = 'member' - allow_names = False - - -class CreateMember(neutronV20.CreateCommand): - """Create a member.""" - - resource = 'member' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--weight', - help=_('Weight of pool member in the pool (default:1, [0..256]).')) - parser.add_argument( - '--address', - required=True, - help=_('IP address of the pool member on the pool network.')) - parser.add_argument( - '--protocol-port', - required=True, - help=_('Port on which the pool member listens for requests or ' - 'connections.')) - parser.add_argument( - 'pool_id', metavar='POOL', - help=_('Pool ID or name this vip belongs to.')) - - def args2body(self, parsed_args): - _pool_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'pool', parsed_args.pool_id) - body = { - self.resource: { - 'pool_id': _pool_id, - 'admin_state_up': parsed_args.admin_state, - }, - } - neutronV20.update_dict( - parsed_args, - body[self.resource], - ['address', 'protocol_port', 'weight', 'tenant_id'] - ) - return body - - -class UpdateMember(neutronV20.UpdateCommand): - """Update a given member.""" - - resource = 'member' - - -class DeleteMember(neutronV20.DeleteCommand): - """Delete a given member.""" - - resource = 'member' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/pool.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/pool.py deleted file mode 100644 index c10f7a87f6..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/pool.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - - -import six - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _format_provider(pool): - return pool.get('provider') or 'N/A' - - -class ListPool(neutronV20.ListCommand): - """List pools that belong to a given tenant.""" - - resource = 'pool' - list_columns = ['id', 'name', 'provider', 'lb_method', 'protocol', - 'admin_state_up', 'status'] - _formatters = {'provider': _format_provider} - pagination_support = True - sorting_support = True - - -class ShowPool(neutronV20.ShowCommand): - """Show information of a given pool.""" - - resource = 'pool' - - -class CreatePool(neutronV20.CreateCommand): - """Create a pool.""" - - resource = 'pool' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--description', - help=_('Description of the pool.')) - parser.add_argument( - '--lb-method', - required=True, - choices=['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP'], - help=_('The algorithm used to distribute load between the members ' - 'of the pool.')) - parser.add_argument( - '--name', - required=True, - help=_('The name of the pool.')) - parser.add_argument( - '--protocol', - required=True, - choices=['HTTP', 'HTTPS', 'TCP'], - help=_('Protocol for balancing.')) - parser.add_argument( - '--subnet-id', metavar='SUBNET', - required=True, - help=_('The subnet on which the members of the pool will be ' - 'located.')) - parser.add_argument( - '--provider', - help=_('Provider name of loadbalancer service.')) - - def args2body(self, parsed_args): - _subnet_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'subnet', parsed_args.subnet_id) - body = { - self.resource: { - 'admin_state_up': parsed_args.admin_state, - 'subnet_id': _subnet_id, - }, - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['description', 'lb_method', 'name', - 'protocol', 'tenant_id', 'provider']) - return body - - -class UpdatePool(neutronV20.UpdateCommand): - """Update a given pool.""" - - resource = 'pool' - - -class DeletePool(neutronV20.DeleteCommand): - """Delete a given pool.""" - - resource = 'pool' - - -class RetrievePoolStats(neutronV20.ShowCommand): - """Retrieve stats for a given pool.""" - - resource = 'pool' - - def get_data(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - pool_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'pool', parsed_args.id) - params = {} - if parsed_args.fields: - params = {'fields': parsed_args.fields} - - data = neutron_client.retrieve_pool_stats(pool_id, **params) - self.format_output_data(data) - stats = data['stats'] - if 'stats' in data: - return zip(*sorted(six.iteritems(stats))) - else: - return None diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/__init__.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/healthmonitor.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/healthmonitor.py deleted file mode 100644 index 23136f74f7..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/healthmonitor.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# Author: Ilya Shakhat, Mirantis Inc. -# Author: Craig Tracey -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListHealthMonitor(neutronV20.ListCommand): - """LBaaS v2 List healthmonitors that belong to a given tenant.""" - - resource = 'healthmonitor' - shadow_resource = 'lbaas_healthmonitor' - list_columns = ['id', 'type', 'admin_state_up'] - pagination_support = True - sorting_support = True - - -class ShowHealthMonitor(neutronV20.ShowCommand): - """LBaaS v2 Show information of a given healthmonitor.""" - - resource = 'healthmonitor' - shadow_resource = 'lbaas_healthmonitor' - - -class CreateHealthMonitor(neutronV20.CreateCommand): - """LBaaS v2 Create a healthmonitor.""" - - resource = 'healthmonitor' - shadow_resource = 'lbaas_healthmonitor' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--expected-codes', - help=_('The list of HTTP status codes expected in ' - 'response from the member to declare it healthy. This ' - 'attribute can contain one value, ' - 'or a list of values separated by comma, ' - 'or a range of values (e.g. "200-299"). If this attribute ' - 'is not specified, it defaults to "200".')) - parser.add_argument( - '--http-method', - help=_('The HTTP method used for requests by the monitor of type ' - 'HTTP.')) - parser.add_argument( - '--url-path', - help=_('The HTTP path used in the HTTP request used by the monitor' - ' to test a member health. This must be a string ' - 'beginning with a / (forward slash).')) - parser.add_argument( - '--delay', - required=True, - help=_('The time in seconds between sending probes to members.')) - parser.add_argument( - '--max-retries', - required=True, - help=_('Number of permissible connection failures before changing ' - 'the member status to INACTIVE. [1..10].')) - parser.add_argument( - '--timeout', - required=True, - help=_('Maximum number of seconds for a monitor to wait for a ' - 'connection to be established before it times out. The ' - 'value must be less than the delay value.')) - parser.add_argument( - '--type', - required=True, choices=['PING', 'TCP', 'HTTP', 'HTTPS'], - help=_('One of the predefined health monitor types.')) - - def args2body(self, parsed_args): - body = { - self.resource: { - 'admin_state_up': parsed_args.admin_state, - 'delay': parsed_args.delay, - 'max_retries': parsed_args.max_retries, - 'timeout': parsed_args.timeout, - 'type': parsed_args.type, - }, - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['expected_codes', 'http_method', 'url_path', - 'tenant_id']) - return body - - -class UpdateHealthMonitor(neutronV20.UpdateCommand): - """LBaaS v2 Update a given healthmonitor.""" - - resource = 'healthmonitor' - shadow_resource = 'lbaas_healthmonitor' - allow_names = False - - -class DeleteHealthMonitor(neutronV20.DeleteCommand): - """LBaaS v2 Delete a given healthmonitor.""" - - resource = 'healthmonitor' - shadow_resource = 'lbaas_healthmonitor' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/listener.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/listener.py deleted file mode 100644 index 6b398ffafc..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/listener.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# Author: Craig Tracey -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _get_loadbalancer_id(client, lb_id_or_name): - return neutronV20.find_resourceid_by_name_or_id( - client, - 'loadbalancer', - lb_id_or_name, - cmd_resource='lbaas_loadbalancer') - - -class ListListener(neutronV20.ListCommand): - """LBaaS v2 List listeners that belong to a given tenant.""" - - resource = 'listener' - list_columns = ['id', 'default_pool_id', 'name', 'protocol', - 'protocol_port', 'admin_state_up', 'status'] - pagination_support = True - sorting_support = True - - -class ShowListener(neutronV20.ShowCommand): - """LBaaS v2 Show information of a given listener.""" - - resource = 'listener' - - -class CreateListener(neutronV20.CreateCommand): - """LBaaS v2 Create a listener.""" - - resource = 'listener' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--connection-limit', - help=_('The maximum number of connections per second allowed for ' - 'the vip. Positive integer or -1 for unlimited (default).')) - parser.add_argument( - '--description', - help=_('Description of the listener.')) - parser.add_argument( - '--name', - help=_('The name of the listener.')) - parser.add_argument( - '--loadbalancer', - required=True, - metavar='LOADBALANCER', - help=_('ID or name of the load balancer.')) - parser.add_argument( - '--protocol', - required=True, - choices=['TCP', 'HTTP', 'HTTPS'], - help=_('Protocol for the listener.')) - parser.add_argument( - '--protocol-port', - dest='protocol_port', required=True, - metavar='PORT', - help=_('Protocol port for the listener.')) - - def args2body(self, parsed_args): - if parsed_args.loadbalancer: - parsed_args.loadbalancer = _get_loadbalancer_id( - self.get_client(), - parsed_args.loadbalancer) - body = { - self.resource: { - 'loadbalancer_id': parsed_args.loadbalancer, - 'protocol': parsed_args.protocol, - 'protocol_port': parsed_args.protocol_port, - 'admin_state_up': parsed_args.admin_state, - }, - } - - neutronV20.update_dict(parsed_args, body[self.resource], - ['connection-limit', 'description', - 'loadbalancer_id', 'name']) - return body - - -class UpdateListener(neutronV20.UpdateCommand): - """LBaaS v2 Update a given listener.""" - - resource = 'listener' - allow_names = False - - -class DeleteListener(neutronV20.DeleteCommand): - """LBaaS v2 Delete a given listener.""" - - resource = 'listener' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/loadbalancer.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/loadbalancer.py deleted file mode 100644 index 576c5fa5a1..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/loadbalancer.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# Author: Craig Tracey -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListLoadBalancer(neutronV20.ListCommand): - """LBaaS v2 List loadbalancers that belong to a given tenant.""" - - resource = 'loadbalancer' - list_columns = ['id', 'name', 'vip_address', - 'provisioning_status', 'provider'] - pagination_support = True - sorting_support = True - - -class ShowLoadBalancer(neutronV20.ShowCommand): - """LBaaS v2 Show information of a given loadbalancer.""" - - resource = 'loadbalancer' - - -class CreateLoadBalancer(neutronV20.CreateCommand): - """LBaaS v2 Create a loadbalancer.""" - - resource = 'loadbalancer' - allow_names = True - - def add_known_arguments(self, parser): - parser.add_argument( - '--description', - help=_('Description of the load balancer.')) - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--name', metavar='NAME', - help=_('Name of the load balancer.')) - parser.add_argument( - '--provider', - help=_('Provider name of load balancer service.')) - parser.add_argument( - '--vip-address', - help=_('VIP address for the load balancer.')) - parser.add_argument( - 'vip_subnet', metavar='VIP_SUBNET', - help=_('Load balancer VIP subnet.')) - - def args2body(self, parsed_args): - _subnet_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'subnet', parsed_args.vip_subnet) - body = { - self.resource: { - 'name': parsed_args.name, - 'vip_subnet_id': _subnet_id, - 'admin_state_up': parsed_args.admin_state, - }, - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['description', 'provider', 'vip_address']) - return body - - -class UpdateLoadBalancer(neutronV20.UpdateCommand): - """LBaaS v2 Update a given loadbalancer.""" - - resource = 'loadbalancer' - allow_names = True - - -class DeleteLoadBalancer(neutronV20.DeleteCommand): - """LBaaS v2 Delete a given loadbalancer.""" - - resource = 'loadbalancer' - allow_names = True diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/member.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/member.py deleted file mode 100644 index 4709f65ba1..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/member.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# Copyright 2014 Blue Box Group, Inc. -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# Author: Ilya Shakhat, Mirantis Inc. -# Author: Craig Tracey -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _get_pool_id(client, pool_id_or_name): - return neutronV20.find_resourceid_by_name_or_id(client, 'pool', - pool_id_or_name, - cmd_resource='lbaas_pool') - - -class LbaasMemberMixin(object): - - def set_extra_attrs(self, parsed_args): - self.parent_id = _get_pool_id(self.get_client(), parsed_args.pool) - - def add_known_arguments(self, parser): - parser.add_argument( - 'pool', metavar='POOL', - help=_('ID or name of the pool that this member belongs to.')) - - -class ListMember(LbaasMemberMixin, neutronV20.ListCommand): - """LBaaS v2 List members that belong to a given tenant.""" - - resource = 'member' - shadow_resource = 'lbaas_member' - list_columns = [ - 'id', 'address', 'protocol_port', 'weight', - 'subnet_id', 'admin_state_up', 'status' - ] - pagination_support = True - sorting_support = True - - -class ShowMember(LbaasMemberMixin, neutronV20.ShowCommand): - """LBaaS v2 Show information of a given member.""" - - resource = 'member' - shadow_resource = 'lbaas_member' - - -class CreateMember(neutronV20.CreateCommand): - """LBaaS v2 Create a member.""" - - resource = 'member' - shadow_resource = 'lbaas_member' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false')) - parser.add_argument( - '--weight', - help=_('Weight of member in the pool (default:1, [0..256]).')) - parser.add_argument( - '--subnet', - required=True, - help=_('Subnet ID or name for the member.')) - parser.add_argument( - '--address', - required=True, - help=_('IP address of the pool member in the pool.')) - parser.add_argument( - '--protocol-port', - required=True, - help=_('Port on which the pool member listens for requests or ' - 'connections.')) - parser.add_argument( - 'pool', metavar='POOL', - help=_('ID or name of the pool that this member belongs to.')) - - def args2body(self, parsed_args): - self.parent_id = _get_pool_id(self.get_client(), parsed_args.pool) - _subnet_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'subnet', parsed_args.subnet) - body = { - self.resource: { - 'subnet_id': _subnet_id, - 'admin_state_up': parsed_args.admin_state, - 'protocol_port': parsed_args.protocol_port, - 'address': parsed_args.address, - }, - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['weight', 'subnet_id']) - return body - - -class UpdateMember(neutronV20.UpdateCommand): - """LBaaS v2 Update a given member.""" - - resource = 'member' - shadow_resource = 'lbaas_member' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false')) - parser.add_argument( - '--weight', - help=_('Weight of member in the pool (default:1, [0..256])')) - parser.add_argument( - 'pool', metavar='POOL', - help=_('ID or name of the pool that this member belongs to')) - - def args2body(self, parsed_args): - self.parent_id = _get_pool_id(self.get_client(), parsed_args.pool) - body = { - self.resource: {} - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['admin_state_up', 'weight']) - return body - - -class DeleteMember(LbaasMemberMixin, neutronV20.DeleteCommand): - """LBaaS v2 Delete a given member.""" - - resource = 'member' - shadow_resource = 'lbaas_member' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/pool.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/pool.py deleted file mode 100644 index 11644be45d..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/v2/pool.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# Copyright 2014 Blue Box Group, Inc. -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# Author: Ilya Shakhat, Mirantis Inc. -# Author: Craig Tracey -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.common import exceptions -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _parse_persistence(parsed_args): - persistence = None - if parsed_args.session_persistence: - parts = parsed_args.session_persistence.split(':') - if not len(parts) == 2: - raise exceptions.CommandError('Incorrect --session-persistence' - ' format. Format is :') - persistence = {'type': parts[0], 'cookie_name': parts[1]} - return persistence - - -class ListPool(neutronV20.ListCommand): - """LBaaS v2 List pools that belong to a given tenant.""" - - resource = 'pool' - shadow_resource = 'lbaas_pool' - list_columns = ['id', 'name', 'lb_method', 'protocol', - 'admin_state_up'] - pagination_support = True - sorting_support = True - - -class ShowPool(neutronV20.ShowCommand): - """LBaaS v2 Show information of a given pool.""" - - resource = 'pool' - shadow_resource = 'lbaas_pool' - - def cleanup_output_data(self, data): - if 'members' not in data['pool']: - return [] - member_info = [] - for member in data['pool']['members']: - member_info.append(member['id']) - data['pool']['members'] = member_info - - -class CreatePool(neutronV20.CreateCommand): - """LBaaS v2 Create a pool.""" - - resource = 'pool' - shadow_resource = 'lbaas_pool' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--description', - help=_('Description of the pool.')) - parser.add_argument( - '--healthmonitor-id', - help=_('ID of the health monitor to use.')) - parser.add_argument( - '--session-persistence', metavar='TYPE:VALUE', - help=_('The type of session persistence to use.')) - parser.add_argument( - '--lb-algorithm', - required=True, - choices=['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP'], - help=_('The algorithm used to distribute load between the members ' - 'of the pool.')) - parser.add_argument( - '--listener', - required=True, - help=_('The listener to associate with the pool')) - parser.add_argument( - '--protocol', - required=True, - choices=['HTTP', 'HTTPS', 'TCP'], - help=_('Protocol for balancing.')) - parser.add_argument( - 'name', metavar='NAME', - help=_('The name of the pool.')) - - def args2body(self, parsed_args): - if parsed_args.session_persistence: - parsed_args.session_persistence = _parse_persistence(parsed_args) - _listener_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'listener', parsed_args.listener) - body = { - self.resource: { - 'name': parsed_args.name, - 'admin_state_up': parsed_args.admin_state, - 'protocol': parsed_args.protocol, - 'lb_algorithm': parsed_args.lb_algorithm, - 'listener_id': _listener_id, - }, - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['description', 'healthmonitor_id', - 'session_persistence']) - return body - - -class UpdatePool(neutronV20.UpdateCommand): - """LBaaS v2 Update a given pool.""" - - resource = 'pool' - shadow_resource = 'lbaas_pool' - - -class DeletePool(neutronV20.DeleteCommand): - """LBaaS v2 Delete a given pool.""" - - resource = 'pool' - shadow_resource = 'lbaas_pool' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/vip.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/vip.py deleted file mode 100644 index 3c85d3378e..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/lb/vip.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListVip(neutronV20.ListCommand): - """List vips that belong to a given tenant.""" - - resource = 'vip' - list_columns = ['id', 'name', 'algorithm', 'address', 'protocol', - 'admin_state_up', 'status'] - pagination_support = True - sorting_support = True - - -class ShowVip(neutronV20.ShowCommand): - """Show information of a given vip.""" - - resource = 'vip' - - -class CreateVip(neutronV20.CreateCommand): - """Create a vip.""" - - resource = 'vip' - - def add_known_arguments(self, parser): - parser.add_argument( - 'pool_id', metavar='POOL', - help=_('Pool ID or name this vip belongs to.')) - parser.add_argument( - '--address', - help=_('IP address of the vip.')) - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--connection-limit', - help=_('The maximum number of connections per second allowed for ' - 'the vip. Positive integer or -1 for unlimited (default).')) - parser.add_argument( - '--description', - help=_('Description of the vip.')) - parser.add_argument( - '--name', - required=True, - help=_('Name of the vip.')) - parser.add_argument( - '--protocol-port', - required=True, - help=_('TCP port on which to listen for client traffic that is ' - 'associated with the vip address.')) - parser.add_argument( - '--protocol', - required=True, choices=['TCP', 'HTTP', 'HTTPS'], - help=_('Protocol for balancing.')) - parser.add_argument( - '--subnet-id', metavar='SUBNET', - required=True, - help=_('The subnet on which to allocate the vip address.')) - - def args2body(self, parsed_args): - _pool_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'pool', parsed_args.pool_id) - _subnet_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'subnet', parsed_args.subnet_id) - - body = { - self.resource: { - 'pool_id': _pool_id, - 'admin_state_up': parsed_args.admin_state, - 'subnet_id': _subnet_id, - }, - } - neutronV20.update_dict(parsed_args, body[self.resource], - ['address', 'connection_limit', 'description', - 'name', 'protocol_port', 'protocol', - 'tenant_id']) - return body - - -class UpdateVip(neutronV20.UpdateCommand): - """Update a given vip.""" - - resource = 'vip' - - -class DeleteVip(neutronV20.DeleteCommand): - """Delete a given vip.""" - - resource = 'vip' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/metering.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/metering.py deleted file mode 100644 index c2649c483a..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/metering.py +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright (C) 2013 eNovance SAS -# -# Author: Sylvain Afchain -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 - - -class ListMeteringLabel(neutronv20.ListCommand): - """List metering labels that belong to a given tenant.""" - - resource = 'metering_label' - list_columns = ['id', 'name', 'description', 'shared'] - pagination_support = True - sorting_support = True - - -class ShowMeteringLabel(neutronv20.ShowCommand): - """Show information of a given metering label.""" - - resource = 'metering_label' - allow_names = True - - -class CreateMeteringLabel(neutronv20.CreateCommand): - """Create a metering label for a given tenant.""" - - resource = 'metering_label' - - def add_known_arguments(self, parser): - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of metering label to create.')) - parser.add_argument( - '--description', - help=_('Description of metering label to create.')) - parser.add_argument( - '--shared', - action='store_true', - help=_('Set the label as shared.')) - - def args2body(self, parsed_args): - body = {'metering_label': { - 'name': parsed_args.name}, } - - if parsed_args.tenant_id: - body['metering_label'].update({'tenant_id': parsed_args.tenant_id}) - if parsed_args.description: - body['metering_label'].update( - {'description': parsed_args.description}) - if parsed_args.shared: - body['metering_label'].update( - {'shared': True}) - return body - - -class DeleteMeteringLabel(neutronv20.DeleteCommand): - """Delete a given metering label.""" - - resource = 'metering_label' - allow_names = True - - -class ListMeteringLabelRule(neutronv20.ListCommand): - """List metering labels that belong to a given label.""" - - resource = 'metering_label_rule' - list_columns = ['id', 'excluded', 'direction', 'remote_ip_prefix'] - pagination_support = True - sorting_support = True - - -class ShowMeteringLabelRule(neutronv20.ShowCommand): - """Show information of a given metering label rule.""" - - resource = 'metering_label_rule' - - -class CreateMeteringLabelRule(neutronv20.CreateCommand): - """Create a metering label rule for a given label.""" - - resource = 'metering_label_rule' - - def add_known_arguments(self, parser): - parser.add_argument( - 'label_id', metavar='LABEL', - help=_('Id or Name of the label.')) - parser.add_argument( - 'remote_ip_prefix', metavar='REMOTE_IP_PREFIX', - help=_('CIDR to match on.')) - parser.add_argument( - '--direction', - default='ingress', choices=['ingress', 'egress'], - help=_('Direction of traffic, default: ingress.')) - parser.add_argument( - '--excluded', - action='store_true', - help=_('Exclude this CIDR from the label, default: not excluded.')) - - def args2body(self, parsed_args): - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - label_id = neutronv20.find_resourceid_by_name_or_id( - neutron_client, 'metering_label', parsed_args.label_id) - - body = {'metering_label_rule': { - 'metering_label_id': label_id, - 'remote_ip_prefix': parsed_args.remote_ip_prefix - }} - - if parsed_args.direction: - body['metering_label_rule'].update( - {'direction': parsed_args.direction}) - if parsed_args.excluded: - body['metering_label_rule'].update( - {'excluded': True}) - return body - - -class DeleteMeteringLabelRule(neutronv20.DeleteCommand): - """Delete a given metering label.""" - - resource = 'metering_label_rule' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/nec/__init__.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/nec/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/nec/packetfilter.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/nec/packetfilter.py deleted file mode 100644 index dd77cf569a..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/nec/packetfilter.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright 2014 NEC Corporation -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.common import validators -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListPacketFilter(neutronV20.ListCommand): - """List packet filters that belong to a given tenant.""" - - resource = 'packet_filter' - list_columns = ['id', 'name', 'action', 'priority', 'summary'] - pagination_support = True - sorting_support = True - - def extend_list(self, data, parsed_args): - for d in data: - val = [] - proto_eth_type = [] - if d.get('protocol'): - proto_eth_type.append('protocol: %s' % d['protocol'].upper()) - if d.get('eth_type'): - proto_eth_type.append('eth_type: %s' % d['eth_type']) - if proto_eth_type: - val.append(', '.join(proto_eth_type)) - val.append('network: ' + d['network_id']) - if d.get('in_port'): - val.append('in_port: ' + d['in_port']) - source = [str(d.get(field)) for field - in ['src_mac', 'src_cidr', 'src_port'] if d.get(field)] - if source: - val.append('source: ' + ' '.join(source)) - dest = [str(d.get(field)) for field - in ['dst_mac', 'dst_cidr', 'dst_port'] if d.get(field)] - if dest: - val.append('destination: ' + ' '.join(dest)) - d['summary'] = '\n'.join(val) - - -class ShowPacketFilter(neutronV20.ShowCommand): - """Show information of a given packet filter.""" - - resource = 'packet_filter' - - -class PacketFilterOptionMixin(object): - def add_known_arguments(self, parser): - mode = self._get_mode() - if not mode: - return - mode_create = mode == 'create' - - if mode_create: - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set Admin State Up to false')) - else: - utils.add_boolean_argument( - parser, '--admin-state', - help=_('Set a value of Admin State Up')) - - parser.add_argument( - '--name', - help=_('Name of this packet filter')) - - if mode_create: - parser.add_argument( - '--in-port', metavar='PORT', - help=_('Name or ID of the input port')) - - parser.add_argument( - '--src-mac', - help=_('Source MAC address')) - parser.add_argument( - '--dst-mac', - help=_('Destination MAC address')) - parser.add_argument( - '--eth-type', - help=_('Ether Type. Integer [0:65535] (hex or decimal).' - ' E.g., 0x0800 (IPv4), 0x0806 (ARP), 0x86DD (IPv6)')) - parser.add_argument( - '--protocol', - help=_('IP Protocol.' - ' Protocol name or integer.' - ' Recognized names are icmp, tcp, udp, arp' - ' (case insensitive).' - ' Integer should be [0:255] (decimal or hex).')) - parser.add_argument( - '--src-cidr', - help=_('Source IP address CIDR')) - parser.add_argument( - '--dst-cidr', - help=_('Destination IP address CIDR')) - parser.add_argument( - '--src-port', - help=_('Source port address')) - parser.add_argument( - '--dst-port', - help=_('Destination port address')) - - default_priority = '30000' if mode_create else None - parser.add_argument( - '--priority', metavar='PRIORITY', - default=default_priority, - help=(_('Priority of the filter. Integer of [0:65535].%s') - % (' Default: 30000.' if mode_create else ''))) - - default_action = 'allow' if mode_create else None - parser.add_argument( - '--action', - choices=['allow', 'drop'], - default=default_action, - help=(_('Action of the filter.%s') - % (' Default: allow' if mode_create else ''))) - - if mode_create: - parser.add_argument( - 'network', metavar='NETWORK', - help=_('network to which this packet filter is applied')) - - def _get_mode(self): - klass = self.__class__.__name__.lower() - if klass.startswith('create'): - mode = 'create' - elif klass.startswith('update'): - mode = 'update' - else: - mode = None - return mode - - def validate_fields(self, parsed_args): - self._validate_protocol(parsed_args.protocol) - validators.validate_int_range(parsed_args, 'priority', 0, 0xffff) - validators.validate_int_range(parsed_args, 'src_port', 0, 0xffff) - validators.validate_int_range(parsed_args, 'dst_port', 0, 0xffff) - validators.validate_ip_subnet(parsed_args, 'src_cidr') - validators.validate_ip_subnet(parsed_args, 'dst_cidr') - - def _validate_protocol(self, protocol): - if not protocol or protocol == 'action=clear': - return - try: - protocol = int(protocol, 0) - if 0 <= protocol <= 255: - return - except ValueError: - # Use string as a protocol name - # Exact check will be done in the server side. - return - msg = (_('protocol %s should be either of name ' - '(tcp, udp, icmp, arp; ' - 'case insensitive) or integer [0:255] (decimal or hex).') % - protocol) - raise exceptions.CommandError(msg) - - -class CreatePacketFilter(PacketFilterOptionMixin, - neutronV20.CreateCommand): - """Create a packet filter for a given tenant.""" - - resource = 'packet_filter' - - def args2body(self, parsed_args): - self.validate_fields(parsed_args) - - _network_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'network', parsed_args.network) - body = {'network_id': _network_id, - 'admin_state_up': parsed_args.admin_state} - if parsed_args.in_port: - _port_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'port', parsed_args.in_port) - body['in_port'] = _port_id - - neutronV20.update_dict( - parsed_args, body, - ['action', 'priority', 'name', - 'eth_type', 'protocol', 'src_mac', 'dst_mac', - 'src_cidr', 'dst_cidr', 'src_port', 'dst_port']) - - return {self.resource: body} - - -class UpdatePacketFilter(PacketFilterOptionMixin, - neutronV20.UpdateCommand): - """Update packet filter's information.""" - - resource = 'packet_filter' - - def args2body(self, parsed_args): - self.validate_fields(parsed_args) - - body = {} - if hasattr(parsed_args, 'admin_state'): - body['admin_state_up'] = (parsed_args.admin_state == 'True') - - # fields which allows None - for attr in ['eth_type', 'protocol', 'src_mac', 'dst_mac', - 'src_cidr', 'dst_cidr', 'src_port', 'dst_port']: - if not hasattr(parsed_args, attr): - continue - val = getattr(parsed_args, attr) - if val is None: - continue - if val == '' or val == 'action=clear': - body[attr] = None - else: - body[attr] = val - - for attr in ['action', 'priority', 'name']: - if (hasattr(parsed_args, attr) and - getattr(parsed_args, attr) is not None): - body[attr] = getattr(parsed_args, attr) - - return {self.resource: body} - - -class DeletePacketFilter(neutronV20.DeleteCommand): - """Delete a given packet filter.""" - - resource = 'packet_filter' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/netpartition.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/netpartition.py deleted file mode 100644 index 4fd0604429..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/netpartition.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2014 Alcatel-Lucent USA Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ronak Shah, Nuage Networks, Alcatel-Lucent USA Inc. - -from neutronclient.neutron.v2_0 import CreateCommand -from neutronclient.neutron.v2_0 import DeleteCommand -from neutronclient.neutron.v2_0 import ListCommand -from neutronclient.neutron.v2_0 import ShowCommand - - -class ListNetPartition(ListCommand): - """List netpartitions that belong to a given tenant.""" - resource = 'net_partition' - list_columns = ['id', 'name'] - - -class ShowNetPartition(ShowCommand): - """Show information of a given netpartition.""" - - resource = 'net_partition' - - -class CreateNetPartition(CreateCommand): - """Create a netpartition for a given tenant.""" - - resource = 'net_partition' - - def add_known_arguments(self, parser): - parser.add_argument( - 'name', metavar='name', - help='Name of netpartition to create.') - - def args2body(self, parsed_args): - body = {'net_partition': {'name': parsed_args.name}, } - return body - - -class DeleteNetPartition(DeleteCommand): - """Delete a given netpartition.""" - - resource = 'net_partition' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/network.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/network.py deleted file mode 100644 index 44adff7444..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/network.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import argparse - -from neutronclient.common import exceptions -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _format_subnets(network): - try: - return '\n'.join([' '.join([s['id'], s.get('cidr', '')]) - for s in network['subnets']]) - except (TypeError, KeyError): - return '' - - -class ListNetwork(neutronV20.ListCommand): - """List networks that belong to a given tenant.""" - - # Length of a query filter on subnet id - # id=& (with len(uuid)=36) - subnet_id_filter_len = 40 - resource = 'network' - _formatters = {'subnets': _format_subnets, } - list_columns = ['id', 'name', 'subnets'] - pagination_support = True - sorting_support = True - - def extend_list(self, data, parsed_args): - """Add subnet information to a network list.""" - neutron_client = self.get_client() - search_opts = {'fields': ['id', 'cidr']} - if self.pagination_support: - page_size = parsed_args.page_size - if page_size: - search_opts.update({'limit': page_size}) - subnet_ids = [] - for n in data: - if 'subnets' in n: - subnet_ids.extend(n['subnets']) - - def _get_subnet_list(sub_ids): - search_opts['id'] = sub_ids - return neutron_client.list_subnets( - **search_opts).get('subnets', []) - - try: - subnets = _get_subnet_list(subnet_ids) - except exceptions.RequestURITooLong as uri_len_exc: - # The URI is too long because of too many subnet_id filters - # Use the excess attribute of the exception to know how many - # subnet_id filters can be inserted into a single request - subnet_count = len(subnet_ids) - max_size = ((self.subnet_id_filter_len * subnet_count) - - uri_len_exc.excess) - chunk_size = max_size // self.subnet_id_filter_len - subnets = [] - for i in range(0, subnet_count, chunk_size): - subnets.extend( - _get_subnet_list(subnet_ids[i: i + chunk_size])) - - subnet_dict = dict([(s['id'], s) for s in subnets]) - for n in data: - if 'subnets' in n: - n['subnets'] = [(subnet_dict.get(s) or {"id": s}) - for s in n['subnets']] - - -class ListExternalNetwork(ListNetwork): - """List external networks that belong to a given tenant.""" - - pagination_support = True - sorting_support = True - - def retrieve_list(self, parsed_args): - external = '--router:external=True' - if external not in self.values_specs: - self.values_specs.append('--router:external=True') - return super(ListExternalNetwork, self).retrieve_list(parsed_args) - - -class ShowNetwork(neutronV20.ShowCommand): - """Show information of a given network.""" - - resource = 'network' - - -class CreateNetwork(neutronV20.CreateCommand): - """Create a network for a given tenant.""" - - resource = 'network' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--admin_state_down', - dest='admin_state', action='store_false', - help=argparse.SUPPRESS) - parser.add_argument( - '--shared', - action='store_true', - help=_('Set the network as shared.'), - default=argparse.SUPPRESS) - parser.add_argument( - '--router:external', - action='store_true', - help=_('Set network as external, it is only available for admin'), - default=argparse.SUPPRESS) - parser.add_argument( - '--provider:network_type', - metavar='', - help=_('The physical mechanism by which the virtual network' - ' is implemented.')) - parser.add_argument( - '--provider:physical_network', - metavar='', - help=_('Name of the physical network over which the virtual' - ' network is implemented.')) - parser.add_argument( - '--provider:segmentation_id', - metavar='', - help=_('VLAN ID for VLAN networks or tunnel-id for GRE/VXLAN' - ' networks.')) - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of network to create.')) - - def args2body(self, parsed_args): - body = {'network': { - 'name': parsed_args.name, - 'admin_state_up': parsed_args.admin_state}, } - neutronV20.update_dict(parsed_args, body['network'], - ['shared', 'tenant_id', 'router:external', - 'provider:network_type', - 'provider:physical_network', - 'provider:segmentation_id']) - return body - - -class DeleteNetwork(neutronV20.DeleteCommand): - """Delete a given network.""" - - resource = 'network' - - -class UpdateNetwork(neutronV20.UpdateCommand): - """Update network's information.""" - - resource = 'network' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/networkprofile.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/networkprofile.py deleted file mode 100644 index 03fc4972ad..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/networkprofile.py +++ /dev/null @@ -1,151 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -#@author Abhishek Raut, Cisco Systems -#@author Sergey Sudakovich, Cisco Systems -#@author Rudrajit Tapadar, Cisco Systems - -from __future__ import print_function - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 -from neutronclient.neutron.v2_0 import parse_args_to_dict - -RESOURCE = 'network_profile' -SEGMENT_TYPE_CHOICES = ['vlan', 'overlay', 'multi-segment', 'trunk'] - - -class ListNetworkProfile(neutronV20.ListCommand): - """List network profiles that belong to a given tenant.""" - - resource = RESOURCE - _formatters = {} - list_columns = ['id', 'name', 'segment_type', 'sub_type', 'segment_range', - 'physical_network', 'multicast_ip_index', - 'multicast_ip_range'] - - -class ShowNetworkProfile(neutronV20.ShowCommand): - """Show information of a given network profile.""" - - resource = RESOURCE - allow_names = True - - -class CreateNetworkProfile(neutronV20.CreateCommand): - """Creates a network profile.""" - - resource = RESOURCE - - def add_known_arguments(self, parser): - parser.add_argument('name', - help=_('Name for network profile.')) - parser.add_argument('segment_type', - choices=SEGMENT_TYPE_CHOICES, - help='Segment type.') - # TODO(Abhishek): Check on sub-type choices depending on segment_type - parser.add_argument('--sub_type', - help=_('Sub-type for the segment. Available ' - 'sub-types for overlay segments: ' - 'native, enhanced; For trunk segments: ' - 'vlan, overlay.')) - parser.add_argument('--segment_range', - help=_('Range for the segment.')) - parser.add_argument('--physical_network', - help=_('Name for the physical network.')) - parser.add_argument('--multicast_ip_range', - help=_('Multicast IPv4 range.')) - parser.add_argument("--add-tenant", - action='append', dest='add_tenants', - help=_("Add tenant to the network profile. " - "You can repeat this option.")) - - def args2body(self, parsed_args): - body = {'network_profile': {'name': parsed_args.name}} - if parsed_args.segment_type: - body['network_profile'].update({'segment_type': - parsed_args.segment_type}) - if parsed_args.sub_type: - body['network_profile'].update({'sub_type': - parsed_args.sub_type}) - if parsed_args.segment_range: - body['network_profile'].update({'segment_range': - parsed_args.segment_range}) - if parsed_args.physical_network: - body['network_profile'].update({'physical_network': - parsed_args.physical_network}) - if parsed_args.multicast_ip_range: - body['network_profile'].update({'multicast_ip_range': - parsed_args.multicast_ip_range}) - if parsed_args.add_tenants: - body['network_profile'].update({'add_tenants': - parsed_args.add_tenants}) - return body - - -class DeleteNetworkProfile(neutronV20.DeleteCommand): - """Delete a given network profile.""" - - resource = RESOURCE - allow_names = True - - -class UpdateNetworkProfile(neutronV20.UpdateCommand): - """Update network profile's information.""" - - resource = RESOURCE - - def add_known_arguments(self, parser): - parser.add_argument("--remove-tenant", - action='append', dest='remove_tenants', - help=_("Remove tenant from the network profile. " - "You can repeat this option.")) - parser.add_argument("--add-tenant", - action='append', dest='add_tenants', - help=_("Add tenant to the network profile. " - "You can repeat this option.")) - - def args2body(self, parsed_args): - body = {'network_profile': {}} - if parsed_args.remove_tenants: - body['network_profile']['remove_tenants'] = (parsed_args. - remove_tenants) - if parsed_args.add_tenants: - body['network_profile']['add_tenants'] = parsed_args.add_tenants - return body - - -# Aaron: This function is deprecated -class UpdateNetworkProfileV2(neutronV20.NeutronCommand): - - api = 'network' - resource = RESOURCE - - def get_parser(self, prog_name): - parser = super(UpdateNetworkProfileV2, self).get_parser(prog_name) - parser.add_argument("--remove-tenant", - help="Remove tenant from the network profile.") - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - data = {self.resource: parse_args_to_dict(parsed_args)} - if parsed_args.remove_tenant: - data[self.resource]['remove_tenant'] = parsed_args.remove_tenant - neutron_client.update_network_profile(parsed_args.id, - {self.resource: data}) - print((_('Updated %(resource)s: %(id)s') % - {'id': parsed_args.id, 'resource': self.resource}), - file=self.app.stdout) - return diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/__init__.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/networkgateway.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/networkgateway.py deleted file mode 100644 index 52a38256b7..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/networkgateway.py +++ /dev/null @@ -1,267 +0,0 @@ -# Copyright 2013 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from __future__ import print_function - -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - -GW_RESOURCE = 'network_gateway' -DEV_RESOURCE = 'gateway_device' -CONNECTOR_TYPE_HELP = _("Type of the transport zone connector to use for this " - "device. Valid values are gre, stt, ipsecgre, " - "ipsecstt, and bridge. Defaults to stt.") -CONNECTOR_IP_HELP = _("IP address for this device's transport connector. " - "It must correspond to the IP address of the interface " - "used for tenant traffic on the NSX gateway node.") -CLIENT_CERT_HELP = _("PEM certificate used by the NSX gateway transport node " - "to authenticate with the NSX controller.") -CLIENT_CERT_FILE_HELP = _("File containing the PEM certificate used by the " - "NSX gateway transport node to authenticate with " - "the NSX controller.") - - -class ListGatewayDevice(neutronV20.ListCommand): - """List network gateway devices for a given tenant.""" - - resource = DEV_RESOURCE - list_columns = ['id', 'name'] - - -class ShowGatewayDevice(neutronV20.ShowCommand): - """Show information for a given network gateway device.""" - - resource = DEV_RESOURCE - - -def read_cert_file(cert_file): - return open(cert_file, 'rb').read() - - -def gateway_device_args2body(parsed_args): - body = {} - if parsed_args.name: - body['name'] = parsed_args.name - if parsed_args.connector_type: - body['connector_type'] = parsed_args.connector_type - if parsed_args.connector_ip: - body['connector_ip'] = parsed_args.connector_ip - cert_data = None - if parsed_args.cert_file: - cert_data = read_cert_file(parsed_args.cert_file) - elif parsed_args.cert_data: - cert_data = parsed_args.cert_data - if cert_data: - body['client_certificate'] = cert_data - if getattr(parsed_args, 'tenant_id', None): - body['tenant_id'] = parsed_args.tenant_id - return {DEV_RESOURCE: body} - - -class CreateGatewayDevice(neutronV20.CreateCommand): - """Create a network gateway device.""" - - resource = DEV_RESOURCE - - def add_known_arguments(self, parser): - parser.add_argument( - 'name', metavar='NAME', - help='Name of network gateway device to create.') - parser.add_argument( - '--connector-type', - default='stt', - choices=['stt', 'gre', 'ipsecgre', 'ipsecstt', 'bridge'], - help=CONNECTOR_TYPE_HELP) - parser.add_argument( - '--connector-ip', - required=True, - help=CONNECTOR_IP_HELP) - client_cert_group = parser.add_mutually_exclusive_group( - required=True) - client_cert_group.add_argument( - '--client-certificate', - dest='cert_data', - help=CLIENT_CERT_HELP) - client_cert_group.add_argument( - '--client-certificate-file', - dest='cert_file', - help=CLIENT_CERT_FILE_HELP) - - def args2body(self, parsed_args): - return gateway_device_args2body(parsed_args) - - -class UpdateGatewayDevice(neutronV20.UpdateCommand): - """Update a network gateway device.""" - - resource = DEV_RESOURCE - - def add_known_arguments(self, parser): - parser.add_argument( - '--name', metavar='NAME', - help='New name for network gateway device.') - parser.add_argument( - '--connector-type', - required=False, - choices=['stt', 'gre', 'ipsecgre', 'ipsecstt', 'bridge'], - help=CONNECTOR_TYPE_HELP) - parser.add_argument( - '--connector-ip', - required=False, - help=CONNECTOR_IP_HELP) - client_cert_group = parser.add_mutually_exclusive_group() - client_cert_group.add_argument( - '--client-certificate', - dest='cert_data', - help=CLIENT_CERT_HELP) - client_cert_group.add_argument( - '--client-certificate-file', - dest='cert_file', - help=CLIENT_CERT_FILE_HELP) - - def args2body(self, parsed_args): - return gateway_device_args2body(parsed_args) - - -class DeleteGatewayDevice(neutronV20.DeleteCommand): - """Delete a given network gateway device.""" - - resource = DEV_RESOURCE - - -class ListNetworkGateway(neutronV20.ListCommand): - """List network gateways for a given tenant.""" - - resource = GW_RESOURCE - list_columns = ['id', 'name'] - - -class ShowNetworkGateway(neutronV20.ShowCommand): - """Show information of a given network gateway.""" - - resource = GW_RESOURCE - - -class CreateNetworkGateway(neutronV20.CreateCommand): - """Create a network gateway.""" - - resource = GW_RESOURCE - - def add_known_arguments(self, parser): - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of network gateway to create.')) - parser.add_argument( - '--device', metavar='id=ID,interface_name=NAME_OR_ID', - action='append', - help=_('Device info for this gateway. You can repeat this ' - 'option for multiple devices for HA gateways.')) - - def args2body(self, parsed_args): - body = {self.resource: { - 'name': parsed_args.name}} - devices = [] - if parsed_args.device: - for device in parsed_args.device: - devices.append(utils.str2dict(device)) - if devices: - body[self.resource].update({'devices': devices}) - if parsed_args.tenant_id: - body[self.resource].update({'tenant_id': parsed_args.tenant_id}) - return body - - -class DeleteNetworkGateway(neutronV20.DeleteCommand): - """Delete a given network gateway.""" - - resource = GW_RESOURCE - - -class UpdateNetworkGateway(neutronV20.UpdateCommand): - """Update the name for a network gateway.""" - - resource = GW_RESOURCE - - -class NetworkGatewayInterfaceCommand(neutronV20.NeutronCommand): - """Base class for connecting/disconnecting networks to/from a gateway.""" - - resource = GW_RESOURCE - - def get_parser(self, prog_name): - parser = super(NetworkGatewayInterfaceCommand, - self).get_parser(prog_name) - parser.add_argument( - 'net_gateway_id', metavar='NET-GATEWAY-ID', - help=_('ID of the network gateway.')) - parser.add_argument( - 'network_id', metavar='NETWORK-ID', - help=_('ID of the internal network to connect on the gateway.')) - parser.add_argument( - '--segmentation-type', - help=_('L2 segmentation strategy on the external side of ' - 'the gateway (e.g.: VLAN, FLAT).')) - parser.add_argument( - '--segmentation-id', - help=_('Identifier for the L2 segment on the external side ' - 'of the gateway.')) - return parser - - def retrieve_ids(self, client, args): - gateway_id = neutronV20.find_resourceid_by_name_or_id( - client, self.resource, args.net_gateway_id) - network_id = neutronV20.find_resourceid_by_name_or_id( - client, 'network', args.network_id) - return (gateway_id, network_id) - - -class ConnectNetworkGateway(NetworkGatewayInterfaceCommand): - """Add an internal network interface to a router.""" - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - (gateway_id, network_id) = self.retrieve_ids(neutron_client, - parsed_args) - neutron_client.connect_network_gateway( - gateway_id, {'network_id': network_id, - 'segmentation_type': parsed_args.segmentation_type, - 'segmentation_id': parsed_args.segmentation_id}) - # TODO(Salvatore-Orlando): Do output formatting as - # any other command - print(_('Connected network to gateway %s') % gateway_id, - file=self.app.stdout) - - -class DisconnectNetworkGateway(NetworkGatewayInterfaceCommand): - """Remove a network from a network gateway.""" - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - (gateway_id, network_id) = self.retrieve_ids(neutron_client, - parsed_args) - neutron_client.disconnect_network_gateway( - gateway_id, {'network_id': network_id, - 'segmentation_type': parsed_args.segmentation_type, - 'segmentation_id': parsed_args.segmentation_id}) - # TODO(Salvatore-Orlando): Do output formatting as - # any other command - print(_('Disconnected network from gateway %s') % gateway_id, - file=self.app.stdout) diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/qos_queue.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/qos_queue.py deleted file mode 100644 index 7f6cb68b2e..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/nsx/qos_queue.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2013 VMware Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListQoSQueue(neutronV20.ListCommand): - """List queues that belong to a given tenant.""" - - resource = 'qos_queue' - list_columns = ['id', 'name', 'min', 'max', - 'qos_marking', 'dscp', 'default'] - - -class ShowQoSQueue(neutronV20.ShowCommand): - """Show information of a given queue.""" - - resource = 'qos_queue' - allow_names = True - - -class CreateQoSQueue(neutronV20.CreateCommand): - """Create a queue.""" - - resource = 'qos_queue' - - def add_known_arguments(self, parser): - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of queue.')) - parser.add_argument( - '--min', - help=_('Minimum rate.')), - parser.add_argument( - '--max', - help=_('Maximum rate.')), - parser.add_argument( - '--qos-marking', - help=_('QOS marking as untrusted or trusted.')), - parser.add_argument( - '--default', - default=False, - help=_('If true all created ports will be the size of this queue, ' - 'if queue is not specified')), - parser.add_argument( - '--dscp', - help=_('Differentiated Services Code Point.')), - - def args2body(self, parsed_args): - params = {'name': parsed_args.name, - 'default': parsed_args.default} - if parsed_args.min: - params['min'] = parsed_args.min - if parsed_args.max: - params['max'] = parsed_args.max - if parsed_args.qos_marking: - params['qos_marking'] = parsed_args.qos_marking - if parsed_args.dscp: - params['dscp'] = parsed_args.dscp - if parsed_args.tenant_id: - params['tenant_id'] = parsed_args.tenant_id - return {'qos_queue': params} - - -class DeleteQoSQueue(neutronV20.DeleteCommand): - """Delete a given queue.""" - - resource = 'qos_queue' - allow_names = True diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/policyprofile.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/policyprofile.py deleted file mode 100644 index 03fd8af10c..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/policyprofile.py +++ /dev/null @@ -1,74 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -#@author Abhishek Raut, Cisco Systems -#@author Sergey Sudakovich, Cisco Systems - -from __future__ import print_function - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 -from neutronclient.neutron.v2_0 import parse_args_to_dict - -RESOURCE = 'policy_profile' - - -class ListPolicyProfile(neutronV20.ListCommand): - """List policy profiles that belong to a given tenant.""" - - resource = RESOURCE - _formatters = {} - list_columns = ['id', 'name'] - - -class ShowPolicyProfile(neutronV20.ShowCommand): - """Show information of a given policy profile.""" - - resource = RESOURCE - allow_names = True - - -class UpdatePolicyProfile(neutronV20.UpdateCommand): - """Update policy profile's information.""" - - resource = RESOURCE - - -class UpdatePolicyProfileV2(neutronV20.UpdateCommand): - """Update policy profile's information.""" - - api = 'network' - resource = RESOURCE - - def get_parser(self, prog_name): - parser = super(UpdatePolicyProfileV2, self).get_parser(prog_name) - parser.add_argument("--add-tenant", - help=_("Add tenant to the policy profile.")) - parser.add_argument("--remove-tenant", - help=_("Remove tenant from the policy profile.")) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - data = {self.resource: parse_args_to_dict(parsed_args)} - if parsed_args.add_tenant: - data[self.resource]['add_tenant'] = parsed_args.add_tenant - if parsed_args.remove_tenant: - data[self.resource]['remove_tenant'] = parsed_args.remove_tenant - neutron_client.update_policy_profile(parsed_args.id, - {self.resource: data}) - print((_('Updated %(resource)s: %(id)s') % - {'id': parsed_args.id, 'resource': self.resource}), - file=self.app.stdout) - return diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/port.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/port.py deleted file mode 100644 index 79ac1bfcd2..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/port.py +++ /dev/null @@ -1,276 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import argparse - -from oslo.serialization import jsonutils - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _format_fixed_ips(port): - try: - return '\n'.join([jsonutils.dumps(ip) for ip in port['fixed_ips']]) - except (TypeError, KeyError): - return '' - - -def _format_fixed_ips_csv(port): - try: - return jsonutils.dumps(port['fixed_ips']) - except (TypeError, KeyError): - return '' - - -def _add_updatable_args(parser): - parser.add_argument( - '--name', - help=_('Name of this port.')) - parser.add_argument( - '--fixed-ip', metavar='subnet_id=SUBNET,ip_address=IP_ADDR', - action='append', - help=_('Desired IP and/or subnet for this port: ' - 'subnet_id=,ip_address=. ' - 'You can repeat this option.')) - parser.add_argument( - '--fixed_ip', - action='append', - help=argparse.SUPPRESS) - parser.add_argument( - '--device-id', - help=_('Device ID of this port.')) - parser.add_argument( - '--device_id', - help=argparse.SUPPRESS) - parser.add_argument( - '--device-owner', - help=_('Device owner of this port.')) - parser.add_argument( - '--device_owner', - help=argparse.SUPPRESS) - - -def _updatable_args2body(parsed_args, body, client): - if parsed_args.device_id: - body['port'].update({'device_id': parsed_args.device_id}) - if parsed_args.device_owner: - body['port'].update({'device_owner': parsed_args.device_owner}) - if parsed_args.name: - body['port'].update({'name': parsed_args.name}) - ips = [] - if parsed_args.fixed_ip: - for ip_spec in parsed_args.fixed_ip: - ip_dict = utils.str2dict(ip_spec) - if 'subnet_id' in ip_dict: - subnet_name_id = ip_dict['subnet_id'] - _subnet_id = neutronV20.find_resourceid_by_name_or_id( - client, 'subnet', subnet_name_id) - ip_dict['subnet_id'] = _subnet_id - ips.append(ip_dict) - if ips: - body['port'].update({'fixed_ips': ips}) - - -class ListPort(neutronV20.ListCommand): - """List ports that belong to a given tenant.""" - - resource = 'port' - _formatters = {'fixed_ips': _format_fixed_ips, } - _formatters_csv = {'fixed_ips': _format_fixed_ips_csv, } - list_columns = ['id', 'name', 'mac_address', 'fixed_ips'] - pagination_support = True - sorting_support = True - - -class ListRouterPort(neutronV20.ListCommand): - """List ports that belong to a given tenant, with specified router.""" - - resource = 'port' - _formatters = {'fixed_ips': _format_fixed_ips, } - list_columns = ['id', 'name', 'mac_address', 'fixed_ips'] - pagination_support = True - sorting_support = True - - def get_parser(self, prog_name): - parser = super(ListRouterPort, self).get_parser(prog_name) - parser.add_argument( - 'id', metavar='router', - help=_('ID or name of router to look up.')) - return parser - - def get_data(self, parsed_args): - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'router', parsed_args.id) - self.values_specs.append('--device_id=%s' % _id) - return super(ListRouterPort, self).get_data(parsed_args) - - -class ShowPort(neutronV20.ShowCommand): - """Show information of a given port.""" - - resource = 'port' - - -class UpdatePortSecGroupMixin(object): - def add_arguments_secgroup(self, parser): - group_sg = parser.add_mutually_exclusive_group() - group_sg.add_argument( - '--security-group', metavar='SECURITY_GROUP', - default=[], action='append', dest='security_groups', - help=_('Security group associated with the port. You can ' - 'repeat this option.')) - group_sg.add_argument( - '--no-security-groups', - action='store_true', - help=_('Associate no security groups with the port.')) - - def _resolv_sgid(self, secgroup): - return neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'security_group', secgroup) - - def args2body_secgroup(self, parsed_args, port): - if parsed_args.security_groups: - port['security_groups'] = [self._resolv_sgid(sg) for sg - in parsed_args.security_groups] - elif parsed_args.no_security_groups: - port['security_groups'] = [] - - -class UpdateExtraDhcpOptMixin(object): - def add_arguments_extradhcpopt(self, parser): - group_sg = parser.add_mutually_exclusive_group() - group_sg.add_argument( - '--extra-dhcp-opt', - default=[], - action='append', - dest='extra_dhcp_opts', - help=_('Extra dhcp options to be assigned to this port: ' - 'opt_name=,opt_value=,' - 'ip_version={4,6}. You can repeat this option.')) - - def args2body_extradhcpopt(self, parsed_args, port): - ops = [] - if parsed_args.extra_dhcp_opts: - # the extra_dhcp_opt params (opt_name & opt_value) - # must come in pairs, if there is a parm error - # both must be thrown out. - opt_ele = {} - edo_err_msg = _("Invalid --extra-dhcp-opt option, can only be: " - "opt_name=,opt_value=," - "ip_version={4,6}. " - "You can repeat this option.") - for opt in parsed_args.extra_dhcp_opts: - opt_ele.update(utils.str2dict(opt)) - if ('opt_name' in opt_ele and - ('opt_value' in opt_ele or 'ip_version' in opt_ele)): - if opt_ele.get('opt_value') == 'null': - opt_ele['opt_value'] = None - ops.append(opt_ele) - opt_ele = {} - else: - raise exceptions.CommandError(edo_err_msg) - - if ops: - port.update({'extra_dhcp_opts': ops}) - - -class CreatePort(neutronV20.CreateCommand, UpdatePortSecGroupMixin, - UpdateExtraDhcpOptMixin): - """Create a port for a given tenant.""" - - resource = 'port' - - def add_known_arguments(self, parser): - _add_updatable_args(parser) - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--admin_state_down', - dest='admin_state', action='store_false', - help=argparse.SUPPRESS) - parser.add_argument( - '--mac-address', - help=_('MAC address of this port.')) - parser.add_argument( - '--mac_address', - help=argparse.SUPPRESS) - self.add_arguments_secgroup(parser) - self.add_arguments_extradhcpopt(parser) - - parser.add_argument( - 'network_id', metavar='NETWORK', - help=_('Network ID or name this port belongs to.')) - - def args2body(self, parsed_args): - client = self.get_client() - _network_id = neutronV20.find_resourceid_by_name_or_id( - client, 'network', parsed_args.network_id) - body = {'port': {'admin_state_up': parsed_args.admin_state, - 'network_id': _network_id, }, } - _updatable_args2body(parsed_args, body, client) - if parsed_args.mac_address: - body['port'].update({'mac_address': parsed_args.mac_address}) - if parsed_args.tenant_id: - body['port'].update({'tenant_id': parsed_args.tenant_id}) - - self.args2body_secgroup(parsed_args, body['port']) - self.args2body_extradhcpopt(parsed_args, body['port']) - - return body - - -class DeletePort(neutronV20.DeleteCommand): - """Delete a given port.""" - - resource = 'port' - - -class UpdatePort(neutronV20.UpdateCommand, UpdatePortSecGroupMixin, - UpdateExtraDhcpOptMixin): - """Update port's information.""" - - resource = 'port' - - def add_known_arguments(self, parser): - _add_updatable_args(parser) - parser.add_argument( - '--admin-state-up', - choices=['True', 'False'], - help=_('Set admin state up for the port.')) - parser.add_argument( - '--admin_state_up', - choices=['True', 'False'], - help=argparse.SUPPRESS) - self.add_arguments_secgroup(parser) - self.add_arguments_extradhcpopt(parser) - - def args2body(self, parsed_args): - body = {'port': {}} - client = self.get_client() - _updatable_args2body(parsed_args, body, client) - if parsed_args.admin_state_up: - body['port'].update({'admin_state_up': - parsed_args.admin_state_up}) - self.args2body_secgroup(parsed_args, body['port']) - self.args2body_extradhcpopt(parsed_args, body['port']) - return body diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/quota.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/quota.py deleted file mode 100644 index 780f510b1c..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/quota.py +++ /dev/null @@ -1,245 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from __future__ import print_function - -import argparse - -from cliff import lister -from cliff import show -from oslo.serialization import jsonutils -import six - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def get_tenant_id(tenant_id, client): - return (tenant_id if tenant_id else - client.get_quotas_tenant()['tenant']['tenant_id']) - - -class DeleteQuota(neutronV20.NeutronCommand): - """Delete defined quotas of a given tenant.""" - - api = 'network' - resource = 'quota' - - def get_parser(self, prog_name): - parser = super(DeleteQuota, self).get_parser(prog_name) - parser.add_argument( - '--tenant-id', metavar='tenant-id', - help=_('The owner tenant ID.')) - parser.add_argument( - '--tenant_id', - help=argparse.SUPPRESS) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - tenant_id = get_tenant_id(parsed_args.tenant_id, - neutron_client) - obj_deleter = getattr(neutron_client, - "delete_%s" % self.resource) - obj_deleter(tenant_id) - print((_('Deleted %(resource)s: %(tenant_id)s') - % {'tenant_id': tenant_id, - 'resource': self.resource}), - file=self.app.stdout) - return - - -class ListQuota(neutronV20.NeutronCommand, lister.Lister): - """List quotas of all tenants who have non-default quota values.""" - - api = 'network' - resource = 'quota' - - def get_parser(self, prog_name): - parser = super(ListQuota, self).get_parser(prog_name) - return parser - - def get_data(self, parsed_args): - self.log.debug('get_data(%s)', parsed_args) - neutron_client = self.get_client() - search_opts = {} - self.log.debug('search options: %s', search_opts) - neutron_client.format = parsed_args.request_format - obj_lister = getattr(neutron_client, - "list_%ss" % self.resource) - data = obj_lister(**search_opts) - info = [] - collection = self.resource + "s" - if collection in data: - info = data[collection] - _columns = len(info) > 0 and sorted(info[0].keys()) or [] - return (_columns, (utils.get_item_properties(s, _columns) - for s in info)) - - -class ShowQuota(neutronV20.NeutronCommand, show.ShowOne): - """Show quotas of a given tenant. - - """ - api = 'network' - resource = "quota" - - def get_parser(self, prog_name): - parser = super(ShowQuota, self).get_parser(prog_name) - parser.add_argument( - '--tenant-id', metavar='tenant-id', - help=_('The owner tenant ID.')) - parser.add_argument( - '--tenant_id', - help=argparse.SUPPRESS) - return parser - - def get_data(self, parsed_args): - self.log.debug('get_data(%s)', parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - tenant_id = get_tenant_id(parsed_args.tenant_id, - neutron_client) - params = {} - obj_shower = getattr(neutron_client, - "show_%s" % self.resource) - data = obj_shower(tenant_id, **params) - if self.resource in data: - for k, v in six.iteritems(data[self.resource]): - if isinstance(v, list): - value = "" - for _item in v: - if value: - value += "\n" - if isinstance(_item, dict): - value += jsonutils.dumps(_item) - else: - value += str(_item) - data[self.resource][k] = value - elif v is None: - data[self.resource][k] = '' - return zip(*sorted(six.iteritems(data[self.resource]))) - else: - return None - - -class UpdateQuota(neutronV20.NeutronCommand, show.ShowOne): - """Define tenant's quotas not to use defaults.""" - - resource = 'quota' - - def get_parser(self, prog_name): - parser = super(UpdateQuota, self).get_parser(prog_name) - parser.add_argument( - '--tenant-id', metavar='tenant-id', - help=_('The owner tenant ID.')) - parser.add_argument( - '--tenant_id', - help=argparse.SUPPRESS) - parser.add_argument( - '--network', metavar='networks', - help=_('The limit of networks.')) - parser.add_argument( - '--subnet', metavar='subnets', - help=_('The limit of subnets.')) - parser.add_argument( - '--port', metavar='ports', - help=_('The limit of ports.')) - parser.add_argument( - '--router', metavar='routers', - help=_('The limit of routers.')) - parser.add_argument( - '--floatingip', metavar='floatingips', - help=_('The limit of floating IPs.')) - parser.add_argument( - '--security-group', metavar='security_groups', - help=_('The limit of security groups.')) - parser.add_argument( - '--security-group-rule', metavar='security_group_rules', - help=_('The limit of security groups rules.')) - parser.add_argument( - '--vip', metavar='vips', - help=_('The limit of vips.')) - parser.add_argument( - '--pool', metavar='pools', - help=_('The limit of pools.')) - parser.add_argument( - '--member', metavar='members', - help=_('The limit of pool members.')) - parser.add_argument( - '--health-monitor', metavar='health_monitors', - help=_('The limit of health monitors.')) - - return parser - - def _validate_int(self, name, value): - try: - return_value = int(value) - except Exception: - message = (_('Quota limit for %(name)s must be an integer') % - {'name': name}) - raise exceptions.NeutronClientException(message=message) - return return_value - - def args2body(self, parsed_args): - quota = {} - for resource in ('network', 'subnet', 'port', 'router', 'floatingip', - 'security_group', 'security_group_rule', - 'vip', 'pool', 'member', 'health_monitor'): - if getattr(parsed_args, resource): - quota[resource] = self._validate_int( - resource, - getattr(parsed_args, resource)) - return {self.resource: quota} - - def get_data(self, parsed_args): - self.log.debug('run(%s)', parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _extra_values = neutronV20.parse_args_to_dict(self.values_specs) - neutronV20._merge_args(self, parsed_args, _extra_values, - self.values_specs) - body = self.args2body(parsed_args) - if self.resource in body: - body[self.resource].update(_extra_values) - else: - body[self.resource] = _extra_values - obj_updator = getattr(neutron_client, - "update_%s" % self.resource) - tenant_id = get_tenant_id(parsed_args.tenant_id, - neutron_client) - data = obj_updator(tenant_id, body) - if self.resource in data: - for k, v in six.iteritems(data[self.resource]): - if isinstance(v, list): - value = "" - for _item in v: - if value: - value += "\n" - if isinstance(_item, dict): - value += jsonutils.dumps(_item) - else: - value += str(_item) - data[self.resource][k] = value - elif v is None: - data[self.resource][k] = '' - return zip(*sorted(six.iteritems(data[self.resource]))) - else: - return None diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/router.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/router.py deleted file mode 100644 index 6112596036..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/router.py +++ /dev/null @@ -1,226 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from __future__ import print_function - -import argparse - -from oslo.serialization import jsonutils - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _format_external_gateway_info(router): - try: - return jsonutils.dumps(router['external_gateway_info']) - except (TypeError, KeyError): - return '' - - -class ListRouter(neutronV20.ListCommand): - """List routers that belong to a given tenant.""" - - resource = 'router' - _formatters = {'external_gateway_info': _format_external_gateway_info, } - list_columns = ['id', 'name', 'external_gateway_info', 'distributed', 'ha'] - pagination_support = True - sorting_support = True - - -class ShowRouter(neutronV20.ShowCommand): - """Show information of a given router.""" - - resource = 'router' - - -class CreateRouter(neutronV20.CreateCommand): - """Create a router for a given tenant.""" - - resource = 'router' - _formatters = {'external_gateway_info': _format_external_gateway_info, } - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--admin_state_down', - dest='admin_state', action='store_false', - help=argparse.SUPPRESS) - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of router to create.')) - utils.add_boolean_argument( - parser, '--distributed', dest='distributed', - help=_('Create a distributed router.')) - utils.add_boolean_argument( - parser, '--ha', dest='ha', - help=_('Create a highly available router.')) - - def args2body(self, parsed_args): - body = {self.resource: {'admin_state_up': parsed_args.admin_state}} - neutronV20.update_dict(parsed_args, body[self.resource], - ['name', 'tenant_id', 'distributed', 'ha']) - return body - - -class DeleteRouter(neutronV20.DeleteCommand): - """Delete a given router.""" - - resource = 'router' - - -class UpdateRouter(neutronV20.UpdateCommand): - """Update router's information.""" - - resource = 'router' - - -class RouterInterfaceCommand(neutronV20.NeutronCommand): - """Based class to Add/Remove router interface.""" - - api = 'network' - resource = 'router' - - def call_api(self, neutron_client, router_id, body): - raise NotImplementedError() - - def success_message(self, router_id, portinfo): - raise NotImplementedError() - - def get_parser(self, prog_name): - parser = super(RouterInterfaceCommand, self).get_parser(prog_name) - parser.add_argument( - 'router', metavar='ROUTER', - help=_('ID or name of the router.')) - parser.add_argument( - 'interface', metavar='INTERFACE', - help=_('The format is "SUBNET|subnet=SUBNET|port=PORT". ' - 'Either a subnet or port must be specified. ' - 'Both ID and name are accepted as SUBNET or PORT. ' - 'Note that "subnet=" can be omitted when specifying a ' - 'subnet.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - - if '=' in parsed_args.interface: - resource, value = parsed_args.interface.split('=', 1) - if resource not in ['subnet', 'port']: - exceptions.CommandError(_('You must specify either subnet or ' - 'port for INTERFACE parameter.')) - else: - resource = 'subnet' - value = parsed_args.interface - - _router_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, self.resource, parsed_args.router) - - _interface_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, resource, value) - body = {'%s_id' % resource: _interface_id} - - portinfo = self.call_api(neutron_client, _router_id, body) - print(self.success_message(parsed_args.router, portinfo), - file=self.app.stdout) - - -class AddInterfaceRouter(RouterInterfaceCommand): - """Add an internal network interface to a router.""" - - def call_api(self, neutron_client, router_id, body): - return neutron_client.add_interface_router(router_id, body) - - def success_message(self, router_id, portinfo): - return (_('Added interface %(port)s to router %(router)s.') % - {'router': router_id, 'port': portinfo['port_id']}) - - -class RemoveInterfaceRouter(RouterInterfaceCommand): - """Remove an internal network interface from a router.""" - - def call_api(self, neutron_client, router_id, body): - return neutron_client.remove_interface_router(router_id, body) - - def success_message(self, router_id, portinfo): - # portinfo is not used since it is None for router-interface-delete. - return _('Removed interface from router %s.') % router_id - - -class SetGatewayRouter(neutronV20.NeutronCommand): - """Set the external network gateway for a router.""" - - api = 'network' - resource = 'router' - - def get_parser(self, prog_name): - parser = super(SetGatewayRouter, self).get_parser(prog_name) - parser.add_argument( - 'router', metavar='ROUTER', - help=_('ID or name of the router.')) - parser.add_argument( - 'external_network', metavar='EXTERNAL-NETWORK', - help=_('ID or name of the external network for the gateway.')) - parser.add_argument( - '--disable-snat', action='store_true', - help=_('Disable source NAT on the router gateway.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _router_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, self.resource, parsed_args.router) - _ext_net_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, 'network', parsed_args.external_network) - router_dict = {'network_id': _ext_net_id} - if parsed_args.disable_snat: - router_dict['enable_snat'] = False - neutron_client.add_gateway_router(_router_id, router_dict) - print(_('Set gateway for router %s') % parsed_args.router, - file=self.app.stdout) - - -class RemoveGatewayRouter(neutronV20.NeutronCommand): - """Remove an external network gateway from a router.""" - - api = 'network' - resource = 'router' - - def get_parser(self, prog_name): - parser = super(RemoveGatewayRouter, self).get_parser(prog_name) - parser.add_argument( - 'router', metavar='ROUTER', - help=_('ID or name of the router.')) - return parser - - def run(self, parsed_args): - self.log.debug('run(%s)' % parsed_args) - neutron_client = self.get_client() - neutron_client.format = parsed_args.request_format - _router_id = neutronV20.find_resourceid_by_name_or_id( - neutron_client, self.resource, parsed_args.router) - neutron_client.remove_gateway_router(_router_id) - print(_('Removed gateway from router %s') % parsed_args.router, - file=self.app.stdout) diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/securitygroup.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/securitygroup.py deleted file mode 100644 index 6bfd80d65f..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/securitygroup.py +++ /dev/null @@ -1,274 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import argparse - -from neutronclient.common import exceptions -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListSecurityGroup(neutronV20.ListCommand): - """List security groups that belong to a given tenant.""" - - resource = 'security_group' - list_columns = ['id', 'name', 'description'] - pagination_support = True - sorting_support = True - - -class ShowSecurityGroup(neutronV20.ShowCommand): - """Show information of a given security group.""" - - resource = 'security_group' - allow_names = True - - -class CreateSecurityGroup(neutronV20.CreateCommand): - """Create a security group.""" - - resource = 'security_group' - - def add_known_arguments(self, parser): - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of security group.')) - parser.add_argument( - '--description', - help=_('Description of security group.')) - - def args2body(self, parsed_args): - body = {'security_group': { - 'name': parsed_args.name}} - if parsed_args.description: - body['security_group'].update( - {'description': parsed_args.description}) - if parsed_args.tenant_id: - body['security_group'].update({'tenant_id': parsed_args.tenant_id}) - return body - - -class DeleteSecurityGroup(neutronV20.DeleteCommand): - """Delete a given security group.""" - - resource = 'security_group' - allow_names = True - - -class UpdateSecurityGroup(neutronV20.UpdateCommand): - """Update a given security group.""" - - resource = 'security_group' - - def add_known_arguments(self, parser): - parser.add_argument( - '--name', - help=_('Name of security group.')) - parser.add_argument( - '--description', - help=_('Description of security group.')) - - def args2body(self, parsed_args): - body = {'security_group': {}} - if parsed_args.name: - body['security_group'].update( - {'name': parsed_args.name}) - if parsed_args.description: - body['security_group'].update( - {'description': parsed_args.description}) - return body - - -class ListSecurityGroupRule(neutronV20.ListCommand): - """List security group rules that belong to a given tenant.""" - - resource = 'security_group_rule' - list_columns = ['id', 'security_group_id', 'direction', 'protocol', - 'remote_ip_prefix', 'remote_group_id'] - replace_rules = {'security_group_id': 'security_group', - 'remote_group_id': 'remote_group'} - pagination_support = True - sorting_support = True - - def get_parser(self, prog_name): - parser = super(ListSecurityGroupRule, self).get_parser(prog_name) - parser.add_argument( - '--no-nameconv', action='store_true', - help=_('Do not convert security group ID to its name.')) - return parser - - @staticmethod - def replace_columns(cols, rules, reverse=False): - if reverse: - rules = dict((rules[k], k) for k in rules.keys()) - return [rules.get(col, col) for col in cols] - - def retrieve_list(self, parsed_args): - parsed_args.fields = self.replace_columns(parsed_args.fields, - self.replace_rules, - reverse=True) - return super(ListSecurityGroupRule, self).retrieve_list(parsed_args) - - def extend_list(self, data, parsed_args): - if parsed_args.no_nameconv: - return - neutron_client = self.get_client() - search_opts = {'fields': ['id', 'name']} - if self.pagination_support: - page_size = parsed_args.page_size - if page_size: - search_opts.update({'limit': page_size}) - sec_group_ids = set() - for rule in data: - for key in self.replace_rules: - if rule.get(key): - sec_group_ids.add(rule[key]) - sec_group_ids = list(sec_group_ids) - - def _get_sec_group_list(sec_group_ids): - search_opts['id'] = sec_group_ids - return neutron_client.list_security_groups( - **search_opts).get('security_groups', []) - - try: - secgroups = _get_sec_group_list(sec_group_ids) - except exceptions.RequestURITooLong as uri_len_exc: - # Length of a query filter on security group rule id - # id=& (with len(uuid)=36) - sec_group_id_filter_len = 40 - # The URI is too long because of too many sec_group_id filters - # Use the excess attribute of the exception to know how many - # sec_group_id filters can be inserted into a single request - sec_group_count = len(sec_group_ids) - max_size = ((sec_group_id_filter_len * sec_group_count) - - uri_len_exc.excess) - chunk_size = max_size // sec_group_id_filter_len - secgroups = [] - for i in range(0, sec_group_count, chunk_size): - secgroups.extend( - _get_sec_group_list(sec_group_ids[i: i + chunk_size])) - - sg_dict = dict([(sg['id'], sg['name']) - for sg in secgroups if sg['name']]) - for rule in data: - for key in self.replace_rules: - if key in rule: - rule[key] = sg_dict.get(rule[key], rule[key]) - - def setup_columns(self, info, parsed_args): - parsed_args.columns = self.replace_columns(parsed_args.columns, - self.replace_rules, - reverse=True) - # NOTE(amotoki): 2nd element of the tuple returned by setup_columns() - # is a generator, so if you need to create a look using the generator - # object, you need to recreate a generator to show a list expectedly. - info = super(ListSecurityGroupRule, self).setup_columns(info, - parsed_args) - cols = info[0] - if not parsed_args.no_nameconv: - cols = self.replace_columns(info[0], self.replace_rules) - parsed_args.columns = cols - return (cols, info[1]) - - -class ShowSecurityGroupRule(neutronV20.ShowCommand): - """Show information of a given security group rule.""" - - resource = 'security_group_rule' - allow_names = False - - -class CreateSecurityGroupRule(neutronV20.CreateCommand): - """Create a security group rule.""" - - resource = 'security_group_rule' - - def add_known_arguments(self, parser): - parser.add_argument( - 'security_group_id', metavar='SECURITY_GROUP', - help=_('Security group name or ID to add rule.')) - parser.add_argument( - '--direction', - default='ingress', choices=['ingress', 'egress'], - help=_('Direction of traffic: ingress/egress.')) - parser.add_argument( - '--ethertype', - default='IPv4', - help=_('IPv4/IPv6')) - parser.add_argument( - '--protocol', - help=_('Protocol of packet.')) - parser.add_argument( - '--port-range-min', - help=_('Starting port range.')) - parser.add_argument( - '--port_range_min', - help=argparse.SUPPRESS) - parser.add_argument( - '--port-range-max', - help=_('Ending port range.')) - parser.add_argument( - '--port_range_max', - help=argparse.SUPPRESS) - parser.add_argument( - '--remote-ip-prefix', - help=_('CIDR to match on.')) - parser.add_argument( - '--remote_ip_prefix', - help=argparse.SUPPRESS) - parser.add_argument( - '--remote-group-id', metavar='REMOTE_GROUP', - help=_('Remote security group name or ID to apply rule.')) - parser.add_argument( - '--remote_group_id', - help=argparse.SUPPRESS) - - def args2body(self, parsed_args): - _security_group_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'security_group', parsed_args.security_group_id) - body = {'security_group_rule': { - 'security_group_id': _security_group_id, - 'direction': parsed_args.direction, - 'ethertype': parsed_args.ethertype}} - if parsed_args.protocol: - body['security_group_rule'].update( - {'protocol': parsed_args.protocol}) - if parsed_args.port_range_min: - body['security_group_rule'].update( - {'port_range_min': parsed_args.port_range_min}) - if parsed_args.port_range_max: - body['security_group_rule'].update( - {'port_range_max': parsed_args.port_range_max}) - if parsed_args.remote_ip_prefix: - body['security_group_rule'].update( - {'remote_ip_prefix': parsed_args.remote_ip_prefix}) - if parsed_args.remote_group_id: - _remote_group_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'security_group', - parsed_args.remote_group_id) - body['security_group_rule'].update( - {'remote_group_id': _remote_group_id}) - if parsed_args.tenant_id: - body['security_group_rule'].update( - {'tenant_id': parsed_args.tenant_id}) - return body - - -class DeleteSecurityGroupRule(neutronV20.DeleteCommand): - """Delete a given security group rule.""" - - resource = 'security_group_rule' - allow_names = False diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/servicetype.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/servicetype.py deleted file mode 100644 index ec8454f948..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/servicetype.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2013 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -from neutronclient.neutron import v2_0 as neutronV20 - - -class ListServiceProvider(neutronV20.ListCommand): - """List service providers.""" - - resource = 'service_provider' - list_columns = ['service_type', 'name', 'default'] - _formatters = {} - pagination_support = True - sorting_support = True diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/subnet.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/subnet.py deleted file mode 100644 index 86c9f182da..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/subnet.py +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import argparse - -from oslo.serialization import jsonutils - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronV20 - - -def _format_allocation_pools(subnet): - try: - return '\n'.join([jsonutils.dumps(pool) for pool in - subnet['allocation_pools']]) - except (TypeError, KeyError): - return '' - - -def _format_dns_nameservers(subnet): - try: - return '\n'.join([jsonutils.dumps(server) for server in - subnet['dns_nameservers']]) - except (TypeError, KeyError): - return '' - - -def _format_host_routes(subnet): - try: - return '\n'.join([jsonutils.dumps(route) for route in - subnet['host_routes']]) - except (TypeError, KeyError): - return '' - - -def add_updatable_arguments(parser): - parser.add_argument( - '--name', - help=_('Name of this subnet.')) - parser.add_argument( - '--gateway', metavar='GATEWAY_IP', - help=_('Gateway IP of this subnet.')) - parser.add_argument( - '--no-gateway', - action='store_true', - help=_('No distribution of gateway.')) - parser.add_argument( - '--allocation-pool', metavar='start=IP_ADDR,end=IP_ADDR', - action='append', dest='allocation_pools', type=utils.str2dict, - help=_('Allocation pool IP addresses for this subnet ' - '(This option can be repeated).')) - parser.add_argument( - '--allocation_pool', - action='append', dest='allocation_pools', type=utils.str2dict, - help=argparse.SUPPRESS) - parser.add_argument( - '--host-route', metavar='destination=CIDR,nexthop=IP_ADDR', - action='append', dest='host_routes', type=utils.str2dict, - help=_('Additional route (This option can be repeated).')) - parser.add_argument( - '--dns-nameserver', metavar='DNS_NAMESERVER', - action='append', dest='dns_nameservers', - help=_('DNS name server for this subnet ' - '(This option can be repeated).')) - parser.add_argument( - '--disable-dhcp', - action='store_true', - help=_('Disable DHCP for this subnet.')) - parser.add_argument( - '--enable-dhcp', - action='store_true', - help=_('Enable DHCP for this subnet.')) - # NOTE(ihrachys): yes, that's awful, but should be left as-is for - # backwards compatibility for versions <=2.3.4 that passed the - # boolean values through to the server without any argument - # validation. - parser.add_argument( - '--enable-dhcp=True', - action='store_true', - dest='enable_dhcp', - help=argparse.SUPPRESS) - parser.add_argument( - '--enable-dhcp=False', - action='store_true', - dest='disable_dhcp', - help=argparse.SUPPRESS) - - -def updatable_args2body(parsed_args, body, for_create=True): - if parsed_args.gateway and parsed_args.no_gateway: - raise exceptions.CommandError(_("--gateway option and " - "--no-gateway option can " - "not be used same time")) - if parsed_args.disable_dhcp and parsed_args.enable_dhcp: - raise exceptions.CommandError(_( - "You cannot enable and disable DHCP at the same time.")) - - if parsed_args.no_gateway: - body['subnet'].update({'gateway_ip': None}) - if parsed_args.gateway: - body['subnet'].update({'gateway_ip': parsed_args.gateway}) - if parsed_args.name: - body['subnet'].update({'name': parsed_args.name}) - if parsed_args.disable_dhcp: - body['subnet'].update({'enable_dhcp': False}) - if parsed_args.enable_dhcp: - body['subnet'].update({'enable_dhcp': True}) - if parsed_args.allocation_pools: - body['subnet']['allocation_pools'] = parsed_args.allocation_pools - if parsed_args.host_routes: - body['subnet']['host_routes'] = parsed_args.host_routes - if parsed_args.dns_nameservers: - body['subnet']['dns_nameservers'] = parsed_args.dns_nameservers - if for_create and parsed_args.ipv6_ra_mode: - if parsed_args.ip_version == 4: - raise exceptions.CommandError(_("--ipv6-ra-mode is invalid " - "when --ip-version is 4")) - body['subnet']['ipv6_ra_mode'] = parsed_args.ipv6_ra_mode - if for_create and parsed_args.ipv6_address_mode: - if parsed_args.ip_version == 4: - raise exceptions.CommandError(_("--ipv6-address-mode is " - "invalid when --ip-version " - "is 4")) - body['subnet']['ipv6_address_mode'] = parsed_args.ipv6_address_mode - - -class ListSubnet(neutronV20.ListCommand): - """List subnets that belong to a given tenant.""" - - resource = 'subnet' - _formatters = {'allocation_pools': _format_allocation_pools, - 'dns_nameservers': _format_dns_nameservers, - 'host_routes': _format_host_routes, } - list_columns = ['id', 'name', 'cidr', 'allocation_pools'] - pagination_support = True - sorting_support = True - - -class ShowSubnet(neutronV20.ShowCommand): - """Show information of a given subnet.""" - - resource = 'subnet' - - -class CreateSubnet(neutronV20.CreateCommand): - """Create a subnet for a given tenant.""" - - resource = 'subnet' - - def add_known_arguments(self, parser): - add_updatable_arguments(parser) - parser.add_argument( - '--ip-version', - type=int, - default=4, choices=[4, 6], - help=_('IP version to use, default is 4.')) - parser.add_argument( - '--ip_version', - type=int, - choices=[4, 6], - help=argparse.SUPPRESS) - parser.add_argument( - 'network_id', metavar='NETWORK', - help=_('Network ID or name this subnet belongs to.')) - parser.add_argument( - 'cidr', metavar='CIDR', - help=_('CIDR of subnet to create.')) - parser.add_argument( - '--ipv6-ra-mode', - choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'], - help=_('IPv6 RA (Router Advertisement) mode.')) - parser.add_argument( - '--ipv6-address-mode', - choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'], - help=_('IPv6 address mode.')) - - def args2body(self, parsed_args): - if parsed_args.ip_version == 4 and parsed_args.cidr.endswith('/32'): - self.log.warning(_("An IPv4 subnet with a /32 CIDR will have " - "only one usable IP address so the device " - "attached to it will not have any IP " - "connectivity.")) - _network_id = neutronV20.find_resourceid_by_name_or_id( - self.get_client(), 'network', parsed_args.network_id) - body = {'subnet': {'cidr': parsed_args.cidr, - 'network_id': _network_id, - 'ip_version': parsed_args.ip_version, }, } - - updatable_args2body(parsed_args, body) - if parsed_args.tenant_id: - body['subnet'].update({'tenant_id': parsed_args.tenant_id}) - - return body - - -class DeleteSubnet(neutronV20.DeleteCommand): - """Delete a given subnet.""" - - resource = 'subnet' - - -class UpdateSubnet(neutronV20.UpdateCommand): - """Update subnet's information.""" - - resource = 'subnet' - - def add_known_arguments(self, parser): - add_updatable_arguments(parser) - - def args2body(self, parsed_args): - body = {'subnet': {}} - updatable_args2body(parsed_args, body, for_create=False) - return body diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/__init__.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ikepolicy.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ikepolicy.py deleted file mode 100644 index e2f5d28612..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ikepolicy.py +++ /dev/null @@ -1,127 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett-Packard. -# - -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 -from neutronclient.neutron.v2_0.vpn import utils as vpn_utils - - -class ListIKEPolicy(neutronv20.ListCommand): - """List IKE policies that belong to a tenant.""" - - resource = 'ikepolicy' - list_columns = ['id', 'name', 'auth_algorithm', - 'encryption_algorithm', 'ike_version', 'pfs'] - _formatters = {} - pagination_support = True - sorting_support = True - - -class ShowIKEPolicy(neutronv20.ShowCommand): - """Show information of a given IKE policy.""" - - resource = 'ikepolicy' - - -class CreateIKEPolicy(neutronv20.CreateCommand): - """Create an IKE policy.""" - - resource = 'ikepolicy' - - def add_known_arguments(self, parser): - parser.add_argument( - '--description', - help=_('Description of the IKE policy')) - parser.add_argument( - '--auth-algorithm', - default='sha1', choices=['sha1'], - help=_('Authentication algorithm in lowercase. ' - 'Default:sha1')) - parser.add_argument( - '--encryption-algorithm', - default='aes-128', - help=_('Encryption algorithm in lowercase, default:aes-128')) - parser.add_argument( - '--phase1-negotiation-mode', - default='main', choices=['main'], - help=_('IKE Phase1 negotiation mode in lowercase, default:main')) - parser.add_argument( - '--ike-version', - default='v1', choices=['v1', 'v2'], - help=_('IKE version in lowercase, default:v1')) - parser.add_argument( - '--pfs', - default='group5', choices=['group2', 'group5', 'group14'], - help=_('Perfect Forward Secrecy in lowercase, default:group5')) - parser.add_argument( - '--lifetime', - metavar="units=UNITS,value=VALUE", - type=utils.str2dict, - help=vpn_utils.lifetime_help("IKE")) - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of the IKE policy.')) - - def args2body(self, parsed_args): - - body = {'ikepolicy': { - 'auth_algorithm': parsed_args.auth_algorithm, - 'encryption_algorithm': parsed_args.encryption_algorithm, - 'phase1_negotiation_mode': parsed_args.phase1_negotiation_mode, - 'ike_version': parsed_args.ike_version, - 'pfs': parsed_args.pfs, - }, } - if parsed_args.name: - body['ikepolicy'].update({'name': parsed_args.name}) - if parsed_args.description: - body['ikepolicy'].update({'description': parsed_args.description}) - if parsed_args.tenant_id: - body['ikepolicy'].update({'tenant_id': parsed_args.tenant_id}) - if parsed_args.lifetime: - vpn_utils.validate_lifetime_dict(parsed_args.lifetime) - body['ikepolicy'].update({'lifetime': parsed_args.lifetime}) - return body - - -class UpdateIKEPolicy(neutronv20.UpdateCommand): - """Update a given IKE policy.""" - - resource = 'ikepolicy' - - def add_known_arguments(self, parser): - parser.add_argument( - '--lifetime', - metavar="units=UNITS,value=VALUE", - type=utils.str2dict, - help=vpn_utils.lifetime_help("IKE")) - - def args2body(self, parsed_args): - - body = {'ikepolicy': { - }, } - if parsed_args.lifetime: - vpn_utils.validate_lifetime_dict(parsed_args.lifetime) - body['ikepolicy'].update({'lifetime': parsed_args.lifetime}) - return body - - -class DeleteIKEPolicy(neutronv20.DeleteCommand): - """Delete a given IKE policy.""" - - resource = 'ikepolicy' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py deleted file mode 100644 index 59d676e0af..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py +++ /dev/null @@ -1,187 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett-Packard. -# - -from oslo.serialization import jsonutils - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 -from neutronclient.neutron.v2_0.vpn import utils as vpn_utils - - -def _format_peer_cidrs(ipsec_site_connection): - try: - return '\n'.join([jsonutils.dumps(cidrs) for cidrs in - ipsec_site_connection['peer_cidrs']]) - except (TypeError, KeyError): - return '' - - -class ListIPsecSiteConnection(neutronv20.ListCommand): - """List IPsec site connections that belong to a given tenant.""" - - resource = 'ipsec_site_connection' - _formatters = {'peer_cidrs': _format_peer_cidrs} - list_columns = [ - 'id', 'name', 'peer_address', 'peer_cidrs', 'route_mode', - 'auth_mode', 'status'] - pagination_support = True - sorting_support = True - - -class ShowIPsecSiteConnection(neutronv20.ShowCommand): - """Show information of a given IPsec site connection.""" - - resource = 'ipsec_site_connection' - - -class CreateIPsecSiteConnection(neutronv20.CreateCommand): - """Create an IPsec site connection.""" - resource = 'ipsec_site_connection' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - default=True, action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--name', - help=_('Set friendly name for the connection.')) - parser.add_argument( - '--description', - help=_('Set a description for the connection.')) - parser.add_argument( - '--mtu', - default='1500', - help=_('MTU size for the connection, default:1500')) - parser.add_argument( - '--initiator', - default='bi-directional', choices=['bi-directional', - 'response-only'], - help=_('Initiator state in lowercase, default:bi-directional')) - parser.add_argument( - '--dpd', - metavar="action=ACTION,interval=INTERVAL,timeout=TIMEOUT", - type=utils.str2dict, - help=vpn_utils.dpd_help("IPsec connection.")) - parser.add_argument( - '--vpnservice-id', metavar='VPNSERVICE', - required=True, - help=_('VPN service instance ID associated with this connection.')) - parser.add_argument( - '--ikepolicy-id', metavar='IKEPOLICY', - required=True, - help=_('IKE policy ID associated with this connection.')) - parser.add_argument( - '--ipsecpolicy-id', metavar='IPSECPOLICY', - required=True, - help=_('IPsec policy ID associated with this connection.')) - parser.add_argument( - '--peer-address', - required=True, - help=_('Peer gateway public IPv4/IPv6 address or FQDN.')) - parser.add_argument( - '--peer-id', - required=True, - help=_('Peer router identity for authentication. Can be ' - 'IPv4/IPv6 address, e-mail address, key id, or FQDN.')) - parser.add_argument( - '--peer-cidr', - action='append', dest='peer_cidrs', - required=True, - help=_('Remote subnet(s) in CIDR format.')) - parser.add_argument( - '--psk', - required=True, - help=_('Pre-shared key string.')) - - def args2body(self, parsed_args): - _vpnservice_id = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'vpnservice', - parsed_args.vpnservice_id) - _ikepolicy_id = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'ikepolicy', - parsed_args.ikepolicy_id) - _ipsecpolicy_id = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'ipsecpolicy', - parsed_args.ipsecpolicy_id) - if int(parsed_args.mtu) < 68: - message = _("Invalid MTU value: MTU must be " - "greater than or equal to 68") - raise exceptions.CommandError(message) - body = {'ipsec_site_connection': { - 'vpnservice_id': _vpnservice_id, - 'ikepolicy_id': _ikepolicy_id, - 'ipsecpolicy_id': _ipsecpolicy_id, - 'peer_address': parsed_args.peer_address, - 'peer_id': parsed_args.peer_id, - 'mtu': parsed_args.mtu, - 'initiator': parsed_args.initiator, - 'psk': parsed_args.psk, - 'admin_state_up': parsed_args.admin_state_down, - }, } - if parsed_args.name: - body['ipsec_site_connection'].update( - {'name': parsed_args.name} - ) - if parsed_args.description: - body['ipsec_site_connection'].update( - {'description': parsed_args.description} - ) - if parsed_args.tenant_id: - body['ipsec_site_connection'].update( - {'tenant_id': parsed_args.tenant_id} - ) - if parsed_args.dpd: - vpn_utils.validate_dpd_dict(parsed_args.dpd) - body['ipsec_site_connection'].update({'dpd': parsed_args.dpd}) - if parsed_args.peer_cidrs: - body['ipsec_site_connection'][ - 'peer_cidrs'] = parsed_args.peer_cidrs - - return body - - -class UpdateIPsecSiteConnection(neutronv20.UpdateCommand): - """Update a given IPsec site connection.""" - - resource = 'ipsec_site_connection' - - def add_known_arguments(self, parser): - - parser.add_argument( - '--dpd', - metavar="action=ACTION,interval=INTERVAL,timeout=TIMEOUT", - type=utils.str2dict, - help=vpn_utils.dpd_help("IPsec connection.")) - - def args2body(self, parsed_args): - body = {'ipsec_site_connection': { - }, } - - if parsed_args.dpd: - vpn_utils.validate_dpd_dict(parsed_args.dpd) - body['ipsec_site_connection'].update({'dpd': parsed_args.dpd}) - return body - - -class DeleteIPsecSiteConnection(neutronv20.DeleteCommand): - """Delete a given IPsec site connection.""" - - resource = 'ipsec_site_connection' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py deleted file mode 100644 index cade641b9b..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py +++ /dev/null @@ -1,127 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett-Packard. - -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 -from neutronclient.neutron.v2_0.vpn import utils as vpn_utils - - -class ListIPsecPolicy(neutronv20.ListCommand): - """List IPsec policies that belong to a given tenant connection.""" - - resource = 'ipsecpolicy' - list_columns = ['id', 'name', 'auth_algorithm', - 'encryption_algorithm', 'pfs'] - _formatters = {} - pagination_support = True - sorting_support = True - - -class ShowIPsecPolicy(neutronv20.ShowCommand): - """Show information of a given IPsec policy.""" - - resource = 'ipsecpolicy' - - -class CreateIPsecPolicy(neutronv20.CreateCommand): - """Create an IPsec policy.""" - - resource = 'ipsecpolicy' - - def add_known_arguments(self, parser): - parser.add_argument( - '--description', - help=_('Description of the IPsec policy.')) - parser.add_argument( - '--transform-protocol', - default='esp', choices=['esp', 'ah', 'ah-esp'], - help=_('Transform protocol in lowercase, default:esp')) - parser.add_argument( - '--auth-algorithm', - default='sha1', choices=['sha1'], - help=_('Authentication algorithm in lowercase, default:sha1')) - parser.add_argument( - '--encryption-algorithm', - default='aes-128', - help=_('Encryption algorithm in lowercase, default:aes-128')) - parser.add_argument( - '--encapsulation-mode', - default='tunnel', choices=['tunnel', 'transport'], - help=_('Encapsulation mode in lowercase, default:tunnel')) - parser.add_argument( - '--pfs', - default='group5', choices=['group2', 'group5', 'group14'], - help=_('Perfect Forward Secrecy in lowercase, default:group5')) - parser.add_argument( - '--lifetime', - metavar="units=UNITS,value=VALUE", - type=utils.str2dict, - help=vpn_utils.lifetime_help("IPsec")) - parser.add_argument( - 'name', metavar='NAME', - help=_('Name of the IPsec policy.')) - - def args2body(self, parsed_args): - - body = {'ipsecpolicy': { - 'auth_algorithm': parsed_args.auth_algorithm, - 'encryption_algorithm': parsed_args.encryption_algorithm, - 'encapsulation_mode': parsed_args.encapsulation_mode, - 'transform_protocol': parsed_args.transform_protocol, - 'pfs': parsed_args.pfs, - }, } - if parsed_args.name: - body['ipsecpolicy'].update({'name': parsed_args.name}) - if parsed_args.description: - body['ipsecpolicy'].update( - {'description': parsed_args.description} - ) - if parsed_args.tenant_id: - body['ipsecpolicy'].update({'tenant_id': parsed_args.tenant_id}) - if parsed_args.lifetime: - vpn_utils.validate_lifetime_dict(parsed_args.lifetime) - body['ipsecpolicy'].update({'lifetime': parsed_args.lifetime}) - return body - - -class UpdateIPsecPolicy(neutronv20.UpdateCommand): - """Update a given IPsec policy.""" - - resource = 'ipsecpolicy' - - def add_known_arguments(self, parser): - parser.add_argument( - '--lifetime', - metavar="units=UNITS,value=VALUE", - type=utils.str2dict, - help=vpn_utils.lifetime_help("IPsec")) - - def args2body(self, parsed_args): - - body = {'ipsecpolicy': { - }, } - if parsed_args.lifetime: - vpn_utils.validate_lifetime_dict(parsed_args.lifetime) - body['ipsecpolicy'].update({'lifetime': parsed_args.lifetime}) - return body - - -class DeleteIPsecPolicy(neutronv20.DeleteCommand): - """Delete a given IPsec policy.""" - - resource = 'ipsecpolicy' diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/utils.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/utils.py deleted file mode 100644 index 74fbeef6fd..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/utils.py +++ /dev/null @@ -1,114 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett-Packard. -# - - -"""VPN Utilities and helper functions.""" - - -from neutronclient.common import exceptions -from neutronclient.i18n import _ - -dpd_supported_actions = ['hold', 'clear', 'restart', - 'restart-by-peer', 'disabled'] -dpd_supported_keys = ['action', 'interval', 'timeout'] - -lifetime_keys = ['units', 'value'] -lifetime_units = ['seconds'] - - -def validate_dpd_dict(dpd_dict): - for key, value in dpd_dict.items(): - if key not in dpd_supported_keys: - message = _( - "DPD Dictionary KeyError: " - "Reason-Invalid DPD key : " - "'%(key)s' not in %(supported_key)s ") % { - 'key': key, 'supported_key': dpd_supported_keys} - raise exceptions.CommandError(message) - if key == 'action' and value not in dpd_supported_actions: - message = _( - "DPD Dictionary ValueError: " - "Reason-Invalid DPD action : " - "'%(key_value)s' not in %(supported_action)s ") % { - 'key_value': value, - 'supported_action': dpd_supported_actions} - raise exceptions.CommandError(message) - if key in ('interval', 'timeout'): - try: - if int(value) <= 0: - raise ValueError() - except ValueError: - message = _( - "DPD Dictionary ValueError: " - "Reason-Invalid positive integer value: " - "'%(key)s' = %(value)s ") % { - 'key': key, 'value': value} - raise exceptions.CommandError(message) - else: - dpd_dict[key] = int(value) - return - - -def validate_lifetime_dict(lifetime_dict): - - for key, value in lifetime_dict.items(): - if key not in lifetime_keys: - message = _( - "Lifetime Dictionary KeyError: " - "Reason-Invalid unit key : " - "'%(key)s' not in %(supported_key)s ") % { - 'key': key, 'supported_key': lifetime_keys} - raise exceptions.CommandError(message) - if key == 'units' and value not in lifetime_units: - message = _( - "Lifetime Dictionary ValueError: " - "Reason-Invalid units : " - "'%(key_value)s' not in %(supported_units)s ") % { - 'key_value': key, 'supported_units': lifetime_units} - raise exceptions.CommandError(message) - if key == 'value': - try: - if int(value) < 60: - raise ValueError() - except ValueError: - message = _( - "Lifetime Dictionary ValueError: " - "Reason-Invalid value should be at least 60:" - "'%(key_value)s' = %(value)s ") % { - 'key_value': key, 'value': value} - raise exceptions.CommandError(message) - else: - lifetime_dict['value'] = int(value) - return - - -def lifetime_help(policy): - lifetime = _("%s lifetime attributes. " - "'units'-seconds, default:seconds. " - "'value'-non negative integer, default:3600.") % policy - return lifetime - - -def dpd_help(policy): - dpd = _(" %s Dead Peer Detection attributes." - " 'action'-hold,clear,disabled,restart,restart-by-peer." - " 'interval' and 'timeout' are non negative integers. " - " 'interval' should be less than 'timeout' value. " - " 'action', default:hold 'interval', default:30, " - " 'timeout', default:120.") % policy.capitalize() - return dpd diff --git a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/vpnservice.py b/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/vpnservice.py deleted file mode 100644 index cf892646ff..0000000000 --- a/awx/lib/site-packages/neutronclient/neutron/v2_0/vpn/vpnservice.py +++ /dev/null @@ -1,90 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett-Packard. -# - -from neutronclient.i18n import _ -from neutronclient.neutron import v2_0 as neutronv20 - - -class ListVPNService(neutronv20.ListCommand): - """List VPN service configurations that belong to a given tenant.""" - - resource = 'vpnservice' - list_columns = [ - 'id', 'name', 'router_id', 'status' - ] - _formatters = {} - pagination_support = True - sorting_support = True - - -class ShowVPNService(neutronv20.ShowCommand): - """Show information of a given VPN service.""" - - resource = 'vpnservice' - - -class CreateVPNService(neutronv20.CreateCommand): - """Create a VPN service.""" - resource = 'vpnservice' - - def add_known_arguments(self, parser): - parser.add_argument( - '--admin-state-down', - dest='admin_state', action='store_false', - help=_('Set admin state up to false.')) - parser.add_argument( - '--name', - help=_('Set a name for the VPN service.')) - parser.add_argument( - '--description', - help=_('Set a description for the VPN service.')) - parser.add_argument( - 'router', metavar='ROUTER', - help=_('Router unique identifier for the VPN service.')) - parser.add_argument( - 'subnet', metavar='SUBNET', - help=_('Subnet unique identifier for the VPN service deployment.')) - - def args2body(self, parsed_args): - _subnet_id = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'subnet', - parsed_args.subnet) - _router_id = neutronv20.find_resourceid_by_name_or_id( - self.get_client(), 'router', - parsed_args.router) - - body = {self.resource: {'subnet_id': _subnet_id, - 'router_id': _router_id, - 'admin_state_up': parsed_args.admin_state}, } - neutronv20.update_dict(parsed_args, body[self.resource], - ['name', 'description', - 'tenant_id']) - - return body - - -class UpdateVPNService(neutronv20.UpdateCommand): - """Update a given VPN service.""" - - resource = 'vpnservice' - - -class DeleteVPNService(neutronv20.DeleteCommand): - """Delete a given VPN service.""" - - resource = 'vpnservice' diff --git a/awx/lib/site-packages/neutronclient/shell.py b/awx/lib/site-packages/neutronclient/shell.py deleted file mode 100644 index 66fdca81a1..0000000000 --- a/awx/lib/site-packages/neutronclient/shell.py +++ /dev/null @@ -1,992 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -""" -Command-line interface to the Neutron APIs -""" - -from __future__ import print_function - -import argparse -import getpass -import logging -import os -import sys - -from keystoneclient.auth.identity import v2 as v2_auth -from keystoneclient.auth.identity import v3 as v3_auth -from keystoneclient import discover -from keystoneclient.openstack.common.apiclient import exceptions as ks_exc -from keystoneclient import session -from oslo.utils import encodeutils -import six.moves.urllib.parse as urlparse - -from cliff import app -from cliff import commandmanager - -from neutronclient.common import clientmanager -from neutronclient.common import command as openstack_command -from neutronclient.common import exceptions as exc -from neutronclient.common import utils -from neutronclient.i18n import _ -from neutronclient.neutron.v2_0 import agent -from neutronclient.neutron.v2_0 import agentscheduler -from neutronclient.neutron.v2_0 import credential -from neutronclient.neutron.v2_0 import extension -from neutronclient.neutron.v2_0 import floatingip -from neutronclient.neutron.v2_0.fw import firewall -from neutronclient.neutron.v2_0.fw import firewallpolicy -from neutronclient.neutron.v2_0.fw import firewallrule -from neutronclient.neutron.v2_0.lb import healthmonitor as lb_healthmonitor -from neutronclient.neutron.v2_0.lb import member as lb_member -from neutronclient.neutron.v2_0.lb import pool as lb_pool -from neutronclient.neutron.v2_0.lb.v2 import healthmonitor as lbaas_healthmon -from neutronclient.neutron.v2_0.lb.v2 import listener as lbaas_listener -from neutronclient.neutron.v2_0.lb.v2 import loadbalancer as lbaas_loadbalancer -from neutronclient.neutron.v2_0.lb.v2 import member as lbaas_member -from neutronclient.neutron.v2_0.lb.v2 import pool as lbaas_pool -from neutronclient.neutron.v2_0.lb import vip as lb_vip -from neutronclient.neutron.v2_0 import metering -from neutronclient.neutron.v2_0.nec import packetfilter -from neutronclient.neutron.v2_0 import netpartition -from neutronclient.neutron.v2_0 import network -from neutronclient.neutron.v2_0 import networkprofile -from neutronclient.neutron.v2_0.nsx import networkgateway -from neutronclient.neutron.v2_0.nsx import qos_queue -from neutronclient.neutron.v2_0 import policyprofile -from neutronclient.neutron.v2_0 import port -from neutronclient.neutron.v2_0 import quota -from neutronclient.neutron.v2_0 import router -from neutronclient.neutron.v2_0 import securitygroup -from neutronclient.neutron.v2_0 import servicetype -from neutronclient.neutron.v2_0 import subnet -from neutronclient.neutron.v2_0.vpn import ikepolicy -from neutronclient.neutron.v2_0.vpn import ipsec_site_connection -from neutronclient.neutron.v2_0.vpn import ipsecpolicy -from neutronclient.neutron.v2_0.vpn import vpnservice -from neutronclient.version import __version__ - - -VERSION = '2.0' -NEUTRON_API_VERSION = '2.0' - - -def run_command(cmd, cmd_parser, sub_argv): - _argv = sub_argv - index = -1 - values_specs = [] - if '--' in sub_argv: - index = sub_argv.index('--') - _argv = sub_argv[:index] - values_specs = sub_argv[index:] - known_args, _values_specs = cmd_parser.parse_known_args(_argv) - cmd.values_specs = (index == -1 and _values_specs or values_specs) - return cmd.run(known_args) - - -def env(*_vars, **kwargs): - """Search for the first defined of possibly many env vars. - - Returns the first environment variable defined in vars, or - returns the default defined in kwargs. - - """ - for v in _vars: - value = os.environ.get(v, None) - if value: - return value - return kwargs.get('default', '') - - -def check_non_negative_int(value): - try: - value = int(value) - except ValueError: - raise argparse.ArgumentTypeError(_("invalid int value: %r") % value) - if value < 0: - raise argparse.ArgumentTypeError(_("input value %d is negative") % - value) - return value - - -class BashCompletionCommand(openstack_command.OpenStackCommand): - """Prints all of the commands and options for bash-completion.""" - resource = "bash_completion" - -COMMAND_V2 = { - 'bash-completion': BashCompletionCommand, - 'net-list': network.ListNetwork, - 'net-external-list': network.ListExternalNetwork, - 'net-show': network.ShowNetwork, - 'net-create': network.CreateNetwork, - 'net-delete': network.DeleteNetwork, - 'net-update': network.UpdateNetwork, - 'subnet-list': subnet.ListSubnet, - 'subnet-show': subnet.ShowSubnet, - 'subnet-create': subnet.CreateSubnet, - 'subnet-delete': subnet.DeleteSubnet, - 'subnet-update': subnet.UpdateSubnet, - 'port-list': port.ListPort, - 'port-show': port.ShowPort, - 'port-create': port.CreatePort, - 'port-delete': port.DeletePort, - 'port-update': port.UpdatePort, - 'quota-list': quota.ListQuota, - 'quota-show': quota.ShowQuota, - 'quota-delete': quota.DeleteQuota, - 'quota-update': quota.UpdateQuota, - 'ext-list': extension.ListExt, - 'ext-show': extension.ShowExt, - 'router-list': router.ListRouter, - 'router-port-list': port.ListRouterPort, - 'router-show': router.ShowRouter, - 'router-create': router.CreateRouter, - 'router-delete': router.DeleteRouter, - 'router-update': router.UpdateRouter, - 'router-interface-add': router.AddInterfaceRouter, - 'router-interface-delete': router.RemoveInterfaceRouter, - 'router-gateway-set': router.SetGatewayRouter, - 'router-gateway-clear': router.RemoveGatewayRouter, - 'floatingip-list': floatingip.ListFloatingIP, - 'floatingip-show': floatingip.ShowFloatingIP, - 'floatingip-create': floatingip.CreateFloatingIP, - 'floatingip-delete': floatingip.DeleteFloatingIP, - 'floatingip-associate': floatingip.AssociateFloatingIP, - 'floatingip-disassociate': floatingip.DisassociateFloatingIP, - 'security-group-list': securitygroup.ListSecurityGroup, - 'security-group-show': securitygroup.ShowSecurityGroup, - 'security-group-create': securitygroup.CreateSecurityGroup, - 'security-group-delete': securitygroup.DeleteSecurityGroup, - 'security-group-update': securitygroup.UpdateSecurityGroup, - 'security-group-rule-list': securitygroup.ListSecurityGroupRule, - 'security-group-rule-show': securitygroup.ShowSecurityGroupRule, - 'security-group-rule-create': securitygroup.CreateSecurityGroupRule, - 'security-group-rule-delete': securitygroup.DeleteSecurityGroupRule, - 'lbaas-loadbalancer-list': lbaas_loadbalancer.ListLoadBalancer, - 'lbaas-loadbalancer-show': lbaas_loadbalancer.ShowLoadBalancer, - 'lbaas-loadbalancer-create': lbaas_loadbalancer.CreateLoadBalancer, - 'lbaas-loadbalancer-update': lbaas_loadbalancer.UpdateLoadBalancer, - 'lbaas-loadbalancer-delete': lbaas_loadbalancer.DeleteLoadBalancer, - 'lbaas-listener-list': lbaas_listener.ListListener, - 'lbaas-listener-show': lbaas_listener.ShowListener, - 'lbaas-listener-create': lbaas_listener.CreateListener, - 'lbaas-listener-update': lbaas_listener.UpdateListener, - 'lbaas-listener-delete': lbaas_listener.DeleteListener, - 'lbaas-pool-list': lbaas_pool.ListPool, - 'lbaas-pool-show': lbaas_pool.ShowPool, - 'lbaas-pool-create': lbaas_pool.CreatePool, - 'lbaas-pool-update': lbaas_pool.UpdatePool, - 'lbaas-pool-delete': lbaas_pool.DeletePool, - 'lbaas-healthmonitor-list': lbaas_healthmon.ListHealthMonitor, - 'lbaas-healthmonitor-show': lbaas_healthmon.ShowHealthMonitor, - 'lbaas-healthmonitor-create': lbaas_healthmon.CreateHealthMonitor, - 'lbaas-healthmonitor-update': lbaas_healthmon.UpdateHealthMonitor, - 'lbaas-healthmonitor-delete': lbaas_healthmon.DeleteHealthMonitor, - 'lbaas-member-list': lbaas_member.ListMember, - 'lbaas-member-show': lbaas_member.ShowMember, - 'lbaas-member-create': lbaas_member.CreateMember, - 'lbaas-member-update': lbaas_member.UpdateMember, - 'lbaas-member-delete': lbaas_member.DeleteMember, - 'lb-vip-list': lb_vip.ListVip, - 'lb-vip-show': lb_vip.ShowVip, - 'lb-vip-create': lb_vip.CreateVip, - 'lb-vip-update': lb_vip.UpdateVip, - 'lb-vip-delete': lb_vip.DeleteVip, - 'lb-pool-list': lb_pool.ListPool, - 'lb-pool-show': lb_pool.ShowPool, - 'lb-pool-create': lb_pool.CreatePool, - 'lb-pool-update': lb_pool.UpdatePool, - 'lb-pool-delete': lb_pool.DeletePool, - 'lb-pool-stats': lb_pool.RetrievePoolStats, - 'lb-member-list': lb_member.ListMember, - 'lb-member-show': lb_member.ShowMember, - 'lb-member-create': lb_member.CreateMember, - 'lb-member-update': lb_member.UpdateMember, - 'lb-member-delete': lb_member.DeleteMember, - 'lb-healthmonitor-list': lb_healthmonitor.ListHealthMonitor, - 'lb-healthmonitor-show': lb_healthmonitor.ShowHealthMonitor, - 'lb-healthmonitor-create': lb_healthmonitor.CreateHealthMonitor, - 'lb-healthmonitor-update': lb_healthmonitor.UpdateHealthMonitor, - 'lb-healthmonitor-delete': lb_healthmonitor.DeleteHealthMonitor, - 'lb-healthmonitor-associate': lb_healthmonitor.AssociateHealthMonitor, - 'lb-healthmonitor-disassociate': ( - lb_healthmonitor.DisassociateHealthMonitor - ), - 'queue-create': qos_queue.CreateQoSQueue, - 'queue-delete': qos_queue.DeleteQoSQueue, - 'queue-show': qos_queue.ShowQoSQueue, - 'queue-list': qos_queue.ListQoSQueue, - 'agent-list': agent.ListAgent, - 'agent-show': agent.ShowAgent, - 'agent-delete': agent.DeleteAgent, - 'agent-update': agent.UpdateAgent, - 'net-gateway-create': networkgateway.CreateNetworkGateway, - 'net-gateway-update': networkgateway.UpdateNetworkGateway, - 'net-gateway-delete': networkgateway.DeleteNetworkGateway, - 'net-gateway-show': networkgateway.ShowNetworkGateway, - 'net-gateway-list': networkgateway.ListNetworkGateway, - 'net-gateway-connect': networkgateway.ConnectNetworkGateway, - 'net-gateway-disconnect': networkgateway.DisconnectNetworkGateway, - 'gateway-device-create': networkgateway.CreateGatewayDevice, - 'gateway-device-update': networkgateway.UpdateGatewayDevice, - 'gateway-device-delete': networkgateway.DeleteGatewayDevice, - 'gateway-device-show': networkgateway.ShowGatewayDevice, - 'gateway-device-list': networkgateway.ListGatewayDevice, - 'dhcp-agent-network-add': agentscheduler.AddNetworkToDhcpAgent, - 'dhcp-agent-network-remove': agentscheduler.RemoveNetworkFromDhcpAgent, - 'net-list-on-dhcp-agent': agentscheduler.ListNetworksOnDhcpAgent, - 'dhcp-agent-list-hosting-net': agentscheduler.ListDhcpAgentsHostingNetwork, - 'l3-agent-router-add': agentscheduler.AddRouterToL3Agent, - 'l3-agent-router-remove': agentscheduler.RemoveRouterFromL3Agent, - 'router-list-on-l3-agent': agentscheduler.ListRoutersOnL3Agent, - 'l3-agent-list-hosting-router': agentscheduler.ListL3AgentsHostingRouter, - 'lb-pool-list-on-agent': agentscheduler.ListPoolsOnLbaasAgent, - 'lb-agent-hosting-pool': agentscheduler.GetLbaasAgentHostingPool, - 'service-provider-list': servicetype.ListServiceProvider, - 'firewall-rule-list': firewallrule.ListFirewallRule, - 'firewall-rule-show': firewallrule.ShowFirewallRule, - 'firewall-rule-create': firewallrule.CreateFirewallRule, - 'firewall-rule-update': firewallrule.UpdateFirewallRule, - 'firewall-rule-delete': firewallrule.DeleteFirewallRule, - 'firewall-policy-list': firewallpolicy.ListFirewallPolicy, - 'firewall-policy-show': firewallpolicy.ShowFirewallPolicy, - 'firewall-policy-create': firewallpolicy.CreateFirewallPolicy, - 'firewall-policy-update': firewallpolicy.UpdateFirewallPolicy, - 'firewall-policy-delete': firewallpolicy.DeleteFirewallPolicy, - 'firewall-policy-insert-rule': firewallpolicy.FirewallPolicyInsertRule, - 'firewall-policy-remove-rule': firewallpolicy.FirewallPolicyRemoveRule, - 'firewall-list': firewall.ListFirewall, - 'firewall-show': firewall.ShowFirewall, - 'firewall-create': firewall.CreateFirewall, - 'firewall-update': firewall.UpdateFirewall, - 'firewall-delete': firewall.DeleteFirewall, - 'cisco-credential-list': credential.ListCredential, - 'cisco-credential-show': credential.ShowCredential, - 'cisco-credential-create': credential.CreateCredential, - 'cisco-credential-delete': credential.DeleteCredential, - 'cisco-network-profile-list': networkprofile.ListNetworkProfile, - 'cisco-network-profile-show': networkprofile.ShowNetworkProfile, - 'cisco-network-profile-create': networkprofile.CreateNetworkProfile, - 'cisco-network-profile-delete': networkprofile.DeleteNetworkProfile, - 'cisco-network-profile-update': networkprofile.UpdateNetworkProfile, - 'cisco-policy-profile-list': policyprofile.ListPolicyProfile, - 'cisco-policy-profile-show': policyprofile.ShowPolicyProfile, - 'cisco-policy-profile-update': policyprofile.UpdatePolicyProfile, - 'ipsec-site-connection-list': ( - ipsec_site_connection.ListIPsecSiteConnection - ), - 'ipsec-site-connection-show': ( - ipsec_site_connection.ShowIPsecSiteConnection - ), - 'ipsec-site-connection-create': ( - ipsec_site_connection.CreateIPsecSiteConnection - ), - 'ipsec-site-connection-update': ( - ipsec_site_connection.UpdateIPsecSiteConnection - ), - 'ipsec-site-connection-delete': ( - ipsec_site_connection.DeleteIPsecSiteConnection - ), - 'vpn-service-list': vpnservice.ListVPNService, - 'vpn-service-show': vpnservice.ShowVPNService, - 'vpn-service-create': vpnservice.CreateVPNService, - 'vpn-service-update': vpnservice.UpdateVPNService, - 'vpn-service-delete': vpnservice.DeleteVPNService, - 'vpn-ipsecpolicy-list': ipsecpolicy.ListIPsecPolicy, - 'vpn-ipsecpolicy-show': ipsecpolicy.ShowIPsecPolicy, - 'vpn-ipsecpolicy-create': ipsecpolicy.CreateIPsecPolicy, - 'vpn-ipsecpolicy-update': ipsecpolicy.UpdateIPsecPolicy, - 'vpn-ipsecpolicy-delete': ipsecpolicy.DeleteIPsecPolicy, - 'vpn-ikepolicy-list': ikepolicy.ListIKEPolicy, - 'vpn-ikepolicy-show': ikepolicy.ShowIKEPolicy, - 'vpn-ikepolicy-create': ikepolicy.CreateIKEPolicy, - 'vpn-ikepolicy-update': ikepolicy.UpdateIKEPolicy, - 'vpn-ikepolicy-delete': ikepolicy.DeleteIKEPolicy, - 'meter-label-create': metering.CreateMeteringLabel, - 'meter-label-list': metering.ListMeteringLabel, - 'meter-label-show': metering.ShowMeteringLabel, - 'meter-label-delete': metering.DeleteMeteringLabel, - 'meter-label-rule-create': metering.CreateMeteringLabelRule, - 'meter-label-rule-list': metering.ListMeteringLabelRule, - 'meter-label-rule-show': metering.ShowMeteringLabelRule, - 'meter-label-rule-delete': metering.DeleteMeteringLabelRule, - 'nuage-netpartition-list': netpartition.ListNetPartition, - 'nuage-netpartition-show': netpartition.ShowNetPartition, - 'nuage-netpartition-create': netpartition.CreateNetPartition, - 'nuage-netpartition-delete': netpartition.DeleteNetPartition, - 'nec-packet-filter-list': packetfilter.ListPacketFilter, - 'nec-packet-filter-show': packetfilter.ShowPacketFilter, - 'nec-packet-filter-create': packetfilter.CreatePacketFilter, - 'nec-packet-filter-update': packetfilter.UpdatePacketFilter, - 'nec-packet-filter-delete': packetfilter.DeletePacketFilter, -} - -COMMANDS = {'2.0': COMMAND_V2} - - -class HelpAction(argparse.Action): - """Provide a custom action so the -h and --help options - to the main app will print a list of the commands. - - The commands are determined by checking the CommandManager - instance, passed in as the "default" value for the action. - """ - def __call__(self, parser, namespace, values, option_string=None): - outputs = [] - max_len = 0 - app = self.default - parser.print_help(app.stdout) - app.stdout.write(_('\nCommands for API v%s:\n') % app.api_version) - command_manager = app.command_manager - for name, ep in sorted(command_manager): - factory = ep.load() - cmd = factory(self, None) - one_liner = cmd.get_description().split('\n')[0] - outputs.append((name, one_liner)) - max_len = max(len(name), max_len) - for (name, one_liner) in outputs: - app.stdout.write(' %s %s\n' % (name.ljust(max_len), one_liner)) - sys.exit(0) - - -class NeutronShell(app.App): - - # verbose logging levels - WARNING_LEVEL = 0 - INFO_LEVEL = 1 - DEBUG_LEVEL = 2 - CONSOLE_MESSAGE_FORMAT = '%(message)s' - DEBUG_MESSAGE_FORMAT = '%(levelname)s: %(name)s %(message)s' - log = logging.getLogger(__name__) - - def __init__(self, apiversion): - super(NeutronShell, self).__init__( - description=__doc__.strip(), - version=VERSION, - command_manager=commandmanager.CommandManager('neutron.cli'), ) - self.commands = COMMANDS - for k, v in self.commands[apiversion].items(): - self.command_manager.add_command(k, v) - - # Pop the 'complete' to correct the outputs of 'neutron help'. - self.command_manager.commands.pop('complete') - - # This is instantiated in initialize_app() only when using - # password flow auth - self.auth_client = None - self.api_version = apiversion - - def build_option_parser(self, description, version): - """Return an argparse option parser for this application. - - Subclasses may override this method to extend - the parser with more global options. - - :param description: full description of the application - :paramtype description: str - :param version: version number for the application - :paramtype version: str - """ - parser = argparse.ArgumentParser( - description=description, - add_help=False, ) - parser.add_argument( - '--version', - action='version', - version=__version__, ) - parser.add_argument( - '-v', '--verbose', '--debug', - action='count', - dest='verbose_level', - default=self.DEFAULT_VERBOSE_LEVEL, - help=_('Increase verbosity of output and show tracebacks on' - ' errors. You can repeat this option.')) - parser.add_argument( - '-q', '--quiet', - action='store_const', - dest='verbose_level', - const=0, - help=_('Suppress output except warnings and errors.')) - parser.add_argument( - '-h', '--help', - action=HelpAction, - nargs=0, - default=self, # tricky - help=_("Show this help message and exit.")) - parser.add_argument( - '-r', '--retries', - metavar="NUM", - type=check_non_negative_int, - default=0, - help=_("How many times the request to the Neutron server should " - "be retried if it fails.")) - # FIXME(bklei): this method should come from python-keystoneclient - self._append_global_identity_args(parser) - - return parser - - def _append_global_identity_args(self, parser): - # FIXME(bklei): these are global identity (Keystone) arguments which - # should be consistent and shared by all service clients. Therefore, - # they should be provided by python-keystoneclient. We will need to - # refactor this code once this functionality is available in - # python-keystoneclient. - # - # Note: At that time we'll need to decide if we can just abandon - # the deprecated args (--service-type and --endpoint-type). - - parser.add_argument( - '--os-service-type', metavar='', - default=env('OS_NETWORK_SERVICE_TYPE', default='network'), - help=_('Defaults to env[OS_NETWORK_SERVICE_TYPE] or network.')) - - parser.add_argument( - '--os-endpoint-type', metavar='', - default=env('OS_ENDPOINT_TYPE', default='publicURL'), - help=_('Defaults to env[OS_ENDPOINT_TYPE] or publicURL.')) - - # FIXME(bklei): --service-type is deprecated but kept in for - # backward compatibility. - parser.add_argument( - '--service-type', metavar='', - default=env('OS_NETWORK_SERVICE_TYPE', default='network'), - help=_('DEPRECATED! Use --os-service-type.')) - - # FIXME(bklei): --endpoint-type is deprecated but kept in for - # backward compatibility. - parser.add_argument( - '--endpoint-type', metavar='', - default=env('OS_ENDPOINT_TYPE', default='publicURL'), - help=_('DEPRECATED! Use --os-endpoint-type.')) - - parser.add_argument( - '--os-auth-strategy', metavar='', - default=env('OS_AUTH_STRATEGY', default='keystone'), - help=_('DEPRECATED! Only keystone is supported.')) - - parser.add_argument( - '--os_auth_strategy', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-auth-url', metavar='', - default=env('OS_AUTH_URL'), - help=_('Authentication URL, defaults to env[OS_AUTH_URL].')) - parser.add_argument( - '--os_auth_url', - help=argparse.SUPPRESS) - - project_name_group = parser.add_mutually_exclusive_group() - project_name_group.add_argument( - '--os-tenant-name', metavar='', - default=env('OS_TENANT_NAME'), - help=_('Authentication tenant name, defaults to ' - 'env[OS_TENANT_NAME].')) - project_name_group.add_argument( - '--os-project-name', - metavar='', - default=utils.env('OS_PROJECT_NAME'), - help='Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - ' --os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].') - - parser.add_argument( - '--os_tenant_name', - help=argparse.SUPPRESS) - - project_id_group = parser.add_mutually_exclusive_group() - project_id_group.add_argument( - '--os-tenant-id', metavar='', - default=env('OS_TENANT_ID'), - help=_('Authentication tenant ID, defaults to ' - 'env[OS_TENANT_ID].')) - project_id_group.add_argument( - '--os-project-id', - metavar='', - default=utils.env('OS_PROJECT_ID'), - help='Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - ' --os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].') - - parser.add_argument( - '--os-username', metavar='', - default=utils.env('OS_USERNAME'), - help=_('Authentication username, defaults to env[OS_USERNAME].')) - parser.add_argument( - '--os_username', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-id', metavar='', - default=env('OS_USER_ID'), - help=_('Authentication user ID (Env: OS_USER_ID)')) - - parser.add_argument( - '--os_user_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-domain-id', - metavar='', - default=utils.env('OS_USER_DOMAIN_ID'), - help='OpenStack user domain ID. ' - 'Defaults to env[OS_USER_DOMAIN_ID].') - - parser.add_argument( - '--os_user_domain_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-user-domain-name', - metavar='', - default=utils.env('OS_USER_DOMAIN_NAME'), - help='OpenStack user domain name. ' - 'Defaults to env[OS_USER_DOMAIN_NAME].') - - parser.add_argument( - '--os_user_domain_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os_project_id', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os_project_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-project-domain-id', - metavar='', - default=utils.env('OS_PROJECT_DOMAIN_ID'), - help='Defaults to env[OS_PROJECT_DOMAIN_ID].') - - parser.add_argument( - '--os-project-domain-name', - metavar='', - default=utils.env('OS_PROJECT_DOMAIN_NAME'), - help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') - - parser.add_argument( - '--os-cert', - metavar='', - default=utils.env('OS_CERT'), - help=_("Path of certificate file to use in SSL " - "connection. This file can optionally be " - "prepended with the private key. Defaults " - "to env[OS_CERT].")) - - parser.add_argument( - '--os-cacert', - metavar='', - default=env('OS_CACERT', default=None), - help=_("Specify a CA bundle file to use in " - "verifying a TLS (https) server certificate. " - "Defaults to env[OS_CACERT].")) - - parser.add_argument( - '--os-key', - metavar='', - default=utils.env('OS_KEY'), - help=_("Path of client key to use in SSL " - "connection. This option is not necessary " - "if your key is prepended to your certificate " - "file. Defaults to env[OS_KEY].")) - - parser.add_argument( - '--os-password', metavar='', - default=utils.env('OS_PASSWORD'), - help=_('Authentication password, defaults to env[OS_PASSWORD].')) - parser.add_argument( - '--os_password', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-region-name', metavar='', - default=env('OS_REGION_NAME'), - help=_('Authentication region name, defaults to ' - 'env[OS_REGION_NAME].')) - parser.add_argument( - '--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument( - '--os-token', metavar='', - default=env('OS_TOKEN'), - help=_('Authentication token, defaults to env[OS_TOKEN].')) - parser.add_argument( - '--os_token', - help=argparse.SUPPRESS) - - parser.add_argument( - '--http-timeout', metavar='', - default=env('OS_NETWORK_TIMEOUT', default=None), type=float, - help=_('Timeout in seconds to wait for an HTTP response. Defaults ' - 'to env[OS_NETWORK_TIMEOUT] or None if not specified.')) - - parser.add_argument( - '--os-url', metavar='', - default=env('OS_URL'), - help=_('Defaults to env[OS_URL].')) - parser.add_argument( - '--os_url', - help=argparse.SUPPRESS) - - parser.add_argument( - '--insecure', - action='store_true', - default=env('NEUTRONCLIENT_INSECURE', default=False), - help=_("Explicitly allow neutronclient to perform \"insecure\" " - "SSL (https) requests. The server's certificate will " - "not be verified against any certificate authorities. " - "This option should be used with caution.")) - - def _bash_completion(self): - """Prints all of the commands and options for bash-completion.""" - commands = set() - options = set() - for option, _action in self.parser._option_string_actions.items(): - options.add(option) - for command_name, command in self.command_manager: - commands.add(command_name) - cmd_factory = command.load() - cmd = cmd_factory(self, None) - cmd_parser = cmd.get_parser('') - for option, _action in cmd_parser._option_string_actions.items(): - options.add(option) - print(' '.join(commands | options)) - - def run(self, argv): - """Equivalent to the main program for the application. - - :param argv: input arguments and options - :paramtype argv: list of str - """ - try: - index = 0 - command_pos = -1 - help_pos = -1 - help_command_pos = -1 - for arg in argv: - if arg == 'bash-completion' and help_command_pos == -1: - self._bash_completion() - return 0 - if arg in self.commands[self.api_version]: - if command_pos == -1: - command_pos = index - elif arg in ('-h', '--help'): - if help_pos == -1: - help_pos = index - elif arg == 'help': - if help_command_pos == -1: - help_command_pos = index - index = index + 1 - if command_pos > -1 and help_pos > command_pos: - argv = ['help', argv[command_pos]] - if help_command_pos > -1 and command_pos == -1: - argv[help_command_pos] = '--help' - self.options, remainder = self.parser.parse_known_args(argv) - self.configure_logging() - self.interactive_mode = not remainder - self.initialize_app(remainder) - except Exception as err: - if self.options.verbose_level >= self.DEBUG_LEVEL: - self.log.exception(err) - raise - else: - self.log.error(err) - return 1 - if self.interactive_mode: - _argv = [sys.argv[0]] - sys.argv = _argv - return self.interact() - return self.run_subcommand(remainder) - - def run_subcommand(self, argv): - subcommand = self.command_manager.find_command(argv) - cmd_factory, cmd_name, sub_argv = subcommand - cmd = cmd_factory(self, self.options) - try: - self.prepare_to_run_command(cmd) - full_name = (cmd_name - if self.interactive_mode - else ' '.join([self.NAME, cmd_name]) - ) - cmd_parser = cmd.get_parser(full_name) - return run_command(cmd, cmd_parser, sub_argv) - except Exception as e: - if self.options.verbose_level >= self.DEBUG_LEVEL: - self.log.exception("%s", e) - raise - self.log.error("%s", e) - return 1 - - def authenticate_user(self): - """Make sure the user has provided all of the authentication - info we need. - """ - if self.options.os_auth_strategy == 'keystone': - if self.options.os_token or self.options.os_url: - # Token flow auth takes priority - if not self.options.os_token: - raise exc.CommandError( - _("You must provide a token via" - " either --os-token or env[OS_TOKEN]")) - - if not self.options.os_url: - raise exc.CommandError( - _("You must provide a service URL via" - " either --os-url or env[OS_URL]")) - - else: - # Validate password flow auth - project_info = (self.options.os_tenant_name or - self.options.os_tenant_id or - (self.options.os_project_name and - (self.options.os_project_domain_name or - self.options.os_project_domain_id)) or - self.options.os_project_id) - - if (not self.options.os_username - and not self.options.os_user_id): - raise exc.CommandError( - _("You must provide a username or user ID via" - " --os-username, env[OS_USERNAME] or" - " --os-user-id, env[OS_USER_ID]")) - - if not self.options.os_password: - # No password, If we've got a tty, try prompting for it - if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): - # Check for Ctl-D - try: - self.options.os_password = getpass.getpass( - 'OS Password: ') - except EOFError: - pass - # No password because we didn't have a tty or the - # user Ctl-D when prompted. - if not self.options.os_password: - raise exc.CommandError( - _("You must provide a password via" - " either --os-password or env[OS_PASSWORD]")) - - if (not project_info): - # tenent is deprecated in Keystone v3. Use the latest - # terminology instead. - raise exc.CommandError( - _("You must provide a project_id or project_name (" - "with project_domain_name or project_domain_id) " - "via " - " --os-project-id (env[OS_PROJECT_ID])" - " --os-project-name (env[OS_PROJECT_NAME])," - " --os-project-domain-id " - "(env[OS_PROJECT_DOMAIN_ID])" - " --os-project-domain-name " - "(env[OS_PROJECT_DOMAIN_NAME])")) - - if not self.options.os_auth_url: - raise exc.CommandError( - _("You must provide an auth url via" - " either --os-auth-url or via env[OS_AUTH_URL]")) - auth_session = self._get_keystone_session() - auth = auth_session.auth - else: # not keystone - if not self.options.os_url: - raise exc.CommandError( - _("You must provide a service URL via" - " either --os-url or env[OS_URL]")) - auth_session = None - auth = None - - self.client_manager = clientmanager.ClientManager( - token=self.options.os_token, - url=self.options.os_url, - auth_url=self.options.os_auth_url, - tenant_name=self.options.os_tenant_name, - tenant_id=self.options.os_tenant_id, - username=self.options.os_username, - user_id=self.options.os_user_id, - password=self.options.os_password, - region_name=self.options.os_region_name, - api_version=self.api_version, - auth_strategy=self.options.os_auth_strategy, - # FIXME (bklei) honor deprecated service_type and - # endpoint type until they are removed - service_type=self.options.os_service_type or - self.options.service_type, - endpoint_type=self.options.os_endpoint_type or self.endpoint_type, - insecure=self.options.insecure, - ca_cert=self.options.os_cacert, - timeout=self.options.http_timeout, - retries=self.options.retries, - raise_errors=False, - session=auth_session, - auth=auth, - log_credentials=True) - return - - def initialize_app(self, argv): - """Global app init bits: - - * set up API versions - * validate authentication info - """ - - super(NeutronShell, self).initialize_app(argv) - - self.api_version = {'network': self.api_version} - - # If the user is not asking for help, make sure they - # have given us auth. - cmd_name = None - if argv: - cmd_info = self.command_manager.find_command(argv) - cmd_factory, cmd_name, sub_argv = cmd_info - if self.interactive_mode or cmd_name != 'help': - self.authenticate_user() - - def configure_logging(self): - """Create logging handlers for any log output.""" - root_logger = logging.getLogger('') - - # Set up logging to a file - root_logger.setLevel(logging.DEBUG) - - # Send higher-level messages to the console via stderr - console = logging.StreamHandler(self.stderr) - console_level = {self.WARNING_LEVEL: logging.WARNING, - self.INFO_LEVEL: logging.INFO, - self.DEBUG_LEVEL: logging.DEBUG, - }.get(self.options.verbose_level, logging.DEBUG) - # The default log level is INFO, in this situation, set the - # log level of the console to WARNING, to avoid displaying - # useless messages. This equals using "--quiet" - if console_level == logging.INFO: - console.setLevel(logging.WARNING) - else: - console.setLevel(console_level) - if logging.DEBUG == console_level: - formatter = logging.Formatter(self.DEBUG_MESSAGE_FORMAT) - else: - formatter = logging.Formatter(self.CONSOLE_MESSAGE_FORMAT) - logging.getLogger('iso8601.iso8601').setLevel(logging.WARNING) - logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING) - console.setFormatter(formatter) - root_logger.addHandler(console) - return - - def get_v2_auth(self, v2_auth_url): - return v2_auth.Password( - v2_auth_url, - username=self.options.os_username, - password=self.options.os_password, - tenant_id=self.options.os_tenant_id, - tenant_name=self.options.os_tenant_name) - - def get_v3_auth(self, v3_auth_url): - project_id = self.options.os_project_id or self.options.os_tenant_id - project_name = (self.options.os_project_name or - self.options.os_tenant_name) - - return v3_auth.Password( - v3_auth_url, - username=self.options.os_username, - password=self.options.os_password, - user_id=self.options.os_user_id, - user_domain_name=self.options.os_user_domain_name, - user_domain_id=self.options.os_user_domain_id, - project_id=project_id, - project_name=project_name, - project_domain_name=self.options.os_project_domain_name, - project_domain_id=self.options.os_project_domain_id - ) - - def _discover_auth_versions(self, session, auth_url): - # discover the API versions the server is supporting base on the - # given URL - try: - ks_discover = discover.Discover(session=session, auth_url=auth_url) - return (ks_discover.url_for('2.0'), ks_discover.url_for('3.0')) - except ks_exc.ClientException: - # Identity service may not support discover API version. - # Lets try to figure out the API version from the original URL. - url_parts = urlparse.urlparse(auth_url) - (scheme, netloc, path, params, query, fragment) = url_parts - path = path.lower() - if path.startswith('/v3'): - return (None, auth_url) - elif path.startswith('/v2'): - return (auth_url, None) - else: - # not enough information to determine the auth version - msg = _('Unable to determine the Keystone version ' - 'to authenticate with using the given ' - 'auth_url. Identity service may not support API ' - 'version discovery. Please provide a versioned ' - 'auth_url instead.') - raise exc.CommandError(msg) - - def _get_keystone_session(self): - # first create a Keystone session - cacert = self.options.os_cacert or None - cert = self.options.os_cert or None - key = self.options.os_key or None - insecure = self.options.insecure or False - ks_session = session.Session.construct(dict(cacert=cacert, - cert=cert, - key=key, - insecure=insecure)) - # discover the supported keystone versions using the given url - (v2_auth_url, v3_auth_url) = self._discover_auth_versions( - session=ks_session, - auth_url=self.options.os_auth_url) - - # Determine which authentication plugin to use. First inspect the - # auth_url to see the supported version. If both v3 and v2 are - # supported, then use the highest version if possible. - user_domain_name = self.options.os_user_domain_name or None - user_domain_id = self.options.os_user_domain_id or None - project_domain_name = self.options.os_project_domain_name or None - project_domain_id = self.options.os_project_domain_id or None - domain_info = (user_domain_name or user_domain_id or - project_domain_name or project_domain_id) - - if (v2_auth_url and not domain_info) or not v3_auth_url: - ks_session.auth = self.get_v2_auth(v2_auth_url) - else: - ks_session.auth = self.get_v3_auth(v3_auth_url) - - return ks_session - - -def main(argv=sys.argv[1:]): - try: - return NeutronShell(NEUTRON_API_VERSION).run( - list(map(encodeutils.safe_decode, argv))) - except KeyboardInterrupt: - print("... terminating neutron client", file=sys.stderr) - return 130 - except exc.NeutronClientException: - return 1 - except Exception as e: - print(e) - return 1 - - -if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) diff --git a/awx/lib/site-packages/neutronclient/tests/__init__.py b/awx/lib/site-packages/neutronclient/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/tests/unit/__init__.py b/awx/lib/site-packages/neutronclient/tests/unit/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/tests/unit/fw/__init__.py b/awx/lib/site-packages/neutronclient/tests/unit/fw/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewall.py b/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewall.py deleted file mode 100644 index 3b6288b632..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewall.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2013 Big Switch Networks Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: KC Wang, Big Switch Networks Inc. -# - -import sys - -from neutronclient.neutron.v2_0.fw import firewall -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FirewallJSON(test_cli20.CLITestV20Base): - - def test_create_firewall_with_mandatory_params(self): - """firewall-create with mandatory (none) params.""" - resource = 'firewall' - cmd = firewall.CreateFirewall(test_cli20.MyApp(sys.stdout), None) - name = '' - tenant_id = 'my-tenant' - my_id = 'my-id' - policy_id = 'my-policy-id' - args = ['--tenant-id', tenant_id, policy_id, ] - position_names = ['firewall_policy_id', ] - position_values = [policy_id, ] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True, tenant_id=tenant_id) - - def test_create_firewall_with_all_params(self): - """firewall-create with all params set.""" - resource = 'firewall' - cmd = firewall.CreateFirewall(test_cli20.MyApp(sys.stdout), None) - name = 'my-name' - description = 'my-desc' - policy_id = 'my-policy-id' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--description', description, - '--shared', - '--admin-state-down', - '--tenant-id', tenant_id, - policy_id] - position_names = ['firewall_policy_id', ] - position_values = [policy_id, ] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - description=description, - shared=True, admin_state_up=False, - tenant_id=tenant_id) - - def test_list_firewalls(self): - """firewall-list.""" - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_firewalls_pagination(self): - """firewall-list with pagination.""" - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_firewalls_sort(self): - """sorted list: firewall-list --sort-key name --sort-key id - --sort-key asc --sort-key desc - """ - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_firewalls_limit(self): - """size (1000) limited list: firewall-list -P.""" - resources = "firewalls" - cmd = firewall.ListFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_firewall_id(self): - """firewall-show test_id.""" - resource = 'firewall' - cmd = firewall.ShowFirewall(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_firewall_id_name(self): - """firewall-show.""" - resource = 'firewall' - cmd = firewall.ShowFirewall(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_firewall(self): - """firewall-update myid --name newname --tags a b.""" - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_update_firewall_using_policy_name(self): - """firewall-update myid --policy newpolicy.""" - resource = 'firewall' - cmd = firewall.UpdateFirewall(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--policy', 'newpolicy'], - {'firewall_policy_id': 'newpolicy'}) - - def test_delete_firewall(self): - """firewall-delete my-id.""" - resource = 'firewall' - cmd = firewall.DeleteFirewall(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - -class CLITestV20FirewallXML(CLITestV20FirewallJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py b/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py deleted file mode 100644 index a8786dbbca..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewallpolicy.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright 2013 Big Switch Networks Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: KC Wang, Big Switch Networks Inc. -# - -import sys - -from mox3 import mox - -from neutronclient.neutron.v2_0.fw import firewallpolicy -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FirewallPolicyJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20FirewallPolicyJSON, self).setUp() - - def test_create_firewall_policy_with_mandatory_params(self): - """firewall-policy-create with mandatory (none) params only.""" - resource = 'firewall_policy' - cmd = firewallpolicy.CreateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - tenant_id = 'my-tenant' - name = 'my-name' - my_id = 'myid' - args = ['--tenant-id', tenant_id, - '--admin-state_up', - name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True, tenant_id=tenant_id) - - def test_create_firewall_policy_with_all_params(self): - """firewall-policy-create with rule param of misc format.""" - resource = 'firewall_policy' - cmd = firewallpolicy.CreateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - description = 'my-desc' - firewall_rules_res = ['rule_id1', 'rule_id2'] - tenant_id = 'my-tenant' - my_id = 'myid' - position_names = ['name', ] - position_values = [name, ] - - #check for both str and unicode format firewall_rules_arg - for firewall_rules_arg in ['rule_id1 rule_id2', u'rule_id1 rule_id2']: - args = ['--description', description, - '--shared', - '--firewall-rules', firewall_rules_arg, - '--audited', - '--tenant-id', tenant_id, - '--admin-state_up', - name] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - description=description, shared=True, - firewall_rules=firewall_rules_res, - audited=True, admin_state_up=True, - tenant_id=tenant_id) - - def test_list_firewall_policies(self): - """firewall-policy-list.""" - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_firewall_policies_pagination(self): - """firewall-policy-list.""" - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_firewall_policies_sort(self): - """sorted list: firewall-policy-list --sort-key name --sort-key id - --sort-key asc --sort-key desc - """ - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_firewall_policies_limit(self): - """size (1000) limited list: firewall-policy-list -P.""" - resources = "firewall_policies" - cmd = firewallpolicy.ListFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_firewall_policy_id(self): - """firewall-policy-show test_id.""" - resource = 'firewall_policy' - cmd = firewallpolicy.ShowFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_firewall_policy_id_name(self): - """firewall-policy-show.""" - resource = 'firewall_policy' - cmd = firewallpolicy.ShowFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_firewall_policy(self): - """firewall-policy-update myid --name newname.""" - resource = 'firewall_policy' - cmd = firewallpolicy.UpdateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_update_firewall_policy_with_rules(self): - """firewall-policy-update myid --firewall-rules "rule1 rule2".""" - resource = 'firewall_policy' - cmd = firewallpolicy.UpdateFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - firewall_rules_arg = u'rule_id3 rule_id4' - firewall_rules_res = ['rule_id3', 'rule_id4'] - self._test_update_resource( - resource, cmd, 'myid', - ['myid', '--firewall-rules', firewall_rules_arg], - {'firewall_rules': firewall_rules_res, }) - - def test_delete_firewall_policy(self): - """firewall-policy-delete my-id.""" - resource = 'firewall_policy' - cmd = firewallpolicy.DeleteFirewallPolicy(test_cli20.MyApp(sys.stdout), - None) - my_id = 'myid1' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_insert_firewall_rule(self): - """firewall-policy-insert-rule myid newruleid - --insert-before ruleAid - --insert-after ruleBid - """ - resource = 'firewall_policy' - cmd = firewallpolicy.FirewallPolicyInsertRule( - test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = ['myid', 'newrule', - '--insert-before', 'rule2', - '--insert-after', 'rule1'] - extrafields = {'firewall_rule_id': 'newrule', - 'insert_before': 'rule2', - 'insert_after': 'rule1'} - - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - body = extrafields - path = getattr(self.client, resource + "_insert_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path % myid, format=self.format), - self.client), - 'PUT', body=test_cli20.MyComparator(body, self.client), - headers=mox.ContainsKeyValue( - 'X-Auth-Token', - test_cli20.TOKEN)).AndReturn((test_cli20.MyResp(204), None)) - args.extend(['--request-format', self.format]) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser(resource + "_insert_rule") - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - def test_remove_firewall_rule(self): - """firewall-policy-remove-rule myid ruleid - """ - resource = 'firewall_policy' - cmd = firewallpolicy.FirewallPolicyRemoveRule( - test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = ['myid', 'removerule'] - extrafields = {'firewall_rule_id': 'removerule', } - - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - body = extrafields - path = getattr(self.client, resource + "_remove_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path % myid, format=self.format), - self.client), - 'PUT', body=test_cli20.MyComparator(body, self.client), - headers=mox.ContainsKeyValue( - 'X-Auth-Token', - test_cli20.TOKEN)).AndReturn((test_cli20.MyResp(204), None)) - args.extend(['--request-format', self.format]) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser(resource + "_remove_rule") - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - -class CLITestV20FirewallPolicyXML(CLITestV20FirewallPolicyJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewallrule.py b/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewallrule.py deleted file mode 100644 index e302d65696..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/fw/test_cli20_firewallrule.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright 2013 Big Switch Networks Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: KC Wang, Big Switch Networks Inc. -# - -import sys - -from neutronclient.neutron.v2_0.fw import firewallrule -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FirewallRuleJSON(test_cli20.CLITestV20Base): - - def _test_create_firewall_rule_with_mandatory_params(self, enabled): - """firewall-rule-create with mandatory (none) params only.""" - resource = 'firewall_rule' - cmd = firewallrule.CreateFirewallRule(test_cli20.MyApp(sys.stdout), - None) - tenant_id = 'my-tenant' - name = '' - my_id = 'myid' - protocol = 'tcp' - action = 'allow' - args = ['--tenant-id', tenant_id, - '--admin-state-up', - '--protocol', protocol, - '--action', action, - '--enabled', enabled] - position_names = [] - position_values = [] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - protocol=protocol, action=action, - enabled=enabled, tenant_id=tenant_id) - - def test_create_enabled_firewall_rule_with_mandatory_params_lcase(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='true') - - def test_create_disabled_firewall_rule_with_mandatory_params_lcase(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='false') - - def test_create_enabled_firewall_rule_with_mandatory_params(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='True') - - def test_create_disabled_firewall_rule_with_mandatory_params(self): - self._test_create_firewall_rule_with_mandatory_params(enabled='False') - - def _setup_create_firewall_rule_with_all_params(self, protocol='tcp'): - """firewall-rule-create with all params set.""" - resource = 'firewall_rule' - cmd = firewallrule.CreateFirewallRule(test_cli20.MyApp(sys.stdout), - None) - name = 'my-name' - description = 'my-desc' - source_ip = '192.168.1.0/24' - destination_ip = '192.168.2.0/24' - source_port = '0:65535' - destination_port = '0:65535' - action = 'allow' - tenant_id = 'my-tenant' - my_id = 'myid' - enabled = 'True' - args = ['--description', description, - '--shared', - '--protocol', protocol, - '--source-ip-address', source_ip, - '--destination-ip-address', destination_ip, - '--source-port', source_port, - '--destination-port', destination_port, - '--action', action, - '--enabled', enabled, - '--admin-state-up', - '--tenant-id', tenant_id] - position_names = [] - position_values = [] - if protocol == 'any': - protocol = None - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - description=description, shared=True, - protocol=protocol, - source_ip_address=source_ip, - destination_ip_address=destination_ip, - source_port=source_port, - destination_port=destination_port, - action=action, enabled='True', - tenant_id=tenant_id) - - def test_create_firewall_rule_with_all_params(self): - self._setup_create_firewall_rule_with_all_params() - - def test_create_firewall_rule_with_proto_any(self): - self._setup_create_firewall_rule_with_all_params(protocol='any') - - def test_list_firewall_rules(self): - """firewall-rule-list.""" - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_firewall_rules_pagination(self): - """firewall-rule-list.""" - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_firewall_rules_sort(self): - """firewall-rule-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_firewall_rules_limit(self): - """firewall-rule-list -P.""" - resources = "firewall_rules" - cmd = firewallrule.ListFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_firewall_rule_id(self): - """firewall-rule-show test_id.""" - resource = 'firewall_rule' - cmd = firewallrule.ShowFirewallRule(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_firewall_rule_id_name(self): - """firewall-rule-show.""" - resource = 'firewall_rule' - cmd = firewallrule.ShowFirewallRule(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_firewall_rule(self): - """firewall-rule-update myid --name newname.""" - resource = 'firewall_rule' - cmd = firewallrule.UpdateFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_update_firewall_rule_protocol(self): - """firewall-rule-update myid --protocol any.""" - resource = 'firewall_rule' - cmd = firewallrule.UpdateFirewallRule(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--protocol', 'any'], - {'protocol': None, }) - - def test_delete_firewall_rule(self): - """firewall-rule-delete my-id.""" - resource = 'firewall_rule' - cmd = firewallrule.DeleteFirewallRule(test_cli20.MyApp(sys.stdout), - None) - my_id = 'myid1' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - -class CLITestV20FirewallRuleXML(CLITestV20FirewallRuleJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/__init__.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py deleted file mode 100644 index 2415a176c9..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_healthmonitor.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - -import sys - -from mox3 import mox - -from neutronclient.neutron.v2_0.lb import healthmonitor -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbHealthmonitorJSON(test_cli20.CLITestV20Base): - def test_create_healthmonitor_with_mandatory_params(self): - """lb-healthmonitor-create with mandatory params only.""" - resource = 'health_monitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - admin_state_up = False - delay = '60' - max_retries = '2' - timeout = '10' - type = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--admin-state-down', - '--delay', delay, - '--max-retries', max_retries, - '--timeout', timeout, - '--type', type, - '--tenant-id', tenant_id] - position_names = ['admin_state_up', 'delay', 'max_retries', 'timeout', - 'type', 'tenant_id'] - position_values = [admin_state_up, delay, max_retries, timeout, type, - tenant_id] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values) - - def test_create_healthmonitor_with_all_params(self): - """lb-healthmonitor-create with all params set.""" - resource = 'health_monitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - admin_state_up = False - delay = '60' - expected_codes = '200-202,204' - http_method = 'HEAD' - max_retries = '2' - timeout = '10' - type = 'TCP' - tenant_id = 'my-tenant' - url_path = '/health' - my_id = 'my-id' - args = ['--admin-state-down', - '--delay', delay, - '--expected-codes', expected_codes, - '--http-method', http_method, - '--max-retries', max_retries, - '--timeout', timeout, - '--type', type, - '--tenant-id', tenant_id, - '--url-path', url_path] - position_names = ['admin_state_up', 'delay', - 'expected_codes', 'http_method', - 'max_retries', 'timeout', - 'type', 'tenant_id', 'url_path'] - position_values = [admin_state_up, delay, - expected_codes, http_method, - max_retries, timeout, - type, tenant_id, url_path] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values) - - def test_list_healthmonitors(self): - """lb-healthmonitor-list.""" - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_healthmonitors_pagination(self): - """lb-healthmonitor-list.""" - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_healthmonitors_sort(self): - """lb-healthmonitor-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_healthmonitors_limit(self): - """lb-healthmonitor-list -P.""" - resources = "health_monitors" - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_healthmonitor_id(self): - """lb-healthmonitor-show test_id.""" - resource = 'health_monitor' - cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_update_health_monitor(self): - """lb-healthmonitor-update myid --name myname --tags a b.""" - resource = 'health_monitor' - cmd = healthmonitor.UpdateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--timeout', '5'], - {'timeout': '5', }) - - def test_delete_healthmonitor(self): - """lb-healthmonitor-delete my-id.""" - resource = 'health_monitor' - cmd = healthmonitor.DeleteHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_associate_healthmonitor(self): - cmd = healthmonitor.AssociateHealthMonitor( - test_cli20.MyApp(sys.stdout), - None) - resource = 'health_monitor' - health_monitor_id = 'hm-id' - pool_id = 'p_id' - args = [health_monitor_id, pool_id] - - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - - body = {resource: {'id': health_monitor_id}} - result = {resource: {'id': health_monitor_id}, } - result_str = self.client.serialize(result) - - path = getattr(self.client, - "associate_pool_health_monitors_path") % pool_id - return_tup = (test_cli20.MyResp(200), result_str) - self.client.httpclient.request( - test_cli20.end_url(path), 'POST', - body=test_cli20.MyComparator(body, self.client), - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(return_tup) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - def test_disassociate_healthmonitor(self): - cmd = healthmonitor.DisassociateHealthMonitor( - test_cli20.MyApp(sys.stdout), - None) - resource = 'health_monitor' - health_monitor_id = 'hm-id' - pool_id = 'p_id' - args = [health_monitor_id, pool_id] - - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - - path = (getattr(self.client, - "disassociate_pool_health_monitors_path") % - {'pool': pool_id, 'health_monitor': health_monitor_id}) - return_tup = (test_cli20.MyResp(204), None) - self.client.httpclient.request( - test_cli20.end_url(path), 'DELETE', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(return_tup) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - -class CLITestV20LbHealthmonitorXML(CLITestV20LbHealthmonitorJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_member.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_member.py deleted file mode 100644 index d793d7e691..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_member.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - -import sys - -from neutronclient.neutron.v2_0.lb import member -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbMemberJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20LbMemberJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_member(self): - """lb-member-create with mandatory params only.""" - resource = 'member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - address = '10.0.0.1' - port = '8080' - tenant_id = 'my-tenant' - my_id = 'my-id' - pool_id = 'pool-id' - args = ['--address', address, '--protocol-port', port, - '--tenant-id', tenant_id, pool_id] - position_names = ['address', 'protocol_port', 'tenant_id', 'pool_id', - 'admin_state_up'] - position_values = [address, port, tenant_id, pool_id, True] - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values, - admin_state_up=None) - - def test_create_member_all_params(self): - """lb-member-create with all available params.""" - resource = 'member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - address = '10.0.0.1' - admin_state_up = False - port = '8080' - weight = '1' - tenant_id = 'my-tenant' - my_id = 'my-id' - pool_id = 'pool-id' - args = ['--address', address, '--admin-state-down', - '--protocol-port', port, '--weight', weight, - '--tenant-id', tenant_id, pool_id] - position_names = [ - 'address', 'admin_state_up', 'protocol_port', 'weight', - 'tenant_id', 'pool_id' - ] - position_values = [address, admin_state_up, port, weight, - tenant_id, pool_id] - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values, - admin_state_up=None) - - def test_list_members(self): - """lb-member-list.""" - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_members_pagination(self): - """lb-member-list.""" - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_members_sort(self): - """lb-member-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_members_limit(self): - """lb-member-list -P.""" - resources = "members" - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_member_id(self): - """lb-member-show test_id.""" - resource = 'member' - cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_update_member(self): - """lb-member-update myid --name myname --tags a b.""" - resource = 'member' - cmd = member.UpdateMember(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], }) - - def test_delete_member(self): - """lb-member-delete my-id.""" - resource = 'member' - cmd = member.DeleteMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - -class CLITestV20LbMemberXML(CLITestV20LbMemberJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_pool.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_pool.py deleted file mode 100644 index c293fa87f1..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_pool.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - -import sys - -from mox3 import mox - -from neutronclient.neutron.v2_0.lb import pool -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base): - - def test_create_pool_with_mandatory_params(self): - """lb-pool-create with mandatory params only.""" - resource = 'pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - name = 'my-name' - lb_method = 'ROUND_ROBIN' - protocol = 'HTTP' - subnet_id = 'subnet-id' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--lb-method', lb_method, - '--name', name, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id] - position_names = ['admin_state_up', 'lb_method', 'name', - 'protocol', 'subnet_id', 'tenant_id'] - position_values = [True, lb_method, name, - protocol, subnet_id, tenant_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_pool_with_all_params(self): - """lb-pool-create with all params set.""" - resource = 'pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - name = 'my-name' - description = 'my-desc' - lb_method = 'ROUND_ROBIN' - protocol = 'HTTP' - subnet_id = 'subnet-id' - tenant_id = 'my-tenant' - my_id = 'my-id' - provider = 'lbaas' - args = ['--admin-state-down', - '--description', description, - '--lb-method', lb_method, - '--name', name, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - '--provider', provider] - position_names = ['admin_state_up', 'description', 'lb_method', 'name', - 'protocol', 'subnet_id', 'tenant_id', 'provider'] - position_values = [False, description, lb_method, name, - protocol, subnet_id, tenant_id, provider] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_list_pools(self): - """lb-pool-list.""" - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_pools_pagination(self): - """lb-pool-list.""" - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_pools_sort(self): - """lb-pool-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_pools_limit(self): - """lb-pool-list -P.""" - resources = "pools" - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_pool_id(self): - """lb-pool-show test_id.""" - resource = 'pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_pool_id_name(self): - """lb-pool-show.""" - resource = 'pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_pool(self): - """lb-pool-update myid --name newname --tags a b.""" - resource = 'pool' - cmd = pool.UpdatePool(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_delete_pool(self): - """lb-pool-delete my-id.""" - resource = 'pool' - cmd = pool.DeletePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_retrieve_pool_stats(self): - """lb-pool-stats test_id.""" - resource = 'pool' - cmd = pool.RetrievePoolStats(test_cli20.MyApp(sys.stdout), None) - my_id = self.test_id - fields = ['bytes_in', 'bytes_out'] - args = ['--fields', 'bytes_in', '--fields', 'bytes_out', my_id] - - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - query = "&".join(["fields=%s" % field for field in fields]) - expected_res = {'stats': {'bytes_in': '1234', 'bytes_out': '4321'}} - resstr = self.client.serialize(expected_res) - path = getattr(self.client, "pool_path_stats") - return_tup = (test_cli20.MyResp(200), resstr) - self.client.httpclient.request( - test_cli20.end_url(path % my_id, query), 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(return_tup) - self.mox.ReplayAll() - - cmd_parser = cmd.get_parser("test_" + resource) - parsed_args = cmd_parser.parse_args(args) - cmd.run(parsed_args) - - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertIn('bytes_in', _str) - self.assertIn('bytes_out', _str) - - -class CLITestV20LbPoolXML(CLITestV20LbPoolJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_vip.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_vip.py deleted file mode 100644 index fb501415e5..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/test_cli20_vip.py +++ /dev/null @@ -1,213 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ilya Shakhat, Mirantis Inc. -# - -import sys - -from neutronclient.neutron.v2_0.lb import vip -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbVipJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20LbVipJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_vip_with_mandatory_params(self): - """lb-vip-create with all mandatory params.""" - resource = 'vip' - cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) - pool_id = 'my-pool-id' - name = 'my-name' - subnet_id = 'subnet-id' - protocol_port = '1000' - protocol = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--name', name, - '--protocol-port', protocol_port, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - pool_id] - position_names = ['pool_id', 'name', 'protocol_port', 'protocol', - 'subnet_id', 'tenant_id'] - position_values = [pool_id, name, protocol_port, protocol, - subnet_id, tenant_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True) - - def test_create_vip_with_all_params(self): - """lb-vip-create with all params.""" - resource = 'vip' - cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) - pool_id = 'my-pool-id' - name = 'my-name' - description = 'my-desc' - address = '10.0.0.2' - admin_state = False - connection_limit = '1000' - subnet_id = 'subnet-id' - protocol_port = '80' - protocol = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--name', name, - '--description', description, - '--address', address, - '--admin-state-down', - '--connection-limit', connection_limit, - '--protocol-port', protocol_port, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - pool_id] - position_names = ['pool_id', 'name', 'description', 'address', - 'admin_state_up', 'connection_limit', - 'protocol_port', 'protocol', 'subnet_id', - 'tenant_id'] - position_values = [pool_id, name, description, address, - admin_state, connection_limit, protocol_port, - protocol, subnet_id, - tenant_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_vip_with_session_persistence_params(self): - """lb-vip-create with mandatory and session-persistence params.""" - resource = 'vip' - cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None) - pool_id = 'my-pool-id' - name = 'my-name' - subnet_id = 'subnet-id' - protocol_port = '1000' - protocol = 'TCP' - tenant_id = 'my-tenant' - my_id = 'my-id' - args = ['--name', name, - '--protocol-port', protocol_port, - '--protocol', protocol, - '--subnet-id', subnet_id, - '--tenant-id', tenant_id, - pool_id, - '--session-persistence', 'type=dict', - 'type=cookie,cookie_name=pie', - '--optional-param', 'any'] - position_names = ['pool_id', 'name', 'protocol_port', 'protocol', - 'subnet_id', 'tenant_id', 'optional_param'] - position_values = [pool_id, name, protocol_port, protocol, - subnet_id, tenant_id, 'any'] - extra_body = { - 'session_persistence': { - 'type': 'cookie', - 'cookie_name': 'pie', - }, - } - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - admin_state_up=True, extra_body=extra_body) - - def test_list_vips(self): - """lb-vip-list.""" - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_vips_pagination(self): - """lb-vip-list.""" - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_vips_sort(self): - """lb-vip-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_vips_limit(self): - """lb-vip-list -P.""" - resources = "vips" - cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_vip_id(self): - """lb-vip-show test_id.""" - resource = 'vip' - cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_vip_id_name(self): - """lb-vip-show.""" - resource = 'vip' - cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_vip(self): - """lb-vip-update myid --name myname --tags a b.""" - resource = 'vip' - cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], }) - - def test_update_vip_with_session_persistence(self): - resource = 'vip' - cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) - body = { - 'session_persistence': { - 'type': 'source', - }, - } - args = ['myid', '--session-persistence', 'type=dict', - 'type=source'] - self._test_update_resource(resource, cmd, 'myid', args, body) - - def test_update_vip_with_session_persistence_and_name(self): - resource = 'vip' - cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None) - body = { - 'name': 'newname', - 'session_persistence': { - 'type': 'cookie', - 'cookie_name': 'pie', - }, - } - args = ['myid', '--name', 'newname', - '--session-persistence', 'type=dict', - 'type=cookie,cookie_name=pie'] - self._test_update_resource(resource, cmd, 'myid', args, body) - - def test_delete_vip(self): - """lb-vip-delete my-id.""" - resource = 'vip' - cmd = vip.DeleteVip(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - -class CLITestV20LbVipXML(CLITestV20LbVipJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/__init__.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_healthmonitor.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_healthmonitor.py deleted file mode 100644 index 20af127622..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_healthmonitor.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Craig Tracey -# - -import sys - -from neutronclient.neutron.v2_0.lb.v2 import healthmonitor -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbHealthMonitorJSON(test_cli20.CLITestV20Base): - - def test_create_healthmonitor_with_mandatory_params(self): - """lbaas-healthmonitor-create with mandatory params only.""" - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - type = 'PING' - max_retries = '3' - delay = '10' - timeout = '60' - args = ['--type', type, '--max-retries', max_retries, - '--delay', delay, '--timeout', timeout] - position_names = ['type', 'max_retries', 'delay', 'timeout'] - position_values = [type, max_retries, delay, timeout] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_healthmonitor_with_all_params(self): - """lbaas-healthmonitor-create with all params set.""" - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - type = 'PING' - max_retries = '3' - delay = '10' - timeout = '60' - http_method = 'GET' - expected_codes = '201' - url_path = '/somepath' - args = ['--admin-state-down', '--http-method', http_method, - '--expected-codes', expected_codes, '--url-path', url_path, - '--type', type, '--max-retries', max_retries, - '--delay', delay, '--timeout', timeout] - position_names = ['admin_state_up', 'http_method', 'expected_codes', - 'url_path', 'type', 'max_retries', 'delay', - 'timeout'] - position_values = [False, http_method, expected_codes, url_path, - type, max_retries, delay, timeout] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_healthmonitors(self): - """lbaas-healthmonitor-list.""" - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_healthmonitors_pagination(self): - """lbaas-healthmonitor-list with pagination.""" - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_healthmonitors_sort(self): - """lbaas-healthmonitor-list --sort-key id --sort-key asc.""" - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_healthmonitors_limit(self): - """lbaas-healthmonitor-list -P.""" - resources = 'healthmonitors' - cmd_resources = 'lbaas_healthmonitors' - cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_healthmonitor_id(self): - """lbaas-healthmonitor-show test_id.""" - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_healthmonitor_id_name(self): - """lbaas-healthmonitor-show.""" - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def test_update_healthmonitor(self): - """lbaas-healthmonitor-update myid --name newname.""" - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.UpdateHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }, - cmd_resource=cmd_resource) - - def test_delete_healthmonitor(self): - """lbaas-healthmonitor-delete my-id.""" - resource = 'healthmonitor' - cmd_resource = 'lbaas_healthmonitor' - cmd = healthmonitor.DeleteHealthMonitor(test_cli20.MyApp(sys.stdout), - None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) - - -class CLITestV20LbHealthMonitorXML(CLITestV20LbHealthMonitorJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_listener.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_listener.py deleted file mode 100644 index fc0a062b63..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_listener.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Craig Tracey -# - -import sys - -from neutronclient.neutron.v2_0.lb.v2 import listener -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbListenerJSON(test_cli20.CLITestV20Base): - - def test_create_listener_with_mandatory_params(self): - """lbaas-listener-create with mandatory params only.""" - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - loadbalancer_id = 'loadbalancer' - protocol = 'TCP' - protocol_port = '80' - args = ['--protocol', protocol, '--protocol-port', protocol_port, - '--loadbalancer', loadbalancer_id] - position_names = ['protocol', 'protocol_port', 'loadbalancer_id'] - position_values = [protocol, protocol_port, loadbalancer_id, - True] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_listener_with_all_params(self): - """lbaas-listener-create with all params set.""" - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.CreateListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - loadbalancer = 'loadbalancer' - protocol = 'TCP' - protocol_port = '80' - args = ['--admin-state-down', - '--protocol', protocol, '--protocol-port', protocol_port, - '--loadbalancer', loadbalancer] - position_names = ['admin_state_up', - 'protocol', 'protocol_port', 'loadbalancer_id'] - position_values = [False, protocol, protocol_port, loadbalancer] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_listeners(self): - """lbaas-listener-list.""" - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_listeners_pagination(self): - """lbaas-listener-list with pagination.""" - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_listeners_sort(self): - """lbaas-listener-list --sort-key id --sort-key asc.""" - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_listeners_limit(self): - """lbaas-listener-list -P.""" - resources = 'listeners' - cmd_resources = 'lbaas_listeners' - cmd = listener.ListListener(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_listener_id(self): - """lbaas-listener-show test_id.""" - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.ShowListener(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_listener_id_name(self): - """lbaas-listener-show.""" - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.ShowListener(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def test_update_listener(self): - """lbaas-listener-update myid --name newname.""" - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.UpdateListener(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }, - cmd_resource=cmd_resource) - - def test_delete_listener(self): - """lbaas-listener-delete my-id.""" - resource = 'listener' - cmd_resource = 'lbaas_listener' - cmd = listener.DeleteListener(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) - - -class CLITestV20LbListenerXML(CLITestV20LbListenerJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py deleted file mode 100644 index a8ccd4e7e4..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_loadbalancer.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Craig Tracey -# - -import sys - -from neutronclient.neutron.v2_0.lb.v2 import loadbalancer as lb -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbLoadBalancerJSON(test_cli20.CLITestV20Base): - - def test_create_loadbalancer_with_mandatory_params(self): - """lbaas-loadbalancer-create with mandatory params only.""" - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.CreateLoadBalancer(test_cli20.MyApp(sys.stdout), None) - name = 'lbaas-loadbalancer-name' - vip_subnet_id = 'vip-subnet' - my_id = 'my-id' - args = ['--name', name, vip_subnet_id] - position_names = ['name', 'vip_subnet_id'] - position_values = [name, vip_subnet_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_loadbalancer_with_all_params(self): - """lbaas-loadbalancer-create with all params set.""" - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.CreateLoadBalancer(test_cli20.MyApp(sys.stdout), None) - name = 'lbaas-loadbalancer-name' - description = 'lbaas-loadbalancer-desc' - vip_subnet_id = 'vip-subnet' - my_id = 'my-id' - args = ['--admin-state-down', '--description', description, - '--name', name, vip_subnet_id] - position_names = ['admin_state_up', 'description', 'name', - 'vip_subnet_id'] - position_values = [False, description, name, vip_subnet_id] - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_loadbalancers(self): - """lbaas-loadbalancer-list.""" - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_loadbalancers_pagination(self): - """lbaas-loadbalancer-list with pagination.""" - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_loadbalancers_sort(self): - """lbaas-loadbalancer-list --sort-key name --sort-key id - --sort-key asc --sort-key desc - """ - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"], - cmd_resources=cmd_resources) - - def test_list_loadbalancers_limit(self): - """lbaas-loadbalancer-list -P.""" - resources = 'loadbalancers' - cmd_resources = 'lbaas_loadbalancers' - cmd = lb.ListLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_loadbalancer_id(self): - """lbaas-loadbalancer-loadbalancer-show test_id.""" - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.ShowLoadBalancer(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_loadbalancer_id_name(self): - """lbaas-loadbalancer-loadbalancer-show.""" - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.ShowLoadBalancer(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def test_update_loadbalancer(self): - """lbaas-loadbalancer-loadbalancer-update myid --name newname.""" - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.UpdateLoadBalancer(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }, - cmd_resource=cmd_resource) - - def test_delete_loadbalancer(self): - """lbaas-loadbalancer-loadbalancer-delete my-id.""" - resource = 'loadbalancer' - cmd_resource = 'lbaas_loadbalancer' - cmd = lb.DeleteLoadBalancer(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) - - -class CLITestV20LbLoadBalancerXML(CLITestV20LbLoadBalancerJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_member.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_member.py deleted file mode 100644 index 2adb03660b..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_member.py +++ /dev/null @@ -1,159 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Craig Tracey -# - -import sys - -from neutronclient.neutron.v2_0.lb.v2 import member -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbMemberJSON(test_cli20.CLITestV20Base): - - def test_create_member_with_mandatory_params(self): - """lbaas-member-create with mandatory params only.""" - resource = 'member' - cmd_resource = 'lbaas_member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - address = '10.1.1.1' - protocol_port = '80' - pool_id = 'pool-id' - subnet_id = 'subnet-id' - args = ['--address', address, '--protocol-port', protocol_port, - '--subnet', subnet_id, pool_id] - position_names = ['admin_state_up', 'address', - 'protocol_port', 'subnet_id'] - position_values = [True, address, protocol_port, subnet_id] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource, - parent_id=pool_id) - - def test_create_member_with_all_params(self): - """lbaas-member-create with all params set.""" - resource = 'member' - cmd_resource = 'lbaas_member' - cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - address = '10.1.1.1' - protocol_port = '80' - pool_id = 'pool-id' - subnet_id = 'subnet-id' - weight = '100' - args = ['--address', address, '--protocol-port', protocol_port, - '--subnet', subnet_id, pool_id, '--weight', weight, - '--admin-state-down'] - position_names = ['admin_state_up', 'address', 'protocol_port', - 'subnet_id', 'weight'] - position_values = [False, address, protocol_port, subnet_id, weight] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource, - parent_id=pool_id) - - def test_list_members(self): - """lbaas-member-list.""" - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id) - - def test_list_members_pagination(self): - """lbaas-member-list with pagination.""" - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id) - - def test_list_members_sort(self): - """lbaas-member-list --sort-key id --sort-key asc.""" - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id) - - def test_list_members_limit(self): - """lbaas-member-list -P.""" - resources = 'members' - cmd_resources = 'lbaas_members' - pool_id = 'pool-id' - cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - base_args=[pool_id], - cmd_resources=cmd_resources, - parent_id=pool_id) - - def test_show_member_id(self): - """lbaas-member-show test_id.""" - resource = 'member' - cmd_resource = 'lbaas_member' - pool_id = 'pool-id' - cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id, pool_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource, parent_id=pool_id) - - def test_show_member_id_name(self): - """lbaas-member-show.""" - resource = 'member' - cmd_resource = 'lbaas_member' - pool_id = 'pool-id' - cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id, pool_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource, parent_id=pool_id) - - def test_update_member(self): - """lbaas-member-update myid --name newname.""" - resource = 'member' - cmd_resource = 'lbaas_member' - my_id = 'my-id' - pool_id = 'pool-id' - args = [my_id, pool_id, '--name', 'newname'] - cmd = member.UpdateMember(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, my_id, args, - {'name': 'newname', }, - cmd_resource=cmd_resource, - parent_id=pool_id) - - def test_delete_member(self): - """lbaas-member-delete my-id.""" - resource = 'member' - cmd_resource = 'lbaas_member' - cmd = member.DeleteMember(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - pool_id = 'pool-id' - args = [my_id, pool_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource, - parent_id=pool_id) - - -class CLITestV20LbMemberXML(CLITestV20LbMemberJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_pool.py b/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_pool.py deleted file mode 100644 index daf3e5292a..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/lb/v2/test_cli20_pool.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright 2014 Blue Box Group, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Craig Tracey -# - -import sys - -from neutronclient.neutron.v2_0.lb.v2 import pool -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20LbPoolJSON(test_cli20.CLITestV20Base): - - def test_create_pool_with_mandatory_params(self): - """lbaas-pool-create with mandatory params only.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - lb_algorithm = 'ROUND_ROBIN' - listener = 'listener' - protocol = 'TCP' - name = 'my-pool' - args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol, - '--listener', listener, name] - position_names = ['admin_state_up', 'lb_algorithm', 'protocol', - 'listener_id', 'name'] - position_values = [True, lb_algorithm, protocol, listener, name] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_create_pool_with_all_params(self): - """lbaas-pool-create with all params set.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - lb_algorithm = 'ROUND_ROBIN' - listener = 'listener' - protocol = 'TCP' - description = 'description' - session_persistence_str = 'HTTP_COOKIE:1234' - session_persistence = {'type': 'HTTP_COOKIE', - 'cookie_name': '1234'} - healthmon_id = 'healthmon-id' - name = 'my-pool' - args = ['--lb-algorithm', lb_algorithm, '--protocol', protocol, - '--description', description, '--session-persistence', - session_persistence_str, '--healthmonitor-id', - healthmon_id, '--admin-state-down', name, - '--listener', listener] - position_names = ['lb_algorithm', 'protocol', 'description', - 'session_persistence', 'healthmonitor_id', - 'admin_state_up', 'listener_id', 'name'] - position_values = [lb_algorithm, protocol, description, - session_persistence, healthmon_id, - False, listener, name] - self._test_create_resource(resource, cmd, '', my_id, args, - position_names, position_values, - cmd_resource=cmd_resource) - - def test_list_pools(self): - """lbaas-pool-list.""" - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_pools_pagination(self): - """lbaas-pool-list with pagination.""" - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd, - cmd_resources=cmd_resources) - - def test_list_pools_sort(self): - """lbaas-pool-list --sort-key id --sort-key asc.""" - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True, - cmd_resources=cmd_resources) - - def test_list_pools_limit(self): - """lbaas-pool-list -P.""" - resources = 'pools' - cmd_resources = 'lbaas_pools' - cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000, - cmd_resources=cmd_resources) - - def test_show_pool_id(self): - """lbaas-pool-show test_id.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id'], - cmd_resource=cmd_resource) - - def test_show_pool_id_name(self): - """lbaas-pool-show.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name'], - cmd_resource=cmd_resource) - - def test_update_pool(self): - """lbaas-pool-update myid --name newname.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.UpdatePool(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }, - cmd_resource=cmd_resource) - - def test_delete_pool(self): - """lbaas-pool-delete my-id.""" - resource = 'pool' - cmd_resource = 'lbaas_pool' - cmd = pool.DeletePool(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args, - cmd_resource=cmd_resource) - - -class CLITestV20LbPoolXML(CLITestV20LbPoolJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_auth.py b/awx/lib/site-packages/neutronclient/tests/unit/test_auth.py deleted file mode 100644 index 2cae5115d2..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_auth.py +++ /dev/null @@ -1,434 +0,0 @@ -# Copyright 2012 NEC Corporation -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import json -import logging -import uuid - -import fixtures -from oslo.serialization import jsonutils -from requests_mock.contrib import fixture as mock_fixture -import testtools - -from keystoneclient.auth.identity import v2 as ks_v2_auth -from keystoneclient.auth.identity import v3 as ks_v3_auth -from keystoneclient import exceptions as ks_exceptions -from keystoneclient import fixture as ks_fixture -from keystoneclient import session - -from neutronclient import client -from neutronclient.common import exceptions - - -USERNAME = 'testuser' -USER_ID = 'testuser_id' -TENANT_NAME = 'testtenant' -TENANT_ID = 'testtenant_id' -PASSWORD = 'password' -ENDPOINT_URL = 'http://localurl' -PUBLIC_ENDPOINT_URL = '%s/public' % ENDPOINT_URL -ADMIN_ENDPOINT_URL = '%s/admin' % ENDPOINT_URL -INTERNAL_ENDPOINT_URL = '%s/internal' % ENDPOINT_URL -ENDPOINT_OVERRIDE = 'http://otherurl' -TOKENID = uuid.uuid4().hex -REGION = 'RegionOne' -NOAUTH = 'noauth' - -KS_TOKEN_RESULT = ks_fixture.V2Token() -KS_TOKEN_RESULT.set_scope() -_s = KS_TOKEN_RESULT.add_service('network', 'Neutron Service') -_s.add_endpoint(ENDPOINT_URL, region=REGION) - -ENDPOINTS_RESULT = { - 'endpoints': [{ - 'type': 'network', - 'name': 'Neutron Service', - 'region': REGION, - 'adminURL': ENDPOINT_URL, - 'internalURL': ENDPOINT_URL, - 'publicURL': ENDPOINT_URL - }] -} - -BASE_URL = "http://keystone.example.com:5000/" - -V2_URL = "%sv2.0" % BASE_URL -V3_URL = "%sv3" % BASE_URL - -_v2 = ks_fixture.V2Discovery(V2_URL) -_v3 = ks_fixture.V3Discovery(V3_URL) - -V3_VERSION_LIST = jsonutils.dumps({'versions': {'values': [_v2, _v3]}}) - -V2_VERSION_ENTRY = {'version': _v2} -V3_VERSION_ENTRY = {'version': _v3} - - -def setup_keystone_v2(mrequests): - v2_token = ks_fixture.V2Token(token_id=TOKENID) - service = v2_token.add_service('network') - service.add_endpoint(PUBLIC_ENDPOINT_URL, region=REGION) - - mrequests.register_uri('POST', - '%s/tokens' % (V2_URL), - json=v2_token) - - auth_session = session.Session() - auth_plugin = ks_v2_auth.Password(V2_URL, 'xx', 'xx') - return auth_session, auth_plugin - - -def setup_keystone_v3(mrequests): - mrequests.register_uri('GET', - V3_URL, - json=V3_VERSION_ENTRY) - - v3_token = ks_fixture.V3Token() - service = v3_token.add_service('network') - service.add_standard_endpoints(public=PUBLIC_ENDPOINT_URL, - admin=ADMIN_ENDPOINT_URL, - internal=INTERNAL_ENDPOINT_URL, - region=REGION) - - mrequests.register_uri('POST', - '%s/auth/tokens' % (V3_URL), - text=json.dumps(v3_token), - headers={'X-Subject-Token': TOKENID}) - - auth_session = session.Session() - auth_plugin = ks_v3_auth.Password(V3_URL, - username='xx', - user_id='xx', - user_domain_name='xx', - user_domain_id='xx') - return auth_session, auth_plugin - - -AUTH_URL = V2_URL - - -class CLITestAuthNoAuth(testtools.TestCase): - - def setUp(self): - """Prepare the test environment.""" - super(CLITestAuthNoAuth, self).setUp() - - self.requests = self.useFixture(mock_fixture.Fixture()) - - self.client = client.HTTPClient(username=USERNAME, - tenant_name=TENANT_NAME, - password=PASSWORD, - endpoint_url=ENDPOINT_URL, - auth_strategy=NOAUTH, - region_name=REGION) - - def test_get_noauth(self): - url = ENDPOINT_URL + '/resource' - self.requests.get(ENDPOINT_URL + '/resource') - self.client.do_request('/resource', 'GET') - self.assertEqual(url, self.requests.last_request.url) - self.assertEqual(self.client.endpoint_url, ENDPOINT_URL) - - -class CLITestAuthKeystone(testtools.TestCase): - - def setUp(self): - """Prepare the test environment.""" - super(CLITestAuthKeystone, self).setUp() - - for var in ('http_proxy', 'HTTP_PROXY'): - self.useFixture(fixtures.EnvironmentVariableFixture(var)) - - self.logger = self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) - self.requests = self.useFixture(mock_fixture.Fixture()) - - self.client = client.construct_http_client( - username=USERNAME, - tenant_name=TENANT_NAME, - password=PASSWORD, - auth_url=AUTH_URL, - region_name=REGION) - - def test_reused_token_get_auth_info(self): - """Test that Client.get_auth_info() works even if client was - instantiated with predefined token. - """ - token_id = uuid.uuid4().hex - client_ = client.HTTPClient(username=USERNAME, - tenant_name=TENANT_NAME, - token=token_id, - password=PASSWORD, - auth_url=AUTH_URL, - region_name=REGION) - expected = {'auth_token': token_id, - 'auth_tenant_id': None, - 'auth_user_id': None, - 'endpoint_url': self.client.endpoint_url} - self.assertEqual(client_.get_auth_info(), expected) - - def test_get_token(self): - auth_session, auth_plugin = setup_keystone_v2(self.requests) - - self.client = client.construct_http_client( - username=USERNAME, - tenant_name=TENANT_NAME, - password=PASSWORD, - auth_url=AUTH_URL, - region_name=REGION, - session=auth_session, - auth=auth_plugin) - - m = self.requests.get(PUBLIC_ENDPOINT_URL + '/resource', - request_headers={'X-Auth-Token': TOKENID}) - self.client.do_request('/resource', 'GET') - self.assertTrue(m.called) - - def test_refresh_token(self): - token_id = uuid.uuid4().hex - text = uuid.uuid4().hex - self.client.auth_token = token_id - self.client.endpoint_url = ENDPOINT_URL - - res_url = ENDPOINT_URL + '/resource' - v2_url = AUTH_URL + '/tokens' - - # token_id gives 401, KS_TOKEN_RESULT gives 200 - self.requests.get(res_url, - request_headers={'X-Auth-Token': token_id}, - status_code=401) - - self.requests.get( - res_url, - text=text, - status_code=200, - request_headers={'X-Auth-Token': KS_TOKEN_RESULT.token_id}) - - self.requests.post(v2_url, json=KS_TOKEN_RESULT) - - resp = self.client.do_request('/resource', 'GET') - - self.assertEqual(text, resp[1]) - self.assertEqual(3, len(self.requests.request_history)) - - self.assertEqual(res_url, self.requests.request_history[0].url) - self.assertEqual(v2_url, self.requests.request_history[1].url) - self.assertEqual(res_url, self.requests.request_history[2].url) - - def test_refresh_token_no_auth_url(self): - self.client.auth_url = None - - token_id = uuid.uuid4().hex - self.client.auth_token = token_id - self.client.endpoint_url = ENDPOINT_URL - - self.requests.get(ENDPOINT_URL + '/resource', status_code=401) - self.assertRaises(exceptions.NoAuthURLProvided, - self.client.do_request, - '/resource', - 'GET') - - def test_get_endpoint_url_with_invalid_auth_url(self): - # Handle the case when auth_url is not provided - self.client.auth_url = None - self.assertRaises(exceptions.NoAuthURLProvided, - self.client._get_endpoint_url) - - def test_get_endpoint_url(self): - token_id = uuid.uuid4().hex - self.client.auth_token = token_id - - self.requests.get(AUTH_URL + '/tokens/%s/endpoints' % token_id, - json=ENDPOINTS_RESULT) - self.requests.get(ENDPOINT_URL + '/resource') - - self.client.do_request('/resource', 'GET') - - self.assertEqual(token_id, - self.requests.last_request.headers['X-Auth-Token']) - - def test_use_given_endpoint_url(self): - self.client = client.HTTPClient( - username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD, - auth_url=AUTH_URL, region_name=REGION, - endpoint_url=ENDPOINT_OVERRIDE) - self.assertEqual(self.client.endpoint_url, ENDPOINT_OVERRIDE) - - token_id = uuid.uuid4().hex - self.client.auth_token = token_id - - self.requests.get(ENDPOINT_OVERRIDE + '/resource') - - self.client.do_request('/resource', 'GET') - - self.assertEqual(self.client.endpoint_url, ENDPOINT_OVERRIDE) - self.assertEqual(token_id, - self.requests.last_request.headers['X-Auth-Token']) - - def test_get_endpoint_url_other(self): - self.client = client.HTTPClient( - username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD, - auth_url=AUTH_URL, region_name=REGION, endpoint_type='otherURL') - - token_id = uuid.uuid4().hex - self.client.auth_token = token_id - - self.requests.get(AUTH_URL + '/tokens/%s/endpoints' % token_id, - json=ENDPOINTS_RESULT) - - self.assertRaises(exceptions.EndpointTypeNotFound, - self.client.do_request, - '/resource', - 'GET') - - def test_get_endpoint_url_failed(self): - token_id = uuid.uuid4().hex - self.client.auth_token = token_id - - self.requests.get(AUTH_URL + '/tokens/%s/endpoints' % token_id, - status_code=401) - self.requests.post(AUTH_URL + '/tokens', json=KS_TOKEN_RESULT) - m = self.requests.get(ENDPOINT_URL + '/resource') - - self.client.do_request('/resource', 'GET') - - self.assertEqual(KS_TOKEN_RESULT.token_id, - m.last_request.headers['X-Auth-Token']) - - def test_endpoint_type(self): - auth_session, auth_plugin = setup_keystone_v3(self.requests) - - # Test default behavior is to choose public. - self.client = client.construct_http_client( - username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD, - auth_url=AUTH_URL, region_name=REGION, - session=auth_session, auth=auth_plugin) - - self.assertEqual(self.client.endpoint_url, PUBLIC_ENDPOINT_URL) - - # Test admin url - self.client = client.construct_http_client( - username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD, - auth_url=AUTH_URL, region_name=REGION, endpoint_type='adminURL', - session=auth_session, auth=auth_plugin) - - self.assertEqual(self.client.endpoint_url, ADMIN_ENDPOINT_URL) - - # Test public url - self.client = client.construct_http_client( - username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD, - auth_url=AUTH_URL, region_name=REGION, endpoint_type='publicURL', - session=auth_session, auth=auth_plugin) - - self.assertEqual(self.client.endpoint_url, PUBLIC_ENDPOINT_URL) - - # Test internal url - self.client = client.construct_http_client( - username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD, - auth_url=AUTH_URL, region_name=REGION, endpoint_type='internalURL', - session=auth_session, auth=auth_plugin) - - self.assertEqual(self.client.endpoint_url, INTERNAL_ENDPOINT_URL) - - # Test url that isn't found in the service catalog - self.client = client.construct_http_client( - username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD, - auth_url=AUTH_URL, region_name=REGION, endpoint_type='privateURL', - session=auth_session, auth=auth_plugin) - - self.assertRaises( - ks_exceptions.EndpointNotFound, - getattr, self.client, 'endpoint_url') - - def test_strip_credentials_from_log(self): - m = self.requests.post(AUTH_URL + '/tokens', json=KS_TOKEN_RESULT) - self.requests.get(ENDPOINT_URL + '/resource') - self.client.do_request('/resource', 'GET') - - self.assertIn('REDACTED', self.logger.output) - self.assertNotIn(self.client.password, self.logger.output) - - self.assertNotIn('REDACTED', m.last_request.body) - self.assertIn(self.client.password, m.last_request.body) - - -class CLITestAuthKeystoneWithId(CLITestAuthKeystone): - - def setUp(self): - """Prepare the test environment.""" - super(CLITestAuthKeystoneWithId, self).setUp() - self.client = client.HTTPClient(user_id=USER_ID, - tenant_id=TENANT_ID, - password=PASSWORD, - auth_url=AUTH_URL, - region_name=REGION) - - -class CLITestAuthKeystoneWithIdandName(CLITestAuthKeystone): - - def setUp(self): - """Prepare the test environment.""" - super(CLITestAuthKeystoneWithIdandName, self).setUp() - self.client = client.HTTPClient(username=USERNAME, - user_id=USER_ID, - tenant_id=TENANT_ID, - tenant_name=TENANT_NAME, - password=PASSWORD, - auth_url=AUTH_URL, - region_name=REGION) - - -class TestKeystoneClientVersions(testtools.TestCase): - - def setUp(self): - """Prepare the test environment.""" - super(TestKeystoneClientVersions, self).setUp() - self.requests = self.useFixture(mock_fixture.Fixture()) - - def test_v2_auth(self): - auth_session, auth_plugin = setup_keystone_v2(self.requests) - - self.client = client.construct_http_client( - username=USERNAME, - tenant_name=TENANT_NAME, - password=PASSWORD, - auth_url=AUTH_URL, - region_name=REGION, - session=auth_session, - auth=auth_plugin) - - m = self.requests.get(PUBLIC_ENDPOINT_URL + '/resource') - - self.client.do_request('/resource', 'GET') - - self.assertTrue(m.called) - - def test_v3_auth(self): - auth_session, auth_plugin = setup_keystone_v3(self.requests) - - self.client = client.construct_http_client( - user_id=USER_ID, - tenant_id=TENANT_ID, - password=PASSWORD, - auth_url=V3_URL, - region_name=REGION, - session=auth_session, - auth=auth_plugin) - - m = self.requests.get(PUBLIC_ENDPOINT_URL + '/resource') - - self.client.do_request('/resource', 'GET') - - self.assertTrue(m.called) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_casual_args.py b/awx/lib/site-packages/neutronclient/tests/unit/test_casual_args.py deleted file mode 100644 index f1cf201b5a..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_casual_args.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import testtools - -from neutronclient.common import exceptions -from neutronclient.neutron import v2_0 as neutronV20 - - -class CLITestArgs(testtools.TestCase): - - def test_empty(self): - _mydict = neutronV20.parse_args_to_dict([]) - self.assertEqual({}, _mydict) - - def test_default_bool(self): - _specs = ['--my_bool', '--arg1', 'value1'] - _mydict = neutronV20.parse_args_to_dict(_specs) - self.assertTrue(_mydict['my_bool']) - - def test_bool_true(self): - _specs = ['--my-bool', 'type=bool', 'true', '--arg1', 'value1'] - _mydict = neutronV20.parse_args_to_dict(_specs) - self.assertTrue(_mydict['my_bool']) - - def test_bool_false(self): - _specs = ['--my_bool', 'type=bool', 'false', '--arg1', 'value1'] - _mydict = neutronV20.parse_args_to_dict(_specs) - self.assertFalse(_mydict['my_bool']) - - def test_nargs(self): - _specs = ['--tag', 'x', 'y', '--arg1', 'value1'] - _mydict = neutronV20.parse_args_to_dict(_specs) - self.assertIn('x', _mydict['tag']) - self.assertIn('y', _mydict['tag']) - - def test_badarg(self): - _specs = ['--tag=t', 'x', 'y', '--arg1', 'value1'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) - - def test_badarg_with_minus(self): - _specs = ['--arg1', 'value1', '-D'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) - - def test_goodarg_with_minus_number(self): - _specs = ['--arg1', 'value1', '-1', '-1.0'] - _mydict = neutronV20.parse_args_to_dict(_specs) - self.assertEqual(['value1', '-1', '-1.0'], - _mydict['arg1']) - - def test_badarg_duplicate(self): - _specs = ['--tag=t', '--arg1', 'value1', '--arg1', 'value1'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) - - def test_badarg_early_type_specification(self): - _specs = ['type=dict', 'key=value'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) - - def test_arg(self): - _specs = ['--tag=t', '--arg1', 'value1'] - self.assertEqual('value1', - neutronV20.parse_args_to_dict(_specs)['arg1']) - - def test_dict_arg(self): - _specs = ['--tag=t', '--arg1', 'type=dict', 'key1=value1,key2=value2'] - arg1 = neutronV20.parse_args_to_dict(_specs)['arg1'] - self.assertEqual('value1', arg1['key1']) - self.assertEqual('value2', arg1['key2']) - - def test_dict_arg_with_attribute_named_type(self): - _specs = ['--tag=t', '--arg1', 'type=dict', 'type=value1,key2=value2'] - arg1 = neutronV20.parse_args_to_dict(_specs)['arg1'] - self.assertEqual('value1', arg1['type']) - self.assertEqual('value2', arg1['key2']) - - def test_list_of_dict_arg(self): - _specs = ['--tag=t', '--arg1', 'type=dict', - 'list=true', 'key1=value1,key2=value2'] - arg1 = neutronV20.parse_args_to_dict(_specs)['arg1'] - self.assertEqual('value1', arg1[0]['key1']) - self.assertEqual('value2', arg1[0]['key2']) - - def test_clear_action(self): - _specs = ['--anyarg', 'action=clear'] - args = neutronV20.parse_args_to_dict(_specs) - self.assertIsNone(args['anyarg']) - - def test_bad_values_str(self): - _specs = ['--strarg', 'type=str'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) - - def test_bad_values_list(self): - _specs = ['--listarg', 'list=true', 'type=str'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) - _specs = ['--listarg', 'type=list'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) - _specs = ['--listarg', 'type=list', 'action=clear'] - self.assertRaises(exceptions.CommandError, - neutronV20.parse_args_to_dict, _specs) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20.py deleted file mode 100644 index 5f5e06a3e7..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20.py +++ /dev/null @@ -1,767 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import contextlib -import itertools -import sys - -import fixtures -from mox3 import mox -from oslo.utils import encodeutils -from oslotest import base -import requests -import six -import six.moves.urllib.parse as urlparse - -from neutronclient.common import constants -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.neutron import v2_0 as neutronV2_0 -from neutronclient import shell -from neutronclient.v2_0 import client - -API_VERSION = "2.0" -FORMAT = 'json' -TOKEN = 'testtoken' -ENDURL = 'localurl' - - -@contextlib.contextmanager -def capture_std_streams(): - fake_stdout, fake_stderr = six.StringIO(), six.StringIO() - stdout, stderr = sys.stdout, sys.stderr - try: - sys.stdout, sys.stderr = fake_stdout, fake_stderr - yield fake_stdout, fake_stderr - finally: - sys.stdout, sys.stderr = stdout, stderr - - -class FakeStdout: - - def __init__(self): - self.content = [] - - def write(self, text): - self.content.append(text) - - def make_string(self): - result = '' - for line in self.content: - result = result + line - return result - - -class MyResp(object): - def __init__(self, status_code, headers=None, reason=None): - self.status_code = status_code - self.headers = headers or {} - self.reason = reason - - -class MyApp(object): - def __init__(self, _stdout): - self.stdout = _stdout - - -def end_url(path, query=None, format=FORMAT): - _url_str = ENDURL + "/v" + API_VERSION + path + "." + format - return query and _url_str + "?" + query or _url_str - - -class MyUrlComparator(mox.Comparator): - def __init__(self, lhs, client): - self.lhs = lhs - self.client = client - - def equals(self, rhs): - lhsp = urlparse.urlparse(self.lhs) - rhsp = urlparse.urlparse(rhs) - - return (lhsp.scheme == rhsp.scheme and - lhsp.netloc == rhsp.netloc and - lhsp.path == rhsp.path and - urlparse.parse_qs(lhsp.query) == urlparse.parse_qs(rhsp.query)) - - def __str__(self): - if self.client and self.client.format != FORMAT: - lhs_parts = self.lhs.split("?", 1) - if len(lhs_parts) == 2: - lhs = ("%s.%s?%s" % (lhs_parts[0][:-4], - self.client.format, - lhs_parts[1])) - else: - lhs = ("%s.%s" % (lhs_parts[0][:-4], - self.client.format)) - return lhs - return self.lhs - - def __repr__(self): - return str(self) - - -class MyComparator(mox.Comparator): - def __init__(self, lhs, client): - self.lhs = lhs - self.client = client - - def _com_dict(self, lhs, rhs): - if len(lhs) != len(rhs): - return False - for key, value in six.iteritems(lhs): - if key not in rhs: - return False - rhs_value = rhs[key] - if not self._com(value, rhs_value): - return False - return True - - def _com_list(self, lhs, rhs): - if len(lhs) != len(rhs): - return False - for lhs_value in lhs: - if lhs_value not in rhs: - return False - return True - - def _com(self, lhs, rhs): - if lhs is None: - return rhs is None - if isinstance(lhs, dict): - if not isinstance(rhs, dict): - return False - return self._com_dict(lhs, rhs) - if isinstance(lhs, list): - if not isinstance(rhs, list): - return False - return self._com_list(lhs, rhs) - if isinstance(lhs, tuple): - if not isinstance(rhs, tuple): - return False - return self._com_list(lhs, rhs) - return lhs == rhs - - def equals(self, rhs): - if self.client: - rhs = self.client.deserialize(rhs, 200) - return self._com(self.lhs, rhs) - - def __repr__(self): - if self.client: - return self.client.serialize(self.lhs) - return str(self.lhs) - - -class CLITestV20Base(base.BaseTestCase): - - format = 'json' - test_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' - id_field = 'id' - - def _find_resourceid(self, client, resource, name_or_id, - cmd_resource=None, parent_id=None): - return name_or_id - - def _get_attr_metadata(self): - return self.metadata - - def setUp(self, plurals=None): - """Prepare the test environment.""" - super(CLITestV20Base, self).setUp() - client.Client.EXTED_PLURALS.update(constants.PLURALS) - if plurals is not None: - client.Client.EXTED_PLURALS.update(plurals) - self.metadata = {'plurals': client.Client.EXTED_PLURALS, - 'xmlns': constants.XML_NS_V20, - constants.EXT_NS: {'prefix': - 'http://xxxx.yy.com'}} - self.mox = mox.Mox() - self.endurl = ENDURL - self.fake_stdout = FakeStdout() - self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.fake_stdout)) - self.useFixture(fixtures.MonkeyPatch( - 'neutronclient.neutron.v2_0.find_resourceid_by_name_or_id', - self._find_resourceid)) - self.useFixture(fixtures.MonkeyPatch( - 'neutronclient.neutron.v2_0.find_resourceid_by_id', - self._find_resourceid)) - self.useFixture(fixtures.MonkeyPatch( - 'neutronclient.v2_0.client.Client.get_attr_metadata', - self._get_attr_metadata)) - self.client = client.Client(token=TOKEN, endpoint_url=self.endurl) - - def _test_create_resource(self, resource, cmd, name, myid, args, - position_names, position_values, - tenant_id=None, tags=None, admin_state_up=True, - extra_body=None, cmd_resource=None, - parent_id=None, **kwargs): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - non_admin_status_resources = ['subnet', 'floatingip', 'security_group', - 'security_group_rule', 'qos_queue', - 'network_gateway', 'gateway_device', - 'credential', 'network_profile', - 'policy_profile', 'ikepolicy', - 'ipsecpolicy', 'metering_label', - 'metering_label_rule', 'net_partition'] - if not cmd_resource: - cmd_resource = resource - if (resource in non_admin_status_resources): - body = {resource: {}, } - else: - body = {resource: {'admin_state_up': admin_state_up, }, } - if tenant_id: - body[resource].update({'tenant_id': tenant_id}) - if tags: - body[resource].update({'tags': tags}) - if extra_body: - body[resource].update(extra_body) - body[resource].update(kwargs) - - for i in range(len(position_names)): - body[resource].update({position_names[i]: position_values[i]}) - ress = {resource: - {self.id_field: myid}, } - if name: - ress[resource].update({'name': name}) - self.client.format = self.format - resstr = self.client.serialize(ress) - # url method body - resource_plural = neutronV2_0._get_resource_plural(cmd_resource, - self.client) - path = getattr(self.client, resource_plural + "_path") - if parent_id: - path = path % parent_id - # Work around for LP #1217791. XML deserializer called from - # MyComparator does not decodes XML string correctly. - if self.format == 'json': - mox_body = MyComparator(body, self.client) - else: - mox_body = self.client.serialize(body) - self.client.httpclient.request( - end_url(path, format=self.format), 'POST', - body=mox_body, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr)) - args.extend(['--request-format', self.format]) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser('create_' + resource) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - if name: - self.assertIn(name, _str) - - def _test_list_columns(self, cmd, resources, - resources_out, args=('-f', 'json'), - cmd_resources=None, parent_id=None): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - self.client.format = self.format - if not cmd_resources: - cmd_resources = resources - - resstr = self.client.serialize(resources_out) - - path = getattr(self.client, cmd_resources + "_path") - if parent_id: - path = path % parent_id - self.client.httpclient.request( - end_url(path, format=self.format), 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr)) - args = tuple(args) + ('--request-format', self.format) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("list_" + cmd_resources) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - def _test_list_resources(self, resources, cmd, detail=False, tags=(), - fields_1=(), fields_2=(), page_size=None, - sort_key=(), sort_dir=(), response_contents=None, - base_args=None, path=None, cmd_resources=None, - parent_id=None, output_format=None): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - if not cmd_resources: - cmd_resources = resources - if response_contents is None: - contents = [{self.id_field: 'myid1', }, - {self.id_field: 'myid2', }, ] - else: - contents = response_contents - reses = {resources: contents} - self.client.format = self.format - resstr = self.client.serialize(reses) - # url method body - query = "" - args = base_args if base_args is not None else [] - if detail: - args.append('-D') - args.extend(['--request-format', self.format]) - if fields_1: - for field in fields_1: - args.append('--fields') - args.append(field) - - if tags: - args.append('--') - args.append("--tag") - for tag in tags: - args.append(tag) - tag_query = urlparse.urlencode( - {'tag': encodeutils.safe_encode(tag)}) - if query: - query += "&" + tag_query - else: - query = tag_query - if (not tags) and fields_2: - args.append('--') - if fields_2: - args.append("--fields") - for field in fields_2: - args.append(field) - if detail: - query = query and query + '&verbose=True' or 'verbose=True' - for field in itertools.chain(fields_1, fields_2): - if query: - query += "&fields=" + field - else: - query = "fields=" + field - if page_size: - args.append("--page-size") - args.append(str(page_size)) - if query: - query += "&limit=%s" % page_size - else: - query = "limit=%s" % page_size - if sort_key: - for key in sort_key: - args.append('--sort-key') - args.append(key) - if query: - query += '&' - query += 'sort_key=%s' % key - if sort_dir: - len_diff = len(sort_key) - len(sort_dir) - if len_diff > 0: - sort_dir = tuple(sort_dir) + ('asc',) * len_diff - elif len_diff < 0: - sort_dir = sort_dir[:len(sort_key)] - for dir in sort_dir: - args.append('--sort-dir') - args.append(dir) - if query: - query += '&' - query += 'sort_dir=%s' % dir - if path is None: - path = getattr(self.client, cmd_resources + "_path") - if parent_id: - path = path % parent_id - if output_format: - args.append('-f') - args.append(output_format) - self.client.httpclient.request( - MyUrlComparator(end_url(path, query, format=self.format), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr)) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("list_" + cmd_resources) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - if response_contents is None: - self.assertIn('myid1', _str) - return _str - - def _test_list_resources_with_pagination(self, resources, cmd, - base_args=None, - cmd_resources=None, - parent_id=None): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - if not cmd_resources: - cmd_resources = resources - - path = getattr(self.client, cmd_resources + "_path") - if parent_id: - path = path % parent_id - fake_query = "marker=myid2&limit=2" - reses1 = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }], - '%s_links' % resources: [{'href': end_url(path, fake_query), - 'rel': 'next'}]} - reses2 = {resources: [{'id': 'myid3', }, - {'id': 'myid4', }]} - self.client.format = self.format - resstr1 = self.client.serialize(reses1) - resstr2 = self.client.serialize(reses2) - self.client.httpclient.request( - end_url(path, "", format=self.format), 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr1)) - self.client.httpclient.request( - MyUrlComparator(end_url(path, fake_query, format=self.format), - self.client), 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr2)) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("list_" + cmd_resources) - args = base_args if base_args is not None else [] - args.extend(['--request-format', self.format]) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - def _test_update_resource(self, resource, cmd, myid, args, extrafields, - cmd_resource=None, parent_id=None): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - if not cmd_resource: - cmd_resource = resource - - body = {resource: extrafields} - path = getattr(self.client, cmd_resource + "_path") - if parent_id: - path = path % (parent_id, myid) - else: - path = path % myid - self.client.format = self.format - # Work around for LP #1217791. XML deserializer called from - # MyComparator does not decodes XML string correctly. - if self.format == 'json': - mox_body = MyComparator(body, self.client) - else: - mox_body = self.client.serialize(body) - self.client.httpclient.request( - MyUrlComparator(end_url(path, format=self.format), - self.client), - 'PUT', - body=mox_body, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(204), None)) - args.extend(['--request-format', self.format]) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("update_" + cmd_resource) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - - def _test_show_resource(self, resource, cmd, myid, args, fields=(), - cmd_resource=None, parent_id=None): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - if not cmd_resource: - cmd_resource = resource - - query = "&".join(["fields=%s" % field for field in fields]) - expected_res = {resource: - {self.id_field: myid, - 'name': 'myname', }, } - self.client.format = self.format - resstr = self.client.serialize(expected_res) - path = getattr(self.client, cmd_resource + "_path") - if parent_id: - path = path % (parent_id, myid) - else: - path = path % myid - self.client.httpclient.request( - end_url(path, query, format=self.format), 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(200), resstr)) - args.extend(['--request-format', self.format]) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("show_" + cmd_resource) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - self.assertIn('myname', _str) - - def _test_delete_resource(self, resource, cmd, myid, args, - cmd_resource=None, parent_id=None): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - if not cmd_resource: - cmd_resource = resource - path = getattr(self.client, cmd_resource + "_path") - if parent_id: - path = path % (parent_id, myid) - else: - path = path % (myid) - self.client.httpclient.request( - end_url(path, format=self.format), 'DELETE', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(204), None)) - args.extend(['--request-format', self.format]) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("delete_" + cmd_resource) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - - def _test_update_resource_action(self, resource, cmd, myid, action, args, - body, retval=None, cmd_resource=None): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - if not cmd_resource: - cmd_resource = resource - path = getattr(self.client, cmd_resource + "_path") - path_action = '%s/%s' % (myid, action) - self.client.httpclient.request( - end_url(path % path_action, format=self.format), 'PUT', - body=MyComparator(body, self.client), - headers=mox.ContainsKeyValue( - 'X-Auth-Token', TOKEN)).AndReturn((MyResp(204), retval)) - args.extend(['--request-format', self.format]) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("delete_" + cmd_resource) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertIn(myid, _str) - - -class ClientV2TestJson(CLITestV20Base): - def test_do_request_unicode(self): - self.client.format = self.format - self.mox.StubOutWithMock(self.client.httpclient, "request") - unicode_text = u'\u7f51\u7edc' - # url with unicode - action = u'/test' - expected_action = action - # query string with unicode - params = {'test': unicode_text} - expect_query = urlparse.urlencode(utils.safe_encode_dict(params)) - # request body with unicode - body = params - expect_body = self.client.serialize(body) - self.client.httpclient.auth_token = encodeutils.safe_encode( - unicode_text) - expected_auth_token = encodeutils.safe_encode(unicode_text) - - self.client.httpclient.request( - end_url(expected_action, query=expect_query, format=self.format), - 'PUT', body=expect_body, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', - expected_auth_token)).AndReturn((MyResp(200), expect_body)) - - self.mox.ReplayAll() - res_body = self.client.do_request('PUT', action, body=body, - params=params) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - # test response with unicode - self.assertEqual(res_body, body) - - def test_do_request_error_without_response_body(self): - self.client.format = self.format - self.mox.StubOutWithMock(self.client.httpclient, "request") - params = {'test': 'value'} - expect_query = six.moves.urllib.parse.urlencode(params) - self.client.httpclient.auth_token = 'token' - - self.client.httpclient.request( - MyUrlComparator(end_url( - '/test', query=expect_query, format=self.format), self.client), - 'PUT', body='', - headers=mox.ContainsKeyValue('X-Auth-Token', 'token') - ).AndReturn((MyResp(400, reason='An error'), '')) - - self.mox.ReplayAll() - error = self.assertRaises(exceptions.NeutronClientException, - self.client.do_request, 'PUT', '/test', - body='', params=params) - self.assertEqual("An error", str(error)) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - -class ClientV2UnicodeTestXML(ClientV2TestJson): - format = 'xml' - - -class CLITestV20ExceptionHandler(CLITestV20Base): - - def _test_exception_handler_v20( - self, expected_exception, status_code, expected_msg, - error_type=None, error_msg=None, error_detail=None, - error_content=None): - if error_content is None: - error_content = {'NeutronError': {'type': error_type, - 'message': error_msg, - 'detail': error_detail}} - - e = self.assertRaises(expected_exception, - client.exception_handler_v20, - status_code, error_content) - self.assertEqual(status_code, e.status_code) - - if expected_msg is None: - if error_detail: - expected_msg = '\n'.join([error_msg, error_detail]) - else: - expected_msg = error_msg - self.assertEqual(expected_msg, e.message) - - def test_exception_handler_v20_ip_address_in_use(self): - err_msg = ('Unable to complete operation for network ' - 'fake-network-uuid. The IP address fake-ip is in use.') - self._test_exception_handler_v20( - exceptions.IpAddressInUseClient, 409, err_msg, - 'IpAddressInUse', err_msg, '') - - def test_exception_handler_v20_neutron_known_error(self): - known_error_map = [ - ('NetworkNotFound', exceptions.NetworkNotFoundClient, 404), - ('PortNotFound', exceptions.PortNotFoundClient, 404), - ('NetworkInUse', exceptions.NetworkInUseClient, 409), - ('PortInUse', exceptions.PortInUseClient, 409), - ('StateInvalid', exceptions.StateInvalidClient, 400), - ('IpAddressInUse', exceptions.IpAddressInUseClient, 409), - ('IpAddressGenerationFailure', - exceptions.IpAddressGenerationFailureClient, 409), - ('MacAddressInUse', exceptions.MacAddressInUseClient, 409), - ('ExternalIpAddressExhausted', - exceptions.ExternalIpAddressExhaustedClient, 400), - ('OverQuota', exceptions.OverQuotaClient, 409), - ('InvalidIpForNetwork', exceptions.InvalidIpForNetworkClient, 400), - ] - - error_msg = 'dummy exception message' - error_detail = 'sample detail' - for server_exc, client_exc, status_code in known_error_map: - self._test_exception_handler_v20( - client_exc, status_code, - error_msg + '\n' + error_detail, - server_exc, error_msg, error_detail) - - def test_exception_handler_v20_neutron_known_error_without_detail(self): - error_msg = 'Network not found' - error_detail = '' - self._test_exception_handler_v20( - exceptions.NetworkNotFoundClient, 404, - error_msg, - 'NetworkNotFound', error_msg, error_detail) - - def test_exception_handler_v20_unknown_error_to_per_code_exception(self): - for status_code, client_exc in exceptions.HTTP_EXCEPTION_MAP.items(): - error_msg = 'Unknown error' - error_detail = 'This is detail' - self._test_exception_handler_v20( - client_exc, status_code, - error_msg + '\n' + error_detail, - 'UnknownError', error_msg, error_detail) - - def test_exception_handler_v20_neutron_unknown_status_code(self): - error_msg = 'Unknown error' - error_detail = 'This is detail' - self._test_exception_handler_v20( - exceptions.NeutronClientException, 501, - error_msg + '\n' + error_detail, - 'UnknownError', error_msg, error_detail) - - def test_exception_handler_v20_bad_neutron_error(self): - error_content = {'NeutronError': {'unknown_key': 'UNKNOWN'}} - self._test_exception_handler_v20( - exceptions.NeutronClientException, 500, - expected_msg={'unknown_key': 'UNKNOWN'}, - error_content=error_content) - - def test_exception_handler_v20_error_dict_contains_message(self): - error_content = {'message': 'This is an error message'} - self._test_exception_handler_v20( - exceptions.NeutronClientException, 500, - expected_msg='This is an error message', - error_content=error_content) - - def test_exception_handler_v20_error_dict_not_contain_message(self): - error_content = {'error': 'This is an error message'} - expected_msg = '%s-%s' % (500, error_content) - self._test_exception_handler_v20( - exceptions.NeutronClientException, 500, - expected_msg=expected_msg, - error_content=error_content) - - def test_exception_handler_v20_default_fallback(self): - error_content = 'This is an error message' - expected_msg = '%s-%s' % (500, error_content) - self._test_exception_handler_v20( - exceptions.NeutronClientException, 500, - expected_msg=expected_msg, - error_content=error_content) - - def test_exception_status(self): - e = exceptions.BadRequest() - self.assertEqual(e.status_code, 400) - - e = exceptions.BadRequest(status_code=499) - self.assertEqual(e.status_code, 499) - - # SslCertificateValidationError has no explicit status_code, - # but should have a 'safe' defined fallback. - e = exceptions.SslCertificateValidationError() - self.assertIsNotNone(e.status_code) - - e = exceptions.SslCertificateValidationError(status_code=599) - self.assertEqual(e.status_code, 599) - - def test_connection_failed(self): - self.mox.StubOutWithMock(self.client.httpclient, 'request') - self.client.httpclient.auth_token = 'token' - - self.client.httpclient.request( - end_url('/test'), 'GET', - headers=mox.ContainsKeyValue('X-Auth-Token', 'token') - ).AndRaise(requests.exceptions.ConnectionError('Connection refused')) - - self.mox.ReplayAll() - - error = self.assertRaises(exceptions.ConnectionFailed, - self.client.get, '/test') - # NB: ConnectionFailed has no explicit status_code, so this - # tests that there is a fallback defined. - self.assertIsNotNone(error.status_code) - self.mox.VerifyAll() - self.mox.UnsetStubs() diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_agents.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_agents.py deleted file mode 100644 index f74427467e..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_agents.py +++ /dev/null @@ -1,81 +0,0 @@ -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from oslo.serialization import jsonutils - -from neutronclient.neutron.v2_0 import agent -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Agent(test_cli20.CLITestV20Base): - def test_list_agents(self): - contents = {'agents': [{'id': 'myname', 'agent_type': 'mytype', - 'alive': True}]} - args = ['-f', 'json'] - resources = "agents" - - cmd = agent.ListAgent(test_cli20.MyApp(sys.stdout), None) - self._test_list_columns(cmd, resources, contents, args) - _str = self.fake_stdout.make_string() - - returned_agents = jsonutils.loads(_str) - self.assertEqual(1, len(returned_agents)) - ag = returned_agents[0] - self.assertEqual(3, len(ag)) - self.assertIn("alive", ag.keys()) - - def test_list_agents_field(self): - contents = {'agents': [{'alive': True}]} - args = ['-f', 'json'] - resources = "agents" - smile = ':-)' - - cmd = agent.ListAgent(test_cli20.MyApp(sys.stdout), None) - self._test_list_columns(cmd, resources, contents, args) - _str = self.fake_stdout.make_string() - - returned_agents = jsonutils.loads(_str) - self.assertEqual(1, len(returned_agents)) - ag = returned_agents[0] - self.assertEqual(1, len(ag)) - self.assertIn("alive", ag.keys()) - self.assertIn(smile, ag.values()) - - def test_update_agent(self): - """agent-update myid --admin-state-down --description mydescr.""" - resource = 'agent' - cmd = agent.UpdateAgent(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource( - resource, cmd, 'myid', - ['myid', '--admin-state-down', '--description', 'mydescr'], - {'description': 'mydescr', 'admin_state_up': False} - ) - - def test_show_agent(self): - """Show agent: --field id --field binary myid.""" - resource = 'agent' - cmd = agent.ShowAgent(test_cli20.MyApp(sys.stdout), None) - args = ['--field', 'id', '--field', 'binary', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'binary']) - - def test_delete_agent(self): - """Delete agent: myid.""" - resource = 'agent' - cmd = agent.DeleteAgent(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_agentschedulers.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_agentschedulers.py deleted file mode 100644 index 8dc307a8b1..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_agentschedulers.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Oleg Bondarev, Mirantis Inc. -# - -import sys - -from mox3 import mox - -from neutronclient.neutron.v2_0 import agentscheduler -from neutronclient.neutron.v2_0 import network -from neutronclient.tests.unit import test_cli20 - - -AGENT_ID = 'agent_id1' -NETWORK_ID = 'net_id1' -ROUTER_ID = 'router_id1' - - -class CLITestV20AgentScheduler(test_cli20.CLITestV20Base): - def _test_add_to_agent(self, resource, cmd, cmd_args, destination, - body, result): - path = ((self.client.agent_path + destination) % - cmd_args[0]) - - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - result_str = self.client.serialize(result) - return_tup = (test_cli20.MyResp(200), result_str) - - self.client.httpclient.request( - test_cli20.end_url(path), 'POST', - body=test_cli20.MyComparator(body, self.client), - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(return_tup) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(cmd_args) - cmd.run(parsed_args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - def _test_remove_from_agent(self, resource, cmd, cmd_args, destination): - path = ((self.client.agent_path + destination + '/%s') % - cmd_args) - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - - return_tup = (test_cli20.MyResp(204), None) - self.client.httpclient.request( - test_cli20.end_url(path), 'DELETE', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(return_tup) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser('test_' + resource) - parsed_args = cmd_parser.parse_args(cmd_args) - cmd.run(parsed_args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - -class CLITestV20DHCPAgentScheduler(CLITestV20AgentScheduler): - - def test_add_network_to_agent(self): - resource = 'agent' - cmd = agentscheduler.AddNetworkToDhcpAgent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, NETWORK_ID) - body = {'network_id': NETWORK_ID} - result = {'network_id': 'net_id', } - self._test_add_to_agent(resource, cmd, args, self.client.DHCP_NETS, - body, result) - - def test_remove_network_from_agent(self): - resource = 'agent' - cmd = agentscheduler.RemoveNetworkFromDhcpAgent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, NETWORK_ID) - self._test_remove_from_agent(resource, cmd, args, - self.client.DHCP_NETS) - - def test_list_networks_on_agent(self): - resources = 'networks' - cmd = agentscheduler.ListNetworksOnDhcpAgent( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.agent_path + self.client.DHCP_NETS) % - agent_id) - self.mox.StubOutWithMock(network.ListNetwork, "extend_list") - network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg()) - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path) - - def test_list_agents_hosting_network(self): - resources = 'agent' - cmd = agentscheduler.ListDhcpAgentsHostingNetwork( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.network_path + self.client.DHCP_AGENTS) % - agent_id) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path, response_contents=contents) - - -class CLITestV20L3AgentScheduler(CLITestV20AgentScheduler): - - def test_add_router_to_agent(self): - resource = 'agent' - cmd = agentscheduler.AddRouterToL3Agent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, ROUTER_ID) - body = {'router_id': ROUTER_ID} - result = {'network_id': 'net_id', } - self._test_add_to_agent(resource, cmd, args, self.client.L3_ROUTERS, - body, result) - - def test_remove_router_from_agent(self): - resource = 'agent' - cmd = agentscheduler.RemoveRouterFromL3Agent( - test_cli20.MyApp(sys.stdout), None) - args = (AGENT_ID, ROUTER_ID) - self._test_remove_from_agent(resource, cmd, args, - self.client.L3_ROUTERS) - - def test_list_routers_on_agent(self): - resources = 'router' - cmd = agentscheduler.ListRoutersOnL3Agent( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.agent_path + self.client.L3_ROUTERS) % - agent_id) - contents = {self.id_field: 'myid1', 'name': 'my_name'} - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path, response_contents=contents) - - def test_list_agents_hosting_router(self): - resources = 'agent' - cmd = agentscheduler.ListL3AgentsHostingRouter( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.router_path + self.client.L3_AGENTS) % - agent_id) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path, response_contents=contents) - - -class CLITestV20LBaaSAgentScheduler(test_cli20.CLITestV20Base): - - def test_list_pools_on_agent(self): - resources = 'pools' - cmd = agentscheduler.ListPoolsOnLbaasAgent( - test_cli20.MyApp(sys.stdout), None) - agent_id = 'agent_id1' - path = ((self.client.agent_path + self.client.LOADBALANCER_POOLS) % - agent_id) - self._test_list_resources(resources, cmd, base_args=[agent_id], - path=path) - - def test_get_lbaas_agent_hosting_pool(self): - resources = 'agent' - cmd = agentscheduler.GetLbaasAgentHostingPool( - test_cli20.MyApp(sys.stdout), None) - pool_id = 'pool_id1' - path = ((self.client.pool_path + self.client.LOADBALANCER_AGENT) % - pool_id) - contents = {self.id_field: 'myid1', 'alive': True} - self._test_list_resources(resources, cmd, base_args=[pool_id], - path=path, response_contents=contents) - - -class CLITestV20LBaaSAgentSchedulerXML(CLITestV20LBaaSAgentScheduler): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_credential.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_credential.py deleted file mode 100644 index 53e8ecc8ad..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_credential.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2013 Cisco Systems Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Kyle Mestery, Cisco Systems, Inc. -# - -import sys - -from neutronclient.neutron.v2_0 import credential -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Credential(test_cli20.CLITestV20Base): - - def test_create_credential(self): - """Create credential: myid.""" - resource = 'credential' - cmd = credential.CreateCredential(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - type = 'mytype' - args = [name, type] - position_names = ['credential_name', 'type'] - position_values = [name, type] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_credentials_detail(self): - """List credentials: -D.""" - resources = 'credentials' - cmd = credential.ListCredential(test_cli20.MyApp(sys.stdout), None) - contents = [{'credential_name': 'myname', 'type': 'mytype'}] - self._test_list_resources(resources, cmd, True, - response_contents=contents) - - def test_list_credential_known_option_after_unknown(self): - """List credential: -- --tags a b --request-format xml.""" - resources = 'credentials' - cmd = credential.ListCredential(test_cli20.MyApp(sys.stdout), None) - contents = [{'credential_name': 'myname', 'type': 'mytype'}] - self._test_list_resources(resources, cmd, tags=['a', 'b'], - response_contents=contents) - - def test_list_credential_fields(self): - """List credential: --fields a --fields b -- --fields c d.""" - resources = 'credentials' - cmd = credential.ListCredential(test_cli20.MyApp(sys.stdout), None) - contents = [{'credential_name': 'myname', 'type': 'mytype'}] - self._test_list_resources(resources, cmd, - fields_1=['a', 'b'], fields_2=['c', 'd'], - response_contents=contents) - - def test_show_credential(self): - """Show credential: --fields id --fields name myid.""" - resource = 'credential' - cmd = credential.ShowCredential(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_delete_credential(self): - """Delete credential: myid.""" - resource = 'credential' - cmd = credential.DeleteCredential(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_extensions.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_extensions.py deleted file mode 100644 index 9e7d30a348..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_extensions.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2013 NEC Corporation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from neutronclient.neutron.v2_0.extension import ListExt -from neutronclient.neutron.v2_0.extension import ShowExt -from neutronclient.tests.unit.test_cli20 import CLITestV20Base -from neutronclient.tests.unit.test_cli20 import MyApp - - -class CLITestV20Extension(CLITestV20Base): - id_field = 'alias' - - def test_list_extensions(self): - resources = 'extensions' - cmd = ListExt(MyApp(sys.stdout), None) - contents = [{'alias': 'ext1', 'name': 'name1', 'other': 'other1'}, - {'alias': 'ext2', 'name': 'name2', 'other': 'other2'}] - ret = self._test_list_resources(resources, cmd, - response_contents=contents) - ret_words = set(ret.split()) - # Check only the default columns are shown. - self.assertIn('name', ret_words) - self.assertIn('alias', ret_words) - self.assertNotIn('other', ret_words) - - def test_show_extension(self): - # -F option does not work for ext-show at the moment, so -F option - # is not passed in the commandline args as other tests do. - resource = 'extension' - cmd = ShowExt(MyApp(sys.stdout), None) - args = [self.test_id] - ext_alias = self.test_id - self._test_show_resource(resource, cmd, ext_alias, args, fields=[]) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_floatingips.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_floatingips.py deleted file mode 100644 index 92f527a4b3..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_floatingips.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python -# Copyright 2012 Red Hat -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from neutronclient.neutron.v2_0 import floatingip as fip -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20FloatingIpsJSON(test_cli20.CLITestV20Base): - def test_create_floatingip(self): - """Create floatingip: fip1.""" - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - args = [name] - position_names = ['floating_network_id'] - position_values = [name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_and_port(self): - """Create floatingip: fip1.""" - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - pid = 'mypid' - args = [name, '--port_id', pid] - position_names = ['floating_network_id', 'port_id'] - position_values = [name, pid] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = [name, '--port-id', pid] - position_names = ['floating_network_id', 'port_id'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_and_port_and_address(self): - """Create floatingip: fip1 with a given port and address.""" - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - pid = 'mypid' - addr = '10.0.0.99' - args = [name, '--port_id', pid, '--fixed_ip_address', addr] - position_names = ['floating_network_id', 'port_id', 'fixed_ip_address'] - position_values = [name, pid, addr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - # Test dashed options - args = [name, '--port-id', pid, '--fixed-ip-address', addr] - position_names = ['floating_network_id', 'port_id', 'fixed_ip_address'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_floatingip_with_ip_address_of_floating_ip(self): - """Create floatingip: fip1 with a given IP address of floating IP.""" - resource = 'floatingip' - cmd = fip.CreateFloatingIP(test_cli20.MyApp(sys.stdout), None) - name = 'fip1' - myid = 'myid' - addr = '10.0.0.99' - - args = [name, '--floating-ip-address', addr] - position_values = [name, addr] - position_names = ['floating_network_id', 'floating_ip_address'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_floatingips(self): - """list floatingips: -D.""" - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_floatingips_pagination(self): - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_floatingips_sort(self): - """list floatingips: --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_floatingips_limit(self): - """list floatingips: -P.""" - resources = 'floatingips' - cmd = fip.ListFloatingIP(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_delete_floatingip(self): - """Delete floatingip: fip1.""" - resource = 'floatingip' - cmd = fip.DeleteFloatingIP(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_floatingip(self): - """Show floatingip: --fields id.""" - resource = 'floatingip' - cmd = fip.ShowFloatingIP(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def test_disassociate_ip(self): - """Disassociate floating IP: myid.""" - resource = 'floatingip' - cmd = fip.DisassociateFloatingIP(test_cli20.MyApp(sys.stdout), None) - args = ['myid'] - self._test_update_resource(resource, cmd, 'myid', - args, {"port_id": None} - ) - - def test_associate_ip(self): - """Associate floating IP: myid portid.""" - resource = 'floatingip' - cmd = fip.AssociateFloatingIP(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'portid'] - self._test_update_resource(resource, cmd, 'myid', - args, {"port_id": "portid"} - ) - - -class CLITestV20FloatingIpsXML(CLITestV20FloatingIpsJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_metering.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_metering.py deleted file mode 100644 index 995c29b6fe..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_metering.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (C) 2013 eNovance SAS -# -# Author: Sylvain Afchain -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from neutronclient.neutron.v2_0 import metering -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20MeteringJSON(test_cli20.CLITestV20Base): - def test_create_metering_label(self): - """Create a metering label.""" - resource = 'metering_label' - cmd = metering.CreateMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - name = 'my label' - myid = 'myid' - description = 'my description' - args = [name, '--description', description, '--shared'] - position_names = ['name', 'description', 'shared'] - position_values = [name, description, True] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_metering_labels(self): - resources = "metering_labels" - cmd = metering.ListMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd) - - def test_delete_metering_label(self): - """Delete a metering label.""" - resource = 'metering_label' - cmd = metering.DeleteMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_metering_label(self): - resource = 'metering_label' - cmd = metering.ShowMeteringLabel( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def test_create_metering_label_rule(self): - resource = 'metering_label_rule' - cmd = metering.CreateMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - metering_label_id = 'aaa' - remote_ip_prefix = '10.0.0.0/24' - direction = 'ingress' - args = [metering_label_id, remote_ip_prefix, '--direction', direction, - '--excluded'] - position_names = ['metering_label_id', 'remote_ip_prefix', 'direction', - 'excluded'] - position_values = [metering_label_id, remote_ip_prefix, - direction, True] - self._test_create_resource(resource, cmd, metering_label_id, - myid, args, position_names, position_values) - - def test_list_metering_label_rules(self): - resources = "metering_label_rules" - cmd = metering.ListMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd) - - def test_delete_metering_label_rule(self): - resource = 'metering_label_rule' - cmd = metering.DeleteMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_metering_label_rule(self): - resource = 'metering_label_rule' - cmd = metering.ShowMeteringLabelRule( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - -class CLITestV20MeteringXML(CLITestV20MeteringJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_network.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_network.py deleted file mode 100644 index 1ac49b6375..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_network.py +++ /dev/null @@ -1,577 +0,0 @@ -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import itertools -import sys - -from mox3 import mox -from oslo.serialization import jsonutils - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import network -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20NetworkJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20NetworkJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_network(self): - """Create net: myname.""" - resource = 'network' - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = [name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_network_with_unicode(self): - """Create net: u'\u7f51\u7edc'.""" - resource = 'network' - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - name = u'\u7f51\u7edc' - myid = 'myid' - args = [name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_network_tenant(self): - """Create net: --tenant_id tenantid myname.""" - resource = 'network' - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = ['--tenant_id', 'tenantid', name] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - # Test dashed options - args = ['--tenant-id', 'tenantid', name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_network_provider_args(self): - """Create net: with --provider arguments.""" - resource = 'network' - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - - # Test --provider attributes before network name - args = ['--provider:network_type', 'vlan', - '--provider:physical_network', 'physnet1', - '--provider:segmentation_id', '400', name] - position_names = ['provider:network_type', - 'provider:physical_network', - 'provider:segmentation_id', 'name'] - position_values = ['vlan', 'physnet1', '400', name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_network_tags(self): - """Create net: myname --tags a b.""" - resource = 'network' - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = [name, '--tags', 'a', 'b'] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tags=['a', 'b']) - - def test_create_network_external(self): - """Create net: --router:external myname.""" - resource = 'network' - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = [name, '--router:external'] - position_names = ['name', ] - position_values = [name, ] - external = {'router:external': True} - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - **external) - - def test_create_network_state(self): - """Create net: --admin_state_down myname.""" - resource = 'network' - cmd = network.CreateNetwork(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = ['--admin_state_down', name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - admin_state_up=False) - - # Test dashed options - args = ['--admin-state-down', name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - admin_state_up=False) - - def test_list_nets_empty_with_column(self): - resources = "networks" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - self.mox.StubOutWithMock(network.ListNetwork, "extend_list") - network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg()) - cmd.get_client().MultipleTimes().AndReturn(self.client) - reses = {resources: []} - resstr = self.client.serialize(reses) - # url method body - query = "id=myfakeid" - args = ['-c', 'id', '--', '--id', 'myfakeid'] - path = getattr(self.client, resources + "_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator(test_cli20.end_url(path, query), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', - test_cli20.TOKEN)).AndReturn( - (test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertEqual('\n', _str) - - def _test_list_networks(self, cmd, detail=False, tags=(), - fields_1=(), fields_2=(), page_size=None, - sort_key=(), sort_dir=()): - resources = "networks" - self.mox.StubOutWithMock(network.ListNetwork, "extend_list") - network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg()) - self._test_list_resources(resources, cmd, detail, tags, - fields_1, fields_2, page_size=page_size, - sort_key=sort_key, sort_dir=sort_dir) - - def test_list_nets_pagination(self): - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(network.ListNetwork, "extend_list") - network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg()) - self._test_list_resources_with_pagination("networks", cmd) - - def test_list_nets_sort(self): - """list nets: --sort-key name --sort-key id --sort-dir asc - --sort-dir desc - """ - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, sort_key=['name', 'id'], - sort_dir=['asc', 'desc']) - - def test_list_nets_sort_with_keys_more_than_dirs(self): - """list nets: --sort-key name --sort-key id --sort-dir desc - """ - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, sort_key=['name', 'id'], - sort_dir=['desc']) - - def test_list_nets_sort_with_dirs_more_than_keys(self): - """list nets: --sort-key name --sort-dir desc --sort-dir asc - """ - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, sort_key=['name'], - sort_dir=['desc', 'asc']) - - def test_list_nets_limit(self): - """list nets: -P.""" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, page_size=1000) - - def test_list_nets_detail(self): - """list nets: -D.""" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, True) - - def test_list_nets_tags(self): - """List nets: -- --tags a b.""" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, tags=['a', 'b']) - - def test_list_nets_tags_with_unicode(self): - """List nets: -- --tags u'\u7f51\u7edc'.""" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, tags=[u'\u7f51\u7edc']) - - def test_list_nets_detail_tags(self): - """List nets: -D -- --tags a b.""" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, detail=True, tags=['a', 'b']) - - def _test_list_nets_extend_subnets(self, data, expected): - def setup_list_stub(resources, data, query): - reses = {resources: data} - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, resources + '_path') - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query), self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(resp) - - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(cmd, 'get_client') - self.mox.StubOutWithMock(self.client.httpclient, 'request') - cmd.get_client().AndReturn(self.client) - setup_list_stub('networks', data, '') - cmd.get_client().AndReturn(self.client) - filters = '' - for n in data: - for s in n['subnets']: - filters = filters + "&id=%s" % s - setup_list_stub('subnets', - [{'id': 'mysubid1', 'cidr': '192.168.1.0/24'}, - {'id': 'mysubid2', 'cidr': '172.16.0.0/24'}, - {'id': 'mysubid3', 'cidr': '10.1.1.0/24'}], - query='fields=id&fields=cidr' + filters) - self.mox.ReplayAll() - - args = [] - cmd_parser = cmd.get_parser('list_networks') - parsed_args = cmd_parser.parse_args(args) - result = cmd.get_data(parsed_args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _result = [x for x in result[1]] - self.assertEqual(len(_result), len(expected)) - for res, exp in zip(_result, expected): - self.assertEqual(len(res), len(exp)) - for a, b in zip(res, exp): - self.assertEqual(a, b) - - def test_list_nets_extend_subnets(self): - data = [{'id': 'netid1', 'name': 'net1', 'subnets': ['mysubid1']}, - {'id': 'netid2', 'name': 'net2', 'subnets': ['mysubid2', - 'mysubid3']}] - # id, name, subnets - expected = [('netid1', 'net1', 'mysubid1 192.168.1.0/24'), - ('netid2', 'net2', - 'mysubid2 172.16.0.0/24\nmysubid3 10.1.1.0/24')] - self._test_list_nets_extend_subnets(data, expected) - - def test_list_nets_extend_subnets_no_subnet(self): - data = [{'id': 'netid1', 'name': 'net1', 'subnets': ['mysubid1']}, - {'id': 'netid2', 'name': 'net2', 'subnets': ['mysubid4']}] - # id, name, subnets - expected = [('netid1', 'net1', 'mysubid1 192.168.1.0/24'), - ('netid2', 'net2', 'mysubid4 ')] - self._test_list_nets_extend_subnets(data, expected) - - def test_list_nets_fields(self): - """List nets: --fields a --fields b -- --fields c d.""" - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_networks(cmd, - fields_1=['a', 'b'], fields_2=['c', 'd']) - - def _test_list_nets_columns(self, cmd, returned_body, - args=('-f', 'json')): - resources = 'networks' - self.mox.StubOutWithMock(network.ListNetwork, "extend_list") - network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg()) - self._test_list_columns(cmd, resources, returned_body, args=args) - - def test_list_nets_defined_column(self): - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - returned_body = {"networks": [{"name": "buildname3", - "id": "id3", - "tenant_id": "tenant_3", - "subnets": []}]} - self._test_list_nets_columns(cmd, returned_body, - args=['-f', 'json', '-c', 'id']) - _str = self.fake_stdout.make_string() - returned_networks = jsonutils.loads(_str) - self.assertEqual(1, len(returned_networks)) - net = returned_networks[0] - self.assertEqual(1, len(net)) - self.assertIn("id", net.keys()) - - def test_list_nets_with_default_column(self): - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - returned_body = {"networks": [{"name": "buildname3", - "id": "id3", - "tenant_id": "tenant_3", - "subnets": []}]} - self._test_list_nets_columns(cmd, returned_body) - _str = self.fake_stdout.make_string() - returned_networks = jsonutils.loads(_str) - self.assertEqual(1, len(returned_networks)) - net = returned_networks[0] - self.assertEqual(3, len(net)) - self.assertEqual(0, len(set(net) ^ set(cmd.list_columns))) - - def test_list_external_nets_empty_with_column(self): - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - self.mox.StubOutWithMock(network.ListNetwork, "extend_list") - network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg()) - cmd.get_client().MultipleTimes().AndReturn(self.client) - reses = {resources: []} - resstr = self.client.serialize(reses) - # url method body - query = "router%3Aexternal=True&id=myfakeid" - args = ['-c', 'id', '--', '--id', 'myfakeid'] - path = getattr(self.client, resources + "_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query), self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', - test_cli20.TOKEN)).AndReturn( - (test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - self.assertEqual('\n', _str) - - def _test_list_external_nets(self, resources, cmd, - detail=False, tags=(), - fields_1=(), fields_2=()): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - self.mox.StubOutWithMock(network.ListNetwork, "extend_list") - network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg()) - cmd.get_client().MultipleTimes().AndReturn(self.client) - reses = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }, ], } - - resstr = self.client.serialize(reses) - - # url method body - query = "" - args = detail and ['-D', ] or [] - if fields_1: - for field in fields_1: - args.append('--fields') - args.append(field) - if tags: - args.append('--') - args.append("--tag") - for tag in tags: - args.append(tag) - if (not tags) and fields_2: - args.append('--') - if fields_2: - args.append("--fields") - for field in fields_2: - args.append(field) - for field in itertools.chain(fields_1, fields_2): - if query: - query += "&fields=" + field - else: - query = "fields=" + field - if query: - query += '&router%3Aexternal=True' - else: - query += 'router%3Aexternal=True' - for tag in tags: - if query: - query += "&tag=" + tag - else: - query = "tag=" + tag - if detail: - query = query and query + '&verbose=True' or 'verbose=True' - path = getattr(self.client, resources + "_path") - - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query), self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - - self.assertIn('myid1', _str) - - def test_list_external_nets_detail(self): - """list external nets: -D.""" - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, cmd, True) - - def test_list_external_nets_tags(self): - """List external nets: -- --tags a b.""" - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, - cmd, tags=['a', 'b']) - - def test_list_external_nets_detail_tags(self): - """List external nets: -D -- --tags a b.""" - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, cmd, - detail=True, tags=['a', 'b']) - - def test_list_externel_nets_fields(self): - """List external nets: --fields a --fields b -- --fields c d.""" - resources = "networks" - cmd = network.ListExternalNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_list_external_nets(resources, cmd, - fields_1=['a', 'b'], - fields_2=['c', 'd']) - - def test_update_network_exception(self): - """Update net: myid.""" - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self.assertRaises(exceptions.CommandError, self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_update_network(self): - """Update net: myid --name myname --tags a b.""" - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], } - ) - - def test_update_network_with_unicode(self): - """Update net: myid --name u'\u7f51\u7edc' --tags a b.""" - resource = 'network' - cmd = network.UpdateNetwork(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', u'\u7f51\u7edc', - '--tags', 'a', 'b'], - {'name': u'\u7f51\u7edc', - 'tags': ['a', 'b'], } - ) - - def test_show_network(self): - """Show net: --fields id --fields name myid.""" - resource = 'network' - cmd = network.ShowNetwork(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_delete_network(self): - """Delete net: myid.""" - resource = 'network' - cmd = network.DeleteNetwork(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def _test_extend_list(self, mox_calls): - data = [{'id': 'netid%d' % i, 'name': 'net%d' % i, - 'subnets': ['mysubid%d' % i]} - for i in range(10)] - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, 'subnets_path') - cmd = network.ListNetwork(test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(cmd, "get_client") - cmd.get_client().MultipleTimes().AndReturn(self.client) - mox_calls(path, data) - self.mox.ReplayAll() - known_args, _vs = cmd.get_parser('create_subnets').parse_known_args() - cmd.extend_list(data, known_args) - self.mox.VerifyAll() - - def _build_test_data(self, data): - subnet_ids = [] - response = [] - filters = "" - for n in data: - if 'subnets' in n: - subnet_ids.extend(n['subnets']) - for subnet_id in n['subnets']: - filters = "%s&id=%s" % (filters, subnet_id) - response.append({'id': subnet_id, - 'cidr': '192.168.0.0/16'}) - resp_str = self.client.serialize({'subnets': response}) - resp = (test_cli20.MyResp(200), resp_str) - return filters, resp - - def test_extend_list(self): - def mox_calls(path, data): - filters, response = self._build_test_data(data) - self.client.httpclient.request( - test_cli20.MyUrlComparator(test_cli20.end_url( - path, 'fields=id&fields=cidr' + filters), self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(response) - - self._test_extend_list(mox_calls) - - def test_extend_list_exceed_max_uri_len(self): - def mox_calls(path, data): - sub_data_lists = [data[:len(data) - 1], data[len(data) - 1:]] - filters, response = self._build_test_data(data) - - # 1 char of extra URI len will cause a split in 2 requests - self.mox.StubOutWithMock(self.client.httpclient, - "_check_uri_length") - self.client.httpclient._check_uri_length(mox.IgnoreArg()).AndRaise( - exceptions.RequestURITooLong(excess=1)) - - for data in sub_data_lists: - filters, response = self._build_test_data(data) - self.client.httpclient._check_uri_length( - mox.IgnoreArg()).AndReturn(None) - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url( - path, 'fields=id&fields=cidr%s' % filters), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(response) - - self._test_extend_list(mox_calls) - - -class CLITestV20NetworkXML(CLITestV20NetworkJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_networkprofile.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_networkprofile.py deleted file mode 100644 index 8b955ed668..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_networkprofile.py +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright 2013 Cisco Systems Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Kyle Mestery, Cisco Systems, Inc. -# - -import sys - -from neutronclient.neutron.v2_0 import networkprofile -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20NetworkProfile(test_cli20.CLITestV20Base): - - def test_create_networkprofile(self): - """Create networkprofile: myid.""" - resource = 'network_profile' - cmd = networkprofile.CreateNetworkProfile(test_cli20. - MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - segment_type = 'vlan' - args = [name, segment_type] - position_names = ['name', 'segment_type'] - position_values = [name, segment_type] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_networkprofile_detail(self): - """List networkprofile: -D.""" - resources = 'network_profiles' - cmd = networkprofile.ListNetworkProfile(test_cli20.MyApp(sys.stdout), - None) - contents = [{'name': 'myname', 'segment_type': 'vlan'}] - self._test_list_resources(resources, cmd, True, - response_contents=contents) - - def test_list_networkprofile_known_option_after_unknown(self): - """List networkprofile: -- --tags a b --request-format xml.""" - resources = 'network_profiles' - cmd = networkprofile.ListNetworkProfile(test_cli20.MyApp(sys.stdout), - None) - contents = [{'name': 'myname', 'segment_type': 'vlan'}] - self._test_list_resources(resources, cmd, tags=['a', 'b'], - response_contents=contents) - - def test_list_networkprofile_fields(self): - """List networkprofile: --fields a --fields b -- --fields c d.""" - resources = 'network_profiles' - cmd = networkprofile.ListNetworkProfile(test_cli20.MyApp(sys.stdout), - None) - contents = [{'name': 'myname', 'segment_type': 'vlan'}] - self._test_list_resources(resources, cmd, - fields_1=['a', 'b'], fields_2=['c', 'd'], - response_contents=contents) - - def test_show_networkprofile(self): - """Show networkprofile: --fields id --fields name myid.""" - resource = 'network_profile' - cmd = networkprofile.ShowNetworkProfile(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_delete_networkprofile(self): - """Delete networkprofile: myid.""" - resource = 'network_profile' - cmd = networkprofile.DeleteNetworkProfile(test_cli20. - MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_create_networkprofile_trunk(self): - """Create networkprofile: myid.""" - resource = 'network_profile' - cmd = networkprofile.CreateNetworkProfile(test_cli20. - MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - segment_type = 'trunk' - args = [name, segment_type, '--sub_type', 'vlan'] - position_names = ['name', 'segment_type', ] - position_values = [name, segment_type, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - sub_type='vlan') - - def test_list_networkprofile_trunk_detail(self): - """List networkprofile: -D.""" - resources = 'network_profiles' - cmd = networkprofile.ListNetworkProfile(test_cli20.MyApp(sys.stdout), - None) - contents = [{'name': 'myname', 'segment_type': 'trunk', - '--sub_type': 'vlan'}] - self._test_list_resources(resources, cmd, True, - response_contents=contents) - - def test_create_networkprofile_multi_tenants(self): - """Create networkprofile with mulitple tenants: myid.""" - resource = 'network_profile' - cmd = networkprofile.CreateNetworkProfile(test_cli20. - MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - segment_type = 'vlan' - args = [name, segment_type, '--add-tenant', 'demo', - '--add-tenant', 'admin'] - position_names = ['name', 'segment_type', 'add_tenants'] - position_values = [name, segment_type, ['demo', 'admin']] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_update_networkprofile_multi_tenants(self): - resource = 'network_profile' - cmd = networkprofile.UpdateNetworkProfile(test_cli20. - MyApp(sys.stdout), None) - args = ['myid', '--add-tenant', 'service', '--add-tenant', 'demo', - '--remove-tenant', 'demo'] - extrafields = {'add_tenants': ['service', 'demo'], - 'remove_tenants': ['demo']} - self._test_update_resource(resource, cmd, 'myid', args, extrafields) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nsx_networkgateway.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nsx_networkgateway.py deleted file mode 100644 index 0d77d4ddf9..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nsx_networkgateway.py +++ /dev/null @@ -1,265 +0,0 @@ -# Copyright 2012 VMware, Inc -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import sys - -from mox3 import mox -import six - -from neutronclient.neutron.v2_0.nsx import networkgateway as nwgw -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20NetworkGatewayJSON(test_cli20.CLITestV20Base): - - gw_resource = "network_gateway" - dev_resource = "gateway_device" - - def setUp(self): - super(CLITestV20NetworkGatewayJSON, self).setUp( - plurals={'devices': 'device', - 'network_gateways': 'network_gateway'}) - - def test_create_gateway(self): - cmd = nwgw.CreateNetworkGateway(test_cli20.MyApp(sys.stdout), None) - name = 'gw-test' - myid = 'myid' - args = [name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(self.gw_resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_gateway_with_tenant(self): - cmd = nwgw.CreateNetworkGateway(test_cli20.MyApp(sys.stdout), None) - name = 'gw-test' - myid = 'myid' - args = ['--tenant_id', 'tenantid', name] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(self.gw_resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_gateway_with_device(self): - cmd = nwgw.CreateNetworkGateway(test_cli20.MyApp(sys.stdout), None) - name = 'gw-test' - myid = 'myid' - args = ['--device', 'device_id=test', name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(self.gw_resource, cmd, name, myid, args, - position_names, position_values, - devices=[{'device_id': 'test'}]) - - def test_list_gateways(self): - resources = '%ss' % self.gw_resource - cmd = nwgw.ListNetworkGateway(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_update_gateway(self): - cmd = nwgw.UpdateNetworkGateway(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(self.gw_resource, cmd, 'myid', - ['myid', '--name', 'higuain'], - {'name': 'higuain'}) - - def test_delete_gateway(self): - cmd = nwgw.DeleteNetworkGateway(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(self.gw_resource, cmd, myid, args) - - def test_show_gateway(self): - cmd = nwgw.ShowNetworkGateway(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(self.gw_resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_connect_network_to_gateway(self): - cmd = nwgw.ConnectNetworkGateway(test_cli20.MyApp(sys.stdout), None) - args = ['gw_id', 'net_id', - '--segmentation-type', 'edi', - '--segmentation-id', '7'] - self._test_update_resource_action(self.gw_resource, cmd, 'gw_id', - 'connect_network', - args, - {'network_id': 'net_id', - 'segmentation_type': 'edi', - 'segmentation_id': '7'}) - - def test_disconnect_network_from_gateway(self): - cmd = nwgw.DisconnectNetworkGateway(test_cli20.MyApp(sys.stdout), None) - args = ['gw_id', 'net_id', - '--segmentation-type', 'edi', - '--segmentation-id', '7'] - self._test_update_resource_action(self.gw_resource, cmd, 'gw_id', - 'disconnect_network', - args, - {'network_id': 'net_id', - 'segmentation_type': 'edi', - 'segmentation_id': '7'}) - - def _test_create_gateway_device(self, - name, - connector_type, - connector_ip, - client_certificate=None, - client_certificate_file=None, - must_raise=False): - cmd = nwgw.CreateGatewayDevice(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - extra_body = {'connector_type': connector_type, - 'connector_ip': connector_ip, - 'client_certificate': client_certificate} - self.mox.StubOutWithMock(nwgw, 'read_cert_file') - if client_certificate_file: - nwgw.read_cert_file(mox.IgnoreArg()).AndReturn('xyz') - extra_body['client_certificate'] = 'xyz' - self.mox.ReplayAll() - position_names = ['name', ] - position_values = [name, ] - args = [] - for (k, v) in six.iteritems(extra_body): - if (k == 'client_certificate' and client_certificate_file): - v = client_certificate_file - k = 'client_certificate_file' - # Append argument only if value for it was specified - if v: - args.extend(['--%s' % k.replace('_', '-'), v]) - # The following is just for verifying the call fails as expected when - # both certificate and certificate file are specified. The extra - # argument added is client-certificate since the loop above added - # client-certificate-file - if client_certificate_file and client_certificate: - args.extend(['--client-certificate', client_certificate_file]) - args.append(name) - if must_raise: - with test_cli20.capture_std_streams(): - self.assertRaises( - SystemExit, self._test_create_resource, - self.dev_resource, cmd, name, myid, args, - position_names, position_values, extra_body=extra_body) - else: - self._test_create_resource( - self.dev_resource, cmd, name, myid, args, - position_names, position_values, extra_body=extra_body) - self.mox.UnsetStubs() - - def test_create_gateway_device(self): - self._test_create_gateway_device('dev_test', 'stt', '1.1.1.1', 'xyz') - - def test_create_gateway_device_with_certfile(self): - self._test_create_gateway_device('dev_test', 'stt', '1.1.1.1', - client_certificate_file='some_file') - - def test_create_gateway_device_invalid_connector_type_fails(self): - self._test_create_gateway_device('dev_test', 'ciccio', - '1.1.1.1', client_certificate='xyz', - must_raise=True) - - def test_create_gateway_device_missing_connector_ip_fails(self): - self._test_create_gateway_device('dev_test', 'stt', - None, client_certificate='xyz', - must_raise=True) - - def test_create_gateway_device_missing_certificates_fails(self): - self._test_create_gateway_device('dev_test', 'stt', '1.1.1.1', - must_raise=True) - - def test_create_gateway_device_with_cert_and_cert_file_fails(self): - self._test_create_gateway_device('dev_test', 'stt', '1.1.1.1', - client_certificate='xyz', - client_certificate_file='some_file', - must_raise=True) - - def _test_update_gateway_device(self, - name=None, - connector_type=None, - connector_ip=None, - client_certificate=None, - client_certificate_file=None, - must_raise=False): - cmd = nwgw.UpdateGatewayDevice(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - extra_body = {} - self.mox.StubOutWithMock(nwgw, 'read_cert_file') - if client_certificate_file: - nwgw.read_cert_file(mox.IgnoreArg()).AndReturn('xyz') - self.mox.ReplayAll() - args = [myid] - - def process_arg(argname, arg): - if arg: - extra_body[argname] = arg - args.extend(['--%s' % argname.replace('_', '-'), arg]) - - process_arg('name', name) - process_arg('connector_type', connector_type) - process_arg('connector_ip', connector_ip) - process_arg('client_certificate', client_certificate) - if client_certificate_file: - extra_body['client_certificate'] = 'xyz' - args.extend(['--client-certificate-file', - client_certificate_file]) - if must_raise: - with test_cli20.capture_std_streams(): - self.assertRaises( - SystemExit, self._test_update_resource, - self.dev_resource, cmd, myid, args, - extrafields=extra_body) - else: - self._test_update_resource( - self.dev_resource, cmd, myid, args, - extrafields=extra_body) - self.mox.UnsetStubs() - - def test_update_gateway_device(self): - self._test_update_gateway_device('dev_test', 'stt', '1.1.1.1', 'xyz') - - def test_update_gateway_device_partial_body(self): - self._test_update_gateway_device(name='dev_test', - connector_type='stt') - - def test_update_gateway_device_with_certfile(self): - self._test_update_gateway_device('dev_test', 'stt', '1.1.1.1', - client_certificate_file='some_file') - - def test_update_gateway_device_invalid_connector_type_fails(self): - self._test_update_gateway_device('dev_test', 'ciccio', - '1.1.1.1', client_certificate='xyz', - must_raise=True) - - def test_update_gateway_device_with_cert_and_cert_file_fails(self): - self._test_update_gateway_device('dev_test', 'stt', '1.1.1.1', - client_certificate='xyz', - client_certificate_file='some_file', - must_raise=True) - - def test_delete_gateway_device(self): - cmd = nwgw.DeleteGatewayDevice(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(self.dev_resource, cmd, myid, args) - - def test_show_gateway_device(self): - cmd = nwgw.ShowGatewayDevice(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(self.dev_resource, cmd, self.test_id, args, - ['id', 'name']) - - -class CLITestV20NetworkGatewayXML(CLITestV20NetworkGatewayJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nsx_queue.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nsx_queue.py deleted file mode 100644 index f650873473..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nsx_queue.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -# Copyright 2013 VMware Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from neutronclient.neutron.v2_0.nsx import qos_queue as qos -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20QosQueueJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20QosQueueJSON, self).setUp( - plurals={'qos_queues': 'qos_queue'}) - - def test_create_qos_queue(self): - """Create a qos queue.""" - resource = 'qos_queue' - cmd = qos.CreateQoSQueue( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - name = 'my_queue' - default = False - args = ['--default', default, name] - position_names = ['name', 'default'] - position_values = [name, default] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_qos_queue_all_values(self): - """Create a qos queue.""" - resource = 'qos_queue' - cmd = qos.CreateQoSQueue( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - name = 'my_queue' - default = False - min = '10' - max = '40' - qos_marking = 'untrusted' - dscp = '0' - args = ['--default', default, '--min', min, '--max', max, - '--qos-marking', qos_marking, '--dscp', dscp, name] - position_names = ['name', 'default', 'min', 'max', 'qos_marking', - 'dscp'] - position_values = [name, default, min, max, qos_marking, dscp] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_qos_queue(self): - resources = "qos_queues" - cmd = qos.ListQoSQueue( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_show_qos_queue_id(self): - resource = 'qos_queue' - cmd = qos.ShowQoSQueue( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def test_delete_qos_queue(self): - resource = 'qos_queue' - cmd = qos.DeleteQoSQueue( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - -class CLITestV20QosQueueXML(CLITestV20QosQueueJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nuage_netpartition.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nuage_netpartition.py deleted file mode 100644 index b62d296889..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_nuage_netpartition.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2014 Alcatel-Lucent USA Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Ronak Shah, Nuage Networks, Alcatel-Lucent USA Inc. - -import sys - -from neutronclient.neutron.v2_0 import netpartition -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20NetPartitionJSON(test_cli20.CLITestV20Base): - resource = 'net_partition' - - def test_create_netpartition(self): - cmd = netpartition.CreateNetPartition(test_cli20.MyApp(sys.stdout), - None) - name = 'myname' - myid = 'myid' - args = [name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(self.resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_netpartitions(self): - resources = '%ss' % self.resource - cmd = netpartition.ListNetPartition(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_show_netpartition(self): - cmd = netpartition.ShowNetPartition(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(self.resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_delete_netpartition(self): - cmd = netpartition.DeleteNetPartition(test_cli20.MyApp(sys.stdout), - None) - myid = 'myid' - args = [myid] - self._test_delete_resource(self.resource, cmd, myid, args) - - -class CLITestV20NetPartitionXML(CLITestV20NetPartitionJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_packetfilter.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_packetfilter.py deleted file mode 100644 index dcb190e1ce..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_packetfilter.py +++ /dev/null @@ -1,298 +0,0 @@ -# Copyright 2014 NEC Corporation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from mox3 import mox - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.nec import packetfilter as pf -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20PacketFilterJSON(test_cli20.CLITestV20Base): - def test_create_packetfilter_with_mandatory_params(self): - """Create packetfilter: packetfilter1.""" - resource = 'packet_filter' - cmd = pf.CreatePacketFilter(test_cli20.MyApp(sys.stdout), None) - name = 'packetfilter1' - myid = 'myid' - args = ['--priority', '30000', '--action', 'allow', 'net1'] - position_names = ['network_id', 'action', 'priority'] - position_values = ['net1', 'allow', '30000'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_packetfilter_with_all_params(self): - """Create packetfilter: packetfilter1.""" - resource = 'packet_filter' - cmd = pf.CreatePacketFilter(test_cli20.MyApp(sys.stdout), None) - name = 'packetfilter1' - myid = 'myid' - args = ['--name', name, - '--admin-state-down', - '--in-port', 'port1', - '--src-mac', '00:11:22:33:44:55', - '--dst-mac', 'aa:bb:cc:dd:ee:ff', - '--eth-type', '0x0800', - '--protocol', 'tcp', - '--src-cidr', '10.1.1.0/24', - '--dst-cidr', '10.2.2.0/24', - '--src-port', '40001', - '--dst-port', '4000', - '--priority', '30000', - '--action', 'drop', 'net1'] - params = {'network_id': 'net1', - 'action': 'drop', - 'priority': '30000', - 'name': name, - 'admin_state_up': False, - 'in_port': 'port1', - 'src_mac': '00:11:22:33:44:55', - 'dst_mac': 'aa:bb:cc:dd:ee:ff', - 'eth_type': '0x0800', - 'protocol': 'tcp', - 'src_cidr': '10.1.1.0/24', - 'dst_cidr': '10.2.2.0/24', - 'src_port': '40001', - 'dst_port': '4000', - } - position_names = sorted(params) - position_values = [params[k] for k in sorted(params)] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_packetfilters_detail(self): - """list packetfilters: -D.""" - resources = "packet_filters" - cmd = pf.ListPacketFilter(test_cli20.MyApp(sys.stdout), None) - response_contents = [{'id': 'myid1', 'network_id': 'net1'}, - {'id': 'myid2', 'network_id': 'net2'}] - self._test_list_resources(resources, cmd, True, - response_contents=response_contents) - - def _stubout_extend_list(self): - self.mox.StubOutWithMock(pf.ListPacketFilter, "extend_list") - pf.ListPacketFilter.extend_list(mox.IsA(list), mox.IgnoreArg()) - - def test_list_packetfilters_pagination(self): - resources = "packet_filters" - cmd = pf.ListPacketFilter(test_cli20.MyApp(sys.stdout), None) - self._stubout_extend_list() - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_packetfilters_sort(self): - """list packetfilters: --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "packet_filters" - cmd = pf.ListPacketFilter(test_cli20.MyApp(sys.stdout), None) - self._stubout_extend_list() - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_packetfilters_limit(self): - """list packetfilters: -P.""" - resources = "packet_filters" - cmd = pf.ListPacketFilter(test_cli20.MyApp(sys.stdout), None) - self._stubout_extend_list() - self._test_list_resources(resources, cmd, page_size=1000) - - def test_update_packetfilter(self): - """Update packetfilter: myid --name myname --tags a b.""" - resource = 'packet_filter' - cmd = pf.UpdatePacketFilter(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname'], - {'name': 'myname'} - ) - - def test_update_packetfilter_with_all_params(self): - resource = 'packet_filter' - cmd = pf.UpdatePacketFilter(test_cli20.MyApp(sys.stdout), None) - name = 'packetfilter1' - args = ['--name', name, - '--admin-state', 'True', - '--src-mac', '00:11:22:33:44:55', - '--dst-mac', 'aa:bb:cc:dd:ee:ff', - '--eth-type', '0x0800', - '--protocol', 'tcp', - '--src-cidr', '10.1.1.0/24', - '--dst-cidr', '10.2.2.0/24', - '--src-port', '40001', - '--dst-port', '4000', - '--priority', '30000', - '--action', 'drop', - 'myid' - ] - params = {'action': 'drop', - 'priority': '30000', - 'name': name, - 'admin_state_up': True, - 'src_mac': '00:11:22:33:44:55', - 'dst_mac': 'aa:bb:cc:dd:ee:ff', - 'eth_type': '0x0800', - 'protocol': 'tcp', - 'src_cidr': '10.1.1.0/24', - 'dst_cidr': '10.2.2.0/24', - 'src_port': '40001', - 'dst_port': '4000', - } - # position_names = sorted(params) - # position_values = [params[k] for k in sorted(params)] - self._test_update_resource(resource, cmd, 'myid', - args, params) - - def test_update_packetfilter_admin_state_false(self): - resource = 'packet_filter' - cmd = pf.UpdatePacketFilter(test_cli20.MyApp(sys.stdout), None) - args = ['--admin-state', 'False', 'myid'] - params = {'admin_state_up': False} - self._test_update_resource(resource, cmd, 'myid', - args, params) - - def test_update_packetfilter_exception(self): - """Update packetfilter: myid.""" - resource = 'packet_filter' - cmd = pf.UpdatePacketFilter(test_cli20.MyApp(sys.stdout), None) - exc = self.assertRaises(exceptions.CommandError, - self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - self.assertEqual('Must specify new values to update packet_filter', - str(exc)) - - def test_delete_packetfilter(self): - """Delete packetfilter: myid.""" - resource = 'packet_filter' - cmd = pf.DeletePacketFilter(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_packetfilter(self): - """Show packetfilter: myid.""" - resource = 'packet_filter' - cmd = pf.ShowPacketFilter(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - -class CLITestV20PacketFilterXML(CLITestV20PacketFilterJSON): - format = 'xml' - - -class CLITestV20PacketFilterValidateParam(test_cli20.CLITestV20Base): - def _test_create_packetfilter_pass_validation(self, cmdline=None, - params=None, base_args=None): - resource = 'packet_filter' - cmd = pf.CreatePacketFilter(test_cli20.MyApp(sys.stdout), None) - name = 'packetfilter1' - myid = 'myid' - if base_args is None: - args = '--priority 30000 --action allow net1'.split() - else: - args = base_args.split() - if cmdline: - args += cmdline.split() - _params = {'network_id': 'net1', - 'action': 'allow', - 'priority': '30000'} - if params: - _params.update(params) - position_names = sorted(_params) - position_values = [_params[k] for k in sorted(_params)] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def _test_create_packetfilter_negative_validation(self, cmdline): - resource = 'packet_filter' - cmd = pf.CreatePacketFilter(test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - cmd_parser = cmd.get_parser('create_' + resource) - args = cmdline.split() - self.assertRaises(exceptions.CommandError, - shell.run_command, - cmd, cmd_parser, args) - - def test_create_pf_hex_priority(self): - self._test_create_packetfilter_pass_validation( - base_args='--priority 0xffff --action allow net1', - params={'priority': '0xffff'}) - - def test_create_pf_hex_src_port(self): - self._test_create_packetfilter_pass_validation( - cmdline='--src-port 0xffff', params={'src_port': '0xffff'}) - - def test_create_pf_hex_dst_port(self): - self._test_create_packetfilter_pass_validation( - cmdline='--dst-port 0xffff', params={'dst_port': '0xffff'}) - - def test_create_pf_ip_proto_zero(self): - self._test_create_packetfilter_pass_validation( - cmdline='--protocol 0', params={'protocol': '0'}) - - def test_create_pf_ip_proto_max_hex(self): - self._test_create_packetfilter_pass_validation( - cmdline='--protocol 0xff', params={'protocol': '0xff'}) - - def test_create_pf_ip_proto_with_names(self): - for proto in ['tcp', 'xxxx']: - self._test_create_packetfilter_pass_validation( - cmdline='--protocol ' + proto, params={'protocol': proto}) - - def test_create_pf_negative_priority(self): - self._test_create_packetfilter_negative_validation( - '--priority -1 --action allow net1') - - def test_create_pf_too_big_priority(self): - self._test_create_packetfilter_negative_validation( - '--priority 65536 --action allow net1') - - def test_create_pf_negative_src_port(self): - self._test_create_packetfilter_negative_validation( - '--src-port -1 --priority 20000 --action allow net1') - - def test_create_pf_too_big_src_port(self): - self._test_create_packetfilter_negative_validation( - '--src-port 65536 --priority 20000 --action allow net1') - - def test_create_pf_negative_dst_port(self): - self._test_create_packetfilter_negative_validation( - '--dst-port -1 --priority 20000 --action allow net1') - - def test_create_pf_too_big_dst_port(self): - self._test_create_packetfilter_negative_validation( - '--dst-port 65536 --priority 20000 --action allow net1') - - def test_create_pf_negative_protocol(self): - self._test_create_packetfilter_negative_validation( - '--protocol -1 --priority 20000 --action allow net1') - - def test_create_pf_too_big_hex_protocol(self): - self._test_create_packetfilter_negative_validation( - '--protocol 0x100 --priority 20000 --action allow net1') - - def test_create_pf_invalid_src_cidr(self): - self._test_create_packetfilter_negative_validation( - '--src-cidr invalid --priority 20000 --action allow net1') - - def test_create_pf_invalid_dst_cidr(self): - self._test_create_packetfilter_negative_validation( - '--dst-cidr invalid --priority 20000 --action allow net1') diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_policyprofile.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_policyprofile.py deleted file mode 100644 index 791b840ba2..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_policyprofile.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2013 Cisco Systems Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Kyle Mestery, Cisco Systems, Inc. -# - -import sys - -from neutronclient.neutron.v2_0 import policyprofile -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20PolicyProfile(test_cli20.CLITestV20Base): - - def test_list_policyprofile_detail(self): - """List policyprofile: -D.""" - resources = 'policy_profiles' - cmd = policyprofile.ListPolicyProfile(test_cli20.MyApp(sys.stdout), - None) - contents = [{'name': 'myname', 'segment_type': 'vlan'}] - self._test_list_resources(resources, cmd, True, - response_contents=contents) - - def test_list_policyprofile_known_option_after_unknown(self): - """List policyprofile: -- --tags a b --request-format xml.""" - resources = 'policy_profiles' - cmd = policyprofile.ListPolicyProfile(test_cli20.MyApp(sys.stdout), - None) - contents = [{'name': 'myname', 'segment_type': 'vlan'}] - self._test_list_resources(resources, cmd, tags=['a', 'b'], - response_contents=contents) - - def test_list_policyprofile_fields(self): - """List policyprofile: --fields a --fields b -- --fields c d.""" - resources = 'policy_profiles' - cmd = policyprofile.ListPolicyProfile(test_cli20.MyApp(sys.stdout), - None) - contents = [{'name': 'myname', 'segment_type': 'vlan'}] - self._test_list_resources(resources, cmd, - fields_1=['a', 'b'], fields_2=['c', 'd'], - response_contents=contents) - - def test_show_policyprofile(self): - """Show policyprofile: --fields id --fields name myid.""" - resource = 'policy_profile' - cmd = policyprofile.ShowPolicyProfile(test_cli20.MyApp(sys.stdout), - None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def test_update_policyprofile(self): - """Update policyprofile: myid --name myname --tags a b.""" - resource = 'policy_profile' - cmd = policyprofile.UpdatePolicyProfile(test_cli20.MyApp(sys.stdout), - None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], } - ) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_port.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_port.py deleted file mode 100644 index cda9657e24..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_port.py +++ /dev/null @@ -1,511 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import itertools -import sys - -from mox3 import mox - -from neutronclient.neutron.v2_0 import port -from neutronclient import shell -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20PortJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20PortJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_port(self): - """Create port: netid.""" - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = [netid] - position_names = ['network_id'] - position_values = [] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_extra_dhcp_opts_args(self): - """Create port: netid --extra_dhcp_opt.""" - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - extra_dhcp_opts = [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0'}, - {'opt_name': 'tftp-server', - 'opt_value': '123.123.123.123'}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45'}] - args = [netid] - for dhcp_opt in extra_dhcp_opts: - args += ['--extra-dhcp-opt', - ('opt_name=%(opt_name)s,opt_value=%(opt_value)s' % - dhcp_opt)] - position_names = ['network_id', 'extra_dhcp_opts'] - position_values = [netid, extra_dhcp_opts] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_extra_dhcp_opts_args_ip_version(self): - """Create port: netid --extra_dhcp_opt.""" - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - extra_dhcp_opts = [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0', - 'ip_version': "4"}, - {'opt_name': 'tftp-server', - 'opt_value': '2001:192:168::1', - 'ip_version': "6"}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45', - 'ip_version': "4"}] - args = [netid] - for dhcp_opt in extra_dhcp_opts: - args += ['--extra-dhcp-opt', - ('opt_name=%(opt_name)s,opt_value=%(opt_value)s,' - 'ip_version=%(ip_version)s' % - dhcp_opt)] - position_names = ['network_id', 'extra_dhcp_opts'] - position_values = [netid, extra_dhcp_opts] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_full(self): - """Create port: --mac_address mac --device_id deviceid netid.""" - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--mac_address', 'mac', '--device_id', 'deviceid', netid] - position_names = ['network_id', 'mac_address', 'device_id'] - position_values = [netid, 'mac', 'deviceid'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - # Test dashed options - args = ['--mac-address', 'mac', '--device-id', 'deviceid', netid] - position_names = ['network_id', 'mac_address', 'device_id'] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_tenant(self): - """Create port: --tenant_id tenantid netid.""" - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--tenant_id', 'tenantid', netid, ] - position_names = ['network_id'] - position_values = [] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - # Test dashed options - args = ['--tenant-id', 'tenantid', netid, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_port_tags(self): - """Create port: netid mac_address device_id --tags a b.""" - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = [netid, '--tags', 'a', 'b'] - position_names = ['network_id'] - position_values = [] - position_values.extend([netid]) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tags=['a', 'b']) - - def test_create_port_secgroup(self): - """Create port: --security-group sg1_id netid.""" - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--security-group', 'sg1_id', netid] - position_names = ['network_id', 'security_groups'] - position_values = [netid, ['sg1_id']] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_secgroups(self): - """Create port: netid - - The are - --security-group sg1_id --security-group sg2_id - """ - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--security-group', 'sg1_id', - '--security-group', 'sg2_id', - netid] - position_names = ['network_id', 'security_groups'] - position_values = [netid, ['sg1_id', 'sg2_id']] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_secgroup_off(self): - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = ['--no-security-group', netid] - position_names = ['network_id', 'security_groups'] - position_values = [netid, []] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_port_secgroups_list(self): - """Create port: netid - The are - --security-groups list=true sg_id1 sg_id2 - """ - resource = 'port' - cmd = port.CreatePort(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - args = [netid, '--security-groups', 'list=true', 'sg_id1', 'sg_id2'] - position_names = ['network_id', 'security_groups'] - position_values = [netid, ['sg_id1', 'sg_id2']] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_ports(self): - """List ports: -D.""" - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_ports_pagination(self): - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ports_sort(self): - """list ports: --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ports_limit(self): - """list ports: -P.""" - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_list_ports_tags(self): - """List ports: -- --tags a b.""" - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, tags=['a', 'b']) - - def test_list_ports_detail_tags(self): - """List ports: -D -- --tags a b.""" - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, detail=True, tags=['a', 'b']) - - def test_list_ports_fields(self): - """List ports: --fields a --fields b -- --fields c d.""" - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - fields_1=['a', 'b'], fields_2=['c', 'd']) - - def test_list_ports_with_fixed_ips_in_csv(self): - """List ports: -f csv.""" - resources = "ports" - cmd = port.ListPort(test_cli20.MyApp(sys.stdout), None) - fixed_ips = [{"subnet_id": "30422057-d6df-4c90-8314-aefb5e326666", - "ip_address": "10.0.0.12"}, - {"subnet_id": "30422057-d6df-4c90-8314-aefb5e326666", - "ip_address": "10.0.0.4"}] - contents = [{'name': 'name1', 'fixed_ips': fixed_ips}] - self._test_list_resources(resources, cmd, True, - response_contents=contents, - output_format='csv') - - def _test_list_router_port(self, resources, cmd, - myid, detail=False, tags=(), - fields_1=(), fields_2=()): - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - cmd.get_client().MultipleTimes().AndReturn(self.client) - reses = {resources: [{'id': 'myid1', }, - {'id': 'myid2', }, ], } - - resstr = self.client.serialize(reses) - - # url method body - query = "" - args = detail and ['-D', ] or [] - - if fields_1: - for field in fields_1: - args.append('--fields') - args.append(field) - args.append(myid) - if tags: - args.append('--') - args.append("--tag") - for tag in tags: - args.append(tag) - if (not tags) and fields_2: - args.append('--') - if fields_2: - args.append("--fields") - for field in fields_2: - args.append(field) - for field in itertools.chain(fields_1, fields_2): - if query: - query += "&fields=" + field - else: - query = "fields=" + field - - for tag in tags: - if query: - query += "&tag=" + tag - else: - query = "tag=" + tag - if detail: - query = query and query + '&verbose=True' or 'verbose=True' - query = query and query + '&device_id=%s' or 'device_id=%s' - path = getattr(self.client, resources + "_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query % myid), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - cmd_parser = cmd.get_parser("list_" + resources) - shell.run_command(cmd, cmd_parser, args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - _str = self.fake_stdout.make_string() - - self.assertIn('myid1', _str) - - def test_list_router_ports(self): - """List router ports: -D.""" - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, - self.test_id, True) - - def test_list_router_ports_tags(self): - """List router ports: -- --tags a b.""" - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, - self.test_id, tags=['a', 'b']) - - def test_list_router_ports_detail_tags(self): - """List router ports: -D -- --tags a b.""" - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, self.test_id, - detail=True, tags=['a', 'b']) - - def test_list_router_ports_fields(self): - """List ports: --fields a --fields b -- --fields c d.""" - resources = "ports" - cmd = port.ListRouterPort(test_cli20.MyApp(sys.stdout), None) - self._test_list_router_port(resources, cmd, self.test_id, - fields_1=['a', 'b'], - fields_2=['c', 'd']) - - def test_update_port(self): - """Update port: myid --name myname --admin-state-up False - --tags a b. - """ - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--admin-state-up', 'False', - '--tags', 'a', 'b'], - {'name': 'myname', - 'admin_state_up': 'False', - 'tags': ['a', 'b'], }) - - def test_update_port_secgroup(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = ['--security-group', 'sg1_id', myid] - updatefields = {'security_groups': ['sg1_id']} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_secgroups(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = ['--security-group', 'sg1_id', - '--security-group', 'sg2_id', - myid] - updatefields = {'security_groups': ['sg1_id', 'sg2_id']} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_extra_dhcp_opts(self): - """Update port: myid --extra_dhcp_opt.""" - resource = 'port' - myid = 'myid' - args = [myid, - '--extra-dhcp-opt', - "opt_name=bootfile-name,opt_value=pxelinux.0", - '--extra-dhcp-opt', - "opt_name=tftp-server,opt_value=123.123.123.123", - '--extra-dhcp-opt', - "opt_name=server-ip-address,opt_value=123.123.123.45" - ] - updatedfields = {'extra_dhcp_opts': [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0'}, - {'opt_name': 'tftp-server', - 'opt_value': '123.123.123.123'}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45'}]} - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, myid, args, updatedfields) - - def test_update_port_fixed_ip(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - net_id = 'net_id' - ip_addr = '123.123.123.123' - args = [myid, - '--fixed-ip', "network_id=%(net_id)s,ip_address=%(ip_addr)s" % - {'net_id': net_id, - 'ip_addr': ip_addr}] - updated_fields = {"fixed_ips": [{'network_id': net_id, - 'ip_address': ip_addr}]} - self._test_update_resource(resource, cmd, myid, args, updated_fields) - - def test_update_port_device_id_device_owner(self): - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = ['--device-id', 'dev_id', '--device-owner', 'fake', myid] - updatefields = {'device_id': 'dev_id', - 'device_owner': 'fake'} - self._test_update_resource(resource, cmd, myid, args, updatefields) - - def test_update_port_extra_dhcp_opts_ip_version(self): - """Update port: myid --extra_dhcp_opt.""" - resource = 'port' - myid = 'myid' - args = [myid, - '--extra-dhcp-opt', - "opt_name=bootfile-name,opt_value=pxelinux.0,ip_version=4", - '--extra-dhcp-opt', - "opt_name=tftp-server,opt_value=2001:192:168::1,ip_version=6", - '--extra-dhcp-opt', - "opt_name=server-ip-address,opt_value=null,ip_version=4" - ] - updatedfields = {'extra_dhcp_opts': [{'opt_name': 'bootfile-name', - 'opt_value': 'pxelinux.0', - 'ip_version': '4'}, - {'opt_name': 'tftp-server', - 'opt_value': '2001:192:168::1', - 'ip_version': '6'}, - {'opt_name': 'server-ip-address', - 'opt_value': None, - 'ip_version': '4'}]} - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, myid, args, updatedfields) - - def test_delete_extra_dhcp_opts_from_port(self): - resource = 'port' - myid = 'myid' - args = [myid, - '--extra-dhcp-opt', - "opt_name=bootfile-name,opt_value=null", - '--extra-dhcp-opt', - "opt_name=tftp-server,opt_value=123.123.123.123", - '--extra-dhcp-opt', - "opt_name=server-ip-address,opt_value=123.123.123.45" - ] - # the client code will change the null to None and send to server, - # where its interpreted as delete the DHCP option on the port. - updatedfields = {'extra_dhcp_opts': [{'opt_name': 'bootfile-name', - 'opt_value': None}, - {'opt_name': 'tftp-server', - 'opt_value': '123.123.123.123'}, - {'opt_name': 'server-ip-address', - 'opt_value': '123.123.123.45'}]} - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, myid, args, updatedfields) - - def test_update_port_security_group_off(self): - """Update port: --no-security-groups myid.""" - resource = 'port' - cmd = port.UpdatePort(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['--no-security-groups', 'myid'], - {'security_groups': []}) - - def test_show_port(self): - """Show port: --fields id --fields name myid.""" - resource = 'port' - cmd = port.ShowPort(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_delete_port(self): - """Delete port: myid.""" - resource = 'port' - cmd = port.DeletePort(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - -class CLITestV20PortXML(CLITestV20PortJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_router.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_router.py deleted file mode 100644 index 87e878aa6f..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_router.py +++ /dev/null @@ -1,258 +0,0 @@ -# Copyright 2012 VMware, Inc -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import router -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20RouterJSON(test_cli20.CLITestV20Base): - def test_create_router(self): - """Create router: router1.""" - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'router1' - myid = 'myid' - args = [name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_router_tenant(self): - """Create router: --tenant_id tenantid myname.""" - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = ['--tenant_id', 'tenantid', name] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_router_admin_state(self): - """Create router: --admin_state_down myname.""" - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = ['--admin_state_down', name, ] - position_names = ['name', ] - position_values = [name, ] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - admin_state_up=False) - - def _create_router_distributed_or_ha(self, distributed=None, ha=None): - """Create router: --distributed distributed --ha ha myname.""" - resource = 'router' - cmd = router.CreateRouter(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - args = [] - if distributed is not None: - args += ['--distributed', str(distributed)] - if ha is not None: - args += ['--ha', str(ha)] - args.append(name) - position_names = ['name', ] - position_values = [name, ] - expected = {} - if distributed is not None: - expected['distributed'] = str(distributed) - if ha is not None: - expected['ha'] = str(ha) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - **expected) - - def test_create_router_distributed_True(self): - """Create router: --distributed=True.""" - self._create_router_distributed_or_ha(distributed='True') - - def test_create_router_ha_with_True(self): - self._create_router_distributed_or_ha(ha='True') - - def test_create_router_ha_with_true(self): - self._create_router_distributed_or_ha(ha='true') - - def test_create_router_ha_with_False(self): - self._create_router_distributed_or_ha(ha='False') - - def test_create_router_ha_with_false(self): - self._create_router_distributed_or_ha(ha='false') - - def test_create_router_distributed_False(self): - """Create router: --distributed=False.""" - self._create_router_distributed_or_ha(distributed='False') - - def test_create_router_distributed_true(self): - """Create router: --distributed=true.""" - self._create_router_distributed_or_ha(distributed='true') - - def test_create_router_distributed_false(self): - """Create router: --distributed=false.""" - self._create_router_distributed_or_ha(distributed='false') - - def test_list_routers_detail(self): - """list routers: -D.""" - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_routers_pagination(self): - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_routers_sort(self): - """list routers: --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_routers_limit(self): - """list routers: -P.""" - resources = "routers" - cmd = router.ListRouter(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_update_router_exception(self): - """Update router: myid.""" - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - self.assertRaises(exceptions.CommandError, self._test_update_resource, - resource, cmd, 'myid', ['myid'], {}) - - def test_update_router(self): - """Update router: myid --name myname --tags a b.""" - resource = 'router' - cmd = router.UpdateRouter(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname'], - {'name': 'myname'} - ) - - def test_delete_router(self): - """Delete router: myid.""" - resource = 'router' - cmd = router.DeleteRouter(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_show_router(self): - """Show router: myid.""" - resource = 'router' - cmd = router.ShowRouter(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, - ['id', 'name']) - - def _test_add_remove_interface(self, action, mode, cmd, args): - resource = 'router' - subcmd = '%s_router_interface' % action - if mode == 'port': - body = {'port_id': 'portid'} - else: - body = {'subnet_id': 'subnetid'} - if action == 'add': - retval = {'subnet_id': 'subnetid', 'port_id': 'portid'} - else: - retval = None - self._test_update_resource_action(resource, cmd, 'myid', - subcmd, args, - body, retval) - - def test_add_interface_compat(self): - """Add interface to router: myid subnetid.""" - cmd = router.AddInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnetid'] - self._test_add_remove_interface('add', 'subnet', cmd, args) - - def test_add_interface_by_subnet(self): - """Add interface to router: myid subnet=subnetid.""" - cmd = router.AddInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnet=subnetid'] - self._test_add_remove_interface('add', 'subnet', cmd, args) - - def test_add_interface_by_port(self): - """Add interface to router: myid port=portid.""" - cmd = router.AddInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'port=portid'] - self._test_add_remove_interface('add', 'port', cmd, args) - - def test_del_interface_compat(self): - """Delete interface from router: myid subnetid.""" - cmd = router.RemoveInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnetid'] - self._test_add_remove_interface('remove', 'subnet', cmd, args) - - def test_del_interface_by_subnet(self): - """Delete interface from router: myid subnet=subnetid.""" - cmd = router.RemoveInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'subnet=subnetid'] - self._test_add_remove_interface('remove', 'subnet', cmd, args) - - def test_del_interface_by_port(self): - """Delete interface from router: myid port=portid.""" - cmd = router.RemoveInterfaceRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'port=portid'] - self._test_add_remove_interface('remove', 'port', cmd, args) - - def test_set_gateway(self): - """Set external gateway for router: myid externalid.""" - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid"}} - ) - - def test_set_gateway_disable_snat(self): - """set external gateway for router: myid externalid.""" - resource = 'router' - cmd = router.SetGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['myid', 'externalid', '--disable-snat'] - self._test_update_resource(resource, cmd, 'myid', - args, - {"external_gateway_info": - {"network_id": "externalid", - "enable_snat": False}} - ) - - def test_remove_gateway(self): - """Remove external gateway from router: externalid.""" - resource = 'router' - cmd = router.RemoveGatewayRouter(test_cli20.MyApp(sys.stdout), None) - args = ['externalid'] - self._test_update_resource(resource, cmd, 'externalid', - args, {"external_gateway_info": {}} - ) - - -class CLITestV20RouterXML(CLITestV20RouterJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_securitygroup.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_securitygroup.py deleted file mode 100644 index ec18fb8ee1..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_securitygroup.py +++ /dev/null @@ -1,439 +0,0 @@ -#!/usr/bin/env python -# Copyright 2012 Red Hat -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from mox3 import mox -import six - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.neutron.v2_0 import securitygroup -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20SecurityGroupsJSON(test_cli20.CLITestV20Base): - def test_create_security_group(self): - """Create security group: webservers.""" - resource = 'security_group' - cmd = securitygroup.CreateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - name = 'webservers' - myid = 'myid' - args = [name, ] - position_names = ['name'] - position_values = [name] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_security_group_tenant(self): - """Create security group: webservers.""" - resource = 'security_group' - cmd = securitygroup.CreateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - name = 'webservers' - description = 'my webservers' - myid = 'myid' - args = ['--tenant_id', 'tenant_id', '--description', description, name] - position_names = ['name', 'description'] - position_values = [name, description] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenant_id') - - def test_create_security_group_with_description(self): - """Create security group: webservers.""" - resource = 'security_group' - cmd = securitygroup.CreateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - name = 'webservers' - description = 'my webservers' - myid = 'myid' - args = [name, '--description', description] - position_names = ['name', 'description'] - position_values = [name, description] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_list_security_groups(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_security_groups_pagination(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_security_groups_sort(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_security_groups_limit(self): - resources = "security_groups" - cmd = securitygroup.ListSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_security_group_id(self): - resource = 'security_group' - cmd = securitygroup.ShowSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def test_show_security_group_id_name(self): - resource = 'security_group' - cmd = securitygroup.ShowSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_delete_security_group(self): - """Delete security group: myid.""" - resource = 'security_group' - cmd = securitygroup.DeleteSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_update_security_group(self): - """Update security group: myid --name myname --description desc.""" - resource = 'security_group' - cmd = securitygroup.UpdateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--description', 'mydescription'], - {'name': 'myname', - 'description': 'mydescription'} - ) - - def test_update_security_group_with_unicode(self): - resource = 'security_group' - cmd = securitygroup.UpdateSecurityGroup( - test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', u'\u7f51\u7edc', - '--description', u'\u7f51\u7edc'], - {'name': u'\u7f51\u7edc', - 'description': u'\u7f51\u7edc'} - ) - - def test_create_security_group_rule_full(self): - """Create security group rule.""" - resource = 'security_group_rule' - cmd = securitygroup.CreateSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - direction = 'ingress' - ethertype = 'IPv4' - protocol = 'tcp' - port_range_min = '22' - port_range_max = '22' - remote_ip_prefix = '10.0.0.0/24' - security_group_id = '1' - remote_group_id = '1' - args = ['--remote_ip_prefix', remote_ip_prefix, '--direction', - direction, '--ethertype', ethertype, '--protocol', protocol, - '--port_range_min', port_range_min, '--port_range_max', - port_range_max, '--remote_group_id', remote_group_id, - security_group_id] - position_names = ['remote_ip_prefix', 'direction', 'ethertype', - 'protocol', 'port_range_min', 'port_range_max', - 'remote_group_id', 'security_group_id'] - position_values = [remote_ip_prefix, direction, ethertype, protocol, - port_range_min, port_range_max, remote_group_id, - security_group_id] - self._test_create_resource(resource, cmd, None, myid, args, - position_names, position_values) - - def test_delete_security_group_rule(self): - """Delete security group rule: myid.""" - resource = 'security_group_rule' - cmd = securitygroup.DeleteSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - def test_list_security_group_rules(self): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(securitygroup.ListSecurityGroupRule, - "extend_list") - securitygroup.ListSecurityGroupRule.extend_list(mox.IsA(list), - mox.IgnoreArg()) - self._test_list_resources(resources, cmd, True) - - def _test_extend_list(self, mox_calls, data): - resources = "security_groups" - - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(cmd, "get_client") - self.mox.StubOutWithMock(self.client.httpclient, "request") - - cmd.get_client().MultipleTimes().AndReturn(self.client) - path = getattr(self.client, resources + '_path') - mox_calls(path, data) - self.mox.ReplayAll() - known_args, _vs = cmd.get_parser( - 'list' + resources).parse_known_args() - - cmd.extend_list(data, known_args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - def _build_test_data(self, data, excess=0): - # Length of a query filter on security group rule id - # in these testcases, id='secgroupid%02d' (with len(id)=12) - sec_group_id_filter_len = 12 - - response = [] - replace_rules = {'security_group_id': 'security_group', - 'remote_group_id': 'remote_group'} - - search_opts = {'fields': ['id', 'name']} - sec_group_ids = set() - for rule in data: - for key in replace_rules: - if rule.get(key): - sec_group_ids.add(rule[key]) - response.append({'id': rule[key], 'name': 'default'}) - sec_group_ids = list(sec_group_ids) - - result = [] - - sec_group_count = len(sec_group_ids) - max_size = ((sec_group_id_filter_len * sec_group_count) - excess) - chunk_size = max_size // sec_group_id_filter_len - - for i in range(0, sec_group_count, chunk_size): - search_opts['id'] = sec_group_ids[i: i + chunk_size] - params = utils.safe_encode_dict(search_opts) - resp_str = self.client.serialize({'security_groups': response}) - - result.append({ - 'filter': six.moves.urllib.parse.urlencode(params, doseq=1), - 'response': (test_cli20.MyResp(200), resp_str), - }) - - return result - - def test_extend_list(self): - def mox_calls(path, data): - responses = self._build_test_data(data) - self.client.httpclient.request( - test_cli20.MyUrlComparator(test_cli20.end_url( - path, responses[0]['filter']), self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn( - responses[0]['response']) - - data = [{'name': 'default', - 'remote_group_id': 'remgroupid%02d' % i} - for i in range(10)] - data.append({'name': 'default', 'remote_group_id': None}) - self._test_extend_list(mox_calls, data) - - def test_extend_list_exceed_max_uri_len(self): - def mox_calls(path, data): - # 1 char of extra URI len will cause a split in 2 requests - self.mox.StubOutWithMock(self.client.httpclient, - '_check_uri_length') - self.client.httpclient._check_uri_length(mox.IgnoreArg()).AndRaise( - exceptions.RequestURITooLong(excess=1)) - responses = self._build_test_data(data, excess=1) - - for item in responses: - self.client.httpclient._check_uri_length( - mox.IgnoreArg()).AndReturn(None) - self.client.httpclient.request( - test_cli20.end_url(path, item['filter']), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn( - item['response']) - - data = [{'name': 'default', - 'security_group_id': 'secgroupid%02d' % i, - 'remote_group_id': 'remgroupid%02d' % i} - for i in range(10)] - data.append({'name': 'default', - 'security_group_id': 'secgroupid10', - 'remote_group_id': None}) - self._test_extend_list(mox_calls, data) - - def test_list_security_group_rules_pagination(self): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(securitygroup.ListSecurityGroupRule, - "extend_list") - securitygroup.ListSecurityGroupRule.extend_list(mox.IsA(list), - mox.IgnoreArg()) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_security_group_rules_sort(self): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(securitygroup.ListSecurityGroupRule, - "extend_list") - securitygroup.ListSecurityGroupRule.extend_list(mox.IsA(list), - mox.IgnoreArg()) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_security_group_rules_limit(self): - resources = "security_group_rules" - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(securitygroup.ListSecurityGroupRule, - "extend_list") - securitygroup.ListSecurityGroupRule.extend_list(mox.IsA(list), - mox.IgnoreArg()) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_security_group_rule(self): - resource = 'security_group_rule' - cmd = securitygroup.ShowSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id']) - - def _test_list_security_group_rules_extend(self, data=None, expected=None, - args=(), conv=True, - query_field=False): - def setup_list_stub(resources, data, query): - reses = {resources: data} - resstr = self.client.serialize(reses) - resp = (test_cli20.MyResp(200), resstr) - path = getattr(self.client, resources + '_path') - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, query), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue( - 'X-Auth-Token', test_cli20.TOKEN)).AndReturn(resp) - - # Setup the default data - _data = {'cols': ['id', 'security_group_id', 'remote_group_id'], - 'data': [('ruleid1', 'myid1', 'myid1'), - ('ruleid2', 'myid2', 'myid3'), - ('ruleid3', 'myid2', 'myid2')]} - _expected = {'cols': ['id', 'security_group', 'remote_group'], - 'data': [('ruleid1', 'group1', 'group1'), - ('ruleid2', 'group2', 'group3'), - ('ruleid3', 'group2', 'group2')]} - if data is None: - data = _data - list_data = [dict(zip(data['cols'], d)) for d in data['data']] - if expected is None: - expected = {} - expected['cols'] = expected.get('cols', _expected['cols']) - expected['data'] = expected.get('data', _expected['data']) - - cmd = securitygroup.ListSecurityGroupRule( - test_cli20.MyApp(sys.stdout), None) - self.mox.StubOutWithMock(cmd, 'get_client') - self.mox.StubOutWithMock(self.client.httpclient, 'request') - cmd.get_client().AndReturn(self.client) - query = '' - if query_field: - query = '&'.join(['fields=' + f for f in data['cols']]) - setup_list_stub('security_group_rules', list_data, query) - if conv: - cmd.get_client().AndReturn(self.client) - sec_ids = set() - for n in data['data']: - sec_ids.add(n[1]) - sec_ids.add(n[2]) - filters = '' - for id in sec_ids: - filters = filters + "&id=%s" % id - setup_list_stub('security_groups', - [{'id': 'myid1', 'name': 'group1'}, - {'id': 'myid2', 'name': 'group2'}, - {'id': 'myid3', 'name': 'group3'}], - query='fields=id&fields=name' + filters) - self.mox.ReplayAll() - - cmd_parser = cmd.get_parser('list_security_group_rules') - parsed_args = cmd_parser.parse_args(args) - result = cmd.get_data(parsed_args) - self.mox.VerifyAll() - self.mox.UnsetStubs() - # Check columns - self.assertEqual(result[0], expected['cols']) - # Check data - _result = [x for x in result[1]] - self.assertEqual(len(_result), len(expected['data'])) - for res, exp in zip(_result, expected['data']): - self.assertEqual(len(res), len(exp)) - self.assertEqual(res, exp) - - def test_list_security_group_rules_extend_source_id(self): - self._test_list_security_group_rules_extend() - - def test_list_security_group_rules_extend_no_nameconv(self): - expected = {'cols': ['id', 'security_group_id', 'remote_group_id'], - 'data': [('ruleid1', 'myid1', 'myid1'), - ('ruleid2', 'myid2', 'myid3'), - ('ruleid3', 'myid2', 'myid2')]} - args = ['--no-nameconv'] - self._test_list_security_group_rules_extend(expected=expected, - args=args, conv=False) - - def test_list_security_group_rules_extend_with_columns(self): - args = '-c id -c security_group_id -c remote_group_id'.split() - self._test_list_security_group_rules_extend(args=args) - - def test_list_security_group_rules_extend_with_columns_no_id(self): - args = '-c id -c security_group -c remote_group'.split() - self._test_list_security_group_rules_extend(args=args) - - def test_list_security_group_rules_extend_with_fields(self): - args = '-F id -F security_group_id -F remote_group_id'.split() - self._test_list_security_group_rules_extend(args=args, - query_field=True) - - def test_list_security_group_rules_extend_with_fields_no_id(self): - args = '-F id -F security_group -F remote_group'.split() - self._test_list_security_group_rules_extend(args=args, - query_field=True) - - -class CLITestV20SecurityGroupsXML(CLITestV20SecurityGroupsJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_servicetype.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_servicetype.py deleted file mode 100644 index 0429a1a442..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_servicetype.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2013 Mirantis Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Eugene Nikanorov, Mirantis Inc. -# - -import sys - -from neutronclient.neutron.v2_0 import servicetype -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20ServiceProvidersJSON(test_cli20.CLITestV20Base): - id_field = "name" - - def setUp(self): - super(CLITestV20ServiceProvidersJSON, self).setUp( - plurals={'tags': 'tag'} - ) - - def test_list_service_providers(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, True) - - def test_list_service_providers_pagination(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_service_providers_sort(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, - sort_key=["name"], - sort_dir=["asc", "desc"]) - - def test_list_service_providers_limit(self): - resources = "service_providers" - cmd = servicetype.ListServiceProvider(test_cli20.MyApp(sys.stdout), - None) - self._test_list_resources(resources, cmd, page_size=1000) - - -class CLITestV20ServiceProvidersXML(CLITestV20ServiceProvidersJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_subnet.py b/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_subnet.py deleted file mode 100644 index a98af01f17..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_cli20_subnet.py +++ /dev/null @@ -1,608 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import sys - -from mox3 import mox - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import subnet -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20SubnetJSON(test_cli20.CLITestV20Base): - def setUp(self): - super(CLITestV20SubnetJSON, self).setUp(plurals={'tags': 'tag'}) - - def test_create_subnet(self): - """Create subnet: --gateway gateway netid cidr.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - gateway = 'gatewayvalue' - args = ['--gateway', gateway, netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, gateway] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnet_with_no_gateway(self): - """Create subnet: --no-gateway netid cidr.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - args = ['--no-gateway', netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, None] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - - def test_create_subnet_with_bad_gateway_option(self): - """Create sbunet: --no-gateway netid cidr.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - gateway = 'gatewayvalue' - args = ['--gateway', gateway, '--no-gateway', netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, None] - try: - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - except Exception: - return - self.fail('No exception for bad gateway option') - - def _test_create_resource_and_catch_command_error(self, tested_args, - should_fail, - *args): - _j = lambda args: ' '.join(args) - try: - self._test_create_resource(*args) - except exceptions.CommandError: - if not should_fail: - self.fail( - 'Unexpected exception raised for %s options' % - _j(tested_args)) - self.mox.UnsetStubs() - else: - if should_fail: - self.fail( - 'No exception for %s options' % _j(tested_args)) - - def test_create_subnet_with_enable_and_disable_dhcp(self): - """Create subnet: --enable-dhcp and --disable-dhcp.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - position_names = ['ip_version', 'network_id', 'cidr', 'enable_dhcp'] - # enable_dhcp value is appended later inside the loop - position_values = [4, netid, cidr] - for enable_dhcp_arg, should_fail in ( - ('--enable-dhcp=False', False), - ('--enable-dhcp=True', True), - ('--enable-dhcp', True) - ): - tested_args = [enable_dhcp_arg, '--disable-dhcp'] - args = tested_args + [netid, cidr] - pos_values = position_values + [should_fail] - self._test_create_resource_and_catch_command_error( - tested_args, should_fail, - resource, cmd, name, myid, args, position_names, pos_values) - - def test_create_subnet_with_multiple_enable_dhcp(self): - """Create subnet with multiple --enable-dhcp arguments passed.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'cidrvalue' - position_names = ['ip_version', 'network_id', 'cidr', 'enable_dhcp'] - # enable_dhcp value is appended later inside the loop - position_values = [4, netid, cidr] - - _ = 'UNUSED_MARKER' - for tested_args, should_fail, pos_value in ( - (['--enable-dhcp', '--enable-dhcp=True'], False, True), - (['--enable-dhcp', '--enable-dhcp=False'], True, _), - (['--enable-dhcp=False', '--enable-dhcp'], True, _), - (['--enable-dhcp=True', '--enable-dhcp=False'], True, _), - (['--enable-dhcp=False', '--enable-dhcp=True'], True, _) - ): - args = tested_args + [netid, cidr] - pos_values = position_values + [pos_value] - self._test_create_resource_and_catch_command_error( - tested_args, should_fail, - resource, cmd, name, myid, args, position_names, pos_values) - - def test_create_subnet_tenant(self): - """Create subnet: --tenant_id tenantid netid cidr.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr'] - position_values = [4, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_tags(self): - """Create subnet: netid cidr --tags a b.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = [netid, cidr, '--tags', 'a', 'b'] - position_names = ['ip_version', 'network_id', 'cidr'] - position_values = [4, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tags=['a', 'b']) - - def test_create_subnet_allocation_pool(self): - """Create subnet: --tenant_id tenantid netid cidr. - The is --allocation_pool start=1.1.1.10,end=1.1.1.20 - """ - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation_pool', 'start=1.1.1.10,end=1.1.1.20', - netid, cidr] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pool = [{'start': '1.1.1.10', 'end': '1.1.1.20'}] - position_values = [4, pool, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_allocation_pools(self): - """Create subnet: --tenant-id tenantid netid cidr. - The are --allocation_pool start=1.1.1.10,end=1.1.1.20 and - --allocation_pool start=1.1.1.30,end=1.1.1.40 - """ - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation_pool', 'start=1.1.1.10,end=1.1.1.20', - '--allocation_pool', 'start=1.1.1.30,end=1.1.1.40', - netid, cidr] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.10', 'end': '1.1.1.20'}, - {'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_host_route(self): - """Create subnet: --tenant_id tenantid netid cidr. - The is - --host-route destination=172.16.1.0/24,nexthop=1.1.1.20 - """ - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--host-route', 'destination=172.16.1.0/24,nexthop=1.1.1.20', - netid, cidr] - position_names = ['ip_version', 'host_routes', 'network_id', - 'cidr'] - route = [{'destination': '172.16.1.0/24', 'nexthop': '1.1.1.20'}] - position_values = [4, route, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_host_routes(self): - """Create subnet: --tenant-id tenantid netid cidr. - The are - --host-route destination=172.16.1.0/24,nexthop=1.1.1.20 and - --host-route destination=172.17.7.0/24,nexthop=1.1.1.40 - """ - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--host-route', 'destination=172.16.1.0/24,nexthop=1.1.1.20', - '--host-route', 'destination=172.17.7.0/24,nexthop=1.1.1.40', - netid, cidr] - position_names = ['ip_version', 'host_routes', 'network_id', - 'cidr'] - routes = [{'destination': '172.16.1.0/24', 'nexthop': '1.1.1.20'}, - {'destination': '172.17.7.0/24', 'nexthop': '1.1.1.40'}] - position_values = [4, routes, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_dns_nameservers(self): - """Create subnet: --tenant-id tenantid netid cidr. - The are - --dns-nameserver 1.1.1.20 and --dns-nameserver 1.1.1.40 - """ - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--dns-nameserver', '1.1.1.20', - '--dns-nameserver', '1.1.1.40', - netid, cidr] - position_names = ['ip_version', 'dns_nameservers', 'network_id', - 'cidr'] - nameservers = ['1.1.1.20', '1.1.1.40'] - position_values = [4, nameservers, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_disable_dhcp(self): - """Create subnet: --tenant-id tenantid --disable-dhcp netid cidr.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--disable-dhcp', - netid, cidr] - position_names = ['ip_version', 'enable_dhcp', 'network_id', - 'cidr'] - position_values = [4, False, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_merge_single_plurar(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation-pool', 'start=1.1.1.10,end=1.1.1.20', - netid, cidr, - '--allocation-pools', 'list=true', 'type=dict', - 'start=1.1.1.30,end=1.1.1.40'] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.10', 'end': '1.1.1.20'}, - {'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_merge_plurar(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - netid, cidr, - '--allocation-pools', 'list=true', 'type=dict', - 'start=1.1.1.30,end=1.1.1.40'] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_merge_single_single(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--allocation-pool', 'start=1.1.1.10,end=1.1.1.20', - netid, cidr, - '--allocation-pool', - 'start=1.1.1.30,end=1.1.1.40'] - position_names = ['ip_version', 'allocation_pools', 'network_id', - 'cidr'] - pools = [{'start': '1.1.1.10', 'end': '1.1.1.20'}, - {'start': '1.1.1.30', 'end': '1.1.1.40'}] - position_values = [4, pools, netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_max_v4_cidr(self): - """Create subnet: --gateway gateway netid cidr.""" - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = '192.168.0.1/32' - gateway = 'gatewayvalue' - args = ['--gateway', gateway, netid, cidr] - position_names = ['ip_version', 'network_id', 'cidr', 'gateway_ip'] - position_values = [4, netid, cidr, gateway] - self.mox.StubOutWithMock(cmd.log, 'warning') - cmd.log.warning(mox.IgnoreArg()) - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values) - self.mox.VerifyAll() - self.mox.UnsetStubs() - - def test_create_subnet_with_ipv6_ra_mode(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '6', - '--ipv6-ra-mode', 'dhcpv6-stateful', - netid, cidr] - position_names = ['ip_version', 'ipv6_ra_mode', - 'network_id', 'cidr'] - position_values = [6, 'dhcpv6-stateful', netid, cidr] - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_ipv6_address_mode(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '6', - '--ipv6-address-mode', 'dhcpv6-stateful', - netid, cidr] - position_names = ['ip_version', 'ipv6_address_mode', - 'network_id', 'cidr'] - position_values = [6, 'dhcpv6-stateful', netid, cidr] - - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_ipv6_modes(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '6', - '--ipv6-address-mode', 'slaac', - '--ipv6-ra-mode', 'slaac', - netid, cidr] - position_names = ['ip_version', 'ipv6_address_mode', - 'ipv6_ra_mode', 'network_id', 'cidr'] - position_values = [6, 'slaac', 'slaac', netid, cidr] - - self._test_create_resource(resource, cmd, name, myid, args, - position_names, position_values, - tenant_id='tenantid') - - def test_create_subnet_with_ipv6_ra_mode_ipv4(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '4', - '--ipv6-ra-mode', 'slaac', - netid, cidr] - position_names = ['ip_version', 'ipv6_ra_mode', - 'network_id', 'cidr'] - position_values = [4, None, netid, cidr] - self.assertRaises(exceptions.CommandError, self._test_create_resource, - resource, cmd, name, myid, args, position_names, - position_values, tenant_id='tenantid') - - def test_create_subnet_with_ipv6_address_mode_ipv4(self): - resource = 'subnet' - cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None) - name = 'myname' - myid = 'myid' - netid = 'netid' - cidr = 'prefixvalue' - args = ['--tenant_id', 'tenantid', - '--ip-version', '4', - '--ipv6-address-mode', 'slaac', - netid, cidr] - position_names = ['ip_version', 'ipv6_address_mode', - 'network_id', 'cidr'] - position_values = [4, None, netid, cidr] - self.assertRaises(exceptions.CommandError, self._test_create_resource, - resource, cmd, name, myid, args, position_names, - position_values, tenant_id='tenantid') - - def test_list_subnets_detail(self): - """List subnets: -D.""" - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_subnets_tags(self): - """List subnets: -- --tags a b.""" - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, tags=['a', 'b']) - - def test_list_subnets_known_option_after_unknown(self): - """List subnets: -- --tags a b --request-format xml.""" - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, tags=['a', 'b']) - - def test_list_subnets_detail_tags(self): - """List subnets: -D -- --tags a b.""" - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, detail=True, tags=['a', 'b']) - - def test_list_subnets_fields(self): - """List subnets: --fields a --fields b -- --fields c d.""" - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - fields_1=['a', 'b'], fields_2=['c', 'd']) - - def test_list_subnets_pagination(self): - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_subnets_sort(self): - """List subnets: --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_subnets_limit(self): - """List subnets: -P.""" - resources = "subnets" - cmd = subnet.ListSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_update_subnet(self): - """Update subnet: myid --name myname --tags a b.""" - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--tags', 'a', 'b'], - {'name': 'myname', 'tags': ['a', 'b'], } - ) - - def test_update_subnet_known_option_before_id(self): - """Update subnet: --request-format json myid --name myname.""" - # --request-format xml is known option - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['--request-format', 'json', - 'myid', '--name', 'myname'], - {'name': 'myname', } - ) - - def test_update_subnet_known_option_after_id(self): - """Update subnet: myid --name myname --request-format json.""" - # --request-format xml is known option - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--request-format', 'json'], - {'name': 'myname', } - ) - - def test_update_subnet_allocation_pools(self): - """Update subnet: myid --name myname --tags a b.""" - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--allocation-pool', - 'start=1.2.0.2,end=1.2.0.127', - '--request-format', 'json'], - {'allocation_pools': [{'start': '1.2.0.2', - 'end': '1.2.0.127'}]} - ) - - def test_update_subnet_enable_disable_dhcp(self): - """Update sbunet: --enable-dhcp and --disable-dhcp.""" - resource = 'subnet' - cmd = subnet.UpdateSubnet(test_cli20.MyApp(sys.stdout), None) - try: - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'myname', - '--enable-dhcp', '--disable-dhcp'], - {'name': 'myname', } - ) - except exceptions.CommandError: - return - self.fail('No exception for --enable-dhcp --disable-dhcp option') - - def test_show_subnet(self): - """Show subnet: --fields id --fields name myid.""" - resource = 'subnet' - cmd = subnet.ShowSubnet(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_delete_subnet(self): - """Delete subnet: subnetid.""" - resource = 'subnet' - cmd = subnet.DeleteSubnet(test_cli20.MyApp(sys.stdout), None) - myid = 'myid' - args = [myid] - self._test_delete_resource(resource, cmd, myid, args) - - -class CLITestV20SubnetXML(CLITestV20SubnetJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_command_meta.py b/awx/lib/site-packages/neutronclient/tests/unit/test_command_meta.py deleted file mode 100644 index be50ab8abb..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_command_meta.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2013 Intel -# Copyright 2013 Isaku Yamahata -# -# All Rights Reserved. -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Isaku Yamahata, Intel - -import logging - -import testtools -from testtools import helpers - -from neutronclient.neutron import v2_0 as neutronV20 - - -class TestCommandMeta(testtools.TestCase): - def test_neutron_command_meta_defines_log(self): - class FakeCommand(neutronV20.NeutronCommand): - pass - - self.assertTrue(helpers.safe_hasattr(FakeCommand, 'log')) - self.assertIsInstance(FakeCommand.log, logging.getLoggerClass()) - self.assertEqual(FakeCommand.log.name, __name__ + ".FakeCommand") - - def test_neutron_command_log_defined_explicitly(self): - class FakeCommand(neutronV20.NeutronCommand): - log = None - - self.assertTrue(helpers.safe_hasattr(FakeCommand, 'log')) - self.assertIsNone(FakeCommand.log) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_http.py b/awx/lib/site-packages/neutronclient/tests/unit/test_http.py deleted file mode 100644 index 6e04b62dfb..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_http.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (C) 2013 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import abc - -from requests_mock.contrib import fixture as mock_fixture -import six -import testtools - -from neutronclient import client -from neutronclient.common import exceptions -from neutronclient.tests.unit import test_auth - - -AUTH_TOKEN = 'test_token' -END_URL = 'test_url' -METHOD = 'GET' -URL = 'http://test.test:1234/v2.0/test' -BODY = 'IAMFAKE' - - -@six.add_metaclass(abc.ABCMeta) -class TestHTTPClientMixin(object): - - def setUp(self): - super(TestHTTPClientMixin, self).setUp() - - self.requests = self.useFixture(mock_fixture.Fixture()) - self.clazz, self.http = self.initialize() - - @abc.abstractmethod - def initialize(self): - """Return client class, instance.""" - - def _test_headers(self, expected_headers, **kwargs): - """Test headers.""" - self.requests.register_uri(METHOD, URL, - request_headers=expected_headers) - self.http.request(URL, METHOD, **kwargs) - self.assertEqual(kwargs.get('body'), self.requests.last_request.body) - - def test_headers_without_body(self): - self._test_headers({'Accept': 'application/json'}) - - def test_headers_with_body(self): - headers = {'Accept': 'application/json', - 'Content-Type': 'application/json'} - self._test_headers(headers, body=BODY) - - def test_headers_without_body_with_content_type(self): - headers = {'Accept': 'application/xml'} - self._test_headers(headers, content_type='application/xml') - - def test_headers_with_body_with_content_type(self): - headers = {'Accept': 'application/xml', - 'Content-Type': 'application/xml'} - self._test_headers(headers, body=BODY, content_type='application/xml') - - def test_headers_defined_in_headers(self): - headers = {'Accept': 'application/xml', - 'Content-Type': 'application/xml'} - self._test_headers(headers, body=BODY, headers=headers) - - -class TestSessionClient(TestHTTPClientMixin, testtools.TestCase): - - def initialize(self): - session, auth = test_auth.setup_keystone_v2(self.requests) - return [client.SessionClient, - client.SessionClient(session=session, auth=auth)] - - -class TestHTTPClient(TestHTTPClientMixin, testtools.TestCase): - - def initialize(self): - return [client.HTTPClient, - client.HTTPClient(token=AUTH_TOKEN, endpoint_url=END_URL)] - - def test_request_error(self): - def cb(*args, **kwargs): - raise Exception('error msg') - - self.requests.get(URL, body=cb) - self.assertRaises( - exceptions.ConnectionFailed, - self.http._cs_request, - URL, METHOD - ) - - def test_request_success(self): - text = 'test content' - self.requests.register_uri(METHOD, URL, text=text) - - resp, resp_text = self.http._cs_request(URL, METHOD) - self.assertEqual(200, resp.status_code) - self.assertEqual(text, resp_text) - - def test_request_unauthorized(self): - text = 'unauthorized message' - self.requests.register_uri(METHOD, URL, status_code=401, text=text) - e = self.assertRaises(exceptions.Unauthorized, - self.http._cs_request, URL, METHOD) - self.assertEqual(text, e.message) - - def test_request_forbidden_is_returned_to_caller(self): - text = 'forbidden message' - self.requests.register_uri(METHOD, URL, status_code=403, text=text) - - resp, resp_text = self.http._cs_request(URL, METHOD) - self.assertEqual(403, resp.status_code) - self.assertEqual(text, resp_text) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_name_or_id.py b/awx/lib/site-packages/neutronclient/tests/unit/test_name_or_id.py deleted file mode 100644 index 412c45515c..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_name_or_id.py +++ /dev/null @@ -1,198 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import uuid - -from mox3 import mox -import testtools - -from neutronclient.common import exceptions -from neutronclient.neutron import v2_0 as neutronV20 -from neutronclient.tests.unit import test_cli20 -from neutronclient.v2_0 import client - - -class CLITestNameorID(testtools.TestCase): - - def setUp(self): - """Prepare the test environment.""" - super(CLITestNameorID, self).setUp() - self.mox = mox.Mox() - self.endurl = test_cli20.ENDURL - self.client = client.Client(token=test_cli20.TOKEN, - endpoint_url=self.endurl) - self.addCleanup(self.mox.VerifyAll) - self.addCleanup(self.mox.UnsetStubs) - - def test_get_id_from_id(self): - _id = str(uuid.uuid4()) - reses = {'networks': [{'id': _id, }, ], } - resstr = self.client.serialize(reses) - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, "networks_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&id=" + _id), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - returned_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', _id) - self.assertEqual(_id, returned_id) - - def test_get_id_from_id_then_name_empty(self): - _id = str(uuid.uuid4()) - reses = {'networks': [{'id': _id, }, ], } - resstr = self.client.serialize(reses) - resstr1 = self.client.serialize({'networks': []}) - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, "networks_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&id=" + _id), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr1)) - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + _id), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - returned_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', _id) - self.assertEqual(_id, returned_id) - - def test_get_id_from_name(self): - name = 'myname' - _id = str(uuid.uuid4()) - reses = {'networks': [{'id': _id, }, ], } - resstr = self.client.serialize(reses) - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, "networks_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + name), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - returned_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', name) - self.assertEqual(_id, returned_id) - - def test_get_id_from_name_multiple(self): - name = 'myname' - reses = {'networks': [{'id': str(uuid.uuid4())}, - {'id': str(uuid.uuid4())}]} - resstr = self.client.serialize(reses) - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, "networks_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + name), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - try: - neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', name) - except exceptions.NeutronClientNoUniqueMatch as ex: - self.assertIn('Multiple', ex.message) - - def test_get_id_from_name_notfound(self): - name = 'myname' - reses = {'networks': []} - resstr = self.client.serialize(reses) - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, "networks_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=" + name), - self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - try: - neutronV20.find_resourceid_by_name_or_id( - self.client, 'network', name) - except exceptions.NeutronClientException as ex: - self.assertIn('Unable to find', ex.message) - self.assertEqual(404, ex.status_code) - - def test_get_id_from_name_multiple_with_project(self): - name = 'web_server' - project = str(uuid.uuid4()) - expect_id = str(uuid.uuid4()) - reses = {'security_groups': - [{'id': expect_id, 'tenant_id': project}]} - resstr = self.client.serialize(reses) - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, "security_groups_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=%s&tenant_id=%s" % - (name, project)), self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - - observed_id = neutronV20.find_resourceid_by_name_or_id( - self.client, 'security_group', name, project) - - self.assertEqual(expect_id, observed_id) - - def test_get_id_from_name_multiple_with_project_not_found(self): - name = 'web_server' - project = str(uuid.uuid4()) - reses = {'security_groups': - [{'id': str(uuid.uuid4()), 'tenant_id': str(uuid.uuid4())}]} - resstr = self.client.serialize(reses) - self.mox.StubOutWithMock(self.client.httpclient, "request") - path = getattr(self.client, "security_groups_path") - self.client.httpclient.request( - test_cli20.MyUrlComparator( - test_cli20.end_url(path, "fields=id&name=%s&tenant_id=%s" % - (name, project)), self.client), - 'GET', - body=None, - headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN) - ).AndReturn((test_cli20.MyResp(200), resstr)) - self.mox.ReplayAll() - - try: - neutronV20.find_resourceid_by_name_or_id( - self.client, 'security_group', name, project) - except exceptions.NeutronClientException as ex: - self.assertIn('Unable to find', ex.message) - self.assertEqual(404, ex.status_code) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_quota.py b/awx/lib/site-packages/neutronclient/tests/unit/test_quota.py deleted file mode 100644 index 5364a412ec..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_quota.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2013 Yahoo! Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0 import quota as test_quota -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20Quota(test_cli20.CLITestV20Base): - def test_show_quota(self): - resource = 'quota' - cmd = test_quota.ShowQuota( - test_cli20.MyApp(sys.stdout), None) - args = ['--tenant-id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args) - - def test_update_quota(self): - resource = 'quota' - cmd = test_quota.UpdateQuota( - test_cli20.MyApp(sys.stdout), None) - args = ['--tenant-id', self.test_id, '--network', 'test'] - self.assertRaises( - exceptions.NeutronClientException, self._test_update_resource, - resource, cmd, self.test_id, args=args, - extrafields={'network': 'new'}) - - def test_delete_quota_get_parser(self): - cmd = test_cli20.MyApp(sys.stdout) - test_quota.DeleteQuota(cmd, None).get_parser(cmd) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_shell.py b/awx/lib/site-packages/neutronclient/tests/unit/test_shell.py deleted file mode 100644 index 091c9ecf1a..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_shell.py +++ /dev/null @@ -1,511 +0,0 @@ -# Copyright (C) 2013 Yahoo! Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import logging -import os -import re -import sys - -import fixtures -from mox3 import mox -import requests_mock -import six -import testtools -from testtools import matchers - -from keystoneclient.auth.identity import v2 as v2_auth -from keystoneclient.auth.identity import v3 as v3_auth -from keystoneclient import session - -from neutronclient.common import clientmanager -from neutronclient import shell as openstack_shell -from neutronclient.tests.unit import test_auth as auth - - -DEFAULT_USERNAME = 'username' -DEFAULT_PASSWORD = 'password' -DEFAULT_TENANT_ID = 'tenant_id' -DEFAULT_TENANT_NAME = 'tenant_name' -DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/' -DEFAULT_TOKEN = '3bcc3d3a03f44e3d8377f9247b0ad155' -DEFAULT_URL = 'http://quantum.example.org:9696/' - - -class ShellTest(testtools.TestCase): - - FAKE_ENV = { - 'OS_USERNAME': DEFAULT_USERNAME, - 'OS_PASSWORD': DEFAULT_PASSWORD, - 'OS_TENANT_ID': DEFAULT_TENANT_ID, - 'OS_TENANT_NAME': DEFAULT_TENANT_NAME, - 'OS_AUTH_URL': DEFAULT_AUTH_URL, - 'OS_REGION_NAME': None, - 'HTTP_PROXY': None, - 'http_proxy': None, - } - - # Patch os.environ to avoid required auth info. - def setUp(self): - super(ShellTest, self).setUp() - self.mox = mox.Mox() - for var in self.FAKE_ENV: - self.useFixture( - fixtures.EnvironmentVariable( - var, self.FAKE_ENV[var])) - - def shell(self, argstr, check=False): - orig = (sys.stdout, sys.stderr) - clean_env = {} - _old_env, os.environ = os.environ, clean_env.copy() - try: - sys.stdout = six.moves.cStringIO() - sys.stderr = six.moves.cStringIO() - _shell = openstack_shell.NeutronShell('2.0') - _shell.run(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertEqual(exc_value.code, 0) - finally: - stdout = sys.stdout.getvalue() - stderr = sys.stderr.getvalue() - sys.stdout.close() - sys.stderr.close() - sys.stdout, sys.stderr = orig - os.environ = _old_env - return stdout, stderr - - def test_run_unknown_command(self): - self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) - stdout, stderr = self.shell('fake', check=True) - self.assertFalse(stdout) - self.assertEqual("Unknown command ['fake']", stderr.strip()) - - def test_help(self): - required = 'usage:' - help_text, stderr = self.shell('help') - self.assertThat( - help_text, - matchers.MatchesRegex(required)) - self.assertFalse(stderr) - - def test_bash_completion(self): - required = '.*os_user_domain_id.*' - bash_completion, stderr = self.shell('bash-completion') - self.assertThat( - bash_completion, - matchers.MatchesRegex(required)) - self.assertFalse(stderr) - - def test_help_on_subcommand(self): - required = [ - '.*?^usage: .* quota-list'] - stdout, stderr = self.shell('help quota-list') - for r in required: - self.assertThat( - stdout, - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - self.assertFalse(stderr) - - def test_help_command(self): - required = 'usage:' - help_text, stderr = self.shell('help network-create') - self.assertThat( - help_text, - matchers.MatchesRegex(required)) - self.assertFalse(stderr) - - def test_bash_completion_in_outputs_of_help_command(self): - help_text, stderr = self.shell('help') - self.assertFalse(stderr) - completion_cmd = "bash-completion" - completion_help_str = ("Prints all of the commands and options " - "for bash-completion.") - self.assertIn(completion_cmd, help_text) - self.assertIn(completion_help_str, help_text) - - def test_bash_completion_command(self): - # just check we have some output - required = [ - '.*--tenant_id', - '.*--client-certificate', - '.*help', - '.*gateway-device-create', - '.*--dns-nameserver'] - help_text, stderr = self.shell('neutron bash-completion') - self.assertFalse(stderr) - for r in required: - self.assertThat(help_text, - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_unknown_auth_strategy(self): - self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) - stdout, stderr = self.shell('--os-auth-strategy fake quota-list') - self.assertFalse(stdout) - self.assertEqual('You must provide a service URL via ' - 'either --os-url or env[OS_URL]', stderr.strip()) - - @requests_mock.Mocker() - def test_auth(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V3_URL, - json=auth.V3_VERSION_ENTRY) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.V3_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - endpoint_type='publicURL', insecure=False, ca_cert=None, - timeout=None, - raise_errors=False, - retries=0, - auth=mox.IsA(v3_auth.Password), - session=mox.IsA(session.Session), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-tenant-name test ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.V3_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_auth_cert_and_key(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V3_URL, - json=auth.V3_VERSION_ENTRY) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.V3_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - raise_errors=False, - endpoint_type='publicURL', insecure=False, ca_cert=None, retries=0, - timeout=None, - auth=mox.IsA(v3_auth.Password), - session=mox.IsA(session.Session), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-tenant-name test ' - '--os-cert test ' - '--os-key test ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.V3_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_v2_auth(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V2_URL, - json=auth.V2_VERSION_ENTRY) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.V2_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - endpoint_type='publicURL', insecure=False, ca_cert=None, - timeout=None, - raise_errors=False, - retries=0, - auth=mox.IsA(v2_auth.Password), - session=mox.IsA(session.Session), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-tenant-name test ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.V2_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_failed_auth_version_discovery_v3_auth_url(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V3_URL, - status_code=405) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.V3_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - endpoint_type='publicURL', insecure=False, ca_cert=None, - timeout=None, - raise_errors=False, - retries=0, - auth=mox.IsA(v3_auth.Password), - session=mox.IsA(session.Session), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-user-domain-name test ' - '--os-tenant-name test ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.V3_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_failed_auth_version_discovery_v2_auth_url(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V2_URL, - status_code=405) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.V2_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - endpoint_type='publicURL', insecure=False, ca_cert=None, - timeout=None, - raise_errors=False, - retries=0, - auth=mox.IsA(v2_auth.Password), - session=mox.IsA(session.Session), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-tenant-name test ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.V2_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_auth_version_discovery_v3(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.BASE_URL, - text=auth.V3_VERSION_LIST) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.BASE_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - endpoint_type='publicURL', insecure=False, ca_cert=None, - timeout=None, - raise_errors=False, - retries=0, - auth=mox.IsA(v3_auth.Password), - session=mox.IsA(session.Session), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-user-domain-name test ' - '--os-tenant-name test ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.BASE_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_auth_version_discovery_v2(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.BASE_URL, - text=auth.V3_VERSION_LIST) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.BASE_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - endpoint_type='publicURL', insecure=False, ca_cert=None, - timeout=None, - raise_errors=False, - retries=0, - auth=mox.IsA(v2_auth.Password), - session=mox.IsA(session.Session), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-tenant-name test ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.BASE_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_insecure_auth(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V2_URL, - json=auth.V2_VERSION_ENTRY) - - neutron_shell = openstack_shell.NeutronShell('2.0') - self.addCleanup(self.mox.UnsetStubs) - self.mox.StubOutWithMock(clientmanager.ClientManager, '__init__') - self.mox.StubOutWithMock(neutron_shell, 'run_subcommand') - clientmanager.ClientManager.__init__( - token='', url='', auth_url=auth.V2_URL, - tenant_name='test', tenant_id='tenant_id', - username='test', user_id='', - password='test', region_name='', api_version={'network': '2.0'}, - auth_strategy='keystone', service_type='network', - endpoint_type='publicURL', insecure=True, ca_cert=None, - timeout=None, - raise_errors=False, - retries=0, - auth=mox.IgnoreArg(), - session=mox.IgnoreArg(), - log_credentials=True) - neutron_shell.run_subcommand(['quota-list']) - self.mox.ReplayAll() - cmdline = ('--os-username test ' - '--os-password test ' - '--os-tenant-name test ' - '--insecure ' - '--os-auth-url %s ' - '--os-auth-strategy keystone quota-list' - % auth.V2_URL) - neutron_shell.run(cmdline.split()) - self.mox.VerifyAll() - - def test_build_option_parser(self): - neutron_shell = openstack_shell.NeutronShell('2.0') - result = neutron_shell.build_option_parser('descr', '2.0') - self.assertEqual(True, isinstance(result, argparse.ArgumentParser)) - - def test_main_with_unicode(self): - self.mox.StubOutClassWithMocks(openstack_shell, 'NeutronShell') - qshell_mock = openstack_shell.NeutronShell('2.0') - unicode_text = u'\u7f51\u7edc' - argv = ['net-list', unicode_text, unicode_text] - qshell_mock.run([u'net-list', unicode_text, - unicode_text]).AndReturn(0) - self.mox.ReplayAll() - ret = openstack_shell.main(argv=argv) - self.mox.VerifyAll() - self.mox.UnsetStubs() - self.assertEqual(ret, 0) - - def test_endpoint_option(self): - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - # Neither $OS_ENDPOINT_TYPE nor --os-endpoint-type - namespace = parser.parse_args([]) - self.assertEqual('publicURL', namespace.os_endpoint_type) - - # --endpoint-type but not $OS_ENDPOINT_TYPE - namespace = parser.parse_args(['--os-endpoint-type=admin']) - self.assertEqual('admin', namespace.os_endpoint_type) - - def test_endpoint_environment_variable(self): - fixture = fixtures.EnvironmentVariable("OS_ENDPOINT_TYPE", - "public") - self.useFixture(fixture) - - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - # $OS_ENDPOINT_TYPE but not --endpoint-type - namespace = parser.parse_args([]) - self.assertEqual("public", namespace.os_endpoint_type) - - # --endpoint-type and $OS_ENDPOINT_TYPE - namespace = parser.parse_args(['--endpoint-type=admin']) - self.assertEqual('admin', namespace.endpoint_type) - - def test_timeout_option(self): - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - # Neither $OS_ENDPOINT_TYPE nor --endpoint-type - namespace = parser.parse_args([]) - self.assertIsNone(namespace.http_timeout) - - # --endpoint-type but not $OS_ENDPOINT_TYPE - namespace = parser.parse_args(['--http-timeout=50']) - self.assertEqual(50, namespace.http_timeout) - - def test_timeout_environment_variable(self): - fixture = fixtures.EnvironmentVariable("OS_NETWORK_TIMEOUT", - "50") - self.useFixture(fixture) - - shell = openstack_shell.NeutronShell('2.0') - parser = shell.build_option_parser('descr', '2.0') - - namespace = parser.parse_args([]) - self.assertEqual(50, namespace.http_timeout) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_ssl.py b/awx/lib/site-packages/neutronclient/tests/unit/test_ssl.py deleted file mode 100644 index e28f7c0c5b..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_ssl.py +++ /dev/null @@ -1,179 +0,0 @@ -# Copyright (C) 2013 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -import requests -import testtools - -from mox3 import mox -import requests_mock - -from neutronclient.client import HTTPClient -from neutronclient.common.clientmanager import ClientManager -from neutronclient.common import exceptions -from neutronclient import shell as openstack_shell -from neutronclient.tests.unit import test_auth as auth - -AUTH_TOKEN = 'test_token' -END_URL = 'test_url' -METHOD = 'GET' -URL = 'http://test.test:1234/v2.0/' -CA_CERT = '/tmp/test/path' - - -class TestSSL(testtools.TestCase): - def setUp(self): - super(TestSSL, self).setUp() - - self.useFixture(fixtures.EnvironmentVariable('OS_TOKEN', AUTH_TOKEN)) - self.useFixture(fixtures.EnvironmentVariable('OS_URL', END_URL)) - - self.mox = mox.Mox() - self.addCleanup(self.mox.UnsetStubs) - - @requests_mock.Mocker() - def test_ca_cert_passed(self, mrequests): - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V3_URL, - json=auth.V3_VERSION_ENTRY) - - self.mox.StubOutWithMock(ClientManager, '__init__') - self.mox.StubOutWithMock(openstack_shell.NeutronShell, 'interact') - - ClientManager.__init__( - ca_cert=CA_CERT, - # we are not really interested in other args - api_version=mox.IgnoreArg(), - auth_strategy=mox.IgnoreArg(), - auth_url=mox.IgnoreArg(), - service_type=mox.IgnoreArg(), - endpoint_type=mox.IgnoreArg(), - insecure=mox.IgnoreArg(), - password=mox.IgnoreArg(), - region_name=mox.IgnoreArg(), - tenant_id=mox.IgnoreArg(), - tenant_name=mox.IgnoreArg(), - token=mox.IgnoreArg(), - url=mox.IgnoreArg(), - username=mox.IgnoreArg(), - user_id=mox.IgnoreArg(), - retries=mox.IgnoreArg(), - raise_errors=mox.IgnoreArg(), - log_credentials=mox.IgnoreArg(), - timeout=mox.IgnoreArg(), - auth=mox.IgnoreArg(), - session=mox.IgnoreArg() - ) - openstack_shell.NeutronShell.interact().AndReturn(0) - self.mox.ReplayAll() - - cmdline = ( - '--os-cacert %s --os-auth-url %s' % - (CA_CERT, auth.V3_URL)) - - openstack_shell.NeutronShell('2.0').run(cmdline.split()) - self.mox.VerifyAll() - - @requests_mock.Mocker() - def test_ca_cert_passed_as_env_var(self, mrequests): - - # emulate Keystone version discovery - mrequests.register_uri('GET', - auth.V3_URL, - json=auth.V3_VERSION_ENTRY) - - self.useFixture(fixtures.EnvironmentVariable('OS_CACERT', CA_CERT)) - - self.mox.StubOutWithMock(ClientManager, '__init__') - self.mox.StubOutWithMock(openstack_shell.NeutronShell, 'interact') - - ClientManager.__init__( - ca_cert=CA_CERT, - # we are not really interested in other args - api_version=mox.IgnoreArg(), - auth_strategy=mox.IgnoreArg(), - auth_url=mox.IgnoreArg(), - service_type=mox.IgnoreArg(), - endpoint_type=mox.IgnoreArg(), - insecure=mox.IgnoreArg(), - password=mox.IgnoreArg(), - region_name=mox.IgnoreArg(), - tenant_id=mox.IgnoreArg(), - tenant_name=mox.IgnoreArg(), - token=mox.IgnoreArg(), - url=mox.IgnoreArg(), - username=mox.IgnoreArg(), - user_id=mox.IgnoreArg(), - retries=mox.IgnoreArg(), - raise_errors=mox.IgnoreArg(), - log_credentials=mox.IgnoreArg(), - timeout=mox.IgnoreArg(), - auth=mox.IgnoreArg(), - session=mox.IgnoreArg() - ) - openstack_shell.NeutronShell.interact().AndReturn(0) - self.mox.ReplayAll() - - cmdline = ('--os-auth-url %s' % auth.V3_URL) - openstack_shell.NeutronShell('2.0').run(cmdline.split()) - - self.mox.VerifyAll() - - def test_client_manager_properly_creates_httpclient_instance(self): - self.mox.StubOutWithMock(HTTPClient, '__init__') - HTTPClient.__init__( - ca_cert=CA_CERT, - # we are not really interested in other args - auth_strategy=mox.IgnoreArg(), - auth_url=mox.IgnoreArg(), - endpoint_url=mox.IgnoreArg(), - insecure=mox.IgnoreArg(), - password=mox.IgnoreArg(), - region_name=mox.IgnoreArg(), - tenant_name=mox.IgnoreArg(), - token=mox.IgnoreArg(), - username=mox.IgnoreArg(), - user_id=mox.IgnoreArg(), - tenant_id=mox.IgnoreArg(), - timeout=mox.IgnoreArg(), - log_credentials=mox.IgnoreArg(), - service_type=mox.IgnoreArg(), - endpoint_type=mox.IgnoreArg() - ) - self.mox.ReplayAll() - - version = {'network': '2.0'} - ClientManager(ca_cert=CA_CERT, - api_version=version, - url=END_URL, - token=AUTH_TOKEN).neutron - self.mox.VerifyAll() - - def test_proper_exception_is_raised_when_cert_validation_fails(self): - http = HTTPClient(token=AUTH_TOKEN, endpoint_url=END_URL) - - self.mox.StubOutWithMock(HTTPClient, 'request') - HTTPClient.request( - URL, METHOD, headers=mox.IgnoreArg() - ).AndRaise(requests.exceptions.SSLError) - self.mox.ReplayAll() - - self.assertRaises( - exceptions.SslCertificateValidationError, - http._cs_request, - URL, METHOD - ) - self.mox.VerifyAll() diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_utils.py b/awx/lib/site-packages/neutronclient/tests/unit/test_utils.py deleted file mode 100644 index a0044d61ac..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_utils.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (C) 2013 Yahoo! Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import testtools - -from neutronclient.common import exceptions -from neutronclient.common import utils - - -class TestUtils(testtools.TestCase): - def test_string_to_bool_true(self): - self.assertTrue(utils.str2bool('true')) - - def test_string_to_bool_false(self): - self.assertFalse(utils.str2bool('false')) - - def test_string_to_bool_None(self): - self.assertIsNone(utils.str2bool(None)) - - def test_string_to_dictionary(self): - input_str = 'key1=value1,key2=value2' - expected = {'key1': 'value1', 'key2': 'value2'} - self.assertEqual(expected, utils.str2dict(input_str)) - - def test_none_string_to_dictionary(self): - input_str = '' - expected = {} - self.assertEqual(expected, utils.str2dict(input_str)) - input_str = None - expected = {} - self.assertEqual(expected, utils.str2dict(input_str)) - - def test_get_dict_item_properties(self): - item = {'name': 'test_name', 'id': 'test_id'} - fields = ('name', 'id') - actual = utils.get_item_properties(item=item, fields=fields) - self.assertEqual(('test_name', 'test_id'), actual) - - def test_get_object_item_properties_mixed_case_fields(self): - class Fake(object): - def __init__(self): - self.id = 'test_id' - self.name = 'test_name' - self.test_user = 'test' - - fields = ('name', 'id', 'test user') - mixed_fields = ('test user', 'ID') - item = Fake() - actual = utils.get_item_properties(item, fields, mixed_fields) - self.assertEqual(('test_name', 'test_id', 'test'), actual) - - def test_get_object_item_desired_fields_differ_from_item(self): - class Fake(object): - def __init__(self): - self.id = 'test_id_1' - self.name = 'test_name' - self.test_user = 'test' - - fields = ('name', 'id', 'test user') - item = Fake() - actual = utils.get_item_properties(item, fields) - self.assertNotEqual(('test_name', 'test_id', 'test'), actual) - - def test_get_object_item_desired_fields_is_empty(self): - class Fake(object): - def __init__(self): - self.id = 'test_id_1' - self.name = 'test_name' - self.test_user = 'test' - - fields = [] - item = Fake() - actual = utils.get_item_properties(item, fields) - self.assertEqual((), actual) - - def test_get_object_item_with_formatters(self): - class Fake(object): - def __init__(self): - self.id = 'test_id' - self.name = 'test_name' - self.test_user = 'test' - - class FakeCallable(object): - def __call__(self, *args, **kwargs): - return 'pass' - - fields = ('name', 'id', 'test user', 'is_public') - formatters = {'is_public': FakeCallable()} - item = Fake() - act = utils.get_item_properties(item, fields, formatters=formatters) - self.assertEqual(('test_name', 'test_id', 'test', 'pass'), act) - - -class ImportClassTestCase(testtools.TestCase): - def test_get_client_class_invalid_version(self): - self.assertRaises( - exceptions.UnsupportedVersion, - utils.get_client_class, 'image', '2', {'image': '2'}) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/test_validators.py b/awx/lib/site-packages/neutronclient/tests/unit/test_validators.py deleted file mode 100644 index 619acb8178..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/test_validators.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2014 NEC Corporation -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import testtools - -from neutronclient.common import exceptions -from neutronclient.common import validators - - -class FakeParsedArgs(): - pass - - -class ValidatorTest(testtools.TestCase): - - def _test_validate_int(self, attr_val, attr_name='attr1', - min_value=1, max_value=10): - obj = FakeParsedArgs() - setattr(obj, attr_name, attr_val) - ret = validators.validate_int_range(obj, attr_name, - min_value, max_value) - # Come here only if there is no exception. - self.assertIsNone(ret) - - def _test_validate_int_error(self, attr_val, expected_msg, - attr_name='attr1', expected_exc=None, - min_value=1, max_value=10): - if expected_exc is None: - expected_exc = exceptions.CommandError - e = self.assertRaises(expected_exc, - self._test_validate_int, - attr_val, attr_name, min_value, max_value) - self.assertEqual(expected_msg, str(e)) - - def test_validate_int_min_max(self): - self._test_validate_int(1) - self._test_validate_int(10) - self._test_validate_int('1') - self._test_validate_int('10') - self._test_validate_int('0x0a') - - self._test_validate_int_error( - 0, 'attr1 "0" should be an integer [1:10].') - self._test_validate_int_error( - 11, 'attr1 "11" should be an integer [1:10].') - self._test_validate_int_error( - '0x10', 'attr1 "0x10" should be an integer [1:10].') - - def test_validate_int_min_only(self): - self._test_validate_int(1, max_value=None) - self._test_validate_int(10, max_value=None) - self._test_validate_int(11, max_value=None) - self._test_validate_int_error( - 0, 'attr1 "0" should be an integer greater than or equal to 1.', - max_value=None) - - def test_validate_int_max_only(self): - self._test_validate_int(0, min_value=None) - self._test_validate_int(1, min_value=None) - self._test_validate_int(10, min_value=None) - self._test_validate_int_error( - 11, 'attr1 "11" should be an integer smaller than or equal to 10.', - min_value=None) - - def test_validate_int_no_limit(self): - self._test_validate_int(0, min_value=None, max_value=None) - self._test_validate_int(1, min_value=None, max_value=None) - self._test_validate_int(10, min_value=None, max_value=None) - self._test_validate_int(11, min_value=None, max_value=None) - self._test_validate_int_error( - 'abc', 'attr1 "abc" should be an integer.', - min_value=None, max_value=None) - - def _test_validate_subnet(self, attr_val, attr_name='attr1'): - obj = FakeParsedArgs() - setattr(obj, attr_name, attr_val) - ret = validators.validate_ip_subnet(obj, attr_name) - # Come here only if there is no exception. - self.assertIsNone(ret) - - def test_validate_ip_subnet(self): - self._test_validate_subnet('192.168.2.0/24') - self._test_validate_subnet('192.168.2.3/20') - self._test_validate_subnet('192.168.2.1') - - e = self.assertRaises(exceptions.CommandError, - self._test_validate_subnet, - '192.168.2.256') - self.assertEqual('attr1 "192.168.2.256" is not a valid CIDR.', str(e)) diff --git a/awx/lib/site-packages/neutronclient/tests/unit/vpn/__init__.py b/awx/lib/site-packages/neutronclient/tests/unit/vpn/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ikepolicy.py b/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ikepolicy.py deleted file mode 100644 index fc5a1a4d0e..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ikepolicy.py +++ /dev/null @@ -1,212 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett Packard. - -import sys - -from neutronclient.neutron.v2_0.vpn import ikepolicy -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20VpnIkePolicyJSON(test_cli20.CLITestV20Base): - - def test_create_ikepolicy_all_params(self): - """vpn-ikepolicy-create all params.""" - resource = 'ikepolicy' - cmd = ikepolicy.CreateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ikepolicy1' - description = 'my-ike-policy' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-256' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - lifetime = 'units=seconds,value=20000' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--ike-version', ike_version, - '--phase1-negotiation-mode', phase1_negotiation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'description', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, description, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, ike_version, pfs, - tenant_id] - extra_body = { - 'lifetime': { - 'units': 'seconds', - 'value': 20000, - }, - } - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - - def test_create_ikepolicy_with_limited_params(self): - """vpn-ikepolicy-create with limited params.""" - resource = 'ikepolicy' - cmd = ikepolicy.CreateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ikepolicy1' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-128' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--tenant-id', tenant_id] - - position_names = ['name', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, - ike_version, pfs, - tenant_id] - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def _test_lifetime_values(self, lifetime): - resource = 'ikepolicy' - cmd = ikepolicy.CreateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ikepolicy1' - description = 'my-ike-policy' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-256' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--ike-version', ike_version, - '--phase1-negotiation-mode', phase1_negotiation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'description', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, description, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, ike_version, pfs, - tenant_id] - try: - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - except Exception: - return - self.fail("IKEPolicy Lifetime Error") - - def test_create_ikepolicy_with_invalid_lifetime_keys(self): - lifetime = 'uts=seconds,val=20000' - self._test_lifetime_values(lifetime) - - def test_create_ikepolicy_with_invalid_lifetime_value(self): - lifetime = 'units=seconds,value=-1' - self._test_lifetime_values(lifetime) - - def test_list_ikepolicy(self): - """vpn-ikepolicy-list.""" - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_ikepolicy_pagination(self): - """vpn-ikepolicy-list.""" - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ikepolicy_sort(self): - """vpn-ikepolicy-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ikepolicy_limit(self): - """vpn-ikepolicy-list -P.""" - resources = "ikepolicies" - cmd = ikepolicy.ListIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_ikepolicy_id(self): - """vpn-ikepolicy-show ikepolicy_id.""" - resource = 'ikepolicy' - cmd = ikepolicy.ShowIKEPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_ikepolicy_id_name(self): - """vpn-ikepolicy-show.""" - resource = 'ikepolicy' - cmd = ikepolicy.ShowIKEPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_ikepolicy(self): - """vpn-ikepolicy-update myid --name newname --tags a b.""" - resource = 'ikepolicy' - cmd = ikepolicy.UpdateIKEPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_delete_ikepolicy(self): - """vpn-ikepolicy-delete my-id.""" - resource = 'ikepolicy' - cmd = ikepolicy.DeleteIKEPolicy(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - -class CLITestV20VpnIkePolicyXML(CLITestV20VpnIkePolicyJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ipsec_site_connection.py b/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ipsec_site_connection.py deleted file mode 100644 index 077db1e16e..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ipsec_site_connection.py +++ /dev/null @@ -1,307 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett Packard. - -import sys - -from neutronclient.common import exceptions -from neutronclient.neutron.v2_0.vpn import ipsec_site_connection -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20IPsecSiteConnectionJSON(test_cli20.CLITestV20Base): - - def test_create_ipsec_site_connection_all_params(self): - """ipsecsite-connection-create all params.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - name = 'connection1' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '1500' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - peer_cidrs = ['192.168.3.0/24', '192.168.2.0/24'] - admin_state = True - description = 'my-vpn-connection' - dpd = 'action=restart,interval=30,timeout=120' - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, '--peer-id', peer_id, - '--psk', psk, '--initiator', initiator, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, '--name', name, - '--ipsecpolicy-id', ipsecpolicy_id, '--mtu', mtu, - '--description', description, - '--peer-cidr', '192.168.3.0/24', - '--peer-cidr', '192.168.2.0/24', - '--dpd', dpd] - - position_names = ['name', 'tenant_id', 'admin_state_up', - 'peer_address', 'peer_id', 'peer_cidrs', - 'psk', 'mtu', 'initiator', 'description', - 'vpnservice_id', 'ikepolicy_id', - 'ipsecpolicy_id'] - - position_values = [name, tenant_id, admin_state, peer_address, - peer_id, peer_cidrs, psk, mtu, - initiator, description, - vpnservice_id, ikepolicy_id, ipsecpolicy_id] - extra_body = { - 'dpd': { - 'action': 'restart', - 'interval': 30, - 'timeout': 120, - }, - } - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - - def test_create_ipsec_site_connection_with_limited_params(self): - """ipsecsite-connection-create with limited params.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '1500' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - peer_cidrs = ['192.168.3.0/24', '192.168.2.0/24'] - admin_state = True - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, - '--peer-id', peer_id, - '--psk', psk, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, - '--ipsecpolicy-id', ipsecpolicy_id, - '--peer-cidr', '192.168.3.0/24', - '--peer-cidr', '192.168.2.0/24'] - - position_names = ['tenant_id', 'admin_state_up', - 'peer_address', 'peer_id', 'peer_cidrs', - 'psk', 'mtu', 'initiator', - 'vpnservice_id', 'ikepolicy_id', - 'ipsecpolicy_id'] - - position_values = [tenant_id, admin_state, peer_address, - peer_id, peer_cidrs, psk, mtu, - initiator, - vpnservice_id, ikepolicy_id, ipsecpolicy_id] - - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values) - - def _test_dpd_values(self, dpd): - """ipsecsite-connection-create with invalid dpd values.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - name = 'connection1' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '1500' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - peer_cidrs = ['192.168.3.0/24', '192.168.2.0/24'] - admin_state = True - description = 'my-vpn-connection' - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, '--peer-id', peer_id, - '--psk', psk, '--initiator', initiator, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, '--name', name, - '--ipsecpolicy-id', ipsecpolicy_id, '--mtu', mtu, - '--description', description, - '--peer-cidr', '192.168.3.0/24', - '--peer-cidr', '192.168.2.0/24', - '--dpd', dpd] - - position_names = ['name', 'tenant_id', 'admin_state_up', - 'peer_address', 'peer_id', 'peer_cidrs', - 'psk', 'mtu', 'initiator', 'description', - 'vpnservice_id', 'ikepolicy_id', - 'ipsecpolicy_id'] - - position_values = [name, tenant_id, admin_state, peer_address, - peer_id, peer_cidrs, psk, mtu, - initiator, description, - vpnservice_id, ikepolicy_id, ipsecpolicy_id] - self.assertRaises( - exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - - def test_invalid_mtu(self): - """ipsecsite-connection-create with invalid dpd values.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.CreateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - tenant_id = 'mytenant_id' - name = 'connection1' - my_id = 'my_id' - peer_address = '192.168.2.10' - peer_id = '192.168.2.10' - psk = 'abcd' - mtu = '67' - initiator = 'bi-directional' - vpnservice_id = 'vpnservice_id' - ikepolicy_id = 'ikepolicy_id' - ipsecpolicy_id = 'ipsecpolicy_id' - peer_cidrs = ['192.168.3.0/24', '192.168.2.0/24'] - admin_state = True - description = 'my-vpn-connection' - - args = ['--tenant-id', tenant_id, - '--peer-address', peer_address, '--peer-id', peer_id, - '--psk', psk, '--initiator', initiator, - '--vpnservice-id', vpnservice_id, - '--ikepolicy-id', ikepolicy_id, '--name', name, - '--ipsecpolicy-id', ipsecpolicy_id, '--mtu', mtu, - '--description', description, - '--peer-cidr', '192.168.3.0/24', - '--peer-cidr', '192.168.2.0/24'] - - position_names = ['name', 'tenant_id', 'admin_state_up', - 'peer_address', 'peer_id', 'peer_cidrs', - 'psk', 'mtu', 'initiator', 'description', - 'vpnservice_id', 'ikepolicy_id', - 'ipsecpolicy_id'] - - position_values = [name, tenant_id, admin_state, peer_address, - peer_id, peer_cidrs, psk, mtu, - initiator, description, - vpnservice_id, ikepolicy_id, ipsecpolicy_id] - self.assertRaises( - exceptions.CommandError, - self._test_create_resource, - resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_ipsec_site_connection_with_invalid_dpd_keys(self): - dpd = 'act=restart,interval=30,time=120' - self._test_dpd_values(dpd) - - def test_create_ipsec_site_connection_with_invalid_dpd_values(self): - dpd = 'action=hold,interval=30,timeout=-1' - self._test_dpd_values(dpd) - - def test_list_ipsec_site_connection(self): - """ipsecsite-connection-list.""" - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources(resources, cmd, True) - - def test_list_ipsec_site_connection_pagination(self): - """ipsecsite-connection-list.""" - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ipsec_site_connection_sort(self): - """ipsecsite-connection-list. - --sort-key name --sort-key id --sort-key asc --sort-key desc - """ - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ipsec_site_connection_limit(self): - """ipsecsite-connection-list -P.""" - resources = "ipsec_site_connections" - cmd = ipsec_site_connection.ListIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_delete_ipsec_site_connection(self): - """ipsecsite-connection-delete my-id.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.DeleteIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - def test_update_ipsec_site_connection(self): - """ipsecsite-connection-update myid --name myname --tags a b.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.UpdateIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'Branch-new', - '--tags', 'a', 'b'], - {'name': 'Branch-new', - 'tags': ['a', 'b'], }) - - def test_show_ipsec_site_connection_id(self): - """ipsecsite-connection-show test_id.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.ShowIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_ipsec_site_connection_id_name(self): - """ipsecsite-connection-show.""" - resource = 'ipsec_site_connection' - cmd = ipsec_site_connection.ShowIPsecSiteConnection( - test_cli20.MyApp(sys.stdout), None - ) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - -class CLITestV20IPsecSiteConnectionXML(CLITestV20IPsecSiteConnectionJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ipsecpolicy.py b/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ipsecpolicy.py deleted file mode 100644 index ca413a053b..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_ipsecpolicy.py +++ /dev/null @@ -1,209 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett Packard. - -import sys - -from neutronclient.neutron.v2_0.vpn import ipsecpolicy -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20VpnIpsecPolicyJSON(test_cli20.CLITestV20Base): - - def test_create_ipsecpolicy_all_params(self): - """vpn-ipsecpolicy-create all params with dashes.""" - resource = 'ipsecpolicy' - cmd = ipsecpolicy.CreateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ipsecpolicy1' - description = 'first-ipsecpolicy1' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-256' - encapsulation_mode = 'tunnel' - pfs = 'group5' - transform_protocol = 'ah' - tenant_id = 'my-tenant' - my_id = 'my-id' - lifetime = 'units=seconds,value=20000' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--transform-protocol', transform_protocol, - '--encapsulation-mode', encapsulation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'auth_algorithm', 'encryption_algorithm', - 'encapsulation_mode', 'description', - 'transform_protocol', 'pfs', - 'tenant_id'] - - position_values = [name, auth_algorithm, encryption_algorithm, - encapsulation_mode, description, - transform_protocol, pfs, - tenant_id] - extra_body = { - 'lifetime': { - 'units': 'seconds', - 'value': 20000, - }, - } - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values, - extra_body=extra_body) - - def test_create_ipsecpolicy_with_limited_params(self): - """vpn-ipsecpolicy-create with limited params.""" - resource = 'ipsecpolicy' - cmd = ipsecpolicy.CreateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ipsecpolicy1' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-128' - encapsulation_mode = 'tunnel' - pfs = 'group5' - transform_protocol = 'esp' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--tenant-id', tenant_id] - - position_names = ['name', 'auth_algorithm', 'encryption_algorithm', - 'encapsulation_mode', - 'transform_protocol', 'pfs', - 'tenant_id'] - - position_values = [name, auth_algorithm, encryption_algorithm, - encapsulation_mode, - transform_protocol, pfs, - tenant_id] - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def _test_lifetime_values(self, lifetime): - resource = 'ipsecpolicy' - cmd = ipsecpolicy.CreateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - name = 'ipsecpolicy1' - description = 'my-ipsec-policy' - auth_algorithm = 'sha1' - encryption_algorithm = 'aes-256' - ike_version = 'v1' - phase1_negotiation_mode = 'main' - pfs = 'group5' - tenant_id = 'my-tenant' - my_id = 'my-id' - - args = [name, - '--description', description, - '--tenant-id', tenant_id, - '--auth-algorithm', auth_algorithm, - '--encryption-algorithm', encryption_algorithm, - '--ike-version', ike_version, - '--phase1-negotiation-mode', phase1_negotiation_mode, - '--lifetime', lifetime, - '--pfs', pfs] - - position_names = ['name', 'description', - 'auth_algorithm', 'encryption_algorithm', - 'phase1_negotiation_mode', - 'ike_version', 'pfs', - 'tenant_id'] - - position_values = [name, description, - auth_algorithm, encryption_algorithm, - phase1_negotiation_mode, ike_version, pfs, - tenant_id] - try: - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - except Exception: - return - self.fail("IPsecPolicy Lifetime Error") - - def test_create_ipsecpolicy_with_invalid_lifetime_keys(self): - lifetime = 'uts=seconds,val=20000' - self._test_lifetime_values(lifetime) - - def test_create_ipsecpolicy_with_invalide_lifetime_values(self): - lifetime = 'units=minutes,value=0' - self._test_lifetime_values(lifetime) - - def test_list_ipsecpolicy(self): - """vpn-ipsecpolicy-list.""" - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_ipsecpolicy_pagination(self): - """vpn-ipsecpolicy-list.""" - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_ipsecpolicy_sort(self): - """vpn-ipsecpolicy-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_ipsecpolicy_limit(self): - """vpn-ipsecpolicy-list -P.""" - resources = "ipsecpolicies" - cmd = ipsecpolicy.ListIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_ipsecpolicy_id(self): - """vpn-ipsecpolicy-show ipsecpolicy_id.""" - resource = 'ipsecpolicy' - cmd = ipsecpolicy.ShowIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_ipsecpolicy_id_name(self): - """vpn-ipsecpolicy-show.""" - resource = 'ipsecpolicy' - cmd = ipsecpolicy.ShowIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_ipsecpolicy(self): - """vpn-ipsecpolicy-update myid --name newname --tags a b.""" - resource = 'ipsecpolicy' - cmd = ipsecpolicy.UpdateIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_delete_ipsecpolicy(self): - """vpn-ipsecpolicy-delete my-id.""" - resource = 'ipsecpolicy' - cmd = ipsecpolicy.DeleteIPsecPolicy(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - -class CLITestV20VpnIpsecPolicyXML(CLITestV20VpnIpsecPolicyJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_vpnservice.py b/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_vpnservice.py deleted file mode 100644 index 8afd081dc4..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_cli20_vpnservice.py +++ /dev/null @@ -1,138 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett Packard. - -import sys - -from neutronclient.neutron.v2_0.vpn import vpnservice -from neutronclient.tests.unit import test_cli20 - - -class CLITestV20VpnServiceJSON(test_cli20.CLITestV20Base): - - def test_create_vpnservice_all_params(self): - """vpn-service-create all params.""" - resource = 'vpnservice' - cmd = vpnservice.CreateVPNService(test_cli20.MyApp(sys.stdout), None) - subnet = 'mysubnet-id' - router = 'myrouter-id' - tenant_id = 'mytenant-id' - my_id = 'my-id' - name = 'myvpnservice' - description = 'my-vpn-service' - admin_state = True - - args = ['--name', name, - '--description', description, - router, - subnet, - '--tenant-id', tenant_id] - - position_names = ['admin_state_up', 'name', 'description', - 'subnet_id', 'router_id', - 'tenant_id'] - - position_values = [admin_state, name, description, - subnet, router, tenant_id] - - self._test_create_resource(resource, cmd, name, my_id, args, - position_names, position_values) - - def test_create_vpnservice_with_limited_params(self): - """vpn-service-create with limited params.""" - resource = 'vpnservice' - cmd = vpnservice.CreateVPNService(test_cli20.MyApp(sys.stdout), None) - subnet = 'mysubnet-id' - router = 'myrouter-id' - tenant_id = 'mytenant-id' - my_id = 'my-id' - admin_state = True - - args = [router, - subnet, - '--tenant-id', tenant_id] - - position_names = ['admin_state_up', - 'subnet_id', 'router_id', - 'tenant_id'] - - position_values = [admin_state, subnet, router, tenant_id] - - self._test_create_resource(resource, cmd, None, my_id, args, - position_names, position_values) - - def test_list_vpnservice(self): - """vpn-service-list.""" - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, True) - - def test_list_vpnservice_pagination(self): - """vpn-service-list.""" - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources_with_pagination(resources, cmd) - - def test_list_vpnservice_sort(self): - """vpn-service-list --sort-key name --sort-key id --sort-key asc - --sort-key desc - """ - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, - sort_key=["name", "id"], - sort_dir=["asc", "desc"]) - - def test_list_vpnservice_limit(self): - """vpn-service-list -P.""" - resources = "vpnservices" - cmd = vpnservice.ListVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_list_resources(resources, cmd, page_size=1000) - - def test_show_vpnservice_id(self): - """vpn-service-show test_id.""" - resource = 'vpnservice' - cmd = vpnservice.ShowVPNService(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, args, ['id']) - - def test_show_vpnservice_id_name(self): - """vpn-service-show.""" - resource = 'vpnservice' - cmd = vpnservice.ShowVPNService(test_cli20.MyApp(sys.stdout), None) - args = ['--fields', 'id', '--fields', 'name', self.test_id] - self._test_show_resource(resource, cmd, self.test_id, - args, ['id', 'name']) - - def test_update_vpnservice(self): - """vpn-service-update myid --name newname --tags a b.""" - resource = 'vpnservice' - cmd = vpnservice.UpdateVPNService(test_cli20.MyApp(sys.stdout), None) - self._test_update_resource(resource, cmd, 'myid', - ['myid', '--name', 'newname'], - {'name': 'newname', }) - - def test_delete_vpnservice(self): - """vpn-service-delete my-id.""" - resource = 'vpnservice' - cmd = vpnservice.DeleteVPNService(test_cli20.MyApp(sys.stdout), None) - my_id = 'my-id' - args = [my_id] - self._test_delete_resource(resource, cmd, my_id, args) - - -class CLITestV20VpnServiceXML(CLITestV20VpnServiceJSON): - format = 'xml' diff --git a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_utils.py b/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_utils.py deleted file mode 100644 index 7b815a55ab..0000000000 --- a/awx/lib/site-packages/neutronclient/tests/unit/vpn/test_utils.py +++ /dev/null @@ -1,131 +0,0 @@ -# (c) Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Swaminathan Vasudevan, Hewlett Packard. - -import testtools - -from neutronclient.common import exceptions -from neutronclient.common import utils -from neutronclient.neutron.v2_0.vpn import utils as vpn_utils - - -class TestVPNUtils(testtools.TestCase): - - def test_validate_lifetime_dictionary_seconds(self): - input_str = utils.str2dict("units=seconds,value=3600") - self.assertIsNone(vpn_utils.validate_lifetime_dict(input_str)) - - def test_validate_dpd_dictionary_action_hold(self): - input_str = utils.str2dict("action=hold,interval=30,timeout=120") - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_restart(self): - input_str = utils.str2dict("action=restart,interval=30,timeout=120") - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_restart_by_peer(self): - input_str = utils.str2dict( - "action=restart-by-peer,interval=30,timeout=120" - ) - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_clear(self): - input_str = utils.str2dict('action=clear,interval=30,timeout=120') - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_dpd_dictionary_action_disabled(self): - input_str = utils.str2dict('action=disabled,interval=30,timeout=120') - self.assertIsNone(vpn_utils.validate_dpd_dict(input_str)) - - def test_validate_lifetime_dictionary_invalid_unit_key(self): - input_str = utils.str2dict('ut=seconds,value=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_invalid_unit_key_value(self): - input_str = utils.str2dict('units=seconds,val=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_unsupported_units(self): - input_str = utils.str2dict('units=minutes,value=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_invalid_empty_unit(self): - input_str = utils.str2dict('units=,value=3600') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_under_minimum_integer_value(self): - input_str = utils.str2dict('units=seconds,value=59') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_negative_integer_value(self): - input_str = utils.str2dict('units=seconds,value=-1') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_lifetime_dictionary_empty_value(self): - input_str = utils.str2dict('units=seconds,value=') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_dpd_dictionary_invalid_key_action(self): - input_str = utils.str2dict('act=hold,interval=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_invalid_key_interval(self): - input_str = utils.str2dict('action=hold,int=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_invalid_key_timeout(self): - input_str = utils.str2dict('action=hold,interval=30,tiut=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_unsupported_action(self): - input_str = utils.str2dict('action=bye-bye,interval=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_empty_action(self): - input_str = utils.str2dict('action=,interval=30,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_empty_interval(self): - input_str = utils.str2dict('action=hold,interval=,timeout=120') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_negative_interval_value(self): - input_str = utils.str2dict('action=hold,interval=-1,timeout=120') - self._test_validate_lifetime_negative_test_case(input_str) - - def test_validate_dpd_dictionary_zero_timeout(self): - input_str = utils.str2dict('action=hold,interval=30,timeout=0') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_empty_timeout(self): - input_str = utils.str2dict('action=hold,interval=30,timeout=') - self._test_validate_dpd_negative_test_case(input_str) - - def test_validate_dpd_dictionary_negative_timeout_value(self): - input_str = utils.str2dict('action=hold,interval=30,timeout=-1') - self._test_validate_lifetime_negative_test_case(input_str) - - def _test_validate_lifetime_negative_test_case(self, input_str): - """Generic handler for negative lifetime tests.""" - self.assertRaises(exceptions.CommandError, - vpn_utils.validate_lifetime_dict, - (input_str)) - - def _test_validate_dpd_negative_test_case(self, input_str): - """Generic handler for negative lifetime tests.""" - self.assertRaises(exceptions.CommandError, - vpn_utils.validate_lifetime_dict, - (input_str)) diff --git a/awx/lib/site-packages/neutronclient/v2_0/__init__.py b/awx/lib/site-packages/neutronclient/v2_0/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/neutronclient/v2_0/client.py b/awx/lib/site-packages/neutronclient/v2_0/client.py deleted file mode 100644 index 96405725b3..0000000000 --- a/awx/lib/site-packages/neutronclient/v2_0/client.py +++ /dev/null @@ -1,1525 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# Copyright 2015 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import logging -import time - -import requests -import six.moves.urllib.parse as urlparse - -from neutronclient import client -from neutronclient.common import constants -from neutronclient.common import exceptions -from neutronclient.common import serializer -from neutronclient.common import utils -from neutronclient.i18n import _ - - -_logger = logging.getLogger(__name__) - - -def exception_handler_v20(status_code, error_content): - """Exception handler for API v2.0 client. - - This routine generates the appropriate Neutron exception according to - the contents of the response body. - - :param status_code: HTTP error status code - :param error_content: deserialized body of error response - """ - error_dict = None - if isinstance(error_content, dict): - error_dict = error_content.get('NeutronError') - # Find real error type - bad_neutron_error_flag = False - if error_dict: - # If Neutron key is found, it will definitely contain - # a 'message' and 'type' keys? - try: - error_type = error_dict['type'] - error_message = error_dict['message'] - if error_dict['detail']: - error_message += "\n" + error_dict['detail'] - except Exception: - bad_neutron_error_flag = True - if not bad_neutron_error_flag: - # If corresponding exception is defined, use it. - client_exc = getattr(exceptions, '%sClient' % error_type, None) - # Otherwise look up per status-code client exception - if not client_exc: - client_exc = exceptions.HTTP_EXCEPTION_MAP.get(status_code) - if client_exc: - raise client_exc(message=error_message, - status_code=status_code) - else: - raise exceptions.NeutronClientException( - status_code=status_code, message=error_message) - else: - raise exceptions.NeutronClientException(status_code=status_code, - message=error_dict) - else: - message = None - if isinstance(error_content, dict): - message = error_content.get('message') - if message: - raise exceptions.NeutronClientException(status_code=status_code, - message=message) - - # If we end up here the exception was not a neutron error - msg = "%s-%s" % (status_code, error_content) - raise exceptions.NeutronClientException(status_code=status_code, - message=msg) - - -class APIParamsCall(object): - """A Decorator to add support for format and tenant overriding and filters. - """ - def __init__(self, function): - self.function = function - - def __get__(self, instance, owner): - def with_params(*args, **kwargs): - _format = instance.format - if 'format' in kwargs: - instance.format = kwargs['format'] - ret = self.function(instance, *args, **kwargs) - instance.format = _format - return ret - return with_params - - -class ClientBase(object): - """Client for the OpenStack Neutron v2.0 API. - - :param string username: Username for authentication. (optional) - :param string user_id: User ID for authentication. (optional) - :param string password: Password for authentication. (optional) - :param string token: Token for authentication. (optional) - :param string tenant_name: Tenant name. (optional) - :param string tenant_id: Tenant id. (optional) - :param string auth_strategy: 'keystone' by default, 'noauth' for no - authentication against keystone. (optional) - :param string auth_url: Keystone service endpoint for authorization. - :param string service_type: Network service type to pull from the - keystone catalog (e.g. 'network') (optional) - :param string endpoint_type: Network service endpoint type to pull from the - keystone catalog (e.g. 'publicURL', - 'internalURL', or 'adminURL') (optional) - :param string region_name: Name of a region to select when choosing an - endpoint from the service catalog. - :param string endpoint_url: A user-supplied endpoint URL for the neutron - service. Lazy-authentication is possible for API - service calls if endpoint is set at - instantiation.(optional) - :param integer timeout: Allows customization of the timeout for client - http requests. (optional) - :param bool insecure: SSL certificate validation. (optional) - :param bool log_credentials: Allow for logging of passwords or not. - Defaults to False. (optional) - :param string ca_cert: SSL CA bundle file to use. (optional) - :param integer retries: How many times idempotent (GET, PUT, DELETE) - requests to Neutron server should be retried if - they fail (default: 0). - :param bool raise_errors: If True then exceptions caused by connection - failure are propagated to the caller. - (default: True) - :param session: Keystone client auth session to use. (optional) - :param auth: Keystone auth plugin to use. (optional) - - Example:: - - from neutronclient.v2_0 import client - neutron = client.Client(username=USER, - password=PASS, - tenant_name=TENANT_NAME, - auth_url=KEYSTONE_URL) - - nets = neutron.list_networks() - ... - - """ - - # API has no way to report plurals, so we have to hard code them - # This variable should be overridden by a child class. - EXTED_PLURALS = {} - - def __init__(self, **kwargs): - """Initialize a new client for the Neutron v2.0 API.""" - super(ClientBase, self).__init__() - self.retries = kwargs.pop('retries', 0) - self.raise_errors = kwargs.pop('raise_errors', True) - self.httpclient = client.construct_http_client(**kwargs) - self.version = '2.0' - self.format = 'json' - self.action_prefix = "/v%s" % (self.version) - self.retry_interval = 1 - - def _handle_fault_response(self, status_code, response_body): - # Create exception with HTTP status code and message - _logger.debug("Error message: %s", response_body) - # Add deserialized error message to exception arguments - try: - des_error_body = self.deserialize(response_body, status_code) - except Exception: - # If unable to deserialized body it is probably not a - # Neutron error - des_error_body = {'message': response_body} - # Raise the appropriate exception - exception_handler_v20(status_code, des_error_body) - - def do_request(self, method, action, body=None, headers=None, params=None): - # Add format and tenant_id - action += ".%s" % self.format - action = self.action_prefix + action - if type(params) is dict and params: - params = utils.safe_encode_dict(params) - action += '?' + urlparse.urlencode(params, doseq=1) - - if body: - body = self.serialize(body) - - resp, replybody = self.httpclient.do_request( - action, method, body=body, - content_type=self.content_type()) - - status_code = resp.status_code - if status_code in (requests.codes.ok, - requests.codes.created, - requests.codes.accepted, - requests.codes.no_content): - return self.deserialize(replybody, status_code) - else: - if not replybody: - replybody = resp.reason - self._handle_fault_response(status_code, replybody) - - def get_auth_info(self): - return self.httpclient.get_auth_info() - - def serialize(self, data): - """Serializes a dictionary into either XML or JSON. - - A dictionary with a single key can be passed and it can contain any - structure. - """ - if data is None: - return None - elif type(data) is dict: - return serializer.Serializer( - self.get_attr_metadata()).serialize(data, self.content_type()) - else: - raise Exception(_("Unable to serialize object of type = '%s'") % - type(data)) - - def deserialize(self, data, status_code): - """Deserializes an XML or JSON string into a dictionary.""" - if status_code == 204: - return data - return serializer.Serializer(self.get_attr_metadata()).deserialize( - data, self.content_type())['body'] - - def get_attr_metadata(self): - if self.format == 'json': - return {} - old_request_format = self.format - self.format = 'json' - exts = self.list_extensions()['extensions'] - self.format = old_request_format - ns = dict([(ext['alias'], ext['namespace']) for ext in exts]) - self.EXTED_PLURALS.update(constants.PLURALS) - return {'plurals': self.EXTED_PLURALS, - 'xmlns': constants.XML_NS_V20, - constants.EXT_NS: ns} - - def content_type(self, _format=None): - """Returns the mime-type for either 'xml' or 'json'. - - Defaults to the currently set format. - """ - _format = _format or self.format - return "application/%s" % (_format) - - def retry_request(self, method, action, body=None, - headers=None, params=None): - """Call do_request with the default retry configuration. - - Only idempotent requests should retry failed connection attempts. - :raises: ConnectionFailed if the maximum # of retries is exceeded - """ - max_attempts = self.retries + 1 - for i in range(max_attempts): - try: - return self.do_request(method, action, body=body, - headers=headers, params=params) - except exceptions.ConnectionFailed: - # Exception has already been logged by do_request() - if i < self.retries: - _logger.debug('Retrying connection to Neutron service') - time.sleep(self.retry_interval) - elif self.raise_errors: - raise - - if self.retries: - msg = (_("Failed to connect to Neutron server after %d attempts") - % max_attempts) - else: - msg = _("Failed to connect Neutron server") - - raise exceptions.ConnectionFailed(reason=msg) - - def delete(self, action, body=None, headers=None, params=None): - return self.retry_request("DELETE", action, body=body, - headers=headers, params=params) - - def get(self, action, body=None, headers=None, params=None): - return self.retry_request("GET", action, body=body, - headers=headers, params=params) - - def post(self, action, body=None, headers=None, params=None): - # Do not retry POST requests to avoid the orphan objects problem. - return self.do_request("POST", action, body=body, - headers=headers, params=params) - - def put(self, action, body=None, headers=None, params=None): - return self.retry_request("PUT", action, body=body, - headers=headers, params=params) - - def list(self, collection, path, retrieve_all=True, **params): - if retrieve_all: - res = [] - for r in self._pagination(collection, path, **params): - res.extend(r[collection]) - return {collection: res} - else: - return self._pagination(collection, path, **params) - - def _pagination(self, collection, path, **params): - if params.get('page_reverse', False): - linkrel = 'previous' - else: - linkrel = 'next' - next = True - while next: - res = self.get(path, params=params) - yield res - next = False - try: - for link in res['%s_links' % collection]: - if link['rel'] == linkrel: - query_str = urlparse.urlparse(link['href']).query - params = urlparse.parse_qs(query_str) - next = True - break - except KeyError: - break - - -class Client(ClientBase): - - networks_path = "/networks" - network_path = "/networks/%s" - ports_path = "/ports" - port_path = "/ports/%s" - subnets_path = "/subnets" - subnet_path = "/subnets/%s" - quotas_path = "/quotas" - quota_path = "/quotas/%s" - extensions_path = "/extensions" - extension_path = "/extensions/%s" - routers_path = "/routers" - router_path = "/routers/%s" - floatingips_path = "/floatingips" - floatingip_path = "/floatingips/%s" - security_groups_path = "/security-groups" - security_group_path = "/security-groups/%s" - security_group_rules_path = "/security-group-rules" - security_group_rule_path = "/security-group-rules/%s" - vpnservices_path = "/vpn/vpnservices" - vpnservice_path = "/vpn/vpnservices/%s" - ipsecpolicies_path = "/vpn/ipsecpolicies" - ipsecpolicy_path = "/vpn/ipsecpolicies/%s" - ikepolicies_path = "/vpn/ikepolicies" - ikepolicy_path = "/vpn/ikepolicies/%s" - ipsec_site_connections_path = "/vpn/ipsec-site-connections" - ipsec_site_connection_path = "/vpn/ipsec-site-connections/%s" - - lbaas_loadbalancers_path = "/lbaas/loadbalancers" - lbaas_loadbalancer_path = "/lbaas/loadbalancers/%s" - lbaas_listeners_path = "/lbaas/listeners" - lbaas_listener_path = "/lbaas/listeners/%s" - lbaas_pools_path = "/lbaas/pools" - lbaas_pool_path = "/lbaas/pools/%s" - lbaas_healthmonitors_path = "/lbaas/healthmonitors" - lbaas_healthmonitor_path = "/lbaas/healthmonitors/%s" - lbaas_members_path = lbaas_pool_path + "/members" - lbaas_member_path = lbaas_pool_path + "/members/%s" - - vips_path = "/lb/vips" - vip_path = "/lb/vips/%s" - pools_path = "/lb/pools" - pool_path = "/lb/pools/%s" - pool_path_stats = "/lb/pools/%s/stats" - members_path = "/lb/members" - member_path = "/lb/members/%s" - health_monitors_path = "/lb/health_monitors" - health_monitor_path = "/lb/health_monitors/%s" - associate_pool_health_monitors_path = "/lb/pools/%s/health_monitors" - disassociate_pool_health_monitors_path = ( - "/lb/pools/%(pool)s/health_monitors/%(health_monitor)s") - qos_queues_path = "/qos-queues" - qos_queue_path = "/qos-queues/%s" - agents_path = "/agents" - agent_path = "/agents/%s" - network_gateways_path = "/network-gateways" - network_gateway_path = "/network-gateways/%s" - gateway_devices_path = "/gateway-devices" - gateway_device_path = "/gateway-devices/%s" - service_providers_path = "/service-providers" - credentials_path = "/credentials" - credential_path = "/credentials/%s" - network_profiles_path = "/network_profiles" - network_profile_path = "/network_profiles/%s" - network_profile_bindings_path = "/network_profile_bindings" - policy_profiles_path = "/policy_profiles" - policy_profile_path = "/policy_profiles/%s" - policy_profile_bindings_path = "/policy_profile_bindings" - metering_labels_path = "/metering/metering-labels" - metering_label_path = "/metering/metering-labels/%s" - metering_label_rules_path = "/metering/metering-label-rules" - metering_label_rule_path = "/metering/metering-label-rules/%s" - packet_filters_path = "/packet_filters" - packet_filter_path = "/packet_filters/%s" - - DHCP_NETS = '/dhcp-networks' - DHCP_AGENTS = '/dhcp-agents' - L3_ROUTERS = '/l3-routers' - L3_AGENTS = '/l3-agents' - LOADBALANCER_POOLS = '/loadbalancer-pools' - LOADBALANCER_AGENT = '/loadbalancer-agent' - firewall_rules_path = "/fw/firewall_rules" - firewall_rule_path = "/fw/firewall_rules/%s" - firewall_policies_path = "/fw/firewall_policies" - firewall_policy_path = "/fw/firewall_policies/%s" - firewall_policy_insert_path = "/fw/firewall_policies/%s/insert_rule" - firewall_policy_remove_path = "/fw/firewall_policies/%s/remove_rule" - firewalls_path = "/fw/firewalls" - firewall_path = "/fw/firewalls/%s" - net_partitions_path = "/net-partitions" - net_partition_path = "/net-partitions/%s" - - # API has no way to report plurals, so we have to hard code them - EXTED_PLURALS = {'routers': 'router', - 'floatingips': 'floatingip', - 'service_types': 'service_type', - 'service_definitions': 'service_definition', - 'security_groups': 'security_group', - 'security_group_rules': 'security_group_rule', - 'ipsecpolicies': 'ipsecpolicy', - 'ikepolicies': 'ikepolicy', - 'ipsec_site_connections': 'ipsec_site_connection', - 'vpnservices': 'vpnservice', - 'vips': 'vip', - 'pools': 'pool', - 'members': 'member', - 'health_monitors': 'health_monitor', - 'quotas': 'quota', - 'service_providers': 'service_provider', - 'firewall_rules': 'firewall_rule', - 'firewall_policies': 'firewall_policy', - 'firewalls': 'firewall', - 'metering_labels': 'metering_label', - 'metering_label_rules': 'metering_label_rule', - 'net_partitions': 'net_partition', - 'packet_filters': 'packet_filter', - 'loadbalancers': 'loadbalancer', - 'listeners': 'listener', - 'lbaas_pools': 'lbaas_pool', - 'lbaas_healthmonitors': 'lbaas_healthmonitor', - 'lbaas_members': 'lbaas_member', - 'healthmonitors': 'healthmonitor', - } - - @APIParamsCall - def get_quotas_tenant(self, **_params): - """Fetch tenant info in server's context for following quota operation. - """ - return self.get(self.quota_path % 'tenant', params=_params) - - @APIParamsCall - def list_quotas(self, **_params): - """Fetch all tenants' quotas.""" - return self.get(self.quotas_path, params=_params) - - @APIParamsCall - def show_quota(self, tenant_id, **_params): - """Fetch information of a certain tenant's quotas.""" - return self.get(self.quota_path % (tenant_id), params=_params) - - @APIParamsCall - def update_quota(self, tenant_id, body=None): - """Update a tenant's quotas.""" - return self.put(self.quota_path % (tenant_id), body=body) - - @APIParamsCall - def delete_quota(self, tenant_id): - """Delete the specified tenant's quota values.""" - return self.delete(self.quota_path % (tenant_id)) - - @APIParamsCall - def list_extensions(self, **_params): - """Fetch a list of all exts on server side.""" - return self.get(self.extensions_path, params=_params) - - @APIParamsCall - def show_extension(self, ext_alias, **_params): - """Fetch a list of all exts on server side.""" - return self.get(self.extension_path % ext_alias, params=_params) - - @APIParamsCall - def list_ports(self, retrieve_all=True, **_params): - """Fetches a list of all networks for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('ports', self.ports_path, retrieve_all, - **_params) - - @APIParamsCall - def show_port(self, port, **_params): - """Fetches information of a certain network.""" - return self.get(self.port_path % (port), params=_params) - - @APIParamsCall - def create_port(self, body=None): - """Creates a new port.""" - return self.post(self.ports_path, body=body) - - @APIParamsCall - def update_port(self, port, body=None): - """Updates a port.""" - return self.put(self.port_path % (port), body=body) - - @APIParamsCall - def delete_port(self, port): - """Deletes the specified port.""" - return self.delete(self.port_path % (port)) - - @APIParamsCall - def list_networks(self, retrieve_all=True, **_params): - """Fetches a list of all networks for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('networks', self.networks_path, retrieve_all, - **_params) - - @APIParamsCall - def show_network(self, network, **_params): - """Fetches information of a certain network.""" - return self.get(self.network_path % (network), params=_params) - - @APIParamsCall - def create_network(self, body=None): - """Creates a new network.""" - return self.post(self.networks_path, body=body) - - @APIParamsCall - def update_network(self, network, body=None): - """Updates a network.""" - return self.put(self.network_path % (network), body=body) - - @APIParamsCall - def delete_network(self, network): - """Deletes the specified network.""" - return self.delete(self.network_path % (network)) - - @APIParamsCall - def list_subnets(self, retrieve_all=True, **_params): - """Fetches a list of all networks for a tenant.""" - return self.list('subnets', self.subnets_path, retrieve_all, - **_params) - - @APIParamsCall - def show_subnet(self, subnet, **_params): - """Fetches information of a certain subnet.""" - return self.get(self.subnet_path % (subnet), params=_params) - - @APIParamsCall - def create_subnet(self, body=None): - """Creates a new subnet.""" - return self.post(self.subnets_path, body=body) - - @APIParamsCall - def update_subnet(self, subnet, body=None): - """Updates a subnet.""" - return self.put(self.subnet_path % (subnet), body=body) - - @APIParamsCall - def delete_subnet(self, subnet): - """Deletes the specified subnet.""" - return self.delete(self.subnet_path % (subnet)) - - @APIParamsCall - def list_routers(self, retrieve_all=True, **_params): - """Fetches a list of all routers for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('routers', self.routers_path, retrieve_all, - **_params) - - @APIParamsCall - def show_router(self, router, **_params): - """Fetches information of a certain router.""" - return self.get(self.router_path % (router), params=_params) - - @APIParamsCall - def create_router(self, body=None): - """Creates a new router.""" - return self.post(self.routers_path, body=body) - - @APIParamsCall - def update_router(self, router, body=None): - """Updates a router.""" - return self.put(self.router_path % (router), body=body) - - @APIParamsCall - def delete_router(self, router): - """Deletes the specified router.""" - return self.delete(self.router_path % (router)) - - @APIParamsCall - def add_interface_router(self, router, body=None): - """Adds an internal network interface to the specified router.""" - return self.put((self.router_path % router) + "/add_router_interface", - body=body) - - @APIParamsCall - def remove_interface_router(self, router, body=None): - """Removes an internal network interface from the specified router.""" - return self.put((self.router_path % router) + - "/remove_router_interface", body=body) - - @APIParamsCall - def add_gateway_router(self, router, body=None): - """Adds an external network gateway to the specified router.""" - return self.put((self.router_path % router), - body={'router': {'external_gateway_info': body}}) - - @APIParamsCall - def remove_gateway_router(self, router): - """Removes an external network gateway from the specified router.""" - return self.put((self.router_path % router), - body={'router': {'external_gateway_info': {}}}) - - @APIParamsCall - def list_floatingips(self, retrieve_all=True, **_params): - """Fetches a list of all floatingips for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('floatingips', self.floatingips_path, retrieve_all, - **_params) - - @APIParamsCall - def show_floatingip(self, floatingip, **_params): - """Fetches information of a certain floatingip.""" - return self.get(self.floatingip_path % (floatingip), params=_params) - - @APIParamsCall - def create_floatingip(self, body=None): - """Creates a new floatingip.""" - return self.post(self.floatingips_path, body=body) - - @APIParamsCall - def update_floatingip(self, floatingip, body=None): - """Updates a floatingip.""" - return self.put(self.floatingip_path % (floatingip), body=body) - - @APIParamsCall - def delete_floatingip(self, floatingip): - """Deletes the specified floatingip.""" - return self.delete(self.floatingip_path % (floatingip)) - - @APIParamsCall - def create_security_group(self, body=None): - """Creates a new security group.""" - return self.post(self.security_groups_path, body=body) - - @APIParamsCall - def update_security_group(self, security_group, body=None): - """Updates a security group.""" - return self.put(self.security_group_path % - security_group, body=body) - - @APIParamsCall - def list_security_groups(self, retrieve_all=True, **_params): - """Fetches a list of all security groups for a tenant.""" - return self.list('security_groups', self.security_groups_path, - retrieve_all, **_params) - - @APIParamsCall - def show_security_group(self, security_group, **_params): - """Fetches information of a certain security group.""" - return self.get(self.security_group_path % (security_group), - params=_params) - - @APIParamsCall - def delete_security_group(self, security_group): - """Deletes the specified security group.""" - return self.delete(self.security_group_path % (security_group)) - - @APIParamsCall - def create_security_group_rule(self, body=None): - """Creates a new security group rule.""" - return self.post(self.security_group_rules_path, body=body) - - @APIParamsCall - def delete_security_group_rule(self, security_group_rule): - """Deletes the specified security group rule.""" - return self.delete(self.security_group_rule_path % - (security_group_rule)) - - @APIParamsCall - def list_security_group_rules(self, retrieve_all=True, **_params): - """Fetches a list of all security group rules for a tenant.""" - return self.list('security_group_rules', - self.security_group_rules_path, - retrieve_all, **_params) - - @APIParamsCall - def show_security_group_rule(self, security_group_rule, **_params): - """Fetches information of a certain security group rule.""" - return self.get(self.security_group_rule_path % (security_group_rule), - params=_params) - - @APIParamsCall - def list_vpnservices(self, retrieve_all=True, **_params): - """Fetches a list of all configured VPN services for a tenant.""" - return self.list('vpnservices', self.vpnservices_path, retrieve_all, - **_params) - - @APIParamsCall - def show_vpnservice(self, vpnservice, **_params): - """Fetches information of a specific VPN service.""" - return self.get(self.vpnservice_path % (vpnservice), params=_params) - - @APIParamsCall - def create_vpnservice(self, body=None): - """Creates a new VPN service.""" - return self.post(self.vpnservices_path, body=body) - - @APIParamsCall - def update_vpnservice(self, vpnservice, body=None): - """Updates a VPN service.""" - return self.put(self.vpnservice_path % (vpnservice), body=body) - - @APIParamsCall - def delete_vpnservice(self, vpnservice): - """Deletes the specified VPN service.""" - return self.delete(self.vpnservice_path % (vpnservice)) - - @APIParamsCall - def list_ipsec_site_connections(self, retrieve_all=True, **_params): - """Fetches all configured IPsecSiteConnections for a tenant.""" - return self.list('ipsec_site_connections', - self.ipsec_site_connections_path, - retrieve_all, - **_params) - - @APIParamsCall - def show_ipsec_site_connection(self, ipsecsite_conn, **_params): - """Fetches information of a specific IPsecSiteConnection.""" - return self.get( - self.ipsec_site_connection_path % (ipsecsite_conn), params=_params - ) - - @APIParamsCall - def create_ipsec_site_connection(self, body=None): - """Creates a new IPsecSiteConnection.""" - return self.post(self.ipsec_site_connections_path, body=body) - - @APIParamsCall - def update_ipsec_site_connection(self, ipsecsite_conn, body=None): - """Updates an IPsecSiteConnection.""" - return self.put( - self.ipsec_site_connection_path % (ipsecsite_conn), body=body - ) - - @APIParamsCall - def delete_ipsec_site_connection(self, ipsecsite_conn): - """Deletes the specified IPsecSiteConnection.""" - return self.delete(self.ipsec_site_connection_path % (ipsecsite_conn)) - - @APIParamsCall - def list_ikepolicies(self, retrieve_all=True, **_params): - """Fetches a list of all configured IKEPolicies for a tenant.""" - return self.list('ikepolicies', self.ikepolicies_path, retrieve_all, - **_params) - - @APIParamsCall - def show_ikepolicy(self, ikepolicy, **_params): - """Fetches information of a specific IKEPolicy.""" - return self.get(self.ikepolicy_path % (ikepolicy), params=_params) - - @APIParamsCall - def create_ikepolicy(self, body=None): - """Creates a new IKEPolicy.""" - return self.post(self.ikepolicies_path, body=body) - - @APIParamsCall - def update_ikepolicy(self, ikepolicy, body=None): - """Updates an IKEPolicy.""" - return self.put(self.ikepolicy_path % (ikepolicy), body=body) - - @APIParamsCall - def delete_ikepolicy(self, ikepolicy): - """Deletes the specified IKEPolicy.""" - return self.delete(self.ikepolicy_path % (ikepolicy)) - - @APIParamsCall - def list_ipsecpolicies(self, retrieve_all=True, **_params): - """Fetches a list of all configured IPsecPolicies for a tenant.""" - return self.list('ipsecpolicies', - self.ipsecpolicies_path, - retrieve_all, - **_params) - - @APIParamsCall - def show_ipsecpolicy(self, ipsecpolicy, **_params): - """Fetches information of a specific IPsecPolicy.""" - return self.get(self.ipsecpolicy_path % (ipsecpolicy), params=_params) - - @APIParamsCall - def create_ipsecpolicy(self, body=None): - """Creates a new IPsecPolicy.""" - return self.post(self.ipsecpolicies_path, body=body) - - @APIParamsCall - def update_ipsecpolicy(self, ipsecpolicy, body=None): - """Updates an IPsecPolicy.""" - return self.put(self.ipsecpolicy_path % (ipsecpolicy), body=body) - - @APIParamsCall - def delete_ipsecpolicy(self, ipsecpolicy): - """Deletes the specified IPsecPolicy.""" - return self.delete(self.ipsecpolicy_path % (ipsecpolicy)) - - @APIParamsCall - def list_loadbalancers(self, retrieve_all=True, **_params): - """Fetches a list of all loadbalancers for a tenant.""" - return self.list('loadbalancers', self.lbaas_loadbalancers_path, - retrieve_all, **_params) - - @APIParamsCall - def show_loadbalancer(self, lbaas_loadbalancer, **_params): - """Fetches information for a load balancer.""" - return self.get(self.lbaas_loadbalancer_path % (lbaas_loadbalancer), - params=_params) - - @APIParamsCall - def create_loadbalancer(self, body=None): - """Creates a new load balancer.""" - return self.post(self.lbaas_loadbalancers_path, body=body) - - @APIParamsCall - def update_loadbalancer(self, lbaas_loadbalancer, body=None): - """Updates a load balancer.""" - return self.put(self.lbaas_loadbalancer_path % (lbaas_loadbalancer), - body=body) - - @APIParamsCall - def delete_loadbalancer(self, lbaas_loadbalancer): - """Deletes the specified load balancer.""" - return self.delete(self.lbaas_loadbalancer_path % - (lbaas_loadbalancer)) - - @APIParamsCall - def list_listeners(self, retrieve_all=True, **_params): - """Fetches a list of all lbaas_listeners for a tenant.""" - return self.list('listeners', self.lbaas_listeners_path, - retrieve_all, **_params) - - @APIParamsCall - def show_listener(self, lbaas_listener, **_params): - """Fetches information for a lbaas_listener.""" - return self.get(self.lbaas_listener_path % (lbaas_listener), - params=_params) - - @APIParamsCall - def create_listener(self, body=None): - """Creates a new lbaas_listener.""" - return self.post(self.lbaas_listeners_path, body=body) - - @APIParamsCall - def update_listener(self, lbaas_listener, body=None): - """Updates a lbaas_listener.""" - return self.put(self.lbaas_listener_path % (lbaas_listener), - body=body) - - @APIParamsCall - def delete_listener(self, lbaas_listener): - """Deletes the specified lbaas_listener.""" - return self.delete(self.lbaas_listener_path % (lbaas_listener)) - - @APIParamsCall - def list_lbaas_pools(self, retrieve_all=True, **_params): - """Fetches a list of all lbaas_pools for a tenant.""" - return self.list('pools', self.lbaas_pools_path, - retrieve_all, **_params) - - @APIParamsCall - def show_lbaas_pool(self, lbaas_pool, **_params): - """Fetches information for a lbaas_pool.""" - return self.get(self.lbaas_pool_path % (lbaas_pool), - params=_params) - - @APIParamsCall - def create_lbaas_pool(self, body=None): - """Creates a new lbaas_pool.""" - return self.post(self.lbaas_pools_path, body=body) - - @APIParamsCall - def update_lbaas_pool(self, lbaas_pool, body=None): - """Updates a lbaas_pool.""" - return self.put(self.lbaas_pool_path % (lbaas_pool), - body=body) - - @APIParamsCall - def delete_lbaas_pool(self, lbaas_pool): - """Deletes the specified lbaas_pool.""" - return self.delete(self.lbaas_pool_path % (lbaas_pool)) - - @APIParamsCall - def list_lbaas_healthmonitors(self, retrieve_all=True, **_params): - """Fetches a list of all lbaas_healthmonitors for a tenant.""" - return self.list('healthmonitors', self.lbaas_healthmonitors_path, - retrieve_all, **_params) - - @APIParamsCall - def show_lbaas_healthmonitor(self, lbaas_healthmonitor, **_params): - """Fetches information for a lbaas_healthmonitor.""" - return self.get(self.lbaas_healthmonitor_path % (lbaas_healthmonitor), - params=_params) - - @APIParamsCall - def create_lbaas_healthmonitor(self, body=None): - """Creates a new lbaas_healthmonitor.""" - return self.post(self.lbaas_healthmonitors_path, body=body) - - @APIParamsCall - def update_lbaas_healthmonitor(self, lbaas_healthmonitor, body=None): - """Updates a lbaas_healthmonitor.""" - return self.put(self.lbaas_healthmonitor_path % (lbaas_healthmonitor), - body=body) - - @APIParamsCall - def delete_lbaas_healthmonitor(self, lbaas_healthmonitor): - """Deletes the specified lbaas_healthmonitor.""" - return self.delete(self.lbaas_healthmonitor_path % - (lbaas_healthmonitor)) - - @APIParamsCall - def list_lbaas_loadbalancers(self, retrieve_all=True, **_params): - """Fetches a list of all lbaas_loadbalancers for a tenant.""" - return self.list('loadbalancers', self.lbaas_loadbalancers_path, - retrieve_all, **_params) - - @APIParamsCall - def list_lbaas_members(self, lbaas_pool, retrieve_all=True, **_params): - """Fetches a list of all lbaas_members for a tenant.""" - return self.list('members', self.lbaas_members_path % lbaas_pool, - retrieve_all, **_params) - - @APIParamsCall - def show_lbaas_member(self, lbaas_member, lbaas_pool, **_params): - """Fetches information of a certain lbaas_member.""" - return self.get(self.lbaas_member_path % (lbaas_pool, lbaas_member), - params=_params) - - @APIParamsCall - def create_lbaas_member(self, lbaas_pool, body=None): - """Creates an lbaas_member.""" - return self.post(self.lbaas_members_path % lbaas_pool, body=body) - - @APIParamsCall - def update_lbaas_member(self, lbaas_member, lbaas_pool, body=None): - """Updates a lbaas_healthmonitor.""" - return self.put(self.lbaas_member_path % (lbaas_pool, lbaas_member), - body=body) - - @APIParamsCall - def delete_lbaas_member(self, lbaas_member, lbaas_pool): - """Deletes the specified lbaas_member.""" - return self.delete(self.lbaas_member_path % (lbaas_pool, lbaas_member)) - - @APIParamsCall - def list_vips(self, retrieve_all=True, **_params): - """Fetches a list of all load balancer vips for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('vips', self.vips_path, retrieve_all, - **_params) - - @APIParamsCall - def show_vip(self, vip, **_params): - """Fetches information of a certain load balancer vip.""" - return self.get(self.vip_path % (vip), params=_params) - - @APIParamsCall - def create_vip(self, body=None): - """Creates a new load balancer vip.""" - return self.post(self.vips_path, body=body) - - @APIParamsCall - def update_vip(self, vip, body=None): - """Updates a load balancer vip.""" - return self.put(self.vip_path % (vip), body=body) - - @APIParamsCall - def delete_vip(self, vip): - """Deletes the specified load balancer vip.""" - return self.delete(self.vip_path % (vip)) - - @APIParamsCall - def list_pools(self, retrieve_all=True, **_params): - """Fetches a list of all load balancer pools for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('pools', self.pools_path, retrieve_all, - **_params) - - @APIParamsCall - def show_pool(self, pool, **_params): - """Fetches information of a certain load balancer pool.""" - return self.get(self.pool_path % (pool), params=_params) - - @APIParamsCall - def create_pool(self, body=None): - """Creates a new load balancer pool.""" - return self.post(self.pools_path, body=body) - - @APIParamsCall - def update_pool(self, pool, body=None): - """Updates a load balancer pool.""" - return self.put(self.pool_path % (pool), body=body) - - @APIParamsCall - def delete_pool(self, pool): - """Deletes the specified load balancer pool.""" - return self.delete(self.pool_path % (pool)) - - @APIParamsCall - def retrieve_pool_stats(self, pool, **_params): - """Retrieves stats for a certain load balancer pool.""" - return self.get(self.pool_path_stats % (pool), params=_params) - - @APIParamsCall - def list_members(self, retrieve_all=True, **_params): - """Fetches a list of all load balancer members for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('members', self.members_path, retrieve_all, - **_params) - - @APIParamsCall - def show_member(self, member, **_params): - """Fetches information of a certain load balancer member.""" - return self.get(self.member_path % (member), params=_params) - - @APIParamsCall - def create_member(self, body=None): - """Creates a new load balancer member.""" - return self.post(self.members_path, body=body) - - @APIParamsCall - def update_member(self, member, body=None): - """Updates a load balancer member.""" - return self.put(self.member_path % (member), body=body) - - @APIParamsCall - def delete_member(self, member): - """Deletes the specified load balancer member.""" - return self.delete(self.member_path % (member)) - - @APIParamsCall - def list_health_monitors(self, retrieve_all=True, **_params): - """Fetches a list of all load balancer health monitors for a tenant.""" - # Pass filters in "params" argument to do_request - return self.list('health_monitors', self.health_monitors_path, - retrieve_all, **_params) - - @APIParamsCall - def show_health_monitor(self, health_monitor, **_params): - """Fetches information of a certain load balancer health monitor.""" - return self.get(self.health_monitor_path % (health_monitor), - params=_params) - - @APIParamsCall - def create_health_monitor(self, body=None): - """Creates a new load balancer health monitor.""" - return self.post(self.health_monitors_path, body=body) - - @APIParamsCall - def update_health_monitor(self, health_monitor, body=None): - """Updates a load balancer health monitor.""" - return self.put(self.health_monitor_path % (health_monitor), body=body) - - @APIParamsCall - def delete_health_monitor(self, health_monitor): - """Deletes the specified load balancer health monitor.""" - return self.delete(self.health_monitor_path % (health_monitor)) - - @APIParamsCall - def associate_health_monitor(self, pool, body): - """Associate specified load balancer health monitor and pool.""" - return self.post(self.associate_pool_health_monitors_path % (pool), - body=body) - - @APIParamsCall - def disassociate_health_monitor(self, pool, health_monitor): - """Disassociate specified load balancer health monitor and pool.""" - path = (self.disassociate_pool_health_monitors_path % - {'pool': pool, 'health_monitor': health_monitor}) - return self.delete(path) - - @APIParamsCall - def create_qos_queue(self, body=None): - """Creates a new queue.""" - return self.post(self.qos_queues_path, body=body) - - @APIParamsCall - def list_qos_queues(self, **_params): - """Fetches a list of all queues for a tenant.""" - return self.get(self.qos_queues_path, params=_params) - - @APIParamsCall - def show_qos_queue(self, queue, **_params): - """Fetches information of a certain queue.""" - return self.get(self.qos_queue_path % (queue), - params=_params) - - @APIParamsCall - def delete_qos_queue(self, queue): - """Deletes the specified queue.""" - return self.delete(self.qos_queue_path % (queue)) - - @APIParamsCall - def list_agents(self, **_params): - """Fetches agents.""" - # Pass filters in "params" argument to do_request - return self.get(self.agents_path, params=_params) - - @APIParamsCall - def show_agent(self, agent, **_params): - """Fetches information of a certain agent.""" - return self.get(self.agent_path % (agent), params=_params) - - @APIParamsCall - def update_agent(self, agent, body=None): - """Updates an agent.""" - return self.put(self.agent_path % (agent), body=body) - - @APIParamsCall - def delete_agent(self, agent): - """Deletes the specified agent.""" - return self.delete(self.agent_path % (agent)) - - @APIParamsCall - def list_network_gateways(self, **_params): - """Retrieve network gateways.""" - return self.get(self.network_gateways_path, params=_params) - - @APIParamsCall - def show_network_gateway(self, gateway_id, **_params): - """Fetch a network gateway.""" - return self.get(self.network_gateway_path % gateway_id, params=_params) - - @APIParamsCall - def create_network_gateway(self, body=None): - """Create a new network gateway.""" - return self.post(self.network_gateways_path, body=body) - - @APIParamsCall - def update_network_gateway(self, gateway_id, body=None): - """Update a network gateway.""" - return self.put(self.network_gateway_path % gateway_id, body=body) - - @APIParamsCall - def delete_network_gateway(self, gateway_id): - """Delete the specified network gateway.""" - return self.delete(self.network_gateway_path % gateway_id) - - @APIParamsCall - def connect_network_gateway(self, gateway_id, body=None): - """Connect a network gateway to the specified network.""" - base_uri = self.network_gateway_path % gateway_id - return self.put("%s/connect_network" % base_uri, body=body) - - @APIParamsCall - def disconnect_network_gateway(self, gateway_id, body=None): - """Disconnect a network from the specified gateway.""" - base_uri = self.network_gateway_path % gateway_id - return self.put("%s/disconnect_network" % base_uri, body=body) - - @APIParamsCall - def list_gateway_devices(self, **_params): - """Retrieve gateway devices.""" - return self.get(self.gateway_devices_path, params=_params) - - @APIParamsCall - def show_gateway_device(self, gateway_device_id, **_params): - """Fetch a gateway device.""" - return self.get(self.gateway_device_path % gateway_device_id, - params=_params) - - @APIParamsCall - def create_gateway_device(self, body=None): - """Create a new gateway device.""" - return self.post(self.gateway_devices_path, body=body) - - @APIParamsCall - def update_gateway_device(self, gateway_device_id, body=None): - """Updates a new gateway device.""" - return self.put(self.gateway_device_path % gateway_device_id, - body=body) - - @APIParamsCall - def delete_gateway_device(self, gateway_device_id): - """Delete the specified gateway device.""" - return self.delete(self.gateway_device_path % gateway_device_id) - - @APIParamsCall - def list_dhcp_agent_hosting_networks(self, network, **_params): - """Fetches a list of dhcp agents hosting a network.""" - return self.get((self.network_path + self.DHCP_AGENTS) % network, - params=_params) - - @APIParamsCall - def list_networks_on_dhcp_agent(self, dhcp_agent, **_params): - """Fetches a list of dhcp agents hosting a network.""" - return self.get((self.agent_path + self.DHCP_NETS) % dhcp_agent, - params=_params) - - @APIParamsCall - def add_network_to_dhcp_agent(self, dhcp_agent, body=None): - """Adds a network to dhcp agent.""" - return self.post((self.agent_path + self.DHCP_NETS) % dhcp_agent, - body=body) - - @APIParamsCall - def remove_network_from_dhcp_agent(self, dhcp_agent, network_id): - """Remove a network from dhcp agent.""" - return self.delete((self.agent_path + self.DHCP_NETS + "/%s") % ( - dhcp_agent, network_id)) - - @APIParamsCall - def list_l3_agent_hosting_routers(self, router, **_params): - """Fetches a list of L3 agents hosting a router.""" - return self.get((self.router_path + self.L3_AGENTS) % router, - params=_params) - - @APIParamsCall - def list_routers_on_l3_agent(self, l3_agent, **_params): - """Fetches a list of L3 agents hosting a router.""" - return self.get((self.agent_path + self.L3_ROUTERS) % l3_agent, - params=_params) - - @APIParamsCall - def add_router_to_l3_agent(self, l3_agent, body): - """Adds a router to L3 agent.""" - return self.post((self.agent_path + self.L3_ROUTERS) % l3_agent, - body=body) - - @APIParamsCall - def list_firewall_rules(self, retrieve_all=True, **_params): - """Fetches a list of all firewall rules for a tenant.""" - # Pass filters in "params" argument to do_request - - return self.list('firewall_rules', self.firewall_rules_path, - retrieve_all, **_params) - - @APIParamsCall - def show_firewall_rule(self, firewall_rule, **_params): - """Fetches information of a certain firewall rule.""" - return self.get(self.firewall_rule_path % (firewall_rule), - params=_params) - - @APIParamsCall - def create_firewall_rule(self, body=None): - """Creates a new firewall rule.""" - return self.post(self.firewall_rules_path, body=body) - - @APIParamsCall - def update_firewall_rule(self, firewall_rule, body=None): - """Updates a firewall rule.""" - return self.put(self.firewall_rule_path % (firewall_rule), body=body) - - @APIParamsCall - def delete_firewall_rule(self, firewall_rule): - """Deletes the specified firewall rule.""" - return self.delete(self.firewall_rule_path % (firewall_rule)) - - @APIParamsCall - def list_firewall_policies(self, retrieve_all=True, **_params): - """Fetches a list of all firewall policies for a tenant.""" - # Pass filters in "params" argument to do_request - - return self.list('firewall_policies', self.firewall_policies_path, - retrieve_all, **_params) - - @APIParamsCall - def show_firewall_policy(self, firewall_policy, **_params): - """Fetches information of a certain firewall policy.""" - return self.get(self.firewall_policy_path % (firewall_policy), - params=_params) - - @APIParamsCall - def create_firewall_policy(self, body=None): - """Creates a new firewall policy.""" - return self.post(self.firewall_policies_path, body=body) - - @APIParamsCall - def update_firewall_policy(self, firewall_policy, body=None): - """Updates a firewall policy.""" - return self.put(self.firewall_policy_path % (firewall_policy), - body=body) - - @APIParamsCall - def delete_firewall_policy(self, firewall_policy): - """Deletes the specified firewall policy.""" - return self.delete(self.firewall_policy_path % (firewall_policy)) - - @APIParamsCall - def firewall_policy_insert_rule(self, firewall_policy, body=None): - """Inserts specified rule into firewall policy.""" - return self.put(self.firewall_policy_insert_path % (firewall_policy), - body=body) - - @APIParamsCall - def firewall_policy_remove_rule(self, firewall_policy, body=None): - """Removes specified rule from firewall policy.""" - return self.put(self.firewall_policy_remove_path % (firewall_policy), - body=body) - - @APIParamsCall - def list_firewalls(self, retrieve_all=True, **_params): - """Fetches a list of all firewals for a tenant.""" - # Pass filters in "params" argument to do_request - - return self.list('firewalls', self.firewalls_path, retrieve_all, - **_params) - - @APIParamsCall - def show_firewall(self, firewall, **_params): - """Fetches information of a certain firewall.""" - return self.get(self.firewall_path % (firewall), params=_params) - - @APIParamsCall - def create_firewall(self, body=None): - """Creates a new firewall.""" - return self.post(self.firewalls_path, body=body) - - @APIParamsCall - def update_firewall(self, firewall, body=None): - """Updates a firewall.""" - return self.put(self.firewall_path % (firewall), body=body) - - @APIParamsCall - def delete_firewall(self, firewall): - """Deletes the specified firewall.""" - return self.delete(self.firewall_path % (firewall)) - - @APIParamsCall - def remove_router_from_l3_agent(self, l3_agent, router_id): - """Remove a router from l3 agent.""" - return self.delete((self.agent_path + self.L3_ROUTERS + "/%s") % ( - l3_agent, router_id)) - - @APIParamsCall - def get_lbaas_agent_hosting_pool(self, pool, **_params): - """Fetches a loadbalancer agent hosting a pool.""" - return self.get((self.pool_path + self.LOADBALANCER_AGENT) % pool, - params=_params) - - @APIParamsCall - def list_pools_on_lbaas_agent(self, lbaas_agent, **_params): - """Fetches a list of pools hosted by the loadbalancer agent.""" - return self.get((self.agent_path + self.LOADBALANCER_POOLS) % - lbaas_agent, params=_params) - - @APIParamsCall - def list_service_providers(self, retrieve_all=True, **_params): - """Fetches service providers.""" - # Pass filters in "params" argument to do_request - return self.list('service_providers', self.service_providers_path, - retrieve_all, **_params) - - def list_credentials(self, **_params): - """Fetch a list of all credentials for a tenant.""" - return self.get(self.credentials_path, params=_params) - - @APIParamsCall - def show_credential(self, credential, **_params): - """Fetch a credential.""" - return self.get(self.credential_path % (credential), params=_params) - - @APIParamsCall - def create_credential(self, body=None): - """Create a new credential.""" - return self.post(self.credentials_path, body=body) - - @APIParamsCall - def update_credential(self, credential, body=None): - """Update a credential.""" - return self.put(self.credential_path % (credential), body=body) - - @APIParamsCall - def delete_credential(self, credential): - """Delete the specified credential.""" - return self.delete(self.credential_path % (credential)) - - def list_network_profile_bindings(self, **params): - """Fetch a list of all tenants associated for a network profile.""" - return self.get(self.network_profile_bindings_path, params=params) - - @APIParamsCall - def list_network_profiles(self, **params): - """Fetch a list of all network profiles for a tenant.""" - return self.get(self.network_profiles_path, params=params) - - @APIParamsCall - def show_network_profile(self, profile, **params): - """Fetch a network profile.""" - return self.get(self.network_profile_path % (profile), params=params) - - @APIParamsCall - def create_network_profile(self, body=None): - """Create a network profile.""" - return self.post(self.network_profiles_path, body=body) - - @APIParamsCall - def update_network_profile(self, profile, body=None): - """Update a network profile.""" - return self.put(self.network_profile_path % (profile), body=body) - - @APIParamsCall - def delete_network_profile(self, profile): - """Delete the network profile.""" - return self.delete(self.network_profile_path % profile) - - @APIParamsCall - def list_policy_profile_bindings(self, **params): - """Fetch a list of all tenants associated for a policy profile.""" - return self.get(self.policy_profile_bindings_path, params=params) - - @APIParamsCall - def list_policy_profiles(self, **params): - """Fetch a list of all network profiles for a tenant.""" - return self.get(self.policy_profiles_path, params=params) - - @APIParamsCall - def show_policy_profile(self, profile, **params): - """Fetch a network profile.""" - return self.get(self.policy_profile_path % (profile), params=params) - - @APIParamsCall - def update_policy_profile(self, profile, body=None): - """Update a policy profile.""" - return self.put(self.policy_profile_path % (profile), body=body) - - @APIParamsCall - def create_metering_label(self, body=None): - """Creates a metering label.""" - return self.post(self.metering_labels_path, body=body) - - @APIParamsCall - def delete_metering_label(self, label): - """Deletes the specified metering label.""" - return self.delete(self.metering_label_path % (label)) - - @APIParamsCall - def list_metering_labels(self, retrieve_all=True, **_params): - """Fetches a list of all metering labels for a tenant.""" - return self.list('metering_labels', self.metering_labels_path, - retrieve_all, **_params) - - @APIParamsCall - def show_metering_label(self, metering_label, **_params): - """Fetches information of a certain metering label.""" - return self.get(self.metering_label_path % - (metering_label), params=_params) - - @APIParamsCall - def create_metering_label_rule(self, body=None): - """Creates a metering label rule.""" - return self.post(self.metering_label_rules_path, body=body) - - @APIParamsCall - def delete_metering_label_rule(self, rule): - """Deletes the specified metering label rule.""" - return self.delete(self.metering_label_rule_path % (rule)) - - @APIParamsCall - def list_metering_label_rules(self, retrieve_all=True, **_params): - """Fetches a list of all metering label rules for a label.""" - return self.list('metering_label_rules', - self.metering_label_rules_path, retrieve_all, - **_params) - - @APIParamsCall - def show_metering_label_rule(self, metering_label_rule, **_params): - """Fetches information of a certain metering label rule.""" - return self.get(self.metering_label_rule_path % - (metering_label_rule), params=_params) - - @APIParamsCall - def list_net_partitions(self, **params): - """Fetch a list of all network partitions for a tenant.""" - return self.get(self.net_partitions_path, params=params) - - @APIParamsCall - def show_net_partition(self, netpartition, **params): - """Fetch a network partition.""" - return self.get(self.net_partition_path % (netpartition), - params=params) - - @APIParamsCall - def create_net_partition(self, body=None): - """Create a network partition.""" - return self.post(self.net_partitions_path, body=body) - - @APIParamsCall - def delete_net_partition(self, netpartition): - """Delete the network partition.""" - return self.delete(self.net_partition_path % netpartition) - - @APIParamsCall - def create_packet_filter(self, body=None): - """Create a new packet filter.""" - return self.post(self.packet_filters_path, body=body) - - @APIParamsCall - def update_packet_filter(self, packet_filter_id, body=None): - """Update a packet filter.""" - return self.put(self.packet_filter_path % packet_filter_id, body=body) - - @APIParamsCall - def list_packet_filters(self, retrieve_all=True, **_params): - """Fetch a list of all packet filters for a tenant.""" - return self.list('packet_filters', self.packet_filters_path, - retrieve_all, **_params) - - @APIParamsCall - def show_packet_filter(self, packet_filter_id, **_params): - """Fetch information of a certain packet filter.""" - return self.get(self.packet_filter_path % packet_filter_id, - params=_params) - - @APIParamsCall - def delete_packet_filter(self, packet_filter_id): - """Delete the specified packet filter.""" - return self.delete(self.packet_filter_path % packet_filter_id) diff --git a/awx/lib/site-packages/neutronclient/version.py b/awx/lib/site-packages/neutronclient/version.py deleted file mode 100644 index 189990079f..0000000000 --- a/awx/lib/site-packages/neutronclient/version.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# -# @author: Carl Baldwin, Hewlett-Packard - -import pbr.version - - -__version__ = pbr.version.VersionInfo('python-neutronclient').version_string() diff --git a/awx/lib/site-packages/novaclient/__init__.py b/awx/lib/site-packages/novaclient/__init__.py deleted file mode 100644 index bfa75532f4..0000000000 --- a/awx/lib/site-packages/novaclient/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import pbr.version - - -__version__ = pbr.version.VersionInfo('python-novaclient').version_string() diff --git a/awx/lib/site-packages/novaclient/auth_plugin.py b/awx/lib/site-packages/novaclient/auth_plugin.py deleted file mode 100644 index da2c07b26f..0000000000 --- a/awx/lib/site-packages/novaclient/auth_plugin.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 Spanish National Research Council. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -import pkg_resources -import six - -from novaclient import exceptions -from novaclient import utils - - -logger = logging.getLogger(__name__) - - -_discovered_plugins = {} - - -def discover_auth_systems(): - """Discover the available auth-systems. - - This won't take into account the old style auth-systems. - """ - ep_name = 'openstack.client.auth_plugin' - for ep in pkg_resources.iter_entry_points(ep_name): - try: - auth_plugin = ep.load() - except (ImportError, pkg_resources.UnknownExtra, AttributeError) as e: - logger.debug("ERROR: Cannot load auth plugin %s" % ep.name) - logger.debug(e, exc_info=1) - else: - _discovered_plugins[ep.name] = auth_plugin - - -def load_auth_system_opts(parser): - """Load options needed by the available auth-systems into a parser. - - This function will try to populate the parser with options from the - available plugins. - """ - for name, auth_plugin in six.iteritems(_discovered_plugins): - add_opts_fn = getattr(auth_plugin, "add_opts", None) - if add_opts_fn: - group = parser.add_argument_group("Auth-system '%s' options" % - name) - add_opts_fn(group) - - -def load_plugin(auth_system): - if auth_system in _discovered_plugins: - return _discovered_plugins[auth_system]() - - # NOTE(aloga): If we arrive here, the plugin will be an old-style one, - # so we have to create a fake AuthPlugin for it. - return DeprecatedAuthPlugin(auth_system) - - -class BaseAuthPlugin(object): - """Base class for authentication plugins. - - An authentication plugin needs to override at least the authenticate - method to be a valid plugin. - """ - def __init__(self): - self.opts = {} - - def get_auth_url(self): - """Return the auth url for the plugin (if any).""" - return None - - @staticmethod - def add_opts(parser): - """Populate and return the parser with the options for this plugin. - - If the plugin does not need any options, it should return the same - parser untouched. - """ - return parser - - def parse_opts(self, args): - """Parse the actual auth-system options if any. - - This method is expected to populate the attribute self.opts with a - dict containing the options and values needed to make authentication. - If the dict is empty, the client should assume that it needs the same - options as the 'keystone' auth system (i.e. os_username and - os_password). - - Returns the self.opts dict. - """ - return self.opts - - def authenticate(self, cls, auth_url): - """Authenticate using plugin defined method.""" - raise exceptions.AuthSystemNotFound(self.auth_system) - - -class DeprecatedAuthPlugin(object): - """Class to mimic the AuthPlugin class for deprecated auth systems. - - Old auth systems only define two entry points: openstack.client.auth_url - and openstack.client.authenticate. This class will load those entry points - into a class similar to a valid AuthPlugin. - """ - def __init__(self, auth_system): - self.auth_system = auth_system - - def authenticate(cls, auth_url): - raise exceptions.AuthSystemNotFound(self.auth_system) - - self.opts = {} - - self.get_auth_url = lambda: None - self.authenticate = authenticate - - self._load_endpoints() - - def _load_endpoints(self): - ep_name = 'openstack.client.auth_url' - fn = utils._load_entry_point(ep_name, name=self.auth_system) - if fn: - self.get_auth_url = fn - - ep_name = 'openstack.client.authenticate' - fn = utils._load_entry_point(ep_name, name=self.auth_system) - if fn: - self.authenticate = fn - - def parse_opts(self, args): - return self.opts diff --git a/awx/lib/site-packages/novaclient/base.py b/awx/lib/site-packages/novaclient/base.py deleted file mode 100644 index 173eda0858..0000000000 --- a/awx/lib/site-packages/novaclient/base.py +++ /dev/null @@ -1,236 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -import abc -import inspect - -import six - -from novaclient import exceptions -from novaclient.openstack.common.apiclient import base -from novaclient import utils - -Resource = base.Resource - - -def getid(obj): - """ - Abstracts the common pattern of allowing both an object or an object's ID - as a parameter when dealing with relationships. - """ - try: - return obj.id - except AttributeError: - return obj - - -class Manager(utils.HookableMixin): - """ - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, api): - self.api = api - - def _write_object_to_completion_cache(self, obj): - if hasattr(self.api, 'write_object_to_completion_cache'): - self.api.write_object_to_completion_cache(obj) - - def _clear_completion_cache_for_class(self, obj_class): - if hasattr(self.api, 'clear_completion_cache_for_class'): - self.api.clear_completion_cache_for_class(obj_class) - - def _list(self, url, response_key, obj_class=None, body=None): - if body: - _resp, body = self.api.client.post(url, body=body) - else: - _resp, body = self.api.client.get(url) - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - if isinstance(data, dict): - try: - data = data['values'] - except KeyError: - pass - - self._clear_completion_cache_for_class(obj_class) - - objs = [] - for res in data: - if res: - obj = obj_class(self, res, loaded=True) - self._write_object_to_completion_cache(obj) - objs.append(obj) - - return objs - - def _get(self, url, response_key): - _resp, body = self.api.client.get(url) - obj = self.resource_class(self, body[response_key], loaded=True) - self._write_object_to_completion_cache(obj) - return obj - - def _create(self, url, body, response_key, return_raw=False, **kwargs): - self.run_hooks('modify_body_for_create', body, **kwargs) - _resp, body = self.api.client.post(url, body=body) - if return_raw: - return body[response_key] - - obj = self.resource_class(self, body[response_key]) - self._write_object_to_completion_cache(obj) - return obj - - def _delete(self, url): - _resp, _body = self.api.client.delete(url) - - def _update(self, url, body, response_key=None, **kwargs): - self.run_hooks('modify_body_for_update', body, **kwargs) - _resp, body = self.api.client.put(url, body=body) - if body: - if response_key: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(Manager): - """ - Like a `Manager`, but with additional `find()`/`findall()` methods. - """ - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """ - Find a single item with attributes matching ``**kwargs``. - """ - matches = self.findall(**kwargs) - num_matches = len(matches) - if num_matches == 0: - msg = "No %s matching %s." % (self.resource_class.__name__, kwargs) - raise exceptions.NotFound(404, msg) - elif num_matches > 1: - raise exceptions.NoUniqueMatch - else: - return matches[0] - - def findall(self, **kwargs): - """ - Find all items with attributes matching ``**kwargs``. - """ - found = [] - searches = kwargs.items() - - detailed = True - list_kwargs = {} - - list_argspec = inspect.getargspec(self.list) - if 'detailed' in list_argspec.args: - detailed = ("human_id" not in kwargs and - "name" not in kwargs and - "display_name" not in kwargs) - list_kwargs['detailed'] = detailed - - if 'is_public' in list_argspec.args and 'is_public' in kwargs: - is_public = kwargs['is_public'] - list_kwargs['is_public'] = is_public - if is_public is None: - tmp_kwargs = kwargs.copy() - del tmp_kwargs['is_public'] - searches = tmp_kwargs.items() - - if 'search_opts' in list_argspec.args: - # pass search_opts in to do server side based filtering. - # TODO(jogo) not all search_opts support regex, find way to - # identify when to use regex and when to use string matching. - # volumes does not support regex while servers does. So when - # doing findall on servers some client side filtering is still - # needed. - if "human_id" in kwargs: - list_kwargs['search_opts'] = {"name": kwargs["human_id"]} - elif "name" in kwargs: - list_kwargs['search_opts'] = {"name": kwargs["name"]} - elif "display_name" in kwargs: - list_kwargs['search_opts'] = {"name": kwargs["display_name"]} - - listing = self.list(**list_kwargs) - - for obj in listing: - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - if detailed: - found.append(obj) - else: - found.append(self.get(obj.id)) - except AttributeError: - continue - - return found - - -class BootingManagerWithFind(ManagerWithFind): - """Like a `ManagerWithFind`, but has the ability to boot servers.""" - - def _parse_block_device_mapping(self, block_device_mapping): - bdm = [] - - for device_name, mapping in six.iteritems(block_device_mapping): - # - # The mapping is in the format: - # :[]:[]:[] - # - bdm_dict = {'device_name': device_name} - - mapping_parts = mapping.split(':') - source_id = mapping_parts[0] - bdm_dict['uuid'] = source_id - bdm_dict['boot_index'] = 0 - if len(mapping_parts) == 1: - bdm_dict['volume_id'] = source_id - bdm_dict['source_type'] = 'volume' - - elif len(mapping_parts) > 1: - source_type = mapping_parts[1] - bdm_dict['source_type'] = source_type - if source_type.startswith('snap'): - bdm_dict['snapshot_id'] = source_id - else: - bdm_dict['volume_id'] = source_id - - if len(mapping_parts) > 2 and mapping_parts[2]: - bdm_dict['volume_size'] = str(int(mapping_parts[2])) - - if len(mapping_parts) > 3: - bdm_dict['delete_on_termination'] = mapping_parts[3] - - bdm.append(bdm_dict) - return bdm diff --git a/awx/lib/site-packages/novaclient/client.py b/awx/lib/site-packages/novaclient/client.py deleted file mode 100644 index b0d9aea107..0000000000 --- a/awx/lib/site-packages/novaclient/client.py +++ /dev/null @@ -1,765 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Piston Cloud Computing, Inc. - -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -import copy -import errno -import functools -import glob -import hashlib -import logging -import os -import re -import time - -from keystoneclient import adapter -from oslo.utils import netutils -import requests -from requests import adapters - -try: - import json -except ImportError: - import simplejson as json - -from six.moves.urllib import parse - -from novaclient import exceptions -from novaclient.openstack.common.gettextutils import _ -from novaclient import service_catalog -from novaclient import utils - - -class _ClientConnectionPool(object): - - def __init__(self): - self._adapters = {} - - def get(self, url): - """ - Store and reuse HTTP adapters per Service URL. - """ - if url not in self._adapters: - self._adapters[url] = adapters.HTTPAdapter() - - return self._adapters[url] - - -class CompletionCache(object): - """The completion cache is how we support tab-completion with novaclient. - - The `Manager` writes object IDs and Human-IDs to the completion-cache on - object-show, object-list, and object-create calls. - - The `nova.bash_completion` script then uses these files to provide the - actual tab-completion. - - The cache directory layout is: - - ~/.novaclient/ - / - -id-cache - -human-id-cache - """ - def __init__(self, username, auth_url, attributes=('id', 'human_id')): - self.directory = self._make_directory_name(username, auth_url) - self.attributes = attributes - - def _make_directory_name(self, username, auth_url): - """Creates a unique directory name based on the auth_url and username - of the current user. - """ - uniqifier = hashlib.md5(username.encode('utf-8') + - auth_url.encode('utf-8')).hexdigest() - base_dir = utils.env('NOVACLIENT_UUID_CACHE_DIR', - default="~/.novaclient") - return os.path.expanduser(os.path.join(base_dir, uniqifier)) - - def _prepare_directory(self): - try: - os.makedirs(self.directory, 0o755) - except OSError: - # NOTE(kiall): This is typically either permission denied while - # attempting to create the directory, or the - # directory already exists. Either way, don't - # fail. - pass - - def clear_class(self, obj_class): - self._prepare_directory() - - resource = obj_class.__name__.lower() - resource_glob = os.path.join(self.directory, "%s-*-cache" % resource) - - for filename in glob.iglob(resource_glob): - try: - os.unlink(filename) - except OSError as e: - if e.errno != errno.ENOENT: - raise - - def _write_attribute(self, resource, attribute, value): - self._prepare_directory() - - filename = "%s-%s-cache" % (resource, attribute.replace('_', '-')) - path = os.path.join(self.directory, filename) - - with open(path, 'a') as f: - f.write("%s\n" % value) - - def write_object(self, obj): - resource = obj.__class__.__name__.lower() - - for attribute in self.attributes: - value = getattr(obj, attribute, None) - if value: - self._write_attribute(resource, attribute, value) - - -class SessionClient(adapter.LegacyJsonAdapter): - - def request(self, url, method, **kwargs): - # NOTE(jamielennox): The standard call raises errors from - # keystoneclient, where we need to raise the novaclient errors. - raise_exc = kwargs.pop('raise_exc', True) - resp, body = super(SessionClient, self).request(url, - method, - raise_exc=False, - **kwargs) - - if raise_exc and resp.status_code >= 400: - raise exceptions.from_response(resp, body, url, method) - - return resp, body - - -def _original_only(f): - """Indicates and enforces that this function can only be used if we are - using the original HTTPClient object. - - We use this to specify that if you use the newer Session HTTP client then - you are aware that the way you use your client has been updated and certain - functions are no longer allowed to be used. - """ - @functools.wraps(f) - def wrapper(self, *args, **kwargs): - if isinstance(self.client, SessionClient): - msg = ('This call is no longer available. The operation should ' - 'be performed on the session object instead.') - raise exceptions.InvalidUsage(msg) - - return f(self, *args, **kwargs) - - return wrapper - - -class HTTPClient(object): - USER_AGENT = 'python-novaclient' - - def __init__(self, user, password, projectid=None, auth_url=None, - insecure=False, timeout=None, proxy_tenant_id=None, - proxy_token=None, region_name=None, - endpoint_type='publicURL', service_type=None, - service_name=None, volume_service_name=None, - timings=False, bypass_url=None, - os_cache=False, no_cache=True, - http_log_debug=False, auth_system='keystone', - auth_plugin=None, auth_token=None, - cacert=None, tenant_id=None, user_id=None, - connection_pool=False): - self.user = user - self.user_id = user_id - self.password = password - self.projectid = projectid - self.tenant_id = tenant_id - - self._connection_pool = (_ClientConnectionPool() - if connection_pool else None) - - # This will be called by #_get_password if self.password is None. - # EG if a password can only be obtained by prompting the user, but a - # token is available, you don't want to prompt until the token has - # been proven invalid - self.password_func = None - - if auth_system and auth_system != 'keystone' and not auth_plugin: - raise exceptions.AuthSystemNotFound(auth_system) - - if not auth_url and auth_system and auth_system != 'keystone': - auth_url = auth_plugin.get_auth_url() - if not auth_url: - raise exceptions.EndpointNotFound() - self.auth_url = auth_url.rstrip('/') if auth_url else auth_url - self.version = 'v1.1' - self.region_name = region_name - self.endpoint_type = endpoint_type - self.service_type = service_type - self.service_name = service_name - self.volume_service_name = volume_service_name - self.timings = timings - self.bypass_url = bypass_url.rstrip('/') if bypass_url else bypass_url - self.os_cache = os_cache or not no_cache - self.http_log_debug = http_log_debug - if timeout is not None: - self.timeout = float(timeout) - else: - self.timeout = None - - self.times = [] # [("item", starttime, endtime), ...] - - self.management_url = self.bypass_url or None - self.auth_token = auth_token - self.proxy_token = proxy_token - self.proxy_tenant_id = proxy_tenant_id - self.keyring_saver = None - self.keyring_saved = False - - if insecure: - self.verify_cert = False - else: - if cacert: - self.verify_cert = cacert - else: - self.verify_cert = True - - self.auth_system = auth_system - self.auth_plugin = auth_plugin - self._session = None - self._current_url = None - self._logger = logging.getLogger(__name__) - - if self.http_log_debug and not self._logger.handlers: - # Logging level is already set on the root logger - ch = logging.StreamHandler() - self._logger.addHandler(ch) - self._logger.propagate = False - if hasattr(requests, 'logging'): - rql = requests.logging.getLogger(requests.__name__) - rql.addHandler(ch) - # Since we have already setup the root logger on debug, we - # have to set it up here on WARNING (its original level) - # otherwise we will get all the requests logging messages - rql.setLevel(logging.WARNING) - - def use_token_cache(self, use_it): - self.os_cache = use_it - - def unauthenticate(self): - """Forget all of our authentication information.""" - self.management_url = None - self.auth_token = None - - def set_management_url(self, url): - self.management_url = url - - def get_timings(self): - return self.times - - def reset_timings(self): - self.times = [] - - def _redact(self, target, path, text=None): - """Replace the value of a key in `target`. - - The key can be at the top level by specifying a list with a single - key as the path. Nested dictionaries are also supported by passing a - list of keys to be navigated to find the one that should be replaced. - In this case the last one is the one that will be replaced. - - :param dict target: the dictionary that may have a key to be redacted; - modified in place - :param list path: a list representing the nested structure in `target` - that should be redacted; modified in place - :param string text: optional text to use as a replacement for the - redacted key. if text is not specified, the - default text will be sha1 hash of the value being - redacted - """ - - key = path.pop() - - # move to the most nested dict - for p in path: - try: - target = target[p] - except KeyError: - return - - if key in target: - if text: - target[key] = text - else: - # because in python3 byte string handling is ... ug - value = target[key].encode('utf-8') - sha1sum = hashlib.sha1(value) - target[key] = "{SHA1}%s" % sha1sum.hexdigest() - - def http_log_req(self, method, url, kwargs): - if not self.http_log_debug: - return - - string_parts = ['curl -i'] - - if not kwargs.get('verify', True): - string_parts.append(' --insecure') - - string_parts.append(" '%s'" % url) - string_parts.append(' -X %s' % method) - - headers = copy.deepcopy(kwargs['headers']) - self._redact(headers, ['X-Auth-Token']) - # because dict ordering changes from 2 to 3 - keys = sorted(headers.keys()) - for name in keys: - value = headers[name] - header = ' -H "%s: %s"' % (name, value) - string_parts.append(header) - - if 'data' in kwargs: - data = json.loads(kwargs['data']) - self._redact(data, ['auth', 'passwordCredentials', 'password']) - string_parts.append(" -d '%s'" % json.dumps(data)) - self._logger.debug("REQ: %s" % "".join(string_parts)) - - def http_log_resp(self, resp): - if not self.http_log_debug: - return - - if resp.text and resp.status_code != 400: - try: - body = json.loads(resp.text) - self._redact(body, ['access', 'token', 'id']) - except ValueError: - body = None - else: - body = None - - self._logger.debug("RESP: [%(status)s] %(headers)s\nRESP BODY: " - "%(text)s\n", {'status': resp.status_code, - 'headers': resp.headers, - 'text': json.dumps(body)}) - - def open_session(self): - if not self._connection_pool: - self._session = requests.Session() - - def close_session(self): - if self._session and not self._connection_pool: - self._session.close() - self._session = None - - def _get_session(self, url): - if self._connection_pool: - magic_tuple = parse.urlsplit(url) - scheme, netloc, path, query, frag = magic_tuple - service_url = '%s://%s' % (scheme, netloc) - if self._current_url != service_url: - # Invalidate Session object in case the url is somehow changed - if self._session: - self._session.close() - self._current_url = service_url - self._logger.debug( - "New session created for: (%s)" % service_url) - self._session = requests.Session() - self._session.mount(service_url, - self._connection_pool.get(service_url)) - return self._session - elif self._session: - return self._session - - def request(self, url, method, **kwargs): - kwargs.setdefault('headers', kwargs.get('headers', {})) - kwargs['headers']['User-Agent'] = self.USER_AGENT - kwargs['headers']['Accept'] = 'application/json' - if 'body' in kwargs: - kwargs['headers']['Content-Type'] = 'application/json' - kwargs['data'] = json.dumps(kwargs['body']) - del kwargs['body'] - if self.timeout is not None: - kwargs.setdefault('timeout', self.timeout) - kwargs['verify'] = self.verify_cert - - self.http_log_req(method, url, kwargs) - - request_func = requests.request - session = self._get_session(url) - if session: - request_func = session.request - - resp = request_func( - method, - url, - **kwargs) - - self.http_log_resp(resp) - - if resp.text: - # TODO(dtroyer): verify the note below in a requests context - # NOTE(alaski): Because force_exceptions_to_status_code=True - # httplib2 returns a connection refused event as a 400 response. - # To determine if it is a bad request or refused connection we need - # to check the body. httplib2 tests check for 'Connection refused' - # or 'actively refused' in the body, so that's what we'll do. - if resp.status_code == 400: - if ('Connection refused' in resp.text or - 'actively refused' in resp.text): - raise exceptions.ConnectionRefused(resp.text) - try: - body = json.loads(resp.text) - except ValueError: - body = None - else: - body = None - - if resp.status_code >= 400: - raise exceptions.from_response(resp, body, url, method) - - return resp, body - - def _time_request(self, url, method, **kwargs): - start_time = time.time() - resp, body = self.request(url, method, **kwargs) - self.times.append(("%s %s" % (method, url), - start_time, time.time())) - return resp, body - - def _cs_request(self, url, method, **kwargs): - if not self.management_url: - self.authenticate() - if url is None: - # To get API version information, it is necessary to GET - # a nova endpoint directly without "v2/". - magic_tuple = parse.urlsplit(self.management_url) - scheme, netloc, path, query, frag = magic_tuple - path = re.sub(r'v[1-9]/[a-z0-9]+$', '', path) - url = parse.urlunsplit((scheme, netloc, path, None, None)) - else: - url = self.management_url + url - - # Perform the request once. If we get a 401 back then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - kwargs.setdefault('headers', {})['X-Auth-Token'] = self.auth_token - if self.projectid: - kwargs['headers']['X-Auth-Project-Id'] = self.projectid - - resp, body = self._time_request(url, method, **kwargs) - return resp, body - except exceptions.Unauthorized as e: - try: - # first discard auth token, to avoid the possibly expired - # token being re-used in the re-authentication attempt - self.unauthenticate() - # overwrite bad token - self.keyring_saved = False - self.authenticate() - kwargs['headers']['X-Auth-Token'] = self.auth_token - resp, body = self._time_request(url, method, **kwargs) - return resp, body - except exceptions.Unauthorized: - raise e - - def _get_password(self): - if not self.password and self.password_func: - self.password = self.password_func() - return self.password - - def get(self, url, **kwargs): - return self._cs_request(url, 'GET', **kwargs) - - def post(self, url, **kwargs): - return self._cs_request(url, 'POST', **kwargs) - - def put(self, url, **kwargs): - return self._cs_request(url, 'PUT', **kwargs) - - def delete(self, url, **kwargs): - return self._cs_request(url, 'DELETE', **kwargs) - - def _extract_service_catalog(self, url, resp, body, extract_token=True): - """See what the auth service told us and process the response. - We may get redirected to another site, fail or actually get - back a service catalog with a token and our endpoints. - """ - - # content must always present - if resp.status_code == 200 or resp.status_code == 201: - try: - self.auth_url = url - self.service_catalog = \ - service_catalog.ServiceCatalog(body) - if extract_token: - self.auth_token = self.service_catalog.get_token() - self.tenant_id = self.service_catalog.get_tenant_id() - - management_url = self.service_catalog.url_for( - attr='region', - filter_value=self.region_name, - endpoint_type=self.endpoint_type, - service_type=self.service_type, - service_name=self.service_name, - volume_service_name=self.volume_service_name,) - self.management_url = management_url.rstrip('/') - return None - except exceptions.AmbiguousEndpoints: - print(_("Found more than one valid endpoint. Use a more " - "restrictive filter")) - raise - except KeyError: - raise exceptions.AuthorizationFailure() - except exceptions.EndpointNotFound: - print(_("Could not find any suitable endpoint. Correct " - "region?")) - raise - - elif resp.status_code == 305: - return resp.headers['location'] - else: - raise exceptions.from_response(resp, body, url) - - def _fetch_endpoints_from_auth(self, url): - """We have a token, but don't know the final endpoint for - the region. We have to go back to the auth service and - ask again. This request requires an admin-level token - to work. The proxy token supplied could be from a low-level enduser. - - We can't get this from the keystone service endpoint, we have to use - the admin endpoint. - - This will overwrite our admin token with the user token. - """ - - # GET ...:5001/v2.0/tokens/#####/endpoints - url = '/'.join([url, 'tokens', '%s?belongsTo=%s' - % (self.proxy_token, self.proxy_tenant_id)]) - self._logger.debug("Using Endpoint URL: %s" % url) - resp, body = self._time_request( - url, "GET", headers={'X-Auth-Token': self.auth_token}) - return self._extract_service_catalog(url, resp, body, - extract_token=False) - - def authenticate(self): - magic_tuple = netutils.urlsplit(self.auth_url) - scheme, netloc, path, query, frag = magic_tuple - port = magic_tuple.port - if port is None: - port = 80 - path_parts = path.split('/') - for part in path_parts: - if len(part) > 0 and part[0] == 'v': - self.version = part - break - - if self.auth_token and self.management_url: - self._save_keys() - return - - # TODO(sandy): Assume admin endpoint is 35357 for now. - # Ideally this is going to have to be provided by the service catalog. - new_netloc = netloc.replace(':%d' % port, ':%d' % (35357,)) - admin_url = parse.urlunsplit( - (scheme, new_netloc, path, query, frag)) - - auth_url = self.auth_url - if self.version == "v2.0": # FIXME(chris): This should be better. - while auth_url: - if not self.auth_system or self.auth_system == 'keystone': - auth_url = self._v2_auth(auth_url) - else: - auth_url = self._plugin_auth(auth_url) - - # Are we acting on behalf of another user via an - # existing token? If so, our actual endpoints may - # be different than that of the admin token. - if self.proxy_token: - if self.bypass_url: - self.set_management_url(self.bypass_url) - else: - self._fetch_endpoints_from_auth(admin_url) - # Since keystone no longer returns the user token - # with the endpoints any more, we need to replace - # our service account token with the user token. - self.auth_token = self.proxy_token - else: - try: - while auth_url: - auth_url = self._v1_auth(auth_url) - # In some configurations nova makes redirection to - # v2.0 keystone endpoint. Also, new location does not contain - # real endpoint, only hostname and port. - except exceptions.AuthorizationFailure: - if auth_url.find('v2.0') < 0: - auth_url = auth_url + '/v2.0' - self._v2_auth(auth_url) - - if self.bypass_url: - self.set_management_url(self.bypass_url) - elif not self.management_url: - raise exceptions.Unauthorized('Nova Client') - - self._save_keys() - - def _save_keys(self): - # Store the token/mgmt url in the keyring for later requests. - if (self.keyring_saver and self.os_cache and not self.keyring_saved - and self.auth_token and self.management_url - and self.tenant_id): - self.keyring_saver.save(self.auth_token, - self.management_url, - self.tenant_id) - # Don't save it again - self.keyring_saved = True - - def _v1_auth(self, url): - if self.proxy_token: - raise exceptions.NoTokenLookupException() - - headers = {'X-Auth-User': self.user, - 'X-Auth-Key': self._get_password()} - if self.projectid: - headers['X-Auth-Project-Id'] = self.projectid - - resp, body = self._time_request(url, 'GET', headers=headers) - if resp.status_code in (200, 204): # in some cases we get No Content - try: - mgmt_header = 'x-server-management-url' - self.management_url = resp.headers[mgmt_header].rstrip('/') - self.auth_token = resp.headers['x-auth-token'] - self.auth_url = url - except (KeyError, TypeError): - raise exceptions.AuthorizationFailure() - elif resp.status_code == 305: - return resp.headers['location'] - else: - raise exceptions.from_response(resp, body, url) - - def _plugin_auth(self, auth_url): - return self.auth_plugin.authenticate(self, auth_url) - - def _v2_auth(self, url): - """Authenticate against a v2.0 auth service.""" - if self.auth_token: - body = {"auth": { - "token": {"id": self.auth_token}}} - elif self.user_id: - body = {"auth": { - "passwordCredentials": {"userId": self.user_id, - "password": self._get_password()}}} - else: - body = {"auth": { - "passwordCredentials": {"username": self.user, - "password": self._get_password()}}} - - if self.tenant_id: - body['auth']['tenantId'] = self.tenant_id - elif self.projectid: - body['auth']['tenantName'] = self.projectid - - return self._authenticate(url, body) - - def _authenticate(self, url, body, **kwargs): - """Authenticate and extract the service catalog.""" - method = "POST" - token_url = url + "/tokens" - - # Make sure we follow redirects when trying to reach Keystone - resp, respbody = self._time_request( - token_url, - method, - body=body, - allow_redirects=True, - **kwargs) - - return self._extract_service_catalog(url, resp, respbody) - - -def _construct_http_client(username=None, password=None, project_id=None, - auth_url=None, insecure=False, timeout=None, - proxy_tenant_id=None, proxy_token=None, - region_name=None, endpoint_type='publicURL', - extensions=None, service_type='compute', - service_name=None, volume_service_name=None, - timings=False, bypass_url=None, os_cache=False, - no_cache=True, http_log_debug=False, - auth_system='keystone', auth_plugin=None, - auth_token=None, cacert=None, tenant_id=None, - user_id=None, connection_pool=False, session=None, - auth=None, user_agent='python-novaclient', - **kwargs): - if session: - return SessionClient(session=session, - auth=auth, - interface=endpoint_type, - service_type=service_type, - region_name=region_name, - service_name=service_name, - user_agent=user_agent, - **kwargs) - else: - # FIXME(jamielennox): username and password are now optional. Need - # to test that they were provided in this mode. - return HTTPClient(username, - password, - user_id=user_id, - projectid=project_id, - tenant_id=tenant_id, - auth_url=auth_url, - auth_token=auth_token, - insecure=insecure, - timeout=timeout, - auth_system=auth_system, - auth_plugin=auth_plugin, - proxy_token=proxy_token, - proxy_tenant_id=proxy_tenant_id, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - timings=timings, - bypass_url=bypass_url, - os_cache=os_cache, - http_log_debug=http_log_debug, - cacert=cacert, - connection_pool=connection_pool) - - -def get_client_class(version): - version_map = { - '1.1': 'novaclient.v1_1.client.Client', - '2': 'novaclient.v1_1.client.Client', - '3': 'novaclient.v3.client.Client', - } - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = _("Invalid client version '%(version)s'. must be one of: " - "%(keys)s") % {'version': version, - 'keys': ', '.join(version_map.keys())} - raise exceptions.UnsupportedVersion(msg) - - return utils.import_class(client_path) - - -def Client(version, *args, **kwargs): - client_class = get_client_class(version) - return client_class(*args, **kwargs) diff --git a/awx/lib/site-packages/novaclient/crypto.py b/awx/lib/site-packages/novaclient/crypto.py deleted file mode 100644 index 21af60cdc4..0000000000 --- a/awx/lib/site-packages/novaclient/crypto.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2013 Nebula, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import base64 -import subprocess - - -class DecryptionFailure(Exception): - pass - - -def decrypt_password(private_key, password): - """Base64 decodes password and unencrypts it with private key. - - Requires openssl binary available in the path. - """ - unencoded = base64.b64decode(password) - cmd = ['openssl', 'rsautl', '-decrypt', '-inkey', private_key] - proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out, err = proc.communicate(unencoded) - proc.stdin.close() - if proc.returncode: - raise DecryptionFailure(err) - return out diff --git a/awx/lib/site-packages/novaclient/exceptions.py b/awx/lib/site-packages/novaclient/exceptions.py deleted file mode 100644 index d550b754b6..0000000000 --- a/awx/lib/site-packages/novaclient/exceptions.py +++ /dev/null @@ -1,261 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception definitions. -""" - - -class UnsupportedVersion(Exception): - """Indicates that the user is trying to use an unsupported - version of the API. - """ - pass - - -class CommandError(Exception): - pass - - -class AuthorizationFailure(Exception): - pass - - -class NoUniqueMatch(Exception): - pass - - -class AuthSystemNotFound(Exception): - """When the user specify a AuthSystem but not installed.""" - def __init__(self, auth_system): - self.auth_system = auth_system - - def __str__(self): - return "AuthSystemNotFound: %s" % repr(self.auth_system) - - -class NoTokenLookupException(Exception): - """This form of authentication does not support looking up - endpoints from an existing token. - """ - pass - - -class EndpointNotFound(Exception): - """Could not find Service or Region in Service Catalog.""" - pass - - -class AmbiguousEndpoints(Exception): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - self.endpoints = endpoints - - def __str__(self): - return "AmbiguousEndpoints: %s" % repr(self.endpoints) - - -class ConnectionRefused(Exception): - """ - Connection refused: the server refused the connection. - """ - def __init__(self, response=None): - self.response = response - - def __str__(self): - return "ConnectionRefused: %s" % repr(self.response) - - -class InstanceInErrorState(Exception): - """Instance is in the error state.""" - pass - - -class ClientException(Exception): - """ - The base exception class for all exceptions this library raises. - """ - message = 'Unknown Error' - - def __init__(self, code, message=None, details=None, request_id=None, - url=None, method=None): - self.code = code - self.message = message or self.__class__.message - self.details = details - self.request_id = request_id - self.url = url - self.method = method - - def __str__(self): - formatted_string = "%s (HTTP %s)" % (self.message, self.code) - if self.request_id: - formatted_string += " (Request-ID: %s)" % self.request_id - - return formatted_string - - -class RetryAfterException(ClientException): - """ - The base exception class for ClientExceptions that use Retry-After header. - """ - def __init__(self, *args, **kwargs): - try: - self.retry_after = int(kwargs.pop('retry_after')) - except (KeyError, ValueError): - self.retry_after = 0 - - super(RetryAfterException, self).__init__(*args, **kwargs) - - -class BadRequest(ClientException): - """ - HTTP 400 - Bad request: you sent some malformed data. - """ - http_status = 400 - message = "Bad request" - - -class Unauthorized(ClientException): - """ - HTTP 401 - Unauthorized: bad credentials. - """ - http_status = 401 - message = "Unauthorized" - - -class Forbidden(ClientException): - """ - HTTP 403 - Forbidden: your credentials don't give you access to this - resource. - """ - http_status = 403 - message = "Forbidden" - - -class NotFound(ClientException): - """ - HTTP 404 - Not found - """ - http_status = 404 - message = "Not found" - - -class MethodNotAllowed(ClientException): - """ - HTTP 405 - Method Not Allowed - """ - http_status = 405 - message = "Method Not Allowed" - - -class Conflict(ClientException): - """ - HTTP 409 - Conflict - """ - http_status = 409 - message = "Conflict" - - -class OverLimit(RetryAfterException): - """ - HTTP 413 - Over limit: you're over the API limits for this time period. - """ - http_status = 413 - message = "Over limit" - - -class RateLimit(RetryAfterException): - """ - HTTP 429 - Rate limit: you've sent too many requests for this time period. - """ - http_status = 429 - message = "Rate limit" - - -# NotImplemented is a python keyword. -class HTTPNotImplemented(ClientException): - """ - HTTP 501 - Not Implemented: the server does not support this operation. - """ - http_status = 501 - message = "Not Implemented" - - -# In Python 2.4 Exception is old-style and thus doesn't have a __subclasses__() -# so we can do this: -# _code_map = dict((c.http_status, c) -# for c in ClientException.__subclasses__()) -# -# Instead, we have to hardcode it: -_error_classes = [BadRequest, Unauthorized, Forbidden, NotFound, - MethodNotAllowed, Conflict, OverLimit, RateLimit, - HTTPNotImplemented] -_code_map = dict((c.http_status, c) for c in _error_classes) - - -class InvalidUsage(RuntimeError): - """This function call is invalid in the way you are using this client. - - Due to the transition to using keystoneclient some function calls are no - longer available. You should make a similar call to the session object - instead. - """ - pass - - -def from_response(response, body, url, method=None): - """ - Return an instance of an ClientException or subclass - based on an requests response. - - Usage:: - - resp, body = requests.request(...) - if resp.status_code != 200: - raise exception_from_response(resp, rest.text) - """ - cls = _code_map.get(response.status_code, ClientException) - - kwargs = { - 'code': response.status_code, - 'method': method, - 'url': url, - 'request_id': None, - } - - if response.headers: - kwargs['request_id'] = response.headers.get('x-compute-request-id') - - if (issubclass(cls, RetryAfterException) and - 'retry-after' in response.headers): - kwargs['retry_after'] = response.headers.get('retry-after') - - if body: - message = "n/a" - details = "n/a" - - if hasattr(body, 'keys'): - error = body[list(body)[0]] - message = error.get('message') - details = error.get('details') - - kwargs['message'] = message - kwargs['details'] = details - - return cls(**kwargs) - - -class ResourceNotFound(Exception): - """Error in getting the resource.""" - pass diff --git a/awx/lib/site-packages/novaclient/extension.py b/awx/lib/site-packages/novaclient/extension.py deleted file mode 100644 index ac105070a6..0000000000 --- a/awx/lib/site-packages/novaclient/extension.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient import utils - - -class Extension(utils.HookableMixin): - """Extension descriptor.""" - - SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') - - def __init__(self, name, module): - self.name = name - self.module = module - self._parse_extension_module() - - def _parse_extension_module(self): - self.manager_class = None - for attr_name, attr_value in self.module.__dict__.items(): - if attr_name in self.SUPPORTED_HOOKS: - self.add_hook(attr_name, attr_value) - elif utils.safe_issubclass(attr_value, base.Manager): - self.manager_class = attr_value - - def __repr__(self): - return "" % self.name diff --git a/awx/lib/site-packages/novaclient/i18n.py b/awx/lib/site-packages/novaclient/i18n.py deleted file mode 100644 index e9d39d4ab8..0000000000 --- a/awx/lib/site-packages/novaclient/i18n.py +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module for novaclient. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html . - -""" - -from oslo import i18n - - -_translators = i18n.TranslatorFactory(domain='novaclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/novaclient/openstack/__init__.py b/awx/lib/site-packages/novaclient/openstack/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/openstack/common/__init__.py b/awx/lib/site-packages/novaclient/openstack/common/__init__.py deleted file mode 100644 index d1223eaf76..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - - -six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox')) diff --git a/awx/lib/site-packages/novaclient/openstack/common/_i18n.py b/awx/lib/site-packages/novaclient/openstack/common/_i18n.py deleted file mode 100644 index 6ae2ff239b..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/_i18n.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html - -""" - -import oslo.i18n - - -# NOTE(dhellmann): This reference to o-s-l-o will be replaced by the -# application name when this module is synced into the separate -# repository. It is OK to have more than one translation function -# using the same domain, since there will still only be one message -# catalog. -_translators = oslo.i18n.TranslatorFactory(domain='novaclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/novaclient/openstack/common/apiclient/__init__.py b/awx/lib/site-packages/novaclient/openstack/common/apiclient/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/openstack/common/apiclient/auth.py b/awx/lib/site-packages/novaclient/openstack/common/apiclient/auth.py deleted file mode 100644 index 67a1bf7ddd..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/apiclient/auth.py +++ /dev/null @@ -1,221 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# Copyright 2013 Spanish National Research Council. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import abc -import argparse -import os - -import six -from stevedore import extension - -from novaclient.openstack.common.apiclient import exceptions - - -_discovered_plugins = {} - - -def discover_auth_systems(): - """Discover the available auth-systems. - - This won't take into account the old style auth-systems. - """ - global _discovered_plugins - _discovered_plugins = {} - - def add_plugin(ext): - _discovered_plugins[ext.name] = ext.plugin - - ep_namespace = "novaclient.openstack.common.apiclient.auth" - mgr = extension.ExtensionManager(ep_namespace) - mgr.map(add_plugin) - - -def load_auth_system_opts(parser): - """Load options needed by the available auth-systems into a parser. - - This function will try to populate the parser with options from the - available plugins. - """ - group = parser.add_argument_group("Common auth options") - BaseAuthPlugin.add_common_opts(group) - for name, auth_plugin in six.iteritems(_discovered_plugins): - group = parser.add_argument_group( - "Auth-system '%s' options" % name, - conflict_handler="resolve") - auth_plugin.add_opts(group) - - -def load_plugin(auth_system): - try: - plugin_class = _discovered_plugins[auth_system] - except KeyError: - raise exceptions.AuthSystemNotFound(auth_system) - return plugin_class(auth_system=auth_system) - - -def load_plugin_from_args(args): - """Load required plugin and populate it with options. - - Try to guess auth system if it is not specified. Systems are tried in - alphabetical order. - - :type args: argparse.Namespace - :raises: AuthPluginOptionsMissing - """ - auth_system = args.os_auth_system - if auth_system: - plugin = load_plugin(auth_system) - plugin.parse_opts(args) - plugin.sufficient_options() - return plugin - - for plugin_auth_system in sorted(six.iterkeys(_discovered_plugins)): - plugin_class = _discovered_plugins[plugin_auth_system] - plugin = plugin_class() - plugin.parse_opts(args) - try: - plugin.sufficient_options() - except exceptions.AuthPluginOptionsMissing: - continue - return plugin - raise exceptions.AuthPluginOptionsMissing(["auth_system"]) - - -@six.add_metaclass(abc.ABCMeta) -class BaseAuthPlugin(object): - """Base class for authentication plugins. - - An authentication plugin needs to override at least the authenticate - method to be a valid plugin. - """ - - auth_system = None - opt_names = [] - common_opt_names = [ - "auth_system", - "username", - "password", - "tenant_name", - "token", - "auth_url", - ] - - def __init__(self, auth_system=None, **kwargs): - self.auth_system = auth_system or self.auth_system - self.opts = dict((name, kwargs.get(name)) - for name in self.opt_names) - - @staticmethod - def _parser_add_opt(parser, opt): - """Add an option to parser in two variants. - - :param opt: option name (with underscores) - """ - dashed_opt = opt.replace("_", "-") - env_var = "OS_%s" % opt.upper() - arg_default = os.environ.get(env_var, "") - arg_help = "Defaults to env[%s]." % env_var - parser.add_argument( - "--os-%s" % dashed_opt, - metavar="<%s>" % dashed_opt, - default=arg_default, - help=arg_help) - parser.add_argument( - "--os_%s" % opt, - metavar="<%s>" % dashed_opt, - help=argparse.SUPPRESS) - - @classmethod - def add_opts(cls, parser): - """Populate the parser with the options for this plugin. - """ - for opt in cls.opt_names: - # use `BaseAuthPlugin.common_opt_names` since it is never - # changed in child classes - if opt not in BaseAuthPlugin.common_opt_names: - cls._parser_add_opt(parser, opt) - - @classmethod - def add_common_opts(cls, parser): - """Add options that are common for several plugins. - """ - for opt in cls.common_opt_names: - cls._parser_add_opt(parser, opt) - - @staticmethod - def get_opt(opt_name, args): - """Return option name and value. - - :param opt_name: name of the option, e.g., "username" - :param args: parsed arguments - """ - return (opt_name, getattr(args, "os_%s" % opt_name, None)) - - def parse_opts(self, args): - """Parse the actual auth-system options if any. - - This method is expected to populate the attribute `self.opts` with a - dict containing the options and values needed to make authentication. - """ - self.opts.update(dict(self.get_opt(opt_name, args) - for opt_name in self.opt_names)) - - def authenticate(self, http_client): - """Authenticate using plugin defined method. - - The method usually analyses `self.opts` and performs - a request to authentication server. - - :param http_client: client object that needs authentication - :type http_client: HTTPClient - :raises: AuthorizationFailure - """ - self.sufficient_options() - self._do_authenticate(http_client) - - @abc.abstractmethod - def _do_authenticate(self, http_client): - """Protected method for authentication. - """ - - def sufficient_options(self): - """Check if all required options are present. - - :raises: AuthPluginOptionsMissing - """ - missing = [opt - for opt in self.opt_names - if not self.opts.get(opt)] - if missing: - raise exceptions.AuthPluginOptionsMissing(missing) - - @abc.abstractmethod - def token_and_endpoint(self, endpoint_type, service_type): - """Return token and endpoint. - - :param service_type: Service type of the endpoint - :type service_type: string - :param endpoint_type: Type of endpoint. - Possible values: public or publicURL, - internal or internalURL, - admin or adminURL - :type endpoint_type: string - :returns: tuple of token and endpoint strings - :raises: EndpointException - """ diff --git a/awx/lib/site-packages/novaclient/openstack/common/apiclient/base.py b/awx/lib/site-packages/novaclient/openstack/common/apiclient/base.py deleted file mode 100644 index 8380ba397f..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/apiclient/base.py +++ /dev/null @@ -1,525 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2012 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Base utilities to build API operation managers and objects on top of. -""" - -# E1102: %s is not callable -# pylint: disable=E1102 - -import abc -import copy - -import six -from six.moves.urllib import parse - -from novaclient.openstack.common.apiclient import exceptions -from novaclient.openstack.common.gettextutils import _ -from novaclient.openstack.common import strutils -from novaclient.openstack.common import uuidutils - - -def getid(obj): - """Return id if argument is a Resource. - - Abstracts the common pattern of allowing both an object or an object's ID - (UUID) as a parameter when dealing with relationships. - """ - try: - if obj.uuid: - return obj.uuid - except AttributeError: - pass - try: - return obj.id - except AttributeError: - return obj - - -# TODO(aababilov): call run_hooks() in HookableMixin's child classes -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - """Add a new hook of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param hook_func: hook function - """ - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - """Run all hooks of specified type. - - :param cls: class that registers hooks - :param hook_type: hook type, e.g., '__pre_parse_args__' - :param args: args to be passed to every hook function - :param kwargs: kwargs to be passed to every hook function - """ - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - -class BaseManager(HookableMixin): - """Basic manager type providing common operations. - - Managers interact with a particular type of API (servers, flavors, images, - etc.) and provide CRUD operations for them. - """ - resource_class = None - - def __init__(self, client): - """Initializes BaseManager with `client`. - - :param client: instance of BaseClient descendant for HTTP requests - """ - super(BaseManager, self).__init__() - self.client = client - - def _list(self, url, response_key, obj_class=None, json=None): - """List the collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param obj_class: class for constructing the returned objects - (self.resource_class will be used by default) - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - """ - if json: - body = self.client.post(url, json=json).json() - else: - body = self.client.get(url).json() - - if obj_class is None: - obj_class = self.resource_class - - data = body[response_key] - # NOTE(ja): keystone returns values as list as {'values': [ ... ]} - # unlike other services which just return the list... - try: - data = data['values'] - except (KeyError, TypeError): - pass - - return [obj_class(self, res, loaded=True) for res in data if res] - - def _get(self, url, response_key): - """Get an object from collection. - - :param url: a partial URL, e.g., '/servers' - :param response_key: the key to be looked up in response dictionary, - e.g., 'server' - """ - body = self.client.get(url).json() - return self.resource_class(self, body[response_key], loaded=True) - - def _head(self, url): - """Retrieve request headers for an object. - - :param url: a partial URL, e.g., '/servers' - """ - resp = self.client.head(url) - return resp.status_code == 204 - - def _post(self, url, json, response_key, return_raw=False): - """Create an object. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - :param return_raw: flag to force returning raw JSON instead of - Python object of self.resource_class - """ - body = self.client.post(url, json=json).json() - if return_raw: - return body[response_key] - return self.resource_class(self, body[response_key]) - - def _put(self, url, json=None, response_key=None): - """Update an object with PUT method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - """ - resp = self.client.put(url, json=json) - # PUT requests may not return a body - if resp.content: - body = resp.json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _patch(self, url, json=None, response_key=None): - """Update an object with PATCH method. - - :param url: a partial URL, e.g., '/servers' - :param json: data that will be encoded as JSON and passed in POST - request (GET will be sent by default) - :param response_key: the key to be looked up in response dictionary, - e.g., 'servers' - """ - body = self.client.patch(url, json=json).json() - if response_key is not None: - return self.resource_class(self, body[response_key]) - else: - return self.resource_class(self, body) - - def _delete(self, url): - """Delete an object. - - :param url: a partial URL, e.g., '/servers/my-server' - """ - return self.client.delete(url) - - -@six.add_metaclass(abc.ABCMeta) -class ManagerWithFind(BaseManager): - """Manager with additional `find()`/`findall()` methods.""" - - @abc.abstractmethod - def list(self): - pass - - def find(self, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - matches = self.findall(**kwargs) - num_matches = len(matches) - if num_matches == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(msg) - elif num_matches > 1: - raise exceptions.NoUniqueMatch() - else: - return matches[0] - - def findall(self, **kwargs): - """Find all items with attributes matching ``**kwargs``. - - This isn't very efficient: it loads the entire list then filters on - the Python side. - """ - found = [] - searches = kwargs.items() - - for obj in self.list(): - try: - if all(getattr(obj, attr) == value - for (attr, value) in searches): - found.append(obj) - except AttributeError: - continue - - return found - - -class CrudManager(BaseManager): - """Base manager class for manipulating entities. - - Children of this class are expected to define a `collection_key` and `key`. - - - `collection_key`: Usually a plural noun by convention (e.g. `entities`); - used to refer collections in both URL's (e.g. `/v3/entities`) and JSON - objects containing a list of member resources (e.g. `{'entities': [{}, - {}, {}]}`). - - `key`: Usually a singular noun by convention (e.g. `entity`); used to - refer to an individual member of the collection. - - """ - collection_key = None - key = None - - def build_url(self, base_url=None, **kwargs): - """Builds a resource URL for the given kwargs. - - Given an example collection where `collection_key = 'entities'` and - `key = 'entity'`, the following URL's could be generated. - - By default, the URL will represent a collection of entities, e.g.:: - - /entities - - If kwargs contains an `entity_id`, then the URL will represent a - specific member, e.g.:: - - /entities/{entity_id} - - :param base_url: if provided, the generated URL will be appended to it - """ - url = base_url if base_url is not None else '' - - url += '/%s' % self.collection_key - - # do we have a specific entity? - entity_id = kwargs.get('%s_id' % self.key) - if entity_id is not None: - url += '/%s' % entity_id - - return url - - def _filter_kwargs(self, kwargs): - """Drop null values and handle ids.""" - for key, ref in six.iteritems(kwargs.copy()): - if ref is None: - kwargs.pop(key) - else: - if isinstance(ref, Resource): - kwargs.pop(key) - kwargs['%s_id' % key] = getid(ref) - return kwargs - - def create(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._post( - self.build_url(**kwargs), - {self.key: kwargs}, - self.key) - - def get(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._get( - self.build_url(**kwargs), - self.key) - - def head(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - return self._head(self.build_url(**kwargs)) - - def list(self, base_url=None, **kwargs): - """List the collection. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - - def put(self, base_url=None, **kwargs): - """Update an element. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - return self._put(self.build_url(base_url=base_url, **kwargs)) - - def update(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - params = kwargs.copy() - params.pop('%s_id' % self.key) - - return self._patch( - self.build_url(**kwargs), - {self.key: params}, - self.key) - - def delete(self, **kwargs): - kwargs = self._filter_kwargs(kwargs) - - return self._delete( - self.build_url(**kwargs)) - - def find(self, base_url=None, **kwargs): - """Find a single item with attributes matching ``**kwargs``. - - :param base_url: if provided, the generated URL will be appended to it - """ - kwargs = self._filter_kwargs(kwargs) - - rl = self._list( - '%(base_url)s%(query)s' % { - 'base_url': self.build_url(base_url=base_url, **kwargs), - 'query': '?%s' % parse.urlencode(kwargs) if kwargs else '', - }, - self.collection_key) - num = len(rl) - - if num == 0: - msg = _("No %(name)s matching %(args)s.") % { - 'name': self.resource_class.__name__, - 'args': kwargs - } - raise exceptions.NotFound(404, msg) - elif num > 1: - raise exceptions.NoUniqueMatch - else: - return rl[0] - - -class Extension(HookableMixin): - """Extension descriptor.""" - - SUPPORTED_HOOKS = ('__pre_parse_args__', '__post_parse_args__') - manager_class = None - - def __init__(self, name, module): - super(Extension, self).__init__() - self.name = name - self.module = module - self._parse_extension_module() - - def _parse_extension_module(self): - self.manager_class = None - for attr_name, attr_value in self.module.__dict__.items(): - if attr_name in self.SUPPORTED_HOOKS: - self.add_hook(attr_name, attr_value) - else: - try: - if issubclass(attr_value, BaseManager): - self.manager_class = attr_value - except TypeError: - pass - - def __repr__(self): - return "" % self.name - - -class Resource(object): - """Base class for OpenStack resources (tenant, user, etc.). - - This is pretty much just a bag for attributes. - """ - - HUMAN_ID = False - NAME_ATTR = 'name' - - def __init__(self, manager, info, loaded=False): - """Populate and bind to a manager. - - :param manager: BaseManager object - :param info: dictionary representing resource attributes - :param loaded: prevent lazy-loading if set to True - """ - self.manager = manager - self._info = info - self._add_details(info) - self._loaded = loaded - self._init_completion_cache() - - def _init_completion_cache(self): - cache_write = getattr(self.manager, 'write_to_completion_cache', None) - if not cache_write: - return - - # NOTE(sirp): ensure `id` is already present because if it isn't we'll - # enter an infinite loop of __getattr__ -> get -> __init__ -> - # __getattr__ -> ... - if 'id' in self.__dict__ and uuidutils.is_uuid_like(self.id): - cache_write('uuid', self.id) - - if self.human_id: - cache_write('human_id', self.human_id) - - def __repr__(self): - reprkeys = sorted(k - for k in self.__dict__.keys() - if k[0] != '_' and k != 'manager') - info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys) - return "<%s %s>" % (self.__class__.__name__, info) - - @property - def human_id(self): - """Human-readable ID which can be used for bash completion. - """ - if self.HUMAN_ID: - name = getattr(self, self.NAME_ATTR, None) - if name is not None: - return strutils.to_slug(name) - return None - - def _add_details(self, info): - for (k, v) in six.iteritems(info): - try: - setattr(self, k, v) - self._info[k] = v - except AttributeError: - # In this case we already defined the attribute on the class - pass - - def __getattr__(self, k): - if k not in self.__dict__: - # NOTE(bcwaldon): disallow lazy-loading if already loaded once - if not self.is_loaded(): - self.get() - return self.__getattr__(k) - - raise AttributeError(k) - else: - return self.__dict__[k] - - def get(self): - """Support for lazy loading details. - - Some clients, such as novaclient have the option to lazy load the - details, details which can be loaded with this function. - """ - # set_loaded() first ... so if we have to bail, we know we tried. - self.set_loaded(True) - if not hasattr(self.manager, 'get'): - return - - new = self.manager.get(self.id) - if new: - self._add_details(new._info) - - def __eq__(self, other): - if not isinstance(other, Resource): - return NotImplemented - # two resources of different types are not equal - if not isinstance(other, self.__class__): - return False - if hasattr(self, 'id') and hasattr(other, 'id'): - return self.id == other.id - return self._info == other._info - - def is_loaded(self): - return self._loaded - - def set_loaded(self, val): - self._loaded = val - - def to_dict(self): - return copy.deepcopy(self._info) diff --git a/awx/lib/site-packages/novaclient/openstack/common/apiclient/client.py b/awx/lib/site-packages/novaclient/openstack/common/apiclient/client.py deleted file mode 100644 index a3666daf0a..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/apiclient/client.py +++ /dev/null @@ -1,364 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2011 Piston Cloud Computing, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 Grid Dynamics -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -OpenStack Client interface. Handles the REST calls and responses. -""" - -# E0202: An attribute inherited from %s hide this method -# pylint: disable=E0202 - -import logging -import time - -try: - import simplejson as json -except ImportError: - import json - -import requests - -from novaclient.openstack.common.apiclient import exceptions -from novaclient.openstack.common.gettextutils import _ -from novaclient.openstack.common import importutils - - -_logger = logging.getLogger(__name__) - - -class HTTPClient(object): - """This client handles sending HTTP requests to OpenStack servers. - - Features: - - - share authentication information between several clients to different - services (e.g., for compute and image clients); - - reissue authentication request for expired tokens; - - encode/decode JSON bodies; - - raise exceptions on HTTP errors; - - pluggable authentication; - - store authentication information in a keyring; - - store time spent for requests; - - register clients for particular services, so one can use - `http_client.identity` or `http_client.compute`; - - log requests and responses in a format that is easy to copy-and-paste - into terminal and send the same request with curl. - """ - - user_agent = "novaclient.openstack.common.apiclient" - - def __init__(self, - auth_plugin, - region_name=None, - endpoint_type="publicURL", - original_ip=None, - verify=True, - cert=None, - timeout=None, - timings=False, - keyring_saver=None, - debug=False, - user_agent=None, - http=None): - self.auth_plugin = auth_plugin - - self.endpoint_type = endpoint_type - self.region_name = region_name - - self.original_ip = original_ip - self.timeout = timeout - self.verify = verify - self.cert = cert - - self.keyring_saver = keyring_saver - self.debug = debug - self.user_agent = user_agent or self.user_agent - - self.times = [] # [("item", starttime, endtime), ...] - self.timings = timings - - # requests within the same session can reuse TCP connections from pool - self.http = http or requests.Session() - - self.cached_token = None - - def _http_log_req(self, method, url, kwargs): - if not self.debug: - return - - string_parts = [ - "curl -i", - "-X '%s'" % method, - "'%s'" % url, - ] - - for element in kwargs['headers']: - header = "-H '%s: %s'" % (element, kwargs['headers'][element]) - string_parts.append(header) - - _logger.debug("REQ: %s" % " ".join(string_parts)) - if 'data' in kwargs: - _logger.debug("REQ BODY: %s\n" % (kwargs['data'])) - - def _http_log_resp(self, resp): - if not self.debug: - return - _logger.debug( - "RESP: [%s] %s\n", - resp.status_code, - resp.headers) - if resp._content_consumed: - _logger.debug( - "RESP BODY: %s\n", - resp.text) - - def serialize(self, kwargs): - if kwargs.get('json') is not None: - kwargs['headers']['Content-Type'] = 'application/json' - kwargs['data'] = json.dumps(kwargs['json']) - try: - del kwargs['json'] - except KeyError: - pass - - def get_timings(self): - return self.times - - def reset_timings(self): - self.times = [] - - def request(self, method, url, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around `requests.Session.request` to handle tasks such as - setting headers, JSON encoding/decoding, and error handling. - - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - requests.Session.request (such as `headers`) or `json` - that will be encoded as JSON and used as `data` argument - """ - kwargs.setdefault("headers", kwargs.get("headers", {})) - kwargs["headers"]["User-Agent"] = self.user_agent - if self.original_ip: - kwargs["headers"]["Forwarded"] = "for=%s;by=%s" % ( - self.original_ip, self.user_agent) - if self.timeout is not None: - kwargs.setdefault("timeout", self.timeout) - kwargs.setdefault("verify", self.verify) - if self.cert is not None: - kwargs.setdefault("cert", self.cert) - self.serialize(kwargs) - - self._http_log_req(method, url, kwargs) - if self.timings: - start_time = time.time() - resp = self.http.request(method, url, **kwargs) - if self.timings: - self.times.append(("%s %s" % (method, url), - start_time, time.time())) - self._http_log_resp(resp) - - if resp.status_code >= 400: - _logger.debug( - "Request returned failure status: %s", - resp.status_code) - raise exceptions.from_response(resp, method, url) - - return resp - - @staticmethod - def concat_url(endpoint, url): - """Concatenate endpoint and final URL. - - E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to - "http://keystone/v2.0/tokens". - - :param endpoint: the base URL - :param url: the final URL - """ - return "%s/%s" % (endpoint.rstrip("/"), url.strip("/")) - - def client_request(self, client, method, url, **kwargs): - """Send an http request using `client`'s endpoint and specified `url`. - - If request was rejected as unauthorized (possibly because the token is - expired), issue one authorization attempt and send the request once - again. - - :param client: instance of BaseClient descendant - :param method: method of HTTP request - :param url: URL of HTTP request - :param kwargs: any other parameter that can be passed to - `HTTPClient.request` - """ - - filter_args = { - "endpoint_type": client.endpoint_type or self.endpoint_type, - "service_type": client.service_type, - } - token, endpoint = (self.cached_token, client.cached_endpoint) - just_authenticated = False - if not (token and endpoint): - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - pass - if not (token and endpoint): - self.authenticate() - just_authenticated = True - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - if not (token and endpoint): - raise exceptions.AuthorizationFailure( - _("Cannot find endpoint or token for request")) - - old_token_endpoint = (token, endpoint) - kwargs.setdefault("headers", {})["X-Auth-Token"] = token - self.cached_token = token - client.cached_endpoint = endpoint - # Perform the request once. If we get Unauthorized, then it - # might be because the auth token expired, so try to - # re-authenticate and try again. If it still fails, bail. - try: - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - except exceptions.Unauthorized as unauth_ex: - if just_authenticated: - raise - self.cached_token = None - client.cached_endpoint = None - self.authenticate() - try: - token, endpoint = self.auth_plugin.token_and_endpoint( - **filter_args) - except exceptions.EndpointException: - raise unauth_ex - if (not (token and endpoint) or - old_token_endpoint == (token, endpoint)): - raise unauth_ex - self.cached_token = token - client.cached_endpoint = endpoint - kwargs["headers"]["X-Auth-Token"] = token - return self.request( - method, self.concat_url(endpoint, url), **kwargs) - - def add_client(self, base_client_instance): - """Add a new instance of :class:`BaseClient` descendant. - - `self` will store a reference to `base_client_instance`. - - Example: - - >>> def test_clients(): - ... from keystoneclient.auth import keystone - ... from openstack.common.apiclient import client - ... auth = keystone.KeystoneAuthPlugin( - ... username="user", password="pass", tenant_name="tenant", - ... auth_url="http://auth:5000/v2.0") - ... openstack_client = client.HTTPClient(auth) - ... # create nova client - ... from novaclient.v1_1 import client - ... client.Client(openstack_client) - ... # create keystone client - ... from keystoneclient.v2_0 import client - ... client.Client(openstack_client) - ... # use them - ... openstack_client.identity.tenants.list() - ... openstack_client.compute.servers.list() - """ - service_type = base_client_instance.service_type - if service_type and not hasattr(self, service_type): - setattr(self, service_type, base_client_instance) - - def authenticate(self): - self.auth_plugin.authenticate(self) - # Store the authentication results in the keyring for later requests - if self.keyring_saver: - self.keyring_saver.save(self) - - -class BaseClient(object): - """Top-level object to access the OpenStack API. - - This client uses :class:`HTTPClient` to send requests. :class:`HTTPClient` - will handle a bunch of issues such as authentication. - """ - - service_type = None - endpoint_type = None # "publicURL" will be used - cached_endpoint = None - - def __init__(self, http_client, extensions=None): - self.http_client = http_client - http_client.add_client(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - def client_request(self, method, url, **kwargs): - return self.http_client.client_request( - self, method, url, **kwargs) - - def head(self, url, **kwargs): - return self.client_request("HEAD", url, **kwargs) - - def get(self, url, **kwargs): - return self.client_request("GET", url, **kwargs) - - def post(self, url, **kwargs): - return self.client_request("POST", url, **kwargs) - - def put(self, url, **kwargs): - return self.client_request("PUT", url, **kwargs) - - def delete(self, url, **kwargs): - return self.client_request("DELETE", url, **kwargs) - - def patch(self, url, **kwargs): - return self.client_request("PATCH", url, **kwargs) - - @staticmethod - def get_class(api_name, version, version_map): - """Returns the client class for the requested API version - - :param api_name: the name of the API, e.g. 'compute', 'image', etc - :param version: the requested API version - :param version_map: a dict of client classes keyed by version - :rtype: a client class for the requested API version - """ - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - msg = _("Invalid %(api_name)s client version '%(version)s'. " - "Must be one of: %(version_map)s") % { - 'api_name': api_name, - 'version': version, - 'version_map': ', '.join(version_map.keys()) - } - raise exceptions.UnsupportedVersion(msg) - - return importutils.import_class(client_path) diff --git a/awx/lib/site-packages/novaclient/openstack/common/apiclient/exceptions.py b/awx/lib/site-packages/novaclient/openstack/common/apiclient/exceptions.py deleted file mode 100644 index 8e0d2ad9b8..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/apiclient/exceptions.py +++ /dev/null @@ -1,466 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 Nebula, Inc. -# Copyright 2013 Alessio Ababilov -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception definitions. -""" - -import inspect -import sys - -import six - -from novaclient.openstack.common.gettextutils import _ - - -class ClientException(Exception): - """The base exception class for all exceptions this library raises. - """ - pass - - -class MissingArgs(ClientException): - """Supplied arguments are not sufficient for calling a function.""" - def __init__(self, missing): - self.missing = missing - msg = _("Missing arguments: %s") % ", ".join(missing) - super(MissingArgs, self).__init__(msg) - - -class ValidationError(ClientException): - """Error in validation on API client side.""" - pass - - -class UnsupportedVersion(ClientException): - """User is trying to use an unsupported version of the API.""" - pass - - -class CommandError(ClientException): - """Error in CLI tool.""" - pass - - -class AuthorizationFailure(ClientException): - """Cannot authorize API client.""" - pass - - -class ConnectionRefused(ClientException): - """Cannot connect to API service.""" - pass - - -class AuthPluginOptionsMissing(AuthorizationFailure): - """Auth plugin misses some options.""" - def __init__(self, opt_names): - super(AuthPluginOptionsMissing, self).__init__( - _("Authentication failed. Missing options: %s") % - ", ".join(opt_names)) - self.opt_names = opt_names - - -class AuthSystemNotFound(AuthorizationFailure): - """User has specified an AuthSystem that is not installed.""" - def __init__(self, auth_system): - super(AuthSystemNotFound, self).__init__( - _("AuthSystemNotFound: %s") % repr(auth_system)) - self.auth_system = auth_system - - -class NoUniqueMatch(ClientException): - """Multiple entities found instead of one.""" - pass - - -class EndpointException(ClientException): - """Something is rotten in Service Catalog.""" - pass - - -class EndpointNotFound(EndpointException): - """Could not find requested endpoint in Service Catalog.""" - pass - - -class AmbiguousEndpoints(EndpointException): - """Found more than one matching endpoint in Service Catalog.""" - def __init__(self, endpoints=None): - super(AmbiguousEndpoints, self).__init__( - _("AmbiguousEndpoints: %s") % repr(endpoints)) - self.endpoints = endpoints - - -class HttpError(ClientException): - """The base exception class for all HTTP exceptions. - """ - http_status = 0 - message = _("HTTP Error") - - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None): - self.http_status = http_status or self.http_status - self.message = message or self.message - self.details = details - self.request_id = request_id - self.response = response - self.url = url - self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) - if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HttpError, self).__init__(formatted_string) - - -class HTTPRedirection(HttpError): - """HTTP Redirection.""" - message = _("HTTP Redirection") - - -class HTTPClientError(HttpError): - """Client-side HTTP error. - - Exception for cases in which the client seems to have erred. - """ - message = _("HTTP Client Error") - - -class HttpServerError(HttpError): - """Server-side HTTP error. - - Exception for cases in which the server is aware that it has - erred or is incapable of performing the request. - """ - message = _("HTTP Server Error") - - -class MultipleChoices(HTTPRedirection): - """HTTP 300 - Multiple Choices. - - Indicates multiple options for the resource that the client may follow. - """ - - http_status = 300 - message = _("Multiple Choices") - - -class BadRequest(HTTPClientError): - """HTTP 400 - Bad Request. - - The request cannot be fulfilled due to bad syntax. - """ - http_status = 400 - message = _("Bad Request") - - -class Unauthorized(HTTPClientError): - """HTTP 401 - Unauthorized. - - Similar to 403 Forbidden, but specifically for use when authentication - is required and has failed or has not yet been provided. - """ - http_status = 401 - message = _("Unauthorized") - - -class PaymentRequired(HTTPClientError): - """HTTP 402 - Payment Required. - - Reserved for future use. - """ - http_status = 402 - message = _("Payment Required") - - -class Forbidden(HTTPClientError): - """HTTP 403 - Forbidden. - - The request was a valid request, but the server is refusing to respond - to it. - """ - http_status = 403 - message = _("Forbidden") - - -class NotFound(HTTPClientError): - """HTTP 404 - Not Found. - - The requested resource could not be found but may be available again - in the future. - """ - http_status = 404 - message = _("Not Found") - - -class MethodNotAllowed(HTTPClientError): - """HTTP 405 - Method Not Allowed. - - A request was made of a resource using a request method not supported - by that resource. - """ - http_status = 405 - message = _("Method Not Allowed") - - -class NotAcceptable(HTTPClientError): - """HTTP 406 - Not Acceptable. - - The requested resource is only capable of generating content not - acceptable according to the Accept headers sent in the request. - """ - http_status = 406 - message = _("Not Acceptable") - - -class ProxyAuthenticationRequired(HTTPClientError): - """HTTP 407 - Proxy Authentication Required. - - The client must first authenticate itself with the proxy. - """ - http_status = 407 - message = _("Proxy Authentication Required") - - -class RequestTimeout(HTTPClientError): - """HTTP 408 - Request Timeout. - - The server timed out waiting for the request. - """ - http_status = 408 - message = _("Request Timeout") - - -class Conflict(HTTPClientError): - """HTTP 409 - Conflict. - - Indicates that the request could not be processed because of conflict - in the request, such as an edit conflict. - """ - http_status = 409 - message = _("Conflict") - - -class Gone(HTTPClientError): - """HTTP 410 - Gone. - - Indicates that the resource requested is no longer available and will - not be available again. - """ - http_status = 410 - message = _("Gone") - - -class LengthRequired(HTTPClientError): - """HTTP 411 - Length Required. - - The request did not specify the length of its content, which is - required by the requested resource. - """ - http_status = 411 - message = _("Length Required") - - -class PreconditionFailed(HTTPClientError): - """HTTP 412 - Precondition Failed. - - The server does not meet one of the preconditions that the requester - put on the request. - """ - http_status = 412 - message = _("Precondition Failed") - - -class RequestEntityTooLarge(HTTPClientError): - """HTTP 413 - Request Entity Too Large. - - The request is larger than the server is willing or able to process. - """ - http_status = 413 - message = _("Request Entity Too Large") - - def __init__(self, *args, **kwargs): - try: - self.retry_after = int(kwargs.pop('retry_after')) - except (KeyError, ValueError): - self.retry_after = 0 - - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) - - -class RequestUriTooLong(HTTPClientError): - """HTTP 414 - Request-URI Too Long. - - The URI provided was too long for the server to process. - """ - http_status = 414 - message = _("Request-URI Too Long") - - -class UnsupportedMediaType(HTTPClientError): - """HTTP 415 - Unsupported Media Type. - - The request entity has a media type which the server or resource does - not support. - """ - http_status = 415 - message = _("Unsupported Media Type") - - -class RequestedRangeNotSatisfiable(HTTPClientError): - """HTTP 416 - Requested Range Not Satisfiable. - - The client has asked for a portion of the file, but the server cannot - supply that portion. - """ - http_status = 416 - message = _("Requested Range Not Satisfiable") - - -class ExpectationFailed(HTTPClientError): - """HTTP 417 - Expectation Failed. - - The server cannot meet the requirements of the Expect request-header field. - """ - http_status = 417 - message = _("Expectation Failed") - - -class UnprocessableEntity(HTTPClientError): - """HTTP 422 - Unprocessable Entity. - - The request was well-formed but was unable to be followed due to semantic - errors. - """ - http_status = 422 - message = _("Unprocessable Entity") - - -class InternalServerError(HttpServerError): - """HTTP 500 - Internal Server Error. - - A generic error message, given when no more specific message is suitable. - """ - http_status = 500 - message = _("Internal Server Error") - - -# NotImplemented is a python keyword. -class HttpNotImplemented(HttpServerError): - """HTTP 501 - Not Implemented. - - The server either does not recognize the request method, or it lacks - the ability to fulfill the request. - """ - http_status = 501 - message = _("Not Implemented") - - -class BadGateway(HttpServerError): - """HTTP 502 - Bad Gateway. - - The server was acting as a gateway or proxy and received an invalid - response from the upstream server. - """ - http_status = 502 - message = _("Bad Gateway") - - -class ServiceUnavailable(HttpServerError): - """HTTP 503 - Service Unavailable. - - The server is currently unavailable. - """ - http_status = 503 - message = _("Service Unavailable") - - -class GatewayTimeout(HttpServerError): - """HTTP 504 - Gateway Timeout. - - The server was acting as a gateway or proxy and did not receive a timely - response from the upstream server. - """ - http_status = 504 - message = _("Gateway Timeout") - - -class HttpVersionNotSupported(HttpServerError): - """HTTP 505 - HttpVersion Not Supported. - - The server does not support the HTTP protocol version used in the request. - """ - http_status = 505 - message = _("HTTP Version Not Supported") - - -# _code_map contains all the classes that have http_status attribute. -_code_map = dict( - (getattr(obj, 'http_status', None), obj) - for name, obj in six.iteritems(vars(sys.modules[__name__])) - if inspect.isclass(obj) and getattr(obj, 'http_status', False) -) - - -def from_response(response, method, url): - """Returns an instance of :class:`HttpError` or subclass based on response. - - :param response: instance of `requests.Response` class - :param method: HTTP method used for request - :param url: URL used for request - """ - - req_id = response.headers.get("x-openstack-request-id") - # NOTE(hdd) true for older versions of nova and cinder - if not req_id: - req_id = response.headers.get("x-compute-request-id") - kwargs = { - "http_status": response.status_code, - "response": response, - "method": method, - "url": url, - "request_id": req_id, - } - if "retry-after" in response.headers: - kwargs["retry_after"] = response.headers["retry-after"] - - content_type = response.headers.get("Content-Type", "") - if content_type.startswith("application/json"): - try: - body = response.json() - except ValueError: - pass - else: - if isinstance(body, dict): - error = list(body.values())[0] - kwargs["message"] = error.get("message") - kwargs["details"] = error.get("details") - elif content_type.startswith("text/"): - kwargs["details"] = response.text - - try: - cls = _code_map[response.status_code] - except KeyError: - if 500 <= response.status_code < 600: - cls = HttpServerError - elif 400 <= response.status_code < 500: - cls = HTTPClientError - else: - cls = HttpError - return cls(**kwargs) diff --git a/awx/lib/site-packages/novaclient/openstack/common/apiclient/fake_client.py b/awx/lib/site-packages/novaclient/openstack/common/apiclient/fake_client.py deleted file mode 100644 index b6670a67b5..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/apiclient/fake_client.py +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -# W0102: Dangerous default value %s as argument -# pylint: disable=W0102 - -import json - -import requests -import six -from six.moves.urllib import parse - -from novaclient.openstack.common.apiclient import client - - -def assert_has_keys(dct, required=[], optional=[]): - for k in required: - try: - assert k in dct - except AssertionError: - extra_keys = set(dct.keys()).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class TestResponse(requests.Response): - """Wrap requests.Response and provide a convenient initialization. - """ - - def __init__(self, data): - super(TestResponse, self).__init__() - self._content_consumed = True - if isinstance(data, dict): - self.status_code = data.get('status_code', 200) - # Fake the text attribute to streamline Response creation - text = data.get('text', "") - if isinstance(text, (dict, list)): - self._content = json.dumps(text) - default_headers = { - "Content-Type": "application/json", - } - else: - self._content = text - default_headers = {} - if six.PY3 and isinstance(self._content, six.string_types): - self._content = self._content.encode('utf-8', 'strict') - self.headers = data.get('headers') or default_headers - else: - self.status_code = data - - def __eq__(self, other): - return (self.status_code == other.status_code and - self.headers == other.headers and - self._content == other._content) - - -class FakeHTTPClient(client.HTTPClient): - - def __init__(self, *args, **kwargs): - self.callstack = [] - self.fixtures = kwargs.pop("fixtures", None) or {} - if not args and "auth_plugin" not in kwargs: - args = (None, ) - super(FakeHTTPClient, self).__init__(*args, **kwargs) - - def assert_called(self, method, url, body=None, pos=-1): - """Assert than an API method was just called. - """ - expected = (method, url) - called = self.callstack[pos][0:2] - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - assert expected == called, 'Expected %s %s; got %s %s' % \ - (expected + called) - - if body is not None: - if self.callstack[pos][3] != body: - raise AssertionError('%r != %r' % - (self.callstack[pos][3], body)) - - def assert_called_anytime(self, method, url, body=None): - """Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.callstack, \ - "Expected %s %s but no calls were made." % expected - - found = False - entry = None - for entry in self.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s %s; got %s' % \ - (method, url, self.callstack) - if body is not None: - assert entry[3] == body, "%s != %s" % (entry[3], body) - - self.callstack = [] - - def clear_callstack(self): - self.callstack = [] - - def authenticate(self): - pass - - def client_request(self, client, method, url, **kwargs): - # Check that certain things are called correctly - if method in ["GET", "DELETE"]: - assert "json" not in kwargs - - # Note the call - self.callstack.append( - (method, - url, - kwargs.get("headers") or {}, - kwargs.get("json") or kwargs.get("data"))) - try: - fixture = self.fixtures[url][method] - except KeyError: - pass - else: - return TestResponse({"headers": fixture[0], - "text": fixture[1]}) - - # Call the method - args = parse.parse_qsl(parse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - resp = getattr(self, callback)(**kwargs) - if len(resp) == 3: - status, headers, body = resp - else: - status, body = resp - headers = {} - return TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) diff --git a/awx/lib/site-packages/novaclient/openstack/common/apiclient/utils.py b/awx/lib/site-packages/novaclient/openstack/common/apiclient/utils.py deleted file mode 100644 index 09ddae43be..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/apiclient/utils.py +++ /dev/null @@ -1,87 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.utils import encodeutils -import six - -from novaclient.openstack.common._i18n import _ -from novaclient.openstack.common.apiclient import exceptions -from novaclient.openstack.common import uuidutils - - -def find_resource(manager, name_or_id, **find_args): - """Look for resource in a given manager. - - Used as a helper for the _find_* methods. - Example: - - .. code-block:: python - - def _find_hypervisor(cs, hypervisor): - #Get a hypervisor by name or ID. - return cliutils.find_resource(cs.hypervisors, hypervisor) - """ - # first try to get entity as integer id - try: - return manager.get(int(name_or_id)) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # now try to get entity as uuid - try: - if six.PY2: - tmp_id = encodeutils.safe_encode(name_or_id) - else: - tmp_id = encodeutils.safe_decode(name_or_id) - - if uuidutils.is_uuid_like(tmp_id): - return manager.get(tmp_id) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # for str id which is not uuid - if getattr(manager, 'is_alphanum_id_allowed', False): - try: - return manager.get(name_or_id) - except exceptions.NotFound: - pass - - try: - try: - return manager.find(human_id=name_or_id, **find_args) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - resource = getattr(manager, 'resource_class', None) - name_attr = resource.NAME_ATTR if resource else 'name' - kwargs = {name_attr: name_or_id} - kwargs.update(find_args) - return manager.find(**kwargs) - except exceptions.NotFound: - msg = _("No %(name)s with a name or " - "ID of '%(name_or_id)s' exists.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = _("Multiple %(name)s matches found for " - "'%(name_or_id)s', use an ID to be more specific.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) diff --git a/awx/lib/site-packages/novaclient/openstack/common/cliutils.py b/awx/lib/site-packages/novaclient/openstack/common/cliutils.py deleted file mode 100644 index 6a96da57b2..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/cliutils.py +++ /dev/null @@ -1,309 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# W0603: Using the global statement -# W0621: Redefining name %s from outer scope -# pylint: disable=W0603,W0621 - -from __future__ import print_function - -import getpass -import inspect -import os -import sys -import textwrap - -import prettytable -import six -from six import moves - -from novaclient.openstack.common.apiclient import exceptions -from novaclient.openstack.common.gettextutils import _ -from novaclient.openstack.common import strutils -from novaclient.openstack.common import uuidutils - - -def validate_args(fn, *args, **kwargs): - """Check that the supplied args are sufficient for calling a function. - - >>> validate_args(lambda a: None) - Traceback (most recent call last): - ... - MissingArgs: Missing argument(s): a - >>> validate_args(lambda a, b, c, d: None, 0, c=1) - Traceback (most recent call last): - ... - MissingArgs: Missing argument(s): b, d - - :param fn: the function to check - :param arg: the positional arguments supplied - :param kwargs: the keyword arguments supplied - """ - argspec = inspect.getargspec(fn) - - num_defaults = len(argspec.defaults or []) - required_args = argspec.args[:len(argspec.args) - num_defaults] - - def isbound(method): - return getattr(method, 'im_self', None) is not None - - if isbound(fn): - required_args.pop(0) - - missing = [arg for arg in required_args if arg not in kwargs] - missing = missing[len(args):] - if missing: - raise exceptions.MissingArgs(missing) - - -def arg(*args, **kwargs): - """Decorator for CLI args. - - Example: - - >>> @arg("name", help="Name of the new entity") - ... def entity_create(args): - ... pass - """ - def _decorator(func): - add_arg(func, *args, **kwargs) - return func - return _decorator - - -def env(*args, **kwargs): - """Returns the first environment variable set. - - If all are empty, defaults to '' or keyword arg `default`. - """ - for arg in args: - value = os.environ.get(arg) - if value: - return value - return kwargs.get('default', '') - - -def add_arg(func, *args, **kwargs): - """Bind CLI arguments to a shell.py `do_foo` function.""" - - if not hasattr(func, 'arguments'): - func.arguments = [] - - # NOTE(sirp): avoid dups that can occur when the module is shared across - # tests. - if (args, kwargs) not in func.arguments: - # Because of the semantics of decorator composition if we just append - # to the options list positional options will appear to be backwards. - func.arguments.insert(0, (args, kwargs)) - - -def unauthenticated(func): - """Adds 'unauthenticated' attribute to decorated function. - - Usage: - - >>> @unauthenticated - ... def mymethod(f): - ... pass - """ - func.unauthenticated = True - return func - - -def isunauthenticated(func): - """Checks if the function does not require authentication. - - Mark such functions with the `@unauthenticated` decorator. - - :returns: bool - """ - return getattr(func, 'unauthenticated', False) - - -def print_list(objs, fields, formatters=None, sortby_index=0, - mixed_case_fields=None): - """Print a list or objects as a table, one row per object. - - :param objs: iterable of :class:`Resource` - :param fields: attributes that correspond to columns, in order - :param formatters: `dict` of callables for field formatting - :param sortby_index: index of the field for sorting table rows - :param mixed_case_fields: fields corresponding to object attributes that - have mixed case names (e.g., 'serverId') - """ - formatters = formatters or {} - mixed_case_fields = mixed_case_fields or [] - if sortby_index is None: - kwargs = {} - else: - kwargs = {'sortby': fields[sortby_index]} - pt = prettytable.PrettyTable(fields, caching=False) - pt.align = 'l' - - for o in objs: - row = [] - for field in fields: - if field in formatters: - row.append(formatters[field](o)) - else: - if field in mixed_case_fields: - field_name = field.replace(' ', '_') - else: - field_name = field.lower().replace(' ', '_') - data = getattr(o, field_name, '') - row.append(data) - pt.add_row(row) - - print(strutils.safe_encode(pt.get_string(**kwargs))) - - -def print_dict(dct, dict_property="Property", wrap=0): - """Print a `dict` as a table of two columns. - - :param dct: `dict` to print - :param dict_property: name of the first column - :param wrap: wrapping for the second column - """ - pt = prettytable.PrettyTable([dict_property, 'Value'], caching=False) - pt.align = 'l' - for k, v in six.iteritems(dct): - # convert dict to str to check length - if isinstance(v, dict): - v = six.text_type(v) - if wrap > 0: - v = textwrap.fill(six.text_type(v), wrap) - # if value has a newline, add in multiple rows - # e.g. fault with stacktrace - if v and isinstance(v, six.string_types) and r'\n' in v: - lines = v.strip().split(r'\n') - col1 = k - for line in lines: - pt.add_row([col1, line]) - col1 = '' - else: - pt.add_row([k, v]) - print(strutils.safe_encode(pt.get_string())) - - -def get_password(max_password_prompts=3): - """Read password from TTY.""" - verify = strutils.bool_from_string(env("OS_VERIFY_PASSWORD")) - pw = None - if hasattr(sys.stdin, "isatty") and sys.stdin.isatty(): - # Check for Ctrl-D - try: - for __ in moves.range(max_password_prompts): - pw1 = getpass.getpass("OS Password: ") - if verify: - pw2 = getpass.getpass("Please verify: ") - else: - pw2 = pw1 - if pw1 == pw2 and pw1: - pw = pw1 - break - except EOFError: - pass - return pw - - -def find_resource(manager, name_or_id, **find_args): - """Look for resource in a given manager. - - Used as a helper for the _find_* methods. - Example: - - def _find_hypervisor(cs, hypervisor): - #Get a hypervisor by name or ID. - return cliutils.find_resource(cs.hypervisors, hypervisor) - """ - # first try to get entity as integer id - try: - return manager.get(int(name_or_id)) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # now try to get entity as uuid - try: - tmp_id = strutils.safe_encode(name_or_id) - - if uuidutils.is_uuid_like(tmp_id): - return manager.get(tmp_id) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # for str id which is not uuid - if getattr(manager, 'is_alphanum_id_allowed', False): - try: - return manager.get(name_or_id) - except exceptions.NotFound: - pass - - try: - try: - return manager.find(human_id=name_or_id, **find_args) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - resource = getattr(manager, 'resource_class', None) - name_attr = resource.NAME_ATTR if resource else 'name' - kwargs = {name_attr: name_or_id} - kwargs.update(find_args) - return manager.find(**kwargs) - except exceptions.NotFound: - msg = _("No %(name)s with a name or " - "ID of '%(name_or_id)s' exists.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = _("Multiple %(name)s matches found for " - "'%(name_or_id)s', use an ID to be more specific.") % \ - { - "name": manager.resource_class.__name__.lower(), - "name_or_id": name_or_id - } - raise exceptions.CommandError(msg) - - -def service_type(stype): - """Adds 'service_type' attribute to decorated function. - - Usage: - @service_type('volume') - def mymethod(f): - ... - """ - def inner(f): - f.service_type = stype - return f - return inner - - -def get_service_type(f): - """Retrieves service type from function.""" - return getattr(f, 'service_type', None) - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def exit(msg=''): - if msg: - print (msg, file=sys.stderr) - sys.exit(1) diff --git a/awx/lib/site-packages/novaclient/openstack/common/gettextutils.py b/awx/lib/site-packages/novaclient/openstack/common/gettextutils.py deleted file mode 100644 index a48a728125..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/gettextutils.py +++ /dev/null @@ -1,498 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -gettext for openstack-common modules. - -Usual usage in an openstack.common module: - - from novaclient.openstack.common.gettextutils import _ -""" - -import copy -import functools -import gettext -import locale -from logging import handlers -import os - -from babel import localedata -import six - -_AVAILABLE_LANGUAGES = {} - -# FIXME(dhellmann): Remove this when moving to oslo.i18n. -USE_LAZY = False - - -class TranslatorFactory(object): - """Create translator functions - """ - - def __init__(self, domain, lazy=False, localedir=None): - """Establish a set of translation functions for the domain. - - :param domain: Name of translation domain, - specifying a message catalog. - :type domain: str - :param lazy: Delays translation until a message is emitted. - Defaults to False. - :type lazy: Boolean - :param localedir: Directory with translation catalogs. - :type localedir: str - """ - self.domain = domain - self.lazy = lazy - if localedir is None: - localedir = os.environ.get(domain.upper() + '_LOCALEDIR') - self.localedir = localedir - - def _make_translation_func(self, domain=None): - """Return a new translation function ready for use. - - Takes into account whether or not lazy translation is being - done. - - The domain can be specified to override the default from the - factory, but the localedir from the factory is always used - because we assume the log-level translation catalogs are - installed in the same directory as the main application - catalog. - - """ - if domain is None: - domain = self.domain - if self.lazy: - return functools.partial(Message, domain=domain) - t = gettext.translation( - domain, - localedir=self.localedir, - fallback=True, - ) - if six.PY3: - return t.gettext - return t.ugettext - - @property - def primary(self): - "The default translation function." - return self._make_translation_func() - - def _make_log_translation_func(self, level): - return self._make_translation_func(self.domain + '-log-' + level) - - @property - def log_info(self): - "Translate info-level log messages." - return self._make_log_translation_func('info') - - @property - def log_warning(self): - "Translate warning-level log messages." - return self._make_log_translation_func('warning') - - @property - def log_error(self): - "Translate error-level log messages." - return self._make_log_translation_func('error') - - @property - def log_critical(self): - "Translate critical-level log messages." - return self._make_log_translation_func('critical') - - -# NOTE(dhellmann): When this module moves out of the incubator into -# oslo.i18n, these global variables can be moved to an integration -# module within each application. - -# Create the global translation functions. -_translators = TranslatorFactory('novaclient') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical - -# NOTE(dhellmann): End of globals that will move to the application's -# integration module. - - -def enable_lazy(): - """Convenience function for configuring _() to use lazy gettext - - Call this at the start of execution to enable the gettextutils._ - function to use lazy gettext functionality. This is useful if - your project is importing _ directly instead of using the - gettextutils.install() way of importing the _ function. - """ - # FIXME(dhellmann): This function will be removed in oslo.i18n, - # because the TranslatorFactory makes it superfluous. - global _, _LI, _LW, _LE, _LC, USE_LAZY - tf = TranslatorFactory('novaclient', lazy=True) - _ = tf.primary - _LI = tf.log_info - _LW = tf.log_warning - _LE = tf.log_error - _LC = tf.log_critical - USE_LAZY = True - - -def install(domain, lazy=False): - """Install a _() function using the given translation domain. - - Given a translation domain, install a _() function using gettext's - install() function. - - The main difference from gettext.install() is that we allow - overriding the default localedir (e.g. /usr/share/locale) using - a translation-domain-specific environment variable (e.g. - NOVA_LOCALEDIR). - - :param domain: the translation domain - :param lazy: indicates whether or not to install the lazy _() function. - The lazy _() introduces a way to do deferred translation - of messages by installing a _ that builds Message objects, - instead of strings, which can then be lazily translated into - any available locale. - """ - if lazy: - from six import moves - tf = TranslatorFactory(domain, lazy=True) - moves.builtins.__dict__['_'] = tf.primary - else: - localedir = '%s_LOCALEDIR' % domain.upper() - if six.PY3: - gettext.install(domain, - localedir=os.environ.get(localedir)) - else: - gettext.install(domain, - localedir=os.environ.get(localedir), - unicode=True) - - -class Message(six.text_type): - """A Message object is a unicode object that can be translated. - - Translation of Message is done explicitly using the translate() method. - For all non-translation intents and purposes, a Message is simply unicode, - and can be treated as such. - """ - - def __new__(cls, msgid, msgtext=None, params=None, - domain='novaclient', *args): - """Create a new Message object. - - In order for translation to work gettext requires a message ID, this - msgid will be used as the base unicode text. It is also possible - for the msgid and the base unicode text to be different by passing - the msgtext parameter. - """ - # If the base msgtext is not given, we use the default translation - # of the msgid (which is in English) just in case the system locale is - # not English, so that the base text will be in that locale by default. - if not msgtext: - msgtext = Message._translate_msgid(msgid, domain) - # We want to initialize the parent unicode with the actual object that - # would have been plain unicode if 'Message' was not enabled. - msg = super(Message, cls).__new__(cls, msgtext) - msg.msgid = msgid - msg.domain = domain - msg.params = params - return msg - - def translate(self, desired_locale=None): - """Translate this message to the desired locale. - - :param desired_locale: The desired locale to translate the message to, - if no locale is provided the message will be - translated to the system's default locale. - - :returns: the translated message in unicode - """ - - translated_message = Message._translate_msgid(self.msgid, - self.domain, - desired_locale) - if self.params is None: - # No need for more translation - return translated_message - - # This Message object may have been formatted with one or more - # Message objects as substitution arguments, given either as a single - # argument, part of a tuple, or as one or more values in a dictionary. - # When translating this Message we need to translate those Messages too - translated_params = _translate_args(self.params, desired_locale) - - translated_message = translated_message % translated_params - - return translated_message - - @staticmethod - def _translate_msgid(msgid, domain, desired_locale=None): - if not desired_locale: - system_locale = locale.getdefaultlocale() - # If the system locale is not available to the runtime use English - if not system_locale[0]: - desired_locale = 'en_US' - else: - desired_locale = system_locale[0] - - locale_dir = os.environ.get(domain.upper() + '_LOCALEDIR') - lang = gettext.translation(domain, - localedir=locale_dir, - languages=[desired_locale], - fallback=True) - if six.PY3: - translator = lang.gettext - else: - translator = lang.ugettext - - translated_message = translator(msgid) - return translated_message - - def __mod__(self, other): - # When we mod a Message we want the actual operation to be performed - # by the parent class (i.e. unicode()), the only thing we do here is - # save the original msgid and the parameters in case of a translation - params = self._sanitize_mod_params(other) - unicode_mod = super(Message, self).__mod__(params) - modded = Message(self.msgid, - msgtext=unicode_mod, - params=params, - domain=self.domain) - return modded - - def _sanitize_mod_params(self, other): - """Sanitize the object being modded with this Message. - - - Add support for modding 'None' so translation supports it - - Trim the modded object, which can be a large dictionary, to only - those keys that would actually be used in a translation - - Snapshot the object being modded, in case the message is - translated, it will be used as it was when the Message was created - """ - if other is None: - params = (other,) - elif isinstance(other, dict): - # Merge the dictionaries - # Copy each item in case one does not support deep copy. - params = {} - if isinstance(self.params, dict): - for key, val in self.params.items(): - params[key] = self._copy_param(val) - for key, val in other.items(): - params[key] = self._copy_param(val) - else: - params = self._copy_param(other) - return params - - def _copy_param(self, param): - try: - return copy.deepcopy(param) - except Exception: - # Fallback to casting to unicode this will handle the - # python code-like objects that can't be deep-copied - return six.text_type(param) - - def __add__(self, other): - msg = _('Message objects do not support addition.') - raise TypeError(msg) - - def __radd__(self, other): - return self.__add__(other) - - if six.PY2: - def __str__(self): - # NOTE(luisg): Logging in python 2.6 tries to str() log records, - # and it expects specifically a UnicodeError in order to proceed. - msg = _('Message objects do not support str() because they may ' - 'contain non-ascii characters. ' - 'Please use unicode() or translate() instead.') - raise UnicodeError(msg) - - -def get_available_languages(domain): - """Lists the available languages for the given translation domain. - - :param domain: the domain to get languages for - """ - if domain in _AVAILABLE_LANGUAGES: - return copy.copy(_AVAILABLE_LANGUAGES[domain]) - - localedir = '%s_LOCALEDIR' % domain.upper() - find = lambda x: gettext.find(domain, - localedir=os.environ.get(localedir), - languages=[x]) - - # NOTE(mrodden): en_US should always be available (and first in case - # order matters) since our in-line message strings are en_US - language_list = ['en_US'] - # NOTE(luisg): Babel <1.0 used a function called list(), which was - # renamed to locale_identifiers() in >=1.0, the requirements master list - # requires >=0.9.6, uncapped, so defensively work with both. We can remove - # this check when the master list updates to >=1.0, and update all projects - list_identifiers = (getattr(localedata, 'list', None) or - getattr(localedata, 'locale_identifiers')) - locale_identifiers = list_identifiers() - - for i in locale_identifiers: - if find(i) is not None: - language_list.append(i) - - # NOTE(luisg): Babel>=1.0,<1.3 has a bug where some OpenStack supported - # locales (e.g. 'zh_CN', and 'zh_TW') aren't supported even though they - # are perfectly legitimate locales: - # https://github.com/mitsuhiko/babel/issues/37 - # In Babel 1.3 they fixed the bug and they support these locales, but - # they are still not explicitly "listed" by locale_identifiers(). - # That is why we add the locales here explicitly if necessary so that - # they are listed as supported. - aliases = {'zh': 'zh_CN', - 'zh_Hant_HK': 'zh_HK', - 'zh_Hant': 'zh_TW', - 'fil': 'tl_PH'} - for (locale_, alias) in six.iteritems(aliases): - if locale_ in language_list and alias not in language_list: - language_list.append(alias) - - _AVAILABLE_LANGUAGES[domain] = language_list - return copy.copy(language_list) - - -def translate(obj, desired_locale=None): - """Gets the translated unicode representation of the given object. - - If the object is not translatable it is returned as-is. - If the locale is None the object is translated to the system locale. - - :param obj: the object to translate - :param desired_locale: the locale to translate the message to, if None the - default system locale will be used - :returns: the translated object in unicode, or the original object if - it could not be translated - """ - message = obj - if not isinstance(message, Message): - # If the object to translate is not already translatable, - # let's first get its unicode representation - message = six.text_type(obj) - if isinstance(message, Message): - # Even after unicoding() we still need to check if we are - # running with translatable unicode before translating - return message.translate(desired_locale) - return obj - - -def _translate_args(args, desired_locale=None): - """Translates all the translatable elements of the given arguments object. - - This method is used for translating the translatable values in method - arguments which include values of tuples or dictionaries. - If the object is not a tuple or a dictionary the object itself is - translated if it is translatable. - - If the locale is None the object is translated to the system locale. - - :param args: the args to translate - :param desired_locale: the locale to translate the args to, if None the - default system locale will be used - :returns: a new args object with the translated contents of the original - """ - if isinstance(args, tuple): - return tuple(translate(v, desired_locale) for v in args) - if isinstance(args, dict): - translated_dict = {} - for (k, v) in six.iteritems(args): - translated_v = translate(v, desired_locale) - translated_dict[k] = translated_v - return translated_dict - return translate(args, desired_locale) - - -class TranslationHandler(handlers.MemoryHandler): - """Handler that translates records before logging them. - - The TranslationHandler takes a locale and a target logging.Handler object - to forward LogRecord objects to after translating them. This handler - depends on Message objects being logged, instead of regular strings. - - The handler can be configured declaratively in the logging.conf as follows: - - [handlers] - keys = translatedlog, translator - - [handler_translatedlog] - class = handlers.WatchedFileHandler - args = ('/var/log/api-localized.log',) - formatter = context - - [handler_translator] - class = openstack.common.log.TranslationHandler - target = translatedlog - args = ('zh_CN',) - - If the specified locale is not available in the system, the handler will - log in the default locale. - """ - - def __init__(self, locale=None, target=None): - """Initialize a TranslationHandler - - :param locale: locale to use for translating messages - :param target: logging.Handler object to forward - LogRecord objects to after translation - """ - # NOTE(luisg): In order to allow this handler to be a wrapper for - # other handlers, such as a FileHandler, and still be able to - # configure it using logging.conf, this handler has to extend - # MemoryHandler because only the MemoryHandlers' logging.conf - # parsing is implemented such that it accepts a target handler. - handlers.MemoryHandler.__init__(self, capacity=0, target=target) - self.locale = locale - - def setFormatter(self, fmt): - self.target.setFormatter(fmt) - - def emit(self, record): - # We save the message from the original record to restore it - # after translation, so other handlers are not affected by this - original_msg = record.msg - original_args = record.args - - try: - self._translate_and_log_record(record) - finally: - record.msg = original_msg - record.args = original_args - - def _translate_and_log_record(self, record): - record.msg = translate(record.msg, self.locale) - - # In addition to translating the message, we also need to translate - # arguments that were passed to the log method that were not part - # of the main message e.g., log.info(_('Some message %s'), this_one)) - record.args = _translate_args(record.args, self.locale) - - self.target.emit(record) diff --git a/awx/lib/site-packages/novaclient/openstack/common/importutils.py b/awx/lib/site-packages/novaclient/openstack/common/importutils.py deleted file mode 100644 index 863255db38..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/importutils.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class.""" - mod_str, _sep, class_str = import_str.rpartition('.') - __import__(mod_str) - try: - return getattr(sys.modules[mod_str], class_str) - except AttributeError: - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """Tries to import object from default namespace. - - Imports a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def import_versioned_module(version, submodule=None): - module = 'novaclient.v%s' % version - if submodule: - module = '.'.join((module, submodule)) - return import_module(module) - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/awx/lib/site-packages/novaclient/openstack/common/jsonutils.py b/awx/lib/site-packages/novaclient/openstack/common/jsonutils.py deleted file mode 100644 index b08a679c51..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/jsonutils.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -''' -JSON related utilities. - -This module provides a few things: - - 1) A handy function for getting an object down to something that can be - JSON serialized. See to_primitive(). - - 2) Wrappers around loads() and dumps(). The dumps() wrapper will - automatically use to_primitive() for you if needed. - - 3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson - is available. -''' - - -import codecs -import datetime -import functools -import inspect -import itertools -import sys - -if sys.version_info < (2, 7): - # On Python <= 2.6, json module is not C boosted, so try to use - # simplejson module if available - try: - import simplejson as json - except ImportError: - import json -else: - import json - -import six -import six.moves.xmlrpc_client as xmlrpclib - -from novaclient.openstack.common import gettextutils -from novaclient.openstack.common import importutils -from novaclient.openstack.common import strutils -from novaclient.openstack.common import timeutils - -netaddr = importutils.try_import("netaddr") - -_nasty_type_tests = [inspect.ismodule, inspect.isclass, inspect.ismethod, - inspect.isfunction, inspect.isgeneratorfunction, - inspect.isgenerator, inspect.istraceback, inspect.isframe, - inspect.iscode, inspect.isbuiltin, inspect.isroutine, - inspect.isabstract] - -_simple_types = (six.string_types + six.integer_types - + (type(None), bool, float)) - - -def to_primitive(value, convert_instances=False, convert_datetime=True, - level=0, max_depth=3): - """Convert a complex object into primitives. - - Handy for JSON serialization. We can optionally handle instances, - but since this is a recursive function, we could have cyclical - data structures. - - To handle cyclical data structures we could track the actual objects - visited in a set, but not all objects are hashable. Instead we just - track the depth of the object inspections and don't go too deep. - - Therefore, convert_instances=True is lossy ... be aware. - - """ - # handle obvious types first - order of basic types determined by running - # full tests on nova project, resulting in the following counts: - # 572754 - # 460353 - # 379632 - # 274610 - # 199918 - # 114200 - # 51817 - # 26164 - # 6491 - # 283 - # 19 - if isinstance(value, _simple_types): - return value - - if isinstance(value, datetime.datetime): - if convert_datetime: - return timeutils.strtime(value) - else: - return value - - # value of itertools.count doesn't get caught by nasty_type_tests - # and results in infinite loop when list(value) is called. - if type(value) == itertools.count: - return six.text_type(value) - - # FIXME(vish): Workaround for LP bug 852095. Without this workaround, - # tests that raise an exception in a mocked method that - # has a @wrap_exception with a notifier will fail. If - # we up the dependency to 0.5.4 (when it is released) we - # can remove this workaround. - if getattr(value, '__module__', None) == 'mox': - return 'mock' - - if level > max_depth: - return '?' - - # The try block may not be necessary after the class check above, - # but just in case ... - try: - recursive = functools.partial(to_primitive, - convert_instances=convert_instances, - convert_datetime=convert_datetime, - level=level, - max_depth=max_depth) - if isinstance(value, dict): - return dict((k, recursive(v)) for k, v in six.iteritems(value)) - elif isinstance(value, (list, tuple)): - return [recursive(lv) for lv in value] - - # It's not clear why xmlrpclib created their own DateTime type, but - # for our purposes, make it a datetime type which is explicitly - # handled - if isinstance(value, xmlrpclib.DateTime): - value = datetime.datetime(*tuple(value.timetuple())[:6]) - - if convert_datetime and isinstance(value, datetime.datetime): - return timeutils.strtime(value) - elif isinstance(value, gettextutils.Message): - return value.data - elif hasattr(value, 'iteritems'): - return recursive(dict(value.iteritems()), level=level + 1) - elif hasattr(value, '__iter__'): - return recursive(list(value)) - elif convert_instances and hasattr(value, '__dict__'): - # Likely an instance of something. Watch for cycles. - # Ignore class member vars. - return recursive(value.__dict__, level=level + 1) - elif netaddr and isinstance(value, netaddr.IPAddress): - return six.text_type(value) - else: - if any(test(value) for test in _nasty_type_tests): - return six.text_type(value) - return value - except TypeError: - # Class objects are tricky since they may define something like - # __iter__ defined but it isn't callable as list(). - return six.text_type(value) - - -def dumps(value, default=to_primitive, **kwargs): - return json.dumps(value, default=default, **kwargs) - - -def loads(s, encoding='utf-8'): - return json.loads(strutils.safe_decode(s, encoding)) - - -def load(fp, encoding='utf-8'): - return json.load(codecs.getreader(encoding)(fp)) - - -try: - import anyjson -except ImportError: - pass -else: - anyjson._modules.append((__name__, 'dumps', TypeError, - 'loads', ValueError, 'load')) - anyjson.force_implementation(__name__) diff --git a/awx/lib/site-packages/novaclient/openstack/common/network_utils.py b/awx/lib/site-packages/novaclient/openstack/common/network_utils.py deleted file mode 100644 index fa812b29f3..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/network_utils.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Network-related utilities and helper functions. -""" - -# TODO(jd) Use six.moves once -# https://bitbucket.org/gutworth/six/pull-request/28 -# is merged -try: - import urllib.parse - SplitResult = urllib.parse.SplitResult -except ImportError: - import urlparse - SplitResult = urlparse.SplitResult - -from six.moves.urllib import parse - - -def parse_host_port(address, default_port=None): - """Interpret a string as a host:port pair. - - An IPv6 address MUST be escaped if accompanied by a port, - because otherwise ambiguity ensues: 2001:db8:85a3::8a2e:370:7334 - means both [2001:db8:85a3::8a2e:370:7334] and - [2001:db8:85a3::8a2e:370]:7334. - - >>> parse_host_port('server01:80') - ('server01', 80) - >>> parse_host_port('server01') - ('server01', None) - >>> parse_host_port('server01', default_port=1234) - ('server01', 1234) - >>> parse_host_port('[::1]:80') - ('::1', 80) - >>> parse_host_port('[::1]') - ('::1', None) - >>> parse_host_port('[::1]', default_port=1234) - ('::1', 1234) - >>> parse_host_port('2001:db8:85a3::8a2e:370:7334', default_port=1234) - ('2001:db8:85a3::8a2e:370:7334', 1234) - - """ - if address[0] == '[': - # Escaped ipv6 - _host, _port = address[1:].split(']') - host = _host - if ':' in _port: - port = _port.split(':')[1] - else: - port = default_port - else: - if address.count(':') == 1: - host, port = address.split(':') - else: - # 0 means ipv4, >1 means ipv6. - # We prohibit unescaped ipv6 addresses with port. - host = address - port = default_port - - return (host, None if port is None else int(port)) - - -class ModifiedSplitResult(SplitResult): - """Split results class for urlsplit.""" - - # NOTE(dims): The functions below are needed for Python 2.6.x. - # We can remove these when we drop support for 2.6.x. - @property - def hostname(self): - netloc = self.netloc.split('@', 1)[-1] - host, port = parse_host_port(netloc) - return host - - @property - def port(self): - netloc = self.netloc.split('@', 1)[-1] - host, port = parse_host_port(netloc) - return port - - -def urlsplit(url, scheme='', allow_fragments=True): - """Parse a URL using urlparse.urlsplit(), splitting query and fragments. - This function papers over Python issue9374 when needed. - - The parameters are the same as urlparse.urlsplit. - """ - scheme, netloc, path, query, fragment = parse.urlsplit( - url, scheme, allow_fragments) - if allow_fragments and '#' in path: - path, fragment = path.split('#', 1) - if '?' in path: - path, query = path.split('?', 1) - return ModifiedSplitResult(scheme, netloc, - path, query, fragment) diff --git a/awx/lib/site-packages/novaclient/openstack/common/py3kcompat/__init__.py b/awx/lib/site-packages/novaclient/openstack/common/py3kcompat/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/openstack/common/py3kcompat/urlutils.py b/awx/lib/site-packages/novaclient/openstack/common/py3kcompat/urlutils.py deleted file mode 100644 index 84e457a44f..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/py3kcompat/urlutils.py +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright 2013 Canonical Ltd. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -""" -Python2/Python3 compatibility layer for OpenStack -""" - -import six - -if six.PY3: - # python3 - import urllib.error - import urllib.parse - import urllib.request - - urlencode = urllib.parse.urlencode - urljoin = urllib.parse.urljoin - quote = urllib.parse.quote - quote_plus = urllib.parse.quote_plus - parse_qsl = urllib.parse.parse_qsl - unquote = urllib.parse.unquote - unquote_plus = urllib.parse.unquote_plus - urlparse = urllib.parse.urlparse - urlsplit = urllib.parse.urlsplit - urlunsplit = urllib.parse.urlunsplit - SplitResult = urllib.parse.SplitResult - - urlopen = urllib.request.urlopen - URLError = urllib.error.URLError - pathname2url = urllib.request.pathname2url -else: - # python2 - import urllib - import urllib2 - import urlparse - - urlencode = urllib.urlencode - quote = urllib.quote - quote_plus = urllib.quote_plus - unquote = urllib.unquote - unquote_plus = urllib.unquote_plus - - parse = urlparse - parse_qsl = parse.parse_qsl - urljoin = parse.urljoin - urlparse = parse.urlparse - urlsplit = parse.urlsplit - urlunsplit = parse.urlunsplit - SplitResult = parse.SplitResult - - urlopen = urllib2.urlopen - URLError = urllib2.URLError - pathname2url = urllib.pathname2url diff --git a/awx/lib/site-packages/novaclient/openstack/common/strutils.py b/awx/lib/site-packages/novaclient/openstack/common/strutils.py deleted file mode 100644 index c22063d904..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/strutils.py +++ /dev/null @@ -1,245 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -System-level utilities and helper functions. -""" - -import math -import re -import sys -import unicodedata - -import six - -from novaclient.openstack.common.gettextutils import _ - - -UNIT_PREFIX_EXPONENT = { - 'k': 1, - 'K': 1, - 'Ki': 1, - 'M': 2, - 'Mi': 2, - 'G': 3, - 'Gi': 3, - 'T': 4, - 'Ti': 4, -} -UNIT_SYSTEM_INFO = { - 'IEC': (1024, re.compile(r'(^[-+]?\d*\.?\d+)([KMGT]i?)?(b|bit|B)$')), - 'SI': (1000, re.compile(r'(^[-+]?\d*\.?\d+)([kMGT])?(b|bit|B)$')), -} - -TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes') -FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no') - -SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]") -SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+") - - -def int_from_bool_as_string(subject): - """Interpret a string as a boolean and return either 1 or 0. - - Any string value in: - - ('True', 'true', 'On', 'on', '1') - - is interpreted as a boolean True. - - Useful for JSON-decoded stuff and config file parsing - """ - return bool_from_string(subject) and 1 or 0 - - -def bool_from_string(subject, strict=False, default=False): - """Interpret a string as a boolean. - - A case-insensitive match is performed such that strings matching 't', - 'true', 'on', 'y', 'yes', or '1' are considered True and, when - `strict=False`, anything else returns the value specified by 'default'. - - Useful for JSON-decoded stuff and config file parsing. - - If `strict=True`, unrecognized values, including None, will raise a - ValueError which is useful when parsing values passed in from an API call. - Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. - """ - if not isinstance(subject, six.string_types): - subject = str(subject) - - lowered = subject.strip().lower() - - if lowered in TRUE_STRINGS: - return True - elif lowered in FALSE_STRINGS: - return False - elif strict: - acceptable = ', '.join( - "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) - msg = _("Unrecognized value '%(val)s', acceptable values are:" - " %(acceptable)s") % {'val': subject, - 'acceptable': acceptable} - raise ValueError(msg) - else: - return default - - -def safe_decode(text, incoming=None, errors='strict'): - """Decodes incoming text/bytes string using `incoming` if they're not - already unicode. - - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a unicode `incoming` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be decoded" % type(text)) - - if isinstance(text, six.text_type): - return text - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - try: - return text.decode(incoming, errors) - except UnicodeDecodeError: - # Note(flaper87) If we get here, it means that - # sys.stdin.encoding / sys.getdefaultencoding - # didn't return a suitable encoding to decode - # text. This happens mostly when global LANG - # var is not set correctly and there's no - # default encoding. In this case, most likely - # python will use ASCII or ANSI encoders as - # default encodings but they won't be capable - # of decoding non-ASCII characters. - # - # Also, UTF-8 is being used since it's an ASCII - # extension. - return text.decode('utf-8', errors) - - -def safe_encode(text, incoming=None, - encoding='utf-8', errors='strict'): - """Encodes incoming text/bytes string using `encoding`. - - If incoming is not specified, text is expected to be encoded with - current python's default encoding. (`sys.getdefaultencoding`) - - :param incoming: Text's current encoding - :param encoding: Expected encoding for text (Default UTF-8) - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a bytestring `encoding` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be encoded" % type(text)) - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - if isinstance(text, six.text_type): - if six.PY3: - return text.encode(encoding, errors).decode(incoming) - else: - return text.encode(encoding, errors) - elif text and encoding != incoming: - # Decode text before encoding it with `encoding` - text = safe_decode(text, incoming, errors) - if six.PY3: - return text.encode(encoding, errors).decode(incoming) - else: - return text.encode(encoding, errors) - - return text - - -def string_to_bytes(text, unit_system='IEC', return_int=False): - """Converts a string into an float representation of bytes. - - The units supported for IEC :: - - Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it) - KB, KiB, MB, MiB, GB, GiB, TB, TiB - - The units supported for SI :: - - kb(it), Mb(it), Gb(it), Tb(it) - kB, MB, GB, TB - - Note that the SI unit system does not support capital letter 'K' - - :param text: String input for bytes size conversion. - :param unit_system: Unit system for byte size conversion. - :param return_int: If True, returns integer representation of text - in bytes. (default: decimal) - :returns: Numerical representation of text in bytes. - :raises ValueError: If text has an invalid value. - - """ - try: - base, reg_ex = UNIT_SYSTEM_INFO[unit_system] - except KeyError: - msg = _('Invalid unit system: "%s"') % unit_system - raise ValueError(msg) - match = reg_ex.match(text) - if match: - magnitude = float(match.group(1)) - unit_prefix = match.group(2) - if match.group(3) in ['b', 'bit']: - magnitude /= 8 - else: - msg = _('Invalid string format: %s') % text - raise ValueError(msg) - if not unit_prefix: - res = magnitude - else: - res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix]) - if return_int: - return int(math.ceil(res)) - return res - - -def to_slug(value, incoming=None, errors="strict"): - """Normalize string. - - Convert to lowercase, remove non-word characters, and convert spaces - to hyphens. - - Inspired by Django's `slugify` filter. - - :param value: Text to slugify - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: slugified unicode representation of `value` - :raises TypeError: If text is not an instance of str - """ - value = safe_decode(value, incoming, errors) - # NOTE(aababilov): no need to use safe_(encode|decode) here: - # encodings are always "ascii", error handling is always "ignore" - # and types are always known (first: unicode; second: str) - value = unicodedata.normalize("NFKD", value).encode( - "ascii", "ignore").decode("ascii") - value = SLUGIFY_STRIP_RE.sub("", value).strip().lower() - return SLUGIFY_HYPHENATE_RE.sub("-", value) diff --git a/awx/lib/site-packages/novaclient/openstack/common/timeutils.py b/awx/lib/site-packages/novaclient/openstack/common/timeutils.py deleted file mode 100644 index 52688a0268..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/timeutils.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Time related utilities and helper functions. -""" - -import calendar -import datetime -import time - -import iso8601 -import six - - -# ISO 8601 extended time format with microseconds -_ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f' -_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S' -PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND - - -def isotime(at=None, subsecond=False): - """Stringify time in ISO 8601 format.""" - if not at: - at = utcnow() - st = at.strftime(_ISO8601_TIME_FORMAT - if not subsecond - else _ISO8601_TIME_FORMAT_SUBSECOND) - tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC' - st += ('Z' if tz == 'UTC' else tz) - return st - - -def parse_isotime(timestr): - """Parse time from ISO 8601 format.""" - try: - return iso8601.parse_date(timestr) - except iso8601.ParseError as e: - raise ValueError(six.text_type(e)) - except TypeError as e: - raise ValueError(six.text_type(e)) - - -def strtime(at=None, fmt=PERFECT_TIME_FORMAT): - """Returns formatted utcnow.""" - if not at: - at = utcnow() - return at.strftime(fmt) - - -def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): - """Turn a formatted time back into a datetime.""" - return datetime.datetime.strptime(timestr, fmt) - - -def normalize_time(timestamp): - """Normalize time in arbitrary timezone to UTC naive object.""" - offset = timestamp.utcoffset() - if offset is None: - return timestamp - return timestamp.replace(tzinfo=None) - offset - - -def is_older_than(before, seconds): - """Return True if before is older than seconds.""" - if isinstance(before, six.string_types): - before = parse_strtime(before).replace(tzinfo=None) - else: - before = before.replace(tzinfo=None) - - return utcnow() - before > datetime.timedelta(seconds=seconds) - - -def is_newer_than(after, seconds): - """Return True if after is newer than seconds.""" - if isinstance(after, six.string_types): - after = parse_strtime(after).replace(tzinfo=None) - else: - after = after.replace(tzinfo=None) - - return after - utcnow() > datetime.timedelta(seconds=seconds) - - -def utcnow_ts(): - """Timestamp version of our utcnow function.""" - if utcnow.override_time is None: - # NOTE(kgriffs): This is several times faster - # than going through calendar.timegm(...) - return int(time.time()) - - return calendar.timegm(utcnow().timetuple()) - - -def utcnow(): - """Overridable version of utils.utcnow.""" - if utcnow.override_time: - try: - return utcnow.override_time.pop(0) - except AttributeError: - return utcnow.override_time - return datetime.datetime.utcnow() - - -def iso8601_from_timestamp(timestamp): - """Returns a iso8601 formatted date from timestamp.""" - return isotime(datetime.datetime.utcfromtimestamp(timestamp)) - - -utcnow.override_time = None - - -def set_time_override(override_time=None): - """Overrides utils.utcnow. - - Make it return a constant time or a list thereof, one at a time. - - :param override_time: datetime instance or list thereof. If not - given, defaults to the current UTC time. - """ - utcnow.override_time = override_time or datetime.datetime.utcnow() - - -def advance_time_delta(timedelta): - """Advance overridden time using a datetime.timedelta.""" - assert(not utcnow.override_time is None) - try: - for dt in utcnow.override_time: - dt += timedelta - except TypeError: - utcnow.override_time += timedelta - - -def advance_time_seconds(seconds): - """Advance overridden time by seconds.""" - advance_time_delta(datetime.timedelta(0, seconds)) - - -def clear_time_override(): - """Remove the overridden time.""" - utcnow.override_time = None - - -def marshall_now(now=None): - """Make an rpc-safe datetime with microseconds. - - Note: tzinfo is stripped, but not required for relative times. - """ - if not now: - now = utcnow() - return dict(day=now.day, month=now.month, year=now.year, hour=now.hour, - minute=now.minute, second=now.second, - microsecond=now.microsecond) - - -def unmarshall_time(tyme): - """Unmarshall a datetime dict.""" - return datetime.datetime(day=tyme['day'], - month=tyme['month'], - year=tyme['year'], - hour=tyme['hour'], - minute=tyme['minute'], - second=tyme['second'], - microsecond=tyme['microsecond']) - - -def delta_seconds(before, after): - """Return the difference between two timing objects. - - Compute the difference in seconds between two date, time, or - datetime objects (as a float, to microsecond resolution). - """ - delta = after - before - return total_seconds(delta) - - -def total_seconds(delta): - """Return the total seconds of datetime.timedelta object. - - Compute total seconds of datetime.timedelta, datetime.timedelta - doesn't have method total_seconds in Python2.6, calculate it manually. - """ - try: - return delta.total_seconds() - except AttributeError: - return ((delta.days * 24 * 3600) + delta.seconds + - float(delta.microseconds) / (10 ** 6)) - - -def is_soon(dt, window): - """Determines if time is going to happen in the next window seconds. - - :param dt: the time - :param window: minimum seconds to remain to consider the time not soon - - :return: True if expiration is within the given duration - """ - soon = (utcnow() + datetime.timedelta(seconds=window)) - return normalize_time(dt) <= soon diff --git a/awx/lib/site-packages/novaclient/openstack/common/uuidutils.py b/awx/lib/site-packages/novaclient/openstack/common/uuidutils.py deleted file mode 100644 index 234b880c99..0000000000 --- a/awx/lib/site-packages/novaclient/openstack/common/uuidutils.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2012 Intel Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -UUID related utilities and helper functions. -""" - -import uuid - - -def generate_uuid(): - return str(uuid.uuid4()) - - -def is_uuid_like(val): - """Returns validation of a value as a UUID. - - For our purposes, a UUID is a canonical form string: - aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa - - """ - try: - return str(uuid.UUID(val)) == val - except (TypeError, ValueError, AttributeError): - return False diff --git a/awx/lib/site-packages/novaclient/service_catalog.py b/awx/lib/site-packages/novaclient/service_catalog.py deleted file mode 100644 index 26f4ccc5cc..0000000000 --- a/awx/lib/site-packages/novaclient/service_catalog.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2011, Piston Cloud Computing, Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import novaclient.exceptions - - -class ServiceCatalog(object): - """Helper methods for dealing with a Keystone Service Catalog.""" - - def __init__(self, resource_dict): - self.catalog = resource_dict - - def get_token(self): - return self.catalog['access']['token']['id'] - - def get_tenant_id(self): - return self.catalog['access']['token']['tenant']['id'] - - def url_for(self, attr=None, filter_value=None, - service_type=None, endpoint_type='publicURL', - service_name=None, volume_service_name=None): - """Fetch the public URL from the Compute service for - a particular endpoint attribute. If none given, return - the first. See tests for sample service catalog. - """ - matching_endpoints = [] - if 'endpoints' in self.catalog: - # We have a bastardized service catalog. Treat it special. :/ - for endpoint in self.catalog['endpoints']: - if not filter_value or endpoint[attr] == filter_value: - # Ignore 1.0 compute endpoints - if endpoint.get("type") == 'compute' and \ - endpoint.get('versionId') in (None, '1.1', '2'): - matching_endpoints.append(endpoint) - if not matching_endpoints: - raise novaclient.exceptions.EndpointNotFound() - - # We don't always get a service catalog back ... - if 'serviceCatalog' not in self.catalog['access']: - return None - - # Full catalog ... - catalog = self.catalog['access']['serviceCatalog'] - - for service in catalog: - if service.get("type") != service_type: - continue - - if (service_name and service_type == 'compute' and - service.get('name') != service_name): - continue - - if (volume_service_name and service_type == 'volume' and - service.get('name') != volume_service_name): - continue - - endpoints = service['endpoints'] - for endpoint in endpoints: - # Ignore 1.0 compute endpoints - if service.get("type") == 'compute' and \ - endpoint.get('versionId', '2') not in ('1.1', '2'): - continue - if not filter_value or \ - endpoint.get(attr).lower() == filter_value.lower(): - endpoint["serviceName"] = service.get("name") - matching_endpoints.append(endpoint) - - if not matching_endpoints: - raise novaclient.exceptions.EndpointNotFound() - elif len(matching_endpoints) > 1: - raise novaclient.exceptions.AmbiguousEndpoints( - endpoints=matching_endpoints) - else: - return matching_endpoints[0][endpoint_type] diff --git a/awx/lib/site-packages/novaclient/shell.py b/awx/lib/site-packages/novaclient/shell.py deleted file mode 100644 index 6623b7fbf4..0000000000 --- a/awx/lib/site-packages/novaclient/shell.py +++ /dev/null @@ -1,815 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Command-line interface to the OpenStack Nova API. -""" - -from __future__ import print_function -import argparse -import getpass -import glob -import imp -import itertools -import logging -import os -import pkgutil -import sys - -from oslo.utils import encodeutils -from oslo.utils import strutils -import pkg_resources -import six - -HAS_KEYRING = False -all_errors = ValueError -try: - import keyring - HAS_KEYRING = True -except ImportError: - pass - -import novaclient -import novaclient.auth_plugin -from novaclient import client -from novaclient import exceptions as exc -import novaclient.extension -from novaclient.openstack.common import cliutils -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils -from novaclient.v1_1 import shell as shell_v1_1 -from novaclient.v3 import shell as shell_v3 - -DEFAULT_OS_COMPUTE_API_VERSION = "1.1" -DEFAULT_NOVA_ENDPOINT_TYPE = 'publicURL' -# NOTE(cyeoh): Having the service type dependent on the API version -# is pretty ugly, but we have to do this because traditionally the -# catalog entry for compute points directly to the V2 API rather than -# the root, and then doing version discovery. -DEFAULT_NOVA_SERVICE_TYPE_MAP = {'1.1': 'compute', - '2': 'compute', - '3': 'computev3'} - -logger = logging.getLogger(__name__) - - -def positive_non_zero_float(text): - if text is None: - return None - try: - value = float(text) - except ValueError: - msg = _("%s must be a float") % text - raise argparse.ArgumentTypeError(msg) - if value <= 0: - msg = _("%s must be greater than 0") % text - raise argparse.ArgumentTypeError(msg) - return value - - -class SecretsHelper(object): - def __init__(self, args, client): - self.args = args - self.client = client - self.key = None - self._password = None - - def _validate_string(self, text): - if text is None or len(text) == 0: - return False - return True - - def _make_key(self): - if self.key is not None: - return self.key - keys = [ - self.client.auth_url, - self.client.projectid, - self.client.user, - self.client.region_name, - self.client.endpoint_type, - self.client.service_type, - self.client.service_name, - self.client.volume_service_name, - ] - for (index, key) in enumerate(keys): - if key is None: - keys[index] = '?' - else: - keys[index] = str(keys[index]) - self.key = "/".join(keys) - return self.key - - def _prompt_password(self, verify=True): - pw = None - if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): - # Check for Ctl-D - try: - while True: - pw1 = getpass.getpass('OS Password: ') - if verify: - pw2 = getpass.getpass('Please verify: ') - else: - pw2 = pw1 - if pw1 == pw2 and self._validate_string(pw1): - pw = pw1 - break - except EOFError: - pass - return pw - - def save(self, auth_token, management_url, tenant_id): - if not HAS_KEYRING or not self.args.os_cache: - return - if (auth_token == self.auth_token and - management_url == self.management_url): - # Nothing changed.... - return - if not all([management_url, auth_token, tenant_id]): - raise ValueError(_("Unable to save empty management url/auth " - "token")) - value = "|".join([str(auth_token), - str(management_url), - str(tenant_id)]) - keyring.set_password("novaclient_auth", self._make_key(), value) - - @property - def password(self): - # Cache password so we prompt user at most once - if self._password: - pass - elif self._validate_string(self.args.os_password): - self._password = self.args.os_password - else: - verify_pass = strutils.bool_from_string( - utils.env("OS_VERIFY_PASSWORD", default=False), True) - self._password = self._prompt_password(verify_pass) - if not self._password: - raise exc.CommandError( - 'Expecting a password provided via either ' - '--os-password, env[OS_PASSWORD], or ' - 'prompted response') - return self._password - - @property - def management_url(self): - if not HAS_KEYRING or not self.args.os_cache: - return None - management_url = None - try: - block = keyring.get_password('novaclient_auth', self._make_key()) - if block: - _token, management_url, _tenant_id = block.split('|', 2) - except all_errors: - pass - return management_url - - @property - def auth_token(self): - # Now is where it gets complicated since we - # want to look into the keyring module, if it - # exists and see if anything was provided in that - # file that we can use. - if not HAS_KEYRING or not self.args.os_cache: - return None - token = None - try: - block = keyring.get_password('novaclient_auth', self._make_key()) - if block: - token, _management_url, _tenant_id = block.split('|', 2) - except all_errors: - pass - return token - - @property - def tenant_id(self): - if not HAS_KEYRING or not self.args.os_cache: - return None - tenant_id = None - try: - block = keyring.get_password('novaclient_auth', self._make_key()) - if block: - _token, _management_url, tenant_id = block.split('|', 2) - except all_errors: - pass - return tenant_id - - -class NovaClientArgumentParser(argparse.ArgumentParser): - - def __init__(self, *args, **kwargs): - super(NovaClientArgumentParser, self).__init__(*args, **kwargs) - - def error(self, message): - """error(message: string) - - Prints a usage message incorporating the message to stderr and - exits. - """ - self.print_usage(sys.stderr) - # FIXME(lzyeval): if changes occur in argparse.ArgParser._check_value - choose_from = ' (choose from' - progparts = self.prog.partition(' ') - self.exit(2, _("error: %(errmsg)s\nTry '%(mainp)s help %(subp)s'" - " for more information.\n") % - {'errmsg': message.split(choose_from)[0], - 'mainp': progparts[0], - 'subp': progparts[2]}) - - -class OpenStackComputeShell(object): - - def get_base_parser(self): - parser = NovaClientArgumentParser( - prog='nova', - description=__doc__.strip(), - epilog='See "nova help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=OpenStackHelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS, - ) - - parser.add_argument('--version', - action='version', - version=novaclient.__version__) - - parser.add_argument('--debug', - default=False, - action='store_true', - help=_("Print debugging output")) - - parser.add_argument('--os-cache', - default=strutils.bool_from_string( - utils.env('OS_CACHE', default=False), True), - action='store_true', - help=_("Use the auth token cache. Defaults to False if " - "env[OS_CACHE] is not set.")) - - parser.add_argument('--timings', - default=False, - action='store_true', - help=_("Print call timing info")) - - parser.add_argument('--timeout', - default=600, - metavar='', - type=positive_non_zero_float, - help=_("Set HTTP call timeout (in seconds)")) - - parser.add_argument('--os-auth-token', - default=utils.env('OS_AUTH_TOKEN'), - help='Defaults to env[OS_AUTH_TOKEN]') - - parser.add_argument('--os-username', - metavar='', - default=utils.env('OS_USERNAME', 'NOVA_USERNAME'), - help=_('Defaults to env[OS_USERNAME].')) - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-user-id', - metavar='', - default=utils.env('OS_USER_ID'), - help=_('Defaults to env[OS_USER_ID].')) - - parser.add_argument('--os-password', - metavar='', - default=utils.env('OS_PASSWORD', 'NOVA_PASSWORD'), - help=_('Defaults to env[OS_PASSWORD].')) - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - metavar='', - default=utils.env('OS_TENANT_NAME', 'NOVA_PROJECT_ID'), - help=_('Defaults to env[OS_TENANT_NAME].')) - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - metavar='', - default=utils.env('OS_TENANT_ID'), - help=_('Defaults to env[OS_TENANT_ID].')) - - parser.add_argument('--os-auth-url', - metavar='', - default=utils.env('OS_AUTH_URL', 'NOVA_URL'), - help=_('Defaults to env[OS_AUTH_URL].')) - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-region-name', - metavar='', - default=utils.env('OS_REGION_NAME', 'NOVA_REGION_NAME'), - help=_('Defaults to env[OS_REGION_NAME].')) - parser.add_argument('--os_region_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-system', - metavar='', - default=utils.env('OS_AUTH_SYSTEM'), - help='Defaults to env[OS_AUTH_SYSTEM].') - parser.add_argument('--os_auth_system', - help=argparse.SUPPRESS) - - parser.add_argument('--service-type', - metavar='', - help=_('Defaults to compute for most actions')) - parser.add_argument('--service_type', - help=argparse.SUPPRESS) - - parser.add_argument('--service-name', - metavar='', - default=utils.env('NOVA_SERVICE_NAME'), - help=_('Defaults to env[NOVA_SERVICE_NAME]')) - parser.add_argument('--service_name', - help=argparse.SUPPRESS) - - parser.add_argument('--volume-service-name', - metavar='', - default=utils.env('NOVA_VOLUME_SERVICE_NAME'), - help=_('Defaults to env[NOVA_VOLUME_SERVICE_NAME]')) - parser.add_argument('--volume_service_name', - help=argparse.SUPPRESS) - - parser.add_argument('--endpoint-type', - metavar='', - default=utils.env('NOVA_ENDPOINT_TYPE', - default=DEFAULT_NOVA_ENDPOINT_TYPE), - help=_('Defaults to env[NOVA_ENDPOINT_TYPE] or ') - + DEFAULT_NOVA_ENDPOINT_TYPE + '.') - # NOTE(dtroyer): We can't add --endpoint_type here due to argparse - # thinking usage-list --end is ambiguous; but it - # works fine with only --endpoint-type present - # Go figure. I'm leaving this here for doc purposes. - # parser.add_argument('--endpoint_type', - # help=argparse.SUPPRESS) - - parser.add_argument('--os-compute-api-version', - metavar='', - default=utils.env('OS_COMPUTE_API_VERSION', - default=DEFAULT_OS_COMPUTE_API_VERSION), - help=_('Accepts 1.1 or 3, ' - 'defaults to env[OS_COMPUTE_API_VERSION].')) - parser.add_argument('--os_compute_api_version', - help=argparse.SUPPRESS) - - parser.add_argument('--os-cacert', - metavar='', - default=utils.env('OS_CACERT', default=None), - help='Specify a CA bundle file to use in ' - 'verifying a TLS (https) server certificate. ' - 'Defaults to env[OS_CACERT]') - - parser.add_argument('--insecure', - default=utils.env('NOVACLIENT_INSECURE', default=False), - action='store_true', - help=_("Explicitly allow novaclient to perform \"insecure\" " - "SSL (https) requests. The server's certificate will " - "not be verified against any certificate authorities. " - "This option should be used with caution.")) - - parser.add_argument('--bypass-url', - metavar='', - dest='bypass_url', - default=utils.env('NOVACLIENT_BYPASS_URL'), - help="Use this API endpoint instead of the Service Catalog. " - "Defaults to env[NOVACLIENT_BYPASS_URL]") - parser.add_argument('--bypass_url', - help=argparse.SUPPRESS) - - # The auth-system-plugins might require some extra options - novaclient.auth_plugin.load_auth_system_opts(parser) - - return parser - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='') - - try: - actions_module = { - '1.1': shell_v1_1, - '2': shell_v1_1, - '3': shell_v3, - }[version] - except KeyError: - actions_module = shell_v1_1 - - self._find_actions(subparsers, actions_module) - self._find_actions(subparsers, self) - - for extension in self.extensions: - self._find_actions(subparsers, extension.module) - - self._add_bash_completion_subparser(subparsers) - - return parser - - def _discover_extensions(self, version): - extensions = [] - for name, module in itertools.chain( - self._discover_via_python_path(), - self._discover_via_contrib_path(version), - self._discover_via_entry_points()): - - extension = novaclient.extension.Extension(name, module) - extensions.append(extension) - - return extensions - - def _discover_via_python_path(self): - for (module_loader, name, _ispkg) in pkgutil.iter_modules(): - if name.endswith('_python_novaclient_ext'): - if not hasattr(module_loader, 'load_module'): - # Python 2.6 compat: actually get an ImpImporter obj - module_loader = module_loader.find_module(name) - - module = module_loader.load_module(name) - if hasattr(module, 'extension_name'): - name = module.extension_name - - yield name, module - - def _discover_via_contrib_path(self, version): - module_path = os.path.dirname(os.path.abspath(__file__)) - version_str = "v%s" % version.replace('.', '_') - ext_path = os.path.join(module_path, version_str, 'contrib') - ext_glob = os.path.join(ext_path, "*.py") - - for ext_path in glob.iglob(ext_glob): - name = os.path.basename(ext_path)[:-3] - - if name == "__init__": - continue - - module = imp.load_source(name, ext_path) - yield name, module - - def _discover_via_entry_points(self): - for ep in pkg_resources.iter_entry_points('novaclient.extension'): - name = ep.name - module = ep.load() - - yield name, module - - def _add_bash_completion_subparser(self, subparsers): - subparser = subparsers.add_parser('bash_completion', - add_help=False, - formatter_class=OpenStackHelpFormatter - ) - self.subcommands['bash_completion'] = subparser - subparser.set_defaults(func=self.do_bash_completion) - - def _find_actions(self, subparsers, actions_module): - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hyphen-separated instead of underscores. - command = attr[3:].replace('_', '-') - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - action_help = desc.strip() - arguments = getattr(callback, 'arguments', []) - - subparser = subparsers.add_parser(command, - help=action_help, - description=desc, - add_help=False, - formatter_class=OpenStackHelpFormatter - ) - subparser.add_argument('-h', '--help', - action='help', - help=argparse.SUPPRESS, - ) - self.subcommands[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - def setup_debugging(self, debug): - if not debug: - return - - streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" - # Set up the root logger to debug so that the submodules can - # print debug messages - logging.basicConfig(level=logging.DEBUG, - format=streamformat) - - def main(self, argv): - # Parse args once to find version and debug settings - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - self.setup_debugging(options.debug) - - # Discover available auth plugins - novaclient.auth_plugin.discover_auth_systems() - - # build available subcommands based on version - self.extensions = self._discover_extensions( - options.os_compute_api_version) - self._run_extension_hooks('__pre_parse_args__') - - # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse - # thinking usage-list --end is ambiguous; but it - # works fine with only --endpoint-type present - # Go figure. - if '--endpoint_type' in argv: - spot = argv.index('--endpoint_type') - argv[spot] = '--endpoint-type' - - subcommand_parser = self.get_subcommand_parser( - options.os_compute_api_version) - self.parser = subcommand_parser - - if options.help or not argv: - subcommand_parser.print_help() - return 0 - - args = subcommand_parser.parse_args(argv) - self._run_extension_hooks('__post_parse_args__', args) - - # Short-circuit and deal with help right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion(args) - return 0 - - os_username = args.os_username - os_user_id = args.os_user_id - os_password = None # Fetched and set later as needed - os_tenant_name = args.os_tenant_name - os_tenant_id = args.os_tenant_id - os_auth_url = args.os_auth_url - os_region_name = args.os_region_name - os_auth_system = args.os_auth_system - endpoint_type = args.endpoint_type - insecure = args.insecure - service_type = args.service_type - service_name = args.service_name - volume_service_name = args.volume_service_name - bypass_url = args.bypass_url - os_cache = args.os_cache - cacert = args.os_cacert - timeout = args.timeout - - # We may have either, both or none of these. - # If we have both, we don't need USERNAME, PASSWORD etc. - # Fill in the blanks from the SecretsHelper if possible. - # Finally, authenticate unless we have both. - # Note if we don't auth we probably don't have a tenant ID so we can't - # cache the token. - auth_token = args.os_auth_token if args.os_auth_token else None - management_url = bypass_url if bypass_url else None - - if os_auth_system and os_auth_system != "keystone": - auth_plugin = novaclient.auth_plugin.load_plugin(os_auth_system) - else: - auth_plugin = None - - if not endpoint_type: - endpoint_type = DEFAULT_NOVA_ENDPOINT_TYPE - - if not service_type: - os_compute_api_version = (options.os_compute_api_version or - DEFAULT_OS_COMPUTE_API_VERSION) - try: - service_type = DEFAULT_NOVA_SERVICE_TYPE_MAP[ - os_compute_api_version] - except KeyError: - service_type = DEFAULT_NOVA_SERVICE_TYPE_MAP[ - DEFAULT_OS_COMPUTE_API_VERSION] - service_type = utils.get_service_type(args.func) or service_type - - # If we have an auth token but no management_url, we must auth anyway. - # Expired tokens are handled by client.py:_cs_request - must_auth = not (cliutils.isunauthenticated(args.func) - or (auth_token and management_url)) - - # FIXME(usrleon): Here should be restrict for project id same as - # for os_username or os_password but for compatibility it is not. - if must_auth: - if auth_plugin: - auth_plugin.parse_opts(args) - - if not auth_plugin or not auth_plugin.opts: - if not os_username and not os_user_id: - raise exc.CommandError(_("You must provide a username " - "or user id via --os-username, --os-user-id, " - "env[OS_USERNAME] or env[OS_USER_ID]")) - - if not os_tenant_name and not os_tenant_id: - raise exc.CommandError(_("You must provide a tenant name " - "or tenant id via --os-tenant-name, " - "--os-tenant-id, env[OS_TENANT_NAME] " - "or env[OS_TENANT_ID]")) - - if not os_auth_url: - if os_auth_system and os_auth_system != 'keystone': - os_auth_url = auth_plugin.get_auth_url() - - if not os_auth_url: - raise exc.CommandError(_("You must provide an auth url " - "via either --os-auth-url or env[OS_AUTH_URL] " - "or specify an auth_system which defines a " - "default url with --os-auth-system " - "or env[OS_AUTH_SYSTEM]")) - - if (options.os_compute_api_version and - options.os_compute_api_version != '1.0'): - if not os_tenant_name and not os_tenant_id: - raise exc.CommandError(_("You must provide a tenant name " - "or tenant id via --os-tenant-name, " - "--os-tenant-id, env[OS_TENANT_NAME] " - "or env[OS_TENANT_ID]")) - - if not os_auth_url: - raise exc.CommandError(_("You must provide an auth url " - "via either --os-auth-url or env[OS_AUTH_URL]")) - - completion_cache = client.CompletionCache(os_username, os_auth_url) - - self.cs = client.Client(options.os_compute_api_version, - os_username, os_password, os_tenant_name, - tenant_id=os_tenant_id, user_id=os_user_id, - auth_url=os_auth_url, insecure=insecure, - region_name=os_region_name, endpoint_type=endpoint_type, - extensions=self.extensions, service_type=service_type, - service_name=service_name, auth_system=os_auth_system, - auth_plugin=auth_plugin, auth_token=auth_token, - volume_service_name=volume_service_name, - timings=args.timings, bypass_url=bypass_url, - os_cache=os_cache, http_log_debug=options.debug, - cacert=cacert, timeout=timeout, - completion_cache=completion_cache) - - # Now check for the password/token of which pieces of the - # identifying keyring key can come from the underlying client - if must_auth: - helper = SecretsHelper(args, self.cs.client) - if (auth_plugin and auth_plugin.opts and - "os_password" not in auth_plugin.opts): - use_pw = False - else: - use_pw = True - - tenant_id = helper.tenant_id - # Allow commandline to override cache - if not auth_token: - auth_token = helper.auth_token - if not management_url: - management_url = helper.management_url - if tenant_id and auth_token and management_url: - self.cs.client.tenant_id = tenant_id - self.cs.client.auth_token = auth_token - self.cs.client.management_url = management_url - self.cs.client.password_func = lambda: helper.password - elif use_pw: - # We're missing something, so auth with user/pass and save - # the result in our helper. - self.cs.client.password = helper.password - self.cs.client.keyring_saver = helper - - try: - # This does a couple of bits which are useful even if we've - # got the token + service URL already. It exits fast in that case. - if not cliutils.isunauthenticated(args.func): - self.cs.authenticate() - except exc.Unauthorized: - raise exc.CommandError(_("Invalid OpenStack Nova credentials.")) - except exc.AuthorizationFailure: - raise exc.CommandError(_("Unable to authorize user")) - - if options.os_compute_api_version == "3" and service_type != 'image': - # NOTE(cyeoh): create an image based client because the - # images api is no longer proxied by the V3 API and we - # sometimes need to be able to look up images information - # via glance when connected to the nova api. - image_service_type = 'image' - # NOTE(hdd): the password is needed again because creating a new - # Client without specifying bypass_url will force authentication. - # We can't reuse self.cs's bypass_url, because that's the URL for - # the nova service; we need to get glance's URL for this Client - if not os_password: - os_password = helper.password - self.cs.image_cs = client.Client( - options.os_compute_api_version, os_username, - os_password, os_tenant_name, tenant_id=os_tenant_id, - auth_url=os_auth_url, insecure=insecure, - region_name=os_region_name, endpoint_type=endpoint_type, - extensions=self.extensions, service_type=image_service_type, - service_name=service_name, auth_system=os_auth_system, - auth_plugin=auth_plugin, - volume_service_name=volume_service_name, - timings=args.timings, bypass_url=bypass_url, - os_cache=os_cache, http_log_debug=options.debug, - cacert=cacert, timeout=timeout) - - args.func(self.cs, args) - - if args.timings: - self._dump_timings(self.cs.get_timings()) - - def _dump_timings(self, timings): - class Tyme(object): - def __init__(self, url, seconds): - self.url = url - self.seconds = seconds - results = [Tyme(url, end - start) for url, start, end in timings] - total = 0.0 - for tyme in results: - total += tyme.seconds - results.append(Tyme("Total", total)) - utils.print_list(results, ["url", "seconds"], sortby_index=None) - - def _run_extension_hooks(self, hook_type, *args, **kwargs): - """Run hooks for all registered extensions.""" - for extension in self.extensions: - extension.run_hooks(hook_type, *args, **kwargs) - - def do_bash_completion(self, _args): - """ - Prints all of the commands and options to stdout so that the - nova.bash_completion script doesn't have to hard code them. - """ - commands = set() - options = set() - for sc_str, sc in self.subcommands.items(): - commands.add(sc_str) - for option in sc._optionals._option_string_actions.keys(): - options.add(option) - - commands.remove('bash-completion') - commands.remove('bash_completion') - print(' '.join(commands | options)) - - @utils.arg('command', metavar='', nargs='?', - help='Display help for ') - def do_help(self, args): - """ - Display help about this program or one of its subcommands. - """ - if args.command: - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError(_("'%s' is not a valid subcommand") % - args.command) - else: - self.parser.print_help() - - -# I'm picky about my shell help. -class OpenStackHelpFormatter(argparse.HelpFormatter): - def __init__(self, prog, indent_increment=2, max_help_position=32, - width=None): - super(OpenStackHelpFormatter, self).__init__(prog, indent_increment, - max_help_position, width) - - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(OpenStackHelpFormatter, self).start_section(heading) - - -def main(): - try: - argv = [encodeutils.safe_decode(a) for a in sys.argv[1:]] - OpenStackComputeShell().main(argv) - - except Exception as e: - logger.debug(e, exc_info=1) - details = {'name': encodeutils.safe_encode(e.__class__.__name__), - 'msg': encodeutils.safe_encode(six.text_type(e))} - print("ERROR (%(name)s): %(msg)s" % details, - file=sys.stderr) - sys.exit(1) - except KeyboardInterrupt as e: - print("Shutting down novaclient", file=sys.stderr) - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/awx/lib/site-packages/novaclient/tests/__init__.py b/awx/lib/site-packages/novaclient/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/tests/fakes.py b/awx/lib/site-packages/novaclient/tests/fakes.py deleted file mode 100644 index c73f72f919..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fakes.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -from novaclient import base - - -def assert_has_keys(dict, required=[], optional=[]): - keys = dict.keys() - for k in required: - try: - assert k in keys - except AssertionError: - extra_keys = set(keys).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class FakeClient(object): - - def assert_called(self, method, url, body=None, pos=-1): - """ - Assert than an API method was just called. - """ - expected = (method, url) - called = self.client.callstack[pos][0:2] - - assert self.client.callstack, \ - "Expected %s %s but no calls were made." % expected - - assert expected == called, 'Expected %s %s; got %s %s' % \ - (expected + called) - - if body is not None: - if self.client.callstack[pos][2] != body: - raise AssertionError('%r != %r' % - (self.client.callstack[pos][2], body)) - - def assert_called_anytime(self, method, url, body=None): - """ - Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.client.callstack, \ - "Expected %s %s but no calls were made." % expected - - found = False - for entry in self.client.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s; got %s' % \ - (expected, self.client.callstack) - if body is not None: - try: - assert entry[2] == body - except AssertionError: - print(entry[2]) - print("!=") - print(body) - raise - - self.client.callstack = [] - - def clear_callstack(self): - self.client.callstack = [] - - def authenticate(self): - pass - - -# Fake class that will be used as an extension -class FakeManager(base.Manager): - pass diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/__init__.py b/awx/lib/site-packages/novaclient/tests/fixture_data/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/agents.py b/awx/lib/site-packages/novaclient/tests/fixture_data/agents.py deleted file mode 100644 index f1c2aed016..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/agents.py +++ /dev/null @@ -1,54 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-agents' - - def setUp(self): - super(Fixture, self).setUp() - - post_os_agents = { - 'agent': { - 'url': '/xxx/xxx/xxx', - 'hypervisor': 'kvm', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'version': '7.0', - 'architecture': 'x86', - 'os': 'win', - 'id': 1 - } - } - - self.requests.register_uri('POST', self.url(), - json=post_os_agents, - headers=self.json_headers) - - put_os_agents_1 = { - "agent": { - "url": "/yyy/yyyy/yyyy", - "version": "8.0", - "md5hash": "add6bb58e139be103324d04d82d8f546", - 'id': 1 - } - } - - self.requests.register_uri('PUT', self.url(1), - json=put_os_agents_1, - headers=self.json_headers) - - self.requests.register_uri('DELETE', self.url(1), - headers=self.json_headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/aggregates.py b/awx/lib/site-packages/novaclient/tests/fixture_data/aggregates.py deleted file mode 100644 index 26f00d7acf..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/aggregates.py +++ /dev/null @@ -1,52 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-aggregates' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_aggregates = {"aggregates": [ - {'id': '1', - 'name': 'test', - 'availability_zone': 'nova1'}, - {'id': '2', - 'name': 'test2', - 'availability_zone': 'nova1'}, - ]} - - self.requests.register_uri('GET', self.url(), - json=get_os_aggregates, - headers=self.json_headers) - - get_aggregates_1 = {'aggregate': get_os_aggregates['aggregates'][0]} - - self.requests.register_uri('POST', self.url(), - json=get_aggregates_1, - headers=self.json_headers) - - for agg_id in (1, 2): - for method in ('GET', 'PUT'): - self.requests.register_uri(method, self.url(agg_id), - json=get_aggregates_1, - headers=self.json_headers) - - self.requests.register_uri('POST', self.url(agg_id, 'action'), - json=get_aggregates_1, - headers=self.json_headers) - - self.requests.register_uri('DELETE', self.url(1), status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/availability_zones.py b/awx/lib/site-packages/novaclient/tests/fixture_data/availability_zones.py deleted file mode 100644 index 451a64b2ac..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/availability_zones.py +++ /dev/null @@ -1,97 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-availability-zone' - - zone_info_key = 'availabilityZoneInfo' - zone_name_key = 'zoneName' - zone_state_key = 'zoneState' - - def setUp(self): - super(V1, self).setUp() - - get_os_availability_zone = { - self.zone_info_key: [ - { - self.zone_name_key: "zone-1", - self.zone_state_key: {"available": True}, - "hosts": None - }, - { - self.zone_name_key: "zone-2", - self.zone_state_key: {"available": False}, - "hosts": None - } - ] - } - - self.requests.register_uri('GET', self.url(), - json=get_os_availability_zone, - headers=self.json_headers) - - get_os_zone_detail = { - self.zone_info_key: [ - { - self.zone_name_key: "zone-1", - self.zone_state_key: {"available": True}, - "hosts": { - "fake_host-1": { - "nova-compute": { - "active": True, - "available": True, - "updated_at": '2012-12-26 14:45:25' - } - } - } - }, - { - self.zone_name_key: "internal", - self.zone_state_key: {"available": True}, - "hosts": { - "fake_host-1": { - "nova-sched": { - "active": True, - "available": True, - "updated_at": '2012-12-26 14:45:25' - } - }, - "fake_host-2": { - "nova-network": { - "active": True, - "available": False, - "updated_at": '2012-12-26 14:45:24' - } - } - } - }, - { - self.zone_name_key: "zone-2", - self.zone_state_key: {"available": False}, - "hosts": None - } - ] - } - - self.requests.register_uri('GET', self.url('detail'), - json=get_os_zone_detail, - headers=self.json_headers) - - -class V3(V1): - zone_info_key = 'availability_zone_info' - zone_name_key = 'zone_name' - zone_state_key = 'zone_state' diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/base.py b/awx/lib/site-packages/novaclient/tests/fixture_data/base.py deleted file mode 100644 index 6a2e238b58..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/base.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -from six.moves.urllib import parse - -COMPUTE_URL = 'http://compute.host' - - -class Fixture(fixtures.Fixture): - - base_url = None - json_headers = {'Content-Type': 'application/json'} - - def __init__(self, requests, compute_url=COMPUTE_URL): - super(Fixture, self).__init__() - self.requests = requests - self.compute_url = compute_url - - def url(self, *args, **kwargs): - url_args = [self.compute_url] - - if self.base_url: - url_args.append(self.base_url) - - url = '/'.join(str(a).strip('/') for a in tuple(url_args) + args) - - if kwargs: - url += '?%s' % parse.urlencode(kwargs, doseq=True) - - return url diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/certs.py b/awx/lib/site-packages/novaclient/tests/fixture_data/certs.py deleted file mode 100644 index 40421ca1bc..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/certs.py +++ /dev/null @@ -1,55 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-certificates' - - def get_os_certificates_root(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': None, 'data': 'foo'}} - ) - - def post_os_certificates(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': 'foo', 'data': 'bar'}} - ) - - def setUp(self): - super(Fixture, self).setUp() - - get_os_certificate = { - 'certificate': { - 'private_key': None, - 'data': 'foo' - } - } - self.requests.register_uri('GET', self.url('root'), - json=get_os_certificate, - headers=self.json_headers) - - post_os_certificates = { - 'certificate': { - 'private_key': 'foo', - 'data': 'bar' - } - } - self.requests.register_uri('POST', self.url(), - json=post_os_certificates, - headers=self.json_headers) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/client.py b/awx/lib/site-packages/novaclient/tests/fixture_data/client.py deleted file mode 100644 index e52d4a2335..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/client.py +++ /dev/null @@ -1,83 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -from keystoneclient.auth.identity import v2 -from keystoneclient import fixture -from keystoneclient import session - -from novaclient.v1_1 import client as v1_1client -from novaclient.v3 import client as v3client - -IDENTITY_URL = 'http://identityserver:5000/v2.0' -COMPUTE_URL = 'http://compute.host' - - -class V1(fixtures.Fixture): - - def __init__(self, requests, - compute_url=COMPUTE_URL, identity_url=IDENTITY_URL): - super(V1, self).__init__() - self.identity_url = identity_url - self.compute_url = compute_url - self.client = None - self.requests = requests - - self.token = fixture.V2Token() - self.token.set_scope() - - s = self.token.add_service('compute') - s.add_endpoint(self.compute_url) - - s = self.token.add_service('computev3') - s.add_endpoint(self.compute_url) - - def setUp(self): - super(V1, self).setUp() - - auth_url = '%s/tokens' % self.identity_url - headers = {'X-Content-Type': 'application/json'} - self.requests.register_uri('POST', auth_url, - json=self.token, - headers=headers) - self.client = self.new_client() - - def new_client(self): - return v1_1client.Client(username='xx', - api_key='xx', - project_id='xx', - auth_url=self.identity_url) - - -class V3(V1): - - def new_client(self): - return v3client.Client(username='xx', - password='xx', - project_id='xx', - auth_url=self.identity_url) - - -class SessionV1(V1): - - def new_client(self): - self.session = session.Session() - self.session.auth = v2.Password(self.identity_url, 'xx', 'xx') - return v1_1client.Client(session=self.session) - - -class SessionV3(V1): - - def new_client(self): - self.session = session.Session() - self.session.auth = v2.Password(self.identity_url, 'xx', 'xx') - return v3client.Client(session=self.session) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/cloudpipe.py b/awx/lib/site-packages/novaclient/tests/fixture_data/cloudpipe.py deleted file mode 100644 index 32b5c210ca..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/cloudpipe.py +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-cloudpipe' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_cloudpipe = {'cloudpipes': [{'project_id': 1}]} - self.requests.register_uri('GET', self.url(), - json=get_os_cloudpipe, - headers=self.json_headers) - - instance_id = '9d5824aa-20e6-4b9f-b967-76a699fc51fd' - post_os_cloudpipe = {'instance_id': instance_id} - self.requests.register_uri('POST', self.url(), - json=post_os_cloudpipe, - headers=self.json_headers, - status_code=202) - - self.requests.register_uri('PUT', self.url('configure-project'), - headers=self.json_headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/fixedips.py b/awx/lib/site-packages/novaclient/tests/fixture_data/fixedips.py deleted file mode 100644 index 71f18a4e65..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/fixedips.py +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-fixed-ips' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_fixed_ips = { - "fixed_ip": { - 'cidr': '192.168.1.0/24', - 'address': '192.168.1.1', - 'hostname': 'foo', - 'host': 'bar' - } - } - - self.requests.register_uri('GET', self.url('192.168.1.1'), - json=get_os_fixed_ips, - headers=self.json_headers) - - self.requests.register_uri('POST', - self.url('192.168.1.1', 'action'), - headers=self.json_headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/floatingips.py b/awx/lib/site-packages/novaclient/tests/fixture_data/floatingips.py deleted file mode 100644 index 5fc6848a74..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/floatingips.py +++ /dev/null @@ -1,210 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests import fakes -from novaclient.tests.fixture_data import base - - -class FloatingFixture(base.Fixture): - - base_url = 'os-floating-ips' - - def setUp(self): - super(FloatingFixture, self).setUp() - - floating_ips = [{'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}] - - get_os_floating_ips = {'floating_ips': floating_ips} - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ips, - headers=self.json_headers) - - for ip in floating_ips: - get_os_floating_ip = {'floating_ip': ip} - self.requests.register_uri('GET', self.url(ip['id']), - json=get_os_floating_ip, - headers=self.json_headers) - - self.requests.register_uri('DELETE', self.url(ip['id']), - headers=self.json_headers, - status_code=204) - - def post_os_floating_ips(request, context): - body = jsonutils.loads(request.body) - ip = floating_ips[0].copy() - ip['pool'] = body.get('pool') - return {'floating_ip': ip} - self.requests.register_uri('POST', self.url(), - json=post_os_floating_ips, - headers=self.json_headers) - - -class DNSFixture(base.Fixture): - - base_url = 'os-floating-ip-dns' - - def setUp(self): - super(DNSFixture, self).setUp() - - get_os_floating_ip_dns = { - 'domain_entries': [ - {'domain': 'example.org'}, - {'domain': 'example.com'} - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ip_dns, - headers=self.json_headers, - status_code=205) - - get_dns_testdomain_entries_testname = { - 'dns_entry': { - 'ip': "10.10.10.10", - 'name': 'testname', - 'type': "A", - 'domain': 'testdomain' - } - } - url = self.url('testdomain', 'entries', 'testname') - self.requests.register_uri('GET', url, - json=get_dns_testdomain_entries_testname, - headers=self.json_headers, - status_code=205) - - self.requests.register_uri('DELETE', self.url('testdomain')) - - url = self.url('testdomain', 'entries', 'testname') - self.requests.register_uri('DELETE', url) - - def put_dns_testdomain_entries_testname(request, context): - body = jsonutils.loads(request.body) - fakes.assert_has_keys(body['dns_entry'], - required=['ip', 'dns_type']) - context.status_code = 205 - return request.body - self.requests.register_uri('PUT', url, - text=put_dns_testdomain_entries_testname, - headers=self.json_headers) - - url = self.url('testdomain', 'entries') - self.requests.register_uri('GET', url, status_code=404) - - get_os_floating_ip_dns_testdomain = { - 'dns_entries': [ - { - 'dns_entry': { - 'ip': '1.2.3.4', - 'name': "host1", - 'type': "A", - 'domain': 'testdomain' - } - }, - { - 'dns_entry': { - 'ip': '1.2.3.4', - 'name': "host2", - 'type': "A", - 'domain': 'testdomain' - } - }, - ] - } - self.requests.register_uri('GET', url + '?ip=1.2.3.4', - json=get_os_floating_ip_dns_testdomain, - status_code=205, - headers=self.json_headers) - - def put_os_floating_ip_dns_testdomain(request, context): - body = jsonutils.loads(request.body) - if body['domain_entry']['scope'] == 'private': - fakes.assert_has_keys(body['domain_entry'], - required=['availability_zone', 'scope']) - elif body['domain_entry']['scope'] == 'public': - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - else: - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - - return request.body - - self.requests.register_uri('PUT', self.url('testdomain'), - text=put_os_floating_ip_dns_testdomain, - status_code=205, - headers=self.json_headers) - - -class BulkFixture(base.Fixture): - - base_url = 'os-floating-ips-bulk' - - def setUp(self): - super(BulkFixture, self).setUp() - - get_os_floating_ips_bulk = { - 'floating_ip_info': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ips_bulk, - headers=self.json_headers) - self.requests.register_uri('GET', self.url('testHost'), - json=get_os_floating_ips_bulk, - headers=self.json_headers) - - def put_os_floating_ips_bulk_delete(request, context): - body = jsonutils.loads(request.body) - ip_range = body.get('ip_range') - return {'floating_ips_bulk_delete': ip_range} - - self.requests.register_uri('PUT', self.url('delete'), - json=put_os_floating_ips_bulk_delete, - headers=self.json_headers) - - def post_os_floating_ips_bulk(request, context): - body = jsonutils.loads(request.body) - params = body.get('floating_ips_bulk_create') - pool = params.get('pool', 'defaultPool') - interface = params.get('interface', 'defaultInterface') - return { - 'floating_ips_bulk_create': { - 'ip_range': '192.168.1.0/30', - 'pool': pool, - 'interface': interface - } - } - - self.requests.register_uri('POST', self.url(), - json=post_os_floating_ips_bulk, - headers=self.json_headers) - - -class PoolsFixture(base.Fixture): - - base_url = 'os-floating-ip-pools' - - def setUp(self): - super(PoolsFixture, self).setUp() - - get_os_floating_ip_pools = { - 'floating_ip_pools': [ - {'name': 'foo'}, - {'name': 'bar'} - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ip_pools, - headers=self.json_headers) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/fping.py b/awx/lib/site-packages/novaclient/tests/fixture_data/fping.py deleted file mode 100644 index 837db6daa0..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/fping.py +++ /dev/null @@ -1,46 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-fping' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_fping_1 = { - 'server': { - "id": "1", - "project_id": "fake-project", - "alive": True, - } - } - self.requests.register_uri('GET', self.url(1), - json=get_os_fping_1, - headers=self.json_headers) - - get_os_fping = { - 'servers': [ - get_os_fping_1['server'], - { - "id": "2", - "project_id": "fake-project", - "alive": True, - }, - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_fping, - headers=self.json_headers) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/hosts.py b/awx/lib/site-packages/novaclient/tests/fixture_data/hosts.py deleted file mode 100644 index babfbec7c7..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/hosts.py +++ /dev/null @@ -1,169 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from six.moves.urllib import parse - -from novaclient.openstack.common import jsonutils -from novaclient.tests.fixture_data import base - - -class BaseFixture(base.Fixture): - - base_url = 'os-hosts' - - def setUp(self): - super(BaseFixture, self).setUp() - - get_os_hosts_host = { - 'host': [ - {'resource': {'project': '(total)', 'host': 'dummy', - 'cpu': 16, 'memory_mb': 32234, 'disk_gb': 128}}, - {'resource': {'project': '(used_now)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2075, 'disk_gb': 45}}, - {'resource': {'project': '(used_max)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}, - {'resource': {'project': 'admin', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}} - ] - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url('host'), - json=get_os_hosts_host, - headers=headers) - - def get_os_hosts(request, context): - host, query = parse.splitquery(request.url) - zone = 'nova1' - service = None - - if query: - qs = parse.parse_qs(query) - try: - zone = qs['zone'][0] - except Exception: - pass - - try: - service = qs['service'][0] - except Exception: - pass - - return { - 'hosts': [ - { - 'host': 'host1', - 'service': service or 'nova-compute', - 'zone': zone - }, - { - 'host': 'host1', - 'service': service or 'nova-cert', - 'zone': zone - } - ] - } - - self.requests.register_uri('GET', self.url(), - json=get_os_hosts, - headers=headers) - - get_os_hosts_sample_host = { - 'host': [ - {'resource': {'host': 'sample_host'}} - ], - } - self.requests.register_uri('GET', self.url('sample_host'), - json=get_os_hosts_sample_host, - headers=headers) - - self.requests.register_uri('PUT', self.url('sample_host', 1), - json=self.put_host_1(), - headers=headers) - - self.requests.register_uri('PUT', self.url('sample_host', 2), - json=self.put_host_2(), - headers=headers) - - self.requests.register_uri('PUT', self.url('sample_host', 3), - json=self.put_host_3(), - headers=headers) - - self.requests.register_uri('GET', self.url('sample_host', 'reboot'), - json=self.get_host_reboot(), - headers=headers) - - self.requests.register_uri('GET', self.url('sample_host', 'startup'), - json=self.get_host_startup(), - headers=headers) - - self.requests.register_uri('GET', self.url('sample_host', 'shutdown'), - json=self.get_host_shutdown(), - headers=headers) - - def put_os_hosts_sample_host(request, context): - result = {'host': 'dummy'} - result.update(jsonutils.loads(request.body)) - return result - - self.requests.register_uri('PUT', self.url('sample_host'), - json=put_os_hosts_sample_host, - headers=headers) - - -class V1(BaseFixture): - - def put_host_1(self): - return {'host': 'sample-host_1', - 'status': 'enabled'} - - def put_host_2(self): - return {'host': 'sample-host_2', - 'maintenance_mode': 'on_maintenance'} - - def put_host_3(self): - return {'host': 'sample-host_3', - 'status': 'enabled', - 'maintenance_mode': 'on_maintenance'} - - def get_host_reboot(self): - return {'host': 'sample_host', - 'power_action': 'reboot'} - - def get_host_startup(self): - return {'host': 'sample_host', - 'power_action': 'startup'} - - def get_host_shutdown(self): - return {'host': 'sample_host', - 'power_action': 'shutdown'} - - -class V3(V1): - def put_host_1(self): - return {'host': super(V3, self).put_host_1()} - - def put_host_2(self): - return {'host': super(V3, self).put_host_2()} - - def put_host_3(self): - return {'host': super(V3, self).put_host_3()} - - def get_host_reboot(self): - return {'host': super(V3, self).get_host_reboot()} - - def get_host_startup(self): - return {'host': super(V3, self).get_host_startup()} - - def get_host_shutdown(self): - return {'host': super(V3, self).get_host_shutdown()} diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/hypervisors.py b/awx/lib/site-packages/novaclient/tests/fixture_data/hypervisors.py deleted file mode 100644 index c3f6f7210d..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/hypervisors.py +++ /dev/null @@ -1,215 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-hypervisors' - - def setUp(self): - super(V1, self).setUp() - - get_os_hypervisors = { - 'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'}, - ] - } - - self.headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_os_hypervisors, - headers=self.headers) - - get_os_hypervisors_detail = { - 'hypervisors': [ - { - 'id': 1234, - 'service': { - 'id': 1, - 'host': 'compute1', - }, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'hypervisor_hostname': 'hyper1', - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100 - }, - { - 'id': 2, - 'service': { - 'id': 2, - 'host': 'compute2', - }, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'hypervisor_hostname': 'hyper2', - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100 - } - ] - } - - self.requests.register_uri('GET', self.url('detail'), - json=get_os_hypervisors_detail, - headers=self.headers) - - get_os_hypervisors_stats = { - 'hypervisor_statistics': { - 'count': 2, - 'vcpus': 8, - 'memory_mb': 20 * 1024, - 'local_gb': 500, - 'vcpus_used': 4, - 'memory_mb_used': 10 * 1024, - 'local_gb_used': 250, - 'free_ram_mb': 10 * 1024, - 'free_disk_gb': 250, - 'current_workload': 4, - 'running_vms': 4, - 'disk_available_least': 200, - } - } - - self.requests.register_uri('GET', self.url('statistics'), - json=get_os_hypervisors_stats, - headers=self.headers) - - get_os_hypervisors_search = { - 'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'} - ] - } - - self.requests.register_uri('GET', self.url('hyper', 'search'), - json=get_os_hypervisors_search, - headers=self.headers) - - get_hyper_server = { - 'hypervisors': [ - { - 'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'servers': [ - {'name': 'inst1', 'uuid': 'uuid1'}, - {'name': 'inst2', 'uuid': 'uuid2'} - ] - }, - { - 'id': 5678, - 'hypervisor_hostname': 'hyper2', - 'servers': [ - {'name': 'inst3', 'uuid': 'uuid3'}, - {'name': 'inst4', 'uuid': 'uuid4'} - ] - } - ] - } - - self.requests.register_uri('GET', self.url('hyper', 'servers'), - json=get_hyper_server, - headers=self.headers) - - get_os_hypervisors_1234 = { - 'hypervisor': { - 'id': 1234, - 'service': {'id': 1, 'host': 'compute1'}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'hypervisor_hostname': 'hyper1', - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100 - } - } - - self.requests.register_uri('GET', self.url(1234), - json=get_os_hypervisors_1234, - headers=self.headers) - - get_os_hypervisors_uptime = { - 'hypervisor': { - 'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'uptime': 'fake uptime' - } - } - - self.requests.register_uri('GET', self.url(1234, 'uptime'), - json=get_os_hypervisors_uptime, - headers=self.headers) - - -class V3(V1): - - def setUp(self): - super(V3, self).setUp() - - get_os_hypervisors_search = { - 'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'} - ] - } - - self.requests.register_uri('GET', - self.url('search', query='hyper'), - json=get_os_hypervisors_search, - headers=self.headers) - - get_1234_servers = { - 'hypervisor': { - 'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'servers': [ - {'name': 'inst1', 'id': 'uuid1'}, - {'name': 'inst2', 'id': 'uuid2'} - ] - }, - } - - self.requests.register_uri('GET', self.url(1234, 'servers'), - json=get_1234_servers, - headers=self.headers) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/images.py b/awx/lib/site-packages/novaclient/tests/fixture_data/images.py deleted file mode 100644 index 40cfd0c949..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/images.py +++ /dev/null @@ -1,112 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests import fakes -from novaclient.tests.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'images' - - def setUp(self): - super(V1, self).setUp() - - get_images = { - 'images': [ - {'id': 1, 'name': 'CentOS 5.2'}, - {'id': 2, 'name': 'My Server Backup'} - ] - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_images, - headers=headers) - - image_1 = { - 'id': 1, - 'name': 'CentOS 5.2', - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "ACTIVE", - "metadata": { - "test_key": "test_value", - }, - "links": {}, - } - - image_2 = { - "id": 2, - "name": "My Server Backup", - "serverId": 1234, - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "SAVING", - "progress": 80, - "links": {}, - } - - self.requests.register_uri('GET', self.url('detail'), - json={'images': [image_1, image_2]}, - headers=headers) - - self.requests.register_uri('GET', self.url(1), - json={'image': image_1}, - headers=headers) - - self.requests.register_uri('GET', self.url(2), - json={'image': image_2}, - headers=headers) - - self.requests.register_uri('GET', self.url(456), - json={'image': image_2}, - headers=headers) - - def post_images(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['image'] - fakes.assert_has_keys(body['image'], required=['serverId', 'name']) - return images_1 - - self.requests.register_uri('POST', self.url(), - json=post_images, - headers=headers, - status_code=202) - - def post_images_1_metadata(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['metadata'] - fakes.assert_has_keys(body['metadata'], required=['test_key']) - return {'metadata': image_1['metadata']} - - self.requests.register_uri('POST', self.url(1, 'metadata'), - json=post_images_1_metadata, - headers=headers) - - for u in (1, 2, '1/metadata/test_key'): - self.requests.register_uri('DELETE', self.url(u), status_code=204) - - image_headers = {'x-image-meta-id': '1', - 'x-image-meta-name': 'CentOS 5.2', - 'x-image-meta-updated': '2010-10-10T12:00:00Z', - 'x-image-meta-created': '2010-10-10T12:00:00Z', - 'x-image-meta-status': 'ACTIVE', - 'x-image-meta-property-test-key': 'test_value'} - self.requests.register_uri('HEAD', self.url(1), headers=image_headers) - - -class V3(V1): - - base_url = 'v1/images' diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/keypairs.py b/awx/lib/site-packages/novaclient/tests/fixture_data/keypairs.py deleted file mode 100644 index cc8921beb7..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/keypairs.py +++ /dev/null @@ -1,51 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests import fakes -from novaclient.tests.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-keypairs' - - def setUp(self): - super(V1, self).setUp() - keypair = {'fingerprint': 'FAKE_KEYPAIR', 'name': 'test'} - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json={'keypairs': [keypair]}, - headers=headers) - - self.requests.register_uri('GET', self.url('test'), - json={'keypair': keypair}, - headers=headers) - - self.requests.register_uri('DELETE', self.url('test'), status_code=202) - - def post_os_keypairs(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['keypair'] - fakes.assert_has_keys(body['keypair'], required=['name']) - return {'keypair': keypair} - - self.requests.register_uri('POST', self.url(), - json=post_os_keypairs, - headers=headers) - - -class V3(V1): - - base_url = 'keypairs' diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/limits.py b/awx/lib/site-packages/novaclient/tests/fixture_data/limits.py deleted file mode 100644 index 0b9488d3fb..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/limits.py +++ /dev/null @@ -1,80 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'limits' - - def setUp(self): - super(Fixture, self).setUp() - - get_limits = { - "limits": { - "rate": [ - { - "uri": "*", - "regex": ".*", - "limit": [ - { - "value": 10, - "verb": "POST", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 10, - "verb": "PUT", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 100, - "verb": "DELETE", - "remaining": 100, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - } - ] - }, - { - "uri": "*/servers", - "regex": "^/servers", - "limit": [ - { - "verb": "POST", - "value": 25, - "remaining": 24, - "unit": "DAY", - "next-available": "2011-12-15T22:42:45Z" - } - ] - } - ], - "absolute": { - "maxTotalRAMSize": 51200, - "maxServerMeta": 5, - "maxImageMeta": 5, - "maxPersonality": 5, - "maxPersonalitySize": 10240 - }, - }, - } - - headers = {'Content-Type': 'application/json'} - self.requests.register_uri('GET', self.url(), - json=get_limits, - headers=headers) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/networks.py b/awx/lib/site-packages/novaclient/tests/fixture_data/networks.py deleted file mode 100644 index df721b25d1..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/networks.py +++ /dev/null @@ -1,61 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-networks' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_networks = { - 'networks': [ - { - "label": "1", - "cidr": "10.0.0.0/24", - 'project_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1' - } - ] - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_os_networks, - headers=headers) - - def post_os_networks(request, context): - body = jsonutils.loads(request.body) - return {'network': body} - - self.requests.register_uri("POST", self.url(), - json=post_os_networks, - headers=headers) - - get_os_networks_1 = {'network': {"label": "1", "cidr": "10.0.0.0/24"}} - - self.requests.register_uri('GET', self.url(1), - json=get_os_networks_1, - headers=headers) - - self.requests.register_uri('DELETE', - self.url('networkdelete'), - status_code=202) - - for u in ('add', 'networkdisassociate/action', 'networktest/action', - '1/action', '2/action'): - self.requests.register_uri('POST', self.url(u), status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/quotas.py b/awx/lib/site-packages/novaclient/tests/fixture_data/quotas.py deleted file mode 100644 index 3250f8843d..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/quotas.py +++ /dev/null @@ -1,84 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-quota-sets' - - def setUp(self): - super(V1, self).setUp() - - uuid = '97f4c221-bff4-4578-b030-0df4ef119353' - uuid2 = '97f4c221bff44578b0300df4ef119353' - test_json = {'quota_set': self.test_quota('test')} - self.headers = {'Content-Type': 'application/json'} - - for u in ('test', 'tenant-id', 'tenant-id/defaults', - '%s/defaults' % uuid2): - self.requests.register_uri('GET', self.url(u), - json=test_json, - headers=self.headers) - - self.requests.register_uri('PUT', self.url(uuid), - json={'quota_set': self.test_quota(uuid)}, - headers=self.headers) - - self.requests.register_uri('GET', self.url(uuid), - json={'quota_set': self.test_quota(uuid)}, - headers=self.headers) - - self.requests.register_uri('PUT', self.url(uuid2), - json={'quota_set': self.test_quota(uuid2)}, - headers=self.headers) - self.requests.register_uri('GET', self.url(uuid2), - json={'quota_set': self.test_quota(uuid2)}, - headers=self.headers) - - for u in ('test', uuid2): - self.requests.register_uri('DELETE', self.url(u), status_code=202) - - def test_quota(self, tenant_id='test'): - return { - 'tenant_id': tenant_id, - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1 - } - - -class V3(V1): - - def setUp(self): - super(V3, self).setUp() - - get_detail = { - 'quota_set': { - 'cores': {'reserved': 0, 'in_use': 0, 'limit': 10}, - 'instances': {'reserved': 0, 'in_use': 4, 'limit': 50}, - 'ram': {'reserved': 0, 'in_use': 1024, 'limit': 51200} - } - } - - self.requests.register_uri('GET', self.url('test', 'detail'), - json=get_detail, - headers=self.headers) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/security_group_rules.py b/awx/lib/site-packages/novaclient/tests/fixture_data/security_group_rules.py deleted file mode 100644 index 480c4fc6d0..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/security_group_rules.py +++ /dev/null @@ -1,57 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests import fakes -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-security-group-rules' - - def setUp(self): - super(Fixture, self).setUp() - - rule = { - 'id': 1, - 'parent_group_id': 1, - 'group_id': 2, - 'ip_protocol': 'TCP', - 'from_port': '22', - 'to_port': 22, - 'cidr': '10.0.0.0/8' - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json={'security_group_rules': [rule]}, - headers=headers) - - for u in (1, 11, 12): - self.requests.register_uri('DELETE', self.url(u), status_code=202) - - def post_rules(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['security_group_rule'] - fakes.assert_has_keys(body['security_group_rule'], - required=['parent_group_id'], - optional=['group_id', 'ip_protocol', - 'from_port', 'to_port', 'cidr']) - - return {'security_group_rule': rule} - - self.requests.register_uri('POST', self.url(), - json=post_rules, - headers=headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/security_groups.py b/awx/lib/site-packages/novaclient/tests/fixture_data/security_groups.py deleted file mode 100644 index 7d1fed380a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/security_groups.py +++ /dev/null @@ -1,99 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests import fakes -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-security-groups' - - def setUp(self): - super(Fixture, self).setUp() - - security_group_1 = { - "name": "test", - "description": "FAKE_SECURITY_GROUP", - "tenant_id": "4ffc664c198e435e9853f2538fbcd7a7", - "id": 1, - "rules": [ - { - "id": 11, - "group": {}, - "ip_protocol": "TCP", - "from_port": 22, - "to_port": 22, - "parent_group_id": 1, - "ip_range": {"cidr": "10.0.0.0/8"} - }, - { - "id": 12, - "group": { - "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582", - "name": "test2" - }, - "ip_protocol": "TCP", - "from_port": 222, - "to_port": 222, - "parent_group_id": 1, - "ip_range": {} - } - ] - } - - security_group_2 = { - "name": "test2", - "description": "FAKE_SECURITY_GROUP2", - "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582", - "id": 2, - "rules": [] - } - - get_groups = {'security_groups': [security_group_1, security_group_2]} - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_groups, - headers=headers) - - get_group_1 = {'security_group': security_group_1} - self.requests.register_uri('GET', self.url(1), - json=get_group_1, - headers=headers) - - self.requests.register_uri('DELETE', self.url(1), status_code=202) - - def post_os_security_groups(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - return {'security_group': security_group_1} - - self.requests.register_uri('POST', self.url(), - json=post_os_security_groups, - headers=headers, - status_code=202) - - def put_os_security_groups_1(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - return body - - self.requests.register_uri('PUT', self.url(1), - json=put_os_security_groups_1, - headers=headers, - status_code=205) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/server_groups.py b/awx/lib/site-packages/novaclient/tests/fixture_data/server_groups.py deleted file mode 100644 index 47e307153d..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/server_groups.py +++ /dev/null @@ -1,73 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-server-groups' - - def setUp(self): - super(Fixture, self).setUp() - - server_groups = [ - { - "members": [], - "metadata": {}, - "id": "2cbd51f4-fafe-4cdb-801b-cf913a6f288b", - "policies": [], - "name": "ig1" - }, - { - "members": [], - "metadata": {}, - "id": "4473bb03-4370-4bfb-80d3-dc8cffc47d94", - "policies": ["anti-affinity"], - "name": "ig2" - }, - { - "members": [], - "metadata": {"key": "value"}, - "id": "31ab9bdb-55e1-4ac3-b094-97eeb1b65cc4", - "policies": [], "name": "ig3" - }, - { - "members": ["2dccb4a1-02b9-482a-aa23-5799490d6f5d"], - "metadata": {}, - "id": "4890bb03-7070-45fb-8453-d34556c87d94", - "policies": ["anti-affinity"], - "name": "ig2" - } - ] - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json={'server_groups': server_groups}, - headers=headers) - - server = server_groups[0] - server_j = jsonutils.dumps({'server_group': server}) - - def _register(method, *args): - self.requests.register_uri(method, self.url(*args), text=server_j) - - _register('POST') - _register('POST', server['id']) - _register('GET', server['id']) - _register('PUT', server['id']) - _register('POST', server['id'], '/action') - - self.requests.register_uri('DELETE', self.url(server['id']), - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/fixture_data/servers.py b/awx/lib/site-packages/novaclient/tests/fixture_data/servers.py deleted file mode 100644 index c8f87bf604..0000000000 --- a/awx/lib/site-packages/novaclient/tests/fixture_data/servers.py +++ /dev/null @@ -1,612 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common import jsonutils -from novaclient.tests import fakes -from novaclient.tests.fixture_data import base - - -class Base(base.Fixture): - - base_url = 'servers' - - def setUp(self): - super(Base, self).setUp() - - get_servers = { - "servers": [ - {'id': 1234, 'name': 'sample-server'}, - {'id': 5678, 'name': 'sample-server2'} - ] - } - - self.requests.register_uri('GET', self.url(), - json=get_servers, - headers=self.json_headers) - - self.server_1234 = { - "id": 1234, - "name": "sample-server", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0", - "status": "BUILD", - "progress": 60, - "addresses": { - "public": [{ - "version": 4, - "addr": "1.2.3.4", - }, - { - "version": 4, - "addr": "5.6.7.8", - }], - "private": [{ - "version": 4, - "addr": "10.11.12.13", - }], - }, - "metadata": { - "Server Label": "Web Head 1", - "Image Version": "2.1" - }, - "OS-EXT-SRV-ATTR:host": "computenode1", - "security_groups": [{ - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - "OS-EXT-MOD:some_thing": "mod_some_thing_value", - } - - self.server_5678 = { - "id": 5678, - "name": "sample-server2", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [{ - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - }, - "OS-EXT-SRV-ATTR:host": "computenode2", - "security_groups": [{ - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }, - { - 'id': 2, 'name': 'securitygroup2', - 'description': 'ANOTHER_FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - } - - self.server_9012 = { - "id": 9012, - "name": "sample-server3", - "image": "", - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [{ - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - } - } - - servers = [self.server_1234, self.server_5678, self.server_9012] - get_servers_detail = {"servers": servers} - - self.requests.register_uri('GET', self.url('detail'), - json=get_servers_detail, - headers=self.json_headers) - - self.server_1235 = self.server_1234.copy() - self.server_1235['id'] = 1235 - self.server_1235['status'] = 'error' - self.server_1235['fault'] = {'message': 'something went wrong!'} - - for s in servers + [self.server_1235]: - self.requests.register_uri('GET', self.url(s['id']), - json={'server': s}, - headers=self.json_headers) - - for s in (1234, 5678): - self.requests.register_uri('DELETE', self.url(s), status_code=202) - - for k in ('test_key', 'key1', 'key2'): - self.requests.register_uri('DELETE', - self.url(1234, 'metadata', k), - status_code=204) - - metadata1 = {'metadata': {'test_key': 'test_value'}} - self.requests.register_uri('POST', self.url(1234, 'metadata'), - json=metadata1, - headers=self.json_headers) - self.requests.register_uri('PUT', - self.url(1234, 'metadata', 'test_key'), - json=metadata1, - headers=self.json_headers) - - self.diagnostic = {'data': 'Fake diagnostics'} - - metadata2 = {'metadata': {'key1': 'val1'}} - for u in ('uuid1', 'uuid2', 'uuid3', 'uuid4'): - self.requests.register_uri('POST', self.url(u, 'metadata'), - json=metadata2, status_code=204) - self.requests.register_uri('DELETE', - self.url(u, 'metadata', 'key1'), - json=self.diagnostic, - headers=self.json_headers) - - get_security_groups = { - "security_groups": [{ - 'id': 1, - 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'rules': []}] - } - - self.requests.register_uri('GET', - self.url('1234', 'os-security-groups'), - json=get_security_groups) - - self.requests.register_uri('POST', self.url(), - json=self.post_servers, - headers=self.json_headers) - - self.requests.register_uri('POST', self.url('1234', 'action'), - json=self.post_servers_1234_action, - headers=self.json_headers) - - get_os_interface = { - "interfaceAttachments": [ - { - "port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - }, - { - "port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - } - ] - } - - self.requests.register_uri('GET', - self.url('1234', 'os-interface'), - json=get_os_interface, - headers=self.json_headers) - - interface_data = {'interfaceAttachment': {}} - self.requests.register_uri('POST', - self.url('1234', 'os-interface'), - json=interface_data, - headers=self.json_headers) - - def put_servers_1234(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['server'] - fakes.assert_has_keys(body['server'], - optional=['name', 'adminPass']) - return request.body - - self.requests.register_uri('PUT', self.url(1234), - text=put_servers_1234, - status_code=204, - headers=self.json_headers) - - def post_os_volumes_boot(request, context): - body = jsonutils.loads(request.body) - assert (set(body.keys()) <= - set(['server', 'os:scheduler_hints'])) - - fakes.assert_has_keys(body['server'], - required=['name', 'flavorRef'], - optional=['imageRef']) - - data = body['server'] - - # Require one, and only one, of the keys for bdm - if 'block_device_mapping' not in data: - if 'block_device_mapping_v2' not in data: - msg = "missing required keys: 'block_device_mapping'" - raise AssertionError(msg) - elif 'block_device_mapping_v2' in data: - msg = "found extra keys: 'block_device_mapping'" - raise AssertionError(msg) - - return {'server': self.server_9012} - - # NOTE(jamielennox): hack to make os_volumes mock go to the right place - base_url = self.base_url - self.base_url = None - self.requests.register_uri('POST', self.url('os-volumes_boot'), - json=post_os_volumes_boot, - status_code=202, - headers=self.json_headers) - self.base_url = base_url - - # - # Server password - # - - self.requests.register_uri('DELETE', - self.url(1234, 'os-server-password'), - status_code=202) - - -class V1(Base): - - def setUp(self): - super(V1, self).setUp() - - # - # Server Addresses - # - - add = self.server_1234['addresses'] - self.requests.register_uri('GET', self.url(1234, 'ips'), - json={'addresses': add}, - headers=self.json_headers) - - self.requests.register_uri('GET', self.url(1234, 'ips', 'public'), - json={'public': add['public']}, - headers=self.json_headers) - - self.requests.register_uri('GET', self.url(1234, 'ips', 'private'), - json={'private': add['private']}, - headers=self.json_headers) - - self.requests.register_uri('DELETE', - self.url(1234, 'ips', 'public', '1.2.3.4'), - status_code=202) - - self.requests.register_uri('GET', - self.url('1234', 'diagnostics'), - json=self.diagnostic) - - self.requests.register_uri('DELETE', - self.url('1234', 'os-interface', 'port-id')) - - # Testing with the following password and key - # - # Clear password: FooBar123 - # - # RSA Private Key: novaclient/tests/idfake.pem - # - # Encrypted password - # OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r - # qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho - # QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw - # /y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N - # tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk - # Hi/fmZZNQQqj1Ijq0caOIw== - - get_server_password = {'password': - 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r' - 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho' - 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw' - '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N' - 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk' - 'Hi/fmZZNQQqj1Ijq0caOIw=='} - self.requests.register_uri('GET', - self.url(1234, 'os-server-password'), - json=get_server_password) - - def post_servers(self, request, context): - body = jsonutils.loads(request.body) - context.status_code = 202 - assert (set(body.keys()) <= - set(['server', 'os:scheduler_hints'])) - fakes.assert_has_keys(body['server'], - required=['name', 'imageRef', 'flavorRef'], - optional=['metadata', 'personality']) - if 'personality' in body['server']: - for pfile in body['server']['personality']: - fakes.assert_has_keys(pfile, required=['path', 'contents']) - if body['server']['name'] == 'some-bad-server': - body = self.server_1235 - else: - body = self.server_1234 - - return {'server': body} - - def post_servers_1234_action(self, request, context): - _body = '' - body = jsonutils.loads(request.body) - context.status_code = 202 - assert len(body.keys()) == 1 - action = list(body)[0] - if action == 'reboot': - assert list(body[action]) == ['type'] - assert body[action]['type'] in ['HARD', 'SOFT'] - elif action == 'rebuild': - body = body[action] - adminPass = body.get('adminPass', 'randompassword') - assert 'imageRef' in body - _body = self.server_1234.copy() - _body['adminPass'] = adminPass - elif action == 'resize': - keys = body[action].keys() - assert 'flavorRef' in keys - elif action == 'confirmResize': - assert body[action] is None - # This one method returns a different response code - context.status_code = 204 - return None - elif action == 'revertResize': - assert body[action] is None - elif action == 'migrate': - assert body[action] is None - elif action == 'os-stop': - assert body[action] is None - elif action == 'os-start': - assert body[action] is None - elif action == 'forceDelete': - assert body[action] is None - elif action == 'restore': - assert body[action] is None - elif action == 'pause': - assert body[action] is None - elif action == 'unpause': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'rescue': - assert body[action] is None - _body = {'Password': 'RescuePassword'} - elif action == 'unrescue': - assert body[action] is None - elif action == 'resume': - assert body[action] is None - elif action == 'suspend': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'shelve': - assert body[action] is None - elif action == 'shelveOffload': - assert body[action] is None - elif action == 'unshelve': - assert body[action] is None - elif action == 'addFixedIp': - assert list(body[action]) == ['networkId'] - elif action == 'removeFixedIp': - assert list(body[action]) == ['address'] - elif action == 'addFloatingIp': - assert (list(body[action]) == ['address'] or - sorted(list(body[action])) == ['address', - 'fixed_address']) - elif action == 'removeFloatingIp': - assert list(body[action]) == ['address'] - elif action == 'createImage': - assert set(body[action].keys()) == set(['name', 'metadata']) - context.headers['location'] = "http://blah/images/456" - elif action == 'changePassword': - assert list(body[action]) == ['adminPass'] - elif action == 'os-getConsoleOutput': - assert list(body[action]) == ['length'] - context.status_code = 202 - return {'output': 'foo'} - elif action == 'os-getVNCConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getSPICEConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getRDPConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getSerialConsole': - assert list(body[action]) == ['type'] - elif action == 'os-migrateLive': - assert set(body[action].keys()) == set(['host', - 'block_migration', - 'disk_over_commit']) - elif action == 'os-resetState': - assert list(body[action]) == ['state'] - elif action == 'resetNetwork': - assert body[action] is None - elif action == 'addSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'removeSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'createBackup': - assert set(body[action]) == set(['name', - 'backup_type', - 'rotation']) - elif action == 'evacuate': - keys = list(body[action]) - if 'adminPass' in keys: - keys.remove('adminPass') - assert set(keys) == set(['host', 'onSharedStorage']) - else: - raise AssertionError("Unexpected server action: %s" % action) - return {'server': _body} - - -class V3(Base): - - def setUp(self): - super(V3, self).setUp() - - get_interfaces = { - "interface_attachments": [ - { - "port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - }, - { - "port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - } - ] - } - - self.requests.register_uri('GET', - self.url('1234', 'os-attach-interfaces'), - json=get_interfaces, - headers=self.json_headers) - - attach_body = {'interface_attachment': {}} - self.requests.register_uri('POST', - self.url('1234', 'os-attach-interfaces'), - json=attach_body, - headers=self.json_headers) - - self.requests.register_uri('GET', - self.url('1234', 'os-server-diagnostics'), - json=self.diagnostic) - - url = self.url('1234', 'os-attach-interfaces', 'port-id') - self.requests.register_uri('DELETE', url) - - self.requests.register_uri('GET', - self.url(1234, 'os-server-password'), - json={'password': ''}) - - def post_servers(self, request, context): - body = jsonutils.loads(request.body) - assert set(body.keys()) <= set(['server']) - fakes.assert_has_keys(body['server'], - required=['name', 'image_ref', 'flavor_ref'], - optional=['metadata', 'personality', - 'os-scheduler-hints:scheduler_hints']) - if body['server']['name'] == 'some-bad-server': - body = self.server_1235 - else: - body = self.server_1234 - - context.status_code = 202 - return {'server': body} - - def post_servers_1234_action(self, request, context): - context.status_code = 202 - body_is_none_list = [ - 'revert_resize', 'migrate', 'stop', 'start', 'force_delete', - 'restore', 'pause', 'unpause', 'lock', 'unlock', 'unrescue', - 'resume', 'suspend', 'lock', 'unlock', 'shelve', 'shelve_offload', - 'unshelve', 'reset_network', 'rescue', 'confirm_resize'] - body_return_map = { - 'rescue': {'admin_password': 'RescuePassword'}, - 'get_console_output': {'output': 'foo'}, - 'rebuild': {'server': self.server_1234}, - } - body_param_check_exists = { - 'rebuild': 'image_ref', - 'resize': 'flavor_ref'} - body_params_check_exact = { - 'reboot': ['type'], - 'add_fixed_ip': ['network_id'], - 'evacuate': ['host', 'on_shared_storage'], - 'remove_fixed_ip': ['address'], - 'change_password': ['admin_password'], - 'get_console_output': ['length'], - 'get_vnc_console': ['type'], - 'get_spice_console': ['type'], - 'get_serial_console': ['type'], - 'reset_state': ['state'], - 'create_image': ['name', 'metadata'], - 'migrate_live': ['host', 'block_migration', 'disk_over_commit'], - 'create_backup': ['name', 'backup_type', 'rotation'], - 'attach': ['volume_id', 'device'], - 'detach': ['volume_id'], - 'swap_volume_attachment': ['old_volume_id', 'new_volume_id']} - - body = jsonutils.loads(request.body) - assert len(body.keys()) == 1 - action = list(body)[0] - _body = body_return_map.get(action, '') - - if action in body_is_none_list: - assert body[action] is None - - if action in body_param_check_exists: - assert body_param_check_exists[action] in body[action] - - if action == 'evacuate': - body[action].pop('admin_password', None) - - if action in body_params_check_exact: - assert set(body[action]) == set(body_params_check_exact[action]) - - if action == 'reboot': - assert body[action]['type'] in ['HARD', 'SOFT'] - elif action == 'confirm_resize': - # This one method returns a different response code - context.status_code = 204 - elif action == 'create_image': - context.headers['location'] = "http://blah/images/456" - - if action not in set.union(set(body_is_none_list), - set(body_params_check_exact.keys()), - set(body_param_check_exists.keys())): - raise AssertionError("Unexpected server action: %s" % action) - - return _body diff --git a/awx/lib/site-packages/novaclient/tests/functional/README.rst b/awx/lib/site-packages/novaclient/tests/functional/README.rst deleted file mode 100644 index be4ebd079f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/functional/README.rst +++ /dev/null @@ -1,50 +0,0 @@ -===================================== -python-novaclient functional testing -===================================== - -Idea ------- - -Over time we have noticed two issues with novaclient unit tests. - -* Does not exercise the CLI -* We can get the expected server behavior wrong, and test the wrong thing. - -We are using functional tests, run against a running cloud -(primarily devstack), to address these two cases. - -Additionally these functional tests can be considered example uses -of python-novaclient. - -These tests started out in tempest as read only nova CLI tests, to make sure -the CLI didn't simply stacktrace when being used (which happened on -multiple occasions). - - -Testing Theory ----------------- - -We are treating python-novaclient as legacy code, so we do not want to spend a -lot of effort adding in missing features. In the future the CLI will move to -python-openstackclient, and the python API will be based on the OpenStack -SDK project. But until that happens we still need better functional testing, -to prevent regressions etc. - - -Since python-novaclient has two uses, CLI and python API, we should have two -sets of functional tests. CLI and python API. The python API tests should -never use the CLI. But the CLI tests can use the python API where adding -native support to the CLI for the required functionality would involve a -non trivial amount of work. - -Functional Test Guidelines ---------------------------- - -* Consume credentials via standard client environmental variables:: - - OS_USERNAME - OS_PASSWORD - OS_TENANT_NAME - OS_AUTH_URL - -* Try not to require an additional configuration file diff --git a/awx/lib/site-packages/novaclient/tests/functional/__init__.py b/awx/lib/site-packages/novaclient/tests/functional/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/tests/functional/base.py b/awx/lib/site-packages/novaclient/tests/functional/base.py deleted file mode 100644 index 27015bda8a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/functional/base.py +++ /dev/null @@ -1,44 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -from tempest_lib.cli import base - - -class ClientTestBase(base.ClientTestBase): - """ - This is a first pass at a simple read only python-novaclient test. This - only exercises client commands that are read only. - - This should test commands: - * as a regular user - * as a admin user - * with and without optional parameters - * initially just check return codes, and later test command outputs - - """ - def _get_clients(self): - cli_dir = os.environ.get( - 'OS_NOVACLIENT_EXEC_DIR', - os.path.join(os.path.abspath('.'), '.tox/functional/bin')) - - return base.CLIClient( - username=os.environ.get('OS_USERNAME'), - password=os.environ.get('OS_PASSWORD'), - tenant_name=os.environ.get('OS_TENANT_NAME'), - uri=os.environ.get('OS_AUTH_URL'), - cli_dir=cli_dir) - - def nova(self, *args, **kwargs): - return self.clients.nova(*args, - **kwargs) diff --git a/awx/lib/site-packages/novaclient/tests/functional/hooks/post_test_hook.sh b/awx/lib/site-packages/novaclient/tests/functional/hooks/post_test_hook.sh deleted file mode 100755 index e9e35b24ec..0000000000 --- a/awx/lib/site-packages/novaclient/tests/functional/hooks/post_test_hook.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -xe - -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# This script is executed inside post_test_hook function in devstack gate. - -function generate_testr_results { - if [ -f .testrepository/0 ]; then - sudo .tox/functional/bin/testr last --subunit > $WORKSPACE/testrepository.subunit - sudo mv $WORKSPACE/testrepository.subunit $BASE/logs/testrepository.subunit - sudo .tox/functional/bin/python /usr/local/jenkins/slave_scripts/subunit2html.py $BASE/logs/testrepository.subunit $BASE/logs/testr_results.html - sudo gzip -9 $BASE/logs/testrepository.subunit - sudo gzip -9 $BASE/logs/testr_results.html - sudo chown jenkins:jenkins $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz - sudo chmod a+r $BASE/logs/testrepository.subunit.gz $BASE/logs/testr_results.html.gz - fi -} - -export NOVACLIENT_DIR="$BASE/new/python-novaclient" - -# Get admin credentials -cd $BASE/new/devstack -source openrc admin admin - -# Go to the novaclient dir -cd $NOVACLIENT_DIR - -sudo chown -R jenkins:stack $NOVACLIENT_DIR - -# Run tests -echo "Running novaclient functional test suite" -set +e -# Preserve env for OS_ credentials -sudo -E -H -u jenkins tox -efunctional -EXIT_CODE=$? -set -e - -# Collect and parse result -generate_testr_results -exit $EXIT_CODE diff --git a/awx/lib/site-packages/novaclient/tests/functional/test_instances.py b/awx/lib/site-packages/novaclient/tests/functional/test_instances.py deleted file mode 100644 index c963a6b710..0000000000 --- a/awx/lib/site-packages/novaclient/tests/functional/test_instances.py +++ /dev/null @@ -1,155 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import time -import uuid - -import novaclient.client -from novaclient.tests.functional import base - - -# TODO(sdague): content that probably should be in utils, also throw -# Exceptions when they fail. -def pick_flavor(flavors): - """Given a flavor list pick a reasonable one.""" - for flavor in flavors: - if flavor.name == 'm1.tiny': - return flavor - - for flavor in flavors: - if flavor.name == 'm1.small': - return flavor - - -def pick_image(images): - for image in images: - if image.name.startswith('cirros') and image.name.endswith('-uec'): - return image - - -def volume_id_from_cli_create(output): - """Scrape the volume id out of the 'volume create' command - - The cli for Nova automatically routes requests to the volumes - service end point. However the nova api low level commands don't - redirect to the correct service endpoint, so for volumes commands - (even setup ones) we use the cli for magic routing. - - This function lets us get the id out of the prettytable that's - dumped on the cli during create. - - """ - for line in output.split("\n"): - fields = line.split() - if len(fields) > 4: - if fields[1] == "id": - return fields[3] - - -def volume_at_status(output, volume_id, status): - for line in output.split("\n"): - fields = line.split() - if len(fields) > 4: - if fields[1] == volume_id: - return fields[3] == status - raise Exception("Volume %s did not reach status '%s' in output: %s" - % (volume_id, status, output)) - - -class TestInstanceCLI(base.ClientTestBase): - def setUp(self): - super(TestInstanceCLI, self).setUp() - # TODO(sdague): while we collect this information in - # tempest-lib, we do it in a way that's not available for top - # level tests. Long term this probably needs to be in the base - # class. - user = os.environ['OS_USERNAME'] - passwd = os.environ['OS_PASSWORD'] - tenant = os.environ['OS_TENANT_NAME'] - auth_url = os.environ['OS_AUTH_URL'] - - # TODO(sdague): we made a lot of fun of the glanceclient team - # for version as int in first parameter. I guess we know where - # they copied it from. - self.client = novaclient.client.Client( - 2, user, passwd, tenant, - auth_url=auth_url) - - # pick some reasonable flavor / image combo - self.flavor = pick_flavor(self.client.flavors.list()) - self.image = pick_image(self.client.images.list()) - - def test_attach_volume(self): - """Test we can attach a volume via the cli. - - This test was added after bug 1423695. That bug exposed - inconsistencies in how to talk to API services from the CLI - vs. API level. The volumes api calls that were designed to - populate the completion cache were incorrectly routed to the - Nova endpoint. Novaclient volumes support actually talks to - Cinder endpoint directly. - - This would case volume-attach to return a bad error code, - however it does this *after* the attach command is correctly - dispatched. So the volume-attach still works, but the user is - presented a 404 error. - - This test ensures we can do a through path test of: boot, - create volume, attach volume, detach volume, delete volume, - destroy. - - """ - # TODO(sdague): better random name - name = str(uuid.uuid4()) - - # Boot via the cli, as we're primarily testing the cli in this test - self.nova('boot', params="--flavor %s --image %s %s --poll" % - (self.flavor.name, self.image.name, name)) - - # Be nice about cleaning up, however, use the API for this to avoid - # parsing text. - servers = self.client.servers.list(search_opts={"name": name}) - # the name is a random uuid, there better only be one - self.assertEqual(1, len(servers), servers) - server = servers[0] - self.addCleanup(server.delete) - - # create a volume for attachment. We use the CLI because it - # magic routes to cinder, however the low level API does not. - volume_id = volume_id_from_cli_create( - self.nova('volume-create', params="1")) - self.addCleanup(self.nova, 'volume-delete', params=volume_id) - - # allow volume to become available - for x in xrange(60): - volumes = self.nova('volume-list') - if volume_at_status(volumes, volume_id, 'available'): - break - time.sleep(1) - else: - self.fail("Volume %s not available after 60s" % volume_id) - - # attach the volume - self.nova('volume-attach', params="%s %s" % (name, volume_id)) - - # volume needs to transition to 'in-use' to be attached - for x in xrange(60): - volumes = self.nova('volume-list') - if volume_at_status(volumes, volume_id, 'in-use'): - break - time.sleep(1) - else: - self.fail("Volume %s not attached after 60s" % volume_id) - - # clean up on success - self.nova('volume-detach', params="%s %s" % (name, volume_id)) diff --git a/awx/lib/site-packages/novaclient/tests/functional/test_readonly_nova.py b/awx/lib/site-packages/novaclient/tests/functional/test_readonly_nova.py deleted file mode 100644 index 2ea4ec986b..0000000000 --- a/awx/lib/site-packages/novaclient/tests/functional/test_readonly_nova.py +++ /dev/null @@ -1,171 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from tempest_lib import decorators -from tempest_lib import exceptions - -from novaclient.tests.functional import base - - -class SimpleReadOnlyNovaClientTest(base.ClientTestBase): - - """ - read only functional python-novaclient tests. - - This only exercises client commands that are read only. - """ - - def test_admin_fake_action(self): - self.assertRaises(exceptions.CommandFailed, - self.nova, - 'this-does-nova-exist') - - # NOTE(jogo): Commands in order listed in 'nova help' - - def test_admin_absolute_limites(self): - self.nova('absolute-limits') - self.nova('absolute-limits', params='--reserved') - - def test_admin_aggregate_list(self): - self.nova('aggregate-list') - - def test_admin_availability_zone_list(self): - self.assertIn("internal", self.nova('availability-zone-list')) - - def test_admin_cloudpipe_list(self): - self.nova('cloudpipe-list') - - def test_admin_credentials(self): - self.nova('credentials') - - # "Neutron does not provide this feature" - def test_admin_dns_domains(self): - self.nova('dns-domains') - - @decorators.skip_because(bug="1157349") - def test_admin_dns_list(self): - self.nova('dns-list') - - def test_admin_endpoints(self): - self.nova('endpoints') - - def test_admin_flavor_acces_list(self): - self.assertRaises(exceptions.CommandFailed, - self.nova, - 'flavor-access-list') - # Failed to get access list for public flavor type - self.assertRaises(exceptions.CommandFailed, - self.nova, - 'flavor-access-list', - params='--flavor m1.tiny') - - def test_admin_flavor_list(self): - self.assertIn("Memory_MB", self.nova('flavor-list')) - - def test_admin_floating_ip_bulk_list(self): - self.nova('floating-ip-bulk-list') - - def test_admin_floating_ip_list(self): - self.nova('floating-ip-list') - - def test_admin_floating_ip_pool_list(self): - self.nova('floating-ip-pool-list') - - def test_admin_host_list(self): - self.nova('host-list') - - def test_admin_hypervisor_list(self): - self.nova('hypervisor-list') - - def test_admin_image_list(self): - self.nova('image-list') - - @decorators.skip_because(bug="1157349") - def test_admin_interface_list(self): - self.nova('interface-list') - - def test_admin_keypair_list(self): - self.nova('keypair-list') - - def test_admin_list(self): - self.nova('list') - self.nova('list', params='--all-tenants 1') - self.nova('list', params='--all-tenants 0') - self.assertRaises(exceptions.CommandFailed, - self.nova, - 'list', - params='--all-tenants bad') - - def test_admin_network_list(self): - self.nova('network-list') - - def test_admin_rate_limits(self): - self.nova('rate-limits') - - def test_admin_secgroup_list(self): - self.nova('secgroup-list') - - @decorators.skip_because(bug="1157349") - def test_admin_secgroup_list_rules(self): - self.nova('secgroup-list-rules') - - def test_admin_server_group_list(self): - self.nova('server-group-list') - - def test_admin_servce_list(self): - self.nova('service-list') - - def test_admin_usage(self): - self.nova('usage') - - def test_admin_usage_list(self): - self.nova('usage-list') - - def test_admin_volume_list(self): - self.nova('volume-list') - - def test_admin_volume_snapshot_list(self): - self.nova('volume-snapshot-list') - - def test_admin_volume_type_list(self): - self.nova('volume-type-list') - - def test_admin_help(self): - self.nova('help') - - def test_admin_list_extensions(self): - self.nova('list-extensions') - - def test_admin_net_list(self): - self.nova('net-list') - - def test_agent_list(self): - self.nova('agent-list') - self.nova('agent-list', flags='--debug') - - def test_migration_list(self): - self.nova('migration-list') - self.nova('migration-list', flags='--debug') - - # Optional arguments: - - def test_admin_version(self): - self.nova('', flags='--version') - - def test_admin_debug_list(self): - self.nova('list', flags='--debug') - - def test_admin_timeout(self): - self.nova('list', flags='--timeout %d' % 10) - - def test_admin_timing(self): - self.nova('list', flags='--timing') diff --git a/awx/lib/site-packages/novaclient/tests/functional/test_volumes_api.py b/awx/lib/site-packages/novaclient/tests/functional/test_volumes_api.py deleted file mode 100644 index e427c2e212..0000000000 --- a/awx/lib/site-packages/novaclient/tests/functional/test_volumes_api.py +++ /dev/null @@ -1,111 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import time -import uuid - -import six.moves - -from novaclient import client -from novaclient import exceptions -from novaclient.tests.functional import base - - -def wait_for_delete(test, name, thing, get_func): - thing.delete() - for x in six.moves.range(60): - try: - thing = get_func(thing.id) - except exceptions.NotFound: - break - time.sleep(1) - else: - test.fail('%s %s still not deleted after 60s' % (name, thing.id)) - - -class TestVolumesAPI(base.ClientTestBase): - - def setUp(self): - super(TestVolumesAPI, self).setUp() - user = os.environ['OS_USERNAME'] - passwd = os.environ['OS_PASSWORD'] - tenant = os.environ['OS_TENANT_NAME'] - auth_url = os.environ['OS_AUTH_URL'] - - self.client = client.Client(2, user, passwd, tenant, auth_url=auth_url) - - def test_volumes_snapshots_types_create_get_list_delete(self): - # Create a volume - volume = self.client.volumes.create(1) - - # Make sure we can still list servers after using the volume endpoint - self.client.servers.list() - - # This cleanup tests volume delete - self.addCleanup(volume.delete) - - # Wait for the volume to become available - for x in six.moves.range(60): - volume = self.client.volumes.get(volume.id) - if volume.status == 'available': - break - elif volume.status == 'error': - self.fail('Volume %s is in error state' % volume.id) - time.sleep(1) - else: - self.fail('Volume %s not available after 60s' % volume.id) - - # List all volumes - self.client.volumes.list() - - # Create a volume snapshot - snapshot = self.client.volume_snapshots.create(volume.id) - - # This cleanup tests volume snapshot delete. The volume - # can't be deleted until the dependent snapshot is gone - self.addCleanup(wait_for_delete, self, 'Snapshot', snapshot, - self.client.volume_snapshots.get) - - # Wait for the snapshot to become available - for x in six.moves.range(60): - snapshot = self.client.volume_snapshots.get(snapshot.id) - if snapshot.status == 'available': - break - elif snapshot.status == 'error': - self.fail('Snapshot %s is in error state' % snapshot.id) - time.sleep(1) - else: - self.fail('Snapshot %s not available after 60s' % snapshot.id) - - # List snapshots - self.client.volume_snapshots.list() - - # List servers again to make sure things are still good - self.client.servers.list() - - # Create a volume type - # TODO(melwitt): Use a better random name - name = str(uuid.uuid4()) - volume_type = self.client.volume_types.create(name) - - # This cleanup tests volume type delete - self.addCleanup(self.client.volume_types.delete, volume_type.id) - - # Get the volume type - volume_type = self.client.volume_types.get(volume_type.id) - - # List all volume types - self.client.volume_types.list() - - # One more servers list - self.client.servers.list() diff --git a/awx/lib/site-packages/novaclient/tests/idfake.pem b/awx/lib/site-packages/novaclient/tests/idfake.pem deleted file mode 100644 index f7b4466419..0000000000 --- a/awx/lib/site-packages/novaclient/tests/idfake.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA9QstF/7prDY7a9La7GS9TpMX+MWWXQgK6pHRLakDFp1WX1Q3 -Vly7rWitaZUGirUPMm181oJXBwkKlAxFD7hKjyHYaSswNszPYIAsVkc1+AO5epXz -g9kUBNtfg44Pg72UecwLrZ8JpmNZpJlKQOx6vF+yi7JmHrrIf6il/grIGUPzoT2L -yReimpyPoBrGtXhJYaCJ/XbKg1idRZiQdmwh1F/OmZWn9p0wunnsv08a0+qIywuw -WhG9/Zy9fjnEByfusS6gI0GIxDRL4RWzOqphd3PZzunwIBgEKFhgiki9+2DgcRVO -9I5wnDvfwQREJRZWh1uJa5ZTcfPa1EzZryVeOQIDAQABAoIBABxO3Te/cBk/7p9n -LXlPrfrszUEk+ljm+/PbQpIGy1+Kb5b1sKrebaP7ysS+vZG6lvXZZimVxx398mXm -APhu7tYYL9r+bUR3ZqGcTQLumRJ8w6mgtxANPN3Oxfr5p1stxIBJjTPSgpfhNFLq -joRvjUJDv+mZg2ibZVwyDHMLpdAdKp+3XMdyTLZcH9esqwii+natix7rHd1RuF85 -L1dfpxjkItwhgHsfdYS++5X3fRByFOhQ+Nhabh/kPQbQMcteRn1bN6zeCWBSglNb -Ka/ZrXb6ApRUc22Ji62mNO2ZPPekLJeCHk2h2E7ezYX+sGDNvvd/jHVDJJ20FjD1 -Z9KXuK0CgYEA/2vniy9yWd925QQtWbmrxgy6yj89feMH/LTv4qP298rGZ2nqxsyd -9pdBdb4NMsi4HmV5PG1hp3VRNBHl53DNh5eqzT8WEXnIF+sbrIU3KzrCVAx1kZTl -+OWKA6aVUsvvO3y85SOvInnsV+IsOGmU4/WBSjYoe39Bo7mq/YuZB9MCgYEA9ZlB -KBm6PjFdHQGNgedXahWzRcwC+ALCYqequPYqJolNzhrK4Uc2sWPSGdnldcHZ4XCQ -wbfCxUSwrMpA1oyuIQ0U4aowmOw5DjIueBWI8XBYEVRBlwvJwbXpBZ/DspGzTUDx -MBrrEwEaMadQvxhRnAzhp0rQAepatcz6Fgb1JkMCgYBMwDLiew5kfSav6JJsDMPW -DksurNQgeNEUmZYfx19V1EPMHWKj/CZXS9oqtEIpCXFyCNHmW4PlmvYcrGgmJJpN -7UAwzo0mES8UKNy2+Yy7W7u7H8dQSKrWILtZH3xtVcR8Xp4wSIm+1V40hkz9YpSP -71y7XQzLF1E1DnyYFZOVawKBgAFrmHfd5jjT2kD/sEzPBK9lXrsJmf7LLUqaw578 -NXQxmRSXDRNOcR+Hf0CNBQmwTE1EdGHaaTLw2cC2Drfu6lbgl31SmaNYwl+1pJUn -MrqKtseq4BI6jDkljypsKRqQQyQwOvTXQwLCH9+nowzn3Bj17hwkj51jOJESlWOp -OKO3AoGBALm+jjqyqX7gSnqK3FAumB8mlhv3yI1Wr1ctwe18mKfKbz17HxXRu9pF -K/6e7WMCA1p+jhoE8gj1h2WBcH0nV2qt8Ye8gJBbCi4dhI08o4AfrIV47oZx1RlO -qYcA1U9lyaODY5SL8+6PHOy5J/aYtuA+wvfEnWiCIdKQrhWetcn3 ------END RSA PRIVATE KEY----- diff --git a/awx/lib/site-packages/novaclient/tests/test_auth_plugins.py b/awx/lib/site-packages/novaclient/tests/test_auth_plugins.py deleted file mode 100644 index ffc591c7f7..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_auth_plugins.py +++ /dev/null @@ -1,328 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -from keystoneclient import fixture -import mock -import pkg_resources -import requests - -try: - import json -except ImportError: - import simplejson as json - -from novaclient import auth_plugin -from novaclient import exceptions -from novaclient.tests import utils -from novaclient.v1_1 import client - - -def mock_http_request(resp=None): - """Mock an HTTP Request.""" - if not resp: - resp = fixture.V2Token() - resp.set_scope() - s = resp.add_service('compute') - s.add_endpoint("http://localhost:8774/v1.1", region='RegionOne') - - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - return mock.Mock(return_value=(auth_response)) - - -def requested_headers(cs): - """Return requested passed headers.""" - return { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - - -class DeprecatedAuthPluginTest(utils.TestCase): - def test_auth_system_success(self): - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.authenticate - - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - def mock_iter_entry_points(_type, name): - if _type == 'openstack.client.authenticate': - return [MockEntrypoint("fake", "fake", ["fake"])] - else: - return [] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - plugin = auth_plugin.DeprecatedAuthPlugin("fake") - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, auth_system="fake", - auth_plugin=plugin) - cs.client.authenticate() - - headers = requested_headers(cs) - token_url = cs.client.auth_url + "/tokens" - - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data='{"fake": "me"}', - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - test_auth_call() - - def test_auth_system_not_exists(self): - def mock_iter_entry_points(_t, name=None): - return [pkg_resources.EntryPoint("fake", "fake", ["fake"])] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - auth_plugin.discover_auth_systems() - plugin = auth_plugin.DeprecatedAuthPlugin("notexists") - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, auth_system="notexists", - auth_plugin=plugin) - self.assertRaises(exceptions.AuthSystemNotFound, - cs.client.authenticate) - - test_auth_call() - - def test_auth_system_defining_auth_url(self): - class MockAuthUrlEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.auth_url - - def auth_url(self): - return "http://faked/v2.0" - - class MockAuthenticateEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.authenticate - - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - def mock_iter_entry_points(_type, name): - if _type == 'openstack.client.auth_url': - return [MockAuthUrlEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["auth_url"])] - elif _type == 'openstack.client.authenticate': - return [MockAuthenticateEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["authenticate"])] - else: - return [] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl") - cs = client.Client("username", "password", "project_id", - auth_system="fakewithauthurl", - auth_plugin=plugin) - cs.client.authenticate() - self.assertEqual("http://faked/v2.0", cs.client.auth_url) - - test_auth_call() - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_client_raises_exc_without_auth_url(self, mock_iter_entry_points): - class MockAuthUrlEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.auth_url - - def auth_url(self): - return None - - mock_iter_entry_points.side_effect = lambda _t, name: [ - MockAuthUrlEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["auth_url"])] - - plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl") - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fakewithauthurl", auth_plugin=plugin) - - -class AuthPluginTest(utils.TestCase): - @mock.patch.object(requests, "request") - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_auth_system_success(self, mock_iter_entry_points, mock_request): - """Test that we can authenticate using the auth system.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - mock_request.side_effect = mock_http_request() - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, auth_system="fake", - auth_plugin=plugin) - cs.client.authenticate() - - headers = requested_headers(cs) - token_url = cs.client.auth_url + "/tokens" - - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data='{"fake": "me"}', - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_discover_auth_system_options(self, mock_iter_entry_points): - """Test that we can load the auth system options.""" - class FakePlugin(auth_plugin.BaseAuthPlugin): - @staticmethod - def add_opts(parser): - parser.add_argument('--auth_system_opt', - default=False, - action='store_true', - help="Fake option") - return parser - - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - parser = argparse.ArgumentParser() - auth_plugin.discover_auth_systems() - auth_plugin.load_auth_system_opts(parser) - opts, args = parser.parse_known_args(['--auth_system_opt']) - - self.assertTrue(opts.auth_system_opt) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_parse_auth_system_options(self, mock_iter_entry_points): - """Test that we can parse the auth system options.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def __init__(self): - self.opts = {"fake_argument": True} - - def parse_opts(self, args): - return self.opts - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - plugin.parse_opts([]) - self.assertIn("fake_argument", plugin.opts) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_auth_system_defining_url(self, mock_iter_entry_points): - """Test the auth_system defining an url.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def get_auth_url(self): - return "http://faked/v2.0" - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - cs = client.Client("username", "password", "project_id", - auth_system="fakewithauthurl", - auth_plugin=plugin) - self.assertEqual("http://faked/v2.0", cs.client.auth_url) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_exception_if_no_authenticate(self, mock_iter_entry_points): - """Test that no authenticate raises a proper exception.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - pass - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fake", auth_plugin=plugin) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_exception_if_no_url(self, mock_iter_entry_points): - """Test that no auth_url at all raises exception.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - pass - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fake", auth_plugin=plugin) diff --git a/awx/lib/site-packages/novaclient/tests/test_base.py b/awx/lib/site-packages/novaclient/tests/test_base.py deleted file mode 100644 index fca5b72d41..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_base.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient import exceptions -from novaclient.tests import utils -from novaclient.tests.v1_1 import fakes -from novaclient.v1_1 import flavors - - -cs = fakes.FakeClient() - - -class BaseTest(utils.TestCase): - - def test_resource_repr(self): - r = base.Resource(None, dict(foo="bar", baz="spam")) - self.assertEqual("", repr(r)) - - def test_getid(self): - self.assertEqual(4, base.getid(4)) - - class TmpObject(object): - id = 4 - self.assertEqual(4, base.getid(TmpObject)) - - def test_resource_lazy_getattr(self): - f = flavors.Flavor(cs.flavors, {'id': 1}) - self.assertEqual('256 MB Server', f.name) - cs.assert_called('GET', '/flavors/1') - - # Missing stuff still fails after a second get - self.assertRaises(AttributeError, getattr, f, 'blahblah') - - def test_eq(self): - # Two resources of the same type with the same id: equal - r1 = base.Resource(None, {'id': 1, 'name': 'hi'}) - r2 = base.Resource(None, {'id': 1, 'name': 'hello'}) - self.assertEqual(r1, r2) - - # Two resoruces of different types: never equal - r1 = base.Resource(None, {'id': 1}) - r2 = flavors.Flavor(None, {'id': 1}) - self.assertNotEqual(r1, r2) - - # Two resources with no ID: equal if their info is equal - r1 = base.Resource(None, {'name': 'joe', 'age': 12}) - r2 = base.Resource(None, {'name': 'joe', 'age': 12}) - self.assertEqual(r1, r2) - - def test_findall_invalid_attribute(self): - # Make sure findall with an invalid attribute doesn't cause errors. - # The following should not raise an exception. - cs.flavors.findall(vegetable='carrot') - - # However, find() should raise an error - self.assertRaises(exceptions.NotFound, - cs.flavors.find, - vegetable='carrot') diff --git a/awx/lib/site-packages/novaclient/tests/test_client.py b/awx/lib/site-packages/novaclient/tests/test_client.py deleted file mode 100644 index f8bcaed80b..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_client.py +++ /dev/null @@ -1,420 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import json -import logging - -import fixtures -import mock -import requests - -import novaclient.client -import novaclient.extension -import novaclient.tests.fakes as fakes -from novaclient.tests import utils -import novaclient.v1_1.client -import novaclient.v3.client - - -class ClientConnectionPoolTest(utils.TestCase): - - @mock.patch("novaclient.client.adapters.HTTPAdapter") - def test_get(self, mock_http_adapter): - mock_http_adapter.side_effect = lambda: mock.Mock() - pool = novaclient.client._ClientConnectionPool() - self.assertEqual(pool.get("abc"), pool.get("abc")) - self.assertNotEqual(pool.get("abc"), pool.get("def")) - - -class ClientTest(utils.TestCase): - - def test_client_with_timeout(self): - instance = novaclient.client.HTTPClient(user='user', - password='password', - projectid='project', - timeout=2, - auth_url="http://www.blah.com") - self.assertEqual(2, instance.timeout) - mock_request = mock.Mock() - mock_request.return_value = requests.Response() - mock_request.return_value.status_code = 200 - mock_request.return_value.headers = { - 'x-server-management-url': 'blah.com', - 'x-auth-token': 'blah', - } - with mock.patch('requests.request', mock_request): - instance.authenticate() - requests.request.assert_called_with(mock.ANY, mock.ANY, - timeout=2, - headers=mock.ANY, - verify=mock.ANY) - - def test_client_reauth(self): - instance = novaclient.client.HTTPClient(user='user', - password='password', - projectid='project', - timeout=2, - auth_url="http://www.blah.com") - instance.auth_token = 'foobar' - instance.management_url = 'http://example.com' - instance.version = 'v2.0' - mock_request = mock.Mock() - mock_request.side_effect = novaclient.exceptions.Unauthorized(401) - with mock.patch('requests.request', mock_request): - try: - instance.get('/servers/detail') - except Exception: - pass - get_headers = {'X-Auth-Project-Id': 'project', - 'X-Auth-Token': 'foobar', - 'User-Agent': 'python-novaclient', - 'Accept': 'application/json'} - reauth_headers = {'Content-Type': 'application/json', - 'Accept': 'application/json', - 'User-Agent': 'python-novaclient'} - data = { - "auth": { - "tenantName": "project", - "passwordCredentials": { - "username": "user", - "password": "password" - } - } - } - - expected = [mock.call('GET', - 'http://example.com/servers/detail', - timeout=mock.ANY, - headers=get_headers, - verify=mock.ANY), - mock.call('POST', 'http://www.blah.com/tokens', - timeout=mock.ANY, - headers=reauth_headers, - allow_redirects=mock.ANY, - data=json.dumps(data), - verify=mock.ANY)] - self.assertEqual(expected, mock_request.call_args_list) - - @mock.patch.object(novaclient.client.HTTPClient, 'request', - return_value=(200, "{'versions':[]}")) - def _check_version_url(self, management_url, version_url, mock_request): - projectid = '25e469aa1848471b875e68cde6531bc5' - instance = novaclient.client.HTTPClient(user='user', - password='password', - projectid=projectid, - auth_url="http://www.blah.com") - instance.auth_token = 'foobar' - instance.management_url = management_url % projectid - instance.version = 'v2.0' - - # If passing None as the part of url, a client accesses the url which - # doesn't include "v2/" for getting API version info. - instance.get(None) - mock_request.assert_called_once_with(version_url, 'GET', - headers=mock.ANY) - mock_request.reset_mock() - - # Otherwise, a client accesses the url which includes "v2/". - instance.get('servers') - url = instance.management_url + 'servers' - mock_request.assert_called_once_with(url, 'GET', headers=mock.ANY) - - def test_client_version_url(self): - self._check_version_url('http://foo.com/v2/%s', 'http://foo.com/') - - def test_client_version_url_with_project_name(self): - self._check_version_url('http://foo.com/nova/v2/%s', - 'http://foo.com/nova/') - - def test_get_client_class_v3(self): - output = novaclient.client.get_client_class('3') - self.assertEqual(output, novaclient.v3.client.Client) - - def test_get_client_class_v2(self): - output = novaclient.client.get_client_class('2') - self.assertEqual(output, novaclient.v1_1.client.Client) - - def test_get_client_class_v2_int(self): - output = novaclient.client.get_client_class(2) - self.assertEqual(output, novaclient.v1_1.client.Client) - - def test_get_client_class_v1_1(self): - output = novaclient.client.get_client_class('1.1') - self.assertEqual(output, novaclient.v1_1.client.Client) - - def test_get_client_class_unknown(self): - self.assertRaises(novaclient.exceptions.UnsupportedVersion, - novaclient.client.get_client_class, '0') - - def test_client_with_os_cache_enabled(self): - cs = novaclient.v1_1.client.Client("user", "password", "project_id", - auth_url="foo/v2", os_cache=True) - self.assertEqual(True, cs.os_cache) - self.assertEqual(True, cs.client.os_cache) - - def test_client_with_os_cache_disabled(self): - cs = novaclient.v1_1.client.Client("user", "password", "project_id", - auth_url="foo/v2", os_cache=False) - self.assertEqual(False, cs.os_cache) - self.assertEqual(False, cs.client.os_cache) - - def test_client_with_no_cache_enabled(self): - cs = novaclient.v1_1.client.Client("user", "password", "project_id", - auth_url="foo/v2", no_cache=True) - self.assertEqual(False, cs.os_cache) - self.assertEqual(False, cs.client.os_cache) - - def test_client_with_no_cache_disabled(self): - cs = novaclient.v1_1.client.Client("user", "password", "project_id", - auth_url="foo/v2", no_cache=False) - self.assertEqual(True, cs.os_cache) - self.assertEqual(True, cs.client.os_cache) - - def test_client_set_management_url_v1_1(self): - cs = novaclient.v1_1.client.Client("user", "password", "project_id", - auth_url="foo/v2") - cs.set_management_url("blabla") - self.assertEqual("blabla", cs.client.management_url) - - def test_client_get_reset_timings_v1_1(self): - cs = novaclient.v1_1.client.Client("user", "password", "project_id", - auth_url="foo/v2") - self.assertEqual(0, len(cs.get_timings())) - cs.client.times.append("somevalue") - self.assertEqual(1, len(cs.get_timings())) - self.assertEqual("somevalue", cs.get_timings()[0]) - - cs.reset_timings() - self.assertEqual(0, len(cs.get_timings())) - - def test_client_set_management_url_v3(self): - cs = novaclient.v3.client.Client("user", "password", "project_id", - auth_url="foo/v2") - cs.set_management_url("blabla") - self.assertEqual("blabla", cs.client.management_url) - - def test_client_get_reset_timings_v3(self): - cs = novaclient.v3.client.Client("user", "password", "project_id", - auth_url="foo/v2") - self.assertEqual(0, len(cs.get_timings())) - cs.client.times.append("somevalue") - self.assertEqual(["somevalue"], cs.get_timings()) - - cs.reset_timings() - self.assertEqual(0, len(cs.get_timings())) - - def test_clent_extensions_v3(self): - fake_attribute_name1 = "FakeAttribute1" - fake_attribute_name2 = "FakeAttribute2" - extensions = [ - novaclient.extension.Extension(fake_attribute_name1, - fakes), - novaclient.extension.Extension(fake_attribute_name2, - utils), - ] - - cs = novaclient.v3.client.Client("user", "password", "project_id", - auth_url="foo/v2", - extensions=extensions) - self.assertIsInstance(getattr(cs, fake_attribute_name1, None), - fakes.FakeManager) - self.assertFalse(hasattr(cs, fake_attribute_name2)) - - @mock.patch.object(novaclient.client.HTTPClient, 'authenticate') - def test_authenticate_call_v3(self, mock_authenticate): - cs = novaclient.v3.client.Client("user", "password", "project_id", - auth_url="foo/v2") - cs.authenticate() - self.assertTrue(mock_authenticate.called) - - @mock.patch('novaclient.client.HTTPClient') - def test_contextmanager_v1_1(self, mock_http_client): - fake_client = mock.Mock() - mock_http_client.return_value = fake_client - with novaclient.v1_1.client.Client("user", "password", "project_id", - auth_url="foo/v2"): - pass - self.assertTrue(fake_client.open_session.called) - self.assertTrue(fake_client.close_session.called) - - @mock.patch('novaclient.client.HTTPClient') - def test_contextmanager_v3(self, mock_http_client): - fake_client = mock.Mock() - mock_http_client.return_value = fake_client - with novaclient.v3.client.Client("user", "password", "project_id", - auth_url="foo/v2"): - pass - self.assertTrue(fake_client.open_session.called) - self.assertTrue(fake_client.close_session.called) - - def test_get_password_simple(self): - cs = novaclient.client.HTTPClient("user", "password", "", "") - cs.password_func = mock.Mock() - self.assertEqual("password", cs._get_password()) - self.assertFalse(cs.password_func.called) - - def test_get_password_none(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - self.assertIsNone(cs._get_password()) - - def test_get_password_func(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - cs.password_func = mock.Mock(return_value="password") - self.assertEqual("password", cs._get_password()) - cs.password_func.assert_called_once_with() - - cs.password_func = mock.Mock() - self.assertEqual("password", cs._get_password()) - self.assertFalse(cs.password_func.called) - - def test_auth_url_rstrip_slash(self): - cs = novaclient.client.HTTPClient("user", "password", "project_id", - auth_url="foo/v2/") - self.assertEqual("foo/v2", cs.auth_url) - - def test_token_and_bypass_url(self): - cs = novaclient.client.HTTPClient(None, None, None, - auth_token="12345", - bypass_url="compute/v100/") - self.assertIsNone(cs.auth_url) - self.assertEqual("12345", cs.auth_token) - self.assertEqual("compute/v100", cs.bypass_url) - self.assertEqual("compute/v100", cs.management_url) - - @mock.patch("novaclient.client.requests.Session") - def test_session(self, mock_session): - fake_session = mock.Mock() - mock_session.return_value = fake_session - cs = novaclient.client.HTTPClient("user", None, "", "") - cs.open_session() - self.assertEqual(cs._session, fake_session) - cs.close_session() - self.assertIsNone(cs._session) - - def test_session_connection_pool(self): - cs = novaclient.client.HTTPClient("user", None, "", - "", connection_pool=True) - cs.open_session() - self.assertIsNone(cs._session) - cs.close_session() - self.assertIsNone(cs._session) - - def test_get_session(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - self.assertIsNone(cs._get_session("http://nooooooooo.com")) - - @mock.patch("novaclient.client.requests.Session") - def test_get_session_open_session(self, mock_session): - fake_session = mock.Mock() - mock_session.return_value = fake_session - cs = novaclient.client.HTTPClient("user", None, "", "") - cs.open_session() - self.assertEqual(fake_session, cs._get_session("http://example.com")) - - @mock.patch("novaclient.client.requests.Session") - @mock.patch("novaclient.client._ClientConnectionPool") - def test_get_session_connection_pool(self, mock_pool, mock_session): - service_url = "http://example.com" - - pool = mock.MagicMock() - pool.get.return_value = "http_adapter" - mock_pool.return_value = pool - cs = novaclient.client.HTTPClient("user", None, "", - "", connection_pool=True) - cs._current_url = "http://another.com" - - session = cs._get_session(service_url) - self.assertEqual(session, mock_session.return_value) - pool.get.assert_called_once_with(service_url) - mock_session().mount.assert_called_once_with(service_url, - 'http_adapter') - - def test_init_without_connection_pool(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - self.assertIsNone(cs._connection_pool) - - @mock.patch("novaclient.client._ClientConnectionPool") - def test_init_with_proper_connection_pool(self, mock_pool): - fake_pool = mock.Mock() - mock_pool.return_value = fake_pool - cs = novaclient.client.HTTPClient("user", None, "", - connection_pool=True) - self.assertEqual(cs._connection_pool, fake_pool) - - def test_log_req(self): - self.logger = self.useFixture( - fixtures.FakeLogger( - format="%(message)s", - level=logging.DEBUG, - nuke_handlers=True - ) - ) - cs = novaclient.client.HTTPClient("user", None, "", - connection_pool=True) - cs.http_log_debug = True - cs.http_log_req('GET', '/foo', {'headers': {}}) - cs.http_log_req('GET', '/foo', {'headers': - {'X-Auth-Token': 'totally_bogus'} - }) - cs.http_log_req('GET', '/foo', {'headers': - {'X-Foo': 'bar', - 'X-Auth-Token': 'totally_bogus'} - }) - cs.http_log_req('GET', '/foo', {'headers': {}, - 'data': '{"auth": {"passwordCredentials": ' - '{"password": "zhaoqin"}}}'}) - - output = self.logger.output.split('\n') - - self.assertIn("REQ: curl -i '/foo' -X GET", output) - self.assertIn( - "REQ: curl -i '/foo' -X GET -H " - '"X-Auth-Token: {SHA1}b42162b6ffdbd7c3c37b7c95b7ba9f51dda0236d"', - output) - self.assertIn( - "REQ: curl -i '/foo' -X GET -H " - '"X-Auth-Token: {SHA1}b42162b6ffdbd7c3c37b7c95b7ba9f51dda0236d"' - ' -H "X-Foo: bar"', - output) - self.assertIn( - "REQ: curl -i '/foo' -X GET -d " - '\'{"auth": {"passwordCredentials": {"password":' - ' "{SHA1}4fc49c6a671ce889078ff6b250f7066cf6d2ada2"}}}\'', - output) - - def test_log_resp(self): - self.logger = self.useFixture( - fixtures.FakeLogger( - format="%(message)s", - level=logging.DEBUG, - nuke_handlers=True - ) - ) - - cs = novaclient.client.HTTPClient("user", None, "", - connection_pool=True) - cs.http_log_debug = True - text = ('{"access": {"token": {"id": "zhaoqin"}}}') - resp = utils.TestResponse({'status_code': 200, 'headers': {}, - 'text': text}) - - cs.http_log_resp(resp) - output = self.logger.output.split('\n') - - self.assertIn('RESP: [200] {}', output) - self.assertIn('RESP BODY: {"access": {"token": {"id":' - ' "{SHA1}4fc49c6a671ce889078ff6b250f7066cf6d2ada2"}}}', - output) diff --git a/awx/lib/site-packages/novaclient/tests/test_discover.py b/awx/lib/site-packages/novaclient/tests/test_discover.py deleted file mode 100644 index a498824947..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_discover.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import imp -import inspect - -import mock -import pkg_resources - -import novaclient.shell -from novaclient.tests import utils - - -class DiscoverTest(utils.TestCase): - - def test_discover_via_entry_points(self): - - def mock_iter_entry_points(group): - if group == 'novaclient.extension': - fake_ep = mock.Mock() - fake_ep.name = 'foo' - fake_ep.module = imp.new_module('foo') - fake_ep.load.return_value = fake_ep.module - return [fake_ep] - - @mock.patch.object(pkg_resources, 'iter_entry_points', - mock_iter_entry_points) - def test(): - shell = novaclient.shell.OpenStackComputeShell() - for name, module in shell._discover_via_entry_points(): - self.assertEqual('foo', name) - self.assertTrue(inspect.ismodule(module)) - - test() - - def test_discover_extensions(self): - - def mock_discover_via_python_path(self): - yield 'foo', imp.new_module('foo') - - def mock_discover_via_contrib_path(self, version): - yield 'bar', imp.new_module('bar') - - def mock_discover_via_entry_points(self): - yield 'baz', imp.new_module('baz') - - @mock.patch.object(novaclient.shell.OpenStackComputeShell, - '_discover_via_python_path', - mock_discover_via_python_path) - @mock.patch.object(novaclient.shell.OpenStackComputeShell, - '_discover_via_contrib_path', - mock_discover_via_contrib_path) - @mock.patch.object(novaclient.shell.OpenStackComputeShell, - '_discover_via_entry_points', - mock_discover_via_entry_points) - def test(): - shell = novaclient.shell.OpenStackComputeShell() - extensions = shell._discover_extensions('1.1') - self.assertEqual(3, len(extensions)) - names = sorted(['foo', 'bar', 'baz']) - sorted_extensions = sorted(extensions, key=lambda ext: ext.name) - for i in range(len(names)): - ext = sorted_extensions[i] - name = names[i] - self.assertEqual(ext.name, name) - self.assertTrue(inspect.ismodule(ext.module)) - - test() diff --git a/awx/lib/site-packages/novaclient/tests/test_http.py b/awx/lib/site-packages/novaclient/tests/test_http.py deleted file mode 100644 index bd12ed827a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_http.py +++ /dev/null @@ -1,212 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import requests -import six - -from novaclient import client -from novaclient import exceptions -from novaclient.tests import utils - - -fake_response = utils.TestResponse({ - "status_code": 200, - "text": '{"hi": "there"}', -}) -mock_request = mock.Mock(return_value=(fake_response)) - -refused_response = utils.TestResponse({ - "status_code": 400, - "text": '[Errno 111] Connection refused', -}) -refused_mock_request = mock.Mock(return_value=(refused_response)) - -bad_req_response = utils.TestResponse({ - "status_code": 400, - "text": '', -}) -bad_req_mock_request = mock.Mock(return_value=(bad_req_response)) - -unknown_error_response = utils.TestResponse({ - "status_code": 503, - "text": '', -}) -unknown_error_mock_request = mock.Mock(return_value=unknown_error_response) - -retry_after_response = utils.TestResponse({ - "status_code": 413, - "text": '', - "headers": { - "retry-after": "5" - }, -}) -retry_after_mock_request = mock.Mock(return_value=retry_after_response) - -retry_after_no_headers_response = utils.TestResponse({ - "status_code": 413, - "text": '', -}) -retry_after_no_headers_mock_request = mock.Mock( - return_value=retry_after_no_headers_response) - -retry_after_non_supporting_response = utils.TestResponse({ - "status_code": 403, - "text": '', - "headers": { - "retry-after": "5" - }, -}) -retry_after_non_supporting_mock_request = mock.Mock( - return_value=retry_after_non_supporting_response) - - -def get_client(): - cl = client.HTTPClient("username", "password", - "project_id", - utils.AUTH_URL_V2) - return cl - - -def get_authed_client(): - cl = get_client() - cl.management_url = "http://example.com" - cl.auth_token = "token" - return cl - - -class ClientTest(utils.TestCase): - - def test_get(self): - cl = get_authed_client() - - @mock.patch.object(requests, "request", mock_request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - headers = {"X-Auth-Token": "token", - "X-Auth-Project-Id": "project_id", - "User-Agent": cl.USER_AGENT, - 'Accept': 'application/json', - } - mock_request.assert_called_with( - "GET", - "http://example.com/hi", - headers=headers, - **self.TEST_REQUEST_BASE) - # Automatic JSON parsing - self.assertEqual({"hi": "there"}, body) - - test_get_call() - - def test_post(self): - cl = get_authed_client() - - @mock.patch.object(requests, "request", mock_request) - def test_post_call(): - cl.post("/hi", body=[1, 2, 3]) - headers = { - "X-Auth-Token": "token", - "X-Auth-Project-Id": "project_id", - "Content-Type": "application/json", - 'Accept': 'application/json', - "User-Agent": cl.USER_AGENT - } - mock_request.assert_called_with( - "POST", - "http://example.com/hi", - headers=headers, - data='[1, 2, 3]', - **self.TEST_REQUEST_BASE) - - test_post_call() - - def test_auth_failure(self): - cl = get_client() - - # response must not have x-server-management-url header - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.AuthorizationFailure, cl.authenticate) - - test_auth_call() - - def test_connection_refused(self): - cl = get_client() - - @mock.patch.object(requests, "request", refused_mock_request) - def test_refused_call(): - self.assertRaises(exceptions.ConnectionRefused, cl.get, "/hi") - - test_refused_call() - - def test_bad_request(self): - cl = get_client() - - @mock.patch.object(requests, "request", bad_req_mock_request) - def test_refused_call(): - self.assertRaises(exceptions.BadRequest, cl.get, "/hi") - - test_refused_call() - - def test_client_logger(self): - cl1 = client.HTTPClient("username", "password", "project_id", - "auth_test", http_log_debug=True) - self.assertEqual(1, len(cl1._logger.handlers)) - - cl2 = client.HTTPClient("username", "password", "project_id", - "auth_test", http_log_debug=True) - self.assertEqual(1, len(cl2._logger.handlers)) - - @mock.patch.object(requests, 'request', unknown_error_mock_request) - def test_unknown_server_error(self): - cl = get_client() - # This would be cleaner with the context manager version of - # assertRaises or assertRaisesRegexp, but both only appeared in - # Python 2.7 and testtools doesn't match that implementation yet - try: - cl.get('/hi') - except exceptions.ClientException as exc: - self.assertIn('Unknown Error', six.text_type(exc)) - else: - self.fail('Expected exceptions.ClientException') - - @mock.patch.object(requests, "request", retry_after_mock_request) - def test_retry_after_request(self): - cl = get_client() - - try: - cl.get("/hi") - except exceptions.OverLimit as exc: - self.assertEqual(5, exc.retry_after) - else: - self.fail('Expected exceptions.OverLimit') - - @mock.patch.object(requests, "request", - retry_after_no_headers_mock_request) - def test_retry_after_request_no_headers(self): - cl = get_client() - - try: - cl.get("/hi") - except exceptions.OverLimit as exc: - self.assertEqual(0, exc.retry_after) - else: - self.fail('Expected exceptions.OverLimit') - - @mock.patch.object(requests, "request", - retry_after_non_supporting_mock_request) - def test_retry_after_request_non_supporting_exc(self): - cl = get_client() - - self.assertRaises(exceptions.Forbidden, cl.get, "/hi") diff --git a/awx/lib/site-packages/novaclient/tests/test_service_catalog.py b/awx/lib/site-packages/novaclient/tests/test_service_catalog.py deleted file mode 100644 index 6f6ff4f466..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_service_catalog.py +++ /dev/null @@ -1,73 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import fixture - -from novaclient import exceptions -from novaclient import service_catalog -from novaclient.tests import utils - - -SERVICE_CATALOG = fixture.V2Token() -SERVICE_CATALOG.set_scope() - -_s = SERVICE_CATALOG.add_service('compute') -_e = _s.add_endpoint("https://compute1.host/v1/1") -_e["tenantId"] = "1" -_e["versionId"] = "1.0" -_e = _s.add_endpoint("https://compute1.host/v1.1/2", region="North") -_e["tenantId"] = "2" -_e["versionId"] = "1.1" -_e = _s.add_endpoint("https://compute1.host/v2/1", region="North") -_e["tenantId"] = "1" -_e["versionId"] = "2" - -_s = SERVICE_CATALOG.add_service('volume') -_e = _s.add_endpoint("https://volume1.host/v1/1", region="South") -_e["tenantId"] = "1" -_e = _s.add_endpoint("https://volume1.host/v1.1/2", region="South") -_e["tenantId"] = "2" - - -class ServiceCatalogTest(utils.TestCase): - def test_building_a_service_catalog(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - service_type='compute') - self.assertEqual("https://compute1.host/v2/1", - sc.url_for('tenantId', '1', service_type='compute')) - self.assertEqual("https://compute1.host/v1.1/2", - sc.url_for('tenantId', '2', service_type='compute')) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - "region", "South", service_type='compute') - - def test_building_a_service_catalog_insensitive_case(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - # Matching south (and catalog has South). - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - 'region', 'south', service_type='volume') - - def test_alternate_service_type(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - service_type='volume') - self.assertEqual("https://volume1.host/v1/1", - sc.url_for('tenantId', '1', service_type='volume')) - self.assertEqual("https://volume1.host/v1.1/2", - sc.url_for('tenantId', '2', service_type='volume')) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - "region", "North", service_type='volume') diff --git a/awx/lib/site-packages/novaclient/tests/test_shell.py b/awx/lib/site-packages/novaclient/tests/test_shell.py deleted file mode 100644 index 240965d79e..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_shell.py +++ /dev/null @@ -1,274 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import distutils.version as dist_version -import re -import sys - -import fixtures -import mock -import prettytable -import six -from testtools import matchers - -import novaclient.client -from novaclient import exceptions -import novaclient.shell -from novaclient.tests import utils - -FAKE_ENV = {'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': 'http://no.where'} - -FAKE_ENV2 = {'OS_USER_ID': 'user_id', - 'OS_PASSWORD': 'password', - 'OS_TENANT_ID': 'tenant_id', - 'OS_AUTH_URL': 'http://no.where'} - - -class ShellTest(utils.TestCase): - - def make_env(self, exclude=None, fake_env=FAKE_ENV): - env = dict((k, v) for k, v in fake_env.items() if k != exclude) - self.useFixture(fixtures.MonkeyPatch('os.environ', env)) - - def setUp(self): - super(ShellTest, self).setUp() - self.useFixture(fixtures.MonkeyPatch( - 'novaclient.client.get_client_class', - mock.MagicMock)) - self.nc_util = mock.patch( - 'novaclient.openstack.common.cliutils.isunauthenticated').start() - self.nc_util.return_value = False - - def shell(self, argstr, exitcodes=(0,)): - orig = sys.stdout - orig_stderr = sys.stderr - try: - sys.stdout = six.StringIO() - sys.stderr = six.StringIO() - _shell = novaclient.shell.OpenStackComputeShell() - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertIn(exc_value.code, exitcodes) - finally: - stdout = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - stderr = sys.stderr.getvalue() - sys.stderr.close() - sys.stderr = orig_stderr - return (stdout, stderr) - - def test_help_unknown_command(self): - self.assertRaises(exceptions.CommandError, self.shell, 'help foofoo') - - def test_invalid_timeout(self): - for f in [0, -1, -10]: - cmd_text = '--timeout %s' % (f) - stdout, stderr = self.shell(cmd_text, exitcodes=[0, 2]) - required = [ - 'argument --timeout: %s must be greater than 0' % (f), - ] - for r in required: - self.assertIn(r, stderr) - - def test_help(self): - required = [ - '.*?^usage: ', - '.*?^\s+root-password\s+Change the root password', - '.*?^See "nova help COMMAND" for help on a specific command', - ] - stdout, stderr = self.shell('help') - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_help_on_subcommand(self): - required = [ - '.*?^usage: nova root-password', - '.*?^Change the root password', - '.*?^Positional arguments:', - ] - stdout, stderr = self.shell('help root-password') - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_help_no_options(self): - required = [ - '.*?^usage: ', - '.*?^\s+root-password\s+Change the root password', - '.*?^See "nova help COMMAND" for help on a specific command', - ] - stdout, stderr = self.shell('') - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_bash_completion(self): - stdout, stderr = self.shell('bash-completion') - # just check we have some output - required = [ - '.*--matching', - '.*--wrap', - '.*help', - '.*secgroup-delete-rule', - '.*--priority'] - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_no_username(self): - required = ('You must provide a username or user id' - ' via --os-username, --os-user-id,' - ' env[OS_USERNAME] or env[OS_USER_ID]') - self.make_env(exclude='OS_USERNAME') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args[0]) - else: - self.fail('CommandError not raised') - - def test_no_user_id(self): - required = ('You must provide a username or user id' - ' via --os-username, --os-user-id,' - ' env[OS_USERNAME] or env[OS_USER_ID]') - self.make_env(exclude='OS_USER_ID', fake_env=FAKE_ENV2) - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args[0]) - else: - self.fail('CommandError not raised') - - def test_no_tenant_name(self): - required = ('You must provide a tenant name or tenant id' - ' via --os-tenant-name, --os-tenant-id,' - ' env[OS_TENANT_NAME] or env[OS_TENANT_ID]') - self.make_env(exclude='OS_TENANT_NAME') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args[0]) - else: - self.fail('CommandError not raised') - - def test_no_tenant_id(self): - required = ('You must provide a tenant name or tenant id' - ' via --os-tenant-name, --os-tenant-id,' - ' env[OS_TENANT_NAME] or env[OS_TENANT_ID]',) - self.make_env(exclude='OS_TENANT_ID', fake_env=FAKE_ENV2) - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args) - else: - self.fail('CommandError not raised') - - def test_no_auth_url(self): - required = ('You must provide an auth url' - ' via either --os-auth-url or env[OS_AUTH_URL] or' - ' specify an auth_system which defines a default url' - ' with --os-auth-system or env[OS_AUTH_SYSTEM]',) - self.make_env(exclude='OS_AUTH_URL') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args) - else: - self.fail('CommandError not raised') - - @mock.patch('sys.stdin', side_effect=mock.MagicMock) - @mock.patch('getpass.getpass', return_value='password') - def test_password(self, mock_getpass, mock_stdin): - mock_stdin.encoding = "utf-8" - - # default output of empty tables differs depending between prettytable - # versions - if (hasattr(prettytable, '__version__') and - dist_version.StrictVersion(prettytable.__version__) < - dist_version.StrictVersion('0.7.2')): - ex = '\n' - else: - ex = ( - '+----+------+--------+------------+-------------+----------+\n' - '| ID | Name | Status | Task State | Power State | Networks |\n' - '+----+------+--------+------------+-------------+----------+\n' - '+----+------+--------+------------+-------------+----------+\n' - ) - self.make_env(exclude='OS_PASSWORD') - stdout, stderr = self.shell('list') - self.assertEqual((stdout + stderr), ex) - - @mock.patch('sys.stdin', side_effect=mock.MagicMock) - @mock.patch('getpass.getpass', side_effect=EOFError) - def test_no_password(self, mock_getpass, mock_stdin): - required = ('Expecting a password provided' - ' via either --os-password, env[OS_PASSWORD],' - ' or prompted response',) - self.make_env(exclude='OS_PASSWORD') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args) - else: - self.fail('CommandError not raised') - - def _test_service_type(self, version, service_type, mock_client): - if version is None: - cmd = 'list' - else: - cmd = ('--service_type %s --os-compute-api-version %s list' % - (service_type, version)) - self.make_env() - self.shell(cmd) - _, client_kwargs = mock_client.call_args_list[0] - self.assertEqual(service_type, client_kwargs['service_type']) - - @mock.patch('novaclient.client.Client') - def test_default_service_type(self, mock_client): - self._test_service_type(None, 'compute', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v1_1_service_type(self, mock_client): - self._test_service_type('1.1', 'compute', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v2_service_type(self, mock_client): - self._test_service_type('2', 'compute', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v3_service_type(self, mock_client): - self._test_service_type('3', 'computev3', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v_unknown_service_type(self, mock_client): - self._test_service_type('unknown', 'compute', mock_client) - - @mock.patch('sys.argv', ['nova']) - @mock.patch('sys.stdout', six.StringIO()) - @mock.patch('sys.stderr', six.StringIO()) - def test_main_noargs(self): - # Ensure that main works with no command-line arguments - try: - novaclient.shell.main() - except SystemExit: - self.fail('Unexpected SystemExit') - - # We expect the normal usage as a result - self.assertIn('Command-line interface to the OpenStack Nova API', - sys.stdout.getvalue()) diff --git a/awx/lib/site-packages/novaclient/tests/test_utils.py b/awx/lib/site-packages/novaclient/tests/test_utils.py deleted file mode 100644 index 69e5d61888..0000000000 --- a/awx/lib/site-packages/novaclient/tests/test_utils.py +++ /dev/null @@ -1,323 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -import mock -import six - -from novaclient import base -from novaclient import exceptions -from novaclient.tests import utils as test_utils -from novaclient import utils - -UUID = '8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0' - - -class FakeResource(object): - NAME_ATTR = 'name' - - def __init__(self, _id, properties): - self.id = _id - try: - self.name = properties['name'] - except KeyError: - pass - - -class FakeManager(base.ManagerWithFind): - - resource_class = FakeResource - - resources = [ - FakeResource('1234', {'name': 'entity_one'}), - FakeResource(UUID, {'name': 'entity_two'}), - FakeResource('5678', {'name': '9876'}), - FakeResource('01234', {'name': 'entity_three'}) - ] - - is_alphanum_id_allowed = None - - def __init__(self, alphanum_id_allowed=False): - self.is_alphanum_id_allowed = alphanum_id_allowed - - def get(self, resource_id): - for resource in self.resources: - if resource.id == str(resource_id): - return resource - raise exceptions.NotFound(resource_id) - - def list(self): - return self.resources - - -class FakeDisplayResource(object): - NAME_ATTR = 'display_name' - - def __init__(self, _id, properties): - self.id = _id - try: - self.display_name = properties['display_name'] - except KeyError: - pass - - -class FakeDisplayManager(FakeManager): - - resource_class = FakeDisplayResource - - resources = [ - FakeDisplayResource('4242', {'display_name': 'entity_three'}), - ] - - -class FindResourceTestCase(test_utils.TestCase): - - def setUp(self): - super(FindResourceTestCase, self).setUp() - self.manager = FakeManager(None) - - def test_find_none(self): - """Test a few non-valid inputs.""" - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - 'asdf') - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - None) - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - {}) - - def test_find_by_integer_id(self): - output = utils.find_resource(self.manager, 1234) - self.assertEqual(output, self.manager.get('1234')) - - def test_find_by_str_id(self): - output = utils.find_resource(self.manager, '1234') - self.assertEqual(output, self.manager.get('1234')) - - def test_find_by_uuid(self): - output = utils.find_resource(self.manager, UUID) - self.assertEqual(output, self.manager.get(UUID)) - - def test_find_by_str_name(self): - output = utils.find_resource(self.manager, 'entity_one') - self.assertEqual(output, self.manager.get('1234')) - - def test_find_by_str_displayname(self): - display_manager = FakeDisplayManager(None) - output = utils.find_resource(display_manager, 'entity_three') - self.assertEqual(output, display_manager.get('4242')) - - def test_find_in_alphanum_allowd_manager_by_str_id_(self): - alphanum_manager = FakeManager(True) - output = utils.find_resource(alphanum_manager, '01234') - self.assertEqual(output, alphanum_manager.get('01234')) - - -class _FakeResult(object): - def __init__(self, name, value): - self.name = name - self.value = value - - -class PrintResultTestCase(test_utils.TestCase): - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict(self): - dict = {'key': 'value'} - utils.print_dict(dict) - self.assertEqual('+----------+-------+\n' - '| Property | Value |\n' - '+----------+-------+\n' - '| key | value |\n' - '+----------+-------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_wrap(self): - dict = {'key1': 'not wrapped', - 'key2': 'this will be wrapped'} - utils.print_dict(dict, wrap=16) - self.assertEqual('+----------+--------------+\n' - '| Property | Value |\n' - '+----------+--------------+\n' - '| key1 | not wrapped |\n' - '| key2 | this will be |\n' - '| | wrapped |\n' - '+----------+--------------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_list_sort_by_str(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 2), - _FakeResult("k2", 3)] - - utils.print_list(objs, ["Name", "Value"], sortby_index=0) - - self.assertEqual('+------+-------+\n' - '| Name | Value |\n' - '+------+-------+\n' - '| k1 | 1 |\n' - '| k2 | 3 |\n' - '| k3 | 2 |\n' - '+------+-------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_list_sort_by_integer(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 2), - _FakeResult("k2", 3)] - - utils.print_list(objs, ["Name", "Value"], sortby_index=1) - - self.assertEqual('+------+-------+\n' - '| Name | Value |\n' - '+------+-------+\n' - '| k1 | 1 |\n' - '| k3 | 2 |\n' - '| k2 | 3 |\n' - '+------+-------+\n', - sys.stdout.getvalue()) - - # without sorting - @mock.patch('sys.stdout', six.StringIO()) - def test_print_list_sort_by_none(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 3), - _FakeResult("k2", 2)] - - utils.print_list(objs, ["Name", "Value"], sortby_index=None) - - self.assertEqual('+------+-------+\n' - '| Name | Value |\n' - '+------+-------+\n' - '| k1 | 1 |\n' - '| k3 | 3 |\n' - '| k2 | 2 |\n' - '+------+-------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_dictionary(self): - dict = {'k': {'foo': 'bar'}} - utils.print_dict(dict) - self.assertEqual('+----------+----------------+\n' - '| Property | Value |\n' - '+----------+----------------+\n' - '| k | {"foo": "bar"} |\n' - '+----------+----------------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_list_dictionary(self): - dict = {'k': [{'foo': 'bar'}]} - utils.print_dict(dict) - self.assertEqual('+----------+------------------+\n' - '| Property | Value |\n' - '+----------+------------------+\n' - '| k | [{"foo": "bar"}] |\n' - '+----------+------------------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_list(self): - dict = {'k': ['foo', 'bar']} - utils.print_dict(dict) - self.assertEqual('+----------+----------------+\n' - '| Property | Value |\n' - '+----------+----------------+\n' - '| k | ["foo", "bar"] |\n' - '+----------+----------------+\n', - sys.stdout.getvalue()) - - -class FlattenTestCase(test_utils.TestCase): - def test_flattening(self): - squashed = utils.flatten_dict( - {'a1': {'b1': 1234, - 'b2': 'string', - 'b3': set((1, 2, 3)), - 'b4': {'c1': ['l', 'l', ['l']], - 'c2': 'string'}}, - 'a2': ['l'], - 'a3': ('t',)}) - - self.assertEqual({'a1_b1': 1234, - 'a1_b2': 'string', - 'a1_b3': set([1, 2, 3]), - 'a1_b4_c1': ['l', 'l', ['l']], - 'a1_b4_c2': 'string', - 'a2': ['l'], - 'a3': ('t',)}, - squashed) - - def test_pretty_choice_list(self): - l = [] - r = utils.pretty_choice_list(l) - self.assertEqual("", r) - - l = ["v1", "v2", "v3"] - r = utils.pretty_choice_list(l) - self.assertEqual("'v1', 'v2', 'v3'", r) - - def test_pretty_choice_dict(self): - d = {} - r = utils.pretty_choice_dict(d) - self.assertEqual("", r) - - d = {"k1": "v1", - "k2": "v2", - "k3": "v3"} - r = utils.pretty_choice_dict(d) - self.assertEqual("'k1=v1', 'k2=v2', 'k3=v3'", r) - - -class ValidationsTestCase(test_utils.TestCase): - def test_validate_flavor_metadata_keys_with_valid_keys(self): - valid_keys = ['key1', 'month.price', 'I-Am:AK-ey.01-', 'spaces and _'] - utils.validate_flavor_metadata_keys(valid_keys) - - def test_validate_flavor_metadata_keys_with_invalid_keys(self): - invalid_keys = ['/1', '?1', '%1', '<', '>', '\1'] - for key in invalid_keys: - try: - utils.validate_flavor_metadata_keys([key]) - self.fail("Invalid key passed validation: %s" % key) - except exceptions.CommandError as ce: - self.assertTrue(key in str(ce)) - - -class ResourceManagerExtraKwargsHookTestCase(test_utils.TestCase): - def test_get_resource_manager_extra_kwargs_hook_test(self): - do_foo = mock.MagicMock() - - def hook1(args): - return {'kwarg1': 'v_hook1'} - - def hook2(args): - return {'kwarg1': 'v_hook2'} - do_foo.resource_manager_kwargs_hooks = [hook1, hook2] - args = {} - exc = self.assertRaises(exceptions.NoUniqueMatch, - utils.get_resource_manager_extra_kwargs, - do_foo, - args) - except_error = ("Hook 'hook2' is attempting to redefine " - "attributes") - self.assertIn(except_error, six.text_type(exc)) diff --git a/awx/lib/site-packages/novaclient/tests/unit/__init__.py b/awx/lib/site-packages/novaclient/tests/unit/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/tests/unit/fakes.py b/awx/lib/site-packages/novaclient/tests/unit/fakes.py deleted file mode 100644 index ef6b59b523..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fakes.py +++ /dev/null @@ -1,92 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -A fake server that "responds" to API methods with pre-canned responses. - -All of these responses come from the spec, so if for some reason the spec's -wrong the tests might raise AssertionError. I've indicated in comments the -places where actual behavior differs from the spec. -""" - -from novaclient import base - - -def assert_has_keys(dict, required=[], optional=[]): - keys = dict.keys() - for k in required: - try: - assert k in keys - except AssertionError: - extra_keys = set(keys).difference(set(required + optional)) - raise AssertionError("found unexpected keys: %s" % - list(extra_keys)) - - -class FakeClient(object): - - def assert_called(self, method, url, body=None, pos=-1): - """ - Assert than an API method was just called. - """ - expected = (method, url) - called = self.client.callstack[pos][0:2] - - assert self.client.callstack, \ - "Expected %s %s but no calls were made." % expected - - assert expected == called, \ - 'Expected %s %s; got %s %s' % (expected + called) - - if body is not None: - if self.client.callstack[pos][2] != body: - raise AssertionError('%r != %r' % - (self.client.callstack[pos][2], body)) - - def assert_called_anytime(self, method, url, body=None): - """ - Assert than an API method was called anytime in the test. - """ - expected = (method, url) - - assert self.client.callstack, \ - "Expected %s %s but no calls were made." % expected - - found = False - for entry in self.client.callstack: - if expected == entry[0:2]: - found = True - break - - assert found, 'Expected %s; got %s' % (expected, self.client.callstack) - if body is not None: - try: - assert entry[2] == body - except AssertionError: - print(entry[2]) - print("!=") - print(body) - raise - - self.client.callstack = [] - - def clear_callstack(self): - self.client.callstack = [] - - def authenticate(self): - pass - - -# Fake class that will be used as an extension -class FakeManager(base.Manager): - pass diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/__init__.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/agents.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/agents.py deleted file mode 100644 index 46a0bb67b2..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/agents.py +++ /dev/null @@ -1,54 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-agents' - - def setUp(self): - super(Fixture, self).setUp() - - post_os_agents = { - 'agent': { - 'url': '/xxx/xxx/xxx', - 'hypervisor': 'kvm', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'version': '7.0', - 'architecture': 'x86', - 'os': 'win', - 'id': 1 - } - } - - self.requests.register_uri('POST', self.url(), - json=post_os_agents, - headers=self.json_headers) - - put_os_agents_1 = { - "agent": { - "url": "/yyy/yyyy/yyyy", - "version": "8.0", - "md5hash": "add6bb58e139be103324d04d82d8f546", - 'id': 1 - } - } - - self.requests.register_uri('PUT', self.url(1), - json=put_os_agents_1, - headers=self.json_headers) - - self.requests.register_uri('DELETE', self.url(1), - headers=self.json_headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/aggregates.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/aggregates.py deleted file mode 100644 index ed743ed1f9..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/aggregates.py +++ /dev/null @@ -1,52 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-aggregates' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_aggregates = {"aggregates": [ - {'id': '1', - 'name': 'test', - 'availability_zone': 'nova1'}, - {'id': '2', - 'name': 'test2', - 'availability_zone': 'nova1'}, - ]} - - self.requests.register_uri('GET', self.url(), - json=get_os_aggregates, - headers=self.json_headers) - - get_aggregates_1 = {'aggregate': get_os_aggregates['aggregates'][0]} - - self.requests.register_uri('POST', self.url(), - json=get_aggregates_1, - headers=self.json_headers) - - for agg_id in (1, 2): - for method in ('GET', 'PUT'): - self.requests.register_uri(method, self.url(agg_id), - json=get_aggregates_1, - headers=self.json_headers) - - self.requests.register_uri('POST', self.url(agg_id, 'action'), - json=get_aggregates_1, - headers=self.json_headers) - - self.requests.register_uri('DELETE', self.url(1), status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/availability_zones.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/availability_zones.py deleted file mode 100644 index 36659d70a5..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/availability_zones.py +++ /dev/null @@ -1,91 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-availability-zone' - - zone_info_key = 'availabilityZoneInfo' - zone_name_key = 'zoneName' - zone_state_key = 'zoneState' - - def setUp(self): - super(V1, self).setUp() - - get_os_availability_zone = { - self.zone_info_key: [ - { - self.zone_name_key: "zone-1", - self.zone_state_key: {"available": True}, - "hosts": None - }, - { - self.zone_name_key: "zone-2", - self.zone_state_key: {"available": False}, - "hosts": None - } - ] - } - - self.requests.register_uri('GET', self.url(), - json=get_os_availability_zone, - headers=self.json_headers) - - get_os_zone_detail = { - self.zone_info_key: [ - { - self.zone_name_key: "zone-1", - self.zone_state_key: {"available": True}, - "hosts": { - "fake_host-1": { - "nova-compute": { - "active": True, - "available": True, - "updated_at": '2012-12-26 14:45:25' - } - } - } - }, - { - self.zone_name_key: "internal", - self.zone_state_key: {"available": True}, - "hosts": { - "fake_host-1": { - "nova-sched": { - "active": True, - "available": True, - "updated_at": '2012-12-26 14:45:25' - } - }, - "fake_host-2": { - "nova-network": { - "active": True, - "available": False, - "updated_at": '2012-12-26 14:45:24' - } - } - } - }, - { - self.zone_name_key: "zone-2", - self.zone_state_key: {"available": False}, - "hosts": None - } - ] - } - - self.requests.register_uri('GET', self.url('detail'), - json=get_os_zone_detail, - headers=self.json_headers) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/base.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/base.py deleted file mode 100644 index 6a2e238b58..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/base.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -from six.moves.urllib import parse - -COMPUTE_URL = 'http://compute.host' - - -class Fixture(fixtures.Fixture): - - base_url = None - json_headers = {'Content-Type': 'application/json'} - - def __init__(self, requests, compute_url=COMPUTE_URL): - super(Fixture, self).__init__() - self.requests = requests - self.compute_url = compute_url - - def url(self, *args, **kwargs): - url_args = [self.compute_url] - - if self.base_url: - url_args.append(self.base_url) - - url = '/'.join(str(a).strip('/') for a in tuple(url_args) + args) - - if kwargs: - url += '?%s' % parse.urlencode(kwargs, doseq=True) - - return url diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/certs.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/certs.py deleted file mode 100644 index 1dedaa4a33..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/certs.py +++ /dev/null @@ -1,55 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-certificates' - - def get_os_certificates_root(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': None, 'data': 'foo'}} - ) - - def post_os_certificates(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': 'foo', 'data': 'bar'}} - ) - - def setUp(self): - super(Fixture, self).setUp() - - get_os_certificate = { - 'certificate': { - 'private_key': None, - 'data': 'foo' - } - } - self.requests.register_uri('GET', self.url('root'), - json=get_os_certificate, - headers=self.json_headers) - - post_os_certificates = { - 'certificate': { - 'private_key': 'foo', - 'data': 'bar' - } - } - self.requests.register_uri('POST', self.url(), - json=post_os_certificates, - headers=self.json_headers) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/client.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/client.py deleted file mode 100644 index 5f933b7502..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/client.py +++ /dev/null @@ -1,65 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -from keystoneclient.auth.identity import v2 -from keystoneclient import fixture -from keystoneclient import session - -from novaclient.v2 import client as v2client - -IDENTITY_URL = 'http://identityserver:5000/v2.0' -COMPUTE_URL = 'http://compute.host' - - -class V1(fixtures.Fixture): - - def __init__(self, requests, - compute_url=COMPUTE_URL, identity_url=IDENTITY_URL): - super(V1, self).__init__() - self.identity_url = identity_url - self.compute_url = compute_url - self.client = None - self.requests = requests - - self.token = fixture.V2Token() - self.token.set_scope() - - s = self.token.add_service('compute') - s.add_endpoint(self.compute_url) - - s = self.token.add_service('computev3') - s.add_endpoint(self.compute_url) - - def setUp(self): - super(V1, self).setUp() - - auth_url = '%s/tokens' % self.identity_url - headers = {'X-Content-Type': 'application/json'} - self.requests.register_uri('POST', auth_url, - json=self.token, - headers=headers) - self.client = self.new_client() - - def new_client(self): - return v2client.Client(username='xx', - api_key='xx', - project_id='xx', - auth_url=self.identity_url) - - -class SessionV1(V1): - - def new_client(self): - self.session = session.Session() - self.session.auth = v2.Password(self.identity_url, 'xx', 'xx') - return v2client.Client(session=self.session) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/cloudpipe.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/cloudpipe.py deleted file mode 100644 index abe590563b..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/cloudpipe.py +++ /dev/null @@ -1,37 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-cloudpipe' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_cloudpipe = {'cloudpipes': [{'project_id': 1}]} - self.requests.register_uri('GET', self.url(), - json=get_os_cloudpipe, - headers=self.json_headers) - - instance_id = '9d5824aa-20e6-4b9f-b967-76a699fc51fd' - post_os_cloudpipe = {'instance_id': instance_id} - self.requests.register_uri('POST', self.url(), - json=post_os_cloudpipe, - headers=self.json_headers, - status_code=202) - - self.requests.register_uri('PUT', self.url('configure-project'), - headers=self.json_headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/fixedips.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/fixedips.py deleted file mode 100644 index fb677e91ce..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/fixedips.py +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-fixed-ips' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_fixed_ips = { - "fixed_ip": { - 'cidr': '192.168.1.0/24', - 'address': '192.168.1.1', - 'hostname': 'foo', - 'host': 'bar' - } - } - - self.requests.register_uri('GET', self.url('192.168.1.1'), - json=get_os_fixed_ips, - headers=self.json_headers) - - self.requests.register_uri('POST', - self.url('192.168.1.1', 'action'), - headers=self.json_headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/floatingips.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/floatingips.py deleted file mode 100644 index 10772a798d..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/floatingips.py +++ /dev/null @@ -1,211 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit import fakes -from novaclient.tests.unit.fixture_data import base - - -class FloatingFixture(base.Fixture): - - base_url = 'os-floating-ips' - - def setUp(self): - super(FloatingFixture, self).setUp() - - floating_ips = [{'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}] - - get_os_floating_ips = {'floating_ips': floating_ips} - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ips, - headers=self.json_headers) - - for ip in floating_ips: - get_os_floating_ip = {'floating_ip': ip} - self.requests.register_uri('GET', self.url(ip['id']), - json=get_os_floating_ip, - headers=self.json_headers) - - self.requests.register_uri('DELETE', self.url(ip['id']), - headers=self.json_headers, - status_code=204) - - def post_os_floating_ips(request, context): - body = jsonutils.loads(request.body) - ip = floating_ips[0].copy() - ip['pool'] = body.get('pool') - return {'floating_ip': ip} - self.requests.register_uri('POST', self.url(), - json=post_os_floating_ips, - headers=self.json_headers) - - -class DNSFixture(base.Fixture): - - base_url = 'os-floating-ip-dns' - - def setUp(self): - super(DNSFixture, self).setUp() - - get_os_floating_ip_dns = { - 'domain_entries': [ - {'domain': 'example.org'}, - {'domain': 'example.com'} - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ip_dns, - headers=self.json_headers, - status_code=205) - - get_dns_testdomain_entries_testname = { - 'dns_entry': { - 'ip': "10.10.10.10", - 'name': 'testname', - 'type': "A", - 'domain': 'testdomain' - } - } - url = self.url('testdomain', 'entries', 'testname') - self.requests.register_uri('GET', url, - json=get_dns_testdomain_entries_testname, - headers=self.json_headers, - status_code=205) - - self.requests.register_uri('DELETE', self.url('testdomain')) - - url = self.url('testdomain', 'entries', 'testname') - self.requests.register_uri('DELETE', url) - - def put_dns_testdomain_entries_testname(request, context): - body = jsonutils.loads(request.body) - fakes.assert_has_keys(body['dns_entry'], - required=['ip', 'dns_type']) - context.status_code = 205 - return request.body - self.requests.register_uri('PUT', url, - text=put_dns_testdomain_entries_testname, - headers=self.json_headers) - - url = self.url('testdomain', 'entries') - self.requests.register_uri('GET', url, status_code=404) - - get_os_floating_ip_dns_testdomain = { - 'dns_entries': [ - { - 'dns_entry': { - 'ip': '1.2.3.4', - 'name': "host1", - 'type': "A", - 'domain': 'testdomain' - } - }, - { - 'dns_entry': { - 'ip': '1.2.3.4', - 'name': "host2", - 'type': "A", - 'domain': 'testdomain' - } - }, - ] - } - self.requests.register_uri('GET', url + '?ip=1.2.3.4', - json=get_os_floating_ip_dns_testdomain, - status_code=205, - headers=self.json_headers) - - def put_os_floating_ip_dns_testdomain(request, context): - body = jsonutils.loads(request.body) - if body['domain_entry']['scope'] == 'private': - fakes.assert_has_keys(body['domain_entry'], - required=['availability_zone', 'scope']) - elif body['domain_entry']['scope'] == 'public': - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - else: - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - - return request.body - - self.requests.register_uri('PUT', self.url('testdomain'), - text=put_os_floating_ip_dns_testdomain, - status_code=205, - headers=self.json_headers) - - -class BulkFixture(base.Fixture): - - base_url = 'os-floating-ips-bulk' - - def setUp(self): - super(BulkFixture, self).setUp() - - get_os_floating_ips_bulk = { - 'floating_ip_info': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ips_bulk, - headers=self.json_headers) - self.requests.register_uri('GET', self.url('testHost'), - json=get_os_floating_ips_bulk, - headers=self.json_headers) - - def put_os_floating_ips_bulk_delete(request, context): - body = jsonutils.loads(request.body) - ip_range = body.get('ip_range') - return {'floating_ips_bulk_delete': ip_range} - - self.requests.register_uri('PUT', self.url('delete'), - json=put_os_floating_ips_bulk_delete, - headers=self.json_headers) - - def post_os_floating_ips_bulk(request, context): - body = jsonutils.loads(request.body) - params = body.get('floating_ips_bulk_create') - pool = params.get('pool', 'defaultPool') - interface = params.get('interface', 'defaultInterface') - return { - 'floating_ips_bulk_create': { - 'ip_range': '192.168.1.0/30', - 'pool': pool, - 'interface': interface - } - } - - self.requests.register_uri('POST', self.url(), - json=post_os_floating_ips_bulk, - headers=self.json_headers) - - -class PoolsFixture(base.Fixture): - - base_url = 'os-floating-ip-pools' - - def setUp(self): - super(PoolsFixture, self).setUp() - - get_os_floating_ip_pools = { - 'floating_ip_pools': [ - {'name': 'foo'}, - {'name': 'bar'} - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_floating_ip_pools, - headers=self.json_headers) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/fping.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/fping.py deleted file mode 100644 index 6c6cd4f89c..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/fping.py +++ /dev/null @@ -1,46 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-fping' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_fping_1 = { - 'server': { - "id": "1", - "project_id": "fake-project", - "alive": True, - } - } - self.requests.register_uri('GET', self.url(1), - json=get_os_fping_1, - headers=self.json_headers) - - get_os_fping = { - 'servers': [ - get_os_fping_1['server'], - { - "id": "2", - "project_id": "fake-project", - "alive": True, - }, - ] - } - self.requests.register_uri('GET', self.url(), - json=get_os_fping, - headers=self.json_headers) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/hosts.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/hosts.py deleted file mode 100644 index 5c1ff60a39..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/hosts.py +++ /dev/null @@ -1,149 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils -from six.moves.urllib import parse - -from novaclient.tests.unit.fixture_data import base - - -class BaseFixture(base.Fixture): - - base_url = 'os-hosts' - - def setUp(self): - super(BaseFixture, self).setUp() - - get_os_hosts_host = { - 'host': [ - {'resource': {'project': '(total)', 'host': 'dummy', - 'cpu': 16, 'memory_mb': 32234, 'disk_gb': 128}}, - {'resource': {'project': '(used_now)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2075, 'disk_gb': 45}}, - {'resource': {'project': '(used_max)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}, - {'resource': {'project': 'admin', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}} - ] - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url('host'), - json=get_os_hosts_host, - headers=headers) - - def get_os_hosts(request, context): - host, query = parse.splitquery(request.url) - zone = 'nova1' - service = None - - if query: - qs = parse.parse_qs(query) - try: - zone = qs['zone'][0] - except Exception: - pass - - try: - service = qs['service'][0] - except Exception: - pass - - return { - 'hosts': [ - { - 'host': 'host1', - 'service': service or 'nova-compute', - 'zone': zone - }, - { - 'host': 'host1', - 'service': service or 'nova-cert', - 'zone': zone - } - ] - } - - self.requests.register_uri('GET', self.url(), - json=get_os_hosts, - headers=headers) - - get_os_hosts_sample_host = { - 'host': [ - {'resource': {'host': 'sample_host'}} - ], - } - self.requests.register_uri('GET', self.url('sample_host'), - json=get_os_hosts_sample_host, - headers=headers) - - self.requests.register_uri('PUT', self.url('sample_host', 1), - json=self.put_host_1(), - headers=headers) - - self.requests.register_uri('PUT', self.url('sample_host', 2), - json=self.put_host_2(), - headers=headers) - - self.requests.register_uri('PUT', self.url('sample_host', 3), - json=self.put_host_3(), - headers=headers) - - self.requests.register_uri('GET', self.url('sample_host', 'reboot'), - json=self.get_host_reboot(), - headers=headers) - - self.requests.register_uri('GET', self.url('sample_host', 'startup'), - json=self.get_host_startup(), - headers=headers) - - self.requests.register_uri('GET', self.url('sample_host', 'shutdown'), - json=self.get_host_shutdown(), - headers=headers) - - def put_os_hosts_sample_host(request, context): - result = {'host': 'dummy'} - result.update(jsonutils.loads(request.body)) - return result - - self.requests.register_uri('PUT', self.url('sample_host'), - json=put_os_hosts_sample_host, - headers=headers) - - -class V1(BaseFixture): - - def put_host_1(self): - return {'host': 'sample-host_1', - 'status': 'enabled'} - - def put_host_2(self): - return {'host': 'sample-host_2', - 'maintenance_mode': 'on_maintenance'} - - def put_host_3(self): - return {'host': 'sample-host_3', - 'status': 'enabled', - 'maintenance_mode': 'on_maintenance'} - - def get_host_reboot(self): - return {'host': 'sample_host', - 'power_action': 'reboot'} - - def get_host_startup(self): - return {'host': 'sample_host', - 'power_action': 'startup'} - - def get_host_shutdown(self): - return {'host': 'sample_host', - 'power_action': 'shutdown'} diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/hypervisors.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/hypervisors.py deleted file mode 100644 index 62952f081f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/hypervisors.py +++ /dev/null @@ -1,182 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-hypervisors' - - def setUp(self): - super(V1, self).setUp() - - get_os_hypervisors = { - 'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'}, - ] - } - - self.headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_os_hypervisors, - headers=self.headers) - - get_os_hypervisors_detail = { - 'hypervisors': [ - { - 'id': 1234, - 'service': { - 'id': 1, - 'host': 'compute1', - }, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'hypervisor_hostname': 'hyper1', - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100 - }, - { - 'id': 2, - 'service': { - 'id': 2, - 'host': 'compute2', - }, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'hypervisor_hostname': 'hyper2', - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100 - } - ] - } - - self.requests.register_uri('GET', self.url('detail'), - json=get_os_hypervisors_detail, - headers=self.headers) - - get_os_hypervisors_stats = { - 'hypervisor_statistics': { - 'count': 2, - 'vcpus': 8, - 'memory_mb': 20 * 1024, - 'local_gb': 500, - 'vcpus_used': 4, - 'memory_mb_used': 10 * 1024, - 'local_gb_used': 250, - 'free_ram_mb': 10 * 1024, - 'free_disk_gb': 250, - 'current_workload': 4, - 'running_vms': 4, - 'disk_available_least': 200, - } - } - - self.requests.register_uri('GET', self.url('statistics'), - json=get_os_hypervisors_stats, - headers=self.headers) - - get_os_hypervisors_search = { - 'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'} - ] - } - - self.requests.register_uri('GET', self.url('hyper', 'search'), - json=get_os_hypervisors_search, - headers=self.headers) - - get_hyper_server = { - 'hypervisors': [ - { - 'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'servers': [ - {'name': 'inst1', 'uuid': 'uuid1'}, - {'name': 'inst2', 'uuid': 'uuid2'} - ] - }, - { - 'id': 5678, - 'hypervisor_hostname': 'hyper2', - 'servers': [ - {'name': 'inst3', 'uuid': 'uuid3'}, - {'name': 'inst4', 'uuid': 'uuid4'} - ] - } - ] - } - - self.requests.register_uri('GET', self.url('hyper', 'servers'), - json=get_hyper_server, - headers=self.headers) - - get_os_hypervisors_1234 = { - 'hypervisor': { - 'id': 1234, - 'service': {'id': 1, 'host': 'compute1'}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': 'xen', - 'hypervisor_version': 3, - 'hypervisor_hostname': 'hyper1', - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100 - } - } - - self.requests.register_uri('GET', self.url(1234), - json=get_os_hypervisors_1234, - headers=self.headers) - - get_os_hypervisors_uptime = { - 'hypervisor': { - 'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'uptime': 'fake uptime' - } - } - - self.requests.register_uri('GET', self.url(1234, 'uptime'), - json=get_os_hypervisors_uptime, - headers=self.headers) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/images.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/images.py deleted file mode 100644 index 02f3596683..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/images.py +++ /dev/null @@ -1,113 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit import fakes -from novaclient.tests.unit.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'images' - - def setUp(self): - super(V1, self).setUp() - - get_images = { - 'images': [ - {'id': 1, 'name': 'CentOS 5.2'}, - {'id': 2, 'name': 'My Server Backup'} - ] - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_images, - headers=headers) - - image_1 = { - 'id': 1, - 'name': 'CentOS 5.2', - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "ACTIVE", - "metadata": { - "test_key": "test_value", - }, - "links": {}, - } - - image_2 = { - "id": 2, - "name": "My Server Backup", - "serverId": 1234, - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "SAVING", - "progress": 80, - "links": {}, - } - - self.requests.register_uri('GET', self.url('detail'), - json={'images': [image_1, image_2]}, - headers=headers) - - self.requests.register_uri('GET', self.url(1), - json={'image': image_1}, - headers=headers) - - self.requests.register_uri('GET', self.url(2), - json={'image': image_2}, - headers=headers) - - self.requests.register_uri('GET', self.url(456), - json={'image': image_2}, - headers=headers) - - def post_images(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['image'] - fakes.assert_has_keys(body['image'], required=['serverId', 'name']) - return images_1 - - self.requests.register_uri('POST', self.url(), - json=post_images, - headers=headers, - status_code=202) - - def post_images_1_metadata(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['metadata'] - fakes.assert_has_keys(body['metadata'], required=['test_key']) - return {'metadata': image_1['metadata']} - - self.requests.register_uri('POST', self.url(1, 'metadata'), - json=post_images_1_metadata, - headers=headers) - - for u in (1, 2, '1/metadata/test_key'): - self.requests.register_uri('DELETE', self.url(u), status_code=204) - - image_headers = {'x-image-meta-id': '1', - 'x-image-meta-name': 'CentOS 5.2', - 'x-image-meta-updated': '2010-10-10T12:00:00Z', - 'x-image-meta-created': '2010-10-10T12:00:00Z', - 'x-image-meta-status': 'ACTIVE', - 'x-image-meta-property-test-key': 'test_value'} - self.requests.register_uri('HEAD', self.url(1), headers=image_headers) - - -class V3(V1): - - base_url = 'v1/images' diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/keypairs.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/keypairs.py deleted file mode 100644 index 9314c58a59..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/keypairs.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit import fakes -from novaclient.tests.unit.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-keypairs' - - def setUp(self): - super(V1, self).setUp() - keypair = {'fingerprint': 'FAKE_KEYPAIR', 'name': 'test'} - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json={'keypairs': [keypair]}, - headers=headers) - - self.requests.register_uri('GET', self.url('test'), - json={'keypair': keypair}, - headers=headers) - - self.requests.register_uri('DELETE', self.url('test'), status_code=202) - - def post_os_keypairs(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['keypair'] - fakes.assert_has_keys(body['keypair'], required=['name']) - return {'keypair': keypair} - - self.requests.register_uri('POST', self.url(), - json=post_os_keypairs, - headers=headers) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/limits.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/limits.py deleted file mode 100644 index 55d324d955..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/limits.py +++ /dev/null @@ -1,80 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'limits' - - def setUp(self): - super(Fixture, self).setUp() - - get_limits = { - "limits": { - "rate": [ - { - "uri": "*", - "regex": ".*", - "limit": [ - { - "value": 10, - "verb": "POST", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 10, - "verb": "PUT", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 100, - "verb": "DELETE", - "remaining": 100, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - } - ] - }, - { - "uri": "*/servers", - "regex": "^/servers", - "limit": [ - { - "verb": "POST", - "value": 25, - "remaining": 24, - "unit": "DAY", - "next-available": "2011-12-15T22:42:45Z" - } - ] - } - ], - "absolute": { - "maxTotalRAMSize": 51200, - "maxServerMeta": 5, - "maxImageMeta": 5, - "maxPersonality": 5, - "maxPersonalitySize": 10240 - }, - }, - } - - headers = {'Content-Type': 'application/json'} - self.requests.register_uri('GET', self.url(), - json=get_limits, - headers=headers) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/networks.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/networks.py deleted file mode 100644 index 9ef692c3ee..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/networks.py +++ /dev/null @@ -1,62 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-networks' - - def setUp(self): - super(Fixture, self).setUp() - - get_os_networks = { - 'networks': [ - { - "label": "1", - "cidr": "10.0.0.0/24", - 'project_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1' - } - ] - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_os_networks, - headers=headers) - - def post_os_networks(request, context): - body = jsonutils.loads(request.body) - return {'network': body} - - self.requests.register_uri("POST", self.url(), - json=post_os_networks, - headers=headers) - - get_os_networks_1 = {'network': {"label": "1", "cidr": "10.0.0.0/24"}} - - self.requests.register_uri('GET', self.url(1), - json=get_os_networks_1, - headers=headers) - - self.requests.register_uri('DELETE', - self.url('networkdelete'), - status_code=202) - - for u in ('add', 'networkdisassociate/action', 'networktest/action', - '1/action', '2/action'): - self.requests.register_uri('POST', self.url(u), status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/quotas.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/quotas.py deleted file mode 100644 index 83f448f49c..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/quotas.py +++ /dev/null @@ -1,66 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import base - - -class V1(base.Fixture): - - base_url = 'os-quota-sets' - - def setUp(self): - super(V1, self).setUp() - - uuid = '97f4c221-bff4-4578-b030-0df4ef119353' - uuid2 = '97f4c221bff44578b0300df4ef119353' - test_json = {'quota_set': self.test_quota('test')} - self.headers = {'Content-Type': 'application/json'} - - for u in ('test', 'tenant-id', 'tenant-id/defaults', - '%s/defaults' % uuid2): - self.requests.register_uri('GET', self.url(u), - json=test_json, - headers=self.headers) - - self.requests.register_uri('PUT', self.url(uuid), - json={'quota_set': self.test_quota(uuid)}, - headers=self.headers) - - self.requests.register_uri('GET', self.url(uuid), - json={'quota_set': self.test_quota(uuid)}, - headers=self.headers) - - self.requests.register_uri('PUT', self.url(uuid2), - json={'quota_set': self.test_quota(uuid2)}, - headers=self.headers) - self.requests.register_uri('GET', self.url(uuid2), - json={'quota_set': self.test_quota(uuid2)}, - headers=self.headers) - - for u in ('test', uuid2): - self.requests.register_uri('DELETE', self.url(u), status_code=202) - - def test_quota(self, tenant_id='test'): - return { - 'tenant_id': tenant_id, - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1 - } diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/security_group_rules.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/security_group_rules.py deleted file mode 100644 index 5f1d2fad5b..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/security_group_rules.py +++ /dev/null @@ -1,58 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit import fakes -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-security-group-rules' - - def setUp(self): - super(Fixture, self).setUp() - - rule = { - 'id': 1, - 'parent_group_id': 1, - 'group_id': 2, - 'ip_protocol': 'TCP', - 'from_port': '22', - 'to_port': 22, - 'cidr': '10.0.0.0/8' - } - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json={'security_group_rules': [rule]}, - headers=headers) - - for u in (1, 11, 12): - self.requests.register_uri('DELETE', self.url(u), status_code=202) - - def post_rules(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['security_group_rule'] - fakes.assert_has_keys(body['security_group_rule'], - required=['parent_group_id'], - optional=['group_id', 'ip_protocol', - 'from_port', 'to_port', 'cidr']) - - return {'security_group_rule': rule} - - self.requests.register_uri('POST', self.url(), - json=post_rules, - headers=headers, - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/security_groups.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/security_groups.py deleted file mode 100644 index ac5d182c6f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/security_groups.py +++ /dev/null @@ -1,100 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit import fakes -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-security-groups' - - def setUp(self): - super(Fixture, self).setUp() - - security_group_1 = { - "name": "test", - "description": "FAKE_SECURITY_GROUP", - "tenant_id": "4ffc664c198e435e9853f2538fbcd7a7", - "id": 1, - "rules": [ - { - "id": 11, - "group": {}, - "ip_protocol": "TCP", - "from_port": 22, - "to_port": 22, - "parent_group_id": 1, - "ip_range": {"cidr": "10.0.0.0/8"} - }, - { - "id": 12, - "group": { - "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582", - "name": "test2" - }, - "ip_protocol": "TCP", - "from_port": 222, - "to_port": 222, - "parent_group_id": 1, - "ip_range": {} - } - ] - } - - security_group_2 = { - "name": "test2", - "description": "FAKE_SECURITY_GROUP2", - "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582", - "id": 2, - "rules": [] - } - - get_groups = {'security_groups': [security_group_1, security_group_2]} - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json=get_groups, - headers=headers) - - get_group_1 = {'security_group': security_group_1} - self.requests.register_uri('GET', self.url(1), - json=get_group_1, - headers=headers) - - self.requests.register_uri('DELETE', self.url(1), status_code=202) - - def post_os_security_groups(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - return {'security_group': security_group_1} - - self.requests.register_uri('POST', self.url(), - json=post_os_security_groups, - headers=headers, - status_code=202) - - def put_os_security_groups_1(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - return body - - self.requests.register_uri('PUT', self.url(1), - json=put_os_security_groups_1, - headers=headers, - status_code=205) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/server_groups.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/server_groups.py deleted file mode 100644 index 1fcfdea55c..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/server_groups.py +++ /dev/null @@ -1,74 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit.fixture_data import base - - -class Fixture(base.Fixture): - - base_url = 'os-server-groups' - - def setUp(self): - super(Fixture, self).setUp() - - server_groups = [ - { - "members": [], - "metadata": {}, - "id": "2cbd51f4-fafe-4cdb-801b-cf913a6f288b", - "policies": [], - "name": "ig1" - }, - { - "members": [], - "metadata": {}, - "id": "4473bb03-4370-4bfb-80d3-dc8cffc47d94", - "policies": ["anti-affinity"], - "name": "ig2" - }, - { - "members": [], - "metadata": {"key": "value"}, - "id": "31ab9bdb-55e1-4ac3-b094-97eeb1b65cc4", - "policies": [], "name": "ig3" - }, - { - "members": ["2dccb4a1-02b9-482a-aa23-5799490d6f5d"], - "metadata": {}, - "id": "4890bb03-7070-45fb-8453-d34556c87d94", - "policies": ["anti-affinity"], - "name": "ig2" - } - ] - - headers = {'Content-Type': 'application/json'} - - self.requests.register_uri('GET', self.url(), - json={'server_groups': server_groups}, - headers=headers) - - server = server_groups[0] - server_j = jsonutils.dumps({'server_group': server}) - - def _register(method, *args): - self.requests.register_uri(method, self.url(*args), text=server_j) - - _register('POST') - _register('POST', server['id']) - _register('GET', server['id']) - _register('PUT', server['id']) - _register('POST', server['id'], '/action') - - self.requests.register_uri('DELETE', self.url(server['id']), - status_code=202) diff --git a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/servers.py b/awx/lib/site-packages/novaclient/tests/unit/fixture_data/servers.py deleted file mode 100644 index 6e3dd46b7a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/fixture_data/servers.py +++ /dev/null @@ -1,495 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo.serialization import jsonutils - -from novaclient.tests.unit import fakes -from novaclient.tests.unit.fixture_data import base - - -class Base(base.Fixture): - - base_url = 'servers' - - def setUp(self): - super(Base, self).setUp() - - get_servers = { - "servers": [ - {'id': 1234, 'name': 'sample-server'}, - {'id': 5678, 'name': 'sample-server2'} - ] - } - - self.requests.register_uri('GET', self.url(), - json=get_servers, - headers=self.json_headers) - - self.server_1234 = { - "id": 1234, - "name": "sample-server", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0", - "status": "BUILD", - "progress": 60, - "addresses": { - "public": [ - { - "version": 4, - "addr": "1.2.3.4", - }, - { - "version": 4, - "addr": "5.6.7.8", - }], - "private": [{ - "version": 4, - "addr": "10.11.12.13", - }], - }, - "metadata": { - "Server Label": "Web Head 1", - "Image Version": "2.1" - }, - "OS-EXT-SRV-ATTR:host": "computenode1", - "security_groups": [{ - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - "OS-EXT-MOD:some_thing": "mod_some_thing_value", - } - - self.server_5678 = { - "id": 5678, - "name": "sample-server2", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [ - { - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - }, - "OS-EXT-SRV-ATTR:host": "computenode2", - "security_groups": [ - { - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }, - { - 'id': 2, 'name': 'securitygroup2', - 'description': 'ANOTHER_FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - } - - self.server_9012 = { - "id": 9012, - "name": "sample-server3", - "image": "", - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [ - { - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - } - } - - servers = [self.server_1234, self.server_5678, self.server_9012] - get_servers_detail = {"servers": servers} - - self.requests.register_uri('GET', self.url('detail'), - json=get_servers_detail, - headers=self.json_headers) - - self.server_1235 = self.server_1234.copy() - self.server_1235['id'] = 1235 - self.server_1235['status'] = 'error' - self.server_1235['fault'] = {'message': 'something went wrong!'} - - for s in servers + [self.server_1235]: - self.requests.register_uri('GET', self.url(s['id']), - json={'server': s}, - headers=self.json_headers) - - for s in (1234, 5678): - self.requests.register_uri('DELETE', self.url(s), status_code=202) - - for k in ('test_key', 'key1', 'key2'): - self.requests.register_uri('DELETE', - self.url(1234, 'metadata', k), - status_code=204) - - metadata1 = {'metadata': {'test_key': 'test_value'}} - self.requests.register_uri('POST', self.url(1234, 'metadata'), - json=metadata1, - headers=self.json_headers) - self.requests.register_uri('PUT', - self.url(1234, 'metadata', 'test_key'), - json=metadata1, - headers=self.json_headers) - - self.diagnostic = {'data': 'Fake diagnostics'} - - metadata2 = {'metadata': {'key1': 'val1'}} - for u in ('uuid1', 'uuid2', 'uuid3', 'uuid4'): - self.requests.register_uri('POST', self.url(u, 'metadata'), - json=metadata2, status_code=204) - self.requests.register_uri('DELETE', - self.url(u, 'metadata', 'key1'), - json=self.diagnostic, - headers=self.json_headers) - - get_security_groups = { - "security_groups": [{ - 'id': 1, - 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'rules': []}] - } - - self.requests.register_uri('GET', - self.url('1234', 'os-security-groups'), - json=get_security_groups) - - self.requests.register_uri('POST', self.url(), - json=self.post_servers, - headers=self.json_headers) - - self.requests.register_uri('POST', self.url('1234', 'action'), - json=self.post_servers_1234_action, - headers=self.json_headers) - - get_os_interface = { - "interfaceAttachments": [ - { - "port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - }, - { - "port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - } - ] - } - - self.requests.register_uri('GET', - self.url('1234', 'os-interface'), - json=get_os_interface, - headers=self.json_headers) - - interface_data = {'interfaceAttachment': {}} - self.requests.register_uri('POST', - self.url('1234', 'os-interface'), - json=interface_data, - headers=self.json_headers) - - def put_servers_1234(request, context): - body = jsonutils.loads(request.body) - assert list(body) == ['server'] - fakes.assert_has_keys(body['server'], - optional=['name', 'adminPass']) - return request.body - - self.requests.register_uri('PUT', self.url(1234), - text=put_servers_1234, - status_code=204, - headers=self.json_headers) - - def post_os_volumes_boot(request, context): - body = jsonutils.loads(request.body) - assert (set(body.keys()) <= - set(['server', 'os:scheduler_hints'])) - - fakes.assert_has_keys(body['server'], - required=['name', 'flavorRef'], - optional=['imageRef']) - - data = body['server'] - - # Require one, and only one, of the keys for bdm - if 'block_device_mapping' not in data: - if 'block_device_mapping_v2' not in data: - msg = "missing required keys: 'block_device_mapping'" - raise AssertionError(msg) - elif 'block_device_mapping_v2' in data: - msg = "found extra keys: 'block_device_mapping'" - raise AssertionError(msg) - - return {'server': self.server_9012} - - # NOTE(jamielennox): hack to make os_volumes mock go to the right place - base_url = self.base_url - self.base_url = None - self.requests.register_uri('POST', self.url('os-volumes_boot'), - json=post_os_volumes_boot, - status_code=202, - headers=self.json_headers) - self.base_url = base_url - - # - # Server password - # - - self.requests.register_uri('DELETE', - self.url(1234, 'os-server-password'), - status_code=202) - - -class V1(Base): - - def setUp(self): - super(V1, self).setUp() - - # - # Server Addresses - # - - add = self.server_1234['addresses'] - self.requests.register_uri('GET', self.url(1234, 'ips'), - json={'addresses': add}, - headers=self.json_headers) - - self.requests.register_uri('GET', self.url(1234, 'ips', 'public'), - json={'public': add['public']}, - headers=self.json_headers) - - self.requests.register_uri('GET', self.url(1234, 'ips', 'private'), - json={'private': add['private']}, - headers=self.json_headers) - - self.requests.register_uri('DELETE', - self.url(1234, 'ips', 'public', '1.2.3.4'), - status_code=202) - - self.requests.register_uri('GET', - self.url('1234', 'diagnostics'), - json=self.diagnostic) - - self.requests.register_uri('DELETE', - self.url('1234', 'os-interface', 'port-id')) - - # Testing with the following password and key - # - # Clear password: FooBar123 - # - # RSA Private Key: novaclient/tests/unit/idfake.pem - # - # Encrypted password - # OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r - # qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho - # QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw - # /y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N - # tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk - # Hi/fmZZNQQqj1Ijq0caOIw== - - get_server_password = { - 'password': - 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r' - 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho' - 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw' - '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N' - 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk' - 'Hi/fmZZNQQqj1Ijq0caOIw=='} - self.requests.register_uri('GET', - self.url(1234, 'os-server-password'), - json=get_server_password) - - def post_servers(self, request, context): - body = jsonutils.loads(request.body) - context.status_code = 202 - assert (set(body.keys()) <= - set(['server', 'os:scheduler_hints'])) - fakes.assert_has_keys(body['server'], - required=['name', 'imageRef', 'flavorRef'], - optional=['metadata', 'personality']) - if 'personality' in body['server']: - for pfile in body['server']['personality']: - fakes.assert_has_keys(pfile, required=['path', 'contents']) - if body['server']['name'] == 'some-bad-server': - body = self.server_1235 - else: - body = self.server_1234 - - return {'server': body} - - def post_servers_1234_action(self, request, context): - _body = '' - body = jsonutils.loads(request.body) - context.status_code = 202 - assert len(body.keys()) == 1 - action = list(body)[0] - if action == 'reboot': - assert list(body[action]) == ['type'] - assert body[action]['type'] in ['HARD', 'SOFT'] - elif action == 'rebuild': - body = body[action] - adminPass = body.get('adminPass', 'randompassword') - assert 'imageRef' in body - _body = self.server_1234.copy() - _body['adminPass'] = adminPass - elif action == 'resize': - keys = body[action].keys() - assert 'flavorRef' in keys - elif action == 'confirmResize': - assert body[action] is None - # This one method returns a different response code - context.status_code = 204 - return None - elif action == 'revertResize': - assert body[action] is None - elif action == 'migrate': - assert body[action] is None - elif action == 'os-stop': - assert body[action] is None - elif action == 'os-start': - assert body[action] is None - elif action == 'forceDelete': - assert body[action] is None - elif action == 'restore': - assert body[action] is None - elif action == 'pause': - assert body[action] is None - elif action == 'unpause': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'rescue': - if body[action]: - keys = set(body[action].keys()) - assert not (keys - set(['adminPass', 'rescue_image_ref'])) - else: - assert body[action] is None - _body = {'adminPass': 'RescuePassword'} - elif action == 'unrescue': - assert body[action] is None - elif action == 'resume': - assert body[action] is None - elif action == 'suspend': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'shelve': - assert body[action] is None - elif action == 'shelveOffload': - assert body[action] is None - elif action == 'unshelve': - assert body[action] is None - elif action == 'addFixedIp': - assert list(body[action]) == ['networkId'] - elif action == 'removeFixedIp': - assert list(body[action]) == ['address'] - elif action == 'addFloatingIp': - assert (list(body[action]) == ['address'] or - sorted(list(body[action])) == ['address', - 'fixed_address']) - elif action == 'removeFloatingIp': - assert list(body[action]) == ['address'] - elif action == 'createImage': - assert set(body[action].keys()) == set(['name', 'metadata']) - context.headers['location'] = "http://blah/images/456" - elif action == 'changePassword': - assert list(body[action]) == ['adminPass'] - elif action == 'os-getConsoleOutput': - assert list(body[action]) == ['length'] - context.status_code = 202 - return {'output': 'foo'} - elif action == 'os-getVNCConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getSPICEConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getRDPConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getSerialConsole': - assert list(body[action]) == ['type'] - elif action == 'os-migrateLive': - assert set(body[action].keys()) == set(['host', - 'block_migration', - 'disk_over_commit']) - elif action == 'os-resetState': - assert list(body[action]) == ['state'] - elif action == 'resetNetwork': - assert body[action] is None - elif action == 'addSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'removeSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'createBackup': - assert set(body[action]) == set(['name', - 'backup_type', - 'rotation']) - elif action == 'evacuate': - keys = list(body[action]) - if 'adminPass' in keys: - keys.remove('adminPass') - assert set(keys) == set(['host', 'onSharedStorage']) - else: - raise AssertionError("Unexpected server action: %s" % action) - return {'server': _body} diff --git a/awx/lib/site-packages/novaclient/tests/unit/idfake.pem b/awx/lib/site-packages/novaclient/tests/unit/idfake.pem deleted file mode 100644 index f7b4466419..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/idfake.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA9QstF/7prDY7a9La7GS9TpMX+MWWXQgK6pHRLakDFp1WX1Q3 -Vly7rWitaZUGirUPMm181oJXBwkKlAxFD7hKjyHYaSswNszPYIAsVkc1+AO5epXz -g9kUBNtfg44Pg72UecwLrZ8JpmNZpJlKQOx6vF+yi7JmHrrIf6il/grIGUPzoT2L -yReimpyPoBrGtXhJYaCJ/XbKg1idRZiQdmwh1F/OmZWn9p0wunnsv08a0+qIywuw -WhG9/Zy9fjnEByfusS6gI0GIxDRL4RWzOqphd3PZzunwIBgEKFhgiki9+2DgcRVO -9I5wnDvfwQREJRZWh1uJa5ZTcfPa1EzZryVeOQIDAQABAoIBABxO3Te/cBk/7p9n -LXlPrfrszUEk+ljm+/PbQpIGy1+Kb5b1sKrebaP7ysS+vZG6lvXZZimVxx398mXm -APhu7tYYL9r+bUR3ZqGcTQLumRJ8w6mgtxANPN3Oxfr5p1stxIBJjTPSgpfhNFLq -joRvjUJDv+mZg2ibZVwyDHMLpdAdKp+3XMdyTLZcH9esqwii+natix7rHd1RuF85 -L1dfpxjkItwhgHsfdYS++5X3fRByFOhQ+Nhabh/kPQbQMcteRn1bN6zeCWBSglNb -Ka/ZrXb6ApRUc22Ji62mNO2ZPPekLJeCHk2h2E7ezYX+sGDNvvd/jHVDJJ20FjD1 -Z9KXuK0CgYEA/2vniy9yWd925QQtWbmrxgy6yj89feMH/LTv4qP298rGZ2nqxsyd -9pdBdb4NMsi4HmV5PG1hp3VRNBHl53DNh5eqzT8WEXnIF+sbrIU3KzrCVAx1kZTl -+OWKA6aVUsvvO3y85SOvInnsV+IsOGmU4/WBSjYoe39Bo7mq/YuZB9MCgYEA9ZlB -KBm6PjFdHQGNgedXahWzRcwC+ALCYqequPYqJolNzhrK4Uc2sWPSGdnldcHZ4XCQ -wbfCxUSwrMpA1oyuIQ0U4aowmOw5DjIueBWI8XBYEVRBlwvJwbXpBZ/DspGzTUDx -MBrrEwEaMadQvxhRnAzhp0rQAepatcz6Fgb1JkMCgYBMwDLiew5kfSav6JJsDMPW -DksurNQgeNEUmZYfx19V1EPMHWKj/CZXS9oqtEIpCXFyCNHmW4PlmvYcrGgmJJpN -7UAwzo0mES8UKNy2+Yy7W7u7H8dQSKrWILtZH3xtVcR8Xp4wSIm+1V40hkz9YpSP -71y7XQzLF1E1DnyYFZOVawKBgAFrmHfd5jjT2kD/sEzPBK9lXrsJmf7LLUqaw578 -NXQxmRSXDRNOcR+Hf0CNBQmwTE1EdGHaaTLw2cC2Drfu6lbgl31SmaNYwl+1pJUn -MrqKtseq4BI6jDkljypsKRqQQyQwOvTXQwLCH9+nowzn3Bj17hwkj51jOJESlWOp -OKO3AoGBALm+jjqyqX7gSnqK3FAumB8mlhv3yI1Wr1ctwe18mKfKbz17HxXRu9pF -K/6e7WMCA1p+jhoE8gj1h2WBcH0nV2qt8Ye8gJBbCi4dhI08o4AfrIV47oZx1RlO -qYcA1U9lyaODY5SL8+6PHOy5J/aYtuA+wvfEnWiCIdKQrhWetcn3 ------END RSA PRIVATE KEY----- diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_auth_plugins.py b/awx/lib/site-packages/novaclient/tests/unit/test_auth_plugins.py deleted file mode 100644 index 675102ca35..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_auth_plugins.py +++ /dev/null @@ -1,328 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -from keystoneclient import fixture -import mock -import pkg_resources -import requests - -try: - import json -except ImportError: - import simplejson as json - -from novaclient import auth_plugin -from novaclient import exceptions -from novaclient.tests.unit import utils -from novaclient.v2 import client - - -def mock_http_request(resp=None): - """Mock an HTTP Request.""" - if not resp: - resp = fixture.V2Token() - resp.set_scope() - s = resp.add_service('compute') - s.add_endpoint("http://localhost:8774/v1.1", region='RegionOne') - - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - return mock.Mock(return_value=(auth_response)) - - -def requested_headers(cs): - """Return requested passed headers.""" - return { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - - -class DeprecatedAuthPluginTest(utils.TestCase): - def test_auth_system_success(self): - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.authenticate - - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - def mock_iter_entry_points(_type, name): - if _type == 'openstack.client.authenticate': - return [MockEntrypoint("fake", "fake", ["fake"])] - else: - return [] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - plugin = auth_plugin.DeprecatedAuthPlugin("fake") - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, auth_system="fake", - auth_plugin=plugin) - cs.client.authenticate() - - headers = requested_headers(cs) - token_url = cs.client.auth_url + "/tokens" - - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data='{"fake": "me"}', - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - test_auth_call() - - def test_auth_system_not_exists(self): - def mock_iter_entry_points(_t, name=None): - return [pkg_resources.EntryPoint("fake", "fake", ["fake"])] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - auth_plugin.discover_auth_systems() - plugin = auth_plugin.DeprecatedAuthPlugin("notexists") - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, auth_system="notexists", - auth_plugin=plugin) - self.assertRaises(exceptions.AuthSystemNotFound, - cs.client.authenticate) - - test_auth_call() - - def test_auth_system_defining_auth_url(self): - class MockAuthUrlEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.auth_url - - def auth_url(self): - return "http://faked/v2.0" - - class MockAuthenticateEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.authenticate - - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - def mock_iter_entry_points(_type, name): - if _type == 'openstack.client.auth_url': - return [MockAuthUrlEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["auth_url"])] - elif _type == 'openstack.client.authenticate': - return [MockAuthenticateEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["authenticate"])] - else: - return [] - - mock_request = mock_http_request() - - @mock.patch.object(pkg_resources, "iter_entry_points", - mock_iter_entry_points) - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl") - cs = client.Client("username", "password", "project_id", - auth_system="fakewithauthurl", - auth_plugin=plugin) - cs.client.authenticate() - self.assertEqual("http://faked/v2.0", cs.client.auth_url) - - test_auth_call() - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_client_raises_exc_without_auth_url(self, mock_iter_entry_points): - class MockAuthUrlEntrypoint(pkg_resources.EntryPoint): - def load(self): - return self.auth_url - - def auth_url(self): - return None - - mock_iter_entry_points.side_effect = lambda _t, name: [ - MockAuthUrlEntrypoint("fakewithauthurl", - "fakewithauthurl", - ["auth_url"])] - - plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl") - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fakewithauthurl", auth_plugin=plugin) - - -class AuthPluginTest(utils.TestCase): - @mock.patch.object(requests, "request") - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_auth_system_success(self, mock_iter_entry_points, mock_request): - """Test that we can authenticate using the auth system.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def authenticate(self, cls, auth_url): - cls._authenticate(auth_url, {"fake": "me"}) - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - mock_request.side_effect = mock_http_request() - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, auth_system="fake", - auth_plugin=plugin) - cs.client.authenticate() - - headers = requested_headers(cs) - token_url = cs.client.auth_url + "/tokens" - - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data='{"fake": "me"}', - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_discover_auth_system_options(self, mock_iter_entry_points): - """Test that we can load the auth system options.""" - class FakePlugin(auth_plugin.BaseAuthPlugin): - @staticmethod - def add_opts(parser): - parser.add_argument('--auth_system_opt', - default=False, - action='store_true', - help="Fake option") - return parser - - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - parser = argparse.ArgumentParser() - auth_plugin.discover_auth_systems() - auth_plugin.load_auth_system_opts(parser) - opts, args = parser.parse_known_args(['--auth_system_opt']) - - self.assertTrue(opts.auth_system_opt) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_parse_auth_system_options(self, mock_iter_entry_points): - """Test that we can parse the auth system options.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def __init__(self): - self.opts = {"fake_argument": True} - - def parse_opts(self, args): - return self.opts - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - plugin.parse_opts([]) - self.assertIn("fake_argument", plugin.opts) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_auth_system_defining_url(self, mock_iter_entry_points): - """Test the auth_system defining an url.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - def get_auth_url(self): - return "http://faked/v2.0" - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - cs = client.Client("username", "password", "project_id", - auth_system="fakewithauthurl", - auth_plugin=plugin) - self.assertEqual("http://faked/v2.0", cs.client.auth_url) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_exception_if_no_authenticate(self, mock_iter_entry_points): - """Test that no authenticate raises a proper exception.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - pass - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fake", auth_plugin=plugin) - - @mock.patch.object(pkg_resources, "iter_entry_points") - def test_exception_if_no_url(self, mock_iter_entry_points): - """Test that no auth_url at all raises exception.""" - class MockEntrypoint(pkg_resources.EntryPoint): - def load(self): - return FakePlugin - - class FakePlugin(auth_plugin.BaseAuthPlugin): - pass - - mock_iter_entry_points.side_effect = lambda _t: [ - MockEntrypoint("fake", "fake", ["FakePlugin"])] - - auth_plugin.discover_auth_systems() - plugin = auth_plugin.load_plugin("fake") - - self.assertRaises( - exceptions.EndpointNotFound, - client.Client, "username", "password", "project_id", - auth_system="fake", auth_plugin=plugin) diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_base.py b/awx/lib/site-packages/novaclient/tests/unit/test_base.py deleted file mode 100644 index b7bceb7b86..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_base.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient import exceptions -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2 import fakes -from novaclient.v2 import flavors - - -cs = fakes.FakeClient() - - -class BaseTest(utils.TestCase): - - def test_resource_repr(self): - r = base.Resource(None, dict(foo="bar", baz="spam")) - self.assertEqual("", repr(r)) - - def test_getid(self): - self.assertEqual(4, base.getid(4)) - - class TmpObject(object): - id = 4 - self.assertEqual(4, base.getid(TmpObject)) - - def test_resource_lazy_getattr(self): - f = flavors.Flavor(cs.flavors, {'id': 1}) - self.assertEqual('256 MB Server', f.name) - cs.assert_called('GET', '/flavors/1') - - # Missing stuff still fails after a second get - self.assertRaises(AttributeError, getattr, f, 'blahblah') - - def test_eq(self): - # Two resources of the same type with the same id: equal - r1 = base.Resource(None, {'id': 1, 'name': 'hi'}) - r2 = base.Resource(None, {'id': 1, 'name': 'hello'}) - self.assertEqual(r1, r2) - - # Two resoruces of different types: never equal - r1 = base.Resource(None, {'id': 1}) - r2 = flavors.Flavor(None, {'id': 1}) - self.assertNotEqual(r1, r2) - - # Two resources with no ID: equal if their info is equal - r1 = base.Resource(None, {'name': 'joe', 'age': 12}) - r2 = base.Resource(None, {'name': 'joe', 'age': 12}) - self.assertEqual(r1, r2) - - def test_findall_invalid_attribute(self): - # Make sure findall with an invalid attribute doesn't cause errors. - # The following should not raise an exception. - cs.flavors.findall(vegetable='carrot') - - # However, find() should raise an error - self.assertRaises(exceptions.NotFound, - cs.flavors.find, - vegetable='carrot') diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_client.py b/awx/lib/site-packages/novaclient/tests/unit/test_client.py deleted file mode 100644 index 8ed7cb9f3f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_client.py +++ /dev/null @@ -1,368 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import json -import logging - -import fixtures -import mock -import requests - -import novaclient.client -import novaclient.extension -from novaclient.tests.unit import utils -import novaclient.v2.client - - -class ClientConnectionPoolTest(utils.TestCase): - - @mock.patch("novaclient.client.TCPKeepAliveAdapter") - def test_get(self, mock_http_adapter): - mock_http_adapter.side_effect = lambda: mock.Mock() - pool = novaclient.client._ClientConnectionPool() - self.assertEqual(pool.get("abc"), pool.get("abc")) - self.assertNotEqual(pool.get("abc"), pool.get("def")) - - -class ClientTest(utils.TestCase): - - def test_client_with_timeout(self): - instance = novaclient.client.HTTPClient(user='user', - password='password', - projectid='project', - timeout=2, - auth_url="http://www.blah.com") - self.assertEqual(2, instance.timeout) - mock_request = mock.Mock() - mock_request.return_value = requests.Response() - mock_request.return_value.status_code = 200 - mock_request.return_value.headers = { - 'x-server-management-url': 'blah.com', - 'x-auth-token': 'blah', - } - with mock.patch('requests.request', mock_request): - instance.authenticate() - requests.request.assert_called_with( - mock.ANY, mock.ANY, timeout=2, headers=mock.ANY, - verify=mock.ANY) - - def test_client_reauth(self): - instance = novaclient.client.HTTPClient(user='user', - password='password', - projectid='project', - timeout=2, - auth_url="http://www.blah.com") - instance.auth_token = 'foobar' - instance.management_url = 'http://example.com' - instance.version = 'v2.0' - mock_request = mock.Mock() - mock_request.side_effect = novaclient.exceptions.Unauthorized(401) - with mock.patch('requests.request', mock_request): - try: - instance.get('/servers/detail') - except Exception: - pass - get_headers = {'X-Auth-Project-Id': 'project', - 'X-Auth-Token': 'foobar', - 'User-Agent': 'python-novaclient', - 'Accept': 'application/json'} - reauth_headers = {'Content-Type': 'application/json', - 'Accept': 'application/json', - 'User-Agent': 'python-novaclient'} - data = { - "auth": { - "tenantName": "project", - "passwordCredentials": { - "username": "user", - "password": "password" - } - } - } - - expected = [mock.call('GET', - 'http://example.com/servers/detail', - timeout=mock.ANY, - headers=get_headers, - verify=mock.ANY), - mock.call('POST', 'http://www.blah.com/tokens', - timeout=mock.ANY, - headers=reauth_headers, - allow_redirects=mock.ANY, - data=mock.ANY, - verify=mock.ANY)] - self.assertEqual(expected, mock_request.call_args_list) - token_post_call = mock_request.call_args_list[1] - self.assertEqual(data, json.loads(token_post_call[1]['data'])) - - @mock.patch.object(novaclient.client.HTTPClient, 'request', - return_value=(200, "{'versions':[]}")) - def _check_version_url(self, management_url, version_url, mock_request): - projectid = '25e469aa1848471b875e68cde6531bc5' - instance = novaclient.client.HTTPClient(user='user', - password='password', - projectid=projectid, - auth_url="http://www.blah.com") - instance.auth_token = 'foobar' - instance.management_url = management_url % projectid - instance.version = 'v2.0' - - # If passing None as the part of url, a client accesses the url which - # doesn't include "v2/" for getting API version info. - instance.get(None) - mock_request.assert_called_once_with(version_url, 'GET', - headers=mock.ANY) - mock_request.reset_mock() - - # Otherwise, a client accesses the url which includes "v2/". - instance.get('servers') - url = instance.management_url + 'servers' - mock_request.assert_called_once_with(url, 'GET', headers=mock.ANY) - - def test_client_version_url(self): - self._check_version_url('http://foo.com/v2/%s', 'http://foo.com/') - - def test_client_version_url_with_project_name(self): - self._check_version_url('http://foo.com/nova/v2/%s', - 'http://foo.com/nova/') - - def test_get_client_class_v3(self): - output = novaclient.client.get_client_class('3') - self.assertEqual(output, novaclient.v2.client.Client) - - def test_get_client_class_v2(self): - output = novaclient.client.get_client_class('2') - self.assertEqual(output, novaclient.v2.client.Client) - - def test_get_client_class_v2_int(self): - output = novaclient.client.get_client_class(2) - self.assertEqual(output, novaclient.v2.client.Client) - - def test_get_client_class_v1_1(self): - output = novaclient.client.get_client_class('1.1') - self.assertEqual(output, novaclient.v2.client.Client) - - def test_get_client_class_unknown(self): - self.assertRaises(novaclient.exceptions.UnsupportedVersion, - novaclient.client.get_client_class, '0') - - def test_client_with_os_cache_enabled(self): - cs = novaclient.v2.client.Client("user", "password", "project_id", - auth_url="foo/v2", os_cache=True) - self.assertEqual(True, cs.os_cache) - self.assertEqual(True, cs.client.os_cache) - - def test_client_with_os_cache_disabled(self): - cs = novaclient.v2.client.Client("user", "password", "project_id", - auth_url="foo/v2", os_cache=False) - self.assertEqual(False, cs.os_cache) - self.assertEqual(False, cs.client.os_cache) - - def test_client_with_no_cache_enabled(self): - cs = novaclient.v2.client.Client("user", "password", "project_id", - auth_url="foo/v2", no_cache=True) - self.assertEqual(False, cs.os_cache) - self.assertEqual(False, cs.client.os_cache) - - def test_client_with_no_cache_disabled(self): - cs = novaclient.v2.client.Client("user", "password", "project_id", - auth_url="foo/v2", no_cache=False) - self.assertEqual(True, cs.os_cache) - self.assertEqual(True, cs.client.os_cache) - - def test_client_set_management_url_v1_1(self): - cs = novaclient.v2.client.Client("user", "password", "project_id", - auth_url="foo/v2") - cs.set_management_url("blabla") - self.assertEqual("blabla", cs.client.management_url) - - def test_client_get_reset_timings_v1_1(self): - cs = novaclient.v2.client.Client("user", "password", "project_id", - auth_url="foo/v2") - self.assertEqual(0, len(cs.get_timings())) - cs.client.times.append("somevalue") - self.assertEqual(1, len(cs.get_timings())) - self.assertEqual("somevalue", cs.get_timings()[0]) - - cs.reset_timings() - self.assertEqual(0, len(cs.get_timings())) - - @mock.patch('novaclient.client.HTTPClient') - def test_contextmanager_v1_1(self, mock_http_client): - fake_client = mock.Mock() - mock_http_client.return_value = fake_client - with novaclient.v2.client.Client("user", "password", "project_id", - auth_url="foo/v2"): - pass - self.assertTrue(fake_client.open_session.called) - self.assertTrue(fake_client.close_session.called) - - def test_get_password_simple(self): - cs = novaclient.client.HTTPClient("user", "password", "", "") - cs.password_func = mock.Mock() - self.assertEqual("password", cs._get_password()) - self.assertFalse(cs.password_func.called) - - def test_get_password_none(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - self.assertIsNone(cs._get_password()) - - def test_get_password_func(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - cs.password_func = mock.Mock(return_value="password") - self.assertEqual("password", cs._get_password()) - cs.password_func.assert_called_once_with() - - cs.password_func = mock.Mock() - self.assertEqual("password", cs._get_password()) - self.assertFalse(cs.password_func.called) - - def test_auth_url_rstrip_slash(self): - cs = novaclient.client.HTTPClient("user", "password", "project_id", - auth_url="foo/v2/") - self.assertEqual("foo/v2", cs.auth_url) - - def test_token_and_bypass_url(self): - cs = novaclient.client.HTTPClient(None, None, None, - auth_token="12345", - bypass_url="compute/v100/") - self.assertIsNone(cs.auth_url) - self.assertEqual("12345", cs.auth_token) - self.assertEqual("compute/v100", cs.bypass_url) - self.assertEqual("compute/v100", cs.management_url) - - @mock.patch("novaclient.client.requests.Session") - def test_session(self, mock_session): - fake_session = mock.Mock() - mock_session.return_value = fake_session - cs = novaclient.client.HTTPClient("user", None, "", "") - cs.open_session() - self.assertEqual(cs._session, fake_session) - cs.close_session() - self.assertIsNone(cs._session) - - def test_session_connection_pool(self): - cs = novaclient.client.HTTPClient("user", None, "", - "", connection_pool=True) - cs.open_session() - self.assertIsNone(cs._session) - cs.close_session() - self.assertIsNone(cs._session) - - def test_get_session(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - self.assertIsNone(cs._get_session("http://nooooooooo.com")) - - @mock.patch("novaclient.client.requests.Session") - def test_get_session_open_session(self, mock_session): - fake_session = mock.Mock() - mock_session.return_value = fake_session - cs = novaclient.client.HTTPClient("user", None, "", "") - cs.open_session() - self.assertEqual(fake_session, cs._get_session("http://example.com")) - - @mock.patch("novaclient.client.requests.Session") - @mock.patch("novaclient.client._ClientConnectionPool") - def test_get_session_connection_pool(self, mock_pool, mock_session): - service_url = "http://example.com" - - pool = mock.MagicMock() - pool.get.return_value = "http_adapter" - mock_pool.return_value = pool - cs = novaclient.client.HTTPClient("user", None, "", - "", connection_pool=True) - cs._current_url = "http://another.com" - - session = cs._get_session(service_url) - self.assertEqual(session, mock_session.return_value) - pool.get.assert_called_once_with(service_url) - mock_session().mount.assert_called_once_with(service_url, - 'http_adapter') - - def test_init_without_connection_pool(self): - cs = novaclient.client.HTTPClient("user", None, "", "") - self.assertIsNone(cs._connection_pool) - - @mock.patch("novaclient.client._ClientConnectionPool") - def test_init_with_proper_connection_pool(self, mock_pool): - fake_pool = mock.Mock() - mock_pool.return_value = fake_pool - cs = novaclient.client.HTTPClient("user", None, "", - connection_pool=True) - self.assertEqual(cs._connection_pool, fake_pool) - - def test_log_req(self): - self.logger = self.useFixture( - fixtures.FakeLogger( - format="%(message)s", - level=logging.DEBUG, - nuke_handlers=True - ) - ) - cs = novaclient.client.HTTPClient("user", None, "", - connection_pool=True) - cs.http_log_debug = True - cs.http_log_req('GET', '/foo', {'headers': {}}) - cs.http_log_req('GET', '/foo', {'headers': - {'X-Auth-Token': 'totally_bogus'}}) - cs.http_log_req('GET', '/foo', {'headers': - {'X-Foo': 'bar', - 'X-Auth-Token': 'totally_bogus'}}) - cs.http_log_req('GET', '/foo', {'headers': {}, - 'data': - '{"auth": {"passwordCredentials": ' - '{"password": "zhaoqin"}}}'}) - - output = self.logger.output.split('\n') - - self.assertIn("REQ: curl -g -i '/foo' -X GET", output) - self.assertIn( - "REQ: curl -g -i '/foo' -X GET -H " - '"X-Auth-Token: {SHA1}b42162b6ffdbd7c3c37b7c95b7ba9f51dda0236d"', - output) - self.assertIn( - "REQ: curl -g -i '/foo' -X GET -H " - '"X-Auth-Token: {SHA1}b42162b6ffdbd7c3c37b7c95b7ba9f51dda0236d"' - ' -H "X-Foo: bar"', - output) - self.assertIn( - "REQ: curl -g -i '/foo' -X GET -d " - '\'{"auth": {"passwordCredentials": {"password":' - ' "{SHA1}4fc49c6a671ce889078ff6b250f7066cf6d2ada2"}}}\'', - output) - - def test_log_resp(self): - self.logger = self.useFixture( - fixtures.FakeLogger( - format="%(message)s", - level=logging.DEBUG, - nuke_handlers=True - ) - ) - - cs = novaclient.client.HTTPClient("user", None, "", - connection_pool=True) - cs.http_log_debug = True - text = ('{"access": {"token": {"id": "zhaoqin"}}}') - resp = utils.TestResponse({'status_code': 200, 'headers': {}, - 'text': text}) - - cs.http_log_resp(resp) - output = self.logger.output.split('\n') - - self.assertIn('RESP: [200] {}', output) - self.assertIn('RESP BODY: {"access": {"token": {"id":' - ' "{SHA1}4fc49c6a671ce889078ff6b250f7066cf6d2ada2"}}}', - output) diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_discover.py b/awx/lib/site-packages/novaclient/tests/unit/test_discover.py deleted file mode 100644 index f8414c664f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_discover.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import imp -import inspect - -import mock -import pkg_resources - -import novaclient.shell -from novaclient.tests.unit import utils - - -class DiscoverTest(utils.TestCase): - - def test_discover_via_entry_points(self): - - def mock_iter_entry_points(group): - if group == 'novaclient.extension': - fake_ep = mock.Mock() - fake_ep.name = 'foo' - fake_ep.module = imp.new_module('foo') - fake_ep.load.return_value = fake_ep.module - return [fake_ep] - - @mock.patch.object(pkg_resources, 'iter_entry_points', - mock_iter_entry_points) - def test(): - shell = novaclient.shell.OpenStackComputeShell() - for name, module in shell._discover_via_entry_points(): - self.assertEqual('foo', name) - self.assertTrue(inspect.ismodule(module)) - - test() - - def test_discover_extensions(self): - - def mock_discover_via_python_path(self): - yield 'foo', imp.new_module('foo') - - def mock_discover_via_contrib_path(self, version): - yield 'bar', imp.new_module('bar') - - def mock_discover_via_entry_points(self): - yield 'baz', imp.new_module('baz') - - @mock.patch.object(novaclient.shell.OpenStackComputeShell, - '_discover_via_python_path', - mock_discover_via_python_path) - @mock.patch.object(novaclient.shell.OpenStackComputeShell, - '_discover_via_contrib_path', - mock_discover_via_contrib_path) - @mock.patch.object(novaclient.shell.OpenStackComputeShell, - '_discover_via_entry_points', - mock_discover_via_entry_points) - def test(): - shell = novaclient.shell.OpenStackComputeShell() - extensions = shell._discover_extensions('1.1') - self.assertEqual(3, len(extensions)) - names = sorted(['foo', 'bar', 'baz']) - sorted_extensions = sorted(extensions, key=lambda ext: ext.name) - for i in range(len(names)): - ext = sorted_extensions[i] - name = names[i] - self.assertEqual(ext.name, name) - self.assertTrue(inspect.ismodule(ext.module)) - - test() diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_http.py b/awx/lib/site-packages/novaclient/tests/unit/test_http.py deleted file mode 100644 index 5e676828a2..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_http.py +++ /dev/null @@ -1,216 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import requests -import six - -from novaclient import client -from novaclient import exceptions -from novaclient.tests.unit import utils - - -fake_response = utils.TestResponse({ - "status_code": 200, - "text": '{"hi": "there"}', -}) -mock_request = mock.Mock(return_value=(fake_response)) - -refused_response = utils.TestResponse({ - "status_code": 400, - "text": '[Errno 111] Connection refused', -}) -refused_mock_request = mock.Mock(return_value=(refused_response)) - -bad_req_response = utils.TestResponse({ - "status_code": 400, - "text": '', -}) -bad_req_mock_request = mock.Mock(return_value=(bad_req_response)) - -unknown_error_response = utils.TestResponse({ - "status_code": 503, - "text": '', -}) -unknown_error_mock_request = mock.Mock(return_value=unknown_error_response) - -retry_after_response = utils.TestResponse({ - "status_code": 413, - "text": '', - "headers": { - "retry-after": "5" - }, -}) -retry_after_mock_request = mock.Mock(return_value=retry_after_response) - -retry_after_no_headers_response = utils.TestResponse({ - "status_code": 413, - "text": '', -}) -retry_after_no_headers_mock_request = mock.Mock( - return_value=retry_after_no_headers_response) - -retry_after_non_supporting_response = utils.TestResponse({ - "status_code": 403, - "text": '', - "headers": { - "retry-after": "5" - }, -}) -retry_after_non_supporting_mock_request = mock.Mock( - return_value=retry_after_non_supporting_response) - - -def get_client(): - cl = client.HTTPClient("username", "password", - "project_id", - utils.AUTH_URL_V2) - return cl - - -def get_authed_client(): - cl = get_client() - cl.management_url = "http://example.com" - cl.auth_token = "token" - return cl - - -class ClientTest(utils.TestCase): - - def test_get(self): - cl = get_authed_client() - - @mock.patch.object(requests, "request", mock_request) - @mock.patch('time.time', mock.Mock(return_value=1234)) - def test_get_call(): - resp, body = cl.get("/hi") - headers = {"X-Auth-Token": "token", - "X-Auth-Project-Id": "project_id", - "User-Agent": cl.USER_AGENT, - 'Accept': 'application/json'} - mock_request.assert_called_with( - "GET", - "http://example.com/hi", - headers=headers, - **self.TEST_REQUEST_BASE) - # Automatic JSON parsing - self.assertEqual({"hi": "there"}, body) - - test_get_call() - - def test_post(self): - cl = get_authed_client() - - @mock.patch.object(requests, "request", mock_request) - def test_post_call(): - cl.post("/hi", body=[1, 2, 3]) - headers = { - "X-Auth-Token": "token", - "X-Auth-Project-Id": "project_id", - "Content-Type": "application/json", - 'Accept': 'application/json', - "User-Agent": cl.USER_AGENT - } - mock_request.assert_called_with( - "POST", - "http://example.com/hi", - headers=headers, - data='[1, 2, 3]', - **self.TEST_REQUEST_BASE) - - test_post_call() - - def test_auth_failure(self): - cl = get_client() - - # response must not have x-server-management-url header - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.AuthorizationFailure, cl.authenticate) - - test_auth_call() - - def test_auth_failure_due_to_miss_of_auth_url(self): - cl = client.HTTPClient("username", "password") - - self.assertRaises(exceptions.AuthorizationFailure, cl.authenticate) - - def test_connection_refused(self): - cl = get_client() - - @mock.patch.object(requests, "request", refused_mock_request) - def test_refused_call(): - self.assertRaises(exceptions.ConnectionRefused, cl.get, "/hi") - - test_refused_call() - - def test_bad_request(self): - cl = get_client() - - @mock.patch.object(requests, "request", bad_req_mock_request) - def test_refused_call(): - self.assertRaises(exceptions.BadRequest, cl.get, "/hi") - - test_refused_call() - - def test_client_logger(self): - cl1 = client.HTTPClient("username", "password", "project_id", - "auth_test", http_log_debug=True) - self.assertEqual(1, len(cl1._logger.handlers)) - - cl2 = client.HTTPClient("username", "password", "project_id", - "auth_test", http_log_debug=True) - self.assertEqual(1, len(cl2._logger.handlers)) - - @mock.patch.object(requests, 'request', unknown_error_mock_request) - def test_unknown_server_error(self): - cl = get_client() - # This would be cleaner with the context manager version of - # assertRaises or assertRaisesRegexp, but both only appeared in - # Python 2.7 and testtools doesn't match that implementation yet - try: - cl.get('/hi') - except exceptions.ClientException as exc: - self.assertIn('Unknown Error', six.text_type(exc)) - else: - self.fail('Expected exceptions.ClientException') - - @mock.patch.object(requests, "request", retry_after_mock_request) - def test_retry_after_request(self): - cl = get_client() - - try: - cl.get("/hi") - except exceptions.OverLimit as exc: - self.assertEqual(5, exc.retry_after) - else: - self.fail('Expected exceptions.OverLimit') - - @mock.patch.object(requests, "request", - retry_after_no_headers_mock_request) - def test_retry_after_request_no_headers(self): - cl = get_client() - - try: - cl.get("/hi") - except exceptions.OverLimit as exc: - self.assertEqual(0, exc.retry_after) - else: - self.fail('Expected exceptions.OverLimit') - - @mock.patch.object(requests, "request", - retry_after_non_supporting_mock_request) - def test_retry_after_request_non_supporting_exc(self): - cl = get_client() - - self.assertRaises(exceptions.Forbidden, cl.get, "/hi") diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_service_catalog.py b/awx/lib/site-packages/novaclient/tests/unit/test_service_catalog.py deleted file mode 100644 index 33be77791e..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_service_catalog.py +++ /dev/null @@ -1,73 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from keystoneclient import fixture - -from novaclient import exceptions -from novaclient import service_catalog -from novaclient.tests.unit import utils - - -SERVICE_CATALOG = fixture.V2Token() -SERVICE_CATALOG.set_scope() - -_s = SERVICE_CATALOG.add_service('compute') -_e = _s.add_endpoint("https://compute1.host/v1/1") -_e["tenantId"] = "1" -_e["versionId"] = "1.0" -_e = _s.add_endpoint("https://compute1.host/v1.1/2", region="North") -_e["tenantId"] = "2" -_e["versionId"] = "1.1" -_e = _s.add_endpoint("https://compute1.host/v2/1", region="North") -_e["tenantId"] = "1" -_e["versionId"] = "2" - -_s = SERVICE_CATALOG.add_service('volume') -_e = _s.add_endpoint("https://volume1.host/v1/1", region="South") -_e["tenantId"] = "1" -_e = _s.add_endpoint("https://volume1.host/v1.1/2", region="South") -_e["tenantId"] = "2" - - -class ServiceCatalogTest(utils.TestCase): - def test_building_a_service_catalog(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - service_type='compute') - self.assertEqual("https://compute1.host/v2/1", - sc.url_for('tenantId', '1', service_type='compute')) - self.assertEqual("https://compute1.host/v1.1/2", - sc.url_for('tenantId', '2', service_type='compute')) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - "region", "South", service_type='compute') - - def test_building_a_service_catalog_insensitive_case(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - # Matching south (and catalog has South). - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - 'region', 'south', service_type='volume') - - def test_alternate_service_type(self): - sc = service_catalog.ServiceCatalog(SERVICE_CATALOG) - - self.assertRaises(exceptions.AmbiguousEndpoints, sc.url_for, - service_type='volume') - self.assertEqual("https://volume1.host/v1/1", - sc.url_for('tenantId', '1', service_type='volume')) - self.assertEqual("https://volume1.host/v1.1/2", - sc.url_for('tenantId', '2', service_type='volume')) - - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - "region", "North", service_type='volume') diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_shell.py b/awx/lib/site-packages/novaclient/tests/unit/test_shell.py deleted file mode 100644 index e0995113bb..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_shell.py +++ /dev/null @@ -1,389 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import distutils.version as dist_version -import re -import sys - -import fixtures -from keystoneclient import fixture -import mock -import prettytable -import requests_mock -import six -from testtools import matchers - -import novaclient.client -from novaclient import exceptions -import novaclient.shell -from novaclient.tests.unit import utils - -FAKE_ENV = {'OS_USERNAME': 'username', - 'OS_PASSWORD': 'password', - 'OS_TENANT_NAME': 'tenant_name', - 'OS_AUTH_URL': 'http://no.where/v2.0'} - -FAKE_ENV2 = {'OS_USER_ID': 'user_id', - 'OS_PASSWORD': 'password', - 'OS_TENANT_ID': 'tenant_id', - 'OS_AUTH_URL': 'http://no.where/v2.0'} - -FAKE_ENV3 = {'OS_USER_ID': 'user_id', - 'OS_PASSWORD': 'password', - 'OS_TENANT_ID': 'tenant_id', - 'OS_AUTH_URL': 'http://no.where/v2.0', - 'NOVA_ENDPOINT_TYPE': 'novaURL', - 'OS_ENDPOINT_TYPE': 'osURL'} - -FAKE_ENV4 = {'OS_USER_ID': 'user_id', - 'OS_PASSWORD': 'password', - 'OS_TENANT_ID': 'tenant_id', - 'OS_AUTH_URL': 'http://no.where/v2.0', - 'NOVA_ENDPOINT_TYPE': 'internal', - 'OS_ENDPOINT_TYPE': 'osURL'} - - -def _create_ver_list(versions): - return {'versions': {'values': versions}} - - -class ParserTest(utils.TestCase): - - def setUp(self): - super(ParserTest, self).setUp() - self.parser = novaclient.shell.NovaClientArgumentParser() - - def test_ambiguous_option(self): - self.parser.add_argument('--tic') - self.parser.add_argument('--tac') - - try: - self.parser.parse_args(['--t']) - except SystemExit as err: - self.assertEqual(2, err.code) - else: - self.fail('SystemExit not raised') - - def test_not_really_ambiguous_option(self): - # current/deprecated forms of the same option - self.parser.add_argument('--tic-tac', action="store_true") - self.parser.add_argument('--tic_tac', action="store_true") - args = self.parser.parse_args(['--tic']) - self.assertTrue(args.tic_tac) - - -class ShellTest(utils.TestCase): - - _msg_no_tenant_project = ("You must provide a project name or project" - " id via --os-project-name, --os-project-id," - " env[OS_PROJECT_ID] or env[OS_PROJECT_NAME]." - " You may use os-project and os-tenant" - " interchangeably.") - - def make_env(self, exclude=None, fake_env=FAKE_ENV): - env = dict((k, v) for k, v in fake_env.items() if k != exclude) - self.useFixture(fixtures.MonkeyPatch('os.environ', env)) - - def setUp(self): - super(ShellTest, self).setUp() - self.useFixture(fixtures.MonkeyPatch( - 'novaclient.client.get_client_class', - mock.MagicMock)) - self.nc_util = mock.patch( - 'novaclient.openstack.common.cliutils.isunauthenticated').start() - self.nc_util.return_value = False - - def shell(self, argstr, exitcodes=(0,)): - orig = sys.stdout - orig_stderr = sys.stderr - try: - sys.stdout = six.StringIO() - sys.stderr = six.StringIO() - _shell = novaclient.shell.OpenStackComputeShell() - _shell.main(argstr.split()) - except SystemExit: - exc_type, exc_value, exc_traceback = sys.exc_info() - self.assertIn(exc_value.code, exitcodes) - finally: - stdout = sys.stdout.getvalue() - sys.stdout.close() - sys.stdout = orig - stderr = sys.stderr.getvalue() - sys.stderr.close() - sys.stderr = orig_stderr - return (stdout, stderr) - - def register_keystone_discovery_fixture(self, mreq): - v2_url = "http://no.where/v2.0" - v2_version = fixture.V2Discovery(v2_url) - mreq.register_uri( - 'GET', v2_url, json=_create_ver_list([v2_version]), - status_code=200) - - def test_help_unknown_command(self): - self.assertRaises(exceptions.CommandError, self.shell, 'help foofoo') - - def test_invalid_timeout(self): - for f in [0, -1, -10]: - cmd_text = '--timeout %s' % (f) - stdout, stderr = self.shell(cmd_text, exitcodes=[0, 2]) - required = [ - 'argument --timeout: %s must be greater than 0' % (f), - ] - for r in required: - self.assertIn(r, stderr) - - def test_help(self): - required = [ - '.*?^usage: ', - '.*?^\s+root-password\s+Change the admin password', - '.*?^See "nova help COMMAND" for help on a specific command', - ] - stdout, stderr = self.shell('help') - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_help_on_subcommand(self): - required = [ - '.*?^usage: nova root-password', - '.*?^Change the admin password', - '.*?^Positional arguments:', - ] - stdout, stderr = self.shell('help root-password') - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_help_no_options(self): - required = [ - '.*?^usage: ', - '.*?^\s+root-password\s+Change the admin password', - '.*?^See "nova help COMMAND" for help on a specific command', - ] - stdout, stderr = self.shell('') - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_bash_completion(self): - stdout, stderr = self.shell('bash-completion') - # just check we have some output - required = [ - '.*--matching', - '.*--wrap', - '.*help', - '.*secgroup-delete-rule', - '.*--priority'] - for r in required: - self.assertThat((stdout + stderr), - matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE)) - - def test_no_username(self): - required = ('You must provide a username or user id' - ' via --os-username, --os-user-id,' - ' env[OS_USERNAME] or env[OS_USER_ID]') - self.make_env(exclude='OS_USERNAME') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args[0]) - else: - self.fail('CommandError not raised') - - def test_no_user_id(self): - required = ('You must provide a username or user id' - ' via --os-username, --os-user-id,' - ' env[OS_USERNAME] or env[OS_USER_ID]') - self.make_env(exclude='OS_USER_ID', fake_env=FAKE_ENV2) - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args[0]) - else: - self.fail('CommandError not raised') - - def test_no_tenant_name(self): - required = self._msg_no_tenant_project - self.make_env(exclude='OS_TENANT_NAME') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args[0]) - else: - self.fail('CommandError not raised') - - def test_no_tenant_id(self): - required = self._msg_no_tenant_project - self.make_env(exclude='OS_TENANT_ID', fake_env=FAKE_ENV2) - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args[0]) - else: - self.fail('CommandError not raised') - - def test_no_auth_url(self): - required = ('You must provide an auth url' - ' via either --os-auth-url or env[OS_AUTH_URL] or' - ' specify an auth_system which defines a default url' - ' with --os-auth-system or env[OS_AUTH_SYSTEM]',) - self.make_env(exclude='OS_AUTH_URL') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args) - else: - self.fail('CommandError not raised') - - @mock.patch('novaclient.client.Client') - @requests_mock.Mocker() - def test_nova_endpoint_type(self, mock_client, m_requests): - self.make_env(fake_env=FAKE_ENV3) - self.register_keystone_discovery_fixture(m_requests) - self.shell('list') - client_kwargs = mock_client.call_args_list[0][1] - self.assertEqual(client_kwargs['endpoint_type'], 'novaURL') - - @mock.patch('novaclient.client.Client') - @requests_mock.Mocker() - def test_endpoint_type_like_other_clients(self, mock_client, m_requests): - self.make_env(fake_env=FAKE_ENV4) - self.register_keystone_discovery_fixture(m_requests) - self.shell('list') - client_kwargs = mock_client.call_args_list[0][1] - self.assertEqual(client_kwargs['endpoint_type'], 'internalURL') - - @mock.patch('novaclient.client.Client') - @requests_mock.Mocker() - def test_os_endpoint_type(self, mock_client, m_requests): - self.make_env(exclude='NOVA_ENDPOINT_TYPE', fake_env=FAKE_ENV3) - self.register_keystone_discovery_fixture(m_requests) - self.shell('list') - client_kwargs = mock_client.call_args_list[0][1] - self.assertEqual(client_kwargs['endpoint_type'], 'osURL') - - @mock.patch('novaclient.client.Client') - def test_default_endpoint_type(self, mock_client): - self.make_env() - self.shell('list') - client_kwargs = mock_client.call_args_list[0][1] - self.assertEqual(client_kwargs['endpoint_type'], 'publicURL') - - @mock.patch('sys.stdin', side_effect=mock.MagicMock) - @mock.patch('getpass.getpass', return_value='password') - @requests_mock.Mocker() - def test_password(self, mock_getpass, mock_stdin, m_requests): - mock_stdin.encoding = "utf-8" - - # default output of empty tables differs depending between prettytable - # versions - if (hasattr(prettytable, '__version__') and - dist_version.StrictVersion(prettytable.__version__) < - dist_version.StrictVersion('0.7.2')): - ex = '\n' - else: - ex = '\n'.join([ - '+----+------+--------+------------+-------------+----------+', - '| ID | Name | Status | Task State | Power State | Networks |', - '+----+------+--------+------------+-------------+----------+', - '+----+------+--------+------------+-------------+----------+', - '' - ]) - self.make_env(exclude='OS_PASSWORD') - self.register_keystone_discovery_fixture(m_requests) - stdout, stderr = self.shell('list') - self.assertEqual((stdout + stderr), ex) - - @mock.patch('sys.stdin', side_effect=mock.MagicMock) - @mock.patch('getpass.getpass', side_effect=EOFError) - def test_no_password(self, mock_getpass, mock_stdin): - required = ('Expecting a password provided' - ' via either --os-password, env[OS_PASSWORD],' - ' or prompted response',) - self.make_env(exclude='OS_PASSWORD') - try: - self.shell('list') - except exceptions.CommandError as message: - self.assertEqual(required, message.args) - else: - self.fail('CommandError not raised') - - def _test_service_type(self, version, service_type, mock_client): - if version is None: - cmd = 'list' - else: - cmd = ('--service_type %s --os-compute-api-version %s list' % - (service_type, version)) - self.make_env() - self.shell(cmd) - _, client_kwargs = mock_client.call_args_list[0] - self.assertEqual(service_type, client_kwargs['service_type']) - - @mock.patch('novaclient.client.Client') - def test_default_service_type(self, mock_client): - self._test_service_type(None, 'compute', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v1_1_service_type(self, mock_client): - self._test_service_type('1.1', 'compute', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v2_service_type(self, mock_client): - self._test_service_type('2', 'compute', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v3_service_type(self, mock_client): - self._test_service_type('3', 'computev3', mock_client) - - @mock.patch('novaclient.client.Client') - def test_v_unknown_service_type(self, mock_client): - self._test_service_type('unknown', 'compute', mock_client) - - @mock.patch('sys.argv', ['nova']) - @mock.patch('sys.stdout', six.StringIO()) - @mock.patch('sys.stderr', six.StringIO()) - def test_main_noargs(self): - # Ensure that main works with no command-line arguments - try: - novaclient.shell.main() - except SystemExit: - self.fail('Unexpected SystemExit') - - # We expect the normal usage as a result - self.assertIn('Command-line interface to the OpenStack Nova API', - sys.stdout.getvalue()) - - @mock.patch.object(novaclient.shell.OpenStackComputeShell, 'main') - def test_main_keyboard_interrupt(self, mock_compute_shell): - # Ensure that exit code is 130 for KeyboardInterrupt - mock_compute_shell.side_effect = KeyboardInterrupt() - try: - novaclient.shell.main() - except SystemExit as ex: - self.assertEqual(ex.code, 130) - - -class ShellTestKeystoneV3(ShellTest): - def make_env(self, exclude=None, fake_env=FAKE_ENV): - if 'OS_AUTH_URL' in fake_env: - fake_env.update({'OS_AUTH_URL': 'http://no.where/v3'}) - env = dict((k, v) for k, v in fake_env.items() if k != exclude) - self.useFixture(fixtures.MonkeyPatch('os.environ', env)) - - def register_keystone_discovery_fixture(self, mreq): - v3_url = "http://no.where/v3" - v3_version = fixture.V3Discovery(v3_url) - mreq.register_uri( - 'GET', v3_url, json=_create_ver_list([v3_version]), - status_code=200) diff --git a/awx/lib/site-packages/novaclient/tests/unit/test_utils.py b/awx/lib/site-packages/novaclient/tests/unit/test_utils.py deleted file mode 100644 index 2e72ef6591..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/test_utils.py +++ /dev/null @@ -1,357 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -import mock -import six - -from novaclient import base -from novaclient import exceptions -from novaclient.tests.unit import utils as test_utils -from novaclient import utils - -UUID = '8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0' - - -class FakeResource(object): - NAME_ATTR = 'name' - - def __init__(self, _id, properties): - self.id = _id - try: - self.name = properties['name'] - except KeyError: - pass - - -class FakeManager(base.ManagerWithFind): - - resource_class = FakeResource - - resources = [ - FakeResource('1234', {'name': 'entity_one'}), - FakeResource('12345', {'name': 'UPPER'}), - FakeResource('123456', {'name': 'lower'}), - FakeResource('1234567', {'name': 'Mixed'}), - FakeResource('12345678', {'name': 'mixed'}), - FakeResource(UUID, {'name': 'entity_two'}), - FakeResource('5678', {'name': '9876'}), - FakeResource('01234', {'name': 'entity_three'}) - ] - - is_alphanum_id_allowed = None - - def __init__(self, alphanum_id_allowed=False): - self.is_alphanum_id_allowed = alphanum_id_allowed - - def get(self, resource_id): - for resource in self.resources: - if resource.id == str(resource_id): - return resource - raise exceptions.NotFound(resource_id) - - def list(self): - return self.resources - - -class FakeDisplayResource(object): - NAME_ATTR = 'display_name' - - def __init__(self, _id, properties): - self.id = _id - try: - self.display_name = properties['display_name'] - except KeyError: - pass - - -class FakeDisplayManager(FakeManager): - - resource_class = FakeDisplayResource - - resources = [ - FakeDisplayResource('4242', {'display_name': 'entity_three'}), - ] - - -class FindResourceTestCase(test_utils.TestCase): - - def setUp(self): - super(FindResourceTestCase, self).setUp() - self.manager = FakeManager(None) - - def test_find_none(self): - """Test a few non-valid inputs.""" - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - 'asdf') - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - None) - self.assertRaises(exceptions.CommandError, - utils.find_resource, - self.manager, - {}) - - def test_find_by_integer_id(self): - output = utils.find_resource(self.manager, 1234) - self.assertEqual(output, self.manager.get('1234')) - - def test_find_by_str_id(self): - output = utils.find_resource(self.manager, '1234') - self.assertEqual(output, self.manager.get('1234')) - - def test_find_by_uuid(self): - output = utils.find_resource(self.manager, UUID) - self.assertEqual(output, self.manager.get(UUID)) - - def test_find_by_str_name(self): - output = utils.find_resource(self.manager, 'entity_one') - self.assertEqual(output, self.manager.get('1234')) - - def test_find_by_str_upper_name(self): - output = utils.find_resource(self.manager, 'UPPER') - self.assertEqual(output, self.manager.get('12345')) - - def test_find_by_str_lower_name(self): - output = utils.find_resource(self.manager, 'lower') - self.assertEqual(output, self.manager.get('123456')) - - def test_find_by_str_mix_name(self): - output = utils.find_resource(self.manager, 'Mixed') - self.assertEqual(output, self.manager.get('1234567')) - - def test_find_by_str_lower_name_mixed(self): - output = utils.find_resource(self.manager, 'mixed') - self.assertEqual(output, self.manager.get('12345678')) - - def test_find_by_str_display_name(self): - display_manager = FakeDisplayManager(None) - output = utils.find_resource(display_manager, 'entity_three') - self.assertEqual(output, display_manager.get('4242')) - - def test_find_in_alphanum_allowed_manager_by_str_id_(self): - alphanum_manager = FakeManager(True) - output = utils.find_resource(alphanum_manager, '01234') - self.assertEqual(output, alphanum_manager.get('01234')) - - -class _FakeResult(object): - def __init__(self, name, value): - self.name = name - self.value = value - - -class PrintResultTestCase(test_utils.TestCase): - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict(self): - dict = {'key': 'value'} - utils.print_dict(dict) - self.assertEqual('+----------+-------+\n' - '| Property | Value |\n' - '+----------+-------+\n' - '| key | value |\n' - '+----------+-------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_wrap(self): - dict = {'key1': 'not wrapped', - 'key2': 'this will be wrapped'} - utils.print_dict(dict, wrap=16) - self.assertEqual('+----------+--------------+\n' - '| Property | Value |\n' - '+----------+--------------+\n' - '| key1 | not wrapped |\n' - '| key2 | this will be |\n' - '| | wrapped |\n' - '+----------+--------------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_list_sort_by_str(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 2), - _FakeResult("k2", 3)] - - utils.print_list(objs, ["Name", "Value"], sortby_index=0) - - self.assertEqual('+------+-------+\n' - '| Name | Value |\n' - '+------+-------+\n' - '| k1 | 1 |\n' - '| k2 | 3 |\n' - '| k3 | 2 |\n' - '+------+-------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_list_sort_by_integer(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 2), - _FakeResult("k2", 3)] - - utils.print_list(objs, ["Name", "Value"], sortby_index=1) - - self.assertEqual('+------+-------+\n' - '| Name | Value |\n' - '+------+-------+\n' - '| k1 | 1 |\n' - '| k3 | 2 |\n' - '| k2 | 3 |\n' - '+------+-------+\n', - sys.stdout.getvalue()) - - # without sorting - @mock.patch('sys.stdout', six.StringIO()) - def test_print_list_sort_by_none(self): - objs = [_FakeResult("k1", 1), - _FakeResult("k3", 3), - _FakeResult("k2", 2)] - - utils.print_list(objs, ["Name", "Value"], sortby_index=None) - - self.assertEqual('+------+-------+\n' - '| Name | Value |\n' - '+------+-------+\n' - '| k1 | 1 |\n' - '| k3 | 3 |\n' - '| k2 | 2 |\n' - '+------+-------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_dictionary(self): - dict = {'k': {'foo': 'bar'}} - utils.print_dict(dict) - self.assertEqual('+----------+----------------+\n' - '| Property | Value |\n' - '+----------+----------------+\n' - '| k | {"foo": "bar"} |\n' - '+----------+----------------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_list_dictionary(self): - dict = {'k': [{'foo': 'bar'}]} - utils.print_dict(dict) - self.assertEqual('+----------+------------------+\n' - '| Property | Value |\n' - '+----------+------------------+\n' - '| k | [{"foo": "bar"}] |\n' - '+----------+------------------+\n', - sys.stdout.getvalue()) - - @mock.patch('sys.stdout', six.StringIO()) - def test_print_dict_list(self): - dict = {'k': ['foo', 'bar']} - utils.print_dict(dict) - self.assertEqual('+----------+----------------+\n' - '| Property | Value |\n' - '+----------+----------------+\n' - '| k | ["foo", "bar"] |\n' - '+----------+----------------+\n', - sys.stdout.getvalue()) - - -class FlattenTestCase(test_utils.TestCase): - def test_flattening(self): - squashed = utils.flatten_dict( - {'a1': {'b1': 1234, - 'b2': 'string', - 'b3': set((1, 2, 3)), - 'b4': {'c1': ['l', 'l', ['l']], - 'c2': 'string'}}, - 'a2': ['l'], - 'a3': ('t',)}) - - self.assertEqual({'a1_b1': 1234, - 'a1_b2': 'string', - 'a1_b3': set([1, 2, 3]), - 'a1_b4_c1': ['l', 'l', ['l']], - 'a1_b4_c2': 'string', - 'a2': ['l'], - 'a3': ('t',)}, - squashed) - - def test_pretty_choice_dict(self): - d = {} - r = utils.pretty_choice_dict(d) - self.assertEqual("", r) - - d = {"k1": "v1", - "k2": "v2", - "k3": "v3"} - r = utils.pretty_choice_dict(d) - self.assertEqual("'k1=v1', 'k2=v2', 'k3=v3'", r) - - -class ValidationsTestCase(test_utils.TestCase): - def test_validate_flavor_metadata_keys_with_valid_keys(self): - valid_keys = ['key1', 'month.price', 'I-Am:AK-ey.01-', 'spaces and _'] - utils.validate_flavor_metadata_keys(valid_keys) - - def test_validate_flavor_metadata_keys_with_invalid_keys(self): - invalid_keys = ['/1', '?1', '%1', '<', '>', '\1'] - for key in invalid_keys: - try: - utils.validate_flavor_metadata_keys([key]) - self.fail("Invalid key passed validation: %s" % key) - except exceptions.CommandError as ce: - self.assertTrue(key in str(ce)) - - -class ResourceManagerExtraKwargsHookTestCase(test_utils.TestCase): - def test_get_resource_manager_extra_kwargs_hook_test(self): - do_foo = mock.MagicMock() - - def hook1(args): - return {'kwarg1': 'v_hook1'} - - def hook2(args): - return {'kwarg1': 'v_hook2'} - do_foo.resource_manager_kwargs_hooks = [hook1, hook2] - args = {} - exc = self.assertRaises(exceptions.NoUniqueMatch, - utils.get_resource_manager_extra_kwargs, - do_foo, - args) - except_error = ("Hook 'hook2' is attempting to redefine " - "attributes") - self.assertIn(except_error, six.text_type(exc)) - - -class DoActionOnManyTestCase(test_utils.TestCase): - - def _test_do_action_on_many(self, side_effect, fail): - action = mock.Mock(side_effect=side_effect) - - if fail: - self.assertRaises(exceptions.CommandError, - utils.do_action_on_many, - action, [1, 2], 'success with %s', 'error') - else: - utils.do_action_on_many(action, [1, 2], 'success with %s', 'error') - action.assert_has_calls([mock.call(1), mock.call(2)]) - - def test_do_action_on_many_success(self): - self._test_do_action_on_many([None, None], fail=False) - - def test_do_action_on_many_first_fails(self): - self._test_do_action_on_many([Exception(), None], fail=True) - - def test_do_action_on_many_last_fails(self): - self._test_do_action_on_many([None, Exception()], fail=True) diff --git a/awx/lib/site-packages/novaclient/tests/unit/utils.py b/awx/lib/site-packages/novaclient/tests/unit/utils.py deleted file mode 100644 index ab1ddcd185..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/utils.py +++ /dev/null @@ -1,128 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -import fixtures -import mock -from oslo.serialization import jsonutils -import requests -from requests_mock.contrib import fixture as requests_mock_fixture -import six -import testscenarios -import testtools - -AUTH_URL = "http://localhost:5002/auth_url" -AUTH_URL_V1 = "http://localhost:5002/auth_url/v1.0" -AUTH_URL_V2 = "http://localhost:5002/auth_url/v2.0" - - -def _patch_mock_to_raise_for_invalid_assert_calls(): - def raise_for_invalid_assert_calls(wrapped): - def wrapper(_self, name): - valid_asserts = [ - 'assert_called_with', - 'assert_called_once_with', - 'assert_has_calls', - 'assert_any_calls'] - - if name.startswith('assert') and name not in valid_asserts: - raise AttributeError('%s is not a valid mock assert method' - % name) - - return wrapped(_self, name) - return wrapper - mock.Mock.__getattr__ = raise_for_invalid_assert_calls( - mock.Mock.__getattr__) - -# NOTE(gibi): needs to be called only once at import time -# to patch the mock lib -_patch_mock_to_raise_for_invalid_assert_calls() - - -class TestCase(testtools.TestCase): - TEST_REQUEST_BASE = { - 'verify': True, - } - - def setUp(self): - super(TestCase, self).setUp() - if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or - os.environ.get('OS_STDOUT_CAPTURE') == '1'): - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or - os.environ.get('OS_STDERR_CAPTURE') == '1'): - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - - -class FixturedTestCase(testscenarios.TestWithScenarios, TestCase): - - client_fixture_class = None - data_fixture_class = None - - def setUp(self): - super(FixturedTestCase, self).setUp() - - self.requests = self.useFixture(requests_mock_fixture.Fixture()) - self.data_fixture = None - self.client_fixture = None - self.cs = None - - if self.client_fixture_class: - fix = self.client_fixture_class(self.requests) - self.client_fixture = self.useFixture(fix) - self.cs = self.client_fixture.client - - if self.data_fixture_class: - fix = self.data_fixture_class(self.requests) - self.data_fixture = self.useFixture(fix) - - def assert_called(self, method, path, body=None): - self.assertEqual(self.requests.last_request.method, method) - self.assertEqual(self.requests.last_request.path_url, path) - - if body: - req_data = self.requests.last_request.body - if isinstance(req_data, six.binary_type): - req_data = req_data.decode('utf-8') - if not isinstance(body, six.string_types): - # json load if the input body to match against is not a string - req_data = jsonutils.loads(req_data) - self.assertEqual(req_data, body) - - -class TestResponse(requests.Response): - """ - Class used to wrap requests.Response and provide some - convenience to initialize with a dict - """ - - def __init__(self, data): - super(TestResponse, self).__init__() - self._text = None - if isinstance(data, dict): - self.status_code = data.get('status_code') - self.headers = data.get('headers') - # Fake the text attribute to streamline Response creation - self._text = data.get('text') - else: - self.status_code = data - - def __eq__(self, other): - return self.__dict__ == other.__dict__ - - @property - def text(self): - return self._text diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/__init__.py b/awx/lib/site-packages/novaclient/tests/unit/v2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/__init__.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/fakes.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/fakes.py deleted file mode 100644 index 8703395845..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/fakes.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from novaclient.tests.unit.v2 import fakes -from novaclient.v2 import client - - -class FakeClient(fakes.FakeClient): - def __init__(self, *args, **kwargs): - client.Client.__init__(self, 'username', 'password', - 'project_id', 'auth_url', - extensions=kwargs.get('extensions')) - self.client = FakeHTTPClient(**kwargs) - - -class FakeHTTPClient(fakes.FakeHTTPClient): - def get_os_tenant_networks(self): - return (200, {}, { - 'networks': [{"label": "1", "cidr": "10.0.0.0/24", - 'project_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1'}]}) - - def get_os_tenant_networks_1(self, **kw): - return (200, {}, { - 'network': {"label": "1", "cidr": "10.0.0.0/24", - 'project_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1'}}) - - def post_os_tenant_networks(self, **kw): - return (201, {}, { - 'network': {"label": "1", "cidr": "10.0.0.0/24", - 'project_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1'}}) - - def delete_os_tenant_networks_1(self, **kw): - return (204, {}, None) - - def get_os_baremetal_nodes(self, **kw): - return ( - 200, {}, { - 'nodes': [ - { - "id": 1, - "instance_uuid": None, - "interfaces": [], - "cpus": 2, - "local_gb": 10, - "memory_mb": 5, - "pm_address": "2.3.4.5", - "pm_user": "pmuser", - "pm_password": "pmpass", - "prov_mac_address": "aa:bb:cc:dd:ee:ff", - "prov_vlan_id": 1, - "service_host": "somehost", - "terminal_port": 8080, - } - ] - } - ) - - def get_os_baremetal_nodes_1(self, **kw): - return ( - 200, {}, { - 'node': { - "id": 1, - "instance_uuid": None, - "pm_address": "1.2.3.4", - "interfaces": [], - "cpus": 2, - "local_gb": 10, - "memory_mb": 5, - "pm_user": "pmuser", - "pm_password": "pmpass", - "prov_mac_address": "aa:bb:cc:dd:ee:ff", - "prov_vlan_id": 1, - "service_host": "somehost", - "terminal_port": 8080, - } - } - ) - - def post_os_baremetal_nodes(self, **kw): - return ( - 200, {}, { - 'node': { - "id": 1, - "instance_uuid": None, - "cpus": 2, - "local_gb": 10, - "memory_mb": 5, - "pm_address": "2.3.4.5", - "pm_user": "pmuser", - "pm_password": "pmpass", - "prov_mac_address": "aa:bb:cc:dd:ee:ff", - "prov_vlan_id": 1, - "service_host": "somehost", - "terminal_port": 8080, - } - } - ) - - def delete_os_baremetal_nodes_1(self, **kw): - return (202, {}, {}) - - def post_os_baremetal_nodes_1_action(self, **kw): - body = kw['body'] - action = list(body)[0] - if action == "add_interface": - return ( - 200, {}, { - 'interface': { - "id": 2, - "address": "bb:cc:dd:ee:ff:aa", - "datapath_id": 1, - "port_no": 2, - } - } - ) - elif action == "remove_interface": - return (202, {}, {}) - else: - return (500, {}, {}) - - def post_os_assisted_volume_snapshots(self, **kw): - return (202, {}, {'snapshot': {'id': 'blah', 'volumeId': '1'}}) - - def delete_os_assisted_volume_snapshots_x(self, **kw): - return (202, {}, {}) - - def post_os_server_external_events(self, **kw): - return (200, {}, { - 'events': [ - {'name': 'test-event', - 'status': 'completed', - 'tag': 'tag', - 'server_uuid': 'fake-uuid1'}, - {'name': 'test-event', - 'status': 'completed', - 'tag': 'tag', - 'server_uuid': 'fake-uuid2'}]}) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_assisted_volume_snapshots.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_assisted_volume_snapshots.py deleted file mode 100644 index 8ab732aed2..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_assisted_volume_snapshots.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2013, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Assisted volume snapshots - to be used by Cinder and not end users. -""" - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2.contrib import fakes -from novaclient.v2.contrib import assisted_volume_snapshots as assisted_snaps - - -extensions = [ - extension.Extension(assisted_snaps.__name__.split(".")[-1], - assisted_snaps), -] -cs = fakes.FakeClient(extensions=extensions) - - -class AssistedVolumeSnapshotsTestCase(utils.TestCase): - - def test_create_snap(self): - cs.assisted_volume_snapshots.create('1', {}) - cs.assert_called('POST', '/os-assisted-volume-snapshots') - - def test_delete_snap(self): - cs.assisted_volume_snapshots.delete('x', {}) - cs.assert_called( - 'DELETE', - '/os-assisted-volume-snapshots/x?delete_info={}') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_baremetal.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_baremetal.py deleted file mode 100644 index a5ee414677..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_baremetal.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2.contrib import fakes -from novaclient.v2.contrib import baremetal - - -extensions = [ - extension.Extension(baremetal.__name__.split(".")[-1], baremetal), -] -cs = fakes.FakeClient(extensions=extensions) - - -class BaremetalExtensionTest(utils.TestCase): - - def test_list_nodes(self): - nl = cs.baremetal.list() - cs.assert_called('GET', '/os-baremetal-nodes') - for n in nl: - self.assertIsInstance(n, baremetal.BareMetalNode) - - def test_get_node(self): - n = cs.baremetal.get(1) - cs.assert_called('GET', '/os-baremetal-nodes/1') - self.assertIsInstance(n, baremetal.BareMetalNode) - - def test_create_node(self): - n = cs.baremetal.create("service_host", 1, 1024, 2048, - "aa:bb:cc:dd:ee:ff") - cs.assert_called('POST', '/os-baremetal-nodes') - self.assertIsInstance(n, baremetal.BareMetalNode) - - def test_delete_node(self): - n = cs.baremetal.get(1) - cs.baremetal.delete(n) - cs.assert_called('DELETE', '/os-baremetal-nodes/1') - - def test_node_add_interface(self): - i = cs.baremetal.add_interface(1, "bb:cc:dd:ee:ff:aa", 1, 2) - cs.assert_called('POST', '/os-baremetal-nodes/1/action') - self.assertIsInstance(i, baremetal.BareMetalNodeInterface) - - def test_node_remove_interface(self): - cs.baremetal.remove_interface(1, "bb:cc:dd:ee:ff:aa") - cs.assert_called('POST', '/os-baremetal-nodes/1/action') - - def test_node_list_interfaces(self): - cs.baremetal.list_interfaces(1) - cs.assert_called('GET', '/os-baremetal-nodes/1') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_cells.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_cells.py deleted file mode 100644 index e411502bca..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_cells.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2.contrib import fakes -from novaclient.v2.contrib import cells - - -extensions = [ - extension.Extension(cells.__name__.split(".")[-1], - cells), -] -cs = fakes.FakeClient(extensions=extensions) - - -class CellsExtensionTests(utils.TestCase): - def test_get_cells(self): - cell_name = 'child_cell' - cs.cells.get(cell_name) - cs.assert_called('GET', '/os-cells/%s' % cell_name) - - def test_get_capacities_for_a_given_cell(self): - cell_name = 'child_cell' - cs.cells.capacities(cell_name) - cs.assert_called('GET', '/os-cells/%s/capacities' % cell_name) - - def test_get_capacities_for_all_cells(self): - cs.cells.capacities() - cs.assert_called('GET', '/os-cells/capacities') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_instance_actions.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_instance_actions.py deleted file mode 100644 index 0b0400a296..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_instance_actions.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2.contrib import fakes -from novaclient.v2.contrib import instance_action - - -extensions = [ - extension.Extension(instance_action.__name__.split(".")[-1], - instance_action), -] -cs = fakes.FakeClient(extensions=extensions) - - -class InstanceActionExtensionTests(utils.TestCase): - def test_list_instance_actions(self): - server_uuid = '1234' - cs.instance_action.list(server_uuid) - cs.assert_called( - 'GET', '/servers/%s/os-instance-actions' % - server_uuid) - - def test_get_instance_action(self): - server_uuid = '1234' - request_id = 'req-abcde12345' - cs.instance_action.get(server_uuid, request_id) - cs.assert_called( - 'GET', '/servers/%s/os-instance-actions/%s' - % (server_uuid, request_id)) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_list_extensions.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_list_extensions.py deleted file mode 100644 index 3fa5253bae..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_list_extensions.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2 import fakes -from novaclient.v2.contrib import list_extensions - - -extensions = [ - extension.Extension(list_extensions.__name__.split(".")[-1], - list_extensions), -] -cs = fakes.FakeClient(extensions=extensions) - - -class ListExtensionsTests(utils.TestCase): - def test_list_extensions(self): - all_exts = cs.list_extensions.show_all() - cs.assert_called('GET', '/extensions') - self.assertTrue(len(all_exts) > 0) - for r in all_exts: - self.assertTrue(len(r.summary) > 0) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_migrations.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_migrations.py deleted file mode 100644 index 881fd1e505..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_migrations.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2 import fakes -from novaclient.v2.contrib import migrations - -extensions = [ - extension.Extension(migrations.__name__.split(".")[-1], - migrations), -] -cs = fakes.FakeClient(extensions=extensions) - - -class MigrationsTest(utils.TestCase): - - def test_list_migrations(self): - ml = cs.migrations.list() - cs.assert_called('GET', '/os-migrations') - for m in ml: - self.assertIsInstance(m, migrations.Migration) - - def test_list_migrations_with_filters(self): - ml = cs.migrations.list('host1', 'finished', 'child1') - - cs.assert_called('GET', - '/os-migrations?cell_name=child1&host=host1' - '&status=finished') - for m in ml: - self.assertIsInstance(m, migrations.Migration) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_server_external_events.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_server_external_events.py deleted file mode 100644 index 1b941c9d67..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_server_external_events.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2014, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -External event triggering for servers, not to be used by users. -""" - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2.contrib import fakes -from novaclient.v2.contrib import server_external_events as ext_events - - -extensions = [ - extension.Extension(ext_events.__name__.split(".")[-1], - ext_events), -] -cs = fakes.FakeClient(extensions=extensions) - - -class ServerExternalEventsTestCase(utils.TestCase): - def test_external_event(self): - events = [{'server_uuid': 'fake-uuid1', - 'name': 'test-event', - 'status': 'completed', - 'tag': 'tag'}, - {'server_uuid': 'fake-uuid2', - 'name': 'test-event', - 'status': 'completed', - 'tag': 'tag'}] - result = cs.server_external_events.create(events) - self.assertEqual(events, result) - cs.assert_called('POST', '/os-server-external-events') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_tenant_networks.py b/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_tenant_networks.py deleted file mode 100644 index 13159ce5fe..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/contrib/test_tenant_networks.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2.contrib import fakes -from novaclient.v2.contrib import tenant_networks - - -extensions = [ - extension.Extension(tenant_networks.__name__.split(".")[-1], - tenant_networks), -] -cs = fakes.FakeClient(extensions=extensions) - - -class TenantNetworkExtensionTests(utils.TestCase): - def test_list_tenant_networks(self): - nets = cs.tenant_networks.list() - cs.assert_called('GET', '/os-tenant-networks') - self.assertTrue(len(nets) > 0) - - def test_get_tenant_network(self): - cs.tenant_networks.get(1) - cs.assert_called('GET', '/os-tenant-networks/1') - - def test_create_tenant_networks(self): - cs.tenant_networks.create(label="net", - cidr="10.0.0.0/24") - cs.assert_called('POST', '/os-tenant-networks') - - def test_delete_tenant_networks(self): - cs.tenant_networks.delete(1) - cs.assert_called('DELETE', '/os-tenant-networks/1') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/fakes.py b/awx/lib/site-packages/novaclient/tests/unit/v2/fakes.py deleted file mode 100644 index 55b5bad6fe..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/fakes.py +++ /dev/null @@ -1,2228 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import datetime - -import mock -from oslo.utils import strutils -import six -from six.moves.urllib import parse - -from novaclient import client as base_client -from novaclient import exceptions -from novaclient.tests.unit import fakes -from novaclient.tests.unit import utils -from novaclient.v2 import client - - -class FakeClient(fakes.FakeClient, client.Client): - - def __init__(self, *args, **kwargs): - client.Client.__init__(self, 'username', 'password', - 'project_id', 'auth_url', - extensions=kwargs.get('extensions')) - self.client = FakeHTTPClient(**kwargs) - - -class FakeHTTPClient(base_client.HTTPClient): - - def __init__(self, **kwargs): - self.username = 'username' - self.password = 'password' - self.auth_url = 'auth_url' - self.tenant_id = 'tenant_id' - self.callstack = [] - self.projectid = 'projectid' - self.user = 'user' - self.region_name = 'region_name' - self.endpoint_type = 'endpoint_type' - self.service_type = 'service_type' - self.service_name = 'service_name' - self.volume_service_name = 'volume_service_name' - self.timings = 'timings' - self.bypass_url = 'bypass_url' - self.os_cache = 'os_cache' - self.http_log_debug = 'http_log_debug' - - def _cs_request(self, url, method, **kwargs): - # Check that certain things are called correctly - if method in ['GET', 'DELETE']: - assert 'body' not in kwargs - elif method == 'PUT': - assert 'body' in kwargs - - # Call the method - args = parse.parse_qsl(parse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - munged_url = munged_url.replace(' ', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - # Note the call - self.callstack.append((method, url, kwargs.get('body'))) - - status, headers, body = getattr(self, callback)(**kwargs) - r = utils.TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) - return r, body - - # - # agents - # - - def get_os_agents(self, **kw): - hypervisor = kw.get('hypervisor', 'kvm') - return (200, {}, { - 'agents': - [{'hypervisor': hypervisor, - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'id': 1}, - {'hypervisor': hypervisor, - 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'xxx://xxxx/xxx/xxx1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'id': 2}]}) - - def post_os_agents(self, body): - return (200, {}, {'agent': { - 'url': '/xxx/xxx/xxx', - 'hypervisor': body['agent']['hypervisor'], - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'version': '7.0', - 'architecture': 'x86', - 'os': 'win', - 'id': 1}}) - - def delete_os_agents_1(self, **kw): - return (202, {}, None) - - def put_os_agents_1(self, body, **kw): - return (200, {}, { - "agent": {"url": "/yyy/yyyy/yyyy", - "version": "8.0", - "md5hash": "add6bb58e139be103324d04d82d8f546", - 'id': 1}}) - - # - # List all extensions - # - - def get_extensions(self, **kw): - exts = [ - { - "alias": "NMN", - "description": "Multiple network support", - "links": [], - "name": "Multinic", - "namespace": ("http://docs.openstack.org/" - "compute/ext/multinic/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" - }, - { - "alias": "OS-DCF", - "description": "Disk Management Extension", - "links": [], - "name": "DiskConfig", - "namespace": ("http://docs.openstack.org/" - "compute/ext/disk_config/api/v1.1"), - "updated": "2011-09-27T00:00:00+00:00" - }, - { - "alias": "OS-EXT-SRV-ATTR", - "description": "Extended Server Attributes support.", - "links": [], - "name": "ExtendedServerAttributes", - "namespace": ("http://docs.openstack.org/" - "compute/ext/extended_status/api/v1.1"), - "updated": "2011-11-03T00:00:00+00:00" - }, - { - "alias": "OS-EXT-STS", - "description": "Extended Status support", - "links": [], - "name": "ExtendedStatus", - "namespace": ("http://docs.openstack.org/" - "compute/ext/extended_status/api/v1.1"), - "updated": "2011-11-03T00:00:00+00:00" - }, - ] - return (200, {}, { - "extensions": exts, - }) - - # - # Limits - # - - def get_limits(self, **kw): - return (200, {}, {"limits": { - "rate": [ - { - "uri": "*", - "regex": ".*", - "limit": [ - { - "value": 10, - "verb": "POST", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 10, - "verb": "PUT", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 100, - "verb": "DELETE", - "remaining": 100, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - } - ] - }, - { - "uri": "*/servers", - "regex": "^/servers", - "limit": [ - { - "verb": "POST", - "value": 25, - "remaining": 24, - "unit": "DAY", - "next-available": "2011-12-15T22:42:45Z" - } - ] - } - ], - "absolute": { - "maxTotalRAMSize": 51200, - "maxServerMeta": 5, - "maxImageMeta": 5, - "maxPersonality": 5, - "maxPersonalitySize": 10240 - }, - }}) - - # - # Servers - # - - def get_servers(self, **kw): - return (200, {}, {"servers": [ - {'id': 1234, 'name': 'sample-server'}, - {'id': 5678, 'name': 'sample-server2'} - ]}) - - def get_servers_detail(self, **kw): - return (200, {}, {"servers": [ - { - "id": 1234, - "name": "sample-server", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0", - "status": "BUILD", - "progress": 60, - "addresses": { - "public": [ - { - "version": 4, - "addr": "1.2.3.4", - }, - { - "version": 4, - "addr": "5.6.7.8", - }], - "private": [{ - "version": 4, - "addr": "10.11.12.13", - }], - }, - "metadata": { - "Server Label": "Web Head 1", - "Image Version": "2.1" - }, - "OS-EXT-SRV-ATTR:host": "computenode1", - "security_groups": [{ - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - "OS-EXT-MOD:some_thing": "mod_some_thing_value", - }, - { - "id": 5678, - "name": "sample-server2", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [ - { - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - }, - "OS-EXT-SRV-ATTR:host": "computenode2", - "security_groups": [ - { - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }, - { - 'id': 2, 'name': 'securitygroup2', - 'description': 'ANOTHER_FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - }, - { - "id": 9012, - "name": "sample-server3", - "image": "", - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [ - { - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - } - } - ]}) - - def post_servers(self, body, **kw): - assert set(body.keys()) <= set(['server', 'os:scheduler_hints']) - fakes.assert_has_keys( - body['server'], - required=['name', 'imageRef', 'flavorRef'], - optional=['metadata', 'personality']) - if 'personality' in body['server']: - for pfile in body['server']['personality']: - fakes.assert_has_keys(pfile, required=['path', 'contents']) - if body['server']['name'] == 'some-bad-server': - return (202, {}, self.get_servers_1235()[2]) - else: - return (202, {}, self.get_servers_1234()[2]) - - def post_os_volumes_boot(self, body, **kw): - assert set(body.keys()) <= set(['server', 'os:scheduler_hints']) - fakes.assert_has_keys( - body['server'], - required=['name', 'flavorRef'], - optional=['imageRef']) - - # Require one, and only one, of the keys for bdm - if 'block_device_mapping' not in body['server']: - if 'block_device_mapping_v2' not in body['server']: - raise AssertionError( - "missing required keys: 'block_device_mapping'" - ) - elif 'block_device_mapping_v2' in body['server']: - raise AssertionError("found extra keys: 'block_device_mapping'") - - return (202, {}, self.get_servers_9012()[2]) - - def get_servers_1234(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][0]} - return (200, {}, r) - - def get_servers_1235(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][0]} - r['server']['id'] = 1235 - r['server']['status'] = 'error' - r['server']['fault'] = {'message': 'something went wrong!'} - return (200, {}, r) - - def get_servers_5678(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][1]} - return (200, {}, r) - - def get_servers_9012(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][2]} - return (200, {}, r) - - def put_servers_1234(self, body, **kw): - assert list(body) == ['server'] - fakes.assert_has_keys(body['server'], optional=['name', 'adminPass']) - return (204, {}, body) - - def delete_os_server_groups_12345(self, **kw): - return (202, {}, None) - - def delete_os_server_groups_56789(self, **kw): - return (202, {}, None) - - def delete_servers_1234(self, **kw): - return (202, {}, None) - - def delete_servers_5678(self, **kw): - return (202, {}, None) - - def delete_servers_1234_metadata_test_key(self, **kw): - return (204, {}, None) - - def delete_servers_1234_metadata_key1(self, **kw): - return (204, {}, None) - - def delete_servers_1234_metadata_key2(self, **kw): - return (204, {}, None) - - def post_servers_1234_metadata(self, **kw): - return (204, {}, {'metadata': {'test_key': 'test_value'}}) - - def put_servers_1234_metadata_test_key(self, **kw): - return (200, {}, {'meta': {'test_key': 'test_value'}}) - - def get_servers_1234_diagnostics(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def post_servers_uuid1_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def post_servers_uuid2_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def post_servers_uuid3_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def post_servers_uuid4_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def delete_servers_uuid1_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def delete_servers_uuid2_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def delete_servers_uuid3_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def delete_servers_uuid4_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def get_servers_1234_os_security_groups(self, **kw): - return (200, {}, { - "security_groups": [{ - 'id': 1, - 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'rules': []}] - }) - - # - # Server Addresses - # - - def get_servers_1234_ips(self, **kw): - return (200, {}, { - 'addresses': - self.get_servers_1234()[1]['server']['addresses']}) - - def get_servers_1234_ips_public(self, **kw): - return (200, {}, { - 'public': - self.get_servers_1234_ips()[1]['addresses']['public']}) - - def get_servers_1234_ips_private(self, **kw): - return ( - 200, {}, - {'private': - self.get_servers_1234_ips()[1]['addresses']['private']}) - - def delete_servers_1234_ips_public_1_2_3_4(self, **kw): - return (202, {}, None) - - # - # Server password - # - - # Testing with the following password and key - # - # Clear password: FooBar123 - # - # RSA Private Key: novaclient/tests/unit/idfake.pem - # - # Encrypted password - # OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r - # qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho - # QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw - # /y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N - # tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk - # Hi/fmZZNQQqj1Ijq0caOIw== - def get_servers_1234_os_server_password(self, **kw): - return (200, {}, { - 'password': - 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r' - 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho' - 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw' - '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N' - 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk' - 'Hi/fmZZNQQqj1Ijq0caOIw=='}) - - def delete_servers_1234_os_server_password(self, **kw): - return (202, {}, None) - - # - # Server actions - # - - def post_servers_1234_action(self, body, **kw): - _headers = None - _body = None - resp = 202 - assert len(body.keys()) == 1 - action = list(body)[0] - if action == 'reboot': - assert list(body[action]) == ['type'] - assert body[action]['type'] in ['HARD', 'SOFT'] - elif action == 'rebuild': - body = body[action] - adminPass = body.get('adminPass', 'randompassword') - assert 'imageRef' in body - _body = self.get_servers_1234()[2] - _body['server']['adminPass'] = adminPass - elif action == 'resize': - keys = body[action].keys() - assert 'flavorRef' in keys - elif action == 'confirmResize': - assert body[action] is None - # This one method returns a different response code - return (204, {}, None) - elif action == 'revertResize': - assert body[action] is None - elif action == 'migrate': - assert body[action] is None - elif action == 'os-stop': - assert body[action] is None - elif action == 'os-start': - assert body[action] is None - elif action == 'forceDelete': - assert body[action] is None - elif action == 'restore': - assert body[action] is None - elif action == 'pause': - assert body[action] is None - elif action == 'unpause': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'rescue': - if body[action]: - keys = set(body[action].keys()) - assert not (keys - set(['adminPass', 'rescue_image_ref'])) - else: - assert body[action] is None - _body = {'adminPass': 'RescuePassword'} - elif action == 'unrescue': - assert body[action] is None - elif action == 'resume': - assert body[action] is None - elif action == 'suspend': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'shelve': - assert body[action] is None - elif action == 'shelveOffload': - assert body[action] is None - elif action == 'unshelve': - assert body[action] is None - elif action == 'addFixedIp': - assert list(body[action]) == ['networkId'] - elif action == 'removeFixedIp': - assert list(body[action]) == ['address'] - elif action == 'addFloatingIp': - assert (list(body[action]) == ['address'] or - sorted(list(body[action])) == ['address', - 'fixed_address']) - elif action == 'removeFloatingIp': - assert list(body[action]) == ['address'] - elif action == 'createImage': - assert set(body[action].keys()) == set(['name', 'metadata']) - _headers = dict(location="http://blah/images/456") - elif action == 'changePassword': - assert list(body[action]) == ['adminPass'] - elif action == 'os-getConsoleOutput': - assert list(body[action]) == ['length'] - return (202, {}, {'output': 'foo'}) - elif action == 'os-getVNCConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getSPICEConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getRDPConsole': - assert list(body[action]) == ['type'] - elif action == 'os-migrateLive': - assert set(body[action].keys()) == set(['host', - 'block_migration', - 'disk_over_commit']) - elif action == 'os-resetState': - assert list(body[action]) == ['state'] - elif action == 'resetNetwork': - assert body[action] is None - elif action == 'addSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'removeSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'createBackup': - assert set(body[action]) == set(['name', - 'backup_type', - 'rotation']) - elif action == 'evacuate': - keys = list(body[action]) - if 'adminPass' in keys: - keys.remove('adminPass') - if 'host' in keys: - keys.remove('host') - assert set(keys) == set(['onSharedStorage']) - else: - raise AssertionError("Unexpected server action: %s" % action) - return (resp, _headers, _body) - - def post_servers_5678_action(self, body, **kw): - return self.post_servers_1234_action(body, **kw) - - # - # Cloudpipe - # - - def get_os_cloudpipe(self, **kw): - return ( - 200, - {}, - {'cloudpipes': [{'project_id': 1}]} - ) - - def post_os_cloudpipe(self, **ks): - return ( - 202, - {}, - {'instance_id': '9d5824aa-20e6-4b9f-b967-76a699fc51fd'} - ) - - def put_os_cloudpipe_configure_project(self, **kw): - return (202, {}, None) - - # - # Flavors - # - - def get_flavors(self, **kw): - status, header, flavors = self.get_flavors_detail(**kw) - for flavor in flavors['flavors']: - for k in list(flavor): - if k not in ['id', 'name']: - del flavor[k] - - return (200, {}, flavors) - - def get_flavors_detail(self, **kw): - flavors = {'flavors': [ - {'id': 1, 'name': '256 MB Server', 'ram': 256, 'disk': 10, - 'OS-FLV-EXT-DATA:ephemeral': 10, - 'os-flavor-access:is_public': True, - 'links': {}}, - {'id': 2, 'name': '512 MB Server', 'ram': 512, 'disk': 20, - 'OS-FLV-EXT-DATA:ephemeral': 20, - 'os-flavor-access:is_public': False, - 'links': {}}, - {'id': 4, 'name': '1024 MB Server', 'ram': 1024, 'disk': 10, - 'OS-FLV-EXT-DATA:ephemeral': 10, - 'os-flavor-access:is_public': True, - 'links': {}}, - {'id': 'aa1', 'name': '128 MB Server', 'ram': 128, 'disk': 0, - 'OS-FLV-EXT-DATA:ephemeral': 0, - 'os-flavor-access:is_public': True, - 'links': {}} - ]} - - if 'is_public' not in kw: - filter_is_public = True - else: - if kw['is_public'].lower() == 'none': - filter_is_public = None - else: - filter_is_public = strutils.bool_from_string(kw['is_public'], - True) - - if filter_is_public is not None: - if filter_is_public: - flavors['flavors'] = [ - v for v in flavors['flavors'] - if v['os-flavor-access:is_public'] - ] - else: - flavors['flavors'] = [ - v for v in flavors['flavors'] - if not v['os-flavor-access:is_public'] - ] - - return (200, {}, flavors) - - def get_flavors_1(self, **kw): - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][0]} - ) - - def get_flavors_2(self, **kw): - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][1]} - ) - - def get_flavors_3(self, **kw): - # Diablo has no ephemeral - return ( - 200, - {}, - {'flavor': { - 'id': 3, - 'name': '256 MB Server', - 'ram': 256, - 'disk': 10, - }}, - ) - - def get_flavors_512_MB_Server(self, **kw): - raise exceptions.NotFound('404') - - def get_flavors_128_MB_Server(self, **kw): - raise exceptions.NotFound('404') - - def get_flavors_aa1(self, **kw): - # Alphanumeric flavor id are allowed. - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][3]} - ) - - def get_flavors_4(self, **kw): - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][2]} - ) - - def delete_flavors_flavordelete(self, **kw): - return (202, {}, None) - - def delete_flavors_2(self, **kw): - return (202, {}, None) - - def post_flavors(self, body, **kw): - return ( - 202, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][0]} - ) - - def get_flavors_1_os_extra_specs(self, **kw): - return ( - 200, - {}, - {'extra_specs': {"k1": "v1"}}) - - def get_flavors_2_os_extra_specs(self, **kw): - return ( - 200, - {}, - {'extra_specs': {"k2": "v2"}}) - - def get_flavors_aa1_os_extra_specs(self, **kw): - return ( - 200, {}, - {'extra_specs': {"k3": "v3"}}) - - def get_flavors_4_os_extra_specs(self, **kw): - return ( - 200, - {}, - {'extra_specs': {"k4": "v4"}}) - - def post_flavors_1_os_extra_specs(self, body, **kw): - assert list(body) == ['extra_specs'] - fakes.assert_has_keys(body['extra_specs'], - required=['k1']) - return ( - 200, - {}, - {'extra_specs': {"k1": "v1"}}) - - def post_flavors_4_os_extra_specs(self, body, **kw): - assert list(body) == ['extra_specs'] - - return ( - 200, - {}, - body) - - def delete_flavors_1_os_extra_specs_k1(self, **kw): - return (204, {}, None) - - # - # Flavor access - # - - def get_flavors_1_os_flavor_access(self, **kw): - return (404, {}, None) - - def get_flavors_2_os_flavor_access(self, **kw): - return ( - 200, {}, - {'flavor_access': [{'flavor_id': '2', 'tenant_id': 'proj1'}, - {'flavor_id': '2', 'tenant_id': 'proj2'}]}) - - def post_flavors_2_action(self, body, **kw): - return (202, {}, self.get_flavors_2_os_flavor_access()[2]) - - # - # Floating IPs - # - - def get_os_floating_ip_pools(self): - return ( - 200, - {}, - {'floating_ip_pools': [{'name': 'foo'}, {'name': 'bar'}]} - ) - - def get_os_floating_ips(self, **kw): - return ( - 200, - {}, - {'floating_ips': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ]}, - ) - - def get_os_floating_ips_1(self, **kw): - return ( - 200, {}, {'floating_ip': {'id': 1, 'fixed_ip': '10.0.0.1', - 'ip': '11.0.0.1'}}) - - def post_os_floating_ips(self, body): - if body.get('pool'): - return ( - 200, {}, {'floating_ip': {'id': 1, 'fixed_ip': '10.0.0.1', - 'ip': '11.0.0.1', - 'pool': 'nova'}}) - else: - return ( - 200, {}, {'floating_ip': {'id': 1, 'fixed_ip': '10.0.0.1', - 'ip': '11.0.0.1', - 'pool': None}}) - - def delete_os_floating_ips_1(self, **kw): - return (204, {}, None) - - def get_os_floating_ip_dns(self, **kw): - return (205, {}, {'domain_entries': - [{'domain': 'example.org'}, - {'domain': 'example.com'}]}) - - def get_os_floating_ip_dns_testdomain_entries(self, **kw): - if kw.get('ip'): - return (205, {}, { - 'dns_entries': [ - {'dns_entry': {'ip': kw.get('ip'), - 'name': "host1", - 'type': "A", - 'domain': 'testdomain'}}, - {'dns_entry': {'ip': kw.get('ip'), - 'name': "host2", - 'type': "A", - 'domain': 'testdomain'}}]}) - else: - return (404, {}, None) - - def get_os_floating_ip_dns_testdomain_entries_testname(self, **kw): - return (205, {}, { - 'dns_entry': {'ip': "10.10.10.10", - 'name': 'testname', - 'type': "A", - 'domain': 'testdomain'}}) - - def put_os_floating_ip_dns_testdomain(self, body, **kw): - if body['domain_entry']['scope'] == 'private': - fakes.assert_has_keys(body['domain_entry'], - required=['availability_zone', 'scope']) - elif body['domain_entry']['scope'] == 'public': - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - - else: - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - return (205, {}, body) - - def put_os_floating_ip_dns_testdomain_entries_testname(self, body, **kw): - fakes.assert_has_keys(body['dns_entry'], - required=['ip', 'dns_type']) - return (205, {}, body) - - def delete_os_floating_ip_dns_testdomain(self, **kw): - return (200, {}, None) - - def delete_os_floating_ip_dns_testdomain_entries_testname(self, **kw): - return (200, {}, None) - - def get_os_floating_ips_bulk(self, **kw): - return (200, {}, {'floating_ip_info': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ]}) - - def get_os_floating_ips_bulk_testHost(self, **kw): - return (200, {}, {'floating_ip_info': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ]}) - - def post_os_floating_ips_bulk(self, **kw): - params = kw.get('body').get('floating_ips_bulk_create') - pool = params.get('pool', 'defaultPool') - interface = params.get('interface', 'defaultInterface') - return (200, {}, {'floating_ips_bulk_create': - {'ip_range': '192.168.1.0/30', - 'pool': pool, - 'interface': interface}}) - - def put_os_floating_ips_bulk_delete(self, **kw): - ip_range = kw.get('body').get('ip_range') - return (200, {}, {'floating_ips_bulk_delete': ip_range}) - - # - # Images - # - def get_images(self, **kw): - return (200, {}, {'images': [ - {'id': 1, 'name': 'CentOS 5.2'}, - {'id': 2, 'name': 'My Server Backup'} - ]}) - - def get_images_detail(self, **kw): - return (200, {}, {'images': [ - { - 'id': 1, - 'name': 'CentOS 5.2', - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "ACTIVE", - "metadata": { - "test_key": "test_value", - }, - "links": {}, - }, - { - "id": 2, - "name": "My Server Backup", - "serverId": 1234, - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "SAVING", - "progress": 80, - "links": {}, - } - ]}) - - def get_images_1(self, **kw): - return (200, {}, {'image': self.get_images_detail()[2]['images'][0]}) - - def get_images_2(self, **kw): - return (200, {}, {'image': self.get_images_detail()[2]['images'][1]}) - - def get_images_456(self, **kw): - return (200, {}, {'image': self.get_images_detail()[2]['images'][1]}) - - def post_images(self, body, **kw): - assert list(body) == ['image'] - fakes.assert_has_keys(body['image'], required=['serverId', 'name']) - return (202, {}, self.get_images_1()[2]) - - def post_images_1_metadata(self, body, **kw): - assert list(body) == ['metadata'] - fakes.assert_has_keys(body['metadata'], - required=['test_key']) - return ( - 200, - {}, - {'metadata': self.get_images_1()[2]['image']['metadata']}) - - def delete_images_1(self, **kw): - return (204, {}, None) - - def delete_images_2(self, **kw): - return (204, {}, None) - - def delete_images_1_metadata_test_key(self, **kw): - return (204, {}, None) - - # - # Keypairs - # - def get_os_keypairs_test(self, *kw): - return (200, {}, {'keypair': - self.get_os_keypairs()[2]['keypairs'][0]['keypair']}) - - def get_os_keypairs(self, *kw): - return (200, {}, { - "keypairs": [{"keypair": { - "public_key": "FAKE_SSH_RSA", - "private_key": "FAKE_PRIVATE_KEY", - "user_id": "81e373b596d6466e99c4896826abaa46", - "name": "test", - "deleted": False, - "created_at": "2014-04-19T02:16:44.000000", - "updated_at": "2014-04-19T10:12:3.000000", - "figerprint": "FAKE_KEYPAIR", - "deleted_at": None, - "id": 4}} - ]}) - - def delete_os_keypairs_test(self, **kw): - return (202, {}, None) - - def post_os_keypairs(self, body, **kw): - assert list(body) == ['keypair'] - fakes.assert_has_keys(body['keypair'], - required=['name']) - r = {'keypair': self.get_os_keypairs()[2]['keypairs'][0]['keypair']} - return (202, {}, r) - - # - # Virtual Interfaces - # - def get_servers_1234_os_virtual_interfaces(self, **kw): - return (200, {}, {"virtual_interfaces": [ - {'id': 'fakeid', 'mac_address': 'fakemac'} - ]}) - - # - # Quotas - # - - def get_os_quota_sets_test(self, **kw): - return (200, {}, { - 'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_tenant_id(self, **kw): - return (200, {}, { - 'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, **kw): - return (200, {}, { - 'quota_set': { - 'tenant_id': '97f4c221bff44578b0300df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw): - return (200, {}, { - 'quota_set': { - 'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw): - return (200, {}, { - 'quota_set': { - 'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_97f4c221bff44578b0300df4ef119353_defaults(self): - return (200, {}, { - 'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_tenant_id_defaults(self): - return (200, {}, { - 'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, body, **kw): - assert list(body) == ['quota_set'] - fakes.assert_has_keys(body['quota_set'], - required=['tenant_id']) - return (200, {}, { - 'quota_set': { - 'tenant_id': '97f4c221bff44578b0300df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def delete_os_quota_sets_test(self, **kw): - return (202, {}, {}) - - def delete_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, **kw): - return (202, {}, {}) - - # - # Quota Classes - # - - def get_os_quota_class_sets_test(self, **kw): - return (200, {}, { - 'quota_class_set': { - 'id': 'test', - 'metadata_items': 1, - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'key_pairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_class_sets_test(self, body, **kw): - assert list(body) == ['quota_class_set'] - return (200, {}, { - 'quota_class_set': { - 'metadata_items': 1, - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'key_pairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_class_sets_97f4c221bff44578b0300df4ef119353(self, - body, **kw): - assert list(body) == ['quota_class_set'] - return (200, {}, { - 'quota_class_set': { - 'metadata_items': 1, - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'key_pairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - # - # Security Groups - # - def get_os_security_groups(self, **kw): - return (200, {}, {"security_groups": [ - {"name": "test", - "description": "FAKE_SECURITY_GROUP", - "tenant_id": "4ffc664c198e435e9853f2538fbcd7a7", - "id": 1, - "rules": [ - {"id": 11, - "group": {}, - "ip_protocol": "TCP", - "from_port": 22, - "to_port": 22, - "parent_group_id": 1, - "ip_range": - {"cidr": "10.0.0.0/8"}}, - {"id": 12, - "group": { - "tenant_id": - "272bee4c1e624cd4a72a6b0ea55b4582", - "name": "test2"}, - - "ip_protocol": "TCP", - "from_port": 222, - "to_port": 222, - "parent_group_id": 1, - "ip_range": {}}, - {"id": 14, - "group": { - "tenant_id": - "272bee4c1e624cd4a72a6b0ea55b4582", - "name": "test4"}, - - "ip_protocol": "TCP", - "from_port": -1, - "to_port": -1, - "parent_group_id": 1, - "ip_range": {}}]}, - {"name": "test2", - "description": "FAKE_SECURITY_GROUP2", - "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582", - "id": 2, - "rules": []}, - {"name": "test4", - "description": "FAKE_SECURITY_GROUP4", - "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582", - "id": 4, - "rules": []} - ]}) - - def get_os_security_groups_1(self, **kw): - return (200, {}, {"security_group": - {'id': 1, 'name': 'test', 'description': 'FAKE_SECURITY_GROUP'} - }) - - def delete_os_security_groups_1(self, **kw): - return (202, {}, None) - - def post_os_security_groups(self, body, **kw): - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - r = {'security_group': - self.get_os_security_groups()[2]['security_groups'][0]} - return (202, {}, r) - - def put_os_security_groups_1(self, body, **kw): - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - return (205, {}, body) - - # - # Security Group Rules - # - def get_os_security_group_rules(self, **kw): - return (200, {}, {"security_group_rules": [ - {'id': 1, 'parent_group_id': 1, 'group_id': 2, - 'ip_protocol': 'TCP', 'from_port': 22, 'to_port': 22, - 'cidr': '10.0.0.0/8'} - ]}) - - def delete_os_security_group_rules_1(self, **kw): - return (202, {}, None) - - def delete_os_security_group_rules_11(self, **kw): - return (202, {}, None) - - def delete_os_security_group_rules_12(self, **kw): - return (202, {}, None) - - def delete_os_security_group_rules_14(self, **kw): - return (202, {}, None) - - def post_os_security_group_rules(self, body, **kw): - assert list(body) == ['security_group_rule'] - fakes.assert_has_keys( - body['security_group_rule'], - required=['parent_group_id'], - optional=['group_id', 'ip_protocol', 'from_port', - 'to_port', 'cidr']) - r = {'security_group_rule': - self.get_os_security_group_rules()[2]['security_group_rules'][0]} - return (202, {}, r) - - # - # Security Group Default Rules - # - def get_os_security_group_default_rules(self, **kw): - return (200, {}, {"security_group_default_rules": [ - {'id': 1, 'ip_protocol': 'TCP', 'from_port': 22, - 'to_port': 22, 'cidr': '10.0.0.0/8'} - ]}) - - def delete_os_security_group_default_rules_1(self, **kw): - return (202, {}, None) - - def delete_os_security_group_default_rules_11(self, **kw): - return (202, {}, None) - - def delete_os_security_group_default_rules_12(self, **kw): - return (202, {}, None) - - def post_os_security_group_default_rules(self, body, **kw): - assert list(body) == ['security_group_default_rule'] - fakes.assert_has_keys(body['security_group_default_rule'], - optional=['ip_protocol', 'from_port', - 'to_port', 'cidr']) - rules = self.get_os_security_group_default_rules() - r = {'security_group_default_rule': - rules[2]['security_group_default_rules'][0]} - return (202, {}, r) - - # - # Tenant Usage - # - def get_os_simple_tenant_usage(self, **kw): - return (200, {}, - {six.u('tenant_usages'): [{ - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, - six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, - six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): - six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}]}) - - def get_os_simple_tenant_usage_tenantfoo(self, **kw): - return (200, {}, - {six.u('tenant_usage'): { - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): - six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}}) - - def get_os_simple_tenant_usage_test(self, **kw): - return (200, {}, {six.u('tenant_usage'): { - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}}) - - def get_os_simple_tenant_usage_tenant_id(self, **kw): - return (200, {}, {six.u('tenant_usage'): { - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}}) - # - # Certificates - # - - def get_os_certificates_root(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': None, 'data': 'foo'}} - ) - - def post_os_certificates(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': 'foo', 'data': 'bar'}} - ) - - # - # Aggregates - # - - def get_os_aggregates(self, *kw): - return (200, {}, {"aggregates": [ - {'id': '1', - 'name': 'test', - 'availability_zone': 'nova1'}, - {'id': '2', - 'name': 'test2', - 'availability_zone': 'nova1'}, - {'id': '3', - 'name': 'test3', - 'metadata': {'test': "dup", "none_key": "Nine"}}, - ]}) - - def _return_aggregate(self): - r = {'aggregate': self.get_os_aggregates()[2]['aggregates'][0]} - return (200, {}, r) - - def _return_aggregate_3(self): - r = {'aggregate': self.get_os_aggregates()[2]['aggregates'][2]} - return (200, {}, r) - - def get_os_aggregates_1(self, **kw): - return self._return_aggregate() - - def get_os_aggregates_3(self, **kw): - return self._return_aggregate_3() - - def post_os_aggregates(self, body, **kw): - return self._return_aggregate() - - def put_os_aggregates_1(self, body, **kw): - return self._return_aggregate() - - def put_os_aggregates_2(self, body, **kw): - return self._return_aggregate() - - def put_os_aggregates_3(self, body, **kw): - return self._return_aggregate_3() - - def post_os_aggregates_1_action(self, body, **kw): - return self._return_aggregate() - - def post_os_aggregates_2_action(self, body, **kw): - return self._return_aggregate() - - def post_os_aggregates_3_action(self, body, **kw): - return self._return_aggregate_3() - - def delete_os_aggregates_1(self, **kw): - return (202, {}, None) - - # - # Services - # - def get_os_services(self, **kw): - host = kw.get('host', 'host1') - binary = kw.get('binary', 'nova-compute') - return (200, {}, {'services': [{'binary': binary, - 'host': host, - 'zone': 'nova', - 'status': 'enabled', - 'state': 'up', - 'updated_at': datetime.datetime( - 2012, 10, 29, 13, 42, 2)}, - {'binary': binary, - 'host': host, - 'zone': 'nova', - 'status': 'disabled', - 'state': 'down', - 'updated_at': datetime.datetime( - 2012, 9, 18, 8, 3, 38)}, - ]}) - - def put_os_services_enable(self, body, **kw): - return (200, {}, {'service': {'host': body['host'], - 'binary': body['binary'], - 'status': 'enabled'}}) - - def put_os_services_disable(self, body, **kw): - return (200, {}, {'service': {'host': body['host'], - 'binary': body['binary'], - 'status': 'disabled'}}) - - def put_os_services_disable_log_reason(self, body, **kw): - return (200, {}, {'service': { - 'host': body['host'], - 'binary': body['binary'], - 'status': 'disabled', - 'disabled_reason': body['disabled_reason']}}) - - def delete_os_services_1(self, **kw): - return (204, {}, None) - - # - # Fixed IPs - # - def get_os_fixed_ips_192_168_1_1(self, *kw): - return (200, {}, {"fixed_ip": {'cidr': '192.168.1.0/24', - 'address': '192.168.1.1', - 'hostname': 'foo', - 'host': 'bar'}}) - - def post_os_fixed_ips_192_168_1_1_action(self, body, **kw): - return (202, {}, None) - - # - # Hosts - # - def get_os_hosts_host(self, *kw): - return (200, {}, {'host': - [{'resource': {'project': '(total)', 'host': 'dummy', - 'cpu': 16, 'memory_mb': 32234, 'disk_gb': 128}}, - {'resource': {'project': '(used_now)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2075, 'disk_gb': 45}}, - {'resource': {'project': '(used_max)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}, - {'resource': {'project': 'admin', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}]}) - - def get_os_hosts(self, **kw): - zone = kw.get('zone', 'nova1') - return (200, {}, {'hosts': [{'host': 'host1', - 'service': 'nova-compute', - 'zone': zone}, - {'host': 'host1', - 'service': 'nova-cert', - 'zone': zone}]}) - - def get_os_hosts_sample_host(self, *kw): - return (200, {}, {'host': [{'resource': {'host': 'sample_host'}}], }) - - def put_os_hosts_sample_host_1(self, body, **kw): - return (200, {}, {'host': 'sample-host_1', - 'status': 'enabled'}) - - def put_os_hosts_sample_host_2(self, body, **kw): - return (200, {}, {'host': 'sample-host_2', - 'maintenance_mode': 'on_maintenance'}) - - def put_os_hosts_sample_host_3(self, body, **kw): - return (200, {}, {'host': 'sample-host_3', - 'status': 'enabled', - 'maintenance_mode': 'on_maintenance'}) - - def get_os_hosts_sample_host_reboot(self, **kw): - return (200, {}, {'host': 'sample_host', - 'power_action': 'reboot'}) - - def get_os_hosts_sample_host_startup(self, **kw): - return (200, {}, {'host': 'sample_host', - 'power_action': 'startup'}) - - def get_os_hosts_sample_host_shutdown(self, **kw): - return (200, {}, {'host': 'sample_host', - 'power_action': 'shutdown'}) - - def put_os_hosts_sample_host(self, body, **kw): - result = {'host': 'dummy'} - result.update(body) - return (200, {}, result) - - def get_os_hypervisors(self, **kw): - return (200, {}, { - "hypervisors": [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'}]}) - - def get_os_hypervisors_detail(self, **kw): - return (200, {}, { - "hypervisors": [ - {'id': 1234, - 'service': {'id': 1, 'host': 'compute1'}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': "xen", - 'hypervisor_version': 3, - 'hypervisor_hostname': "hyper1", - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100}, - {'id': 2, - 'service': {'id': 2, 'host': "compute2"}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': "xen", - 'hypervisor_version': 3, - 'hypervisor_hostname': "hyper2", - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100}] - }) - - def get_os_hypervisors_statistics(self, **kw): - return (200, {}, { - "hypervisor_statistics": { - 'count': 2, - 'vcpus': 8, - 'memory_mb': 20 * 1024, - 'local_gb': 500, - 'vcpus_used': 4, - 'memory_mb_used': 10 * 1024, - 'local_gb_used': 250, - 'free_ram_mb': 10 * 1024, - 'free_disk_gb': 250, - 'current_workload': 4, - 'running_vms': 4, - 'disk_available_least': 200} - }) - - def get_os_hypervisors_hyper_search(self, **kw): - return (200, {}, { - 'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'}]}) - - def get_os_hypervisors_hyper_servers(self, **kw): - return (200, {}, { - 'hypervisors': [ - {'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'servers': [ - {'name': 'inst1', 'uuid': 'uuid1'}, - {'name': 'inst2', 'uuid': 'uuid2'}]}, - {'id': 5678, - 'hypervisor_hostname': 'hyper2', - 'servers': [ - {'name': 'inst3', 'uuid': 'uuid3'}, - {'name': 'inst4', 'uuid': 'uuid4'}]}] - }) - - def get_os_hypervisors_hyper_no_servers_servers(self, **kw): - return (200, {}, {'hypervisors': - [{'id': 1234, 'hypervisor_hostname': 'hyper1'}]}) - - def get_os_hypervisors_1234(self, **kw): - return (200, {}, { - 'hypervisor': - {'id': 1234, - 'service': {'id': 1, 'host': 'compute1'}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': "xen", - 'hypervisor_version': 3, - 'hypervisor_hostname': "hyper1", - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100}}) - - def get_os_hypervisors_1234_uptime(self, **kw): - return (200, {}, { - 'hypervisor': {'id': 1234, - 'hypervisor_hostname': "hyper1", - 'uptime': "fake uptime"}}) - - def get_os_networks(self, **kw): - return (200, {}, {'networks': [{"label": "1", "cidr": "10.0.0.0/24", - 'project_id': - '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1', 'vlan': '1234'}]}) - - def delete_os_networks_1(self, **kw): - return (202, {}, None) - - def post_os_networks(self, **kw): - return (202, {}, {'network': kw}) - - def get_os_networks_1(self, **kw): - return (200, {}, {'network': {"label": "1", "cidr": "10.0.0.0/24", - "id": "1"}}) - - def delete_os_networks_networkdelete(self, **kw): - return (202, {}, None) - - def post_os_networks_add(self, **kw): - return (202, {}, None) - - def post_os_networks_networkdisassociate_action(self, **kw): - return (202, {}, None) - - def get_os_fping(self, **kw): - return ( - 200, {}, { - 'servers': [ - { - "id": "1", - "project_id": "fake-project", - "alive": True, - }, - { - "id": "2", - "project_id": "fake-project", - "alive": True, - }, - ] - } - ) - - def get_os_fping_1(self, **kw): - return ( - 200, {}, { - 'server': { - "id": "1", - "project_id": "fake-project", - "alive": True, - } - } - ) - - def post_os_networks_1_action(self, **kw): - return (202, {}, None) - - def post_os_networks_networktest_action(self, **kw): - return (202, {}, None) - - def post_os_networks_2_action(self, **kw): - return (202, {}, None) - - def get_os_tenant_networks(self, **kw): - return (200, {}, {'networks': [{"label": "1", "cidr": "10.0.0.0/24", - 'project_id': - '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1', 'vlan': '1234'}]}) - - def get_os_tenant_networks_1(self, **kw): - return (200, {}, {'network': {"label": "1", "cidr": "10.0.0.0/24", - "id": "1"}}) - - def post_os_tenant_networks(self, **kw): - return (202, {}, {'network': {"label": "new_network1", - "cidr1": "10.0.1.0/24"}}) - - def delete_os_tenant_networks_1(self, **kw): - return (202, {}, None) - - def get_os_availability_zone(self, **kw): - return (200, {}, { - "availabilityZoneInfo": [ - {"zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": None}, - {"zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None}] - }) - - def get_os_availability_zone_detail(self, **kw): - return (200, {}, { - "availabilityZoneInfo": [ - {"zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "nova-compute": { - "active": True, - "available": True, - "updated_at": datetime.datetime( - 2012, 12, 26, 14, 45, 25, 0)}}}}, - {"zoneName": "internal", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "nova-sched": { - "active": True, - "available": True, - "updated_at": datetime.datetime( - 2012, 12, 26, 14, 45, 25, 0)}}, - "fake_host-2": { - "nova-network": { - "active": True, - "available": False, - "updated_at": datetime.datetime( - 2012, 12, 26, 14, 45, 24, 0)}}}}, - {"zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None}]}) - - def get_servers_1234_os_interface(self, **kw): - return (200, {}, { - "interfaceAttachments": [ - {"port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - }, - {"port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - }] - }) - - def post_servers_1234_os_interface(self, **kw): - return (200, {}, {'interfaceAttachment': {}}) - - def delete_servers_1234_os_interface_port_id(self, **kw): - return (200, {}, None) - - # NOTE (vkhomenko): - # Volume responses was taken from: - # https://wiki.openstack.org/wiki/CreateVolumeFromImage - # http://jorgew.github.com/block-storage-api/content/ - # GET_listDetailVolumes_v1__tenantId__volumes_detail_.html - # I suppose they are outdated and should be updated after Cinder released - - def get_volumes_detail(self, **kw): - return (200, {}, {"volumes": [ - { - "display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "3333", - "links": ''}], - "metadata": {}}, - { - "display_name": "Work2", - "display_description": "volume for work2", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-ee32ba30feaa", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "2222", - "links": ''}], - "metadata": {}}]}) - - def get_volumes(self, **kw): - return (200, {}, {"volumes": [ - { - "display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "3333", - "links": ''}], - "metadata": {}}, - { - "display_name": "Work2", - "display_description": "volume for work2", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-ee32ba30feaa", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "2222", - "links": ''}], - "metadata": {}}]}) - - def get_volumes_15e59938_07d5_11e1_90e3_e3dffe0c5983(self, **kw): - return (200, {}, { - "volume": self.get_volumes_detail()[2]['volumes'][0]}) - - def get_volumes_15e59938_07d5_11e1_90e3_ee32ba30feaa(self, **kw): - return (200, {}, { - "volume": self.get_volumes_detail()[2]['volumes'][1]}) - - def post_volumes(self, **kw): - return (200, {}, {"volume": - {"status": "creating", - "display_name": "vol-007", - "attachments": [(0)], - "availability_zone": "cinder", - "created_at": "2012-08-13T10:57:17.000000", - "display_description": "create volume from image", - "image_id": "f4cf905f-7c58-4d7b-8314-8dd8a2d1d483", - "volume_type": "None", - "metadata": {}, - "id": "5cb239f6-1baf-4fe1-bd78-c852cf00fa39", - "size": 1}}) - - def delete_volumes_15e59938_07d5_11e1_90e3_e3dffe0c5983(self, **kw): - return (200, {}, {}) - - def delete_volumes_15e59938_07d5_11e1_90e3_ee32ba30feaa(self, **kw): - return (200, {}, {}) - - def post_servers_1234_os_volume_attachments(self, **kw): - return (200, {}, { - "volumeAttachment": - {"device": "/dev/vdb", - "volumeId": 2}}) - - def put_servers_1234_os_volume_attachments_Work(self, **kw): - return (200, {}, {"volumeAttachment": {"volumeId": 2}}) - - def get_servers_1234_os_volume_attachments(self, **kw): - return (200, {}, { - "volumeAttachments": [ - {"display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [{"id": "3333", "links": ''}], - "metadata": {}}]}) - - def get_servers_1234_os_volume_attachments_Work(self, **kw): - return (200, {}, { - "volumeAttachment": - {"display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [{"id": "3333", "links": ''}], - "metadata": {}}}) - - def delete_servers_1234_os_volume_attachments_Work(self, **kw): - return (200, {}, {}) - - def get_servers_1234_os_instance_actions(self, **kw): - return (200, {}, { - "instanceActions": - [{"instance_uuid": "1234", - "user_id": "b968c25e04ab405f9fe4e6ca54cce9a5", - "start_time": "2013-03-25T13:45:09.000000", - "request_id": "req-abcde12345", - "action": "create", - "message": None, - "project_id": "04019601fe3648c0abd4f4abfb9e6106"}]}) - - def get_servers_1234_os_instance_actions_req_abcde12345(self, **kw): - return (200, {}, { - "instanceAction": - {"instance_uuid": "1234", - "user_id": "b968c25e04ab405f9fe4e6ca54cce9a5", - "start_time": "2013-03-25T13:45:09.000000", - "request_id": "req-abcde12345", - "action": "create", - "message": None, - "project_id": "04019601fe3648c0abd4f4abfb9e6106"}}) - - def post_servers_uuid1_action(self, **kw): - return 202, {}, {} - - def post_servers_uuid2_action(self, **kw): - return 202, {}, {} - - def post_servers_uuid3_action(self, **kw): - return 202, {}, {} - - def post_servers_uuid4_action(self, **kw): - return 202, {}, {} - - def get_os_cells_child_cell(self, **kw): - cell = {'cell': { - 'username': 'cell1_user', - 'name': 'cell1', - 'rpc_host': '10.0.1.10', - 'info': { - 'username': 'cell1_user', - 'rpc_host': '10.0.1.10', - 'type': 'child', - 'name': 'cell1', - 'rpc_port': 5673}, - 'type': 'child', - 'rpc_port': 5673, - 'loaded': True - }} - return (200, {}, cell) - - def get_os_cells_capacities(self, **kw): - cell_capacities_response = {"cell": {"capacities": {"ram_free": { - "units_by_mb": {"8192": 0, "512": 13, "4096": 1, "2048": 3, - "16384": 0}, "total_mb": 7680}, "disk_free": { - "units_by_mb": {"81920": 11, "20480": 46, "40960": 23, "163840": 5, - "0": 0}, "total_mb": 1052672}}}} - return (200, {}, cell_capacities_response) - - def get_os_cells_child_cell_capacities(self, **kw): - return self.get_os_cells_capacities() - - def get_os_migrations(self, **kw): - migrations = {'migrations': [ - { - "created_at": "2012-10-29T13:42:02.000000", - "dest_compute": "compute2", - "dest_host": "1.2.3.4", - "dest_node": "node2", - "id": 1234, - "instance_uuid": "instance_id_123", - "new_instance_type_id": 2, - "old_instance_type_id": 1, - "source_compute": "compute1", - "source_node": "node1", - "status": "Done", - "updated_at": "2012-10-29T13:42:02.000000" - }]} - return (200, {}, migrations) - - def post_os_server_external_events(self, **kw): - return (200, {}, {'events': [ - {'name': 'network-changed', - 'server_uuid': '1234'}]}) - - # - # Server Groups - # - - def get_os_server_groups(self, *kw): - return (200, {}, - {"server_groups": [ - {"members": [], "metadata": {}, - "id": "2cbd51f4-fafe-4cdb-801b-cf913a6f288b", - "policies": [], "name": "ig1"}, - {"members": [], "metadata": {}, - "id": "4473bb03-4370-4bfb-80d3-dc8cffc47d94", - "policies": ["anti-affinity"], "name": "ig2"}, - {"members": [], "metadata": {"key": "value"}, - "id": "31ab9bdb-55e1-4ac3-b094-97eeb1b65cc4", - "policies": [], "name": "ig3"}, - {"members": ["2dccb4a1-02b9-482a-aa23-5799490d6f5d"], - "metadata": {}, - "id": "4890bb03-7070-45fb-8453-d34556c87d94", - "policies": ["anti-affinity"], "name": "ig2"}]}) - - def _return_server_group(self): - r = {'server_group': - self.get_os_server_groups()[2]['server_groups'][0]} - return (200, {}, r) - - def post_os_server_groups(self, body, **kw): - return self._return_server_group() - - def get_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b(self, **kw): - return self._return_server_group() - - def put_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b(self, **kw): - return self._return_server_group() - - def post_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b_action( - self, body, **kw): - return self._return_server_group() - - def delete_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b( - self, **kw): - return (202, {}, None) - - -class FakeSessionClient(fakes.FakeClient, client.Client): - - def __init__(self, *args, **kwargs): - client.Client.__init__(self, 'username', 'password', - 'project_id', 'auth_url', - extensions=kwargs.get('extensions')) - self.client = FakeSessionMockClient(**kwargs) - - -class FakeSessionMockClient(base_client.SessionClient, FakeHTTPClient): - - def __init__(self, *args, **kwargs): - - self.callstack = [] - self.auth = mock.Mock() - self.session = mock.Mock() - - self.auth.get_auth_ref.return_value.project_id = 'tenant_id' - - def request(self, url, method, **kwargs): - return self._cs_request(url, method, **kwargs) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_agents.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_agents.py deleted file mode 100644 index e7fa7d6edb..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_agents.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import agents as data -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit import utils -from novaclient.v2 import agents - - -class AgentsTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def stub_hypervisors(self, hypervisor='kvm'): - get_os_agents = { - 'agents': [ - { - 'hypervisor': hypervisor, - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'id': 1 - }, - { - 'hypervisor': hypervisor, - 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'xxx://xxxx/xxx/xxx1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'id': 2 - }, - ] - } - - headers = {'Content-Type': 'application/json'} - self.requests.register_uri('GET', self.data_fixture.url(), - json=get_os_agents, - headers=headers) - - def test_list_agents(self): - self.stub_hypervisors() - ags = self.cs.agents.list() - self.assert_called('GET', '/os-agents') - for a in ags: - self.assertIsInstance(a, agents.Agent) - self.assertEqual('kvm', a.hypervisor) - - def test_list_agents_with_hypervisor(self): - self.stub_hypervisors('xen') - ags = self.cs.agents.list('xen') - self.assert_called('GET', '/os-agents?hypervisor=xen') - for a in ags: - self.assertIsInstance(a, agents.Agent) - self.assertEqual('xen', a.hypervisor) - - def test_agents_create(self): - ag = self.cs.agents.create('win', 'x86', '7.0', - '/xxx/xxx/xxx', - 'add6bb58e139be103324d04d82d8f546', - 'xen') - body = {'agent': {'url': '/xxx/xxx/xxx', - 'hypervisor': 'xen', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'version': '7.0', - 'architecture': 'x86', - 'os': 'win'}} - self.assert_called('POST', '/os-agents', body) - self.assertEqual(1, ag._info.copy()['id']) - - def test_agents_delete(self): - self.cs.agents.delete('1') - self.assert_called('DELETE', '/os-agents/1') - - def _build_example_update_body(self): - return {"para": { - "url": "/yyy/yyyy/yyyy", - "version": "8.0", - "md5hash": "add6bb58e139be103324d04d82d8f546"}} - - def test_agents_modify(self): - ag = self.cs.agents.update('1', '8.0', - '/yyy/yyyy/yyyy', - 'add6bb58e139be103324d04d82d8f546') - body = self._build_example_update_body() - self.assert_called('PUT', '/os-agents/1', body) - self.assertEqual(1, ag.id) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_aggregates.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_aggregates.py deleted file mode 100644 index 97a3ffc2bc..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_aggregates.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import aggregates as data -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit import utils -from novaclient.v2 import aggregates - - -class AggregatesTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_list_aggregates(self): - result = self.cs.aggregates.list() - self.assert_called('GET', '/os-aggregates') - for aggregate in result: - self.assertIsInstance(aggregate, aggregates.Aggregate) - - def test_create_aggregate(self): - body = {"aggregate": {"name": "test", "availability_zone": "nova1"}} - aggregate = self.cs.aggregates.create("test", "nova1") - self.assert_called('POST', '/os-aggregates', body) - self.assertIsInstance(aggregate, aggregates.Aggregate) - - def test_get(self): - aggregate = self.cs.aggregates.get("1") - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate, aggregates.Aggregate) - - aggregate2 = self.cs.aggregates.get(aggregate) - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate2, aggregates.Aggregate) - - def test_get_details(self): - aggregate = self.cs.aggregates.get_details("1") - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate, aggregates.Aggregate) - - aggregate2 = self.cs.aggregates.get_details(aggregate) - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate2, aggregates.Aggregate) - - def test_update(self): - aggregate = self.cs.aggregates.get("1") - values = {"name": "foo"} - body = {"aggregate": values} - - result1 = aggregate.update(values) - self.assert_called('PUT', '/os-aggregates/1', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.update(2, values) - self.assert_called('PUT', '/os-aggregates/2', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - def test_update_with_availability_zone(self): - aggregate = self.cs.aggregates.get("1") - values = {"name": "foo", "availability_zone": "new_zone"} - body = {"aggregate": values} - - result3 = self.cs.aggregates.update(aggregate, values) - self.assert_called('PUT', '/os-aggregates/1', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_add_host(self): - aggregate = self.cs.aggregates.get("1") - host = "host1" - body = {"add_host": {"host": "host1"}} - - result1 = aggregate.add_host(host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.add_host("2", host) - self.assert_called('POST', '/os-aggregates/2/action', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - result3 = self.cs.aggregates.add_host(aggregate, host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_remove_host(self): - aggregate = self.cs.aggregates.get("1") - host = "host1" - body = {"remove_host": {"host": "host1"}} - - result1 = aggregate.remove_host(host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.remove_host("2", host) - self.assert_called('POST', '/os-aggregates/2/action', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - result3 = self.cs.aggregates.remove_host(aggregate, host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_set_metadata(self): - aggregate = self.cs.aggregates.get("1") - metadata = {"foo": "bar"} - body = {"set_metadata": {"metadata": metadata}} - - result1 = aggregate.set_metadata(metadata) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.set_metadata(2, metadata) - self.assert_called('POST', '/os-aggregates/2/action', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - result3 = self.cs.aggregates.set_metadata(aggregate, metadata) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_delete_aggregate(self): - aggregate = self.cs.aggregates.list()[0] - aggregate.delete() - self.assert_called('DELETE', '/os-aggregates/1') - - self.cs.aggregates.delete('1') - self.assert_called('DELETE', '/os-aggregates/1') - - self.cs.aggregates.delete(aggregate) - self.assert_called('DELETE', '/os-aggregates/1') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_auth.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_auth.py deleted file mode 100644 index 95e96ded19..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_auth.py +++ /dev/null @@ -1,386 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import json - -from keystoneclient import fixture -import mock -import requests - -from novaclient import exceptions -from novaclient.tests.unit import utils -from novaclient.v2 import client - - -class AuthenticateAgainstKeystoneTests(utils.TestCase): - - def get_token(self, **kwargs): - resp = fixture.V2Token(**kwargs) - resp.set_scope() - - s = resp.add_service('compute') - s.add_endpoint('http://localhost:8774/v1.1', region='RegionOne') - - return resp - - def test_authenticate_success(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, service_type='compute') - resp = self.get_token() - - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2) - resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}} - auth_response = utils.TestResponse({ - "status_code": 401, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_v1_auth_redirect(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V1, service_type='compute') - dict_correct_response = self.get_token() - correct_response = json.dumps(dict_correct_response) - dict_responses = [ - {"headers": {'location': 'http://127.0.0.1:5001'}, - "status_code": 305, - "text": "Use proxy"}, - # Configured on admin port, nova redirects to v2.0 port. - # When trying to connect on it, keystone auth succeed by v1.0 - # protocol (through headers) but tokens are being returned in - # body (looks like keystone bug). Leaved for compatibility. - {"headers": {}, - "status_code": 200, - "text": correct_response}, - {"headers": {}, - "status_code": 200, - "text": correct_response} - ] - - responses = [(utils.TestResponse(resp)) for resp in dict_responses] - - def side_effect(*args, **kwargs): - return responses.pop(0) - - mock_request = mock.Mock(side_effect=side_effect) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - kwargs = copy.copy(self.TEST_REQUEST_BASE) - kwargs['headers'] = headers - kwargs['data'] = json.dumps(body) - mock_request.assert_called_with( - "POST", - token_url, - allow_redirects=True, - **kwargs) - - resp = dict_correct_response - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - test_auth_call() - - def test_v2_auth_redirect(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, service_type='compute') - dict_correct_response = self.get_token() - correct_response = json.dumps(dict_correct_response) - dict_responses = [ - {"headers": {'location': 'http://127.0.0.1:5001'}, - "status_code": 305, - "text": "Use proxy"}, - # Configured on admin port, nova redirects to v2.0 port. - # When trying to connect on it, keystone auth succeed by v1.0 - # protocol (through headers) but tokens are being returned in - # body (looks like keystone bug). Leaved for compatibility. - {"headers": {}, - "status_code": 200, - "text": correct_response}, - {"headers": {}, - "status_code": 200, - "text": correct_response} - ] - - responses = [(utils.TestResponse(resp)) for resp in dict_responses] - - def side_effect(*args, **kwargs): - return responses.pop(0) - - mock_request = mock.Mock(side_effect=side_effect) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - kwargs = copy.copy(self.TEST_REQUEST_BASE) - kwargs['headers'] = headers - kwargs['data'] = json.dumps(body) - mock_request.assert_called_with( - "POST", - token_url, - allow_redirects=True, - **kwargs) - - resp = dict_correct_response - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - test_auth_call() - - def test_ambiguous_endpoints(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, service_type='compute') - resp = self.get_token() - - # duplicate existing service - s = resp.add_service('compute') - s.add_endpoint('http://localhost:8774/v1.1', region='RegionOne') - - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.AmbiguousEndpoints, - cs.client.authenticate) - - test_auth_call() - - def test_authenticate_with_token_success(self): - cs = client.Client("username", None, "project_id", - utils.AUTH_URL_V2, service_type='compute') - cs.client.auth_token = "FAKE_ID" - resp = self.get_token(token_id="FAKE_ID") - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - with mock.patch.object(requests, "request", mock_request): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'token': { - 'id': cs.client.auth_token, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - def test_authenticate_with_token_failure(self): - cs = client.Client("username", None, "project_id", utils.AUTH_URL_V2) - cs.client.auth_token = "FAKE_ID" - resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}} - auth_response = utils.TestResponse({ - "status_code": 401, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - with mock.patch.object(requests.Session, "request", mock_request): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - -class AuthenticationTests(utils.TestCase): - def test_authenticate_success(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - management_url = 'https://localhost/v1.1/443470' - auth_response = utils.TestResponse({ - 'status_code': 204, - 'headers': { - 'x-server-management-url': management_url, - 'x-auth-token': '1b751d74-de0c-46ae-84f0-915744b582d1', - }, - }) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'Accept': 'application/json', - 'X-Auth-User': 'username', - 'X-Auth-Key': 'password', - 'X-Auth-Project-Id': 'project_id', - 'User-Agent': cs.client.USER_AGENT - } - mock_request.assert_called_with( - "GET", - cs.client.auth_url, - headers=headers, - **self.TEST_REQUEST_BASE) - - self.assertEqual(cs.client.management_url, - auth_response.headers['x-server-management-url']) - self.assertEqual(cs.client.auth_token, - auth_response.headers['x-auth-token']) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - auth_response = utils.TestResponse({'status_code': 401}) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_auth_automatic(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - http_client = cs.client - http_client.management_url = '' - mock_request = mock.Mock(return_value=(None, None)) - - @mock.patch.object(http_client, 'request', mock_request) - @mock.patch.object(http_client, 'authenticate') - def test_auth_call(m): - http_client.get('/') - self.assertTrue(m.called) - self.assertTrue(mock_request.called) - - test_auth_call() - - def test_auth_manual(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - - @mock.patch.object(cs.client, 'authenticate') - def test_auth_call(m): - cs.authenticate() - self.assertTrue(m.called) - - test_auth_call() diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_availability_zone.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_availability_zone.py deleted file mode 100644 index a7d6d82e28..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_availability_zone.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from novaclient.tests.unit.fixture_data import availability_zones as data -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit import utils -from novaclient.v2 import availability_zones - - -class AvailabilityZoneTest(utils.FixturedTestCase): - # NOTE(cyeoh): import shell here so the V3 version of - # this class can inherit off the v3 version of shell - from novaclient.v2 import shell # noqa - - data_fixture_class = data.V1 - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def setUp(self): - super(AvailabilityZoneTest, self).setUp() - self.availability_zone_type = self._get_availability_zone_type() - - def _get_availability_zone_type(self): - return availability_zones.AvailabilityZone - - def _assertZone(self, zone, name, status): - self.assertEqual(zone.zoneName, name) - self.assertEqual(zone.zoneState, status) - - def test_list_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=False) - self.assert_called('GET', '/os-availability-zone') - - for zone in zones: - self.assertIsInstance(zone, self.availability_zone_type) - - self.assertEqual(2, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('zone-2'), six.u('not available')] - - z0 = self.shell._treeizeAvailabilityZone(zones[0]) - z1 = self.shell._treeizeAvailabilityZone(zones[1]) - - self.assertEqual((1, 1), (len(z0), len(z1))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z1[0], l1[0], l1[1]) - - def test_detail_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=True) - self.assert_called('GET', '/os-availability-zone/detail') - - for zone in zones: - self.assertIsInstance(zone, self.availability_zone_type) - - self.assertEqual(3, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('|- fake_host-1'), six.u('')] - l2 = [six.u('| |- nova-compute'), - six.u('enabled :-) 2012-12-26 14:45:25')] - l3 = [six.u('internal'), six.u('available')] - l4 = [six.u('|- fake_host-1'), six.u('')] - l5 = [six.u('| |- nova-sched'), - six.u('enabled :-) 2012-12-26 14:45:25')] - l6 = [six.u('|- fake_host-2'), six.u('')] - l7 = [six.u('| |- nova-network'), - six.u('enabled XXX 2012-12-26 14:45:24')] - l8 = [six.u('zone-2'), six.u('not available')] - - z0 = self.shell._treeizeAvailabilityZone(zones[0]) - z1 = self.shell._treeizeAvailabilityZone(zones[1]) - z2 = self.shell._treeizeAvailabilityZone(zones[2]) - - self.assertEqual((3, 5, 1), (len(z0), len(z1), len(z2))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z0[1], l1[0], l1[1]) - self._assertZone(z0[2], l2[0], l2[1]) - self._assertZone(z1[0], l3[0], l3[1]) - self._assertZone(z1[1], l4[0], l4[1]) - self._assertZone(z1[2], l5[0], l5[1]) - self._assertZone(z1[3], l6[0], l6[1]) - self._assertZone(z1[4], l7[0], l7[1]) - self._assertZone(z2[0], l8[0], l8[1]) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_certs.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_certs.py deleted file mode 100644 index 6ec2258fc3..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_certs.py +++ /dev/null @@ -1,36 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import certs as data -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit import utils -from novaclient.v2 import certs - - -class CertsTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - cert_type = certs.Certificate - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_create_cert(self): - cert = self.cs.certs.create() - self.assert_called('POST', '/os-certificates') - self.assertIsInstance(cert, self.cert_type) - - def test_get_root_cert(self): - cert = self.cs.certs.get() - self.assert_called('GET', '/os-certificates/root') - self.assertIsInstance(cert, self.cert_type) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_client.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_client.py deleted file mode 100644 index b4c59ce381..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_client.py +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from keystoneclient import session - -from novaclient.tests.unit import utils -from novaclient.v2 import client - - -class ClientTest(utils.TestCase): - - def test_adapter_properties(self): - # sample of properties, there are many more - user_agent = uuid.uuid4().hex - endpoint_override = uuid.uuid4().hex - - s = session.Session() - c = client.Client(session=s, - user_agent=user_agent, - endpoint_override=endpoint_override) - - self.assertEqual(user_agent, c.client.user_agent) - self.assertEqual(endpoint_override, c.client.endpoint_override) - - def test_passing_interface(self): - endpoint_type = uuid.uuid4().hex - interface = uuid.uuid4().hex - - s = session.Session() - c = client.Client(session=s, - interface=interface, - endpoint_type=endpoint_type) - - self.assertEqual(interface, c.client.interface) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_cloudpipe.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_cloudpipe.py deleted file mode 100644 index 3ef9533cd0..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_cloudpipe.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import cloudpipe as data -from novaclient.tests.unit import utils -from novaclient.v2 import cloudpipe - - -class CloudpipeTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_list_cloudpipes(self): - cp = self.cs.cloudpipe.list() - self.assert_called('GET', '/os-cloudpipe') - [self.assertIsInstance(c, cloudpipe.Cloudpipe) for c in cp] - - def test_create(self): - project = "test" - cp = self.cs.cloudpipe.create(project) - body = {'cloudpipe': {'project_id': project}} - self.assert_called('POST', '/os-cloudpipe', body) - self.assertIsInstance(cp, six.string_types) - - def test_update(self): - self.cs.cloudpipe.update("192.168.1.1", 2345) - body = {'configure_project': {'vpn_ip': "192.168.1.1", - 'vpn_port': 2345}} - self.assert_called('PUT', '/os-cloudpipe/configure-project', body) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_fixed_ips.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_fixed_ips.py deleted file mode 100644 index 02ba39b6d0..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_fixed_ips.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import fixedips as data -from novaclient.tests.unit import utils - - -class FixedIpsTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_get_fixed_ip(self): - info = self.cs.fixed_ips.get(fixed_ip='192.168.1.1') - self.assert_called('GET', '/os-fixed-ips/192.168.1.1') - self.assertEqual('192.168.1.0/24', info.cidr) - self.assertEqual('192.168.1.1', info.address) - self.assertEqual('foo', info.hostname) - self.assertEqual('bar', info.host) - - def test_reserve_fixed_ip(self): - body = {"reserve": None} - self.cs.fixed_ips.reserve(fixed_ip='192.168.1.1') - self.assert_called('POST', '/os-fixed-ips/192.168.1.1/action', body) - - def test_unreserve_fixed_ip(self): - body = {"unreserve": None} - self.cs.fixed_ips.unreserve(fixed_ip='192.168.1.1') - self.assert_called('POST', '/os-fixed-ips/192.168.1.1/action', body) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_flavor_access.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_flavor_access.py deleted file mode 100644 index 109f177e66..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_flavor_access.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2 import fakes -from novaclient.v2 import flavor_access - - -cs = fakes.FakeClient() - - -class FlavorAccessTest(utils.TestCase): - - def test_list_access_by_flavor_private(self): - kwargs = {'flavor': cs.flavors.get(2)} - r = cs.flavor_access.list(**kwargs) - cs.assert_called('GET', '/flavors/2/os-flavor-access') - [self.assertIsInstance(a, flavor_access.FlavorAccess) for a in r] - - def test_add_tenant_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj2' - r = cs.flavor_access.add_tenant_access(flavor, tenant) - - body = { - "addTenantAccess": { - "tenant": "proj2" - } - } - - cs.assert_called('POST', '/flavors/2/action', body) - [self.assertIsInstance(a, flavor_access.FlavorAccess) for a in r] - - def test_remove_tenant_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj2' - r = cs.flavor_access.remove_tenant_access(flavor, tenant) - - body = { - "removeTenantAccess": { - "tenant": "proj2" - } - } - - cs.assert_called('POST', '/flavors/2/action', body) - [self.assertIsInstance(a, flavor_access.FlavorAccess) for a in r] - - def test_repr_flavor_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj3' - r = cs.flavor_access.add_tenant_access(flavor, tenant) - - def get_expected(flavor_access): - return ("" % - (flavor_access.flavor_id, flavor_access.tenant_id)) - - for a in r: - self.assertEqual(get_expected(a), repr(a)) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_flavors.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_flavors.py deleted file mode 100644 index 27b77c068f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_flavors.py +++ /dev/null @@ -1,219 +0,0 @@ -# Copyright (c) 2013, OpenStack -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from novaclient import exceptions -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2 import fakes -from novaclient.v2 import flavors - - -class FlavorsTest(utils.TestCase): - def setUp(self): - super(FlavorsTest, self).setUp() - self.cs = self._get_fake_client() - self.flavor_type = self._get_flavor_type() - - def _get_fake_client(self): - return fakes.FakeClient() - - def _get_flavor_type(self): - return flavors.Flavor - - def test_list_flavors(self): - fl = self.cs.flavors.list() - self.cs.assert_called('GET', '/flavors/detail') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_undetailed(self): - fl = self.cs.flavors.list(detailed=False) - self.cs.assert_called('GET', '/flavors') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_is_public_none(self): - fl = self.cs.flavors.list(is_public=None) - self.cs.assert_called('GET', '/flavors/detail?is_public=None') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_is_public_false(self): - fl = self.cs.flavors.list(is_public=False) - self.cs.assert_called('GET', '/flavors/detail?is_public=False') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_is_public_true(self): - fl = self.cs.flavors.list(is_public=True) - self.cs.assert_called('GET', '/flavors/detail') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_get_flavor_details(self): - f = self.cs.flavors.get(1) - self.cs.assert_called('GET', '/flavors/1') - self.assertIsInstance(f, self.flavor_type) - self.assertEqual(256, f.ram) - self.assertEqual(10, f.disk) - self.assertEqual(10, f.ephemeral) - self.assertEqual(True, f.is_public) - - def test_get_flavor_details_alphanum_id(self): - f = self.cs.flavors.get('aa1') - self.cs.assert_called('GET', '/flavors/aa1') - self.assertIsInstance(f, self.flavor_type) - self.assertEqual(128, f.ram) - self.assertEqual(0, f.disk) - self.assertEqual(0, f.ephemeral) - self.assertEqual(True, f.is_public) - - def test_get_flavor_details_diablo(self): - f = self.cs.flavors.get(3) - self.cs.assert_called('GET', '/flavors/3') - self.assertIsInstance(f, self.flavor_type) - self.assertEqual(256, f.ram) - self.assertEqual(10, f.disk) - self.assertEqual('N/A', f.ephemeral) - self.assertEqual('N/A', f.is_public) - - def test_find(self): - f = self.cs.flavors.find(ram=256) - self.cs.assert_called('GET', '/flavors/detail') - self.assertEqual('256 MB Server', f.name) - - f = self.cs.flavors.find(disk=0) - self.assertEqual('128 MB Server', f.name) - - self.assertRaises(exceptions.NotFound, self.cs.flavors.find, - disk=12345) - - def _create_body(self, name, ram, vcpus, disk, ephemeral, id, swap, - rxtx_factor, is_public): - return { - "flavor": { - "name": name, - "ram": ram, - "vcpus": vcpus, - "disk": disk, - "OS-FLV-EXT-DATA:ephemeral": ephemeral, - "id": id, - "swap": swap, - "rxtx_factor": rxtx_factor, - "os-flavor-access:is_public": is_public, - } - } - - def test_create(self): - f = self.cs.flavors.create("flavorcreate", 512, 1, 10, 1234, - ephemeral=10, is_public=False) - - body = self._create_body("flavorcreate", 512, 1, 10, 10, 1234, 0, 1.0, - False) - - self.cs.assert_called('POST', '/flavors', body) - self.assertIsInstance(f, self.flavor_type) - - def test_create_with_id_as_string(self): - flavor_id = 'foobar' - f = self.cs.flavors.create("flavorcreate", 512, - 1, 10, flavor_id, ephemeral=10, - is_public=False) - - body = self._create_body("flavorcreate", 512, 1, 10, 10, flavor_id, 0, - 1.0, False) - - self.cs.assert_called('POST', '/flavors', body) - self.assertIsInstance(f, self.flavor_type) - - def test_create_ephemeral_ispublic_defaults(self): - f = self.cs.flavors.create("flavorcreate", 512, 1, 10, 1234) - - body = self._create_body("flavorcreate", 512, 1, 10, 0, 1234, 0, - 1.0, True) - - self.cs.assert_called('POST', '/flavors', body) - self.assertIsInstance(f, self.flavor_type) - - def test_invalid_parameters_create(self): - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", "invalid", 1, 10, 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, "invalid", 10, 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, "invalid", 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap="invalid", - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap=0, - ephemeral="invalid", rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap=0, - ephemeral=0, rxtx_factor="invalid", is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public='invalid') - - def test_delete(self): - self.cs.flavors.delete("flavordelete") - self.cs.assert_called('DELETE', '/flavors/flavordelete') - - def test_delete_with_flavor_instance(self): - f = self.cs.flavors.get(2) - self.cs.flavors.delete(f) - self.cs.assert_called('DELETE', '/flavors/2') - - def test_delete_with_flavor_instance_method(self): - f = self.cs.flavors.get(2) - f.delete() - self.cs.assert_called('DELETE', '/flavors/2') - - def test_set_keys(self): - f = self.cs.flavors.get(1) - f.set_keys({'k1': 'v1'}) - self.cs.assert_called('POST', '/flavors/1/os-extra_specs', - {"extra_specs": {'k1': 'v1'}}) - - def test_set_with_valid_keys(self): - valid_keys = ['key4', 'month.price', 'I-Am:AK-ey.44-', - 'key with spaces and _'] - - f = self.cs.flavors.get(4) - for key in valid_keys: - f.set_keys({key: 'v4'}) - self.cs.assert_called('POST', '/flavors/4/os-extra_specs', - {"extra_specs": {key: 'v4'}}) - - def test_set_with_invalid_keys(self): - invalid_keys = ['/1', '?1', '%1', '<', '>'] - - f = self.cs.flavors.get(1) - for key in invalid_keys: - self.assertRaises(exceptions.CommandError, f.set_keys, {key: 'v1'}) - - @mock.patch.object(flavors.FlavorManager, '_delete') - def test_unset_keys(self, mock_delete): - f = self.cs.flavors.get(1) - keys = ['k1', 'k2'] - f.unset_keys(keys) - mock_delete.assert_has_calls([ - mock.call("/flavors/1/os-extra_specs/k1"), - mock.call("/flavors/1/os-extra_specs/k2") - ]) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ip_dns.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ip_dns.py deleted file mode 100644 index ec20e56c5f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ip_dns.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import floatingips as data -from novaclient.tests.unit import utils -from novaclient.v2 import floating_ip_dns - - -class FloatingIPDNSDomainTest(utils.FixturedTestCase): - - testdomain = "testdomain" - client_fixture_class = client.V1 - data_fixture_class = data.DNSFixture - - def test_dns_domains(self): - domainlist = self.cs.dns_domains.domains() - self.assertEqual(2, len(domainlist)) - - for entry in domainlist: - self.assertIsInstance(entry, - floating_ip_dns.FloatingIPDNSDomain) - - self.assertEqual('example.com', domainlist[1].domain) - - def test_create_private_domain(self): - self.cs.dns_domains.create_private(self.testdomain, 'test_avzone') - self.assert_called('PUT', '/os-floating-ip-dns/%s' % - self.testdomain) - - def test_create_public_domain(self): - self.cs.dns_domains.create_public(self.testdomain, 'test_project') - self.assert_called('PUT', '/os-floating-ip-dns/%s' % - self.testdomain) - - def test_delete_domain(self): - self.cs.dns_domains.delete(self.testdomain) - self.assert_called('DELETE', '/os-floating-ip-dns/%s' % - self.testdomain) - - -class FloatingIPDNSEntryTest(utils.FixturedTestCase): - - testname = "testname" - testip = "1.2.3.4" - testdomain = "testdomain" - testtype = "A" - client_fixture_class = client.V1 - data_fixture_class = data.DNSFixture - - def test_get_dns_entries_by_ip(self): - entries = self.cs.dns_entries.get_for_ip(self.testdomain, - ip=self.testip) - self.assertEqual(2, len(entries)) - - for entry in entries: - self.assertIsInstance(entry, - floating_ip_dns.FloatingIPDNSEntry) - - self.assertEqual('host2', entries[1].dns_entry['name']) - self.assertEqual(entries[1].dns_entry['ip'], self.testip) - - def test_get_dns_entry_by_name(self): - entry = self.cs.dns_entries.get(self.testdomain, - self.testname) - self.assertIsInstance(entry, floating_ip_dns.FloatingIPDNSEntry) - self.assertEqual(entry.name, self.testname) - - def test_create_entry(self): - self.cs.dns_entries.create(self.testdomain, - self.testname, - self.testip, - self.testtype) - - self.assert_called('PUT', '/os-floating-ip-dns/%s/entries/%s' % - (self.testdomain, self.testname)) - - def test_delete_entry(self): - self.cs.dns_entries.delete(self.testdomain, self.testname) - self.assert_called('DELETE', '/os-floating-ip-dns/%s/entries/%s' % - (self.testdomain, self.testname)) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ip_pools.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ip_pools.py deleted file mode 100644 index a138fc285c..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ip_pools.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import floatingips as data -from novaclient.tests.unit import utils -from novaclient.v2 import floating_ip_pools - - -class TestFloatingIPPools(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.PoolsFixture - - def test_list_floating_ips(self): - fl = self.cs.floating_ip_pools.list() - self.assert_called('GET', '/os-floating-ip-pools') - for f in fl: - self.assertIsInstance(f, floating_ip_pools.FloatingIPPool) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ips.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ips.py deleted file mode 100644 index 2b091a516b..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ips.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import floatingips as data -from novaclient.tests.unit import utils -from novaclient.v2 import floating_ips - - -class FloatingIPsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.FloatingFixture - - def test_list_floating_ips(self): - fips = self.cs.floating_ips.list() - self.assert_called('GET', '/os-floating-ips') - for fip in fips: - self.assertIsInstance(fip, floating_ips.FloatingIP) - - def test_list_floating_ips_all_tenants(self): - fips = self.cs.floating_ips.list(all_tenants=True) - self.assert_called('GET', '/os-floating-ips?all_tenants=1') - for fip in fips: - self.assertIsInstance(fip, floating_ips.FloatingIP) - - def test_delete_floating_ip(self): - fl = self.cs.floating_ips.list()[0] - fl.delete() - self.assert_called('DELETE', '/os-floating-ips/1') - self.cs.floating_ips.delete(1) - self.assert_called('DELETE', '/os-floating-ips/1') - self.cs.floating_ips.delete(fl) - self.assert_called('DELETE', '/os-floating-ips/1') - - def test_create_floating_ip(self): - fl = self.cs.floating_ips.create() - self.assert_called('POST', '/os-floating-ips') - self.assertIsNone(fl.pool) - self.assertIsInstance(fl, floating_ips.FloatingIP) - - def test_create_floating_ip_with_pool(self): - fl = self.cs.floating_ips.create('nova') - self.assert_called('POST', '/os-floating-ips') - self.assertEqual('nova', fl.pool) - self.assertIsInstance(fl, floating_ips.FloatingIP) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ips_bulk.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ips_bulk.py deleted file mode 100644 index 69b553f24c..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_floating_ips_bulk.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import floatingips as data -from novaclient.tests.unit import utils -from novaclient.v2 import floating_ips_bulk - - -class FloatingIPsBulkTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.BulkFixture - - def test_list_floating_ips_bulk(self): - fl = self.cs.floating_ips_bulk.list() - self.assert_called('GET', '/os-floating-ips-bulk') - [self.assertIsInstance(f, floating_ips_bulk.FloatingIP) - for f in fl] - - def test_list_floating_ips_bulk_host_filter(self): - fl = self.cs.floating_ips_bulk.list('testHost') - self.assert_called('GET', '/os-floating-ips-bulk/testHost') - [self.assertIsInstance(f, floating_ips_bulk.FloatingIP) - for f in fl] - - def test_create_floating_ips_bulk(self): - fl = self.cs.floating_ips_bulk.create('192.168.1.0/30') - body = {'floating_ips_bulk_create': {'ip_range': '192.168.1.0/30'}} - self.assert_called('POST', '/os-floating-ips-bulk', body) - self.assertEqual(fl.ip_range, - body['floating_ips_bulk_create']['ip_range']) - - def test_create_floating_ips_bulk_with_pool_and_host(self): - fl = self.cs.floating_ips_bulk.create('192.168.1.0/30', 'poolTest', - 'interfaceTest') - body = {'floating_ips_bulk_create': { - 'ip_range': '192.168.1.0/30', 'pool': 'poolTest', - 'interface': 'interfaceTest'}} - self.assert_called('POST', '/os-floating-ips-bulk', body) - self.assertEqual(fl.ip_range, - body['floating_ips_bulk_create']['ip_range']) - self.assertEqual(fl.pool, - body['floating_ips_bulk_create']['pool']) - self.assertEqual(fl.interface, - body['floating_ips_bulk_create']['interface']) - - def test_delete_floating_ips_bulk(self): - fl = self.cs.floating_ips_bulk.delete('192.168.1.0/30') - body = {'ip_range': '192.168.1.0/30'} - self.assert_called('PUT', '/os-floating-ips-bulk/delete', body) - self.assertEqual(fl.floating_ips_bulk_delete, body['ip_range']) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_fping.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_fping.py deleted file mode 100644 index b9ecc39911..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_fping.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import fping as data -from novaclient.tests.unit import utils -from novaclient.v2 import fping - - -class FpingTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_fping_repr(self): - r = self.cs.fping.get(1) - self.assertEqual("", repr(r)) - - def test_list_fpings(self): - fl = self.cs.fping.list() - self.assert_called('GET', '/os-fping') - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assertEqual("fake-project", f.project_id) - self.assertEqual(True, f.alive) - - def test_list_fpings_all_tenants(self): - fl = self.cs.fping.list(all_tenants=True) - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assert_called('GET', '/os-fping?all_tenants=1') - - def test_list_fpings_exclude(self): - fl = self.cs.fping.list(exclude=['1']) - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assert_called('GET', '/os-fping?exclude=1') - - def test_list_fpings_include(self): - fl = self.cs.fping.list(include=['1']) - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assert_called('GET', '/os-fping?include=1') - - def test_get_fping(self): - f = self.cs.fping.get(1) - self.assert_called('GET', '/os-fping/1') - self.assertIsInstance(f, fping.Fping) - self.assertEqual("fake-project", f.project_id) - self.assertEqual(True, f.alive) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_hosts.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_hosts.py deleted file mode 100644 index 029964b6b5..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_hosts.py +++ /dev/null @@ -1,84 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import hosts as data -from novaclient.tests.unit import utils -from novaclient.v2 import hosts - - -class HostsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def test_describe_resource(self): - hs = self.cs.hosts.get('host') - self.assert_called('GET', '/os-hosts/host') - [self.assertIsInstance(h, hosts.Host) for h in hs] - - def test_list_host(self): - hs = self.cs.hosts.list() - self.assert_called('GET', '/os-hosts') - [self.assertIsInstance(h, hosts.Host) for h in hs] - [self.assertEqual(h.zone, 'nova1') for h in hs] - - def test_list_host_with_zone(self): - hs = self.cs.hosts.list('nova') - self.assert_called('GET', '/os-hosts?zone=nova') - [self.assertIsInstance(h, hosts.Host) for h in hs] - [self.assertEqual(h.zone, 'nova') for h in hs] - - def test_update_enable(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"status": "enabled"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', values) - self.assertIsInstance(result, hosts.Host) - - def test_update_maintenance(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"maintenance_mode": "enable"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', values) - self.assertIsInstance(result, hosts.Host) - - def test_update_both(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"status": "enabled", - "maintenance_mode": "enable"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', values) - self.assertIsInstance(result, hosts.Host) - - def test_host_startup(self): - host = self.cs.hosts.get('sample_host')[0] - host.startup() - self.assert_called( - 'GET', '/os-hosts/sample_host/startup') - - def test_host_reboot(self): - host = self.cs.hosts.get('sample_host')[0] - host.reboot() - self.assert_called( - 'GET', '/os-hosts/sample_host/reboot') - - def test_host_shutdown(self): - host = self.cs.hosts.get('sample_host')[0] - host.shutdown() - self.assert_called( - 'GET', '/os-hosts/sample_host/shutdown') - - def test_hosts_repr(self): - hs = self.cs.hosts.get('host') - self.assertEqual('', repr(hs[0])) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_hypervisors.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_hypervisors.py deleted file mode 100644 index b297c12470..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_hypervisors.py +++ /dev/null @@ -1,178 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import hypervisors as data -from novaclient.tests.unit import utils - - -class HypervisorsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def compare_to_expected(self, expected, hyper): - for key, value in expected.items(): - self.assertEqual(getattr(hyper, key), value) - - def test_hypervisor_index(self): - expected = [ - dict(id=1234, hypervisor_hostname='hyper1'), - dict(id=5678, hypervisor_hostname='hyper2')] - - result = self.cs.hypervisors.list(False) - self.assert_called('GET', '/os-hypervisors') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_detail(self): - expected = [ - dict(id=1234, - service=dict(id=1, host='compute1'), - vcpus=4, - memory_mb=10 * 1024, - local_gb=250, - vcpus_used=2, - memory_mb_used=5 * 1024, - local_gb_used=125, - hypervisor_type="xen", - hypervisor_version=3, - hypervisor_hostname="hyper1", - free_ram_mb=5 * 1024, - free_disk_gb=125, - current_workload=2, - running_vms=2, - cpu_info='cpu_info', - disk_available_least=100), - dict(id=2, - service=dict(id=2, host="compute2"), - vcpus=4, - memory_mb=10 * 1024, - local_gb=250, - vcpus_used=2, - memory_mb_used=5 * 1024, - local_gb_used=125, - hypervisor_type="xen", - hypervisor_version=3, - hypervisor_hostname="hyper2", - free_ram_mb=5 * 1024, - free_disk_gb=125, - current_workload=2, - running_vms=2, - cpu_info='cpu_info', - disk_available_least=100)] - - result = self.cs.hypervisors.list() - self.assert_called('GET', '/os-hypervisors/detail') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_search(self): - expected = [ - dict(id=1234, hypervisor_hostname='hyper1'), - dict(id=5678, hypervisor_hostname='hyper2')] - - result = self.cs.hypervisors.search('hyper') - self.assert_called('GET', '/os-hypervisors/hyper/search') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_servers(self): - expected = [ - dict(id=1234, - hypervisor_hostname='hyper1', - servers=[ - dict(name='inst1', uuid='uuid1'), - dict(name='inst2', uuid='uuid2')]), - dict(id=5678, - hypervisor_hostname='hyper2', - servers=[ - dict(name='inst3', uuid='uuid3'), - dict(name='inst4', uuid='uuid4')]), - ] - - result = self.cs.hypervisors.search('hyper', True) - self.assert_called('GET', '/os-hypervisors/hyper/servers') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_get(self): - expected = dict( - id=1234, - service=dict(id=1, host='compute1'), - vcpus=4, - memory_mb=10 * 1024, - local_gb=250, - vcpus_used=2, - memory_mb_used=5 * 1024, - local_gb_used=125, - hypervisor_type="xen", - hypervisor_version=3, - hypervisor_hostname="hyper1", - free_ram_mb=5 * 1024, - free_disk_gb=125, - current_workload=2, - running_vms=2, - cpu_info='cpu_info', - disk_available_least=100) - - result = self.cs.hypervisors.get(1234) - self.assert_called('GET', '/os-hypervisors/1234') - - self.compare_to_expected(expected, result) - - def test_hypervisor_uptime(self): - expected = dict( - id=1234, - hypervisor_hostname="hyper1", - uptime="fake uptime") - - result = self.cs.hypervisors.uptime(1234) - self.assert_called('GET', '/os-hypervisors/1234/uptime') - - self.compare_to_expected(expected, result) - - def test_hypervisor_statistics(self): - expected = dict( - count=2, - vcpus=8, - memory_mb=20 * 1024, - local_gb=500, - vcpus_used=4, - memory_mb_used=10 * 1024, - local_gb_used=250, - free_ram_mb=10 * 1024, - free_disk_gb=250, - current_workload=4, - running_vms=4, - disk_available_least=200, - ) - - result = self.cs.hypervisors.statistics() - self.assert_called('GET', '/os-hypervisors/statistics') - - self.compare_to_expected(expected, result) - - def test_hypervisor_statistics_data_model(self): - result = self.cs.hypervisor_stats.statistics() - self.assert_called('GET', '/os-hypervisors/statistics') - - # Test for Bug #1370415, the line below used to raise AttributeError - self.assertEqual("", - result.__repr__()) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_images.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_images.py deleted file mode 100644 index 1f8104edbb..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_images.py +++ /dev/null @@ -1,66 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import images as data -from novaclient.tests.unit import utils -from novaclient.v2 import images - - -class ImagesTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def test_list_images(self): - il = self.cs.images.list() - self.assert_called('GET', '/images/detail') - [self.assertIsInstance(i, images.Image) for i in il] - - def test_list_images_undetailed(self): - il = self.cs.images.list(detailed=False) - self.assert_called('GET', '/images') - [self.assertIsInstance(i, images.Image) for i in il] - - def test_list_images_with_limit(self): - self.cs.images.list(limit=4) - self.assert_called('GET', '/images/detail?limit=4') - - def test_get_image_details(self): - i = self.cs.images.get(1) - self.assert_called('GET', '/images/1') - self.assertIsInstance(i, images.Image) - self.assertEqual(1, i.id) - self.assertEqual('CentOS 5.2', i.name) - - def test_delete_image(self): - self.cs.images.delete(1) - self.assert_called('DELETE', '/images/1') - - def test_delete_meta(self): - self.cs.images.delete_meta(1, {'test_key': 'test_value'}) - self.assert_called('DELETE', '/images/1/metadata/test_key') - - def test_set_meta(self): - self.cs.images.set_meta(1, {'test_key': 'test_value'}) - self.assert_called('POST', '/images/1/metadata', - {"metadata": {'test_key': 'test_value'}}) - - def test_find(self): - i = self.cs.images.find(name="CentOS 5.2") - self.assertEqual(1, i.id) - self.assert_called('GET', '/images/1') - - iml = self.cs.images.findall(status='SAVING') - self.assertEqual(1, len(iml)) - self.assertEqual('My Server Backup', iml[0].name) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_keypairs.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_keypairs.py deleted file mode 100644 index 91c249f824..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_keypairs.py +++ /dev/null @@ -1,64 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import keypairs as data -from novaclient.tests.unit import utils -from novaclient.v2 import keypairs - - -class KeypairsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def setUp(self): - super(KeypairsTest, self).setUp() - self.keypair_type = self._get_keypair_type() - self.keypair_prefix = self._get_keypair_prefix() - - def _get_keypair_type(self): - return keypairs.Keypair - - def _get_keypair_prefix(self): - return keypairs.KeypairManager.keypair_prefix - - def test_get_keypair(self): - kp = self.cs.keypairs.get('test') - self.assert_called('GET', '/%s/test' % self.keypair_prefix) - self.assertIsInstance(kp, keypairs.Keypair) - self.assertEqual('test', kp.name) - - def test_list_keypairs(self): - kps = self.cs.keypairs.list() - self.assert_called('GET', '/%s' % self.keypair_prefix) - [self.assertIsInstance(kp, keypairs.Keypair) for kp in kps] - - def test_delete_keypair(self): - kp = self.cs.keypairs.list()[0] - kp.delete() - self.assert_called('DELETE', '/%s/test' % self.keypair_prefix) - self.cs.keypairs.delete('test') - self.assert_called('DELETE', '/%s/test' % self.keypair_prefix) - self.cs.keypairs.delete(kp) - self.assert_called('DELETE', '/%s/test' % self.keypair_prefix) - - def test_create_keypair(self): - kp = self.cs.keypairs.create("foo") - self.assert_called('POST', '/%s' % self.keypair_prefix) - self.assertIsInstance(kp, keypairs.Keypair) - - def test_import_keypair(self): - kp = self.cs.keypairs.create("foo", "fake-public-key") - self.assert_called('POST', '/%s' % self.keypair_prefix) - self.assertIsInstance(kp, keypairs.Keypair) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_limits.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_limits.py deleted file mode 100644 index 94a62c5c0c..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_limits.py +++ /dev/null @@ -1,88 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import limits as data -from novaclient.tests.unit import utils -from novaclient.v2 import limits - - -class LimitsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_get_limits(self): - obj = self.cs.limits.get() - self.assert_called('GET', '/limits') - self.assertIsInstance(obj, limits.Limits) - - def test_get_limits_for_a_tenant(self): - obj = self.cs.limits.get(tenant_id=1234) - self.assert_called('GET', '/limits?tenant_id=1234') - self.assertIsInstance(obj, limits.Limits) - - def test_absolute_limits(self): - obj = self.cs.limits.get() - - expected = ( - limits.AbsoluteLimit("maxTotalRAMSize", 51200), - limits.AbsoluteLimit("maxServerMeta", 5), - limits.AbsoluteLimit("maxImageMeta", 5), - limits.AbsoluteLimit("maxPersonality", 5), - limits.AbsoluteLimit("maxPersonalitySize", 10240), - ) - - abs_limits = list(obj.absolute) - self.assertEqual(len(abs_limits), len(expected)) - - for limit in abs_limits: - self.assertTrue(limit in expected) - - def test_absolute_limits_reserved(self): - obj = self.cs.limits.get(reserved=True) - - expected = ( - limits.AbsoluteLimit("maxTotalRAMSize", 51200), - limits.AbsoluteLimit("maxServerMeta", 5), - limits.AbsoluteLimit("maxImageMeta", 5), - limits.AbsoluteLimit("maxPersonality", 5), - limits.AbsoluteLimit("maxPersonalitySize", 10240), - ) - - self.assert_called('GET', '/limits?reserved=1') - abs_limits = list(obj.absolute) - self.assertEqual(len(abs_limits), len(expected)) - - for limit in abs_limits: - self.assertTrue(limit in expected) - - def test_rate_limits(self): - obj = self.cs.limits.get() - - expected = ( - limits.RateLimit('POST', '*', '.*', 10, 2, 'MINUTE', - '2011-12-15T22:42:45Z'), - limits.RateLimit('PUT', '*', '.*', 10, 2, 'MINUTE', - '2011-12-15T22:42:45Z'), - limits.RateLimit('DELETE', '*', '.*', 100, 100, 'MINUTE', - '2011-12-15T22:42:45Z'), - limits.RateLimit('POST', '*/servers', '^/servers', 25, 24, 'DAY', - '2011-12-15T22:42:45Z'), - ) - - rate_limits = list(obj.rate) - self.assertEqual(len(rate_limits), len(expected)) - - for limit in rate_limits: - self.assertTrue(limit in expected) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_networks.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_networks.py deleted file mode 100644 index a45ba80dc9..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_networks.py +++ /dev/null @@ -1,106 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import networks as data -from novaclient.tests.unit import utils -from novaclient.v2 import networks - - -class NetworksTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_list_networks(self): - fl = self.cs.networks.list() - self.assert_called('GET', '/os-networks') - [self.assertIsInstance(f, networks.Network) for f in fl] - - def test_get_network(self): - f = self.cs.networks.get(1) - self.assert_called('GET', '/os-networks/1') - self.assertIsInstance(f, networks.Network) - - def test_delete(self): - self.cs.networks.delete('networkdelete') - self.assert_called('DELETE', '/os-networks/networkdelete') - - def test_create(self): - f = self.cs.networks.create(label='foo') - self.assert_called('POST', '/os-networks', - {'network': {'label': 'foo'}}) - self.assertIsInstance(f, networks.Network) - - def test_create_allparams(self): - params = { - 'label': 'bar', - 'bridge': 'br0', - 'bridge_interface': 'int0', - 'cidr': '192.0.2.0/24', - 'cidr_v6': '2001:DB8::/32', - 'dns1': '1.1.1.1', - 'dns2': '1.1.1.2', - 'fixed_cidr': '198.51.100.0/24', - 'gateway': '192.0.2.1', - 'gateway_v6': '2001:DB8::1', - 'multi_host': 'T', - 'priority': '1', - 'project_id': '1', - 'vlan': 5, - 'vlan_start': 1, - 'vpn_start': 1, - 'mtu': 1500, - 'enable_dhcp': 'T', - 'dhcp_server': '1920.2.2', - 'share_address': 'T', - 'allowed_start': '192.0.2.10', - 'allowed_end': '192.0.2.20', - } - - f = self.cs.networks.create(**params) - self.assert_called('POST', '/os-networks', {'network': params}) - self.assertIsInstance(f, networks.Network) - - def test_associate_project(self): - self.cs.networks.associate_project('networktest') - self.assert_called('POST', '/os-networks/add', - {'id': 'networktest'}) - - def test_associate_host(self): - self.cs.networks.associate_host('networktest', 'testHost') - self.assert_called('POST', '/os-networks/networktest/action', - {'associate_host': 'testHost'}) - - def test_disassociate(self): - self.cs.networks.disassociate('networkdisassociate') - self.assert_called('POST', - '/os-networks/networkdisassociate/action', - {'disassociate': None}) - - def test_disassociate_host_only(self): - self.cs.networks.disassociate('networkdisassociate', True, False) - self.assert_called('POST', - '/os-networks/networkdisassociate/action', - {'disassociate_host': None}) - - def test_disassociate_project(self): - self.cs.networks.disassociate('networkdisassociate', False, True) - self.assert_called('POST', - '/os-networks/networkdisassociate/action', - {'disassociate_project': None}) - - def test_add(self): - self.cs.networks.add('networkadd') - self.assert_called('POST', '/os-networks/add', - {'id': 'networkadd'}) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_quota_classes.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_quota_classes.py deleted file mode 100644 index 467ff830d8..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_quota_classes.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2 import fakes - - -cs = fakes.FakeClient() - - -class QuotaClassSetsTest(utils.TestCase): - - def test_class_quotas_get(self): - class_name = 'test' - cs.quota_classes.get(class_name) - cs.assert_called('GET', '/os-quota-class-sets/%s' % class_name) - - def test_update_quota(self): - q = cs.quota_classes.get('test') - q.update(cores=2) - cs.assert_called('PUT', '/os-quota-class-sets/test') - - def test_refresh_quota(self): - q = cs.quota_classes.get('test') - q2 = cs.quota_classes.get('test') - self.assertEqual(q.cores, q2.cores) - q2.cores = 0 - self.assertNotEqual(q.cores, q2.cores) - q2.get() - self.assertEqual(q.cores, q2.cores) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_quotas.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_quotas.py deleted file mode 100644 index 43f8ce1d8f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_quotas.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import quotas as data -from novaclient.tests.unit import utils - - -class QuotaSetsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def test_tenant_quotas_get(self): - tenant_id = 'test' - self.cs.quotas.get(tenant_id) - self.assert_called('GET', '/os-quota-sets/%s' % tenant_id) - - def test_user_quotas_get(self): - tenant_id = 'test' - user_id = 'fake_user' - self.cs.quotas.get(tenant_id, user_id=user_id) - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - self.assert_called('GET', url) - - def test_tenant_quotas_defaults(self): - tenant_id = '97f4c221bff44578b0300df4ef119353' - self.cs.quotas.defaults(tenant_id) - self.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id) - - def test_force_update_quota(self): - q = self.cs.quotas.get('97f4c221bff44578b0300df4ef119353') - q.update(cores=2, force=True) - self.assert_called( - 'PUT', '/os-quota-sets/97f4c221bff44578b0300df4ef119353', - {'quota_set': {'force': True, - 'cores': 2, - 'tenant_id': '97f4c221bff44578b0300df4ef119353'}}) - - def test_quotas_delete(self): - tenant_id = 'test' - self.cs.quotas.delete(tenant_id) - self.assert_called('DELETE', '/os-quota-sets/%s' % tenant_id) - - def test_user_quotas_delete(self): - tenant_id = 'test' - user_id = 'fake_user' - self.cs.quotas.delete(tenant_id, user_id=user_id) - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - self.assert_called('DELETE', url) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_security_group_rules.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_security_group_rules.py deleted file mode 100644 index 8375198212..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_security_group_rules.py +++ /dev/null @@ -1,89 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import exceptions -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import security_group_rules as data -from novaclient.tests.unit import utils -from novaclient.v2 import security_group_rules - - -class SecurityGroupRulesTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_delete_security_group_rule(self): - self.cs.security_group_rules.delete(1) - self.assert_called('DELETE', '/os-security-group-rules/1') - - def test_create_security_group_rule(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16") - - body = { - "security_group_rule": { - "ip_protocol": "tcp", - "from_port": 1, - "to_port": 65535, - "cidr": "10.0.0.0/16", - "group_id": None, - "parent_group_id": 1, - } - } - - self.assert_called('POST', '/os-security-group-rules', body) - self.assertTrue(isinstance(sg, security_group_rules.SecurityGroupRule)) - - def test_create_security_group_group_rule(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16", 101) - - body = { - "security_group_rule": { - "ip_protocol": "tcp", - "from_port": 1, - "to_port": 65535, - "cidr": "10.0.0.0/16", - "group_id": 101, - "parent_group_id": 1, - } - } - - self.assert_called('POST', '/os-security-group-rules', body) - self.assertTrue(isinstance(sg, security_group_rules.SecurityGroupRule)) - - def test_invalid_parameters_create(self): - self.assertRaises(exceptions.CommandError, - self.cs.security_group_rules.create, - 1, "invalid_ip_protocol", 1, 65535, - "10.0.0.0/16", 101) - self.assertRaises(exceptions.CommandError, - self.cs.security_group_rules.create, - 1, "tcp", "invalid_from_port", 65535, - "10.0.0.0/16", 101) - self.assertRaises(exceptions.CommandError, - self.cs.security_group_rules.create, - 1, "tcp", 1, "invalid_to_port", - "10.0.0.0/16", 101) - - def test_security_group_rule_str(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16") - self.assertEqual('1', str(sg)) - - def test_security_group_rule_del(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16") - sg.delete() - self.assert_called('DELETE', '/os-security-group-rules/1') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_security_groups.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_security_groups.py deleted file mode 100644 index d05a93aa1f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_security_groups.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import security_groups as data -from novaclient.tests.unit import utils -from novaclient.v2 import security_groups - - -class SecurityGroupsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def _do_test_list_security_groups(self, search_opts, path): - sgs = self.cs.security_groups.list(search_opts=search_opts) - self.assert_called('GET', path) - for sg in sgs: - self.assertIsInstance(sg, security_groups.SecurityGroup) - - def test_list_security_groups_all_tenants_on(self): - self._do_test_list_security_groups( - None, '/os-security-groups') - - def test_list_security_groups_all_tenants_on_with_search_opts(self): - self._do_test_list_security_groups( - {'all_tenants': 1}, '/os-security-groups?all_tenants=1') - - def test_list_security_groups_all_tenants_off(self): - self._do_test_list_security_groups( - {'all_tenants': 0}, '/os-security-groups') - - def test_get_security_groups(self): - sg = self.cs.security_groups.get(1) - self.assert_called('GET', '/os-security-groups/1') - self.assertIsInstance(sg, security_groups.SecurityGroup) - self.assertEqual('1', str(sg)) - - def test_delete_security_group(self): - sg = self.cs.security_groups.list()[0] - sg.delete() - self.assert_called('DELETE', '/os-security-groups/1') - self.cs.security_groups.delete(1) - self.assert_called('DELETE', '/os-security-groups/1') - self.cs.security_groups.delete(sg) - self.assert_called('DELETE', '/os-security-groups/1') - - def test_create_security_group(self): - sg = self.cs.security_groups.create("foo", "foo barr") - self.assert_called('POST', '/os-security-groups') - self.assertIsInstance(sg, security_groups.SecurityGroup) - - def test_update_security_group(self): - sg = self.cs.security_groups.list()[0] - secgroup = self.cs.security_groups.update(sg, "update", "update") - self.assert_called('PUT', '/os-security-groups/1') - self.assertIsInstance(secgroup, security_groups.SecurityGroup) - - def test_refresh_security_group(self): - sg = self.cs.security_groups.get(1) - sg2 = self.cs.security_groups.get(1) - self.assertEqual(sg.name, sg2.name) - sg2.name = "should be test" - self.assertNotEqual(sg.name, sg2.name) - sg2.get() - self.assertEqual(sg.name, sg2.name) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_server_groups.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_server_groups.py deleted file mode 100644 index fcda2dec7e..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_server_groups.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2014 VMware, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import server_groups as data -from novaclient.tests.unit import utils -from novaclient.v2 import server_groups - - -class ServerGroupsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_list_server_groups(self): - result = self.cs.server_groups.list() - self.assert_called('GET', '/os-server-groups') - for server_group in result: - self.assertTrue(isinstance(server_group, - server_groups.ServerGroup)) - - def test_create_server_group(self): - kwargs = {'name': 'ig1', - 'policies': ['anti-affinity']} - server_group = self.cs.server_groups.create(**kwargs) - body = {'server_group': kwargs} - self.assert_called('POST', '/os-server-groups', body) - self.assertTrue(isinstance(server_group, - server_groups.ServerGroup)) - - def test_get_server_group(self): - id = '2cbd51f4-fafe-4cdb-801b-cf913a6f288b' - server_group = self.cs.server_groups.get(id) - self.assert_called('GET', '/os-server-groups/%s' % id) - self.assertTrue(isinstance(server_group, - server_groups.ServerGroup)) - - def test_delete_server_group(self): - id = '2cbd51f4-fafe-4cdb-801b-cf913a6f288b' - self.cs.server_groups.delete(id) - self.assert_called('DELETE', '/os-server-groups/%s' % id) - - def test_delete_server_group_object(self): - id = '2cbd51f4-fafe-4cdb-801b-cf913a6f288b' - server_group = self.cs.server_groups.get(id) - server_group.delete() - self.assert_called('DELETE', '/os-server-groups/%s' % id) diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_servers.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_servers.py deleted file mode 100644 index c9b15f30a9..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_servers.py +++ /dev/null @@ -1,704 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslo.serialization import jsonutils -import six - -from novaclient import exceptions -from novaclient.tests.unit.fixture_data import client -from novaclient.tests.unit.fixture_data import floatingips -from novaclient.tests.unit.fixture_data import servers as data -from novaclient.tests.unit import utils -from novaclient.v2 import servers - - -class ServersTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def setUp(self): - super(ServersTest, self).setUp() - self.useFixture(floatingips.FloatingFixture(self.requests)) - - def test_list_servers(self): - sl = self.cs.servers.list() - self.assert_called('GET', '/servers/detail') - [self.assertIsInstance(s, servers.Server) for s in sl] - - def test_list_servers_undetailed(self): - sl = self.cs.servers.list(detailed=False) - self.assert_called('GET', '/servers') - [self.assertIsInstance(s, servers.Server) for s in sl] - - def test_list_servers_with_marker_limit(self): - sl = self.cs.servers.list(marker=1234, limit=2) - self.assert_called('GET', '/servers/detail?limit=2&marker=1234') - for s in sl: - self.assertIsInstance(s, servers.Server) - - def test_list_servers_sort_single(self): - sl = self.cs.servers.list(sort_keys=['display_name'], - sort_dirs=['asc']) - self.assert_called( - 'GET', - '/servers/detail?sort_dir=asc&sort_key=display_name') - for s in sl: - self.assertIsInstance(s, servers.Server) - - def test_list_servers_sort_multiple(self): - sl = self.cs.servers.list(sort_keys=['display_name', 'id'], - sort_dirs=['asc', 'desc']) - self.assert_called( - 'GET', - ('/servers/detail?sort_dir=asc&sort_dir=desc&' - 'sort_key=display_name&sort_key=id')) - for s in sl: - self.assertIsInstance(s, servers.Server) - - def test_get_server_details(self): - s = self.cs.servers.get(1234) - self.assert_called('GET', '/servers/1234') - self.assertIsInstance(s, servers.Server) - self.assertEqual(1234, s.id) - self.assertEqual('BUILD', s.status) - - def test_get_server_promote_details(self): - s1 = self.cs.servers.list(detailed=False)[0] - s2 = self.cs.servers.list(detailed=True)[0] - self.assertNotEqual(s1._info, s2._info) - s1.get() - self.assertEqual(s1._info, s2._info) - - def test_create_server(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - } - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_boot_from_volume_with_nics(self): - old_boot = self.cs.servers._boot - - nics = [{'net-id': '11111111-1111-1111-1111-111111111111', - 'v4-fixed-ip': '10.0.0.7'}] - bdm = {"volume_size": "1", - "volume_id": "11111111-1111-1111-1111-111111111111", - "delete_on_termination": "0", - "device_name": "vda"} - - def wrapped_boot(url, key, *boot_args, **boot_kwargs): - self.assertEqual(boot_kwargs['block_device_mapping'], bdm) - self.assertEqual(boot_kwargs['nics'], nics) - return old_boot(url, key, *boot_args, **boot_kwargs) - - @mock.patch.object(self.cs.servers, '_boot', wrapped_boot) - def test_create_server_from_volume(): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - block_device_mapping=bdm, - nics=nics - ) - self.assert_called('POST', '/os-volumes_boot') - self.assertIsInstance(s, servers.Server) - - test_create_server_from_volume() - - def test_create_server_boot_with_nics_ipv6(self): - old_boot = self.cs.servers._boot - nics = [{'net-id': '11111111-1111-1111-1111-111111111111', - 'v6-fixed-ip': '2001:db9:0:1::10'}] - - def wrapped_boot(url, key, *boot_args, **boot_kwargs): - self.assertEqual(boot_kwargs['nics'], nics) - return old_boot(url, key, *boot_args, **boot_kwargs) - - with mock.patch.object(self.cs.servers, '_boot', wrapped_boot): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - nics=nics - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_file_object(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata=six.StringIO('hello moto'), - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_unicode(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata=six.u('ã“ã‚“ã«ã¡ã¯'), - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_utf8(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata='ã“ã‚“ã«ã¡ã¯', - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def _create_disk_config(self, disk_config): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - disk_config=disk_config - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - # verify disk config param was used in the request: - body = jsonutils.loads(self.requests.last_request.body) - server = body['server'] - self.assertTrue('OS-DCF:diskConfig' in server) - self.assertEqual(disk_config, server['OS-DCF:diskConfig']) - - def test_create_server_disk_config_auto(self): - self._create_disk_config('AUTO') - - def test_create_server_disk_config_manual(self): - self._create_disk_config('MANUAL') - - def test_update_server(self): - s = self.cs.servers.get(1234) - - # Update via instance - s.update(name='hi') - self.assert_called('PUT', '/servers/1234') - s.update(name='hi') - self.assert_called('PUT', '/servers/1234') - - # Silly, but not an error - s.update() - - # Update via manager - self.cs.servers.update(s, name='hi') - self.assert_called('PUT', '/servers/1234') - - def test_delete_server(self): - s = self.cs.servers.get(1234) - s.delete() - self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(1234) - self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(s) - self.assert_called('DELETE', '/servers/1234') - - def test_delete_server_meta(self): - self.cs.servers.delete_meta(1234, ['test_key']) - self.assert_called('DELETE', '/servers/1234/metadata/test_key') - - def test_set_server_meta(self): - self.cs.servers.set_meta(1234, {'test_key': 'test_value'}) - self.assert_called('POST', '/servers/1234/metadata', - {'metadata': {'test_key': 'test_value'}}) - - def test_set_server_meta_item(self): - self.cs.servers.set_meta_item(1234, 'test_key', 'test_value') - self.assert_called('PUT', '/servers/1234/metadata/test_key', - {'meta': {'test_key': 'test_value'}}) - - def test_find(self): - server = self.cs.servers.find(name='sample-server') - self.assert_called('GET', '/servers/1234') - self.assertEqual('sample-server', server.name) - - self.assertRaises(exceptions.NoUniqueMatch, self.cs.servers.find, - flavor={"id": 1, "name": "256 MB Server"}) - - sl = self.cs.servers.findall(flavor={"id": 1, "name": "256 MB Server"}) - self.assertEqual([1234, 5678, 9012], [s.id for s in sl]) - - def test_reboot_server(self): - s = self.cs.servers.get(1234) - s.reboot() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reboot(s, reboot_type='HARD') - self.assert_called('POST', '/servers/1234/action') - - def test_rebuild_server(self): - s = self.cs.servers.get(1234) - s.rebuild(image=1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1) - self.assert_called('POST', '/servers/1234/action') - s.rebuild(image=1, password='5678') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1, password='5678') - self.assert_called('POST', '/servers/1234/action') - - def _rebuild_resize_disk_config(self, disk_config, operation="rebuild"): - s = self.cs.servers.get(1234) - - if operation == "rebuild": - s.rebuild(image=1, disk_config=disk_config) - elif operation == "resize": - s.resize(flavor=1, disk_config=disk_config) - self.assert_called('POST', '/servers/1234/action') - - # verify disk config param was used in the request: - body = jsonutils.loads(self.requests.last_request.body) - - d = body[operation] - self.assertTrue('OS-DCF:diskConfig' in d) - self.assertEqual(disk_config, d['OS-DCF:diskConfig']) - - def test_rebuild_server_disk_config_auto(self): - self._rebuild_resize_disk_config('AUTO') - - def test_rebuild_server_disk_config_manual(self): - self._rebuild_resize_disk_config('MANUAL') - - def test_rebuild_server_preserve_ephemeral(self): - s = self.cs.servers.get(1234) - s.rebuild(image=1, preserve_ephemeral=True) - self.assert_called('POST', '/servers/1234/action') - body = jsonutils.loads(self.requests.last_request.body) - d = body['rebuild'] - self.assertIn('preserve_ephemeral', d) - self.assertEqual(True, d['preserve_ephemeral']) - - def test_rebuild_server_name_meta_files(self): - files = {'/etc/passwd': 'some data'} - s = self.cs.servers.get(1234) - s.rebuild(image=1, name='new', meta={'foo': 'bar'}, files=files) - body = jsonutils.loads(self.requests.last_request.body) - d = body['rebuild'] - self.assertEqual('new', d['name']) - self.assertEqual({'foo': 'bar'}, d['metadata']) - self.assertEqual('/etc/passwd', - d['personality'][0]['path']) - - def test_resize_server(self): - s = self.cs.servers.get(1234) - s.resize(flavor=1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.resize(s, flavor=1) - self.assert_called('POST', '/servers/1234/action') - - def test_resize_server_disk_config_auto(self): - self._rebuild_resize_disk_config('AUTO', 'resize') - - def test_resize_server_disk_config_manual(self): - self._rebuild_resize_disk_config('MANUAL', 'resize') - - def test_confirm_resized_server(self): - s = self.cs.servers.get(1234) - s.confirm_resize() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.confirm_resize(s) - self.assert_called('POST', '/servers/1234/action') - - def test_revert_resized_server(self): - s = self.cs.servers.get(1234) - s.revert_resize() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.revert_resize(s) - self.assert_called('POST', '/servers/1234/action') - - def test_migrate_server(self): - s = self.cs.servers.get(1234) - s.migrate() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.migrate(s) - self.assert_called('POST', '/servers/1234/action') - - def test_add_fixed_ip(self): - s = self.cs.servers.get(1234) - s.add_fixed_ip(1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_fixed_ip(s, 1) - self.assert_called('POST', '/servers/1234/action') - - def test_remove_fixed_ip(self): - s = self.cs.servers.get(1234) - s.remove_fixed_ip('10.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_fixed_ip(s, '10.0.0.1') - self.assert_called('POST', '/servers/1234/action') - - def test_add_floating_ip(self): - s = self.cs.servers.get(1234) - s.add_floating_ip('11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_floating_ip(s, '11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - f = self.cs.floating_ips.list()[0] - self.cs.servers.add_floating_ip(s, f) - self.assert_called('POST', '/servers/1234/action') - s.add_floating_ip(f) - self.assert_called('POST', '/servers/1234/action') - - def test_add_floating_ip_to_fixed(self): - s = self.cs.servers.get(1234) - s.add_floating_ip('11.0.0.1', fixed_address='12.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_floating_ip(s, '11.0.0.1', - fixed_address='12.0.0.1') - self.assert_called('POST', '/servers/1234/action') - f = self.cs.floating_ips.list()[0] - self.cs.servers.add_floating_ip(s, f) - self.assert_called('POST', '/servers/1234/action') - s.add_floating_ip(f) - self.assert_called('POST', '/servers/1234/action') - - def test_remove_floating_ip(self): - s = self.cs.servers.get(1234) - s.remove_floating_ip('11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_floating_ip(s, '11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - f = self.cs.floating_ips.list()[0] - self.cs.servers.remove_floating_ip(s, f) - self.assert_called('POST', '/servers/1234/action') - s.remove_floating_ip(f) - self.assert_called('POST', '/servers/1234/action') - - def test_stop(self): - s = self.cs.servers.get(1234) - s.stop() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.stop(s) - self.assert_called('POST', '/servers/1234/action') - - def test_force_delete(self): - s = self.cs.servers.get(1234) - s.force_delete() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.force_delete(s) - self.assert_called('POST', '/servers/1234/action') - - def test_restore(self): - s = self.cs.servers.get(1234) - s.restore() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.restore(s) - self.assert_called('POST', '/servers/1234/action') - - def test_start(self): - s = self.cs.servers.get(1234) - s.start() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.start(s) - self.assert_called('POST', '/servers/1234/action') - - def test_rescue(self): - s = self.cs.servers.get(1234) - s.rescue() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rescue(s) - self.assert_called('POST', '/servers/1234/action') - - def test_rescue_password(self): - s = self.cs.servers.get(1234) - s.rescue(password='asdf') - self.assert_called('POST', '/servers/1234/action', - {'rescue': {'adminPass': 'asdf'}}) - self.cs.servers.rescue(s, password='asdf') - self.assert_called('POST', '/servers/1234/action', - {'rescue': {'adminPass': 'asdf'}}) - - def test_rescue_image(self): - s = self.cs.servers.get(1234) - s.rescue(image=1) - self.assert_called('POST', '/servers/1234/action', - {'rescue': {'rescue_image_ref': 1}}) - self.cs.servers.rescue(s, image=1) - self.assert_called('POST', '/servers/1234/action', - {'rescue': {'rescue_image_ref': 1}}) - - def test_unrescue(self): - s = self.cs.servers.get(1234) - s.unrescue() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unrescue(s) - self.assert_called('POST', '/servers/1234/action') - - def test_lock(self): - s = self.cs.servers.get(1234) - s.lock() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.lock(s) - self.assert_called('POST', '/servers/1234/action') - - def test_unlock(self): - s = self.cs.servers.get(1234) - s.unlock() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unlock(s) - self.assert_called('POST', '/servers/1234/action') - - def test_backup(self): - s = self.cs.servers.get(1234) - s.backup('back1', 'daily', 1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.backup(s, 'back1', 'daily', 2) - self.assert_called('POST', '/servers/1234/action') - - def test_get_console_output_without_length(self): - success = 'foo' - s = self.cs.servers.get(1234) - s.get_console_output() - self.assertEqual(success, s.get_console_output()) - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_console_output(s) - self.assertEqual(success, self.cs.servers.get_console_output(s)) - self.assert_called('POST', '/servers/1234/action') - - def test_get_console_output_with_length(self): - success = 'foo' - - s = self.cs.servers.get(1234) - s.get_console_output(length=50) - self.assertEqual(success, s.get_console_output(length=50)) - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_console_output(s, length=50) - self.assertEqual(success, - self.cs.servers.get_console_output(s, length=50)) - self.assert_called('POST', '/servers/1234/action') - - # Testing password methods with the following password and key - # - # Clear password: FooBar123 - # - # RSA Private Key: novaclient/tests/unit/idfake.pem - # - # Encrypted password - # OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r - # qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho - # QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw - # /y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N - # tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk - # Hi/fmZZNQQqj1Ijq0caOIw== - - def test_get_password(self): - s = self.cs.servers.get(1234) - self.assertEqual(b'FooBar123', - s.get_password('novaclient/tests/unit/idfake.pem')) - self.assert_called('GET', '/servers/1234/os-server-password') - - def test_get_password_without_key(self): - s = self.cs.servers.get(1234) - self.assertEqual( - 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r' - 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho' - 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw' - '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N' - 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk' - 'Hi/fmZZNQQqj1Ijq0caOIw==', s.get_password()) - self.assert_called('GET', '/servers/1234/os-server-password') - - def test_clear_password(self): - s = self.cs.servers.get(1234) - s.clear_password() - self.assert_called('DELETE', '/servers/1234/os-server-password') - - def test_get_server_diagnostics(self): - s = self.cs.servers.get(1234) - diagnostics = s.diagnostics() - self.assertTrue(diagnostics is not None) - self.assert_called('GET', '/servers/1234/diagnostics') - - diagnostics_from_manager = self.cs.servers.diagnostics(1234) - self.assertTrue(diagnostics_from_manager is not None) - self.assert_called('GET', '/servers/1234/diagnostics') - - self.assertEqual(diagnostics[1], diagnostics_from_manager[1]) - - def test_get_vnc_console(self): - s = self.cs.servers.get(1234) - s.get_vnc_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_vnc_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_get_spice_console(self): - s = self.cs.servers.get(1234) - s.get_spice_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_spice_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_get_serial_console(self): - s = self.cs.servers.get(1234) - s.get_serial_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_serial_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_get_rdp_console(self): - s = self.cs.servers.get(1234) - s.get_rdp_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_rdp_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_create_image(self): - s = self.cs.servers.get(1234) - s.create_image('123') - self.assert_called('POST', '/servers/1234/action') - s.create_image('123', {}) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123', {}) - - def test_live_migrate_server(self): - s = self.cs.servers.get(1234) - s.live_migrate(host='hostname', block_migration=False, - disk_over_commit=False) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.live_migrate(s, host='hostname', block_migration=False, - disk_over_commit=False) - self.assert_called('POST', '/servers/1234/action') - - def test_reset_state(self): - s = self.cs.servers.get(1234) - s.reset_state('newstate') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_state(s, 'newstate') - self.assert_called('POST', '/servers/1234/action') - - def test_reset_network(self): - s = self.cs.servers.get(1234) - s.reset_network() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_network(s) - self.assert_called('POST', '/servers/1234/action') - - def test_add_security_group(self): - s = self.cs.servers.get(1234) - s.add_security_group('newsg') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_security_group(s, 'newsg') - self.assert_called('POST', '/servers/1234/action') - - def test_remove_security_group(self): - s = self.cs.servers.get(1234) - s.remove_security_group('oldsg') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_security_group(s, 'oldsg') - self.assert_called('POST', '/servers/1234/action') - - def test_list_security_group(self): - s = self.cs.servers.get(1234) - s.list_security_group() - self.assert_called('GET', '/servers/1234/os-security-groups') - - def test_evacuate(self): - s = self.cs.servers.get(1234) - s.evacuate('fake_target_host', 'True') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.evacuate(s, 'fake_target_host', - 'False', 'NewAdminPassword') - self.assert_called('POST', '/servers/1234/action') - - def test_interface_list(self): - s = self.cs.servers.get(1234) - s.interface_list() - self.assert_called('GET', '/servers/1234/os-interface') - - def test_interface_list_result_string_representable(self): - """Test for bugs.launchpad.net/python-novaclient/+bug/1280453.""" - # According to https://github.com/openstack/nova/blob/master/ - # nova/api/openstack/compute/contrib/attach_interfaces.py#L33, - # the attach_interface extension get method will return a json - # object partly like this: - interface_list = [{ - 'net_id': 'd7745cf5-63f9-4883-b0ae-983f061e4f23', - 'port_id': 'f35079da-36d5-4513-8ec1-0298d703f70e', - 'mac_addr': 'fa:16:3e:4c:37:c8', - 'port_state': 'ACTIVE', - 'fixed_ips': [ - { - 'subnet_id': 'f1ad93ad-2967-46ba-b403-e8cbbe65f7fa', - 'ip_address': '10.2.0.96' - }] - }] - # If server is not string representable, it will raise an exception, - # because attribute named 'name' cannot be found. - # Parameter 'loaded' must be True or it will try to get attribute - # 'id' then fails (lazy load detail), this is exactly same as - # novaclient.base.Manager._list() - s = servers.Server(servers.ServerManager, interface_list[0], - loaded=True) - # Trigger the __repr__ magic method - self.assertEqual('', '%r' % s) - - def test_interface_attach(self): - s = self.cs.servers.get(1234) - s.interface_attach(None, None, None) - self.assert_called('POST', '/servers/1234/os-interface') - - def test_interface_detach(self): - s = self.cs.servers.get(1234) - s.interface_detach('port-id') - self.assert_called('DELETE', '/servers/1234/os-interface/port-id') diff --git a/awx/lib/site-packages/novaclient/tests/unit/v2/test_services.py b/awx/lib/site-packages/novaclient/tests/unit/v2/test_services.py deleted file mode 100644 index 2724342d40..0000000000 --- a/awx/lib/site-packages/novaclient/tests/unit/v2/test_services.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.unit import utils -from novaclient.tests.unit.v2 import fakes -from novaclient.v2 import services - - -class ServicesTest(utils.TestCase): - def setUp(self): - super(ServicesTest, self).setUp() - self.cs = self._get_fake_client() - self.service_type = self._get_service_type() - - def _get_fake_client(self): - return fakes.FakeClient() - - def _get_service_type(self): - return services.Service - - def test_list_services(self): - svs = self.cs.services.list() - self.cs.assert_called('GET', '/os-services') - for s in svs: - self.assertIsInstance(s, self._get_service_type()) - self.assertEqual('nova-compute', s.binary) - self.assertEqual('host1', s.host) - self.assertTrue(str(s).startswith(' 0) - for r in all_exts: - self.assertTrue(len(r.summary) > 0) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_migrations.py b/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_migrations.py deleted file mode 100644 index 5337502a1a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_migrations.py +++ /dev/null @@ -1,40 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests import utils -from novaclient.tests.v1_1 import fakes -from novaclient.v1_1.contrib import migrations - -extensions = [ - extension.Extension(migrations.__name__.split(".")[-1], - migrations), -] -cs = fakes.FakeClient(extensions=extensions) - - -class MigrationsTest(utils.TestCase): - - def test_list_migrations(self): - ml = cs.migrations.list() - cs.assert_called('GET', '/os-migrations') - for m in ml: - self.assertIsInstance(m, migrations.Migration) - - def test_list_migrations_with_filters(self): - ml = cs.migrations.list('host1', 'finished', 'child1') - - cs.assert_called('GET', - '/os-migrations?cell_name=child1&host=host1' - '&status=finished') - for m in ml: - self.assertIsInstance(m, migrations.Migration) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_server_external_events.py b/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_server_external_events.py deleted file mode 100644 index c92ba34e0e..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_server_external_events.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2014, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -External event triggering for servers, not to be used by users. -""" - -from novaclient import extension -from novaclient.tests import utils -from novaclient.tests.v1_1.contrib import fakes -from novaclient.v1_1.contrib import server_external_events as ext_events - - -extensions = [ - extension.Extension(ext_events.__name__.split(".")[-1], - ext_events), -] -cs = fakes.FakeClient(extensions=extensions) - - -class ServerExternalEventsTestCase(utils.TestCase): - def test_external_event(self): - events = [{'server_uuid': 'fake-uuid1', - 'name': 'test-event', - 'status': 'completed', - 'tag': 'tag'}, - {'server_uuid': 'fake-uuid2', - 'name': 'test-event', - 'status': 'completed', - 'tag': 'tag'}] - result = cs.server_external_events.create(events) - self.assertEqual(events, result) - cs.assert_called('POST', '/os-server-external-events') diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_tenant_networks.py b/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_tenant_networks.py deleted file mode 100644 index 1289928b8a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/contrib/test_tenant_networks.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests import utils -from novaclient.tests.v1_1.contrib import fakes -from novaclient.v1_1.contrib import tenant_networks - - -extensions = [ - extension.Extension(tenant_networks.__name__.split(".")[-1], - tenant_networks), -] -cs = fakes.FakeClient(extensions=extensions) - - -class TenantNetworkExtensionTests(utils.TestCase): - def test_list_tenant_networks(self): - nets = cs.tenant_networks.list() - cs.assert_called('GET', '/os-tenant-networks') - self.assertTrue(len(nets) > 0) - - def test_get_tenant_network(self): - cs.tenant_networks.get(1) - cs.assert_called('GET', '/os-tenant-networks/1') - - def test_create_tenant_networks(self): - cs.tenant_networks.create(label="net", - cidr="10.0.0.0/24") - cs.assert_called('POST', '/os-tenant-networks') - - def test_delete_tenant_networks(self): - cs.tenant_networks.delete(1) - cs.assert_called('DELETE', '/os-tenant-networks/1') diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/fakes.py b/awx/lib/site-packages/novaclient/tests/v1_1/fakes.py deleted file mode 100644 index 3e82eb053f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/fakes.py +++ /dev/null @@ -1,2140 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import datetime - -from oslo.utils import strutils -import six -from six.moves.urllib import parse - -from novaclient import client as base_client -from novaclient import exceptions -from novaclient.tests import fakes -from novaclient.tests import utils -from novaclient.v1_1 import client - - -class FakeClient(fakes.FakeClient, client.Client): - - def __init__(self, *args, **kwargs): - client.Client.__init__(self, 'username', 'password', - 'project_id', 'auth_url', - extensions=kwargs.get('extensions')) - self.client = FakeHTTPClient(**kwargs) - - -class FakeHTTPClient(base_client.HTTPClient): - - def __init__(self, **kwargs): - self.username = 'username' - self.password = 'password' - self.auth_url = 'auth_url' - self.tenant_id = 'tenant_id' - self.callstack = [] - self.projectid = 'projectid' - self.user = 'user' - self.region_name = 'region_name' - self.endpoint_type = 'endpoint_type' - self.service_type = 'service_type' - self.service_name = 'service_name' - self.volume_service_name = 'volume_service_name' - self.timings = 'timings' - self.bypass_url = 'bypass_url' - self.os_cache = 'os_cache' - self.http_log_debug = 'http_log_debug' - - def _cs_request(self, url, method, **kwargs): - # Check that certain things are called correctly - if method in ['GET', 'DELETE']: - assert 'body' not in kwargs - elif method == 'PUT': - assert 'body' in kwargs - - # Call the method - args = parse.parse_qsl(parse.urlparse(url)[4]) - kwargs.update(args) - munged_url = url.rsplit('?', 1)[0] - munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') - munged_url = munged_url.replace('-', '_') - munged_url = munged_url.replace(' ', '_') - - callback = "%s_%s" % (method.lower(), munged_url) - - if not hasattr(self, callback): - raise AssertionError('Called unknown API method: %s %s, ' - 'expected fakes method name: %s' % - (method, url, callback)) - - # Note the call - self.callstack.append((method, url, kwargs.get('body'))) - - status, headers, body = getattr(self, callback)(**kwargs) - r = utils.TestResponse({ - "status_code": status, - "text": body, - "headers": headers, - }) - return r, body - - # - # agents - # - - def get_os_agents(self, **kw): - hypervisor = kw.get('hypervisor', 'kvm') - return (200, {}, {'agents': - [{'hypervisor': hypervisor, - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'id': 1}, - {'hypervisor': hypervisor, - 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'xxx://xxxx/xxx/xxx1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'id': 2}, - ]}) - - def post_os_agents(self, body): - return (200, {}, {'agent': { - 'url': '/xxx/xxx/xxx', - 'hypervisor': body['agent']['hypervisor'], - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'version': '7.0', - 'architecture': 'x86', - 'os': 'win', - 'id': 1}}) - - def delete_os_agents_1(self, **kw): - return (202, {}, None) - - def put_os_agents_1(self, body, **kw): - return (200, {}, {"agent": { - "url": "/yyy/yyyy/yyyy", - "version": "8.0", - "md5hash": "add6bb58e139be103324d04d82d8f546", - 'id': 1}}) - - # - # List all extensions - # - - def get_extensions(self, **kw): - exts = [ - { - "alias": "NMN", - "description": "Multiple network support", - "links": [], - "name": "Multinic", - "namespace": ("http://docs.openstack.org/" - "compute/ext/multinic/api/v1.1"), - "updated": "2011-06-09T00:00:00+00:00" - }, - { - "alias": "OS-DCF", - "description": "Disk Management Extension", - "links": [], - "name": "DiskConfig", - "namespace": ("http://docs.openstack.org/" - "compute/ext/disk_config/api/v1.1"), - "updated": "2011-09-27T00:00:00+00:00" - }, - { - "alias": "OS-EXT-SRV-ATTR", - "description": "Extended Server Attributes support.", - "links": [], - "name": "ExtendedServerAttributes", - "namespace": ("http://docs.openstack.org/" - "compute/ext/extended_status/api/v1.1"), - "updated": "2011-11-03T00:00:00+00:00" - }, - { - "alias": "OS-EXT-STS", - "description": "Extended Status support", - "links": [], - "name": "ExtendedStatus", - "namespace": ("http://docs.openstack.org/" - "compute/ext/extended_status/api/v1.1"), - "updated": "2011-11-03T00:00:00+00:00" - }, - ] - return (200, {}, { - "extensions": exts, - }) - - # - # Limits - # - - def get_limits(self, **kw): - return (200, {}, {"limits": { - "rate": [ - { - "uri": "*", - "regex": ".*", - "limit": [ - { - "value": 10, - "verb": "POST", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 10, - "verb": "PUT", - "remaining": 2, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - }, - { - "value": 100, - "verb": "DELETE", - "remaining": 100, - "unit": "MINUTE", - "next-available": "2011-12-15T22:42:45Z" - } - ] - }, - { - "uri": "*/servers", - "regex": "^/servers", - "limit": [ - { - "verb": "POST", - "value": 25, - "remaining": 24, - "unit": "DAY", - "next-available": "2011-12-15T22:42:45Z" - } - ] - } - ], - "absolute": { - "maxTotalRAMSize": 51200, - "maxServerMeta": 5, - "maxImageMeta": 5, - "maxPersonality": 5, - "maxPersonalitySize": 10240 - }, - }, - }) - - # - # Servers - # - - def get_servers(self, **kw): - return (200, {}, {"servers": [ - {'id': 1234, 'name': 'sample-server'}, - {'id': 5678, 'name': 'sample-server2'} - ]}) - - def get_servers_detail(self, **kw): - return (200, {}, {"servers": [ - { - "id": 1234, - "name": "sample-server", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0", - "status": "BUILD", - "progress": 60, - "addresses": { - "public": [{ - "version": 4, - "addr": "1.2.3.4", - }, - { - "version": 4, - "addr": "5.6.7.8", - }], - "private": [{ - "version": 4, - "addr": "10.11.12.13", - }], - }, - "metadata": { - "Server Label": "Web Head 1", - "Image Version": "2.1" - }, - "OS-EXT-SRV-ATTR:host": "computenode1", - "security_groups": [{ - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - "OS-EXT-MOD:some_thing": "mod_some_thing_value", - }, - { - "id": 5678, - "name": "sample-server2", - "image": { - "id": 2, - "name": "sample image", - }, - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [{ - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - }, - "OS-EXT-SRV-ATTR:host": "computenode2", - "security_groups": [{ - 'id': 1, 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }, - { - 'id': 2, 'name': 'securitygroup2', - 'description': 'ANOTHER_FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7' - }], - }, - { - "id": 9012, - "name": "sample-server3", - "image": "", - "flavor": { - "id": 1, - "name": "256 MB Server", - }, - "hostId": "9e107d9d372bb6826bd81d3542a419d6", - "status": "ACTIVE", - "addresses": { - "public": [{ - "version": 4, - "addr": "4.5.6.7", - }, - { - "version": 4, - "addr": "5.6.9.8", - }], - "private": [{ - "version": 4, - "addr": "10.13.12.13", - }], - }, - "metadata": { - "Server Label": "DB 1" - } - } - ]}) - - def post_servers(self, body, **kw): - assert set(body.keys()) <= set(['server', 'os:scheduler_hints']) - fakes.assert_has_keys(body['server'], - required=['name', 'imageRef', 'flavorRef'], - optional=['metadata', 'personality']) - if 'personality' in body['server']: - for pfile in body['server']['personality']: - fakes.assert_has_keys(pfile, required=['path', 'contents']) - if body['server']['name'] == 'some-bad-server': - return (202, {}, self.get_servers_1235()[2]) - else: - return (202, {}, self.get_servers_1234()[2]) - - def post_os_volumes_boot(self, body, **kw): - assert set(body.keys()) <= set(['server', 'os:scheduler_hints']) - fakes.assert_has_keys(body['server'], - required=['name', 'flavorRef'], - optional=['imageRef']) - - # Require one, and only one, of the keys for bdm - if 'block_device_mapping' not in body['server']: - if 'block_device_mapping_v2' not in body['server']: - raise AssertionError( - "missing required keys: 'block_device_mapping'" - ) - elif 'block_device_mapping_v2' in body['server']: - raise AssertionError("found extra keys: 'block_device_mapping'") - - return (202, {}, self.get_servers_9012()[2]) - - def get_servers_1234(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][0]} - return (200, {}, r) - - def get_servers_1235(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][0]} - r['server']['id'] = 1235 - r['server']['status'] = 'error' - r['server']['fault'] = {'message': 'something went wrong!'} - return (200, {}, r) - - def get_servers_5678(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][1]} - return (200, {}, r) - - def get_servers_9012(self, **kw): - r = {'server': self.get_servers_detail()[2]['servers'][2]} - return (200, {}, r) - - def put_servers_1234(self, body, **kw): - assert list(body) == ['server'] - fakes.assert_has_keys(body['server'], optional=['name', 'adminPass']) - return (204, {}, body) - - def delete_os_server_groups_12345(self, **kw): - return (202, {}, None) - - def delete_os_server_groups_56789(self, **kw): - return (202, {}, None) - - def delete_servers_1234(self, **kw): - return (202, {}, None) - - def delete_servers_5678(self, **kw): - return (202, {}, None) - - def delete_servers_1234_metadata_test_key(self, **kw): - return (204, {}, None) - - def delete_servers_1234_metadata_key1(self, **kw): - return (204, {}, None) - - def delete_servers_1234_metadata_key2(self, **kw): - return (204, {}, None) - - def post_servers_1234_metadata(self, **kw): - return (204, {}, {'metadata': {'test_key': 'test_value'}}) - - def put_servers_1234_metadata_test_key(self, **kw): - return (200, {}, {'meta': {'test_key': 'test_value'}}) - - def get_servers_1234_diagnostics(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def post_servers_uuid1_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def post_servers_uuid2_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def post_servers_uuid3_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def post_servers_uuid4_metadata(self, **kw): - return (204, {}, {'metadata': {'key1': 'val1'}}) - - def delete_servers_uuid1_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def delete_servers_uuid2_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def delete_servers_uuid3_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def delete_servers_uuid4_metadata_key1(self, **kw): - return (200, {}, {'data': 'Fake diagnostics'}) - - def get_servers_1234_os_security_groups(self, **kw): - return (200, {}, { - "security_groups": [{ - 'id': 1, - 'name': 'securitygroup1', - 'description': 'FAKE_SECURITY_GROUP', - 'tenant_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'rules': []}] - }) - - # - # Server Addresses - # - - def get_servers_1234_ips(self, **kw): - return (200, {}, {'addresses': - self.get_servers_1234()[1]['server']['addresses']}) - - def get_servers_1234_ips_public(self, **kw): - return (200, {}, {'public': - self.get_servers_1234_ips()[1]['addresses']['public']}) - - def get_servers_1234_ips_private(self, **kw): - return (200, {}, {'private': - self.get_servers_1234_ips()[1]['addresses']['private']}) - - def delete_servers_1234_ips_public_1_2_3_4(self, **kw): - return (202, {}, None) - - # - # Server password - # - - # Testing with the following password and key - # - # Clear password: FooBar123 - # - # RSA Private Key: novaclient/tests/idfake.pem - # - # Encrypted password - # OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r - # qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho - # QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw - # /y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N - # tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk - # Hi/fmZZNQQqj1Ijq0caOIw== - def get_servers_1234_os_server_password(self, **kw): - return (200, {}, {'password': - 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r' - 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho' - 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw' - '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N' - 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk' - 'Hi/fmZZNQQqj1Ijq0caOIw=='}) - - def delete_servers_1234_os_server_password(self, **kw): - return (202, {}, None) - - # - # Server actions - # - - def post_servers_1234_action(self, body, **kw): - _headers = None - _body = None - resp = 202 - assert len(body.keys()) == 1 - action = list(body)[0] - if action == 'reboot': - assert list(body[action]) == ['type'] - assert body[action]['type'] in ['HARD', 'SOFT'] - elif action == 'rebuild': - body = body[action] - adminPass = body.get('adminPass', 'randompassword') - assert 'imageRef' in body - _body = self.get_servers_1234()[2] - _body['server']['adminPass'] = adminPass - elif action == 'resize': - keys = body[action].keys() - assert 'flavorRef' in keys - elif action == 'confirmResize': - assert body[action] is None - # This one method returns a different response code - return (204, {}, None) - elif action == 'revertResize': - assert body[action] is None - elif action == 'migrate': - assert body[action] is None - elif action == 'os-stop': - assert body[action] is None - elif action == 'os-start': - assert body[action] is None - elif action == 'forceDelete': - assert body[action] is None - elif action == 'restore': - assert body[action] is None - elif action == 'pause': - assert body[action] is None - elif action == 'unpause': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'rescue': - assert body[action] is None - _body = {'Password': 'RescuePassword'} - elif action == 'unrescue': - assert body[action] is None - elif action == 'resume': - assert body[action] is None - elif action == 'suspend': - assert body[action] is None - elif action == 'lock': - assert body[action] is None - elif action == 'unlock': - assert body[action] is None - elif action == 'shelve': - assert body[action] is None - elif action == 'shelveOffload': - assert body[action] is None - elif action == 'unshelve': - assert body[action] is None - elif action == 'addFixedIp': - assert list(body[action]) == ['networkId'] - elif action == 'removeFixedIp': - assert list(body[action]) == ['address'] - elif action == 'addFloatingIp': - assert (list(body[action]) == ['address'] or - sorted(list(body[action])) == ['address', - 'fixed_address']) - elif action == 'removeFloatingIp': - assert list(body[action]) == ['address'] - elif action == 'createImage': - assert set(body[action].keys()) == set(['name', 'metadata']) - _headers = dict(location="http://blah/images/456") - elif action == 'changePassword': - assert list(body[action]) == ['adminPass'] - elif action == 'os-getConsoleOutput': - assert list(body[action]) == ['length'] - return (202, {}, {'output': 'foo'}) - elif action == 'os-getVNCConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getSPICEConsole': - assert list(body[action]) == ['type'] - elif action == 'os-getRDPConsole': - assert list(body[action]) == ['type'] - elif action == 'os-migrateLive': - assert set(body[action].keys()) == set(['host', - 'block_migration', - 'disk_over_commit']) - elif action == 'os-resetState': - assert list(body[action]) == ['state'] - elif action == 'resetNetwork': - assert body[action] is None - elif action == 'addSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'removeSecurityGroup': - assert list(body[action]) == ['name'] - elif action == 'createBackup': - assert set(body[action]) == set(['name', - 'backup_type', - 'rotation']) - elif action == 'evacuate': - keys = list(body[action]) - if 'adminPass' in keys: - keys.remove('adminPass') - if 'host' in keys: - keys.remove('host') - assert set(keys) == set(['onSharedStorage']) - else: - raise AssertionError("Unexpected server action: %s" % action) - return (resp, _headers, _body) - - def post_servers_5678_action(self, body, **kw): - return self.post_servers_1234_action(body, **kw) - - # - # Cloudpipe - # - - def get_os_cloudpipe(self, **kw): - return ( - 200, - {}, - {'cloudpipes': [{'project_id': 1}]} - ) - - def post_os_cloudpipe(self, **ks): - return ( - 202, - {}, - {'instance_id': '9d5824aa-20e6-4b9f-b967-76a699fc51fd'} - ) - - def put_os_cloudpipe_configure_project(self, **kw): - return (202, {}, None) - - # - # Flavors - # - - def get_flavors(self, **kw): - status, header, flavors = self.get_flavors_detail(**kw) - for flavor in flavors['flavors']: - for k in list(flavor): - if k not in ['id', 'name']: - del flavor[k] - - return (200, {}, flavors) - - def get_flavors_detail(self, **kw): - flavors = {'flavors': [ - {'id': 1, 'name': '256 MB Server', 'ram': 256, 'disk': 10, - 'OS-FLV-EXT-DATA:ephemeral': 10, - 'os-flavor-access:is_public': True, - 'links': {}}, - {'id': 2, 'name': '512 MB Server', 'ram': 512, 'disk': 20, - 'OS-FLV-EXT-DATA:ephemeral': 20, - 'os-flavor-access:is_public': False, - 'links': {}}, - {'id': 4, 'name': '1024 MB Server', 'ram': 1024, 'disk': 10, - 'OS-FLV-EXT-DATA:ephemeral': 10, - 'os-flavor-access:is_public': True, - 'links': {}}, - {'id': 'aa1', 'name': '128 MB Server', 'ram': 128, 'disk': 0, - 'OS-FLV-EXT-DATA:ephemeral': 0, - 'os-flavor-access:is_public': True, - 'links': {}} - ]} - - if 'is_public' not in kw: - filter_is_public = True - else: - if kw['is_public'].lower() == 'none': - filter_is_public = None - else: - filter_is_public = strutils.bool_from_string(kw['is_public'], - True) - - if filter_is_public is not None: - if filter_is_public: - flavors['flavors'] = [ - v for v in flavors['flavors'] - if v['os-flavor-access:is_public'] - ] - else: - flavors['flavors'] = [ - v for v in flavors['flavors'] - if not v['os-flavor-access:is_public'] - ] - - return (200, {}, flavors) - - def get_flavors_1(self, **kw): - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][0]} - ) - - def get_flavors_2(self, **kw): - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][1]} - ) - - def get_flavors_3(self, **kw): - # Diablo has no ephemeral - return ( - 200, - {}, - {'flavor': { - 'id': 3, - 'name': '256 MB Server', - 'ram': 256, - 'disk': 10, - }}, - ) - - def get_flavors_512_MB_Server(self, **kw): - raise exceptions.NotFound('404') - - def get_flavors_128_MB_Server(self, **kw): - raise exceptions.NotFound('404') - - def get_flavors_aa1(self, **kw): - # Alphanumeric flavor id are allowed. - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][3]} - ) - - def get_flavors_4(self, **kw): - return ( - 200, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][2]} - ) - - def delete_flavors_flavordelete(self, **kw): - return (202, {}, None) - - def delete_flavors_2(self, **kw): - return (202, {}, None) - - def post_flavors(self, body, **kw): - return ( - 202, - {}, - {'flavor': - self.get_flavors_detail(is_public='None')[2]['flavors'][0]} - ) - - def get_flavors_1_os_extra_specs(self, **kw): - return (200, - {}, - {'extra_specs': {"k1": "v1"}}) - - def get_flavors_2_os_extra_specs(self, **kw): - return (200, - {}, - {'extra_specs': {"k2": "v2"}}) - - def get_flavors_aa1_os_extra_specs(self, **kw): - return (200, {}, - {'extra_specs': {"k3": "v3"}}) - - def get_flavors_4_os_extra_specs(self, **kw): - return (200, - {}, - {'extra_specs': {"k4": "v4"}}) - - def post_flavors_1_os_extra_specs(self, body, **kw): - assert list(body) == ['extra_specs'] - fakes.assert_has_keys(body['extra_specs'], - required=['k1']) - return (200, - {}, - {'extra_specs': {"k1": "v1"}}) - - def post_flavors_4_os_extra_specs(self, body, **kw): - assert list(body) == ['extra_specs'] - - return (200, - {}, - body) - - def delete_flavors_1_os_extra_specs_k1(self, **kw): - return (204, {}, None) - - # - # Flavor access - # - - def get_flavors_1_os_flavor_access(self, **kw): - return (404, {}, None) - - def get_flavors_2_os_flavor_access(self, **kw): - return (200, {}, {'flavor_access': [ - {'flavor_id': '2', 'tenant_id': 'proj1'}, - {'flavor_id': '2', 'tenant_id': 'proj2'} - ]}) - - def post_flavors_2_action(self, body, **kw): - return (202, {}, self.get_flavors_2_os_flavor_access()[2]) - - # - # Floating ips - # - - def get_os_floating_ip_pools(self): - return ( - 200, - {}, - {'floating_ip_pools': [{'name': 'foo'}, {'name': 'bar'}]} - ) - - def get_os_floating_ips(self, **kw): - return ( - 200, - {}, - {'floating_ips': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ]}, - ) - - def get_os_floating_ips_1(self, **kw): - return (200, {}, {'floating_ip': - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'} - }) - - def post_os_floating_ips(self, body): - if body.get('pool'): - return (200, {}, {'floating_ip': - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1', - 'pool': 'nova'}}) - else: - return (200, {}, {'floating_ip': - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1', - 'pool': None}}) - - def delete_os_floating_ips_1(self, **kw): - return (204, {}, None) - - def get_os_floating_ip_dns(self, **kw): - return (205, {}, {'domain_entries': - [{'domain': 'example.org'}, - {'domain': 'example.com'}]}) - - def get_os_floating_ip_dns_testdomain_entries(self, **kw): - if kw.get('ip'): - return (205, {}, {'dns_entries': - [{'dns_entry': - {'ip': kw.get('ip'), - 'name': "host1", - 'type': "A", - 'domain': 'testdomain'}}, - {'dns_entry': - {'ip': kw.get('ip'), - 'name': "host2", - 'type': "A", - 'domain': 'testdomain'}}]}) - else: - return (404, {}, None) - - def get_os_floating_ip_dns_testdomain_entries_testname(self, **kw): - return (205, {}, {'dns_entry': - {'ip': "10.10.10.10", - 'name': 'testname', - 'type': "A", - 'domain': 'testdomain'}}) - - def put_os_floating_ip_dns_testdomain(self, body, **kw): - if body['domain_entry']['scope'] == 'private': - fakes.assert_has_keys(body['domain_entry'], - required=['availability_zone', 'scope']) - elif body['domain_entry']['scope'] == 'public': - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - - else: - fakes.assert_has_keys(body['domain_entry'], - required=['project', 'scope']) - return (205, {}, body) - - def put_os_floating_ip_dns_testdomain_entries_testname(self, body, **kw): - fakes.assert_has_keys(body['dns_entry'], - required=['ip', 'dns_type']) - return (205, {}, body) - - def delete_os_floating_ip_dns_testdomain(self, **kw): - return (200, {}, None) - - def delete_os_floating_ip_dns_testdomain_entries_testname(self, **kw): - return (200, {}, None) - - def get_os_floating_ips_bulk(self, **kw): - return (200, {}, {'floating_ip_info': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ]}) - - def get_os_floating_ips_bulk_testHost(self, **kw): - return (200, {}, {'floating_ip_info': [ - {'id': 1, 'fixed_ip': '10.0.0.1', 'ip': '11.0.0.1'}, - {'id': 2, 'fixed_ip': '10.0.0.2', 'ip': '11.0.0.2'}, - ]}) - - def post_os_floating_ips_bulk(self, **kw): - params = kw.get('body').get('floating_ips_bulk_create') - pool = params.get('pool', 'defaultPool') - interface = params.get('interface', 'defaultInterface') - return (200, {}, {'floating_ips_bulk_create': - {'ip_range': '192.168.1.0/30', - 'pool': pool, - 'interface': interface}}) - - def put_os_floating_ips_bulk_delete(self, **kw): - ip_range = kw.get('body').get('ip_range') - return (200, {}, {'floating_ips_bulk_delete': ip_range}) - - # - # Images - # - def get_images(self, **kw): - return (200, {}, {'images': [ - {'id': 1, 'name': 'CentOS 5.2'}, - {'id': 2, 'name': 'My Server Backup'} - ]}) - - def get_images_detail(self, **kw): - return (200, {}, {'images': [ - { - 'id': 1, - 'name': 'CentOS 5.2', - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "ACTIVE", - "metadata": { - "test_key": "test_value", - }, - "links": {}, - }, - { - "id": 2, - "name": "My Server Backup", - "serverId": 1234, - "updated": "2010-10-10T12:00:00Z", - "created": "2010-08-10T12:00:00Z", - "status": "SAVING", - "progress": 80, - "links": {}, - } - ]}) - - def get_images_1(self, **kw): - return (200, {}, {'image': self.get_images_detail()[2]['images'][0]}) - - def get_images_2(self, **kw): - return (200, {}, {'image': self.get_images_detail()[2]['images'][1]}) - - def get_images_456(self, **kw): - return (200, {}, {'image': self.get_images_detail()[2]['images'][1]}) - - def post_images(self, body, **kw): - assert list(body) == ['image'] - fakes.assert_has_keys(body['image'], required=['serverId', 'name']) - return (202, {}, self.get_images_1()[2]) - - def post_images_1_metadata(self, body, **kw): - assert list(body) == ['metadata'] - fakes.assert_has_keys(body['metadata'], - required=['test_key']) - return (200, - {}, - {'metadata': self.get_images_1()[2]['image']['metadata']}) - - def delete_images_1(self, **kw): - return (204, {}, None) - - def delete_images_2(self, **kw): - return (204, {}, None) - - def delete_images_1_metadata_test_key(self, **kw): - return (204, {}, None) - - # - # Keypairs - # - def get_os_keypairs_test(self, *kw): - return (200, {}, {'keypair': - self.get_os_keypairs()[2]['keypairs'][0]['keypair']}) - - def get_os_keypairs(self, *kw): - return (200, {}, {"keypairs": [ - {"keypair": { - "public_key": "FAKE_SSH_RSA", - "private_key": "FAKE_PRIVATE_KEY", - "user_id": - "81e373b596d6466e99c4896826abaa46", - "name": "test", - "deleted": False, - "created_at": "2014-04-19T02:16:44.000000", - "updated_at": "2014-04-19T10:12:3.000000", - "figerprint": "FAKE_KEYPAIR", - "deleted_at": None, - "id": 4} - }]}) - - def delete_os_keypairs_test(self, **kw): - return (202, {}, None) - - def post_os_keypairs(self, body, **kw): - assert list(body) == ['keypair'] - fakes.assert_has_keys(body['keypair'], - required=['name']) - r = {'keypair': self.get_os_keypairs()[2]['keypairs'][0]['keypair']} - return (202, {}, r) - - # - # Virtual Interfaces - # - def get_servers_1234_os_virtual_interfaces(self, **kw): - return (200, {}, {"virtual_interfaces": [ - {'id': 'fakeid', 'mac_address': 'fakemac'} - ]}) - - # - # Quotas - # - - def get_os_quota_sets_test(self, **kw): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_tenant_id(self, **kw): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, **kw): - return (200, {}, {'quota_set': { - 'tenant_id': '97f4c221bff44578b0300df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw): - return (200, {}, {'quota_set': { - 'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw): - return (200, {}, {'quota_set': { - 'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_97f4c221bff44578b0300df4ef119353_defaults(self): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def get_os_quota_sets_tenant_id_defaults(self): - return (200, {}, {'quota_set': { - 'tenant_id': 'test', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, body, **kw): - assert list(body) == ['quota_set'] - fakes.assert_has_keys(body['quota_set'], - required=['tenant_id']) - return (200, {}, {'quota_set': { - 'tenant_id': '97f4c221bff44578b0300df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def delete_os_quota_sets_test(self, **kw): - return (202, {}, {}) - - def delete_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, **kw): - return (202, {}, {}) - - # - # Quota Classes - # - - def get_os_quota_class_sets_test(self, **kw): - return (200, {}, {'quota_class_set': { - 'id': 'test', - 'metadata_items': 1, - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'key_pairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_class_sets_test(self, body, **kw): - assert list(body) == ['quota_class_set'] - return (200, {}, {'quota_class_set': { - 'metadata_items': 1, - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'key_pairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - def put_os_quota_class_sets_97f4c221bff44578b0300df4ef119353(self, - body, **kw): - assert list(body) == ['quota_class_set'] - return (200, {}, {'quota_class_set': { - 'metadata_items': 1, - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'key_pairs': 1, - 'security_groups': 1, - 'security_group_rules': 1}}) - - # - # Security Groups - # - def get_os_security_groups(self, **kw): - return (200, {}, {"security_groups": [ - {"name": "test", - "description": "FAKE_SECURITY_GROUP", - "tenant_id": - "4ffc664c198e435e9853f2538fbcd7a7", - "id": 1, - "rules": [ - {"id": 11, - "group": {}, - "ip_protocol": "TCP", - "from_port": 22, - "to_port": 22, - "parent_group_id": 1, - "ip_range": - {"cidr": "10.0.0.0/8"}}, - {"id": 12, - "group": { - "tenant_id": - "272bee4c1e624cd4a72a6b0ea55b4582", - "name": "test2"}, - - "ip_protocol": "TCP", - "from_port": 222, - "to_port": 222, - "parent_group_id": 1, - "ip_range": {}}]}, - {"name": "test2", - "description": "FAKE_SECURITY_GROUP2", - "tenant_id": "272bee4c1e624cd4a72a6b0ea55b4582", - "id": 2, - "rules": []} - ]} - ) - - def get_os_security_groups_1(self, **kw): - return (200, {}, {"security_group": - {'id': 1, 'name': 'test', 'description': 'FAKE_SECURITY_GROUP'} - }) - - def delete_os_security_groups_1(self, **kw): - return (202, {}, None) - - def post_os_security_groups(self, body, **kw): - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - r = {'security_group': - self.get_os_security_groups()[2]['security_groups'][0]} - return (202, {}, r) - - def put_os_security_groups_1(self, body, **kw): - assert list(body) == ['security_group'] - fakes.assert_has_keys(body['security_group'], - required=['name', 'description']) - return (205, {}, body) - - # - # Security Group Rules - # - def get_os_security_group_rules(self, **kw): - return (200, {}, {"security_group_rules": [ - {'id': 1, 'parent_group_id': 1, 'group_id': 2, - 'ip_protocol': 'TCP', 'from_port': 22, 'to_port': 22, - 'cidr': '10.0.0.0/8'} - ]}) - - def delete_os_security_group_rules_1(self, **kw): - return (202, {}, None) - - def delete_os_security_group_rules_11(self, **kw): - return (202, {}, None) - - def delete_os_security_group_rules_12(self, **kw): - return (202, {}, None) - - def post_os_security_group_rules(self, body, **kw): - assert list(body) == ['security_group_rule'] - fakes.assert_has_keys(body['security_group_rule'], - required=['parent_group_id'], - optional=['group_id', 'ip_protocol', 'from_port', - 'to_port', 'cidr']) - r = {'security_group_rule': - self.get_os_security_group_rules()[2]['security_group_rules'][0]} - return (202, {}, r) - - # - # Security Group Default Rules - # - def get_os_security_group_default_rules(self, **kw): - return (200, {}, {"security_group_default_rules": [ - {'id': 1, 'ip_protocol': 'TCP', 'from_port': 22, - 'to_port': 22, 'cidr': '10.0.0.0/8'} - ]}) - - def delete_os_security_group_default_rules_1(self, **kw): - return (202, {}, None) - - def delete_os_security_group_default_rules_11(self, **kw): - return (202, {}, None) - - def delete_os_security_group_default_rules_12(self, **kw): - return (202, {}, None) - - def post_os_security_group_default_rules(self, body, **kw): - assert list(body) == ['security_group_default_rule'] - fakes.assert_has_keys(body['security_group_default_rule'], - optional=['ip_protocol', 'from_port', - 'to_port', 'cidr']) - rules = self.get_os_security_group_default_rules() - r = {'security_group_default_rule': - rules[2]['security_group_default_rules'][0]} - return (202, {}, r) - - # - # Tenant Usage - # - def get_os_simple_tenant_usage(self, **kw): - return (200, {}, - {six.u('tenant_usages'): [{ - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, - six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, - six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): - six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}]}) - - def get_os_simple_tenant_usage_tenantfoo(self, **kw): - return (200, {}, - {six.u('tenant_usage'): { - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): - six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): - six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}}) - - def get_os_simple_tenant_usage_test(self, **kw): - return (200, {}, {six.u('tenant_usage'): { - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}}) - - def get_os_simple_tenant_usage_tenant_id(self, **kw): - return (200, {}, {six.u('tenant_usage'): { - six.u('total_memory_mb_usage'): 25451.762807466665, - six.u('total_vcpus_usage'): 49.71047423333333, - six.u('total_hours'): 49.71047423333333, - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('stop'): six.u('2012-01-22 19:48:41.750722'), - six.u('server_usages'): [{ - six.u('hours'): 49.71047423333333, - six.u('uptime'): 27035, six.u('local_gb'): 0, - six.u('ended_at'): None, - six.u('name'): six.u('f15image1'), - six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'), - six.u('vcpus'): 1, six.u('memory_mb'): 512, - six.u('state'): six.u('active'), - six.u('flavor'): six.u('m1.tiny'), - six.u('started_at'): six.u('2012-01-20 18:06:06.479998')}], - six.u('start'): six.u('2011-12-25 19:48:41.750687'), - six.u('total_local_gb_usage'): 0.0}}) - # - # Certificates - # - - def get_os_certificates_root(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': None, 'data': 'foo'}} - ) - - def post_os_certificates(self, **kw): - return ( - 200, - {}, - {'certificate': {'private_key': 'foo', 'data': 'bar'}} - ) - - # - # Aggregates - # - - def get_os_aggregates(self, *kw): - return (200, {}, {"aggregates": [ - {'id': '1', - 'name': 'test', - 'availability_zone': 'nova1'}, - {'id': '2', - 'name': 'test2', - 'availability_zone': 'nova1'}, - {'id': '3', - 'name': 'test3', - 'metadata': {'test': "dup", "none_key": "Nine"}}, - ]}) - - def _return_aggregate(self): - r = {'aggregate': self.get_os_aggregates()[2]['aggregates'][0]} - return (200, {}, r) - - def _return_aggregate_3(self): - r = {'aggregate': self.get_os_aggregates()[2]['aggregates'][2]} - return (200, {}, r) - - def get_os_aggregates_1(self, **kw): - return self._return_aggregate() - - def get_os_aggregates_3(self, **kw): - return self._return_aggregate_3() - - def post_os_aggregates(self, body, **kw): - return self._return_aggregate() - - def put_os_aggregates_1(self, body, **kw): - return self._return_aggregate() - - def put_os_aggregates_2(self, body, **kw): - return self._return_aggregate() - - def put_os_aggregates_3(self, body, **kw): - return self._return_aggregate_3() - - def post_os_aggregates_1_action(self, body, **kw): - return self._return_aggregate() - - def post_os_aggregates_2_action(self, body, **kw): - return self._return_aggregate() - - def post_os_aggregates_3_action(self, body, **kw): - return self._return_aggregate_3() - - def delete_os_aggregates_1(self, **kw): - return (202, {}, None) - - # - # Services - # - def get_os_services(self, **kw): - host = kw.get('host', 'host1') - binary = kw.get('binary', 'nova-compute') - return (200, {}, {'services': - [{'binary': binary, - 'host': host, - 'zone': 'nova', - 'status': 'enabled', - 'state': 'up', - 'updated_at': datetime.datetime( - 2012, 10, 29, 13, 42, 2 - )}, - {'binary': binary, - 'host': host, - 'zone': 'nova', - 'status': 'disabled', - 'state': 'down', - 'updated_at': datetime.datetime( - 2012, 9, 18, 8, 3, 38 - )}, - ]}) - - def put_os_services_enable(self, body, **kw): - return (200, {}, {'service': {'host': body['host'], - 'binary': body['binary'], - 'status': 'enabled'}}) - - def put_os_services_disable(self, body, **kw): - return (200, {}, {'service': {'host': body['host'], - 'binary': body['binary'], - 'status': 'disabled'}}) - - def put_os_services_disable_log_reason(self, body, **kw): - return (200, {}, {'service': {'host': body['host'], - 'binary': body['binary'], - 'status': 'disabled', - 'disabled_reason': body['disabled_reason']}}) - - def delete_os_services_1(self, **kw): - return (204, {}, None) - - # - # Fixed IPs - # - def get_os_fixed_ips_192_168_1_1(self, *kw): - return (200, {}, {"fixed_ip": - {'cidr': '192.168.1.0/24', - 'address': '192.168.1.1', - 'hostname': 'foo', - 'host': 'bar'}}) - - def post_os_fixed_ips_192_168_1_1_action(self, body, **kw): - return (202, {}, None) - - # - # Hosts - # - def get_os_hosts_host(self, *kw): - return (200, {}, {'host': - [{'resource': {'project': '(total)', 'host': 'dummy', - 'cpu': 16, 'memory_mb': 32234, 'disk_gb': 128}}, - {'resource': {'project': '(used_now)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2075, 'disk_gb': 45}}, - {'resource': {'project': '(used_max)', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}, - {'resource': {'project': 'admin', 'host': 'dummy', - 'cpu': 1, 'memory_mb': 2048, 'disk_gb': 30}}]}) - - def get_os_hosts(self, **kw): - zone = kw.get('zone', 'nova1') - return (200, {}, {'hosts': - [{'host': 'host1', - 'service': 'nova-compute', - 'zone': zone}, - {'host': 'host1', - 'service': 'nova-cert', - 'zone': zone}]}) - - def get_os_hosts_sample_host(self, *kw): - return (200, {}, {'host': [{'resource': {'host': 'sample_host'}}], }) - - def put_os_hosts_sample_host_1(self, body, **kw): - return (200, {}, {'host': 'sample-host_1', - 'status': 'enabled'}) - - def put_os_hosts_sample_host_2(self, body, **kw): - return (200, {}, {'host': 'sample-host_2', - 'maintenance_mode': 'on_maintenance'}) - - def put_os_hosts_sample_host_3(self, body, **kw): - return (200, {}, {'host': 'sample-host_3', - 'status': 'enabled', - 'maintenance_mode': 'on_maintenance'}) - - def get_os_hosts_sample_host_reboot(self, **kw): - return (200, {}, {'host': 'sample_host', - 'power_action': 'reboot'}) - - def get_os_hosts_sample_host_startup(self, **kw): - return (200, {}, {'host': 'sample_host', - 'power_action': 'startup'}) - - def get_os_hosts_sample_host_shutdown(self, **kw): - return (200, {}, {'host': 'sample_host', - 'power_action': 'shutdown'}) - - def put_os_hosts_sample_host(self, body, **kw): - result = {'host': 'dummy'} - result.update(body) - return (200, {}, result) - - def get_os_hypervisors(self, **kw): - return (200, {}, {"hypervisors": [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'}, - ]}) - - def get_os_hypervisors_detail(self, **kw): - return (200, {}, {"hypervisors": [ - {'id': 1234, - 'service': {'id': 1, 'host': 'compute1'}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': "xen", - 'hypervisor_version': 3, - 'hypervisor_hostname': "hyper1", - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100}, - {'id': 2, - 'service': {'id': 2, 'host': "compute2"}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': "xen", - 'hypervisor_version': 3, - 'hypervisor_hostname': "hyper2", - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100} - ]}) - - def get_os_hypervisors_statistics(self, **kw): - return (200, {}, {"hypervisor_statistics": { - 'count': 2, - 'vcpus': 8, - 'memory_mb': 20 * 1024, - 'local_gb': 500, - 'vcpus_used': 4, - 'memory_mb_used': 10 * 1024, - 'local_gb_used': 250, - 'free_ram_mb': 10 * 1024, - 'free_disk_gb': 250, - 'current_workload': 4, - 'running_vms': 4, - 'disk_available_least': 200, - }}) - - def get_os_hypervisors_hyper_search(self, **kw): - return (200, {}, {'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'} - ]}) - - def get_os_hypervisors_hyper_servers(self, **kw): - return (200, {}, {'hypervisors': [ - {'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'servers': [ - {'name': 'inst1', 'uuid': 'uuid1'}, - {'name': 'inst2', 'uuid': 'uuid2'} - ]}, - {'id': 5678, - 'hypervisor_hostname': 'hyper2', - 'servers': [ - {'name': 'inst3', 'uuid': 'uuid3'}, - {'name': 'inst4', 'uuid': 'uuid4'} - ]} - ]}) - - def get_os_hypervisors_hyper_no_servers_servers(self, **kw): - return (200, {}, {'hypervisors': - [{'id': 1234, 'hypervisor_hostname': 'hyper1'}]}) - - def get_os_hypervisors_1234(self, **kw): - return (200, {}, {'hypervisor': - {'id': 1234, - 'service': {'id': 1, 'host': 'compute1'}, - 'vcpus': 4, - 'memory_mb': 10 * 1024, - 'local_gb': 250, - 'vcpus_used': 2, - 'memory_mb_used': 5 * 1024, - 'local_gb_used': 125, - 'hypervisor_type': "xen", - 'hypervisor_version': 3, - 'hypervisor_hostname': "hyper1", - 'free_ram_mb': 5 * 1024, - 'free_disk_gb': 125, - 'current_workload': 2, - 'running_vms': 2, - 'cpu_info': 'cpu_info', - 'disk_available_least': 100}}) - - def get_os_hypervisors_1234_uptime(self, **kw): - return (200, {}, {'hypervisor': - {'id': 1234, - 'hypervisor_hostname': "hyper1", - 'uptime': "fake uptime"}}) - - def get_os_networks(self, **kw): - return (200, {}, {'networks': [{"label": "1", "cidr": "10.0.0.0/24", - 'project_id': '4ffc664c198e435e9853f2538fbcd7a7', - 'id': '1', 'vlan': '1234'}]}) - - def delete_os_networks_1(self, **kw): - return (202, {}, None) - - def post_os_networks(self, **kw): - return (202, {}, {'network': kw}) - - def get_os_networks_1(self, **kw): - return (200, {}, {'network': {"label": "1", "cidr": "10.0.0.0/24", - "id": "1"}}) - - def delete_os_networks_networkdelete(self, **kw): - return (202, {}, None) - - def post_os_networks_add(self, **kw): - return (202, {}, None) - - def post_os_networks_networkdisassociate_action(self, **kw): - return (202, {}, None) - - def get_os_fping(self, **kw): - return ( - 200, {}, { - 'servers': [ - { - "id": "1", - "project_id": "fake-project", - "alive": True, - }, - { - "id": "2", - "project_id": "fake-project", - "alive": True, - }, - ] - } - ) - - def get_os_fping_1(self, **kw): - return ( - 200, {}, { - 'server': { - "id": "1", - "project_id": "fake-project", - "alive": True, - } - } - ) - - def post_os_networks_1_action(self, **kw): - return (202, {}, None) - - def post_os_networks_networktest_action(self, **kw): - return (202, {}, None) - - def post_os_networks_2_action(self, **kw): - return (202, {}, None) - - def get_os_availability_zone(self, **kw): - return (200, {}, {"availabilityZoneInfo": [ - {"zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": None}, - {"zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None}]}) - - def get_os_availability_zone_detail(self, **kw): - return (200, {}, {"availabilityZoneInfo": [ - {"zoneName": "zone-1", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "nova-compute": {"active": True, - "available": True, - "updated_at": - datetime.datetime( - 2012, 12, 26, 14, 45, 25, 0 - )}}}}, - {"zoneName": "internal", - "zoneState": {"available": True}, - "hosts": { - "fake_host-1": { - "nova-sched": { - "active": True, - "available": True, - "updated_at": - datetime.datetime( - 2012, 12, 26, 14, 45, 25, 0 - )}}, - "fake_host-2": { - "nova-network": { - "active": True, - "available": False, - "updated_at": - datetime.datetime( - 2012, 12, 26, 14, 45, 24, 0 - )}}}}, - {"zoneName": "zone-2", - "zoneState": {"available": False}, - "hosts": None}]}) - - def get_servers_1234_os_interface(self, **kw): - return (200, {}, {"interfaceAttachments": [ - {"port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - }, - {"port_state": "ACTIVE", - "net_id": "net-id-1", - "port_id": "port-id-1", - "mac_address": "aa:bb:cc:dd:ee:ff", - "fixed_ips": [{"ip_address": "1.2.3.4"}], - }]}) - - def post_servers_1234_os_interface(self, **kw): - return (200, {}, {'interfaceAttachment': {}}) - - def delete_servers_1234_os_interface_port_id(self, **kw): - return (200, {}, None) - - # NOTE (vkhomenko): - # Volume responses was taken from: - # https://wiki.openstack.org/wiki/CreateVolumeFromImage - # http://jorgew.github.com/block-storage-api/content/ - # GET_listDetailVolumes_v1__tenantId__volumes_detail_.html - # I suppose they are outdated and should be updated after Cinder released - - def get_volumes_detail(self, **kw): - return (200, {}, {"volumes": [ - { - "display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "3333", - "links": ''}], - "metadata": {}}, - { - "display_name": "Work2", - "display_description": "volume for work2", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-ee32ba30feaa", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "2222", - "links": ''}], - "metadata": {}}]}) - - def get_volumes(self, **kw): - return (200, {}, {"volumes": [ - { - "display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "3333", - "links": ''}], - "metadata": {}}, - { - "display_name": "Work2", - "display_description": "volume for work2", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-ee32ba30feaa", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "2222", - "links": ''}], - "metadata": {}}]}) - - def get_volumes_15e59938_07d5_11e1_90e3_e3dffe0c5983(self, **kw): - return (200, {}, { - "volume": self.get_volumes_detail()[2]['volumes'][0]}) - - def get_volumes_15e59938_07d5_11e1_90e3_ee32ba30feaa(self, **kw): - return (200, {}, { - "volume": self.get_volumes_detail()[2]['volumes'][1]}) - - def post_volumes(self, **kw): - return (200, {}, {"volume": - {"status": "creating", - "display_name": "vol-007", - "attachments": [(0)], - "availability_zone": "cinder", - "created_at": "2012-08-13T10:57:17.000000", - "display_description": "create volume from image", - "image_id": "f4cf905f-7c58-4d7b-8314-8dd8a2d1d483", - "volume_type": "None", - "metadata": {}, - "id": "5cb239f6-1baf-4fe1-bd78-c852cf00fa39", - "size": 1}}) - - def delete_volumes_15e59938_07d5_11e1_90e3_e3dffe0c5983(self, **kw): - return (200, {}, {}) - - def delete_volumes_15e59938_07d5_11e1_90e3_ee32ba30feaa(self, **kw): - return (200, {}, {}) - - def post_servers_1234_os_volume_attachments(self, **kw): - return (200, {}, {"volumeAttachment": - {"device": "/dev/vdb", - "volumeId": 2}}) - - def put_servers_1234_os_volume_attachments_Work(self, **kw): - return (200, {}, {"volumeAttachment": {"volumeId": 2}}) - - def get_servers_1234_os_volume_attachments(self, **kw): - return (200, {}, {"volumeAttachments": [ - {"display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "3333", - "links": ''}], - "metadata": {}}]}) - - def get_servers_1234_os_volume_attachments_Work(self, **kw): - return (200, {}, {"volumeAttachment": - {"display_name": "Work", - "display_description": "volume for work", - "status": "ATTACHED", - "id": "15e59938-07d5-11e1-90e3-e3dffe0c5983", - "created_at": "2011-09-09T00:00:00Z", - "attached": "2011-11-11T00:00:00Z", - "size": 1024, - "attachments": [ - {"id": "3333", - "links": ''}], - "metadata": {}}}) - - def delete_servers_1234_os_volume_attachments_Work(self, **kw): - return (200, {}, {}) - - def get_servers_1234_os_instance_actions(self, **kw): - return (200, {}, {"instanceActions": - [{"instance_uuid": "1234", - "user_id": "b968c25e04ab405f9fe4e6ca54cce9a5", - "start_time": "2013-03-25T13:45:09.000000", - "request_id": "req-abcde12345", - "action": "create", - "message": None, - "project_id": "04019601fe3648c0abd4f4abfb9e6106"}]}) - - def get_servers_1234_os_instance_actions_req_abcde12345(self, **kw): - return (200, {}, {"instanceAction": - {"instance_uuid": "1234", - "user_id": "b968c25e04ab405f9fe4e6ca54cce9a5", - "start_time": "2013-03-25T13:45:09.000000", - "request_id": "req-abcde12345", - "action": "create", - "message": None, - "project_id": "04019601fe3648c0abd4f4abfb9e6106"}}) - - def post_servers_uuid1_action(self, **kw): - return 202, {}, {} - - def post_servers_uuid2_action(self, **kw): - return 202, {}, {} - - def post_servers_uuid3_action(self, **kw): - return 202, {}, {} - - def post_servers_uuid4_action(self, **kw): - return 202, {}, {} - - def get_os_cells_child_cell(self, **kw): - cell = {'cell': { - 'username': 'cell1_user', - 'name': 'cell1', - 'rpc_host': '10.0.1.10', - 'info': { - 'username': 'cell1_user', - 'rpc_host': '10.0.1.10', - 'type': 'child', - 'name': 'cell1', - 'rpc_port': 5673 - }, - 'type': 'child', - 'rpc_port': 5673, - 'loaded': True - }} - return (200, {}, cell) - - def get_os_cells_capacities(self, **kw): - cell_capacities_response = {"cell": {"capacities": {"ram_free": { - "units_by_mb": {"8192": 0, "512": 13, "4096": 1, "2048": 3, - "16384": 0}, "total_mb": 7680}, "disk_free": { - "units_by_mb": {"81920": 11, "20480": 46, "40960": 23, "163840": 5, - "0": 0}, "total_mb": 1052672}}}} - return (200, {}, cell_capacities_response) - - def get_os_cells_child_cell_capacities(self, **kw): - return self.get_os_cells_capacities() - - def get_os_migrations(self, **kw): - migrations = {'migrations': - [{ - "created_at": "2012-10-29T13:42:02.000000", - "dest_compute": "compute2", - "dest_host": "1.2.3.4", - "dest_node": "node2", - "id": 1234, - "instance_uuid": "instance_id_123", - "new_instance_type_id": 2, - "old_instance_type_id": 1, - "source_compute": "compute1", - "source_node": "node1", - "status": "Done", - "updated_at": "2012-10-29T13:42:02.000000" - }]} - return (200, {}, migrations) - - def post_os_server_external_events(self, **kw): - return (200, {}, {'events': [ - {'name': 'network-changed', - 'server_uuid': '1234'}]}) - - # - # Server Groups - # - - def get_os_server_groups(self, *kw): - return (200, {}, - {"server_groups": [ - {"members": [], "metadata": {}, - "id": "2cbd51f4-fafe-4cdb-801b-cf913a6f288b", - "policies": [], "name": "ig1"}, - {"members": [], "metadata": {}, - "id": "4473bb03-4370-4bfb-80d3-dc8cffc47d94", - "policies": ["anti-affinity"], "name": "ig2"}, - {"members": [], "metadata": {"key": "value"}, - "id": "31ab9bdb-55e1-4ac3-b094-97eeb1b65cc4", - "policies": [], "name": "ig3"}, - {"members": ["2dccb4a1-02b9-482a-aa23-5799490d6f5d"], - "metadata": {}, - "id": "4890bb03-7070-45fb-8453-d34556c87d94", - "policies": ["anti-affinity"], "name": "ig2"}]}) - - def _return_server_group(self): - r = {'server_group': - self.get_os_server_groups()[2]['server_groups'][0]} - return (200, {}, r) - - def post_os_server_groups(self, body, **kw): - return self._return_server_group() - - def get_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b(self, - **kw): - return self._return_server_group() - - def put_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b(self, - **kw): - return self._return_server_group() - - def post_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b_action( - self, body, **kw): - return self._return_server_group() - - def delete_os_server_groups_2cbd51f4_fafe_4cdb_801b_cf913a6f288b( - self, **kw): - return (202, {}, None) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_agents.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_agents.py deleted file mode 100644 index 1a580f5f19..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_agents.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import agents as data -from novaclient.tests.fixture_data import client -from novaclient.tests import utils -from novaclient.v1_1 import agents - - -class AgentsTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def stub_hypervisors(self, hypervisor='kvm'): - get_os_agents = {'agents': - [ - { - 'hypervisor': hypervisor, - 'os': 'win', - 'architecture': 'x86', - 'version': '7.0', - 'url': 'xxx://xxxx/xxx/xxx', - 'md5hash': 'add6bb58e139be103324d04d82d8f545', - 'id': 1 - }, - { - 'hypervisor': hypervisor, - 'os': 'linux', - 'architecture': 'x86', - 'version': '16.0', - 'url': 'xxx://xxxx/xxx/xxx1', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'id': 2 - }, - ] - } - - headers = {'Content-Type': 'application/json'} - self.requests.register_uri('GET', self.data_fixture.url(), - json=get_os_agents, - headers=headers) - - def test_list_agents(self): - self.stub_hypervisors() - ags = self.cs.agents.list() - self.assert_called('GET', '/os-agents') - for a in ags: - self.assertIsInstance(a, agents.Agent) - self.assertEqual('kvm', a.hypervisor) - - def test_list_agents_with_hypervisor(self): - self.stub_hypervisors('xen') - ags = self.cs.agents.list('xen') - self.assert_called('GET', '/os-agents?hypervisor=xen') - for a in ags: - self.assertIsInstance(a, agents.Agent) - self.assertEqual('xen', a.hypervisor) - - def test_agents_create(self): - ag = self.cs.agents.create('win', 'x86', '7.0', - '/xxx/xxx/xxx', - 'add6bb58e139be103324d04d82d8f546', - 'xen') - body = {'agent': { - 'url': '/xxx/xxx/xxx', - 'hypervisor': 'xen', - 'md5hash': 'add6bb58e139be103324d04d82d8f546', - 'version': '7.0', - 'architecture': 'x86', - 'os': 'win'}} - self.assert_called('POST', '/os-agents', body) - self.assertEqual(1, ag._info.copy()['id']) - - def test_agents_delete(self): - self.cs.agents.delete('1') - self.assert_called('DELETE', '/os-agents/1') - - def _build_example_update_body(self): - return {"para": { - "url": "/yyy/yyyy/yyyy", - "version": "8.0", - "md5hash": "add6bb58e139be103324d04d82d8f546"}} - - def test_agents_modify(self): - ag = self.cs.agents.update('1', '8.0', - '/yyy/yyyy/yyyy', - 'add6bb58e139be103324d04d82d8f546') - body = self._build_example_update_body() - self.assert_called('PUT', '/os-agents/1', body) - self.assertEqual(1, ag.id) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_aggregates.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_aggregates.py deleted file mode 100644 index 6e7bd44e9c..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_aggregates.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import aggregates as data -from novaclient.tests.fixture_data import client -from novaclient.tests import utils -from novaclient.v1_1 import aggregates - - -class AggregatesTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_list_aggregates(self): - result = self.cs.aggregates.list() - self.assert_called('GET', '/os-aggregates') - for aggregate in result: - self.assertIsInstance(aggregate, aggregates.Aggregate) - - def test_create_aggregate(self): - body = {"aggregate": {"name": "test", "availability_zone": "nova1"}} - aggregate = self.cs.aggregates.create("test", "nova1") - self.assert_called('POST', '/os-aggregates', body) - self.assertIsInstance(aggregate, aggregates.Aggregate) - - def test_get(self): - aggregate = self.cs.aggregates.get("1") - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate, aggregates.Aggregate) - - aggregate2 = self.cs.aggregates.get(aggregate) - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate2, aggregates.Aggregate) - - def test_get_details(self): - aggregate = self.cs.aggregates.get_details("1") - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate, aggregates.Aggregate) - - aggregate2 = self.cs.aggregates.get_details(aggregate) - self.assert_called('GET', '/os-aggregates/1') - self.assertIsInstance(aggregate2, aggregates.Aggregate) - - def test_update(self): - aggregate = self.cs.aggregates.get("1") - values = {"name": "foo"} - body = {"aggregate": values} - - result1 = aggregate.update(values) - self.assert_called('PUT', '/os-aggregates/1', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.update(2, values) - self.assert_called('PUT', '/os-aggregates/2', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - def test_update_with_availability_zone(self): - aggregate = self.cs.aggregates.get("1") - values = {"name": "foo", "availability_zone": "new_zone"} - body = {"aggregate": values} - - result3 = self.cs.aggregates.update(aggregate, values) - self.assert_called('PUT', '/os-aggregates/1', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_add_host(self): - aggregate = self.cs.aggregates.get("1") - host = "host1" - body = {"add_host": {"host": "host1"}} - - result1 = aggregate.add_host(host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.add_host("2", host) - self.assert_called('POST', '/os-aggregates/2/action', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - result3 = self.cs.aggregates.add_host(aggregate, host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_remove_host(self): - aggregate = self.cs.aggregates.get("1") - host = "host1" - body = {"remove_host": {"host": "host1"}} - - result1 = aggregate.remove_host(host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.remove_host("2", host) - self.assert_called('POST', '/os-aggregates/2/action', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - result3 = self.cs.aggregates.remove_host(aggregate, host) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_set_metadata(self): - aggregate = self.cs.aggregates.get("1") - metadata = {"foo": "bar"} - body = {"set_metadata": {"metadata": metadata}} - - result1 = aggregate.set_metadata(metadata) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result1, aggregates.Aggregate) - - result2 = self.cs.aggregates.set_metadata(2, metadata) - self.assert_called('POST', '/os-aggregates/2/action', body) - self.assertIsInstance(result2, aggregates.Aggregate) - - result3 = self.cs.aggregates.set_metadata(aggregate, metadata) - self.assert_called('POST', '/os-aggregates/1/action', body) - self.assertIsInstance(result3, aggregates.Aggregate) - - def test_delete_aggregate(self): - aggregate = self.cs.aggregates.list()[0] - aggregate.delete() - self.assert_called('DELETE', '/os-aggregates/1') - - self.cs.aggregates.delete('1') - self.assert_called('DELETE', '/os-aggregates/1') - - self.cs.aggregates.delete(aggregate) - self.assert_called('DELETE', '/os-aggregates/1') diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_auth.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_auth.py deleted file mode 100644 index 6355b3245d..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_auth.py +++ /dev/null @@ -1,386 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import json - -from keystoneclient import fixture -import mock -import requests - -from novaclient import exceptions -from novaclient.tests import utils -from novaclient.v1_1 import client - - -class AuthenticateAgainstKeystoneTests(utils.TestCase): - - def get_token(self, **kwargs): - resp = fixture.V2Token(**kwargs) - resp.set_scope() - - s = resp.add_service('compute') - s.add_endpoint('http://localhost:8774/v1.1', region='RegionOne') - - return resp - - def test_authenticate_success(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, service_type='compute') - resp = self.get_token() - - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2) - resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}} - auth_response = utils.TestResponse({ - "status_code": 401, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_v1_auth_redirect(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V1, service_type='compute') - dict_correct_response = self.get_token() - correct_response = json.dumps(dict_correct_response) - dict_responses = [ - {"headers": {'location': 'http://127.0.0.1:5001'}, - "status_code": 305, - "text": "Use proxy"}, - # Configured on admin port, nova redirects to v2.0 port. - # When trying to connect on it, keystone auth succeed by v1.0 - # protocol (through headers) but tokens are being returned in - # body (looks like keystone bug). Leaved for compatibility. - {"headers": {}, - "status_code": 200, - "text": correct_response}, - {"headers": {}, - "status_code": 200, - "text": correct_response} - ] - - responses = [(utils.TestResponse(resp)) for resp in dict_responses] - - def side_effect(*args, **kwargs): - return responses.pop(0) - - mock_request = mock.Mock(side_effect=side_effect) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - kwargs = copy.copy(self.TEST_REQUEST_BASE) - kwargs['headers'] = headers - kwargs['data'] = json.dumps(body) - mock_request.assert_called_with( - "POST", - token_url, - allow_redirects=True, - **kwargs) - - resp = dict_correct_response - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - test_auth_call() - - def test_v2_auth_redirect(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, service_type='compute') - dict_correct_response = self.get_token() - correct_response = json.dumps(dict_correct_response) - dict_responses = [ - {"headers": {'location': 'http://127.0.0.1:5001'}, - "status_code": 305, - "text": "Use proxy"}, - # Configured on admin port, nova redirects to v2.0 port. - # When trying to connect on it, keystone auth succeed by v1.0 - # protocol (through headers) but tokens are being returned in - # body (looks like keystone bug). Leaved for compatibility. - {"headers": {}, - "status_code": 200, - "text": correct_response}, - {"headers": {}, - "status_code": 200, - "text": correct_response} - ] - - responses = [(utils.TestResponse(resp)) for resp in dict_responses] - - def side_effect(*args, **kwargs): - return responses.pop(0) - - mock_request = mock.Mock(side_effect=side_effect) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'passwordCredentials': { - 'username': cs.client.user, - 'password': cs.client.password, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - kwargs = copy.copy(self.TEST_REQUEST_BASE) - kwargs['headers'] = headers - kwargs['data'] = json.dumps(body) - mock_request.assert_called_with( - "POST", - token_url, - allow_redirects=True, - **kwargs) - - resp = dict_correct_response - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - test_auth_call() - - def test_ambiguous_endpoints(self): - cs = client.Client("username", "password", "project_id", - utils.AUTH_URL_V2, service_type='compute') - resp = self.get_token() - - # duplicate existing service - s = resp.add_service('compute') - s.add_endpoint('http://localhost:8774/v1.1', region='RegionOne') - - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests.Session, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.AmbiguousEndpoints, - cs.client.authenticate) - - test_auth_call() - - def test_authenticate_with_token_success(self): - cs = client.Client("username", None, "project_id", - utils.AUTH_URL_V2, service_type='compute') - cs.client.auth_token = "FAKE_ID" - resp = self.get_token(token_id="FAKE_ID") - auth_response = utils.TestResponse({ - "status_code": 200, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - with mock.patch.object(requests, "request", mock_request): - cs.client.authenticate() - headers = { - 'User-Agent': cs.client.USER_AGENT, - 'Content-Type': 'application/json', - 'Accept': 'application/json', - } - body = { - 'auth': { - 'token': { - 'id': cs.client.auth_token, - }, - 'tenantName': cs.client.projectid, - }, - } - - token_url = cs.client.auth_url + "/tokens" - mock_request.assert_called_with( - "POST", - token_url, - headers=headers, - data=json.dumps(body), - allow_redirects=True, - **self.TEST_REQUEST_BASE) - - endpoints = resp["access"]["serviceCatalog"][0]['endpoints'] - public_url = endpoints[0]["publicURL"].rstrip('/') - self.assertEqual(cs.client.management_url, public_url) - token_id = resp["access"]["token"]["id"] - self.assertEqual(cs.client.auth_token, token_id) - - def test_authenticate_with_token_failure(self): - cs = client.Client("username", None, "project_id", utils.AUTH_URL_V2) - cs.client.auth_token = "FAKE_ID" - resp = {"unauthorized": {"message": "Unauthorized", "code": "401"}} - auth_response = utils.TestResponse({ - "status_code": 401, - "text": json.dumps(resp), - }) - - mock_request = mock.Mock(return_value=(auth_response)) - - with mock.patch.object(requests.Session, "request", mock_request): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - -class AuthenticationTests(utils.TestCase): - def test_authenticate_success(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - management_url = 'https://localhost/v1.1/443470' - auth_response = utils.TestResponse({ - 'status_code': 204, - 'headers': { - 'x-server-management-url': management_url, - 'x-auth-token': '1b751d74-de0c-46ae-84f0-915744b582d1', - }, - }) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - cs.client.authenticate() - headers = { - 'Accept': 'application/json', - 'X-Auth-User': 'username', - 'X-Auth-Key': 'password', - 'X-Auth-Project-Id': 'project_id', - 'User-Agent': cs.client.USER_AGENT - } - mock_request.assert_called_with( - "GET", - cs.client.auth_url, - headers=headers, - **self.TEST_REQUEST_BASE) - - self.assertEqual(cs.client.management_url, - auth_response.headers['x-server-management-url']) - self.assertEqual(cs.client.auth_token, - auth_response.headers['x-auth-token']) - - test_auth_call() - - def test_authenticate_failure(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - auth_response = utils.TestResponse({'status_code': 401}) - mock_request = mock.Mock(return_value=(auth_response)) - - @mock.patch.object(requests, "request", mock_request) - def test_auth_call(): - self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) - - test_auth_call() - - def test_auth_automatic(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - http_client = cs.client - http_client.management_url = '' - mock_request = mock.Mock(return_value=(None, None)) - - @mock.patch.object(http_client, 'request', mock_request) - @mock.patch.object(http_client, 'authenticate') - def test_auth_call(m): - http_client.get('/') - m.assert_called() - mock_request.assert_called() - - test_auth_call() - - def test_auth_manual(self): - cs = client.Client("username", "password", - "project_id", utils.AUTH_URL) - - @mock.patch.object(cs.client, 'authenticate') - def test_auth_call(m): - cs.authenticate() - m.assert_called() - - test_auth_call() diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_availability_zone.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_availability_zone.py deleted file mode 100644 index 6851d9aeac..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_availability_zone.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from novaclient.tests.fixture_data import availability_zones as data -from novaclient.tests.fixture_data import client -from novaclient.tests import utils -from novaclient.v1_1 import availability_zones - - -class AvailabilityZoneTest(utils.FixturedTestCase): - # NOTE(cyeoh): import shell here so the V3 version of - # this class can inherit off the v3 version of shell - from novaclient.v1_1 import shell # noqa - - data_fixture_class = data.V1 - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def setUp(self): - super(AvailabilityZoneTest, self).setUp() - self.availability_zone_type = self._get_availability_zone_type() - - def _get_availability_zone_type(self): - return availability_zones.AvailabilityZone - - def _assertZone(self, zone, name, status): - self.assertEqual(zone.zoneName, name) - self.assertEqual(zone.zoneState, status) - - def test_list_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=False) - self.assert_called('GET', '/os-availability-zone') - - for zone in zones: - self.assertIsInstance(zone, self.availability_zone_type) - - self.assertEqual(2, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('zone-2'), six.u('not available')] - - z0 = self.shell._treeizeAvailabilityZone(zones[0]) - z1 = self.shell._treeizeAvailabilityZone(zones[1]) - - self.assertEqual((1, 1), (len(z0), len(z1))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z1[0], l1[0], l1[1]) - - def test_detail_availability_zone(self): - zones = self.cs.availability_zones.list(detailed=True) - self.assert_called('GET', '/os-availability-zone/detail') - - for zone in zones: - self.assertIsInstance(zone, self.availability_zone_type) - - self.assertEqual(3, len(zones)) - - l0 = [six.u('zone-1'), six.u('available')] - l1 = [six.u('|- fake_host-1'), six.u('')] - l2 = [six.u('| |- nova-compute'), - six.u('enabled :-) 2012-12-26 14:45:25')] - l3 = [six.u('internal'), six.u('available')] - l4 = [six.u('|- fake_host-1'), six.u('')] - l5 = [six.u('| |- nova-sched'), - six.u('enabled :-) 2012-12-26 14:45:25')] - l6 = [six.u('|- fake_host-2'), six.u('')] - l7 = [six.u('| |- nova-network'), - six.u('enabled XXX 2012-12-26 14:45:24')] - l8 = [six.u('zone-2'), six.u('not available')] - - z0 = self.shell._treeizeAvailabilityZone(zones[0]) - z1 = self.shell._treeizeAvailabilityZone(zones[1]) - z2 = self.shell._treeizeAvailabilityZone(zones[2]) - - self.assertEqual((3, 5, 1), (len(z0), len(z1), len(z2))) - - self._assertZone(z0[0], l0[0], l0[1]) - self._assertZone(z0[1], l1[0], l1[1]) - self._assertZone(z0[2], l2[0], l2[1]) - self._assertZone(z1[0], l3[0], l3[1]) - self._assertZone(z1[1], l4[0], l4[1]) - self._assertZone(z1[2], l5[0], l5[1]) - self._assertZone(z1[3], l6[0], l6[1]) - self._assertZone(z1[4], l7[0], l7[1]) - self._assertZone(z2[0], l8[0], l8[1]) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_certs.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_certs.py deleted file mode 100644 index 0a568d5851..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_certs.py +++ /dev/null @@ -1,36 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import certs as data -from novaclient.tests.fixture_data import client -from novaclient.tests import utils -from novaclient.v1_1 import certs - - -class CertsTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - cert_type = certs.Certificate - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_create_cert(self): - cert = self.cs.certs.create() - self.assert_called('POST', '/os-certificates') - self.assertIsInstance(cert, self.cert_type) - - def test_get_root_cert(self): - cert = self.cs.certs.get() - self.assert_called('GET', '/os-certificates/root') - self.assertIsInstance(cert, self.cert_type) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_cloudpipe.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_cloudpipe.py deleted file mode 100644 index 0a319085bc..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_cloudpipe.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import cloudpipe as data -from novaclient.tests import utils -from novaclient.v1_1 import cloudpipe - - -class CloudpipeTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_list_cloudpipes(self): - cp = self.cs.cloudpipe.list() - self.assert_called('GET', '/os-cloudpipe') - [self.assertIsInstance(c, cloudpipe.Cloudpipe) for c in cp] - - def test_create(self): - project = "test" - cp = self.cs.cloudpipe.create(project) - body = {'cloudpipe': {'project_id': project}} - self.assert_called('POST', '/os-cloudpipe', body) - self.assertIsInstance(cp, six.string_types) - - def test_update(self): - self.cs.cloudpipe.update("192.168.1.1", 2345) - body = {'configure_project': {'vpn_ip': "192.168.1.1", - 'vpn_port': 2345}} - self.assert_called('PUT', '/os-cloudpipe/configure-project', body) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_fixed_ips.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_fixed_ips.py deleted file mode 100644 index 5cfecf3335..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_fixed_ips.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import fixedips as data -from novaclient.tests import utils - - -class FixedIpsTest(utils.FixturedTestCase): - - data_fixture_class = data.Fixture - - scenarios = [('original', {'client_fixture_class': client.V1}), - ('session', {'client_fixture_class': client.SessionV1})] - - def test_get_fixed_ip(self): - info = self.cs.fixed_ips.get(fixed_ip='192.168.1.1') - self.assert_called('GET', '/os-fixed-ips/192.168.1.1') - self.assertEqual('192.168.1.0/24', info.cidr) - self.assertEqual('192.168.1.1', info.address) - self.assertEqual('foo', info.hostname) - self.assertEqual('bar', info.host) - - def test_reserve_fixed_ip(self): - body = {"reserve": None} - self.cs.fixed_ips.reserve(fixed_ip='192.168.1.1') - self.assert_called('POST', '/os-fixed-ips/192.168.1.1/action', body) - - def test_unreserve_fixed_ip(self): - body = {"unreserve": None} - self.cs.fixed_ips.unreserve(fixed_ip='192.168.1.1') - self.assert_called('POST', '/os-fixed-ips/192.168.1.1/action', body) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_flavor_access.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_flavor_access.py deleted file mode 100644 index b85f838ee5..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_flavor_access.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests import utils -from novaclient.tests.v1_1 import fakes -from novaclient.v1_1 import flavor_access - - -cs = fakes.FakeClient() - - -class FlavorAccessTest(utils.TestCase): - - def test_list_access_by_flavor_private(self): - kwargs = {'flavor': cs.flavors.get(2)} - r = cs.flavor_access.list(**kwargs) - cs.assert_called('GET', '/flavors/2/os-flavor-access') - [self.assertIsInstance(a, flavor_access.FlavorAccess) for a in r] - - def test_add_tenant_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj2' - r = cs.flavor_access.add_tenant_access(flavor, tenant) - - body = { - "addTenantAccess": { - "tenant": "proj2" - } - } - - cs.assert_called('POST', '/flavors/2/action', body) - [self.assertIsInstance(a, flavor_access.FlavorAccess) for a in r] - - def test_remove_tenant_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj2' - r = cs.flavor_access.remove_tenant_access(flavor, tenant) - - body = { - "removeTenantAccess": { - "tenant": "proj2" - } - } - - cs.assert_called('POST', '/flavors/2/action', body) - [self.assertIsInstance(a, flavor_access.FlavorAccess) for a in r] - - def test_repr_flavor_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj3' - r = cs.flavor_access.add_tenant_access(flavor, tenant) - - def get_expected(flavor_access): - return ("" % - (flavor_access.flavor_id, flavor_access.tenant_id)) - - for a in r: - self.assertEqual(get_expected(a), repr(a)) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_flavors.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_flavors.py deleted file mode 100644 index 8f5aea0079..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_flavors.py +++ /dev/null @@ -1,219 +0,0 @@ -# Copyright (c) 2013, OpenStack -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from novaclient import exceptions -from novaclient.tests import utils -from novaclient.tests.v1_1 import fakes -from novaclient.v1_1 import flavors - - -class FlavorsTest(utils.TestCase): - def setUp(self): - super(FlavorsTest, self).setUp() - self.cs = self._get_fake_client() - self.flavor_type = self._get_flavor_type() - - def _get_fake_client(self): - return fakes.FakeClient() - - def _get_flavor_type(self): - return flavors.Flavor - - def test_list_flavors(self): - fl = self.cs.flavors.list() - self.cs.assert_called('GET', '/flavors/detail') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_undetailed(self): - fl = self.cs.flavors.list(detailed=False) - self.cs.assert_called('GET', '/flavors') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_is_public_none(self): - fl = self.cs.flavors.list(is_public=None) - self.cs.assert_called('GET', '/flavors/detail?is_public=None') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_is_public_false(self): - fl = self.cs.flavors.list(is_public=False) - self.cs.assert_called('GET', '/flavors/detail?is_public=False') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_list_flavors_is_public_true(self): - fl = self.cs.flavors.list(is_public=True) - self.cs.assert_called('GET', '/flavors/detail') - for flavor in fl: - self.assertIsInstance(flavor, self.flavor_type) - - def test_get_flavor_details(self): - f = self.cs.flavors.get(1) - self.cs.assert_called('GET', '/flavors/1') - self.assertIsInstance(f, self.flavor_type) - self.assertEqual(256, f.ram) - self.assertEqual(10, f.disk) - self.assertEqual(10, f.ephemeral) - self.assertEqual(True, f.is_public) - - def test_get_flavor_details_alphanum_id(self): - f = self.cs.flavors.get('aa1') - self.cs.assert_called('GET', '/flavors/aa1') - self.assertIsInstance(f, self.flavor_type) - self.assertEqual(128, f.ram) - self.assertEqual(0, f.disk) - self.assertEqual(0, f.ephemeral) - self.assertEqual(True, f.is_public) - - def test_get_flavor_details_diablo(self): - f = self.cs.flavors.get(3) - self.cs.assert_called('GET', '/flavors/3') - self.assertIsInstance(f, self.flavor_type) - self.assertEqual(256, f.ram) - self.assertEqual(10, f.disk) - self.assertEqual('N/A', f.ephemeral) - self.assertEqual('N/A', f.is_public) - - def test_find(self): - f = self.cs.flavors.find(ram=256) - self.cs.assert_called('GET', '/flavors/detail') - self.assertEqual('256 MB Server', f.name) - - f = self.cs.flavors.find(disk=0) - self.assertEqual('128 MB Server', f.name) - - self.assertRaises(exceptions.NotFound, self.cs.flavors.find, - disk=12345) - - def _create_body(self, name, ram, vcpus, disk, ephemeral, id, swap, - rxtx_factor, is_public): - return { - "flavor": { - "name": name, - "ram": ram, - "vcpus": vcpus, - "disk": disk, - "OS-FLV-EXT-DATA:ephemeral": ephemeral, - "id": id, - "swap": swap, - "rxtx_factor": rxtx_factor, - "os-flavor-access:is_public": is_public, - } - } - - def test_create(self): - f = self.cs.flavors.create("flavorcreate", 512, 1, 10, 1234, - ephemeral=10, is_public=False) - - body = self._create_body("flavorcreate", 512, 1, 10, 10, 1234, 0, 1.0, - False) - - self.cs.assert_called('POST', '/flavors', body) - self.assertIsInstance(f, self.flavor_type) - - def test_create_with_id_as_string(self): - flavor_id = 'foobar' - f = self.cs.flavors.create("flavorcreate", 512, - 1, 10, flavor_id, ephemeral=10, - is_public=False) - - body = self._create_body("flavorcreate", 512, 1, 10, 10, flavor_id, 0, - 1.0, False) - - self.cs.assert_called('POST', '/flavors', body) - self.assertIsInstance(f, self.flavor_type) - - def test_create_ephemeral_ispublic_defaults(self): - f = self.cs.flavors.create("flavorcreate", 512, 1, 10, 1234) - - body = self._create_body("flavorcreate", 512, 1, 10, 0, 1234, 0, - 1.0, True) - - self.cs.assert_called('POST', '/flavors', body) - self.assertIsInstance(f, self.flavor_type) - - def test_invalid_parameters_create(self): - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", "invalid", 1, 10, 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, "invalid", 10, 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, "invalid", 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap="invalid", - ephemeral=0, rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap=0, - ephemeral="invalid", rxtx_factor=1.0, is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap=0, - ephemeral=0, rxtx_factor="invalid", is_public=True) - self.assertRaises(exceptions.CommandError, self.cs.flavors.create, - "flavorcreate", 512, 1, 10, 1234, swap=0, - ephemeral=0, rxtx_factor=1.0, is_public='invalid') - - def test_delete(self): - self.cs.flavors.delete("flavordelete") - self.cs.assert_called('DELETE', '/flavors/flavordelete') - - def test_delete_with_flavor_instance(self): - f = self.cs.flavors.get(2) - self.cs.flavors.delete(f) - self.cs.assert_called('DELETE', '/flavors/2') - - def test_delete_with_flavor_instance_method(self): - f = self.cs.flavors.get(2) - f.delete() - self.cs.assert_called('DELETE', '/flavors/2') - - def test_set_keys(self): - f = self.cs.flavors.get(1) - f.set_keys({'k1': 'v1'}) - self.cs.assert_called('POST', '/flavors/1/os-extra_specs', - {"extra_specs": {'k1': 'v1'}}) - - def test_set_with_valid_keys(self): - valid_keys = ['key4', 'month.price', 'I-Am:AK-ey.44-', - 'key with spaces and _'] - - f = self.cs.flavors.get(4) - for key in valid_keys: - f.set_keys({key: 'v4'}) - self.cs.assert_called('POST', '/flavors/4/os-extra_specs', - {"extra_specs": {key: 'v4'}}) - - def test_set_with_invalid_keys(self): - invalid_keys = ['/1', '?1', '%1', '<', '>'] - - f = self.cs.flavors.get(1) - for key in invalid_keys: - self.assertRaises(exceptions.CommandError, f.set_keys, {key: 'v1'}) - - @mock.patch.object(flavors.FlavorManager, '_delete') - def test_unset_keys(self, mock_delete): - f = self.cs.flavors.get(1) - keys = ['k1', 'k2'] - f.unset_keys(keys) - mock_delete.assert_has_calls([ - mock.call("/flavors/1/os-extra_specs/k1"), - mock.call("/flavors/1/os-extra_specs/k2") - ]) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ip_dns.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ip_dns.py deleted file mode 100644 index 2ded1725e3..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ip_dns.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import floatingips as data -from novaclient.tests import utils -from novaclient.v1_1 import floating_ip_dns - - -class FloatingIPDNSDomainTest(utils.FixturedTestCase): - - testdomain = "testdomain" - client_fixture_class = client.V1 - data_fixture_class = data.DNSFixture - - def test_dns_domains(self): - domainlist = self.cs.dns_domains.domains() - self.assertEqual(2, len(domainlist)) - - for entry in domainlist: - self.assertIsInstance(entry, - floating_ip_dns.FloatingIPDNSDomain) - - self.assertEqual('example.com', domainlist[1].domain) - - def test_create_private_domain(self): - self.cs.dns_domains.create_private(self.testdomain, 'test_avzone') - self.assert_called('PUT', '/os-floating-ip-dns/%s' % - self.testdomain) - - def test_create_public_domain(self): - self.cs.dns_domains.create_public(self.testdomain, 'test_project') - self.assert_called('PUT', '/os-floating-ip-dns/%s' % - self.testdomain) - - def test_delete_domain(self): - self.cs.dns_domains.delete(self.testdomain) - self.assert_called('DELETE', '/os-floating-ip-dns/%s' % - self.testdomain) - - -class FloatingIPDNSEntryTest(utils.FixturedTestCase): - - testname = "testname" - testip = "1.2.3.4" - testdomain = "testdomain" - testtype = "A" - client_fixture_class = client.V1 - data_fixture_class = data.DNSFixture - - def test_get_dns_entries_by_ip(self): - entries = self.cs.dns_entries.get_for_ip(self.testdomain, - ip=self.testip) - self.assertEqual(2, len(entries)) - - for entry in entries: - self.assertIsInstance(entry, - floating_ip_dns.FloatingIPDNSEntry) - - self.assertEqual('host2', entries[1].dns_entry['name']) - self.assertEqual(entries[1].dns_entry['ip'], self.testip) - - def test_get_dns_entry_by_name(self): - entry = self.cs.dns_entries.get(self.testdomain, - self.testname) - self.assertIsInstance(entry, floating_ip_dns.FloatingIPDNSEntry) - self.assertEqual(entry.name, self.testname) - - def test_create_entry(self): - self.cs.dns_entries.create(self.testdomain, - self.testname, - self.testip, - self.testtype) - - self.assert_called('PUT', '/os-floating-ip-dns/%s/entries/%s' % - (self.testdomain, self.testname)) - - def test_delete_entry(self): - self.cs.dns_entries.delete(self.testdomain, self.testname) - self.assert_called('DELETE', '/os-floating-ip-dns/%s/entries/%s' % - (self.testdomain, self.testname)) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ip_pools.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ip_pools.py deleted file mode 100644 index efdfabf30e..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ip_pools.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import floatingips as data -from novaclient.tests import utils -from novaclient.v1_1 import floating_ip_pools - - -class TestFloatingIPPools(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.PoolsFixture - - def test_list_floating_ips(self): - fl = self.cs.floating_ip_pools.list() - self.assert_called('GET', '/os-floating-ip-pools') - [self.assertIsInstance(f, floating_ip_pools.FloatingIPPool) - for f in fl] diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ips.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ips.py deleted file mode 100644 index 93cc733bad..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ips.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import floatingips as data -from novaclient.tests import utils -from novaclient.v1_1 import floating_ips - - -class FloatingIPsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.FloatingFixture - - def test_list_floating_ips(self): - fips = self.cs.floating_ips.list() - self.assert_called('GET', '/os-floating-ips') - for fip in fips: - self.assertIsInstance(fip, floating_ips.FloatingIP) - - def test_list_floating_ips_all_tenants(self): - fips = self.cs.floating_ips.list(all_tenants=True) - self.assert_called('GET', '/os-floating-ips?all_tenants=1') - for fip in fips: - self.assertIsInstance(fip, floating_ips.FloatingIP) - - def test_delete_floating_ip(self): - fl = self.cs.floating_ips.list()[0] - fl.delete() - self.assert_called('DELETE', '/os-floating-ips/1') - self.cs.floating_ips.delete(1) - self.assert_called('DELETE', '/os-floating-ips/1') - self.cs.floating_ips.delete(fl) - self.assert_called('DELETE', '/os-floating-ips/1') - - def test_create_floating_ip(self): - fl = self.cs.floating_ips.create() - self.assert_called('POST', '/os-floating-ips') - self.assertIsNone(fl.pool) - self.assertIsInstance(fl, floating_ips.FloatingIP) - - def test_create_floating_ip_with_pool(self): - fl = self.cs.floating_ips.create('nova') - self.assert_called('POST', '/os-floating-ips') - self.assertEqual('nova', fl.pool) - self.assertIsInstance(fl, floating_ips.FloatingIP) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ips_bulk.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ips_bulk.py deleted file mode 100644 index dd4f823c7a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_floating_ips_bulk.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import floatingips as data -from novaclient.tests import utils -from novaclient.v1_1 import floating_ips_bulk - - -class FloatingIPsBulkTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.BulkFixture - - def test_list_floating_ips_bulk(self): - fl = self.cs.floating_ips_bulk.list() - self.assert_called('GET', '/os-floating-ips-bulk') - [self.assertIsInstance(f, floating_ips_bulk.FloatingIP) - for f in fl] - - def test_list_floating_ips_bulk_host_filter(self): - fl = self.cs.floating_ips_bulk.list('testHost') - self.assert_called('GET', '/os-floating-ips-bulk/testHost') - [self.assertIsInstance(f, floating_ips_bulk.FloatingIP) - for f in fl] - - def test_create_floating_ips_bulk(self): - fl = self.cs.floating_ips_bulk.create('192.168.1.0/30') - body = {'floating_ips_bulk_create': {'ip_range': '192.168.1.0/30'}} - self.assert_called('POST', '/os-floating-ips-bulk', body) - self.assertEqual(fl.ip_range, - body['floating_ips_bulk_create']['ip_range']) - - def test_create_floating_ips_bulk_with_pool_and_host(self): - fl = self.cs.floating_ips_bulk.create('192.168.1.0/30', 'poolTest', - 'interfaceTest') - body = {'floating_ips_bulk_create': - {'ip_range': '192.168.1.0/30', 'pool': 'poolTest', - 'interface': 'interfaceTest'}} - self.assert_called('POST', '/os-floating-ips-bulk', body) - self.assertEqual(fl.ip_range, - body['floating_ips_bulk_create']['ip_range']) - self.assertEqual(fl.pool, - body['floating_ips_bulk_create']['pool']) - self.assertEqual(fl.interface, - body['floating_ips_bulk_create']['interface']) - - def test_delete_floating_ips_bulk(self): - fl = self.cs.floating_ips_bulk.delete('192.168.1.0/30') - body = {'ip_range': '192.168.1.0/30'} - self.assert_called('PUT', '/os-floating-ips-bulk/delete', body) - self.assertEqual(fl.floating_ips_bulk_delete, body['ip_range']) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_fping.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_fping.py deleted file mode 100644 index 5a3fb6401d..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_fping.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import fping as data -from novaclient.tests import utils -from novaclient.v1_1 import fping - - -class FpingTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_fping_repr(self): - r = self.cs.fping.get(1) - self.assertEqual("", repr(r)) - - def test_list_fpings(self): - fl = self.cs.fping.list() - self.assert_called('GET', '/os-fping') - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assertEqual("fake-project", f.project_id) - self.assertEqual(True, f.alive) - - def test_list_fpings_all_tenants(self): - fl = self.cs.fping.list(all_tenants=True) - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assert_called('GET', '/os-fping?all_tenants=1') - - def test_list_fpings_exclude(self): - fl = self.cs.fping.list(exclude=['1']) - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assert_called('GET', '/os-fping?exclude=1') - - def test_list_fpings_include(self): - fl = self.cs.fping.list(include=['1']) - for f in fl: - self.assertIsInstance(f, fping.Fping) - self.assert_called('GET', '/os-fping?include=1') - - def test_get_fping(self): - f = self.cs.fping.get(1) - self.assert_called('GET', '/os-fping/1') - self.assertIsInstance(f, fping.Fping) - self.assertEqual("fake-project", f.project_id) - self.assertEqual(True, f.alive) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_hosts.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_hosts.py deleted file mode 100644 index 8fcdf5a76f..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_hosts.py +++ /dev/null @@ -1,84 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import hosts as data -from novaclient.tests import utils -from novaclient.v1_1 import hosts - - -class HostsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def test_describe_resource(self): - hs = self.cs.hosts.get('host') - self.assert_called('GET', '/os-hosts/host') - [self.assertIsInstance(h, hosts.Host) for h in hs] - - def test_list_host(self): - hs = self.cs.hosts.list() - self.assert_called('GET', '/os-hosts') - [self.assertIsInstance(h, hosts.Host) for h in hs] - [self.assertEqual(h.zone, 'nova1') for h in hs] - - def test_list_host_with_zone(self): - hs = self.cs.hosts.list('nova') - self.assert_called('GET', '/os-hosts?zone=nova') - [self.assertIsInstance(h, hosts.Host) for h in hs] - [self.assertEqual(h.zone, 'nova') for h in hs] - - def test_update_enable(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"status": "enabled"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', values) - self.assertIsInstance(result, hosts.Host) - - def test_update_maintenance(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"maintenance_mode": "enable"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', values) - self.assertIsInstance(result, hosts.Host) - - def test_update_both(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"status": "enabled", - "maintenance_mode": "enable"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', values) - self.assertIsInstance(result, hosts.Host) - - def test_host_startup(self): - host = self.cs.hosts.get('sample_host')[0] - host.startup() - self.assert_called( - 'GET', '/os-hosts/sample_host/startup') - - def test_host_reboot(self): - host = self.cs.hosts.get('sample_host')[0] - host.reboot() - self.assert_called( - 'GET', '/os-hosts/sample_host/reboot') - - def test_host_shutdown(self): - host = self.cs.hosts.get('sample_host')[0] - host.shutdown() - self.assert_called( - 'GET', '/os-hosts/sample_host/shutdown') - - def test_hosts_repr(self): - hs = self.cs.hosts.get('host') - self.assertEqual('', repr(hs[0])) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_hypervisors.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_hypervisors.py deleted file mode 100644 index 8376d61f57..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_hypervisors.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import hypervisors as data -from novaclient.tests import utils - - -class HypervisorsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def compare_to_expected(self, expected, hyper): - for key, value in expected.items(): - self.assertEqual(getattr(hyper, key), value) - - def test_hypervisor_index(self): - expected = [ - dict(id=1234, hypervisor_hostname='hyper1'), - dict(id=5678, hypervisor_hostname='hyper2'), - ] - - result = self.cs.hypervisors.list(False) - self.assert_called('GET', '/os-hypervisors') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_detail(self): - expected = [ - dict(id=1234, - service=dict(id=1, host='compute1'), - vcpus=4, - memory_mb=10 * 1024, - local_gb=250, - vcpus_used=2, - memory_mb_used=5 * 1024, - local_gb_used=125, - hypervisor_type="xen", - hypervisor_version=3, - hypervisor_hostname="hyper1", - free_ram_mb=5 * 1024, - free_disk_gb=125, - current_workload=2, - running_vms=2, - cpu_info='cpu_info', - disk_available_least=100), - dict(id=2, - service=dict(id=2, host="compute2"), - vcpus=4, - memory_mb=10 * 1024, - local_gb=250, - vcpus_used=2, - memory_mb_used=5 * 1024, - local_gb_used=125, - hypervisor_type="xen", - hypervisor_version=3, - hypervisor_hostname="hyper2", - free_ram_mb=5 * 1024, - free_disk_gb=125, - current_workload=2, - running_vms=2, - cpu_info='cpu_info', - disk_available_least=100)] - - result = self.cs.hypervisors.list() - self.assert_called('GET', '/os-hypervisors/detail') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_search(self): - expected = [ - dict(id=1234, hypervisor_hostname='hyper1'), - dict(id=5678, hypervisor_hostname='hyper2'), - ] - - result = self.cs.hypervisors.search('hyper') - self.assert_called('GET', '/os-hypervisors/hyper/search') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_servers(self): - expected = [ - dict(id=1234, - hypervisor_hostname='hyper1', - servers=[ - dict(name='inst1', uuid='uuid1'), - dict(name='inst2', uuid='uuid2')]), - dict(id=5678, - hypervisor_hostname='hyper2', - servers=[ - dict(name='inst3', uuid='uuid3'), - dict(name='inst4', uuid='uuid4')]), - ] - - result = self.cs.hypervisors.search('hyper', True) - self.assert_called('GET', '/os-hypervisors/hyper/servers') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_get(self): - expected = dict( - id=1234, - service=dict(id=1, host='compute1'), - vcpus=4, - memory_mb=10 * 1024, - local_gb=250, - vcpus_used=2, - memory_mb_used=5 * 1024, - local_gb_used=125, - hypervisor_type="xen", - hypervisor_version=3, - hypervisor_hostname="hyper1", - free_ram_mb=5 * 1024, - free_disk_gb=125, - current_workload=2, - running_vms=2, - cpu_info='cpu_info', - disk_available_least=100) - - result = self.cs.hypervisors.get(1234) - self.assert_called('GET', '/os-hypervisors/1234') - - self.compare_to_expected(expected, result) - - def test_hypervisor_uptime(self): - expected = dict( - id=1234, - hypervisor_hostname="hyper1", - uptime="fake uptime") - - result = self.cs.hypervisors.uptime(1234) - self.assert_called('GET', '/os-hypervisors/1234/uptime') - - self.compare_to_expected(expected, result) - - def test_hypervisor_statistics(self): - expected = dict( - count=2, - vcpus=8, - memory_mb=20 * 1024, - local_gb=500, - vcpus_used=4, - memory_mb_used=10 * 1024, - local_gb_used=250, - free_ram_mb=10 * 1024, - free_disk_gb=250, - current_workload=4, - running_vms=4, - disk_available_least=200, - ) - - result = self.cs.hypervisors.statistics() - self.assert_called('GET', '/os-hypervisors/statistics') - - self.compare_to_expected(expected, result) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_images.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_images.py deleted file mode 100644 index e237bcd5cb..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_images.py +++ /dev/null @@ -1,66 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import images as data -from novaclient.tests import utils -from novaclient.v1_1 import images - - -class ImagesTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def test_list_images(self): - il = self.cs.images.list() - self.assert_called('GET', '/images/detail') - [self.assertIsInstance(i, images.Image) for i in il] - - def test_list_images_undetailed(self): - il = self.cs.images.list(detailed=False) - self.assert_called('GET', '/images') - [self.assertIsInstance(i, images.Image) for i in il] - - def test_list_images_with_limit(self): - self.cs.images.list(limit=4) - self.assert_called('GET', '/images/detail?limit=4') - - def test_get_image_details(self): - i = self.cs.images.get(1) - self.assert_called('GET', '/images/1') - self.assertIsInstance(i, images.Image) - self.assertEqual(1, i.id) - self.assertEqual('CentOS 5.2', i.name) - - def test_delete_image(self): - self.cs.images.delete(1) - self.assert_called('DELETE', '/images/1') - - def test_delete_meta(self): - self.cs.images.delete_meta(1, {'test_key': 'test_value'}) - self.assert_called('DELETE', '/images/1/metadata/test_key') - - def test_set_meta(self): - self.cs.images.set_meta(1, {'test_key': 'test_value'}) - self.assert_called('POST', '/images/1/metadata', - {"metadata": {'test_key': 'test_value'}}) - - def test_find(self): - i = self.cs.images.find(name="CentOS 5.2") - self.assertEqual(1, i.id) - self.assert_called('GET', '/images/1') - - iml = self.cs.images.findall(status='SAVING') - self.assertEqual(1, len(iml)) - self.assertEqual('My Server Backup', iml[0].name) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_keypairs.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_keypairs.py deleted file mode 100644 index 9e8e63fd52..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_keypairs.py +++ /dev/null @@ -1,64 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import keypairs as data -from novaclient.tests import utils -from novaclient.v1_1 import keypairs - - -class KeypairsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def setUp(self): - super(KeypairsTest, self).setUp() - self.keypair_type = self._get_keypair_type() - self.keypair_prefix = self._get_keypair_prefix() - - def _get_keypair_type(self): - return keypairs.Keypair - - def _get_keypair_prefix(self): - return keypairs.KeypairManager.keypair_prefix - - def test_get_keypair(self): - kp = self.cs.keypairs.get('test') - self.assert_called('GET', '/%s/test' % self.keypair_prefix) - self.assertIsInstance(kp, keypairs.Keypair) - self.assertEqual('test', kp.name) - - def test_list_keypairs(self): - kps = self.cs.keypairs.list() - self.assert_called('GET', '/%s' % self.keypair_prefix) - [self.assertIsInstance(kp, keypairs.Keypair) for kp in kps] - - def test_delete_keypair(self): - kp = self.cs.keypairs.list()[0] - kp.delete() - self.assert_called('DELETE', '/%s/test' % self.keypair_prefix) - self.cs.keypairs.delete('test') - self.assert_called('DELETE', '/%s/test' % self.keypair_prefix) - self.cs.keypairs.delete(kp) - self.assert_called('DELETE', '/%s/test' % self.keypair_prefix) - - def test_create_keypair(self): - kp = self.cs.keypairs.create("foo") - self.assert_called('POST', '/%s' % self.keypair_prefix) - self.assertIsInstance(kp, keypairs.Keypair) - - def test_import_keypair(self): - kp = self.cs.keypairs.create("foo", "fake-public-key") - self.assert_called('POST', '/%s' % self.keypair_prefix) - self.assertIsInstance(kp, keypairs.Keypair) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_limits.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_limits.py deleted file mode 100644 index 212be45499..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_limits.py +++ /dev/null @@ -1,88 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import limits as data -from novaclient.tests import utils -from novaclient.v1_1 import limits - - -class LimitsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_get_limits(self): - obj = self.cs.limits.get() - self.assert_called('GET', '/limits') - self.assertIsInstance(obj, limits.Limits) - - def test_get_limits_for_a_tenant(self): - obj = self.cs.limits.get(tenant_id=1234) - self.assert_called('GET', '/limits?tenant_id=1234') - self.assertIsInstance(obj, limits.Limits) - - def test_absolute_limits(self): - obj = self.cs.limits.get() - - expected = ( - limits.AbsoluteLimit("maxTotalRAMSize", 51200), - limits.AbsoluteLimit("maxServerMeta", 5), - limits.AbsoluteLimit("maxImageMeta", 5), - limits.AbsoluteLimit("maxPersonality", 5), - limits.AbsoluteLimit("maxPersonalitySize", 10240), - ) - - abs_limits = list(obj.absolute) - self.assertEqual(len(abs_limits), len(expected)) - - for limit in abs_limits: - self.assertTrue(limit in expected) - - def test_absolute_limits_reserved(self): - obj = self.cs.limits.get(reserved=True) - - expected = ( - limits.AbsoluteLimit("maxTotalRAMSize", 51200), - limits.AbsoluteLimit("maxServerMeta", 5), - limits.AbsoluteLimit("maxImageMeta", 5), - limits.AbsoluteLimit("maxPersonality", 5), - limits.AbsoluteLimit("maxPersonalitySize", 10240), - ) - - self.assert_called('GET', '/limits?reserved=1') - abs_limits = list(obj.absolute) - self.assertEqual(len(abs_limits), len(expected)) - - for limit in abs_limits: - self.assertTrue(limit in expected) - - def test_rate_limits(self): - obj = self.cs.limits.get() - - expected = ( - limits.RateLimit('POST', '*', '.*', 10, 2, 'MINUTE', - '2011-12-15T22:42:45Z'), - limits.RateLimit('PUT', '*', '.*', 10, 2, 'MINUTE', - '2011-12-15T22:42:45Z'), - limits.RateLimit('DELETE', '*', '.*', 100, 100, 'MINUTE', - '2011-12-15T22:42:45Z'), - limits.RateLimit('POST', '*/servers', '^/servers', 25, 24, 'DAY', - '2011-12-15T22:42:45Z'), - ) - - rate_limits = list(obj.rate) - self.assertEqual(len(rate_limits), len(expected)) - - for limit in rate_limits: - self.assertTrue(limit in expected) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_networks.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_networks.py deleted file mode 100644 index 1fbd112ce2..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_networks.py +++ /dev/null @@ -1,106 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import networks as data -from novaclient.tests import utils -from novaclient.v1_1 import networks - - -class NetworksTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_list_networks(self): - fl = self.cs.networks.list() - self.assert_called('GET', '/os-networks') - [self.assertIsInstance(f, networks.Network) for f in fl] - - def test_get_network(self): - f = self.cs.networks.get(1) - self.assert_called('GET', '/os-networks/1') - self.assertIsInstance(f, networks.Network) - - def test_delete(self): - self.cs.networks.delete('networkdelete') - self.assert_called('DELETE', '/os-networks/networkdelete') - - def test_create(self): - f = self.cs.networks.create(label='foo') - self.assert_called('POST', '/os-networks', - {'network': {'label': 'foo'}}) - self.assertIsInstance(f, networks.Network) - - def test_create_allparams(self): - params = { - 'label': 'bar', - 'bridge': 'br0', - 'bridge_interface': 'int0', - 'cidr': '192.0.2.0/24', - 'cidr_v6': '2001:DB8::/32', - 'dns1': '1.1.1.1', - 'dns2': '1.1.1.2', - 'fixed_cidr': '198.51.100.0/24', - 'gateway': '192.0.2.1', - 'gateway_v6': '2001:DB8::1', - 'multi_host': 'T', - 'priority': '1', - 'project_id': '1', - 'vlan': 5, - 'vlan_start': 1, - 'vpn_start': 1, - 'mtu': 1500, - 'enable_dhcp': 'T', - 'dhcp_server': '1920.2.2', - 'share_address': 'T', - 'allowed_start': '192.0.2.10', - 'allowed_end': '192.0.2.20', - } - - f = self.cs.networks.create(**params) - self.assert_called('POST', '/os-networks', {'network': params}) - self.assertIsInstance(f, networks.Network) - - def test_associate_project(self): - self.cs.networks.associate_project('networktest') - self.assert_called('POST', '/os-networks/add', - {'id': 'networktest'}) - - def test_associate_host(self): - self.cs.networks.associate_host('networktest', 'testHost') - self.assert_called('POST', '/os-networks/networktest/action', - {'associate_host': 'testHost'}) - - def test_disassociate(self): - self.cs.networks.disassociate('networkdisassociate') - self.assert_called('POST', - '/os-networks/networkdisassociate/action', - {'disassociate': None}) - - def test_disassociate_host_only(self): - self.cs.networks.disassociate('networkdisassociate', True, False) - self.assert_called('POST', - '/os-networks/networkdisassociate/action', - {'disassociate_host': None}) - - def test_disassociate_project(self): - self.cs.networks.disassociate('networkdisassociate', False, True) - self.assert_called('POST', - '/os-networks/networkdisassociate/action', - {'disassociate_project': None}) - - def test_add(self): - self.cs.networks.add('networkadd') - self.assert_called('POST', '/os-networks/add', - {'id': 'networkadd'}) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_quota_classes.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_quota_classes.py deleted file mode 100644 index 338549bfa9..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_quota_classes.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests import utils -from novaclient.tests.v1_1 import fakes - - -cs = fakes.FakeClient() - - -class QuotaClassSetsTest(utils.TestCase): - - def test_class_quotas_get(self): - class_name = 'test' - cs.quota_classes.get(class_name) - cs.assert_called('GET', '/os-quota-class-sets/%s' % class_name) - - def test_update_quota(self): - q = cs.quota_classes.get('test') - q.update(cores=2) - cs.assert_called('PUT', '/os-quota-class-sets/test') - - def test_refresh_quota(self): - q = cs.quota_classes.get('test') - q2 = cs.quota_classes.get('test') - self.assertEqual(q.cores, q2.cores) - q2.cores = 0 - self.assertNotEqual(q.cores, q2.cores) - q2.get() - self.assertEqual(q.cores, q2.cores) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_quotas.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_quotas.py deleted file mode 100644 index 8ff0d5967a..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_quotas.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import quotas as data -from novaclient.tests import utils - - -class QuotaSetsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def test_tenant_quotas_get(self): - tenant_id = 'test' - self.cs.quotas.get(tenant_id) - self.assert_called('GET', '/os-quota-sets/%s' % tenant_id) - - def test_user_quotas_get(self): - tenant_id = 'test' - user_id = 'fake_user' - self.cs.quotas.get(tenant_id, user_id=user_id) - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - self.assert_called('GET', url) - - def test_tenant_quotas_defaults(self): - tenant_id = '97f4c221bff44578b0300df4ef119353' - self.cs.quotas.defaults(tenant_id) - self.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id) - - def test_force_update_quota(self): - q = self.cs.quotas.get('97f4c221bff44578b0300df4ef119353') - q.update(cores=2, force=True) - self.assert_called( - 'PUT', '/os-quota-sets/97f4c221bff44578b0300df4ef119353', - {'quota_set': {'force': True, - 'cores': 2, - 'tenant_id': '97f4c221bff44578b0300df4ef119353'}}) - - def test_quotas_delete(self): - tenant_id = 'test' - self.cs.quotas.delete(tenant_id) - self.assert_called('DELETE', '/os-quota-sets/%s' % tenant_id) - - def test_user_quotas_delete(self): - tenant_id = 'test' - user_id = 'fake_user' - self.cs.quotas.delete(tenant_id, user_id=user_id) - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - self.assert_called('DELETE', url) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_security_group_rules.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_security_group_rules.py deleted file mode 100644 index bf69a86ed8..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_security_group_rules.py +++ /dev/null @@ -1,86 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import exceptions -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import security_group_rules as data -from novaclient.tests import utils -from novaclient.v1_1 import security_group_rules - - -class SecurityGroupRulesTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_delete_security_group_rule(self): - self.cs.security_group_rules.delete(1) - self.assert_called('DELETE', '/os-security-group-rules/1') - - def test_create_security_group_rule(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16") - - body = { - "security_group_rule": { - "ip_protocol": "tcp", - "from_port": 1, - "to_port": 65535, - "cidr": "10.0.0.0/16", - "group_id": None, - "parent_group_id": 1, - } - } - - self.assert_called('POST', '/os-security-group-rules', body) - self.assertTrue(isinstance(sg, security_group_rules.SecurityGroupRule)) - - def test_create_security_group_group_rule(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16", 101) - - body = { - "security_group_rule": { - "ip_protocol": "tcp", - "from_port": 1, - "to_port": 65535, - "cidr": "10.0.0.0/16", - "group_id": 101, - "parent_group_id": 1, - } - } - - self.assert_called('POST', '/os-security-group-rules', body) - self.assertTrue(isinstance(sg, security_group_rules.SecurityGroupRule)) - - def test_invalid_parameters_create(self): - self.assertRaises(exceptions.CommandError, - self.cs.security_group_rules.create, - 1, "invalid_ip_protocol", 1, 65535, "10.0.0.0/16", 101) - self.assertRaises(exceptions.CommandError, - self.cs.security_group_rules.create, - 1, "tcp", "invalid_from_port", 65535, "10.0.0.0/16", 101) - self.assertRaises(exceptions.CommandError, - self.cs.security_group_rules.create, - 1, "tcp", 1, "invalid_to_port", "10.0.0.0/16", 101) - - def test_security_group_rule_str(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16") - self.assertEqual('1', str(sg)) - - def test_security_group_rule_del(self): - sg = self.cs.security_group_rules.create(1, "tcp", 1, 65535, - "10.0.0.0/16") - sg.delete() - self.assert_called('DELETE', '/os-security-group-rules/1') diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_security_groups.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_security_groups.py deleted file mode 100644 index f5b771af1d..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_security_groups.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import security_groups as data -from novaclient.tests import utils -from novaclient.v1_1 import security_groups - - -class SecurityGroupsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def _do_test_list_security_groups(self, search_opts, path): - sgs = self.cs.security_groups.list(search_opts=search_opts) - self.assert_called('GET', path) - for sg in sgs: - self.assertIsInstance(sg, security_groups.SecurityGroup) - - def test_list_security_groups_all_tenants_on(self): - self._do_test_list_security_groups( - None, '/os-security-groups') - - def test_list_security_groups_all_tenants_on(self): - self._do_test_list_security_groups( - {'all_tenants': 1}, '/os-security-groups?all_tenants=1') - - def test_list_security_groups_all_tenants_off(self): - self._do_test_list_security_groups( - {'all_tenants': 0}, '/os-security-groups') - - def test_get_security_groups(self): - sg = self.cs.security_groups.get(1) - self.assert_called('GET', '/os-security-groups/1') - self.assertIsInstance(sg, security_groups.SecurityGroup) - self.assertEqual('1', str(sg)) - - def test_delete_security_group(self): - sg = self.cs.security_groups.list()[0] - sg.delete() - self.assert_called('DELETE', '/os-security-groups/1') - self.cs.security_groups.delete(1) - self.assert_called('DELETE', '/os-security-groups/1') - self.cs.security_groups.delete(sg) - self.assert_called('DELETE', '/os-security-groups/1') - - def test_create_security_group(self): - sg = self.cs.security_groups.create("foo", "foo barr") - self.assert_called('POST', '/os-security-groups') - self.assertIsInstance(sg, security_groups.SecurityGroup) - - def test_update_security_group(self): - sg = self.cs.security_groups.list()[0] - secgroup = self.cs.security_groups.update(sg, "update", "update") - self.assert_called('PUT', '/os-security-groups/1') - self.assertIsInstance(secgroup, security_groups.SecurityGroup) - - def test_refresh_security_group(self): - sg = self.cs.security_groups.get(1) - sg2 = self.cs.security_groups.get(1) - self.assertEqual(sg.name, sg2.name) - sg2.name = "should be test" - self.assertNotEqual(sg.name, sg2.name) - sg2.get() - self.assertEqual(sg.name, sg2.name) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_server_groups.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_server_groups.py deleted file mode 100644 index e341dc0c37..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_server_groups.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2014 VMware, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import server_groups as data -from novaclient.tests import utils -from novaclient.v1_1 import server_groups - - -class ServerGroupsTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.Fixture - - def test_list_server_groups(self): - result = self.cs.server_groups.list() - self.assert_called('GET', '/os-server-groups') - for server_group in result: - self.assertTrue(isinstance(server_group, - server_groups.ServerGroup)) - - def test_create_server_group(self): - kwargs = {'name': 'ig1', - 'policies': ['anti-affinity']} - server_group = self.cs.server_groups.create(**kwargs) - body = {'server_group': kwargs} - self.assert_called('POST', '/os-server-groups', body) - self.assertTrue(isinstance(server_group, - server_groups.ServerGroup)) - - def test_get_server_group(self): - id = '2cbd51f4-fafe-4cdb-801b-cf913a6f288b' - server_group = self.cs.server_groups.get(id) - self.assert_called('GET', '/os-server-groups/%s' % id) - self.assertTrue(isinstance(server_group, - server_groups.ServerGroup)) - - def test_delete_server_group(self): - id = '2cbd51f4-fafe-4cdb-801b-cf913a6f288b' - self.cs.server_groups.delete(id) - self.assert_called('DELETE', '/os-server-groups/%s' % id) diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_servers.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_servers.py deleted file mode 100644 index a8a3aeabdf..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_servers.py +++ /dev/null @@ -1,666 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import six - -from novaclient import exceptions -from novaclient.openstack.common import jsonutils -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import floatingips -from novaclient.tests.fixture_data import servers as data -from novaclient.tests import utils -from novaclient.v1_1 import servers - - -class ServersTest(utils.FixturedTestCase): - - client_fixture_class = client.V1 - data_fixture_class = data.V1 - - def setUp(self): - super(ServersTest, self).setUp() - self.useFixture(floatingips.FloatingFixture(self.requests)) - - def test_list_servers(self): - sl = self.cs.servers.list() - self.assert_called('GET', '/servers/detail') - [self.assertIsInstance(s, servers.Server) for s in sl] - - def test_list_servers_undetailed(self): - sl = self.cs.servers.list(detailed=False) - self.assert_called('GET', '/servers') - [self.assertIsInstance(s, servers.Server) for s in sl] - - def test_list_servers_with_marker_limit(self): - sl = self.cs.servers.list(marker=1234, limit=2) - self.assert_called('GET', '/servers/detail?limit=2&marker=1234') - for s in sl: - self.assertIsInstance(s, servers.Server) - - def test_get_server_details(self): - s = self.cs.servers.get(1234) - self.assert_called('GET', '/servers/1234') - self.assertIsInstance(s, servers.Server) - self.assertEqual(1234, s.id) - self.assertEqual('BUILD', s.status) - - def test_get_server_promote_details(self): - s1 = self.cs.servers.list(detailed=False)[0] - s2 = self.cs.servers.list(detailed=True)[0] - self.assertNotEqual(s1._info, s2._info) - s1.get() - self.assertEqual(s1._info, s2._info) - - def test_create_server(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - } - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_boot_from_volume_with_nics(self): - old_boot = self.cs.servers._boot - - nics = [{'net-id': '11111111-1111-1111-1111-111111111111', - 'v4-fixed-ip': '10.0.0.7'}] - bdm = {"volume_size": "1", - "volume_id": "11111111-1111-1111-1111-111111111111", - "delete_on_termination": "0", - "device_name": "vda"} - - def wrapped_boot(url, key, *boot_args, **boot_kwargs): - self.assertEqual(boot_kwargs['block_device_mapping'], bdm) - self.assertEqual(boot_kwargs['nics'], nics) - return old_boot(url, key, *boot_args, **boot_kwargs) - - @mock.patch.object(self.cs.servers, '_boot', wrapped_boot) - def test_create_server_from_volume(): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - block_device_mapping=bdm, - nics=nics - ) - self.assert_called('POST', '/os-volumes_boot') - self.assertIsInstance(s, servers.Server) - - test_create_server_from_volume() - - def test_create_server_boot_with_nics_ipv6(self): - old_boot = self.cs.servers._boot - nics = [{'net-id': '11111111-1111-1111-1111-111111111111', - 'v6-fixed-ip': '2001:db9:0:1::10'}] - - def wrapped_boot(url, key, *boot_args, **boot_kwargs): - self.assertEqual(boot_kwargs['nics'], nics) - return old_boot(url, key, *boot_args, **boot_kwargs) - - with mock.patch.object(self.cs.servers, '_boot', wrapped_boot): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - nics=nics - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_file_object(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata=six.StringIO('hello moto'), - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_unicode(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata=six.u('ã“ã‚“ã«ã¡ã¯'), - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_utf8(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata='ã“ã‚“ã«ã¡ã¯', - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def _create_disk_config(self, disk_config): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - disk_config=disk_config - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - # verify disk config param was used in the request: - body = jsonutils.loads(self.requests.last_request.body) - server = body['server'] - self.assertTrue('OS-DCF:diskConfig' in server) - self.assertEqual(disk_config, server['OS-DCF:diskConfig']) - - def test_create_server_disk_config_auto(self): - self._create_disk_config('AUTO') - - def test_create_server_disk_config_manual(self): - self._create_disk_config('MANUAL') - - def test_update_server(self): - s = self.cs.servers.get(1234) - - # Update via instance - s.update(name='hi') - self.assert_called('PUT', '/servers/1234') - s.update(name='hi') - self.assert_called('PUT', '/servers/1234') - - # Silly, but not an error - s.update() - - # Update via manager - self.cs.servers.update(s, name='hi') - self.assert_called('PUT', '/servers/1234') - - def test_delete_server(self): - s = self.cs.servers.get(1234) - s.delete() - self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(1234) - self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(s) - self.assert_called('DELETE', '/servers/1234') - - def test_delete_server_meta(self): - self.cs.servers.delete_meta(1234, ['test_key']) - self.assert_called('DELETE', '/servers/1234/metadata/test_key') - - def test_set_server_meta(self): - self.cs.servers.set_meta(1234, {'test_key': 'test_value'}) - self.assert_called('POST', '/servers/1234/metadata', - {'metadata': {'test_key': 'test_value'}}) - - def test_set_server_meta_item(self): - self.cs.servers.set_meta_item(1234, 'test_key', 'test_value') - self.assert_called('PUT', '/servers/1234/metadata/test_key', - {'meta': {'test_key': 'test_value'}}) - - def test_find(self): - server = self.cs.servers.find(name='sample-server') - self.assert_called('GET', '/servers/1234') - self.assertEqual('sample-server', server.name) - - self.assertRaises(exceptions.NoUniqueMatch, self.cs.servers.find, - flavor={"id": 1, "name": "256 MB Server"}) - - sl = self.cs.servers.findall(flavor={"id": 1, "name": "256 MB Server"}) - self.assertEqual([1234, 5678, 9012], [s.id for s in sl]) - - def test_reboot_server(self): - s = self.cs.servers.get(1234) - s.reboot() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reboot(s, reboot_type='HARD') - self.assert_called('POST', '/servers/1234/action') - - def test_rebuild_server(self): - s = self.cs.servers.get(1234) - s.rebuild(image=1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1) - self.assert_called('POST', '/servers/1234/action') - s.rebuild(image=1, password='5678') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1, password='5678') - self.assert_called('POST', '/servers/1234/action') - - def _rebuild_resize_disk_config(self, disk_config, operation="rebuild"): - s = self.cs.servers.get(1234) - - if operation == "rebuild": - s.rebuild(image=1, disk_config=disk_config) - elif operation == "resize": - s.resize(flavor=1, disk_config=disk_config) - self.assert_called('POST', '/servers/1234/action') - - # verify disk config param was used in the request: - body = jsonutils.loads(self.requests.last_request.body) - - d = body[operation] - self.assertTrue('OS-DCF:diskConfig' in d) - self.assertEqual(disk_config, d['OS-DCF:diskConfig']) - - def test_rebuild_server_disk_config_auto(self): - self._rebuild_resize_disk_config('AUTO') - - def test_rebuild_server_disk_config_manual(self): - self._rebuild_resize_disk_config('MANUAL') - - def test_rebuild_server_preserve_ephemeral(self): - s = self.cs.servers.get(1234) - s.rebuild(image=1, preserve_ephemeral=True) - self.assert_called('POST', '/servers/1234/action') - body = jsonutils.loads(self.requests.last_request.body) - d = body['rebuild'] - self.assertIn('preserve_ephemeral', d) - self.assertEqual(True, d['preserve_ephemeral']) - - def test_rebuild_server_name_meta_files(self): - files = {'/etc/passwd': 'some data'} - s = self.cs.servers.get(1234) - s.rebuild(image=1, name='new', meta={'foo': 'bar'}, files=files) - body = jsonutils.loads(self.requests.last_request.body) - d = body['rebuild'] - self.assertEqual('new', d['name']) - self.assertEqual({'foo': 'bar'}, d['metadata']) - self.assertEqual('/etc/passwd', - d['personality'][0]['path']) - - def test_resize_server(self): - s = self.cs.servers.get(1234) - s.resize(flavor=1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.resize(s, flavor=1) - self.assert_called('POST', '/servers/1234/action') - - def test_resize_server_disk_config_auto(self): - self._rebuild_resize_disk_config('AUTO', 'resize') - - def test_resize_server_disk_config_manual(self): - self._rebuild_resize_disk_config('MANUAL', 'resize') - - def test_confirm_resized_server(self): - s = self.cs.servers.get(1234) - s.confirm_resize() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.confirm_resize(s) - self.assert_called('POST', '/servers/1234/action') - - def test_revert_resized_server(self): - s = self.cs.servers.get(1234) - s.revert_resize() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.revert_resize(s) - self.assert_called('POST', '/servers/1234/action') - - def test_migrate_server(self): - s = self.cs.servers.get(1234) - s.migrate() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.migrate(s) - self.assert_called('POST', '/servers/1234/action') - - def test_add_fixed_ip(self): - s = self.cs.servers.get(1234) - s.add_fixed_ip(1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_fixed_ip(s, 1) - self.assert_called('POST', '/servers/1234/action') - - def test_remove_fixed_ip(self): - s = self.cs.servers.get(1234) - s.remove_fixed_ip('10.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_fixed_ip(s, '10.0.0.1') - self.assert_called('POST', '/servers/1234/action') - - def test_add_floating_ip(self): - s = self.cs.servers.get(1234) - s.add_floating_ip('11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_floating_ip(s, '11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - f = self.cs.floating_ips.list()[0] - self.cs.servers.add_floating_ip(s, f) - self.assert_called('POST', '/servers/1234/action') - s.add_floating_ip(f) - self.assert_called('POST', '/servers/1234/action') - - def test_add_floating_ip_to_fixed(self): - s = self.cs.servers.get(1234) - s.add_floating_ip('11.0.0.1', fixed_address='12.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_floating_ip(s, '11.0.0.1', - fixed_address='12.0.0.1') - self.assert_called('POST', '/servers/1234/action') - f = self.cs.floating_ips.list()[0] - self.cs.servers.add_floating_ip(s, f) - self.assert_called('POST', '/servers/1234/action') - s.add_floating_ip(f) - self.assert_called('POST', '/servers/1234/action') - - def test_remove_floating_ip(self): - s = self.cs.servers.get(1234) - s.remove_floating_ip('11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_floating_ip(s, '11.0.0.1') - self.assert_called('POST', '/servers/1234/action') - f = self.cs.floating_ips.list()[0] - self.cs.servers.remove_floating_ip(s, f) - self.assert_called('POST', '/servers/1234/action') - s.remove_floating_ip(f) - self.assert_called('POST', '/servers/1234/action') - - def test_stop(self): - s = self.cs.servers.get(1234) - s.stop() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.stop(s) - self.assert_called('POST', '/servers/1234/action') - - def test_force_delete(self): - s = self.cs.servers.get(1234) - s.force_delete() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.force_delete(s) - self.assert_called('POST', '/servers/1234/action') - - def test_restore(self): - s = self.cs.servers.get(1234) - s.restore() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.restore(s) - self.assert_called('POST', '/servers/1234/action') - - def test_start(self): - s = self.cs.servers.get(1234) - s.start() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.start(s) - self.assert_called('POST', '/servers/1234/action') - - def test_rescue(self): - s = self.cs.servers.get(1234) - s.rescue() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rescue(s) - self.assert_called('POST', '/servers/1234/action') - - def test_unrescue(self): - s = self.cs.servers.get(1234) - s.unrescue() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unrescue(s) - self.assert_called('POST', '/servers/1234/action') - - def test_lock(self): - s = self.cs.servers.get(1234) - s.lock() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.lock(s) - self.assert_called('POST', '/servers/1234/action') - - def test_unlock(self): - s = self.cs.servers.get(1234) - s.unlock() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unlock(s) - self.assert_called('POST', '/servers/1234/action') - - def test_backup(self): - s = self.cs.servers.get(1234) - s.backup('back1', 'daily', 1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.backup(s, 'back1', 'daily', 2) - self.assert_called('POST', '/servers/1234/action') - - def test_get_console_output_without_length(self): - success = 'foo' - s = self.cs.servers.get(1234) - s.get_console_output() - self.assertEqual(success, s.get_console_output()) - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_console_output(s) - self.assertEqual(success, self.cs.servers.get_console_output(s)) - self.assert_called('POST', '/servers/1234/action') - - def test_get_console_output_with_length(self): - success = 'foo' - - s = self.cs.servers.get(1234) - s.get_console_output(length=50) - self.assertEqual(success, s.get_console_output(length=50)) - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_console_output(s, length=50) - self.assertEqual(success, - self.cs.servers.get_console_output(s, length=50)) - self.assert_called('POST', '/servers/1234/action') - - # Testing password methods with the following password and key - # - # Clear password: FooBar123 - # - # RSA Private Key: novaclient/tests/idfake.pem - # - # Encrypted password - # OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r - # qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho - # QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw - # /y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N - # tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk - # Hi/fmZZNQQqj1Ijq0caOIw== - - def test_get_password(self): - s = self.cs.servers.get(1234) - self.assertEqual(b'FooBar123', - s.get_password('novaclient/tests/idfake.pem')) - self.assert_called('GET', '/servers/1234/os-server-password') - - def test_get_password_without_key(self): - s = self.cs.servers.get(1234) - self.assertEqual( - 'OIuEuQttO8Rk93BcKlwHQsziDAnkAm/V6V8VPToA8ZeUaUBWwS0gwo2K6Y61Z96r' - 'qG447iRz0uTEEYq3RAYJk1mh3mMIRVl27t8MtIecR5ggVVbz1S9AwXJQypDKl0ho' - 'QFvhCBcMWPohyGewDJOhDbtuN1IoFI9G55ZvFwCm5y7m7B2aVcoLeIsJZE4PLsIw' - '/y5a6Z3/AoJZYGG7IH5WN88UROU3B9JZGFB2qtPLQTOvDMZLUhoPRIJeHiVSlo1N' - 'tI2/++UsXVg3ow6ItqCJGgdNuGG5JB+bslDHWPxROpesEIHdczk46HCpHQN8f1sk' - 'Hi/fmZZNQQqj1Ijq0caOIw==', s.get_password()) - self.assert_called('GET', '/servers/1234/os-server-password') - - def test_clear_password(self): - s = self.cs.servers.get(1234) - s.clear_password() - self.assert_called('DELETE', '/servers/1234/os-server-password') - - def test_get_server_diagnostics(self): - s = self.cs.servers.get(1234) - diagnostics = s.diagnostics() - self.assertTrue(diagnostics is not None) - self.assert_called('GET', '/servers/1234/diagnostics') - - diagnostics_from_manager = self.cs.servers.diagnostics(1234) - self.assertTrue(diagnostics_from_manager is not None) - self.assert_called('GET', '/servers/1234/diagnostics') - - self.assertEqual(diagnostics[1], diagnostics_from_manager[1]) - - def test_get_vnc_console(self): - s = self.cs.servers.get(1234) - s.get_vnc_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_vnc_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_get_spice_console(self): - s = self.cs.servers.get(1234) - s.get_spice_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_spice_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_get_serial_console(self): - s = self.cs.servers.get(1234) - s.get_serial_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_serial_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_get_rdp_console(self): - s = self.cs.servers.get(1234) - s.get_rdp_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_rdp_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_create_image(self): - s = self.cs.servers.get(1234) - s.create_image('123') - self.assert_called('POST', '/servers/1234/action') - s.create_image('123', {}) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123', {}) - - def test_live_migrate_server(self): - s = self.cs.servers.get(1234) - s.live_migrate(host='hostname', block_migration=False, - disk_over_commit=False) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.live_migrate(s, host='hostname', block_migration=False, - disk_over_commit=False) - self.assert_called('POST', '/servers/1234/action') - - def test_reset_state(self): - s = self.cs.servers.get(1234) - s.reset_state('newstate') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_state(s, 'newstate') - self.assert_called('POST', '/servers/1234/action') - - def test_reset_network(self): - s = self.cs.servers.get(1234) - s.reset_network() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_network(s) - self.assert_called('POST', '/servers/1234/action') - - def test_add_security_group(self): - s = self.cs.servers.get(1234) - s.add_security_group('newsg') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_security_group(s, 'newsg') - self.assert_called('POST', '/servers/1234/action') - - def test_remove_security_group(self): - s = self.cs.servers.get(1234) - s.remove_security_group('oldsg') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_security_group(s, 'oldsg') - self.assert_called('POST', '/servers/1234/action') - - def test_list_security_group(self): - s = self.cs.servers.get(1234) - s.list_security_group() - self.assert_called('GET', '/servers/1234/os-security-groups') - - def test_evacuate(self): - s = self.cs.servers.get(1234) - s.evacuate('fake_target_host', 'True') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.evacuate(s, 'fake_target_host', - 'False', 'NewAdminPassword') - self.assert_called('POST', '/servers/1234/action') - - def test_interface_list(self): - s = self.cs.servers.get(1234) - s.interface_list() - self.assert_called('GET', '/servers/1234/os-interface') - - def test_interface_list_result_string_representable(self): - """Test for bugs.launchpad.net/python-novaclient/+bug/1280453.""" - # According to https://github.com/openstack/nova/blob/master/ - # nova/api/openstack/compute/contrib/attach_interfaces.py#L33, - # the attach_interface extension get method will return a json - # object partly like this: - interface_list = [{ - 'net_id': 'd7745cf5-63f9-4883-b0ae-983f061e4f23', - 'port_id': 'f35079da-36d5-4513-8ec1-0298d703f70e', - 'mac_addr': 'fa:16:3e:4c:37:c8', - 'port_state': 'ACTIVE', - 'fixed_ips': [{ - 'subnet_id': 'f1ad93ad-2967-46ba-b403-e8cbbe65f7fa', - 'ip_address': '10.2.0.96' - }] - }] - # If server is not string representable, it will raise an exception, - # because attribute named 'name' cannot be found. - # Parameter 'loaded' must be True or it will try to get attribute - # 'id' then fails (lazy load detail), this is exactly same as - # novaclient.base.Manager._list() - s = servers.Server(servers.ServerManager, interface_list[0], - loaded=True) - # Trigger the __repr__ magic method - self.assertEqual('', '%r' % s) - - def test_interface_attach(self): - s = self.cs.servers.get(1234) - s.interface_attach(None, None, None) - self.assert_called('POST', '/servers/1234/os-interface') - - def test_interface_detach(self): - s = self.cs.servers.get(1234) - s.interface_detach('port-id') - self.assert_called('DELETE', '/servers/1234/os-interface/port-id') diff --git a/awx/lib/site-packages/novaclient/tests/v1_1/test_services.py b/awx/lib/site-packages/novaclient/tests/v1_1/test_services.py deleted file mode 100644 index acd25152fa..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v1_1/test_services.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests import utils -from novaclient.tests.v1_1 import fakes -from novaclient.v1_1 import services - - -class ServicesTest(utils.TestCase): - def setUp(self): - super(ServicesTest, self).setUp() - self.cs = self._get_fake_client() - self.service_type = self._get_service_type() - - def _get_fake_client(self): - return fakes.FakeClient() - - def _get_service_type(self): - return services.Service - - def test_list_services(self): - svs = self.cs.services.list() - self.cs.assert_called('GET', '/os-services') - for s in svs: - self.assertIsInstance(s, self._get_service_type()) - self.assertEqual('nova-compute', s.binary) - self.assertEqual('host1', s.host) - self.assertTrue(str(s).startswith('= set(body_params_check_superset[action]) - - if action == 'reboot': - assert body[action]['type'] in ['HARD', 'SOFT'] - elif action == 'confirm_resize': - # This one method returns a different response code - resp = 204 - elif action == 'create_image': - _headers = dict(location="http://blah/images/456") - - if action not in set.union(set(body_is_none_list), - set(body_params_check_exact.keys()), - set(body_param_check_exists.keys()), - set(body_params_check_superset.keys())): - raise AssertionError("Unexpected server action: %s" % action) - - return (resp, _headers, _body) - - # - # Server password - # - - def get_servers_1234_os_server_password(self, **kw): - return (200, {}, {'password': ''}) - - def delete_servers_1234_os_server_password(self, **kw): - return (202, {}, None) - - # - # Availability Zones - # - def get_os_availability_zone(self, **kw): - return (200, {}, {"availability_zone_info": [ - {"zone_name": "zone-1", - "zone_state": {"available": True}, - "hosts": None}, - {"zone_name": "zone-2", - "zone_state": {"available": False}, - "hosts": None}]}) - - def get_os_availability_zone_detail(self, **kw): - return (200, {}, {"availability_zone_info": [ - {"zone_name": "zone-1", - "zone_state": {"available": True}, - "hosts": { - "fake_host-1": { - "nova-compute": {"active": True, - "available": True, - "updated_at": - datetime.datetime( - 2012, 12, 26, 14, 45, 25, 0 - )}}}}, - {"zone_name": "internal", - "zone_state": {"available": True}, - "hosts": { - "fake_host-1": { - "nova-sched": { - "active": True, - "available": True, - "updated_at": - datetime.datetime( - 2012, 12, 26, 14, 45, 25, 0 - )}}, - "fake_host-2": { - "nova-network": { - "active": True, - "available": False, - "updated_at": - datetime.datetime( - 2012, 12, 26, 14, 45, 24, 0 - )}}}}, - {"zone_name": "zone-2", - "zone_state": {"available": False}, - "hosts": None}]}) - - # - # Quotas - # - def put_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, body, **kw): - assert list(body) == ['quota_set'] - return (200, {}, {'quota_set': { - 'tenant_id': '97f4c221bff44578b0300df4ef119353', - 'metadata_items': [], - 'injected_file_content_bytes': 1, - 'injected_file_path_bytes': 1, - 'ram': 1, - 'floating_ips': 1, - 'instances': 1, - 'injected_files': 1, - 'cores': 1, - 'keypairs': 1, - 'security_groups': 1, - 'security_group_rules': 1, - 'server_groups': 1, - 'server_group_members': 1}}) - - def get_os_quota_sets_test_detail(self, **kw): - return (200, {}, {'quota_set': { - 'cores': {'reserved': 0, 'in_use': 0, 'limit': 10}, - 'instances': {'reserved': 0, 'in_use': 4, 'limit': 50}, - 'ram': {'reserved': 0, 'in_use': 1024, 'limit': 51200}}}) - - # - # Hypervisors - # - def get_os_hypervisors_search(self, **kw): - return (200, {}, {'hypervisors': [ - {'id': 1234, 'hypervisor_hostname': 'hyper1'}, - {'id': 5678, 'hypervisor_hostname': 'hyper2'} - ]}) - - def get_os_hypervisors_1234_servers(self, **kw): - return (200, {}, {'hypervisor': - {'id': 1234, - 'hypervisor_hostname': 'hyper1', - 'servers': [ - {'name': 'inst1', 'id': 'uuid1'}, - {'name': 'inst2', 'id': 'uuid2'} - ]}, - }) - - # - # Keypairs - # - get_keypairs_test = fakes_v1_1.FakeHTTPClient.get_os_keypairs_test - get_keypairs = fakes_v1_1.FakeHTTPClient.get_os_keypairs - delete_keypairs_test = fakes_v1_1.FakeHTTPClient.delete_os_keypairs_test - post_keypairs = fakes_v1_1.FakeHTTPClient.post_os_keypairs - - # - # List all extensions - # - def get_extensions(self, **kw): - exts = [ - { - "alias": "os-multinic", - "description": "Multiple network support", - "name": "Multinic", - "version": 1, - }, - { - "alias": "os-extended-server-attributes", - "description": "Extended Server Attributes support.", - "name": "ExtendedServerAttributes", - "version": 1, - }, - { - "alias": "os-extended-status", - "description": "Extended Status support", - "name": "ExtendedStatus", - "version": 1, - }, - ] - return (200, {}, { - "extensions": exts, - }) diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_agents.py b/awx/lib/site-packages/novaclient/tests/v3/test_agents.py deleted file mode 100644 index bdd101bdc8..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_agents.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.v1_1 import test_agents - - -class AgentsTest(test_agents.AgentsTest): - - scenarios = [('original', {'client_fixture_class': client.V3}), - ('session', {'client_fixture_class': client.SessionV3})] - - def _build_example_update_body(self): - return {"agent": { - "url": "/yyy/yyyy/yyyy", - "version": "8.0", - "md5hash": "add6bb58e139be103324d04d82d8f546"}} diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_aggregates.py b/awx/lib/site-packages/novaclient/tests/v3/test_aggregates.py deleted file mode 100644 index 17e27d1621..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_aggregates.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.v1_1 import test_aggregates - - -class AggregatesTest(test_aggregates.AggregatesTest): - - scenarios = [('original', {'client_fixture_class': client.V3}), - ('session', {'client_fixture_class': client.SessionV3})] diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_availability_zone.py b/awx/lib/site-packages/novaclient/tests/v3/test_availability_zone.py deleted file mode 100644 index 67a4415bf7..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_availability_zone.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import availability_zones as data -from novaclient.tests.fixture_data import client -from novaclient.tests.v1_1 import test_availability_zone -from novaclient.v3 import availability_zones - - -class AvailabilityZoneTest(test_availability_zone.AvailabilityZoneTest): - from novaclient.v3 import shell # noqa - - data_fixture_class = data.V3 - - scenarios = [('original', {'client_fixture_class': client.V3}), - ('session', {'client_fixture_class': client.SessionV3})] - - def _assertZone(self, zone, name, status): - self.assertEqual(zone.zone_name, name) - self.assertEqual(zone.zone_state, status) - - def _get_availability_zone_type(self): - return availability_zones.AvailabilityZone diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_certs.py b/awx/lib/site-packages/novaclient/tests/v3/test_certs.py deleted file mode 100644 index 30597fc10b..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_certs.py +++ /dev/null @@ -1,21 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.v1_1 import test_certs - - -class CertsTest(test_certs.CertsTest): - - scenarios = [('original', {'client_fixture_class': client.V3}), - ('session', {'client_fixture_class': client.SessionV3})] diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_flavor_access.py b/awx/lib/site-packages/novaclient/tests/v3/test_flavor_access.py deleted file mode 100644 index cd5914012b..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_flavor_access.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests import utils -from novaclient.tests.v3 import fakes -from novaclient.v3 import flavor_access - - -cs = fakes.FakeClient() - - -class FlavorAccessTest(utils.TestCase): - - def test_list_access_by_flavor_private(self): - kwargs = {'flavor': cs.flavors.get(2)} - r = cs.flavor_access.list(**kwargs) - cs.assert_called('GET', '/flavors/2/flavor-access') - for access_list in r: - self.assertIsInstance(access_list, - flavor_access.FlavorAccess) - - def test_add_tenant_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj2' - r = cs.flavor_access.add_tenant_access(flavor, tenant) - - body = { - "add_tenant_access": { - "tenant_id": "proj2" - } - } - - cs.assert_called('POST', '/flavors/2/action', body) - for a in r: - self.assertIsInstance(a, flavor_access.FlavorAccess) - - def test_remove_tenant_access(self): - flavor = cs.flavors.get(2) - tenant = 'proj2' - r = cs.flavor_access.remove_tenant_access(flavor, tenant) - - body = { - "remove_tenant_access": { - "tenant_id": "proj2" - } - } - - cs.assert_called('POST', '/flavors/2/action', body) - for a in r: - self.assertIsInstance(a, flavor_access.FlavorAccess) diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_flavors.py b/awx/lib/site-packages/novaclient/tests/v3/test_flavors.py deleted file mode 100644 index 4dadc0ab54..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_flavors.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 2013, OpenStack -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from novaclient.tests.v1_1 import test_flavors -from novaclient.tests.v3 import fakes -from novaclient.v3 import flavors - - -class FlavorsTest(test_flavors.FlavorsTest): - def _get_fake_client(self): - return fakes.FakeClient() - - def _get_flavor_type(self): - return flavors.Flavor - - def _create_body(self, name, ram, vcpus, disk, ephemeral, id, swap, - rxtx_factor, is_public): - return { - "flavor": { - "name": name, - "ram": ram, - "vcpus": vcpus, - "disk": disk, - "ephemeral": ephemeral, - "id": id, - "swap": swap, - "os-flavor-rxtx:rxtx_factor": rxtx_factor, - "flavor-access:is_public": is_public, - } - } - - def test_set_keys(self): - f = self.cs.flavors.get(1) - f.set_keys({'k1': 'v1'}) - self.cs.assert_called('POST', '/flavors/1/flavor-extra-specs', - {"extra_specs": {'k1': 'v1'}}) - - def test_set_with_valid_keys(self): - valid_keys = ['key4', 'month.price', 'I-Am:AK-ey.44-', - 'key with spaces and _'] - - f = self.cs.flavors.get(4) - for key in valid_keys: - f.set_keys({key: 'v4'}) - self.cs.assert_called('POST', '/flavors/4/flavor-extra-specs', - {"extra_specs": {key: 'v4'}}) - - @mock.patch.object(flavors.FlavorManager, '_delete') - def test_unset_keys(self, mock_delete): - f = self.cs.flavors.get(1) - keys = ['k1', 'k2'] - f.unset_keys(keys) - mock_delete.assert_has_calls([ - mock.call("/flavors/1/flavor-extra-specs/k1"), - mock.call("/flavors/1/flavor-extra-specs/k2") - ]) - - def test_get_flavor_details_diablo(self): - # Don't need for V3 API to work against diablo - pass diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_hosts.py b/awx/lib/site-packages/novaclient/tests/v3/test_hosts.py deleted file mode 100644 index 56579330ac..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_hosts.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import hosts as data -from novaclient.tests import utils -from novaclient.v3 import hosts - - -class HostsTest(utils.FixturedTestCase): - - client_fixture_class = client.V3 - data_fixture_class = data.V3 - - def test_describe_resource(self): - hs = self.cs.hosts.get('host') - self.assert_called('GET', '/os-hosts/host') - for h in hs: - self.assertIsInstance(h, hosts.Host) - - def test_list_host(self): - hs = self.cs.hosts.list() - self.assert_called('GET', '/os-hosts') - for h in hs: - self.assertIsInstance(h, hosts.Host) - self.assertEqual('nova1', h.zone) - - def test_list_host_with_zone(self): - hs = self.cs.hosts.list('nova') - self.assert_called('GET', '/os-hosts?zone=nova') - for h in hs: - self.assertIsInstance(h, hosts.Host) - self.assertEqual('nova', h.zone) - - def test_list_host_with_service(self): - hs = self.cs.hosts.list(service='nova-compute') - self.assert_called('GET', '/os-hosts?service=nova-compute') - for h in hs: - self.assertIsInstance(h, hosts.Host) - self.assertEqual(h.service, 'nova-compute') - - def test_list_host_with_zone_and_service(self): - hs = self.cs.hosts.list(service='nova-compute', zone='nova') - self.assert_called('GET', '/os-hosts?zone=nova&service=nova-compute') - for h in hs: - self.assertIsInstance(h, hosts.Host) - self.assertEqual(h.zone, 'nova') - self.assertEqual(h.service, 'nova-compute') - - def test_update_enable(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"status": "enabled"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', {"host": values}) - self.assertIsInstance(result, hosts.Host) - - def test_update_maintenance(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"maintenance_mode": "enable"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', {"host": values}) - self.assertIsInstance(result, hosts.Host) - - def test_update_both(self): - host = self.cs.hosts.get('sample_host')[0] - values = {"status": "enabled", - "maintenance_mode": "enable"} - result = host.update(values) - self.assert_called('PUT', '/os-hosts/sample_host', {"host": values}) - self.assertIsInstance(result, hosts.Host) - - def test_host_startup(self): - host = self.cs.hosts.get('sample_host')[0] - host.startup() - self.assert_called( - 'GET', '/os-hosts/sample_host/startup') - - def test_host_reboot(self): - host = self.cs.hosts.get('sample_host')[0] - host.reboot() - self.assert_called( - 'GET', '/os-hosts/sample_host/reboot') - - def test_host_shutdown(self): - host = self.cs.hosts.get('sample_host')[0] - host.shutdown() - self.assert_called( - 'GET', '/os-hosts/sample_host/shutdown') diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_hypervisors.py b/awx/lib/site-packages/novaclient/tests/v3/test_hypervisors.py deleted file mode 100644 index ee7c83fcba..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_hypervisors.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import hypervisors as data -from novaclient.tests.v1_1 import test_hypervisors - - -class HypervisorsTest(test_hypervisors.HypervisorsTest): - - client_fixture_class = client.V3 - data_fixture_class = data.V3 - - def test_hypervisor_search(self): - expected = [ - dict(id=1234, hypervisor_hostname='hyper1'), - dict(id=5678, hypervisor_hostname='hyper2'), - ] - - result = self.cs.hypervisors.search('hyper') - self.assert_called('GET', '/os-hypervisors/search?query=hyper') - - for idx, hyper in enumerate(result): - self.compare_to_expected(expected[idx], hyper) - - def test_hypervisor_servers(self): - expected = dict(id=1234, - hypervisor_hostname='hyper1', - servers=[ - dict(name='inst1', id='uuid1'), - dict(name='inst2', id='uuid2')]) - - result = self.cs.hypervisors.servers('1234') - self.assert_called('GET', '/os-hypervisors/1234/servers') - - self.compare_to_expected(expected, result) diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_images.py b/awx/lib/site-packages/novaclient/tests/v3/test_images.py deleted file mode 100644 index be8260d8fe..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_images.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import images as data -from novaclient.tests import utils -from novaclient.v3 import images - - -class ImagesTest(utils.FixturedTestCase): - - client_fixture_class = client.V3 - data_fixture_class = data.V3 - - def test_list_images(self): - il = self.cs.images.list() - self.assert_called('GET', '/v1/images/detail') - for i in il: - self.assertIsInstance(i, images.Image) - - def test_list_images_undetailed(self): - il = self.cs.images.list(detailed=False) - self.assert_called('GET', '/v1/images') - for i in il: - self.assertIsInstance(i, images.Image) - - def test_list_images_with_limit(self): - self.cs.images.list(limit=4) - self.assert_called('GET', '/v1/images/detail?limit=4') - - def test_get_image_details(self): - i = self.cs.images.get(1) - self.assert_called('HEAD', '/v1/images/1') - self.assertIsInstance(i, images.Image) - self.assertEqual('1', i.id) - self.assertEqual('CentOS 5.2', i.name) - - def test_find(self): - i = self.cs.images.find(name="CentOS 5.2") - self.assertEqual('1', i.id) - self.assert_called('HEAD', '/v1/images/1') - - iml = self.cs.images.findall(status='SAVING') - self.assertEqual(1, len(iml)) - self.assertEqual('My Server Backup', iml[0].name) diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_keypairs.py b/awx/lib/site-packages/novaclient/tests/v3/test_keypairs.py deleted file mode 100644 index 157042fce0..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_keypairs.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import keypairs as data -from novaclient.tests.v1_1 import test_keypairs -from novaclient.v3 import keypairs - - -class KeypairsTest(test_keypairs.KeypairsTest): - - client_fixture_class = client.V3 - data_fixture_class = data.V3 - - def _get_keypair_type(self): - return keypairs.Keypair - - def _get_keypair_prefix(self): - return keypairs.KeypairManager.keypair_prefix diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_list_extensions.py b/awx/lib/site-packages/novaclient/tests/v3/test_list_extensions.py deleted file mode 100644 index 61d387c3ce..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_list_extensions.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2014 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import extension -from novaclient.tests import utils -from novaclient.tests.v3 import fakes -from novaclient.v3 import list_extensions - - -extensions = [ - extension.Extension("list_extensions", list_extensions), -] -cs = fakes.FakeClient(extensions=extensions) - - -class ListExtensionsTests(utils.TestCase): - def test_list_extensions(self): - all_exts = cs.list_extensions.show_all() - cs.assert_called('GET', '/extensions') - self.assertTrue(len(all_exts) > 0) - for r in all_exts: - self.assertTrue(len(r.summary) > 0) diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_quota_classes.py b/awx/lib/site-packages/novaclient/tests/v3/test_quota_classes.py deleted file mode 100644 index 2e0ceb9f02..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_quota_classes.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright IBM Corp. 2013 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.v1_1 import test_quota_classes -from novaclient.tests.v3 import fakes - - -class QuotaClassSetsTest(test_quota_classes.QuotaClassSetsTest): - def setUp(self): - super(QuotaClassSetsTest, self).setUp() - self.cs = self._get_fake_client() - - def _get_fake_client(self): - return fakes.FakeClient() diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_quotas.py b/awx/lib/site-packages/novaclient/tests/v3/test_quotas.py deleted file mode 100644 index 53ca3258eb..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_quotas.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright IBM Corp. 2013 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import quotas as data -from novaclient.tests.v1_1 import test_quotas - - -class QuotaSetsTest(test_quotas.QuotaSetsTest): - - client_fixture_class = client.V3 - data_fixture_class = data.V3 - - def test_force_update_quota(self): - q = self.cs.quotas.get('97f4c221bff44578b0300df4ef119353') - q.update(cores=2, force=True) - self.assert_called( - 'PUT', '/os-quota-sets/97f4c221bff44578b0300df4ef119353', - {'quota_set': {'force': True, - 'cores': 2}}) - - def test_tenant_quotas_get_detail(self): - tenant_id = 'test' - self.cs.quotas.get(tenant_id, detail=True) - self.assert_called('GET', '/os-quota-sets/%s/detail' % tenant_id) - - def test_user_quotas_get_detail(self): - tenant_id = 'test' - user_id = 'fake_user' - self.cs.quotas.get(tenant_id, user_id=user_id, detail=True) - url = '/os-quota-sets/%s/detail?user_id=%s' % (tenant_id, user_id) - self.assert_called('GET', url) diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_servers.py b/awx/lib/site-packages/novaclient/tests/v3/test_servers.py deleted file mode 100644 index c9357b5656..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_servers.py +++ /dev/null @@ -1,478 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -import six - -from novaclient import exceptions -from novaclient.tests.fixture_data import client -from novaclient.tests.fixture_data import servers as data -from novaclient.tests import utils -from novaclient.v3 import servers - - -class ServersTest(utils.FixturedTestCase): - - client_fixture_class = client.V3 - data_fixture_class = data.V3 - - def test_list_servers(self): - sl = self.cs.servers.list() - self.assert_called('GET', '/servers/detail') - for s in sl: - self.assertIsInstance(s, servers.Server) - - def test_list_servers_undetailed(self): - sl = self.cs.servers.list(detailed=False) - self.assert_called('GET', '/servers') - for s in sl: - self.assertIsInstance(s, servers.Server) - - def test_list_servers_with_marker_limit(self): - sl = self.cs.servers.list(marker=1234, limit=2) - self.assert_called('GET', '/servers/detail?limit=2&marker=1234') - for s in sl: - self.assertIsInstance(s, servers.Server) - - def test_get_server_details(self): - s = self.cs.servers.get(1234) - self.assert_called('GET', '/servers/1234') - self.assertIsInstance(s, servers.Server) - self.assertEqual(1234, s.id) - self.assertEqual('BUILD', s.status) - - def test_get_server_promote_details(self): - s1 = self.cs.servers.list(detailed=False)[0] - s2 = self.cs.servers.list(detailed=True)[0] - self.assertNotEqual(s1._info, s2._info) - s1.get() - self.assertEqual(s1._info, s2._info) - - def test_create_server(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - } - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_boot_with_nics_ipv4(self): - old_boot = self.cs.servers._boot - nics = [{'net-id': '11111111-1111-1111-1111-111111111111', - 'v4-fixed-ip': '10.10.0.7'}] - - def wrapped_boot(url, key, *boot_args, **boot_kwargs): - self.assertEqual(boot_kwargs['nics'], nics) - return old_boot(url, key, *boot_args, **boot_kwargs) - - with mock.patch.object(self.cs.servers, '_boot', wrapped_boot): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - nics=nics - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_boot_with_nics_ipv6(self): - old_boot = self.cs.servers._boot - nics = [{'net-id': '11111111-1111-1111-1111-111111111111', - 'v6-fixed-ip': '2001:db9:0:1::10'}] - - def wrapped_boot(url, key, *boot_args, **boot_kwargs): - self.assertEqual(nics, boot_kwargs['nics']) - return old_boot(url, key, *boot_args, **boot_kwargs) - - with mock.patch.object(self.cs.servers, '_boot', wrapped_boot): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata="hello moto", - key_name="fakekey", - nics=nics - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_file_object(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata=six.StringIO('hello moto'), - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_unicode(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata=six.u('ã“ã‚“ã«ã¡ã¯'), - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_userdata_utf8(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - meta={'foo': 'bar'}, - userdata='ã“ã‚“ã«ã¡ã¯', - key_name="fakekey", - files={ - '/etc/passwd': 'some data', # a file - '/tmp/foo.txt': six.StringIO('data'), # a stream - }, - ) - self.assert_called('POST', '/servers') - self.assertIsInstance(s, servers.Server) - - def test_create_server_return_reservation_id(self): - s = self.cs.servers.create( - name="My server", - image=1, - flavor=1, - reservation_id=True - ) - expected_body = { - 'server': { - 'name': 'My server', - 'image_ref': '1', - 'flavor_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - 'os-multiple-create:return_reservation_id': True, - } - } - self.assert_called('POST', '/servers', expected_body) - self.assertIsInstance(s, servers.Server) - - def test_update_server(self): - s = self.cs.servers.get(1234) - - # Update via instance - s.update(name='hi') - self.assert_called('PUT', '/servers/1234') - s.update(name='hi') - self.assert_called('PUT', '/servers/1234') - - # Silly, but not an error - s.update() - - # Update via manager - self.cs.servers.update(s, name='hi') - self.assert_called('PUT', '/servers/1234') - - def test_delete_server(self): - s = self.cs.servers.get(1234) - s.delete() - self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(1234) - self.assert_called('DELETE', '/servers/1234') - self.cs.servers.delete(s) - self.assert_called('DELETE', '/servers/1234') - - def test_delete_server_meta(self): - self.cs.servers.delete_meta(1234, ['test_key']) - self.assert_called('DELETE', '/servers/1234/metadata/test_key') - - def test_set_server_meta(self): - self.cs.servers.set_meta(1234, {'test_key': 'test_value'}) - self.assert_called('POST', '/servers/1234/metadata', - {'metadata': {'test_key': 'test_value'}}) - - def test_find(self): - server = self.cs.servers.find(name='sample-server') - self.assert_called('GET', '/servers/1234') - self.assertEqual('sample-server', server.name) - - self.assertRaises(exceptions.NoUniqueMatch, self.cs.servers.find, - flavor={"id": 1, "name": "256 MB Server"}) - - sl = self.cs.servers.findall(flavor={"id": 1, "name": "256 MB Server"}) - self.assertEqual([1234, 5678, 9012], [s.id for s in sl]) - - def test_reboot_server(self): - s = self.cs.servers.get(1234) - s.reboot() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reboot(s, reboot_type='HARD') - self.assert_called('POST', '/servers/1234/action') - - def test_rebuild_server(self): - s = self.cs.servers.get(1234) - s.rebuild(image=1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1) - self.assert_called('POST', '/servers/1234/action') - s.rebuild(image=1, password='5678') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rebuild(s, image=1, password='5678') - self.assert_called('POST', '/servers/1234/action') - - def test_resize_server(self): - s = self.cs.servers.get(1234) - s.resize(flavor=1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.resize(s, flavor=1) - self.assert_called('POST', '/servers/1234/action') - - def test_confirm_resized_server(self): - s = self.cs.servers.get(1234) - s.confirm_resize() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.confirm_resize(s) - self.assert_called('POST', '/servers/1234/action') - - def test_revert_resized_server(self): - s = self.cs.servers.get(1234) - s.revert_resize() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.revert_resize(s) - self.assert_called('POST', '/servers/1234/action') - - def test_migrate_server(self): - s = self.cs.servers.get(1234) - s.migrate() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.migrate(s) - self.assert_called('POST', '/servers/1234/action') - - def test_add_fixed_ip(self): - s = self.cs.servers.get(1234) - s.add_fixed_ip(1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.add_fixed_ip(s, 1) - self.assert_called('POST', '/servers/1234/action') - - def test_remove_fixed_ip(self): - s = self.cs.servers.get(1234) - s.remove_fixed_ip('10.0.0.1') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.remove_fixed_ip(s, '10.0.0.1') - self.assert_called('POST', '/servers/1234/action') - - def test_stop(self): - s = self.cs.servers.get(1234) - s.stop() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.stop(s) - self.assert_called('POST', '/servers/1234/action') - - def test_force_delete(self): - s = self.cs.servers.get(1234) - s.force_delete() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.force_delete(s) - self.assert_called('POST', '/servers/1234/action') - - def test_restore(self): - s = self.cs.servers.get(1234) - s.restore() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.restore(s) - self.assert_called('POST', '/servers/1234/action') - - def test_start(self): - s = self.cs.servers.get(1234) - s.start() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.start(s) - self.assert_called('POST', '/servers/1234/action') - - def test_rescue(self): - s = self.cs.servers.get(1234) - s.rescue() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.rescue(s) - self.assert_called('POST', '/servers/1234/action') - - def test_unrescue(self): - s = self.cs.servers.get(1234) - s.unrescue() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unrescue(s) - self.assert_called('POST', '/servers/1234/action') - - def test_lock(self): - s = self.cs.servers.get(1234) - s.lock() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.lock(s) - self.assert_called('POST', '/servers/1234/action') - - def test_unlock(self): - s = self.cs.servers.get(1234) - s.unlock() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.unlock(s) - self.assert_called('POST', '/servers/1234/action') - - def test_backup(self): - s = self.cs.servers.get(1234) - s.backup('back1', 'daily', 1) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.backup(s, 'back1', 'daily', 2) - self.assert_called('POST', '/servers/1234/action') - - def test_get_console_output_without_length(self): - success = 'foo' - s = self.cs.servers.get(1234) - s.get_console_output() - self.assertEqual(success, s.get_console_output()) - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_console_output(s) - self.assertEqual(success, self.cs.servers.get_console_output(s)) - self.assert_called('POST', '/servers/1234/action', - {'get_console_output': {'length': -1}}) - - def test_get_console_output_with_length(self): - success = 'foo' - - s = self.cs.servers.get(1234) - s.get_console_output(length=50) - self.assertEqual(success, s.get_console_output(length=50)) - self.assert_called('POST', '/servers/1234/action', - {'get_console_output': {'length': 50}}) - - self.cs.servers.get_console_output(s, length=50) - self.assertEqual(success, - self.cs.servers.get_console_output(s, length=50)) - self.assert_called('POST', '/servers/1234/action', - {'get_console_output': {'length': 50}}) - - def test_get_password(self): - s = self.cs.servers.get(1234) - self.assertEqual('', s.get_password('/foo/id_rsa')) - self.assert_called('GET', '/servers/1234/os-server-password') - - def test_clear_password(self): - s = self.cs.servers.get(1234) - s.clear_password() - self.assert_called('DELETE', '/servers/1234/os-server-password') - - def test_get_server_diagnostics(self): - s = self.cs.servers.get(1234) - diagnostics = s.diagnostics() - self.assertTrue(diagnostics is not None) - self.assert_called('GET', '/servers/1234/os-server-diagnostics') - - diagnostics_from_manager = self.cs.servers.diagnostics(1234) - self.assertTrue(diagnostics_from_manager is not None) - self.assert_called('GET', '/servers/1234/os-server-diagnostics') - - self.assertEqual(diagnostics_from_manager[1], diagnostics[1]) - - def test_get_vnc_console(self): - s = self.cs.servers.get(1234) - s.get_vnc_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_vnc_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_get_spice_console(self): - s = self.cs.servers.get(1234) - s.get_spice_console('fake') - self.assert_called('POST', '/servers/1234/action') - - self.cs.servers.get_spice_console(s, 'fake') - self.assert_called('POST', '/servers/1234/action') - - def test_create_image(self): - s = self.cs.servers.get(1234) - s.create_image('123') - self.assert_called('POST', '/servers/1234/action') - s.create_image('123', {}) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.create_image(s, '123', {}) - - def test_live_migrate_server(self): - s = self.cs.servers.get(1234) - s.live_migrate(host='hostname', block_migration=False, - disk_over_commit=False) - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.live_migrate(s, host='hostname', block_migration=False, - disk_over_commit=False) - self.assert_called('POST', '/servers/1234/action') - - def test_reset_state(self): - s = self.cs.servers.get(1234) - s.reset_state('newstate') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_state(s, 'newstate') - self.assert_called('POST', '/servers/1234/action') - - def test_reset_network(self): - s = self.cs.servers.get(1234) - s.reset_network() - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.reset_network(s) - self.assert_called('POST', '/servers/1234/action') - - def test_evacuate(self): - s = self.cs.servers.get(1234) - s.evacuate('fake_target_host', 'True') - self.assert_called('POST', '/servers/1234/action') - self.cs.servers.evacuate(s, 'fake_target_host', - 'False', 'NewAdminPassword') - self.assert_called('POST', '/servers/1234/action') - - def test_interface_list(self): - s = self.cs.servers.get(1234) - s.interface_list() - self.assert_called('GET', '/servers/1234/os-attach-interfaces') - - def test_interface_attach(self): - s = self.cs.servers.get(1234) - s.interface_attach(None, None, None) - self.assert_called('POST', '/servers/1234/os-attach-interfaces') - - def test_interface_detach(self): - s = self.cs.servers.get(1234) - s.interface_detach('port-id') - self.assert_called('DELETE', - '/servers/1234/os-attach-interfaces/port-id') diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_services.py b/awx/lib/site-packages/novaclient/tests/v3/test_services.py deleted file mode 100644 index 0fd2fc0cf2..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_services.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests import utils -from novaclient.tests.v3 import fakes -from novaclient.v3 import services - - -class ServicesTest(utils.TestCase): - def setUp(self): - super(ServicesTest, self).setUp() - self.cs = self._get_fake_client() - self.service_type = self._get_service_type() - - def _get_fake_client(self): - return fakes.FakeClient() - - def _get_service_type(self): - return services.Service - - def _update_body(self, host, binary, disabled_reason=None): - body = {"host": host, - "binary": binary} - if disabled_reason is not None: - body["disabled_reason"] = disabled_reason - return body diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_shell.py b/awx/lib/site-packages/novaclient/tests/v3/test_shell.py deleted file mode 100644 index 68931a1374..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_shell.py +++ /dev/null @@ -1,724 +0,0 @@ -# Copyright 2013 Cloudwatt -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import base64 -import os - -import fixtures -import mock -import six - -from novaclient import exceptions -import novaclient.shell -from novaclient.tests import utils -from novaclient.tests.v3 import fakes - - -class ShellFixture(fixtures.Fixture): - def setUp(self): - super(ShellFixture, self).setUp() - self.shell = novaclient.shell.OpenStackComputeShell() - - def tearDown(self): - # For some method like test_image_meta_bad_action we are - # testing a SystemExit to be thrown and object self.shell has - # no time to get instantatiated which is OK in this case, so - # we make sure the method is there before launching it. - if hasattr(self.shell, 'cs'): - self.shell.cs.clear_callstack() - super(ShellFixture, self).tearDown() - - -class ShellTest(utils.TestCase): - FAKE_ENV = { - 'NOVA_USERNAME': 'username', - 'NOVA_PASSWORD': 'password', - 'NOVA_PROJECT_ID': 'project_id', - 'OS_COMPUTE_API_VERSION': '3', - 'NOVA_URL': 'http://no.where', - } - - def setUp(self): - """Run before each test.""" - super(ShellTest, self).setUp() - - for var in self.FAKE_ENV: - self.useFixture(fixtures.EnvironmentVariable(var, - self.FAKE_ENV[var])) - self.shell = self.useFixture(ShellFixture()).shell - - self.useFixture(fixtures.MonkeyPatch( - 'novaclient.client.get_client_class', - lambda *_: fakes.FakeClient)) - - @mock.patch('sys.stdout', new_callable=six.StringIO) - def run_command(self, cmd, mock_stdout): - if isinstance(cmd, list): - self.shell.main(cmd) - else: - self.shell.main(cmd.split()) - return mock_stdout.getvalue() - - def assert_called(self, method, url, body=None, **kwargs): - return self.shell.cs.assert_called(method, url, body, **kwargs) - - def assert_called_anytime(self, method, url, body=None): - return self.shell.cs.assert_called_anytime(method, url, body) - - def test_list_deleted(self): - self.run_command('list --deleted') - self.assert_called('GET', '/servers/detail?deleted=True') - - def test_aggregate_list(self): - self.run_command('aggregate-list') - self.assert_called('GET', '/os-aggregates') - - def test_aggregate_create(self): - self.run_command('aggregate-create test_name nova1') - body = {"aggregate": {"name": "test_name", - "availability_zone": "nova1"}} - self.assert_called('POST', '/os-aggregates', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_delete_by_id(self): - self.run_command('aggregate-delete 1') - self.assert_called('DELETE', '/os-aggregates/1') - - def test_aggregate_delete_by_name(self): - self.run_command('aggregate-delete test') - self.assert_called('DELETE', '/os-aggregates/1') - - def test_aggregate_update_by_id(self): - self.run_command('aggregate-update 1 new_name') - body = {"aggregate": {"name": "new_name"}} - self.assert_called('PUT', '/os-aggregates/1', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_update_by_name(self): - self.run_command('aggregate-update test new_name') - body = {"aggregate": {"name": "new_name"}} - self.assert_called('PUT', '/os-aggregates/1', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_update_with_availability_zone_by_id(self): - self.run_command('aggregate-update 1 foo new_zone') - body = {"aggregate": {"name": "foo", "availability_zone": "new_zone"}} - self.assert_called('PUT', '/os-aggregates/1', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_update_with_availability_zone_by_name(self): - self.run_command('aggregate-update test foo new_zone') - body = {"aggregate": {"name": "foo", "availability_zone": "new_zone"}} - self.assert_called('PUT', '/os-aggregates/1', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_set_metadata_add_by_id(self): - self.run_command('aggregate-set-metadata 3 foo=bar') - body = {"set_metadata": {"metadata": {"foo": "bar"}}} - self.assert_called('POST', '/os-aggregates/3/action', body, pos=-2) - self.assert_called('GET', '/os-aggregates/3', pos=-1) - - def test_aggregate_set_metadata_add_duplicate_by_id(self): - cmd = 'aggregate-set-metadata 3 test=dup' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_aggregate_set_metadata_delete_by_id(self): - self.run_command('aggregate-set-metadata 3 none_key') - body = {"set_metadata": {"metadata": {"none_key": None}}} - self.assert_called('POST', '/os-aggregates/3/action', body, pos=-2) - self.assert_called('GET', '/os-aggregates/3', pos=-1) - - def test_aggregate_set_metadata_delete_missing_by_id(self): - cmd = 'aggregate-set-metadata 3 delete_key2' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_aggregate_set_metadata_by_name(self): - self.run_command('aggregate-set-metadata test foo=bar') - body = {"set_metadata": {"metadata": {"foo": "bar"}}} - self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_add_host_by_id(self): - self.run_command('aggregate-add-host 1 host1') - body = {"add_host": {"host": "host1"}} - self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_add_host_by_name(self): - self.run_command('aggregate-add-host test host1') - body = {"add_host": {"host": "host1"}} - self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_remove_host_by_id(self): - self.run_command('aggregate-remove-host 1 host1') - body = {"remove_host": {"host": "host1"}} - self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_remove_host_by_name(self): - self.run_command('aggregate-remove-host test host1') - body = {"remove_host": {"host": "host1"}} - self.assert_called('POST', '/os-aggregates/1/action', body, pos=-2) - self.assert_called('GET', '/os-aggregates/1', pos=-1) - - def test_aggregate_details_by_id(self): - self.run_command('aggregate-details 1') - self.assert_called('GET', '/os-aggregates/1') - - def test_aggregate_details_by_name(self): - self.run_command('aggregate-details test') - self.assert_called('GET', '/os-aggregates') - - def test_boot(self): - self.run_command('boot --flavor 1 --image 1 some-server') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - - def test_boot_image_with(self): - self.run_command("boot --flavor 1" - " --image-with test_key=test_value some-server") - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - - def test_boot_key(self): - self.run_command('boot --flavor 1 --image 1 --key_name 1 some-server') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'key_name': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - - def test_boot_user_data(self): - file_text = 'text' - - with mock.patch('novaclient.v3.shell.open', create=True) as mock_open: - mock_open.return_value = file_text - testfile = 'some_dir/some_file.txt' - - self.run_command('boot --flavor 1 --image 1 --user_data %s ' - 'some-server' % testfile) - - mock_open.assert_called_once_with(testfile) - - user_data = base64.b64encode(file_text.encode('utf-8')).decode('utf-8') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - 'user_data': user_data}}, - ) - - def test_boot_avzone(self): - self.run_command( - 'boot --flavor 1 --image 1 --availability-zone avzone ' - 'some-server') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-availability-zone:availability_zone': 'avzone', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1 - }}, - ) - - def test_boot_secgroup(self): - self.run_command( - 'boot --flavor 1 --image 1 --security-groups secgroup1,' - 'secgroup2 some-server') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'security_groups': [{'name': 'secgroup1'}, - {'name': 'secgroup2'}], - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - - def test_boot_config_drive(self): - self.run_command( - 'boot --flavor 1 --image 1 --config-drive 1 some-server') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - 'os-config-drive:config_drive': True - }}, - ) - - def test_boot_config_drive_custom(self): - self.run_command( - 'boot --flavor 1 --image 1 --config-drive /dev/hda some-server') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - 'os-config-drive:config_drive': '/dev/hda' - }}, - ) - - def test_boot_invalid_user_data(self): - invalid_file = os.path.join(os.path.dirname(__file__), - 'no_such_file') - cmd = ('boot some-server --flavor 1 --image 1' - ' --user_data %s' % invalid_file) - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_no_image_no_bdms(self): - cmd = 'boot --flavor 1 some-server' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_no_flavor(self): - cmd = 'boot --image 1 some-server' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_no_image_bdms(self): - self.run_command( - 'boot --flavor 1 --block_device_mapping vda=blah:::0 some-server' - ) - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'block_device_mapping': [ - { - 'volume_id': 'blah', - 'delete_on_termination': '0', - 'device_name': 'vda', - 'boot_index': 0, - 'uuid': 'blah', - 'source_type': '' - } - ], - 'image_ref': '', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - - def test_boot_image_bdms(self): - self.run_command( - 'boot --flavor 1 --image 1 --block-device id=fake-id,' - 'source=volume,dest=volume,device=vda,size=1,format=ext4,' - 'type=disk,shutdown=preserve some-server' - ) - id = ('fake-id,source=volume,dest=volume,device=vda,size=1,' - 'format=ext4,type=disk,shutdown=preserve') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'block_device_mapping': [ - {'device_name': 'id', 'volume_id': id, - 'source_type': 'volume', 'boot_index': 0, 'uuid': id}], - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - - def test_boot_metadata(self): - self.run_command('boot --image 1 --flavor 1 --meta foo=bar=pants' - ' --meta spam=eggs some-server ') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'metadata': {'foo': 'bar=pants', 'spam': 'eggs'}, - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - - def test_boot_hints(self): - self.run_command('boot --image 1 --flavor 1 ' - '--hint a=b1=c1 --hint a2=b2=c2 --hint a=b0=c0 ' - 'some-server') - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - 'os-scheduler-hints:scheduler_hints': { - 'a': ['b1=c1', 'b0=c0'], 'a2': 'b2=c2'}, - }, - }, - ) - - def test_boot_nics(self): - cmd = ('boot --image 1 --flavor 1 ' - '--nic net-id=a=c,v4-fixed-ip=10.0.0.1 some-server') - self.run_command(cmd) - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - 'networks': [ - {'uuid': 'a=c', 'fixed_ip': '10.0.0.1'}, - ], - }, - }, - ) - - def test_boot_nics_ipv6(self): - cmd = ('boot --image 1 --flavor 1 ' - '--nic net-id=a=c,v6-fixed-ip=2001:db9:0:1::10 some-server') - self.run_command(cmd) - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - 'networks': [ - {'uuid': 'a=c', 'fixed_ip': '2001:db9:0:1::10'}, - ], - }, - }, - ) - - def test_boot_nics_both_ipv4_and_ipv6(self): - cmd = ('boot --image 1 --flavor 1 ' - '--nic net-id=a=c,v4-fixed-ip=10.0.0.1,' - 'v6-fixed-ip=2001:db9:0:1::10 some-server') - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_nics_no_value(self): - cmd = ('boot --image 1 --flavor 1 ' - '--nic net-id some-server') - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_nics_random_key(self): - cmd = ('boot --image 1 --flavor 1 ' - '--nic net-id=a=c,v4-fixed-ip=10.0.0.1,foo=bar some-server') - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_nics_no_netid_or_portid(self): - cmd = ('boot --image 1 --flavor 1 ' - '--nic v4-fixed-ip=10.0.0.1 some-server') - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_nics_netid_and_portid(self): - cmd = ('boot --image 1 --flavor 1 ' - '--nic port-id=some=port,net-id=some=net some-server') - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_num_instances(self): - self.run_command('boot --image 1 --flavor 1 --num-instances 3 server') - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 3, - } - }) - - def test_boot_invalid_num_instances(self): - cmd = 'boot --image 1 --flavor 1 --num-instances 0 server' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_num_instances_and_count(self): - cmd = 'boot --image 1 --flavor 1 --num-instances 3 --min-count 3 serv' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - cmd = 'boot --image 1 --flavor 1 --num-instances 3 --max-count 3 serv' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_boot_min_max_count(self): - self.run_command('boot --image 1 --flavor 1 --max-count 3 server') - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 3, - } - }) - self.run_command('boot --image 1 --flavor 1 --min-count 3 server') - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'server', - 'image_ref': '1', - 'os-multiple-create:min_count': 3, - 'os-multiple-create:max_count': 3, - } - }) - self.run_command('boot --image 1 --flavor 1 ' - '--min-count 3 --max-count 3 server') - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'server', - 'image_ref': '1', - 'os-multiple-create:min_count': 3, - 'os-multiple-create:max_count': 3, - } - }) - self.run_command('boot --image 1 --flavor 1 ' - '--min-count 3 --max-count 5 server') - self.assert_called_anytime( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '1', - 'name': 'server', - 'image_ref': '1', - 'os-multiple-create:min_count': 3, - 'os-multiple-create:max_count': 5, - } - }) - cmd = 'boot --image 1 --flavor 1 --min-count 3 --max-count 1 serv' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - @mock.patch('novaclient.v3.shell._poll_for_status') - def test_boot_with_poll(self, poll_method): - self.run_command('boot --flavor 1 --image 1 some-server --poll') - self.assert_called_anytime( - 'POST', '/servers', - {'server': { - 'flavor_ref': '1', - 'name': 'some-server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 1, - }}, - ) - self.assertEqual(1, poll_method.call_count) - poll_method.assert_has_calls( - [mock.call(self.shell.cs.servers.get, 1234, 'building', - ['active'])]) - - def test_boot_with_poll_to_check_VM_state_error(self): - self.assertRaises(exceptions.InstanceInErrorState, self.run_command, - 'boot --flavor 1 --image 1 some-bad-server --poll') - - def test_evacuate(self): - self.run_command('evacuate sample-server new_host') - self.assert_called('POST', '/servers/1234/action', - {'evacuate': {'host': 'new_host', - 'on_shared_storage': False}}) - self.run_command('evacuate sample-server new_host ' - '--password NewAdminPass') - self.assert_called('POST', '/servers/1234/action', - {'evacuate': {'host': 'new_host', - 'on_shared_storage': False, - 'admin_password': 'NewAdminPass'}}) - self.run_command('evacuate sample-server new_host') - self.assert_called('POST', '/servers/1234/action', - {'evacuate': {'host': 'new_host', - 'on_shared_storage': False}}) - self.run_command('evacuate sample-server new_host ' - '--on-shared-storage') - self.assert_called('POST', '/servers/1234/action', - {'evacuate': {'host': 'new_host', - 'on_shared_storage': True}}) - - def test_evacuate_with_no_target_host(self): - self.run_command('evacuate sample-server') - self.assert_called('POST', '/servers/1234/action', - {'evacuate': {'on_shared_storage': False}}) - self.run_command('evacuate sample-server --password NewAdminPass') - self.assert_called('POST', '/servers/1234/action', - {'evacuate': {'on_shared_storage': False, - 'admin_password': 'NewAdminPass'}}) - self.run_command('evacuate sample-server --on-shared-storage') - self.assert_called('POST', '/servers/1234/action', - {'evacuate': {'on_shared_storage': True}}) - - def test_boot_named_flavor(self): - self.run_command(["boot", "--image", "1", - "--flavor", "512 MB Server", - "--max-count", "3", "server"]) - self.assert_called('GET', '/flavors/512 MB Server', pos=0) - self.assert_called('GET', '/flavors?is_public=None', pos=1) - self.assert_called('GET', '/flavors?is_public=None', pos=2) - self.assert_called('GET', '/flavors/2', pos=3) - self.assert_called( - 'POST', '/servers', - { - 'server': { - 'flavor_ref': '2', - 'name': 'server', - 'image_ref': '1', - 'os-multiple-create:min_count': 1, - 'os-multiple-create:max_count': 3, - } - }, pos=4) - - def test_flavor_show_by_name(self): - self.run_command(['flavor-show', '128 MB Server']) - self.assert_called('GET', '/flavors/128 MB Server', pos=0) - self.assert_called('GET', '/flavors?is_public=None', pos=1) - self.assert_called('GET', '/flavors?is_public=None', pos=2) - self.assert_called('GET', '/flavors/aa1', pos=3) - self.assert_called('GET', '/flavors/aa1/flavor-extra-specs', pos=4) - - def test_flavor_show_by_name_priv(self): - self.run_command(['flavor-show', '512 MB Server']) - self.assert_called('GET', '/flavors/512 MB Server', pos=0) - self.assert_called('GET', '/flavors?is_public=None', pos=1) - self.assert_called('GET', '/flavors?is_public=None', pos=2) - self.assert_called('GET', '/flavors/2', pos=3) - self.assert_called('GET', '/flavors/2/flavor-extra-specs', pos=4) - - def test_delete(self): - self.run_command('delete 1234') - self.assert_called('DELETE', '/servers/1234') - self.run_command('delete sample-server') - self.assert_called('DELETE', '/servers/1234') - - def test_delete_two_with_two_existent(self): - self.run_command('delete 1234 5678') - self.assert_called('DELETE', '/servers/1234', pos=-3) - self.assert_called('DELETE', '/servers/5678', pos=-1) - self.run_command('delete sample-server sample-server2') - self.assert_called('GET', '/servers?name=sample-server', pos=-6) - self.assert_called('GET', '/servers/1234', pos=-5) - self.assert_called('DELETE', '/servers/1234', pos=-4) - self.assert_called('GET', '/servers?name=sample-server2', pos=-3) - self.assert_called('GET', '/servers/5678', pos=-2) - self.assert_called('DELETE', '/servers/5678', pos=-1) - - def test_delete_two_with_one_nonexistent(self): - cmd = 'delete 1234 123456789' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - self.assert_called_anytime('DELETE', '/servers/1234') - cmd = 'delete sample-server nonexistentserver' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - self.assert_called_anytime('DELETE', '/servers/1234') - - def test_delete_one_with_one_nonexistent(self): - cmd = 'delete 123456789' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - cmd = 'delete nonexistent-server1' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - def test_delete_two_with_two_nonexistent(self): - cmd = 'delete 123456789 987654321' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - cmd = 'delete nonexistent-server1 nonexistent-server2' - self.assertRaises(exceptions.CommandError, self.run_command, cmd) - - -class GetFirstEndpointTest(utils.TestCase): - def test_only_one_endpoint(self): - """If there is only one endpoint, it is returned.""" - endpoint = {"url": "test"} - result = novaclient.v3.shell._get_first_endpoint([endpoint], "XYZ") - self.assertEqual(endpoint, result) - - def test_multiple_endpoints(self): - """If there are multiple endpoints, the first one of the appropriate - region is returned. - - """ - endpoints = [ - {"region": "XYZ"}, - {"region": "ORD", "number": 1}, - {"region": "ORD", "number": 2} - ] - result = novaclient.v3.shell._get_first_endpoint(endpoints, "ORD") - self.assertEqual(endpoints[1], result) - - def test_multiple_endpoints_but_none_suitable(self): - """If there are multiple endpoints but none of them are suitable, an - exception is raised. - - """ - endpoints = [ - {"region": "XYZ"}, - {"region": "PQR"}, - {"region": "STU"} - ] - self.assertRaises(LookupError, - novaclient.v3.shell._get_first_endpoint, - endpoints, "ORD") - - def test_no_endpoints(self): - """If there are no endpoints available, an exception is raised.""" - self.assertRaises(LookupError, - novaclient.v3.shell._get_first_endpoint, - [], "ORD") diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_usage.py b/awx/lib/site-packages/novaclient/tests/v3/test_usage.py deleted file mode 100644 index b4ffab79e9..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_usage.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests.v1_1 import fakes -from novaclient.tests.v1_1 import test_usage -from novaclient.v3 import usage - - -class UsageTest(test_usage.UsageTest): - def setUp(self): - super(UsageTest, self).setUp() - self.cs = self._get_fake_client() - self.usage_type = self._get_usage_type() - - def _get_fake_client(self): - return fakes.FakeClient() - - def _get_usage_type(self): - return usage.Usage diff --git a/awx/lib/site-packages/novaclient/tests/v3/test_volumes.py b/awx/lib/site-packages/novaclient/tests/v3/test_volumes.py deleted file mode 100644 index cfe6d9eb33..0000000000 --- a/awx/lib/site-packages/novaclient/tests/v3/test_volumes.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.tests import utils -from novaclient.tests.v3 import fakes - - -class VolumesTest(utils.TestCase): - def setUp(self): - super(VolumesTest, self).setUp() - self.cs = self._get_fake_client() - - def _get_fake_client(self): - return fakes.FakeClient() - - def test_attach_server_volume(self): - self.cs.volumes.attach_server_volume( - server=1234, - volume_id='15e59938-07d5-11e1-90e3-e3dffe0c5983', - device='/dev/vdb' - ) - self.cs.assert_called('POST', '/servers/1234/action') - - def test_attach_server_volume_disk_bus_device_type(self): - volume_id = '15e59938-07d5-11e1-90e3-e3dffe0c5983' - device = '/dev/vdb' - disk_bus = 'ide' - device_type = 'cdrom' - self.cs.volumes.attach_server_volume(server=1234, - volume_id=volume_id, - device=device, - disk_bus=disk_bus, - device_type=device_type) - body_params = {'volume_id': volume_id, - 'device': device, - 'disk_bus': disk_bus, - 'device_type': device_type} - body = {'attach': body_params} - self.cs.assert_called('POST', '/servers/1234/action', body) - - def test_update_server_volume(self): - vol_id = '15e59938-07d5-11e1-90e3-e3dffe0c5983' - self.cs.volumes.update_server_volume( - server=1234, - old_volume_id='Work', - new_volume_id=vol_id - ) - self.cs.assert_called('POST', '/servers/1234/action') - - def test_delete_server_volume(self): - self.cs.volumes.delete_server_volume(1234, 'Work') - self.cs.assert_called('POST', '/servers/1234/action') diff --git a/awx/lib/site-packages/novaclient/utils.py b/awx/lib/site-packages/novaclient/utils.py deleted file mode 100644 index d6068ba0c1..0000000000 --- a/awx/lib/site-packages/novaclient/utils.py +++ /dev/null @@ -1,378 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import re -import sys -import textwrap -import uuid - -from oslo.utils import encodeutils -import pkg_resources -import prettytable -import six - -from novaclient import exceptions -from novaclient.openstack.common import cliutils -from novaclient.openstack.common.gettextutils import _ -from novaclient.openstack.common import jsonutils - - -arg = cliutils.arg -env = cliutils.env - -VALID_KEY_REGEX = re.compile(r"[\w\.\- :]+$", re.UNICODE) - - -def add_resource_manager_extra_kwargs_hook(f, hook): - """Add hook to bind CLI arguments to ResourceManager calls. - - The `do_foo` calls in shell.py will receive CLI args and then in turn pass - them through to the ResourceManager. Before passing through the args, the - hooks registered here will be called, giving us a chance to add extra - kwargs (taken from the command-line) to what's passed to the - ResourceManager. - """ - if not hasattr(f, 'resource_manager_kwargs_hooks'): - f.resource_manager_kwargs_hooks = [] - - names = [h.__name__ for h in f.resource_manager_kwargs_hooks] - if hook.__name__ not in names: - f.resource_manager_kwargs_hooks.append(hook) - - -def get_resource_manager_extra_kwargs(f, args, allow_conflicts=False): - """Return extra_kwargs by calling resource manager kwargs hooks.""" - hooks = getattr(f, "resource_manager_kwargs_hooks", []) - extra_kwargs = {} - for hook in hooks: - hook_kwargs = hook(args) - hook_name = hook.__name__ - conflicting_keys = set(hook_kwargs.keys()) & set(extra_kwargs.keys()) - if conflicting_keys and not allow_conflicts: - msg = (_("Hook '%(hook_name)s' is attempting to redefine " - "attributes '%(conflicting_keys)s'") % - {'hook_name': hook_name, - 'conflicting_keys': conflicting_keys}) - raise exceptions.NoUniqueMatch(msg) - - extra_kwargs.update(hook_kwargs) - - return extra_kwargs - - -def service_type(stype): - """ - Adds 'service_type' attribute to decorated function. - Usage: - @service_type('volume') - def mymethod(f): - ... - """ - def inner(f): - f.service_type = stype - return f - return inner - - -def get_service_type(f): - """ - Retrieves service type from function - """ - return getattr(f, 'service_type', None) - - -def pretty_choice_list(l): - return ', '.join("'%s'" % i for i in l) - - -def pretty_choice_dict(d): - """Returns a formatted dict as 'key=value'.""" - return pretty_choice_list(['%s=%s' % (k, d[k]) for k in sorted(d.keys())]) - - -def print_list(objs, fields, formatters={}, sortby_index=None): - if sortby_index is None: - sortby = None - else: - sortby = fields[sortby_index] - mixed_case_fields = ['serverId'] - pt = prettytable.PrettyTable([f for f in fields], caching=False) - pt.align = 'l' - - for o in objs: - row = [] - for field in fields: - if field in formatters: - row.append(formatters[field](o)) - else: - if field in mixed_case_fields: - field_name = field.replace(' ', '_') - else: - field_name = field.lower().replace(' ', '_') - data = getattr(o, field_name, '') - if data is None: - data = '-' - row.append(data) - pt.add_row(row) - - if sortby is not None: - result = encodeutils.safe_encode(pt.get_string(sortby=sortby)) - else: - result = encodeutils.safe_encode(pt.get_string()) - - if six.PY3: - result = result.decode() - - print(result) - - -def _flatten(data, prefix=None): - """Flatten a dict, using name as a prefix for the keys of dict. - - >>> _flatten('cpu_info', {'arch':'x86_64'}) - [('cpu_info_arch': 'x86_64')] - - """ - if isinstance(data, dict): - for key, value in six.iteritems(data): - new_key = '%s_%s' % (prefix, key) if prefix else key - if isinstance(value, (dict, list)): - for item in _flatten(value, new_key): - yield item - else: - yield new_key, value - else: - yield prefix, data - - -def flatten_dict(data): - """Return a new dict whose sub-dicts have been merged into the - original. Each of the parents keys are prepended to the child's - to prevent collisions. Any string elements will be JSON parsed - before flattening. - - >>> flatten_dict({'service': {'host':'cloud9@compute-068', 'id': 143}}) - {'service_host': colud9@compute-068', 'service_id': 143} - - """ - data = data.copy() - # Try and decode any nested JSON structures. - for key, value in six.iteritems(data): - if isinstance(value, six.string_types): - try: - data[key] = json.loads(value) - except ValueError: - pass - - return dict(_flatten(data)) - - -def print_dict(d, dict_property="Property", dict_value="Value", wrap=0): - pt = prettytable.PrettyTable([dict_property, dict_value], caching=False) - pt.align = 'l' - for k, v in sorted(d.items()): - # convert dict to str to check length - if isinstance(v, (dict, list)): - v = jsonutils.dumps(v) - if wrap > 0: - v = textwrap.fill(str(v), wrap) - # if value has a newline, add in multiple rows - # e.g. fault with stacktrace - if v and isinstance(v, six.string_types) and r'\n' in v: - lines = v.strip().split(r'\n') - col1 = k - for line in lines: - pt.add_row([col1, line]) - col1 = '' - else: - if v is None: - v = '-' - pt.add_row([k, v]) - - result = encodeutils.safe_encode(pt.get_string()) - - if six.PY3: - result = result.decode() - - print(result) - - -def find_resource(manager, name_or_id, **find_args): - """Helper for the _find_* methods.""" - # for str id which is not uuid (for Flavor and Keypair search currently) - if getattr(manager, 'is_alphanum_id_allowed', False): - try: - return manager.get(name_or_id) - except exceptions.NotFound: - pass - - # try to get entity as integer id - try: - return manager.get(int(name_or_id)) - except (TypeError, ValueError, exceptions.NotFound): - pass - - # now try to get entity as uuid - try: - tmp_id = encodeutils.safe_encode(name_or_id) - - if six.PY3: - tmp_id = tmp_id.decode() - - uuid.UUID(tmp_id) - return manager.get(tmp_id) - except (TypeError, ValueError, exceptions.NotFound): - pass - - try: - try: - return manager.find(human_id=name_or_id, **find_args) - except exceptions.NotFound: - pass - - # finally try to find entity by name - try: - resource = getattr(manager, 'resource_class', None) - name_attr = resource.NAME_ATTR if resource else 'name' - kwargs = {name_attr: name_or_id} - kwargs.update(find_args) - return manager.find(**kwargs) - except exceptions.NotFound: - msg = _("No %(class)s with a name or ID of '%(name)s' exists.") % \ - {'class': manager.resource_class.__name__.lower(), - 'name': name_or_id} - raise exceptions.CommandError(msg) - except exceptions.NoUniqueMatch: - msg = (_("Multiple %(class)s matches found for '%(name)s', use an ID " - "to be more specific.") % - {'class': manager.resource_class.__name__.lower(), - 'name': name_or_id}) - raise exceptions.CommandError(msg) - - -def _format_servers_list_networks(server): - output = [] - for (network, addresses) in server.networks.items(): - if len(addresses) == 0: - continue - addresses_csv = ', '.join(addresses) - group = "%s=%s" % (network, addresses_csv) - output.append(group) - - return '; '.join(output) - - -def _format_security_groups(groups): - return ', '.join(group['name'] for group in groups) - - -def _format_field_name(attr): - """Format an object attribute in a human-friendly way.""" - # Split at ':' and leave the extension name as-is. - parts = attr.rsplit(':', 1) - name = parts[-1].replace('_', ' ') - # Don't title() on mixed case - if name.isupper() or name.islower(): - name = name.title() - parts[-1] = name - return ': '.join(parts) - - -def _make_field_formatter(attr, filters=None): - """ - Given an object attribute, return a formatted field name and a - formatter suitable for passing to print_list. - - Optionally pass a dict mapping attribute names to a function. The function - will be passed the value of the attribute and should return the string to - display. - """ - filter_ = None - if filters: - filter_ = filters.get(attr) - - def get_field(obj): - field = getattr(obj, attr, '') - if field and filter_: - field = filter_(field) - return field - - name = _format_field_name(attr) - formatter = get_field - return name, formatter - - -class HookableMixin(object): - """Mixin so classes can register and run hooks.""" - _hooks_map = {} - - @classmethod - def add_hook(cls, hook_type, hook_func): - if hook_type not in cls._hooks_map: - cls._hooks_map[hook_type] = [] - - cls._hooks_map[hook_type].append(hook_func) - - @classmethod - def run_hooks(cls, hook_type, *args, **kwargs): - hook_funcs = cls._hooks_map.get(hook_type) or [] - for hook_func in hook_funcs: - hook_func(*args, **kwargs) - - -def safe_issubclass(*args): - """Like issubclass, but will just return False if not a class.""" - - try: - if issubclass(*args): - return True - except TypeError: - pass - - return False - - -def import_class(import_str): - """Returns a class from a string including module and class.""" - mod_str, _sep, class_str = import_str.rpartition('.') - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - - -def _load_entry_point(ep_name, name=None): - """Try to load the entry point ep_name that matches name.""" - for ep in pkg_resources.iter_entry_points(ep_name, name=name): - try: - return ep.load() - except (ImportError, pkg_resources.UnknownExtra, AttributeError): - continue - - -def is_integer_like(val): - """Returns validation of a value as an integer.""" - try: - int(val) - return True - except (TypeError, ValueError, AttributeError): - return False - - -def validate_flavor_metadata_keys(keys): - for key in keys: - valid_name = VALID_KEY_REGEX.match(key) - if not valid_name: - msg = _('Invalid key: "%s". Keys may only contain letters, ' - 'numbers, spaces, underscores, periods, colons and ' - 'hyphens.') - raise exceptions.CommandError(msg % key) diff --git a/awx/lib/site-packages/novaclient/v1_1/__init__.py b/awx/lib/site-packages/novaclient/v1_1/__init__.py deleted file mode 100644 index 19712285f8..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.v1_1.client import Client # noqa diff --git a/awx/lib/site-packages/novaclient/v1_1/agents.py b/awx/lib/site-packages/novaclient/v1_1/agents.py deleted file mode 100644 index a58675ade1..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/agents.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -agent interface -""" - -from novaclient import base - - -class Agent(base.Resource): - def __repr__(self): - return "" % self.agent - - def _add_details(self, info): - dico = 'resource' in info and info['resource'] or info - for (k, v) in dico.items(): - setattr(self, k, v) - - -class AgentsManager(base.ManagerWithFind): - resource_class = Agent - - def list(self, hypervisor=None): - """List all agent builds.""" - url = "/os-agents" - if hypervisor: - url = "/os-agents?hypervisor=%s" % hypervisor - return self._list(url, "agents") - - def _build_update_body(self, version, url, md5hash): - return {'para': { - 'version': version, - 'url': url, - 'md5hash': md5hash}} - - def update(self, id, version, - url, md5hash): - """Update an existing agent build.""" - body = self._build_update_body(version, url, md5hash) - return self._update('/os-agents/%s' % id, body, 'agent') - - def create(self, os, architecture, version, - url, md5hash, hypervisor): - """Create a new agent build.""" - body = {'agent': { - 'hypervisor': hypervisor, - 'os': os, - 'architecture': architecture, - 'version': version, - 'url': url, - 'md5hash': md5hash}} - return self._create('/os-agents', body, 'agent') - - def delete(self, id): - """Deletes an existing agent build.""" - self._delete('/os-agents/%s' % id) diff --git a/awx/lib/site-packages/novaclient/v1_1/aggregates.py b/awx/lib/site-packages/novaclient/v1_1/aggregates.py deleted file mode 100644 index c2df31526d..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/aggregates.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Aggregate interface.""" - -from novaclient import base - - -class Aggregate(base.Resource): - """An aggregates is a collection of compute hosts.""" - - def __repr__(self): - return "" % self.id - - def update(self, values): - """Update the name and/or availability zone.""" - return self.manager.update(self, values) - - def add_host(self, host): - return self.manager.add_host(self, host) - - def remove_host(self, host): - return self.manager.remove_host(self, host) - - def set_metadata(self, metadata): - return self.manager.set_metadata(self, metadata) - - def delete(self): - self.manager.delete(self) - - -class AggregateManager(base.ManagerWithFind): - resource_class = Aggregate - - def list(self): - """Get a list of os-aggregates.""" - return self._list('/os-aggregates', 'aggregates') - - def create(self, name, availability_zone): - """Create a new aggregate.""" - body = {'aggregate': {'name': name, - 'availability_zone': availability_zone}} - return self._create('/os-aggregates', body, 'aggregate') - - def get(self, aggregate): - """Get details of the specified aggregate.""" - return self._get('/os-aggregates/%s' % (base.getid(aggregate)), - "aggregate") - - # NOTE:(dtroyer): utils.find_resource() uses manager.get() but we need to - # keep the API backward compatible - def get_details(self, aggregate): - """Get details of the specified aggregate.""" - return self.get(aggregate) - - def update(self, aggregate, values): - """Update the name and/or availability zone.""" - body = {'aggregate': values} - return self._update("/os-aggregates/%s" % base.getid(aggregate), - body, - "aggregate") - - def add_host(self, aggregate, host): - """Add a host into the Host Aggregate.""" - body = {'add_host': {'host': host}} - return self._create("/os-aggregates/%s/action" % base.getid(aggregate), - body, "aggregate") - - def remove_host(self, aggregate, host): - """Remove a host from the Host Aggregate.""" - body = {'remove_host': {'host': host}} - return self._create("/os-aggregates/%s/action" % base.getid(aggregate), - body, "aggregate") - - def set_metadata(self, aggregate, metadata): - """Set a aggregate metadata, replacing the existing metadata.""" - body = {'set_metadata': {'metadata': metadata}} - return self._create("/os-aggregates/%s/action" % base.getid(aggregate), - body, "aggregate") - - def delete(self, aggregate): - """Delete the specified aggregates.""" - self._delete('/os-aggregates/%s' % (base.getid(aggregate))) diff --git a/awx/lib/site-packages/novaclient/v1_1/availability_zones.py b/awx/lib/site-packages/novaclient/v1_1/availability_zones.py deleted file mode 100644 index bf59037853..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/availability_zones.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Availability Zone interface (1.1 extension). -""" - -from novaclient import base - - -class AvailabilityZone(base.Resource): - """ - An availability zone object. - """ - NAME_ATTR = 'display_name' - - def __repr__(self): - return "" % self.zoneName - - -class AvailabilityZoneManager(base.ManagerWithFind): - """ - Manage :class:`AvailabilityZone` resources. - """ - resource_class = AvailabilityZone - return_parameter_name = "availabilityZoneInfo" - - def list(self, detailed=True): - """ - Get a list of all availability zones. - - :rtype: list of :class:`AvailabilityZone` - """ - if detailed is True: - return self._list("/os-availability-zone/detail", - self.return_parameter_name) - else: - return self._list("/os-availability-zone", - self.return_parameter_name) diff --git a/awx/lib/site-packages/novaclient/v1_1/certs.py b/awx/lib/site-packages/novaclient/v1_1/certs.py deleted file mode 100644 index 232d7c1fdb..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/certs.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Certificate interface. -""" - -from novaclient import base - - -class Certificate(base.Resource): - def __repr__(self): - return "" % \ - (len(self.private_key) if self.private_key else 0, - len(self.data)) - - -class CertificateManager(base.Manager): - """ - Manage :class:`Certificate` resources. - """ - resource_class = Certificate - - def create(self): - """ - Create a x509 certificate for a user in tenant. - """ - return self._create('/os-certificates', {}, 'certificate') - - def get(self): - """ - Get root certificate. - """ - return self._get("/os-certificates/root", 'certificate') diff --git a/awx/lib/site-packages/novaclient/v1_1/client.py b/awx/lib/site-packages/novaclient/v1_1/client.py deleted file mode 100644 index 2e79e5bb1c..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/client.py +++ /dev/null @@ -1,239 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import client -from novaclient.v1_1 import agents -from novaclient.v1_1 import aggregates -from novaclient.v1_1 import availability_zones -from novaclient.v1_1 import certs -from novaclient.v1_1 import cloudpipe -from novaclient.v1_1 import fixed_ips -from novaclient.v1_1 import flavor_access -from novaclient.v1_1 import flavors -from novaclient.v1_1 import floating_ip_dns -from novaclient.v1_1 import floating_ip_pools -from novaclient.v1_1 import floating_ips -from novaclient.v1_1 import floating_ips_bulk -from novaclient.v1_1 import fping -from novaclient.v1_1 import hosts -from novaclient.v1_1 import hypervisors -from novaclient.v1_1 import images -from novaclient.v1_1 import keypairs -from novaclient.v1_1 import limits -from novaclient.v1_1 import networks -from novaclient.v1_1 import quota_classes -from novaclient.v1_1 import quotas -from novaclient.v1_1 import security_group_default_rules -from novaclient.v1_1 import security_group_rules -from novaclient.v1_1 import security_groups -from novaclient.v1_1 import server_groups -from novaclient.v1_1 import servers -from novaclient.v1_1 import services -from novaclient.v1_1 import usage -from novaclient.v1_1 import versions -from novaclient.v1_1 import virtual_interfaces -from novaclient.v1_1 import volume_snapshots -from novaclient.v1_1 import volume_types -from novaclient.v1_1 import volumes - - -class Client(object): - """ - Top-level object to access the OpenStack Compute API. - - Create an instance with your creds:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) - - Or, alternatively, you can create a client instance using the - keystoneclient.session API:: - - >>> from keystoneclient.auth.identity import v2 - >>> from keystoneclient import session - >>> from novaclient.client import Client - >>> auth = v2.Password(auth_url=AUTH_URL, - username=USERNAME, - password=PASSWORD, - tenant_name=PROJECT_ID) - >>> sess = session.Session(auth=auth) - >>> nova = client.Client(VERSION, session=sess) - - Then call methods on its managers:: - - >>> client.servers.list() - ... - >>> client.flavors.list() - ... - - It is also possible to use an instance as a context manager in which - case there will be a session kept alive for the duration of the with - statement:: - - >>> with Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) as client: - ... client.servers.list() - ... client.flavors.list() - ... - - It is also possible to have a permanent (process-long) connection pool, - by passing a connection_pool=True:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, - ... AUTH_URL, connection_pool=True) - """ - - def __init__(self, username=None, api_key=None, project_id=None, - auth_url=None, insecure=False, timeout=None, - proxy_tenant_id=None, proxy_token=None, region_name=None, - endpoint_type='publicURL', extensions=None, - service_type='compute', service_name=None, - volume_service_name=None, timings=False, bypass_url=None, - os_cache=False, no_cache=True, http_log_debug=False, - auth_system='keystone', auth_plugin=None, auth_token=None, - cacert=None, tenant_id=None, user_id=None, - connection_pool=False, session=None, auth=None, - completion_cache=None): - # FIXME(comstud): Rename the api_key argument above when we - # know it's not being used as keyword argument - - # NOTE(cyeoh): In the novaclient context (unlike Nova) the - # project_id is not the same as the tenant_id. Here project_id - # is a name (what the Nova API often refers to as a project or - # tenant name) and tenant_id is a UUID (what the Nova API - # often refers to as a project_id or tenant_id). - - password = api_key - self.projectid = project_id - self.tenant_id = tenant_id - self.user_id = user_id - self.flavors = flavors.FlavorManager(self) - self.flavor_access = flavor_access.FlavorAccessManager(self) - self.images = images.ImageManager(self) - self.limits = limits.LimitsManager(self) - self.servers = servers.ServerManager(self) - self.versions = versions.VersionManager(self) - - # extensions - self.agents = agents.AgentsManager(self) - self.dns_domains = floating_ip_dns.FloatingIPDNSDomainManager(self) - self.dns_entries = floating_ip_dns.FloatingIPDNSEntryManager(self) - self.cloudpipe = cloudpipe.CloudpipeManager(self) - self.certs = certs.CertificateManager(self) - self.floating_ips = floating_ips.FloatingIPManager(self) - self.floating_ip_pools = floating_ip_pools.FloatingIPPoolManager(self) - self.fping = fping.FpingManager(self) - self.volumes = volumes.VolumeManager(self) - self.volume_snapshots = volume_snapshots.SnapshotManager(self) - self.volume_types = volume_types.VolumeTypeManager(self) - self.keypairs = keypairs.KeypairManager(self) - self.networks = networks.NetworkManager(self) - self.quota_classes = quota_classes.QuotaClassSetManager(self) - self.quotas = quotas.QuotaSetManager(self) - self.security_groups = security_groups.SecurityGroupManager(self) - self.security_group_rules = \ - security_group_rules.SecurityGroupRuleManager(self) - self.security_group_default_rules = \ - security_group_default_rules.SecurityGroupDefaultRuleManager(self) - self.usage = usage.UsageManager(self) - self.virtual_interfaces = \ - virtual_interfaces.VirtualInterfaceManager(self) - self.aggregates = aggregates.AggregateManager(self) - self.hosts = hosts.HostManager(self) - self.hypervisors = hypervisors.HypervisorManager(self) - self.services = services.ServiceManager(self) - self.fixed_ips = fixed_ips.FixedIPsManager(self) - self.floating_ips_bulk = floating_ips_bulk.FloatingIPBulkManager(self) - self.os_cache = os_cache or not no_cache - self.availability_zones = \ - availability_zones.AvailabilityZoneManager(self) - self.server_groups = server_groups.ServerGroupsManager(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - self.client = client._construct_http_client( - username=username, - password=password, - user_id=user_id, - project_id=project_id, - tenant_id=tenant_id, - auth_url=auth_url, - auth_token=auth_token, - insecure=insecure, - timeout=timeout, - auth_system=auth_system, - auth_plugin=auth_plugin, - proxy_token=proxy_token, - proxy_tenant_id=proxy_tenant_id, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - timings=timings, - bypass_url=bypass_url, - os_cache=self.os_cache, - http_log_debug=http_log_debug, - cacert=cacert, - connection_pool=connection_pool, - session=session, - auth=auth) - - self.completion_cache = completion_cache - - def write_object_to_completion_cache(self, obj): - if self.completion_cache: - self.completion_cache.write_object(obj) - - def clear_completion_cache_for_class(self, obj_class): - if self.completion_cache: - self.completion_cache.clear_class(obj_class) - - @client._original_only - def __enter__(self): - self.client.open_session() - return self - - @client._original_only - def __exit__(self, t, v, tb): - self.client.close_session() - - @client._original_only - def set_management_url(self, url): - self.client.set_management_url(url) - - @client._original_only - def get_timings(self): - return self.client.get_timings() - - @client._original_only - def reset_timings(self): - self.client.reset_timings() - - @client._original_only - def authenticate(self): - """ - Authenticate against the server. - - Normally this is called automatically when you first access the API, - but you can call this method to force authentication right now. - - Returns on success; raises :exc:`exceptions.Unauthorized` if the - credentials are wrong. - """ - self.client.authenticate() diff --git a/awx/lib/site-packages/novaclient/v1_1/cloudpipe.py b/awx/lib/site-packages/novaclient/v1_1/cloudpipe.py deleted file mode 100644 index 6e05f4a20f..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/cloudpipe.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Cloudpipe interface.""" - -from novaclient import base - - -class Cloudpipe(base.Resource): - """A cloudpipe instance is a VPN attached to a project's VLAN.""" - - def __repr__(self): - return "" % self.project_id - - def delete(self): - self.manager.delete(self) - - -class CloudpipeManager(base.ManagerWithFind): - resource_class = Cloudpipe - - def create(self, project): - """ - Launch a cloudpipe instance. - - :param project: UUID of the project (tenant) for the cloudpipe - """ - body = {'cloudpipe': {'project_id': project}} - return self._create('/os-cloudpipe', body, 'instance_id', - return_raw=True) - - def list(self): - """ - Get a list of cloudpipe instances. - """ - return self._list('/os-cloudpipe', 'cloudpipes') - - def update(self, address, port): - """ - Update VPN address and port for all networks associated - with the project defined by authentication - - :param address: IP address - :param port: Port number - """ - - body = {'configure_project': {'vpn_ip': address, - 'vpn_port': port}} - self._update("/os-cloudpipe/configure-project", body) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/__init__.py b/awx/lib/site-packages/novaclient/v1_1/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/assisted_volume_snapshots.py b/awx/lib/site-packages/novaclient/v1_1/contrib/assisted_volume_snapshots.py deleted file mode 100644 index 0f1773b497..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/assisted_volume_snapshots.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2013, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Assisted volume snapshots - to be used by Cinder and not end users. -""" - -import json - -from novaclient import base - - -class Snapshot(base.Resource): - def __repr__(self): - return "" % self.id - - def delete(self): - """ - Delete this snapshot. - """ - self.manager.delete(self) - - -class AssistedSnapshotManager(base.Manager): - resource_class = Snapshot - - def create(self, volume_id, create_info): - body = {'snapshot': {'volume_id': volume_id, - 'create_info': create_info}} - return self._create('/os-assisted-volume-snapshots', body, 'snapshot') - - def delete(self, snapshot, delete_info): - self._delete("/os-assisted-volume-snapshots/%s?delete_info=%s" % ( - base.getid(snapshot), json.dumps(delete_info))) - -manager_class = AssistedSnapshotManager -name = 'assisted_volume_snapshots' diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/baremetal.py b/awx/lib/site-packages/novaclient/v1_1/contrib/baremetal.py deleted file mode 100644 index d13018ce8b..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/baremetal.py +++ /dev/null @@ -1,317 +0,0 @@ -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Baremetal interface (v2 extension). -""" -from novaclient import base -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class BareMetalNode(base.Resource): - """ - A baremetal node (typically a physical server or an empty VM). - """ - - def __repr__(self): - return "" % self.id - - -class BareMetalNodeInterface(base.Resource): - """ - An interface belonging to a baremetal node. - """ - - def __repr__(self): - return "" % self.id - - -class BareMetalNodeManager(base.ManagerWithFind): - """ - Manage :class:`BareMetalNode` resources. - """ - resource_class = BareMetalNode - - def create(self, - service_host, - cpus, - memory_mb, - local_gb, - prov_mac_address, - pm_address=None, - pm_user=None, - pm_password=None, - terminal_port=None): - """ - Create a baremetal node. - - :param service_host: Name of controlling compute host - :param cpus: Number of CPUs in the node - :param memory_mb: Megabytes of RAM in the node - :param local_gb: Gigabytes of local storage in the node - :param pm_address: Power management IP for the node - :param pm_user: Username for the node's power management - :param pm_password: Password for the node's power management - :param prov_mac_address: MAC address to provision the node - :param terminal_port: ShellInABox port - :rtype: :class:`BareMetalNode` - """ - body = {'node': {'service_host': service_host, - 'cpus': cpus, - 'memory_mb': memory_mb, - 'local_gb': local_gb, - 'pm_address': pm_address, - 'pm_user': pm_user, - 'pm_password': pm_password, - 'prov_mac_address': prov_mac_address, - 'terminal_port': terminal_port}} - - return self._create('/os-baremetal-nodes', body, 'node') - - def delete(self, node): - """ - Delete a baremetal node. - - :param node: The :class:`BareMetalNode` to delete. - """ - self._delete('/os-baremetal-nodes/%s' % base.getid(node)) - - def get(self, node_id): - """ - Get a baremetal node. - - :param node_id: The ID of the node to delete. - :rtype: :class:`BareMetalNode` - """ - return self._get("/os-baremetal-nodes/%s" % node_id, 'node') - - def list(self): - """ - Get a list of all baremetal nodes. - - :rtype: list of :class:`BareMetalNode` - """ - return self._list('/os-baremetal-nodes', 'nodes') - - def add_interface(self, node_id, address, datapath_id=0, port_no=0): - """ - Add an interface to a baremetal node. - - :param node_id: The ID of the node to modify. - :param address: The MAC address to add. - :param datapath_id: Datapath ID of OpenFlow switch for the interface - :param port_no: OpenFlow port number for the interface - :rtype: :class:`BareMetalNodeInterface` - """ - body = {'add_interface': {'address': address, - 'datapath_id': datapath_id, - 'port_no': port_no}} - url = '/os-baremetal-nodes/%s/action' % node_id - _resp, body = self.api.client.post(url, body=body) - return BareMetalNodeInterface(self, body['interface']) - - def remove_interface(self, node_id, address): - """ - Remove an interface from a baremetal node. - - :param node_id: The ID of the node to modify. - :param address: The MAC address to remove. - :rtype: bool - """ - req_body = {'remove_interface': {'address': address}} - url = '/os-baremetal-nodes/%s/action' % node_id - self.api.client.post(url, body=req_body) - - def list_interfaces(self, node_id): - """ - List the interfaces on a baremetal node. - - :param node_id: The ID of the node to list. - :rtype: list - """ - interfaces = [] - node = self._get("/os-baremetal-nodes/%s" % node_id, 'node') - for interface in node.interfaces: - interface_object = BareMetalNodeInterface(self, interface) - interfaces.append(interface_object) - return interfaces - - -@utils.arg('service_host', - metavar='', - help=_('Name of nova compute host which will control this baremetal ' - 'node')) -@utils.arg('cpus', - metavar='', - type=int, - help=_('Number of CPUs in the node')) -@utils.arg('memory_mb', - metavar='', - type=int, - help=_('Megabytes of RAM in the node')) -@utils.arg('local_gb', - metavar='', - type=int, - help=_('Gigabytes of local storage in the node')) -@utils.arg('prov_mac_address', - metavar='', - help=_('MAC address to provision the node')) -@utils.arg('--pm_address', default=None, - metavar='', - help=_('Power management IP for the node')) -@utils.arg('--pm_user', default=None, - metavar='', - help=_('Username for the node\'s power management')) -@utils.arg('--pm_password', default=None, - metavar='', - help=_('Password for the node\'s power management')) -@utils.arg('--terminal_port', default=None, - metavar='', - type=int, - help=_('ShellInABox port?')) -def do_baremetal_node_create(cs, args): - """Create a baremetal node.""" - node = cs.baremetal.create(args.service_host, args.cpus, - args.memory_mb, args.local_gb, args.prov_mac_address, - pm_address=args.pm_address, pm_user=args.pm_user, - pm_password=args.pm_password, - terminal_port=args.terminal_port) - _print_baremetal_resource(node) - - -@utils.arg('node', - metavar='', - help=_('ID of the node to delete.')) -def do_baremetal_node_delete(cs, args): - """Remove a baremetal node and any associated interfaces.""" - node = _find_baremetal_node(cs, args.node) - cs.baremetal.delete(node) - - -def _translate_baremetal_node_keys(collection): - convert = [('service_host', 'host'), - ('local_gb', 'disk_gb'), - ('prov_mac_address', 'mac_address'), - ('pm_address', 'pm_address'), - ('pm_user', 'pm_username'), - ('pm_password', 'pm_password'), - ('terminal_port', 'terminal_port'), - ] - for item in collection: - keys = item.__dict__.keys() - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _print_baremetal_nodes_list(nodes): - """Print the list of baremetal nodes.""" - - def _parse_address(fields): - macs = [] - for interface in fields.interfaces: - macs.append(interface['address']) - return ', '.join("%s" % i for i in macs) - - formatters = { - 'MAC Address': _parse_address - } - - _translate_baremetal_node_keys(nodes) - utils.print_list(nodes, [ - 'ID', - 'Host', - 'Task State', - 'CPUs', - 'Memory_MB', - 'Disk_GB', - 'MAC Address', - 'PM Address', - 'PM Username', - 'PM Password', - 'Terminal Port', - ], formatters=formatters) - - -def do_baremetal_node_list(cs, _args): - """Print list of available baremetal nodes.""" - nodes = cs.baremetal.list() - _print_baremetal_nodes_list(nodes) - - -def _find_baremetal_node(cs, node): - """Get a node by ID.""" - return utils.find_resource(cs.baremetal, node) - - -def _print_baremetal_resource(resource): - """Print details of a baremetal resource.""" - info = resource._info.copy() - utils.print_dict(info) - - -def _print_baremetal_node_interfaces(interfaces): - """Print interfaces of a baremetal node.""" - utils.print_list(interfaces, [ - 'ID', - 'Datapath_ID', - 'Port_No', - 'Address', - ]) - - -@utils.arg('node', - metavar='', - help=_("ID of node")) -def do_baremetal_node_show(cs, args): - """Show information about a baremetal node.""" - node = _find_baremetal_node(cs, args.node) - _print_baremetal_resource(node) - - -@utils.arg('node', - metavar='', - help=_("ID of node")) -@utils.arg('address', - metavar='
', - help=_("MAC address of interface")) -@utils.arg('--datapath_id', - default=0, - metavar='', - help=_("OpenFlow Datapath ID of interface")) -@utils.arg('--port_no', - default=0, - metavar='', - help=_("OpenFlow port number of interface")) -def do_baremetal_interface_add(cs, args): - """Add a network interface to a baremetal node.""" - bmif = cs.baremetal.add_interface(args.node, args.address, - args.datapath_id, args.port_no) - _print_baremetal_resource(bmif) - - -@utils.arg('node', metavar='', help=_("ID of node")) -@utils.arg('address', metavar='
', help=_("MAC address of interface")) -def do_baremetal_interface_remove(cs, args): - """Remove a network interface from a baremetal node.""" - cs.baremetal.remove_interface(args.node, args.address) - - -@utils.arg('node', metavar='', help=_("ID of node")) -def do_baremetal_interface_list(cs, args): - """List network interfaces associated with a baremetal node.""" - interfaces = cs.baremetal.list_interfaces(args.node) - _print_baremetal_node_interfaces(interfaces) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/cells.py b/awx/lib/site-packages/novaclient/v1_1/contrib/cells.py deleted file mode 100644 index 7c59400ef0..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/cells.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class Cell(base.Resource): - def __repr__(self): - return "" % self.name - - -class CellsManager(base.Manager): - resource_class = Cell - - def get(self, cell_name): - """ - Get a cell. - - :param cell: Name of the :class:`Cell` to get. - :rtype: :class:`Cell` - """ - return self._get("/os-cells/%s" % cell_name, "cell") - - def capacities(self, cell_name=None): - """ - Get capacities for a cell. - - :param cell: Name of the :class:`Cell` to get capacities for. - :rtype: :class:`Cell` - """ - path = ["%s/capacities" % cell_name, "capacities"][cell_name is None] - return self._get("/os-cells/%s" % path, "cell") - - -@utils.arg('cell', - metavar='', - help=_('Name of the cell.')) -def do_cell_show(cs, args): - """Show details of a given cell.""" - cell = cs.cells.get(args.cell) - utils.print_dict(cell._info) - - -@utils.arg('--cell', - metavar='', - help=_("Name of the cell to get the capacities."), - default=None) -def do_cell_capacities(cs, args): - """Get cell capacities for all cells or a given cell.""" - cell = cs.cells.capacities(args.cell) - print(_("Ram Available: %s MB") % cell.capacities['ram_free']['total_mb']) - utils.print_dict(cell.capacities['ram_free']['units_by_mb'], - dict_property='Ram(MB)', dict_value="Units") - print(_("\nDisk Available: %s MB") % - cell.capacities['disk_free']['total_mb']) - utils.print_dict(cell.capacities['disk_free']['units_by_mb'], - dict_property='Disk(MB)', dict_value="Units") diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/deferred_delete.py b/awx/lib/site-packages/novaclient/v1_1/contrib/deferred_delete.py deleted file mode 100644 index 1412702d57..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/deferred_delete.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from novaclient import utils - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_force_delete(cs, args): - """Force delete a server.""" - utils.find_resource(cs.servers, args.server).force_delete() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_restore(cs, args): - """Restore a soft-deleted server.""" - utils.find_resource(cs.servers, args.server).restore() diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/host_evacuate.py b/awx/lib/site-packages/novaclient/v1_1/contrib/host_evacuate.py deleted file mode 100644 index 12ad602fa8..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/host_evacuate.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class EvacuateHostResponse(base.Resource): - pass - - -def _server_evacuate(cs, server, args): - success = True - error_message = "" - try: - cs.servers.evacuate(server=server['uuid'], host=args.target_host, - on_shared_storage=args.on_shared_storage) - except Exception as e: - success = False - error_message = _("Error while evacuating instance: %s") % e - return EvacuateHostResponse(base.Manager, - {"server_uuid": server['uuid'], - "evacuate_accepted": success, - "error_message": error_message}) - - -@utils.arg('host', metavar='', help='Name of host.') -@utils.arg('--target_host', - metavar='', - default=None, - help=_('Name of target host. ' - 'If no host is specified the scheduler' - ' will select a target.')) -@utils.arg('--on-shared-storage', - dest='on_shared_storage', - action="store_true", - default=False, - help=_('Specifies whether all instances files are on shared ' - ' storage')) -def do_host_evacuate(cs, args): - """Evacuate all instances from failed host.""" - hypervisors = cs.hypervisors.search(args.host, servers=True) - response = [] - for hyper in hypervisors: - if hasattr(hyper, 'servers'): - for server in hyper.servers: - response.append(_server_evacuate(cs, server, args)) - - utils.print_list(response, - ["Server UUID", "Evacuate Accepted", "Error Message"]) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/host_servers_migrate.py b/awx/lib/site-packages/novaclient/v1_1/contrib/host_servers_migrate.py deleted file mode 100644 index ac5238f429..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/host_servers_migrate.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class HostServersMigrateResponse(base.Resource): - pass - - -def _server_migrate(cs, server): - success = True - error_message = "" - try: - cs.servers.migrate(server['uuid']) - except Exception as e: - success = False - error_message = _("Error while migrating instance: %s") % e - return HostServersMigrateResponse(base.Manager, - {"server_uuid": server['uuid'], - "migration_accepted": success, - "error_message": error_message}) - - -@utils.arg('host', metavar='', help='Name of host.') -def do_host_servers_migrate(cs, args): - """Migrate all instances of the specified host to other available hosts.""" - hypervisors = cs.hypervisors.search(args.host, servers=True) - response = [] - for hyper in hypervisors: - if hasattr(hyper, 'servers'): - for server in hyper.servers: - response.append(_server_migrate(cs, server)) - - utils.print_list(response, - ["Server UUID", "Migration Accepted", "Error Message"]) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/instance_action.py b/awx/lib/site-packages/novaclient/v1_1/contrib/instance_action.py deleted file mode 100644 index cddc300125..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/instance_action.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import pprint - -from novaclient import base -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class InstanceActionManager(base.ManagerWithFind): - resource_class = base.Resource - - def get(self, server, request_id): - """ - Get details of an action performed on an instance. - - :param request_id: The request_id of the action to get. - """ - return self._get("/servers/%s/os-instance-actions/%s" % - (base.getid(server), request_id), 'instanceAction') - - def list(self, server): - """ - Get a list of actions performed on an server. - """ - return self._list('/servers/%s/os-instance-actions' % - base.getid(server), 'instanceActions') - - -@utils.arg('server', - metavar='', - help=_('Name or UUID of the server to show an action for.')) -@utils.arg('request_id', - metavar='', - help=_('Request ID of the action to get.')) -def do_instance_action(cs, args): - """Show an action.""" - server = utils.find_resource(cs.servers, args.server) - action_resource = cs.instance_action.get(server, args.request_id) - action = action_resource._info - if 'events' in action: - action['events'] = pprint.pformat(action['events']) - utils.print_dict(action) - - -@utils.arg('server', - metavar='', - help=_('Name or UUID of the server to list actions for.')) -def do_instance_action_list(cs, args): - """List actions on a server.""" - server = utils.find_resource(cs.servers, args.server) - actions = cs.instance_action.list(server) - utils.print_list(actions, - ['Action', 'Request_ID', 'Message', 'Start_Time'], sortby_index=3) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/list_extensions.py b/awx/lib/site-packages/novaclient/v1_1/contrib/list_extensions.py deleted file mode 100644 index 7eb9f16c8a..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/list_extensions.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient import utils - - -class ListExtResource(base.Resource): - @property - def summary(self): - descr = self.description.strip() - if not descr: - return '??' - lines = descr.split("\n") - if len(lines) == 1: - return lines[0] - else: - return lines[0] + "..." - - -class ListExtManager(base.Manager): - resource_class = ListExtResource - - def show_all(self): - return self._list("/extensions", 'extensions') - - -def do_list_extensions(client, _args): - """ - List all the os-api extensions that are available. - """ - extensions = client.list_extensions.show_all() - fields = ["Name", "Summary", "Alias", "Updated"] - utils.print_list(extensions, fields) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/metadata_extensions.py b/awx/lib/site-packages/novaclient/v1_1/contrib/metadata_extensions.py deleted file mode 100644 index 27b864f7a2..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/metadata_extensions.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils -from novaclient.v1_1 import shell - - -@utils.arg('host', - metavar='', - help=_('Name of host.')) -@utils.arg('action', - metavar='', - choices=['set', 'delete'], - help=_("Actions: 'set' or 'delete'")) -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to set or delete (only key is necessary on ' - 'delete)')) -def do_host_meta(cs, args): - """Set or Delete metadata on all instances of a host.""" - hypervisors = cs.hypervisors.search(args.host, servers=True) - for hyper in hypervisors: - metadata = shell._extract_metadata(args) - if hasattr(hyper, 'servers'): - for server in hyper.servers: - if args.action == 'set': - cs.servers.set_meta(server['uuid'], metadata) - elif args.action == 'delete': - cs.servers.delete_meta(server['uuid'], metadata.keys()) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/migrations.py b/awx/lib/site-packages/novaclient/v1_1/contrib/migrations.py deleted file mode 100644 index 16be844abb..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/migrations.py +++ /dev/null @@ -1,87 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -migration interface -""" - -from six.moves.urllib import parse - -from novaclient import base -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class Migration(base.Resource): - def __repr__(self): - return "" % self.id - - -class MigrationManager(base.ManagerWithFind): - resource_class = Migration - - def list(self, host=None, status=None, cell_name=None): - """ - Get a list of migrations. - :param host: (optional) filter migrations by host name. - :param status: (optional) filter migrations by status. - :param cell_name: (optional) filter migrations for a cell. - """ - opts = {} - if host: - opts['host'] = host - if status: - opts['status'] = status - if cell_name: - opts['cell_name'] = cell_name - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - new_opts = sorted(opts.items(), key=lambda x: x[0]) - - query_string = "?%s" % parse.urlencode(new_opts) if new_opts else "" - - return self._list("/os-migrations%s" % query_string, "migrations") - - -@utils.arg('--host', - dest='host', - metavar='', - help=_('Fetch migrations for the given host.')) -@utils.arg('--status', - dest='status', - metavar='', - help=_('Fetch migrations for the given status.')) -@utils.arg('--cell_name', - dest='cell_name', - metavar='', - help=_('Fetch migrations for the given cell_name.')) -def do_migration_list(cs, args): - """Print a list of migrations.""" - _print_migrations(cs.migrations.list(args.host, args.status, - args.cell_name)) - - -def _print_migrations(migrations): - fields = ['Source Node', 'Dest Node', 'Source Compute', 'Dest Compute', - 'Dest Host', 'Status', 'Instance UUID', 'Old Flavor', - 'New Flavor', 'Created At', 'Updated At'] - - def old_flavor(migration): - return migration.old_instance_type_id - - def new_flavor(migration): - return migration.new_instance_type_id - - formatters = {'Old Flavor': old_flavor, 'New Flavor': new_flavor} - - utils.print_list(migrations, fields, formatters) diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/server_external_events.py b/awx/lib/site-packages/novaclient/v1_1/contrib/server_external_events.py deleted file mode 100644 index a45914b55c..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/server_external_events.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2014, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -External event triggering for servers, not to be used by users. -""" - -from novaclient import base - - -class Event(base.Resource): - def __repr__(self): - return "" % self.name - - -class ServerExternalEventManager(base.Manager): - resource_class = Event - - def create(self, events): - """Create one or more server events. - - :param:events: A list of dictionaries containing 'server_uuid', 'name', - 'status', and 'tag' (which may be absent) - """ - - body = {'events': events} - return self._create('/os-server-external-events', body, 'events', - return_raw=True) - - -manager_class = ServerExternalEventManager -name = 'server_external_events' diff --git a/awx/lib/site-packages/novaclient/v1_1/contrib/tenant_networks.py b/awx/lib/site-packages/novaclient/v1_1/contrib/tenant_networks.py deleted file mode 100644 index 8c9b22ebc9..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/contrib/tenant_networks.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from novaclient import base -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class TenantNetwork(base.Resource): - def delete(self): - self.manager.delete(network=self) - - -class TenantNetworkManager(base.ManagerWithFind): - resource_class = base.Resource - - def list(self): - return self._list('/os-tenant-networks', 'networks') - - def get(self, network): - return self._get('/os-tenant-networks/%s' % base.getid(network), - 'network') - - def delete(self, network): - self._delete('/os-tenant-networks/%s' % base.getid(network)) - - def create(self, label, cidr): - body = {'network': {'label': label, 'cidr': cidr}} - return self._create('/os-tenant-networks', body, 'network') - - -@utils.arg('network_id', metavar='', help='ID of network') -def do_net(cs, args): - """ - Show a network - """ - network = cs.tenant_networks.get(args.network_id) - utils.print_dict(network._info) - - -def do_net_list(cs, args): - """ - List networks - """ - networks = cs.tenant_networks.list() - utils.print_list(networks, ['ID', 'Label', 'CIDR']) - - -@utils.arg('label', metavar='', - help=_('Network label (ex. my_new_network)')) -@utils.arg('cidr', metavar='', - help=_('IP block to allocate from (ex. 172.16.0.0/24 or ' - '2001:DB8::/64)')) -def do_net_create(cs, args): - """ - Create a network - """ - network = cs.tenant_networks.create(args.label, args.cidr) - utils.print_dict(network._info) - - -@utils.arg('network_id', metavar='', help='ID of network') -def do_net_delete(cs, args): - """ - Delete a network - """ - cs.tenant_networks.delete(args.network_id) diff --git a/awx/lib/site-packages/novaclient/v1_1/fixed_ips.py b/awx/lib/site-packages/novaclient/v1_1/fixed_ips.py deleted file mode 100644 index 4e7c0e9512..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/fixed_ips.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Fixed IPs interface. -""" - -from novaclient import base - - -class FixedIP(base.Resource): - def __repr__(self): - return "" % self.address - - -class FixedIPsManager(base.Manager): - resource_class = FixedIP - - def get(self, fixed_ip): - """ - Show information for a Fixed IP - - :param fixed_ip: Fixed IP address to get info for - """ - return self._get('/os-fixed-ips/%s' % base.getid(fixed_ip), - "fixed_ip") - - def reserve(self, fixed_ip): - """Reserve a Fixed IP - - :param fixed_ip: Fixed IP address to reserve - """ - body = {"reserve": None} - self.api.client.post('/os-fixed-ips/%s/action' % base.getid(fixed_ip), - body=body) - - def unreserve(self, fixed_ip): - """Unreserve a Fixed IP - - :param fixed_ip: Fixed IP address to unreserve - """ - body = {"unreserve": None} - self.api.client.post('/os-fixed-ips/%s/action' % base.getid(fixed_ip), - body=body) diff --git a/awx/lib/site-packages/novaclient/v1_1/flavor_access.py b/awx/lib/site-packages/novaclient/v1_1/flavor_access.py deleted file mode 100644 index 3b4ce43e63..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/flavor_access.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Flavor access interface.""" - -from novaclient import base -from novaclient.openstack.common.gettextutils import _ - - -class FlavorAccess(base.Resource): - def __repr__(self): - return ("" % - (self.flavor_id, self.tenant_id)) - - -class FlavorAccessManager(base.ManagerWithFind): - """ - Manage :class:`FlavorAccess` resources. - """ - resource_class = FlavorAccess - - def list(self, **kwargs): - if kwargs.get('flavor'): - return self._list_by_flavor(kwargs['flavor']) - elif kwargs.get('tenant'): - return self._list_by_tenant(kwargs['tenant']) - else: - raise NotImplementedError(_('Unknown list options.')) - - def _list_by_flavor(self, flavor): - return self._list('/flavors/%s/os-flavor-access' % base.getid(flavor), - 'flavor_access') - - def _list_by_tenant(self, tenant): - """Print flavor list shared with the given tenant.""" - # TODO(uni): need to figure out a proper URI for list_by_tenant - # since current API already provided current tenant_id information - raise NotImplementedError(_('Sorry, query by tenant not supported.')) - - def add_tenant_access(self, flavor, tenant): - """Add a tenant to the given flavor access list.""" - info = {'tenant': tenant} - return self._action('addTenantAccess', flavor, info) - - def remove_tenant_access(self, flavor, tenant): - """Remove a tenant from the given flavor access list.""" - info = {'tenant': tenant} - return self._action('removeTenantAccess', flavor, info) - - def _action(self, action, flavor, info, **kwargs): - """Perform a flavor action.""" - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/flavors/%s/action' % base.getid(flavor) - _resp, body = self.api.client.post(url, body=body) - - return [self.resource_class(self, res) - for res in body['flavor_access']] diff --git a/awx/lib/site-packages/novaclient/v1_1/flavors.py b/awx/lib/site-packages/novaclient/v1_1/flavors.py deleted file mode 100644 index e66e0b9e23..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/flavors.py +++ /dev/null @@ -1,211 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Flavor interface. -""" - -from oslo.utils import strutils -from six.moves.urllib import parse - -from novaclient import base -from novaclient import exceptions -from novaclient.openstack.common.gettextutils import _ -from novaclient import utils - - -class Flavor(base.Resource): - """ - A flavor is an available hardware configuration for a server. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.name - - @property - def ephemeral(self): - """ - Provide a user-friendly accessor to OS-FLV-EXT-DATA:ephemeral - """ - return self._info.get("OS-FLV-EXT-DATA:ephemeral", 'N/A') - - @property - def is_public(self): - """ - Provide a user-friendly accessor to os-flavor-access:is_public - """ - return self._info.get("os-flavor-access:is_public", 'N/A') - - def get_keys(self): - """ - Get extra specs from a flavor. - - :param flavor: The :class:`Flavor` to get extra specs from - """ - _resp, body = self.manager.api.client.get( - "/flavors/%s/os-extra_specs" % - base.getid(self)) - return body["extra_specs"] - - def set_keys(self, metadata): - """ - Set extra specs on a flavor. - - :param flavor: The :class:`Flavor` to set extra spec on - :param metadata: A dict of key/value pairs to be set - """ - utils.validate_flavor_metadata_keys(metadata.keys()) - - body = {'extra_specs': metadata} - return self.manager._create( - "/flavors/%s/os-extra_specs" % base.getid(self), - body, - "extra_specs", - return_raw=True) - - def unset_keys(self, keys): - """ - Unset extra specs on a flavor. - - :param flavor: The :class:`Flavor` to unset extra spec on - :param keys: A list of keys to be unset - """ - for k in keys: - self.manager._delete( - "/flavors/%s/os-extra_specs/%s" % ( - base.getid(self), k)) - - def delete(self): - """ - Delete this flavor. - """ - self.manager.delete(self) - - -class FlavorManager(base.ManagerWithFind): - """ - Manage :class:`Flavor` resources. - """ - resource_class = Flavor - is_alphanum_id_allowed = True - - def list(self, detailed=True, is_public=True): - """ - Get a list of all flavors. - - :rtype: list of :class:`Flavor`. - """ - qparams = {} - # is_public is ternary - None means give all flavors. - # By default Nova assumes True and gives admins public flavors - # and flavors from their own projects only. - if not is_public: - qparams['is_public'] = is_public - query_string = "?%s" % parse.urlencode(qparams) if qparams else "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/flavors%s%s" % (detail, query_string), "flavors") - - def get(self, flavor): - """ - Get a specific flavor. - - :param flavor: The ID of the :class:`Flavor` to get. - :rtype: :class:`Flavor` - """ - return self._get("/flavors/%s" % base.getid(flavor), "flavor") - - def delete(self, flavor): - """ - Delete a specific flavor. - - :param flavor: The ID of the :class:`Flavor` to get. - """ - self._delete("/flavors/%s" % base.getid(flavor)) - - def _build_body(self, name, ram, vcpus, disk, id, swap, - ephemeral, rxtx_factor, is_public): - return { - "flavor": { - "name": name, - "ram": ram, - "vcpus": vcpus, - "disk": disk, - "id": id, - "swap": swap, - "OS-FLV-EXT-DATA:ephemeral": ephemeral, - "rxtx_factor": rxtx_factor, - "os-flavor-access:is_public": is_public, - } - } - - def create(self, name, ram, vcpus, disk, flavorid="auto", - ephemeral=0, swap=0, rxtx_factor=1.0, is_public=True): - """ - Create a flavor. - - :param name: Descriptive name of the flavor - :param ram: Memory in MB for the flavor - :param vcpus: Number of VCPUs for the flavor - :param disk: Size of local disk in GB - :param flavorid: ID for the flavor (optional). You can use the reserved - value ``"auto"`` to have Nova generate a UUID for the - flavor in cases where you cannot simply pass ``None``. - :param swap: Swap space in MB - :param rxtx_factor: RX/TX factor - :rtype: :class:`Flavor` - """ - - try: - ram = int(ram) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Ram must be an integer.")) - try: - vcpus = int(vcpus) - except (TypeError, ValueError): - raise exceptions.CommandError(_("VCPUs must be an integer.")) - try: - disk = int(disk) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Disk must be an integer.")) - - if flavorid == "auto": - flavorid = None - - try: - swap = int(swap) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Swap must be an integer.")) - try: - ephemeral = int(ephemeral) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Ephemeral must be an integer.")) - try: - rxtx_factor = float(rxtx_factor) - except (TypeError, ValueError): - raise exceptions.CommandError(_("rxtx_factor must be a float.")) - - try: - is_public = strutils.bool_from_string(is_public, True) - except Exception: - raise exceptions.CommandError(_("is_public must be a boolean.")) - - body = self._build_body(name, ram, vcpus, disk, flavorid, swap, - ephemeral, rxtx_factor, is_public) - - return self._create("/flavors", body, "flavor") diff --git a/awx/lib/site-packages/novaclient/v1_1/floating_ip_dns.py b/awx/lib/site-packages/novaclient/v1_1/floating_ip_dns.py deleted file mode 100644 index 449c7e11e0..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/floating_ip_dns.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2011 Andrew Bogott for The Wikimedia Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from six.moves.urllib import parse - -from novaclient import base - - -def _quote_domain(domain): - """Special quoting rule for placing domain names on a url line. - - Domain names tend to have .'s in them. Urllib doesn't quote dots, - but Routes tends to choke on them, so we need an extra level of - by-hand quoting here. - """ - return parse.quote(domain.replace('.', '%2E')) - - -class FloatingIPDNSDomain(base.Resource): - def delete(self): - self.manager.delete(self.domain) - - def create(self): - if self.scope == 'public': - self.manager.create_public(self.domain, self.project) - else: - self.manager.create_private(self.domain, self.availability_zone) - - def get(self): - entries = self.manager.domains() - for entry in entries: - if entry.get('domain') == self.domain: - return entry - - return None - - -class FloatingIPDNSDomainManager(base.Manager): - resource_class = FloatingIPDNSDomain - - def domains(self): - """Return the list of available dns domains.""" - return self._list("/os-floating-ip-dns", "domain_entries") - - def create_private(self, fqdomain, availability_zone): - """Add or modify a private DNS domain.""" - body = {'domain_entry': - {'scope': 'private', - 'availability_zone': availability_zone}} - return self._update('/os-floating-ip-dns/%s' % _quote_domain(fqdomain), - body, - 'domain_entry') - - def create_public(self, fqdomain, project): - """Add or modify a public DNS domain.""" - body = {'domain_entry': - {'scope': 'public', - 'project': project}} - - return self._update('/os-floating-ip-dns/%s' % _quote_domain(fqdomain), - body, - 'domain_entry') - - def delete(self, fqdomain): - """Delete the specified domain.""" - self._delete("/os-floating-ip-dns/%s" % _quote_domain(fqdomain)) - - -class FloatingIPDNSEntry(base.Resource): - def delete(self): - self.manager.delete(self.name, self.domain) - - def create(self): - self.manager.create(self.domain, self.name, - self.ip, self.dns_type) - - def get(self): - return self.manager.get(self.domain, self.name) - - -class FloatingIPDNSEntryManager(base.Manager): - resource_class = FloatingIPDNSEntry - - def get(self, domain, name): - """Return a list of entries for the given domain and ip or name.""" - return self._get("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name), - "dns_entry") - - def get_for_ip(self, domain, ip): - """Return a list of entries for the given domain and ip or name.""" - qparams = {'ip': ip} - params = "?%s" % parse.urlencode(qparams) - - return self._list("/os-floating-ip-dns/%s/entries%s" % - (_quote_domain(domain), params), - "dns_entries") - - def create(self, domain, name, ip, dns_type): - """Add a new DNS entry.""" - body = {'dns_entry': - {'ip': ip, - 'dns_type': dns_type}} - - return self._update("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name), - body, - "dns_entry") - - def modify_ip(self, domain, name, ip): - """Add a new DNS entry.""" - body = {'dns_entry': - {'ip': ip, - 'dns_type': 'A'}} - - return self._update("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name), - body, - "dns_entry") - - def delete(self, domain, name): - """Delete entry specified by name and domain.""" - self._delete("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name)) diff --git a/awx/lib/site-packages/novaclient/v1_1/floating_ip_pools.py b/awx/lib/site-packages/novaclient/v1_1/floating_ip_pools.py deleted file mode 100644 index 7666bd57f8..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/floating_ip_pools.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class FloatingIPPool(base.Resource): - def __repr__(self): - return "" % self.name - - -class FloatingIPPoolManager(base.ManagerWithFind): - resource_class = FloatingIPPool - - def list(self): - """ - Retrieve a list of all floating ip pools. - """ - return self._list('/os-floating-ip-pools', 'floating_ip_pools') diff --git a/awx/lib/site-packages/novaclient/v1_1/floating_ips.py b/awx/lib/site-packages/novaclient/v1_1/floating_ips.py deleted file mode 100644 index 54979371f3..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/floating_ips.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class FloatingIP(base.Resource): - def delete(self): - """ - Delete this floating ip - """ - self.manager.delete(self) - - -class FloatingIPManager(base.ManagerWithFind): - resource_class = FloatingIP - - def list(self, all_tenants=False): - """ - List floating ips - """ - url = '/os-floating-ips' - if all_tenants: - url += '?all_tenants=1' - return self._list(url, "floating_ips") - - def create(self, pool=None): - """ - Create (allocate) a floating ip for a tenant - """ - return self._create("/os-floating-ips", {'pool': pool}, "floating_ip") - - def delete(self, floating_ip): - """ - Delete (deallocate) a floating ip for a tenant - - :param floating_ip: The floating ip address to delete. - """ - self._delete("/os-floating-ips/%s" % base.getid(floating_ip)) - - def get(self, floating_ip): - """ - Retrieve a floating ip - """ - return self._get("/os-floating-ips/%s" % base.getid(floating_ip), - "floating_ip") diff --git a/awx/lib/site-packages/novaclient/v1_1/floating_ips_bulk.py b/awx/lib/site-packages/novaclient/v1_1/floating_ips_bulk.py deleted file mode 100644 index fb59a19e74..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/floating_ips_bulk.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Bulk Floating IPs interface -""" -from novaclient import base - - -class FloatingIP(base.Resource): - def __repr__(self): - return "" % self.address - - -class FloatingIPBulkManager(base.ManagerWithFind): - resource_class = FloatingIP - - def list(self, host=None): - """ - List all floating IPs - """ - if host is None: - return self._list('/os-floating-ips-bulk', 'floating_ip_info') - else: - return self._list('/os-floating-ips-bulk/%s' % host, - 'floating_ip_info') - - def create(self, ip_range, pool=None, interface=None): - """ - Create floating IPs by range - """ - body = {"floating_ips_bulk_create": {'ip_range': ip_range}} - if pool is not None: - body['floating_ips_bulk_create']['pool'] = pool - if interface is not None: - body['floating_ips_bulk_create']['interface'] = interface - - return self._create('/os-floating-ips-bulk', body, - 'floating_ips_bulk_create') - - def delete(self, ip_range): - """ - Delete floating IPs by range - """ - body = {"ip_range": ip_range} - return self._update('/os-floating-ips-bulk/delete', body) diff --git a/awx/lib/site-packages/novaclient/v1_1/fping.py b/awx/lib/site-packages/novaclient/v1_1/fping.py deleted file mode 100644 index ac958d4c6f..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/fping.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Fping interface. -""" - -from novaclient import base - - -class Fping(base.Resource): - """ - A server to fping. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.id - - -class FpingManager(base.ManagerWithFind): - """ - Manage :class:`Fping` resources. - """ - resource_class = Fping - - def list(self, all_tenants=False, include=[], exclude=[]): - """ - Fping all servers. - - :rtype: list of :class:`Fping`. - """ - params = [] - if all_tenants: - params.append("all_tenants=1") - if include: - params.append("include=%s" % ",".join(include)) - elif exclude: - params.append("exclude=%s" % ",".join(exclude)) - uri = "/os-fping" - if params: - uri = "%s?%s" % (uri, "&".join(params)) - return self._list(uri, "servers") - - def get(self, server): - """ - Fping a specific server. - - :param network: ID of the server to fping. - :rtype: :class:`Fping` - """ - return self._get("/os-fping/%s" % base.getid(server), "server") diff --git a/awx/lib/site-packages/novaclient/v1_1/hosts.py b/awx/lib/site-packages/novaclient/v1_1/hosts.py deleted file mode 100644 index af1756ad2c..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/hosts.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -host interface (1.1 extension). -""" -from novaclient import base - - -class Host(base.Resource): - def __repr__(self): - return "" % self.host - - def _add_details(self, info): - dico = 'resource' in info and info['resource'] or info - for (k, v) in dico.items(): - setattr(self, k, v) - - def update(self, values): - return self.manager.update(self.host, values) - - def startup(self): - return self.manager.host_action(self.host, 'startup') - - def shutdown(self): - return self.manager.host_action(self.host, 'shutdown') - - def reboot(self): - return self.manager.host_action(self.host, 'reboot') - - -class HostManager(base.ManagerWithFind): - resource_class = Host - - def get(self, host): - """ - Describes cpu/memory/hdd info for host. - - :param host: destination host name. - """ - return self._list("/os-hosts/%s" % host, "host") - - def update(self, host, values): - """Update status or maintenance mode for the host.""" - return self._update("/os-hosts/%s" % host, values) - - def host_action(self, host, action): - """Perform an action on a host.""" - url = '/os-hosts/{0}/{1}'.format(host, action) - return self.api.client.get(url) - - def list(self, zone=None): - url = '/os-hosts' - if zone: - url = '/os-hosts?zone=%s' % zone - return self._list(url, "hosts") - - list_all = list diff --git a/awx/lib/site-packages/novaclient/v1_1/hypervisors.py b/awx/lib/site-packages/novaclient/v1_1/hypervisors.py deleted file mode 100644 index 4a4f2b93a8..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/hypervisors.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Hypervisors interface (1.1 extension). -""" - -from six.moves.urllib import parse - -from novaclient import base - - -class Hypervisor(base.Resource): - NAME_ATTR = 'hypervisor_hostname' - - def __repr__(self): - return "" % self.id - - -class HypervisorManager(base.ManagerWithFind): - resource_class = Hypervisor - - def list(self, detailed=True): - """ - Get a list of hypervisors. - """ - detail = "" - if detailed: - detail = "/detail" - return self._list('/os-hypervisors%s' % detail, 'hypervisors') - - def search(self, hypervisor_match, servers=False): - """ - Get a list of matching hypervisors. - - :param servers: If True, server information is also retrieved. - """ - target = 'servers' if servers else 'search' - url = ('/os-hypervisors/%s/%s' % - (parse.quote(hypervisor_match, safe=''), target)) - return self._list(url, 'hypervisors') - - def get(self, hypervisor): - """ - Get a specific hypervisor. - """ - return self._get("/os-hypervisors/%s" % base.getid(hypervisor), - "hypervisor") - - def uptime(self, hypervisor): - """ - Get the uptime for a specific hypervisor. - """ - return self._get("/os-hypervisors/%s/uptime" % base.getid(hypervisor), - "hypervisor") - - def statistics(self): - """ - Get hypervisor statistics over all compute nodes. - """ - return self._get("/os-hypervisors/statistics", "hypervisor_statistics") diff --git a/awx/lib/site-packages/novaclient/v1_1/images.py b/awx/lib/site-packages/novaclient/v1_1/images.py deleted file mode 100644 index f355b894fe..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/images.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Image interface. -""" - -from six.moves.urllib import parse - -from novaclient import base - - -class Image(base.Resource): - """ - An image is a collection of files used to create or rebuild a server. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.name - - def delete(self): - """ - Delete this image. - """ - self.manager.delete(self) - - -class ImageManager(base.ManagerWithFind): - """ - Manage :class:`Image` resources. - """ - resource_class = Image - - def get(self, image): - """ - Get an image. - - :param image: The ID of the image to get. - :rtype: :class:`Image` - """ - return self._get("/images/%s" % base.getid(image), "image") - - def list(self, detailed=True, limit=None): - """ - Get a list of all images. - - :rtype: list of :class:`Image` - :param limit: maximum number of images to return. - """ - params = {} - detail = '' - if detailed: - detail = '/detail' - if limit: - params['limit'] = int(limit) - query = '?%s' % parse.urlencode(params) if params else '' - return self._list('/images%s%s' % (detail, query), 'images') - - def delete(self, image): - """ - Delete an image. - - It should go without saying that you can't delete an image - that you didn't create. - - :param image: The :class:`Image` (or its ID) to delete. - """ - self._delete("/images/%s" % base.getid(image)) - - def set_meta(self, image, metadata): - """ - Set an images metadata - - :param image: The :class:`Image` to add metadata to - :param metadata: A dict of metadata to add to the image - """ - body = {'metadata': metadata} - return self._create("/images/%s/metadata" % base.getid(image), body, - "metadata") - - def delete_meta(self, image, keys): - """ - Delete metadata from an image - - :param image: The :class:`Image` to delete metadata - :param keys: A list of metadata keys to delete from the image - """ - for k in keys: - self._delete("/images/%s/metadata/%s" % (base.getid(image), k)) diff --git a/awx/lib/site-packages/novaclient/v1_1/keypairs.py b/awx/lib/site-packages/novaclient/v1_1/keypairs.py deleted file mode 100644 index 96caff6189..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/keypairs.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Keypair interface (1.1 extension). -""" - -from novaclient import base - - -class Keypair(base.Resource): - """ - A keypair is a ssh key that can be injected into a server on launch. - """ - - def __repr__(self): - return "" % self.id - - def _add_details(self, info): - dico = 'keypair' in info and \ - info['keypair'] or info - for (k, v) in dico.items(): - # NOTE(rpodolyaka): keypair name allows us to uniquely identify - # a specific keypair, while its id attribute - # is nothing more than an implementation - # detail. We can safely omit the id attribute - # here to ensure setattr() won't raise - # AttributeError trying to set read-only - # property id - if k != 'id': - setattr(self, k, v) - - @property - def id(self): - return self.name - - def delete(self): - self.manager.delete(self) - - -class KeypairManager(base.ManagerWithFind): - resource_class = Keypair - keypair_prefix = "os-keypairs" - is_alphanum_id_allowed = True - - def get(self, keypair): - """ - Get a keypair. - - :param keypair: The ID of the keypair to get. - :rtype: :class:`Keypair` - """ - return self._get("/%s/%s" % (self.keypair_prefix, base.getid(keypair)), - "keypair") - - def create(self, name, public_key=None): - """ - Create a keypair - - :param name: name for the keypair to create - :param public_key: existing public key to import - """ - body = {'keypair': {'name': name}} - if public_key: - body['keypair']['public_key'] = public_key - return self._create('/%s' % self.keypair_prefix, body, 'keypair') - - def delete(self, key): - """ - Delete a keypair - - :param key: The :class:`Keypair` (or its ID) to delete. - """ - self._delete('/%s/%s' % (self.keypair_prefix, base.getid(key))) - - def list(self): - """ - Get a list of keypairs. - """ - return self._list('/%s' % self.keypair_prefix, 'keypairs') diff --git a/awx/lib/site-packages/novaclient/v1_1/limits.py b/awx/lib/site-packages/novaclient/v1_1/limits.py deleted file mode 100644 index 46d77def81..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/limits.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from six.moves.urllib import parse - -from novaclient import base - - -class Limits(base.Resource): - """A collection of RateLimit and AbsoluteLimit objects.""" - - def __repr__(self): - return "" - - @property - def absolute(self): - for (name, value) in self._info['absolute'].items(): - yield AbsoluteLimit(name, value) - - @property - def rate(self): - for group in self._info['rate']: - uri = group['uri'] - regex = group['regex'] - for rate in group['limit']: - yield RateLimit(rate['verb'], uri, regex, rate['value'], - rate['remaining'], rate['unit'], - rate['next-available']) - - -class RateLimit(object): - """Data model that represents a flattened view of a single rate limit.""" - - def __init__(self, verb, uri, regex, value, remain, - unit, next_available): - self.verb = verb - self.uri = uri - self.regex = regex - self.value = value - self.remain = remain - self.unit = unit - self.next_available = next_available - - def __eq__(self, other): - return self.uri == other.uri \ - and self.regex == other.regex \ - and self.value == other.value \ - and self.verb == other.verb \ - and self.remain == other.remain \ - and self.unit == other.unit \ - and self.next_available == other.next_available - - def __repr__(self): - return "" % (self.verb, self.uri) - - -class AbsoluteLimit(object): - """Data model that represents a single absolute limit.""" - - def __init__(self, name, value): - self.name = name - self.value = value - - def __eq__(self, other): - return self.value == other.value and self.name == other.name - - def __repr__(self): - return "" % (self.name) - - -class LimitsManager(base.Manager): - """Manager object used to interact with limits resource.""" - - resource_class = Limits - - def get(self, reserved=False, tenant_id=None): - """ - Get a specific extension. - - :rtype: :class:`Limits` - """ - opts = {} - if reserved: - opts['reserved'] = 1 - if tenant_id: - opts['tenant_id'] = tenant_id - query_string = "?%s" % parse.urlencode(opts) if opts else "" - - return self._get("/limits%s" % query_string, "limits") diff --git a/awx/lib/site-packages/novaclient/v1_1/networks.py b/awx/lib/site-packages/novaclient/v1_1/networks.py deleted file mode 100644 index a275028689..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/networks.py +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Network interface. -""" - -from novaclient import base -from novaclient import exceptions -from novaclient.openstack.common.gettextutils import _ - - -class Network(base.Resource): - """ - A network. - """ - HUMAN_ID = True - NAME_ATTR = "label" - - def __repr__(self): - return "" % self.label - - def delete(self): - self.manager.delete(self) - - -class NetworkManager(base.ManagerWithFind): - """ - Manage :class:`Network` resources. - """ - resource_class = Network - - def list(self): - """ - Get a list of all networks. - - :rtype: list of :class:`Network`. - """ - return self._list("/os-networks", "networks") - - def get(self, network): - """ - Get a specific network. - - :param network: The ID of the :class:`Network` to get. - :rtype: :class:`Network` - """ - return self._get("/os-networks/%s" % base.getid(network), - "network") - - def delete(self, network): - """ - Delete a specific network. - - :param network: The ID of the :class:`Network` to delete. - """ - self._delete("/os-networks/%s" % base.getid(network)) - - def create(self, **kwargs): - """ - Create (allocate) a network. The following parameters are - optional except for label; cidr or cidr_v6 must be specified, too. - - :param label: str - :param bridge: str - :param bridge_interface: str - :param cidr: str - :param cidr_v6: str - :param dns1: str - :param dns2: str - :param fixed_cidr: str - :param gateway: str - :param gateway_v6: str - :param multi_host: str - :param priority: str - :param project_id: str - :param vlan: int - :param vlan_start: int - :param vpn_start: int - :param mtu: int - :param enable_dhcp: int - :param dhcp_server: str - :param share_address: int - :param allowed_start: str - :param allowed_end: str - - :rtype: object of :class:`Network` - """ - body = {"network": kwargs} - return self._create('/os-networks', body, 'network') - - def disassociate(self, network, disassociate_host=True, - disassociate_project=True): - """ - Disassociate a specific network from project and/or host. - - :param network: The ID of the :class:`Network`. - :param disassociate_host: Whether to disassociate the host - :param disassociate_project: Whether to disassociate the project - """ - if disassociate_host and disassociate_project: - body = {"disassociate": None} - elif disassociate_project: - body = {"disassociate_project": None} - elif disassociate_host: - body = {"disassociate_host": None} - else: - raise exceptions.CommandError( - _("Must disassociate either host or project or both")) - - self.api.client.post("/os-networks/%s/action" % - base.getid(network), body=body) - - def associate_host(self, network, host): - """ - Associate a specific network with a host. - - :param network: The ID of the :class:`Network`. - :param host: The name of the host to associate the network with - """ - self.api.client.post("/os-networks/%s/action" % - base.getid(network), - body={"associate_host": host}) - - def associate_project(self, network): - """ - Associate a specific network with a project. - - The project is defined by the project authenticated against - - :param network: The ID of the :class:`Network`. - """ - self.api.client.post("/os-networks/add", body={"id": network}) - - def add(self, network=None): - """ - Associates the current project with a network. Network can be chosen - automatically or provided explicitly. - - :param network: The ID of the :class:`Network` to associate (optional). - """ - self.api.client.post( - "/os-networks/add", - body={"id": base.getid(network) if network else None}) diff --git a/awx/lib/site-packages/novaclient/v1_1/quota_classes.py b/awx/lib/site-packages/novaclient/v1_1/quota_classes.py deleted file mode 100644 index 4a38a970c2..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/quota_classes.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class QuotaClassSet(base.Resource): - - def update(self, *args, **kwargs): - return self.manager.update(self.id, *args, **kwargs) - - -class QuotaClassSetManager(base.Manager): - resource_class = QuotaClassSet - - def get(self, class_name): - return self._get("/os-quota-class-sets/%s" % (class_name), - "quota_class_set") - - def _update_body(self, **kwargs): - return {'quota_class_set': kwargs} - - def update(self, class_name, **kwargs): - body = self._update_body(**kwargs) - - for key in list(body['quota_class_set']): - if body['quota_class_set'][key] is None: - body['quota_class_set'].pop(key) - - return self._update('/os-quota-class-sets/%s' % (class_name), - body, - 'quota_class_set') diff --git a/awx/lib/site-packages/novaclient/v1_1/quotas.py b/awx/lib/site-packages/novaclient/v1_1/quotas.py deleted file mode 100644 index cd16042b44..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/quotas.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class QuotaSet(base.Resource): - - @property - def id(self): - """QuotaSet does not have a 'id' attribute but base.Resource needs it - to self-refresh and QuotaSet is indexed by tenant_id. - """ - return self.tenant_id - - def update(self, *args, **kwargs): - return self.manager.update(self.tenant_id, *args, **kwargs) - - -class QuotaSetManager(base.Manager): - resource_class = QuotaSet - - def get(self, tenant_id, user_id=None): - if hasattr(tenant_id, 'tenant_id'): - tenant_id = tenant_id.tenant_id - if user_id: - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - else: - url = '/os-quota-sets/%s' % tenant_id - return self._get(url, "quota_set") - - def _update_body(self, tenant_id, **kwargs): - kwargs['tenant_id'] = tenant_id - return {'quota_set': kwargs} - - def update(self, tenant_id, **kwargs): - - user_id = kwargs.pop('user_id', None) - body = self._update_body(tenant_id, **kwargs) - - for key in list(body['quota_set']): - if body['quota_set'][key] is None: - body['quota_set'].pop(key) - - if user_id: - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - else: - url = '/os-quota-sets/%s' % tenant_id - return self._update(url, body, 'quota_set') - - def defaults(self, tenant_id): - return self._get('/os-quota-sets/%s/defaults' % tenant_id, - 'quota_set') - - def delete(self, tenant_id, user_id=None): - if user_id: - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - else: - url = '/os-quota-sets/%s' % tenant_id - self._delete(url) diff --git a/awx/lib/site-packages/novaclient/v1_1/security_group_default_rules.py b/awx/lib/site-packages/novaclient/v1_1/security_group_default_rules.py deleted file mode 100644 index 5208cb0612..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/security_group_default_rules.py +++ /dev/null @@ -1,81 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Security group default rules interface. -""" - -from novaclient import base -from novaclient import exceptions -from novaclient.openstack.common.gettextutils import _ - - -class SecurityGroupDefaultRule(base.Resource): - def __str__(self): - return str(self.id) - - def delete(self): - self.manager.delete(self) - - -class SecurityGroupDefaultRuleManager(base.Manager): - resource_class = SecurityGroupDefaultRule - - def create(self, ip_protocol=None, from_port=None, to_port=None, - cidr=None): - """ - Create a security group default rule - - :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp' - :param from_port: Source port - :param to_port: Destination port - :param cidr: Destination IP address(es) in CIDR notation - """ - - try: - from_port = int(from_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("From port must be an integer.")) - try: - to_port = int(to_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("To port must be an integer.")) - if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']: - raise exceptions.CommandError(_("Ip protocol must be 'tcp', 'udp'" - ", or 'icmp'.")) - - body = {"security_group_default_rule": { - "ip_protocol": ip_protocol, - "from_port": from_port, - "to_port": to_port, - "cidr": cidr}} - - return self._create('/os-security-group-default-rules', body, - 'security_group_default_rule') - - def delete(self, rule): - """ - Delete a security group default rule - - :param rule: The security group default rule to delete (ID or Class) - """ - self._delete('/os-security-group-default-rules/%s' % base.getid(rule)) - - def list(self): - """ - Get a list of all security group default rules - - :rtype: list of :class:`SecurityGroupDefaultRule` - """ - - return self._list('/os-security-group-default-rules', - 'security_group_default_rules') diff --git a/awx/lib/site-packages/novaclient/v1_1/security_group_rules.py b/awx/lib/site-packages/novaclient/v1_1/security_group_rules.py deleted file mode 100644 index f1348920af..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/security_group_rules.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Security group rules interface (1.1 extension). -""" - -from novaclient import base -from novaclient import exceptions -from novaclient.openstack.common.gettextutils import _ - - -class SecurityGroupRule(base.Resource): - def __str__(self): - return str(self.id) - - def delete(self): - self.manager.delete(self) - - -class SecurityGroupRuleManager(base.Manager): - resource_class = SecurityGroupRule - - def create(self, parent_group_id, ip_protocol=None, from_port=None, - to_port=None, cidr=None, group_id=None): - """ - Create a security group rule - - :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp' - :param from_port: Source port - :param to_port: Destination port - :param cidr: Destination IP address(es) in CIDR notation - :param group_id: Security group id (int) - :param parent_group_id: Parent security group id (int) - """ - - try: - from_port = int(from_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("From port must be an integer.")) - try: - to_port = int(to_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("To port must be an integer.")) - if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']: - raise exceptions.CommandError(_("Ip protocol must be 'tcp', 'udp'" - ", or 'icmp'.")) - - body = {"security_group_rule": { - "ip_protocol": ip_protocol, - "from_port": from_port, - "to_port": to_port, - "cidr": cidr, - "group_id": group_id, - "parent_group_id": parent_group_id}} - - return self._create('/os-security-group-rules', body, - 'security_group_rule') - - def delete(self, rule): - """ - Delete a security group rule - - :param rule: The security group rule to delete (ID or Class) - """ - self._delete('/os-security-group-rules/%s' % base.getid(rule)) diff --git a/awx/lib/site-packages/novaclient/v1_1/security_groups.py b/awx/lib/site-packages/novaclient/v1_1/security_groups.py deleted file mode 100644 index 40d1e7ff72..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/security_groups.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Security group interface (1.1 extension). -""" - -import six -from six.moves.urllib import parse - -from novaclient import base - - -class SecurityGroup(base.Resource): - def __str__(self): - return str(self.id) - - def delete(self): - self.manager.delete(self) - - def update(self): - self.manager.update(self) - - -class SecurityGroupManager(base.ManagerWithFind): - resource_class = SecurityGroup - - def create(self, name, description): - """ - Create a security group - - :param name: name for the security group to create - :param description: description of the security group - :rtype: the security group object - """ - body = {"security_group": {"name": name, 'description': description}} - return self._create('/os-security-groups', body, 'security_group') - - def update(self, group, name, description): - """ - Update a security group - - :param group: The security group to update (group or ID) - :param name: name for the security group to update - :param description: description for the security group to update - :rtype: the security group object - """ - body = {"security_group": {"name": name, 'description': description}} - return self._update('/os-security-groups/%s' % base.getid(group), - body, 'security_group') - - def delete(self, group): - """ - Delete a security group - - :param group: The security group to delete (group or ID) - :rtype: None - """ - self._delete('/os-security-groups/%s' % base.getid(group)) - - def get(self, group_id): - """ - Get a security group - - :param group_id: The security group to get by ID - :rtype: :class:`SecurityGroup` - """ - return self._get('/os-security-groups/%s' % group_id, - 'security_group') - - def list(self, search_opts=None): - """ - Get a list of all security_groups - - :rtype: list of :class:`SecurityGroup` - """ - search_opts = search_opts or {} - - qparams = dict((k, v) for (k, v) in six.iteritems(search_opts) if v) - - query_string = '?%s' % parse.urlencode(qparams) if qparams else '' - - return self._list('/os-security-groups%s' % query_string, - 'security_groups') diff --git a/awx/lib/site-packages/novaclient/v1_1/server_groups.py b/awx/lib/site-packages/novaclient/v1_1/server_groups.py deleted file mode 100644 index be6ff8eefb..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/server_groups.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2014 VMware, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Server group interface. -""" - -from novaclient import base - - -class ServerGroup(base.Resource): - """ - A server group. - """ - NAME_ATTR = 'server_group_name' - - def __repr__(self): - return '' % self.id - - def delete(self): - self.manager.delete(self) - - -class ServerGroupsManager(base.ManagerWithFind): - """ - Manage :class:`ServerGroup` resources. - """ - resource_class = ServerGroup - - def list(self): - """Get a list of all server groups. - - :rtype: list of :class:`ServerGroup`. - """ - return self._list('/os-server-groups', 'server_groups') - - def get(self, id): - """Get a specific server group. - - :param id: The ID of the :class:`ServerGroup` to get. - :rtype: :class:`ServerGroup` - """ - return self._get('/os-server-groups/%s' % id, - 'server_group') - - def delete(self, id): - """Delete a specific server group. - - :param id: The ID of the :class:`ServerGroup` to delete. - """ - self._delete('/os-server-groups/%s' % id) - - def create(self, **kwargs): - """Create (allocate) a server group. - - :rtype: list of :class:`ServerGroup` - """ - body = {'server_group': kwargs} - return self._create('/os-server-groups', body, 'server_group') diff --git a/awx/lib/site-packages/novaclient/v1_1/servers.py b/awx/lib/site-packages/novaclient/v1_1/servers.py deleted file mode 100644 index 38bde8c620..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/servers.py +++ /dev/null @@ -1,1240 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Server interface. -""" - -import base64 - -from oslo.utils import encodeutils -import six -from six.moves.urllib import parse - -from novaclient import base -from novaclient import crypto -from novaclient.openstack.common.gettextutils import _ -from novaclient.v1_1 import security_groups - - -REBOOT_SOFT, REBOOT_HARD = 'SOFT', 'HARD' - - -class Server(base.Resource): - HUMAN_ID = True - - def __repr__(self): - return '' % getattr(self, 'name', 'unknown-name') - - def delete(self): - """ - Delete (i.e. shut down and delete the image) this server. - """ - self.manager.delete(self) - - def update(self, name=None): - """ - Update the name for this server. - - :param name: Update the server's name. - """ - self.manager.update(self, name=name) - - def get_console_output(self, length=None): - """ - Get text console log output from Server. - - :param length: The number of lines you would like to retrieve (as int) - """ - return self.manager.get_console_output(self, length) - - def get_vnc_console(self, console_type): - """ - Get vnc console for a Server. - - :param console_type: Type of console ('novnc' or 'xvpvnc') - """ - return self.manager.get_vnc_console(self, console_type) - - def get_spice_console(self, console_type): - """ - Get spice console for a Server. - - :param console_type: Type of console ('spice-html5') - """ - return self.manager.get_spice_console(self, console_type) - - def get_rdp_console(self, console_type): - """ - Get rdp console for a Server. - - :param console_type: Type of console ('rdp-html5') - """ - return self.manager.get_rdp_console(self, console_type) - - def get_serial_console(self, console_type): - """ - Get serial console for a Server. - - :param console_type: Type of console ('serial') - """ - return self.manager.get_serial_console(self, console_type) - - def get_password(self, private_key=None): - """ - Get password for a Server. - - Returns the clear password of an instance if private_key is - provided, returns the ciphered password otherwise. - - :param private_key: Path to private key file for decryption - (optional) - """ - return self.manager.get_password(self, private_key) - - def clear_password(self): - """ - Get password for a Server. - - """ - return self.manager.clear_password(self) - - def add_fixed_ip(self, network_id): - """ - Add an IP address on a network. - - :param network_id: The ID of the network the IP should be on. - """ - self.manager.add_fixed_ip(self, network_id) - - def add_floating_ip(self, address, fixed_address=None): - """ - Add floating IP to an instance - - :param address: The ip address or FloatingIP to add to the instance - :param fixed_address: The fixedIP address the FloatingIP is to be - associated with (optional) - """ - self.manager.add_floating_ip(self, address, fixed_address) - - def remove_floating_ip(self, address): - """ - Remove floating IP from an instance - - :param address: The ip address or FloatingIP to remove - """ - self.manager.remove_floating_ip(self, address) - - def stop(self): - """ - Stop -- Stop the running server. - """ - self.manager.stop(self) - - def force_delete(self): - """ - Force delete -- Force delete a server. - """ - self.manager.force_delete(self) - - def restore(self): - """ - Restore -- Restore a server in 'soft-deleted' state. - """ - self.manager.restore(self) - - def start(self): - """ - Start -- Start the paused server. - """ - self.manager.start(self) - - def pause(self): - """ - Pause -- Pause the running server. - """ - self.manager.pause(self) - - def unpause(self): - """ - Unpause -- Unpause the paused server. - """ - self.manager.unpause(self) - - def lock(self): - """ - Lock -- Lock the instance from certain operations. - """ - self.manager.lock(self) - - def unlock(self): - """ - Unlock -- Remove instance lock. - """ - self.manager.unlock(self) - - def suspend(self): - """ - Suspend -- Suspend the running server. - """ - self.manager.suspend(self) - - def resume(self): - """ - Resume -- Resume the suspended server. - """ - self.manager.resume(self) - - def rescue(self): - """ - Rescue -- Rescue the problematic server. - """ - return self.manager.rescue(self) - - def unrescue(self): - """ - Unrescue -- Unrescue the rescued server. - """ - self.manager.unrescue(self) - - def shelve(self): - """ - Shelve -- Shelve the server. - """ - self.manager.shelve(self) - - def shelve_offload(self): - """ - Shelve_offload -- Remove a shelved server from the compute node. - """ - self.manager.shelve_offload(self) - - def unshelve(self): - """ - Unshelve -- Unshelve the server. - """ - self.manager.unshelve(self) - - def diagnostics(self): - """Diagnostics -- Retrieve server diagnostics.""" - return self.manager.diagnostics(self) - - def migrate(self): - """ - Migrate a server to a new host. - """ - self.manager.migrate(self) - - def remove_fixed_ip(self, address): - """ - Remove an IP address. - - :param address: The IP address to remove. - """ - self.manager.remove_fixed_ip(self, address) - - def change_password(self, password): - """ - Update the password for a server. - """ - self.manager.change_password(self, password) - - def reboot(self, reboot_type=REBOOT_SOFT): - """ - Reboot the server. - - :param reboot_type: either :data:`REBOOT_SOFT` for a software-level - reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. - """ - self.manager.reboot(self, reboot_type) - - def rebuild(self, image, password=None, preserve_ephemeral=False, - **kwargs): - """ - Rebuild -- shut down and then re-image -- this server. - - :param image: the :class:`Image` (or its ID) to re-image with. - :param password: string to set as password on the rebuilt server. - :param preserve_ephemeral: If True, request that any ephemeral device - be preserved when rebuilding the instance. Defaults to False. - """ - return self.manager.rebuild(self, image, password=password, - preserve_ephemeral=preserve_ephemeral, **kwargs) - - def resize(self, flavor, **kwargs): - """ - Resize the server's resources. - - :param flavor: the :class:`Flavor` (or its ID) to resize to. - - Until a resize event is confirmed with :meth:`confirm_resize`, the old - server will be kept around and you'll be able to roll back to the old - flavor quickly with :meth:`revert_resize`. All resizes are - automatically confirmed after 24 hours. - """ - self.manager.resize(self, flavor, **kwargs) - - def create_image(self, image_name, metadata=None): - """ - Create an image based on this server. - - :param image_name: The name to assign the newly create image. - :param metadata: Metadata to assign to the image. - """ - return self.manager.create_image(self, image_name, metadata) - - def backup(self, backup_name, backup_type, rotation): - """ - Backup a server instance. - - :param backup_name: Name of the backup image - :param backup_type: The backup type, like 'daily' or 'weekly' - :param rotation: Int parameter representing how many backups to - keep around. - """ - self.manager.backup(self, backup_name, backup_type, rotation) - - def confirm_resize(self): - """ - Confirm that the resize worked, thus removing the original server. - """ - self.manager.confirm_resize(self) - - def revert_resize(self): - """ - Revert a previous resize, switching back to the old server. - """ - self.manager.revert_resize(self) - - @property - def networks(self): - """ - Generate a simplified list of addresses - """ - networks = {} - try: - for network_label, address_list in self.addresses.items(): - networks[network_label] = [a['addr'] for a in address_list] - return networks - except Exception: - return {} - - def live_migrate(self, host=None, - block_migration=False, - disk_over_commit=False): - """ - Migrates a running instance to a new machine. - """ - self.manager.live_migrate(self, host, - block_migration, - disk_over_commit) - - def reset_state(self, state='error'): - """ - Reset the state of an instance to active or error. - """ - self.manager.reset_state(self, state) - - def reset_network(self): - """ - Reset network of an instance. - """ - self.manager.reset_network(self) - - def add_security_group(self, security_group): - """ - Add a security group to an instance. - """ - self.manager.add_security_group(self, security_group) - - def remove_security_group(self, security_group): - """ - Remove a security group from an instance. - """ - self.manager.remove_security_group(self, security_group) - - def list_security_group(self): - """ - List security group(s) of an instance. - """ - return self.manager.list_security_group(self) - - def evacuate(self, host=None, on_shared_storage=True, password=None): - """ - Evacuate an instance from failed host to specified host. - - :param host: Name of the target host - :param on_shared_storage: Specifies whether instance files located - on shared storage - :param password: string to set as password on the evacuated server. - """ - return self.manager.evacuate(self, host, on_shared_storage, password) - - def interface_list(self): - """ - List interfaces attached to an instance. - """ - return self.manager.interface_list(self) - - def interface_attach(self, port_id, net_id, fixed_ip): - """ - Attach a network interface to an instance. - """ - return self.manager.interface_attach(self, port_id, net_id, fixed_ip) - - def interface_detach(self, port_id): - """ - Detach a network interface from an instance. - """ - return self.manager.interface_detach(self, port_id) - - -class ServerManager(base.BootingManagerWithFind): - resource_class = Server - - def _boot(self, resource_url, response_key, name, image, flavor, - meta=None, files=None, userdata=None, - reservation_id=None, return_raw=False, min_count=None, - max_count=None, security_groups=None, key_name=None, - availability_zone=None, block_device_mapping=None, - block_device_mapping_v2=None, nics=None, scheduler_hints=None, - config_drive=None, admin_pass=None, disk_config=None, **kwargs): - """ - Create (boot) a new server. - - :param name: Something to name the server. - :param image: The :class:`Image` to boot with. - :param flavor: The :class:`Flavor` to boot onto. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param files: A dict of files to overwrite on the server upon boot. - Keys are file names (i.e. ``/etc/passwd``) and values - are the file contents (either as a string or as a - file-like object). A maximum of five entries is allowed, - and each file must be 10k or less. - :param reservation_id: a UUID for the set of servers being requested. - :param return_raw: If True, don't try to coerce the result into - a Resource object. - :param security_groups: list of security group names - :param key_name: (optional extension) name of keypair to inject into - the instance - :param availability_zone: Name of the availability zone for instance - placement. - :param block_device_mapping: A dict of block device mappings for this - server. - :param block_device_mapping_v2: A dict of block device mappings V2 for - this server. - :param nics: (optional extension) an ordered list of nics to be - added to this server, with information about - connected networks, fixed ips, etc. - :param scheduler_hints: (optional extension) arbitrary key-value pairs - specified by the client to help boot an instance. - :param config_drive: (optional extension) If True, enable config drive - on the server. - :param admin_pass: admin password for the server. - :param disk_config: (optional extension) control how the disk is - partitioned when the server is created. - """ - body = {"server": { - "name": name, - "imageRef": str(base.getid(image)) if image else '', - "flavorRef": str(base.getid(flavor)), - }} - if userdata: - if hasattr(userdata, 'read'): - userdata = userdata.read() - - if six.PY3: - userdata = userdata.encode("utf-8") - else: - userdata = encodeutils.safe_encode(userdata) - - userdata_b64 = base64.b64encode(userdata).decode('utf-8') - body["server"]["user_data"] = userdata_b64 - if meta: - body["server"]["metadata"] = meta - if reservation_id: - body["server"]["reservation_id"] = reservation_id - if key_name: - body["server"]["key_name"] = key_name - if scheduler_hints: - body['os:scheduler_hints'] = scheduler_hints - if config_drive: - body["server"]["config_drive"] = config_drive - if admin_pass: - body["server"]["adminPass"] = admin_pass - if not min_count: - min_count = 1 - if not max_count: - max_count = min_count - body["server"]["min_count"] = min_count - body["server"]["max_count"] = max_count - - if security_groups: - body["server"]["security_groups"] =\ - [{'name': sg} for sg in security_groups] - - # Files are a slight bit tricky. They're passed in a "personality" - # list to the POST. Each item is a dict giving a file name and the - # base64-encoded contents of the file. We want to allow passing - # either an open file *or* some contents as files here. - if files: - personality = body['server']['personality'] = [] - for filepath, file_or_string in sorted(files.items(), - key=lambda x: x[0]): - if hasattr(file_or_string, 'read'): - data = file_or_string.read() - else: - data = file_or_string - - cont = base64.b64encode(data.encode('utf-8')).decode('utf-8') - personality.append({ - 'path': filepath, - 'contents': cont, - }) - - if availability_zone: - body["server"]["availability_zone"] = availability_zone - - # Block device mappings are passed as a list of dictionaries - if block_device_mapping: - body['server']['block_device_mapping'] = \ - self._parse_block_device_mapping(block_device_mapping) - elif block_device_mapping_v2: - # Append the image to the list only if we have new style BDMs - if image: - bdm_dict = {'uuid': image.id, 'source_type': 'image', - 'destination_type': 'local', 'boot_index': 0, - 'delete_on_termination': True} - block_device_mapping_v2.insert(0, bdm_dict) - - body['server']['block_device_mapping_v2'] = block_device_mapping_v2 - - if nics is not None: - # NOTE(tr3buchet): nics can be an empty list - all_net_data = [] - for nic_info in nics: - net_data = {} - # if value is empty string, do not send value in body - if nic_info.get('net-id'): - net_data['uuid'] = nic_info['net-id'] - if (nic_info.get('v4-fixed-ip') and - nic_info.get('v6-fixed-ip')): - raise base.exceptions.CommandError(_( - "Only one of 'v4-fixed-ip' and 'v6-fixed-ip' may be" - " provided.")) - elif nic_info.get('v4-fixed-ip'): - net_data['fixed_ip'] = nic_info['v4-fixed-ip'] - elif nic_info.get('v6-fixed-ip'): - net_data['fixed_ip'] = nic_info['v6-fixed-ip'] - if nic_info.get('port-id'): - net_data['port'] = nic_info['port-id'] - all_net_data.append(net_data) - body['server']['networks'] = all_net_data - - if disk_config is not None: - body['server']['OS-DCF:diskConfig'] = disk_config - - return self._create(resource_url, body, response_key, - return_raw=return_raw, **kwargs) - - def get(self, server): - """ - Get a server. - - :param server: ID of the :class:`Server` to get. - :rtype: :class:`Server` - """ - return self._get("/servers/%s" % base.getid(server), "server") - - def list(self, detailed=True, search_opts=None, marker=None, limit=None): - """ - Get a list of servers. - - :param detailed: Whether to return detailed server info (optional). - :param search_opts: Search options to filter out servers (optional). - :param marker: Begin returning servers that appear later in the server - list than that represented by this server id (optional). - :param limit: Maximum number of servers to return (optional). - - :rtype: list of :class:`Server` - """ - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - if qparams: - new_qparams = sorted(qparams.items(), key=lambda x: x[0]) - query_string = "?%s" % parse.urlencode(new_qparams) - else: - query_string = "" - - detail = "" - if detailed: - detail = "/detail" - return self._list("/servers%s%s" % (detail, query_string), "servers") - - def add_fixed_ip(self, server, network_id): - """ - Add an IP address on a network. - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param network_id: The ID of the network the IP should be on. - """ - self._action('addFixedIp', server, {'networkId': network_id}) - - def remove_fixed_ip(self, server, address): - """ - Remove an IP address. - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param address: The IP address to remove. - """ - self._action('removeFixedIp', server, {'address': address}) - - def add_floating_ip(self, server, address, fixed_address=None): - """ - Add a floating ip to an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param address: The FloatingIP or string floating address to add. - :param fixed_address: The FixedIP the floatingIP should be - associated with (optional) - """ - - address = address.ip if hasattr(address, 'ip') else address - if fixed_address: - if hasattr(fixed_address, 'ip'): - fixed_address = fixed_address.ip - self._action('addFloatingIp', server, - {'address': address, 'fixed_address': fixed_address}) - else: - self._action('addFloatingIp', server, {'address': address}) - - def remove_floating_ip(self, server, address): - """ - Remove a floating IP address. - - :param server: The :class:`Server` (or its ID) to remove an IP from. - :param address: The FloatingIP or string floating address to remove. - """ - - address = address.ip if hasattr(address, 'ip') else address - self._action('removeFloatingIp', server, {'address': address}) - - def get_vnc_console(self, server, console_type): - """ - Get a vnc console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of vnc console to get ('novnc' or 'xvpvnc') - """ - - return self._action('os-getVNCConsole', server, - {'type': console_type})[1] - - def get_spice_console(self, server, console_type): - """ - Get a spice console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of spice console to get ('spice-html5') - """ - - return self._action('os-getSPICEConsole', server, - {'type': console_type})[1] - - def get_rdp_console(self, server, console_type): - """ - Get a rdp console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of rdp console to get ('rdp-html5') - """ - - return self._action('os-getRDPConsole', server, - {'type': console_type})[1] - - def get_serial_console(self, server, console_type): - """ - Get a serial console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of serial console to get ('serial') - """ - - return self._action('os-getSerialConsole', server, - {'type': console_type})[1] - - def get_password(self, server, private_key=None): - """ - Get password for an instance - - Returns the clear password of an instance if private_key is - provided, returns the ciphered password otherwise. - - Requires that openssl is installed and in the path - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param private_key: The private key to decrypt password - (optional) - """ - - _resp, body = self.api.client.get("/servers/%s/os-server-password" - % base.getid(server)) - ciphered_pw = body.get('password', '') if body else '' - if private_key and ciphered_pw: - try: - return crypto.decrypt_password(private_key, ciphered_pw) - except Exception as exc: - return '%sFailed to decrypt:\n%s' % (exc, ciphered_pw) - return ciphered_pw - - def clear_password(self, server): - """ - Clear password for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - """ - - return self._delete("/servers/%s/os-server-password" - % base.getid(server)) - - def stop(self, server): - """ - Stop the server. - """ - return self._action('os-stop', server, None) - - def force_delete(self, server): - """ - Force delete the server. - """ - return self._action('forceDelete', server, None) - - def restore(self, server): - """ - Restore soft-deleted server. - """ - return self._action('restore', server, None) - - def start(self, server): - """ - Start the server. - """ - self._action('os-start', server, None) - - def pause(self, server): - """ - Pause the server. - """ - self._action('pause', server, None) - - def unpause(self, server): - """ - Unpause the server. - """ - self._action('unpause', server, None) - - def lock(self, server): - """ - Lock the server. - """ - self._action('lock', server, None) - - def unlock(self, server): - """ - Unlock the server. - """ - self._action('unlock', server, None) - - def suspend(self, server): - """ - Suspend the server. - """ - self._action('suspend', server, None) - - def resume(self, server): - """ - Resume the server. - """ - self._action('resume', server, None) - - def rescue(self, server): - """ - Rescue the server. - """ - return self._action('rescue', server, None) - - def unrescue(self, server): - """ - Unrescue the server. - """ - self._action('unrescue', server, None) - - def shelve(self, server): - """ - Shelve the server. - """ - self._action('shelve', server, None) - - def shelve_offload(self, server): - """ - Remove a shelved instance from the compute node. - """ - self._action('shelveOffload', server, None) - - def unshelve(self, server): - """ - Unshelve the server. - """ - self._action('unshelve', server, None) - - def diagnostics(self, server): - """Retrieve server diagnostics.""" - return self.api.client.get("/servers/%s/diagnostics" % - base.getid(server)) - - def create(self, name, image, flavor, meta=None, files=None, - reservation_id=None, min_count=None, - max_count=None, security_groups=None, userdata=None, - key_name=None, availability_zone=None, - block_device_mapping=None, block_device_mapping_v2=None, - nics=None, scheduler_hints=None, - config_drive=None, disk_config=None, **kwargs): - # TODO(anthony): indicate in doc string if param is an extension - # and/or optional - """ - Create (boot) a new server. - - :param name: Something to name the server. - :param image: The :class:`Image` to boot with. - :param flavor: The :class:`Flavor` to boot onto. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param files: A dict of files to overrwrite on the server upon boot. - Keys are file names (i.e. ``/etc/passwd``) and values - are the file contents (either as a string or as a - file-like object). A maximum of five entries is allowed, - and each file must be 10k or less. - :param userdata: user data to pass to be exposed by the metadata - server this can be a file type object as well or a - string. - :param reservation_id: a UUID for the set of servers being requested. - :param key_name: (optional extension) name of previously created - keypair to inject into the instance. - :param availability_zone: Name of the availability zone for instance - placement. - :param block_device_mapping: (optional extension) A dict of block - device mappings for this server. - :param block_device_mapping_v2: (optional extension) A dict of block - device mappings for this server. - :param nics: (optional extension) an ordered list of nics to be - added to this server, with information about - connected networks, fixed ips, port etc. - :param scheduler_hints: (optional extension) arbitrary key-value pairs - specified by the client to help boot an instance - :param config_drive: (optional extension) value for config drive - either boolean, or volume-id - :param disk_config: (optional extension) control how the disk is - partitioned when the server is created. possible - values are 'AUTO' or 'MANUAL'. - """ - if not min_count: - min_count = 1 - if not max_count: - max_count = min_count - if min_count > max_count: - min_count = max_count - - boot_args = [name, image, flavor] - - boot_kwargs = dict( - meta=meta, files=files, userdata=userdata, - reservation_id=reservation_id, min_count=min_count, - max_count=max_count, security_groups=security_groups, - key_name=key_name, availability_zone=availability_zone, - scheduler_hints=scheduler_hints, config_drive=config_drive, - disk_config=disk_config, **kwargs) - - if block_device_mapping: - resource_url = "/os-volumes_boot" - boot_kwargs['block_device_mapping'] = block_device_mapping - elif block_device_mapping_v2: - resource_url = "/os-volumes_boot" - boot_kwargs['block_device_mapping_v2'] = block_device_mapping_v2 - else: - resource_url = "/servers" - if nics: - boot_kwargs['nics'] = nics - - response_key = "server" - return self._boot(resource_url, response_key, *boot_args, - **boot_kwargs) - - def update(self, server, name=None): - """ - Update the name or the password for a server. - - :param server: The :class:`Server` (or its ID) to update. - :param name: Update the server's name. - """ - if name is None: - return - - body = { - "server": { - "name": name, - }, - } - - return self._update("/servers/%s" % base.getid(server), body, "server") - - def change_password(self, server, password): - """ - Update the password for a server. - """ - self._action("changePassword", server, {"adminPass": password}) - - def delete(self, server): - """ - Delete (i.e. shut down and delete the image) this server. - """ - self._delete("/servers/%s" % base.getid(server)) - - def reboot(self, server, reboot_type=REBOOT_SOFT): - """ - Reboot a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param reboot_type: either :data:`REBOOT_SOFT` for a software-level - reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. - """ - self._action('reboot', server, {'type': reboot_type}) - - def rebuild(self, server, image, password=None, disk_config=None, - preserve_ephemeral=False, name=None, meta=None, files=None, - **kwargs): - """ - Rebuild -- shut down and then re-image -- a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param image: the :class:`Image` (or its ID) to re-image with. - :param password: string to set as password on the rebuilt server. - :param disk_config: partitioning mode to use on the rebuilt server. - Valid values are 'AUTO' or 'MANUAL' - :param preserve_ephemeral: If True, request that any ephemeral device - be preserved when rebuilding the instance. Defaults to False. - :param name: Something to name the server. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param files: A dict of files to overwrite on the server upon boot. - Keys are file names (i.e. ``/etc/passwd``) and values - are the file contents (either as a string or as a - file-like object). A maximum of five entries is allowed, - and each file must be 10k or less. - """ - body = {'imageRef': base.getid(image)} - if password is not None: - body['adminPass'] = password - if disk_config is not None: - body['OS-DCF:diskConfig'] = disk_config - if preserve_ephemeral is not False: - body['preserve_ephemeral'] = True - if name is not None: - body['name'] = name - if meta: - body['metadata'] = meta - if files: - personality = body['personality'] = [] - for filepath, file_or_string in sorted(files.items(), - key=lambda x: x[0]): - if hasattr(file_or_string, 'read'): - data = file_or_string.read() - else: - data = file_or_string - - cont = base64.b64encode(data.encode('utf-8')).decode('utf-8') - personality.append({ - 'path': filepath, - 'contents': cont, - }) - - _resp, body = self._action('rebuild', server, body, **kwargs) - return Server(self, body['server']) - - def migrate(self, server): - """ - Migrate a server to a new host. - - :param server: The :class:`Server` (or its ID). - """ - self._action('migrate', server) - - def resize(self, server, flavor, disk_config=None, **kwargs): - """ - Resize a server's resources. - - :param server: The :class:`Server` (or its ID) to share onto. - :param flavor: the :class:`Flavor` (or its ID) to resize to. - :param disk_config: partitioning mode to use on the rebuilt server. - Valid values are 'AUTO' or 'MANUAL' - - Until a resize event is confirmed with :meth:`confirm_resize`, the old - server will be kept around and you'll be able to roll back to the old - flavor quickly with :meth:`revert_resize`. All resizes are - automatically confirmed after 24 hours. - """ - info = {'flavorRef': base.getid(flavor)} - if disk_config is not None: - info['OS-DCF:diskConfig'] = disk_config - - self._action('resize', server, info=info, **kwargs) - - def confirm_resize(self, server): - """ - Confirm that the resize worked, thus removing the original server. - - :param server: The :class:`Server` (or its ID) to share onto. - """ - self._action('confirmResize', server) - - def revert_resize(self, server): - """ - Revert a previous resize, switching back to the old server. - - :param server: The :class:`Server` (or its ID) to share onto. - """ - self._action('revertResize', server) - - def create_image(self, server, image_name, metadata=None): - """ - Snapshot a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param image_name: Name to give the snapshot image - :param meta: Metadata to give newly-created image entity - """ - body = {'name': image_name, 'metadata': metadata or {}} - resp = self._action('createImage', server, body)[0] - location = resp.headers['location'] - image_uuid = location.split('/')[-1] - return image_uuid - - def backup(self, server, backup_name, backup_type, rotation): - """ - Backup a server instance. - - :param server: The :class:`Server` (or its ID) to share onto. - :param backup_name: Name of the backup image - :param backup_type: The backup type, like 'daily' or 'weekly' - :param rotation: Int parameter representing how many backups to - keep around. - """ - body = {'name': backup_name, - 'backup_type': backup_type, - 'rotation': rotation} - self._action('createBackup', server, body) - - def set_meta(self, server, metadata): - """ - Set a servers metadata - :param server: The :class:`Server` to add metadata to - :param metadata: A dict of metadata to add to the server - """ - body = {'metadata': metadata} - return self._create("/servers/%s/metadata" % base.getid(server), - body, "metadata") - - def set_meta_item(self, server, key, value): - """ - Updates an item of server metadata - :param server: The :class:`Server` to add metadata to - :param key: metadata key to update - :param value: string value - """ - body = {'meta': {key: value}} - return self._update("/servers/%s/metadata/%s" % - (base.getid(server), key), body) - - def get_console_output(self, server, length=None): - """ - Get text console log output from Server. - - :param server: The :class:`Server` (or its ID) whose console output - you would like to retrieve. - :param length: The number of tail loglines you would like to retrieve. - """ - return self._action('os-getConsoleOutput', - server, - {'length': length})[1]['output'] - - def delete_meta(self, server, keys): - """ - Delete metadata from an server - :param server: The :class:`Server` to add metadata to - :param keys: A list of metadata keys to delete from the server - """ - for k in keys: - self._delete("/servers/%s/metadata/%s" % (base.getid(server), k)) - - def live_migrate(self, server, host, block_migration, disk_over_commit): - """ - Migrates a running instance to a new machine. - - :param server: instance id which comes from nova list. - :param host: destination host name. - :param block_migration: if True, do block_migration. - :param disk_over_commit: if True, Allow overcommit. - - """ - self._action('os-migrateLive', server, - {'host': host, - 'block_migration': block_migration, - 'disk_over_commit': disk_over_commit}) - - def reset_state(self, server, state='error'): - """ - Reset the state of an instance to active or error. - - :param server: ID of the instance to reset the state of. - :param state: Desired state; either 'active' or 'error'. - Defaults to 'error'. - """ - self._action('os-resetState', server, dict(state=state)) - - def reset_network(self, server): - """ - Reset network of an instance. - """ - self._action('resetNetwork', server) - - def add_security_group(self, server, security_group): - """ - Add a Security Group to an instance - - :param server: ID of the instance. - :param security_group: The name of security group to add. - - """ - self._action('addSecurityGroup', server, {'name': security_group}) - - def remove_security_group(self, server, security_group): - """ - Add a Security Group to an instance - - :param server: ID of the instance. - :param security_group: The name of security group to remove. - - """ - self._action('removeSecurityGroup', server, {'name': security_group}) - - def list_security_group(self, server): - """ - List Security Group(s) of an instance - - :param server: ID of the instance. - - """ - return self._list('/servers/%s/os-security-groups' % - base.getid(server), 'security_groups', - security_groups.SecurityGroup) - - def evacuate(self, server, host=None, on_shared_storage=True, - password=None): - """ - Evacuate a server instance. - - :param server: The :class:`Server` (or its ID) to share onto. - :param host: Name of the target host. - :param on_shared_storage: Specifies whether instance files located - on shared storage - :param password: string to set as password on the evacuated server. - """ - - body = {'onSharedStorage': on_shared_storage} - if host is not None: - body['host'] = host - - if password is not None: - body['adminPass'] = password - - return self._action('evacuate', server, body) - - def interface_list(self, server): - """ - List attached network interfaces - - :param server: The :class:`Server` (or its ID) to query. - """ - return self._list('/servers/%s/os-interface' % base.getid(server), - 'interfaceAttachments') - - def interface_attach(self, server, port_id, net_id, fixed_ip): - """ - Attach a network_interface to an instance. - - :param server: The :class:`Server` (or its ID) to attach to. - :param port_id: The port to attach. - """ - - body = {'interfaceAttachment': {}} - if port_id: - body['interfaceAttachment']['port_id'] = port_id - if net_id: - body['interfaceAttachment']['net_id'] = net_id - if fixed_ip: - body['interfaceAttachment']['fixed_ips'] = [ - {'ip_address': fixed_ip}] - - return self._create('/servers/%s/os-interface' % base.getid(server), - body, 'interfaceAttachment') - - def interface_detach(self, server, port_id): - """ - Detach a network_interface from an instance. - - :param server: The :class:`Server` (or its ID) to detach from. - :param port_id: The port to detach. - """ - self._delete('/servers/%s/os-interface/%s' % (base.getid(server), - port_id)) - - def _action(self, action, server, info=None, **kwargs): - """ - Perform a server "action" -- reboot/rebuild/resize/etc. - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/servers/%s/action' % base.getid(server) - return self.api.client.post(url, body=body) diff --git a/awx/lib/site-packages/novaclient/v1_1/services.py b/awx/lib/site-packages/novaclient/v1_1/services.py deleted file mode 100644 index d51fa3ebfd..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/services.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -service interface -""" -from novaclient import base - - -class Service(base.Resource): - def __repr__(self): - return "" % self.binary - - def _add_details(self, info): - dico = 'resource' in info and info['resource'] or info - for (k, v) in dico.items(): - setattr(self, k, v) - - -class ServiceManager(base.ManagerWithFind): - resource_class = Service - - def list(self, host=None, binary=None): - """ - Describes cpu/memory/hdd info for host. - - :param host: destination host name. - """ - url = "/os-services" - filters = [] - if host: - filters.append("host=%s" % host) - if binary: - filters.append("binary=%s" % binary) - if filters: - url = "%s?%s" % (url, "&".join(filters)) - return self._list(url, "services") - - def _update_body(self, host, binary, disabled_reason=None): - body = {"host": host, - "binary": binary} - if disabled_reason is not None: - body["disabled_reason"] = disabled_reason - return body - - def enable(self, host, binary): - """Enable the service specified by hostname and binary.""" - body = self._update_body(host, binary) - return self._update("/os-services/enable", body, "service") - - def disable(self, host, binary): - """Disable the service specified by hostname and binary.""" - body = self._update_body(host, binary) - return self._update("/os-services/disable", body, "service") - - def disable_log_reason(self, host, binary, reason): - """Disable the service with reason.""" - body = self._update_body(host, binary, reason) - return self._update("/os-services/disable-log-reason", body, "service") - - def delete(self, service_id): - """Delete a service.""" - return self._delete("/os-services/%s" % service_id) diff --git a/awx/lib/site-packages/novaclient/v1_1/shell.py b/awx/lib/site-packages/novaclient/v1_1/shell.py deleted file mode 100644 index 457ebc1a10..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/shell.py +++ /dev/null @@ -1,3928 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import argparse -import copy -import datetime -import getpass -import locale -import logging -import os -import sys -import time - -from oslo.utils import encodeutils -from oslo.utils import strutils -from oslo.utils import timeutils -import six - -from novaclient import exceptions -from novaclient.openstack.common.gettextutils import _ -from novaclient.openstack.common import uuidutils -from novaclient import utils -from novaclient.v1_1 import availability_zones -from novaclient.v1_1 import quotas -from novaclient.v1_1 import servers - - -logger = logging.getLogger(__name__) - - -CLIENT_BDM2_KEYS = { - 'id': 'uuid', - 'source': 'source_type', - 'dest': 'destination_type', - 'bus': 'disk_bus', - 'device': 'device_name', - 'size': 'volume_size', - 'format': 'guest_format', - 'bootindex': 'boot_index', - 'type': 'device_type', - 'shutdown': 'delete_on_termination', -} - - -def _key_value_pairing(text): - try: - (k, v) = text.split('=', 1) - return (k, v) - except ValueError: - msg = "%r is not in the format of key=value" % text - raise argparse.ArgumentTypeError(msg) - - -def _match_image(cs, wanted_properties): - image_list = cs.images.list() - images_matched = [] - match = set(wanted_properties) - for img in image_list: - try: - if match == match.intersection(set(img.metadata.items())): - images_matched.append(img) - except AttributeError: - pass - return images_matched - - -def _parse_block_device_mapping_v2(args, image): - bdm = [] - - if args.boot_volume: - bdm_dict = {'uuid': args.boot_volume, 'source_type': 'volume', - 'destination_type': 'volume', 'boot_index': 0, - 'delete_on_termination': False} - bdm.append(bdm_dict) - - if args.snapshot: - bdm_dict = {'uuid': args.snapshot, 'source_type': 'snapshot', - 'destination_type': 'volume', 'boot_index': 0, - 'delete_on_termination': False} - bdm.append(bdm_dict) - - for device_spec in args.block_device: - spec_dict = dict(v.split('=') for v in device_spec.split(',')) - bdm_dict = {} - - for key, value in six.iteritems(spec_dict): - bdm_dict[CLIENT_BDM2_KEYS[key]] = value - - # Convert the delete_on_termination to a boolean or set it to true by - # default for local block devices when not specified. - if 'delete_on_termination' in bdm_dict: - action = bdm_dict['delete_on_termination'] - bdm_dict['delete_on_termination'] = (action == 'remove') - elif bdm_dict.get('destination_type') == 'local': - bdm_dict['delete_on_termination'] = True - - bdm.append(bdm_dict) - - for ephemeral_spec in args.ephemeral: - bdm_dict = {'source_type': 'blank', 'destination_type': 'local', - 'boot_index': -1, 'delete_on_termination': True} - - eph_dict = dict(v.split('=') for v in ephemeral_spec.split(',')) - if 'size' in eph_dict: - bdm_dict['volume_size'] = eph_dict['size'] - if 'format' in eph_dict: - bdm_dict['guest_format'] = eph_dict['format'] - - bdm.append(bdm_dict) - - if args.swap: - bdm_dict = {'source_type': 'blank', 'destination_type': 'local', - 'boot_index': -1, 'delete_on_termination': True, - 'guest_format': 'swap', 'volume_size': args.swap} - bdm.append(bdm_dict) - - return bdm - - -def _boot(cs, args): - """Boot a new server.""" - if args.image: - image = _find_image(cs, args.image) - else: - image = None - - if not image and args.image_with: - images = _match_image(cs, args.image_with) - if images: - # TODO(harlowja): log a warning that we - # are selecting the first of many? - image = images[0] - - if not args.flavor: - raise exceptions.CommandError(_("you need to specify a Flavor ID ")) - - min_count = 1 - max_count = 1 - # Don't let user mix num_instances and max_count/min_count. - if (args.num_instances is not None and - args.min_count is None and args.max_count is None): - if args.num_instances < 1: - raise exceptions.CommandError(_("num_instances should be >= 1")) - max_count = args.num_instances - elif (args.num_instances is not None and - (args.min_count is not None or args.max_count is not None)): - raise exceptions.CommandError(_("Don't mix num-instances and " - "max/min-count")) - if args.min_count is not None: - if args.min_count < 1: - raise exceptions.CommandError(_("min_count should be >= 1")) - min_count = args.min_count - max_count = min_count - if args.max_count is not None: - if args.max_count < 1: - raise exceptions.CommandError(_("max_count should be >= 1")) - max_count = args.max_count - if (args.min_count is not None and args.max_count is not None and - args.min_count > args.max_count): - raise exceptions.CommandError(_( - "min_count should be <= max_count")) - - flavor = _find_flavor(cs, args.flavor) - - meta = dict(v.split('=', 1) for v in args.meta) - - files = {} - for f in args.files: - try: - dst, src = f.split('=', 1) - files[dst] = open(src) - except IOError as e: - raise exceptions.CommandError(_("Can't open '%(src)s': %(exc)s") % - {'src': src, 'exc': e}) - except ValueError as e: - raise exceptions.CommandError(_("Invalid file argument '%s'. " - "File arguments must be of the " - "form '--file " - "'") % f) - - # use the os-keypair extension - key_name = None - if args.key_name is not None: - key_name = args.key_name - - if args.user_data: - try: - userdata = open(args.user_data) - except IOError as e: - raise exceptions.CommandError(_("Can't open '%(user_data)s': " - "%(exc)s") % - {'user_data': args.user_data, - 'exc': e}) - else: - userdata = None - - if args.availability_zone: - availability_zone = args.availability_zone - else: - availability_zone = None - - if args.security_groups: - security_groups = args.security_groups.split(',') - else: - security_groups = None - - block_device_mapping = {} - for bdm in args.block_device_mapping: - device_name, mapping = bdm.split('=', 1) - block_device_mapping[device_name] = mapping - - block_device_mapping_v2 = _parse_block_device_mapping_v2(args, image) - - n_boot_args = len(list(filter( - bool, (image, args.boot_volume, args.snapshot)))) - have_bdm = block_device_mapping_v2 or block_device_mapping - - # Fail if more than one boot devices are present - # or if there is no device to boot from. - if n_boot_args > 1 or n_boot_args == 0 and not have_bdm: - raise exceptions.CommandError( - _("you need to specify at least one source ID (Image, Snapshot, " - "or Volume), a block device mapping or provide a set of " - "properties to match against an image")) - - if block_device_mapping and block_device_mapping_v2: - raise exceptions.CommandError( - _("you can't mix old block devices (--block-device-mapping) " - "with the new ones (--block-device, --boot-volume, --snapshot, " - "--ephemeral, --swap)")) - - nics = [] - for nic_str in args.nics: - err_msg = (_("Invalid nic argument '%s'. Nic arguments must be of " - "the form --nic , with at minimum " - "net-id or port-id (but not both) specified.") % nic_str) - nic_info = {"net-id": "", "v4-fixed-ip": "", "v6-fixed-ip": "", - "port-id": ""} - - for kv_str in nic_str.split(","): - try: - k, v = kv_str.split("=", 1) - except ValueError as e: - raise exceptions.CommandError(err_msg) - - if k in nic_info: - nic_info[k] = v - else: - raise exceptions.CommandError(err_msg) - - if bool(nic_info['net-id']) == bool(nic_info['port-id']): - raise exceptions.CommandError(err_msg) - - nics.append(nic_info) - - hints = {} - if args.scheduler_hints: - for hint in args.scheduler_hints: - key, _sep, value = hint.partition('=') - # NOTE(vish): multiple copies of the same hint will - # result in a list of values - if key in hints: - if isinstance(hints[key], six.string_types): - hints[key] = [hints[key]] - hints[key] += [value] - else: - hints[key] = value - boot_args = [args.name, image, flavor] - - if str(args.config_drive).lower() in ("true", "1"): - config_drive = True - elif str(args.config_drive).lower() in ("false", "0", "", "none"): - config_drive = None - else: - config_drive = args.config_drive - - boot_kwargs = dict( - meta=meta, - files=files, - key_name=key_name, - min_count=min_count, - max_count=max_count, - userdata=userdata, - availability_zone=availability_zone, - security_groups=security_groups, - block_device_mapping=block_device_mapping, - block_device_mapping_v2=block_device_mapping_v2, - nics=nics, - scheduler_hints=hints, - config_drive=config_drive) - - return boot_args, boot_kwargs - - -@utils.arg('--flavor', - default=None, - metavar='', - help=_("Name or ID of flavor (see 'nova flavor-list').")) -@utils.arg('--image', - default=None, - metavar='', - help=_("Name or ID of image (see 'nova image-list'). ")) -@utils.arg('--image-with', - default=[], - type=_key_value_pairing, - action='append', - metavar='', - help=_("Image metadata property (see 'nova image-show'). ")) -@utils.arg('--boot-volume', - default=None, - metavar="", - help=_("Volume ID to boot from.")) -@utils.arg('--snapshot', - default=None, - metavar="", - help=_("Snapshot ID to boot from (will create a volume).")) -@utils.arg('--num-instances', - default=None, - type=int, - metavar='', - help=argparse.SUPPRESS) -@utils.arg('--min-count', - default=None, - type=int, - metavar='', - help=_("Boot at least servers (limited by quota).")) -@utils.arg('--max-count', - default=None, - type=int, - metavar='', - help=_("Boot up to servers (limited by quota).")) -@utils.arg('--meta', - metavar="", - action='append', - default=[], - help=_("Record arbitrary key/value metadata to /meta.js " - "on the new server. Can be specified multiple times.")) -@utils.arg('--file', - metavar="", - action='append', - dest='files', - default=[], - help=_("Store arbitrary files from locally to " - "on the new server. You may store up to 5 files.")) -@utils.arg('--key-name', - default=os.environ.get('NOVACLIENT_DEFAULT_KEY_NAME'), - metavar='', - help=_("Key name of keypair that should be created earlier with \ - the command keypair-add")) -@utils.arg('--key_name', - help=argparse.SUPPRESS) -@utils.arg('name', metavar='', help=_('Name for the new server')) -@utils.arg('--user-data', - default=None, - metavar='', - help=_("user data file to pass to be exposed by the metadata server.")) -@utils.arg('--user_data', - help=argparse.SUPPRESS) -@utils.arg('--availability-zone', - default=None, - metavar='', - help=_("The availability zone for server placement.")) -@utils.arg('--availability_zone', - help=argparse.SUPPRESS) -@utils.arg('--security-groups', - default=None, - metavar='', - help=_("Comma separated list of security group names.")) -@utils.arg('--security_groups', - help=argparse.SUPPRESS) -@utils.arg('--block-device-mapping', - metavar="", - action='append', - default=[], - help=_("Block device mapping in the format " - "=:::.")) -@utils.arg('--block_device_mapping', - action='append', - help=argparse.SUPPRESS) -@utils.arg('--block-device', - metavar="key1=value1[,key2=value2...]", - action='append', - default=[], - help=_("Block device mapping with the keys: " - "id=UUID (image_id, snapshot_id or volume_id only if using source " - "image, snapshot or volume) " - "source=source type (image, snapshot, volume or blank), " - "dest=destination type of the block device (volume or local), " - "bus=device's bus (e.g. uml, lxc, virtio, ...; if omitted, " - "hypervisor driver chooses a suitable default, " - "honoured only if device type is supplied) " - "type=device type (e.g. disk, cdrom, ...; defaults to 'disk') " - "device=name of the device (e.g. vda, xda, ...; " - "if omitted, hypervisor driver chooses suitable device " - "depending on selected bus), " - "size=size of the block device in GB (if omitted, " - "hypervisor driver calculates size), " - "format=device will be formatted (e.g. swap, ntfs, ...; optional), " - "bootindex=integer used for ordering the boot disks " - "(for image backed instances it is equal to 0, " - "for others need to be specified) and " - "shutdown=shutdown behaviour (either preserve or remove, " - "for local destination set to remove).")) -@utils.arg('--swap', - metavar="", - default=None, - help=_("Create and attach a local swap block device of MB.")) -@utils.arg('--ephemeral', - metavar="size=[,format=]", - action='append', - default=[], - help=_("Create and attach a local ephemeral block device of GB " - "and format it to .")) -@utils.arg('--hint', - action='append', - dest='scheduler_hints', - default=[], - metavar='', - help=_("Send arbitrary key/value pairs to the scheduler for custom " - "use.")) -@utils.arg('--nic', - metavar="", - action='append', - dest='nics', - default=[], - help=_("Create a NIC on the server. " - "Specify option multiple times to create multiple NICs. " - "net-id: attach NIC to network with this UUID " - "(either port-id or net-id must be provided), " - "v4-fixed-ip: IPv4 fixed address for NIC (optional), " - "v6-fixed-ip: IPv6 fixed address for NIC (optional), " - "port-id: attach NIC to port with this UUID " - "(either port-id or net-id must be provided).")) -@utils.arg('--config-drive', - metavar="", - dest='config_drive', - default=False, - help=_("Enable config drive")) -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the new server boot progress until it completes.')) -def do_boot(cs, args): - """Boot a new server.""" - boot_args, boot_kwargs = _boot(cs, args) - - extra_boot_kwargs = utils.get_resource_manager_extra_kwargs(do_boot, args) - boot_kwargs.update(extra_boot_kwargs) - - server = cs.servers.create(*boot_args, **boot_kwargs) - _print_server(cs, args, server) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'building', ['active']) - - -def do_cloudpipe_list(cs, _args): - """Print a list of all cloudpipe instances.""" - cloudpipes = cs.cloudpipe.list() - columns = ['Project Id', "Public IP", "Public Port", "Internal IP"] - utils.print_list(cloudpipes, columns) - - -@utils.arg('project', metavar='', - help=_('UUID of the project to create the cloudpipe for.')) -def do_cloudpipe_create(cs, args): - """Create a cloudpipe instance for the given project.""" - cs.cloudpipe.create(args.project) - - -@utils.arg('address', metavar='', help=_('New IP Address.')) -@utils.arg('port', metavar='', help='New Port.') -def do_cloudpipe_configure(cs, args): - """Update the VPN IP/port of a cloudpipe instance.""" - cs.cloudpipe.update(args.address, args.port) - - -def _poll_for_status(poll_fn, obj_id, action, final_ok_states, - poll_period=5, show_progress=True, - status_field="status", silent=False): - """Block while an action is being performed, periodically printing - progress. - """ - def print_progress(progress): - if show_progress: - msg = (_('\rServer %(action)s... %(progress)s%% complete') - % dict(action=action, progress=progress)) - else: - msg = _('\rServer %(action)s...') % dict(action=action) - - sys.stdout.write(msg) - sys.stdout.flush() - - if not silent: - print() - - while True: - obj = poll_fn(obj_id) - - status = getattr(obj, status_field) - - if status: - status = status.lower() - - progress = getattr(obj, 'progress', None) or 0 - if status in final_ok_states: - if not silent: - print_progress(100) - print(_("\nFinished")) - break - elif status == "error": - if not silent: - print(_("\nError %s server") % action) - raise exceptions.InstanceInErrorState(obj.fault['message']) - - if not silent: - print_progress(progress) - - time.sleep(poll_period) - - -def _translate_keys(collection, convert): - for item in collection: - keys = item.__dict__.keys() - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _translate_extended_states(collection): - power_states = [ - 'NOSTATE', # 0x00 - 'Running', # 0x01 - '', # 0x02 - 'Paused', # 0x03 - 'Shutdown', # 0x04 - '', # 0x05 - 'Crashed', # 0x06 - 'Suspended' # 0x07 - ] - - for item in collection: - try: - setattr(item, 'power_state', - power_states[getattr(item, 'power_state')] - ) - except AttributeError: - setattr(item, 'power_state', "N/A") - try: - getattr(item, 'task_state') - except AttributeError: - setattr(item, 'task_state', "N/A") - - -def _translate_flavor_keys(collection): - _translate_keys(collection, [('ram', 'memory_mb')]) - - -def _print_flavor_extra_specs(flavor): - try: - return flavor.get_keys() - except exceptions.NotFound: - return "N/A" - - -def _print_flavor_list(flavors, show_extra_specs=False): - _translate_flavor_keys(flavors) - - headers = [ - 'ID', - 'Name', - 'Memory_MB', - 'Disk', - 'Ephemeral', - 'Swap', - 'VCPUs', - 'RXTX_Factor', - 'Is_Public', - ] - - if show_extra_specs: - formatters = {'extra_specs': _print_flavor_extra_specs} - headers.append('extra_specs') - else: - formatters = {} - - utils.print_list(flavors, headers, formatters) - - -@utils.arg('--extra-specs', - dest='extra_specs', - action='store_true', - default=False, - help=_('Get extra-specs of each flavor.')) -@utils.arg('--all', - dest='all', - action='store_true', - default=False, - help=_('Display all flavors (Admin only).')) -def do_flavor_list(cs, args): - """Print a list of available 'flavors' (sizes of servers).""" - if args.all: - flavors = cs.flavors.list(is_public=None) - else: - flavors = cs.flavors.list() - _print_flavor_list(flavors, args.extra_specs) - - -@utils.arg('flavor', - metavar='', - help=_("Name or ID of the flavor to delete")) -def do_flavor_delete(cs, args): - """Delete a specific flavor""" - flavorid = _find_flavor(cs, args.flavor) - cs.flavors.delete(flavorid) - _print_flavor_list([flavorid]) - - -@utils.arg('flavor', - metavar='', - help=_("Name or ID of flavor")) -def do_flavor_show(cs, args): - """Show details about the given flavor.""" - flavor = _find_flavor(cs, args.flavor) - _print_flavor(flavor) - - -@utils.arg('name', - metavar='', - help=_("Name of the new flavor")) -@utils.arg('id', - metavar='', - help=_("Unique ID (integer or UUID) for the new flavor." - " If specifying 'auto', a UUID will be generated as id")) -@utils.arg('ram', - metavar='', - help=_("Memory size in MB")) -@utils.arg('disk', - metavar='', - help=_("Disk size in GB")) -@utils.arg('--ephemeral', - metavar='', - help=_("Ephemeral space size in GB (default 0)"), - default=0) -@utils.arg('vcpus', - metavar='', - help=_("Number of vcpus")) -@utils.arg('--swap', - metavar='', - help=_("Swap space size in MB (default 0)"), - default=0) -@utils.arg('--rxtx-factor', - metavar='', - help=_("RX/TX factor (default 1)"), - default=1.0) -@utils.arg('--is-public', - metavar='', - help=_("Make flavor accessible to the public (default true)"), - type=lambda v: strutils.bool_from_string(v, True), - default=True) -def do_flavor_create(cs, args): - """Create a new flavor""" - f = cs.flavors.create(args.name, args.ram, args.vcpus, args.disk, args.id, - args.ephemeral, args.swap, args.rxtx_factor, - args.is_public) - _print_flavor_list([f]) - - -@utils.arg('flavor', - metavar='', - help=_("Name or ID of flavor")) -@utils.arg('action', - metavar='', - choices=['set', 'unset'], - help=_("Actions: 'set' or 'unset'")) -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Extra_specs to set/unset (only key is necessary on unset)')) -def do_flavor_key(cs, args): - """Set or unset extra_spec for a flavor.""" - flavor = _find_flavor(cs, args.flavor) - keypair = _extract_metadata(args) - - if args.action == 'set': - flavor.set_keys(keypair) - elif args.action == 'unset': - flavor.unset_keys(keypair.keys()) - - -@utils.arg('--flavor', - metavar='', - help=_("Filter results by flavor name or ID.")) -@utils.arg('--tenant', metavar='', - help=_('Filter results by tenant ID.')) -def do_flavor_access_list(cs, args): - """Print access information about the given flavor.""" - if args.flavor and args.tenant: - raise exceptions.CommandError(_("Unable to filter results by " - "both --flavor and --tenant.")) - elif args.flavor: - flavor = _find_flavor(cs, args.flavor) - if flavor.is_public: - raise exceptions.CommandError(_("Failed to get access list " - "for public flavor type.")) - kwargs = {'flavor': flavor} - elif args.tenant: - kwargs = {'tenant': args.tenant} - else: - raise exceptions.CommandError(_("Unable to get all access lists. " - "Specify --flavor or --tenant")) - - try: - access_list = cs.flavor_access.list(**kwargs) - except NotImplementedError as e: - raise exceptions.CommandError("%s" % str(e)) - - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@utils.arg('flavor', - metavar='', - help=_("Flavor name or ID to add access for the given tenant.")) -@utils.arg('tenant', metavar='', - help=_('Tenant ID to add flavor access for.')) -def do_flavor_access_add(cs, args): - """Add flavor access for the given tenant.""" - flavor = _find_flavor(cs, args.flavor) - access_list = cs.flavor_access.add_tenant_access(flavor, args.tenant) - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@utils.arg('flavor', - metavar='', - help=_("Flavor name or ID to remove access for the given tenant.")) -@utils.arg('tenant', metavar='', - help=_('Tenant ID to remove flavor access for.')) -def do_flavor_access_remove(cs, args): - """Remove flavor access for the given tenant.""" - flavor = _find_flavor(cs, args.flavor) - access_list = cs.flavor_access.remove_tenant_access(flavor, args.tenant) - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@utils.arg('project_id', metavar='', - help=_('The ID of the project.')) -def do_scrub(cs, args): - """Delete data associated with the project.""" - networks_list = cs.networks.list() - networks_list = [network for network in networks_list - if getattr(network, 'project_id', '') == args.project_id] - search_opts = {'all_tenants': 1} - groups = cs.security_groups.list(search_opts) - groups = [group for group in groups - if group.tenant_id == args.project_id] - for network in networks_list: - cs.networks.disassociate(network) - for group in groups: - cs.security_groups.delete(group) - - -@utils.arg('--fields', - default=None, - metavar='', - help='Comma-separated list of fields to display. ' - 'Use the show command to see which fields are available.') -def do_network_list(cs, args): - """Print a list of available networks.""" - network_list = cs.networks.list() - columns = ['ID', 'Label', 'Cidr'] - - formatters = {} - field_titles = [] - if args.fields: - for field in args.fields.split(','): - field_title, formatter = utils._make_field_formatter(field, {}) - field_titles.append(field_title) - formatters[field_title] = formatter - - columns = columns + field_titles - utils.print_list(network_list, columns) - - -@utils.arg('network', - metavar='', - help=_("uuid or label of network")) -def do_network_show(cs, args): - """Show details about the given network.""" - network = utils.find_resource(cs.networks, args.network) - utils.print_dict(network._info) - - -@utils.arg('network', - metavar='', - help=_("uuid or label of network")) -def do_network_delete(cs, args): - """Delete network by label or id.""" - network = utils.find_resource(cs.networks, args.network) - network.delete() - - -@utils.arg('--host-only', - dest='host_only', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0) -@utils.arg('--project-only', - dest='project_only', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0) -@utils.arg('network', - metavar='', - help="uuid of network") -def do_network_disassociate(cs, args): - """Disassociate host and/or project from the given network.""" - if args.host_only: - cs.networks.disassociate(args.network, True, False) - elif args.project_only: - cs.networks.disassociate(args.network, False, True) - else: - cs.networks.disassociate(args.network, True, True) - - -@utils.arg('network', - metavar='', - help="uuid of network") -@utils.arg('host', - metavar='', - help="Name of host") -def do_network_associate_host(cs, args): - """Associate host with network.""" - cs.networks.associate_host(args.network, args.host) - - -@utils.arg('network', - metavar='', - help="uuid of network") -def do_network_associate_project(cs, args): - """Associate project with network.""" - cs.networks.associate_project(args.network) - - -def _filter_network_create_options(args): - valid_args = ['label', 'cidr', 'vlan_start', 'vpn_start', 'cidr_v6', - 'gateway', 'gateway_v6', 'bridge', 'bridge_interface', - 'multi_host', 'dns1', 'dns2', 'uuid', 'fixed_cidr', - 'project_id', 'priority', 'vlan', 'mtu', 'dhcp_server', - 'allowed_start', 'allowed_end'] - kwargs = {} - for k, v in args.__dict__.items(): - if k in valid_args and v is not None: - kwargs[k] = v - - return kwargs - - -@utils.arg('label', - metavar='', - help=_("Label for network")) -@utils.arg('--fixed-range-v4', - dest='cidr', - metavar='', - help=_("IPv4 subnet (ex: 10.0.0.0/8)")) -@utils.arg('--fixed-range-v6', - dest="cidr_v6", - help=_('IPv6 subnet (ex: fe80::/64')) -@utils.arg('--vlan', - dest='vlan', - type=int, - metavar='', - help=_("The vlan ID to be assigned to the project.")) -@utils.arg('--vlan-start', - dest='vlan_start', - type=int, - metavar='', - help=_('First vlan ID to be assigned to the project. Subsequent vlan ' - 'IDs will be assigned incrementally.')) -@utils.arg('--vpn', - dest='vpn_start', - type=int, - metavar='', - help=_("vpn start")) -@utils.arg('--gateway', - dest="gateway", - help=_('gateway')) -@utils.arg('--gateway-v6', - dest="gateway_v6", - help=_('IPv6 gateway')) -@utils.arg('--bridge', - dest="bridge", - metavar='', - help=_('VIFs on this network are connected to this bridge.')) -@utils.arg('--bridge-interface', - dest="bridge_interface", - metavar='', - help=_('The bridge is connected to this interface.')) -@utils.arg('--multi-host', - dest="multi_host", - metavar="<'T'|'F'>", - help=_('Multi host')) -@utils.arg('--dns1', - dest="dns1", - metavar="", help='First DNS') -@utils.arg('--dns2', - dest="dns2", - metavar="", - help=_('Second DNS')) -@utils.arg('--uuid', - dest="uuid", - metavar="", - help=_('Network UUID')) -@utils.arg('--fixed-cidr', - dest="fixed_cidr", - metavar='', - help=_('IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)')) -@utils.arg('--project-id', - dest="project_id", - metavar="", - help=_('Project ID')) -@utils.arg('--priority', - dest="priority", - metavar="", - help=_('Network interface priority')) -@utils.arg('--mtu', - dest="mtu", - type=int, - help=_('MTU for network')) -@utils.arg('--enable-dhcp', - dest="enable_dhcp", - metavar="<'T'|'F'>", - help=_('Enable dhcp')) -@utils.arg('--dhcp-server', - dest="dhcp_server", - help=_('Dhcp-server (defaults to gateway address)')) -@utils.arg('--share-address', - dest="share_address", - metavar="<'T'|'F'>", - help=_('Share address')) -@utils.arg('--allowed-start', - dest="allowed_start", - help=_('Start of allowed addresses for instances')) -@utils.arg('--allowed-end', - dest="allowed_end", - help=_('End of allowed addresses for instances')) -def do_network_create(cs, args): - """Create a network.""" - - if not (args.cidr or args.cidr_v6): - raise exceptions.CommandError( - _("Must specify either fixed_range_v4 or fixed_range_v6")) - kwargs = _filter_network_create_options(args) - if args.multi_host is not None: - kwargs['multi_host'] = bool(args.multi_host == 'T' or - strutils.bool_from_string(args.multi_host)) - if args.enable_dhcp is not None: - kwargs['enable_dhcp'] = bool(args.enable_dhcp == 'T' or - strutils.bool_from_string(args.enable_dhcp)) - if args.share_address is not None: - kwargs['share_address'] = bool(args.share_address == 'T' or - strutils.bool_from_string(args.share_address)) - - cs.networks.create(**kwargs) - - -@utils.arg('--limit', - dest="limit", - metavar="", - help=_('Number of images to return per request.')) -def do_image_list(cs, _args): - """Print a list of available images to boot from.""" - limit = _args.limit - image_list = cs.images.list(limit=limit) - - def parse_server_name(image): - try: - return image.server['id'] - except (AttributeError, KeyError): - return '' - - fmts = {'Server': parse_server_name} - utils.print_list(image_list, ['ID', 'Name', 'Status', 'Server'], - fmts, sortby_index=1) - - -@utils.arg('image', - metavar='', - help=_("Name or ID of image")) -@utils.arg('action', - metavar='', - choices=['set', 'delete'], - help=_("Actions: 'set' or 'delete'")) -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to add/update or delete (only key is necessary on ' - 'delete)')) -def do_image_meta(cs, args): - """Set or Delete metadata on an image.""" - image = _find_image(cs, args.image) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.images.set_meta(image, metadata) - elif args.action == 'delete': - cs.images.delete_meta(image, metadata.keys()) - - -def _extract_metadata(args): - metadata = {} - for metadatum in args.metadata[0]: - # Can only pass the key in on 'delete' - # So this doesn't have to have '=' - if metadatum.find('=') > -1: - (key, value) = metadatum.split('=', 1) - else: - key = metadatum - value = None - - metadata[key] = value - return metadata - - -def _print_image(image): - info = image._info.copy() - - # ignore links, we don't need to present those - info.pop('links') - - # try to replace a server entity to just an id - server = info.pop('server', None) - try: - info['server'] = server['id'] - except (KeyError, TypeError): - pass - - # break up metadata and display each on its own row - metadata = info.pop('metadata', {}) - try: - for key, value in metadata.items(): - _key = 'metadata %s' % key - info[_key] = value - except AttributeError: - pass - - utils.print_dict(info) - - -def _print_flavor(flavor): - info = flavor._info.copy() - # ignore links, we don't need to present those - info.pop('links') - info.update({"extra_specs": _print_flavor_extra_specs(flavor)}) - utils.print_dict(info) - - -@utils.arg('image', - metavar='', - help=_("Name or ID of image")) -def do_image_show(cs, args): - """Show details about the given image.""" - image = _find_image(cs, args.image) - _print_image(image) - - -@utils.arg('image', metavar='', nargs='+', - help=_('Name or ID of image(s).')) -def do_image_delete(cs, args): - """Delete specified image(s).""" - for image in args.image: - try: - _find_image(cs, image).delete() - except Exception as e: - print(_("Delete for image %(image)s failed: %(e)s") % - {'image': image, 'e': e}) - - -@utils.arg('--reservation-id', - dest='reservation_id', - metavar='', - default=None, - help=_('Only return servers that match reservation-id.')) -@utils.arg('--reservation_id', - help=argparse.SUPPRESS) -@utils.arg('--ip', - dest='ip', - metavar='', - default=None, - help=_('Search with regular expression match by IP address.')) -@utils.arg('--ip6', - dest='ip6', - metavar='', - default=None, - help=_('Search with regular expression match by IPv6 address.')) -@utils.arg('--name', - dest='name', - metavar='', - default=None, - help=_('Search with regular expression match by name')) -@utils.arg('--instance-name', - dest='instance_name', - metavar='', - default=None, - help=_('Search with regular expression match by server name.')) -@utils.arg('--instance_name', - help=argparse.SUPPRESS) -@utils.arg('--status', - dest='status', - metavar='', - default=None, - help=_('Search by server status')) -@utils.arg('--flavor', - dest='flavor', - metavar='', - default=None, - help=_('Search by flavor name or ID')) -@utils.arg('--image', - dest='image', - metavar='', - default=None, - help=_('Search by image name or ID')) -@utils.arg('--host', - dest='host', - metavar='', - default=None, - help=_('Search servers by hostname to which they are assigned (Admin ' - 'only).')) -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help=_('Display information from all tenants (Admin only).')) -@utils.arg('--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@utils.arg('--tenant', - # nova db searches by project_id - dest='tenant', - metavar='', - nargs='?', - help=_('Display information from single tenant (Admin only).')) -@utils.arg('--deleted', - dest='deleted', - action="store_true", - default=False, - help='Only display deleted servers (Admin only).') -@utils.arg('--fields', - default=None, - metavar='', - help=_('Comma-separated list of fields to display. ' - 'Use the show command to see which fields are available.')) -@utils.arg('--minimal', - dest='minimal', - action="store_true", - default=False, - help=_('Get only uuid and name.')) -def do_list(cs, args): - """List active servers.""" - imageid = None - flavorid = None - if args.image: - imageid = _find_image(cs, args.image).id - if args.flavor: - flavorid = _find_flavor(cs, args.flavor).id - search_opts = { - 'all_tenants': args.all_tenants, - 'reservation_id': args.reservation_id, - 'ip': args.ip, - 'ip6': args.ip6, - 'name': args.name, - 'image': imageid, - 'flavor': flavorid, - 'status': args.status, - 'tenant_id': args.tenant, - 'host': args.host, - 'deleted': args.deleted, - 'instance_name': args.instance_name} - - filters = {'flavor': lambda f: f['id'], - 'security_groups': utils._format_security_groups} - - formatters = {} - field_titles = [] - if args.fields: - for field in args.fields.split(','): - field_title, formatter = utils._make_field_formatter(field, - filters) - field_titles.append(field_title) - formatters[field_title] = formatter - - id_col = 'ID' - - detailed = not args.minimal - - servers = cs.servers.list(detailed=detailed, - search_opts=search_opts) - convert = [('OS-EXT-SRV-ATTR:host', 'host'), - ('OS-EXT-STS:task_state', 'task_state'), - ('OS-EXT-SRV-ATTR:instance_name', 'instance_name'), - ('OS-EXT-STS:power_state', 'power_state'), - ('hostId', 'host_id')] - _translate_keys(servers, convert) - _translate_extended_states(servers) - if args.minimal: - columns = [ - id_col, - 'Name'] - elif field_titles: - columns = [id_col] + field_titles - else: - columns = [ - id_col, - 'Name', - 'Status', - 'Task State', - 'Power State', - 'Networks' - ] - formatters['Networks'] = utils._format_servers_list_networks - utils.print_list(servers, columns, - formatters, sortby_index=1) - - -@utils.arg('--hard', - dest='reboot_type', - action='store_const', - const=servers.REBOOT_HARD, - default=servers.REBOOT_SOFT, - help=_('Perform a hard reboot (instead of a soft one).')) -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help=_('Poll until reboot is complete.')) -def do_reboot(cs, args): - """Reboot a server.""" - server = _find_server(cs, args.server) - server.reboot(args.reboot_type) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'rebooting', ['active'], - show_progress=False) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('image', metavar='', help=_("Name or ID of new image.")) -@utils.arg('--rebuild-password', - dest='rebuild_password', - metavar='', - default=False, - help=_("Set the provided password on the rebuild server.")) -@utils.arg('--rebuild_password', - help=argparse.SUPPRESS) -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the server rebuild progress until it completes.')) -@utils.arg('--minimal', - dest='minimal', - action="store_true", - default=False, - help=_('Skips flavor/image lookups when showing servers')) -@utils.arg('--preserve-ephemeral', - action="store_true", - default=False, - help='Preserve the default ephemeral storage partition on rebuild.') -@utils.arg('--name', - metavar='', - default=None, - help=_('Name for the new server')) -@utils.arg('--meta', - metavar="", - action='append', - default=[], - help=_("Record arbitrary key/value metadata to /meta.js " - "on the new server. Can be specified multiple times.")) -@utils.arg('--file', - metavar="", - action='append', - dest='files', - default=[], - help=_("Store arbitrary files from locally to " - "on the new server. You may store up to 5 files.")) -def do_rebuild(cs, args): - """Shutdown, re-image, and re-boot a server.""" - server = _find_server(cs, args.server) - image = _find_image(cs, args.image) - - if args.rebuild_password is not False: - _password = args.rebuild_password - else: - _password = None - - kwargs = utils.get_resource_manager_extra_kwargs(do_rebuild, args) - kwargs['preserve_ephemeral'] = args.preserve_ephemeral - kwargs['name'] = args.name - meta = dict(v.split('=', 1) for v in args.meta) - kwargs['meta'] = meta - - files = {} - for f in args.files: - try: - dst, src = f.split('=', 1) - with open(src, 'r') as s: - files[dst] = s.read() - except IOError as e: - raise exceptions.CommandError(_("Can't open '%(src)s': %(exc)s") % - {'src': src, 'exc': e}) - except ValueError as e: - raise exceptions.CommandError(_("Invalid file argument '%s'. " - "File arguments must be of the " - "form '--file " - "'") % f) - kwargs['files'] = files - server = server.rebuild(image, _password, **kwargs) - _print_server(cs, args, server) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'rebuilding', ['active']) - - -@utils.arg('server', metavar='', - help=_('Name (old name) or ID of server.')) -@utils.arg('name', metavar='', help=_('New name for the server.')) -def do_rename(cs, args): - """Rename a server.""" - _find_server(cs, args.server).update(name=args.name) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('flavor', metavar='', help=_("Name or ID of new flavor.")) -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the server resize progress until it completes.')) -def do_resize(cs, args): - """Resize a server.""" - server = _find_server(cs, args.server) - flavor = _find_flavor(cs, args.flavor) - kwargs = utils.get_resource_manager_extra_kwargs(do_resize, args) - server.resize(flavor, **kwargs) - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'resizing', - ['active', 'verify_resize']) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_resize_confirm(cs, args): - """Confirm a previous resize.""" - _find_server(cs, args.server).confirm_resize() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_resize_revert(cs, args): - """Revert a previous resize (and return to the previous VM).""" - _find_server(cs, args.server).revert_resize() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the server migration progress until it completes.')) -def do_migrate(cs, args): - """Migrate a server. The new host will be selected by the scheduler.""" - server = _find_server(cs, args.server) - server.migrate() - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'migrating', - ['active', 'verify_resize']) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_pause(cs, args): - """Pause a server.""" - _find_server(cs, args.server).pause() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unpause(cs, args): - """Unpause a server.""" - _find_server(cs, args.server).unpause() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_stop(cs, args): - """Stop a server.""" - _find_server(cs, args.server).stop() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_start(cs, args): - """Start a server.""" - _find_server(cs, args.server).start() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_lock(cs, args): - """Lock a server.""" - _find_server(cs, args.server).lock() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unlock(cs, args): - """Unlock a server.""" - _find_server(cs, args.server).unlock() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_suspend(cs, args): - """Suspend a server.""" - _find_server(cs, args.server).suspend() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_resume(cs, args): - """Resume a server.""" - _find_server(cs, args.server).resume() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_rescue(cs, args): - """Reboots a server into rescue mode, which starts the machine - from the initial image, attaching the current boot disk as secondary. - """ - utils.print_dict(_find_server(cs, args.server).rescue()[1]) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unrescue(cs, args): - """Restart the server from normal boot disk again.""" - _find_server(cs, args.server).unrescue() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_shelve(cs, args): - """Shelve a server.""" - _find_server(cs, args.server).shelve() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_shelve_offload(cs, args): - """Remove a shelved server from the compute node.""" - _find_server(cs, args.server).shelve_offload() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unshelve(cs, args): - """Unshelve a server.""" - _find_server(cs, args.server).unshelve() - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_diagnostics(cs, args): - """Retrieve server diagnostics.""" - server = _find_server(cs, args.server) - utils.print_dict(cs.servers.diagnostics(server)[1], wrap=80) - - -@utils.arg('server', metavar='', - help=_('Name or ID of a server for which the network cache should ' - 'be refreshed from neutron (Admin only).')) -def do_refresh_network(cs, args): - """Refresh server network information.""" - server = _find_server(cs, args.server) - cs.server_external_events.create([{'server_uuid': server.id, - 'name': 'network-changed'}]) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_root_password(cs, args): - """ - Change the root password for a server. - """ - server = _find_server(cs, args.server) - p1 = getpass.getpass('New password: ') - p2 = getpass.getpass('Again: ') - if p1 != p2: - raise exceptions.CommandError(_("Passwords do not match.")) - server.change_password(p1) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('name', metavar='', help=_('Name of snapshot.')) -@utils.arg('--show', - dest='show', - action="store_true", - default=False, - help=_('Print image info.')) -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the snapshot progress and poll until image creation is ' - 'complete.')) -def do_image_create(cs, args): - """Create a new image by taking a snapshot of a running server.""" - server = _find_server(cs, args.server) - image_uuid = cs.servers.create_image(server, args.name) - - if args.poll: - _poll_for_status(cs.images.get, image_uuid, 'snapshotting', - ['active']) - - # NOTE(sirp): A race-condition exists between when the image finishes - # uploading and when the servers's `task_state` is cleared. To account - # for this, we need to poll a second time to ensure the `task_state` is - # cleared before returning, ensuring that a snapshot taken immediately - # after this function returns will succeed. - # - # A better long-term solution will be to separate 'snapshotting' and - # 'image-uploading' in Nova and clear the task-state once the VM - # snapshot is complete but before the upload begins. - task_state_field = "OS-EXT-STS:task_state" - if hasattr(server, task_state_field): - _poll_for_status(cs.servers.get, server.id, 'image_snapshot', - [None], status_field=task_state_field, - show_progress=False, silent=True) - - if args.show: - _print_image(cs.images.get(image_uuid)) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('name', metavar='', help=_('Name of the backup image.')) -@utils.arg('backup_type', metavar='', - help=_('The backup type, like "daily" or "weekly".')) -@utils.arg('rotation', metavar='', - help=_('Int parameter representing how many backups to keep ' - 'around.')) -def do_backup(cs, args): - """Backup a server by creating a 'backup' type snapshot.""" - _find_server(cs, args.server).backup(args.name, - args.backup_type, - args.rotation) - - -@utils.arg('server', - metavar='', - help=_("Name or ID of server")) -@utils.arg('action', - metavar='', - choices=['set', 'delete'], - help=_("Actions: 'set' or 'delete'")) -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to set or delete (only key is necessary on delete)')) -def do_meta(cs, args): - """Set or Delete metadata on a server.""" - server = _find_server(cs, args.server) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.servers.set_meta(server, metadata) - elif args.action == 'delete': - cs.servers.delete_meta(server, sorted(metadata.keys(), reverse=True)) - - -def _print_server(cs, args, server=None): - # By default when searching via name we will do a - # findall(name=blah) and due a REST /details which is not the same - # as a .get() and doesn't get the information about flavors and - # images. This fix it as we redo the call with the id which does a - # .get() to get all informations. - if not server: - server = _find_server(cs, args.server) - - minimal = getattr(args, "minimal", False) - - networks = server.networks - info = server._info.copy() - for network_label, address_list in networks.items(): - info['%s network' % network_label] = ', '.join(address_list) - - flavor = info.get('flavor', {}) - flavor_id = flavor.get('id', '') - if minimal: - info['flavor'] = flavor_id - else: - info['flavor'] = '%s (%s)' % (_find_flavor(cs, flavor_id).name, - flavor_id) - - if 'security_groups' in info: - # when we have multiple nics the info will include the - # security groups N times where N == number of nics. Be nice - # and only display it once. - info['security_groups'] = ', '.join( - sorted(set(group['name'] for group in info['security_groups']))) - - image = info.get('image', {}) - if image: - image_id = image.get('id', '') - if minimal: - info['image'] = image_id - else: - try: - info['image'] = '%s (%s)' % (_find_image(cs, image_id).name, - image_id) - except Exception: - info['image'] = '%s (%s)' % (_("Image not found"), image_id) - else: # Booted from volume - info['image'] = _("Attempt to boot from volume - no image supplied") - - info.pop('links', None) - info.pop('addresses', None) - - utils.print_dict(info) - - -@utils.arg('--minimal', - dest='minimal', - action="store_true", - default=False, - help=_('Skips flavor/image lookups when showing servers')) -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_show(cs, args): - """Show details about the given server.""" - _print_server(cs, args) - - -@utils.arg('server', metavar='', nargs='+', - help=_('Name or ID of server(s).')) -def do_delete(cs, args): - """Immediately shut down and delete specified server(s).""" - failure_flag = False - - for server in args.server: - try: - _find_server(cs, server).delete() - print(_("Request to delete server %s has been accepted.") % server) - except Exception as e: - failure_flag = True - print(e) - - if failure_flag: - raise exceptions.CommandError(_("Unable to delete the " - "specified server(s).")) - - -def _find_server(cs, server): - """Get a server by name or ID.""" - return utils.find_resource(cs.servers, server) - - -def _find_image(cs, image): - """Get an image by name or ID.""" - return utils.find_resource(cs.images, image) - - -def _find_flavor(cs, flavor): - """Get a flavor by name, ID, or RAM size.""" - try: - return utils.find_resource(cs.flavors, flavor, is_public=None) - except exceptions.NotFound: - return cs.flavors.find(ram=flavor) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('network_id', - metavar='', - help='Network ID.') -def do_add_fixed_ip(cs, args): - """Add new IP address on a network to server.""" - server = _find_server(cs, args.server) - server.add_fixed_ip(args.network_id) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('address', metavar='
', help=_('IP Address.')) -def do_remove_fixed_ip(cs, args): - """Remove an IP address from a server.""" - server = _find_server(cs, args.server) - server.remove_fixed_ip(args.address) - - -def _find_volume(cs, volume): - """Get a volume by name or ID.""" - return utils.find_resource(cs.volumes, volume) - - -def _find_volume_snapshot(cs, snapshot): - """Get a volume snapshot by name or ID.""" - return utils.find_resource(cs.volume_snapshots, snapshot) - - -def _print_volume(volume): - utils.print_dict(volume._info) - - -def _print_volume_snapshot(snapshot): - utils.print_dict(snapshot._info) - - -def _translate_volume_keys(collection): - _translate_keys(collection, - [('displayName', 'display_name'), - ('volumeType', 'volume_type')]) - - -def _translate_volume_snapshot_keys(collection): - _translate_keys(collection, - [('displayName', 'display_name'), - ('volumeId', 'volume_id')]) - - -def _translate_availability_zone_keys(collection): - _translate_keys(collection, - [('zoneName', 'name'), ('zoneState', 'status')]) - - -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help=_('Display information from all tenants (Admin only).')) -@utils.arg('--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@utils.service_type('volume') -def do_volume_list(cs, args): - """List all the volumes.""" - search_opts = {'all_tenants': args.all_tenants} - volumes = cs.volumes.list(search_opts=search_opts) - _translate_volume_keys(volumes) - - # Create a list of servers to which the volume is attached - for vol in volumes: - servers = [s.get('server_id') for s in vol.attachments] - setattr(vol, 'attached_to', ','.join(map(str, servers))) - utils.print_list(volumes, ['ID', 'Status', 'Display Name', - 'Size', 'Volume Type', 'Attached to']) - - -@utils.arg('volume', metavar='', help=_('Name or ID of the volume.')) -@utils.service_type('volume') -def do_volume_show(cs, args): - """Show details about a volume.""" - volume = _find_volume(cs, args.volume) - _print_volume(volume) - - -@utils.arg('size', - metavar='', - type=int, - help=_('Size of volume in GB')) -@utils.arg('--snapshot-id', - metavar='', - default=None, - help=_('Optional snapshot id to create the volume from. (Default=None)')) -@utils.arg('--snapshot_id', - help=argparse.SUPPRESS) -@utils.arg('--image-id', - metavar='', - help=_('Optional image id to create the volume from. (Default=None)'), - default=None) -@utils.arg('--display-name', - metavar='', - default=None, - help=_('Optional volume name. (Default=None)')) -@utils.arg('--display_name', - help=argparse.SUPPRESS) -@utils.arg('--display-description', - metavar='', - default=None, - help=_('Optional volume description. (Default=None)')) -@utils.arg('--display_description', - help=argparse.SUPPRESS) -@utils.arg('--volume-type', - metavar='', - default=None, - help=_('Optional volume type. (Default=None)')) -@utils.arg('--volume_type', - help=argparse.SUPPRESS) -@utils.arg('--availability-zone', metavar='', - help=_('Optional Availability Zone for volume. (Default=None)'), - default=None) -@utils.service_type('volume') -def do_volume_create(cs, args): - """Add a new volume.""" - volume = cs.volumes.create(args.size, - args.snapshot_id, - args.display_name, - args.display_description, - args.volume_type, - args.availability_zone, - imageRef=args.image_id) - _print_volume(volume) - - -@utils.arg('volume', - metavar='', nargs='+', - help=_('Name or ID of the volume(s) to delete.')) -@utils.service_type('volume') -def do_volume_delete(cs, args): - """Remove volume(s).""" - for volume in args.volume: - try: - _find_volume(cs, volume).delete() - except Exception as e: - print(_("Delete for volume %(volume)s failed: %(e)s") % - {'volume': volume, 'e': e}) - - -@utils.arg('server', - metavar='', - help=_('Name or ID of server.')) -@utils.arg('volume', - metavar='', - help=_('ID of the volume to attach.')) -@utils.arg('device', metavar='', default=None, nargs='?', - help=_('Name of the device e.g. /dev/vdb. ' - 'Use "auto" for autoassign (if supported)')) -def do_volume_attach(cs, args): - """Attach a volume to a server.""" - if args.device == 'auto': - args.device = None - - volume = cs.volumes.create_server_volume(_find_server(cs, args.server).id, - args.volume, - args.device) - _print_volume(volume) - - -@utils.arg('server', - metavar='', - help=_('Name or ID of server.')) -@utils.arg('attachment_id', - metavar='', - help=_('Attachment ID of the volume.')) -@utils.arg('new_volume', - metavar='', - help=_('ID of the volume to attach.')) -def do_volume_update(cs, args): - """Update volume attachment.""" - cs.volumes.update_server_volume(_find_server(cs, args.server).id, - args.attachment_id, - args.new_volume) - - -@utils.arg('server', - metavar='', - help=_('Name or ID of server.')) -@utils.arg('attachment_id', - metavar='', - help=_('ID of the volume to detach.')) -def do_volume_detach(cs, args): - """Detach a volume from a server.""" - cs.volumes.delete_server_volume(_find_server(cs, args.server).id, - args.attachment_id) - - -@utils.service_type('volume') -def do_volume_snapshot_list(cs, _args): - """List all the snapshots.""" - snapshots = cs.volume_snapshots.list() - _translate_volume_snapshot_keys(snapshots) - utils.print_list(snapshots, ['ID', 'Volume ID', 'Status', 'Display Name', - 'Size']) - - -@utils.arg('snapshot', - metavar='', - help=_('Name or ID of the snapshot.')) -@utils.service_type('volume') -def do_volume_snapshot_show(cs, args): - """Show details about a snapshot.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - _print_volume_snapshot(snapshot) - - -@utils.arg('volume_id', - metavar='', - help=_('ID of the volume to snapshot')) -@utils.arg('--force', - metavar='', - help=_('Optional flag to indicate whether to snapshot a volume even if ' - 'its attached to a server. (Default=False)'), - default=False) -@utils.arg('--display-name', - metavar='', - default=None, - help=_('Optional snapshot name. (Default=None)')) -@utils.arg('--display_name', - help=argparse.SUPPRESS) -@utils.arg('--display-description', - metavar='', - default=None, - help=_('Optional snapshot description. (Default=None)')) -@utils.arg('--display_description', - help=argparse.SUPPRESS) -@utils.service_type('volume') -def do_volume_snapshot_create(cs, args): - """Add a new snapshot.""" - snapshot = cs.volume_snapshots.create(args.volume_id, - args.force, - args.display_name, - args.display_description) - _print_volume_snapshot(snapshot) - - -@utils.arg('snapshot', - metavar='', - help=_('Name or ID of the snapshot to delete.')) -@utils.service_type('volume') -def do_volume_snapshot_delete(cs, args): - """Remove a snapshot.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - snapshot.delete() - - -def _print_volume_type_list(vtypes): - utils.print_list(vtypes, ['ID', 'Name']) - - -@utils.service_type('volume') -def do_volume_type_list(cs, args): - """Print a list of available 'volume types'.""" - vtypes = cs.volume_types.list() - _print_volume_type_list(vtypes) - - -@utils.arg('name', - metavar='', - help=_("Name of the new volume type")) -@utils.service_type('volume') -def do_volume_type_create(cs, args): - """Create a new volume type.""" - vtype = cs.volume_types.create(args.name) - _print_volume_type_list([vtype]) - - -@utils.arg('id', - metavar='', - help=_("Unique ID of the volume type to delete")) -@utils.service_type('volume') -def do_volume_type_delete(cs, args): - """Delete a specific volume type.""" - cs.volume_types.delete(args.id) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('console_type', - metavar='', - help=_('Type of vnc console ("novnc" or "xvpvnc").')) -def do_get_vnc_console(cs, args): - """Get a vnc console to a server.""" - server = _find_server(cs, args.server) - data = server.get_vnc_console(args.console_type) - - class VNCConsole: - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([VNCConsole(data['console'])], ['Type', 'Url']) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('console_type', - metavar='', - help=_('Type of spice console ("spice-html5").')) -def do_get_spice_console(cs, args): - """Get a spice console to a server.""" - server = _find_server(cs, args.server) - data = server.get_spice_console(args.console_type) - - class SPICEConsole: - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([SPICEConsole(data['console'])], ['Type', 'Url']) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('console_type', - metavar='', - help='Type of rdp console ("rdp-html5").') -def do_get_rdp_console(cs, args): - """Get a rdp console to a server.""" - server = _find_server(cs, args.server) - data = server.get_rdp_console(args.console_type) - - class RDPConsole: - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([RDPConsole(data['console'])], ['Type', 'Url']) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('--console_type', default='serial', - help=_('Type of serial console, default="serial".')) -def do_get_serial_console(cs, args): - """Get a serial console to a server.""" - if args.console_type not in ('serial',): - raise exceptions.CommandError( - _("Invalid parameter value for 'console_type', " - "currently supported 'serial'.")) - - server = _find_server(cs, args.server) - data = server.get_serial_console(args.console_type) - - class SerialConsole: - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([SerialConsole(data['console'])], ['Type', 'Url']) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('private_key', - metavar='', - help=_('Private key (used locally to decrypt password) (Optional). ' - 'When specified, the command displays the clear (decrypted) VM ' - 'password. When not specified, the ciphered VM password is ' - 'displayed.'), - nargs='?', - default=None) -def do_get_password(cs, args): - """Get password for a server.""" - server = _find_server(cs, args.server) - data = server.get_password(args.private_key) - print(data) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_clear_password(cs, args): - """Clear password for a server.""" - server = _find_server(cs, args.server) - server.clear_password() - - -def _print_floating_ip_list(floating_ips): - convert = [('instance_id', 'server_id')] - _translate_keys(floating_ips, convert) - - utils.print_list(floating_ips, ['Ip', 'Server Id', 'Fixed Ip', 'Pool']) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('--length', - metavar='', - default=None, - help=_('Length in lines to tail.')) -def do_console_log(cs, args): - """Get console log output of a server.""" - server = _find_server(cs, args.server) - data = server.get_console_output(length=args.length) - print(data) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('address', metavar='
', help=_('IP Address.')) -@utils.arg('--fixed-address', - metavar='', - default=None, - help=_('Fixed IP Address to associate with.')) -def do_add_floating_ip(cs, args): - """DEPRECATED, use floating-ip-associate instead.""" - _associate_floating_ip(cs, args) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('address', metavar='
', help='IP Address.') -@utils.arg('--fixed-address', - metavar='', - default=None, - help='Fixed IP Address to associate with.') -def do_floating_ip_associate(cs, args): - """Associate a floating IP address to a server.""" - _associate_floating_ip(cs, args) - - -def _associate_floating_ip(cs, args): - server = _find_server(cs, args.server) - server.add_floating_ip(args.address, args.fixed_address) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('address', metavar='
', help=_('IP Address.')) -def do_remove_floating_ip(cs, args): - """DEPRECATED, use floating-ip-disassociate instead.""" - _disassociate_floating_ip(cs, args) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('address', metavar='
', help='IP Address.') -def do_floating_ip_disassociate(cs, args): - """Disassociate a floating IP address from a server.""" - _disassociate_floating_ip(cs, args) - - -def _disassociate_floating_ip(cs, args): - server = _find_server(cs, args.server) - server.remove_floating_ip(args.address) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('secgroup', metavar='', help=_('Name of Security Group.')) -def do_add_secgroup(cs, args): - """Add a Security Group to a server.""" - server = _find_server(cs, args.server) - server.add_security_group(args.secgroup) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('secgroup', metavar='', help=_('Name of Security Group.')) -def do_remove_secgroup(cs, args): - """Remove a Security Group from a server.""" - server = _find_server(cs, args.server) - server.remove_security_group(args.secgroup) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_list_secgroup(cs, args): - """List Security Group(s) of a server.""" - server = _find_server(cs, args.server) - groups = server.list_security_group() - _print_secgroups(groups) - - -@utils.arg('pool', - metavar='', - help=_('Name of Floating IP Pool. (Optional)'), - nargs='?', - default=None) -def do_floating_ip_create(cs, args): - """Allocate a floating IP for the current tenant.""" - _print_floating_ip_list([cs.floating_ips.create(pool=args.pool)]) - - -@utils.arg('address', metavar='
', help=_('IP of Floating Ip.')) -def do_floating_ip_delete(cs, args): - """De-allocate a floating IP.""" - floating_ips = cs.floating_ips.list() - for floating_ip in floating_ips: - if floating_ip.ip == args.address: - return cs.floating_ips.delete(floating_ip.id) - raise exceptions.CommandError(_("Floating ip %s not found.") % - args.address) - - -@utils.arg('--all-tenants', - action='store_true', - default=False, - help=_('Display floatingips from all tenants (Admin only).')) -def do_floating_ip_list(cs, args): - """List floating ips.""" - _print_floating_ip_list(cs.floating_ips.list(args.all_tenants)) - - -def do_floating_ip_pool_list(cs, _args): - """List all floating ip pools.""" - utils.print_list(cs.floating_ip_pools.list(), ['name']) - - -@utils.arg('--host', dest='host', metavar='', default=None, - help=_('Filter by host')) -def do_floating_ip_bulk_list(cs, args): - """List all floating ips.""" - utils.print_list(cs.floating_ips_bulk.list(args.host), ['project_id', - 'address', - 'instance_uuid', - 'pool', - 'interface']) - - -@utils.arg('ip_range', metavar='', help=_('Address range to create')) -@utils.arg('--pool', dest='pool', metavar='', default=None, - help=_('Pool for new Floating IPs')) -@utils.arg('--interface', metavar='', default=None, - help=_('Interface for new Floating IPs')) -def do_floating_ip_bulk_create(cs, args): - """Bulk create floating ips by range.""" - cs.floating_ips_bulk.create(args.ip_range, args.pool, args.interface) - - -@utils.arg('ip_range', metavar='', help=_('Address range to delete')) -def do_floating_ip_bulk_delete(cs, args): - """Bulk delete floating ips by range.""" - cs.floating_ips_bulk.delete(args.ip_range) - - -def _print_dns_list(dns_entries): - utils.print_list(dns_entries, ['ip', 'name', 'domain']) - - -def _print_domain_list(domain_entries): - utils.print_list(domain_entries, ['domain', 'scope', - 'project', 'availability_zone']) - - -def do_dns_domains(cs, args): - """Print a list of available dns domains.""" - domains = cs.dns_domains.domains() - _print_domain_list(domains) - - -@utils.arg('domain', metavar='', help=_('DNS domain')) -@utils.arg('--ip', metavar='', help=_('ip address'), default=None) -@utils.arg('--name', metavar='', help=_('DNS name'), default=None) -def do_dns_list(cs, args): - """List current DNS entries for domain and ip or domain and name.""" - if not (args.ip or args.name): - raise exceptions.CommandError( - _("You must specify either --ip or --name")) - if args.name: - entry = cs.dns_entries.get(args.domain, args.name) - _print_dns_list([entry]) - else: - entries = cs.dns_entries.get_for_ip(args.domain, - ip=args.ip) - _print_dns_list(entries) - - -@utils.arg('ip', metavar='', help=_('ip address')) -@utils.arg('name', metavar='', help=_('DNS name')) -@utils.arg('domain', metavar='', help=_('DNS domain')) -@utils.arg('--type', metavar='', help=_('dns type (e.g. "A")'), - default='A') -def do_dns_create(cs, args): - """Create a DNS entry for domain, name and ip.""" - cs.dns_entries.create(args.domain, args.name, args.ip, args.type) - - -@utils.arg('domain', metavar='', help=_('DNS domain')) -@utils.arg('name', metavar='', help=_('DNS name')) -def do_dns_delete(cs, args): - """Delete the specified DNS entry.""" - cs.dns_entries.delete(args.domain, args.name) - - -@utils.arg('domain', metavar='', help=_('DNS domain')) -def do_dns_delete_domain(cs, args): - """Delete the specified DNS domain.""" - cs.dns_domains.delete(args.domain) - - -@utils.arg('domain', metavar='', help=_('DNS domain')) -@utils.arg('--availability-zone', - metavar='', - default=None, - help=_('Limit access to this domain to servers ' - 'in the specified availability zone.')) -@utils.arg('--availability_zone', - help=argparse.SUPPRESS) -def do_dns_create_private_domain(cs, args): - """Create the specified DNS domain.""" - cs.dns_domains.create_private(args.domain, - args.availability_zone) - - -@utils.arg('domain', metavar='', help=_('DNS domain')) -@utils.arg('--project', metavar='', - help=_('Limit access to this domain to users ' - 'of the specified project.'), - default=None) -def do_dns_create_public_domain(cs, args): - """Create the specified DNS domain.""" - cs.dns_domains.create_public(args.domain, - args.project) - - -def _print_secgroup_rules(rules, show_source_group=True): - class FormattedRule: - def __init__(self, obj): - items = (obj if isinstance(obj, dict) else obj._info).items() - for k, v in items: - if k == 'ip_range': - v = v.get('cidr') - elif k == 'group': - k = 'source_group' - v = v.get('name') - if v is None: - v = '' - - setattr(self, k, v) - - rules = [FormattedRule(rule) for rule in rules] - headers = ['IP Protocol', 'From Port', 'To Port', 'IP Range'] - if show_source_group: - headers.append('Source Group') - utils.print_list(rules, headers) - - -def _print_secgroups(secgroups): - utils.print_list(secgroups, ['Id', 'Name', 'Description']) - - -def _get_secgroup(cs, secgroup): - # Check secgroup is an ID (nova-network) or UUID (neutron) - if (utils.is_integer_like(encodeutils.safe_encode(secgroup)) - or uuidutils.is_uuid_like(secgroup)): - try: - return cs.security_groups.get(secgroup) - except exceptions.NotFound: - pass - - # Check secgroup as a name - match_found = False - for s in cs.security_groups.list(): - encoding = (locale.getpreferredencoding() or - sys.stdin.encoding or - 'UTF-8') - if not six.PY3: - s.name = s.name.encode(encoding) - if secgroup == s.name: - if match_found is not False: - msg = (_("Multiple security group matches found for name '%s'" - ", use an ID to be more specific.") % secgroup) - raise exceptions.NoUniqueMatch(msg) - match_found = s - if match_found is False: - raise exceptions.CommandError(_("Secgroup ID or name '%s' not found.") - % secgroup) - return match_found - - -@utils.arg('secgroup', - metavar='', - help=_('ID or name of security group.')) -@utils.arg('ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@utils.arg('from_port', - metavar='', - help=_('Port at start of range.')) -@utils.arg('to_port', - metavar='', - help=_('Port at end of range.')) -@utils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_add_rule(cs, args): - """Add a rule to a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - rule = cs.security_group_rules.create(secgroup.id, - args.ip_proto, - args.from_port, - args.to_port, - args.cidr) - _print_secgroup_rules([rule]) - - -@utils.arg('secgroup', - metavar='', - help=_('ID or name of security group.')) -@utils.arg('ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@utils.arg('from_port', - metavar='', - help=_('Port at start of range.')) -@utils.arg('to_port', - metavar='', - help=_('Port at end of range.')) -@utils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_delete_rule(cs, args): - """Delete a rule from a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - for rule in secgroup.rules: - if (rule['ip_protocol'] and - rule['ip_protocol'].upper() == args.ip_proto.upper() and - rule['from_port'] == int(args.from_port) and - rule['to_port'] == int(args.to_port) and - rule['ip_range']['cidr'] == args.cidr): - _print_secgroup_rules([rule]) - return cs.security_group_rules.delete(rule['id']) - - raise exceptions.CommandError(_("Rule not found")) - - -@utils.arg('name', metavar='', help=_('Name of security group.')) -@utils.arg('description', metavar='', - help=_('Description of security group.')) -def do_secgroup_create(cs, args): - """Create a security group.""" - secgroup = cs.security_groups.create(args.name, args.description) - _print_secgroups([secgroup]) - - -@utils.arg('secgroup', - metavar='', - help=_('ID or name of security group.')) -@utils.arg('name', metavar='', help=_('Name of security group.')) -@utils.arg('description', metavar='', - help=_('Description of security group.')) -def do_secgroup_update(cs, args): - """Update a security group.""" - sg = _get_secgroup(cs, args.secgroup) - secgroup = cs.security_groups.update(sg, args.name, args.description) - _print_secgroups([secgroup]) - - -@utils.arg('secgroup', - metavar='', - help=_('ID or name of security group.')) -def do_secgroup_delete(cs, args): - """Delete a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - cs.security_groups.delete(secgroup) - _print_secgroups([secgroup]) - - -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help=_('Display information from all tenants (Admin only).')) -@utils.arg('--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -def do_secgroup_list(cs, args): - """List security groups for the current tenant.""" - search_opts = {'all_tenants': args.all_tenants} - columns = ['Id', 'Name', 'Description'] - if args.all_tenants: - columns.append('Tenant_ID') - groups = cs.security_groups.list(search_opts=search_opts) - utils.print_list(groups, columns) - - -@utils.arg('secgroup', - metavar='', - help=_('ID or name of security group.')) -def do_secgroup_list_rules(cs, args): - """List rules for a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - _print_secgroup_rules(secgroup.rules) - - -@utils.arg('secgroup', - metavar='', - help=_('ID or name of security group.')) -@utils.arg('source_group', - metavar='', - help=_('ID or name of source group.')) -@utils.arg('ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@utils.arg('from_port', - metavar='', - help=_('Port at start of range.')) -@utils.arg('to_port', - metavar='', - help=_('Port at end of range.')) -def do_secgroup_add_group_rule(cs, args): - """Add a source group rule to a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - source_group = _get_secgroup(cs, args.source_group) - params = {} - params['group_id'] = source_group.id - - if args.ip_proto or args.from_port or args.to_port: - if not (args.ip_proto and args.from_port and args.to_port): - raise exceptions.CommandError(_("ip_proto, from_port, and to_port" - " must be specified together")) - params['ip_protocol'] = args.ip_proto.upper() - params['from_port'] = args.from_port - params['to_port'] = args.to_port - - rule = cs.security_group_rules.create(secgroup.id, **params) - _print_secgroup_rules([rule]) - - -@utils.arg('secgroup', - metavar='', - help=_('ID or name of security group.')) -@utils.arg('source_group', - metavar='', - help=_('ID or name of source group.')) -@utils.arg('ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@utils.arg('from_port', - metavar='', - help=_('Port at start of range.')) -@utils.arg('to_port', - metavar='', - help=_('Port at end of range.')) -def do_secgroup_delete_group_rule(cs, args): - """Delete a source group rule from a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - source_group = _get_secgroup(cs, args.source_group) - params = {} - params['group_name'] = source_group.name - - if args.ip_proto or args.from_port or args.to_port: - if not (args.ip_proto and args.from_port and args.to_port): - raise exceptions.CommandError(_("ip_proto, from_port, and to_port" - " must be specified together")) - params['ip_protocol'] = args.ip_proto.upper() - params['from_port'] = int(args.from_port) - params['to_port'] = int(args.to_port) - - for rule in secgroup.rules: - if (rule.get('ip_protocol').upper() == params.get( - 'ip_protocol').upper() and - rule.get('from_port') == params.get('from_port') and - rule.get('to_port') == params.get('to_port') and - rule.get('group', {}).get('name') == - params.get('group_name')): - return cs.security_group_rules.delete(rule['id']) - - raise exceptions.CommandError(_("Rule not found")) - - -@utils.arg('name', metavar='', help=_('Name of key.')) -@utils.arg('--pub-key', - metavar='', - default=None, - help=_('Path to a public ssh key.')) -@utils.arg('--pub_key', - help=argparse.SUPPRESS) -def do_keypair_add(cs, args): - """Create a new key pair for use with servers.""" - name = args.name - pub_key = args.pub_key - - if pub_key: - try: - with open(os.path.expanduser(pub_key)) as f: - pub_key = f.read() - except IOError as e: - raise exceptions.CommandError(_("Can't open or read '%(key)s': " - "%(exc)s") % {'key': pub_key, - 'exc': e}) - - keypair = cs.keypairs.create(name, pub_key) - - if not pub_key: - private_key = keypair.private_key - print(private_key) - - -@utils.arg('name', metavar='', help=_('Keypair name to delete.')) -def do_keypair_delete(cs, args): - """Delete keypair given by its name.""" - name = _find_keypair(cs, args.name) - cs.keypairs.delete(name) - - -def do_keypair_list(cs, args): - """Print a list of keypairs for a user""" - keypairs = cs.keypairs.list() - columns = ['Name', 'Fingerprint'] - utils.print_list(keypairs, columns) - - -def _print_keypair(keypair): - kp = keypair._info.copy() - pk = kp.pop('public_key') - utils.print_dict(kp) - print(_("Public key: %s") % pk) - - -@utils.arg('keypair', - metavar='', - help=_("Name or ID of keypair")) -def do_keypair_show(cs, args): - """Show details about the given keypair.""" - keypair = _find_keypair(cs, args.keypair) - _print_keypair(keypair) - - -def _find_keypair(cs, keypair): - """Get a keypair by name or ID.""" - return utils.find_resource(cs.keypairs, keypair) - - -@utils.arg('--tenant', - # nova db searches by project_id - dest='tenant', - metavar='', - nargs='?', - help=_('Display information from single tenant (Admin only).')) -@utils.arg('--reserved', - dest='reserved', - action='store_true', - default=False, - help=_('Include reservations count.')) -def do_absolute_limits(cs, args): - """Print a list of absolute limits for a user""" - limits = cs.limits.get(args.reserved, args.tenant).absolute - columns = ['Name', 'Value'] - utils.print_list(limits, columns) - - -def do_rate_limits(cs, args): - """Print a list of rate limits for a user""" - limits = cs.limits.get().rate - columns = ['Verb', 'URI', 'Value', 'Remain', 'Unit', 'Next_Available'] - utils.print_list(limits, columns) - - -@utils.arg('--start', metavar='', - help=_('Usage range start date ex 2012-01-20 (default: 4 weeks ' - 'ago)'), - default=None) -@utils.arg('--end', metavar='', - help=_('Usage range end date, ex 2012-01-20 (default: tomorrow)'), - default=None) -def do_usage_list(cs, args): - """List usage data for all tenants.""" - dateformat = "%Y-%m-%d" - rows = ["Tenant ID", "Servers", "RAM MB-Hours", "CPU Hours", - "Disk GB-Hours"] - - now = timeutils.utcnow() - - if args.start: - start = datetime.datetime.strptime(args.start, dateformat) - else: - start = now - datetime.timedelta(weeks=4) - - if args.end: - end = datetime.datetime.strptime(args.end, dateformat) - else: - end = now + datetime.timedelta(days=1) - - def simplify_usage(u): - simplerows = [x.lower().replace(" ", "_") for x in rows] - - setattr(u, simplerows[0], u.tenant_id) - setattr(u, simplerows[1], "%d" % len(u.server_usages)) - setattr(u, simplerows[2], "%.2f" % u.total_memory_mb_usage) - setattr(u, simplerows[3], "%.2f" % u.total_vcpus_usage) - setattr(u, simplerows[4], "%.2f" % u.total_local_gb_usage) - - usage_list = cs.usage.list(start, end, detailed=True) - - print(_("Usage from %(start)s to %(end)s:") % - {'start': start.strftime(dateformat), - 'end': end.strftime(dateformat)}) - - for usage in usage_list: - simplify_usage(usage) - - utils.print_list(usage_list, rows) - - -@utils.arg('--start', metavar='', - help=_('Usage range start date ex 2012-01-20 (default: 4 weeks ' - 'ago)'), - default=None) -@utils.arg('--end', metavar='', - help=_('Usage range end date, ex 2012-01-20 (default: tomorrow)'), - default=None) -@utils.arg('--tenant', metavar='', - default=None, - help=_('UUID or name of tenant to get usage for.')) -def do_usage(cs, args): - """Show usage data for a single tenant.""" - dateformat = "%Y-%m-%d" - rows = ["Servers", "RAM MB-Hours", "CPU Hours", "Disk GB-Hours"] - - now = timeutils.utcnow() - - if args.start: - start = datetime.datetime.strptime(args.start, dateformat) - else: - start = now - datetime.timedelta(weeks=4) - - if args.end: - end = datetime.datetime.strptime(args.end, dateformat) - else: - end = now + datetime.timedelta(days=1) - - def simplify_usage(u): - simplerows = [x.lower().replace(" ", "_") for x in rows] - - setattr(u, simplerows[0], "%d" % len(u.server_usages)) - setattr(u, simplerows[1], "%.2f" % u.total_memory_mb_usage) - setattr(u, simplerows[2], "%.2f" % u.total_vcpus_usage) - setattr(u, simplerows[3], "%.2f" % u.total_local_gb_usage) - - if args.tenant: - usage = cs.usage.get(args.tenant, start, end) - else: - usage = cs.usage.get(cs.client.tenant_id, start, end) - - print(_("Usage from %(start)s to %(end)s:") % - {'start': start.strftime(dateformat), - 'end': end.strftime(dateformat)}) - - if getattr(usage, 'total_vcpus_usage', None): - simplify_usage(usage) - utils.print_list([usage], rows) - else: - print(_('None')) - - -@utils.arg('pk_filename', - metavar='', - nargs='?', - default='pk.pem', - help=_('Filename for the private key [Default: pk.pem]')) -@utils.arg('cert_filename', - metavar='', - nargs='?', - default='cert.pem', - help=_('Filename for the X.509 certificate [Default: cert.pem]')) -def do_x509_create_cert(cs, args): - """Create x509 cert for a user in tenant.""" - - if os.path.exists(args.pk_filename): - raise exceptions.CommandError(_("Unable to write privatekey - %s " - "exists.") % args.pk_filename) - if os.path.exists(args.cert_filename): - raise exceptions.CommandError(_("Unable to write x509 cert - %s " - "exists.") % args.cert_filename) - - certs = cs.certs.create() - - try: - old_umask = os.umask(0o377) - with open(args.pk_filename, 'w') as private_key: - private_key.write(certs.private_key) - print(_("Wrote private key to %s") % args.pk_filename) - finally: - os.umask(old_umask) - - with open(args.cert_filename, 'w') as cert: - cert.write(certs.data) - print(_("Wrote x509 certificate to %s") % args.cert_filename) - - -@utils.arg('filename', - metavar='', - nargs='?', - default='cacert.pem', - help=_('Filename to write the x509 root cert.')) -def do_x509_get_root_cert(cs, args): - """Fetch the x509 root cert.""" - if os.path.exists(args.filename): - raise exceptions.CommandError(_("Unable to write x509 root cert - \ - %s exists.") % args.filename) - - with open(args.filename, 'w') as cert: - cacert = cs.certs.get() - cert.write(cacert.data) - print(_("Wrote x509 root cert to %s") % args.filename) - - -@utils.arg('--hypervisor', metavar='', default=None, - help=_('type of hypervisor.')) -def do_agent_list(cs, args): - """List all builds.""" - result = cs.agents.list(args.hypervisor) - columns = ["Agent_id", "Hypervisor", "OS", "Architecture", "Version", - 'Md5hash', 'Url'] - utils.print_list(result, columns) - - -@utils.arg('os', metavar='', help=_('type of os.')) -@utils.arg('architecture', metavar='', - help=_('type of architecture')) -@utils.arg('version', metavar='', help=_('version')) -@utils.arg('url', metavar='', help=_('url')) -@utils.arg('md5hash', metavar='', help=_('md5 hash')) -@utils.arg('hypervisor', metavar='', default='xen', - help=_('type of hypervisor.')) -def do_agent_create(cs, args): - """Create new agent build.""" - result = cs.agents.create(args.os, args.architecture, - args.version, args.url, - args.md5hash, args.hypervisor) - utils.print_dict(result._info.copy()) - - -@utils.arg('id', metavar='', help=_('id of the agent-build')) -def do_agent_delete(cs, args): - """Delete existing agent build.""" - cs.agents.delete(args.id) - - -@utils.arg('id', metavar='', help=_('id of the agent-build')) -@utils.arg('version', metavar='', help=_('version')) -@utils.arg('url', metavar='', help=_('url')) -@utils.arg('md5hash', metavar='', help=_('md5hash')) -def do_agent_modify(cs, args): - """Modify existing agent build.""" - result = cs.agents.update(args.id, args.version, - args.url, args.md5hash) - utils.print_dict(result._info) - - -def _find_aggregate(cs, aggregate): - """Get a aggregate by name or ID.""" - return utils.find_resource(cs.aggregates, aggregate) - - -def do_aggregate_list(cs, args): - """Print a list of all aggregates.""" - aggregates = cs.aggregates.list() - columns = ['Id', 'Name', 'Availability Zone'] - utils.print_list(aggregates, columns) - - -@utils.arg('name', metavar='', help=_('Name of aggregate.')) -@utils.arg('availability_zone', - metavar='', - default=None, - nargs='?', - help=_('The availability zone of the aggregate (optional).')) -def do_aggregate_create(cs, args): - """Create a new aggregate with the specified details.""" - aggregate = cs.aggregates.create(args.name, args.availability_zone) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', - help=_('Name or ID of aggregate to delete.')) -def do_aggregate_delete(cs, args): - """Delete the aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - cs.aggregates.delete(aggregate) - print(_("Aggregate %s has been successfully deleted.") % aggregate.id) - - -@utils.arg('aggregate', metavar='', - help=_('Name or ID of aggregate to update.')) -@utils.arg('name', metavar='', help=_('Name of aggregate.')) -@utils.arg('availability_zone', - metavar='', - nargs='?', - default=None, - help=_('The availability zone of the aggregate.')) -def do_aggregate_update(cs, args): - """Update the aggregate's name and optionally availability zone.""" - aggregate = _find_aggregate(cs, args.aggregate) - updates = {"name": args.name} - if args.availability_zone: - updates["availability_zone"] = args.availability_zone - - aggregate = cs.aggregates.update(aggregate.id, updates) - print(_("Aggregate %s has been successfully updated.") % aggregate.id) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', - help=_('Name or ID of aggregate to update.')) -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to add/update to aggregate. ' - 'Specify only the key to delete a metadata item.')) -def do_aggregate_set_metadata(cs, args): - """Update the metadata associated with the aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - metadata = _extract_metadata(args) - currentmetadata = getattr(aggregate, 'metadata', {}) - if set(metadata.items()) & set(currentmetadata.items()): - raise exceptions.CommandError(_("metadata already exists")) - for key, value in metadata.items(): - if value is None and key not in currentmetadata: - raise exceptions.CommandError(_("metadata key %s does not exist" - " hence can not be deleted") - % key) - aggregate = cs.aggregates.set_metadata(aggregate.id, metadata) - print(_("Metadata has been successfully updated for aggregate %s.") % - aggregate.id) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', - help=_('Name or ID of aggregate.')) -@utils.arg('host', metavar='', - help=_('The host to add to the aggregate.')) -def do_aggregate_add_host(cs, args): - """Add the host to the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - aggregate = cs.aggregates.add_host(aggregate.id, args.host) - print(_("Host %(host)s has been successfully added for aggregate " - "%(aggregate_id)s ") % {'host': args.host, - 'aggregate_id': aggregate.id}) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', - help=_('Name or ID of aggregate.')) -@utils.arg('host', metavar='', - help=_('The host to remove from the aggregate.')) -def do_aggregate_remove_host(cs, args): - """Remove the specified host from the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - aggregate = cs.aggregates.remove_host(aggregate.id, args.host) - print(_("Host %(host)s has been successfully removed from aggregate " - "%(aggregate_id)s ") % {'host': args.host, - 'aggregate_id': aggregate.id}) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', - help=_('Name or ID of aggregate.')) -def do_aggregate_details(cs, args): - """Show details of the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - _print_aggregate_details(aggregate) - - -def _print_aggregate_details(aggregate): - columns = ['Id', 'Name', 'Availability Zone', 'Hosts', 'Metadata'] - - def parser_metadata(fields): - return utils.pretty_choice_dict(getattr(fields, 'metadata', {}) or {}) - - def parser_hosts(fields): - return utils.pretty_choice_list(getattr(fields, 'hosts', [])) - - formatters = { - 'Metadata': parser_metadata, - 'Hosts': parser_hosts, - } - utils.print_list([aggregate], columns, formatters=formatters) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('host', metavar='', default=None, nargs='?', - help=_('destination host name.')) -@utils.arg('--block-migrate', - action='store_true', - dest='block_migrate', - default=False, - help=_('True in case of block_migration. (Default=False:live_migration)')) -@utils.arg('--block_migrate', - action='store_true', - help=argparse.SUPPRESS) -@utils.arg('--disk-over-commit', - action='store_true', - dest='disk_over_commit', - default=False, - help=_('Allow overcommit.(Default=False)')) -@utils.arg('--disk_over_commit', - action='store_true', - help=argparse.SUPPRESS) -def do_live_migration(cs, args): - """Migrate running server to a new machine.""" - _find_server(cs, args.server).live_migrate(args.host, - args.block_migrate, - args.disk_over_commit) - - -@utils.arg('server', metavar='', nargs='+', - help=_('Name or ID of server(s).')) -@utils.arg('--active', action='store_const', dest='state', - default='error', const='active', - help=_('Request the server be reset to "active" state instead ' - 'of "error" state (the default).')) -def do_reset_state(cs, args): - """Reset the state of a server.""" - failure_flag = False - - for server in args.server: - try: - _find_server(cs, server).reset_state(args.state) - except Exception as e: - failure_flag = True - msg = "Reset state for server %s failed: %s" % (server, e) - print(msg) - - if failure_flag: - msg = "Unable to reset the state for the specified server(s)." - raise exceptions.CommandError(msg) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_reset_network(cs, args): - """Reset network of a server.""" - _find_server(cs, args.server).reset_network() - - -@utils.arg('--host', metavar='', default=None, - help=_('Name of host.')) -@utils.arg('--binary', metavar='', default=None, - help=_('Service binary.')) -def do_service_list(cs, args): - """Show a list of all running services. Filter by host & binary.""" - result = cs.services.list(host=args.host, binary=args.binary) - columns = ["Binary", "Host", "Zone", "Status", "State", "Updated_at"] - # NOTE(sulo): we check if the response has disabled_reason - # so as not to add the column when the extended ext is not enabled. - if result and hasattr(result[0], 'disabled_reason'): - columns.append("Disabled Reason") - - # NOTE(gtt): After https://review.openstack.org/#/c/39998/ nova will - # show id in response. - if result and hasattr(result[0], 'id'): - columns.insert(0, "Id") - - utils.print_list(result, columns) - - -@utils.arg('host', metavar='', help=_('Name of host.')) -@utils.arg('binary', metavar='', help=_('Service binary.')) -def do_service_enable(cs, args): - """Enable the service.""" - result = cs.services.enable(args.host, args.binary) - utils.print_list([result], ['Host', 'Binary', 'Status']) - - -@utils.arg('host', metavar='', help=_('Name of host.')) -@utils.arg('binary', metavar='', help=_('Service binary.')) -@utils.arg('--reason', metavar='', - help=_('Reason for disabling service.')) -def do_service_disable(cs, args): - """Disable the service.""" - if args.reason: - result = cs.services.disable_log_reason(args.host, args.binary, - args.reason) - utils.print_list([result], ['Host', 'Binary', 'Status', - 'Disabled Reason']) - else: - result = cs.services.disable(args.host, args.binary) - utils.print_list([result], ['Host', 'Binary', 'Status']) - - -@utils.arg('id', metavar='', help=_('Id of service.')) -def do_service_delete(cs, args): - """Delete the service.""" - cs.services.delete(args.id) - - -@utils.arg('fixed_ip', metavar='', help=_('Fixed IP Address.')) -def do_fixed_ip_get(cs, args): - """Retrieve info on a fixed ip.""" - result = cs.fixed_ips.get(args.fixed_ip) - utils.print_list([result], ['address', 'cidr', 'hostname', 'host']) - - -@utils.arg('fixed_ip', metavar='', help=_('Fixed IP Address.')) -def do_fixed_ip_reserve(cs, args): - """Reserve a fixed IP.""" - cs.fixed_ips.reserve(args.fixed_ip) - - -@utils.arg('fixed_ip', metavar='', help=_('Fixed IP Address.')) -def do_fixed_ip_unreserve(cs, args): - """Unreserve a fixed IP.""" - cs.fixed_ips.unreserve(args.fixed_ip) - - -@utils.arg('host', metavar='', help=_('Name of host.')) -def do_host_describe(cs, args): - """Describe a specific host.""" - result = cs.hosts.get(args.host) - columns = ["HOST", "PROJECT", "cpu", "memory_mb", "disk_gb"] - utils.print_list(result, columns) - - -@utils.arg('--zone', metavar='', default=None, - help=_('Filters the list, returning only those ' - 'hosts in the availability zone .')) -def do_host_list(cs, args): - """List all hosts by service.""" - columns = ["host_name", "service", "zone"] - result = cs.hosts.list(args.zone) - utils.print_list(result, columns) - - -@utils.arg('host', metavar='', help='Name of host.') -@utils.arg('--status', metavar='', default=None, dest='status', - help=_('Either enable or disable a host.')) -@utils.arg('--maintenance', - metavar='', - default=None, - dest='maintenance', - help=_('Either put or resume host to/from maintenance.')) -def do_host_update(cs, args): - """Update host settings.""" - updates = {} - columns = ["HOST"] - if args.status: - updates['status'] = args.status - columns.append("status") - if args.maintenance: - updates['maintenance_mode'] = args.maintenance - columns.append("maintenance_mode") - result = cs.hosts.update(args.host, updates) - utils.print_list([result], columns) - - -@utils.arg('host', metavar='', help='Name of host.') -@utils.arg('--action', metavar='', dest='action', - choices=['startup', 'shutdown', 'reboot'], - help=_('A power action: startup, reboot, or shutdown.')) -def do_host_action(cs, args): - """Perform a power action on a host.""" - result = cs.hosts.host_action(args.host, args.action) - utils.print_list([result], ['HOST', 'power_action']) - - -def _find_hypervisor(cs, hypervisor): - """Get a hypervisor by name or ID.""" - return utils.find_resource(cs.hypervisors, hypervisor) - - -@utils.arg('--matching', metavar='', default=None, - help=_('List hypervisors matching the given .')) -def do_hypervisor_list(cs, args): - """List hypervisors.""" - columns = ['ID', 'Hypervisor hostname'] - if args.matching: - utils.print_list(cs.hypervisors.search(args.matching), columns) - else: - # Since we're not outputting detail data, choose - # detailed=False for server-side efficiency - utils.print_list(cs.hypervisors.list(False), columns) - - -@utils.arg('hostname', metavar='', - help=_('The hypervisor hostname (or pattern) to search for.')) -def do_hypervisor_servers(cs, args): - """List servers belonging to specific hypervisors.""" - hypers = cs.hypervisors.search(args.hostname, servers=True) - - class InstanceOnHyper(object): - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - # Massage the result into a list to be displayed - instances = [] - for hyper in hypers: - hyper_host = hyper.hypervisor_hostname - hyper_id = hyper.id - if hasattr(hyper, 'servers'): - instances.extend([InstanceOnHyper(id=serv['uuid'], - name=serv['name'], - hypervisor_hostname=hyper_host, - hypervisor_id=hyper_id) - for serv in hyper.servers]) - - # Output the data - utils.print_list(instances, ['ID', 'Name', 'Hypervisor ID', - 'Hypervisor Hostname']) - - -@utils.arg('hypervisor', - metavar='', - help=_('Name or ID of the hypervisor to show the details of.')) -def do_hypervisor_show(cs, args): - """Display the details of the specified hypervisor.""" - hyper = _find_hypervisor(cs, args.hypervisor) - utils.print_dict(utils.flatten_dict(hyper._info)) - - -@utils.arg('hypervisor', - metavar='', - help=_('Name or ID of the hypervisor to show the uptime of.')) -def do_hypervisor_uptime(cs, args): - """Display the uptime of the specified hypervisor.""" - hyper = _find_hypervisor(cs, args.hypervisor) - hyper = cs.hypervisors.uptime(hyper) - - # Output the uptime information - utils.print_dict(hyper._info.copy()) - - -def do_hypervisor_stats(cs, args): - """Get hypervisor statistics over all compute nodes.""" - stats = cs.hypervisors.statistics() - utils.print_dict(stats._info.copy()) - - -def ensure_service_catalog_present(cs): - if not hasattr(cs.client, 'service_catalog'): - # Turn off token caching and re-auth - cs.client.unauthenticate() - cs.client.use_token_cache(False) - cs.client.authenticate() - - -def do_endpoints(cs, _args): - """Discover endpoints that get returned from the authenticate services.""" - ensure_service_catalog_present(cs) - - catalog = cs.client.service_catalog.catalog - region = cs.client.region_name - - for service in catalog['access']['serviceCatalog']: - name, endpoints = service["name"], service["endpoints"] - - try: - endpoint = _get_first_endpoint(endpoints, region) - utils.print_dict(endpoint, name) - except LookupError: - print(_("WARNING: %(service)s has no endpoint in %(region)s! " - "Available endpoints for this service:") % - {'service': name, 'region': region}) - for other_endpoint in endpoints: - utils.print_dict(other_endpoint, name) - - -def _get_first_endpoint(endpoints, region): - """Find the first suitable endpoint in endpoints. - - If there is only one endpoint, return it. If there is more than - one endpoint, return the first one with the given region. If there - are no endpoints, or there is more than one endpoint but none of - them match the given region, raise KeyError. - - """ - if len(endpoints) == 1: - return endpoints[0] - else: - for candidate_endpoint in endpoints: - if candidate_endpoint["region"] == region: - return candidate_endpoint - - raise LookupError("No suitable endpoint found") - - -@utils.arg('--wrap', dest='wrap', metavar='', default=64, - help=_('wrap PKI tokens to a specified length, or 0 to disable')) -def do_credentials(cs, _args): - """Show user credentials returned from auth.""" - ensure_service_catalog_present(cs) - catalog = cs.client.service_catalog.catalog - utils.print_dict(catalog['access']['user'], "User Credentials", - wrap=int(_args.wrap)) - utils.print_dict(catalog['access']['token'], "Token", wrap=int(_args.wrap)) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('--port', - dest='port', - action='store', - type=int, - default=22, - help=_('Optional flag to indicate which port to use for ssh. ' - '(Default=22)')) -@utils.arg('--private', - dest='private', - action='store_true', - default=False, - help=argparse.SUPPRESS) -@utils.arg('--address-type', - dest='address_type', - action='store', - type=str, - default='floating', - help=_('Optional flag to indicate which IP type to use. Possible values ' - 'includes fixed and floating (the Default).')) -@utils.arg('--network', metavar='', - help=_('Network to use for the ssh.'), default=None) -@utils.arg('--ipv6', - dest='ipv6', - action='store_true', - default=False, - help=_('Optional flag to indicate whether to use an IPv6 address ' - 'attached to a server. (Defaults to IPv4 address)')) -@utils.arg('--login', metavar='', help=_('Login to use.'), - default="root") -@utils.arg('-i', '--identity', - dest='identity', - help=_('Private key file, same as the -i option to the ssh command.'), - default='') -@utils.arg('--extra-opts', - dest='extra', - help=_('Extra options to pass to ssh. see: man ssh'), - default='') -def do_ssh(cs, args): - """SSH into a server.""" - if '@' in args.server: - user, server = args.server.split('@', 1) - args.login = user - args.server = server - - addresses = _find_server(cs, args.server).addresses - address_type = "fixed" if args.private else args.address_type - version = 6 if args.ipv6 else 4 - pretty_version = 'IPv%d' % version - - # Select the network to use. - if args.network: - network_addresses = addresses.get(args.network) - if not network_addresses: - msg = _("Server '%(server)s' is not attached to network " - "'%(network)s'") - raise exceptions.ResourceNotFound( - msg % {'server': args.server, 'network': args.network}) - else: - if len(addresses) > 1: - msg = _("Server '%(server)s' is attached to more than one network." - " Please pick the network to use.") - raise exceptions.CommandError(msg % {'server': args.server}) - elif not addresses: - msg = _("Server '%(server)s' is not attached to any network.") - raise exceptions.CommandError(msg % {'server': args.server}) - else: - network_addresses = list(six.itervalues(addresses))[0] - - # Select the address in the selected network. - # If the extension is not present, we assume the address to be floating. - match = lambda addr: all(( - addr.get('version') == version, - addr.get('OS-EXT-IPS:type', 'floating') == address_type)) - matching_addresses = [address.get('addr') for address in network_addresses - if match(address)] - if not any(matching_addresses): - msg = _("No address that would match network '%(network)s'" - " and type '%(address_type)s' of version %(pretty_version)s " - "has been found for server '%(server)s'.") - raise exceptions.ResourceNotFound(msg % { - 'network': args.network, 'address_type': address_type, - 'pretty_version': pretty_version, 'server': args.server}) - elif len(matching_addresses) > 1: - msg = _("More than one %(pretty_version)s %(address_type)s address" - "found.") - raise exceptions.CommandError(msg % {'pretty_version': pretty_version, - 'address_type': address_type}) - else: - ip_address = matching_addresses[0] - - identity = '-i %s' % args.identity if len(args.identity) else '' - - cmd = "ssh -%d -p%d %s %s@%s %s" % (version, args.port, identity, - args.login, ip_address, args.extra) - logger.debug("Executing cmd '%s'", cmd) - os.system(cmd) - - -_quota_resources = ['instances', 'cores', 'ram', - 'floating_ips', 'fixed_ips', 'metadata_items', - 'injected_files', 'injected_file_content_bytes', - 'injected_file_path_bytes', 'key_pairs', - 'security_groups', 'security_group_rules', - 'server_groups', 'server_group_members'] - - -def _quota_show(quotas): - class FormattedQuota(object): - def __init__(self, key, value): - setattr(self, 'quota', key) - setattr(self, 'limit', value) - - quota_list = [] - for resource in _quota_resources: - try: - quota = FormattedQuota(resource, getattr(quotas, resource)) - quota_list.append(quota) - except AttributeError: - pass - columns = ['Quota', 'Limit'] - utils.print_list(quota_list, columns) - - -def _quota_update(manager, identifier, args): - updates = {} - for resource in _quota_resources: - val = getattr(args, resource, None) - if val is not None: - updates[resource] = val - - if updates: - # default value of force is None to make sure this client - # will be compatibile with old nova server - force_update = getattr(args, 'force', None) - user_id = getattr(args, 'user', None) - if isinstance(manager, quotas.QuotaSetManager): - manager.update(identifier, force=force_update, user_id=user_id, - **updates) - else: - manager.update(identifier, **updates) - - -@utils.arg('--tenant', - metavar='', - default=None, - help=_('ID of tenant to list the quotas for.')) -@utils.arg('--user', - metavar='', - default=None, - help=_('ID of user to list the quotas for.')) -def do_quota_show(cs, args): - """List the quotas for a tenant/user.""" - - if not args.tenant: - _quota_show(cs.quotas.get(cs.client.tenant_id, user_id=args.user)) - else: - _quota_show(cs.quotas.get(args.tenant, user_id=args.user)) - - -@utils.arg('--tenant', - metavar='', - default=None, - help=_('ID of tenant to list the default quotas for.')) -def do_quota_defaults(cs, args): - """List the default quotas for a tenant.""" - - if not args.tenant: - _quota_show(cs.quotas.defaults(cs.client.tenant_id)) - else: - _quota_show(cs.quotas.defaults(args.tenant)) - - -@utils.arg('tenant', - metavar='', - help=_('ID of tenant to set the quotas for.')) -@utils.arg('--user', - metavar='', - default=None, - help=_('ID of user to set the quotas for.')) -@utils.arg('--instances', - metavar='', - type=int, default=None, - help=_('New value for the "instances" quota.')) -@utils.arg('--cores', - metavar='', - type=int, default=None, - help=_('New value for the "cores" quota.')) -@utils.arg('--ram', - metavar='', - type=int, default=None, - help=_('New value for the "ram" quota.')) -@utils.arg('--floating-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "floating-ips" quota.')) -@utils.arg('--floating_ips', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--fixed-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "fixed-ips" quota.')) -@utils.arg('--metadata-items', - metavar='', - type=int, - default=None, - help=_('New value for the "metadata-items" quota.')) -@utils.arg('--metadata_items', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--injected-files', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-files" quota.')) -@utils.arg('--injected_files', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--injected-file-content-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-content-bytes" quota.')) -@utils.arg('--injected_file_content_bytes', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--injected-file-path-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-path-bytes" quota.')) -@utils.arg('--key-pairs', - metavar='', - type=int, - default=None, - help=_('New value for the "key-pairs" quota.')) -@utils.arg('--security-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "security-groups" quota.')) -@utils.arg('--security-group-rules', - metavar='', - type=int, - default=None, - help=_('New value for the "security-group-rules" quota.')) -@utils.arg('--server-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "server-groups" quota.')) -@utils.arg('--server-group-members', - metavar='', - type=int, - default=None, - help=_('New value for the "server-group-members" quota.')) -@utils.arg('--force', - dest='force', - action="store_true", - default=None, - help=_('Whether force update the quota even if the already used' - ' and reserved exceeds the new quota')) -def do_quota_update(cs, args): - """Update the quotas for a tenant/user.""" - - _quota_update(cs.quotas, args.tenant, args) - - -@utils.arg('--tenant', - metavar='', - required=True, - help=_('ID of tenant to delete quota for.')) -@utils.arg('--user', - metavar='', - help=_('ID of user to delete quota for.')) -def do_quota_delete(cs, args): - """Delete quota for a tenant/user so their quota will Revert - back to default. - """ - - cs.quotas.delete(args.tenant, user_id=args.user) - - -@utils.arg('class_name', - metavar='', - help=_('Name of quota class to list the quotas for.')) -def do_quota_class_show(cs, args): - """List the quotas for a quota class.""" - - _quota_show(cs.quota_classes.get(args.class_name)) - - -@utils.arg('class_name', - metavar='', - help=_('Name of quota class to set the quotas for.')) -@utils.arg('--instances', - metavar='', - type=int, default=None, - help=_('New value for the "instances" quota.')) -@utils.arg('--cores', - metavar='', - type=int, default=None, - help=_('New value for the "cores" quota.')) -@utils.arg('--ram', - metavar='', - type=int, default=None, - help=_('New value for the "ram" quota.')) -@utils.arg('--floating-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "floating-ips" quota.')) -@utils.arg('--floating_ips', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--fixed-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "fixed-ips" quota.')) -@utils.arg('--metadata-items', - metavar='', - type=int, - default=None, - help=_('New value for the "metadata-items" quota.')) -@utils.arg('--metadata_items', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--injected-files', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-files" quota.')) -@utils.arg('--injected_files', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--injected-file-content-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-content-bytes" quota.')) -@utils.arg('--injected_file_content_bytes', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--injected-file-path-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-path-bytes" quota.')) -@utils.arg('--key-pairs', - metavar='', - type=int, - default=None, - help=_('New value for the "key-pairs" quota.')) -@utils.arg('--security-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "security-groups" quota.')) -@utils.arg('--security-group-rules', - metavar='', - type=int, - default=None, - help=_('New value for the "security-group-rules" quota.')) -@utils.arg('--server-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "server-groups" quota.')) -@utils.arg('--server-group-members', - metavar='', - type=int, - default=None, - help=_('New value for the "server-group-members" quota.')) -def do_quota_class_update(cs, args): - """Update the quotas for a quota class.""" - - _quota_update(cs.quota_classes, args.class_name, args) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('host', metavar='', nargs='?', - help=_("Name or ID of the target host. " - "If no host is specified, the scheduler will choose one.")) -@utils.arg('--password', - dest='password', - metavar='', - help=_("Set the provided password on the evacuated server. Not applicable " - "with on-shared-storage flag")) -@utils.arg('--on-shared-storage', - dest='on_shared_storage', - action="store_true", - default=False, - help=_('Specifies whether server files are located on shared storage')) -def do_evacuate(cs, args): - """Evacuate server from failed host.""" - - server = _find_server(cs, args.server) - - res = server.evacuate(args.host, args.on_shared_storage, args.password)[1] - if type(res) is dict: - utils.print_dict(res) - - -def _print_interfaces(interfaces): - columns = ['Port State', 'Port ID', 'Net ID', 'IP addresses', - 'MAC Addr'] - - class FormattedInterface(object): - def __init__(self, interface): - for col in columns: - key = col.lower().replace(" ", "_") - if hasattr(interface, key): - setattr(self, key, getattr(interface, key)) - self.ip_addresses = ",".join([fip['ip_address'] - for fip in interface.fixed_ips]) - utils.print_list([FormattedInterface(i) for i in interfaces], columns) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_interface_list(cs, args): - """List interfaces attached to a server.""" - server = _find_server(cs, args.server) - - res = server.interface_list() - if type(res) is list: - _print_interfaces(res) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('--port-id', metavar='', help=_('Port ID.'), - dest="port_id") -@utils.arg('--net-id', metavar='', help=_('Network ID'), - default=None, dest="net_id") -@utils.arg('--fixed-ip', metavar='', help=_('Requested fixed IP.'), - default=None, dest="fixed_ip") -def do_interface_attach(cs, args): - """Attach a network interface to a server.""" - server = _find_server(cs, args.server) - - res = server.interface_attach(args.port_id, args.net_id, args.fixed_ip) - if type(res) is dict: - utils.print_dict(res) - - -@utils.arg('server', metavar='', help=_('Name or ID of server.')) -@utils.arg('port_id', metavar='', help=_('Port ID.')) -def do_interface_detach(cs, args): - """Detach a network interface from a server.""" - server = _find_server(cs, args.server) - - res = server.interface_detach(args.port_id) - if type(res) is dict: - utils.print_dict(res) - - -def _treeizeAvailabilityZone(zone): - """Build a tree view for availability zones.""" - AvailabilityZone = availability_zones.AvailabilityZone - - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - result = [] - - # Zone tree view item - az.zoneName = zone.zoneName - az.zoneState = ('available' - if zone.zoneState['available'] else 'not available') - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - if zone.hosts is not None: - zone_hosts = sorted(zone.hosts.items(), key=lambda x: x[0]) - for (host, services) in zone_hosts: - # Host tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '|- %s' % host - az.zoneState = '' - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - for (svc, state) in services.items(): - # Service tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '| |- %s' % svc - az.zoneState = '%s %s %s' % ( - 'enabled' if state['active'] else 'disabled', - ':-)' if state['available'] else 'XXX', - state['updated_at']) - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - return result - - -@utils.service_type('compute') -def do_availability_zone_list(cs, _args): - """List all the availability zones.""" - try: - availability_zones = cs.availability_zones.list() - except exceptions.Forbidden as e: # policy doesn't allow probably - try: - availability_zones = cs.availability_zones.list(detailed=False) - except Exception: - raise e - - result = [] - for zone in availability_zones: - result += _treeizeAvailabilityZone(zone) - _translate_availability_zone_keys(result) - utils.print_list(result, ['Name', 'Status'], - sortby_index=None) - - -def _print_server_group_details(server_group): - columns = ['Id', 'Name', 'Policies', 'Members', 'Metadata'] - utils.print_list(server_group, columns) - - -def do_server_group_list(cs, args): - """Print a list of all server groups.""" - server_groups = cs.server_groups.list() - _print_server_group_details(server_groups) - - -def do_secgroup_list_default_rules(cs, args): - """List rules for the default security group.""" - _print_secgroup_rules(cs.security_group_default_rules.list(), - show_source_group=False) - - -@utils.arg('ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@utils.arg('from_port', - metavar='', - help=_('Port at start of range.')) -@utils.arg('to_port', - metavar='', - help=_('Port at end of range.')) -@utils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_add_default_rule(cs, args): - """Add a rule to the default security group.""" - rule = cs.security_group_default_rules.create(args.ip_proto, - args.from_port, - args.to_port, - args.cidr) - _print_secgroup_rules([rule], show_source_group=False) - - -@utils.arg('ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@utils.arg('from_port', - metavar='', - help=_('Port at start of range.')) -@utils.arg('to_port', - metavar='', - help=_('Port at end of range.')) -@utils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_delete_default_rule(cs, args): - """Delete a rule from the default security group.""" - for rule in cs.security_group_default_rules.list(): - if (rule.ip_protocol and - rule.ip_protocol.upper() == args.ip_proto.upper() and - rule.from_port == int(args.from_port) and - rule.to_port == int(args.to_port) and - rule.ip_range['cidr'] == args.cidr): - _print_secgroup_rules([rule], show_source_group=False) - return cs.security_group_default_rules.delete(rule.id) - - raise exceptions.CommandError(_("Rule not found")) - - -@utils.arg('name', metavar='', help='Server group name.') -# NOTE(wingwj): The '--policy' way is still reserved here for preserving -# the backwards compatibility of CLI, even if a user won't get this usage -# in '--help' description. It will be deprecated after an suitable deprecation -# period(probably 2 coordinated releases or so). -# -# Moreover, we imagine that a given user will use only positional parameters or -# only the "--policy" option. So we don't need to properly handle -# the possibility that they might mix them here. That usage is unsupported. -# The related discussion can be found in -# https://review.openstack.org/#/c/96382/2/. -@utils.arg('policy', - metavar='', - default=argparse.SUPPRESS, - nargs='*', - help='Policies for the server groups ' - '("affinity" or "anti-affinity")') -@utils.arg('--policy', - default=[], - action='append', - help=argparse.SUPPRESS) -def do_server_group_create(cs, args): - """Create a new server group with the specified details.""" - if not args.policy: - raise exceptions.CommandError(_("at least one policy must be " - "specified")) - kwargs = {'name': args.name, - 'policies': args.policy} - server_group = cs.server_groups.create(**kwargs) - _print_server_group_details([server_group]) - - -@utils.arg('id', metavar='', nargs='+', - help="Unique ID(s) of the server group to delete") -def do_server_group_delete(cs, args): - """Delete specific server group(s).""" - failure_count = 0 - - for sg in args.id: - try: - cs.server_groups.delete(sg) - print(_("Server group %s has been successfully deleted.") % sg) - except Exception as e: - failure_count += 1 - print(_("Delete for server group %(sg)s failed: %(e)s") % - {'sg': sg, 'e': e}) - if failure_count == len(args.id): - raise exceptions.CommandError(_("Unable to delete any of the " - "specified server groups.")) - - -@utils.arg('id', metavar='', - help="Unique ID of the server group to get") -def do_server_group_get(cs, args): - """Get a specific server group.""" - server_group = cs.server_groups.get(args.id) - _print_server_group_details([server_group]) - - -def do_version_list(cs, args): - """List all API versions.""" - result = cs.versions.list() - columns = ["Id", "Status", "Updated"] - utils.print_list(result, columns) diff --git a/awx/lib/site-packages/novaclient/v1_1/usage.py b/awx/lib/site-packages/novaclient/v1_1/usage.py deleted file mode 100644 index 05ce020a01..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/usage.py +++ /dev/null @@ -1,61 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Usage interface. -""" - -from novaclient import base - - -class Usage(base.Resource): - """ - Usage contains information about a tenant's physical resource usage - """ - def __repr__(self): - return "" - - -class UsageManager(base.ManagerWithFind): - """ - Manage :class:`Usage` resources. - """ - resource_class = Usage - - def list(self, start, end, detailed=False): - """ - Get usage for all tenants - - :param start: :class:`datetime.datetime` Start date - :param end: :class:`datetime.datetime` End date - :param detailed: Whether to include information about each - instance whose usage is part of the report - :rtype: list of :class:`Usage`. - """ - return self._list( - "/os-simple-tenant-usage?start=%s&end=%s&detailed=%s" % - (start.isoformat(), end.isoformat(), int(bool(detailed))), - "tenant_usages") - - def get(self, tenant_id, start, end): - """ - Get usage for a specific tenant. - - :param tenant_id: Tenant ID to fetch usage for - :param start: :class:`datetime.datetime` Start date - :param end: :class:`datetime.datetime` End date - :rtype: :class:`Usage` - """ - return self._get("/os-simple-tenant-usage/%s?start=%s&end=%s" % - (tenant_id, start.isoformat(), end.isoformat()), - "tenant_usage") diff --git a/awx/lib/site-packages/novaclient/v1_1/versions.py b/awx/lib/site-packages/novaclient/v1_1/versions.py deleted file mode 100644 index 5ab09a103a..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/versions.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2014 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -version interface -""" - -from novaclient import base - - -class Version(base.Resource): - """ - Compute REST API information - """ - def __repr__(self): - return "" - - -class VersionManager(base.ManagerWithFind): - resource_class = Version - - def list(self): - """List all versions.""" - return self._list(None, "versions") diff --git a/awx/lib/site-packages/novaclient/v1_1/virtual_interfaces.py b/awx/lib/site-packages/novaclient/v1_1/virtual_interfaces.py deleted file mode 100644 index 9c04e8d866..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/virtual_interfaces.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Virtual Interfaces (1.1 extension). -""" - -from novaclient import base - - -class VirtualInterface(base.Resource): - def __repr__(self): - pass - - -class VirtualInterfaceManager(base.ManagerWithFind): - resource_class = VirtualInterface - - def list(self, instance_id): - return self._list('/servers/%s/os-virtual-interfaces' % instance_id, - 'virtual_interfaces') diff --git a/awx/lib/site-packages/novaclient/v1_1/volume_snapshots.py b/awx/lib/site-packages/novaclient/v1_1/volume_snapshots.py deleted file mode 100644 index b30a60a826..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/volume_snapshots.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2011 Denali Systems, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume snapshot interface (1.1 extension). -""" - -from novaclient import base - - -class Snapshot(base.Resource): - """ - A Snapshot is a point-in-time snapshot of an openstack volume. - """ - NAME_ATTR = 'display_name' - - def __repr__(self): - return "" % self.id - - def delete(self): - """ - Delete this snapshot. - """ - self.manager.delete(self) - - -class SnapshotManager(base.ManagerWithFind): - """ - Manage :class:`Snapshot` resources. - """ - resource_class = Snapshot - - def create(self, volume_id, force=False, - display_name=None, display_description=None): - - """ - Create a snapshot of the given volume. - - :param volume_id: The ID of the volume to snapshot. - :param force: If force is True, create a snapshot even if the volume is - attached to an instance. Default is False. - :param display_name: Name of the snapshot - :param display_description: Description of the snapshot - :rtype: :class:`Snapshot` - """ - body = {'snapshot': {'volume_id': volume_id, - 'force': force, - 'display_name': display_name, - 'display_description': display_description}} - return self._create('/snapshots', body, 'snapshot') - - def get(self, snapshot_id): - """ - Get a snapshot. - - :param snapshot_id: The ID of the snapshot to get. - :rtype: :class:`Snapshot` - """ - return self._get("/snapshots/%s" % snapshot_id, "snapshot") - - def list(self, detailed=True): - """ - Get a list of all snapshots. - - :rtype: list of :class:`Snapshot` - """ - if detailed is True: - return self._list("/snapshots/detail", "snapshots") - else: - return self._list("/snapshots", "snapshots") - - def delete(self, snapshot): - """ - Delete a snapshot. - - :param snapshot: The :class:`Snapshot` to delete. - """ - self._delete("/snapshots/%s" % base.getid(snapshot)) diff --git a/awx/lib/site-packages/novaclient/v1_1/volume_types.py b/awx/lib/site-packages/novaclient/v1_1/volume_types.py deleted file mode 100644 index 3d1c7f5316..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/volume_types.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2011 Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -""" -Volume Type interface. -""" - -from novaclient import base - - -class VolumeType(base.Resource): - """ - A Volume Type is the type of volume to be created - """ - def __repr__(self): - return "" % self.name - - -class VolumeTypeManager(base.ManagerWithFind): - """ - Manage :class:`VolumeType` resources. - """ - resource_class = VolumeType - - def list(self): - """ - Get a list of all volume types. - - :rtype: list of :class:`VolumeType`. - """ - return self._list("/types", "volume_types") - - def get(self, volume_type): - """ - Get a specific volume type. - - :param volume_type: The ID of the :class:`VolumeType` to get. - :rtype: :class:`VolumeType` - """ - return self._get("/types/%s" % base.getid(volume_type), "volume_type") - - def delete(self, volume_type): - """ - Delete a specific volume_type. - - :param volume_type: The ID of the :class:`VolumeType` to get. - """ - self._delete("/types/%s" % base.getid(volume_type)) - - def create(self, name): - """ - Create a volume type. - - :param name: Descriptive name of the volume type - :rtype: :class:`VolumeType` - """ - - body = { - "volume_type": { - "name": name, - } - } - - return self._create("/types", body, "volume_type") diff --git a/awx/lib/site-packages/novaclient/v1_1/volumes.py b/awx/lib/site-packages/novaclient/v1_1/volumes.py deleted file mode 100644 index 77746dd30a..0000000000 --- a/awx/lib/site-packages/novaclient/v1_1/volumes.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright 2011 Denali Systems, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume interface (1.1 extension). -""" - -import six -from six.moves.urllib import parse - -from novaclient import base - - -class Volume(base.Resource): - """ - A volume is an extra block level storage to the OpenStack instances. - """ - NAME_ATTR = 'display_name' - - def __repr__(self): - return "" % self.id - - def delete(self): - """ - Delete this volume. - """ - self.manager.delete(self) - - -class VolumeManager(base.ManagerWithFind): - """ - Manage :class:`Volume` resources. - """ - resource_class = Volume - - def create(self, size, snapshot_id=None, - display_name=None, display_description=None, - volume_type=None, availability_zone=None, - imageRef=None): - """ - Create a volume. - - :param size: Size of volume in GB - :param snapshot_id: ID of the snapshot - :param display_name: Name of the volume - :param display_description: Description of the volume - :param volume_type: Type of volume - :param availability_zone: Availability Zone for volume - :rtype: :class:`Volume` - :param imageRef: reference to an image stored in glance - """ - body = {'volume': {'size': size, - 'snapshot_id': snapshot_id, - 'display_name': display_name, - 'display_description': display_description, - 'volume_type': volume_type, - 'availability_zone': availability_zone, - 'imageRef': imageRef}} - return self._create('/volumes', body, 'volume') - - def get(self, volume_id): - """ - Get a volume. - - :param volume_id: The ID of the volume to delete. - :rtype: :class:`Volume` - """ - return self._get("/volumes/%s" % volume_id, "volume") - - def list(self, detailed=True, search_opts=None): - """ - Get a list of all volumes. - - :rtype: list of :class:`Volume` - """ - search_opts = search_opts or {} - - qparams = dict((k, v) for (k, v) in six.iteritems(search_opts) if v) - - query_string = '?%s' % parse.urlencode(qparams) if qparams else '' - - if detailed is True: - return self._list("/volumes/detail%s" % query_string, "volumes") - else: - return self._list("/volumes%s" % query_string, "volumes") - - def delete(self, volume): - """ - Delete a volume. - - :param volume: The :class:`Volume` to delete. - """ - self._delete("/volumes/%s" % base.getid(volume)) - - def create_server_volume(self, server_id, volume_id, device): - """ - Attach a volume identified by the volume ID to the given server ID - - :param server_id: The ID of the server - :param volume_id: The ID of the volume to attach. - :param device: The device name - :rtype: :class:`Volume` - """ - body = {'volumeAttachment': {'volumeId': volume_id, - 'device': device}} - return self._create("/servers/%s/os-volume_attachments" % server_id, - body, "volumeAttachment") - - def update_server_volume(self, server_id, attachment_id, new_volume_id): - """ - Update the volume identified by the attachment ID, that is attached to - the given server ID - - :param server_id: The ID of the server - :param attachment_id: The ID of the attachment - :param new_volume_id: The ID of the new volume to attach - :rtype: :class:`Volume` - """ - body = {'volumeAttachment': {'volumeId': new_volume_id}} - return self._update("/servers/%s/os-volume_attachments/%s" % - (server_id, attachment_id,), body, "volumeAttachment") - - def get_server_volume(self, server_id, attachment_id): - """ - Get the volume identified by the attachment ID, that is attached to - the given server ID - - :param server_id: The ID of the server - :param attachment_id: The ID of the attachment - :rtype: :class:`Volume` - """ - return self._get("/servers/%s/os-volume_attachments/%s" % (server_id, - attachment_id,), "volumeAttachment") - - def get_server_volumes(self, server_id): - """ - Get a list of all the attached volumes for the given server ID - - :param server_id: The ID of the server - :rtype: list of :class:`Volume` - """ - return self._list("/servers/%s/os-volume_attachments" % server_id, - "volumeAttachments") - - def delete_server_volume(self, server_id, attachment_id): - """ - Detach a volume identified by the attachment ID from the given server - - :param server_id: The ID of the server - :param attachment_id: The ID of the attachment - """ - self._delete("/servers/%s/os-volume_attachments/%s" % - (server_id, attachment_id,)) diff --git a/awx/lib/site-packages/novaclient/v2/__init__.py b/awx/lib/site-packages/novaclient/v2/__init__.py deleted file mode 100644 index 21d7c4fcc1..0000000000 --- a/awx/lib/site-packages/novaclient/v2/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.v2.client import Client # noqa diff --git a/awx/lib/site-packages/novaclient/v2/agents.py b/awx/lib/site-packages/novaclient/v2/agents.py deleted file mode 100644 index b5372cbd80..0000000000 --- a/awx/lib/site-packages/novaclient/v2/agents.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -agent interface -""" - -from novaclient import base - - -class Agent(base.Resource): - def __repr__(self): - return "" % self.agent - - def _add_details(self, info): - dico = 'resource' in info and info['resource'] or info - for (k, v) in dico.items(): - setattr(self, k, v) - - -class AgentsManager(base.ManagerWithFind): - resource_class = Agent - - def list(self, hypervisor=None): - """List all agent builds.""" - url = "/os-agents" - if hypervisor: - url = "/os-agents?hypervisor=%s" % hypervisor - return self._list(url, "agents") - - def _build_update_body(self, version, url, md5hash): - return {'para': {'version': version, - 'url': url, - 'md5hash': md5hash}} - - def update(self, id, version, - url, md5hash): - """Update an existing agent build.""" - body = self._build_update_body(version, url, md5hash) - return self._update('/os-agents/%s' % id, body, 'agent') - - def create(self, os, architecture, version, - url, md5hash, hypervisor): - """Create a new agent build.""" - body = {'agent': {'hypervisor': hypervisor, - 'os': os, - 'architecture': architecture, - 'version': version, - 'url': url, - 'md5hash': md5hash}} - return self._create('/os-agents', body, 'agent') - - def delete(self, id): - """Deletes an existing agent build.""" - self._delete('/os-agents/%s' % id) diff --git a/awx/lib/site-packages/novaclient/v2/aggregates.py b/awx/lib/site-packages/novaclient/v2/aggregates.py deleted file mode 100644 index c2df31526d..0000000000 --- a/awx/lib/site-packages/novaclient/v2/aggregates.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Aggregate interface.""" - -from novaclient import base - - -class Aggregate(base.Resource): - """An aggregates is a collection of compute hosts.""" - - def __repr__(self): - return "" % self.id - - def update(self, values): - """Update the name and/or availability zone.""" - return self.manager.update(self, values) - - def add_host(self, host): - return self.manager.add_host(self, host) - - def remove_host(self, host): - return self.manager.remove_host(self, host) - - def set_metadata(self, metadata): - return self.manager.set_metadata(self, metadata) - - def delete(self): - self.manager.delete(self) - - -class AggregateManager(base.ManagerWithFind): - resource_class = Aggregate - - def list(self): - """Get a list of os-aggregates.""" - return self._list('/os-aggregates', 'aggregates') - - def create(self, name, availability_zone): - """Create a new aggregate.""" - body = {'aggregate': {'name': name, - 'availability_zone': availability_zone}} - return self._create('/os-aggregates', body, 'aggregate') - - def get(self, aggregate): - """Get details of the specified aggregate.""" - return self._get('/os-aggregates/%s' % (base.getid(aggregate)), - "aggregate") - - # NOTE:(dtroyer): utils.find_resource() uses manager.get() but we need to - # keep the API backward compatible - def get_details(self, aggregate): - """Get details of the specified aggregate.""" - return self.get(aggregate) - - def update(self, aggregate, values): - """Update the name and/or availability zone.""" - body = {'aggregate': values} - return self._update("/os-aggregates/%s" % base.getid(aggregate), - body, - "aggregate") - - def add_host(self, aggregate, host): - """Add a host into the Host Aggregate.""" - body = {'add_host': {'host': host}} - return self._create("/os-aggregates/%s/action" % base.getid(aggregate), - body, "aggregate") - - def remove_host(self, aggregate, host): - """Remove a host from the Host Aggregate.""" - body = {'remove_host': {'host': host}} - return self._create("/os-aggregates/%s/action" % base.getid(aggregate), - body, "aggregate") - - def set_metadata(self, aggregate, metadata): - """Set a aggregate metadata, replacing the existing metadata.""" - body = {'set_metadata': {'metadata': metadata}} - return self._create("/os-aggregates/%s/action" % base.getid(aggregate), - body, "aggregate") - - def delete(self, aggregate): - """Delete the specified aggregates.""" - self._delete('/os-aggregates/%s' % (base.getid(aggregate))) diff --git a/awx/lib/site-packages/novaclient/v2/availability_zones.py b/awx/lib/site-packages/novaclient/v2/availability_zones.py deleted file mode 100644 index bf59037853..0000000000 --- a/awx/lib/site-packages/novaclient/v2/availability_zones.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Availability Zone interface (1.1 extension). -""" - -from novaclient import base - - -class AvailabilityZone(base.Resource): - """ - An availability zone object. - """ - NAME_ATTR = 'display_name' - - def __repr__(self): - return "" % self.zoneName - - -class AvailabilityZoneManager(base.ManagerWithFind): - """ - Manage :class:`AvailabilityZone` resources. - """ - resource_class = AvailabilityZone - return_parameter_name = "availabilityZoneInfo" - - def list(self, detailed=True): - """ - Get a list of all availability zones. - - :rtype: list of :class:`AvailabilityZone` - """ - if detailed is True: - return self._list("/os-availability-zone/detail", - self.return_parameter_name) - else: - return self._list("/os-availability-zone", - self.return_parameter_name) diff --git a/awx/lib/site-packages/novaclient/v2/certs.py b/awx/lib/site-packages/novaclient/v2/certs.py deleted file mode 100644 index 2c3006c6f7..0000000000 --- a/awx/lib/site-packages/novaclient/v2/certs.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Certificate interface. -""" - -from novaclient import base - - -class Certificate(base.Resource): - def __repr__(self): - return ("" % - (len(self.private_key) if self.private_key else 0, - len(self.data))) - - -class CertificateManager(base.Manager): - """ - Manage :class:`Certificate` resources. - """ - resource_class = Certificate - - def create(self): - """ - Create a x509 certificate for a user in tenant. - """ - return self._create('/os-certificates', {}, 'certificate') - - def get(self): - """ - Get root certificate. - """ - return self._get("/os-certificates/root", 'certificate') diff --git a/awx/lib/site-packages/novaclient/v2/client.py b/awx/lib/site-packages/novaclient/v2/client.py deleted file mode 100644 index e087ac68c1..0000000000 --- a/awx/lib/site-packages/novaclient/v2/client.py +++ /dev/null @@ -1,229 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import client -from novaclient.v2 import agents -from novaclient.v2 import aggregates -from novaclient.v2 import availability_zones -from novaclient.v2 import certs -from novaclient.v2 import cloudpipe -from novaclient.v2 import fixed_ips -from novaclient.v2 import flavor_access -from novaclient.v2 import flavors -from novaclient.v2 import floating_ip_dns -from novaclient.v2 import floating_ip_pools -from novaclient.v2 import floating_ips -from novaclient.v2 import floating_ips_bulk -from novaclient.v2 import fping -from novaclient.v2 import hosts -from novaclient.v2 import hypervisors -from novaclient.v2 import images -from novaclient.v2 import keypairs -from novaclient.v2 import limits -from novaclient.v2 import networks -from novaclient.v2 import quota_classes -from novaclient.v2 import quotas -from novaclient.v2 import security_group_default_rules -from novaclient.v2 import security_group_rules -from novaclient.v2 import security_groups -from novaclient.v2 import server_groups -from novaclient.v2 import servers -from novaclient.v2 import services -from novaclient.v2 import usage -from novaclient.v2 import versions -from novaclient.v2 import virtual_interfaces -from novaclient.v2 import volume_snapshots -from novaclient.v2 import volume_types -from novaclient.v2 import volumes - - -class Client(object): - """ - Top-level object to access the OpenStack Compute API. - - Create an instance with your creds:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) - - Or, alternatively, you can create a client instance using the - keystoneclient.session API:: - - >>> from keystoneclient.auth.identity import v2 - >>> from keystoneclient import session - >>> from novaclient.client import Client - >>> auth = v2.Password(auth_url=AUTH_URL, - username=USERNAME, - password=PASSWORD, - tenant_name=PROJECT_ID) - >>> sess = session.Session(auth=auth) - >>> nova = client.Client(VERSION, session=sess) - - Then call methods on its managers:: - - >>> client.servers.list() - ... - >>> client.flavors.list() - ... - - It is also possible to use an instance as a context manager in which - case there will be a session kept alive for the duration of the with - statement:: - - >>> with Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) as client: - ... client.servers.list() - ... client.flavors.list() - ... - - It is also possible to have a permanent (process-long) connection pool, - by passing a connection_pool=True:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, - ... AUTH_URL, connection_pool=True) - """ - - def __init__(self, username=None, api_key=None, project_id=None, - auth_url=None, insecure=False, timeout=None, - proxy_tenant_id=None, proxy_token=None, region_name=None, - endpoint_type='publicURL', extensions=None, - service_type='compute', service_name=None, - volume_service_name=None, timings=False, bypass_url=None, - os_cache=False, no_cache=True, http_log_debug=False, - auth_system='keystone', auth_plugin=None, auth_token=None, - cacert=None, tenant_id=None, user_id=None, - connection_pool=False, session=None, auth=None, - **kwargs): - # FIXME(comstud): Rename the api_key argument above when we - # know it's not being used as keyword argument - - # NOTE(cyeoh): In the novaclient context (unlike Nova) the - # project_id is not the same as the tenant_id. Here project_id - # is a name (what the Nova API often refers to as a project or - # tenant name) and tenant_id is a UUID (what the Nova API - # often refers to as a project_id or tenant_id). - - password = api_key - self.projectid = project_id - self.tenant_id = tenant_id - self.user_id = user_id - self.flavors = flavors.FlavorManager(self) - self.flavor_access = flavor_access.FlavorAccessManager(self) - self.images = images.ImageManager(self) - self.limits = limits.LimitsManager(self) - self.servers = servers.ServerManager(self) - self.versions = versions.VersionManager(self) - - # extensions - self.agents = agents.AgentsManager(self) - self.dns_domains = floating_ip_dns.FloatingIPDNSDomainManager(self) - self.dns_entries = floating_ip_dns.FloatingIPDNSEntryManager(self) - self.cloudpipe = cloudpipe.CloudpipeManager(self) - self.certs = certs.CertificateManager(self) - self.floating_ips = floating_ips.FloatingIPManager(self) - self.floating_ip_pools = floating_ip_pools.FloatingIPPoolManager(self) - self.fping = fping.FpingManager(self) - self.volumes = volumes.VolumeManager(self) - self.volume_snapshots = volume_snapshots.SnapshotManager(self) - self.volume_types = volume_types.VolumeTypeManager(self) - self.keypairs = keypairs.KeypairManager(self) - self.networks = networks.NetworkManager(self) - self.quota_classes = quota_classes.QuotaClassSetManager(self) - self.quotas = quotas.QuotaSetManager(self) - self.security_groups = security_groups.SecurityGroupManager(self) - self.security_group_rules = \ - security_group_rules.SecurityGroupRuleManager(self) - self.security_group_default_rules = \ - security_group_default_rules.SecurityGroupDefaultRuleManager(self) - self.usage = usage.UsageManager(self) - self.virtual_interfaces = \ - virtual_interfaces.VirtualInterfaceManager(self) - self.aggregates = aggregates.AggregateManager(self) - self.hosts = hosts.HostManager(self) - self.hypervisors = hypervisors.HypervisorManager(self) - self.hypervisor_stats = hypervisors.HypervisorStatsManager(self) - self.services = services.ServiceManager(self) - self.fixed_ips = fixed_ips.FixedIPsManager(self) - self.floating_ips_bulk = floating_ips_bulk.FloatingIPBulkManager(self) - self.os_cache = os_cache or not no_cache - self.availability_zones = \ - availability_zones.AvailabilityZoneManager(self) - self.server_groups = server_groups.ServerGroupsManager(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - self.client = client._construct_http_client( - username=username, - password=password, - user_id=user_id, - project_id=project_id, - tenant_id=tenant_id, - auth_url=auth_url, - auth_token=auth_token, - insecure=insecure, - timeout=timeout, - auth_system=auth_system, - auth_plugin=auth_plugin, - proxy_token=proxy_token, - proxy_tenant_id=proxy_tenant_id, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - timings=timings, - bypass_url=bypass_url, - os_cache=self.os_cache, - http_log_debug=http_log_debug, - cacert=cacert, - connection_pool=connection_pool, - session=session, - auth=auth, - **kwargs) - - @client._original_only - def __enter__(self): - self.client.open_session() - return self - - @client._original_only - def __exit__(self, t, v, tb): - self.client.close_session() - - @client._original_only - def set_management_url(self, url): - self.client.set_management_url(url) - - def get_timings(self): - return self.client.get_timings() - - def reset_timings(self): - self.client.reset_timings() - - @client._original_only - def authenticate(self): - """ - Authenticate against the server. - - Normally this is called automatically when you first access the API, - but you can call this method to force authentication right now. - - Returns on success; raises :exc:`exceptions.Unauthorized` if the - credentials are wrong. - """ - self.client.authenticate() diff --git a/awx/lib/site-packages/novaclient/v2/cloudpipe.py b/awx/lib/site-packages/novaclient/v2/cloudpipe.py deleted file mode 100644 index c0926ed405..0000000000 --- a/awx/lib/site-packages/novaclient/v2/cloudpipe.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Cloudpipe interface.""" - -from novaclient import base - - -class Cloudpipe(base.Resource): - """A cloudpipe instance is a VPN attached to a project's VLAN.""" - - def __repr__(self): - return "" % self.project_id - - def delete(self): - self.manager.delete(self) - - -class CloudpipeManager(base.ManagerWithFind): - resource_class = Cloudpipe - - def create(self, project): - """ - Launch a cloudpipe instance. - - :param project: UUID of the project (tenant) for the cloudpipe - """ - body = {'cloudpipe': {'project_id': project}} - return self._create('/os-cloudpipe', body, 'instance_id', - return_raw=True) - - def list(self): - """ - Get a list of cloudpipe instances. - """ - return self._list('/os-cloudpipe', 'cloudpipes') - - def update(self, address, port): - """ - Update VPN address and port for all networks associated - with the project defined by authentication - - :param address: IP address - :param port: Port number - """ - - body = {'configure_project': {'vpn_ip': address, - 'vpn_port': port}} - self._update("/os-cloudpipe/configure-project", body) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/__init__.py b/awx/lib/site-packages/novaclient/v2/contrib/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/novaclient/v2/contrib/assisted_volume_snapshots.py b/awx/lib/site-packages/novaclient/v2/contrib/assisted_volume_snapshots.py deleted file mode 100644 index ce1a0413c8..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/assisted_volume_snapshots.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2013, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Assisted volume snapshots - to be used by Cinder and not end users. -""" - -import json - -from novaclient import base - - -class Snapshot(base.Resource): - def __repr__(self): - return "" % self.id - - def delete(self): - """ - Delete this snapshot. - """ - self.manager.delete(self) - - -class AssistedSnapshotManager(base.Manager): - resource_class = Snapshot - - def create(self, volume_id, create_info): - body = {'snapshot': {'volume_id': volume_id, - 'create_info': create_info}} - return self._create('/os-assisted-volume-snapshots', body, 'snapshot') - - def delete(self, snapshot, delete_info): - self._delete("/os-assisted-volume-snapshots/%s?delete_info=%s" % ( - base.getid(snapshot), json.dumps(delete_info))) - -manager_class = AssistedSnapshotManager -name = 'assisted_volume_snapshots' diff --git a/awx/lib/site-packages/novaclient/v2/contrib/baremetal.py b/awx/lib/site-packages/novaclient/v2/contrib/baremetal.py deleted file mode 100644 index d23a38e53c..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/baremetal.py +++ /dev/null @@ -1,339 +0,0 @@ -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Baremetal interface (v2 extension). -""" - -from novaclient import base -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class BareMetalNode(base.Resource): - """ - A baremetal node (typically a physical server or an empty VM). - """ - - def __repr__(self): - return "" % self.id - - -class BareMetalNodeInterface(base.Resource): - """ - An interface belonging to a baremetal node. - """ - - def __repr__(self): - return "" % self.id - - -class BareMetalNodeManager(base.ManagerWithFind): - """ - Manage :class:`BareMetalNode` resources. - """ - resource_class = BareMetalNode - - def create(self, - service_host, - cpus, - memory_mb, - local_gb, - prov_mac_address, - pm_address=None, - pm_user=None, - pm_password=None, - terminal_port=None): - """ - Create a baremetal node. - - :param service_host: Name of controlling compute host - :param cpus: Number of CPUs in the node - :param memory_mb: Megabytes of RAM in the node - :param local_gb: Gigabytes of local storage in the node - :param pm_address: Power management IP for the node - :param pm_user: Username for the node's power management - :param pm_password: Password for the node's power management - :param prov_mac_address: MAC address to provision the node - :param terminal_port: ShellInABox port - :rtype: :class:`BareMetalNode` - """ - body = {'node': {'service_host': service_host, - 'cpus': cpus, - 'memory_mb': memory_mb, - 'local_gb': local_gb, - 'pm_address': pm_address, - 'pm_user': pm_user, - 'pm_password': pm_password, - 'prov_mac_address': prov_mac_address, - 'terminal_port': terminal_port}} - - return self._create('/os-baremetal-nodes', body, 'node') - - def delete(self, node): - """ - Delete a baremetal node. - - :param node: The :class:`BareMetalNode` to delete. - """ - self._delete('/os-baremetal-nodes/%s' % base.getid(node)) - - def get(self, node_id): - """ - Get a baremetal node. - - :param node_id: The ID of the node to delete. - :rtype: :class:`BareMetalNode` - """ - return self._get("/os-baremetal-nodes/%s" % node_id, 'node') - - def list(self): - """ - Get a list of all baremetal nodes. - - :rtype: list of :class:`BareMetalNode` - """ - return self._list('/os-baremetal-nodes', 'nodes') - - def add_interface(self, node_id, address, datapath_id=0, port_no=0): - """ - Add an interface to a baremetal node. - - :param node_id: The ID of the node to modify. - :param address: The MAC address to add. - :param datapath_id: Datapath ID of OpenFlow switch for the interface - :param port_no: OpenFlow port number for the interface - :rtype: :class:`BareMetalNodeInterface` - """ - body = {'add_interface': {'address': address, - 'datapath_id': datapath_id, - 'port_no': port_no}} - url = '/os-baremetal-nodes/%s/action' % node_id - _resp, body = self.api.client.post(url, body=body) - return BareMetalNodeInterface(self, body['interface']) - - def remove_interface(self, node_id, address): - """ - Remove an interface from a baremetal node. - - :param node_id: The ID of the node to modify. - :param address: The MAC address to remove. - :rtype: bool - """ - req_body = {'remove_interface': {'address': address}} - url = '/os-baremetal-nodes/%s/action' % node_id - self.api.client.post(url, body=req_body) - - def list_interfaces(self, node_id): - """ - List the interfaces on a baremetal node. - - :param node_id: The ID of the node to list. - :rtype: list - """ - interfaces = [] - node = self._get("/os-baremetal-nodes/%s" % node_id, 'node') - for interface in node.interfaces: - interface_object = BareMetalNodeInterface(self, interface) - interfaces.append(interface_object) - return interfaces - - -@cliutils.arg( - 'service_host', - metavar='', - help=_('Name of nova compute host which will control this baremetal ' - 'node')) -@cliutils.arg( - 'cpus', - metavar='', - type=int, - help=_('Number of CPUs in the node')) -@cliutils.arg( - 'memory_mb', - metavar='', - type=int, - help=_('Megabytes of RAM in the node')) -@cliutils.arg( - 'local_gb', - metavar='', - type=int, - help=_('Gigabytes of local storage in the node')) -@cliutils.arg( - 'prov_mac_address', - metavar='', - help=_('MAC address to provision the node')) -@cliutils.arg( - '--pm_address', default=None, - metavar='', - help=_('Power management IP for the node')) -@cliutils.arg( - '--pm_user', default=None, - metavar='', - help=_('Username for the node\'s power management')) -@cliutils.arg( - '--pm_password', default=None, - metavar='', - help=_('Password for the node\'s power management')) -@cliutils.arg( - '--terminal_port', default=None, - metavar='', - type=int, - help=_('ShellInABox port?')) -def do_baremetal_node_create(cs, args): - """Create a baremetal node.""" - node = cs.baremetal.create(args.service_host, args.cpus, - args.memory_mb, args.local_gb, - args.prov_mac_address, - pm_address=args.pm_address, - pm_user=args.pm_user, - pm_password=args.pm_password, - terminal_port=args.terminal_port) - _print_baremetal_resource(node) - - -@cliutils.arg( - 'node', - metavar='', - help=_('ID of the node to delete.')) -def do_baremetal_node_delete(cs, args): - """Remove a baremetal node and any associated interfaces.""" - node = _find_baremetal_node(cs, args.node) - cs.baremetal.delete(node) - - -def _translate_baremetal_node_keys(collection): - convert = [('service_host', 'host'), - ('local_gb', 'disk_gb'), - ('prov_mac_address', 'mac_address'), - ('pm_address', 'pm_address'), - ('pm_user', 'pm_username'), - ('pm_password', 'pm_password'), - ('terminal_port', 'terminal_port'), - ] - for item in collection: - keys = item.__dict__.keys() - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _print_baremetal_nodes_list(nodes): - """Print the list of baremetal nodes.""" - - def _parse_address(fields): - macs = [] - for interface in fields.interfaces: - macs.append(interface['address']) - return ', '.join("%s" % i for i in macs) - - formatters = { - 'MAC Address': _parse_address - } - - _translate_baremetal_node_keys(nodes) - utils.print_list(nodes, [ - 'ID', - 'Host', - 'Task State', - 'CPUs', - 'Memory_MB', - 'Disk_GB', - 'MAC Address', - 'PM Address', - 'PM Username', - 'PM Password', - 'Terminal Port', - ], formatters=formatters) - - -def do_baremetal_node_list(cs, _args): - """Print list of available baremetal nodes.""" - nodes = cs.baremetal.list() - _print_baremetal_nodes_list(nodes) - - -def _find_baremetal_node(cs, node): - """Get a node by ID.""" - return utils.find_resource(cs.baremetal, node) - - -def _print_baremetal_resource(resource): - """Print details of a baremetal resource.""" - info = resource._info.copy() - utils.print_dict(info) - - -def _print_baremetal_node_interfaces(interfaces): - """Print interfaces of a baremetal node.""" - utils.print_list(interfaces, [ - 'ID', - 'Datapath_ID', - 'Port_No', - 'Address', - ]) - - -@cliutils.arg( - 'node', - metavar='', - help=_("ID of node")) -def do_baremetal_node_show(cs, args): - """Show information about a baremetal node.""" - node = _find_baremetal_node(cs, args.node) - _print_baremetal_resource(node) - - -@cliutils.arg( - 'node', - metavar='', - help=_("ID of node")) -@cliutils.arg( - 'address', - metavar='
', - help=_("MAC address of interface")) -@cliutils.arg( - '--datapath_id', - default=0, - metavar='', - help=_("OpenFlow Datapath ID of interface")) -@cliutils.arg( - '--port_no', - default=0, - metavar='', - help=_("OpenFlow port number of interface")) -def do_baremetal_interface_add(cs, args): - """Add a network interface to a baremetal node.""" - bmif = cs.baremetal.add_interface(args.node, args.address, - args.datapath_id, args.port_no) - _print_baremetal_resource(bmif) - - -@cliutils.arg('node', metavar='', help=_("ID of node")) -@cliutils.arg( - 'address', - metavar='
', - help=_("MAC address of interface")) -def do_baremetal_interface_remove(cs, args): - """Remove a network interface from a baremetal node.""" - cs.baremetal.remove_interface(args.node, args.address) - - -@cliutils.arg('node', metavar='', help=_("ID of node")) -def do_baremetal_interface_list(cs, args): - """List network interfaces associated with a baremetal node.""" - interfaces = cs.baremetal.list_interfaces(args.node) - _print_baremetal_node_interfaces(interfaces) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/cells.py b/awx/lib/site-packages/novaclient/v2/contrib/cells.py deleted file mode 100644 index 7099a5a007..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/cells.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class Cell(base.Resource): - def __repr__(self): - return "" % self.name - - -class CellsManager(base.Manager): - resource_class = Cell - - def get(self, cell_name): - """ - Get a cell. - - :param cell_name: Name of the :class:`Cell` to get. - :rtype: :class:`Cell` - """ - return self._get("/os-cells/%s" % cell_name, "cell") - - def capacities(self, cell_name=None): - """ - Get capacities for a cell. - - :param cell_name: Name of the :class:`Cell` to get capacities for. - :rtype: :class:`Cell` - """ - path = ["%s/capacities" % cell_name, "capacities"][cell_name is None] - return self._get("/os-cells/%s" % path, "cell") - - -@cliutils.arg( - 'cell', - metavar='', - help=_('Name of the cell.')) -def do_cell_show(cs, args): - """Show details of a given cell.""" - cell = cs.cells.get(args.cell) - utils.print_dict(cell._info) - - -@cliutils.arg( - '--cell', - metavar='', - help=_("Name of the cell to get the capacities."), - default=None) -def do_cell_capacities(cs, args): - """Get cell capacities for all cells or a given cell.""" - cell = cs.cells.capacities(args.cell) - print(_("Ram Available: %s MB") % cell.capacities['ram_free']['total_mb']) - utils.print_dict(cell.capacities['ram_free']['units_by_mb'], - dict_property='Ram(MB)', dict_value="Units") - print(_("\nDisk Available: %s MB") % - cell.capacities['disk_free']['total_mb']) - utils.print_dict(cell.capacities['disk_free']['units_by_mb'], - dict_property='Disk(MB)', dict_value="Units") diff --git a/awx/lib/site-packages/novaclient/v2/contrib/deferred_delete.py b/awx/lib/site-packages/novaclient/v2/contrib/deferred_delete.py deleted file mode 100644 index 5d8d7d9e39..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/deferred_delete.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from novaclient.openstack.common import cliutils -from novaclient import utils - - -@cliutils.arg('server', metavar='', help='Name or ID of server.') -def do_force_delete(cs, args): - """Force delete a server.""" - utils.find_resource(cs.servers, args.server).force_delete() - - -@cliutils.arg('server', metavar='', help='Name or ID of server.') -def do_restore(cs, args): - """Restore a soft-deleted server.""" - utils.find_resource(cs.servers, args.server).restore() diff --git a/awx/lib/site-packages/novaclient/v2/contrib/host_evacuate.py b/awx/lib/site-packages/novaclient/v2/contrib/host_evacuate.py deleted file mode 100644 index b08e28cd1c..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/host_evacuate.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class EvacuateHostResponse(base.Resource): - pass - - -def _server_evacuate(cs, server, args): - success = True - error_message = "" - try: - cs.servers.evacuate(server=server['uuid'], host=args.target_host, - on_shared_storage=args.on_shared_storage) - except Exception as e: - success = False - error_message = _("Error while evacuating instance: %s") % e - return EvacuateHostResponse(base.Manager, - {"server_uuid": server['uuid'], - "evacuate_accepted": success, - "error_message": error_message}) - - -@cliutils.arg('host', metavar='', help='Name of host.') -@cliutils.arg( - '--target_host', - metavar='', - default=None, - help=_('Name of target host. If no host is specified the scheduler will ' - 'select a target.')) -@cliutils.arg( - '--on-shared-storage', - dest='on_shared_storage', - action="store_true", - default=False, - help=_('Specifies whether all instances files are on shared storage')) -def do_host_evacuate(cs, args): - """Evacuate all instances from failed host.""" - hypervisors = cs.hypervisors.search(args.host, servers=True) - response = [] - for hyper in hypervisors: - if hasattr(hyper, 'servers'): - for server in hyper.servers: - response.append(_server_evacuate(cs, server, args)) - - utils.print_list(response, - ["Server UUID", "Evacuate Accepted", "Error Message"]) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/host_evacuate_live.py b/awx/lib/site-packages/novaclient/v2/contrib/host_evacuate_live.py deleted file mode 100644 index 276fb2f703..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/host_evacuate_live.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -def _server_live_migrate(cs, server, args): - class HostEvacuateLiveResponse(object): - def __init__(self, server_uuid, live_migration_accepted, - error_message): - self.server_uuid = server_uuid - self.live_migration_accepted = live_migration_accepted - self.error_message = error_message - success = True - error_message = "" - try: - cs.servers.live_migrate(server['uuid'], args.target_host, - args.block_migrate, args.disk_over_commit) - except Exception as e: - success = False - error_message = _("Error while live migrating instance: %s") % e - return HostEvacuateLiveResponse(server['uuid'], - success, - error_message) - - -@cliutils.arg('host', metavar='', help='Name of host.') -@cliutils.arg( - '--target-host', - metavar='', - default=None, - help=_('Name of target host.')) -@cliutils.arg( - '--block-migrate', - action='store_true', - default=False, - help=_('Enable block migration.')) -@cliutils.arg( - '--disk-over-commit', - action='store_true', - default=False, - help=_('Enable disk overcommit.')) -def do_host_evacuate_live(cs, args): - """Live migrate all instances of the specified host - to other available hosts. - """ - hypervisors = cs.hypervisors.search(args.host, servers=True) - response = [] - for hyper in hypervisors: - for server in getattr(hyper, 'servers', []): - response.append(_server_live_migrate(cs, server, args)) - - utils.print_list(response, ["Server UUID", "Live Migration Accepted", - "Error Message"]) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/host_servers_migrate.py b/awx/lib/site-packages/novaclient/v2/contrib/host_servers_migrate.py deleted file mode 100644 index 470f161f19..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/host_servers_migrate.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class HostServersMigrateResponse(base.Resource): - pass - - -def _server_migrate(cs, server): - success = True - error_message = "" - try: - cs.servers.migrate(server['uuid']) - except Exception as e: - success = False - error_message = _("Error while migrating instance: %s") % e - return HostServersMigrateResponse(base.Manager, - {"server_uuid": server['uuid'], - "migration_accepted": success, - "error_message": error_message}) - - -@cliutils.arg('host', metavar='', help='Name of host.') -def do_host_servers_migrate(cs, args): - """Migrate all instances of the specified host to other available hosts.""" - hypervisors = cs.hypervisors.search(args.host, servers=True) - response = [] - for hyper in hypervisors: - if hasattr(hyper, 'servers'): - for server in hyper.servers: - response.append(_server_migrate(cs, server)) - - utils.print_list(response, - ["Server UUID", "Migration Accepted", "Error Message"]) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/instance_action.py b/awx/lib/site-packages/novaclient/v2/contrib/instance_action.py deleted file mode 100644 index 10e518ea23..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/instance_action.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import pprint - -from novaclient import base -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class InstanceActionManager(base.ManagerWithFind): - resource_class = base.Resource - - def get(self, server, request_id): - """ - Get details of an action performed on an instance. - - :param request_id: The request_id of the action to get. - """ - return self._get("/servers/%s/os-instance-actions/%s" % - (base.getid(server), request_id), 'instanceAction') - - def list(self, server): - """ - Get a list of actions performed on an server. - """ - return self._list('/servers/%s/os-instance-actions' % - base.getid(server), 'instanceActions') - - -@cliutils.arg( - 'server', - metavar='', - help=_('Name or UUID of the server to show an action for.')) -@cliutils.arg( - 'request_id', - metavar='', - help=_('Request ID of the action to get.')) -def do_instance_action(cs, args): - """Show an action.""" - server = utils.find_resource(cs.servers, args.server) - action_resource = cs.instance_action.get(server, args.request_id) - action = action_resource._info - if 'events' in action: - action['events'] = pprint.pformat(action['events']) - utils.print_dict(action) - - -@cliutils.arg( - 'server', - metavar='', - help=_('Name or UUID of the server to list actions for.')) -def do_instance_action_list(cs, args): - """List actions on a server.""" - server = utils.find_resource(cs.servers, args.server) - actions = cs.instance_action.list(server) - utils.print_list(actions, - ['Action', 'Request_ID', 'Message', 'Start_Time'], - sortby_index=3) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/list_extensions.py b/awx/lib/site-packages/novaclient/v2/contrib/list_extensions.py deleted file mode 100644 index 7eb9f16c8a..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/list_extensions.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base -from novaclient import utils - - -class ListExtResource(base.Resource): - @property - def summary(self): - descr = self.description.strip() - if not descr: - return '??' - lines = descr.split("\n") - if len(lines) == 1: - return lines[0] - else: - return lines[0] + "..." - - -class ListExtManager(base.Manager): - resource_class = ListExtResource - - def show_all(self): - return self._list("/extensions", 'extensions') - - -def do_list_extensions(client, _args): - """ - List all the os-api extensions that are available. - """ - extensions = client.list_extensions.show_all() - fields = ["Name", "Summary", "Alias", "Updated"] - utils.print_list(extensions, fields) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/metadata_extensions.py b/awx/lib/site-packages/novaclient/v2/contrib/metadata_extensions.py deleted file mode 100644 index ad843b7461..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/metadata_extensions.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2013 Rackspace Hosting -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient.v2 import shell - - -@cliutils.arg( - 'host', - metavar='', - help=_('Name of host.')) -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'delete'], - help=_("Actions: 'set' or 'delete'")) -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to set or delete (only key is necessary on delete)')) -def do_host_meta(cs, args): - """Set or Delete metadata on all instances of a host.""" - hypervisors = cs.hypervisors.search(args.host, servers=True) - for hyper in hypervisors: - metadata = shell._extract_metadata(args) - if hasattr(hyper, 'servers'): - for server in hyper.servers: - if args.action == 'set': - cs.servers.set_meta(server['uuid'], metadata) - elif args.action == 'delete': - cs.servers.delete_meta(server['uuid'], metadata.keys()) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/migrations.py b/awx/lib/site-packages/novaclient/v2/contrib/migrations.py deleted file mode 100644 index 15959818a4..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/migrations.py +++ /dev/null @@ -1,91 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -migration interface -""" - -from six.moves.urllib import parse - -from novaclient import base -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class Migration(base.Resource): - def __repr__(self): - return "" % self.id - - -class MigrationManager(base.ManagerWithFind): - resource_class = Migration - - def list(self, host=None, status=None, cell_name=None): - """ - Get a list of migrations. - :param host: (optional) filter migrations by host name. - :param status: (optional) filter migrations by status. - :param cell_name: (optional) filter migrations for a cell. - """ - opts = {} - if host: - opts['host'] = host - if status: - opts['status'] = status - if cell_name: - opts['cell_name'] = cell_name - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - new_opts = sorted(opts.items(), key=lambda x: x[0]) - - query_string = "?%s" % parse.urlencode(new_opts) if new_opts else "" - - return self._list("/os-migrations%s" % query_string, "migrations") - - -@cliutils.arg( - '--host', - dest='host', - metavar='', - help=_('Fetch migrations for the given host.')) -@cliutils.arg( - '--status', - dest='status', - metavar='', - help=_('Fetch migrations for the given status.')) -@cliutils.arg( - '--cell_name', - dest='cell_name', - metavar='', - help=_('Fetch migrations for the given cell_name.')) -def do_migration_list(cs, args): - """Print a list of migrations.""" - _print_migrations(cs.migrations.list(args.host, args.status, - args.cell_name)) - - -def _print_migrations(migrations): - fields = ['Source Node', 'Dest Node', 'Source Compute', 'Dest Compute', - 'Dest Host', 'Status', 'Instance UUID', 'Old Flavor', - 'New Flavor', 'Created At', 'Updated At'] - - def old_flavor(migration): - return migration.old_instance_type_id - - def new_flavor(migration): - return migration.new_instance_type_id - - formatters = {'Old Flavor': old_flavor, 'New Flavor': new_flavor} - - utils.print_list(migrations, fields, formatters) diff --git a/awx/lib/site-packages/novaclient/v2/contrib/server_external_events.py b/awx/lib/site-packages/novaclient/v2/contrib/server_external_events.py deleted file mode 100644 index a45914b55c..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/server_external_events.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2014, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -External event triggering for servers, not to be used by users. -""" - -from novaclient import base - - -class Event(base.Resource): - def __repr__(self): - return "" % self.name - - -class ServerExternalEventManager(base.Manager): - resource_class = Event - - def create(self, events): - """Create one or more server events. - - :param:events: A list of dictionaries containing 'server_uuid', 'name', - 'status', and 'tag' (which may be absent) - """ - - body = {'events': events} - return self._create('/os-server-external-events', body, 'events', - return_raw=True) - - -manager_class = ServerExternalEventManager -name = 'server_external_events' diff --git a/awx/lib/site-packages/novaclient/v2/contrib/tenant_networks.py b/awx/lib/site-packages/novaclient/v2/contrib/tenant_networks.py deleted file mode 100644 index 0b56ae8ccd..0000000000 --- a/awx/lib/site-packages/novaclient/v2/contrib/tenant_networks.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from novaclient import base -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class TenantNetwork(base.Resource): - def delete(self): - self.manager.delete(network=self) - - -class TenantNetworkManager(base.ManagerWithFind): - resource_class = base.Resource - - def list(self): - return self._list('/os-tenant-networks', 'networks') - - def get(self, network): - return self._get('/os-tenant-networks/%s' % base.getid(network), - 'network') - - def delete(self, network): - self._delete('/os-tenant-networks/%s' % base.getid(network)) - - def create(self, label, cidr): - body = {'network': {'label': label, 'cidr': cidr}} - return self._create('/os-tenant-networks', body, 'network') - - -@cliutils.arg('network_id', metavar='', help='ID of network') -def do_net(cs, args): - """ - DEPRECATED, Use tenant-network-show instead. - """ - do_tenant_network_show(cs, args) - - -@cliutils.arg('network_id', metavar='', help='ID of network') -def do_tenant_network_show(cs, args): - """ - Show a tenant network. - """ - network = cs.tenant_networks.get(args.network_id) - utils.print_dict(network._info) - - -def do_net_list(cs, args): - """ - DEPRECATED, use tenant-network-list instead. - """ - do_tenant_network_list(cs, args) - - -def do_tenant_network_list(cs, args): - """ - List tenant networks. - """ - networks = cs.tenant_networks.list() - utils.print_list(networks, ['ID', 'Label', 'CIDR']) - - -@cliutils.arg( - 'label', - metavar='', - help=_('Network label (ex. my_new_network)')) -@cliutils.arg( - 'cidr', - metavar='', - help=_('IP block to allocate from (ex. 172.16.0.0/24 or 2001:DB8::/64)')) -def do_net_create(cs, args): - """ - DEPRECATED, use tenant-network-create instead. - """ - do_tenant_network_create(cs, args) - - -@cliutils.arg( - 'label', - metavar='', - help=_('Network label (ex. my_new_network)')) -@cliutils.arg( - 'cidr', - metavar='', - help=_('IP block to allocate from (ex. 172.16.0.0/24 or 2001:DB8::/64)')) -def do_tenant_network_create(cs, args): - """ - Create a tenant network. - """ - network = cs.tenant_networks.create(args.label, args.cidr) - utils.print_dict(network._info) - - -@cliutils.arg('network_id', metavar='', help='ID of network') -def do_net_delete(cs, args): - """ - DEPRECATED, use tenant-network-delete instead. - """ - do_tenant_network_delete(cs, args) - - -@cliutils.arg('network_id', metavar='', help='ID of network') -def do_tenant_network_delete(cs, args): - """ - Delete a tenant network. - """ - cs.tenant_networks.delete(args.network_id) diff --git a/awx/lib/site-packages/novaclient/v2/fixed_ips.py b/awx/lib/site-packages/novaclient/v2/fixed_ips.py deleted file mode 100644 index 4e7c0e9512..0000000000 --- a/awx/lib/site-packages/novaclient/v2/fixed_ips.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Fixed IPs interface. -""" - -from novaclient import base - - -class FixedIP(base.Resource): - def __repr__(self): - return "" % self.address - - -class FixedIPsManager(base.Manager): - resource_class = FixedIP - - def get(self, fixed_ip): - """ - Show information for a Fixed IP - - :param fixed_ip: Fixed IP address to get info for - """ - return self._get('/os-fixed-ips/%s' % base.getid(fixed_ip), - "fixed_ip") - - def reserve(self, fixed_ip): - """Reserve a Fixed IP - - :param fixed_ip: Fixed IP address to reserve - """ - body = {"reserve": None} - self.api.client.post('/os-fixed-ips/%s/action' % base.getid(fixed_ip), - body=body) - - def unreserve(self, fixed_ip): - """Unreserve a Fixed IP - - :param fixed_ip: Fixed IP address to unreserve - """ - body = {"unreserve": None} - self.api.client.post('/os-fixed-ips/%s/action' % base.getid(fixed_ip), - body=body) diff --git a/awx/lib/site-packages/novaclient/v2/flavor_access.py b/awx/lib/site-packages/novaclient/v2/flavor_access.py deleted file mode 100644 index ca78bdff75..0000000000 --- a/awx/lib/site-packages/novaclient/v2/flavor_access.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Flavor access interface.""" - -from novaclient import base -from novaclient.i18n import _ - - -class FlavorAccess(base.Resource): - def __repr__(self): - return ("" % - (self.flavor_id, self.tenant_id)) - - -class FlavorAccessManager(base.ManagerWithFind): - """ - Manage :class:`FlavorAccess` resources. - """ - resource_class = FlavorAccess - - def list(self, **kwargs): - if kwargs.get('flavor'): - return self._list_by_flavor(kwargs['flavor']) - elif kwargs.get('tenant'): - return self._list_by_tenant(kwargs['tenant']) - else: - raise NotImplementedError(_('Unknown list options.')) - - def _list_by_flavor(self, flavor): - return self._list('/flavors/%s/os-flavor-access' % base.getid(flavor), - 'flavor_access') - - def _list_by_tenant(self, tenant): - """Print flavor list shared with the given tenant.""" - # TODO(uni): need to figure out a proper URI for list_by_tenant - # since current API already provided current tenant_id information - raise NotImplementedError(_('Sorry, query by tenant not supported.')) - - def add_tenant_access(self, flavor, tenant): - """Add a tenant to the given flavor access list.""" - info = {'tenant': tenant} - return self._action('addTenantAccess', flavor, info) - - def remove_tenant_access(self, flavor, tenant): - """Remove a tenant from the given flavor access list.""" - info = {'tenant': tenant} - return self._action('removeTenantAccess', flavor, info) - - def _action(self, action, flavor, info, **kwargs): - """Perform a flavor action.""" - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/flavors/%s/action' % base.getid(flavor) - _resp, body = self.api.client.post(url, body=body) - - return [self.resource_class(self, res) - for res in body['flavor_access']] diff --git a/awx/lib/site-packages/novaclient/v2/flavors.py b/awx/lib/site-packages/novaclient/v2/flavors.py deleted file mode 100644 index 54b0f49743..0000000000 --- a/awx/lib/site-packages/novaclient/v2/flavors.py +++ /dev/null @@ -1,203 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Flavor interface. -""" - -from oslo.utils import strutils -from six.moves.urllib import parse - -from novaclient import base -from novaclient import exceptions -from novaclient.i18n import _ -from novaclient import utils - - -class Flavor(base.Resource): - """ - A flavor is an available hardware configuration for a server. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.name - - @property - def ephemeral(self): - """ - Provide a user-friendly accessor to OS-FLV-EXT-DATA:ephemeral - """ - return self._info.get("OS-FLV-EXT-DATA:ephemeral", 'N/A') - - @property - def is_public(self): - """ - Provide a user-friendly accessor to os-flavor-access:is_public - """ - return self._info.get("os-flavor-access:is_public", 'N/A') - - def get_keys(self): - """ - Get extra specs from a flavor. - """ - _resp, body = self.manager.api.client.get( - "/flavors/%s/os-extra_specs" % base.getid(self)) - return body["extra_specs"] - - def set_keys(self, metadata): - """ - Set extra specs on a flavor. - - :param metadata: A dict of key/value pairs to be set - """ - utils.validate_flavor_metadata_keys(metadata.keys()) - - body = {'extra_specs': metadata} - return self.manager._create( - "/flavors/%s/os-extra_specs" % base.getid(self), body, - "extra_specs", return_raw=True) - - def unset_keys(self, keys): - """ - Unset extra specs on a flavor. - - :param keys: A list of keys to be unset - """ - for k in keys: - self.manager._delete( - "/flavors/%s/os-extra_specs/%s" % (base.getid(self), k)) - - def delete(self): - """ - Delete this flavor. - """ - self.manager.delete(self) - - -class FlavorManager(base.ManagerWithFind): - """ - Manage :class:`Flavor` resources. - """ - resource_class = Flavor - is_alphanum_id_allowed = True - - def list(self, detailed=True, is_public=True): - """ - Get a list of all flavors. - - :rtype: list of :class:`Flavor`. - """ - qparams = {} - # is_public is ternary - None means give all flavors. - # By default Nova assumes True and gives admins public flavors - # and flavors from their own projects only. - if not is_public: - qparams['is_public'] = is_public - query_string = "?%s" % parse.urlencode(qparams) if qparams else "" - - detail = "" - if detailed: - detail = "/detail" - - return self._list("/flavors%s%s" % (detail, query_string), "flavors") - - def get(self, flavor): - """ - Get a specific flavor. - - :param flavor: The ID of the :class:`Flavor` to get. - :rtype: :class:`Flavor` - """ - return self._get("/flavors/%s" % base.getid(flavor), "flavor") - - def delete(self, flavor): - """ - Delete a specific flavor. - - :param flavor: The ID of the :class:`Flavor` to get. - """ - self._delete("/flavors/%s" % base.getid(flavor)) - - def _build_body(self, name, ram, vcpus, disk, id, swap, - ephemeral, rxtx_factor, is_public): - return { - "flavor": { - "name": name, - "ram": ram, - "vcpus": vcpus, - "disk": disk, - "id": id, - "swap": swap, - "OS-FLV-EXT-DATA:ephemeral": ephemeral, - "rxtx_factor": rxtx_factor, - "os-flavor-access:is_public": is_public, - } - } - - def create(self, name, ram, vcpus, disk, flavorid="auto", - ephemeral=0, swap=0, rxtx_factor=1.0, is_public=True): - """ - Create a flavor. - - :param name: Descriptive name of the flavor - :param ram: Memory in MB for the flavor - :param vcpus: Number of VCPUs for the flavor - :param disk: Size of local disk in GB - :param flavorid: ID for the flavor (optional). You can use the reserved - value ``"auto"`` to have Nova generate a UUID for the - flavor in cases where you cannot simply pass ``None``. - :param swap: Swap space in MB - :param rxtx_factor: RX/TX factor - :rtype: :class:`Flavor` - """ - - try: - ram = int(ram) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Ram must be an integer.")) - try: - vcpus = int(vcpus) - except (TypeError, ValueError): - raise exceptions.CommandError(_("VCPUs must be an integer.")) - try: - disk = int(disk) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Disk must be an integer.")) - - if flavorid == "auto": - flavorid = None - - try: - swap = int(swap) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Swap must be an integer.")) - try: - ephemeral = int(ephemeral) - except (TypeError, ValueError): - raise exceptions.CommandError(_("Ephemeral must be an integer.")) - try: - rxtx_factor = float(rxtx_factor) - except (TypeError, ValueError): - raise exceptions.CommandError(_("rxtx_factor must be a float.")) - - try: - is_public = strutils.bool_from_string(is_public, True) - except Exception: - raise exceptions.CommandError(_("is_public must be a boolean.")) - - body = self._build_body(name, ram, vcpus, disk, flavorid, swap, - ephemeral, rxtx_factor, is_public) - - return self._create("/flavors", body, "flavor") diff --git a/awx/lib/site-packages/novaclient/v2/floating_ip_dns.py b/awx/lib/site-packages/novaclient/v2/floating_ip_dns.py deleted file mode 100644 index 41df0f6284..0000000000 --- a/awx/lib/site-packages/novaclient/v2/floating_ip_dns.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright 2011 Andrew Bogott for The Wikimedia Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from six.moves.urllib import parse - -from novaclient import base - - -def _quote_domain(domain): - """Special quoting rule for placing domain names on a url line. - - Domain names tend to have .'s in them. Urllib doesn't quote dots, - but Routes tends to choke on them, so we need an extra level of - by-hand quoting here. - """ - return parse.quote(domain.replace('.', '%2E')) - - -class FloatingIPDNSDomain(base.Resource): - def delete(self): - self.manager.delete(self.domain) - - def create(self): - if self.scope == 'public': - self.manager.create_public(self.domain, self.project) - else: - self.manager.create_private(self.domain, self.availability_zone) - - def get(self): - entries = self.manager.domains() - for entry in entries: - if entry.get('domain') == self.domain: - return entry - - return None - - -class FloatingIPDNSDomainManager(base.Manager): - resource_class = FloatingIPDNSDomain - - def domains(self): - """Return the list of available dns domains.""" - return self._list("/os-floating-ip-dns", "domain_entries") - - def create_private(self, fqdomain, availability_zone): - """Add or modify a private DNS domain.""" - body = {'domain_entry': {'scope': 'private', - 'availability_zone': availability_zone}} - return self._update('/os-floating-ip-dns/%s' % _quote_domain(fqdomain), - body, - 'domain_entry') - - def create_public(self, fqdomain, project): - """Add or modify a public DNS domain.""" - body = {'domain_entry': {'scope': 'public', 'project': project}} - - return self._update('/os-floating-ip-dns/%s' % _quote_domain(fqdomain), - body, 'domain_entry') - - def delete(self, fqdomain): - """Delete the specified domain.""" - self._delete("/os-floating-ip-dns/%s" % _quote_domain(fqdomain)) - - -class FloatingIPDNSEntry(base.Resource): - def delete(self): - self.manager.delete(self.name, self.domain) - - def create(self): - self.manager.create(self.domain, self.name, self.ip, self.dns_type) - - def get(self): - return self.manager.get(self.domain, self.name) - - -class FloatingIPDNSEntryManager(base.Manager): - resource_class = FloatingIPDNSEntry - - def get(self, domain, name): - """Return a list of entries for the given domain and IP or name.""" - return self._get("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name), "dns_entry") - - def get_for_ip(self, domain, ip): - """Return a list of entries for the given domain and IP or name.""" - qparams = {'ip': ip} - params = "?%s" % parse.urlencode(qparams) - - return self._list("/os-floating-ip-dns/%s/entries%s" % - (_quote_domain(domain), params), "dns_entries") - - def create(self, domain, name, ip, dns_type): - """Add a new DNS entry.""" - body = {'dns_entry': {'ip': ip, 'dns_type': dns_type}} - - return self._update("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name), body, "dns_entry") - - def modify_ip(self, domain, name, ip): - """Add a new DNS entry.""" - body = {'dns_entry': {'ip': ip, 'dns_type': 'A'}} - - return self._update("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name), body, "dns_entry") - - def delete(self, domain, name): - """Delete entry specified by name and domain.""" - self._delete("/os-floating-ip-dns/%s/entries/%s" % - (_quote_domain(domain), name)) diff --git a/awx/lib/site-packages/novaclient/v2/floating_ip_pools.py b/awx/lib/site-packages/novaclient/v2/floating_ip_pools.py deleted file mode 100644 index 7666bd57f8..0000000000 --- a/awx/lib/site-packages/novaclient/v2/floating_ip_pools.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class FloatingIPPool(base.Resource): - def __repr__(self): - return "" % self.name - - -class FloatingIPPoolManager(base.ManagerWithFind): - resource_class = FloatingIPPool - - def list(self): - """ - Retrieve a list of all floating ip pools. - """ - return self._list('/os-floating-ip-pools', 'floating_ip_pools') diff --git a/awx/lib/site-packages/novaclient/v2/floating_ips.py b/awx/lib/site-packages/novaclient/v2/floating_ips.py deleted file mode 100644 index cce92da250..0000000000 --- a/awx/lib/site-packages/novaclient/v2/floating_ips.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class FloatingIP(base.Resource): - def delete(self): - """ - Delete this floating IP - """ - self.manager.delete(self) - - -class FloatingIPManager(base.ManagerWithFind): - resource_class = FloatingIP - - def list(self, all_tenants=False): - """ - List floating IPs - """ - url = '/os-floating-ips' - if all_tenants: - url += '?all_tenants=1' - return self._list(url, "floating_ips") - - def create(self, pool=None): - """ - Create (allocate) a floating IP for a tenant - """ - return self._create("/os-floating-ips", {'pool': pool}, "floating_ip") - - def delete(self, floating_ip): - """ - Delete (deallocate) a floating IP for a tenant - - :param floating_ip: The floating IP address to delete. - """ - self._delete("/os-floating-ips/%s" % base.getid(floating_ip)) - - def get(self, floating_ip): - """ - Retrieve a floating IP - """ - return self._get("/os-floating-ips/%s" % base.getid(floating_ip), - "floating_ip") diff --git a/awx/lib/site-packages/novaclient/v2/floating_ips_bulk.py b/awx/lib/site-packages/novaclient/v2/floating_ips_bulk.py deleted file mode 100644 index fb59a19e74..0000000000 --- a/awx/lib/site-packages/novaclient/v2/floating_ips_bulk.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Bulk Floating IPs interface -""" -from novaclient import base - - -class FloatingIP(base.Resource): - def __repr__(self): - return "" % self.address - - -class FloatingIPBulkManager(base.ManagerWithFind): - resource_class = FloatingIP - - def list(self, host=None): - """ - List all floating IPs - """ - if host is None: - return self._list('/os-floating-ips-bulk', 'floating_ip_info') - else: - return self._list('/os-floating-ips-bulk/%s' % host, - 'floating_ip_info') - - def create(self, ip_range, pool=None, interface=None): - """ - Create floating IPs by range - """ - body = {"floating_ips_bulk_create": {'ip_range': ip_range}} - if pool is not None: - body['floating_ips_bulk_create']['pool'] = pool - if interface is not None: - body['floating_ips_bulk_create']['interface'] = interface - - return self._create('/os-floating-ips-bulk', body, - 'floating_ips_bulk_create') - - def delete(self, ip_range): - """ - Delete floating IPs by range - """ - body = {"ip_range": ip_range} - return self._update('/os-floating-ips-bulk/delete', body) diff --git a/awx/lib/site-packages/novaclient/v2/fping.py b/awx/lib/site-packages/novaclient/v2/fping.py deleted file mode 100644 index 5e8b74bb9b..0000000000 --- a/awx/lib/site-packages/novaclient/v2/fping.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Fping interface. -""" - -from novaclient import base - - -class Fping(base.Resource): - """ - A server to fping. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.id - - -class FpingManager(base.ManagerWithFind): - """ - Manage :class:`Fping` resources. - """ - resource_class = Fping - - def list(self, all_tenants=False, include=[], exclude=[]): - """ - Fping all servers. - - :rtype: list of :class:`Fping`. - """ - params = [] - if all_tenants: - params.append("all_tenants=1") - if include: - params.append("include=%s" % ",".join(include)) - elif exclude: - params.append("exclude=%s" % ",".join(exclude)) - uri = "/os-fping" - if params: - uri = "%s?%s" % (uri, "&".join(params)) - return self._list(uri, "servers") - - def get(self, server): - """ - Fping a specific server. - - :param server: ID of the server to fping. - :rtype: :class:`Fping` - """ - return self._get("/os-fping/%s" % base.getid(server), "server") diff --git a/awx/lib/site-packages/novaclient/v2/hosts.py b/awx/lib/site-packages/novaclient/v2/hosts.py deleted file mode 100644 index af1756ad2c..0000000000 --- a/awx/lib/site-packages/novaclient/v2/hosts.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -host interface (1.1 extension). -""" -from novaclient import base - - -class Host(base.Resource): - def __repr__(self): - return "" % self.host - - def _add_details(self, info): - dico = 'resource' in info and info['resource'] or info - for (k, v) in dico.items(): - setattr(self, k, v) - - def update(self, values): - return self.manager.update(self.host, values) - - def startup(self): - return self.manager.host_action(self.host, 'startup') - - def shutdown(self): - return self.manager.host_action(self.host, 'shutdown') - - def reboot(self): - return self.manager.host_action(self.host, 'reboot') - - -class HostManager(base.ManagerWithFind): - resource_class = Host - - def get(self, host): - """ - Describes cpu/memory/hdd info for host. - - :param host: destination host name. - """ - return self._list("/os-hosts/%s" % host, "host") - - def update(self, host, values): - """Update status or maintenance mode for the host.""" - return self._update("/os-hosts/%s" % host, values) - - def host_action(self, host, action): - """Perform an action on a host.""" - url = '/os-hosts/{0}/{1}'.format(host, action) - return self.api.client.get(url) - - def list(self, zone=None): - url = '/os-hosts' - if zone: - url = '/os-hosts?zone=%s' % zone - return self._list(url, "hosts") - - list_all = list diff --git a/awx/lib/site-packages/novaclient/v2/hypervisors.py b/awx/lib/site-packages/novaclient/v2/hypervisors.py deleted file mode 100644 index b1bfcb4b97..0000000000 --- a/awx/lib/site-packages/novaclient/v2/hypervisors.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Hypervisors interface (1.1 extension). -""" - -from six.moves.urllib import parse - -from novaclient import base - - -class Hypervisor(base.Resource): - NAME_ATTR = 'hypervisor_hostname' - - def __repr__(self): - return "" % self.id - - -class HypervisorManager(base.ManagerWithFind): - resource_class = Hypervisor - - def list(self, detailed=True): - """ - Get a list of hypervisors. - """ - detail = "" - if detailed: - detail = "/detail" - return self._list('/os-hypervisors%s' % detail, 'hypervisors') - - def search(self, hypervisor_match, servers=False): - """ - Get a list of matching hypervisors. - - :param servers: If True, server information is also retrieved. - """ - target = 'servers' if servers else 'search' - url = ('/os-hypervisors/%s/%s' % - (parse.quote(hypervisor_match, safe=''), target)) - return self._list(url, 'hypervisors') - - def get(self, hypervisor): - """ - Get a specific hypervisor. - """ - return self._get("/os-hypervisors/%s" % base.getid(hypervisor), - "hypervisor") - - def uptime(self, hypervisor): - """ - Get the uptime for a specific hypervisor. - """ - return self._get("/os-hypervisors/%s/uptime" % base.getid(hypervisor), - "hypervisor") - - def statistics(self): - """ - Get hypervisor statistics over all compute nodes. - - Kept for backwards compatibility, new code should call - hypervisor_stats.statistics() instead of hypervisors.statistics() - """ - return self.api.hypervisor_stats.statistics() - - -class HypervisorStats(base.Resource): - def __repr__(self): - return ("" % - (self.count, "s" if self.count != 1 else "")) - - -class HypervisorStatsManager(base.Manager): - resource_class = HypervisorStats - - def statistics(self): - """ - Get hypervisor statistics over all compute nodes. - """ - return self._get("/os-hypervisors/statistics", "hypervisor_statistics") diff --git a/awx/lib/site-packages/novaclient/v2/images.py b/awx/lib/site-packages/novaclient/v2/images.py deleted file mode 100644 index 2d413a6bfe..0000000000 --- a/awx/lib/site-packages/novaclient/v2/images.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Image interface. -""" - -from six.moves.urllib import parse - -from novaclient import base - - -class Image(base.Resource): - """ - An image is a collection of files used to create or rebuild a server. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.name - - def delete(self): - """ - Delete this image. - """ - self.manager.delete(self) - - -class ImageManager(base.ManagerWithFind): - """ - Manage :class:`Image` resources. - """ - resource_class = Image - - def get(self, image): - """ - Get an image. - - :param image: The ID of the image to get. - :rtype: :class:`Image` - """ - return self._get("/images/%s" % base.getid(image), "image") - - def list(self, detailed=True, limit=None): - """ - Get a list of all images. - - :rtype: list of :class:`Image` - :param limit: maximum number of images to return. - """ - params = {} - detail = '' - if detailed: - detail = '/detail' - if limit: - params['limit'] = int(limit) - query = '?%s' % parse.urlencode(params) if params else '' - return self._list('/images%s%s' % (detail, query), 'images') - - def delete(self, image): - """ - Delete an image. - - It should go without saying that you can't delete an image - that you didn't create. - - :param image: The :class:`Image` (or its ID) to delete. - """ - self._delete("/images/%s" % base.getid(image)) - - def set_meta(self, image, metadata): - """ - Set an images metadata - - :param image: The :class:`Image` to add metadata to - :param metadata: A dict of metadata to add to the image - """ - body = {'metadata': metadata} - return self._create("/images/%s/metadata" % base.getid(image), - body, "metadata") - - def delete_meta(self, image, keys): - """ - Delete metadata from an image - - :param image: The :class:`Image` to delete metadata - :param keys: A list of metadata keys to delete from the image - """ - for k in keys: - self._delete("/images/%s/metadata/%s" % (base.getid(image), k)) diff --git a/awx/lib/site-packages/novaclient/v2/keypairs.py b/awx/lib/site-packages/novaclient/v2/keypairs.py deleted file mode 100644 index 96caff6189..0000000000 --- a/awx/lib/site-packages/novaclient/v2/keypairs.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Keypair interface (1.1 extension). -""" - -from novaclient import base - - -class Keypair(base.Resource): - """ - A keypair is a ssh key that can be injected into a server on launch. - """ - - def __repr__(self): - return "" % self.id - - def _add_details(self, info): - dico = 'keypair' in info and \ - info['keypair'] or info - for (k, v) in dico.items(): - # NOTE(rpodolyaka): keypair name allows us to uniquely identify - # a specific keypair, while its id attribute - # is nothing more than an implementation - # detail. We can safely omit the id attribute - # here to ensure setattr() won't raise - # AttributeError trying to set read-only - # property id - if k != 'id': - setattr(self, k, v) - - @property - def id(self): - return self.name - - def delete(self): - self.manager.delete(self) - - -class KeypairManager(base.ManagerWithFind): - resource_class = Keypair - keypair_prefix = "os-keypairs" - is_alphanum_id_allowed = True - - def get(self, keypair): - """ - Get a keypair. - - :param keypair: The ID of the keypair to get. - :rtype: :class:`Keypair` - """ - return self._get("/%s/%s" % (self.keypair_prefix, base.getid(keypair)), - "keypair") - - def create(self, name, public_key=None): - """ - Create a keypair - - :param name: name for the keypair to create - :param public_key: existing public key to import - """ - body = {'keypair': {'name': name}} - if public_key: - body['keypair']['public_key'] = public_key - return self._create('/%s' % self.keypair_prefix, body, 'keypair') - - def delete(self, key): - """ - Delete a keypair - - :param key: The :class:`Keypair` (or its ID) to delete. - """ - self._delete('/%s/%s' % (self.keypair_prefix, base.getid(key))) - - def list(self): - """ - Get a list of keypairs. - """ - return self._list('/%s' % self.keypair_prefix, 'keypairs') diff --git a/awx/lib/site-packages/novaclient/v2/limits.py b/awx/lib/site-packages/novaclient/v2/limits.py deleted file mode 100644 index 46d77def81..0000000000 --- a/awx/lib/site-packages/novaclient/v2/limits.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from six.moves.urllib import parse - -from novaclient import base - - -class Limits(base.Resource): - """A collection of RateLimit and AbsoluteLimit objects.""" - - def __repr__(self): - return "" - - @property - def absolute(self): - for (name, value) in self._info['absolute'].items(): - yield AbsoluteLimit(name, value) - - @property - def rate(self): - for group in self._info['rate']: - uri = group['uri'] - regex = group['regex'] - for rate in group['limit']: - yield RateLimit(rate['verb'], uri, regex, rate['value'], - rate['remaining'], rate['unit'], - rate['next-available']) - - -class RateLimit(object): - """Data model that represents a flattened view of a single rate limit.""" - - def __init__(self, verb, uri, regex, value, remain, - unit, next_available): - self.verb = verb - self.uri = uri - self.regex = regex - self.value = value - self.remain = remain - self.unit = unit - self.next_available = next_available - - def __eq__(self, other): - return self.uri == other.uri \ - and self.regex == other.regex \ - and self.value == other.value \ - and self.verb == other.verb \ - and self.remain == other.remain \ - and self.unit == other.unit \ - and self.next_available == other.next_available - - def __repr__(self): - return "" % (self.verb, self.uri) - - -class AbsoluteLimit(object): - """Data model that represents a single absolute limit.""" - - def __init__(self, name, value): - self.name = name - self.value = value - - def __eq__(self, other): - return self.value == other.value and self.name == other.name - - def __repr__(self): - return "" % (self.name) - - -class LimitsManager(base.Manager): - """Manager object used to interact with limits resource.""" - - resource_class = Limits - - def get(self, reserved=False, tenant_id=None): - """ - Get a specific extension. - - :rtype: :class:`Limits` - """ - opts = {} - if reserved: - opts['reserved'] = 1 - if tenant_id: - opts['tenant_id'] = tenant_id - query_string = "?%s" % parse.urlencode(opts) if opts else "" - - return self._get("/limits%s" % query_string, "limits") diff --git a/awx/lib/site-packages/novaclient/v2/networks.py b/awx/lib/site-packages/novaclient/v2/networks.py deleted file mode 100644 index 06dee27047..0000000000 --- a/awx/lib/site-packages/novaclient/v2/networks.py +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Network interface. -""" - -from novaclient import base -from novaclient import exceptions -from novaclient.i18n import _ - - -class Network(base.Resource): - """ - A network. - """ - HUMAN_ID = True - NAME_ATTR = "label" - - def __repr__(self): - return "" % self.label - - def delete(self): - self.manager.delete(self) - - -class NetworkManager(base.ManagerWithFind): - """ - Manage :class:`Network` resources. - """ - resource_class = Network - - def list(self): - """ - Get a list of all networks. - - :rtype: list of :class:`Network`. - """ - return self._list("/os-networks", "networks") - - def get(self, network): - """ - Get a specific network. - - :param network: The ID of the :class:`Network` to get. - :rtype: :class:`Network` - """ - return self._get("/os-networks/%s" % base.getid(network), - "network") - - def delete(self, network): - """ - Delete a specific network. - - :param network: The ID of the :class:`Network` to delete. - """ - self._delete("/os-networks/%s" % base.getid(network)) - - def create(self, **kwargs): - """ - Create (allocate) a network. The following parameters are - optional except for label; cidr or cidr_v6 must be specified, too. - - :param label: str - :param bridge: str - :param bridge_interface: str - :param cidr: str - :param cidr_v6: str - :param dns1: str - :param dns2: str - :param fixed_cidr: str - :param gateway: str - :param gateway_v6: str - :param multi_host: str - :param priority: str - :param project_id: str - :param vlan: int - :param vlan_start: int - :param vpn_start: int - :param mtu: int - :param enable_dhcp: int - :param dhcp_server: str - :param share_address: int - :param allowed_start: str - :param allowed_end: str - - :rtype: object of :class:`Network` - """ - body = {"network": kwargs} - return self._create('/os-networks', body, 'network') - - def disassociate(self, network, disassociate_host=True, - disassociate_project=True): - """ - Disassociate a specific network from project and/or host. - - :param network: The ID of the :class:`Network`. - :param disassociate_host: Whether to disassociate the host - :param disassociate_project: Whether to disassociate the project - """ - if disassociate_host and disassociate_project: - body = {"disassociate": None} - elif disassociate_project: - body = {"disassociate_project": None} - elif disassociate_host: - body = {"disassociate_host": None} - else: - raise exceptions.CommandError( - _("Must disassociate either host or project or both")) - - self.api.client.post("/os-networks/%s/action" % - base.getid(network), body=body) - - def associate_host(self, network, host): - """ - Associate a specific network with a host. - - :param network: The ID of the :class:`Network`. - :param host: The name of the host to associate the network with - """ - self.api.client.post("/os-networks/%s/action" % - base.getid(network), - body={"associate_host": host}) - - def associate_project(self, network): - """ - Associate a specific network with a project. - - The project is defined by the project authenticated against - - :param network: The ID of the :class:`Network`. - """ - self.api.client.post("/os-networks/add", body={"id": network}) - - def add(self, network=None): - """ - Associates the current project with a network. Network can be chosen - automatically or provided explicitly. - - :param network: The ID of the :class:`Network` to associate (optional). - """ - self.api.client.post( - "/os-networks/add", - body={"id": base.getid(network) if network else None}) diff --git a/awx/lib/site-packages/novaclient/v2/quota_classes.py b/awx/lib/site-packages/novaclient/v2/quota_classes.py deleted file mode 100644 index 4a38a970c2..0000000000 --- a/awx/lib/site-packages/novaclient/v2/quota_classes.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class QuotaClassSet(base.Resource): - - def update(self, *args, **kwargs): - return self.manager.update(self.id, *args, **kwargs) - - -class QuotaClassSetManager(base.Manager): - resource_class = QuotaClassSet - - def get(self, class_name): - return self._get("/os-quota-class-sets/%s" % (class_name), - "quota_class_set") - - def _update_body(self, **kwargs): - return {'quota_class_set': kwargs} - - def update(self, class_name, **kwargs): - body = self._update_body(**kwargs) - - for key in list(body['quota_class_set']): - if body['quota_class_set'][key] is None: - body['quota_class_set'].pop(key) - - return self._update('/os-quota-class-sets/%s' % (class_name), - body, - 'quota_class_set') diff --git a/awx/lib/site-packages/novaclient/v2/quotas.py b/awx/lib/site-packages/novaclient/v2/quotas.py deleted file mode 100644 index cd16042b44..0000000000 --- a/awx/lib/site-packages/novaclient/v2/quotas.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import base - - -class QuotaSet(base.Resource): - - @property - def id(self): - """QuotaSet does not have a 'id' attribute but base.Resource needs it - to self-refresh and QuotaSet is indexed by tenant_id. - """ - return self.tenant_id - - def update(self, *args, **kwargs): - return self.manager.update(self.tenant_id, *args, **kwargs) - - -class QuotaSetManager(base.Manager): - resource_class = QuotaSet - - def get(self, tenant_id, user_id=None): - if hasattr(tenant_id, 'tenant_id'): - tenant_id = tenant_id.tenant_id - if user_id: - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - else: - url = '/os-quota-sets/%s' % tenant_id - return self._get(url, "quota_set") - - def _update_body(self, tenant_id, **kwargs): - kwargs['tenant_id'] = tenant_id - return {'quota_set': kwargs} - - def update(self, tenant_id, **kwargs): - - user_id = kwargs.pop('user_id', None) - body = self._update_body(tenant_id, **kwargs) - - for key in list(body['quota_set']): - if body['quota_set'][key] is None: - body['quota_set'].pop(key) - - if user_id: - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - else: - url = '/os-quota-sets/%s' % tenant_id - return self._update(url, body, 'quota_set') - - def defaults(self, tenant_id): - return self._get('/os-quota-sets/%s/defaults' % tenant_id, - 'quota_set') - - def delete(self, tenant_id, user_id=None): - if user_id: - url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id) - else: - url = '/os-quota-sets/%s' % tenant_id - self._delete(url) diff --git a/awx/lib/site-packages/novaclient/v2/security_group_default_rules.py b/awx/lib/site-packages/novaclient/v2/security_group_default_rules.py deleted file mode 100644 index d82a1d8180..0000000000 --- a/awx/lib/site-packages/novaclient/v2/security_group_default_rules.py +++ /dev/null @@ -1,81 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Security group default rules interface. -""" - -from novaclient import base -from novaclient import exceptions -from novaclient.i18n import _ - - -class SecurityGroupDefaultRule(base.Resource): - def __str__(self): - return str(self.id) - - def delete(self): - self.manager.delete(self) - - -class SecurityGroupDefaultRuleManager(base.Manager): - resource_class = SecurityGroupDefaultRule - - def create(self, ip_protocol=None, from_port=None, to_port=None, - cidr=None): - """ - Create a security group default rule - - :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp' - :param from_port: Source port - :param to_port: Destination port - :param cidr: Destination IP address(es) in CIDR notation - """ - - try: - from_port = int(from_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("From port must be an integer.")) - try: - to_port = int(to_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("To port must be an integer.")) - if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']: - raise exceptions.CommandError(_("IP protocol must be 'tcp', 'udp'" - ", or 'icmp'.")) - - body = {"security_group_default_rule": { - "ip_protocol": ip_protocol, - "from_port": from_port, - "to_port": to_port, - "cidr": cidr}} - - return self._create('/os-security-group-default-rules', body, - 'security_group_default_rule') - - def delete(self, rule): - """ - Delete a security group default rule - - :param rule: The security group default rule to delete (ID or Class) - """ - self._delete('/os-security-group-default-rules/%s' % base.getid(rule)) - - def list(self): - """ - Get a list of all security group default rules - - :rtype: list of :class:`SecurityGroupDefaultRule` - """ - - return self._list('/os-security-group-default-rules', - 'security_group_default_rules') diff --git a/awx/lib/site-packages/novaclient/v2/security_group_rules.py b/awx/lib/site-packages/novaclient/v2/security_group_rules.py deleted file mode 100644 index 4cb51b01bd..0000000000 --- a/awx/lib/site-packages/novaclient/v2/security_group_rules.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Security group rules interface (1.1 extension). -""" - -from novaclient import base -from novaclient import exceptions -from novaclient.i18n import _ - - -class SecurityGroupRule(base.Resource): - def __str__(self): - return str(self.id) - - def delete(self): - self.manager.delete(self) - - -class SecurityGroupRuleManager(base.Manager): - resource_class = SecurityGroupRule - - def create(self, parent_group_id, ip_protocol=None, from_port=None, - to_port=None, cidr=None, group_id=None): - """ - Create a security group rule - - :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp' - :param from_port: Source port - :param to_port: Destination port - :param cidr: Destination IP address(es) in CIDR notation - :param group_id: Security group id (int) - :param parent_group_id: Parent security group id (int) - """ - - try: - from_port = int(from_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("From port must be an integer.")) - try: - to_port = int(to_port) - except (TypeError, ValueError): - raise exceptions.CommandError(_("To port must be an integer.")) - if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']: - raise exceptions.CommandError(_("IP protocol must be 'tcp', 'udp'" - ", or 'icmp'.")) - - body = {"security_group_rule": { - "ip_protocol": ip_protocol, - "from_port": from_port, - "to_port": to_port, - "cidr": cidr, - "group_id": group_id, - "parent_group_id": parent_group_id}} - - return self._create('/os-security-group-rules', body, - 'security_group_rule') - - def delete(self, rule): - """ - Delete a security group rule - - :param rule: The security group rule to delete (ID or Class) - """ - self._delete('/os-security-group-rules/%s' % base.getid(rule)) diff --git a/awx/lib/site-packages/novaclient/v2/security_groups.py b/awx/lib/site-packages/novaclient/v2/security_groups.py deleted file mode 100644 index 40d1e7ff72..0000000000 --- a/awx/lib/site-packages/novaclient/v2/security_groups.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Security group interface (1.1 extension). -""" - -import six -from six.moves.urllib import parse - -from novaclient import base - - -class SecurityGroup(base.Resource): - def __str__(self): - return str(self.id) - - def delete(self): - self.manager.delete(self) - - def update(self): - self.manager.update(self) - - -class SecurityGroupManager(base.ManagerWithFind): - resource_class = SecurityGroup - - def create(self, name, description): - """ - Create a security group - - :param name: name for the security group to create - :param description: description of the security group - :rtype: the security group object - """ - body = {"security_group": {"name": name, 'description': description}} - return self._create('/os-security-groups', body, 'security_group') - - def update(self, group, name, description): - """ - Update a security group - - :param group: The security group to update (group or ID) - :param name: name for the security group to update - :param description: description for the security group to update - :rtype: the security group object - """ - body = {"security_group": {"name": name, 'description': description}} - return self._update('/os-security-groups/%s' % base.getid(group), - body, 'security_group') - - def delete(self, group): - """ - Delete a security group - - :param group: The security group to delete (group or ID) - :rtype: None - """ - self._delete('/os-security-groups/%s' % base.getid(group)) - - def get(self, group_id): - """ - Get a security group - - :param group_id: The security group to get by ID - :rtype: :class:`SecurityGroup` - """ - return self._get('/os-security-groups/%s' % group_id, - 'security_group') - - def list(self, search_opts=None): - """ - Get a list of all security_groups - - :rtype: list of :class:`SecurityGroup` - """ - search_opts = search_opts or {} - - qparams = dict((k, v) for (k, v) in six.iteritems(search_opts) if v) - - query_string = '?%s' % parse.urlencode(qparams) if qparams else '' - - return self._list('/os-security-groups%s' % query_string, - 'security_groups') diff --git a/awx/lib/site-packages/novaclient/v2/server_groups.py b/awx/lib/site-packages/novaclient/v2/server_groups.py deleted file mode 100644 index a5205e7726..0000000000 --- a/awx/lib/site-packages/novaclient/v2/server_groups.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2014 VMware, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Server group interface. -""" - -from novaclient import base - - -class ServerGroup(base.Resource): - """ - A server group. - """ - NAME_ATTR = 'server_group_name' - - def __repr__(self): - return '' % self.id - - def delete(self): - self.manager.delete(self.id) - - -class ServerGroupsManager(base.ManagerWithFind): - """ - Manage :class:`ServerGroup` resources. - """ - resource_class = ServerGroup - - def list(self): - """Get a list of all server groups. - - :rtype: list of :class:`ServerGroup`. - """ - return self._list('/os-server-groups', 'server_groups') - - def get(self, id): - """Get a specific server group. - - :param id: The ID of the :class:`ServerGroup` to get. - :rtype: :class:`ServerGroup` - """ - return self._get('/os-server-groups/%s' % id, - 'server_group') - - def delete(self, id): - """Delete a specific server group. - - :param id: The ID of the :class:`ServerGroup` to delete. - """ - self._delete('/os-server-groups/%s' % id) - - def create(self, **kwargs): - """Create (allocate) a server group. - - :rtype: list of :class:`ServerGroup` - """ - body = {'server_group': kwargs} - return self._create('/os-server-groups', body, 'server_group') diff --git a/awx/lib/site-packages/novaclient/v2/servers.py b/awx/lib/site-packages/novaclient/v2/servers.py deleted file mode 100644 index 8055f15092..0000000000 --- a/awx/lib/site-packages/novaclient/v2/servers.py +++ /dev/null @@ -1,1267 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Server interface. -""" - -import base64 - -from oslo.utils import encodeutils -import six -from six.moves.urllib import parse - -from novaclient import base -from novaclient import crypto -from novaclient.i18n import _ -from novaclient.v2 import security_groups - - -REBOOT_SOFT, REBOOT_HARD = 'SOFT', 'HARD' - - -class Server(base.Resource): - HUMAN_ID = True - - def __repr__(self): - return '' % getattr(self, 'name', 'unknown-name') - - def delete(self): - """ - Delete (i.e. shut down and delete the image) this server. - """ - self.manager.delete(self) - - def update(self, name=None): - """ - Update the name for this server. - - :param name: Update the server's name. - """ - self.manager.update(self, name=name) - - def get_console_output(self, length=None): - """ - Get text console log output from Server. - - :param length: The number of lines you would like to retrieve (as int) - """ - return self.manager.get_console_output(self, length) - - def get_vnc_console(self, console_type): - """ - Get vnc console for a Server. - - :param console_type: Type of console ('novnc' or 'xvpvnc') - """ - return self.manager.get_vnc_console(self, console_type) - - def get_spice_console(self, console_type): - """ - Get spice console for a Server. - - :param console_type: Type of console ('spice-html5') - """ - return self.manager.get_spice_console(self, console_type) - - def get_rdp_console(self, console_type): - """ - Get rdp console for a Server. - - :param console_type: Type of console ('rdp-html5') - """ - return self.manager.get_rdp_console(self, console_type) - - def get_serial_console(self, console_type): - """ - Get serial console for a Server. - - :param console_type: Type of console ('serial') - """ - return self.manager.get_serial_console(self, console_type) - - def get_password(self, private_key=None): - """ - Get password for a Server. - - Returns the clear password of an instance if private_key is - provided, returns the ciphered password otherwise. - - :param private_key: Path to private key file for decryption - (optional) - """ - return self.manager.get_password(self, private_key) - - def clear_password(self): - """ - Get password for a Server. - - """ - return self.manager.clear_password(self) - - def add_fixed_ip(self, network_id): - """ - Add an IP address on a network. - - :param network_id: The ID of the network the IP should be on. - """ - self.manager.add_fixed_ip(self, network_id) - - def add_floating_ip(self, address, fixed_address=None): - """ - Add floating IP to an instance - - :param address: The IP address or FloatingIP to add to the instance - :param fixed_address: The fixedIP address the FloatingIP is to be - associated with (optional) - """ - self.manager.add_floating_ip(self, address, fixed_address) - - def remove_floating_ip(self, address): - """ - Remove floating IP from an instance - - :param address: The IP address or FloatingIP to remove - """ - self.manager.remove_floating_ip(self, address) - - def stop(self): - """ - Stop -- Stop the running server. - """ - self.manager.stop(self) - - def force_delete(self): - """ - Force delete -- Force delete a server. - """ - self.manager.force_delete(self) - - def restore(self): - """ - Restore -- Restore a server in 'soft-deleted' state. - """ - self.manager.restore(self) - - def start(self): - """ - Start -- Start the paused server. - """ - self.manager.start(self) - - def pause(self): - """ - Pause -- Pause the running server. - """ - self.manager.pause(self) - - def unpause(self): - """ - Unpause -- Unpause the paused server. - """ - self.manager.unpause(self) - - def lock(self): - """ - Lock -- Lock the instance from certain operations. - """ - self.manager.lock(self) - - def unlock(self): - """ - Unlock -- Remove instance lock. - """ - self.manager.unlock(self) - - def suspend(self): - """ - Suspend -- Suspend the running server. - """ - self.manager.suspend(self) - - def resume(self): - """ - Resume -- Resume the suspended server. - """ - self.manager.resume(self) - - def rescue(self, password=None, image=None): - """ - Rescue -- Rescue the problematic server. - - :param password: The admin password to be set in the rescue instance. - :param image: The :class:`Image` to rescue with. - """ - return self.manager.rescue(self, password, image) - - def unrescue(self): - """ - Unrescue -- Unrescue the rescued server. - """ - self.manager.unrescue(self) - - def shelve(self): - """ - Shelve -- Shelve the server. - """ - self.manager.shelve(self) - - def shelve_offload(self): - """ - Shelve_offload -- Remove a shelved server from the compute node. - """ - self.manager.shelve_offload(self) - - def unshelve(self): - """ - Unshelve -- Unshelve the server. - """ - self.manager.unshelve(self) - - def diagnostics(self): - """Diagnostics -- Retrieve server diagnostics.""" - return self.manager.diagnostics(self) - - def migrate(self): - """ - Migrate a server to a new host. - """ - self.manager.migrate(self) - - def remove_fixed_ip(self, address): - """ - Remove an IP address. - - :param address: The IP address to remove. - """ - self.manager.remove_fixed_ip(self, address) - - def change_password(self, password): - """ - Update the admin password for a server. - - :param password: string to set as the admin password on the server - """ - self.manager.change_password(self, password) - - def reboot(self, reboot_type=REBOOT_SOFT): - """ - Reboot the server. - - :param reboot_type: either :data:`REBOOT_SOFT` for a software-level - reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. - """ - self.manager.reboot(self, reboot_type) - - def rebuild(self, image, password=None, preserve_ephemeral=False, - **kwargs): - """ - Rebuild -- shut down and then re-image -- this server. - - :param image: the :class:`Image` (or its ID) to re-image with. - :param password: string to set as the admin password on the rebuilt - server. - :param preserve_ephemeral: If True, request that any ephemeral device - be preserved when rebuilding the instance. Defaults to False. - """ - return self.manager.rebuild(self, image, password=password, - preserve_ephemeral=preserve_ephemeral, - **kwargs) - - def resize(self, flavor, **kwargs): - """ - Resize the server's resources. - - :param flavor: the :class:`Flavor` (or its ID) to resize to. - - Until a resize event is confirmed with :meth:`confirm_resize`, the old - server will be kept around and you'll be able to roll back to the old - flavor quickly with :meth:`revert_resize`. All resizes are - automatically confirmed after 24 hours. - """ - self.manager.resize(self, flavor, **kwargs) - - def create_image(self, image_name, metadata=None): - """ - Create an image based on this server. - - :param image_name: The name to assign the newly create image. - :param metadata: Metadata to assign to the image. - """ - return self.manager.create_image(self, image_name, metadata) - - def backup(self, backup_name, backup_type, rotation): - """ - Backup a server instance. - - :param backup_name: Name of the backup image - :param backup_type: The backup type, like 'daily' or 'weekly' - :param rotation: Int parameter representing how many backups to - keep around. - """ - self.manager.backup(self, backup_name, backup_type, rotation) - - def confirm_resize(self): - """ - Confirm that the resize worked, thus removing the original server. - """ - self.manager.confirm_resize(self) - - def revert_resize(self): - """ - Revert a previous resize, switching back to the old server. - """ - self.manager.revert_resize(self) - - @property - def networks(self): - """ - Generate a simplified list of addresses - """ - networks = {} - try: - for network_label, address_list in self.addresses.items(): - networks[network_label] = [a['addr'] for a in address_list] - return networks - except Exception: - return {} - - def live_migrate(self, host=None, - block_migration=False, - disk_over_commit=False): - """ - Migrates a running instance to a new machine. - """ - self.manager.live_migrate(self, host, - block_migration, - disk_over_commit) - - def reset_state(self, state='error'): - """ - Reset the state of an instance to active or error. - """ - self.manager.reset_state(self, state) - - def reset_network(self): - """ - Reset network of an instance. - """ - self.manager.reset_network(self) - - def add_security_group(self, security_group): - """ - Add a security group to an instance. - """ - self.manager.add_security_group(self, security_group) - - def remove_security_group(self, security_group): - """ - Remove a security group from an instance. - """ - self.manager.remove_security_group(self, security_group) - - def list_security_group(self): - """ - List security group(s) of an instance. - """ - return self.manager.list_security_group(self) - - def evacuate(self, host=None, on_shared_storage=True, password=None): - """ - Evacuate an instance from failed host to specified host. - - :param host: Name of the target host - :param on_shared_storage: Specifies whether instance files located - on shared storage - :param password: string to set as admin password on the evacuated - server. - """ - return self.manager.evacuate(self, host, on_shared_storage, password) - - def interface_list(self): - """ - List interfaces attached to an instance. - """ - return self.manager.interface_list(self) - - def interface_attach(self, port_id, net_id, fixed_ip): - """ - Attach a network interface to an instance. - """ - return self.manager.interface_attach(self, port_id, net_id, fixed_ip) - - def interface_detach(self, port_id): - """ - Detach a network interface from an instance. - """ - return self.manager.interface_detach(self, port_id) - - -class ServerManager(base.BootingManagerWithFind): - resource_class = Server - - def _boot(self, resource_url, response_key, name, image, flavor, - meta=None, files=None, userdata=None, - reservation_id=None, return_raw=False, min_count=None, - max_count=None, security_groups=None, key_name=None, - availability_zone=None, block_device_mapping=None, - block_device_mapping_v2=None, nics=None, scheduler_hints=None, - config_drive=None, admin_pass=None, disk_config=None, **kwargs): - """ - Create (boot) a new server. - - :param name: Something to name the server. - :param image: The :class:`Image` to boot with. - :param flavor: The :class:`Flavor` to boot onto. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param files: A dict of files to overwrite on the server upon boot. - Keys are file names (i.e. ``/etc/passwd``) and values - are the file contents (either as a string or as a - file-like object). A maximum of five entries is allowed, - and each file must be 10k or less. - :param reservation_id: a UUID for the set of servers being requested. - :param return_raw: If True, don't try to coerce the result into - a Resource object. - :param security_groups: list of security group names - :param key_name: (optional extension) name of keypair to inject into - the instance - :param availability_zone: Name of the availability zone for instance - placement. - :param block_device_mapping: A dict of block device mappings for this - server. - :param block_device_mapping_v2: A dict of block device mappings V2 for - this server. - :param nics: (optional extension) an ordered list of nics to be - added to this server, with information about - connected networks, fixed IPs, etc. - :param scheduler_hints: (optional extension) arbitrary key-value pairs - specified by the client to help boot an instance. - :param config_drive: (optional extension) If True, enable config drive - on the server. - :param admin_pass: admin password for the server. - :param disk_config: (optional extension) control how the disk is - partitioned when the server is created. - """ - body = {"server": { - "name": name, - "imageRef": str(base.getid(image)) if image else '', - "flavorRef": str(base.getid(flavor)), - }} - if userdata: - if hasattr(userdata, 'read'): - userdata = userdata.read() - - if six.PY3: - userdata = userdata.encode("utf-8") - else: - userdata = encodeutils.safe_encode(userdata) - - userdata_b64 = base64.b64encode(userdata).decode('utf-8') - body["server"]["user_data"] = userdata_b64 - if meta: - body["server"]["metadata"] = meta - if reservation_id: - body["server"]["reservation_id"] = reservation_id - if key_name: - body["server"]["key_name"] = key_name - if scheduler_hints: - body['os:scheduler_hints'] = scheduler_hints - if config_drive: - body["server"]["config_drive"] = config_drive - if admin_pass: - body["server"]["adminPass"] = admin_pass - if not min_count: - min_count = 1 - if not max_count: - max_count = min_count - body["server"]["min_count"] = min_count - body["server"]["max_count"] = max_count - - if security_groups: - body["server"]["security_groups"] = [{'name': sg} - for sg in security_groups] - - # Files are a slight bit tricky. They're passed in a "personality" - # list to the POST. Each item is a dict giving a file name and the - # base64-encoded contents of the file. We want to allow passing - # either an open file *or* some contents as files here. - if files: - personality = body['server']['personality'] = [] - for filepath, file_or_string in sorted(files.items(), - key=lambda x: x[0]): - if hasattr(file_or_string, 'read'): - data = file_or_string.read() - else: - data = file_or_string - - if six.PY3 and isinstance(data, str): - data = data.encode('utf-8') - cont = base64.b64encode(data).decode('utf-8') - personality.append({ - 'path': filepath, - 'contents': cont, - }) - - if availability_zone: - body["server"]["availability_zone"] = availability_zone - - # Block device mappings are passed as a list of dictionaries - if block_device_mapping: - body['server']['block_device_mapping'] = \ - self._parse_block_device_mapping(block_device_mapping) - elif block_device_mapping_v2: - body['server']['block_device_mapping_v2'] = block_device_mapping_v2 - - if nics is not None: - # NOTE(tr3buchet): nics can be an empty list - all_net_data = [] - for nic_info in nics: - net_data = {} - # if value is empty string, do not send value in body - if nic_info.get('net-id'): - net_data['uuid'] = nic_info['net-id'] - if (nic_info.get('v4-fixed-ip') and - nic_info.get('v6-fixed-ip')): - raise base.exceptions.CommandError(_( - "Only one of 'v4-fixed-ip' and 'v6-fixed-ip' may be" - " provided.")) - elif nic_info.get('v4-fixed-ip'): - net_data['fixed_ip'] = nic_info['v4-fixed-ip'] - elif nic_info.get('v6-fixed-ip'): - net_data['fixed_ip'] = nic_info['v6-fixed-ip'] - if nic_info.get('port-id'): - net_data['port'] = nic_info['port-id'] - all_net_data.append(net_data) - body['server']['networks'] = all_net_data - - if disk_config is not None: - body['server']['OS-DCF:diskConfig'] = disk_config - - return self._create(resource_url, body, response_key, - return_raw=return_raw, **kwargs) - - def get(self, server): - """ - Get a server. - - :param server: ID of the :class:`Server` to get. - :rtype: :class:`Server` - """ - return self._get("/servers/%s" % base.getid(server), "server") - - def list(self, detailed=True, search_opts=None, marker=None, limit=None, - sort_keys=None, sort_dirs=None): - """ - Get a list of servers. - - :param detailed: Whether to return detailed server info (optional). - :param search_opts: Search options to filter out servers (optional). - :param marker: Begin returning servers that appear later in the server - list than that represented by this server id (optional). - :param limit: Maximum number of servers to return (optional). - :param sort_keys: List of sort keys - :param sort_dirs: List of sort directions - - :rtype: list of :class:`Server` - """ - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - if qparams or sort_keys or sort_dirs: - # sort keys and directions are unique since the same parameter - # key is repeated for each associated value - # (ie, &sort_key=key1&sort_key=key2&sort_key=key3) - items = list(qparams.items()) - if sort_keys: - items.extend(('sort_key', sort_key) for sort_key in sort_keys) - if sort_dirs: - items.extend(('sort_dir', sort_dir) for sort_dir in sort_dirs) - new_qparams = sorted(items, key=lambda x: x[0]) - query_string = "?%s" % parse.urlencode(new_qparams) - else: - query_string = "" - - detail = "" - if detailed: - detail = "/detail" - return self._list("/servers%s%s" % (detail, query_string), "servers") - - def add_fixed_ip(self, server, network_id): - """ - Add an IP address on a network. - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param network_id: The ID of the network the IP should be on. - """ - self._action('addFixedIp', server, {'networkId': network_id}) - - def remove_fixed_ip(self, server, address): - """ - Remove an IP address. - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param address: The IP address to remove. - """ - self._action('removeFixedIp', server, {'address': address}) - - def add_floating_ip(self, server, address, fixed_address=None): - """ - Add a floating IP to an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param address: The FloatingIP or string floating address to add. - :param fixed_address: The FixedIP the floatingIP should be - associated with (optional) - """ - - address = address.ip if hasattr(address, 'ip') else address - if fixed_address: - if hasattr(fixed_address, 'ip'): - fixed_address = fixed_address.ip - self._action('addFloatingIp', server, - {'address': address, 'fixed_address': fixed_address}) - else: - self._action('addFloatingIp', server, {'address': address}) - - def remove_floating_ip(self, server, address): - """ - Remove a floating IP address. - - :param server: The :class:`Server` (or its ID) to remove an IP from. - :param address: The FloatingIP or string floating address to remove. - """ - - address = address.ip if hasattr(address, 'ip') else address - self._action('removeFloatingIp', server, {'address': address}) - - def get_vnc_console(self, server, console_type): - """ - Get a vnc console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of vnc console to get ('novnc' or 'xvpvnc') - """ - - return self._action('os-getVNCConsole', server, - {'type': console_type})[1] - - def get_spice_console(self, server, console_type): - """ - Get a spice console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of spice console to get ('spice-html5') - """ - - return self._action('os-getSPICEConsole', server, - {'type': console_type})[1] - - def get_rdp_console(self, server, console_type): - """ - Get a rdp console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of rdp console to get ('rdp-html5') - """ - - return self._action('os-getRDPConsole', server, - {'type': console_type})[1] - - def get_serial_console(self, server, console_type): - """ - Get a serial console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of serial console to get ('serial') - """ - - return self._action('os-getSerialConsole', server, - {'type': console_type})[1] - - def get_password(self, server, private_key=None): - """ - Get admin password of an instance - - Returns the admin password of an instance in the clear if private_key - is provided, returns the ciphered password otherwise. - - Requires that openssl is installed and in the path - - :param server: The :class:`Server` (or its ID) for which the admin - password is to be returned - :param private_key: The private key to decrypt password - (optional) - """ - - _resp, body = self.api.client.get("/servers/%s/os-server-password" - % base.getid(server)) - ciphered_pw = body.get('password', '') if body else '' - if private_key and ciphered_pw: - try: - return crypto.decrypt_password(private_key, ciphered_pw) - except Exception as exc: - return '%sFailed to decrypt:\n%s' % (exc, ciphered_pw) - return ciphered_pw - - def clear_password(self, server): - """ - Clear the admin password of an instance - - Remove the admin password for an instance from the metadata server. - - :param server: The :class:`Server` (or its ID) for which the admin - password is to be cleared - """ - - return self._delete("/servers/%s/os-server-password" - % base.getid(server)) - - def stop(self, server): - """ - Stop the server. - """ - return self._action('os-stop', server, None) - - def force_delete(self, server): - """ - Force delete the server. - """ - return self._action('forceDelete', server, None) - - def restore(self, server): - """ - Restore soft-deleted server. - """ - return self._action('restore', server, None) - - def start(self, server): - """ - Start the server. - """ - self._action('os-start', server, None) - - def pause(self, server): - """ - Pause the server. - """ - self._action('pause', server, None) - - def unpause(self, server): - """ - Unpause the server. - """ - self._action('unpause', server, None) - - def lock(self, server): - """ - Lock the server. - """ - self._action('lock', server, None) - - def unlock(self, server): - """ - Unlock the server. - """ - self._action('unlock', server, None) - - def suspend(self, server): - """ - Suspend the server. - """ - self._action('suspend', server, None) - - def resume(self, server): - """ - Resume the server. - """ - self._action('resume', server, None) - - def rescue(self, server, password=None, image=None): - """ - Rescue the server. - - :param server: The :class:`Server` to rescue. - :param password: The admin password to be set in the rescue instance. - :param image: The :class:`Image` to rescue with. - """ - info = {} - if password: - info['adminPass'] = password - if image: - info['rescue_image_ref'] = base.getid(image) - return self._action('rescue', server, info or None) - - def unrescue(self, server): - """ - Unrescue the server. - """ - self._action('unrescue', server, None) - - def shelve(self, server): - """ - Shelve the server. - """ - self._action('shelve', server, None) - - def shelve_offload(self, server): - """ - Remove a shelved instance from the compute node. - """ - self._action('shelveOffload', server, None) - - def unshelve(self, server): - """ - Unshelve the server. - """ - self._action('unshelve', server, None) - - def diagnostics(self, server): - """Retrieve server diagnostics.""" - return self.api.client.get("/servers/%s/diagnostics" % - base.getid(server)) - - def create(self, name, image, flavor, meta=None, files=None, - reservation_id=None, min_count=None, - max_count=None, security_groups=None, userdata=None, - key_name=None, availability_zone=None, - block_device_mapping=None, block_device_mapping_v2=None, - nics=None, scheduler_hints=None, - config_drive=None, disk_config=None, **kwargs): - # TODO(anthony): indicate in doc string if param is an extension - # and/or optional - """ - Create (boot) a new server. - - :param name: Something to name the server. - :param image: The :class:`Image` to boot with. - :param flavor: The :class:`Flavor` to boot onto. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param files: A dict of files to overrwrite on the server upon boot. - Keys are file names (i.e. ``/etc/passwd``) and values - are the file contents (either as a string or as a - file-like object). A maximum of five entries is allowed, - and each file must be 10k or less. - :param userdata: user data to pass to be exposed by the metadata - server this can be a file type object as well or a - string. - :param reservation_id: a UUID for the set of servers being requested. - :param key_name: (optional extension) name of previously created - keypair to inject into the instance. - :param availability_zone: Name of the availability zone for instance - placement. - :param block_device_mapping: (optional extension) A dict of block - device mappings for this server. - :param block_device_mapping_v2: (optional extension) A dict of block - device mappings for this server. - :param nics: (optional extension) an ordered list of nics to be - added to this server, with information about - connected networks, fixed IPs, port etc. - :param scheduler_hints: (optional extension) arbitrary key-value pairs - specified by the client to help boot an instance - :param config_drive: (optional extension) value for config drive - either boolean, or volume-id - :param disk_config: (optional extension) control how the disk is - partitioned when the server is created. possible - values are 'AUTO' or 'MANUAL'. - """ - if not min_count: - min_count = 1 - if not max_count: - max_count = min_count - if min_count > max_count: - min_count = max_count - - boot_args = [name, image, flavor] - - boot_kwargs = dict( - meta=meta, files=files, userdata=userdata, - reservation_id=reservation_id, min_count=min_count, - max_count=max_count, security_groups=security_groups, - key_name=key_name, availability_zone=availability_zone, - scheduler_hints=scheduler_hints, config_drive=config_drive, - disk_config=disk_config, **kwargs) - - if block_device_mapping: - resource_url = "/os-volumes_boot" - boot_kwargs['block_device_mapping'] = block_device_mapping - elif block_device_mapping_v2: - resource_url = "/os-volumes_boot" - boot_kwargs['block_device_mapping_v2'] = block_device_mapping_v2 - else: - resource_url = "/servers" - if nics: - boot_kwargs['nics'] = nics - - response_key = "server" - return self._boot(resource_url, response_key, *boot_args, - **boot_kwargs) - - def update(self, server, name=None): - """ - Update the name or the password for a server. - - :param server: The :class:`Server` (or its ID) to update. - :param name: Update the server's name. - """ - if name is None: - return - - body = { - "server": { - "name": name, - }, - } - - return self._update("/servers/%s" % base.getid(server), body, "server") - - def change_password(self, server, password): - """ - Update the password for a server. - """ - self._action("changePassword", server, {"adminPass": password}) - - def delete(self, server): - """ - Delete (i.e. shut down and delete the image) this server. - """ - self._delete("/servers/%s" % base.getid(server)) - - def reboot(self, server, reboot_type=REBOOT_SOFT): - """ - Reboot a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param reboot_type: either :data:`REBOOT_SOFT` for a software-level - reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. - """ - self._action('reboot', server, {'type': reboot_type}) - - def rebuild(self, server, image, password=None, disk_config=None, - preserve_ephemeral=False, name=None, meta=None, files=None, - **kwargs): - """ - Rebuild -- shut down and then re-image -- a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param image: the :class:`Image` (or its ID) to re-image with. - :param password: string to set as password on the rebuilt server. - :param disk_config: partitioning mode to use on the rebuilt server. - Valid values are 'AUTO' or 'MANUAL' - :param preserve_ephemeral: If True, request that any ephemeral device - be preserved when rebuilding the instance. Defaults to False. - :param name: Something to name the server. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param files: A dict of files to overwrite on the server upon boot. - Keys are file names (i.e. ``/etc/passwd``) and values - are the file contents (either as a string or as a - file-like object). A maximum of five entries is allowed, - and each file must be 10k or less. - """ - body = {'imageRef': base.getid(image)} - if password is not None: - body['adminPass'] = password - if disk_config is not None: - body['OS-DCF:diskConfig'] = disk_config - if preserve_ephemeral is not False: - body['preserve_ephemeral'] = True - if name is not None: - body['name'] = name - if meta: - body['metadata'] = meta - if files: - personality = body['personality'] = [] - for filepath, file_or_string in sorted(files.items(), - key=lambda x: x[0]): - if hasattr(file_or_string, 'read'): - data = file_or_string.read() - else: - data = file_or_string - - cont = base64.b64encode(data.encode('utf-8')).decode('utf-8') - personality.append({ - 'path': filepath, - 'contents': cont, - }) - - _resp, body = self._action('rebuild', server, body, **kwargs) - return Server(self, body['server']) - - def migrate(self, server): - """ - Migrate a server to a new host. - - :param server: The :class:`Server` (or its ID). - """ - self._action('migrate', server) - - def resize(self, server, flavor, disk_config=None, **kwargs): - """ - Resize a server's resources. - - :param server: The :class:`Server` (or its ID) to share onto. - :param flavor: the :class:`Flavor` (or its ID) to resize to. - :param disk_config: partitioning mode to use on the rebuilt server. - Valid values are 'AUTO' or 'MANUAL' - - Until a resize event is confirmed with :meth:`confirm_resize`, the old - server will be kept around and you'll be able to roll back to the old - flavor quickly with :meth:`revert_resize`. All resizes are - automatically confirmed after 24 hours. - """ - info = {'flavorRef': base.getid(flavor)} - if disk_config is not None: - info['OS-DCF:diskConfig'] = disk_config - - self._action('resize', server, info=info, **kwargs) - - def confirm_resize(self, server): - """ - Confirm that the resize worked, thus removing the original server. - - :param server: The :class:`Server` (or its ID) to share onto. - """ - self._action('confirmResize', server) - - def revert_resize(self, server): - """ - Revert a previous resize, switching back to the old server. - - :param server: The :class:`Server` (or its ID) to share onto. - """ - self._action('revertResize', server) - - def create_image(self, server, image_name, metadata=None): - """ - Snapshot a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param image_name: Name to give the snapshot image - :param metadata: Metadata to give newly-created image entity - """ - body = {'name': image_name, 'metadata': metadata or {}} - resp = self._action('createImage', server, body)[0] - location = resp.headers['location'] - image_uuid = location.split('/')[-1] - return image_uuid - - def backup(self, server, backup_name, backup_type, rotation): - """ - Backup a server instance. - - :param server: The :class:`Server` (or its ID) to share onto. - :param backup_name: Name of the backup image - :param backup_type: The backup type, like 'daily' or 'weekly' - :param rotation: Int parameter representing how many backups to - keep around. - """ - body = {'name': backup_name, - 'backup_type': backup_type, - 'rotation': rotation} - self._action('createBackup', server, body) - - def set_meta(self, server, metadata): - """ - Set a servers metadata - :param server: The :class:`Server` to add metadata to - :param metadata: A dict of metadata to add to the server - """ - body = {'metadata': metadata} - return self._create("/servers/%s/metadata" % base.getid(server), - body, "metadata") - - def set_meta_item(self, server, key, value): - """ - Updates an item of server metadata - :param server: The :class:`Server` to add metadata to - :param key: metadata key to update - :param value: string value - """ - body = {'meta': {key: value}} - return self._update("/servers/%s/metadata/%s" % - (base.getid(server), key), body) - - def get_console_output(self, server, length=None): - """ - Get text console log output from Server. - - :param server: The :class:`Server` (or its ID) whose console output - you would like to retrieve. - :param length: The number of tail loglines you would like to retrieve. - """ - return self._action('os-getConsoleOutput', - server, - {'length': length})[1]['output'] - - def delete_meta(self, server, keys): - """ - Delete metadata from an server - :param server: The :class:`Server` to add metadata to - :param keys: A list of metadata keys to delete from the server - """ - for k in keys: - self._delete("/servers/%s/metadata/%s" % (base.getid(server), k)) - - def live_migrate(self, server, host, block_migration, disk_over_commit): - """ - Migrates a running instance to a new machine. - - :param server: instance id which comes from nova list. - :param host: destination host name. - :param block_migration: if True, do block_migration. - :param disk_over_commit: if True, Allow overcommit. - - """ - self._action('os-migrateLive', server, - {'host': host, - 'block_migration': block_migration, - 'disk_over_commit': disk_over_commit}) - - def reset_state(self, server, state='error'): - """ - Reset the state of an instance to active or error. - - :param server: ID of the instance to reset the state of. - :param state: Desired state; either 'active' or 'error'. - Defaults to 'error'. - """ - self._action('os-resetState', server, dict(state=state)) - - def reset_network(self, server): - """ - Reset network of an instance. - """ - self._action('resetNetwork', server) - - def add_security_group(self, server, security_group): - """ - Add a Security Group to an instance - - :param server: ID of the instance. - :param security_group: The name of security group to add. - - """ - self._action('addSecurityGroup', server, {'name': security_group}) - - def remove_security_group(self, server, security_group): - """ - Add a Security Group to an instance - - :param server: ID of the instance. - :param security_group: The name of security group to remove. - - """ - self._action('removeSecurityGroup', server, {'name': security_group}) - - def list_security_group(self, server): - """ - List Security Group(s) of an instance - - :param server: ID of the instance. - - """ - return self._list('/servers/%s/os-security-groups' % - base.getid(server), 'security_groups', - security_groups.SecurityGroup) - - def evacuate(self, server, host=None, on_shared_storage=True, - password=None): - """ - Evacuate a server instance. - - :param server: The :class:`Server` (or its ID) to share onto. - :param host: Name of the target host. - :param on_shared_storage: Specifies whether instance files located - on shared storage - :param password: string to set as password on the evacuated server. - """ - - body = {'onSharedStorage': on_shared_storage} - if host is not None: - body['host'] = host - - if password is not None: - body['adminPass'] = password - - return self._action('evacuate', server, body) - - def interface_list(self, server): - """ - List attached network interfaces - - :param server: The :class:`Server` (or its ID) to query. - """ - return self._list('/servers/%s/os-interface' % base.getid(server), - 'interfaceAttachments') - - def interface_attach(self, server, port_id, net_id, fixed_ip): - """ - Attach a network_interface to an instance. - - :param server: The :class:`Server` (or its ID) to attach to. - :param port_id: The port to attach. - """ - - body = {'interfaceAttachment': {}} - if port_id: - body['interfaceAttachment']['port_id'] = port_id - if net_id: - body['interfaceAttachment']['net_id'] = net_id - if fixed_ip: - body['interfaceAttachment']['fixed_ips'] = [ - {'ip_address': fixed_ip}] - - return self._create('/servers/%s/os-interface' % base.getid(server), - body, 'interfaceAttachment') - - def interface_detach(self, server, port_id): - """ - Detach a network_interface from an instance. - - :param server: The :class:`Server` (or its ID) to detach from. - :param port_id: The port to detach. - """ - self._delete('/servers/%s/os-interface/%s' % (base.getid(server), - port_id)) - - def _action(self, action, server, info=None, **kwargs): - """ - Perform a server "action" -- reboot/rebuild/resize/etc. - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/servers/%s/action' % base.getid(server) - return self.api.client.post(url, body=body) diff --git a/awx/lib/site-packages/novaclient/v2/services.py b/awx/lib/site-packages/novaclient/v2/services.py deleted file mode 100644 index d51fa3ebfd..0000000000 --- a/awx/lib/site-packages/novaclient/v2/services.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -service interface -""" -from novaclient import base - - -class Service(base.Resource): - def __repr__(self): - return "" % self.binary - - def _add_details(self, info): - dico = 'resource' in info and info['resource'] or info - for (k, v) in dico.items(): - setattr(self, k, v) - - -class ServiceManager(base.ManagerWithFind): - resource_class = Service - - def list(self, host=None, binary=None): - """ - Describes cpu/memory/hdd info for host. - - :param host: destination host name. - """ - url = "/os-services" - filters = [] - if host: - filters.append("host=%s" % host) - if binary: - filters.append("binary=%s" % binary) - if filters: - url = "%s?%s" % (url, "&".join(filters)) - return self._list(url, "services") - - def _update_body(self, host, binary, disabled_reason=None): - body = {"host": host, - "binary": binary} - if disabled_reason is not None: - body["disabled_reason"] = disabled_reason - return body - - def enable(self, host, binary): - """Enable the service specified by hostname and binary.""" - body = self._update_body(host, binary) - return self._update("/os-services/enable", body, "service") - - def disable(self, host, binary): - """Disable the service specified by hostname and binary.""" - body = self._update_body(host, binary) - return self._update("/os-services/disable", body, "service") - - def disable_log_reason(self, host, binary, reason): - """Disable the service with reason.""" - body = self._update_body(host, binary, reason) - return self._update("/os-services/disable-log-reason", body, "service") - - def delete(self, service_id): - """Delete a service.""" - return self._delete("/os-services/%s" % service_id) diff --git a/awx/lib/site-packages/novaclient/v2/shell.py b/awx/lib/site-packages/novaclient/v2/shell.py deleted file mode 100644 index f030e768a0..0000000000 --- a/awx/lib/site-packages/novaclient/v2/shell.py +++ /dev/null @@ -1,4452 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import argparse -import copy -import datetime -import getpass -import locale -import logging -import os -import sys -import time - -from oslo.utils import encodeutils -from oslo.utils import strutils -from oslo.utils import timeutils -import six - -from novaclient import client -from novaclient import exceptions -from novaclient.i18n import _ -from novaclient.openstack.common import cliutils -from novaclient.openstack.common import uuidutils -from novaclient import utils -from novaclient.v2 import availability_zones -from novaclient.v2 import quotas -from novaclient.v2 import servers - - -logger = logging.getLogger(__name__) - - -CLIENT_BDM2_KEYS = { - 'id': 'uuid', - 'source': 'source_type', - 'dest': 'destination_type', - 'bus': 'disk_bus', - 'device': 'device_name', - 'size': 'volume_size', - 'format': 'guest_format', - 'bootindex': 'boot_index', - 'type': 'device_type', - 'shutdown': 'delete_on_termination', -} - - -def _key_value_pairing(text): - try: - (k, v) = text.split('=', 1) - return (k, v) - except ValueError: - msg = "%r is not in the format of key=value" % text - raise argparse.ArgumentTypeError(msg) - - -def _match_image(cs, wanted_properties): - image_list = cs.images.list() - images_matched = [] - match = set(wanted_properties) - for img in image_list: - try: - if match == match.intersection(set(img.metadata.items())): - images_matched.append(img) - except AttributeError: - pass - return images_matched - - -def _parse_block_device_mapping_v2(args, image): - bdm = [] - - if args.boot_volume: - bdm_dict = {'uuid': args.boot_volume, 'source_type': 'volume', - 'destination_type': 'volume', 'boot_index': 0, - 'delete_on_termination': False} - bdm.append(bdm_dict) - - if args.snapshot: - bdm_dict = {'uuid': args.snapshot, 'source_type': 'snapshot', - 'destination_type': 'volume', 'boot_index': 0, - 'delete_on_termination': False} - bdm.append(bdm_dict) - - for device_spec in args.block_device: - spec_dict = dict(v.split('=') for v in device_spec.split(',')) - bdm_dict = {} - - for key, value in six.iteritems(spec_dict): - bdm_dict[CLIENT_BDM2_KEYS[key]] = value - - # Convert the delete_on_termination to a boolean or set it to true by - # default for local block devices when not specified. - if 'delete_on_termination' in bdm_dict: - action = bdm_dict['delete_on_termination'] - bdm_dict['delete_on_termination'] = (action == 'remove') - elif bdm_dict.get('destination_type') == 'local': - bdm_dict['delete_on_termination'] = True - - bdm.append(bdm_dict) - - for ephemeral_spec in args.ephemeral: - bdm_dict = {'source_type': 'blank', 'destination_type': 'local', - 'boot_index': -1, 'delete_on_termination': True} - - eph_dict = dict(v.split('=') for v in ephemeral_spec.split(',')) - if 'size' in eph_dict: - bdm_dict['volume_size'] = eph_dict['size'] - if 'format' in eph_dict: - bdm_dict['guest_format'] = eph_dict['format'] - - bdm.append(bdm_dict) - - if args.swap: - bdm_dict = {'source_type': 'blank', 'destination_type': 'local', - 'boot_index': -1, 'delete_on_termination': True, - 'guest_format': 'swap', 'volume_size': args.swap} - bdm.append(bdm_dict) - - return bdm - - -def _boot(cs, args): - """Boot a new server.""" - if args.image: - image = _find_image(cs, args.image) - else: - image = None - - if not image and args.image_with: - images = _match_image(cs, args.image_with) - if images: - # TODO(harlowja): log a warning that we - # are selecting the first of many? - image = images[0] - - if not args.flavor: - raise exceptions.CommandError(_("you need to specify a Flavor ID ")) - - min_count = 1 - max_count = 1 - # Don't let user mix num_instances and max_count/min_count. - if (args.num_instances is not None and - args.min_count is None and - args.max_count is None): - if args.num_instances < 1: - raise exceptions.CommandError(_("num_instances should be >= 1")) - max_count = args.num_instances - elif (args.num_instances is not None and - (args.min_count is not None or args.max_count is not None)): - raise exceptions.CommandError(_("Don't mix num-instances and " - "max/min-count")) - if args.min_count is not None: - if args.min_count < 1: - raise exceptions.CommandError(_("min_count should be >= 1")) - min_count = args.min_count - max_count = min_count - if args.max_count is not None: - if args.max_count < 1: - raise exceptions.CommandError(_("max_count should be >= 1")) - max_count = args.max_count - if (args.min_count is not None and - args.max_count is not None and - args.min_count > args.max_count): - raise exceptions.CommandError(_("min_count should be <= max_count")) - - flavor = _find_flavor(cs, args.flavor) - - meta = dict(v.split('=', 1) for v in args.meta) - - files = {} - for f in args.files: - try: - dst, src = f.split('=', 1) - files[dst] = open(src) - except IOError as e: - raise exceptions.CommandError(_("Can't open '%(src)s': %(exc)s") % - {'src': src, 'exc': e}) - except ValueError: - raise exceptions.CommandError(_("Invalid file argument '%s'. " - "File arguments must be of the " - "form '--file " - "'") % f) - - # use the os-keypair extension - key_name = None - if args.key_name is not None: - key_name = args.key_name - - if args.user_data: - try: - userdata = open(args.user_data) - except IOError as e: - raise exceptions.CommandError(_("Can't open '%(user_data)s': " - "%(exc)s") % - {'user_data': args.user_data, - 'exc': e}) - else: - userdata = None - - if args.availability_zone: - availability_zone = args.availability_zone - else: - availability_zone = None - - if args.security_groups: - security_groups = args.security_groups.split(',') - else: - security_groups = None - - block_device_mapping = {} - for bdm in args.block_device_mapping: - device_name, mapping = bdm.split('=', 1) - block_device_mapping[device_name] = mapping - - block_device_mapping_v2 = _parse_block_device_mapping_v2(args, image) - - n_boot_args = len(list(filter( - bool, (image, args.boot_volume, args.snapshot)))) - have_bdm = block_device_mapping_v2 or block_device_mapping - - # Fail if more than one boot devices are present - # or if there is no device to boot from. - if n_boot_args > 1 or n_boot_args == 0 and not have_bdm: - raise exceptions.CommandError( - _("you need to specify at least one source ID (Image, Snapshot, " - "or Volume), a block device mapping or provide a set of " - "properties to match against an image")) - - if block_device_mapping and block_device_mapping_v2: - raise exceptions.CommandError( - _("you can't mix old block devices (--block-device-mapping) " - "with the new ones (--block-device, --boot-volume, --snapshot, " - "--ephemeral, --swap)")) - - nics = [] - for nic_str in args.nics: - err_msg = (_("Invalid nic argument '%s'. Nic arguments must be of " - "the form --nic , with at minimum " - "net-id or port-id (but not both) specified.") % nic_str) - nic_info = {"net-id": "", "v4-fixed-ip": "", "v6-fixed-ip": "", - "port-id": ""} - - for kv_str in nic_str.split(","): - try: - k, v = kv_str.split("=", 1) - except ValueError: - raise exceptions.CommandError(err_msg) - - if k in nic_info: - nic_info[k] = v - else: - raise exceptions.CommandError(err_msg) - - if bool(nic_info['net-id']) == bool(nic_info['port-id']): - raise exceptions.CommandError(err_msg) - - nics.append(nic_info) - - hints = {} - if args.scheduler_hints: - for hint in args.scheduler_hints: - key, _sep, value = hint.partition('=') - # NOTE(vish): multiple copies of the same hint will - # result in a list of values - if key in hints: - if isinstance(hints[key], six.string_types): - hints[key] = [hints[key]] - hints[key] += [value] - else: - hints[key] = value - boot_args = [args.name, image, flavor] - - if str(args.config_drive).lower() in ("true", "1"): - config_drive = True - elif str(args.config_drive).lower() in ("false", "0", "", "none"): - config_drive = None - else: - config_drive = args.config_drive - - boot_kwargs = dict( - meta=meta, - files=files, - key_name=key_name, - min_count=min_count, - max_count=max_count, - userdata=userdata, - availability_zone=availability_zone, - security_groups=security_groups, - block_device_mapping=block_device_mapping, - block_device_mapping_v2=block_device_mapping_v2, - nics=nics, - scheduler_hints=hints, - config_drive=config_drive) - - return boot_args, boot_kwargs - - -@cliutils.arg( - '--flavor', - default=None, - metavar='', - help=_("Name or ID of flavor (see 'nova flavor-list').")) -@cliutils.arg( - '--image', - default=None, - metavar='', - help=_("Name or ID of image (see 'nova image-list'). ")) -@cliutils.arg( - '--image-with', - default=[], - type=_key_value_pairing, - action='append', - metavar='', - help=_("Image metadata property (see 'nova image-show'). ")) -@cliutils.arg( - '--boot-volume', - default=None, - metavar="", - help=_("Volume ID to boot from.")) -@cliutils.arg( - '--snapshot', - default=None, - metavar="", - help=_("Snapshot ID to boot from (will create a volume).")) -@cliutils.arg( - '--num-instances', - default=None, - type=int, - metavar='', - help=argparse.SUPPRESS) -@cliutils.arg( - '--min-count', - default=None, - type=int, - metavar='', - help=_("Boot at least servers (limited by quota).")) -@cliutils.arg( - '--max-count', - default=None, - type=int, - metavar='', - help=_("Boot up to servers (limited by quota).")) -@cliutils.arg( - '--meta', - metavar="", - action='append', - default=[], - help=_("Record arbitrary key/value metadata to /meta_data.json " - "on the metadata server. Can be specified multiple times.")) -@cliutils.arg( - '--file', - metavar="", - action='append', - dest='files', - default=[], - help=_("Store arbitrary files from locally to " - "on the new server. You may store up to 5 files.")) -@cliutils.arg( - '--key-name', - default=os.environ.get('NOVACLIENT_DEFAULT_KEY_NAME'), - metavar='', - help=_("Key name of keypair that should be created earlier with \ - the command keypair-add")) -@cliutils.arg( - '--key_name', - help=argparse.SUPPRESS) -@cliutils.arg('name', metavar='', help=_('Name for the new server')) -@cliutils.arg( - '--user-data', - default=None, - metavar='', - help=_("user data file to pass to be exposed by the metadata server.")) -@cliutils.arg( - '--user_data', - help=argparse.SUPPRESS) -@cliutils.arg( - '--availability-zone', - default=None, - metavar='', - help=_("The availability zone for server placement.")) -@cliutils.arg( - '--availability_zone', - help=argparse.SUPPRESS) -@cliutils.arg( - '--security-groups', - default=None, - metavar='', - help=_("Comma separated list of security group names.")) -@cliutils.arg( - '--security_groups', - help=argparse.SUPPRESS) -@cliutils.arg( - '--block-device-mapping', - metavar="", - action='append', - default=[], - help=_("Block device mapping in the format " - "=:::.")) -@cliutils.arg( - '--block_device_mapping', - action='append', - help=argparse.SUPPRESS) -@cliutils.arg( - '--block-device', - metavar="key1=value1[,key2=value2...]", - action='append', - default=[], - help=_("Block device mapping with the keys: " - "id=UUID (image_id, snapshot_id or volume_id only if using source " - "image, snapshot or volume) " - "source=source type (image, snapshot, volume or blank), " - "dest=destination type of the block device (volume or local), " - "bus=device's bus (e.g. uml, lxc, virtio, ...; if omitted, " - "hypervisor driver chooses a suitable default, " - "honoured only if device type is supplied) " - "type=device type (e.g. disk, cdrom, ...; defaults to 'disk') " - "device=name of the device (e.g. vda, xda, ...; " - "if omitted, hypervisor driver chooses suitable device " - "depending on selected bus), " - "size=size of the block device in GB (if omitted, " - "hypervisor driver calculates size), " - "format=device will be formatted (e.g. swap, ntfs, ...; optional), " - "bootindex=integer used for ordering the boot disks " - "(for image backed instances it is equal to 0, " - "for others need to be specified) and " - "shutdown=shutdown behaviour (either preserve or remove, " - "for local destination set to remove).")) -@cliutils.arg( - '--swap', - metavar="", - default=None, - help=_("Create and attach a local swap block device of MB.")) -@cliutils.arg( - '--ephemeral', - metavar="size=[,format=]", - action='append', - default=[], - help=_("Create and attach a local ephemeral block device of GB " - "and format it to .")) -@cliutils.arg( - '--hint', - action='append', - dest='scheduler_hints', - default=[], - metavar='', - help=_("Send arbitrary key/value pairs to the scheduler for custom " - "use.")) -@cliutils.arg( - '--nic', - metavar="", - action='append', - dest='nics', - default=[], - help=_("Create a NIC on the server. " - "Specify option multiple times to create multiple NICs. " - "net-id: attach NIC to network with this UUID " - "(either port-id or net-id must be provided), " - "v4-fixed-ip: IPv4 fixed address for NIC (optional), " - "v6-fixed-ip: IPv6 fixed address for NIC (optional), " - "port-id: attach NIC to port with this UUID " - "(either port-id or net-id must be provided).")) -@cliutils.arg( - '--config-drive', - metavar="", - dest='config_drive', - default=False, - help=_("Enable config drive")) -@cliutils.arg( - '--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the new server boot progress until it completes.')) -def do_boot(cs, args): - """Boot a new server.""" - boot_args, boot_kwargs = _boot(cs, args) - - extra_boot_kwargs = utils.get_resource_manager_extra_kwargs(do_boot, args) - boot_kwargs.update(extra_boot_kwargs) - - server = cs.servers.create(*boot_args, **boot_kwargs) - _print_server(cs, args, server) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'building', ['active']) - - -def do_cloudpipe_list(cs, _args): - """Print a list of all cloudpipe instances.""" - cloudpipes = cs.cloudpipe.list() - columns = ['Project Id', "Public IP", "Public Port", "Internal IP"] - utils.print_list(cloudpipes, columns) - - -@cliutils.arg( - 'project', - metavar='', - help=_('UUID of the project to create the cloudpipe for.')) -def do_cloudpipe_create(cs, args): - """Create a cloudpipe instance for the given project.""" - cs.cloudpipe.create(args.project) - - -@cliutils.arg('address', metavar='', help=_('New IP Address.')) -@cliutils.arg('port', metavar='', help='New Port.') -def do_cloudpipe_configure(cs, args): - """Update the VPN IP/port of a cloudpipe instance.""" - cs.cloudpipe.update(args.address, args.port) - - -def _poll_for_status(poll_fn, obj_id, action, final_ok_states, - poll_period=5, show_progress=True, - status_field="status", silent=False): - """Block while an action is being performed, periodically printing - progress. - """ - def print_progress(progress): - if show_progress: - msg = (_('\rServer %(action)s... %(progress)s%% complete') - % dict(action=action, progress=progress)) - else: - msg = _('\rServer %(action)s...') % dict(action=action) - - sys.stdout.write(msg) - sys.stdout.flush() - - if not silent: - print() - - while True: - obj = poll_fn(obj_id) - - status = getattr(obj, status_field) - - if status: - status = status.lower() - - progress = getattr(obj, 'progress', None) or 0 - if status in final_ok_states: - if not silent: - print_progress(100) - print(_("\nFinished")) - break - elif status == "error": - if not silent: - print(_("\nError %s server") % action) - raise exceptions.InstanceInErrorState(obj.fault['message']) - - if not silent: - print_progress(progress) - - time.sleep(poll_period) - - -def _translate_keys(collection, convert): - for item in collection: - keys = item.__dict__.keys() - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _translate_extended_states(collection): - power_states = [ - 'NOSTATE', # 0x00 - 'Running', # 0x01 - '', # 0x02 - 'Paused', # 0x03 - 'Shutdown', # 0x04 - '', # 0x05 - 'Crashed', # 0x06 - 'Suspended' # 0x07 - ] - - for item in collection: - try: - setattr(item, 'power_state', - power_states[getattr(item, 'power_state')]) - except AttributeError: - setattr(item, 'power_state', "N/A") - try: - getattr(item, 'task_state') - except AttributeError: - setattr(item, 'task_state', "N/A") - - -def _translate_flavor_keys(collection): - _translate_keys(collection, [('ram', 'memory_mb')]) - - -def _print_flavor_extra_specs(flavor): - try: - return flavor.get_keys() - except exceptions.NotFound: - return "N/A" - - -def _print_flavor_list(flavors, show_extra_specs=False): - _translate_flavor_keys(flavors) - - headers = [ - 'ID', - 'Name', - 'Memory_MB', - 'Disk', - 'Ephemeral', - 'Swap', - 'VCPUs', - 'RXTX_Factor', - 'Is_Public', - ] - - if show_extra_specs: - formatters = {'extra_specs': _print_flavor_extra_specs} - headers.append('extra_specs') - else: - formatters = {} - - utils.print_list(flavors, headers, formatters) - - -@cliutils.arg( - '--extra-specs', - dest='extra_specs', - action='store_true', - default=False, - help=_('Get extra-specs of each flavor.')) -@cliutils.arg( - '--all', - dest='all', - action='store_true', - default=False, - help=_('Display all flavors (Admin only).')) -def do_flavor_list(cs, args): - """Print a list of available 'flavors' (sizes of servers).""" - if args.all: - flavors = cs.flavors.list(is_public=None) - else: - flavors = cs.flavors.list() - _print_flavor_list(flavors, args.extra_specs) - - -@cliutils.arg( - 'flavor', - metavar='', - help=_("Name or ID of the flavor to delete")) -def do_flavor_delete(cs, args): - """Delete a specific flavor""" - flavorid = _find_flavor(cs, args.flavor) - cs.flavors.delete(flavorid) - _print_flavor_list([flavorid]) - - -@cliutils.arg( - 'flavor', - metavar='', - help=_("Name or ID of flavor")) -def do_flavor_show(cs, args): - """Show details about the given flavor.""" - flavor = _find_flavor(cs, args.flavor) - _print_flavor(flavor) - - -@cliutils.arg( - 'name', - metavar='', - help=_("Name of the new flavor")) -@cliutils.arg( - 'id', - metavar='', - help=_("Unique ID (integer or UUID) for the new flavor." - " If specifying 'auto', a UUID will be generated as id")) -@cliutils.arg( - 'ram', - metavar='', - help=_("Memory size in MB")) -@cliutils.arg( - 'disk', - metavar='', - help=_("Disk size in GB")) -@cliutils.arg( - '--ephemeral', - metavar='', - help=_("Ephemeral space size in GB (default 0)"), - default=0) -@cliutils.arg( - 'vcpus', - metavar='', - help=_("Number of vcpus")) -@cliutils.arg( - '--swap', - metavar='', - help=_("Swap space size in MB (default 0)"), - default=0) -@cliutils.arg( - '--rxtx-factor', - metavar='', - help=_("RX/TX factor (default 1)"), - default=1.0) -@cliutils.arg( - '--is-public', - metavar='', - help=_("Make flavor accessible to the public (default true)"), - type=lambda v: strutils.bool_from_string(v, True), - default=True) -def do_flavor_create(cs, args): - """Create a new flavor""" - f = cs.flavors.create(args.name, args.ram, args.vcpus, args.disk, args.id, - args.ephemeral, args.swap, args.rxtx_factor, - args.is_public) - _print_flavor_list([f]) - - -@cliutils.arg( - 'flavor', - metavar='', - help=_("Name or ID of flavor")) -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'unset'], - help=_("Actions: 'set' or 'unset'")) -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Extra_specs to set/unset (only key is necessary on unset)')) -def do_flavor_key(cs, args): - """Set or unset extra_spec for a flavor.""" - flavor = _find_flavor(cs, args.flavor) - keypair = _extract_metadata(args) - - if args.action == 'set': - flavor.set_keys(keypair) - elif args.action == 'unset': - flavor.unset_keys(keypair.keys()) - - -@cliutils.arg( - '--flavor', - metavar='', - help=_("Filter results by flavor name or ID.")) -@cliutils.arg( - '--tenant', metavar='', - help=_('Filter results by tenant ID.')) -def do_flavor_access_list(cs, args): - """Print access information about the given flavor.""" - if args.flavor and args.tenant: - raise exceptions.CommandError(_("Unable to filter results by " - "both --flavor and --tenant.")) - elif args.flavor: - flavor = _find_flavor(cs, args.flavor) - if flavor.is_public: - raise exceptions.CommandError(_("Failed to get access list " - "for public flavor type.")) - kwargs = {'flavor': flavor} - elif args.tenant: - kwargs = {'tenant': args.tenant} - else: - raise exceptions.CommandError(_("Unable to get all access lists. " - "Specify --flavor or --tenant")) - - try: - access_list = cs.flavor_access.list(**kwargs) - except NotImplementedError as e: - raise exceptions.CommandError("%s" % str(e)) - - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@cliutils.arg( - 'flavor', - metavar='', - help=_("Flavor name or ID to add access for the given tenant.")) -@cliutils.arg( - 'tenant', metavar='', - help=_('Tenant ID to add flavor access for.')) -def do_flavor_access_add(cs, args): - """Add flavor access for the given tenant.""" - flavor = _find_flavor(cs, args.flavor) - access_list = cs.flavor_access.add_tenant_access(flavor, args.tenant) - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@cliutils.arg( - 'flavor', - metavar='', - help=_("Flavor name or ID to remove access for the given tenant.")) -@cliutils.arg( - 'tenant', metavar='', - help=_('Tenant ID to remove flavor access for.')) -def do_flavor_access_remove(cs, args): - """Remove flavor access for the given tenant.""" - flavor = _find_flavor(cs, args.flavor) - access_list = cs.flavor_access.remove_tenant_access(flavor, args.tenant) - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@cliutils.arg( - 'project_id', metavar='', - help=_('The ID of the project.')) -def do_scrub(cs, args): - """Delete networks and security groups associated with a project.""" - networks_list = cs.networks.list() - networks_list = [network for network in networks_list - if getattr(network, 'project_id', '') == args.project_id] - search_opts = {'all_tenants': 1} - groups = cs.security_groups.list(search_opts) - groups = [group for group in groups - if group.tenant_id == args.project_id] - for network in networks_list: - cs.networks.disassociate(network) - for group in groups: - cs.security_groups.delete(group) - - -@cliutils.arg( - '--fields', - default=None, - metavar='', - help='Comma-separated list of fields to display. ' - 'Use the show command to see which fields are available.') -def do_network_list(cs, args): - """Print a list of available networks.""" - network_list = cs.networks.list() - columns = ['ID', 'Label', 'Cidr'] - - formatters = {} - field_titles = [] - if args.fields: - for field in args.fields.split(','): - field_title, formatter = utils._make_field_formatter(field, {}) - field_titles.append(field_title) - formatters[field_title] = formatter - - columns = columns + field_titles - utils.print_list(network_list, columns) - - -@cliutils.arg( - 'network', - metavar='', - help=_("uuid or label of network")) -def do_network_show(cs, args): - """Show details about the given network.""" - network = utils.find_resource(cs.networks, args.network) - utils.print_dict(network._info) - - -@cliutils.arg( - 'network', - metavar='', - help=_("uuid or label of network")) -def do_network_delete(cs, args): - """Delete network by label or id.""" - network = utils.find_resource(cs.networks, args.network) - network.delete() - - -@cliutils.arg( - '--host-only', - dest='host_only', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0) -@cliutils.arg( - '--project-only', - dest='project_only', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0) -@cliutils.arg( - 'network', - metavar='', - help="uuid of network") -def do_network_disassociate(cs, args): - """Disassociate host and/or project from the given network.""" - if args.host_only: - cs.networks.disassociate(args.network, True, False) - elif args.project_only: - cs.networks.disassociate(args.network, False, True) - else: - cs.networks.disassociate(args.network, True, True) - - -@cliutils.arg( - 'network', - metavar='', - help="uuid of network") -@cliutils.arg( - 'host', - metavar='', - help="Name of host") -def do_network_associate_host(cs, args): - """Associate host with network.""" - cs.networks.associate_host(args.network, args.host) - - -@cliutils.arg( - 'network', - metavar='', - help="uuid of network") -def do_network_associate_project(cs, args): - """Associate project with network.""" - cs.networks.associate_project(args.network) - - -def _filter_network_create_options(args): - valid_args = ['label', 'cidr', 'vlan_start', 'vpn_start', 'cidr_v6', - 'gateway', 'gateway_v6', 'bridge', 'bridge_interface', - 'multi_host', 'dns1', 'dns2', 'uuid', 'fixed_cidr', - 'project_id', 'priority', 'vlan', 'mtu', 'dhcp_server', - 'allowed_start', 'allowed_end'] - kwargs = {} - for k, v in args.__dict__.items(): - if k in valid_args and v is not None: - kwargs[k] = v - - return kwargs - - -@cliutils.arg( - 'label', - metavar='', - help=_("Label for network")) -@cliutils.arg( - '--fixed-range-v4', - dest='cidr', - metavar='', - help=_("IPv4 subnet (ex: 10.0.0.0/8)")) -@cliutils.arg( - '--fixed-range-v6', - dest="cidr_v6", - help=_('IPv6 subnet (ex: fe80::/64')) -@cliutils.arg( - '--vlan', - dest='vlan', - type=int, - metavar='', - help=_("The vlan ID to be assigned to the project.")) -@cliutils.arg( - '--vlan-start', - dest='vlan_start', - type=int, - metavar='', - help=_('First vlan ID to be assigned to the project. Subsequent vlan ' - 'IDs will be assigned incrementally.')) -@cliutils.arg( - '--vpn', - dest='vpn_start', - type=int, - metavar='', - help=_("vpn start")) -@cliutils.arg( - '--gateway', - dest="gateway", - help=_('gateway')) -@cliutils.arg( - '--gateway-v6', - dest="gateway_v6", - help=_('IPv6 gateway')) -@cliutils.arg( - '--bridge', - dest="bridge", - metavar='', - help=_('VIFs on this network are connected to this bridge.')) -@cliutils.arg( - '--bridge-interface', - dest="bridge_interface", - metavar='', - help=_('The bridge is connected to this interface.')) -@cliutils.arg( - '--multi-host', - dest="multi_host", - metavar="<'T'|'F'>", - help=_('Multi host')) -@cliutils.arg( - '--dns1', - dest="dns1", - metavar="", help='First DNS') -@cliutils.arg( - '--dns2', - dest="dns2", - metavar="", - help=_('Second DNS')) -@cliutils.arg( - '--uuid', - dest="uuid", - metavar="", - help=_('Network UUID')) -@cliutils.arg( - '--fixed-cidr', - dest="fixed_cidr", - metavar='', - help=_('IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)')) -@cliutils.arg( - '--project-id', - dest="project_id", - metavar="", - help=_('Project ID')) -@cliutils.arg( - '--priority', - dest="priority", - metavar="", - help=_('Network interface priority')) -@cliutils.arg( - '--mtu', - dest="mtu", - type=int, - help=_('MTU for network')) -@cliutils.arg( - '--enable-dhcp', - dest="enable_dhcp", - metavar="<'T'|'F'>", - help=_('Enable dhcp')) -@cliutils.arg( - '--dhcp-server', - dest="dhcp_server", - help=_('Dhcp-server (defaults to gateway address)')) -@cliutils.arg( - '--share-address', - dest="share_address", - metavar="<'T'|'F'>", - help=_('Share address')) -@cliutils.arg( - '--allowed-start', - dest="allowed_start", - help=_('Start of allowed addresses for instances')) -@cliutils.arg( - '--allowed-end', - dest="allowed_end", - help=_('End of allowed addresses for instances')) -def do_network_create(cs, args): - """Create a network.""" - - if not (args.cidr or args.cidr_v6): - raise exceptions.CommandError( - _("Must specify either fixed_range_v4 or fixed_range_v6")) - kwargs = _filter_network_create_options(args) - if args.multi_host is not None: - kwargs['multi_host'] = bool(args.multi_host == 'T' or - strutils.bool_from_string(args.multi_host)) - if args.enable_dhcp is not None: - kwargs['enable_dhcp'] = bool( - args.enable_dhcp == 'T' or - strutils.bool_from_string(args.enable_dhcp)) - if args.share_address is not None: - kwargs['share_address'] = bool( - args.share_address == 'T' or - strutils.bool_from_string(args.share_address)) - - cs.networks.create(**kwargs) - - -@cliutils.arg( - '--limit', - dest="limit", - metavar="", - help=_('Number of images to return per request.')) -def do_image_list(cs, _args): - """Print a list of available images to boot from.""" - limit = _args.limit - image_list = cs.images.list(limit=limit) - - def parse_server_name(image): - try: - return image.server['id'] - except (AttributeError, KeyError): - return '' - - fmts = {'Server': parse_server_name} - utils.print_list(image_list, ['ID', 'Name', 'Status', 'Server'], - fmts, sortby_index=1) - - -@cliutils.arg( - 'image', - metavar='', - help=_("Name or ID of image")) -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'delete'], - help=_("Actions: 'set' or 'delete'")) -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to add/update or delete (only key is necessary on ' - 'delete)')) -def do_image_meta(cs, args): - """Set or Delete metadata on an image.""" - image = _find_image(cs, args.image) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.images.set_meta(image, metadata) - elif args.action == 'delete': - cs.images.delete_meta(image, metadata.keys()) - - -def _extract_metadata(args): - metadata = {} - for metadatum in args.metadata[0]: - # Can only pass the key in on 'delete' - # So this doesn't have to have '=' - if metadatum.find('=') > -1: - (key, value) = metadatum.split('=', 1) - else: - key = metadatum - value = None - - metadata[key] = value - return metadata - - -def _print_image(image): - info = image._info.copy() - - # ignore links, we don't need to present those - info.pop('links') - - # try to replace a server entity to just an id - server = info.pop('server', None) - try: - info['server'] = server['id'] - except (KeyError, TypeError): - pass - - # break up metadata and display each on its own row - metadata = info.pop('metadata', {}) - try: - for key, value in metadata.items(): - _key = 'metadata %s' % key - info[_key] = value - except AttributeError: - pass - - utils.print_dict(info) - - -def _print_flavor(flavor): - info = flavor._info.copy() - # ignore links, we don't need to present those - info.pop('links') - info.update({"extra_specs": _print_flavor_extra_specs(flavor)}) - utils.print_dict(info) - - -@cliutils.arg( - 'image', - metavar='', - help=_("Name or ID of image")) -def do_image_show(cs, args): - """Show details about the given image.""" - image = _find_image(cs, args.image) - _print_image(image) - - -@cliutils.arg( - 'image', metavar='', nargs='+', - help=_('Name or ID of image(s).')) -def do_image_delete(cs, args): - """Delete specified image(s).""" - for image in args.image: - try: - _find_image(cs, image).delete() - except Exception as e: - print(_("Delete for image %(image)s failed: %(e)s") % - {'image': image, 'e': e}) - - -@cliutils.arg( - '--reservation-id', - dest='reservation_id', - metavar='', - default=None, - help=_('Only return servers that match reservation-id.')) -@cliutils.arg( - '--reservation_id', - help=argparse.SUPPRESS) -@cliutils.arg( - '--ip', - dest='ip', - metavar='', - default=None, - help=_('Search with regular expression match by IP address.')) -@cliutils.arg( - '--ip6', - dest='ip6', - metavar='', - default=None, - help=_('Search with regular expression match by IPv6 address.')) -@cliutils.arg( - '--name', - dest='name', - metavar='', - default=None, - help=_('Search with regular expression match by name')) -@cliutils.arg( - '--instance-name', - dest='instance_name', - metavar='', - default=None, - help=_('Search with regular expression match by server name.')) -@cliutils.arg( - '--instance_name', - help=argparse.SUPPRESS) -@cliutils.arg( - '--status', - dest='status', - metavar='', - default=None, - help=_('Search by server status')) -@cliutils.arg( - '--flavor', - dest='flavor', - metavar='', - default=None, - help=_('Search by flavor name or ID')) -@cliutils.arg( - '--image', - dest='image', - metavar='', - default=None, - help=_('Search by image name or ID')) -@cliutils.arg( - '--host', - dest='host', - metavar='', - default=None, - help=_('Search servers by hostname to which they are assigned (Admin ' - 'only).')) -@cliutils.arg( - '--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help=_('Display information from all tenants (Admin only).')) -@cliutils.arg( - '--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@cliutils.arg( - '--tenant', - # nova db searches by project_id - dest='tenant', - metavar='', - nargs='?', - help=_('Display information from single tenant (Admin only). ' - 'The --all-tenants option must also be provided.')) -@cliutils.arg( - '--user', - dest='user', - metavar='', - nargs='?', - help=_('Display information from single user (Admin only).')) -@cliutils.arg( - '--deleted', - dest='deleted', - action="store_true", - default=False, - help='Only display deleted servers (Admin only).') -@cliutils.arg( - '--fields', - default=None, - metavar='', - help=_('Comma-separated list of fields to display. ' - 'Use the show command to see which fields are available.')) -@cliutils.arg( - '--minimal', - dest='minimal', - action="store_true", - default=False, - help=_('Get only uuid and name.')) -@cliutils.arg( - '--sort', - dest='sort', - metavar='[:]', - help=('Comma-separated list of sort keys and directions in the form' - ' of [:]. The direction defaults to descending if' - ' not specified.')) -def do_list(cs, args): - """List active servers.""" - imageid = None - flavorid = None - if args.image: - imageid = _find_image(cs, args.image).id - if args.flavor: - flavorid = _find_flavor(cs, args.flavor).id - # search by tenant or user only works with all_tenants - if args.tenant or args.user: - args.all_tenants = 1 - search_opts = { - 'all_tenants': args.all_tenants, - 'reservation_id': args.reservation_id, - 'ip': args.ip, - 'ip6': args.ip6, - 'name': args.name, - 'image': imageid, - 'flavor': flavorid, - 'status': args.status, - 'tenant_id': args.tenant, - 'user_id': args.user, - 'host': args.host, - 'deleted': args.deleted, - 'instance_name': args.instance_name} - - filters = {'flavor': lambda f: f['id'], - 'security_groups': utils._format_security_groups} - - formatters = {} - field_titles = [] - if args.fields: - for field in args.fields.split(','): - field_title, formatter = utils._make_field_formatter(field, - filters) - field_titles.append(field_title) - formatters[field_title] = formatter - - id_col = 'ID' - - detailed = not args.minimal - - sort_keys = [] - sort_dirs = [] - if args.sort: - for sort in args.sort.split(','): - sort_key, _sep, sort_dir = sort.partition(':') - if not sort_dir: - sort_dir = 'desc' - elif sort_dir not in ('asc', 'desc'): - raise exceptions.CommandError(_( - 'Unknown sort direction: %s') % sort_dir) - sort_keys.append(sort_key) - sort_dirs.append(sort_dir) - - servers = cs.servers.list(detailed=detailed, - search_opts=search_opts, - sort_keys=sort_keys, - sort_dirs=sort_dirs) - convert = [('OS-EXT-SRV-ATTR:host', 'host'), - ('OS-EXT-STS:task_state', 'task_state'), - ('OS-EXT-SRV-ATTR:instance_name', 'instance_name'), - ('OS-EXT-STS:power_state', 'power_state'), - ('hostId', 'host_id')] - _translate_keys(servers, convert) - _translate_extended_states(servers) - if args.minimal: - columns = [ - id_col, - 'Name'] - elif field_titles: - columns = [id_col] + field_titles - else: - columns = [ - id_col, - 'Name', - 'Status', - 'Task State', - 'Power State', - 'Networks' - ] - # If getting the data for all tenants, print - # Tenant ID as well - if search_opts['all_tenants']: - columns.insert(2, 'Tenant ID') - formatters['Networks'] = utils._format_servers_list_networks - sortby_index = 1 - if args.sort: - sortby_index = None - utils.print_list(servers, columns, - formatters, sortby_index=sortby_index) - - -@cliutils.arg( - '--hard', - dest='reboot_type', - action='store_const', - const=servers.REBOOT_HARD, - default=servers.REBOOT_SOFT, - help=_('Perform a hard reboot (instead of a soft one).')) -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - '--poll', - dest='poll', - action="store_true", - default=False, - help=_('Poll until reboot is complete.')) -def do_reboot(cs, args): - """Reboot a server.""" - server = _find_server(cs, args.server) - server.reboot(args.reboot_type) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'rebooting', ['active'], - show_progress=False) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg('image', metavar='', help=_("Name or ID of new image.")) -@cliutils.arg( - '--rebuild-password', - dest='rebuild_password', - metavar='', - default=False, - help=_("Set the provided admin password on the rebuilt server.")) -@cliutils.arg( - '--rebuild_password', - help=argparse.SUPPRESS) -@cliutils.arg( - '--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the server rebuild progress until it completes.')) -@cliutils.arg( - '--minimal', - dest='minimal', - action="store_true", - default=False, - help=_('Skips flavor/image lookups when showing servers')) -@cliutils.arg( - '--preserve-ephemeral', - action="store_true", - default=False, - help='Preserve the default ephemeral storage partition on rebuild.') -@cliutils.arg( - '--name', - metavar='', - default=None, - help=_('Name for the new server')) -@cliutils.arg( - '--meta', - metavar="", - action='append', - default=[], - help=_("Record arbitrary key/value metadata to /meta_data.json " - "on the metadata server. Can be specified multiple times.")) -@cliutils.arg( - '--file', - metavar="", - action='append', - dest='files', - default=[], - help=_("Store arbitrary files from locally to " - "on the new server. You may store up to 5 files.")) -def do_rebuild(cs, args): - """Shutdown, re-image, and re-boot a server.""" - server = _find_server(cs, args.server) - image = _find_image(cs, args.image) - - if args.rebuild_password is not False: - _password = args.rebuild_password - else: - _password = None - - kwargs = utils.get_resource_manager_extra_kwargs(do_rebuild, args) - kwargs['preserve_ephemeral'] = args.preserve_ephemeral - kwargs['name'] = args.name - meta = dict(v.split('=', 1) for v in args.meta) - kwargs['meta'] = meta - - files = {} - for f in args.files: - try: - dst, src = f.split('=', 1) - with open(src, 'r') as s: - files[dst] = s.read() - except IOError as e: - raise exceptions.CommandError(_("Can't open '%(src)s': %(exc)s") % - {'src': src, 'exc': e}) - except ValueError: - raise exceptions.CommandError(_("Invalid file argument '%s'. " - "File arguments must be of the " - "form '--file " - "'") % f) - kwargs['files'] = files - server = server.rebuild(image, _password, **kwargs) - _print_server(cs, args, server) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'rebuilding', ['active']) - - -@cliutils.arg( - 'server', metavar='', - help=_('Name (old name) or ID of server.')) -@cliutils.arg('name', metavar='', help=_('New name for the server.')) -def do_rename(cs, args): - """Rename a server.""" - _find_server(cs, args.server).update(name=args.name) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'flavor', - metavar='', - help=_("Name or ID of new flavor.")) -@cliutils.arg( - '--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the server resize progress until it completes.')) -def do_resize(cs, args): - """Resize a server.""" - server = _find_server(cs, args.server) - flavor = _find_flavor(cs, args.flavor) - kwargs = utils.get_resource_manager_extra_kwargs(do_resize, args) - server.resize(flavor, **kwargs) - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'resizing', - ['active', 'verify_resize']) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_resize_confirm(cs, args): - """Confirm a previous resize.""" - _find_server(cs, args.server).confirm_resize() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_resize_revert(cs, args): - """Revert a previous resize (and return to the previous VM).""" - _find_server(cs, args.server).revert_resize() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - '--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the server migration progress until it completes.')) -def do_migrate(cs, args): - """Migrate a server. The new host will be selected by the scheduler.""" - server = _find_server(cs, args.server) - server.migrate() - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'migrating', - ['active', 'verify_resize']) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_pause(cs, args): - """Pause a server.""" - _find_server(cs, args.server).pause() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unpause(cs, args): - """Unpause a server.""" - _find_server(cs, args.server).unpause() - - -@cliutils.arg( - 'server', - metavar='', nargs='+', - help=_('Name or ID of server(s).')) -def do_stop(cs, args): - """Stop the server(s).""" - utils.do_action_on_many( - lambda s: _find_server(cs, s).stop(), - args.server, - _("Request to stop server %s has been accepted."), - _("Unable to stop the specified server(s).")) - - -@cliutils.arg( - 'server', - metavar='', nargs='+', - help=_('Name or ID of server(s).')) -def do_start(cs, args): - """Start the server(s).""" - utils.do_action_on_many( - lambda s: _find_server(cs, s).start(), - args.server, - _("Request to start server %s has been accepted."), - _("Unable to start the specified server(s).")) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_lock(cs, args): - """Lock a server. A normal (non-admin) user will not be able to execute - actions on a locked server. - """ - _find_server(cs, args.server).lock() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unlock(cs, args): - """Unlock a server.""" - _find_server(cs, args.server).unlock() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_suspend(cs, args): - """Suspend a server.""" - _find_server(cs, args.server).suspend() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_resume(cs, args): - """Resume a server.""" - _find_server(cs, args.server).resume() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - '--password', - metavar='', - dest='password', - help=_('The admin password to be set in the rescue environment.')) -@cliutils.arg( - '--image', - metavar='', - dest='image', - help=_('The image to rescue with.')) -def do_rescue(cs, args): - """Reboots a server into rescue mode, which starts the machine - from either the initial image or a specified image, attaching the current - boot disk as secondary. - """ - kwargs = {} - if args.image: - kwargs['image'] = _find_image(cs, args.image) - if args.password: - kwargs['password'] = args.password - utils.print_dict(_find_server(cs, args.server).rescue(**kwargs)[1]) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unrescue(cs, args): - """Restart the server from normal boot disk again.""" - _find_server(cs, args.server).unrescue() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_shelve(cs, args): - """Shelve a server.""" - _find_server(cs, args.server).shelve() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_shelve_offload(cs, args): - """Remove a shelved server from the compute node.""" - _find_server(cs, args.server).shelve_offload() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_unshelve(cs, args): - """Unshelve a server.""" - _find_server(cs, args.server).unshelve() - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_diagnostics(cs, args): - """Retrieve server diagnostics.""" - server = _find_server(cs, args.server) - utils.print_dict(cs.servers.diagnostics(server)[1], wrap=80) - - -@cliutils.arg( - 'server', metavar='', - help=_('Name or ID of a server for which the network cache should ' - 'be refreshed from neutron (Admin only).')) -def do_refresh_network(cs, args): - """Refresh server network information.""" - server = _find_server(cs, args.server) - cs.server_external_events.create([{'server_uuid': server.id, - 'name': 'network-changed'}]) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_root_password(cs, args): - """ - Change the admin password for a server. - """ - server = _find_server(cs, args.server) - p1 = getpass.getpass('New password: ') - p2 = getpass.getpass('Again: ') - if p1 != p2: - raise exceptions.CommandError(_("Passwords do not match.")) - server.change_password(p1) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg('name', metavar='', help=_('Name of snapshot.')) -@cliutils.arg( - '--show', - dest='show', - action="store_true", - default=False, - help=_('Print image info.')) -@cliutils.arg( - '--poll', - dest='poll', - action="store_true", - default=False, - help=_('Report the snapshot progress and poll until image creation is ' - 'complete.')) -def do_image_create(cs, args): - """Create a new image by taking a snapshot of a running server.""" - server = _find_server(cs, args.server) - image_uuid = cs.servers.create_image(server, args.name) - - if args.poll: - _poll_for_status(cs.images.get, image_uuid, 'snapshotting', - ['active']) - - # NOTE(sirp): A race-condition exists between when the image finishes - # uploading and when the servers's `task_state` is cleared. To account - # for this, we need to poll a second time to ensure the `task_state` is - # cleared before returning, ensuring that a snapshot taken immediately - # after this function returns will succeed. - # - # A better long-term solution will be to separate 'snapshotting' and - # 'image-uploading' in Nova and clear the task-state once the VM - # snapshot is complete but before the upload begins. - task_state_field = "OS-EXT-STS:task_state" - if hasattr(server, task_state_field): - _poll_for_status(cs.servers.get, server.id, 'image_snapshot', - [None], status_field=task_state_field, - show_progress=False, silent=True) - - if args.show: - _print_image(cs.images.get(image_uuid)) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg('name', metavar='', help=_('Name of the backup image.')) -@cliutils.arg( - 'backup_type', metavar='', - help=_('The backup type, like "daily" or "weekly".')) -@cliutils.arg( - 'rotation', metavar='', - help=_('Int parameter representing how many backups to keep ' - 'around.')) -def do_backup(cs, args): - """Backup a server by creating a 'backup' type snapshot.""" - _find_server(cs, args.server).backup(args.name, - args.backup_type, - args.rotation) - - -@cliutils.arg( - 'server', - metavar='', - help=_("Name or ID of server")) -@cliutils.arg( - 'action', - metavar='', - choices=['set', 'delete'], - help=_("Actions: 'set' or 'delete'")) -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to set or delete (only key is necessary on delete)')) -def do_meta(cs, args): - """Set or Delete metadata on a server.""" - server = _find_server(cs, args.server) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.servers.set_meta(server, metadata) - elif args.action == 'delete': - cs.servers.delete_meta(server, sorted(metadata.keys(), reverse=True)) - - -def _print_server(cs, args, server=None): - # By default when searching via name we will do a - # findall(name=blah) and due a REST /details which is not the same - # as a .get() and doesn't get the information about flavors and - # images. This fix it as we redo the call with the id which does a - # .get() to get all informations. - if not server: - server = _find_server(cs, args.server) - - minimal = getattr(args, "minimal", False) - - networks = server.networks - info = server._info.copy() - for network_label, address_list in networks.items(): - info['%s network' % network_label] = ', '.join(address_list) - - flavor = info.get('flavor', {}) - flavor_id = flavor.get('id', '') - if minimal: - info['flavor'] = flavor_id - else: - info['flavor'] = '%s (%s)' % (_find_flavor(cs, flavor_id).name, - flavor_id) - - if 'security_groups' in info: - # when we have multiple nics the info will include the - # security groups N times where N == number of nics. Be nice - # and only display it once. - info['security_groups'] = ', '.join( - sorted(set(group['name'] for group in info['security_groups']))) - - image = info.get('image', {}) - if image: - image_id = image.get('id', '') - if minimal: - info['image'] = image_id - else: - try: - info['image'] = '%s (%s)' % (_find_image(cs, image_id).name, - image_id) - except Exception: - info['image'] = '%s (%s)' % (_("Image not found"), image_id) - else: # Booted from volume - info['image'] = _("Attempt to boot from volume - no image supplied") - - info.pop('links', None) - info.pop('addresses', None) - - utils.print_dict(info) - - -@cliutils.arg( - '--minimal', - dest='minimal', - action="store_true", - default=False, - help=_('Skips flavor/image lookups when showing servers')) -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_show(cs, args): - """Show details about the given server.""" - _print_server(cs, args) - - -@cliutils.arg( - 'server', metavar='', nargs='+', - help=_('Name or ID of server(s).')) -def do_delete(cs, args): - """Immediately shut down and delete specified server(s).""" - find_args = {'all_tenants': '1'} - utils.do_action_on_many( - lambda s: _find_server(cs, s, **find_args).delete(), - args.server, - _("Request to delete server %s has been accepted."), - _("Unable to delete the specified server(s).")) - - -def _find_server(cs, server, **find_args): - """Get a server by name or ID.""" - return utils.find_resource(cs.servers, server, **find_args) - - -def _find_image(cs, image): - """Get an image by name or ID.""" - return utils.find_resource(cs.images, image) - - -def _find_flavor(cs, flavor): - """Get a flavor by name, ID, or RAM size.""" - try: - return utils.find_resource(cs.flavors, flavor, is_public=None) - except exceptions.NotFound: - return cs.flavors.find(ram=flavor) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'network_id', - metavar='', - help='Network ID.') -def do_add_fixed_ip(cs, args): - """Add new IP address on a network to server.""" - server = _find_server(cs, args.server) - server.add_fixed_ip(args.network_id) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg('address', metavar='
', help=_('IP Address.')) -def do_remove_fixed_ip(cs, args): - """Remove an IP address from a server.""" - server = _find_server(cs, args.server) - server.remove_fixed_ip(args.address) - - -def _find_volume(cs, volume): - """Get a volume by name or ID.""" - return utils.find_resource(cs.volumes, volume) - - -def _find_volume_snapshot(cs, snapshot): - """Get a volume snapshot by name or ID.""" - return utils.find_resource(cs.volume_snapshots, snapshot) - - -def _print_volume(volume): - utils.print_dict(volume._info) - - -def _print_volume_snapshot(snapshot): - utils.print_dict(snapshot._info) - - -def _translate_volume_keys(collection): - _translate_keys(collection, - [('displayName', 'display_name'), - ('volumeType', 'volume_type')]) - - -def _translate_volume_snapshot_keys(collection): - _translate_keys(collection, - [('displayName', 'display_name'), - ('volumeId', 'volume_id')]) - - -def _translate_availability_zone_keys(collection): - _translate_keys(collection, - [('zoneName', 'name'), ('zoneState', 'status')]) - - -@cliutils.arg( - '--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help=_('Display information from all tenants (Admin only).')) -@cliutils.arg( - '--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@cliutils.service_type('volume') -def do_volume_list(cs, args): - """List all the volumes.""" - search_opts = {'all_tenants': args.all_tenants} - volumes = cs.volumes.list(search_opts=search_opts) - _translate_volume_keys(volumes) - - # Create a list of servers to which the volume is attached - for vol in volumes: - servers = [s.get('server_id') for s in vol.attachments] - setattr(vol, 'attached_to', ','.join(map(str, servers))) - utils.print_list(volumes, ['ID', 'Status', 'Display Name', - 'Size', 'Volume Type', 'Attached to']) - - -@cliutils.arg( - 'volume', - metavar='', - help=_('Name or ID of the volume.')) -@cliutils.service_type('volume') -def do_volume_show(cs, args): - """Show details about a volume.""" - volume = _find_volume(cs, args.volume) - _print_volume(volume) - - -@cliutils.arg( - 'size', - metavar='', - type=int, - help=_('Size of volume in GB')) -@cliutils.arg( - '--snapshot-id', - metavar='', - default=None, - help=_('Optional snapshot id to create the volume from. (Default=None)')) -@cliutils.arg( - '--snapshot_id', - help=argparse.SUPPRESS) -@cliutils.arg( - '--image-id', - metavar='', - help=_('Optional image id to create the volume from. (Default=None)'), - default=None) -@cliutils.arg( - '--display-name', - metavar='', - default=None, - help=_('Optional volume name. (Default=None)')) -@cliutils.arg( - '--display_name', - help=argparse.SUPPRESS) -@cliutils.arg( - '--display-description', - metavar='', - default=None, - help=_('Optional volume description. (Default=None)')) -@cliutils.arg( - '--display_description', - help=argparse.SUPPRESS) -@cliutils.arg( - '--volume-type', - metavar='', - default=None, - help=_('Optional volume type. (Default=None)')) -@cliutils.arg( - '--volume_type', - help=argparse.SUPPRESS) -@cliutils.arg( - '--availability-zone', metavar='', - help=_('Optional Availability Zone for volume. (Default=None)'), - default=None) -@cliutils.service_type('volume') -def do_volume_create(cs, args): - """Add a new volume.""" - volume = cs.volumes.create(args.size, - args.snapshot_id, - args.display_name, - args.display_description, - args.volume_type, - args.availability_zone, - imageRef=args.image_id) - _print_volume(volume) - - -@cliutils.arg( - 'volume', - metavar='', nargs='+', - help=_('Name or ID of the volume(s) to delete.')) -@cliutils.service_type('volume') -def do_volume_delete(cs, args): - """Remove volume(s).""" - for volume in args.volume: - try: - _find_volume(cs, volume).delete() - except Exception as e: - print(_("Delete for volume %(volume)s failed: %(e)s") % - {'volume': volume, 'e': e}) - - -@cliutils.arg( - 'server', - metavar='', - help=_('Name or ID of server.')) -@cliutils.arg( - 'volume', - metavar='', - help=_('ID of the volume to attach.')) -@cliutils.arg( - 'device', metavar='', default=None, nargs='?', - help=_('Name of the device e.g. /dev/vdb. ' - 'Use "auto" for autoassign (if supported)')) -def do_volume_attach(cs, args): - """Attach a volume to a server.""" - if args.device == 'auto': - args.device = None - - volume = cs.volumes.create_server_volume(_find_server(cs, args.server).id, - args.volume, - args.device) - _print_volume(volume) - - -@cliutils.arg( - 'server', - metavar='', - help=_('Name or ID of server.')) -@cliutils.arg( - 'attachment_id', - metavar='', - help=_('Attachment ID of the volume.')) -@cliutils.arg( - 'new_volume', - metavar='', - help=_('ID of the volume to attach.')) -def do_volume_update(cs, args): - """Update volume attachment.""" - cs.volumes.update_server_volume(_find_server(cs, args.server).id, - args.attachment_id, - args.new_volume) - - -@cliutils.arg( - 'server', - metavar='', - help=_('Name or ID of server.')) -@cliutils.arg( - 'attachment_id', - metavar='', - help=_('ID of the volume to detach.')) -def do_volume_detach(cs, args): - """Detach a volume from a server.""" - cs.volumes.delete_server_volume(_find_server(cs, args.server).id, - args.attachment_id) - - -@cliutils.service_type('volume') -def do_volume_snapshot_list(cs, _args): - """List all the snapshots.""" - snapshots = cs.volume_snapshots.list() - _translate_volume_snapshot_keys(snapshots) - utils.print_list(snapshots, ['ID', 'Volume ID', 'Status', 'Display Name', - 'Size']) - - -@cliutils.arg( - 'snapshot', - metavar='', - help=_('Name or ID of the snapshot.')) -@cliutils.service_type('volume') -def do_volume_snapshot_show(cs, args): - """Show details about a snapshot.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - _print_volume_snapshot(snapshot) - - -@cliutils.arg( - 'volume_id', - metavar='', - help=_('ID of the volume to snapshot')) -@cliutils.arg( - '--force', - metavar='', - help=_('Optional flag to indicate whether to snapshot a volume even if ' - 'its attached to a server. (Default=False)'), - default=False) -@cliutils.arg( - '--display-name', - metavar='', - default=None, - help=_('Optional snapshot name. (Default=None)')) -@cliutils.arg( - '--display_name', - help=argparse.SUPPRESS) -@cliutils.arg( - '--display-description', - metavar='', - default=None, - help=_('Optional snapshot description. (Default=None)')) -@cliutils.arg( - '--display_description', - help=argparse.SUPPRESS) -@cliutils.service_type('volume') -def do_volume_snapshot_create(cs, args): - """Add a new snapshot.""" - snapshot = cs.volume_snapshots.create(args.volume_id, - args.force, - args.display_name, - args.display_description) - _print_volume_snapshot(snapshot) - - -@cliutils.arg( - 'snapshot', - metavar='', - help=_('Name or ID of the snapshot to delete.')) -@cliutils.service_type('volume') -def do_volume_snapshot_delete(cs, args): - """Remove a snapshot.""" - snapshot = _find_volume_snapshot(cs, args.snapshot) - snapshot.delete() - - -def _print_volume_type_list(vtypes): - utils.print_list(vtypes, ['ID', 'Name']) - - -@cliutils.service_type('volume') -def do_volume_type_list(cs, args): - """Print a list of available 'volume types'.""" - vtypes = cs.volume_types.list() - _print_volume_type_list(vtypes) - - -@cliutils.arg( - 'name', - metavar='', - help=_("Name of the new volume type")) -@cliutils.service_type('volume') -def do_volume_type_create(cs, args): - """Create a new volume type.""" - vtype = cs.volume_types.create(args.name) - _print_volume_type_list([vtype]) - - -@cliutils.arg( - 'id', - metavar='', - help=_("Unique ID of the volume type to delete")) -@cliutils.service_type('volume') -def do_volume_type_delete(cs, args): - """Delete a specific volume type.""" - cs.volume_types.delete(args.id) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'console_type', - metavar='', - help=_('Type of vnc console ("novnc" or "xvpvnc").')) -def do_get_vnc_console(cs, args): - """Get a vnc console to a server.""" - server = _find_server(cs, args.server) - data = server.get_vnc_console(args.console_type) - - class VNCConsole(object): - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([VNCConsole(data['console'])], ['Type', 'Url']) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'console_type', - metavar='', - help=_('Type of spice console ("spice-html5").')) -def do_get_spice_console(cs, args): - """Get a spice console to a server.""" - server = _find_server(cs, args.server) - data = server.get_spice_console(args.console_type) - - class SPICEConsole(object): - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([SPICEConsole(data['console'])], ['Type', 'Url']) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'console_type', - metavar='', - help='Type of rdp console ("rdp-html5").') -def do_get_rdp_console(cs, args): - """Get a rdp console to a server.""" - server = _find_server(cs, args.server) - data = server.get_rdp_console(args.console_type) - - class RDPConsole(object): - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([RDPConsole(data['console'])], ['Type', 'Url']) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - '--console_type', default='serial', - help=_('Type of serial console, default="serial".')) -def do_get_serial_console(cs, args): - """Get a serial console to a server.""" - if args.console_type not in ('serial',): - raise exceptions.CommandError( - _("Invalid parameter value for 'console_type', " - "currently supported 'serial'.")) - - server = _find_server(cs, args.server) - data = server.get_serial_console(args.console_type) - - class SerialConsole(object): - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([SerialConsole(data['console'])], ['Type', 'Url']) - - -@cliutils.arg('server', metavar='', help='Name or ID of server.') -@cliutils.arg( - 'private_key', - metavar='', - help=_('Private key (used locally to decrypt password) (Optional). ' - 'When specified, the command displays the clear (decrypted) VM ' - 'password. When not specified, the ciphered VM password is ' - 'displayed.'), - nargs='?', - default=None) -def do_get_password(cs, args): - """Get the admin password for a server.""" - server = _find_server(cs, args.server) - data = server.get_password(args.private_key) - print(data) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_clear_password(cs, args): - """Clear the admin password for a server.""" - server = _find_server(cs, args.server) - server.clear_password() - - -def _print_floating_ip_list(floating_ips): - convert = [('instance_id', 'server_id')] - _translate_keys(floating_ips, convert) - - utils.print_list(floating_ips, - ['Id', 'IP', 'Server Id', 'Fixed IP', 'Pool']) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - '--length', - metavar='', - default=None, - help=_('Length in lines to tail.')) -def do_console_log(cs, args): - """Get console log output of a server.""" - server = _find_server(cs, args.server) - data = server.get_console_output(length=args.length) - print(data) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg('address', metavar='
', help=_('IP Address.')) -@cliutils.arg( - '--fixed-address', - metavar='', - default=None, - help=_('Fixed IP Address to associate with.')) -def do_add_floating_ip(cs, args): - """DEPRECATED, use floating-ip-associate instead.""" - _associate_floating_ip(cs, args) - - -@cliutils.arg('server', metavar='', help='Name or ID of server.') -@cliutils.arg('address', metavar='
', help='IP Address.') -@cliutils.arg( - '--fixed-address', - metavar='', - default=None, - help='Fixed IP Address to associate with.') -def do_floating_ip_associate(cs, args): - """Associate a floating IP address to a server.""" - _associate_floating_ip(cs, args) - - -def _associate_floating_ip(cs, args): - server = _find_server(cs, args.server) - server.add_floating_ip(args.address, args.fixed_address) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg('address', metavar='
', help=_('IP Address.')) -def do_remove_floating_ip(cs, args): - """DEPRECATED, use floating-ip-disassociate instead.""" - _disassociate_floating_ip(cs, args) - - -@cliutils.arg('server', metavar='', help='Name or ID of server.') -@cliutils.arg('address', metavar='
', help='IP Address.') -def do_floating_ip_disassociate(cs, args): - """Disassociate a floating IP address from a server.""" - _disassociate_floating_ip(cs, args) - - -def _disassociate_floating_ip(cs, args): - server = _find_server(cs, args.server) - server.remove_floating_ip(args.address) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'secgroup', - metavar='', - help=_('Name of Security Group.')) -def do_add_secgroup(cs, args): - """Add a Security Group to a server.""" - server = _find_server(cs, args.server) - server.add_security_group(args.secgroup) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'secgroup', - metavar='', - help=_('Name of Security Group.')) -def do_remove_secgroup(cs, args): - """Remove a Security Group from a server.""" - server = _find_server(cs, args.server) - server.remove_security_group(args.secgroup) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_list_secgroup(cs, args): - """List Security Group(s) of a server.""" - server = _find_server(cs, args.server) - groups = server.list_security_group() - _print_secgroups(groups) - - -@cliutils.arg( - 'pool', - metavar='', - help=_('Name of Floating IP Pool. (Optional)'), - nargs='?', - default=None) -def do_floating_ip_create(cs, args): - """Allocate a floating IP for the current tenant.""" - _print_floating_ip_list([cs.floating_ips.create(pool=args.pool)]) - - -@cliutils.arg('address', metavar='
', help=_('IP of Floating IP.')) -def do_floating_ip_delete(cs, args): - """De-allocate a floating IP.""" - floating_ips = cs.floating_ips.list() - for floating_ip in floating_ips: - if floating_ip.ip == args.address: - return cs.floating_ips.delete(floating_ip.id) - raise exceptions.CommandError(_("Floating IP %s not found.") % - args.address) - - -@cliutils.arg( - '--all-tenants', - action='store_true', - default=False, - help=_('Display floatingips from all tenants (Admin only).')) -def do_floating_ip_list(cs, args): - """List floating IPs.""" - _print_floating_ip_list(cs.floating_ips.list(args.all_tenants)) - - -def do_floating_ip_pool_list(cs, _args): - """List all floating IP pools.""" - utils.print_list(cs.floating_ip_pools.list(), ['name']) - - -@cliutils.arg( - '--host', dest='host', metavar='', default=None, - help=_('Filter by host')) -def do_floating_ip_bulk_list(cs, args): - """List all floating IPs.""" - utils.print_list(cs.floating_ips_bulk.list(args.host), ['project_id', - 'address', - 'instance_uuid', - 'pool', - 'interface']) - - -@cliutils.arg('ip_range', metavar='', help=_('Address range to create')) -@cliutils.arg( - '--pool', dest='pool', metavar='', default=None, - help=_('Pool for new Floating IPs')) -@cliutils.arg( - '--interface', metavar='', default=None, - help=_('Interface for new Floating IPs')) -def do_floating_ip_bulk_create(cs, args): - """Bulk create floating IPs by range.""" - cs.floating_ips_bulk.create(args.ip_range, args.pool, args.interface) - - -@cliutils.arg('ip_range', metavar='', help=_('Address range to delete')) -def do_floating_ip_bulk_delete(cs, args): - """Bulk delete floating IPs by range.""" - cs.floating_ips_bulk.delete(args.ip_range) - - -def _print_dns_list(dns_entries): - utils.print_list(dns_entries, ['ip', 'name', 'domain']) - - -def _print_domain_list(domain_entries): - utils.print_list(domain_entries, ['domain', 'scope', - 'project', 'availability_zone']) - - -def do_dns_domains(cs, args): - """Print a list of available dns domains.""" - domains = cs.dns_domains.domains() - _print_domain_list(domains) - - -@cliutils.arg('domain', metavar='', help=_('DNS domain')) -@cliutils.arg('--ip', metavar='', help=_('IP address'), default=None) -@cliutils.arg('--name', metavar='', help=_('DNS name'), default=None) -def do_dns_list(cs, args): - """List current DNS entries for domain and IP or domain and name.""" - if not (args.ip or args.name): - raise exceptions.CommandError( - _("You must specify either --ip or --name")) - if args.name: - entry = cs.dns_entries.get(args.domain, args.name) - _print_dns_list([entry]) - else: - entries = cs.dns_entries.get_for_ip(args.domain, - ip=args.ip) - _print_dns_list(entries) - - -@cliutils.arg('ip', metavar='', help=_('IP address')) -@cliutils.arg('name', metavar='', help=_('DNS name')) -@cliutils.arg('domain', metavar='', help=_('DNS domain')) -@cliutils.arg( - '--type', - metavar='', - help=_('dns type (e.g. "A")'), - default='A') -def do_dns_create(cs, args): - """Create a DNS entry for domain, name and IP.""" - cs.dns_entries.create(args.domain, args.name, args.ip, args.type) - - -@cliutils.arg('domain', metavar='', help=_('DNS domain')) -@cliutils.arg('name', metavar='', help=_('DNS name')) -def do_dns_delete(cs, args): - """Delete the specified DNS entry.""" - cs.dns_entries.delete(args.domain, args.name) - - -@cliutils.arg('domain', metavar='', help=_('DNS domain')) -def do_dns_delete_domain(cs, args): - """Delete the specified DNS domain.""" - cs.dns_domains.delete(args.domain) - - -@cliutils.arg('domain', metavar='', help=_('DNS domain')) -@cliutils.arg( - '--availability-zone', - metavar='', - default=None, - help=_('Limit access to this domain to servers ' - 'in the specified availability zone.')) -@cliutils.arg( - '--availability_zone', - help=argparse.SUPPRESS) -def do_dns_create_private_domain(cs, args): - """Create the specified DNS domain.""" - cs.dns_domains.create_private(args.domain, - args.availability_zone) - - -@cliutils.arg('domain', metavar='', help=_('DNS domain')) -@cliutils.arg( - '--project', metavar='', - help=_('Limit access to this domain to users ' - 'of the specified project.'), - default=None) -def do_dns_create_public_domain(cs, args): - """Create the specified DNS domain.""" - cs.dns_domains.create_public(args.domain, - args.project) - - -def _print_secgroup_rules(rules, show_source_group=True): - class FormattedRule(object): - def __init__(self, obj): - items = (obj if isinstance(obj, dict) else obj._info).items() - for k, v in items: - if k == 'ip_range': - v = v.get('cidr') - elif k == 'group': - k = 'source_group' - v = v.get('name') - if v is None: - v = '' - - setattr(self, k, v) - - rules = [FormattedRule(rule) for rule in rules] - headers = ['IP Protocol', 'From Port', 'To Port', 'IP Range'] - if show_source_group: - headers.append('Source Group') - utils.print_list(rules, headers) - - -def _print_secgroups(secgroups): - utils.print_list(secgroups, ['Id', 'Name', 'Description']) - - -def _get_secgroup(cs, secgroup): - # Check secgroup is an ID (nova-network) or UUID (neutron) - if (utils.is_integer_like(encodeutils.safe_encode(secgroup)) or - uuidutils.is_uuid_like(secgroup)): - try: - return cs.security_groups.get(secgroup) - except exceptions.NotFound: - pass - - # Check secgroup as a name - match_found = False - for s in cs.security_groups.list(): - encoding = ( - locale.getpreferredencoding() or sys.stdin.encoding or 'UTF-8') - if not six.PY3: - s.name = s.name.encode(encoding) - if secgroup == s.name: - if match_found is not False: - msg = (_("Multiple security group matches found for name '%s'" - ", use an ID to be more specific.") % secgroup) - raise exceptions.NoUniqueMatch(msg) - match_found = s - if match_found is False: - raise exceptions.CommandError(_("Secgroup ID or name '%s' not found.") - % secgroup) - return match_found - - -@cliutils.arg( - 'secgroup', - metavar='', - help=_('ID or name of security group.')) -@cliutils.arg( - 'ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@cliutils.arg( - 'from_port', - metavar='', - help=_('Port at start of range.')) -@cliutils.arg( - 'to_port', - metavar='', - help=_('Port at end of range.')) -@cliutils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_add_rule(cs, args): - """Add a rule to a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - rule = cs.security_group_rules.create(secgroup.id, - args.ip_proto, - args.from_port, - args.to_port, - args.cidr) - _print_secgroup_rules([rule]) - - -@cliutils.arg( - 'secgroup', - metavar='', - help=_('ID or name of security group.')) -@cliutils.arg( - 'ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@cliutils.arg( - 'from_port', - metavar='', - help=_('Port at start of range.')) -@cliutils.arg( - 'to_port', - metavar='', - help=_('Port at end of range.')) -@cliutils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_delete_rule(cs, args): - """Delete a rule from a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - for rule in secgroup.rules: - if (rule['ip_protocol'] and - rule['ip_protocol'].upper() == args.ip_proto.upper() and - rule['from_port'] == int(args.from_port) and - rule['to_port'] == int(args.to_port) and - rule['ip_range']['cidr'] == args.cidr): - _print_secgroup_rules([rule]) - return cs.security_group_rules.delete(rule['id']) - - raise exceptions.CommandError(_("Rule not found")) - - -@cliutils.arg('name', metavar='', help=_('Name of security group.')) -@cliutils.arg( - 'description', metavar='', - help=_('Description of security group.')) -def do_secgroup_create(cs, args): - """Create a security group.""" - secgroup = cs.security_groups.create(args.name, args.description) - _print_secgroups([secgroup]) - - -@cliutils.arg( - 'secgroup', - metavar='', - help=_('ID or name of security group.')) -@cliutils.arg('name', metavar='', help=_('Name of security group.')) -@cliutils.arg( - 'description', metavar='', - help=_('Description of security group.')) -def do_secgroup_update(cs, args): - """Update a security group.""" - sg = _get_secgroup(cs, args.secgroup) - secgroup = cs.security_groups.update(sg, args.name, args.description) - _print_secgroups([secgroup]) - - -@cliutils.arg( - 'secgroup', - metavar='', - help=_('ID or name of security group.')) -def do_secgroup_delete(cs, args): - """Delete a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - cs.security_groups.delete(secgroup) - _print_secgroups([secgroup]) - - -@cliutils.arg( - '--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help=_('Display information from all tenants (Admin only).')) -@cliutils.arg( - '--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -def do_secgroup_list(cs, args): - """List security groups for the current tenant.""" - search_opts = {'all_tenants': args.all_tenants} - columns = ['Id', 'Name', 'Description'] - if args.all_tenants: - columns.append('Tenant_ID') - groups = cs.security_groups.list(search_opts=search_opts) - utils.print_list(groups, columns) - - -@cliutils.arg( - 'secgroup', - metavar='', - help=_('ID or name of security group.')) -def do_secgroup_list_rules(cs, args): - """List rules for a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - _print_secgroup_rules(secgroup.rules) - - -@cliutils.arg( - 'secgroup', - metavar='', - help=_('ID or name of security group.')) -@cliutils.arg( - 'source_group', - metavar='', - help=_('ID or name of source group.')) -@cliutils.arg( - 'ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@cliutils.arg( - 'from_port', - metavar='', - help=_('Port at start of range.')) -@cliutils.arg( - 'to_port', - metavar='', - help=_('Port at end of range.')) -def do_secgroup_add_group_rule(cs, args): - """Add a source group rule to a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - source_group = _get_secgroup(cs, args.source_group) - params = {} - params['group_id'] = source_group.id - - if args.ip_proto or args.from_port or args.to_port: - if not (args.ip_proto and args.from_port and args.to_port): - raise exceptions.CommandError(_("ip_proto, from_port, and to_port" - " must be specified together")) - params['ip_protocol'] = args.ip_proto.upper() - params['from_port'] = args.from_port - params['to_port'] = args.to_port - - rule = cs.security_group_rules.create(secgroup.id, **params) - _print_secgroup_rules([rule]) - - -@cliutils.arg( - 'secgroup', - metavar='', - help=_('ID or name of security group.')) -@cliutils.arg( - 'source_group', - metavar='', - help=_('ID or name of source group.')) -@cliutils.arg( - 'ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@cliutils.arg( - 'from_port', - metavar='', - help=_('Port at start of range.')) -@cliutils.arg( - 'to_port', - metavar='', - help=_('Port at end of range.')) -def do_secgroup_delete_group_rule(cs, args): - """Delete a source group rule from a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - source_group = _get_secgroup(cs, args.source_group) - params = {} - params['group_name'] = source_group.name - - if args.ip_proto or args.from_port or args.to_port: - if not (args.ip_proto and args.from_port and args.to_port): - raise exceptions.CommandError(_("ip_proto, from_port, and to_port" - " must be specified together")) - params['ip_protocol'] = args.ip_proto.upper() - params['from_port'] = int(args.from_port) - params['to_port'] = int(args.to_port) - - for rule in secgroup.rules: - if (rule.get('ip_protocol') and - rule['ip_protocol'].upper() == params.get( - 'ip_protocol').upper() and - rule.get('from_port') == params.get('from_port') and - rule.get('to_port') == params.get('to_port') and - rule.get('group', {}).get('name') == params.get('group_name')): - return cs.security_group_rules.delete(rule['id']) - - raise exceptions.CommandError(_("Rule not found")) - - -@cliutils.arg('name', metavar='', help=_('Name of key.')) -@cliutils.arg( - '--pub-key', - metavar='', - default=None, - help=_('Path to a public ssh key.')) -@cliutils.arg( - '--pub_key', - help=argparse.SUPPRESS) -def do_keypair_add(cs, args): - """Create a new key pair for use with servers.""" - name = args.name - pub_key = args.pub_key - - if pub_key: - if pub_key == '-': - pub_key = sys.stdin.read() - else: - try: - with open(os.path.expanduser(pub_key)) as f: - pub_key = f.read() - except IOError as e: - raise exceptions.CommandError( - _("Can't open or read '%(key)s': %(exc)s") - % {'key': pub_key, 'exc': e} - ) - - keypair = cs.keypairs.create(name, pub_key) - - if not pub_key: - private_key = keypair.private_key - print(private_key) - - -@cliutils.arg('name', metavar='', help=_('Keypair name to delete.')) -def do_keypair_delete(cs, args): - """Delete keypair given by its name.""" - name = _find_keypair(cs, args.name) - cs.keypairs.delete(name) - - -def do_keypair_list(cs, args): - """Print a list of keypairs for a user""" - keypairs = cs.keypairs.list() - columns = ['Name', 'Fingerprint'] - utils.print_list(keypairs, columns) - - -def _print_keypair(keypair): - kp = keypair._info.copy() - pk = kp.pop('public_key') - utils.print_dict(kp) - print(_("Public key: %s") % pk) - - -@cliutils.arg( - 'keypair', - metavar='', - help=_("Name or ID of keypair")) -def do_keypair_show(cs, args): - """Show details about the given keypair.""" - keypair = _find_keypair(cs, args.keypair) - _print_keypair(keypair) - - -def _find_keypair(cs, keypair): - """Get a keypair by name or ID.""" - return utils.find_resource(cs.keypairs, keypair) - - -@cliutils.arg( - '--tenant', - # nova db searches by project_id - dest='tenant', - metavar='', - nargs='?', - help=_('Display information from single tenant (Admin only).')) -@cliutils.arg( - '--reserved', - dest='reserved', - action='store_true', - default=False, - help=_('Include reservations count.')) -def do_absolute_limits(cs, args): - """Print a list of absolute limits for a user""" - limits = cs.limits.get(args.reserved, args.tenant).absolute - - class Limit(object): - def __init__(self, name, used, max, other): - self.name = name - self.used = used - self.max = max - self.other = other - - limit_map = { - 'maxServerMeta': {'name': 'Server Meta', 'type': 'max'}, - 'maxPersonality': {'name': 'Personality', 'type': 'max'}, - 'maxPersonalitySize': {'name': 'Personality Size', 'type': 'max'}, - 'maxImageMeta': {'name': 'ImageMeta', 'type': 'max'}, - 'maxTotalKeypairs': {'name': 'Keypairs', 'type': 'max'}, - 'totalCoresUsed': {'name': 'Cores', 'type': 'used'}, - 'maxTotalCores': {'name': 'Cores', 'type': 'max'}, - 'totalRAMUsed': {'name': 'RAM', 'type': 'used'}, - 'maxTotalRAMSize': {'name': 'RAM', 'type': 'max'}, - 'totalInstancesUsed': {'name': 'Instances', 'type': 'used'}, - 'maxTotalInstances': {'name': 'Instances', 'type': 'max'}, - 'totalFloatingIpsUsed': {'name': 'FloatingIps', 'type': 'used'}, - 'maxTotalFloatingIps': {'name': 'FloatingIps', 'type': 'max'}, - 'totalSecurityGroupsUsed': {'name': 'SecurityGroups', 'type': 'used'}, - 'maxSecurityGroups': {'name': 'SecurityGroups', 'type': 'max'}, - 'maxSecurityGroupRules': {'name': 'SecurityGroupRules', 'type': 'max'}, - 'maxServerGroups': {'name': 'ServerGroups', 'type': 'max'}, - 'totalServerGroupsUsed': {'name': 'ServerGroups', 'type': 'used'}, - 'maxServerGroupMembers': {'name': 'ServerGroupMembers', 'type': 'max'}, - } - - max = {} - used = {} - other = {} - limit_names = [] - columns = ['Name', 'Used', 'Max'] - for l in limits: - map = limit_map.get(l.name, {'name': l.name, 'type': 'other'}) - name = map['name'] - if map['type'] == 'max': - max[name] = l.value - elif map['type'] == 'used': - used[name] = l.value - else: - other[name] = l.value - columns.append('Other') - if name not in limit_names: - limit_names.append(name) - - limit_names.sort() - - limit_list = [] - for name in limit_names: - l = Limit(name, - used.get(name, "-"), - max.get(name, "-"), - other.get(name, "-")) - limit_list.append(l) - - utils.print_list(limit_list, columns) - - -def do_rate_limits(cs, args): - """Print a list of rate limits for a user""" - limits = cs.limits.get().rate - columns = ['Verb', 'URI', 'Value', 'Remain', 'Unit', 'Next_Available'] - utils.print_list(limits, columns) - - -@cliutils.arg( - '--start', - metavar='', - help=_('Usage range start date ex 2012-01-20 (default: 4 weeks ago)'), - default=None) -@cliutils.arg( - '--end', - metavar='', - help=_('Usage range end date, ex 2012-01-20 (default: tomorrow)'), - default=None) -def do_usage_list(cs, args): - """List usage data for all tenants.""" - dateformat = "%Y-%m-%d" - rows = ["Tenant ID", "Servers", "RAM MB-Hours", "CPU Hours", - "Disk GB-Hours"] - - now = timeutils.utcnow() - - if args.start: - start = datetime.datetime.strptime(args.start, dateformat) - else: - start = now - datetime.timedelta(weeks=4) - - if args.end: - end = datetime.datetime.strptime(args.end, dateformat) - else: - end = now + datetime.timedelta(days=1) - - def simplify_usage(u): - simplerows = [x.lower().replace(" ", "_") for x in rows] - - setattr(u, simplerows[0], u.tenant_id) - setattr(u, simplerows[1], "%d" % len(u.server_usages)) - setattr(u, simplerows[2], "%.2f" % u.total_memory_mb_usage) - setattr(u, simplerows[3], "%.2f" % u.total_vcpus_usage) - setattr(u, simplerows[4], "%.2f" % u.total_local_gb_usage) - - usage_list = cs.usage.list(start, end, detailed=True) - - print(_("Usage from %(start)s to %(end)s:") % - {'start': start.strftime(dateformat), - 'end': end.strftime(dateformat)}) - - for usage in usage_list: - simplify_usage(usage) - - utils.print_list(usage_list, rows) - - -@cliutils.arg( - '--start', - metavar='', - help=_('Usage range start date ex 2012-01-20 (default: 4 weeks ago)'), - default=None) -@cliutils.arg( - '--end', metavar='', - help=_('Usage range end date, ex 2012-01-20 (default: tomorrow)'), - default=None) -@cliutils.arg( - '--tenant', - metavar='', - default=None, - help=_('UUID of tenant to get usage for.')) -def do_usage(cs, args): - """Show usage data for a single tenant.""" - dateformat = "%Y-%m-%d" - rows = ["Servers", "RAM MB-Hours", "CPU Hours", "Disk GB-Hours"] - - now = timeutils.utcnow() - - if args.start: - start = datetime.datetime.strptime(args.start, dateformat) - else: - start = now - datetime.timedelta(weeks=4) - - if args.end: - end = datetime.datetime.strptime(args.end, dateformat) - else: - end = now + datetime.timedelta(days=1) - - def simplify_usage(u): - simplerows = [x.lower().replace(" ", "_") for x in rows] - - setattr(u, simplerows[0], "%d" % len(u.server_usages)) - setattr(u, simplerows[1], "%.2f" % u.total_memory_mb_usage) - setattr(u, simplerows[2], "%.2f" % u.total_vcpus_usage) - setattr(u, simplerows[3], "%.2f" % u.total_local_gb_usage) - - if args.tenant: - usage = cs.usage.get(args.tenant, start, end) - else: - if isinstance(cs.client, client.SessionClient): - auth = cs.client.auth - project_id = auth.get_auth_ref(cs.client.session).project_id - usage = cs.usage.get(project_id, start, end) - else: - usage = cs.usage.get(cs.client.tenant_id, start, end) - - print(_("Usage from %(start)s to %(end)s:") % - {'start': start.strftime(dateformat), - 'end': end.strftime(dateformat)}) - - if getattr(usage, 'total_vcpus_usage', None): - simplify_usage(usage) - utils.print_list([usage], rows) - else: - print(_('None')) - - -@cliutils.arg( - 'pk_filename', - metavar='', - nargs='?', - default='pk.pem', - help=_('Filename for the private key [Default: pk.pem]')) -@cliutils.arg( - 'cert_filename', - metavar='', - nargs='?', - default='cert.pem', - help=_('Filename for the X.509 certificate [Default: cert.pem]')) -def do_x509_create_cert(cs, args): - """Create x509 cert for a user in tenant.""" - - if os.path.exists(args.pk_filename): - raise exceptions.CommandError(_("Unable to write privatekey - %s " - "exists.") % args.pk_filename) - if os.path.exists(args.cert_filename): - raise exceptions.CommandError(_("Unable to write x509 cert - %s " - "exists.") % args.cert_filename) - - certs = cs.certs.create() - - try: - old_umask = os.umask(0o377) - with open(args.pk_filename, 'w') as private_key: - private_key.write(certs.private_key) - print(_("Wrote private key to %s") % args.pk_filename) - finally: - os.umask(old_umask) - - with open(args.cert_filename, 'w') as cert: - cert.write(certs.data) - print(_("Wrote x509 certificate to %s") % args.cert_filename) - - -@cliutils.arg( - 'filename', - metavar='', - nargs='?', - default='cacert.pem', - help=_('Filename to write the x509 root cert.')) -def do_x509_get_root_cert(cs, args): - """Fetch the x509 root cert.""" - if os.path.exists(args.filename): - raise exceptions.CommandError(_("Unable to write x509 root cert - \ - %s exists.") % args.filename) - - with open(args.filename, 'w') as cert: - cacert = cs.certs.get() - cert.write(cacert.data) - print(_("Wrote x509 root cert to %s") % args.filename) - - -@cliutils.arg( - '--hypervisor', - metavar='', - default=None, - help=_('type of hypervisor.')) -def do_agent_list(cs, args): - """List all builds.""" - result = cs.agents.list(args.hypervisor) - columns = ["Agent_id", "Hypervisor", "OS", "Architecture", "Version", - 'Md5hash', 'Url'] - utils.print_list(result, columns) - - -@cliutils.arg('os', metavar='', help=_('type of os.')) -@cliutils.arg( - 'architecture', - metavar='', - help=_('type of architecture')) -@cliutils.arg('version', metavar='', help=_('version')) -@cliutils.arg('url', metavar='', help=_('url')) -@cliutils.arg('md5hash', metavar='', help=_('md5 hash')) -@cliutils.arg( - 'hypervisor', - metavar='', - default='xen', - help=_('type of hypervisor.')) -def do_agent_create(cs, args): - """Create new agent build.""" - result = cs.agents.create(args.os, args.architecture, - args.version, args.url, - args.md5hash, args.hypervisor) - utils.print_dict(result._info.copy()) - - -@cliutils.arg('id', metavar='', help=_('id of the agent-build')) -def do_agent_delete(cs, args): - """Delete existing agent build.""" - cs.agents.delete(args.id) - - -@cliutils.arg('id', metavar='', help=_('id of the agent-build')) -@cliutils.arg('version', metavar='', help=_('version')) -@cliutils.arg('url', metavar='', help=_('url')) -@cliutils.arg('md5hash', metavar='', help=_('md5hash')) -def do_agent_modify(cs, args): - """Modify existing agent build.""" - result = cs.agents.update(args.id, args.version, - args.url, args.md5hash) - utils.print_dict(result._info) - - -def _find_aggregate(cs, aggregate): - """Get a aggregate by name or ID.""" - return utils.find_resource(cs.aggregates, aggregate) - - -def do_aggregate_list(cs, args): - """Print a list of all aggregates.""" - aggregates = cs.aggregates.list() - columns = ['Id', 'Name', 'Availability Zone'] - utils.print_list(aggregates, columns) - - -@cliutils.arg('name', metavar='', help=_('Name of aggregate.')) -@cliutils.arg( - 'availability_zone', - metavar='', - default=None, - nargs='?', - help=_('The availability zone of the aggregate (optional).')) -def do_aggregate_create(cs, args): - """Create a new aggregate with the specified details.""" - aggregate = cs.aggregates.create(args.name, args.availability_zone) - _print_aggregate_details(aggregate) - - -@cliutils.arg( - 'aggregate', - metavar='', - help=_('Name or ID of aggregate to delete.')) -def do_aggregate_delete(cs, args): - """Delete the aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - cs.aggregates.delete(aggregate) - print(_("Aggregate %s has been successfully deleted.") % aggregate.id) - - -@cliutils.arg( - 'aggregate', - metavar='', - help=_('Name or ID of aggregate to update.')) -@cliutils.arg('name', metavar='', help=_('Name of aggregate.')) -@cliutils.arg( - 'availability_zone', - metavar='', - nargs='?', - default=None, - help=_('The availability zone of the aggregate.')) -def do_aggregate_update(cs, args): - """Update the aggregate's name and optionally availability zone.""" - aggregate = _find_aggregate(cs, args.aggregate) - updates = {"name": args.name} - if args.availability_zone: - updates["availability_zone"] = args.availability_zone - - aggregate = cs.aggregates.update(aggregate.id, updates) - print(_("Aggregate %s has been successfully updated.") % aggregate.id) - _print_aggregate_details(aggregate) - - -@cliutils.arg( - 'aggregate', metavar='', - help=_('Name or ID of aggregate to update.')) -@cliutils.arg( - 'metadata', - metavar='', - nargs='+', - action='append', - default=[], - help=_('Metadata to add/update to aggregate. ' - 'Specify only the key to delete a metadata item.')) -def do_aggregate_set_metadata(cs, args): - """Update the metadata associated with the aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - metadata = _extract_metadata(args) - currentmetadata = getattr(aggregate, 'metadata', {}) - if set(metadata.items()) & set(currentmetadata.items()): - raise exceptions.CommandError(_("metadata already exists")) - for key, value in metadata.items(): - if value is None and key not in currentmetadata: - raise exceptions.CommandError(_("metadata key %s does not exist" - " hence can not be deleted") - % key) - aggregate = cs.aggregates.set_metadata(aggregate.id, metadata) - print(_("Metadata has been successfully updated for aggregate %s.") % - aggregate.id) - _print_aggregate_details(aggregate) - - -@cliutils.arg( - 'aggregate', metavar='', - help=_('Name or ID of aggregate.')) -@cliutils.arg( - 'host', metavar='', - help=_('The host to add to the aggregate.')) -def do_aggregate_add_host(cs, args): - """Add the host to the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - aggregate = cs.aggregates.add_host(aggregate.id, args.host) - print(_("Host %(host)s has been successfully added for aggregate " - "%(aggregate_id)s ") % {'host': args.host, - 'aggregate_id': aggregate.id}) - _print_aggregate_details(aggregate) - - -@cliutils.arg( - 'aggregate', metavar='', - help=_('Name or ID of aggregate.')) -@cliutils.arg( - 'host', metavar='', - help=_('The host to remove from the aggregate.')) -def do_aggregate_remove_host(cs, args): - """Remove the specified host from the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - aggregate = cs.aggregates.remove_host(aggregate.id, args.host) - print(_("Host %(host)s has been successfully removed from aggregate " - "%(aggregate_id)s ") % {'host': args.host, - 'aggregate_id': aggregate.id}) - _print_aggregate_details(aggregate) - - -@cliutils.arg( - 'aggregate', metavar='', - help=_('Name or ID of aggregate.')) -def do_aggregate_details(cs, args): - """Show details of the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - _print_aggregate_details(aggregate) - - -def _print_aggregate_details(aggregate): - columns = ['Id', 'Name', 'Availability Zone', 'Hosts', 'Metadata'] - - def parser_metadata(fields): - return utils.pretty_choice_dict(getattr(fields, 'metadata', {}) or {}) - - def parser_hosts(fields): - return cliutils.pretty_choice_list(getattr(fields, 'hosts', [])) - - formatters = { - 'Metadata': parser_metadata, - 'Hosts': parser_hosts, - } - utils.print_list([aggregate], columns, formatters=formatters) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'host', metavar='', default=None, nargs='?', - help=_('destination host name.')) -@cliutils.arg( - '--block-migrate', - action='store_true', - dest='block_migrate', - default=False, - help=_('True in case of block_migration. (Default=False:live_migration)')) -@cliutils.arg( - '--block_migrate', - action='store_true', - help=argparse.SUPPRESS) -@cliutils.arg( - '--disk-over-commit', - action='store_true', - dest='disk_over_commit', - default=False, - help=_('Allow overcommit.(Default=False)')) -@cliutils.arg( - '--disk_over_commit', - action='store_true', - help=argparse.SUPPRESS) -def do_live_migration(cs, args): - """Migrate running server to a new machine.""" - _find_server(cs, args.server).live_migrate(args.host, - args.block_migrate, - args.disk_over_commit) - - -@cliutils.arg( - 'server', metavar='', nargs='+', - help=_('Name or ID of server(s).')) -@cliutils.arg( - '--active', action='store_const', dest='state', - default='error', const='active', - help=_('Request the server be reset to "active" state instead ' - 'of "error" state (the default).')) -def do_reset_state(cs, args): - """Reset the state of a server.""" - failure_flag = False - - for server in args.server: - try: - _find_server(cs, server).reset_state(args.state) - except Exception as e: - failure_flag = True - msg = "Reset state for server %s failed: %s" % (server, e) - print(msg) - - if failure_flag: - msg = "Unable to reset the state for the specified server(s)." - raise exceptions.CommandError(msg) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_reset_network(cs, args): - """Reset network of a server.""" - _find_server(cs, args.server).reset_network() - - -@cliutils.arg( - '--host', - metavar='', - default=None, - help=_('Name of host.')) -@cliutils.arg( - '--binary', - metavar='', - default=None, - help=_('Service binary.')) -def do_service_list(cs, args): - """Show a list of all running services. Filter by host & binary.""" - result = cs.services.list(host=args.host, binary=args.binary) - columns = ["Binary", "Host", "Zone", "Status", "State", "Updated_at"] - # NOTE(sulo): we check if the response has disabled_reason - # so as not to add the column when the extended ext is not enabled. - if result and hasattr(result[0], 'disabled_reason'): - columns.append("Disabled Reason") - - # NOTE(gtt): After https://review.openstack.org/#/c/39998/ nova will - # show id in response. - if result and hasattr(result[0], 'id'): - columns.insert(0, "Id") - - utils.print_list(result, columns) - - -@cliutils.arg('host', metavar='', help=_('Name of host.')) -@cliutils.arg('binary', metavar='', help=_('Service binary.')) -def do_service_enable(cs, args): - """Enable the service.""" - result = cs.services.enable(args.host, args.binary) - utils.print_list([result], ['Host', 'Binary', 'Status']) - - -@cliutils.arg('host', metavar='', help=_('Name of host.')) -@cliutils.arg('binary', metavar='', help=_('Service binary.')) -@cliutils.arg( - '--reason', - metavar='', - help=_('Reason for disabling service.')) -def do_service_disable(cs, args): - """Disable the service.""" - if args.reason: - result = cs.services.disable_log_reason(args.host, args.binary, - args.reason) - utils.print_list([result], ['Host', 'Binary', 'Status', - 'Disabled Reason']) - else: - result = cs.services.disable(args.host, args.binary) - utils.print_list([result], ['Host', 'Binary', 'Status']) - - -@cliutils.arg('id', metavar='', help=_('Id of service.')) -def do_service_delete(cs, args): - """Delete the service.""" - cs.services.delete(args.id) - - -@cliutils.arg('fixed_ip', metavar='', help=_('Fixed IP Address.')) -def do_fixed_ip_get(cs, args): - """Retrieve info on a fixed IP.""" - result = cs.fixed_ips.get(args.fixed_ip) - utils.print_list([result], ['address', 'cidr', 'hostname', 'host']) - - -@cliutils.arg('fixed_ip', metavar='', help=_('Fixed IP Address.')) -def do_fixed_ip_reserve(cs, args): - """Reserve a fixed IP.""" - cs.fixed_ips.reserve(args.fixed_ip) - - -@cliutils.arg('fixed_ip', metavar='', help=_('Fixed IP Address.')) -def do_fixed_ip_unreserve(cs, args): - """Unreserve a fixed IP.""" - cs.fixed_ips.unreserve(args.fixed_ip) - - -@cliutils.arg('host', metavar='', help=_('Name of host.')) -def do_host_describe(cs, args): - """Describe a specific host.""" - result = cs.hosts.get(args.host) - columns = ["HOST", "PROJECT", "cpu", "memory_mb", "disk_gb"] - utils.print_list(result, columns) - - -@cliutils.arg( - '--zone', - metavar='', - default=None, - help=_('Filters the list, returning only those hosts in the availability ' - 'zone .')) -def do_host_list(cs, args): - """List all hosts by service.""" - columns = ["host_name", "service", "zone"] - result = cs.hosts.list(args.zone) - utils.print_list(result, columns) - - -@cliutils.arg('host', metavar='', help='Name of host.') -@cliutils.arg( - '--status', metavar='', default=None, dest='status', - help=_('Either enable or disable a host.')) -@cliutils.arg( - '--maintenance', - metavar='', - default=None, - dest='maintenance', - help=_('Either put or resume host to/from maintenance.')) -def do_host_update(cs, args): - """Update host settings.""" - updates = {} - columns = ["HOST"] - if args.status: - updates['status'] = args.status - columns.append("status") - if args.maintenance: - updates['maintenance_mode'] = args.maintenance - columns.append("maintenance_mode") - result = cs.hosts.update(args.host, updates) - utils.print_list([result], columns) - - -@cliutils.arg('host', metavar='', help='Name of host.') -@cliutils.arg( - '--action', metavar='', dest='action', - choices=['startup', 'shutdown', 'reboot'], - help=_('A power action: startup, reboot, or shutdown.')) -def do_host_action(cs, args): - """Perform a power action on a host.""" - result = cs.hosts.host_action(args.host, args.action) - utils.print_list([result], ['HOST', 'power_action']) - - -def _find_hypervisor(cs, hypervisor): - """Get a hypervisor by name or ID.""" - return utils.find_resource(cs.hypervisors, hypervisor) - - -@cliutils.arg( - '--matching', - metavar='', - default=None, - help=_('List hypervisors matching the given .')) -def do_hypervisor_list(cs, args): - """List hypervisors.""" - columns = ['ID', 'Hypervisor hostname', 'State', 'Status'] - if args.matching: - utils.print_list(cs.hypervisors.search(args.matching), columns) - else: - # Since we're not outputting detail data, choose - # detailed=False for server-side efficiency - utils.print_list(cs.hypervisors.list(False), columns) - - -@cliutils.arg( - 'hostname', - metavar='', - help=_('The hypervisor hostname (or pattern) to search for.')) -def do_hypervisor_servers(cs, args): - """List servers belonging to specific hypervisors.""" - hypers = cs.hypervisors.search(args.hostname, servers=True) - - class InstanceOnHyper(object): - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - # Massage the result into a list to be displayed - instances = [] - for hyper in hypers: - hyper_host = hyper.hypervisor_hostname - hyper_id = hyper.id - if hasattr(hyper, 'servers'): - instances.extend([InstanceOnHyper(id=serv['uuid'], - name=serv['name'], - hypervisor_hostname=hyper_host, - hypervisor_id=hyper_id) - for serv in hyper.servers]) - - # Output the data - utils.print_list(instances, ['ID', 'Name', 'Hypervisor ID', - 'Hypervisor Hostname']) - - -@cliutils.arg( - 'hypervisor', - metavar='', - help=_('Name or ID of the hypervisor to show the details of.')) -def do_hypervisor_show(cs, args): - """Display the details of the specified hypervisor.""" - hyper = _find_hypervisor(cs, args.hypervisor) - utils.print_dict(utils.flatten_dict(hyper._info)) - - -@cliutils.arg( - 'hypervisor', - metavar='', - help=_('Name or ID of the hypervisor to show the uptime of.')) -def do_hypervisor_uptime(cs, args): - """Display the uptime of the specified hypervisor.""" - hyper = _find_hypervisor(cs, args.hypervisor) - hyper = cs.hypervisors.uptime(hyper) - - # Output the uptime information - utils.print_dict(hyper._info.copy()) - - -def do_hypervisor_stats(cs, args): - """Get hypervisor statistics over all compute nodes.""" - stats = cs.hypervisor_stats.statistics() - utils.print_dict(stats._info.copy()) - - -def ensure_service_catalog_present(cs): - if not hasattr(cs.client, 'service_catalog'): - # Turn off token caching and re-auth - cs.client.unauthenticate() - cs.client.use_token_cache(False) - cs.client.authenticate() - - -def do_endpoints(cs, _args): - """Discover endpoints that get returned from the authenticate services.""" - if isinstance(cs.client, client.SessionClient): - auth = cs.client.auth - sc = auth.get_access(cs.client.session).service_catalog - for service in sc.get_data(): - _print_endpoints(service, cs.client.region_name) - else: - ensure_service_catalog_present(cs) - - catalog = cs.client.service_catalog.catalog - region = cs.client.region_name - for service in catalog['access']['serviceCatalog']: - _print_endpoints(service, region) - - -def _print_endpoints(service, region): - name, endpoints = service["name"], service["endpoints"] - - try: - endpoint = _get_first_endpoint(endpoints, region) - utils.print_dict(endpoint, name) - except LookupError: - print(_("WARNING: %(service)s has no endpoint in %(region)s! " - "Available endpoints for this service:") % - {'service': name, 'region': region}) - for other_endpoint in endpoints: - utils.print_dict(other_endpoint, name) - - -def _get_first_endpoint(endpoints, region): - """Find the first suitable endpoint in endpoints. - - If there is only one endpoint, return it. If there is more than - one endpoint, return the first one with the given region. If there - are no endpoints, or there is more than one endpoint but none of - them match the given region, raise KeyError. - - """ - if len(endpoints) == 1: - return endpoints[0] - else: - for candidate_endpoint in endpoints: - if candidate_endpoint["region"] == region: - return candidate_endpoint - - raise LookupError("No suitable endpoint found") - - -@cliutils.arg( - '--wrap', dest='wrap', metavar='', default=64, - help=_('wrap PKI tokens to a specified length, or 0 to disable')) -def do_credentials(cs, _args): - """Show user credentials returned from auth.""" - if isinstance(cs.client, client.SessionClient): - auth = cs.client.auth - sc = auth.get_access(cs.client.session).service_catalog - utils.print_dict(sc.catalog['user'], 'User Credentials', - wrap=int(_args.wrap)) - utils.print_dict(sc.get_token(), 'Token', wrap=int(_args.wrap)) - else: - ensure_service_catalog_present(cs) - catalog = cs.client.service_catalog.catalog - utils.print_dict(catalog['access']['user'], "User Credentials", - wrap=int(_args.wrap)) - utils.print_dict(catalog['access']['token'], "Token", - wrap=int(_args.wrap)) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - '--port', - dest='port', - action='store', - type=int, - default=22, - help=_('Optional flag to indicate which port to use for ssh. ' - '(Default=22)')) -@cliutils.arg( - '--private', - dest='private', - action='store_true', - default=False, - help=argparse.SUPPRESS) -@cliutils.arg( - '--address-type', - dest='address_type', - action='store', - type=str, - default='floating', - help=_('Optional flag to indicate which IP type to use. Possible values ' - 'includes fixed and floating (the Default).')) -@cliutils.arg( - '--network', metavar='', - help=_('Network to use for the ssh.'), default=None) -@cliutils.arg( - '--ipv6', - dest='ipv6', - action='store_true', - default=False, - help=_('Optional flag to indicate whether to use an IPv6 address ' - 'attached to a server. (Defaults to IPv4 address)')) -@cliutils.arg( - '--login', metavar='', help=_('Login to use.'), - default="root") -@cliutils.arg( - '-i', '--identity', - dest='identity', - help=_('Private key file, same as the -i option to the ssh command.'), - default='') -@cliutils.arg( - '--extra-opts', - dest='extra', - help=_('Extra options to pass to ssh. see: man ssh'), - default='') -def do_ssh(cs, args): - """SSH into a server.""" - if '@' in args.server: - user, server = args.server.split('@', 1) - args.login = user - args.server = server - - addresses = _find_server(cs, args.server).addresses - address_type = "fixed" if args.private else args.address_type - version = 6 if args.ipv6 else 4 - pretty_version = 'IPv%d' % version - - # Select the network to use. - if args.network: - network_addresses = addresses.get(args.network) - if not network_addresses: - msg = _("Server '%(server)s' is not attached to network " - "'%(network)s'") - raise exceptions.ResourceNotFound( - msg % {'server': args.server, 'network': args.network}) - else: - if len(addresses) > 1: - msg = _("Server '%(server)s' is attached to more than one network." - " Please pick the network to use.") - raise exceptions.CommandError(msg % {'server': args.server}) - elif not addresses: - msg = _("Server '%(server)s' is not attached to any network.") - raise exceptions.CommandError(msg % {'server': args.server}) - else: - network_addresses = list(six.itervalues(addresses))[0] - - # Select the address in the selected network. - # If the extension is not present, we assume the address to be floating. - match = lambda addr: all(( - addr.get('version') == version, - addr.get('OS-EXT-IPS:type', 'floating') == address_type)) - matching_addresses = [address.get('addr') - for address in network_addresses if match(address)] - if not any(matching_addresses): - msg = _("No address that would match network '%(network)s'" - " and type '%(address_type)s' of version %(pretty_version)s " - "has been found for server '%(server)s'.") - raise exceptions.ResourceNotFound(msg % { - 'network': args.network, 'address_type': address_type, - 'pretty_version': pretty_version, 'server': args.server}) - elif len(matching_addresses) > 1: - msg = _("More than one %(pretty_version)s %(address_type)s address" - "found.") - raise exceptions.CommandError(msg % {'pretty_version': pretty_version, - 'address_type': address_type}) - else: - ip_address = matching_addresses[0] - - identity = '-i %s' % args.identity if len(args.identity) else '' - - cmd = "ssh -%d -p%d %s %s@%s %s" % (version, args.port, identity, - args.login, ip_address, args.extra) - logger.debug("Executing cmd '%s'", cmd) - os.system(cmd) - - -_quota_resources = ['instances', 'cores', 'ram', - 'floating_ips', 'fixed_ips', 'metadata_items', - 'injected_files', 'injected_file_content_bytes', - 'injected_file_path_bytes', 'key_pairs', - 'security_groups', 'security_group_rules', - 'server_groups', 'server_group_members'] - - -def _quota_show(quotas): - class FormattedQuota(object): - def __init__(self, key, value): - setattr(self, 'quota', key) - setattr(self, 'limit', value) - - quota_list = [] - for resource in _quota_resources: - try: - quota = FormattedQuota(resource, getattr(quotas, resource)) - quota_list.append(quota) - except AttributeError: - pass - columns = ['Quota', 'Limit'] - utils.print_list(quota_list, columns) - - -def _quota_update(manager, identifier, args): - updates = {} - for resource in _quota_resources: - val = getattr(args, resource, None) - if val is not None: - updates[resource] = val - - if updates: - # default value of force is None to make sure this client - # will be compatibile with old nova server - force_update = getattr(args, 'force', None) - user_id = getattr(args, 'user', None) - if isinstance(manager, quotas.QuotaSetManager): - manager.update(identifier, force=force_update, user_id=user_id, - **updates) - else: - manager.update(identifier, **updates) - - -@cliutils.arg( - '--tenant', - metavar='', - default=None, - help=_('ID of tenant to list the quotas for.')) -@cliutils.arg( - '--user', - metavar='', - default=None, - help=_('ID of user to list the quotas for.')) -def do_quota_show(cs, args): - """List the quotas for a tenant/user.""" - - if args.tenant: - project_id = args.tenant - elif isinstance(cs.client, client.SessionClient): - auth = cs.client.auth - project_id = auth.get_auth_ref(cs.client.session).project_id - else: - project_id = cs.client.tenant_id - - _quota_show(cs.quotas.get(project_id, user_id=args.user)) - - -@cliutils.arg( - '--tenant', - metavar='', - default=None, - help=_('ID of tenant to list the default quotas for.')) -def do_quota_defaults(cs, args): - """List the default quotas for a tenant.""" - - if args.tenant: - project_id = args.tenant - elif isinstance(cs.client, client.SessionClient): - auth = cs.client.auth - project_id = auth.get_auth_ref(cs.client.session).project_id - else: - project_id = cs.client.tenant_id - - _quota_show(cs.quotas.defaults(project_id)) - - -@cliutils.arg( - 'tenant', - metavar='', - help=_('ID of tenant to set the quotas for.')) -@cliutils.arg( - '--user', - metavar='', - default=None, - help=_('ID of user to set the quotas for.')) -@cliutils.arg( - '--instances', - metavar='', - type=int, default=None, - help=_('New value for the "instances" quota.')) -@cliutils.arg( - '--cores', - metavar='', - type=int, default=None, - help=_('New value for the "cores" quota.')) -@cliutils.arg( - '--ram', - metavar='', - type=int, default=None, - help=_('New value for the "ram" quota.')) -@cliutils.arg( - '--floating-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "floating-ips" quota.')) -@cliutils.arg( - '--floating_ips', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--fixed-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "fixed-ips" quota.')) -@cliutils.arg( - '--metadata-items', - metavar='', - type=int, - default=None, - help=_('New value for the "metadata-items" quota.')) -@cliutils.arg( - '--metadata_items', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--injected-files', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-files" quota.')) -@cliutils.arg( - '--injected_files', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--injected-file-content-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-content-bytes" quota.')) -@cliutils.arg( - '--injected_file_content_bytes', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--injected-file-path-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-path-bytes" quota.')) -@cliutils.arg( - '--key-pairs', - metavar='', - type=int, - default=None, - help=_('New value for the "key-pairs" quota.')) -@cliutils.arg( - '--security-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "security-groups" quota.')) -@cliutils.arg( - '--security-group-rules', - metavar='', - type=int, - default=None, - help=_('New value for the "security-group-rules" quota.')) -@cliutils.arg( - '--server-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "server-groups" quota.')) -@cliutils.arg( - '--server-group-members', - metavar='', - type=int, - default=None, - help=_('New value for the "server-group-members" quota.')) -@cliutils.arg( - '--force', - dest='force', - action="store_true", - default=None, - help=_('Whether force update the quota even if the already used and ' - 'reserved exceeds the new quota')) -def do_quota_update(cs, args): - """Update the quotas for a tenant/user.""" - - _quota_update(cs.quotas, args.tenant, args) - - -@cliutils.arg( - '--tenant', - metavar='', - required=True, - help=_('ID of tenant to delete quota for.')) -@cliutils.arg( - '--user', - metavar='', - help=_('ID of user to delete quota for.')) -def do_quota_delete(cs, args): - """Delete quota for a tenant/user so their quota will Revert - back to default. - """ - - cs.quotas.delete(args.tenant, user_id=args.user) - - -@cliutils.arg( - 'class_name', - metavar='', - help=_('Name of quota class to list the quotas for.')) -def do_quota_class_show(cs, args): - """List the quotas for a quota class.""" - - _quota_show(cs.quota_classes.get(args.class_name)) - - -@cliutils.arg( - 'class_name', - metavar='', - help=_('Name of quota class to set the quotas for.')) -@cliutils.arg( - '--instances', - metavar='', - type=int, default=None, - help=_('New value for the "instances" quota.')) -@cliutils.arg( - '--cores', - metavar='', - type=int, default=None, - help=_('New value for the "cores" quota.')) -@cliutils.arg( - '--ram', - metavar='', - type=int, default=None, - help=_('New value for the "ram" quota.')) -@cliutils.arg( - '--floating-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "floating-ips" quota.')) -@cliutils.arg( - '--floating_ips', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--fixed-ips', - metavar='', - type=int, - default=None, - help=_('New value for the "fixed-ips" quota.')) -@cliutils.arg( - '--metadata-items', - metavar='', - type=int, - default=None, - help=_('New value for the "metadata-items" quota.')) -@cliutils.arg( - '--metadata_items', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--injected-files', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-files" quota.')) -@cliutils.arg( - '--injected_files', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--injected-file-content-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-content-bytes" quota.')) -@cliutils.arg( - '--injected_file_content_bytes', - type=int, - help=argparse.SUPPRESS) -@cliutils.arg( - '--injected-file-path-bytes', - metavar='', - type=int, - default=None, - help=_('New value for the "injected-file-path-bytes" quota.')) -@cliutils.arg( - '--key-pairs', - metavar='', - type=int, - default=None, - help=_('New value for the "key-pairs" quota.')) -@cliutils.arg( - '--security-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "security-groups" quota.')) -@cliutils.arg( - '--security-group-rules', - metavar='', - type=int, - default=None, - help=_('New value for the "security-group-rules" quota.')) -@cliutils.arg( - '--server-groups', - metavar='', - type=int, - default=None, - help=_('New value for the "server-groups" quota.')) -@cliutils.arg( - '--server-group-members', - metavar='', - type=int, - default=None, - help=_('New value for the "server-group-members" quota.')) -def do_quota_class_update(cs, args): - """Update the quotas for a quota class.""" - - _quota_update(cs.quota_classes, args.class_name, args) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - 'host', metavar='', nargs='?', - help=_("Name or ID of the target host. " - "If no host is specified, the scheduler will choose one.")) -@cliutils.arg( - '--password', - dest='password', - metavar='', - help=_("Set the provided admin password on the evacuated server. Not" - " applicable with on-shared-storage flag")) -@cliutils.arg( - '--on-shared-storage', - dest='on_shared_storage', - action="store_true", - default=False, - help=_('Specifies whether server files are located on shared storage')) -def do_evacuate(cs, args): - """Evacuate server from failed host.""" - - server = _find_server(cs, args.server) - - res = server.evacuate(args.host, args.on_shared_storage, args.password)[1] - if type(res) is dict: - utils.print_dict(res) - - -def _print_interfaces(interfaces): - columns = ['Port State', 'Port ID', 'Net ID', 'IP addresses', - 'MAC Addr'] - - class FormattedInterface(object): - def __init__(self, interface): - for col in columns: - key = col.lower().replace(" ", "_") - if hasattr(interface, key): - setattr(self, key, getattr(interface, key)) - self.ip_addresses = ",".join([fip['ip_address'] - for fip in interface.fixed_ips]) - utils.print_list([FormattedInterface(i) for i in interfaces], columns) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -def do_interface_list(cs, args): - """List interfaces attached to a server.""" - server = _find_server(cs, args.server) - - res = server.interface_list() - if type(res) is list: - _print_interfaces(res) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg( - '--port-id', - metavar='', - help=_('Port ID.'), - dest="port_id") -@cliutils.arg( - '--net-id', - metavar='', - help=_('Network ID'), - default=None, dest="net_id") -@cliutils.arg( - '--fixed-ip', - metavar='', - help=_('Requested fixed IP.'), - default=None, dest="fixed_ip") -def do_interface_attach(cs, args): - """Attach a network interface to a server.""" - server = _find_server(cs, args.server) - - res = server.interface_attach(args.port_id, args.net_id, args.fixed_ip) - if type(res) is dict: - utils.print_dict(res) - - -@cliutils.arg('server', metavar='', help=_('Name or ID of server.')) -@cliutils.arg('port_id', metavar='', help=_('Port ID.')) -def do_interface_detach(cs, args): - """Detach a network interface from a server.""" - server = _find_server(cs, args.server) - - res = server.interface_detach(args.port_id) - if type(res) is dict: - utils.print_dict(res) - - -def _treeizeAvailabilityZone(zone): - """Build a tree view for availability zones.""" - AvailabilityZone = availability_zones.AvailabilityZone - - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - result = [] - - # Zone tree view item - az.zoneName = zone.zoneName - az.zoneState = ('available' - if zone.zoneState['available'] else 'not available') - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - if zone.hosts is not None: - zone_hosts = sorted(zone.hosts.items(), key=lambda x: x[0]) - for (host, services) in zone_hosts: - # Host tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '|- %s' % host - az.zoneState = '' - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - - for (svc, state) in services.items(): - # Service tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zoneName = '| |- %s' % svc - az.zoneState = '%s %s %s' % ( - 'enabled' if state['active'] else 'disabled', - ':-)' if state['available'] else 'XXX', - state['updated_at']) - az._info['zoneName'] = az.zoneName - az._info['zoneState'] = az.zoneState - result.append(az) - return result - - -@cliutils.service_type('compute') -def do_availability_zone_list(cs, _args): - """List all the availability zones.""" - try: - availability_zones = cs.availability_zones.list() - except exceptions.Forbidden as e: # policy doesn't allow probably - try: - availability_zones = cs.availability_zones.list(detailed=False) - except Exception: - raise e - - result = [] - for zone in availability_zones: - result += _treeizeAvailabilityZone(zone) - _translate_availability_zone_keys(result) - utils.print_list(result, ['Name', 'Status'], - sortby_index=None) - - -def _print_server_group_details(server_group): - columns = ['Id', 'Name', 'Policies', 'Members', 'Metadata'] - utils.print_list(server_group, columns) - - -def do_server_group_list(cs, args): - """Print a list of all server groups.""" - server_groups = cs.server_groups.list() - _print_server_group_details(server_groups) - - -def do_secgroup_list_default_rules(cs, args): - """List rules for the default security group.""" - _print_secgroup_rules(cs.security_group_default_rules.list(), - show_source_group=False) - - -@cliutils.arg( - 'ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@cliutils.arg( - 'from_port', - metavar='', - help=_('Port at start of range.')) -@cliutils.arg( - 'to_port', - metavar='', - help=_('Port at end of range.')) -@cliutils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_add_default_rule(cs, args): - """Add a rule to the default security group.""" - rule = cs.security_group_default_rules.create(args.ip_proto, - args.from_port, - args.to_port, - args.cidr) - _print_secgroup_rules([rule], show_source_group=False) - - -@cliutils.arg( - 'ip_proto', - metavar='', - help=_('IP protocol (icmp, tcp, udp).')) -@cliutils.arg( - 'from_port', - metavar='', - help=_('Port at start of range.')) -@cliutils.arg( - 'to_port', - metavar='', - help=_('Port at end of range.')) -@cliutils.arg('cidr', metavar='', help=_('CIDR for address range.')) -def do_secgroup_delete_default_rule(cs, args): - """Delete a rule from the default security group.""" - for rule in cs.security_group_default_rules.list(): - if (rule.ip_protocol and - rule.ip_protocol.upper() == args.ip_proto.upper() and - rule.from_port == int(args.from_port) and - rule.to_port == int(args.to_port) and - rule.ip_range['cidr'] == args.cidr): - _print_secgroup_rules([rule], show_source_group=False) - return cs.security_group_default_rules.delete(rule.id) - - raise exceptions.CommandError(_("Rule not found")) - - -@cliutils.arg('name', metavar='', help='Server group name.') -# NOTE(wingwj): The '--policy' way is still reserved here for preserving -# the backwards compatibility of CLI, even if a user won't get this usage -# in '--help' description. It will be deprecated after an suitable deprecation -# period(probably 2 coordinated releases or so). -# -# Moreover, we imagine that a given user will use only positional parameters or -# only the "--policy" option. So we don't need to properly handle -# the possibility that they might mix them here. That usage is unsupported. -# The related discussion can be found in -# https://review.openstack.org/#/c/96382/2/. -@cliutils.arg( - 'policy', - metavar='', - default=argparse.SUPPRESS, - nargs='*', - help='Policies for the server groups ("affinity" or "anti-affinity")') -@cliutils.arg( - '--policy', - default=[], - action='append', - help=argparse.SUPPRESS) -def do_server_group_create(cs, args): - """Create a new server group with the specified details.""" - if not args.policy: - raise exceptions.CommandError(_("at least one policy must be " - "specified")) - kwargs = {'name': args.name, - 'policies': args.policy} - server_group = cs.server_groups.create(**kwargs) - _print_server_group_details([server_group]) - - -@cliutils.arg( - 'id', - metavar='', - nargs='+', - help="Unique ID(s) of the server group to delete") -def do_server_group_delete(cs, args): - """Delete specific server group(s).""" - failure_count = 0 - - for sg in args.id: - try: - cs.server_groups.delete(sg) - print(_("Server group %s has been successfully deleted.") % sg) - except Exception as e: - failure_count += 1 - print(_("Delete for server group %(sg)s failed: %(e)s") % - {'sg': sg, 'e': e}) - if failure_count == len(args.id): - raise exceptions.CommandError(_("Unable to delete any of the " - "specified server groups.")) - - -@cliutils.arg( - 'id', - metavar='', - help="Unique ID of the server group to get") -def do_server_group_get(cs, args): - """Get a specific server group.""" - server_group = cs.server_groups.get(args.id) - _print_server_group_details([server_group]) - - -def do_version_list(cs, args): - """List all API versions.""" - result = cs.versions.list() - columns = ["Id", "Status", "Updated"] - utils.print_list(result, columns) diff --git a/awx/lib/site-packages/novaclient/v2/usage.py b/awx/lib/site-packages/novaclient/v2/usage.py deleted file mode 100644 index 585ce11653..0000000000 --- a/awx/lib/site-packages/novaclient/v2/usage.py +++ /dev/null @@ -1,61 +0,0 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Usage interface. -""" - -from novaclient import base - - -class Usage(base.Resource): - """ - Usage contains information about a tenant's physical resource usage - """ - def __repr__(self): - return "" - - -class UsageManager(base.ManagerWithFind): - """ - Manage :class:`Usage` resources. - """ - resource_class = Usage - - def list(self, start, end, detailed=False): - """ - Get usage for all tenants - - :param start: :class:`datetime.datetime` Start date - :param end: :class:`datetime.datetime` End date - :param detailed: Whether to include information about each - instance whose usage is part of the report - :rtype: list of :class:`Usage`. - """ - return self._list( - "/os-simple-tenant-usage?start=%s&end=%s&detailed=%s" % - (start.isoformat(), end.isoformat(), int(bool(detailed))), - "tenant_usages") - - def get(self, tenant_id, start, end): - """ - Get usage for a specific tenant. - - :param tenant_id: Tenant ID to fetch usage for - :param start: :class:`datetime.datetime` Start date - :param end: :class:`datetime.datetime` End date - :rtype: :class:`Usage` - """ - return self._get("/os-simple-tenant-usage/%s?start=%s&end=%s" % - (tenant_id, start.isoformat(), end.isoformat()), - "tenant_usage") diff --git a/awx/lib/site-packages/novaclient/v2/versions.py b/awx/lib/site-packages/novaclient/v2/versions.py deleted file mode 100644 index 5ab09a103a..0000000000 --- a/awx/lib/site-packages/novaclient/v2/versions.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2014 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -version interface -""" - -from novaclient import base - - -class Version(base.Resource): - """ - Compute REST API information - """ - def __repr__(self): - return "" - - -class VersionManager(base.ManagerWithFind): - resource_class = Version - - def list(self): - """List all versions.""" - return self._list(None, "versions") diff --git a/awx/lib/site-packages/novaclient/v2/virtual_interfaces.py b/awx/lib/site-packages/novaclient/v2/virtual_interfaces.py deleted file mode 100644 index 9c04e8d866..0000000000 --- a/awx/lib/site-packages/novaclient/v2/virtual_interfaces.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Virtual Interfaces (1.1 extension). -""" - -from novaclient import base - - -class VirtualInterface(base.Resource): - def __repr__(self): - pass - - -class VirtualInterfaceManager(base.ManagerWithFind): - resource_class = VirtualInterface - - def list(self, instance_id): - return self._list('/servers/%s/os-virtual-interfaces' % instance_id, - 'virtual_interfaces') diff --git a/awx/lib/site-packages/novaclient/v2/volume_snapshots.py b/awx/lib/site-packages/novaclient/v2/volume_snapshots.py deleted file mode 100644 index d3bc91808f..0000000000 --- a/awx/lib/site-packages/novaclient/v2/volume_snapshots.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2011 Denali Systems, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume snapshot interface (1.1 extension). -""" - -from novaclient import base - - -class Snapshot(base.Resource): - """ - A Snapshot is a point-in-time snapshot of an openstack volume. - """ - NAME_ATTR = 'display_name' - - def __repr__(self): - return "" % self.id - - def delete(self): - """ - Delete this snapshot. - """ - self.manager.delete(self) - - -class SnapshotManager(base.ManagerWithFind): - """ - Manage :class:`Snapshot` resources. - """ - resource_class = Snapshot - - def create(self, volume_id, force=False, display_name=None, - display_description=None): - - """ - Create a snapshot of the given volume. - - :param volume_id: The ID of the volume to snapshot. - :param force: If force is True, create a snapshot even if the volume is - attached to an instance. Default is False. - :param display_name: Name of the snapshot - :param display_description: Description of the snapshot - :rtype: :class:`Snapshot` - """ - body = {'snapshot': {'volume_id': volume_id, - 'force': force, - 'display_name': display_name, - 'display_description': display_description}} - return self._create('/snapshots', body, 'snapshot') - - def get(self, snapshot_id): - """ - Get a snapshot. - - :param snapshot_id: The ID of the snapshot to get. - :rtype: :class:`Snapshot` - """ - return self._get("/snapshots/%s" % snapshot_id, "snapshot") - - def list(self, detailed=True): - """ - Get a list of all snapshots. - - :rtype: list of :class:`Snapshot` - """ - if detailed is True: - return self._list("/snapshots/detail", "snapshots") - else: - return self._list("/snapshots", "snapshots") - - def delete(self, snapshot): - """ - Delete a snapshot. - - :param snapshot: The :class:`Snapshot` to delete. - """ - self._delete("/snapshots/%s" % base.getid(snapshot)) diff --git a/awx/lib/site-packages/novaclient/v2/volume_types.py b/awx/lib/site-packages/novaclient/v2/volume_types.py deleted file mode 100644 index 3d1c7f5316..0000000000 --- a/awx/lib/site-packages/novaclient/v2/volume_types.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2011 Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -""" -Volume Type interface. -""" - -from novaclient import base - - -class VolumeType(base.Resource): - """ - A Volume Type is the type of volume to be created - """ - def __repr__(self): - return "" % self.name - - -class VolumeTypeManager(base.ManagerWithFind): - """ - Manage :class:`VolumeType` resources. - """ - resource_class = VolumeType - - def list(self): - """ - Get a list of all volume types. - - :rtype: list of :class:`VolumeType`. - """ - return self._list("/types", "volume_types") - - def get(self, volume_type): - """ - Get a specific volume type. - - :param volume_type: The ID of the :class:`VolumeType` to get. - :rtype: :class:`VolumeType` - """ - return self._get("/types/%s" % base.getid(volume_type), "volume_type") - - def delete(self, volume_type): - """ - Delete a specific volume_type. - - :param volume_type: The ID of the :class:`VolumeType` to get. - """ - self._delete("/types/%s" % base.getid(volume_type)) - - def create(self, name): - """ - Create a volume type. - - :param name: Descriptive name of the volume type - :rtype: :class:`VolumeType` - """ - - body = { - "volume_type": { - "name": name, - } - } - - return self._create("/types", body, "volume_type") diff --git a/awx/lib/site-packages/novaclient/v2/volumes.py b/awx/lib/site-packages/novaclient/v2/volumes.py deleted file mode 100644 index 9b9cf18862..0000000000 --- a/awx/lib/site-packages/novaclient/v2/volumes.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright 2011 Denali Systems, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume interface (1.1 extension). -""" - -import six -from six.moves.urllib import parse - -from novaclient import base - - -class Volume(base.Resource): - """ - A volume is an extra block level storage to the OpenStack instances. - """ - NAME_ATTR = 'display_name' - - def __repr__(self): - return "" % self.id - - def delete(self): - """ - Delete this volume. - """ - self.manager.delete(self) - - -class VolumeManager(base.ManagerWithFind): - """ - Manage :class:`Volume` resources. - """ - resource_class = Volume - - def create(self, size, snapshot_id=None, display_name=None, - display_description=None, volume_type=None, - availability_zone=None, imageRef=None): - """ - Create a volume. - - :param size: Size of volume in GB - :param snapshot_id: ID of the snapshot - :param display_name: Name of the volume - :param display_description: Description of the volume - :param volume_type: Type of volume - :param availability_zone: Availability Zone for volume - :rtype: :class:`Volume` - :param imageRef: reference to an image stored in glance - """ - body = {'volume': {'size': size, - 'snapshot_id': snapshot_id, - 'display_name': display_name, - 'display_description': display_description, - 'volume_type': volume_type, - 'availability_zone': availability_zone, - 'imageRef': imageRef}} - return self._create('/volumes', body, 'volume') - - def get(self, volume_id): - """ - Get a volume. - - :param volume_id: The ID of the volume to get. - :rtype: :class:`Volume` - """ - return self._get("/volumes/%s" % volume_id, "volume") - - def list(self, detailed=True, search_opts=None): - """ - Get a list of all volumes. - - :rtype: list of :class:`Volume` - """ - search_opts = search_opts or {} - - qparams = dict((k, v) for (k, v) in six.iteritems(search_opts) if v) - - query_string = '?%s' % parse.urlencode(qparams) if qparams else '' - - if detailed is True: - return self._list("/volumes/detail%s" % query_string, "volumes") - else: - return self._list("/volumes%s" % query_string, "volumes") - - def delete(self, volume): - """ - Delete a volume. - - :param volume: The :class:`Volume` to delete. - """ - self._delete("/volumes/%s" % base.getid(volume)) - - def create_server_volume(self, server_id, volume_id, device): - """ - Attach a volume identified by the volume ID to the given server ID - - :param server_id: The ID of the server - :param volume_id: The ID of the volume to attach. - :param device: The device name - :rtype: :class:`Volume` - """ - body = {'volumeAttachment': {'volumeId': volume_id, - 'device': device}} - return self._create("/servers/%s/os-volume_attachments" % server_id, - body, "volumeAttachment") - - def update_server_volume(self, server_id, attachment_id, new_volume_id): - """ - Update the volume identified by the attachment ID, that is attached to - the given server ID - - :param server_id: The ID of the server - :param attachment_id: The ID of the attachment - :param new_volume_id: The ID of the new volume to attach - :rtype: :class:`Volume` - """ - body = {'volumeAttachment': {'volumeId': new_volume_id}} - return self._update("/servers/%s/os-volume_attachments/%s" % - (server_id, attachment_id,), - body, "volumeAttachment") - - def get_server_volume(self, server_id, attachment_id): - """ - Get the volume identified by the attachment ID, that is attached to - the given server ID - - :param server_id: The ID of the server - :param attachment_id: The ID of the attachment - :rtype: :class:`Volume` - """ - return self._get("/servers/%s/os-volume_attachments/%s" % (server_id, - attachment_id,), "volumeAttachment") - - def get_server_volumes(self, server_id): - """ - Get a list of all the attached volumes for the given server ID - - :param server_id: The ID of the server - :rtype: list of :class:`Volume` - """ - return self._list("/servers/%s/os-volume_attachments" % server_id, - "volumeAttachments") - - def delete_server_volume(self, server_id, attachment_id): - """ - Detach a volume identified by the attachment ID from the given server - - :param server_id: The ID of the server - :param attachment_id: The ID of the attachment - """ - self._delete("/servers/%s/os-volume_attachments/%s" % - (server_id, attachment_id,)) diff --git a/awx/lib/site-packages/novaclient/v3/__init__.py b/awx/lib/site-packages/novaclient/v3/__init__.py deleted file mode 100644 index a442be1095..0000000000 --- a/awx/lib/site-packages/novaclient/v3/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2012 OpenStack Foundation -# -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.v3.client import Client # noqa diff --git a/awx/lib/site-packages/novaclient/v3/agents.py b/awx/lib/site-packages/novaclient/v3/agents.py deleted file mode 100644 index f26bba3fa4..0000000000 --- a/awx/lib/site-packages/novaclient/v3/agents.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2012 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -agent interface -""" - -from novaclient.v1_1 import agents - - -class Agent(agents.Agent): - pass - - -class AgentsManager(agents.AgentsManager): - resource_class = Agent - - def _build_update_body(self, version, url, md5hash): - return {'agent': { - 'version': version, - 'url': url, - 'md5hash': md5hash}} diff --git a/awx/lib/site-packages/novaclient/v3/aggregates.py b/awx/lib/site-packages/novaclient/v3/aggregates.py deleted file mode 100644 index b2728d6d18..0000000000 --- a/awx/lib/site-packages/novaclient/v3/aggregates.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Aggregate interface.""" - -from novaclient.v1_1 import aggregates - - -class Aggregate(aggregates.Aggregate): - pass - - -class AggregateManager(aggregates.AggregateManager): - resource_class = Aggregate diff --git a/awx/lib/site-packages/novaclient/v3/availability_zones.py b/awx/lib/site-packages/novaclient/v3/availability_zones.py deleted file mode 100644 index bd2a9d2393..0000000000 --- a/awx/lib/site-packages/novaclient/v3/availability_zones.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Availability Zone interface. -""" - -from novaclient.v1_1 import availability_zones - - -class AvailabilityZone(availability_zones.AvailabilityZone): - pass - - -class AvailabilityZoneManager(availability_zones.AvailabilityZoneManager): - """ - Manage :class:`AvailabilityZone` resources. - """ - resource_class = AvailabilityZone - return_parameter_name = 'availability_zone_info' diff --git a/awx/lib/site-packages/novaclient/v3/certs.py b/awx/lib/site-packages/novaclient/v3/certs.py deleted file mode 100644 index 5e67851089..0000000000 --- a/awx/lib/site-packages/novaclient/v3/certs.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Certificate interface. -""" - -from novaclient.v1_1 import certs - - -class Certificate(certs.Certificate): - pass - - -class CertificateManager(certs.CertificateManager): - pass diff --git a/awx/lib/site-packages/novaclient/v3/client.py b/awx/lib/site-packages/novaclient/v3/client.py deleted file mode 100644 index a30f9191e1..0000000000 --- a/awx/lib/site-packages/novaclient/v3/client.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient import client -from novaclient.v3 import agents -from novaclient.v3 import aggregates -from novaclient.v3 import availability_zones -from novaclient.v3 import certs -from novaclient.v3 import flavor_access -from novaclient.v3 import flavors -from novaclient.v3 import hosts -from novaclient.v3 import hypervisors -from novaclient.v3 import images -from novaclient.v3 import keypairs -from novaclient.v3 import list_extensions -from novaclient.v3 import quotas -from novaclient.v3 import servers -from novaclient.v3 import services -from novaclient.v3 import usage -from novaclient.v3 import volumes - - -class Client(object): - """ - Top-level object to access the OpenStack Compute API. - - Create an instance with your creds:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) - - Or, alternatively, you can create a client instance using the - keystoneclient.session API:: - - >>> from keystoneclient.auth.identity import v2 - >>> from keystoneclient import session - >>> from novaclient.client import Client - >>> auth = v2.Password(auth_url=AUTH_URL, - username=USERNAME, - password=PASSWORD, - tenant_name=PROJECT_ID) - >>> sess = session.Session(auth=auth) - >>> nova = client.Client(VERSION, session=sess) - - Then call methods on its managers:: - - >>> client.servers.list() - ... - >>> client.flavors.list() - ... - - It is also possible to use an instance as a context manager in which - case there will be a session kept alive for the duration of the with - statement:: - - >>> with Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) as client: - ... client.servers.list() - ... client.flavors.list() - ... - - It is also possible to have a permanent (process-long) connection pool, - by passing a connection_pool=True:: - - >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, - ... AUTH_URL, connection_pool=True) - """ - - def __init__(self, username=None, password=None, project_id=None, - auth_url=None, insecure=False, timeout=None, - proxy_tenant_id=None, proxy_token=None, region_name=None, - endpoint_type='publicURL', extensions=None, - service_type='computev3', service_name=None, - volume_service_name=None, timings=False, bypass_url=None, - os_cache=False, no_cache=True, http_log_debug=False, - auth_system='keystone', auth_plugin=None, auth_token=None, - cacert=None, tenant_id=None, user_id=None, - connection_pool=False, session=None, auth=None, - completion_cache=None): - # NOTE(cyeoh): In the novaclient context (unlike Nova) the - # project_id is not the same as the tenant_id. Here project_id - # is a name (what the Nova API often refers to as a project or - # tenant name) and tenant_id is a UUID (what the Nova API - # often refers to as a project_id or tenant_id). - - self.projectid = project_id - self.tenant_id = tenant_id - self.user_id = user_id - self.os_cache = os_cache or not no_cache - # TODO(bnemec): Add back in v3 extensions - self.agents = agents.AgentsManager(self) - self.aggregates = aggregates.AggregateManager(self) - self.availability_zones = \ - availability_zones.AvailabilityZoneManager(self) - self.certs = certs.CertificateManager(self) - self.list_extensions = list_extensions.ListExtManager(self) - self.hosts = hosts.HostManager(self) - self.flavors = flavors.FlavorManager(self) - self.flavor_access = flavor_access.FlavorAccessManager(self) - self.hypervisors = hypervisors.HypervisorManager(self) - self.images = images.ImageManager(self) - self.keypairs = keypairs.KeypairManager(self) - self.quotas = quotas.QuotaSetManager(self) - self.servers = servers.ServerManager(self) - self.services = services.ServiceManager(self) - self.usage = usage.UsageManager(self) - self.volumes = volumes.VolumeManager(self) - - # Add in any extensions... - if extensions: - for extension in extensions: - if extension.manager_class: - setattr(self, extension.name, - extension.manager_class(self)) - - self.client = client._construct_http_client( - username=username, - password=password, - user_id=user_id, - project_id=project_id, - tenant_id=tenant_id, - auth_url=auth_url, - auth_token=auth_token, - insecure=insecure, - timeout=timeout, - auth_system=auth_system, - auth_plugin=auth_plugin, - proxy_token=proxy_token, - proxy_tenant_id=proxy_tenant_id, - region_name=region_name, - endpoint_type=endpoint_type, - service_type=service_type, - service_name=service_name, - volume_service_name=volume_service_name, - timings=timings, - bypass_url=bypass_url, - os_cache=self.os_cache, - http_log_debug=http_log_debug, - cacert=cacert, - connection_pool=connection_pool, - session=session, - auth=auth) - - self.completion_cache = completion_cache - - def write_object_to_completion_cache(self, obj): - if self.completion_cache: - self.completion_cache.write_object(obj) - - def clear_completion_cache_for_class(self, obj_class): - if self.completion_cache: - self.completion_cache.clear_class(obj_class) - - @client._original_only - def __enter__(self): - self.client.open_session() - return self - - @client._original_only - def __exit__(self, t, v, tb): - self.client.close_session() - - @client._original_only - def set_management_url(self, url): - self.client.set_management_url(url) - - @client._original_only - def get_timings(self): - return self.client.get_timings() - - @client._original_only - def reset_timings(self): - self.client.reset_timings() - - @client._original_only - def authenticate(self): - """ - Authenticate against the server. - - Normally this is called automatically when you first access the API, - but you can call this method to force authentication right now. - - Returns on success; raises :exc:`exceptions.Unauthorized` if the - credentials are wrong. - """ - self.client.authenticate() diff --git a/awx/lib/site-packages/novaclient/v3/flavor_access.py b/awx/lib/site-packages/novaclient/v3/flavor_access.py deleted file mode 100644 index 6896dac364..0000000000 --- a/awx/lib/site-packages/novaclient/v3/flavor_access.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Flavor access interface.""" - -from novaclient import base -from novaclient.v1_1 import flavor_access - - -class FlavorAccess(flavor_access.FlavorAccess): - pass - - -class FlavorAccessManager(flavor_access.FlavorAccessManager): - """ - Manage :class:`FlavorAccess` resources. - """ - resource_class = FlavorAccess - - def _list_by_flavor(self, flavor): - return self._list('/flavors/%s/flavor-access' % base.getid(flavor), - 'flavor_access') - - def add_tenant_access(self, flavor, tenant): - """Add a tenant to the given flavor access list.""" - info = {'tenant_id': tenant} - return self._action('add_tenant_access', flavor, info) - - def remove_tenant_access(self, flavor, tenant): - """Remove a tenant from the given flavor access list.""" - info = {'tenant_id': tenant} - return self._action('remove_tenant_access', flavor, info) diff --git a/awx/lib/site-packages/novaclient/v3/flavors.py b/awx/lib/site-packages/novaclient/v3/flavors.py deleted file mode 100644 index e65f2f1f4e..0000000000 --- a/awx/lib/site-packages/novaclient/v3/flavors.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Flavor interface. -""" - -from novaclient import base -from novaclient import utils -from novaclient.v1_1 import flavors - - -class Flavor(base.Resource): - """ - A flavor is an available hardware configuration for a server. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.name - - @property - def is_public(self): - """ - Provide a user-friendly accessor to flavor-access:is_public - """ - return self._info.get("flavor-access:is_public", 'N/A') - - def get_keys(self): - """ - Get extra specs from a flavor. - - :param flavor: The :class:`Flavor` to get extra specs from - """ - _resp, body = self.manager.api.client.get( - "/flavors/%s/flavor-extra-specs" % - base.getid(self)) - return body["extra_specs"] - - def set_keys(self, metadata): - """ - Set extra specs on a flavor. - - :param flavor: The :class:`Flavor` to set extra spec on - :param metadata: A dict of key/value pairs to be set - """ - utils.validate_flavor_metadata_keys(metadata.keys()) - - body = {'extra_specs': metadata} - return self.manager._create( - "/flavors/%s/flavor-extra-specs" % - base.getid(self), body, "extra_specs", - return_raw=True) - - def unset_keys(self, keys): - """ - Unset extra specs on a flavor. - - :param flavor: The :class:`Flavor` to unset extra spec on - :param keys: A list of keys to be unset - """ - for k in keys: - self.manager._delete( - "/flavors/%s/flavor-extra-specs/%s" % ( - base.getid(self), k)) - - def delete(self): - """ - Delete this flavor. - """ - self.manager.delete(self) - - -class FlavorManager(flavors.FlavorManager): - resource_class = Flavor - - def _build_body(self, name, ram, vcpus, disk, id, swap, - ephemeral, rxtx_factor, is_public): - return { - "flavor": { - "name": name, - "ram": ram, - "vcpus": vcpus, - "disk": disk, - "id": id, - "swap": swap, - "ephemeral": ephemeral, - "os-flavor-rxtx:rxtx_factor": rxtx_factor, - "flavor-access:is_public": is_public, - } - } diff --git a/awx/lib/site-packages/novaclient/v3/hosts.py b/awx/lib/site-packages/novaclient/v3/hosts.py deleted file mode 100644 index 174b623342..0000000000 --- a/awx/lib/site-packages/novaclient/v3/hosts.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2013 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" V3 API versions of the Hosts interface. - -Inherits from the 1.1 code because a lot of the functionality is shared. -""" - -from novaclient.v1_1 import hosts - - -Host = hosts.Host - - -class HostManager(hosts.HostManager): - def update(self, host, values): - """Update status or maintenance mode for the host.""" - body = dict(host=values) - return self._update("/os-hosts/%s" % host, body, response_key='host') - - def host_action(self, host, action): - """Perform an action on a host.""" - url = '/os-hosts/{0}/{1}'.format(host, action) - return self._get(url, response_key='host') - - def list(self, zone=None, service=None): - """List cloud hosts.""" - - filters = [] - if zone: - filters.append('zone=%s' % zone) - if service: - filters.append('service=%s' % service) - - if filters: - url = '/os-hosts?%s' % '&'.join(filters) - else: - url = '/os-hosts' - - return self._list(url, "hosts") diff --git a/awx/lib/site-packages/novaclient/v3/hypervisors.py b/awx/lib/site-packages/novaclient/v3/hypervisors.py deleted file mode 100644 index b04a600802..0000000000 --- a/awx/lib/site-packages/novaclient/v3/hypervisors.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2013 IBM Corp -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Hypervisors interface -""" - -from six.moves.urllib import parse - -from novaclient.v1_1 import hypervisors - - -class Hypervisor(hypervisors.Hypervisor): - pass - - -class HypervisorManager(hypervisors.HypervisorManager): - resource_class = Hypervisor - - def search(self, hypervisor_match): - """ - Get a list of matching hypervisors. - - :param servers: If True, server information is also retrieved. - """ - url = ('/os-hypervisors/search?query=%s' % - parse.quote(hypervisor_match, safe='')) - return self._list(url, 'hypervisors') - - def servers(self, hypervisor): - """ - Get servers for a specific hypervisor - - :param hypervisor: ID of hypervisor to get list of servers for. - """ - return self._get('/os-hypervisors/%s/servers' % hypervisor, - 'hypervisor') diff --git a/awx/lib/site-packages/novaclient/v3/images.py b/awx/lib/site-packages/novaclient/v3/images.py deleted file mode 100644 index 7bc3d584c7..0000000000 --- a/awx/lib/site-packages/novaclient/v3/images.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Image interface. -""" - -from oslo.utils import encodeutils -from oslo.utils import strutils -from six.moves.urllib import parse - -from novaclient import base - - -class Image(base.Resource): - """ - An image is a collection of files used to create or rebuild a server. - """ - HUMAN_ID = True - - def __repr__(self): - return "" % self.name - - def delete(self): - """ - Delete this image. - """ - self.manager.delete(self) - - -class ImageManager(base.ManagerWithFind): - """ - Manage :class:`Image` resources. - """ - resource_class = Image - # NOTE(cyeoh): Eventually we'll want novaclient to be smart - # enough to do version discovery, but for now we just request - # the v1 image API - image_api_prefix = '/v1' - - def _image_meta_from_headers(self, headers): - meta = {'properties': {}} - safe_decode = encodeutils.safe_decode - for key, value in headers.items(): - value = safe_decode(value, incoming='utf-8') - if key.startswith('x-image-meta-property-'): - _key = safe_decode(key[22:], incoming='utf-8') - meta['properties'][_key] = value - elif key.startswith('x-image-meta-'): - _key = safe_decode(key[13:], incoming='utf-8') - meta[_key] = value - - for key in ['is_public', 'protected', 'deleted']: - if key in meta: - meta[key] = strutils.bool_from_string(meta[key]) - - return self._format_image_meta_for_user(meta) - - @staticmethod - def _format_image_meta_for_user(meta): - for key in ['size', 'min_ram', 'min_disk']: - if key in meta: - try: - meta[key] = int(meta[key]) - except ValueError: - pass - return meta - - def get(self, image): - """ - Get an image. - - :param image: The ID of the image to get. - :rtype: :class:`Image` - """ - url = "%s/images/%s" % (self.image_api_prefix, base.getid(image)) - resp, _ = self.api.client._cs_request(url, 'HEAD') - foo = self._image_meta_from_headers(resp.headers) - return Image(self, foo) - - def list(self, detailed=True, limit=None): - """ - Get a list of all images. - - :rtype: list of :class:`Image` - :param limit: maximum number of images to return. - """ - params = {} - detail = '' - if detailed: - detail = '/detail' - if limit: - params['limit'] = int(limit) - query = '?%s' % parse.urlencode(params) if params else '' - return self._list('/v1/images%s%s' % (detail, query), 'images') diff --git a/awx/lib/site-packages/novaclient/v3/keypairs.py b/awx/lib/site-packages/novaclient/v3/keypairs.py deleted file mode 100644 index f1ef8ac580..0000000000 --- a/awx/lib/site-packages/novaclient/v3/keypairs.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Keypair interface -""" - -from novaclient.v1_1 import keypairs - - -class Keypair(keypairs.Keypair): - pass - - -class KeypairManager(keypairs.KeypairManager): - resource_class = Keypair - keypair_prefix = "keypairs" diff --git a/awx/lib/site-packages/novaclient/v3/list_extensions.py b/awx/lib/site-packages/novaclient/v3/list_extensions.py deleted file mode 100644 index bcc187494f..0000000000 --- a/awx/lib/site-packages/novaclient/v3/list_extensions.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2014 NEC Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -extension interface -""" - -from novaclient.v1_1.contrib import list_extensions - - -class ListExtResource(list_extensions.ListExtResource): - pass - - -class ListExtManager(list_extensions.ListExtManager): - pass diff --git a/awx/lib/site-packages/novaclient/v3/quota_classes.py b/awx/lib/site-packages/novaclient/v3/quota_classes.py deleted file mode 100644 index e12209eb1f..0000000000 --- a/awx/lib/site-packages/novaclient/v3/quota_classes.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright IBM Corp. 2013 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.v1_1 import quota_classes - - -class QuotaClassSet(quota_classes.QuotaClassSet): - pass - - -class QuotaClassSetManager(quota_classes.QuotaClassSetManager): - resource_class = QuotaClassSet diff --git a/awx/lib/site-packages/novaclient/v3/quotas.py b/awx/lib/site-packages/novaclient/v3/quotas.py deleted file mode 100644 index b55842daa9..0000000000 --- a/awx/lib/site-packages/novaclient/v3/quotas.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from novaclient.v1_1 import quotas - - -class QuotaSet(quotas.QuotaSet): - pass - - -class QuotaSetManager(quotas.QuotaSetManager): - resource_class = QuotaSet - - def get(self, tenant_id, user_id=None, detail=False): - if detail: - detail_string = '/detail' - else: - detail_string = '' - - if hasattr(tenant_id, 'tenant_id'): - tenant_id = tenant_id.tenant_id - if user_id: - url = '/os-quota-sets/%s%s?user_id=%s' % (tenant_id, detail_string, - user_id) - else: - url = '/os-quota-sets/%s%s' % (tenant_id, detail_string) - return self._get(url, "quota_set") - - def _update_body(self, tenant_id, **kwargs): - return {'quota_set': kwargs} diff --git a/awx/lib/site-packages/novaclient/v3/servers.py b/awx/lib/site-packages/novaclient/v3/servers.py deleted file mode 100644 index 70bc5a54bf..0000000000 --- a/awx/lib/site-packages/novaclient/v3/servers.py +++ /dev/null @@ -1,1021 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Server interface. -""" - -import base64 - -from oslo.utils import encodeutils -import six -from six.moves.urllib import parse - -from novaclient import base -from novaclient import crypto -from novaclient.openstack.common.gettextutils import _ - -REBOOT_SOFT, REBOOT_HARD = 'SOFT', 'HARD' - - -class Server(base.Resource): - HUMAN_ID = True - - def __repr__(self): - return "" % self.name - - def delete(self): - """ - Delete (i.e. shut down and delete the image) this server. - """ - self.manager.delete(self) - - def update(self, name=None): - """ - Update the name or the password for this server. - - :param name: Update the server's name. - :param password: Update the root password. - """ - self.manager.update(self, name=name) - - def get_console_output(self, length=None): - """ - Get text console log output from Server. - - :param length: The number of lines you would like to retrieve (as int) - """ - return self.manager.get_console_output(self, length) - - def get_vnc_console(self, console_type): - """ - Get vnc console for a Server. - - :param console_type: Type of console ('novnc' or 'xvpvnc') - """ - return self.manager.get_vnc_console(self, console_type) - - def get_spice_console(self, console_type): - """ - Get spice console for a Server. - - :param console_type: Type of console ('spice-html5') - """ - return self.manager.get_spice_console(self, console_type) - - def get_password(self, private_key): - """ - Get password for a Server. - - :param private_key: Path to private key file for decryption - """ - return self.manager.get_password(self, private_key) - - def clear_password(self): - """ - Get password for a Server. - - """ - return self.manager.clear_password(self) - - def add_fixed_ip(self, network_id): - """ - Add an IP address on a network. - - :param network_id: The ID of the network the IP should be on. - """ - self.manager.add_fixed_ip(self, network_id) - - def remove_floating_ip(self, address): - """ - Remove floating IP from an instance - - :param address: The ip address or FloatingIP to remove - """ - self.manager.remove_floating_ip(self, address) - - def stop(self): - """ - Stop -- Stop the running server. - """ - self.manager.stop(self) - - def force_delete(self): - """ - Force delete -- Force delete a server. - """ - self.manager.force_delete(self) - - def restore(self): - """ - Restore -- Restore a server in 'soft-deleted' state. - """ - self.manager.restore(self) - - def start(self): - """ - Start -- Start the paused server. - """ - self.manager.start(self) - - def pause(self): - """ - Pause -- Pause the running server. - """ - self.manager.pause(self) - - def unpause(self): - """ - Unpause -- Unpause the paused server. - """ - self.manager.unpause(self) - - def lock(self): - """ - Lock -- Lock the instance from certain operations. - """ - self.manager.lock(self) - - def unlock(self): - """ - Unlock -- Remove instance lock. - """ - self.manager.unlock(self) - - def suspend(self): - """ - Suspend -- Suspend the running server. - """ - self.manager.suspend(self) - - def resume(self): - """ - Resume -- Resume the suspended server. - """ - self.manager.resume(self) - - def rescue(self): - """ - Rescue -- Rescue the problematic server. - """ - return self.manager.rescue(self) - - def unrescue(self): - """ - Unrescue -- Unrescue the rescued server. - """ - self.manager.unrescue(self) - - def shelve(self): - """ - Shelve -- Shelve the server. - """ - self.manager.shelve(self) - - def shelve_offload(self): - """ - Shelve_offload -- Remove a shelved server from the compute node. - """ - self.manager.shelve_offload(self) - - def unshelve(self): - """ - Unshelve -- Unshelve the server. - """ - self.manager.unshelve(self) - - def diagnostics(self): - """Diagnostics -- Retrieve server diagnostics.""" - return self.manager.diagnostics(self) - - def migrate(self): - """ - Migrate a server to a new host. - """ - self.manager.migrate(self) - - def remove_fixed_ip(self, address): - """ - Remove an IP address. - - :param address: The IP address to remove. - """ - self.manager.remove_fixed_ip(self, address) - - def change_password(self, password): - """ - Update the password for a server. - """ - self.manager.change_password(self, password) - - def reboot(self, reboot_type=REBOOT_SOFT): - """ - Reboot the server. - - :param reboot_type: either :data:`REBOOT_SOFT` for a software-level - reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. - """ - self.manager.reboot(self, reboot_type) - - def rebuild(self, image, password=None, **kwargs): - """ - Rebuild -- shut down and then re-image -- this server. - - :param image: the :class:`Image` (or its ID) to re-image with. - :param password: string to set as password on the rebuilt server. - """ - return self.manager.rebuild(self, image, password=password, **kwargs) - - def resize(self, flavor, **kwargs): - """ - Resize the server's resources. - - :param flavor: the :class:`Flavor` (or its ID) to resize to. - - Until a resize event is confirmed with :meth:`confirm_resize`, the old - server will be kept around and you'll be able to roll back to the old - flavor quickly with :meth:`revert_resize`. All resizes are - automatically confirmed after 24 hours. - """ - self.manager.resize(self, flavor, **kwargs) - - def create_image(self, image_name, metadata=None): - """ - Create an image based on this server. - - :param image_name: The name to assign the newly create image. - :param metadata: Metadata to assign to the image. - """ - return self.manager.create_image(self, image_name, metadata) - - def backup(self, backup_name, backup_type, rotation): - """ - Backup a server instance. - - :param backup_name: Name of the backup image - :param backup_type: The backup type, like 'daily' or 'weekly' - :param rotation: Int parameter representing how many backups to - keep around. - """ - self.manager.backup(self, backup_name, backup_type, rotation) - - def confirm_resize(self): - """ - Confirm that the resize worked, thus removing the original server. - """ - self.manager.confirm_resize(self) - - def revert_resize(self): - """ - Revert a previous resize, switching back to the old server. - """ - self.manager.revert_resize(self) - - @property - def networks(self): - """ - Generate a simplified list of addresses - """ - networks = {} - try: - for network_label, address_list in self.addresses.items(): - networks[network_label] = [a['addr'] for a in address_list] - return networks - except Exception: - return {} - - def live_migrate(self, host=None, - block_migration=False, - disk_over_commit=False): - """ - Migrates a running instance to a new machine. - """ - self.manager.live_migrate(self, host, - block_migration, - disk_over_commit) - - def reset_state(self, state='error'): - """ - Reset the state of an instance to active or error. - """ - self.manager.reset_state(self, state) - - def reset_network(self): - """ - Reset network of an instance. - """ - self.manager.reset_network(self) - - def evacuate(self, host=None, on_shared_storage=True, password=None): - """ - Evacuate an instance from failed host to specified host. - - :param host: Name of the target host - :param on_shared_storage: Specifies whether instance files located - on shared storage - :param password: string to set as password on the evacuated server. - """ - return self.manager.evacuate(self, host, on_shared_storage, password) - - def interface_list(self): - """ - List interfaces attached to an instance. - """ - return self.manager.interface_list(self) - - def interface_attach(self, port_id, net_id, fixed_ip): - """ - Attach a network interface to an instance. - """ - return self.manager.interface_attach(self, port_id, net_id, fixed_ip) - - def interface_detach(self, port_id): - """ - Detach a network interface from an instance. - """ - return self.manager.interface_detach(self, port_id) - - -class ServerManager(base.BootingManagerWithFind): - resource_class = Server - - def _boot(self, resource_url, response_key, name, image, flavor, - meta=None, userdata=None, - reservation_id=None, return_raw=False, min_count=None, - max_count=None, security_groups=None, key_name=None, - availability_zone=None, block_device_mapping=None, - block_device_mapping_v2=None, nics=None, scheduler_hints=None, - config_drive=None, admin_pass=None, **kwargs): - """ - Create (boot) a new server. - - :param name: Something to name the server. - :param image: The :class:`Image` to boot with. - :param flavor: The :class:`Flavor` to boot onto. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param reservation_id: a UUID for the set of servers being requested. - :param return_raw: If True, don't try to coearse the result into - a Resource object. - :param security_groups: list of security group names - :param key_name: (optional extension) name of keypair to inject into - the instance - :param availability_zone: Name of the availability zone for instance - placement. - :param block_device_mapping: A dict of block device mappings for this - server. - :param block_device_mapping_v2: A dict of block device mappings V2 for - this server. - :param nics: (optional extension) an ordered list of nics to be - added to this server, with information about - connected networks, fixed ips, etc. - :param scheduler_hints: (optional extension) arbitrary key-value pairs - specified by the client to help boot an instance. - :param config_drive: (optional extension) value for config drive - either boolean, or volume-id - :param admin_pass: admin password for the server. - """ - body = {"server": { - "name": name, - "image_ref": str(base.getid(image)) if image else '', - "flavor_ref": str(base.getid(flavor)), - }} - if userdata: - if hasattr(userdata, 'read'): - userdata = userdata.read() - - if six.PY3: - userdata = userdata.encode("utf-8") - else: - userdata = encodeutils.safe_encode(userdata) - - data = base64.b64encode(userdata).decode('utf-8') - body["server"]["user_data"] = data - if meta: - body["server"]["metadata"] = meta - if reservation_id: - body["server"][ - "os-multiple-create:return_reservation_id"] = reservation_id - if key_name: - body["server"]["key_name"] = key_name - if scheduler_hints: - body["server"][ - "os-scheduler-hints:scheduler_hints"] = scheduler_hints - if config_drive: - body["server"]["os-config-drive:config_drive"] = config_drive - if admin_pass: - body["server"]["admin_password"] = admin_pass - if not min_count: - min_count = 1 - if not max_count: - max_count = min_count - body["server"]["os-multiple-create:min_count"] = min_count - body["server"]["os-multiple-create:max_count"] = max_count - - if security_groups: - body["server"]["security_groups"] = \ - [{'name': sg} for sg in security_groups] - - if availability_zone: - body["server"][ - "os-availability-zone:availability_zone"] = availability_zone - - # Block device mappings are passed as a list of dictionaries - if block_device_mapping: - bdm_param = 'block_device_mapping' - body['server'][bdm_param] = \ - self._parse_block_device_mapping(block_device_mapping) - elif block_device_mapping_v2: - # Append the image to the list only if we have new style BDMs - bdm_param = 'block_device_mapping_v2' - if image: - bdm_dict = {'uuid': image.id, 'source_type': 'image', - 'destination_type': 'local', 'boot_index': 0, - 'delete_on_termination': True} - block_device_mapping_v2.insert(0, bdm_dict) - - body['server'][bdm_param] = block_device_mapping_v2 - - if nics is not None: - # NOTE(tr3buchet): nics can be an empty list - all_net_data = [] - for nic_info in nics: - net_data = {} - # if value is empty string, do not send value in body - if nic_info.get('net-id'): - net_data['uuid'] = nic_info['net-id'] - if (nic_info.get('v4-fixed-ip') and - nic_info.get('v6-fixed-ip')): - raise base.exceptions.CommandError(_( - "Only one of 'v4-fixed-ip' and 'v6-fixed-ip' may be" - " provided.")) - elif nic_info.get('v4-fixed-ip'): - net_data['fixed_ip'] = nic_info['v4-fixed-ip'] - elif nic_info.get('v6-fixed-ip'): - net_data['fixed_ip'] = nic_info['v6-fixed-ip'] - if nic_info.get('port-id'): - net_data['port'] = nic_info['port-id'] - all_net_data.append(net_data) - body['server']['networks'] = all_net_data - - return self._create(resource_url, body, response_key, - return_raw=return_raw, **kwargs) - - def get(self, server): - """ - Get a server. - - :param server: ID of the :class:`Server` to get. - :rtype: :class:`Server` - """ - return self._get("/servers/%s" % base.getid(server), "server") - - def list(self, detailed=True, search_opts=None, marker=None, limit=None): - """ - Get a list of servers. - - :param detailed: Whether to return detailed server info (optional). - :param search_opts: Search options to filter out servers (optional). - :param marker: Begin returning servers that appear later in the server - list than that represented by this server id (optional). - :param limit: Maximum number of servers to return (optional). - - :rtype: list of :class:`Server` - """ - if search_opts is None: - search_opts = {} - - qparams = {} - - for opt, val in six.iteritems(search_opts): - if val: - qparams[opt] = val - - if marker: - qparams['marker'] = marker - - if limit: - qparams['limit'] = limit - - # Transform the dict to a sequence of two-element tuples in fixed - # order, then the encoded string will be consistent in Python 2&3. - if qparams: - new_qparams = sorted(qparams.items(), key=lambda x: x[0]) - query_string = "?%s" % parse.urlencode(new_qparams) - else: - query_string = "" - - detail = "" - if detailed: - detail = "/detail" - return self._list("/servers%s%s" % (detail, query_string), "servers") - - def add_fixed_ip(self, server, network_id): - """ - Add an IP address on a network. - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param network_id: The ID of the network the IP should be on. - """ - self._action('add_fixed_ip', server, {'network_id': network_id}) - - def remove_fixed_ip(self, server, address): - """ - Remove an IP address. - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param address: The IP address to remove. - """ - self._action('remove_fixed_ip', server, {'address': address}) - - def get_vnc_console(self, server, console_type): - """ - Get a vnc console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of vnc console to get ('novnc' or 'xvpvnc') - """ - - return self._action('get_vnc_console', server, - {'type': console_type})[1] - - def get_spice_console(self, server, console_type): - """ - Get a spice console for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param console_type: Type of spice console to get ('spice-html5') - """ - - return self._action('get_spice_console', server, - {'type': console_type})[1] - - def get_password(self, server, private_key): - """ - Get password for an instance - - Requires that openssl is installed and in the path - - :param server: The :class:`Server` (or its ID) to add an IP to. - :param private_key: The private key to decrypt password - """ - - _resp, body = self.api.client.get("/servers/%s/os-server-password" - % base.getid(server)) - if body and body.get('password'): - try: - return crypto.decrypt_password(private_key, body['password']) - except Exception as exc: - return '%sFailed to decrypt:\n%s' % (exc, body['password']) - return '' - - def clear_password(self, server): - """ - Clear password for an instance - - :param server: The :class:`Server` (or its ID) to add an IP to. - """ - - return self._delete("/servers/%s/os-server-password" - % base.getid(server)) - - def stop(self, server): - """ - Stop the server. - """ - return self._action('stop', server, None) - - def force_delete(self, server): - """ - Force delete the server. - """ - return self._action('force_delete', server, None) - - def restore(self, server): - """ - Restore soft-deleted server. - """ - return self._action('restore', server, None) - - def start(self, server): - """ - Start the server. - """ - self._action('start', server, None) - - def pause(self, server): - """ - Pause the server. - """ - self._action('pause', server, None) - - def unpause(self, server): - """ - Unpause the server. - """ - self._action('unpause', server, None) - - def lock(self, server): - """ - Lock the server. - """ - self._action('lock', server, None) - - def unlock(self, server): - """ - Unlock the server. - """ - self._action('unlock', server, None) - - def suspend(self, server): - """ - Suspend the server. - """ - self._action('suspend', server, None) - - def resume(self, server): - """ - Resume the server. - """ - self._action('resume', server, None) - - def rescue(self, server): - """ - Rescue the server. - """ - return self._action('rescue', server, None) - - def unrescue(self, server): - """ - Unrescue the server. - """ - self._action('unrescue', server, None) - - def shelve(self, server): - """ - Shelve the server. - """ - self._action('shelve', server, None) - - def shelve_offload(self, server): - """ - Remove a shelved instance from the compute node. - """ - self._action('shelve_offload', server, None) - - def unshelve(self, server): - """ - Unshelve the server. - """ - self._action('unshelve', server, None) - - def diagnostics(self, server): - """Retrieve server diagnostics.""" - return self.api.client.get("/servers/%s/os-server-diagnostics" % - base.getid(server)) - - def create(self, name, image, flavor, meta=None, files=None, - reservation_id=None, min_count=None, - max_count=None, security_groups=None, userdata=None, - key_name=None, availability_zone=None, - block_device_mapping=None, block_device_mapping_v2=None, - nics=None, scheduler_hints=None, - config_drive=None, **kwargs): - # TODO(anthony): indicate in doc string if param is an extension - # and/or optional - """ - Create (boot) a new server. - - :param name: Something to name the server. - :param image: The :class:`Image` to boot with. - :param flavor: The :class:`Flavor` to boot onto. - :param meta: A dict of arbitrary key/value metadata to store for this - server. A maximum of five entries is allowed, and both - keys and values must be 255 characters or less. - :param files: A dict of files to overrwrite on the server upon boot. - Keys are file names (i.e. ``/etc/passwd``) and values - are the file contents (either as a string or as a - file-like object). A maximum of five entries is allowed, - and each file must be 10k or less. - :param userdata: user data to pass to be exposed by the metadata - server this can be a file type object as well or a - string. - :param reservation_id: a UUID for the set of servers being requested. - :param key_name: (optional extension) name of previously created - keypair to inject into the instance. - :param availability_zone: Name of the availability zone for instance - placement. - :param block_device_mapping: (optional extension) A dict of block - device mappings for this server. - :param block_device_mapping_v2: (optional extension) A dict of block - device mappings for this server. - :param nics: (optional extension) an ordered list of nics to be - added to this server, with information about - connected networks, fixed ips, port etc. - :param scheduler_hints: (optional extension) arbitrary key-value pairs - specified by the client to help boot an instance - :param config_drive: (optional extension) value for config drive - either boolean, or volume-id - """ - if not min_count: - min_count = 1 - if not max_count: - max_count = min_count - if min_count > max_count: - min_count = max_count - - boot_args = [name, image, flavor] - - boot_kwargs = dict( - meta=meta, files=files, userdata=userdata, - reservation_id=reservation_id, min_count=min_count, - max_count=max_count, security_groups=security_groups, - key_name=key_name, availability_zone=availability_zone, - scheduler_hints=scheduler_hints, config_drive=config_drive, - **kwargs) - - if block_device_mapping: - boot_kwargs['block_device_mapping'] = block_device_mapping - elif block_device_mapping_v2: - boot_kwargs['block_device_mapping_v2'] = block_device_mapping_v2 - resource_url = "/servers" - if nics: - boot_kwargs['nics'] = nics - - response_key = "server" - return self._boot(resource_url, response_key, *boot_args, - **boot_kwargs) - - def update(self, server, name=None): - """ - Update the name or the password for a server. - - :param server: The :class:`Server` (or its ID) to update. - :param name: Update the server's name. - """ - if name is None: - return - - body = { - "server": { - "name": name, - }, - } - - return self._update("/servers/%s" % base.getid(server), body, "server") - - def change_password(self, server, password): - """ - Update the password for a server. - """ - self._action("change_password", server, {"admin_password": password}) - - def delete(self, server): - """ - Delete (i.e. shut down and delete the image) this server. - """ - self._delete("/servers/%s" % base.getid(server)) - - def reboot(self, server, reboot_type=REBOOT_SOFT): - """ - Reboot a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param reboot_type: either :data:`REBOOT_SOFT` for a software-level - reboot, or `REBOOT_HARD` for a virtual power cycle hard reboot. - """ - self._action('reboot', server, {'type': reboot_type}) - - def rebuild(self, server, image, password=None, **kwargs): - """ - Rebuild -- shut down and then re-image -- a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param image: the :class:`Image` (or its ID) to re-image with. - :param password: string to set as password on the rebuilt server. - """ - body = {'image_ref': base.getid(image)} - if password is not None: - body['admin_password'] = password - - _resp, body = self._action('rebuild', server, body, **kwargs) - return Server(self, body['server']) - - def migrate(self, server): - """ - Migrate a server to a new host. - - :param server: The :class:`Server` (or its ID). - """ - self._action('migrate', server) - - def resize(self, server, flavor, **kwargs): - """ - Resize a server's resources. - - :param server: The :class:`Server` (or its ID) to share onto. - :param flavor: the :class:`Flavor` (or its ID) to resize to. - - Until a resize event is confirmed with :meth:`confirm_resize`, the old - server will be kept around and you'll be able to roll back to the old - flavor quickly with :meth:`revert_resize`. All resizes are - automatically confirmed after 24 hours. - """ - info = {'flavor_ref': base.getid(flavor)} - - self._action('resize', server, info=info, **kwargs) - - def confirm_resize(self, server): - """ - Confirm that the resize worked, thus removing the original server. - - :param server: The :class:`Server` (or its ID) to share onto. - """ - self._action('confirm_resize', server) - - def revert_resize(self, server): - """ - Revert a previous resize, switching back to the old server. - - :param server: The :class:`Server` (or its ID) to share onto. - """ - self._action('revert_resize', server) - - def create_image(self, server, image_name, metadata=None): - """ - Snapshot a server. - - :param server: The :class:`Server` (or its ID) to share onto. - :param image_name: Name to give the snapshot image - :param meta: Metadata to give newly-created image entity - """ - body = {'name': image_name, 'metadata': metadata or {}} - resp = self._action('create_image', server, body)[0] - location = resp.headers['location'] - image_uuid = location.split('/')[-1] - return image_uuid - - def backup(self, server, backup_name, backup_type, rotation): - """ - Backup a server instance. - - :param server: The :class:`Server` (or its ID) to share onto. - :param backup_name: Name of the backup image - :param backup_type: The backup type, like 'daily' or 'weekly' - :param rotation: Int parameter representing how many backups to - keep around. - """ - body = {'name': backup_name, - 'backup_type': backup_type, - 'rotation': rotation} - self._action('create_backup', server, body) - - def set_meta(self, server, metadata): - """ - Set a servers metadata - :param server: The :class:`Server` to add metadata to - :param metadata: A dict of metadata to add to the server - """ - body = {'metadata': metadata} - return self._create("/servers/%s/metadata" % base.getid(server), - body, "metadata") - - def get_console_output(self, server, length=None): - """ - Get text console log output from Server. - - :param server: The :class:`Server` (or its ID) whose console output - you would like to retrieve. - :param length: The number of tail loglines you would like to retrieve. - """ - if length is None: - # NOTE: On v3 get_console_output API, -1 means an unlimited length. - # Here translates None, which means an unlimited in the internal - # implementation, to -1. - length = -1 - return self._action('get_console_output', - server, {'length': length})[1]['output'] - - def delete_meta(self, server, keys): - """ - Delete metadata from an server - :param server: The :class:`Server` to add metadata to - :param keys: A list of metadata keys to delete from the server - """ - for k in keys: - self._delete("/servers/%s/metadata/%s" % (base.getid(server), k)) - - def live_migrate(self, server, host, block_migration, disk_over_commit): - """ - Migrates a running instance to a new machine. - - :param server: instance id which comes from nova list. - :param host: destination host name. - :param block_migration: if True, do block_migration. - :param disk_over_commit: if True, Allow overcommit. - - """ - self._action('migrate_live', server, - {'host': host, - 'block_migration': block_migration, - 'disk_over_commit': disk_over_commit}) - - def reset_state(self, server, state='error'): - """ - Reset the state of an instance to active or error. - - :param server: ID of the instance to reset the state of. - :param state: Desired state; either 'active' or 'error'. - Defaults to 'error'. - """ - self._action('reset_state', server, dict(state=state)) - - def reset_network(self, server): - """ - Reset network of an instance. - """ - self._action('reset_network', server) - - def evacuate(self, server, host=None, - on_shared_storage=True, password=None): - """ - Evacuate a server instance. - - :param server: The :class:`Server` (or its ID) to share onto. - :param host: Name of the target host. - :param on_shared_storage: Specifies whether instance files located - on shared storage - :param password: string to set as password on the evacuated server. - """ - body = {'on_shared_storage': on_shared_storage} - if host is not None: - body['host'] = host - - if password is not None: - body['admin_password'] = password - - return self._action('evacuate', server, body) - - def interface_list(self, server): - """ - List attached network interfaces - - :param server: The :class:`Server` (or its ID) to query. - """ - return self._list('/servers/%s/os-attach-interfaces' - % base.getid(server), 'interface_attachments') - - def interface_attach(self, server, port_id, net_id, fixed_ip): - """ - Attach a network_interface to an instance. - - :param server: The :class:`Server` (or its ID) to attach to. - :param port_id: The port to attach. - """ - - body = {'interface_attachment': {}} - if port_id: - body['interface_attachment']['port_id'] = port_id - if net_id: - body['interface_attachment']['net_id'] = net_id - if fixed_ip: - body['interface_attachment']['fixed_ips'] = [ - {'ip_address': fixed_ip}] - - return self._create('/servers/%s/os-attach-interfaces' - % base.getid(server), - body, 'interface_attachment') - - def interface_detach(self, server, port_id): - """ - Detach a network_interface from an instance. - - :param server: The :class:`Server` (or its ID) to detach from. - :param port_id: The port to detach. - """ - self._delete('/servers/%s/os-attach-interfaces/%s' - % (base.getid(server), port_id)) - - def _action(self, action, server, info=None, **kwargs): - """ - Perform a server "action" -- reboot/rebuild/resize/etc. - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/servers/%s/action' % base.getid(server) - return self.api.client.post(url, body=body) diff --git a/awx/lib/site-packages/novaclient/v3/services.py b/awx/lib/site-packages/novaclient/v3/services.py deleted file mode 100644 index fe0f3a6a40..0000000000 --- a/awx/lib/site-packages/novaclient/v3/services.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -service interface -""" -from novaclient.v1_1 import services - - -class Service(services.Service): - pass - - -class ServiceManager(services.ServiceManager): - resource_class = Service - - def _update_body(self, host, binary, disabled_reason=None): - body = {"service": - {"host": host, - "binary": binary}} - if disabled_reason is not None: - body["service"]["disabled_reason"] = disabled_reason - return body diff --git a/awx/lib/site-packages/novaclient/v3/shell.py b/awx/lib/site-packages/novaclient/v3/shell.py deleted file mode 100644 index 3d17e28906..0000000000 --- a/awx/lib/site-packages/novaclient/v3/shell.py +++ /dev/null @@ -1,3087 +0,0 @@ -# Copyright 2010 Jacob Kaplan-Moss - -# Copyright 2011 OpenStack Foundation -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import argparse -import copy -import datetime -import getpass -import locale -import os -import sys -import time - -from oslo.utils import strutils -from oslo.utils import timeutils -import six - -from novaclient import exceptions -from novaclient.openstack.common.gettextutils import _ -from novaclient.openstack.common import uuidutils -from novaclient import utils -from novaclient.v3 import availability_zones -from novaclient.v3 import servers - - -def _key_value_pairing(text): - try: - (k, v) = text.split('=', 1) - return (k, v) - except ValueError: - msg = "%r is not in the format of key=value" % text - raise argparse.ArgumentTypeError(msg) - - -def _match_image(cs, wanted_properties): - image_list = cs.images.list() - images_matched = [] - match = set(wanted_properties) - for img in image_list: - try: - if match == match.intersection(set(img.metadata.items())): - images_matched.append(img) - except AttributeError: - pass - return images_matched - - -def _boot(cs, args): - """Boot a new server.""" - if args.image: - image = _find_image(cs.image_cs, args.image) - else: - image = None - - if not image and args.image_with: - images = _match_image(cs.image_cs, args.image_with) - if images: - # TODO(harlowja): log a warning that we - # are selecting the first of many? - image = images[0] - - if not image and not args.block_device_mapping: - raise exceptions.CommandError("you need to specify an Image ID " - "or a block device mapping " - "or provide a set of properties to match" - " against an image") - if not args.flavor: - raise exceptions.CommandError("you need to specify a Flavor ID ") - - min_count = 1 - max_count = 1 - # Don't let user mix num_instances and max_count/min_count. - if (args.num_instances is not None and - args.min_count is None and args.max_count is None): - if args.num_instances < 1: - raise exceptions.CommandError("num_instances should be >= 1") - max_count = args.num_instances - elif (args.num_instances is not None and - (args.min_count is not None or args.max_count is not None)): - raise exceptions.CommandError("Don't mix num-instances and " - "max/min-count") - if args.min_count is not None: - if args.min_count < 1: - raise exceptions.CommandError("min_count should be >= 1") - min_count = args.min_count - max_count = min_count - if args.max_count is not None: - if args.max_count < 1: - raise exceptions.CommandError("max_count should be >= 1") - max_count = args.max_count - if (args.min_count is not None and args.max_count is not None and - args.min_count > args.max_count): - raise exceptions.CommandError( - "min_count should be <= max_count") - - flavor = _find_flavor(cs, args.flavor) - - meta = dict(v.split('=', 1) for v in args.meta) - - files = {} - for f in args.files: - try: - dst, src = f.split('=', 1) - files[dst] = open(src) - except IOError as e: - raise exceptions.CommandError("Can't open '%s': %s" % (src, e)) - except ValueError as e: - raise exceptions.CommandError("Invalid file argument '%s'. File " - "arguments must be of the form '--file '" % f) - - # use the os-keypair extension - key_name = None - if args.key_name is not None: - key_name = args.key_name - - if args.user_data: - try: - userdata = open(args.user_data) - except IOError as e: - raise exceptions.CommandError("Can't open '%s': %s" % - (args.user_data, e)) - else: - userdata = None - - if args.availability_zone: - availability_zone = args.availability_zone - else: - availability_zone = None - - if args.security_groups: - security_groups = args.security_groups.split(',') - else: - security_groups = None - - block_device_mapping = {} - for bdm in args.block_device_mapping: - device_name, mapping = bdm.split('=', 1) - block_device_mapping[device_name] = mapping - - nics = [] - for nic_str in args.nics: - err_msg = ("Invalid nic argument '%s'. Nic arguments must be of the " - "form --nic , with at minimum " - "net-id or port-id (but not both) specified." % nic_str) - nic_info = {"net-id": "", "v4-fixed-ip": "", "v6-fixed-ip": "", - "port-id": ""} - - for kv_str in nic_str.split(","): - try: - k, v = kv_str.split("=", 1) - except ValueError as e: - raise exceptions.CommandError(err_msg) - - if k in nic_info: - nic_info[k] = v - else: - raise exceptions.CommandError(err_msg) - - if bool(nic_info['net-id']) == bool(nic_info['port-id']): - raise exceptions.CommandError(err_msg) - - nics.append(nic_info) - - hints = {} - if args.scheduler_hints: - for hint in args.scheduler_hints: - key, _sep, value = hint.partition('=') - # NOTE(vish): multiple copies of the same hint will - # result in a list of values - if key in hints: - if isinstance(hints[key], six.string_types): - hints[key] = [hints[key]] - hints[key] += [value] - else: - hints[key] = value - boot_args = [args.name, image, flavor] - - if str(args.config_drive).lower() in ("true", "1"): - config_drive = True - elif str(args.config_drive).lower() in ("false", "0", "", "none"): - config_drive = None - else: - config_drive = args.config_drive - - boot_kwargs = dict( - meta=meta, - files=files, - key_name=key_name, - min_count=min_count, - max_count=max_count, - userdata=userdata, - availability_zone=availability_zone, - security_groups=security_groups, - block_device_mapping=block_device_mapping, - nics=nics, - scheduler_hints=hints, - config_drive=config_drive) - - return boot_args, boot_kwargs - - -@utils.arg('--flavor', - default=None, - metavar='', - help="Flavor ID (see 'nova flavor-list').") -@utils.arg('--image', - default=None, - metavar='', - help="Image ID (see 'nova image-list'). ") -@utils.arg('--image-with', - default=[], - type=_key_value_pairing, - action='append', - metavar='', - help="Image metadata property (see 'nova image-show'). ") -@utils.arg('--num-instances', - default=None, - type=int, - metavar='', - help=argparse.SUPPRESS) -@utils.arg('--min-count', - default=None, - type=int, - metavar='', - help="Boot at least servers (limited by quota).") -@utils.arg('--max-count', - default=None, - type=int, - metavar='', - help="Boot up to servers (limited by quota).") -@utils.arg('--meta', - metavar="", - action='append', - default=[], - help="Record arbitrary key/value metadata to /meta.js " - "on the new server. Can be specified multiple times.") -@utils.arg('--file', - metavar="", - action='append', - dest='files', - default=[], - help="Store arbitrary files from locally to " - "on the new server. You may store up to 5 files.") -@utils.arg('--key-name', - default=os.environ.get('NOVACLIENT_DEFAULT_KEY_NAME'), - metavar='', - help="Key name of keypair that should be created earlier with \ - the command keypair-add") -@utils.arg('--key_name', - help=argparse.SUPPRESS) -@utils.arg('name', metavar='', help='Name for the new server') -@utils.arg('--user-data', - default=None, - metavar='', - help="user data file to pass to be exposed by the metadata server.") -@utils.arg('--user_data', - help=argparse.SUPPRESS) -@utils.arg('--availability-zone', - default=None, - metavar='', - help="The availability zone for server placement.") -@utils.arg('--availability_zone', - help=argparse.SUPPRESS) -@utils.arg('--security-groups', - default=None, - metavar='', - help="Comma separated list of security group names.") -@utils.arg('--security_groups', - help=argparse.SUPPRESS) -@utils.arg('--block-device-mapping', - metavar="", - action='append', - default=[], - help="Block device mapping in the format " - "=:::.") -@utils.arg('--block_device_mapping', - action='append', - help=argparse.SUPPRESS) -@utils.arg('--hint', - action='append', - dest='scheduler_hints', - default=[], - metavar='', - help="Send arbitrary key/value pairs to the scheduler for custom use.") -@utils.arg('--nic', - metavar="", - action='append', - dest='nics', - default=[], - help="Create a NIC on the server. " - "Specify option multiple times to create multiple NICs. " - "net-id: attach NIC to network with this UUID " - "(either port-id or net-id must be provided), " - "v4-fixed-ip: IPv4 fixed address for NIC (optional), " - "v6-fixed-ip: IPv6 fixed address for NIC (optional), " - "port-id: attach NIC to port with this UUID " - "(either port-id or net-id must be provided).") -@utils.arg('--config-drive', - metavar="", - dest='config_drive', - default=False, - help="Enable config drive") -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help='Report the new server boot progress until it completes.') -def do_boot(cs, args): - """Boot a new server.""" - boot_args, boot_kwargs = _boot(cs, args) - - extra_boot_kwargs = utils.get_resource_manager_extra_kwargs(do_boot, args) - boot_kwargs.update(extra_boot_kwargs) - - server = cs.servers.create(*boot_args, **boot_kwargs) - _print_server(cs, args, server) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'building', ['active']) - - -def _poll_for_status(poll_fn, obj_id, action, final_ok_states, - poll_period=5, show_progress=True, - status_field="status", silent=False): - """Block while an action is being performed, periodically printing - progress. - """ - def print_progress(progress): - if show_progress: - msg = ('\rServer %(action)s... %(progress)s%% complete' - % dict(action=action, progress=progress)) - else: - msg = '\rServer %(action)s...' % dict(action=action) - - sys.stdout.write(msg) - sys.stdout.flush() - - if not silent: - print() - - while True: - obj = poll_fn(obj_id) - - status = getattr(obj, status_field) - - if status: - status = status.lower() - - progress = getattr(obj, 'progress', None) or 0 - if status in final_ok_states: - if not silent: - print_progress(100) - print("\nFinished") - break - elif status == "error": - if not silent: - print("\nError %s server" % action) - raise exceptions.InstanceInErrorState(obj.fault['message']) - - if not silent: - print_progress(progress) - - time.sleep(poll_period) - - -def _translate_keys(collection, convert): - for item in collection: - keys = item.__dict__.keys() - for from_key, to_key in convert: - if from_key in keys and to_key not in keys: - setattr(item, to_key, item._info[from_key]) - - -def _translate_extended_states(collection): - power_states = [ - 'NOSTATE', # 0x00 - 'Running', # 0x01 - '', # 0x02 - 'Paused', # 0x03 - 'Shutdown', # 0x04 - '', # 0x05 - 'Crashed', # 0x06 - 'Suspended' # 0x07 - ] - - for item in collection: - try: - setattr(item, 'power_state', - power_states[getattr(item, 'power_state')] - ) - except AttributeError: - setattr(item, 'power_state', "N/A") - try: - getattr(item, 'task_state') - except AttributeError: - setattr(item, 'task_state', "N/A") - - -def _translate_flavor_keys(collection): - _translate_keys(collection, [('ram', 'memory_mb')]) - - -def _print_flavor_extra_specs(flavor): - try: - return flavor.get_keys() - except exceptions.NotFound: - return "N/A" - - -def _print_flavor_list(flavors, show_extra_specs=False): - _translate_flavor_keys(flavors) - - headers = [ - 'ID', - 'Name', - 'Memory_MB', - 'Disk', - 'Ephemeral', - 'Swap', - 'VCPUs', - 'RXTX_Factor', - 'Is_Public', - ] - - if show_extra_specs: - formatters = {'extra_specs': _print_flavor_extra_specs} - headers.append('extra_specs') - else: - formatters = {} - - utils.print_list(flavors, headers, formatters) - - -@utils.arg('--extra-specs', - dest='extra_specs', - action='store_true', - default=False, - help='Get extra-specs of each flavor.') -@utils.arg('--all', - dest='all', - action='store_true', - default=False, - help='Display all flavors (Admin only).') -def do_flavor_list(cs, args): - """Print a list of available 'flavors' (sizes of servers).""" - if args.all: - flavors = cs.flavors.list(is_public=None) - else: - flavors = cs.flavors.list() - _print_flavor_list(flavors, args.extra_specs) - - -@utils.arg('flavor', - metavar='', - help="Name or ID of the flavor to delete") -def do_flavor_delete(cs, args): - """Delete a specific flavor""" - flavorid = _find_flavor(cs, args.flavor) - cs.flavors.delete(flavorid) - _print_flavor_list([flavorid]) - - -@utils.arg('flavor', - metavar='', - help="Name or ID of flavor") -def do_flavor_show(cs, args): - """Show details about the given flavor.""" - flavor = _find_flavor(cs, args.flavor) - _print_flavor(flavor) - - -@utils.arg('name', - metavar='', - help="Name of the new flavor") -@utils.arg('id', - metavar='', - help="Unique ID (integer or UUID) for the new flavor." - " If specifying 'auto', a UUID will be generated as id") -@utils.arg('ram', - metavar='', - help="Memory size in MB") -@utils.arg('disk', - metavar='', - help="Disk size in GB") -@utils.arg('--ephemeral', - metavar='', - help="Ephemeral space size in GB (default 0)", - default=0) -@utils.arg('vcpus', - metavar='', - help="Number of vcpus") -@utils.arg('--swap', - metavar='', - help="Swap space size in MB (default 0)", - default=0) -@utils.arg('--rxtx-factor', - metavar='', - help="RX/TX factor (default 1)", - default=1.0) -@utils.arg('--is-public', - metavar='', - help="Make flavor accessible to the public (default true)", - type=lambda v: strutils.bool_from_string(v, True), - default=True) -def do_flavor_create(cs, args): - """Create a new flavor""" - f = cs.flavors.create(args.name, args.ram, args.vcpus, args.disk, args.id, - args.ephemeral, args.swap, args.rxtx_factor, - args.is_public) - _print_flavor_list([f]) - - -@utils.arg('flavor', - metavar='', - help="Name or ID of flavor") -@utils.arg('action', - metavar='', - choices=['set', 'unset'], - help="Actions: 'set' or 'unset'") -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help='Extra_specs to set/unset (only key is necessary on unset)') -def do_flavor_key(cs, args): - """Set or unset extra_spec for a flavor.""" - flavor = _find_flavor(cs, args.flavor) - keypair = _extract_metadata(args) - - if args.action == 'set': - flavor.set_keys(keypair) - elif args.action == 'unset': - flavor.unset_keys(keypair.keys()) - - -@utils.arg('--flavor', - metavar='', - help="Filter results by flavor name or ID.") -@utils.arg('--tenant', metavar='', - help='Filter results by tenant ID.') -def do_flavor_access_list(cs, args): - """Print access information about the given flavor.""" - if args.flavor and args.tenant: - raise exceptions.CommandError("Unable to filter results by " - "both --flavor and --tenant.") - elif args.flavor: - flavor = _find_flavor(cs, args.flavor) - if flavor.is_public: - raise exceptions.CommandError("Failed to get access list " - "for public flavor type.") - kwargs = {'flavor': flavor} - elif args.tenant: - kwargs = {'tenant': args.tenant} - else: - raise exceptions.CommandError("Unable to get all access lists. " - "Specify --flavor or --tenant") - - try: - access_list = cs.flavor_access.list(**kwargs) - except NotImplementedError as e: - raise exceptions.CommandError("%s" % str(e)) - - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@utils.arg('flavor', - metavar='', - help="Flavor name or ID to add access for the given tenant.") -@utils.arg('tenant', metavar='', - help='Tenant ID to add flavor access for.') -def do_flavor_access_add(cs, args): - """Add flavor access for the given tenant.""" - flavor = _find_flavor(cs, args.flavor) - access_list = cs.flavor_access.add_tenant_access(flavor, args.tenant) - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@utils.arg('flavor', - metavar='', - help="Flavor name or ID to remove access for the given tenant.") -@utils.arg('tenant', metavar='', - help='Tenant ID to remove flavor access for.') -def do_flavor_access_remove(cs, args): - """Remove flavor access for the given tenant.""" - flavor = _find_flavor(cs, args.flavor) - access_list = cs.flavor_access.remove_tenant_access(flavor, args.tenant) - columns = ['Flavor_ID', 'Tenant_ID'] - utils.print_list(access_list, columns) - - -@utils.arg('project_id', metavar='', - help='The ID of the project.') -def do_scrub(cs, args): - """Delete data associated with the project.""" - networks_list = cs.networks.list() - networks_list = [network for network in networks_list - if getattr(network, 'project_id', '') == args.project_id] - search_opts = {'all_tenants': 1} - groups = cs.security_groups.list(search_opts) - groups = [group for group in groups - if group.tenant_id == args.project_id] - for network in networks_list: - cs.networks.disassociate(network) - for group in groups: - cs.security_groups.delete(group) - - -def do_network_list(cs, _args): - """Print a list of available networks.""" - network_list = cs.networks.list() - columns = ['ID', 'Label', 'Cidr'] - utils.print_list(network_list, columns) - - -@utils.arg('network', - metavar='', - help="uuid or label of network") -def do_network_show(cs, args): - """Show details about the given network.""" - network = utils.find_resource(cs.networks, args.network) - utils.print_dict(network._info) - - -@utils.arg('--host-only', - dest='host_only', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0) -@utils.arg('--project-only', - dest='project_only', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=0) -@utils.arg('network', - metavar='', - help="uuid of network") -def do_network_disassociate(cs, args): - """Disassociate host and/or project from the given network.""" - if args.host_only: - cs.networks.disassociate(args.network, True, False) - elif args.project_only: - cs.networks.disassociate(args.network, False, True) - else: - cs.networks.disassociate(args.network, True, True) - - -@utils.arg('network', - metavar='', - help="uuid of network") -@utils.arg('host', - metavar='', - help="Name of host") -def do_network_associate_host(cs, args): - """Associate host with network.""" - cs.networks.associate_host(args.network, args.host) - - -@utils.arg('network', - metavar='', - help="uuid of network") -def do_network_associate_project(cs, args): - """Associate project with network.""" - cs.networks.associate_project(args.network) - - -def _filter_network_create_options(args): - valid_args = ['label', 'cidr', 'vlan_start', 'vpn_start', 'cidr_v6', - 'gateway', 'gateway_v6', 'bridge', 'bridge_interface', - 'multi_host', 'dns1', 'dns2', 'uuid', 'fixed_cidr', - 'project_id', 'priority'] - kwargs = {} - for k, v in args.__dict__.items(): - if k in valid_args and v is not None: - kwargs[k] = v - - return kwargs - - -@utils.arg('label', - metavar='', - help="Label for network") -@utils.arg('--fixed-range-v4', - dest='cidr', - metavar='', - help="IPv4 subnet (ex: 10.0.0.0/8)") -@utils.arg('--fixed-range-v6', - dest="cidr_v6", - help='IPv6 subnet (ex: fe80::/64') -@utils.arg('--vlan', - dest='vlan_start', - metavar='', - help="vlan id") -@utils.arg('--vpn', - dest='vpn_start', - metavar='', - help="vpn start") -@utils.arg('--gateway', - dest="gateway", - help='gateway') -@utils.arg('--gateway-v6', - dest="gateway_v6", - help='IPv6 gateway') -@utils.arg('--bridge', - dest="bridge", - metavar='', - help='VIFs on this network are connected to this bridge.') -@utils.arg('--bridge-interface', - dest="bridge_interface", - metavar='', - help='The bridge is connected to this interface.') -@utils.arg('--multi-host', - dest="multi_host", - metavar="<'T'|'F'>", - help='Multi host') -@utils.arg('--dns1', - dest="dns1", - metavar="", help='First DNS') -@utils.arg('--dns2', - dest="dns2", - metavar="", - help='Second DNS') -@utils.arg('--uuid', - dest="uuid", - metavar="", - help='Network UUID') -@utils.arg('--fixed-cidr', - dest="fixed_cidr", - metavar='', - help='IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)') -@utils.arg('--project-id', - dest="project_id", - metavar="", - help='Project ID') -@utils.arg('--priority', - dest="priority", - metavar="", - help='Network interface priority') -def do_network_create(cs, args): - """Create a network.""" - - if not (args.cidr or args.cidr_v6): - raise exceptions.CommandError( - "Must specify either fixed_range_v4 or fixed_range_v6") - kwargs = _filter_network_create_options(args) - if args.multi_host is not None: - kwargs['multi_host'] = bool(args.multi_host == 'T' or - strutils.bool_from_string(args.multi_host)) - - cs.networks.create(**kwargs) - - -@utils.arg('--limit', - dest="limit", - metavar="", - help='Number of images to return per request.') -@utils.service_type('image') -def do_image_list(cs, _args): - """Print a list of available images to boot from.""" - limit = _args.limit - image_list = cs.images.list(limit=limit) - - def parse_server_name(image): - try: - return image.server['id'] - except (AttributeError, KeyError): - return '' - - fmts = {'Server': parse_server_name} - utils.print_list(image_list, ['ID', 'Name', 'Status', 'Server'], - fmts, sortby_index=1) - - -@utils.arg('image', - metavar='', - help="Name or ID of image") -@utils.arg('action', - metavar='', - choices=['set', 'delete'], - help="Actions: 'set' or 'delete'") -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help='Metadata to add/update or delete (only key is necessary on delete)') -def do_image_meta(cs, args): - """Set or Delete metadata on an image.""" - image = _find_image(cs, args.image) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.images.set_meta(image, metadata) - elif args.action == 'delete': - cs.images.delete_meta(image, metadata.keys()) - - -def _extract_metadata(args): - metadata = {} - for metadatum in args.metadata[0]: - # Can only pass the key in on 'delete' - # So this doesn't have to have '=' - if metadatum.find('=') > -1: - (key, value) = metadatum.split('=', 1) - else: - key = metadatum - value = None - - metadata[key] = value - return metadata - - -def _print_image(image): - info = image._info.copy() - - # try to replace a server entity to just an id - server = info.pop('server', None) - try: - info['server'] = server['id'] - except (KeyError, TypeError): - pass - - # break up metadata and display each on its own row - properties = info.pop('properties', {}) - try: - for key, value in properties.items(): - _key = 'Property %s' % key - info[_key] = value - except AttributeError: - pass - - utils.print_dict(info) - - -def _print_flavor(flavor): - info = flavor._info.copy() - # ignore links, we don't need to present those - info.pop('links') - info.update({"extra_specs": _print_flavor_extra_specs(flavor)}) - utils.print_dict(info) - - -@utils.arg('image', - metavar='', - help="Name or ID of image") -@utils.service_type('image') -def do_image_show(cs, args): - """Show details about the given image.""" - image = _find_image(cs, args.image) - _print_image(image) - - -@utils.arg('image', metavar='', nargs='+', - help='Name or ID of image(s).') -def do_image_delete(cs, args): - """Delete specified image(s).""" - for image in args.image: - try: - _find_image(cs, image).delete() - except Exception as e: - print("Delete for image %s failed: %s" % (image, e)) - - -@utils.arg('--reservation-id', - dest='reservation_id', - metavar='', - default=None, - help='Only return servers that match reservation-id.') -@utils.arg('--reservation_id', - help=argparse.SUPPRESS) -@utils.arg('--ip', - dest='ip', - metavar='', - default=None, - help='Search with regular expression match by IP address.') -@utils.arg('--ip6', - dest='ip6', - metavar='', - default=None, - help='Search with regular expression match by IPv6 address.') -@utils.arg('--name', - dest='name', - metavar='', - default=None, - help='Search with regular expression match by name') -@utils.arg('--instance-name', - dest='instance_name', - metavar='', - default=None, - help='Search with regular expression match by server name.') -@utils.arg('--instance_name', - help=argparse.SUPPRESS) -@utils.arg('--status', - dest='status', - metavar='', - default=None, - help='Search by server status') -@utils.arg('--flavor', - dest='flavor', - metavar='', - default=None, - help='Search by flavor name or ID') -@utils.arg('--image', - dest='image', - metavar='', - default=None, - help='Search by image name or ID') -@utils.arg('--host', - dest='host', - metavar='', - default=None, - help='Search servers by hostname to which they are assigned ' - '(Admin only).') -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help='Display information from all tenants (Admin only).') -@utils.arg('--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -@utils.arg('--tenant', - # nova db searches by project_id - dest='tenant', - metavar='', - nargs='?', - help='Display information from single tenant (Admin only).') -@utils.arg('--fields', - default=None, - metavar='', - help='Comma-separated list of fields to display. ' - 'Use the show command to see which fields are available.') -@utils.arg('--deleted', - dest='deleted', - action="store_true", - default=False, - help='Only display deleted servers (Admin only).') -@utils.arg('--minimal', - dest='minimal', - action="store_true", - default=False, - help='Get only uuid and name.') -def do_list(cs, args): - """List active servers.""" - imageid = None - flavorid = None - if args.image: - imageid = _find_image(cs, args.image).id - if args.flavor: - flavorid = _find_flavor(cs, args.flavor).id - search_opts = { - 'all_tenants': args.all_tenants, - 'reservation_id': args.reservation_id, - 'ip': args.ip, - 'ip6': args.ip6, - 'name': args.name, - 'image': imageid, - 'flavor': flavorid, - 'status': args.status, - 'tenant_id': args.tenant, - 'host': args.host, - 'deleted': args.deleted, - 'instance_name': args.instance_name} - - filters = {'flavor': lambda f: f['id'], - 'security_groups': utils._format_security_groups} - - formatters = {} - field_titles = [] - if args.fields: - for field in args.fields.split(','): - field_title, formatter = utils._make_field_formatter(field, - filters) - field_titles.append(field_title) - formatters[field_title] = formatter - - id_col = 'ID' - - detailed = not args.minimal - - servers = cs.servers.list(detailed=detailed, - search_opts=search_opts) - convert = [('os-extended-server-attributes:hypervisor_hostname', 'host'), - ('os-extended-status:task_state', 'task_state'), - ('os-extended-server-attributes:instance_name', - 'instance_name'), - ('os-extended-status:power_state', 'power_state')] - _translate_keys(servers, convert) - _translate_extended_states(servers) - if args.minimal: - columns = [ - id_col, - 'Name'] - elif field_titles: - columns = [id_col] + field_titles - else: - columns = [ - id_col, - 'Name', - 'Status', - 'Task State', - 'Power State', - 'Networks' - ] - formatters['Networks'] = utils._format_servers_list_networks - utils.print_list(servers, columns, - formatters, sortby_index=1) - - -@utils.arg('--hard', - dest='reboot_type', - action='store_const', - const=servers.REBOOT_HARD, - default=servers.REBOOT_SOFT, - help='Perform a hard reboot (instead of a soft one).') -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help='Poll until reboot is complete.') -def do_reboot(cs, args): - """Reboot a server.""" - server = _find_server(cs, args.server) - server.reboot(args.reboot_type) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'rebooting', ['active'], - show_progress=False) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('image', metavar='', help="Name or ID of new image.") -@utils.arg('--rebuild-password', - dest='rebuild_password', - metavar='', - default=False, - help="Set the provided password on the rebuild server.") -@utils.arg('--rebuild_password', - help=argparse.SUPPRESS) -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help='Report the server rebuild progress until it completes.') -@utils.arg('--minimal', - dest='minimal', - action="store_true", - default=False, - help='Skips flavor/image lookups when showing servers') -def do_rebuild(cs, args): - """Shutdown, re-image, and re-boot a server.""" - server = _find_server(cs, args.server) - image = _find_image(cs, args.image) - - if args.rebuild_password is not False: - _password = args.rebuild_password - else: - _password = None - - kwargs = utils.get_resource_manager_extra_kwargs(do_rebuild, args) - server = server.rebuild(image, _password, **kwargs) - _print_server(cs, args, server) - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'rebuilding', ['active']) - - -@utils.arg('server', metavar='', - help='Name (old name) or ID of server.') -@utils.arg('name', metavar='', help='New name for the server.') -def do_rename(cs, args): - """Rename a server.""" - _find_server(cs, args.server).update(name=args.name) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('flavor', metavar='', help="Name or ID of new flavor.") -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help='Report the server resize progress until it completes.') -def do_resize(cs, args): - """Resize a server.""" - server = _find_server(cs, args.server) - flavor = _find_flavor(cs, args.flavor) - kwargs = utils.get_resource_manager_extra_kwargs(do_resize, args) - server.resize(flavor, **kwargs) - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'resizing', - ['active', 'verify_resize']) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_resize_confirm(cs, args): - """Confirm a previous resize.""" - _find_server(cs, args.server).confirm_resize() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_resize_revert(cs, args): - """Revert a previous resize (and return to the previous VM).""" - _find_server(cs, args.server).revert_resize() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help='Report the server migration progress until it completes.') -def do_migrate(cs, args): - """Migrate a server. The new host will be selected by the scheduler.""" - server = _find_server(cs, args.server) - server.migrate() - - if args.poll: - _poll_for_status(cs.servers.get, server.id, 'migrating', - ['active', 'verify_resize']) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_pause(cs, args): - """Pause a server.""" - _find_server(cs, args.server).pause() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_unpause(cs, args): - """Unpause a server.""" - _find_server(cs, args.server).unpause() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_stop(cs, args): - """Stop a server.""" - _find_server(cs, args.server).stop() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_start(cs, args): - """Start a server.""" - _find_server(cs, args.server).start() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_lock(cs, args): - """Lock a server.""" - _find_server(cs, args.server).lock() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_unlock(cs, args): - """Unlock a server.""" - _find_server(cs, args.server).unlock() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_suspend(cs, args): - """Suspend a server.""" - _find_server(cs, args.server).suspend() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_resume(cs, args): - """Resume a server.""" - _find_server(cs, args.server).resume() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_rescue(cs, args): - """Reboots a server into rescue mode, which starts the machine - from the initial image, attaching the current boot disk as secondary. - """ - utils.print_dict(_find_server(cs, args.server).rescue()[1]) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_unrescue(cs, args): - """Restart the server from normal boot disk again.""" - _find_server(cs, args.server).unrescue() - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_diagnostics(cs, args): - """Retrieve server diagnostics.""" - server = _find_server(cs, args.server) - utils.print_dict(cs.servers.diagnostics(server)[1], wrap=80) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_root_password(cs, args): - """ - Change the root password for a server. - """ - server = _find_server(cs, args.server) - p1 = getpass.getpass('New password: ') - p2 = getpass.getpass('Again: ') - if p1 != p2: - raise exceptions.CommandError("Passwords do not match.") - server.change_password(p1) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('name', metavar='', help='Name of snapshot.') -@utils.arg('--show', - dest='show', - action="store_true", - default=False, - help='Print image info.') -@utils.arg('--poll', - dest='poll', - action="store_true", - default=False, - help='Report the snapshot progress and poll until image creation is ' - 'complete.') -def do_image_create(cs, args): - """Create a new image by taking a snapshot of a running server.""" - server = _find_server(cs, args.server) - image_uuid = cs.servers.create_image(server, args.name) - - if args.poll: - _poll_for_status(cs.images.get, image_uuid, 'snapshotting', - ['active']) - - # NOTE(sirp): A race-condition exists between when the image finishes - # uploading and when the servers's `task_state` is cleared. To account - # for this, we need to poll a second time to ensure the `task_state` is - # cleared before returning, ensuring that a snapshot taken immediately - # after this function returns will succeed. - # - # A better long-term solution will be to separate 'snapshotting' and - # 'image-uploading' in Nova and clear the task-state once the VM - # snapshot is complete but before the upload begins. - task_state_field = "OS-EXT-STS:task_state" - if hasattr(server, task_state_field): - _poll_for_status(cs.servers.get, server.id, 'image_snapshot', - [None], status_field=task_state_field, - show_progress=False, silent=True) - - if args.show: - _print_image(cs.images.get(image_uuid)) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('name', metavar='', help='Name of the backup image.') -@utils.arg('backup_type', metavar='', - help='The backup type, like "daily" or "weekly".') -@utils.arg('rotation', metavar='', - help='Int parameter representing how many backups to keep around.') -def do_backup(cs, args): - """Backup a server by creating a 'backup' type snapshot.""" - _find_server(cs, args.server).backup(args.name, - args.backup_type, - args.rotation) - - -@utils.arg('server', - metavar='', - help="Name or ID of server") -@utils.arg('action', - metavar='', - choices=['set', 'delete'], - help="Actions: 'set' or 'delete'") -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help='Metadata to set or delete (only key is necessary on delete)') -def do_meta(cs, args): - """Set or Delete metadata on a server.""" - server = _find_server(cs, args.server) - metadata = _extract_metadata(args) - - if args.action == 'set': - cs.servers.set_meta(server, metadata) - elif args.action == 'delete': - cs.servers.delete_meta(server, metadata.keys()) - - -def _print_server(cs, args, server=None): - # By default when searching via name we will do a - # findall(name=blah) and due a REST /details which is not the same - # as a .get() and doesn't get the information about flavors and - # images. This fix it as we redo the call with the id which does a - # .get() to get all informations. - if not server: - server = _find_server(cs, args.server) - - minimal = getattr(args, "minimal", False) - - networks = server.networks - info = server._info.copy() - for network_label, address_list in networks.items(): - info['%s network' % network_label] = ', '.join(address_list) - - flavor = info.get('flavor', {}) - flavor_id = flavor.get('id', '') - if minimal: - info['flavor'] = flavor_id - else: - info['flavor'] = '%s (%s)' % (_find_flavor(cs, flavor_id).name, - flavor_id) - - if 'security_groups' in info: - # when we have multiple nics the info will include the - # security groups N times where N == number of nics. Be nice - # and only display it once. - info['security_groups'] = ', '.join( - sorted(set(group['name'] for group in info['security_groups']))) - - image = info.get('image', {}) - if image: - image_id = image.get('id', '') - if minimal: - info['image'] = image_id - else: - try: - info['image'] = '%s (%s)' % (_find_image(cs, image_id).name, - image_id) - except Exception: - info['image'] = '%s (%s)' % ("Image not found", image_id) - else: # Booted from volume - info['image'] = "Attempt to boot from volume - no image supplied" - - info.pop('links', None) - info.pop('addresses', None) - - utils.print_dict(info) - - -@utils.arg('--minimal', - dest='minimal', - action="store_true", - default=False, - help='Skips flavor/image lookups when showing servers') -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_show(cs, args): - """Show details about the given server.""" - _print_server(cs, args) - - -@utils.arg('server', metavar='', nargs='+', - help='Name or ID of server(s).') -def do_delete(cs, args): - """Immediately shut down and delete specified server(s).""" - failure_flag = False - - for server in args.server: - try: - _find_server(cs, server).delete() - print("Request to delete server %s has been accepted." % server) - except Exception as e: - failure_flag = True - print(e) - - if failure_flag: - raise exceptions.CommandError("Unable to delete the specified " - "server(s).") - - -def _find_server(cs, server): - """Get a server by name or ID.""" - return utils.find_resource(cs.servers, server) - - -def _find_image(cs, image): - """Get an image by name or ID.""" - return utils.find_resource(cs.images, image) - - -def _find_flavor(cs, flavor): - """Get a flavor by name, ID, or RAM size.""" - try: - return utils.find_resource(cs.flavors, flavor, is_public=None) - except exceptions.NotFound: - return cs.flavors.find(ram=flavor) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('network_id', - metavar='', - help='Network ID.') -def do_add_fixed_ip(cs, args): - """Add new IP address on a network to server.""" - server = _find_server(cs, args.server) - server.add_fixed_ip(args.network_id) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('address', metavar='
', help='IP Address.') -def do_remove_fixed_ip(cs, args): - """Remove an IP address from a server.""" - server = _find_server(cs, args.server) - server.remove_fixed_ip(args.address) - - -def _translate_availability_zone_keys(collection): - _translate_keys(collection, - [('zone_name', 'name'), ('zone_state', 'status')]) - - -@utils.arg('server', - metavar='', - help='Name or ID of server.') -@utils.arg('volume', - metavar='', - help='ID of the volume to attach.') -@utils.arg('device', metavar='', default=None, nargs='?', - help='Name of the device e.g. /dev/vdb. ' - 'Use "auto" for autoassign (if supported)') -@utils.arg('disk_bus', - metavar='', - default=None, - nargs='?', - help='The disk bus e.g. ide of the volume (optional).') -@utils.arg('device_type', - metavar='', - default=None, - nargs='?', - help='The device type e.g. cdrom of the volume (optional).') -def do_volume_attach(cs, args): - """Attach a volume to a server.""" - if args.device == 'auto': - args.device = None - - cs.volumes.attach_server_volume(_find_server(cs, args.server).id, - args.volume, args.device, args.disk_bus, - args.device_type) - - -@utils.arg('server', - metavar='', - help='Name or ID of server.') -@utils.arg('attachment_id', - metavar='', - help='Attachment ID of the volume.') -@utils.arg('new_volume', - metavar='', - help='ID of the volume to attach.') -def do_volume_update(cs, args): - """Update volume attachment.""" - cs.volumes.update_server_volume(_find_server(cs, args.server).id, - args.attachment_id, args.new_volume) - - -@utils.arg('server', - metavar='', - help='Name or ID of server.') -@utils.arg('attachment_id', - metavar='', - help='ID of the volume to detach.') -def do_volume_detach(cs, args): - """Detach a volume from a server.""" - cs.volumes.delete_server_volume(_find_server(cs, args.server).id, - args.attachment_id) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('console_type', - metavar='', - help='Type of vnc console ("novnc" or "xvpvnc").') -def do_get_vnc_console(cs, args): - """Get a vnc console to a server.""" - server = _find_server(cs, args.server) - data = server.get_vnc_console(args.console_type) - - class VNCConsole: - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([VNCConsole(data['console'])], ['Type', 'Url']) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('console_type', - metavar='', - help='Type of spice console ("spice-html5").') -def do_get_spice_console(cs, args): - """Get a spice console to a server.""" - server = _find_server(cs, args.server) - data = server.get_spice_console(args.console_type) - - class SPICEConsole: - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([SPICEConsole(data['console'])], ['Type', 'Url']) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('console_type', - metavar='', - help='Type of rdp console ("rdp-html5").') -def do_get_rdp_console(cs, args): - """Get a rdp console to a server.""" - server = _find_server(cs, args.server) - data = server.get_rdp_console(args.console_type) - - class RDPConsole: - def __init__(self, console_dict): - self.type = console_dict['type'] - self.url = console_dict['url'] - - utils.print_list([RDPConsole(data['console'])], ['Type', 'Url']) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('private_key', - metavar='', - help='Private key (used locally to decrypt password) (Optional). ' - 'When specified, the command displays the clear (decrypted) VM ' - 'password. When not specified, the ciphered VM password is ' - 'displayed.', - nargs='?', - default=None) -def do_get_password(cs, args): - """Get password for a server.""" - server = _find_server(cs, args.server) - data = server.get_password(args.private_key) - print(data) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_clear_password(cs, args): - """Clear password for a server.""" - server = _find_server(cs, args.server) - server.clear_password() - - -def _print_floating_ip_list(floating_ips): - convert = [('instance_id', 'server_id')] - _translate_keys(floating_ips, convert) - - utils.print_list(floating_ips, ['Ip', 'Server Id', 'Fixed Ip', 'Pool']) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('--length', - metavar='', - default=None, - help='Length in lines to tail.') -def do_console_log(cs, args): - """Get console log output of a server.""" - server = _find_server(cs, args.server) - data = server.get_console_output(length=args.length) - print(data) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('address', metavar='
', help='IP Address.') -@utils.arg('--fixed-address', - metavar='', - default=None, - help='Fixed IP Address to associate with.') -def do_add_floating_ip(cs, args): - """Add a floating IP address to a server.""" - server = _find_server(cs, args.server) - server.add_floating_ip(args.address, args.fixed_address) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('address', metavar='
', help='IP Address.') -def do_remove_floating_ip(cs, args): - """Remove a floating IP address from a server.""" - server = _find_server(cs, args.server) - server.remove_floating_ip(args.address) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('secgroup', metavar='', help='Name of Security Group.') -def do_add_secgroup(cs, args): - """Add a Security Group to a server.""" - server = _find_server(cs, args.server) - server.add_security_group(args.secgroup) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('secgroup', metavar='', help='Name of Security Group.') -def do_remove_secgroup(cs, args): - """Remove a Security Group from a server.""" - server = _find_server(cs, args.server) - server.remove_security_group(args.secgroup) - - -@utils.arg('pool', - metavar='', - help='Name of Floating IP Pool. (Optional)', - nargs='?', - default=None) -def do_floating_ip_create(cs, args): - """Allocate a floating IP for the current tenant.""" - _print_floating_ip_list([cs.floating_ips.create(pool=args.pool)]) - - -@utils.arg('address', metavar='
', help='IP of Floating Ip.') -def do_floating_ip_delete(cs, args): - """De-allocate a floating IP.""" - floating_ips = cs.floating_ips.list() - for floating_ip in floating_ips: - if floating_ip.ip == args.address: - return cs.floating_ips.delete(floating_ip.id) - raise exceptions.CommandError("Floating ip %s not found." % args.address) - - -def do_floating_ip_list(cs, _args): - """List floating ips for this tenant.""" - _print_floating_ip_list(cs.floating_ips.list()) - - -def do_floating_ip_pool_list(cs, _args): - """List all floating ip pools.""" - utils.print_list(cs.floating_ip_pools.list(), ['name']) - - -@utils.arg('--host', dest='host', metavar='', default=None, - help='Filter by host') -def do_floating_ip_bulk_list(cs, args): - """List all floating ips.""" - utils.print_list(cs.floating_ips_bulk.list(args.host), ['project_id', - 'address', - 'instance_uuid', - 'pool', - 'interface']) - - -@utils.arg('ip_range', metavar='', help='Address range to create') -@utils.arg('--pool', dest='pool', metavar='', default=None, - help='Pool for new Floating IPs') -@utils.arg('--interface', metavar='', default=None, - help='Interface for new Floating IPs') -def do_floating_ip_bulk_create(cs, args): - """Bulk create floating ips by range.""" - cs.floating_ips_bulk.create(args.ip_range, args.pool, args.interface) - - -@utils.arg('ip_range', metavar='', help='Address range to delete') -def do_floating_ip_bulk_delete(cs, args): - """Bulk delete floating ips by range.""" - cs.floating_ips_bulk.delete(args.ip_range) - - -def _print_dns_list(dns_entries): - utils.print_list(dns_entries, ['ip', 'name', 'domain']) - - -def _print_domain_list(domain_entries): - utils.print_list(domain_entries, ['domain', 'scope', - 'project', 'availability_zone']) - - -def do_dns_domains(cs, args): - """Print a list of available dns domains.""" - domains = cs.dns_domains.domains() - _print_domain_list(domains) - - -@utils.arg('domain', metavar='', help='DNS domain') -@utils.arg('--ip', metavar='', help='ip address', default=None) -@utils.arg('--name', metavar='', help='DNS name', default=None) -def do_dns_list(cs, args): - """List current DNS entries for domain and ip or domain and name.""" - if not (args.ip or args.name): - raise exceptions.CommandError( - "You must specify either --ip or --name") - if args.name: - entry = cs.dns_entries.get(args.domain, args.name) - _print_dns_list([entry]) - else: - entries = cs.dns_entries.get_for_ip(args.domain, - ip=args.ip) - _print_dns_list(entries) - - -@utils.arg('ip', metavar='', help='ip address') -@utils.arg('name', metavar='', help='DNS name') -@utils.arg('domain', metavar='', help='DNS domain') -@utils.arg('--type', metavar='', help='dns type (e.g. "A")', default='A') -def do_dns_create(cs, args): - """Create a DNS entry for domain, name and ip.""" - cs.dns_entries.create(args.domain, args.name, args.ip, args.type) - - -@utils.arg('domain', metavar='', help='DNS domain') -@utils.arg('name', metavar='', help='DNS name') -def do_dns_delete(cs, args): - """Delete the specified DNS entry.""" - cs.dns_entries.delete(args.domain, args.name) - - -@utils.arg('domain', metavar='', help='DNS domain') -def do_dns_delete_domain(cs, args): - """Delete the specified DNS domain.""" - cs.dns_domains.delete(args.domain) - - -@utils.arg('domain', metavar='', help='DNS domain') -@utils.arg('--availability-zone', - metavar='', - default=None, - help='Limit access to this domain to servers ' - 'in the specified availability zone.') -@utils.arg('--availability_zone', - help=argparse.SUPPRESS) -def do_dns_create_private_domain(cs, args): - """Create the specified DNS domain.""" - cs.dns_domains.create_private(args.domain, - args.availability_zone) - - -@utils.arg('domain', metavar='', help='DNS domain') -@utils.arg('--project', metavar='', - help='Limit access to this domain to users ' - 'of the specified project.', - default=None) -def do_dns_create_public_domain(cs, args): - """Create the specified DNS domain.""" - cs.dns_domains.create_public(args.domain, - args.project) - - -def _print_secgroup_rules(rules): - class FormattedRule: - def __init__(self, obj): - items = (obj if isinstance(obj, dict) else obj._info).items() - for k, v in items: - if k == 'ip_range': - v = v.get('cidr') - elif k == 'group': - k = 'source_group' - v = v.get('name') - if v is None: - v = '' - - setattr(self, k, v) - - rules = [FormattedRule(rule) for rule in rules] - utils.print_list(rules, ['IP Protocol', 'From Port', 'To Port', - 'IP Range', 'Source Group']) - - -def _print_secgroups(secgroups): - utils.print_list(secgroups, ['Id', 'Name', 'Description']) - - -def _get_secgroup(cs, secgroup): - # Check secgroup is an ID - if uuidutils.is_uuid_like(strutils.safe_encode(secgroup)): - try: - return cs.security_groups.get(secgroup) - except exceptions.NotFound: - pass - - # Check secgroup as a name - match_found = False - for s in cs.security_groups.list(): - encoding = (locale.getpreferredencoding() or - sys.stdin.encoding or - 'UTF-8') - s.name = s.name.encode(encoding) - if secgroup == s.name: - if match_found is not False: - msg = ("Multiple security group matches found for name" - " '%s', use an ID to be more specific." % secgroup) - raise exceptions.NoUniqueMatch(msg) - match_found = s - if match_found is False: - raise exceptions.CommandError("Secgroup ID or name '%s' not found." - % secgroup) - return match_found - - -@utils.arg('secgroup', - metavar='', - help='ID or name of security group.') -@utils.arg('ip_proto', - metavar='', - help='IP protocol (icmp, tcp, udp).') -@utils.arg('from_port', - metavar='', - help='Port at start of range.') -@utils.arg('to_port', - metavar='', - help='Port at end of range.') -@utils.arg('cidr', metavar='', help='CIDR for address range.') -def do_secgroup_add_rule(cs, args): - """Add a rule to a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - rule = cs.security_group_rules.create(secgroup.id, - args.ip_proto, - args.from_port, - args.to_port, - args.cidr) - _print_secgroup_rules([rule]) - - -@utils.arg('secgroup', - metavar='', - help='ID or name of security group.') -@utils.arg('ip_proto', - metavar='', - help='IP protocol (icmp, tcp, udp).') -@utils.arg('from_port', - metavar='', - help='Port at start of range.') -@utils.arg('to_port', - metavar='', - help='Port at end of range.') -@utils.arg('cidr', metavar='', help='CIDR for address range.') -def do_secgroup_delete_rule(cs, args): - """Delete a rule from a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - for rule in secgroup.rules: - if (rule['ip_protocol'] and - rule['ip_protocol'].upper() == args.ip_proto.upper() and - rule['from_port'] == int(args.from_port) and - rule['to_port'] == int(args.to_port) and - rule['ip_range']['cidr'] == args.cidr): - _print_secgroup_rules([rule]) - return cs.security_group_rules.delete(rule['id']) - - raise exceptions.CommandError("Rule not found") - - -@utils.arg('name', metavar='', help='Name of security group.') -@utils.arg('description', metavar='', - help='Description of security group.') -def do_secgroup_create(cs, args): - """Create a security group.""" - secgroup = cs.security_groups.create(args.name, args.description) - _print_secgroups([secgroup]) - - -@utils.arg('secgroup', - metavar='', - help='ID or name of security group.') -@utils.arg('name', metavar='', help='Name of security group.') -@utils.arg('description', metavar='', - help='Description of security group.') -def do_secgroup_update(cs, args): - """Update a security group.""" - sg = _get_secgroup(cs, args.secgroup) - secgroup = cs.security_groups.update(sg, args.name, args.description) - _print_secgroups([secgroup]) - - -@utils.arg('secgroup', - metavar='', - help='ID or name of security group.') -def do_secgroup_delete(cs, args): - """Delete a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - cs.security_groups.delete(secgroup) - _print_secgroups([secgroup]) - - -@utils.arg('--all-tenants', - dest='all_tenants', - metavar='<0|1>', - nargs='?', - type=int, - const=1, - default=int(strutils.bool_from_string( - os.environ.get("ALL_TENANTS", 'false'), True)), - help='Display information from all tenants (Admin only).') -@utils.arg('--all_tenants', - nargs='?', - type=int, - const=1, - help=argparse.SUPPRESS) -def do_secgroup_list(cs, args): - """List security groups for the current tenant.""" - search_opts = {'all_tenants': args.all_tenants} - columns = ['Id', 'Name', 'Description'] - if args.all_tenants: - columns.append('Tenant_ID') - groups = cs.security_groups.list(search_opts=search_opts) - utils.print_list(groups, columns) - - -@utils.arg('secgroup', - metavar='', - help='ID or name of security group.') -def do_secgroup_list_rules(cs, args): - """List rules for a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - _print_secgroup_rules(secgroup.rules) - - -@utils.arg('secgroup', - metavar='', - help='ID or name of security group.') -@utils.arg('source_group', - metavar='', - help='ID or name of source group.') -@utils.arg('ip_proto', - metavar='', - help='IP protocol (icmp, tcp, udp).') -@utils.arg('from_port', - metavar='', - help='Port at start of range.') -@utils.arg('to_port', - metavar='', - help='Port at end of range.') -def do_secgroup_add_group_rule(cs, args): - """Add a source group rule to a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - source_group = _get_secgroup(cs, args.source_group) - params = {} - params['group_id'] = source_group.id - - if args.ip_proto or args.from_port or args.to_port: - if not (args.ip_proto and args.from_port and args.to_port): - raise exceptions.CommandError("ip_proto, from_port, and to_port" - " must be specified together") - params['ip_protocol'] = args.ip_proto.upper() - params['from_port'] = args.from_port - params['to_port'] = args.to_port - - rule = cs.security_group_rules.create(secgroup.id, **params) - _print_secgroup_rules([rule]) - - -@utils.arg('secgroup', - metavar='', - help='ID or name of security group.') -@utils.arg('source_group', - metavar='', - help='ID or name of source group.') -@utils.arg('ip_proto', - metavar='', - help='IP protocol (icmp, tcp, udp).') -@utils.arg('from_port', - metavar='', - help='Port at start of range.') -@utils.arg('to_port', - metavar='', - help='Port at end of range.') -def do_secgroup_delete_group_rule(cs, args): - """Delete a source group rule from a security group.""" - secgroup = _get_secgroup(cs, args.secgroup) - source_group = _get_secgroup(cs, args.source_group) - params = {} - params['group_name'] = source_group.name - - if args.ip_proto or args.from_port or args.to_port: - if not (args.ip_proto and args.from_port and args.to_port): - raise exceptions.CommandError("ip_proto, from_port, and to_port" - " must be specified together") - params['ip_protocol'] = args.ip_proto.upper() - params['from_port'] = int(args.from_port) - params['to_port'] = int(args.to_port) - - for rule in secgroup.rules: - if (rule.get('ip_protocol').upper() == params.get( - 'ip_protocol').upper() and - rule.get('from_port') == params.get('from_port') and - rule.get('to_port') == params.get('to_port') and - rule.get('group', {}).get('name') == - params.get('group_name')): - return cs.security_group_rules.delete(rule['id']) - - raise exceptions.CommandError("Rule not found") - - -@utils.arg('name', metavar='', help='Name of key.') -@utils.arg('--pub-key', - metavar='', - default=None, - help='Path to a public ssh key.') -@utils.arg('--pub_key', - help=argparse.SUPPRESS) -def do_keypair_add(cs, args): - """Create a new key pair for use with servers.""" - name = args.name - pub_key = args.pub_key - - if pub_key: - try: - with open(os.path.expanduser(pub_key)) as f: - pub_key = f.read() - except IOError as e: - raise exceptions.CommandError("Can't open or read '%s': %s" % - (pub_key, e)) - - keypair = cs.keypairs.create(name, pub_key) - - if not pub_key: - private_key = keypair.private_key - print(private_key) - - -@utils.arg('name', metavar='', help='Keypair name to delete.') -def do_keypair_delete(cs, args): - """Delete keypair given by its name.""" - name = _find_keypair(cs, args.name) - cs.keypairs.delete(name) - - -def do_keypair_list(cs, args): - """Print a list of keypairs for a user""" - keypairs = cs.keypairs.list() - columns = ['Name', 'Fingerprint'] - utils.print_list(keypairs, columns) - - -def _print_keypair(keypair): - kp = keypair._info.copy() - pk = kp.pop('public_key') - utils.print_dict(kp) - print("Public key: %s" % pk) - - -@utils.arg('keypair', - metavar='', - help="Name or ID of keypair") -def do_keypair_show(cs, args): - """Show details about the given keypair.""" - keypair = _find_keypair(cs, args.keypair) - _print_keypair(keypair) - - -def _find_keypair(cs, keypair): - """Get a keypair by name or ID.""" - return utils.find_resource(cs.keypairs, keypair) - - -@utils.arg('--start', metavar='', - help='Usage range start date ex 2012-01-20 (default: 4 weeks ago)', - default=None) -@utils.arg('--end', metavar='', - help='Usage range end date, ex 2012-01-20 (default: tomorrow) ', - default=None) -def do_usage_list(cs, args): - """List usage data for all tenants.""" - dateformat = "%Y-%m-%d" - rows = ["Tenant ID", "Servers", "RAM MB-Hours", "CPU Hours", - "Disk GB-Hours"] - - now = timeutils.utcnow() - - if args.start: - start = datetime.datetime.strptime(args.start, dateformat) - else: - start = now - datetime.timedelta(weeks=4) - - if args.end: - end = datetime.datetime.strptime(args.end, dateformat) - else: - end = now + datetime.timedelta(days=1) - - def simplify_usage(u): - simplerows = map(lambda x: x.lower().replace(" ", "_"), rows) - - setattr(u, simplerows[0], u.tenant_id) - setattr(u, simplerows[1], "%d" % len(u.server_usages)) - setattr(u, simplerows[2], "%.2f" % u.total_memory_mb_usage) - setattr(u, simplerows[3], "%.2f" % u.total_vcpus_usage) - setattr(u, simplerows[4], "%.2f" % u.total_local_gb_usage) - - usage_list = cs.usage.list(start, end, detailed=True) - - print("Usage from %s to %s:" % (start.strftime(dateformat), - end.strftime(dateformat))) - - for usage in usage_list: - simplify_usage(usage) - - utils.print_list(usage_list, rows) - - -@utils.arg('--start', metavar='', - help='Usage range start date ex 2012-01-20 (default: 4 weeks ago)', - default=None) -@utils.arg('--end', metavar='', - help='Usage range end date, ex 2012-01-20 (default: tomorrow) ', - default=None) -@utils.arg('--tenant', metavar='', - default=None, - help='UUID or name of tenant to get usage for.') -def do_usage(cs, args): - """Show usage data for a single tenant.""" - dateformat = "%Y-%m-%d" - rows = ["Servers", "RAM MB-Hours", "CPU Hours", "Disk GB-Hours"] - - now = timeutils.utcnow() - - if args.start: - start = datetime.datetime.strptime(args.start, dateformat) - else: - start = now - datetime.timedelta(weeks=4) - - if args.end: - end = datetime.datetime.strptime(args.end, dateformat) - else: - end = now + datetime.timedelta(days=1) - - def simplify_usage(u): - simplerows = map(lambda x: x.lower().replace(" ", "_"), rows) - - setattr(u, simplerows[0], "%d" % len(u.server_usages)) - setattr(u, simplerows[1], "%.2f" % u.total_memory_mb_usage) - setattr(u, simplerows[2], "%.2f" % u.total_vcpus_usage) - setattr(u, simplerows[3], "%.2f" % u.total_local_gb_usage) - - if args.tenant: - usage = cs.usage.get(args.tenant, start, end) - else: - usage = cs.usage.get(cs.client.tenant_id, start, end) - - print("Usage from %s to %s:" % (start.strftime(dateformat), - end.strftime(dateformat))) - - if getattr(usage, 'total_vcpus_usage', None): - simplify_usage(usage) - utils.print_list([usage], rows) - else: - print('None') - - -@utils.arg('pk_filename', - metavar='', - nargs='?', - default='pk.pem', - help='Filename for the private key [Default: pk.pem]') -@utils.arg('cert_filename', - metavar='', - nargs='?', - default='cert.pem', - help='Filename for the X.509 certificate [Default: cert.pem]') -def do_x509_create_cert(cs, args): - """Create x509 cert for a user in tenant.""" - - if os.path.exists(args.pk_filename): - raise exceptions.CommandError("Unable to write privatekey - %s exists." - % args.pk_filename) - if os.path.exists(args.cert_filename): - raise exceptions.CommandError("Unable to write x509 cert - %s exists." - % args.cert_filename) - - certs = cs.certs.create() - - try: - old_umask = os.umask(0o377) - with open(args.pk_filename, 'w') as private_key: - private_key.write(certs.private_key) - print("Wrote private key to %s" % args.pk_filename) - finally: - os.umask(old_umask) - - with open(args.cert_filename, 'w') as cert: - cert.write(certs.data) - print("Wrote x509 certificate to %s" % args.cert_filename) - - -@utils.arg('filename', - metavar='', - nargs='?', - default='cacert.pem', - help='Filename to write the x509 root cert.') -def do_x509_get_root_cert(cs, args): - """Fetch the x509 root cert.""" - if os.path.exists(args.filename): - raise exceptions.CommandError("Unable to write x509 root cert - \ - %s exists." % args.filename) - - with open(args.filename, 'w') as cert: - cacert = cs.certs.get() - cert.write(cacert.data) - print("Wrote x509 root cert to %s" % args.filename) - - -@utils.arg('--hypervisor', metavar='', default=None, - help='type of hypervisor.') -def do_agent_list(cs, args): - """List all builds.""" - result = cs.agents.list(args.hypervisor) - columns = ["Agent_id", "Hypervisor", "OS", "Architecture", "Version", - 'Md5hash', 'Url'] - utils.print_list(result, columns) - - -@utils.arg('os', metavar='', help='type of os.') -@utils.arg('architecture', metavar='', - help='type of architecture') -@utils.arg('version', metavar='', help='version') -@utils.arg('url', metavar='', help='url') -@utils.arg('md5hash', metavar='', help='md5 hash') -@utils.arg('hypervisor', metavar='', default='xen', - help='type of hypervisor.') -def do_agent_create(cs, args): - """Create new agent build.""" - result = cs.agents.create(args.os, args.architecture, - args.version, args.url, - args.md5hash, args.hypervisor) - utils.print_dict(result._info.copy()) - - -@utils.arg('id', metavar='', help='id of the agent-build') -def do_agent_delete(cs, args): - """Delete existing agent build.""" - cs.agents.delete(args.id) - - -@utils.arg('id', metavar='', help='id of the agent-build') -@utils.arg('version', metavar='', help='version') -@utils.arg('url', metavar='', help='url') -@utils.arg('md5hash', metavar='', help='md5hash') -def do_agent_modify(cs, args): - """Modify existing agent build.""" - result = cs.agents.update(args.id, args.version, - args.url, args.md5hash) - utils.print_dict(result._info) - - -def _find_aggregate(cs, aggregate): - """Get a aggregate by name or ID.""" - return utils.find_resource(cs.aggregates, aggregate) - - -def do_aggregate_list(cs, args): - """Print a list of all aggregates.""" - aggregates = cs.aggregates.list() - columns = ['Id', 'Name', 'Availability Zone'] - utils.print_list(aggregates, columns) - - -@utils.arg('name', metavar='', help='Name of aggregate.') -@utils.arg('availability_zone', - metavar='', - default=None, - nargs='?', - help='The availability zone of the aggregate (optional).') -def do_aggregate_create(cs, args): - """Create a new aggregate with the specified details.""" - aggregate = cs.aggregates.create(args.name, args.availability_zone) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', - help='Name or ID of aggregate to delete.') -def do_aggregate_delete(cs, args): - """Delete the aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - cs.aggregates.delete(aggregate) - print("Aggregate %s has been successfully deleted." % aggregate.id) - - -@utils.arg('aggregate', metavar='', - help='Name or ID of aggregate to update.') -@utils.arg('name', metavar='', help='Name of aggregate.') -@utils.arg('availability_zone', - metavar='', - nargs='?', - default=None, - help='The availability zone of the aggregate.') -def do_aggregate_update(cs, args): - """Update the aggregate's name and optionally availability zone.""" - aggregate = _find_aggregate(cs, args.aggregate) - updates = {"name": args.name} - if args.availability_zone: - updates["availability_zone"] = args.availability_zone - - aggregate = cs.aggregates.update(aggregate.id, updates) - print("Aggregate %s has been successfully updated." % aggregate.id) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', - help='Name or ID of aggregate to update.') -@utils.arg('metadata', - metavar='', - nargs='+', - action='append', - default=[], - help='Metadata to add/update to aggregate') -def do_aggregate_set_metadata(cs, args): - """Update the metadata associated with the aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - metadata = _extract_metadata(args) - currentmetadata = getattr(aggregate, 'metadata', {}) - if set(metadata.items()) & set(currentmetadata.items()): - raise exceptions.CommandError("metadata already exists") - for key, value in metadata.items(): - if value is None and key not in currentmetadata: - raise exceptions.CommandError("metadata key %s does not exist" - " hence can not be deleted" - % key) - aggregate = cs.aggregates.set_metadata(aggregate.id, metadata) - print("Metadata has been successfully updated for aggregate %s." % - aggregate.id) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', help='Name or ID of aggregate.') -@utils.arg('host', metavar='', help='The host to add to the aggregate.') -def do_aggregate_add_host(cs, args): - """Add the host to the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - aggregate = cs.aggregates.add_host(aggregate.id, args.host) - print("Host %s has been successfully added for aggregate %s " % - (args.host, aggregate.id)) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', help='Name or ID of aggregate.') -@utils.arg('host', metavar='', - help='The host to remove from the aggregate.') -def do_aggregate_remove_host(cs, args): - """Remove the specified host from the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - aggregate = cs.aggregates.remove_host(aggregate.id, args.host) - print("Host %s has been successfully removed from aggregate %s " % - (args.host, aggregate.id)) - _print_aggregate_details(aggregate) - - -@utils.arg('aggregate', metavar='', help='Name or ID of aggregate.') -def do_aggregate_details(cs, args): - """Show details of the specified aggregate.""" - aggregate = _find_aggregate(cs, args.aggregate) - _print_aggregate_details(aggregate) - - -def _print_aggregate_details(aggregate): - columns = ['Id', 'Name', 'Availability Zone', 'Hosts', 'Metadata'] - - def parser_metadata(fields): - return utils.pretty_choice_dict(getattr(fields, 'metadata', {}) or {}) - - def parser_hosts(fields): - return utils.pretty_choice_list(getattr(fields, 'hosts', [])) - - formatters = { - 'Metadata': parser_metadata, - 'Hosts': parser_hosts, - } - utils.print_list([aggregate], columns, formatters=formatters) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('host', metavar='', default=None, nargs='?', - help='destination host name.') -@utils.arg('--block-migrate', - action='store_true', - dest='block_migrate', - default=False, - help='True in case of block_migration.\ - (Default=False:live_migration)') -@utils.arg('--block_migrate', - action='store_true', - help=argparse.SUPPRESS) -@utils.arg('--disk-over-commit', - action='store_true', - dest='disk_over_commit', - default=False, - help='Allow overcommit.(Default=False)') -@utils.arg('--disk_over_commit', - action='store_true', - help=argparse.SUPPRESS) -def do_live_migration(cs, args): - """Migrate running server to a new machine.""" - _find_server(cs, args.server).live_migrate(args.host, - args.block_migrate, - args.disk_over_commit) - - -@utils.arg('server', metavar='', nargs='+', - help='Name or ID of server(s).') -@utils.arg('--active', action='store_const', dest='state', - default='error', const='active', - help='Request the server be reset to "active" state instead ' - 'of "error" state (the default).') -def do_reset_state(cs, args): - """Reset the state of a server.""" - failure_flag = False - - for server in args.server: - try: - _find_server(cs, server).reset_state(args.state) - except Exception as e: - failure_flag = True - msg = "Reset state for server %s failed: %s" % (server, e) - print(msg) - - if failure_flag: - msg = "Unable to reset the state for the specified server(s)." - raise exceptions.CommandError(msg) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_reset_network(cs, args): - """Reset network of a server.""" - _find_server(cs, args.server).reset_network() - - -@utils.arg('--host', metavar='', default=None, - help='Name of host.') -@utils.arg('--binary', metavar='', default=None, - help='Service binary.') -def do_service_list(cs, args): - """Show a list of all running services. Filter by host & binary.""" - result = cs.services.list(host=args.host, binary=args.binary) - columns = ["Binary", "Host", "Zone", "Status", "State", "Updated_at"] - # NOTE(sulo): we check if the response has disabled_reason - # so as not to add the column when the extended ext is not enabled. - if hasattr(result[0], 'disabled_reason'): - columns.append("Disabled Reason") - - # NOTE(gtt): After https://review.openstack.org/#/c/39998/ nova will - # show id in response. - if result and hasattr(result[0], 'id'): - columns.insert(0, "Id") - - utils.print_list(result, columns) - - -@utils.arg('host', metavar='', help='Name of host.') -@utils.arg('binary', metavar='', help='Service binary.') -def do_service_enable(cs, args): - """Enable the service.""" - result = cs.services.enable(args.host, args.binary) - utils.print_list([result], ['Host', 'Binary', 'Status']) - - -@utils.arg('host', metavar='', help='Name of host.') -@utils.arg('binary', metavar='', help='Service binary.') -@utils.arg('--reason', metavar='', - help='Reason for disabling service.') -def do_service_disable(cs, args): - """Disable the service.""" - if args.reason: - result = cs.services.disable_log_reason(args.host, args.binary, - args.reason) - utils.print_list([result], ['Host', 'Binary', 'Status', - 'Disabled Reason']) - else: - result = cs.services.disable(args.host, args.binary) - utils.print_list([result], ['Host', 'Binary', 'Status']) - - -@utils.arg('id', metavar='', help='Id of service.') -def do_service_delete(cs, args): - """Delete the service.""" - cs.services.delete(args.id) - - -@utils.arg('fixed_ip', metavar='', help='Fixed IP Address.') -def do_fixed_ip_get(cs, args): - """Retrieve info on a fixed ip.""" - result = cs.fixed_ips.get(args.fixed_ip) - utils.print_list([result], ['address', 'cidr', 'hostname', 'host']) - - -@utils.arg('fixed_ip', metavar='', help='Fixed IP Address.') -def do_fixed_ip_reserve(cs, args): - """Reserve a fixed IP.""" - cs.fixed_ips.reserve(args.fixed_ip) - - -@utils.arg('fixed_ip', metavar='', help='Fixed IP Address.') -def do_fixed_ip_unreserve(cs, args): - """Unreserve a fixed IP.""" - cs.fixed_ips.unreserve(args.fixed_ip) - - -@utils.arg('host', metavar='', help='Name of host.') -def do_host_describe(cs, args): - """Describe a specific host.""" - result = cs.hosts.get(args.host) - columns = ["HOST", "PROJECT", "cpu", "memory_mb", "disk_gb"] - utils.print_list(result, columns) - - -@utils.arg('--zone', metavar='', default=None, - help='Filters the list, returning only those ' - 'hosts in the availability zone .') -@utils.arg('--service-name', metavar='', default=None, - help='Filters the list, returning only those ' - 'hosts providing service .') -def do_host_list(cs, args): - """List all hosts by service.""" - columns = ["host_name", "service", "zone"] - result = cs.hosts.list(args.zone, args.service_name) - utils.print_list(result, columns) - - -@utils.arg('host', metavar='', help='Name of host.') -@utils.arg('--status', metavar='', default=None, dest='status', - help='Either enable or disable a host.') -@utils.arg('--maintenance', - metavar='', - default=None, - dest='maintenance', - help='Either put or resume host to/from maintenance.') -def do_host_update(cs, args): - """Update host settings.""" - updates = {} - columns = ["HOST"] - if args.status: - updates['status'] = args.status - columns.append("status") - if args.maintenance: - updates['maintenance_mode'] = args.maintenance - columns.append("maintenance_mode") - result = cs.hosts.update(args.host, updates) - utils.print_list([result], columns) - - -@utils.arg('host', metavar='', help='Name of host.') -@utils.arg('--action', metavar='', dest='action', - choices=['startup', 'shutdown', 'reboot'], - help='A power action: startup, reboot, or shutdown.') -def do_host_action(cs, args): - """Perform a power action on a host.""" - result = cs.hosts.host_action(args.host, args.action) - utils.print_list([result], ['HOST', 'power_action']) - - -def _find_hypervisor(cs, hypervisor): - """Get a hypervisor by name or ID.""" - return utils.find_resource(cs.hypervisors, hypervisor) - - -@utils.arg('--matching', metavar='', default=None, - help='List hypervisors matching the given .') -def do_hypervisor_list(cs, args): - """List hypervisors.""" - columns = ['ID', 'Hypervisor hostname'] - if args.matching: - utils.print_list(cs.hypervisors.search(args.matching), columns) - else: - # Since we're not outputting detail data, choose - # detailed=False for server-side efficiency - utils.print_list(cs.hypervisors.list(False), columns) - - -@utils.arg('hostname', metavar='', - help='The hypervisor hostname (or pattern) to search for.') -def do_hypervisor_servers(cs, args): - """List servers belonging to specific hypervisors.""" - # Get a list of hypervisors first - hypers = cs.hypervisors.search(args.hostname) - - class InstanceOnHyper(object): - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - # Massage the result into a list to be displayed - servers = [] - for hyper in hypers: - # Get a list of servers for each hypervisor - hyper_host = hyper.hypervisor_hostname - hyper_id = hyper.id - - hyper_servers = cs.hypervisors.servers(hyper_id) - if hasattr(hyper_servers, 'servers'): - print(hyper_servers.servers) - servers.extend([InstanceOnHyper(id=serv['id'], - name=serv['name'], - hypervisor_hostname=hyper_host, - hypervisor_id=hyper_id) - for serv in hyper_servers.servers]) - - # Output the data - utils.print_list(servers, ['ID', 'Name', 'Hypervisor ID', - 'Hypervisor Hostname']) - - -@utils.arg('hypervisor', - metavar='', - help='Name or ID of the hypervisor to show the details of.') -def do_hypervisor_show(cs, args): - """Display the details of the specified hypervisor.""" - hyper = _find_hypervisor(cs, args.hypervisor) - - # Build up the dict - info = hyper._info.copy() - info['service_id'] = info['service']['id'] - info['service_host'] = info['service']['host'] - del info['service'] - - utils.print_dict(info) - - -@utils.arg('hypervisor', - metavar='', - help='Name or ID of the hypervisor to show the uptime of.') -def do_hypervisor_uptime(cs, args): - """Display the uptime of the specified hypervisor.""" - hyper = _find_hypervisor(cs, args.hypervisor) - hyper = cs.hypervisors.uptime(hyper) - - # Output the uptime information - utils.print_dict(hyper._info.copy()) - - -def do_hypervisor_stats(cs, args): - """Get hypervisor statistics over all compute nodes.""" - stats = cs.hypervisors.statistics() - utils.print_dict(stats._info.copy()) - - -def ensure_service_catalog_present(cs): - if not hasattr(cs.client, 'service_catalog'): - # Turn off token caching and re-auth - cs.client.unauthenticate() - cs.client.use_token_cache(False) - cs.client.authenticate() - - -def do_endpoints(cs, _args): - """Discover endpoints that get returned from the authenticate services.""" - ensure_service_catalog_present(cs) - - catalog = cs.client.service_catalog.catalog - region = cs.client.region_name - - for service in catalog['access']['serviceCatalog']: - name, endpoints = service["name"], service["endpoints"] - - try: - endpoint = _get_first_endpoint(endpoints, region) - utils.print_dict(endpoint, name) - except LookupError: - print(_("WARNING: %(service)s has no endpoint in %(region)s! " - "Available endpoints for this service:") % - {'service': name, 'region': region}) - for other_endpoint in endpoints: - utils.print_dict(other_endpoint, name) - - -def _get_first_endpoint(endpoints, region): - """Find the first suitable endpoint in endpoints. - - If there is only one endpoint, return it. If there is more than - one endpoint, return the first one with the given region. If there - are no endpoints, or there is more than one endpoint but none of - them match the given region, raise KeyError. - - """ - if len(endpoints) == 1: - return endpoints[0] - else: - for candidate_endpoint in endpoints: - if candidate_endpoint["region"] == region: - return candidate_endpoint - - raise LookupError("No suitable endpoint found") - - -@utils.arg('--wrap', dest='wrap', metavar='', default=64, - help='wrap PKI tokens to a specified length, or 0 to disable') -def do_credentials(cs, _args): - """Show user credentials returned from auth.""" - ensure_service_catalog_present(cs) - catalog = cs.client.service_catalog.catalog - utils.print_dict(catalog['access']['user'], "User Credentials", - wrap=int(_args.wrap)) - utils.print_dict(catalog['access']['token'], "Token", wrap=int(_args.wrap)) - - -def do_extension_list(cs, _args): - """ - List all the os-api extensions that are available. - """ - extensions = cs.list_extensions.show_all() - fields = ["Name", "Summary", "Alias", "Version"] - utils.print_list(extensions, fields) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('--port', - dest='port', - action='store', - type=int, - default=22, - help='Optional flag to indicate which port to use for ssh. ' - '(Default=22)') -@utils.arg('--private', - dest='private', - action='store_true', - default=False, - help=argparse.SUPPRESS) -@utils.arg('--address-type', - dest='address_type', - action='store', - type=str, - default='floating', - help='Optional flag to indicate which IP type to use. Possible values ' - 'includes fixed and floating (the Default).') -@utils.arg('--network', metavar='', - help='Network to use for the ssh.', default=None) -@utils.arg('--ipv6', - dest='ipv6', - action='store_true', - default=False, - help='Optional flag to indicate whether to use an IPv6 address ' - 'attached to a server. (Defaults to IPv4 address)') -@utils.arg('--login', metavar='', help='Login to use.', default="root") -@utils.arg('-i', '--identity', - dest='identity', - help='Private key file, same as the -i option to the ssh command.', - default='') -@utils.arg('--extra-opts', - dest='extra', - help='Extra options to pass to ssh. see: man ssh', - default='') -def do_ssh(cs, args): - """SSH into a server.""" - if '@' in args.server: - user, server = args.server.split('@', 1) - args.login = user - args.server = server - - addresses = _find_server(cs, args.server).addresses - address_type = "fixed" if args.private else args.address_type - version = 6 if args.ipv6 else 4 - pretty_version = 'IPv%d' % version - - # Select the network to use. - if args.network: - network_addresses = addresses.get(args.network) - if not network_addresses: - msg = _("Server '%(server)s' is not attached to network " - "'%(network)s'") - raise exceptions.ResourceNotFound( - msg % {'server': args.server, 'network': args.network}) - else: - if len(addresses) > 1: - msg = _("Server '%(server)s' is attached to more than one network." - " Please pick the network to use.") - raise exceptions.CommandError(msg % {'server': args.server}) - elif not addresses: - msg = _("Server '%(server)s' is not attached to any network.") - raise exceptions.CommandError(msg % {'server': args.server}) - else: - network_addresses = list(six.itervalues(addresses))[0] - - # Select the address in the selected network. - # If the extension is not present, we assume the address to be floating. - match = lambda addr: all(( - addr.get('version') == version, - addr.get('OS-EXT-IPS:type', 'floating') == address_type)) - matching_addresses = [address.get('addr') for address in network_addresses - if match(address)] - if not any(matching_addresses): - msg = _("No address that would match network '%(network)s'" - " and type '%(address_type)s' of version %(pretty_version)s " - "has been found for server '%(server)s'.") - raise exceptions.ResourceNotFound(msg % { - 'network': args.network, 'address_type': address_type, - 'pretty_version': pretty_version, 'server': args.server}) - elif len(matching_addresses) > 1: - msg = _("More than one %(pretty_version)s %(address_type)s address" - "found.") - raise exceptions.CommandError(msg % {'pretty_version': pretty_version, - 'address_type': address_type}) - else: - ip_address = matching_addresses[0] - - identity = '-i %s' % args.identity if len(args.identity) else '' - - cmd = "ssh -%d -p%d %s %s@%s %s" % (version, args.port, identity, - args.login, ip_address, args.extra) - logger.debug("Executing cmd '%s'", cmd) - os.system(cmd) - - -_quota_resources = ['instances', 'cores', 'ram', - 'fixed_ips', 'metadata_items', 'key_pairs', - 'server_groups', 'server_group_members'] - - -def _quota_show(quotas): - quota_dict = {} - for resource in _quota_resources: - try: - quota_dict[resource] = getattr(quotas, resource) - except AttributeError: - pass - utils.print_dict(quota_dict) - - -def _quota_usage(quotas): - class QuotaObj(object): - def __init__(self, resource, quota_dict): - setattr(self, 'resource', resource) - for (k, v) in six.iteritems(quota_dict): - setattr(self, k, v) - - quota_list = [] - for resource in _quota_resources: - try: - quota_list.append(QuotaObj(resource, getattr(quotas, resource))) - except AttributeError: - pass - utils.print_list(quota_list, ['resource', 'in use', 'limit'], - sortby_index=0) - - -def _quota_update(manager, identifier, args): - updates = {} - for resource in _quota_resources: - val = getattr(args, resource, None) - if val is not None: - updates[resource] = val - - if updates: - # default value of force is None to make sure this client - # will be compatibile with old nova server - manager.update(identifier, **updates) - - -@utils.arg('--tenant', - metavar='', - default=None, - help='ID of tenant to list the quotas for.') -def do_quota_show(cs, args): - """List the quotas for a tenant.""" - - if not args.tenant: - _quota_show(cs.quotas.get(cs.client.tenant_id)) - else: - _quota_show(cs.quotas.get(args.tenant)) - - -@utils.arg('--tenant', - metavar='', - default=None, - help='ID of tenant to list the quotas for.') -@utils.arg('--user', - metavar='', - default=None, - help='ID of user to list the quotas for.') -def do_quota_usage(cs, args): - """List the quotas for a tenant.""" - - tenant = args.tenant or cs.client.tenant_id - _quota_usage(cs.quotas.get(tenant, user_id=args.user, detail=True)) - - -@utils.arg('--tenant', - metavar='', - default=None, - help='ID of tenant to list the default quotas for.') -def do_quota_defaults(cs, args): - """List the default quotas for a tenant.""" - - if not args.tenant: - _quota_show(cs.quotas.defaults(cs.client.tenant_id)) - else: - _quota_show(cs.quotas.defaults(args.tenant)) - - -@utils.arg('tenant', - metavar='', - help='ID of tenant to set the quotas for.') -@utils.arg('--instances', - metavar='', - type=int, default=None, - help='New value for the "instances" quota.') -@utils.arg('--cores', - metavar='', - type=int, default=None, - help='New value for the "cores" quota.') -@utils.arg('--ram', - metavar='', - type=int, default=None, - help='New value for the "ram" quota.') -@utils.arg('--fixed-ips', - metavar='', - type=int, - default=None, - help='New value for the "fixed-ips" quota.') -@utils.arg('--metadata-items', - metavar='', - type=int, - default=None, - help='New value for the "metadata-items" quota.') -@utils.arg('--metadata_items', - type=int, - help=argparse.SUPPRESS) -@utils.arg('--key-pairs', - metavar='', - type=int, - default=None, - help='New value for the "key-pairs" quota.') -@utils.arg('--server-groups', - metavar='', - type=int, - default=None, - help='New value for the "server-groups" quota.') -@utils.arg('--server-group-members', - metavar='', - type=int, - default=None, - help='New value for the "server-group-members" quota.') -@utils.arg('--force', - dest='force', - action="store_true", - default=None, - help='Whether force update the quota even if the already used' - ' and reserved exceeds the new quota') -def do_quota_update(cs, args): - """Update the quotas for a tenant.""" - - _quota_update(cs.quotas, args.tenant, args) - - -@utils.arg('--tenant', - metavar='', - required=True, - help='ID of tenant to delete quota for.') -def do_quota_delete(cs, args): - """Delete quota for a tenant so their quota will revert back to default.""" - - cs.quotas.delete(args.tenant) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('host', metavar='', nargs='?', - help="Name or ID of the target host. " - "If no host is specified, the scheduler will choose one.") -@utils.arg('--password', - dest='password', - metavar='', - help="Set the provided password on the evacuated server. Not applicable " - "with on-shared-storage flag") -@utils.arg('--on-shared-storage', - dest='on_shared_storage', - action="store_true", - default=False, - help='Specifies whether server files are located on shared storage') -def do_evacuate(cs, args): - """Evacuate server from failed host to specified one.""" - server = _find_server(cs, args.server) - - res = server.evacuate(args.host, args.on_shared_storage, args.password)[1] - if type(res) is dict: - utils.print_dict(res) - - -def _print_interfaces(interfaces): - columns = ['Port State', 'Port ID', 'Net ID', 'IP addresses', - 'MAC Addr'] - - class FormattedInterface(object): - def __init__(self, interface): - for col in columns: - key = col.lower().replace(" ", "_") - if hasattr(interface, key): - setattr(self, key, getattr(interface, key)) - self.ip_addresses = ",".join([fip['ip_address'] - for fip in interface.fixed_ips]) - utils.print_list([FormattedInterface(i) for i in interfaces], columns) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -def do_interface_list(cs, args): - """List interfaces attached to a server.""" - server = _find_server(cs, args.server) - - res = server.interface_list() - if type(res) is list: - _print_interfaces(res) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('--port-id', metavar='', help='Port ID.', dest="port_id") -@utils.arg('--net-id', metavar='', help='Network ID', - default=None, dest="net_id") -@utils.arg('--fixed-ip', metavar='', help='Requested fixed IP.', - default=None, dest="fixed_ip") -def do_interface_attach(cs, args): - """Attach a network interface to a server.""" - server = _find_server(cs, args.server) - - res = server.interface_attach(args.port_id, args.net_id, args.fixed_ip) - if type(res) is dict: - utils.print_dict(res) - - -@utils.arg('server', metavar='', help='Name or ID of server.') -@utils.arg('port_id', metavar='', help='Port ID.') -def do_interface_detach(cs, args): - """Detach a network interface from a server.""" - server = _find_server(cs, args.server) - - res = server.interface_detach(args.port_id) - if type(res) is dict: - utils.print_dict(res) - - -def _treeizeAvailabilityZone(zone): - """Build a tree view for availability zones.""" - AvailabilityZone = availability_zones.AvailabilityZone - - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - result = [] - - # Zone tree view item - az.zone_name = zone.zone_name - az.zone_state = ('available' - if zone.zone_state['available'] else 'not available') - az._info['zone_name'] = az.zone_name - az._info['zone_state'] = az.zone_state - result.append(az) - - if zone.hosts is not None: - zone_hosts = sorted(zone.hosts.items(), key=lambda x: x[0]) - for (host, services) in zone_hosts: - # Host tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zone_name = '|- %s' % host - az.zone_state = '' - az._info['zone_name'] = az.zone_name - az._info['zone_state'] = az.zone_state - result.append(az) - - for (svc, state) in services.items(): - # Service tree view item - az = AvailabilityZone(zone.manager, - copy.deepcopy(zone._info), zone._loaded) - az.zone_name = '| |- %s' % svc - az.zone_state = '%s %s %s' % ( - 'enabled' if state['active'] else 'disabled', - ':-)' if state['available'] else 'XXX', - state['updated_at']) - az._info['zone_name'] = az.zone_name - az._info['zone_state'] = az.zone_state - result.append(az) - return result - - -def do_availability_zone_list(cs, _args): - """List all the availability zones.""" - try: - availability_zones = cs.availability_zones.list() - except exceptions.Forbidden as e: # policy doesn't allow probably - try: - availability_zones = cs.availability_zones.list(detailed=False) - except Exception: - raise e - - result = [] - for zone in availability_zones: - result += _treeizeAvailabilityZone(zone) - _translate_availability_zone_keys(result) - utils.print_list(result, ['Name', 'Status'], - sortby_index=None) diff --git a/awx/lib/site-packages/novaclient/v3/usage.py b/awx/lib/site-packages/novaclient/v3/usage.py deleted file mode 100644 index dd16997c68..0000000000 --- a/awx/lib/site-packages/novaclient/v3/usage.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Usage interface. -""" - -from novaclient.v1_1 import usage - - -class Usage(usage.Usage): - pass - - -class UsageManager(usage.UsageManager): - pass diff --git a/awx/lib/site-packages/novaclient/v3/volumes.py b/awx/lib/site-packages/novaclient/v3/volumes.py deleted file mode 100644 index 53cc05f6c7..0000000000 --- a/awx/lib/site-packages/novaclient/v3/volumes.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Volume interface -""" - -from novaclient import base - - -class VolumeManager(base.Manager): - """ - Manage :class:`Volume` resources. - """ - - def attach_server_volume(self, server, volume_id, device, - disk_bus=None, device_type=None): - """ - Attach a volume identified by the volume ID to the given server ID - - :param server: The server (or it's ID) - :param volume_id: The ID of the volume to attach. - :param device: The device name - :param disk_bus: The disk bus of the volume - :param device_type: The device type of the volume - :rtype: :class:`Volume` - """ - body = {'volume_id': volume_id, 'device': device} - if disk_bus: - body['disk_bus'] = disk_bus - if device_type: - body['device_type'] = device_type - return self._action('attach', server, body) - - def update_server_volume(self, server, old_volume_id, new_volume_id): - """ - Update the volume identified by the attachment ID, that is attached to - the given server ID - - :param server_id: The server (or it's ID) - :param old_volume_id: The ID of the attachment - :param new_volume_id: The ID of the new volume to attach - :rtype: :class:`Volume` - """ - body = {'new_volume_id': new_volume_id, 'old_volume_id': old_volume_id} - return self._action('swap_volume_attachment', server, body) - - def delete_server_volume(self, server, volume_id): - """ - Detach a volume identified by the attachment ID from the given server - - :param server_id: The ID of the server - :param volume_id: The ID of the attachment - """ - return self._action('detach', server, {'volume_id': volume_id}) - - def _action(self, action, server, info=None, **kwargs): - """ - Perform a server "action" -- reboot/rebuild/resize/etc. - """ - body = {action: info} - self.run_hooks('modify_body_for_action', body, **kwargs) - url = '/servers/%s/action' % base.getid(server) - return self.api.client.post(url, body=body) diff --git a/awx/lib/site-packages/ordereddict.py b/awx/lib/site-packages/ordereddict.py deleted file mode 100644 index 5b0303f5a3..0000000000 --- a/awx/lib/site-packages/ordereddict.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright (c) 2009 Raymond Hettinger -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. - -from UserDict import DictMixin - -class OrderedDict(dict, DictMixin): - - def __init__(self, *args, **kwds): - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__end - except AttributeError: - self.clear() - self.update(*args, **kwds) - - def clear(self): - self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] - dict.clear(self) - - def __setitem__(self, key, value): - if key not in self: - end = self.__end - curr = end[1] - curr[2] = end[1] = self.__map[key] = [key, curr, end] - dict.__setitem__(self, key, value) - - def __delitem__(self, key): - dict.__delitem__(self, key) - key, prev, next = self.__map.pop(key) - prev[2] = next - next[1] = prev - - def __iter__(self): - end = self.__end - curr = end[2] - while curr is not end: - yield curr[0] - curr = curr[2] - - def __reversed__(self): - end = self.__end - curr = end[1] - while curr is not end: - yield curr[0] - curr = curr[1] - - def popitem(self, last=True): - if not self: - raise KeyError('dictionary is empty') - if last: - key = reversed(self).next() - else: - key = iter(self).next() - value = self.pop(key) - return key, value - - def __reduce__(self): - items = [[k, self[k]] for k in self] - tmp = self.__map, self.__end - del self.__map, self.__end - inst_dict = vars(self).copy() - self.__map, self.__end = tmp - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def keys(self): - return list(self) - - setdefault = DictMixin.setdefault - update = DictMixin.update - pop = DictMixin.pop - values = DictMixin.values - items = DictMixin.items - iterkeys = DictMixin.iterkeys - itervalues = DictMixin.itervalues - iteritems = DictMixin.iteritems - - def __repr__(self): - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - - def copy(self): - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - if isinstance(other, OrderedDict): - if len(self) != len(other): - return False - for p, q in zip(self.items(), other.items()): - if p != q: - return False - return True - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other diff --git a/awx/lib/site-packages/os_client_config/__init__.py b/awx/lib/site-packages/os_client_config/__init__.py deleted file mode 100644 index d5fd36cb60..0000000000 --- a/awx/lib/site-packages/os_client_config/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from os_client_config.config import OpenStackConfig # noqa diff --git a/awx/lib/site-packages/os_client_config/cloud_config.py b/awx/lib/site-packages/os_client_config/cloud_config.py deleted file mode 100644 index 6f501c6921..0000000000 --- a/awx/lib/site-packages/os_client_config/cloud_config.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class CloudConfig(object): - def __init__(self, name, region, config): - self.name = name or 'openstack' - self.region = region - self.config = config - - def __getattr__(self, key): - """Return arbitrary attributes.""" - - if key.startswith('os_'): - key = key[3:] - - if key in [attr.replace('-', '_') for attr in self.config]: - return self.config[key] - else: - return None - - def __iter__(self): - return self.config.__iter__() diff --git a/awx/lib/site-packages/os_client_config/config.py b/awx/lib/site-packages/os_client_config/config.py deleted file mode 100644 index 48b99f591d..0000000000 --- a/awx/lib/site-packages/os_client_config/config.py +++ /dev/null @@ -1,357 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import os - -import yaml - -try: - import keystoneclient.auth as ksc_auth -except ImportError: - ksc_auth = None - -from os_client_config import cloud_config -from os_client_config import defaults -from os_client_config import exceptions -from os_client_config import vendors - -CONFIG_HOME = os.path.join(os.path.expanduser( - os.environ.get('XDG_CONFIG_HOME', os.path.join('~', '.config'))), - 'openstack') -CONFIG_SEARCH_PATH = [os.getcwd(), CONFIG_HOME, '/etc/openstack'] -CONFIG_FILES = [ - os.path.join(d, 'clouds.yaml') for d in CONFIG_SEARCH_PATH] -CACHE_PATH = os.path.join(os.path.expanduser( - os.environ.get('XDG_CACHE_PATH', os.path.join('~', '.cache'))), - 'openstack') -BOOL_KEYS = ('insecure', 'cache') -VENDOR_SEARCH_PATH = [os.getcwd(), CONFIG_HOME, '/etc/openstack'] -VENDOR_FILES = [ - os.path.join(d, 'clouds-public.yaml') for d in VENDOR_SEARCH_PATH] - - -def set_default(key, value): - defaults._defaults[key] = value - - -def get_boolean(value): - if value.lower() == 'true': - return True - return False - - -def _get_os_environ(): - ret = dict(defaults._defaults) - for (k, v) in os.environ.items(): - if k.startswith('OS_'): - newkey = k[3:].lower() - ret[newkey] = v - return ret - - -def _auth_update(old_dict, new_dict): - """Like dict.update, except handling the nested dict called auth.""" - for (k, v) in new_dict.items(): - if k == 'auth': - if k in old_dict: - old_dict[k].update(v) - else: - old_dict[k] = v.copy() - else: - old_dict[k] = v - return old_dict - - -class OpenStackConfig(object): - - def __init__(self, config_files=None, vendor_files=None): - self._config_files = config_files or CONFIG_FILES - self._vendor_files = vendor_files or VENDOR_FILES - - self.defaults = _get_os_environ() - - # use a config file if it exists where expected - self.cloud_config = self._load_config_file() - if not self.cloud_config: - self.cloud_config = dict( - clouds=dict(openstack=dict(self.defaults))) - - self._cache_max_age = 300 - self._cache_path = CACHE_PATH - self._cache_class = 'dogpile.cache.memory' - self._cache_arguments = {} - if 'cache' in self.cloud_config: - self._cache_max_age = self.cloud_config['cache'].get( - 'max_age', self._cache_max_age) - self._cache_path = os.path.expanduser( - self.cloud_config['cache'].get('path', self._cache_path)) - self._cache_class = self.cloud_config['cache'].get( - 'class', self._cache_class) - self._cache_arguments = self.cloud_config['cache'].get( - 'arguments', self._cache_arguments) - - def _load_config_file(self): - for path in self._config_files: - if os.path.exists(path): - with open(path, 'r') as f: - return yaml.safe_load(f) - - def _load_vendor_file(self): - for path in self._vendor_files: - if os.path.exists(path): - with open(path, 'r') as f: - return yaml.safe_load(f) - - def get_cache_max_age(self): - return self._cache_max_age - - def get_cache_path(self): - return self._cache_path - - def get_cache_class(self): - return self._cache_class - - def get_cache_arguments(self): - return self._cache_arguments - - def _get_regions(self, cloud): - try: - return self.cloud_config['clouds'][cloud]['region_name'] - except KeyError: - # No region configured - return '' - - def _get_region(self, cloud): - return self._get_regions(cloud).split(',')[0] - - def _get_cloud_sections(self): - return self.cloud_config['clouds'].keys() - - def _get_base_cloud_config(self, name): - cloud = dict() - - # Only validate cloud name if one was given - if name and name not in self.cloud_config['clouds']: - raise exceptions.OpenStackConfigException( - "Named cloud {name} requested that was not found.".format( - name=name)) - - our_cloud = self.cloud_config['clouds'].get(name, dict()) - - # Get the defaults (including env vars) first - cloud.update(self.defaults) - - # yes, I know the next line looks silly - if 'cloud' in our_cloud: - cloud_name = our_cloud['cloud'] - vendor_file = self._load_vendor_file() - if vendor_file and cloud_name in vendor_file['public-clouds']: - _auth_update(cloud, vendor_file['public-clouds'][cloud_name]) - else: - try: - _auth_update(cloud, vendors.CLOUD_DEFAULTS[cloud_name]) - except KeyError: - # Can't find the requested vendor config, go about business - pass - - if 'auth' not in cloud: - cloud['auth'] = dict() - - _auth_update(cloud, our_cloud) - if 'cloud' in cloud: - del cloud['cloud'] - - return self._fix_backwards_madness(cloud) - - def _fix_backwards_madness(self, cloud): - cloud = self._fix_backwards_project(cloud) - cloud = self._fix_backwards_auth_plugin(cloud) - return cloud - - def _fix_backwards_project(self, cloud): - # Do the lists backwards so that project_name is the ultimate winner - mappings = { - 'project_name': ('tenant_id', 'project_id', - 'tenant_name', 'project_name'), - } - for target_key, possible_values in mappings.items(): - target = None - for key in possible_values: - if key in cloud: - target = cloud[key] - del cloud[key] - if key in cloud['auth']: - target = cloud['auth'][key] - del cloud['auth'][key] - cloud['auth'][target_key] = target - return cloud - - def _fix_backwards_auth_plugin(self, cloud): - # Do the lists backwards so that auth_type is the ultimate winner - mappings = { - 'auth_type': ('auth_plugin', 'auth_type'), - } - for target_key, possible_values in mappings.items(): - target = None - for key in possible_values: - if key in cloud: - target = cloud[key] - del cloud[key] - cloud[target_key] = target - return cloud - - def get_all_clouds(self): - - clouds = [] - - for cloud in self._get_cloud_sections(): - for region in self._get_regions(cloud).split(','): - clouds.append(self.get_one_cloud(cloud, region_name=region)) - return clouds - - def _fix_args(self, args, argparse=None): - """Massage the passed-in options - - Replace - with _ and strip os_ prefixes. - - Convert an argparse Namespace object to a dict, removing values - that are either None or ''. - """ - - if argparse: - # Convert the passed-in Namespace - o_dict = vars(argparse) - parsed_args = dict() - for k in o_dict: - if o_dict[k] is not None and o_dict[k] != '': - parsed_args[k] = o_dict[k] - args.update(parsed_args) - - os_args = dict() - new_args = dict() - for (key, val) in iter(args.items()): - key = key.replace('-', '_') - if key.startswith('os'): - os_args[key[3:]] = val - else: - new_args[key] = val - new_args.update(os_args) - return new_args - - def _find_winning_auth_value(self, opt, config): - opt_name = opt.name.replace('-', '_') - if opt_name in config: - return config[opt_name] - else: - for d_opt in opt.deprecated_opts: - d_opt_name = d_opt.name.replace('-', '_') - if d_opt_name in config: - return config[d_opt_name] - - def _validate_auth(self, config): - # May throw a keystoneclient.exceptions.NoMatchingPlugin - plugin_options = ksc_auth.get_plugin_class( - config['auth_type']).get_options() - - for p_opt in plugin_options: - # if it's in config.auth, win, kill it from config dict - # if it's in config and not in config.auth, move it - # deprecated loses to current - # provided beats default, deprecated or not - winning_value = self._find_winning_auth_value( - p_opt, config['auth']) - if not winning_value: - winning_value = self._find_winning_auth_value(p_opt, config) - - # if the plugin tells us that this value is required - # then error if it's doesn't exist now - if not winning_value and p_opt.required: - raise exceptions.OpenStackConfigException( - 'Unable to find auth information for cloud' - ' {cloud} in config files {files}' - ' or environment variables. Missing value {auth_key}' - ' required for auth plugin {plugin}'.format( - cloud=cloud, files=','.join(self._config_files), - auth_key=p_opt.name, plugin=config.get('auth_type'))) - - # Clean up after ourselves - for opt in [p_opt.name] + [o.name for o in p_opt.deprecated_opts]: - opt = opt.replace('-', '_') - config.pop(opt, None) - config['auth'].pop(opt, None) - - if winning_value: - # Prefer the plugin configuration dest value if the value's key - # is marked as depreciated. - if p_opt.dest is None: - config['auth'][p_opt.name.replace('-', '_')] = ( - winning_value) - else: - config['auth'][p_opt.dest] = winning_value - - return config - - def get_one_cloud(self, cloud=None, validate=True, - argparse=None, **kwargs): - """Retrieve a single cloud configuration and merge additional options - - :param string cloud: - The name of the configuration to load from clouds.yaml - :param boolean validate: - Validate that required arguments are present and certain - argument combinations are valid - :param Namespace argparse: - An argparse Namespace object; allows direct passing in of - argparse options to be added to the cloud config. Values - of None and '' will be removed. - :param kwargs: Additional configuration options - """ - - args = self._fix_args(kwargs, argparse=argparse) - - if 'region_name' not in args or args['region_name'] is None: - args['region_name'] = self._get_region(cloud) - - config = self._get_base_cloud_config(cloud) - - # Can't just do update, because None values take over - for (key, val) in iter(args.items()): - if val is not None: - config[key] = val - - for key in BOOL_KEYS: - if key in config: - if type(config[key]) is not bool: - config[key] = get_boolean(config[key]) - - if 'auth_type' in config: - if config['auth_type'] in ('', 'None', None): - validate = False - - if validate and ksc_auth: - config = self._validate_auth(config) - - # If any of the defaults reference other values, we need to expand - for (key, value) in config.items(): - if hasattr(value, 'format'): - config[key] = value.format(**config) - - return cloud_config.CloudConfig( - name=cloud, region=config['region_name'], config=config) - -if __name__ == '__main__': - config = OpenStackConfig().get_all_clouds() - for cloud in config: - print(cloud.name, cloud.region, cloud.config) diff --git a/awx/lib/site-packages/os_client_config/defaults.py b/awx/lib/site-packages/os_client_config/defaults.py deleted file mode 100644 index 5f70d6ee4e..0000000000 --- a/awx/lib/site-packages/os_client_config/defaults.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -_defaults = dict( - auth_type='password', - compute_api_version='2', - identity_api_version='2', - image_api_version='1', - network_api_version='2', - object_api_version='1', - volume_api_version='1', -) diff --git a/awx/lib/site-packages/os_client_config/exceptions.py b/awx/lib/site-packages/os_client_config/exceptions.py deleted file mode 100644 index ab78dc2e5c..0000000000 --- a/awx/lib/site-packages/os_client_config/exceptions.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class OpenStackConfigException(Exception): - """Something went wrong with parsing your OpenStack Config.""" diff --git a/awx/lib/site-packages/os_client_config/tests/__init__.py b/awx/lib/site-packages/os_client_config/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/os_client_config/tests/base.py b/awx/lib/site-packages/os_client_config/tests/base.py deleted file mode 100644 index 1c30cdb56e..0000000000 --- a/awx/lib/site-packages/os_client_config/tests/base.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2010-2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base - - -class TestCase(base.BaseTestCase): - - """Test case base class for all unit tests.""" diff --git a/awx/lib/site-packages/os_client_config/tests/test_cloud_config.py b/awx/lib/site-packages/os_client_config/tests/test_cloud_config.py deleted file mode 100644 index 36386e50ea..0000000000 --- a/awx/lib/site-packages/os_client_config/tests/test_cloud_config.py +++ /dev/null @@ -1,44 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from os_client_config import cloud_config -from os_client_config.tests import base - - -fake_config_dict = {'a': 1, 'os_b': 2, 'c': 3, 'os_c': 4} - - -class TestCloudConfig(base.TestCase): - - def test_arbitrary_attributes(self): - cc = cloud_config.CloudConfig("test1", "region-al", fake_config_dict) - self.assertEqual("test1", cc.name) - self.assertEqual("region-al", cc.region) - - # Look up straight value - self.assertEqual(1, cc.a) - - # Look up prefixed attribute, fail - returns None - self.assertEqual(None, cc.os_b) - - # Look up straight value, then prefixed value - self.assertEqual(3, cc.c) - self.assertEqual(3, cc.os_c) - - # Lookup mystery attribute - self.assertIsNone(cc.x) - - def test_iteration(self): - cc = cloud_config.CloudConfig("test1", "region-al", fake_config_dict) - self.assertTrue('a' in cc) - self.assertFalse('x' in cc) diff --git a/awx/lib/site-packages/os_client_config/tests/test_config.py b/awx/lib/site-packages/os_client_config/tests/test_config.py deleted file mode 100644 index 5ef3048f0f..0000000000 --- a/awx/lib/site-packages/os_client_config/tests/test_config.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import tempfile - -import extras -import fixtures -import testtools -import yaml - -from os_client_config import cloud_config -from os_client_config import config - -VENDOR_CONF = { - 'public-clouds': { - '_test_cloud_in_our_cloud': { - 'auth': { - 'username': 'testotheruser', - 'project_name': 'testproject', - }, - }, - } -} -USER_CONF = { - 'clouds': { - '_test_cloud_': { - 'cloud': '_test_cloud_in_our_cloud', - 'auth': { - 'username': 'testuser', - 'password': 'testpass', - }, - 'region_name': 'test-region', - }, - '_test_cloud_no_vendor': { - 'cloud': '_test_non_existant_cloud', - 'auth': { - 'username': 'testuser', - 'password': 'testpass', - 'project_name': 'testproject', - }, - 'region_name': 'test-region', - }, - }, - 'cache': {'max_age': 1}, -} - - -def _write_yaml(obj): - # Assume NestedTempfile so we don't have to cleanup - with tempfile.NamedTemporaryFile(delete=False) as obj_yaml: - obj_yaml.write(yaml.safe_dump(obj).encode('utf-8')) - return obj_yaml.name - - -class TestConfig(testtools.TestCase): - def setUp(self): - super(TestConfig, self).setUp() - self.useFixture(fixtures.NestedTempfile()) - conf = dict(USER_CONF) - tdir = self.useFixture(fixtures.TempDir()) - conf['cache']['path'] = tdir.path - self.cloud_yaml = _write_yaml(conf) - self.vendor_yaml = _write_yaml(VENDOR_CONF) - - def test_get_one_cloud(self): - c = config.OpenStackConfig(config_files=[self.cloud_yaml], - vendor_files=[self.vendor_yaml]) - self.assertIsInstance(c.get_one_cloud(), cloud_config.CloudConfig) - - def test_get_one_cloud_with_config_files(self): - c = config.OpenStackConfig(config_files=[self.cloud_yaml], - vendor_files=[self.vendor_yaml]) - self.assertIsInstance(c.cloud_config, dict) - self.assertIn('cache', c.cloud_config) - self.assertIsInstance(c.cloud_config['cache'], dict) - self.assertIn('max_age', c.cloud_config['cache']) - self.assertIn('path', c.cloud_config['cache']) - cc = c.get_one_cloud('_test_cloud_') - self._assert_cloud_details(cc) - cc = c.get_one_cloud('_test_cloud_no_vendor') - self._assert_cloud_details(cc) - - def _assert_cloud_details(self, cc): - self.assertIsInstance(cc, cloud_config.CloudConfig) - self.assertTrue(extras.safe_hasattr(cc, 'auth')) - self.assertIsInstance(cc.auth, dict) - self.assertIsNone(cc.cloud) - self.assertIn('username', cc.auth) - self.assertEqual('testuser', cc.auth['username']) - self.assertEqual('testproject', cc.auth['project_name']) diff --git a/awx/lib/site-packages/os_client_config/tests/test_os_client_config.py b/awx/lib/site-packages/os_client_config/tests/test_os_client_config.py deleted file mode 100644 index 7421b6fe4a..0000000000 --- a/awx/lib/site-packages/os_client_config/tests/test_os_client_config.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -test_os_client_config ----------------------------------- - -Tests for `os_client_config` module. -""" - -from os_client_config.tests import base - - -class TestOs_client_config(base.TestCase): - - def test_something(self): - pass diff --git a/awx/lib/site-packages/os_client_config/vendors.py b/awx/lib/site-packages/os_client_config/vendors.py deleted file mode 100644 index eb08bbdbd5..0000000000 --- a/awx/lib/site-packages/os_client_config/vendors.py +++ /dev/null @@ -1,33 +0,0 @@ -# flake8: noqa -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -CLOUD_DEFAULTS = dict( - hp=dict( - auth=dict( - auth_url='https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0', - ), - region_name='region-b.geo-1', - dns_service_type='hpext:dns', - image_api_version='1', - ), - rackspace=dict( - auth=dict( - auth_url='https://identity.api.rackspacecloud.com/v2.0/', - ), - database_service_type='rax:database', - compute_service_name='cloudServersOpenStack', - image_api_version='2', - ) -) diff --git a/awx/lib/site-packages/os_diskconfig_python_novaclient_ext/__init__.py b/awx/lib/site-packages/os_diskconfig_python_novaclient_ext/__init__.py deleted file mode 100644 index e287da55e2..0000000000 --- a/awx/lib/site-packages/os_diskconfig_python_novaclient_ext/__init__.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Disk Config extension -""" - -from novaclient import utils -from novaclient.v1_1 import servers -from novaclient.v1_1 import shell - -API_DISK_CONFIG = "OS-DCF:diskConfig" - -# This function was removed from python-novaclient, so we are defining it here -# So the add_args() function will work again. - -def add_arg(f, *args, **kwargs): - """Bind CLI arguments to a shell.py `do_foo` function.""" - - if not hasattr(f, 'arguments'): - f.arguments = [] - - # NOTE(sirp): avoid dups that can occur when the module is shared across - # tests. - if (args, kwargs) not in f.arguments: - # Because of the semantics of the decorator composition if we just append - # to the options list positional options will appear to be backwards. - f.arguments.insert(0, (args, kwargs)) - -def add_args(): - add_arg(shell.do_boot, - '--disk-config', - default=None, - metavar='', - help="Whether to expand primary partition to fill disk." - " This overrides the value inherited from image.") - - -def bind_args_to_resource_manager(args): - def add_disk_config(args): - return dict(disk_config=args.disk_config) - - utils.add_resource_manager_extra_kwargs_hook( - shell.do_boot, add_disk_config) - - -def add_modify_body_hook(): - def modify_body_for_create(body, **kwargs): - disk_config = kwargs.get('disk_config') - if disk_config: - disk_config = disk_config.upper() - - if disk_config in ('AUTO', 'MANUAL'): - body["server"][API_DISK_CONFIG] = disk_config - else: - raise Exception("Unrecognized disk_config '%s'" % disk_config) - - servers.ServerManager.add_hook( - 'modify_body_for_create', modify_body_for_create) - - -def __pre_parse_args__(): - add_args() - - -def __post_parse_args__(args): - bind_args_to_resource_manager(args) - add_modify_body_hook() diff --git a/awx/lib/site-packages/os_networksv2_python_novaclient_ext.py b/awx/lib/site-packages/os_networksv2_python_novaclient_ext.py deleted file mode 100644 index b4d61a1408..0000000000 --- a/awx/lib/site-packages/os_networksv2_python_novaclient_ext.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2011 OpenStack, LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from novaclient import base -from novaclient.openstack.common import cliutils as utils - - -class Network(base.Resource): - def delete(self): - self.manager.delete(network=self) - - -class NetworkManager(base.ManagerWithFind): - resource_class = base.Resource - - def list(self): - return self._list('/os-networksv2', 'networks') - - def get(self, network): - return self._get('/os-networksv2/%s' % base.getid(network), 'network') - - def delete(self, network): - self._delete('/os-networksv2/%s' % base.getid(network)) - - def create(self, label, cidr): - body = {'network': {'label': label, 'cidr': cidr}} - return self._create('/os-networksv2', body, 'network') - - -@utils.arg('network_id', metavar='', help='ID of network') -def do_network(cs, args): - """ - Show a network - """ - network = cs.os_networksv2_python_novaclient_ext.get(args.network_id) - utils.print_dict(network._info) - - -do_network_show = do_network - - -def do_network_list(cs, args): - """ - List networks - """ - networks = cs.os_networksv2_python_novaclient_ext.list() - utils.print_list(networks, ['ID', 'Label', 'CIDR']) - - -@utils.arg('label', metavar='', - help='Network label (ex. my_new_network)') -@utils.arg('cidr', metavar='', - help='IP block to allocate from (ex. 172.16.0.0/24 or ' - '2001:DB8::/64)') -def do_network_create(cs, args): - """ - Create a network - """ - network = cs.os_networksv2_python_novaclient_ext.create(args.label, - args.cidr) - utils.print_dict(network._info) - - -@utils.arg('network_id', metavar='', help='ID of network') -def do_network_delete(cs, args): - """ - Delete a network - """ - cs.os_networksv2_python_novaclient_ext.delete(args.network_id) diff --git a/awx/lib/site-packages/os_virtual_interfacesv2_python_novaclient_ext.py b/awx/lib/site-packages/os_virtual_interfacesv2_python_novaclient_ext.py deleted file mode 100644 index 7707c3ec8e..0000000000 --- a/awx/lib/site-packages/os_virtual_interfacesv2_python_novaclient_ext.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright 2011 OpenStack, LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from novaclient import base -from novaclient.openstack.common import cliutils -from novaclient import utils - - -class VirtualInterface(base.Resource): - def create(self): - self.manager.create() - - -class VirtualInterfaceManager(base.ManagerWithFind): - resource_class = base.Resource - - def list(self, instance_id): - return self._list("/servers/%s/os-virtual-interfacesv2" % instance_id, - "virtual_interfaces") - - def create(self, network_id, instance_id): - body = {'virtual_interface': {'network_id': network_id}} - return self._create('/servers/%s/os-virtual-interfacesv2' % - instance_id, - body, 'virtual_interfaces', return_raw=True) - - def delete(self, instance_id, interface_id): - return self._delete('/servers/%s/os-virtual-interfacesv2/%s' % - (instance_id, interface_id)) - - -def ip_dict_formatter(ip_dict): - net_id = ip_dict["network_id"] - ip_addr = ip_dict["address"] - label = ip_dict["network_label"] - return "label=%s, network_id=%s, ip_address=%s" % (label, - net_id, ip_addr) - - -def ip_address_formatter(field): - addresses = [ip_dict_formatter(addr) for addr in field.ip_addresses] - return ",".join(addresses) - - -@cliutils.arg('instance_id', metavar='', - help="ID of the instance you want to display virtual" - "interfaces for") -def do_virtual_interface_list(cs, args): - """ - Lists the virtual interfaces for an instance - """ - vifs = cs.os_virtual_interfacesv2_python_novaclient_ext.list( - args.instance_id) - utils.print_list(vifs, ["id", "mac_address", "ip_addresses"], - formatters={"ip_addresses": ip_address_formatter}) - - -@cliutils.arg('network_id', metavar='', - help='Network ID to connect the new virtual interface to') -@cliutils.arg('instance_id', metavar='', - help="Instance to attach the new virtual interface to") -def do_virtual_interface_create(cs, args): - """ - Add a new virtual interface to an instance - """ - addresses = cs.os_virtual_interfacesv2_python_novaclient_ext.create( - args.network_id, - args.instance_id) - for address in addresses: - addr_list = [ip_dict_formatter(a) for a in address["ip_addresses"]] - addr_dict = {"id": address["id"], - "mac_address": address["mac_address"], - "ip_addresses": ','.join(addr_list)} - utils.print_dict(addr_dict) - - -@cliutils.arg('instance_id', metavar='', - help="Instance to remove the virtual interface from") -@cliutils.arg('interface_id', metavar='', - help='ID of the virtual interface to delete') -def do_virtual_interface_delete(cs, args): - """ - Removes the specified virtual interface from an instance - """ - cs.os_virtual_interfacesv2_python_novaclient_ext.delete(args.instance_id, - args.interface_id) diff --git a/awx/lib/site-packages/oslo/__init__.py b/awx/lib/site-packages/oslo/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/oslo/config/__init__.py b/awx/lib/site-packages/oslo/config/__init__.py deleted file mode 100644 index 331e0b08b1..0000000000 --- a/awx/lib/site-packages/oslo/config/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - -from oslo_config import * # noqa - - -def deprecated(): - new_name = __name__.replace('.', '_') - warnings.warn( - ('The oslo namespace package is deprecated. Please use %s instead.' % - new_name), - DeprecationWarning, - stacklevel=3, - ) - - -deprecated() diff --git a/awx/lib/site-packages/oslo/config/cfg.py b/awx/lib/site-packages/oslo/config/cfg.py deleted file mode 100644 index 281352520d..0000000000 --- a/awx/lib/site-packages/oslo/config/cfg.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config.cfg import * # noqa diff --git a/awx/lib/site-packages/oslo/config/cfgfilter.py b/awx/lib/site-packages/oslo/config/cfgfilter.py deleted file mode 100644 index 4d45ac9b72..0000000000 --- a/awx/lib/site-packages/oslo/config/cfgfilter.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config.cfgfilter import * # noqa diff --git a/awx/lib/site-packages/oslo/config/fixture.py b/awx/lib/site-packages/oslo/config/fixture.py deleted file mode 100644 index ab3aacbce3..0000000000 --- a/awx/lib/site-packages/oslo/config/fixture.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config.fixture import * # noqa diff --git a/awx/lib/site-packages/oslo/config/generator.py b/awx/lib/site-packages/oslo/config/generator.py deleted file mode 100644 index f635dc7d63..0000000000 --- a/awx/lib/site-packages/oslo/config/generator.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config.generator import * # noqa diff --git a/awx/lib/site-packages/oslo/config/iniparser.py b/awx/lib/site-packages/oslo/config/iniparser.py deleted file mode 100644 index f46978ca1a..0000000000 --- a/awx/lib/site-packages/oslo/config/iniparser.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config.iniparser import * # noqa diff --git a/awx/lib/site-packages/oslo/config/types.py b/awx/lib/site-packages/oslo/config/types.py deleted file mode 100644 index 2ed9fa9dc8..0000000000 --- a/awx/lib/site-packages/oslo/config/types.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_config.types import * # noqa diff --git a/awx/lib/site-packages/oslo/i18n/__init__.py b/awx/lib/site-packages/oslo/i18n/__init__.py deleted file mode 100644 index e43c963deb..0000000000 --- a/awx/lib/site-packages/oslo/i18n/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - -from oslo_i18n._factory import * -from oslo_i18n._gettextutils import * -from oslo_i18n._lazy import * -from oslo_i18n._translate import * - - -def deprecated(): - new_name = __name__.replace('.', '_') - warnings.warn( - ('The oslo namespace package is deprecated. Please use %s instead.' % - new_name), - DeprecationWarning, - stacklevel=3, - ) - - -deprecated() diff --git a/awx/lib/site-packages/oslo/i18n/fixture.py b/awx/lib/site-packages/oslo/i18n/fixture.py deleted file mode 100644 index eb087734c9..0000000000 --- a/awx/lib/site-packages/oslo/i18n/fixture.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_i18n.fixture import * # noqa diff --git a/awx/lib/site-packages/oslo/i18n/log.py b/awx/lib/site-packages/oslo/i18n/log.py deleted file mode 100644 index ac187668b1..0000000000 --- a/awx/lib/site-packages/oslo/i18n/log.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_i18n.log import * # noqa diff --git a/awx/lib/site-packages/oslo/serialization/__init__.py b/awx/lib/site-packages/oslo/serialization/__init__.py deleted file mode 100644 index 73e54f3d9b..0000000000 --- a/awx/lib/site-packages/oslo/serialization/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - - -def deprecated(): - new_name = __name__.replace('.', '_') - warnings.warn( - ('The oslo namespace package is deprecated. Please use %s instead.' % - new_name), - DeprecationWarning, - stacklevel=3, - ) - - -deprecated() diff --git a/awx/lib/site-packages/oslo/serialization/jsonutils.py b/awx/lib/site-packages/oslo/serialization/jsonutils.py deleted file mode 100644 index 74476f6333..0000000000 --- a/awx/lib/site-packages/oslo/serialization/jsonutils.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_serialization.jsonutils import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/__init__.py b/awx/lib/site-packages/oslo/utils/__init__.py deleted file mode 100644 index 73e54f3d9b..0000000000 --- a/awx/lib/site-packages/oslo/utils/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - - -def deprecated(): - new_name = __name__.replace('.', '_') - warnings.warn( - ('The oslo namespace package is deprecated. Please use %s instead.' % - new_name), - DeprecationWarning, - stacklevel=3, - ) - - -deprecated() diff --git a/awx/lib/site-packages/oslo/utils/encodeutils.py b/awx/lib/site-packages/oslo/utils/encodeutils.py deleted file mode 100644 index 0de24762c8..0000000000 --- a/awx/lib/site-packages/oslo/utils/encodeutils.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.encodeutils import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/excutils.py b/awx/lib/site-packages/oslo/utils/excutils.py deleted file mode 100644 index 333c955ee6..0000000000 --- a/awx/lib/site-packages/oslo/utils/excutils.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.excutils import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/importutils.py b/awx/lib/site-packages/oslo/utils/importutils.py deleted file mode 100644 index 9097dc4227..0000000000 --- a/awx/lib/site-packages/oslo/utils/importutils.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.importutils import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/netutils.py b/awx/lib/site-packages/oslo/utils/netutils.py deleted file mode 100644 index 701224d467..0000000000 --- a/awx/lib/site-packages/oslo/utils/netutils.py +++ /dev/null @@ -1,15 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.netutils import * # noqa -# NOTE(dhellmann): Needed for taskflow. -from oslo_utils.netutils import _ModifiedSplitResult # noqa diff --git a/awx/lib/site-packages/oslo/utils/reflection.py b/awx/lib/site-packages/oslo/utils/reflection.py deleted file mode 100644 index f8b5c16068..0000000000 --- a/awx/lib/site-packages/oslo/utils/reflection.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.reflection import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/strutils.py b/awx/lib/site-packages/oslo/utils/strutils.py deleted file mode 100644 index 989e088fc7..0000000000 --- a/awx/lib/site-packages/oslo/utils/strutils.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.strutils import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/timeutils.py b/awx/lib/site-packages/oslo/utils/timeutils.py deleted file mode 100644 index 65b856a26c..0000000000 --- a/awx/lib/site-packages/oslo/utils/timeutils.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.timeutils import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/units.py b/awx/lib/site-packages/oslo/utils/units.py deleted file mode 100644 index 741e740719..0000000000 --- a/awx/lib/site-packages/oslo/utils/units.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.units import * # noqa diff --git a/awx/lib/site-packages/oslo/utils/uuidutils.py b/awx/lib/site-packages/oslo/utils/uuidutils.py deleted file mode 100644 index 4f98a84ca2..0000000000 --- a/awx/lib/site-packages/oslo/utils/uuidutils.py +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_utils.uuidutils import * # noqa diff --git a/awx/lib/site-packages/oslo_config/__init__.py b/awx/lib/site-packages/oslo_config/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/oslo_config/cfg.py b/awx/lib/site-packages/oslo_config/cfg.py deleted file mode 100644 index 77fd44d768..0000000000 --- a/awx/lib/site-packages/oslo_config/cfg.py +++ /dev/null @@ -1,2603 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -r""" -Configuration options may be set on the command line or in config files. - -The schema for each option is defined using the -:class:`Opt` class or its sub-classes, for example: - -:: - - from oslo_config import cfg - from oslo_config import types - - PortType = types.Integer(1, 65535) - - common_opts = [ - cfg.StrOpt('bind_host', - default='0.0.0.0', - help='IP address to listen on.'), - cfg.Opt('bind_port', - type=PortType(), - default=9292, - help='Port number to listen on.') - ] - -Option Types ------------- - -Options can have arbitrary types via the ``type`` constructor to -``Opt``. The type constructor is a callable object that takes a string and -either returns a value of that particular type or raises ValueError if -the value can not be converted. - -There are predefined types in :class:`oslo_config.cfg` : strings, -integers, floats, booleans, lists, 'multi strings' and 'key/value -pairs' (dictionary) :: - - enabled_apis_opt = cfg.ListOpt('enabled_apis', - default=['ec2', 'osapi_compute'], - help='List of APIs to enable by default.') - - DEFAULT_EXTENSIONS = [ - 'nova.api.openstack.compute.contrib.standard_extensions' - ] - osapi_compute_extension_opt = cfg.MultiStrOpt('osapi_compute_extension', - default=DEFAULT_EXTENSIONS) - -Registering Options -------------------- - -Option schemas are registered with the config manager at runtime, but before -the option is referenced:: - - class ExtensionManager(object): - - enabled_apis_opt = cfg.ListOpt(...) - - def __init__(self, conf): - self.conf = conf - self.conf.register_opt(enabled_apis_opt) - ... - - def _load_extensions(self): - for ext_factory in self.conf.osapi_compute_extension: - .... - -A common usage pattern is for each option schema to be defined in the module or -class which uses the option:: - - opts = ... - - def add_common_opts(conf): - conf.register_opts(opts) - - def get_bind_host(conf): - return conf.bind_host - - def get_bind_port(conf): - return conf.bind_port - -An option may optionally be made available via the command line. Such options -must be registered with the config manager before the command line is parsed -(for the purposes of --help and CLI arg validation):: - - cli_opts = [ - cfg.BoolOpt('verbose', - short='v', - default=False, - help='Print more verbose output.'), - cfg.BoolOpt('debug', - short='d', - default=False, - help='Print debugging output.'), - ] - - def add_common_opts(conf): - conf.register_cli_opts(cli_opts) - -Loading Config Files --------------------- - -The config manager has two CLI options defined by default, --config-file -and --config-dir:: - - class ConfigOpts(object): - - def __call__(self, ...): - - opts = [ - MultiStrOpt('config-file', - ...), - StrOpt('config-dir', - ...), - ] - - self.register_cli_opts(opts) - -Option values are parsed from any supplied config files using -oslo_config.iniparser. If none are specified, a default set is used -for example glance-api.conf and glance-common.conf:: - - glance-api.conf: - [DEFAULT] - bind_port = 9292 - - glance-common.conf: - [DEFAULT] - bind_host = 0.0.0.0 - -Option values in config files and those on the command line are parsed -in order. The same option can appear many times, in config files or on -the command line. Later values always override earlier ones. - -The parsing of CLI args and config files is initiated by invoking the config -manager for example:: - - conf = ConfigOpts() - conf.register_opt(BoolOpt('verbose', ...)) - conf(sys.argv[1:]) - if conf.verbose: - ... - -Option Groups -------------- - -Options can be registered as belonging to a group:: - - rabbit_group = cfg.OptGroup(name='rabbit', - title='RabbitMQ options') - - rabbit_host_opt = cfg.StrOpt('host', - default='localhost', - help='IP/hostname to listen on.'), - rabbit_port_opt = cfg.IntOpt('port', - default=5672, - help='Port number to listen on.') - - def register_rabbit_opts(conf): - conf.register_group(rabbit_group) - # options can be registered under a group in either of these ways: - conf.register_opt(rabbit_host_opt, group=rabbit_group) - conf.register_opt(rabbit_port_opt, group='rabbit') - -If no group attributes are required other than the group name, the group -need not be explicitly registered for example:: - - def register_rabbit_opts(conf): - # The group will automatically be created, equivalent calling:: - # conf.register_group(OptGroup(name='rabbit')) - conf.register_opt(rabbit_port_opt, group='rabbit') - -If no group is specified, options belong to the 'DEFAULT' section of config -files:: - - glance-api.conf: - [DEFAULT] - bind_port = 9292 - ... - - [rabbit] - host = localhost - port = 5672 - use_ssl = False - userid = guest - password = guest - virtual_host = / - -Command-line options in a group are automatically prefixed with the -group name:: - - --rabbit-host localhost --rabbit-port 9999 - -Accessing Option Values In Your Code ------------------------------------- - -Option values in the default group are referenced as attributes/properties on -the config manager; groups are also attributes on the config manager, with -attributes for each of the options associated with the group:: - - server.start(app, conf.bind_port, conf.bind_host, conf) - - self.connection = kombu.connection.BrokerConnection( - hostname=conf.rabbit.host, - port=conf.rabbit.port, - ...) - -Option Value Interpolation --------------------------- - -Option values may reference other values using PEP 292 string substitution:: - - opts = [ - cfg.StrOpt('state_path', - default=os.path.join(os.path.dirname(__file__), '../'), - help='Top-level directory for maintaining nova state.'), - cfg.StrOpt('sqlite_db', - default='nova.sqlite', - help='File name for SQLite.'), - cfg.StrOpt('sql_connection', - default='sqlite:///$state_path/$sqlite_db', - help='Connection string for SQL database.'), - ] - -.. note:: - - Interpolation can be avoided by using `$$`. - -.. warning:: - - Interpolation using the values of options in groups is not yet - supported. The interpolated option must be in the DEFAULT group - (i.e., ``"$state_path"`` works but ``"$database.state_path"`` does - not). - -Special Handling Instructions ------------------------------ - -Options may be declared as required so that an error is raised if the user -does not supply a value for the option:: - - opts = [ - cfg.StrOpt('service_name', required=True), - cfg.StrOpt('image_id', required=True), - ... - ] - -Options may be declared as secret so that their values are not leaked into -log files:: - - opts = [ - cfg.StrOpt('s3_store_access_key', secret=True), - cfg.StrOpt('s3_store_secret_key', secret=True), - ... - ] - -Global ConfigOpts ------------------ - -This module also contains a global instance of the ConfigOpts class -in order to support a common usage pattern in OpenStack:: - - from oslo_config import cfg - - opts = [ - cfg.StrOpt('bind_host', default='0.0.0.0'), - cfg.IntOpt('bind_port', default=9292), - ] - - CONF = cfg.CONF - CONF.register_opts(opts) - - def start(server, app): - server.start(app, CONF.bind_port, CONF.bind_host) - -Positional Command Line Arguments ---------------------------------- - -Positional command line arguments are supported via a 'positional' Opt -constructor argument:: - - >>> conf = ConfigOpts() - >>> conf.register_cli_opt(MultiStrOpt('bar', positional=True)) - True - >>> conf(['a', 'b']) - >>> conf.bar - ['a', 'b'] - -Sub-Parsers ------------ - -It is also possible to use argparse "sub-parsers" to parse additional -command line arguments using the SubCommandOpt class: - - >>> def add_parsers(subparsers): - ... list_action = subparsers.add_parser('list') - ... list_action.add_argument('id') - ... - >>> conf = ConfigOpts() - >>> conf.register_cli_opt(SubCommandOpt('action', handler=add_parsers)) - True - >>> conf(args=['list', '10']) - >>> conf.action.name, conf.action.id - ('list', '10') - -""" - -import argparse -import collections -import copy -import errno -import functools -import glob -import itertools -import logging -import os -import string -import sys - -import six -from six import moves - -from oslo_config import iniparser -from oslo_config import types - -LOG = logging.getLogger(__name__) - - -class Error(Exception): - """Base class for cfg exceptions.""" - - def __init__(self, msg=None): - self.msg = msg - - def __str__(self): - return self.msg - - -class NotInitializedError(Error): - """Raised if parser is not initialized yet.""" - - def __str__(self): - return "call expression on parser has not been invoked" - - -class ArgsAlreadyParsedError(Error): - """Raised if a CLI opt is registered after parsing.""" - - def __str__(self): - ret = "arguments already parsed" - if self.msg: - ret += ": " + self.msg - return ret - - -class NoSuchOptError(Error, AttributeError): - """Raised if an opt which doesn't exist is referenced.""" - - def __init__(self, opt_name, group=None): - self.opt_name = opt_name - self.group = group - - def __str__(self): - if self.group is None: - return "no such option: %s" % self.opt_name - else: - return "no such option in group %s: %s" % (self.group.name, - self.opt_name) - - -class NoSuchGroupError(Error): - """Raised if a group which doesn't exist is referenced.""" - - def __init__(self, group_name): - self.group_name = group_name - - def __str__(self): - return "no such group: %s" % self.group_name - - -class DuplicateOptError(Error): - """Raised if multiple opts with the same name are registered.""" - - def __init__(self, opt_name): - self.opt_name = opt_name - - def __str__(self): - return "duplicate option: %s" % self.opt_name - - -class RequiredOptError(Error): - """Raised if an option is required but no value is supplied by the user.""" - - def __init__(self, opt_name, group=None): - self.opt_name = opt_name - self.group = group - - def __str__(self): - if self.group is None: - return "value required for option: %s" % self.opt_name - else: - return "value required for option: %s.%s" % (self.group.name, - self.opt_name) - - -class TemplateSubstitutionError(Error): - """Raised if an error occurs substituting a variable in an opt value.""" - - def __str__(self): - return "template substitution error: %s" % self.msg - - -class ConfigFilesNotFoundError(Error): - """Raised if one or more config files are not found.""" - - def __init__(self, config_files): - self.config_files = config_files - - def __str__(self): - return ('Failed to find some config files: %s' % - ",".join(self.config_files)) - - -class ConfigFilesPermissionDeniedError(Error): - """Raised if one or more config files are not readable.""" - - def __init__(self, config_files): - self.config_files = config_files - - def __str__(self): - return ('Failed to open some config files: %s' % - ",".join(self.config_files)) - - -class ConfigDirNotFoundError(Error): - """Raised if the requested config-dir is not found.""" - - def __init__(self, config_dir): - self.config_dir = config_dir - - def __str__(self): - return ('Failed to read config file directory: %s' % self.config_dir) - - -class ConfigFileParseError(Error): - """Raised if there is an error parsing a config file.""" - - def __init__(self, config_file, msg): - self.config_file = config_file - self.msg = msg - - def __str__(self): - return 'Failed to parse %s: %s' % (self.config_file, self.msg) - - -class ConfigFileValueError(Error): - """Raised if a config file value does not match its opt type.""" - pass - - -def _fixpath(p): - """Apply tilde expansion and absolutization to a path.""" - return os.path.abspath(os.path.expanduser(p)) - - -def _get_config_dirs(project=None): - """Return a list of directories where config files may be located. - - :param project: an optional project name - - If a project is specified, following directories are returned:: - - ~/.${project}/ - ~/ - /etc/${project}/ - /etc/ - - Otherwise, these directories:: - - ~/ - /etc/ - """ - cfg_dirs = [ - _fixpath(os.path.join('~', '.' + project)) if project else None, - _fixpath('~'), - os.path.join('/etc', project) if project else None, - '/etc' - ] - - return list(moves.filter(bool, cfg_dirs)) - - -def _search_dirs(dirs, basename, extension=""): - """Search a list of directories for a given filename. - - Iterator over the supplied directories, returning the first file - found with the supplied name and extension. - - :param dirs: a list of directories - :param basename: the filename, for example 'glance-api' - :param extension: the file extension, for example '.conf' - :returns: the path to a matching file, or None - """ - for d in dirs: - path = os.path.join(d, '%s%s' % (basename, extension)) - if os.path.exists(path): - return path - - -def find_config_files(project=None, prog=None, extension='.conf'): - """Return a list of default configuration files. - - :param project: an optional project name - :param prog: the program name, defaulting to the basename of sys.argv[0] - :param extension: the type of the config file - - We default to two config files: [${project}.conf, ${prog}.conf] - - And we look for those config files in the following directories:: - - ~/.${project}/ - ~/ - /etc/${project}/ - /etc/ - - We return an absolute path for (at most) one of each the default config - files, for the topmost directory it exists in. - - For example, if project=foo, prog=bar and /etc/foo/foo.conf, /etc/bar.conf - and ~/.foo/bar.conf all exist, then we return ['/etc/foo/foo.conf', - '~/.foo/bar.conf'] - - If no project name is supplied, we only look for ${prog.conf}. - """ - if prog is None: - prog = os.path.basename(sys.argv[0]) - - cfg_dirs = _get_config_dirs(project) - - config_files = [] - if project: - config_files.append(_search_dirs(cfg_dirs, project, extension)) - config_files.append(_search_dirs(cfg_dirs, prog, extension)) - - return list(moves.filter(bool, config_files)) - - -def _is_opt_registered(opts, opt): - """Check whether an opt with the same name is already registered. - - The same opt may be registered multiple times, with only the first - registration having any effect. However, it is an error to attempt - to register a different opt with the same name. - - :param opts: the set of opts already registered - :param opt: the opt to be registered - :returns: True if the opt was previously registered, False otherwise - :raises: DuplicateOptError if a naming conflict is detected - """ - if opt.dest in opts: - if opts[opt.dest]['opt'] != opt: - raise DuplicateOptError(opt.name) - return True - else: - return False - - -def set_defaults(opts, **kwargs): - for opt in opts: - if opt.dest in kwargs: - opt.default = kwargs[opt.dest] - - -def _normalize_group_name(group_name): - if group_name == 'DEFAULT': - return group_name - return group_name.lower() - - -class Opt(object): - - """Base class for all configuration options. - - An Opt object has no public methods, but has a number of public string - properties: - - name: - the name of the option, which may include hyphens - type: - a callable object that takes string and returns converted and - validated value. Default types are available from - :class:`oslo_config.types` - dest: - the (hyphen-less) ConfigOpts property which contains the option value - short: - a single character CLI option name - default: - the default value of the option - sample_default: - a sample default value string to include in sample config files - positional: - True if the option is a positional CLI argument - metavar: - the name shown as the argument to a CLI option in --help output - help: - a string explaining how the option's value is used - """ - multi = False - - def __init__(self, name, type=None, dest=None, short=None, - default=None, positional=False, metavar=None, help=None, - secret=False, required=False, - deprecated_name=None, deprecated_group=None, - deprecated_opts=None, sample_default=None, - deprecated_for_removal=False): - """Construct an Opt object. - - The only required parameter is the option's name. However, it is - common to also supply a default and help string for all options. - - :param name: the option's name - :param type: the option's type. Must be a callable object that - takes string and returns converted and validated value - :param dest: the name of the corresponding ConfigOpts property - :param short: a single character CLI option name - :param default: the default value of the option - :param positional: True if the option is a positional CLI argument - :param metavar: the option argument to show in --help - :param help: an explanation of how the option is used - :param secret: true iff the value should be obfuscated in log output - :param required: true iff a value must be supplied for this option - :param deprecated_name: deprecated name option. Acts like an alias - :param deprecated_group: the group containing a deprecated alias - :param deprecated_opts: array of DeprecatedOpt(s) - :param sample_default: a default string for sample config files - :param deprecated_for_removal: indicates whether this opt is planned - for removal in a future release - """ - if name.startswith('_'): - raise ValueError('illegal name %s with prefix _' % (name,)) - self.name = name - - if type is None: - type = types.String() - - if not callable(type): - raise TypeError('type must be callable') - self.type = type - - if dest is None: - self.dest = self.name.replace('-', '_') - else: - self.dest = dest - self.short = short - self.default = default - self.sample_default = sample_default - self.positional = positional - self.metavar = metavar - self.help = help - self.secret = secret - self.required = required - self.deprecated_for_removal = deprecated_for_removal - self._logged_deprecation = False - if deprecated_name is not None: - deprecated_name = deprecated_name.replace('-', '_') - - self.deprecated_opts = copy.deepcopy(deprecated_opts) or [] - if deprecated_name is not None or deprecated_group is not None: - self.deprecated_opts.append(DeprecatedOpt(deprecated_name, - group=deprecated_group)) - self._assert_default_is_of_opt_type() - - def _default_is_ref(self): - """Check if default is a reference to another var.""" - if isinstance(self.default, six.string_types): - tmpl = self.default.replace('\$', '').replace('$$', '') - return '$' in tmpl - return False - - def _assert_default_is_of_opt_type(self): - if (self.default is not None - and not self._default_is_ref() - and hasattr(self.type, 'is_base_type') - and not self.type.is_base_type(self.default)): - # NOTE(tcammann) Change this to raise error after K relase - expected_types = ", ".join( - [t.__name__ for t in self.type.BASE_TYPES]) - LOG.debug(('Expected default value of type(s) %(extypes)s but got ' - '%(default)r of type %(deftypes)s'), - {'extypes': expected_types, - 'default': self.default, - 'deftypes': type(self.default).__name__}) - - def __ne__(self, another): - return vars(self) != vars(another) - - def __eq__(self, another): - return vars(self) == vars(another) - - __hash__ = object.__hash__ - - def _get_from_namespace(self, namespace, group_name): - """Retrieves the option value from a _Namespace object. - - :param namespace: a _Namespace object - :param group_name: a group name - """ - names = [(group_name, self.dest)] - - for opt in self.deprecated_opts: - dname, dgroup = opt.name, opt.group - if dname or dgroup: - names.append((dgroup if dgroup else group_name, - dname if dname else self.dest)) - - value = namespace._get_value(names, self.multi, self.positional) - # The previous line will raise a KeyError if no value is set in the - # config file, so we'll only log deprecations for set options. - if self.deprecated_for_removal and not self._logged_deprecation: - self._logged_deprecation = True - pretty_group = group_name or 'DEFAULT' - LOG.warning('Option "%s" from group "%s" is deprecated for ' - 'removal. Its value may be silently ignored in the ' - 'future.', self.dest, pretty_group) - return value - - def _add_to_cli(self, parser, group=None): - """Makes the option available in the command line interface. - - This is the method ConfigOpts uses to add the opt to the CLI interface - as appropriate for the opt type. Some opt types may extend this method, - others may just extend the helper methods it uses. - - :param parser: the CLI option parser - :param group: an optional OptGroup object - """ - container = self._get_argparse_container(parser, group) - kwargs = self._get_argparse_kwargs(group) - prefix = self._get_argparse_prefix('', group.name if group else None) - deprecated_names = [] - for opt in self.deprecated_opts: - deprecated_name = self._get_deprecated_cli_name(opt.name, - opt.group) - if deprecated_name is not None: - deprecated_names.append(deprecated_name) - self._add_to_argparse(parser, container, self.name, self.short, - kwargs, prefix, - self.positional, deprecated_names) - - def _add_to_argparse(self, parser, container, name, short, kwargs, - prefix='', positional=False, deprecated_names=None): - """Add an option to an argparse parser or group. - - :param container: an argparse._ArgumentGroup object - :param name: the opt name - :param short: the short opt name - :param kwargs: the keyword arguments for add_argument() - :param prefix: an optional prefix to prepend to the opt name - :param positional: whether the option is a positional CLI argument - """ - def hyphen(arg): - return arg if not positional else '' - - args = [hyphen('--') + prefix + name] - if short: - args.append(hyphen('-') + short) - for deprecated_name in deprecated_names: - args.append(hyphen('--') + deprecated_name) - - parser.add_parser_argument(container, *args, **kwargs) - - def _get_argparse_container(self, parser, group): - """Returns an argparse._ArgumentGroup. - - :param parser: an argparse.ArgumentParser - :param group: an (optional) OptGroup object - :returns: an argparse._ArgumentGroup if group is given, else parser - """ - if group is not None: - return group._get_argparse_group(parser) - else: - return parser - - def _get_argparse_kwargs(self, group, **kwargs): - """Build a dict of keyword arguments for argparse's add_argument(). - - Most opt types extend this method to customize the behaviour of the - options added to argparse. - - :param group: an optional group - :param kwargs: optional keyword arguments to add to - :returns: a dict of keyword arguments - """ - if not self.positional: - dest = self.dest - if group is not None: - dest = group.name + '_' + dest - kwargs['dest'] = dest - else: - kwargs['nargs'] = '?' - kwargs.update({'default': None, - 'metavar': self.metavar, - 'help': self.help, }) - return kwargs - - def _get_argparse_prefix(self, prefix, group_name): - """Build a prefix for the CLI option name, if required. - - CLI options in a group are prefixed with the group's name in order - to avoid conflicts between similarly named options in different - groups. - - :param prefix: an existing prefix to append to (for example 'no' or '') - :param group_name: an optional group name - :returns: a CLI option prefix including the group name, if appropriate - """ - if group_name is not None: - return group_name + '-' + prefix - else: - return prefix - - def _get_deprecated_cli_name(self, dname, dgroup, prefix=''): - """Build a CLi arg name for deprecated options. - - Either a deprecated name or a deprecated group or both or - neither can be supplied: - - dname, dgroup -> dgroup + '-' + dname - dname -> dname - dgroup -> dgroup + '-' + self.name - neither -> None - - :param dname: a deprecated name, which can be None - :param dgroup: a deprecated group, which can be None - :param prefix: an prefix to append to (for example 'no' or '') - :returns: a CLI argument name - """ - if dgroup == 'DEFAULT': - dgroup = None - - if dname is None and dgroup is None: - return None - - if dname is None: - dname = self.name - - return self._get_argparse_prefix(prefix, dgroup) + dname - - def __lt__(self, another): - return hash(self) < hash(another) - -# NOTE(jd) Not available for py2.6 -if six.PY3: - Opt = functools.total_ordering(Opt) - - -class DeprecatedOpt(object): - - """Represents a Deprecated option. - - Here's how you can use it:: - - oldopts = [cfg.DeprecatedOpt('oldopt1', group='group1'), - cfg.DeprecatedOpt('oldopt2', group='group2')] - cfg.CONF.register_group(cfg.OptGroup('group1')) - cfg.CONF.register_opt(cfg.StrOpt('newopt', deprecated_opts=oldopts), - group='group1') - - For options which have a single value (like in the example above), - if the new option is present ("[group1]/newopt" above), it will override - any deprecated options present ("[group1]/oldopt1" and "[group2]/oldopt2" - above). - - If no group is specified for a DeprecatedOpt option (i.e. the group is - None), lookup will happen within the same group the new option is in. - For example, if no group was specified for the second option 'oldopt2' in - oldopts list: - - oldopts = [cfg.DeprecatedOpt('oldopt1', group='group1'), - cfg.DeprecatedOpt('oldopt2')] - cfg.CONF.register_group(cfg.OptGroup('group1')) - cfg.CONF.register_opt(cfg.StrOpt('newopt', deprecated_opts=oldopts), - group='group1') - - then lookup for that option will happen in group 'group1'. - - If the new option is not present and multiple deprecated options are - present, the option corresponding to the first element of deprecated_opts - will be chosen. - - Multi-value options will return all new and deprecated - options. So if we have a multi-value option "[group1]/opt1" whose - deprecated option is "[group2]/opt2", and the conf file has both these - options specified like so:: - - [group1] - opt1=val10,val11 - - [group2] - opt2=val21,val22 - - Then the value of "[group1]/opt1" will be ['val11', 'val12', 'val21', - 'val22']. - """ - - def __init__(self, name, group=None): - """Constructs an DeprecatedOpt object. - - :param name: the name of the option - :param group: the group of the option - """ - self.name = name - self.group = group - - def __key(self): - return (self.name, self.group) - - def __eq__(self, other): - return self.__key() == other.__key() - - def __hash__(self): - return hash(self.__key()) - - -class StrOpt(Opt): - """Option with String type - - Option with ``type`` :class:`oslo_config.types.String` - - `Kept for backward-compatibility with options not using Opt directly`. - - :param choices: Optional sequence of valid values. - """ - - def __init__(self, name, choices=None, **kwargs): - super(StrOpt, self).__init__(name, - type=types.String(choices=choices), - **kwargs) - - -class BoolOpt(Opt): - - """Boolean options. - - Bool opts are set to True or False on the command line using --optname or - --noopttname respectively. - - In config files, boolean values are cast with Boolean type. - """ - - def __init__(self, name, **kwargs): - if 'positional' in kwargs: - raise ValueError('positional boolean args not supported') - super(BoolOpt, self).__init__(name, type=types.Boolean(), **kwargs) - - def _add_to_cli(self, parser, group=None): - """Extends the base class method to add the --nooptname option.""" - super(BoolOpt, self)._add_to_cli(parser, group) - self._add_inverse_to_argparse(parser, group) - - def _add_inverse_to_argparse(self, parser, group): - """Add the --nooptname option to the option parser.""" - container = self._get_argparse_container(parser, group) - kwargs = self._get_argparse_kwargs(group, action='store_false') - prefix = self._get_argparse_prefix('no', group.name if group else None) - deprecated_names = [] - for opt in self.deprecated_opts: - deprecated_name = self._get_deprecated_cli_name(opt.name, - opt.group, - prefix='no') - if deprecated_name is not None: - deprecated_names.append(deprecated_name) - kwargs["help"] = "The inverse of --" + self.name - self._add_to_argparse(parser, container, self.name, None, kwargs, - prefix, self.positional, deprecated_names) - - def _get_argparse_kwargs(self, group, action='store_true', **kwargs): - """Extends the base argparse keyword dict for boolean options.""" - - kwargs = super(BoolOpt, self)._get_argparse_kwargs(group, **kwargs) - # type has no effect for BoolOpt, it only matters for - # values that came from config files - if 'type' in kwargs: - del kwargs['type'] - - # metavar has no effect for BoolOpt - if 'metavar' in kwargs: - del kwargs['metavar'] - - kwargs['action'] = action - - return kwargs - - -class IntOpt(Opt): - - """Option with Integer type - - Option with ``type`` :class:`oslo_config.types.Integer` - - `Kept for backward-compatibility with options not using Opt directly`. - """ - - def __init__(self, name, **kwargs): - super(IntOpt, self).__init__(name, type=types.Integer(), **kwargs) - - -class FloatOpt(Opt): - - """Option with Float type - - Option with ``type`` :class:`oslo_config.types.Float` - - `Kept for backward-communicability with options not using Opt directly`. - """ - - def __init__(self, name, **kwargs): - super(FloatOpt, self).__init__(name, type=types.Float(), **kwargs) - - -class ListOpt(Opt): - - """Option with List(String) type - - Option with ``type`` :class:`oslo_config.types.List` - - `Kept for backward-compatibility with options not using Opt directly`. - """ - - def __init__(self, name, **kwargs): - super(ListOpt, self).__init__(name, type=types.List(), **kwargs) - - -class DictOpt(Opt): - - """Option with Dict(String) type - - Option with ``type`` :class:`oslo_config.types.Dict` - - `Kept for backward-compatibility with options not using Opt directly`. - """ - - def __init__(self, name, **kwargs): - super(DictOpt, self).__init__(name, type=types.Dict(), **kwargs) - - -class IPOpt(Opt): - - """Opt with IPAddress type - - Option with ``type`` :class:`oslo_config.types.IPAddress` - - :param version: one of either ``4``, ``6``, or ``None`` to specify - either version. - """ - - def __init__(self, name, version=None, **kwargs): - super(IPOpt, self).__init__(name, type=types.IPAddress(version), - **kwargs) - - -class MultiOpt(Opt): - - """Multi-value option. - - Multi opt values are typed opts which may be specified multiple times. - The opt value is a list containing all the values specified. - - :param name: Name of the config option - :param item_type: Type of items (see :class:`oslo_config.types`) - - For example:: - - cfg.MultiOpt('foo', - item_type=types.Integer(), - default=None, - help="Multiple foo option") - - The command line ``--foo=1 --foo=2`` would result in ``cfg.CONF.foo`` - containing ``[1,2]`` - """ - multi = True - - def __init__(self, name, item_type, **kwargs): - super(MultiOpt, self).__init__(name, item_type, **kwargs) - - def _get_argparse_kwargs(self, group, **kwargs): - """Extends the base argparse keyword dict for multi value options.""" - kwargs = super(MultiOpt, self)._get_argparse_kwargs(group) - if not self.positional: - kwargs['action'] = 'append' - else: - kwargs['nargs'] = '*' - return kwargs - - -class MultiStrOpt(MultiOpt): - - """MultiOpt with a MultiString ``item_type``. - - MultiOpt with a default :class:`oslo_config.types.MultiString` item - type. - - `Kept for backwards-compatibility for options that do not use - MultiOpt directly`. - - """ - - def __init__(self, name, **kwargs): - super(MultiStrOpt, self).__init__(name, - item_type=types.MultiString(), - **kwargs) - - -class SubCommandOpt(Opt): - - """Sub-command options. - - Sub-command options allow argparse sub-parsers to be used to parse - additional command line arguments. - - The handler argument to the SubCommandOpt constructor is a callable - which is supplied an argparse subparsers object. Use this handler - callable to add sub-parsers. - - The opt value is SubCommandAttr object with the name of the chosen - sub-parser stored in the 'name' attribute and the values of other - sub-parser arguments available as additional attributes. - """ - - def __init__(self, name, dest=None, handler=None, - title=None, description=None, help=None): - """Construct an sub-command parsing option. - - This behaves similarly to other Opt sub-classes but adds a - 'handler' argument. The handler is a callable which is supplied - an subparsers object when invoked. The add_parser() method on - this subparsers object can be used to register parsers for - sub-commands. - - :param name: the option's name - :param dest: the name of the corresponding ConfigOpts property - :param title: title of the sub-commands group in help output - :param description: description of the group in help output - :param help: a help string giving an overview of available sub-commands - """ - super(SubCommandOpt, self).__init__(name, type=types.String(), - dest=dest, help=help) - self.handler = handler - self.title = title - self.description = description - - def _add_to_cli(self, parser, group=None): - """Add argparse sub-parsers and invoke the handler method.""" - dest = self.dest - if group is not None: - dest = group.name + '_' + dest - - subparsers = parser.add_subparsers(dest=dest, - title=self.title, - description=self.description, - help=self.help) - # NOTE(jd) Set explicitly to True for Python 3 - # See http://bugs.python.org/issue9253 for context - subparsers.required = True - - if self.handler is not None: - self.handler(subparsers) - - -class _ConfigFileOpt(Opt): - - """The --config-file option. - - This is an private option type which handles the special processing - required for --config-file options. - - As each --config-file option is encountered on the command line, we - parse the file and store the parsed values in the _Namespace object. - This allows us to properly handle the precedence of --config-file - options over previous command line arguments, but not over subsequent - arguments. - """ - - class ConfigFileAction(argparse.Action): - - """An argparse action for --config-file. - - As each --config-file option is encountered, this action adds the - value to the config_file attribute on the _Namespace object but also - parses the configuration file and stores the values found also in - the _Namespace object. - """ - - def __call__(self, parser, namespace, values, option_string=None): - """Handle a --config-file command line argument. - - :raises: ConfigFileParseError, ConfigFileValueError - """ - if getattr(namespace, self.dest, None) is None: - setattr(namespace, self.dest, []) - items = getattr(namespace, self.dest) - items.append(values) - - ConfigParser._parse_file(values, namespace) - - def __init__(self, name, **kwargs): - super(_ConfigFileOpt, self).__init__(name, lambda x: x, **kwargs) - - def _get_argparse_kwargs(self, group, **kwargs): - """Extends the base argparse keyword dict for the config file opt.""" - kwargs = super(_ConfigFileOpt, self)._get_argparse_kwargs(group) - kwargs['action'] = self.ConfigFileAction - return kwargs - - -class _ConfigDirOpt(Opt): - - """The --config-dir option. - - This is an private option type which handles the special processing - required for --config-dir options. - - As each --config-dir option is encountered on the command line, we - parse the files in that directory and store the parsed values in the - _Namespace object. This allows us to properly handle the precedence of - --config-dir options over previous command line arguments, but not - over subsequent arguments. - """ - - class ConfigDirAction(argparse.Action): - - """An argparse action for --config-dir. - - As each --config-dir option is encountered, this action sets the - config_dir attribute on the _Namespace object but also parses the - configuration files and stores the values found also in the - _Namespace object. - """ - - def __call__(self, parser, namespace, values, option_string=None): - """Handle a --config-dir command line argument. - - :raises: ConfigFileParseError, ConfigFileValueError, - ConfigDirNotFoundError - """ - setattr(namespace, self.dest, values) - - values = os.path.expanduser(values) - - if not os.path.exists(values): - raise ConfigDirNotFoundError(values) - - config_dir_glob = os.path.join(values, '*.conf') - - for config_file in sorted(glob.glob(config_dir_glob)): - ConfigParser._parse_file(config_file, namespace) - - def __init__(self, name, **kwargs): - super(_ConfigDirOpt, self).__init__(name, type=types.String(), - **kwargs) - - def _get_argparse_kwargs(self, group, **kwargs): - """Extends the base argparse keyword dict for the config dir option.""" - kwargs = super(_ConfigDirOpt, self)._get_argparse_kwargs(group) - kwargs['action'] = self.ConfigDirAction - return kwargs - - -class OptGroup(object): - - """Represents a group of opts. - - CLI opts in the group are automatically prefixed with the group name. - - Each group corresponds to a section in config files. - - An OptGroup object has no public methods, but has a number of public string - properties: - - name: - the name of the group - title: - the group title as displayed in --help - help: - the group description as displayed in --help - """ - - def __init__(self, name, title=None, help=None): - """Constructs an OptGroup object. - - :param name: the group name - :param title: the group title for --help - :param help: the group description for --help - """ - self.name = name - self.title = "%s options" % name if title is None else title - self.help = help - - self._opts = {} # dict of dicts of (opt:, override:, default:) - self._argparse_group = None - - def _register_opt(self, opt, cli=False): - """Add an opt to this group. - - :param opt: an Opt object - :param cli: whether this is a CLI option - :returns: False if previously registered, True otherwise - :raises: DuplicateOptError if a naming conflict is detected - """ - if _is_opt_registered(self._opts, opt): - return False - - self._opts[opt.dest] = {'opt': opt, 'cli': cli} - - return True - - def _unregister_opt(self, opt): - """Remove an opt from this group. - - :param opt: an Opt object - """ - if opt.dest in self._opts: - del self._opts[opt.dest] - - def _get_argparse_group(self, parser): - if self._argparse_group is None: - """Build an argparse._ArgumentGroup for this group.""" - self._argparse_group = parser.add_argument_group(self.title, - self.help) - return self._argparse_group - - def _clear(self): - """Clear this group's option parsing state.""" - self._argparse_group = None - - -class ParseError(iniparser.ParseError): - def __init__(self, msg, lineno, line, filename): - super(ParseError, self).__init__(msg, lineno, line) - self.filename = filename - - def __str__(self): - return 'at %s:%d, %s: %r' % (self.filename, self.lineno, - self.msg, self.line) - - -class ConfigParser(iniparser.BaseParser): - def __init__(self, filename, sections): - super(ConfigParser, self).__init__() - self.filename = filename - self.sections = sections - self._normalized = None - self.section = None - - def _add_normalized(self, normalized): - self._normalized = normalized - - def parse(self): - with open(self.filename) as f: - return super(ConfigParser, self).parse(f) - - def new_section(self, section): - self.section = section - self.sections.setdefault(self.section, {}) - - if self._normalized is not None: - self._normalized.setdefault(_normalize_group_name(self.section), - {}) - - def assignment(self, key, value): - if not self.section: - raise self.error_no_section() - - value = '\n'.join(value) - - def append(sections, section): - sections[section].setdefault(key, []) - sections[section][key].append(value) - - append(self.sections, self.section) - if self._normalized is not None: - append(self._normalized, _normalize_group_name(self.section)) - - def parse_exc(self, msg, lineno, line=None): - return ParseError(msg, lineno, line, self.filename) - - def error_no_section(self): - return self.parse_exc('Section must be started before assignment', - self.lineno) - - @classmethod - def _parse_file(cls, config_file, namespace): - """Parse a config file and store any values in the namespace. - - :raises: ConfigFileParseError, ConfigFileValueError - """ - config_file = _fixpath(config_file) - - sections = {} - normalized = {} - parser = cls(config_file, sections) - parser._add_normalized(normalized) - - try: - parser.parse() - except iniparser.ParseError as pe: - raise ConfigFileParseError(pe.filename, str(pe)) - except IOError as err: - if err.errno == errno.ENOENT: - namespace._file_not_found(config_file) - return - if err.errno == errno.EACCES: - namespace._file_permission_denied(config_file) - return - raise - - namespace._add_parsed_config_file(sections, normalized) - - -class MultiConfigParser(object): - _deprecated_opt_message = ('Option "%s" from group "%s" is deprecated. ' - 'Use option "%s" from group "%s".') - - def __init__(self): - self.parsed = [] - self._normalized = [] - self._emitted_deprecations = set() - - def read(self, config_files): - read_ok = [] - - for filename in config_files: - sections = {} - normalized = {} - parser = ConfigParser(filename, sections) - parser._add_normalized(normalized) - - try: - parser.parse() - except IOError: - continue - self._add_parsed_config_file(sections, normalized) - read_ok.append(filename) - - return read_ok - - def _add_parsed_config_file(self, sections, normalized): - """Add a parsed config file to the list of parsed files. - - :param sections: a mapping of section name to dicts of config values - :param normalized: sections mapping with section names normalized - :raises: ConfigFileValueError - """ - self.parsed.insert(0, sections) - self._normalized.insert(0, normalized) - - def get(self, names, multi=False): - return self._get(names, multi=multi) - - def _get(self, names, multi=False, normalized=False): - """Fetch a config file value from the parsed files. - - :param names: a list of (section, name) tuples - :param multi: a boolean indicating whether to return multiple values - :param normalized: whether to normalize group names to lowercase - """ - rvalue = [] - - def normalize(name): - return _normalize_group_name(name) if normalized else name - - names = [(normalize(section), name) for section, name in names] - - for sections in (self._normalized if normalized else self.parsed): - for section, name in names: - if section not in sections: - continue - if name in sections[section]: - self._check_deprecated((section, name), names[0], - names[1:]) - val = sections[section][name] - if multi: - rvalue = val + rvalue - else: - return val - if multi and rvalue != []: - return rvalue - raise KeyError - - def _check_deprecated(self, name, current, deprecated): - """Check for usage of deprecated names. - - :param name: A tuple of the form (group, name) representing the group - and name where an opt value was found. - :param current: A tuple of the form (group, name) representing the - current name for an option. - :param deprecated: A list of tuples with the same format as the name - param which represent any deprecated names for an option. - If the name param matches any entries in this list a - deprecation warning will be logged. - """ - # Opts in the DEFAULT group may come in with a group name of either - # 'DEFAULT' or None. Force them all to 'DEFAULT' since that's a more - # user-friendly form. - deprecated_names = set((g or 'DEFAULT', n) for (g, n) in deprecated) - name = (name[0] or 'DEFAULT', name[1]) - if name in deprecated_names and name not in self._emitted_deprecations: - self._emitted_deprecations.add(name) - current = (current[0] or 'DEFAULT', current[1]) - # NOTE(bnemec): Not using versionutils for this to avoid a - # circular dependency between oslo.config and whatever library - # versionutils ends up in. - LOG.warning(self._deprecated_opt_message, name[1], - name[0], current[1], current[0]) - - -class _Namespace(argparse.Namespace): - - """An argparse namespace which also stores config file values. - - As we parse command line arguments, the values get set as attributes - on a namespace object. However, we also want to parse config files as - they are specified on the command line and collect the values alongside - the option values parsed from the command line. - - Note, we don't actually assign values from config files as attributes - on the namespace because config file options be registered after the - command line has been parsed, so we may not know how to properly parse - or convert a config file value at this point. - """ - - def __init__(self, conf): - self._conf = conf - self._parser = MultiConfigParser() - self._files_not_found = [] - self._files_permission_denied = [] - - def _parse_cli_opts_from_config_file(self, sections, normalized): - """Parse CLI options from a config file. - - CLI options are special - we require they be registered before the - command line is parsed. This means that as we parse config files, we - can go ahead and apply the appropriate option-type specific conversion - to the values in config files for CLI options. We can't do this for - non-CLI options, because the schema describing those options may not be - registered until after the config files are parsed. - - This method relies on that invariant in order to enforce proper - priority of option values - i.e. that the order in which an option - value is parsed, whether the value comes from the CLI or a config file, - determines which value specified for a given option wins. - - The way we implement this ordering is that as we parse each config - file, we look for values in that config file for CLI options only. Any - values for CLI options found in the config file are treated like they - had appeared on the command line and set as attributes on the namespace - objects. Values in later config files or on the command line will - override values found in this file. - """ - namespace = _Namespace(self._conf) - namespace._parser._add_parsed_config_file(sections, normalized) - - for opt, group in sorted(self._conf._all_cli_opts()): - group_name = group.name if group is not None else None - try: - value = opt._get_from_namespace(namespace, group_name) - except KeyError: - continue - except ValueError as ve: - raise ConfigFileValueError(str(ve)) - - if group_name is None: - dest = opt.dest - else: - dest = group_name + '_' + opt.dest - - if opt.multi: - if getattr(self, dest, None) is None: - setattr(self, dest, []) - values = getattr(self, dest) - values.extend(value) - else: - setattr(self, dest, value) - - def _add_parsed_config_file(self, sections, normalized): - """Add a parsed config file to the list of parsed files. - - :param sections: a mapping of section name to dicts of config values - :param normalized: sections mapping with section names normalized - :raises: ConfigFileValueError - """ - self._parse_cli_opts_from_config_file(sections, normalized) - self._parser._add_parsed_config_file(sections, normalized) - - def _file_not_found(self, config_file): - """Record that we were unable to open a config file. - - :param config_file: the path to the failed file - """ - self._files_not_found.append(config_file) - - def _file_permission_denied(self, config_file): - """Record that we have no permission to open a config file. - - :param config_file: the path to the failed file - """ - self._files_permission_denied.append(config_file) - - def _get_cli_value(self, names, positional): - """Fetch a CLI option value. - - Look up the value of a CLI option. The value itself may have come from - parsing the command line or parsing config files specified on the - command line. Type conversion have already been performed for CLI - options at this point. - - :param names: a list of (section, name) tuples - :param positional: whether this is a positional option - """ - for group_name, name in names: - name = name if group_name is None else group_name + '_' + name - value = getattr(self, name, None) - if value is not None: - # argparse ignores default=None for nargs='*' and returns [] - if positional and not value: - continue - - return value - - raise KeyError - - def _get_value(self, names, multi, positional): - """Fetch a value from config files. - - Multiple names for a given configuration option may be supplied so - that we can transparently handle files containing deprecated option - names or groups. - - :param names: a list of (section, name) tuples - :param multi: a boolean indicating whether to return multiple values - :param positional: whether this is a positional option - """ - try: - return self._get_cli_value(names, positional) - except KeyError: - pass - - names = [(g if g is not None else 'DEFAULT', n) for g, n in names] - values = self._parser._get(names, multi=multi, normalized=True) - return values if multi else values[-1] - - -class _CachedArgumentParser(argparse.ArgumentParser): - - """class for caching/collecting command line arguments. - - It also sorts the arguments before initializing the ArgumentParser. - We need to do this since ArgumentParser by default does not sort - the argument options and the only way to influence the order of - arguments in '--help' is to ensure they are added in the sorted - order. - """ - - def __init__(self, prog=None, usage=None, **kwargs): - super(_CachedArgumentParser, self).__init__(prog, usage, **kwargs) - self._args_cache = {} - - def add_parser_argument(self, container, *args, **kwargs): - values = [] - if container in self._args_cache: - values = self._args_cache[container] - values.append({'args': args, 'kwargs': kwargs}) - self._args_cache[container] = values - - def initialize_parser_arguments(self): - # NOTE(mfedosin): The code below looks a little bit weird, but - # it's done because we need to sort only optional opts and do - # not touch positional. For the reason optional opts go first in - # the values we only need to find an index of the first positional - # option and then sort the values slice. - for container, values in six.iteritems(self._args_cache): - index = 0 - for index, argument in enumerate(values): - if not argument['args'][0].startswith('-'): - break - values[:index] = sorted(values[:index], key=lambda x: x['args']) - for argument in values: - try: - container.add_argument(*argument['args'], - **argument['kwargs']) - except argparse.ArgumentError as e: - raise DuplicateOptError(e) - self._args_cache = {} - - def parse_args(self, args=None, namespace=None): - self.initialize_parser_arguments() - return super(_CachedArgumentParser, self).parse_args(args, namespace) - - def print_help(self, file=None): - self.initialize_parser_arguments() - super(_CachedArgumentParser, self).print_help(file) - - def print_usage(self, file=None): - self.initialize_parser_arguments() - super(_CachedArgumentParser, self).print_usage(file) - - -class ConfigOpts(collections.Mapping): - - """Config options which may be set on the command line or in config files. - - ConfigOpts is a configuration option manager with APIs for registering - option schemas, grouping options, parsing option values and retrieving - the values of options. - """ - - def __init__(self): - """Construct a ConfigOpts object.""" - self._opts = {} # dict of dicts of (opt:, override:, default:) - self._groups = {} - - self._args = None - - self._oparser = None - self._namespace = None - self.__cache = {} - self._config_opts = [] - self._cli_opts = collections.deque() - self._validate_default_values = False - - def _pre_setup(self, project, prog, version, usage, default_config_files): - """Initialize a ConfigCliParser object for option parsing.""" - - if prog is None: - prog = os.path.basename(sys.argv[0]) - - if default_config_files is None: - default_config_files = find_config_files(project, prog) - - self._oparser = _CachedArgumentParser(prog=prog, usage=usage) - self._oparser.add_parser_argument(self._oparser, - '--version', - action='version', - version=version) - - return prog, default_config_files - - def _setup(self, project, prog, version, usage, default_config_files): - """Initialize a ConfigOpts object for option parsing.""" - - self._config_opts = [ - _ConfigFileOpt('config-file', - default=default_config_files, - metavar='PATH', - help=('Path to a config file to use. Multiple ' - 'config files can be specified, with values ' - 'in later files taking precedence. The ' - 'default files used are: %(default)s.')), - _ConfigDirOpt('config-dir', - metavar='DIR', - help='Path to a config directory to pull *.conf ' - 'files from. This file set is sorted, so as to ' - 'provide a predictable parse order if ' - 'individual options are over-ridden. The set ' - 'is parsed after the file(s) specified via ' - 'previous --config-file, arguments hence ' - 'over-ridden options in the directory take ' - 'precedence.'), - ] - self.register_cli_opts(self._config_opts) - - self.project = project - self.prog = prog - self.version = version - self.usage = usage - self.default_config_files = default_config_files - - def __clear_cache(f): - @functools.wraps(f) - def __inner(self, *args, **kwargs): - if kwargs.pop('clear_cache', True): - result = f(self, *args, **kwargs) - self.__cache.clear() - return result - else: - return f(self, *args, **kwargs) - - return __inner - - def __call__(self, - args=None, - project=None, - prog=None, - version=None, - usage=None, - default_config_files=None, - validate_default_values=False): - """Parse command line arguments and config files. - - Calling a ConfigOpts object causes the supplied command line arguments - and config files to be parsed, causing opt values to be made available - as attributes of the object. - - The object may be called multiple times, each time causing the previous - set of values to be overwritten. - - Automatically registers the --config-file option with either a supplied - list of default config files, or a list from find_config_files(). - - If the --config-dir option is set, any *.conf files from this - directory are pulled in, after all the file(s) specified by the - --config-file option. - - :param args: command line arguments (defaults to sys.argv[1:]) - :param project: the toplevel project name, used to locate config files - :param prog: the name of the program (defaults to sys.argv[0] basename) - :param version: the program version (for --version) - :param usage: a usage string (%prog will be expanded) - :param default_config_files: config files to use by default - :param validate_default_values: whether to validate the default values - :returns: the list of arguments left over after parsing options - :raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError, - ConfigFilesPermissionDeniedError, - RequiredOptError, DuplicateOptError - """ - self.clear() - - self._validate_default_values = validate_default_values - - prog, default_config_files = self._pre_setup(project, - prog, - version, - usage, - default_config_files) - - self._setup(project, prog, version, usage, default_config_files) - - self._namespace = self._parse_cli_opts(args if args is not None - else sys.argv[1:]) - if self._namespace._files_not_found: - raise ConfigFilesNotFoundError(self._namespace._files_not_found) - if self._namespace._files_permission_denied: - raise ConfigFilesPermissionDeniedError( - self._namespace._files_permission_denied) - - self._check_required_opts() - - def __getattr__(self, name): - """Look up an option value and perform string substitution. - - :param name: the opt name (or 'dest', more precisely) - :returns: the option value (after string substitution) or a GroupAttr - :raises: NoSuchOptError - """ - try: - return self._get(name) - except Exception: - raise NoSuchOptError(name) - - def __getitem__(self, key): - """Look up an option value and perform string substitution.""" - return self.__getattr__(key) - - def __contains__(self, key): - """Return True if key is the name of a registered opt or group.""" - return key in self._opts or key in self._groups - - def __iter__(self): - """Iterate over all registered opt and group names.""" - for key in itertools.chain(self._opts.keys(), self._groups.keys()): - yield key - - def __len__(self): - """Return the number of options and option groups.""" - return len(self._opts) + len(self._groups) - - def reset(self): - """Clear the object state and unset overrides and defaults.""" - self._unset_defaults_and_overrides() - self.clear() - - @__clear_cache - def clear(self): - """Clear the state of the object to before it was called. - - Any subparsers added using the add_cli_subparsers() will also be - removed as a side-effect of this method. - """ - self._args = None - self._oparser = None - self._namespace = None - self._validate_default_values = False - self.unregister_opts(self._config_opts) - for group in self._groups.values(): - group._clear() - - def _add_cli_opt(self, opt, group): - if {'opt': opt, 'group': group} in self._cli_opts: - return - if opt.positional: - self._cli_opts.append({'opt': opt, 'group': group}) - else: - self._cli_opts.appendleft({'opt': opt, 'group': group}) - - @__clear_cache - def register_opt(self, opt, group=None, cli=False): - """Register an option schema. - - Registering an option schema makes any option value which is previously - or subsequently parsed from the command line or config files available - as an attribute of this object. - - :param opt: an instance of an Opt sub-class - :param cli: whether this is a CLI option - :param group: an optional OptGroup object or group name - :return: False if the opt was already registered, True otherwise - :raises: DuplicateOptError - """ - if group is not None: - group = self._get_group(group, autocreate=True) - if cli: - self._add_cli_opt(opt, group) - return group._register_opt(opt, cli) - - if cli: - self._add_cli_opt(opt, None) - - if _is_opt_registered(self._opts, opt): - return False - - self._opts[opt.dest] = {'opt': opt, 'cli': cli} - - return True - - @__clear_cache - def register_opts(self, opts, group=None): - """Register multiple option schemas at once.""" - for opt in opts: - self.register_opt(opt, group, clear_cache=False) - - @__clear_cache - def register_cli_opt(self, opt, group=None): - """Register a CLI option schema. - - CLI option schemas must be registered before the command line and - config files are parsed. This is to ensure that all CLI options are - shown in --help and option validation works as expected. - - :param opt: an instance of an Opt sub-class - :param group: an optional OptGroup object or group name - :return: False if the opt was already registered, True otherwise - :raises: DuplicateOptError, ArgsAlreadyParsedError - """ - if self._args is not None: - raise ArgsAlreadyParsedError("cannot register CLI option") - - return self.register_opt(opt, group, cli=True, clear_cache=False) - - @__clear_cache - def register_cli_opts(self, opts, group=None): - """Register multiple CLI option schemas at once.""" - for opt in opts: - self.register_cli_opt(opt, group, clear_cache=False) - - def register_group(self, group): - """Register an option group. - - An option group must be registered before options can be registered - with the group. - - :param group: an OptGroup object - """ - if group.name in self._groups: - return - - self._groups[group.name] = copy.copy(group) - - @__clear_cache - def unregister_opt(self, opt, group=None): - """Unregister an option. - - :param opt: an Opt object - :param group: an optional OptGroup object or group name - :raises: ArgsAlreadyParsedError, NoSuchGroupError - """ - if self._args is not None: - raise ArgsAlreadyParsedError("reset before unregistering options") - - remitem = None - for item in self._cli_opts: - if (item['opt'].dest == opt.dest and - (group is None or - self._get_group(group).name == item['group'].name)): - remitem = item - break - if remitem is not None: - self._cli_opts.remove(remitem) - - if group is not None: - self._get_group(group)._unregister_opt(opt) - elif opt.dest in self._opts: - del self._opts[opt.dest] - - @__clear_cache - def unregister_opts(self, opts, group=None): - """Unregister multiple CLI option schemas at once.""" - for opt in opts: - self.unregister_opt(opt, group, clear_cache=False) - - def import_opt(self, name, module_str, group=None): - """Import an option definition from a module. - - Import a module and check that a given option is registered. - - This is intended for use with global configuration objects - like cfg.CONF where modules commonly register options with - CONF at module load time. If one module requires an option - defined by another module it can use this method to explicitly - declare the dependency. - - :param name: the name/dest of the opt - :param module_str: the name of a module to import - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - __import__(module_str) - self._get_opt_info(name, group) - - def import_group(self, group, module_str): - """Import an option group from a module. - - Import a module and check that a given option group is registered. - - This is intended for use with global configuration objects - like cfg.CONF where modules commonly register options with - CONF at module load time. If one module requires an option group - defined by another module it can use this method to explicitly - declare the dependency. - - :param group: an option OptGroup object or group name - :param module_str: the name of a module to import - :raises: ImportError, NoSuchGroupError - """ - __import__(module_str) - self._get_group(group) - - @__clear_cache - def set_override(self, name, override, group=None): - """Override an opt value. - - Override the command line, config file and default values of a - given option. - - :param name: the name/dest of the opt - :param override: the override value - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - opt_info = self._get_opt_info(name, group) - opt_info['override'] = override - - @__clear_cache - def set_default(self, name, default, group=None): - """Override an opt's default value. - - Override the default value of given option. A command line or - config file value will still take precedence over this default. - - :param name: the name/dest of the opt - :param default: the default value - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - opt_info = self._get_opt_info(name, group) - opt_info['default'] = default - - @__clear_cache - def clear_override(self, name, group=None): - """Clear an override an opt value. - - Clear a previously set override of the command line, config file - and default values of a given option. - - :param name: the name/dest of the opt - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - opt_info = self._get_opt_info(name, group) - opt_info.pop('override', None) - - @__clear_cache - def clear_default(self, name, group=None): - """Clear an override an opt's default value. - - Clear a previously set override of the default value of given option. - - :param name: the name/dest of the opt - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - opt_info = self._get_opt_info(name, group) - opt_info.pop('default', None) - - def _all_opt_infos(self): - """A generator function for iteration opt infos.""" - for info in self._opts.values(): - yield info, None - for group in self._groups.values(): - for info in group._opts.values(): - yield info, group - - def _all_cli_opts(self): - """A generator function for iterating CLI opts.""" - for item in self._cli_opts: - yield item['opt'], item['group'] - - def _unset_defaults_and_overrides(self): - """Unset any default or override on all options.""" - for info, group in self._all_opt_infos(): - info.pop('default', None) - info.pop('override', None) - - def find_file(self, name): - """Locate a file located alongside the config files. - - Search for a file with the supplied basename in the directories - which we have already loaded config files from and other known - configuration directories. - - The directory, if any, supplied by the config_dir option is - searched first. Then the config_file option is iterated over - and each of the base directories of the config_files values - are searched. Failing both of these, the standard directories - searched by the module level find_config_files() function is - used. The first matching file is returned. - - :param name: the filename, for example 'policy.json' - :returns: the path to a matching file, or None - """ - dirs = [] - if self.config_dir: - dirs.append(_fixpath(self.config_dir)) - - for cf in reversed(self.config_file): - dirs.append(os.path.dirname(_fixpath(cf))) - - dirs.extend(_get_config_dirs(self.project)) - - return _search_dirs(dirs, name) - - def log_opt_values(self, logger, lvl): - """Log the value of all registered opts. - - It's often useful for an app to log its configuration to a log file at - startup for debugging. This method dumps to the entire config state to - the supplied logger at a given log level. - - :param logger: a logging.Logger object - :param lvl: the log level (for example logging.DEBUG) arg to - logger.log() - """ - logger.log(lvl, "*" * 80) - logger.log(lvl, "Configuration options gathered from:") - logger.log(lvl, "command line args: %s", self._args) - logger.log(lvl, "config files: %s", self.config_file) - logger.log(lvl, "=" * 80) - - def _sanitize(opt, value): - """Obfuscate values of options declared secret.""" - return value if not opt.secret else '*' * 4 - - for opt_name in sorted(self._opts): - opt = self._get_opt_info(opt_name)['opt'] - logger.log(lvl, "%-30s = %s", opt_name, - _sanitize(opt, getattr(self, opt_name))) - - for group_name in self._groups: - group_attr = self.GroupAttr(self, self._get_group(group_name)) - for opt_name in sorted(self._groups[group_name]._opts): - opt = self._get_opt_info(opt_name, group_name)['opt'] - logger.log(lvl, "%-30s = %s", - "%s.%s" % (group_name, opt_name), - _sanitize(opt, getattr(group_attr, opt_name))) - - logger.log(lvl, "*" * 80) - - def print_usage(self, file=None): - """Print the usage message for the current program. - - This method is for use after all CLI options are known - registered using __call__() method. If this method is called - before the __call__() is invoked, it throws NotInitializedError - - :param file: the File object (if None, output is on sys.stdout) - :raises: NotInitializedError - """ - if not self._oparser: - raise NotInitializedError() - self._oparser.print_usage(file) - - def print_help(self, file=None): - """Print the help message for the current program. - - This method is for use after all CLI options are known - registered using __call__() method. If this method is called - before the __call__() is invoked, it throws NotInitializedError - - :param file: the File object (if None, output is on sys.stdout) - :raises: NotInitializedError - """ - if not self._oparser: - raise NotInitializedError() - self._oparser.print_help(file) - - def _get(self, name, group=None, namespace=None): - if isinstance(group, OptGroup): - key = (group.name, name) - else: - key = (group, name) - try: - if namespace is not None: - raise KeyError - - return self.__cache[key] - except KeyError: - value = self._do_get(name, group, namespace) - self.__cache[key] = value - return value - - def _do_get(self, name, group=None, namespace=None): - """Look up an option value. - - :param name: the opt name (or 'dest', more precisely) - :param group: an OptGroup - :param namespace: the namespace object that retrieves the option - value from - :returns: the option value, or a GroupAttr object - :raises: NoSuchOptError, NoSuchGroupError, ConfigFileValueError, - TemplateSubstitutionError - """ - if group is None and name in self._groups: - return self.GroupAttr(self, self._get_group(name)) - - info = self._get_opt_info(name, group) - opt = info['opt'] - - if isinstance(opt, SubCommandOpt): - return self.SubCommandAttr(self, group, opt.dest) - - if 'override' in info: - return self._substitute(info['override']) - - if namespace is None: - namespace = self._namespace - - def convert(value): - return self._convert_value( - self._substitute(value, group, namespace), opt) - - if namespace is not None: - group_name = group.name if group else None - try: - return convert(opt._get_from_namespace(namespace, group_name)) - except KeyError: - pass - except ValueError as ve: - raise ConfigFileValueError(str(ve)) - - if 'default' in info: - return self._substitute(info['default']) - - if self._validate_default_values: - if opt.default is not None: - try: - convert(opt.default) - except ValueError as e: - raise ConfigFileValueError( - "Default value for option %s is not valid: %s" - % (opt.name, str(e))) - - if opt.default is not None: - return convert(opt.default) - - return None - - def _substitute(self, value, group=None, namespace=None): - """Perform string template substitution. - - Substitute any template variables (for example $foo, ${bar}) in - the supplied string value(s) with opt values. - - :param value: the string value, or list of string values - :param group: the group that retrieves the option value from - :param namespace: the namespace object that retrieves the option - value from - :returns: the substituted string(s) - """ - if isinstance(value, list): - return [self._substitute(i, group=group, namespace=namespace) - for i in value] - elif isinstance(value, str): - # Treat a backslash followed by the dollar sign "\$" - # the same as the string template escape "$$" as it is - # a bit more natural for users - if '\$' in value: - value = value.replace('\$', '$$') - tmpl = string.Template(value) - ret = tmpl.safe_substitute( - self.StrSubWrapper(self, group=group, namespace=namespace)) - return ret - else: - return value - - def _convert_value(self, value, opt): - """Perform value type conversion. - - Converts values using option's type. Handles cases when value is - actually a list of values (for example for multi opts). - - :param value: the string value, or list of string values - :param opt: option definition (instance of Opt class or its subclasses) - :returns: converted value - """ - if opt.multi: - return [opt.type(v) for v in value] - else: - return opt.type(value) - - def _get_group(self, group_or_name, autocreate=False): - """Looks up a OptGroup object. - - Helper function to return an OptGroup given a parameter which can - either be the group's name or an OptGroup object. - - The OptGroup object returned is from the internal dict of OptGroup - objects, which will be a copy of any OptGroup object that users of - the API have access to. - - If autocreate is True, the group will be created if it's not found. If - group is an instance of OptGroup, that same instance will be - registered, otherwise a new instance of OptGroup will be created. - - :param group_or_name: the group's name or the OptGroup object itself - :param autocreate: whether to auto-create the group if it's not found - :raises: NoSuchGroupError - """ - group = group_or_name if isinstance(group_or_name, OptGroup) else None - group_name = group.name if group else group_or_name - - if group_name not in self._groups: - if not autocreate: - raise NoSuchGroupError(group_name) - - self.register_group(group or OptGroup(name=group_name)) - - return self._groups[group_name] - - def _get_opt_info(self, opt_name, group=None): - """Return the (opt, override, default) dict for an opt. - - :param opt_name: an opt name/dest - :param group: an optional group name or OptGroup object - :raises: NoSuchOptError, NoSuchGroupError - """ - if group is None: - opts = self._opts - else: - group = self._get_group(group) - opts = group._opts - - if opt_name not in opts: - raise NoSuchOptError(opt_name, group) - - return opts[opt_name] - - def _check_required_opts(self, namespace=None): - """Check that all opts marked as required have values specified. - - :param namespace: the namespace object be checked the required options - :raises: RequiredOptError - """ - for info, group in self._all_opt_infos(): - opt = info['opt'] - - if opt.required: - if 'default' in info or 'override' in info: - continue - - if self._get(opt.dest, group, namespace) is None: - raise RequiredOptError(opt.name, group) - - def _parse_cli_opts(self, args): - """Parse command line options. - - Initializes the command line option parser and parses the supplied - command line arguments. - - :param args: the command line arguments - :returns: a _Namespace object containing the parsed option values - :raises: SystemExit, DuplicateOptError - ConfigFileParseError, ConfigFileValueError - - """ - self._args = args - for opt, group in self._all_cli_opts(): - opt._add_to_cli(self._oparser, group) - - return self._parse_config_files() - - def _parse_config_files(self): - """Parse configure files options. - - :raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError, - ConfigFilesPermissionDeniedError, - RequiredOptError, DuplicateOptError - """ - namespace = _Namespace(self) - for arg in self._args: - if arg == '--config-file' or arg.startswith('--config-file='): - break - else: - for config_file in self.default_config_files: - ConfigParser._parse_file(config_file, namespace) - - self._oparser.parse_args(self._args, namespace) - - self._validate_cli_options(namespace) - - return namespace - - def _validate_cli_options(self, namespace): - for opt, group in sorted(self._all_cli_opts(), - key=lambda x: x[0].name): - group_name = group.name if group else None - try: - value = opt._get_from_namespace(namespace, group_name) - except KeyError: - continue - - value = self._substitute(value, group=group, namespace=namespace) - - try: - self._convert_value(value, opt) - except ValueError: - sys.stderr.write("argument --%s: Invalid %s value: %s\n" % ( - opt.dest, repr(opt.type), value)) - raise SystemExit - - @__clear_cache - def reload_config_files(self): - """Reload configure files and parse all options - - :return False if reload configure files failed or else return True - """ - try: - namespace = self._parse_config_files() - if namespace._files_not_found: - raise ConfigFilesNotFoundError(namespace._files_not_found) - if namespace._files_permission_denied: - raise ConfigFilesPermissionDeniedError( - namespace._files_permission_denied) - self._check_required_opts(namespace) - - except SystemExit as exc: - LOG.warn("Caught SystemExit while reloading configure files " - "with exit code: %d", exc.code) - return False - except Error as err: - LOG.warn("Caught Error while reloading configure files: %s", - err) - return False - else: - self._namespace = namespace - return True - - def list_all_sections(self): - """List all sections from the configuration. - - Returns an iterator over all section names found in the - configuration files, whether declared beforehand or not. - """ - for sections in self._namespace._parser.parsed: - for section in sections: - yield section - - class GroupAttr(collections.Mapping): - - """Helper class. - - Represents the option values of a group as a mapping and attributes. - """ - - def __init__(self, conf, group): - """Construct a GroupAttr object. - - :param conf: a ConfigOpts object - :param group: an OptGroup object - """ - self._conf = conf - self._group = group - - def __getattr__(self, name): - """Look up an option value and perform template substitution.""" - return self._conf._get(name, self._group) - - def __getitem__(self, key): - """Look up an option value and perform string substitution.""" - return self.__getattr__(key) - - def __contains__(self, key): - """Return True if key is the name of a registered opt or group.""" - return key in self._group._opts - - def __iter__(self): - """Iterate over all registered opt and group names.""" - for key in self._group._opts.keys(): - yield key - - def __len__(self): - """Return the number of options and option groups.""" - return len(self._group._opts) - - class SubCommandAttr(object): - - """Helper class. - - Represents the name and arguments of an argparse sub-parser. - """ - - def __init__(self, conf, group, dest): - """Construct a SubCommandAttr object. - - :param conf: a ConfigOpts object - :param group: an OptGroup object - :param dest: the name of the sub-parser - """ - self._conf = conf - self._group = group - self._dest = dest - - def __getattr__(self, name): - """Look up a sub-parser name or argument value.""" - if name == 'name': - name = self._dest - if self._group is not None: - name = self._group.name + '_' + name - return getattr(self._conf._namespace, name) - - if name in self._conf: - raise DuplicateOptError(name) - - try: - return getattr(self._conf._namespace, name) - except AttributeError: - raise NoSuchOptError(name) - - class StrSubWrapper(object): - - """Helper class. - - Exposes opt values as a dict for string substitution. - """ - - def __init__(self, conf, group=None, namespace=None): - """Construct a StrSubWrapper object. - - :param conf: a ConfigOpts object - """ - self.conf = conf - self.namespace = namespace - self.group = group - - def __getitem__(self, key): - """Look up an opt value from the ConfigOpts object. - - :param key: an opt name - :returns: an opt value - :raises: TemplateSubstitutionError if attribute is a group - """ - try: - value = self.conf._get(key, group=self.group, - namespace=self.namespace) - except NoSuchOptError: - value = self.conf._get(key, namespace=self.namespace) - if isinstance(value, self.conf.GroupAttr): - raise TemplateSubstitutionError( - 'substituting group %s not supported' % key) - return value - - -CONF = ConfigOpts() diff --git a/awx/lib/site-packages/oslo_config/cfgfilter.py b/awx/lib/site-packages/oslo_config/cfgfilter.py deleted file mode 100644 index 6b1781beb4..0000000000 --- a/awx/lib/site-packages/oslo_config/cfgfilter.py +++ /dev/null @@ -1,367 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -r""" -There are three use cases for the ConfigFilter class: - -1. Help enforce that a given module does not access options registered - by another module, without first declaring those cross-module - dependencies using import_opt(). - -2. Prevent private configuration opts from being visible to modules - other than the one which registered it. - -3. Limit the options on a Cfg object that can be accessed. - -Cross-Module Option Dependencies --------------------------------- - -When using the global cfg.CONF object, it is quite common for a module -to require the existence of configuration options registered by other -modules. - -For example, if module 'foo' registers the 'blaa' option and the module -'bar' uses the 'blaa' option then 'bar' might do:: - - import foo - - print(CONF.blaa) - -However, it's completely non-obvious why foo is being imported (is it -unused, can we remove the import) and where the 'blaa' option comes from. - -The CONF.import_opt() method allows such a dependency to be explicitly -declared:: - - CONF.import_opt('blaa', 'foo') - print(CONF.blaa) - -However, import_opt() has a weakness - if 'bar' imports 'foo' using the -import builtin and doesn't use import_opt() to import 'blaa', then 'blaa' -can still be used without problems. Similarly, where multiple options -are registered a module imported via importopt(), a lazy programmer can -get away with only declaring a dependency on a single option. - -The ConfigFilter class provides a way to ensure that options are not -available unless they have been registered in the module or imported using -import_opt() for example with:: - - CONF = ConfigFilter(cfg.CONF) - CONF.import_opt('blaa', 'foo') - print(CONF.blaa) - -no other options other than 'blaa' are available via CONF. - -Private Configuration Options ------------------------------ - -Libraries which register configuration options typically do not want -users of the library API to access those configuration options. If -API users do access private configuration options, those users will -be disrupted if and when a configuration option is renamed. In other -words, one does not typically wish for the name of the private config -options to be part of the public API. - -The ConfigFilter class provides a way for a library to register -options such that they are not visible via the ConfigOpts instance -which the API user supplies to the library. For example:: - - from __future__ import print_function - - from oslo_config.cfg import * - from oslo_config.cfgfilter import * - - class Widget(object): - - def __init__(self, conf): - self.conf = conf - self._private_conf = ConfigFilter(self.conf) - self._private_conf.register_opt(StrOpt('foo')) - - @property - def foo(self): - return self._private_conf.foo - - conf = ConfigOpts() - widget = Widget(conf) - print(widget.foo) - print(conf.foo) # raises NoSuchOptError - - -Limited Configuration Options ------------------------------ - -It may be required that when passing a CONF object to other functions we want -to filter that the receiving code is only able to access a restricted subset -of the options that are available on the CONF object. This is essentially a -more general case of the Private Configuration Options and Cross-Module Options -whereby we expose an option that is already present on the underlying CONF -object without providing any means to load it if not present. - -So given a CONF object with options defined:: - - CONF.register_opt(StrOpt('foo')) - CONF.register_opt(StrOpt('bar')) - -we can expose options such that only those options are present:: - - restricted_conf = CfgFilter(CONF) - restricted_conf.expose_opt('foo') - - print(restricted_conf.foo) - print(restricted_conf.bar) # raises NoSuchOptError - - -""" - -import collections -import itertools - -from oslo_config import cfg - - -class ConfigFilter(collections.Mapping): - - """A helper class which wraps a ConfigOpts object. - - ConfigFilter enforces the explicit declaration of dependencies on external - options and allows private options which are not registered with the - wrapped Configopts object. - """ - - def __init__(self, conf): - """Construct a ConfigFilter object. - - :param conf: a ConfigOpts object - """ - self._conf = conf - self._fconf = cfg.ConfigOpts() - self._sync() - - self._imported_opts = set() - self._imported_groups = dict() - - def _sync(self): - if self._fconf._namespace is not self._conf._namespace: - self._fconf.clear() - self._fconf._namespace = self._conf._namespace - self._fconf._args = self._conf._args - - def __getattr__(self, name): - """Look up an option value. - - :param name: the opt name (or 'dest', more precisely) - :returns: the option value (after string subsititution) or a GroupAttr - :raises: NoSuchOptError,ConfigFileValueError,TemplateSubstitutionError - """ - if name in self._imported_groups: - return self._imported_groups[name] - elif name in self._imported_opts: - return getattr(self._conf, name) - else: - self._sync() - return getattr(self._fconf, name) - - def __getitem__(self, key): - """Look up an option value.""" - return getattr(self, key) - - def __contains__(self, key): - """Return True if key is the name of a registered opt or group.""" - return (key in self._fconf or - key in self._imported_opts or - key in self._imported_groups) - - def __iter__(self): - """Iterate over all registered opt and group names.""" - return itertools.chain(self._fconf.keys(), - self._imported_opts, - self._imported_groups.keys()) - - def __len__(self): - """Return the number of options and option groups.""" - return (len(self._fconf) + - len(self._imported_opts) + - len(self._imported_groups)) - - @staticmethod - def _already_registered(conf, opt, group=None): - group_name = group.name if isinstance(group, cfg.OptGroup) else group - return ((group_name is None and - opt.dest in conf) or - (group_name is not None and - group_name in conf and - opt.dest in conf[group_name])) - - def register_opt(self, opt, group=None): - """Register an option schema. - - :param opt: an instance of an Opt sub-class - :param group: an optional OptGroup object or group name - :return: False if the opt was already registered, True otherwise - :raises: DuplicateOptError - """ - if self._already_registered(self._conf, opt, group): - # Raises DuplicateError if there is another opt with the same name - ret = self._conf.register_opt(opt, group) - self._import_opt(opt.dest, group) - return ret - else: - return self._fconf.register_opt(opt, group) - - def register_opts(self, opts, group=None): - """Register multiple option schemas at once.""" - for opt in opts: - self.register_opt(opt, group) - - def register_cli_opt(self, opt, group=None): - """Register a CLI option schema. - - :param opt: an instance of an Opt sub-class - :param group: an optional OptGroup object or group name - :return: False if the opt was already register, True otherwise - :raises: DuplicateOptError, ArgsAlreadyParsedError - """ - if self._already_registered(self._conf, opt, group): - # Raises DuplicateError if there is another opt with the same name - ret = self._conf.register_cli_opt(opt, group) - self._import_opt(opt.dest, group) - return ret - else: - return self._fconf.register_cli_opt(opt, group) - - def register_cli_opts(self, opts, group=None): - """Register multiple CLI option schemas at once.""" - for opt in opts: - self.register_cli_opt(opt, group) - - def register_group(self, group): - """Register an option group. - - :param group: an OptGroup object - """ - self._fconf.register_group(group) - - def import_opt(self, opt_name, module_str, group=None): - """Import an option definition from a module. - - :param name: the name/dest of the opt - :param module_str: the name of a module to import - :param group: an option OptGroup object or group name - :raises: NoSuchOptError, NoSuchGroupError - """ - self._conf.import_opt(opt_name, module_str, group) - self._import_opt(opt_name, group) - - def import_group(self, group, module_str): - """Import an option group from a module. - - Note that this allows access to all options registered with - the group whether or not those options were registered by - the given module. - - :param group: an option OptGroup object or group name - :param module_str: the name of a module to import - :raises: ImportError, NoSuchGroupError - """ - self._conf.import_group(group, module_str) - group = self._import_group(group) - group._all_opts = True - - def _import_opt(self, opt_name, group): - if group is None: - self._imported_opts.add(opt_name) - return True - else: - group = self._import_group(group) - return group._import_opt(opt_name) - - def _import_group(self, group_or_name): - if isinstance(group_or_name, cfg.OptGroup): - group_name = group_or_name.name - else: - group_name = group_or_name - - if group_name in self._imported_groups: - return self._imported_groups[group_name] - else: - group = self.GroupAttr(self._conf, group_name) - self._imported_groups[group_name] = group - return group - - def expose_opt(self, opt_name, group=None): - """Expose an option from the underlying conf object. - - This allows an object that has already been imported or used from the - base conf object to be seen from the filter object. - - :param opt_name: the name/dest of the opt - :param group: an option OptGroup object or group name - """ - self._import_opt(opt_name, group) - - def expose_group(self, group): - """Expose all option from a group in the underlying conf object. - - This allows an object that has already been imported or used from the - base conf object to be seen from the filter object. - - :param group: an option OptGroup object or group name - """ - group = self._import_group(group) - group._all_opts = True - - class GroupAttr(collections.Mapping): - - """Helper class to wrap a group object. - - Represents the option values of a group as a mapping and attributes. - """ - - def __init__(self, conf, group): - """Construct a GroupAttr object. - - :param conf: a ConfigOpts object - :param group: an OptGroup object - """ - self._conf = conf - self._group = group - self._imported_opts = set() - self._all_opts = False - - def __getattr__(self, name): - """Look up an option value.""" - if not self._all_opts and name not in self._imported_opts: - raise cfg.NoSuchOptError(name) - return getattr(self._conf[self._group], name) - - def __getitem__(self, key): - """Look up an option value.""" - return getattr(self, key) - - def __contains__(self, key): - """Return True if key is the name of a registered opt or group.""" - return key in self._imported_opts - - def __iter__(self): - """Iterate over all registered opt and group names.""" - for key in self._imported_opts: - yield key - - def __len__(self): - """Return the number of options and option groups.""" - return len(self._imported_opts) - - def _import_opt(self, opt_name): - self._imported_opts.add(opt_name) diff --git a/awx/lib/site-packages/oslo_config/fixture.py b/awx/lib/site-packages/oslo_config/fixture.py deleted file mode 100644 index 02d570d952..0000000000 --- a/awx/lib/site-packages/oslo_config/fixture.py +++ /dev/null @@ -1,118 +0,0 @@ -# -# Copyright 2013 Mirantis, Inc. -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures -import six - -from oslo_config import cfg - - -class Config(fixtures.Fixture): - """Allows overriding configuration settings for the test. - - `conf` will be reset on cleanup. - - """ - - def __init__(self, conf=cfg.CONF): - self.conf = conf - - def setUp(self): - super(Config, self).setUp() - # NOTE(morganfainberg): unregister must be added to cleanup before - # reset is because cleanup works in reverse order of registered items, - # and a reset must occur before unregistering options can occur. - self.addCleanup(self._unregister_config_opts) - self.addCleanup(self.conf.reset) - self._registered_config_opts = {} - - def config(self, **kw): - """Override configuration values. - - The keyword arguments are the names of configuration options to - override and their values. - - If a `group` argument is supplied, the overrides are applied to - the specified configuration option group, otherwise the overrides - are applied to the ``default`` group. - - """ - - group = kw.pop('group', None) - for k, v in six.iteritems(kw): - self.conf.set_override(k, v, group) - - def _unregister_config_opts(self): - for group in self._registered_config_opts: - self.conf.unregister_opts(self._registered_config_opts[group], - group=group) - - def register_opt(self, opt, group=None): - """Register a single option for the test run. - - Options registered in this manner will automatically be unregistered - during cleanup. - - If a `group` argument is supplied, it will register the new option - to that group, otherwise the option is registered to the ``default`` - group. - """ - self.conf.register_opt(opt, group=group) - self._registered_config_opts.setdefault(group, set()).add(opt) - - def register_opts(self, opts, group=None): - """Register multiple options for the test run. - - This works in the same manner as register_opt() but takes a list of - options as the first argument. All arguments will be registered to the - same group if the ``group`` argument is supplied, otherwise all options - will be registered to the ``default`` group. - """ - for opt in opts: - self.register_opt(opt, group=group) - - def register_cli_opt(self, opt, group=None): - """Register a single CLI option for the test run. - - Options registered in this manner will automatically be unregistered - during cleanup. - - If a `group` argument is supplied, it will register the new option - to that group, otherwise the option is registered to the ``default`` - group. - - CLI options must be registered before the command line and config files - are parsed. This is to ensure that all CLI options are shown in --help - and option validation works as expected. - """ - self.conf.register_cli_opt(opt, group=group) - self._registered_config_opts.setdefault(group, set()).add(opt) - - def register_cli_opts(self, opts, group=None): - """Register multiple CLI options for the test run. - - This works in the same manner as register_opt() but takes a list of - options as the first argument. All arguments will be registered to the - same group if the ``group`` argument is supplied, otherwise all options - will be registered to the ``default`` group. - - CLI options must be registered before the command line and config files - are parsed. This is to ensure that all CLI options are shown in --help - and option validation works as expected. - """ - for opt in opts: - self.register_cli_opt(opt, group=group) diff --git a/awx/lib/site-packages/oslo_config/generator.py b/awx/lib/site-packages/oslo_config/generator.py deleted file mode 100644 index 182054870f..0000000000 --- a/awx/lib/site-packages/oslo_config/generator.py +++ /dev/null @@ -1,336 +0,0 @@ -# Copyright 2012 SINA Corporation -# Copyright 2014 Cisco Systems, Inc. -# All Rights Reserved. -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -r""" -A sample configuration file generator. - -oslo-config-generator is a utility for generating sample config files. For -example, to generate a sample config file for oslo.messaging you would run:: - - $> oslo-config-generator --namespace oslo.messaging > oslo.messaging.conf - -This generated sample lists all of the available options, along with their help -string, type, deprecated aliases and defaults. - -The --namespace option specifies an entry point name registered under the -'oslo.config.opts' entry point namespace. For example, in oslo.messaging's -setup.cfg we have:: - - [entry_points] - oslo.config.opts = - oslo.messaging = oslo.messaging.opts:list_opts - -The callable referenced by the entry point should take no arguments and return -a list of (group_name, [opt_1, opt_2]) tuples. For example:: - - opts = [ - cfg.StrOpt('foo'), - cfg.StrOpt('bar'), - ] - - cfg.CONF.register_opts(opts, group='blaa') - - def list_opts(): - return [('blaa', opts)] - -You might choose to return a copy of the options so that the return value can't -be modified for nefarious purposes:: - - def list_opts(): - return [('blaa', copy.deepcopy(opts))] - -A single codebase might have multiple programs, each of which use a subset of -the total set of options registered by the codebase. In that case, you can -register multiple entry points:: - - [entry_points] - oslo.config.opts = - nova.common = nova.config:list_common_opts - nova.api = nova.config:list_api_opts - nova.compute = nova.config:list_compute_opts - -and generate a config file specific to each program:: - - $> oslo-config-generator --namespace oslo.messaging \ - --namespace nova.common \ - --namespace nova.api > nova-api.conf - $> oslo-config-generator --namespace oslo.messaging \ - --namespace nova.common \ - --namespace nova.compute > nova-compute.conf - -To make this more convenient, you can use config files to describe your config -files:: - - $> cat > config-generator/api.conf < cat > config-generator/compute.conf < oslo-config-generator --config-file config-generator/api.conf - $> oslo-config-generator --config-file config-generator/compute.conf - -The default runtime values of configuration options are not always the most -suitable values to include in sample config files - for example, rather than -including the IP address or hostname of the machine where the config file -was generated, you might want to include something like '10.0.0.1'. To -facilitate this, options can be supplied with a 'sample_default' attribute:: - - cfg.StrOpt('base_dir' - default=os.getcwd(), - sample_default='/usr/lib/myapp') -""" - -import logging -import operator -import sys -import textwrap - -import pkg_resources -import six - -from oslo_config import cfg -import stevedore.named # noqa - -LOG = logging.getLogger(__name__) - -_generator_opts = [ - cfg.StrOpt('output-file', - help='Path of the file to write to. Defaults to stdout.'), - cfg.IntOpt('wrap-width', - default=70, - help='The maximum length of help lines.'), - cfg.MultiStrOpt('namespace', - help='Option namespace under "oslo.config.opts" in which ' - 'to query for options.'), -] - - -def register_cli_opts(conf): - """Register the formatter's CLI options with a ConfigOpts instance. - - Note, this must be done before the ConfigOpts instance is called to parse - the configuration. - - :param conf: a ConfigOpts instance - :raises: DuplicateOptError, ArgsAlreadyParsedError - """ - conf.register_cli_opts(_generator_opts) - - -class _OptFormatter(object): - - """Format configuration option descriptions to a file.""" - - _TYPE_DESCRIPTIONS = { - cfg.StrOpt: 'string value', - cfg.BoolOpt: 'boolean value', - cfg.IntOpt: 'integer value', - cfg.FloatOpt: 'floating point value', - cfg.ListOpt: 'list value', - cfg.DictOpt: 'dict value', - cfg.MultiStrOpt: 'multi valued', - } - - def __init__(self, output_file=None, wrap_width=70): - """Construct an OptFormatter object. - - :param output_file: a writeable file object - :param wrap_width: The maximum length of help lines, 0 to not wrap - """ - self.output_file = output_file or sys.stdout - self.wrap_width = wrap_width - - def _format_help(self, help_text): - """Format the help for a group or option to the output file. - - :param help_text: The text of the help string - """ - if self.wrap_width is not None and self.wrap_width > 0: - lines = [textwrap.fill(help_text, - self.wrap_width, - initial_indent='# ', - subsequent_indent='# ') + '\n'] - else: - lines = ['# ' + help_text + '\n'] - return lines - - def _get_choice_text(self, choice): - if choice is None: - return '' - elif choice == '': - return "''" - return six.text_type(choice) - - def format(self, opt): - """Format a description of an option to the output file. - - :param opt: a cfg.Opt instance - """ - if not opt.help: - LOG.warning('"%s" is missing a help string', opt.dest) - - opt_type = self._TYPE_DESCRIPTIONS.get(type(opt), 'unknown type') - - if opt.help: - help_text = u'%s (%s)' % (opt.help, - opt_type) - else: - help_text = u'(%s)' % opt_type - lines = self._format_help(help_text) - - if getattr(opt.type, 'choices', None): - choices_text = ', '.join([self._get_choice_text(choice) - for choice in opt.type.choices]) - lines.append('# Allowed values: %s\n' % choices_text) - - for d in opt.deprecated_opts: - lines.append('# Deprecated group/name - [%s]/%s\n' % - (d.group or 'DEFAULT', d.name or opt.dest)) - - if isinstance(opt, cfg.MultiStrOpt): - if opt.sample_default is not None: - defaults = opt.sample_default - elif not opt.default: - defaults = [''] - else: - defaults = opt.default - else: - if opt.sample_default is not None: - default_str = str(opt.sample_default) - elif opt.default is None: - default_str = '' - elif isinstance(opt, cfg.StrOpt): - default_str = opt.default - elif isinstance(opt, cfg.BoolOpt): - default_str = str(opt.default).lower() - elif (isinstance(opt, cfg.IntOpt) or - isinstance(opt, cfg.FloatOpt)): - default_str = str(opt.default) - elif isinstance(opt, cfg.ListOpt): - default_str = ','.join(opt.default) - elif isinstance(opt, cfg.DictOpt): - sorted_items = sorted(opt.default.items(), - key=operator.itemgetter(0)) - default_str = ','.join(['%s:%s' % i for i in sorted_items]) - else: - LOG.warning('Unknown option type: %s', repr(opt)) - default_str = str(opt.default) - defaults = [default_str] - - for default_str in defaults: - if default_str.strip() != default_str: - default_str = '"%s"' % default_str - if default_str: - default_str = ' ' + default_str - lines.append('#%s =%s\n' % (opt.dest, default_str)) - - self.writelines(lines) - - def write(self, s): - """Write an arbitrary string to the output file. - - :param s: an arbitrary string - """ - self.output_file.write(s) - - def writelines(self, l): - """Write an arbitrary sequence of strings to the output file. - - :param l: a list of arbitrary strings - """ - self.output_file.writelines(l) - - -def _list_opts(namespaces): - """List the options available via the given namespaces. - - :param namespaces: a list of namespaces registered under 'oslo.config.opts' - :returns: a list of (namespace, [(group, [opt_1, opt_2])]) tuples - """ - mgr = stevedore.named.NamedExtensionManager( - 'oslo.config.opts', - names=namespaces, - on_load_failure_callback=on_load_failure_callback, - invoke_on_load=True) - return [(ep.name, ep.obj) for ep in mgr] - - -def on_load_failure_callback(*args, **kwargs): - raise - - -def generate(conf): - """Generate a sample config file. - - List all of the options available via the namespaces specified in the given - configuration and write a description of them to the specified output file. - - :param conf: a ConfigOpts instance containing the generator's configuration - """ - conf.register_opts(_generator_opts) - - output_file = (open(conf.output_file, 'w') - if conf.output_file else sys.stdout) - - formatter = _OptFormatter(output_file=output_file, - wrap_width=conf.wrap_width) - - groups = {'DEFAULT': []} - for namespace, listing in _list_opts(conf.namespace): - for group, opts in listing: - if not opts: - continue - namespaces = groups.setdefault(group or 'DEFAULT', []) - namespaces.append((namespace, opts)) - - def _output_opts(f, group, namespaces): - f.write('[%s]\n' % group) - for (namespace, opts) in sorted(namespaces, - key=operator.itemgetter(0)): - f.write('\n#\n# From %s\n#\n' % namespace) - for opt in opts: - f.write('\n') - f.format(opt) - - _output_opts(formatter, 'DEFAULT', groups.pop('DEFAULT')) - for group, namespaces in sorted(groups.items(), - key=operator.itemgetter(0)): - formatter.write('\n\n') - _output_opts(formatter, group, namespaces) - - -def main(args=None): - """The main function of oslo-config-generator.""" - version = pkg_resources.get_distribution('oslo.config').version - logging.basicConfig(level=logging.WARN) - conf = cfg.ConfigOpts() - register_cli_opts(conf) - conf(args, version=version) - generate(conf) - - -if __name__ == '__main__': - main() diff --git a/awx/lib/site-packages/oslo_config/iniparser.py b/awx/lib/site-packages/oslo_config/iniparser.py deleted file mode 100644 index 90218e454b..0000000000 --- a/awx/lib/site-packages/oslo_config/iniparser.py +++ /dev/null @@ -1,127 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class ParseError(Exception): - def __init__(self, message, lineno, line): - self.msg = message - self.line = line - self.lineno = lineno - - def __str__(self): - return 'at line %d, %s: %r' % (self.lineno, self.msg, self.line) - - -class BaseParser(object): - lineno = 0 - parse_exc = ParseError - - def _assignment(self, key, value): - self.assignment(key, value) - return None, [] - - def _get_section(self, line): - if not line.endswith(']'): - return self.error_no_section_end_bracket(line) - if len(line) <= 2: - return self.error_no_section_name(line) - - return line[1:-1] - - def _split_key_value(self, line): - colon = line.find(':') - equal = line.find('=') - if colon < 0 and equal < 0: - return self.error_invalid_assignment(line) - - if colon < 0 or (equal >= 0 and equal < colon): - key, value = line[:equal], line[equal + 1:] - else: - key, value = line[:colon], line[colon + 1:] - - value = value.strip() - if value and value[0] == value[-1] and value.startswith(("\"", "'")): - value = value[1:-1] - return key.strip(), [value] - - def parse(self, lineiter): - key = None - value = [] - - for line in lineiter: - self.lineno += 1 - - line = line.rstrip() - if not line: - # Blank line, ends multi-line values - if key: - key, value = self._assignment(key, value) - continue - elif line.startswith((' ', '\t')): - # Continuation of previous assignment - if key is None: - self.error_unexpected_continuation(line) - else: - value.append(line.lstrip()) - continue - - if key: - # Flush previous assignment, if any - key, value = self._assignment(key, value) - - if line.startswith('['): - # Section start - section = self._get_section(line) - if section: - self.new_section(section) - elif line.startswith(('#', ';')): - self.comment(line[1:].lstrip()) - else: - key, value = self._split_key_value(line) - if not key: - return self.error_empty_key(line) - - if key: - # Flush previous assignment, if any - self._assignment(key, value) - - def assignment(self, key, value): - """Called when a full assignment is parsed.""" - raise NotImplementedError() - - def new_section(self, section): - """Called when a new section is started.""" - raise NotImplementedError() - - def comment(self, comment): - """Called when a comment is parsed.""" - pass - - def error_invalid_assignment(self, line): - raise self.parse_exc("No ':' or '=' found in assignment", - self.lineno, line) - - def error_empty_key(self, line): - raise self.parse_exc('Key cannot be empty', self.lineno, line) - - def error_unexpected_continuation(self, line): - raise self.parse_exc('Unexpected continuation line', - self.lineno, line) - - def error_no_section_end_bracket(self, line): - raise self.parse_exc('Invalid section (must end with ])', - self.lineno, line) - - def error_no_section_name(self, line): - raise self.parse_exc('Empty section name', self.lineno, line) diff --git a/awx/lib/site-packages/oslo_config/tests/__init__.py b/awx/lib/site-packages/oslo_config/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/oslo_config/tests/test_cfg.py b/awx/lib/site-packages/oslo_config/tests/test_cfg.py deleted file mode 100644 index 5518f53842..0000000000 --- a/awx/lib/site-packages/oslo_config/tests/test_cfg.py +++ /dev/null @@ -1,3726 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import errno -import functools -import os -import shutil -import sys -import tempfile - -import fixtures -import mock -from oslotest import base -import six -from six import moves -import testscenarios - -from oslo_config import cfg -from oslo_config import types - -load_tests = testscenarios.load_tests_apply_scenarios - - -class ExceptionsTestCase(base.BaseTestCase): - - def test_error(self): - msg = str(cfg.Error('foobar')) - self.assertEqual(msg, 'foobar') - - def test_args_already_parsed_error(self): - msg = str(cfg.ArgsAlreadyParsedError('foobar')) - self.assertEqual(msg, 'arguments already parsed: foobar') - - def test_no_such_opt_error(self): - msg = str(cfg.NoSuchOptError('foo')) - self.assertEqual(msg, 'no such option: foo') - - def test_no_such_opt_error_with_group(self): - msg = str(cfg.NoSuchOptError('foo', cfg.OptGroup('bar'))) - self.assertEqual(msg, 'no such option in group bar: foo') - - def test_no_such_group_error(self): - msg = str(cfg.NoSuchGroupError('bar')) - self.assertEqual(msg, 'no such group: bar') - - def test_duplicate_opt_error(self): - msg = str(cfg.DuplicateOptError('foo')) - self.assertEqual(msg, 'duplicate option: foo') - - def test_required_opt_error(self): - msg = str(cfg.RequiredOptError('foo')) - self.assertEqual(msg, 'value required for option: foo') - - def test_required_opt_error_with_group(self): - msg = str(cfg.RequiredOptError('foo', cfg.OptGroup('bar'))) - self.assertEqual(msg, 'value required for option: bar.foo') - - def test_template_substitution_error(self): - msg = str(cfg.TemplateSubstitutionError('foobar')) - self.assertEqual(msg, 'template substitution error: foobar') - - def test_config_files_not_found_error(self): - msg = str(cfg.ConfigFilesNotFoundError(['foo', 'bar'])) - self.assertEqual(msg, 'Failed to find some config files: foo,bar') - - def test_config_files_permission_denied_error(self): - msg = str(cfg.ConfigFilesPermissionDeniedError(['foo', 'bar'])) - self.assertEqual(msg, 'Failed to open some config files: foo,bar') - - def test_config_dir_not_found_error(self): - msg = str(cfg.ConfigDirNotFoundError('foobar')) - self.assertEqual(msg, 'Failed to read config file directory: foobar') - - def test_config_file_parse_error(self): - msg = str(cfg.ConfigFileParseError('foo', 'foobar')) - self.assertEqual(msg, 'Failed to parse foo: foobar') - - -class BaseTestCase(base.BaseTestCase): - - class TestConfigOpts(cfg.ConfigOpts): - def __call__(self, args=None, default_config_files=[]): - return cfg.ConfigOpts.__call__( - self, - args=args, - prog='test', - version='1.0', - usage='%(prog)s FOO BAR', - default_config_files=default_config_files, - validate_default_values=True) - - def setUp(self): - super(BaseTestCase, self).setUp() - self.useFixture(fixtures.NestedTempfile()) - self.conf = self.TestConfigOpts() - - self.tempdirs = [] - - def create_tempfiles(self, files, ext='.conf'): - tempfiles = [] - for (basename, contents) in files: - if not os.path.isabs(basename): - (fd, path) = tempfile.mkstemp(prefix=basename, suffix=ext) - else: - path = basename + ext - fd = os.open(path, os.O_CREAT | os.O_WRONLY) - tempfiles.append(path) - try: - os.write(fd, contents.encode('utf-8')) - finally: - os.close(fd) - return tempfiles - - -class UsageTestCase(BaseTestCase): - - def test_print_usage(self): - f = moves.StringIO() - self.conf([]) - self.conf.print_usage(file=f) - self.assertTrue('usage: test FOO BAR' in f.getvalue()) - self.assertTrue('optional:' not in f.getvalue()) - - -class HelpTestCase(BaseTestCase): - - def test_print_help(self): - f = moves.StringIO() - self.conf([]) - self.conf.print_help(file=f) - self.assertTrue('usage: test FOO BAR' in f.getvalue()) - self.assertTrue('optional' in f.getvalue()) - self.assertTrue('-h, --help' in f.getvalue()) - - def test_print_sorted_help(self): - f = moves.StringIO() - self.conf.register_cli_opt(cfg.StrOpt('zba')) - self.conf.register_cli_opt(cfg.StrOpt('abc')) - self.conf.register_cli_opt(cfg.StrOpt('ghi')) - self.conf.register_cli_opt(cfg.StrOpt('deb')) - self.conf([]) - self.conf.print_help(file=f) - zba = f.getvalue().find('--zba') - abc = f.getvalue().find('--abc') - ghi = f.getvalue().find('--ghi') - deb = f.getvalue().find('--deb') - list = [abc, deb, ghi, zba] - self.assertEqual(sorted(list), list) - - -class FindConfigFilesTestCase(BaseTestCase): - - def test_find_config_files(self): - config_files = [os.path.expanduser('~/.blaa/blaa.conf'), - '/etc/foo.conf'] - - self.useFixture(fixtures.MonkeyPatch('sys.argv', ['foo'])) - self.useFixture(fixtures.MonkeyPatch('os.path.exists', - lambda p: p in config_files)) - - self.assertEqual(cfg.find_config_files(project='blaa'), config_files) - - def test_find_config_files_with_extension(self): - config_files = ['/etc/foo.json'] - - self.useFixture(fixtures.MonkeyPatch('sys.argv', ['foo'])) - self.useFixture(fixtures.MonkeyPatch('os.path.exists', - lambda p: p in config_files)) - - self.assertEqual(cfg.find_config_files(project='blaa'), []) - self.assertEqual(cfg.find_config_files(project='blaa', - extension='.json'), - config_files) - - -class DefaultConfigFilesTestCase(BaseTestCase): - - def test_use_default(self): - self.conf.register_opt(cfg.StrOpt('foo')) - paths = self.create_tempfiles([('foo-', '[DEFAULT]\n''foo = bar\n')]) - - self.conf.register_cli_opt(cfg.StrOpt('config-file-foo')) - self.conf(args=['--config-file-foo', 'foo.conf'], - default_config_files=[paths[0]]) - - self.assertEqual(self.conf.config_file, [paths[0]]) - self.assertEqual(self.conf.foo, 'bar') - - def test_do_not_use_default_multi_arg(self): - self.conf.register_opt(cfg.StrOpt('foo')) - paths = self.create_tempfiles([('foo-', '[DEFAULT]\n''foo = bar\n')]) - - self.conf(args=['--config-file', paths[0]], - default_config_files=['bar.conf']) - - self.assertEqual(self.conf.config_file, [paths[0]]) - self.assertEqual(self.conf.foo, 'bar') - - def test_do_not_use_default_single_arg(self): - self.conf.register_opt(cfg.StrOpt('foo')) - paths = self.create_tempfiles([('foo-', '[DEFAULT]\n''foo = bar\n')]) - - self.conf(args=['--config-file=' + paths[0]], - default_config_files=['bar.conf']) - - self.assertEqual(self.conf.config_file, [paths[0]]) - self.assertEqual(self.conf.foo, 'bar') - - def test_no_default_config_file(self): - self.conf(args=[]) - self.assertEqual(self.conf.config_file, []) - - def test_find_default_config_file(self): - paths = self.create_tempfiles([('def', '[DEFAULT]')]) - - self.useFixture(fixtures.MonkeyPatch( - 'oslo_config.cfg.find_config_files', - lambda project, prog: paths)) - - self.conf(args=[], default_config_files=None) - self.assertEqual(self.conf.config_file, paths) - - def test_default_config_file(self): - paths = self.create_tempfiles([('def', '[DEFAULT]')]) - - self.conf(args=[], default_config_files=paths) - - self.assertEqual(self.conf.config_file, paths) - - def test_default_config_file_with_value(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - - paths = self.create_tempfiles([('def', '[DEFAULT]\n''foo = bar\n')]) - - self.conf(args=[], default_config_files=paths) - - self.assertEqual(self.conf.config_file, paths) - self.assertEqual(self.conf.foo, 'bar') - - def test_default_config_file_priority(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - - paths = self.create_tempfiles([('def', '[DEFAULT]\n''foo = bar\n')]) - - self.conf(args=['--foo=blaa'], default_config_files=paths) - - self.assertEqual(self.conf.config_file, paths) - self.assertEqual(self.conf.foo, 'blaa') - - -class CliOptsTestCase(BaseTestCase): - """Test CLI Options. - - Each test scenario takes a name for the scenarios, as well as a dict: - opt_class - class of the type of option that should be tested - default - a default value for the option - cli_args - a list containing a representation of an input command line - value - the result value that is expected to be found - deps - a tuple of deprecated name/group - """ - - IPv4Opt = functools.partial(cfg.IPOpt, version=4) - IPv6Opt = functools.partial(cfg.IPOpt, version=6) - - multi_int = functools.partial(cfg.MultiOpt, item_type=types.Integer()) - multi_float = functools.partial(cfg.MultiOpt, item_type=types.Float()) - multi_string = functools.partial(cfg.MultiOpt, item_type=types.String()) - - scenarios = [ - ('str_default', - dict(opt_class=cfg.StrOpt, default=None, cli_args=[], value=None, - deps=(None, None))), - ('str_arg', - dict(opt_class=cfg.StrOpt, default=None, cli_args=['--foo', 'bar'], - value='bar', deps=(None, None))), - ('str_arg_deprecated_name', - dict(opt_class=cfg.StrOpt, default=None, - cli_args=['--oldfoo', 'bar'], value='bar', - deps=('oldfoo', None))), - ('str_arg_deprecated_group', - dict(opt_class=cfg.StrOpt, default=None, - cli_args=['--old-foo', 'bar'], value='bar', - deps=(None, 'old'))), - ('str_arg_deprecated_group_default', - dict(opt_class=cfg.StrOpt, default=None, cli_args=['--foo', 'bar'], - value='bar', deps=(None, 'DEFAULT'))), - ('str_arg_deprecated_group_and_name', - dict(opt_class=cfg.StrOpt, default=None, - cli_args=['--old-oof', 'bar'], value='bar', - deps=('oof', 'old'))), - ('bool_default', - dict(opt_class=cfg.BoolOpt, default=False, - cli_args=[], value=False, deps=(None, None))), - ('bool_arg', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--foo'], value=True, deps=(None, None))), - ('bool_arg_deprecated_name', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--oldfoo'], value=True, - deps=('oldfoo', None))), - ('bool_arg_deprecated_group', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--old-foo'], value=True, - deps=(None, 'old'))), - ('bool_arg_deprecated_group_default', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--foo'], value=True, - deps=(None, 'DEFAULT'))), - ('bool_arg_deprecated_group_and_name', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--old-oof'], value=True, - deps=('oof', 'old'))), - ('bool_arg_inverse', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--foo', '--nofoo'], value=False, deps=(None, None))), - ('bool_arg_inverse_deprecated_name', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--oldfoo', '--nooldfoo'], value=False, - deps=('oldfoo', None))), - ('bool_arg_inverse_deprecated_group', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--old-foo', '--old-nofoo'], value=False, - deps=(None, 'old'))), - ('bool_arg_inverse_deprecated_group_default', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--foo', '--nofoo'], value=False, - deps=(None, 'DEFAULT'))), - ('bool_arg_inverse_deprecated_group_and_name', - dict(opt_class=cfg.BoolOpt, default=None, - cli_args=['--old-oof', '--old-nooof'], value=False, - deps=('oof', 'old'))), - ('int_default', - dict(opt_class=cfg.IntOpt, default=10, - cli_args=[], value=10, deps=(None, None))), - ('int_arg', - dict(opt_class=cfg.IntOpt, default=None, - cli_args=['--foo=20'], value=20, deps=(None, None))), - ('int_arg_deprecated_name', - dict(opt_class=cfg.IntOpt, default=None, - cli_args=['--oldfoo=20'], value=20, deps=('oldfoo', None))), - ('int_arg_deprecated_group', - dict(opt_class=cfg.IntOpt, default=None, - cli_args=['--old-foo=20'], value=20, deps=(None, 'old'))), - ('int_arg_deprecated_group_default', - dict(opt_class=cfg.IntOpt, default=None, - cli_args=['--foo=20'], value=20, deps=(None, 'DEFAULT'))), - ('int_arg_deprecated_group_and_name', - dict(opt_class=cfg.IntOpt, default=None, - cli_args=['--old-oof=20'], value=20, deps=('oof', 'old'))), - ('float_default', - dict(opt_class=cfg.FloatOpt, default=1.0, - cli_args=[], value=1.0, deps=(None, None))), - ('float_arg', - dict(opt_class=cfg.FloatOpt, default=None, - cli_args=['--foo', '2.0'], value=2.0, deps=(None, None))), - ('float_arg_deprecated_name', - dict(opt_class=cfg.FloatOpt, default=None, - cli_args=['--oldfoo', '2.0'], value=2.0, deps=('oldfoo', None))), - ('float_arg_deprecated_group', - dict(opt_class=cfg.FloatOpt, default=None, - cli_args=['--old-foo', '2.0'], value=2.0, deps=(None, 'old'))), - ('float_arg_deprecated_group_default', - dict(opt_class=cfg.FloatOpt, default=None, - cli_args=['--foo', '2.0'], value=2.0, deps=(None, 'DEFAULT'))), - ('float_arg_deprecated_group_and_name', - dict(opt_class=cfg.FloatOpt, default=None, - cli_args=['--old-oof', '2.0'], value=2.0, deps=('oof', 'old'))), - ('float_default_as_integer', - dict(opt_class=cfg.FloatOpt, default=2, - cli_args=['--old-oof', '2.0'], value=2.0, deps=('oof', 'old'))), - ('ipv4addr_arg', - dict(opt_class=IPv4Opt, default=None, - cli_args=['--foo', '192.168.0.1'], value='192.168.0.1', - deps=(None, None))), - ('ipaddr_arg_implicitv4', - dict(opt_class=cfg.IPOpt, default=None, - cli_args=['--foo', '192.168.0.1'], value='192.168.0.1', - deps=(None, None))), - ('ipaddr_arg_implicitv6', - dict(opt_class=cfg.IPOpt, default=None, - cli_args=['--foo', 'abcd:ef::1'], value='abcd:ef::1', - deps=(None, None))), - ('ipv6addr_arg', - dict(opt_class=IPv6Opt, default=None, - cli_args=['--foo', 'abcd:ef::1'], value='abcd:ef::1', - deps=(None, None))), - ('list_default', - dict(opt_class=cfg.ListOpt, default=['bar'], - cli_args=[], value=['bar'], deps=(None, None))), - ('list_arg', - dict(opt_class=cfg.ListOpt, default=None, - cli_args=['--foo', 'blaa,bar'], value=['blaa', 'bar'], - deps=(None, None))), - ('list_arg_with_spaces', - dict(opt_class=cfg.ListOpt, default=None, - cli_args=['--foo', 'blaa ,bar'], value=['blaa', 'bar'], - deps=(None, None))), - ('list_arg_deprecated_name', - dict(opt_class=cfg.ListOpt, default=None, - cli_args=['--oldfoo', 'blaa,bar'], value=['blaa', 'bar'], - deps=('oldfoo', None))), - ('list_arg_deprecated_group', - dict(opt_class=cfg.ListOpt, default=None, - cli_args=['--old-foo', 'blaa,bar'], value=['blaa', 'bar'], - deps=(None, 'old'))), - ('list_arg_deprecated_group_default', - dict(opt_class=cfg.ListOpt, default=None, - cli_args=['--foo', 'blaa,bar'], value=['blaa', 'bar'], - deps=(None, 'DEFAULT'))), - ('list_arg_deprecated_group_and_name', - dict(opt_class=cfg.ListOpt, default=None, - cli_args=['--old-oof', 'blaa,bar'], value=['blaa', 'bar'], - deps=('oof', 'old'))), - ('dict_default', - dict(opt_class=cfg.DictOpt, default={'foo': 'bar'}, - cli_args=[], value={'foo': 'bar'}, deps=(None, None))), - ('dict_arg', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--foo', 'key1:blaa,key2:bar'], - value={'key1': 'blaa', 'key2': 'bar'}, deps=(None, None))), - ('dict_arg_multiple_keys_last_wins', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--foo', 'key1:blaa', '--foo', 'key2:bar'], - value={'key2': 'bar'}, deps=(None, None))), - ('dict_arg_with_spaces', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--foo', 'key1:blaa ,key2:bar'], - value={'key1': 'blaa', 'key2': 'bar'}, deps=(None, None))), - ('dict_arg_deprecated_name', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--oldfoo', 'key1:blaa', '--oldfoo', 'key2:bar'], - value={'key2': 'bar'}, deps=('oldfoo', None))), - ('dict_arg_deprecated_group', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--old-foo', 'key1:blaa,key2:bar'], - value={'key1': 'blaa', 'key2': 'bar'}, deps=(None, 'old'))), - ('dict_arg_deprecated_group2', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--old-foo', 'key1:blaa', '--old-foo', 'key2:bar'], - value={'key2': 'bar'}, deps=(None, 'old'))), - ('dict_arg_deprecated_group_default', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--foo', 'key1:blaa', '--foo', 'key2:bar'], - value={'key2': 'bar'}, deps=(None, 'DEFAULT'))), - ('dict_arg_deprecated_group_and_name', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--old-oof', 'key1:blaa,key2:bar'], - value={'key1': 'blaa', 'key2': 'bar'}, deps=('oof', 'old'))), - ('dict_arg_deprecated_group_and_name2', - dict(opt_class=cfg.DictOpt, default=None, - cli_args=['--old-oof', 'key1:blaa', '--old-oof', 'key2:bar'], - value={'key2': 'bar'}, deps=('oof', 'old'))), - ('multistr_default', - dict(opt_class=cfg.MultiStrOpt, default=['bar'], cli_args=[], - value=['bar'], deps=(None, None))), - ('multistr_arg', - dict(opt_class=cfg.MultiStrOpt, default=None, - cli_args=['--foo', 'blaa', '--foo', 'bar'], - value=['blaa', 'bar'], deps=(None, None))), - ('multistr_arg_deprecated_name', - dict(opt_class=cfg.MultiStrOpt, default=None, - cli_args=['--oldfoo', 'blaa', '--oldfoo', 'bar'], - value=['blaa', 'bar'], deps=('oldfoo', None))), - ('multistr_arg_deprecated_group', - dict(opt_class=cfg.MultiStrOpt, default=None, - cli_args=['--old-foo', 'blaa', '--old-foo', 'bar'], - value=['blaa', 'bar'], deps=(None, 'old'))), - ('multistr_arg_deprecated_group_default', - dict(opt_class=cfg.MultiStrOpt, default=None, - cli_args=['--foo', 'blaa', '--foo', 'bar'], - value=['blaa', 'bar'], deps=(None, 'DEFAULT'))), - ('multistr_arg_deprecated_group_and_name', - dict(opt_class=cfg.MultiStrOpt, default=None, - cli_args=['--old-oof', 'blaa', '--old-oof', 'bar'], - value=['blaa', 'bar'], deps=('oof', 'old'))), - ('multiopt_arg_int', - dict(opt_class=multi_int, default=None, - cli_args=['--foo', '1', '--foo', '2'], - value=[1, 2], deps=(None, None))), - ('multiopt_float_int', - dict(opt_class=multi_float, default=None, - cli_args=['--foo', '1.2', '--foo', '2.3'], - value=[1.2, 2.3], deps=(None, None))), - ('multiopt_string', - dict(opt_class=multi_string, default=None, - cli_args=['--foo', 'bar', '--foo', 'baz'], - value=["bar", "baz"], deps=(None, None))), - ] - - def test_cli(self): - - self.conf.register_cli_opt( - self.opt_class('foo', default=self.default, - deprecated_name=self.deps[0], - deprecated_group=self.deps[1])) - - self.conf(self.cli_args) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, self.value) - - -class CliSpecialOptsTestCase(BaseTestCase): - - def test_help(self): - self.useFixture(fixtures.MonkeyPatch('sys.stdout', moves.StringIO())) - self.assertRaises(SystemExit, self.conf, ['--help']) - self.assertTrue('FOO BAR' in sys.stdout.getvalue()) - self.assertTrue('--version' in sys.stdout.getvalue()) - self.assertTrue('--help' in sys.stdout.getvalue()) - self.assertTrue('--config-file' in sys.stdout.getvalue()) - - def test_version(self): - # In Python 3.4+, argparse prints the version on stdout; before 3.4, it - # printed it on stderr. - if sys.version_info >= (3, 4): - stream_name = 'stdout' - else: - stream_name = 'stderr' - self.useFixture(fixtures.MonkeyPatch("sys.%s" % stream_name, - moves.StringIO())) - self.assertRaises(SystemExit, self.conf, ['--version']) - self.assertTrue('1.0' in getattr(sys, stream_name).getvalue()) - - def test_config_file(self): - paths = self.create_tempfiles([('1', '[DEFAULT]'), - ('2', '[DEFAULT]')]) - - self.conf(['--config-file', paths[0], '--config-file', paths[1]]) - - self.assertEqual(self.conf.config_file, paths) - - -class PositionalTestCase(BaseTestCase): - - def _do_pos_test(self, opt_class, default, cli_args, value): - self.conf.register_cli_opt(opt_class('foo', - default=default, - positional=True)) - - self.conf(cli_args) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, value) - - def test_positional_str_none_default(self): - self._do_pos_test(cfg.StrOpt, None, [], None) - - def test_positional_str_default(self): - self._do_pos_test(cfg.StrOpt, 'bar', [], 'bar') - - def test_positional_str_arg(self): - self._do_pos_test(cfg.StrOpt, None, ['bar'], 'bar') - - def test_positional_int_none_default(self): - self._do_pos_test(cfg.IntOpt, None, [], None) - - def test_positional_int_default(self): - self._do_pos_test(cfg.IntOpt, 10, [], 10) - - def test_positional_int_arg(self): - self._do_pos_test(cfg.IntOpt, None, ['20'], 20) - - def test_positional_float_none_default(self): - self._do_pos_test(cfg.FloatOpt, None, [], None) - - def test_positional_float_default(self): - self._do_pos_test(cfg.FloatOpt, 1.0, [], 1.0) - - def test_positional_float_arg(self): - self._do_pos_test(cfg.FloatOpt, None, ['2.0'], 2.0) - - def test_positional_list_none_default(self): - self._do_pos_test(cfg.ListOpt, None, [], None) - - def test_positional_list_empty_default(self): - self._do_pos_test(cfg.ListOpt, [], [], []) - - def test_positional_list_default(self): - self._do_pos_test(cfg.ListOpt, ['bar'], [], ['bar']) - - def test_positional_list_arg(self): - self._do_pos_test(cfg.ListOpt, None, - ['blaa,bar'], ['blaa', 'bar']) - - def test_positional_dict_none_default(self): - self._do_pos_test(cfg.DictOpt, None, [], None) - - def test_positional_dict_empty_default(self): - self._do_pos_test(cfg.DictOpt, {}, [], {}) - - def test_positional_dict_default(self): - self._do_pos_test(cfg.DictOpt, {'key1': 'bar'}, [], {'key1': 'bar'}) - - def test_positional_dict_arg(self): - self._do_pos_test(cfg.DictOpt, None, - ['key1:blaa,key2:bar'], - {'key1': 'blaa', 'key2': 'bar'}) - - def test_positional_multistr_none_default(self): - self._do_pos_test(cfg.MultiStrOpt, None, [], None) - - def test_positional_multistr_empty_default(self): - self._do_pos_test(cfg.MultiStrOpt, [], [], []) - - def test_positional_multistr_default(self): - self._do_pos_test(cfg.MultiStrOpt, ['bar'], [], ['bar']) - - def test_positional_multistr_arg(self): - self._do_pos_test(cfg.MultiStrOpt, None, - ['blaa', 'bar'], ['blaa', 'bar']) - - def test_positional_bool(self): - self.assertRaises(ValueError, cfg.BoolOpt, 'foo', positional=True) - - def test_required_positional_opt(self): - self.conf.register_cli_opt( - cfg.StrOpt('foo', required=True, positional=True)) - - self.conf(['bar']) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - def test_missing_required_cli_opt(self): - self.conf.register_cli_opt( - cfg.StrOpt('foo', required=True, positional=True)) - self.assertRaises(cfg.RequiredOptError, self.conf, []) - - def test_positional_opts_order(self): - self.conf.register_cli_opts(( - cfg.StrOpt('command', positional=True), - cfg.StrOpt('arg1', positional=True), - cfg.StrOpt('arg2', positional=True)) - ) - - self.conf(['command', 'arg1', 'arg2']) - - self.assertEqual('command', self.conf.command) - self.assertEqual('arg1', self.conf.arg1) - self.assertEqual('arg2', self.conf.arg2) - - def test_positional_opt_order(self): - self.conf.register_cli_opt( - cfg.StrOpt('command', positional=True)) - self.conf.register_cli_opt( - cfg.StrOpt('arg1', positional=True)) - self.conf.register_cli_opt( - cfg.StrOpt('arg2', positional=True)) - - self.conf(['command', 'arg1', 'arg2']) - - self.assertEqual('command', self.conf.command) - self.assertEqual('arg1', self.conf.arg1) - self.assertEqual('arg2', self.conf.arg2) - - def test_positional_opt_unregister(self): - command = cfg.StrOpt('command', positional=True) - arg1 = cfg.StrOpt('arg1', positional=True) - arg2 = cfg.StrOpt('arg2', positional=True) - self.conf.register_cli_opt(command) - self.conf.register_cli_opt(arg1) - self.conf.register_cli_opt(arg2) - - self.conf(['command', 'arg1', 'arg2']) - - self.assertEqual('command', self.conf.command) - self.assertEqual('arg1', self.conf.arg1) - self.assertEqual('arg2', self.conf.arg2) - - self.conf.reset() - - self.conf.unregister_opt(arg1) - self.conf.unregister_opt(arg2) - - arg0 = cfg.StrOpt('arg0', positional=True) - self.conf.register_cli_opt(arg0) - self.conf.register_cli_opt(arg1) - - self.conf(['command', 'arg0', 'arg1']) - - self.assertEqual('command', self.conf.command) - self.assertEqual('arg0', self.conf.arg0) - self.assertEqual('arg1', self.conf.arg1) - - -class ConfigFileOptsTestCase(BaseTestCase): - - def _do_deprecated_test(self, opt_class, value, result, key, - section='DEFAULT', - dname=None, dgroup=None): - self.conf.register_opt(opt_class('newfoo', - deprecated_name=dname, - deprecated_group=dgroup)) - - paths = self.create_tempfiles([('test', - '[' + section + ']\n' + - key + ' = ' + value + '\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'newfoo')) - self.assertEqual(self.conf.newfoo, result) - - def _do_dname_test_use(self, opt_class, value, result): - self._do_deprecated_test(opt_class, value, result, 'oldfoo', - dname='oldfoo') - - def _do_dgroup_test_use(self, opt_class, value, result): - self._do_deprecated_test(opt_class, value, result, 'newfoo', - section='old', dgroup='old') - - def _do_default_dgroup_test_use(self, opt_class, value, result): - self._do_deprecated_test(opt_class, value, result, 'newfoo', - section='DEFAULT', dgroup='DEFAULT') - - def _do_dgroup_and_dname_test_use(self, opt_class, value, result): - self._do_deprecated_test(opt_class, value, result, 'oof', - section='old', dgroup='old', dname='oof') - - def _do_dname_test_ignore(self, opt_class, value, result): - self._do_deprecated_test(opt_class, value, result, 'newfoo', - dname='oldfoo') - - def _do_dgroup_test_ignore(self, opt_class, value, result): - self._do_deprecated_test(opt_class, value, result, 'newfoo', - section='DEFAULT', dgroup='old') - - def _do_dgroup_and_dname_test_ignore(self, opt_class, value, result): - self._do_deprecated_test(opt_class, value, result, 'oof', - section='old', dgroup='old', dname='oof') - - def test_conf_file_str_default(self): - self.conf.register_opt(cfg.StrOpt('foo', default='bar')) - - paths = self.create_tempfiles([('test', '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - def test_conf_file_str_value(self): - self.conf.register_opt(cfg.StrOpt('foo')) - - paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - def test_conf_file_str_value_override(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = baar\n'), - ('2', - '[DEFAULT]\n' - 'foo = baaar\n')]) - - self.conf(['--foo', 'bar', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'baaar') - - def test_conf_file_str_value_override_use_deprecated(self): - """last option should always win, even if last uses deprecated.""" - self.conf.register_cli_opt( - cfg.StrOpt('newfoo', deprecated_name='oldfoo')) - - paths = self.create_tempfiles([('0', - '[DEFAULT]\n' - 'newfoo = middle\n'), - ('1', - '[DEFAULT]\n' - 'oldfoo = last\n')]) - - self.conf(['--newfoo', 'first', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'newfoo')) - self.assertFalse(hasattr(self.conf, 'oldfoo')) - self.assertEqual(self.conf.newfoo, 'last') - - def test_conf_file_str_use_dname(self): - self._do_dname_test_use(cfg.StrOpt, 'value1', 'value1') - - def test_conf_file_str_use_dgroup(self): - self._do_dgroup_test_use(cfg.StrOpt, 'value1', 'value1') - - def test_conf_file_str_use_default_dgroup(self): - self._do_default_dgroup_test_use(cfg.StrOpt, 'value1', 'value1') - - def test_conf_file_str_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use(cfg.StrOpt, 'value1', 'value1') - - def test_conf_file_str_ignore_dname(self): - self._do_dname_test_ignore(cfg.StrOpt, 'value2', 'value2') - - def test_conf_file_str_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.StrOpt, 'value2', 'value2') - - def test_conf_file_str_ignore_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_ignore(cfg.StrOpt, 'value2', 'value2') - - def test_conf_file_bool_default(self): - self.conf.register_opt(cfg.BoolOpt('foo', default=False)) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, False) - - def test_conf_file_bool_value(self): - self.conf.register_opt(cfg.BoolOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = true\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, True) - - def test_conf_file_bool_cli_value_override(self): - self.conf.register_cli_opt(cfg.BoolOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = 0\n')]) - - self.conf(['--foo', - '--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, False) - - def test_conf_file_bool_cli_inverse_override(self): - self.conf.register_cli_opt(cfg.BoolOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = true\n')]) - - self.conf(['--nofoo', - '--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, True) - - def test_conf_file_bool_cli_order_override(self): - self.conf.register_cli_opt(cfg.BoolOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = false\n')]) - - self.conf(['--config-file', paths[0], - '--foo']) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, True) - - def test_conf_file_bool_file_value_override(self): - self.conf.register_cli_opt(cfg.BoolOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = 0\n'), - ('2', - '[DEFAULT]\n' - 'foo = yes\n')]) - - self.conf(['--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, True) - - def test_conf_file_bool_use_dname(self): - self._do_dname_test_use(cfg.BoolOpt, 'yes', True) - - def test_conf_file_bool_use_dgroup(self): - self._do_dgroup_test_use(cfg.BoolOpt, 'yes', True) - - def test_conf_file_bool_use_default_dgroup(self): - self._do_default_dgroup_test_use(cfg.BoolOpt, 'yes', True) - - def test_conf_file_bool_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use(cfg.BoolOpt, 'yes', True) - - def test_conf_file_bool_ignore_dname(self): - self._do_dname_test_ignore(cfg.BoolOpt, 'no', False) - - def test_conf_file_bool_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.BoolOpt, 'no', False) - - def test_conf_file_bool_ignore_group_and_dname(self): - self._do_dgroup_and_dname_test_ignore(cfg.BoolOpt, 'no', False) - - def test_conf_file_int_default(self): - self.conf.register_opt(cfg.IntOpt('foo', default=666)) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 666) - - @mock.patch.object(cfg, 'LOG') - def test_conf_file_int_wrong_default(self, mock_log): - cfg.IntOpt('foo', default='666') - mock_log.debug.assert_call_count(1) - - def test_conf_file_int_value(self): - self.conf.register_opt(cfg.IntOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = 666\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 666) - - def test_conf_file_int_value_override(self): - self.conf.register_cli_opt(cfg.IntOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = 66\n'), - ('2', - '[DEFAULT]\n' - 'foo = 666\n')]) - - self.conf(['--foo', '6', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 666) - - def test_conf_file_int_use_dname(self): - self._do_dname_test_use(cfg.IntOpt, '66', 66) - - def test_conf_file_int_use_dgroup(self): - self._do_dgroup_test_use(cfg.IntOpt, '66', 66) - - def test_conf_file_int_use_default_dgroup(self): - self._do_default_dgroup_test_use(cfg.IntOpt, '66', 66) - - def test_conf_file_int_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use(cfg.IntOpt, '66', 66) - - def test_conf_file_int_ignore_dname(self): - self._do_dname_test_ignore(cfg.IntOpt, '64', 64) - - def test_conf_file_int_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.IntOpt, '64', 64) - - def test_conf_file_int_ignore_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_ignore(cfg.IntOpt, '64', 64) - - def test_conf_file_float_default(self): - self.conf.register_opt(cfg.FloatOpt('foo', default=6.66)) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 6.66) - - @mock.patch.object(cfg, 'LOG') - def test_conf_file_float_default_wrong_type(self, mock_log): - cfg.FloatOpt('foo', default='foobar6.66') - mock_log.debug.assert_call_count(1) - - def test_conf_file_float_value(self): - self.conf.register_opt(cfg.FloatOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = 6.66\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 6.66) - - def test_conf_file_float_value_override(self): - self.conf.register_cli_opt(cfg.FloatOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = 6.6\n'), - ('2', - '[DEFAULT]\n' - 'foo = 6.66\n')]) - - self.conf(['--foo', '6', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 6.66) - - def test_conf_file_float_use_dname(self): - self._do_dname_test_use(cfg.FloatOpt, '66.54', 66.54) - - def test_conf_file_float_use_dgroup(self): - self._do_dgroup_test_use(cfg.FloatOpt, '66.54', 66.54) - - def test_conf_file_float_use_default_dgroup(self): - self._do_default_dgroup_test_use(cfg.FloatOpt, '66.54', 66.54) - - def test_conf_file_float_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use(cfg.FloatOpt, '66.54', 66.54) - - def test_conf_file_float_ignore_dname(self): - self._do_dname_test_ignore(cfg.FloatOpt, '64.54', 64.54) - - def test_conf_file_float_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.FloatOpt, '64.54', 64.54) - - def test_conf_file_float_ignore_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_ignore(cfg.FloatOpt, '64.54', 64.54) - - def test_conf_file_list_default(self): - self.conf.register_opt(cfg.ListOpt('foo', default=['bar'])) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, ['bar']) - - @mock.patch.object(cfg, 'LOG') - def test_conf_file_list_default_wrong_type(self, mock_log): - cfg.ListOpt('foo', default=25) - mock_log.debug.assert_called_once_with( - 'Expected default value of type(s) %(extypes)s but ' - 'got %(default)r of type %(deftypes)s', - {'extypes': 'list', - 'default': 25, - 'deftypes': 'int'}) - - def test_conf_file_list_value(self): - self.conf.register_opt(cfg.ListOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, ['bar']) - - def test_conf_file_list_value_override(self): - self.conf.register_cli_opt(cfg.ListOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = bar,bar\n'), - ('2', - '[DEFAULT]\n' - 'foo = b,a,r\n')]) - - self.conf(['--foo', 'bar', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, ['b', 'a', 'r']) - - def test_conf_file_list_use_dname(self): - self._do_dname_test_use(cfg.ListOpt, 'a,b,c', ['a', 'b', 'c']) - - def test_conf_file_list_use_dgroup(self): - self._do_dgroup_test_use(cfg.ListOpt, 'a,b,c', ['a', 'b', 'c']) - - def test_conf_file_list_use_default_dgroup(self): - self._do_default_dgroup_test_use(cfg.ListOpt, 'a,b,c', ['a', 'b', 'c']) - - def test_conf_file_list_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use(cfg.ListOpt, 'a,b,c', - ['a', 'b', 'c']) - - def test_conf_file_list_ignore_dname(self): - self._do_dname_test_ignore(cfg.ListOpt, 'd,e,f', ['d', 'e', 'f']) - - def test_conf_file_list_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.ListOpt, 'd,e,f', ['d', 'e', 'f']) - - def test_conf_file_list_ignore_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_ignore( - cfg.ListOpt, 'd,e,f', ['d', 'e', 'f']) - - def test_conf_file_list_spaces_use_dname(self): - self._do_dname_test_use(cfg.ListOpt, 'a, b, c', ['a', 'b', 'c']) - - def test_conf_file_list_spaces_use_dgroup(self): - self._do_dgroup_test_use(cfg.ListOpt, 'a, b, c', ['a', 'b', 'c']) - - def test_conf_file_list_spaces_use_default_dgroup(self): - self._do_default_dgroup_test_use( - cfg.ListOpt, 'a, b, c', ['a', 'b', 'c']) - - def test_conf_file_list_spaces_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use( - cfg.ListOpt, 'a, b, c', ['a', 'b', 'c']) - - def test_conf_file_list_spaces_ignore_dname(self): - self._do_dname_test_ignore(cfg.ListOpt, 'd, e, f', ['d', 'e', 'f']) - - def test_conf_file_list_spaces_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.ListOpt, 'd, e, f', ['d', 'e', 'f']) - - def test_conf_file_list_spaces_ignore_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_ignore(cfg.ListOpt, 'd, e, f', - ['d', 'e', 'f']) - - def test_conf_file_dict_default(self): - self.conf.register_opt(cfg.DictOpt('foo', default={'key': 'bar'})) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, {'key': 'bar'}) - - def test_conf_file_dict_value(self): - self.conf.register_opt(cfg.DictOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = key:bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, {'key': 'bar'}) - - def test_conf_file_dict_colon_in_value(self): - self.conf.register_opt(cfg.DictOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = key:bar:baz\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, {'key': 'bar:baz'}) - - def test_conf_file_dict_value_no_colon(self): - self.conf.register_opt(cfg.DictOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = key:bar,baz\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo') - self.assertRaises(AttributeError, getattr, self.conf, 'foo') - - def test_conf_file_dict_value_duplicate_key(self): - self.conf.register_opt(cfg.DictOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = key:bar,key:baz\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo') - self.assertRaises(AttributeError, getattr, self.conf, 'foo') - - def test_conf_file_dict_values_override_deprecated(self): - self.conf.register_cli_opt(cfg.DictOpt('foo', - deprecated_name='oldfoo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = key1:bar1\n'), - ('2', - '[DEFAULT]\n' - 'oldfoo = key2:bar2\n' - 'oldfoo = key3:bar3\n')]) - - self.conf(['--foo', 'key0:bar0', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - - self.assertEqual(self.conf.foo, {'key3': 'bar3'}) - - def test_conf_file_dict_deprecated(self): - self.conf.register_opt(cfg.DictOpt('newfoo', deprecated_name='oldfoo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'oldfoo= key1:bar1\n' - 'oldfoo = key2:bar2\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'newfoo')) - self.assertEqual(self.conf.newfoo, {'key2': 'bar2'}) - - def test_conf_file_dict_value_override(self): - self.conf.register_cli_opt(cfg.DictOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = key:bar,key2:bar\n'), - ('2', - '[DEFAULT]\n' - 'foo = k1:v1,k2:v2\n')]) - - self.conf(['--foo', 'x:y,x2:y2', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, {'k1': 'v1', 'k2': 'v2'}) - - def test_conf_file_dict_use_dname(self): - self._do_dname_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_use_dgroup(self): - self._do_dgroup_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_use_default_dgroup(self): - self._do_default_dgroup_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_ignore_dname(self): - self._do_dname_test_ignore(cfg.DictOpt, - 'k1:d,k2:e,k3:f', - {'k1': 'd', 'k2': 'e', 'k3': 'f'}) - - def test_conf_file_dict_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.DictOpt, - 'k1:d,k2:e,k3:f', - {'k1': 'd', 'k2': 'e', 'k3': 'f'}) - - def test_conf_file_dict_ignore_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_ignore(cfg.DictOpt, - 'k1:d,k2:e,k3:f', - {'k1': 'd', - 'k2': 'e', - 'k3': 'f'}) - - def test_conf_file_dict_spaces_use_dname(self): - self._do_dname_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_spaces_use_dgroup(self): - self._do_dgroup_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_spaces_use_default_dgroup(self): - self._do_default_dgroup_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_spaces_use_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_use(cfg.DictOpt, - 'k1:a,k2:b,k3:c', - {'k1': 'a', 'k2': 'b', 'k3': 'c'}) - - def test_conf_file_dict_spaces_ignore_dname(self): - self._do_dname_test_ignore(cfg.DictOpt, - 'k1:d,k2:e,k3:f', - {'k1': 'd', 'k2': 'e', 'k3': 'f'}) - - def test_conf_file_dict_spaces_ignore_dgroup(self): - self._do_dgroup_test_ignore(cfg.DictOpt, - 'k1:d,k2:e,k3:f', - {'k1': 'd', 'k2': 'e', 'k3': 'f'}) - - def test_conf_file_dict_spaces_ignore_dgroup_and_dname(self): - self._do_dgroup_and_dname_test_ignore(cfg.DictOpt, - 'k1:d,k2:e,k3:f', - {'k1': 'd', - 'k2': 'e', - 'k3': 'f'}) - - def test_conf_file_multistr_default(self): - self.conf.register_opt(cfg.MultiStrOpt('foo', default=['bar'])) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, ['bar']) - - def test_conf_file_multistr_value(self): - self.conf.register_opt(cfg.MultiStrOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, ['bar']) - - def test_conf_file_multistr_values_append_deprecated(self): - self.conf.register_cli_opt(cfg.MultiStrOpt('foo', - deprecated_name='oldfoo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = bar1\n'), - ('2', - '[DEFAULT]\n' - 'oldfoo = bar2\n' - 'oldfoo = bar3\n')]) - - self.conf(['--foo', 'bar0', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - - self.assertEqual(self.conf.foo, ['bar0', 'bar1', 'bar2', 'bar3']) - - def test_conf_file_multistr_values_append(self): - self.conf.register_cli_opt(cfg.MultiStrOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = bar1\n'), - ('2', - '[DEFAULT]\n' - 'foo = bar2\n' - 'foo = bar3\n')]) - - self.conf(['--foo', 'bar0', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - - self.assertEqual(self.conf.foo, ['bar0', 'bar1', 'bar2', 'bar3']) - - def test_conf_file_multistr_deprecated(self): - self.conf.register_opt( - cfg.MultiStrOpt('newfoo', deprecated_name='oldfoo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'oldfoo= bar1\n' - 'oldfoo = bar2\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'newfoo')) - self.assertEqual(self.conf.newfoo, ['bar1', 'bar2']) - - def test_conf_file_multiple_opts(self): - self.conf.register_opts([cfg.StrOpt('foo'), cfg.StrOpt('bar')]) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n' - 'bar = foo\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - self.assertTrue(hasattr(self.conf, 'bar')) - self.assertEqual(self.conf.bar, 'foo') - - def test_conf_file_raw_value(self): - self.conf.register_opt(cfg.StrOpt('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar-%08x\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar-%08x') - - -class ConfigFileReloadTestCase(BaseTestCase): - - def test_conf_files_reload(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = baar\n'), - ('2', - '[DEFAULT]\n' - 'foo = baaar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'baar') - - shutil.copy(paths[1], paths[0]) - - self.conf.reload_config_files() - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'baaar') - - def test_conf_files_reload_default(self): - self.conf.register_cli_opt(cfg.StrOpt('foo1')) - self.conf.register_cli_opt(cfg.StrOpt('foo2')) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo1 = default1\n'), - ('2', - '[DEFAULT]\n' - 'foo2 = default2\n')]) - - paths_change = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo1 = change_default1\n'), - ('2', - '[DEFAULT]\n' - 'foo2 = change_default2\n')]) - - self.conf(args=[], default_config_files=paths) - self.assertTrue(hasattr(self.conf, 'foo1')) - self.assertEqual(self.conf.foo1, 'default1') - self.assertTrue(hasattr(self.conf, 'foo2')) - self.assertEqual(self.conf.foo2, 'default2') - - shutil.copy(paths_change[0], paths[0]) - shutil.copy(paths_change[1], paths[1]) - - self.conf.reload_config_files() - self.assertTrue(hasattr(self.conf, 'foo1')) - self.assertEqual(self.conf.foo1, 'change_default1') - self.assertTrue(hasattr(self.conf, 'foo2')) - self.assertEqual(self.conf.foo2, 'change_default2') - - def test_conf_files_reload_file_not_found(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', required=True)) - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = baar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'baar') - - os.remove(paths[0]) - - self.conf.reload_config_files() - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'baar') - - def test_conf_files_reload_error(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', required=True)) - self.conf.register_cli_opt(cfg.StrOpt('foo1', required=True)) - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = test1\n' - 'foo1 = test11\n'), - ('2', - '[DEFAULT]\n' - 'foo2 = test2\n' - 'foo3 = test22\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'test1') - self.assertTrue(hasattr(self.conf, 'foo1')) - self.assertEqual(self.conf.foo1, 'test11') - - shutil.copy(paths[1], paths[0]) - - self.conf.reload_config_files() - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'test1') - self.assertTrue(hasattr(self.conf, 'foo1')) - self.assertEqual(self.conf.foo1, 'test11') - - -class OptGroupsTestCase(BaseTestCase): - - def test_arg_group(self): - blaa_group = cfg.OptGroup('blaa', 'blaa options') - self.conf.register_group(blaa_group) - self.conf.register_cli_opt(cfg.StrOpt('foo'), group=blaa_group) - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_autocreate_group_by_name(self): - self.conf.register_cli_opt(cfg.StrOpt('foo'), group='blaa') - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_autocreate_group_by_group(self): - group = cfg.OptGroup(name='blaa', title='Blaa options') - self.conf.register_cli_opt(cfg.StrOpt('foo'), group=group) - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_autocreate_title(self): - blaa_group = cfg.OptGroup('blaa') - self.assertEqual(blaa_group.title, 'blaa options') - - def test_arg_group_by_name(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt(cfg.StrOpt('foo'), group='blaa') - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_with_default(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt( - cfg.StrOpt('foo', default='bar'), group='blaa') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_with_conf_and_group_opts(self): - self.conf.register_cli_opt(cfg.StrOpt('conf'), group='blaa') - self.conf.register_cli_opt(cfg.StrOpt('group'), group='blaa') - - self.conf(['--blaa-conf', 'foo', '--blaa-group', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'conf')) - self.assertEqual(self.conf.blaa.conf, 'foo') - self.assertTrue(hasattr(self.conf.blaa, 'group')) - self.assertEqual(self.conf.blaa.group, 'bar') - - def test_arg_group_in_config_file(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo'), group='blaa') - - paths = self.create_tempfiles([('test', - '[blaa]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_with_deprecated_name(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='oldfoo'), - group='blaa') - - paths = self.create_tempfiles([('test', - '[blaa]\n' - 'oldfoo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_with_deprecated_group(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', deprecated_group='DEFAULT'), - group='blaa') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_with_deprecated_group_and_name(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt( - cfg.StrOpt('foo', deprecated_group='DEFAULT', - deprecated_name='oldfoo'), group='blaa') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'oldfoo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_override_deprecated_name(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='oldfoo'), - group='blaa') - - paths = self.create_tempfiles([('test', - '[blaa]\n' - 'foo = bar\n' - 'oldfoo = blabla\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_override_deprecated_group(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', deprecated_group='DEFAULT'), - group='blaa') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = blabla\n' - '[blaa]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_override_deprecated_group_and_name(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt( - cfg.StrOpt('foo', deprecated_group='DEFAULT', - deprecated_name='oldfoo'), group='blaa') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'oldfoo = blabla\n' - '[blaa]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_with_capital_name(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo'), group='blaa') - - paths = self.create_tempfiles([('test', - '[BLAA]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertFalse(hasattr(self.conf, 'BLAA')) - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_arg_group_in_config_file_with_capital_name_on_legacy_code(self): - self.conf.register_group(cfg.OptGroup('BLAA')) - self.conf.register_opt(cfg.StrOpt('foo'), group='BLAA') - - paths = self.create_tempfiles([('test', - '[BLAA]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertFalse(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf, 'BLAA')) - self.assertTrue(hasattr(self.conf.BLAA, 'foo')) - self.assertEqual(self.conf.BLAA.foo, 'bar') - - -class MappingInterfaceTestCase(BaseTestCase): - - def test_mapping_interface(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - - self.conf(['--foo', 'bar']) - - self.assertTrue('foo' in self.conf) - self.assertTrue('config_file' in self.conf) - self.assertEqual(len(self.conf), 3) - self.assertEqual(self.conf['foo'], 'bar') - self.assertEqual(self.conf.get('foo'), 'bar') - self.assertTrue('bar' in list(self.conf.values())) - - def test_mapping_interface_with_group(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt(cfg.StrOpt('foo'), group='blaa') - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue('blaa' in self.conf) - self.assertTrue('foo' in list(self.conf['blaa'])) - self.assertEqual(len(self.conf['blaa']), 1) - self.assertEqual(self.conf['blaa']['foo'], 'bar') - self.assertEqual(self.conf['blaa'].get('foo'), 'bar') - self.assertTrue('bar' in self.conf['blaa'].values()) - self.assertEqual(self.conf.blaa, self.conf['blaa']) - - -class OptNameSeparatorTestCast(BaseTestCase): - - scenarios = [ - ('hyphen', - dict(opt_name='foo-bar', - opt_dest='foo_bar', - broken_opt_dest='foo-bar', - cf_name='foo_bar', - broken_cf_name='foo-bar', - cli_name='foo-bar', - broken_cli_name='foo_bar', - broken=True)), # FIXME(markmc): see #1279973 - ('underscore', - dict(opt_name='foo_bar', - opt_dest='foo_bar', - broken_opt_dest='foo-bar', - cf_name='foo_bar', - broken_cf_name='foo-bar', - cli_name='foo_bar', - broken_cli_name='foo_bar', - broken=False)), - ] - - def test_attribute_and_key_name(self): - self.conf.register_opt(cfg.StrOpt(self.opt_name)) - - self.assertTrue(hasattr(self.conf, self.opt_dest)) - self.assertFalse(hasattr(self.conf, self.broken_opt_dest)) - self.assertIn(self.opt_dest, self.conf) - self.assertNotIn(self.broken_opt_dest, self.conf) - - def test_cli_opt_name(self): - self.conf.register_cli_opt(cfg.BoolOpt(self.opt_name)) - - self.conf(['--' + self.cli_name]) - - self.assertTrue(getattr(self.conf, self.opt_dest)) - - def test_config_file_opt_name(self): - self.conf.register_opt(cfg.BoolOpt(self.opt_name)) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' + - self.cf_name + ' = True\n' + - self.broken_cf_name + ' = False\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(getattr(self.conf, self.opt_dest)) - - def test_deprecated_name(self): - self.conf.register_opt(cfg.StrOpt('foobar', - deprecated_name=self.opt_name)) - - self.assertTrue(hasattr(self.conf, 'foobar')) - self.assertFalse(hasattr(self.conf, self.opt_dest)) - self.assertFalse(hasattr(self.conf, self.broken_opt_dest)) - self.assertIn('foobar', self.conf) - self.assertNotIn(self.opt_dest, self.conf) - self.assertNotIn(self.broken_opt_dest, self.conf) - - def test_deprecated_name_cli(self): - self.conf.register_cli_opt(cfg.BoolOpt('foobar', - deprecated_name=self.opt_name)) - - # FIXME(markmc): this should be self.cli_name, see #1279973 - if self.broken: - self.conf(['--' + self.broken_cli_name]) - else: - self.conf(['--' + self.cli_name]) - - self.assertTrue(self.conf.foobar) - - def test_deprecated_name_config_file(self): - self.conf.register_opt(cfg.BoolOpt('foobar', - deprecated_name=self.opt_name)) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' + - self.cf_name + ' = True\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(self.conf.foobar) - - def test_deprecated_opts(self): - oldopts = [cfg.DeprecatedOpt(self.opt_name)] - self.conf.register_opt(cfg.StrOpt('foobar', - deprecated_opts=oldopts)) - - self.assertTrue(hasattr(self.conf, 'foobar')) - self.assertFalse(hasattr(self.conf, self.opt_dest)) - self.assertFalse(hasattr(self.conf, self.broken_opt_dest)) - self.assertIn('foobar', self.conf) - self.assertNotIn(self.opt_dest, self.conf) - self.assertNotIn(self.broken_opt_dest, self.conf) - - def test_deprecated_opts_cli(self): - oldopts = [cfg.DeprecatedOpt(self.opt_name)] - self.conf.register_cli_opt(cfg.BoolOpt('foobar', - deprecated_opts=oldopts)) - - self.conf(['--' + self.cli_name]) - - self.assertTrue(self.conf.foobar) - - def test_deprecated_opts_config_file(self): - oldopts = [cfg.DeprecatedOpt(self.opt_name)] - self.conf.register_opt(cfg.BoolOpt('foobar', - deprecated_opts=oldopts)) - - # FIXME(markmc): this should be self.cf_name, see #1279973 - if self.broken: - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' + - self.broken_cf_name + - ' = True\n')]) - else: - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' + - self.cf_name + ' = True\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(self.conf.foobar) - - -class ReRegisterOptTestCase(BaseTestCase): - - def test_conf_file_re_register_opt(self): - opt = cfg.StrOpt('foo') - self.assertTrue(self.conf.register_opt(opt)) - self.assertFalse(self.conf.register_opt(opt)) - - def test_conf_file_re_register_opt_in_group(self): - group = cfg.OptGroup('blaa') - self.conf.register_group(group) - self.conf.register_group(group) # not an error - opt = cfg.StrOpt('foo') - self.assertTrue(self.conf.register_opt(opt, group=group)) - self.assertFalse(self.conf.register_opt(opt, group='blaa')) - - -class TemplateSubstitutionTestCase(BaseTestCase): - - def _prep_test_str_sub(self, foo_default=None, bar_default=None): - self.conf.register_cli_opt(cfg.StrOpt('foo', default=foo_default)) - self.conf.register_cli_opt(cfg.StrOpt('bar', default=bar_default)) - - def _assert_str_sub(self): - self.assertTrue(hasattr(self.conf, 'bar')) - self.assertEqual(self.conf.bar, 'blaa') - - def test_str_sub_default_from_default(self): - self._prep_test_str_sub(foo_default='blaa', bar_default='$foo') - - self.conf([]) - - self._assert_str_sub() - - def test_str_sub_default_from_default_recurse(self): - self.conf.register_cli_opt(cfg.StrOpt('blaa', default='blaa')) - self._prep_test_str_sub(foo_default='$blaa', bar_default='$foo') - - self.conf([]) - - self._assert_str_sub() - - def test_str_sub_default_from_arg(self): - self._prep_test_str_sub(bar_default='$foo') - - self.conf(['--foo', 'blaa']) - - self._assert_str_sub() - - def test_str_sub_default_from_config_file(self): - self._prep_test_str_sub(bar_default='$foo') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = blaa\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_str_sub() - - def test_str_sub_arg_from_default(self): - self._prep_test_str_sub(foo_default='blaa') - - self.conf(['--bar', '$foo']) - - self._assert_str_sub() - - def test_str_sub_arg_from_arg(self): - self._prep_test_str_sub() - - self.conf(['--foo', 'blaa', '--bar', '$foo']) - - self._assert_str_sub() - - def test_str_sub_arg_from_config_file(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = blaa\n')]) - - self.conf(['--config-file', paths[0], '--bar=$foo']) - - self._assert_str_sub() - - def test_str_sub_config_file_from_default(self): - self._prep_test_str_sub(foo_default='blaa') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar = $foo\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_str_sub() - - def test_str_sub_config_file_from_arg(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar = $foo\n')]) - - self.conf(['--config-file', paths[0], '--foo=blaa']) - - self._assert_str_sub() - - def test_str_sub_config_file_from_config_file(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar = $foo\n' - 'foo = blaa\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_str_sub() - - def test_str_sub_with_dollar_escape_char(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar=foo-somethin$$k2\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'bar')) - self.assertEqual(self.conf.bar, 'foo-somethin$k2') - - def test_str_sub_with_backslash_escape_char(self): - self._prep_test_str_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar=foo-somethin\$k2\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'bar')) - self.assertEqual(self.conf.bar, 'foo-somethin$k2') - - def test_str_sub_group_from_default(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', default='blaa')) - self.conf.register_group(cfg.OptGroup('ba')) - self.conf.register_cli_opt(cfg.StrOpt('r', default='$foo'), group='ba') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'ba')) - self.assertTrue(hasattr(self.conf.ba, 'r')) - self.assertEqual(self.conf.ba.r, 'blaa') - - def test_str_sub_set_default(self): - self._prep_test_str_sub() - self.conf.set_default('bar', '$foo') - self.conf.set_default('foo', 'blaa') - - self.conf([]) - - self._assert_str_sub() - - def test_str_sub_set_override(self): - self._prep_test_str_sub() - self.conf.set_override('bar', '$foo') - self.conf.set_override('foo', 'blaa') - - self.conf([]) - - self._assert_str_sub() - - def _prep_test_str_int_sub(self, foo_default=None, bar_default=None): - self.conf.register_cli_opt(cfg.StrOpt('foo', default=foo_default)) - self.conf.register_cli_opt(cfg.IntOpt('bar', default=bar_default)) - - def _assert_int_sub(self): - self.assertTrue(hasattr(self.conf, 'bar')) - self.assertEqual(self.conf.bar, 123) - - def test_sub_default_from_default(self): - self._prep_test_str_int_sub(foo_default='123', bar_default='$foo') - - self.conf([]) - - self._assert_int_sub() - - def test_sub_default_from_default_recurse(self): - self.conf.register_cli_opt(cfg.StrOpt('blaa', default='123')) - self._prep_test_str_int_sub(foo_default='$blaa', bar_default='$foo') - - self.conf([]) - - self._assert_int_sub() - - def test_sub_default_from_arg(self): - self._prep_test_str_int_sub(bar_default='$foo') - - self.conf(['--foo', '123']) - - self._assert_int_sub() - - def test_sub_default_from_config_file(self): - self._prep_test_str_int_sub(bar_default='$foo') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = 123\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_int_sub() - - def test_sub_arg_from_default(self): - self._prep_test_str_int_sub(foo_default='123') - - self.conf(['--bar', '$foo']) - - self._assert_int_sub() - - def test_sub_arg_from_arg(self): - self._prep_test_str_int_sub() - - self.conf(['--foo', '123', '--bar', '$foo']) - - self._assert_int_sub() - - def test_sub_arg_from_config_file(self): - self._prep_test_str_int_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = 123\n')]) - - self.conf(['--config-file', paths[0], '--bar=$foo']) - - self._assert_int_sub() - - def test_sub_config_file_from_default(self): - self._prep_test_str_int_sub(foo_default='123') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar = $foo\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_int_sub() - - def test_sub_config_file_from_arg(self): - self._prep_test_str_int_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar = $foo\n')]) - - self.conf(['--config-file', paths[0], '--foo=123']) - - self._assert_int_sub() - - def test_sub_config_file_from_config_file(self): - self._prep_test_str_int_sub() - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'bar = $foo\n' - 'foo = 123\n')]) - - self.conf(['--config-file', paths[0]]) - - self._assert_int_sub() - - def test_sub_group_from_default(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', default='123')) - self.conf.register_group(cfg.OptGroup('ba')) - self.conf.register_cli_opt(cfg.IntOpt('r', default='$foo'), group='ba') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'ba')) - self.assertTrue(hasattr(self.conf.ba, 'r')) - self.assertEqual(self.conf.foo, '123') - self.assertEqual(self.conf.ba.r, 123) - - def test_sub_group_from_default_deprecated(self): - self.conf.register_group(cfg.OptGroup('ba')) - self.conf.register_cli_opt(cfg.StrOpt( - 'foo', default='123', deprecated_group='DEFAULT'), group='ba') - self.conf.register_cli_opt(cfg.IntOpt('r', default='$foo'), group='ba') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'ba')) - self.assertTrue(hasattr(self.conf.ba, 'foo')) - self.assertEqual(self.conf.ba.foo, '123') - self.assertTrue(hasattr(self.conf.ba, 'r')) - self.assertEqual(self.conf.ba.r, 123) - - def test_sub_group_from_args_deprecated(self): - self.conf.register_group(cfg.OptGroup('ba')) - self.conf.register_cli_opt(cfg.StrOpt( - 'foo', default='123', deprecated_group='DEFAULT'), group='ba') - self.conf.register_cli_opt(cfg.IntOpt('r', default='$foo'), group='ba') - - self.conf(['--ba-foo=4242']) - - self.assertTrue(hasattr(self.conf, 'ba')) - self.assertTrue(hasattr(self.conf.ba, 'foo')) - self.assertTrue(hasattr(self.conf.ba, 'r')) - self.assertEqual(self.conf.ba.foo, '4242') - self.assertEqual(self.conf.ba.r, 4242) - - def test_sub_group_from_configfile_deprecated(self): - self.conf.register_group(cfg.OptGroup('ba')) - self.conf.register_cli_opt(cfg.StrOpt( - 'foo', default='123', deprecated_group='DEFAULT'), group='ba') - self.conf.register_cli_opt(cfg.IntOpt('r', default='$foo'), group='ba') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo=4242\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'ba')) - self.assertTrue(hasattr(self.conf.ba, 'foo')) - self.assertTrue(hasattr(self.conf.ba, 'r')) - self.assertEqual(self.conf.ba.foo, '4242') - self.assertEqual(self.conf.ba.r, 4242) - - -class ConfigDirTestCase(BaseTestCase): - - def test_config_dir(self): - snafu_group = cfg.OptGroup('snafu') - self.conf.register_group(snafu_group) - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.conf.register_cli_opt(cfg.StrOpt('bell'), group=snafu_group) - - dir = tempfile.mkdtemp() - self.tempdirs.append(dir) - - paths = self.create_tempfiles([(os.path.join(dir, '00-test'), - '[DEFAULT]\n' - 'foo = bar-00\n' - '[snafu]\n' - 'bell = whistle-00\n'), - (os.path.join(dir, '02-test'), - '[snafu]\n' - 'bell = whistle-02\n' - '[DEFAULT]\n' - 'foo = bar-02\n'), - (os.path.join(dir, '01-test'), - '[DEFAULT]\n' - 'foo = bar-01\n')]) - - self.conf(['--foo', 'bar', - '--config-dir', os.path.dirname(paths[0])]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar-02') - self.assertTrue(hasattr(self.conf, 'snafu')) - self.assertTrue(hasattr(self.conf.snafu, 'bell')) - self.assertEqual(self.conf.snafu.bell, 'whistle-02') - - def test_config_dir_file_precedence(self): - snafu_group = cfg.OptGroup('snafu') - self.conf.register_group(snafu_group) - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.conf.register_cli_opt(cfg.StrOpt('bell'), group=snafu_group) - - dir = tempfile.mkdtemp() - self.tempdirs.append(dir) - - paths = self.create_tempfiles([(os.path.join(dir, '00-test'), - '[DEFAULT]\n' - 'foo = bar-00\n'), - ('01-test', - '[snafu]\n' - 'bell = whistle-01\n' - '[DEFAULT]\n' - 'foo = bar-01\n'), - ('03-test', - '[snafu]\n' - 'bell = whistle-03\n' - '[DEFAULT]\n' - 'foo = bar-03\n'), - (os.path.join(dir, '02-test'), - '[DEFAULT]\n' - 'foo = bar-02\n')]) - - self.conf(['--foo', 'bar', - '--config-file', paths[1], - '--config-dir', os.path.dirname(paths[0]), - '--config-file', paths[2], ]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar-03') - self.assertTrue(hasattr(self.conf, 'snafu')) - self.assertTrue(hasattr(self.conf.snafu, 'bell')) - self.assertEqual(self.conf.snafu.bell, 'whistle-03') - - def test_config_dir_default_file_precedence(self): - snafu_group = cfg.OptGroup('snafu') - self.conf.register_group(snafu_group) - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.conf.register_cli_opt(cfg.StrOpt('bell'), group=snafu_group) - - dir = tempfile.mkdtemp() - self.tempdirs.append(dir) - - paths = self.create_tempfiles([(os.path.join(dir, '00-test'), - '[DEFAULT]\n' - 'foo = bar-00\n' - '[snafu]\n' - 'bell = whistle-11\n'), - ('01-test', - '[snafu]\n' - 'bell = whistle-01\n' - '[DEFAULT]\n' - 'foo = bar-01\n'), - ('03-test', - '[snafu]\n' - 'bell = whistle-03\n' - '[DEFAULT]\n' - 'foo = bar-03\n'), - (os.path.join(dir, '02-test'), - '[DEFAULT]\n' - 'foo = bar-02\n')]) - - self.conf(['--foo', 'bar', '--config-dir', os.path.dirname(paths[0])], - default_config_files=[paths[1], paths[2]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar-02') - self.assertTrue(hasattr(self.conf, 'snafu')) - self.assertTrue(hasattr(self.conf.snafu, 'bell')) - self.assertEqual(self.conf.snafu.bell, 'whistle-11') - - def test_config_dir_doesnt_exist(self): - tmpdir = '/tmp/foo' - - self.assertRaises(cfg.ConfigDirNotFoundError, - self.conf, - ['--config-dir', tmpdir] - ) - - -class ReparseTestCase(BaseTestCase): - - def test_reparse(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt( - cfg.StrOpt('foo', default='r'), group='blaa') - - paths = self.create_tempfiles([('test', - '[blaa]\n' - 'foo = b\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'b') - - self.conf(['--blaa-foo', 'a']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'a') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'r') - - -class OverridesTestCase(BaseTestCase): - - def test_default_none(self): - self.conf.register_opt(cfg.StrOpt('foo', default='foo')) - self.conf([]) - self.assertEqual(self.conf.foo, 'foo') - self.conf.set_default('foo', None) - self.assertIsNone(self.conf.foo) - self.conf.clear_default('foo') - self.assertEqual(self.conf.foo, 'foo') - - def test_override_none(self): - self.conf.register_opt(cfg.StrOpt('foo', default='foo')) - self.conf([]) - self.assertEqual(self.conf.foo, 'foo') - self.conf.set_override('foo', None) - self.assertIsNone(self.conf.foo) - self.conf.clear_override('foo') - self.assertEqual(self.conf.foo, 'foo') - - def test_no_default_override(self): - self.conf.register_opt(cfg.StrOpt('foo')) - self.conf([]) - self.assertIsNone(self.conf.foo) - self.conf.set_default('foo', 'bar') - self.assertEqual(self.conf.foo, 'bar') - self.conf.clear_default('foo') - self.assertIsNone(self.conf.foo) - - def test_default_override(self): - self.conf.register_opt(cfg.StrOpt('foo', default='foo')) - self.conf([]) - self.assertEqual(self.conf.foo, 'foo') - self.conf.set_default('foo', 'bar') - self.assertEqual(self.conf.foo, 'bar') - self.conf.clear_default('foo') - self.assertEqual(self.conf.foo, 'foo') - - def test_override(self): - self.conf.register_opt(cfg.StrOpt('foo')) - self.conf.set_override('foo', 'bar') - self.conf([]) - self.assertEqual(self.conf.foo, 'bar') - self.conf.clear_override('foo') - self.assertIsNone(self.conf.foo) - - def test_group_no_default_override(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo'), group='blaa') - self.conf([]) - self.assertIsNone(self.conf.blaa.foo) - self.conf.set_default('foo', 'bar', group='blaa') - self.assertEqual(self.conf.blaa.foo, 'bar') - self.conf.clear_default('foo', group='blaa') - self.assertIsNone(self.conf.blaa.foo) - - def test_group_default_override(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', default='foo'), group='blaa') - self.conf([]) - self.assertEqual(self.conf.blaa.foo, 'foo') - self.conf.set_default('foo', 'bar', group='blaa') - self.assertEqual(self.conf.blaa.foo, 'bar') - self.conf.clear_default('foo', group='blaa') - self.assertEqual(self.conf.blaa.foo, 'foo') - - def test_group_override(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo'), group='blaa') - self.assertIsNone(self.conf.blaa.foo) - self.conf.set_override('foo', 'bar', group='blaa') - self.conf([]) - self.assertEqual(self.conf.blaa.foo, 'bar') - self.conf.clear_override('foo', group='blaa') - self.assertIsNone(self.conf.blaa.foo) - - def test_cli_bool_default(self): - self.conf.register_cli_opt(cfg.BoolOpt('foo')) - self.conf.set_default('foo', True) - self.assertTrue(self.conf.foo) - self.conf([]) - self.assertTrue(self.conf.foo) - self.conf.set_default('foo', False) - self.assertFalse(self.conf.foo) - self.conf.clear_default('foo') - self.assertIsNone(self.conf.foo) - - def test_cli_bool_override(self): - self.conf.register_cli_opt(cfg.BoolOpt('foo')) - self.conf.set_override('foo', True) - self.assertTrue(self.conf.foo) - self.conf([]) - self.assertTrue(self.conf.foo) - self.conf.set_override('foo', False) - self.assertFalse(self.conf.foo) - self.conf.clear_override('foo') - self.assertIsNone(self.conf.foo) - - -class ResetAndClearTestCase(BaseTestCase): - - def test_clear(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.conf.register_cli_opt(cfg.StrOpt('bar'), group='blaa') - - self.assertIsNone(self.conf.foo) - self.assertIsNone(self.conf.blaa.bar) - - self.conf(['--foo', 'foo', '--blaa-bar', 'bar']) - - self.assertEqual(self.conf.foo, 'foo') - self.assertEqual(self.conf.blaa.bar, 'bar') - - self.conf.clear() - - self.assertIsNone(self.conf.foo) - self.assertIsNone(self.conf.blaa.bar) - - def test_reset_and_clear_with_defaults_and_overrides(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.conf.register_cli_opt(cfg.StrOpt('bar'), group='blaa') - - self.conf.set_default('foo', 'foo') - self.conf.set_override('bar', 'bar', group='blaa') - - self.conf(['--foo', 'foofoo']) - - self.assertEqual(self.conf.foo, 'foofoo') - self.assertEqual(self.conf.blaa.bar, 'bar') - - self.conf.clear() - - self.assertEqual(self.conf.foo, 'foo') - self.assertEqual(self.conf.blaa.bar, 'bar') - - self.conf.reset() - - self.assertIsNone(self.conf.foo) - self.assertIsNone(self.conf.blaa.bar) - - -class UnregisterOptTestCase(BaseTestCase): - - def test_unregister_opt(self): - opts = [cfg.StrOpt('foo'), cfg.StrOpt('bar')] - - self.conf.register_opts(opts) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertTrue(hasattr(self.conf, 'bar')) - - self.conf.unregister_opt(opts[0]) - - self.assertFalse(hasattr(self.conf, 'foo')) - self.assertTrue(hasattr(self.conf, 'bar')) - - self.conf([]) - - self.assertRaises(cfg.ArgsAlreadyParsedError, - self.conf.unregister_opt, opts[1]) - - self.conf.clear() - - self.assertTrue(hasattr(self.conf, 'bar')) - - self.conf.unregister_opts(opts) - - def test_unregister_opt_from_group(self): - opt = cfg.StrOpt('foo') - - self.conf.register_opt(opt, group='blaa') - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - - self.conf.unregister_opt(opt, group='blaa') - - self.assertFalse(hasattr(self.conf.blaa, 'foo')) - - -class ImportOptTestCase(BaseTestCase): - - def test_import_opt(self): - self.assertFalse(hasattr(cfg.CONF, 'blaa')) - cfg.CONF.import_opt('blaa', 'tests.testmods.blaa_opt') - self.assertTrue(hasattr(cfg.CONF, 'blaa')) - - def test_import_opt_in_group(self): - self.assertFalse(hasattr(cfg.CONF, 'bar')) - cfg.CONF.import_opt('foo', 'tests.testmods.bar_foo_opt', group='bar') - self.assertTrue(hasattr(cfg.CONF, 'bar')) - self.assertTrue(hasattr(cfg.CONF.bar, 'foo')) - - def test_import_opt_import_errror(self): - self.assertRaises(ImportError, cfg.CONF.import_opt, - 'blaa', 'tests.testmods.blaablaa_opt') - - def test_import_opt_no_such_opt(self): - self.assertRaises(cfg.NoSuchOptError, cfg.CONF.import_opt, - 'blaablaa', 'tests.testmods.blaa_opt') - - def test_import_opt_no_such_group(self): - self.assertRaises(cfg.NoSuchGroupError, cfg.CONF.import_opt, - 'blaa', 'tests.testmods.blaa_opt', group='blaa') - - -class ImportGroupTestCase(BaseTestCase): - - def test_import_group(self): - self.assertFalse(hasattr(cfg.CONF, 'qux')) - cfg.CONF.import_group('qux', 'tests.testmods.baz_qux_opt') - self.assertTrue(hasattr(cfg.CONF, 'qux')) - self.assertTrue(hasattr(cfg.CONF.qux, 'baz')) - - def test_import_group_import_error(self): - self.assertRaises(ImportError, cfg.CONF.import_group, - 'qux', 'tests.testmods.bazzz_quxxx_opt') - - def test_import_group_no_such_group(self): - self.assertRaises(cfg.NoSuchGroupError, cfg.CONF.import_group, - 'quxxx', 'tests.testmods.baz_qux_opt') - - -class RequiredOptsTestCase(BaseTestCase): - - def setUp(self): - BaseTestCase.setUp(self) - self.conf.register_opt(cfg.StrOpt('boo', required=False)) - - def test_required_opt(self): - self.conf.register_opt(cfg.StrOpt('foo', required=True)) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - def test_required_cli_opt(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', required=True)) - - self.conf(['--foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - def test_required_cli_opt_with_dash(self): - self.conf.register_cli_opt(cfg.StrOpt('foo-bar', required=True)) - - self.conf(['--foo-bar', 'baz']) - - self.assertTrue(hasattr(self.conf, 'foo_bar')) - self.assertEqual(self.conf.foo_bar, 'baz') - - def test_missing_required_opt(self): - self.conf.register_opt(cfg.StrOpt('foo', required=True)) - self.assertRaises(cfg.RequiredOptError, self.conf, []) - - def test_missing_required_cli_opt(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', required=True)) - self.assertRaises(cfg.RequiredOptError, self.conf, []) - - def test_required_group_opt(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', required=True), group='blaa') - - paths = self.create_tempfiles([('test', - '[blaa]\n' - 'foo = bar')]) - - self.conf(['--config-file', paths[0]]) - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_required_cli_group_opt(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt( - cfg.StrOpt('foo', required=True), group='blaa') - - self.conf(['--blaa-foo', 'bar']) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'foo')) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_missing_required_group_opt(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', required=True), group='blaa') - self.assertRaises(cfg.RequiredOptError, self.conf, []) - - def test_missing_required_cli_group_opt(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt( - cfg.StrOpt('foo', required=True), group='blaa') - self.assertRaises(cfg.RequiredOptError, self.conf, []) - - def test_required_opt_with_default(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', required=True)) - self.conf.set_default('foo', 'bar') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - def test_required_opt_with_override(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', required=True)) - self.conf.set_override('foo', 'bar') - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - -class SadPathTestCase(BaseTestCase): - - def test_unknown_attr(self): - self.conf([]) - self.assertFalse(hasattr(self.conf, 'foo')) - self.assertRaises(AttributeError, getattr, self.conf, 'foo') - self.assertRaises(cfg.NoSuchOptError, self.conf._get, 'foo') - self.assertRaises(cfg.NoSuchOptError, self.conf.__getattr__, 'foo') - - def test_unknown_attr_is_attr_error(self): - self.conf([]) - self.assertFalse(hasattr(self.conf, 'foo')) - self.assertRaises(AttributeError, getattr, self.conf, 'foo') - - def test_unknown_group_attr(self): - self.conf.register_group(cfg.OptGroup('blaa')) - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertFalse(hasattr(self.conf.blaa, 'foo')) - self.assertRaises(cfg.NoSuchOptError, getattr, self.conf.blaa, 'foo') - - def test_ok_duplicate(self): - opt = cfg.StrOpt('foo') - self.conf.register_cli_opt(opt) - opt2 = cfg.StrOpt('foo') - self.conf.register_cli_opt(opt2) - - self.conf([]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertIsNone(self.conf.foo) - - def test_error_duplicate(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', help='bar')) - self.assertRaises(cfg.DuplicateOptError, - self.conf.register_cli_opt, cfg.StrOpt('foo')) - - def test_error_duplicate_with_different_dest(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', dest='f')) - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.assertRaises(cfg.DuplicateOptError, self.conf, []) - - def test_error_duplicate_short(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', short='f')) - self.conf.register_cli_opt(cfg.StrOpt('bar', short='f')) - self.assertRaises(cfg.DuplicateOptError, self.conf, []) - - def test_already_parsed(self): - self.conf([]) - - self.assertRaises(cfg.ArgsAlreadyParsedError, - self.conf.register_cli_opt, cfg.StrOpt('foo')) - - def test_bad_cli_arg(self): - self.conf.register_opt(cfg.BoolOpt('foo')) - - self.useFixture(fixtures.MonkeyPatch('sys.stderr', moves.StringIO())) - - self.assertRaises(SystemExit, self.conf, ['--foo']) - - self.assertTrue('error' in sys.stderr.getvalue()) - self.assertTrue('--foo' in sys.stderr.getvalue()) - - def _do_test_bad_cli_value(self, opt_class): - self.conf.register_cli_opt(opt_class('foo')) - - self.useFixture(fixtures.MonkeyPatch('sys.stderr', moves.StringIO())) - - self.assertRaises(SystemExit, self.conf, ['--foo', 'bar']) - - self.assertTrue('foo' in sys.stderr.getvalue()) - self.assertTrue('bar' in sys.stderr.getvalue()) - - def test_bad_int_arg(self): - self._do_test_bad_cli_value(cfg.IntOpt) - - def test_bad_float_arg(self): - self._do_test_bad_cli_value(cfg.FloatOpt) - - def test_conf_file_not_found(self): - (fd, path) = tempfile.mkstemp() - - os.remove(path) - - self.assertRaises(cfg.ConfigFilesNotFoundError, - self.conf, ['--config-file', path]) - - def test_conf_file_permission_denied(self): - (fd, path) = tempfile.mkstemp() - - os.chmod(path, 0x000) - - self.assertRaises(cfg.ConfigFilesPermissionDeniedError, - self.conf, ['--config-file', path]) - os.remove(path) - - def test_conf_file_broken(self): - paths = self.create_tempfiles([('test', 'foo')]) - - self.assertRaises(cfg.ConfigFileParseError, - self.conf, ['--config-file', paths[0]]) - - def _do_test_conf_file_bad_value(self, opt_class): - self.conf.register_opt(opt_class('foo')) - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertRaises(AttributeError, getattr, self.conf, 'foo') - self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo') - - def test_conf_file_bad_bool(self): - self._do_test_conf_file_bad_value(cfg.BoolOpt) - - def test_conf_file_bad_int(self): - self._do_test_conf_file_bad_value(cfg.IntOpt) - - def test_conf_file_bad_float(self): - self._do_test_conf_file_bad_value(cfg.FloatOpt) - - def test_str_sub_from_group(self): - self.conf.register_group(cfg.OptGroup('f')) - self.conf.register_cli_opt(cfg.StrOpt('oo', default='blaa'), group='f') - self.conf.register_cli_opt(cfg.StrOpt('bar', default='$f.oo')) - - self.conf([]) - - self.assertFalse(hasattr(self.conf, 'bar')) - self.assertRaises( - AttributeError, getattr, self.conf, 'bar') - self.assertRaises( - cfg.TemplateSubstitutionError, self.conf._get, 'bar') - - def test_set_default_unknown_attr(self): - self.conf([]) - self.assertRaises( - cfg.NoSuchOptError, self.conf.set_default, 'foo', 'bar') - - def test_set_default_unknown_group(self): - self.conf([]) - self.assertRaises(cfg.NoSuchGroupError, - self.conf.set_default, 'foo', 'bar', group='blaa') - - def test_set_override_unknown_attr(self): - self.conf([]) - self.assertRaises( - cfg.NoSuchOptError, self.conf.set_override, 'foo', 'bar') - - def test_set_override_unknown_group(self): - self.conf([]) - self.assertRaises(cfg.NoSuchGroupError, - self.conf.set_override, 'foo', 'bar', group='blaa') - - -class FindFileTestCase(BaseTestCase): - - def test_find_policy_file(self): - policy_file = '/etc/policy.json' - - self.useFixture(fixtures.MonkeyPatch( - 'os.path.exists', - lambda p: p == policy_file)) - - self.conf([]) - - self.assertIsNone(self.conf.find_file('foo.json')) - self.assertEqual(self.conf.find_file('policy.json'), policy_file) - - def test_find_policy_file_with_config_file(self): - dir = tempfile.mkdtemp() - self.tempdirs.append(dir) - - paths = self.create_tempfiles([(os.path.join(dir, 'test.conf'), - '[DEFAULT]'), - (os.path.join(dir, 'policy.json'), - '{}')], - ext='') - - self.conf(['--config-file', paths[0]]) - - self.assertEqual(self.conf.find_file('policy.json'), paths[1]) - - def test_find_policy_file_with_config_dir(self): - dir = tempfile.mkdtemp() - self.tempdirs.append(dir) - - path = self.create_tempfiles([(os.path.join(dir, 'policy.json'), - '{}')], - ext='')[0] - - self.conf(['--config-dir', dir]) - - self.assertEqual(self.conf.find_file('policy.json'), path) - - -class OptDumpingTestCase(BaseTestCase): - - class FakeLogger: - - def __init__(self, test_case, expected_lvl): - self.test_case = test_case - self.expected_lvl = expected_lvl - self.logged = [] - - def log(self, lvl, fmt, *args): - self.test_case.assertEqual(lvl, self.expected_lvl) - self.logged.append(fmt % args) - - def setUp(self): - super(OptDumpingTestCase, self).setUp() - self._args = ['--foo', 'this', '--blaa-bar', 'that', - '--blaa-key', 'admin', '--passwd', 'hush'] - - def _do_test_log_opt_values(self, args): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.conf.register_cli_opt(cfg.StrOpt('passwd', secret=True)) - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt(cfg.StrOpt('bar'), 'blaa') - self.conf.register_cli_opt(cfg.StrOpt('key', secret=True), 'blaa') - - self.conf(args) - - logger = self.FakeLogger(self, 666) - - self.conf.log_opt_values(logger, 666) - - self.assertEqual(logger.logged, [ - "*" * 80, - "Configuration options gathered from:", - "command line args: ['--foo', 'this', '--blaa-bar', " - "'that', '--blaa-key', 'admin', '--passwd', 'hush']", - "config files: []", - "=" * 80, - "config_dir = None", - "config_file = []", - "foo = this", - "passwd = ****", - "blaa.bar = that", - "blaa.key = ****", - "*" * 80, - ]) - - def test_log_opt_values(self): - self._do_test_log_opt_values(self._args) - - def test_log_opt_values_from_sys_argv(self): - self.useFixture(fixtures.MonkeyPatch('sys.argv', ['foo'] + self._args)) - self._do_test_log_opt_values(None) - - -class ConfigParserTestCase(BaseTestCase): - - def test_parse_file(self): - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n' - '[BLAA]\n' - 'bar = foo\n')]) - - sections = {} - parser = cfg.ConfigParser(paths[0], sections) - parser.parse() - - self.assertTrue('DEFAULT' in sections) - self.assertTrue('BLAA' in sections) - self.assertEqual(sections['DEFAULT']['foo'], ['bar']) - self.assertEqual(sections['BLAA']['bar'], ['foo']) - - def test_parse_file_with_normalized(self): - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n' - '[BLAA]\n' - 'bar = foo\n')]) - - sections = {} - normalized = {} - parser = cfg.ConfigParser(paths[0], sections) - parser._add_normalized(normalized) - parser.parse() - - self.assertTrue('DEFAULT' in sections) - self.assertTrue('DEFAULT' in normalized) - self.assertTrue('BLAA' in sections) - self.assertTrue('blaa' in normalized) - self.assertEqual(sections['DEFAULT']['foo'], ['bar']) - self.assertEqual(normalized['DEFAULT']['foo'], ['bar']) - self.assertEqual(sections['BLAA']['bar'], ['foo']) - self.assertEqual(normalized['blaa']['bar'], ['foo']) - - def test_no_section(self): - with tempfile.NamedTemporaryFile() as tmpfile: - tmpfile.write(six.b('foo = bar')) - tmpfile.flush() - - parser = cfg.ConfigParser(tmpfile.name, {}) - self.assertRaises(cfg.ParseError, parser.parse) - - def test__parse_file_ioerror(self): - # Test that IOErrors (other than 'No such file or directory') - # are propagated. - filename = 'fake' - namespace = mock.Mock() - with mock.patch('oslo_config.cfg.ConfigParser.parse') as parse: - parse.side_effect = IOError(errno.EMFILE, filename, - 'Too many open files') - self.assertRaises(IOError, cfg.ConfigParser._parse_file, filename, - namespace) - - -class MultiConfigParserTestCase(BaseTestCase): - - def test_parse_single_file(self): - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bar\n' - '[BLAA]\n' - 'bar = foo\n')]) - - parser = cfg.MultiConfigParser() - read_ok = parser.read(paths) - - self.assertEqual(read_ok, paths) - - self.assertTrue('DEFAULT' in parser.parsed[0]) - self.assertEqual(parser.parsed[0]['DEFAULT']['foo'], ['bar']) - self.assertEqual(parser.get([('DEFAULT', 'foo')]), ['bar']) - self.assertEqual(parser.get([('DEFAULT', 'foo')], multi=True), - ['bar']) - self.assertEqual(parser.get([('DEFAULT', 'foo')], multi=True), - ['bar']) - self.assertEqual(parser._get([('DEFAULT', 'foo')], - multi=True, normalized=True), - ['bar']) - - self.assertTrue('BLAA' in parser.parsed[0]) - self.assertEqual(parser.parsed[0]['BLAA']['bar'], ['foo']) - self.assertEqual(parser.get([('BLAA', 'bar')]), ['foo']) - self.assertEqual(parser.get([('BLAA', 'bar')], multi=True), - ['foo']) - self.assertEqual(parser._get([('blaa', 'bar')], - multi=True, normalized=True), - ['foo']) - - def test_parse_multiple_files(self): - paths = self.create_tempfiles([('test1', - '[DEFAULT]\n' - 'foo = bar\n' - '[BLAA]\n' - 'bar = foo'), - ('test2', - '[DEFAULT]\n' - 'foo = barbar\n' - '[BLAA]\n' - 'bar = foofoo\n' - '[bLAa]\n' - 'bar = foofoofoo\n')]) - - parser = cfg.MultiConfigParser() - read_ok = parser.read(paths) - - self.assertEqual(read_ok, paths) - - self.assertTrue('DEFAULT' in parser.parsed[0]) - self.assertEqual(parser.parsed[0]['DEFAULT']['foo'], ['barbar']) - self.assertTrue('DEFAULT' in parser.parsed[1]) - self.assertEqual(parser.parsed[1]['DEFAULT']['foo'], ['bar']) - self.assertEqual(parser.get([('DEFAULT', 'foo')]), ['barbar']) - self.assertEqual(parser.get([('DEFAULT', 'foo')], multi=True), - ['bar', 'barbar']) - - self.assertTrue('BLAA' in parser.parsed[0]) - self.assertTrue('bLAa' in parser.parsed[0]) - self.assertEqual(parser.parsed[0]['BLAA']['bar'], ['foofoo']) - self.assertEqual(parser.parsed[0]['bLAa']['bar'], ['foofoofoo']) - self.assertTrue('BLAA' in parser.parsed[1]) - self.assertEqual(parser.parsed[1]['BLAA']['bar'], ['foo']) - self.assertEqual(parser.get([('BLAA', 'bar')]), ['foofoo']) - self.assertEqual(parser.get([('bLAa', 'bar')]), ['foofoofoo']) - self.assertEqual(parser.get([('BLAA', 'bar')], multi=True), - ['foo', 'foofoo']) - self.assertEqual(parser._get([('BLAA', 'bar')], - multi=True, normalized=True), - ['foo', 'foofoo', 'foofoofoo']) - - -class TildeExpansionTestCase(BaseTestCase): - - def test_config_file_tilde(self): - homedir = os.path.expanduser('~') - tmpfile = tempfile.mktemp(dir=homedir, prefix='cfg-', suffix='.conf') - tmpbase = os.path.basename(tmpfile) - - try: - self.conf(['--config-file', os.path.join('~', tmpbase)]) - except cfg.ConfigFilesNotFoundError as cfnfe: - self.assertTrue(homedir in str(cfnfe)) - - self.useFixture(fixtures.MonkeyPatch( - 'os.path.exists', - lambda p: p == tmpfile)) - - self.assertEqual(self.conf.find_file(tmpbase), tmpfile) - - def test_config_dir_tilde(self): - homedir = os.path.expanduser('~') - try: - tmpdir = tempfile.mkdtemp(dir=homedir, - prefix='cfg-', - suffix='.d') - tmpfile = os.path.join(tmpdir, 'foo.conf') - - self.useFixture(fixtures.MonkeyPatch( - 'glob.glob', - lambda p: [tmpfile])) - - e = self.assertRaises(cfg.ConfigFilesNotFoundError, - self.conf, - ['--config-dir', - os.path.join('~', - os.path.basename(tmpdir))] - ) - self.assertIn(tmpdir, str(e)) - finally: - try: - shutil.rmtree(tmpdir) - except OSError as exc: - if exc.errno != 2: - raise - - -class SubCommandTestCase(BaseTestCase): - - def test_sub_command(self): - def add_parsers(subparsers): - sub = subparsers.add_parser('a') - sub.add_argument('bar', type=int) - - self.conf.register_cli_opt( - cfg.SubCommandOpt('cmd', handler=add_parsers)) - self.assertTrue(hasattr(self.conf, 'cmd')) - self.conf(['a', '10']) - self.assertTrue(hasattr(self.conf.cmd, 'name')) - self.assertTrue(hasattr(self.conf.cmd, 'bar')) - self.assertEqual(self.conf.cmd.name, 'a') - self.assertEqual(self.conf.cmd.bar, 10) - - def test_sub_command_with_parent(self): - def add_parsers(subparsers): - parent = argparse.ArgumentParser(add_help=False) - parent.add_argument('bar', type=int) - subparsers.add_parser('a', parents=[parent]) - - self.conf.register_cli_opt( - cfg.SubCommandOpt('cmd', handler=add_parsers)) - self.assertTrue(hasattr(self.conf, 'cmd')) - self.conf(['a', '10']) - self.assertTrue(hasattr(self.conf.cmd, 'name')) - self.assertTrue(hasattr(self.conf.cmd, 'bar')) - self.assertEqual(self.conf.cmd.name, 'a') - self.assertEqual(self.conf.cmd.bar, 10) - - def test_sub_command_with_dest(self): - def add_parsers(subparsers): - subparsers.add_parser('a') - - self.conf.register_cli_opt( - cfg.SubCommandOpt('cmd', dest='command', handler=add_parsers)) - self.assertTrue(hasattr(self.conf, 'command')) - self.conf(['a']) - self.assertEqual(self.conf.command.name, 'a') - - def test_sub_command_with_group(self): - def add_parsers(subparsers): - sub = subparsers.add_parser('a') - sub.add_argument('--bar', choices='XYZ') - - self.conf.register_cli_opt( - cfg.SubCommandOpt('cmd', handler=add_parsers), group='blaa') - self.assertTrue(hasattr(self.conf, 'blaa')) - self.assertTrue(hasattr(self.conf.blaa, 'cmd')) - self.conf(['a', '--bar', 'Z']) - self.assertTrue(hasattr(self.conf.blaa.cmd, 'name')) - self.assertTrue(hasattr(self.conf.blaa.cmd, 'bar')) - self.assertEqual(self.conf.blaa.cmd.name, 'a') - self.assertEqual(self.conf.blaa.cmd.bar, 'Z') - - def test_sub_command_not_cli(self): - self.conf.register_opt(cfg.SubCommandOpt('cmd')) - self.conf([]) - - def test_sub_command_resparse(self): - def add_parsers(subparsers): - subparsers.add_parser('a') - - self.conf.register_cli_opt( - cfg.SubCommandOpt('cmd', handler=add_parsers)) - - foo_opt = cfg.StrOpt('foo') - self.conf.register_cli_opt(foo_opt) - - self.conf(['--foo=bar', 'a']) - - self.assertTrue(hasattr(self.conf.cmd, 'name')) - self.assertEqual(self.conf.cmd.name, 'a') - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - - self.conf.clear() - self.conf.unregister_opt(foo_opt) - self.conf(['a']) - - self.assertTrue(hasattr(self.conf.cmd, 'name')) - self.assertEqual(self.conf.cmd.name, 'a') - self.assertFalse(hasattr(self.conf, 'foo')) - - def test_sub_command_no_handler(self): - self.conf.register_cli_opt(cfg.SubCommandOpt('cmd')) - self.useFixture(fixtures.MonkeyPatch('sys.stderr', moves.StringIO())) - self.assertRaises(SystemExit, self.conf, []) - self.assertTrue('error' in sys.stderr.getvalue()) - - def test_sub_command_with_help(self): - def add_parsers(subparsers): - subparsers.add_parser('a') - - self.conf.register_cli_opt(cfg.SubCommandOpt('cmd', - title='foo foo', - description='bar bar', - help='blaa blaa', - handler=add_parsers)) - self.useFixture(fixtures.MonkeyPatch('sys.stdout', moves.StringIO())) - self.assertRaises(SystemExit, self.conf, ['--help']) - self.assertTrue('foo foo' in sys.stdout.getvalue()) - self.assertTrue('bar bar' in sys.stdout.getvalue()) - self.assertTrue('blaa blaa' in sys.stdout.getvalue()) - - def test_sub_command_errors(self): - def add_parsers(subparsers): - sub = subparsers.add_parser('a') - sub.add_argument('--bar') - - self.conf.register_cli_opt(cfg.BoolOpt('bar')) - self.conf.register_cli_opt( - cfg.SubCommandOpt('cmd', handler=add_parsers)) - self.conf(['a']) - self.assertRaises(cfg.DuplicateOptError, getattr, self.conf.cmd, 'bar') - self.assertRaises(cfg.NoSuchOptError, getattr, self.conf.cmd, 'foo') - - def test_sub_command_multiple(self): - self.conf.register_cli_opt(cfg.SubCommandOpt('cmd1')) - self.conf.register_cli_opt(cfg.SubCommandOpt('cmd2')) - self.useFixture(fixtures.MonkeyPatch('sys.stderr', moves.StringIO())) - self.assertRaises(SystemExit, self.conf, []) - self.assertTrue('multiple' in sys.stderr.getvalue()) - - -class SetDefaultsTestCase(BaseTestCase): - - def test_default_to_none(self): - opts = [cfg.StrOpt('foo', default='foo')] - self.conf.register_opts(opts) - cfg.set_defaults(opts, foo=None) - self.conf([]) - self.assertIsNone(self.conf.foo) - - def test_default_from_none(self): - opts = [cfg.StrOpt('foo')] - self.conf.register_opts(opts) - cfg.set_defaults(opts, foo='bar') - self.conf([]) - self.assertEqual(self.conf.foo, 'bar') - - def test_change_default(self): - opts = [cfg.StrOpt('foo', default='foo')] - self.conf.register_opts(opts) - cfg.set_defaults(opts, foo='bar') - self.conf([]) - self.assertEqual(self.conf.foo, 'bar') - - def test_change_default_many(self): - opts = [cfg.StrOpt('foo', default='foo'), - cfg.StrOpt('foo2', default='foo2')] - self.conf.register_opts(opts) - cfg.set_defaults(opts, foo='bar', foo2='bar2') - self.conf([]) - self.assertEqual(self.conf.foo, 'bar') - self.assertEqual(self.conf.foo2, 'bar2') - - def test_group_default_to_none(self): - opts = [cfg.StrOpt('foo', default='foo')] - self.conf.register_opts(opts, group='blaa') - cfg.set_defaults(opts, foo=None) - self.conf([]) - self.assertIsNone(self.conf.blaa.foo) - - def test_group_default_from_none(self): - opts = [cfg.StrOpt('foo')] - self.conf.register_opts(opts, group='blaa') - cfg.set_defaults(opts, foo='bar') - self.conf([]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_group_change_default(self): - opts = [cfg.StrOpt('foo', default='foo')] - self.conf.register_opts(opts, group='blaa') - cfg.set_defaults(opts, foo='bar') - self.conf([]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - -class DeprecatedOptionsTestCase(BaseTestCase): - - def test_deprecated_opts_equal(self): - d1 = cfg.DeprecatedOpt('oldfoo', group='oldgroup') - d2 = cfg.DeprecatedOpt('oldfoo', group='oldgroup') - self.assertEqual(d1, d2) - - def test_deprecated_opts_not_equal(self): - d1 = cfg.DeprecatedOpt('oldfoo', group='oldgroup') - d2 = cfg.DeprecatedOpt('oldfoo2', group='oldgroup') - self.assertNotEqual(d1, d2) - - -class MultipleDeprecatedOptionsTestCase(BaseTestCase): - - def test_conf_file_override_use_deprecated_name_and_group(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_opt(cfg.StrOpt('foo', - deprecated_name='oldfoo', - deprecated_group='oldgroup'), - group='blaa') - - paths = self.create_tempfiles([('test', - '[oldgroup]\n' - 'oldfoo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_conf_file_override_use_deprecated_opts(self): - self.conf.register_group(cfg.OptGroup('blaa')) - oldopts = [cfg.DeprecatedOpt('oldfoo', group='oldgroup')] - self.conf.register_opt(cfg.StrOpt('foo', deprecated_opts=oldopts), - group='blaa') - - paths = self.create_tempfiles([('test', - '[oldgroup]\n' - 'oldfoo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_conf_file_override_use_deprecated_multi_opts(self): - self.conf.register_group(cfg.OptGroup('blaa')) - oldopts = [cfg.DeprecatedOpt('oldfoo', group='oldgroup'), - cfg.DeprecatedOpt('oldfoo2', group='oldgroup2')] - self.conf.register_opt(cfg.StrOpt('foo', deprecated_opts=oldopts), - group='blaa') - - paths = self.create_tempfiles([('test', - '[oldgroup2]\n' - 'oldfoo2 = bar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - -class MultipleDeprecatedCliOptionsTestCase(BaseTestCase): - - def test_conf_file_override_use_deprecated_name_and_group(self): - self.conf.register_group(cfg.OptGroup('blaa')) - self.conf.register_cli_opt(cfg.StrOpt('foo', - deprecated_name='oldfoo', - deprecated_group='oldgroup'), - group='blaa') - - paths = self.create_tempfiles([('test', - '[oldgroup]\n' - 'oldfoo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_conf_file_override_use_deprecated_opts(self): - self.conf.register_group(cfg.OptGroup('blaa')) - oldopts = [cfg.DeprecatedOpt('oldfoo', group='oldgroup')] - self.conf.register_cli_opt(cfg.StrOpt('foo', deprecated_opts=oldopts), - group='blaa') - - paths = self.create_tempfiles([('test', - '[oldgroup]\n' - 'oldfoo = bar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_conf_file_override_use_deprecated_multi_opts(self): - self.conf.register_group(cfg.OptGroup('blaa')) - oldopts = [cfg.DeprecatedOpt('oldfoo', group='oldgroup'), - cfg.DeprecatedOpt('oldfoo2', group='oldgroup2')] - self.conf.register_cli_opt(cfg.StrOpt('foo', deprecated_opts=oldopts), - group='blaa') - - paths = self.create_tempfiles([('test', - '[oldgroup2]\n' - 'oldfoo2 = bar\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.blaa.foo, 'bar') - - def test_conf_file_common_deprecated_group(self): - self.conf.register_group(cfg.OptGroup('foo')) - self.conf.register_group(cfg.OptGroup('bar')) - oldopts = [cfg.DeprecatedOpt('foo', group='DEFAULT')] - self.conf.register_opt(cfg.StrOpt('common_opt', - deprecated_opts=oldopts), - group='bar') - self.conf.register_opt(cfg.StrOpt('common_opt', - deprecated_opts=oldopts), - group='foo') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bla\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.foo.common_opt, 'bla') - self.assertEqual(self.conf.bar.common_opt, 'bla') - - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' - 'foo = bla\n' - '[bar]\n' - 'common_opt = blabla\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.foo.common_opt, 'bla') - self.assertEqual(self.conf.bar.common_opt, 'blabla') - - paths = self.create_tempfiles([('test', - '[foo]\n' - 'common_opt = bla\n' - '[bar]\n' - 'common_opt = blabla\n')]) - - self.conf(['--config-file', paths[0]]) - self.assertEqual(self.conf.foo.common_opt, 'bla') - self.assertEqual(self.conf.bar.common_opt, 'blabla') - - -class ChoicesTestCase(BaseTestCase): - - def test_choice_default(self): - self.conf.register_cli_opt(cfg.StrOpt('protocol', - default='http', - choices=['http', 'https', 'ftp'])) - self.conf([]) - self.assertEqual(self.conf.protocol, 'http') - - def test_choice_good(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', - choices=['bar1', 'bar2'])) - self.conf(['--foo', 'bar1']) - self.assertEqual(self.conf.foo, 'bar1') - - def test_choice_bad(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', - choices=['bar1', 'bar2'])) - self.assertRaises(SystemExit, self.conf, ['--foo', 'bar3']) - - def test_conf_file_choice_value(self): - self.conf.register_opt(cfg.StrOpt('foo', - choices=['bar1', 'bar2'])) - - paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = bar1\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar1') - - def test_conf_file_choice_empty_value(self): - self.conf.register_opt(cfg.StrOpt('foo', - choices=['', 'bar1', 'bar2'])) - - paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = \n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, '') - - def test_conf_file_choice_none_value(self): - self.conf.register_opt(cfg.StrOpt('foo', - default=None, - choices=[None, 'bar1', 'bar2'])) - - paths = self.create_tempfiles([('test', '[DEFAULT]\n''\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, None) - - def test_conf_file_bad_choice_value(self): - self.conf.register_opt(cfg.StrOpt('foo', - choices=['bar1', 'bar2'])) - - paths = self.create_tempfiles([('test', '[DEFAULT]\n''foo = bar3\n')]) - - self.conf(['--config-file', paths[0]]) - - self.assertRaises(cfg.ConfigFileValueError, self.conf._get, 'foo') - self.assertRaises(AttributeError, getattr, self.conf, 'foo') - - def test_conf_file_choice_value_override(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', - choices=['baar', 'baaar'])) - - paths = self.create_tempfiles([('1', - '[DEFAULT]\n' - 'foo = baar\n'), - ('2', - '[DEFAULT]\n' - 'foo = baaar\n')]) - - self.conf(['--foo', 'baar', - '--config-file', paths[0], - '--config-file', paths[1]]) - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'baaar') - - def test_conf_file_choice_bad_default(self): - self.conf.register_cli_opt(cfg.StrOpt('foo', - choices=['baar', 'baaar'], - default='foobaz')) - self.conf([]) - self.assertRaises(AttributeError, - getattr, - self.conf, - 'foobaz') - - -class PrintHelpTestCase(base.BaseTestCase): - - def test_print_help_without_init(self): - conf = cfg.ConfigOpts() - conf.register_opts([]) - self.assertRaises(cfg.NotInitializedError, - conf.print_help) - - def test_print_help_with_clear(self): - conf = cfg.ConfigOpts() - conf.register_opts([]) - conf([]) - conf.clear() - self.assertRaises(cfg.NotInitializedError, - conf.print_help) - - -class OptTestCase(base.BaseTestCase): - - def test_opt_eq(self): - d1 = cfg.ListOpt('oldfoo') - d2 = cfg.ListOpt('oldfoo') - self.assertEqual(d1, d2) - - def test_opt_not_eq(self): - d1 = cfg.ListOpt('oldfoo') - d2 = cfg.ListOpt('oldbar') - self.assertNotEqual(d1, d2) - - def test_illegal_name(self): - self.assertRaises(ValueError, cfg.BoolOpt, '_foo') - - -class SectionsTestCase(base.BaseTestCase): - def test_list_all_sections(self): - paths = self.create_tempfiles([('test.ini', - '[DEFAULT]\n' - 'foo = bar\n' - '[BLAA]\n' - 'bar = foo\n')]) - config = cfg.ConfigOpts() - config(args=[], default_config_files=[paths[0]]) - sections = set(config.list_all_sections()) - self.assertEqual(sections, set(['DEFAULT', 'BLAA'])) - - -class DeprecationWarningTestBase(BaseTestCase): - def setUp(self): - super(DeprecationWarningTestBase, self).setUp() - self.log_fixture = self.useFixture(fixtures.FakeLogger()) - self._parser_class = cfg.MultiConfigParser - - -class DeprecationWarningTestScenarios(DeprecationWarningTestBase): - scenarios = [('default-deprecated', dict(deprecated=True, - group='DEFAULT')), - ('default-not-deprecated', dict(deprecated=False, - group='DEFAULT')), - ('other-deprecated', dict(deprecated=True, - group='other')), - ('other-not-deprecated', dict(deprecated=False, - group='other')), - ] - - def test_deprecated_logging(self): - self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='bar')) - self.conf.register_group(cfg.OptGroup('other')) - self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='bar'), - group='other') - if self.deprecated: - content = 'bar=baz' - else: - content = 'foo=baz' - paths = self.create_tempfiles([('test', - '[' + self.group + ']\n' + - content + '\n')]) - - self.conf(['--config-file', paths[0]]) - # Reference these twice to verify they only get logged once - if self.group == 'DEFAULT': - self.assertEqual('baz', self.conf.foo) - self.assertEqual('baz', self.conf.foo) - else: - self.assertEqual('baz', self.conf.other.foo) - self.assertEqual('baz', self.conf.other.foo) - if self.deprecated: - expected = (self._parser_class._deprecated_opt_message % - ('bar', self.group, 'foo', self.group) + '\n') - else: - expected = '' - self.assertEqual(expected, self.log_fixture.output) - - -class DeprecationWarningTests(DeprecationWarningTestBase): - def test_DeprecatedOpt(self): - default_deprecated = [cfg.DeprecatedOpt('bar')] - other_deprecated = [cfg.DeprecatedOpt('baz', group='other')] - self.conf.register_group(cfg.OptGroup('other')) - self.conf.register_opt(cfg.StrOpt('foo', - deprecated_opts=default_deprecated)) - self.conf.register_opt(cfg.StrOpt('foo', - deprecated_opts=other_deprecated), - group='other') - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' + - 'bar=baz\n' + - '[other]\n' + - 'baz=baz\n')]) - self.conf(['--config-file', paths[0]]) - self.assertEqual('baz', self.conf.foo) - self.assertEqual('baz', self.conf.other.foo) - self.assertIn('Option "bar" from group "DEFAULT"', - self.log_fixture.output) - self.assertIn('Option "baz" from group "other"', - self.log_fixture.output) - - def test_check_deprecated_default_none(self): - parser = self._parser_class() - deprecated_list = [(None, 'bar')] - parser._check_deprecated(('DEFAULT', 'bar'), (None, 'foo'), - deprecated_list) - self.assert_message_logged('bar', 'DEFAULT', 'foo', 'DEFAULT') - # Make sure check_deprecated didn't modify the list passed in - self.assertEqual([(None, 'bar')], deprecated_list) - - def test_check_deprecated_none_default(self): - parser = self._parser_class() - deprecated_list = [('DEFAULT', 'bar')] - parser._check_deprecated((None, 'bar'), ('DEFAULT', 'foo'), - deprecated_list) - self.assert_message_logged('bar', 'DEFAULT', 'foo', 'DEFAULT') - # Make sure check_deprecated didn't modify the list passed in - self.assertEqual([('DEFAULT', 'bar')], deprecated_list) - - def assert_message_logged(self, deprecated_name, deprecated_group, - current_name, current_group): - expected = (self._parser_class._deprecated_opt_message % - (deprecated_name, deprecated_group, - current_name, current_group) - ) - self.assertEqual(expected + '\n', self.log_fixture.output) - - def test_deprecated_for_removal(self): - self.conf.register_opt(cfg.StrOpt('foo', - deprecated_for_removal=True)) - self.conf.register_opt(cfg.StrOpt('bar', - deprecated_for_removal=True)) - paths = self.create_tempfiles([('test', - '[DEFAULT]\n' + - 'foo=bar\n')]) - self.conf(['--config-file', paths[0]]) - # Multiple references should be logged only once. - self.assertEqual('bar', self.conf.foo) - self.assertEqual('bar', self.conf.foo) - # Options not set in the config should not be logged. - self.assertEqual(None, self.conf.bar) - expected = ('Option "foo" from group "DEFAULT" is deprecated for ' - 'removal. Its value may be silently ignored in the ' - 'future.\n') - self.assertEqual(expected, self.log_fixture.output) - - def test_deprecated_for_removal_with_group(self): - self.conf.register_group(cfg.OptGroup('other')) - self.conf.register_opt(cfg.StrOpt('foo', - deprecated_for_removal=True), - group='other') - self.conf.register_opt(cfg.StrOpt('bar', - deprecated_for_removal=True), - group='other') - paths = self.create_tempfiles([('test', - '[other]\n' + - 'foo=bar\n')]) - self.conf(['--config-file', paths[0]]) - # Multiple references should be logged only once. - self.assertEqual('bar', self.conf.other.foo) - self.assertEqual('bar', self.conf.other.foo) - # Options not set in the config should not be logged. - self.assertEqual(None, self.conf.other.bar) - expected = ('Option "foo" from group "other" is deprecated for ' - 'removal. Its value may be silently ignored in the ' - 'future.\n') - self.assertEqual(expected, self.log_fixture.output) diff --git a/awx/lib/site-packages/oslo_config/tests/test_cfgfilter.py b/awx/lib/site-packages/oslo_config/tests/test_cfgfilter.py deleted file mode 100644 index 6353ce6d91..0000000000 --- a/awx/lib/site-packages/oslo_config/tests/test_cfgfilter.py +++ /dev/null @@ -1,330 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base - -from oslo_config import cfg -from oslo_config import cfgfilter - - -class BaseTestCase(test_base.BaseTestCase): - - def setUp(self, conf=None): - super(BaseTestCase, self).setUp() - if conf is None: - self.conf = cfg.ConfigOpts() - else: - self.conf = conf - self.fconf = cfgfilter.ConfigFilter(self.conf) - - -class RegisterTestCase(BaseTestCase): - - def test_register_opt_default(self): - self.fconf.register_opt(cfg.StrOpt('foo', default='bar')) - - self.assertEqual('bar', self.fconf.foo) - self.assertEqual('bar', self.fconf['foo']) - self.assertIn('foo', self.fconf) - self.assertEqual(['foo'], list(self.fconf)) - self.assertEqual(1, len(self.fconf)) - - self.assertNotIn('foo', self.conf) - self.assertEqual(0, len(self.conf)) - self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'foo') - - def test_register_opt_none_default(self): - self.fconf.register_opt(cfg.StrOpt('foo')) - - self.assertIsNone(self.fconf.foo) - self.assertIsNone(self.fconf['foo']) - self.assertIn('foo', self.fconf) - self.assertEqual(['foo'], list(self.fconf)) - self.assertEqual(1, len(self.fconf)) - - self.assertNotIn('foo', self.conf) - self.assertEqual(0, len(self.conf)) - self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'foo') - - def test_register_grouped_opt_default(self): - self.fconf.register_opt(cfg.StrOpt('foo', default='bar'), - group='blaa') - - self.assertEqual('bar', self.fconf.blaa.foo) - self.assertEqual('bar', self.fconf['blaa']['foo']) - self.assertIn('blaa', self.fconf) - self.assertIn('foo', self.fconf.blaa) - self.assertEqual(['blaa'], list(self.fconf)) - self.assertEqual(['foo'], list(self.fconf.blaa)) - self.assertEqual(1, len(self.fconf)) - self.assertEqual(1, len(self.fconf.blaa)) - - self.assertNotIn('blaa', self.conf) - self.assertEqual(0, len(self.conf)) - self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'blaa') - - def test_register_grouped_opt_none_default(self): - self.fconf.register_opt(cfg.StrOpt('foo'), group='blaa') - - self.assertIsNone(self.fconf.blaa.foo) - self.assertIsNone(self.fconf['blaa']['foo']) - self.assertIn('blaa', self.fconf) - self.assertIn('foo', self.fconf.blaa) - self.assertEqual(['blaa'], list(self.fconf)) - self.assertEqual(['foo'], list(self.fconf.blaa)) - self.assertEqual(1, len(self.fconf)) - self.assertEqual(1, len(self.fconf.blaa)) - - self.assertNotIn('blaa', self.conf) - self.assertEqual(0, len(self.conf)) - self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'blaa') - - def test_register_group(self): - group = cfg.OptGroup('blaa') - self.fconf.register_group(group) - self.fconf.register_opt(cfg.StrOpt('foo'), group=group) - - self.assertIsNone(self.fconf.blaa.foo) - self.assertIsNone(self.fconf['blaa']['foo']) - self.assertIn('blaa', self.fconf) - self.assertIn('foo', self.fconf.blaa) - self.assertEqual(['blaa'], list(self.fconf)) - self.assertEqual(['foo'], list(self.fconf.blaa)) - self.assertEqual(1, len(self.fconf)) - self.assertEqual(1, len(self.fconf.blaa)) - - self.assertNotIn('blaa', self.conf) - self.assertEqual(0, len(self.conf)) - self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'blaa') - - def test_register_opts(self): - self.fconf.register_opts([cfg.StrOpt('foo'), - cfg.StrOpt('bar')]) - self.assertIn('foo', self.fconf) - self.assertIn('bar', self.fconf) - self.assertNotIn('foo', self.conf) - self.assertNotIn('bar', self.conf) - - def test_register_cli_opt(self): - self.fconf.register_cli_opt(cfg.StrOpt('foo')) - self.assertIn('foo', self.fconf) - self.assertNotIn('foo', self.conf) - - def test_register_cli_opts(self): - self.fconf.register_cli_opts([cfg.StrOpt('foo'), cfg.StrOpt('bar')]) - self.assertIn('foo', self.fconf) - self.assertIn('bar', self.fconf) - self.assertNotIn('foo', self.conf) - self.assertNotIn('bar', self.conf) - - def test_register_opts_grouped(self): - self.fconf.register_opts([cfg.StrOpt('foo'), cfg.StrOpt('bar')], - group='blaa') - self.assertIn('foo', self.fconf.blaa) - self.assertIn('bar', self.fconf.blaa) - self.assertNotIn('blaa', self.conf) - - def test_register_cli_opt_grouped(self): - self.fconf.register_cli_opt(cfg.StrOpt('foo'), group='blaa') - self.assertIn('foo', self.fconf.blaa) - self.assertNotIn('blaa', self.conf) - - def test_register_cli_opts_grouped(self): - self.fconf.register_cli_opts([cfg.StrOpt('foo'), cfg.StrOpt('bar')], - group='blaa') - self.assertIn('foo', self.fconf.blaa) - self.assertIn('bar', self.fconf.blaa) - self.assertNotIn('blaa', self.conf) - - def test_unknown_opt(self): - self.assertNotIn('foo', self.fconf) - self.assertEqual(0, len(self.fconf)) - self.assertRaises(cfg.NoSuchOptError, getattr, self.fconf, 'foo') - self.assertNotIn('blaa', self.conf) - - def test_blocked_opt(self): - self.conf.register_opt(cfg.StrOpt('foo')) - - self.assertIn('foo', self.conf) - self.assertEqual(1, len(self.conf)) - self.assertIsNone(self.conf.foo) - self.assertNotIn('foo', self.fconf) - self.assertEqual(0, len(self.fconf)) - self.assertRaises(cfg.NoSuchOptError, getattr, self.fconf, 'foo') - - def test_already_registered_opt(self): - self.conf.register_opt(cfg.StrOpt('foo')) - self.fconf.register_opt(cfg.StrOpt('foo')) - - self.assertIn('foo', self.conf) - self.assertEqual(1, len(self.conf)) - self.assertIsNone(self.conf.foo) - self.assertIn('foo', self.fconf) - self.assertEqual(1, len(self.fconf)) - self.assertIsNone(self.fconf.foo) - - self.conf.set_override('foo', 'bar') - - self.assertEqual('bar', self.conf.foo) - self.assertEqual('bar', self.fconf.foo) - - def test_already_registered_opts(self): - self.conf.register_opts([cfg.StrOpt('foo'), - cfg.StrOpt('fu')]) - self.fconf.register_opts([cfg.StrOpt('foo'), - cfg.StrOpt('bu')]) - - self.assertIn('foo', self.conf) - self.assertIn('fu', self.conf) - self.assertNotIn('bu', self.conf) - self.assertEqual(2, len(self.conf)) - self.assertIsNone(self.conf.foo) - self.assertIsNone(self.conf.fu) - self.assertIn('foo', self.fconf) - self.assertIn('bu', self.fconf) - self.assertNotIn('fu', self.fconf) - self.assertEqual(2, len(self.fconf)) - self.assertIsNone(self.fconf.foo) - self.assertIsNone(self.fconf.bu) - - self.conf.set_override('foo', 'bar') - - self.assertEqual('bar', self.conf.foo) - self.assertEqual('bar', self.fconf.foo) - - def test_already_registered_cli_opt(self): - self.conf.register_cli_opt(cfg.StrOpt('foo')) - self.fconf.register_cli_opt(cfg.StrOpt('foo')) - - self.assertIn('foo', self.conf) - self.assertEqual(1, len(self.conf)) - self.assertIsNone(self.conf.foo) - self.assertIn('foo', self.fconf) - self.assertEqual(1, len(self.fconf)) - self.assertIsNone(self.fconf.foo) - - self.conf.set_override('foo', 'bar') - - self.assertEqual('bar', self.conf.foo) - self.assertEqual('bar', self.fconf.foo) - - def test_already_registered_cli_opts(self): - self.conf.register_cli_opts([cfg.StrOpt('foo'), - cfg.StrOpt('fu')]) - self.fconf.register_cli_opts([cfg.StrOpt('foo'), - cfg.StrOpt('bu')]) - - self.assertIn('foo', self.conf) - self.assertIn('fu', self.conf) - self.assertNotIn('bu', self.conf) - self.assertEqual(2, len(self.conf)) - self.assertIsNone(self.conf.foo) - self.assertIsNone(self.conf.fu) - self.assertIn('foo', self.fconf) - self.assertIn('bu', self.fconf) - self.assertNotIn('fu', self.fconf) - self.assertEqual(2, len(self.fconf)) - self.assertIsNone(self.fconf.foo) - self.assertIsNone(self.fconf.bu) - - self.conf.set_override('foo', 'bar') - - self.assertEqual('bar', self.conf.foo) - self.assertEqual('bar', self.fconf.foo) - - -class ImportTestCase(BaseTestCase): - - def setUp(self): - super(ImportTestCase, self).setUp(cfg.CONF) - - def test_import_opt(self): - self.assertFalse(hasattr(self.conf, 'fblaa')) - self.conf.import_opt('fblaa', 'tests.testmods.fblaa_opt') - self.assertTrue(hasattr(self.conf, 'fblaa')) - self.assertFalse(hasattr(self.fconf, 'fblaa')) - self.fconf.import_opt('fblaa', 'tests.testmods.fblaa_opt') - self.assertTrue(hasattr(self.fconf, 'fblaa')) - - def test_import_opt_in_group(self): - self.assertFalse(hasattr(self.conf, 'fbar')) - self.conf.import_opt('foo', 'tests.testmods.fbar_foo_opt', - group='fbar') - self.assertTrue(hasattr(self.conf, 'fbar')) - self.assertTrue(hasattr(self.conf.fbar, 'foo')) - self.assertFalse(hasattr(self.fconf, 'fbar')) - self.fconf.import_opt('foo', 'tests.testmods.fbar_foo_opt', - group='fbar') - self.assertTrue(hasattr(self.fconf, 'fbar')) - self.assertTrue(hasattr(self.fconf.fbar, 'foo')) - - def test_import_group(self): - self.assertFalse(hasattr(self.conf, 'fbaar')) - self.conf.import_group('fbaar', 'tests.testmods.fbaar_baa_opt') - self.assertTrue(hasattr(self.conf, 'fbaar')) - self.assertTrue(hasattr(self.conf.fbaar, 'baa')) - self.assertFalse(hasattr(self.fconf, 'fbaar')) - self.fconf.import_group('fbaar', 'tests.testmods.fbaar_baa_opt') - self.assertTrue(hasattr(self.fconf, 'fbaar')) - self.assertTrue(hasattr(self.fconf.fbaar, 'baa')) - - -class ExposeTestCase(BaseTestCase): - - def test_expose_opt(self): - self.assertFalse(hasattr(self.conf, 'foo')) - self.assertFalse(hasattr(self.fconf, 'foo')) - - self.conf.register_opt(cfg.StrOpt('foo')) - self.conf.set_override('foo', 'bar') - - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertEqual(self.conf.foo, 'bar') - self.assertFalse(hasattr(self.fconf, 'foo')) - - self.fconf.expose_opt('foo') - self.assertTrue(hasattr(self.conf, 'foo')) - self.assertTrue(hasattr(self.fconf, 'foo')) - self.assertEqual(self.fconf.foo, 'bar') - - def test_expose_opt_with_group(self): - self.assertFalse(hasattr(self.conf, 'foo')) - self.assertFalse(hasattr(self.fconf, 'foo')) - - self.conf.register_opt(cfg.StrOpt('foo'), group='group') - self.conf.set_override('foo', 'bar', group='group') - - self.assertTrue(hasattr(self.conf.group, 'foo')) - self.assertEqual(self.conf.group.foo, 'bar') - self.assertFalse(hasattr(self.fconf, 'group')) - - self.fconf.expose_opt('foo', group='group') - self.assertTrue(hasattr(self.conf.group, 'foo')) - self.assertTrue(hasattr(self.fconf.group, 'foo')) - self.assertEqual(self.fconf.group.foo, 'bar') - - def test_expose_group(self): - self.conf.register_opts([cfg.StrOpt('foo'), - cfg.StrOpt('bar')], group='group') - self.conf.register_opts([cfg.StrOpt('foo'), - cfg.StrOpt('bar')], group='another') - self.conf.set_override('foo', 'a', group='group') - self.conf.set_override('bar', 'b', group='group') - - self.fconf.expose_group('group') - - self.assertEqual('a', self.fconf.group.foo) - self.assertEqual('b', self.fconf.group.bar) - self.assertFalse(hasattr(self.fconf, 'another')) - self.assertTrue(hasattr(self.conf, 'another')) diff --git a/awx/lib/site-packages/oslo_config/tests/test_fixture.py b/awx/lib/site-packages/oslo_config/tests/test_fixture.py deleted file mode 100644 index 6d8b2a7b2a..0000000000 --- a/awx/lib/site-packages/oslo_config/tests/test_fixture.py +++ /dev/null @@ -1,87 +0,0 @@ -# -# Copyright 2013 Mirantis, Inc. -# Copyright 2013 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base - -from oslo_config import cfg -from oslo_config import fixture as config - -conf = cfg.CONF - - -class ConfigTestCase(base.BaseTestCase): - def setUp(self): - super(ConfigTestCase, self).setUp() - self.config_fixture = self.useFixture(config.Config(conf)) - self.config = self.config_fixture.config - self.config_fixture.register_opt(cfg.StrOpt( - 'testing_option', default='initial_value')) - - def test_overridden_value(self): - self.assertEqual(conf.get('testing_option'), 'initial_value') - self.config(testing_option='changed_value') - self.assertEqual(conf.get('testing_option'), - self.config_fixture.conf.get('testing_option')) - - def test_cleanup(self): - self.config(testing_option='changed_value') - self.assertEqual(self.config_fixture.conf.get('testing_option'), - 'changed_value') - self.config_fixture.conf.reset() - self.assertEqual(conf.get('testing_option'), 'initial_value') - - def test_register_option(self): - opt = cfg.StrOpt('new_test_opt', default='initial_value') - self.config_fixture.register_opt(opt) - self.assertEqual(conf.get('new_test_opt'), - opt.default) - - def test_register_options(self): - opt1 = cfg.StrOpt('first_test_opt', default='initial_value_1') - opt2 = cfg.StrOpt('second_test_opt', default='initial_value_2') - self.config_fixture.register_opts([opt1, opt2]) - self.assertEqual(conf.get('first_test_opt'), opt1.default) - self.assertEqual(conf.get('second_test_opt'), opt2.default) - - def test_cleanup_unregister_option(self): - opt = cfg.StrOpt('new_test_opt', default='initial_value') - self.config_fixture.register_opt(opt) - self.assertEqual(conf.get('new_test_opt'), - opt.default) - self.config_fixture.cleanUp() - self.assertRaises(cfg.NoSuchOptError, conf.get, 'new_test_opt') - - def test_register_cli_option(self): - opt = cfg.StrOpt('new_test_opt', default='initial_value') - self.config_fixture.register_cli_opt(opt) - self.assertEqual(conf.get('new_test_opt'), - opt.default) - - def test_register_cli_options(self): - opt1 = cfg.StrOpt('first_test_opt', default='initial_value_1') - opt2 = cfg.StrOpt('second_test_opt', default='initial_value_2') - self.config_fixture.register_cli_opts([opt1, opt2]) - self.assertEqual(conf.get('first_test_opt'), opt1.default) - self.assertEqual(conf.get('second_test_opt'), opt2.default) - - def test_cleanup_unregister_cli_option(self): - opt = cfg.StrOpt('new_test_opt', default='initial_value') - self.config_fixture.register_cli_opt(opt) - self.assertEqual(conf.get('new_test_opt'), - opt.default) - self.config_fixture.cleanUp() - self.assertRaises(cfg.NoSuchOptError, conf.get, 'new_test_opt') diff --git a/awx/lib/site-packages/oslo_config/tests/test_generator.py b/awx/lib/site-packages/oslo_config/tests/test_generator.py deleted file mode 100644 index 144a4f8198..0000000000 --- a/awx/lib/site-packages/oslo_config/tests/test_generator.py +++ /dev/null @@ -1,583 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -import fixtures -import mock -from oslotest import base -from six import moves -import testscenarios - -from oslo_config import cfg -from oslo_config import fixture as config_fixture -from oslo_config import generator - -load_tests = testscenarios.load_tests_apply_scenarios - - -class GeneratorTestCase(base.BaseTestCase): - - opts = { - 'foo': cfg.StrOpt('foo', help='foo option'), - 'bar': cfg.StrOpt('bar', help='bar option'), - 'foo-bar': cfg.StrOpt('foo-bar', help='foobar'), - 'no_help': cfg.StrOpt('no_help'), - 'long_help': cfg.StrOpt('long_help', - help='Lorem ipsum dolor sit amet, consectetur ' - 'adipisicing elit, sed do eiusmod tempor ' - 'incididunt ut labore et dolore magna ' - 'aliqua. Ut enim ad minim veniam, quis ' - 'nostrud exercitation ullamco laboris ' - 'nisi ut aliquip ex ea commodo ' - 'consequat. Duis aute irure dolor in ' - 'reprehenderit in voluptate velit esse ' - 'cillum dolore eu fugiat nulla ' - 'pariatur. Excepteur sint occaecat ' - 'cupidatat non proident, sunt in culpa ' - 'qui officia deserunt mollit anim id est ' - 'laborum.'), - 'choices_opt': cfg.StrOpt('choices_opt', - default='a', - choices=(None, '', 'a', 'b', 'c'), - help='a string with choices'), - 'deprecated_opt': cfg.StrOpt('bar', - deprecated_name='foobar', - help='deprecated'), - 'deprecated_group': cfg.StrOpt('bar', - deprecated_group='group1', - deprecated_name='foobar', - help='deprecated'), - # Unknown Opt default must be a string - 'unknown_type': cfg.Opt('unknown_opt', - default='123', - help='unknown'), - 'str_opt': cfg.StrOpt('str_opt', - default='foo bar', - help='a string'), - 'str_opt_sample_default': cfg.StrOpt('str_opt', - default='fooishbar', - help='a string'), - 'str_opt_with_space': cfg.StrOpt('str_opt', - default=' foo bar ', - help='a string with spaces'), - 'bool_opt': cfg.BoolOpt('bool_opt', - default=False, - help='a boolean'), - 'int_opt': cfg.IntOpt('int_opt', - default=10, - help='an integer'), - 'float_opt': cfg.FloatOpt('float_opt', - default=0.1, - help='a float'), - 'list_opt': cfg.ListOpt('list_opt', - default=['1', '2', '3'], - help='a list'), - 'dict_opt': cfg.DictOpt('dict_opt', - default={'1': 'yes', '2': 'no'}, - help='a dict'), - 'multi_opt': cfg.MultiStrOpt('multi_opt', - default=['1', '2', '3'], - help='multiple strings'), - 'multi_opt_none': cfg.MultiStrOpt('multi_opt_none', - help='multiple strings'), - 'multi_opt_empty': cfg.MultiStrOpt('multi_opt_empty', - default=[], - help='multiple strings'), - 'multi_opt_sample_default': cfg.MultiStrOpt('multi_opt', - default=['1', '2', '3'], - sample_default=['5', '6'], - help='multiple strings'), - } - - content_scenarios = [ - ('empty', - dict(opts=[], expected='''[DEFAULT] -''')), - ('single_namespace', - dict(opts=[('test', [(None, [opts['foo']])])], - expected='''[DEFAULT] - -# -# From test -# - -# foo option (string value) -#foo = -''')), - ('multiple_namespaces', - dict(opts=[('test', [(None, [opts['foo']])]), - ('other', [(None, [opts['bar']])])], - expected='''[DEFAULT] - -# -# From other -# - -# bar option (string value) -#bar = - -# -# From test -# - -# foo option (string value) -#foo = -''')), - ('group', - dict(opts=[('test', [('group1', [opts['foo']])])], - expected='''[DEFAULT] - - -[group1] - -# -# From test -# - -# foo option (string value) -#foo = -''')), - ('empty_group', - dict(opts=[('test', [('group1', [])])], - expected='''[DEFAULT] -''')), - ('multiple_groups', - dict(opts=[('test', [('group1', [opts['foo']]), - ('group2', [opts['bar']])])], - expected='''[DEFAULT] - - -[group1] - -# -# From test -# - -# foo option (string value) -#foo = - - -[group2] - -# -# From test -# - -# bar option (string value) -#bar = -''')), - ('group_in_multiple_namespaces', - dict(opts=[('test', [('group1', [opts['foo']])]), - ('other', [('group1', [opts['bar']])])], - expected='''[DEFAULT] - - -[group1] - -# -# From other -# - -# bar option (string value) -#bar = - -# -# From test -# - -# foo option (string value) -#foo = -''')), - ('hyphenated_name', - dict(opts=[('test', [(None, [opts['foo-bar']])])], - expected='''[DEFAULT] - -# -# From test -# - -# foobar (string value) -#foo_bar = -''')), - ('no_help', - dict(opts=[('test', [(None, [opts['no_help']])])], - log_warning=('"%s" is missing a help string', 'no_help'), - expected='''[DEFAULT] - -# -# From test -# - -# (string value) -#no_help = -''')), - ('long_help', - dict(opts=[('test', [(None, [opts['long_help']])])], - expected='''[DEFAULT] - -# -# From test -# - -# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do -# eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim -# ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut -# aliquip ex ea commodo consequat. Duis aute irure dolor in -# reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla -# pariatur. Excepteur sint occaecat cupidatat non proident, sunt in -# culpa qui officia deserunt mollit anim id est laborum. (string -# value) -#long_help = -''')), - ('long_help_wrap_at_40', - dict(opts=[('test', [(None, [opts['long_help']])])], - wrap_width=40, - expected='''[DEFAULT] - -# -# From test -# - -# Lorem ipsum dolor sit amet, -# consectetur adipisicing elit, sed do -# eiusmod tempor incididunt ut labore et -# dolore magna aliqua. Ut enim ad minim -# veniam, quis nostrud exercitation -# ullamco laboris nisi ut aliquip ex ea -# commodo consequat. Duis aute irure -# dolor in reprehenderit in voluptate -# velit esse cillum dolore eu fugiat -# nulla pariatur. Excepteur sint -# occaecat cupidatat non proident, sunt -# in culpa qui officia deserunt mollit -# anim id est laborum. (string value) -#long_help = -''')), - ('long_help_no_wrapping', - dict(opts=[('test', [(None, [opts['long_help']])])], - wrap_width=0, - expected='''[DEFAULT] - -# -# From test -# - -''' # noqa -'# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod ' -'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ' -'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo ' -'consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse ' -'cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' -'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ' -'(string value)' -''' -#long_help = -''')), - ('choices_opt', - dict(opts=[('test', [(None, [opts['choices_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a string with choices (string value) -# Allowed values: , '', a, b, c -#choices_opt = a -''')), - ('deprecated', - dict(opts=[('test', [('foo', [opts['deprecated_opt']])])], - expected='''[DEFAULT] - - -[foo] - -# -# From test -# - -# deprecated (string value) -# Deprecated group/name - [DEFAULT]/foobar -#bar = -''')), - ('deprecated_group', - dict(opts=[('test', [('foo', [opts['deprecated_group']])])], - expected='''[DEFAULT] - - -[foo] - -# -# From test -# - -# deprecated (string value) -# Deprecated group/name - [group1]/foobar -#bar = -''')), - ('unknown_type', - dict(opts=[('test', [(None, [opts['unknown_type']])])], - log_warning=('Unknown option type: %s', - repr(opts['unknown_type'])), - expected='''[DEFAULT] - -# -# From test -# - -# unknown (unknown type) -#unknown_opt = 123 -''')), - ('str_opt', - dict(opts=[('test', [(None, [opts['str_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a string (string value) -#str_opt = foo bar -''')), - ('str_opt_with_space', - dict(opts=[('test', [(None, [opts['str_opt_with_space']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a string with spaces (string value) -#str_opt = " foo bar " -''')), - ('bool_opt', - dict(opts=[('test', [(None, [opts['bool_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a boolean (boolean value) -#bool_opt = false -''')), - ('int_opt', - dict(opts=[('test', [(None, [opts['int_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# an integer (integer value) -#int_opt = 10 -''')), - ('float_opt', - dict(opts=[('test', [(None, [opts['float_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a float (floating point value) -#float_opt = 0.1 -''')), - ('list_opt', - dict(opts=[('test', [(None, [opts['list_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a list (list value) -#list_opt = 1,2,3 -''')), - ('dict_opt', - dict(opts=[('test', [(None, [opts['dict_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a dict (dict value) -#dict_opt = 1:yes,2:no -''')), - ('multi_opt', - dict(opts=[('test', [(None, [opts['multi_opt']])])], - expected='''[DEFAULT] - -# -# From test -# - -# multiple strings (multi valued) -#multi_opt = 1 -#multi_opt = 2 -#multi_opt = 3 -''')), - ('multi_opt_none', - dict(opts=[('test', [(None, [opts['multi_opt_none']])])], - expected='''[DEFAULT] - -# -# From test -# - -# multiple strings (multi valued) -#multi_opt_none = -''')), - ('multi_opt_empty', - dict(opts=[('test', [(None, [opts['multi_opt_empty']])])], - expected='''[DEFAULT] - -# -# From test -# - -# multiple strings (multi valued) -#multi_opt_empty = -''')), - ('str_opt_sample_default', - dict(opts=[('test', [(None, [opts['str_opt_sample_default']])])], - expected='''[DEFAULT] - -# -# From test -# - -# a string (string value) -#str_opt = fooishbar -''')), - ('multi_opt_sample_default', - dict(opts=[('test', [(None, [opts['multi_opt_sample_default']])])], - expected='''[DEFAULT] - -# -# From test -# - -# multiple strings (multi valued) -#multi_opt = 5 -#multi_opt = 6 -''')), - ] - - output_file_scenarios = [ - ('stdout', - dict(stdout=True, output_file=None)), - ('output_file', - dict(output_file='sample.conf', stdout=False)), - ] - - @classmethod - def generate_scenarios(cls): - cls.scenarios = testscenarios.multiply_scenarios( - cls.content_scenarios, - cls.output_file_scenarios) - - def setUp(self): - super(GeneratorTestCase, self).setUp() - - self.conf = cfg.ConfigOpts() - self.config_fixture = config_fixture.Config(self.conf) - self.config = self.config_fixture.config - self.useFixture(self.config_fixture) - - self.tempdir = self.useFixture(fixtures.TempDir()) - - def _capture_stream(self, stream_name): - self.useFixture(fixtures.MonkeyPatch("sys.%s" % stream_name, - moves.StringIO())) - return getattr(sys, stream_name) - - def _capture_stdout(self): - return self._capture_stream('stdout') - - @mock.patch('stevedore.named.NamedExtensionManager') - @mock.patch.object(generator, 'LOG') - def test_generate(self, mock_log, named_mgr): - generator.register_cli_opts(self.conf) - - namespaces = [i[0] for i in self.opts] - self.config(namespace=namespaces) - - wrap_width = getattr(self, 'wrap_width', None) - if wrap_width is not None: - self.config(wrap_width=wrap_width) - - if self.stdout: - stdout = self._capture_stdout() - else: - output_file = self.tempdir.join(self.output_file) - self.config(output_file=output_file) - - mock_eps = [] - for name, opts in self.opts: - mock_ep = mock.Mock() - mock_ep.configure_mock(name=name, obj=opts) - mock_eps.append(mock_ep) - named_mgr.return_value = mock_eps - - generator.generate(self.conf) - - if self.stdout: - self.assertEqual(self.expected, stdout.getvalue()) - else: - content = open(output_file).read() - self.assertEqual(self.expected, content) - - named_mgr.assert_called_once_with( - 'oslo.config.opts', - names=namespaces, - on_load_failure_callback=generator.on_load_failure_callback, - invoke_on_load=True) - - log_warning = getattr(self, 'log_warning', None) - if log_warning is not None: - mock_log.warning.assert_called_once_with(*log_warning) - else: - self.assertFalse(mock_log.warning.called) - - -class GeneratorRaiseErrorTestCase(base.BaseTestCase): - - def test_generator_raises_error(self): - """Verifies that errors from extension manager are not suppressed.""" - class FakeException(Exception): - pass - - class FakeEP(object): - - def __init__(self): - self.name = 'callback_is_expected' - self.require = self.resolve - self.load = self.resolve - - def resolve(self, *args, **kwargs): - raise FakeException() - - fake_ep = FakeEP() - self.conf = cfg.ConfigOpts() - self.conf.register_opts(generator._generator_opts) - self.conf.set_default('namespace', fake_ep.name) - fake_eps = mock.Mock(return_value=[fake_ep]) - with mock.patch('pkg_resources.iter_entry_points', fake_eps): - self.assertRaises(FakeException, generator.generate, self.conf) - - -GeneratorTestCase.generate_scenarios() diff --git a/awx/lib/site-packages/oslo_config/tests/test_iniparser.py b/awx/lib/site-packages/oslo_config/tests/test_iniparser.py deleted file mode 100644 index 5c2166b014..0000000000 --- a/awx/lib/site-packages/oslo_config/tests/test_iniparser.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import unittest - -from oslo_config import iniparser - - -class TestParser(iniparser.BaseParser): - comment_called = False - values = None - section = '' - - def __init__(self): - self.values = {} - - def assignment(self, key, value): - self.values.setdefault(self.section, {}) - self.values[self.section][key] = value - - def new_section(self, section): - self.section = section - - def comment(self, section): - self.comment_called = True - - -class BaseParserTestCase(unittest.TestCase): - def setUp(self): - self.parser = iniparser.BaseParser() - - def _assertParseError(self, *lines): - self.assertRaises(iniparser.ParseError, self.parser.parse, lines) - - def test_invalid_assignment(self): - self._assertParseError("foo - bar") - - def test_empty_key(self): - self._assertParseError(": bar") - - def test_unexpected_continuation(self): - self._assertParseError(" baz") - - def test_invalid_section(self): - self._assertParseError("[section") - - def test_no_section_name(self): - self._assertParseError("[]") - - -class ParserTestCase(unittest.TestCase): - def setUp(self): - self.parser = TestParser() - - def test_blank_line(self): - lines = [""] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {}) - - def test_assignment_equal(self): - lines = ["foo = bar"] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {'': {'foo': ['bar']}}) - - def test_assignment_colon(self): - lines = ["foo: bar"] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {'': {'foo': ['bar']}}) - - def test_assignment_multiline(self): - lines = ["foo = bar0", " bar1"] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {'': {'foo': ['bar0', 'bar1']}}) - - def test_assignment_multline_empty(self): - lines = ["foo = bar0", "", " bar1"] - self.assertRaises(iniparser.ParseError, self.parser.parse, lines) - - def test_section_assignment(self): - lines = ["[test]", "foo = bar"] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {'test': {'foo': ['bar']}}) - - def test_new_section(self): - lines = ["[foo]"] - self.parser.parse(lines) - self.assertEqual(self.parser.section, 'foo') - - def test_comment(self): - lines = ["# foobar"] - self.parser.parse(lines) - self.assertTrue(self.parser.comment_called) - - def test_empty_assignment(self): - lines = ["foo = "] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {'': {'foo': ['']}}) - - def test_assignment_space_single_quote(self): - lines = ["foo = ' bar '"] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {'': {'foo': [' bar ']}}) - - def test_assignment_space_double_quote(self): - lines = ["foo = \" bar \""] - self.parser.parse(lines) - self.assertEqual(self.parser.values, {'': {'foo': [' bar ']}}) - - -class ExceptionTestCase(unittest.TestCase): - def test_parseerror(self): - exc = iniparser.ParseError('test', 42, 'example') - self.assertEqual(str(exc), "at line 42, test: 'example'") diff --git a/awx/lib/site-packages/oslo_config/tests/test_types.py b/awx/lib/site-packages/oslo_config/tests/test_types.py deleted file mode 100644 index 3824adb9c3..0000000000 --- a/awx/lib/site-packages/oslo_config/tests/test_types.py +++ /dev/null @@ -1,412 +0,0 @@ -# Copyright 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import unittest - -from oslo_config import types - - -class TypeTestHelper(object): - def setUp(self): - super(TypeTestHelper, self).setUp() - self.type_instance = self.type - - def assertConvertedValue(self, s, expected): - self.assertEqual(expected, self.type_instance(s)) - - def assertInvalid(self, value): - self.assertRaises(ValueError, self.type_instance, value) - - -class StringTypeTests(TypeTestHelper, unittest.TestCase): - type = types.String() - - def test_empty_string_passes(self): - self.assertConvertedValue('', '') - - def test_should_return_same_string_if_valid(self): - self.assertConvertedValue('foo bar', 'foo bar') - - def test_listed_value(self): - self.type_instance = types.String(choices=['foo', 'bar']) - self.assertConvertedValue('foo', 'foo') - - def test_unlisted_value(self): - self.type_instance = types.String(choices=['foo', 'bar']) - self.assertInvalid('baz') - - def test_with_no_values_returns_error(self): - self.type_instance = types.String(choices=[]) - self.assertInvalid('foo') - - def test_string_with_non_closed_quote_is_invalid(self): - self.type_instance = types.String(quotes=True) - self.assertInvalid('"foo bar') - self.assertInvalid("'bar baz") - - def test_quotes_are_stripped(self): - self.type_instance = types.String(quotes=True) - self.assertConvertedValue('"foo bar"', 'foo bar') - - def test_trailing_quote_is_ok(self): - self.type_instance = types.String(quotes=True) - self.assertConvertedValue('foo bar"', 'foo bar"') - - def test_repr(self): - t = types.String() - self.assertEqual('String', repr(t)) - - def test_repr_with_choices(self): - t = types.String(choices=['foo', 'bar']) - self.assertEqual('String(choices=[\'foo\', \'bar\'])', repr(t)) - - def test_equal(self): - self.assertTrue(types.String() == types.String()) - - def test_equal_with_same_choices(self): - t1 = types.String(choices=['foo', 'bar']) - t2 = types.String(choices=['foo', 'bar']) - self.assertTrue(t1 == t2) - - def test_not_equal_with_different_choices(self): - t1 = types.String(choices=['foo', 'bar']) - t2 = types.String(choices=['foo', 'baz']) - self.assertFalse(t1 == t2) - - def test_equal_with_equal_quote_falgs(self): - t1 = types.String(quotes=True) - t2 = types.String(quotes=True) - self.assertTrue(t1 == t2) - - def test_not_equal_with_different_quote_falgs(self): - t1 = types.String(quotes=False) - t2 = types.String(quotes=True) - self.assertFalse(t1 == t2) - - def test_not_equal_to_other_class(self): - self.assertFalse(types.String() == types.Integer()) - - -class BooleanTypeTests(TypeTestHelper, unittest.TestCase): - type = types.Boolean() - - def test_True(self): - self.assertConvertedValue('True', True) - - def test_yes(self): - self.assertConvertedValue('yes', True) - - def test_on(self): - self.assertConvertedValue('on', True) - - def test_1(self): - self.assertConvertedValue('1', True) - - def test_False(self): - self.assertConvertedValue('False', False) - - def test_no(self): - self.assertConvertedValue('no', False) - - def test_off(self): - self.assertConvertedValue('off', False) - - def test_0(self): - self.assertConvertedValue('0', False) - - def test_other_values_produce_error(self): - self.assertInvalid('foo') - - def test_repr(self): - self.assertEqual('Boolean', repr(types.Boolean())) - - def test_equal(self): - self.assertEqual(types.Boolean(), types.Boolean()) - - def test_not_equal_to_other_class(self): - self.assertFalse(types.Boolean() == types.String()) - - -class IntegerTypeTests(TypeTestHelper, unittest.TestCase): - type = types.Integer() - - def test_empty_string(self): - self.assertConvertedValue('', None) - - def test_whitespace_string(self): - self.assertConvertedValue(" \t\t\t\t", None) - - def test_positive_values_are_valid(self): - self.assertConvertedValue('123', 123) - - def test_zero_is_valid(self): - self.assertConvertedValue('0', 0) - - def test_negative_values_are_valid(self): - self.assertConvertedValue('-123', -123) - - def test_leading_whitespace_is_ignored(self): - self.assertConvertedValue(' 5', 5) - - def test_trailing_whitespace_is_ignored(self): - self.assertConvertedValue('7 ', 7) - - def test_non_digits_are_invalid(self): - self.assertInvalid('12a45') - - def test_repr(self): - t = types.Integer() - self.assertEqual('Integer', repr(t)) - - def test_repr_with_min(self): - t = types.Integer(min=123) - self.assertEqual('Integer(min=123)', repr(t)) - - def test_repr_with_max(self): - t = types.Integer(max=456) - self.assertEqual('Integer(max=456)', repr(t)) - - def test_repr_with_min_and_max(self): - t = types.Integer(min=123, max=456) - self.assertEqual('Integer(min=123, max=456)', repr(t)) - - def test_equal(self): - self.assertTrue(types.Integer() == types.Integer()) - - def test_equal_with_same_min_and_no_max(self): - self.assertTrue(types.Integer(min=123) == types.Integer(min=123)) - - def test_equal_with_same_max_and_no_min(self): - self.assertTrue(types.Integer(max=123) == types.Integer(max=123)) - - def test_equal_with_same_min_and_max(self): - t1 = types.Integer(min=1, max=123) - t2 = types.Integer(min=1, max=123) - self.assertTrue(t1 == t2) - - def test_not_equal(self): - self.assertFalse(types.Integer(min=123) == types.Integer(min=456)) - - def test_not_equal_to_other_class(self): - self.assertFalse(types.Integer() == types.String()) - - def test_with_max_and_min(self): - t = types.Integer(min=123, max=456) - self.assertRaises(ValueError, t, 122) - t(123) - t(300) - t(456) - self.assertRaises(ValueError, t, 0) - self.assertRaises(ValueError, t, 457) - - -class FloatTypeTests(TypeTestHelper, unittest.TestCase): - type = types.Float() - - def test_decimal_format(self): - v = self.type_instance('123.456') - self.assertAlmostEqual(v, 123.456) - - def test_decimal_format_negative_float(self): - v = self.type_instance('-123.456') - self.assertAlmostEqual(v, -123.456) - - def test_exponential_format(self): - v = self.type_instance('123e-2') - self.assertAlmostEqual(v, 1.23) - - def test_non_float_is_invalid(self): - self.assertInvalid('123,345') - self.assertInvalid('foo') - - def test_repr(self): - self.assertEqual('Float', repr(types.Float())) - - def test_equal(self): - self.assertTrue(types.Float() == types.Float()) - - def test_not_equal_to_other_class(self): - self.assertFalse(types.Float() == types.Integer()) - - -class ListTypeTests(TypeTestHelper, unittest.TestCase): - type = types.List() - - def test_empty_value(self): - self.assertConvertedValue('', []) - - def test_single_value(self): - self.assertConvertedValue(' foo bar ', - ['foo bar']) - - def test_list_of_values(self): - self.assertConvertedValue(' foo bar, baz ', - ['foo bar', - 'baz']) - - def test_list_of_values_containing_commas(self): - self.type_instance = types.List(types.String(quotes=True)) - self.assertConvertedValue('foo,"bar, baz",bam', - ['foo', - 'bar, baz', - 'bam']) - - def test_list_of_lists(self): - self.type_instance = types.List( - types.List(types.String(), bounds=True) - ) - self.assertConvertedValue('[foo],[bar, baz],[bam]', - [['foo'], ['bar', 'baz'], ['bam']]) - - def test_list_of_custom_type(self): - self.type_instance = types.List(types.Integer()) - self.assertConvertedValue('1,2,3,5', - [1, 2, 3, 5]) - - def test_bounds_parsing(self): - self.type_instance = types.List(types.Integer(), bounds=True) - self.assertConvertedValue('[1,2,3]', [1, 2, 3]) - - def test_bounds_required(self): - self.type_instance = types.List(types.Integer(), bounds=True) - self.assertInvalid('1,2,3') - self.assertInvalid('[1,2,3') - self.assertInvalid('1,2,3]') - - def test_repr(self): - t = types.List(types.Integer()) - self.assertEqual('List of Integer', repr(t)) - - def test_equal(self): - self.assertTrue(types.List() == types.List()) - - def test_equal_with_equal_custom_item_types(self): - it1 = types.Integer() - it2 = types.Integer() - self.assertTrue(types.List(it1) == types.List(it2)) - - def test_not_equal_with_non_equal_custom_item_types(self): - it1 = types.Integer() - it2 = types.String() - self.assertFalse(it1 == it2) - self.assertFalse(types.List(it1) == types.List(it2)) - - def test_not_equal_to_other_class(self): - self.assertFalse(types.List() == types.Integer()) - - -class DictTypeTests(TypeTestHelper, unittest.TestCase): - type = types.Dict() - - def test_empty_value(self): - self.assertConvertedValue('', {}) - - def test_single_value(self): - self.assertConvertedValue(' foo: bar ', - {'foo': 'bar'}) - - def test_dict_of_values(self): - self.assertConvertedValue(' foo: bar, baz: 123 ', - {'foo': 'bar', - 'baz': '123'}) - - def test_custom_value_type(self): - self.type_instance = types.Dict(types.Integer()) - self.assertConvertedValue('foo:123, bar: 456', - {'foo': 123, - 'bar': 456}) - - def test_dict_of_values_containing_commas(self): - self.type_instance = types.Dict(types.String(quotes=True)) - self.assertConvertedValue('foo:"bar, baz",bam:quux', - {'foo': 'bar, baz', - 'bam': 'quux'}) - - def test_dict_of_dicts(self): - self.type_instance = types.Dict( - types.Dict(types.String(), bounds=True) - ) - self.assertConvertedValue('k1:{k1:v1,k2:v2},k2:{k3:v3}', - {'k1': {'k1': 'v1', 'k2': 'v2'}, - 'k2': {'k3': 'v3'}}) - - def test_bounds_parsing(self): - self.type_instance = types.Dict(types.String(), bounds=True) - self.assertConvertedValue('{foo:bar,baz:123}', - {'foo': 'bar', - 'baz': '123'}) - - def test_bounds_required(self): - self.type_instance = types.Dict(types.String(), bounds=True) - self.assertInvalid('foo:bar,baz:123') - self.assertInvalid('{foo:bar,baz:123') - self.assertInvalid('foo:bar,baz:123}') - - def test_no_mapping_produces_error(self): - self.assertInvalid('foo,bar') - - def test_repr(self): - t = types.Dict(types.Integer()) - self.assertEqual('Dict of Integer', repr(t)) - - def test_equal(self): - self.assertTrue(types.Dict() == types.Dict()) - - def test_equal_with_equal_custom_item_types(self): - it1 = types.Integer() - it2 = types.Integer() - self.assertTrue(types.Dict(it1) == types.Dict(it2)) - - def test_not_equal_with_non_equal_custom_item_types(self): - it1 = types.Integer() - it2 = types.String() - self.assertFalse(it1 == it2) - self.assertFalse(types.Dict(it1) == types.Dict(it2)) - - def test_not_equal_to_other_class(self): - self.assertFalse(types.Dict() == types.Integer()) - - -class IPAddressTypeTests(TypeTestHelper, unittest.TestCase): - type = types.IPAddress() - - def test_ipv4_address(self): - self.assertConvertedValue('192.168.0.1', '192.168.0.1') - - def test_ipv6_address(self): - self.assertConvertedValue('abcd:ef::1', 'abcd:ef::1') - - def test_strings(self): - self.assertInvalid('') - self.assertInvalid('foo') - - def test_numbers(self): - self.assertInvalid(1) - self.assertInvalid(-1) - self.assertInvalid(3.14) - - -class IPv4AddressTypeTests(IPAddressTypeTests): - type = types.IPAddress(4) - - def test_ipv6_address(self): - self.assertInvalid('abcd:ef::1') - - -class IPv6AddressTypeTests(IPAddressTypeTests): - type = types.IPAddress(6) - - def test_ipv4_address(self): - self.assertInvalid('192.168.0.1') diff --git a/awx/lib/site-packages/oslo_config/types.py b/awx/lib/site-packages/oslo_config/types.py deleted file mode 100644 index d120472c6a..0000000000 --- a/awx/lib/site-packages/oslo_config/types.py +++ /dev/null @@ -1,413 +0,0 @@ -# Copyright 2013 Mirantis, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Type conversion and validation classes for configuration options. - -Use these classes as values for the `type` argument to -:class:`oslo_config.cfg.Opt` and its subclasses. - -""" -import netaddr -import six - - -class ConfigType(object): - - BASE_TYPES = (None,) - - def is_base_type(self, other): - return isinstance(other, self.BASE_TYPES) - - -class String(ConfigType): - - """String type. - - String values do not get transformed and are returned as str objects. - - :param choices: Optional sequence of valid values. - :param quotes: If True and string is enclosed with single or double - quotes, will strip those quotes. Will signal error if - string have quote at the beginning and no quote at - the end. Turned off by default. Useful if used with - container types like List. - """ - - BASE_TYPES = six.string_types - - def __init__(self, choices=None, quotes=False): - super(String, self).__init__() - self.choices = choices - self.quotes = quotes - - def __call__(self, value): - value = str(value) - if self.quotes and value: - if value[0] in "\"'": - if value[-1] != value[0]: - raise ValueError('Non-closed quote: %s' % value) - value = value[1:-1] - - if self.choices is None or value in self.choices: - return value - - raise ValueError( - 'Valid values are [%s], but found %s' % ( - ', '.join([str(v) for v in self.choices]), - repr(value))) - - def __repr__(self): - if self.choices: - return 'String(choices=%s)' % repr(self.choices) - return 'String' - - def __eq__(self, other): - return ( - (self.__class__ == other.__class__) and - (self.choices == other.choices) and - (self.quotes == other.quotes) - ) - - -class MultiString(String): - - BASE_TYPES = six.string_types + (list,) - - -class Boolean(ConfigType): - - """Boolean type. - - Values are case insensitive and can be set using - 1/0, yes/no, true/false or on/off. - """ - TRUE_VALUES = ['true', '1', 'on', 'yes'] - FALSE_VALUES = ['false', '0', 'off', 'no'] - - BASE_TYPES = (bool,) - - def __call__(self, value): - if isinstance(value, bool): - return value - - s = value.lower() - if s in self.TRUE_VALUES: - return True - elif s in self.FALSE_VALUES: - return False - else: - raise ValueError('Unexpected boolean value %r' % value) - - def __repr__(self): - return 'Boolean' - - def __eq__(self, other): - return self.__class__ == other.__class__ - - -class Integer(ConfigType): - - """Integer type. - - Converts value to an integer optionally doing range checking. - If value is whitespace or empty string will return None. - - :param min: Optional check that value is greater than or equal to min - :param max: Optional check that value is less than or equal to max - """ - - BASE_TYPES = six.integer_types - - def __init__(self, min=None, max=None): - super(Integer, self).__init__() - self.min = min - self.max = max - if min and max and max < min: - raise ValueError('Max value is less than min value') - - def __call__(self, value): - if not isinstance(value, int): - s = str(value).strip() - if s == '': - value = None - else: - value = int(value) - - if value is not None: - self._check_range(value) - - return value - - def _check_range(self, value): - if self.min and value < self.min: - raise ValueError('Should be greater than or equal to %d' % - self.min) - if self.max and value > self.max: - raise ValueError('Should be less than or equal to %d' % self.max) - - def __repr__(self): - props = [] - if self.min: - props.append('min=%d' % self.min) - if self.max: - props.append('max=%d' % self.max) - - if props: - return 'Integer(%s)' % ', '.join(props) - return 'Integer' - - def __eq__(self, other): - return ( - (self.__class__ == other.__class__) and - (self.min == other.min) and - (self.max == other.max) - ) - - -class Float(ConfigType): - - """Float type.""" - - # allow float to be set from int - BASE_TYPES = six.integer_types + (float,) - - def __call__(self, value): - if isinstance(value, float): - return value - - return float(value) - - def __repr__(self): - return 'Float' - - def __eq__(self, other): - return self.__class__ == other.__class__ - - -class List(ConfigType): - - """List type. - - Represent values of other (item) type, separated by commas. - The resulting value is a list containing those values. - - List doesn't know if item type can also contain commas. To workaround this - it tries the following: if the next part fails item validation, it appends - comma and next item until validation succeeds or there is no parts left. - In the later case it will signal validation error. - - :param item_type: type of list items - :param bounds: if True, value should be inside "[" and "]" pair - """ - - BASE_TYPES = (list,) - - def __init__(self, item_type=None, bounds=False): - super(List, self).__init__() - - if item_type is None: - item_type = String() - - if not callable(item_type): - raise TypeError('item_type must be callable') - self.item_type = item_type - self.bounds = bounds - - def __call__(self, value): - if isinstance(value, list): - return value - - result = [] - s = value.strip() - - if self.bounds: - if not s.startswith('['): - raise ValueError('Value should start with "["') - if not s.endswith(']'): - raise ValueError('Value should end with "]"') - s = s[1:-1] - - if s == '': - return result - - values = s.split(',') - while values: - value = values.pop(0) - while True: - first_error = None - try: - validated_value = self.item_type(value.strip()) - break - except ValueError as e: - if not first_error: - first_error = e - if len(values) == 0: - raise first_error - - value += ',' + values.pop(0) - - result.append(validated_value) - - return result - - def __repr__(self): - return 'List of %s' % repr(self.item_type) - - def __eq__(self, other): - return ( - (self.__class__ == other.__class__) and - (self.item_type == other.item_type) - ) - - -class Dict(ConfigType): - - """Dictionary type. - - Dictionary type values are key:value pairs separated by commas. - The resulting value is a dictionary of these key/value pairs. - Type of dictionary key is always string, but dictionary value - type can be customized. - - :param value_type: type of values in dictionary - :param bounds: if True, value should be inside "{" and "}" pair - """ - - BASE_TYPES = (dict,) - - def __init__(self, value_type=None, bounds=False): - super(Dict, self).__init__() - - if value_type is None: - value_type = String() - - if not callable(value_type): - raise TypeError('value_type must be callable') - self.value_type = value_type - self.bounds = bounds - - def __call__(self, value): - if isinstance(value, dict): - return value - - result = {} - s = value.strip() - - if self.bounds: - if not s.startswith('{'): - raise ValueError('Value should start with "{"') - if not s.endswith('}'): - raise ValueError('Value should end with "}"') - s = s[1:-1] - - if s == '': - return result - - pairs = s.split(',') - while pairs: - pair = pairs.pop(0) - - while True: - first_error = None - try: - key_value = pair.split(':', 1) - - if len(key_value) < 2: - raise ValueError('Value should be NAME:VALUE pairs ' - 'separated by ","') - - key, value = key_value - key = key.strip() - value = value.strip() - - value = self.value_type(value) - break - except ValueError as e: - if not first_error: - first_error = e - if not pairs: - raise first_error - - pair += ',' + pairs.pop(0) - - if key == '': - raise ValueError('Key name should not be empty') - - if key in result: - raise ValueError('Duplicate key %s' % key) - - result[key] = value - - return result - - def __repr__(self): - return 'Dict of %s' % repr(self.value_type) - - def __eq__(self, other): - return ( - (self.__class__ == other.__class__) and - (self.value_type == other.value_type) - ) - - -class IPAddress(ConfigType): - - """IP address type - - Represents either ipv4 or ipv6. Without specifying version parameter both - versions are checked - - :param version: defines which version should be explicitly checked (4 or 6) - - """ - - BASE_TYPES = six.string_types - - def __init__(self, version=None): - super(IPAddress, self).__init__() - version_checkers = { - None: self._check_both_versions, - 4: self._check_ipv4, - 6: self._check_ipv6 - } - - self.version_checker = version_checkers.get(version) - if self.version_checker is None: - raise TypeError("%s is not a valid IP version." % version) - - def __call__(self, value): - value = str(value) - if not value: - raise ValueError("IP address cannot be an empty string") - self.version_checker(value) - return value - - def __repr__(self): - return "IPAddress" - - def __eq__(self, other): - return self.__class__ == other.__class__ - - def _check_ipv4(self, address): - if not netaddr.valid_ipv4(address, netaddr.core.INET_PTON): - raise ValueError("%s is not an IPv4 address" % address) - - def _check_ipv6(self, address): - if not netaddr.valid_ipv6(address, netaddr.core.INET_PTON): - raise ValueError("%s is not an IPv6 address" % address) - - def _check_both_versions(self, address): - if not (netaddr.valid_ipv4(address, netaddr.core.INET_PTON) or - netaddr.valid_ipv6(address, netaddr.core.INET_PTON)): - raise ValueError("%s is not IPv4 or IPv6 address" % address) diff --git a/awx/lib/site-packages/oslo_i18n/__init__.py b/awx/lib/site-packages/oslo_i18n/__init__.py deleted file mode 100644 index 4602749340..0000000000 --- a/awx/lib/site-packages/oslo_i18n/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from ._factory import * -from ._gettextutils import * -from ._lazy import * -from ._translate import * diff --git a/awx/lib/site-packages/oslo_i18n/_factory.py b/awx/lib/site-packages/oslo_i18n/_factory.py deleted file mode 100644 index 73ab217703..0000000000 --- a/awx/lib/site-packages/oslo_i18n/_factory.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Translation function factory -""" - -import gettext -import os - -import six - -from oslo_i18n import _lazy -from oslo_i18n import _locale -from oslo_i18n import _message - - -__all__ = [ - 'TranslatorFactory', -] - - -class TranslatorFactory(object): - "Create translator functions" - - def __init__(self, domain, localedir=None): - """Establish a set of translation functions for the domain. - - :param domain: Name of translation domain, - specifying a message catalog. - :type domain: str - :param localedir: Directory with translation catalogs. - :type localedir: str - """ - self.domain = domain - if localedir is None: - variable_name = _locale.get_locale_dir_variable_name(domain) - localedir = os.environ.get(variable_name) - self.localedir = localedir - - def _make_translation_func(self, domain=None): - """Return a translation function ready for use with messages. - - The returned function takes a single value, the unicode string - to be translated. The return type varies depending on whether - lazy translation is being done. When lazy translation is - enabled, :class:`Message` objects are returned instead of - regular :class:`unicode` strings. - - The domain argument can be specified to override the default - from the factory, but the localedir from the factory is always - used because we assume the log-level translation catalogs are - installed in the same directory as the main application - catalog. - - """ - if domain is None: - domain = self.domain - t = gettext.translation(domain, - localedir=self.localedir, - fallback=True) - # Use the appropriate method of the translation object based - # on the python version. - m = t.gettext if six.PY3 else t.ugettext - - def f(msg): - """oslo_i18n.gettextutils translation function.""" - if _lazy.USE_LAZY: - return _message.Message(msg, domain=domain) - return m(msg) - return f - - @property - def primary(self): - "The default translation function." - return self._make_translation_func() - - def _make_log_translation_func(self, level): - return self._make_translation_func(self.domain + '-log-' + level) - - @property - def log_info(self): - "Translate info-level log messages." - return self._make_log_translation_func('info') - - @property - def log_warning(self): - "Translate warning-level log messages." - return self._make_log_translation_func('warning') - - @property - def log_error(self): - "Translate error-level log messages." - return self._make_log_translation_func('error') - - @property - def log_critical(self): - "Translate critical-level log messages." - return self._make_log_translation_func('critical') diff --git a/awx/lib/site-packages/oslo_i18n/_gettextutils.py b/awx/lib/site-packages/oslo_i18n/_gettextutils.py deleted file mode 100644 index 75a83131df..0000000000 --- a/awx/lib/site-packages/oslo_i18n/_gettextutils.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""gettextutils provides a wrapper around gettext for OpenStack projects -""" - -import copy -import gettext -import os - -from babel import localedata -import six - -from oslo_i18n import _factory -from oslo_i18n import _locale - -__all__ = [ - 'install', - 'get_available_languages', -] - - -def install(domain): - """Install a _() function using the given translation domain. - - Given a translation domain, install a _() function using gettext's - install() function. - - The main difference from gettext.install() is that we allow - overriding the default localedir (e.g. /usr/share/locale) using - a translation-domain-specific environment variable (e.g. - NOVA_LOCALEDIR). - - :param domain: the translation domain - """ - from six import moves - tf = _factory.TranslatorFactory(domain) - moves.builtins.__dict__['_'] = tf.primary - - -_AVAILABLE_LANGUAGES = {} - - -def get_available_languages(domain): - """Lists the available languages for the given translation domain. - - :param domain: the domain to get languages for - """ - if domain in _AVAILABLE_LANGUAGES: - return copy.copy(_AVAILABLE_LANGUAGES[domain]) - - localedir = os.environ.get(_locale.get_locale_dir_variable_name(domain)) - find = lambda x: gettext.find(domain, - localedir=localedir, - languages=[x]) - - # NOTE(mrodden): en_US should always be available (and first in case - # order matters) since our in-line message strings are en_US - language_list = ['en_US'] - locale_identifiers = localedata.locale_identifiers() - language_list.extend(language for language in locale_identifiers - if find(language)) - - # In Babel 1.3, locale_identifiers() doesn't list some OpenStack supported - # locales (e.g. 'zh_CN', and 'zh_TW') so we add the locales explicitly if - # necessary so that they are listed as supported. - aliases = {'zh': 'zh_CN', - 'zh_Hant_HK': 'zh_HK', - 'zh_Hant': 'zh_TW', - 'fil': 'tl_PH'} - - language_list.extend(alias for locale, alias in six.iteritems(aliases) - if (locale in language_list and - alias not in language_list)) - - _AVAILABLE_LANGUAGES[domain] = language_list - return copy.copy(language_list) diff --git a/awx/lib/site-packages/oslo_i18n/_i18n.py b/awx/lib/site-packages/oslo_i18n/_i18n.py deleted file mode 100644 index 72cdb3cb91..0000000000 --- a/awx/lib/site-packages/oslo_i18n/_i18n.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Translation support for messages in this library. -""" - -from oslo_i18n import _factory - -# Create the global translation functions. -_translators = _factory.TranslatorFactory('oslo.i18n') - -# The primary translation function using the well-known name "_" -_ = _translators.primary diff --git a/awx/lib/site-packages/oslo_i18n/_lazy.py b/awx/lib/site-packages/oslo_i18n/_lazy.py deleted file mode 100644 index 82de17d08e..0000000000 --- a/awx/lib/site-packages/oslo_i18n/_lazy.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -__all__ = [ - 'enable_lazy', -] - -USE_LAZY = False - - -def enable_lazy(enable=True): - """Convenience function for configuring _() to use lazy gettext - - Call this at the start of execution to enable the gettextutils._ - function to use lazy gettext functionality. This is useful if - your project is importing _ directly instead of using the - gettextutils.install() way of importing the _ function. - - :param enable: Flag indicating whether lazy translation should be - turned on or off. Defaults to True. - :type enable: bool - - """ - global USE_LAZY - USE_LAZY = enable diff --git a/awx/lib/site-packages/oslo_i18n/_locale.py b/awx/lib/site-packages/oslo_i18n/_locale.py deleted file mode 100644 index 51908db2f4..0000000000 --- a/awx/lib/site-packages/oslo_i18n/_locale.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -def get_locale_dir_variable_name(domain): - """Build environment variable name for local dir. - - Convert a translation domain name to a variable for specifying - a separate locale dir. - - """ - return domain.upper().replace('.', '_').replace('-', '_') + '_LOCALEDIR' diff --git a/awx/lib/site-packages/oslo_i18n/_message.py b/awx/lib/site-packages/oslo_i18n/_message.py deleted file mode 100644 index ceb39e7978..0000000000 --- a/awx/lib/site-packages/oslo_i18n/_message.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Private Message class for lazy translation support. -""" - -import copy -import gettext -import locale -import os - -import six - -from oslo_i18n import _locale -from oslo_i18n import _translate - - -class Message(six.text_type): - """A Message object is a unicode object that can be translated. - - Translation of Message is done explicitly using the translate() method. - For all non-translation intents and purposes, a Message is simply unicode, - and can be treated as such. - """ - - def __new__(cls, msgid, msgtext=None, params=None, - domain='oslo', *args): - """Create a new Message object. - - In order for translation to work gettext requires a message ID, this - msgid will be used as the base unicode text. It is also possible - for the msgid and the base unicode text to be different by passing - the msgtext parameter. - """ - # If the base msgtext is not given, we use the default translation - # of the msgid (which is in English) just in case the system locale is - # not English, so that the base text will be in that locale by default. - if not msgtext: - msgtext = Message._translate_msgid(msgid, domain) - # We want to initialize the parent unicode with the actual object that - # would have been plain unicode if 'Message' was not enabled. - msg = super(Message, cls).__new__(cls, msgtext) - msg.msgid = msgid - msg.domain = domain - msg.params = params - return msg - - def translate(self, desired_locale=None): - """Translate this message to the desired locale. - - :param desired_locale: The desired locale to translate the message to, - if no locale is provided the message will be - translated to the system's default locale. - - :returns: the translated message in unicode - """ - - translated_message = Message._translate_msgid(self.msgid, - self.domain, - desired_locale) - if self.params is None: - # No need for more translation - return translated_message - - # This Message object may have been formatted with one or more - # Message objects as substitution arguments, given either as a single - # argument, part of a tuple, or as one or more values in a dictionary. - # When translating this Message we need to translate those Messages too - translated_params = _translate.translate_args(self.params, - desired_locale) - - translated_message = translated_message % translated_params - - return translated_message - - @staticmethod - def _translate_msgid(msgid, domain, desired_locale=None): - if not desired_locale: - system_locale = locale.getdefaultlocale() - # If the system locale is not available to the runtime use English - desired_locale = system_locale[0] or 'en_US' - - locale_dir = os.environ.get( - _locale.get_locale_dir_variable_name(domain) - ) - lang = gettext.translation(domain, - localedir=locale_dir, - languages=[desired_locale], - fallback=True) - translator = lang.gettext if six.PY3 else lang.ugettext - - translated_message = translator(msgid) - return translated_message - - def __mod__(self, other): - # When we mod a Message we want the actual operation to be performed - # by the parent class (i.e. unicode()), the only thing we do here is - # save the original msgid and the parameters in case of a translation - params = self._sanitize_mod_params(other) - unicode_mod = super(Message, self).__mod__(params) - modded = Message(self.msgid, - msgtext=unicode_mod, - params=params, - domain=self.domain) - return modded - - def _sanitize_mod_params(self, other): - """Sanitize the object being modded with this Message. - - - Add support for modding 'None' so translation supports it - - Trim the modded object, which can be a large dictionary, to only - those keys that would actually be used in a translation - - Snapshot the object being modded, in case the message is - translated, it will be used as it was when the Message was created - """ - if other is None: - params = (other,) - elif isinstance(other, dict): - # Merge the dictionaries - # Copy each item in case one does not support deep copy. - params = {} - if isinstance(self.params, dict): - params.update((key, self._copy_param(val)) - for key, val in self.params.items()) - params.update((key, self._copy_param(val)) - for key, val in other.items()) - else: - params = self._copy_param(other) - return params - - def _copy_param(self, param): - try: - return copy.deepcopy(param) - except Exception: - # Fallback to casting to unicode this will handle the - # python code-like objects that can't be deep-copied - return six.text_type(param) - - def __add__(self, other): - from oslo_i18n._i18n import _ - msg = _('Message objects do not support addition.') - raise TypeError(msg) - - def __radd__(self, other): - return self.__add__(other) - - if six.PY2: - def __str__(self): - # NOTE(luisg): Logging in python 2.6 tries to str() log records, - # and it expects specifically a UnicodeError in order to proceed. - from oslo_i18n._i18n import _ - msg = _('Message objects do not support str() because they may ' - 'contain non-ascii characters. ' - 'Please use unicode() or translate() instead.') - raise UnicodeError(msg) diff --git a/awx/lib/site-packages/oslo_i18n/_translate.py b/awx/lib/site-packages/oslo_i18n/_translate.py deleted file mode 100644 index 1809e1e2e8..0000000000 --- a/awx/lib/site-packages/oslo_i18n/_translate.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - -__all__ = [ - 'translate', -] - - -def translate(obj, desired_locale=None): - """Gets the translated unicode representation of the given object. - - If the object is not translatable it is returned as-is. - - If the desired_locale argument is None the object is translated to - the system locale. - - :param obj: the object to translate - :param desired_locale: the locale to translate the message to, if None the - default system locale will be used - :returns: the translated object in unicode, or the original object if - it could not be translated - - """ - from oslo_i18n import _message # avoid circular dependency at module level - message = obj - if not isinstance(message, _message.Message): - # If the object to translate is not already translatable, - # let's first get its unicode representation - message = six.text_type(obj) - if isinstance(message, _message.Message): - # Even after unicoding() we still need to check if we are - # running with translatable unicode before translating - return message.translate(desired_locale) - return obj - - -def translate_args(args, desired_locale=None): - """Translates all the translatable elements of the given arguments object. - - This method is used for translating the translatable values in method - arguments which include values of tuples or dictionaries. - If the object is not a tuple or a dictionary the object itself is - translated if it is translatable. - - If the locale is None the object is translated to the system locale. - - :param args: the args to translate - :param desired_locale: the locale to translate the args to, if None the - default system locale will be used - :returns: a new args object with the translated contents of the original - """ - if isinstance(args, tuple): - return tuple(translate(v, desired_locale) for v in args) - if isinstance(args, dict): - translated_dict = dict((key, translate(value, desired_locale)) - for key, value in six.iteritems(args)) - return translated_dict - return translate(args, desired_locale) diff --git a/awx/lib/site-packages/oslo_i18n/fixture.py b/awx/lib/site-packages/oslo_i18n/fixture.py deleted file mode 100644 index 6dd2ee0b61..0000000000 --- a/awx/lib/site-packages/oslo_i18n/fixture.py +++ /dev/null @@ -1,165 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Test fixtures for working with oslo_i18n. - -""" - -import gettext - -import fixtures -import six - -from oslo_i18n import _lazy -from oslo_i18n import _message - - -class Translation(fixtures.Fixture): - """Fixture for managing translatable strings. - - This class provides methods for creating translatable strings - using both lazy translation and immediate translation. It can be - used to generate the different types of messages returned from - oslo_i18n to test code that may need to know about the type to - handle them differently (for example, error handling in WSGI apps, - or logging). - - Use this class to generate messages instead of toggling the global - lazy flag and using the regular translation factory. - - """ - - def __init__(self, domain='test-domain'): - """Initialize the fixture. - - :param domain: The translation domain. This is not expected to - coincide with an actual set of message - catalogs, but it can. - :type domain: str - """ - self.domain = domain - - def lazy(self, msg): - """Return a lazily translated message. - - :param msg: Input message string. May optionally include - positional or named string interpolation markers. - :type msg: str or unicode - - """ - return _message.Message(msg, domain=self.domain) - - def immediate(self, msg): - """Return a string as though it had been translated immediately. - - :param msg: Input message string. May optionally include - positional or named string interpolation markers. - :type msg: str or unicode - - """ - return six.text_type(msg) - - -class ToggleLazy(fixtures.Fixture): - """Fixture to toggle lazy translation on or off for a test.""" - - def __init__(self, enabled): - """Force lazy translation on or off. - - :param enabled: Flag controlling whether to enable or disable - lazy translation, passed to :func:`~oslo_i18n.enable_lazy`. - :type enabled: bool - """ - super(ToggleLazy, self).__init__() - self._enabled = enabled - self._original_value = _lazy.USE_LAZY - - def setUp(self): - super(ToggleLazy, self).setUp() - self.addCleanup(self._restore_original) - _lazy.enable_lazy(self._enabled) - - def _restore_original(self): - _lazy.enable_lazy(self._original_value) - - -class _PrefixTranslator(gettext.NullTranslations): - """Translator that adds prefix to message ids - - NOTE: gettext.NullTranslations is an old style class - - :parm prefix: prefix to add to message id. If not specified (None) - then 'noprefix' is used. - :type prefix: string - - """ - - def __init__(self, fp=None, prefix='noprefix'): - gettext.NullTranslations.__init__(self, fp) - self.prefix = prefix - - def gettext(self, message): - msg = gettext.NullTranslations.gettext(self, message) - return self.prefix + msg - - def ugettext(self, message): - msg = gettext.NullTranslations.ugettext(self, message) - return self.prefix + msg - - -def _prefix_translations(*x, **y): - """Use message id prefixed with domain and language as translation - - """ - return _PrefixTranslator(prefix=x[0] + '/' + y['languages'][0] + ': ') - - -class PrefixLazyTranslation(fixtures.Fixture): - """Fixture to prefix lazy translation enabled messages - - Use of this fixture will cause messages supporting lazy translation to - be replaced with the message id prefixed with 'domain/language:'. - For example, 'oslo/en_US: message about something'. It will also - override the available languages returned from - oslo_18n.get_available_languages to the specified languages. - - This will enable tests to ensure that messages were translated lazily - with the specified language and not immediately with the default language. - - NOTE that this does not work unless lazy translation is enabled, so it - uses the ToggleLazy fixture to enable lazy translation. - - :param languages: list of languages to support. If not specified (None) - then ['en_US'] is used. - :type languages: list of strings - - """ - - _DEFAULT_LANG = 'en_US' - - def __init__(self, languages=None): - super(PrefixLazyTranslation, self).__init__() - self.languages = languages or [PrefixLazyTranslation._DEFAULT_LANG] - - def setUp(self): - super(PrefixLazyTranslation, self).setUp() - self.useFixture(ToggleLazy(True)) - self.useFixture(fixtures.MonkeyPatch( - 'oslo_i18n._gettextutils.get_available_languages', - lambda *x, **y: self.languages)) - self.useFixture(fixtures.MonkeyPatch( - 'oslo.i18n.get_available_languages', - lambda *x, **y: self.languages)) - self.useFixture(fixtures.MonkeyPatch( - 'oslo_i18n.get_available_languages', - lambda *x, **y: self.languages)) - self.useFixture(fixtures.MonkeyPatch('gettext.translation', - _prefix_translations)) diff --git a/awx/lib/site-packages/oslo_i18n/log.py b/awx/lib/site-packages/oslo_i18n/log.py deleted file mode 100644 index 563c1b3aae..0000000000 --- a/awx/lib/site-packages/oslo_i18n/log.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""logging utilities for translation -""" - -from logging import handlers - -from oslo_i18n import _translate - - -class TranslationHandler(handlers.MemoryHandler): - """Handler that translates records before logging them. - - When lazy translation is enabled in the application (see - :func:`~oslo_i18n.enable_lazy`), the :class:`TranslationHandler` - uses its locale configuration setting to determine how to - translate LogRecord objects before forwarding them to the - logging.Handler. - - When lazy translation is disabled, the message in the LogRecord is - converted to unicode without any changes and then forwarded to the - logging.Handler. - - The handler can be configured declaratively in the - ``logging.conf`` as follows:: - - [handlers] - keys = translatedlog, translator - - [handler_translatedlog] - class = handlers.WatchedFileHandler - args = ('/var/log/api-localized.log',) - formatter = context - - [handler_translator] - class = oslo_i18n.log.TranslationHandler - target = translatedlog - args = ('zh_CN',) - - If the specified locale is not available in the system, the handler will - log in the default locale. - - """ - - def __init__(self, locale=None, target=None): - """Initialize a TranslationHandler - - :param locale: locale to use for translating messages - :param target: logging.Handler object to forward - LogRecord objects to after translation - """ - # NOTE(luisg): In order to allow this handler to be a wrapper for - # other handlers, such as a FileHandler, and still be able to - # configure it using logging.conf, this handler has to extend - # MemoryHandler because only the MemoryHandlers' logging.conf - # parsing is implemented such that it accepts a target handler. - handlers.MemoryHandler.__init__(self, capacity=0, target=target) - self.locale = locale - - def setFormatter(self, fmt): - self.target.setFormatter(fmt) - - def emit(self, record): - # We save the message from the original record to restore it - # after translation, so other handlers are not affected by this - original_msg = record.msg - original_args = record.args - - try: - self._translate_and_log_record(record) - finally: - record.msg = original_msg - record.args = original_args - - def _translate_and_log_record(self, record): - record.msg = _translate.translate(record.msg, self.locale) - - # In addition to translating the message, we also need to translate - # arguments that were passed to the log method that were not part - # of the main message e.g., log.info(_('Some message %s'), this_one)) - record.args = _translate.translate_args(record.args, self.locale) - - self.target.emit(record) diff --git a/awx/lib/site-packages/oslo_i18n/tests/__init__.py b/awx/lib/site-packages/oslo_i18n/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/oslo_i18n/tests/fakes.py b/awx/lib/site-packages/oslo_i18n/tests/fakes.py deleted file mode 100644 index 6bed973690..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/fakes.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2012 Intel Inc, OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Fakes For translation tests. -""" - -import gettext - - -class FakeTranslations(gettext.GNUTranslations): - """A test GNUTranslations class that takes a map of msg -> translations.""" - - def __init__(self, translations): - self.translations = translations - - # used by Python 3 - def gettext(self, msgid): - return self.translations.get(msgid, msgid) - - # used by Python 2 - def ugettext(self, msgid): - return self.translations.get(msgid, msgid) - - @staticmethod - def translator(locales_map): - """Build mock translator for the given locales. - - Returns a mock gettext.translation function that uses - individual TestTranslations to translate in the given locales. - - :param locales_map: A map from locale name to a translations map. - { - 'es': {'Hi': 'Hola', 'Bye': 'Adios'}, - 'zh': {'Hi': 'Ni Hao', 'Bye': 'Zaijian'} - } - - - """ - def _translation(domain, localedir=None, - languages=None, fallback=None): - if languages: - language = languages[0] - if language in locales_map: - return FakeTranslations(locales_map[language]) - return gettext.NullTranslations() - return _translation diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_factory.py b/awx/lib/site-packages/oslo_i18n/tests/test_factory.py deleted file mode 100644 index 771728ef85..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_factory.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslotest import base as test_base -import six - -from oslo_i18n import _factory -from oslo_i18n import _lazy -from oslo_i18n import _message - - -class TranslatorFactoryTest(test_base.BaseTestCase): - - def setUp(self): - super(TranslatorFactoryTest, self).setUp() - # remember so we can reset to it later in case it changes - self._USE_LAZY = _lazy.USE_LAZY - - def tearDown(self): - # reset to value before test - _lazy.USE_LAZY = self._USE_LAZY - super(TranslatorFactoryTest, self).tearDown() - - def test_lazy(self): - _lazy.enable_lazy(True) - with mock.patch.object(_message, 'Message') as msg: - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - msg.assert_called_with('some text', domain='domain') - - def test_not_lazy(self): - _lazy.enable_lazy(False) - with mock.patch.object(_message, 'Message') as msg: - msg.side_effect = AssertionError('should not use Message') - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - - def test_change_lazy(self): - _lazy.enable_lazy(True) - tf = _factory.TranslatorFactory('domain') - r = tf.primary('some text') - self.assertIsInstance(r, _message.Message) - _lazy.enable_lazy(False) - r = tf.primary('some text') - # Python 2.6 doesn't have assertNotIsInstance(). - self.assertFalse(isinstance(r, _message.Message)) - - def test_py2(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', False): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.gettext.side_effect = AssertionError( - 'should have called ugettext') - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - trans.ugettext.assert_called_with('some text') - - def test_py3(self): - _lazy.enable_lazy(False) - with mock.patch.object(six, 'PY3', True): - with mock.patch('gettext.translation') as translation: - trans = mock.Mock() - translation.return_value = trans - trans.ugettext.side_effect = AssertionError( - 'should have called gettext') - tf = _factory.TranslatorFactory('domain') - tf.primary('some text') - trans.gettext.assert_called_with('some text') - - def test_log_level_domain_name(self): - with mock.patch.object(_factory.TranslatorFactory, - '_make_translation_func') as mtf: - tf = _factory.TranslatorFactory('domain') - tf._make_log_translation_func('mylevel') - mtf.assert_called_with('domain-log-mylevel') diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_fixture.py b/awx/lib/site-packages/oslo_i18n/tests/test_fixture.py deleted file mode 100644 index 7bc29d1f48..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_fixture.py +++ /dev/null @@ -1,124 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base -import six - -from oslo import i18n as old_i18n -import oslo_i18n as new_i18n -from oslo_i18n import _gettextutils -from oslo_i18n._i18n import _ -from oslo_i18n import _lazy -from oslo_i18n import _message -from oslo_i18n import _translate -from oslo_i18n import fixture - - -class TranslationFixtureTest(test_base.BaseTestCase): - - def setUp(self): - super(TranslationFixtureTest, self).setUp() - self.trans_fixture = self.useFixture(fixture.Translation()) - - def test_lazy(self): - msg = self.trans_fixture.lazy('this is a lazy message') - self.assertIsInstance(msg, _message.Message) - self.assertEqual(msg.msgid, 'this is a lazy message') - - def test_immediate(self): - msg = self.trans_fixture.immediate('this is a lazy message') - # Python 2.6 does not have assertNotIsInstance - self.assertFalse(isinstance(msg, _message.Message)) - self.assertIsInstance(msg, six.text_type) - self.assertEqual(msg, u'this is a lazy message') - - -class ToggleLazyFixtureText(test_base.BaseTestCase): - - def test_on_on(self): - _lazy.USE_LAZY = True - f = fixture.ToggleLazy(True) - f.setUp() - self.assertTrue(_lazy.USE_LAZY) - f._restore_original() - self.assertTrue(_lazy.USE_LAZY) - - def test_on_off(self): - _lazy.USE_LAZY = True - f = fixture.ToggleLazy(False) - f.setUp() - self.assertFalse(_lazy.USE_LAZY) - f._restore_original() - self.assertTrue(_lazy.USE_LAZY) - - def test_off_on(self): - _lazy.USE_LAZY = False - f = fixture.ToggleLazy(True) - f.setUp() - self.assertTrue(_lazy.USE_LAZY) - f._restore_original() - self.assertFalse(_lazy.USE_LAZY) - - def test_off_off(self): - _lazy.USE_LAZY = False - f = fixture.ToggleLazy(False) - f.setUp() - self.assertFalse(_lazy.USE_LAZY) - f._restore_original() - self.assertFalse(_lazy.USE_LAZY) - - -_FAKE_LANG = 'en_ZZ' - - -class PrefixLazyTranslationTest(test_base.BaseTestCase): - - def test_default(self): - - # Turn lazy off to check that fixture turns it on - self.useFixture(fixture.ToggleLazy(False)) - self.useFixture(fixture.PrefixLazyTranslation()) - self.assertTrue(_lazy.USE_LAZY) - default_lang = fixture.PrefixLazyTranslation._DEFAULT_LANG - raw_id1 = 'fake msg1' - expected_msg = 'oslo.i18n/' + default_lang + ': ' + raw_id1 - msg1 = _(raw_id1) # noqa - self.assertEqual([default_lang], - _gettextutils.get_available_languages('oslo')) - self.assertEqual([default_lang], - old_i18n.get_available_languages('oslo')) - self.assertEqual([default_lang], - new_i18n.get_available_languages('oslo')) - self.assertEqual(expected_msg, _translate.translate(msg1)) - - def test_extra_lang(self): - languages = _gettextutils.get_available_languages('oslo') - languages.append(_FAKE_LANG) - self.useFixture(fixture.PrefixLazyTranslation(languages=languages)) - raw_id1 = 'fake msg1' - expected_msg_en_US = ('oslo.i18n/' + - fixture.PrefixLazyTranslation._DEFAULT_LANG + - ': ' + raw_id1) - expected_msg_en_ZZ = 'oslo.i18n/' + _FAKE_LANG + ': ' + raw_id1 - msg1 = _(raw_id1) # noqa - self.assertEqual(languages, - _gettextutils.get_available_languages('oslo')) - self.assertEqual(languages, - old_i18n.get_available_languages('oslo')) - self.assertEqual(languages, - new_i18n.get_available_languages('oslo')) - self.assertEqual(expected_msg_en_US, _translate.translate(msg1)) - self.assertEqual(expected_msg_en_ZZ, - _translate.translate(msg1, - desired_locale=_FAKE_LANG)) diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_gettextutils.py b/awx/lib/site-packages/oslo_i18n/tests/test_gettextutils.py deleted file mode 100644 index 6f0d5c5b48..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_gettextutils.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import gettext -import logging - -from babel import localedata -import mock -from oslotest import base as test_base -from oslotest import moxstubout -import six - -from oslo_i18n import _factory -from oslo_i18n import _gettextutils -from oslo_i18n import _lazy -from oslo_i18n import _message - - -LOG = logging.getLogger(__name__) - - -class GettextTest(test_base.BaseTestCase): - - def setUp(self): - super(GettextTest, self).setUp() - moxfixture = self.useFixture(moxstubout.MoxStubout()) - self.stubs = moxfixture.stubs - self.mox = moxfixture.mox - # remember so we can reset to it later in case it changes - self._USE_LAZY = _lazy.USE_LAZY - self.t = _factory.TranslatorFactory('oslo_i18n.test') - - def tearDown(self): - # reset to value before test - _lazy.USE_LAZY = self._USE_LAZY - super(GettextTest, self).tearDown() - - def test_gettext_does_not_blow_up(self): - LOG.info(self.t.primary('test')) - - def test__gettextutils_install(self): - _gettextutils.install('blaa') - _lazy.enable_lazy(False) - self.assertTrue(isinstance(self.t.primary('A String'), - six.text_type)) - - _gettextutils.install('blaa') - _lazy.enable_lazy(True) - self.assertTrue(isinstance(self.t.primary('A Message'), - _message.Message)) - - def test_gettext_install_looks_up_localedir(self): - with mock.patch('os.environ.get') as environ_get: - with mock.patch('gettext.install'): - environ_get.return_value = '/foo/bar' - _gettextutils.install('blaa') - environ_get.assert_calls([mock.call('BLAA_LOCALEDIR')]) - - def test_gettext_install_updates_builtins(self): - with mock.patch('os.environ.get') as environ_get: - with mock.patch('gettext.install'): - environ_get.return_value = '/foo/bar' - if '_' in six.moves.builtins.__dict__: - del six.moves.builtins.__dict__['_'] - _gettextutils.install('blaa') - self.assertIn('_', six.moves.builtins.__dict__) - - def test_get_available_languages(self): - # All the available languages for which locale data is available - def _mock_locale_identifiers(): - # 'zh', 'zh_Hant'. 'zh_Hant_HK', 'fil' all have aliases - # missing from babel but we add them in _gettextutils, we - # test that here too - return ['zh', 'es', 'nl', 'fr', 'zh_Hant', 'zh_Hant_HK', 'fil'] - - self.stubs.Set(localedata, - 'list' if hasattr(localedata, 'list') - else 'locale_identifiers', - _mock_locale_identifiers) - - # Only the languages available for a specific translation domain - def _mock_gettext_find(domain, localedir=None, languages=None, all=0): - languages = languages or [] - if domain == 'domain_1': - return 'translation-file' if any(x in ['zh', 'es', 'fil'] - for x in languages) else None - elif domain == 'domain_2': - return 'translation-file' if any(x in ['fr', 'zh_Hant'] - for x in languages) else None - return None - self.stubs.Set(gettext, 'find', _mock_gettext_find) - - # Ensure that no domains are cached - _gettextutils._AVAILABLE_LANGUAGES = {} - - # en_US should always be available no matter the domain - # and it should also always be the first element since order matters - domain_1_languages = _gettextutils.get_available_languages('domain_1') - domain_2_languages = _gettextutils.get_available_languages('domain_2') - self.assertEqual('en_US', domain_1_languages[0]) - self.assertEqual('en_US', domain_2_languages[0]) - # The domain languages should be included after en_US with - # with their respective aliases when it applies - self.assertEqual(6, len(domain_1_languages)) - self.assertIn('zh', domain_1_languages) - self.assertIn('zh_CN', domain_1_languages) - self.assertIn('es', domain_1_languages) - self.assertIn('fil', domain_1_languages) - self.assertIn('tl_PH', domain_1_languages) - self.assertEqual(4, len(domain_2_languages)) - self.assertIn('fr', domain_2_languages) - self.assertIn('zh_Hant', domain_2_languages) - self.assertIn('zh_TW', domain_2_languages) - self.assertEqual(2, len(_gettextutils._AVAILABLE_LANGUAGES)) - # Now test an unknown domain, only en_US should be included - unknown_domain_languages = _gettextutils.get_available_languages('huh') - self.assertEqual(1, len(unknown_domain_languages)) - self.assertIn('en_US', unknown_domain_languages) diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_handler.py b/awx/lib/site-packages/oslo_i18n/tests/test_handler.py deleted file mode 100644 index b0c678e0f1..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_handler.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging - -import mock -from oslotest import base as test_base -import six - -from oslo_i18n import _message -from oslo_i18n import log as i18n_log -from oslo_i18n.tests import fakes - -LOG = logging.getLogger(__name__) - - -class TranslationHandlerTestCase(test_base.BaseTestCase): - - def setUp(self): - super(TranslationHandlerTestCase, self).setUp() - - self.stream = six.StringIO() - self.destination_handler = logging.StreamHandler(self.stream) - self.translation_handler = i18n_log.TranslationHandler('zh_CN') - self.translation_handler.setTarget(self.destination_handler) - - self.logger = logging.getLogger('localehander_logger') - self.logger.setLevel(logging.DEBUG) - self.logger.addHandler(self.translation_handler) - - def test_set_formatter(self): - formatter = 'some formatter' - self.translation_handler.setFormatter(formatter) - self.assertEqual(formatter, self.translation_handler.target.formatter) - - @mock.patch('gettext.translation') - def test_emit_translated_message(self, mock_translation): - log_message = 'A message to be logged' - log_message_translation = 'A message to be logged in Chinese' - translations = {log_message: log_message_translation} - translations_map = {'zh_CN': translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - msg = _message.Message(log_message) - - self.logger.info(msg) - self.assertIn(log_message_translation, self.stream.getvalue()) - - @mock.patch('gettext.translation') - def test_emit_translated_message_with_args(self, mock_translation): - log_message = 'A message to be logged %s' - log_message_translation = 'A message to be logged in Chinese %s' - log_arg = 'Arg to be logged' - log_arg_translation = 'An arg to be logged in Chinese' - - translations = {log_message: log_message_translation, - log_arg: log_arg_translation} - translations_map = {'zh_CN': translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - msg = _message.Message(log_message) - arg = _message.Message(log_arg) - - self.logger.info(msg, arg) - self.assertIn(log_message_translation % log_arg_translation, - self.stream.getvalue()) - - @mock.patch('gettext.translation') - def test_emit_translated_message_with_named_args(self, mock_translation): - log_message = 'A message to be logged %(arg1)s $(arg2)s' - log_message_translation = 'Chinese msg to be logged %(arg1)s $(arg2)s' - log_arg_1 = 'Arg1 to be logged' - log_arg_1_translation = 'Arg1 to be logged in Chinese' - log_arg_2 = 'Arg2 to be logged' - log_arg_2_translation = 'Arg2 to be logged in Chinese' - - translations = {log_message: log_message_translation, - log_arg_1: log_arg_1_translation, - log_arg_2: log_arg_2_translation} - translations_map = {'zh_CN': translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - msg = _message.Message(log_message) - arg_1 = _message.Message(log_arg_1) - arg_2 = _message.Message(log_arg_2) - - self.logger.info(msg, {'arg1': arg_1, 'arg2': arg_2}) - translation = log_message_translation % {'arg1': log_arg_1_translation, - 'arg2': log_arg_2_translation} - self.assertIn(translation, self.stream.getvalue()) diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_lazy.py b/awx/lib/site-packages/oslo_i18n/tests/test_lazy.py deleted file mode 100644 index 049d51a4d9..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_lazy.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base - -from oslo_i18n import _lazy - - -class LazyTest(test_base.BaseTestCase): - - def setUp(self): - super(LazyTest, self).setUp() - self._USE_LAZY = _lazy.USE_LAZY - - def tearDown(self): - _lazy.USE_LAZY = self._USE_LAZY - super(LazyTest, self).tearDown() - - def test_enable_lazy(self): - _lazy.USE_LAZY = False - _lazy.enable_lazy() - self.assertTrue(_lazy.USE_LAZY) - - def test_disable_lazy(self): - _lazy.USE_LAZY = True - _lazy.enable_lazy(False) - self.assertFalse(_lazy.USE_LAZY) diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_locale_dir_variable.py b/awx/lib/site-packages/oslo_i18n/tests/test_locale_dir_variable.py deleted file mode 100644 index 26321c188f..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_locale_dir_variable.py +++ /dev/null @@ -1,32 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base -import testscenarios.testcase - -from oslo_i18n import _locale - - -class LocaleDirVariableTest(testscenarios.testcase.WithScenarios, - test_base.BaseTestCase): - - scenarios = [ - ('simple', {'domain': 'simple', 'expected': 'SIMPLE_LOCALEDIR'}), - ('with_dot', {'domain': 'one.two', 'expected': 'ONE_TWO_LOCALEDIR'}), - ('with_dash', {'domain': 'one-two', 'expected': 'ONE_TWO_LOCALEDIR'}), - ] - - def test_make_variable_name(self): - var = _locale.get_locale_dir_variable_name(self.domain) - self.assertEqual(self.expected, var) diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_logging.py b/awx/lib/site-packages/oslo_i18n/tests/test_logging.py deleted file mode 100644 index 07e5c71ca2..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_logging.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslotest import base as test_base - -from oslo_i18n import _factory - - -class LogLevelTranslationsTest(test_base.BaseTestCase): - - def test_info(self): - self._test('info') - - def test_warning(self): - self._test('warning') - - def test_error(self): - self._test('error') - - def test_critical(self): - self._test('critical') - - def _test(self, level): - with mock.patch.object(_factory.TranslatorFactory, - '_make_translation_func') as mtf: - tf = _factory.TranslatorFactory('domain') - getattr(tf, 'log_%s' % level) - mtf.assert_called_with('domain-log-%s' % level) diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_message.py b/awx/lib/site-packages/oslo_i18n/tests/test_message.py deleted file mode 100644 index 0fab2faf06..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_message.py +++ /dev/null @@ -1,518 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import unicode_literals - -import logging - -import mock -from oslotest import base as test_base -import six -import testtools - -from oslo_i18n import _message -from oslo_i18n.tests import fakes -from oslo_i18n.tests import utils - -LOG = logging.getLogger(__name__) - - -class MessageTestCase(test_base.BaseTestCase): - """Unit tests for locale Message class.""" - - def test_message_id_and_message_text(self): - message = _message.Message('1') - self.assertEqual('1', message.msgid) - self.assertEqual('1', message) - message = _message.Message('1', msgtext='A') - self.assertEqual('1', message.msgid) - self.assertEqual('A', message) - - def test_message_is_unicode(self): - message = _message.Message('some %s') % 'message' - self.assertIsInstance(message, six.text_type) - - @mock.patch('locale.getdefaultlocale') - @mock.patch('gettext.translation') - def test_create_message_non_english_default_locale(self, - mock_translation, - mock_getdefaultlocale): - msgid = 'A message in English' - es_translation = 'A message in Spanish' - - es_translations = {msgid: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - mock_getdefaultlocale.return_value = ('es',) - - message = _message.Message(msgid) - - # The base representation of the message is in Spanish, as well as - # the default translation, since the default locale was Spanish. - self.assertEqual(es_translation, message) - self.assertEqual(es_translation, message.translate()) - - def test_translate_returns_unicode(self): - message = _message.Message('some %s') % 'message' - self.assertIsInstance(message.translate(), six.text_type) - - def test_mod_with_named_parameters(self): - msgid = ("%(description)s\nCommand: %(cmd)s\n" - "Exit code: %(exit_code)s\nStdout: %(stdout)r\n" - "Stderr: %(stderr)r %%(something)s") - params = {'description': 'test1', - 'cmd': 'test2', - 'exit_code': 'test3', - 'stdout': 'test4', - 'stderr': 'test5', - 'something': 'trimmed'} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(result, expected) - self.assertEqual(result.translate(), expected) - - def test_multiple_mod_with_named_parameter(self): - msgid = ("%(description)s\nCommand: %(cmd)s\n" - "Exit code: %(exit_code)s\nStdout: %(stdout)r\n" - "Stderr: %(stderr)r") - params = {'description': 'test1', - 'cmd': 'test2', - 'exit_code': 'test3', - 'stdout': 'test4', - 'stderr': 'test5'} - - # Run string interpolation the first time to make a new Message - first = _message.Message(msgid) % params - - # Run string interpolation on the new Message, to replicate - # one of the error paths with some Exception classes we've - # implemented in OpenStack. We should receive a second Message - # object, but the translation results should be the same. - # - # The production code that triggers this problem does something - # like: - # - # msg = _('there was a problem %(name)s') % {'name': 'some value'} - # LOG.error(msg) - # raise BadExceptionClass(msg) - # - # where BadExceptionClass does something like: - # - # class BadExceptionClass(Exception): - # def __init__(self, msg, **kwds): - # super(BadExceptionClass, self).__init__(msg % kwds) - # - expected = first % {} - - # Base message id should be the same - self.assertEqual(first.msgid, expected.msgid) - - # Preserved arguments should be the same - self.assertEqual(first.params, expected.params) - - # Should have different objects - self.assertIsNot(expected, first) - - # Final translations should be the same - self.assertEqual(expected.translate(), first.translate()) - - def test_mod_with_named_parameters_no_space(self): - msgid = ("Request: %(method)s http://%(server)s:" - "%(port)s%(url)s with headers %(headers)s") - params = {'method': 'POST', - 'server': 'test1', - 'port': 1234, - 'url': 'test2', - 'headers': {'h1': 'val1'}} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(result, expected) - self.assertEqual(result.translate(), expected) - - def test_mod_with_dict_parameter(self): - msgid = "Test that we can inject a dictionary %s" - params = {'description': 'test1'} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(expected, result) - self.assertEqual(expected, result.translate()) - - def test_mod_with_integer_parameters(self): - msgid = "Some string with params: %d" - params = [0, 1, 10, 24124] - - messages = [] - results = [] - for param in params: - messages.append(msgid % param) - results.append(_message.Message(msgid) % param) - - for message, result in zip(messages, results): - self.assertEqual(type(result), _message.Message) - self.assertEqual(result.translate(), message) - - # simulate writing out as string - result_str = '%s' % result.translate() - self.assertEqual(result_str, message) - self.assertEqual(result, message) - - def test_mod_copies_parameters(self): - msgid = "Found object: %(current_value)s" - changing_dict = {'current_value': 1} - # A message created with some params - result = _message.Message(msgid) % changing_dict - # The parameters may change - changing_dict['current_value'] = 2 - # Even if the param changes when the message is - # translated it should use the original param - self.assertEqual(result.translate(), 'Found object: 1') - - def test_mod_deep_copies_parameters(self): - msgid = "Found list: %(current_list)s" - changing_list = list([1, 2, 3]) - params = {'current_list': changing_list} - # Apply the params - result = _message.Message(msgid) % params - # Change the list - changing_list.append(4) - # Even though the list changed the message - # translation should use the original list - self.assertEqual(result.translate(), "Found list: [1, 2, 3]") - - def test_mod_deep_copies_param_nodeep_param(self): - msgid = "Value: %s" - params = utils.NoDeepCopyObject(5) - # Apply the params - result = _message.Message(msgid) % params - self.assertEqual(result.translate(), "Value: 5") - - def test_mod_deep_copies_param_nodeep_dict(self): - msgid = "Values: %(val1)s %(val2)s" - params = {'val1': 1, 'val2': utils.NoDeepCopyObject(2)} - # Apply the params - result = _message.Message(msgid) % params - self.assertEqual(result.translate(), "Values: 1 2") - - # Apply again to make sure other path works as well - params = {'val1': 3, 'val2': utils.NoDeepCopyObject(4)} - result = _message.Message(msgid) % params - self.assertEqual(result.translate(), "Values: 3 4") - - def test_mod_returns_a_copy(self): - msgid = "Some msgid string: %(test1)s %(test2)s" - message = _message.Message(msgid) - m1 = message % {'test1': 'foo', 'test2': 'bar'} - m2 = message % {'test1': 'foo2', 'test2': 'bar2'} - - self.assertIsNot(message, m1) - self.assertIsNot(message, m2) - self.assertEqual(m1.translate(), - msgid % {'test1': 'foo', 'test2': 'bar'}) - self.assertEqual(m2.translate(), - msgid % {'test1': 'foo2', 'test2': 'bar2'}) - - def test_mod_with_none_parameter(self): - msgid = "Some string with params: %s" - message = _message.Message(msgid) % None - self.assertEqual(msgid % None, message) - self.assertEqual(msgid % None, message.translate()) - - def test_mod_with_missing_parameters(self): - msgid = "Some string with params: %s %s" - test_me = lambda: _message.Message(msgid) % 'just one' - # Just like with strings missing parameters raise TypeError - self.assertRaises(TypeError, test_me) - - def test_mod_with_extra_parameters(self): - msgid = "Some string with params: %(param1)s %(param2)s" - params = {'param1': 'test', - 'param2': 'test2', - 'param3': 'notinstring'} - - result = _message.Message(msgid) % params - - expected = msgid % params - self.assertEqual(result, expected) - self.assertEqual(result.translate(), expected) - - # Make sure unused params still there - self.assertEqual(result.params.keys(), params.keys()) - - def test_mod_with_missing_named_parameters(self): - msgid = ("Some string with params: %(param1)s %(param2)s" - " and a missing one %(missing)s") - params = {'param1': 'test', - 'param2': 'test2'} - - test_me = lambda: _message.Message(msgid) % params - # Just like with strings missing named parameters raise KeyError - self.assertRaises(KeyError, test_me) - - def test_add_disabled(self): - msgid = "A message" - test_me = lambda: _message.Message(msgid) + ' some string' - self.assertRaises(TypeError, test_me) - - def test_radd_disabled(self): - msgid = "A message" - test_me = lambda: utils.SomeObject('test') + _message.Message(msgid) - self.assertRaises(TypeError, test_me) - - @testtools.skipIf(six.PY3, 'test specific to Python 2') - def test_str_disabled(self): - msgid = "A message" - test_me = lambda: str(_message.Message(msgid)) - self.assertRaises(UnicodeError, test_me) - - @mock.patch('gettext.translation') - def test_translate(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - message = _message.Message(en_message) - - es_translations = {en_message: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - self.assertEqual(es_translation, message.translate('es')) - - @mock.patch('gettext.translation') - def test_translate_message_from_unicoded_object(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - message = _message.Message(en_message) - es_translations = {en_message: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - # Here we are not testing the Message object directly but the result - # of unicoding() an object whose unicode representation is a Message - obj = utils.SomeObject(message) - unicoded_obj = six.text_type(obj) - - self.assertEqual(es_translation, unicoded_obj.translate('es')) - - @mock.patch('gettext.translation') - def test_translate_multiple_languages(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - zh_translation = 'A message in Chinese' - message = _message.Message(en_message) - - es_translations = {en_message: es_translation} - zh_translations = {en_message: zh_translation} - translations_map = {'es': es_translations, - 'zh': zh_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - self.assertEqual(es_translation, message.translate('es')) - self.assertEqual(zh_translation, message.translate('zh')) - self.assertEqual(en_message, message.translate(None)) - self.assertEqual(en_message, message.translate('en')) - self.assertEqual(en_message, message.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_param(self, mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s' - param = 'A Message param' - - translations = {message_with_params: es_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg = msg % param - - default_translation = message_with_params % param - expected_translation = es_translation % param - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_object_param(self, mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s' - param = 'A Message param' - param_translation = 'A Message param in Spanish' - - translations = {message_with_params: es_translation, - param: param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - param_msg = _message.Message(param) - - # Here we are testing translation of a Message with another object - # that can be translated via its unicode() representation, this is - # very common for instance when modding an Exception with a Message - obj = utils.SomeObject(param_msg) - msg = msg % obj - - default_translation = message_with_params % param - expected_translation = es_translation % param_translation - - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_param_from_unicoded_obj(self, - mock_translation): - message_with_params = 'A message: %s' - es_translation = 'A message in Spanish: %s' - param = 'A Message param' - - translations = {message_with_params: es_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg = msg % param - - default_translation = message_with_params % param - expected_translation = es_translation % param - - obj = utils.SomeObject(msg) - unicoded_obj = six.text_type(obj) - - self.assertEqual(expected_translation, unicoded_obj.translate('es')) - self.assertEqual(default_translation, unicoded_obj.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_message_parameter(self, mock_translation): - message_with_params = 'A message with param: %s' - es_translation = 'A message with param in Spanish: %s' - message_param = 'A message param' - es_param_translation = 'A message param in Spanish' - - translations = {message_with_params: es_translation, - message_param: es_param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg_param = _message.Message(message_param) - msg = msg % msg_param - - default_translation = message_with_params % message_param - expected_translation = es_translation % es_param_translation - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_message_parameters(self, mock_translation): - message_with_params = 'A message with params: %s %s' - es_translation = 'A message with params in Spanish: %s %s' - message_param = 'A message param' - es_param_translation = 'A message param in Spanish' - another_message_param = 'Another message param' - another_es_param_translation = 'Another message param in Spanish' - - translations = {message_with_params: es_translation, - message_param: es_param_translation, - another_message_param: another_es_param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - param_1 = _message.Message(message_param) - param_2 = _message.Message(another_message_param) - msg = msg % (param_1, param_2) - - default_translation = message_with_params % (message_param, - another_message_param) - expected_translation = es_translation % (es_param_translation, - another_es_param_translation) - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('gettext.translation') - def test_translate_message_with_named_parameters(self, mock_translation): - message_with_params = 'A message with params: %(param)s' - es_translation = 'A message with params in Spanish: %(param)s' - message_param = 'A Message param' - es_param_translation = 'A message param in Spanish' - - translations = {message_with_params: es_translation, - message_param: es_param_translation} - translator = fakes.FakeTranslations.translator({'es': translations}) - mock_translation.side_effect = translator - - msg = _message.Message(message_with_params) - msg_param = _message.Message(message_param) - msg = msg % {'param': msg_param} - - default_translation = message_with_params % {'param': message_param} - expected_translation = es_translation % {'param': es_param_translation} - self.assertEqual(expected_translation, msg.translate('es')) - self.assertEqual(default_translation, msg.translate('XX')) - - @mock.patch('locale.getdefaultlocale') - @mock.patch('gettext.translation') - def test_translate_message_non_default_locale(self, - mock_translation, - mock_getdefaultlocale): - message_with_params = 'A message with params: %(param)s' - es_translation = 'A message with params in Spanish: %(param)s' - zh_translation = 'A message with params in Chinese: %(param)s' - fr_translation = 'A message with params in French: %(param)s' - - message_param = 'A Message param' - es_param_translation = 'A message param in Spanish' - zh_param_translation = 'A message param in Chinese' - fr_param_translation = 'A message param in French' - - es_translations = {message_with_params: es_translation, - message_param: es_param_translation} - zh_translations = {message_with_params: zh_translation, - message_param: zh_param_translation} - fr_translations = {message_with_params: fr_translation, - message_param: fr_param_translation} - - translator = fakes.FakeTranslations.translator({'es': es_translations, - 'zh': zh_translations, - 'fr': fr_translations}) - mock_translation.side_effect = translator - mock_getdefaultlocale.return_value = ('es',) - - msg = _message.Message(message_with_params) - msg_param = _message.Message(message_param) - msg = msg % {'param': msg_param} - - es_translation = es_translation % {'param': es_param_translation} - zh_translation = zh_translation % {'param': zh_param_translation} - fr_translation = fr_translation % {'param': fr_param_translation} - - # Because sys.getdefaultlocale() was Spanish, - # the default translation will be to Spanish - self.assertEqual(es_translation, msg) - self.assertEqual(es_translation, msg.translate()) - self.assertEqual(es_translation, msg.translate('es')) - - # Translation into other locales still works - self.assertEqual(zh_translation, msg.translate('zh')) - self.assertEqual(fr_translation, msg.translate('fr')) diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_public_api.py b/awx/lib/site-packages/oslo_i18n/tests/test_public_api.py deleted file mode 100644 index d4191053bf..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_public_api.py +++ /dev/null @@ -1,44 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""A few tests that use the public API to ensure the imports work. -""" - -import unittest - -import mock - -import oslo_i18n -from oslo_i18n import _lazy - - -class PublicAPITest(unittest.TestCase): - - def test_create_factory(self): - oslo_i18n.TranslatorFactory('domain') - - def test_install(self): - with mock.patch('six.moves.builtins'): - oslo_i18n.install('domain') - - def test_get_available_languages(self): - oslo_i18n.get_available_languages('domains') - - def test_toggle_lazy(self): - original = _lazy.USE_LAZY - try: - oslo_i18n.enable_lazy(True) - oslo_i18n.enable_lazy(False) - finally: - oslo_i18n.enable_lazy(original) - - def test_translate(self): - oslo_i18n.translate(u'string') diff --git a/awx/lib/site-packages/oslo_i18n/tests/test_translate.py b/awx/lib/site-packages/oslo_i18n/tests/test_translate.py deleted file mode 100644 index 335b28cec4..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/test_translate.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2012 Red Hat, Inc. -# Copyright 2013 IBM Corp. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import unicode_literals - -import mock -from oslotest import base as test_base - -from oslo_i18n import _message -from oslo_i18n import _translate -from oslo_i18n.tests import fakes -from oslo_i18n.tests import utils - - -class TranslateTest(test_base.BaseTestCase): - - @mock.patch('gettext.translation') - def test_translate(self, mock_translation): - en_message = 'A message in the default locale' - es_translation = 'A message in Spanish' - message = _message.Message(en_message) - - es_translations = {en_message: es_translation} - translations_map = {'es': es_translations} - translator = fakes.FakeTranslations.translator(translations_map) - mock_translation.side_effect = translator - - # translate() works on msgs and on objects whose unicode reps are msgs - obj = utils.SomeObject(message) - self.assertEqual(es_translation, _translate.translate(message, 'es')) - self.assertEqual(es_translation, _translate.translate(obj, 'es')) diff --git a/awx/lib/site-packages/oslo_i18n/tests/utils.py b/awx/lib/site-packages/oslo_i18n/tests/utils.py deleted file mode 100644 index a6ad6c3b4c..0000000000 --- a/awx/lib/site-packages/oslo_i18n/tests/utils.py +++ /dev/null @@ -1,42 +0,0 @@ -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import six - - -class SomeObject(object): - - def __init__(self, message): - self.message = message - - def __unicode__(self): - return self.message - # alias for Python 3 - __str__ = __unicode__ - - -class NoDeepCopyObject(object): - - def __init__(self, value): - self.value = value - - if six.PY3: - def __str__(self): - return str(self.value) - else: - def __unicode__(self): - return unicode(self.value) - - def __deepcopy__(self, memo): - raise TypeError('Deep Copy not supported') diff --git a/awx/lib/site-packages/oslo_serialization/__init__.py b/awx/lib/site-packages/oslo_serialization/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/oslo_serialization/jsonutils.py b/awx/lib/site-packages/oslo_serialization/jsonutils.py deleted file mode 100644 index 8dba68445f..0000000000 --- a/awx/lib/site-packages/oslo_serialization/jsonutils.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -''' -JSON related utilities. - -This module provides a few things: - - 1) A handy function for getting an object down to something that can be - JSON serialized. See to_primitive(). - - 2) Wrappers around loads() and dumps(). The dumps() wrapper will - automatically use to_primitive() for you if needed. - - 3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson - is available. -''' - - -import codecs -import datetime -import functools -import inspect -import itertools -import sys -import uuid - -is_simplejson = False -if sys.version_info < (2, 7): - # On Python <= 2.6, json module is not C boosted, so try to use - # simplejson module if available - try: - import simplejson as json - # NOTE(mriedem): Make sure we have a new enough version of simplejson - # to support the namedobject_as_tuple argument. This can be removed - # in the Kilo release when python 2.6 support is dropped. - if 'namedtuple_as_object' in inspect.getargspec(json.dumps).args: - is_simplejson = True - else: - import json - except ImportError: - import json -else: - import json - -from oslo_utils import encodeutils -from oslo_utils import importutils -from oslo_utils import timeutils -import six -import six.moves.xmlrpc_client as xmlrpclib - -netaddr = importutils.try_import("netaddr") - -_nasty_type_tests = [inspect.ismodule, inspect.isclass, inspect.ismethod, - inspect.isfunction, inspect.isgeneratorfunction, - inspect.isgenerator, inspect.istraceback, inspect.isframe, - inspect.iscode, inspect.isbuiltin, inspect.isroutine, - inspect.isabstract] - -_simple_types = (six.string_types + six.integer_types - + (type(None), bool, float)) - - -def to_primitive(value, convert_instances=False, convert_datetime=True, - level=0, max_depth=3): - """Convert a complex object into primitives. - - Handy for JSON serialization. We can optionally handle instances, - but since this is a recursive function, we could have cyclical - data structures. - - To handle cyclical data structures we could track the actual objects - visited in a set, but not all objects are hashable. Instead we just - track the depth of the object inspections and don't go too deep. - - Therefore, convert_instances=True is lossy ... be aware. - """ - # handle obvious types first - order of basic types determined by running - # full tests on nova project, resulting in the following counts: - # 572754 - # 460353 - # 379632 - # 274610 - # 199918 - # 114200 - # 51817 - # 26164 - # 6491 - # 283 - # 19 - if isinstance(value, _simple_types): - return value - - if isinstance(value, datetime.datetime): - if convert_datetime: - return timeutils.strtime(value) - else: - return value - - if isinstance(value, uuid.UUID): - return six.text_type(value) - - # value of itertools.count doesn't get caught by nasty_type_tests - # and results in infinite loop when list(value) is called. - if type(value) == itertools.count: - return six.text_type(value) - - # FIXME(vish): Workaround for LP bug 852095. Without this workaround, - # tests that raise an exception in a mocked method that - # has a @wrap_exception with a notifier will fail. If - # we up the dependency to 0.5.4 (when it is released) we - # can remove this workaround. - if getattr(value, '__module__', None) == 'mox': - return 'mock' - - if level > max_depth: - return '?' - - # The try block may not be necessary after the class check above, - # but just in case ... - try: - recursive = functools.partial(to_primitive, - convert_instances=convert_instances, - convert_datetime=convert_datetime, - level=level, - max_depth=max_depth) - if isinstance(value, dict): - return dict((k, recursive(v)) for k, v in six.iteritems(value)) - - # It's not clear why xmlrpclib created their own DateTime type, but - # for our purposes, make it a datetime type which is explicitly - # handled - if isinstance(value, xmlrpclib.DateTime): - value = datetime.datetime(*tuple(value.timetuple())[:6]) - - if convert_datetime and isinstance(value, datetime.datetime): - return timeutils.strtime(value) - elif hasattr(value, 'iteritems'): - return recursive(dict(value.iteritems()), level=level + 1) - elif hasattr(value, '__iter__'): - return list(map(recursive, value)) - elif convert_instances and hasattr(value, '__dict__'): - # Likely an instance of something. Watch for cycles. - # Ignore class member vars. - return recursive(value.__dict__, level=level + 1) - elif netaddr and isinstance(value, netaddr.IPAddress): - return six.text_type(value) - elif any(test(value) for test in _nasty_type_tests): - return six.text_type(value) - return value - except TypeError: - # Class objects are tricky since they may define something like - # __iter__ defined but it isn't callable as list(). - return six.text_type(value) - - -JSONEncoder = json.JSONEncoder -JSONDecoder = json.JSONDecoder - - -def dumps(obj, default=to_primitive, **kwargs): - """Serialize ``obj`` to a JSON formatted ``str``. - - :param obj: object to be serialized - :param default: function that returns a serializable version of an object - :param kwargs: extra named parameters, please see documentation \ - of `json.dumps `_ - :returns: json formatted string - """ - if is_simplejson: - kwargs['namedtuple_as_object'] = False - return json.dumps(obj, default=default, **kwargs) - - -def dump(obj, fp, *args, **kwargs): - """Serialize ``obj`` as a JSON formatted stream to ``fp`` - - :param obj: object to be serialized - :param fp: a ``.write()``-supporting file-like object - :param default: function that returns a serializable version of an object - :param args: extra arguments, please see documentation \ - of `json.dump `_ - :param kwargs: extra named parameters, please see documentation \ - of `json.dump `_ - """ - default = kwargs.get('default', to_primitive) - if is_simplejson: - kwargs['namedtuple_as_object'] = False - return json.dump(obj, fp, default=default, *args, **kwargs) - - -def loads(s, encoding='utf-8', **kwargs): - """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON - - :param s: string to deserialize - :param encoding: encoding used to interpret the string - :param kwargs: extra named parameters, please see documentation \ - of `json.loads `_ - :returns: python object - """ - return json.loads(encodeutils.safe_decode(s, encoding), **kwargs) - - -def load(fp, encoding='utf-8', **kwargs): - """Deserialize ``fp`` to a Python object. - - :param fp: a ``.read()`` -supporting file-like object - :param encoding: encoding used to interpret the string - :param kwargs: extra named parameters, please see documentation \ - of `json.loads `_ - :returns: python object - """ - return json.load(codecs.getreader(encoding)(fp), **kwargs) - - -try: - import anyjson -except ImportError: - pass -else: - anyjson._modules.append((__name__, 'dumps', TypeError, - 'loads', ValueError, 'load')) - anyjson.force_implementation(__name__) diff --git a/awx/lib/site-packages/oslo_serialization/msgpackutils.py b/awx/lib/site-packages/oslo_serialization/msgpackutils.py deleted file mode 100644 index 5a7f038d16..0000000000 --- a/awx/lib/site-packages/oslo_serialization/msgpackutils.py +++ /dev/null @@ -1,169 +0,0 @@ -# Copyright (C) 2015 Yahoo! Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime -import itertools -import sys -import uuid - -import msgpack -from oslo_utils import importutils -from pytz import timezone -import six -import six.moves.xmlrpc_client as xmlrpclib - -netaddr = importutils.try_import("netaddr") - -# NOTE(harlowja): itertools.count only started to take a step value -# in python 2.7+ so we can't use it in 2.6... -if sys.version_info[0:2] == (2, 6): - _PY26 = True -else: - _PY26 = False - - -def _serialize_datetime(dt): - dct = { - 'day': dt.day, - 'month': dt.month, - 'year': dt.year, - 'hour': dt.hour, - 'minute': dt.minute, - 'second': dt.second, - 'microsecond': dt.microsecond, - } - if dt.tzinfo: - dct['tz'] = dt.tzinfo.tzname(None) - return dumps(dct) - - -def _deserialize_datetime(blob): - dct = loads(blob) - dt = datetime.datetime(day=dct['day'], - month=dct['month'], - year=dct['year'], - hour=dct['hour'], - minute=dct['minute'], - second=dct['second'], - microsecond=dct['microsecond']) - if 'tz' in dct: - tzinfo = timezone(dct['tz']) - dt = tzinfo.localize(dt) - return dt - - -def _serialize_date(d): - dct = { - 'year': d.year, - 'month': d.month, - 'day': d.day, - } - return dumps(dct) - - -def _deserialize_date(blob): - dct = loads(blob) - return datetime.date(year=dct['year'], - month=dct['month'], - day=dct['day']) - - -def _serializer(obj): - # Applications can assign 0 to 127 to store - # application-specific type information... - if isinstance(obj, uuid.UUID): - return msgpack.ExtType(0, six.text_type(obj.hex).encode('ascii')) - if isinstance(obj, datetime.datetime): - return msgpack.ExtType(1, _serialize_datetime(obj)) - if type(obj) == itertools.count: - # FIXME(harlowja): figure out a better way to avoid hacking into - # the string representation of count to get at the right numbers... - obj = six.text_type(obj) - start = obj.find("(") + 1 - end = obj.rfind(")") - pieces = obj[start:end].split(",") - if len(pieces) == 1: - start = int(pieces[0]) - step = 1 - else: - start = int(pieces[0]) - step = int(pieces[1]) - return msgpack.ExtType(2, msgpack.packb([start, step])) - if netaddr and isinstance(obj, netaddr.IPAddress): - return msgpack.ExtType(3, msgpack.packb(obj.value)) - if isinstance(obj, (set, frozenset)): - value = dumps(list(obj)) - if isinstance(obj, set): - ident = 4 - else: - ident = 5 - return msgpack.ExtType(ident, value) - if isinstance(obj, xmlrpclib.DateTime): - dt = datetime.datetime(*tuple(obj.timetuple())[:6]) - return msgpack.ExtType(6, _serialize_datetime(dt)) - if isinstance(obj, datetime.date): - return msgpack.ExtType(7, _serialize_date(obj)) - raise TypeError("Unknown type: %r" % (obj,)) - - -def _unserializer(code, data): - if code == 0: - return uuid.UUID(hex=six.text_type(data, encoding='ascii')) - if code == 1: - return _deserialize_datetime(data) - if code == 2: - value = msgpack.unpackb(data) - if not _PY26: - return itertools.count(value[0], value[1]) - else: - return itertools.count(value[0]) - if netaddr and code == 3: - value = msgpack.unpackb(data) - return netaddr.IPAddress(value) - if code in (4, 5): - value = loads(data) - if code == 4: - return set(value) - else: - return frozenset(value) - if code == 6: - dt = _deserialize_datetime(data) - return xmlrpclib.DateTime(dt.timetuple()) - if code == 7: - return _deserialize_date(data) - return msgpack.ExtType(code, data) - - -def load(fp): - """Deserialize ``fp`` into a Python object.""" - # NOTE(harlowja): the reason we can't use the more native msgpack functions - # here is that the unpack() function (oddly) doesn't seem to take a - # 'ext_hook' parameter.. - return msgpack.Unpacker(fp, ext_hook=_unserializer, - encoding='utf-8').unpack() - - -def dump(obj, fp): - """Serialize ``obj`` as a messagepack formatted stream to ``fp``.""" - return msgpack.pack(obj, fp, default=_serializer, use_bin_type=True) - - -def dumps(obj): - """Serialize ``obj`` to a messagepack formatted ``str``.""" - return msgpack.packb(obj, default=_serializer, use_bin_type=True) - - -def loads(s): - """Deserialize ``s`` messagepack ``str`` into a Python object.""" - return msgpack.unpackb(s, ext_hook=_unserializer, encoding='utf-8') diff --git a/awx/lib/site-packages/oslo_serialization/tests/__init__.py b/awx/lib/site-packages/oslo_serialization/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/oslo_serialization/tests/test_jsonutils.py b/awx/lib/site-packages/oslo_serialization/tests/test_jsonutils.py deleted file mode 100644 index 9709cb66be..0000000000 --- a/awx/lib/site-packages/oslo_serialization/tests/test_jsonutils.py +++ /dev/null @@ -1,275 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import collections -import datetime -import json - -import mock -import netaddr -from oslo_i18n import fixture -from oslotest import base as test_base -import simplejson -import six -import six.moves.xmlrpc_client as xmlrpclib - -from oslo_serialization import jsonutils - - -class JSONUtilsTestMixin(object): - - json_impl = None - - def setUp(self): - super(JSONUtilsTestMixin, self).setUp() - self.json_patcher = mock.patch.multiple( - jsonutils, json=self.json_impl, - is_simplejson=self.json_impl is simplejson) - self.json_impl_mock = self.json_patcher.start() - - def tearDown(self): - self.json_patcher.stop() - super(JSONUtilsTestMixin, self).tearDown() - - def test_dumps(self): - self.assertEqual('{"a": "b"}', jsonutils.dumps({'a': 'b'})) - - def test_dumps_namedtuple(self): - n = collections.namedtuple("foo", "bar baz")(1, 2) - self.assertEqual('[1, 2]', jsonutils.dumps(n)) - - def test_dump(self): - expected = '{"a": "b"}' - json_dict = {'a': 'b'} - - fp = six.StringIO() - jsonutils.dump(json_dict, fp) - - self.assertEqual(expected, fp.getvalue()) - - def test_dump_namedtuple(self): - expected = '[1, 2]' - json_dict = collections.namedtuple("foo", "bar baz")(1, 2) - - fp = six.StringIO() - jsonutils.dump(json_dict, fp) - - self.assertEqual(expected, fp.getvalue()) - - def test_loads(self): - self.assertEqual({'a': 'b'}, jsonutils.loads('{"a": "b"}')) - - def test_loads_unicode(self): - self.assertIsInstance(jsonutils.loads(b'"foo"'), six.text_type) - self.assertIsInstance(jsonutils.loads(u'"foo"'), six.text_type) - - # 'test' in Ukrainian - i18n_str_unicode = u'"\u0442\u0435\u0441\u0442"' - self.assertIsInstance(jsonutils.loads(i18n_str_unicode), six.text_type) - - i18n_str = i18n_str_unicode.encode('utf-8') - self.assertIsInstance(jsonutils.loads(i18n_str), six.text_type) - - def test_loads_with_kwargs(self): - jsontext = u'{"foo": 3}' - result = jsonutils.loads(jsontext, parse_int=lambda x: 5) - self.assertEqual(5, result['foo']) - - def test_load(self): - - jsontext = u'{"a": "\u0442\u044d\u0441\u0442"}' - expected = {u'a': u'\u0442\u044d\u0441\u0442'} - - for encoding in ('utf-8', 'cp1251'): - fp = six.BytesIO(jsontext.encode(encoding)) - result = jsonutils.load(fp, encoding=encoding) - self.assertEqual(expected, result) - for key, val in result.items(): - self.assertIsInstance(key, six.text_type) - self.assertIsInstance(val, six.text_type) - - -class JSONUtilsTestJson(JSONUtilsTestMixin, test_base.BaseTestCase): - json_impl = json - - -class JSONUtilsTestSimpleJson(JSONUtilsTestMixin, test_base.BaseTestCase): - json_impl = simplejson - - -class ToPrimitiveTestCase(test_base.BaseTestCase): - def setUp(self): - super(ToPrimitiveTestCase, self).setUp() - self.trans_fixture = self.useFixture(fixture.Translation()) - - def test_list(self): - self.assertEqual(jsonutils.to_primitive([1, 2, 3]), [1, 2, 3]) - - def test_empty_list(self): - self.assertEqual(jsonutils.to_primitive([]), []) - - def test_tuple(self): - self.assertEqual(jsonutils.to_primitive((1, 2, 3)), [1, 2, 3]) - - def test_dict(self): - self.assertEqual(jsonutils.to_primitive(dict(a=1, b=2, c=3)), - dict(a=1, b=2, c=3)) - - def test_empty_dict(self): - self.assertEqual(jsonutils.to_primitive({}), {}) - - def test_datetime(self): - x = datetime.datetime(1920, 2, 3, 4, 5, 6, 7) - self.assertEqual(jsonutils.to_primitive(x), - '1920-02-03T04:05:06.000007') - - def test_datetime_preserve(self): - x = datetime.datetime(1920, 2, 3, 4, 5, 6, 7) - self.assertEqual(jsonutils.to_primitive(x, convert_datetime=False), x) - - def test_DateTime(self): - x = xmlrpclib.DateTime() - x.decode("19710203T04:05:06") - self.assertEqual(jsonutils.to_primitive(x), - '1971-02-03T04:05:06.000000') - - def test_iter(self): - class IterClass(object): - def __init__(self): - self.data = [1, 2, 3, 4, 5] - self.index = 0 - - def __iter__(self): - return self - - def next(self): - if self.index == len(self.data): - raise StopIteration - self.index = self.index + 1 - return self.data[self.index - 1] - __next__ = next - - x = IterClass() - self.assertEqual(jsonutils.to_primitive(x), [1, 2, 3, 4, 5]) - - def test_iteritems(self): - class IterItemsClass(object): - def __init__(self): - self.data = dict(a=1, b=2, c=3).items() - self.index = 0 - - def iteritems(self): - return self.data - - x = IterItemsClass() - p = jsonutils.to_primitive(x) - self.assertEqual(p, {'a': 1, 'b': 2, 'c': 3}) - - def test_iteritems_with_cycle(self): - class IterItemsClass(object): - def __init__(self): - self.data = dict(a=1, b=2, c=3) - self.index = 0 - - def iteritems(self): - return self.data.items() - - x = IterItemsClass() - x2 = IterItemsClass() - x.data['other'] = x2 - x2.data['other'] = x - - # If the cycle isn't caught, to_primitive() will eventually result in - # an exception due to excessive recursion depth. - jsonutils.to_primitive(x) - - def test_instance(self): - class MysteryClass(object): - a = 10 - - def __init__(self): - self.b = 1 - - x = MysteryClass() - self.assertEqual(jsonutils.to_primitive(x, convert_instances=True), - dict(b=1)) - - self.assertEqual(jsonutils.to_primitive(x), x) - - def test_typeerror(self): - x = bytearray # Class, not instance - if six.PY3: - self.assertEqual(jsonutils.to_primitive(x), u"") - else: - self.assertEqual(jsonutils.to_primitive(x), u"") - - def test_nasties(self): - def foo(): - pass - x = [datetime, foo, dir] - ret = jsonutils.to_primitive(x) - self.assertEqual(len(ret), 3) - self.assertTrue(ret[0].startswith(u".foo at 0x' - )) - else: - self.assertTrue(ret[1].startswith('') - - def test_depth(self): - class LevelsGenerator(object): - def __init__(self, levels): - self._levels = levels - - def iteritems(self): - if self._levels == 0: - return iter([]) - else: - return iter([(0, LevelsGenerator(self._levels - 1))]) - - l4_obj = LevelsGenerator(4) - - json_l2 = {0: {0: '?'}} - json_l3 = {0: {0: {0: '?'}}} - json_l4 = {0: {0: {0: {0: '?'}}}} - - ret = jsonutils.to_primitive(l4_obj, max_depth=2) - self.assertEqual(ret, json_l2) - - ret = jsonutils.to_primitive(l4_obj, max_depth=3) - self.assertEqual(ret, json_l3) - - ret = jsonutils.to_primitive(l4_obj, max_depth=4) - self.assertEqual(ret, json_l4) - - def test_ipaddr(self): - thing = {'ip_addr': netaddr.IPAddress('1.2.3.4')} - ret = jsonutils.to_primitive(thing) - self.assertEqual({'ip_addr': '1.2.3.4'}, ret) - - def test_message_with_param(self): - msg = self.trans_fixture.lazy('A message with param: %s') - msg = msg % 'test_domain' - ret = jsonutils.to_primitive(msg) - self.assertEqual(msg, ret) - - def test_message_with_named_param(self): - msg = self.trans_fixture.lazy('A message with params: %(param)s') - msg = msg % {'param': 'hello'} - ret = jsonutils.to_primitive(msg) - self.assertEqual(msg, ret) diff --git a/awx/lib/site-packages/oslo_utils/__init__.py b/awx/lib/site-packages/oslo_utils/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/oslo_utils/_i18n.py b/awx/lib/site-packages/oslo_utils/_i18n.py deleted file mode 100644 index c690fc34d9..0000000000 --- a/awx/lib/site-packages/oslo_utils/_i18n.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2014 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html . - -""" - -import oslo_i18n - - -_translators = oslo_i18n.TranslatorFactory(domain='oslo.utils') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/awx/lib/site-packages/oslo_utils/encodeutils.py b/awx/lib/site-packages/oslo_utils/encodeutils.py deleted file mode 100644 index 14bd717590..0000000000 --- a/awx/lib/site-packages/oslo_utils/encodeutils.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import sys - -import six - - -def safe_decode(text, incoming=None, errors='strict'): - """Decodes incoming text/bytes string using `incoming` if they're not - already unicode. - - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a unicode `incoming` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be decoded" % type(text)) - - if isinstance(text, six.text_type): - return text - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - try: - return text.decode(incoming, errors) - except UnicodeDecodeError: - # Note(flaper87) If we get here, it means that - # sys.stdin.encoding / sys.getdefaultencoding - # didn't return a suitable encoding to decode - # text. This happens mostly when global LANG - # var is not set correctly and there's no - # default encoding. In this case, most likely - # python will use ASCII or ANSI encoders as - # default encodings but they won't be capable - # of decoding non-ASCII characters. - # - # Also, UTF-8 is being used since it's an ASCII - # extension. - return text.decode('utf-8', errors) - - -def safe_encode(text, incoming=None, - encoding='utf-8', errors='strict'): - """Encodes incoming text/bytes string using `encoding`. - - If incoming is not specified, text is expected to be encoded with - current python's default encoding. (`sys.getdefaultencoding`) - - :param incoming: Text's current encoding - :param encoding: Expected encoding for text (Default UTF-8) - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: text or a bytestring `encoding` encoded - representation of it. - :raises TypeError: If text is not an instance of str - """ - if not isinstance(text, (six.string_types, six.binary_type)): - raise TypeError("%s can't be encoded" % type(text)) - - if not incoming: - incoming = (sys.stdin.encoding or - sys.getdefaultencoding()) - - # Avoid case issues in comparisons - if hasattr(incoming, 'lower'): - incoming = incoming.lower() - if hasattr(encoding, 'lower'): - encoding = encoding.lower() - - if isinstance(text, six.text_type): - return text.encode(encoding, errors) - elif text and encoding != incoming: - # Decode text before encoding it with `encoding` - text = safe_decode(text, incoming, errors) - return text.encode(encoding, errors) - else: - return text diff --git a/awx/lib/site-packages/oslo_utils/eventletutils.py b/awx/lib/site-packages/oslo_utils/eventletutils.py deleted file mode 100644 index 01021a4cf5..0000000000 --- a/awx/lib/site-packages/oslo_utils/eventletutils.py +++ /dev/null @@ -1,98 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2015 Yahoo! Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - -from oslo_utils import importutils - -# These may or may not exist; so carefully import them if we can... -_eventlet = importutils.try_import('eventlet') -_patcher = importutils.try_import('eventlet.patcher') - -# Attribute that can be used by others to see if eventlet is even currently -# useable (can be used in unittests to skip test cases or test classes that -# require eventlet to work). -EVENTLET_AVAILABLE = all((_eventlet, _patcher)) - -# Taken from eventlet.py (v0.16.1) patcher code (it's not a accessible set -# for some reason...) -_ALL_PATCH = frozenset(['__builtin__', 'MySQLdb', 'os', - 'psycopg', 'select', 'socket', 'thread', 'time']) - - -def warn_eventlet_not_patched(expected_patched_modules=None, - what='this library'): - """Warns if eventlet is being used without patching provided modules. - - :param expected_patched_modules: list of modules to check to ensure that - they are patched (and to warn if they - are not); these names should correspond - to the names passed into the eventlet - monkey_patch() routine. If not provided - then *all* the modules that could be - patched are checked. The currently valid - selection is one or multiple of - ['MySQLdb', '__builtin__', 'all', 'os', - 'psycopg', 'select', 'socket', 'thread', - 'time'] (where 'all' has an inherent - special meaning). - :type expected_patched_modules: list/tuple/iterable - :param what: string to merge into the warnings message to identify - what is being checked (used in forming the emitted warnings - message). - :type what: string - """ - if not expected_patched_modules: - expanded_patched_modules = _ALL_PATCH.copy() - else: - expanded_patched_modules = set() - for m in expected_patched_modules: - if m == 'all': - expanded_patched_modules.update(_ALL_PATCH) - else: - if m not in _ALL_PATCH: - raise ValueError("Unknown module '%s' requested to check" - " if patched" % m) - else: - expanded_patched_modules.add(m) - if EVENTLET_AVAILABLE: - try: - # The patcher code stores a dictionary here of all modules - # names -> whether it was patched... - # - # Example: - # - # >>> _patcher.monkey_patch(os=True) - # >>> print(_patcher.already_patched) - # {'os': True} - maybe_patched = bool(_patcher.already_patched) - except AttributeError: - # Assume it is patched (the attribute used here doesn't appear - # to be a public documented API so we will assume that everything - # is patched when that attribute isn't there to be safe...) - maybe_patched = True - if maybe_patched: - not_patched = [] - for m in sorted(expanded_patched_modules): - if not _patcher.is_monkey_patched(m): - not_patched.append(m) - if not_patched: - warnings.warn("It is highly recommended that when eventlet" - " is used that the %s modules are monkey" - " patched when using %s (to avoid" - " spurious or unexpected lock-ups" - " and/or hangs)" % (not_patched, what), - RuntimeWarning, stacklevel=3) diff --git a/awx/lib/site-packages/oslo_utils/excutils.py b/awx/lib/site-packages/oslo_utils/excutils.py deleted file mode 100644 index 4e4c6693b5..0000000000 --- a/awx/lib/site-packages/oslo_utils/excutils.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# Copyright 2012, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exception related utilities. -""" - -import logging -import sys -import time -import traceback - -import six - -from oslo_utils._i18n import _LE - - -class save_and_reraise_exception(object): - """Save current exception, run some code and then re-raise. - - In some cases the exception context can be cleared, resulting in None - being attempted to be re-raised after an exception handler is run. This - can happen when eventlet switches greenthreads or when running an - exception handler, code raises and catches an exception. In both - cases the exception context will be cleared. - - To work around this, we save the exception state, run handler code, and - then re-raise the original exception. If another exception occurs, the - saved exception is logged and the new exception is re-raised. - - In some cases the caller may not want to re-raise the exception, and - for those circumstances this context provides a reraise flag that - can be used to suppress the exception. For example:: - - except Exception: - with save_and_reraise_exception() as ctxt: - decide_if_need_reraise() - if not should_be_reraised: - ctxt.reraise = False - - If another exception occurs and reraise flag is False, - the saved exception will not be logged. - - If the caller wants to raise new exception during exception handling - he/she sets reraise to False initially with an ability to set it back to - True if needed:: - - except Exception: - with save_and_reraise_exception(reraise=False) as ctxt: - [if statements to determine whether to raise a new exception] - # Not raising a new exception, so reraise - ctxt.reraise = True - """ - def __init__(self, reraise=True, logger=None): - self.reraise = reraise - if logger is None: - logger = logging.getLogger() - self.logger = logger - - def __enter__(self): - self.type_, self.value, self.tb, = sys.exc_info() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if exc_type is not None: - if self.reraise: - self.logger.error(_LE('Original exception being dropped: %s'), - traceback.format_exception(self.type_, - self.value, - self.tb)) - return False - if self.reraise: - six.reraise(self.type_, self.value, self.tb) - - -def forever_retry_uncaught_exceptions(infunc): - def inner_func(*args, **kwargs): - last_log_time = 0 - last_exc_message = None - exc_count = 0 - while True: - try: - return infunc(*args, **kwargs) - except Exception as exc: - this_exc_message = six.u(str(exc)) - if this_exc_message == last_exc_message: - exc_count += 1 - else: - exc_count = 1 - # Do not log any more frequently than once a minute unless - # the exception message changes - cur_time = int(time.time()) - if (cur_time - last_log_time > 60 or - this_exc_message != last_exc_message): - logging.exception( - _LE('Unexpected exception occurred %d time(s)... ' - 'retrying.') % exc_count) - last_log_time = cur_time - last_exc_message = this_exc_message - exc_count = 0 - # This should be a very rare event. In case it isn't, do - # a sleep. - time.sleep(1) - return inner_func diff --git a/awx/lib/site-packages/oslo_utils/fixture.py b/awx/lib/site-packages/oslo_utils/fixture.py deleted file mode 100644 index 9d91695a69..0000000000 --- a/awx/lib/site-packages/oslo_utils/fixture.py +++ /dev/null @@ -1,45 +0,0 @@ - -# Copyright 2015 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import fixtures - -from oslo_utils import timeutils - - -class TimeFixture(fixtures.Fixture): - """A fixture for overriding the time returned by timeutils.utcnow(). - - :param override_time: datetime instance or list thereof. If not given, - defaults to the current UTC time. - - """ - - def __init__(self, override_time=None): - super(TimeFixture, self).__init__() - self._override_time = override_time - - def setUp(self): - super(TimeFixture, self).setUp() - timeutils.set_time_override(self._override_time) - self.addCleanup(timeutils.clear_time_override) - - def advance_time_delta(self, timedelta): - """Advance overridden time using a datetime.timedelta.""" - timeutils.advance_time_delta(timedelta) - - def advance_time_seconds(self, seconds): - """Advance overridden time by seconds.""" - timeutils.advance_time_seconds(seconds) diff --git a/awx/lib/site-packages/oslo_utils/importutils.py b/awx/lib/site-packages/oslo_utils/importutils.py deleted file mode 100644 index 043f81728e..0000000000 --- a/awx/lib/site-packages/oslo_utils/importutils.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Import related utilities and helper functions. -""" - -import sys -import traceback - - -def import_class(import_str): - """Returns a class from a string including module and class.""" - mod_str, _sep, class_str = import_str.rpartition('.') - __import__(mod_str) - try: - return getattr(sys.modules[mod_str], class_str) - except AttributeError: - raise ImportError('Class %s cannot be found (%s)' % - (class_str, - traceback.format_exception(*sys.exc_info()))) - - -def import_object(import_str, *args, **kwargs): - """Import a class and return an instance of it.""" - return import_class(import_str)(*args, **kwargs) - - -def import_object_ns(name_space, import_str, *args, **kwargs): - """Tries to import object from default namespace. - - Imports a class and return an instance of it, first by trying - to find the class in a default namespace, then failing back to - a full path if not found in the default namespace. - """ - import_value = "%s.%s" % (name_space, import_str) - try: - return import_class(import_value)(*args, **kwargs) - except ImportError: - return import_class(import_str)(*args, **kwargs) - - -def import_module(import_str): - """Import a module.""" - __import__(import_str) - return sys.modules[import_str] - - -def import_versioned_module(version, submodule=None): - module = 'oslo.v%s' % version - if submodule: - module = '.'.join((module, submodule)) - return import_module(module) - - -def try_import(import_str, default=None): - """Try to import a module and if it fails return default.""" - try: - return import_module(import_str) - except ImportError: - return default diff --git a/awx/lib/site-packages/oslo_utils/netutils.py b/awx/lib/site-packages/oslo_utils/netutils.py deleted file mode 100644 index bdb463200b..0000000000 --- a/awx/lib/site-packages/oslo_utils/netutils.py +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Network-related utilities and helper functions. -""" - -import logging -import os -import socket - -import netaddr -import netifaces -from six.moves.urllib import parse - -from oslo_utils._i18n import _ -from oslo_utils._i18n import _LI -from oslo_utils._i18n import _LW - -LOG = logging.getLogger(__name__) -_IS_IPV6_ENABLED = None - - -def parse_host_port(address, default_port=None): - """Interpret a string as a host:port pair. - - An IPv6 address MUST be escaped if accompanied by a port, - because otherwise ambiguity ensues: 2001:db8:85a3::8a2e:370:7334 - means both [2001:db8:85a3::8a2e:370:7334] and - [2001:db8:85a3::8a2e:370]:7334. - - >>> parse_host_port('server01:80') - ('server01', 80) - >>> parse_host_port('server01') - ('server01', None) - >>> parse_host_port('server01', default_port=1234) - ('server01', 1234) - >>> parse_host_port('[::1]:80') - ('::1', 80) - >>> parse_host_port('[::1]') - ('::1', None) - >>> parse_host_port('[::1]', default_port=1234) - ('::1', 1234) - >>> parse_host_port('2001:db8:85a3::8a2e:370:7334', default_port=1234) - ('2001:db8:85a3::8a2e:370:7334', 1234) - >>> parse_host_port(None) - (None, None) - """ - if not address: - return (None, None) - - if address[0] == '[': - # Escaped ipv6 - _host, _port = address[1:].split(']') - host = _host - if ':' in _port: - port = _port.split(':')[1] - else: - port = default_port - else: - if address.count(':') == 1: - host, port = address.split(':') - else: - # 0 means ipv4, >1 means ipv6. - # We prohibit unescaped ipv6 addresses with port. - host = address - port = default_port - - return (host, None if port is None else int(port)) - - -def is_valid_ipv4(address): - """Verify that address represents a valid IPv4 address. - - :param address: Value to verify - :type address: string - :returns: bool - """ - try: - return netaddr.valid_ipv4(address) - except Exception: - return False - - -def is_valid_ipv6(address): - """Verify that address represents a valid IPv6 address. - - :param address: Value to verify - :type address: string - :returns: bool - """ - try: - return netaddr.valid_ipv6(address) - except Exception: - return False - - -def get_ipv6_addr_by_EUI64(prefix, mac): - """Calculate IPv6 address using EUI-64 specification. - - This method calculates the IPv6 address using the EUI-64 - addressing scheme as explained in rfc2373. - - :param prefix: IPv6 prefix. - :param mac: IEEE 802 48-bit MAC address. - :returns: IPv6 address on success. - :raises ValueError, TypeError: For any invalid input. - """ - # Check if the prefix is an IPv4 address - if netaddr.valid_ipv4(prefix): - msg = _("Unable to generate IP address by EUI64 for IPv4 prefix") - raise ValueError(msg) - try: - eui64 = int(netaddr.EUI(mac).eui64()) - prefix = netaddr.IPNetwork(prefix) - return netaddr.IPAddress(prefix.first + eui64 ^ (1 << 57)) - except (ValueError, netaddr.AddrFormatError): - raise ValueError(_('Bad prefix or mac format for generating IPv6 ' - 'address by EUI-64: %(prefix)s, %(mac)s:') - % {'prefix': prefix, 'mac': mac}) - except TypeError: - raise TypeError(_('Bad prefix type for generating IPv6 address by ' - 'EUI-64: %s') % prefix) - - -def is_ipv6_enabled(): - """Check if IPv6 support is enabled on the platform. - - This api will look into the proc entries of the platform to figure - out the status of IPv6 support on the platform. - - :returns: True if the platform has IPv6 support, False otherwise. - - """ - - global _IS_IPV6_ENABLED - - if _IS_IPV6_ENABLED is None: - disabled_ipv6_path = "/proc/sys/net/ipv6/conf/default/disable_ipv6" - if os.path.exists(disabled_ipv6_path): - with open(disabled_ipv6_path, 'r') as f: - disabled = f.read().strip() - _IS_IPV6_ENABLED = disabled == "0" - else: - _IS_IPV6_ENABLED = False - return _IS_IPV6_ENABLED - - -def is_valid_ip(address): - """Verify that address represents a valid IP address. - - :param address: Value to verify - :type address: string - :returns: bool - """ - return is_valid_ipv4(address) or is_valid_ipv6(address) - - -def is_valid_port(port): - """Verify that port represents a valid port number.""" - try: - val = int(port) - except (ValueError, TypeError): - return False - - return (val > 0 and val <= 65535) - - -def get_my_ipv4(): - """Returns the actual ipv4 of the local machine. - - This code figures out what source address would be used if some traffic - were to be sent out to some well known address on the Internet. In this - case, IP from RFC5737 is used, but the specific address does not - matter much. No traffic is actually sent. - """ - try: - csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - csock.connect(('192.0.2.0', 80)) - (addr, port) = csock.getsockname() - csock.close() - return addr - except socket.error: - return _get_my_ipv4_address() - - -def _get_my_ipv4_address(): - """Figure out the best ipv4 - """ - LOCALHOST = '127.0.0.1' - gtw = netifaces.gateways() - try: - interface = gtw['default'][netifaces.AF_INET][1] - except (KeyError, IndexError): - LOG.info(_LI('Could not determine default network interface, ' - 'using 127.0.0.1 for IPv4 address')) - return LOCALHOST - - try: - return netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr'] - except (KeyError, IndexError): - LOG.info(_LI('Could not determine IPv4 address for interface %s, ' - 'using 127.0.0.1'), - interface) - except Exception as e: - LOG.info(_LI('Could not determine IPv4 address for ' - 'interface %(interface)s: %(error)s'), - {'interface': interface, 'error': e}) - return LOCALHOST - - -class _ModifiedSplitResult(parse.SplitResult): - """Split results class for urlsplit.""" - - # NOTE(dims): The functions below are needed for Python 2.6.x. - # We can remove these when we drop support for 2.6.x. - @property - def hostname(self): - netloc = self.netloc.split('@', 1)[-1] - host, port = parse_host_port(netloc) - return host - - @property - def port(self): - netloc = self.netloc.split('@', 1)[-1] - host, port = parse_host_port(netloc) - return port - - def params(self, collapse=True): - """Extracts the query parameters from the split urls components. - - This method will provide back as a dictionary the query parameter - names and values that were provided in the url. - - :param collapse: Boolean, turn on or off collapsing of query values - with the same name. Since a url can contain the same query parameter - name with different values it may or may not be useful for users to - care that this has happened. This parameter when True uses the - last value that was given for a given name, while if False it will - retain all values provided by associating the query parameter name with - a list of values instead of a single (non-list) value. - """ - if self.query: - if collapse: - return dict(parse.parse_qsl(self.query)) - else: - params = {} - for (key, value) in parse.parse_qsl(self.query): - if key in params: - if isinstance(params[key], list): - params[key].append(value) - else: - params[key] = [params[key], value] - else: - params[key] = value - return params - else: - return {} - - -def urlsplit(url, scheme='', allow_fragments=True): - """Parse a URL using urlparse.urlsplit(), splitting query and fragments. - This function papers over Python issue9374_ when needed. - - .. _issue9374: http://bugs.python.org/issue9374 - - The parameters are the same as urlparse.urlsplit. - """ - scheme, netloc, path, query, fragment = parse.urlsplit( - url, scheme, allow_fragments) - if allow_fragments and '#' in path: - path, fragment = path.split('#', 1) - if '?' in path: - path, query = path.split('?', 1) - return _ModifiedSplitResult(scheme, netloc, - path, query, fragment) - - -def set_tcp_keepalive(sock, tcp_keepalive=True, - tcp_keepidle=None, - tcp_keepalive_interval=None, - tcp_keepalive_count=None): - """Set values for tcp keepalive parameters - - This function configures tcp keepalive parameters if users wish to do - so. - - :param tcp_keepalive: Boolean, turn on or off tcp_keepalive. If users are - not sure, this should be True, and default values will be used. - - :param tcp_keepidle: time to wait before starting to send keepalive probes - :param tcp_keepalive_interval: time between successive probes, once the - initial wait time is over - :param tcp_keepalive_count: number of probes to send before the connection - is killed - """ - - # NOTE(praneshp): Despite keepalive being a tcp concept, the level is - # still SOL_SOCKET. This is a quirk. - if isinstance(tcp_keepalive, bool): - sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, tcp_keepalive) - else: - raise TypeError("tcp_keepalive must be a boolean") - - if not tcp_keepalive: - return - - # These options aren't available in the OS X version of eventlet, - # Idle + Count * Interval effectively gives you the total timeout. - if tcp_keepidle is not None: - if hasattr(socket, 'TCP_KEEPIDLE'): - sock.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPIDLE, - tcp_keepidle) - else: - LOG.warning(_LW('tcp_keepidle not available on your system')) - if tcp_keepalive_interval is not None: - if hasattr(socket, 'TCP_KEEPINTVL'): - sock.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPINTVL, - tcp_keepalive_interval) - else: - LOG.warning(_LW('tcp_keepintvl not available on your system')) - if tcp_keepalive_count is not None: - if hasattr(socket, 'TCP_KEEPCNT'): - sock.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPCNT, - tcp_keepalive_count) - else: - LOG.warning(_LW('tcp_keepcnt not available on your system')) diff --git a/awx/lib/site-packages/oslo_utils/reflection.py b/awx/lib/site-packages/oslo_utils/reflection.py deleted file mode 100644 index b964cf340c..0000000000 --- a/awx/lib/site-packages/oslo_utils/reflection.py +++ /dev/null @@ -1,208 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2012-2013 Yahoo! Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import inspect -import types - -import six - -try: - _TYPE_TYPE = types.TypeType -except AttributeError: - _TYPE_TYPE = type - -# See: https://docs.python.org/2/library/__builtin__.html#module-__builtin__ -# and see https://docs.python.org/2/reference/executionmodel.html (and likely -# others)... -_BUILTIN_MODULES = ('builtins', '__builtin__', '__builtins__', 'exceptions') - - -def _get_members(obj, exclude_hidden): - """Yields the members of an object, filtering by hidden/not hidden.""" - for (name, value) in inspect.getmembers(obj): - if name.startswith("_") and exclude_hidden: - continue - yield (name, value) - - -def get_member_names(obj, exclude_hidden=True): - """Get all the member names for a object.""" - return [name for (name, _obj) in _get_members(obj, exclude_hidden)] - - -def get_class_name(obj, fully_qualified=True): - """Get class name for object. - - If object is a type, fully qualified name of the type is returned. - Else, fully qualified name of the type of the object is returned. - For builtin types, just name is returned. - """ - if not isinstance(obj, six.class_types): - obj = type(obj) - try: - built_in = obj.__module__ in _BUILTIN_MODULES - except AttributeError: - pass - else: - if built_in: - try: - return obj.__qualname__ - except AttributeError: - return obj.__name__ - pieces = [] - try: - pieces.append(obj.__qualname__) - except AttributeError: - pieces.append(obj.__name__) - if fully_qualified: - try: - pieces.insert(0, obj.__module__) - except AttributeError: - pass - return '.'.join(pieces) - - -def get_all_class_names(obj, up_to=object): - """Get class names of object parent classes. - - Iterate over all class names object is instance or subclass of, - in order of method resolution (mro). If up_to parameter is provided, - only name of classes that are sublcasses to that class are returned. - """ - if not isinstance(obj, six.class_types): - obj = type(obj) - for cls in obj.mro(): - if issubclass(cls, up_to): - yield get_class_name(cls) - - -def get_callable_name(function): - """Generate a name from callable. - - Tries to do the best to guess fully qualified callable name. - """ - method_self = get_method_self(function) - if method_self is not None: - # This is a bound method. - if isinstance(method_self, six.class_types): - # This is a bound class method. - im_class = method_self - else: - im_class = type(method_self) - try: - parts = (im_class.__module__, function.__qualname__) - except AttributeError: - parts = (im_class.__module__, im_class.__name__, function.__name__) - elif inspect.ismethod(function) or inspect.isfunction(function): - # This could be a function, a static method, a unbound method... - try: - parts = (function.__module__, function.__qualname__) - except AttributeError: - if hasattr(function, 'im_class'): - # This is a unbound method, which exists only in python 2.x - im_class = function.im_class - parts = (im_class.__module__, - im_class.__name__, function.__name__) - else: - parts = (function.__module__, function.__name__) - else: - im_class = type(function) - if im_class is _TYPE_TYPE: - im_class = function - try: - parts = (im_class.__module__, im_class.__qualname__) - except AttributeError: - parts = (im_class.__module__, im_class.__name__) - return '.'.join(parts) - - -def get_method_self(method): - if not inspect.ismethod(method): - return None - try: - return six.get_method_self(method) - except AttributeError: - return None - - -def is_same_callback(callback1, callback2, strict=True): - """Returns if the two callbacks are the same.""" - if callback1 is callback2: - # This happens when plain methods are given (or static/non-bound - # methods). - return True - if callback1 == callback2: - if not strict: - return True - # Two bound methods are equal if functions themselves are equal and - # objects they are applied to are equal. This means that a bound - # method could be the same bound method on another object if the - # objects have __eq__ methods that return true (when in fact it is a - # different bound method). Python u so crazy! - try: - self1 = six.get_method_self(callback1) - self2 = six.get_method_self(callback2) - return self1 is self2 - except AttributeError: - pass - return False - - -def is_bound_method(method): - """Returns if the given method is bound to an object.""" - return bool(get_method_self(method)) - - -def is_subclass(obj, cls): - """Returns if the object is class and it is subclass of a given class.""" - return inspect.isclass(obj) and issubclass(obj, cls) - - -def _get_arg_spec(function): - if isinstance(function, _TYPE_TYPE): - bound = True - function = function.__init__ - elif isinstance(function, (types.FunctionType, types.MethodType)): - bound = is_bound_method(function) - function = getattr(function, '__wrapped__', function) - else: - function = function.__call__ - bound = is_bound_method(function) - return inspect.getargspec(function), bound - - -def get_callable_args(function, required_only=False): - """Get names of callable arguments. - - Special arguments (like *args and **kwargs) are not included into - output. - - If required_only is True, optional arguments (with default values) - are not included into output. - """ - argspec, bound = _get_arg_spec(function) - f_args = argspec.args - if required_only and argspec.defaults: - f_args = f_args[:-len(argspec.defaults)] - if bound: - f_args = f_args[1:] - return f_args - - -def accepts_kwargs(function): - """Returns True if function accepts kwargs.""" - argspec, _bound = _get_arg_spec(function) - return bool(argspec.keywords) diff --git a/awx/lib/site-packages/oslo_utils/strutils.py b/awx/lib/site-packages/oslo_utils/strutils.py deleted file mode 100644 index 2851ced839..0000000000 --- a/awx/lib/site-packages/oslo_utils/strutils.py +++ /dev/null @@ -1,266 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -System-level utilities and helper functions. -""" - -import math -import re -import unicodedata - -import six - -from oslo_utils._i18n import _ -from oslo_utils import encodeutils - - -UNIT_PREFIX_EXPONENT = { - 'k': 1, - 'K': 1, - 'Ki': 1, - 'M': 2, - 'Mi': 2, - 'G': 3, - 'Gi': 3, - 'T': 4, - 'Ti': 4, -} -UNIT_SYSTEM_INFO = { - 'IEC': (1024, re.compile(r'(^[-+]?\d*\.?\d+)([KMGT]i?)?(b|bit|B)$')), - 'SI': (1000, re.compile(r'(^[-+]?\d*\.?\d+)([kMGT])?(b|bit|B)$')), -} - -TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes') -FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no') - -SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]") -SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+") - - -# NOTE(flaper87): The following globals are used by `mask_password` -_SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password', - 'auth_token', 'new_pass', 'auth_password', 'secret_uuid'] - -# NOTE(ldbragst): Let's build a list of regex objects using the list of -# _SANITIZE_KEYS we already have. This way, we only have to add the new key -# to the list of _SANITIZE_KEYS and we can generate regular expressions -# for XML and JSON automatically. -_SANITIZE_PATTERNS_2 = {} -_SANITIZE_PATTERNS_1 = {} - -# NOTE(amrith): Some regular expressions have only one parameter, some -# have two parameters. Use different lists of patterns here. -_FORMAT_PATTERNS_1 = [r'(%(key)s\s*[=]\s*)[^\s^\'^\"]+'] -_FORMAT_PATTERNS_2 = [r'(%(key)s\s*[=]\s*[\"\'])[^\"\']*([\"\'])', - r'(%(key)s\s+[\"\'])[^\"\']*([\"\'])', - r'([-]{2}%(key)s\s+)[^\'^\"^=^\s]+([\s]*)', - r'(<%(key)s>)[^<]*()', - r'([\"\']%(key)s[\"\']\s*:\s*[\"\'])[^\"\']*([\"\'])', - r'([\'"][^"\']*%(key)s[\'"]\s*:\s*u?[\'"])[^\"\']*' - '([\'"])', - r'([\'"][^\'"]*%(key)s[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?' - '[\'"])[^\"\']*([\'"])', - r'(%(key)s\s*--?[A-z]+\s*)\S+(\s*)'] - -# NOTE(dhellmann): Keep a separate list of patterns by key so we only -# need to apply the substitutions for keys we find using a quick "in" -# test. -for key in _SANITIZE_KEYS: - _SANITIZE_PATTERNS_1[key] = [] - _SANITIZE_PATTERNS_2[key] = [] - - for pattern in _FORMAT_PATTERNS_2: - reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) - _SANITIZE_PATTERNS_2[key].append(reg_ex) - - for pattern in _FORMAT_PATTERNS_1: - reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) - _SANITIZE_PATTERNS_1[key].append(reg_ex) - - -def int_from_bool_as_string(subject): - """Interpret a string as a boolean and return either 1 or 0. - - Any string value in: - - ('True', 'true', 'On', 'on', '1') - - is interpreted as a boolean True. - - Useful for JSON-decoded stuff and config file parsing - """ - return int(bool_from_string(subject)) - - -def bool_from_string(subject, strict=False, default=False): - """Interpret a string as a boolean. - - A case-insensitive match is performed such that strings matching 't', - 'true', 'on', 'y', 'yes', or '1' are considered True and, when - `strict=False`, anything else returns the value specified by 'default'. - - Useful for JSON-decoded stuff and config file parsing. - - If `strict=True`, unrecognized values, including None, will raise a - ValueError which is useful when parsing values passed in from an API call. - Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. - """ - if not isinstance(subject, six.string_types): - subject = six.text_type(subject) - - lowered = subject.strip().lower() - - if lowered in TRUE_STRINGS: - return True - elif lowered in FALSE_STRINGS: - return False - elif strict: - acceptable = ', '.join( - "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) - msg = _("Unrecognized value '%(val)s', acceptable values are:" - " %(acceptable)s") % {'val': subject, - 'acceptable': acceptable} - raise ValueError(msg) - else: - return default - - -def string_to_bytes(text, unit_system='IEC', return_int=False): - """Converts a string into an float representation of bytes. - - The units supported for IEC :: - - Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it) - KB, KiB, MB, MiB, GB, GiB, TB, TiB - - The units supported for SI :: - - kb(it), Mb(it), Gb(it), Tb(it) - kB, MB, GB, TB - - Note that the SI unit system does not support capital letter 'K' - - :param text: String input for bytes size conversion. - :param unit_system: Unit system for byte size conversion. - :param return_int: If True, returns integer representation of text - in bytes. (default: decimal) - :returns: Numerical representation of text in bytes. - :raises ValueError: If text has an invalid value. - - """ - try: - base, reg_ex = UNIT_SYSTEM_INFO[unit_system] - except KeyError: - msg = _('Invalid unit system: "%s"') % unit_system - raise ValueError(msg) - match = reg_ex.match(text) - if match: - magnitude = float(match.group(1)) - unit_prefix = match.group(2) - if match.group(3) in ['b', 'bit']: - magnitude /= 8 - else: - msg = _('Invalid string format: %s') % text - raise ValueError(msg) - if not unit_prefix: - res = magnitude - else: - res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix]) - if return_int: - return int(math.ceil(res)) - return res - - -def to_slug(value, incoming=None, errors="strict"): - """Normalize string. - - Convert to lowercase, remove non-word characters, and convert spaces - to hyphens. - - Inspired by Django's `slugify` filter. - - :param value: Text to slugify - :param incoming: Text's current encoding - :param errors: Errors handling policy. See here for valid - values http://docs.python.org/2/library/codecs.html - :returns: slugified unicode representation of `value` - :raises TypeError: If text is not an instance of str - """ - value = encodeutils.safe_decode(value, incoming, errors) - # NOTE(aababilov): no need to use safe_(encode|decode) here: - # encodings are always "ascii", error handling is always "ignore" - # and types are always known (first: unicode; second: str) - value = unicodedata.normalize("NFKD", value).encode( - "ascii", "ignore").decode("ascii") - value = SLUGIFY_STRIP_RE.sub("", value).strip().lower() - return SLUGIFY_HYPHENATE_RE.sub("-", value) - - -def mask_password(message, secret="***"): - """Replace password with 'secret' in message. - - :param message: The string which includes security information. - :param secret: value with which to replace passwords. - :returns: The unicode value of message with the password fields masked. - - For example: - - >>> mask_password("'adminPass' : 'aaaaa'") - "'adminPass' : '***'" - >>> mask_password("'admin_pass' : 'aaaaa'") - "'admin_pass' : '***'" - >>> mask_password('"password" : "aaaaa"') - '"password" : "***"' - >>> mask_password("'original_password' : 'aaaaa'") - "'original_password' : '***'" - >>> mask_password("u'original_password' : u'aaaaa'") - "u'original_password' : u'***'" - """ - - try: - message = six.text_type(message) - except UnicodeDecodeError: - # NOTE(jecarey): Temporary fix to handle cases where message is a - # byte string. A better solution will be provided in Kilo. - pass - - substitute1 = r'\g<1>' + secret - substitute2 = r'\g<1>' + secret + r'\g<2>' - - # NOTE(ldbragst): Check to see if anything in message contains any key - # specified in _SANITIZE_KEYS, if not then just return the message since - # we don't have to mask any passwords. - for key in _SANITIZE_KEYS: - if key in message: - for pattern in _SANITIZE_PATTERNS_2[key]: - message = re.sub(pattern, substitute2, message) - for pattern in _SANITIZE_PATTERNS_1[key]: - message = re.sub(pattern, substitute1, message) - - return message - - -def is_int_like(val): - """Check if a value looks like an integer with base 10. - - :param val: Value to verify - :type val: string - :returns: bool - """ - try: - return six.text_type(int(val)) == six.text_type(val) - except (TypeError, ValueError): - return False diff --git a/awx/lib/site-packages/oslo_utils/tests/__init__.py b/awx/lib/site-packages/oslo_utils/tests/__init__.py deleted file mode 100644 index 19f5e722fb..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. diff --git a/awx/lib/site-packages/oslo_utils/tests/base.py b/awx/lib/site-packages/oslo_utils/tests/base.py deleted file mode 100644 index a3069ed7a4..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/base.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2010-2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -import fixtures -import testtools - -_TRUE_VALUES = ('true', '1', 'yes') - -# FIXME(dhellmann) Update this to use oslo.test library - - -class TestCase(testtools.TestCase): - - """Test case base class for all unit tests.""" - - def setUp(self): - """Run before each test method to initialize test environment.""" - - super(TestCase, self).setUp() - test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) - try: - test_timeout = int(test_timeout) - except ValueError: - # If timeout value is invalid do not set a timeout. - test_timeout = 0 - if test_timeout > 0: - self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) - - self.useFixture(fixtures.NestedTempfile()) - self.useFixture(fixtures.TempHomeDir()) - - if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - - self.log_fixture = self.useFixture(fixtures.FakeLogger()) diff --git a/awx/lib/site-packages/oslo_utils/tests/fake/__init__.py b/awx/lib/site-packages/oslo_utils/tests/fake/__init__.py deleted file mode 100644 index 06cc9445d5..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/fake/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2012 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class FakeDriver(): - def __init__(self, first_arg=True): - self.first_arg = first_arg - - -class FakeDriver2(): - def __init__(self, first_arg): - self.first_arg = first_arg diff --git a/awx/lib/site-packages/oslo_utils/tests/test_eventletutils.py b/awx/lib/site-packages/oslo_utils/tests/test_eventletutils.py deleted file mode 100644 index 28a30ffa0c..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_eventletutils.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2012, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import warnings - -import mock -from oslotest import base as test_base -import six - -from oslo_utils import eventletutils - - -class EventletUtilsTest(test_base.BaseTestCase): - def setUp(self): - super(EventletUtilsTest, self).setUp() - self._old_avail = eventletutils.EVENTLET_AVAILABLE - eventletutils.EVENTLET_AVAILABLE = True - - def tearDown(self): - super(EventletUtilsTest, self).tearDown() - eventletutils.EVENTLET_AVAILABLE = self._old_avail - - @mock.patch("oslo_utils.eventletutils._patcher") - def test_warning_not_patched(self, mock_patcher): - mock_patcher.already_patched = True - mock_patcher.is_monkey_patched.return_value = False - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched(['os']) - self.assertEqual(1, len(capture)) - w = capture[0] - self.assertEqual(RuntimeWarning, w.category) - self.assertIn('os', six.text_type(w.message)) - - @mock.patch("oslo_utils.eventletutils._patcher") - def test_warning_not_patched_none_provided(self, mock_patcher): - mock_patcher.already_patched = True - mock_patcher.is_monkey_patched.return_value = False - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched() - self.assertEqual(1, len(capture)) - w = capture[0] - self.assertEqual(RuntimeWarning, w.category) - for m in eventletutils._ALL_PATCH: - self.assertIn(m, six.text_type(w.message)) - - @mock.patch("oslo_utils.eventletutils._patcher") - def test_warning_not_patched_all(self, mock_patcher): - mock_patcher.already_patched = True - mock_patcher.is_monkey_patched.return_value = False - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched(['all']) - self.assertEqual(1, len(capture)) - w = capture[0] - self.assertEqual(RuntimeWarning, w.category) - for m in eventletutils._ALL_PATCH: - self.assertIn(m, six.text_type(w.message)) - - @mock.patch("oslo_utils.eventletutils._patcher") - def test_no_warning(self, mock_patcher): - mock_patcher.already_patched = True - mock_patcher.is_monkey_patched.return_value = True - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched(['os']) - self.assertEqual(0, len(capture)) - - @mock.patch("oslo_utils.eventletutils._patcher") - def test_partially_patched_warning(self, mock_patcher): - is_patched = set() - mock_patcher.already_patched = True - mock_patcher.is_monkey_patched.side_effect = lambda m: m in is_patched - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched(['os']) - self.assertEqual(1, len(capture)) - is_patched.add('os') - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched(['os']) - self.assertEqual(0, len(capture)) - is_patched.add('thread') - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched(['os', 'thread']) - self.assertEqual(0, len(capture)) - with warnings.catch_warnings(record=True) as capture: - warnings.simplefilter("always") - eventletutils.warn_eventlet_not_patched(['all']) - self.assertEqual(1, len(capture)) - w = capture[0] - self.assertEqual(RuntimeWarning, w.category) - for m in ['os', 'thread']: - self.assertNotIn(m, six.text_type(w.message)) - - def test_invalid_patch_check(self): - self.assertRaises(ValueError, - eventletutils.warn_eventlet_not_patched, - ['blah.blah']) diff --git a/awx/lib/site-packages/oslo_utils/tests/test_excutils.py b/awx/lib/site-packages/oslo_utils/tests/test_excutils.py deleted file mode 100644 index c2626a4541..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_excutils.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2012, Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import logging -import time - -import mock -from oslotest import base as test_base -from oslotest import moxstubout - -from oslo_utils import excutils - - -mox = moxstubout.mox - - -class SaveAndReraiseTest(test_base.BaseTestCase): - - def test_save_and_reraise_exception(self): - e = None - msg = 'foo' - try: - try: - raise Exception(msg) - except Exception: - with excutils.save_and_reraise_exception(): - pass - except Exception as _e: - e = _e - - self.assertEqual(str(e), msg) - - @mock.patch('logging.getLogger') - def test_save_and_reraise_exception_dropped(self, get_logger_mock): - logger = get_logger_mock() - e = None - msg = 'second exception' - try: - try: - raise Exception('dropped') - except Exception: - with excutils.save_and_reraise_exception(): - raise Exception(msg) - except Exception as _e: - e = _e - self.assertEqual(str(e), msg) - self.assertTrue(logger.error.called) - - def test_save_and_reraise_exception_no_reraise(self): - """Test that suppressing the reraise works.""" - try: - raise Exception('foo') - except Exception: - with excutils.save_and_reraise_exception() as ctxt: - ctxt.reraise = False - - @mock.patch('logging.getLogger') - def test_save_and_reraise_exception_dropped_no_reraise(self, - get_logger_mock): - logger = get_logger_mock() - e = None - msg = 'second exception' - try: - try: - raise Exception('dropped') - except Exception: - with excutils.save_and_reraise_exception(reraise=False): - raise Exception(msg) - except Exception as _e: - e = _e - self.assertEqual(str(e), msg) - self.assertFalse(logger.error.called) - - def test_save_and_reraise_exception_provided_logger(self): - fake_logger = mock.MagicMock() - try: - try: - raise Exception('foo') - except Exception: - with excutils.save_and_reraise_exception(logger=fake_logger): - raise Exception('second exception') - except Exception: - pass - self.assertTrue(fake_logger.error.called) - - -class ForeverRetryUncaughtExceptionsTest(test_base.BaseTestCase): - - def setUp(self): - super(ForeverRetryUncaughtExceptionsTest, self).setUp() - moxfixture = self.useFixture(moxstubout.MoxStubout()) - self.mox = moxfixture.mox - self.stubs = moxfixture.stubs - - @excutils.forever_retry_uncaught_exceptions - def exception_generator(self): - exc = self.exception_to_raise() - while exc is not None: - raise exc - exc = self.exception_to_raise() - - def exception_to_raise(self): - return None - - def my_time_sleep(self, arg): - pass - - def exc_retrier_common_start(self): - self.stubs.Set(time, 'sleep', self.my_time_sleep) - self.mox.StubOutWithMock(logging, 'exception') - self.mox.StubOutWithMock(time, 'time', - use_mock_anything=True) - self.mox.StubOutWithMock(self, 'exception_to_raise') - - def exc_retrier_sequence(self, exc_id=None, timestamp=None, - exc_count=None): - self.exception_to_raise().AndReturn( - Exception('unexpected %d' % exc_id)) - time.time().AndReturn(timestamp) - if exc_count != 0: - logging.exception(mox.In( - 'Unexpected exception occurred %d time(s)' % exc_count)) - - def exc_retrier_common_end(self): - self.exception_to_raise().AndReturn(None) - self.mox.ReplayAll() - self.exception_generator() - self.addCleanup(self.stubs.UnsetAll) - - def test_exc_retrier_1exc_gives_1log(self): - self.exc_retrier_common_start() - self.exc_retrier_sequence(exc_id=1, timestamp=1, exc_count=1) - self.exc_retrier_common_end() - - def test_exc_retrier_same_10exc_1min_gives_1log(self): - self.exc_retrier_common_start() - self.exc_retrier_sequence(exc_id=1, timestamp=1, exc_count=1) - # By design, the following exception don't get logged because they - # are within the same minute. - for i in range(2, 11): - self.exc_retrier_sequence(exc_id=1, timestamp=i, exc_count=0) - self.exc_retrier_common_end() - - def test_exc_retrier_same_2exc_2min_gives_2logs(self): - self.exc_retrier_common_start() - self.exc_retrier_sequence(exc_id=1, timestamp=1, exc_count=1) - self.exc_retrier_sequence(exc_id=1, timestamp=65, exc_count=1) - self.exc_retrier_common_end() - - def test_exc_retrier_same_10exc_2min_gives_2logs(self): - self.exc_retrier_common_start() - self.exc_retrier_sequence(exc_id=1, timestamp=1, exc_count=1) - self.exc_retrier_sequence(exc_id=1, timestamp=12, exc_count=0) - self.exc_retrier_sequence(exc_id=1, timestamp=23, exc_count=0) - self.exc_retrier_sequence(exc_id=1, timestamp=34, exc_count=0) - self.exc_retrier_sequence(exc_id=1, timestamp=45, exc_count=0) - # The previous 4 exceptions are counted here - self.exc_retrier_sequence(exc_id=1, timestamp=106, exc_count=5) - # Again, the following are not logged due to being within - # the same minute - self.exc_retrier_sequence(exc_id=1, timestamp=117, exc_count=0) - self.exc_retrier_sequence(exc_id=1, timestamp=128, exc_count=0) - self.exc_retrier_sequence(exc_id=1, timestamp=139, exc_count=0) - self.exc_retrier_sequence(exc_id=1, timestamp=150, exc_count=0) - self.exc_retrier_common_end() - - def test_exc_retrier_mixed_4exc_1min_gives_2logs(self): - self.exc_retrier_common_start() - self.exc_retrier_sequence(exc_id=1, timestamp=1, exc_count=1) - # By design, this second 'unexpected 1' exception is not counted. This - # is likely a rare thing and is a sacrifice for code simplicity. - self.exc_retrier_sequence(exc_id=1, timestamp=10, exc_count=0) - self.exc_retrier_sequence(exc_id=2, timestamp=20, exc_count=1) - # Again, trailing exceptions within a minute are not counted. - self.exc_retrier_sequence(exc_id=2, timestamp=30, exc_count=0) - self.exc_retrier_common_end() - - def test_exc_retrier_mixed_4exc_2min_gives_2logs(self): - self.exc_retrier_common_start() - self.exc_retrier_sequence(exc_id=1, timestamp=1, exc_count=1) - # Again, this second exception of the same type is not counted - # for the sake of code simplicity. - self.exc_retrier_sequence(exc_id=1, timestamp=10, exc_count=0) - # The difference between this and the previous case is the log - # is also triggered by more than a minute expiring. - self.exc_retrier_sequence(exc_id=2, timestamp=100, exc_count=1) - self.exc_retrier_sequence(exc_id=2, timestamp=110, exc_count=0) - self.exc_retrier_common_end() - - def test_exc_retrier_mixed_4exc_2min_gives_3logs(self): - self.exc_retrier_common_start() - self.exc_retrier_sequence(exc_id=1, timestamp=1, exc_count=1) - # This time the second 'unexpected 1' exception is counted due - # to the same exception occurring same when the minute expires. - self.exc_retrier_sequence(exc_id=1, timestamp=10, exc_count=0) - self.exc_retrier_sequence(exc_id=1, timestamp=100, exc_count=2) - self.exc_retrier_sequence(exc_id=2, timestamp=110, exc_count=1) - self.exc_retrier_common_end() diff --git a/awx/lib/site-packages/oslo_utils/tests/test_fixture.py b/awx/lib/site-packages/oslo_utils/tests/test_fixture.py deleted file mode 100644 index 3e0898ab19..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_fixture.py +++ /dev/null @@ -1,63 +0,0 @@ - -# Copyright 2015 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -from oslotest import base as test_base - -from oslo_utils import fixture -from oslo_utils import timeutils - - -class TimeFixtureTest(test_base.BaseTestCase): - - def test_set_time_override_using_default(self): - # When the fixture is used with its default constructor, the - # override_time is set to the current timestamp. - # Also, when the fixture is cleaned up, the override_time is reset. - - self.assertIsNone(timeutils.utcnow.override_time) - with fixture.TimeFixture(): - self.assertIsNotNone(timeutils.utcnow.override_time) - self.assertIsNone(timeutils.utcnow.override_time) - - def test_set_time_override(self): - # When the fixture is used to set a time, utcnow returns that time. - - new_time = datetime.datetime(2015, 1, 2, 3, 4, 6, 7) - self.useFixture(fixture.TimeFixture(new_time)) - self.assertEqual(new_time, timeutils.utcnow()) - # Call again to make sure it keeps returning the same time. - self.assertEqual(new_time, timeutils.utcnow()) - - def test_advance_time_delta(self): - # advance_time_delta() advances the overridden time by some timedelta. - - new_time = datetime.datetime(2015, 1, 2, 3, 4, 6, 7) - time_fixture = self.useFixture(fixture.TimeFixture(new_time)) - time_fixture.advance_time_delta(datetime.timedelta(seconds=1)) - expected_time = datetime.datetime(2015, 1, 2, 3, 4, 7, 7) - self.assertEqual(expected_time, timeutils.utcnow()) - - def test_advance_time_seconds(self): - # advance_time_seconds() advances the overridden time by some number of - # seconds. - - new_time = datetime.datetime(2015, 1, 2, 3, 4, 6, 7) - time_fixture = self.useFixture(fixture.TimeFixture(new_time)) - time_fixture.advance_time_seconds(2) - expected_time = datetime.datetime(2015, 1, 2, 3, 4, 8, 7) - self.assertEqual(expected_time, timeutils.utcnow()) diff --git a/awx/lib/site-packages/oslo_utils/tests/test_importutils.py b/awx/lib/site-packages/oslo_utils/tests/test_importutils.py deleted file mode 100644 index bbdff04b61..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_importutils.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime -import sys - -from oslotest import base as test_base - -from oslo_utils import importutils - - -class ImportUtilsTest(test_base.BaseTestCase): - - # NOTE(jkoelker) There has GOT to be a way to test this. But mocking - # __import__ is the devil. Right now we just make - # sure we can import something from the stdlib - def test_import_class(self): - dt = importutils.import_class('datetime.datetime') - self.assertEqual(sys.modules['datetime'].datetime, dt) - - def test_import_bad_class(self): - self.assertRaises(ImportError, importutils.import_class, - 'lol.u_mad.brah') - - def test_import_module(self): - dt = importutils.import_module('datetime') - self.assertEqual(sys.modules['datetime'], dt) - - def test_import_object_optional_arg_not_present(self): - obj = importutils.import_object('oslo_utils.tests.fake.FakeDriver') - self.assertEqual(obj.__class__.__name__, 'FakeDriver') - - def test_import_object_optional_arg_present(self): - obj = importutils.import_object('oslo_utils.tests.fake.FakeDriver', - first_arg=False) - self.assertEqual(obj.__class__.__name__, 'FakeDriver') - - def test_import_object_required_arg_not_present(self): - # arg 1 isn't optional here - self.assertRaises(TypeError, importutils.import_object, - 'oslo_utils.tests.fake.FakeDriver2') - - def test_import_object_required_arg_present(self): - obj = importutils.import_object('oslo_utils.tests.fake.FakeDriver2', - first_arg=False) - self.assertEqual(obj.__class__.__name__, 'FakeDriver2') - - # namespace tests - def test_import_object_ns_optional_arg_not_present(self): - obj = importutils.import_object_ns('oslo_utils', - 'tests.fake.FakeDriver') - self.assertEqual(obj.__class__.__name__, 'FakeDriver') - - def test_import_object_ns_optional_arg_present(self): - obj = importutils.import_object_ns('oslo_utils', - 'tests.fake.FakeDriver', - first_arg=False) - self.assertEqual(obj.__class__.__name__, 'FakeDriver') - - def test_import_object_ns_required_arg_not_present(self): - # arg 1 isn't optional here - self.assertRaises(TypeError, importutils.import_object_ns, - 'oslo_utils', 'tests.fake.FakeDriver2') - - def test_import_object_ns_required_arg_present(self): - obj = importutils.import_object_ns('oslo_utils', - 'tests.fake.FakeDriver2', - first_arg=False) - self.assertEqual(obj.__class__.__name__, 'FakeDriver2') - - # namespace tests - def test_import_object_ns_full_optional_arg_not_present(self): - obj = importutils.import_object_ns('tests2', - 'oslo_utils.tests.fake.FakeDriver') - self.assertEqual(obj.__class__.__name__, 'FakeDriver') - - def test_import_object_ns_full_optional_arg_present(self): - obj = importutils.import_object_ns('tests2', - 'oslo_utils.tests.fake.FakeDriver', - first_arg=False) - self.assertEqual(obj.__class__.__name__, 'FakeDriver') - - def test_import_object_ns_full_required_arg_not_present(self): - # arg 1 isn't optional here - self.assertRaises(TypeError, importutils.import_object_ns, - 'tests2', 'oslo_utils.tests.fake.FakeDriver2') - - def test_import_object_ns_full_required_arg_present(self): - obj = importutils.import_object_ns('tests2', - 'oslo_utils.tests.fake.FakeDriver2', - first_arg=False) - self.assertEqual(obj.__class__.__name__, 'FakeDriver2') - - def test_import_object(self): - dt = importutils.import_object('datetime.time') - self.assertTrue(isinstance(dt, sys.modules['datetime'].time)) - - def test_import_object_with_args(self): - dt = importutils.import_object('datetime.datetime', 2012, 4, 5) - self.assertTrue(isinstance(dt, sys.modules['datetime'].datetime)) - self.assertEqual(dt, datetime.datetime(2012, 4, 5)) - - def test_try_import(self): - dt = importutils.try_import('datetime') - self.assertEqual(sys.modules['datetime'], dt) - - def test_try_import_returns_default(self): - foo = importutils.try_import('foo.bar') - self.assertIsNone(foo) diff --git a/awx/lib/site-packages/oslo_utils/tests/test_netutils.py b/awx/lib/site-packages/oslo_utils/tests/test_netutils.py deleted file mode 100644 index 1bc4990e95..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_netutils.py +++ /dev/null @@ -1,304 +0,0 @@ -# Copyright 2012 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import socket - -import mock -from mock import patch -import netifaces -from oslotest import base as test_base - -from oslo_utils import netutils - - -class NetworkUtilsTest(test_base.BaseTestCase): - - def test_no_host(self): - result = netutils.urlsplit('http://') - self.assertEqual('', result.netloc) - self.assertEqual(None, result.port) - self.assertEqual(None, result.hostname) - self.assertEqual('http', result.scheme) - - def test_parse_host_port(self): - self.assertEqual(('server01', 80), - netutils.parse_host_port('server01:80')) - self.assertEqual(('server01', None), - netutils.parse_host_port('server01')) - self.assertEqual(('server01', 1234), - netutils.parse_host_port('server01', - default_port=1234)) - self.assertEqual(('::1', 80), - netutils.parse_host_port('[::1]:80')) - self.assertEqual(('::1', None), - netutils.parse_host_port('[::1]')) - self.assertEqual(('::1', 1234), - netutils.parse_host_port('[::1]', - default_port=1234)) - self.assertEqual(('2001:db8:85a3::8a2e:370:7334', 1234), - netutils.parse_host_port( - '2001:db8:85a3::8a2e:370:7334', - default_port=1234)) - - def test_urlsplit(self): - result = netutils.urlsplit('rpc://myhost?someparam#somefragment') - self.assertEqual(result.scheme, 'rpc') - self.assertEqual(result.netloc, 'myhost') - self.assertEqual(result.path, '') - self.assertEqual(result.query, 'someparam') - self.assertEqual(result.fragment, 'somefragment') - - result = netutils.urlsplit( - 'rpc://myhost/mypath?someparam#somefragment', - allow_fragments=False) - self.assertEqual(result.scheme, 'rpc') - self.assertEqual(result.netloc, 'myhost') - self.assertEqual(result.path, '/mypath') - self.assertEqual(result.query, 'someparam#somefragment') - self.assertEqual(result.fragment, '') - - result = netutils.urlsplit( - 'rpc://user:pass@myhost/mypath?someparam#somefragment', - allow_fragments=False) - self.assertEqual(result.scheme, 'rpc') - self.assertEqual(result.netloc, 'user:pass@myhost') - self.assertEqual(result.path, '/mypath') - self.assertEqual(result.query, 'someparam#somefragment') - self.assertEqual(result.fragment, '') - - def test_urlsplit_ipv6(self): - ipv6_url = 'http://[::1]:443/v2.0/' - result = netutils.urlsplit(ipv6_url) - self.assertEqual(result.scheme, 'http') - self.assertEqual(result.netloc, '[::1]:443') - self.assertEqual(result.path, '/v2.0/') - self.assertEqual(result.hostname, '::1') - self.assertEqual(result.port, 443) - - ipv6_url = 'http://user:pass@[::1]/v2.0/' - result = netutils.urlsplit(ipv6_url) - self.assertEqual(result.scheme, 'http') - self.assertEqual(result.netloc, 'user:pass@[::1]') - self.assertEqual(result.path, '/v2.0/') - self.assertEqual(result.hostname, '::1') - self.assertEqual(result.port, None) - - ipv6_url = 'https://[2001:db8:85a3::8a2e:370:7334]:1234/v2.0/xy?ab#12' - result = netutils.urlsplit(ipv6_url) - self.assertEqual(result.scheme, 'https') - self.assertEqual(result.netloc, '[2001:db8:85a3::8a2e:370:7334]:1234') - self.assertEqual(result.path, '/v2.0/xy') - self.assertEqual(result.hostname, '2001:db8:85a3::8a2e:370:7334') - self.assertEqual(result.port, 1234) - self.assertEqual(result.query, 'ab') - self.assertEqual(result.fragment, '12') - - def test_urlsplit_params(self): - test_url = "http://localhost/?a=b&c=d" - result = netutils.urlsplit(test_url) - self.assertEqual({'a': 'b', 'c': 'd'}, result.params()) - self.assertEqual({'a': 'b', 'c': 'd'}, result.params(collapse=False)) - - test_url = "http://localhost/?a=b&a=c&a=d" - result = netutils.urlsplit(test_url) - self.assertEqual({'a': 'd'}, result.params()) - self.assertEqual({'a': ['b', 'c', 'd']}, result.params(collapse=False)) - - test_url = "http://localhost" - result = netutils.urlsplit(test_url) - self.assertEqual({}, result.params()) - - test_url = "http://localhost?" - result = netutils.urlsplit(test_url) - self.assertEqual({}, result.params()) - - def test_set_tcp_keepalive(self): - mock_sock = mock.Mock() - netutils.set_tcp_keepalive(mock_sock, True, 100, 10, 5) - calls = [ - mock.call.setsockopt(socket.SOL_SOCKET, - socket.SO_KEEPALIVE, True), - ] - if hasattr(socket, 'TCP_KEEPIDLE'): - calls += [ - mock.call.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPIDLE, 100) - ] - if hasattr(socket, 'TCP_KEEPINTVL'): - calls += [ - mock.call.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPINTVL, 10), - ] - if hasattr(socket, 'TCP_KEEPCNT'): - calls += [ - mock.call.setsockopt(socket.IPPROTO_TCP, - socket.TCP_KEEPCNT, 5) - ] - mock_sock.assert_has_calls(calls) - - mock_sock.reset_mock() - netutils.set_tcp_keepalive(mock_sock, False) - self.assertEqual(1, len(mock_sock.mock_calls)) - - def test_is_valid_ipv4(self): - self.assertTrue(netutils.is_valid_ipv4('42.42.42.42')) - - self.assertFalse(netutils.is_valid_ipv4('-1.11.11.11')) - - self.assertFalse(netutils.is_valid_ipv4('')) - - def test_is_valid_ipv6(self): - self.assertTrue(netutils.is_valid_ipv6('::1')) - - self.assertFalse(netutils.is_valid_ipv6( - '1fff::a88:85a3::172.31.128.1')) - - self.assertFalse(netutils.is_valid_ipv6('')) - - def test_is_valid_ip(self): - self.assertTrue(netutils.is_valid_ip('127.0.0.1')) - - self.assertTrue(netutils.is_valid_ip('2001:db8::ff00:42:8329')) - - self.assertFalse(netutils.is_valid_ip('256.0.0.0')) - - self.assertFalse(netutils.is_valid_ip('::1.2.3.')) - - self.assertFalse(netutils.is_valid_ip('')) - - def test_valid_port(self): - valid_inputs = [1, '1', 2, '3', '5', 8, 13, 21, - '80', '3246', '65535'] - for input_str in valid_inputs: - self.assertTrue(netutils.is_valid_port(input_str)) - - def test_valid_port_fail(self): - invalid_inputs = ['-32768', '0', 0, '65536', 528491, '528491', - '528.491', 'thirty-seven', None] - for input_str in invalid_inputs: - self.assertFalse(netutils.is_valid_port(input_str)) - - def test_get_my_ip(self): - sock_attrs = { - 'return_value.getsockname.return_value': ['1.2.3.4', '']} - with mock.patch('socket.socket', **sock_attrs): - addr = netutils.get_my_ipv4() - self.assertEqual(addr, '1.2.3.4') - - @mock.patch('socket.socket') - @mock.patch('oslo_utils.netutils._get_my_ipv4_address') - def test_get_my_ip_socket_error(self, ip, mock_socket): - mock_socket.side_effect = socket.error - ip.return_value = '1.2.3.4' - addr = netutils.get_my_ipv4() - self.assertEqual(addr, '1.2.3.4') - - @mock.patch('netifaces.gateways') - @mock.patch('netifaces.ifaddresses') - def test_get_my_ipv4_address_with_default_route( - self, ifaddr, gateways): - with patch.dict(netifaces.__dict__, {'AF_INET': '0'}): - ifaddr.return_value = {'0': [{'addr': '172.18.204.1'}]} - addr = netutils._get_my_ipv4_address() - self.assertEqual('172.18.204.1', addr) - - @mock.patch('netifaces.gateways') - @mock.patch('netifaces.ifaddresses') - def test_get_my_ipv4_address_without_default_route( - self, ifaddr, gateways): - with patch.dict(netifaces.__dict__, {'AF_INET': '0'}): - ifaddr.return_value = {} - addr = netutils._get_my_ipv4_address() - self.assertEqual('127.0.0.1', addr) - - @mock.patch('netifaces.gateways') - @mock.patch('netifaces.ifaddresses') - def test_get_my_ipv4_address_without_default_interface( - self, ifaddr, gateways): - gateways.return_value = {} - addr = netutils._get_my_ipv4_address() - self.assertEqual('127.0.0.1', addr) - self.assertFalse(ifaddr.called) - - -class IPv6byEUI64TestCase(test_base.BaseTestCase): - """Unit tests to generate IPv6 by EUI-64 operations.""" - - def test_generate_IPv6_by_EUI64(self): - addr = netutils.get_ipv6_addr_by_EUI64('2001:db8::', - '00:16:3e:33:44:55') - self.assertEqual('2001:db8::216:3eff:fe33:4455', addr.format()) - - def test_generate_IPv6_with_IPv4_prefix(self): - ipv4_prefix = '10.0.8' - mac = '00:16:3e:33:44:55' - self.assertRaises(ValueError, lambda: - netutils.get_ipv6_addr_by_EUI64(ipv4_prefix, mac)) - - def test_generate_IPv6_with_bad_mac(self): - bad_mac = '00:16:3e:33:44:5Z' - prefix = '2001:db8::' - self.assertRaises(ValueError, lambda: - netutils.get_ipv6_addr_by_EUI64(prefix, bad_mac)) - - def test_generate_IPv6_with_bad_prefix(self): - mac = '00:16:3e:33:44:55' - bad_prefix = 'bb' - self.assertRaises(ValueError, lambda: - netutils.get_ipv6_addr_by_EUI64(bad_prefix, mac)) - - def test_generate_IPv6_with_error_prefix_type(self): - mac = '00:16:3e:33:44:55' - prefix = 123 - self.assertRaises(TypeError, lambda: - netutils.get_ipv6_addr_by_EUI64(prefix, mac)) - - -class TestIsIPv6Enabled(test_base.BaseTestCase): - - def setUp(self): - super(TestIsIPv6Enabled, self).setUp() - - def reset_detection_flag(): - netutils._IS_IPV6_ENABLED = None - reset_detection_flag() - self.addCleanup(reset_detection_flag) - self.mock_exists = mock.patch("os.path.exists", - return_value=True).start() - mock_open = mock.patch("six.moves.builtins.open").start() - self.mock_read = mock_open.return_value.__enter__.return_value.read - - def test_enabled(self): - self.mock_read.return_value = "0" - enabled = netutils.is_ipv6_enabled() - self.assertTrue(enabled) - - def test_disabled(self): - self.mock_read.return_value = "1" - enabled = netutils.is_ipv6_enabled() - self.assertFalse(enabled) - - def test_disabled_non_exists(self): - self.mock_exists.return_value = False - enabled = netutils.is_ipv6_enabled() - self.assertFalse(enabled) - self.assertFalse(self.mock_read.called) - - def test_memoize(self): - self.mock_read.return_value = "0" - netutils.is_ipv6_enabled() - enabled = netutils.is_ipv6_enabled() - self.assertTrue(enabled) - self.mock_read.assert_called_once_with() diff --git a/awx/lib/site-packages/oslo_utils/tests/test_reflection.py b/awx/lib/site-packages/oslo_utils/tests/test_reflection.py deleted file mode 100644 index d66f438c5c..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_reflection.py +++ /dev/null @@ -1,279 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2012 Yahoo! Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslotest import base as test_base -import six -import testtools - -from oslo_utils import reflection - - -if six.PY3: - RUNTIME_ERROR_CLASSES = ['RuntimeError', 'Exception', - 'BaseException', 'object'] -else: - RUNTIME_ERROR_CLASSES = ['RuntimeError', 'StandardError', 'Exception', - 'BaseException', 'object'] - - -def dummy_decorator(f): - - @six.wraps(f) - def wrapper(*args, **kwargs): - return f(*args, **kwargs) - - return wrapper - - -def mere_function(a, b): - pass - - -def function_with_defs(a, b, optional=None): - pass - - -def function_with_kwargs(a, b, **kwargs): - pass - - -class Class(object): - - def method(self, c, d): - pass - - @staticmethod - def static_method(e, f): - pass - - @classmethod - def class_method(cls, g, h): - pass - - -class CallableClass(object): - def __call__(self, i, j): - pass - - -class ClassWithInit(object): - def __init__(self, k, l): - pass - - -class CallbackEqualityTest(test_base.BaseTestCase): - def test_different_simple_callbacks(self): - - def a(): - pass - - def b(): - pass - - self.assertFalse(reflection.is_same_callback(a, b)) - - def test_static_instance_callbacks(self): - - class A(object): - - @staticmethod - def b(a, b, c): - pass - - a = A() - b = A() - - self.assertTrue(reflection.is_same_callback(a.b, b.b)) - - def test_different_instance_callbacks(self): - - class A(object): - def b(self): - pass - - def __eq__(self, other): - return True - - b = A() - c = A() - - self.assertFalse(reflection.is_same_callback(b.b, c.b)) - self.assertTrue(reflection.is_same_callback(b.b, c.b, strict=False)) - - -class GetCallableNameTest(test_base.BaseTestCase): - - def test_mere_function(self): - name = reflection.get_callable_name(mere_function) - self.assertEqual('.'.join((__name__, 'mere_function')), name) - - def test_method(self): - name = reflection.get_callable_name(Class.method) - self.assertEqual('.'.join((__name__, 'Class', 'method')), name) - - def test_instance_method(self): - name = reflection.get_callable_name(Class().method) - self.assertEqual('.'.join((__name__, 'Class', 'method')), name) - - def test_static_method(self): - name = reflection.get_callable_name(Class.static_method) - if six.PY3: - self.assertEqual('.'.join((__name__, 'Class', 'static_method')), - name) - else: - # NOTE(imelnikov): static method are just functions, class name - # is not recorded anywhere in them. - self.assertEqual('.'.join((__name__, 'static_method')), name) - - def test_class_method(self): - name = reflection.get_callable_name(Class.class_method) - self.assertEqual('.'.join((__name__, 'Class', 'class_method')), name) - - def test_constructor(self): - name = reflection.get_callable_name(Class) - self.assertEqual('.'.join((__name__, 'Class')), name) - - def test_callable_class(self): - name = reflection.get_callable_name(CallableClass()) - self.assertEqual('.'.join((__name__, 'CallableClass')), name) - - def test_callable_class_call(self): - name = reflection.get_callable_name(CallableClass().__call__) - self.assertEqual('.'.join((__name__, 'CallableClass', - '__call__')), name) - - -# These extended/special case tests only work on python 3, due to python 2 -# being broken/incorrect with regard to these special cases... -@testtools.skipIf(not six.PY3, 'python 3.x is not currently available') -class GetCallableNameTestExtended(test_base.BaseTestCase): - # Tests items in http://legacy.python.org/dev/peps/pep-3155/ - - class InnerCallableClass(object): - def __call__(self): - pass - - def test_inner_callable_class(self): - obj = self.InnerCallableClass() - name = reflection.get_callable_name(obj.__call__) - expected_name = '.'.join((__name__, 'GetCallableNameTestExtended', - 'InnerCallableClass', '__call__')) - self.assertEqual(expected_name, name) - - def test_inner_callable_function(self): - def a(): - - def b(): - pass - - return b - - name = reflection.get_callable_name(a()) - expected_name = '.'.join((__name__, 'GetCallableNameTestExtended', - 'test_inner_callable_function', '', - 'a', '', 'b')) - self.assertEqual(expected_name, name) - - def test_inner_class(self): - obj = self.InnerCallableClass() - name = reflection.get_callable_name(obj) - expected_name = '.'.join((__name__, - 'GetCallableNameTestExtended', - 'InnerCallableClass')) - self.assertEqual(expected_name, name) - - -class GetCallableArgsTest(test_base.BaseTestCase): - - def test_mere_function(self): - result = reflection.get_callable_args(mere_function) - self.assertEqual(['a', 'b'], result) - - def test_function_with_defaults(self): - result = reflection.get_callable_args(function_with_defs) - self.assertEqual(['a', 'b', 'optional'], result) - - def test_required_only(self): - result = reflection.get_callable_args(function_with_defs, - required_only=True) - self.assertEqual(['a', 'b'], result) - - def test_method(self): - result = reflection.get_callable_args(Class.method) - self.assertEqual(['self', 'c', 'd'], result) - - def test_instance_method(self): - result = reflection.get_callable_args(Class().method) - self.assertEqual(['c', 'd'], result) - - def test_class_method(self): - result = reflection.get_callable_args(Class.class_method) - self.assertEqual(['g', 'h'], result) - - def test_class_constructor(self): - result = reflection.get_callable_args(ClassWithInit) - self.assertEqual(['k', 'l'], result) - - def test_class_with_call(self): - result = reflection.get_callable_args(CallableClass()) - self.assertEqual(['i', 'j'], result) - - def test_decorators_work(self): - @dummy_decorator - def special_fun(x, y): - pass - result = reflection.get_callable_args(special_fun) - self.assertEqual(['x', 'y'], result) - - -class AcceptsKwargsTest(test_base.BaseTestCase): - - def test_no_kwargs(self): - self.assertEqual(False, reflection.accepts_kwargs(mere_function)) - - def test_with_kwargs(self): - self.assertEqual(True, reflection.accepts_kwargs(function_with_kwargs)) - - -class GetClassNameTest(test_base.BaseTestCase): - - def test_std_exception(self): - name = reflection.get_class_name(RuntimeError) - self.assertEqual('RuntimeError', name) - - def test_class(self): - name = reflection.get_class_name(Class) - self.assertEqual('.'.join((__name__, 'Class')), name) - - def test_instance(self): - name = reflection.get_class_name(Class()) - self.assertEqual('.'.join((__name__, 'Class')), name) - - def test_int(self): - name = reflection.get_class_name(42) - self.assertEqual('int', name) - - -class GetAllClassNamesTest(test_base.BaseTestCase): - - def test_std_class(self): - names = list(reflection.get_all_class_names(RuntimeError)) - self.assertEqual(RUNTIME_ERROR_CLASSES, names) - - def test_std_class_up_to(self): - names = list(reflection.get_all_class_names(RuntimeError, - up_to=Exception)) - self.assertEqual(RUNTIME_ERROR_CLASSES[:-2], names) diff --git a/awx/lib/site-packages/oslo_utils/tests/test_strutils.py b/awx/lib/site-packages/oslo_utils/tests/test_strutils.py deleted file mode 100644 index 89734c31ff..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_strutils.py +++ /dev/null @@ -1,594 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import math - -import mock -from oslotest import base as test_base -import six -import testscenarios - -from oslo_utils import strutils -from oslo_utils import units - -load_tests = testscenarios.load_tests_apply_scenarios - - -class StrUtilsTest(test_base.BaseTestCase): - - def test_bool_bool_from_string(self): - self.assertTrue(strutils.bool_from_string(True)) - self.assertFalse(strutils.bool_from_string(False)) - - def test_bool_bool_from_string_default(self): - self.assertTrue(strutils.bool_from_string('', default=True)) - self.assertFalse(strutils.bool_from_string('wibble', default=False)) - - def _test_bool_from_string(self, c): - self.assertTrue(strutils.bool_from_string(c('true'))) - self.assertTrue(strutils.bool_from_string(c('TRUE'))) - self.assertTrue(strutils.bool_from_string(c('on'))) - self.assertTrue(strutils.bool_from_string(c('On'))) - self.assertTrue(strutils.bool_from_string(c('yes'))) - self.assertTrue(strutils.bool_from_string(c('YES'))) - self.assertTrue(strutils.bool_from_string(c('yEs'))) - self.assertTrue(strutils.bool_from_string(c('1'))) - self.assertTrue(strutils.bool_from_string(c('T'))) - self.assertTrue(strutils.bool_from_string(c('t'))) - self.assertTrue(strutils.bool_from_string(c('Y'))) - self.assertTrue(strutils.bool_from_string(c('y'))) - - self.assertFalse(strutils.bool_from_string(c('false'))) - self.assertFalse(strutils.bool_from_string(c('FALSE'))) - self.assertFalse(strutils.bool_from_string(c('off'))) - self.assertFalse(strutils.bool_from_string(c('OFF'))) - self.assertFalse(strutils.bool_from_string(c('no'))) - self.assertFalse(strutils.bool_from_string(c('0'))) - self.assertFalse(strutils.bool_from_string(c('42'))) - self.assertFalse(strutils.bool_from_string(c( - 'This should not be True'))) - self.assertFalse(strutils.bool_from_string(c('F'))) - self.assertFalse(strutils.bool_from_string(c('f'))) - self.assertFalse(strutils.bool_from_string(c('N'))) - self.assertFalse(strutils.bool_from_string(c('n'))) - - # Whitespace should be stripped - self.assertTrue(strutils.bool_from_string(c(' 1 '))) - self.assertTrue(strutils.bool_from_string(c(' true '))) - self.assertFalse(strutils.bool_from_string(c(' 0 '))) - self.assertFalse(strutils.bool_from_string(c(' false '))) - - def test_bool_from_string(self): - self._test_bool_from_string(lambda s: s) - - def test_unicode_bool_from_string(self): - self._test_bool_from_string(six.text_type) - self.assertFalse(strutils.bool_from_string(u'使用', strict=False)) - - exc = self.assertRaises(ValueError, strutils.bool_from_string, - u'使用', strict=True) - expected_msg = (u"Unrecognized value '使用', acceptable values are:" - u" '0', '1', 'f', 'false', 'n', 'no', 'off', 'on'," - u" 't', 'true', 'y', 'yes'") - self.assertEqual(expected_msg, six.text_type(exc)) - - def test_other_bool_from_string(self): - self.assertFalse(strutils.bool_from_string(None)) - self.assertFalse(strutils.bool_from_string(mock.Mock())) - - def test_int_bool_from_string(self): - self.assertTrue(strutils.bool_from_string(1)) - - self.assertFalse(strutils.bool_from_string(-1)) - self.assertFalse(strutils.bool_from_string(0)) - self.assertFalse(strutils.bool_from_string(2)) - - def test_strict_bool_from_string(self): - # None isn't allowed in strict mode - exc = self.assertRaises(ValueError, strutils.bool_from_string, None, - strict=True) - expected_msg = ("Unrecognized value 'None', acceptable values are:" - " '0', '1', 'f', 'false', 'n', 'no', 'off', 'on'," - " 't', 'true', 'y', 'yes'") - self.assertEqual(expected_msg, str(exc)) - - # Unrecognized strings aren't allowed - self.assertFalse(strutils.bool_from_string('Other', strict=False)) - exc = self.assertRaises(ValueError, strutils.bool_from_string, 'Other', - strict=True) - expected_msg = ("Unrecognized value 'Other', acceptable values are:" - " '0', '1', 'f', 'false', 'n', 'no', 'off', 'on'," - " 't', 'true', 'y', 'yes'") - self.assertEqual(expected_msg, str(exc)) - - # Unrecognized numbers aren't allowed - exc = self.assertRaises(ValueError, strutils.bool_from_string, 2, - strict=True) - expected_msg = ("Unrecognized value '2', acceptable values are:" - " '0', '1', 'f', 'false', 'n', 'no', 'off', 'on'," - " 't', 'true', 'y', 'yes'") - self.assertEqual(expected_msg, str(exc)) - - # False-like values are allowed - self.assertFalse(strutils.bool_from_string('f', strict=True)) - self.assertFalse(strutils.bool_from_string('false', strict=True)) - self.assertFalse(strutils.bool_from_string('off', strict=True)) - self.assertFalse(strutils.bool_from_string('n', strict=True)) - self.assertFalse(strutils.bool_from_string('no', strict=True)) - self.assertFalse(strutils.bool_from_string('0', strict=True)) - - self.assertTrue(strutils.bool_from_string('1', strict=True)) - - # Avoid font-similarity issues (one looks like lowercase-el, zero like - # oh, etc...) - for char in ('O', 'o', 'L', 'l', 'I', 'i'): - self.assertRaises(ValueError, strutils.bool_from_string, char, - strict=True) - - def test_int_from_bool_as_string(self): - self.assertEqual(1, strutils.int_from_bool_as_string(True)) - self.assertEqual(0, strutils.int_from_bool_as_string(False)) - - def test_slugify(self): - to_slug = strutils.to_slug - self.assertRaises(TypeError, to_slug, True) - self.assertEqual(six.u("hello"), to_slug("hello")) - self.assertEqual(six.u("two-words"), to_slug("Two Words")) - self.assertEqual(six.u("ma-any-spa-ce-es"), - to_slug("Ma-any\t spa--ce- es")) - self.assertEqual(six.u("excamation"), to_slug("exc!amation!")) - self.assertEqual(six.u("ampserand"), to_slug("&ser$and")) - self.assertEqual(six.u("ju5tnum8er"), to_slug("ju5tnum8er")) - self.assertEqual(six.u("strip-"), to_slug(" strip - ")) - self.assertEqual(six.u("perche"), to_slug(six.b("perch\xc3\xa9"))) - self.assertEqual(six.u("strange"), - to_slug("\x80strange", errors="ignore")) - - -class StringToBytesTest(test_base.BaseTestCase): - - _unit_system = [ - ('si', dict(unit_system='SI')), - ('iec', dict(unit_system='IEC')), - ('invalid_unit_system', dict(unit_system='KKK', assert_error=True)), - ] - - _sign = [ - ('no_sign', dict(sign='')), - ('positive', dict(sign='+')), - ('negative', dict(sign='-')), - ('invalid_sign', dict(sign='~', assert_error=True)), - ] - - _magnitude = [ - ('integer', dict(magnitude='79')), - ('decimal', dict(magnitude='7.9')), - ('decimal_point_start', dict(magnitude='.9')), - ('decimal_point_end', dict(magnitude='79.', assert_error=True)), - ('invalid_literal', dict(magnitude='7.9.9', assert_error=True)), - ('garbage_value', dict(magnitude='asdf', assert_error=True)), - ] - - _unit_prefix = [ - ('no_unit_prefix', dict(unit_prefix='')), - ('k', dict(unit_prefix='k')), - ('K', dict(unit_prefix='K')), - ('M', dict(unit_prefix='M')), - ('G', dict(unit_prefix='G')), - ('T', dict(unit_prefix='T')), - ('Ki', dict(unit_prefix='Ki')), - ('Mi', dict(unit_prefix='Mi')), - ('Gi', dict(unit_prefix='Gi')), - ('Ti', dict(unit_prefix='Ti')), - ('invalid_unit_prefix', dict(unit_prefix='B', assert_error=True)), - ] - - _unit_suffix = [ - ('b', dict(unit_suffix='b')), - ('bit', dict(unit_suffix='bit')), - ('B', dict(unit_suffix='B')), - ('invalid_unit_suffix', dict(unit_suffix='Kg', assert_error=True)), - ] - - _return_int = [ - ('return_dec', dict(return_int=False)), - ('return_int', dict(return_int=True)), - ] - - @classmethod - def generate_scenarios(cls): - cls.scenarios = testscenarios.multiply_scenarios(cls._unit_system, - cls._sign, - cls._magnitude, - cls._unit_prefix, - cls._unit_suffix, - cls._return_int) - - def test_string_to_bytes(self): - - def _get_quantity(sign, magnitude, unit_suffix): - res = float('%s%s' % (sign, magnitude)) - if unit_suffix in ['b', 'bit']: - res /= 8 - return res - - def _get_constant(unit_prefix, unit_system): - if not unit_prefix: - return 1 - elif unit_system == 'SI': - res = getattr(units, unit_prefix) - elif unit_system == 'IEC': - if unit_prefix.endswith('i'): - res = getattr(units, unit_prefix) - else: - res = getattr(units, '%si' % unit_prefix) - return res - - text = ''.join([self.sign, self.magnitude, self.unit_prefix, - self.unit_suffix]) - err_si = self.unit_system == 'SI' and (self.unit_prefix == 'K' or - self.unit_prefix.endswith('i')) - err_iec = self.unit_system == 'IEC' and self.unit_prefix == 'k' - if getattr(self, 'assert_error', False) or err_si or err_iec: - self.assertRaises(ValueError, strutils.string_to_bytes, - text, unit_system=self.unit_system, - return_int=self.return_int) - return - quantity = _get_quantity(self.sign, self.magnitude, self.unit_suffix) - constant = _get_constant(self.unit_prefix, self.unit_system) - expected = quantity * constant - actual = strutils.string_to_bytes(text, unit_system=self.unit_system, - return_int=self.return_int) - if self.return_int: - self.assertEqual(actual, int(math.ceil(expected))) - else: - self.assertAlmostEqual(actual, expected) - -StringToBytesTest.generate_scenarios() - - -class MaskPasswordTestCase(test_base.BaseTestCase): - - def test_json(self): - # Test 'adminPass' w/o spaces - payload = """{'adminPass':'mypassword'}""" - expected = """{'adminPass':'***'}""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'adminPass' with spaces - payload = """{ 'adminPass' : 'mypassword' }""" - expected = """{ 'adminPass' : '***' }""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_pass' w/o spaces - payload = """{'admin_pass':'mypassword'}""" - expected = """{'admin_pass':'***'}""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_pass' with spaces - payload = """{ 'admin_pass' : 'mypassword' }""" - expected = """{ 'admin_pass' : '***' }""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_password' w/o spaces - payload = """{'admin_password':'mypassword'}""" - expected = """{'admin_password':'***'}""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_password' with spaces - payload = """{ 'admin_password' : 'mypassword' }""" - expected = """{ 'admin_password' : '***' }""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'password' w/o spaces - payload = """{'password':'mypassword'}""" - expected = """{'password':'***'}""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'password' with spaces - payload = """{ 'password' : 'mypassword' }""" - expected = """{ 'password' : '***' }""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'auth_password' w/o spaces - payload = """{'auth_password':'mypassword'}""" - expected = """{'auth_password':'***'}""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'auth_password' with spaces - payload = """{ 'auth_password' : 'mypassword' }""" - expected = """{ 'auth_password' : '***' }""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'secret_uuid' w/o spaces - payload = """{'secret_uuid':'myuuid'}""" - expected = """{'secret_uuid':'***'}""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'secret_uuid' with spaces - payload = """{ 'secret_uuid' : 'myuuid' }""" - expected = """{ 'secret_uuid' : '***' }""" - self.assertEqual(expected, strutils.mask_password(payload)) - - def test_xml(self): - # Test 'adminPass' w/o spaces - payload = """mypassword""" - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'adminPass' with spaces - payload = """ - mypassword - """ - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_pass' w/o spaces - payload = """mypassword""" - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_pass' with spaces - payload = """ - mypassword - """ - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_password' w/o spaces - payload = """mypassword""" - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_password' with spaces - payload = """ - mypassword - """ - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'password' w/o spaces - payload = """mypassword""" - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'password' with spaces - payload = """ - mypassword - """ - expected = """***""" - self.assertEqual(expected, strutils.mask_password(payload)) - - def test_xml_attribute(self): - # Test 'adminPass' w/o spaces - payload = """adminPass='mypassword'""" - expected = """adminPass='***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'adminPass' with spaces - payload = """adminPass = 'mypassword'""" - expected = """adminPass = '***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'adminPass' with double quotes - payload = """adminPass = "mypassword\"""" - expected = """adminPass = "***\"""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_pass' w/o spaces - payload = """admin_pass='mypassword'""" - expected = """admin_pass='***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_pass' with spaces - payload = """admin_pass = 'mypassword'""" - expected = """admin_pass = '***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_pass' with double quotes - payload = """admin_pass = "mypassword\"""" - expected = """admin_pass = "***\"""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_password' w/o spaces - payload = """admin_password='mypassword'""" - expected = """admin_password='***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_password' with spaces - payload = """admin_password = 'mypassword'""" - expected = """admin_password = '***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'admin_password' with double quotes - payload = """admin_password = "mypassword\"""" - expected = """admin_password = "***\"""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'password' w/o spaces - payload = """password='mypassword'""" - expected = """password='***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'password' with spaces - payload = """password = 'mypassword'""" - expected = """password = '***'""" - self.assertEqual(expected, strutils.mask_password(payload)) - # Test 'password' with double quotes - payload = """password = "mypassword\"""" - expected = """password = "***\"""" - self.assertEqual(expected, strutils.mask_password(payload)) - - def test_json_message(self): - payload = """body: {"changePassword": {"adminPass": "1234567"}}""" - expected = """body: {"changePassword": {"adminPass": "***"}}""" - self.assertEqual(expected, strutils.mask_password(payload)) - payload = """body: {"rescue": {"admin_pass": "1234567"}}""" - expected = """body: {"rescue": {"admin_pass": "***"}}""" - self.assertEqual(expected, strutils.mask_password(payload)) - payload = """body: {"rescue": {"admin_password": "1234567"}}""" - expected = """body: {"rescue": {"admin_password": "***"}}""" - self.assertEqual(expected, strutils.mask_password(payload)) - payload = """body: {"rescue": {"password": "1234567"}}""" - expected = """body: {"rescue": {"password": "***"}}""" - self.assertEqual(expected, strutils.mask_password(payload)) - - def test_xml_message(self): - payload = """ - - - Apache1 - -""" - expected = """ - - - Apache1 - -""" - self.assertEqual(expected, strutils.mask_password(payload)) - payload = """ -""" - expected = """ -""" - self.assertEqual(expected, strutils.mask_password(payload)) - payload = """ -""" - expected = """ -""" - self.assertEqual(expected, strutils.mask_password(payload)) - payload = """ -""" - expected = """ -""" - self.assertEqual(expected, strutils.mask_password(payload)) - - def test_mask_password(self): - payload = "test = 'password' : 'aaaaaa'" - expected = "test = 'password' : '111'" - self.assertEqual(expected, - strutils.mask_password(payload, secret='111')) - - payload = 'mysqld --password "aaaaaa"' - expected = 'mysqld --password "****"' - self.assertEqual(expected, - strutils.mask_password(payload, secret='****')) - - payload = 'mysqld --password aaaaaa' - expected = 'mysqld --password ???' - self.assertEqual(expected, - strutils.mask_password(payload, secret='???')) - - payload = 'mysqld --password = "aaaaaa"' - expected = 'mysqld --password = "****"' - self.assertEqual(expected, - strutils.mask_password(payload, secret='****')) - - payload = "mysqld --password = 'aaaaaa'" - expected = "mysqld --password = '****'" - self.assertEqual(expected, - strutils.mask_password(payload, secret='****')) - - payload = "mysqld --password = aaaaaa" - expected = "mysqld --password = ****" - self.assertEqual(expected, - strutils.mask_password(payload, secret='****')) - - payload = "test = password = aaaaaa" - expected = "test = password = 111" - self.assertEqual(expected, - strutils.mask_password(payload, secret='111')) - - payload = "test = password= aaaaaa" - expected = "test = password= 111" - self.assertEqual(expected, - strutils.mask_password(payload, secret='111')) - - payload = "test = password =aaaaaa" - expected = "test = password =111" - self.assertEqual(expected, - strutils.mask_password(payload, secret='111')) - - payload = "test = password=aaaaaa" - expected = "test = password=111" - self.assertEqual(expected, - strutils.mask_password(payload, secret='111')) - - payload = 'test = "original_password" : "aaaaaaaaa"' - expected = 'test = "original_password" : "***"' - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = 'test = "param1" : "value"' - expected = 'test = "param1" : "value"' - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = """{'adminPass':'mypassword'}""" - payload = six.text_type(payload) - expected = """{'adminPass':'***'}""" - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = ("test = 'node.session.auth.password','-v','mypassword'," - "'nomask'") - expected = ("test = 'node.session.auth.password','-v','***'," - "'nomask'") - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = ("test = 'node.session.auth.password', '--password', " - "'mypassword', 'nomask'") - expected = ("test = 'node.session.auth.password', '--password', " - "'***', 'nomask'") - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = ("test = 'node.session.auth.password', '--password', " - "'mypassword'") - expected = ("test = 'node.session.auth.password', '--password', " - "'***'") - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = "test = node.session.auth.password -v mypassword nomask" - expected = "test = node.session.auth.password -v *** nomask" - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = ("test = node.session.auth.password --password mypassword " - "nomask") - expected = ("test = node.session.auth.password --password *** " - "nomask") - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = ("test = node.session.auth.password --password mypassword") - expected = ("test = node.session.auth.password --password ***") - self.assertEqual(expected, strutils.mask_password(payload)) - - payload = "test = cmd --password my\xe9\x80\x80pass" - expected = ("test = cmd --password ***") - self.assertEqual(expected, strutils.mask_password(payload)) - - -class IsIntLikeTestCase(test_base.BaseTestCase): - def test_is_int_like_true(self): - self.assertTrue(strutils.is_int_like(1)) - self.assertTrue(strutils.is_int_like("1")) - self.assertTrue(strutils.is_int_like("514")) - self.assertTrue(strutils.is_int_like("0")) - - def test_is_int_like_false(self): - self.assertFalse(strutils.is_int_like(1.1)) - self.assertFalse(strutils.is_int_like("1.1")) - self.assertFalse(strutils.is_int_like("1.1.1")) - self.assertFalse(strutils.is_int_like(None)) - self.assertFalse(strutils.is_int_like("0.")) - self.assertFalse(strutils.is_int_like("aaaaaa")) - self.assertFalse(strutils.is_int_like("....")) - self.assertFalse(strutils.is_int_like("1g")) - self.assertFalse( - strutils.is_int_like("0cc3346e-9fef-4445-abe6-5d2b2690ec64")) - self.assertFalse(strutils.is_int_like("a1")) - # NOTE(viktors): 12e3 - is a float number - self.assertFalse(strutils.is_int_like("12e3")) - # NOTE(viktors): Check integer numbers with base not 10 - self.assertFalse(strutils.is_int_like("0o51")) - self.assertFalse(strutils.is_int_like("0xDEADBEEF")) diff --git a/awx/lib/site-packages/oslo_utils/tests/test_timeutils.py b/awx/lib/site-packages/oslo_utils/tests/test_timeutils.py deleted file mode 100644 index cacb0ef4fe..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_timeutils.py +++ /dev/null @@ -1,508 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import calendar -import datetime -import time - -import iso8601 -import mock -from oslotest import base as test_base -from testtools import matchers - -from oslo_utils import timeutils - - -def monotonic_iter(start=0, incr=0.05): - while True: - yield start - start += incr - - -class TimeUtilsTest(test_base.BaseTestCase): - - def setUp(self): - super(TimeUtilsTest, self).setUp() - self.skynet_self_aware_time_str = '1997-08-29T06:14:00Z' - self.skynet_self_aware_time_ms_str = '1997-08-29T06:14:00.000123Z' - self.skynet_self_aware_time = datetime.datetime(1997, 8, 29, 6, 14, 0) - self.skynet_self_aware_ms_time = datetime.datetime( - 1997, 8, 29, 6, 14, 0, 123) - self.one_minute_before = datetime.datetime(1997, 8, 29, 6, 13, 0) - self.one_minute_after = datetime.datetime(1997, 8, 29, 6, 15, 0) - self.skynet_self_aware_time_perfect_str = '1997-08-29T06:14:00.000000' - self.skynet_self_aware_time_perfect = datetime.datetime(1997, 8, 29, - 6, 14, 0) - self.addCleanup(timeutils.clear_time_override) - - def test_isotime(self): - with mock.patch('datetime.datetime') as datetime_mock: - datetime_mock.utcnow.return_value = self.skynet_self_aware_time - dt = timeutils.isotime() - self.assertEqual(dt, self.skynet_self_aware_time_str) - - def test_isotimei_micro_second_precision(self): - with mock.patch('datetime.datetime') as datetime_mock: - datetime_mock.utcnow.return_value = self.skynet_self_aware_ms_time - dt = timeutils.isotime(subsecond=True) - self.assertEqual(dt, self.skynet_self_aware_time_ms_str) - - def test_parse_isotime(self): - expect = timeutils.parse_isotime(self.skynet_self_aware_time_str) - skynet_self_aware_time_utc = self.skynet_self_aware_time.replace( - tzinfo=iso8601.iso8601.UTC) - self.assertEqual(skynet_self_aware_time_utc, expect) - - def test_parse_isotime_micro_second_precision(self): - expect = timeutils.parse_isotime(self.skynet_self_aware_time_ms_str) - skynet_self_aware_time_ms_utc = self.skynet_self_aware_ms_time.replace( - tzinfo=iso8601.iso8601.UTC) - self.assertEqual(skynet_self_aware_time_ms_utc, expect) - - def test_strtime(self): - expect = timeutils.strtime(self.skynet_self_aware_time_perfect) - self.assertEqual(self.skynet_self_aware_time_perfect_str, expect) - - def test_parse_strtime(self): - perfect_time_format = self.skynet_self_aware_time_perfect_str - expect = timeutils.parse_strtime(perfect_time_format) - self.assertEqual(self.skynet_self_aware_time_perfect, expect) - - def test_strtime_and_back(self): - orig_t = datetime.datetime(1997, 8, 29, 6, 14, 0) - s = timeutils.strtime(orig_t) - t = timeutils.parse_strtime(s) - self.assertEqual(orig_t, t) - - def _test_is_older_than(self, fn): - strptime = datetime.datetime.strptime - with mock.patch('datetime.datetime') as datetime_mock: - datetime_mock.utcnow.return_value = self.skynet_self_aware_time - datetime_mock.strptime = strptime - expect_true = timeutils.is_older_than(fn(self.one_minute_before), - 59) - self.assertTrue(expect_true) - expect_false = timeutils.is_older_than(fn(self.one_minute_before), - 60) - self.assertFalse(expect_false) - expect_false = timeutils.is_older_than(fn(self.one_minute_before), - 61) - self.assertFalse(expect_false) - - def test_is_older_than_datetime(self): - self._test_is_older_than(lambda x: x) - - def test_is_older_than_str(self): - self._test_is_older_than(timeutils.strtime) - - def test_is_older_than_aware(self): - """Tests sending is_older_than an 'aware' datetime.""" - self._test_is_older_than(lambda x: x.replace( - tzinfo=iso8601.iso8601.UTC)) - - def _test_is_newer_than(self, fn): - strptime = datetime.datetime.strptime - with mock.patch('datetime.datetime') as datetime_mock: - datetime_mock.utcnow.return_value = self.skynet_self_aware_time - datetime_mock.strptime = strptime - expect_true = timeutils.is_newer_than(fn(self.one_minute_after), - 59) - self.assertTrue(expect_true) - expect_false = timeutils.is_newer_than(fn(self.one_minute_after), - 60) - self.assertFalse(expect_false) - expect_false = timeutils.is_newer_than(fn(self.one_minute_after), - 61) - self.assertFalse(expect_false) - - def test_is_newer_than_datetime(self): - self._test_is_newer_than(lambda x: x) - - def test_is_newer_than_str(self): - self._test_is_newer_than(timeutils.strtime) - - def test_is_newer_than_aware(self): - """Tests sending is_newer_than an 'aware' datetime.""" - self._test_is_newer_than(lambda x: x.replace( - tzinfo=iso8601.iso8601.UTC)) - - def test_set_time_override_using_default(self): - now = timeutils.utcnow_ts() - - # NOTE(kgriffs): Normally it's bad form to sleep in a unit test, - # but this is the only way to test that set_time_override defaults - # to setting the override to the current time. - time.sleep(1) - - timeutils.set_time_override() - overriden_now = timeutils.utcnow_ts() - self.assertThat(now, matchers.LessThan(overriden_now)) - - def test_utcnow_ts(self): - skynet_self_aware_ts = 872835240 - skynet_dt = datetime.datetime.utcfromtimestamp(skynet_self_aware_ts) - self.assertEqual(self.skynet_self_aware_time, skynet_dt) - - # NOTE(kgriffs): timeutils.utcnow_ts() uses time.time() - # IFF time override is not set. - with mock.patch('time.time') as time_mock: - time_mock.return_value = skynet_self_aware_ts - ts = timeutils.utcnow_ts() - self.assertEqual(ts, skynet_self_aware_ts) - - timeutils.set_time_override(skynet_dt) - ts = timeutils.utcnow_ts() - self.assertEqual(ts, skynet_self_aware_ts) - - def test_utcnow(self): - timeutils.set_time_override(mock.sentinel.utcnow) - self.assertEqual(timeutils.utcnow(), mock.sentinel.utcnow) - - timeutils.clear_time_override() - self.assertFalse(timeutils.utcnow() == mock.sentinel.utcnow) - - self.assertTrue(timeutils.utcnow()) - - def test_advance_time_delta(self): - timeutils.set_time_override(self.one_minute_before) - timeutils.advance_time_delta(datetime.timedelta(seconds=60)) - self.assertEqual(timeutils.utcnow(), self.skynet_self_aware_time) - - def test_advance_time_seconds(self): - timeutils.set_time_override(self.one_minute_before) - timeutils.advance_time_seconds(60) - self.assertEqual(timeutils.utcnow(), self.skynet_self_aware_time) - - def test_marshall_time(self): - now = timeutils.utcnow() - binary = timeutils.marshall_now(now) - backagain = timeutils.unmarshall_time(binary) - self.assertEqual(now, backagain) - - def test_delta_seconds(self): - before = timeutils.utcnow() - after = before + datetime.timedelta(days=7, seconds=59, - microseconds=123456) - self.assertAlmostEquals(604859.123456, - timeutils.delta_seconds(before, after)) - - def test_total_seconds(self): - delta = datetime.timedelta(days=1, hours=2, minutes=3, seconds=4.5) - self.assertAlmostEquals(93784.5, - timeutils.total_seconds(delta)) - - def test_iso8601_from_timestamp(self): - utcnow = timeutils.utcnow() - iso = timeutils.isotime(utcnow) - ts = calendar.timegm(utcnow.timetuple()) - self.assertEqual(iso, timeutils.iso8601_from_timestamp(ts)) - - def test_iso8601_from_timestamp_ms(self): - ts = timeutils.utcnow_ts(microsecond=True) - utcnow = datetime.datetime.utcfromtimestamp(ts) - iso = timeutils.isotime(utcnow, subsecond=True) - self.assertEqual(iso, timeutils.iso8601_from_timestamp(ts, True)) - - def test_is_soon(self): - expires = timeutils.utcnow() + datetime.timedelta(minutes=5) - self.assertFalse(timeutils.is_soon(expires, 120)) - self.assertTrue(timeutils.is_soon(expires, 300)) - self.assertTrue(timeutils.is_soon(expires, 600)) - - with mock.patch('datetime.datetime') as datetime_mock: - datetime_mock.utcnow.return_value = self.skynet_self_aware_time - expires = timeutils.utcnow() - self.assertTrue(timeutils.is_soon(expires, 0)) - - -class TestIso8601Time(test_base.BaseTestCase): - - def _instaneous(self, timestamp, yr, mon, day, hr, minute, sec, micro): - self.assertEqual(timestamp.year, yr) - self.assertEqual(timestamp.month, mon) - self.assertEqual(timestamp.day, day) - self.assertEqual(timestamp.hour, hr) - self.assertEqual(timestamp.minute, minute) - self.assertEqual(timestamp.second, sec) - self.assertEqual(timestamp.microsecond, micro) - - def _do_test(self, time_str, yr, mon, day, hr, minute, sec, micro, shift): - DAY_SECONDS = 24 * 60 * 60 - timestamp = timeutils.parse_isotime(time_str) - self._instaneous(timestamp, yr, mon, day, hr, minute, sec, micro) - offset = timestamp.tzinfo.utcoffset(None) - self.assertEqual(offset.seconds + offset.days * DAY_SECONDS, shift) - - def test_zulu(self): - time_str = '2012-02-14T20:53:07Z' - self._do_test(time_str, 2012, 2, 14, 20, 53, 7, 0, 0) - - def test_zulu_micros(self): - time_str = '2012-02-14T20:53:07.123Z' - self._do_test(time_str, 2012, 2, 14, 20, 53, 7, 123000, 0) - - def test_offset_east(self): - time_str = '2012-02-14T20:53:07+04:30' - offset = 4.5 * 60 * 60 - self._do_test(time_str, 2012, 2, 14, 20, 53, 7, 0, offset) - - def test_offset_east_micros(self): - time_str = '2012-02-14T20:53:07.42+04:30' - offset = 4.5 * 60 * 60 - self._do_test(time_str, 2012, 2, 14, 20, 53, 7, 420000, offset) - - def test_offset_west(self): - time_str = '2012-02-14T20:53:07-05:30' - offset = -5.5 * 60 * 60 - self._do_test(time_str, 2012, 2, 14, 20, 53, 7, 0, offset) - - def test_offset_west_micros(self): - time_str = '2012-02-14T20:53:07.654321-05:30' - offset = -5.5 * 60 * 60 - self._do_test(time_str, 2012, 2, 14, 20, 53, 7, 654321, offset) - - def test_compare(self): - zulu = timeutils.parse_isotime('2012-02-14T20:53:07') - east = timeutils.parse_isotime('2012-02-14T20:53:07-01:00') - west = timeutils.parse_isotime('2012-02-14T20:53:07+01:00') - self.assertTrue(east > west) - self.assertTrue(east > zulu) - self.assertTrue(zulu > west) - - def test_compare_micros(self): - zulu = timeutils.parse_isotime('2012-02-14T20:53:07.6544') - east = timeutils.parse_isotime('2012-02-14T19:53:07.654321-01:00') - west = timeutils.parse_isotime('2012-02-14T21:53:07.655+01:00') - self.assertTrue(east < west) - self.assertTrue(east < zulu) - self.assertTrue(zulu < west) - - def test_zulu_roundtrip(self): - time_str = '2012-02-14T20:53:07Z' - zulu = timeutils.parse_isotime(time_str) - self.assertEqual(zulu.tzinfo, iso8601.iso8601.UTC) - self.assertEqual(timeutils.isotime(zulu), time_str) - - def test_east_roundtrip(self): - time_str = '2012-02-14T20:53:07-07:00' - east = timeutils.parse_isotime(time_str) - self.assertEqual(east.tzinfo.tzname(None), '-07:00') - self.assertEqual(timeutils.isotime(east), time_str) - - def test_west_roundtrip(self): - time_str = '2012-02-14T20:53:07+11:30' - west = timeutils.parse_isotime(time_str) - self.assertEqual(west.tzinfo.tzname(None), '+11:30') - self.assertEqual(timeutils.isotime(west), time_str) - - def test_now_roundtrip(self): - time_str = timeutils.isotime() - now = timeutils.parse_isotime(time_str) - self.assertEqual(now.tzinfo, iso8601.iso8601.UTC) - self.assertEqual(timeutils.isotime(now), time_str) - - def test_zulu_normalize(self): - time_str = '2012-02-14T20:53:07Z' - zulu = timeutils.parse_isotime(time_str) - normed = timeutils.normalize_time(zulu) - self._instaneous(normed, 2012, 2, 14, 20, 53, 7, 0) - - def test_east_normalize(self): - time_str = '2012-02-14T20:53:07-07:00' - east = timeutils.parse_isotime(time_str) - normed = timeutils.normalize_time(east) - self._instaneous(normed, 2012, 2, 15, 3, 53, 7, 0) - - def test_west_normalize(self): - time_str = '2012-02-14T20:53:07+21:00' - west = timeutils.parse_isotime(time_str) - normed = timeutils.normalize_time(west) - self._instaneous(normed, 2012, 2, 13, 23, 53, 7, 0) - - def test_normalize_aware_to_naive(self): - dt = datetime.datetime(2011, 2, 14, 20, 53, 7) - time_str = '2011-02-14T20:53:07+21:00' - aware = timeutils.parse_isotime(time_str) - naive = timeutils.normalize_time(aware) - self.assertTrue(naive < dt) - - def test_normalize_zulu_aware_to_naive(self): - dt = datetime.datetime(2011, 2, 14, 20, 53, 7) - time_str = '2011-02-14T19:53:07Z' - aware = timeutils.parse_isotime(time_str) - naive = timeutils.normalize_time(aware) - self.assertTrue(naive < dt) - - def test_normalize_naive(self): - dt = datetime.datetime(2011, 2, 14, 20, 53, 7) - dtn = datetime.datetime(2011, 2, 14, 19, 53, 7) - naive = timeutils.normalize_time(dtn) - self.assertTrue(naive < dt) - - -class StopWatchTest(test_base.BaseTestCase): - def test_leftover_no_duration(self): - watch = timeutils.StopWatch() - watch.start() - self.assertRaises(RuntimeError, watch.leftover) - self.assertRaises(RuntimeError, watch.leftover, return_none=False) - self.assertIsNone(watch.leftover(return_none=True)) - - def test_no_states(self): - watch = timeutils.StopWatch() - self.assertRaises(RuntimeError, watch.stop) - self.assertRaises(RuntimeError, watch.resume) - - def test_bad_expiry(self): - self.assertRaises(ValueError, timeutils.StopWatch, -1) - - @mock.patch('oslo_utils.timeutils.now') - def test_backwards(self, mock_now): - mock_now.side_effect = [0, 0.5, -1.0, -1.0] - watch = timeutils.StopWatch(0.1) - watch.start() - self.assertTrue(watch.expired()) - self.assertFalse(watch.expired()) - self.assertEqual(0.0, watch.elapsed()) - - @mock.patch('oslo_utils.timeutils.now') - def test_expiry(self, mock_now): - mock_now.side_effect = monotonic_iter(incr=0.2) - watch = timeutils.StopWatch(0.1) - watch.start() - self.assertTrue(watch.expired()) - - @mock.patch('oslo_utils.timeutils.now') - def test_not_expired(self, mock_now): - mock_now.side_effect = monotonic_iter() - watch = timeutils.StopWatch(0.1) - watch.start() - self.assertFalse(watch.expired()) - - def test_has_started_stopped(self): - watch = timeutils.StopWatch() - self.assertFalse(watch.has_started()) - self.assertFalse(watch.has_stopped()) - watch.start() - - self.assertTrue(watch.has_started()) - self.assertFalse(watch.has_stopped()) - - watch.stop() - self.assertTrue(watch.has_stopped()) - self.assertFalse(watch.has_started()) - - def test_no_expiry(self): - watch = timeutils.StopWatch(0.1) - self.assertRaises(RuntimeError, watch.expired) - - @mock.patch('oslo_utils.timeutils.now') - def test_elapsed(self, mock_now): - mock_now.side_effect = monotonic_iter(incr=0.2) - watch = timeutils.StopWatch() - watch.start() - matcher = matchers.GreaterThan(0.19) - self.assertThat(watch.elapsed(), matcher) - - def test_no_elapsed(self): - watch = timeutils.StopWatch() - self.assertRaises(RuntimeError, watch.elapsed) - - def test_no_leftover(self): - watch = timeutils.StopWatch() - self.assertRaises(RuntimeError, watch.leftover) - watch = timeutils.StopWatch(1) - self.assertRaises(RuntimeError, watch.leftover) - - @mock.patch('oslo_utils.timeutils.now') - def test_pause_resume(self, mock_now): - mock_now.side_effect = monotonic_iter() - watch = timeutils.StopWatch() - watch.start() - watch.stop() - elapsed = watch.elapsed() - self.assertAlmostEqual(elapsed, watch.elapsed()) - watch.resume() - self.assertNotEqual(elapsed, watch.elapsed()) - - @mock.patch('oslo_utils.timeutils.now') - def test_context_manager(self, mock_now): - mock_now.side_effect = monotonic_iter() - with timeutils.StopWatch() as watch: - pass - matcher = matchers.GreaterThan(0.04) - self.assertThat(watch.elapsed(), matcher) - - @mock.patch('oslo_utils.timeutils.now') - def test_context_manager_splits(self, mock_now): - mock_now.side_effect = monotonic_iter() - with timeutils.StopWatch() as watch: - time.sleep(0.01) - watch.split() - self.assertRaises(RuntimeError, watch.split) - self.assertEqual(1, len(watch.splits)) - - def test_splits_stopped(self): - watch = timeutils.StopWatch() - watch.start() - watch.split() - watch.stop() - self.assertRaises(RuntimeError, watch.split) - - def test_splits_never_started(self): - watch = timeutils.StopWatch() - self.assertRaises(RuntimeError, watch.split) - - @mock.patch('oslo_utils.timeutils.now') - def test_splits(self, mock_now): - mock_now.side_effect = monotonic_iter() - - watch = timeutils.StopWatch() - watch.start() - self.assertEqual(0, len(watch.splits)) - - watch.split() - self.assertEqual(1, len(watch.splits)) - self.assertEqual(watch.splits[0].elapsed, - watch.splits[0].length) - - watch.split() - splits = watch.splits - self.assertEqual(2, len(splits)) - self.assertNotEqual(splits[0].elapsed, splits[1].elapsed) - self.assertEqual(splits[1].length, - splits[1].elapsed - splits[0].elapsed) - - watch.stop() - self.assertEqual(2, len(watch.splits)) - - watch.start() - self.assertEqual(0, len(watch.splits)) - - @mock.patch('oslo_utils.timeutils.now') - def test_elapsed_maximum(self, mock_now): - mock_now.side_effect = [0, 1] + ([11] * 4) - - watch = timeutils.StopWatch() - watch.start() - self.assertEqual(1, watch.elapsed()) - - self.assertEqual(11, watch.elapsed()) - self.assertEqual(1, watch.elapsed(maximum=1)) - - watch.stop() - self.assertEqual(11, watch.elapsed()) - self.assertEqual(11, watch.elapsed()) - self.assertEqual(0, watch.elapsed(maximum=-1)) diff --git a/awx/lib/site-packages/oslo_utils/tests/test_uuidutils.py b/awx/lib/site-packages/oslo_utils/tests/test_uuidutils.py deleted file mode 100644 index 95ede43aca..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/test_uuidutils.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2012 Intel Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import uuid - -from oslotest import base as test_base - -from oslo_utils import uuidutils - - -class UUIDUtilsTest(test_base.BaseTestCase): - - def test_generate_uuid(self): - uuid_string = uuidutils.generate_uuid() - self.assertTrue(isinstance(uuid_string, str)) - self.assertEqual(len(uuid_string), 36) - # make sure there are 4 dashes - self.assertEqual(len(uuid_string.replace('-', '')), 32) - - def test_is_uuid_like(self): - self.assertTrue(uuidutils.is_uuid_like(str(uuid.uuid4()))) - self.assertTrue(uuidutils.is_uuid_like( - '{12345678-1234-5678-1234-567812345678}')) - self.assertTrue(uuidutils.is_uuid_like( - '12345678123456781234567812345678')) - self.assertTrue(uuidutils.is_uuid_like( - 'urn:uuid:12345678-1234-5678-1234-567812345678')) - self.assertTrue(uuidutils.is_uuid_like( - 'urn:bbbaaaaa-aaaa-aaaa-aabb-bbbbbbbbbbbb')) - self.assertTrue(uuidutils.is_uuid_like( - 'uuid:bbbaaaaa-aaaa-aaaa-aabb-bbbbbbbbbbbb')) - self.assertTrue(uuidutils.is_uuid_like( - '{}---bbb---aaa--aaa--aaa-----aaa---aaa--bbb-bbb---bbb-bbb-bb-{}')) - - def test_is_uuid_like_insensitive(self): - self.assertTrue(uuidutils.is_uuid_like(str(uuid.uuid4()).upper())) - - def test_id_is_uuid_like(self): - self.assertFalse(uuidutils.is_uuid_like(1234567)) - - def test_name_is_uuid_like(self): - self.assertFalse(uuidutils.is_uuid_like('zhongyueluo')) diff --git a/awx/lib/site-packages/oslo_utils/tests/tests_encodeutils.py b/awx/lib/site-packages/oslo_utils/tests/tests_encodeutils.py deleted file mode 100644 index 6af4bfb51b..0000000000 --- a/awx/lib/site-packages/oslo_utils/tests/tests_encodeutils.py +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2014 Red Hat, Inc. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock -from oslotest import base as test_base -import six - -from oslo_utils import encodeutils - - -class EncodeUtilsTest(test_base.BaseTestCase): - - def test_safe_decode(self): - safe_decode = encodeutils.safe_decode - self.assertRaises(TypeError, safe_decode, True) - self.assertEqual(six.u('ni\xf1o'), safe_decode(six.b("ni\xc3\xb1o"), - incoming="utf-8")) - if six.PY2: - # In Python 3, bytes.decode() doesn't support anymore - # bytes => bytes encodings like base64 - self.assertEqual(six.u("test"), safe_decode("dGVzdA==", - incoming='base64')) - - self.assertEqual(six.u("strange"), safe_decode(six.b('\x80strange'), - errors='ignore')) - - self.assertEqual(six.u('\xc0'), safe_decode(six.b('\xc0'), - incoming='iso-8859-1')) - - # Forcing incoming to ascii so it falls back to utf-8 - self.assertEqual(six.u('ni\xf1o'), safe_decode(six.b('ni\xc3\xb1o'), - incoming='ascii')) - - self.assertEqual(six.u('foo'), safe_decode(b'foo')) - - def test_safe_encode_none_instead_of_text(self): - self.assertRaises(TypeError, encodeutils.safe_encode, None) - - def test_safe_encode_bool_instead_of_text(self): - self.assertRaises(TypeError, encodeutils.safe_encode, True) - - def test_safe_encode_int_instead_of_text(self): - self.assertRaises(TypeError, encodeutils.safe_encode, 1) - - def test_safe_encode_list_instead_of_text(self): - self.assertRaises(TypeError, encodeutils.safe_encode, []) - - def test_safe_encode_dict_instead_of_text(self): - self.assertRaises(TypeError, encodeutils.safe_encode, {}) - - def test_safe_encode_tuple_instead_of_text(self): - self.assertRaises(TypeError, encodeutils.safe_encode, ('foo', 'bar', )) - - def test_safe_encode_py2(self): - if six.PY2: - # In Python 3, str.encode() doesn't support anymore - # text => text encodings like base64 - self.assertEqual( - six.b("dGVzdA==\n"), - encodeutils.safe_encode("test", encoding='base64'), - ) - else: - self.skipTest("Requires py2.x") - - def test_safe_encode_force_incoming_utf8_to_ascii(self): - # Forcing incoming to ascii so it falls back to utf-8 - self.assertEqual( - six.b('ni\xc3\xb1o'), - encodeutils.safe_encode(six.b('ni\xc3\xb1o'), incoming='ascii'), - ) - - def test_safe_encode_same_encoding_different_cases(self): - with mock.patch.object(encodeutils, 'safe_decode', mock.Mock()): - utf8 = encodeutils.safe_encode( - six.u('foo\xf1bar'), encoding='utf-8') - self.assertEqual( - encodeutils.safe_encode(utf8, 'UTF-8', 'utf-8'), - encodeutils.safe_encode(utf8, 'utf-8', 'UTF-8'), - ) - self.assertEqual( - encodeutils.safe_encode(utf8, 'UTF-8', 'utf-8'), - encodeutils.safe_encode(utf8, 'utf-8', 'utf-8'), - ) - encodeutils.safe_decode.assert_has_calls([]) - - def test_safe_encode_different_encodings(self): - text = six.u('foo\xc3\xb1bar') - result = encodeutils.safe_encode( - text=text, incoming='utf-8', encoding='iso-8859-1') - self.assertNotEqual(text, result) - self.assertNotEqual(six.b("foo\xf1bar"), result) diff --git a/awx/lib/site-packages/oslo_utils/timeutils.py b/awx/lib/site-packages/oslo_utils/timeutils.py deleted file mode 100644 index 437b729b1c..0000000000 --- a/awx/lib/site-packages/oslo_utils/timeutils.py +++ /dev/null @@ -1,430 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Time related utilities and helper functions. -""" - -import calendar -import datetime -import time - -import iso8601 -import six - -from oslo_utils import reflection - -# ISO 8601 extended time format with microseconds -_ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f' -_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S' -PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND - -# Use monotonic time in stopwatches if we can get at it... -# -# PEP @ https://www.python.org/dev/peps/pep-0418/ -try: - now = time.monotonic -except AttributeError: - try: - # Try to use the pypi module if it's available (optionally...) - from monotonic import monotonic as now - except (AttributeError, ImportError): - # Ok fallback to the non-monotonic one... - now = time.time - - -def isotime(at=None, subsecond=False): - """Stringify time in ISO 8601 format.""" - if not at: - at = utcnow() - st = at.strftime(_ISO8601_TIME_FORMAT - if not subsecond - else _ISO8601_TIME_FORMAT_SUBSECOND) - tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC' - st += ('Z' if tz == 'UTC' else tz) - return st - - -def parse_isotime(timestr): - """Parse time from ISO 8601 format.""" - try: - return iso8601.parse_date(timestr) - except iso8601.ParseError as e: - raise ValueError(six.text_type(e)) - except TypeError as e: - raise ValueError(six.text_type(e)) - - -def strtime(at=None, fmt=PERFECT_TIME_FORMAT): - """Returns formatted utcnow.""" - if not at: - at = utcnow() - return at.strftime(fmt) - - -def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): - """Turn a formatted time back into a datetime.""" - return datetime.datetime.strptime(timestr, fmt) - - -def normalize_time(timestamp): - """Normalize time in arbitrary timezone to UTC naive object.""" - offset = timestamp.utcoffset() - if offset is None: - return timestamp - return timestamp.replace(tzinfo=None) - offset - - -def is_older_than(before, seconds): - """Return True if before is older than seconds.""" - if isinstance(before, six.string_types): - before = parse_strtime(before).replace(tzinfo=None) - else: - before = before.replace(tzinfo=None) - - return utcnow() - before > datetime.timedelta(seconds=seconds) - - -def is_newer_than(after, seconds): - """Return True if after is newer than seconds.""" - if isinstance(after, six.string_types): - after = parse_strtime(after).replace(tzinfo=None) - else: - after = after.replace(tzinfo=None) - - return after - utcnow() > datetime.timedelta(seconds=seconds) - - -def utcnow_ts(microsecond=False): - """Timestamp version of our utcnow function. - - See :py:class:`oslo_utils.fixture.TimeFixture`. - - """ - if utcnow.override_time is None: - # NOTE(kgriffs): This is several times faster - # than going through calendar.timegm(...) - timestamp = time.time() - if not microsecond: - timestamp = int(timestamp) - return timestamp - - now = utcnow() - timestamp = calendar.timegm(now.timetuple()) - - if microsecond: - timestamp += float(now.microsecond) / 1000000 - - return timestamp - - -def utcnow(): - """Overridable version of utils.utcnow. - - See :py:class:`oslo_utils.fixture.TimeFixture`. - - """ - if utcnow.override_time: - try: - return utcnow.override_time.pop(0) - except AttributeError: - return utcnow.override_time - return datetime.datetime.utcnow() - - -def iso8601_from_timestamp(timestamp, microsecond=False): - """Returns an iso8601 formatted date from timestamp.""" - return isotime(datetime.datetime.utcfromtimestamp(timestamp), microsecond) - - -utcnow.override_time = None - - -def set_time_override(override_time=None): - """Overrides utils.utcnow. - - Make it return a constant time or a list thereof, one at a time. - - See :py:class:`oslo_utils.fixture.TimeFixture`. - - :param override_time: datetime instance or list thereof. If not - given, defaults to the current UTC time. - """ - utcnow.override_time = override_time or datetime.datetime.utcnow() - - -def advance_time_delta(timedelta): - """Advance overridden time using a datetime.timedelta. - - See :py:class:`oslo_utils.fixture.TimeFixture`. - - """ - assert utcnow.override_time is not None - try: - for dt in utcnow.override_time: - dt += timedelta - except TypeError: - utcnow.override_time += timedelta - - -def advance_time_seconds(seconds): - """Advance overridden time by seconds. - - See :py:class:`oslo_utils.fixture.TimeFixture`. - - """ - advance_time_delta(datetime.timedelta(0, seconds)) - - -def clear_time_override(): - """Remove the overridden time. - - See :py:class:`oslo_utils.fixture.TimeFixture`. - - """ - utcnow.override_time = None - - -def marshall_now(now=None): - """Make an rpc-safe datetime with microseconds. - - Note: tzinfo is stripped, but not required for relative times. - """ - if not now: - now = utcnow() - return dict(day=now.day, month=now.month, year=now.year, hour=now.hour, - minute=now.minute, second=now.second, - microsecond=now.microsecond) - - -def unmarshall_time(tyme): - """Unmarshall a datetime dict.""" - return datetime.datetime(day=tyme['day'], - month=tyme['month'], - year=tyme['year'], - hour=tyme['hour'], - minute=tyme['minute'], - second=tyme['second'], - microsecond=tyme['microsecond']) - - -def delta_seconds(before, after): - """Return the difference between two timing objects. - - Compute the difference in seconds between two date, time, or - datetime objects (as a float, to microsecond resolution). - """ - delta = after - before - return total_seconds(delta) - - -def total_seconds(delta): - """Return the total seconds of datetime.timedelta object. - - Compute total seconds of datetime.timedelta, datetime.timedelta - doesn't have method total_seconds in Python2.6, calculate it manually. - """ - try: - return delta.total_seconds() - except AttributeError: - return ((delta.days * 24 * 3600) + delta.seconds + - float(delta.microseconds) / (10 ** 6)) - - -def is_soon(dt, window): - """Determines if time is going to happen in the next window seconds. - - :param dt: the time - :param window: minimum seconds to remain to consider the time not soon - - :return: True if expiration is within the given duration - """ - soon = (utcnow() + datetime.timedelta(seconds=window)) - return normalize_time(dt) <= soon - - -class Split(object): - """A *immutable* stopwatch split. - - See: http://en.wikipedia.org/wiki/Stopwatch for what this is/represents. - """ - - __slots__ = ['_elapsed', '_length'] - - def __init__(self, elapsed, length): - self._elapsed = elapsed - self._length = length - - @property - def elapsed(self): - """Duration from stopwatch start.""" - return self._elapsed - - @property - def length(self): - """Seconds from last split (or the elapsed time if no prior split).""" - return self._length - - def __repr__(self): - r = reflection.get_class_name(self, fully_qualified=False) - r += "(elapsed=%s, length=%s)" % (self._elapsed, self._length) - return r - - -class StopWatch(object): - """A simple timer/stopwatch helper class. - - Inspired by: apache-commons-lang java stopwatch. - - Not thread-safe (when a single watch is mutated by multiple threads at - the same time). Thread-safe when used by a single thread (not shared) or - when operations are performed in a thread-safe manner on these objects by - wrapping those operations with locks. - """ - _STARTED = 'STARTED' - _STOPPED = 'STOPPED' - - def __init__(self, duration=None): - if duration is not None and duration < 0: - raise ValueError("Duration must be greater or equal to" - " zero and not %s" % duration) - self._duration = duration - self._started_at = None - self._stopped_at = None - self._state = None - self._splits = [] - - def start(self): - """Starts the watch (if not already started). - - NOTE(harlowja): resets any splits previously captured (if any). - """ - if self._state == self._STARTED: - return self - self._started_at = now() - self._stopped_at = None - self._state = self._STARTED - self._splits = [] - return self - - @property - def splits(self): - """Accessor to all/any splits that have been captured.""" - return tuple(self._splits) - - def split(self): - """Captures a split/elapsed since start time (and doesn't stop).""" - if self._state == self._STARTED: - elapsed = self.elapsed() - if self._splits: - length = self._delta_seconds(self._splits[-1].elapsed, elapsed) - else: - length = elapsed - self._splits.append(Split(elapsed, length)) - return self._splits[-1] - else: - raise RuntimeError("Can not create a split time of a stopwatch" - " if it has not been started or if it has been" - " stopped") - - def restart(self): - """Restarts the watch from a started/stopped state.""" - if self._state == self._STARTED: - self.stop() - self.start() - return self - - @staticmethod - def _delta_seconds(earlier, later): - # Uses max to avoid the delta/time going backwards (and thus negative). - return max(0.0, later - earlier) - - def elapsed(self, maximum=None): - """Returns how many seconds have elapsed.""" - if self._state not in (self._STARTED, self._STOPPED): - raise RuntimeError("Can not get the elapsed time of a stopwatch" - " if it has not been started/stopped") - if self._state == self._STOPPED: - elapsed = self._delta_seconds(self._started_at, self._stopped_at) - else: - elapsed = self._delta_seconds(self._started_at, now()) - if maximum is not None and elapsed > maximum: - elapsed = max(0.0, maximum) - return elapsed - - def __enter__(self): - """Starts the watch.""" - self.start() - return self - - def __exit__(self, type, value, traceback): - """Stops the watch (ignoring errors if stop fails).""" - try: - self.stop() - except RuntimeError: - pass - - def leftover(self, return_none=False): - """Returns how many seconds are left until the watch expires. - - :param return_none: when ``True`` instead of raising a ``RuntimeError`` - when no duration has been set this call will - return ``None`` instead. - :type return_none: boolean - """ - if self._state != self._STARTED: - raise RuntimeError("Can not get the leftover time of a stopwatch" - " that has not been started") - if self._duration is None: - if not return_none: - raise RuntimeError("Can not get the leftover time of a watch" - " that has no duration") - return None - return max(0.0, self._duration - self.elapsed()) - - def expired(self): - """Returns if the watch has expired (ie, duration provided elapsed).""" - if self._state not in (self._STARTED, self._STOPPED): - raise RuntimeError("Can not check if a stopwatch has expired" - " if it has not been started/stopped") - if self._duration is None: - return False - return self.elapsed() > self._duration - - def has_started(self): - return self._state == self._STARTED - - def has_stopped(self): - return self._state == self._STOPPED - - def resume(self): - """Resumes the watch from a stopped state.""" - if self._state == self._STOPPED: - self._state = self._STARTED - return self - else: - raise RuntimeError("Can not resume a stopwatch that has not been" - " stopped") - - def stop(self): - """Stops the watch.""" - if self._state == self._STOPPED: - return self - if self._state != self._STARTED: - raise RuntimeError("Can not stop a stopwatch that has not been" - " started") - self._stopped_at = now() - self._state = self._STOPPED - return self diff --git a/awx/lib/site-packages/oslo_utils/units.py b/awx/lib/site-packages/oslo_utils/units.py deleted file mode 100644 index 4817da509f..0000000000 --- a/awx/lib/site-packages/oslo_utils/units.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2013 IBM Corp -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Unit constants -""" - -# Binary unit constants. -Ki = 1024 -Mi = 1024 ** 2 -Gi = 1024 ** 3 -Ti = 1024 ** 4 -Pi = 1024 ** 5 -Ei = 1024 ** 6 -Zi = 1024 ** 7 -Yi = 1024 ** 8 - -# Decimal unit constants. -k = 1000 -M = 1000 ** 2 -G = 1000 ** 3 -T = 1000 ** 4 -P = 1000 ** 5 -E = 1000 ** 6 -Z = 1000 ** 7 -Y = 1000 ** 8 diff --git a/awx/lib/site-packages/oslo_utils/uuidutils.py b/awx/lib/site-packages/oslo_utils/uuidutils.py deleted file mode 100644 index 62b0b5f496..0000000000 --- a/awx/lib/site-packages/oslo_utils/uuidutils.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2012 Intel Corporation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -UUID related utilities and helper functions. -""" - -import uuid - - -def generate_uuid(): - return str(uuid.uuid4()) - - -def _format_uuid_string(string): - return (string.replace('urn:', '') - .replace('uuid:', '') - .strip('{}') - .replace('-', '') - .lower()) - - -def is_uuid_like(val): - """Returns validation of a value as a UUID. - - :param val: Value to verify - :type val: string - :returns: bool - """ - try: - return str(uuid.UUID(val)).replace('-', '') == _format_uuid_string(val) - except (TypeError, ValueError, AttributeError): - return False diff --git a/awx/lib/site-packages/pbr/__init__.py b/awx/lib/site-packages/pbr/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/core.py b/awx/lib/site-packages/pbr/core.py deleted file mode 100644 index 0f4b94a1e8..0000000000 --- a/awx/lib/site-packages/pbr/core.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -from distutils import core -from distutils import errors -import logging -import os -import sys -import warnings - -from setuptools import dist - -from pbr import util - - -_saved_core_distribution = core.Distribution - - -def _monkeypatch_distribution(): - core.Distribution = dist._get_unpatched(core.Distribution) - - -def _restore_distribution_monkeypatch(): - core.Distribution = _saved_core_distribution - - -if sys.version_info[0] == 3: - string_type = str - integer_types = (int,) -else: - string_type = basestring - integer_types = (int, long) - - -def pbr(dist, attr, value): - """Implements the actual pbr setup() keyword. When used, this should be - the only keyword in your setup() aside from `setup_requires`. - - If given as a string, the value of pbr is assumed to be the relative path - to the setup.cfg file to use. Otherwise, if it evaluates to true, it - simply assumes that pbr should be used, and the default 'setup.cfg' is - used. - - This works by reading the setup.cfg file, parsing out the supported - metadata and command options, and using them to rebuild the - `DistributionMetadata` object and set the newly added command options. - - The reason for doing things this way is that a custom `Distribution` class - will not play nicely with setup_requires; however, this implementation may - not work well with distributions that do use a `Distribution` subclass. - """ - - try: - _monkeypatch_distribution() - if not value: - return - if isinstance(value, string_type): - path = os.path.abspath(value) - else: - path = os.path.abspath('setup.cfg') - if not os.path.exists(path): - raise errors.DistutilsFileError( - 'The setup.cfg file %s does not exist.' % path) - - # Converts the setup.cfg file to setup() arguments - try: - attrs = util.cfg_to_args(path) - except Exception: - e = sys.exc_info()[1] - # NB: This will output to the console if no explicit logging has - # been setup - but thats fine, this is a fatal distutils error, so - # being pretty isn't the #1 goal.. being diagnosable is. - logging.exception('Error parsing') - raise errors.DistutilsSetupError( - 'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e)) - - # Repeat some of the Distribution initialization code with the newly - # provided attrs - if attrs: - # Skips 'options' and 'licence' support which are rarely used; may - # add back in later if demanded - for key, val in attrs.items(): - if hasattr(dist.metadata, 'set_' + key): - getattr(dist.metadata, 'set_' + key)(val) - elif hasattr(dist.metadata, key): - setattr(dist.metadata, key, val) - elif hasattr(dist, key): - setattr(dist, key, val) - else: - msg = 'Unknown distribution option: %s' % repr(key) - warnings.warn(msg) - - # Re-finalize the underlying Distribution - core.Distribution.finalize_options(dist) - - # This bit comes out of distribute/setuptools - if isinstance(dist.metadata.version, integer_types + (float,)): - # Some people apparently take "version number" too literally :) - dist.metadata.version = str(dist.metadata.version) - - # This bit of hackery is necessary so that the Distribution will ignore - # normally unsupport command options (namely pre-hooks and post-hooks). - # dist.command_options is normally a dict mapping command names to - # dicts of their options. Now it will be a defaultdict that returns - # IgnoreDicts for the each command's options so we can pass through the - # unsupported options - ignore = ['pre_hook.*', 'post_hook.*'] - dist.command_options = util.DefaultGetDict( - lambda: util.IgnoreDict(ignore) - ) - finally: - _restore_distribution_monkeypatch() diff --git a/awx/lib/site-packages/pbr/extra_files.py b/awx/lib/site-packages/pbr/extra_files.py deleted file mode 100644 index a72db0c133..0000000000 --- a/awx/lib/site-packages/pbr/extra_files.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from distutils import errors -import os - -_extra_files = [] - - -def get_extra_files(): - global _extra_files - return _extra_files - - -def set_extra_files(extra_files): - # Let's do a sanity check - for filename in extra_files: - if not os.path.exists(filename): - raise errors.DistutilsFileError( - '%s from the extra_files option in setup.cfg does not ' - 'exist' % filename) - global _extra_files - _extra_files[:] = extra_files[:] diff --git a/awx/lib/site-packages/pbr/find_package.py b/awx/lib/site-packages/pbr/find_package.py deleted file mode 100644 index 2319c060dc..0000000000 --- a/awx/lib/site-packages/pbr/find_package.py +++ /dev/null @@ -1,30 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import setuptools - - -def smart_find_packages(package_list): - """Run find_packages the way we intend.""" - packages = [] - for pkg in package_list.strip().split("\n"): - pkg_path = pkg.replace('.', os.path.sep) - packages.append(pkg) - packages.extend(['%s.%s' % (pkg, f) - for f in setuptools.find_packages(pkg_path)]) - return "\n".join(set(packages)) diff --git a/awx/lib/site-packages/pbr/hooks/__init__.py b/awx/lib/site-packages/pbr/hooks/__init__.py deleted file mode 100644 index b35cd4255a..0000000000 --- a/awx/lib/site-packages/pbr/hooks/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from pbr.hooks import backwards -from pbr.hooks import commands -from pbr.hooks import files -from pbr.hooks import metadata - - -def setup_hook(config): - """Filter config parsed from a setup.cfg to inject our defaults.""" - metadata_config = metadata.MetadataConfig(config) - metadata_config.run() - backwards.BackwardsCompatConfig(config).run() - commands.CommandsConfig(config).run() - files.FilesConfig(config, metadata_config.get_name()).run() diff --git a/awx/lib/site-packages/pbr/hooks/backwards.py b/awx/lib/site-packages/pbr/hooks/backwards.py deleted file mode 100644 index d9183b3fd7..0000000000 --- a/awx/lib/site-packages/pbr/hooks/backwards.py +++ /dev/null @@ -1,34 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from pbr.hooks import base -from pbr import packaging - - -class BackwardsCompatConfig(base.BaseConfig): - - section = 'backwards_compat' - - def hook(self): - self.config['include_package_data'] = 'True' - packaging.append_text_list( - self.config, 'dependency_links', - packaging.parse_dependency_links()) - packaging.append_text_list( - self.config, 'tests_require', - packaging.parse_requirements( - packaging.TEST_REQUIREMENTS_FILES)) diff --git a/awx/lib/site-packages/pbr/hooks/base.py b/awx/lib/site-packages/pbr/hooks/base.py deleted file mode 100644 index 925573a78c..0000000000 --- a/awx/lib/site-packages/pbr/hooks/base.py +++ /dev/null @@ -1,36 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -class BaseConfig(object): - - section = None - - def __init__(self, config): - self._global_config = config - self.config = self._global_config.get(self.section, dict()) - self.pbr_config = config.get('pbr', dict()) - - def run(self): - self.hook() - self.save() - - def hook(self): - pass - - def save(self): - self._global_config[self.section] = self.config diff --git a/awx/lib/site-packages/pbr/hooks/commands.py b/awx/lib/site-packages/pbr/hooks/commands.py deleted file mode 100644 index b4206edd13..0000000000 --- a/awx/lib/site-packages/pbr/hooks/commands.py +++ /dev/null @@ -1,63 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os - -from setuptools.command import easy_install - -from pbr.hooks import base -from pbr import packaging - - -class CommandsConfig(base.BaseConfig): - - section = 'global' - - def __init__(self, config): - super(CommandsConfig, self).__init__(config) - self.commands = self.config.get('commands', "") - - def save(self): - self.config['commands'] = self.commands - super(CommandsConfig, self).save() - - def add_command(self, command): - self.commands = "%s\n%s" % (self.commands, command) - - def hook(self): - self.add_command('pbr.packaging.LocalEggInfo') - self.add_command('pbr.packaging.LocalSDist') - self.add_command('pbr.packaging.LocalInstallScripts') - if os.name != 'nt': - easy_install.get_script_args = packaging.override_get_script_args - - if packaging.have_sphinx(): - self.add_command('pbr.packaging.LocalBuildDoc') - self.add_command('pbr.packaging.LocalBuildLatex') - - if os.path.exists('.testr.conf') and packaging.have_testr(): - # There is a .testr.conf file. We want to use it. - self.add_command('pbr.packaging.TestrTest') - elif self.config.get('nosetests', False) and packaging.have_nose(): - # We seem to still have nose configured - self.add_command('pbr.packaging.NoseTest') - - use_egg = packaging.get_boolean_option( - self.pbr_config, 'use-egg', 'PBR_USE_EGG') - # We always want non-egg install unless explicitly requested - if 'manpages' in self.pbr_config or not use_egg: - self.add_command('pbr.packaging.LocalInstall') diff --git a/awx/lib/site-packages/pbr/hooks/files.py b/awx/lib/site-packages/pbr/hooks/files.py deleted file mode 100644 index ba24aace99..0000000000 --- a/awx/lib/site-packages/pbr/hooks/files.py +++ /dev/null @@ -1,101 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import sys - -from pbr import find_package -from pbr.hooks import base - - -def get_manpath(): - manpath = 'share/man' - if os.path.exists(os.path.join(sys.prefix, 'man')): - # This works around a bug with install where it expects every node - # in the relative data directory to be an actual directory, since at - # least Debian derivatives (and probably other platforms as well) - # like to symlink Unixish /usr/local/man to /usr/local/share/man. - manpath = 'man' - return manpath - - -def get_man_section(section): - return os.path.join(get_manpath(), 'man%s' % section) - - -class FilesConfig(base.BaseConfig): - - section = 'files' - - def __init__(self, config, name): - super(FilesConfig, self).__init__(config) - self.name = name - self.data_files = self.config.get('data_files', '') - - def save(self): - self.config['data_files'] = self.data_files - super(FilesConfig, self).save() - - def expand_globs(self): - finished = [] - for line in self.data_files.split("\n"): - if line.rstrip().endswith('*') and '=' in line: - (target, source_glob) = line.split('=') - source_prefix = source_glob.strip()[:-1] - target = target.strip() - if not target.endswith(os.path.sep): - target += os.path.sep - for (dirpath, dirnames, fnames) in os.walk(source_prefix): - finished.append( - "%s = " % dirpath.replace(source_prefix, target)) - finished.extend( - [" %s" % os.path.join(dirpath, f) for f in fnames]) - else: - finished.append(line) - - self.data_files = "\n".join(finished) - - def add_man_path(self, man_path): - self.data_files = "%s\n%s =" % (self.data_files, man_path) - - def add_man_page(self, man_page): - self.data_files = "%s\n %s" % (self.data_files, man_page) - - def get_man_sections(self): - man_sections = dict() - manpages = self.pbr_config['manpages'] - for manpage in manpages.split(): - section_number = manpage.strip()[-1] - section = man_sections.get(section_number, list()) - section.append(manpage.strip()) - man_sections[section_number] = section - return man_sections - - def hook(self): - package = self.config.get('packages', self.name).strip() - if os.path.isdir(package): - self.config['packages'] = find_package.smart_find_packages(package) - - self.expand_globs() - - if 'manpages' in self.pbr_config: - man_sections = self.get_man_sections() - for (section, pages) in man_sections.items(): - manpath = get_man_section(section) - self.add_man_path(manpath) - for page in pages: - self.add_man_page(page) diff --git a/awx/lib/site-packages/pbr/hooks/metadata.py b/awx/lib/site-packages/pbr/hooks/metadata.py deleted file mode 100644 index 687e14901b..0000000000 --- a/awx/lib/site-packages/pbr/hooks/metadata.py +++ /dev/null @@ -1,34 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from pbr.hooks import base -from pbr import packaging - - -class MetadataConfig(base.BaseConfig): - - section = 'metadata' - - def hook(self): - self.config['version'] = packaging.get_version( - self.config['name'], self.config.get('version', None)) - packaging.append_text_list( - self.config, 'requires_dist', - packaging.parse_requirements()) - - def get_name(self): - return self.config['name'] diff --git a/awx/lib/site-packages/pbr/packaging.py b/awx/lib/site-packages/pbr/packaging.py deleted file mode 100644 index 471ed85683..0000000000 --- a/awx/lib/site-packages/pbr/packaging.py +++ /dev/null @@ -1,872 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities with minimum-depends for use in setup.py -""" - -from __future__ import unicode_literals - -import email -import io -import os -import re -import subprocess -import sys - -from distutils.command import install as du_install -import distutils.errors -from distutils import log -import pkg_resources -from setuptools.command import easy_install -from setuptools.command import egg_info -from setuptools.command import install -from setuptools.command import install_scripts -from setuptools.command import sdist - -try: - import cStringIO -except ImportError: - import io as cStringIO - -from pbr import extra_files - -TRUE_VALUES = ('true', '1', 'yes') -REQUIREMENTS_FILES = ('requirements.txt', 'tools/pip-requires') -TEST_REQUIREMENTS_FILES = ('test-requirements.txt', 'tools/test-requires') - - -def get_requirements_files(): - files = os.environ.get("PBR_REQUIREMENTS_FILES") - if files: - return tuple(f.strip() for f in files.split(',')) - # Returns a list composed of: - # - REQUIREMENTS_FILES with -py2 or -py3 in the name - # (e.g. requirements-py3.txt) - # - REQUIREMENTS_FILES - return (list(map(('-py' + str(sys.version_info[0])).join, - map(os.path.splitext, REQUIREMENTS_FILES))) - + list(REQUIREMENTS_FILES)) - - -def append_text_list(config, key, text_list): - """Append a \n separated list to possibly existing value.""" - new_value = [] - current_value = config.get(key, "") - if current_value: - new_value.append(current_value) - new_value.extend(text_list) - config[key] = '\n'.join(new_value) - - -def _pip_install(links, requires, root=None, option_dict=dict()): - if get_boolean_option( - option_dict, 'skip_pip_install', 'SKIP_PIP_INSTALL'): - return - cmd = [sys.executable, '-m', 'pip.__init__', 'install'] - if root: - cmd.append("--root=%s" % root) - for link in links: - cmd.append("-f") - cmd.append(link) - - # NOTE(ociuhandu): popen on Windows does not accept unicode strings - _run_shell_command( - cmd + requires, - throw_on_error=True, buffer=False, env=dict(PIP_USE_WHEEL=b"true")) - - -def _any_existing(file_list): - return [f for f in file_list if os.path.exists(f)] - - -# Get requirements from the first file that exists -def get_reqs_from_files(requirements_files): - for requirements_file in _any_existing(requirements_files): - with open(requirements_file, 'r') as fil: - return fil.read().split('\n') - return [] - - -def parse_requirements(requirements_files=None): - - if requirements_files is None: - requirements_files = get_requirements_files() - - def egg_fragment(match): - # take a versioned egg fragment and return a - # versioned package requirement e.g. - # nova-1.2.3 becomes nova>=1.2.3 - return re.sub(r'([\w.]+)-([\w.-]+)', - r'\1>=\2', - match.group(1)) - - requirements = [] - for line in get_reqs_from_files(requirements_files): - # Ignore comments - if (not line.strip()) or line.startswith('#'): - continue - - # Handle nested requirements files such as: - # -r other-requirements.txt - if line.startswith('-r'): - req_file = line.partition(' ')[2] - requirements += parse_requirements([req_file]) - continue - - try: - project_name = pkg_resources.Requirement.parse(line).project_name - except ValueError: - project_name = None - - # For the requirements list, we need to inject only the portion - # after egg= so that distutils knows the package it's looking for - # such as: - # -e git://github.com/openstack/nova/master#egg=nova - # -e git://github.com/openstack/nova/master#egg=nova-1.2.3 - if re.match(r'\s*-e\s+', line): - line = re.sub(r'\s*-e\s+.*#egg=(.*)$', egg_fragment, line) - # such as: - # http://github.com/openstack/nova/zipball/master#egg=nova - # http://github.com/openstack/nova/zipball/master#egg=nova-1.2.3 - elif re.match(r'\s*https?:', line): - line = re.sub(r'\s*https?:.*#egg=(.*)$', egg_fragment, line) - # -f lines are for index locations, and don't get used here - elif re.match(r'\s*-f\s+', line): - line = None - reason = 'Index Location' - - if line is not None: - requirements.append(line) - else: - log.info( - '[pbr] Excluding %s: %s' % (project_name, reason)) - - return requirements - - -def parse_dependency_links(requirements_files=None): - if requirements_files is None: - requirements_files = get_requirements_files() - dependency_links = [] - # dependency_links inject alternate locations to find packages listed - # in requirements - for line in get_reqs_from_files(requirements_files): - # skip comments and blank lines - if re.match(r'(\s*#)|(\s*$)', line): - continue - # lines with -e or -f need the whole line, minus the flag - if re.match(r'\s*-[ef]\s+', line): - dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line)) - # lines that are only urls can go in unmolested - elif re.match(r'\s*https?:', line): - dependency_links.append(line) - return dependency_links - - -def _run_git_command(cmd, git_dir, **kwargs): - if not isinstance(cmd, (list, tuple)): - cmd = [cmd] - return _run_shell_command( - ['git', '--git-dir=%s' % git_dir] + cmd, **kwargs) - - -def _run_shell_command(cmd, throw_on_error=False, buffer=True, env=None): - if buffer: - out_location = subprocess.PIPE - err_location = subprocess.PIPE - else: - out_location = None - err_location = None - - newenv = os.environ.copy() - if env: - newenv.update(env) - - output = subprocess.Popen(cmd, - stdout=out_location, - stderr=err_location, - env=newenv) - out = output.communicate() - if output.returncode and throw_on_error: - raise distutils.errors.DistutilsError( - "%s returned %d" % (cmd, output.returncode)) - if len(out) == 0 or not out[0] or not out[0].strip(): - return '' - return out[0].strip().decode('utf-8') - - -def _get_git_directory(): - return _run_shell_command(['git', 'rev-parse', '--git-dir']) - - -def _git_is_installed(): - try: - # We cannot use 'which git' as it may not be available - # in some distributions, So just try 'git --version' - # to see if we run into trouble - _run_shell_command(['git', '--version']) - except OSError: - return False - return True - - -def _get_highest_tag(tags): - """Find the highest tag from a list. - - Pass in a list of tag strings and this will return the highest - (latest) as sorted by the pkg_resources version parser. - """ - return max(tags, key=pkg_resources.parse_version) - - -def get_boolean_option(option_dict, option_name, env_name): - return ((option_name in option_dict - and option_dict[option_name][1].lower() in TRUE_VALUES) or - str(os.getenv(env_name)).lower() in TRUE_VALUES) - - -def write_git_changelog(git_dir=None, dest_dir=os.path.curdir, - option_dict=dict()): - """Write a changelog based on the git changelog.""" - should_skip = get_boolean_option(option_dict, 'skip_changelog', - 'SKIP_WRITE_GIT_CHANGELOG') - if should_skip: - return - - new_changelog = os.path.join(dest_dir, 'ChangeLog') - # If there's already a ChangeLog and it's not writable, just use it - if (os.path.exists(new_changelog) - and not os.access(new_changelog, os.W_OK)): - return - log.info('[pbr] Writing ChangeLog') - if git_dir is None: - git_dir = _get_git_directory() - if not git_dir: - return - - log_cmd = ['log', '--oneline', '--decorate'] - changelog = _run_git_command(log_cmd, git_dir) - first_line = True - with io.open(new_changelog, "w", - encoding="utf-8") as changelog_file: - changelog_file.write("CHANGES\n=======\n\n") - for line in changelog.split('\n'): - line_parts = line.split() - if len(line_parts) < 2: - continue - # Tags are in a list contained in ()'s. If a commit - # subject that is tagged happens to have ()'s in it - # this will fail - if line_parts[1].startswith('(') and ')' in line: - msg = line.split(')')[1].strip() - else: - msg = " ".join(line_parts[1:]) - - if "tag:" in line: - tags = [ - tag.split(",")[0] - for tag in line.split(")")[0].split("tag: ")[1:]] - tag = _get_highest_tag(tags) - - underline = len(tag) * '-' - if not first_line: - changelog_file.write('\n') - changelog_file.write( - ("%(tag)s\n%(underline)s\n\n" % - dict(tag=tag, - underline=underline))) - - if not msg.startswith("Merge "): - if msg.endswith("."): - msg = msg[:-1] - changelog_file.write( - ("* %(msg)s\n" % dict(msg=msg))) - first_line = False - - -def generate_authors(git_dir=None, dest_dir='.', option_dict=dict()): - """Create AUTHORS file using git commits.""" - should_skip = get_boolean_option(option_dict, 'skip_authors', - 'SKIP_GENERATE_AUTHORS') - if should_skip: - return - - old_authors = os.path.join(dest_dir, 'AUTHORS.in') - new_authors = os.path.join(dest_dir, 'AUTHORS') - # If there's already an AUTHORS file and it's not writable, just use it - if (os.path.exists(new_authors) - and not os.access(new_authors, os.W_OK)): - return - log.info('[pbr] Generating AUTHORS') - ignore_emails = '(jenkins@review|infra@lists|jenkins@openstack)' - if git_dir is None: - git_dir = _get_git_directory() - if git_dir: - authors = [] - - # don't include jenkins email address in AUTHORS file - git_log_cmd = ['log', '--format=%aN <%aE>'] - authors += _run_git_command(git_log_cmd, git_dir).split('\n') - authors = [a for a in authors if not re.search(ignore_emails, a)] - - # get all co-authors from commit messages - co_authors_out = _run_git_command('log', git_dir) - co_authors = re.findall('Co-authored-by:.+', co_authors_out, - re.MULTILINE) - co_authors = [signed.split(":", 1)[1].strip() - for signed in co_authors if signed] - - authors += co_authors - authors = sorted(set(authors)) - - with open(new_authors, 'wb') as new_authors_fh: - if os.path.exists(old_authors): - with open(old_authors, "rb") as old_authors_fh: - new_authors_fh.write(old_authors_fh.read()) - new_authors_fh.write(('\n'.join(authors) + '\n') - .encode('utf-8')) - - -def _find_git_files(dirname='', git_dir=None): - """Behave like a file finder entrypoint plugin. - - We don't actually use the entrypoints system for this because it runs - at absurd times. We only want to do this when we are building an sdist. - """ - file_list = [] - if git_dir is None and _git_is_installed(): - git_dir = _get_git_directory() - if git_dir: - log.info("[pbr] In git context, generating filelist from git") - file_list = _run_git_command(['ls-files', '-z'], git_dir) - file_list = file_list.split(b'\x00'.decode('utf-8')) - return [f for f in file_list if f] - - -_rst_template = """%(heading)s -%(underline)s - -.. automodule:: %(module)s - :members: - :undoc-members: - :show-inheritance: -""" - - -def _find_modules(arg, dirname, files): - for filename in files: - if filename.endswith('.py') and filename != '__init__.py': - arg["%s.%s" % (dirname.replace('/', '.'), - filename[:-3])] = True - - -class LocalInstall(install.install): - """Runs python setup.py install in a sensible manner. - - Force a non-egg installed in the manner of - single-version-externally-managed, which allows us to install manpages - and config files. - - Because non-egg installs bypass the depend processing machinery, we - need to do our own. Because easy_install is evil, just use pip to - process our requirements files directly, which means we don't have to - do crazy extra processing. - - Bypass installation if --single-version-externally-managed is given, - so that behavior for packagers remains the same. - """ - - command_name = 'install' - - def run(self): - option_dict = self.distribution.get_option_dict('pbr') - if (not self.single_version_externally_managed - and self.distribution.install_requires): - _pip_install( - self.distribution.dependency_links, - self.distribution.install_requires, self.root, - option_dict=option_dict) - - return du_install.install.run(self) - - -def _newer_requires_files(egg_info_dir): - """Check to see if any of the requires files are newer than egg-info.""" - for target, sources in (('requires.txt', get_requirements_files()), - ('test-requires.txt', TEST_REQUIREMENTS_FILES)): - target_path = os.path.join(egg_info_dir, target) - for src in _any_existing(sources): - if (not os.path.exists(target_path) or - os.path.getmtime(target_path) - < os.path.getmtime(src)): - return True - return False - - -def _copy_test_requires_to(egg_info_dir): - """Copy the requirements file to egg-info/test-requires.txt.""" - with open(os.path.join(egg_info_dir, 'test-requires.txt'), 'w') as dest: - for source in _any_existing(TEST_REQUIREMENTS_FILES): - dest.write(open(source, 'r').read().rstrip('\n') + '\n') - - -class _PipInstallTestRequires(object): - """Mixin class to install test-requirements.txt before running tests.""" - - def install_test_requirements(self): - - links = parse_dependency_links(TEST_REQUIREMENTS_FILES) - if self.distribution.tests_require: - option_dict = self.distribution.get_option_dict('pbr') - _pip_install( - links, self.distribution.tests_require, - option_dict=option_dict) - - def pre_run(self): - self.egg_name = pkg_resources.safe_name(self.distribution.get_name()) - self.egg_info = "%s.egg-info" % pkg_resources.to_filename( - self.egg_name) - if (not os.path.exists(self.egg_info) or - _newer_requires_files(self.egg_info)): - ei_cmd = self.get_finalized_command('egg_info') - ei_cmd.run() - self.install_test_requirements() - _copy_test_requires_to(self.egg_info) - -try: - from pbr import testr_command - - class TestrTest(testr_command.Testr, _PipInstallTestRequires): - """Make setup.py test do the right thing.""" - - command_name = 'test' - - def run(self): - self.pre_run() - # Can't use super - base class old-style class - testr_command.Testr.run(self) - - _have_testr = True - -except ImportError: - _have_testr = False - - -def have_testr(): - return _have_testr - -try: - from nose import commands - - class NoseTest(commands.nosetests, _PipInstallTestRequires): - """Fallback test runner if testr is a no-go.""" - - command_name = 'test' - - def run(self): - self.pre_run() - # Can't use super - base class old-style class - commands.nosetests.run(self) - - _have_nose = True - -except ImportError: - _have_nose = False - - -def have_nose(): - return _have_nose - - -_script_text = """# PBR Generated from %(group)r - -import sys - -from %(module_name)s import %(import_target)s - - -if __name__ == "__main__": - sys.exit(%(invoke_target)s()) -""" - - -def override_get_script_args( - dist, executable=os.path.normpath(sys.executable), is_wininst=False): - """Override entrypoints console_script.""" - header = easy_install.get_script_header("", executable, is_wininst) - for group in 'console_scripts', 'gui_scripts': - for name, ep in dist.get_entry_map(group).items(): - if not ep.attrs or len(ep.attrs) > 2: - raise ValueError("Script targets must be of the form " - "'func' or 'Class.class_method'.") - script_text = _script_text % dict( - group=group, - module_name=ep.module_name, - import_target=ep.attrs[0], - invoke_target='.'.join(ep.attrs), - ) - yield (name, header + script_text) - - -class LocalInstallScripts(install_scripts.install_scripts): - """Intercepts console scripts entry_points.""" - command_name = 'install_scripts' - - def run(self): - if os.name != 'nt': - get_script_args = override_get_script_args - else: - get_script_args = easy_install.get_script_args - - import distutils.command.install_scripts - - self.run_command("egg_info") - if self.distribution.scripts: - # run first to set up self.outfiles - distutils.command.install_scripts.install_scripts.run(self) - else: - self.outfiles = [] - if self.no_ep: - # don't install entry point scripts into .egg file! - return - - ei_cmd = self.get_finalized_command("egg_info") - dist = pkg_resources.Distribution( - ei_cmd.egg_base, - pkg_resources.PathMetadata(ei_cmd.egg_base, ei_cmd.egg_info), - ei_cmd.egg_name, ei_cmd.egg_version, - ) - bs_cmd = self.get_finalized_command('build_scripts') - executable = getattr( - bs_cmd, 'executable', easy_install.sys_executable) - is_wininst = getattr( - self.get_finalized_command("bdist_wininst"), '_is_running', False - ) - for args in get_script_args(dist, executable, is_wininst): - self.write_script(*args) - - -class LocalManifestMaker(egg_info.manifest_maker): - """Add any files that are in git and some standard sensible files.""" - - def _add_pbr_defaults(self): - for template_line in [ - 'include AUTHORS', - 'include ChangeLog', - 'exclude .gitignore', - 'exclude .gitreview', - 'global-exclude *.pyc' - ]: - self.filelist.process_template_line(template_line) - - def add_defaults(self): - option_dict = self.distribution.get_option_dict('pbr') - - sdist.sdist.add_defaults(self) - self.filelist.append(self.template) - self.filelist.append(self.manifest) - self.filelist.extend(extra_files.get_extra_files()) - should_skip = get_boolean_option(option_dict, 'skip_git_sdist', - 'SKIP_GIT_SDIST') - if not should_skip: - rcfiles = _find_git_files() - if rcfiles: - self.filelist.extend(rcfiles) - elif os.path.exists(self.manifest): - self.read_manifest() - ei_cmd = self.get_finalized_command('egg_info') - self._add_pbr_defaults() - self.filelist.include_pattern("*", prefix=ei_cmd.egg_info) - - -class LocalEggInfo(egg_info.egg_info): - """Override the egg_info command to regenerate SOURCES.txt sensibly.""" - - command_name = 'egg_info' - - def find_sources(self): - """Generate SOURCES.txt only if there isn't one already. - - If we are in an sdist command, then we always want to update - SOURCES.txt. If we are not in an sdist command, then it doesn't - matter one flip, and is actually destructive. - """ - manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") - if not os.path.exists(manifest_filename) or 'sdist' in sys.argv: - log.info("[pbr] Processing SOURCES.txt") - mm = LocalManifestMaker(self.distribution) - mm.manifest = manifest_filename - mm.run() - self.filelist = mm.filelist - else: - log.info("[pbr] Reusing existing SOURCES.txt") - self.filelist = egg_info.FileList() - for entry in open(manifest_filename, 'r').read().split('\n'): - self.filelist.append(entry) - - -class LocalSDist(sdist.sdist): - """Builds the ChangeLog and Authors files from VC first.""" - - command_name = 'sdist' - - def run(self): - option_dict = self.distribution.get_option_dict('pbr') - write_git_changelog(option_dict=option_dict) - generate_authors(option_dict=option_dict) - # sdist.sdist is an old style class, can't use super() - sdist.sdist.run(self) - -try: - from sphinx import apidoc - from sphinx import application - from sphinx import config - from sphinx import setup_command - - class LocalBuildDoc(setup_command.BuildDoc): - - command_name = 'build_sphinx' - builders = ['html', 'man'] - - def _get_source_dir(self): - option_dict = self.distribution.get_option_dict('build_sphinx') - if 'source_dir' in option_dict: - source_dir = os.path.join(option_dict['source_dir'][1], 'api') - else: - source_dir = 'doc/source/api' - if not os.path.exists(source_dir): - os.makedirs(source_dir) - return source_dir - - def generate_autoindex(self): - log.info("[pbr] Autodocumenting from %s" - % os.path.abspath(os.curdir)) - modules = {} - source_dir = self._get_source_dir() - for pkg in self.distribution.packages: - if '.' not in pkg: - for dirpath, dirnames, files in os.walk(pkg): - _find_modules(modules, dirpath, files) - module_list = list(modules.keys()) - module_list.sort() - autoindex_filename = os.path.join(source_dir, 'autoindex.rst') - with open(autoindex_filename, 'w') as autoindex: - autoindex.write(""".. toctree:: - :maxdepth: 1 - -""") - for module in module_list: - output_filename = os.path.join(source_dir, - "%s.rst" % module) - heading = "The :mod:`%s` Module" % module - underline = "=" * len(heading) - values = dict(module=module, heading=heading, - underline=underline) - - log.info("[pbr] Generating %s" - % output_filename) - with open(output_filename, 'w') as output_file: - output_file.write(_rst_template % values) - autoindex.write(" %s.rst\n" % module) - - def _sphinx_tree(self): - source_dir = self._get_source_dir() - apidoc.main(['apidoc', '.', '-H', 'Modules', '-o', source_dir]) - - def _sphinx_run(self): - if not self.verbose: - status_stream = cStringIO.StringIO() - else: - status_stream = sys.stdout - confoverrides = {} - if self.version: - confoverrides['version'] = self.version - if self.release: - confoverrides['release'] = self.release - if self.today: - confoverrides['today'] = self.today - sphinx_config = config.Config(self.config_dir, 'conf.py', {}, []) - sphinx_config.init_values() - if self.builder == 'man' and len(sphinx_config.man_pages) == 0: - return - app = application.Sphinx( - self.source_dir, self.config_dir, - self.builder_target_dir, self.doctree_dir, - self.builder, confoverrides, status_stream, - freshenv=self.fresh_env, warningiserror=True) - - try: - app.build(force_all=self.all_files) - except Exception as err: - from docutils import utils - if isinstance(err, utils.SystemMessage): - sys.stder.write('reST markup error:\n') - sys.stderr.write(err.args[0].encode('ascii', - 'backslashreplace')) - sys.stderr.write('\n') - else: - raise - - if self.link_index: - src = app.config.master_doc + app.builder.out_suffix - dst = app.builder.get_outfilename('index') - os.symlink(src, dst) - - def run(self): - option_dict = self.distribution.get_option_dict('pbr') - tree_index = get_boolean_option(option_dict, - 'autodoc_tree_index_modules', - 'AUTODOC_TREE_INDEX_MODULES') - auto_index = get_boolean_option(option_dict, - 'autodoc_index_modules', - 'AUTODOC_INDEX_MODULES') - if not os.getenv('SPHINX_DEBUG'): - #NOTE(afazekas): These options can be used together, - # but they do a very similar thing in a difffernet way - if tree_index: - self._sphinx_tree() - if auto_index: - self.generate_autoindex() - - for builder in self.builders: - self.builder = builder - self.finalize_options() - self.project = self.distribution.get_name() - self.version = self.distribution.get_version() - self.release = self.distribution.get_version() - if 'warnerrors' in option_dict: - self._sphinx_run() - else: - setup_command.BuildDoc.run(self) - - def finalize_options(self): - # Not a new style class, super keyword does not work. - setup_command.BuildDoc.finalize_options(self) - # Allow builders to be configurable - as a comma separated list. - if not isinstance(self.builders, list) and self.builders: - self.builders = self.builders.split(',') - - class LocalBuildLatex(LocalBuildDoc): - builders = ['latex'] - command_name = 'build_sphinx_latex' - - _have_sphinx = True - -except ImportError: - _have_sphinx = False - - -def have_sphinx(): - return _have_sphinx - - -def _get_revno(git_dir): - """Return the number of commits since the most recent tag. - - We use git-describe to find this out, but if there are no - tags then we fall back to counting commits since the beginning - of time. - """ - describe = _run_git_command(['describe', '--always'], git_dir) - if "-" in describe: - return describe.rsplit("-", 2)[-2] - - # no tags found - revlist = _run_git_command( - ['rev-list', '--abbrev-commit', 'HEAD'], git_dir) - return len(revlist.splitlines()) - - -def _get_version_from_git(pre_version): - """Return a version which is equal to the tag that's on the current - revision if there is one, or tag plus number of additional revisions - if the current revision has no tag. - """ - - git_dir = _get_git_directory() - if git_dir and _git_is_installed(): - if pre_version: - try: - return _run_git_command( - ['describe', '--exact-match'], git_dir, - throw_on_error=True).replace('-', '.') - except Exception: - sha = _run_git_command( - ['log', '-n1', '--pretty=format:%h'], git_dir) - return "%s.dev%s.g%s" % (pre_version, _get_revno(git_dir), sha) - else: - return _run_git_command( - ['describe', '--always'], git_dir).replace('-', '.') - # If we don't know the version, return an empty string so at least - # the downstream users of the value always have the same type of - # object to work with. - try: - return unicode() - except NameError: - return '' - - -def _get_version_from_pkg_info(package_name): - """Get the version from PKG-INFO file if we can.""" - try: - pkg_info_file = open('PKG-INFO', 'r') - except (IOError, OSError): - return None - try: - pkg_info = email.message_from_file(pkg_info_file) - except email.MessageError: - return None - # Check to make sure we're in our own dir - if pkg_info.get('Name', None) != package_name: - return None - return pkg_info.get('Version', None) - - -def get_version(package_name, pre_version=None): - """Get the version of the project. First, try getting it from PKG-INFO, if - it exists. If it does, that means we're in a distribution tarball or that - install has happened. Otherwise, if there is no PKG-INFO file, pull the - version from git. - - We do not support setup.py version sanity in git archive tarballs, nor do - we support packagers directly sucking our git repo into theirs. We expect - that a source tarball be made from our git repo - or that if someone wants - to make a source tarball from a fork of our repo with additional tags in it - that they understand and desire the results of doing that. - """ - version = os.environ.get( - "PBR_VERSION", - os.environ.get("OSLO_PACKAGE_VERSION", None)) - if version: - return version - version = _get_version_from_pkg_info(package_name) - if version: - return version - version = _get_version_from_git(pre_version) - # Handle http://bugs.python.org/issue11638 - # version will either be an empty unicode string or a valid - # unicode version string, but either way it's unicode and needs to - # be encoded. - if sys.version_info[0] == 2: - version = version.encode('utf-8') - if version: - return version - raise Exception("Versioning for this project requires either an sdist" - " tarball, or access to an upstream git repository." - " Are you sure that git is installed?") diff --git a/awx/lib/site-packages/pbr/testr_command.py b/awx/lib/site-packages/pbr/testr_command.py deleted file mode 100644 index 34b02ed556..0000000000 --- a/awx/lib/site-packages/pbr/testr_command.py +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (c) 2013 Testrepository Contributors -# -# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause -# license at the users choice. A copy of both licenses are available in the -# project source as Apache-2.0 and BSD. You may not use this file except in -# compliance with one of these two licences. -# -# Unless required by applicable law or agreed to in writing, software -# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# license you chose for the specific language governing permissions and -# limitations under that license. - -"""setuptools/distutils commands to run testr via setup.py - -Currently provides 'testr' which runs tests using testr. You can pass ---coverage which will also export PYTHON='coverage run --source ' -and automatically combine the coverage from each testr backend test runner -after the run completes. - -To use, just use setuptools/distribute and depend on testr, and it should be -picked up automatically (as the commands are exported in the testrepository -package metadata. -""" - -from distutils import cmd -import distutils.errors -import logging -import os -import sys - -from testrepository import commands - -logger = logging.getLogger(__name__) - - -class Testr(cmd.Command): - - description = "Run unit tests using testr" - - user_options = [ - ('coverage', None, "Replace PYTHON with coverage and merge coverage " - "from each testr worker."), - ('testr-args=', 't', "Run 'testr' with these args"), - ('omit=', 'o', "Files to omit from coverage calculations"), - ('coverage-package-name=', None, "Use this name for coverage package"), - ('slowest', None, "Show slowest test times after tests complete."), - ('no-parallel', None, "Run testr serially"), - ('log-level=', 'l', "Log level (default: info)"), - ] - - boolean_options = ['coverage', 'slowest', 'no_parallel'] - - def _run_testr(self, *args): - logger.debug("_run_testr called with args = %r", args) - return commands.run_argv([sys.argv[0]] + list(args), - sys.stdin, sys.stdout, sys.stderr) - - def initialize_options(self): - self.testr_args = None - self.coverage = None - self.omit = "" - self.slowest = None - self.coverage_package_name = None - self.no_parallel = None - self.log_level = 'info' - - def finalize_options(self): - self.log_level = getattr( - logging, - self.log_level.upper(), - logging.INFO) - logging.basicConfig(level=self.log_level) - logger.debug("finalize_options called") - if self.testr_args is None: - self.testr_args = [] - else: - self.testr_args = self.testr_args.split() - if self.omit: - self.omit = "--omit=%s" % self.omit - logger.debug("finalize_options: self.__dict__ = %r", self.__dict__) - - def run(self): - """Set up testr repo, then run testr""" - logger.debug("run called") - if not os.path.isdir(".testrepository"): - self._run_testr("init") - - if self.coverage: - self._coverage_before() - if not self.no_parallel: - testr_ret = self._run_testr("run", "--parallel", *self.testr_args) - else: - testr_ret = self._run_testr("run", *self.testr_args) - if testr_ret: - raise distutils.errors.DistutilsError( - "testr failed (%d)" % testr_ret) - if self.slowest: - print("Slowest Tests") - self._run_testr("slowest") - if self.coverage: - self._coverage_after() - - def _coverage_before(self): - logger.debug("_coverage_before called") - package = self.distribution.get_name() - if package.startswith('python-'): - package = package[7:] - - # Use this as coverage package name - if self.coverage_package_name: - package = self.coverage_package_name - options = "--source %s --parallel-mode" % package - os.environ['PYTHON'] = ("coverage run %s" % options) - logger.debug("os.environ['PYTHON'] = %r", os.environ['PYTHON']) - - def _coverage_after(self): - logger.debug("_coverage_after called") - os.system("coverage combine") - os.system("coverage html -d ./cover %s" % self.omit) diff --git a/awx/lib/site-packages/pbr/tests/__init__.py b/awx/lib/site-packages/pbr/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/base.py b/awx/lib/site-packages/pbr/tests/base.py deleted file mode 100644 index ce20de1bdf..0000000000 --- a/awx/lib/site-packages/pbr/tests/base.py +++ /dev/null @@ -1,151 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010-2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -"""Common utilities used in testing""" - -import os -import shutil -import subprocess -import sys - -import fixtures -import testresources -import testtools - -from pbr import packaging - - -class DiveDir(fixtures.Fixture): - """Dive into given directory and return back on cleanup. - - :ivar path: The target directory. - """ - - def __init__(self, path): - self.path = path - - def setUp(self): - super(DiveDir, self).setUp() - self.addCleanup(os.chdir, os.getcwd()) - os.chdir(self.path) - - -class BaseTestCase(testtools.TestCase, testresources.ResourcedTestCase): - - def setUp(self): - super(BaseTestCase, self).setUp() - test_timeout = os.environ.get('OS_TEST_TIMEOUT', 30) - try: - test_timeout = int(test_timeout) - except ValueError: - # If timeout value is invalid, fail hard. - print("OS_TEST_TIMEOUT set to invalid value" - " defaulting to no timeout") - test_timeout = 0 - if test_timeout > 0: - self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) - - if os.environ.get('OS_STDOUT_CAPTURE') in packaging.TRUE_VALUES: - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if os.environ.get('OS_STDERR_CAPTURE') in packaging.TRUE_VALUES: - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - self.log_fixture = self.useFixture( - fixtures.FakeLogger('pbr')) - - # Older git does not have config --local, so create a temporary home - # directory to permit using git config --global without stepping on - # developer configuration. - self.useFixture(fixtures.TempHomeDir()) - self.useFixture(fixtures.NestedTempfile()) - self.useFixture(fixtures.FakeLogger()) - self.useFixture(fixtures.EnvironmentVariable('PBR_VERSION', '0.0')) - - self.temp_dir = self.useFixture(fixtures.TempDir()).path - self.package_dir = os.path.join(self.temp_dir, 'testpackage') - shutil.copytree(os.path.join(os.path.dirname(__file__), 'testpackage'), - self.package_dir) - self.addCleanup(os.chdir, os.getcwd()) - os.chdir(self.package_dir) - self.addCleanup(self._discard_testpackage) - - def _discard_testpackage(self): - # Remove pbr.testpackage from sys.modules so that it can be freshly - # re-imported by the next test - for k in list(sys.modules): - if (k == 'pbr_testpackage' or - k.startswith('pbr_testpackage.')): - del sys.modules[k] - - def run_setup(self, *args, **kwargs): - return self._run_cmd(sys.executable, ('setup.py',) + args, **kwargs) - - def _run_cmd(self, cmd, args=[], allow_fail=True, cwd=None): - """Run a command in the root of the test working copy. - - Runs a command, with the given argument list, in the root of the test - working copy--returns the stdout and stderr streams and the exit code - from the subprocess. - - :param cwd: If falsy run within the test package dir, otherwise run - within the named path. - """ - cwd = cwd or self.package_dir - result = _run_cmd([cmd] + list(args), cwd=cwd) - if result[2] and not allow_fail: - raise Exception("Command failed retcode=%s" % result[2]) - return result - - -def _run_cmd(args, cwd): - """Run the command args in cwd. - - :param args: The command to run e.g. ['git', 'status'] - :param cwd: The directory to run the comamnd in. - :return: ((stdout, stderr), returncode) - """ - p = subprocess.Popen( - args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) - streams = tuple(s.decode('latin1').strip() for s in p.communicate()) - for content in streams: - print(content) - return (streams) + (p.returncode,) diff --git a/awx/lib/site-packages/pbr/tests/test_commands.py b/awx/lib/site-packages/pbr/tests/test_commands.py deleted file mode 100644 index c73a9f3542..0000000000 --- a/awx/lib/site-packages/pbr/tests/test_commands.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -from testtools import content - -from pbr.tests import base - - -class TestCommands(base.BaseTestCase): - def test_custom_build_py_command(self): - """Test custom build_py command. - - Test that a custom subclass of the build_py command runs when listed in - the commands [global] option, rather than the normal build command. - """ - - stdout, stderr, return_code = self.run_setup('build_py') - self.addDetail('stdout', content.text_content(stdout)) - self.addDetail('stderr', content.text_content(stderr)) - self.assertIn('Running custom build_py command.', stdout) - self.assertEqual(return_code, 0) diff --git a/awx/lib/site-packages/pbr/tests/test_core.py b/awx/lib/site-packages/pbr/tests/test_core.py deleted file mode 100644 index 1d1272a3ec..0000000000 --- a/awx/lib/site-packages/pbr/tests/test_core.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -import glob -import os -import tarfile - -import fixtures - -from pbr.tests import base - - -class TestCore(base.BaseTestCase): - - cmd_names = ('pbr_test_cmd', 'pbr_test_cmd_with_class') - - def check_script_install(self, install_stdout): - for cmd_name in self.cmd_names: - install_txt = 'Installing %s script to %s' % (cmd_name, - self.temp_dir) - self.assertIn(install_txt, install_stdout) - - cmd_filename = os.path.join(self.temp_dir, cmd_name) - - script_txt = open(cmd_filename, 'r').read() - self.assertNotIn('pkg_resources', script_txt) - - stdout, _, return_code = self._run_cmd(cmd_filename) - self.assertIn("PBR", stdout) - - def test_setup_py_keywords(self): - """setup.py --keywords. - - Test that the `./setup.py --keywords` command returns the correct - value without balking. - """ - - self.run_setup('egg_info') - stdout, _, _ = self.run_setup('--keywords') - assert stdout == 'packaging,distutils,setuptools' - - def test_sdist_extra_files(self): - """Test that the extra files are correctly added.""" - - stdout, _, return_code = self.run_setup('sdist', '--formats=gztar') - - # There can be only one - try: - tf_path = glob.glob(os.path.join('dist', '*.tar.gz'))[0] - except IndexError: - assert False, 'source dist not found' - - tf = tarfile.open(tf_path) - names = ['/'.join(p.split('/')[1:]) for p in tf.getnames()] - - self.assertIn('extra-file.txt', names) - - def test_console_script_install(self): - """Test that we install a non-pkg-resources console script.""" - - if os.name == 'nt': - self.skipTest('Windows support is passthrough') - - stdout, _, return_code = self.run_setup( - 'install_scripts', '--install-dir=%s' % self.temp_dir) - - self.useFixture( - fixtures.EnvironmentVariable('PYTHONPATH', '.')) - - self.check_script_install(stdout) - - def test_console_script_develop(self): - """Test that we develop a non-pkg-resources console script.""" - - if os.name == 'nt': - self.skipTest('Windows support is passthrough') - - self.useFixture( - fixtures.EnvironmentVariable( - 'PYTHONPATH', ".:%s" % self.temp_dir)) - - stdout, _, return_code = self.run_setup( - 'develop', '--install-dir=%s' % self.temp_dir) - - self.check_script_install(stdout) - - -class TestGitSDist(base.BaseTestCase): - - def setUp(self): - super(TestGitSDist, self).setUp() - - stdout, _, return_code = self._run_cmd('git', ('init',)) - if return_code: - self.skipTest("git not installed") - - stdout, _, return_code = self._run_cmd('git', ('add', '.')) - stdout, _, return_code = self._run_cmd( - 'git', ('commit', '-m', 'Turn this into a git repo')) - - stdout, _, return_code = self.run_setup('sdist', '--formats=gztar') - - def test_sdist_git_extra_files(self): - """Test that extra files found in git are correctly added.""" - # There can be only one - tf_path = glob.glob(os.path.join('dist', '*.tar.gz'))[0] - tf = tarfile.open(tf_path) - names = ['/'.join(p.split('/')[1:]) for p in tf.getnames()] - - self.assertIn('git-extra-file.txt', names) diff --git a/awx/lib/site-packages/pbr/tests/test_files.py b/awx/lib/site-packages/pbr/tests/test_files.py deleted file mode 100644 index d9cf3e5147..0000000000 --- a/awx/lib/site-packages/pbr/tests/test_files.py +++ /dev/null @@ -1,80 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import os - -import fixtures - -from pbr.hooks import files -from pbr.tests import base - - -class FilesConfigTest(base.BaseTestCase): - - def setUp(self): - super(FilesConfigTest, self).setUp() - - pkg_fixture = fixtures.PythonPackage( - "fake_package", [ - ("fake_module.py", b""), - ("other_fake_module.py", b""), - ]) - self.useFixture(pkg_fixture) - pkg_etc = os.path.join(pkg_fixture.base, 'etc') - pkg_sub = os.path.join(pkg_etc, 'sub') - subpackage = os.path.join( - pkg_fixture.base, 'fake_package', 'subpackage') - os.makedirs(pkg_sub) - os.makedirs(subpackage) - with open(os.path.join(pkg_etc, "foo"), 'w') as foo_file: - foo_file.write("Foo Data") - with open(os.path.join(pkg_sub, "bar"), 'w') as foo_file: - foo_file.write("Bar Data") - with open(os.path.join(subpackage, "__init__.py"), 'w') as foo_file: - foo_file.write("# empty") - - self.useFixture(base.DiveDir(pkg_fixture.base)) - - def test_implicit_auto_package(self): - config = dict( - files=dict( - ) - ) - files.FilesConfig(config, 'fake_package').run() - self.assertIn('subpackage', config['files']['packages']) - - def test_auto_package(self): - config = dict( - files=dict( - packages='fake_package', - ) - ) - files.FilesConfig(config, 'fake_package').run() - self.assertIn('subpackage', config['files']['packages']) - - def test_data_files_globbing(self): - config = dict( - files=dict( - data_files="\n etc/pbr = etc/*" - ) - ) - files.FilesConfig(config, 'fake_package').run() - self.assertIn( - '\netc/pbr/ = \n etc/foo\netc/pbr/sub = \n etc/sub/bar', - config['files']['data_files']) diff --git a/awx/lib/site-packages/pbr/tests/test_hooks.py b/awx/lib/site-packages/pbr/tests/test_hooks.py deleted file mode 100644 index b9e874a1c3..0000000000 --- a/awx/lib/site-packages/pbr/tests/test_hooks.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -import os -import textwrap - -from testtools.matchers import Contains - -from pbr.tests import base -from pbr.tests import util - - -class TestHooks(base.BaseTestCase): - def setUp(self): - super(TestHooks, self).setUp() - with util.open_config( - os.path.join(self.package_dir, 'setup.cfg')) as cfg: - cfg.set('global', 'setup-hooks', - 'pbr_testpackage._setup_hooks.test_hook_1\n' - 'pbr_testpackage._setup_hooks.test_hook_2') - cfg.set('build_ext', 'pre-hook.test_pre_hook', - 'pbr_testpackage._setup_hooks.test_pre_hook') - cfg.set('build_ext', 'post-hook.test_post_hook', - 'pbr_testpackage._setup_hooks.test_post_hook') - - def test_global_setup_hooks(self): - """Test setup_hooks. - - Test that setup_hooks listed in the [global] section of setup.cfg are - executed in order. - """ - - stdout, _, return_code = self.run_setup('egg_info') - assert 'test_hook_1\ntest_hook_2' in stdout - assert return_code == 0 - - def test_command_hooks(self): - """Test command hooks. - - Simple test that the appropriate command hooks run at the - beginning/end of the appropriate command. - """ - - stdout, _, return_code = self.run_setup('egg_info') - assert 'build_ext pre-hook' not in stdout - assert 'build_ext post-hook' not in stdout - assert return_code == 0 - - stdout, _, return_code = self.run_setup('build_ext') - assert textwrap.dedent(""" - running build_ext - running pre_hook pbr_testpackage._setup_hooks.test_pre_hook for command build_ext - build_ext pre-hook - """) in stdout # flake8: noqa - assert stdout.endswith('build_ext post-hook') - assert return_code == 0 - - def test_custom_commands_known(self): - stdout, _, return_code = self.run_setup('--help-commands') - self.assertFalse(return_code) - self.assertThat(stdout, Contains(" testr ")) diff --git a/awx/lib/site-packages/pbr/tests/test_packaging.py b/awx/lib/site-packages/pbr/tests/test_packaging.py deleted file mode 100644 index 46dd0d54da..0000000000 --- a/awx/lib/site-packages/pbr/tests/test_packaging.py +++ /dev/null @@ -1,159 +0,0 @@ -# Copyright (c) 2013 New Dream Network, LLC (DreamHost) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -import os -import tempfile - -import fixtures -import mock - -from pbr import packaging -from pbr.tests import base - - -class TestRepo(fixtures.Fixture): - """A git repo for testing with. - - Use of TempHomeDir with this fixture is strongly recommended as due to the - lack of config --local in older gits, it will write to the users global - configuration without TempHomeDir. - """ - - def __init__(self, basedir): - super(TestRepo, self).__init__() - self._basedir = basedir - - def setUp(self): - super(TestRepo, self).setUp() - base._run_cmd(['git', 'init', '.'], self._basedir) - base._run_cmd( - ['git', 'config', '--global', 'user.email', 'example@example.com'], - self._basedir) - base._run_cmd(['git', 'add', '.'], self._basedir) - - def commit(self): - base._run_cmd(['git', 'commit', '-m', 'test commit'], self._basedir) - - -class TestPackagingInGitRepoWithCommit(base.BaseTestCase): - - def setUp(self): - super(TestPackagingInGitRepoWithCommit, self).setUp() - repo = self.useFixture(TestRepo(self.package_dir)) - repo.commit() - self.run_setup('sdist', allow_fail=False) - - def test_authors(self): - # One commit, something should be in the authors list - with open(os.path.join(self.package_dir, 'AUTHORS'), 'r') as f: - body = f.read() - self.assertNotEqual(body, '') - - def test_changelog(self): - with open(os.path.join(self.package_dir, 'ChangeLog'), 'r') as f: - body = f.read() - # One commit, something should be in the ChangeLog list - self.assertNotEqual(body, '') - - -class TestPackagingInGitRepoWithoutCommit(base.BaseTestCase): - - def setUp(self): - super(TestPackagingInGitRepoWithoutCommit, self).setUp() - self.useFixture(TestRepo(self.package_dir)) - self.run_setup('sdist', allow_fail=False) - - def test_authors(self): - # No commits, no authors in list - with open(os.path.join(self.package_dir, 'AUTHORS'), 'r') as f: - body = f.read() - self.assertEqual(body, '\n') - - def test_changelog(self): - # No commits, nothing should be in the ChangeLog list - with open(os.path.join(self.package_dir, 'ChangeLog'), 'r') as f: - body = f.read() - self.assertEqual(body, 'CHANGES\n=======\n\n') - - -class TestPackagingInPlainDirectory(base.BaseTestCase): - - def setUp(self): - super(TestPackagingInPlainDirectory, self).setUp() - self.run_setup('sdist', allow_fail=False) - - def test_authors(self): - # Not a git repo, no AUTHORS file created - filename = os.path.join(self.package_dir, 'AUTHORS') - self.assertFalse(os.path.exists(filename)) - - def test_changelog(self): - # Not a git repo, no ChangeLog created - filename = os.path.join(self.package_dir, 'ChangeLog') - self.assertFalse(os.path.exists(filename)) - - -class TestPresenceOfGit(base.BaseTestCase): - - def testGitIsInstalled(self): - with mock.patch.object(packaging, - '_run_shell_command') as _command: - _command.return_value = 'git version 1.8.4.1' - self.assertEqual(True, packaging._git_is_installed()) - - def testGitIsNotInstalled(self): - with mock.patch.object(packaging, - '_run_shell_command') as _command: - _command.side_effect = OSError - self.assertEqual(False, packaging._git_is_installed()) - - -class TestNestedRequirements(base.BaseTestCase): - - def test_nested_requirement(self): - tempdir = tempfile.mkdtemp() - requirements = os.path.join(tempdir, 'requirements.txt') - nested = os.path.join(tempdir, 'nested.txt') - with open(requirements, 'w') as f: - f.write('-r ' + nested) - with open(nested, 'w') as f: - f.write('pbr') - result = packaging.parse_requirements([requirements]) - self.assertEqual(result, ['pbr']) diff --git a/awx/lib/site-packages/pbr/tests/test_setup.py b/awx/lib/site-packages/pbr/tests/test_setup.py deleted file mode 100644 index 44436df5e3..0000000000 --- a/awx/lib/site-packages/pbr/tests/test_setup.py +++ /dev/null @@ -1,375 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import os -import sys -import tempfile - -try: - import cStringIO as io - BytesIO = io.StringIO -except ImportError: - import io - BytesIO = io.BytesIO - -import fixtures -import testscenarios - -from pbr import packaging -from pbr.tests import base - - -class SkipFileWrites(base.BaseTestCase): - - scenarios = [ - ('changelog_option_true', - dict(option_key='skip_changelog', option_value='True', - env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None, - pkg_func=packaging.write_git_changelog, filename='ChangeLog')), - ('changelog_option_false', - dict(option_key='skip_changelog', option_value='False', - env_key='SKIP_WRITE_GIT_CHANGELOG', env_value=None, - pkg_func=packaging.write_git_changelog, filename='ChangeLog')), - ('changelog_env_true', - dict(option_key='skip_changelog', option_value='False', - env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True', - pkg_func=packaging.write_git_changelog, filename='ChangeLog')), - ('changelog_both_true', - dict(option_key='skip_changelog', option_value='True', - env_key='SKIP_WRITE_GIT_CHANGELOG', env_value='True', - pkg_func=packaging.write_git_changelog, filename='ChangeLog')), - ('authors_option_true', - dict(option_key='skip_authors', option_value='True', - env_key='SKIP_GENERATE_AUTHORS', env_value=None, - pkg_func=packaging.generate_authors, filename='AUTHORS')), - ('authors_option_false', - dict(option_key='skip_authors', option_value='False', - env_key='SKIP_GENERATE_AUTHORS', env_value=None, - pkg_func=packaging.generate_authors, filename='AUTHORS')), - ('authors_env_true', - dict(option_key='skip_authors', option_value='False', - env_key='SKIP_GENERATE_AUTHORS', env_value='True', - pkg_func=packaging.generate_authors, filename='AUTHORS')), - ('authors_both_true', - dict(option_key='skip_authors', option_value='True', - env_key='SKIP_GENERATE_AUTHORS', env_value='True', - pkg_func=packaging.generate_authors, filename='AUTHORS')), - ] - - def setUp(self): - super(SkipFileWrites, self).setUp() - self.temp_path = self.useFixture(fixtures.TempDir()).path - self.root_dir = os.path.abspath(os.path.curdir) - self.git_dir = os.path.join(self.root_dir, ".git") - if not os.path.exists(self.git_dir): - self.skipTest("%s is missing; skipping git-related checks" - % self.git_dir) - return - self.filename = os.path.join(self.temp_path, self.filename) - self.option_dict = dict() - if self.option_key is not None: - self.option_dict[self.option_key] = ('setup.cfg', - self.option_value) - self.useFixture( - fixtures.EnvironmentVariable(self.env_key, self.env_value)) - - def test_skip(self): - self.pkg_func(git_dir=self.git_dir, - dest_dir=self.temp_path, - option_dict=self.option_dict) - self.assertEqual( - not os.path.exists(self.filename), - (self.option_value.lower() in packaging.TRUE_VALUES - or self.env_value is not None)) - -_changelog_content = """04316fe (review/monty_taylor/27519) Make python -378261a Add an integration test script. -3c373ac (HEAD, tag: 2013.2.rc2, tag: 2013.2, milestone-proposed) Merge "Lib -182feb3 (tag: 0.5.17) Fix pip invocation for old versions of pip. -fa4f46e (tag: 0.5.16) Remove explicit depend on distribute. -d1c53dd Use pip instead of easy_install for installation. -a793ea1 Merge "Skip git-checkout related tests when .git is missing" -6c27ce7 Skip git-checkout related tests when .git is missing -04984a5 Refactor hooks file. -a65e8ee (tag: 0.5.14, tag: 0.5.13) Remove jinja pin. -""" - - -class GitLogsTest(base.BaseTestCase): - - def setUp(self): - super(GitLogsTest, self).setUp() - self.temp_path = self.useFixture(fixtures.TempDir()).path - self.root_dir = os.path.abspath(os.path.curdir) - self.git_dir = os.path.join(self.root_dir, ".git") - self.useFixture( - fixtures.EnvironmentVariable('SKIP_GENERATE_AUTHORS')) - self.useFixture( - fixtures.EnvironmentVariable('SKIP_WRITE_GIT_CHANGELOG')) - - def test_write_git_changelog(self): - self.useFixture(fixtures.FakePopen(lambda _: { - "stdout": BytesIO(_changelog_content.encode('utf-8')) - })) - - packaging.write_git_changelog(git_dir=self.git_dir, - dest_dir=self.temp_path) - - with open(os.path.join(self.temp_path, "ChangeLog"), "r") as ch_fh: - changelog_contents = ch_fh.read() - self.assertIn("2013.2", changelog_contents) - self.assertIn("0.5.17", changelog_contents) - self.assertIn("------", changelog_contents) - self.assertIn("Refactor hooks file", changelog_contents) - self.assertNotIn("Refactor hooks file.", changelog_contents) - self.assertNotIn("182feb3", changelog_contents) - self.assertNotIn("review/monty_taylor/27519", changelog_contents) - self.assertNotIn("0.5.13", changelog_contents) - self.assertNotIn('Merge "', changelog_contents) - - def test_generate_authors(self): - author_old = u"Foo Foo " - author_new = u"Bar Bar " - co_author = u"Foo Bar " - co_author_by = u"Co-authored-by: " + co_author - - git_log_cmd = ( - "git --git-dir=%s log --format=%%aN <%%aE>" - % self.git_dir) - git_co_log_cmd = ("git --git-dir=%s log" % self.git_dir) - git_top_level = "git rev-parse --show-toplevel" - cmd_map = { - git_log_cmd: author_new, - git_co_log_cmd: co_author_by, - git_top_level: self.root_dir, - } - - exist_files = [self.git_dir, - os.path.join(self.temp_path, "AUTHORS.in")] - self.useFixture(fixtures.MonkeyPatch( - "os.path.exists", - lambda path: os.path.abspath(path) in exist_files)) - - def _fake_run_shell_command(cmd, **kwargs): - return cmd_map[" ".join(cmd)] - - self.useFixture(fixtures.MonkeyPatch( - "pbr.packaging._run_shell_command", - _fake_run_shell_command)) - - with open(os.path.join(self.temp_path, "AUTHORS.in"), "w") as auth_fh: - auth_fh.write("%s\n" % author_old) - - packaging.generate_authors(git_dir=self.git_dir, - dest_dir=self.temp_path) - - with open(os.path.join(self.temp_path, "AUTHORS"), "r") as auth_fh: - authors = auth_fh.read() - self.assertTrue(author_old in authors) - self.assertTrue(author_new in authors) - self.assertTrue(co_author in authors) - - -class BuildSphinxTest(base.BaseTestCase): - - scenarios = [ - ('true_autodoc_caps', - dict(has_opt=True, autodoc='True', has_autodoc=True)), - ('true_autodoc_lower', - dict(has_opt=True, autodoc='true', has_autodoc=True)), - ('false_autodoc', - dict(has_opt=True, autodoc='False', has_autodoc=False)), - ('no_autodoc', - dict(has_opt=False, autodoc='False', has_autodoc=False)), - ] - - def setUp(self): - super(BuildSphinxTest, self).setUp() - - self.useFixture(fixtures.MonkeyPatch( - "sphinx.setup_command.BuildDoc.run", lambda self: None)) - from distutils import dist - self.distr = dist.Distribution() - self.distr.packages = ("fake_package",) - self.distr.command_options["build_sphinx"] = { - "source_dir": ["a", "."]} - pkg_fixture = fixtures.PythonPackage( - "fake_package", [("fake_module.py", b"")]) - self.useFixture(pkg_fixture) - self.useFixture(base.DiveDir(pkg_fixture.base)) - - def test_build_doc(self): - if self.has_opt: - self.distr.command_options["pbr"] = { - "autodoc_index_modules": ('setup.cfg', self.autodoc)} - build_doc = packaging.LocalBuildDoc(self.distr) - build_doc.run() - - self.assertTrue( - os.path.exists("api/autoindex.rst") == self.has_autodoc) - self.assertTrue( - os.path.exists( - "api/fake_package.fake_module.rst") == self.has_autodoc) - - def test_builders_config(self): - if self.has_opt: - self.distr.command_options["pbr"] = { - "autodoc_index_modules": ('setup.cfg', self.autodoc)} - - build_doc = packaging.LocalBuildDoc(self.distr) - build_doc.finalize_options() - - self.assertEqual(2, len(build_doc.builders)) - self.assertIn('html', build_doc.builders) - self.assertIn('man', build_doc.builders) - - build_doc = packaging.LocalBuildDoc(self.distr) - build_doc.builders = '' - build_doc.finalize_options() - - self.assertEqual('', build_doc.builders) - - build_doc = packaging.LocalBuildDoc(self.distr) - build_doc.builders = 'man' - build_doc.finalize_options() - - self.assertEqual(1, len(build_doc.builders)) - self.assertIn('man', build_doc.builders) - - build_doc = packaging.LocalBuildDoc(self.distr) - build_doc.builders = 'html,man,doctest' - build_doc.finalize_options() - - self.assertIn('html', build_doc.builders) - self.assertIn('man', build_doc.builders) - self.assertIn('doctest', build_doc.builders) - - -class ParseRequirementsTest(base.BaseTestCase): - - def setUp(self): - super(ParseRequirementsTest, self).setUp() - (fd, self.tmp_file) = tempfile.mkstemp(prefix='openstack', - suffix='.setup') - - def test_parse_requirements_normal(self): - with open(self.tmp_file, 'w') as fh: - fh.write("foo\nbar") - self.assertEqual(['foo', 'bar'], - packaging.parse_requirements([self.tmp_file])) - - def test_parse_requirements_with_git_egg_url(self): - with open(self.tmp_file, 'w') as fh: - fh.write("-e git://foo.com/zipball#egg=bar") - self.assertEqual(['bar'], - packaging.parse_requirements([self.tmp_file])) - - def test_parse_requirements_with_versioned_git_egg_url(self): - with open(self.tmp_file, 'w') as fh: - fh.write("-e git://foo.com/zipball#egg=bar-1.2.4") - self.assertEqual(['bar>=1.2.4'], - packaging.parse_requirements([self.tmp_file])) - - def test_parse_requirements_with_http_egg_url(self): - with open(self.tmp_file, 'w') as fh: - fh.write("https://foo.com/zipball#egg=bar") - self.assertEqual(['bar'], - packaging.parse_requirements([self.tmp_file])) - - def test_parse_requirements_with_versioned_http_egg_url(self): - with open(self.tmp_file, 'w') as fh: - fh.write("https://foo.com/zipball#egg=bar-4.2.1") - self.assertEqual(['bar>=4.2.1'], - packaging.parse_requirements([self.tmp_file])) - - def test_parse_requirements_removes_index_lines(self): - with open(self.tmp_file, 'w') as fh: - fh.write("-f foobar") - self.assertEqual([], packaging.parse_requirements([self.tmp_file])) - - def test_parse_requirements_override_with_env(self): - with open(self.tmp_file, 'w') as fh: - fh.write("foo\nbar") - self.useFixture( - fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES', - self.tmp_file)) - self.assertEqual(['foo', 'bar'], - packaging.parse_requirements()) - - def test_parse_requirements_override_with_env_multiple_files(self): - with open(self.tmp_file, 'w') as fh: - fh.write("foo\nbar") - self.useFixture( - fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES', - "no-such-file," + self.tmp_file)) - self.assertEqual(['foo', 'bar'], - packaging.parse_requirements()) - - def test_get_requirement_from_file_empty(self): - actual = packaging.get_reqs_from_files([]) - self.assertEqual([], actual) - - def test_parse_requirements_with_comments(self): - with open(self.tmp_file, 'w') as fh: - fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz") - self.assertEqual(['foobar', 'foobaz'], - packaging.parse_requirements([self.tmp_file])) - - def test_parse_requirements_python_version(self): - with open("requirements-py%d.txt" % sys.version_info[0], - "w") as fh: - fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz") - self.assertEqual(['foobar', 'foobaz'], - packaging.parse_requirements()) - - def test_parse_requirements_right_python_version(self): - with open("requirements-py1.txt", "w") as fh: - fh.write("thisisatrap") - with open("requirements-py%d.txt" % sys.version_info[0], - "w") as fh: - fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz") - self.assertEqual(['foobar', 'foobaz'], - packaging.parse_requirements()) - - -class ParseDependencyLinksTest(base.BaseTestCase): - - def setUp(self): - super(ParseDependencyLinksTest, self).setUp() - (fd, self.tmp_file) = tempfile.mkstemp(prefix="openstack", - suffix=".setup") - - def test_parse_dependency_normal(self): - with open(self.tmp_file, "w") as fh: - fh.write("http://test.com\n") - self.assertEqual( - ["http://test.com"], - packaging.parse_dependency_links([self.tmp_file])) - - def test_parse_dependency_with_git_egg_url(self): - with open(self.tmp_file, "w") as fh: - fh.write("-e git://foo.com/zipball#egg=bar") - self.assertEqual( - ["git://foo.com/zipball#egg=bar"], - packaging.parse_dependency_links([self.tmp_file])) - - -def load_tests(loader, in_tests, pattern): - return testscenarios.load_tests_apply_scenarios(loader, in_tests, pattern) diff --git a/awx/lib/site-packages/pbr/tests/test_version.py b/awx/lib/site-packages/pbr/tests/test_version.py deleted file mode 100644 index e220d031c1..0000000000 --- a/awx/lib/site-packages/pbr/tests/test_version.py +++ /dev/null @@ -1,31 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 Red Hat, Inc. -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from pbr.tests import base -from pbr import version - - -class DeferredVersionTestCase(base.BaseTestCase): - - def test_cached_version(self): - class MyVersionInfo(version.VersionInfo): - def _get_version_from_pkg_resources(self): - return "5.5.5.5" - - deferred_string = MyVersionInfo("openstack").\ - cached_version_string() - self.assertEqual("5.5.5.5", deferred_string) diff --git a/awx/lib/site-packages/pbr/tests/testpackage/CHANGES.txt b/awx/lib/site-packages/pbr/tests/testpackage/CHANGES.txt deleted file mode 100644 index 709b9d4c80..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/CHANGES.txt +++ /dev/null @@ -1,86 +0,0 @@ -Changelog -=========== - -0.3 (unreleased) ------------------- - -- The ``glob_data_files`` hook became a pre-command hook for the install_data - command instead of being a setup-hook. This is to support the additional - functionality of requiring data_files with relative destination paths to be - install relative to the package's install path (i.e. site-packages). - -- Dropped support for and deprecated the easier_install custom command. - Although it should still work, it probably won't be used anymore for - stsci_python packages. - -- Added support for the ``build_optional_ext`` command, which replaces/extends - the default ``build_ext`` command. See the README for more details. - -- Added the ``tag_svn_revision`` setup_hook as a replacement for the - setuptools-specific tag_svn_revision option to the egg_info command. This - new hook is easier to use than the old tag_svn_revision option: It's - automatically enabled by the presence of ``.dev`` in the version string, and - disabled otherwise. - -- The ``svn_info_pre_hook`` and ``svn_info_post_hook`` have been replaced with - ``version_pre_command_hook`` and ``version_post_command_hook`` respectively. - However, a new ``version_setup_hook``, which has the same purpose, has been - added. It is generally easier to use and will give more consistent results - in that it will run every time setup.py is run, regardless of which command - is used. ``stsci.distutils`` itself uses this hook--see the `setup.cfg` file - and `stsci/distutils/__init__.py` for example usage. - -- Instead of creating an `svninfo.py` module, the new ``version_`` hooks create - a file called `version.py`. In addition to the SVN info that was included - in `svninfo.py`, it includes a ``__version__`` variable to be used by the - package's `__init__.py`. This allows there to be a hard-coded - ``__version__`` variable included in the source code, rather than using - pkg_resources to get the version. - -- In `version.py`, the variables previously named ``__svn_version__`` and - ``__full_svn_info__`` are now named ``__svn_revision__`` and - ``__svn_full_info__``. - -- Fixed a bug when using stsci.distutils in the installation of other packages - in the ``stsci.*`` namespace package. If stsci.distutils was not already - installed, and was downloaded automatically by distribute through the - setup_requires option, then ``stsci.distutils`` would fail to import. This - is because the way the namespace package (nspkg) mechanism currently works, - all packages belonging to the nspkg *must* be on the import path at initial - import time. - - So when installing stsci.tools, for example, if ``stsci.tools`` is imported - from within the source code at install time, but before ``stsci.distutils`` - is downloaded and added to the path, the ``stsci`` package is already - imported and can't be extended to include the path of ``stsci.distutils`` - after the fact. The easiest way of dealing with this, it seems, is to - delete ``stsci`` from ``sys.modules``, which forces it to be reimported, now - the its ``__path__`` extended to include ``stsci.distutil``'s path. - - -0.2.2 (2011-11-09) ------------------- - -- Fixed check for the issue205 bug on actual setuptools installs; before it - only worked on distribute. setuptools has the issue205 bug prior to version - 0.6c10. - -- Improved the fix for the issue205 bug, especially on setuptools. - setuptools, prior to 0.6c10, did not back of sys.modules either before - sandboxing, which causes serious problems. In fact, it's so bad that it's - not enough to add a sys.modules backup to the current sandbox: It's in fact - necessary to monkeypatch setuptools.sandbox.run_setup so that any subsequent - calls to it also back up sys.modules. - - -0.2.1 (2011-09-02) ------------------- - -- Fixed the dependencies so that setuptools is requirement but 'distribute' - specifically. Previously installation could fail if users had plain - setuptools installed and not distribute - -0.2 (2011-08-23) ------------------- - -- Initial public release diff --git a/awx/lib/site-packages/pbr/tests/testpackage/LICENSE.txt b/awx/lib/site-packages/pbr/tests/testpackage/LICENSE.txt deleted file mode 100644 index 7e8019a89e..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/LICENSE.txt +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (C) 2005 Association of Universities for Research in Astronomy (AURA) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - 3. The name of AURA and its representatives may not be used to - endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. - diff --git a/awx/lib/site-packages/pbr/tests/testpackage/MANIFEST.in b/awx/lib/site-packages/pbr/tests/testpackage/MANIFEST.in deleted file mode 100644 index cdc95eafc3..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include data_files/* diff --git a/awx/lib/site-packages/pbr/tests/testpackage/README.txt b/awx/lib/site-packages/pbr/tests/testpackage/README.txt deleted file mode 100644 index b6d84a7b1a..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/README.txt +++ /dev/null @@ -1,148 +0,0 @@ -Introduction -============ -This package contains utilities used to package some of STScI's Python -projects; specifically those projects that comprise stsci_python_ and -Astrolib_. - -It currently consists mostly of some setup_hook scripts meant for use with -`distutils2/packaging`_ and/or pbr_, and a customized easy_install command -meant for use with distribute_. - -This package is not meant for general consumption, though it might be worth -looking at for examples of how to do certain things with your own packages, but -YMMV. - -Features -======== - -Hook Scripts ------------- -Currently the main features of this package are a couple of setup_hook scripts. -In distutils2, a setup_hook is a script that runs at the beginning of any -pysetup command, and can modify the package configuration read from setup.cfg. -There are also pre- and post-command hooks that only run before/after a -specific setup command (eg. build_ext, install) is run. - -stsci.distutils.hooks.use_packages_root -''''''''''''''''''''''''''''''''''''''' -If using the ``packages_root`` option under the ``[files]`` section of -setup.cfg, this hook will add that path to ``sys.path`` so that modules in your -package can be imported and used in setup. This can be used even if -``packages_root`` is not specified--in this case it adds ``''`` to -``sys.path``. - -stsci.distutils.hooks.version_setup_hook -'''''''''''''''''''''''''''''''''''''''' -Creates a Python module called version.py which currently contains four -variables: - -* ``__version__`` (the release version) -* ``__svn_revision__`` (the SVN revision info as returned by the ``svnversion`` - command) -* ``__svn_full_info__`` (as returned by the ``svn info`` command) -* ``__setup_datetime__`` (the date and time that setup.py was last run). - -These variables can be imported in the package's `__init__.py` for degugging -purposes. The version.py module will *only* be created in a package that -imports from the version module in its `__init__.py`. It should be noted that -this is generally preferable to writing these variables directly into -`__init__.py`, since this provides more control and is less likely to -unexpectedly break things in `__init__.py`. - -stsci.distutils.hooks.version_pre_command_hook -'''''''''''''''''''''''''''''''''''''''''''''' -Identical to version_setup_hook, but designed to be used as a pre-command -hook. - -stsci.distutils.hooks.version_post_command_hook -''''''''''''''''''''''''''''''''''''''''''''''' -The complement to version_pre_command_hook. This will delete any version.py -files created during a build in order to prevent them from cluttering an SVN -working copy (note, however, that version.py is *not* deleted from the build/ -directory, so a copy of it is still preserved). It will also not be deleted -if the current directory is not an SVN working copy. For example, if source -code extracted from a source tarball it will be preserved. - -stsci.distutils.hooks.tag_svn_revision -'''''''''''''''''''''''''''''''''''''' -A setup_hook to add the SVN revision of the current working copy path to the -package version string, but only if the version ends in .dev. - -For example, ``mypackage-1.0.dev`` becomes ``mypackage-1.0.dev1234``. This is -in accordance with the version string format standardized by PEP 386. - -This should be used as a replacement for the ``tag_svn_revision`` option to -the egg_info command. This hook is more compatible with packaging/distutils2, -which does not include any VCS support. This hook is also more flexible in -that it turns the revision number on/off depending on the presence of ``.dev`` -in the version string, so that it's not automatically added to the version in -final releases. - -This hook does require the ``svnversion`` command to be available in order to -work. It does not examine the working copy metadata directly. - -stsci.distutils.hooks.numpy_extension_hook -'''''''''''''''''''''''''''''''''''''''''' -This is a pre-command hook for the build_ext command. To use it, add a -``[build_ext]`` section to your setup.cfg, and add to it:: - - pre-hook.numpy-extension-hook = stsci.distutils.hooks.numpy_extension_hook - -This hook must be used to build extension modules that use Numpy. The primary -side-effect of this hook is to add the correct numpy include directories to -`include_dirs`. To use it, add 'numpy' to the 'include-dirs' option of each -extension module that requires numpy to build. The value 'numpy' will be -replaced with the actual path to the numpy includes. - -stsci.distutils.hooks.is_display_option -''''''''''''''''''''''''''''''''''''''' -This is not actually a hook, but is a useful utility function that can be used -in writing other hooks. Basically, it returns ``True`` if setup.py was run -with a "display option" such as --version or --help. This can be used to -prevent your hook from running in such cases. - -stsci.distutils.hooks.glob_data_files -''''''''''''''''''''''''''''''''''''' -A pre-command hook for the install_data command. Allows filename wildcards as -understood by ``glob.glob()`` to be used in the data_files option. This hook -must be used in order to have this functionality since it does not normally -exist in distutils. - -This hook also ensures that data files are installed relative to the package -path. data_files shouldn't normally be installed this way, but the -functionality is required for a few special cases. - - -Commands --------- -build_optional_ext -'''''''''''''''''' -This serves as an optional replacement for the default built_ext command, -which compiles C extension modules. Its purpose is to allow extension modules -to be *optional*, so that if their build fails the rest of the package is -still allowed to be built and installed. This can be used when an extension -module is not definitely required to use the package. - -To use this custom command, add:: - - commands = stsci.distutils.command.build_optional_ext.build_optional_ext - -under the ``[global]`` section of your package's setup.cfg. Then, to mark -an individual extension module as optional, under the setup.cfg section for -that extension add:: - - optional = True - -Optionally, you may also add a custom failure message by adding:: - - fail_message = The foobar extension module failed to compile. - This could be because you lack such and such headers. - This package will still work, but such and such features - will be disabled. - - -.. _stsci_python: http://www.stsci.edu/resources/software_hardware/pyraf/stsci_python -.. _Astrolib: http://www.scipy.org/AstroLib/ -.. _distutils2/packaging: http://distutils2.notmyidea.org/ -.. _d2to1: http://pypi.python.org/pypi/d2to1 -.. _distribute: http://pypi.python.org/pypi/distribute diff --git a/awx/lib/site-packages/pbr/tests/testpackage/data_files/a.txt b/awx/lib/site-packages/pbr/tests/testpackage/data_files/a.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/data_files/b.txt b/awx/lib/site-packages/pbr/tests/testpackage/data_files/b.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/data_files/c.rst b/awx/lib/site-packages/pbr/tests/testpackage/data_files/c.rst deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/extra-file.txt b/awx/lib/site-packages/pbr/tests/testpackage/extra-file.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/git-extra-file.txt b/awx/lib/site-packages/pbr/tests/testpackage/git-extra-file.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/__init__.py b/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/_setup_hooks.py b/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/_setup_hooks.py deleted file mode 100644 index f8b3087604..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/_setup_hooks.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -from distutils.command import build_py - - -def test_hook_1(config): - print('test_hook_1') - - -def test_hook_2(config): - print('test_hook_2') - - -class test_command(build_py.build_py): - command_name = 'build_py' - - def run(self): - print('Running custom build_py command.') - return build_py.build_py.run(self) - - -def test_pre_hook(cmdobj): - print('build_ext pre-hook') - - -def test_post_hook(cmdobj): - print('build_ext post-hook') diff --git a/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/cmd.py b/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/cmd.py deleted file mode 100644 index 4cc4522f10..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/cmd.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import print_function - - -def main(): - print("PBR Test Command") - - -class Foo(object): - - @classmethod - def bar(self): - print("PBR Test Command - with class!") diff --git a/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/package_data/1.txt b/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/package_data/1.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/package_data/2.txt b/awx/lib/site-packages/pbr/tests/testpackage/pbr_testpackage/package_data/2.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pbr/tests/testpackage/setup.cfg b/awx/lib/site-packages/pbr/tests/testpackage/setup.cfg deleted file mode 100644 index a410e3c7d9..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/setup.cfg +++ /dev/null @@ -1,51 +0,0 @@ -[metadata] -name = pbr_testpackage -version = 0.1.dev -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://pypi.python.org/pypi/pbr -summary = Test package for testing pbr -description-file = - README.txt - CHANGES.txt -requires-python = >=2.5 - -requires-dist = - setuptools - -classifier = - Development Status :: 3 - Alpha - Intended Audience :: Developers - License :: OSI Approved :: BSD License - Programming Language :: Python - Topic :: Scientific/Engineering - Topic :: Software Development :: Build Tools - Topic :: Software Development :: Libraries :: Python Modules - Topic :: System :: Archiving :: Packaging - -keywords = packaging, distutils, setuptools - -[files] -packages = pbr_testpackage -package-data = testpackage = package_data/*.txt -data-files = testpackage/data_files = data_files/*.txt -extra-files = extra-file.txt - -[entry_points] -console_scripts = - pbr_test_cmd = pbr_testpackage.cmd:main - pbr_test_cmd_with_class = pbr_testpackage.cmd:Foo.bar - -[extension=pbr_testpackage.testext] -sources = src/testext.c -optional = True - -[global] -#setup-hooks = -# pbr_testpackage._setup_hooks.test_hook_1 -# pbr_testpackage._setup_hooks.test_hook_2 -commands = pbr_testpackage._setup_hooks.test_command - -[build_ext] -#pre-hook.test_pre_hook = pbr_testpackage._setup_hooks.test_pre_hook -#post-hook.test_post_hook = pbr_testpackage._setup_hooks.test_post_hook diff --git a/awx/lib/site-packages/pbr/tests/testpackage/setup.py b/awx/lib/site-packages/pbr/tests/testpackage/setup.py deleted file mode 100755 index 8866691061..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/setup.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import setuptools - -setuptools.setup( - setup_requires=['pbr'], - pbr=True, -) diff --git a/awx/lib/site-packages/pbr/tests/testpackage/src/testext.c b/awx/lib/site-packages/pbr/tests/testpackage/src/testext.c deleted file mode 100644 index 872d43c04f..0000000000 --- a/awx/lib/site-packages/pbr/tests/testpackage/src/testext.c +++ /dev/null @@ -1,28 +0,0 @@ -#include - - -static PyMethodDef TestextMethods[] = { - {NULL, NULL, 0, NULL} -}; - - -#if PY_MAJOR_VERSION >=3 -static struct PyModuleDef testextmodule = { - PyModuleDef_HEAD_INIT, - "testext", - -1, - TestextMethods -}; - -PyObject* -PyInit_testext(void) -{ - return PyModule_Create(&testextmodule); -} -#else -PyMODINIT_FUNC -inittestext(void) -{ - Py_InitModule("testext", TestextMethods); -} -#endif diff --git a/awx/lib/site-packages/pbr/tests/util.py b/awx/lib/site-packages/pbr/tests/util.py deleted file mode 100644 index de5a7401aa..0000000000 --- a/awx/lib/site-packages/pbr/tests/util.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -import contextlib -import os -import shutil -import stat - -try: - import ConfigParser as configparser -except ImportError: - import configparser - - -@contextlib.contextmanager -def open_config(filename): - cfg = configparser.ConfigParser() - cfg.read(filename) - yield cfg - with open(filename, 'w') as fp: - cfg.write(fp) - - -def rmtree(path): - """shutil.rmtree() with error handler. - - Handle 'access denied' from trying to delete read-only files. - """ - - def onerror(func, path, exc_info): - if not os.access(path, os.W_OK): - os.chmod(path, stat.S_IWUSR) - func(path) - else: - raise - - return shutil.rmtree(path, onerror=onerror) diff --git a/awx/lib/site-packages/pbr/util.py b/awx/lib/site-packages/pbr/util.py deleted file mode 100644 index 8c7c2c9077..0000000000 --- a/awx/lib/site-packages/pbr/util.py +++ /dev/null @@ -1,618 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Copyright (C) 2013 Association of Universities for Research in Astronomy -# (AURA) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# 3. The name of AURA and its representatives may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - -"""The code in this module is mostly copy/pasted out of the distutils2 source -code, as recommended by Tarek Ziade. As such, it may be subject to some change -as distutils2 development continues, and will have to be kept up to date. - -I didn't want to use it directly from distutils2 itself, since I do not want it -to be an installation dependency for our packages yet--it is still too unstable -(the latest version on PyPI doesn't even install). -""" - -# These first two imports are not used, but are needed to get around an -# irritating Python bug that can crop up when using ./setup.py test. -# See: http://www.eby-sarna.com/pipermail/peak/2010-May/003355.html -try: - import multiprocessing # flake8: noqa -except ImportError: - pass -import logging # flake8: noqa - -import os -import re -import sys -import traceback - -from collections import defaultdict - -import distutils.ccompiler - -from distutils import log -from distutils.errors import (DistutilsOptionError, DistutilsModuleError, - DistutilsFileError) -from setuptools.command.egg_info import manifest_maker -from setuptools.dist import Distribution -from setuptools.extension import Extension - -try: - import ConfigParser as configparser -except ImportError: - import configparser - -from pbr import extra_files -import pbr.hooks - -# A simplified RE for this; just checks that the line ends with version -# predicates in () -_VERSION_SPEC_RE = re.compile(r'\s*(.*?)\s*\((.*)\)\s*$') - - -# Mappings from setup() keyword arguments to setup.cfg options; -# The values are (section, option) tuples, or simply (section,) tuples if -# the option has the same name as the setup() argument -D1_D2_SETUP_ARGS = { - "name": ("metadata",), - "version": ("metadata",), - "author": ("metadata",), - "author_email": ("metadata",), - "maintainer": ("metadata",), - "maintainer_email": ("metadata",), - "url": ("metadata", "home_page"), - "description": ("metadata", "summary"), - "keywords": ("metadata",), - "long_description": ("metadata", "description"), - "download-url": ("metadata",), - "classifiers": ("metadata", "classifier"), - "platforms": ("metadata", "platform"), # ** - "license": ("metadata",), - # Use setuptools install_requires, not - # broken distutils requires - "install_requires": ("metadata", "requires_dist"), - "setup_requires": ("metadata", "setup_requires_dist"), - "provides": ("metadata", "provides_dist"), # ** - "obsoletes": ("metadata", "obsoletes_dist"), # ** - "package_dir": ("files", 'packages_root'), - "packages": ("files",), - "package_data": ("files",), - "namespace_packages": ("files",), - "data_files": ("files",), - "scripts": ("files",), - "py_modules": ("files", "modules"), # ** - "cmdclass": ("global", "commands"), - # Not supported in distutils2, but provided for - # backwards compatibility with setuptools - "use_2to3": ("backwards_compat", "use_2to3"), - "zip_safe": ("backwards_compat", "zip_safe"), - "tests_require": ("backwards_compat", "tests_require"), - "dependency_links": ("backwards_compat",), - "include_package_data": ("backwards_compat",), -} - -# setup() arguments that can have multiple values in setup.cfg -MULTI_FIELDS = ("classifiers", - "platforms", - "install_requires", - "provides", - "obsoletes", - "namespace_packages", - "packages", - "package_data", - "data_files", - "scripts", - "py_modules", - "dependency_links", - "setup_requires", - "tests_require", - "cmdclass") - -# setup() arguments that contain boolean values -BOOL_FIELDS = ("use_2to3", "zip_safe", "include_package_data") - - -CSV_FIELDS = ("keywords",) - - -def resolve_name(name): - """Resolve a name like ``module.object`` to an object and return it. - - Raise ImportError if the module or name is not found. - """ - - parts = name.split('.') - cursor = len(parts) - 1 - module_name = parts[:cursor] - attr_name = parts[-1] - - while cursor > 0: - try: - ret = __import__('.'.join(module_name), fromlist=[attr_name]) - break - except ImportError: - if cursor == 0: - raise - cursor -= 1 - module_name = parts[:cursor] - attr_name = parts[cursor] - ret = '' - - for part in parts[cursor:]: - try: - ret = getattr(ret, part) - except AttributeError: - raise ImportError(name) - - return ret - - -def cfg_to_args(path='setup.cfg'): - """ Distutils2 to distutils1 compatibility util. - - This method uses an existing setup.cfg to generate a dictionary of - keywords that can be used by distutils.core.setup(kwargs**). - - :param file: - The setup.cfg path. - :raises DistutilsFileError: - When the setup.cfg file is not found. - - """ - - # The method source code really starts here. - parser = configparser.RawConfigParser() - if not os.path.exists(path): - raise DistutilsFileError("file '%s' does not exist" % - os.path.abspath(path)) - parser.read(path) - config = {} - for section in parser.sections(): - config[section] = dict(parser.items(section)) - - # Run setup_hooks, if configured - setup_hooks = has_get_option(config, 'global', 'setup_hooks') - package_dir = has_get_option(config, 'files', 'packages_root') - - # Add the source package directory to sys.path in case it contains - # additional hooks, and to make sure it's on the path before any existing - # installations of the package - if package_dir: - package_dir = os.path.abspath(package_dir) - sys.path.insert(0, package_dir) - - try: - if setup_hooks: - setup_hooks = [ - hook for hook in split_multiline(setup_hooks) - if hook != 'pbr.hooks.setup_hook'] - for hook in setup_hooks: - hook_fn = resolve_name(hook) - try : - hook_fn(config) - except SystemExit: - log.error('setup hook %s terminated the installation') - except: - e = sys.exc_info()[1] - log.error('setup hook %s raised exception: %s\n' % - (hook, e)) - log.error(traceback.format_exc()) - sys.exit(1) - - # Run the pbr hook - pbr.hooks.setup_hook(config) - - kwargs = setup_cfg_to_setup_kwargs(config) - - # Set default config overrides - kwargs['include_package_data'] = True - kwargs['zip_safe'] = False - - register_custom_compilers(config) - - ext_modules = get_extension_modules(config) - if ext_modules: - kwargs['ext_modules'] = ext_modules - - entry_points = get_entry_points(config) - if entry_points: - kwargs['entry_points'] = entry_points - - wrap_commands(kwargs) - - # Handle the [files]/extra_files option - files_extra_files = has_get_option(config, 'files', 'extra_files') - if files_extra_files: - extra_files.set_extra_files(split_multiline(files_extra_files)) - - finally: - # Perform cleanup if any paths were added to sys.path - if package_dir: - sys.path.pop(0) - - return kwargs - - -def setup_cfg_to_setup_kwargs(config): - """Processes the setup.cfg options and converts them to arguments accepted - by setuptools' setup() function. - """ - - kwargs = {} - - for arg in D1_D2_SETUP_ARGS: - if len(D1_D2_SETUP_ARGS[arg]) == 2: - # The distutils field name is different than distutils2's. - section, option = D1_D2_SETUP_ARGS[arg] - - elif len(D1_D2_SETUP_ARGS[arg]) == 1: - # The distutils field name is the same thant distutils2's. - section = D1_D2_SETUP_ARGS[arg][0] - option = arg - - in_cfg_value = has_get_option(config, section, option) - if not in_cfg_value: - # There is no such option in the setup.cfg - if arg == "long_description": - in_cfg_value = has_get_option(config, section, - "description_file") - if in_cfg_value: - in_cfg_value = split_multiline(in_cfg_value) - value = '' - for filename in in_cfg_value: - description_file = open(filename) - try: - value += description_file.read().strip() + '\n\n' - finally: - description_file.close() - in_cfg_value = value - else: - continue - - if arg in CSV_FIELDS: - in_cfg_value = split_csv(in_cfg_value) - if arg in MULTI_FIELDS: - in_cfg_value = split_multiline(in_cfg_value) - elif arg in BOOL_FIELDS: - # Provide some flexibility here... - if in_cfg_value.lower() in ('true', 't', '1', 'yes', 'y'): - in_cfg_value = True - else: - in_cfg_value = False - - if in_cfg_value: - if arg in ('install_requires', 'tests_require'): - # Replaces PEP345-style version specs with the sort expected by - # setuptools - in_cfg_value = [_VERSION_SPEC_RE.sub(r'\1\2', pred) - for pred in in_cfg_value] - elif arg == 'package_dir': - in_cfg_value = {'': in_cfg_value} - elif arg in ('package_data', 'data_files'): - data_files = {} - firstline = True - prev = None - for line in in_cfg_value: - if '=' in line: - key, value = line.split('=', 1) - key, value = (key.strip(), value.strip()) - if key in data_files: - # Multiple duplicates of the same package name; - # this is for backwards compatibility of the old - # format prior to d2to1 0.2.6. - prev = data_files[key] - prev.extend(value.split()) - else: - prev = data_files[key.strip()] = value.split() - elif firstline: - raise DistutilsOptionError( - 'malformed package_data first line %r (misses ' - '"=")' % line) - else: - prev.extend(line.strip().split()) - firstline = False - if arg == 'data_files': - # the data_files value is a pointlessly different structure - # from the package_data value - data_files = data_files.items() - in_cfg_value = data_files - elif arg == 'cmdclass': - cmdclass = {} - dist = Distribution() - for cls in in_cfg_value: - cls = resolve_name(cls) - cmd = cls(dist) - cmdclass[cmd.get_command_name()] = cls - in_cfg_value = cmdclass - - kwargs[arg] = in_cfg_value - - return kwargs - - -def register_custom_compilers(config): - """Handle custom compilers; this has no real equivalent in distutils, where - additional compilers could only be added programmatically, so we have to - hack it in somehow. - """ - - compilers = has_get_option(config, 'global', 'compilers') - if compilers: - compilers = split_multiline(compilers) - for compiler in compilers: - compiler = resolve_name(compiler) - - # In distutils2 compilers these class attributes exist; for - # distutils1 we just have to make something up - if hasattr(compiler, 'name'): - name = compiler.name - else: - name = compiler.__name__ - if hasattr(compiler, 'description'): - desc = compiler.description - else: - desc = 'custom compiler %s' % name - - module_name = compiler.__module__ - # Note; this *will* override built in compilers with the same name - # TODO: Maybe display a warning about this? - cc = distutils.ccompiler.compiler_class - cc[name] = (module_name, compiler.__name__, desc) - - # HACK!!!! Distutils assumes all compiler modules are in the - # distutils package - sys.modules['distutils.' + module_name] = sys.modules[module_name] - - -def get_extension_modules(config): - """Handle extension modules""" - - EXTENSION_FIELDS = ("sources", - "include_dirs", - "define_macros", - "undef_macros", - "library_dirs", - "libraries", - "runtime_library_dirs", - "extra_objects", - "extra_compile_args", - "extra_link_args", - "export_symbols", - "swig_opts", - "depends") - - ext_modules = [] - for section in config: - if ':' in section: - labels = section.split(':', 1) - else: - # Backwards compatibility for old syntax; don't use this though - labels = section.split('=', 1) - labels = [l.strip() for l in labels] - if (len(labels) == 2) and (labels[0] == 'extension'): - ext_args = {} - for field in EXTENSION_FIELDS: - value = has_get_option(config, section, field) - # All extension module options besides name can have multiple - # values - if not value: - continue - value = split_multiline(value) - if field == 'define_macros': - macros = [] - for macro in value: - macro = macro.split('=', 1) - if len(macro) == 1: - macro = (macro[0].strip(), None) - else: - macro = (macro[0].strip(), macro[1].strip()) - macros.append(macro) - value = macros - ext_args[field] = value - if ext_args: - if 'name' not in ext_args: - ext_args['name'] = labels[1] - ext_modules.append(Extension(ext_args.pop('name'), - **ext_args)) - return ext_modules - - -def get_entry_points(config): - """Process the [entry_points] section of setup.cfg to handle setuptools - entry points. This is, of course, not a standard feature of - distutils2/packaging, but as there is not currently a standard alternative - in packaging, we provide support for them. - """ - - if not 'entry_points' in config: - return {} - - return dict((option, split_multiline(value)) - for option, value in config['entry_points'].items()) - - -def wrap_commands(kwargs): - dist = Distribution() - - # This should suffice to get the same config values and command classes - # that the actual Distribution will see (not counting cmdclass, which is - # handled below) - dist.parse_config_files() - - for cmd, _ in dist.get_command_list(): - hooks = {} - for opt, val in dist.get_option_dict(cmd).items(): - val = val[1] - if opt.startswith('pre_hook.') or opt.startswith('post_hook.'): - hook_type, alias = opt.split('.', 1) - hook_dict = hooks.setdefault(hook_type, {}) - hook_dict[alias] = val - if not hooks: - continue - - if 'cmdclass' in kwargs and cmd in kwargs['cmdclass']: - cmdclass = kwargs['cmdclass'][cmd] - else: - cmdclass = dist.get_command_class(cmd) - - new_cmdclass = wrap_command(cmd, cmdclass, hooks) - kwargs.setdefault('cmdclass', {})[cmd] = new_cmdclass - - -def wrap_command(cmd, cmdclass, hooks): - def run(self, cmdclass=cmdclass): - self.run_command_hooks('pre_hook') - cmdclass.run(self) - self.run_command_hooks('post_hook') - - return type(cmd, (cmdclass, object), - {'run': run, 'run_command_hooks': run_command_hooks, - 'pre_hook': hooks.get('pre_hook'), - 'post_hook': hooks.get('post_hook')}) - - -def run_command_hooks(cmd_obj, hook_kind): - """Run hooks registered for that command and phase. - - *cmd_obj* is a finalized command object; *hook_kind* is either - 'pre_hook' or 'post_hook'. - """ - - if hook_kind not in ('pre_hook', 'post_hook'): - raise ValueError('invalid hook kind: %r' % hook_kind) - - hooks = getattr(cmd_obj, hook_kind, None) - - if hooks is None: - return - - for hook in hooks.values(): - if isinstance(hook, str): - try: - hook_obj = resolve_name(hook) - except ImportError: - err = sys.exc_info()[1] # For py3k - raise DistutilsModuleError('cannot find hook %s: %s' % - (hook,err)) - else: - hook_obj = hook - - if not hasattr(hook_obj, '__call__'): - raise DistutilsOptionError('hook %r is not callable' % hook) - - log.info('running %s %s for command %s', - hook_kind, hook, cmd_obj.get_command_name()) - - try : - hook_obj(cmd_obj) - except: - e = sys.exc_info()[1] - log.error('hook %s raised exception: %s\n' % (hook, e)) - log.error(traceback.format_exc()) - sys.exit(1) - - -def has_get_option(config, section, option): - if section in config and option in config[section]: - return config[section][option] - elif section in config and option.replace('_', '-') in config[section]: - return config[section][option.replace('_', '-')] - else: - return False - - -def split_multiline(value): - """Special behaviour when we have a multi line options""" - - value = [element for element in - (line.strip() for line in value.split('\n')) - if element] - return value - - -def split_csv(value): - """Special behaviour when we have a comma separated options""" - - value = [element for element in - (chunk.strip() for chunk in value.split(',')) - if element] - return value - - -def monkeypatch_method(cls): - """A function decorator to monkey-patch a method of the same name on the - given class. - """ - - def wrapper(func): - orig = getattr(cls, func.__name__, None) - if orig and not hasattr(orig, '_orig'): # Already patched - setattr(func, '_orig', orig) - setattr(cls, func.__name__, func) - return func - - return wrapper - - -# The following classes are used to hack Distribution.command_options a bit -class DefaultGetDict(defaultdict): - """Like defaultdict, but the get() method also sets and returns the default - value. - """ - - def get(self, key, default=None): - if default is None: - default = self.default_factory() - return super(DefaultGetDict, self).setdefault(key, default) - - -class IgnoreDict(dict): - """A dictionary that ignores any insertions in which the key is a string - matching any string in `ignore`. The ignore list can also contain wildcard - patterns using '*'. - """ - - def __init__(self, ignore): - self.__ignore = re.compile(r'(%s)' % ('|'.join( - [pat.replace('*', '.*') - for pat in ignore]))) - - def __setitem__(self, key, val): - if self.__ignore.match(key): - return - super(IgnoreDict, self).__setitem__(key, val) diff --git a/awx/lib/site-packages/pbr/version.py b/awx/lib/site-packages/pbr/version.py deleted file mode 100644 index 32105051bc..0000000000 --- a/awx/lib/site-packages/pbr/version.py +++ /dev/null @@ -1,101 +0,0 @@ - -# Copyright 2012 OpenStack Foundation -# Copyright 2012-2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities for consuming the version from pkg_resources. -""" - -import pkg_resources - - -class VersionInfo(object): - - def __init__(self, package): - """Object that understands versioning for a package - - :param package: name of the python package, such as glance, or - python-glanceclient - """ - self.package = package - self.release = None - self.version = None - self._cached_version = None - - def __str__(self): - """Make the VersionInfo object behave like a string.""" - return self.version_string() - - def __repr__(self): - """Include the name.""" - return "pbr.version.VersionInfo(%s:%s)" % ( - self.package, self.version_string()) - - def _get_version_from_pkg_resources(self): - """Obtain a version from pkg_resources or setup-time logic if missing. - - This will try to get the version of the package from the pkg_resources - record associated with the package, and if there is no such record - falls back to the logic sdist would use. - """ - try: - requirement = pkg_resources.Requirement.parse(self.package) - provider = pkg_resources.get_provider(requirement) - return provider.version - except pkg_resources.DistributionNotFound: - # The most likely cause for this is running tests in a tree - # produced from a tarball where the package itself has not been - # installed into anything. Revert to setup-time logic. - from pbr import packaging - return packaging.get_version(self.package) - - def release_string(self): - """Return the full version of the package. - - This including suffixes indicating VCS status. - """ - if self.release is None: - self.release = self._get_version_from_pkg_resources() - - return self.release - - def version_string(self): - """Return the short version minus any alpha/beta tags.""" - if self.version is None: - parts = [] - for part in self.release_string().split('.'): - if part[0].isdigit(): - parts.append(part) - else: - break - self.version = ".".join(parts) - - return self.version - - # Compatibility functions - canonical_version_string = version_string - version_string_with_vcs = release_string - - def cached_version_string(self, prefix=""): - """Return a cached version string. - - This will return a cached version string if one is already cached, - irrespective of prefix. If none is cached, one will be created with - prefix and then cached and returned. - """ - if not self._cached_version: - self._cached_version = "%s%s" % (prefix, - self.version_string()) - return self._cached_version diff --git a/awx/lib/site-packages/pexpect/ANSI.py b/awx/lib/site-packages/pexpect/ANSI.py deleted file mode 100644 index c2f20fcdf6..0000000000 --- a/awx/lib/site-packages/pexpect/ANSI.py +++ /dev/null @@ -1,331 +0,0 @@ -'''This implements an ANSI (VT100) terminal emulator as a subclass of screen. - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -# references: -# http://en.wikipedia.org/wiki/ANSI_escape_code -# http://www.retards.org/terminals/vt102.html -# http://vt100.net/docs/vt102-ug/contents.html -# http://vt100.net/docs/vt220-rm/ -# http://www.termsys.demon.co.uk/vtansi.htm - -from . import screen -from . import FSM -import string - -# -# The 'Do.*' functions are helper functions for the ANSI class. -# -def DoEmit (fsm): - - screen = fsm.memory[0] - screen.write_ch(fsm.input_symbol) - -def DoStartNumber (fsm): - - fsm.memory.append (fsm.input_symbol) - -def DoBuildNumber (fsm): - - ns = fsm.memory.pop() - ns = ns + fsm.input_symbol - fsm.memory.append (ns) - -def DoBackOne (fsm): - - screen = fsm.memory[0] - screen.cursor_back () - -def DoBack (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_back (count) - -def DoDownOne (fsm): - - screen = fsm.memory[0] - screen.cursor_down () - -def DoDown (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_down (count) - -def DoForwardOne (fsm): - - screen = fsm.memory[0] - screen.cursor_forward () - -def DoForward (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_forward (count) - -def DoUpReverse (fsm): - - screen = fsm.memory[0] - screen.cursor_up_reverse() - -def DoUpOne (fsm): - - screen = fsm.memory[0] - screen.cursor_up () - -def DoUp (fsm): - - count = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_up (count) - -def DoHome (fsm): - - c = int(fsm.memory.pop()) - r = int(fsm.memory.pop()) - screen = fsm.memory[0] - screen.cursor_home (r,c) - -def DoHomeOrigin (fsm): - - c = 1 - r = 1 - screen = fsm.memory[0] - screen.cursor_home (r,c) - -def DoEraseDown (fsm): - - screen = fsm.memory[0] - screen.erase_down() - -def DoErase (fsm): - - arg = int(fsm.memory.pop()) - screen = fsm.memory[0] - if arg == 0: - screen.erase_down() - elif arg == 1: - screen.erase_up() - elif arg == 2: - screen.erase_screen() - -def DoEraseEndOfLine (fsm): - - screen = fsm.memory[0] - screen.erase_end_of_line() - -def DoEraseLine (fsm): - - arg = int(fsm.memory.pop()) - screen = fsm.memory[0] - if arg == 0: - screen.erase_end_of_line() - elif arg == 1: - screen.erase_start_of_line() - elif arg == 2: - screen.erase_line() - -def DoEnableScroll (fsm): - - screen = fsm.memory[0] - screen.scroll_screen() - -def DoCursorSave (fsm): - - screen = fsm.memory[0] - screen.cursor_save_attrs() - -def DoCursorRestore (fsm): - - screen = fsm.memory[0] - screen.cursor_restore_attrs() - -def DoScrollRegion (fsm): - - screen = fsm.memory[0] - r2 = int(fsm.memory.pop()) - r1 = int(fsm.memory.pop()) - screen.scroll_screen_rows (r1,r2) - -def DoMode (fsm): - - screen = fsm.memory[0] - mode = fsm.memory.pop() # Should be 4 - # screen.setReplaceMode () - -def DoLog (fsm): - - screen = fsm.memory[0] - fsm.memory = [screen] - fout = open ('log', 'a') - fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n') - fout.close() - -class term (screen.screen): - - '''This class is an abstract, generic terminal. - This does nothing. This is a placeholder that - provides a common base class for other terminals - such as an ANSI terminal. ''' - - def __init__ (self, r=24, c=80): - - screen.screen.__init__(self, r,c) - -class ANSI (term): - '''This class implements an ANSI (VT100) terminal. - It is a stream filter that recognizes ANSI terminal - escape sequences and maintains the state of a screen object. ''' - - def __init__ (self, r=24,c=80): - - term.__init__(self,r,c) - - #self.screen = screen (24,80) - self.state = FSM.FSM ('INIT',[self]) - self.state.set_default_transition (DoLog, 'INIT') - self.state.add_transition_any ('INIT', DoEmit, 'INIT') - self.state.add_transition ('\x1b', 'INIT', None, 'ESC') - self.state.add_transition_any ('ESC', DoLog, 'INIT') - self.state.add_transition ('(', 'ESC', None, 'G0SCS') - self.state.add_transition (')', 'ESC', None, 'G1SCS') - self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT') - self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT') - self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT') - self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT') - self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT') - self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT') - self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT') - self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad. - self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND') - self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT') - self.state.add_transition ('[', 'ESC', None, 'ELB') - # ELB means Escape Left Bracket. That is ^[[ - self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT') - self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT') - self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT') - self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT') - self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT') - self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT') - self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT') - self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT') - self.state.add_transition ('m', 'ELB', None, 'INIT') - self.state.add_transition ('?', 'ELB', None, 'MODECRAP') - self.state.add_transition_list (string.digits, 'ELB', DoStartNumber, 'NUMBER_1') - self.state.add_transition_list (string.digits, 'NUMBER_1', DoBuildNumber, 'NUMBER_1') - self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT') - self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT') - self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT') - self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT') - self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT') - self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT') - self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT') - ### It gets worse... the 'm' code can have infinite number of - ### number;number;number before it. I've never seen more than two, - ### but the specs say it's allowed. crap! - self.state.add_transition ('m', 'NUMBER_1', None, 'INIT') - ### LED control. Same implementation problem as 'm' code. - self.state.add_transition ('q', 'NUMBER_1', None, 'INIT') - - # \E[?47h switch to alternate screen - # \E[?47l restores to normal screen from alternate screen. - self.state.add_transition_list (string.digits, 'MODECRAP', DoStartNumber, 'MODECRAP_NUM') - self.state.add_transition_list (string.digits, 'MODECRAP_NUM', DoBuildNumber, 'MODECRAP_NUM') - self.state.add_transition ('l', 'MODECRAP_NUM', None, 'INIT') - self.state.add_transition ('h', 'MODECRAP_NUM', None, 'INIT') - -#RM Reset Mode Esc [ Ps l none - self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON') - self.state.add_transition_any ('SEMICOLON', DoLog, 'INIT') - self.state.add_transition_list (string.digits, 'SEMICOLON', DoStartNumber, 'NUMBER_2') - self.state.add_transition_list (string.digits, 'NUMBER_2', DoBuildNumber, 'NUMBER_2') - self.state.add_transition_any ('NUMBER_2', DoLog, 'INIT') - self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT') - self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT') - self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT') - ### It gets worse... the 'm' code can have infinite number of - ### number;number;number before it. I've never seen more than two, - ### but the specs say it's allowed. crap! - self.state.add_transition ('m', 'NUMBER_2', None, 'INIT') - ### LED control. Same problem as 'm' code. - self.state.add_transition ('q', 'NUMBER_2', None, 'INIT') - self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X') - - # Create a state for 'q' and 'm' which allows an infinite number of ignored numbers - self.state.add_transition_any ('SEMICOLON_X', DoLog, 'INIT') - self.state.add_transition_list (string.digits, 'SEMICOLON_X', None, 'NUMBER_X') - self.state.add_transition_any ('NUMBER_X', DoLog, 'INIT') - self.state.add_transition ('m', 'NUMBER_X', None, 'INIT') - self.state.add_transition ('q', 'NUMBER_X', None, 'INIT') - self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X') - - def process (self, c): - """Process a single byte. Called by :meth:`write`.""" - self.state.process(c) - - def process_list (self, l): - - self.write(l) - - def write (self, s): - """Process text, writing it to the virtual screen while handling - ANSI escape codes. - """ - for c in s: - self.process(c) - - def flush (self): - pass - - def write_ch (self, ch): - '''This puts a character at the current cursor position. The cursor - position is moved forward with wrap-around, but no scrolling is done if - the cursor hits the lower-right corner of the screen. ''' - - #\r and \n both produce a call to cr() and lf(), respectively. - ch = ch[0] - - if ch == '\r': - self.cr() - return - if ch == '\n': - self.crlf() - return - if ch == chr(screen.BS): - self.cursor_back() - return - if ch not in string.printable: - fout = open ('log', 'a') - fout.write ('Nonprint: ' + str(ord(ch)) + '\n') - fout.close() - return - self.put_abs(self.cur_r, self.cur_c, ch) - old_r = self.cur_r - old_c = self.cur_c - self.cursor_forward() - if old_c == self.cur_c: - self.cursor_down() - if old_r != self.cur_r: - self.cursor_home (self.cur_r, 1) - else: - self.scroll_up () - self.cursor_home (self.cur_r, 1) - self.erase_line() diff --git a/awx/lib/site-packages/pexpect/FSM.py b/awx/lib/site-packages/pexpect/FSM.py deleted file mode 100644 index 46b392ea08..0000000000 --- a/awx/lib/site-packages/pexpect/FSM.py +++ /dev/null @@ -1,334 +0,0 @@ -#!/usr/bin/env python - -'''This module implements a Finite State Machine (FSM). In addition to state -this FSM also maintains a user defined "memory". So this FSM can be used as a -Push-down Automata (PDA) since a PDA is a FSM + memory. - -The following describes how the FSM works, but you will probably also need to -see the example function to understand how the FSM is used in practice. - -You define an FSM by building tables of transitions. For a given input symbol -the process() method uses these tables to decide what action to call and what -the next state will be. The FSM has a table of transitions that associate: - - (input_symbol, current_state) --> (action, next_state) - -Where "action" is a function you define. The symbols and states can be any -objects. You use the add_transition() and add_transition_list() methods to add -to the transition table. The FSM also has a table of transitions that -associate: - - (current_state) --> (action, next_state) - -You use the add_transition_any() method to add to this transition table. The -FSM also has one default transition that is not associated with any specific -input_symbol or state. You use the set_default_transition() method to set the -default transition. - -When an action function is called it is passed a reference to the FSM. The -action function may then access attributes of the FSM such as input_symbol, -current_state, or "memory". The "memory" attribute can be any object that you -want to pass along to the action functions. It is not used by the FSM itself. -For parsing you would typically pass a list to be used as a stack. - -The processing sequence is as follows. The process() method is given an -input_symbol to process. The FSM will search the table of transitions that -associate: - - (input_symbol, current_state) --> (action, next_state) - -If the pair (input_symbol, current_state) is found then process() will call the -associated action function and then set the current state to the next_state. - -If the FSM cannot find a match for (input_symbol, current_state) it will then -search the table of transitions that associate: - - (current_state) --> (action, next_state) - -If the current_state is found then the process() method will call the -associated action function and then set the current state to the next_state. -Notice that this table lacks an input_symbol. It lets you define transitions -for a current_state and ANY input_symbol. Hence, it is called the "any" table. -Remember, it is always checked after first searching the table for a specific -(input_symbol, current_state). - -For the case where the FSM did not match either of the previous two cases the -FSM will try to use the default transition. If the default transition is -defined then the process() method will call the associated action function and -then set the current state to the next_state. This lets you define a default -transition as a catch-all case. You can think of it as an exception handler. -There can be only one default transition. - -Finally, if none of the previous cases are defined for an input_symbol and -current_state then the FSM will raise an exception. This may be desirable, but -you can always prevent this just by defining a default transition. - -Noah Spurrier 20020822 - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -class ExceptionFSM(Exception): - - '''This is the FSM Exception class.''' - - def __init__(self, value): - self.value = value - - def __str__(self): - return 'ExceptionFSM: ' + str(self.value) - -class FSM: - - '''This is a Finite State Machine (FSM). - ''' - - def __init__(self, initial_state, memory=None): - - '''This creates the FSM. You set the initial state here. The "memory" - attribute is any object that you want to pass along to the action - functions. It is not used by the FSM. For parsing you would typically - pass a list to be used as a stack. ''' - - # Map (input_symbol, current_state) --> (action, next_state). - self.state_transitions = {} - # Map (current_state) --> (action, next_state). - self.state_transitions_any = {} - self.default_transition = None - - self.input_symbol = None - self.initial_state = initial_state - self.current_state = self.initial_state - self.next_state = None - self.action = None - self.memory = memory - - def reset (self): - - '''This sets the current_state to the initial_state and sets - input_symbol to None. The initial state was set by the constructor - __init__(). ''' - - self.current_state = self.initial_state - self.input_symbol = None - - def add_transition (self, input_symbol, state, action=None, next_state=None): - - '''This adds a transition that associates: - - (input_symbol, current_state) --> (action, next_state) - - The action may be set to None in which case the process() method will - ignore the action and only set the next_state. The next_state may be - set to None in which case the current state will be unchanged. - - You can also set transitions for a list of symbols by using - add_transition_list(). ''' - - if next_state is None: - next_state = state - self.state_transitions[(input_symbol, state)] = (action, next_state) - - def add_transition_list (self, list_input_symbols, state, action=None, next_state=None): - - '''This adds the same transition for a list of input symbols. - You can pass a list or a string. Note that it is handy to use - string.digits, string.whitespace, string.letters, etc. to add - transitions that match character classes. - - The action may be set to None in which case the process() method will - ignore the action and only set the next_state. The next_state may be - set to None in which case the current state will be unchanged. ''' - - if next_state is None: - next_state = state - for input_symbol in list_input_symbols: - self.add_transition (input_symbol, state, action, next_state) - - def add_transition_any (self, state, action=None, next_state=None): - - '''This adds a transition that associates: - - (current_state) --> (action, next_state) - - That is, any input symbol will match the current state. - The process() method checks the "any" state associations after it first - checks for an exact match of (input_symbol, current_state). - - The action may be set to None in which case the process() method will - ignore the action and only set the next_state. The next_state may be - set to None in which case the current state will be unchanged. ''' - - if next_state is None: - next_state = state - self.state_transitions_any [state] = (action, next_state) - - def set_default_transition (self, action, next_state): - - '''This sets the default transition. This defines an action and - next_state if the FSM cannot find the input symbol and the current - state in the transition list and if the FSM cannot find the - current_state in the transition_any list. This is useful as a final - fall-through state for catching errors and undefined states. - - The default transition can be removed by setting the attribute - default_transition to None. ''' - - self.default_transition = (action, next_state) - - def get_transition (self, input_symbol, state): - - '''This returns (action, next state) given an input_symbol and state. - This does not modify the FSM state, so calling this method has no side - effects. Normally you do not call this method directly. It is called by - process(). - - The sequence of steps to check for a defined transition goes from the - most specific to the least specific. - - 1. Check state_transitions[] that match exactly the tuple, - (input_symbol, state) - - 2. Check state_transitions_any[] that match (state) - In other words, match a specific state and ANY input_symbol. - - 3. Check if the default_transition is defined. - This catches any input_symbol and any state. - This is a handler for errors, undefined states, or defaults. - - 4. No transition was defined. If we get here then raise an exception. - ''' - - if (input_symbol, state) in self.state_transitions: - return self.state_transitions[(input_symbol, state)] - elif state in self.state_transitions_any: - return self.state_transitions_any[state] - elif self.default_transition is not None: - return self.default_transition - else: - raise ExceptionFSM ('Transition is undefined: (%s, %s).' % - (str(input_symbol), str(state)) ) - - def process (self, input_symbol): - - '''This is the main method that you call to process input. This may - cause the FSM to change state and call an action. This method calls - get_transition() to find the action and next_state associated with the - input_symbol and current_state. If the action is None then the action - is not called and only the current state is changed. This method - processes one complete input symbol. You can process a list of symbols - (or a string) by calling process_list(). ''' - - self.input_symbol = input_symbol - (self.action, self.next_state) = self.get_transition (self.input_symbol, self.current_state) - if self.action is not None: - self.action (self) - self.current_state = self.next_state - self.next_state = None - - def process_list (self, input_symbols): - - '''This takes a list and sends each element to process(). The list may - be a string or any iterable object. ''' - - for s in input_symbols: - self.process (s) - -############################################################################## -# The following is an example that demonstrates the use of the FSM class to -# process an RPN expression. Run this module from the command line. You will -# get a prompt > for input. Enter an RPN Expression. Numbers may be integers. -# Operators are * / + - Use the = sign to evaluate and print the expression. -# For example: -# -# 167 3 2 2 * * * 1 - = -# -# will print: -# -# 2003 -############################################################################## - -import sys -import string - -PY3 = (sys.version_info[0] >= 3) - -# -# These define the actions. -# Note that "memory" is a list being used as a stack. -# - -def BeginBuildNumber (fsm): - fsm.memory.append (fsm.input_symbol) - -def BuildNumber (fsm): - s = fsm.memory.pop () - s = s + fsm.input_symbol - fsm.memory.append (s) - -def EndBuildNumber (fsm): - s = fsm.memory.pop () - fsm.memory.append (int(s)) - -def DoOperator (fsm): - ar = fsm.memory.pop() - al = fsm.memory.pop() - if fsm.input_symbol == '+': - fsm.memory.append (al + ar) - elif fsm.input_symbol == '-': - fsm.memory.append (al - ar) - elif fsm.input_symbol == '*': - fsm.memory.append (al * ar) - elif fsm.input_symbol == '/': - fsm.memory.append (al / ar) - -def DoEqual (fsm): - print(str(fsm.memory.pop())) - -def Error (fsm): - print('That does not compute.') - print(str(fsm.input_symbol)) - -def main(): - - '''This is where the example starts and the FSM state transitions are - defined. Note that states are strings (such as 'INIT'). This is not - necessary, but it makes the example easier to read. ''' - - f = FSM ('INIT', []) - f.set_default_transition (Error, 'INIT') - f.add_transition_any ('INIT', None, 'INIT') - f.add_transition ('=', 'INIT', DoEqual, 'INIT') - f.add_transition_list (string.digits, 'INIT', BeginBuildNumber, 'BUILDING_NUMBER') - f.add_transition_list (string.digits, 'BUILDING_NUMBER', BuildNumber, 'BUILDING_NUMBER') - f.add_transition_list (string.whitespace, 'BUILDING_NUMBER', EndBuildNumber, 'INIT') - f.add_transition_list ('+-*/', 'INIT', DoOperator, 'INIT') - - print() - print('Enter an RPN Expression.') - print('Numbers may be integers. Operators are * / + -') - print('Use the = sign to evaluate and print the expression.') - print('For example: ') - print(' 167 3 2 2 * * * 1 - =') - inputstr = (input if PY3 else raw_input)('> ') # analysis:ignore - f.process_list(inputstr) - - -if __name__ == '__main__': - main() diff --git a/awx/lib/site-packages/pexpect/__init__.py b/awx/lib/site-packages/pexpect/__init__.py deleted file mode 100644 index a6fb8751db..0000000000 --- a/awx/lib/site-packages/pexpect/__init__.py +++ /dev/null @@ -1,2051 +0,0 @@ -'''Pexpect is a Python module for spawning child applications and controlling -them automatically. Pexpect can be used for automating interactive applications -such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup -scripts for duplicating software package installations on different servers. It -can be used for automated software testing. Pexpect is in the spirit of Don -Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python -require TCL and Expect or require C extensions to be compiled. Pexpect does not -use C, Expect, or TCL extensions. It should work on any platform that supports -the standard Python pty module. The Pexpect interface focuses on ease of use so -that simple tasks are easy. - -There are two main interfaces to the Pexpect system; these are the function, -run() and the class, spawn. The spawn class is more powerful. The run() -function is simpler than spawn, and is good for quickly calling program. When -you call the run() function it executes a given program and then returns the -output. This is a handy replacement for os.system(). - -For example:: - - pexpect.run('ls -la') - -The spawn class is the more powerful interface to the Pexpect system. You can -use this to spawn a child program then interact with it by sending input and -expecting responses (waiting for patterns in the child's output). - -For example:: - - child = pexpect.spawn('scp foo user@example.com:.') - child.expect('Password:') - child.sendline(mypassword) - -This works even for commands that ask for passwords or other input outside of -the normal stdio streams. For example, ssh reads input directly from the TTY -device which bypasses stdin. - -Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett, -Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids -vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin, -Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey, -Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume -Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John -Spiegel, Jan Grant, and Shane Kerr. Let me know if I forgot anyone. - -Pexpect is free, open source, and all that good stuff. -http://pexpect.sourceforge.net/ - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -try: - import os - import sys - import time - import select - import re - import struct - import resource - import types - import pty - import tty - import termios - import fcntl - import errno - import traceback - import signal - import codecs -except ImportError: # pragma: no cover - err = sys.exc_info()[1] - raise ImportError(str(err) + ''' - -A critical module was not found. Probably this operating system does not -support it. Pexpect is intended for UNIX-like operating systems.''') - -__version__ = '3.1' -__revision__ = '' -__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu', - 'which', 'split_command_line', '__version__', '__revision__'] - -PY3 = (sys.version_info[0] >= 3) - -# Exception classes used by this module. -class ExceptionPexpect(Exception): - '''Base class for all exceptions raised by this module. - ''' - - def __init__(self, value): - super(ExceptionPexpect, self).__init__(value) - self.value = value - - def __str__(self): - return str(self.value) - - def get_trace(self): - '''This returns an abbreviated stack trace with lines that only concern - the caller. In other words, the stack trace inside the Pexpect module - is not included. ''' - - tblist = traceback.extract_tb(sys.exc_info()[2]) - tblist = [item for item in tblist if 'pexpect/__init__' not in item[0]] - tblist = traceback.format_list(tblist) - return ''.join(tblist) - - -class EOF(ExceptionPexpect): - '''Raised when EOF is read from a child. - This usually means the child has exited.''' - - -class TIMEOUT(ExceptionPexpect): - '''Raised when a read time exceeds the timeout. ''' - -##class TIMEOUT_PATTERN(TIMEOUT): -## '''Raised when the pattern match time exceeds the timeout. -## This is different than a read TIMEOUT because the child process may -## give output, thus never give a TIMEOUT, but the output -## may never match a pattern. -## ''' -##class MAXBUFFER(ExceptionPexpect): -## '''Raised when a buffer fills before matching an expected pattern.''' - - -def run(command, timeout=-1, withexitstatus=False, events=None, - extra_args=None, logfile=None, cwd=None, env=None): - - ''' - This function runs the given command; waits for it to finish; then - returns all output as a string. STDERR is included in output. If the full - path to the command is not given then the path is searched. - - Note that lines are terminated by CR/LF (\\r\\n) combination even on - UNIX-like systems because this is the standard for pseudottys. If you set - 'withexitstatus' to true, then run will return a tuple of (command_output, - exitstatus). If 'withexitstatus' is false then this returns just - command_output. - - The run() function can often be used instead of creating a spawn instance. - For example, the following code uses spawn:: - - from pexpect import * - child = spawn('scp foo user@example.com:.') - child.expect('(?i)password') - child.sendline(mypassword) - - The previous code can be replace with the following:: - - from pexpect import * - run('scp foo user@example.com:.', events={'(?i)password': mypassword}) - - **Examples** - - Start the apache daemon on the local machine:: - - from pexpect import * - run("/usr/local/apache/bin/apachectl start") - - Check in a file using SVN:: - - from pexpect import * - run("svn ci -m 'automatic commit' my_file.py") - - Run a command and capture exit status:: - - from pexpect import * - (command_output, exitstatus) = run('ls -l /bin', withexitstatus=1) - - The following will run SSH and execute 'ls -l' on the remote machine. The - password 'secret' will be sent if the '(?i)password' pattern is ever seen:: - - run("ssh username@machine.example.com 'ls -l'", - events={'(?i)password':'secret\\n'}) - - This will start mencoder to rip a video from DVD. This will also display - progress ticks every 5 seconds as it runs. For example:: - - from pexpect import * - def print_ticks(d): - print d['event_count'], - run("mencoder dvd://1 -o video.avi -oac copy -ovc copy", - events={TIMEOUT:print_ticks}, timeout=5) - - The 'events' argument should be a dictionary of patterns and responses. - Whenever one of the patterns is seen in the command out run() will send the - associated response string. Note that you should put newlines in your - string if Enter is necessary. The responses may also contain callback - functions. Any callback is function that takes a dictionary as an argument. - The dictionary contains all the locals from the run() function, so you can - access the child spawn object or any other variable defined in run() - (event_count, child, and extra_args are the most useful). A callback may - return True to stop the current run process otherwise run() continues until - the next event. A callback may also return a string which will be sent to - the child. 'extra_args' is not used by directly run(). It provides a way to - pass data to a callback function through run() through the locals - dictionary passed to a callback. - ''' - return _run(command, timeout=timeout, withexitstatus=withexitstatus, - events=events, extra_args=extra_args, logfile=logfile, cwd=cwd, - env=env, _spawn=spawn) - -def runu(command, timeout=-1, withexitstatus=False, events=None, - extra_args=None, logfile=None, cwd=None, env=None, **kwargs): - """This offers the same interface as :func:`run`, but using unicode. - - Like :class:`spawnu`, you can pass ``encoding`` and ``errors`` parameters, - which will be used for both input and output. - """ - return _run(command, timeout=timeout, withexitstatus=withexitstatus, - events=events, extra_args=extra_args, logfile=logfile, cwd=cwd, - env=env, _spawn=spawnu, **kwargs) - -def _run(command, timeout, withexitstatus, events, extra_args, logfile, cwd, - env, _spawn, **kwargs): - if timeout == -1: - child = _spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env, - **kwargs) - else: - child = _spawn(command, timeout=timeout, maxread=2000, logfile=logfile, - cwd=cwd, env=env, **kwargs) - if events is not None: - patterns = list(events.keys()) - responses = list(events.values()) - else: - # This assumes EOF or TIMEOUT will eventually cause run to terminate. - patterns = None - responses = None - child_result_list = [] - event_count = 0 - while True: - try: - index = child.expect(patterns) - if isinstance(child.after, child.allowed_string_types): - child_result_list.append(child.before + child.after) - else: - # child.after may have been a TIMEOUT or EOF, - # which we don't want appended to the list. - child_result_list.append(child.before) - if isinstance(responses[index], child.allowed_string_types): - child.send(responses[index]) - elif isinstance(responses[index], types.FunctionType): - callback_result = responses[index](locals()) - sys.stdout.flush() - if isinstance(callback_result, child.allowed_string_types): - child.send(callback_result) - elif callback_result: - break - else: - raise TypeError('The callback must be a string or function.') - event_count = event_count + 1 - except TIMEOUT: - child_result_list.append(child.before) - break - except EOF: - child_result_list.append(child.before) - break - child_result = child.string_type().join(child_result_list) - if withexitstatus: - child.close() - return (child_result, child.exitstatus) - else: - return child_result - -class spawn(object): - '''This is the main class interface for Pexpect. Use this class to start - and control child applications. ''' - string_type = bytes - if PY3: - allowed_string_types = (bytes, str) - @staticmethod - def _chr(c): - return bytes([c]) - linesep = os.linesep.encode('ascii') - - @staticmethod - def write_to_stdout(b): - try: - return sys.stdout.buffer.write(b) - except AttributeError: - # If stdout has been replaced, it may not have .buffer - return sys.stdout.write(b.decode('ascii', 'replace')) - else: - allowed_string_types = (basestring,) # analysis:ignore - _chr = staticmethod(chr) - linesep = os.linesep - write_to_stdout = sys.stdout.write - - encoding = None - - def __init__(self, command, args=[], timeout=30, maxread=2000, - searchwindowsize=None, logfile=None, cwd=None, env=None, - ignore_sighup=True): - - '''This is the constructor. The command parameter may be a string that - includes a command and any arguments to the command. For example:: - - child = pexpect.spawn('/usr/bin/ftp') - child = pexpect.spawn('/usr/bin/ssh user@example.com') - child = pexpect.spawn('ls -latr /tmp') - - You may also construct it with a list of arguments like so:: - - child = pexpect.spawn('/usr/bin/ftp', []) - child = pexpect.spawn('/usr/bin/ssh', ['user@example.com']) - child = pexpect.spawn('ls', ['-latr', '/tmp']) - - After this the child application will be created and will be ready to - talk to. For normal use, see expect() and send() and sendline(). - - Remember that Pexpect does NOT interpret shell meta characters such as - redirect, pipe, or wild cards (``>``, ``|``, or ``*``). This is a - common mistake. If you want to run a command and pipe it through - another command then you must also start a shell. For example:: - - child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"') - child.expect(pexpect.EOF) - - The second form of spawn (where you pass a list of arguments) is useful - in situations where you wish to spawn a command and pass it its own - argument list. This can make syntax more clear. For example, the - following is equivalent to the previous example:: - - shell_cmd = 'ls -l | grep LOG > logs.txt' - child = pexpect.spawn('/bin/bash', ['-c', shell_cmd]) - child.expect(pexpect.EOF) - - The maxread attribute sets the read buffer size. This is maximum number - of bytes that Pexpect will try to read from a TTY at one time. Setting - the maxread size to 1 will turn off buffering. Setting the maxread - value higher may help performance in cases where large amounts of - output are read back from the child. This feature is useful in - conjunction with searchwindowsize. - - The searchwindowsize attribute sets the how far back in the incoming - seach buffer Pexpect will search for pattern matches. Every time - Pexpect reads some data from the child it will append the data to the - incoming buffer. The default is to search from the beginning of the - incoming buffer each time new data is read from the child. But this is - very inefficient if you are running a command that generates a large - amount of data where you want to match. The searchwindowsize does not - affect the size of the incoming data buffer. You will still have - access to the full buffer after expect() returns. - - The logfile member turns on or off logging. All input and output will - be copied to the given file object. Set logfile to None to stop - logging. This is the default. Set logfile to sys.stdout to echo - everything to standard output. The logfile is flushed after each write. - - Example log input and output to a file:: - - child = pexpect.spawn('some_command') - fout = file('mylog.txt','w') - child.logfile = fout - - Example log to stdout:: - - child = pexpect.spawn('some_command') - child.logfile = sys.stdout - - The logfile_read and logfile_send members can be used to separately log - the input from the child and output sent to the child. Sometimes you - don't want to see everything you write to the child. You only want to - log what the child sends back. For example:: - - child = pexpect.spawn('some_command') - child.logfile_read = sys.stdout - - To separately log output sent to the child use logfile_send:: - - self.logfile_send = fout - - If ``ignore_sighup`` is True, the child process will ignore SIGHUP - signals. For now, the default is True, to preserve the behaviour of - earlier versions of Pexpect, but you should pass this explicitly if you - want to rely on it. - - The delaybeforesend helps overcome a weird behavior that many users - were experiencing. The typical problem was that a user would expect() a - "Password:" prompt and then immediately call sendline() to send the - password. The user would then see that their password was echoed back - to them. Passwords don't normally echo. The problem is caused by the - fact that most applications print out the "Password" prompt and then - turn off stdin echo, but if you send your password before the - application turned off echo, then you get your password echoed. - Normally this wouldn't be a problem when interacting with a human at a - real keyboard. If you introduce a slight delay just before writing then - this seems to clear up the problem. This was such a common problem for - many users that I decided that the default pexpect behavior should be - to sleep just before writing to the child application. 1/20th of a - second (50 ms) seems to be enough to clear up the problem. You can set - delaybeforesend to 0 to return to the old behavior. Most Linux machines - don't like this to be below 0.03. I don't know why. - - Note that spawn is clever about finding commands on your path. - It uses the same logic that "which" uses to find executables. - - If you wish to get the exit status of the child you must call the - close() method. The exit or signal status of the child will be stored - in self.exitstatus or self.signalstatus. If the child exited normally - then exitstatus will store the exit return code and signalstatus will - be None. If the child was terminated abnormally with a signal then - signalstatus will store the signal value and exitstatus will be None. - If you need more detail you can also read the self.status member which - stores the status returned by os.waitpid. You can interpret this using - os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. ''' - - self.STDIN_FILENO = pty.STDIN_FILENO - self.STDOUT_FILENO = pty.STDOUT_FILENO - self.STDERR_FILENO = pty.STDERR_FILENO - self.stdin = sys.stdin - self.stdout = sys.stdout - self.stderr = sys.stderr - - self.searcher = None - self.ignorecase = False - self.before = None - self.after = None - self.match = None - self.match_index = None - self.terminated = True - self.exitstatus = None - self.signalstatus = None - # status returned by os.waitpid - self.status = None - self.flag_eof = False - self.pid = None - # the chile filedescriptor is initially closed - self.child_fd = -1 - self.timeout = timeout - self.delimiter = EOF - self.logfile = logfile - # input from child (read_nonblocking) - self.logfile_read = None - # output to send (send, sendline) - self.logfile_send = None - # max bytes to read at one time into buffer - self.maxread = maxread - # This is the read buffer. See maxread. - self.buffer = self.string_type() - # Data before searchwindowsize point is preserved, but not searched. - self.searchwindowsize = searchwindowsize - # Delay used before sending data to child. Time in seconds. - # Most Linux machines don't like this to be below 0.03 (30 ms). - self.delaybeforesend = 0.05 - # Used by close() to give kernel time to update process status. - # Time in seconds. - self.delayafterclose = 0.1 - # Used by terminate() to give kernel time to update process status. - # Time in seconds. - self.delayafterterminate = 0.1 - self.softspace = False - self.name = '<' + repr(self) + '>' - self.closed = True - self.cwd = cwd - self.env = env - self.ignore_sighup = ignore_sighup - # This flags if we are running on irix - self.__irix_hack = (sys.platform.lower().find('irix') >= 0) - # Solaris uses internal __fork_pty(). All others use pty.fork(). - if ((sys.platform.lower().find('solaris') >= 0) - or (sys.platform.lower().find('sunos5') >= 0)): - self.use_native_pty_fork = False - else: - self.use_native_pty_fork = True - - # Support subclasses that do not use command or args. - if command is None: - self.command = None - self.args = None - self.name = '' - else: - self._spawn(command, args) - - @staticmethod - def _coerce_expect_string(s): - if not isinstance(s, bytes): - return s.encode('ascii') - return s - - @staticmethod - def _coerce_send_string(s): - if not isinstance(s, bytes): - return s.encode('utf-8') - return s - - @staticmethod - def _coerce_read_string(s): - return s - - def __del__(self): - '''This makes sure that no system resources are left open. Python only - garbage collects Python objects. OS file descriptors are not Python - objects, so they must be handled explicitly. If the child file - descriptor was opened outside of this class (passed to the constructor) - then this does not close it. ''' - - if not self.closed: - # It is possible for __del__ methods to execute during the - # teardown of the Python VM itself. Thus self.close() may - # trigger an exception because os.close may be None. - try: - self.close() - # which exception, shouldnt' we catch explicitly .. ? - except: - pass - - def __str__(self): - '''This returns a human-readable string that represents the state of - the object. ''' - - s = [] - s.append(repr(self)) - s.append('version: ' + __version__) - s.append('command: ' + str(self.command)) - s.append('args: %r' % (self.args,)) - s.append('searcher: %r' % (self.searcher,)) - s.append('buffer (last 100 chars): %r' % (self.buffer)[-100:],) - s.append('before (last 100 chars): %r' % (self.before)[-100:],) - s.append('after: %r' % (self.after,)) - s.append('match: %r' % (self.match,)) - s.append('match_index: ' + str(self.match_index)) - s.append('exitstatus: ' + str(self.exitstatus)) - s.append('flag_eof: ' + str(self.flag_eof)) - s.append('pid: ' + str(self.pid)) - s.append('child_fd: ' + str(self.child_fd)) - s.append('closed: ' + str(self.closed)) - s.append('timeout: ' + str(self.timeout)) - s.append('delimiter: ' + str(self.delimiter)) - s.append('logfile: ' + str(self.logfile)) - s.append('logfile_read: ' + str(self.logfile_read)) - s.append('logfile_send: ' + str(self.logfile_send)) - s.append('maxread: ' + str(self.maxread)) - s.append('ignorecase: ' + str(self.ignorecase)) - s.append('searchwindowsize: ' + str(self.searchwindowsize)) - s.append('delaybeforesend: ' + str(self.delaybeforesend)) - s.append('delayafterclose: ' + str(self.delayafterclose)) - s.append('delayafterterminate: ' + str(self.delayafterterminate)) - return '\n'.join(s) - - def _spawn(self, command, args=[]): - '''This starts the given command in a child process. This does all the - fork/exec type of stuff for a pty. This is called by __init__. If args - is empty then command will be parsed (split on spaces) and args will be - set to parsed arguments. ''' - - # The pid and child_fd of this object get set by this method. - # Note that it is difficult for this method to fail. - # You cannot detect if the child process cannot start. - # So the only way you can tell if the child process started - # or not is to try to read from the file descriptor. If you get - # EOF immediately then it means that the child is already dead. - # That may not necessarily be bad because you may have spawned a child - # that performs some task; creates no stdout output; and then dies. - - # If command is an int type then it may represent a file descriptor. - if isinstance(command, type(0)): - raise ExceptionPexpect('Command is an int type. ' + - 'If this is a file descriptor then maybe you want to ' + - 'use fdpexpect.fdspawn which takes an existing ' + - 'file descriptor instead of a command string.') - - if not isinstance(args, type([])): - raise TypeError('The argument, args, must be a list.') - - if args == []: - self.args = split_command_line(command) - self.command = self.args[0] - else: - # Make a shallow copy of the args list. - self.args = args[:] - self.args.insert(0, command) - self.command = command - - command_with_path = which(self.command) - if command_with_path is None: - raise ExceptionPexpect('The command was not found or was not ' + - 'executable: %s.' % self.command) - self.command = command_with_path - self.args[0] = self.command - - self.name = '<' + ' '.join(self.args) + '>' - - assert self.pid is None, 'The pid member must be None.' - assert self.command is not None, 'The command member must not be None.' - - if self.use_native_pty_fork: - try: - self.pid, self.child_fd = pty.fork() - except OSError: - err = sys.exc_info()[1] - raise ExceptionPexpect('pty.fork() failed: ' + str(err)) - else: - # Use internal __fork_pty - self.pid, self.child_fd = self.__fork_pty() - - if self.pid == 0: - # Child - try: - # used by setwinsize() - self.child_fd = sys.stdout.fileno() - self.setwinsize(24, 80) - # which exception, shouldnt' we catch explicitly .. ? - except: - # Some platforms do not like setwinsize (Cygwin). - # This will cause problem when running applications that - # are very picky about window size. - # This is a serious limitation, but not a show stopper. - pass - # Do not allow child to inherit open file descriptors from parent. - max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0] - for i in range(3, max_fd): - try: - os.close(i) - except OSError: - pass - - if self.ignore_sighup: - signal.signal(signal.SIGHUP, signal.SIG_IGN) - - if self.cwd is not None: - os.chdir(self.cwd) - if self.env is None: - os.execv(self.command, self.args) - else: - os.execvpe(self.command, self.args, self.env) - - # Parent - self.terminated = False - self.closed = False - - def __fork_pty(self): - '''This implements a substitute for the forkpty system call. This - should be more portable than the pty.fork() function. Specifically, - this should work on Solaris. - - Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to - resolve the issue with Python's pty.fork() not supporting Solaris, - particularly ssh. Based on patch to posixmodule.c authored by Noah - Spurrier:: - - http://mail.python.org/pipermail/python-dev/2003-May/035281.html - - ''' - - parent_fd, child_fd = os.openpty() - if parent_fd < 0 or child_fd < 0: - raise ExceptionPexpect("Could not open with os.openpty().") - - pid = os.fork() - if pid < 0: - raise ExceptionPexpect("Failed os.fork().") - elif pid == 0: - # Child. - os.close(parent_fd) - self.__pty_make_controlling_tty(child_fd) - - os.dup2(child_fd, 0) - os.dup2(child_fd, 1) - os.dup2(child_fd, 2) - - if child_fd > 2: - os.close(child_fd) - else: - # Parent. - os.close(child_fd) - - return pid, parent_fd - - def __pty_make_controlling_tty(self, tty_fd): - '''This makes the pseudo-terminal the controlling tty. This should be - more portable than the pty.fork() function. Specifically, this should - work on Solaris. ''' - - child_name = os.ttyname(tty_fd) - - # Disconnect from controlling tty. Harmless if not already connected. - try: - fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) - if fd >= 0: - os.close(fd) - # which exception, shouldnt' we catch explicitly .. ? - except: - # Already disconnected. This happens if running inside cron. - pass - - os.setsid() - - # Verify we are disconnected from controlling tty - # by attempting to open it again. - try: - fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) - if fd >= 0: - os.close(fd) - raise ExceptionPexpect('Failed to disconnect from ' + - 'controlling tty. It is still possible to open /dev/tty.') - # which exception, shouldnt' we catch explicitly .. ? - except: - # Good! We are disconnected from a controlling tty. - pass - - # Verify we can open child pty. - fd = os.open(child_name, os.O_RDWR) - if fd < 0: - raise ExceptionPexpect("Could not open child pty, " + child_name) - else: - os.close(fd) - - # Verify we now have a controlling tty. - fd = os.open("/dev/tty", os.O_WRONLY) - if fd < 0: - raise ExceptionPexpect("Could not open controlling tty, /dev/tty") - else: - os.close(fd) - - def fileno(self): - '''This returns the file descriptor of the pty for the child. - ''' - return self.child_fd - - def close(self, force=True): - '''This closes the connection with the child application. Note that - calling close() more than once is valid. This emulates standard Python - behavior with files. Set force to True if you want to make sure that - the child is terminated (SIGKILL is sent if the child ignores SIGHUP - and SIGINT). ''' - - if not self.closed: - self.flush() - os.close(self.child_fd) - # Give kernel time to update process status. - time.sleep(self.delayafterclose) - if self.isalive(): - if not self.terminate(force): - raise ExceptionPexpect('Could not terminate the child.') - self.child_fd = -1 - self.closed = True - #self.pid = None - - def flush(self): - '''This does nothing. It is here to support the interface for a - File-like object. ''' - - pass - - def isatty(self): - '''This returns True if the file descriptor is open and connected to a - tty(-like) device, else False. ''' - - return os.isatty(self.child_fd) - - def waitnoecho(self, timeout=-1): - '''This waits until the terminal ECHO flag is set False. This returns - True if the echo mode is off. This returns False if the ECHO flag was - not set False before the timeout. This can be used to detect when the - child is waiting for a password. Usually a child application will turn - off echo mode when it is waiting for the user to enter a password. For - example, instead of expecting the "password:" prompt you can wait for - the child to set ECHO off:: - - p = pexpect.spawn('ssh user@example.com') - p.waitnoecho() - p.sendline(mypassword) - - If timeout==-1 then this method will use the value in self.timeout. - If timeout==None then this method to block until ECHO flag is False. - ''' - - if timeout == -1: - timeout = self.timeout - if timeout is not None: - end_time = time.time() + timeout - while True: - if not self.getecho(): - return True - if timeout < 0 and timeout is not None: - return False - if timeout is not None: - timeout = end_time - time.time() - time.sleep(0.1) - - def getecho(self): - '''This returns the terminal echo mode. This returns True if echo is - on or False if echo is off. Child applications that are expecting you - to enter a password often set ECHO False. See waitnoecho(). ''' - - attr = termios.tcgetattr(self.child_fd) - if attr[3] & termios.ECHO: - return True - return False - - def setecho(self, state): - '''This sets the terminal echo mode on or off. Note that anything the - child sent before the echo will be lost, so you should be sure that - your input buffer is empty before you call setecho(). For example, the - following will work as expected:: - - p = pexpect.spawn('cat') # Echo is on by default. - p.sendline('1234') # We expect see this twice from the child... - p.expect(['1234']) # ... once from the tty echo... - p.expect(['1234']) # ... and again from cat itself. - p.setecho(False) # Turn off tty echo - p.sendline('abcd') # We will set this only once (echoed by cat). - p.sendline('wxyz') # We will set this only once (echoed by cat) - p.expect(['abcd']) - p.expect(['wxyz']) - - The following WILL NOT WORK because the lines sent before the setecho - will be lost:: - - p = pexpect.spawn('cat') - p.sendline('1234') - p.setecho(False) # Turn off tty echo - p.sendline('abcd') # We will set this only once (echoed by cat). - p.sendline('wxyz') # We will set this only once (echoed by cat) - p.expect(['1234']) - p.expect(['1234']) - p.expect(['abcd']) - p.expect(['wxyz']) - ''' - - self.child_fd - attr = termios.tcgetattr(self.child_fd) - if state: - attr[3] = attr[3] | termios.ECHO - else: - attr[3] = attr[3] & ~termios.ECHO - # I tried TCSADRAIN and TCSAFLUSH, but - # these were inconsistent and blocked on some platforms. - # TCSADRAIN would probably be ideal if it worked. - termios.tcsetattr(self.child_fd, termios.TCSANOW, attr) - - def _log(self, s, direction): - if self.logfile is not None: - self.logfile.write(s) - self.logfile.flush() - second_log = self.logfile_send if (direction=='send') else self.logfile_read - if second_log is not None: - second_log.write(s) - second_log.flush() - - def read_nonblocking(self, size=1, timeout=-1): - '''This reads at most size characters from the child application. It - includes a timeout. If the read does not complete within the timeout - period then a TIMEOUT exception is raised. If the end of file is read - then an EOF exception will be raised. If a log file was set using - setlog() then all data will also be written to the log file. - - If timeout is None then the read may block indefinitely. - If timeout is -1 then the self.timeout value is used. If timeout is 0 - then the child is polled and if there is no data immediately ready - then this will raise a TIMEOUT exception. - - The timeout refers only to the amount of time to read at least one - character. This is not effected by the 'size' parameter, so if you call - read_nonblocking(size=100, timeout=30) and only one character is - available right away then one character will be returned immediately. - It will not wait for 30 seconds for another 99 characters to come in. - - This is a wrapper around os.read(). It uses select.select() to - implement the timeout. ''' - - if self.closed: - raise ValueError('I/O operation on closed file.') - - if timeout == -1: - timeout = self.timeout - - # Note that some systems such as Solaris do not give an EOF when - # the child dies. In fact, you can still try to read - # from the child_fd -- it will block forever or until TIMEOUT. - # For this case, I test isalive() before doing any reading. - # If isalive() is false, then I pretend that this is the same as EOF. - if not self.isalive(): - # timeout of 0 means "poll" - r, w, e = self.__select([self.child_fd], [], [], 0) - if not r: - self.flag_eof = True - raise EOF('End Of File (EOF). Braindead platform.') - elif self.__irix_hack: - # Irix takes a long time before it realizes a child was terminated. - # FIXME So does this mean Irix systems are forced to always have - # FIXME a 2 second delay when calling read_nonblocking? That sucks. - r, w, e = self.__select([self.child_fd], [], [], 2) - if not r and not self.isalive(): - self.flag_eof = True - raise EOF('End Of File (EOF). Slow platform.') - - r, w, e = self.__select([self.child_fd], [], [], timeout) - - if not r: - if not self.isalive(): - # Some platforms, such as Irix, will claim that their - # processes are alive; timeout on the select; and - # then finally admit that they are not alive. - self.flag_eof = True - raise EOF('End of File (EOF). Very slow platform.') - else: - raise TIMEOUT('Timeout exceeded.') - - if self.child_fd in r: - try: - s = os.read(self.child_fd, size) - except OSError: - # Linux does this - self.flag_eof = True - raise EOF('End Of File (EOF). Exception style platform.') - if s == b'': - # BSD style - self.flag_eof = True - raise EOF('End Of File (EOF). Empty string style platform.') - - s = self._coerce_read_string(s) - self._log(s, 'read') - return s - - raise ExceptionPexpect('Reached an unexpected state.') - - def read(self, size=-1): - '''This reads at most "size" bytes from the file (less if the read hits - EOF before obtaining size bytes). If the size argument is negative or - omitted, read all data until EOF is reached. The bytes are returned as - a string object. An empty string is returned when EOF is encountered - immediately. ''' - - if size == 0: - return self.string_type() - if size < 0: - # delimiter default is EOF - self.expect(self.delimiter) - return self.before - - # I could have done this more directly by not using expect(), but - # I deliberately decided to couple read() to expect() so that - # I would catch any bugs early and ensure consistant behavior. - # It's a little less efficient, but there is less for me to - # worry about if I have to later modify read() or expect(). - # Note, it's OK if size==-1 in the regex. That just means it - # will never match anything in which case we stop only on EOF. - cre = re.compile(self._coerce_expect_string('.{%d}' % size), re.DOTALL) - # delimiter default is EOF - index = self.expect([cre, self.delimiter]) - if index == 0: - ### FIXME self.before should be ''. Should I assert this? - return self.after - return self.before - - def readline(self, size=-1): - '''This reads and returns one entire line. The newline at the end of - line is returned as part of the string, unless the file ends without a - newline. An empty string is returned if EOF is encountered immediately. - This looks for a newline as a CR/LF pair (\\r\\n) even on UNIX because - this is what the pseudotty device returns. So contrary to what you may - expect you will receive newlines as \\r\\n. - - If the size argument is 0 then an empty string is returned. In all - other cases the size argument is ignored, which is not standard - behavior for a file-like object. ''' - - if size == 0: - return self.string_type() - # delimiter default is EOF - index = self.expect([b'\r\n', self.delimiter]) - if index == 0: - return self.before + b'\r\n' - else: - return self.before - - def __iter__(self): - '''This is to support iterators over a file-like object. - ''' - return iter(self.readline, self.string_type()) - - def readlines(self, sizehint=-1): - '''This reads until EOF using readline() and returns a list containing - the lines thus read. The optional 'sizehint' argument is ignored. - Remember, because this reads until EOF that means the child - process should have closed its stdout. If you run this method on - a child that is still running with its stdout open then this - method will block until it timesout.''' - - lines = [] - while True: - line = self.readline() - if not line: - break - lines.append(line) - return lines - - def write(self, s): - '''This is similar to send() except that there is no return value. - ''' - - self.send(s) - - def writelines(self, sequence): - '''This calls write() for each element in the sequence. The sequence - can be any iterable object producing strings, typically a list of - strings. This does not add line separators. There is no return value. - ''' - - for s in sequence: - self.write(s) - - def send(self, s): - '''Sends string ``s`` to the child process, returning the number of - bytes written. If a logfile is specified, a copy is written to that - log. ''' - - time.sleep(self.delaybeforesend) - - s = self._coerce_send_string(s) - self._log(s, 'send') - - return self._send(s) - - def _send(self, s): - return os.write(self.child_fd, s) - - def sendline(self, s=''): - '''Wraps send(), sending string ``s`` to child process, with os.linesep - automatically appended. Returns number of bytes written. ''' - - n = self.send(s) - n = n + self.send(self.linesep) - return n - - def sendcontrol(self, char): - - '''Helper method that wraps send() with mnemonic access for sending control - character to the child (such as Ctrl-C or Ctrl-D). For example, to send - Ctrl-G (ASCII 7, bell, '\a'):: - - child.sendcontrol('g') - - See also, sendintr() and sendeof(). - ''' - - char = char.lower() - a = ord(char) - if a >= 97 and a <= 122: - a = a - ord('a') + 1 - return self.send(self._chr(a)) - d = {'@': 0, '`': 0, - '[': 27, '{': 27, - '\\': 28, '|': 28, - ']': 29, '}': 29, - '^': 30, '~': 30, - '_': 31, - '?': 127} - if char not in d: - return 0 - return self.send(self._chr(d[char])) - - def sendeof(self): - - '''This sends an EOF to the child. This sends a character which causes - the pending parent output buffer to be sent to the waiting child - program without waiting for end-of-line. If it is the first character - of the line, the read() in the user program returns 0, which signifies - end-of-file. This means to work as expected a sendeof() has to be - called at the beginning of a line. This method does not send a newline. - It is the responsibility of the caller to ensure the eof is sent at the - beginning of a line. ''' - - ### Hmmm... how do I send an EOF? - ###C if ((m = write(pty, *buf, p - *buf)) < 0) - ###C return (errno == EWOULDBLOCK) ? n : -1; - #fd = sys.stdin.fileno() - #old = termios.tcgetattr(fd) # remember current state - #attr = termios.tcgetattr(fd) - #attr[3] = attr[3] | termios.ICANON # ICANON must be set to see EOF - #try: # use try/finally to ensure state gets restored - # termios.tcsetattr(fd, termios.TCSADRAIN, attr) - # if hasattr(termios, 'CEOF'): - # os.write(self.child_fd, '%c' % termios.CEOF) - # else: - # # Silly platform does not define CEOF so assume CTRL-D - # os.write(self.child_fd, '%c' % 4) - #finally: # restore state - # termios.tcsetattr(fd, termios.TCSADRAIN, old) - if hasattr(termios, 'VEOF'): - char = ord(termios.tcgetattr(self.child_fd)[6][termios.VEOF]) - else: - # platform does not define VEOF so assume CTRL-D - char = 4 - self.send(self._chr(char)) - - def sendintr(self): - - '''This sends a SIGINT to the child. It does not require - the SIGINT to be the first character on a line. ''' - - if hasattr(termios, 'VINTR'): - char = ord(termios.tcgetattr(self.child_fd)[6][termios.VINTR]) - else: - # platform does not define VINTR so assume CTRL-C - char = 3 - self.send(self._chr(char)) - - def eof(self): - - '''This returns True if the EOF exception was ever raised. - ''' - - return self.flag_eof - - def terminate(self, force=False): - - '''This forces a child process to terminate. It starts nicely with - SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This - returns True if the child was terminated. This returns False if the - child could not be terminated. ''' - - if not self.isalive(): - return True - try: - self.kill(signal.SIGHUP) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - self.kill(signal.SIGCONT) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - self.kill(signal.SIGINT) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - if force: - self.kill(signal.SIGKILL) - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - else: - return False - return False - except OSError: - # I think there are kernel timing issues that sometimes cause - # this to happen. I think isalive() reports True, but the - # process is dead to the kernel. - # Make one last attempt to see if the kernel is up to date. - time.sleep(self.delayafterterminate) - if not self.isalive(): - return True - else: - return False - - def wait(self): - - '''This waits until the child exits. This is a blocking call. This will - not read any data from the child, so this will block forever if the - child has unread output and has terminated. In other words, the child - may have printed output then called exit(), but, the child is - technically still alive until its output is read by the parent. ''' - - if self.isalive(): - pid, status = os.waitpid(self.pid, 0) - else: - raise ExceptionPexpect('Cannot wait for dead child process.') - self.exitstatus = os.WEXITSTATUS(status) - if os.WIFEXITED(status): - self.status = status - self.exitstatus = os.WEXITSTATUS(status) - self.signalstatus = None - self.terminated = True - elif os.WIFSIGNALED(status): - self.status = status - self.exitstatus = None - self.signalstatus = os.WTERMSIG(status) - self.terminated = True - elif os.WIFSTOPPED(status): - # You can't call wait() on a child process in the stopped state. - raise ExceptionPexpect('Called wait() on a stopped child ' + - 'process. This is not supported. Is some other ' + - 'process attempting job control with our child pid?') - return self.exitstatus - - def isalive(self): - - '''This tests if the child process is running or not. This is - non-blocking. If the child was terminated then this will read the - exitstatus or signalstatus of the child. This returns True if the child - process appears to be running or False if not. It can take literally - SECONDS for Solaris to return the right status. ''' - - if self.terminated: - return False - - if self.flag_eof: - # This is for Linux, which requires the blocking form - # of waitpid to # get status of a defunct process. - # This is super-lame. The flag_eof would have been set - # in read_nonblocking(), so this should be safe. - waitpid_options = 0 - else: - waitpid_options = os.WNOHANG - - try: - pid, status = os.waitpid(self.pid, waitpid_options) - except OSError: - err = sys.exc_info()[1] - # No child processes - if err.errno == errno.ECHILD: - raise ExceptionPexpect('isalive() encountered condition ' + - 'where "terminated" is 0, but there was no child ' + - 'process. Did someone else call waitpid() ' + - 'on our process?') - else: - raise err - - # I have to do this twice for Solaris. - # I can't even believe that I figured this out... - # If waitpid() returns 0 it means that no child process - # wishes to report, and the value of status is undefined. - if pid == 0: - try: - ### os.WNOHANG) # Solaris! - pid, status = os.waitpid(self.pid, waitpid_options) - except OSError as e: - # This should never happen... - if e.errno == errno.ECHILD: - raise ExceptionPexpect('isalive() encountered condition ' + - 'that should never happen. There was no child ' + - 'process. Did someone else call waitpid() ' + - 'on our process?') - else: - raise - - # If pid is still 0 after two calls to waitpid() then the process - # really is alive. This seems to work on all platforms, except for - # Irix which seems to require a blocking call on waitpid or select, - # so I let read_nonblocking take care of this situation - # (unfortunately, this requires waiting through the timeout). - if pid == 0: - return True - - if pid == 0: - return True - - if os.WIFEXITED(status): - self.status = status - self.exitstatus = os.WEXITSTATUS(status) - self.signalstatus = None - self.terminated = True - elif os.WIFSIGNALED(status): - self.status = status - self.exitstatus = None - self.signalstatus = os.WTERMSIG(status) - self.terminated = True - elif os.WIFSTOPPED(status): - raise ExceptionPexpect('isalive() encountered condition ' + - 'where child process is stopped. This is not ' + - 'supported. Is some other process attempting ' + - 'job control with our child pid?') - return False - - def kill(self, sig): - - '''This sends the given signal to the child application. In keeping - with UNIX tradition it has a misleading name. It does not necessarily - kill the child unless you send the right signal. ''' - - # Same as os.kill, but the pid is given for you. - if self.isalive(): - os.kill(self.pid, sig) - - def _pattern_type_err(self, pattern): - raise TypeError('got {badtype} ({badobj!r}) as pattern, must be one' - ' of: {goodtypes}, pexpect.EOF, pexpect.TIMEOUT'\ - .format(badtype=type(pattern), - badobj=pattern, - goodtypes=', '.join([str(ast)\ - for ast in self.allowed_string_types]) - ) - ) - - def compile_pattern_list(self, patterns): - - '''This compiles a pattern-string or a list of pattern-strings. - Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of - those. Patterns may also be None which results in an empty list (you - might do this if waiting for an EOF or TIMEOUT condition without - expecting any pattern). - - This is used by expect() when calling expect_list(). Thus expect() is - nothing more than:: - - cpl = self.compile_pattern_list(pl) - return self.expect_list(cpl, timeout) - - If you are using expect() within a loop it may be more - efficient to compile the patterns first and then call expect_list(). - This avoid calls in a loop to compile_pattern_list():: - - cpl = self.compile_pattern_list(my_pattern) - while some_condition: - ... - i = self.expect_list(clp, timeout) - ... - ''' - - if patterns is None: - return [] - if not isinstance(patterns, list): - patterns = [patterns] - - # Allow dot to match \n - compile_flags = re.DOTALL - if self.ignorecase: - compile_flags = compile_flags | re.IGNORECASE - compiled_pattern_list = [] - for idx, p in enumerate(patterns): - if isinstance(p, self.allowed_string_types): - p = self._coerce_expect_string(p) - compiled_pattern_list.append(re.compile(p, compile_flags)) - elif p is EOF: - compiled_pattern_list.append(EOF) - elif p is TIMEOUT: - compiled_pattern_list.append(TIMEOUT) - elif isinstance(p, type(re.compile(''))): - compiled_pattern_list.append(p) - else: - self._pattern_type_err(p) - return compiled_pattern_list - - def expect(self, pattern, timeout=-1, searchwindowsize=-1): - - '''This seeks through the stream until a pattern is matched. The - pattern is overloaded and may take several types. The pattern can be a - StringType, EOF, a compiled re, or a list of any of those types. - Strings will be compiled to re types. This returns the index into the - pattern list. If the pattern was not a list this returns index 0 on a - successful match. This may raise exceptions for EOF or TIMEOUT. To - avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern - list. That will cause expect to match an EOF or TIMEOUT condition - instead of raising an exception. - - If you pass a list of patterns and more than one matches, the first - match in the stream is chosen. If more than one pattern matches at that - point, the leftmost in the pattern list is chosen. For example:: - - # the input is 'foobar' - index = p.expect(['bar', 'foo', 'foobar']) - # returns 1('foo') even though 'foobar' is a "better" match - - Please note, however, that buffering can affect this behavior, since - input arrives in unpredictable chunks. For example:: - - # the input is 'foobar' - index = p.expect(['foobar', 'foo']) - # returns 0('foobar') if all input is available at once, - # but returs 1('foo') if parts of the final 'bar' arrive late - - After a match is found the instance attributes 'before', 'after' and - 'match' will be set. You can see all the data read before the match in - 'before'. You can see the data that was matched in 'after'. The - re.MatchObject used in the re match will be in 'match'. If an error - occurred then 'before' will be set to all the data read so far and - 'after' and 'match' will be None. - - If timeout is -1 then timeout will be set to the self.timeout value. - - A list entry may be EOF or TIMEOUT instead of a string. This will - catch these exceptions and return the index of the list entry instead - of raising the exception. The attribute 'after' will be set to the - exception type. The attribute 'match' will be None. This allows you to - write code like this:: - - index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT]) - if index == 0: - do_something() - elif index == 1: - do_something_else() - elif index == 2: - do_some_other_thing() - elif index == 3: - do_something_completely_different() - - instead of code like this:: - - try: - index = p.expect(['good', 'bad']) - if index == 0: - do_something() - elif index == 1: - do_something_else() - except EOF: - do_some_other_thing() - except TIMEOUT: - do_something_completely_different() - - These two forms are equivalent. It all depends on what you want. You - can also just expect the EOF if you are waiting for all output of a - child to finish. For example:: - - p = pexpect.spawn('/bin/ls') - p.expect(pexpect.EOF) - print p.before - - If you are trying to optimize for speed then see expect_list(). - ''' - - compiled_pattern_list = self.compile_pattern_list(pattern) - return self.expect_list(compiled_pattern_list, - timeout, searchwindowsize) - - def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1): - - '''This takes a list of compiled regular expressions and returns the - index into the pattern_list that matched the child output. The list may - also contain EOF or TIMEOUT(which are not compiled regular - expressions). This method is similar to the expect() method except that - expect_list() does not recompile the pattern list on every call. This - may help if you are trying to optimize for speed, otherwise just use - the expect() method. This is called by expect(). If timeout==-1 then - the self.timeout value is used. If searchwindowsize==-1 then the - self.searchwindowsize value is used. ''' - - return self.expect_loop(searcher_re(pattern_list), - timeout, searchwindowsize) - - def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1): - - '''This is similar to expect(), but uses plain string matching instead - of compiled regular expressions in 'pattern_list'. The 'pattern_list' - may be a string; a list or other sequence of strings; or TIMEOUT and - EOF. - - This call might be faster than expect() for two reasons: string - searching is faster than RE matching and it is possible to limit the - search to just the end of the input buffer. - - This method is also useful when you don't want to have to worry about - escaping regular expression characters that you want to match.''' - - if (isinstance(pattern_list, self.allowed_string_types) or - pattern_list in (TIMEOUT, EOF)): - pattern_list = [pattern_list] - - def prepare_pattern(pattern): - if pattern in (TIMEOUT, EOF): - return pattern - if isinstance(pattern, self.allowed_string_types): - return self._coerce_expect_string(pattern) - self._pattern_type_err(pattern) - - try: - pattern_list = iter(pattern_list) - except TypeError: - self._pattern_type_err(pattern_list) - pattern_list = [prepare_pattern(p) for p in pattern_list] - return self.expect_loop(searcher_string(pattern_list), - timeout, searchwindowsize) - - def expect_loop(self, searcher, timeout=-1, searchwindowsize=-1): - - '''This is the common loop used inside expect. The 'searcher' should be - an instance of searcher_re or searcher_string, which describes how and - what to search for in the input. - - See expect() for other arguments, return value and exceptions. ''' - - self.searcher = searcher - - if timeout == -1: - timeout = self.timeout - if timeout is not None: - end_time = time.time() + timeout - if searchwindowsize == -1: - searchwindowsize = self.searchwindowsize - - try: - incoming = self.buffer - freshlen = len(incoming) - while True: - # Keep reading until exception or return. - index = searcher.search(incoming, freshlen, searchwindowsize) - if index >= 0: - self.buffer = incoming[searcher.end:] - self.before = incoming[: searcher.start] - self.after = incoming[searcher.start: searcher.end] - self.match = searcher.match - self.match_index = index - return self.match_index - # No match at this point - if (timeout is not None) and (timeout < 0): - raise TIMEOUT('Timeout exceeded in expect_any().') - # Still have time left, so read more data - c = self.read_nonblocking(self.maxread, timeout) - freshlen = len(c) - time.sleep(0.0001) - incoming = incoming + c - if timeout is not None: - timeout = end_time - time.time() - except EOF: - err = sys.exc_info()[1] - self.buffer = self.string_type() - self.before = incoming - self.after = EOF - index = searcher.eof_index - if index >= 0: - self.match = EOF - self.match_index = index - return self.match_index - else: - self.match = None - self.match_index = None - raise EOF(str(err) + '\n' + str(self)) - except TIMEOUT: - err = sys.exc_info()[1] - self.buffer = incoming - self.before = incoming - self.after = TIMEOUT - index = searcher.timeout_index - if index >= 0: - self.match = TIMEOUT - self.match_index = index - return self.match_index - else: - self.match = None - self.match_index = None - raise TIMEOUT(str(err) + '\n' + str(self)) - except: - self.before = incoming - self.after = None - self.match = None - self.match_index = None - raise - - def getwinsize(self): - - '''This returns the terminal window size of the child tty. The return - value is a tuple of (rows, cols). ''' - - TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912) - s = struct.pack('HHHH', 0, 0, 0, 0) - x = fcntl.ioctl(self.child_fd, TIOCGWINSZ, s) - return struct.unpack('HHHH', x)[0:2] - - def setwinsize(self, rows, cols): - - '''This sets the terminal window size of the child tty. This will cause - a SIGWINCH signal to be sent to the child. This does not change the - physical window size. It changes the size reported to TTY-aware - applications like vi or curses -- applications that respond to the - SIGWINCH signal. ''' - - # Check for buggy platforms. Some Python versions on some platforms - # (notably OSF1 Alpha and RedHat 7.1) truncate the value for - # termios.TIOCSWINSZ. It is not clear why this happens. - # These platforms don't seem to handle the signed int very well; - # yet other platforms like OpenBSD have a large negative value for - # TIOCSWINSZ and they don't have a truncate problem. - # Newer versions of Linux have totally different values for TIOCSWINSZ. - # Note that this fix is a hack. - TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561) - if TIOCSWINSZ == 2148037735: - # Same bits, but with sign. - TIOCSWINSZ = -2146929561 - # Note, assume ws_xpixel and ws_ypixel are zero. - s = struct.pack('HHHH', rows, cols, 0, 0) - fcntl.ioctl(self.fileno(), TIOCSWINSZ, s) - - def interact(self, escape_character=chr(29), - input_filter=None, output_filter=None): - - '''This gives control of the child process to the interactive user (the - human at the keyboard). Keystrokes are sent to the child process, and - the stdout and stderr output of the child process is printed. This - simply echos the child stdout and child stderr to the real stdout and - it echos the real stdin to the child stdin. When the user types the - escape_character this method will stop. The default for - escape_character is ^]. This should not be confused with ASCII 27 -- - the ESC character. ASCII 29 was chosen for historical merit because - this is the character used by 'telnet' as the escape character. The - escape_character will not be sent to the child process. - - You may pass in optional input and output filter functions. These - functions should take a string and return a string. The output_filter - will be passed all the output from the child process. The input_filter - will be passed all the keyboard input from the user. The input_filter - is run BEFORE the check for the escape_character. - - Note that if you change the window size of the parent the SIGWINCH - signal will not be passed through to the child. If you want the child - window size to change when the parent's window size changes then do - something like the following example:: - - import pexpect, struct, fcntl, termios, signal, sys - def sigwinch_passthrough (sig, data): - s = struct.pack("HHHH", 0, 0, 0, 0) - a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), - termios.TIOCGWINSZ , s)) - global p - p.setwinsize(a[0],a[1]) - # Note this 'p' global and used in sigwinch_passthrough. - p = pexpect.spawn('/bin/bash') - signal.signal(signal.SIGWINCH, sigwinch_passthrough) - p.interact() - ''' - - # Flush the buffer. - self.write_to_stdout(self.buffer) - self.stdout.flush() - self.buffer = self.string_type() - mode = tty.tcgetattr(self.STDIN_FILENO) - tty.setraw(self.STDIN_FILENO) - if PY3: - escape_character = escape_character.encode('latin-1') - try: - self.__interact_copy(escape_character, input_filter, output_filter) - finally: - tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode) - - def __interact_writen(self, fd, data): - '''This is used by the interact() method. - ''' - - while data != b'' and self.isalive(): - n = os.write(fd, data) - data = data[n:] - - def __interact_read(self, fd): - '''This is used by the interact() method. - ''' - - return os.read(fd, 1000) - - def __interact_copy(self, escape_character=None, - input_filter=None, output_filter=None): - - '''This is used by the interact() method. - ''' - - while self.isalive(): - r, w, e = self.__select([self.child_fd, self.STDIN_FILENO], [], []) - if self.child_fd in r: - try: - data = self.__interact_read(self.child_fd) - except OSError as e: - # The subprocess may have closed before we get to reading it - if e.errno != errno.EIO: - raise - if output_filter: - data = output_filter(data) - if self.logfile is not None: - self.logfile.write(data) - self.logfile.flush() - os.write(self.STDOUT_FILENO, data) - if self.STDIN_FILENO in r: - data = self.__interact_read(self.STDIN_FILENO) - if input_filter: - data = input_filter(data) - i = data.rfind(escape_character) - if i != -1: - data = data[:i] - self.__interact_writen(self.child_fd, data) - break - self.__interact_writen(self.child_fd, data) - - def __select(self, iwtd, owtd, ewtd, timeout=None): - - '''This is a wrapper around select.select() that ignores signals. If - select.select raises a select.error exception and errno is an EINTR - error then it is ignored. Mainly this is used to ignore sigwinch - (terminal resize). ''' - - # if select() is interrupted by a signal (errno==EINTR) then - # we loop back and enter the select() again. - if timeout is not None: - end_time = time.time() + timeout - while True: - try: - return select.select(iwtd, owtd, ewtd, timeout) - except select.error: - err = sys.exc_info()[1] - if err.errno == errno.EINTR: - # if we loop back we have to subtract the - # amount of time we already waited. - if timeout is not None: - timeout = end_time - time.time() - if timeout < 0: - return([], [], []) - else: - # something else caused the select.error, so - # this actually is an exception. - raise - -############################################################################## -# The following methods are no longer supported or allowed. - - def setmaxread(self, maxread): - - '''This method is no longer supported or allowed. I don't like getters - and setters without a good reason. ''' - - raise ExceptionPexpect('This method is no longer supported ' + - 'or allowed. Just assign a value to the ' + - 'maxread member variable.') - - def setlog(self, fileobject): - - '''This method is no longer supported or allowed. - ''' - - raise ExceptionPexpect('This method is no longer supported ' + - 'or allowed. Just assign a value to the logfile ' + - 'member variable.') - -############################################################################## -# End of spawn class -############################################################################## - -class spawnu(spawn): - """Works like spawn, but accepts and returns unicode strings. - - Extra parameters: - - :param encoding: The encoding to use for communications (default: 'utf-8') - :param errors: How to handle encoding/decoding errors; one of 'strict' - (the default), 'ignore', or 'replace', as described - for :meth:`~bytes.decode` and :meth:`~str.encode`. - """ - if PY3: - string_type = str - allowed_string_types = (str, ) - _chr = staticmethod(chr) - linesep = os.linesep - else: - string_type = unicode - allowed_string_types = (unicode, ) - _chr = staticmethod(unichr) - linesep = os.linesep.decode('ascii') - # This can handle unicode in both Python 2 and 3 - write_to_stdout = sys.stdout.write - - def __init__(self, *args, **kwargs): - self.encoding = kwargs.pop('encoding', 'utf-8') - self.errors = kwargs.pop('errors', 'strict') - self._decoder = codecs.getincrementaldecoder(self.encoding)(errors=self.errors) - super(spawnu, self).__init__(*args, **kwargs) - - @staticmethod - def _coerce_expect_string(s): - return s - - @staticmethod - def _coerce_send_string(s): - return s - - def _coerce_read_string(self, s): - return self._decoder.decode(s, final=False) - - def _send(self, s): - return os.write(self.child_fd, s.encode(self.encoding, self.errors)) - - -class searcher_string(object): - - '''This is a plain string search helper for the spawn.expect_any() method. - This helper class is for speed. For more powerful regex patterns - see the helper class, searcher_re. - - Attributes: - - eof_index - index of EOF, or -1 - timeout_index - index of TIMEOUT, or -1 - - After a successful match by the search() method the following attributes - are available: - - start - index into the buffer, first byte of match - end - index into the buffer, first byte after match - match - the matching string itself - - ''' - - def __init__(self, strings): - - '''This creates an instance of searcher_string. This argument 'strings' - may be a list; a sequence of strings; or the EOF or TIMEOUT types. ''' - - self.eof_index = -1 - self.timeout_index = -1 - self._strings = [] - for n, s in enumerate(strings): - if s is EOF: - self.eof_index = n - continue - if s is TIMEOUT: - self.timeout_index = n - continue - self._strings.append((n, s)) - - def __str__(self): - - '''This returns a human-readable string that represents the state of - the object.''' - - ss = [(ns[0], ' %d: "%s"' % ns) for ns in self._strings] - ss.append((-1, 'searcher_string:')) - if self.eof_index >= 0: - ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) - if self.timeout_index >= 0: - ss.append((self.timeout_index, - ' %d: TIMEOUT' % self.timeout_index)) - ss.sort() - ss = list(zip(*ss))[1] - return '\n'.join(ss) - - def search(self, buffer, freshlen, searchwindowsize=None): - - '''This searches 'buffer' for the first occurence of one of the search - strings. 'freshlen' must indicate the number of bytes at the end of - 'buffer' which have not been searched before. It helps to avoid - searching the same, possibly big, buffer over and over again. - - See class spawn for the 'searchwindowsize' argument. - - If there is a match this returns the index of that string, and sets - 'start', 'end' and 'match'. Otherwise, this returns -1. ''' - - first_match = None - - # 'freshlen' helps a lot here. Further optimizations could - # possibly include: - # - # using something like the Boyer-Moore Fast String Searching - # Algorithm; pre-compiling the search through a list of - # strings into something that can scan the input once to - # search for all N strings; realize that if we search for - # ['bar', 'baz'] and the input is '...foo' we need not bother - # rescanning until we've read three more bytes. - # - # Sadly, I don't know enough about this interesting topic. /grahn - - for index, s in self._strings: - if searchwindowsize is None: - # the match, if any, can only be in the fresh data, - # or at the very end of the old data - offset = -(freshlen + len(s)) - else: - # better obey searchwindowsize - offset = -searchwindowsize - n = buffer.find(s, offset) - if n >= 0 and (first_match is None or n < first_match): - first_match = n - best_index, best_match = index, s - if first_match is None: - return -1 - self.match = best_match - self.start = first_match - self.end = self.start + len(self.match) - return best_index - - -class searcher_re(object): - - '''This is regular expression string search helper for the - spawn.expect_any() method. This helper class is for powerful - pattern matching. For speed, see the helper class, searcher_string. - - Attributes: - - eof_index - index of EOF, or -1 - timeout_index - index of TIMEOUT, or -1 - - After a successful match by the search() method the following attributes - are available: - - start - index into the buffer, first byte of match - end - index into the buffer, first byte after match - match - the re.match object returned by a succesful re.search - - ''' - - def __init__(self, patterns): - - '''This creates an instance that searches for 'patterns' Where - 'patterns' may be a list or other sequence of compiled regular - expressions, or the EOF or TIMEOUT types.''' - - self.eof_index = -1 - self.timeout_index = -1 - self._searches = [] - for n, s in zip(list(range(len(patterns))), patterns): - if s is EOF: - self.eof_index = n - continue - if s is TIMEOUT: - self.timeout_index = n - continue - self._searches.append((n, s)) - - def __str__(self): - - '''This returns a human-readable string that represents the state of - the object.''' - - #ss = [(n, ' %d: re.compile("%s")' % - # (n, repr(s.pattern))) for n, s in self._searches] - ss = list() - for n, s in self._searches: - try: - ss.append((n, ' %d: re.compile("%s")' % (n, s.pattern))) - except UnicodeEncodeError: - # for test cases that display __str__ of searches, dont throw - # another exception just because stdout is ascii-only, using - # repr() - ss.append((n, ' %d: re.compile(%r)' % (n, s.pattern))) - ss.append((-1, 'searcher_re:')) - if self.eof_index >= 0: - ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) - if self.timeout_index >= 0: - ss.append((self.timeout_index, ' %d: TIMEOUT' % - self.timeout_index)) - ss.sort() - ss = list(zip(*ss))[1] - return '\n'.join(ss) - - def search(self, buffer, freshlen, searchwindowsize=None): - - '''This searches 'buffer' for the first occurence of one of the regular - expressions. 'freshlen' must indicate the number of bytes at the end of - 'buffer' which have not been searched before. - - See class spawn for the 'searchwindowsize' argument. - - If there is a match this returns the index of that string, and sets - 'start', 'end' and 'match'. Otherwise, returns -1.''' - - first_match = None - # 'freshlen' doesn't help here -- we cannot predict the - # length of a match, and the re module provides no help. - if searchwindowsize is None: - searchstart = 0 - else: - searchstart = max(0, len(buffer) - searchwindowsize) - for index, s in self._searches: - match = s.search(buffer, searchstart) - if match is None: - continue - n = match.start() - if first_match is None or n < first_match: - first_match = n - the_match = match - best_index = index - if first_match is None: - return -1 - self.start = first_match - self.match = the_match - self.end = self.match.end() - return best_index - - -def which(filename): - - '''This takes a given filename; tries to find it in the environment path; - then checks if it is executable. This returns the full path to the filename - if found and executable. Otherwise this returns None.''' - - # Special case where filename contains an explicit path. - if os.path.dirname(filename) != '': - if os.access(filename, os.X_OK): - return filename - if 'PATH' not in os.environ or os.environ['PATH'] == '': - p = os.defpath - else: - p = os.environ['PATH'] - pathlist = p.split(os.pathsep) - for path in pathlist: - ff = os.path.join(path, filename) - if os.access(ff, os.X_OK): - return ff - return None - - -def split_command_line(command_line): - - '''This splits a command line into a list of arguments. It splits arguments - on spaces, but handles embedded quotes, doublequotes, and escaped - characters. It's impossible to do this with a regular expression, so I - wrote a little state machine to parse the command line. ''' - - arg_list = [] - arg = '' - - # Constants to name the states we can be in. - state_basic = 0 - state_esc = 1 - state_singlequote = 2 - state_doublequote = 3 - # The state when consuming whitespace between commands. - state_whitespace = 4 - state = state_basic - - for c in command_line: - if state == state_basic or state == state_whitespace: - if c == '\\': - # Escape the next character - state = state_esc - elif c == r"'": - # Handle single quote - state = state_singlequote - elif c == r'"': - # Handle double quote - state = state_doublequote - elif c.isspace(): - # Add arg to arg_list if we aren't in the middle of whitespace. - if state == state_whitespace: - # Do nothing. - None - else: - arg_list.append(arg) - arg = '' - state = state_whitespace - else: - arg = arg + c - state = state_basic - elif state == state_esc: - arg = arg + c - state = state_basic - elif state == state_singlequote: - if c == r"'": - state = state_basic - else: - arg = arg + c - elif state == state_doublequote: - if c == r'"': - state = state_basic - else: - arg = arg + c - - if arg != '': - arg_list.append(arg) - return arg_list - -# vi:set sr et ts=4 sw=4 ft=python : diff --git a/awx/lib/site-packages/pexpect/fdpexpect.py b/awx/lib/site-packages/pexpect/fdpexpect.py deleted file mode 100644 index 8a0da4a868..0000000000 --- a/awx/lib/site-packages/pexpect/fdpexpect.py +++ /dev/null @@ -1,97 +0,0 @@ -'''This is like pexpect, but it will work with any file descriptor that you -pass it. You are reponsible for opening and close the file descriptor. -This allows you to use Pexpect with sockets and named pipes (FIFOs). - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -from pexpect import spawn, ExceptionPexpect -import os - -__all__ = ['fdspawn'] - -class fdspawn (spawn): - - '''This is like pexpect.spawn but allows you to supply your own open file - descriptor. For example, you could use it to read through a file looking - for patterns, or to control a modem or serial device. ''' - - def __init__ (self, fd, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None): - - '''This takes a file descriptor (an int) or an object that support the - fileno() method (returning an int). All Python file-like objects - support fileno(). ''' - - ### TODO: Add better handling of trying to use fdspawn in place of spawn - ### TODO: (overload to allow fdspawn to also handle commands as spawn does. - - if type(fd) != type(0) and hasattr(fd, 'fileno'): - fd = fd.fileno() - - if type(fd) != type(0): - raise ExceptionPexpect('The fd argument is not an int. If this is a command string then maybe you want to use pexpect.spawn.') - - try: # make sure fd is a valid file descriptor - os.fstat(fd) - except OSError: - raise ExceptionPexpect('The fd argument is not a valid file descriptor.') - - self.args = None - self.command = None - spawn.__init__(self, None, args, timeout, maxread, searchwindowsize, logfile) - self.child_fd = fd - self.own_fd = False - self.closed = False - self.name = '' % fd - - def __del__ (self): - return - - def close (self): - """Close the file descriptor. - - Calling this method a second time does nothing, but if the file - descriptor was closed elsewhere, :class:`OSError` will be raised. - """ - if self.child_fd == -1: - return - - self.flush() - os.close(self.child_fd) - self.child_fd = -1 - self.closed = True - - def isalive (self): - '''This checks if the file descriptor is still valid. If :func:`os.fstat` - does not raise an exception then we assume it is alive. ''' - - if self.child_fd == -1: - return False - try: - os.fstat(self.child_fd) - return True - except: - return False - - def terminate (self, force=False): - raise ExceptionPexpect('This method is not valid for file descriptors.') - - def kill (self, sig): - """No-op - no process to kill.""" - return diff --git a/awx/lib/site-packages/pexpect/psh.py b/awx/lib/site-packages/pexpect/psh.py deleted file mode 100644 index e453acdc40..0000000000 --- a/awx/lib/site-packages/pexpect/psh.py +++ /dev/null @@ -1,148 +0,0 @@ -'''This is a utility class to make shell scripting easier in Python. -It combines Pexpect and wraps many Standard Python Library functions -to make them look more shell-like. - -This module is undocumented, so its API is provisional, and may change in -future releases without a deprecation cycle. - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -import pexpect, re - -class ExceptionPsh(pexpect.ExceptionPexpect): - '''Raised for Psh exceptions. - ''' - -class ExceptionErrorCode(ExceptionPsh): - '''Raised when an program returns an error code. - ''' - - def __init__(self, string, err_code, cmd_output): - - ExceptionPsh.__init__(self,string) - self.error = err_code - self.output = cmd_output - -class psh (object): - - def __init__ (self,exp): - - self.exp = exp - self.default_timeout = 30 # Seconds - - def ls (self, path=''): - - fileStr = self.run("ls %s" % path) - return fileStr.split() - - def cd (self, path='-'): - - return self.run("cd %s" % path) - - def rm (self, path=''): - - return self.run("/bin/rm -f %s" % path) - - def cp (self, path_from='', path_to=''): - - return self.run("/bin/cp %s %s" % (path_from, path_to)) - - def mv (self, path_from='', path_to=''): - - return self.run("/bin/mv %s %s" % (path_from, path_to)) - - def pwd (self): - - return self.run("/bin/pwd") - - def which (self, exe_name): - - return self.run("/usr/bin/which %s" % exe_name) - - def chown (self, path, user='', group=None, recurse=False): - - xtra_flags = "" - if recurse: xtra_flags = "-R" - if group: group = ':' + group - else: group = "" - - return self.run("/bin/chown %s %s%s %s" % (xtra_flags,user,group,path)) - - def chmod (self, path, perms='', recurse=False): - - xtra_flags = "" - if recurse: xtra_flags = "-R" - return self.run("/usr/bin/chmod %s %s %s" % (xtra_flags, perms, path)) - - def chattr (self, path, attrs='', recurse=False): - - xtra_flags = "" - if recurse: xtra_flags = "-R" - return self.run("/usr/bin/chattr %s %s %s" % (xtra_flags, attrs, path)) - - def cat (self, path): - - return self.run("/bin/cat %s" % path) - - def run (self, cmd, timeout=None): - - (ret, output) = self.run_raw(cmd, timeout) - if ret == 0: return output - raise ExceptionErrorCode("Running command [%s] returned error [%d]" - % (cmd,ret), ret, output) - - def run_raw(self, cmd, timeout=None): - - '''Someone contributed this, but now I've lost touch and I forget the - motive of this. It was sort of a sketch at the time which doesn't make - this any easier to prioritize, but it seemed important at the time. ''' - - if not timeout: timeout = self.default_timeout - - self.exp.sendline("") - if not self.exp.prompt(): raise ExceptionPsh("No prompt") - self.exp.sendline(cmd) - self.exp.expect_exact([cmd]) - self.exp.prompt(timeout=timeout) - - output = self.exp.before - # Get the return code - self.exp.sendline("echo $?") - self.exp.expect_exact(["echo $?"]) - if not self.exp.prompt(): - raise ExceptionPsh("No prompt", 0, self.exp.before) - try: - reg = re.compile(b"^(\d+)") - s = self.exp.before.strip() - #print s - #pdb.set_trace() - s = reg.search(s).groups()[0] - error_code = int(s) - except ValueError: - #log.error("Cannot parse %s into an int!" % self.exp.before) - raise - - if not output[0:2] == '\r\n': - #log.warning("Returned output lacks leading \\r\\n which may indicate a tae error") - #log.debug2("Offending output string: [%s]" % output) - return (error_code, output) - else: - return(error_code, output[2:]) - diff --git a/awx/lib/site-packages/pexpect/pxssh.py b/awx/lib/site-packages/pexpect/pxssh.py deleted file mode 100644 index a068625121..0000000000 --- a/awx/lib/site-packages/pexpect/pxssh.py +++ /dev/null @@ -1,384 +0,0 @@ -'''This class extends pexpect.spawn to specialize setting up SSH connections. -This adds methods for login, logout, and expecting the shell prompt. - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -from pexpect import ExceptionPexpect, TIMEOUT, EOF, spawn -import time -import os - -__all__ = ['ExceptionPxssh', 'pxssh'] - -# Exception classes used by this module. -class ExceptionPxssh(ExceptionPexpect): - '''Raised for pxssh exceptions. - ''' - -class pxssh (spawn): - '''This class extends pexpect.spawn to specialize setting up SSH - connections. This adds methods for login, logout, and expecting the shell - prompt. It does various tricky things to handle many situations in the SSH - login process. For example, if the session is your first login, then pxssh - automatically accepts the remote certificate; or if you have public key - authentication setup then pxssh won't wait for the password prompt. - - pxssh uses the shell prompt to synchronize output from the remote host. In - order to make this more robust it sets the shell prompt to something more - unique than just $ or #. This should work on most Borne/Bash or Csh style - shells. - - Example that runs a few commands on a remote server and prints the result:: - - import pxssh - import getpass - try: - s = pxssh.pxssh() - hostname = raw_input('hostname: ') - username = raw_input('username: ') - password = getpass.getpass('password: ') - s.login (hostname, username, password) - s.sendline ('uptime') # run a command - s.prompt() # match the prompt - print s.before # print everything before the prompt. - s.sendline ('ls -l') - s.prompt() - print s.before - s.sendline ('df') - s.prompt() - print s.before - s.logout() - except pxssh.ExceptionPxssh, e: - print "pxssh failed on login." - print str(e) - - Note that if you have ssh-agent running while doing development with pxssh - then this can lead to a lot of confusion. Many X display managers (xdm, - gdm, kdm, etc.) will automatically start a GUI agent. You may see a GUI - dialog box popup asking for a password during development. You should turn - off any key agents during testing. The 'force_password' attribute will turn - off public key authentication. This will only work if the remote SSH server - is configured to allow password logins. Example of using 'force_password' - attribute:: - - s = pxssh.pxssh() - s.force_password = True - hostname = raw_input('hostname: ') - username = raw_input('username: ') - password = getpass.getpass('password: ') - s.login (hostname, username, password) - ''' - - def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None): - - spawn.__init__(self, None, timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize, logfile=logfile, cwd=cwd, env=env) - - self.name = '' - - #SUBTLE HACK ALERT! Note that the command that SETS the prompt uses a - #slightly different string than the regular expression to match it. This - #is because when you set the prompt the command will echo back, but we - #don't want to match the echoed command. So if we make the set command - #slightly different than the regex we eliminate the problem. To make the - #set command different we add a backslash in front of $. The $ doesn't - #need to be escaped, but it doesn't hurt and serves to make the set - #prompt command different than the regex. - - # used to match the command-line prompt - self.UNIQUE_PROMPT = "\[PEXPECT\][\$\#] " - self.PROMPT = self.UNIQUE_PROMPT - - # used to set shell command-line prompt to UNIQUE_PROMPT. - self.PROMPT_SET_SH = "PS1='[PEXPECT]\$ '" - self.PROMPT_SET_CSH = "set prompt='[PEXPECT]\$ '" - self.SSH_OPTS = ("-o'RSAAuthentication=no'" - + " -o 'PubkeyAuthentication=no'") -# Disabling host key checking, makes you vulnerable to MITM attacks. -# + " -o 'StrictHostKeyChecking=no'" -# + " -o 'UserKnownHostsFile /dev/null' ") - # Disabling X11 forwarding gets rid of the annoying SSH_ASKPASS from - # displaying a GUI password dialog. I have not figured out how to - # disable only SSH_ASKPASS without also disabling X11 forwarding. - # Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying! - #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'" - self.force_password = False - self.auto_prompt_reset = True - - def levenshtein_distance(self, a,b): - - '''This calculates the Levenshtein distance between a and b. - ''' - - n, m = len(a), len(b) - if n > m: - a,b = b,a - n,m = m,n - current = range(n+1) - for i in range(1,m+1): - previous, current = current, [i]+[0]*n - for j in range(1,n+1): - add, delete = previous[j]+1, current[j-1]+1 - change = previous[j-1] - if a[j-1] != b[i-1]: - change = change + 1 - current[j] = min(add, delete, change) - return current[n] - - def try_read_prompt(self, timeout_multiplier): - - '''This facilitates using communication timeouts to perform - synchronization as quickly as possible, while supporting high latency - connections with a tunable worst case performance. Fast connections - should be read almost immediately. Worst case performance for this - method is timeout_multiplier * 3 seconds. - ''' - - # maximum time allowed to read the first response - first_char_timeout = timeout_multiplier * 0.5 - - # maximum time allowed between subsequent characters - inter_char_timeout = timeout_multiplier * 0.1 - - # maximum time for reading the entire prompt - total_timeout = timeout_multiplier * 3.0 - - prompt = b'' - begin = time.time() - expired = 0.0 - timeout = first_char_timeout - - while expired < total_timeout: - try: - prompt += self.read_nonblocking(size=1, timeout=timeout) - expired = time.time() - begin # updated total time expired - timeout = inter_char_timeout - except TIMEOUT: - break - - return prompt - - def sync_original_prompt (self, sync_multiplier=1.0): - - '''This attempts to find the prompt. Basically, press enter and record - the response; press enter again and record the response; if the two - responses are similar then assume we are at the original prompt. - This can be a slow function. Worst case with the default sync_multiplier - can take 12 seconds. Low latency connections are more likely to fail - with a low sync_multiplier. Best case sync time gets worse with a - high sync multiplier (500 ms with default). ''' - - # All of these timing pace values are magic. - # I came up with these based on what seemed reliable for - # connecting to a heavily loaded machine I have. - self.sendline() - time.sleep(0.1) - - try: - # Clear the buffer before getting the prompt. - self.try_read_prompt(sync_multiplier) - except TIMEOUT: - pass - - self.sendline() - x = self.try_read_prompt(sync_multiplier) - - self.sendline() - a = self.try_read_prompt(sync_multiplier) - - self.sendline() - b = self.try_read_prompt(sync_multiplier) - - ld = self.levenshtein_distance(a,b) - len_a = len(a) - if len_a == 0: - return False - if float(ld)/len_a < 0.4: - return True - return False - - ### TODO: This is getting messy and I'm pretty sure this isn't perfect. - ### TODO: I need to draw a flow chart for this. - def login (self,server,username,password='',terminal_type='ansi',original_prompt=r"[#$]",login_timeout=10,port=None,auto_prompt_reset=True,ssh_key=None,quiet=True,sync_multiplier=1,check_local_ip=True): - - '''This logs the user into the given server. It uses the - 'original_prompt' to try to find the prompt right after login. When it - finds the prompt it immediately tries to reset the prompt to something - more easily matched. The default 'original_prompt' is very optimistic - and is easily fooled. It's more reliable to try to match the original - prompt as exactly as possible to prevent false matches by server - strings such as the "Message Of The Day". On many systems you can - disable the MOTD on the remote server by creating a zero-length file - called "~/.hushlogin" on the remote server. If a prompt cannot be found - then this will not necessarily cause the login to fail. In the case of - a timeout when looking for the prompt we assume that the original - prompt was so weird that we could not match it, so we use a few tricks - to guess when we have reached the prompt. Then we hope for the best and - blindly try to reset the prompt to something more unique. If that fails - then login() raises an :class:`ExceptionPxssh` exception. - - In some situations it is not possible or desirable to reset the - original prompt. In this case, set :attr:`auto_prompt_reset` to False to - inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh - uses a unique prompt in the prompt() method. If the original prompt is - not reset then this will disable the prompt() method unless you - manually set the PROMPT attribute. ''' - - ssh_options = '' - if quiet: - ssh_options = ssh_options + ' -q' - if not check_local_ip: - ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'" - if self.force_password: - ssh_options = ssh_options + ' ' + self.SSH_OPTS - if port is not None: - ssh_options = ssh_options + ' -p %s'%(str(port)) - if ssh_key is not None: - try: - os.path.isfile(ssh_key) - except: - raise ExceptionPxssh ('private ssh key does not exist') - ssh_options = ssh_options + ' -i %s' % (ssh_key) - cmd = "ssh %s -l %s %s" % (ssh_options, username, server) - - # This does not distinguish between a remote server 'password' prompt - # and a local ssh 'passphrase' prompt (for unlocking a private key). - spawn._spawn(self, cmd) - i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT, "(?i)connection closed by remote host"], timeout=login_timeout) - - # First phase - if i==0: - # New certificate -- always accept it. - # This is what you get if SSH does not have the remote host's - # public key stored in the 'known_hosts' cache. - self.sendline("yes") - i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT]) - if i==2: # password or passphrase - self.sendline(password) - i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT]) - if i==4: - self.sendline(terminal_type) - i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT]) - - # Second phase - if i==0: - # This is weird. This should not happen twice in a row. - self.close() - raise ExceptionPxssh ('Weird error. Got "are you sure" prompt twice.') - elif i==1: # can occur if you have a public key pair set to authenticate. - ### TODO: May NOT be OK if expect() got tricked and matched a false prompt. - pass - elif i==2: # password prompt again - # For incorrect passwords, some ssh servers will - # ask for the password again, others return 'denied' right away. - # If we get the password prompt again then this means - # we didn't get the password right the first time. - self.close() - raise ExceptionPxssh ('password refused') - elif i==3: # permission denied -- password was bad. - self.close() - raise ExceptionPxssh ('permission denied') - elif i==4: # terminal type again? WTF? - self.close() - raise ExceptionPxssh ('Weird error. Got "terminal type" prompt twice.') - elif i==5: # Timeout - #This is tricky... I presume that we are at the command-line prompt. - #It may be that the shell prompt was so weird that we couldn't match - #it. Or it may be that we couldn't log in for some other reason. I - #can't be sure, but it's safe to guess that we did login because if - #I presume wrong and we are not logged in then this should be caught - #later when I try to set the shell prompt. - pass - elif i==6: # Connection closed by remote host - self.close() - raise ExceptionPxssh ('connection closed') - else: # Unexpected - self.close() - raise ExceptionPxssh ('unexpected login response') - if not self.sync_original_prompt(sync_multiplier): - self.close() - raise ExceptionPxssh ('could not synchronize with original prompt') - # We appear to be in. - # set shell prompt to something unique. - if auto_prompt_reset: - if not self.set_unique_prompt(): - self.close() - raise ExceptionPxssh ('could not set shell prompt\n'+self.before) - return True - - def logout (self): - - '''This sends exit to the remote shell. If there are stopped jobs then - this automatically sends exit twice. ''' - - self.sendline("exit") - index = self.expect([EOF, "(?i)there are stopped jobs"]) - if index==1: - self.sendline("exit") - self.expect(EOF) - self.close() - - def prompt (self, timeout=-1): - - '''This matches the shell prompt. This is little more than a short-cut - to the expect() method. This returns True if the shell prompt was - matched. This returns False if a timeout was raised. Note that if you - called :meth:`login` with :attr:`auto_prompt_reset` set to False then - before calling :meth:`prompt` you must set the :attr:`PROMPT` attribute - to a regex that it will use for matching the prompt. - - Calling :meth:`prompt` will erase the contents of the :attr:`before` - attribute even if no prompt is ever matched. If timeout is not given or - it is set to -1 then self.timeout is used. - ''' - - if timeout == -1: - timeout = self.timeout - i = self.expect([self.PROMPT, TIMEOUT], timeout=timeout) - if i==1: - return False - return True - - def set_unique_prompt (self): - - '''This sets the remote prompt to something more unique than # or $. - This makes it easier for the :meth:`prompt` method to match the shell prompt - unambiguously. This method is called automatically by the :meth:`login` - method, but you may want to call it manually if you somehow reset the - shell prompt. For example, if you 'su' to a different user then you - will need to manually reset the prompt. This sends shell commands to - the remote host to set the prompt, so this assumes the remote host is - ready to receive commands. - - Alternatively, you may use your own prompt pattern. Just set the PROMPT - attribute to a regular expression that matches it. In this case you - should call login() with auto_prompt_reset=False; then set the PROMPT - attribute. After that the prompt() method will try to match your prompt - pattern.''' - - self.sendline ("unset PROMPT_COMMAND") - self.sendline (self.PROMPT_SET_SH) # sh-style - i = self.expect ([TIMEOUT, self.PROMPT], timeout=10) - if i == 0: # csh-style - self.sendline (self.PROMPT_SET_CSH) - i = self.expect ([TIMEOUT, self.PROMPT], timeout=10) - if i == 0: - return False - return True - -# vi:ts=4:sw=4:expandtab:ft=python: diff --git a/awx/lib/site-packages/pexpect/screen.py b/awx/lib/site-packages/pexpect/screen.py deleted file mode 100644 index 61d3b97a36..0000000000 --- a/awx/lib/site-packages/pexpect/screen.py +++ /dev/null @@ -1,364 +0,0 @@ -'''This implements a virtual screen. This is used to support ANSI terminal -emulation. The screen representation and state is implemented in this class. -Most of the methods are inspired by ANSI screen control codes. The -:class:`~pexpect.ANSI.ANSI` class extends this class to add parsing of ANSI -escape codes. - -PEXPECT LICENSE - - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -import copy - -NUL = 0 # Fill character; ignored on input. -ENQ = 5 # Transmit answerback message. -BEL = 7 # Ring the bell. -BS = 8 # Move cursor left. -HT = 9 # Move cursor to next tab stop. -LF = 10 # Line feed. -VT = 11 # Same as LF. -FF = 12 # Same as LF. -CR = 13 # Move cursor to left margin or newline. -SO = 14 # Invoke G1 character set. -SI = 15 # Invoke G0 character set. -XON = 17 # Resume transmission. -XOFF = 19 # Halt transmission. -CAN = 24 # Cancel escape sequence. -SUB = 26 # Same as CAN. -ESC = 27 # Introduce a control sequence. -DEL = 127 # Fill character; ignored on input. -SPACE = chr(32) # Space or blank character. - -def constrain (n, min, max): - - '''This returns a number, n constrained to the min and max bounds. ''' - - if n < min: - return min - if n > max: - return max - return n - -class screen: - '''This object maintains the state of a virtual text screen as a - rectangluar array. This maintains a virtual cursor position and handles - scrolling as characters are added. This supports most of the methods needed - by an ANSI text screen. Row and column indexes are 1-based (not zero-based, - like arrays). ''' - - def __init__ (self, r=24,c=80): - '''This initializes a blank screen of the given dimensions.''' - - self.rows = r - self.cols = c - self.cur_r = 1 - self.cur_c = 1 - self.cur_saved_r = 1 - self.cur_saved_c = 1 - self.scroll_row_start = 1 - self.scroll_row_end = self.rows - self.w = [ [SPACE] * self.cols for c in range(self.rows)] - - def __str__ (self): - '''This returns a printable representation of the screen. The end of - each screen line is terminated by a newline. ''' - - return '\n'.join ([ ''.join(c) for c in self.w ]) - - def dump (self): - '''This returns a copy of the screen as a string. This is similar to - __str__ except that lines are not terminated with line feeds. ''' - - return ''.join ([ ''.join(c) for c in self.w ]) - - def pretty (self): - '''This returns a copy of the screen as a string with an ASCII text box - around the screen border. This is similar to __str__ except that it - adds a box. ''' - - top_bot = '+' + '-'*self.cols + '+\n' - return top_bot + '\n'.join(['|'+line+'|' for line in str(self).split('\n')]) + '\n' + top_bot - - def fill (self, ch=SPACE): - - self.fill_region (1,1,self.rows,self.cols, ch) - - def fill_region (self, rs,cs, re,ce, ch=SPACE): - - rs = constrain (rs, 1, self.rows) - re = constrain (re, 1, self.rows) - cs = constrain (cs, 1, self.cols) - ce = constrain (ce, 1, self.cols) - if rs > re: - rs, re = re, rs - if cs > ce: - cs, ce = ce, cs - for r in range (rs, re+1): - for c in range (cs, ce + 1): - self.put_abs (r,c,ch) - - def cr (self): - '''This moves the cursor to the beginning (col 1) of the current row. - ''' - - self.cursor_home (self.cur_r, 1) - - def lf (self): - '''This moves the cursor down with scrolling. - ''' - - old_r = self.cur_r - self.cursor_down() - if old_r == self.cur_r: - self.scroll_up () - self.erase_line() - - def crlf (self): - '''This advances the cursor with CRLF properties. - The cursor will line wrap and the screen may scroll. - ''' - - self.cr () - self.lf () - - def newline (self): - '''This is an alias for crlf(). - ''' - - self.crlf() - - def put_abs (self, r, c, ch): - '''Screen array starts at 1 index.''' - - r = constrain (r, 1, self.rows) - c = constrain (c, 1, self.cols) - ch = str(ch)[0] - self.w[r-1][c-1] = ch - - def put (self, ch): - '''This puts a characters at the current cursor position. - ''' - - self.put_abs (self.cur_r, self.cur_c, ch) - - def insert_abs (self, r, c, ch): - '''This inserts a character at (r,c). Everything under - and to the right is shifted right one character. - The last character of the line is lost. - ''' - - r = constrain (r, 1, self.rows) - c = constrain (c, 1, self.cols) - for ci in range (self.cols, c, -1): - self.put_abs (r,ci, self.get_abs(r,ci-1)) - self.put_abs (r,c,ch) - - def insert (self, ch): - - self.insert_abs (self.cur_r, self.cur_c, ch) - - def get_abs (self, r, c): - - r = constrain (r, 1, self.rows) - c = constrain (c, 1, self.cols) - return self.w[r-1][c-1] - - def get (self): - - self.get_abs (self.cur_r, self.cur_c) - - def get_region (self, rs,cs, re,ce): - '''This returns a list of lines representing the region. - ''' - - rs = constrain (rs, 1, self.rows) - re = constrain (re, 1, self.rows) - cs = constrain (cs, 1, self.cols) - ce = constrain (ce, 1, self.cols) - if rs > re: - rs, re = re, rs - if cs > ce: - cs, ce = ce, cs - sc = [] - for r in range (rs, re+1): - line = '' - for c in range (cs, ce + 1): - ch = self.get_abs (r,c) - line = line + ch - sc.append (line) - return sc - - def cursor_constrain (self): - '''This keeps the cursor within the screen area. - ''' - - self.cur_r = constrain (self.cur_r, 1, self.rows) - self.cur_c = constrain (self.cur_c, 1, self.cols) - - def cursor_home (self, r=1, c=1): # [{ROW};{COLUMN}H - - self.cur_r = r - self.cur_c = c - self.cursor_constrain () - - def cursor_back (self,count=1): # [{COUNT}D (not confused with down) - - self.cur_c = self.cur_c - count - self.cursor_constrain () - - def cursor_down (self,count=1): # [{COUNT}B (not confused with back) - - self.cur_r = self.cur_r + count - self.cursor_constrain () - - def cursor_forward (self,count=1): # [{COUNT}C - - self.cur_c = self.cur_c + count - self.cursor_constrain () - - def cursor_up (self,count=1): # [{COUNT}A - - self.cur_r = self.cur_r - count - self.cursor_constrain () - - def cursor_up_reverse (self): # M (called RI -- Reverse Index) - - old_r = self.cur_r - self.cursor_up() - if old_r == self.cur_r: - self.scroll_up() - - def cursor_force_position (self, r, c): # [{ROW};{COLUMN}f - '''Identical to Cursor Home.''' - - self.cursor_home (r, c) - - def cursor_save (self): # [s - '''Save current cursor position.''' - - self.cursor_save_attrs() - - def cursor_unsave (self): # [u - '''Restores cursor position after a Save Cursor.''' - - self.cursor_restore_attrs() - - def cursor_save_attrs (self): # 7 - '''Save current cursor position.''' - - self.cur_saved_r = self.cur_r - self.cur_saved_c = self.cur_c - - def cursor_restore_attrs (self): # 8 - '''Restores cursor position after a Save Cursor.''' - - self.cursor_home (self.cur_saved_r, self.cur_saved_c) - - def scroll_constrain (self): - '''This keeps the scroll region within the screen region.''' - - if self.scroll_row_start <= 0: - self.scroll_row_start = 1 - if self.scroll_row_end > self.rows: - self.scroll_row_end = self.rows - - def scroll_screen (self): # [r - '''Enable scrolling for entire display.''' - - self.scroll_row_start = 1 - self.scroll_row_end = self.rows - - def scroll_screen_rows (self, rs, re): # [{start};{end}r - '''Enable scrolling from row {start} to row {end}.''' - - self.scroll_row_start = rs - self.scroll_row_end = re - self.scroll_constrain() - - def scroll_down (self): # D - '''Scroll display down one line.''' - - # Screen is indexed from 1, but arrays are indexed from 0. - s = self.scroll_row_start - 1 - e = self.scroll_row_end - 1 - self.w[s+1:e+1] = copy.deepcopy(self.w[s:e]) - - def scroll_up (self): # M - '''Scroll display up one line.''' - - # Screen is indexed from 1, but arrays are indexed from 0. - s = self.scroll_row_start - 1 - e = self.scroll_row_end - 1 - self.w[s:e] = copy.deepcopy(self.w[s+1:e+1]) - - def erase_end_of_line (self): # [0K -or- [K - '''Erases from the current cursor position to the end of the current - line.''' - - self.fill_region (self.cur_r, self.cur_c, self.cur_r, self.cols) - - def erase_start_of_line (self): # [1K - '''Erases from the current cursor position to the start of the current - line.''' - - self.fill_region (self.cur_r, 1, self.cur_r, self.cur_c) - - def erase_line (self): # [2K - '''Erases the entire current line.''' - - self.fill_region (self.cur_r, 1, self.cur_r, self.cols) - - def erase_down (self): # [0J -or- [J - '''Erases the screen from the current line down to the bottom of the - screen.''' - - self.erase_end_of_line () - self.fill_region (self.cur_r + 1, 1, self.rows, self.cols) - - def erase_up (self): # [1J - '''Erases the screen from the current line up to the top of the - screen.''' - - self.erase_start_of_line () - self.fill_region (self.cur_r-1, 1, 1, self.cols) - - def erase_screen (self): # [2J - '''Erases the screen with the background color.''' - - self.fill () - - def set_tab (self): # H - '''Sets a tab at the current position.''' - - pass - - def clear_tab (self): # [g - '''Clears tab at the current position.''' - - pass - - def clear_all_tabs (self): # [3g - '''Clears all tabs.''' - - pass - -# Insert line Esc [ Pn L -# Delete line Esc [ Pn M -# Delete character Esc [ Pn P -# Scrolling region Esc [ Pn(top);Pn(bot) r - diff --git a/awx/lib/site-packages/pip/__init__.py b/awx/lib/site-packages/pip/__init__.py deleted file mode 100644 index 9b4e9069d9..0000000000 --- a/awx/lib/site-packages/pip/__init__.py +++ /dev/null @@ -1,277 +0,0 @@ -#!/usr/bin/env python -import os -import optparse - -import sys -import re - -from pip.exceptions import InstallationError, CommandError, PipError -from pip.log import logger -from pip.util import get_installed_distributions, get_prog -from pip.vcs import git, mercurial, subversion, bazaar # noqa -from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter -from pip.commands import commands, get_summaries, get_similar_commands - -# This fixes a peculiarity when importing via __import__ - as we are -# initialising the pip module, "from pip import cmdoptions" is recursive -# and appears not to work properly in that situation. -import pip.cmdoptions -cmdoptions = pip.cmdoptions - -# The version as used in the setup.py and the docs conf.py -__version__ = "1.5.4" - - -def autocomplete(): - """Command and option completion for the main option parser (and options) - and its subcommands (and options). - - Enable by sourcing one of the completion shell scripts (bash or zsh). - """ - # Don't complete if user hasn't sourced bash_completion file. - if 'PIP_AUTO_COMPLETE' not in os.environ: - return - cwords = os.environ['COMP_WORDS'].split()[1:] - cword = int(os.environ['COMP_CWORD']) - try: - current = cwords[cword - 1] - except IndexError: - current = '' - - subcommands = [cmd for cmd, summary in get_summaries()] - options = [] - # subcommand - try: - subcommand_name = [w for w in cwords if w in subcommands][0] - except IndexError: - subcommand_name = None - - parser = create_main_parser() - # subcommand options - if subcommand_name: - # special case: 'help' subcommand has no options - if subcommand_name == 'help': - sys.exit(1) - # special case: list locally installed dists for uninstall command - if subcommand_name == 'uninstall' and not current.startswith('-'): - installed = [] - lc = current.lower() - for dist in get_installed_distributions(local_only=True): - if dist.key.startswith(lc) and dist.key not in cwords[1:]: - installed.append(dist.key) - # if there are no dists installed, fall back to option completion - if installed: - for dist in installed: - print(dist) - sys.exit(1) - - subcommand = commands[subcommand_name]() - options += [(opt.get_opt_string(), opt.nargs) - for opt in subcommand.parser.option_list_all - if opt.help != optparse.SUPPRESS_HELP] - - # filter out previously specified options from available options - prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] - options = [(x, v) for (x, v) in options if x not in prev_opts] - # filter options by current input - options = [(k, v) for k, v in options if k.startswith(current)] - for option in options: - opt_label = option[0] - # append '=' to options which require args - if option[1]: - opt_label += '=' - print(opt_label) - else: - # show main parser options only when necessary - if current.startswith('-') or current.startswith('--'): - opts = [i.option_list for i in parser.option_groups] - opts.append(parser.option_list) - opts = (o for it in opts for o in it) - - subcommands += [i.get_opt_string() for i in opts - if i.help != optparse.SUPPRESS_HELP] - - print(' '.join([x for x in subcommands if x.startswith(current)])) - sys.exit(1) - - -def create_main_parser(): - parser_kw = { - 'usage': '\n%prog [options]', - 'add_help_option': False, - 'formatter': UpdatingDefaultsHelpFormatter(), - 'name': 'global', - 'prog': get_prog(), - } - - parser = ConfigOptionParser(**parser_kw) - parser.disable_interspersed_args() - - pip_pkg_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - parser.version = 'pip %s from %s (python %s)' % ( - __version__, pip_pkg_dir, sys.version[:3]) - - # add the general options - gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) - parser.add_option_group(gen_opts) - - parser.main = True # so the help formatter knows - - # create command listing for description - command_summaries = get_summaries() - description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries] - parser.description = '\n'.join(description) - - return parser - - -def parseopts(args): - parser = create_main_parser() - - # Note: parser calls disable_interspersed_args(), so the result of this call - # is to split the initial args into the general options before the - # subcommand and everything else. - # For example: - # args: ['--timeout=5', 'install', '--user', 'INITools'] - # general_options: ['--timeout==5'] - # args_else: ['install', '--user', 'INITools'] - general_options, args_else = parser.parse_args(args) - - # --version - if general_options.version: - sys.stdout.write(parser.version) - sys.stdout.write(os.linesep) - sys.exit() - - # pip || pip help -> print_help() - if not args_else or (args_else[0] == 'help' and len(args_else) == 1): - parser.print_help() - sys.exit() - - # the subcommand name - cmd_name = args_else[0].lower() - - #all the args without the subcommand - cmd_args = args[:] - cmd_args.remove(args_else[0].lower()) - - if cmd_name not in commands: - guess = get_similar_commands(cmd_name) - - msg = ['unknown command "%s"' % cmd_name] - if guess: - msg.append('maybe you meant "%s"' % guess) - - raise CommandError(' - '.join(msg)) - - return cmd_name, cmd_args - - -def main(initial_args=None): - if initial_args is None: - initial_args = sys.argv[1:] - - autocomplete() - - try: - cmd_name, cmd_args = parseopts(initial_args) - except PipError: - e = sys.exc_info()[1] - sys.stderr.write("ERROR: %s" % e) - sys.stderr.write(os.linesep) - sys.exit(1) - - command = commands[cmd_name]() - return command.main(cmd_args) - - -def bootstrap(): - """ - Bootstrapping function to be called from install-pip.py script. - """ - pkgs = ['pip'] - try: - import setuptools - except ImportError: - pkgs.append('setuptools') - return main(['install', '--upgrade'] + pkgs + sys.argv[1:]) - -############################################################ -## Writing freeze files - - -class FrozenRequirement(object): - - def __init__(self, name, req, editable, comments=()): - self.name = name - self.req = req - self.editable = editable - self.comments = comments - - _rev_re = re.compile(r'-r(\d+)$') - _date_re = re.compile(r'-(20\d\d\d\d\d\d)$') - - @classmethod - def from_dist(cls, dist, dependency_links, find_tags=False): - location = os.path.normcase(os.path.abspath(dist.location)) - comments = [] - from pip.vcs import vcs, get_src_requirement - if vcs.get_backend_name(location): - editable = True - try: - req = get_src_requirement(dist, location, find_tags) - except InstallationError: - ex = sys.exc_info()[1] - logger.warn("Error when trying to get requirement for VCS system %s, falling back to uneditable format" % ex) - req = None - if req is None: - logger.warn('Could not determine repository location of %s' % location) - comments.append('## !! Could not determine repository location') - req = dist.as_requirement() - editable = False - else: - editable = False - req = dist.as_requirement() - specs = req.specs - assert len(specs) == 1 and specs[0][0] == '==' - version = specs[0][1] - ver_match = cls._rev_re.search(version) - date_match = cls._date_re.search(version) - if ver_match or date_match: - svn_backend = vcs.get_backend('svn') - if svn_backend: - svn_location = svn_backend( - ).get_location(dist, dependency_links) - if not svn_location: - logger.warn( - 'Warning: cannot find svn location for %s' % req) - comments.append('## FIXME: could not find svn URL in dependency_links for this package:') - else: - comments.append('# Installing as editable to satisfy requirement %s:' % req) - if ver_match: - rev = ver_match.group(1) - else: - rev = '{%s}' % date_match.group(1) - editable = True - req = '%s@%s#egg=%s' % (svn_location, rev, cls.egg_name(dist)) - return cls(dist.project_name, req, editable, comments) - - @staticmethod - def egg_name(dist): - name = dist.egg_name() - match = re.search(r'-py\d\.\d$', name) - if match: - name = name[:match.start()] - return name - - def __str__(self): - req = self.req - if self.editable: - req = '-e %s' % req - return '\n'.join(list(self.comments) + [str(req)]) + '\n' - - -if __name__ == '__main__': - exit = main() - if exit: - sys.exit(exit) diff --git a/awx/lib/site-packages/pip/__main__.py b/awx/lib/site-packages/pip/__main__.py deleted file mode 100644 index 5ca3746342..0000000000 --- a/awx/lib/site-packages/pip/__main__.py +++ /dev/null @@ -1,7 +0,0 @@ -import sys -from .runner import run - -if __name__ == '__main__': - exit = run() - if exit: - sys.exit(exit) diff --git a/awx/lib/site-packages/pip/_vendor/__init__.py b/awx/lib/site-packages/pip/_vendor/__init__.py deleted file mode 100644 index f233ca0d3a..0000000000 --- a/awx/lib/site-packages/pip/_vendor/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -pip._vendor is for vendoring dependencies of pip to prevent needing pip to -depend on something external. - -Files inside of pip._vendor should be considered immutable and should only be -updated to versions from upstream. -""" -from __future__ import absolute_import diff --git a/awx/lib/site-packages/pip/_vendor/_markerlib/__init__.py b/awx/lib/site-packages/pip/_vendor/_markerlib/__init__.py deleted file mode 100644 index 197781a0f2..0000000000 --- a/awx/lib/site-packages/pip/_vendor/_markerlib/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -try: - import ast - from pip._vendor._markerlib.markers import default_environment, compile, interpret -except ImportError: - if 'ast' in globals(): - raise - def default_environment(): - return {} - def compile(marker): - def marker_fn(environment=None, override=None): - # 'empty markers are True' heuristic won't install extra deps. - return not marker.strip() - marker_fn.__doc__ = marker - return marker_fn - def interpret(marker, environment=None, override=None): - return compile(marker)() diff --git a/awx/lib/site-packages/pip/_vendor/_markerlib/markers.py b/awx/lib/site-packages/pip/_vendor/_markerlib/markers.py deleted file mode 100644 index fa837061e0..0000000000 --- a/awx/lib/site-packages/pip/_vendor/_markerlib/markers.py +++ /dev/null @@ -1,119 +0,0 @@ -# -*- coding: utf-8 -*- -"""Interpret PEP 345 environment markers. - -EXPR [in|==|!=|not in] EXPR [or|and] ... - -where EXPR belongs to any of those: - - python_version = '%s.%s' % (sys.version_info[0], sys.version_info[1]) - python_full_version = sys.version.split()[0] - os.name = os.name - sys.platform = sys.platform - platform.version = platform.version() - platform.machine = platform.machine() - platform.python_implementation = platform.python_implementation() - a free string, like '2.6', or 'win32' -""" - -__all__ = ['default_environment', 'compile', 'interpret'] - -import ast -import os -import platform -import sys -import weakref - -_builtin_compile = compile - -try: - from platform import python_implementation -except ImportError: - if os.name == "java": - # Jython 2.5 has ast module, but not platform.python_implementation() function. - def python_implementation(): - return "Jython" - else: - raise - - -# restricted set of variables -_VARS = {'sys.platform': sys.platform, - 'python_version': '%s.%s' % sys.version_info[:2], - # FIXME parsing sys.platform is not reliable, but there is no other - # way to get e.g. 2.7.2+, and the PEP is defined with sys.version - 'python_full_version': sys.version.split(' ', 1)[0], - 'os.name': os.name, - 'platform.version': platform.version(), - 'platform.machine': platform.machine(), - 'platform.python_implementation': python_implementation(), - 'extra': None # wheel extension - } - -for var in list(_VARS.keys()): - if '.' in var: - _VARS[var.replace('.', '_')] = _VARS[var] - -def default_environment(): - """Return copy of default PEP 385 globals dictionary.""" - return dict(_VARS) - -class ASTWhitelist(ast.NodeTransformer): - def __init__(self, statement): - self.statement = statement # for error messages - - ALLOWED = (ast.Compare, ast.BoolOp, ast.Attribute, ast.Name, ast.Load, ast.Str) - # Bool operations - ALLOWED += (ast.And, ast.Or) - # Comparison operations - ALLOWED += (ast.Eq, ast.Gt, ast.GtE, ast.In, ast.Is, ast.IsNot, ast.Lt, ast.LtE, ast.NotEq, ast.NotIn) - - def visit(self, node): - """Ensure statement only contains allowed nodes.""" - if not isinstance(node, self.ALLOWED): - raise SyntaxError('Not allowed in environment markers.\n%s\n%s' % - (self.statement, - (' ' * node.col_offset) + '^')) - return ast.NodeTransformer.visit(self, node) - - def visit_Attribute(self, node): - """Flatten one level of attribute access.""" - new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx) - return ast.copy_location(new_node, node) - -def parse_marker(marker): - tree = ast.parse(marker, mode='eval') - new_tree = ASTWhitelist(marker).generic_visit(tree) - return new_tree - -def compile_marker(parsed_marker): - return _builtin_compile(parsed_marker, '', 'eval', - dont_inherit=True) - -_cache = weakref.WeakValueDictionary() - -def compile(marker): - """Return compiled marker as a function accepting an environment dict.""" - try: - return _cache[marker] - except KeyError: - pass - if not marker.strip(): - def marker_fn(environment=None, override=None): - """""" - return True - else: - compiled_marker = compile_marker(parse_marker(marker)) - def marker_fn(environment=None, override=None): - """override updates environment""" - if override is None: - override = {} - if environment is None: - environment = default_environment() - environment.update(override) - return eval(compiled_marker, environment) - marker_fn.__doc__ = marker - _cache[marker] = marker_fn - return _cache[marker] - -def interpret(marker, environment=None): - return compile(marker)(environment) diff --git a/awx/lib/site-packages/pip/_vendor/colorama/__init__.py b/awx/lib/site-packages/pip/_vendor/colorama/__init__.py deleted file mode 100644 index 2d127fa8e2..0000000000 --- a/awx/lib/site-packages/pip/_vendor/colorama/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from .initialise import init, deinit, reinit -from .ansi import Fore, Back, Style -from .ansitowin32 import AnsiToWin32 - -VERSION = '0.2.7' - diff --git a/awx/lib/site-packages/pip/_vendor/colorama/ansi.py b/awx/lib/site-packages/pip/_vendor/colorama/ansi.py deleted file mode 100644 index fef40571dd..0000000000 --- a/awx/lib/site-packages/pip/_vendor/colorama/ansi.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -''' -This module generates ANSI character codes to printing colors to terminals. -See: http://en.wikipedia.org/wiki/ANSI_escape_code -''' - -CSI = '\033[' - -def code_to_chars(code): - return CSI + str(code) + 'm' - -class AnsiCodes(object): - def __init__(self, codes): - for name in dir(codes): - if not name.startswith('_'): - value = getattr(codes, name) - setattr(self, name, code_to_chars(value)) - -class AnsiFore: - BLACK = 30 - RED = 31 - GREEN = 32 - YELLOW = 33 - BLUE = 34 - MAGENTA = 35 - CYAN = 36 - WHITE = 37 - RESET = 39 - -class AnsiBack: - BLACK = 40 - RED = 41 - GREEN = 42 - YELLOW = 43 - BLUE = 44 - MAGENTA = 45 - CYAN = 46 - WHITE = 47 - RESET = 49 - -class AnsiStyle: - BRIGHT = 1 - DIM = 2 - NORMAL = 22 - RESET_ALL = 0 - -Fore = AnsiCodes( AnsiFore ) -Back = AnsiCodes( AnsiBack ) -Style = AnsiCodes( AnsiStyle ) - diff --git a/awx/lib/site-packages/pip/_vendor/colorama/ansitowin32.py b/awx/lib/site-packages/pip/_vendor/colorama/ansitowin32.py deleted file mode 100644 index d29060187c..0000000000 --- a/awx/lib/site-packages/pip/_vendor/colorama/ansitowin32.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import re -import sys - -from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style -from .winterm import WinTerm, WinColor, WinStyle -from .win32 import windll - - -if windll is not None: - winterm = WinTerm() - - -def is_a_tty(stream): - return hasattr(stream, 'isatty') and stream.isatty() - - -class StreamWrapper(object): - ''' - Wraps a stream (such as stdout), acting as a transparent proxy for all - attribute access apart from method 'write()', which is delegated to our - Converter instance. - ''' - def __init__(self, wrapped, converter): - # double-underscore everything to prevent clashes with names of - # attributes on the wrapped stream object. - self.__wrapped = wrapped - self.__convertor = converter - - def __getattr__(self, name): - return getattr(self.__wrapped, name) - - def write(self, text): - self.__convertor.write(text) - - -class AnsiToWin32(object): - ''' - Implements a 'write()' method which, on Windows, will strip ANSI character - sequences from the text, and if outputting to a tty, will convert them into - win32 function calls. - ''' - ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') - - def __init__(self, wrapped, convert=None, strip=None, autoreset=False): - # The wrapped stream (normally sys.stdout or sys.stderr) - self.wrapped = wrapped - - # should we reset colors to defaults after every .write() - self.autoreset = autoreset - - # create the proxy wrapping our output stream - self.stream = StreamWrapper(wrapped, self) - - on_windows = sys.platform.startswith('win') - - # should we strip ANSI sequences from our output? - if strip is None: - strip = on_windows - self.strip = strip - - # should we should convert ANSI sequences into win32 calls? - if convert is None: - convert = on_windows and is_a_tty(wrapped) - self.convert = convert - - # dict of ansi codes to win32 functions and parameters - self.win32_calls = self.get_win32_calls() - - # are we wrapping stderr? - self.on_stderr = self.wrapped is sys.stderr - - - def should_wrap(self): - ''' - True if this class is actually needed. If false, then the output - stream will not be affected, nor will win32 calls be issued, so - wrapping stdout is not actually required. This will generally be - False on non-Windows platforms, unless optional functionality like - autoreset has been requested using kwargs to init() - ''' - return self.convert or self.strip or self.autoreset - - - def get_win32_calls(self): - if self.convert and winterm: - return { - AnsiStyle.RESET_ALL: (winterm.reset_all, ), - AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), - AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), - AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), - AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), - AnsiFore.RED: (winterm.fore, WinColor.RED), - AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), - AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), - AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), - AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), - AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), - AnsiFore.WHITE: (winterm.fore, WinColor.GREY), - AnsiFore.RESET: (winterm.fore, ), - AnsiBack.BLACK: (winterm.back, WinColor.BLACK), - AnsiBack.RED: (winterm.back, WinColor.RED), - AnsiBack.GREEN: (winterm.back, WinColor.GREEN), - AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), - AnsiBack.BLUE: (winterm.back, WinColor.BLUE), - AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), - AnsiBack.CYAN: (winterm.back, WinColor.CYAN), - AnsiBack.WHITE: (winterm.back, WinColor.GREY), - AnsiBack.RESET: (winterm.back, ), - } - - - def write(self, text): - if self.strip or self.convert: - self.write_and_convert(text) - else: - self.wrapped.write(text) - self.wrapped.flush() - if self.autoreset: - self.reset_all() - - - def reset_all(self): - if self.convert: - self.call_win32('m', (0,)) - elif is_a_tty(self.wrapped): - self.wrapped.write(Style.RESET_ALL) - - - def write_and_convert(self, text): - ''' - Write the given text to our wrapped stream, stripping any ANSI - sequences from the text, and optionally converting them into win32 - calls. - ''' - cursor = 0 - for match in self.ANSI_RE.finditer(text): - start, end = match.span() - self.write_plain_text(text, cursor, start) - self.convert_ansi(*match.groups()) - cursor = end - self.write_plain_text(text, cursor, len(text)) - - - def write_plain_text(self, text, start, end): - if start < end: - self.wrapped.write(text[start:end]) - self.wrapped.flush() - - - def convert_ansi(self, paramstring, command): - if self.convert: - params = self.extract_params(paramstring) - self.call_win32(command, params) - - - def extract_params(self, paramstring): - def split(paramstring): - for p in paramstring.split(';'): - if p != '': - yield int(p) - return tuple(split(paramstring)) - - - def call_win32(self, command, params): - if params == []: - params = [0] - if command == 'm': - for param in params: - if param in self.win32_calls: - func_args = self.win32_calls[param] - func = func_args[0] - args = func_args[1:] - kwargs = dict(on_stderr=self.on_stderr) - func(*args, **kwargs) - elif command in ('H', 'f'): # set cursor position - func = winterm.set_cursor_position - func(params, on_stderr=self.on_stderr) - elif command in ('J'): - func = winterm.erase_data - func(params, on_stderr=self.on_stderr) - elif command == 'A': - if params == () or params == None: - num_rows = 1 - else: - num_rows = params[0] - func = winterm.cursor_up - func(num_rows, on_stderr=self.on_stderr) - diff --git a/awx/lib/site-packages/pip/_vendor/colorama/initialise.py b/awx/lib/site-packages/pip/_vendor/colorama/initialise.py deleted file mode 100644 index 7c8e77611b..0000000000 --- a/awx/lib/site-packages/pip/_vendor/colorama/initialise.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import atexit -import sys - -from .ansitowin32 import AnsiToWin32 - - -orig_stdout = sys.stdout -orig_stderr = sys.stderr - -wrapped_stdout = sys.stdout -wrapped_stderr = sys.stderr - -atexit_done = False - - -def reset_all(): - AnsiToWin32(orig_stdout).reset_all() - - -def init(autoreset=False, convert=None, strip=None, wrap=True): - - if not wrap and any([autoreset, convert, strip]): - raise ValueError('wrap=False conflicts with any other arg=True') - - global wrapped_stdout, wrapped_stderr - sys.stdout = wrapped_stdout = \ - wrap_stream(orig_stdout, convert, strip, autoreset, wrap) - sys.stderr = wrapped_stderr = \ - wrap_stream(orig_stderr, convert, strip, autoreset, wrap) - - global atexit_done - if not atexit_done: - atexit.register(reset_all) - atexit_done = True - - -def deinit(): - sys.stdout = orig_stdout - sys.stderr = orig_stderr - - -def reinit(): - sys.stdout = wrapped_stdout - sys.stderr = wrapped_stdout - - -def wrap_stream(stream, convert, strip, autoreset, wrap): - if wrap: - wrapper = AnsiToWin32(stream, - convert=convert, strip=strip, autoreset=autoreset) - if wrapper.should_wrap(): - stream = wrapper.stream - return stream - - diff --git a/awx/lib/site-packages/pip/_vendor/colorama/win32.py b/awx/lib/site-packages/pip/_vendor/colorama/win32.py deleted file mode 100644 index f4024f95ee..0000000000 --- a/awx/lib/site-packages/pip/_vendor/colorama/win32.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. - -# from winbase.h -STDOUT = -11 -STDERR = -12 - -try: - from ctypes import windll - from ctypes import wintypes -except ImportError: - windll = None - SetConsoleTextAttribute = lambda *_: None -else: - from ctypes import ( - byref, Structure, c_char, c_short, c_uint32, c_ushort, POINTER - ) - - class CONSOLE_SCREEN_BUFFER_INFO(Structure): - """struct in wincon.h.""" - _fields_ = [ - ("dwSize", wintypes._COORD), - ("dwCursorPosition", wintypes._COORD), - ("wAttributes", wintypes.WORD), - ("srWindow", wintypes.SMALL_RECT), - ("dwMaximumWindowSize", wintypes._COORD), - ] - def __str__(self): - return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( - self.dwSize.Y, self.dwSize.X - , self.dwCursorPosition.Y, self.dwCursorPosition.X - , self.wAttributes - , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right - , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X - ) - - _GetStdHandle = windll.kernel32.GetStdHandle - _GetStdHandle.argtypes = [ - wintypes.DWORD, - ] - _GetStdHandle.restype = wintypes.HANDLE - - _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo - _GetConsoleScreenBufferInfo.argtypes = [ - wintypes.HANDLE, - POINTER(CONSOLE_SCREEN_BUFFER_INFO), - ] - _GetConsoleScreenBufferInfo.restype = wintypes.BOOL - - _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute - _SetConsoleTextAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, - ] - _SetConsoleTextAttribute.restype = wintypes.BOOL - - _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition - _SetConsoleCursorPosition.argtypes = [ - wintypes.HANDLE, - wintypes._COORD, - ] - _SetConsoleCursorPosition.restype = wintypes.BOOL - - _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA - _FillConsoleOutputCharacterA.argtypes = [ - wintypes.HANDLE, - c_char, - wintypes.DWORD, - wintypes._COORD, - POINTER(wintypes.DWORD), - ] - _FillConsoleOutputCharacterA.restype = wintypes.BOOL - - _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute - _FillConsoleOutputAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, - wintypes.DWORD, - wintypes._COORD, - POINTER(wintypes.DWORD), - ] - _FillConsoleOutputAttribute.restype = wintypes.BOOL - - handles = { - STDOUT: _GetStdHandle(STDOUT), - STDERR: _GetStdHandle(STDERR), - } - - def GetConsoleScreenBufferInfo(stream_id=STDOUT): - handle = handles[stream_id] - csbi = CONSOLE_SCREEN_BUFFER_INFO() - success = _GetConsoleScreenBufferInfo( - handle, byref(csbi)) - return csbi - - def SetConsoleTextAttribute(stream_id, attrs): - handle = handles[stream_id] - return _SetConsoleTextAttribute(handle, attrs) - - def SetConsoleCursorPosition(stream_id, position): - position = wintypes._COORD(*position) - # If the position is out of range, do nothing. - if position.Y <= 0 or position.X <= 0: - return - # Adjust for Windows' SetConsoleCursorPosition: - # 1. being 0-based, while ANSI is 1-based. - # 2. expecting (x,y), while ANSI uses (y,x). - adjusted_position = wintypes._COORD(position.Y - 1, position.X - 1) - # Adjust for viewport's scroll position - sr = GetConsoleScreenBufferInfo(STDOUT).srWindow - adjusted_position.Y += sr.Top - adjusted_position.X += sr.Left - # Resume normal processing - handle = handles[stream_id] - return _SetConsoleCursorPosition(handle, adjusted_position) - - def FillConsoleOutputCharacter(stream_id, char, length, start): - handle = handles[stream_id] - char = c_char(char) - length = wintypes.DWORD(length) - num_written = wintypes.DWORD(0) - # Note that this is hard-coded for ANSI (vs wide) bytes. - success = _FillConsoleOutputCharacterA( - handle, char, length, start, byref(num_written)) - return num_written.value - - def FillConsoleOutputAttribute(stream_id, attr, length, start): - ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' - handle = handles[stream_id] - attribute = wintypes.WORD(attr) - length = wintypes.DWORD(length) - num_written = wintypes.DWORD(0) - # Note that this is hard-coded for ANSI (vs wide) bytes. - return _FillConsoleOutputAttribute( - handle, attribute, length, start, byref(num_written)) diff --git a/awx/lib/site-packages/pip/_vendor/colorama/winterm.py b/awx/lib/site-packages/pip/_vendor/colorama/winterm.py deleted file mode 100644 index 4a711fde95..0000000000 --- a/awx/lib/site-packages/pip/_vendor/colorama/winterm.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from . import win32 - - -# from wincon.h -class WinColor(object): - BLACK = 0 - BLUE = 1 - GREEN = 2 - CYAN = 3 - RED = 4 - MAGENTA = 5 - YELLOW = 6 - GREY = 7 - -# from wincon.h -class WinStyle(object): - NORMAL = 0x00 # dim text, dim background - BRIGHT = 0x08 # bright text, dim background - - -class WinTerm(object): - - def __init__(self): - self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes - self.set_attrs(self._default) - self._default_fore = self._fore - self._default_back = self._back - self._default_style = self._style - - def get_attrs(self): - return self._fore + self._back * 16 + self._style - - def set_attrs(self, value): - self._fore = value & 7 - self._back = (value >> 4) & 7 - self._style = value & WinStyle.BRIGHT - - def reset_all(self, on_stderr=None): - self.set_attrs(self._default) - self.set_console(attrs=self._default) - - def fore(self, fore=None, on_stderr=False): - if fore is None: - fore = self._default_fore - self._fore = fore - self.set_console(on_stderr=on_stderr) - - def back(self, back=None, on_stderr=False): - if back is None: - back = self._default_back - self._back = back - self.set_console(on_stderr=on_stderr) - - def style(self, style=None, on_stderr=False): - if style is None: - style = self._default_style - self._style = style - self.set_console(on_stderr=on_stderr) - - def set_console(self, attrs=None, on_stderr=False): - if attrs is None: - attrs = self.get_attrs() - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleTextAttribute(handle, attrs) - - def get_position(self, handle): - position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition - # Because Windows coordinates are 0-based, - # and win32.SetConsoleCursorPosition expects 1-based. - position.X += 1 - position.Y += 1 - return position - - def set_cursor_position(self, position=None, on_stderr=False): - if position is None: - #I'm not currently tracking the position, so there is no default. - #position = self.get_position() - return - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleCursorPosition(handle, position) - - def cursor_up(self, num_rows=0, on_stderr=False): - if num_rows == 0: - return - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - position = self.get_position(handle) - adjusted_position = (position.Y - num_rows, position.X) - self.set_cursor_position(adjusted_position, on_stderr) - - def erase_data(self, mode=0, on_stderr=False): - # 0 (or None) should clear from the cursor to the end of the screen. - # 1 should clear from the cursor to the beginning of the screen. - # 2 should clear the entire screen. (And maybe move cursor to (1,1)?) - # - # At the moment, I only support mode 2. From looking at the API, it - # should be possible to calculate a different number of bytes to clear, - # and to do so relative to the cursor position. - if mode[0] not in (2,): - return - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - # here's where we'll home the cursor - coord_screen = win32.COORD(0,0) - csbi = win32.GetConsoleScreenBufferInfo(handle) - # get the number of character cells in the current buffer - dw_con_size = csbi.dwSize.X * csbi.dwSize.Y - # fill the entire screen with blanks - win32.FillConsoleOutputCharacter(handle, ' ', dw_con_size, coord_screen) - # now set the buffer's attributes accordingly - win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen ); - # put the cursor at (0, 0) - win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y)) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/__init__.py b/awx/lib/site-packages/pip/_vendor/distlib/__init__.py deleted file mode 100644 index 56a56ba683..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -import logging - -__version__ = '0.1.7' - -class DistlibException(Exception): - pass - -try: - from logging import NullHandler -except ImportError: # pragma: no cover - class NullHandler(logging.Handler): - def handle(self, record): pass - def emit(self, record): pass - -logger = logging.getLogger(__name__) -logger.addHandler(NullHandler()) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/_backport/__init__.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/__init__.py deleted file mode 100644 index f7dbf4c9aa..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/_backport/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Modules copied from Python 3 standard libraries, for internal use only. - -Individual classes and functions are found in d2._backport.misc. Intended -usage is to always import things missing from 3.1 from that module: the -built-in/stdlib objects will be used if found. -""" diff --git a/awx/lib/site-packages/pip/_vendor/distlib/_backport/misc.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/misc.py deleted file mode 100644 index cfb318d34f..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/_backport/misc.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Backports for individual classes and functions.""" - -import os -import sys - -__all__ = ['cache_from_source', 'callable', 'fsencode'] - - -try: - from imp import cache_from_source -except ImportError: - def cache_from_source(py_file, debug=__debug__): - ext = debug and 'c' or 'o' - return py_file + ext - - -try: - callable = callable -except NameError: - from collections import Callable - - def callable(obj): - return isinstance(obj, Callable) - - -try: - fsencode = os.fsencode -except AttributeError: - def fsencode(filename): - if isinstance(filename, bytes): - return filename - elif isinstance(filename, str): - return filename.encode(sys.getfilesystemencoding()) - else: - raise TypeError("expect bytes or str, not %s" % - type(filename).__name__) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/_backport/shutil.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/shutil.py deleted file mode 100644 index 9e2e234d46..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/_backport/shutil.py +++ /dev/null @@ -1,761 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Utility functions for copying and archiving files and directory trees. - -XXX The functions here don't copy the resource fork or other metadata on Mac. - -""" - -import os -import sys -import stat -from os.path import abspath -import fnmatch -import collections -import errno -from . import tarfile - -try: - import bz2 - _BZ2_SUPPORTED = True -except ImportError: - _BZ2_SUPPORTED = False - -try: - from pwd import getpwnam -except ImportError: - getpwnam = None - -try: - from grp import getgrnam -except ImportError: - getgrnam = None - -__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", - "copytree", "move", "rmtree", "Error", "SpecialFileError", - "ExecError", "make_archive", "get_archive_formats", - "register_archive_format", "unregister_archive_format", - "get_unpack_formats", "register_unpack_format", - "unregister_unpack_format", "unpack_archive", "ignore_patterns"] - -class Error(EnvironmentError): - pass - -class SpecialFileError(EnvironmentError): - """Raised when trying to do a kind of operation (e.g. copying) which is - not supported on a special file (e.g. a named pipe)""" - -class ExecError(EnvironmentError): - """Raised when a command could not be executed""" - -class ReadError(EnvironmentError): - """Raised when an archive cannot be read""" - -class RegistryError(Exception): - """Raised when a registery operation with the archiving - and unpacking registeries fails""" - - -try: - WindowsError -except NameError: - WindowsError = None - -def copyfileobj(fsrc, fdst, length=16*1024): - """copy data from file-like object fsrc to file-like object fdst""" - while 1: - buf = fsrc.read(length) - if not buf: - break - fdst.write(buf) - -def _samefile(src, dst): - # Macintosh, Unix. - if hasattr(os.path, 'samefile'): - try: - return os.path.samefile(src, dst) - except OSError: - return False - - # All other platforms: check for same pathname. - return (os.path.normcase(os.path.abspath(src)) == - os.path.normcase(os.path.abspath(dst))) - -def copyfile(src, dst): - """Copy data from src to dst""" - if _samefile(src, dst): - raise Error("`%s` and `%s` are the same file" % (src, dst)) - - for fn in [src, dst]: - try: - st = os.stat(fn) - except OSError: - # File most likely does not exist - pass - else: - # XXX What about other special files? (sockets, devices...) - if stat.S_ISFIFO(st.st_mode): - raise SpecialFileError("`%s` is a named pipe" % fn) - - with open(src, 'rb') as fsrc: - with open(dst, 'wb') as fdst: - copyfileobj(fsrc, fdst) - -def copymode(src, dst): - """Copy mode bits from src to dst""" - if hasattr(os, 'chmod'): - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - os.chmod(dst, mode) - -def copystat(src, dst): - """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" - st = os.stat(src) - mode = stat.S_IMODE(st.st_mode) - if hasattr(os, 'utime'): - os.utime(dst, (st.st_atime, st.st_mtime)) - if hasattr(os, 'chmod'): - os.chmod(dst, mode) - if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): - try: - os.chflags(dst, st.st_flags) - except OSError as why: - if (not hasattr(errno, 'EOPNOTSUPP') or - why.errno != errno.EOPNOTSUPP): - raise - -def copy(src, dst): - """Copy data and mode bits ("cp src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copymode(src, dst) - -def copy2(src, dst): - """Copy data and all stat info ("cp -p src dst"). - - The destination may be a directory. - - """ - if os.path.isdir(dst): - dst = os.path.join(dst, os.path.basename(src)) - copyfile(src, dst) - copystat(src, dst) - -def ignore_patterns(*patterns): - """Function that can be used as copytree() ignore parameter. - - Patterns is a sequence of glob-style patterns - that are used to exclude files""" - def _ignore_patterns(path, names): - ignored_names = [] - for pattern in patterns: - ignored_names.extend(fnmatch.filter(names, pattern)) - return set(ignored_names) - return _ignore_patterns - -def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, - ignore_dangling_symlinks=False): - """Recursively copy a directory tree. - - The destination directory must not already exist. - If exception(s) occur, an Error is raised with a list of reasons. - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. If the file pointed by the symlink doesn't - exist, an exception will be added in the list of errors raised in - an Error exception at the end of the copy process. - - You can set the optional ignore_dangling_symlinks flag to true if you - want to silence this exception. Notice that this has no effect on - platforms that don't support os.symlink. - - The optional ignore argument is a callable. If given, it - is called with the `src` parameter, which is the directory - being visited by copytree(), and `names` which is the list of - `src` contents, as returned by os.listdir(): - - callable(src, names) -> ignored_names - - Since copytree() is called recursively, the callable will be - called once for each directory that is copied. It returns a - list of names relative to the `src` directory that should - not be copied. - - The optional copy_function argument is a callable that will be used - to copy each file. It will be called with the source path and the - destination path as arguments. By default, copy2() is used, but any - function that supports the same signature (like copy()) can be used. - - """ - names = os.listdir(src) - if ignore is not None: - ignored_names = ignore(src, names) - else: - ignored_names = set() - - os.makedirs(dst) - errors = [] - for name in names: - if name in ignored_names: - continue - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if os.path.islink(srcname): - linkto = os.readlink(srcname) - if symlinks: - os.symlink(linkto, dstname) - else: - # ignore dangling symlink if the flag is on - if not os.path.exists(linkto) and ignore_dangling_symlinks: - continue - # otherwise let the copy occurs. copy2 will raise an error - copy_function(srcname, dstname) - elif os.path.isdir(srcname): - copytree(srcname, dstname, symlinks, ignore, copy_function) - else: - # Will raise a SpecialFileError for unsupported file types - copy_function(srcname, dstname) - # catch the Error from the recursive copytree so that we can - # continue with other files - except Error as err: - errors.extend(err.args[0]) - except EnvironmentError as why: - errors.append((srcname, dstname, str(why))) - try: - copystat(src, dst) - except OSError as why: - if WindowsError is not None and isinstance(why, WindowsError): - # Copying file access times may fail on Windows - pass - else: - errors.extend((src, dst, str(why))) - if errors: - raise Error(errors) - -def rmtree(path, ignore_errors=False, onerror=None): - """Recursively delete a directory tree. - - If ignore_errors is set, errors are ignored; otherwise, if onerror - is set, it is called to handle the error with arguments (func, - path, exc_info) where func is os.listdir, os.remove, or os.rmdir; - path is the argument to that function that caused it to fail; and - exc_info is a tuple returned by sys.exc_info(). If ignore_errors - is false and onerror is None, an exception is raised. - - """ - if ignore_errors: - def onerror(*args): - pass - elif onerror is None: - def onerror(*args): - raise - try: - if os.path.islink(path): - # symlinks to directories are forbidden, see bug #1669 - raise OSError("Cannot call rmtree on a symbolic link") - except OSError: - onerror(os.path.islink, path, sys.exc_info()) - # can't continue even if onerror hook returns - return - names = [] - try: - names = os.listdir(path) - except os.error: - onerror(os.listdir, path, sys.exc_info()) - for name in names: - fullname = os.path.join(path, name) - try: - mode = os.lstat(fullname).st_mode - except os.error: - mode = 0 - if stat.S_ISDIR(mode): - rmtree(fullname, ignore_errors, onerror) - else: - try: - os.remove(fullname) - except os.error: - onerror(os.remove, fullname, sys.exc_info()) - try: - os.rmdir(path) - except os.error: - onerror(os.rmdir, path, sys.exc_info()) - - -def _basename(path): - # A basename() variant which first strips the trailing slash, if present. - # Thus we always get the last component of the path, even for directories. - return os.path.basename(path.rstrip(os.path.sep)) - -def move(src, dst): - """Recursively move a file or directory to another location. This is - similar to the Unix "mv" command. - - If the destination is a directory or a symlink to a directory, the source - is moved inside the directory. The destination path must not already - exist. - - If the destination already exists but is not a directory, it may be - overwritten depending on os.rename() semantics. - - If the destination is on our current filesystem, then rename() is used. - Otherwise, src is copied to the destination and then removed. - A lot more could be done here... A look at a mv.c shows a lot of - the issues this implementation glosses over. - - """ - real_dst = dst - if os.path.isdir(dst): - if _samefile(src, dst): - # We might be on a case insensitive filesystem, - # perform the rename anyway. - os.rename(src, dst) - return - - real_dst = os.path.join(dst, _basename(src)) - if os.path.exists(real_dst): - raise Error("Destination path '%s' already exists" % real_dst) - try: - os.rename(src, real_dst) - except OSError: - if os.path.isdir(src): - if _destinsrc(src, dst): - raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) - copytree(src, real_dst, symlinks=True) - rmtree(src) - else: - copy2(src, real_dst) - os.unlink(src) - -def _destinsrc(src, dst): - src = abspath(src) - dst = abspath(dst) - if not src.endswith(os.path.sep): - src += os.path.sep - if not dst.endswith(os.path.sep): - dst += os.path.sep - return dst.startswith(src) - -def _get_gid(name): - """Returns a gid, given a group name.""" - if getgrnam is None or name is None: - return None - try: - result = getgrnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _get_uid(name): - """Returns an uid, given a user name.""" - if getpwnam is None or name is None: - return None - try: - result = getpwnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - -def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, - owner=None, group=None, logger=None): - """Create a (possibly compressed) tar file from all the files under - 'base_dir'. - - 'compress' must be "gzip" (the default), "bzip2", or None. - - 'owner' and 'group' can be used to define an owner and a group for the - archive that is being built. If not provided, the current owner and group - will be used. - - The output tar file will be named 'base_name' + ".tar", possibly plus - the appropriate compression extension (".gz", or ".bz2"). - - Returns the output filename. - """ - tar_compression = {'gzip': 'gz', None: ''} - compress_ext = {'gzip': '.gz'} - - if _BZ2_SUPPORTED: - tar_compression['bzip2'] = 'bz2' - compress_ext['bzip2'] = '.bz2' - - # flags for compression program, each element of list will be an argument - if compress is not None and compress not in compress_ext: - raise ValueError("bad value for 'compress', or compression format not " - "supported : {0}".format(compress)) - - archive_name = base_name + '.tar' + compress_ext.get(compress, '') - archive_dir = os.path.dirname(archive_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # creating the tarball - if logger is not None: - logger.info('Creating tar archive') - - uid = _get_uid(owner) - gid = _get_gid(group) - - def _set_uid_gid(tarinfo): - if gid is not None: - tarinfo.gid = gid - tarinfo.gname = group - if uid is not None: - tarinfo.uid = uid - tarinfo.uname = owner - return tarinfo - - if not dry_run: - tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) - try: - tar.add(base_dir, filter=_set_uid_gid) - finally: - tar.close() - - return archive_name - -def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): - # XXX see if we want to keep an external call here - if verbose: - zipoptions = "-r" - else: - zipoptions = "-rq" - from distutils.errors import DistutilsExecError - from distutils.spawn import spawn - try: - spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) - except DistutilsExecError: - # XXX really should distinguish between "couldn't find - # external 'zip' command" and "zip failed". - raise ExecError("unable to create zip file '%s': " - "could neither import the 'zipfile' module nor " - "find a standalone zip utility") % zip_filename - -def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): - """Create a zip file from all the files under 'base_dir'. - - The output zip file will be named 'base_name' + ".zip". Uses either the - "zipfile" Python module (if available) or the InfoZIP "zip" utility - (if installed and found on the default search path). If neither tool is - available, raises ExecError. Returns the name of the output zip - file. - """ - zip_filename = base_name + ".zip" - archive_dir = os.path.dirname(base_name) - - if not os.path.exists(archive_dir): - if logger is not None: - logger.info("creating %s", archive_dir) - if not dry_run: - os.makedirs(archive_dir) - - # If zipfile module is not available, try spawning an external 'zip' - # command. - try: - import zipfile - except ImportError: - zipfile = None - - if zipfile is None: - _call_external_zip(base_dir, zip_filename, verbose, dry_run) - else: - if logger is not None: - logger.info("creating '%s' and adding '%s' to it", - zip_filename, base_dir) - - if not dry_run: - zip = zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) - - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - zip.close() - - return zip_filename - -_ARCHIVE_FORMATS = { - 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), - 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), - 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), - 'zip': (_make_zipfile, [], "ZIP file"), - } - -if _BZ2_SUPPORTED: - _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], - "bzip2'ed tar-file") - -def get_archive_formats(): - """Returns a list of supported formats for archiving and unarchiving. - - Each element of the returned sequence is a tuple (name, description) - """ - formats = [(name, registry[2]) for name, registry in - _ARCHIVE_FORMATS.items()] - formats.sort() - return formats - -def register_archive_format(name, function, extra_args=None, description=''): - """Registers an archive format. - - name is the name of the format. function is the callable that will be - used to create archives. If provided, extra_args is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_archive_formats() function. - """ - if extra_args is None: - extra_args = [] - if not isinstance(function, collections.Callable): - raise TypeError('The %s object is not callable' % function) - if not isinstance(extra_args, (tuple, list)): - raise TypeError('extra_args needs to be a sequence') - for element in extra_args: - if not isinstance(element, (tuple, list)) or len(element) !=2: - raise TypeError('extra_args elements are : (arg_name, value)') - - _ARCHIVE_FORMATS[name] = (function, extra_args, description) - -def unregister_archive_format(name): - del _ARCHIVE_FORMATS[name] - -def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, - dry_run=0, owner=None, group=None, logger=None): - """Create an archive file (eg. zip or tar). - - 'base_name' is the name of the file to create, minus any format-specific - extension; 'format' is the archive format: one of "zip", "tar", "bztar" - or "gztar". - - 'root_dir' is a directory that will be the root directory of the - archive; ie. we typically chdir into 'root_dir' before creating the - archive. 'base_dir' is the directory where we start archiving from; - ie. 'base_dir' will be the common prefix of all files and - directories in the archive. 'root_dir' and 'base_dir' both default - to the current directory. Returns the name of the archive file. - - 'owner' and 'group' are used when creating a tar archive. By default, - uses the current owner and group. - """ - save_cwd = os.getcwd() - if root_dir is not None: - if logger is not None: - logger.debug("changing into '%s'", root_dir) - base_name = os.path.abspath(base_name) - if not dry_run: - os.chdir(root_dir) - - if base_dir is None: - base_dir = os.curdir - - kwargs = {'dry_run': dry_run, 'logger': logger} - - try: - format_info = _ARCHIVE_FORMATS[format] - except KeyError: - raise ValueError("unknown archive format '%s'" % format) - - func = format_info[0] - for arg, val in format_info[1]: - kwargs[arg] = val - - if format != 'zip': - kwargs['owner'] = owner - kwargs['group'] = group - - try: - filename = func(base_name, base_dir, **kwargs) - finally: - if root_dir is not None: - if logger is not None: - logger.debug("changing back to '%s'", save_cwd) - os.chdir(save_cwd) - - return filename - - -def get_unpack_formats(): - """Returns a list of supported formats for unpacking. - - Each element of the returned sequence is a tuple - (name, extensions, description) - """ - formats = [(name, info[0], info[3]) for name, info in - _UNPACK_FORMATS.items()] - formats.sort() - return formats - -def _check_unpack_options(extensions, function, extra_args): - """Checks what gets registered as an unpacker.""" - # first make sure no other unpacker is registered for this extension - existing_extensions = {} - for name, info in _UNPACK_FORMATS.items(): - for ext in info[0]: - existing_extensions[ext] = name - - for extension in extensions: - if extension in existing_extensions: - msg = '%s is already registered for "%s"' - raise RegistryError(msg % (extension, - existing_extensions[extension])) - - if not isinstance(function, collections.Callable): - raise TypeError('The registered function must be a callable') - - -def register_unpack_format(name, extensions, function, extra_args=None, - description=''): - """Registers an unpack format. - - `name` is the name of the format. `extensions` is a list of extensions - corresponding to the format. - - `function` is the callable that will be - used to unpack archives. The callable will receive archives to unpack. - If it's unable to handle an archive, it needs to raise a ReadError - exception. - - If provided, `extra_args` is a sequence of - (name, value) tuples that will be passed as arguments to the callable. - description can be provided to describe the format, and will be returned - by the get_unpack_formats() function. - """ - if extra_args is None: - extra_args = [] - _check_unpack_options(extensions, function, extra_args) - _UNPACK_FORMATS[name] = extensions, function, extra_args, description - -def unregister_unpack_format(name): - """Removes the pack format from the registery.""" - del _UNPACK_FORMATS[name] - -def _ensure_directory(path): - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - if not os.path.isdir(dirname): - os.makedirs(dirname) - -def _unpack_zipfile(filename, extract_dir): - """Unpack zip `filename` to `extract_dir` - """ - try: - import zipfile - except ImportError: - raise ReadError('zlib not supported, cannot unpack this archive.') - - if not zipfile.is_zipfile(filename): - raise ReadError("%s is not a zip file" % filename) - - zip = zipfile.ZipFile(filename) - try: - for info in zip.infolist(): - name = info.filename - - # don't extract absolute paths or ones with .. in them - if name.startswith('/') or '..' in name: - continue - - target = os.path.join(extract_dir, *name.split('/')) - if not target: - continue - - _ensure_directory(target) - if not name.endswith('/'): - # file - data = zip.read(info.filename) - f = open(target, 'wb') - try: - f.write(data) - finally: - f.close() - del data - finally: - zip.close() - -def _unpack_tarfile(filename, extract_dir): - """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` - """ - try: - tarobj = tarfile.open(filename) - except tarfile.TarError: - raise ReadError( - "%s is not a compressed or uncompressed tar file" % filename) - try: - tarobj.extractall(extract_dir) - finally: - tarobj.close() - -_UNPACK_FORMATS = { - 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), - 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), - 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") - } - -if _BZ2_SUPPORTED: - _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], - "bzip2'ed tar-file") - -def _find_unpack_format(filename): - for name, info in _UNPACK_FORMATS.items(): - for extension in info[0]: - if filename.endswith(extension): - return name - return None - -def unpack_archive(filename, extract_dir=None, format=None): - """Unpack an archive. - - `filename` is the name of the archive. - - `extract_dir` is the name of the target directory, where the archive - is unpacked. If not provided, the current working directory is used. - - `format` is the archive format: one of "zip", "tar", or "gztar". Or any - other registered format. If not provided, unpack_archive will use the - filename extension and see if an unpacker was registered for that - extension. - - In case none is found, a ValueError is raised. - """ - if extract_dir is None: - extract_dir = os.getcwd() - - if format is not None: - try: - format_info = _UNPACK_FORMATS[format] - except KeyError: - raise ValueError("Unknown unpack format '{0}'".format(format)) - - func = format_info[1] - func(filename, extract_dir, **dict(format_info[2])) - else: - # we need to look at the registered unpackers supported extensions - format = _find_unpack_format(filename) - if format is None: - raise ReadError("Unknown archive format '{0}'".format(filename)) - - func = _UNPACK_FORMATS[format][1] - kwargs = dict(_UNPACK_FORMATS[format][2]) - func(filename, extract_dir, **kwargs) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg b/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg deleted file mode 100644 index 1746bd01c1..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg +++ /dev/null @@ -1,84 +0,0 @@ -[posix_prefix] -# Configuration directories. Some of these come straight out of the -# configure script. They are for implementing the other variables, not to -# be used directly in [resource_locations]. -confdir = /etc -datadir = /usr/share -libdir = /usr/lib -statedir = /var -# User resource directory -local = ~/.local/{distribution.name} - -stdlib = {base}/lib/python{py_version_short} -platstdlib = {platbase}/lib/python{py_version_short} -purelib = {base}/lib/python{py_version_short}/site-packages -platlib = {platbase}/lib/python{py_version_short}/site-packages -include = {base}/include/python{py_version_short}{abiflags} -platinclude = {platbase}/include/python{py_version_short}{abiflags} -data = {base} - -[posix_home] -stdlib = {base}/lib/python -platstdlib = {base}/lib/python -purelib = {base}/lib/python -platlib = {base}/lib/python -include = {base}/include/python -platinclude = {base}/include/python -scripts = {base}/bin -data = {base} - -[nt] -stdlib = {base}/Lib -platstdlib = {base}/Lib -purelib = {base}/Lib/site-packages -platlib = {base}/Lib/site-packages -include = {base}/Include -platinclude = {base}/Include -scripts = {base}/Scripts -data = {base} - -[os2] -stdlib = {base}/Lib -platstdlib = {base}/Lib -purelib = {base}/Lib/site-packages -platlib = {base}/Lib/site-packages -include = {base}/Include -platinclude = {base}/Include -scripts = {base}/Scripts -data = {base} - -[os2_home] -stdlib = {userbase}/lib/python{py_version_short} -platstdlib = {userbase}/lib/python{py_version_short} -purelib = {userbase}/lib/python{py_version_short}/site-packages -platlib = {userbase}/lib/python{py_version_short}/site-packages -include = {userbase}/include/python{py_version_short} -scripts = {userbase}/bin -data = {userbase} - -[nt_user] -stdlib = {userbase}/Python{py_version_nodot} -platstdlib = {userbase}/Python{py_version_nodot} -purelib = {userbase}/Python{py_version_nodot}/site-packages -platlib = {userbase}/Python{py_version_nodot}/site-packages -include = {userbase}/Python{py_version_nodot}/Include -scripts = {userbase}/Scripts -data = {userbase} - -[posix_user] -stdlib = {userbase}/lib/python{py_version_short} -platstdlib = {userbase}/lib/python{py_version_short} -purelib = {userbase}/lib/python{py_version_short}/site-packages -platlib = {userbase}/lib/python{py_version_short}/site-packages -include = {userbase}/include/python{py_version_short} -scripts = {userbase}/bin -data = {userbase} - -[osx_framework_user] -stdlib = {userbase}/lib/python -platstdlib = {userbase}/lib/python -purelib = {userbase}/lib/python/site-packages -platlib = {userbase}/lib/python/site-packages -include = {userbase}/include -scripts = {userbase}/bin -data = {userbase} diff --git a/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py deleted file mode 100644 index a5b55feb4e..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py +++ /dev/null @@ -1,788 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Access to Python's configuration information.""" - -import codecs -import os -import re -import sys -from os.path import pardir, realpath -try: - import configparser -except ImportError: - import ConfigParser as configparser - - -__all__ = [ - 'get_config_h_filename', - 'get_config_var', - 'get_config_vars', - 'get_makefile_filename', - 'get_path', - 'get_path_names', - 'get_paths', - 'get_platform', - 'get_python_version', - 'get_scheme_names', - 'parse_config_h', -] - - -def _safe_realpath(path): - try: - return realpath(path) - except OSError: - return path - - -if sys.executable: - _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) -else: - # sys.executable can be empty if argv[0] has been changed and Python is - # unable to retrieve the real program name - _PROJECT_BASE = _safe_realpath(os.getcwd()) - -if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): - _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) -# PC/VS7.1 -if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): - _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) -# PC/AMD64 -if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): - _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) - - -def is_python_build(): - for fn in ("Setup.dist", "Setup.local"): - if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): - return True - return False - -_PYTHON_BUILD = is_python_build() - -_cfg_read = False - -def _ensure_cfg_read(): - global _cfg_read - if not _cfg_read: - from distlib.resources import finder - backport_package = __name__.rsplit('.', 1)[0] - _finder = finder(backport_package) - _cfgfile = _finder.find('sysconfig.cfg') - assert _cfgfile, 'sysconfig.cfg exists' - with _cfgfile.as_stream() as s: - _SCHEMES.readfp(s) - if _PYTHON_BUILD: - for scheme in ('posix_prefix', 'posix_home'): - _SCHEMES.set(scheme, 'include', '{srcdir}/Include') - _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.') - - _cfg_read = True - - -_SCHEMES = configparser.RawConfigParser() -_VAR_REPL = re.compile(r'\{([^{]*?)\}') - -def _expand_globals(config): - _ensure_cfg_read() - if config.has_section('globals'): - globals = config.items('globals') - else: - globals = tuple() - - sections = config.sections() - for section in sections: - if section == 'globals': - continue - for option, value in globals: - if config.has_option(section, option): - continue - config.set(section, option, value) - config.remove_section('globals') - - # now expanding local variables defined in the cfg file - # - for section in config.sections(): - variables = dict(config.items(section)) - - def _replacer(matchobj): - name = matchobj.group(1) - if name in variables: - return variables[name] - return matchobj.group(0) - - for option, value in config.items(section): - config.set(section, option, _VAR_REPL.sub(_replacer, value)) - -#_expand_globals(_SCHEMES) - - # FIXME don't rely on sys.version here, its format is an implementation detail - # of CPython, use sys.version_info or sys.hexversion -_PY_VERSION = sys.version.split()[0] -_PY_VERSION_SHORT = sys.version[:3] -_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2] -_PREFIX = os.path.normpath(sys.prefix) -_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) -_CONFIG_VARS = None -_USER_BASE = None - - -def _subst_vars(path, local_vars): - """In the string `path`, replace tokens like {some.thing} with the - corresponding value from the map `local_vars`. - - If there is no corresponding value, leave the token unchanged. - """ - def _replacer(matchobj): - name = matchobj.group(1) - if name in local_vars: - return local_vars[name] - elif name in os.environ: - return os.environ[name] - return matchobj.group(0) - return _VAR_REPL.sub(_replacer, path) - - -def _extend_dict(target_dict, other_dict): - target_keys = target_dict.keys() - for key, value in other_dict.items(): - if key in target_keys: - continue - target_dict[key] = value - - -def _expand_vars(scheme, vars): - res = {} - if vars is None: - vars = {} - _extend_dict(vars, get_config_vars()) - - for key, value in _SCHEMES.items(scheme): - if os.name in ('posix', 'nt'): - value = os.path.expanduser(value) - res[key] = os.path.normpath(_subst_vars(value, vars)) - return res - - -def format_value(value, vars): - def _replacer(matchobj): - name = matchobj.group(1) - if name in vars: - return vars[name] - return matchobj.group(0) - return _VAR_REPL.sub(_replacer, value) - - -def _get_default_scheme(): - if os.name == 'posix': - # the default scheme for posix is posix_prefix - return 'posix_prefix' - return os.name - - -def _getuserbase(): - env_base = os.environ.get("PYTHONUSERBASE", None) - - def joinuser(*args): - return os.path.expanduser(os.path.join(*args)) - - # what about 'os2emx', 'riscos' ? - if os.name == "nt": - base = os.environ.get("APPDATA") or "~" - if env_base: - return env_base - else: - return joinuser(base, "Python") - - if sys.platform == "darwin": - framework = get_config_var("PYTHONFRAMEWORK") - if framework: - if env_base: - return env_base - else: - return joinuser("~", "Library", framework, "%d.%d" % - sys.version_info[:2]) - - if env_base: - return env_base - else: - return joinuser("~", ".local") - - -def _parse_makefile(filename, vars=None): - """Parse a Makefile-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - # Regexes needed for parsing Makefile (and similar syntaxes, - # like old-style Setup files). - _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") - _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") - _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") - - if vars is None: - vars = {} - done = {} - notdone = {} - - with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f: - lines = f.readlines() - - for line in lines: - if line.startswith('#') or line.strip() == '': - continue - m = _variable_rx.match(line) - if m: - n, v = m.group(1, 2) - v = v.strip() - # `$$' is a literal `$' in make - tmpv = v.replace('$$', '') - - if "$" in tmpv: - notdone[n] = v - else: - try: - v = int(v) - except ValueError: - # insert literal `$' - done[n] = v.replace('$$', '$') - else: - done[n] = v - - # do variable interpolation here - variables = list(notdone.keys()) - - # Variables with a 'PY_' prefix in the makefile. These need to - # be made available without that prefix through sysconfig. - # Special care is needed to ensure that variable expansion works, even - # if the expansion uses the name without a prefix. - renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') - - while len(variables) > 0: - for name in tuple(variables): - value = notdone[name] - m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m is not None: - n = m.group(1) - found = True - if n in done: - item = str(done[n]) - elif n in notdone: - # get it on a subsequent round - found = False - elif n in os.environ: - # do it like make: fall back to environment - item = os.environ[n] - - elif n in renamed_variables: - if (name.startswith('PY_') and - name[3:] in renamed_variables): - item = "" - - elif 'PY_' + n in notdone: - found = False - - else: - item = str(done['PY_' + n]) - - else: - done[n] = item = "" - - if found: - after = value[m.end():] - value = value[:m.start()] + item + after - if "$" in after: - notdone[name] = value - else: - try: - value = int(value) - except ValueError: - done[name] = value.strip() - else: - done[name] = value - variables.remove(name) - - if (name.startswith('PY_') and - name[3:] in renamed_variables): - - name = name[3:] - if name not in done: - done[name] = value - - else: - # bogus variable reference (e.g. "prefix=$/opt/python"); - # just drop it since we can't deal - done[name] = value - variables.remove(name) - - # strip spurious spaces - for k, v in done.items(): - if isinstance(v, str): - done[k] = v.strip() - - # save the results in the global dictionary - vars.update(done) - return vars - - -def get_makefile_filename(): - """Return the path of the Makefile.""" - if _PYTHON_BUILD: - return os.path.join(_PROJECT_BASE, "Makefile") - if hasattr(sys, 'abiflags'): - config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags) - else: - config_dir_name = 'config' - return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') - - -def _init_posix(vars): - """Initialize the module as appropriate for POSIX systems.""" - # load the installed Makefile: - makefile = get_makefile_filename() - try: - _parse_makefile(makefile, vars) - except IOError as e: - msg = "invalid Python installation: unable to open %s" % makefile - if hasattr(e, "strerror"): - msg = msg + " (%s)" % e.strerror - raise IOError(msg) - # load the installed pyconfig.h: - config_h = get_config_h_filename() - try: - with open(config_h) as f: - parse_config_h(f, vars) - except IOError as e: - msg = "invalid Python installation: unable to open %s" % config_h - if hasattr(e, "strerror"): - msg = msg + " (%s)" % e.strerror - raise IOError(msg) - # On AIX, there are wrong paths to the linker scripts in the Makefile - # -- these paths are relative to the Python source, but when installed - # the scripts are in another directory. - if _PYTHON_BUILD: - vars['LDSHARED'] = vars['BLDSHARED'] - - -def _init_non_posix(vars): - """Initialize the module as appropriate for NT""" - # set basic install directories - vars['LIBDEST'] = get_path('stdlib') - vars['BINLIBDEST'] = get_path('platstdlib') - vars['INCLUDEPY'] = get_path('include') - vars['SO'] = '.pyd' - vars['EXE'] = '.exe' - vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT - vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) - -# -# public APIs -# - - -def parse_config_h(fp, vars=None): - """Parse a config.h-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - if vars is None: - vars = {} - define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") - undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") - - while True: - line = fp.readline() - if not line: - break - m = define_rx.match(line) - if m: - n, v = m.group(1, 2) - try: - v = int(v) - except ValueError: - pass - vars[n] = v - else: - m = undef_rx.match(line) - if m: - vars[m.group(1)] = 0 - return vars - - -def get_config_h_filename(): - """Return the path of pyconfig.h.""" - if _PYTHON_BUILD: - if os.name == "nt": - inc_dir = os.path.join(_PROJECT_BASE, "PC") - else: - inc_dir = _PROJECT_BASE - else: - inc_dir = get_path('platinclude') - return os.path.join(inc_dir, 'pyconfig.h') - - -def get_scheme_names(): - """Return a tuple containing the schemes names.""" - return tuple(sorted(_SCHEMES.sections())) - - -def get_path_names(): - """Return a tuple containing the paths names.""" - # xxx see if we want a static list - return _SCHEMES.options('posix_prefix') - - -def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): - """Return a mapping containing an install scheme. - - ``scheme`` is the install scheme name. If not provided, it will - return the default scheme for the current platform. - """ - _ensure_cfg_read() - if expand: - return _expand_vars(scheme, vars) - else: - return dict(_SCHEMES.items(scheme)) - - -def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): - """Return a path corresponding to the scheme. - - ``scheme`` is the install scheme name. - """ - return get_paths(scheme, vars, expand)[name] - - -def get_config_vars(*args): - """With no arguments, return a dictionary of all configuration - variables relevant for the current platform. - - On Unix, this means every variable defined in Python's installed Makefile; - On Windows and Mac OS it's a much smaller set. - - With arguments, return a list of values that result from looking up - each argument in the configuration variable dictionary. - """ - global _CONFIG_VARS - if _CONFIG_VARS is None: - _CONFIG_VARS = {} - # Normalized versions of prefix and exec_prefix are handy to have; - # in fact, these are the standard versions used most places in the - # distutils2 module. - _CONFIG_VARS['prefix'] = _PREFIX - _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX - _CONFIG_VARS['py_version'] = _PY_VERSION - _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT - _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] - _CONFIG_VARS['base'] = _PREFIX - _CONFIG_VARS['platbase'] = _EXEC_PREFIX - _CONFIG_VARS['projectbase'] = _PROJECT_BASE - try: - _CONFIG_VARS['abiflags'] = sys.abiflags - except AttributeError: - # sys.abiflags may not be defined on all platforms. - _CONFIG_VARS['abiflags'] = '' - - if os.name in ('nt', 'os2'): - _init_non_posix(_CONFIG_VARS) - if os.name == 'posix': - _init_posix(_CONFIG_VARS) - # Setting 'userbase' is done below the call to the - # init function to enable using 'get_config_var' in - # the init-function. - if sys.version >= '2.6': - _CONFIG_VARS['userbase'] = _getuserbase() - - if 'srcdir' not in _CONFIG_VARS: - _CONFIG_VARS['srcdir'] = _PROJECT_BASE - else: - _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir']) - - # Convert srcdir into an absolute path if it appears necessary. - # Normally it is relative to the build directory. However, during - # testing, for example, we might be running a non-installed python - # from a different directory. - if _PYTHON_BUILD and os.name == "posix": - base = _PROJECT_BASE - try: - cwd = os.getcwd() - except OSError: - cwd = None - if (not os.path.isabs(_CONFIG_VARS['srcdir']) and - base != cwd): - # srcdir is relative and we are not in the same directory - # as the executable. Assume executable is in the build - # directory and make srcdir absolute. - srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) - _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) - - if sys.platform == 'darwin': - kernel_version = os.uname()[2] # Kernel version (8.4.3) - major_version = int(kernel_version.split('.')[0]) - - if major_version < 8: - # On Mac OS X before 10.4, check if -arch and -isysroot - # are in CFLAGS or LDFLAGS and remove them if they are. - # This is needed when building extensions on a 10.3 system - # using a universal build of python. - for key in ('LDFLAGS', 'BASECFLAGS', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - flags = _CONFIG_VARS[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = re.sub('-isysroot [^ \t]*', ' ', flags) - _CONFIG_VARS[key] = flags - else: - # Allow the user to override the architecture flags using - # an environment variable. - # NOTE: This name was introduced by Apple in OSX 10.5 and - # is used by several scripting languages distributed with - # that OS release. - if 'ARCHFLAGS' in os.environ: - arch = os.environ['ARCHFLAGS'] - for key in ('LDFLAGS', 'BASECFLAGS', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _CONFIG_VARS[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) - flags = flags + ' ' + arch - _CONFIG_VARS[key] = flags - - # If we're on OSX 10.5 or later and the user tries to - # compiles an extension using an SDK that is not present - # on the current machine it is better to not use an SDK - # than to fail. - # - # The major usecase for this is users using a Python.org - # binary installer on OSX 10.6: that installer uses - # the 10.4u SDK, but that SDK is not installed by default - # when you install Xcode. - # - CFLAGS = _CONFIG_VARS.get('CFLAGS', '') - m = re.search('-isysroot\s+(\S+)', CFLAGS) - if m is not None: - sdk = m.group(1) - if not os.path.exists(sdk): - for key in ('LDFLAGS', 'BASECFLAGS', - # a number of derived variables. These need to be - # patched up as well. - 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): - - flags = _CONFIG_VARS[key] - flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) - _CONFIG_VARS[key] = flags - - if args: - vals = [] - for name in args: - vals.append(_CONFIG_VARS.get(name)) - return vals - else: - return _CONFIG_VARS - - -def get_config_var(name): - """Return the value of a single variable using the dictionary returned by - 'get_config_vars()'. - - Equivalent to get_config_vars().get(name) - """ - return get_config_vars().get(name) - - -def get_platform(): - """Return a string that identifies the current platform. - - This is used mainly to distinguish platform-specific build directories and - platform-specific built distributions. Typically includes the OS name - and version and the architecture (as supplied by 'os.uname()'), - although the exact information included depends on the OS; eg. for IRIX - the architecture isn't particularly important (IRIX only runs on SGI - hardware), but for Linux the kernel version isn't particularly - important. - - Examples of returned values: - linux-i586 - linux-alpha (?) - solaris-2.6-sun4u - irix-5.3 - irix64-6.2 - - Windows will return one of: - win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) - win-ia64 (64bit Windows on Itanium) - win32 (all others - specifically, sys.platform is returned) - - For other non-POSIX platforms, currently just returns 'sys.platform'. - """ - if os.name == 'nt': - # sniff sys.version for architecture. - prefix = " bit (" - i = sys.version.find(prefix) - if i == -1: - return sys.platform - j = sys.version.find(")", i) - look = sys.version[i+len(prefix):j].lower() - if look == 'amd64': - return 'win-amd64' - if look == 'itanium': - return 'win-ia64' - return sys.platform - - if os.name != "posix" or not hasattr(os, 'uname'): - # XXX what about the architecture? NT is Intel or Alpha, - # Mac OS is M68k or PPC, etc. - return sys.platform - - # Try to distinguish various flavours of Unix - osname, host, release, version, machine = os.uname() - - # Convert the OS name to lowercase, remove '/' characters - # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") - osname = osname.lower().replace('/', '') - machine = machine.replace(' ', '_') - machine = machine.replace('/', '-') - - if osname[:5] == "linux": - # At least on Linux/Intel, 'machine' is the processor -- - # i386, etc. - # XXX what about Alpha, SPARC, etc? - return "%s-%s" % (osname, machine) - elif osname[:5] == "sunos": - if release[0] >= "5": # SunOS 5 == Solaris 2 - osname = "solaris" - release = "%d.%s" % (int(release[0]) - 3, release[2:]) - # fall through to standard osname-release-machine representation - elif osname[:4] == "irix": # could be "irix64"! - return "%s-%s" % (osname, release) - elif osname[:3] == "aix": - return "%s-%s.%s" % (osname, version, release) - elif osname[:6] == "cygwin": - osname = "cygwin" - rel_re = re.compile(r'[\d.]+') - m = rel_re.match(release) - if m: - release = m.group() - elif osname[:6] == "darwin": - # - # For our purposes, we'll assume that the system version from - # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set - # to. This makes the compatibility story a bit more sane because the - # machine is going to compile and link as if it were - # MACOSX_DEPLOYMENT_TARGET. - cfgvars = get_config_vars() - macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') - - if True: - # Always calculate the release of the running machine, - # needed to determine if we can build fat binaries or not. - - macrelease = macver - # Get the system version. Reading this plist is a documented - # way to get the system version (see the documentation for - # the Gestalt Manager) - try: - f = open('/System/Library/CoreServices/SystemVersion.plist') - except IOError: - # We're on a plain darwin box, fall back to the default - # behaviour. - pass - else: - try: - m = re.search(r'ProductUserVisibleVersion\s*' - r'(.*?)', f.read()) - finally: - f.close() - if m is not None: - macrelease = '.'.join(m.group(1).split('.')[:2]) - # else: fall back to the default behaviour - - if not macver: - macver = macrelease - - if macver: - release = macver - osname = "macosx" - - if ((macrelease + '.') >= '10.4.' and - '-arch' in get_config_vars().get('CFLAGS', '').strip()): - # The universal build will build fat binaries, but not on - # systems before 10.4 - # - # Try to detect 4-way universal builds, those have machine-type - # 'universal' instead of 'fat'. - - machine = 'fat' - cflags = get_config_vars().get('CFLAGS') - - archs = re.findall('-arch\s+(\S+)', cflags) - archs = tuple(sorted(set(archs))) - - if len(archs) == 1: - machine = archs[0] - elif archs == ('i386', 'ppc'): - machine = 'fat' - elif archs == ('i386', 'x86_64'): - machine = 'intel' - elif archs == ('i386', 'ppc', 'x86_64'): - machine = 'fat3' - elif archs == ('ppc64', 'x86_64'): - machine = 'fat64' - elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): - machine = 'universal' - else: - raise ValueError( - "Don't know machine value for archs=%r" % (archs,)) - - elif machine == 'i386': - # On OSX the machine type returned by uname is always the - # 32-bit variant, even if the executable architecture is - # the 64-bit variant - if sys.maxsize >= 2**32: - machine = 'x86_64' - - elif machine in ('PowerPC', 'Power_Macintosh'): - # Pick a sane name for the PPC architecture. - # See 'i386' case - if sys.maxsize >= 2**32: - machine = 'ppc64' - else: - machine = 'ppc' - - return "%s-%s-%s" % (osname, release, machine) - - -def get_python_version(): - return _PY_VERSION_SHORT - - -def _print_dict(title, data): - for index, (key, value) in enumerate(sorted(data.items())): - if index == 0: - print('%s: ' % (title)) - print('\t%s = "%s"' % (key, value)) - - -def _main(): - """Display all information sysconfig detains.""" - print('Platform: "%s"' % get_platform()) - print('Python version: "%s"' % get_python_version()) - print('Current installation scheme: "%s"' % _get_default_scheme()) - print() - _print_dict('Paths', get_paths()) - print() - _print_dict('Variables', get_config_vars()) - - -if __name__ == '__main__': - _main() diff --git a/awx/lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py b/awx/lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py deleted file mode 100644 index 0580fb7953..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py +++ /dev/null @@ -1,2607 +0,0 @@ -#------------------------------------------------------------------- -# tarfile.py -#------------------------------------------------------------------- -# Copyright (C) 2002 Lars Gustaebel -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -from __future__ import print_function - -"""Read from and write to tar format archives. -""" - -__version__ = "$Revision$" - -version = "0.9.0" -__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" -__date__ = "$Date: 2011-02-25 17:42:01 +0200 (Fri, 25 Feb 2011) $" -__cvsid__ = "$Id: tarfile.py 88586 2011-02-25 15:42:01Z marc-andre.lemburg $" -__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." - -#--------- -# Imports -#--------- -import sys -import os -import stat -import errno -import time -import struct -import copy -import re - -try: - import grp, pwd -except ImportError: - grp = pwd = None - -# os.symlink on Windows prior to 6.0 raises NotImplementedError -symlink_exception = (AttributeError, NotImplementedError) -try: - # WindowsError (1314) will be raised if the caller does not hold the - # SeCreateSymbolicLinkPrivilege privilege - symlink_exception += (WindowsError,) -except NameError: - pass - -# from tarfile import * -__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] - -if sys.version_info[0] < 3: - import __builtin__ as builtins -else: - import builtins - -_open = builtins.open # Since 'open' is TarFile.open - -#--------------------------------------------------------- -# tar constants -#--------------------------------------------------------- -NUL = b"\0" # the null character -BLOCKSIZE = 512 # length of processing blocks -RECORDSIZE = BLOCKSIZE * 20 # length of records -GNU_MAGIC = b"ustar \0" # magic gnu tar string -POSIX_MAGIC = b"ustar\x0000" # magic posix tar string - -LENGTH_NAME = 100 # maximum length of a filename -LENGTH_LINK = 100 # maximum length of a linkname -LENGTH_PREFIX = 155 # maximum length of the prefix field - -REGTYPE = b"0" # regular file -AREGTYPE = b"\0" # regular file -LNKTYPE = b"1" # link (inside tarfile) -SYMTYPE = b"2" # symbolic link -CHRTYPE = b"3" # character special device -BLKTYPE = b"4" # block special device -DIRTYPE = b"5" # directory -FIFOTYPE = b"6" # fifo special device -CONTTYPE = b"7" # contiguous file - -GNUTYPE_LONGNAME = b"L" # GNU tar longname -GNUTYPE_LONGLINK = b"K" # GNU tar longlink -GNUTYPE_SPARSE = b"S" # GNU tar sparse file - -XHDTYPE = b"x" # POSIX.1-2001 extended header -XGLTYPE = b"g" # POSIX.1-2001 global header -SOLARIS_XHDTYPE = b"X" # Solaris extended header - -USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format -GNU_FORMAT = 1 # GNU tar format -PAX_FORMAT = 2 # POSIX.1-2001 (pax) format -DEFAULT_FORMAT = GNU_FORMAT - -#--------------------------------------------------------- -# tarfile constants -#--------------------------------------------------------- -# File types that tarfile supports: -SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, - SYMTYPE, DIRTYPE, FIFOTYPE, - CONTTYPE, CHRTYPE, BLKTYPE, - GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# File types that will be treated as a regular file. -REGULAR_TYPES = (REGTYPE, AREGTYPE, - CONTTYPE, GNUTYPE_SPARSE) - -# File types that are part of the GNU tar format. -GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, - GNUTYPE_SPARSE) - -# Fields from a pax header that override a TarInfo attribute. -PAX_FIELDS = ("path", "linkpath", "size", "mtime", - "uid", "gid", "uname", "gname") - -# Fields from a pax header that are affected by hdrcharset. -PAX_NAME_FIELDS = set(("path", "linkpath", "uname", "gname")) - -# Fields in a pax header that are numbers, all other fields -# are treated as strings. -PAX_NUMBER_FIELDS = { - "atime": float, - "ctime": float, - "mtime": float, - "uid": int, - "gid": int, - "size": int -} - -#--------------------------------------------------------- -# Bits used in the mode field, values in octal. -#--------------------------------------------------------- -S_IFLNK = 0o120000 # symbolic link -S_IFREG = 0o100000 # regular file -S_IFBLK = 0o060000 # block device -S_IFDIR = 0o040000 # directory -S_IFCHR = 0o020000 # character device -S_IFIFO = 0o010000 # fifo - -TSUID = 0o4000 # set UID on execution -TSGID = 0o2000 # set GID on execution -TSVTX = 0o1000 # reserved - -TUREAD = 0o400 # read by owner -TUWRITE = 0o200 # write by owner -TUEXEC = 0o100 # execute/search by owner -TGREAD = 0o040 # read by group -TGWRITE = 0o020 # write by group -TGEXEC = 0o010 # execute/search by group -TOREAD = 0o004 # read by other -TOWRITE = 0o002 # write by other -TOEXEC = 0o001 # execute/search by other - -#--------------------------------------------------------- -# initialization -#--------------------------------------------------------- -if os.name in ("nt", "ce"): - ENCODING = "utf-8" -else: - ENCODING = sys.getfilesystemencoding() - -#--------------------------------------------------------- -# Some useful functions -#--------------------------------------------------------- - -def stn(s, length, encoding, errors): - """Convert a string to a null-terminated bytes object. - """ - s = s.encode(encoding, errors) - return s[:length] + (length - len(s)) * NUL - -def nts(s, encoding, errors): - """Convert a null-terminated bytes object to a string. - """ - p = s.find(b"\0") - if p != -1: - s = s[:p] - return s.decode(encoding, errors) - -def nti(s): - """Convert a number field to a python number. - """ - # There are two possible encodings for a number field, see - # itn() below. - if s[0] != chr(0o200): - try: - n = int(nts(s, "ascii", "strict") or "0", 8) - except ValueError: - raise InvalidHeaderError("invalid header") - else: - n = 0 - for i in range(len(s) - 1): - n <<= 8 - n += ord(s[i + 1]) - return n - -def itn(n, digits=8, format=DEFAULT_FORMAT): - """Convert a python number to a number field. - """ - # POSIX 1003.1-1988 requires numbers to be encoded as a string of - # octal digits followed by a null-byte, this allows values up to - # (8**(digits-1))-1. GNU tar allows storing numbers greater than - # that if necessary. A leading 0o200 byte indicates this particular - # encoding, the following digits-1 bytes are a big-endian - # representation. This allows values up to (256**(digits-1))-1. - if 0 <= n < 8 ** (digits - 1): - s = ("%0*o" % (digits - 1, n)).encode("ascii") + NUL - else: - if format != GNU_FORMAT or n >= 256 ** (digits - 1): - raise ValueError("overflow in number field") - - if n < 0: - # XXX We mimic GNU tar's behaviour with negative numbers, - # this could raise OverflowError. - n = struct.unpack("L", struct.pack("l", n))[0] - - s = bytearray() - for i in range(digits - 1): - s.insert(0, n & 0o377) - n >>= 8 - s.insert(0, 0o200) - return s - -def calc_chksums(buf): - """Calculate the checksum for a member's header by summing up all - characters except for the chksum field which is treated as if - it was filled with spaces. According to the GNU tar sources, - some tars (Sun and NeXT) calculate chksum with signed char, - which will be different if there are chars in the buffer with - the high bit set. So we calculate two checksums, unsigned and - signed. - """ - unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512])) - signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512])) - return unsigned_chksum, signed_chksum - -def copyfileobj(src, dst, length=None): - """Copy length bytes from fileobj src to fileobj dst. - If length is None, copy the entire content. - """ - if length == 0: - return - if length is None: - while True: - buf = src.read(16*1024) - if not buf: - break - dst.write(buf) - return - - BUFSIZE = 16 * 1024 - blocks, remainder = divmod(length, BUFSIZE) - for b in range(blocks): - buf = src.read(BUFSIZE) - if len(buf) < BUFSIZE: - raise IOError("end of file reached") - dst.write(buf) - - if remainder != 0: - buf = src.read(remainder) - if len(buf) < remainder: - raise IOError("end of file reached") - dst.write(buf) - return - -filemode_table = ( - ((S_IFLNK, "l"), - (S_IFREG, "-"), - (S_IFBLK, "b"), - (S_IFDIR, "d"), - (S_IFCHR, "c"), - (S_IFIFO, "p")), - - ((TUREAD, "r"),), - ((TUWRITE, "w"),), - ((TUEXEC|TSUID, "s"), - (TSUID, "S"), - (TUEXEC, "x")), - - ((TGREAD, "r"),), - ((TGWRITE, "w"),), - ((TGEXEC|TSGID, "s"), - (TSGID, "S"), - (TGEXEC, "x")), - - ((TOREAD, "r"),), - ((TOWRITE, "w"),), - ((TOEXEC|TSVTX, "t"), - (TSVTX, "T"), - (TOEXEC, "x")) -) - -def filemode(mode): - """Convert a file's mode to a string of the form - -rwxrwxrwx. - Used by TarFile.list() - """ - perm = [] - for table in filemode_table: - for bit, char in table: - if mode & bit == bit: - perm.append(char) - break - else: - perm.append("-") - return "".join(perm) - -class TarError(Exception): - """Base exception.""" - pass -class ExtractError(TarError): - """General exception for extract errors.""" - pass -class ReadError(TarError): - """Exception for unreadble tar archives.""" - pass -class CompressionError(TarError): - """Exception for unavailable compression methods.""" - pass -class StreamError(TarError): - """Exception for unsupported operations on stream-like TarFiles.""" - pass -class HeaderError(TarError): - """Base exception for header errors.""" - pass -class EmptyHeaderError(HeaderError): - """Exception for empty headers.""" - pass -class TruncatedHeaderError(HeaderError): - """Exception for truncated headers.""" - pass -class EOFHeaderError(HeaderError): - """Exception for end of file headers.""" - pass -class InvalidHeaderError(HeaderError): - """Exception for invalid headers.""" - pass -class SubsequentHeaderError(HeaderError): - """Exception for missing and invalid extended headers.""" - pass - -#--------------------------- -# internal stream interface -#--------------------------- -class _LowLevelFile(object): - """Low-level file object. Supports reading and writing. - It is used instead of a regular file object for streaming - access. - """ - - def __init__(self, name, mode): - mode = { - "r": os.O_RDONLY, - "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, - }[mode] - if hasattr(os, "O_BINARY"): - mode |= os.O_BINARY - self.fd = os.open(name, mode, 0o666) - - def close(self): - os.close(self.fd) - - def read(self, size): - return os.read(self.fd, size) - - def write(self, s): - os.write(self.fd, s) - -class _Stream(object): - """Class that serves as an adapter between TarFile and - a stream-like object. The stream-like object only - needs to have a read() or write() method and is accessed - blockwise. Use of gzip or bzip2 compression is possible. - A stream-like object could be for example: sys.stdin, - sys.stdout, a socket, a tape device etc. - - _Stream is intended to be used only internally. - """ - - def __init__(self, name, mode, comptype, fileobj, bufsize): - """Construct a _Stream object. - """ - self._extfileobj = True - if fileobj is None: - fileobj = _LowLevelFile(name, mode) - self._extfileobj = False - - if comptype == '*': - # Enable transparent compression detection for the - # stream interface - fileobj = _StreamProxy(fileobj) - comptype = fileobj.getcomptype() - - self.name = name or "" - self.mode = mode - self.comptype = comptype - self.fileobj = fileobj - self.bufsize = bufsize - self.buf = b"" - self.pos = 0 - self.closed = False - - try: - if comptype == "gz": - try: - import zlib - except ImportError: - raise CompressionError("zlib module is not available") - self.zlib = zlib - self.crc = zlib.crc32(b"") - if mode == "r": - self._init_read_gz() - else: - self._init_write_gz() - - if comptype == "bz2": - try: - import bz2 - except ImportError: - raise CompressionError("bz2 module is not available") - if mode == "r": - self.dbuf = b"" - self.cmp = bz2.BZ2Decompressor() - else: - self.cmp = bz2.BZ2Compressor() - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - def __del__(self): - if hasattr(self, "closed") and not self.closed: - self.close() - - def _init_write_gz(self): - """Initialize for writing with gzip compression. - """ - self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, - -self.zlib.MAX_WBITS, - self.zlib.DEF_MEM_LEVEL, - 0) - timestamp = struct.pack(" self.bufsize: - self.fileobj.write(self.buf[:self.bufsize]) - self.buf = self.buf[self.bufsize:] - - def close(self): - """Close the _Stream object. No operation should be - done on it afterwards. - """ - if self.closed: - return - - if self.mode == "w" and self.comptype != "tar": - self.buf += self.cmp.flush() - - if self.mode == "w" and self.buf: - self.fileobj.write(self.buf) - self.buf = b"" - if self.comptype == "gz": - # The native zlib crc is an unsigned 32-bit integer, but - # the Python wrapper implicitly casts that to a signed C - # long. So, on a 32-bit box self.crc may "look negative", - # while the same crc on a 64-bit box may "look positive". - # To avoid irksome warnings from the `struct` module, force - # it to look positive on all boxes. - self.fileobj.write(struct.pack("= 0: - blocks, remainder = divmod(pos - self.pos, self.bufsize) - for i in range(blocks): - self.read(self.bufsize) - self.read(remainder) - else: - raise StreamError("seeking backwards is not allowed") - return self.pos - - def read(self, size=None): - """Return the next size number of bytes from the stream. - If size is not defined, return all bytes of the stream - up to EOF. - """ - if size is None: - t = [] - while True: - buf = self._read(self.bufsize) - if not buf: - break - t.append(buf) - buf = "".join(t) - else: - buf = self._read(size) - self.pos += len(buf) - return buf - - def _read(self, size): - """Return size bytes from the stream. - """ - if self.comptype == "tar": - return self.__read(size) - - c = len(self.dbuf) - while c < size: - buf = self.__read(self.bufsize) - if not buf: - break - try: - buf = self.cmp.decompress(buf) - except IOError: - raise ReadError("invalid compressed data") - self.dbuf += buf - c += len(buf) - buf = self.dbuf[:size] - self.dbuf = self.dbuf[size:] - return buf - - def __read(self, size): - """Return size bytes from stream. If internal buffer is empty, - read another block from the stream. - """ - c = len(self.buf) - while c < size: - buf = self.fileobj.read(self.bufsize) - if not buf: - break - self.buf += buf - c += len(buf) - buf = self.buf[:size] - self.buf = self.buf[size:] - return buf -# class _Stream - -class _StreamProxy(object): - """Small proxy class that enables transparent compression - detection for the Stream interface (mode 'r|*'). - """ - - def __init__(self, fileobj): - self.fileobj = fileobj - self.buf = self.fileobj.read(BLOCKSIZE) - - def read(self, size): - self.read = self.fileobj.read - return self.buf - - def getcomptype(self): - if self.buf.startswith(b"\037\213\010"): - return "gz" - if self.buf.startswith(b"BZh91"): - return "bz2" - return "tar" - - def close(self): - self.fileobj.close() -# class StreamProxy - -class _BZ2Proxy(object): - """Small proxy class that enables external file object - support for "r:bz2" and "w:bz2" modes. This is actually - a workaround for a limitation in bz2 module's BZ2File - class which (unlike gzip.GzipFile) has no support for - a file object argument. - """ - - blocksize = 16 * 1024 - - def __init__(self, fileobj, mode): - self.fileobj = fileobj - self.mode = mode - self.name = getattr(self.fileobj, "name", None) - self.init() - - def init(self): - import bz2 - self.pos = 0 - if self.mode == "r": - self.bz2obj = bz2.BZ2Decompressor() - self.fileobj.seek(0) - self.buf = b"" - else: - self.bz2obj = bz2.BZ2Compressor() - - def read(self, size): - x = len(self.buf) - while x < size: - raw = self.fileobj.read(self.blocksize) - if not raw: - break - data = self.bz2obj.decompress(raw) - self.buf += data - x += len(data) - - buf = self.buf[:size] - self.buf = self.buf[size:] - self.pos += len(buf) - return buf - - def seek(self, pos): - if pos < self.pos: - self.init() - self.read(pos - self.pos) - - def tell(self): - return self.pos - - def write(self, data): - self.pos += len(data) - raw = self.bz2obj.compress(data) - self.fileobj.write(raw) - - def close(self): - if self.mode == "w": - raw = self.bz2obj.flush() - self.fileobj.write(raw) -# class _BZ2Proxy - -#------------------------ -# Extraction file object -#------------------------ -class _FileInFile(object): - """A thin wrapper around an existing file object that - provides a part of its data as an individual file - object. - """ - - def __init__(self, fileobj, offset, size, blockinfo=None): - self.fileobj = fileobj - self.offset = offset - self.size = size - self.position = 0 - - if blockinfo is None: - blockinfo = [(0, size)] - - # Construct a map with data and zero blocks. - self.map_index = 0 - self.map = [] - lastpos = 0 - realpos = self.offset - for offset, size in blockinfo: - if offset > lastpos: - self.map.append((False, lastpos, offset, None)) - self.map.append((True, offset, offset + size, realpos)) - realpos += size - lastpos = offset + size - if lastpos < self.size: - self.map.append((False, lastpos, self.size, None)) - - def seekable(self): - if not hasattr(self.fileobj, "seekable"): - # XXX gzip.GzipFile and bz2.BZ2File - return True - return self.fileobj.seekable() - - def tell(self): - """Return the current file position. - """ - return self.position - - def seek(self, position): - """Seek to a position in the file. - """ - self.position = position - - def read(self, size=None): - """Read data from the file. - """ - if size is None: - size = self.size - self.position - else: - size = min(size, self.size - self.position) - - buf = b"" - while size > 0: - while True: - data, start, stop, offset = self.map[self.map_index] - if start <= self.position < stop: - break - else: - self.map_index += 1 - if self.map_index == len(self.map): - self.map_index = 0 - length = min(size, stop - self.position) - if data: - self.fileobj.seek(offset + (self.position - start)) - buf += self.fileobj.read(length) - else: - buf += NUL * length - size -= length - self.position += length - return buf -#class _FileInFile - - -class ExFileObject(object): - """File-like object for reading an archive member. - Is returned by TarFile.extractfile(). - """ - blocksize = 1024 - - def __init__(self, tarfile, tarinfo): - self.fileobj = _FileInFile(tarfile.fileobj, - tarinfo.offset_data, - tarinfo.size, - tarinfo.sparse) - self.name = tarinfo.name - self.mode = "r" - self.closed = False - self.size = tarinfo.size - - self.position = 0 - self.buffer = b"" - - def readable(self): - return True - - def writable(self): - return False - - def seekable(self): - return self.fileobj.seekable() - - def read(self, size=None): - """Read at most size bytes from the file. If size is not - present or None, read all data until EOF is reached. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - buf = b"" - if self.buffer: - if size is None: - buf = self.buffer - self.buffer = b"" - else: - buf = self.buffer[:size] - self.buffer = self.buffer[size:] - - if size is None: - buf += self.fileobj.read() - else: - buf += self.fileobj.read(size - len(buf)) - - self.position += len(buf) - return buf - - # XXX TextIOWrapper uses the read1() method. - read1 = read - - def readline(self, size=-1): - """Read one entire line from the file. If size is present - and non-negative, return a string with at most that - size, which may be an incomplete line. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - pos = self.buffer.find(b"\n") + 1 - if pos == 0: - # no newline found. - while True: - buf = self.fileobj.read(self.blocksize) - self.buffer += buf - if not buf or b"\n" in buf: - pos = self.buffer.find(b"\n") + 1 - if pos == 0: - # no newline found. - pos = len(self.buffer) - break - - if size != -1: - pos = min(size, pos) - - buf = self.buffer[:pos] - self.buffer = self.buffer[pos:] - self.position += len(buf) - return buf - - def readlines(self): - """Return a list with all remaining lines. - """ - result = [] - while True: - line = self.readline() - if not line: break - result.append(line) - return result - - def tell(self): - """Return the current file position. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - return self.position - - def seek(self, pos, whence=os.SEEK_SET): - """Seek to a position in the file. - """ - if self.closed: - raise ValueError("I/O operation on closed file") - - if whence == os.SEEK_SET: - self.position = min(max(pos, 0), self.size) - elif whence == os.SEEK_CUR: - if pos < 0: - self.position = max(self.position + pos, 0) - else: - self.position = min(self.position + pos, self.size) - elif whence == os.SEEK_END: - self.position = max(min(self.size + pos, self.size), 0) - else: - raise ValueError("Invalid argument") - - self.buffer = b"" - self.fileobj.seek(self.position) - - def close(self): - """Close the file object. - """ - self.closed = True - - def __iter__(self): - """Get an iterator over the file's lines. - """ - while True: - line = self.readline() - if not line: - break - yield line -#class ExFileObject - -#------------------ -# Exported Classes -#------------------ -class TarInfo(object): - """Informational class which holds the details about an - archive member given by a tar header block. - TarInfo objects are returned by TarFile.getmember(), - TarFile.getmembers() and TarFile.gettarinfo() and are - usually created internally. - """ - - __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", - "chksum", "type", "linkname", "uname", "gname", - "devmajor", "devminor", - "offset", "offset_data", "pax_headers", "sparse", - "tarfile", "_sparse_structs", "_link_target") - - def __init__(self, name=""): - """Construct a TarInfo object. name is the optional name - of the member. - """ - self.name = name # member name - self.mode = 0o644 # file permissions - self.uid = 0 # user id - self.gid = 0 # group id - self.size = 0 # file size - self.mtime = 0 # modification time - self.chksum = 0 # header checksum - self.type = REGTYPE # member type - self.linkname = "" # link name - self.uname = "" # user name - self.gname = "" # group name - self.devmajor = 0 # device major number - self.devminor = 0 # device minor number - - self.offset = 0 # the tar header starts here - self.offset_data = 0 # the file's data starts here - - self.sparse = None # sparse member information - self.pax_headers = {} # pax header information - - # In pax headers the "name" and "linkname" field are called - # "path" and "linkpath". - def _getpath(self): - return self.name - def _setpath(self, name): - self.name = name - path = property(_getpath, _setpath) - - def _getlinkpath(self): - return self.linkname - def _setlinkpath(self, linkname): - self.linkname = linkname - linkpath = property(_getlinkpath, _setlinkpath) - - def __repr__(self): - return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) - - def get_info(self): - """Return the TarInfo's attributes as a dictionary. - """ - info = { - "name": self.name, - "mode": self.mode & 0o7777, - "uid": self.uid, - "gid": self.gid, - "size": self.size, - "mtime": self.mtime, - "chksum": self.chksum, - "type": self.type, - "linkname": self.linkname, - "uname": self.uname, - "gname": self.gname, - "devmajor": self.devmajor, - "devminor": self.devminor - } - - if info["type"] == DIRTYPE and not info["name"].endswith("/"): - info["name"] += "/" - - return info - - def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): - """Return a tar header as a string of 512 byte blocks. - """ - info = self.get_info() - - if format == USTAR_FORMAT: - return self.create_ustar_header(info, encoding, errors) - elif format == GNU_FORMAT: - return self.create_gnu_header(info, encoding, errors) - elif format == PAX_FORMAT: - return self.create_pax_header(info, encoding) - else: - raise ValueError("invalid format") - - def create_ustar_header(self, info, encoding, errors): - """Return the object as a ustar header block. - """ - info["magic"] = POSIX_MAGIC - - if len(info["linkname"]) > LENGTH_LINK: - raise ValueError("linkname is too long") - - if len(info["name"]) > LENGTH_NAME: - info["prefix"], info["name"] = self._posix_split_name(info["name"]) - - return self._create_header(info, USTAR_FORMAT, encoding, errors) - - def create_gnu_header(self, info, encoding, errors): - """Return the object as a GNU header block sequence. - """ - info["magic"] = GNU_MAGIC - - buf = b"" - if len(info["linkname"]) > LENGTH_LINK: - buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) - - if len(info["name"]) > LENGTH_NAME: - buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) - - return buf + self._create_header(info, GNU_FORMAT, encoding, errors) - - def create_pax_header(self, info, encoding): - """Return the object as a ustar header block. If it cannot be - represented this way, prepend a pax extended header sequence - with supplement information. - """ - info["magic"] = POSIX_MAGIC - pax_headers = self.pax_headers.copy() - - # Test string fields for values that exceed the field length or cannot - # be represented in ASCII encoding. - for name, hname, length in ( - ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), - ("uname", "uname", 32), ("gname", "gname", 32)): - - if hname in pax_headers: - # The pax header has priority. - continue - - # Try to encode the string as ASCII. - try: - info[name].encode("ascii", "strict") - except UnicodeEncodeError: - pax_headers[hname] = info[name] - continue - - if len(info[name]) > length: - pax_headers[hname] = info[name] - - # Test number fields for values that exceed the field limit or values - # that like to be stored as float. - for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): - if name in pax_headers: - # The pax header has priority. Avoid overflow. - info[name] = 0 - continue - - val = info[name] - if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): - pax_headers[name] = str(val) - info[name] = 0 - - # Create a pax extended header if necessary. - if pax_headers: - buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) - else: - buf = b"" - - return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") - - @classmethod - def create_pax_global_header(cls, pax_headers): - """Return the object as a pax global header block sequence. - """ - return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf8") - - def _posix_split_name(self, name): - """Split a name longer than 100 chars into a prefix - and a name part. - """ - prefix = name[:LENGTH_PREFIX + 1] - while prefix and prefix[-1] != "/": - prefix = prefix[:-1] - - name = name[len(prefix):] - prefix = prefix[:-1] - - if not prefix or len(name) > LENGTH_NAME: - raise ValueError("name is too long") - return prefix, name - - @staticmethod - def _create_header(info, format, encoding, errors): - """Return a header block. info is a dictionary with file - information, format must be one of the *_FORMAT constants. - """ - parts = [ - stn(info.get("name", ""), 100, encoding, errors), - itn(info.get("mode", 0) & 0o7777, 8, format), - itn(info.get("uid", 0), 8, format), - itn(info.get("gid", 0), 8, format), - itn(info.get("size", 0), 12, format), - itn(info.get("mtime", 0), 12, format), - b" ", # checksum field - info.get("type", REGTYPE), - stn(info.get("linkname", ""), 100, encoding, errors), - info.get("magic", POSIX_MAGIC), - stn(info.get("uname", ""), 32, encoding, errors), - stn(info.get("gname", ""), 32, encoding, errors), - itn(info.get("devmajor", 0), 8, format), - itn(info.get("devminor", 0), 8, format), - stn(info.get("prefix", ""), 155, encoding, errors) - ] - - buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) - chksum = calc_chksums(buf[-BLOCKSIZE:])[0] - buf = buf[:-364] + ("%06o\0" % chksum).encode("ascii") + buf[-357:] - return buf - - @staticmethod - def _create_payload(payload): - """Return the string payload filled with zero bytes - up to the next 512 byte border. - """ - blocks, remainder = divmod(len(payload), BLOCKSIZE) - if remainder > 0: - payload += (BLOCKSIZE - remainder) * NUL - return payload - - @classmethod - def _create_gnu_long_header(cls, name, type, encoding, errors): - """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence - for name. - """ - name = name.encode(encoding, errors) + NUL - - info = {} - info["name"] = "././@LongLink" - info["type"] = type - info["size"] = len(name) - info["magic"] = GNU_MAGIC - - # create extended header + name blocks. - return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ - cls._create_payload(name) - - @classmethod - def _create_pax_generic_header(cls, pax_headers, type, encoding): - """Return a POSIX.1-2008 extended or global header sequence - that contains a list of keyword, value pairs. The values - must be strings. - """ - # Check if one of the fields contains surrogate characters and thereby - # forces hdrcharset=BINARY, see _proc_pax() for more information. - binary = False - for keyword, value in pax_headers.items(): - try: - value.encode("utf8", "strict") - except UnicodeEncodeError: - binary = True - break - - records = b"" - if binary: - # Put the hdrcharset field at the beginning of the header. - records += b"21 hdrcharset=BINARY\n" - - for keyword, value in pax_headers.items(): - keyword = keyword.encode("utf8") - if binary: - # Try to restore the original byte representation of `value'. - # Needless to say, that the encoding must match the string. - value = value.encode(encoding, "surrogateescape") - else: - value = value.encode("utf8") - - l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' - n = p = 0 - while True: - n = l + len(str(p)) - if n == p: - break - p = n - records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" - - # We use a hardcoded "././@PaxHeader" name like star does - # instead of the one that POSIX recommends. - info = {} - info["name"] = "././@PaxHeader" - info["type"] = type - info["size"] = len(records) - info["magic"] = POSIX_MAGIC - - # Create pax header + record blocks. - return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ - cls._create_payload(records) - - @classmethod - def frombuf(cls, buf, encoding, errors): - """Construct a TarInfo object from a 512 byte bytes object. - """ - if len(buf) == 0: - raise EmptyHeaderError("empty header") - if len(buf) != BLOCKSIZE: - raise TruncatedHeaderError("truncated header") - if buf.count(NUL) == BLOCKSIZE: - raise EOFHeaderError("end of file header") - - chksum = nti(buf[148:156]) - if chksum not in calc_chksums(buf): - raise InvalidHeaderError("bad checksum") - - obj = cls() - obj.name = nts(buf[0:100], encoding, errors) - obj.mode = nti(buf[100:108]) - obj.uid = nti(buf[108:116]) - obj.gid = nti(buf[116:124]) - obj.size = nti(buf[124:136]) - obj.mtime = nti(buf[136:148]) - obj.chksum = chksum - obj.type = buf[156:157] - obj.linkname = nts(buf[157:257], encoding, errors) - obj.uname = nts(buf[265:297], encoding, errors) - obj.gname = nts(buf[297:329], encoding, errors) - obj.devmajor = nti(buf[329:337]) - obj.devminor = nti(buf[337:345]) - prefix = nts(buf[345:500], encoding, errors) - - # Old V7 tar format represents a directory as a regular - # file with a trailing slash. - if obj.type == AREGTYPE and obj.name.endswith("/"): - obj.type = DIRTYPE - - # The old GNU sparse format occupies some of the unused - # space in the buffer for up to 4 sparse structures. - # Save the them for later processing in _proc_sparse(). - if obj.type == GNUTYPE_SPARSE: - pos = 386 - structs = [] - for i in range(4): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[482]) - origsize = nti(buf[483:495]) - obj._sparse_structs = (structs, isextended, origsize) - - # Remove redundant slashes from directories. - if obj.isdir(): - obj.name = obj.name.rstrip("/") - - # Reconstruct a ustar longname. - if prefix and obj.type not in GNU_TYPES: - obj.name = prefix + "/" + obj.name - return obj - - @classmethod - def fromtarfile(cls, tarfile): - """Return the next TarInfo object from TarFile object - tarfile. - """ - buf = tarfile.fileobj.read(BLOCKSIZE) - obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) - obj.offset = tarfile.fileobj.tell() - BLOCKSIZE - return obj._proc_member(tarfile) - - #-------------------------------------------------------------------------- - # The following are methods that are called depending on the type of a - # member. The entry point is _proc_member() which can be overridden in a - # subclass to add custom _proc_*() methods. A _proc_*() method MUST - # implement the following - # operations: - # 1. Set self.offset_data to the position where the data blocks begin, - # if there is data that follows. - # 2. Set tarfile.offset to the position where the next member's header will - # begin. - # 3. Return self or another valid TarInfo object. - def _proc_member(self, tarfile): - """Choose the right processing method depending on - the type and call it. - """ - if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): - return self._proc_gnulong(tarfile) - elif self.type == GNUTYPE_SPARSE: - return self._proc_sparse(tarfile) - elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): - return self._proc_pax(tarfile) - else: - return self._proc_builtin(tarfile) - - def _proc_builtin(self, tarfile): - """Process a builtin type or an unknown type which - will be treated as a regular file. - """ - self.offset_data = tarfile.fileobj.tell() - offset = self.offset_data - if self.isreg() or self.type not in SUPPORTED_TYPES: - # Skip the following data blocks. - offset += self._block(self.size) - tarfile.offset = offset - - # Patch the TarInfo object with saved global - # header information. - self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) - - return self - - def _proc_gnulong(self, tarfile): - """Process the blocks that hold a GNU longname - or longlink member. - """ - buf = tarfile.fileobj.read(self._block(self.size)) - - # Fetch the next header and process it. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Patch the TarInfo object from the next header with - # the longname information. - next.offset = self.offset - if self.type == GNUTYPE_LONGNAME: - next.name = nts(buf, tarfile.encoding, tarfile.errors) - elif self.type == GNUTYPE_LONGLINK: - next.linkname = nts(buf, tarfile.encoding, tarfile.errors) - - return next - - def _proc_sparse(self, tarfile): - """Process a GNU sparse header plus extra headers. - """ - # We already collected some sparse structures in frombuf(). - structs, isextended, origsize = self._sparse_structs - del self._sparse_structs - - # Collect sparse structures from extended header blocks. - while isextended: - buf = tarfile.fileobj.read(BLOCKSIZE) - pos = 0 - for i in range(21): - try: - offset = nti(buf[pos:pos + 12]) - numbytes = nti(buf[pos + 12:pos + 24]) - except ValueError: - break - if offset and numbytes: - structs.append((offset, numbytes)) - pos += 24 - isextended = bool(buf[504]) - self.sparse = structs - - self.offset_data = tarfile.fileobj.tell() - tarfile.offset = self.offset_data + self._block(self.size) - self.size = origsize - return self - - def _proc_pax(self, tarfile): - """Process an extended or global header as described in - POSIX.1-2008. - """ - # Read the header information. - buf = tarfile.fileobj.read(self._block(self.size)) - - # A pax header stores supplemental information for either - # the following file (extended) or all following files - # (global). - if self.type == XGLTYPE: - pax_headers = tarfile.pax_headers - else: - pax_headers = tarfile.pax_headers.copy() - - # Check if the pax header contains a hdrcharset field. This tells us - # the encoding of the path, linkpath, uname and gname fields. Normally, - # these fields are UTF-8 encoded but since POSIX.1-2008 tar - # implementations are allowed to store them as raw binary strings if - # the translation to UTF-8 fails. - match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) - if match is not None: - pax_headers["hdrcharset"] = match.group(1).decode("utf8") - - # For the time being, we don't care about anything other than "BINARY". - # The only other value that is currently allowed by the standard is - # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. - hdrcharset = pax_headers.get("hdrcharset") - if hdrcharset == "BINARY": - encoding = tarfile.encoding - else: - encoding = "utf8" - - # Parse pax header information. A record looks like that: - # "%d %s=%s\n" % (length, keyword, value). length is the size - # of the complete record including the length field itself and - # the newline. keyword and value are both UTF-8 encoded strings. - regex = re.compile(br"(\d+) ([^=]+)=") - pos = 0 - while True: - match = regex.match(buf, pos) - if not match: - break - - length, keyword = match.groups() - length = int(length) - value = buf[match.end(2) + 1:match.start(1) + length - 1] - - # Normally, we could just use "utf8" as the encoding and "strict" - # as the error handler, but we better not take the risk. For - # example, GNU tar <= 1.23 is known to store filenames it cannot - # translate to UTF-8 as raw strings (unfortunately without a - # hdrcharset=BINARY header). - # We first try the strict standard encoding, and if that fails we - # fall back on the user's encoding and error handler. - keyword = self._decode_pax_field(keyword, "utf8", "utf8", - tarfile.errors) - if keyword in PAX_NAME_FIELDS: - value = self._decode_pax_field(value, encoding, tarfile.encoding, - tarfile.errors) - else: - value = self._decode_pax_field(value, "utf8", "utf8", - tarfile.errors) - - pax_headers[keyword] = value - pos += length - - # Fetch the next header. - try: - next = self.fromtarfile(tarfile) - except HeaderError: - raise SubsequentHeaderError("missing or bad subsequent header") - - # Process GNU sparse information. - if "GNU.sparse.map" in pax_headers: - # GNU extended sparse format version 0.1. - self._proc_gnusparse_01(next, pax_headers) - - elif "GNU.sparse.size" in pax_headers: - # GNU extended sparse format version 0.0. - self._proc_gnusparse_00(next, pax_headers, buf) - - elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": - # GNU extended sparse format version 1.0. - self._proc_gnusparse_10(next, pax_headers, tarfile) - - if self.type in (XHDTYPE, SOLARIS_XHDTYPE): - # Patch the TarInfo object with the extended header info. - next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) - next.offset = self.offset - - if "size" in pax_headers: - # If the extended header replaces the size field, - # we need to recalculate the offset where the next - # header starts. - offset = next.offset_data - if next.isreg() or next.type not in SUPPORTED_TYPES: - offset += next._block(next.size) - tarfile.offset = offset - - return next - - def _proc_gnusparse_00(self, next, pax_headers, buf): - """Process a GNU tar extended sparse header, version 0.0. - """ - offsets = [] - for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): - offsets.append(int(match.group(1))) - numbytes = [] - for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): - numbytes.append(int(match.group(1))) - next.sparse = list(zip(offsets, numbytes)) - - def _proc_gnusparse_01(self, next, pax_headers): - """Process a GNU tar extended sparse header, version 0.1. - """ - sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _proc_gnusparse_10(self, next, pax_headers, tarfile): - """Process a GNU tar extended sparse header, version 1.0. - """ - fields = None - sparse = [] - buf = tarfile.fileobj.read(BLOCKSIZE) - fields, buf = buf.split(b"\n", 1) - fields = int(fields) - while len(sparse) < fields * 2: - if b"\n" not in buf: - buf += tarfile.fileobj.read(BLOCKSIZE) - number, buf = buf.split(b"\n", 1) - sparse.append(int(number)) - next.offset_data = tarfile.fileobj.tell() - next.sparse = list(zip(sparse[::2], sparse[1::2])) - - def _apply_pax_info(self, pax_headers, encoding, errors): - """Replace fields with supplemental information from a previous - pax extended or global header. - """ - for keyword, value in pax_headers.items(): - if keyword == "GNU.sparse.name": - setattr(self, "path", value) - elif keyword == "GNU.sparse.size": - setattr(self, "size", int(value)) - elif keyword == "GNU.sparse.realsize": - setattr(self, "size", int(value)) - elif keyword in PAX_FIELDS: - if keyword in PAX_NUMBER_FIELDS: - try: - value = PAX_NUMBER_FIELDS[keyword](value) - except ValueError: - value = 0 - if keyword == "path": - value = value.rstrip("/") - setattr(self, keyword, value) - - self.pax_headers = pax_headers.copy() - - def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): - """Decode a single field from a pax record. - """ - try: - return value.decode(encoding, "strict") - except UnicodeDecodeError: - return value.decode(fallback_encoding, fallback_errors) - - def _block(self, count): - """Round up a byte count by BLOCKSIZE and return it, - e.g. _block(834) => 1024. - """ - blocks, remainder = divmod(count, BLOCKSIZE) - if remainder: - blocks += 1 - return blocks * BLOCKSIZE - - def isreg(self): - return self.type in REGULAR_TYPES - def isfile(self): - return self.isreg() - def isdir(self): - return self.type == DIRTYPE - def issym(self): - return self.type == SYMTYPE - def islnk(self): - return self.type == LNKTYPE - def ischr(self): - return self.type == CHRTYPE - def isblk(self): - return self.type == BLKTYPE - def isfifo(self): - return self.type == FIFOTYPE - def issparse(self): - return self.sparse is not None - def isdev(self): - return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) -# class TarInfo - -class TarFile(object): - """The TarFile Class provides an interface to tar archives. - """ - - debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) - - dereference = False # If true, add content of linked file to the - # tar file, else the link. - - ignore_zeros = False # If true, skips empty or invalid blocks and - # continues processing. - - errorlevel = 1 # If 0, fatal errors only appear in debug - # messages (if debug >= 0). If > 0, errors - # are passed to the caller as exceptions. - - format = DEFAULT_FORMAT # The format to use when creating an archive. - - encoding = ENCODING # Encoding for 8-bit character strings. - - errors = None # Error handler for unicode conversion. - - tarinfo = TarInfo # The default TarInfo class to use. - - fileobject = ExFileObject # The default ExFileObject class to use. - - def __init__(self, name=None, mode="r", fileobj=None, format=None, - tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, - errors="surrogateescape", pax_headers=None, debug=None, errorlevel=None): - """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to - read from an existing archive, 'a' to append data to an existing - file or 'w' to create a new file overwriting an existing one. `mode' - defaults to 'r'. - If `fileobj' is given, it is used for reading or writing data. If it - can be determined, `mode' is overridden by `fileobj's mode. - `fileobj' is not closed, when TarFile is closed. - """ - if len(mode) > 1 or mode not in "raw": - raise ValueError("mode must be 'r', 'a' or 'w'") - self.mode = mode - self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] - - if not fileobj: - if self.mode == "a" and not os.path.exists(name): - # Create nonexistent files in append mode. - self.mode = "w" - self._mode = "wb" - fileobj = bltn_open(name, self._mode) - self._extfileobj = False - else: - if name is None and hasattr(fileobj, "name"): - name = fileobj.name - if hasattr(fileobj, "mode"): - self._mode = fileobj.mode - self._extfileobj = True - self.name = os.path.abspath(name) if name else None - self.fileobj = fileobj - - # Init attributes. - if format is not None: - self.format = format - if tarinfo is not None: - self.tarinfo = tarinfo - if dereference is not None: - self.dereference = dereference - if ignore_zeros is not None: - self.ignore_zeros = ignore_zeros - if encoding is not None: - self.encoding = encoding - self.errors = errors - - if pax_headers is not None and self.format == PAX_FORMAT: - self.pax_headers = pax_headers - else: - self.pax_headers = {} - - if debug is not None: - self.debug = debug - if errorlevel is not None: - self.errorlevel = errorlevel - - # Init datastructures. - self.closed = False - self.members = [] # list of members as TarInfo objects - self._loaded = False # flag if all members have been read - self.offset = self.fileobj.tell() - # current position in the archive file - self.inodes = {} # dictionary caching the inodes of - # archive members already added - - try: - if self.mode == "r": - self.firstmember = None - self.firstmember = self.next() - - if self.mode == "a": - # Move to the end of the archive, - # before the first empty block. - while True: - self.fileobj.seek(self.offset) - try: - tarinfo = self.tarinfo.fromtarfile(self) - self.members.append(tarinfo) - except EOFHeaderError: - self.fileobj.seek(self.offset) - break - except HeaderError as e: - raise ReadError(str(e)) - - if self.mode in "aw": - self._loaded = True - - if self.pax_headers: - buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) - self.fileobj.write(buf) - self.offset += len(buf) - except: - if not self._extfileobj: - self.fileobj.close() - self.closed = True - raise - - #-------------------------------------------------------------------------- - # Below are the classmethods which act as alternate constructors to the - # TarFile class. The open() method is the only one that is needed for - # public use; it is the "super"-constructor and is able to select an - # adequate "sub"-constructor for a particular compression using the mapping - # from OPEN_METH. - # - # This concept allows one to subclass TarFile without losing the comfort of - # the super-constructor. A sub-constructor is registered and made available - # by adding it to the mapping in OPEN_METH. - - @classmethod - def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): - """Open a tar archive for reading, writing or appending. Return - an appropriate TarFile class. - - mode: - 'r' or 'r:*' open for reading with transparent compression - 'r:' open for reading exclusively uncompressed - 'r:gz' open for reading with gzip compression - 'r:bz2' open for reading with bzip2 compression - 'a' or 'a:' open for appending, creating the file if necessary - 'w' or 'w:' open for writing without compression - 'w:gz' open for writing with gzip compression - 'w:bz2' open for writing with bzip2 compression - - 'r|*' open a stream of tar blocks with transparent compression - 'r|' open an uncompressed stream of tar blocks for reading - 'r|gz' open a gzip compressed stream of tar blocks - 'r|bz2' open a bzip2 compressed stream of tar blocks - 'w|' open an uncompressed stream for writing - 'w|gz' open a gzip compressed stream for writing - 'w|bz2' open a bzip2 compressed stream for writing - """ - - if not name and not fileobj: - raise ValueError("nothing to open") - - if mode in ("r", "r:*"): - # Find out which *open() is appropriate for opening the file. - for comptype in cls.OPEN_METH: - func = getattr(cls, cls.OPEN_METH[comptype]) - if fileobj is not None: - saved_pos = fileobj.tell() - try: - return func(name, "r", fileobj, **kwargs) - except (ReadError, CompressionError) as e: - if fileobj is not None: - fileobj.seek(saved_pos) - continue - raise ReadError("file could not be opened successfully") - - elif ":" in mode: - filemode, comptype = mode.split(":", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - # Select the *open() function according to - # given compression. - if comptype in cls.OPEN_METH: - func = getattr(cls, cls.OPEN_METH[comptype]) - else: - raise CompressionError("unknown compression type %r" % comptype) - return func(name, filemode, fileobj, **kwargs) - - elif "|" in mode: - filemode, comptype = mode.split("|", 1) - filemode = filemode or "r" - comptype = comptype or "tar" - - if filemode not in "rw": - raise ValueError("mode must be 'r' or 'w'") - - stream = _Stream(name, filemode, comptype, fileobj, bufsize) - try: - t = cls(name, filemode, stream, **kwargs) - except: - stream.close() - raise - t._extfileobj = False - return t - - elif mode in "aw": - return cls.taropen(name, mode, fileobj, **kwargs) - - raise ValueError("undiscernible mode") - - @classmethod - def taropen(cls, name, mode="r", fileobj=None, **kwargs): - """Open uncompressed tar archive name for reading or writing. - """ - if len(mode) > 1 or mode not in "raw": - raise ValueError("mode must be 'r', 'a' or 'w'") - return cls(name, mode, fileobj, **kwargs) - - @classmethod - def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open gzip compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if len(mode) > 1 or mode not in "rw": - raise ValueError("mode must be 'r' or 'w'") - - try: - import gzip - gzip.GzipFile - except (ImportError, AttributeError): - raise CompressionError("gzip module is not available") - - extfileobj = fileobj is not None - try: - fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) - t = cls.taropen(name, mode, fileobj, **kwargs) - except IOError: - if not extfileobj and fileobj is not None: - fileobj.close() - if fileobj is None: - raise - raise ReadError("not a gzip file") - except: - if not extfileobj and fileobj is not None: - fileobj.close() - raise - t._extfileobj = extfileobj - return t - - @classmethod - def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): - """Open bzip2 compressed tar archive name for reading or writing. - Appending is not allowed. - """ - if len(mode) > 1 or mode not in "rw": - raise ValueError("mode must be 'r' or 'w'.") - - try: - import bz2 - except ImportError: - raise CompressionError("bz2 module is not available") - - if fileobj is not None: - fileobj = _BZ2Proxy(fileobj, mode) - else: - fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) - - try: - t = cls.taropen(name, mode, fileobj, **kwargs) - except (IOError, EOFError): - fileobj.close() - raise ReadError("not a bzip2 file") - t._extfileobj = False - return t - - # All *open() methods are registered here. - OPEN_METH = { - "tar": "taropen", # uncompressed tar - "gz": "gzopen", # gzip compressed tar - "bz2": "bz2open" # bzip2 compressed tar - } - - #-------------------------------------------------------------------------- - # The public methods which TarFile provides: - - def close(self): - """Close the TarFile. In write-mode, two finishing zero blocks are - appended to the archive. - """ - if self.closed: - return - - if self.mode in "aw": - self.fileobj.write(NUL * (BLOCKSIZE * 2)) - self.offset += (BLOCKSIZE * 2) - # fill up the end with zero-blocks - # (like option -b20 for tar does) - blocks, remainder = divmod(self.offset, RECORDSIZE) - if remainder > 0: - self.fileobj.write(NUL * (RECORDSIZE - remainder)) - - if not self._extfileobj: - self.fileobj.close() - self.closed = True - - def getmember(self, name): - """Return a TarInfo object for member `name'. If `name' can not be - found in the archive, KeyError is raised. If a member occurs more - than once in the archive, its last occurrence is assumed to be the - most up-to-date version. - """ - tarinfo = self._getmember(name) - if tarinfo is None: - raise KeyError("filename %r not found" % name) - return tarinfo - - def getmembers(self): - """Return the members of the archive as a list of TarInfo objects. The - list has the same order as the members in the archive. - """ - self._check() - if not self._loaded: # if we want to obtain a list of - self._load() # all members, we first have to - # scan the whole archive. - return self.members - - def getnames(self): - """Return the members of the archive as a list of their names. It has - the same order as the list returned by getmembers(). - """ - return [tarinfo.name for tarinfo in self.getmembers()] - - def gettarinfo(self, name=None, arcname=None, fileobj=None): - """Create a TarInfo object for either the file `name' or the file - object `fileobj' (using os.fstat on its file descriptor). You can - modify some of the TarInfo's attributes before you add it using - addfile(). If given, `arcname' specifies an alternative name for the - file in the archive. - """ - self._check("aw") - - # When fileobj is given, replace name by - # fileobj's real name. - if fileobj is not None: - name = fileobj.name - - # Building the name of the member in the archive. - # Backward slashes are converted to forward slashes, - # Absolute paths are turned to relative paths. - if arcname is None: - arcname = name - drv, arcname = os.path.splitdrive(arcname) - arcname = arcname.replace(os.sep, "/") - arcname = arcname.lstrip("/") - - # Now, fill the TarInfo object with - # information specific for the file. - tarinfo = self.tarinfo() - tarinfo.tarfile = self - - # Use os.stat or os.lstat, depending on platform - # and if symlinks shall be resolved. - if fileobj is None: - if hasattr(os, "lstat") and not self.dereference: - statres = os.lstat(name) - else: - statres = os.stat(name) - else: - statres = os.fstat(fileobj.fileno()) - linkname = "" - - stmd = statres.st_mode - if stat.S_ISREG(stmd): - inode = (statres.st_ino, statres.st_dev) - if not self.dereference and statres.st_nlink > 1 and \ - inode in self.inodes and arcname != self.inodes[inode]: - # Is it a hardlink to an already - # archived file? - type = LNKTYPE - linkname = self.inodes[inode] - else: - # The inode is added only if its valid. - # For win32 it is always 0. - type = REGTYPE - if inode[0]: - self.inodes[inode] = arcname - elif stat.S_ISDIR(stmd): - type = DIRTYPE - elif stat.S_ISFIFO(stmd): - type = FIFOTYPE - elif stat.S_ISLNK(stmd): - type = SYMTYPE - linkname = os.readlink(name) - elif stat.S_ISCHR(stmd): - type = CHRTYPE - elif stat.S_ISBLK(stmd): - type = BLKTYPE - else: - return None - - # Fill the TarInfo object with all - # information we can get. - tarinfo.name = arcname - tarinfo.mode = stmd - tarinfo.uid = statres.st_uid - tarinfo.gid = statres.st_gid - if type == REGTYPE: - tarinfo.size = statres.st_size - else: - tarinfo.size = 0 - tarinfo.mtime = statres.st_mtime - tarinfo.type = type - tarinfo.linkname = linkname - if pwd: - try: - tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] - except KeyError: - pass - if grp: - try: - tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] - except KeyError: - pass - - if type in (CHRTYPE, BLKTYPE): - if hasattr(os, "major") and hasattr(os, "minor"): - tarinfo.devmajor = os.major(statres.st_rdev) - tarinfo.devminor = os.minor(statres.st_rdev) - return tarinfo - - def list(self, verbose=True): - """Print a table of contents to sys.stdout. If `verbose' is False, only - the names of the members are printed. If it is True, an `ls -l'-like - output is produced. - """ - self._check() - - for tarinfo in self: - if verbose: - print(filemode(tarinfo.mode), end=' ') - print("%s/%s" % (tarinfo.uname or tarinfo.uid, - tarinfo.gname or tarinfo.gid), end=' ') - if tarinfo.ischr() or tarinfo.isblk(): - print("%10s" % ("%d,%d" \ - % (tarinfo.devmajor, tarinfo.devminor)), end=' ') - else: - print("%10d" % tarinfo.size, end=' ') - print("%d-%02d-%02d %02d:%02d:%02d" \ - % time.localtime(tarinfo.mtime)[:6], end=' ') - - print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') - - if verbose: - if tarinfo.issym(): - print("->", tarinfo.linkname, end=' ') - if tarinfo.islnk(): - print("link to", tarinfo.linkname, end=' ') - print() - - def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): - """Add the file `name' to the archive. `name' may be any type of file - (directory, fifo, symbolic link, etc.). If given, `arcname' - specifies an alternative name for the file in the archive. - Directories are added recursively by default. This can be avoided by - setting `recursive' to False. `exclude' is a function that should - return True for each filename to be excluded. `filter' is a function - that expects a TarInfo object argument and returns the changed - TarInfo object, if it returns None the TarInfo object will be - excluded from the archive. - """ - self._check("aw") - - if arcname is None: - arcname = name - - # Exclude pathnames. - if exclude is not None: - import warnings - warnings.warn("use the filter argument instead", - DeprecationWarning, 2) - if exclude(name): - self._dbg(2, "tarfile: Excluded %r" % name) - return - - # Skip if somebody tries to archive the archive... - if self.name is not None and os.path.abspath(name) == self.name: - self._dbg(2, "tarfile: Skipped %r" % name) - return - - self._dbg(1, name) - - # Create a TarInfo object from the file. - tarinfo = self.gettarinfo(name, arcname) - - if tarinfo is None: - self._dbg(1, "tarfile: Unsupported type %r" % name) - return - - # Change or exclude the TarInfo object. - if filter is not None: - tarinfo = filter(tarinfo) - if tarinfo is None: - self._dbg(2, "tarfile: Excluded %r" % name) - return - - # Append the tar header and data to the archive. - if tarinfo.isreg(): - f = bltn_open(name, "rb") - self.addfile(tarinfo, f) - f.close() - - elif tarinfo.isdir(): - self.addfile(tarinfo) - if recursive: - for f in os.listdir(name): - self.add(os.path.join(name, f), os.path.join(arcname, f), - recursive, exclude, filter=filter) - - else: - self.addfile(tarinfo) - - def addfile(self, tarinfo, fileobj=None): - """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is - given, tarinfo.size bytes are read from it and added to the archive. - You can create TarInfo objects using gettarinfo(). - On Windows platforms, `fileobj' should always be opened with mode - 'rb' to avoid irritation about the file size. - """ - self._check("aw") - - tarinfo = copy.copy(tarinfo) - - buf = tarinfo.tobuf(self.format, self.encoding, self.errors) - self.fileobj.write(buf) - self.offset += len(buf) - - # If there's data to follow, append it. - if fileobj is not None: - copyfileobj(fileobj, self.fileobj, tarinfo.size) - blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) - if remainder > 0: - self.fileobj.write(NUL * (BLOCKSIZE - remainder)) - blocks += 1 - self.offset += blocks * BLOCKSIZE - - self.members.append(tarinfo) - - def extractall(self, path=".", members=None): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - directories = [] - - if members is None: - members = self - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directories with a safe mode. - directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 0o700 - # Do not set_attrs directories, as we will do that further down - self.extract(tarinfo, path, set_attrs=not tarinfo.isdir()) - - # Reverse sort directories. - directories.sort(key=lambda a: a.name) - directories.reverse() - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - dirpath = os.path.join(path, tarinfo.name) - try: - self.chown(tarinfo, dirpath) - self.utime(tarinfo, dirpath) - self.chmod(tarinfo, dirpath) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extract(self, member, path="", set_attrs=True): - """Extract a member from the archive to the current working directory, - using its full name. Its file information is extracted as accurately - as possible. `member' may be a filename or a TarInfo object. You can - specify a different directory using `path'. File attributes (owner, - mtime, mode) are set unless `set_attrs' is False. - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - # Prepare the link target for makelink(). - if tarinfo.islnk(): - tarinfo._link_target = os.path.join(path, tarinfo.linkname) - - try: - self._extract_member(tarinfo, os.path.join(path, tarinfo.name), - set_attrs=set_attrs) - except EnvironmentError as e: - if self.errorlevel > 0: - raise - else: - if e.filename is None: - self._dbg(1, "tarfile: %s" % e.strerror) - else: - self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) - except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - def extractfile(self, member): - """Extract a member from the archive as a file object. `member' may be - a filename or a TarInfo object. If `member' is a regular file, a - file-like object is returned. If `member' is a link, a file-like - object is constructed from the link's target. If `member' is none of - the above, None is returned. - The file-like object is read-only and provides the following - methods: read(), readline(), readlines(), seek() and tell() - """ - self._check("r") - - if isinstance(member, str): - tarinfo = self.getmember(member) - else: - tarinfo = member - - if tarinfo.isreg(): - return self.fileobject(self, tarinfo) - - elif tarinfo.type not in SUPPORTED_TYPES: - # If a member's type is unknown, it is treated as a - # regular file. - return self.fileobject(self, tarinfo) - - elif tarinfo.islnk() or tarinfo.issym(): - if isinstance(self.fileobj, _Stream): - # A small but ugly workaround for the case that someone tries - # to extract a (sym)link as a file-object from a non-seekable - # stream of tar blocks. - raise StreamError("cannot extract (sym)link as file object") - else: - # A (sym)link's file object is its target's file object. - return self.extractfile(self._find_link_target(tarinfo)) - else: - # If there's no data associated with the member (directory, chrdev, - # blkdev, etc.), return None instead of a file object. - return None - - def _extract_member(self, tarinfo, targetpath, set_attrs=True): - """Extract the TarInfo object tarinfo to a physical - file called targetpath. - """ - # Fetch the TarInfo object for the given name - # and build the destination pathname, replacing - # forward slashes to platform specific separators. - targetpath = targetpath.rstrip("/") - targetpath = targetpath.replace("/", os.sep) - - # Create all upper directories. - upperdirs = os.path.dirname(targetpath) - if upperdirs and not os.path.exists(upperdirs): - # Create directories that are not part of the archive with - # default permissions. - os.makedirs(upperdirs) - - if tarinfo.islnk() or tarinfo.issym(): - self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) - else: - self._dbg(1, tarinfo.name) - - if tarinfo.isreg(): - self.makefile(tarinfo, targetpath) - elif tarinfo.isdir(): - self.makedir(tarinfo, targetpath) - elif tarinfo.isfifo(): - self.makefifo(tarinfo, targetpath) - elif tarinfo.ischr() or tarinfo.isblk(): - self.makedev(tarinfo, targetpath) - elif tarinfo.islnk() or tarinfo.issym(): - self.makelink(tarinfo, targetpath) - elif tarinfo.type not in SUPPORTED_TYPES: - self.makeunknown(tarinfo, targetpath) - else: - self.makefile(tarinfo, targetpath) - - if set_attrs: - self.chown(tarinfo, targetpath) - if not tarinfo.issym(): - self.chmod(tarinfo, targetpath) - self.utime(tarinfo, targetpath) - - #-------------------------------------------------------------------------- - # Below are the different file methods. They are called via - # _extract_member() when extract() is called. They can be replaced in a - # subclass to implement other functionality. - - def makedir(self, tarinfo, targetpath): - """Make a directory called targetpath. - """ - try: - # Use a safe mode for the directory, the real mode is set - # later in _extract_member(). - os.mkdir(targetpath, 0o700) - except EnvironmentError as e: - if e.errno != errno.EEXIST: - raise - - def makefile(self, tarinfo, targetpath): - """Make a file called targetpath. - """ - source = self.fileobj - source.seek(tarinfo.offset_data) - target = bltn_open(targetpath, "wb") - if tarinfo.sparse is not None: - for offset, size in tarinfo.sparse: - target.seek(offset) - copyfileobj(source, target, size) - else: - copyfileobj(source, target, tarinfo.size) - target.seek(tarinfo.size) - target.truncate() - target.close() - - def makeunknown(self, tarinfo, targetpath): - """Make a file from a TarInfo object with an unknown type - at targetpath. - """ - self.makefile(tarinfo, targetpath) - self._dbg(1, "tarfile: Unknown file type %r, " \ - "extracted as regular file." % tarinfo.type) - - def makefifo(self, tarinfo, targetpath): - """Make a fifo called targetpath. - """ - if hasattr(os, "mkfifo"): - os.mkfifo(targetpath) - else: - raise ExtractError("fifo not supported by system") - - def makedev(self, tarinfo, targetpath): - """Make a character or block device called targetpath. - """ - if not hasattr(os, "mknod") or not hasattr(os, "makedev"): - raise ExtractError("special devices not supported by system") - - mode = tarinfo.mode - if tarinfo.isblk(): - mode |= stat.S_IFBLK - else: - mode |= stat.S_IFCHR - - os.mknod(targetpath, mode, - os.makedev(tarinfo.devmajor, tarinfo.devminor)) - - def makelink(self, tarinfo, targetpath): - """Make a (symbolic) link called targetpath. If it cannot be created - (platform limitation), we try to make a copy of the referenced file - instead of a link. - """ - try: - # For systems that support symbolic and hard links. - if tarinfo.issym(): - os.symlink(tarinfo.linkname, targetpath) - else: - # See extract(). - if os.path.exists(tarinfo._link_target): - os.link(tarinfo._link_target, targetpath) - else: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except symlink_exception: - if tarinfo.issym(): - linkpath = os.path.join(os.path.dirname(tarinfo.name), - tarinfo.linkname) - else: - linkpath = tarinfo.linkname - else: - try: - self._extract_member(self._find_link_target(tarinfo), - targetpath) - except KeyError: - raise ExtractError("unable to resolve link inside archive") - - def chown(self, tarinfo, targetpath): - """Set owner of targetpath according to tarinfo. - """ - if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: - # We have to be root to do so. - try: - g = grp.getgrnam(tarinfo.gname)[2] - except KeyError: - g = tarinfo.gid - try: - u = pwd.getpwnam(tarinfo.uname)[2] - except KeyError: - u = tarinfo.uid - try: - if tarinfo.issym() and hasattr(os, "lchown"): - os.lchown(targetpath, u, g) - else: - if sys.platform != "os2emx": - os.chown(targetpath, u, g) - except EnvironmentError as e: - raise ExtractError("could not change owner") - - def chmod(self, tarinfo, targetpath): - """Set file permissions of targetpath according to tarinfo. - """ - if hasattr(os, 'chmod'): - try: - os.chmod(targetpath, tarinfo.mode) - except EnvironmentError as e: - raise ExtractError("could not change mode") - - def utime(self, tarinfo, targetpath): - """Set modification time of targetpath according to tarinfo. - """ - if not hasattr(os, 'utime'): - return - try: - os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) - except EnvironmentError as e: - raise ExtractError("could not change modification time") - - #-------------------------------------------------------------------------- - def next(self): - """Return the next member of the archive as a TarInfo object, when - TarFile is opened for reading. Return None if there is no more - available. - """ - self._check("ra") - if self.firstmember is not None: - m = self.firstmember - self.firstmember = None - return m - - # Read the next block. - self.fileobj.seek(self.offset) - tarinfo = None - while True: - try: - tarinfo = self.tarinfo.fromtarfile(self) - except EOFHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - except InvalidHeaderError as e: - if self.ignore_zeros: - self._dbg(2, "0x%X: %s" % (self.offset, e)) - self.offset += BLOCKSIZE - continue - elif self.offset == 0: - raise ReadError(str(e)) - except EmptyHeaderError: - if self.offset == 0: - raise ReadError("empty file") - except TruncatedHeaderError as e: - if self.offset == 0: - raise ReadError(str(e)) - except SubsequentHeaderError as e: - raise ReadError(str(e)) - break - - if tarinfo is not None: - self.members.append(tarinfo) - else: - self._loaded = True - - return tarinfo - - #-------------------------------------------------------------------------- - # Little helper methods: - - def _getmember(self, name, tarinfo=None, normalize=False): - """Find an archive member by name from bottom to top. - If tarinfo is given, it is used as the starting point. - """ - # Ensure that all members have been loaded. - members = self.getmembers() - - # Limit the member search list up to tarinfo. - if tarinfo is not None: - members = members[:members.index(tarinfo)] - - if normalize: - name = os.path.normpath(name) - - for member in reversed(members): - if normalize: - member_name = os.path.normpath(member.name) - else: - member_name = member.name - - if name == member_name: - return member - - def _load(self): - """Read through the entire archive file and look for readable - members. - """ - while True: - tarinfo = self.next() - if tarinfo is None: - break - self._loaded = True - - def _check(self, mode=None): - """Check if TarFile is still open, and if the operation's mode - corresponds to TarFile's mode. - """ - if self.closed: - raise IOError("%s is closed" % self.__class__.__name__) - if mode is not None and self.mode not in mode: - raise IOError("bad operation for mode %r" % self.mode) - - def _find_link_target(self, tarinfo): - """Find the target member of a symlink or hardlink member in the - archive. - """ - if tarinfo.issym(): - # Always search the entire archive. - linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname - limit = None - else: - # Search the archive before the link, because a hard link is - # just a reference to an already archived file. - linkname = tarinfo.linkname - limit = tarinfo - - member = self._getmember(linkname, tarinfo=limit, normalize=True) - if member is None: - raise KeyError("linkname %r not found" % linkname) - return member - - def __iter__(self): - """Provide an iterator object. - """ - if self._loaded: - return iter(self.members) - else: - return TarIter(self) - - def _dbg(self, level, msg): - """Write debugging output to sys.stderr. - """ - if level <= self.debug: - print(msg, file=sys.stderr) - - def __enter__(self): - self._check() - return self - - def __exit__(self, type, value, traceback): - if type is None: - self.close() - else: - # An exception occurred. We must not call close() because - # it would try to write end-of-archive blocks and padding. - if not self._extfileobj: - self.fileobj.close() - self.closed = True -# class TarFile - -class TarIter(object): - """Iterator Class. - - for tarinfo in TarFile(...): - suite... - """ - - def __init__(self, tarfile): - """Construct a TarIter object. - """ - self.tarfile = tarfile - self.index = 0 - def __iter__(self): - """Return iterator object. - """ - return self - - def __next__(self): - """Return the next item using TarFile's next() method. - When all members have been read, set TarFile as _loaded. - """ - # Fix for SF #1100429: Under rare circumstances it can - # happen that getmembers() is called during iteration, - # which will cause TarIter to stop prematurely. - if not self.tarfile._loaded: - tarinfo = self.tarfile.next() - if not tarinfo: - self.tarfile._loaded = True - raise StopIteration - else: - try: - tarinfo = self.tarfile.members[self.index] - except IndexError: - raise StopIteration - self.index += 1 - return tarinfo - - next = __next__ # for Python 2.x - -#-------------------- -# exported functions -#-------------------- -def is_tarfile(name): - """Return True if name points to a tar archive that we - are able to handle, else return False. - """ - try: - t = open(name) - t.close() - return True - except TarError: - return False - -bltn_open = open -open = TarFile.open diff --git a/awx/lib/site-packages/pip/_vendor/distlib/compat.py b/awx/lib/site-packages/pip/_vendor/distlib/compat.py deleted file mode 100644 index 63af3742de..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/compat.py +++ /dev/null @@ -1,1064 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -from __future__ import absolute_import - -import os -import re -import sys - -if sys.version_info[0] < 3: - from StringIO import StringIO - string_types = basestring, - text_type = unicode - from types import FileType as file_type - import __builtin__ as builtins - import ConfigParser as configparser - from ._backport import shutil - from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit - from urllib import (urlretrieve, quote as _quote, unquote, url2pathname, - pathname2url, ContentTooShortError, splittype) - - def quote(s): - if isinstance(s, unicode): - s = s.encode('utf-8') - return _quote(s) - - import urllib2 - from urllib2 import (Request, urlopen, URLError, HTTPError, - HTTPBasicAuthHandler, HTTPPasswordMgr, - HTTPSHandler, HTTPHandler, HTTPRedirectHandler, - build_opener) - import httplib - import xmlrpclib - import Queue as queue - from HTMLParser import HTMLParser - import htmlentitydefs - raw_input = raw_input - from itertools import ifilter as filter - from itertools import ifilterfalse as filterfalse - - _userprog = None - def splituser(host): - """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" - global _userprog - if _userprog is None: - import re - _userprog = re.compile('^(.*)@(.*)$') - - match = _userprog.match(host) - if match: return match.group(1, 2) - return None, host - -else: - from io import StringIO - string_types = str, - text_type = str - from io import TextIOWrapper as file_type - import builtins - import configparser - import shutil - from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote, - unquote, urlsplit, urlunsplit, splittype) - from urllib.request import (urlopen, urlretrieve, Request, url2pathname, - pathname2url, - HTTPBasicAuthHandler, HTTPPasswordMgr, - HTTPSHandler, HTTPHandler, HTTPRedirectHandler, - build_opener) - from urllib.error import HTTPError, URLError, ContentTooShortError - import http.client as httplib - import urllib.request as urllib2 - import xmlrpc.client as xmlrpclib - import queue - from html.parser import HTMLParser - import html.entities as htmlentitydefs - raw_input = input - from itertools import filterfalse - filter = filter - -try: - from ssl import match_hostname, CertificateError -except ImportError: - class CertificateError(ValueError): - pass - - - def _dnsname_to_pat(dn): - pats = [] - for frag in dn.split(r'.'): - if frag == '*': - # When '*' is a fragment by itself, it matches a non-empty - # dotless fragment. - pats.append('[^.]+') - else: - # Otherwise, '*' matches any dotless fragment. - frag = re.escape(frag) - pats.append(frag.replace(r'\*', '[^.]*')) - return re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) - - - def match_hostname(cert, hostname): - """Verify that *cert* (in decoded format as returned by - SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 rules - are mostly followed, but IP addresses are not accepted for *hostname*. - - CertificateError is raised on failure. On success, the function - returns nothing. - """ - if not cert: - raise ValueError("empty or no certificate") - dnsnames = [] - san = cert.get('subjectAltName', ()) - for key, value in san: - if key == 'DNS': - if _dnsname_to_pat(value).match(hostname): - return - dnsnames.append(value) - if not dnsnames: - # The subject is only checked when there is no dNSName entry - # in subjectAltName - for sub in cert.get('subject', ()): - for key, value in sub: - # XXX according to RFC 2818, the most specific Common Name - # must be used. - if key == 'commonName': - if _dnsname_to_pat(value).match(hostname): - return - dnsnames.append(value) - if len(dnsnames) > 1: - raise CertificateError("hostname %r " - "doesn't match either of %s" - % (hostname, ', '.join(map(repr, dnsnames)))) - elif len(dnsnames) == 1: - raise CertificateError("hostname %r " - "doesn't match %r" - % (hostname, dnsnames[0])) - else: - raise CertificateError("no appropriate commonName or " - "subjectAltName fields were found") - - -try: - from types import SimpleNamespace as Container -except ImportError: - class Container(object): - """ - A generic container for when multiple values need to be returned - """ - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - -try: - from shutil import which -except ImportError: - # Implementation from Python 3.3 - def which(cmd, mode=os.F_OK | os.X_OK, path=None): - """Given a command, mode, and a PATH string, return the path which - conforms to the given mode on the PATH, or None if there is no such - file. - - `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result - of os.environ.get("PATH"), or can be overridden with a custom search - path. - - """ - # Check that a given file can be accessed with the correct mode. - # Additionally check that `file` is not a directory, as on Windows - # directories pass the os.access check. - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) - and not os.path.isdir(fn)) - - # If we're given a path with a directory part, look it up directly rather - # than referring to PATH directories. This includes checking relative to the - # current directory, e.g. ./script - if os.path.dirname(cmd): - if _access_check(cmd, mode): - return cmd - return None - - if path is None: - path = os.environ.get("PATH", os.defpath) - if not path: - return None - path = path.split(os.pathsep) - - if sys.platform == "win32": - # The current directory takes precedence on Windows. - if not os.curdir in path: - path.insert(0, os.curdir) - - # PATHEXT is necessary to check on Windows. - pathext = os.environ.get("PATHEXT", "").split(os.pathsep) - # See if the given file matches any of the expected path extensions. - # This will allow us to short circuit when given "python.exe". - # If it does match, only test that one, otherwise we have to try - # others. - if any(cmd.lower().endswith(ext.lower()) for ext in pathext): - files = [cmd] - else: - files = [cmd + ext for ext in pathext] - else: - # On other platforms you don't have things like PATHEXT to tell you - # what file suffixes are executable, so just pass on cmd as-is. - files = [cmd] - - seen = set() - for dir in path: - normdir = os.path.normcase(dir) - if not normdir in seen: - seen.add(normdir) - for thefile in files: - name = os.path.join(dir, thefile) - if _access_check(name, mode): - return name - return None - - -# ZipFile is a context manager in 2.7, but not in 2.6 - -from zipfile import ZipFile as BaseZipFile - -if hasattr(BaseZipFile, '__enter__'): - ZipFile = BaseZipFile -else: - from zipfile import ZipExtFile as BaseZipExtFile - - class ZipExtFile(BaseZipExtFile): - def __init__(self, base): - self.__dict__.update(base.__dict__) - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - # return None, so if an exception occurred, it will propagate - - class ZipFile(BaseZipFile): - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.close() - # return None, so if an exception occurred, it will propagate - - def open(self, *args, **kwargs): - base = BaseZipFile.open(self, *args, **kwargs) - return ZipExtFile(base) - -try: - from platform import python_implementation -except ImportError: # pragma: no cover - def python_implementation(): - """Return a string identifying the Python implementation.""" - if 'PyPy' in sys.version: - return 'PyPy' - if os.name == 'java': - return 'Jython' - if sys.version.startswith('IronPython'): - return 'IronPython' - return 'CPython' - -try: - import sysconfig -except ImportError: # pragma: no cover - from ._backport import sysconfig - -try: - callable = callable -except NameError: # pragma: no cover - from collections import Callable - - def callable(obj): - return isinstance(obj, Callable) - - -try: - fsencode = os.fsencode - fsdecode = os.fsdecode -except AttributeError: # pragma: no cover - _fsencoding = sys.getfilesystemencoding() - if _fsencoding == 'mbcs': - _fserrors = 'strict' - else: - _fserrors = 'surrogateescape' - - def fsencode(filename): - if isinstance(filename, bytes): - return filename - elif isinstance(filename, text_type): - return filename.encode(_fsencoding, _fserrors) - else: - raise TypeError("expect bytes or str, not %s" % - type(filename).__name__) - - def fsdecode(filename): - if isinstance(filename, text_type): - return filename - elif isinstance(filename, bytes): - return filename.decode(_fsencoding, _fserrors) - else: - raise TypeError("expect bytes or str, not %s" % - type(filename).__name__) - -try: - from tokenize import detect_encoding -except ImportError: # pragma: no cover - from codecs import BOM_UTF8, lookup - import re - - cookie_re = re.compile("coding[:=]\s*([-\w.]+)") - - def _get_normal_name(orig_enc): - """Imitates get_normal_name in tokenizer.c.""" - # Only care about the first 12 characters. - enc = orig_enc[:12].lower().replace("_", "-") - if enc == "utf-8" or enc.startswith("utf-8-"): - return "utf-8" - if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ - enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): - return "iso-8859-1" - return orig_enc - - def detect_encoding(readline): - """ - The detect_encoding() function is used to detect the encoding that should - be used to decode a Python source file. It requires one argment, readline, - in the same way as the tokenize() generator. - - It will call readline a maximum of twice, and return the encoding used - (as a string) and a list of any lines (left as bytes) it has read in. - - It detects the encoding from the presence of a utf-8 bom or an encoding - cookie as specified in pep-0263. If both a bom and a cookie are present, - but disagree, a SyntaxError will be raised. If the encoding cookie is an - invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, - 'utf-8-sig' is returned. - - If no encoding is specified, then the default of 'utf-8' will be returned. - """ - try: - filename = readline.__self__.name - except AttributeError: - filename = None - bom_found = False - encoding = None - default = 'utf-8' - def read_or_stop(): - try: - return readline() - except StopIteration: - return b'' - - def find_cookie(line): - try: - # Decode as UTF-8. Either the line is an encoding declaration, - # in which case it should be pure ASCII, or it must be UTF-8 - # per default encoding. - line_string = line.decode('utf-8') - except UnicodeDecodeError: - msg = "invalid or missing encoding declaration" - if filename is not None: - msg = '{} for {!r}'.format(msg, filename) - raise SyntaxError(msg) - - matches = cookie_re.findall(line_string) - if not matches: - return None - encoding = _get_normal_name(matches[0]) - try: - codec = lookup(encoding) - except LookupError: - # This behaviour mimics the Python interpreter - if filename is None: - msg = "unknown encoding: " + encoding - else: - msg = "unknown encoding for {!r}: {}".format(filename, - encoding) - raise SyntaxError(msg) - - if bom_found: - if codec.name != 'utf-8': - # This behaviour mimics the Python interpreter - if filename is None: - msg = 'encoding problem: utf-8' - else: - msg = 'encoding problem for {!r}: utf-8'.format(filename) - raise SyntaxError(msg) - encoding += '-sig' - return encoding - - first = read_or_stop() - if first.startswith(BOM_UTF8): - bom_found = True - first = first[3:] - default = 'utf-8-sig' - if not first: - return default, [] - - encoding = find_cookie(first) - if encoding: - return encoding, [first] - - second = read_or_stop() - if not second: - return default, [first] - - encoding = find_cookie(second) - if encoding: - return encoding, [first, second] - - return default, [first, second] - -# For converting & <-> & etc. -try: - from html import escape -except ImportError: - from cgi import escape -if sys.version_info[:2] < (3, 4): - unescape = HTMLParser().unescape -else: - from html import unescape - -try: - from collections import ChainMap -except ImportError: # pragma: no cover - from collections import MutableMapping - - try: - from reprlib import recursive_repr as _recursive_repr - except ImportError: - def _recursive_repr(fillvalue='...'): - ''' - Decorator to make a repr function return fillvalue for a recursive - call - ''' - - def decorating_function(user_function): - repr_running = set() - - def wrapper(self): - key = id(self), get_ident() - if key in repr_running: - return fillvalue - repr_running.add(key) - try: - result = user_function(self) - finally: - repr_running.discard(key) - return result - - # Can't use functools.wraps() here because of bootstrap issues - wrapper.__module__ = getattr(user_function, '__module__') - wrapper.__doc__ = getattr(user_function, '__doc__') - wrapper.__name__ = getattr(user_function, '__name__') - wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) - return wrapper - - return decorating_function - - class ChainMap(MutableMapping): - ''' A ChainMap groups multiple dicts (or other mappings) together - to create a single, updateable view. - - The underlying mappings are stored in a list. That list is public and can - accessed or updated using the *maps* attribute. There is no other state. - - Lookups search the underlying mappings successively until a key is found. - In contrast, writes, updates, and deletions only operate on the first - mapping. - - ''' - - def __init__(self, *maps): - '''Initialize a ChainMap by setting *maps* to the given mappings. - If no mappings are provided, a single empty dictionary is used. - - ''' - self.maps = list(maps) or [{}] # always at least one map - - def __missing__(self, key): - raise KeyError(key) - - def __getitem__(self, key): - for mapping in self.maps: - try: - return mapping[key] # can't use 'key in mapping' with defaultdict - except KeyError: - pass - return self.__missing__(key) # support subclasses that define __missing__ - - def get(self, key, default=None): - return self[key] if key in self else default - - def __len__(self): - return len(set().union(*self.maps)) # reuses stored hash values if possible - - def __iter__(self): - return iter(set().union(*self.maps)) - - def __contains__(self, key): - return any(key in m for m in self.maps) - - def __bool__(self): - return any(self.maps) - - @_recursive_repr() - def __repr__(self): - return '{0.__class__.__name__}({1})'.format( - self, ', '.join(map(repr, self.maps))) - - @classmethod - def fromkeys(cls, iterable, *args): - 'Create a ChainMap with a single dict created from the iterable.' - return cls(dict.fromkeys(iterable, *args)) - - def copy(self): - 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' - return self.__class__(self.maps[0].copy(), *self.maps[1:]) - - __copy__ = copy - - def new_child(self): # like Django's Context.push() - 'New ChainMap with a new dict followed by all previous maps.' - return self.__class__({}, *self.maps) - - @property - def parents(self): # like Django's Context.pop() - 'New ChainMap from maps[1:].' - return self.__class__(*self.maps[1:]) - - def __setitem__(self, key, value): - self.maps[0][key] = value - - def __delitem__(self, key): - try: - del self.maps[0][key] - except KeyError: - raise KeyError('Key not found in the first mapping: {!r}'.format(key)) - - def popitem(self): - 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' - try: - return self.maps[0].popitem() - except KeyError: - raise KeyError('No keys found in the first mapping.') - - def pop(self, key, *args): - 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' - try: - return self.maps[0].pop(key, *args) - except KeyError: - raise KeyError('Key not found in the first mapping: {!r}'.format(key)) - - def clear(self): - 'Clear maps[0], leaving maps[1:] intact.' - self.maps[0].clear() - -try: - from imp import cache_from_source -except ImportError: # pragma: no cover - def cache_from_source(path, debug_override=None): - assert path.endswith('.py') - if debug_override is None: - debug_override = __debug__ - if debug_override: - suffix = 'c' - else: - suffix = 'o' - return path + suffix - -try: - from collections import OrderedDict -except ImportError: # pragma: no cover -## {{{ http://code.activestate.com/recipes/576693/ (r9) -# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. -# Passes Python2.7's test suite and incorporates all the latest updates. - try: - from thread import get_ident as _get_ident - except ImportError: - from dummy_thread import get_ident as _get_ident - - try: - from _abcoll import KeysView, ValuesView, ItemsView - except ImportError: - pass - - - class OrderedDict(dict): - 'Dictionary that remembers insertion order' - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. - - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. - - ''' - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__root - except AttributeError: - self.__root = root = [] # sentinel node - root[:] = [root, root, None] - self.__map = {} - self.__update(*args, **kwds) - - def __setitem__(self, key, value, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link which goes at the end of the linked - # list, and the inherited dictionary is updated with the new key/value pair. - if key not in self: - root = self.__root - last = root[0] - last[1] = root[0] = self.__map[key] = [last, root, key] - dict_setitem(self, key, value) - - def __delitem__(self, key, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which is - # then removed by updating the links in the predecessor and successor nodes. - dict_delitem(self, key) - link_prev, link_next, key = self.__map.pop(key) - link_prev[1] = link_next - link_next[0] = link_prev - - def __iter__(self): - 'od.__iter__() <==> iter(od)' - root = self.__root - curr = root[1] - while curr is not root: - yield curr[2] - curr = curr[1] - - def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' - root = self.__root - curr = root[0] - while curr is not root: - yield curr[2] - curr = curr[0] - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.itervalues(): - del node[:] - root = self.__root - root[:] = [root, root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) - - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - root = self.__root - if last: - link = root[0] - link_prev = link[0] - link_prev[1] = root - root[0] = link_prev - else: - link = root[1] - link_next = link[1] - root[1] = link_next - link_next[0] = root - key = link[2] - del self.__map[key] - value = dict.pop(self, key) - return key, value - - # -- the following methods do not depend on the internal structure -- - - def keys(self): - 'od.keys() -> list of keys in od' - return list(self) - - def values(self): - 'od.values() -> list of values in od' - return [self[key] for key in self] - - def items(self): - 'od.items() -> list of (key, value) pairs in od' - return [(key, self[key]) for key in self] - - def iterkeys(self): - 'od.iterkeys() -> an iterator over the keys in od' - return iter(self) - - def itervalues(self): - 'od.itervalues -> an iterator over the values in od' - for k in self: - yield self[k] - - def iteritems(self): - 'od.iteritems -> an iterator over the (key, value) items in od' - for k in self: - yield (k, self[k]) - - def update(*args, **kwds): - '''od.update(E, **F) -> None. Update od from dict/iterable E and F. - - If E is a dict instance, does: for k in E: od[k] = E[k] - If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] - Or if E is an iterable of items, does: for k, v in E: od[k] = v - In either case, this is followed by: for k, v in F.items(): od[k] = v - - ''' - if len(args) > 2: - raise TypeError('update() takes at most 2 positional ' - 'arguments (%d given)' % (len(args),)) - elif not args: - raise TypeError('update() takes at least 1 argument (0 given)') - self = args[0] - # Make progressively weaker assumptions about "other" - other = () - if len(args) == 2: - other = args[1] - if isinstance(other, dict): - for key in other: - self[key] = other[key] - elif hasattr(other, 'keys'): - for key in other.keys(): - self[key] = other[key] - else: - for key, value in other: - self[key] = value - for key, value in kwds.items(): - self[key] = value - - __update = update # let subclasses override update without breaking __init__ - - __marker = object() - - def pop(self, key, default=__marker): - '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. - If key is not found, d is returned if given, otherwise KeyError is raised. - - ''' - if key in self: - result = self[key] - del self[key] - return result - if default is self.__marker: - raise KeyError(key) - return default - - def setdefault(self, key, default=None): - 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' - if key in self: - return self[key] - self[key] = default - return default - - def __repr__(self, _repr_running=None): - 'od.__repr__() <==> repr(od)' - if not _repr_running: _repr_running = {} - call_key = id(self), _get_ident() - if call_key in _repr_running: - return '...' - _repr_running[call_key] = 1 - try: - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - finally: - del _repr_running[call_key] - - def __reduce__(self): - 'Return state information for pickling' - items = [[k, self[k]] for k in self] - inst_dict = vars(self).copy() - for k in vars(OrderedDict()): - inst_dict.pop(k, None) - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, OrderedDict): - return len(self)==len(other) and self.items() == other.items() - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other - - # -- the following methods are only used in Python 2.7 -- - - def viewkeys(self): - "od.viewkeys() -> a set-like object providing a view on od's keys" - return KeysView(self) - - def viewvalues(self): - "od.viewvalues() -> an object providing a view on od's values" - return ValuesView(self) - - def viewitems(self): - "od.viewitems() -> a set-like object providing a view on od's items" - return ItemsView(self) - -try: - from logging.config import BaseConfigurator, valid_ident -except ImportError: # pragma: no cover - IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) - - - def valid_ident(s): - m = IDENTIFIER.match(s) - if not m: - raise ValueError('Not a valid Python identifier: %r' % s) - return True - - - # The ConvertingXXX classes are wrappers around standard Python containers, - # and they serve to convert any suitable values in the container. The - # conversion converts base dicts, lists and tuples to their wrapped - # equivalents, whereas strings which match a conversion format are converted - # appropriately. - # - # Each wrapper should have a configurator attribute holding the actual - # configurator to use for conversion. - - class ConvertingDict(dict): - """A converting dictionary wrapper.""" - - def __getitem__(self, key): - value = dict.__getitem__(self, key) - result = self.configurator.convert(value) - #If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def get(self, key, default=None): - value = dict.get(self, key, default) - result = self.configurator.convert(value) - #If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def pop(self, key, default=None): - value = dict.pop(self, key, default) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - class ConvertingList(list): - """A converting list wrapper.""" - def __getitem__(self, key): - value = list.__getitem__(self, key) - result = self.configurator.convert(value) - #If the converted value is different, save for next time - if value is not result: - self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - def pop(self, idx=-1): - value = list.pop(self, idx) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - return result - - class ConvertingTuple(tuple): - """A converting tuple wrapper.""" - def __getitem__(self, key): - value = tuple.__getitem__(self, key) - result = self.configurator.convert(value) - if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): - result.parent = self - result.key = key - return result - - class BaseConfigurator(object): - """ - The configurator base class which defines some useful defaults. - """ - - CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$') - - WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') - DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') - INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') - DIGIT_PATTERN = re.compile(r'^\d+$') - - value_converters = { - 'ext' : 'ext_convert', - 'cfg' : 'cfg_convert', - } - - # We might want to use a different one, e.g. importlib - importer = staticmethod(__import__) - - def __init__(self, config): - self.config = ConvertingDict(config) - self.config.configurator = self - - def resolve(self, s): - """ - Resolve strings to objects using standard import and attribute - syntax. - """ - name = s.split('.') - used = name.pop(0) - try: - found = self.importer(used) - for frag in name: - used += '.' + frag - try: - found = getattr(found, frag) - except AttributeError: - self.importer(used) - found = getattr(found, frag) - return found - except ImportError: - e, tb = sys.exc_info()[1:] - v = ValueError('Cannot resolve %r: %s' % (s, e)) - v.__cause__, v.__traceback__ = e, tb - raise v - - def ext_convert(self, value): - """Default converter for the ext:// protocol.""" - return self.resolve(value) - - def cfg_convert(self, value): - """Default converter for the cfg:// protocol.""" - rest = value - m = self.WORD_PATTERN.match(rest) - if m is None: - raise ValueError("Unable to convert %r" % value) - else: - rest = rest[m.end():] - d = self.config[m.groups()[0]] - #print d, rest - while rest: - m = self.DOT_PATTERN.match(rest) - if m: - d = d[m.groups()[0]] - else: - m = self.INDEX_PATTERN.match(rest) - if m: - idx = m.groups()[0] - if not self.DIGIT_PATTERN.match(idx): - d = d[idx] - else: - try: - n = int(idx) # try as number first (most likely) - d = d[n] - except TypeError: - d = d[idx] - if m: - rest = rest[m.end():] - else: - raise ValueError('Unable to convert ' - '%r at %r' % (value, rest)) - #rest should be empty - return d - - def convert(self, value): - """ - Convert values to an appropriate type. dicts, lists and tuples are - replaced by their converting alternatives. Strings are checked to - see if they have a conversion format and are converted if they do. - """ - if not isinstance(value, ConvertingDict) and isinstance(value, dict): - value = ConvertingDict(value) - value.configurator = self - elif not isinstance(value, ConvertingList) and isinstance(value, list): - value = ConvertingList(value) - value.configurator = self - elif not isinstance(value, ConvertingTuple) and\ - isinstance(value, tuple): - value = ConvertingTuple(value) - value.configurator = self - elif isinstance(value, string_types): - m = self.CONVERT_PATTERN.match(value) - if m: - d = m.groupdict() - prefix = d['prefix'] - converter = self.value_converters.get(prefix, None) - if converter: - suffix = d['suffix'] - converter = getattr(self, converter) - value = converter(suffix) - return value - - def configure_custom(self, config): - """Configure an object with a user-supplied factory.""" - c = config.pop('()') - if not callable(c): - c = self.resolve(c) - props = config.pop('.', None) - # Check for valid identifiers - kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) - result = c(**kwargs) - if props: - for name, value in props.items(): - setattr(result, name, value) - return result - - def as_tuple(self, value): - """Utility function which converts lists to tuples.""" - if isinstance(value, list): - value = tuple(value) - return value diff --git a/awx/lib/site-packages/pip/_vendor/distlib/database.py b/awx/lib/site-packages/pip/_vendor/distlib/database.py deleted file mode 100644 index 0f013ec549..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/database.py +++ /dev/null @@ -1,1301 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2013 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""PEP 376 implementation.""" - -from __future__ import unicode_literals - -import base64 -import codecs -import contextlib -import hashlib -import logging -import os -import posixpath -import sys -import zipimport - -from . import DistlibException, resources -from .compat import StringIO -from .version import get_scheme, UnsupportedVersionError -from .metadata import Metadata, METADATA_FILENAME -from .util import (parse_requirement, cached_property, parse_name_and_version, - read_exports, write_exports, CSVReader, CSVWriter) - - -__all__ = ['Distribution', 'BaseInstalledDistribution', - 'InstalledDistribution', 'EggInfoDistribution', - 'DistributionPath'] - - -logger = logging.getLogger(__name__) - -EXPORTS_FILENAME = 'pydist-exports.json' -COMMANDS_FILENAME = 'pydist-commands.json' - -DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', - 'RESOURCES', EXPORTS_FILENAME, 'SHARED') - -DISTINFO_EXT = '.dist-info' - - -class _Cache(object): - """ - A simple cache mapping names and .dist-info paths to distributions - """ - def __init__(self): - """ - Initialise an instance. There is normally one for each DistributionPath. - """ - self.name = {} - self.path = {} - self.generated = False - - def clear(self): - """ - Clear the cache, setting it to its initial state. - """ - self.name.clear() - self.path.clear() - self.generated = False - - def add(self, dist): - """ - Add a distribution to the cache. - :param dist: The distribution to add. - """ - if dist.path not in self.path: - self.path[dist.path] = dist - self.name.setdefault(dist.key, []).append(dist) - - -class DistributionPath(object): - """ - Represents a set of distributions installed on a path (typically sys.path). - """ - def __init__(self, path=None, include_egg=False): - """ - Create an instance from a path, optionally including legacy (distutils/ - setuptools/distribute) distributions. - :param path: The path to use, as a list of directories. If not specified, - sys.path is used. - :param include_egg: If True, this instance will look for and return legacy - distributions as well as those based on PEP 376. - """ - if path is None: - path = sys.path - self.path = path - self._include_dist = True - self._include_egg = include_egg - - self._cache = _Cache() - self._cache_egg = _Cache() - self._cache_enabled = True - self._scheme = get_scheme('default') - - def _get_cache_enabled(self): - return self._cache_enabled - - def _set_cache_enabled(self, value): - self._cache_enabled = value - - cache_enabled = property(_get_cache_enabled, _set_cache_enabled) - - def clear_cache(self): - """ - Clears the internal cache. - """ - self._cache.clear() - self._cache_egg.clear() - - - def _yield_distributions(self): - """ - Yield .dist-info and/or .egg(-info) distributions. - """ - # We need to check if we've seen some resources already, because on - # some Linux systems (e.g. some Debian/Ubuntu variants) there are - # symlinks which alias other files in the environment. - seen = set() - for path in self.path: - finder = resources.finder_for_path(path) - if finder is None: - continue - r = finder.find('') - if not r or not r.is_container: - continue - rset = sorted(r.resources) - for entry in rset: - r = finder.find(entry) - if not r or r.path in seen: - continue - if self._include_dist and entry.endswith(DISTINFO_EXT): - metadata_path = posixpath.join(entry, METADATA_FILENAME) - pydist = finder.find(metadata_path) - if not pydist: - continue - - metadata = Metadata(fileobj=pydist.as_stream(), - scheme='legacy') - logger.debug('Found %s', r.path) - seen.add(r.path) - yield new_dist_class(r.path, metadata=metadata, - env=self) - elif self._include_egg and entry.endswith(('.egg-info', - '.egg')): - logger.debug('Found %s', r.path) - seen.add(r.path) - yield old_dist_class(r.path, self) - - def _generate_cache(self): - """ - Scan the path for distributions and populate the cache with - those that are found. - """ - gen_dist = not self._cache.generated - gen_egg = self._include_egg and not self._cache_egg.generated - if gen_dist or gen_egg: - for dist in self._yield_distributions(): - if isinstance(dist, InstalledDistribution): - self._cache.add(dist) - else: - self._cache_egg.add(dist) - - if gen_dist: - self._cache.generated = True - if gen_egg: - self._cache_egg.generated = True - - @classmethod - def distinfo_dirname(cls, name, version): - """ - The *name* and *version* parameters are converted into their - filename-escaped form, i.e. any ``'-'`` characters are replaced - with ``'_'`` other than the one in ``'dist-info'`` and the one - separating the name from the version number. - - :parameter name: is converted to a standard distribution name by replacing - any runs of non- alphanumeric characters with a single - ``'-'``. - :type name: string - :parameter version: is converted to a standard version string. Spaces - become dots, and all other non-alphanumeric characters - (except dots) become dashes, with runs of multiple - dashes condensed to a single dash. - :type version: string - :returns: directory name - :rtype: string""" - name = name.replace('-', '_') - return '-'.join([name, version]) + DISTINFO_EXT - - def get_distributions(self): - """ - Provides an iterator that looks for distributions and returns - :class:`InstalledDistribution` or - :class:`EggInfoDistribution` instances for each one of them. - - :rtype: iterator of :class:`InstalledDistribution` and - :class:`EggInfoDistribution` instances - """ - if not self._cache_enabled: - for dist in self._yield_distributions(): - yield dist - else: - self._generate_cache() - - for dist in self._cache.path.values(): - yield dist - - if self._include_egg: - for dist in self._cache_egg.path.values(): - yield dist - - def get_distribution(self, name): - """ - Looks for a named distribution on the path. - - This function only returns the first result found, as no more than one - value is expected. If nothing is found, ``None`` is returned. - - :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` - or ``None`` - """ - result = None - name = name.lower() - if not self._cache_enabled: - for dist in self._yield_distributions(): - if dist.key == name: - result = dist - break - else: - self._generate_cache() - - if name in self._cache.name: - result = self._cache.name[name][0] - elif self._include_egg and name in self._cache_egg.name: - result = self._cache_egg.name[name][0] - return result - - def provides_distribution(self, name, version=None): - """ - Iterates over all distributions to find which distributions provide *name*. - If a *version* is provided, it will be used to filter the results. - - This function only returns the first result found, since no more than - one values are expected. If the directory is not found, returns ``None``. - - :parameter version: a version specifier that indicates the version - required, conforming to the format in ``PEP-345`` - - :type name: string - :type version: string - """ - matcher = None - if not version is None: - try: - matcher = self._scheme.matcher('%s (%s)' % (name, version)) - except ValueError: - raise DistlibException('invalid name or version: %r, %r' % - (name, version)) - - for dist in self.get_distributions(): - provided = dist.provides - - for p in provided: - p_name, p_ver = parse_name_and_version(p) - if matcher is None: - if p_name == name: - yield dist - break - else: - if p_name == name and matcher.match(p_ver): - yield dist - break - - def get_file_path(self, name, relative_path): - """ - Return the path to a resource file. - """ - dist = self.get_distribution(name) - if dist is None: - raise LookupError('no distribution named %r found' % name) - return dist.get_resource_path(relative_path) - - def get_exported_entries(self, category, name=None): - """ - Return all of the exported entries in a particular category. - - :param category: The category to search for entries. - :param name: If specified, only entries with that name are returned. - """ - for dist in self.get_distributions(): - r = dist.exports - if category in r: - d = r[category] - if name is not None: - if name in d: - yield d[name] - else: - for v in d.values(): - yield v - - -class Distribution(object): - """ - A base class for distributions, whether installed or from indexes. - Either way, it must have some metadata, so that's all that's needed - for construction. - """ - - build_time_dependency = False - """ - Set to True if it's known to be only a build-time dependency (i.e. - not needed after installation). - """ - - requested = False - """A boolean that indicates whether the ``REQUESTED`` metadata file is - present (in other words, whether the package was installed by user - request or it was installed as a dependency).""" - - def __init__(self, metadata): - """ - Initialise an instance. - :param metadata: The instance of :class:`Metadata` describing this - distribution. - """ - self.metadata = metadata - self.name = metadata.name - self.key = self.name.lower() # for case-insensitive comparisons - self.version = metadata.version - self.locator = None - self.digest = None - self.extras = None # additional features requested - self.context = None # environment marker overrides - - @property - def source_url(self): - """ - The source archive download URL for this distribution. - """ - return self.metadata.source_url - - download_url = source_url # Backward compatibility - - @property - def name_and_version(self): - """ - A utility property which displays the name and version in parentheses. - """ - return '%s (%s)' % (self.name, self.version) - - @property - def provides(self): - """ - A set of distribution names and versions provided by this distribution. - :return: A set of "name (version)" strings. - """ - plist = self.metadata.provides - s = '%s (%s)' % (self.name, self.version) - if s not in plist: - plist.append(s) - return plist - - def _get_requirements(self, req_attr): - reqts = getattr(self.metadata, req_attr) - return set(self.metadata.get_requirements(reqts, extras=self.extras, - env=self.context)) - - @property - def run_requires(self): - return self._get_requirements('run_requires') - - @property - def meta_requires(self): - return self._get_requirements('meta_requires') - - @property - def build_requires(self): - return self._get_requirements('build_requires') - - @property - def test_requires(self): - return self._get_requirements('test_requires') - - @property - def dev_requires(self): - return self._get_requirements('dev_requires') - - def matches_requirement(self, req): - """ - Say if this instance matches (fulfills) a requirement. - :param req: The requirement to match. - :rtype req: str - :return: True if it matches, else False. - """ - # Requirement may contain extras - parse to lose those - # from what's passed to the matcher - r = parse_requirement(req) - scheme = get_scheme(self.metadata.scheme) - try: - matcher = scheme.matcher(r.requirement) - except UnsupportedVersionError: - # XXX compat-mode if cannot read the version - logger.warning('could not read version %r - using name only', - req) - name = req.split()[0] - matcher = scheme.matcher(name) - - name = matcher.key # case-insensitive - - result = False - for p in self.provides: - p_name, p_ver = parse_name_and_version(p) - if p_name != name: - continue - try: - result = matcher.match(p_ver) - break - except UnsupportedVersionError: - pass - return result - - def __repr__(self): - """ - Return a textual representation of this instance, - """ - if self.source_url: - suffix = ' [%s]' % self.source_url - else: - suffix = '' - return '' % (self.name, self.version, suffix) - - def __eq__(self, other): - """ - See if this distribution is the same as another. - :param other: The distribution to compare with. To be equal to one - another. distributions must have the same type, name, - version and source_url. - :return: True if it is the same, else False. - """ - if type(other) is not type(self): - result = False - else: - result = (self.name == other.name and - self.version == other.version and - self.source_url == other.source_url) - return result - - def __hash__(self): - """ - Compute hash in a way which matches the equality test. - """ - return hash(self.name) + hash(self.version) + hash(self.source_url) - - -class BaseInstalledDistribution(Distribution): - """ - This is the base class for installed distributions (whether PEP 376 or - legacy). - """ - - hasher = None - - def __init__(self, metadata, path, env=None): - """ - Initialise an instance. - :param metadata: An instance of :class:`Metadata` which describes the - distribution. This will normally have been initialised - from a metadata file in the ``path``. - :param path: The path of the ``.dist-info`` or ``.egg-info`` - directory for the distribution. - :param env: This is normally the :class:`DistributionPath` - instance where this distribution was found. - """ - super(BaseInstalledDistribution, self).__init__(metadata) - self.path = path - self.dist_path = env - - def get_hash(self, data, hasher=None): - """ - Get the hash of some data, using a particular hash algorithm, if - specified. - - :param data: The data to be hashed. - :type data: bytes - :param hasher: The name of a hash implementation, supported by hashlib, - or ``None``. Examples of valid values are ``'sha1'``, - ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and - ``'sha512'``. If no hasher is specified, the ``hasher`` - attribute of the :class:`InstalledDistribution` instance - is used. If the hasher is determined to be ``None``, MD5 - is used as the hashing algorithm. - :returns: The hash of the data. If a hasher was explicitly specified, - the returned hash will be prefixed with the specified hasher - followed by '='. - :rtype: str - """ - if hasher is None: - hasher = self.hasher - if hasher is None: - hasher = hashlib.md5 - prefix = '' - else: - hasher = getattr(hashlib, hasher) - prefix = '%s=' % self.hasher - digest = hasher(data).digest() - digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') - return '%s%s' % (prefix, digest) - - -class InstalledDistribution(BaseInstalledDistribution): - """ - Created with the *path* of the ``.dist-info`` directory provided to the - constructor. It reads the metadata contained in ``pydist.json`` when it is - instantiated., or uses a passed in Metadata instance (useful for when - dry-run mode is being used). - """ - - hasher = 'sha256' - - def __init__(self, path, metadata=None, env=None): - self.finder = finder = resources.finder_for_path(path) - if finder is None: - import pdb; pdb.set_trace () - if env and env._cache_enabled and path in env._cache.path: - metadata = env._cache.path[path].metadata - elif metadata is None: - r = finder.find(METADATA_FILENAME) - # Temporary - for legacy support - if r is None: - r = finder.find('METADATA') - if r is None: - raise ValueError('no %s found in %s' % (METADATA_FILENAME, - path)) - with contextlib.closing(r.as_stream()) as stream: - metadata = Metadata(fileobj=stream, scheme='legacy') - - super(InstalledDistribution, self).__init__(metadata, path, env) - - if env and env._cache_enabled: - env._cache.add(self) - - try: - r = finder.find('REQUESTED') - except AttributeError: - import pdb; pdb.set_trace () - self.requested = r is not None - - def __repr__(self): - return '' % ( - self.name, self.version, self.path) - - def __str__(self): - return "%s %s" % (self.name, self.version) - - def _get_records(self): - """ - Get the list of installed files for the distribution - :return: A list of tuples of path, hash and size. Note that hash and - size might be ``None`` for some entries. The path is exactly - as stored in the file (which is as in PEP 376). - """ - results = [] - r = self.get_distinfo_resource('RECORD') - with contextlib.closing(r.as_stream()) as stream: - with CSVReader(stream=stream) as record_reader: - # Base location is parent dir of .dist-info dir - #base_location = os.path.dirname(self.path) - #base_location = os.path.abspath(base_location) - for row in record_reader: - missing = [None for i in range(len(row), 3)] - path, checksum, size = row + missing - #if not os.path.isabs(path): - # path = path.replace('/', os.sep) - # path = os.path.join(base_location, path) - results.append((path, checksum, size)) - return results - - @cached_property - def exports(self): - """ - Return the information exported by this distribution. - :return: A dictionary of exports, mapping an export category to a dict - of :class:`ExportEntry` instances describing the individual - export entries, and keyed by name. - """ - result = {} - r = self.get_distinfo_resource(EXPORTS_FILENAME) - if r: - result = self.read_exports() - return result - - def read_exports(self): - """ - Read exports data from a file in .ini format. - - :return: A dictionary of exports, mapping an export category to a list - of :class:`ExportEntry` instances describing the individual - export entries. - """ - result = {} - r = self.get_distinfo_resource(EXPORTS_FILENAME) - if r: - with contextlib.closing(r.as_stream()) as stream: - result = read_exports(stream) - return result - - def write_exports(self, exports): - """ - Write a dictionary of exports to a file in .ini format. - :param exports: A dictionary of exports, mapping an export category to - a list of :class:`ExportEntry` instances describing the - individual export entries. - """ - rf = self.get_distinfo_file(EXPORTS_FILENAME) - with open(rf, 'w') as f: - write_exports(exports, f) - - def get_resource_path(self, relative_path): - """ - NOTE: This API may change in the future. - - Return the absolute path to a resource file with the given relative - path. - - :param relative_path: The path, relative to .dist-info, of the resource - of interest. - :return: The absolute path where the resource is to be found. - """ - r = self.get_distinfo_resource('RESOURCES') - with contextlib.closing(r.as_stream()) as stream: - with CSVReader(stream=stream) as resources_reader: - for relative, destination in resources_reader: - if relative == relative_path: - return destination - raise KeyError('no resource file with relative path %r ' - 'is installed' % relative_path) - - def list_installed_files(self): - """ - Iterates over the ``RECORD`` entries and returns a tuple - ``(path, hash, size)`` for each line. - - :returns: iterator of (path, hash, size) - """ - for result in self._get_records(): - yield result - - def write_installed_files(self, paths, prefix, dry_run=False): - """ - Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any - existing ``RECORD`` file is silently overwritten. - - prefix is used to determine when to write absolute paths. - """ - prefix = os.path.join(prefix, '') - base = os.path.dirname(self.path) - base_under_prefix = base.startswith(prefix) - base = os.path.join(base, '') - record_path = self.get_distinfo_file('RECORD') - logger.info('creating %s', record_path) - if dry_run: - return None - with CSVWriter(record_path) as writer: - for path in paths: - if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): - # do not put size and hash, as in PEP-376 - hash_value = size = '' - else: - size = '%d' % os.path.getsize(path) - with open(path, 'rb') as fp: - hash_value = self.get_hash(fp.read()) - if path.startswith(base) or (base_under_prefix and - path.startswith(prefix)): - path = os.path.relpath(path, base) - writer.writerow((path, hash_value, size)) - - # add the RECORD file itself - if record_path.startswith(base): - record_path = os.path.relpath(record_path, base) - writer.writerow((record_path, '', '')) - return record_path - - def check_installed_files(self): - """ - Checks that the hashes and sizes of the files in ``RECORD`` are - matched by the files themselves. Returns a (possibly empty) list of - mismatches. Each entry in the mismatch list will be a tuple consisting - of the path, 'exists', 'size' or 'hash' according to what didn't match - (existence is checked first, then size, then hash), the expected - value and the actual value. - """ - mismatches = [] - base = os.path.dirname(self.path) - record_path = self.get_distinfo_file('RECORD') - for path, hash_value, size in self.list_installed_files(): - if not os.path.isabs(path): - path = os.path.join(base, path) - if path == record_path: - continue - if not os.path.exists(path): - mismatches.append((path, 'exists', True, False)) - elif os.path.isfile(path): - actual_size = str(os.path.getsize(path)) - if size and actual_size != size: - mismatches.append((path, 'size', size, actual_size)) - elif hash_value: - if '=' in hash_value: - hasher = hash_value.split('=', 1)[0] - else: - hasher = None - - with open(path, 'rb') as f: - actual_hash = self.get_hash(f.read(), hasher) - if actual_hash != hash_value: - mismatches.append((path, 'hash', hash_value, actual_hash)) - return mismatches - - @cached_property - def shared_locations(self): - """ - A dictionary of shared locations whose keys are in the set 'prefix', - 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. - The corresponding value is the absolute path of that category for - this distribution, and takes into account any paths selected by the - user at installation time (e.g. via command-line arguments). In the - case of the 'namespace' key, this would be a list of absolute paths - for the roots of namespace packages in this distribution. - - The first time this property is accessed, the relevant information is - read from the SHARED file in the .dist-info directory. - """ - result = {} - shared_path = os.path.join(self.path, 'SHARED') - if os.path.isfile(shared_path): - with codecs.open(shared_path, 'r', encoding='utf-8') as f: - lines = f.read().splitlines() - for line in lines: - key, value = line.split('=', 1) - if key == 'namespace': - result.setdefault(key, []).append(value) - else: - result[key] = value - return result - - def write_shared_locations(self, paths, dry_run=False): - """ - Write shared location information to the SHARED file in .dist-info. - :param paths: A dictionary as described in the documentation for - :meth:`shared_locations`. - :param dry_run: If True, the action is logged but no file is actually - written. - :return: The path of the file written to. - """ - shared_path = os.path.join(self.path, 'SHARED') - logger.info('creating %s', shared_path) - if dry_run: - return None - lines = [] - for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): - path = paths[key] - if os.path.isdir(paths[key]): - lines.append('%s=%s' % (key, path)) - for ns in paths.get('namespace', ()): - lines.append('namespace=%s' % ns) - - with codecs.open(shared_path, 'w', encoding='utf-8') as f: - f.write('\n'.join(lines)) - return shared_path - - def get_distinfo_resource(self, path): - if path not in DIST_FILES: - raise DistlibException('invalid path for a dist-info file: ' - '%r at %r' % (path, self.path)) - finder = resources.finder_for_path(self.path) - if finder is None: - raise DistlibException('Unable to get a finder for %s' % self.path) - return finder.find(path) - - def get_distinfo_file(self, path): - """ - Returns a path located under the ``.dist-info`` directory. Returns a - string representing the path. - - :parameter path: a ``'/'``-separated path relative to the - ``.dist-info`` directory or an absolute path; - If *path* is an absolute path and doesn't start - with the ``.dist-info`` directory path, - a :class:`DistlibException` is raised - :type path: str - :rtype: str - """ - # Check if it is an absolute path # XXX use relpath, add tests - if path.find(os.sep) >= 0: - # it's an absolute path? - distinfo_dirname, path = path.split(os.sep)[-2:] - if distinfo_dirname != self.path.split(os.sep)[-1]: - raise DistlibException( - 'dist-info file %r does not belong to the %r %s ' - 'distribution' % (path, self.name, self.version)) - - # The file must be relative - if path not in DIST_FILES: - raise DistlibException('invalid path for a dist-info file: ' - '%r at %r' % (path, self.path)) - - return os.path.join(self.path, path) - - def list_distinfo_files(self): - """ - Iterates over the ``RECORD`` entries and returns paths for each line if - the path is pointing to a file located in the ``.dist-info`` directory - or one of its subdirectories. - - :returns: iterator of paths - """ - base = os.path.dirname(self.path) - for path, checksum, size in self._get_records(): - # XXX add separator or use real relpath algo - if not os.path.isabs(path): - path = os.path.join(base, path) - if path.startswith(self.path): - yield path - - def __eq__(self, other): - return (isinstance(other, InstalledDistribution) and - self.path == other.path) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - __hash__ = object.__hash__ - - -class EggInfoDistribution(BaseInstalledDistribution): - """Created with the *path* of the ``.egg-info`` directory or file provided - to the constructor. It reads the metadata contained in the file itself, or - if the given path happens to be a directory, the metadata is read from the - file ``PKG-INFO`` under that directory.""" - - requested = True # as we have no way of knowing, assume it was - shared_locations = {} - - def __init__(self, path, env=None): - def set_name_and_version(s, n, v): - s.name = n - s.key = n.lower() # for case-insensitive comparisons - s.version = v - - self.path = path - self.dist_path = env - if env and env._cache_enabled and path in env._cache_egg.path: - metadata = env._cache_egg.path[path].metadata - set_name_and_version(self, metadata.name, metadata.version) - else: - metadata = self._get_metadata(path) - - # Need to be set before caching - set_name_and_version(self, metadata.name, metadata.version) - - if env and env._cache_enabled: - env._cache_egg.add(self) - super(EggInfoDistribution, self).__init__(metadata, path, env) - - def _get_metadata(self, path): - requires = None - - def parse_requires_data(data): - """Create a list of dependencies from a requires.txt file. - - *data*: the contents of a setuptools-produced requires.txt file. - """ - reqs = [] - lines = data.splitlines() - for line in lines: - line = line.strip() - if line.startswith('['): - logger.warning('Unexpected line: quitting requirement scan: %r', - line) - break - r = parse_requirement(line) - if not r: - logger.warning('Not recognised as a requirement: %r', line) - continue - if r.extras: - logger.warning('extra requirements in requires.txt are ' - 'not supported') - if not r.constraints: - reqs.append(r.name) - else: - cons = ', '.join('%s%s' % c for c in r.constraints) - reqs.append('%s (%s)' % (r.name, cons)) - return reqs - - def parse_requires_path(req_path): - """Create a list of dependencies from a requires.txt file. - - *req_path*: the path to a setuptools-produced requires.txt file. - """ - - reqs = [] - try: - with codecs.open(req_path, 'r', 'utf-8') as fp: - reqs = parse_requires_data(fp.read()) - except IOError: - pass - return reqs - - if path.endswith('.egg'): - if os.path.isdir(path): - meta_path = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - metadata = Metadata(path=meta_path, scheme='legacy') - req_path = os.path.join(path, 'EGG-INFO', 'requires.txt') - requires = parse_requires_path(req_path) - else: - # FIXME handle the case where zipfile is not available - zipf = zipimport.zipimporter(path) - fileobj = StringIO( - zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) - metadata = Metadata(fileobj=fileobj, scheme='legacy') - try: - data = zipf.get_data('EGG-INFO/requires.txt') - requires = parse_requires_data(data.decode('utf-8')) - except IOError: - requires = None - elif path.endswith('.egg-info'): - if os.path.isdir(path): - path = os.path.join(path, 'PKG-INFO') - req_path = os.path.join(path, 'requires.txt') - requires = parse_requires_path(req_path) - metadata = Metadata(path=path, scheme='legacy') - else: - raise DistlibException('path must end with .egg-info or .egg, ' - 'got %r' % path) - - if requires: - metadata.add_requirements(requires) - return metadata - - def __repr__(self): - return '' % ( - self.name, self.version, self.path) - - def __str__(self): - return "%s %s" % (self.name, self.version) - - def check_installed_files(self): - """ - Checks that the hashes and sizes of the files in ``RECORD`` are - matched by the files themselves. Returns a (possibly empty) list of - mismatches. Each entry in the mismatch list will be a tuple consisting - of the path, 'exists', 'size' or 'hash' according to what didn't match - (existence is checked first, then size, then hash), the expected - value and the actual value. - """ - mismatches = [] - record_path = os.path.join(self.path, 'installed-files.txt') - if os.path.exists(record_path): - for path, _, _ in self.list_installed_files(): - if path == record_path: - continue - if not os.path.exists(path): - mismatches.append((path, 'exists', True, False)) - return mismatches - - def list_installed_files(self): - """ - Iterates over the ``installed-files.txt`` entries and returns a tuple - ``(path, hash, size)`` for each line. - - :returns: a list of (path, hash, size) - """ - - def _md5(path): - f = open(path, 'rb') - try: - content = f.read() - finally: - f.close() - return hashlib.md5(content).hexdigest() - - def _size(path): - return os.stat(path).st_size - - record_path = os.path.join(self.path, 'installed-files.txt') - result = [] - if os.path.exists(record_path): - with codecs.open(record_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - p = os.path.normpath(os.path.join(self.path, line)) - # "./" is present as a marker between installed files - # and installation metadata files - if not os.path.exists(p): - logger.warning('Non-existent file: %s', p) - if p.endswith(('.pyc', '.pyo')): - continue - #otherwise fall through and fail - if not os.path.isdir(p): - result.append((p, _md5(p), _size(p))) - result.append((record_path, None, None)) - return result - - def list_distinfo_files(self, absolute=False): - """ - Iterates over the ``installed-files.txt`` entries and returns paths for - each line if the path is pointing to a file located in the - ``.egg-info`` directory or one of its subdirectories. - - :parameter absolute: If *absolute* is ``True``, each returned path is - transformed into a local absolute path. Otherwise the - raw value from ``installed-files.txt`` is returned. - :type absolute: boolean - :returns: iterator of paths - """ - record_path = os.path.join(self.path, 'installed-files.txt') - skip = True - with codecs.open(record_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if line == './': - skip = False - continue - if not skip: - p = os.path.normpath(os.path.join(self.path, line)) - if p.startswith(self.path): - if absolute: - yield p - else: - yield line - - def __eq__(self, other): - return (isinstance(other, EggInfoDistribution) and - self.path == other.path) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - __hash__ = object.__hash__ - -new_dist_class = InstalledDistribution -old_dist_class = EggInfoDistribution - - -class DependencyGraph(object): - """ - Represents a dependency graph between distributions. - - The dependency relationships are stored in an ``adjacency_list`` that maps - distributions to a list of ``(other, label)`` tuples where ``other`` - is a distribution and the edge is labeled with ``label`` (i.e. the version - specifier, if such was provided). Also, for more efficient traversal, for - every distribution ``x``, a list of predecessors is kept in - ``reverse_list[x]``. An edge from distribution ``a`` to - distribution ``b`` means that ``a`` depends on ``b``. If any missing - dependencies are found, they are stored in ``missing``, which is a - dictionary that maps distributions to a list of requirements that were not - provided by any other distributions. - """ - - def __init__(self): - self.adjacency_list = {} - self.reverse_list = {} - self.missing = {} - - def add_distribution(self, distribution): - """Add the *distribution* to the graph. - - :type distribution: :class:`distutils2.database.InstalledDistribution` - or :class:`distutils2.database.EggInfoDistribution` - """ - self.adjacency_list[distribution] = [] - self.reverse_list[distribution] = [] - #self.missing[distribution] = [] - - def add_edge(self, x, y, label=None): - """Add an edge from distribution *x* to distribution *y* with the given - *label*. - - :type x: :class:`distutils2.database.InstalledDistribution` or - :class:`distutils2.database.EggInfoDistribution` - :type y: :class:`distutils2.database.InstalledDistribution` or - :class:`distutils2.database.EggInfoDistribution` - :type label: ``str`` or ``None`` - """ - self.adjacency_list[x].append((y, label)) - # multiple edges are allowed, so be careful - if x not in self.reverse_list[y]: - self.reverse_list[y].append(x) - - def add_missing(self, distribution, requirement): - """ - Add a missing *requirement* for the given *distribution*. - - :type distribution: :class:`distutils2.database.InstalledDistribution` - or :class:`distutils2.database.EggInfoDistribution` - :type requirement: ``str`` - """ - logger.debug('%s missing %r', distribution, requirement) - self.missing.setdefault(distribution, []).append(requirement) - - def _repr_dist(self, dist): - return '%s %s' % (dist.name, dist.version) - - def repr_node(self, dist, level=1): - """Prints only a subgraph""" - output = [self._repr_dist(dist)] - for other, label in self.adjacency_list[dist]: - dist = self._repr_dist(other) - if label is not None: - dist = '%s [%s]' % (dist, label) - output.append(' ' * level + str(dist)) - suboutput = self.repr_node(other, level + 1) - subs = suboutput.split('\n') - output.extend(subs[1:]) - return '\n'.join(output) - - def to_dot(self, f, skip_disconnected=True): - """Writes a DOT output for the graph to the provided file *f*. - - If *skip_disconnected* is set to ``True``, then all distributions - that are not dependent on any other distribution are skipped. - - :type f: has to support ``file``-like operations - :type skip_disconnected: ``bool`` - """ - disconnected = [] - - f.write("digraph dependencies {\n") - for dist, adjs in self.adjacency_list.items(): - if len(adjs) == 0 and not skip_disconnected: - disconnected.append(dist) - for other, label in adjs: - if not label is None: - f.write('"%s" -> "%s" [label="%s"]\n' % - (dist.name, other.name, label)) - else: - f.write('"%s" -> "%s"\n' % (dist.name, other.name)) - if not skip_disconnected and len(disconnected) > 0: - f.write('subgraph disconnected {\n') - f.write('label = "Disconnected"\n') - f.write('bgcolor = red\n') - - for dist in disconnected: - f.write('"%s"' % dist.name) - f.write('\n') - f.write('}\n') - f.write('}\n') - - def topological_sort(self): - """ - Perform a topological sort of the graph. - :return: A tuple, the first element of which is a topologically sorted - list of distributions, and the second element of which is a - list of distributions that cannot be sorted because they have - circular dependencies and so form a cycle. - """ - result = [] - # Make a shallow copy of the adjacency list - alist = {} - for k, v in self.adjacency_list.items(): - alist[k] = v[:] - while True: - # See what we can remove in this run - to_remove = [] - for k, v in list(alist.items())[:]: - if not v: - to_remove.append(k) - del alist[k] - if not to_remove: - # What's left in alist (if anything) is a cycle. - break - # Remove from the adjacency list of others - for k, v in alist.items(): - alist[k] = [(d, r) for d, r in v if d not in to_remove] - logger.debug('Moving to result: %s', - ['%s (%s)' % (d.name, d.version) for d in to_remove]) - result.extend(to_remove) - return result, list(alist.keys()) - - def __repr__(self): - """Representation of the graph""" - output = [] - for dist, adjs in self.adjacency_list.items(): - output.append(self.repr_node(dist)) - return '\n'.join(output) - - -def make_graph(dists, scheme='default'): - """Makes a dependency graph from the given distributions. - - :parameter dists: a list of distributions - :type dists: list of :class:`distutils2.database.InstalledDistribution` and - :class:`distutils2.database.EggInfoDistribution` instances - :rtype: a :class:`DependencyGraph` instance - """ - scheme = get_scheme(scheme) - graph = DependencyGraph() - provided = {} # maps names to lists of (version, dist) tuples - - # first, build the graph and find out what's provided - for dist in dists: - graph.add_distribution(dist) - - for p in dist.provides: - name, version = parse_name_and_version(p) - logger.debug('Add to provided: %s, %s, %s', name, version, dist) - provided.setdefault(name, []).append((version, dist)) - - # now make the edges - for dist in dists: - requires = (dist.run_requires | dist.meta_requires | - dist.build_requires | dist.dev_requires) - for req in requires: - try: - matcher = scheme.matcher(req) - except UnsupportedVersionError: - # XXX compat-mode if cannot read the version - logger.warning('could not read version %r - using name only', - req) - name = req.split()[0] - matcher = scheme.matcher(name) - - name = matcher.key # case-insensitive - - matched = False - if name in provided: - for version, provider in provided[name]: - try: - match = matcher.match(version) - except UnsupportedVersionError: - match = False - - if match: - graph.add_edge(dist, provider, req) - matched = True - break - if not matched: - graph.add_missing(dist, req) - return graph - - -def get_dependent_dists(dists, dist): - """Recursively generate a list of distributions from *dists* that are - dependent on *dist*. - - :param dists: a list of distributions - :param dist: a distribution, member of *dists* for which we are interested - """ - if dist not in dists: - raise DistlibException('given distribution %r is not a member ' - 'of the list' % dist.name) - graph = make_graph(dists) - - dep = [dist] # dependent distributions - todo = graph.reverse_list[dist] # list of nodes we should inspect - - while todo: - d = todo.pop() - dep.append(d) - for succ in graph.reverse_list[d]: - if succ not in dep: - todo.append(succ) - - dep.pop(0) # remove dist from dep, was there to prevent infinite loops - return dep - - -def get_required_dists(dists, dist): - """Recursively generate a list of distributions from *dists* that are - required by *dist*. - - :param dists: a list of distributions - :param dist: a distribution, member of *dists* for which we are interested - """ - if dist not in dists: - raise DistlibException('given distribution %r is not a member ' - 'of the list' % dist.name) - graph = make_graph(dists) - - req = [] # required distributions - todo = graph.adjacency_list[dist] # list of nodes we should inspect - - while todo: - d = todo.pop()[0] - req.append(d) - for pred in graph.adjacency_list[d]: - if pred not in req: - todo.append(pred) - - return req - - -def make_dist(name, version, **kwargs): - """ - A convenience method for making a dist given just a name and version. - """ - summary = kwargs.pop('summary', 'Placeholder for summary') - md = Metadata(**kwargs) - md.name = name - md.version = version - md.summary = summary or 'Plaeholder for summary' - return Distribution(md) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/index.py b/awx/lib/site-packages/pip/_vendor/distlib/index.py deleted file mode 100644 index 30b2aa5a50..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/index.py +++ /dev/null @@ -1,480 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -import hashlib -import logging -import os -import shutil -import subprocess -import tempfile -try: - from threading import Thread -except ImportError: - from dummy_threading import Thread - -from distlib import DistlibException -from distlib.compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, - urlparse, build_opener) -from distlib.util import cached_property, zip_dir - -logger = logging.getLogger(__name__) - -DEFAULT_INDEX = 'https://pypi.python.org/pypi' -DEFAULT_REALM = 'pypi' - -class PackageIndex(object): - """ - This class represents a package index compatible with PyPI, the Python - Package Index. - """ - - boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' - - def __init__(self, url=None): - """ - Initialise an instance. - - :param url: The URL of the index. If not specified, the URL for PyPI is - used. - """ - self.url = url or DEFAULT_INDEX - self.read_configuration() - scheme, netloc, path, params, query, frag = urlparse(self.url) - if params or query or frag or scheme not in ('http', 'https'): - raise DistlibException('invalid repository: %s' % self.url) - self.password_handler = None - self.ssl_verifier = None - self.gpg = None - self.gpg_home = None - with open(os.devnull, 'w') as sink: - for s in ('gpg2', 'gpg'): - try: - rc = subprocess.check_call([s, '--version'], stdout=sink, - stderr=sink) - if rc == 0: - self.gpg = s - break - except OSError: - pass - - def _get_pypirc_command(self): - """ - Get the distutils command for interacting with PyPI configurations. - :return: the command. - """ - from distutils.core import Distribution - from distutils.config import PyPIRCCommand - d = Distribution() - return PyPIRCCommand(d) - - def read_configuration(self): - """ - Read the PyPI access configuration as supported by distutils, getting - PyPI to do the acutal work. This populates ``username``, ``password``, - ``realm`` and ``url`` attributes from the configuration. - """ - # get distutils to do the work - c = self._get_pypirc_command() - c.repository = self.url - cfg = c._read_pypirc() - self.username = cfg.get('username') - self.password = cfg.get('password') - self.realm = cfg.get('realm', 'pypi') - self.url = cfg.get('repository', self.url) - - def save_configuration(self): - """ - Save the PyPI access configuration. You must have set ``username`` and - ``password`` attributes before calling this method. - - Again, distutils is used to do the actual work. - """ - self.check_credentials() - # get distutils to do the work - c = self._get_pypirc_command() - c._store_pypirc(self.username, self.password) - - def check_credentials(self): - """ - Check that ``username`` and ``password`` have been set, and raise an - exception if not. - """ - if self.username is None or self.password is None: - raise DistlibException('username and password must be set') - pm = HTTPPasswordMgr() - _, netloc, _, _, _, _ = urlparse(self.url) - pm.add_password(self.realm, netloc, self.username, self.password) - self.password_handler = HTTPBasicAuthHandler(pm) - - def register(self, metadata): - """ - Register a distribution on PyPI, using the provided metadata. - - :param metadata: A :class:`Metadata` instance defining at least a name - and version number for the distribution to be - registered. - :return: The HTTP response received from PyPI upon submission of the - request. - """ - self.check_credentials() - metadata.validate() - d = metadata.todict() - d[':action'] = 'verify' - request = self.encode_request(d.items(), []) - response = self.send_request(request) - d[':action'] = 'submit' - request = self.encode_request(d.items(), []) - return self.send_request(request) - - def _reader(self, name, stream, outbuf): - """ - Thread runner for reading lines of from a subprocess into a buffer. - - :param name: The logical name of the stream (used for logging only). - :param stream: The stream to read from. This will typically a pipe - connected to the output stream of a subprocess. - :param outbuf: The list to append the read lines to. - """ - while True: - s = stream.readline() - if not s: - break - s = s.decode('utf-8').rstrip() - outbuf.append(s) - logger.debug('%s: %s' % (name, s)) - stream.close() - - def get_sign_command(self, filename, signer, sign_password): - """ - Return a suitable command for signing a file. - - :param filename: The pathname to the file to be signed. - :param signer: The identifier of the signer of the file. - :param sign_password: The passphrase for the signer's - private key used for signing. - :return: The signing command as a list suitable to be - passed to :class:`subprocess.Popen`. - """ - cmd = [self.gpg, '--status-fd', '2', '--no-tty'] - if self.gpg_home: - cmd.extend(['--homedir', self.gpg_home]) - if sign_password is not None: - cmd.extend(['--batch', '--passphrase-fd', '0']) - td = tempfile.mkdtemp() - sf = os.path.join(td, os.path.basename(filename) + '.asc') - cmd.extend(['--detach-sign', '--armor', '--local-user', - signer, '--output', sf, filename]) - logger.debug('invoking: %s', ' '.join(cmd)) - return cmd, sf - - def run_command(self, cmd, input_data=None): - """ - Run a command in a child process , passing it any input data specified. - - :param cmd: The command to run. - :param input_data: If specified, this must be a byte string containing - data to be sent to the child process. - :return: A tuple consisting of the subprocess' exit code, a list of - lines read from the subprocess' ``stdout``, and a list of - lines read from the subprocess' ``stderr``. - """ - kwargs = { - 'stdout': subprocess.PIPE, - 'stderr': subprocess.PIPE, - } - if input_data is not None: - kwargs['stdin'] = subprocess.PIPE - stdout = [] - stderr = [] - p = subprocess.Popen(cmd, **kwargs) - # We don't use communicate() here because we may need to - # get clever with interacting with the command - t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) - t1.start() - t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) - t2.start() - if input_data is not None: - p.stdin.write(input_data) - p.stdin.close() - - p.wait() - t1.join() - t2.join() - return p.returncode, stdout, stderr - - def sign_file(self, filename, signer, sign_password): - """ - Sign a file. - - :param filename: The pathname to the file to be signed. - :param signer: The identifier of the signer of the file. - :param sign_password: The passphrase for the signer's - private key used for signing. - :return: The absolute pathname of the file where the signature is - stored. - """ - cmd, sig_file = self.get_sign_command(filename, signer, sign_password) - rc, stdout, stderr = self.run_command(cmd, - sign_password.encode('utf-8')) - if rc != 0: - raise DistlibException('sign command failed with error ' - 'code %s' % rc) - return sig_file - - def upload_file(self, metadata, filename, signer=None, sign_password=None, - filetype='sdist', pyversion='source'): - """ - Upload a release file to the index. - - :param metadata: A :class:`Metadata` instance defining at least a name - and version number for the file to be uploaded. - :param filename: The pathname of the file to be uploaded. - :param signer: The identifier of the signer of the file. - :param sign_password: The passphrase for the signer's - private key used for signing. - :param filetype: The type of the file being uploaded. This is the - distutils command which produced that file, e.g. - ``sdist`` or ``bdist_wheel``. - :param pyversion: The version of Python which the release relates - to. For code compatible with any Python, this would - be ``source``, otherwise it would be e.g. ``3.2``. - :return: The HTTP response received from PyPI upon submission of the - request. - """ - self.check_credentials() - if not os.path.exists(filename): - raise DistlibException('not found: %s' % filename) - metadata.validate() - d = metadata.todict() - sig_file = None - if signer: - if not self.gpg: - logger.warning('no signing program available - not signed') - else: - sig_file = self.sign_file(filename, signer, sign_password) - with open(filename, 'rb') as f: - file_data = f.read() - md5_digest = hashlib.md5(file_data).hexdigest() - sha256_digest = hashlib.sha256(file_data).hexdigest() - d.update({ - ':action': 'file_upload', - 'protcol_version': '1', - 'filetype': filetype, - 'pyversion': pyversion, - 'md5_digest': md5_digest, - 'sha256_digest': sha256_digest, - }) - files = [('content', os.path.basename(filename), file_data)] - if sig_file: - with open(sig_file, 'rb') as f: - sig_data = f.read() - files.append(('gpg_signature', os.path.basename(sig_file), - sig_data)) - shutil.rmtree(os.path.dirname(sig_file)) - request = self.encode_request(d.items(), files) - return self.send_request(request) - - def upload_documentation(self, metadata, doc_dir): - """ - Upload documentation to the index. - - :param metadata: A :class:`Metadata` instance defining at least a name - and version number for the documentation to be - uploaded. - :param doc_dir: The pathname of the directory which contains the - documentation. This should be the directory that - contains the ``index.html`` for the documentation. - :return: The HTTP response received from PyPI upon submission of the - request. - """ - self.check_credentials() - if not os.path.isdir(doc_dir): - raise DistlibException('not a directory: %r' % doc_dir) - fn = os.path.join(doc_dir, 'index.html') - if not os.path.exists(fn): - raise DistlibException('not found: %r' % fn) - metadata.validate() - name, version = metadata.name, metadata.version - zip_data = zip_dir(doc_dir).getvalue() - fields = [(':action', 'doc_upload'), - ('name', name), ('version', version)] - files = [('content', name, zip_data)] - request = self.encode_request(fields, files) - return self.send_request(request) - - def get_verify_command(self, signature_filename, data_filename): - """ - Return a suitable command for verifying a file. - - :param signature_filename: The pathname to the file containing the - signature. - :param data_filename: The pathname to the file containing the - signed data. - :return: The verifying command as a list suitable to be - passed to :class:`subprocess.Popen`. - """ - cmd = [self.gpg, '--status-fd', '2', '--no-tty'] - if self.gpg_home: - cmd.extend(['--homedir', self.gpg_home]) - cmd.extend(['--verify', signature_filename, data_filename]) - logger.debug('invoking: %s', ' '.join(cmd)) - return cmd - - def verify_signature(self, signature_filename, data_filename): - """ - Verify a signature for a file. - - :param signature_filename: The pathname to the file containing the - signature. - :param data_filename: The pathname to the file containing the - signed data. - :return: True if the signature was verified, else False. - """ - if not self.gpg: - raise DistlibException('verification unavailable because gpg ' - 'unavailable') - cmd = self.get_verify_command(signature_filename, data_filename) - rc, stdout, stderr = self.run_command(cmd) - if rc not in (0, 1): - raise DistlibException('verify command failed with error ' - 'code %s' % rc) - return rc == 0 - - def download_file(self, url, destfile, digest=None, reporthook=None): - """ - This is a convenience method for downloading a file from an URL. - Normally, this will be a file from the index, though currently - no check is made for this (i.e. a file can be downloaded from - anywhere). - - The method is just like the :func:`urlretrieve` function in the - standard library, except that it allows digest computation to be - done during download and checking that the downloaded data - matched any expected value. - - :param url: The URL of the file to be downloaded (assumed to be - available via an HTTP GET request). - :param destfile: The pathname where the downloaded file is to be - saved. - :param digest: If specified, this must be a (hasher, value) - tuple, where hasher is the algorithm used (e.g. - ``'md5'``) and ``value`` is the expected value. - :param reporthook: The same as for :func:`urlretrieve` in the - standard library. - """ - if digest is None: - digester = None - logger.debug('No digest specified') - else: - if isinstance(digest, (list, tuple)): - hasher, digest = digest - else: - hasher = 'md5' - digester = getattr(hashlib, hasher)() - logger.debug('Digest specified: %s' % digest) - # The following code is equivalent to urlretrieve. - # We need to do it this way so that we can compute the - # digest of the file as we go. - with open(destfile, 'wb') as dfp: - # addinfourl is not a context manager on 2.x - # so we have to use try/finally - sfp = self.send_request(Request(url)) - try: - headers = sfp.info() - blocksize = 8192 - size = -1 - read = 0 - blocknum = 0 - if "content-length" in headers: - size = int(headers["Content-Length"]) - if reporthook: - reporthook(blocknum, blocksize, size) - while True: - block = sfp.read(blocksize) - if not block: - break - read += len(block) - dfp.write(block) - if digester: - digester.update(block) - blocknum += 1 - if reporthook: - reporthook(blocknum, blocksize, size) - finally: - sfp.close() - - # check that we got the whole file, if we can - if size >= 0 and read < size: - raise DistlibException( - 'retrieval incomplete: got only %d out of %d bytes' - % (read, size)) - # if we have a digest, it must match. - if digester: - actual = digester.hexdigest() - if digest != actual: - raise DistlibException('%s digest mismatch for %s: expected ' - '%s, got %s' % (hasher, destfile, - digest, actual)) - logger.debug('Digest verified: %s', digest) - - def send_request(self, req): - """ - Send a standard library :class:`Request` to PyPI and return its - response. - - :param req: The request to send. - :return: The HTTP response from PyPI (a standard library HTTPResponse). - """ - handlers = [] - if self.password_handler: - handlers.append(self.password_handler) - if self.ssl_verifier: - handlers.append(self.ssl_verifier) - opener = build_opener(*handlers) - return opener.open(req) - - def encode_request(self, fields, files): - """ - Encode fields and files for posting to an HTTP server. - - :param fields: The fields to send as a list of (fieldname, value) - tuples. - :param files: The files to send as a list of (fieldname, filename, - file_bytes) tuple. - """ - # Adapted from packaging, which in turn was adapted from - # http://code.activestate.com/recipes/146306 - - parts = [] - boundary = self.boundary - for k, values in fields: - if not isinstance(values, (list, tuple)): - values = [values] - - for v in values: - parts.extend(( - b'--' + boundary, - ('Content-Disposition: form-data; name="%s"' % - k).encode('utf-8'), - b'', - v.encode('utf-8'))) - for key, filename, value in files: - parts.extend(( - b'--' + boundary, - ('Content-Disposition: form-data; name="%s"; filename="%s"' % - (key, filename)).encode('utf-8'), - b'', - value)) - - parts.extend((b'--' + boundary + b'--', b'')) - - body = b'\r\n'.join(parts) - ct = b'multipart/form-data; boundary=' + boundary - headers = { - 'Content-type': ct, - 'Content-length': str(len(body)) - } - return Request(self.url, body, headers) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/locators.py b/awx/lib/site-packages/pip/_vendor/distlib/locators.py deleted file mode 100644 index ffe99310f6..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/locators.py +++ /dev/null @@ -1,1187 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# - -import gzip -from io import BytesIO -import json -import logging -import os -import posixpath -import re -try: - import threading -except ImportError: - import dummy_threading as threading -import zlib - -from . import DistlibException -from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, - queue, quote, unescape, string_types, build_opener, - HTTPRedirectHandler as BaseRedirectHandler, - Request, HTTPError, URLError) -from .database import Distribution, DistributionPath, make_dist -from .metadata import Metadata -from .util import (cached_property, parse_credentials, ensure_slash, - split_filename, get_project_data, parse_requirement, - parse_name_and_version, ServerProxy) -from .version import get_scheme, UnsupportedVersionError -from .wheel import Wheel, is_compatible - -logger = logging.getLogger(__name__) - -HASHER_HASH = re.compile('^(\w+)=([a-f0-9]+)') -CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) -HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') -DEFAULT_INDEX = 'http://python.org/pypi' - -def get_all_distribution_names(url=None): - """ - Return all distribution names known by an index. - :param url: The URL of the index. - :return: A list of all known distribution names. - """ - if url is None: - url = DEFAULT_INDEX - client = ServerProxy(url, timeout=3.0) - return client.list_packages() - -class RedirectHandler(BaseRedirectHandler): - """ - A class to work around a bug in some Python 3.2.x releases. - """ - # There's a bug in the base version for some 3.2.x - # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header - # returns e.g. /abc, it bails because it says the scheme '' - # is bogus, when actually it should use the request's - # URL for the scheme. See Python issue #13696. - def http_error_302(self, req, fp, code, msg, headers): - # Some servers (incorrectly) return multiple Location headers - # (so probably same goes for URI). Use first header. - newurl = None - for key in ('location', 'uri'): - if key in headers: - newurl = headers[key] - break - if newurl is None: - return - urlparts = urlparse(newurl) - if urlparts.scheme == '': - newurl = urljoin(req.get_full_url(), newurl) - if hasattr(headers, 'replace_header'): - headers.replace_header(key, newurl) - else: - headers[key] = newurl - return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, - headers) - - http_error_301 = http_error_303 = http_error_307 = http_error_302 - -class Locator(object): - """ - A base class for locators - things that locate distributions. - """ - source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz') - binary_extensions = ('.egg', '.exe', '.whl') - excluded_extensions = ('.pdf',) - - # A list of tags indicating which wheels you want to match. The default - # value of None matches against the tags compatible with the running - # Python. If you want to match other values, set wheel_tags on a locator - # instance to a list of tuples (pyver, abi, arch) which you want to match. - wheel_tags = None - - downloadable_extensions = source_extensions + ('.whl',) - - def __init__(self, scheme='default'): - """ - Initialise an instance. - :param scheme: Because locators look for most recent versions, they - need to know the version scheme to use. This specifies - the current PEP-recommended scheme - use ``'legacy'`` - if you need to support existing distributions on PyPI. - """ - self._cache = {} - self.scheme = scheme - # Because of bugs in some of the handlers on some of the platforms, - # we use our own opener rather than just using urlopen. - self.opener = build_opener(RedirectHandler()) - # If get_project() is called from locate(), the matcher instance - # is set from the requirement passed to locate(). See issue #18 for - # why this can be useful to know. - self.matcher = None - - def clear_cache(self): - self._cache.clear() - - def _get_scheme(self): - return self._scheme - - def _set_scheme(self, value): - self._scheme = value - - scheme = property(_get_scheme, _set_scheme) - - def _get_project(self, name): - """ - For a given project, get a dictionary mapping available versions to Distribution - instances. - - This should be implemented in subclasses. - - If called from a locate() request, self.matcher will be set to a - matcher for the requirement to satisfy, otherwise it will be None. - """ - raise NotImplementedError('Please implement in the subclass') - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - raise NotImplementedError('Please implement in the subclass') - - def get_project(self, name): - """ - For a given project, get a dictionary mapping available versions to Distribution - instances. - - This calls _get_project to do all the work, and just implements a caching layer on top. - """ - if self._cache is None: - result = self._get_project(name) - elif name in self._cache: - result = self._cache[name] - else: - result = self._get_project(name) - self._cache[name] = result - return result - - def score_url(self, url): - """ - Give an url a score which can be used to choose preferred URLs - for a given project release. - """ - t = urlparse(url) - return (t.scheme != 'https', 'pypi.python.org' in t.netloc, - posixpath.basename(t.path)) - - def prefer_url(self, url1, url2): - """ - Choose one of two URLs where both are candidates for distribution - archives for the same version of a distribution (for example, - .tar.gz vs. zip). - - The current implement favours http:// URLs over https://, archives - from PyPI over those from other locations and then the archive name. - """ - result = url2 - if url1: - s1 = self.score_url(url1) - s2 = self.score_url(url2) - if s1 > s2: - result = url1 - if result != url2: - logger.debug('Not replacing %r with %r', url1, url2) - else: - logger.debug('Replacing %r with %r', url1, url2) - return result - - def split_filename(self, filename, project_name): - """ - Attempt to split a filename in project name, version and Python version. - """ - return split_filename(filename, project_name) - - def convert_url_to_download_info(self, url, project_name): - """ - See if a URL is a candidate for a download URL for a project (the URL - has typically been scraped from an HTML page). - - If it is, a dictionary is returned with keys "name", "version", - "filename" and "url"; otherwise, None is returned. - """ - def same_project(name1, name2): - name1, name2 = name1.lower(), name2.lower() - if name1 == name2: - result = True - else: - # distribute replaces '-' by '_' in project names, so it - # can tell where the version starts in a filename. - result = name1.replace('_', '-') == name2.replace('_', '-') - return result - - result = None - scheme, netloc, path, params, query, frag = urlparse(url) - if frag.lower().startswith('egg='): - logger.debug('%s: version hint in fragment: %r', - project_name, frag) - m = HASHER_HASH.match(frag) - if m: - algo, digest = m.groups() - else: - algo, digest = None, None - origpath = path - if path and path[-1] == '/': - path = path[:-1] - if path.endswith('.whl'): - try: - wheel = Wheel(path) - if is_compatible(wheel, self.wheel_tags): - if project_name is None: - include = True - else: - include = same_project(wheel.name, project_name) - if include: - result = { - 'name': wheel.name, - 'version': wheel.version, - 'filename': wheel.filename, - 'url': urlunparse((scheme, netloc, origpath, - params, query, '')), - 'python-version': ', '.join( - ['.'.join(list(v[2:])) for v in wheel.pyver]), - } - except Exception as e: - logger.warning('invalid path for wheel: %s', path) - elif path.endswith(self.downloadable_extensions): - path = filename = posixpath.basename(path) - for ext in self.downloadable_extensions: - if path.endswith(ext): - path = path[:-len(ext)] - t = self.split_filename(path, project_name) - if not t: - logger.debug('No match for project/version: %s', path) - else: - name, version, pyver = t - if not project_name or same_project(project_name, name): - result = { - 'name': name, - 'version': version, - 'filename': filename, - 'url': urlunparse((scheme, netloc, origpath, - params, query, '')), - #'packagetype': 'sdist', - } - if pyver: - result['python-version'] = pyver - break - if result and algo: - result['%s_digest' % algo] = digest - return result - - def _get_digest(self, info): - """ - Get a digest from a dictionary by looking at keys of the form - 'algo_digest'. - - Returns a 2-tuple (algo, digest) if found, else None. Currently - looks only for SHA256, then MD5. - """ - result = None - for algo in ('sha256', 'md5'): - key = '%s_digest' % algo - if key in info: - result = (algo, info[key]) - break - return result - - def _update_version_data(self, result, info): - """ - Update a result dictionary (the final result from _get_project) with a dictionary for a - specific version, whih typically holds information gleaned from a filename or URL for an - archive for the distribution. - """ - name = info.pop('name') - version = info.pop('version') - if version in result: - dist = result[version] - md = dist.metadata - else: - dist = make_dist(name, version, scheme=self.scheme) - md = dist.metadata - dist.digest = self._get_digest(info) - if md.source_url != info['url']: - md.source_url = self.prefer_url(md.source_url, info['url']) - dist.locator = self - result[version] = dist - - def locate(self, requirement, prereleases=False): - """ - Find the most recent distribution which matches the given - requirement. - - :param requirement: A requirement of the form 'foo (1.0)' or perhaps - 'foo (>= 1.0, < 2.0, != 1.3)' - :param prereleases: If ``True``, allow pre-release versions - to be located. Otherwise, pre-release versions - are not returned. - :return: A :class:`Distribution` instance, or ``None`` if no such - distribution could be located. - """ - result = None - r = parse_requirement(requirement) - if r is None: - raise DistlibException('Not a valid requirement: %r' % requirement) - scheme = get_scheme(self.scheme) - self.matcher = matcher = scheme.matcher(r.requirement) - logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) - versions = self.get_project(r.name) - if versions: - # sometimes, versions are invalid - slist = [] - vcls = matcher.version_class - for k in versions: - try: - if not matcher.match(k): - logger.debug('%s did not match %r', matcher, k) - else: - if prereleases or not vcls(k).is_prerelease: - slist.append(k) - else: - logger.debug('skipping pre-release ' - 'version %s of %s', k, matcher.name) - except Exception: - logger.warning('error matching %s with %r', matcher, k) - pass # slist.append(k) - if len(slist) > 1: - slist = sorted(slist, key=scheme.key) - if slist: - logger.debug('sorted list: %s', slist) - result = versions[slist[-1]] - if result and r.extras: - result.extras = r.extras - self.matcher = None - return result - - -class PyPIRPCLocator(Locator): - """ - This locator uses XML-RPC to locate distributions. It therefore - cannot be used with simple mirrors (that only mirror file content). - """ - def __init__(self, url, **kwargs): - """ - Initialise an instance. - - :param url: The URL to use for XML-RPC. - :param kwargs: Passed to the superclass constructor. - """ - super(PyPIRPCLocator, self).__init__(**kwargs) - self.base_url = url - self.client = ServerProxy(url, timeout=3.0) - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - return set(self.client.list_packages()) - - def _get_project(self, name): - result = {} - versions = self.client.package_releases(name, True) - for v in versions: - urls = self.client.release_urls(name, v) - data = self.client.release_data(name, v) - metadata = Metadata(scheme=self.scheme) - metadata.name = data['name'] - metadata.version = data['version'] - metadata.license = data.get('license') - metadata.keywords = data.get('keywords', []) - metadata.summary = data.get('summary') - dist = Distribution(metadata) - if urls: - info = urls[0] - metadata.source_url = info['url'] - dist.digest = self._get_digest(info) - dist.locator = self - result[v] = dist - return result - -class PyPIJSONLocator(Locator): - """ - This locator uses PyPI's JSON interface. It's very limited in functionality - nad probably not worth using. - """ - def __init__(self, url, **kwargs): - super(PyPIJSONLocator, self).__init__(**kwargs) - self.base_url = ensure_slash(url) - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - raise NotImplementedError('Not available from this locator') - - def _get_project(self, name): - result = {} - url = urljoin(self.base_url, '%s/json' % quote(name)) - try: - resp = self.opener.open(url) - data = resp.read().decode() # for now - d = json.loads(data) - md = Metadata(scheme=self.scheme) - data = d['info'] - md.name = data['name'] - md.version = data['version'] - md.license = data.get('license') - md.keywords = data.get('keywords', []) - md.summary = data.get('summary') - dist = Distribution(md) - urls = d['urls'] - if urls: - info = urls[0] - md.source_url = info['url'] - dist.digest = self._get_digest(info) - dist.locator = self - result[md.version] = dist - except Exception as e: - logger.exception('JSON fetch failed: %s', e) - return result - - -class Page(object): - """ - This class represents a scraped HTML page. - """ - # The following slightly hairy-looking regex just looks for the contents of - # an anchor link, which has an attribute "href" either immediately preceded - # or immediately followed by a "rel" attribute. The attribute values can be - # declared with double quotes, single quotes or no quotes - which leads to - # the length of the expression. - _href = re.compile(""" -(rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*))\s+)? -href\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*)) -(\s+rel\s*=\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\s\n]*)))? -""", re.I | re.S | re.X) - _base = re.compile(r"""]+)""", re.I | re.S) - - def __init__(self, data, url): - """ - Initialise an instance with the Unicode page contents and the URL they - came from. - """ - self.data = data - self.base_url = self.url = url - m = self._base.search(self.data) - if m: - self.base_url = m.group(1) - - _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) - - @cached_property - def links(self): - """ - Return the URLs of all the links on a page together with information - about their "rel" attribute, for determining which ones to treat as - downloads and which ones to queue for further scraping. - """ - def clean(url): - "Tidy up an URL." - scheme, netloc, path, params, query, frag = urlparse(url) - return urlunparse((scheme, netloc, quote(path), - params, query, frag)) - - result = set() - for match in self._href.finditer(self.data): - d = match.groupdict('') - rel = (d['rel1'] or d['rel2'] or d['rel3'] or - d['rel4'] or d['rel5'] or d['rel6']) - url = d['url1'] or d['url2'] or d['url3'] - url = urljoin(self.base_url, url) - url = unescape(url) - url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url) - result.add((url, rel)) - # We sort the result, hoping to bring the most recent versions - # to the front - result = sorted(result, key=lambda t: t[0], reverse=True) - return result - - -class SimpleScrapingLocator(Locator): - """ - A locator which scrapes HTML pages to locate downloads for a distribution. - This runs multiple threads to do the I/O; performance is at least as good - as pip's PackageFinder, which works in an analogous fashion. - """ - - # These are used to deal with various Content-Encoding schemes. - decoders = { - 'deflate': zlib.decompress, - 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(d)).read(), - 'none': lambda b: b, - } - - def __init__(self, url, timeout=None, num_workers=10, **kwargs): - """ - Initialise an instance. - :param url: The root URL to use for scraping. - :param timeout: The timeout, in seconds, to be applied to requests. - This defaults to ``None`` (no timeout specified). - :param num_workers: The number of worker threads you want to do I/O, - This defaults to 10. - :param kwargs: Passed to the superclass. - """ - super(SimpleScrapingLocator, self).__init__(**kwargs) - self.base_url = ensure_slash(url) - self.timeout = timeout - self._page_cache = {} - self._seen = set() - self._to_fetch = queue.Queue() - self._bad_hosts = set() - self.skip_externals = False - self.num_workers = num_workers - self._lock = threading.RLock() - - def _prepare_threads(self): - """ - Threads are created only when get_project is called, and terminate - before it returns. They are there primarily to parallelise I/O (i.e. - fetching web pages). - """ - self._threads = [] - for i in range(self.num_workers): - t = threading.Thread(target=self._fetch) - t.setDaemon(True) - t.start() - self._threads.append(t) - - def _wait_threads(self): - """ - Tell all the threads to terminate (by sending a sentinel value) and - wait for them to do so. - """ - # Note that you need two loops, since you can't say which - # thread will get each sentinel - for t in self._threads: - self._to_fetch.put(None) # sentinel - for t in self._threads: - t.join() - self._threads = [] - - def _get_project(self, name): - self.result = result = {} - self.project_name = name - url = urljoin(self.base_url, '%s/' % quote(name)) - self._seen.clear() - self._page_cache.clear() - self._prepare_threads() - try: - logger.debug('Queueing %s', url) - self._to_fetch.put(url) - self._to_fetch.join() - finally: - self._wait_threads() - del self.result - return result - - platform_dependent = re.compile(r'\b(linux-(i\d86|x86_64|arm\w+)|' - r'win(32|-amd64)|macosx-?\d+)\b', re.I) - - def _is_platform_dependent(self, url): - """ - Does an URL refer to a platform-specific download? - """ - return self.platform_dependent.search(url) - - def _process_download(self, url): - """ - See if an URL is a suitable download for a project. - - If it is, register information in the result dictionary (for - _get_project) about the specific version it's for. - - Note that the return value isn't actually used other than as a boolean - value. - """ - if self._is_platform_dependent(url): - info = None - else: - info = self.convert_url_to_download_info(url, self.project_name) - logger.debug('process_download: %s -> %s', url, info) - if info: - with self._lock: # needed because self.result is shared - self._update_version_data(self.result, info) - return info - - def _should_queue(self, link, referrer, rel): - """ - Determine whether a link URL from a referring page and with a - particular "rel" attribute should be queued for scraping. - """ - scheme, netloc, path, _, _, _ = urlparse(link) - if path.endswith(self.source_extensions + self.binary_extensions + - self.excluded_extensions): - result = False - elif self.skip_externals and not link.startswith(self.base_url): - result = False - elif not referrer.startswith(self.base_url): - result = False - elif rel not in ('homepage', 'download'): - result = False - elif scheme not in ('http', 'https', 'ftp'): - result = False - elif self._is_platform_dependent(link): - result = False - else: - host = netloc.split(':', 1)[0] - if host.lower() == 'localhost': - result = False - else: - result = True - logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, - referrer, result) - return result - - def _fetch(self): - """ - Get a URL to fetch from the work queue, get the HTML page, examine its - links for download candidates and candidates for further scraping. - - This is a handy method to run in a thread. - """ - while True: - url = self._to_fetch.get() - try: - if url: - page = self.get_page(url) - if page is None: # e.g. after an error - continue - for link, rel in page.links: - if link not in self._seen: - self._seen.add(link) - if (not self._process_download(link) and - self._should_queue(link, url, rel)): - logger.debug('Queueing %s from %s', link, url) - self._to_fetch.put(link) - finally: - # always do this, to avoid hangs :-) - self._to_fetch.task_done() - if not url: - #logger.debug('Sentinel seen, quitting.') - break - - def get_page(self, url): - """ - Get the HTML for an URL, possibly from an in-memory cache. - - XXX TODO Note: this cache is never actually cleared. It's assumed that - the data won't get stale over the lifetime of a locator instance (not - necessarily true for the default_locator). - """ - # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api - scheme, netloc, path, _, _, _ = urlparse(url) - if scheme == 'file' and os.path.isdir(url2pathname(path)): - url = urljoin(ensure_slash(url), 'index.html') - - if url in self._page_cache: - result = self._page_cache[url] - logger.debug('Returning %s from cache: %s', url, result) - else: - host = netloc.split(':', 1)[0] - result = None - if host in self._bad_hosts: - logger.debug('Skipping %s due to bad host %s', url, host) - else: - req = Request(url, headers={'Accept-encoding': 'identity'}) - try: - logger.debug('Fetching %s', url) - resp = self.opener.open(req, timeout=self.timeout) - logger.debug('Fetched %s', url) - headers = resp.info() - content_type = headers.get('Content-Type', '') - if HTML_CONTENT_TYPE.match(content_type): - final_url = resp.geturl() - data = resp.read() - encoding = headers.get('Content-Encoding') - if encoding: - decoder = self.decoders[encoding] # fail if not found - data = decoder(data) - encoding = 'utf-8' - m = CHARSET.search(content_type) - if m: - encoding = m.group(1) - try: - data = data.decode(encoding) - except UnicodeError: - data = data.decode('latin-1') # fallback - result = Page(data, final_url) - self._page_cache[final_url] = result - except HTTPError as e: - if e.code != 404: - logger.exception('Fetch failed: %s: %s', url, e) - except URLError as e: - logger.exception('Fetch failed: %s: %s', url, e) - with self._lock: - self._bad_hosts.add(host) - except Exception as e: - logger.exception('Fetch failed: %s: %s', url, e) - finally: - self._page_cache[url] = result # even if None (failure) - return result - - _distname_re = re.compile(']*>([^<]+)<') - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - result = set() - page = self.get_page(self.base_url) - if not page: - raise DistlibException('Unable to get %s' % self.base_url) - for match in self._distname_re.finditer(page.data): - result.add(match.group(1)) - return result - -class DirectoryLocator(Locator): - """ - This class locates distributions in a directory tree. - """ - - def __init__(self, path, **kwargs): - """ - Initialise an instance. - :param path: The root of the directory tree to search. - :param kwargs: Passed to the superclass constructor, - except for: - * recursive - if True (the default), subdirectories are - recursed into. If False, only the top-level directory - is searched, - """ - self.recursive = kwargs.pop('recursive', True) - super(DirectoryLocator, self).__init__(**kwargs) - path = os.path.abspath(path) - if not os.path.isdir(path): - raise DistlibException('Not a directory: %r' % path) - self.base_dir = path - - def should_include(self, filename, parent): - """ - Should a filename be considered as a candidate for a distribution - archive? As well as the filename, the directory which contains it - is provided, though not used by the current implementation. - """ - return filename.endswith(self.downloadable_extensions) - - def _get_project(self, name): - result = {} - for root, dirs, files in os.walk(self.base_dir): - for fn in files: - if self.should_include(fn, root): - fn = os.path.join(root, fn) - url = urlunparse(('file', '', - pathname2url(os.path.abspath(fn)), - '', '', '')) - info = self.convert_url_to_download_info(url, name) - if info: - self._update_version_data(result, info) - if not self.recursive: - break - return result - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - result = set() - for root, dirs, files in os.walk(self.base_dir): - for fn in files: - if self.should_include(fn, root): - fn = os.path.join(root, fn) - url = urlunparse(('file', '', - pathname2url(os.path.abspath(fn)), - '', '', '')) - info = self.convert_url_to_download_info(url, None) - if info: - result.add(info['name']) - if not self.recursive: - break - return result - -class JSONLocator(Locator): - """ - This locator uses special extended metadata (not available on PyPI) and is - the basis of performant dependency resolution in distlib. Other locators - require archive downloads before dependencies can be determined! As you - might imagine, that can be slow. - """ - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - raise NotImplementedError('Not available from this locator') - - def _get_project(self, name): - result = {} - data = get_project_data(name) - if data: - for info in data.get('files', []): - if info['ptype'] != 'sdist' or info['pyversion'] != 'source': - continue - # We don't store summary in project metadata as it makes - # the data bigger for no benefit during dependency - # resolution - dist = make_dist(data['name'], info['version'], - summary=data.get('summary', - 'Placeholder for summary'), - scheme=self.scheme) - md = dist.metadata - md.source_url = info['url'] - # TODO SHA256 digest - if 'digest' in info and info['digest']: - dist.digest = ('md5', info['digest']) - md.dependencies = info.get('requirements', {}) - dist.exports = info.get('exports', {}) - result[dist.version] = dist - return result - -class DistPathLocator(Locator): - """ - This locator finds installed distributions in a path. It can be useful for - adding to an :class:`AggregatingLocator`. - """ - def __init__(self, distpath, **kwargs): - """ - Initialise an instance. - - :param distpath: A :class:`DistributionPath` instance to search. - """ - super(DistPathLocator, self).__init__(**kwargs) - assert isinstance(distpath, DistributionPath) - self.distpath = distpath - - def _get_project(self, name): - dist = self.distpath.get_distribution(name) - if dist is None: - result = {} - else: - result = { dist.version: dist } - return result - - -class AggregatingLocator(Locator): - """ - This class allows you to chain and/or merge a list of locators. - """ - def __init__(self, *locators, **kwargs): - """ - Initialise an instance. - - :param locators: The list of locators to search. - :param kwargs: Passed to the superclass constructor, - except for: - * merge - if False (the default), the first successful - search from any of the locators is returned. If True, - the results from all locators are merged (this can be - slow). - """ - self.merge = kwargs.pop('merge', False) - self.locators = locators - super(AggregatingLocator, self).__init__(**kwargs) - - def clear_cache(self): - super(AggregatingLocator, self).clear_cache() - for locator in self.locators: - locator.clear_cache() - - def _set_scheme(self, value): - self._scheme = value - for locator in self.locators: - locator.scheme = value - - scheme = property(Locator.scheme.fget, _set_scheme) - - def _get_project(self, name): - result = {} - for locator in self.locators: - d = locator.get_project(name) - if d: - if self.merge: - result.update(d) - else: - # See issue #18. If any dists are found and we're looking - # for specific constraints, we only return something if - # a match is found. For example, if a DirectoryLocator - # returns just foo (1.0) while we're looking for - # foo (>= 2.0), we'll pretend there was nothing there so - # that subsequent locators can be queried. Otherwise we - # would just return foo (1.0) which would then lead to a - # failure to find foo (>= 2.0), because other locators - # weren't searched. Note that this only matters when - # merge=False. - if self.matcher is None: - found = True - else: - found = False - for k in d: - if self.matcher.match(k): - found = True - break - if found: - result = d - break - return result - - def get_distribution_names(self): - """ - Return all the distribution names known to this locator. - """ - result = set() - for locator in self.locators: - try: - result |= locator.get_distribution_names() - except NotImplementedError: - pass - return result - - -# We use a legacy scheme simply because most of the dists on PyPI use legacy -# versions which don't conform to PEP 426 / PEP 440. -default_locator = AggregatingLocator( - JSONLocator(), - SimpleScrapingLocator('https://pypi.python.org/simple/', - timeout=3.0), - scheme='legacy') - -locate = default_locator.locate - -NAME_VERSION_RE = re.compile(r'(?P[\w-]+)\s*' - r'\(\s*(==\s*)?(?P[^)]+)\)$') - -class DependencyFinder(object): - """ - Locate dependencies for distributions. - """ - - def __init__(self, locator=None): - """ - Initialise an instance, using the specified locator - to locate distributions. - """ - self.locator = locator or default_locator - self.scheme = get_scheme(self.locator.scheme) - - def add_distribution(self, dist): - """ - Add a distribution to the finder. This will update internal information - about who provides what. - :param dist: The distribution to add. - """ - logger.debug('adding distribution %s', dist) - name = dist.key - self.dists_by_name[name] = dist - self.dists[(name, dist.version)] = dist - for p in dist.provides: - name, version = parse_name_and_version(p) - logger.debug('Add to provided: %s, %s, %s', name, version, dist) - self.provided.setdefault(name, set()).add((version, dist)) - - def remove_distribution(self, dist): - """ - Remove a distribution from the finder. This will update internal - information about who provides what. - :param dist: The distribution to remove. - """ - logger.debug('removing distribution %s', dist) - name = dist.key - del self.dists_by_name[name] - del self.dists[(name, dist.version)] - for p in dist.provides: - name, version = parse_name_and_version(p) - logger.debug('Remove from provided: %s, %s, %s', name, version, dist) - s = self.provided[name] - s.remove((version, dist)) - if not s: - del self.provided[name] - - def get_matcher(self, reqt): - """ - Get a version matcher for a requirement. - :param reqt: The requirement - :type reqt: str - :return: A version matcher (an instance of - :class:`distlib.version.Matcher`). - """ - try: - matcher = self.scheme.matcher(reqt) - except UnsupportedVersionError: - # XXX compat-mode if cannot read the version - name = reqt.split()[0] - matcher = self.scheme.matcher(name) - return matcher - - def find_providers(self, reqt): - """ - Find the distributions which can fulfill a requirement. - - :param reqt: The requirement. - :type reqt: str - :return: A set of distribution which can fulfill the requirement. - """ - matcher = self.get_matcher(reqt) - name = matcher.key # case-insensitive - result = set() - provided = self.provided - if name in provided: - for version, provider in provided[name]: - try: - match = matcher.match(version) - except UnsupportedVersionError: - match = False - - if match: - result.add(provider) - break - return result - - def try_to_replace(self, provider, other, problems): - """ - Attempt to replace one provider with another. This is typically used - when resolving dependencies from multiple sources, e.g. A requires - (B >= 1.0) while C requires (B >= 1.1). - - For successful replacement, ``provider`` must meet all the requirements - which ``other`` fulfills. - - :param provider: The provider we are trying to replace with. - :param other: The provider we're trying to replace. - :param problems: If False is returned, this will contain what - problems prevented replacement. This is currently - a tuple of the literal string 'cantreplace', - ``provider``, ``other`` and the set of requirements - that ``provider`` couldn't fulfill. - :return: True if we can replace ``other`` with ``provider``, else - False. - """ - rlist = self.reqts[other] - unmatched = set() - for s in rlist: - matcher = self.get_matcher(s) - if not matcher.match(provider.version): - unmatched.add(s) - if unmatched: - # can't replace other with provider - problems.add(('cantreplace', provider, other, unmatched)) - result = False - else: - # can replace other with provider - self.remove_distribution(other) - del self.reqts[other] - for s in rlist: - self.reqts.setdefault(provider, set()).add(s) - self.add_distribution(provider) - result = True - return result - - def find(self, requirement, meta_extras=None, prereleases=False): - """ - Find a distribution and all distributions it depends on. - - :param requirement: The requirement specifying the distribution to - find, or a Distribution instance. - :param meta_extras: A list of meta extras such as :test:, :build: and - so on. - :param prereleases: If ``True``, allow pre-release versions to be - returned - otherwise, don't return prereleases - unless they're all that's available. - - Return a set of :class:`Distribution` instances and a set of - problems. - - The distributions returned should be such that they have the - :attr:`required` attribute set to ``True`` if they were - from the ``requirement`` passed to ``find()``, and they have the - :attr:`build_time_dependency` attribute set to ``True`` unless they - are post-installation dependencies of the ``requirement``. - - The problems should be a tuple consisting of the string - ``'unsatisfied'`` and the requirement which couldn't be satisfied - by any distribution known to the locator. - """ - - self.provided = {} - self.dists = {} - self.dists_by_name = {} - self.reqts = {} - - meta_extras = set(meta_extras or []) - if ':*:' in meta_extras: - meta_extras.remove(':*:') - # :meta: and :run: are implicitly included - meta_extras |= set([':test:', ':build:', ':dev:']) - - if isinstance(requirement, Distribution): - dist = odist = requirement - logger.debug('passed %s as requirement', odist) - else: - dist = odist = self.locator.locate(requirement, - prereleases=prereleases) - if dist is None: - raise DistlibException('Unable to locate %r' % requirement) - logger.debug('located %s', odist) - dist.requested = True - problems = set() - todo = set([dist]) - install_dists = set([odist]) - while todo: - dist = todo.pop() - name = dist.key # case-insensitive - if name not in self.dists_by_name: - self.add_distribution(dist) - else: - #import pdb; pdb.set_trace() - other = self.dists_by_name[name] - if other != dist: - self.try_to_replace(dist, other, problems) - - ireqts = dist.run_requires | dist.meta_requires - sreqts = dist.build_requires - ereqts = set() - if dist in install_dists: - for key in ('test', 'build', 'dev'): - e = ':%s:' % key - if e in meta_extras: - ereqts |= getattr(dist, '%s_requires' % key) - all_reqts = ireqts | sreqts | ereqts - for r in all_reqts: - providers = self.find_providers(r) - if not providers: - logger.debug('No providers found for %r', r) - provider = self.locator.locate(r, prereleases=prereleases) - # If no provider is found and we didn't consider - # prereleases, consider them now. - if provider is None and not prereleases: - provider = self.locator.locate(r, prereleases=True) - if provider is None: - logger.debug('Cannot satisfy %r', r) - problems.add(('unsatisfied', r)) - else: - n, v = provider.key, provider.version - if (n, v) not in self.dists: - todo.add(provider) - providers.add(provider) - if r in ireqts and dist in install_dists: - install_dists.add(provider) - logger.debug('Adding %s to install_dists', - provider.name_and_version) - for p in providers: - name = p.key - if name not in self.dists_by_name: - self.reqts.setdefault(p, set()).add(r) - else: - other = self.dists_by_name[name] - if other != p: - # see if other can be replaced by p - self.try_to_replace(p, other, problems) - - dists = set(self.dists.values()) - for dist in dists: - dist.build_time_dependency = dist not in install_dists - if dist.build_time_dependency: - logger.debug('%s is a build-time dependency only.', - dist.name_and_version) - logger.debug('find done for %s', odist) - return dists, problems diff --git a/awx/lib/site-packages/pip/_vendor/distlib/manifest.py b/awx/lib/site-packages/pip/_vendor/distlib/manifest.py deleted file mode 100644 index c6b98c59a3..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/manifest.py +++ /dev/null @@ -1,364 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2013 Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -""" -Class representing the list of files in a distribution. - -Equivalent to distutils.filelist, but fixes some problems. -""" -import fnmatch -import logging -import os -import re - -from . import DistlibException -from .compat import fsdecode -from .util import convert_path - - -__all__ = ['Manifest'] - -logger = logging.getLogger(__name__) - -# a \ followed by some spaces + EOL -_COLLAPSE_PATTERN = re.compile('\\\w*\n', re.M) -_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) - - -class Manifest(object): - """A list of files built by on exploring the filesystem and filtered by - applying various patterns to what we find there. - """ - - def __init__(self, base=None): - """ - Initialise an instance. - - :param base: The base directory to explore under. - """ - self.base = os.path.abspath(os.path.normpath(base or os.getcwd())) - self.prefix = self.base + os.sep - self.allfiles = None - self.files = set() - - # - # Public API - # - - def findall(self): - """Find all files under the base and set ``allfiles`` to the absolute - pathnames of files found. - """ - from stat import S_ISREG, S_ISDIR, S_ISLNK - - self.allfiles = allfiles = [] - root = self.base - stack = [root] - pop = stack.pop - push = stack.append - - while stack: - root = pop() - names = os.listdir(root) - - for name in names: - fullname = os.path.join(root, name) - - # Avoid excess stat calls -- just one will do, thank you! - stat = os.stat(fullname) - mode = stat.st_mode - if S_ISREG(mode): - allfiles.append(fsdecode(fullname)) - elif S_ISDIR(mode) and not S_ISLNK(mode): - push(fullname) - - def add(self, item): - """ - Add a file to the manifest. - - :param item: The pathname to add. This can be relative to the base. - """ - if not item.startswith(self.prefix): - item = os.path.join(self.base, item) - self.files.add(os.path.normpath(item)) - - def add_many(self, items): - """ - Add a list of files to the manifest. - - :param items: The pathnames to add. These can be relative to the base. - """ - for item in items: - self.add(item) - - def sorted(self, wantdirs=False): - """ - Return sorted files in directory order - """ - - def add_dir(dirs, d): - dirs.add(d) - logger.debug('add_dir added %s', d) - if d != self.base: - parent, _ = os.path.split(d) - assert parent not in ('', '/') - add_dir(dirs, parent) - - result = set(self.files) # make a copy! - if wantdirs: - dirs = set() - for f in result: - add_dir(dirs, os.path.dirname(f)) - result |= dirs - return [os.path.join(*path_tuple) for path_tuple in - sorted(os.path.split(path) for path in result)] - - def clear(self): - """Clear all collected files.""" - self.files = set() - self.allfiles = [] - - def process_directive(self, directive): - """ - Process a directive which either adds some files from ``allfiles`` to - ``files``, or removes some files from ``files``. - - :param directive: The directive to process. This should be in a format - compatible with distutils ``MANIFEST.in`` files: - - http://docs.python.org/distutils/sourcedist.html#commands - """ - # Parse the line: split it up, make sure the right number of words - # is there, and return the relevant words. 'action' is always - # defined: it's the first word of the line. Which of the other - # three are defined depends on the action; it'll be either - # patterns, (dir and patterns), or (dirpattern). - action, patterns, thedir, dirpattern = self._parse_directive(directive) - - # OK, now we know that the action is valid and we have the - # right number of words on the line for that action -- so we - # can proceed with minimal error-checking. - if action == 'include': - for pattern in patterns: - if not self._include_pattern(pattern, anchor=True): - logger.warning('no files found matching %r', pattern) - - elif action == 'exclude': - for pattern in patterns: - if not self._exclude_pattern(pattern, anchor=True): - logger.warning('no previously-included files ' - 'found matching %r', pattern) - - elif action == 'global-include': - for pattern in patterns: - if not self._include_pattern(pattern, anchor=False): - logger.warning('no files found matching %r ' - 'anywhere in distribution', pattern) - - elif action == 'global-exclude': - for pattern in patterns: - if not self._exclude_pattern(pattern, anchor=False): - logger.warning('no previously-included files ' - 'matching %r found anywhere in ' - 'distribution', pattern) - - elif action == 'recursive-include': - for pattern in patterns: - if not self._include_pattern(pattern, prefix=thedir): - logger.warning('no files found matching %r ' - 'under directory %r', pattern, thedir) - - elif action == 'recursive-exclude': - for pattern in patterns: - if not self._exclude_pattern(pattern, prefix=thedir): - logger.warning('no previously-included files ' - 'matching %r found under directory %r', - pattern, thedir) - - elif action == 'graft': - if not self._include_pattern(None, prefix=dirpattern): - logger.warning('no directories found matching %r', - dirpattern) - - elif action == 'prune': - if not self._exclude_pattern(None, prefix=dirpattern): - logger.warning('no previously-included directories found ' - 'matching %r', dirpattern) - else: # pragma: no cover - # This should never happen, as it should be caught in - # _parse_template_line - raise DistlibException( - 'invalid action %r' % action) - - # - # Private API - # - - def _parse_directive(self, directive): - """ - Validate a directive. - :param directive: The directive to validate. - :return: A tuple of action, patterns, thedir, dir_patterns - """ - words = directive.split() - if len(words) == 1 and words[0] not in ('include', 'exclude', - 'global-include', - 'global-exclude', - 'recursive-include', - 'recursive-exclude', - 'graft', 'prune'): - # no action given, let's use the default 'include' - words.insert(0, 'include') - - action = words[0] - patterns = thedir = dir_pattern = None - - if action in ('include', 'exclude', - 'global-include', 'global-exclude'): - if len(words) < 2: - raise DistlibException( - '%r expects ...' % action) - - patterns = [convert_path(word) for word in words[1:]] - - elif action in ('recursive-include', 'recursive-exclude'): - if len(words) < 3: - raise DistlibException( - '%r expects ...' % action) - - thedir = convert_path(words[1]) - patterns = [convert_path(word) for word in words[2:]] - - elif action in ('graft', 'prune'): - if len(words) != 2: - raise DistlibException( - '%r expects a single ' % action) - - dir_pattern = convert_path(words[1]) - - else: - raise DistlibException('unknown action %r' % action) - - return action, patterns, thedir, dir_pattern - - def _include_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): - """Select strings (presumably filenames) from 'self.files' that - match 'pattern', a Unix-style wildcard (glob) pattern. - - Patterns are not quite the same as implemented by the 'fnmatch' - module: '*' and '?' match non-special characters, where "special" - is platform-dependent: slash on Unix; colon, slash, and backslash on - DOS/Windows; and colon on Mac OS. - - If 'anchor' is true (the default), then the pattern match is more - stringent: "*.py" will match "foo.py" but not "foo/bar.py". If - 'anchor' is false, both of these will match. - - If 'prefix' is supplied, then only filenames starting with 'prefix' - (itself a pattern) and ending with 'pattern', with anything in between - them, will match. 'anchor' is ignored in this case. - - If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and - 'pattern' is assumed to be either a string containing a regex or a - regex object -- no translation is done, the regex is just compiled - and used as-is. - - Selected strings will be added to self.files. - - Return True if files are found. - """ - # XXX docstring lying about what the special chars are? - found = False - pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) - - # delayed loading of allfiles list - if self.allfiles is None: - self.findall() - - for name in self.allfiles: - if pattern_re.search(name): - self.files.add(name) - found = True - return found - - def _exclude_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): - """Remove strings (presumably filenames) from 'files' that match - 'pattern'. - - Other parameters are the same as for 'include_pattern()', above. - The list 'self.files' is modified in place. Return True if files are - found. - - This API is public to allow e.g. exclusion of SCM subdirs, e.g. when - packaging source distributions - """ - found = False - pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) - for f in list(self.files): - if pattern_re.search(f): - self.files.remove(f) - found = True - return found - - def _translate_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): - """Translate a shell-like wildcard pattern to a compiled regular - expression. - - Return the compiled regex. If 'is_regex' true, - then 'pattern' is directly compiled to a regex (if it's a string) - or just returned as-is (assumes it's a regex object). - """ - if is_regex: - if isinstance(pattern, str): - return re.compile(pattern) - else: - return pattern - - if pattern: - pattern_re = self._glob_to_re(pattern) - else: - pattern_re = '' - - base = re.escape(os.path.join(self.base, '')) - if prefix is not None: - # ditch end of pattern character - empty_pattern = self._glob_to_re('') - prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)] - sep = os.sep - if os.sep == '\\': - sep = r'\\' - pattern_re = '^' + base + sep.join((prefix_re, - '.*' + pattern_re)) - else: # no prefix -- respect anchor flag - if anchor: - pattern_re = '^' + base + pattern_re - - return re.compile(pattern_re) - - def _glob_to_re(self, pattern): - """Translate a shell-like glob pattern to a regular expression. - - Return a string containing the regex. Differs from - 'fnmatch.translate()' in that '*' does not match "special characters" - (which are platform-specific). - """ - pattern_re = fnmatch.translate(pattern) - - # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which - # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, - # and by extension they shouldn't match such "special characters" under - # any OS. So change all non-escaped dots in the RE to match any - # character except the special characters (currently: just os.sep). - sep = os.sep - if os.sep == '\\': - # we're using a regex to manipulate a regex, so we need - # to escape the backslash twice - sep = r'\\\\' - escaped = r'\1[^%s]' % sep - pattern_re = re.sub(r'((? y, - 'gte': lambda x, y: x >= y, - 'in': lambda x, y: x in y, - 'lt': lambda x, y: x < y, - 'lte': lambda x, y: x <= y, - 'not': lambda x: not x, - 'noteq': lambda x, y: x != y, - 'notin': lambda x, y: x not in y, - } - - allowed_values = { - 'sys_platform': sys.platform, - 'python_version': '%s.%s' % sys.version_info[:2], - # parsing sys.platform is not reliable, but there is no other - # way to get e.g. 2.7.2+, and the PEP is defined with sys.version - 'python_full_version': sys.version.split(' ', 1)[0], - 'os_name': os.name, - 'platform_in_venv': str(in_venv()), - 'platform_release': platform.release(), - 'platform_version': platform.version(), - 'platform_machine': platform.machine(), - 'platform_python_implementation': python_implementation(), - } - - def __init__(self, context=None): - """ - Initialise an instance. - - :param context: If specified, names are looked up in this mapping. - """ - self.context = context or {} - self.source = None - - def get_fragment(self, offset): - """ - Get the part of the source which is causing a problem. - """ - fragment_len = 10 - s = '%r' % (self.source[offset:offset + fragment_len]) - if offset + fragment_len < len(self.source): - s += '...' - return s - - def get_handler(self, node_type): - """ - Get a handler for the specified AST node type. - """ - return getattr(self, 'do_%s' % node_type, None) - - def evaluate(self, node, filename=None): - """ - Evaluate a source string or node, using ``filename`` when - displaying errors. - """ - if isinstance(node, string_types): - self.source = node - kwargs = {'mode': 'eval'} - if filename: - kwargs['filename'] = filename - try: - node = ast.parse(node, **kwargs) - except SyntaxError as e: - s = self.get_fragment(e.offset) - raise SyntaxError('syntax error %s' % s) - node_type = node.__class__.__name__.lower() - handler = self.get_handler(node_type) - if handler is None: - if self.source is None: - s = '(source not available)' - else: - s = self.get_fragment(node.col_offset) - raise SyntaxError("don't know how to evaluate %r %s" % ( - node_type, s)) - return handler(node) - - def get_attr_key(self, node): - assert isinstance(node, ast.Attribute), 'attribute node expected' - return '%s.%s' % (node.value.id, node.attr) - - def do_attribute(self, node): - if not isinstance(node.value, ast.Name): - valid = False - else: - key = self.get_attr_key(node) - valid = key in self.context or key in self.allowed_values - if not valid: - raise SyntaxError('invalid expression: %s' % key) - if key in self.context: - result = self.context[key] - else: - result = self.allowed_values[key] - return result - - def do_boolop(self, node): - result = self.evaluate(node.values[0]) - is_or = node.op.__class__ is ast.Or - is_and = node.op.__class__ is ast.And - assert is_or or is_and - if (is_and and result) or (is_or and not result): - for n in node.values[1:]: - result = self.evaluate(n) - if (is_or and result) or (is_and and not result): - break - return result - - def do_compare(self, node): - def sanity_check(lhsnode, rhsnode): - valid = True - if isinstance(lhsnode, ast.Str) and isinstance(rhsnode, ast.Str): - valid = False - #elif (isinstance(lhsnode, ast.Attribute) - # and isinstance(rhsnode, ast.Attribute)): - # klhs = self.get_attr_key(lhsnode) - # krhs = self.get_attr_key(rhsnode) - # valid = klhs != krhs - if not valid: - s = self.get_fragment(node.col_offset) - raise SyntaxError('Invalid comparison: %s' % s) - - lhsnode = node.left - lhs = self.evaluate(lhsnode) - result = True - for op, rhsnode in zip(node.ops, node.comparators): - sanity_check(lhsnode, rhsnode) - op = op.__class__.__name__.lower() - if op not in self.operators: - raise SyntaxError('unsupported operation: %r' % op) - rhs = self.evaluate(rhsnode) - result = self.operators[op](lhs, rhs) - if not result: - break - lhs = rhs - lhsnode = rhsnode - return result - - def do_expression(self, node): - return self.evaluate(node.body) - - def do_name(self, node): - valid = False - if node.id in self.context: - valid = True - result = self.context[node.id] - elif node.id in self.allowed_values: - valid = True - result = self.allowed_values[node.id] - if not valid: - raise SyntaxError('invalid expression: %s' % node.id) - return result - - def do_str(self, node): - return node.s - - -def interpret(marker, execution_context=None): - """ - Interpret a marker and return a result depending on environment. - - :param marker: The marker to interpret. - :type marker: str - :param execution_context: The context used for name lookup. - :type execution_context: mapping - """ - return Evaluator(execution_context).evaluate(marker.strip()) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/metadata.py b/awx/lib/site-packages/pip/_vendor/distlib/metadata.py deleted file mode 100644 index ef3b1d6b3a..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/metadata.py +++ /dev/null @@ -1,1015 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -"""Implementation of the Metadata for Python packages PEPs. - -Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental). -""" -from __future__ import unicode_literals - -import codecs -from email import message_from_file -import json -import logging -import re - - -from . import DistlibException, __version__ -from .compat import StringIO, string_types, text_type -from .markers import interpret -from .util import extract_by_key, get_extras -from .version import get_scheme, PEP426_VERSION_RE - -logger = logging.getLogger(__name__) - - -class MetadataMissingError(DistlibException): - """A required metadata is missing""" - - -class MetadataConflictError(DistlibException): - """Attempt to read or write metadata fields that are conflictual.""" - - -class MetadataUnrecognizedVersionError(DistlibException): - """Unknown metadata version number.""" - - -class MetadataInvalidError(DistlibException): - """A metadata value is invalid""" - -# public API of this module -__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] - -# Encoding used for the PKG-INFO files -PKG_INFO_ENCODING = 'utf-8' - -# preferred version. Hopefully will be changed -# to 1.2 once PEP 345 is supported everywhere -PKG_INFO_PREFERRED_VERSION = '1.1' - -_LINE_PREFIX = re.compile('\n \|') -_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'License') - -_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'License', 'Classifier', 'Download-URL', 'Obsoletes', - 'Provides', 'Requires') - -_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', - 'Download-URL') - -_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'Maintainer', 'Maintainer-email', 'License', - 'Classifier', 'Download-URL', 'Obsoletes-Dist', - 'Project-URL', 'Provides-Dist', 'Requires-Dist', - 'Requires-Python', 'Requires-External') - -_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', - 'Obsoletes-Dist', 'Requires-External', 'Maintainer', - 'Maintainer-email', 'Project-URL') - -_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'Maintainer', 'Maintainer-email', 'License', - 'Classifier', 'Download-URL', 'Obsoletes-Dist', - 'Project-URL', 'Provides-Dist', 'Requires-Dist', - 'Requires-Python', 'Requires-External', 'Private-Version', - 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension', - 'Provides-Extra') - -_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', - 'Setup-Requires-Dist', 'Extension') - -_ALL_FIELDS = set() -_ALL_FIELDS.update(_241_FIELDS) -_ALL_FIELDS.update(_314_FIELDS) -_ALL_FIELDS.update(_345_FIELDS) -_ALL_FIELDS.update(_426_FIELDS) - -EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') - - -def _version2fieldlist(version): - if version == '1.0': - return _241_FIELDS - elif version == '1.1': - return _314_FIELDS - elif version == '1.2': - return _345_FIELDS - elif version == '2.0': - return _426_FIELDS - raise MetadataUnrecognizedVersionError(version) - - -def _best_version(fields): - """Detect the best version depending on the fields used.""" - def _has_marker(keys, markers): - for marker in markers: - if marker in keys: - return True - return False - - keys = [] - for key, value in fields.items(): - if value in ([], 'UNKNOWN', None): - continue - keys.append(key) - - possible_versions = ['1.0', '1.1', '1.2', '2.0'] - - # first let's try to see if a field is not part of one of the version - for key in keys: - if key not in _241_FIELDS and '1.0' in possible_versions: - possible_versions.remove('1.0') - if key not in _314_FIELDS and '1.1' in possible_versions: - possible_versions.remove('1.1') - if key not in _345_FIELDS and '1.2' in possible_versions: - possible_versions.remove('1.2') - if key not in _426_FIELDS and '2.0' in possible_versions: - possible_versions.remove('2.0') - - # possible_version contains qualified versions - if len(possible_versions) == 1: - return possible_versions[0] # found ! - elif len(possible_versions) == 0: - raise MetadataConflictError('Unknown metadata set') - - # let's see if one unique marker is found - is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) - is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) - is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS) - if int(is_1_1) + int(is_1_2) + int(is_2_0) > 1: - raise MetadataConflictError('You used incompatible 1.1/1.2/2.0 fields') - - # we have the choice, 1.0, or 1.2, or 2.0 - # - 1.0 has a broken Summary field but works with all tools - # - 1.1 is to avoid - # - 1.2 fixes Summary but has little adoption - # - 2.0 adds more features and is very new - if not is_1_1 and not is_1_2 and not is_2_0: - # we couldn't find any specific marker - if PKG_INFO_PREFERRED_VERSION in possible_versions: - return PKG_INFO_PREFERRED_VERSION - if is_1_1: - return '1.1' - if is_1_2: - return '1.2' - - return '2.0' - -_ATTR2FIELD = { - 'metadata_version': 'Metadata-Version', - 'name': 'Name', - 'version': 'Version', - 'platform': 'Platform', - 'supported_platform': 'Supported-Platform', - 'summary': 'Summary', - 'description': 'Description', - 'keywords': 'Keywords', - 'home_page': 'Home-page', - 'author': 'Author', - 'author_email': 'Author-email', - 'maintainer': 'Maintainer', - 'maintainer_email': 'Maintainer-email', - 'license': 'License', - 'classifier': 'Classifier', - 'download_url': 'Download-URL', - 'obsoletes_dist': 'Obsoletes-Dist', - 'provides_dist': 'Provides-Dist', - 'requires_dist': 'Requires-Dist', - 'setup_requires_dist': 'Setup-Requires-Dist', - 'requires_python': 'Requires-Python', - 'requires_external': 'Requires-External', - 'requires': 'Requires', - 'provides': 'Provides', - 'obsoletes': 'Obsoletes', - 'project_url': 'Project-URL', - 'private_version': 'Private-Version', - 'obsoleted_by': 'Obsoleted-By', - 'extension': 'Extension', - 'provides_extra': 'Provides-Extra', -} - -_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') -_VERSIONS_FIELDS = ('Requires-Python',) -_VERSION_FIELDS = ('Version',) -_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', - 'Requires', 'Provides', 'Obsoletes-Dist', - 'Provides-Dist', 'Requires-Dist', 'Requires-External', - 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist', - 'Provides-Extra', 'Extension') -_LISTTUPLEFIELDS = ('Project-URL',) - -_ELEMENTSFIELD = ('Keywords',) - -_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') - -_MISSING = object() - -_FILESAFE = re.compile('[^A-Za-z0-9.]+') - - -def _get_name_and_version(name, version, for_filename=False): - """Return the distribution name with version. - - If for_filename is true, return a filename-escaped form.""" - if for_filename: - # For both name and version any runs of non-alphanumeric or '.' - # characters are replaced with a single '-'. Additionally any - # spaces in the version string become '.' - name = _FILESAFE.sub('-', name) - version = _FILESAFE.sub('-', version.replace(' ', '.')) - return '%s-%s' % (name, version) - - -class LegacyMetadata(object): - """The legacy metadata of a release. - - Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can - instantiate the class with one of these arguments (or none): - - *path*, the path to a metadata file - - *fileobj* give a file-like object with metadata as content - - *mapping* is a dict-like object - - *scheme* is a version scheme name - """ - # TODO document the mapping API and UNKNOWN default key - - def __init__(self, path=None, fileobj=None, mapping=None, - scheme='default'): - if [path, fileobj, mapping].count(None) < 2: - raise TypeError('path, fileobj and mapping are exclusive') - self._fields = {} - self.requires_files = [] - self._dependencies = None - self.scheme = scheme - if path is not None: - self.read(path) - elif fileobj is not None: - self.read_file(fileobj) - elif mapping is not None: - self.update(mapping) - self.set_metadata_version() - - def set_metadata_version(self): - self._fields['Metadata-Version'] = _best_version(self._fields) - - def _write_field(self, fileobj, name, value): - fileobj.write('%s: %s\n' % (name, value)) - - def __getitem__(self, name): - return self.get(name) - - def __setitem__(self, name, value): - return self.set(name, value) - - def __delitem__(self, name): - field_name = self._convert_name(name) - try: - del self._fields[field_name] - except KeyError: - raise KeyError(name) - - def __contains__(self, name): - return (name in self._fields or - self._convert_name(name) in self._fields) - - def _convert_name(self, name): - if name in _ALL_FIELDS: - return name - name = name.replace('-', '_').lower() - return _ATTR2FIELD.get(name, name) - - def _default_value(self, name): - if name in _LISTFIELDS or name in _ELEMENTSFIELD: - return [] - return 'UNKNOWN' - - def _remove_line_prefix(self, value): - return _LINE_PREFIX.sub('\n', value) - - def __getattr__(self, name): - if name in _ATTR2FIELD: - return self[name] - raise AttributeError(name) - - # - # Public API - # - -# dependencies = property(_get_dependencies, _set_dependencies) - - def get_fullname(self, filesafe=False): - """Return the distribution name with version. - - If filesafe is true, return a filename-escaped form.""" - return _get_name_and_version(self['Name'], self['Version'], filesafe) - - def is_field(self, name): - """return True if name is a valid metadata key""" - name = self._convert_name(name) - return name in _ALL_FIELDS - - def is_multi_field(self, name): - name = self._convert_name(name) - return name in _LISTFIELDS - - def read(self, filepath): - """Read the metadata values from a file path.""" - fp = codecs.open(filepath, 'r', encoding='utf-8') - try: - self.read_file(fp) - finally: - fp.close() - - def read_file(self, fileob): - """Read the metadata values from a file object.""" - msg = message_from_file(fileob) - self._fields['Metadata-Version'] = msg['metadata-version'] - - # When reading, get all the fields we can - for field in _ALL_FIELDS: - if field not in msg: - continue - if field in _LISTFIELDS: - # we can have multiple lines - values = msg.get_all(field) - if field in _LISTTUPLEFIELDS and values is not None: - values = [tuple(value.split(',')) for value in values] - self.set(field, values) - else: - # single line - value = msg[field] - if value is not None and value != 'UNKNOWN': - self.set(field, value) - self.set_metadata_version() - - def write(self, filepath, skip_unknown=False): - """Write the metadata fields to filepath.""" - fp = codecs.open(filepath, 'w', encoding='utf-8') - try: - self.write_file(fp, skip_unknown) - finally: - fp.close() - - def write_file(self, fileobject, skip_unknown=False): - """Write the PKG-INFO format data to a file object.""" - self.set_metadata_version() - - for field in _version2fieldlist(self['Metadata-Version']): - values = self.get(field) - if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']): - continue - if field in _ELEMENTSFIELD: - self._write_field(fileobject, field, ','.join(values)) - continue - if field not in _LISTFIELDS: - if field == 'Description': - values = values.replace('\n', '\n |') - values = [values] - - if field in _LISTTUPLEFIELDS: - values = [','.join(value) for value in values] - - for value in values: - self._write_field(fileobject, field, value) - - def update(self, other=None, **kwargs): - """Set metadata values from the given iterable `other` and kwargs. - - Behavior is like `dict.update`: If `other` has a ``keys`` method, - they are looped over and ``self[key]`` is assigned ``other[key]``. - Else, ``other`` is an iterable of ``(key, value)`` iterables. - - Keys that don't match a metadata field or that have an empty value are - dropped. - """ - def _set(key, value): - if key in _ATTR2FIELD and value: - self.set(self._convert_name(key), value) - - if not other: - # other is None or empty container - pass - elif hasattr(other, 'keys'): - for k in other.keys(): - _set(k, other[k]) - else: - for k, v in other: - _set(k, v) - - if kwargs: - for k, v in kwargs.items(): - _set(k, v) - - def set(self, name, value): - """Control then set a metadata field.""" - name = self._convert_name(name) - - if ((name in _ELEMENTSFIELD or name == 'Platform') and - not isinstance(value, (list, tuple))): - if isinstance(value, string_types): - value = [v.strip() for v in value.split(',')] - else: - value = [] - elif (name in _LISTFIELDS and - not isinstance(value, (list, tuple))): - if isinstance(value, string_types): - value = [value] - else: - value = [] - - if logger.isEnabledFor(logging.WARNING): - project_name = self['Name'] - - scheme = get_scheme(self.scheme) - if name in _PREDICATE_FIELDS and value is not None: - for v in value: - # check that the values are valid - if not scheme.is_valid_matcher(v.split(';')[0]): - logger.warning( - '%r: %r is not valid (field %r)', - project_name, v, name) - # FIXME this rejects UNKNOWN, is that right? - elif name in _VERSIONS_FIELDS and value is not None: - if not scheme.is_valid_constraint_list(value): - logger.warning('%r: %r is not a valid version (field %r)', - project_name, value, name) - elif name in _VERSION_FIELDS and value is not None: - if not scheme.is_valid_version(value): - logger.warning('%r: %r is not a valid version (field %r)', - project_name, value, name) - - if name in _UNICODEFIELDS: - if name == 'Description': - value = self._remove_line_prefix(value) - - self._fields[name] = value - - def get(self, name, default=_MISSING): - """Get a metadata field.""" - name = self._convert_name(name) - if name not in self._fields: - if default is _MISSING: - default = self._default_value(name) - return default - if name in _UNICODEFIELDS: - value = self._fields[name] - return value - elif name in _LISTFIELDS: - value = self._fields[name] - if value is None: - return [] - res = [] - for val in value: - if name not in _LISTTUPLEFIELDS: - res.append(val) - else: - # That's for Project-URL - res.append((val[0], val[1])) - return res - - elif name in _ELEMENTSFIELD: - value = self._fields[name] - if isinstance(value, string_types): - return value.split(',') - return self._fields[name] - - def check(self, strict=False): - """Check if the metadata is compliant. If strict is True then raise if - no Name or Version are provided""" - self.set_metadata_version() - - # XXX should check the versions (if the file was loaded) - missing, warnings = [], [] - - for attr in ('Name', 'Version'): # required by PEP 345 - if attr not in self: - missing.append(attr) - - if strict and missing != []: - msg = 'missing required metadata: %s' % ', '.join(missing) - raise MetadataMissingError(msg) - - for attr in ('Home-page', 'Author'): - if attr not in self: - missing.append(attr) - - # checking metadata 1.2 (XXX needs to check 1.1, 1.0) - if self['Metadata-Version'] != '1.2': - return missing, warnings - - scheme = get_scheme(self.scheme) - - def are_valid_constraints(value): - for v in value: - if not scheme.is_valid_matcher(v.split(';')[0]): - return False - return True - - for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints), - (_VERSIONS_FIELDS, - scheme.is_valid_constraint_list), - (_VERSION_FIELDS, - scheme.is_valid_version)): - for field in fields: - value = self.get(field, None) - if value is not None and not controller(value): - warnings.append('Wrong value for %r: %s' % (field, value)) - - return missing, warnings - - def todict(self, skip_missing=False): - """Return fields as a dict. - - Field names will be converted to use the underscore-lowercase style - instead of hyphen-mixed case (i.e. home_page instead of Home-page). - """ - self.set_metadata_version() - - mapping_1_0 = ( - ('metadata_version', 'Metadata-Version'), - ('name', 'Name'), - ('version', 'Version'), - ('summary', 'Summary'), - ('home_page', 'Home-page'), - ('author', 'Author'), - ('author_email', 'Author-email'), - ('license', 'License'), - ('description', 'Description'), - ('keywords', 'Keywords'), - ('platform', 'Platform'), - ('classifier', 'Classifier'), - ('download_url', 'Download-URL'), - ) - - data = {} - for key, field_name in mapping_1_0: - if not skip_missing or field_name in self._fields: - data[key] = self[field_name] - - if self['Metadata-Version'] == '1.2': - mapping_1_2 = ( - ('requires_dist', 'Requires-Dist'), - ('requires_python', 'Requires-Python'), - ('requires_external', 'Requires-External'), - ('provides_dist', 'Provides-Dist'), - ('obsoletes_dist', 'Obsoletes-Dist'), - ('project_url', 'Project-URL'), - ('maintainer', 'Maintainer'), - ('maintainer_email', 'Maintainer-email'), - ) - for key, field_name in mapping_1_2: - if not skip_missing or field_name in self._fields: - if key != 'project_url': - data[key] = self[field_name] - else: - data[key] = [','.join(u) for u in self[field_name]] - - elif self['Metadata-Version'] == '1.1': - mapping_1_1 = ( - ('provides', 'Provides'), - ('requires', 'Requires'), - ('obsoletes', 'Obsoletes'), - ) - for key, field_name in mapping_1_1: - if not skip_missing or field_name in self._fields: - data[key] = self[field_name] - - return data - - def add_requirements(self, requirements): - if self['Metadata-Version'] == '1.1': - # we can't have 1.1 metadata *and* Setuptools requires - for field in ('Obsoletes', 'Requires', 'Provides'): - if field in self: - del self[field] - self['Requires-Dist'] += requirements - - # Mapping API - # TODO could add iter* variants - - def keys(self): - return list(_version2fieldlist(self['Metadata-Version'])) - - def __iter__(self): - for key in self.keys(): - yield key - - def values(self): - return [self[key] for key in self.keys()] - - def items(self): - return [(key, self[key]) for key in self.keys()] - - def __repr__(self): - return '<%s %s %s>' % (self.__class__.__name__, self.name, - self.version) - - -METADATA_FILENAME = 'pydist.json' - - -class Metadata(object): - """ - The metadata of a release. This implementation uses 2.0 (JSON) - metadata where possible. If not possible, it wraps a LegacyMetadata - instance which handles the key-value metadata format. - """ - - METADATA_VERSION_MATCHER = re.compile('^\d+(\.\d+)*$') - - NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) - - VERSION_MATCHER = PEP426_VERSION_RE - - SUMMARY_MATCHER = re.compile('.{1,2047}') - - METADATA_VERSION = '2.0' - - GENERATOR = 'distlib (%s)' % __version__ - - MANDATORY_KEYS = { - 'name': (), - 'version': (), - 'summary': ('legacy',), - } - - INDEX_KEYS = ('name version license summary description author ' - 'author_email keywords platform home_page classifiers ' - 'download_url') - - DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' - 'dev_requires provides meta_requires obsoleted_by ' - 'supports_environments') - - SYNTAX_VALIDATORS = { - 'metadata_version': (METADATA_VERSION_MATCHER, ()), - 'name': (NAME_MATCHER, ('legacy',)), - 'version': (VERSION_MATCHER, ('legacy',)), - 'summary': (SUMMARY_MATCHER, ('legacy',)), - } - - __slots__ = ('_legacy', '_data', 'scheme') - - def __init__(self, path=None, fileobj=None, mapping=None, - scheme='default'): - if [path, fileobj, mapping].count(None) < 2: - raise TypeError('path, fileobj and mapping are exclusive') - self._legacy = None - self._data = None - self.scheme = scheme - #import pdb; pdb.set_trace() - if mapping is not None: - try: - self._validate_mapping(mapping, scheme) - self._data = mapping - except MetadataUnrecognizedVersionError: - self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) - self.validate() - else: - data = None - if path: - with open(path, 'rb') as f: - data = f.read() - elif fileobj: - data = fileobj.read() - if data is None: - # Initialised with no args - to be added - self._data = { - 'metadata_version': self.METADATA_VERSION, - 'generator': self.GENERATOR, - } - else: - if not isinstance(data, text_type): - data = data.decode('utf-8') - try: - self._data = json.loads(data) - self._validate_mapping(self._data, scheme) - except ValueError: - # Note: MetadataUnrecognizedVersionError does not - # inherit from ValueError (it's a DistlibException, - # which should not inherit from ValueError). - # The ValueError comes from the json.load - if that - # succeeds and we get a validation error, we want - # that to propagate - self._legacy = LegacyMetadata(fileobj=StringIO(data), - scheme=scheme) - self.validate() - - common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) - - none_list = (None, list) - none_dict = (None, dict) - - mapped_keys = { - 'run_requires': ('Requires-Dist', list), - 'build_requires': ('Setup-Requires-Dist', list), - 'dev_requires': none_list, - 'test_requires': none_list, - 'meta_requires': none_list, - 'extras': ('Provides-Extra', list), - 'modules': none_list, - 'namespaces': none_list, - 'exports': none_dict, - 'commands': none_dict, - 'classifiers': ('Classifier', list), - 'source_url': ('Download-URL', None), - 'metadata_version': ('Metadata-Version', None), - } - - del none_list, none_dict - - def __getattribute__(self, key): - common = object.__getattribute__(self, 'common_keys') - mapped = object.__getattribute__(self, 'mapped_keys') - if key in mapped: - lk, maker = mapped[key] - if self._legacy: - if lk is None: - result = None if maker is None else maker() - else: - result = self._legacy.get(lk) - else: - value = None if maker is None else maker() - result = self._data.get(key, value) - elif key not in common: - result = object.__getattribute__(self, key) - elif self._legacy: - result = self._legacy.get(key) - else: - result = self._data.get(key) - return result - - def _validate_value(self, key, value, scheme=None): - if key in self.SYNTAX_VALIDATORS: - pattern, exclusions = self.SYNTAX_VALIDATORS[key] - if (scheme or self.scheme) not in exclusions: - m = pattern.match(value) - if not m: - raise MetadataInvalidError('%r is an invalid value for ' - 'the %r property' % (value, - key)) - - def __setattr__(self, key, value): - self._validate_value(key, value) - common = object.__getattribute__(self, 'common_keys') - mapped = object.__getattribute__(self, 'mapped_keys') - if key in mapped: - lk, _ = mapped[key] - if self._legacy: - if lk is None: - raise NotImplementedError - self._legacy[lk] = value - else: - self._data[key] = value - elif key not in common: - object.__setattr__(self, key, value) - else: - if key == 'keywords': - if isinstance(value, string_types): - value = value.strip() - if value: - value = value.split() - else: - value = [] - if self._legacy: - self._legacy[key] = value - else: - self._data[key] = value - - @property - def name_and_version(self): - return _get_name_and_version(self.name, self.version, True) - - @property - def provides(self): - if self._legacy: - result = self._legacy['Provides-Dist'] - else: - result = self._data.setdefault('provides', []) - s = '%s (%s)' % (self.name, self.version) - if s not in result: - result.append(s) - return result - - @provides.setter - def provides(self, value): - if self._legacy: - self._legacy['Provides-Dist'] = value - else: - self._data['provides'] = value - - def get_requirements(self, reqts, extras=None, env=None): - """ - Base method to get dependencies, given a set of extras - to satisfy and an optional environment context. - :param reqts: A list of sometimes-wanted dependencies, - perhaps dependent on extras and environment. - :param extras: A list of optional components being requested. - :param env: An optional environment for marker evaluation. - """ - if self._legacy: - result = reqts - else: - result = [] - extras = get_extras(extras or [], self.extras) - for d in reqts: - if 'extra' not in d and 'environment' not in d: - # unconditional - include = True - else: - if 'extra' not in d: - # Not extra-dependent - only environment-dependent - include = True - else: - include = d.get('extra') in extras - if include: - # Not excluded because of extras, check environment - marker = d.get('environment') - if marker: - include = interpret(marker, env) - if include: - result.extend(d['requires']) - for key in ('build', 'dev', 'test'): - e = ':%s:' % key - if e in extras: - extras.remove(e) - # A recursive call, but it should terminate since 'test' - # has been removed from the extras - reqts = self._data.get('%s_requires' % key, []) - result.extend(self.get_requirements(reqts, extras=extras, - env=env)) - return result - - @property - def dictionary(self): - if self._legacy: - return self._from_legacy() - return self._data - - @property - def dependencies(self): - if self._legacy: - raise NotImplementedError - else: - return extract_by_key(self._data, self.DEPENDENCY_KEYS) - - @dependencies.setter - def dependencies(self, value): - if self._legacy: - raise NotImplementedError - else: - self._data.update(value) - - def _validate_mapping(self, mapping, scheme): - if mapping.get('metadata_version') != self.METADATA_VERSION: - raise MetadataUnrecognizedVersionError() - missing = [] - for key, exclusions in self.MANDATORY_KEYS.items(): - if key not in mapping: - if scheme not in exclusions: - missing.append(key) - if missing: - msg = 'Missing metadata items: %s' % ', '.join(missing) - raise MetadataMissingError(msg) - for k, v in mapping.items(): - self._validate_value(k, v, scheme) - - def validate(self): - if self._legacy: - missing, warnings = self._legacy.check(True) - if missing or warnings: - logger.warning('Metadata: missing: %s, warnings: %s', - missing, warnings) - else: - self._validate_mapping(self._data, self.scheme) - - def todict(self): - if self._legacy: - return self._legacy.todict(True) - else: - result = extract_by_key(self._data, self.INDEX_KEYS) - return result - - def _from_legacy(self): - assert self._legacy and not self._data - result = { - 'metadata_version': self.METADATA_VERSION, - 'generator': self.GENERATOR, - } - lmd = self._legacy.todict(True) # skip missing ones - for k in ('name', 'version', 'license', 'summary', 'description', - 'classifier'): - if k in lmd: - if k == 'classifier': - nk = 'classifiers' - else: - nk = k - result[nk] = lmd[k] - kw = lmd.get('Keywords', []) - if kw == ['']: - kw = [] - result['keywords'] = kw - keys = (('requires_dist', 'run_requires'), - ('setup_requires_dist', 'build_requires')) - for ok, nk in keys: - if ok in lmd and lmd[ok]: - result[nk] = [{'requires': lmd[ok]}] - result['provides'] = self.provides - author = {} - maintainer = {} - return result - - LEGACY_MAPPING = { - 'name': 'Name', - 'version': 'Version', - 'license': 'License', - 'summary': 'Summary', - 'description': 'Description', - 'classifiers': 'Classifier', - } - - def _to_legacy(self): - def process_entries(entries): - reqts = set() - for e in entries: - extra = e.get('extra') - env = e.get('environment') - rlist = e['requires'] - for r in rlist: - if not env and not extra: - reqts.add(r) - else: - marker = '' - if extra: - marker = 'extra == "%s"' % extra - if env: - if marker: - marker = '(%s) and %s' % (env, marker) - else: - marker = env - reqts.add(';'.join((r, marker))) - return reqts - - assert self._data and not self._legacy - result = LegacyMetadata() - nmd = self._data - for nk, ok in self.LEGACY_MAPPING.items(): - if nk in nmd: - result[ok] = nmd[nk] - r1 = process_entries(self.run_requires + self.meta_requires) - r2 = process_entries(self.build_requires + self.dev_requires) - if self.extras: - result['Provides-Extra'] = sorted(self.extras) - result['Requires-Dist'] = sorted(r1) - result['Setup-Requires-Dist'] = sorted(r2) - # TODO: other fields such as contacts - return result - - def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): - if [path, fileobj].count(None) != 1: - raise ValueError('Exactly one of path and fileobj is needed') - self.validate() - if legacy: - if self._legacy: - legacy_md = self._legacy - else: - legacy_md = self._to_legacy() - if path: - legacy_md.write(path, skip_unknown=skip_unknown) - else: - legacy_md.write_file(fileobj, skip_unknown=skip_unknown) - else: - if self._legacy: - d = self._from_legacy() - else: - d = self._data - if fileobj: - json.dump(d, fileobj, ensure_ascii=True, indent=2, - sort_keys=True) - else: - with codecs.open(path, 'w', 'utf-8') as f: - json.dump(d, f, ensure_ascii=True, indent=2, - sort_keys=True) - - def add_requirements(self, requirements): - if self._legacy: - self._legacy.add_requirements(requirements) - else: - self._data.setdefault('run_requires', []).extend(requirements) - - def __repr__(self): - name = self.name or '(no name)' - version = self.version or 'no version' - return '<%s %s %s (%s)>' % (self.__class__.__name__, - self.metadata_version, name, version) diff --git a/awx/lib/site-packages/pip/_vendor/distlib/resources.py b/awx/lib/site-packages/pip/_vendor/distlib/resources.py deleted file mode 100644 index 7c2673720b..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/resources.py +++ /dev/null @@ -1,351 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -from __future__ import unicode_literals - -import bisect -import io -import logging -import os -import pkgutil -import shutil -import sys -import types -import zipimport - -from . import DistlibException -from .util import cached_property, get_cache_base, path_to_cache_dir - -logger = logging.getLogger(__name__) - - -class Cache(object): - """ - A class implementing a cache for resources that need to live in the file system - e.g. shared libraries. - """ - - def __init__(self, base=None): - """ - Initialise an instance. - - :param base: The base directory where the cache should be located. If - not specified, this will be the ``resource-cache`` - directory under whatever :func:`get_cache_base` returns. - """ - if base is None: - # Use native string to avoid issues on 2.x: see Python #20140. - base = os.path.join(get_cache_base(), str('resource-cache')) - # we use 'isdir' instead of 'exists', because we want to - # fail if there's a file with that name - if not os.path.isdir(base): - os.makedirs(base) - self.base = os.path.abspath(os.path.normpath(base)) - - def prefix_to_dir(self, prefix): - """ - Converts a resource prefix to a directory name in the cache. - """ - return path_to_cache_dir(prefix) - - def is_stale(self, resource, path): - """ - Is the cache stale for the given resource? - - :param resource: The :class:`Resource` being cached. - :param path: The path of the resource in the cache. - :return: True if the cache is stale. - """ - # Cache invalidation is a hard problem :-) - return True - - def get(self, resource): - """ - Get a resource into the cache, - - :param resource: A :class:`Resource` instance. - :return: The pathname of the resource in the cache. - """ - prefix, path = resource.finder.get_cache_info(resource) - if prefix is None: - result = path - else: - result = os.path.join(self.base, self.prefix_to_dir(prefix), path) - dirname = os.path.dirname(result) - if not os.path.isdir(dirname): - os.makedirs(dirname) - if not os.path.exists(result): - stale = True - else: - stale = self.is_stale(resource, path) - if stale: - # write the bytes of the resource to the cache location - with open(result, 'wb') as f: - f.write(resource.bytes) - return result - - def clear(self): - """ - Clear the cache. - """ - not_removed = [] - for fn in os.listdir(self.base): - fn = os.path.join(self.base, fn) - try: - if os.path.islink(fn) or os.path.isfile(fn): - os.remove(fn) - elif os.path.isdir(fn): - shutil.rmtree(fn) - except Exception: - not_removed.append(fn) - return not_removed - -cache = Cache() - - -class ResourceBase(object): - def __init__(self, finder, name): - self.finder = finder - self.name = name - - -class Resource(ResourceBase): - """ - A class representing an in-package resource, such as a data file. This is - not normally instantiated by user code, but rather by a - :class:`ResourceFinder` which manages the resource. - """ - is_container = False # Backwards compatibility - - def as_stream(self): - """ - Get the resource as a stream. - - This is not a property to make it obvious that it returns a new stream - each time. - """ - return self.finder.get_stream(self) - - @cached_property - def file_path(self): - return cache.get(self) - - @cached_property - def bytes(self): - return self.finder.get_bytes(self) - - @cached_property - def size(self): - return self.finder.get_size(self) - - -class ResourceContainer(ResourceBase): - is_container = True # Backwards compatibility - - @cached_property - def resources(self): - return self.finder.get_resources(self) - - -class ResourceFinder(object): - """ - Resource finder for file system resources. - """ - def __init__(self, module): - self.module = module - self.loader = getattr(module, '__loader__', None) - self.base = os.path.dirname(getattr(module, '__file__', '')) - - def _adjust_path(self, path): - return os.path.realpath(path) - - def _make_path(self, resource_name): - parts = resource_name.split('/') - parts.insert(0, self.base) - result = os.path.join(*parts) - return self._adjust_path(result) - - def _find(self, path): - return os.path.exists(path) - - def get_cache_info(self, resource): - return None, resource.path - - def find(self, resource_name): - path = self._make_path(resource_name) - if not self._find(path): - result = None - else: - if self._is_directory(path): - result = ResourceContainer(self, resource_name) - else: - result = Resource(self, resource_name) - result.path = path - return result - - def get_stream(self, resource): - return open(resource.path, 'rb') - - def get_bytes(self, resource): - with open(resource.path, 'rb') as f: - return f.read() - - def get_size(self, resource): - return os.path.getsize(resource.path) - - def get_resources(self, resource): - def allowed(f): - return f != '__pycache__' and not f.endswith(('.pyc', '.pyo')) - return set([f for f in os.listdir(resource.path) if allowed(f)]) - - def is_container(self, resource): - return self._is_directory(resource.path) - - _is_directory = staticmethod(os.path.isdir) - - -class ZipResourceFinder(ResourceFinder): - """ - Resource finder for resources in .zip files. - """ - def __init__(self, module): - super(ZipResourceFinder, self).__init__(module) - archive = self.loader.archive - self.prefix_len = 1 + len(archive) - # PyPy doesn't have a _files attr on zipimporter, and you can't set one - if hasattr(self.loader, '_files'): - self._files = self.loader._files - else: - self._files = zipimport._zip_directory_cache[archive] - self.index = sorted(self._files) - - def _adjust_path(self, path): - return path - - def _find(self, path): - path = path[self.prefix_len:] - if path in self._files: - result = True - else: - if path and path[-1] != os.sep: - path = path + os.sep - i = bisect.bisect(self.index, path) - try: - result = self.index[i].startswith(path) - except IndexError: - result = False - if not result: - logger.debug('_find failed: %r %r', path, self.loader.prefix) - else: - logger.debug('_find worked: %r %r', path, self.loader.prefix) - return result - - def get_cache_info(self, resource): - prefix = self.loader.archive - path = resource.path[1 + len(prefix):] - return prefix, path - - def get_bytes(self, resource): - return self.loader.get_data(resource.path) - - def get_stream(self, resource): - return io.BytesIO(self.get_bytes(resource)) - - def get_size(self, resource): - path = resource.path[self.prefix_len:] - return self._files[path][3] - - def get_resources(self, resource): - path = resource.path[self.prefix_len:] - if path and path[-1] != os.sep: - path += os.sep - plen = len(path) - result = set() - i = bisect.bisect(self.index, path) - while i < len(self.index): - if not self.index[i].startswith(path): - break - s = self.index[i][plen:] - result.add(s.split(os.sep, 1)[0]) # only immediate children - i += 1 - return result - - def _is_directory(self, path): - path = path[self.prefix_len:] - if path and path[-1] != os.sep: - path += os.sep - i = bisect.bisect(self.index, path) - try: - result = self.index[i].startswith(path) - except IndexError: - result = False - return result - -_finder_registry = { - type(None): ResourceFinder, - zipimport.zipimporter: ZipResourceFinder -} - -try: - import _frozen_importlib - _finder_registry[_frozen_importlib.SourceFileLoader] = ResourceFinder - _finder_registry[_frozen_importlib.FileFinder] = ResourceFinder -except (ImportError, AttributeError): - pass - - -def register_finder(loader, finder_maker): - _finder_registry[type(loader)] = finder_maker - -_finder_cache = {} - - -def finder(package): - """ - Return a resource finder for a package. - :param package: The name of the package. - :return: A :class:`ResourceFinder` instance for the package. - """ - if package in _finder_cache: - result = _finder_cache[package] - else: - if package not in sys.modules: - __import__(package) - module = sys.modules[package] - path = getattr(module, '__path__', None) - if path is None: - raise DistlibException('You cannot get a finder for a module, ' - 'only for a package') - loader = getattr(module, '__loader__', None) - finder_maker = _finder_registry.get(type(loader)) - if finder_maker is None: - raise DistlibException('Unable to locate finder for %r' % package) - result = finder_maker(module) - _finder_cache[package] = result - return result - - -_dummy_module = types.ModuleType(str('__dummy__')) - - -def finder_for_path(path): - """ - Return a resource finder for a path, which should represent a container. - - :param path: The path. - :return: A :class:`ResourceFinder` instance for the path. - """ - result = None - # calls any path hooks, gets importer into cache - pkgutil.get_importer(path) - loader = sys.path_importer_cache.get(path) - finder = _finder_registry.get(type(loader)) - if finder: - module = _dummy_module - module.__file__ = os.path.join(path, '') - module.__loader__ = loader - result = finder(module) - return result diff --git a/awx/lib/site-packages/pip/_vendor/distlib/scripts.py b/awx/lib/site-packages/pip/_vendor/distlib/scripts.py deleted file mode 100644 index ba0e5202b5..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/scripts.py +++ /dev/null @@ -1,317 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -from io import BytesIO -import logging -import os -import re -import struct -import sys - -from .compat import sysconfig, fsencode, detect_encoding, ZipFile -from .resources import finder -from .util import (FileOperator, get_export_entry, convert_path, - get_executable, in_venv) - -logger = logging.getLogger(__name__) - -_DEFAULT_MANIFEST = ''' - - - - - - - - - - - - -'''.strip() - -# check if Python is called on the first line with this expression -FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') -SCRIPT_TEMPLATE = '''# -*- coding: utf-8 -*- -if __name__ == '__main__': - import sys, re - - def _resolve(module, func): - __import__(module) - mod = sys.modules[module] - parts = func.split('.') - result = getattr(mod, parts.pop(0)) - for p in parts: - result = getattr(result, p) - return result - - try: - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - - func = _resolve('%(module)s', '%(func)s') - rc = func() # None interpreted as 0 - except Exception as e: # only supporting Python >= 2.6 - sys.stderr.write('%%s\\n' %% e) - rc = 1 - sys.exit(rc) -''' - - -class ScriptMaker(object): - """ - A class to copy or create scripts from source scripts or callable - specifications. - """ - script_template = SCRIPT_TEMPLATE - - executable = None # for shebangs - - def __init__(self, source_dir, target_dir, add_launchers=True, - dry_run=False, fileop=None): - self.source_dir = source_dir - self.target_dir = target_dir - self.add_launchers = add_launchers - self.force = False - self.clobber = False - # It only makes sense to set mode bits on POSIX. - self.set_mode = (os.name == 'posix') - self.variants = set(('', 'X.Y')) - self._fileop = fileop or FileOperator(dry_run) - - def _get_alternate_executable(self, executable, options): - if options.get('gui', False) and os.name == 'nt': - dn, fn = os.path.split(executable) - fn = fn.replace('python', 'pythonw') - executable = os.path.join(dn, fn) - return executable - - def _get_shebang(self, encoding, post_interp=b'', options=None): - if self.executable: - executable = self.executable - elif not sysconfig.is_python_build(): - executable = get_executable() - elif in_venv(): - executable = os.path.join(sysconfig.get_path('scripts'), - 'python%s' % sysconfig.get_config_var('EXE')) - else: - executable = os.path.join( - sysconfig.get_config_var('BINDIR'), - 'python%s%s' % (sysconfig.get_config_var('VERSION'), - sysconfig.get_config_var('EXE'))) - if options: - executable = self._get_alternate_executable(executable, options) - - executable = fsencode(executable) - shebang = b'#!' + executable + post_interp + b'\n' - # Python parser starts to read a script using UTF-8 until - # it gets a #coding:xxx cookie. The shebang has to be the - # first line of a file, the #coding:xxx cookie cannot be - # written before. So the shebang has to be decodable from - # UTF-8. - try: - shebang.decode('utf-8') - except UnicodeDecodeError: - raise ValueError( - 'The shebang (%r) is not decodable from utf-8' % shebang) - # If the script is encoded to a custom encoding (use a - # #coding:xxx cookie), the shebang has to be decodable from - # the script encoding too. - if encoding != 'utf-8': - try: - shebang.decode(encoding) - except UnicodeDecodeError: - raise ValueError( - 'The shebang (%r) is not decodable ' - 'from the script encoding (%r)' % (shebang, encoding)) - return shebang - - def _get_script_text(self, entry): - return self.script_template % dict(module=entry.prefix, - func=entry.suffix) - - manifest = _DEFAULT_MANIFEST - - def get_manifest(self, exename): - base = os.path.basename(exename) - return self.manifest % base - - def _write_script(self, names, shebang, script_bytes, filenames, ext): - use_launcher = self.add_launchers and os.name == 'nt' - linesep = os.linesep.encode('utf-8') - if not use_launcher: - script_bytes = shebang + linesep + script_bytes - else: - if ext == 'py': - launcher = self._get_launcher('t') - else: - launcher = self._get_launcher('w') - stream = BytesIO() - with ZipFile(stream, 'w') as zf: - zf.writestr('__main__.py', script_bytes) - zip_data = stream.getvalue() - script_bytes = launcher + shebang + linesep + zip_data - for name in names: - outname = os.path.join(self.target_dir, name) - if use_launcher: - n, e = os.path.splitext(outname) - if e.startswith('.py'): - outname = n - outname = '%s.exe' % outname - try: - self._fileop.write_binary_file(outname, script_bytes) - except Exception: - # Failed writing an executable - it might be in use. - logger.warning('Failed to write executable - trying to ' - 'use .deleteme logic') - dfname = '%s.deleteme' % outname - if os.path.exists(dfname): - os.remove(dfname) # Not allowed to fail here - os.rename(outname, dfname) # nor here - self._fileop.write_binary_file(outname, script_bytes) - logger.debug('Able to replace executable using ' - '.deleteme logic') - try: - os.remove(dfname) - except Exception: - pass # still in use - ignore error - else: - if os.name == 'nt' and not outname.endswith('.' + ext): - outname = '%s.%s' % (outname, ext) - if os.path.exists(outname) and not self.clobber: - logger.warning('Skipping existing file %s', outname) - continue - self._fileop.write_binary_file(outname, script_bytes) - if self.set_mode: - self._fileop.set_executable_mode([outname]) - filenames.append(outname) - - def _make_script(self, entry, filenames, options=None): - shebang = self._get_shebang('utf-8', options=options) - script = self._get_script_text(entry).encode('utf-8') - name = entry.name - scriptnames = set() - if '' in self.variants: - scriptnames.add(name) - if 'X' in self.variants: - scriptnames.add('%s%s' % (name, sys.version[0])) - if 'X.Y' in self.variants: - scriptnames.add('%s-%s' % (name, sys.version[:3])) - if options and options.get('gui', False): - ext = 'pyw' - else: - ext = 'py' - self._write_script(scriptnames, shebang, script, filenames, ext) - - def _copy_script(self, script, filenames): - adjust = False - script = os.path.join(self.source_dir, convert_path(script)) - outname = os.path.join(self.target_dir, os.path.basename(script)) - if not self.force and not self._fileop.newer(script, outname): - logger.debug('not copying %s (up-to-date)', script) - return - - # Always open the file, but ignore failures in dry-run mode -- - # that way, we'll get accurate feedback if we can read the - # script. - try: - f = open(script, 'rb') - except IOError: - if not self.dry_run: - raise - f = None - else: - encoding, lines = detect_encoding(f.readline) - f.seek(0) - first_line = f.readline() - if not first_line: - logger.warning('%s: %s is an empty file (skipping)', - self.get_command_name(), script) - return - - match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) - if match: - adjust = True - post_interp = match.group(1) or b'' - - if not adjust: - if f: - f.close() - self._fileop.copy_file(script, outname) - if self.set_mode: - self._fileop.set_executable_mode([outname]) - filenames.append(outname) - else: - logger.info('copying and adjusting %s -> %s', script, - self.target_dir) - if not self._fileop.dry_run: - shebang = self._get_shebang(encoding, post_interp) - if b'pythonw' in first_line: - ext = 'pyw' - else: - ext = 'py' - n = os.path.basename(outname) - self._write_script([n], shebang, f.read(), filenames, ext) - if f: - f.close() - - @property - def dry_run(self): - return self._fileop.dry_run - - @dry_run.setter - def dry_run(self, value): - self._fileop.dry_run = value - - if os.name == 'nt': - # Executable launcher support. - # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ - - def _get_launcher(self, kind): - if struct.calcsize('P') == 8: # 64-bit - bits = '64' - else: - bits = '32' - name = '%s%s.exe' % (kind, bits) - # Issue 31: don't hardcode an absolute package name, but - # determine it relative to the current package - distlib_package = __name__.rsplit('.', 1)[0] - result = finder(distlib_package).find(name).bytes - return result - - # Public API follows - - def make(self, specification, options=None): - """ - Make a script. - - :param specification: The specification, which is either a valid export - entry specification (to make a script from a - callable) or a filename (to make a script by - copying from a source location). - :param options: A dictionary of options controlling script generation. - :return: A list of all absolute pathnames written to. - """ - filenames = [] - entry = get_export_entry(specification) - if entry is None: - self._copy_script(specification, filenames) - else: - self._make_script(entry, filenames, options=options) - return filenames - - def make_multiple(self, specifications, options=None): - """ - Take a list of specifications and make scripts from them, - :param specifications: A list of specifications. - :return: A list of all absolute pathnames written to, - """ - filenames = [] - for specification in specifications: - filenames.extend(self.make(specification, options)) - return filenames diff --git a/awx/lib/site-packages/pip/_vendor/distlib/t32.exe b/awx/lib/site-packages/pip/_vendor/distlib/t32.exe deleted file mode 100644 index 43f39f31e9..0000000000 Binary files a/awx/lib/site-packages/pip/_vendor/distlib/t32.exe and /dev/null differ diff --git a/awx/lib/site-packages/pip/_vendor/distlib/t64.exe b/awx/lib/site-packages/pip/_vendor/distlib/t64.exe deleted file mode 100644 index 73e2f40522..0000000000 Binary files a/awx/lib/site-packages/pip/_vendor/distlib/t64.exe and /dev/null differ diff --git a/awx/lib/site-packages/pip/_vendor/distlib/util.py b/awx/lib/site-packages/pip/_vendor/distlib/util.py deleted file mode 100644 index e64d078b6e..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/util.py +++ /dev/null @@ -1,1532 +0,0 @@ -# -# Copyright (C) 2012-2013 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -import codecs -from collections import deque -import contextlib -import csv -from glob import iglob as std_iglob -import io -import json -import logging -import os -import py_compile -import re -import shutil -import socket -import ssl -import subprocess -import sys -import tarfile -import tempfile -try: - import threading -except ImportError: - import dummy_threading as threading -import time - -from . import DistlibException -from .compat import (string_types, text_type, shutil, raw_input, StringIO, - cache_from_source, urlopen, httplib, xmlrpclib, splittype, - HTTPHandler, HTTPSHandler as BaseHTTPSHandler, - BaseConfigurator, valid_ident, Container, configparser, - URLError, match_hostname, CertificateError, ZipFile) - -logger = logging.getLogger(__name__) - -# -# Requirement parsing code for name + optional constraints + optional extras -# -# e.g. 'foo >= 1.2, < 2.0 [bar, baz]' -# -# The regex can seem a bit hairy, so we build it up out of smaller pieces -# which are manageable. -# - -COMMA = r'\s*,\s*' -COMMA_RE = re.compile(COMMA) - -IDENT = r'(\w|[.-])+' -EXTRA_IDENT = r'(\*|:(\*|\w+):|' + IDENT + ')' -VERSPEC = IDENT + r'\*?' - -RELOP = '([<>=!~]=)|[<>]' - -# -# The first relop is optional - if absent, will be taken as '~=' -# -BARE_CONSTRAINTS = ('(' + RELOP + r')?\s*(' + VERSPEC + ')(' + COMMA + '(' + - RELOP + r')\s*(' + VERSPEC + '))*') - -DIRECT_REF = '(from\s+(?P.*))' - -# -# Either the bare constraints or the bare constraints in parentheses -# -CONSTRAINTS = (r'\(\s*(?P' + BARE_CONSTRAINTS + '|' + DIRECT_REF + - r')\s*\)|(?P' + BARE_CONSTRAINTS + '\s*)') - -EXTRA_LIST = EXTRA_IDENT + '(' + COMMA + EXTRA_IDENT + ')*' -EXTRAS = r'\[\s*(?P' + EXTRA_LIST + r')?\s*\]' -REQUIREMENT = ('(?P' + IDENT + r')\s*(' + EXTRAS + r'\s*)?(\s*' + - CONSTRAINTS + ')?$') -REQUIREMENT_RE = re.compile(REQUIREMENT) - -# -# Used to scan through the constraints -# -RELOP_IDENT = '(?P' + RELOP + r')\s*(?P' + VERSPEC + ')' -RELOP_IDENT_RE = re.compile(RELOP_IDENT) - -def parse_requirement(s): - - def get_constraint(m): - d = m.groupdict() - return d['op'], d['vn'] - - result = None - m = REQUIREMENT_RE.match(s) - if m: - d = m.groupdict() - name = d['dn'] - cons = d['c1'] or d['c2'] - if not d['diref']: - url = None - else: - # direct reference - cons = None - url = d['diref'].strip() - if not cons: - cons = None - constr = '' - rs = d['dn'] - else: - if cons[0] not in '<>!=': - cons = '~=' + cons - iterator = RELOP_IDENT_RE.finditer(cons) - cons = [get_constraint(m) for m in iterator] - rs = '%s (%s)' % (name, ', '.join(['%s %s' % con for con in cons])) - if not d['ex']: - extras = None - else: - extras = COMMA_RE.split(d['ex']) - result = Container(name=name, constraints=cons, extras=extras, - requirement=rs, source=s, url=url) - return result - - -def get_resources_dests(resources_root, rules): - """Find destinations for resources files""" - - def get_rel_path(base, path): - # normalizes and returns a lstripped-/-separated path - base = base.replace(os.path.sep, '/') - path = path.replace(os.path.sep, '/') - assert path.startswith(base) - return path[len(base):].lstrip('/') - - - destinations = {} - for base, suffix, dest in rules: - prefix = os.path.join(resources_root, base) - for abs_base in iglob(prefix): - abs_glob = os.path.join(abs_base, suffix) - for abs_path in iglob(abs_glob): - resource_file = get_rel_path(resources_root, abs_path) - if dest is None: # remove the entry if it was here - destinations.pop(resource_file, None) - else: - rel_path = get_rel_path(abs_base, abs_path) - rel_dest = dest.replace(os.path.sep, '/').rstrip('/') - destinations[resource_file] = rel_dest + '/' + rel_path - return destinations - - -def in_venv(): - if hasattr(sys, 'real_prefix'): - # virtualenv venvs - result = True - else: - # PEP 405 venvs - result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix) - return result - - -def get_executable(): - if sys.platform == 'darwin' and ('__VENV_LAUNCHER__' - in os.environ): - result = os.environ['__VENV_LAUNCHER__'] - else: - result = sys.executable - return result - - -def proceed(prompt, allowed_chars, error_prompt=None, default=None): - p = prompt - while True: - s = raw_input(p) - p = prompt - if not s and default: - s = default - if s: - c = s[0].lower() - if c in allowed_chars: - break - if error_prompt: - p = '%c: %s\n%s' % (c, error_prompt, prompt) - return c - - -def extract_by_key(d, keys): - if isinstance(keys, string_types): - keys = keys.split() - result = {} - for key in keys: - if key in d: - result[key] = d[key] - return result - -def read_exports(stream): - if sys.version_info[0] >= 3: - # needs to be a text stream - stream = codecs.getreader('utf-8')(stream) - # Try to load as JSON, falling back on legacy format - data = stream.read() - stream = StringIO(data) - try: - data = json.load(stream) - result = data['exports'] - for group, entries in result.items(): - for k, v in entries.items(): - s = '%s = %s' % (k, v) - entry = get_export_entry(s) - assert entry is not None - entries[k] = entry - return result - except Exception: - stream.seek(0, 0) - cp = configparser.ConfigParser() - if hasattr(cp, 'read_file'): - cp.read_file(stream) - else: - cp.readfp(stream) - result = {} - for key in cp.sections(): - result[key] = entries = {} - for name, value in cp.items(key): - s = '%s = %s' % (name, value) - entry = get_export_entry(s) - assert entry is not None - #entry.dist = self - entries[name] = entry - return result - - -def write_exports(exports, stream): - if sys.version_info[0] >= 3: - # needs to be a text stream - stream = codecs.getwriter('utf-8')(stream) - cp = configparser.ConfigParser() - for k, v in exports.items(): - # TODO check k, v for valid values - cp.add_section(k) - for entry in v.values(): - if entry.suffix is None: - s = entry.prefix - else: - s = '%s:%s' % (entry.prefix, entry.suffix) - if entry.flags: - s = '%s [%s]' % (s, ', '.join(entry.flags)) - cp.set(k, entry.name, s) - cp.write(stream) - - -@contextlib.contextmanager -def tempdir(): - td = tempfile.mkdtemp() - try: - yield td - finally: - shutil.rmtree(td) - -@contextlib.contextmanager -def chdir(d): - cwd = os.getcwd() - try: - os.chdir(d) - yield - finally: - os.chdir(cwd) - - -@contextlib.contextmanager -def socket_timeout(seconds=15): - cto = socket.getdefaulttimeout() - try: - socket.setdefaulttimeout(seconds) - yield - finally: - socket.setdefaulttimeout(cto) - - -class cached_property(object): - def __init__(self, func): - self.func = func - #for attr in ('__name__', '__module__', '__doc__'): - # setattr(self, attr, getattr(func, attr, None)) - - def __get__(self, obj, cls=None): - if obj is None: - return self - value = self.func(obj) - object.__setattr__(obj, self.func.__name__, value) - #obj.__dict__[self.func.__name__] = value = self.func(obj) - return value - -def convert_path(pathname): - """Return 'pathname' as a name that will work on the native filesystem. - - The path is split on '/' and put back together again using the current - directory separator. Needed because filenames in the setup script are - always supplied in Unix style, and have to be converted to the local - convention before we can actually use them in the filesystem. Raises - ValueError on non-Unix-ish systems if 'pathname' either starts or - ends with a slash. - """ - if os.sep == '/': - return pathname - if not pathname: - return pathname - if pathname[0] == '/': - raise ValueError("path '%s' cannot be absolute" % pathname) - if pathname[-1] == '/': - raise ValueError("path '%s' cannot end with '/'" % pathname) - - paths = pathname.split('/') - while os.curdir in paths: - paths.remove(os.curdir) - if not paths: - return os.curdir - return os.path.join(*paths) - - -class FileOperator(object): - def __init__(self, dry_run=False): - self.dry_run = dry_run - self.ensured = set() - self._init_record() - - def _init_record(self): - self.record = False - self.files_written = set() - self.dirs_created = set() - - def record_as_written(self, path): - if self.record: - self.files_written.add(path) - - def newer(self, source, target): - """Tell if the target is newer than the source. - - Returns true if 'source' exists and is more recently modified than - 'target', or if 'source' exists and 'target' doesn't. - - Returns false if both exist and 'target' is the same age or younger - than 'source'. Raise PackagingFileError if 'source' does not exist. - - Note that this test is not very accurate: files created in the same - second will have the same "age". - """ - if not os.path.exists(source): - raise DistlibException("file '%r' does not exist" % - os.path.abspath(source)) - if not os.path.exists(target): - return True - - return os.stat(source).st_mtime > os.stat(target).st_mtime - - def copy_file(self, infile, outfile, check=True): - """Copy a file respecting dry-run and force flags. - """ - self.ensure_dir(os.path.dirname(outfile)) - logger.info('Copying %s to %s', infile, outfile) - if not self.dry_run: - msg = None - if check: - if os.path.islink(outfile): - msg = '%s is a symlink' % outfile - elif os.path.exists(outfile) and not os.path.isfile(outfile): - msg = '%s is a non-regular file' % outfile - if msg: - raise ValueError(msg + ' which would be overwritten') - shutil.copyfile(infile, outfile) - self.record_as_written(outfile) - - def copy_stream(self, instream, outfile, encoding=None): - assert not os.path.isdir(outfile) - self.ensure_dir(os.path.dirname(outfile)) - logger.info('Copying stream %s to %s', instream, outfile) - if not self.dry_run: - if encoding is None: - outstream = open(outfile, 'wb') - else: - outstream = codecs.open(outfile, 'w', encoding=encoding) - try: - shutil.copyfileobj(instream, outstream) - finally: - outstream.close() - self.record_as_written(outfile) - - def write_binary_file(self, path, data): - self.ensure_dir(os.path.dirname(path)) - if not self.dry_run: - with open(path, 'wb') as f: - f.write(data) - self.record_as_written(path) - - def write_text_file(self, path, data, encoding): - self.ensure_dir(os.path.dirname(path)) - if not self.dry_run: - with open(path, 'wb') as f: - f.write(data.encode(encoding)) - self.record_as_written(path) - - def set_mode(self, bits, mask, files): - if os.name == 'posix': - # Set the executable bits (owner, group, and world) on - # all the files specified. - for f in files: - if self.dry_run: - logger.info("changing mode of %s", f) - else: - mode = (os.stat(f).st_mode | bits) & mask - logger.info("changing mode of %s to %o", f, mode) - os.chmod(f, mode) - - set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f) - - def ensure_dir(self, path): - path = os.path.abspath(path) - if path not in self.ensured and not os.path.exists(path): - self.ensured.add(path) - d, f = os.path.split(path) - self.ensure_dir(d) - logger.info('Creating %s' % path) - if not self.dry_run: - os.mkdir(path) - if self.record: - self.dirs_created.add(path) - - def byte_compile(self, path, optimize=False, force=False, prefix=None): - dpath = cache_from_source(path, not optimize) - logger.info('Byte-compiling %s to %s', path, dpath) - if not self.dry_run: - if force or self.newer(path, dpath): - if not prefix: - diagpath = None - else: - assert path.startswith(prefix) - diagpath = path[len(prefix):] - py_compile.compile(path, dpath, diagpath, True) # raise error - self.record_as_written(dpath) - return dpath - - def ensure_removed(self, path): - if os.path.exists(path): - if os.path.isdir(path) and not os.path.islink(path): - logger.debug('Removing directory tree at %s', path) - if not self.dry_run: - shutil.rmtree(path) - if self.record: - if path in self.dirs_created: - self.dirs_created.remove(path) - else: - if os.path.islink(path): - s = 'link' - else: - s = 'file' - logger.debug('Removing %s %s', s, path) - if not self.dry_run: - os.remove(path) - if self.record: - if path in self.files_written: - self.files_written.remove(path) - - def is_writable(self, path): - result = False - while not result: - if os.path.exists(path): - result = os.access(path, os.W_OK) - break - parent = os.path.dirname(path) - if parent == path: - break - path = parent - return result - - def commit(self): - """ - Commit recorded changes, turn off recording, return - changes. - """ - assert self.record - result = self.files_written, self.dirs_created - self._init_record() - return result - - def rollback(self): - if not self.dry_run: - for f in list(self.files_written): - if os.path.exists(f): - os.remove(f) - # dirs should all be empty now, except perhaps for - # __pycache__ subdirs - # reverse so that subdirs appear before their parents - dirs = sorted(self.dirs_created, reverse=True) - for d in dirs: - flist = os.listdir(d) - if flist: - assert flist == ['__pycache__'] - sd = os.path.join(d, flist[0]) - os.rmdir(sd) - os.rmdir(d) # should fail if non-empty - self._init_record() - -def resolve(module_name, dotted_path): - if module_name in sys.modules: - mod = sys.modules[module_name] - else: - mod = __import__(module_name) - if dotted_path is None: - result = mod - else: - parts = dotted_path.split('.') - result = getattr(mod, parts.pop(0)) - for p in parts: - result = getattr(result, p) - return result - - -class ExportEntry(object): - def __init__(self, name, prefix, suffix, flags): - self.name = name - self.prefix = prefix - self.suffix = suffix - self.flags = flags - - @cached_property - def value(self): - return resolve(self.prefix, self.suffix) - - def __repr__(self): - return '' % (self.name, self.prefix, - self.suffix, self.flags) - - def __eq__(self, other): - if not isinstance(other, ExportEntry): - result = False - else: - result = (self.name == other.name and - self.prefix == other.prefix and - self.suffix == other.suffix and - self.flags == other.flags) - return result - - __hash__ = object.__hash__ - - -ENTRY_RE = re.compile(r'''(?P(\w|[-.])+) - \s*=\s*(?P(\w+)([:\.]\w+)*) - \s*(\[\s*(?P\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? - ''', re.VERBOSE) - - -def get_export_entry(specification): - m = ENTRY_RE.search(specification) - if not m: - result = None - if '[' in specification or ']' in specification: - raise DistlibException('Invalid specification ' - '%r' % specification) - else: - d = m.groupdict() - name = d['name'] - path = d['callable'] - colons = path.count(':') - if colons == 0: - prefix, suffix = path, None - else: - if colons != 1: - raise DistlibException('Invalid specification ' - '%r' % specification) - prefix, suffix = path.split(':') - flags = d['flags'] - if flags is None: - if '[' in specification or ']' in specification: - raise DistlibException('Invalid specification ' - '%r' % specification) - flags = [] - else: - flags = [f.strip() for f in flags.split(',')] - result = ExportEntry(name, prefix, suffix, flags) - return result - - -def get_cache_base(suffix=None): - """ - Return the default base location for distlib caches. If the directory does - not exist, it is created. Use the suffix provided for the base directory, - and default to '.distlib' if it isn't provided. - - On Windows, if LOCALAPPDATA is defined in the environment, then it is - assumed to be a directory, and will be the parent directory of the result. - On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home - directory - using os.expanduser('~') - will be the parent directory of - the result. - - The result is just the directory '.distlib' in the parent directory as - determined above, or with the name specified with ``suffix``. - """ - if suffix is None: - suffix = '.distlib' - if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: - result = os.path.expandvars('$localappdata') - else: - # Assume posix, or old Windows - result = os.path.expanduser('~') - result = os.path.join(result, suffix) - # we use 'isdir' instead of 'exists', because we want to - # fail if there's a file with that name - if os.path.isdir(result): - usable = os.access(result, os.W_OK) - if not usable: - logger.warning('Directory exists but is not writable: %s', result) - else: - try: - os.makedirs(result) - usable = True - except OSError: - logger.warning('Unable to create %s', result, exc_info=True) - usable = False - if not usable: - result = tempfile.mkdtemp() - logger.warning('Default location unusable, using %s', result) - return result - - -def path_to_cache_dir(path): - """ - Convert an absolute path to a directory name for use in a cache. - - The algorithm used is: - - #. On Windows, any ``':'`` in the drive is replaced with ``'---'``. - #. Any occurrence of ``os.sep`` is replaced with ``'--'``. - #. ``'.cache'`` is appended. - """ - d, p = os.path.splitdrive(os.path.abspath(path)) - if d: - d = d.replace(':', '---') - p = p.replace(os.sep, '--') - return d + p + '.cache' - - -def ensure_slash(s): - if not s.endswith('/'): - return s + '/' - return s - - -def parse_credentials(netloc): - username = password = None - if '@' in netloc: - prefix, netloc = netloc.split('@', 1) - if ':' not in prefix: - username = prefix - else: - username, password = prefix.split(':', 1) - return username, password, netloc - - -def get_process_umask(): - result = os.umask(0o22) - os.umask(result) - return result - -def is_string_sequence(seq): - result = True - i = None - for i, s in enumerate(seq): - if not isinstance(s, string_types): - result = False - break - assert i is not None - return result - -PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' - '([a-z0-9_.+-]+)', re.I) -PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') - - -def split_filename(filename, project_name=None): - """ - Extract name, version, python version from a filename (no extension) - - Return name, version, pyver or None - """ - result = None - pyver = None - m = PYTHON_VERSION.search(filename) - if m: - pyver = m.group(1) - filename = filename[:m.start()] - if project_name and len(filename) > len(project_name) + 1: - m = re.match(re.escape(project_name) + r'\b', filename) - if m: - n = m.end() - result = filename[:n], filename[n + 1:], pyver - if result is None: - m = PROJECT_NAME_AND_VERSION.match(filename) - if m: - result = m.group(1), m.group(3), pyver - return result - -# Allow spaces in name because of legacy dists like "Twisted Core" -NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*' - r'\(\s*(?P[^\s)]+)\)$') - -def parse_name_and_version(p): - """ - A utility method used to get name and version from a string. - - From e.g. a Provides-Dist value. - - :param p: A value in a form 'foo (1.0)' - :return: The name and version as a tuple. - """ - m = NAME_VERSION_RE.match(p) - if not m: - raise DistlibException('Ill-formed name/version string: \'%s\'' % p) - d = m.groupdict() - return d['name'].strip().lower(), d['ver'] - -def get_extras(requested, available): - result = set() - requested = set(requested or []) - available = set(available or []) - if '*' in requested: - requested.remove('*') - result |= available - for r in requested: - if r == '-': - result.add(r) - elif r.startswith('-'): - unwanted = r[1:] - if unwanted not in available: - logger.warning('undeclared extra: %s' % unwanted) - if unwanted in result: - result.remove(unwanted) - else: - if r not in available: - logger.warning('undeclared extra: %s' % r) - result.add(r) - return result -# -# Extended metadata functionality -# - -def _get_external_data(url): - result = {} - try: - # urlopen might fail if it runs into redirections, - # because of Python issue #13696. Fixed in locators - # using a custom redirect handler. - resp = urlopen(url) - headers = resp.info() - if headers.get('Content-Type') != 'application/json': - logger.debug('Unexpected response for JSON request') - else: - reader = codecs.getreader('utf-8')(resp) - #data = reader.read().decode('utf-8') - #result = json.loads(data) - result = json.load(reader) - except Exception as e: - logger.exception('Failed to get external data for %s: %s', url, e) - return result - - -def get_project_data(name): - url = ('https://www.red-dove.com/pypi/projects/' - '%s/%s/project.json' % (name[0].upper(), name)) - result = _get_external_data(url) - return result - -def get_package_data(name, version): - url = ('https://www.red-dove.com/pypi/projects/' - '%s/%s/package-%s.json' % (name[0].upper(), name, version)) - return _get_external_data(url) - - -class EventMixin(object): - """ - A very simple publish/subscribe system. - """ - def __init__(self): - self._subscribers = {} - - def add(self, event, subscriber, append=True): - """ - Add a subscriber for an event. - - :param event: The name of an event. - :param subscriber: The subscriber to be added (and called when the - event is published). - :param append: Whether to append or prepend the subscriber to an - existing subscriber list for the event. - """ - subs = self._subscribers - if event not in subs: - subs[event] = deque([subscriber]) - else: - sq = subs[event] - if append: - sq.append(subscriber) - else: - sq.appendleft(subscriber) - - def remove(self, event, subscriber): - """ - Remove a subscriber for an event. - - :param event: The name of an event. - :param subscriber: The subscriber to be removed. - """ - subs = self._subscribers - if event not in subs: - raise ValueError('No subscribers: %r' % event) - subs[event].remove(subscriber) - - def get_subscribers(self, event): - """ - Return an iterator for the subscribers for an event. - :param event: The event to return subscribers for. - """ - return iter(self._subscribers.get(event, ())) - - def publish(self, event, *args, **kwargs): - """ - Publish a event and return a list of values returned by its - subscribers. - - :param event: The event to publish. - :param args: The positional arguments to pass to the event's - subscribers. - :param kwargs: The keyword arguments to pass to the event's - subscribers. - """ - result = [] - for subscriber in self.get_subscribers(event): - try: - value = subscriber(event, *args, **kwargs) - except Exception: - logger.exception('Exception during event publication') - value = None - result.append(value) - logger.debug('publish %s: args = %s, kwargs = %s, result = %s', - event, args, kwargs, result) - return result - -# -# Simple sequencing -# -class Sequencer(object): - def __init__(self): - self._preds = {} - self._succs = {} - self._nodes = set() # nodes with no preds/succs - - def add_node(self, node): - self._nodes.add(node) - - def remove_node(self, node, edges=False): - if node in self._nodes: - self._nodes.remove(node) - if edges: - for p in set(self._preds.get(node, ())): - self.remove(p, node) - for s in set(self._succs.get(node, ())): - self.remove(node, s) - # Remove empties - for k, v in list(self._preds.items()): - if not v: - del self._preds[k] - for k, v in list(self._succs.items()): - if not v: - del self._succs[k] - - def add(self, pred, succ): - assert pred != succ - self._preds.setdefault(succ, set()).add(pred) - self._succs.setdefault(pred, set()).add(succ) - - def remove(self, pred, succ): - assert pred != succ - try: - preds = self._preds[succ] - succs = self._succs[pred] - except KeyError: - raise ValueError('%r not a successor of anything' % succ) - try: - preds.remove(pred) - succs.remove(succ) - except KeyError: - raise ValueError('%r not a successor of %r' % (succ, pred)) - - def is_step(self, step): - return (step in self._preds or step in self._succs or - step in self._nodes) - - def get_steps(self, final): - if not self.is_step(final): - raise ValueError('Unknown: %r' % final) - result = [] - todo = [] - seen = set() - todo.append(final) - while todo: - step = todo.pop(0) - if step in seen: - # if a step was already seen, - # move it to the end (so it will appear earlier - # when reversed on return) ... but not for the - # final step, as that would be confusing for - # users - if step != final: - result.remove(step) - result.append(step) - else: - seen.add(step) - result.append(step) - preds = self._preds.get(step, ()) - todo.extend(preds) - return reversed(result) - - @property - def strong_connections(self): - #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm - index_counter = [0] - stack = [] - lowlinks = {} - index = {} - result = [] - - graph = self._succs - - def strongconnect(node): - # set the depth index for this node to the smallest unused index - index[node] = index_counter[0] - lowlinks[node] = index_counter[0] - index_counter[0] += 1 - stack.append(node) - - # Consider successors - try: - successors = graph[node] - except Exception: - successors = [] - for successor in successors: - if successor not in lowlinks: - # Successor has not yet been visited - strongconnect(successor) - lowlinks[node] = min(lowlinks[node],lowlinks[successor]) - elif successor in stack: - # the successor is in the stack and hence in the current - # strongly connected component (SCC) - lowlinks[node] = min(lowlinks[node],index[successor]) - - # If `node` is a root node, pop the stack and generate an SCC - if lowlinks[node] == index[node]: - connected_component = [] - - while True: - successor = stack.pop() - connected_component.append(successor) - if successor == node: break - component = tuple(connected_component) - # storing the result - result.append(component) - - for node in graph: - if node not in lowlinks: - strongconnect(node) - - return result - - @property - def dot(self): - result = ['digraph G {'] - for succ in self._preds: - preds = self._preds[succ] - for pred in preds: - result.append(' %s -> %s;' % (pred, succ)) - for node in self._nodes: - result.append(' %s;' % node) - result.append('}') - return '\n'.join(result) - -# -# Unarchiving functionality for zip, tar, tgz, tbz, whl -# - -ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', - '.tgz', '.tbz', '.whl') - -def unarchive(archive_filename, dest_dir, format=None, check=True): - - def check_path(path): - if not isinstance(path, text_type): - path = path.decode('utf-8') - p = os.path.abspath(os.path.join(dest_dir, path)) - if not p.startswith(dest_dir) or p[plen] != os.sep: - raise ValueError('path outside destination: %r' % p) - - dest_dir = os.path.abspath(dest_dir) - plen = len(dest_dir) - archive = None - if format is None: - if archive_filename.endswith(('.zip', '.whl')): - format = 'zip' - elif archive_filename.endswith(('.tar.gz', '.tgz')): - format = 'tgz' - mode = 'r:gz' - elif archive_filename.endswith(('.tar.bz2', '.tbz')): - format = 'tbz' - mode = 'r:bz2' - elif archive_filename.endswith('.tar'): - format = 'tar' - mode = 'r' - else: - raise ValueError('Unknown format for %r' % archive_filename) - try: - if format == 'zip': - archive = ZipFile(archive_filename, 'r') - if check: - names = archive.namelist() - for name in names: - check_path(name) - else: - archive = tarfile.open(archive_filename, mode) - if check: - names = archive.getnames() - for name in names: - check_path(name) - if format != 'zip' and sys.version_info[0] < 3: - # See Python issue 17153. If the dest path contains Unicode, - # tarfile extraction fails on Python 2.x if a member path name - # contains non-ASCII characters - it leads to an implicit - # bytes -> unicode conversion using ASCII to decode. - for tarinfo in archive.getmembers(): - if not isinstance(tarinfo.name, text_type): - tarinfo.name = tarinfo.name.decode('utf-8') - archive.extractall(dest_dir) - - finally: - if archive: - archive.close() - - -def zip_dir(directory): - """zip a directory tree into a BytesIO object""" - result = io.BytesIO() - dlen = len(directory) - with ZipFile(result, "w") as zf: - for root, dirs, files in os.walk(directory): - for name in files: - full = os.path.join(root, name) - rel = root[dlen:] - dest = os.path.join(rel, name) - zf.write(full, dest) - return result - -# -# Simple progress bar -# - -UNITS = ('', 'K', 'M', 'G','T','P') - - -class Progress(object): - unknown = 'UNKNOWN' - - def __init__(self, minval=0, maxval=100): - assert maxval is None or maxval >= minval - self.min = self.cur = minval - self.max = maxval - self.started = None - self.elapsed = 0 - self.done = False - - def update(self, curval): - assert self.min <= curval - assert self.max is None or curval <= self.max - self.cur = curval - now = time.time() - if self.started is None: - self.started = now - else: - self.elapsed = now - self.started - - def increment(self, incr): - assert incr >= 0 - self.update(self.cur + incr) - - def start(self): - self.update(self.min) - return self - - def stop(self): - if self.max is not None: - self.update(self.max) - self.done = True - - @property - def maximum(self): - return self.unknown if self.max is None else self.max - - @property - def percentage(self): - if self.done: - result = '100 %' - elif self.max is None: - result = ' ?? %' - else: - v = 100.0 * (self.cur - self.min) / (self.max - self.min) - result = '%3d %%' % v - return result - - def format_duration(self, duration): - if (duration <= 0) and self.max is None or self.cur == self.min: - result = '??:??:??' - #elif duration < 1: - # result = '--:--:--' - else: - result = time.strftime('%H:%M:%S', time.gmtime(duration)) - return result - - @property - def ETA(self): - if self.done: - prefix = 'Done' - t = self.elapsed - #import pdb; pdb.set_trace() - else: - prefix = 'ETA ' - if self.max is None: - t = -1 - elif self.elapsed == 0 or (self.cur == self.min): - t = 0 - else: - #import pdb; pdb.set_trace() - t = float(self.max - self.min) - t /= self.cur - self.min - t = (t - 1) * self.elapsed - return '%s: %s' % (prefix, self.format_duration(t)) - - @property - def speed(self): - if self.elapsed == 0: - result = 0.0 - else: - result = (self.cur - self.min) / self.elapsed - for unit in UNITS: - if result < 1000: - break - result /= 1000.0 - return '%d %sB/s' % (result, unit) - -# -# Glob functionality -# - -RICH_GLOB = re.compile(r'\{([^}]*)\}') -_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]') -_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$') - - -def iglob(path_glob): - """Extended globbing function that supports ** and {opt1,opt2,opt3}.""" - if _CHECK_RECURSIVE_GLOB.search(path_glob): - msg = """invalid glob %r: recursive glob "**" must be used alone""" - raise ValueError(msg % path_glob) - if _CHECK_MISMATCH_SET.search(path_glob): - msg = """invalid glob %r: mismatching set marker '{' or '}'""" - raise ValueError(msg % path_glob) - return _iglob(path_glob) - - -def _iglob(path_glob): - rich_path_glob = RICH_GLOB.split(path_glob, 1) - if len(rich_path_glob) > 1: - assert len(rich_path_glob) == 3, rich_path_glob - prefix, set, suffix = rich_path_glob - for item in set.split(','): - for path in _iglob(''.join((prefix, item, suffix))): - yield path - else: - if '**' not in path_glob: - for item in std_iglob(path_glob): - yield item - else: - prefix, radical = path_glob.split('**', 1) - if prefix == '': - prefix = '.' - if radical == '': - radical = '*' - else: - # we support both - radical = radical.lstrip('/') - radical = radical.lstrip('\\') - for path, dir, files in os.walk(prefix): - path = os.path.normpath(path) - for fn in _iglob(os.path.join(path, radical)): - yield fn - - - -# -# HTTPSConnection which verifies certificates/matches domains -# - -class HTTPSConnection(httplib.HTTPSConnection): - ca_certs = None # set this to the path to the certs file (.pem) - check_domain = True # only used if ca_certs is not None - - # noinspection PyPropertyAccess - def connect(self): - sock = socket.create_connection((self.host, self.port), self.timeout) - if getattr(self, '_tunnel_host', False): - self.sock = sock - self._tunnel() - - if not hasattr(ssl, 'SSLContext'): - # For 2.x - if self.ca_certs: - cert_reqs = ssl.CERT_REQUIRED - else: - cert_reqs = ssl.CERT_NONE - self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, - cert_reqs=cert_reqs, - ssl_version=ssl.PROTOCOL_SSLv23, - ca_certs=self.ca_certs) - else: - context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - context.options |= ssl.OP_NO_SSLv2 - if self.cert_file: - context.load_cert_chain(self.cert_file, self.key_file) - kwargs = {} - if self.ca_certs: - context.verify_mode = ssl.CERT_REQUIRED - context.load_verify_locations(cafile=self.ca_certs) - if getattr(ssl, 'HAS_SNI', False): - kwargs['server_hostname'] = self.host - self.sock = context.wrap_socket(sock, **kwargs) - if self.ca_certs and self.check_domain: - try: - match_hostname(self.sock.getpeercert(), self.host) - logger.debug('Host verified: %s', self.host) - except CertificateError: - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() - raise - -class HTTPSHandler(BaseHTTPSHandler): - def __init__(self, ca_certs, check_domain=True): - BaseHTTPSHandler.__init__(self) - self.ca_certs = ca_certs - self.check_domain = check_domain - - def _conn_maker(self, *args, **kwargs): - """ - This is called to create a connection instance. Normally you'd - pass a connection class to do_open, but it doesn't actually check for - a class, and just expects a callable. As long as we behave just as a - constructor would have, we should be OK. If it ever changes so that - we *must* pass a class, we'll create an UnsafeHTTPSConnection class - which just sets check_domain to False in the class definition, and - choose which one to pass to do_open. - """ - result = HTTPSConnection(*args, **kwargs) - if self.ca_certs: - result.ca_certs = self.ca_certs - result.check_domain = self.check_domain - return result - - def https_open(self, req): - try: - return self.do_open(self._conn_maker, req) - except URLError as e: - if 'certificate verify failed' in str(e.reason): - raise CertificateError('Unable to verify server certificate ' - 'for %s' % req.host) - else: - raise - -# -# To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The- -# Middle proxy using HTTP listens on port 443, or an index mistakenly serves -# HTML containing a http://xyz link when it should be https://xyz), -# you can use the following handler class, which does not allow HTTP traffic. -# -# It works by inheriting from HTTPHandler - so build_opener won't add a -# handler for HTTP itself. -# -class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): - def http_open(self, req): - raise URLError('Unexpected HTTP request on what should be a secure ' - 'connection: %s' % req) - -# -# XML-RPC with timeouts -# - -_ver_info = sys.version_info[:2] - -if _ver_info == (2, 6): - class HTTP(httplib.HTTP): - def __init__(self, host='', port=None, **kwargs): - if port == 0: # 0 means use port 0, not the default port - port = None - self._setup(self._connection_class(host, port, **kwargs)) - - - class HTTPS(httplib.HTTPS): - def __init__(self, host='', port=None, **kwargs): - if port == 0: # 0 means use port 0, not the default port - port = None - self._setup(self._connection_class(host, port, **kwargs)) - - -class Transport(xmlrpclib.Transport): - def __init__(self, timeout, use_datetime=0): - self.timeout = timeout - xmlrpclib.Transport.__init__(self, use_datetime) - - def make_connection(self, host): - h, eh, x509 = self.get_host_info(host) - if _ver_info == (2, 6): - result = HTTP(h, timeout=self.timeout) - else: - if not self._connection or host != self._connection[0]: - self._extra_headers = eh - self._connection = host, httplib.HTTPConnection(h) - result = self._connection[1] - return result - -class SafeTransport(xmlrpclib.SafeTransport): - def __init__(self, timeout, use_datetime=0): - self.timeout = timeout - xmlrpclib.SafeTransport.__init__(self, use_datetime) - - def make_connection(self, host): - h, eh, kwargs = self.get_host_info(host) - if not kwargs: - kwargs = {} - kwargs['timeout'] = self.timeout - if _ver_info == (2, 6): - result = HTTPS(host, None, **kwargs) - else: - if not self._connection or host != self._connection[0]: - self._extra_headers = eh - self._connection = host, httplib.HTTPSConnection(h, None, - **kwargs) - result = self._connection[1] - return result - - -class ServerProxy(xmlrpclib.ServerProxy): - def __init__(self, uri, **kwargs): - self.timeout = timeout = kwargs.pop('timeout', None) - # The above classes only come into play if a timeout - # is specified - if timeout is not None: - scheme, _ = splittype(uri) - use_datetime = kwargs.get('use_datetime', 0) - if scheme == 'https': - tcls = SafeTransport - else: - tcls = Transport - kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime) - self.transport = t - xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) - -# -# CSV functionality. This is provided because on 2.x, the csv module can't -# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. -# - -def _csv_open(fn, mode, **kwargs): - if sys.version_info[0] < 3: - mode += 'b' - else: - kwargs['newline'] = '' - return open(fn, mode, **kwargs) - - -class CSVBase(object): - defaults = { - 'delimiter': str(','), # The strs are used because we need native - 'quotechar': str('"'), # str in the csv API (2.x won't take - 'lineterminator': str('\n') # Unicode) - } - - def __enter__(self): - return self - - def __exit__(self, *exc_info): - self.stream.close() - - -class CSVReader(CSVBase): - def __init__(self, **kwargs): - if 'stream' in kwargs: - stream = kwargs['stream'] - if sys.version_info[0] >= 3: - # needs to be a text stream - stream = codecs.getreader('utf-8')(stream) - self.stream = stream - else: - self.stream = _csv_open(kwargs['path'], 'r') - self.reader = csv.reader(self.stream, **self.defaults) - - def __iter__(self): - return self - - def next(self): - result = next(self.reader) - if sys.version_info[0] < 3: - for i, item in enumerate(result): - if not isinstance(item, text_type): - result[i] = item.decode('utf-8') - return result - - __next__ = next - -class CSVWriter(CSVBase): - def __init__(self, fn, **kwargs): - self.stream = _csv_open(fn, 'w') - self.writer = csv.writer(self.stream, **self.defaults) - - def writerow(self, row): - if sys.version_info[0] < 3: - r = [] - for item in row: - if isinstance(item, text_type): - item = item.encode('utf-8') - r.append(item) - row = r - self.writer.writerow(row) - -# -# Configurator functionality -# - -class Configurator(BaseConfigurator): - - value_converters = dict(BaseConfigurator.value_converters) - value_converters['inc'] = 'inc_convert' - - def __init__(self, config, base=None): - super(Configurator, self).__init__(config) - self.base = base or os.getcwd() - - def configure_custom(self, config): - def convert(o): - if isinstance(o, (list, tuple)): - result = type(o)([convert(i) for i in o]) - elif isinstance(o, dict): - if '()' in o: - result = self.configure_custom(o) - else: - result = {} - for k in o: - result[k] = convert(o[k]) - else: - result = self.convert(o) - return result - - c = config.pop('()') - if not callable(c): - c = self.resolve(c) - props = config.pop('.', None) - # Check for valid identifiers - args = config.pop('[]', ()) - if args: - args = tuple([convert(o) for o in args]) - items = [(k, convert(config[k])) for k in config if valid_ident(k)] - kwargs = dict(items) - result = c(*args, **kwargs) - if props: - for n, v in props.items(): - setattr(result, n, convert(v)) - return result - - def __getitem__(self, key): - result = self.config[key] - if isinstance(result, dict) and '()' in result: - self.config[key] = result = self.configure_custom(result) - return result - - def inc_convert(self, value): - """Default converter for the inc:// protocol.""" - if not os.path.isabs(value): - value = os.path.join(self.base, value) - with codecs.open(value, 'r', encoding='utf-8') as f: - result = json.load(f) - return result - -# -# Mixin for running subprocesses and capturing their output -# - -class SubprocessMixin(object): - def __init__(self, verbose=False, progress=None): - self.verbose = verbose - self.progress = progress - - def reader(self, stream, context): - """ - Read lines from a subprocess' output stream and either pass to a progress - callable (if specified) or write progress information to sys.stderr. - """ - progress = self.progress - verbose = self.verbose - while True: - s = stream.readline() - if not s: - break - if progress is not None: - progress(s, context) - else: - if not verbose: - sys.stderr.write('.') - else: - sys.stderr.write(s.decode('utf-8')) - sys.stderr.flush() - stream.close() - - def run_command(self, cmd, **kwargs): - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, **kwargs) - t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) - t1.start() - t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) - t2.start() - p.wait() - t1.join() - t2.join() - if self.progress is not None: - self.progress('done.', 'main') - elif self.verbose: - sys.stderr.write('done.\n') - return p diff --git a/awx/lib/site-packages/pip/_vendor/distlib/version.py b/awx/lib/site-packages/pip/_vendor/distlib/version.py deleted file mode 100644 index a2192274ca..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/version.py +++ /dev/null @@ -1,698 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2012-2013 The Python Software Foundation. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -""" -Implementation of a flexible versioning scheme providing support for PEP-386, -distribute-compatible and semantic versioning. -""" - -import logging -import re - -from .compat import string_types - -__all__ = ['NormalizedVersion', 'NormalizedMatcher', - 'LegacyVersion', 'LegacyMatcher', - 'SemanticVersion', 'SemanticMatcher', - 'UnsupportedVersionError', 'get_scheme'] - -logger = logging.getLogger(__name__) - - -class UnsupportedVersionError(ValueError): - """This is an unsupported version.""" - pass - - -class Version(object): - def __init__(self, s): - self._string = s = s.strip() - self._parts = parts = self.parse(s) - assert isinstance(parts, tuple) - assert len(parts) > 0 - - def parse(self, s): - raise NotImplementedError('please implement in a subclass') - - def _check_compatible(self, other): - if type(self) != type(other): - raise TypeError('cannot compare %r and %r' % (self, other)) - - def __eq__(self, other): - self._check_compatible(other) - return self._parts == other._parts - - def __ne__(self, other): - return not self.__eq__(other) - - def __lt__(self, other): - self._check_compatible(other) - return self._parts < other._parts - - def __gt__(self, other): - return not (self.__lt__(other) or self.__eq__(other)) - - def __le__(self, other): - return self.__lt__(other) or self.__eq__(other) - - def __ge__(self, other): - return self.__gt__(other) or self.__eq__(other) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - def __hash__(self): - return hash(self._parts) - - def __repr__(self): - return "%s('%s')" % (self.__class__.__name__, self._string) - - def __str__(self): - return self._string - - @property - def is_prerelease(self): - raise NotImplementedError('Please implement in subclasses.') - - -class Matcher(object): - version_class = None - - dist_re = re.compile(r"^(\w[\s\w'.-]*)(\((.*)\))?") - comp_re = re.compile(r'^(<=|>=|<|>|!=|==|~=)?\s*([^\s,]+)$') - num_re = re.compile(r'^\d+(\.\d+)*$') - - # value is either a callable or the name of a method - _operators = { - '<': lambda v, c, p: v < c, - '>': lambda v, c, p: v > c, - '<=': lambda v, c, p: v == c or v < c, - '>=': lambda v, c, p: v == c or v > c, - '==': lambda v, c, p: v == c, - # by default, compatible => >=. - '~=': lambda v, c, p: v == c or v > c, - '!=': lambda v, c, p: v != c, - } - - def __init__(self, s): - if self.version_class is None: - raise ValueError('Please specify a version class') - self._string = s = s.strip() - m = self.dist_re.match(s) - if not m: - raise ValueError('Not valid: %r' % s) - groups = m.groups('') - self.name = groups[0].strip() - self.key = self.name.lower() # for case-insensitive comparisons - clist = [] - if groups[2]: - constraints = [c.strip() for c in groups[2].split(',')] - for c in constraints: - m = self.comp_re.match(c) - if not m: - raise ValueError('Invalid %r in %r' % (c, s)) - groups = m.groups() - op = groups[0] or '~=' - s = groups[1] - if s.endswith('.*'): - if op not in ('==', '!='): - raise ValueError('\'.*\' not allowed for ' - '%r constraints' % op) - # Could be a partial version (e.g. for '2.*') which - # won't parse as a version, so keep it as a string - vn, prefix = s[:-2], True - if not self.num_re.match(vn): - # Just to check that vn is a valid version - self.version_class(vn) - else: - # Should parse as a version, so we can create an - # instance for the comparison - vn, prefix = self.version_class(s), False - clist.append((op, vn, prefix)) - self._parts = tuple(clist) - - def match(self, version): - """ - Check if the provided version matches the constraints. - - :param version: The version to match against this instance. - :type version: Strring or :class:`Version` instance. - """ - if isinstance(version, string_types): - version = self.version_class(version) - for operator, constraint, prefix in self._parts: - f = self._operators.get(operator) - if isinstance(f, string_types): - f = getattr(self, f) - if not f: - msg = ('%r not implemented ' - 'for %s' % (operator, self.__class__.__name__)) - raise NotImplementedError(msg) - if not f(version, constraint, prefix): - return False - return True - - @property - def exact_version(self): - result = None - if len(self._parts) == 1 and self._parts[0][0] == '==': - result = self._parts[0][1] - return result - - def _check_compatible(self, other): - if type(self) != type(other) or self.name != other.name: - raise TypeError('cannot compare %s and %s' % (self, other)) - - def __eq__(self, other): - self._check_compatible(other) - return self.key == other.key and self._parts == other._parts - - def __ne__(self, other): - return not self.__eq__(other) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - def __hash__(self): - return hash(self.key) + hash(self._parts) - - def __repr__(self): - return "%s(%r)" % (self.__class__.__name__, self._string) - - def __str__(self): - return self._string - - -PEP426_VERSION_RE = re.compile(r'^(\d+\.\d+(\.\d+)*)((a|b|c|rc)(\d+))?' - r'(\.(post)(\d+))?(\.(dev)(\d+))?' - r'(-(\d+(\.\d+)?))?$') - - -def _pep426_key(s): - s = s.strip() - m = PEP426_VERSION_RE.match(s) - if not m: - raise UnsupportedVersionError('Not a valid version: %s' % s) - groups = m.groups() - nums = tuple(int(v) for v in groups[0].split('.')) - while len(nums) > 1 and nums[-1] == 0: - nums = nums[:-1] - - pre = groups[3:5] - post = groups[6:8] - dev = groups[9:11] - local = groups[12] - if pre == (None, None): - pre = () - else: - pre = pre[0], int(pre[1]) - if post == (None, None): - post = () - else: - post = post[0], int(post[1]) - if dev == (None, None): - dev = () - else: - dev = dev[0], int(dev[1]) - if local is None: - local = () - else: - local = tuple([int(s) for s in local.split('.')]) - if not pre: - # either before pre-release, or final release and after - if not post and dev: - # before pre-release - pre = ('a', -1) # to sort before a0 - else: - pre = ('z',) # to sort after all pre-releases - # now look at the state of post and dev. - if not post: - post = ('_',) # sort before 'a' - if not dev: - dev = ('final',) - - #print('%s -> %s' % (s, m.groups())) - return nums, pre, post, dev, local - - -_normalized_key = _pep426_key - - -class NormalizedVersion(Version): - """A rational version. - - Good: - 1.2 # equivalent to "1.2.0" - 1.2.0 - 1.2a1 - 1.2.3a2 - 1.2.3b1 - 1.2.3c1 - 1.2.3.4 - TODO: fill this out - - Bad: - 1 # mininum two numbers - 1.2a # release level must have a release serial - 1.2.3b - """ - def parse(self, s): - result = _normalized_key(s) - # _normalized_key loses trailing zeroes in the release - # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 - # However, PEP 440 prefix matching needs it: for example, - # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). - m = PEP426_VERSION_RE.match(s) # must succeed - groups = m.groups() - self._release_clause = tuple(int(v) for v in groups[0].split('.')) - return result - - PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) - - @property - def is_prerelease(self): - return any(t[0] in self.PREREL_TAGS for t in self._parts if t) - - -def _match_prefix(x, y): - x = str(x) - y = str(y) - if x == y: - return True - if not x.startswith(y): - return False - n = len(y) - return x[n] == '.' - - -class NormalizedMatcher(Matcher): - version_class = NormalizedVersion - - # value is either a callable or the name of a method - _operators = { - '~=': '_match_compatible', - '<': '_match_lt', - '>': '_match_gt', - '<=': '_match_le', - '>=': '_match_ge', - '==': '_match_eq', - '!=': '_match_ne', - } - - def _match_lt(self, version, constraint, prefix): - if version >= constraint: - return False - release_clause = constraint._release_clause - pfx = '.'.join([str(i) for i in release_clause]) - return not _match_prefix(version, pfx) - - def _match_gt(self, version, constraint, prefix): - if version <= constraint: - return False - release_clause = constraint._release_clause - pfx = '.'.join([str(i) for i in release_clause]) - return not _match_prefix(version, pfx) - - def _match_le(self, version, constraint, prefix): - return version <= constraint - - def _match_ge(self, version, constraint, prefix): - return version >= constraint - - def _match_eq(self, version, constraint, prefix): - if not prefix: - result = (version == constraint) - else: - result = _match_prefix(version, constraint) - return result - - def _match_ne(self, version, constraint, prefix): - if not prefix: - result = (version != constraint) - else: - result = not _match_prefix(version, constraint) - return result - - def _match_compatible(self, version, constraint, prefix): - if version == constraint: - return True - if version < constraint: - return False - release_clause = constraint._release_clause - if len(release_clause) > 1: - release_clause = release_clause[:-1] - pfx = '.'.join([str(i) for i in release_clause]) - return _match_prefix(version, pfx) - -_REPLACEMENTS = ( - (re.compile('[.+-]$'), ''), # remove trailing puncts - (re.compile(r'^[.](\d)'), r'0.\1'), # .N -> 0.N at start - (re.compile('^[.-]'), ''), # remove leading puncts - (re.compile(r'^\((.*)\)$'), r'\1'), # remove parentheses - (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'), # remove leading v(ersion) - (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'), # remove leading v(ersion) - (re.compile('[.]{2,}'), '.'), # multiple runs of '.' - (re.compile(r'\b(alfa|apha)\b'), 'alpha'), # misspelt alpha - (re.compile(r'\b(pre-alpha|prealpha)\b'), - 'pre.alpha'), # standardise - (re.compile(r'\(beta\)$'), 'beta'), # remove parentheses -) - -_SUFFIX_REPLACEMENTS = ( - (re.compile('^[:~._+-]+'), ''), # remove leading puncts - (re.compile('[,*")([\]]'), ''), # remove unwanted chars - (re.compile('[~:+_ -]'), '.'), # replace illegal chars - (re.compile('[.]{2,}'), '.'), # multiple runs of '.' - (re.compile(r'\.$'), ''), # trailing '.' -) - -_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') - - -def _suggest_semantic_version(s): - """ - Try to suggest a semantic form for a version for which - _suggest_normalized_version couldn't come up with anything. - """ - result = s.strip().lower() - for pat, repl in _REPLACEMENTS: - result = pat.sub(repl, result) - if not result: - result = '0.0.0' - - # Now look for numeric prefix, and separate it out from - # the rest. - #import pdb; pdb.set_trace() - m = _NUMERIC_PREFIX.match(result) - if not m: - prefix = '0.0.0' - suffix = result - else: - prefix = m.groups()[0].split('.') - prefix = [int(i) for i in prefix] - while len(prefix) < 3: - prefix.append(0) - if len(prefix) == 3: - suffix = result[m.end():] - else: - suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():] - prefix = prefix[:3] - prefix = '.'.join([str(i) for i in prefix]) - suffix = suffix.strip() - if suffix: - #import pdb; pdb.set_trace() - # massage the suffix. - for pat, repl in _SUFFIX_REPLACEMENTS: - suffix = pat.sub(repl, suffix) - - if not suffix: - result = prefix - else: - sep = '-' if 'dev' in suffix else '+' - result = prefix + sep + suffix - if not is_semver(result): - result = None - return result - - -def _suggest_normalized_version(s): - """Suggest a normalized version close to the given version string. - - If you have a version string that isn't rational (i.e. NormalizedVersion - doesn't like it) then you might be able to get an equivalent (or close) - rational version from this function. - - This does a number of simple normalizations to the given string, based - on observation of versions currently in use on PyPI. Given a dump of - those version during PyCon 2009, 4287 of them: - - 2312 (53.93%) match NormalizedVersion without change - with the automatic suggestion - - 3474 (81.04%) match when using this suggestion method - - @param s {str} An irrational version string. - @returns A rational version string, or None, if couldn't determine one. - """ - try: - _normalized_key(s) - return s # already rational - except UnsupportedVersionError: - pass - - rs = s.lower() - - # part of this could use maketrans - for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), - ('beta', 'b'), ('rc', 'c'), ('-final', ''), - ('-pre', 'c'), - ('-release', ''), ('.release', ''), ('-stable', ''), - ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), - ('final', '')): - rs = rs.replace(orig, repl) - - # if something ends with dev or pre, we add a 0 - rs = re.sub(r"pre$", r"pre0", rs) - rs = re.sub(r"dev$", r"dev0", rs) - - # if we have something like "b-2" or "a.2" at the end of the - # version, that is pobably beta, alpha, etc - # let's remove the dash or dot - rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) - - # 1.0-dev-r371 -> 1.0.dev371 - # 0.1-dev-r79 -> 0.1.dev79 - rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) - - # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 - rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) - - # Clean: v0.3, v1.0 - if rs.startswith('v'): - rs = rs[1:] - - # Clean leading '0's on numbers. - #TODO: unintended side-effect on, e.g., "2003.05.09" - # PyPI stats: 77 (~2%) better - rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) - - # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers - # zero. - # PyPI stats: 245 (7.56%) better - rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) - - # the 'dev-rNNN' tag is a dev tag - rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) - - # clean the - when used as a pre delimiter - rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) - - # a terminal "dev" or "devel" can be changed into ".dev0" - rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) - - # a terminal "dev" can be changed into ".dev0" - rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) - - # a terminal "final" or "stable" can be removed - rs = re.sub(r"(final|stable)$", "", rs) - - # The 'r' and the '-' tags are post release tags - # 0.4a1.r10 -> 0.4a1.post10 - # 0.9.33-17222 -> 0.9.33.post17222 - # 0.9.33-r17222 -> 0.9.33.post17222 - rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) - - # Clean 'r' instead of 'dev' usage: - # 0.9.33+r17222 -> 0.9.33.dev17222 - # 1.0dev123 -> 1.0.dev123 - # 1.0.git123 -> 1.0.dev123 - # 1.0.bzr123 -> 1.0.dev123 - # 0.1a0dev.123 -> 0.1a0.dev123 - # PyPI stats: ~150 (~4%) better - rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) - - # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: - # 0.2.pre1 -> 0.2c1 - # 0.2-c1 -> 0.2c1 - # 1.0preview123 -> 1.0c123 - # PyPI stats: ~21 (0.62%) better - rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) - - # Tcl/Tk uses "px" for their post release markers - rs = re.sub(r"p(\d+)$", r".post\1", rs) - - try: - _normalized_key(rs) - except UnsupportedVersionError: - rs = None - return rs - -# -# Legacy version processing (distribute-compatible) -# - -_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) -_VERSION_REPLACE = { - 'pre': 'c', - 'preview': 'c', - '-': 'final-', - 'rc': 'c', - 'dev': '@', - '': None, - '.': None, -} - - -def _legacy_key(s): - def get_parts(s): - result = [] - for p in _VERSION_PART.split(s.lower()): - p = _VERSION_REPLACE.get(p, p) - if p: - if '0' <= p[:1] <= '9': - p = p.zfill(8) - else: - p = '*' + p - result.append(p) - result.append('*final') - return result - - result = [] - for p in get_parts(s): - if p.startswith('*'): - if p < '*final': - while result and result[-1] == '*final-': - result.pop() - while result and result[-1] == '00000000': - result.pop() - result.append(p) - return tuple(result) - - -class LegacyVersion(Version): - def parse(self, s): - return _legacy_key(s) - - PREREL_TAGS = set( - ['*a', '*alpha', '*b', '*beta', '*c', '*rc', '*r', '*@', '*pre'] - ) - - @property - def is_prerelease(self): - return any(x in self.PREREL_TAGS for x in self._parts) - - -class LegacyMatcher(Matcher): - version_class = LegacyVersion - - _operators = dict(Matcher._operators) - _operators['~='] = '_match_compatible' - - numeric_re = re.compile('^(\d+(\.\d+)*)') - - def _match_compatible(self, version, constraint, prefix): - if version < constraint: - return False - m = self.numeric_re.match(str(constraint)) - if not m: - logger.warning('Cannot compute compatible match for version %s ' - ' and constraint %s', version, constraint) - return True - s = m.groups()[0] - if '.' in s: - s = s.rsplit('.', 1)[0] - return _match_prefix(version, s) - -# -# Semantic versioning -# - -_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' - r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' - r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) - - -def is_semver(s): - return _SEMVER_RE.match(s) - - -def _semantic_key(s): - def make_tuple(s, absent): - if s is None: - result = (absent,) - else: - parts = s[1:].split('.') - # We can't compare ints and strings on Python 3, so fudge it - # by zero-filling numeric values so simulate a numeric comparison - result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) - return result - - m = is_semver(s) - if not m: - raise UnsupportedVersionError(s) - groups = m.groups() - major, minor, patch = [int(i) for i in groups[:3]] - # choose the '|' and '*' so that versions sort correctly - pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') - return (major, minor, patch), pre, build - - -class SemanticVersion(Version): - def parse(self, s): - return _semantic_key(s) - - @property - def is_prerelease(self): - return self._parts[1][0] != '|' - - -class SemanticMatcher(Matcher): - version_class = SemanticVersion - - -class VersionScheme(object): - def __init__(self, key, matcher, suggester=None): - self.key = key - self.matcher = matcher - self.suggester = suggester - - def is_valid_version(self, s): - try: - self.matcher.version_class(s) - result = True - except UnsupportedVersionError: - result = False - return result - - def is_valid_matcher(self, s): - try: - self.matcher(s) - result = True - except UnsupportedVersionError: - result = False - return result - - def is_valid_constraint_list(self, s): - """ - Used for processing some metadata fields - """ - return self.is_valid_matcher('dummy_name (%s)' % s) - - def suggest(self, s): - if self.suggester is None: - result = None - else: - result = self.suggester(s) - return result - -_SCHEMES = { - 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, - _suggest_normalized_version), - 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), - 'semantic': VersionScheme(_semantic_key, SemanticMatcher, - _suggest_semantic_version), -} - -_SCHEMES['default'] = _SCHEMES['normalized'] - - -def get_scheme(name): - if name not in _SCHEMES: - raise ValueError('unknown scheme name: %r' % name) - return _SCHEMES[name] diff --git a/awx/lib/site-packages/pip/_vendor/distlib/w32.exe b/awx/lib/site-packages/pip/_vendor/distlib/w32.exe deleted file mode 100644 index 09e76354f7..0000000000 Binary files a/awx/lib/site-packages/pip/_vendor/distlib/w32.exe and /dev/null differ diff --git a/awx/lib/site-packages/pip/_vendor/distlib/w64.exe b/awx/lib/site-packages/pip/_vendor/distlib/w64.exe deleted file mode 100644 index 29e44e1f8a..0000000000 Binary files a/awx/lib/site-packages/pip/_vendor/distlib/w64.exe and /dev/null differ diff --git a/awx/lib/site-packages/pip/_vendor/distlib/wheel.py b/awx/lib/site-packages/pip/_vendor/distlib/wheel.py deleted file mode 100644 index 6dbca81f1e..0000000000 --- a/awx/lib/site-packages/pip/_vendor/distlib/wheel.py +++ /dev/null @@ -1,723 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2013 Vinay Sajip. -# Licensed to the Python Software Foundation under a contributor agreement. -# See LICENSE.txt and CONTRIBUTORS.txt. -# -from __future__ import unicode_literals - -import base64 -import codecs -import datetime -import distutils.util -from email import message_from_file -import hashlib -import imp -import json -import logging -import os -import posixpath -import re -import shutil -import sys -import tempfile -import zipfile - -from . import __version__, DistlibException -from .compat import sysconfig, ZipFile, fsdecode, text_type, filter -from .database import InstalledDistribution -from .metadata import Metadata, METADATA_FILENAME -from .util import (FileOperator, convert_path, CSVReader, CSVWriter, - cached_property, get_cache_base, read_exports) - - -logger = logging.getLogger(__name__) - - -if hasattr(sys, 'pypy_version_info'): - IMP_PREFIX = 'pp' -elif sys.platform.startswith('java'): - IMP_PREFIX = 'jy' -elif sys.platform == 'cli': - IMP_PREFIX = 'ip' -else: - IMP_PREFIX = 'cp' - -VER_SUFFIX = sysconfig.get_config_var('py_version_nodot') -if not VER_SUFFIX: # pragma: no cover - VER_SUFFIX = '%s%s' % sys.version_info[:2] -PYVER = 'py' + VER_SUFFIX -IMPVER = IMP_PREFIX + VER_SUFFIX - -ARCH = distutils.util.get_platform().replace('-', '_').replace('.', '_') - -ABI = sysconfig.get_config_var('SOABI') -if ABI and ABI.startswith('cpython-'): - ABI = ABI.replace('cpython-', 'cp') -else: - ABI = 'none' - -FILENAME_RE = re.compile(r''' -(?P[^-]+) --(?P\d+[^-]*) -(-(?P\d+[^-]*))? --(?P\w+\d+(\.\w+\d+)*) --(?P\w+) --(?P\w+) -\.whl$ -''', re.IGNORECASE | re.VERBOSE) - -NAME_VERSION_RE = re.compile(r''' -(?P[^-]+) --(?P\d+[^-]*) -(-(?P\d+[^-]*))?$ -''', re.IGNORECASE | re.VERBOSE) - -SHEBANG_RE = re.compile(br'\s*#![^\r\n]*') - -if os.sep == '/': - to_posix = lambda o: o -else: - to_posix = lambda o: o.replace(os.sep, '/') - - -class Mounter(object): - def __init__(self): - self.impure_wheels = {} - self.libs = {} - - def add(self, pathname, extensions): - self.impure_wheels[pathname] = extensions - self.libs.update(extensions) - - def remove(self, pathname): - extensions = self.impure_wheels.pop(pathname) - for k, v in extensions: - if k in self.libs: - del self.libs[k] - - def find_module(self, fullname, path=None): - if fullname in self.libs: - result = self - else: - result = None - return result - - def load_module(self, fullname): - if fullname in sys.modules: - result = sys.modules[fullname] - else: - if fullname not in self.libs: - raise ImportError('unable to find extension for %s' % fullname) - result = imp.load_dynamic(fullname, self.libs[fullname]) - result.__loader__ = self - parts = fullname.rsplit('.', 1) - if len(parts) > 1: - result.__package__ = parts[0] - return result - -_hook = Mounter() - - -class Wheel(object): - """ - Class to build and install from Wheel files (PEP 427). - """ - - wheel_version = (1, 1) - hash_kind = 'sha256' - - def __init__(self, filename=None, sign=False, verify=False): - """ - Initialise an instance using a (valid) filename. - """ - self.sign = sign - self.verify = verify - self.buildver = '' - self.pyver = [PYVER] - self.abi = ['none'] - self.arch = ['any'] - self.dirname = os.getcwd() - if filename is None: - self.name = 'dummy' - self.version = '0.1' - self._filename = self.filename - else: - m = NAME_VERSION_RE.match(filename) - if m: - info = m.groupdict('') - self.name = info['nm'] - self.version = info['vn'] - self.buildver = info['bn'] - self._filename = self.filename - else: - dirname, filename = os.path.split(filename) - m = FILENAME_RE.match(filename) - if not m: - raise DistlibException('Invalid name or ' - 'filename: %r' % filename) - if dirname: - self.dirname = os.path.abspath(dirname) - self._filename = filename - info = m.groupdict('') - self.name = info['nm'] - self.version = info['vn'] - self.buildver = info['bn'] - self.pyver = info['py'].split('.') - self.abi = info['bi'].split('.') - self.arch = info['ar'].split('.') - - @property - def filename(self): - """ - Build and return a filename from the various components. - """ - if self.buildver: - buildver = '-' + self.buildver - else: - buildver = '' - pyver = '.'.join(self.pyver) - abi = '.'.join(self.abi) - arch = '.'.join(self.arch) - return '%s-%s%s-%s-%s-%s.whl' % (self.name, self.version, buildver, - pyver, abi, arch) - - @property - def tags(self): - for pyver in self.pyver: - for abi in self.abi: - for arch in self.arch: - yield pyver, abi, arch - - @cached_property - def metadata(self): - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - info_dir = '%s.dist-info' % name_ver - wrapper = codecs.getreader('utf-8') - metadata_filename = posixpath.join(info_dir, METADATA_FILENAME) - with ZipFile(pathname, 'r') as zf: - try: - with zf.open(metadata_filename) as bf: - wf = wrapper(bf) - result = Metadata(fileobj=wf) - except KeyError: - raise ValueError('Invalid wheel, because %s is ' - 'missing' % METADATA_FILENAME) - return result - - @cached_property - def info(self): - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - info_dir = '%s.dist-info' % name_ver - metadata_filename = posixpath.join(info_dir, 'WHEEL') - wrapper = codecs.getreader('utf-8') - with ZipFile(pathname, 'r') as zf: - with zf.open(metadata_filename) as bf: - wf = wrapper(bf) - message = message_from_file(wf) - result = dict(message) - return result - - def process_shebang(self, data): - m = SHEBANG_RE.match(data) - if m: - data = b'#!python' + data[m.end():] - else: - cr = data.find(b'\r') - lf = data.find(b'\n') - if cr < 0 or cr > lf: - term = b'\n' - else: - if data[cr:cr + 2] == b'\r\n': - term = b'\r\n' - else: - term = b'\r' - data = b'#!python' + term + data - return data - - def get_hash(self, data, hash_kind=None): - if hash_kind is None: - hash_kind = self.hash_kind - try: - hasher = getattr(hashlib, hash_kind) - except AttributeError: - raise DistlibException('Unsupported hash algorithm: %r' % hash_kind) - result = hasher(data).digest() - result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii') - return hash_kind, result - - def write_record(self, records, record_path, base): - with CSVWriter(record_path) as writer: - for row in records: - writer.writerow(row) - p = to_posix(os.path.relpath(record_path, base)) - writer.writerow((p, '', '')) - - def build(self, paths, tags=None, wheel_version=None): - """ - Build a wheel from files in specified paths, and use any specified tags - when determining the name of the wheel. - """ - if tags is None: - tags = {} - - libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0] - if libkey == 'platlib': - is_pure = 'false' - default_pyver = [IMPVER] - default_abi = [ABI] - default_arch = [ARCH] - else: - is_pure = 'true' - default_pyver = [PYVER] - default_abi = ['none'] - default_arch = ['any'] - - self.pyver = tags.get('pyver', default_pyver) - self.abi = tags.get('abi', default_abi) - self.arch = tags.get('arch', default_arch) - - libdir = paths[libkey] - - name_ver = '%s-%s' % (self.name, self.version) - data_dir = '%s.data' % name_ver - info_dir = '%s.dist-info' % name_ver - - archive_paths = [] - - # First, stuff which is not in site-packages - for key in ('data', 'headers', 'scripts'): - if key not in paths: - continue - path = paths[key] - if os.path.isdir(path): - for root, dirs, files in os.walk(path): - for fn in files: - p = fsdecode(os.path.join(root, fn)) - rp = os.path.relpath(p, path) - ap = to_posix(os.path.join(data_dir, key, rp)) - archive_paths.append((ap, p)) - if key == 'scripts' and not p.endswith('.exe'): - with open(p, 'rb') as f: - data = f.read() - data = self.process_shebang(data) - with open(p, 'wb') as f: - f.write(data) - - # Now, stuff which is in site-packages, other than the - # distinfo stuff. - path = libdir - distinfo = None - for root, dirs, files in os.walk(path): - if root == path: - # At the top level only, save distinfo for later - # and skip it for now - for i, dn in enumerate(dirs): - dn = fsdecode(dn) - if dn.endswith('.dist-info'): - distinfo = os.path.join(root, dn) - del dirs[i] - break - assert distinfo, '.dist-info directory expected, not found' - - for fn in files: - # comment out next suite to leave .pyc files in - if fsdecode(fn).endswith(('.pyc', '.pyo')): - continue - p = os.path.join(root, fn) - rp = to_posix(os.path.relpath(p, path)) - archive_paths.append((rp, p)) - - # Now distinfo. Assumed to be flat, i.e. os.listdir is enough. - files = os.listdir(distinfo) - for fn in files: - if fn not in ('RECORD', 'INSTALLER', 'SHARED'): - p = fsdecode(os.path.join(distinfo, fn)) - ap = to_posix(os.path.join(info_dir, fn)) - archive_paths.append((ap, p)) - - wheel_metadata = [ - 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), - 'Generator: distlib %s' % __version__, - 'Root-Is-Purelib: %s' % is_pure, - ] - for pyver, abi, arch in self.tags: - wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch)) - p = os.path.join(distinfo, 'WHEEL') - with open(p, 'w') as f: - f.write('\n'.join(wheel_metadata)) - ap = to_posix(os.path.join(info_dir, 'WHEEL')) - archive_paths.append((ap, p)) - - # Now, at last, RECORD. - # Paths in here are archive paths - nothing else makes sense. - records = [] - hasher = getattr(hashlib, self.hash_kind) - for ap, p in archive_paths: - with open(p, 'rb') as f: - data = f.read() - digest = '%s=%s' % self.get_hash(data) - size = os.path.getsize(p) - records.append((ap, digest, size)) - - p = os.path.join(distinfo, 'RECORD') - self.write_record(records, p, libdir) - ap = to_posix(os.path.join(info_dir, 'RECORD')) - archive_paths.append((ap, p)) - # Now, ready to build the zip file - pathname = os.path.join(self.dirname, self.filename) - with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf: - for ap, p in archive_paths: - logger.debug('Wrote %s to %s in wheel', p, ap) - zf.write(p, ap) - return pathname - - def install(self, paths, maker, **kwargs): - """ - Install a wheel to the specified paths. If kwarg ``warner`` is - specified, it should be a callable, which will be called with two - tuples indicating the wheel version of this software and the wheel - version in the file, if there is a discrepancy in the versions. - This can be used to issue any warnings to raise any exceptions. - If kwarg ``lib_only`` is True, only the purelib/platlib files are - installed, and the headers, scripts, data and dist-info metadata are - not written. - - The return value is a :class:`InstalledDistribution` instance unless - ``options.lib_only`` is True, in which case the return value is ``None``. - """ - - dry_run = maker.dry_run - warner = kwargs.get('warner') - lib_only = kwargs.get('lib_only', False) - - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - data_dir = '%s.data' % name_ver - info_dir = '%s.dist-info' % name_ver - - metadata_name = posixpath.join(info_dir, METADATA_FILENAME) - wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') - record_name = posixpath.join(info_dir, 'RECORD') - - wrapper = codecs.getreader('utf-8') - - with ZipFile(pathname, 'r') as zf: - with zf.open(wheel_metadata_name) as bwf: - wf = wrapper(bwf) - message = message_from_file(wf) - wv = message['Wheel-Version'].split('.', 1) - file_version = tuple([int(i) for i in wv]) - if (file_version != self.wheel_version) and warner: - warner(self.wheel_version, file_version) - - if message['Root-Is-Purelib'] == 'true': - libdir = paths['purelib'] - else: - libdir = paths['platlib'] - - records = {} - with zf.open(record_name) as bf: - with CSVReader(stream=bf) as reader: - for row in reader: - p = row[0] - records[p] = row - - data_pfx = posixpath.join(data_dir, '') - info_pfx = posixpath.join(info_dir, '') - script_pfx = posixpath.join(data_dir, 'scripts', '') - - # make a new instance rather than a copy of maker's, - # as we mutate it - fileop = FileOperator(dry_run=dry_run) - fileop.record = True # so we can rollback if needed - - bc = not sys.dont_write_bytecode # Double negatives. Lovely! - - outfiles = [] # for RECORD writing - - # for script copying/shebang processing - workdir = tempfile.mkdtemp() - # set target dir later - # we default add_launchers to False, as the - # Python Launcher should be used instead - maker.source_dir = workdir - maker.target_dir = None - try: - for zinfo in zf.infolist(): - arcname = zinfo.filename - if isinstance(arcname, text_type): - u_arcname = arcname - else: - u_arcname = arcname.decode('utf-8') - # The signature file won't be in RECORD, - # and we don't currently don't do anything with it - if u_arcname.endswith('/RECORD.jws'): - continue - row = records[u_arcname] - if row[2] and str(zinfo.file_size) != row[2]: - raise DistlibException('size mismatch for ' - '%s' % u_arcname) - if row[1]: - kind, value = row[1].split('=', 1) - with zf.open(arcname) as bf: - data = bf.read() - _, digest = self.get_hash(data, kind) - if digest != value: - raise DistlibException('digest mismatch for ' - '%s' % arcname) - - if lib_only and u_arcname.startswith((info_pfx, data_pfx)): - logger.debug('lib_only: skipping %s', u_arcname) - continue - is_script = (u_arcname.startswith(script_pfx) - and not u_arcname.endswith('.exe')) - - if u_arcname.startswith(data_pfx): - _, where, rp = u_arcname.split('/', 2) - outfile = os.path.join(paths[where], convert_path(rp)) - else: - # meant for site-packages. - if u_arcname in (wheel_metadata_name, record_name): - continue - outfile = os.path.join(libdir, convert_path(u_arcname)) - if not is_script: - with zf.open(arcname) as bf: - fileop.copy_stream(bf, outfile) - outfiles.append(outfile) - # Double check the digest of the written file - if not dry_run and row[1]: - with open(outfile, 'rb') as bf: - data = bf.read() - _, newdigest = self.get_hash(data, kind) - if newdigest != digest: - raise DistlibException('digest mismatch ' - 'on write for ' - '%s' % outfile) - if bc and outfile.endswith('.py'): - try: - pyc = fileop.byte_compile(outfile) - outfiles.append(pyc) - except Exception: - # Don't give up if byte-compilation fails, - # but log it and perhaps warn the user - logger.warning('Byte-compilation failed', - exc_info=True) - else: - fn = os.path.basename(convert_path(arcname)) - workname = os.path.join(workdir, fn) - with zf.open(arcname) as bf: - fileop.copy_stream(bf, workname) - - dn, fn = os.path.split(outfile) - maker.target_dir = dn - filenames = maker.make(fn) - fileop.set_executable_mode(filenames) - outfiles.extend(filenames) - - if lib_only: - logger.debug('lib_only: returning None') - dist = None - else: - # Generate scripts - - # Try to get pydist.json so we can see if there are - # any commands to generate. If this fails (e.g. because - # of a legacy wheel), log a warning but don't give up. - commands = None - file_version = self.info['Wheel-Version'] - if file_version == '1.0': - # Use legacy info - ep = posixpath.join(info_dir, 'entry_points.txt') - try: - with zf.open(ep) as bwf: - epdata = read_exports(bwf) - commands = {} - for key in ('console', 'gui'): - k = '%s_scripts' % key - if k in epdata: - commands['wrap_%s' % key] = d = {} - for v in epdata[k].values(): - s = '%s:%s' % (v.prefix, v.suffix) - if v.flags: - s += ' %s' % v.flags - d[v.name] = s - except Exception: - logger.warning('Unable to read legacy script ' - 'metadata, so cannot generate ' - 'scripts') - else: - try: - with zf.open(metadata_name) as bwf: - wf = wrapper(bwf) - commands = json.load(wf).get('commands') - except Exception: - logger.warning('Unable to read JSON metadata, so ' - 'cannot generate scripts') - if commands: - console_scripts = commands.get('wrap_console', {}) - gui_scripts = commands.get('wrap_gui', {}) - if console_scripts or gui_scripts: - script_dir = paths.get('scripts', '') - if not os.path.isdir(script_dir): - raise ValueError('Valid script path not ' - 'specified') - maker.target_dir = script_dir - for k, v in console_scripts.items(): - script = '%s = %s' % (k, v) - filenames = maker.make(script) - fileop.set_executable_mode(filenames) - - if gui_scripts: - options = {'gui': True } - for k, v in gui_scripts.items(): - script = '%s = %s' % (k, v) - filenames = maker.make(script, options) - fileop.set_executable_mode(filenames) - - p = os.path.join(libdir, info_dir) - dist = InstalledDistribution(p) - - # Write SHARED - paths = dict(paths) # don't change passed in dict - del paths['purelib'] - del paths['platlib'] - paths['lib'] = libdir - p = dist.write_shared_locations(paths, dry_run) - if p: - outfiles.append(p) - - # Write RECORD - dist.write_installed_files(outfiles, paths['prefix'], - dry_run) - return dist - except Exception: # pragma: no cover - logger.exception('installation failed.') - fileop.rollback() - raise - finally: - shutil.rmtree(workdir) - - def _get_dylib_cache(self): - # Use native string to avoid issues on 2.x: see Python #20140. - result = os.path.join(get_cache_base(), str('dylib-cache'), sys.version[:3]) - if not os.path.isdir(result): - os.makedirs(result) - return result - - def _get_extensions(self): - pathname = os.path.join(self.dirname, self.filename) - name_ver = '%s-%s' % (self.name, self.version) - info_dir = '%s.dist-info' % name_ver - arcname = posixpath.join(info_dir, 'EXTENSIONS') - wrapper = codecs.getreader('utf-8') - result = [] - with ZipFile(pathname, 'r') as zf: - try: - with zf.open(arcname) as bf: - wf = wrapper(bf) - extensions = json.load(wf) - cache_base = self._get_dylib_cache() - for name, relpath in extensions.items(): - dest = os.path.join(cache_base, convert_path(relpath)) - if not os.path.exists(dest): - extract = True - else: - file_time = os.stat(dest).st_mtime - file_time = datetime.datetime.fromtimestamp(file_time) - info = zf.getinfo(relpath) - wheel_time = datetime.datetime(*info.date_time) - extract = wheel_time > file_time - if extract: - zf.extract(relpath, cache_base) - result.append((name, dest)) - except KeyError: - pass - return result - - def mount(self, append=False): - pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) - if not is_compatible(self): - msg = 'Wheel %s not mountable in this Python.' % pathname - raise DistlibException(msg) - if pathname in sys.path: - logger.debug('%s already in path', pathname) - else: - if append: - sys.path.append(pathname) - else: - sys.path.insert(0, pathname) - extensions = self._get_extensions() - if extensions: - if _hook not in sys.meta_path: - sys.meta_path.append(_hook) - _hook.add(pathname, extensions) - - def unmount(self): - pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) - if pathname not in sys.path: - logger.debug('%s not in path', pathname) - else: - sys.path.remove(pathname) - if pathname in _hook.impure_wheels: - _hook.remove(pathname) - if not _hook.impure_wheels: - if _hook in sys.meta_path: - sys.meta_path.remove(_hook) - - -def compatible_tags(): - """ - Return (pyver, abi, arch) tuples compatible with this Python. - """ - versions = [VER_SUFFIX] - major = VER_SUFFIX[0] - for minor in range(sys.version_info[1] - 1, - 1, -1): - versions.append(''.join([major, str(minor)])) - - abis = [] - for suffix, _, _ in imp.get_suffixes(): - if suffix.startswith('.abi'): - abis.append(suffix.split('.', 2)[1]) - abis.sort() - if ABI != 'none': - abis.insert(0, ABI) - abis.append('none') - result = [] - - # Most specific - our Python version, ABI and arch - for abi in abis: - result.append((''.join((IMP_PREFIX, versions[0])), abi, ARCH)) - - # where no ABI / arch dependency, but IMP_PREFIX dependency - for i, version in enumerate(versions): - result.append((''.join((IMP_PREFIX, version)), 'none', 'any')) - if i == 0: - result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any')) - - # no IMP_PREFIX, ABI or arch dependency - for i, version in enumerate(versions): - result.append((''.join(('py', version)), 'none', 'any')) - if i == 0: - result.append((''.join(('py', version[0])), 'none', 'any')) - return result - - -COMPATIBLE_TAGS = compatible_tags() - -del compatible_tags - - -def is_compatible(wheel, tags=None): - if not isinstance(wheel, Wheel): - wheel = Wheel(wheel) # assume it's a filename - result = False - if tags is None: - tags = COMPATIBLE_TAGS - for ver, abi, arch in tags: - if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch: - result = True - break - return result diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/__init__.py deleted file mode 100644 index 10e2b74c29..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -HTML parsing library based on the WHATWG "HTML5" -specification. The parser is designed to be compatible with existing -HTML found in the wild and implements well-defined error recovery that -is largely compatible with modern desktop web browsers. - -Example usage: - -import html5lib -f = open("my_document.html") -tree = html5lib.parse(f) -""" - -from __future__ import absolute_import, division, unicode_literals - -from .html5parser import HTMLParser, parse, parseFragment -from .treebuilders import getTreeBuilder -from .treewalkers import getTreeWalker -from .serializer import serialize - -__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", - "getTreeWalker", "serialize"] -__version__ = "1.0b1" diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/constants.py b/awx/lib/site-packages/pip/_vendor/html5lib/constants.py deleted file mode 100644 index 1866dd78e7..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/constants.py +++ /dev/null @@ -1,3086 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -import string -import gettext -_ = gettext.gettext - -EOF = None - -E = { - "null-character": - _("Null character in input stream, replaced with U+FFFD."), - "invalid-codepoint": - _("Invalid codepoint in stream."), - "incorrectly-placed-solidus": - _("Solidus (/) incorrectly placed in tag."), - "incorrect-cr-newline-entity": - _("Incorrect CR newline entity, replaced with LF."), - "illegal-windows-1252-entity": - _("Entity used with illegal number (windows-1252 reference)."), - "cant-convert-numeric-entity": - _("Numeric entity couldn't be converted to character " - "(codepoint U+%(charAsInt)08x)."), - "illegal-codepoint-for-numeric-entity": - _("Numeric entity represents an illegal codepoint: " - "U+%(charAsInt)08x."), - "numeric-entity-without-semicolon": - _("Numeric entity didn't end with ';'."), - "expected-numeric-entity-but-got-eof": - _("Numeric entity expected. Got end of file instead."), - "expected-numeric-entity": - _("Numeric entity expected but none found."), - "named-entity-without-semicolon": - _("Named entity didn't end with ';'."), - "expected-named-entity": - _("Named entity expected. Got none."), - "attributes-in-end-tag": - _("End tag contains unexpected attributes."), - 'self-closing-flag-on-end-tag': - _("End tag contains unexpected self-closing flag."), - "expected-tag-name-but-got-right-bracket": - _("Expected tag name. Got '>' instead."), - "expected-tag-name-but-got-question-mark": - _("Expected tag name. Got '?' instead. (HTML doesn't " - "support processing instructions.)"), - "expected-tag-name": - _("Expected tag name. Got something else instead"), - "expected-closing-tag-but-got-right-bracket": - _("Expected closing tag. Got '>' instead. Ignoring ''."), - "expected-closing-tag-but-got-eof": - _("Expected closing tag. Unexpected end of file."), - "expected-closing-tag-but-got-char": - _("Expected closing tag. Unexpected character '%(data)s' found."), - "eof-in-tag-name": - _("Unexpected end of file in the tag name."), - "expected-attribute-name-but-got-eof": - _("Unexpected end of file. Expected attribute name instead."), - "eof-in-attribute-name": - _("Unexpected end of file in attribute name."), - "invalid-character-in-attribute-name": - _("Invalid character in attribute name"), - "duplicate-attribute": - _("Dropped duplicate attribute on tag."), - "expected-end-of-tag-name-but-got-eof": - _("Unexpected end of file. Expected = or end of tag."), - "expected-attribute-value-but-got-eof": - _("Unexpected end of file. Expected attribute value."), - "expected-attribute-value-but-got-right-bracket": - _("Expected attribute value. Got '>' instead."), - 'equals-in-unquoted-attribute-value': - _("Unexpected = in unquoted attribute"), - 'unexpected-character-in-unquoted-attribute-value': - _("Unexpected character in unquoted attribute"), - "invalid-character-after-attribute-name": - _("Unexpected character after attribute name."), - "unexpected-character-after-attribute-value": - _("Unexpected character after attribute value."), - "eof-in-attribute-value-double-quote": - _("Unexpected end of file in attribute value (\")."), - "eof-in-attribute-value-single-quote": - _("Unexpected end of file in attribute value (')."), - "eof-in-attribute-value-no-quotes": - _("Unexpected end of file in attribute value."), - "unexpected-EOF-after-solidus-in-tag": - _("Unexpected end of file in tag. Expected >"), - "unexpected-character-after-solidus-in-tag": - _("Unexpected character after / in tag. Expected >"), - "expected-dashes-or-doctype": - _("Expected '--' or 'DOCTYPE'. Not found."), - "unexpected-bang-after-double-dash-in-comment": - _("Unexpected ! after -- in comment"), - "unexpected-space-after-double-dash-in-comment": - _("Unexpected space after -- in comment"), - "incorrect-comment": - _("Incorrect comment."), - "eof-in-comment": - _("Unexpected end of file in comment."), - "eof-in-comment-end-dash": - _("Unexpected end of file in comment (-)"), - "unexpected-dash-after-double-dash-in-comment": - _("Unexpected '-' after '--' found in comment."), - "eof-in-comment-double-dash": - _("Unexpected end of file in comment (--)."), - "eof-in-comment-end-space-state": - _("Unexpected end of file in comment."), - "eof-in-comment-end-bang-state": - _("Unexpected end of file in comment."), - "unexpected-char-in-comment": - _("Unexpected character in comment found."), - "need-space-after-doctype": - _("No space after literal string 'DOCTYPE'."), - "expected-doctype-name-but-got-right-bracket": - _("Unexpected > character. Expected DOCTYPE name."), - "expected-doctype-name-but-got-eof": - _("Unexpected end of file. Expected DOCTYPE name."), - "eof-in-doctype-name": - _("Unexpected end of file in DOCTYPE name."), - "eof-in-doctype": - _("Unexpected end of file in DOCTYPE."), - "expected-space-or-right-bracket-in-doctype": - _("Expected space or '>'. Got '%(data)s'"), - "unexpected-end-of-doctype": - _("Unexpected end of DOCTYPE."), - "unexpected-char-in-doctype": - _("Unexpected character in DOCTYPE."), - "eof-in-innerhtml": - _("XXX innerHTML EOF"), - "unexpected-doctype": - _("Unexpected DOCTYPE. Ignored."), - "non-html-root": - _("html needs to be the first start tag."), - "expected-doctype-but-got-eof": - _("Unexpected End of file. Expected DOCTYPE."), - "unknown-doctype": - _("Erroneous DOCTYPE."), - "expected-doctype-but-got-chars": - _("Unexpected non-space characters. Expected DOCTYPE."), - "expected-doctype-but-got-start-tag": - _("Unexpected start tag (%(name)s). Expected DOCTYPE."), - "expected-doctype-but-got-end-tag": - _("Unexpected end tag (%(name)s). Expected DOCTYPE."), - "end-tag-after-implied-root": - _("Unexpected end tag (%(name)s) after the (implied) root element."), - "expected-named-closing-tag-but-got-eof": - _("Unexpected end of file. Expected end tag (%(name)s)."), - "two-heads-are-not-better-than-one": - _("Unexpected start tag head in existing head. Ignored."), - "unexpected-end-tag": - _("Unexpected end tag (%(name)s). Ignored."), - "unexpected-start-tag-out-of-my-head": - _("Unexpected start tag (%(name)s) that can be in head. Moved."), - "unexpected-start-tag": - _("Unexpected start tag (%(name)s)."), - "missing-end-tag": - _("Missing end tag (%(name)s)."), - "missing-end-tags": - _("Missing end tags (%(name)s)."), - "unexpected-start-tag-implies-end-tag": - _("Unexpected start tag (%(startName)s) " - "implies end tag (%(endName)s)."), - "unexpected-start-tag-treated-as": - _("Unexpected start tag (%(originalName)s). Treated as %(newName)s."), - "deprecated-tag": - _("Unexpected start tag %(name)s. Don't use it!"), - "unexpected-start-tag-ignored": - _("Unexpected start tag %(name)s. Ignored."), - "expected-one-end-tag-but-got-another": - _("Unexpected end tag (%(gotName)s). " - "Missing end tag (%(expectedName)s)."), - "end-tag-too-early": - _("End tag (%(name)s) seen too early. Expected other end tag."), - "end-tag-too-early-named": - _("Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s)."), - "end-tag-too-early-ignored": - _("End tag (%(name)s) seen too early. Ignored."), - "adoption-agency-1.1": - _("End tag (%(name)s) violates step 1, " - "paragraph 1 of the adoption agency algorithm."), - "adoption-agency-1.2": - _("End tag (%(name)s) violates step 1, " - "paragraph 2 of the adoption agency algorithm."), - "adoption-agency-1.3": - _("End tag (%(name)s) violates step 1, " - "paragraph 3 of the adoption agency algorithm."), - "adoption-agency-4.4": - _("End tag (%(name)s) violates step 4, " - "paragraph 4 of the adoption agency algorithm."), - "unexpected-end-tag-treated-as": - _("Unexpected end tag (%(originalName)s). Treated as %(newName)s."), - "no-end-tag": - _("This element (%(name)s) has no end tag."), - "unexpected-implied-end-tag-in-table": - _("Unexpected implied end tag (%(name)s) in the table phase."), - "unexpected-implied-end-tag-in-table-body": - _("Unexpected implied end tag (%(name)s) in the table body phase."), - "unexpected-char-implies-table-voodoo": - _("Unexpected non-space characters in " - "table context caused voodoo mode."), - "unexpected-hidden-input-in-table": - _("Unexpected input with type hidden in table context."), - "unexpected-form-in-table": - _("Unexpected form in table context."), - "unexpected-start-tag-implies-table-voodoo": - _("Unexpected start tag (%(name)s) in " - "table context caused voodoo mode."), - "unexpected-end-tag-implies-table-voodoo": - _("Unexpected end tag (%(name)s) in " - "table context caused voodoo mode."), - "unexpected-cell-in-table-body": - _("Unexpected table cell start tag (%(name)s) " - "in the table body phase."), - "unexpected-cell-end-tag": - _("Got table cell end tag (%(name)s) " - "while required end tags are missing."), - "unexpected-end-tag-in-table-body": - _("Unexpected end tag (%(name)s) in the table body phase. Ignored."), - "unexpected-implied-end-tag-in-table-row": - _("Unexpected implied end tag (%(name)s) in the table row phase."), - "unexpected-end-tag-in-table-row": - _("Unexpected end tag (%(name)s) in the table row phase. Ignored."), - "unexpected-select-in-select": - _("Unexpected select start tag in the select phase " - "treated as select end tag."), - "unexpected-input-in-select": - _("Unexpected input start tag in the select phase."), - "unexpected-start-tag-in-select": - _("Unexpected start tag token (%(name)s in the select phase. " - "Ignored."), - "unexpected-end-tag-in-select": - _("Unexpected end tag (%(name)s) in the select phase. Ignored."), - "unexpected-table-element-start-tag-in-select-in-table": - _("Unexpected table element start tag (%(name)s) in the select in table phase."), - "unexpected-table-element-end-tag-in-select-in-table": - _("Unexpected table element end tag (%(name)s) in the select in table phase."), - "unexpected-char-after-body": - _("Unexpected non-space characters in the after body phase."), - "unexpected-start-tag-after-body": - _("Unexpected start tag token (%(name)s)" - " in the after body phase."), - "unexpected-end-tag-after-body": - _("Unexpected end tag token (%(name)s)" - " in the after body phase."), - "unexpected-char-in-frameset": - _("Unexpected characters in the frameset phase. Characters ignored."), - "unexpected-start-tag-in-frameset": - _("Unexpected start tag token (%(name)s)" - " in the frameset phase. Ignored."), - "unexpected-frameset-in-frameset-innerhtml": - _("Unexpected end tag token (frameset) " - "in the frameset phase (innerHTML)."), - "unexpected-end-tag-in-frameset": - _("Unexpected end tag token (%(name)s)" - " in the frameset phase. Ignored."), - "unexpected-char-after-frameset": - _("Unexpected non-space characters in the " - "after frameset phase. Ignored."), - "unexpected-start-tag-after-frameset": - _("Unexpected start tag (%(name)s)" - " in the after frameset phase. Ignored."), - "unexpected-end-tag-after-frameset": - _("Unexpected end tag (%(name)s)" - " in the after frameset phase. Ignored."), - "unexpected-end-tag-after-body-innerhtml": - _("Unexpected end tag after body(innerHtml)"), - "expected-eof-but-got-char": - _("Unexpected non-space characters. Expected end of file."), - "expected-eof-but-got-start-tag": - _("Unexpected start tag (%(name)s)" - ". Expected end of file."), - "expected-eof-but-got-end-tag": - _("Unexpected end tag (%(name)s)" - ". Expected end of file."), - "eof-in-table": - _("Unexpected end of file. Expected table content."), - "eof-in-select": - _("Unexpected end of file. Expected select content."), - "eof-in-frameset": - _("Unexpected end of file. Expected frameset content."), - "eof-in-script-in-script": - _("Unexpected end of file. Expected script content."), - "eof-in-foreign-lands": - _("Unexpected end of file. Expected foreign content"), - "non-void-element-with-trailing-solidus": - _("Trailing solidus not allowed on element %(name)s"), - "unexpected-html-element-in-foreign-content": - _("Element %(name)s not allowed in a non-html context"), - "unexpected-end-tag-before-html": - _("Unexpected end tag (%(name)s) before html."), - "XXX-undefined-error": - _("Undefined error (this sucks and should be fixed)"), -} - -namespaces = { - "html": "http://www.w3.org/1999/xhtml", - "mathml": "http://www.w3.org/1998/Math/MathML", - "svg": "http://www.w3.org/2000/svg", - "xlink": "http://www.w3.org/1999/xlink", - "xml": "http://www.w3.org/XML/1998/namespace", - "xmlns": "http://www.w3.org/2000/xmlns/" -} - -scopingElements = frozenset(( - (namespaces["html"], "applet"), - (namespaces["html"], "caption"), - (namespaces["html"], "html"), - (namespaces["html"], "marquee"), - (namespaces["html"], "object"), - (namespaces["html"], "table"), - (namespaces["html"], "td"), - (namespaces["html"], "th"), - (namespaces["mathml"], "mi"), - (namespaces["mathml"], "mo"), - (namespaces["mathml"], "mn"), - (namespaces["mathml"], "ms"), - (namespaces["mathml"], "mtext"), - (namespaces["mathml"], "annotation-xml"), - (namespaces["svg"], "foreignObject"), - (namespaces["svg"], "desc"), - (namespaces["svg"], "title"), -)) - -formattingElements = frozenset(( - (namespaces["html"], "a"), - (namespaces["html"], "b"), - (namespaces["html"], "big"), - (namespaces["html"], "code"), - (namespaces["html"], "em"), - (namespaces["html"], "font"), - (namespaces["html"], "i"), - (namespaces["html"], "nobr"), - (namespaces["html"], "s"), - (namespaces["html"], "small"), - (namespaces["html"], "strike"), - (namespaces["html"], "strong"), - (namespaces["html"], "tt"), - (namespaces["html"], "u") -)) - -specialElements = frozenset(( - (namespaces["html"], "address"), - (namespaces["html"], "applet"), - (namespaces["html"], "area"), - (namespaces["html"], "article"), - (namespaces["html"], "aside"), - (namespaces["html"], "base"), - (namespaces["html"], "basefont"), - (namespaces["html"], "bgsound"), - (namespaces["html"], "blockquote"), - (namespaces["html"], "body"), - (namespaces["html"], "br"), - (namespaces["html"], "button"), - (namespaces["html"], "caption"), - (namespaces["html"], "center"), - (namespaces["html"], "col"), - (namespaces["html"], "colgroup"), - (namespaces["html"], "command"), - (namespaces["html"], "dd"), - (namespaces["html"], "details"), - (namespaces["html"], "dir"), - (namespaces["html"], "div"), - (namespaces["html"], "dl"), - (namespaces["html"], "dt"), - (namespaces["html"], "embed"), - (namespaces["html"], "fieldset"), - (namespaces["html"], "figure"), - (namespaces["html"], "footer"), - (namespaces["html"], "form"), - (namespaces["html"], "frame"), - (namespaces["html"], "frameset"), - (namespaces["html"], "h1"), - (namespaces["html"], "h2"), - (namespaces["html"], "h3"), - (namespaces["html"], "h4"), - (namespaces["html"], "h5"), - (namespaces["html"], "h6"), - (namespaces["html"], "head"), - (namespaces["html"], "header"), - (namespaces["html"], "hr"), - (namespaces["html"], "html"), - (namespaces["html"], "iframe"), - # Note that image is commented out in the spec as "this isn't an - # element that can end up on the stack, so it doesn't matter," - (namespaces["html"], "image"), - (namespaces["html"], "img"), - (namespaces["html"], "input"), - (namespaces["html"], "isindex"), - (namespaces["html"], "li"), - (namespaces["html"], "link"), - (namespaces["html"], "listing"), - (namespaces["html"], "marquee"), - (namespaces["html"], "menu"), - (namespaces["html"], "meta"), - (namespaces["html"], "nav"), - (namespaces["html"], "noembed"), - (namespaces["html"], "noframes"), - (namespaces["html"], "noscript"), - (namespaces["html"], "object"), - (namespaces["html"], "ol"), - (namespaces["html"], "p"), - (namespaces["html"], "param"), - (namespaces["html"], "plaintext"), - (namespaces["html"], "pre"), - (namespaces["html"], "script"), - (namespaces["html"], "section"), - (namespaces["html"], "select"), - (namespaces["html"], "style"), - (namespaces["html"], "table"), - (namespaces["html"], "tbody"), - (namespaces["html"], "td"), - (namespaces["html"], "textarea"), - (namespaces["html"], "tfoot"), - (namespaces["html"], "th"), - (namespaces["html"], "thead"), - (namespaces["html"], "title"), - (namespaces["html"], "tr"), - (namespaces["html"], "ul"), - (namespaces["html"], "wbr"), - (namespaces["html"], "xmp"), - (namespaces["svg"], "foreignObject") -)) - -htmlIntegrationPointElements = frozenset(( - (namespaces["mathml"], "annotaion-xml"), - (namespaces["svg"], "foreignObject"), - (namespaces["svg"], "desc"), - (namespaces["svg"], "title") -)) - -mathmlTextIntegrationPointElements = frozenset(( - (namespaces["mathml"], "mi"), - (namespaces["mathml"], "mo"), - (namespaces["mathml"], "mn"), - (namespaces["mathml"], "ms"), - (namespaces["mathml"], "mtext") -)) - -spaceCharacters = frozenset(( - "\t", - "\n", - "\u000C", - " ", - "\r" -)) - -tableInsertModeElements = frozenset(( - "table", - "tbody", - "tfoot", - "thead", - "tr" -)) - -asciiLowercase = frozenset(string.ascii_lowercase) -asciiUppercase = frozenset(string.ascii_uppercase) -asciiLetters = frozenset(string.ascii_letters) -digits = frozenset(string.digits) -hexDigits = frozenset(string.hexdigits) - -asciiUpper2Lower = dict([(ord(c), ord(c.lower())) - for c in string.ascii_uppercase]) - -# Heading elements need to be ordered -headingElements = ( - "h1", - "h2", - "h3", - "h4", - "h5", - "h6" -) - -voidElements = frozenset(( - "base", - "command", - "event-source", - "link", - "meta", - "hr", - "br", - "img", - "embed", - "param", - "area", - "col", - "input", - "source", - "track" -)) - -cdataElements = frozenset(('title', 'textarea')) - -rcdataElements = frozenset(( - 'style', - 'script', - 'xmp', - 'iframe', - 'noembed', - 'noframes', - 'noscript' -)) - -booleanAttributes = { - "": frozenset(("irrelevant",)), - "style": frozenset(("scoped",)), - "img": frozenset(("ismap",)), - "audio": frozenset(("autoplay", "controls")), - "video": frozenset(("autoplay", "controls")), - "script": frozenset(("defer", "async")), - "details": frozenset(("open",)), - "datagrid": frozenset(("multiple", "disabled")), - "command": frozenset(("hidden", "disabled", "checked", "default")), - "hr": frozenset(("noshade")), - "menu": frozenset(("autosubmit",)), - "fieldset": frozenset(("disabled", "readonly")), - "option": frozenset(("disabled", "readonly", "selected")), - "optgroup": frozenset(("disabled", "readonly")), - "button": frozenset(("disabled", "autofocus")), - "input": frozenset(("disabled", "readonly", "required", "autofocus", "checked", "ismap")), - "select": frozenset(("disabled", "readonly", "autofocus", "multiple")), - "output": frozenset(("disabled", "readonly")), -} - -# entitiesWindows1252 has to be _ordered_ and needs to have an index. It -# therefore can't be a frozenset. -entitiesWindows1252 = ( - 8364, # 0x80 0x20AC EURO SIGN - 65533, # 0x81 UNDEFINED - 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK - 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK - 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK - 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS - 8224, # 0x86 0x2020 DAGGER - 8225, # 0x87 0x2021 DOUBLE DAGGER - 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT - 8240, # 0x89 0x2030 PER MILLE SIGN - 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON - 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK - 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE - 65533, # 0x8D UNDEFINED - 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON - 65533, # 0x8F UNDEFINED - 65533, # 0x90 UNDEFINED - 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK - 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK - 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK - 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK - 8226, # 0x95 0x2022 BULLET - 8211, # 0x96 0x2013 EN DASH - 8212, # 0x97 0x2014 EM DASH - 732, # 0x98 0x02DC SMALL TILDE - 8482, # 0x99 0x2122 TRADE MARK SIGN - 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON - 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE - 65533, # 0x9D UNDEFINED - 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON - 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS -) - -xmlEntities = frozenset(('lt;', 'gt;', 'amp;', 'apos;', 'quot;')) - -entities = { - "AElig": "\xc6", - "AElig;": "\xc6", - "AMP": "&", - "AMP;": "&", - "Aacute": "\xc1", - "Aacute;": "\xc1", - "Abreve;": "\u0102", - "Acirc": "\xc2", - "Acirc;": "\xc2", - "Acy;": "\u0410", - "Afr;": "\U0001d504", - "Agrave": "\xc0", - "Agrave;": "\xc0", - "Alpha;": "\u0391", - "Amacr;": "\u0100", - "And;": "\u2a53", - "Aogon;": "\u0104", - "Aopf;": "\U0001d538", - "ApplyFunction;": "\u2061", - "Aring": "\xc5", - "Aring;": "\xc5", - "Ascr;": "\U0001d49c", - "Assign;": "\u2254", - "Atilde": "\xc3", - "Atilde;": "\xc3", - "Auml": "\xc4", - "Auml;": "\xc4", - "Backslash;": "\u2216", - "Barv;": "\u2ae7", - "Barwed;": "\u2306", - "Bcy;": "\u0411", - "Because;": "\u2235", - "Bernoullis;": "\u212c", - "Beta;": "\u0392", - "Bfr;": "\U0001d505", - "Bopf;": "\U0001d539", - "Breve;": "\u02d8", - "Bscr;": "\u212c", - "Bumpeq;": "\u224e", - "CHcy;": "\u0427", - "COPY": "\xa9", - "COPY;": "\xa9", - "Cacute;": "\u0106", - "Cap;": "\u22d2", - "CapitalDifferentialD;": "\u2145", - "Cayleys;": "\u212d", - "Ccaron;": "\u010c", - "Ccedil": "\xc7", - "Ccedil;": "\xc7", - "Ccirc;": "\u0108", - "Cconint;": "\u2230", - "Cdot;": "\u010a", - "Cedilla;": "\xb8", - "CenterDot;": "\xb7", - "Cfr;": "\u212d", - "Chi;": "\u03a7", - "CircleDot;": "\u2299", - "CircleMinus;": "\u2296", - "CirclePlus;": "\u2295", - "CircleTimes;": "\u2297", - "ClockwiseContourIntegral;": "\u2232", - "CloseCurlyDoubleQuote;": "\u201d", - "CloseCurlyQuote;": "\u2019", - "Colon;": "\u2237", - "Colone;": "\u2a74", - "Congruent;": "\u2261", - "Conint;": "\u222f", - "ContourIntegral;": "\u222e", - "Copf;": "\u2102", - "Coproduct;": "\u2210", - "CounterClockwiseContourIntegral;": "\u2233", - "Cross;": "\u2a2f", - "Cscr;": "\U0001d49e", - "Cup;": "\u22d3", - "CupCap;": "\u224d", - "DD;": "\u2145", - "DDotrahd;": "\u2911", - "DJcy;": "\u0402", - "DScy;": "\u0405", - "DZcy;": "\u040f", - "Dagger;": "\u2021", - "Darr;": "\u21a1", - "Dashv;": "\u2ae4", - "Dcaron;": "\u010e", - "Dcy;": "\u0414", - "Del;": "\u2207", - "Delta;": "\u0394", - "Dfr;": "\U0001d507", - "DiacriticalAcute;": "\xb4", - "DiacriticalDot;": "\u02d9", - "DiacriticalDoubleAcute;": "\u02dd", - "DiacriticalGrave;": "`", - "DiacriticalTilde;": "\u02dc", - "Diamond;": "\u22c4", - "DifferentialD;": "\u2146", - "Dopf;": "\U0001d53b", - "Dot;": "\xa8", - "DotDot;": "\u20dc", - "DotEqual;": "\u2250", - "DoubleContourIntegral;": "\u222f", - "DoubleDot;": "\xa8", - "DoubleDownArrow;": "\u21d3", - "DoubleLeftArrow;": "\u21d0", - "DoubleLeftRightArrow;": "\u21d4", - "DoubleLeftTee;": "\u2ae4", - "DoubleLongLeftArrow;": "\u27f8", - "DoubleLongLeftRightArrow;": "\u27fa", - "DoubleLongRightArrow;": "\u27f9", - "DoubleRightArrow;": "\u21d2", - "DoubleRightTee;": "\u22a8", - "DoubleUpArrow;": "\u21d1", - "DoubleUpDownArrow;": "\u21d5", - "DoubleVerticalBar;": "\u2225", - "DownArrow;": "\u2193", - "DownArrowBar;": "\u2913", - "DownArrowUpArrow;": "\u21f5", - "DownBreve;": "\u0311", - "DownLeftRightVector;": "\u2950", - "DownLeftTeeVector;": "\u295e", - "DownLeftVector;": "\u21bd", - "DownLeftVectorBar;": "\u2956", - "DownRightTeeVector;": "\u295f", - "DownRightVector;": "\u21c1", - "DownRightVectorBar;": "\u2957", - "DownTee;": "\u22a4", - "DownTeeArrow;": "\u21a7", - "Downarrow;": "\u21d3", - "Dscr;": "\U0001d49f", - "Dstrok;": "\u0110", - "ENG;": "\u014a", - "ETH": "\xd0", - "ETH;": "\xd0", - "Eacute": "\xc9", - "Eacute;": "\xc9", - "Ecaron;": "\u011a", - "Ecirc": "\xca", - "Ecirc;": "\xca", - "Ecy;": "\u042d", - "Edot;": "\u0116", - "Efr;": "\U0001d508", - "Egrave": "\xc8", - "Egrave;": "\xc8", - "Element;": "\u2208", - "Emacr;": "\u0112", - "EmptySmallSquare;": "\u25fb", - "EmptyVerySmallSquare;": "\u25ab", - "Eogon;": "\u0118", - "Eopf;": "\U0001d53c", - "Epsilon;": "\u0395", - "Equal;": "\u2a75", - "EqualTilde;": "\u2242", - "Equilibrium;": "\u21cc", - "Escr;": "\u2130", - "Esim;": "\u2a73", - "Eta;": "\u0397", - "Euml": "\xcb", - "Euml;": "\xcb", - "Exists;": "\u2203", - "ExponentialE;": "\u2147", - "Fcy;": "\u0424", - "Ffr;": "\U0001d509", - "FilledSmallSquare;": "\u25fc", - "FilledVerySmallSquare;": "\u25aa", - "Fopf;": "\U0001d53d", - "ForAll;": "\u2200", - "Fouriertrf;": "\u2131", - "Fscr;": "\u2131", - "GJcy;": "\u0403", - "GT": ">", - "GT;": ">", - "Gamma;": "\u0393", - "Gammad;": "\u03dc", - "Gbreve;": "\u011e", - "Gcedil;": "\u0122", - "Gcirc;": "\u011c", - "Gcy;": "\u0413", - "Gdot;": "\u0120", - "Gfr;": "\U0001d50a", - "Gg;": "\u22d9", - "Gopf;": "\U0001d53e", - "GreaterEqual;": "\u2265", - "GreaterEqualLess;": "\u22db", - "GreaterFullEqual;": "\u2267", - "GreaterGreater;": "\u2aa2", - "GreaterLess;": "\u2277", - "GreaterSlantEqual;": "\u2a7e", - "GreaterTilde;": "\u2273", - "Gscr;": "\U0001d4a2", - "Gt;": "\u226b", - "HARDcy;": "\u042a", - "Hacek;": "\u02c7", - "Hat;": "^", - "Hcirc;": "\u0124", - "Hfr;": "\u210c", - "HilbertSpace;": "\u210b", - "Hopf;": "\u210d", - "HorizontalLine;": "\u2500", - "Hscr;": "\u210b", - "Hstrok;": "\u0126", - "HumpDownHump;": "\u224e", - "HumpEqual;": "\u224f", - "IEcy;": "\u0415", - "IJlig;": "\u0132", - "IOcy;": "\u0401", - "Iacute": "\xcd", - "Iacute;": "\xcd", - "Icirc": "\xce", - "Icirc;": "\xce", - "Icy;": "\u0418", - "Idot;": "\u0130", - "Ifr;": "\u2111", - "Igrave": "\xcc", - "Igrave;": "\xcc", - "Im;": "\u2111", - "Imacr;": "\u012a", - "ImaginaryI;": "\u2148", - "Implies;": "\u21d2", - "Int;": "\u222c", - "Integral;": "\u222b", - "Intersection;": "\u22c2", - "InvisibleComma;": "\u2063", - "InvisibleTimes;": "\u2062", - "Iogon;": "\u012e", - "Iopf;": "\U0001d540", - "Iota;": "\u0399", - "Iscr;": "\u2110", - "Itilde;": "\u0128", - "Iukcy;": "\u0406", - "Iuml": "\xcf", - "Iuml;": "\xcf", - "Jcirc;": "\u0134", - "Jcy;": "\u0419", - "Jfr;": "\U0001d50d", - "Jopf;": "\U0001d541", - "Jscr;": "\U0001d4a5", - "Jsercy;": "\u0408", - "Jukcy;": "\u0404", - "KHcy;": "\u0425", - "KJcy;": "\u040c", - "Kappa;": "\u039a", - "Kcedil;": "\u0136", - "Kcy;": "\u041a", - "Kfr;": "\U0001d50e", - "Kopf;": "\U0001d542", - "Kscr;": "\U0001d4a6", - "LJcy;": "\u0409", - "LT": "<", - "LT;": "<", - "Lacute;": "\u0139", - "Lambda;": "\u039b", - "Lang;": "\u27ea", - "Laplacetrf;": "\u2112", - "Larr;": "\u219e", - "Lcaron;": "\u013d", - "Lcedil;": "\u013b", - "Lcy;": "\u041b", - "LeftAngleBracket;": "\u27e8", - "LeftArrow;": "\u2190", - "LeftArrowBar;": "\u21e4", - "LeftArrowRightArrow;": "\u21c6", - "LeftCeiling;": "\u2308", - "LeftDoubleBracket;": "\u27e6", - "LeftDownTeeVector;": "\u2961", - "LeftDownVector;": "\u21c3", - "LeftDownVectorBar;": "\u2959", - "LeftFloor;": "\u230a", - "LeftRightArrow;": "\u2194", - "LeftRightVector;": "\u294e", - "LeftTee;": "\u22a3", - "LeftTeeArrow;": "\u21a4", - "LeftTeeVector;": "\u295a", - "LeftTriangle;": "\u22b2", - "LeftTriangleBar;": "\u29cf", - "LeftTriangleEqual;": "\u22b4", - "LeftUpDownVector;": "\u2951", - "LeftUpTeeVector;": "\u2960", - "LeftUpVector;": "\u21bf", - "LeftUpVectorBar;": "\u2958", - "LeftVector;": "\u21bc", - "LeftVectorBar;": "\u2952", - "Leftarrow;": "\u21d0", - "Leftrightarrow;": "\u21d4", - "LessEqualGreater;": "\u22da", - "LessFullEqual;": "\u2266", - "LessGreater;": "\u2276", - "LessLess;": "\u2aa1", - "LessSlantEqual;": "\u2a7d", - "LessTilde;": "\u2272", - "Lfr;": "\U0001d50f", - "Ll;": "\u22d8", - "Lleftarrow;": "\u21da", - "Lmidot;": "\u013f", - "LongLeftArrow;": "\u27f5", - "LongLeftRightArrow;": "\u27f7", - "LongRightArrow;": "\u27f6", - "Longleftarrow;": "\u27f8", - "Longleftrightarrow;": "\u27fa", - "Longrightarrow;": "\u27f9", - "Lopf;": "\U0001d543", - "LowerLeftArrow;": "\u2199", - "LowerRightArrow;": "\u2198", - "Lscr;": "\u2112", - "Lsh;": "\u21b0", - "Lstrok;": "\u0141", - "Lt;": "\u226a", - "Map;": "\u2905", - "Mcy;": "\u041c", - "MediumSpace;": "\u205f", - "Mellintrf;": "\u2133", - "Mfr;": "\U0001d510", - "MinusPlus;": "\u2213", - "Mopf;": "\U0001d544", - "Mscr;": "\u2133", - "Mu;": "\u039c", - "NJcy;": "\u040a", - "Nacute;": "\u0143", - "Ncaron;": "\u0147", - "Ncedil;": "\u0145", - "Ncy;": "\u041d", - "NegativeMediumSpace;": "\u200b", - "NegativeThickSpace;": "\u200b", - "NegativeThinSpace;": "\u200b", - "NegativeVeryThinSpace;": "\u200b", - "NestedGreaterGreater;": "\u226b", - "NestedLessLess;": "\u226a", - "NewLine;": "\n", - "Nfr;": "\U0001d511", - "NoBreak;": "\u2060", - "NonBreakingSpace;": "\xa0", - "Nopf;": "\u2115", - "Not;": "\u2aec", - "NotCongruent;": "\u2262", - "NotCupCap;": "\u226d", - "NotDoubleVerticalBar;": "\u2226", - "NotElement;": "\u2209", - "NotEqual;": "\u2260", - "NotEqualTilde;": "\u2242\u0338", - "NotExists;": "\u2204", - "NotGreater;": "\u226f", - "NotGreaterEqual;": "\u2271", - "NotGreaterFullEqual;": "\u2267\u0338", - "NotGreaterGreater;": "\u226b\u0338", - "NotGreaterLess;": "\u2279", - "NotGreaterSlantEqual;": "\u2a7e\u0338", - "NotGreaterTilde;": "\u2275", - "NotHumpDownHump;": "\u224e\u0338", - "NotHumpEqual;": "\u224f\u0338", - "NotLeftTriangle;": "\u22ea", - "NotLeftTriangleBar;": "\u29cf\u0338", - "NotLeftTriangleEqual;": "\u22ec", - "NotLess;": "\u226e", - "NotLessEqual;": "\u2270", - "NotLessGreater;": "\u2278", - "NotLessLess;": "\u226a\u0338", - "NotLessSlantEqual;": "\u2a7d\u0338", - "NotLessTilde;": "\u2274", - "NotNestedGreaterGreater;": "\u2aa2\u0338", - "NotNestedLessLess;": "\u2aa1\u0338", - "NotPrecedes;": "\u2280", - "NotPrecedesEqual;": "\u2aaf\u0338", - "NotPrecedesSlantEqual;": "\u22e0", - "NotReverseElement;": "\u220c", - "NotRightTriangle;": "\u22eb", - "NotRightTriangleBar;": "\u29d0\u0338", - "NotRightTriangleEqual;": "\u22ed", - "NotSquareSubset;": "\u228f\u0338", - "NotSquareSubsetEqual;": "\u22e2", - "NotSquareSuperset;": "\u2290\u0338", - "NotSquareSupersetEqual;": "\u22e3", - "NotSubset;": "\u2282\u20d2", - "NotSubsetEqual;": "\u2288", - "NotSucceeds;": "\u2281", - "NotSucceedsEqual;": "\u2ab0\u0338", - "NotSucceedsSlantEqual;": "\u22e1", - "NotSucceedsTilde;": "\u227f\u0338", - "NotSuperset;": "\u2283\u20d2", - "NotSupersetEqual;": "\u2289", - "NotTilde;": "\u2241", - "NotTildeEqual;": "\u2244", - "NotTildeFullEqual;": "\u2247", - "NotTildeTilde;": "\u2249", - "NotVerticalBar;": "\u2224", - "Nscr;": "\U0001d4a9", - "Ntilde": "\xd1", - "Ntilde;": "\xd1", - "Nu;": "\u039d", - "OElig;": "\u0152", - "Oacute": "\xd3", - "Oacute;": "\xd3", - "Ocirc": "\xd4", - "Ocirc;": "\xd4", - "Ocy;": "\u041e", - "Odblac;": "\u0150", - "Ofr;": "\U0001d512", - "Ograve": "\xd2", - "Ograve;": "\xd2", - "Omacr;": "\u014c", - "Omega;": "\u03a9", - "Omicron;": "\u039f", - "Oopf;": "\U0001d546", - "OpenCurlyDoubleQuote;": "\u201c", - "OpenCurlyQuote;": "\u2018", - "Or;": "\u2a54", - "Oscr;": "\U0001d4aa", - "Oslash": "\xd8", - "Oslash;": "\xd8", - "Otilde": "\xd5", - "Otilde;": "\xd5", - "Otimes;": "\u2a37", - "Ouml": "\xd6", - "Ouml;": "\xd6", - "OverBar;": "\u203e", - "OverBrace;": "\u23de", - "OverBracket;": "\u23b4", - "OverParenthesis;": "\u23dc", - "PartialD;": "\u2202", - "Pcy;": "\u041f", - "Pfr;": "\U0001d513", - "Phi;": "\u03a6", - "Pi;": "\u03a0", - "PlusMinus;": "\xb1", - "Poincareplane;": "\u210c", - "Popf;": "\u2119", - "Pr;": "\u2abb", - "Precedes;": "\u227a", - "PrecedesEqual;": "\u2aaf", - "PrecedesSlantEqual;": "\u227c", - "PrecedesTilde;": "\u227e", - "Prime;": "\u2033", - "Product;": "\u220f", - "Proportion;": "\u2237", - "Proportional;": "\u221d", - "Pscr;": "\U0001d4ab", - "Psi;": "\u03a8", - "QUOT": "\"", - "QUOT;": "\"", - "Qfr;": "\U0001d514", - "Qopf;": "\u211a", - "Qscr;": "\U0001d4ac", - "RBarr;": "\u2910", - "REG": "\xae", - "REG;": "\xae", - "Racute;": "\u0154", - "Rang;": "\u27eb", - "Rarr;": "\u21a0", - "Rarrtl;": "\u2916", - "Rcaron;": "\u0158", - "Rcedil;": "\u0156", - "Rcy;": "\u0420", - "Re;": "\u211c", - "ReverseElement;": "\u220b", - "ReverseEquilibrium;": "\u21cb", - "ReverseUpEquilibrium;": "\u296f", - "Rfr;": "\u211c", - "Rho;": "\u03a1", - "RightAngleBracket;": "\u27e9", - "RightArrow;": "\u2192", - "RightArrowBar;": "\u21e5", - "RightArrowLeftArrow;": "\u21c4", - "RightCeiling;": "\u2309", - "RightDoubleBracket;": "\u27e7", - "RightDownTeeVector;": "\u295d", - "RightDownVector;": "\u21c2", - "RightDownVectorBar;": "\u2955", - "RightFloor;": "\u230b", - "RightTee;": "\u22a2", - "RightTeeArrow;": "\u21a6", - "RightTeeVector;": "\u295b", - "RightTriangle;": "\u22b3", - "RightTriangleBar;": "\u29d0", - "RightTriangleEqual;": "\u22b5", - "RightUpDownVector;": "\u294f", - "RightUpTeeVector;": "\u295c", - "RightUpVector;": "\u21be", - "RightUpVectorBar;": "\u2954", - "RightVector;": "\u21c0", - "RightVectorBar;": "\u2953", - "Rightarrow;": "\u21d2", - "Ropf;": "\u211d", - "RoundImplies;": "\u2970", - "Rrightarrow;": "\u21db", - "Rscr;": "\u211b", - "Rsh;": "\u21b1", - "RuleDelayed;": "\u29f4", - "SHCHcy;": "\u0429", - "SHcy;": "\u0428", - "SOFTcy;": "\u042c", - "Sacute;": "\u015a", - "Sc;": "\u2abc", - "Scaron;": "\u0160", - "Scedil;": "\u015e", - "Scirc;": "\u015c", - "Scy;": "\u0421", - "Sfr;": "\U0001d516", - "ShortDownArrow;": "\u2193", - "ShortLeftArrow;": "\u2190", - "ShortRightArrow;": "\u2192", - "ShortUpArrow;": "\u2191", - "Sigma;": "\u03a3", - "SmallCircle;": "\u2218", - "Sopf;": "\U0001d54a", - "Sqrt;": "\u221a", - "Square;": "\u25a1", - "SquareIntersection;": "\u2293", - "SquareSubset;": "\u228f", - "SquareSubsetEqual;": "\u2291", - "SquareSuperset;": "\u2290", - "SquareSupersetEqual;": "\u2292", - "SquareUnion;": "\u2294", - "Sscr;": "\U0001d4ae", - "Star;": "\u22c6", - "Sub;": "\u22d0", - "Subset;": "\u22d0", - "SubsetEqual;": "\u2286", - "Succeeds;": "\u227b", - "SucceedsEqual;": "\u2ab0", - "SucceedsSlantEqual;": "\u227d", - "SucceedsTilde;": "\u227f", - "SuchThat;": "\u220b", - "Sum;": "\u2211", - "Sup;": "\u22d1", - "Superset;": "\u2283", - "SupersetEqual;": "\u2287", - "Supset;": "\u22d1", - "THORN": "\xde", - "THORN;": "\xde", - "TRADE;": "\u2122", - "TSHcy;": "\u040b", - "TScy;": "\u0426", - "Tab;": "\t", - "Tau;": "\u03a4", - "Tcaron;": "\u0164", - "Tcedil;": "\u0162", - "Tcy;": "\u0422", - "Tfr;": "\U0001d517", - "Therefore;": "\u2234", - "Theta;": "\u0398", - "ThickSpace;": "\u205f\u200a", - "ThinSpace;": "\u2009", - "Tilde;": "\u223c", - "TildeEqual;": "\u2243", - "TildeFullEqual;": "\u2245", - "TildeTilde;": "\u2248", - "Topf;": "\U0001d54b", - "TripleDot;": "\u20db", - "Tscr;": "\U0001d4af", - "Tstrok;": "\u0166", - "Uacute": "\xda", - "Uacute;": "\xda", - "Uarr;": "\u219f", - "Uarrocir;": "\u2949", - "Ubrcy;": "\u040e", - "Ubreve;": "\u016c", - "Ucirc": "\xdb", - "Ucirc;": "\xdb", - "Ucy;": "\u0423", - "Udblac;": "\u0170", - "Ufr;": "\U0001d518", - "Ugrave": "\xd9", - "Ugrave;": "\xd9", - "Umacr;": "\u016a", - "UnderBar;": "_", - "UnderBrace;": "\u23df", - "UnderBracket;": "\u23b5", - "UnderParenthesis;": "\u23dd", - "Union;": "\u22c3", - "UnionPlus;": "\u228e", - "Uogon;": "\u0172", - "Uopf;": "\U0001d54c", - "UpArrow;": "\u2191", - "UpArrowBar;": "\u2912", - "UpArrowDownArrow;": "\u21c5", - "UpDownArrow;": "\u2195", - "UpEquilibrium;": "\u296e", - "UpTee;": "\u22a5", - "UpTeeArrow;": "\u21a5", - "Uparrow;": "\u21d1", - "Updownarrow;": "\u21d5", - "UpperLeftArrow;": "\u2196", - "UpperRightArrow;": "\u2197", - "Upsi;": "\u03d2", - "Upsilon;": "\u03a5", - "Uring;": "\u016e", - "Uscr;": "\U0001d4b0", - "Utilde;": "\u0168", - "Uuml": "\xdc", - "Uuml;": "\xdc", - "VDash;": "\u22ab", - "Vbar;": "\u2aeb", - "Vcy;": "\u0412", - "Vdash;": "\u22a9", - "Vdashl;": "\u2ae6", - "Vee;": "\u22c1", - "Verbar;": "\u2016", - "Vert;": "\u2016", - "VerticalBar;": "\u2223", - "VerticalLine;": "|", - "VerticalSeparator;": "\u2758", - "VerticalTilde;": "\u2240", - "VeryThinSpace;": "\u200a", - "Vfr;": "\U0001d519", - "Vopf;": "\U0001d54d", - "Vscr;": "\U0001d4b1", - "Vvdash;": "\u22aa", - "Wcirc;": "\u0174", - "Wedge;": "\u22c0", - "Wfr;": "\U0001d51a", - "Wopf;": "\U0001d54e", - "Wscr;": "\U0001d4b2", - "Xfr;": "\U0001d51b", - "Xi;": "\u039e", - "Xopf;": "\U0001d54f", - "Xscr;": "\U0001d4b3", - "YAcy;": "\u042f", - "YIcy;": "\u0407", - "YUcy;": "\u042e", - "Yacute": "\xdd", - "Yacute;": "\xdd", - "Ycirc;": "\u0176", - "Ycy;": "\u042b", - "Yfr;": "\U0001d51c", - "Yopf;": "\U0001d550", - "Yscr;": "\U0001d4b4", - "Yuml;": "\u0178", - "ZHcy;": "\u0416", - "Zacute;": "\u0179", - "Zcaron;": "\u017d", - "Zcy;": "\u0417", - "Zdot;": "\u017b", - "ZeroWidthSpace;": "\u200b", - "Zeta;": "\u0396", - "Zfr;": "\u2128", - "Zopf;": "\u2124", - "Zscr;": "\U0001d4b5", - "aacute": "\xe1", - "aacute;": "\xe1", - "abreve;": "\u0103", - "ac;": "\u223e", - "acE;": "\u223e\u0333", - "acd;": "\u223f", - "acirc": "\xe2", - "acirc;": "\xe2", - "acute": "\xb4", - "acute;": "\xb4", - "acy;": "\u0430", - "aelig": "\xe6", - "aelig;": "\xe6", - "af;": "\u2061", - "afr;": "\U0001d51e", - "agrave": "\xe0", - "agrave;": "\xe0", - "alefsym;": "\u2135", - "aleph;": "\u2135", - "alpha;": "\u03b1", - "amacr;": "\u0101", - "amalg;": "\u2a3f", - "amp": "&", - "amp;": "&", - "and;": "\u2227", - "andand;": "\u2a55", - "andd;": "\u2a5c", - "andslope;": "\u2a58", - "andv;": "\u2a5a", - "ang;": "\u2220", - "ange;": "\u29a4", - "angle;": "\u2220", - "angmsd;": "\u2221", - "angmsdaa;": "\u29a8", - "angmsdab;": "\u29a9", - "angmsdac;": "\u29aa", - "angmsdad;": "\u29ab", - "angmsdae;": "\u29ac", - "angmsdaf;": "\u29ad", - "angmsdag;": "\u29ae", - "angmsdah;": "\u29af", - "angrt;": "\u221f", - "angrtvb;": "\u22be", - "angrtvbd;": "\u299d", - "angsph;": "\u2222", - "angst;": "\xc5", - "angzarr;": "\u237c", - "aogon;": "\u0105", - "aopf;": "\U0001d552", - "ap;": "\u2248", - "apE;": "\u2a70", - "apacir;": "\u2a6f", - "ape;": "\u224a", - "apid;": "\u224b", - "apos;": "'", - "approx;": "\u2248", - "approxeq;": "\u224a", - "aring": "\xe5", - "aring;": "\xe5", - "ascr;": "\U0001d4b6", - "ast;": "*", - "asymp;": "\u2248", - "asympeq;": "\u224d", - "atilde": "\xe3", - "atilde;": "\xe3", - "auml": "\xe4", - "auml;": "\xe4", - "awconint;": "\u2233", - "awint;": "\u2a11", - "bNot;": "\u2aed", - "backcong;": "\u224c", - "backepsilon;": "\u03f6", - "backprime;": "\u2035", - "backsim;": "\u223d", - "backsimeq;": "\u22cd", - "barvee;": "\u22bd", - "barwed;": "\u2305", - "barwedge;": "\u2305", - "bbrk;": "\u23b5", - "bbrktbrk;": "\u23b6", - "bcong;": "\u224c", - "bcy;": "\u0431", - "bdquo;": "\u201e", - "becaus;": "\u2235", - "because;": "\u2235", - "bemptyv;": "\u29b0", - "bepsi;": "\u03f6", - "bernou;": "\u212c", - "beta;": "\u03b2", - "beth;": "\u2136", - "between;": "\u226c", - "bfr;": "\U0001d51f", - "bigcap;": "\u22c2", - "bigcirc;": "\u25ef", - "bigcup;": "\u22c3", - "bigodot;": "\u2a00", - "bigoplus;": "\u2a01", - "bigotimes;": "\u2a02", - "bigsqcup;": "\u2a06", - "bigstar;": "\u2605", - "bigtriangledown;": "\u25bd", - "bigtriangleup;": "\u25b3", - "biguplus;": "\u2a04", - "bigvee;": "\u22c1", - "bigwedge;": "\u22c0", - "bkarow;": "\u290d", - "blacklozenge;": "\u29eb", - "blacksquare;": "\u25aa", - "blacktriangle;": "\u25b4", - "blacktriangledown;": "\u25be", - "blacktriangleleft;": "\u25c2", - "blacktriangleright;": "\u25b8", - "blank;": "\u2423", - "blk12;": "\u2592", - "blk14;": "\u2591", - "blk34;": "\u2593", - "block;": "\u2588", - "bne;": "=\u20e5", - "bnequiv;": "\u2261\u20e5", - "bnot;": "\u2310", - "bopf;": "\U0001d553", - "bot;": "\u22a5", - "bottom;": "\u22a5", - "bowtie;": "\u22c8", - "boxDL;": "\u2557", - "boxDR;": "\u2554", - "boxDl;": "\u2556", - "boxDr;": "\u2553", - "boxH;": "\u2550", - "boxHD;": "\u2566", - "boxHU;": "\u2569", - "boxHd;": "\u2564", - "boxHu;": "\u2567", - "boxUL;": "\u255d", - "boxUR;": "\u255a", - "boxUl;": "\u255c", - "boxUr;": "\u2559", - "boxV;": "\u2551", - "boxVH;": "\u256c", - "boxVL;": "\u2563", - "boxVR;": "\u2560", - "boxVh;": "\u256b", - "boxVl;": "\u2562", - "boxVr;": "\u255f", - "boxbox;": "\u29c9", - "boxdL;": "\u2555", - "boxdR;": "\u2552", - "boxdl;": "\u2510", - "boxdr;": "\u250c", - "boxh;": "\u2500", - "boxhD;": "\u2565", - "boxhU;": "\u2568", - "boxhd;": "\u252c", - "boxhu;": "\u2534", - "boxminus;": "\u229f", - "boxplus;": "\u229e", - "boxtimes;": "\u22a0", - "boxuL;": "\u255b", - "boxuR;": "\u2558", - "boxul;": "\u2518", - "boxur;": "\u2514", - "boxv;": "\u2502", - "boxvH;": "\u256a", - "boxvL;": "\u2561", - "boxvR;": "\u255e", - "boxvh;": "\u253c", - "boxvl;": "\u2524", - "boxvr;": "\u251c", - "bprime;": "\u2035", - "breve;": "\u02d8", - "brvbar": "\xa6", - "brvbar;": "\xa6", - "bscr;": "\U0001d4b7", - "bsemi;": "\u204f", - "bsim;": "\u223d", - "bsime;": "\u22cd", - "bsol;": "\\", - "bsolb;": "\u29c5", - "bsolhsub;": "\u27c8", - "bull;": "\u2022", - "bullet;": "\u2022", - "bump;": "\u224e", - "bumpE;": "\u2aae", - "bumpe;": "\u224f", - "bumpeq;": "\u224f", - "cacute;": "\u0107", - "cap;": "\u2229", - "capand;": "\u2a44", - "capbrcup;": "\u2a49", - "capcap;": "\u2a4b", - "capcup;": "\u2a47", - "capdot;": "\u2a40", - "caps;": "\u2229\ufe00", - "caret;": "\u2041", - "caron;": "\u02c7", - "ccaps;": "\u2a4d", - "ccaron;": "\u010d", - "ccedil": "\xe7", - "ccedil;": "\xe7", - "ccirc;": "\u0109", - "ccups;": "\u2a4c", - "ccupssm;": "\u2a50", - "cdot;": "\u010b", - "cedil": "\xb8", - "cedil;": "\xb8", - "cemptyv;": "\u29b2", - "cent": "\xa2", - "cent;": "\xa2", - "centerdot;": "\xb7", - "cfr;": "\U0001d520", - "chcy;": "\u0447", - "check;": "\u2713", - "checkmark;": "\u2713", - "chi;": "\u03c7", - "cir;": "\u25cb", - "cirE;": "\u29c3", - "circ;": "\u02c6", - "circeq;": "\u2257", - "circlearrowleft;": "\u21ba", - "circlearrowright;": "\u21bb", - "circledR;": "\xae", - "circledS;": "\u24c8", - "circledast;": "\u229b", - "circledcirc;": "\u229a", - "circleddash;": "\u229d", - "cire;": "\u2257", - "cirfnint;": "\u2a10", - "cirmid;": "\u2aef", - "cirscir;": "\u29c2", - "clubs;": "\u2663", - "clubsuit;": "\u2663", - "colon;": ":", - "colone;": "\u2254", - "coloneq;": "\u2254", - "comma;": ",", - "commat;": "@", - "comp;": "\u2201", - "compfn;": "\u2218", - "complement;": "\u2201", - "complexes;": "\u2102", - "cong;": "\u2245", - "congdot;": "\u2a6d", - "conint;": "\u222e", - "copf;": "\U0001d554", - "coprod;": "\u2210", - "copy": "\xa9", - "copy;": "\xa9", - "copysr;": "\u2117", - "crarr;": "\u21b5", - "cross;": "\u2717", - "cscr;": "\U0001d4b8", - "csub;": "\u2acf", - "csube;": "\u2ad1", - "csup;": "\u2ad0", - "csupe;": "\u2ad2", - "ctdot;": "\u22ef", - "cudarrl;": "\u2938", - "cudarrr;": "\u2935", - "cuepr;": "\u22de", - "cuesc;": "\u22df", - "cularr;": "\u21b6", - "cularrp;": "\u293d", - "cup;": "\u222a", - "cupbrcap;": "\u2a48", - "cupcap;": "\u2a46", - "cupcup;": "\u2a4a", - "cupdot;": "\u228d", - "cupor;": "\u2a45", - "cups;": "\u222a\ufe00", - "curarr;": "\u21b7", - "curarrm;": "\u293c", - "curlyeqprec;": "\u22de", - "curlyeqsucc;": "\u22df", - "curlyvee;": "\u22ce", - "curlywedge;": "\u22cf", - "curren": "\xa4", - "curren;": "\xa4", - "curvearrowleft;": "\u21b6", - "curvearrowright;": "\u21b7", - "cuvee;": "\u22ce", - "cuwed;": "\u22cf", - "cwconint;": "\u2232", - "cwint;": "\u2231", - "cylcty;": "\u232d", - "dArr;": "\u21d3", - "dHar;": "\u2965", - "dagger;": "\u2020", - "daleth;": "\u2138", - "darr;": "\u2193", - "dash;": "\u2010", - "dashv;": "\u22a3", - "dbkarow;": "\u290f", - "dblac;": "\u02dd", - "dcaron;": "\u010f", - "dcy;": "\u0434", - "dd;": "\u2146", - "ddagger;": "\u2021", - "ddarr;": "\u21ca", - "ddotseq;": "\u2a77", - "deg": "\xb0", - "deg;": "\xb0", - "delta;": "\u03b4", - "demptyv;": "\u29b1", - "dfisht;": "\u297f", - "dfr;": "\U0001d521", - "dharl;": "\u21c3", - "dharr;": "\u21c2", - "diam;": "\u22c4", - "diamond;": "\u22c4", - "diamondsuit;": "\u2666", - "diams;": "\u2666", - "die;": "\xa8", - "digamma;": "\u03dd", - "disin;": "\u22f2", - "div;": "\xf7", - "divide": "\xf7", - "divide;": "\xf7", - "divideontimes;": "\u22c7", - "divonx;": "\u22c7", - "djcy;": "\u0452", - "dlcorn;": "\u231e", - "dlcrop;": "\u230d", - "dollar;": "$", - "dopf;": "\U0001d555", - "dot;": "\u02d9", - "doteq;": "\u2250", - "doteqdot;": "\u2251", - "dotminus;": "\u2238", - "dotplus;": "\u2214", - "dotsquare;": "\u22a1", - "doublebarwedge;": "\u2306", - "downarrow;": "\u2193", - "downdownarrows;": "\u21ca", - "downharpoonleft;": "\u21c3", - "downharpoonright;": "\u21c2", - "drbkarow;": "\u2910", - "drcorn;": "\u231f", - "drcrop;": "\u230c", - "dscr;": "\U0001d4b9", - "dscy;": "\u0455", - "dsol;": "\u29f6", - "dstrok;": "\u0111", - "dtdot;": "\u22f1", - "dtri;": "\u25bf", - "dtrif;": "\u25be", - "duarr;": "\u21f5", - "duhar;": "\u296f", - "dwangle;": "\u29a6", - "dzcy;": "\u045f", - "dzigrarr;": "\u27ff", - "eDDot;": "\u2a77", - "eDot;": "\u2251", - "eacute": "\xe9", - "eacute;": "\xe9", - "easter;": "\u2a6e", - "ecaron;": "\u011b", - "ecir;": "\u2256", - "ecirc": "\xea", - "ecirc;": "\xea", - "ecolon;": "\u2255", - "ecy;": "\u044d", - "edot;": "\u0117", - "ee;": "\u2147", - "efDot;": "\u2252", - "efr;": "\U0001d522", - "eg;": "\u2a9a", - "egrave": "\xe8", - "egrave;": "\xe8", - "egs;": "\u2a96", - "egsdot;": "\u2a98", - "el;": "\u2a99", - "elinters;": "\u23e7", - "ell;": "\u2113", - "els;": "\u2a95", - "elsdot;": "\u2a97", - "emacr;": "\u0113", - "empty;": "\u2205", - "emptyset;": "\u2205", - "emptyv;": "\u2205", - "emsp13;": "\u2004", - "emsp14;": "\u2005", - "emsp;": "\u2003", - "eng;": "\u014b", - "ensp;": "\u2002", - "eogon;": "\u0119", - "eopf;": "\U0001d556", - "epar;": "\u22d5", - "eparsl;": "\u29e3", - "eplus;": "\u2a71", - "epsi;": "\u03b5", - "epsilon;": "\u03b5", - "epsiv;": "\u03f5", - "eqcirc;": "\u2256", - "eqcolon;": "\u2255", - "eqsim;": "\u2242", - "eqslantgtr;": "\u2a96", - "eqslantless;": "\u2a95", - "equals;": "=", - "equest;": "\u225f", - "equiv;": "\u2261", - "equivDD;": "\u2a78", - "eqvparsl;": "\u29e5", - "erDot;": "\u2253", - "erarr;": "\u2971", - "escr;": "\u212f", - "esdot;": "\u2250", - "esim;": "\u2242", - "eta;": "\u03b7", - "eth": "\xf0", - "eth;": "\xf0", - "euml": "\xeb", - "euml;": "\xeb", - "euro;": "\u20ac", - "excl;": "!", - "exist;": "\u2203", - "expectation;": "\u2130", - "exponentiale;": "\u2147", - "fallingdotseq;": "\u2252", - "fcy;": "\u0444", - "female;": "\u2640", - "ffilig;": "\ufb03", - "fflig;": "\ufb00", - "ffllig;": "\ufb04", - "ffr;": "\U0001d523", - "filig;": "\ufb01", - "fjlig;": "fj", - "flat;": "\u266d", - "fllig;": "\ufb02", - "fltns;": "\u25b1", - "fnof;": "\u0192", - "fopf;": "\U0001d557", - "forall;": "\u2200", - "fork;": "\u22d4", - "forkv;": "\u2ad9", - "fpartint;": "\u2a0d", - "frac12": "\xbd", - "frac12;": "\xbd", - "frac13;": "\u2153", - "frac14": "\xbc", - "frac14;": "\xbc", - "frac15;": "\u2155", - "frac16;": "\u2159", - "frac18;": "\u215b", - "frac23;": "\u2154", - "frac25;": "\u2156", - "frac34": "\xbe", - "frac34;": "\xbe", - "frac35;": "\u2157", - "frac38;": "\u215c", - "frac45;": "\u2158", - "frac56;": "\u215a", - "frac58;": "\u215d", - "frac78;": "\u215e", - "frasl;": "\u2044", - "frown;": "\u2322", - "fscr;": "\U0001d4bb", - "gE;": "\u2267", - "gEl;": "\u2a8c", - "gacute;": "\u01f5", - "gamma;": "\u03b3", - "gammad;": "\u03dd", - "gap;": "\u2a86", - "gbreve;": "\u011f", - "gcirc;": "\u011d", - "gcy;": "\u0433", - "gdot;": "\u0121", - "ge;": "\u2265", - "gel;": "\u22db", - "geq;": "\u2265", - "geqq;": "\u2267", - "geqslant;": "\u2a7e", - "ges;": "\u2a7e", - "gescc;": "\u2aa9", - "gesdot;": "\u2a80", - "gesdoto;": "\u2a82", - "gesdotol;": "\u2a84", - "gesl;": "\u22db\ufe00", - "gesles;": "\u2a94", - "gfr;": "\U0001d524", - "gg;": "\u226b", - "ggg;": "\u22d9", - "gimel;": "\u2137", - "gjcy;": "\u0453", - "gl;": "\u2277", - "glE;": "\u2a92", - "gla;": "\u2aa5", - "glj;": "\u2aa4", - "gnE;": "\u2269", - "gnap;": "\u2a8a", - "gnapprox;": "\u2a8a", - "gne;": "\u2a88", - "gneq;": "\u2a88", - "gneqq;": "\u2269", - "gnsim;": "\u22e7", - "gopf;": "\U0001d558", - "grave;": "`", - "gscr;": "\u210a", - "gsim;": "\u2273", - "gsime;": "\u2a8e", - "gsiml;": "\u2a90", - "gt": ">", - "gt;": ">", - "gtcc;": "\u2aa7", - "gtcir;": "\u2a7a", - "gtdot;": "\u22d7", - "gtlPar;": "\u2995", - "gtquest;": "\u2a7c", - "gtrapprox;": "\u2a86", - "gtrarr;": "\u2978", - "gtrdot;": "\u22d7", - "gtreqless;": "\u22db", - "gtreqqless;": "\u2a8c", - "gtrless;": "\u2277", - "gtrsim;": "\u2273", - "gvertneqq;": "\u2269\ufe00", - "gvnE;": "\u2269\ufe00", - "hArr;": "\u21d4", - "hairsp;": "\u200a", - "half;": "\xbd", - "hamilt;": "\u210b", - "hardcy;": "\u044a", - "harr;": "\u2194", - "harrcir;": "\u2948", - "harrw;": "\u21ad", - "hbar;": "\u210f", - "hcirc;": "\u0125", - "hearts;": "\u2665", - "heartsuit;": "\u2665", - "hellip;": "\u2026", - "hercon;": "\u22b9", - "hfr;": "\U0001d525", - "hksearow;": "\u2925", - "hkswarow;": "\u2926", - "hoarr;": "\u21ff", - "homtht;": "\u223b", - "hookleftarrow;": "\u21a9", - "hookrightarrow;": "\u21aa", - "hopf;": "\U0001d559", - "horbar;": "\u2015", - "hscr;": "\U0001d4bd", - "hslash;": "\u210f", - "hstrok;": "\u0127", - "hybull;": "\u2043", - "hyphen;": "\u2010", - "iacute": "\xed", - "iacute;": "\xed", - "ic;": "\u2063", - "icirc": "\xee", - "icirc;": "\xee", - "icy;": "\u0438", - "iecy;": "\u0435", - "iexcl": "\xa1", - "iexcl;": "\xa1", - "iff;": "\u21d4", - "ifr;": "\U0001d526", - "igrave": "\xec", - "igrave;": "\xec", - "ii;": "\u2148", - "iiiint;": "\u2a0c", - "iiint;": "\u222d", - "iinfin;": "\u29dc", - "iiota;": "\u2129", - "ijlig;": "\u0133", - "imacr;": "\u012b", - "image;": "\u2111", - "imagline;": "\u2110", - "imagpart;": "\u2111", - "imath;": "\u0131", - "imof;": "\u22b7", - "imped;": "\u01b5", - "in;": "\u2208", - "incare;": "\u2105", - "infin;": "\u221e", - "infintie;": "\u29dd", - "inodot;": "\u0131", - "int;": "\u222b", - "intcal;": "\u22ba", - "integers;": "\u2124", - "intercal;": "\u22ba", - "intlarhk;": "\u2a17", - "intprod;": "\u2a3c", - "iocy;": "\u0451", - "iogon;": "\u012f", - "iopf;": "\U0001d55a", - "iota;": "\u03b9", - "iprod;": "\u2a3c", - "iquest": "\xbf", - "iquest;": "\xbf", - "iscr;": "\U0001d4be", - "isin;": "\u2208", - "isinE;": "\u22f9", - "isindot;": "\u22f5", - "isins;": "\u22f4", - "isinsv;": "\u22f3", - "isinv;": "\u2208", - "it;": "\u2062", - "itilde;": "\u0129", - "iukcy;": "\u0456", - "iuml": "\xef", - "iuml;": "\xef", - "jcirc;": "\u0135", - "jcy;": "\u0439", - "jfr;": "\U0001d527", - "jmath;": "\u0237", - "jopf;": "\U0001d55b", - "jscr;": "\U0001d4bf", - "jsercy;": "\u0458", - "jukcy;": "\u0454", - "kappa;": "\u03ba", - "kappav;": "\u03f0", - "kcedil;": "\u0137", - "kcy;": "\u043a", - "kfr;": "\U0001d528", - "kgreen;": "\u0138", - "khcy;": "\u0445", - "kjcy;": "\u045c", - "kopf;": "\U0001d55c", - "kscr;": "\U0001d4c0", - "lAarr;": "\u21da", - "lArr;": "\u21d0", - "lAtail;": "\u291b", - "lBarr;": "\u290e", - "lE;": "\u2266", - "lEg;": "\u2a8b", - "lHar;": "\u2962", - "lacute;": "\u013a", - "laemptyv;": "\u29b4", - "lagran;": "\u2112", - "lambda;": "\u03bb", - "lang;": "\u27e8", - "langd;": "\u2991", - "langle;": "\u27e8", - "lap;": "\u2a85", - "laquo": "\xab", - "laquo;": "\xab", - "larr;": "\u2190", - "larrb;": "\u21e4", - "larrbfs;": "\u291f", - "larrfs;": "\u291d", - "larrhk;": "\u21a9", - "larrlp;": "\u21ab", - "larrpl;": "\u2939", - "larrsim;": "\u2973", - "larrtl;": "\u21a2", - "lat;": "\u2aab", - "latail;": "\u2919", - "late;": "\u2aad", - "lates;": "\u2aad\ufe00", - "lbarr;": "\u290c", - "lbbrk;": "\u2772", - "lbrace;": "{", - "lbrack;": "[", - "lbrke;": "\u298b", - "lbrksld;": "\u298f", - "lbrkslu;": "\u298d", - "lcaron;": "\u013e", - "lcedil;": "\u013c", - "lceil;": "\u2308", - "lcub;": "{", - "lcy;": "\u043b", - "ldca;": "\u2936", - "ldquo;": "\u201c", - "ldquor;": "\u201e", - "ldrdhar;": "\u2967", - "ldrushar;": "\u294b", - "ldsh;": "\u21b2", - "le;": "\u2264", - "leftarrow;": "\u2190", - "leftarrowtail;": "\u21a2", - "leftharpoondown;": "\u21bd", - "leftharpoonup;": "\u21bc", - "leftleftarrows;": "\u21c7", - "leftrightarrow;": "\u2194", - "leftrightarrows;": "\u21c6", - "leftrightharpoons;": "\u21cb", - "leftrightsquigarrow;": "\u21ad", - "leftthreetimes;": "\u22cb", - "leg;": "\u22da", - "leq;": "\u2264", - "leqq;": "\u2266", - "leqslant;": "\u2a7d", - "les;": "\u2a7d", - "lescc;": "\u2aa8", - "lesdot;": "\u2a7f", - "lesdoto;": "\u2a81", - "lesdotor;": "\u2a83", - "lesg;": "\u22da\ufe00", - "lesges;": "\u2a93", - "lessapprox;": "\u2a85", - "lessdot;": "\u22d6", - "lesseqgtr;": "\u22da", - "lesseqqgtr;": "\u2a8b", - "lessgtr;": "\u2276", - "lesssim;": "\u2272", - "lfisht;": "\u297c", - "lfloor;": "\u230a", - "lfr;": "\U0001d529", - "lg;": "\u2276", - "lgE;": "\u2a91", - "lhard;": "\u21bd", - "lharu;": "\u21bc", - "lharul;": "\u296a", - "lhblk;": "\u2584", - "ljcy;": "\u0459", - "ll;": "\u226a", - "llarr;": "\u21c7", - "llcorner;": "\u231e", - "llhard;": "\u296b", - "lltri;": "\u25fa", - "lmidot;": "\u0140", - "lmoust;": "\u23b0", - "lmoustache;": "\u23b0", - "lnE;": "\u2268", - "lnap;": "\u2a89", - "lnapprox;": "\u2a89", - "lne;": "\u2a87", - "lneq;": "\u2a87", - "lneqq;": "\u2268", - "lnsim;": "\u22e6", - "loang;": "\u27ec", - "loarr;": "\u21fd", - "lobrk;": "\u27e6", - "longleftarrow;": "\u27f5", - "longleftrightarrow;": "\u27f7", - "longmapsto;": "\u27fc", - "longrightarrow;": "\u27f6", - "looparrowleft;": "\u21ab", - "looparrowright;": "\u21ac", - "lopar;": "\u2985", - "lopf;": "\U0001d55d", - "loplus;": "\u2a2d", - "lotimes;": "\u2a34", - "lowast;": "\u2217", - "lowbar;": "_", - "loz;": "\u25ca", - "lozenge;": "\u25ca", - "lozf;": "\u29eb", - "lpar;": "(", - "lparlt;": "\u2993", - "lrarr;": "\u21c6", - "lrcorner;": "\u231f", - "lrhar;": "\u21cb", - "lrhard;": "\u296d", - "lrm;": "\u200e", - "lrtri;": "\u22bf", - "lsaquo;": "\u2039", - "lscr;": "\U0001d4c1", - "lsh;": "\u21b0", - "lsim;": "\u2272", - "lsime;": "\u2a8d", - "lsimg;": "\u2a8f", - "lsqb;": "[", - "lsquo;": "\u2018", - "lsquor;": "\u201a", - "lstrok;": "\u0142", - "lt": "<", - "lt;": "<", - "ltcc;": "\u2aa6", - "ltcir;": "\u2a79", - "ltdot;": "\u22d6", - "lthree;": "\u22cb", - "ltimes;": "\u22c9", - "ltlarr;": "\u2976", - "ltquest;": "\u2a7b", - "ltrPar;": "\u2996", - "ltri;": "\u25c3", - "ltrie;": "\u22b4", - "ltrif;": "\u25c2", - "lurdshar;": "\u294a", - "luruhar;": "\u2966", - "lvertneqq;": "\u2268\ufe00", - "lvnE;": "\u2268\ufe00", - "mDDot;": "\u223a", - "macr": "\xaf", - "macr;": "\xaf", - "male;": "\u2642", - "malt;": "\u2720", - "maltese;": "\u2720", - "map;": "\u21a6", - "mapsto;": "\u21a6", - "mapstodown;": "\u21a7", - "mapstoleft;": "\u21a4", - "mapstoup;": "\u21a5", - "marker;": "\u25ae", - "mcomma;": "\u2a29", - "mcy;": "\u043c", - "mdash;": "\u2014", - "measuredangle;": "\u2221", - "mfr;": "\U0001d52a", - "mho;": "\u2127", - "micro": "\xb5", - "micro;": "\xb5", - "mid;": "\u2223", - "midast;": "*", - "midcir;": "\u2af0", - "middot": "\xb7", - "middot;": "\xb7", - "minus;": "\u2212", - "minusb;": "\u229f", - "minusd;": "\u2238", - "minusdu;": "\u2a2a", - "mlcp;": "\u2adb", - "mldr;": "\u2026", - "mnplus;": "\u2213", - "models;": "\u22a7", - "mopf;": "\U0001d55e", - "mp;": "\u2213", - "mscr;": "\U0001d4c2", - "mstpos;": "\u223e", - "mu;": "\u03bc", - "multimap;": "\u22b8", - "mumap;": "\u22b8", - "nGg;": "\u22d9\u0338", - "nGt;": "\u226b\u20d2", - "nGtv;": "\u226b\u0338", - "nLeftarrow;": "\u21cd", - "nLeftrightarrow;": "\u21ce", - "nLl;": "\u22d8\u0338", - "nLt;": "\u226a\u20d2", - "nLtv;": "\u226a\u0338", - "nRightarrow;": "\u21cf", - "nVDash;": "\u22af", - "nVdash;": "\u22ae", - "nabla;": "\u2207", - "nacute;": "\u0144", - "nang;": "\u2220\u20d2", - "nap;": "\u2249", - "napE;": "\u2a70\u0338", - "napid;": "\u224b\u0338", - "napos;": "\u0149", - "napprox;": "\u2249", - "natur;": "\u266e", - "natural;": "\u266e", - "naturals;": "\u2115", - "nbsp": "\xa0", - "nbsp;": "\xa0", - "nbump;": "\u224e\u0338", - "nbumpe;": "\u224f\u0338", - "ncap;": "\u2a43", - "ncaron;": "\u0148", - "ncedil;": "\u0146", - "ncong;": "\u2247", - "ncongdot;": "\u2a6d\u0338", - "ncup;": "\u2a42", - "ncy;": "\u043d", - "ndash;": "\u2013", - "ne;": "\u2260", - "neArr;": "\u21d7", - "nearhk;": "\u2924", - "nearr;": "\u2197", - "nearrow;": "\u2197", - "nedot;": "\u2250\u0338", - "nequiv;": "\u2262", - "nesear;": "\u2928", - "nesim;": "\u2242\u0338", - "nexist;": "\u2204", - "nexists;": "\u2204", - "nfr;": "\U0001d52b", - "ngE;": "\u2267\u0338", - "nge;": "\u2271", - "ngeq;": "\u2271", - "ngeqq;": "\u2267\u0338", - "ngeqslant;": "\u2a7e\u0338", - "nges;": "\u2a7e\u0338", - "ngsim;": "\u2275", - "ngt;": "\u226f", - "ngtr;": "\u226f", - "nhArr;": "\u21ce", - "nharr;": "\u21ae", - "nhpar;": "\u2af2", - "ni;": "\u220b", - "nis;": "\u22fc", - "nisd;": "\u22fa", - "niv;": "\u220b", - "njcy;": "\u045a", - "nlArr;": "\u21cd", - "nlE;": "\u2266\u0338", - "nlarr;": "\u219a", - "nldr;": "\u2025", - "nle;": "\u2270", - "nleftarrow;": "\u219a", - "nleftrightarrow;": "\u21ae", - "nleq;": "\u2270", - "nleqq;": "\u2266\u0338", - "nleqslant;": "\u2a7d\u0338", - "nles;": "\u2a7d\u0338", - "nless;": "\u226e", - "nlsim;": "\u2274", - "nlt;": "\u226e", - "nltri;": "\u22ea", - "nltrie;": "\u22ec", - "nmid;": "\u2224", - "nopf;": "\U0001d55f", - "not": "\xac", - "not;": "\xac", - "notin;": "\u2209", - "notinE;": "\u22f9\u0338", - "notindot;": "\u22f5\u0338", - "notinva;": "\u2209", - "notinvb;": "\u22f7", - "notinvc;": "\u22f6", - "notni;": "\u220c", - "notniva;": "\u220c", - "notnivb;": "\u22fe", - "notnivc;": "\u22fd", - "npar;": "\u2226", - "nparallel;": "\u2226", - "nparsl;": "\u2afd\u20e5", - "npart;": "\u2202\u0338", - "npolint;": "\u2a14", - "npr;": "\u2280", - "nprcue;": "\u22e0", - "npre;": "\u2aaf\u0338", - "nprec;": "\u2280", - "npreceq;": "\u2aaf\u0338", - "nrArr;": "\u21cf", - "nrarr;": "\u219b", - "nrarrc;": "\u2933\u0338", - "nrarrw;": "\u219d\u0338", - "nrightarrow;": "\u219b", - "nrtri;": "\u22eb", - "nrtrie;": "\u22ed", - "nsc;": "\u2281", - "nsccue;": "\u22e1", - "nsce;": "\u2ab0\u0338", - "nscr;": "\U0001d4c3", - "nshortmid;": "\u2224", - "nshortparallel;": "\u2226", - "nsim;": "\u2241", - "nsime;": "\u2244", - "nsimeq;": "\u2244", - "nsmid;": "\u2224", - "nspar;": "\u2226", - "nsqsube;": "\u22e2", - "nsqsupe;": "\u22e3", - "nsub;": "\u2284", - "nsubE;": "\u2ac5\u0338", - "nsube;": "\u2288", - "nsubset;": "\u2282\u20d2", - "nsubseteq;": "\u2288", - "nsubseteqq;": "\u2ac5\u0338", - "nsucc;": "\u2281", - "nsucceq;": "\u2ab0\u0338", - "nsup;": "\u2285", - "nsupE;": "\u2ac6\u0338", - "nsupe;": "\u2289", - "nsupset;": "\u2283\u20d2", - "nsupseteq;": "\u2289", - "nsupseteqq;": "\u2ac6\u0338", - "ntgl;": "\u2279", - "ntilde": "\xf1", - "ntilde;": "\xf1", - "ntlg;": "\u2278", - "ntriangleleft;": "\u22ea", - "ntrianglelefteq;": "\u22ec", - "ntriangleright;": "\u22eb", - "ntrianglerighteq;": "\u22ed", - "nu;": "\u03bd", - "num;": "#", - "numero;": "\u2116", - "numsp;": "\u2007", - "nvDash;": "\u22ad", - "nvHarr;": "\u2904", - "nvap;": "\u224d\u20d2", - "nvdash;": "\u22ac", - "nvge;": "\u2265\u20d2", - "nvgt;": ">\u20d2", - "nvinfin;": "\u29de", - "nvlArr;": "\u2902", - "nvle;": "\u2264\u20d2", - "nvlt;": "<\u20d2", - "nvltrie;": "\u22b4\u20d2", - "nvrArr;": "\u2903", - "nvrtrie;": "\u22b5\u20d2", - "nvsim;": "\u223c\u20d2", - "nwArr;": "\u21d6", - "nwarhk;": "\u2923", - "nwarr;": "\u2196", - "nwarrow;": "\u2196", - "nwnear;": "\u2927", - "oS;": "\u24c8", - "oacute": "\xf3", - "oacute;": "\xf3", - "oast;": "\u229b", - "ocir;": "\u229a", - "ocirc": "\xf4", - "ocirc;": "\xf4", - "ocy;": "\u043e", - "odash;": "\u229d", - "odblac;": "\u0151", - "odiv;": "\u2a38", - "odot;": "\u2299", - "odsold;": "\u29bc", - "oelig;": "\u0153", - "ofcir;": "\u29bf", - "ofr;": "\U0001d52c", - "ogon;": "\u02db", - "ograve": "\xf2", - "ograve;": "\xf2", - "ogt;": "\u29c1", - "ohbar;": "\u29b5", - "ohm;": "\u03a9", - "oint;": "\u222e", - "olarr;": "\u21ba", - "olcir;": "\u29be", - "olcross;": "\u29bb", - "oline;": "\u203e", - "olt;": "\u29c0", - "omacr;": "\u014d", - "omega;": "\u03c9", - "omicron;": "\u03bf", - "omid;": "\u29b6", - "ominus;": "\u2296", - "oopf;": "\U0001d560", - "opar;": "\u29b7", - "operp;": "\u29b9", - "oplus;": "\u2295", - "or;": "\u2228", - "orarr;": "\u21bb", - "ord;": "\u2a5d", - "order;": "\u2134", - "orderof;": "\u2134", - "ordf": "\xaa", - "ordf;": "\xaa", - "ordm": "\xba", - "ordm;": "\xba", - "origof;": "\u22b6", - "oror;": "\u2a56", - "orslope;": "\u2a57", - "orv;": "\u2a5b", - "oscr;": "\u2134", - "oslash": "\xf8", - "oslash;": "\xf8", - "osol;": "\u2298", - "otilde": "\xf5", - "otilde;": "\xf5", - "otimes;": "\u2297", - "otimesas;": "\u2a36", - "ouml": "\xf6", - "ouml;": "\xf6", - "ovbar;": "\u233d", - "par;": "\u2225", - "para": "\xb6", - "para;": "\xb6", - "parallel;": "\u2225", - "parsim;": "\u2af3", - "parsl;": "\u2afd", - "part;": "\u2202", - "pcy;": "\u043f", - "percnt;": "%", - "period;": ".", - "permil;": "\u2030", - "perp;": "\u22a5", - "pertenk;": "\u2031", - "pfr;": "\U0001d52d", - "phi;": "\u03c6", - "phiv;": "\u03d5", - "phmmat;": "\u2133", - "phone;": "\u260e", - "pi;": "\u03c0", - "pitchfork;": "\u22d4", - "piv;": "\u03d6", - "planck;": "\u210f", - "planckh;": "\u210e", - "plankv;": "\u210f", - "plus;": "+", - "plusacir;": "\u2a23", - "plusb;": "\u229e", - "pluscir;": "\u2a22", - "plusdo;": "\u2214", - "plusdu;": "\u2a25", - "pluse;": "\u2a72", - "plusmn": "\xb1", - "plusmn;": "\xb1", - "plussim;": "\u2a26", - "plustwo;": "\u2a27", - "pm;": "\xb1", - "pointint;": "\u2a15", - "popf;": "\U0001d561", - "pound": "\xa3", - "pound;": "\xa3", - "pr;": "\u227a", - "prE;": "\u2ab3", - "prap;": "\u2ab7", - "prcue;": "\u227c", - "pre;": "\u2aaf", - "prec;": "\u227a", - "precapprox;": "\u2ab7", - "preccurlyeq;": "\u227c", - "preceq;": "\u2aaf", - "precnapprox;": "\u2ab9", - "precneqq;": "\u2ab5", - "precnsim;": "\u22e8", - "precsim;": "\u227e", - "prime;": "\u2032", - "primes;": "\u2119", - "prnE;": "\u2ab5", - "prnap;": "\u2ab9", - "prnsim;": "\u22e8", - "prod;": "\u220f", - "profalar;": "\u232e", - "profline;": "\u2312", - "profsurf;": "\u2313", - "prop;": "\u221d", - "propto;": "\u221d", - "prsim;": "\u227e", - "prurel;": "\u22b0", - "pscr;": "\U0001d4c5", - "psi;": "\u03c8", - "puncsp;": "\u2008", - "qfr;": "\U0001d52e", - "qint;": "\u2a0c", - "qopf;": "\U0001d562", - "qprime;": "\u2057", - "qscr;": "\U0001d4c6", - "quaternions;": "\u210d", - "quatint;": "\u2a16", - "quest;": "?", - "questeq;": "\u225f", - "quot": "\"", - "quot;": "\"", - "rAarr;": "\u21db", - "rArr;": "\u21d2", - "rAtail;": "\u291c", - "rBarr;": "\u290f", - "rHar;": "\u2964", - "race;": "\u223d\u0331", - "racute;": "\u0155", - "radic;": "\u221a", - "raemptyv;": "\u29b3", - "rang;": "\u27e9", - "rangd;": "\u2992", - "range;": "\u29a5", - "rangle;": "\u27e9", - "raquo": "\xbb", - "raquo;": "\xbb", - "rarr;": "\u2192", - "rarrap;": "\u2975", - "rarrb;": "\u21e5", - "rarrbfs;": "\u2920", - "rarrc;": "\u2933", - "rarrfs;": "\u291e", - "rarrhk;": "\u21aa", - "rarrlp;": "\u21ac", - "rarrpl;": "\u2945", - "rarrsim;": "\u2974", - "rarrtl;": "\u21a3", - "rarrw;": "\u219d", - "ratail;": "\u291a", - "ratio;": "\u2236", - "rationals;": "\u211a", - "rbarr;": "\u290d", - "rbbrk;": "\u2773", - "rbrace;": "}", - "rbrack;": "]", - "rbrke;": "\u298c", - "rbrksld;": "\u298e", - "rbrkslu;": "\u2990", - "rcaron;": "\u0159", - "rcedil;": "\u0157", - "rceil;": "\u2309", - "rcub;": "}", - "rcy;": "\u0440", - "rdca;": "\u2937", - "rdldhar;": "\u2969", - "rdquo;": "\u201d", - "rdquor;": "\u201d", - "rdsh;": "\u21b3", - "real;": "\u211c", - "realine;": "\u211b", - "realpart;": "\u211c", - "reals;": "\u211d", - "rect;": "\u25ad", - "reg": "\xae", - "reg;": "\xae", - "rfisht;": "\u297d", - "rfloor;": "\u230b", - "rfr;": "\U0001d52f", - "rhard;": "\u21c1", - "rharu;": "\u21c0", - "rharul;": "\u296c", - "rho;": "\u03c1", - "rhov;": "\u03f1", - "rightarrow;": "\u2192", - "rightarrowtail;": "\u21a3", - "rightharpoondown;": "\u21c1", - "rightharpoonup;": "\u21c0", - "rightleftarrows;": "\u21c4", - "rightleftharpoons;": "\u21cc", - "rightrightarrows;": "\u21c9", - "rightsquigarrow;": "\u219d", - "rightthreetimes;": "\u22cc", - "ring;": "\u02da", - "risingdotseq;": "\u2253", - "rlarr;": "\u21c4", - "rlhar;": "\u21cc", - "rlm;": "\u200f", - "rmoust;": "\u23b1", - "rmoustache;": "\u23b1", - "rnmid;": "\u2aee", - "roang;": "\u27ed", - "roarr;": "\u21fe", - "robrk;": "\u27e7", - "ropar;": "\u2986", - "ropf;": "\U0001d563", - "roplus;": "\u2a2e", - "rotimes;": "\u2a35", - "rpar;": ")", - "rpargt;": "\u2994", - "rppolint;": "\u2a12", - "rrarr;": "\u21c9", - "rsaquo;": "\u203a", - "rscr;": "\U0001d4c7", - "rsh;": "\u21b1", - "rsqb;": "]", - "rsquo;": "\u2019", - "rsquor;": "\u2019", - "rthree;": "\u22cc", - "rtimes;": "\u22ca", - "rtri;": "\u25b9", - "rtrie;": "\u22b5", - "rtrif;": "\u25b8", - "rtriltri;": "\u29ce", - "ruluhar;": "\u2968", - "rx;": "\u211e", - "sacute;": "\u015b", - "sbquo;": "\u201a", - "sc;": "\u227b", - "scE;": "\u2ab4", - "scap;": "\u2ab8", - "scaron;": "\u0161", - "sccue;": "\u227d", - "sce;": "\u2ab0", - "scedil;": "\u015f", - "scirc;": "\u015d", - "scnE;": "\u2ab6", - "scnap;": "\u2aba", - "scnsim;": "\u22e9", - "scpolint;": "\u2a13", - "scsim;": "\u227f", - "scy;": "\u0441", - "sdot;": "\u22c5", - "sdotb;": "\u22a1", - "sdote;": "\u2a66", - "seArr;": "\u21d8", - "searhk;": "\u2925", - "searr;": "\u2198", - "searrow;": "\u2198", - "sect": "\xa7", - "sect;": "\xa7", - "semi;": ";", - "seswar;": "\u2929", - "setminus;": "\u2216", - "setmn;": "\u2216", - "sext;": "\u2736", - "sfr;": "\U0001d530", - "sfrown;": "\u2322", - "sharp;": "\u266f", - "shchcy;": "\u0449", - "shcy;": "\u0448", - "shortmid;": "\u2223", - "shortparallel;": "\u2225", - "shy": "\xad", - "shy;": "\xad", - "sigma;": "\u03c3", - "sigmaf;": "\u03c2", - "sigmav;": "\u03c2", - "sim;": "\u223c", - "simdot;": "\u2a6a", - "sime;": "\u2243", - "simeq;": "\u2243", - "simg;": "\u2a9e", - "simgE;": "\u2aa0", - "siml;": "\u2a9d", - "simlE;": "\u2a9f", - "simne;": "\u2246", - "simplus;": "\u2a24", - "simrarr;": "\u2972", - "slarr;": "\u2190", - "smallsetminus;": "\u2216", - "smashp;": "\u2a33", - "smeparsl;": "\u29e4", - "smid;": "\u2223", - "smile;": "\u2323", - "smt;": "\u2aaa", - "smte;": "\u2aac", - "smtes;": "\u2aac\ufe00", - "softcy;": "\u044c", - "sol;": "/", - "solb;": "\u29c4", - "solbar;": "\u233f", - "sopf;": "\U0001d564", - "spades;": "\u2660", - "spadesuit;": "\u2660", - "spar;": "\u2225", - "sqcap;": "\u2293", - "sqcaps;": "\u2293\ufe00", - "sqcup;": "\u2294", - "sqcups;": "\u2294\ufe00", - "sqsub;": "\u228f", - "sqsube;": "\u2291", - "sqsubset;": "\u228f", - "sqsubseteq;": "\u2291", - "sqsup;": "\u2290", - "sqsupe;": "\u2292", - "sqsupset;": "\u2290", - "sqsupseteq;": "\u2292", - "squ;": "\u25a1", - "square;": "\u25a1", - "squarf;": "\u25aa", - "squf;": "\u25aa", - "srarr;": "\u2192", - "sscr;": "\U0001d4c8", - "ssetmn;": "\u2216", - "ssmile;": "\u2323", - "sstarf;": "\u22c6", - "star;": "\u2606", - "starf;": "\u2605", - "straightepsilon;": "\u03f5", - "straightphi;": "\u03d5", - "strns;": "\xaf", - "sub;": "\u2282", - "subE;": "\u2ac5", - "subdot;": "\u2abd", - "sube;": "\u2286", - "subedot;": "\u2ac3", - "submult;": "\u2ac1", - "subnE;": "\u2acb", - "subne;": "\u228a", - "subplus;": "\u2abf", - "subrarr;": "\u2979", - "subset;": "\u2282", - "subseteq;": "\u2286", - "subseteqq;": "\u2ac5", - "subsetneq;": "\u228a", - "subsetneqq;": "\u2acb", - "subsim;": "\u2ac7", - "subsub;": "\u2ad5", - "subsup;": "\u2ad3", - "succ;": "\u227b", - "succapprox;": "\u2ab8", - "succcurlyeq;": "\u227d", - "succeq;": "\u2ab0", - "succnapprox;": "\u2aba", - "succneqq;": "\u2ab6", - "succnsim;": "\u22e9", - "succsim;": "\u227f", - "sum;": "\u2211", - "sung;": "\u266a", - "sup1": "\xb9", - "sup1;": "\xb9", - "sup2": "\xb2", - "sup2;": "\xb2", - "sup3": "\xb3", - "sup3;": "\xb3", - "sup;": "\u2283", - "supE;": "\u2ac6", - "supdot;": "\u2abe", - "supdsub;": "\u2ad8", - "supe;": "\u2287", - "supedot;": "\u2ac4", - "suphsol;": "\u27c9", - "suphsub;": "\u2ad7", - "suplarr;": "\u297b", - "supmult;": "\u2ac2", - "supnE;": "\u2acc", - "supne;": "\u228b", - "supplus;": "\u2ac0", - "supset;": "\u2283", - "supseteq;": "\u2287", - "supseteqq;": "\u2ac6", - "supsetneq;": "\u228b", - "supsetneqq;": "\u2acc", - "supsim;": "\u2ac8", - "supsub;": "\u2ad4", - "supsup;": "\u2ad6", - "swArr;": "\u21d9", - "swarhk;": "\u2926", - "swarr;": "\u2199", - "swarrow;": "\u2199", - "swnwar;": "\u292a", - "szlig": "\xdf", - "szlig;": "\xdf", - "target;": "\u2316", - "tau;": "\u03c4", - "tbrk;": "\u23b4", - "tcaron;": "\u0165", - "tcedil;": "\u0163", - "tcy;": "\u0442", - "tdot;": "\u20db", - "telrec;": "\u2315", - "tfr;": "\U0001d531", - "there4;": "\u2234", - "therefore;": "\u2234", - "theta;": "\u03b8", - "thetasym;": "\u03d1", - "thetav;": "\u03d1", - "thickapprox;": "\u2248", - "thicksim;": "\u223c", - "thinsp;": "\u2009", - "thkap;": "\u2248", - "thksim;": "\u223c", - "thorn": "\xfe", - "thorn;": "\xfe", - "tilde;": "\u02dc", - "times": "\xd7", - "times;": "\xd7", - "timesb;": "\u22a0", - "timesbar;": "\u2a31", - "timesd;": "\u2a30", - "tint;": "\u222d", - "toea;": "\u2928", - "top;": "\u22a4", - "topbot;": "\u2336", - "topcir;": "\u2af1", - "topf;": "\U0001d565", - "topfork;": "\u2ada", - "tosa;": "\u2929", - "tprime;": "\u2034", - "trade;": "\u2122", - "triangle;": "\u25b5", - "triangledown;": "\u25bf", - "triangleleft;": "\u25c3", - "trianglelefteq;": "\u22b4", - "triangleq;": "\u225c", - "triangleright;": "\u25b9", - "trianglerighteq;": "\u22b5", - "tridot;": "\u25ec", - "trie;": "\u225c", - "triminus;": "\u2a3a", - "triplus;": "\u2a39", - "trisb;": "\u29cd", - "tritime;": "\u2a3b", - "trpezium;": "\u23e2", - "tscr;": "\U0001d4c9", - "tscy;": "\u0446", - "tshcy;": "\u045b", - "tstrok;": "\u0167", - "twixt;": "\u226c", - "twoheadleftarrow;": "\u219e", - "twoheadrightarrow;": "\u21a0", - "uArr;": "\u21d1", - "uHar;": "\u2963", - "uacute": "\xfa", - "uacute;": "\xfa", - "uarr;": "\u2191", - "ubrcy;": "\u045e", - "ubreve;": "\u016d", - "ucirc": "\xfb", - "ucirc;": "\xfb", - "ucy;": "\u0443", - "udarr;": "\u21c5", - "udblac;": "\u0171", - "udhar;": "\u296e", - "ufisht;": "\u297e", - "ufr;": "\U0001d532", - "ugrave": "\xf9", - "ugrave;": "\xf9", - "uharl;": "\u21bf", - "uharr;": "\u21be", - "uhblk;": "\u2580", - "ulcorn;": "\u231c", - "ulcorner;": "\u231c", - "ulcrop;": "\u230f", - "ultri;": "\u25f8", - "umacr;": "\u016b", - "uml": "\xa8", - "uml;": "\xa8", - "uogon;": "\u0173", - "uopf;": "\U0001d566", - "uparrow;": "\u2191", - "updownarrow;": "\u2195", - "upharpoonleft;": "\u21bf", - "upharpoonright;": "\u21be", - "uplus;": "\u228e", - "upsi;": "\u03c5", - "upsih;": "\u03d2", - "upsilon;": "\u03c5", - "upuparrows;": "\u21c8", - "urcorn;": "\u231d", - "urcorner;": "\u231d", - "urcrop;": "\u230e", - "uring;": "\u016f", - "urtri;": "\u25f9", - "uscr;": "\U0001d4ca", - "utdot;": "\u22f0", - "utilde;": "\u0169", - "utri;": "\u25b5", - "utrif;": "\u25b4", - "uuarr;": "\u21c8", - "uuml": "\xfc", - "uuml;": "\xfc", - "uwangle;": "\u29a7", - "vArr;": "\u21d5", - "vBar;": "\u2ae8", - "vBarv;": "\u2ae9", - "vDash;": "\u22a8", - "vangrt;": "\u299c", - "varepsilon;": "\u03f5", - "varkappa;": "\u03f0", - "varnothing;": "\u2205", - "varphi;": "\u03d5", - "varpi;": "\u03d6", - "varpropto;": "\u221d", - "varr;": "\u2195", - "varrho;": "\u03f1", - "varsigma;": "\u03c2", - "varsubsetneq;": "\u228a\ufe00", - "varsubsetneqq;": "\u2acb\ufe00", - "varsupsetneq;": "\u228b\ufe00", - "varsupsetneqq;": "\u2acc\ufe00", - "vartheta;": "\u03d1", - "vartriangleleft;": "\u22b2", - "vartriangleright;": "\u22b3", - "vcy;": "\u0432", - "vdash;": "\u22a2", - "vee;": "\u2228", - "veebar;": "\u22bb", - "veeeq;": "\u225a", - "vellip;": "\u22ee", - "verbar;": "|", - "vert;": "|", - "vfr;": "\U0001d533", - "vltri;": "\u22b2", - "vnsub;": "\u2282\u20d2", - "vnsup;": "\u2283\u20d2", - "vopf;": "\U0001d567", - "vprop;": "\u221d", - "vrtri;": "\u22b3", - "vscr;": "\U0001d4cb", - "vsubnE;": "\u2acb\ufe00", - "vsubne;": "\u228a\ufe00", - "vsupnE;": "\u2acc\ufe00", - "vsupne;": "\u228b\ufe00", - "vzigzag;": "\u299a", - "wcirc;": "\u0175", - "wedbar;": "\u2a5f", - "wedge;": "\u2227", - "wedgeq;": "\u2259", - "weierp;": "\u2118", - "wfr;": "\U0001d534", - "wopf;": "\U0001d568", - "wp;": "\u2118", - "wr;": "\u2240", - "wreath;": "\u2240", - "wscr;": "\U0001d4cc", - "xcap;": "\u22c2", - "xcirc;": "\u25ef", - "xcup;": "\u22c3", - "xdtri;": "\u25bd", - "xfr;": "\U0001d535", - "xhArr;": "\u27fa", - "xharr;": "\u27f7", - "xi;": "\u03be", - "xlArr;": "\u27f8", - "xlarr;": "\u27f5", - "xmap;": "\u27fc", - "xnis;": "\u22fb", - "xodot;": "\u2a00", - "xopf;": "\U0001d569", - "xoplus;": "\u2a01", - "xotime;": "\u2a02", - "xrArr;": "\u27f9", - "xrarr;": "\u27f6", - "xscr;": "\U0001d4cd", - "xsqcup;": "\u2a06", - "xuplus;": "\u2a04", - "xutri;": "\u25b3", - "xvee;": "\u22c1", - "xwedge;": "\u22c0", - "yacute": "\xfd", - "yacute;": "\xfd", - "yacy;": "\u044f", - "ycirc;": "\u0177", - "ycy;": "\u044b", - "yen": "\xa5", - "yen;": "\xa5", - "yfr;": "\U0001d536", - "yicy;": "\u0457", - "yopf;": "\U0001d56a", - "yscr;": "\U0001d4ce", - "yucy;": "\u044e", - "yuml": "\xff", - "yuml;": "\xff", - "zacute;": "\u017a", - "zcaron;": "\u017e", - "zcy;": "\u0437", - "zdot;": "\u017c", - "zeetrf;": "\u2128", - "zeta;": "\u03b6", - "zfr;": "\U0001d537", - "zhcy;": "\u0436", - "zigrarr;": "\u21dd", - "zopf;": "\U0001d56b", - "zscr;": "\U0001d4cf", - "zwj;": "\u200d", - "zwnj;": "\u200c", -} - -replacementCharacters = { - 0x0: "\uFFFD", - 0x0d: "\u000D", - 0x80: "\u20AC", - 0x81: "\u0081", - 0x81: "\u0081", - 0x82: "\u201A", - 0x83: "\u0192", - 0x84: "\u201E", - 0x85: "\u2026", - 0x86: "\u2020", - 0x87: "\u2021", - 0x88: "\u02C6", - 0x89: "\u2030", - 0x8A: "\u0160", - 0x8B: "\u2039", - 0x8C: "\u0152", - 0x8D: "\u008D", - 0x8E: "\u017D", - 0x8F: "\u008F", - 0x90: "\u0090", - 0x91: "\u2018", - 0x92: "\u2019", - 0x93: "\u201C", - 0x94: "\u201D", - 0x95: "\u2022", - 0x96: "\u2013", - 0x97: "\u2014", - 0x98: "\u02DC", - 0x99: "\u2122", - 0x9A: "\u0161", - 0x9B: "\u203A", - 0x9C: "\u0153", - 0x9D: "\u009D", - 0x9E: "\u017E", - 0x9F: "\u0178", -} - -encodings = { - '437': 'cp437', - '850': 'cp850', - '852': 'cp852', - '855': 'cp855', - '857': 'cp857', - '860': 'cp860', - '861': 'cp861', - '862': 'cp862', - '863': 'cp863', - '865': 'cp865', - '866': 'cp866', - '869': 'cp869', - 'ansix341968': 'ascii', - 'ansix341986': 'ascii', - 'arabic': 'iso8859-6', - 'ascii': 'ascii', - 'asmo708': 'iso8859-6', - 'big5': 'big5', - 'big5hkscs': 'big5hkscs', - 'chinese': 'gbk', - 'cp037': 'cp037', - 'cp1026': 'cp1026', - 'cp154': 'ptcp154', - 'cp367': 'ascii', - 'cp424': 'cp424', - 'cp437': 'cp437', - 'cp500': 'cp500', - 'cp775': 'cp775', - 'cp819': 'windows-1252', - 'cp850': 'cp850', - 'cp852': 'cp852', - 'cp855': 'cp855', - 'cp857': 'cp857', - 'cp860': 'cp860', - 'cp861': 'cp861', - 'cp862': 'cp862', - 'cp863': 'cp863', - 'cp864': 'cp864', - 'cp865': 'cp865', - 'cp866': 'cp866', - 'cp869': 'cp869', - 'cp936': 'gbk', - 'cpgr': 'cp869', - 'cpis': 'cp861', - 'csascii': 'ascii', - 'csbig5': 'big5', - 'cseuckr': 'cp949', - 'cseucpkdfmtjapanese': 'euc_jp', - 'csgb2312': 'gbk', - 'cshproman8': 'hp-roman8', - 'csibm037': 'cp037', - 'csibm1026': 'cp1026', - 'csibm424': 'cp424', - 'csibm500': 'cp500', - 'csibm855': 'cp855', - 'csibm857': 'cp857', - 'csibm860': 'cp860', - 'csibm861': 'cp861', - 'csibm863': 'cp863', - 'csibm864': 'cp864', - 'csibm865': 'cp865', - 'csibm866': 'cp866', - 'csibm869': 'cp869', - 'csiso2022jp': 'iso2022_jp', - 'csiso2022jp2': 'iso2022_jp_2', - 'csiso2022kr': 'iso2022_kr', - 'csiso58gb231280': 'gbk', - 'csisolatin1': 'windows-1252', - 'csisolatin2': 'iso8859-2', - 'csisolatin3': 'iso8859-3', - 'csisolatin4': 'iso8859-4', - 'csisolatin5': 'windows-1254', - 'csisolatin6': 'iso8859-10', - 'csisolatinarabic': 'iso8859-6', - 'csisolatincyrillic': 'iso8859-5', - 'csisolatingreek': 'iso8859-7', - 'csisolatinhebrew': 'iso8859-8', - 'cskoi8r': 'koi8-r', - 'csksc56011987': 'cp949', - 'cspc775baltic': 'cp775', - 'cspc850multilingual': 'cp850', - 'cspc862latinhebrew': 'cp862', - 'cspc8codepage437': 'cp437', - 'cspcp852': 'cp852', - 'csptcp154': 'ptcp154', - 'csshiftjis': 'shift_jis', - 'csunicode11utf7': 'utf-7', - 'cyrillic': 'iso8859-5', - 'cyrillicasian': 'ptcp154', - 'ebcdiccpbe': 'cp500', - 'ebcdiccpca': 'cp037', - 'ebcdiccpch': 'cp500', - 'ebcdiccphe': 'cp424', - 'ebcdiccpnl': 'cp037', - 'ebcdiccpus': 'cp037', - 'ebcdiccpwt': 'cp037', - 'ecma114': 'iso8859-6', - 'ecma118': 'iso8859-7', - 'elot928': 'iso8859-7', - 'eucjp': 'euc_jp', - 'euckr': 'cp949', - 'extendedunixcodepackedformatforjapanese': 'euc_jp', - 'gb18030': 'gb18030', - 'gb2312': 'gbk', - 'gb231280': 'gbk', - 'gbk': 'gbk', - 'greek': 'iso8859-7', - 'greek8': 'iso8859-7', - 'hebrew': 'iso8859-8', - 'hproman8': 'hp-roman8', - 'hzgb2312': 'hz', - 'ibm037': 'cp037', - 'ibm1026': 'cp1026', - 'ibm367': 'ascii', - 'ibm424': 'cp424', - 'ibm437': 'cp437', - 'ibm500': 'cp500', - 'ibm775': 'cp775', - 'ibm819': 'windows-1252', - 'ibm850': 'cp850', - 'ibm852': 'cp852', - 'ibm855': 'cp855', - 'ibm857': 'cp857', - 'ibm860': 'cp860', - 'ibm861': 'cp861', - 'ibm862': 'cp862', - 'ibm863': 'cp863', - 'ibm864': 'cp864', - 'ibm865': 'cp865', - 'ibm866': 'cp866', - 'ibm869': 'cp869', - 'iso2022jp': 'iso2022_jp', - 'iso2022jp2': 'iso2022_jp_2', - 'iso2022kr': 'iso2022_kr', - 'iso646irv1991': 'ascii', - 'iso646us': 'ascii', - 'iso88591': 'windows-1252', - 'iso885910': 'iso8859-10', - 'iso8859101992': 'iso8859-10', - 'iso885911987': 'windows-1252', - 'iso885913': 'iso8859-13', - 'iso885914': 'iso8859-14', - 'iso8859141998': 'iso8859-14', - 'iso885915': 'iso8859-15', - 'iso885916': 'iso8859-16', - 'iso8859162001': 'iso8859-16', - 'iso88592': 'iso8859-2', - 'iso885921987': 'iso8859-2', - 'iso88593': 'iso8859-3', - 'iso885931988': 'iso8859-3', - 'iso88594': 'iso8859-4', - 'iso885941988': 'iso8859-4', - 'iso88595': 'iso8859-5', - 'iso885951988': 'iso8859-5', - 'iso88596': 'iso8859-6', - 'iso885961987': 'iso8859-6', - 'iso88597': 'iso8859-7', - 'iso885971987': 'iso8859-7', - 'iso88598': 'iso8859-8', - 'iso885981988': 'iso8859-8', - 'iso88599': 'windows-1254', - 'iso885991989': 'windows-1254', - 'isoceltic': 'iso8859-14', - 'isoir100': 'windows-1252', - 'isoir101': 'iso8859-2', - 'isoir109': 'iso8859-3', - 'isoir110': 'iso8859-4', - 'isoir126': 'iso8859-7', - 'isoir127': 'iso8859-6', - 'isoir138': 'iso8859-8', - 'isoir144': 'iso8859-5', - 'isoir148': 'windows-1254', - 'isoir149': 'cp949', - 'isoir157': 'iso8859-10', - 'isoir199': 'iso8859-14', - 'isoir226': 'iso8859-16', - 'isoir58': 'gbk', - 'isoir6': 'ascii', - 'koi8r': 'koi8-r', - 'koi8u': 'koi8-u', - 'korean': 'cp949', - 'ksc5601': 'cp949', - 'ksc56011987': 'cp949', - 'ksc56011989': 'cp949', - 'l1': 'windows-1252', - 'l10': 'iso8859-16', - 'l2': 'iso8859-2', - 'l3': 'iso8859-3', - 'l4': 'iso8859-4', - 'l5': 'windows-1254', - 'l6': 'iso8859-10', - 'l8': 'iso8859-14', - 'latin1': 'windows-1252', - 'latin10': 'iso8859-16', - 'latin2': 'iso8859-2', - 'latin3': 'iso8859-3', - 'latin4': 'iso8859-4', - 'latin5': 'windows-1254', - 'latin6': 'iso8859-10', - 'latin8': 'iso8859-14', - 'latin9': 'iso8859-15', - 'ms936': 'gbk', - 'mskanji': 'shift_jis', - 'pt154': 'ptcp154', - 'ptcp154': 'ptcp154', - 'r8': 'hp-roman8', - 'roman8': 'hp-roman8', - 'shiftjis': 'shift_jis', - 'tis620': 'cp874', - 'unicode11utf7': 'utf-7', - 'us': 'ascii', - 'usascii': 'ascii', - 'utf16': 'utf-16', - 'utf16be': 'utf-16-be', - 'utf16le': 'utf-16-le', - 'utf8': 'utf-8', - 'windows1250': 'cp1250', - 'windows1251': 'cp1251', - 'windows1252': 'cp1252', - 'windows1253': 'cp1253', - 'windows1254': 'cp1254', - 'windows1255': 'cp1255', - 'windows1256': 'cp1256', - 'windows1257': 'cp1257', - 'windows1258': 'cp1258', - 'windows936': 'gbk', - 'x-x-big5': 'big5'} - -tokenTypes = { - "Doctype": 0, - "Characters": 1, - "SpaceCharacters": 2, - "StartTag": 3, - "EndTag": 4, - "EmptyTag": 5, - "Comment": 6, - "ParseError": 7 -} - -tagTokenTypes = frozenset((tokenTypes["StartTag"], tokenTypes["EndTag"], - tokenTypes["EmptyTag"])) - - -prefixes = dict([(v, k) for k, v in namespaces.items()]) -prefixes["http://www.w3.org/1998/Math/MathML"] = "math" - - -class DataLossWarning(UserWarning): - pass - - -class ReparseException(Exception): - pass diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/__init__.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/_base.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/_base.py deleted file mode 100644 index c7dbaed0fa..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/filters/_base.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - - -class Filter(object): - def __init__(self, source): - self.source = source - - def __iter__(self): - return iter(self.source) - - def __getattr__(self, name): - return getattr(self.source, name) diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py deleted file mode 100644 index fed6996c1d..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base - -try: - from collections import OrderedDict -except ImportError: - from ordereddict import OrderedDict - - -class Filter(_base.Filter): - def __iter__(self): - for token in _base.Filter.__iter__(self): - if token["type"] in ("StartTag", "EmptyTag"): - attrs = OrderedDict() - for name, value in sorted(token["data"].items(), - key=lambda x: x[0]): - attrs[name] = value - token["data"] = attrs - yield token diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py deleted file mode 100644 index ca33b70b53..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base - - -class Filter(_base.Filter): - def __init__(self, source, encoding): - _base.Filter.__init__(self, source) - self.encoding = encoding - - def __iter__(self): - state = "pre_head" - meta_found = (self.encoding is None) - pending = [] - - for token in _base.Filter.__iter__(self): - type = token["type"] - if type == "StartTag": - if token["name"].lower() == "head": - state = "in_head" - - elif type == "EmptyTag": - if token["name"].lower() == "meta": - # replace charset with actual encoding - has_http_equiv_content_type = False - for (namespace, name), value in token["data"].items(): - if namespace is not None: - continue - elif name.lower() == 'charset': - token["data"][(namespace, name)] = self.encoding - meta_found = True - break - elif name == 'http-equiv' and value.lower() == 'content-type': - has_http_equiv_content_type = True - else: - if has_http_equiv_content_type and (None, "content") in token["data"]: - token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding - meta_found = True - - elif token["name"].lower() == "head" and not meta_found: - # insert meta into empty head - yield {"type": "StartTag", "name": "head", - "data": token["data"]} - yield {"type": "EmptyTag", "name": "meta", - "data": {(None, "charset"): self.encoding}} - yield {"type": "EndTag", "name": "head"} - meta_found = True - continue - - elif type == "EndTag": - if token["name"].lower() == "head" and pending: - # insert meta into head (if necessary) and flush pending queue - yield pending.pop(0) - if not meta_found: - yield {"type": "EmptyTag", "name": "meta", - "data": {(None, "charset"): self.encoding}} - while pending: - yield pending.pop(0) - meta_found = True - state = "post_head" - - if state == "in_head": - pending.append(token) - else: - yield token diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/lint.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/lint.py deleted file mode 100644 index 83ad63971d..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/filters/lint.py +++ /dev/null @@ -1,93 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from gettext import gettext -_ = gettext - -from . import _base -from ..constants import cdataElements, rcdataElements, voidElements - -from ..constants import spaceCharacters -spaceCharacters = "".join(spaceCharacters) - - -class LintError(Exception): - pass - - -class Filter(_base.Filter): - def __iter__(self): - open_elements = [] - contentModelFlag = "PCDATA" - for token in _base.Filter.__iter__(self): - type = token["type"] - if type in ("StartTag", "EmptyTag"): - name = token["name"] - if contentModelFlag != "PCDATA": - raise LintError(_("StartTag not in PCDATA content model flag: %s") % name) - if not isinstance(name, str): - raise LintError(_("Tag name is not a string: %r") % name) - if not name: - raise LintError(_("Empty tag name")) - if type == "StartTag" and name in voidElements: - raise LintError(_("Void element reported as StartTag token: %s") % name) - elif type == "EmptyTag" and name not in voidElements: - raise LintError(_("Non-void element reported as EmptyTag token: %s") % token["name"]) - if type == "StartTag": - open_elements.append(name) - for name, value in token["data"]: - if not isinstance(name, str): - raise LintError(_("Attribute name is not a string: %r") % name) - if not name: - raise LintError(_("Empty attribute name")) - if not isinstance(value, str): - raise LintError(_("Attribute value is not a string: %r") % value) - if name in cdataElements: - contentModelFlag = "CDATA" - elif name in rcdataElements: - contentModelFlag = "RCDATA" - elif name == "plaintext": - contentModelFlag = "PLAINTEXT" - - elif type == "EndTag": - name = token["name"] - if not isinstance(name, str): - raise LintError(_("Tag name is not a string: %r") % name) - if not name: - raise LintError(_("Empty tag name")) - if name in voidElements: - raise LintError(_("Void element reported as EndTag token: %s") % name) - start_name = open_elements.pop() - if start_name != name: - raise LintError(_("EndTag (%s) does not match StartTag (%s)") % (name, start_name)) - contentModelFlag = "PCDATA" - - elif type == "Comment": - if contentModelFlag != "PCDATA": - raise LintError(_("Comment not in PCDATA content model flag")) - - elif type in ("Characters", "SpaceCharacters"): - data = token["data"] - if not isinstance(data, str): - raise LintError(_("Attribute name is not a string: %r") % data) - if not data: - raise LintError(_("%s token with empty data") % type) - if type == "SpaceCharacters": - data = data.strip(spaceCharacters) - if data: - raise LintError(_("Non-space character(s) found in SpaceCharacters token: ") % data) - - elif type == "Doctype": - name = token["name"] - if contentModelFlag != "PCDATA": - raise LintError(_("Doctype not in PCDATA content model flag: %s") % name) - if not isinstance(name, str): - raise LintError(_("Tag name is not a string: %r") % name) - # XXX: what to do with token["data"] ? - - elif type in ("ParseError", "SerializeError"): - pass - - else: - raise LintError(_("Unknown token type: %s") % type) - - yield token diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py deleted file mode 100644 index fefe0b3097..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py +++ /dev/null @@ -1,205 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base - - -class Filter(_base.Filter): - def slider(self): - previous1 = previous2 = None - for token in self.source: - if previous1 is not None: - yield previous2, previous1, token - previous2 = previous1 - previous1 = token - yield previous2, previous1, None - - def __iter__(self): - for previous, token, next in self.slider(): - type = token["type"] - if type == "StartTag": - if (token["data"] or - not self.is_optional_start(token["name"], previous, next)): - yield token - elif type == "EndTag": - if not self.is_optional_end(token["name"], next): - yield token - else: - yield token - - def is_optional_start(self, tagname, previous, next): - type = next and next["type"] or None - if tagname in 'html': - # An html element's start tag may be omitted if the first thing - # inside the html element is not a space character or a comment. - return type not in ("Comment", "SpaceCharacters") - elif tagname == 'head': - # A head element's start tag may be omitted if the first thing - # inside the head element is an element. - # XXX: we also omit the start tag if the head element is empty - if type in ("StartTag", "EmptyTag"): - return True - elif type == "EndTag": - return next["name"] == "head" - elif tagname == 'body': - # A body element's start tag may be omitted if the first thing - # inside the body element is not a space character or a comment, - # except if the first thing inside the body element is a script - # or style element and the node immediately preceding the body - # element is a head element whose end tag has been omitted. - if type in ("Comment", "SpaceCharacters"): - return False - elif type == "StartTag": - # XXX: we do not look at the preceding event, so we never omit - # the body element's start tag if it's followed by a script or - # a style element. - return next["name"] not in ('script', 'style') - else: - return True - elif tagname == 'colgroup': - # A colgroup element's start tag may be omitted if the first thing - # inside the colgroup element is a col element, and if the element - # is not immediately preceeded by another colgroup element whose - # end tag has been omitted. - if type in ("StartTag", "EmptyTag"): - # XXX: we do not look at the preceding event, so instead we never - # omit the colgroup element's end tag when it is immediately - # followed by another colgroup element. See is_optional_end. - return next["name"] == "col" - else: - return False - elif tagname == 'tbody': - # A tbody element's start tag may be omitted if the first thing - # inside the tbody element is a tr element, and if the element is - # not immediately preceeded by a tbody, thead, or tfoot element - # whose end tag has been omitted. - if type == "StartTag": - # omit the thead and tfoot elements' end tag when they are - # immediately followed by a tbody element. See is_optional_end. - if previous and previous['type'] == 'EndTag' and \ - previous['name'] in ('tbody', 'thead', 'tfoot'): - return False - return next["name"] == 'tr' - else: - return False - return False - - def is_optional_end(self, tagname, next): - type = next and next["type"] or None - if tagname in ('html', 'head', 'body'): - # An html element's end tag may be omitted if the html element - # is not immediately followed by a space character or a comment. - return type not in ("Comment", "SpaceCharacters") - elif tagname in ('li', 'optgroup', 'tr'): - # A li element's end tag may be omitted if the li element is - # immediately followed by another li element or if there is - # no more content in the parent element. - # An optgroup element's end tag may be omitted if the optgroup - # element is immediately followed by another optgroup element, - # or if there is no more content in the parent element. - # A tr element's end tag may be omitted if the tr element is - # immediately followed by another tr element, or if there is - # no more content in the parent element. - if type == "StartTag": - return next["name"] == tagname - else: - return type == "EndTag" or type is None - elif tagname in ('dt', 'dd'): - # A dt element's end tag may be omitted if the dt element is - # immediately followed by another dt element or a dd element. - # A dd element's end tag may be omitted if the dd element is - # immediately followed by another dd element or a dt element, - # or if there is no more content in the parent element. - if type == "StartTag": - return next["name"] in ('dt', 'dd') - elif tagname == 'dd': - return type == "EndTag" or type is None - else: - return False - elif tagname == 'p': - # A p element's end tag may be omitted if the p element is - # immediately followed by an address, article, aside, - # blockquote, datagrid, dialog, dir, div, dl, fieldset, - # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu, - # nav, ol, p, pre, section, table, or ul, element, or if - # there is no more content in the parent element. - if type in ("StartTag", "EmptyTag"): - return next["name"] in ('address', 'article', 'aside', - 'blockquote', 'datagrid', 'dialog', - 'dir', 'div', 'dl', 'fieldset', 'footer', - 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', - 'header', 'hr', 'menu', 'nav', 'ol', - 'p', 'pre', 'section', 'table', 'ul') - else: - return type == "EndTag" or type is None - elif tagname == 'option': - # An option element's end tag may be omitted if the option - # element is immediately followed by another option element, - # or if it is immediately followed by an optgroup - # element, or if there is no more content in the parent - # element. - if type == "StartTag": - return next["name"] in ('option', 'optgroup') - else: - return type == "EndTag" or type is None - elif tagname in ('rt', 'rp'): - # An rt element's end tag may be omitted if the rt element is - # immediately followed by an rt or rp element, or if there is - # no more content in the parent element. - # An rp element's end tag may be omitted if the rp element is - # immediately followed by an rt or rp element, or if there is - # no more content in the parent element. - if type == "StartTag": - return next["name"] in ('rt', 'rp') - else: - return type == "EndTag" or type is None - elif tagname == 'colgroup': - # A colgroup element's end tag may be omitted if the colgroup - # element is not immediately followed by a space character or - # a comment. - if type in ("Comment", "SpaceCharacters"): - return False - elif type == "StartTag": - # XXX: we also look for an immediately following colgroup - # element. See is_optional_start. - return next["name"] != 'colgroup' - else: - return True - elif tagname in ('thead', 'tbody'): - # A thead element's end tag may be omitted if the thead element - # is immediately followed by a tbody or tfoot element. - # A tbody element's end tag may be omitted if the tbody element - # is immediately followed by a tbody or tfoot element, or if - # there is no more content in the parent element. - # A tfoot element's end tag may be omitted if the tfoot element - # is immediately followed by a tbody element, or if there is no - # more content in the parent element. - # XXX: we never omit the end tag when the following element is - # a tbody. See is_optional_start. - if type == "StartTag": - return next["name"] in ['tbody', 'tfoot'] - elif tagname == 'tbody': - return type == "EndTag" or type is None - else: - return False - elif tagname == 'tfoot': - # A tfoot element's end tag may be omitted if the tfoot element - # is immediately followed by a tbody element, or if there is no - # more content in the parent element. - # XXX: we never omit the end tag when the following element is - # a tbody. See is_optional_start. - if type == "StartTag": - return next["name"] == 'tbody' - else: - return type == "EndTag" or type is None - elif tagname in ('td', 'th'): - # A td element's end tag may be omitted if the td element is - # immediately followed by a td or th element, or if there is - # no more content in the parent element. - # A th element's end tag may be omitted if the th element is - # immediately followed by a td or th element, or if there is - # no more content in the parent element. - if type == "StartTag": - return next["name"] in ('td', 'th') - else: - return type == "EndTag" or type is None - return False diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py deleted file mode 100644 index b206b54e7a..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -from . import _base -from ..sanitizer import HTMLSanitizerMixin - - -class Filter(_base.Filter, HTMLSanitizerMixin): - def __iter__(self): - for token in _base.Filter.__iter__(self): - token = self.sanitize_token(token) - if token: - yield token diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py b/awx/lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py deleted file mode 100644 index dfc60eebd3..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals - -import re - -from . import _base -from ..constants import rcdataElements, spaceCharacters -spaceCharacters = "".join(spaceCharacters) - -SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) - - -class Filter(_base.Filter): - - spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) - - def __iter__(self): - preserve = 0 - for token in _base.Filter.__iter__(self): - type = token["type"] - if type == "StartTag" \ - and (preserve or token["name"] in self.spacePreserveElements): - preserve += 1 - - elif type == "EndTag" and preserve: - preserve -= 1 - - elif not preserve and type == "SpaceCharacters" and token["data"]: - # Test on token["data"] above to not introduce spaces where there were not - token["data"] = " " - - elif not preserve and type == "Characters": - token["data"] = collapse_spaces(token["data"]) - - yield token - - -def collapse_spaces(text): - return SPACES_REGEX.sub(' ', text) diff --git a/awx/lib/site-packages/pip/_vendor/html5lib/html5parser.py b/awx/lib/site-packages/pip/_vendor/html5lib/html5parser.py deleted file mode 100644 index 8a5acfeb02..0000000000 --- a/awx/lib/site-packages/pip/_vendor/html5lib/html5parser.py +++ /dev/null @@ -1,2725 +0,0 @@ -from __future__ import absolute_import, division, unicode_literals -from pip._vendor.six import with_metaclass - -import types - -from . import inputstream -from . import tokenizer - -from . import treebuilders -from .treebuilders._base import Marker - -from . import utils -from . import constants -from .constants import spaceCharacters, asciiUpper2Lower -from .constants import specialElements -from .constants import headingElements -from .constants import cdataElements, rcdataElements -from .constants import tokenTypes, ReparseException, namespaces -from .constants import htmlIntegrationPointElements, mathmlTextIntegrationPointElements - - -def parse(doc, treebuilder="etree", encoding=None, - namespaceHTMLElements=True): - """Parse a string or file-like object into a tree""" - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parse(doc, encoding=encoding) - - -def parseFragment(doc, container="div", treebuilder="etree", encoding=None, - namespaceHTMLElements=True): - tb = treebuilders.getTreeBuilder(treebuilder) - p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) - return p.parseFragment(doc, container=container, encoding=encoding) - - -def method_decorator_metaclass(function): - class Decorated(type): - def __new__(meta, classname, bases, classDict): - for attributeName, attribute in classDict.items(): - if isinstance(attribute, types.FunctionType): - attribute = function(attribute) - - classDict[attributeName] = attribute - return type.__new__(meta, classname, bases, classDict) - return Decorated - - -class HTMLParser(object): - """HTML parser. Generates a tree structure from a stream of (possibly - malformed) HTML""" - - def __init__(self, tree=None, tokenizer=tokenizer.HTMLTokenizer, - strict=False, namespaceHTMLElements=True, debug=False): - """ - strict - raise an exception when a parse error is encountered - - tree - a treebuilder class controlling the type of tree that will be - returned. Built in treebuilders can be accessed through - html5lib.treebuilders.getTreeBuilder(treeType) - - tokenizer - a class that provides a stream of tokens to the treebuilder. - This may be replaced for e.g. a sanitizer which converts some tags to - text - """ - - # Raise an exception on the first error encountered - self.strict = strict - - if tree is None: - tree = treebuilders.getTreeBuilder("etree") - self.tree = tree(namespaceHTMLElements) - self.tokenizer_class = tokenizer - self.errors = [] - - self.phases = dict([(name, cls(self, self.tree)) for name, cls in - getPhases(debug).items()]) - - def _parse(self, stream, innerHTML=False, container="div", - encoding=None, parseMeta=True, useChardet=True, **kwargs): - - self.innerHTMLMode = innerHTML - self.container = container - self.tokenizer = self.tokenizer_class(stream, encoding=encoding, - parseMeta=parseMeta, - useChardet=useChardet, - parser=self, **kwargs) - self.reset() - - while True: - try: - self.mainLoop() - break - except ReparseException: - self.reset() - - def reset(self): - self.tree.reset() - self.firstStartTag = False - self.errors = [] - self.log = [] # only used with debug mode - # "quirks" / "limited quirks" / "no quirks" - self.compatMode = "no quirks" - - if self.innerHTMLMode: - self.innerHTML = self.container.lower() - - if self.innerHTML in cdataElements: - self.tokenizer.state = self.tokenizer.rcdataState - elif self.innerHTML in rcdataElements: - self.tokenizer.state = self.tokenizer.rawtextState - elif self.innerHTML == 'plaintext': - self.tokenizer.state = self.tokenizer.plaintextState - else: - # state already is data state - # self.tokenizer.state = self.tokenizer.dataState - pass - self.phase = self.phases["beforeHtml"] - self.phase.insertHtmlElement() - self.resetInsertionMode() - else: - self.innerHTML = False - self.phase = self.phases["initial"] - - self.lastPhase = None - - self.beforeRCDataPhase = None - - self.framesetOK = True - - def isHTMLIntegrationPoint(self, element): - if (element.name == "annotation-xml" and - element.namespace == namespaces["mathml"]): - return ("encoding" in element.attributes and - element.attributes["encoding"].translate( - asciiUpper2Lower) in - ("text/html", "application/xhtml+xml")) - else: - return (element.namespace, element.name) in htmlIntegrationPointElements - - def isMathMLTextIntegrationPoint(self, element): - return (element.namespace, element.name) in mathmlTextIntegrationPointElements - - def mainLoop(self): - CharactersToken = tokenTypes["Characters"] - SpaceCharactersToken = tokenTypes["SpaceCharacters"] - StartTagToken = tokenTypes["StartTag"] - EndTagToken = tokenTypes["EndTag"] - CommentToken = tokenTypes["Comment"] - DoctypeToken = tokenTypes["Doctype"] - ParseErrorToken = tokenTypes["ParseError"] - - for token in self.normalizedTokens(): - new_token = token - while new_token is not None: - currentNode = self.tree.openElements[-1] if self.tree.openElements else None - currentNodeNamespace = currentNode.namespace if currentNode else None - currentNodeName = currentNode.name if currentNode else None - - type = new_token["type"] - - if type == ParseErrorToken: - self.parseError(new_token["data"], new_token.get("datavars", {})) - new_token = None - else: - if (len(self.tree.openElements) == 0 or - currentNodeNamespace == self.tree.defaultNamespace or - (self.isMathMLTextIntegrationPoint(currentNode) and - ((type == StartTagToken and - token["name"] not in frozenset(["mglyph", "malignmark"])) or - type in (CharactersToken, SpaceCharactersToken))) or - (currentNodeNamespace == namespaces["mathml"] and - currentNodeName == "annotation-xml" and - token["name"] == "svg") or - (self.isHTMLIntegrationPoint(currentNode) and - type in (StartTagToken, CharactersToken, SpaceCharactersToken))): - phase = self.phase - else: - phase = self.phases["inForeignContent"] - - if type == CharactersToken: - new_token = phase.processCharacters(new_token) - elif type == SpaceCharactersToken: - new_token = phase.processSpaceCharacters(new_token) - elif type == StartTagToken: - new_token = phase.processStartTag(new_token) - elif type == EndTagToken: - new_token = phase.processEndTag(new_token) - elif type == CommentToken: - new_token = phase.processComment(new_token) - elif type == DoctypeToken: - new_token = phase.processDoctype(new_token) - - if (type == StartTagToken and token["selfClosing"] - and not token["selfClosingAcknowledged"]): - self.parseError("non-void-element-with-trailing-solidus", - {"name": token["name"]}) - - # When the loop finishes it's EOF - reprocess = True - phases = [] - while reprocess: - phases.append(self.phase) - reprocess = self.phase.processEOF() - if reprocess: - assert self.phase not in phases - - def normalizedTokens(self): - for token in self.tokenizer: - yield self.normalizeToken(token) - - def parse(self, stream, encoding=None, parseMeta=True, useChardet=True): - """Parse a HTML document into a well-formed tree - - stream - a filelike object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - """ - self._parse(stream, innerHTML=False, encoding=encoding, - parseMeta=parseMeta, useChardet=useChardet) - return self.tree.getDocument() - - def parseFragment(self, stream, container="div", encoding=None, - parseMeta=False, useChardet=True): - """Parse a HTML fragment into a well-formed tree fragment - - container - name of the element we're setting the innerHTML property - if set to None, default to 'div' - - stream - a filelike object or string containing the HTML to be parsed - - The optional encoding parameter must be a string that indicates - the encoding. If specified, that encoding will be used, - regardless of any BOM or later declaration (such as in a meta - element) - """ - self._parse(stream, True, container=container, encoding=encoding) - return self.tree.getFragment() - - def parseError(self, errorcode="XXX-undefined-error", datavars={}): - # XXX The idea is to make errorcode mandatory. - self.errors.append((self.tokenizer.stream.position(), errorcode, datavars)) - if self.strict: - raise ParseError - - def normalizeToken(self, token): - """ HTML5 specific normalizations to the token stream """ - - if token["type"] == tokenTypes["StartTag"]: - token["data"] = dict(token["data"][::-1]) - - return token - - def adjustMathMLAttributes(self, token): - replacements = {"definitionurl": "definitionURL"} - for k, v in replacements.items(): - if k in token["data"]: - token["data"][v] = token["data"][k] - del token["data"][k] - - def adjustSVGAttributes(self, token): - replacements = { - "attributename": "attributeName", - "attributetype": "attributeType", - "basefrequency": "baseFrequency", - "baseprofile": "baseProfile", - "calcmode": "calcMode", - "clippathunits": "clipPathUnits", - "contentscripttype": "contentScriptType", - "contentstyletype": "contentStyleType", - "diffuseconstant": "diffuseConstant", - "edgemode": "edgeMode", - "externalresourcesrequired": "externalResourcesRequired", - "filterres": "filterRes", - "filterunits": "filterUnits", - "glyphref": "glyphRef", - "gradienttransform": "gradientTransform", - "gradientunits": "gradientUnits", - "kernelmatrix": "kernelMatrix", - "kernelunitlength": "kernelUnitLength", - "keypoints": "keyPoints", - "keysplines": "keySplines", - "keytimes": "keyTimes", - "lengthadjust": "lengthAdjust", - "limitingconeangle": "limitingConeAngle", - "markerheight": "markerHeight", - "markerunits": "markerUnits", - "markerwidth": "markerWidth", - "maskcontentunits": "maskContentUnits", - "maskunits": "maskUnits", - "numoctaves": "numOctaves", - "pathlength": "pathLength", - "patterncontentunits": "patternContentUnits", - "patterntransform": "patternTransform", - "patternunits": "patternUnits", - "pointsatx": "pointsAtX", - "pointsaty": "pointsAtY", - "pointsatz": "pointsAtZ", - "preservealpha": "preserveAlpha", - "preserveaspectratio": "preserveAspectRatio", - "primitiveunits": "primitiveUnits", - "refx": "refX", - "refy": "refY", - "repeatcount": "repeatCount", - "repeatdur": "repeatDur", - "requiredextensions": "requiredExtensions", - "requiredfeatures": "requiredFeatures", - "specularconstant": "specularConstant", - "specularexponent": "specularExponent", - "spreadmethod": "spreadMethod", - "startoffset": "startOffset", - "stddeviation": "stdDeviation", - "stitchtiles": "stitchTiles", - "surfacescale": "surfaceScale", - "systemlanguage": "systemLanguage", - "tablevalues": "tableValues", - "targetx": "targetX", - "targety": "targetY", - "textlength": "textLength", - "viewbox": "viewBox", - "viewtarget": "viewTarget", - "xchannelselector": "xChannelSelector", - "ychannelselector": "yChannelSelector", - "zoomandpan": "zoomAndPan" - } - for originalName in list(token["data"].keys()): - if originalName in replacements: - svgName = replacements[originalName] - token["data"][svgName] = token["data"][originalName] - del token["data"][originalName] - - def adjustForeignAttributes(self, token): - replacements = { - "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]), - "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]), - "xlink:href": ("xlink", "href", namespaces["xlink"]), - "xlink:role": ("xlink", "role", namespaces["xlink"]), - "xlink:show": ("xlink", "show", namespaces["xlink"]), - "xlink:title": ("xlink", "title", namespaces["xlink"]), - "xlink:type": ("xlink", "type", namespaces["xlink"]), - "xml:base": ("xml", "base", namespaces["xml"]), - "xml:lang": ("xml", "lang", namespaces["xml"]), - "xml:space": ("xml", "space", namespaces["xml"]), - "xmlns": (None, "xmlns", namespaces["xmlns"]), - "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"]) - } - - for originalName in token["data"].keys(): - if originalName in replacements: - foreignName = replacements[originalName] - token["data"][foreignName] = token["data"][originalName] - del token["data"][originalName] - - def reparseTokenNormal(self, token): - self.parser.phase() - - def resetInsertionMode(self): - # The name of this method is mostly historical. (It's also used in the - # specification.) - last = False - newModes = { - "select": "inSelect", - "td": "inCell", - "th": "inCell", - "tr": "inRow", - "tbody": "inTableBody", - "thead": "inTableBody", - "tfoot": "inTableBody", - "caption": "inCaption", - "colgroup": "inColumnGroup", - "table": "inTable", - "head": "inBody", - "body": "inBody", - "frameset": "inFrameset", - "html": "beforeHead" - } - for node in self.tree.openElements[::-1]: - nodeName = node.name - new_phase = None - if node == self.tree.openElements[0]: - assert self.innerHTML - last = True - nodeName = self.innerHTML - # Check for conditions that should only happen in the innerHTML - # case - if nodeName in ("select", "colgroup", "head", "html"): - assert self.innerHTML - - if not last and node.namespace != self.tree.defaultNamespace: - continue - - if nodeName in newModes: - new_phase = self.phases[newModes[nodeName]] - break - elif last: - new_phase = self.phases["inBody"] - break - - self.phase = new_phase - - def parseRCDataRawtext(self, token, contentType): - """Generic RCDATA/RAWTEXT Parsing algorithm - contentType - RCDATA or RAWTEXT - """ - assert contentType in ("RAWTEXT", "RCDATA") - - self.tree.insertElement(token) - - if contentType == "RAWTEXT": - self.tokenizer.state = self.tokenizer.rawtextState - else: - self.tokenizer.state = self.tokenizer.rcdataState - - self.originalPhase = self.phase - - self.phase = self.phases["text"] - - -def getPhases(debug): - def log(function): - """Logger that records which phase processes each token""" - type_names = dict((value, key) for key, value in - constants.tokenTypes.items()) - - def wrapped(self, *args, **kwargs): - if function.__name__.startswith("process") and len(args) > 0: - token = args[0] - try: - info = {"type": type_names[token['type']]} - except: - raise - if token['type'] in constants.tagTokenTypes: - info["name"] = token['name'] - - self.parser.log.append((self.parser.tokenizer.state.__name__, - self.parser.phase.__class__.__name__, - self.__class__.__name__, - function.__name__, - info)) - return function(self, *args, **kwargs) - else: - return function(self, *args, **kwargs) - return wrapped - - def getMetaclass(use_metaclass, metaclass_func): - if use_metaclass: - return method_decorator_metaclass(metaclass_func) - else: - return type - - class Phase(with_metaclass(getMetaclass(debug, log))): - """Base class for helper object that implements each phase of processing - """ - - def __init__(self, parser, tree): - self.parser = parser - self.tree = tree - - def processEOF(self): - raise NotImplementedError - - def processComment(self, token): - # For most phases the following is correct. Where it's not it will be - # overridden. - self.tree.insertComment(token, self.tree.openElements[-1]) - - def processDoctype(self, token): - self.parser.parseError("unexpected-doctype") - - def processCharacters(self, token): - self.tree.insertText(token["data"]) - - def processSpaceCharacters(self, token): - self.tree.insertText(token["data"]) - - def processStartTag(self, token): - return self.startTagHandler[token["name"]](token) - - def startTagHtml(self, token): - if not self.parser.firstStartTag and token["name"] == "html": - self.parser.parseError("non-html-root") - # XXX Need a check here to see if the first start tag token emitted is - # this token... If it's not, invoke self.parser.parseError(). - for attr, value in token["data"].items(): - if attr not in self.tree.openElements[0].attributes: - self.tree.openElements[0].attributes[attr] = value - self.parser.firstStartTag = False - - def processEndTag(self, token): - return self.endTagHandler[token["name"]](token) - - class InitialPhase(Phase): - def processSpaceCharacters(self, token): - pass - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processDoctype(self, token): - name = token["name"] - publicId = token["publicId"] - systemId = token["systemId"] - correct = token["correct"] - - if (name != "html" or publicId is not None or - systemId is not None and systemId != "about:legacy-compat"): - self.parser.parseError("unknown-doctype") - - if publicId is None: - publicId = "" - - self.tree.insertDoctype(token) - - if publicId != "": - publicId = publicId.translate(asciiUpper2Lower) - - if (not correct or token["name"] != "html" - or publicId.startswith( - ("+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//")) - or publicId in - ("-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html") - or publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is None - or systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"): - self.parser.compatMode = "quirks" - elif (publicId.startswith( - ("-//w3c//dtd xhtml 1.0 frameset//", - "-//w3c//dtd xhtml 1.0 transitional//")) - or publicId.startswith( - ("-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//")) and - systemId is not None): - self.parser.compatMode = "limited quirks" - - self.parser.phase = self.parser.phases["beforeHtml"] - - def anythingElse(self): - self.parser.compatMode = "quirks" - self.parser.phase = self.parser.phases["beforeHtml"] - - def processCharacters(self, token): - self.parser.parseError("expected-doctype-but-got-chars") - self.anythingElse() - return token - - def processStartTag(self, token): - self.parser.parseError("expected-doctype-but-got-start-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEndTag(self, token): - self.parser.parseError("expected-doctype-but-got-end-tag", - {"name": token["name"]}) - self.anythingElse() - return token - - def processEOF(self): - self.parser.parseError("expected-doctype-but-got-eof") - self.anythingElse() - return True - - class BeforeHtmlPhase(Phase): - # helper methods - def insertHtmlElement(self): - self.tree.insertRoot(impliedTagToken("html", "StartTag")) - self.parser.phase = self.parser.phases["beforeHead"] - - # other - def processEOF(self): - self.insertHtmlElement() - return True - - def processComment(self, token): - self.tree.insertComment(token, self.tree.document) - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.insertHtmlElement() - return token - - def processStartTag(self, token): - if token["name"] == "html": - self.parser.firstStartTag = True - self.insertHtmlElement() - return token - - def processEndTag(self, token): - if token["name"] not in ("head", "body", "html", "br"): - self.parser.parseError("unexpected-end-tag-before-html", - {"name": token["name"]}) - else: - self.insertHtmlElement() - return token - - class BeforeHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self.endTagHandler = utils.MethodDispatcher([ - (("head", "body", "html", "br"), self.endTagImplyHead) - ]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.startTagHead(impliedTagToken("head", "StartTag")) - return True - - def processSpaceCharacters(self, token): - pass - - def processCharacters(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.tree.insertElement(token) - self.tree.headPointer = self.tree.openElements[-1] - self.parser.phase = self.parser.phases["inHead"] - - def startTagOther(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagImplyHead(self, token): - self.startTagHead(impliedTagToken("head", "StartTag")) - return token - - def endTagOther(self, token): - self.parser.parseError("end-tag-after-implied-root", - {"name": token["name"]}) - - class InHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("title", self.startTagTitle), - (("noscript", "noframes", "style"), self.startTagNoScriptNoFramesStyle), - ("script", self.startTagScript), - (("base", "basefont", "bgsound", "command", "link"), - self.startTagBaseLinkCommand), - ("meta", self.startTagMeta), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - - self. endTagHandler = utils.MethodDispatcher([ - ("head", self.endTagHead), - (("br", "html", "body"), self.endTagHtmlBodyBr) - ]) - self.endTagHandler.default = self.endTagOther - - # the real thing - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagHead(self, token): - self.parser.parseError("two-heads-are-not-better-than-one") - - def startTagBaseLinkCommand(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - def startTagMeta(self, token): - self.tree.insertElement(token) - self.tree.openElements.pop() - token["selfClosingAcknowledged"] = True - - attributes = token["data"] - if self.parser.tokenizer.stream.charEncoding[1] == "tentative": - if "charset" in attributes: - self.parser.tokenizer.stream.changeEncoding(attributes["charset"]) - elif ("content" in attributes and - "http-equiv" in attributes and - attributes["http-equiv"].lower() == "content-type"): - # Encoding it as UTF-8 here is a hack, as really we should pass - # the abstract Unicode string, and just use the - # ContentAttrParser on that, but using UTF-8 allows all chars - # to be encoded and as a ASCII-superset works. - data = inputstream.EncodingBytes(attributes["content"].encode("utf-8")) - parser = inputstream.ContentAttrParser(data) - codec = parser.parse() - self.parser.tokenizer.stream.changeEncoding(codec) - - def startTagTitle(self, token): - self.parser.parseRCDataRawtext(token, "RCDATA") - - def startTagNoScriptNoFramesStyle(self, token): - # Need to decide whether to implement the scripting-disabled case - self.parser.parseRCDataRawtext(token, "RAWTEXT") - - def startTagScript(self, token): - self.tree.insertElement(token) - self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState - self.parser.originalPhase = self.parser.phase - self.parser.phase = self.parser.phases["text"] - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHead(self, token): - node = self.parser.tree.openElements.pop() - assert node.name == "head", "Expected head got %s" % node.name - self.parser.phase = self.parser.phases["afterHead"] - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.endTagHead(impliedTagToken("head")) - - # XXX If we implement a parser for which scripting is disabled we need to - # implement this phase. - # - # class InHeadNoScriptPhase(Phase): - class AfterHeadPhase(Phase): - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - self.startTagHandler = utils.MethodDispatcher([ - ("html", self.startTagHtml), - ("body", self.startTagBody), - ("frameset", self.startTagFrameset), - (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", - "style", "title"), - self.startTagFromHead), - ("head", self.startTagHead) - ]) - self.startTagHandler.default = self.startTagOther - self.endTagHandler = utils.MethodDispatcher([(("body", "html", "br"), - self.endTagHtmlBodyBr)]) - self.endTagHandler.default = self.endTagOther - - def processEOF(self): - self.anythingElse() - return True - - def processCharacters(self, token): - self.anythingElse() - return token - - def startTagHtml(self, token): - return self.parser.phases["inBody"].processStartTag(token) - - def startTagBody(self, token): - self.parser.framesetOK = False - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inBody"] - - def startTagFrameset(self, token): - self.tree.insertElement(token) - self.parser.phase = self.parser.phases["inFrameset"] - - def startTagFromHead(self, token): - self.parser.parseError("unexpected-start-tag-out-of-my-head", - {"name": token["name"]}) - self.tree.openElements.append(self.tree.headPointer) - self.parser.phases["inHead"].processStartTag(token) - for node in self.tree.openElements[::-1]: - if node.name == "head": - self.tree.openElements.remove(node) - break - - def startTagHead(self, token): - self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) - - def startTagOther(self, token): - self.anythingElse() - return token - - def endTagHtmlBodyBr(self, token): - self.anythingElse() - return token - - def endTagOther(self, token): - self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) - - def anythingElse(self): - self.tree.insertElement(impliedTagToken("body", "StartTag")) - self.parser.phase = self.parser.phases["inBody"] - self.parser.framesetOK = True - - class InBodyPhase(Phase): - # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody - # the really-really-really-very crazy mode - def __init__(self, parser, tree): - Phase.__init__(self, parser, tree) - - # Keep a ref to this for special handling of whitespace in
-            self.processSpaceCharactersNonPre = self.processSpaceCharacters
-
-            self.startTagHandler = utils.MethodDispatcher([
-                ("html", self.startTagHtml),
-                (("base", "basefont", "bgsound", "command", "link", "meta",
-                  "noframes", "script", "style", "title"),
-                 self.startTagProcessInHead),
-                ("body", self.startTagBody),
-                ("frameset", self.startTagFrameset),
-                (("address", "article", "aside", "blockquote", "center", "details",
-                  "details", "dir", "div", "dl", "fieldset", "figcaption", "figure",
-                  "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p",
-                  "section", "summary", "ul"),
-                 self.startTagCloseP),
-                (headingElements, self.startTagHeading),
-                (("pre", "listing"), self.startTagPreListing),
-                ("form", self.startTagForm),
-                (("li", "dd", "dt"), self.startTagListItem),
-                ("plaintext", self.startTagPlaintext),
-                ("a", self.startTagA),
-                (("b", "big", "code", "em", "font", "i", "s", "small", "strike",
-                  "strong", "tt", "u"), self.startTagFormatting),
-                ("nobr", self.startTagNobr),
-                ("button", self.startTagButton),
-                (("applet", "marquee", "object"), self.startTagAppletMarqueeObject),
-                ("xmp", self.startTagXmp),
-                ("table", self.startTagTable),
-                (("area", "br", "embed", "img", "keygen", "wbr"),
-                 self.startTagVoidFormatting),
-                (("param", "source", "track"), self.startTagParamSource),
-                ("input", self.startTagInput),
-                ("hr", self.startTagHr),
-                ("image", self.startTagImage),
-                ("isindex", self.startTagIsIndex),
-                ("textarea", self.startTagTextarea),
-                ("iframe", self.startTagIFrame),
-                (("noembed", "noframes", "noscript"), self.startTagRawtext),
-                ("select", self.startTagSelect),
-                (("rp", "rt"), self.startTagRpRt),
-                (("option", "optgroup"), self.startTagOpt),
-                (("math"), self.startTagMath),
-                (("svg"), self.startTagSvg),
-                (("caption", "col", "colgroup", "frame", "head",
-                  "tbody", "td", "tfoot", "th", "thead",
-                  "tr"), self.startTagMisplaced)
-            ])
-            self.startTagHandler.default = self.startTagOther
-
-            self.endTagHandler = utils.MethodDispatcher([
-                ("body", self.endTagBody),
-                ("html", self.endTagHtml),
-                (("address", "article", "aside", "blockquote", "button", "center",
-                  "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure",
-                  "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre",
-                  "section", "summary", "ul"), self.endTagBlock),
-                ("form", self.endTagForm),
-                ("p", self.endTagP),
-                (("dd", "dt", "li"), self.endTagListItem),
-                (headingElements, self.endTagHeading),
-                (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small",
-                  "strike", "strong", "tt", "u"), self.endTagFormatting),
-                (("applet", "marquee", "object"), self.endTagAppletMarqueeObject),
-                ("br", self.endTagBr),
-            ])
-            self.endTagHandler.default = self.endTagOther
-
-        def isMatchingFormattingElement(self, node1, node2):
-            if node1.name != node2.name or node1.namespace != node2.namespace:
-                return False
-            elif len(node1.attributes) != len(node2.attributes):
-                return False
-            else:
-                attributes1 = sorted(node1.attributes.items())
-                attributes2 = sorted(node2.attributes.items())
-                for attr1, attr2 in zip(attributes1, attributes2):
-                    if attr1 != attr2:
-                        return False
-            return True
-
-        # helper
-        def addFormattingElement(self, token):
-            self.tree.insertElement(token)
-            element = self.tree.openElements[-1]
-
-            matchingElements = []
-            for node in self.tree.activeFormattingElements[::-1]:
-                if node is Marker:
-                    break
-                elif self.isMatchingFormattingElement(node, element):
-                    matchingElements.append(node)
-
-            assert len(matchingElements) <= 3
-            if len(matchingElements) == 3:
-                self.tree.activeFormattingElements.remove(matchingElements[-1])
-            self.tree.activeFormattingElements.append(element)
-
-        # the real deal
-        def processEOF(self):
-            allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td",
-                                          "tfoot", "th", "thead", "tr", "body",
-                                          "html"))
-            for node in self.tree.openElements[::-1]:
-                if node.name not in allowed_elements:
-                    self.parser.parseError("expected-closing-tag-but-got-eof")
-                    break
-            # Stop parsing
-
-        def processSpaceCharactersDropNewline(self, token):
-            # Sometimes (start of 
, , and